From 885c8a793575c46381ad5a93ee8d4d1cffd123cb Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 24 Jun 2016 00:56:33 -0400 Subject: [PATCH 001/203] gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index e213b27f3921..2a7bcb1daa79 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,11 @@ GRTAGS GSYMS GTAGS +*.rej +*.diff +*.patch +*.list +out/* *.orig *~ \#*# From eae04e8cd192caf0eb5c857b25e3ed803aab0143 Mon Sep 17 00:00:00 2001 From: flar2 Date: Thu, 27 Jun 2013 22:05:38 -0400 Subject: [PATCH 002/203] Fix version name Signed-off-by: flar2 --- scripts/setlocalversion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 43f29132a28c..cdf7776d2888 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -182,7 +182,7 @@ else # LOCALVERSION= is not specified if test "${LOCALVERSION+set}" != "set"; then scm=$(scm_version --short) - res="$res${scm:++}" + res="$res" fi fi From 5c42caaa1652ad7284dd5acf1c0d35b8e90d50ae Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 1 Mar 2014 11:18:50 -0500 Subject: [PATCH 003/203] disable crc check Signed-off-by: flar2 --- drivers/mmc/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 42a24413a2c9..55c9b347b531 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -67,7 +67,7 @@ static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; * performance cost, and for other reasons may not always be desired. * So we allow it it to be disabled. */ -bool use_spi_crc = 1; +bool use_spi_crc = 0; module_param(use_spi_crc, bool, 0); /* From cee564a6bde7b8290a4d21b476da291600718cba Mon Sep 17 00:00:00 2001 From: Jeff Liu Date: Sat, 5 Jan 2013 04:53:18 +0100 Subject: [PATCH 004/203] binfmt_elf.c: use get_random_int() to fix entropy depleting Changes: -------- v4->v3: - s/random_stack_user()/get_atrandom_bytes()/ - Move this function to ahead of its use to avoid the predeclaration. v3->v2: - Tweak code comments of random_stack_user(). - Remove redundant bits mask and shift upon the random variable. v2->v1: - Fix random copy to check up buffer length that are not 4-byte multiples. v3 can be found at: http://www.spinics.net/lists/linux-fsdevel/msg59597.html v2 can be found at: http://www.spinics.net/lists/linux-fsdevel/msg59418.html v1 can be found at: http://www.spinics.net/lists/linux-fsdevel/msg59128.html Thanks, -Jeff Entropy is quickly depleted under normal operations like ls(1), cat(1), etc... between 2.6.30 to current mainline, for instance: $ cat /proc/sys/kernel/random/entropy_avail 3428 $ cat /proc/sys/kernel/random/entropy_avail 2911 $cat /proc/sys/kernel/random/entropy_avail 2620 We observed this problem has been occurring since 2.6.30 with fs/binfmt_elf.c: create_elf_tables()->get_random_bytes(), introduced by f06295b44c296c8f ("ELF: implement AT_RANDOM for glibc PRNG seeding"). /* * Generate 16 random bytes for userspace PRNG seeding. */ get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes)); The patch introduces a wrapper around get_random_int() which has lower overhead than calling get_random_bytes() directly. With this patch applied: $ cat /proc/sys/kernel/random/entropy_avail 2731 $ cat /proc/sys/kernel/random/entropy_avail 2802 $ cat /proc/sys/kernel/random/entropy_avail 2878 Analyzed by John Sobecki. Signed-off-by: Jie Liu Cc: Andrew Morton Cc: Al Viro Cc: Andreas Dilger Cc: Alan Cox Cc: Arnd Bergmann Cc: John Sobecki Cc: James Morris Cc: Jakub Jelinek Cc: Ted Ts'o Cc: Greg Kroah-Hartman Cc: Kees Cook Cc: Ulrich Drepper Signed-off-by: flar2 --- fs/binfmt_elf.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 1cf96193f5bb..5527172c109f 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -146,6 +146,25 @@ static int padzero(unsigned long elf_bss) #define ELF_BASE_PLATFORM NULL #endif +/* + * Use get_random_int() to implement AT_RANDOM while avoiding depletion + * of the entropy pool. + */ +static void get_atrandom_bytes(unsigned char *buf, size_t nbytes) +{ + unsigned char *p = buf; + + while (nbytes) { + unsigned int random_variable; + size_t chunk = min(nbytes, sizeof(random_variable)); + + random_variable = get_random_int(); + memcpy(p, &random_variable, chunk); + p += chunk; + nbytes -= chunk; + } +} + static int create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, unsigned long load_addr, unsigned long interp_load_addr) @@ -207,7 +226,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, /* * Generate 16 random bytes for userspace PRNG seeding. */ - get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes)); + get_atrandom_bytes(k_rand_bytes, sizeof(k_rand_bytes)); u_rand_bytes = (elf_addr_t __user *) STACK_ALLOC(p, sizeof(k_rand_bytes)); if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) From 86693ab3ed2743bb31086be582da8971b594190b Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Tue, 19 Jan 2016 16:36:40 -0800 Subject: [PATCH 005/203] mmc: move to a SCHED_FIFO thread Running mmcqd as a prio 120 thread forces it to compete with standard user processes for IO performance, especially when the system is under severe CPU load. Move it to a SCHED_FIFO thread to reduce the impact of load on IO performance. bug 25392275 Change-Id: I1edfe73baa25e181367c30c1f40fee886e92b60d Signed-off-by: flar2 --- drivers/mmc/card/queue.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 4ec0b5adeb58..597bb54f8838 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -21,6 +21,7 @@ #include #include +#include #include "queue.h" #define MMC_QUEUE_BOUNCESZ 65536 @@ -143,6 +144,11 @@ static int mmc_queue_thread(void *d) struct request_queue *q = mq->queue; struct mmc_card *card = mq->card; + struct sched_param scheduler_params = {0}; + scheduler_params.sched_priority = 1; + + sched_setscheduler(current, SCHED_FIFO, &scheduler_params); + current->flags |= PF_MEMALLOC; if (card->host->wakeup_on_idle) set_wake_up_idle(true); From f86f1b8cd5287bd835db235e11d1cf0bbcf509b3 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Tue, 19 Jan 2016 16:35:17 -0800 Subject: [PATCH 006/203] dm-verity: run in a WQ_HIGHPRI workqueue Running dm-verity in a standard workqueue results in IO competing for CPU time with standard user apps, which can lead to pipeline bubbles and seriously degraded performance. Move to a WQ_HIGHPRI workqueue to protect against that. bug 25392275 Change-Id: Ic65d7bd6f04e4d77780119e926a50e71323575f0 Signed-off-by: flar2 --- drivers/md/dm-verity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 1288eaf06ab8..71a98d48f3e4 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -928,7 +928,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) } /* WQ_UNBOUND greatly improves performance when running on ramdisk */ - v->verify_wq = alloc_workqueue("kverityd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus()); + v->verify_wq = alloc_workqueue("kverityd", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus()); if (!v->verify_wq) { ti->error = "Cannot allocate workqueue"; r = -ENOMEM; From fcacd0669ef477828b388d5d3e0da8ce82769f18 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 24 Jun 2016 01:27:47 -0400 Subject: [PATCH 007/203] elementalx defconfig --- arch/arm64/configs/elementalx_defconfig | 4371 +++++++++++++++++++++++ 1 file changed, 4371 insertions(+) create mode 100644 arch/arm64/configs/elementalx_defconfig diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig new file mode 100644 index 000000000000..9e1103eeeafd --- /dev/null +++ b/arch/arm64/configs/elementalx_defconfig @@ -0,0 +1,4371 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 3.18.20 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_ARM64_DMA_USE_IOMMU=y +CONFIG_ARM64_DMA_IOMMU_ALIGNMENT=8 +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="-perf" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_FHANDLE is not set +CONFIG_USELIB=y +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +# CONFIG_AUDITSYSCALL is not set + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +# CONFIG_TICK_CPU_ACCOUNTING is not set +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_IRQ_TIME_ACCOUNTING=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=64 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +# CONFIG_RCU_NOCB_CPU is not set +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +# CONFIG_IKCONFIG_PROC is not set +CONFIG_LOG_BUF_SHIFT=18 +# CONFIG_CONSOLE_FLUSH_ON_HOTPLUG is not set +CONFIG_LOG_CPU_MAX_BUF_SHIFT=15 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +# CONFIG_MEMCG is not set +# CONFIG_CGROUP_PERF is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +CONFIG_RT_GROUP_SCHED=y +# CONFIG_BLK_CGROUP is not set +CONFIG_SCHED_HMP=y +# CONFIG_SCHED_QHMP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_PCI_QUIRKS=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_PROFILING=y +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR_NONE is not set +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_TEST=m +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# Platform selection +# +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +CONFIG_ARCH_MSM=y +# CONFIG_ARCH_MSM8916 is not set +# CONFIG_ARCH_MSMGOLD is not set +# CONFIG_ARCH_MSMTITANIUM is not set +# CONFIG_ARCH_MSM8937 is not set +CONFIG_ARCH_MSM8996=y +# CONFIG_ARCH_MSMCOBALT is not set + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCI_MSM=y + +# +# PCI host controller drivers +# +# CONFIG_PCIEPORTBUS is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_DCACHE_DISABLE is not set +# CONFIG_ARM64_ICACHE_DISABLE is not set +CONFIG_MSM_APP_API=y +CONFIG_ENABLE_FP_SIMD_SETTINGS=y +CONFIG_MSM_APP_SETTINGS=y +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM64_VA_BITS=39 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SMP=y +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_NR_GPIO=1024 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HW_PERF_EVENTS=y +# CONFIG_PERF_EVENTS_USERMODE is not set +# CONFIG_PERF_EVENTS_RESET_PMU_DEBUGFS is not set +CONFIG_ARM64_REG_REBALANCE_ON_CTX_SW=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_DEBUGFS=y +CONFIG_CMA_AREAS=7 +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_BALANCE_ANON_FILE_RECLAIM=y +CONFIG_KSWAPD_CPU_AFFINITY_MASK="" +CONFIG_FORCE_ALLOC_FROM_DMA_ZONE=y +# CONFIG_PROCESS_RECLAIM is not set +CONFIG_SECCOMP=y +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +# CONFIG_CP15_BARRIER_EMULATION is not set +# CONFIG_SETEND_EMULATION is not set + +# +# Boot options +# +CONFIG_CMDLINE="" +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="" + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_WAKELOCK=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +# CONFIG_SUSPEND_TIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM64_CPU_SUSPEND=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM64 CPU Idle Drivers +# +# CONFIG_ARM64_CPUIDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_SCHED_FREQ_INPUT=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_CPUFREQ_DT is not set +CONFIG_CPU_BOOST=y + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_CPU_FREQ_MSM=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_NET_UDP_TUNNEL=y +# CONFIG_NET_FOU is not set +# CONFIG_GENEVE is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +# CONFIG_NET_PTP_CLASSIFY is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_COMMON=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_BROADCAST=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +# CONFIG_NF_CONNTRACK_SNMP is not set +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=y +CONFIG_NF_NAT_PROTO_UDPLITE=y +CONFIG_NF_NAT_PROTO_SCTP=y +CONFIG_NF_NAT_AMANDA=y +CONFIG_NF_NAT_FTP=y +CONFIG_NF_NAT_IRC=y +# CONFIG_NF_NAT_SIP is not set +CONFIG_NF_NAT_TFTP=y +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_CT=y +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_NAT=y +CONFIG_NETFILTER_XT_TARGET_NETMAP=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ECN=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_POLICY=y +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=y +CONFIG_NF_REJECT_IPV4=y +CONFIG_NF_NAT_IPV4=y +CONFIG_NF_NAT_MASQUERADE_IPV4=y +CONFIG_NF_NAT_PROTO_GRE=y +CONFIG_NF_NAT_PPTP=y +CONFIG_NF_NAT_H323=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +# CONFIG_IP_NF_TARGET_NATTYPE_MODULE is not set +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_REJECT_IPV6=y +CONFIG_NF_LOG_IPV6=y +# CONFIG_NF_NAT_IPV6 is not set +CONFIG_IP6_NF_IPTABLES=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_IP6_NF_NAT is not set +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +# CONFIG_BRIDGE_EBT_T_FILTER is not set +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +# CONFIG_BRIDGE_EBT_IP is not set +# CONFIG_BRIDGE_EBT_IP6 is not set +# CONFIG_BRIDGE_EBT_LIMIT is not set +# CONFIG_BRIDGE_EBT_MARK is not set +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_STP is not set +# CONFIG_BRIDGE_EBT_VLAN is not set +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +# CONFIG_BRIDGE_EBT_MARK_T is not set +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +# CONFIG_BRIDGE_EBT_LOG is not set +# CONFIG_BRIDGE_EBT_NFLOG is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_HAVE_NET_DSA=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=y +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +CONFIG_NET_SCH_INGRESS=y +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=y +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +CONFIG_NET_ACT_GACT=y +# CONFIG_GACT_PROB is not set +CONFIG_NET_ACT_MIRRED=y +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +CONFIG_NET_ACT_SKBEDIT=y +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +# CONFIG_RMNET_DATA_DEBUG_PKT is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y +CONFIG_SOCKEV_NLMCAST=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_MSM_BT_POWER=y +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_NFC_NQ is not set +CONFIG_IPC_ROUTER=y +CONFIG_IPC_ROUTER_SECURITY=y +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_HAVE_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_SWR=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 + +# +# Bus devices +# +# CONFIG_ARM_CCN is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_SPMI=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_SLIMBUS=y +CONFIG_OF_BATTERYDATA=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_ZRAM is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +CONFIG_UID_STAT=y +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +CONFIG_QSEECOM=y +CONFIG_HDCP_QSEECOM=y +CONFIG_UID_CPUTIME=y +# CONFIG_USB_EXT_TYPE_C_PERICOM is not set +# CONFIG_USB_EXT_TYPE_C_TI is not set +CONFIG_TUSB320_TYPE_C=y +CONFIG_FUSB301_TYPE_C=y +CONFIG_PTN5150_TYPE_C=y +CONFIG_TI_DRV2667=y +CONFIG_GPIO_SWITCH=y +CONFIG_BOOTLOADER_LOG=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set +CONFIG_MSM_QDSP6V2_CODECS=y +CONFIG_MSM_ULTRASOUND=y + +# +# Intel MIC Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +CONFIG_SCSI_UFSHCD=y +# CONFIG_SCSI_UFSHCD_PCI is not set +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +CONFIG_SCSI_UFS_TEST=m +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y +CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +CONFIG_DM_VERITY=y +# CONFIG_DM_SWITCH is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_NET_XGENE is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +# CONFIG_ECM_IPA is not set +CONFIG_RNDIS_IPA=y +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +# CONFIG_QCOM_EMAC is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_SLIP is not set +CONFIG_SLHC=y +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_AX88179_178A=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=y +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USBNET_IPA_BRIDGE is not set +CONFIG_WLAN=y +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_WIFI_CONTROL_FUNC is not set +# CONFIG_WCNSS_CORE is not set +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CNSS_CRYPTO=y +CONFIG_ATH_CARDS=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K_PCI is not set +# CONFIG_ATH6KL is not set +CONFIG_WIL6210=m +CONFIG_WIL6210_ISR_COR=y +CONFIG_WIL6210_PLATFORM_MSM=y +# CONFIG_BRCMFMAC is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_WL_TI is not set +# CONFIG_MWIFIEX is not set +CONFIG_CNSS=y +CONFIG_CNSS_PCI=y +# CONFIG_CNSS_SDIO is not set +# CONFIG_CNSS_MAC_BUG is not set +# CONFIG_CLD_DEBUG is not set +# CONFIG_CLD_HL_SDIO_CORE is not set +CONFIG_CLD_LL_CORE=y +# CONFIG_CNSS_SECURE_FW is not set +CONFIG_BUS_AUTO_SUSPEND=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_KEYRESET=y +CONFIG_INPUT_KEYCOMBO=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP1106 is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=y +# CONFIG_JOYSTICK_XPAD_FF is not set +# CONFIG_JOYSTICK_XPAD_LEDS is not set +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_GTCO is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE is not set +CONFIG_OF_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH_TS is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_MSTAR21XX is not set +# CONFIG_TOUCHSCREEN_IT7260_I2C is not set +# CONFIG_TOUCHSCREEN_GEN_VKEYS is not set +# CONFIG_TOUCHSCREEN_FT5X06 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_TOUCHSCREEN_GT9XX is not set +# CONFIG_TOUCHSCREEN_MAXIM_STI is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_S3508_I2C_RMI is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_S1302_I2C_RMI=y +CONFIG_TOUCHSCREEN_SYNAPTICS_S3320_I2C_RMI=y +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +CONFIG_INPUT_HBTP_INPUT=y +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +CONFIG_INPUT_KEYCHORD=y +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +CONFIG_TRI_STATE_KEY=y +CONFIG_FINGERPRINT_FPC1022=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_MSM_HS=y +CONFIG_SERIAL_MSM_HSL=y +CONFIG_SERIAL_MSM_HSL_CONSOLE=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_MSM_SMD=y +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set + +# +# Diag Support +# +CONFIG_DIAG_CHAR=y + +# +# DIAG traffic over USB +# +CONFIG_DIAG_OVER_USB=y + +# +# HSIC/SMUX support for DIAG +# +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_MSM_LEGACY=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_MSM_SMD_PKT=y +# CONFIG_XILLYBUS is not set +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_MSM_QUP is not set +CONFIG_I2C_MSM_V2=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SLIMBUS=y +# CONFIG_SLIMBUS_MSM_CTRL is not set +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SOUNDWIRE=y +CONFIG_SOUNDWIRE_WCD_CTRL=y +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +CONFIG_SPI_QUP=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +# CONFIG_PTP_1588_CLOCK is not set + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_MDM9607 is not set +# CONFIG_PINCTRL_MDM9640 is not set +# CONFIG_PINCTRL_MDMCALIFORNIUM is not set +# CONFIG_PINCTRL_APQ8084 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8X74 is not set +CONFIG_PINCTRL_MSM8996=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_QPNP_PIN=y +# CONFIG_GPIO_QPNP_PIN_DEBUG is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_SMB349_USB_CHARGER is not set +# CONFIG_SMB349_DUAL_CHARGER is not set +CONFIG_SMB1351_USB_CHARGER=y +# CONFIG_SMB350_CHARGER is not set +# CONFIG_SMB135X_CHARGER is not set +# CONFIG_SMB1360_CHARGER_FG is not set +# CONFIG_SMB358_CHARGER is not set +# CONFIG_SMB23X_CHARGER is not set +# CONFIG_BATTERY_BQ28400 is not set +# CONFIG_QPNP_CHARGER is not set +CONFIG_QPNP_SMBCHARGER=y +CONFIG_QPNP_FG=y +CONFIG_FG_BQ27541=y +CONFIG_ONEPLUS_FASTCHG=y +CONFIG_BATTERY_BCL=y +# CONFIG_QPNP_VM_BMS is not set +# CONFIG_QPNP_BMS is not set +# CONFIG_QPNP_LINEAR_CHARGER is not set +# CONFIG_QPNP_TYPEC is not set +CONFIG_MSM_BCL_CTL=y +CONFIG_MSM_BCL_PERIPHERAL_CTL=y +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_MSM=y +CONFIG_MSM_DLOAD_MODE=y +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_AVS is not set +CONFIG_MSM_PM=y +CONFIG_APSS_CORE_EA=y +CONFIG_MSM_APM=y +CONFIG_MSM_IDLE_STATS=y +CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 +CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 +CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_PCF8591 is not set +CONFIG_SENSORS_EPM_ADC=y +CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y +CONFIG_SENSORS_QPNP_ADC_CURRENT=y +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_CPU_THERMAL is not set +# CONFIG_THERMAL_EMULATION is not set +CONFIG_THERMAL_TSENS8974=y +CONFIG_LIMITS_MONITOR=y +CONFIG_LIMITS_LITE_HW=y +CONFIG_THERMAL_MONITOR=y +CONFIG_THERMAL_QPNP=y +CONFIG_THERMAL_QPNP_ADC_TM=y + +# +# Texas Instruments thermal drivers +# +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_WCD9320_CODEC is not set +CONFIG_WCD9330_CODEC=y +CONFIG_WCD9335_CODEC=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +CONFIG_REGULATOR_PROXY_CONSUMER=y +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_STUB=y +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +CONFIG_REGULATOR_FAN53555=y +# CONFIG_REGULATOR_MSM_GFX_LDO is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL9305 is not set +CONFIG_REGULATOR_MEM_ACC=y +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_QPNP=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_SPM=y +# CONFIG_REGULATOR_CPR is not set +# CONFIG_REGULATOR_CPR2_GFX is not set +CONFIG_REGULATOR_CPR3=y +CONFIG_REGULATOR_CPR3_HMSS=y +CONFIG_REGULATOR_CPR3_MMSS=y +# CONFIG_REGULATOR_CPR4_APSS is not set +CONFIG_REGULATOR_KRYO=y +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +CONFIG_MEDIA_RADIO_SUPPORT=y +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF2_CORE=y +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y + +# +# Qualcomm MSM Camera And Video +# +CONFIG_MSM_CAMERA=y +# CONFIG_MSM_CAMERA_DEBUG is not set +CONFIG_MSMB_CAMERA=y +# CONFIG_MSMB_CAMERA_DEBUG is not set +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF=y +# CONFIG_MSM_ISPIF_V1 is not set +# CONFIG_MSM_ISPIF_V2 is not set +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_MSM_JPEGDMA=y +# CONFIG_TSPP is not set + +# +# Supported MMC/SDIO adapters +# +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_SHARK is not set +# CONFIG_RADIO_SHARK2 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_USB_RAREMONO is not set +# CONFIG_USB_MA901 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_RADIO_WL128X is not set +# CONFIG_RADIO_IRIS is not set +CONFIG_RADIO_SILABS=y +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_OV2640 is not set +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_MSM_KGSL=y +# CONFIG_MSM_KGSL_CFF_DUMP is not set +CONFIG_MSM_ADRENO_DEFAULT_GOVERNOR="msm-adreno-tz" + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_FB_MSM=y +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +CONFIG_MSM_BA_V4L2=y +# CONFIG_MSM_DBA is not set +CONFIG_FB_MSM_MDSS_COMMON=y +# CONFIG_FB_MSM_MDP is not set +CONFIG_FB_MSM_MDSS=y +# CONFIG_FB_MSM_MDP_NONE is not set +# CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL is not set +# CONFIG_FB_MSM_QPIC_PANEL_DETECT is not set +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y +# CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334 is not set +# CONFIG_FB_MSM_MDSS_MHL3 is not set +# CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS is not set +# CONFIG_FB_MSM_MDSS_EDP_PANEL is not set +# CONFIG_FB_MSM_MDSS_MDP3 is not set +# CONFIG_FB_MSM_MDSS_XLOG_DEBUG is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_GENERIC=m +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_ADF is not set +# CONFIG_VGASTATE is not set +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +# CONFIG_SND_HDA_INTEL is not set +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +CONFIG_SND_SOC=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set + +# +# MSM SoC Audio support +# +CONFIG_SND_SOC_MSM_HOSTLESS_PCM=y +CONFIG_SND_SOC_MSM_QDSP6V2_INTF=y +CONFIG_SND_SOC_QDSP6V2=y +# CONFIG_DOLBY_DAP is not set +CONFIG_DOLBY_DS2=y +CONFIG_DTS_EAGLE=y +CONFIG_DTS_SRS_TM=y +CONFIG_QTI_PP=y +CONFIG_SND_SOC_CPE=y +CONFIG_SND_SOC_MSM8996=y +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271 is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_HDMI_CODEC is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +CONFIG_SND_SOC_WCD9330=y +CONFIG_SND_SOC_WCD9335=y +CONFIG_SND_SOC_WSA881X=y +CONFIG_SND_SOC_WCD9XXX=y +CONFIG_SND_SOC_WCD9XXX_V2=y +CONFIG_SND_SOC_WCD_CPE=y +CONFIG_AUDIO_EXT_CLK=y +CONFIG_SND_SOC_WCD_MBHC=y +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804 is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SOC_MSM_STUB=y +CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=y +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +CONFIG_HID_ELECOM=y +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_MSM is not set +# CONFIG_USB_EHCI_MSM_HSIC is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=y +CONFIG_USB_DWC3_MSM=y + +# +# Debugging features +# +# CONFIG_USB_DWC3_DEBUG is not set +# CONFIG_DWC3_HOST_USB3_LPM_ENABLE is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +CONFIG_USB_EHSET_TEST_FIXTURE=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_WAKELOCK is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_MSM_OTG is not set +# CONFIG_USB_MSM_HSPHY is not set +# CONFIG_USB_MSM_SSPHY is not set +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y +# CONFIG_USB_ULPI is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=4 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_CI13XXX_MSM is not set +# CONFIG_USB_CI13XXX_MSM_HSIC is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_F_ACM=y +CONFIG_USB_U_SERIAL=y +CONFIG_USB_F_SERIAL=y +CONFIG_USB_F_NCM=y +CONFIG_USB_F_ECM=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_F_FS=y +CONFIG_USB_F_UAC1=y +CONFIG_USB_F_AUDIO_SRC=y +# CONFIG_USB_CONFIGFS is not set +CONFIG_USB_G_ANDROID=y +# CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_CLKGATE=y +# CONFIG_MMC_EMBEDDED_SDIO is not set +CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +CONFIG_MMC_TEST=m +CONFIG_MMC_BLOCK_TEST=m + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_ICE=y +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +CONFIG_MMC_CQ_HCI=y +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_QPNP=y +CONFIG_LEDS_QPNP_FLASH=y +CONFIG_LEDS_QPNP_WLED=y +# CONFIG_LEDS_AW2013 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +CONFIG_SWITCH=y +# CONFIG_SWITCH_GPIO is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_EFI is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set +CONFIG_RTC_DRV_QPNP=y +# CONFIG_RTC_DRV_XGENE is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_ESOC=y +CONFIG_ESOC_DEV=y +CONFIG_ESOC_CLIENT=y +# CONFIG_ESOC_DEBUG is not set +CONFIG_ESOC_MDM_4x=y +CONFIG_ESOC_MDM_DRV=y +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC_CORE is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +CONFIG_QCOM_SPS_DMA=y +# CONFIG_PL330_DMA is not set +# CONFIG_FSL_EDMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +CONFIG_UIO=y +# CONFIG_UIO_CIF is not set +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +# CONFIG_UIO_AEC is not set +# CONFIG_UIO_SERCOS3 is not set +# CONFIG_UIO_PCI_GENERIC is not set +# CONFIG_UIO_NETX is not set +# CONFIG_UIO_MF624 is not set +CONFIG_UIO_MSM_SHAREDMEM=y +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_R8723AU is not set +# CONFIG_RTS5208 is not set +# CONFIG_LINE6_USB is not set +# CONFIG_VT6655 is not set +# CONFIG_FB_XGI is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_TIMED_OUTPUT=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ONESHOT_SYNC=y +# CONFIG_ONESHOT_SYNC_USER is not set +CONFIG_ION=y +# CONFIG_ION_TEST is not set +# CONFIG_ION_DUMMY 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 +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set + +# +# Qualcomm MSM specific device drivers +# +CONFIG_MSM_AVTIMER=y +CONFIG_MSM_BUS_SCALING=y +CONFIG_MSM_BUSPM_DEV=m +CONFIG_BUS_TOPOLOGY_ADHOC=y +# CONFIG_DEBUG_BUS_VOTER is not set +CONFIG_QPNP_POWER_ON=y +CONFIG_QPNP_REVID=y +CONFIG_QPNP_COINCELL=y +CONFIG_SPS=y +# CONFIG_EP_PCIE is not set +CONFIG_USB_BAM=y +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +# CONFIG_QPNP_VIBRATOR is not set +CONFIG_IPA=y +# CONFIG_IPA3 is not set +# CONFIG_GSI is not set +CONFIG_RMNET_IPA=y +# CONFIG_MSM_MHI is not set +# CONFIG_PFT is not set +# CONFIG_I2C_MSM_PROF_DBG is not set +CONFIG_SEEMP_CORE=y +CONFIG_QPNP_HAPTIC=y +CONFIG_GPIO_USB_DETECT=y +CONFIG_MSM_11AD=y +CONFIG_MSM_SPMI=y +CONFIG_MSM_SPMI_PMIC_ARB=y +CONFIG_MSM_QPNP_INT=y + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_CP_ACCESS64 is not set +# CONFIG_MSM_INRUSH_CURRENT_MITIGATION is not set +CONFIG_MSM_QDSP6_APRV2=y +# CONFIG_MSM_GLADIATOR_ERP is not set +# CONFIG_MSM_QDSP6_APRV3 is not set +CONFIG_MSM_ADSP_LOADER=y +# CONFIG_MSM_MEMORY_DUMP is not set +CONFIG_MSM_MEMORY_DUMP_V2=y +# CONFIG_MSM_DEBUG_LAR_UNLOCK is not set +# CONFIG_MSM_JTAG is not set +# CONFIG_MSM_JTAG_MM is not set +# CONFIG_MSM_JTAGV8 is not set +CONFIG_MSM_BOOT_STATS=y +# CONFIG_MSM_CPUSS_DUMP is not set +# CONFIG_MSM_COMMON_LOG is not set +# CONFIG_MSM_DDR_HEALTH is not set +# CONFIG_MSM_HYP_DEBUG is not set +CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y +# CONFIG_MSM_CORE_HANG_DETECT is not set +# CONFIG_MSM_GLADIATOR_HANG_DETECT is not set +CONFIG_MSM_CPU_PWR_CTL=y +CONFIG_MSM_CACHE_M4M_ERP64=y +CONFIG_MSM_CACHE_M4M_ERP64_PANIC_ON_CE=y +CONFIG_MSM_CACHE_M4M_ERP64_PANIC_ON_UE=y +CONFIG_MSM_RPM_SMD=y +# CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG is not set +CONFIG_MSM_RPM_LOG=y +CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_MSM_RUN_QUEUE_STATS=y +CONFIG_MSM_SCM=y +# CONFIG_MSM_SCM_XPU is not set +CONFIG_MSM_SCM_ERRATA=y +# CONFIG_MSM_PFE_WA is not set +CONFIG_MSM_MPM_OF=y +CONFIG_MSM_SMEM=y +CONFIG_MSM_SMD=y +# CONFIG_MSM_SMD_DEBUG is not set +CONFIG_MSM_GLINK=y +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y +CONFIG_MSM_GLINK_SMD_XPRT=y +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y +# CONFIG_MSM_SPCOM is not set +CONFIG_MSM_SMEM_LOGGING=y +CONFIG_MSM_SMP2P=y +CONFIG_MSM_SMP2P_TEST=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_QMI_INTERFACE=y +# CONFIG_MSM_DCC is not set +# CONFIG_MSM_HVC is not set +# CONFIG_MSM_IPC_ROUTER_SMD_XPRT is not set +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_SYSMON_GLINK_COMM=y +CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y +# CONFIG_MSM_SYSTEM_HEALTH_MONITOR is not set +CONFIG_MSM_GLINK_PKT=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +# CONFIG_MSM_SHARED_HEAP_ACCESS is not set +CONFIG_TRACER_PKT=y +CONFIG_MSM_SECURE_BUFFER=y +# CONFIG_ICNSS is not set +CONFIG_MSM_CORE_CTL_HELPER=y +# CONFIG_MSM_BAM_DMUX is not set +CONFIG_MSM_PERFORMANCE=y +CONFIG_MSM_PERFORMANCE_HOTPLUG_ON=y +# CONFIG_MSM_SERVICE_LOCATOR is not set +CONFIG_MSM_QBT1000=y +CONFIG_MSM_PACMAN=y +CONFIG_MSM_KERNEL_PROTECT=y +# CONFIG_MSM_KERNEL_PROTECT_TEST is not set +CONFIG_RF_CABLE_DETECT=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +# CONFIG_SOC_TI is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_MSM_CLK_CONTROLLER_V2=y +CONFIG_MSM_MDSS_PLL=y +CONFIG_HWSPINLOCK=y + +# +# Hardware Spinlock drivers +# +CONFIG_REMOTE_SPINLOCK_MSM=y + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_CLKSRC_VERSATILE is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_OF_IOMMU=y +# CONFIG_MSM_IOMMU is not set +CONFIG_ARM_SMMU=y +# CONFIG_IOMMU_DEBUG is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_CPUFREQ=y +CONFIG_DEVFREQ_GOV_MSM_ADRENO_TZ=y +CONFIG_MSM_BIMC_BWMON=y +CONFIG_DEVFREQ_GOV_MSM_GPUBW_MON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_MSMCCI_HWMON=y +CONFIG_MSM_M4M_HWMON=y +CONFIG_DEVFREQ_GOV_MSM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MSM_CACHE_HWMON=y +CONFIG_DEVFREQ_GOV_SPDM_HYP=y +CONFIG_DEVFREQ_GOV_MEMLAT=y + +# +# DEVFREQ Drivers +# +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_MSM_DEVFREQ_DEVBW=y +CONFIG_SPDM_SCM=y +CONFIG_DEVFREQ_SPDM=y +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_QPNP=y +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V3=y +# CONFIG_ARM_GIC_PANIC_HANDLER is not set +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ACL=y +# CONFIG_ARM_GIC_V3_NO_ACCESS_CONTROL is not set +CONFIG_MSM_SHOW_RESUME_IRQ=y +CONFIG_MSM_IRQ=y +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_FMC is not set +# CONFIG_CORESIGHT is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_XGENE is not set +CONFIG_PHY_QCOM_UFS=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +# CONFIG_THUNDERBOLT is not set +CONFIG_SENSORS_SSC=y + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set + +# +# EFI (Extensible Firmware Interface) Support +# +# CONFIG_EFI_VARS is not set +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_ARMSTUB=y +CONFIG_MSM_TZ_LOG=y +# CONFIG_BIF is not set +# CONFIG_MOBICORE_DRIVER is not set +CONFIG_OEM_DEBUG_SUPORT=y +CONFIG_OEM_TRACE_SUPORT=y +# CONFIG_PARAM_READ_WRITE is not set +CONFIG_OEM_FORCE_DUMP=y + +# +# Firmware Drivers +# + +# +# EFI (Extensible Firmware Interface) Support +# + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +# CONFIG_OVERLAY_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DISCARD=y +# CONFIG_EXFAT_DELAYED_SYNC is not set +# CONFIG_EXFAT_KERNEL_DEBUG is not set +# CONFIG_EXFAT_DEBUG_MSG is not set +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +CONFIG_F2FS_FS_SECURITY=y +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_EFIVAR_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set +# CONFIG_VIRTUALIZATION is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_LOG_BUF_MAGIC is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_RECURSIVE_FAULT=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_PANIC_ON_SCHED_BUG is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_PREEMPT is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +# CONFIG_MSM_RTB is not set +# CONFIG_IPC_LOGGING is not set +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_PANIC_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_ARM64_PTDUMP is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_FORCE_PAGES is not set +# CONFIG_FREE_PAGES_RDONLY is not set +# CONFIG_DEBUG_RODATA is not set + +# +# Security options +# +# CONFIG_KEYS is not set + +# +# Qualcomm Technologies, Inc Per File Encryption security device drivers +# +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +CONFIG_LSM_MMAP_MIN_ADDR=32768 +CONFIG_SECURITY_SELINUX=y +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_INTEGRITY is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=y +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_QCE50=y +# CONFIG_FIPS_ENABLE is not set +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_OTA_CRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +# CONFIG_CRYPTO_DEV_CCP is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=y +CONFIG_TEXTSEARCH_BM=y +CONFIG_TEXTSEARCH_FSM=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_LIBFDT=y +CONFIG_UCS2_STRING=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_QMI_ENCDEC=y +# CONFIG_QMI_ENCDEC_DEBUG is not set +# CONFIG_STRICT_MEMORY_RWX is not set From 050f01093f11cf858b0362fd72898c01b8a7677a Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Tue, 19 Jan 2016 16:33:27 -0800 Subject: [PATCH 008/203] dm-crypt: run in a WQ_HIGHPRI workqueue Running dm-crypt in a standard workqueue results in IO competing for CPU time with standard user apps, which can lead to pipeline bubbles and seriously degraded performance. Move to a WQ_HIGHPRI workqueue to protect against that. bug 25392275 Change-Id: I589149a31c7b5d322fe2ed5b2476b1f6e3d5ee6f Signed-off-by: flar2 --- drivers/md/dm-crypt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 5503e43e5f28..9c7a083b2497 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1841,16 +1841,16 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) } ret = -ENOMEM; - cc->io_queue = alloc_workqueue("kcryptd_io", WQ_MEM_RECLAIM, 1); + cc->io_queue = alloc_workqueue("kcryptd_io", WQ_HIGHPRI | WQ_MEM_RECLAIM, 1); if (!cc->io_queue) { ti->error = "Couldn't create kcryptd io queue"; goto bad; } if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) - cc->crypt_queue = alloc_workqueue("kcryptd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 1); + cc->crypt_queue = alloc_workqueue("kcryptd", WQ_HIGHPRI | WQ_MEM_RECLAIM, 1); else - cc->crypt_queue = alloc_workqueue("kcryptd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, + cc->crypt_queue = alloc_workqueue("kcryptd", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus()); if (!cc->crypt_queue) { ti->error = "Couldn't create kcryptd queue"; From 47ac17ee24da1b4a7058c95e38f876c487a25bf0 Mon Sep 17 00:00:00 2001 From: Nikhilesh Reddy Date: Thu, 20 Aug 2015 17:39:21 -0700 Subject: [PATCH 009/203] fs: Workaround the compiler's bad optimization When compiling the kernel with the compiler "aarch64-linux-android-gcc (GCC) 4.9.x-google 20140827 (prerelease)" The compiler seems to be optimizing a value out in the do_sync_write function and is incorrectly passing the pointer instead of the dereferenced value. Force the compiler to use the right value by passing the dereferenced pointer instead of another variable that is assigned with the dereferenced value. Change-Id: I60505ffe39393f6323dcc7c6f912c74ea6aca6cd Signed-off-by: Nikhilesh Reddy --- fs/read_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/read_write.c b/fs/read_write.c index 7d9318c3d43c..7d04af5d7fde 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -454,7 +454,7 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof kiocb.ki_pos = *ppos; kiocb.ki_nbytes = len; - ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); + ret = filp->f_op->aio_write(&kiocb, &iov, 1, *ppos); if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); *ppos = kiocb.ki_pos; From 93e13d796f9425b3c61e5241660d0b2647c1d33b Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Wed, 28 Jan 2015 20:01:39 -0500 Subject: [PATCH 010/203] tcp: fix timing issue in CUBIC slope calculation This patch fixes a bug in CUBIC that causes cwnd to increase slightly too slowly when multiple ACKs arrive in the same jiffy. If cwnd is supposed to increase at a rate of more than once per jiffy, then CUBIC was sometimes too slow. Because the bic_target is calculated for a future point in time, calculated with time in jiffies, the cwnd can increase over the course of the jiffy while the bic_target calculated as the proper CUBIC cwnd at time t=tcp_time_stamp+rtt does not increase, because tcp_time_stamp only increases on jiffy tick boundaries. So since the cnt is set to: ca->cnt = cwnd / (bic_target - cwnd); as cwnd increases but bic_target does not increase due to jiffy granularity, the cnt becomes too large, causing cwnd to increase too slowly. For example: - suppose at the beginning of a jiffy, cwnd=40, bic_target=44 - so CUBIC sets: ca->cnt = cwnd / (bic_target - cwnd) = 40 / (44 - 40) = 40/4 = 10 - suppose we get 10 acks, each for 1 segment, so tcp_cong_avoid_ai() increases cwnd to 41 - so CUBIC sets: ca->cnt = cwnd / (bic_target - cwnd) = 41 / (44 - 41) = 41 / 3 = 13 So now CUBIC will wait for 13 packets to be ACKed before increasing cwnd to 42, insted of 10 as it should. The fix is to avoid adjusting the slope (determined by ca->cnt) multiple times within a jiffy, and instead skip to compute the Reno cwnd, the "TCP friendliness" code path. Reported-by: Eyal Perry Signed-off-by: Neal Cardwell Signed-off-by: Yuchung Cheng Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_cubic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 20de0118c98e..c833def07cdb 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -216,6 +216,13 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32) return; + /* The CUBIC function can update ca->cnt at most once per jiffy. + * On all cwnd reduction events, ca->epoch_start is set to 0, + * which will force a recalculation of ca->cnt. + */ + if (ca->epoch_start && tcp_time_stamp == ca->last_time) + goto tcp_friendliness; + ca->last_cwnd = cwnd; ca->last_time = tcp_time_stamp; @@ -283,6 +290,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) if (ca->last_max_cwnd == 0 && ca->cnt > 20) ca->cnt = 20; /* increase cwnd 5% per RTT */ +tcp_friendliness: /* TCP Friendly */ if (tcp_friendliness) { u32 scale = beta_scale; From 4f07accd475aab5a6cbe7fc38fbafb0fe21110d2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 9 Sep 2015 21:55:07 -0700 Subject: [PATCH 011/203] tcp_cubic: better follow cubic curve after idle period Jana Iyengar found an interesting issue on CUBIC : The epoch is only updated/reset initially and when experiencing losses. The delta "t" of now - epoch_start can be arbitrary large after app idle as well as the bic_target. Consequentially the slope (inverse of ca->cnt) would be really large, and eventually ca->cnt would be lower-bounded in the end to 2 to have delayed-ACK slow-start behavior. This particularly shows up when slow_start_after_idle is disabled as a dangerous cwnd inflation (1.5 x RTT) after few seconds of idle time. Jana initial fix was to reset epoch_start if app limited, but Neal pointed out it would ask the CUBIC algorithm to recalculate the curve so that we again start growing steeply upward from where cwnd is now (as CUBIC does just after a loss). Ideally we'd want the cwnd growth curve to be the same shape, just shifted later in time by the amount of the idle period. Change-Id: Ia99e2743517729b1c0589fbb8db9965ec806043b Reported-by: Jana Iyengar Signed-off-by: Eric Dumazet Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Cc: Stephen Hemminger Cc: Sangtae Ha Cc: Lawrence Brakmo Signed-off-by: David S. Miller Signed-off-by: Andrea Arcangeli --- net/ipv4/tcp_cubic.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index c833def07cdb..8c8c27573de4 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -154,6 +154,21 @@ static void bictcp_init(struct sock *sk) tcp_sk(sk)->snd_ssthresh = initial_ssthresh; } +static void bictcp_cwnd_event(struct sock *sk, enum tcp_ca_event event) +{ + if (event == CA_EVENT_TX_START) { + s32 delta = tcp_time_stamp - tcp_sk(sk)->lsndtime; + struct bictcp *ca = inet_csk_ca(sk); + + /* We were application limited (idle) for a while. + * Shift epoch_start to keep cwnd growth to cubic curve. + */ + if (ca->epoch_start && delta > 0) + ca->epoch_start += delta; + return; + } +} + /* calculate the cubic root of x using a table lookup followed by one * Newton-Raphson iteration. * Avg err ~= 0.195% @@ -448,6 +463,7 @@ static struct tcp_congestion_ops cubictcp __read_mostly = { .cong_avoid = bictcp_cong_avoid, .set_state = bictcp_state, .undo_cwnd = bictcp_undo_cwnd, + .cwnd_event = bictcp_cwnd_event, .pkts_acked = bictcp_acked, .owner = THIS_MODULE, .name = "cubic", From 985799e4d47fc90143140fc31ece1324bc059fb7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 17 Sep 2015 08:38:00 -0700 Subject: [PATCH 012/203] tcp_cubic: do not set epoch_start in the future Tracking idle time in bictcp_cwnd_event() is imprecise, as epoch_start is normally set at ACK processing time, not at send time. Doing a proper fix would need to add an additional state variable, and does not seem worth the trouble, given CUBIC bug has been there forever before Jana noticed it. Let's simply not set epoch_start in the future, otherwise bictcp_update() could overflow and CUBIC would again grow cwnd too fast. This was detected thanks to a packetdrill test Neal wrote that was flaky before applying this fix. Change-Id: I600d3a8ac0ed1d70f3ff5cc6b7341ac13178f4f3 Fixes: 30927520dbae ("tcp_cubic: better follow cubic curve after idle period") Signed-off-by: Eric Dumazet Signed-off-by: Neal Cardwell Signed-off-by: Yuchung Cheng Cc: Jana Iyengar Signed-off-by: David S. Miller Signed-off-by: Andrea Arcangeli --- net/ipv4/tcp_cubic.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 8c8c27573de4..5344ac34eaac 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -157,14 +157,20 @@ static void bictcp_init(struct sock *sk) static void bictcp_cwnd_event(struct sock *sk, enum tcp_ca_event event) { if (event == CA_EVENT_TX_START) { - s32 delta = tcp_time_stamp - tcp_sk(sk)->lsndtime; struct bictcp *ca = inet_csk_ca(sk); + u32 now = tcp_time_stamp; + s32 delta; + + delta = now - tcp_sk(sk)->lsndtime; /* We were application limited (idle) for a while. * Shift epoch_start to keep cwnd growth to cubic curve. */ - if (ca->epoch_start && delta > 0) + if (ca->epoch_start && delta > 0) { ca->epoch_start += delta; + if (after(ca->epoch_start, now)) + ca->epoch_start = now; + } return; } } From 4c64362aedb0bafedcf0956b04ac29babcdfbd1a Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 11 May 2011 16:29:33 +0100 Subject: [PATCH 013/203] mm: slub: Default slub_max_order to 0 To avoid locking and per-cpu overhead, SLUB optimisically uses high-order allocations up to order-3 by default and falls back to lower allocations if they fail. While care is taken that the caller and kswapd take no unusual steps in response to this, there are further consequences like shrinkers who have to free more objects to release any memory. There is anecdotal evidence that significant time is being spent looping in shrinkers with insufficient progress being made (https://lkml.org/lkml/2011/4/28/361) and keeping kswapd awake. SLUB is now the default allocator and some bug reports have been pinned down to SLUB using high orders during operations like copying large amounts of data. SLUBs use of high-orders benefits applications that are sized to memory appropriately but this does not necessarily apply to large file servers or desktops. This patch causes SLUB to use order-0 pages like SLAB does by default. There is further evidence that this keeps kswapd's usage lower (https://lkml.org/lkml/2011/5/10/383). Signed-off-by: Mel Gorman Signed-off-by: flar2 --- mm/slub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index bbfbf3d83166..fb1f31f7eeef 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2760,7 +2760,7 @@ EXPORT_SYMBOL(kmem_cache_free); * take the list_lock. */ static int slub_min_order; -static int slub_max_order = PAGE_ALLOC_COSTLY_ORDER; +static int slub_max_order; static int slub_min_objects; /* From 243487b1eb3650d777424e52cefbb411b01ce0e4 Mon Sep 17 00:00:00 2001 From: franciscofranco Date: Wed, 21 Nov 2012 23:45:56 -0800 Subject: [PATCH 014/203] Added fsync on/off support. Signed-off-by: Francisco Franco Signed-off-by: flar2 --- fs/sync.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/fs/sync.c b/fs/sync.c index bdc729d80e5e..41a8a26fef81 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,9 @@ #include #include "internal.h" +bool fsync_enabled = true; +module_param(fsync_enabled, bool, 0755); + #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ SYNC_FILE_RANGE_WAIT_AFTER) @@ -152,6 +156,9 @@ SYSCALL_DEFINE1(syncfs, int, fd) struct super_block *sb; int ret; + if (!fsync_enabled) + return 0; + if (!f.file) return -EBADF; sb = f.file->f_dentry->d_sb; @@ -177,6 +184,9 @@ SYSCALL_DEFINE1(syncfs, int, fd) */ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) { + if (!fsync_enabled) + return 0; + if (!file->f_op->fsync) return -EINVAL; return file->f_op->fsync(file, start, end, datasync); @@ -193,6 +203,9 @@ EXPORT_SYMBOL(vfs_fsync_range); */ int vfs_fsync(struct file *file, int datasync) { + if (!fsync_enabled) + return 0; + return vfs_fsync_range(file, 0, LLONG_MAX, datasync); } EXPORT_SYMBOL(vfs_fsync); @@ -201,6 +214,9 @@ static int do_fsync(unsigned int fd, int datasync) { struct fd f = fdget(fd); int ret = -EBADF; + + if (!fsync_enabled) + return 0; if (f.file) { ret = vfs_fsync(f.file, datasync); @@ -211,11 +227,17 @@ static int do_fsync(unsigned int fd, int datasync) SYSCALL_DEFINE1(fsync, unsigned int, fd) { + if (!fsync_enabled) + return 0; + return do_fsync(fd, 0); } SYSCALL_DEFINE1(fdatasync, unsigned int, fd) { + if (!fsync_enabled) + return 0; + return do_fsync(fd, 1); } @@ -275,6 +297,9 @@ SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes, loff_t endbyte; /* inclusive */ umode_t i_mode; + if (!fsync_enabled) + return 0; + ret = -EINVAL; if (flags & ~VALID_FLAGS) goto out; From 591435f78a10be9bedb3d5b1ac167a7dc0a11c2a Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 8 Nov 2013 20:53:32 -0500 Subject: [PATCH 015/203] Add SIO and FIOPS i/o schedulers Signed-off-by: flar2 --- block/Kconfig.iosched | 26 ++ block/Makefile | 2 + block/fiops-iosched.c | 765 ++++++++++++++++++++++++++++++++++++++++++ block/sio-iosched.c | 412 +++++++++++++++++++++++ 4 files changed, 1205 insertions(+) create mode 100644 block/fiops-iosched.c create mode 100644 block/sio-iosched.c diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index af3d6a330982..4072cb252ce6 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -43,6 +43,24 @@ config IOSCHED_CFQ This is the default I/O scheduler. +config IOSCHED_FIOPS + tristate "IOPS based I/O scheduler" + default y + ---help--- + This is an IOPS based I/O scheduler. It will try to distribute + IOPS equally among all processes in the system. It's mainly for + Flash based storage. + +config IOSCHED_SIO + tristate "Simple I/O scheduler" + default y + ---help--- + The Simple I/O scheduler is an extremely simple scheduler, + based on noop and deadline, that relies on deadlines to + ensure fairness. The algorithm does not do any sorting but + basic merging, trying to keep a minimum overhead. It is aimed + mainly for aleatory access devices (eg: flash devices). + config CFQ_GROUP_IOSCHED bool "CFQ Group Scheduling support" depends on IOSCHED_CFQ && BLK_CGROUP @@ -66,6 +84,12 @@ choice config DEFAULT_NOOP bool "No-op" + config DEFAULT_SIO + bool "SIO" if IOSCHED_SIO=y + + config DEFAULT_FIOPS + bool "FIOPS" if IOSCHED_FIOPS=y + endchoice config DEFAULT_IOSCHED @@ -73,6 +97,8 @@ config DEFAULT_IOSCHED default "deadline" if DEFAULT_DEADLINE default "cfq" if DEFAULT_CFQ default "noop" if DEFAULT_NOOP + default "fiops" if DEFAULT_FIOPS + default "sio" if DEFAULT_SIO endmenu diff --git a/block/Makefile b/block/Makefile index ba63d68fe91d..985b857c2c7f 100644 --- a/block/Makefile +++ b/block/Makefile @@ -19,6 +19,8 @@ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o +obj-$(CONFIG_IOSCHED_FIOPS) += fiops-iosched.o +obj-$(CONFIG_IOSCHED_SIO) += sio-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o diff --git a/block/fiops-iosched.c b/block/fiops-iosched.c new file mode 100644 index 000000000000..5aa58da5bb62 --- /dev/null +++ b/block/fiops-iosched.c @@ -0,0 +1,765 @@ +/* + * IOPS based IO scheduler. Based on CFQ. + * Copyright (C) 2003 Jens Axboe + * Shaohua Li + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "blk.h" + +#define VIOS_SCALE_SHIFT 10 +#define VIOS_SCALE (1 << VIOS_SCALE_SHIFT) + +#define VIOS_READ_SCALE (1) +#define VIOS_WRITE_SCALE (1) +#define VIOS_SYNC_SCALE (2) +#define VIOS_ASYNC_SCALE (5) + +#define VIOS_PRIO_SCALE (5) + +struct fiops_rb_root { + struct rb_root rb; + struct rb_node *left; + unsigned count; + + u64 min_vios; +}; +#define FIOPS_RB_ROOT (struct fiops_rb_root) { .rb = RB_ROOT} + +enum wl_prio_t { + IDLE_WORKLOAD = 0, + BE_WORKLOAD = 1, + RT_WORKLOAD = 2, + FIOPS_PRIO_NR, +}; + +struct fiops_data { + struct request_queue *queue; + + struct fiops_rb_root service_tree[FIOPS_PRIO_NR]; + + unsigned int busy_queues; + unsigned int in_flight[2]; + + struct work_struct unplug_work; + + unsigned int read_scale; + unsigned int write_scale; + unsigned int sync_scale; + unsigned int async_scale; +}; + +struct fiops_ioc { + struct io_cq icq; + + unsigned int flags; + struct fiops_data *fiopsd; + struct rb_node rb_node; + u64 vios; /* key in service_tree */ + struct fiops_rb_root *service_tree; + + unsigned int in_flight; + + struct rb_root sort_list; + struct list_head fifo; + + pid_t pid; + unsigned short ioprio; + enum wl_prio_t wl_type; +}; + +#define ioc_service_tree(ioc) (&((ioc)->fiopsd->service_tree[(ioc)->wl_type])) +#define RQ_CIC(rq) icq_to_cic((rq)->elv.icq) + +enum ioc_state_flags { + FIOPS_IOC_FLAG_on_rr = 0, /* on round-robin busy list */ + FIOPS_IOC_FLAG_prio_changed, /* task priority has changed */ +}; + +#define FIOPS_IOC_FNS(name) \ +static inline void fiops_mark_ioc_##name(struct fiops_ioc *ioc) \ +{ \ + ioc->flags |= (1 << FIOPS_IOC_FLAG_##name); \ +} \ +static inline void fiops_clear_ioc_##name(struct fiops_ioc *ioc) \ +{ \ + ioc->flags &= ~(1 << FIOPS_IOC_FLAG_##name); \ +} \ +static inline int fiops_ioc_##name(const struct fiops_ioc *ioc) \ +{ \ + return ((ioc)->flags & (1 << FIOPS_IOC_FLAG_##name)) != 0; \ +} + +FIOPS_IOC_FNS(on_rr); +FIOPS_IOC_FNS(prio_changed); +#undef FIOPS_IOC_FNS + +#define fiops_log_ioc(fiopsd, ioc, fmt, args...) \ + blk_add_trace_msg((fiopsd)->queue, "ioc%d " fmt, (ioc)->pid, ##args) +#define fiops_log(fiopsd, fmt, args...) \ + blk_add_trace_msg((fiopsd)->queue, "fiops " fmt, ##args) + +enum wl_prio_t fiops_wl_type(short prio_class) +{ + if (prio_class == IOPRIO_CLASS_RT) + return RT_WORKLOAD; + if (prio_class == IOPRIO_CLASS_BE) + return BE_WORKLOAD; + return IDLE_WORKLOAD; +} + +static inline struct fiops_ioc *icq_to_cic(struct io_cq *icq) +{ + /* cic->icq is the first member, %NULL will convert to %NULL */ + return container_of(icq, struct fiops_ioc, icq); +} + +static inline struct fiops_ioc *fiops_cic_lookup(struct fiops_data *fiopsd, + struct io_context *ioc) +{ + if (ioc) + return icq_to_cic(ioc_lookup_icq(ioc, fiopsd->queue)); + return NULL; +} + +/* + * The below is leftmost cache rbtree addon + */ +static struct fiops_ioc *fiops_rb_first(struct fiops_rb_root *root) +{ + /* Service tree is empty */ + if (!root->count) + return NULL; + + if (!root->left) + root->left = rb_first(&root->rb); + + if (root->left) + return rb_entry(root->left, struct fiops_ioc, rb_node); + + return NULL; +} + +static void rb_erase_init(struct rb_node *n, struct rb_root *root) +{ + rb_erase(n, root); + RB_CLEAR_NODE(n); +} + +static void fiops_rb_erase(struct rb_node *n, struct fiops_rb_root *root) +{ + if (root->left == n) + root->left = NULL; + rb_erase_init(n, &root->rb); + --root->count; +} + +static inline u64 max_vios(u64 min_vios, u64 vios) +{ + s64 delta = (s64)(vios - min_vios); + if (delta > 0) + min_vios = vios; + + return min_vios; +} + +static void fiops_update_min_vios(struct fiops_rb_root *service_tree) +{ + struct fiops_ioc *ioc; + + ioc = fiops_rb_first(service_tree); + if (!ioc) + return; + service_tree->min_vios = max_vios(service_tree->min_vios, ioc->vios); +} + +/* + * The fiopsd->service_trees holds all pending fiops_ioc's that have + * requests waiting to be processed. It is sorted in the order that + * we will service the queues. + */ +static void fiops_service_tree_add(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + struct rb_node **p, *parent; + struct fiops_ioc *__ioc; + struct fiops_rb_root *service_tree = ioc_service_tree(ioc); + u64 vios; + int left; + + /* New added IOC */ + if (RB_EMPTY_NODE(&ioc->rb_node)) { + if (ioc->in_flight > 0) + vios = ioc->vios; + else + vios = max_vios(service_tree->min_vios, ioc->vios); + } else { + vios = ioc->vios; + /* ioc->service_tree might not equal to service_tree */ + fiops_rb_erase(&ioc->rb_node, ioc->service_tree); + ioc->service_tree = NULL; + } + + fiops_log_ioc(fiopsd, ioc, "service tree add, vios %lld", vios); + + left = 1; + parent = NULL; + ioc->service_tree = service_tree; + p = &service_tree->rb.rb_node; + while (*p) { + struct rb_node **n; + + parent = *p; + __ioc = rb_entry(parent, struct fiops_ioc, rb_node); + + /* + * sort by key, that represents service time. + */ + if (vios < __ioc->vios) + n = &(*p)->rb_left; + else { + n = &(*p)->rb_right; + left = 0; + } + + p = n; + } + + if (left) + service_tree->left = &ioc->rb_node; + + ioc->vios = vios; + rb_link_node(&ioc->rb_node, parent, p); + rb_insert_color(&ioc->rb_node, &service_tree->rb); + service_tree->count++; + + fiops_update_min_vios(service_tree); +} + +/* + * Update ioc's position in the service tree. + */ +static void fiops_resort_rr_list(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + /* + * Resorting requires the ioc to be on the RR list already. + */ + if (fiops_ioc_on_rr(ioc)) + fiops_service_tree_add(fiopsd, ioc); +} + +/* + * add to busy list of queues for service, trying to be fair in ordering + * the pending list according to last request service + */ +static void fiops_add_ioc_rr(struct fiops_data *fiopsd, struct fiops_ioc *ioc) +{ + BUG_ON(fiops_ioc_on_rr(ioc)); + fiops_mark_ioc_on_rr(ioc); + + fiopsd->busy_queues++; + + fiops_resort_rr_list(fiopsd, ioc); +} + +/* + * Called when the ioc no longer has requests pending, remove it from + * the service tree. + */ +static void fiops_del_ioc_rr(struct fiops_data *fiopsd, struct fiops_ioc *ioc) +{ + BUG_ON(!fiops_ioc_on_rr(ioc)); + fiops_clear_ioc_on_rr(ioc); + + if (!RB_EMPTY_NODE(&ioc->rb_node)) { + fiops_rb_erase(&ioc->rb_node, ioc->service_tree); + ioc->service_tree = NULL; + } + + BUG_ON(!fiopsd->busy_queues); + fiopsd->busy_queues--; +} + +/* + * rb tree support functions + */ +static void fiops_del_rq_rb(struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + + elv_rb_del(&ioc->sort_list, rq); +} + +static void fiops_add_rq_rb(struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + struct fiops_data *fiopsd = ioc->fiopsd; + + elv_rb_add(&ioc->sort_list, rq); + + if (!fiops_ioc_on_rr(ioc)) + fiops_add_ioc_rr(fiopsd, ioc); +} + +static void fiops_reposition_rq_rb(struct fiops_ioc *ioc, struct request *rq) +{ + elv_rb_del(&ioc->sort_list, rq); + fiops_add_rq_rb(rq); +} + +static void fiops_remove_request(struct request *rq) +{ + list_del_init(&rq->queuelist); + fiops_del_rq_rb(rq); +} + +static u64 fiops_scaled_vios(struct fiops_data *fiopsd, + struct fiops_ioc *ioc, struct request *rq) +{ + int vios = VIOS_SCALE; + + if (rq_data_dir(rq) == WRITE) + vios = vios * fiopsd->write_scale / fiopsd->read_scale; + + if (!rq_is_sync(rq)) + vios = vios * fiopsd->async_scale / fiopsd->sync_scale; + + vios += vios * (ioc->ioprio - IOPRIO_NORM) / VIOS_PRIO_SCALE; + + return vios; +} + +/* return vios dispatched */ +static u64 fiops_dispatch_request(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + struct request *rq; + struct request_queue *q = fiopsd->queue; + + rq = rq_entry_fifo(ioc->fifo.next); + + fiops_remove_request(rq); + elv_dispatch_add_tail(q, rq); + + fiopsd->in_flight[rq_is_sync(rq)]++; + ioc->in_flight++; + + return fiops_scaled_vios(fiopsd, ioc, rq); +} + +static int fiops_forced_dispatch(struct fiops_data *fiopsd) +{ + struct fiops_ioc *ioc; + int dispatched = 0; + int i; + + for (i = RT_WORKLOAD; i >= IDLE_WORKLOAD; i--) { + while (!RB_EMPTY_ROOT(&fiopsd->service_tree[i].rb)) { + ioc = fiops_rb_first(&fiopsd->service_tree[i]); + + while (!list_empty(&ioc->fifo)) { + fiops_dispatch_request(fiopsd, ioc); + dispatched++; + } + if (fiops_ioc_on_rr(ioc)) + fiops_del_ioc_rr(fiopsd, ioc); + } + } + return dispatched; +} + +static struct fiops_ioc *fiops_select_ioc(struct fiops_data *fiopsd) +{ + struct fiops_ioc *ioc; + struct fiops_rb_root *service_tree = NULL; + int i; + struct request *rq; + + for (i = RT_WORKLOAD; i >= IDLE_WORKLOAD; i--) { + if (!RB_EMPTY_ROOT(&fiopsd->service_tree[i].rb)) { + service_tree = &fiopsd->service_tree[i]; + break; + } + } + + if (!service_tree) + return NULL; + + ioc = fiops_rb_first(service_tree); + + rq = rq_entry_fifo(ioc->fifo.next); + /* + * we are the only async task and sync requests are in flight, delay a + * moment. If there are other tasks coming, sync tasks have no chance + * to be starved, don't delay + */ + if (!rq_is_sync(rq) && fiopsd->in_flight[1] != 0 && + service_tree->count == 1) { + fiops_log_ioc(fiopsd, ioc, + "postpone async, in_flight async %d sync %d", + fiopsd->in_flight[0], fiopsd->in_flight[1]); + return NULL; + } + + return ioc; +} + +static void fiops_charge_vios(struct fiops_data *fiopsd, + struct fiops_ioc *ioc, u64 vios) +{ + struct fiops_rb_root *service_tree = ioc->service_tree; + ioc->vios += vios; + + fiops_log_ioc(fiopsd, ioc, "charge vios %lld, new vios %lld", vios, ioc->vios); + + if (RB_EMPTY_ROOT(&ioc->sort_list)) + fiops_del_ioc_rr(fiopsd, ioc); + else + fiops_resort_rr_list(fiopsd, ioc); + + fiops_update_min_vios(service_tree); +} + +static int fiops_dispatch_requests(struct request_queue *q, int force) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *ioc; + u64 vios; + + if (unlikely(force)) + return fiops_forced_dispatch(fiopsd); + + ioc = fiops_select_ioc(fiopsd); + if (!ioc) + return 0; + + vios = fiops_dispatch_request(fiopsd, ioc); + + fiops_charge_vios(fiopsd, ioc, vios); + return 1; +} + +static void fiops_init_prio_data(struct fiops_ioc *cic) +{ + struct task_struct *tsk = current; + struct io_context *ioc = cic->icq.ioc; + int ioprio_class; + + if (!fiops_ioc_prio_changed(cic)) + return; + + ioprio_class = IOPRIO_PRIO_CLASS(ioc->ioprio); + switch (ioprio_class) { + default: + printk(KERN_ERR "fiops: bad prio %x\n", ioprio_class); + case IOPRIO_CLASS_NONE: + /* + * no prio set, inherit CPU scheduling settings + */ + cic->ioprio = task_nice_ioprio(tsk); + cic->wl_type = fiops_wl_type(task_nice_ioclass(tsk)); + break; + case IOPRIO_CLASS_RT: + cic->ioprio = IOPRIO_PRIO_DATA(ioc->ioprio); + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_RT); + break; + case IOPRIO_CLASS_BE: + cic->ioprio = IOPRIO_PRIO_DATA(ioc->ioprio); + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_BE); + break; + case IOPRIO_CLASS_IDLE: + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_IDLE); + cic->ioprio = 7; + break; + } + + fiops_clear_ioc_prio_changed(cic); +} + +static void fiops_insert_request(struct request_queue *q, struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + + fiops_init_prio_data(ioc); + + list_add_tail(&rq->queuelist, &ioc->fifo); + + fiops_add_rq_rb(rq); +} + +/* + * scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing + */ +static inline void fiops_schedule_dispatch(struct fiops_data *fiopsd) +{ + if (fiopsd->busy_queues) + kblockd_schedule_work(fiopsd->queue, &fiopsd->unplug_work); +} + +static void fiops_completed_request(struct request_queue *q, struct request *rq) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *ioc = RQ_CIC(rq); + + fiopsd->in_flight[rq_is_sync(rq)]--; + ioc->in_flight--; + + fiops_log_ioc(fiopsd, ioc, "in_flight %d, busy queues %d", + ioc->in_flight, fiopsd->busy_queues); + + if (fiopsd->in_flight[0] + fiopsd->in_flight[1] == 0) + fiops_schedule_dispatch(fiopsd); +} + +static struct request * +fiops_find_rq_fmerge(struct fiops_data *fiopsd, struct bio *bio) +{ + struct task_struct *tsk = current; + struct fiops_ioc *cic; + + cic = fiops_cic_lookup(fiopsd, tsk->io_context); + + if (cic) { + sector_t sector = bio->bi_sector + bio_sectors(bio); + + return elv_rb_find(&cic->sort_list, sector); + } + + return NULL; +} + +static int fiops_merge(struct request_queue *q, struct request **req, + struct bio *bio) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct request *__rq; + + __rq = fiops_find_rq_fmerge(fiopsd, bio); + if (__rq && elv_rq_merge_ok(__rq, bio)) { + *req = __rq; + return ELEVATOR_FRONT_MERGE; + } + + return ELEVATOR_NO_MERGE; +} + +static void fiops_merged_request(struct request_queue *q, struct request *req, + int type) +{ + if (type == ELEVATOR_FRONT_MERGE) { + struct fiops_ioc *ioc = RQ_CIC(req); + + fiops_reposition_rq_rb(ioc, req); + } +} + +static void +fiops_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + struct fiops_data *fiopsd = q->elevator->elevator_data; + + fiops_remove_request(next); + + ioc = RQ_CIC(next); + /* + * all requests of this task are merged to other tasks, delete it + * from the service tree. + */ + if (fiops_ioc_on_rr(ioc) && RB_EMPTY_ROOT(&ioc->sort_list)) + fiops_del_ioc_rr(fiopsd, ioc); +} + +static int fiops_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *cic; + + /* + * Lookup the ioc that this bio will be queued with. Allow + * merge only if rq is queued there. + */ + cic = fiops_cic_lookup(fiopsd, current->io_context); + + return cic == RQ_CIC(rq); +} + +static void fiops_exit_queue(struct elevator_queue *e) +{ + struct fiops_data *fiopsd = e->elevator_data; + + cancel_work_sync(&fiopsd->unplug_work); + + kfree(fiopsd); +} + +static void fiops_kick_queue(struct work_struct *work) +{ + struct fiops_data *fiopsd = + container_of(work, struct fiops_data, unplug_work); + struct request_queue *q = fiopsd->queue; + + spin_lock_irq(q->queue_lock); + __blk_run_queue(q); + spin_unlock_irq(q->queue_lock); +} + +static int fiops_init_queue(struct request_queue *q, struct elevator_type *e) +{ + struct fiops_data *fiopsd; + int i; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; + + fiopsd = kzalloc_node(sizeof(*fiopsd), GFP_KERNEL, q->node); + if (!fiopsd) { + kobject_put(&eq->kobj); + return -ENOMEM; + } + eq->elevator_data = fiopsd; + + fiopsd->queue = q; + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); + + for (i = IDLE_WORKLOAD; i <= RT_WORKLOAD; i++) + fiopsd->service_tree[i] = FIOPS_RB_ROOT; + + INIT_WORK(&fiopsd->unplug_work, fiops_kick_queue); + + fiopsd->read_scale = VIOS_READ_SCALE; + fiopsd->write_scale = VIOS_WRITE_SCALE; + fiopsd->sync_scale = VIOS_SYNC_SCALE; + fiopsd->async_scale = VIOS_ASYNC_SCALE; + + return 0; +} + +static void fiops_init_icq(struct io_cq *icq) +{ + struct fiops_data *fiopsd = icq->q->elevator->elevator_data; + struct fiops_ioc *ioc = icq_to_cic(icq); + + RB_CLEAR_NODE(&ioc->rb_node); + INIT_LIST_HEAD(&ioc->fifo); + ioc->sort_list = RB_ROOT; + + ioc->fiopsd = fiopsd; + + ioc->pid = current->pid; + fiops_mark_ioc_prio_changed(ioc); +} + +/* + * sysfs parts below --> + */ +static ssize_t +fiops_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +fiops_var_store(unsigned int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + return fiops_var_show(__VAR, (page)); \ +} +SHOW_FUNCTION(fiops_read_scale_show, fiopsd->read_scale); +SHOW_FUNCTION(fiops_write_scale_show, fiopsd->write_scale); +SHOW_FUNCTION(fiops_sync_scale_show, fiopsd->sync_scale); +SHOW_FUNCTION(fiops_async_scale_show, fiopsd->async_scale); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + unsigned int __data; \ + int ret = fiops_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(fiops_read_scale_store, &fiopsd->read_scale, 1, 100); +STORE_FUNCTION(fiops_write_scale_store, &fiopsd->write_scale, 1, 100); +STORE_FUNCTION(fiops_sync_scale_store, &fiopsd->sync_scale, 1, 100); +STORE_FUNCTION(fiops_async_scale_store, &fiopsd->async_scale, 1, 100); +#undef STORE_FUNCTION + +#define FIOPS_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, fiops_##name##_show, fiops_##name##_store) + +static struct elv_fs_entry fiops_attrs[] = { + FIOPS_ATTR(read_scale), + FIOPS_ATTR(write_scale), + FIOPS_ATTR(sync_scale), + FIOPS_ATTR(async_scale), + __ATTR_NULL +}; + +static struct elevator_type iosched_fiops = { + .ops = { + .elevator_merge_fn = fiops_merge, + .elevator_merged_fn = fiops_merged_request, + .elevator_merge_req_fn = fiops_merged_requests, + .elevator_allow_merge_fn = fiops_allow_merge, + .elevator_dispatch_fn = fiops_dispatch_requests, + .elevator_add_req_fn = fiops_insert_request, + .elevator_completed_req_fn = fiops_completed_request, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_init_icq_fn = fiops_init_icq, + .elevator_init_fn = fiops_init_queue, + .elevator_exit_fn = fiops_exit_queue, + }, + .icq_size = sizeof(struct fiops_ioc), + .icq_align = __alignof__(struct fiops_ioc), + .elevator_attrs = fiops_attrs, + .elevator_name = "fiops", + .elevator_owner = THIS_MODULE, +}; + +static int __init fiops_init(void) +{ + return elv_register(&iosched_fiops); +} + +static void __exit fiops_exit(void) +{ + elv_unregister(&iosched_fiops); +} + +module_init(fiops_init); +module_exit(fiops_exit); + +MODULE_AUTHOR("Jens Axboe, Shaohua Li "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IOPS based IO scheduler"); + diff --git a/block/sio-iosched.c b/block/sio-iosched.c new file mode 100644 index 000000000000..31bf114d084c --- /dev/null +++ b/block/sio-iosched.c @@ -0,0 +1,412 @@ +/* + * Simple IO scheduler + * Based on Noop, Deadline and V(R) IO schedulers. + * + * Copyright (C) 2012 Miguel Boton + * + * + * This algorithm does not do any kind of sorting, as it is aimed for + * aleatory access devices, but it does some basic merging. We try to + * keep minimum overhead to achieve low latency. + * + * Asynchronous and synchronous requests are not treated separately, but + * we relay on deadlines to ensure fairness. + * + */ +#include +#include +#include +#include +#include +#include +#include + +enum { ASYNC, SYNC }; + +/* Tunables */ +static const int sync_read_expire = HZ / 2; /* max time before a sync read is submitted. */ +static const int sync_write_expire = 2 * HZ; /* max time before a sync write is submitted. */ + +static const int async_read_expire = 4 * HZ; /* ditto for async, these limits are SOFT! */ +static const int async_write_expire = 16 * HZ; /* ditto for async, these limits are SOFT! */ + +static const int writes_starved = 2; /* max times reads can starve a write */ +static const int fifo_batch = 8; /* # of sequential requests treated as one + by the above parameters. For throughput. */ + +/* Elevator data */ +struct sio_data { + /* Request queues */ + struct list_head fifo_list[2][2]; + + /* Attributes */ + unsigned int batched; + unsigned int starved; + + /* Settings */ + int fifo_expire[2][2]; + int fifo_batch; + int writes_starved; +}; + +static void +sio_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + /* + * If next expires before rq, assign its expire time to rq + * and move into next position (next will be deleted) in fifo. + */ + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { + if (time_before(rq_fifo_time(next), rq_fifo_time(rq))) { + list_move(&rq->queuelist, &next->queuelist); + rq_set_fifo_time(rq, rq_fifo_time(next)); + } + } + + /* Delete next request */ + rq_fifo_clear(next); +} + +static void +sio_add_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + /* + * Add request to the proper fifo list and set its + * expire time. + */ + rq_set_fifo_time(rq, jiffies + sd->fifo_expire[sync][data_dir]); + list_add_tail(&rq->queuelist, &sd->fifo_list[sync][data_dir]); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) +static int +sio_queue_empty(struct request_queue *q) +{ + struct sio_data *sd = q->elevator->elevator_data; + + /* Check if fifo lists are empty */ + return list_empty(&sd->fifo_list[SYNC][READ]) && list_empty(&sd->fifo_list[SYNC][WRITE]) && + list_empty(&sd->fifo_list[ASYNC][READ]) && list_empty(&sd->fifo_list[ASYNC][WRITE]); +} +#endif + +static struct request * +sio_expired_request(struct sio_data *sd, int sync, int data_dir) +{ + struct list_head *list = &sd->fifo_list[sync][data_dir]; + struct request *rq; + + if (list_empty(list)) + return NULL; + + /* Retrieve request */ + rq = rq_entry_fifo(list->next); + + /* Request has expired */ + if (time_after(jiffies, rq_fifo_time(rq))) + return rq; + + return NULL; +} + +static struct request * +sio_choose_expired_request(struct sio_data *sd) +{ + struct request *rq; + + /* + * Check expired requests. + * Asynchronous requests have priority over synchronous. + * Write requests have priority over read. + */ + rq = sio_expired_request(sd, ASYNC, WRITE); + if (rq) + return rq; + rq = sio_expired_request(sd, ASYNC, READ); + if (rq) + return rq; + + rq = sio_expired_request(sd, SYNC, WRITE); + if (rq) + return rq; + rq = sio_expired_request(sd, SYNC, READ); + if (rq) + return rq; + + return NULL; +} + +static struct request * +sio_choose_request(struct sio_data *sd, int data_dir) +{ + struct list_head *sync = sd->fifo_list[SYNC]; + struct list_head *async = sd->fifo_list[ASYNC]; + + /* + * Retrieve request from available fifo list. + * Synchronous requests have priority over asynchronous. + * Read requests have priority over write. + */ + if (!list_empty(&sync[data_dir])) + return rq_entry_fifo(sync[data_dir].next); + if (!list_empty(&async[data_dir])) + return rq_entry_fifo(async[data_dir].next); + + if (!list_empty(&sync[!data_dir])) + return rq_entry_fifo(sync[!data_dir].next); + if (!list_empty(&async[!data_dir])) + return rq_entry_fifo(async[!data_dir].next); + + return NULL; +} + +static inline void +sio_dispatch_request(struct sio_data *sd, struct request *rq) +{ + /* + * Remove the request from the fifo list + * and dispatch it. + */ + rq_fifo_clear(rq); + elv_dispatch_add_tail(rq->q, rq); + + sd->batched++; + + if (rq_data_dir(rq)) + sd->starved = 0; + else + sd->starved++; +} + +static int +sio_dispatch_requests(struct request_queue *q, int force) +{ + struct sio_data *sd = q->elevator->elevator_data; + struct request *rq = NULL; + int data_dir = READ; + + /* + * Retrieve any expired request after a batch of + * sequential requests. + */ + if (sd->batched > sd->fifo_batch) { + sd->batched = 0; + rq = sio_choose_expired_request(sd); + } + + /* Retrieve request */ + if (!rq) { + if (sd->starved > sd->writes_starved) + data_dir = WRITE; + + rq = sio_choose_request(sd, data_dir); + if (!rq) + return 0; + } + + /* Dispatch request */ + sio_dispatch_request(sd, rq); + + return 1; +} + +static struct request * +sio_former_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + if (rq->queuelist.prev == &sd->fifo_list[sync][data_dir]) + return NULL; + + /* Return former request */ + return list_entry(rq->queuelist.prev, struct request, queuelist); +} + +static struct request * +sio_latter_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + if (rq->queuelist.next == &sd->fifo_list[sync][data_dir]) + return NULL; + + /* Return latter request */ + return list_entry(rq->queuelist.next, struct request, queuelist); +} + +static int sio_init_queue(struct request_queue *q, struct elevator_type *e) +{ + struct sio_data *sd; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; + + /* Allocate structure */ + sd = kmalloc_node(sizeof(*sd), GFP_KERNEL, q->node); + if (!sd) { + kobject_put(&eq->kobj); + return -ENOMEM; + } + eq->elevator_data = sd; + + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); + + /* Initialize fifo lists */ + INIT_LIST_HEAD(&sd->fifo_list[SYNC][READ]); + INIT_LIST_HEAD(&sd->fifo_list[SYNC][WRITE]); + INIT_LIST_HEAD(&sd->fifo_list[ASYNC][READ]); + INIT_LIST_HEAD(&sd->fifo_list[ASYNC][WRITE]); + + /* Initialize data */ + sd->batched = 0; + sd->fifo_expire[SYNC][READ] = sync_read_expire; + sd->fifo_expire[SYNC][WRITE] = sync_write_expire; + sd->fifo_expire[ASYNC][READ] = async_read_expire; + sd->fifo_expire[ASYNC][WRITE] = async_write_expire; + sd->fifo_batch = fifo_batch; + + return 0; +} + +static void +sio_exit_queue(struct elevator_queue *e) +{ + struct sio_data *sd = e->elevator_data; + + BUG_ON(!list_empty(&sd->fifo_list[SYNC][READ])); + BUG_ON(!list_empty(&sd->fifo_list[SYNC][WRITE])); + BUG_ON(!list_empty(&sd->fifo_list[ASYNC][READ])); + BUG_ON(!list_empty(&sd->fifo_list[ASYNC][WRITE])); + + /* Free structure */ + kfree(sd); +} + +/* + * sysfs code + */ + +static ssize_t +sio_var_show(int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +sio_var_store(int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtol(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct sio_data *sd = e->elevator_data; \ + int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return sio_var_show(__data, (page)); \ +} +SHOW_FUNCTION(sio_sync_read_expire_show, sd->fifo_expire[SYNC][READ], 1); +SHOW_FUNCTION(sio_sync_write_expire_show, sd->fifo_expire[SYNC][WRITE], 1); +SHOW_FUNCTION(sio_async_read_expire_show, sd->fifo_expire[ASYNC][READ], 1); +SHOW_FUNCTION(sio_async_write_expire_show, sd->fifo_expire[ASYNC][WRITE], 1); +SHOW_FUNCTION(sio_fifo_batch_show, sd->fifo_batch, 0); +SHOW_FUNCTION(sio_writes_starved_show, sd->writes_starved, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct sio_data *sd = e->elevator_data; \ + int __data; \ + int ret = sio_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(sio_sync_read_expire_store, &sd->fifo_expire[SYNC][READ], 0, INT_MAX, 1); +STORE_FUNCTION(sio_sync_write_expire_store, &sd->fifo_expire[SYNC][WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(sio_async_read_expire_store, &sd->fifo_expire[ASYNC][READ], 0, INT_MAX, 1); +STORE_FUNCTION(sio_async_write_expire_store, &sd->fifo_expire[ASYNC][WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(sio_fifo_batch_store, &sd->fifo_batch, 0, INT_MAX, 0); +STORE_FUNCTION(sio_writes_starved_store, &sd->writes_starved, 0, INT_MAX, 0); +#undef STORE_FUNCTION + +#define DD_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, sio_##name##_show, \ + sio_##name##_store) + +static struct elv_fs_entry sio_attrs[] = { + DD_ATTR(sync_read_expire), + DD_ATTR(sync_write_expire), + DD_ATTR(async_read_expire), + DD_ATTR(async_write_expire), + DD_ATTR(fifo_batch), + DD_ATTR(writes_starved), + __ATTR_NULL +}; + +static struct elevator_type iosched_sio = { + .ops = { + .elevator_merge_req_fn = sio_merged_requests, + .elevator_dispatch_fn = sio_dispatch_requests, + .elevator_add_req_fn = sio_add_request, +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) + .elevator_queue_empty_fn = sio_queue_empty, +#endif + .elevator_former_req_fn = sio_former_request, + .elevator_latter_req_fn = sio_latter_request, + .elevator_init_fn = sio_init_queue, + .elevator_exit_fn = sio_exit_queue, + }, + + .elevator_attrs = sio_attrs, + .elevator_name = "sio", + .elevator_owner = THIS_MODULE, +}; + +static int __init sio_init(void) +{ + /* Register elevator */ + elv_register(&iosched_sio); + + return 0; +} + +static void __exit sio_exit(void) +{ + /* Unregister elevator */ + elv_unregister(&iosched_sio); +} + +module_init(sio_init); +module_exit(sio_exit); + +MODULE_AUTHOR("Miguel Boton"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple IO scheduler"); +MODULE_VERSION("0.2"); + From 7b4599dced0d8120c8e4c85358c9d3615f6ec9da Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 21 May 2016 23:37:35 -0400 Subject: [PATCH 016/203] FIOPS: update for linux 3.18 --- block/fiops-iosched.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/block/fiops-iosched.c b/block/fiops-iosched.c index 5aa58da5bb62..a7fcb6fb8f7e 100644 --- a/block/fiops-iosched.c +++ b/block/fiops-iosched.c @@ -501,7 +501,7 @@ static void fiops_insert_request(struct request_queue *q, struct request *rq) static inline void fiops_schedule_dispatch(struct fiops_data *fiopsd) { if (fiopsd->busy_queues) - kblockd_schedule_work(fiopsd->queue, &fiopsd->unplug_work); + kblockd_schedule_work(&fiopsd->unplug_work); } static void fiops_completed_request(struct request_queue *q, struct request *rq) @@ -528,9 +528,7 @@ fiops_find_rq_fmerge(struct fiops_data *fiopsd, struct bio *bio) cic = fiops_cic_lookup(fiopsd, tsk->io_context); if (cic) { - sector_t sector = bio->bi_sector + bio_sectors(bio); - - return elv_rb_find(&cic->sort_list, sector); + return elv_rb_find(&cic->sort_list, bio_end_sector(bio)); } return NULL; From d992dceac631b7c5a6c323c31b678c4038e48578 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 22 May 2016 00:01:35 -0400 Subject: [PATCH 017/203] SIO: update for linux 3.18 --- block/sio-iosched.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/block/sio-iosched.c b/block/sio-iosched.c index 31bf114d084c..a2f8249c7ed7 100644 --- a/block/sio-iosched.c +++ b/block/sio-iosched.c @@ -58,9 +58,9 @@ sio_merged_requests(struct request_queue *q, struct request *rq, * and move into next position (next will be deleted) in fifo. */ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { - if (time_before(rq_fifo_time(next), rq_fifo_time(rq))) { + if (time_before(next->fifo_time, rq->fifo_time)) { list_move(&rq->queuelist, &next->queuelist); - rq_set_fifo_time(rq, rq_fifo_time(next)); + rq->fifo_time = next->fifo_time; } } @@ -79,7 +79,7 @@ sio_add_request(struct request_queue *q, struct request *rq) * Add request to the proper fifo list and set its * expire time. */ - rq_set_fifo_time(rq, jiffies + sd->fifo_expire[sync][data_dir]); + rq->fifo_time = jiffies + sd->fifo_expire[sync][data_dir]; list_add_tail(&rq->queuelist, &sd->fifo_list[sync][data_dir]); } @@ -108,7 +108,7 @@ sio_expired_request(struct sio_data *sd, int sync, int data_dir) rq = rq_entry_fifo(list->next); /* Request has expired */ - if (time_after(jiffies, rq_fifo_time(rq))) + if (time_after(jiffies, rq->fifo_time)) return rq; return NULL; From 58b8403279057df98851d92dd28a2df10bc5e868 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Sat, 6 Jun 2015 17:56:31 +0200 Subject: [PATCH 018/203] block: cgroups, kconfig, build bits for BFQ-v7r8-3.18.0 Update Kconfig.iosched and do the related Makefile changes to include kernel configuration options for BFQ. Also add the bfqio controller to the cgroups subsystem. Signed-off-by: Paolo Valente Signed-off-by: Arianna Avanzini --- block/Kconfig.iosched | 32 ++++++++++++++++++++++++++++++++ block/Makefile | 1 + include/linux/cgroup_subsys.h | 4 ++++ 3 files changed, 37 insertions(+) diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 4072cb252ce6..3437270ec213 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -68,6 +68,27 @@ config CFQ_GROUP_IOSCHED ---help--- Enable group IO scheduling in CFQ. +config IOSCHED_BFQ + tristate "BFQ I/O scheduler" + default n + ---help--- + The BFQ I/O scheduler tries to distribute bandwidth among + all processes according to their weights. + It aims at distributing the bandwidth as desired, independently of + the disk parameters and with any workload. It also tries to + guarantee low latency to interactive and soft real-time + applications. If compiled built-in (saying Y here), BFQ can + be configured to support hierarchical scheduling. + +config CGROUP_BFQIO + bool "BFQ hierarchical scheduling support" + depends on CGROUPS && IOSCHED_BFQ=y + default n + ---help--- + Enable hierarchical scheduling in BFQ, using the cgroups + filesystem interface. The name of the subsystem will be + bfqio. + choice prompt "Default I/O scheduler" default DEFAULT_CFQ @@ -81,6 +102,16 @@ choice config DEFAULT_CFQ bool "CFQ" if IOSCHED_CFQ=y + config DEFAULT_BFQ + bool "BFQ" if IOSCHED_BFQ=y + help + Selects BFQ as the default I/O scheduler which will be + used by default for all block devices. + The BFQ I/O scheduler aims at distributing the bandwidth + as desired, independently of the disk parameters and with + any workload. It also tries to guarantee low latency to + interactive and soft real-time applications. + config DEFAULT_NOOP bool "No-op" @@ -96,6 +127,7 @@ config DEFAULT_IOSCHED string default "deadline" if DEFAULT_DEADLINE default "cfq" if DEFAULT_CFQ + default "bfq" if DEFAULT_BFQ default "noop" if DEFAULT_NOOP default "fiops" if DEFAULT_FIOPS default "sio" if DEFAULT_SIO diff --git a/block/Makefile b/block/Makefile index 985b857c2c7f..dda63b1e3252 100644 --- a/block/Makefile +++ b/block/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o obj-$(CONFIG_IOSCHED_FIOPS) += fiops-iosched.o obj-$(CONFIG_IOSCHED_SIO) += sio-iosched.o +obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 98c4f9b12b03..13b010db223b 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -35,6 +35,10 @@ SUBSYS(net_cls) SUBSYS(blkio) #endif +#if IS_ENABLED(CONFIG_CGROUP_BFQIO) +SUBSYS(bfqio) +#endif + #if IS_ENABLED(CONFIG_CGROUP_PERF) SUBSYS(perf_event) #endif From 6dedcec519137ebbb2a5f36d35f4fb7f1b660120 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Thu, 9 May 2013 19:10:02 +0200 Subject: [PATCH 019/203] block: introduce the BFQ-v7r8 I/O sched for 3.18.0 Add the BFQ-v7r8 I/O scheduler to 3.18.0. The general structure is borrowed from CFQ, as much of the code for handling I/O contexts. Over time, several useful features have been ported from CFQ as well (details in the changelog in README.BFQ). A (bfq_)queue is associated to each task doing I/O on a device, and each time a scheduling decision has to be made a queue is selected and served until it expires. - Slices are given in the service domain: tasks are assigned budgets, measured in number of sectors. Once got the disk, a task must however consume its assigned budget within a configurable maximum time (by default, the maximum possible value of the budgets is automatically computed to comply with this timeout). This allows the desired latency vs "throughput boosting" tradeoff to be set. - Budgets are scheduled according to a variant of WF2Q+, implemented using an augmented rb-tree to take eligibility into account while preserving an O(log N) overall complexity. - A low-latency tunable is provided; if enabled, both interactive and soft real-time applications are guaranteed a very low latency. - Latency guarantees are preserved also in the presence of NCQ. - Also with flash-based devices, a high throughput is achieved while still preserving latency guarantees. - BFQ features Early Queue Merge (EQM), a sort of fusion of the cooperating-queue-merging and the preemption mechanisms present in CFQ. EQM is in fact a unified mechanism that tries to get a sequential read pattern, and hence a high throughput, with any set of processes performing interleaved I/O over a contiguous sequence of sectors. - BFQ supports full hierarchical scheduling, exporting a cgroups interface. Since each node has a full scheduler, each group can be assigned its own weight. - If the cgroups interface is not used, only I/O priorities can be assigned to processes, with ioprio values mapped to weights with the relation weight = IOPRIO_BE_NR - ioprio. - ioprio classes are served in strict priority order, i.e., lower priority queues are not served as long as there are higher priority queues. Among queues in the same class the bandwidth is distributed in proportion to the weight of each queue. A very thin extra bandwidth is however guaranteed to the Idle class, to prevent it from starving. Signed-off-by: Paolo Valente Signed-off-by: Arianna Avanzini --- block/bfq-cgroup.c | 936 +++++++++++ block/bfq-ioc.c | 36 + block/bfq-iosched.c | 3898 +++++++++++++++++++++++++++++++++++++++++++ block/bfq-sched.c | 1208 ++++++++++++++ block/bfq.h | 771 +++++++++ 5 files changed, 6849 insertions(+) create mode 100644 block/bfq-cgroup.c create mode 100644 block/bfq-ioc.c create mode 100644 block/bfq-iosched.c create mode 100644 block/bfq-sched.c create mode 100644 block/bfq.h diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c new file mode 100644 index 000000000000..11e2f1d4e73c --- /dev/null +++ b/block/bfq-cgroup.c @@ -0,0 +1,936 @@ +/* + * BFQ: CGROUPS support. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + * + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ + * file. + */ + +#ifdef CONFIG_CGROUP_BFQIO + +static DEFINE_MUTEX(bfqio_mutex); + +static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) +{ + return bgrp ? !bgrp->online : false; +} + +static struct bfqio_cgroup bfqio_root_cgroup = { + .weight = BFQ_DEFAULT_GRP_WEIGHT, + .ioprio = BFQ_DEFAULT_GRP_IOPRIO, + .ioprio_class = BFQ_DEFAULT_GRP_CLASS, +}; + +static inline void bfq_init_entity(struct bfq_entity *entity, + struct bfq_group *bfqg) +{ + entity->weight = entity->new_weight; + entity->orig_weight = entity->new_weight; + entity->ioprio = entity->new_ioprio; + entity->ioprio_class = entity->new_ioprio_class; + entity->parent = bfqg->my_entity; + entity->sched_data = &bfqg->sched_data; +} + +static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) +{ + return css ? container_of(css, struct bfqio_cgroup, css) : NULL; +} + +/* + * Search the bfq_group for bfqd into the hash table (by now only a list) + * of bgrp. Must be called under rcu_read_lock(). + */ +static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, + struct bfq_data *bfqd) +{ + struct bfq_group *bfqg; + void *key; + + hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { + key = rcu_dereference(bfqg->bfqd); + if (key == bfqd) + return bfqg; + } + + return NULL; +} + +static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, + struct bfq_group *bfqg) +{ + struct bfq_entity *entity = &bfqg->entity; + + /* + * If the weight of the entity has never been set via the sysfs + * interface, then bgrp->weight == 0. In this case we initialize + * the weight from the current ioprio value. Otherwise, the group + * weight, if set, has priority over the ioprio value. + */ + if (bgrp->weight == 0) { + entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); + entity->new_ioprio = bgrp->ioprio; + } else { + if (bgrp->weight < BFQ_MIN_WEIGHT || + bgrp->weight > BFQ_MAX_WEIGHT) { + printk(KERN_CRIT "bfq_group_init_entity: " + "bgrp->weight %d\n", bgrp->weight); + BUG(); + } + entity->new_weight = bgrp->weight; + entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); + } + entity->orig_weight = entity->weight = entity->new_weight; + entity->ioprio = entity->new_ioprio; + entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; + entity->my_sched_data = &bfqg->sched_data; + bfqg->active_entities = 0; +} + +static inline void bfq_group_set_parent(struct bfq_group *bfqg, + struct bfq_group *parent) +{ + struct bfq_entity *entity; + + BUG_ON(parent == NULL); + BUG_ON(bfqg == NULL); + + entity = &bfqg->entity; + entity->parent = parent->my_entity; + entity->sched_data = &parent->sched_data; +} + +/** + * bfq_group_chain_alloc - allocate a chain of groups. + * @bfqd: queue descriptor. + * @css: the leaf cgroup_subsys_state this chain starts from. + * + * Allocate a chain of groups starting from the one belonging to + * @cgroup up to the root cgroup. Stop if a cgroup on the chain + * to the root has already an allocated group on @bfqd. + */ +static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, + struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp; + struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; + + for (; css != NULL; css = css->parent) { + bgrp = css_to_bfqio(css); + + bfqg = bfqio_lookup_group(bgrp, bfqd); + if (bfqg != NULL) { + /* + * All the cgroups in the path from there to the + * root must have a bfq_group for bfqd, so we don't + * need any more allocations. + */ + break; + } + + bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); + if (bfqg == NULL) + goto cleanup; + + bfq_group_init_entity(bgrp, bfqg); + bfqg->my_entity = &bfqg->entity; + + if (leaf == NULL) { + leaf = bfqg; + prev = leaf; + } else { + bfq_group_set_parent(prev, bfqg); + /* + * Build a list of allocated nodes using the bfqd + * filed, that is still unused and will be + * initialized only after the node will be + * connected. + */ + prev->bfqd = bfqg; + prev = bfqg; + } + } + + return leaf; + +cleanup: + while (leaf != NULL) { + prev = leaf; + leaf = leaf->bfqd; + kfree(prev); + } + + return NULL; +} + +/** + * bfq_group_chain_link - link an allocated group chain to a cgroup + * hierarchy. + * @bfqd: the queue descriptor. + * @css: the leaf cgroup_subsys_state to start from. + * @leaf: the leaf group (to be associated to @cgroup). + * + * Try to link a chain of groups to a cgroup hierarchy, connecting the + * nodes bottom-up, so we can be sure that when we find a cgroup in the + * hierarchy that already as a group associated to @bfqd all the nodes + * in the path to the root cgroup have one too. + * + * On locking: the queue lock protects the hierarchy (there is a hierarchy + * per device) while the bfqio_cgroup lock protects the list of groups + * belonging to the same cgroup. + */ +static void bfq_group_chain_link(struct bfq_data *bfqd, + struct cgroup_subsys_state *css, + struct bfq_group *leaf) +{ + struct bfqio_cgroup *bgrp; + struct bfq_group *bfqg, *next, *prev = NULL; + unsigned long flags; + + assert_spin_locked(bfqd->queue->queue_lock); + + for (; css != NULL && leaf != NULL; css = css->parent) { + bgrp = css_to_bfqio(css); + next = leaf->bfqd; + + bfqg = bfqio_lookup_group(bgrp, bfqd); + BUG_ON(bfqg != NULL); + + spin_lock_irqsave(&bgrp->lock, flags); + + rcu_assign_pointer(leaf->bfqd, bfqd); + hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); + hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); + + spin_unlock_irqrestore(&bgrp->lock, flags); + + prev = leaf; + leaf = next; + } + + BUG_ON(css == NULL && leaf != NULL); + if (css != NULL && prev != NULL) { + bgrp = css_to_bfqio(css); + bfqg = bfqio_lookup_group(bgrp, bfqd); + bfq_group_set_parent(prev, bfqg); + } +} + +/** + * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. + * @bfqd: queue descriptor. + * @cgroup: cgroup being searched for. + * + * Return a group associated to @bfqd in @cgroup, allocating one if + * necessary. When a group is returned all the cgroups in the path + * to the root have a group associated to @bfqd. + * + * If the allocation fails, return the root group: this breaks guarantees + * but is a safe fallback. If this loss becomes a problem it can be + * mitigated using the equivalent weight (given by the product of the + * weights of the groups in the path from @group to the root) in the + * root scheduler. + * + * We allocate all the missing nodes in the path from the leaf cgroup + * to the root and we connect the nodes only after all the allocations + * have been successful. + */ +static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, + struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + struct bfq_group *bfqg; + + bfqg = bfqio_lookup_group(bgrp, bfqd); + if (bfqg != NULL) + return bfqg; + + bfqg = bfq_group_chain_alloc(bfqd, css); + if (bfqg != NULL) + bfq_group_chain_link(bfqd, css, bfqg); + else + bfqg = bfqd->root_group; + + return bfqg; +} + +/** + * bfq_bfqq_move - migrate @bfqq to @bfqg. + * @bfqd: queue descriptor. + * @bfqq: the queue to move. + * @entity: @bfqq's entity. + * @bfqg: the group to move to. + * + * Move @bfqq to @bfqg, deactivating it from its old group and reactivating + * it on the new one. Avoid putting the entity on the old group idle tree. + * + * Must be called under the queue lock; the cgroup owning @bfqg must + * not disappear (by now this just means that we are called under + * rcu_read_lock()). + */ +static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct bfq_entity *entity, struct bfq_group *bfqg) +{ + int busy, resume; + + busy = bfq_bfqq_busy(bfqq); + resume = !RB_EMPTY_ROOT(&bfqq->sort_list); + + BUG_ON(resume && !entity->on_st); + BUG_ON(busy && !resume && entity->on_st && + bfqq != bfqd->in_service_queue); + + if (busy) { + BUG_ON(atomic_read(&bfqq->ref) < 2); + + if (!resume) + bfq_del_bfqq_busy(bfqd, bfqq, 0); + else + bfq_deactivate_bfqq(bfqd, bfqq, 0); + } else if (entity->on_st) + bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); + + /* + * Here we use a reference to bfqg. We don't need a refcounter + * as the cgroup reference will not be dropped, so that its + * destroy() callback will not be invoked. + */ + entity->parent = bfqg->my_entity; + entity->sched_data = &bfqg->sched_data; + + if (busy && resume) + bfq_activate_bfqq(bfqd, bfqq); + + if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) + bfq_schedule_dispatch(bfqd); +} + +/** + * __bfq_bic_change_cgroup - move @bic to @cgroup. + * @bfqd: the queue descriptor. + * @bic: the bic to move. + * @cgroup: the cgroup to move to. + * + * Move bic to cgroup, assuming that bfqd->queue is locked; the caller + * has to make sure that the reference to cgroup is valid across the call. + * + * NOTE: an alternative approach might have been to store the current + * cgroup in bfqq and getting a reference to it, reducing the lookup + * time here, at the price of slightly more complex code. + */ +static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, + struct bfq_io_cq *bic, + struct cgroup_subsys_state *css) +{ + struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); + struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); + struct bfq_entity *entity; + struct bfq_group *bfqg; + struct bfqio_cgroup *bgrp; + + bgrp = css_to_bfqio(css); + + bfqg = bfq_find_alloc_group(bfqd, css); + if (async_bfqq != NULL) { + entity = &async_bfqq->entity; + + if (entity->sched_data != &bfqg->sched_data) { + bic_set_bfqq(bic, NULL, 0); + bfq_log_bfqq(bfqd, async_bfqq, + "bic_change_group: %p %d", + async_bfqq, atomic_read(&async_bfqq->ref)); + bfq_put_queue(async_bfqq); + } + } + + if (sync_bfqq != NULL) { + entity = &sync_bfqq->entity; + if (entity->sched_data != &bfqg->sched_data) + bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); + } + + return bfqg; +} + +/** + * bfq_bic_change_cgroup - move @bic to @cgroup. + * @bic: the bic being migrated. + * @cgroup: the destination cgroup. + * + * When the task owning @bic is moved to @cgroup, @bic is immediately + * moved into its new parent group. + */ +static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, + struct cgroup_subsys_state *css) +{ + struct bfq_data *bfqd; + unsigned long uninitialized_var(flags); + + bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), + &flags); + if (bfqd != NULL) { + __bfq_bic_change_cgroup(bfqd, bic, css); + bfq_put_bfqd_unlock(bfqd, &flags); + } +} + +/** + * bfq_bic_update_cgroup - update the cgroup of @bic. + * @bic: the @bic to update. + * + * Make sure that @bic is enqueued in the cgroup of the current task. + * We need this in addition to moving bics during the cgroup attach + * phase because the task owning @bic could be at its first disk + * access or we may end up in the root cgroup as the result of a + * memory allocation failure and here we try to move to the right + * group. + * + * Must be called under the queue lock. It is safe to use the returned + * value even after the rcu_read_unlock() as the migration/destruction + * paths act under the queue lock too. IOW it is impossible to race with + * group migration/destruction and end up with an invalid group as: + * a) here cgroup has not yet been destroyed, nor its destroy callback + * has started execution, as current holds a reference to it, + * b) if it is destroyed after rcu_read_unlock() [after current is + * migrated to a different cgroup] its attach() callback will have + * taken care of remove all the references to the old cgroup data. + */ +static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) +{ + struct bfq_data *bfqd = bic_to_bfqd(bic); + struct bfq_group *bfqg; + struct cgroup_subsys_state *css; + + BUG_ON(bfqd == NULL); + + rcu_read_lock(); + css = task_css(current, bfqio_cgrp_id); + bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); + rcu_read_unlock(); + + return bfqg; +} + +/** + * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. + * @st: the service tree being flushed. + */ +static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) +{ + struct bfq_entity *entity = st->first_idle; + + for (; entity != NULL; entity = st->first_idle) + __bfq_deactivate_entity(entity, 0); +} + +/** + * bfq_reparent_leaf_entity - move leaf entity to the root_group. + * @bfqd: the device data structure with the root group. + * @entity: the entity to move. + */ +static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + + BUG_ON(bfqq == NULL); + bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); + return; +} + +/** + * bfq_reparent_active_entities - move to the root group all active + * entities. + * @bfqd: the device data structure with the root group. + * @bfqg: the group to move from. + * @st: the service tree with the entities. + * + * Needs queue_lock to be taken and reference to be valid over the call. + */ +static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, + struct bfq_group *bfqg, + struct bfq_service_tree *st) +{ + struct rb_root *active = &st->active; + struct bfq_entity *entity = NULL; + + if (!RB_EMPTY_ROOT(&st->active)) + entity = bfq_entity_of(rb_first(active)); + + for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) + bfq_reparent_leaf_entity(bfqd, entity); + + if (bfqg->sched_data.in_service_entity != NULL) + bfq_reparent_leaf_entity(bfqd, + bfqg->sched_data.in_service_entity); + + return; +} + +/** + * bfq_destroy_group - destroy @bfqg. + * @bgrp: the bfqio_cgroup containing @bfqg. + * @bfqg: the group being destroyed. + * + * Destroy @bfqg, making sure that it is not referenced from its parent. + */ +static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) +{ + struct bfq_data *bfqd; + struct bfq_service_tree *st; + struct bfq_entity *entity = bfqg->my_entity; + unsigned long uninitialized_var(flags); + int i; + + hlist_del(&bfqg->group_node); + + /* + * Empty all service_trees belonging to this group before + * deactivating the group itself. + */ + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { + st = bfqg->sched_data.service_tree + i; + + /* + * The idle tree may still contain bfq_queues belonging + * to exited task because they never migrated to a different + * cgroup from the one being destroyed now. No one else + * can access them so it's safe to act without any lock. + */ + bfq_flush_idle_tree(st); + + /* + * It may happen that some queues are still active + * (busy) upon group destruction (if the corresponding + * processes have been forced to terminate). We move + * all the leaf entities corresponding to these queues + * to the root_group. + * Also, it may happen that the group has an entity + * in service, which is disconnected from the active + * tree: it must be moved, too. + * There is no need to put the sync queues, as the + * scheduler has taken no reference. + */ + bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); + if (bfqd != NULL) { + bfq_reparent_active_entities(bfqd, bfqg, st); + bfq_put_bfqd_unlock(bfqd, &flags); + } + BUG_ON(!RB_EMPTY_ROOT(&st->active)); + BUG_ON(!RB_EMPTY_ROOT(&st->idle)); + } + BUG_ON(bfqg->sched_data.next_in_service != NULL); + BUG_ON(bfqg->sched_data.in_service_entity != NULL); + + /* + * We may race with device destruction, take extra care when + * dereferencing bfqg->bfqd. + */ + bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); + if (bfqd != NULL) { + hlist_del(&bfqg->bfqd_node); + __bfq_deactivate_entity(entity, 0); + bfq_put_async_queues(bfqd, bfqg); + bfq_put_bfqd_unlock(bfqd, &flags); + } + BUG_ON(entity->tree != NULL); + + /* + * No need to defer the kfree() to the end of the RCU grace + * period: we are called from the destroy() callback of our + * cgroup, so we can be sure that no one is a) still using + * this cgroup or b) doing lookups in it. + */ + kfree(bfqg); +} + +static void bfq_end_wr_async(struct bfq_data *bfqd) +{ + struct hlist_node *tmp; + struct bfq_group *bfqg; + + hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) + bfq_end_wr_async_queues(bfqd, bfqg); + bfq_end_wr_async_queues(bfqd, bfqd->root_group); +} + +/** + * bfq_disconnect_groups - disconnect @bfqd from all its groups. + * @bfqd: the device descriptor being exited. + * + * When the device exits we just make sure that no lookup can return + * the now unused group structures. They will be deallocated on cgroup + * destruction. + */ +static void bfq_disconnect_groups(struct bfq_data *bfqd) +{ + struct hlist_node *tmp; + struct bfq_group *bfqg; + + bfq_log(bfqd, "disconnect_groups beginning"); + hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { + hlist_del(&bfqg->bfqd_node); + + __bfq_deactivate_entity(bfqg->my_entity, 0); + + /* + * Don't remove from the group hash, just set an + * invalid key. No lookups can race with the + * assignment as bfqd is being destroyed; this + * implies also that new elements cannot be added + * to the list. + */ + rcu_assign_pointer(bfqg->bfqd, NULL); + + bfq_log(bfqd, "disconnect_groups: put async for group %p", + bfqg); + bfq_put_async_queues(bfqd, bfqg); + } +} + +static inline void bfq_free_root_group(struct bfq_data *bfqd) +{ + struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; + struct bfq_group *bfqg = bfqd->root_group; + + bfq_put_async_queues(bfqd, bfqg); + + spin_lock_irq(&bgrp->lock); + hlist_del_rcu(&bfqg->group_node); + spin_unlock_irq(&bgrp->lock); + + /* + * No need to synchronize_rcu() here: since the device is gone + * there cannot be any read-side access to its root_group. + */ + kfree(bfqg); +} + +static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) +{ + struct bfq_group *bfqg; + struct bfqio_cgroup *bgrp; + int i; + + bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); + if (bfqg == NULL) + return NULL; + + bfqg->entity.parent = NULL; + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) + bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; + + bgrp = &bfqio_root_cgroup; + spin_lock_irq(&bgrp->lock); + rcu_assign_pointer(bfqg->bfqd, bfqd); + hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); + spin_unlock_irq(&bgrp->lock); + + return bfqg; +} + +#define SHOW_FUNCTION(__VAR) \ +static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ + struct cftype *cftype) \ +{ \ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ + u64 ret = -ENODEV; \ + \ + mutex_lock(&bfqio_mutex); \ + if (bfqio_is_removed(bgrp)) \ + goto out_unlock; \ + \ + spin_lock_irq(&bgrp->lock); \ + ret = bgrp->__VAR; \ + spin_unlock_irq(&bgrp->lock); \ + \ +out_unlock: \ + mutex_unlock(&bfqio_mutex); \ + return ret; \ +} + +SHOW_FUNCTION(weight); +SHOW_FUNCTION(ioprio); +SHOW_FUNCTION(ioprio_class); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ +static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ + struct cftype *cftype, \ + u64 val) \ +{ \ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ + struct bfq_group *bfqg; \ + int ret = -EINVAL; \ + \ + if (val < (__MIN) || val > (__MAX)) \ + return ret; \ + \ + ret = -ENODEV; \ + mutex_lock(&bfqio_mutex); \ + if (bfqio_is_removed(bgrp)) \ + goto out_unlock; \ + ret = 0; \ + \ + spin_lock_irq(&bgrp->lock); \ + bgrp->__VAR = (unsigned short)val; \ + hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ + /* \ + * Setting the ioprio_changed flag of the entity \ + * to 1 with new_##__VAR == ##__VAR would re-set \ + * the value of the weight to its ioprio mapping. \ + * Set the flag only if necessary. \ + */ \ + if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ + bfqg->entity.new_##__VAR = (unsigned short)val; \ + /* \ + * Make sure that the above new value has been \ + * stored in bfqg->entity.new_##__VAR before \ + * setting the ioprio_changed flag. In fact, \ + * this flag may be read asynchronously (in \ + * critical sections protected by a different \ + * lock than that held here), and finding this \ + * flag set may cause the execution of the code \ + * for updating parameters whose value may \ + * depend also on bfqg->entity.new_##__VAR (in \ + * __bfq_entity_update_weight_prio). \ + * This barrier makes sure that the new value \ + * of bfqg->entity.new_##__VAR is correctly \ + * seen in that code. \ + */ \ + smp_wmb(); \ + bfqg->entity.ioprio_changed = 1; \ + } \ + } \ + spin_unlock_irq(&bgrp->lock); \ + \ +out_unlock: \ + mutex_unlock(&bfqio_mutex); \ + return ret; \ +} + +STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); +STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); +STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); +#undef STORE_FUNCTION + +static struct cftype bfqio_files[] = { + { + .name = "weight", + .read_u64 = bfqio_cgroup_weight_read, + .write_u64 = bfqio_cgroup_weight_write, + }, + { + .name = "ioprio", + .read_u64 = bfqio_cgroup_ioprio_read, + .write_u64 = bfqio_cgroup_ioprio_write, + }, + { + .name = "ioprio_class", + .read_u64 = bfqio_cgroup_ioprio_class_read, + .write_u64 = bfqio_cgroup_ioprio_class_write, + }, + { }, /* terminate */ +}; + +static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state + *parent_css) +{ + struct bfqio_cgroup *bgrp; + + if (parent_css != NULL) { + bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); + if (bgrp == NULL) + return ERR_PTR(-ENOMEM); + } else + bgrp = &bfqio_root_cgroup; + + spin_lock_init(&bgrp->lock); + INIT_HLIST_HEAD(&bgrp->group_data); + bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; + bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; + + return &bgrp->css; +} + +/* + * We cannot support shared io contexts, as we have no means to support + * two tasks with the same ioc in two different groups without major rework + * of the main bic/bfqq data structures. By now we allow a task to change + * its cgroup only if it's the only owner of its ioc; the drawback of this + * behavior is that a group containing a task that forked using CLONE_IO + * will not be destroyed until the tasks sharing the ioc die. + */ +static int bfqio_can_attach(struct cgroup_subsys_state *css, + struct cgroup_taskset *tset) +{ + struct task_struct *task; + struct io_context *ioc; + int ret = 0; + + cgroup_taskset_for_each(task, tset) { + /* + * task_lock() is needed to avoid races with + * exit_io_context() + */ + task_lock(task); + ioc = task->io_context; + if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) + /* + * ioc == NULL means that the task is either too + * young or exiting: if it has still no ioc the + * ioc can't be shared, if the task is exiting the + * attach will fail anyway, no matter what we + * return here. + */ + ret = -EINVAL; + task_unlock(task); + if (ret) + break; + } + + return ret; +} + +static void bfqio_attach(struct cgroup_subsys_state *css, + struct cgroup_taskset *tset) +{ + struct task_struct *task; + struct io_context *ioc; + struct io_cq *icq; + + /* + * IMPORTANT NOTE: The move of more than one process at a time to a + * new group has not yet been tested. + */ + cgroup_taskset_for_each(task, tset) { + ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); + if (ioc) { + /* + * Handle cgroup change here. + */ + rcu_read_lock(); + hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) + if (!strncmp( + icq->q->elevator->type->elevator_name, + "bfq", ELV_NAME_MAX)) + bfq_bic_change_cgroup(icq_to_bic(icq), + css); + rcu_read_unlock(); + put_io_context(ioc); + } + } +} + +static void bfqio_destroy(struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + struct hlist_node *tmp; + struct bfq_group *bfqg; + + /* + * Since we are destroying the cgroup, there are no more tasks + * referencing it, and all the RCU grace periods that may have + * referenced it are ended (as the destruction of the parent + * cgroup is RCU-safe); bgrp->group_data will not be accessed by + * anything else and we don't need any synchronization. + */ + hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) + bfq_destroy_group(bgrp, bfqg); + + BUG_ON(!hlist_empty(&bgrp->group_data)); + + kfree(bgrp); +} + +static int bfqio_css_online(struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + + mutex_lock(&bfqio_mutex); + bgrp->online = true; + mutex_unlock(&bfqio_mutex); + + return 0; +} + +static void bfqio_css_offline(struct cgroup_subsys_state *css) +{ + struct bfqio_cgroup *bgrp = css_to_bfqio(css); + + mutex_lock(&bfqio_mutex); + bgrp->online = false; + mutex_unlock(&bfqio_mutex); +} + +struct cgroup_subsys bfqio_cgrp_subsys = { + .css_alloc = bfqio_create, + .css_online = bfqio_css_online, + .css_offline = bfqio_css_offline, + .can_attach = bfqio_can_attach, + .attach = bfqio_attach, + .css_free = bfqio_destroy, + .legacy_cftypes = bfqio_files, +}; +#else +static inline void bfq_init_entity(struct bfq_entity *entity, + struct bfq_group *bfqg) +{ + entity->weight = entity->new_weight; + entity->orig_weight = entity->new_weight; + entity->ioprio = entity->new_ioprio; + entity->ioprio_class = entity->new_ioprio_class; + entity->sched_data = &bfqg->sched_data; +} + +static inline struct bfq_group * +bfq_bic_update_cgroup(struct bfq_io_cq *bic) +{ + struct bfq_data *bfqd = bic_to_bfqd(bic); + return bfqd->root_group; +} + +static inline void bfq_bfqq_move(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct bfq_entity *entity, + struct bfq_group *bfqg) +{ +} + +static void bfq_end_wr_async(struct bfq_data *bfqd) +{ + bfq_end_wr_async_queues(bfqd, bfqd->root_group); +} + +static inline void bfq_disconnect_groups(struct bfq_data *bfqd) +{ + bfq_put_async_queues(bfqd, bfqd->root_group); +} + +static inline void bfq_free_root_group(struct bfq_data *bfqd) +{ + kfree(bfqd->root_group); +} + +static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) +{ + struct bfq_group *bfqg; + int i; + + bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); + if (bfqg == NULL) + return NULL; + + for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) + bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; + + return bfqg; +} +#endif diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c new file mode 100644 index 000000000000..7f6b0004ca70 --- /dev/null +++ b/block/bfq-ioc.c @@ -0,0 +1,36 @@ +/* + * BFQ: I/O context handling. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + */ + +/** + * icq_to_bic - convert iocontext queue structure to bfq_io_cq. + * @icq: the iocontext queue. + */ +static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) +{ + /* bic->icq is the first member, %NULL will convert to %NULL */ + return container_of(icq, struct bfq_io_cq, icq); +} + +/** + * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. + * @bfqd: the lookup key. + * @ioc: the io_context of the process doing I/O. + * + * Queue lock must be held. + */ +static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, + struct io_context *ioc) +{ + if (ioc) + return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); + return NULL; +} diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c new file mode 100644 index 000000000000..773b2ee064b2 --- /dev/null +++ b/block/bfq-iosched.c @@ -0,0 +1,3898 @@ +/* + * Budget Fair Queueing (BFQ) disk scheduler. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + * + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ + * file. + * + * BFQ is a proportional-share storage-I/O scheduling algorithm based on + * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, + * measured in number of sectors, to processes instead of time slices. The + * device is not granted to the in-service process for a given time slice, + * but until it has exhausted its assigned budget. This change from the time + * to the service domain allows BFQ to distribute the device throughput + * among processes as desired, without any distortion due to ZBR, workload + * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, + * called B-WF2Q+, to schedule processes according to their budgets. More + * precisely, BFQ schedules queues associated to processes. Thanks to the + * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to + * I/O-bound processes issuing sequential requests (to boost the + * throughput), and yet guarantee a low latency to interactive and soft + * real-time applications. + * + * BFQ is described in [1], where also a reference to the initial, more + * theoretical paper on BFQ can be found. The interested reader can find + * in the latter paper full details on the main algorithm, as well as + * formulas of the guarantees and formal proofs of all the properties. + * With respect to the version of BFQ presented in these papers, this + * implementation adds a few more heuristics, such as the one that + * guarantees a low latency to soft real-time applications, and a + * hierarchical extension based on H-WF2Q+. + * + * B-WF2Q+ is based on WF2Q+, that is described in [2], together with + * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) + * complexity derives from the one introduced with EEVDF in [3]. + * + * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness + * with the BFQ Disk I/O Scheduler'', + * Proceedings of the 5th Annual International Systems and Storage + * Conference (SYSTOR '12), June 2012. + * + * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf + * + * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing + * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, + * Oct 1997. + * + * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz + * + * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline + * First: A Flexible and Accurate Mechanism for Proportional Share + * Resource Allocation,'' technical report. + * + * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "bfq.h" +#include "blk.h" + +/* Expiration time of sync (0) and async (1) requests, in jiffies. */ +static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; + +/* Maximum backwards seek, in KiB. */ +static const int bfq_back_max = 16 * 1024; + +/* Penalty of a backwards seek, in number of sectors. */ +static const int bfq_back_penalty = 2; + +/* Idling period duration, in jiffies. */ +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; +static const int bfq_max_budget_async_rq = 4; + +/* + * Async to sync throughput distribution is controlled as follows: + * when an async request is served, the entity is charged the number + * of sectors of the request, multiplied by the factor below + */ +static const int bfq_async_charge_factor = 10; + +/* Default timeout values, in jiffies, approximating CFQ defaults. */ +static const int bfq_timeout_sync = HZ / 8; +static int bfq_timeout_async = HZ / 25; + +struct kmem_cache *bfq_pool; + +/* Below this threshold (in ms), we consider thinktime immediate. */ +#define BFQ_MIN_TT 2 + +/* hw_tag detection: parallel requests threshold and min samples needed. */ +#define BFQ_HW_QUEUE_THRESHOLD 4 +#define BFQ_HW_QUEUE_SAMPLES 32 + +#define BFQQ_SEEK_THR (sector_t)(8 * 1024) +#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) + +/* Min samples used for peak rate estimation (for autotuning). */ +#define BFQ_PEAK_RATE_SAMPLES 32 + +/* Shift used for peak rate fixed precision calculations. */ +#define BFQ_RATE_SHIFT 16 + +/* + * By default, BFQ computes the duration of the weight raising for + * interactive applications automatically, using the following formula: + * duration = (R / r) * T, where r is the peak rate of the device, and + * R and T are two reference parameters. + * In particular, R is the peak rate of the reference device (see below), + * and T is a reference time: given the systems that are likely to be + * installed on the reference device according to its speed class, T is + * about the maximum time needed, under BFQ and while reading two files in + * parallel, to load typical large applications on these systems. + * In practice, the slower/faster the device at hand is, the more/less it + * takes to load applications with respect to the reference device. + * Accordingly, the longer/shorter BFQ grants weight raising to interactive + * applications. + * + * BFQ uses four different reference pairs (R, T), depending on: + * . whether the device is rotational or non-rotational; + * . whether the device is slow, such as old or portable HDDs, as well as + * SD cards, or fast, such as newer HDDs and SSDs. + * + * The device's speed class is dynamically (re)detected in + * bfq_update_peak_rate() every time the estimated peak rate is updated. + * + * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] + * are the reference values for a slow/fast rotational device, whereas + * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for + * a slow/fast non-rotational device. Finally, device_speed_thresh are the + * thresholds used to switch between speed classes. + * Both the reference peak rates and the thresholds are measured in + * sectors/usec, left-shifted by BFQ_RATE_SHIFT. + */ +static int R_slow[2] = {1536, 10752}; +static int R_fast[2] = {17415, 34791}; +/* + * To improve readability, a conversion function is used to initialize the + * following arrays, which entails that they can be initialized only in a + * function. + */ +static int T_slow[2]; +static int T_fast[2]; +static int device_speed_thresh[2]; + +#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ + { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) + +#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) +#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) + +static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); + +#include "bfq-ioc.c" +#include "bfq-sched.c" +#include "bfq-cgroup.c" + +#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ + IOPRIO_CLASS_IDLE) +#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ + IOPRIO_CLASS_RT) + +#define bfq_sample_valid(samples) ((samples) > 80) + +/* + * The following macro groups conditions that need to be evaluated when + * checking if existing queues and groups form a symmetric scenario + * and therefore idling can be reduced or disabled for some of the + * queues. See the comment to the function bfq_bfqq_must_not_expire() + * for further details. + */ +#ifdef CONFIG_CGROUP_BFQIO +#define symmetric_scenario (!bfqd->active_numerous_groups && \ + !bfq_differentiated_weights(bfqd)) +#else +#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) +#endif + +/* + * We regard a request as SYNC, if either it's a read or has the SYNC bit + * set (in which case it could also be a direct WRITE). + */ +static inline int bfq_bio_sync(struct bio *bio) +{ + if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) + return 1; + + return 0; +} + +/* + * Scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing. + */ +static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) +{ + if (bfqd->queued != 0) { + bfq_log(bfqd, "schedule dispatch"); + kblockd_schedule_work(&bfqd->unplug_work); + } +} + +/* + * Lifted from AS - choose which of rq1 and rq2 that is best served now. + * We choose the request that is closesr to the head right now. Distance + * behind the head is penalized and only allowed to a certain extent. + */ +static struct request *bfq_choose_req(struct bfq_data *bfqd, + struct request *rq1, + struct request *rq2, + sector_t last) +{ + sector_t s1, s2, d1 = 0, d2 = 0; + unsigned long back_max; +#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ +#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ + unsigned wrap = 0; /* bit mask: requests behind the disk head? */ + + if (rq1 == NULL || rq1 == rq2) + return rq2; + if (rq2 == NULL) + return rq1; + + if (rq_is_sync(rq1) && !rq_is_sync(rq2)) + return rq1; + else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) + return rq2; + if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) + return rq1; + else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) + return rq2; + + s1 = blk_rq_pos(rq1); + s2 = blk_rq_pos(rq2); + + /* + * By definition, 1KiB is 2 sectors. + */ + back_max = bfqd->bfq_back_max * 2; + + /* + * Strict one way elevator _except_ in the case where we allow + * short backward seeks which are biased as twice the cost of a + * similar forward seek. + */ + if (s1 >= last) + d1 = s1 - last; + else if (s1 + back_max >= last) + d1 = (last - s1) * bfqd->bfq_back_penalty; + else + wrap |= BFQ_RQ1_WRAP; + + if (s2 >= last) + d2 = s2 - last; + else if (s2 + back_max >= last) + d2 = (last - s2) * bfqd->bfq_back_penalty; + else + wrap |= BFQ_RQ2_WRAP; + + /* Found required data */ + + /* + * By doing switch() on the bit mask "wrap" we avoid having to + * check two variables for all permutations: --> faster! + */ + switch (wrap) { + case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ + if (d1 < d2) + return rq1; + else if (d2 < d1) + return rq2; + else { + if (s1 >= s2) + return rq1; + else + return rq2; + } + + case BFQ_RQ2_WRAP: + return rq1; + case BFQ_RQ1_WRAP: + return rq2; + case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ + default: + /* + * Since both rqs are wrapped, + * start with the one that's further behind head + * (--> only *one* back seek required), + * since back seek takes more time than forward. + */ + if (s1 <= s2) + return rq1; + else + return rq2; + } +} + +static struct bfq_queue * +bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, + sector_t sector, struct rb_node **ret_parent, + struct rb_node ***rb_link) +{ + struct rb_node **p, *parent; + struct bfq_queue *bfqq = NULL; + + parent = NULL; + p = &root->rb_node; + while (*p) { + struct rb_node **n; + + parent = *p; + bfqq = rb_entry(parent, struct bfq_queue, pos_node); + + /* + * Sort strictly based on sector. Smallest to the left, + * largest to the right. + */ + if (sector > blk_rq_pos(bfqq->next_rq)) + n = &(*p)->rb_right; + else if (sector < blk_rq_pos(bfqq->next_rq)) + n = &(*p)->rb_left; + else + break; + p = n; + bfqq = NULL; + } + + *ret_parent = parent; + if (rb_link) + *rb_link = p; + + bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", + (long long unsigned)sector, + bfqq != NULL ? bfqq->pid : 0); + + return bfqq; +} + +static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + struct rb_node **p, *parent; + struct bfq_queue *__bfqq; + + if (bfqq->pos_root != NULL) { + rb_erase(&bfqq->pos_node, bfqq->pos_root); + bfqq->pos_root = NULL; + } + + if (bfq_class_idle(bfqq)) + return; + if (!bfqq->next_rq) + return; + + bfqq->pos_root = &bfqd->rq_pos_tree; + __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, + blk_rq_pos(bfqq->next_rq), &parent, &p); + if (__bfqq == NULL) { + rb_link_node(&bfqq->pos_node, parent, p); + rb_insert_color(&bfqq->pos_node, bfqq->pos_root); + } else + bfqq->pos_root = NULL; +} + +/* + * Tell whether there are active queues or groups with differentiated weights. + */ +static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) +{ + /* + * For weights to differ, at least one of the trees must contain + * at least two nodes. + */ + return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && + (bfqd->queue_weights_tree.rb_node->rb_left || + bfqd->queue_weights_tree.rb_node->rb_right) +#ifdef CONFIG_CGROUP_BFQIO + ) || + (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && + (bfqd->group_weights_tree.rb_node->rb_left || + bfqd->group_weights_tree.rb_node->rb_right) +#endif + ); +} + +/* + * If the weight-counter tree passed as input contains no counter for + * the weight of the input entity, then add that counter; otherwise just + * increment the existing counter. + * + * Note that weight-counter trees contain few nodes in mostly symmetric + * scenarios. For example, if all queues have the same weight, then the + * weight-counter tree for the queues may contain at most one node. + * This holds even if low_latency is on, because weight-raised queues + * are not inserted in the tree. + * In most scenarios, the rate at which nodes are created/destroyed + * should be low too. + */ +static void bfq_weights_tree_add(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root) +{ + struct rb_node **new = &(root->rb_node), *parent = NULL; + + /* + * Do not insert if the entity is already associated with a + * counter, which happens if: + * 1) the entity is associated with a queue, + * 2) a request arrival has caused the queue to become both + * non-weight-raised, and hence change its weight, and + * backlogged; in this respect, each of the two events + * causes an invocation of this function, + * 3) this is the invocation of this function caused by the + * second event. This second invocation is actually useless, + * and we handle this fact by exiting immediately. More + * efficient or clearer solutions might possibly be adopted. + */ + if (entity->weight_counter) + return; + + while (*new) { + struct bfq_weight_counter *__counter = container_of(*new, + struct bfq_weight_counter, + weights_node); + parent = *new; + + if (entity->weight == __counter->weight) { + entity->weight_counter = __counter; + goto inc_counter; + } + if (entity->weight < __counter->weight) + new = &((*new)->rb_left); + else + new = &((*new)->rb_right); + } + + entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), + GFP_ATOMIC); + entity->weight_counter->weight = entity->weight; + rb_link_node(&entity->weight_counter->weights_node, parent, new); + rb_insert_color(&entity->weight_counter->weights_node, root); + +inc_counter: + entity->weight_counter->num_active++; +} + +/* + * Decrement the weight counter associated with the entity, and, if the + * counter reaches 0, remove the counter from the tree. + * See the comments to the function bfq_weights_tree_add() for considerations + * about overhead. + */ +static void bfq_weights_tree_remove(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root) +{ + if (!entity->weight_counter) + return; + + BUG_ON(RB_EMPTY_ROOT(root)); + BUG_ON(entity->weight_counter->weight != entity->weight); + + BUG_ON(!entity->weight_counter->num_active); + entity->weight_counter->num_active--; + if (entity->weight_counter->num_active > 0) + goto reset_entity_pointer; + + rb_erase(&entity->weight_counter->weights_node, root); + kfree(entity->weight_counter); + +reset_entity_pointer: + entity->weight_counter = NULL; +} + +static struct request *bfq_find_next_rq(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct request *last) +{ + struct rb_node *rbnext = rb_next(&last->rb_node); + struct rb_node *rbprev = rb_prev(&last->rb_node); + struct request *next = NULL, *prev = NULL; + + BUG_ON(RB_EMPTY_NODE(&last->rb_node)); + + if (rbprev != NULL) + prev = rb_entry_rq(rbprev); + + if (rbnext != NULL) + next = rb_entry_rq(rbnext); + else { + rbnext = rb_first(&bfqq->sort_list); + if (rbnext && rbnext != &last->rb_node) + next = rb_entry_rq(rbnext); + } + + return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); +} + +/* see the definition of bfq_async_charge_factor for details */ +static inline unsigned long bfq_serv_to_charge(struct request *rq, + struct bfq_queue *bfqq) +{ + return blk_rq_sectors(rq) * + (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * + bfq_async_charge_factor)); +} + +/** + * bfq_updated_next_req - update the queue after a new next_rq selection. + * @bfqd: the device data the queue belongs to. + * @bfqq: the queue to update. + * + * If the first request of a queue changes we make sure that the queue + * has enough budget to serve at least its first request (if the + * request has grown). We do this because if the queue has not enough + * budget for its first request, it has to go through two dispatch + * rounds to actually get it dispatched. + */ +static void bfq_updated_next_req(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); + struct request *next_rq = bfqq->next_rq; + unsigned long new_budget; + + if (next_rq == NULL) + return; + + if (bfqq == bfqd->in_service_queue) + /* + * In order not to break guarantees, budgets cannot be + * changed after an entity has been selected. + */ + return; + + BUG_ON(entity->tree != &st->active); + BUG_ON(entity == entity->sched_data->in_service_entity); + + new_budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + if (entity->budget != new_budget) { + entity->budget = new_budget; + bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", + new_budget); + bfq_activate_bfqq(bfqd, bfqq); + } +} + +static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) +{ + u64 dur; + + if (bfqd->bfq_wr_max_time > 0) + return bfqd->bfq_wr_max_time; + + dur = bfqd->RT_prod; + do_div(dur, bfqd->peak_rate); + + return dur; +} + +/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ +static inline void bfq_reset_burst_list(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + struct bfq_queue *item; + struct hlist_node *n; + + hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) + hlist_del_init(&item->burst_list_node); + hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); + bfqd->burst_size = 1; +} + +/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ +static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + /* Increment burst size to take into account also bfqq */ + bfqd->burst_size++; + + if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { + struct bfq_queue *pos, *bfqq_item; + struct hlist_node *n; + + /* + * Enough queues have been activated shortly after each + * other to consider this burst as large. + */ + bfqd->large_burst = true; + + /* + * We can now mark all queues in the burst list as + * belonging to a large burst. + */ + hlist_for_each_entry(bfqq_item, &bfqd->burst_list, + burst_list_node) + bfq_mark_bfqq_in_large_burst(bfqq_item); + bfq_mark_bfqq_in_large_burst(bfqq); + + /* + * From now on, and until the current burst finishes, any + * new queue being activated shortly after the last queue + * was inserted in the burst can be immediately marked as + * belonging to a large burst. So the burst list is not + * needed any more. Remove it. + */ + hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, + burst_list_node) + hlist_del_init(&pos->burst_list_node); + } else /* burst not yet large: add bfqq to the burst list */ + hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); +} + +/* + * If many queues happen to become active shortly after each other, then, + * to help the processes associated to these queues get their job done as + * soon as possible, it is usually better to not grant either weight-raising + * or device idling to these queues. In this comment we describe, firstly, + * the reasons why this fact holds, and, secondly, the next function, which + * implements the main steps needed to properly mark these queues so that + * they can then be treated in a different way. + * + * As for the terminology, we say that a queue becomes active, i.e., + * switches from idle to backlogged, either when it is created (as a + * consequence of the arrival of an I/O request), or, if already existing, + * when a new request for the queue arrives while the queue is idle. + * Bursts of activations, i.e., activations of different queues occurring + * shortly after each other, are typically caused by services or applications + * that spawn or reactivate many parallel threads/processes. Examples are + * systemd during boot or git grep. + * + * These services or applications benefit mostly from a high throughput: + * the quicker the requests of the activated queues are cumulatively served, + * the sooner the target job of these queues gets completed. As a consequence, + * weight-raising any of these queues, which also implies idling the device + * for it, is almost always counterproductive: in most cases it just lowers + * throughput. + * + * On the other hand, a burst of activations may be also caused by the start + * of an application that does not consist in a lot of parallel I/O-bound + * threads. In fact, with a complex application, the burst may be just a + * consequence of the fact that several processes need to be executed to + * start-up the application. To start an application as quickly as possible, + * the best thing to do is to privilege the I/O related to the application + * with respect to all other I/O. Therefore, the best strategy to start as + * quickly as possible an application that causes a burst of activations is + * to weight-raise all the queues activated during the burst. This is the + * exact opposite of the best strategy for the other type of bursts. + * + * In the end, to take the best action for each of the two cases, the two + * types of bursts need to be distinguished. Fortunately, this seems + * relatively easy to do, by looking at the sizes of the bursts. In + * particular, we found a threshold such that bursts with a larger size + * than that threshold are apparently caused only by services or commands + * such as systemd or git grep. For brevity, hereafter we call just 'large' + * these bursts. BFQ *does not* weight-raise queues whose activations occur + * in a large burst. In addition, for each of these queues BFQ performs or + * does not perform idling depending on which choice boosts the throughput + * most. The exact choice depends on the device and request pattern at + * hand. + * + * Turning back to the next function, it implements all the steps needed + * to detect the occurrence of a large burst and to properly mark all the + * queues belonging to it (so that they can then be treated in a different + * way). This goal is achieved by maintaining a special "burst list" that + * holds, temporarily, the queues that belong to the burst in progress. The + * list is then used to mark these queues as belonging to a large burst if + * the burst does become large. The main steps are the following. + * + * . when the very first queue is activated, the queue is inserted into the + * list (as it could be the first queue in a possible burst) + * + * . if the current burst has not yet become large, and a queue Q that does + * not yet belong to the burst is activated shortly after the last time + * at which a new queue entered the burst list, then the function appends + * Q to the burst list + * + * . if, as a consequence of the previous step, the burst size reaches + * the large-burst threshold, then + * + * . all the queues in the burst list are marked as belonging to a + * large burst + * + * . the burst list is deleted; in fact, the burst list already served + * its purpose (keeping temporarily track of the queues in a burst, + * so as to be able to mark them as belonging to a large burst in the + * previous sub-step), and now is not needed any more + * + * . the device enters a large-burst mode + * + * . if a queue Q that does not belong to the burst is activated while + * the device is in large-burst mode and shortly after the last time + * at which a queue either entered the burst list or was marked as + * belonging to the current large burst, then Q is immediately marked + * as belonging to a large burst. + * + * . if a queue Q that does not belong to the burst is activated a while + * later, i.e., not shortly after, than the last time at which a queue + * either entered the burst list or was marked as belonging to the + * current large burst, then the current burst is deemed as finished and: + * + * . the large-burst mode is reset if set + * + * . the burst list is emptied + * + * . Q is inserted in the burst list, as Q may be the first queue + * in a possible new burst (then the burst list contains just Q + * after this step). + */ +static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, + bool idle_for_long_time) +{ + /* + * If bfqq happened to be activated in a burst, but has been idle + * for at least as long as an interactive queue, then we assume + * that, in the overall I/O initiated in the burst, the I/O + * associated to bfqq is finished. So bfqq does not need to be + * treated as a queue belonging to a burst anymore. Accordingly, + * we reset bfqq's in_large_burst flag if set, and remove bfqq + * from the burst list if it's there. We do not decrement instead + * burst_size, because the fact that bfqq does not need to belong + * to the burst list any more does not invalidate the fact that + * bfqq may have been activated during the current burst. + */ + if (idle_for_long_time) { + hlist_del_init(&bfqq->burst_list_node); + bfq_clear_bfqq_in_large_burst(bfqq); + } + + /* + * If bfqq is already in the burst list or is part of a large + * burst, then there is nothing else to do. + */ + if (!hlist_unhashed(&bfqq->burst_list_node) || + bfq_bfqq_in_large_burst(bfqq)) + return; + + /* + * If bfqq's activation happens late enough, then the current + * burst is finished, and related data structures must be reset. + * + * In this respect, consider the special case where bfqq is the very + * first queue being activated. In this case, last_ins_in_burst is + * not yet significant when we get here. But it is easy to verify + * that, whether or not the following condition is true, bfqq will + * end up being inserted into the burst list. In particular the + * list will happen to contain only bfqq. And this is exactly what + * has to happen, as bfqq may be the first queue in a possible + * burst. + */ + if (time_is_before_jiffies(bfqd->last_ins_in_burst + + bfqd->bfq_burst_interval)) { + bfqd->large_burst = false; + bfq_reset_burst_list(bfqd, bfqq); + return; + } + + /* + * If we get here, then bfqq is being activated shortly after the + * last queue. So, if the current burst is also large, we can mark + * bfqq as belonging to this large burst immediately. + */ + if (bfqd->large_burst) { + bfq_mark_bfqq_in_large_burst(bfqq); + return; + } + + /* + * If we get here, then a large-burst state has not yet been + * reached, but bfqq is being activated shortly after the last + * queue. Then we add bfqq to the burst. + */ + bfq_add_to_burst(bfqd, bfqq); +} + +static void bfq_add_request(struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_entity *entity = &bfqq->entity; + struct bfq_data *bfqd = bfqq->bfqd; + struct request *next_rq, *prev; + unsigned long old_wr_coeff = bfqq->wr_coeff; + bool interactive = false; + + bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); + bfqq->queued[rq_is_sync(rq)]++; + bfqd->queued++; + + elv_rb_add(&bfqq->sort_list, rq); + + /* + * Check if this request is a better next-serve candidate. + */ + prev = bfqq->next_rq; + next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); + BUG_ON(next_rq == NULL); + bfqq->next_rq = next_rq; + + /* + * Adjust priority tree position, if next_rq changes. + */ + if (prev != bfqq->next_rq) + bfq_rq_pos_tree_add(bfqd, bfqq); + + if (!bfq_bfqq_busy(bfqq)) { + bool soft_rt, + idle_for_long_time = time_is_before_jiffies( + bfqq->budget_timeout + + bfqd->bfq_wr_min_idle_time); + + if (bfq_bfqq_sync(bfqq)) { + bool already_in_burst = + !hlist_unhashed(&bfqq->burst_list_node) || + bfq_bfqq_in_large_burst(bfqq); + bfq_handle_burst(bfqd, bfqq, idle_for_long_time); + /* + * If bfqq was not already in the current burst, + * then, at this point, bfqq either has been + * added to the current burst or has caused the + * current burst to terminate. In particular, in + * the second case, bfqq has become the first + * queue in a possible new burst. + * In both cases last_ins_in_burst needs to be + * moved forward. + */ + if (!already_in_burst) + bfqd->last_ins_in_burst = jiffies; + } + + soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && + !bfq_bfqq_in_large_burst(bfqq) && + time_is_before_jiffies(bfqq->soft_rt_next_start); + interactive = !bfq_bfqq_in_large_burst(bfqq) && + idle_for_long_time; + entity->budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + + if (!bfq_bfqq_IO_bound(bfqq)) { + if (time_before(jiffies, + RQ_BIC(rq)->ttime.last_end_request + + bfqd->bfq_slice_idle)) { + bfqq->requests_within_timer++; + if (bfqq->requests_within_timer >= + bfqd->bfq_requests_within_timer) + bfq_mark_bfqq_IO_bound(bfqq); + } else + bfqq->requests_within_timer = 0; + } + + if (!bfqd->low_latency) + goto add_bfqq_busy; + + /* + * If the queue is not being boosted and has been idle + * for enough time, start a weight-raising period + */ + if (old_wr_coeff == 1 && (interactive || soft_rt)) { + bfqq->wr_coeff = bfqd->bfq_wr_coeff; + if (interactive) + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); + else + bfqq->wr_cur_max_time = + bfqd->bfq_wr_rt_max_time; + bfq_log_bfqq(bfqd, bfqq, + "wrais starting at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } else if (old_wr_coeff > 1) { + if (interactive) + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); + else if (bfq_bfqq_in_large_burst(bfqq) || + (bfqq->wr_cur_max_time == + bfqd->bfq_wr_rt_max_time && + !soft_rt)) { + bfqq->wr_coeff = 1; + bfq_log_bfqq(bfqd, bfqq, + "wrais ending at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq-> + wr_cur_max_time)); + } else if (time_before( + bfqq->last_wr_start_finish + + bfqq->wr_cur_max_time, + jiffies + + bfqd->bfq_wr_rt_max_time) && + soft_rt) { + /* + * + * The remaining weight-raising time is lower + * than bfqd->bfq_wr_rt_max_time, which + * means that the application is enjoying + * weight raising either because deemed soft- + * rt in the near past, or because deemed + * interactive a long ago. In both cases, + * resetting now the current remaining weight- + * raising time for the application to the + * weight-raising duration for soft rt + * applications would not cause any latency + * increase for the application (as the new + * duration would be higher than the remaining + * time). + * + * In addition, the application is now meeting + * the requirements for being deemed soft rt. + * In the end we can correctly and safely + * (re)charge the weight-raising duration for + * the application with the weight-raising + * duration for soft rt applications. + * + * In particular, doing this recharge now, i.e., + * before the weight-raising period for the + * application finishes, reduces the probability + * of the following negative scenario: + * 1) the weight of a soft rt application is + * raised at startup (as for any newly + * created application), + * 2) since the application is not interactive, + * at a certain time weight-raising is + * stopped for the application, + * 3) at that time the application happens to + * still have pending requests, and hence + * is destined to not have a chance to be + * deemed soft rt before these requests are + * completed (see the comments to the + * function bfq_bfqq_softrt_next_start() + * for details on soft rt detection), + * 4) these pending requests experience a high + * latency because the application is not + * weight-raised while they are pending. + */ + bfqq->last_wr_start_finish = jiffies; + bfqq->wr_cur_max_time = + bfqd->bfq_wr_rt_max_time; + } + } + if (old_wr_coeff != bfqq->wr_coeff) + entity->ioprio_changed = 1; +add_bfqq_busy: + bfqq->last_idle_bklogged = jiffies; + bfqq->service_from_backlogged = 0; + bfq_clear_bfqq_softrt_update(bfqq); + bfq_add_bfqq_busy(bfqd, bfqq); + } else { + if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && + time_is_before_jiffies( + bfqq->last_wr_start_finish + + bfqd->bfq_wr_min_inter_arr_async)) { + bfqq->wr_coeff = bfqd->bfq_wr_coeff; + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); + + bfqd->wr_busy_queues++; + entity->ioprio_changed = 1; + bfq_log_bfqq(bfqd, bfqq, + "non-idle wrais starting at %lu, rais_max_time %u", + jiffies, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } + if (prev != bfqq->next_rq) + bfq_updated_next_req(bfqd, bfqq); + } + + if (bfqd->low_latency && + (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) + bfqq->last_wr_start_finish = jiffies; +} + +static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, + struct bio *bio) +{ + struct task_struct *tsk = current; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq; + + bic = bfq_bic_lookup(bfqd, tsk->io_context); + if (bic == NULL) + return NULL; + + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); + if (bfqq != NULL) + return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); + + return NULL; +} + +static void bfq_activate_request(struct request_queue *q, struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + + bfqd->rq_in_driver++; + bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); + bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", + (long long unsigned)bfqd->last_position); +} + +static inline void bfq_deactivate_request(struct request_queue *q, + struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + + BUG_ON(bfqd->rq_in_driver == 0); + bfqd->rq_in_driver--; +} + +static void bfq_remove_request(struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_data *bfqd = bfqq->bfqd; + const int sync = rq_is_sync(rq); + + if (bfqq->next_rq == rq) { + bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); + bfq_updated_next_req(bfqd, bfqq); + } + + if (rq->queuelist.prev != &rq->queuelist) + list_del_init(&rq->queuelist); + BUG_ON(bfqq->queued[sync] == 0); + bfqq->queued[sync]--; + bfqd->queued--; + elv_rb_del(&bfqq->sort_list, rq); + + if (RB_EMPTY_ROOT(&bfqq->sort_list)) { + if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) + bfq_del_bfqq_busy(bfqd, bfqq, 1); + /* + * Remove queue from request-position tree as it is empty. + */ + if (bfqq->pos_root != NULL) { + rb_erase(&bfqq->pos_node, bfqq->pos_root); + bfqq->pos_root = NULL; + } + } + + if (rq->cmd_flags & REQ_META) { + BUG_ON(bfqq->meta_pending == 0); + bfqq->meta_pending--; + } +} + +static int bfq_merge(struct request_queue *q, struct request **req, + struct bio *bio) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct request *__rq; + + __rq = bfq_find_rq_fmerge(bfqd, bio); + if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { + *req = __rq; + return ELEVATOR_FRONT_MERGE; + } + + return ELEVATOR_NO_MERGE; +} + +static void bfq_merged_request(struct request_queue *q, struct request *req, + int type) +{ + if (type == ELEVATOR_FRONT_MERGE && + rb_prev(&req->rb_node) && + blk_rq_pos(req) < + blk_rq_pos(container_of(rb_prev(&req->rb_node), + struct request, rb_node))) { + struct bfq_queue *bfqq = RQ_BFQQ(req); + struct bfq_data *bfqd = bfqq->bfqd; + struct request *prev, *next_rq; + + /* Reposition request in its sort_list */ + elv_rb_del(&bfqq->sort_list, req); + elv_rb_add(&bfqq->sort_list, req); + /* Choose next request to be served for bfqq */ + prev = bfqq->next_rq; + next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, + bfqd->last_position); + BUG_ON(next_rq == NULL); + bfqq->next_rq = next_rq; + /* + * If next_rq changes, update both the queue's budget to + * fit the new request and the queue's position in its + * rq_pos_tree. + */ + if (prev != bfqq->next_rq) { + bfq_updated_next_req(bfqd, bfqq); + bfq_rq_pos_tree_add(bfqd, bfqq); + } + } +} + +static void bfq_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq), *next_bfqq = RQ_BFQQ(next); + + /* + * If next and rq belong to the same bfq_queue and next is older + * than rq, then reposition rq in the fifo (by substituting next + * with rq). Otherwise, if next and rq belong to different + * bfq_queues, never reposition rq: in fact, we would have to + * reposition it with respect to next's position in its own fifo, + * which would most certainly be too expensive with respect to + * the benefits. + */ + if (bfqq == next_bfqq && + !list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && + time_before(next->fifo_time, rq->fifo_time)) { + list_del_init(&rq->queuelist); + list_replace_init(&next->queuelist, &rq->queuelist); + rq->fifo_time = next->fifo_time; + } + + if (bfqq->next_rq == next) + bfqq->next_rq = rq; + + bfq_remove_request(next); +} + +/* Must be called with bfqq != NULL */ +static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) +{ + BUG_ON(bfqq == NULL); + if (bfq_bfqq_busy(bfqq)) + bfqq->bfqd->wr_busy_queues--; + bfqq->wr_coeff = 1; + bfqq->wr_cur_max_time = 0; + /* Trigger a weight change on the next activation of the queue */ + bfqq->entity.ioprio_changed = 1; +} + +static void bfq_end_wr_async_queues(struct bfq_data *bfqd, + struct bfq_group *bfqg) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < IOPRIO_BE_NR; j++) + if (bfqg->async_bfqq[i][j] != NULL) + bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); + if (bfqg->async_idle_bfqq != NULL) + bfq_bfqq_end_wr(bfqg->async_idle_bfqq); +} + +static void bfq_end_wr(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq; + + spin_lock_irq(bfqd->queue->queue_lock); + + list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) + bfq_bfqq_end_wr(bfqq); + list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) + bfq_bfqq_end_wr(bfqq); + bfq_end_wr_async(bfqd); + + spin_unlock_irq(bfqd->queue->queue_lock); +} + +static int bfq_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq; + + /* + * Disallow merge of a sync bio into an async request. + */ + if (bfq_bio_sync(bio) && !rq_is_sync(rq)) + return 0; + + /* + * Lookup the bfqq that this bio will be queued with. Allow + * merge only if rq is queued there. + * Queue lock is held here. + */ + bic = bfq_bic_lookup(bfqd, current->io_context); + if (bic == NULL) + return 0; + + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); + return bfqq == RQ_BFQQ(rq); +} + +static void __bfq_set_in_service_queue(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (bfqq != NULL) { + bfq_mark_bfqq_must_alloc(bfqq); + bfq_mark_bfqq_budget_new(bfqq); + bfq_clear_bfqq_fifo_expire(bfqq); + + bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; + + bfq_log_bfqq(bfqd, bfqq, + "set_in_service_queue, cur-budget = %lu", + bfqq->entity.budget); + } + + bfqd->in_service_queue = bfqq; +} + +/* + * Get and set a new queue for service. + */ +static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (!bfqq) + bfqq = bfq_get_next_queue(bfqd); + else + bfq_get_next_queue_forced(bfqd, bfqq); + + __bfq_set_in_service_queue(bfqd, bfqq); + return bfqq; +} + +static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, + struct request *rq) +{ + if (blk_rq_pos(rq) >= bfqd->last_position) + return blk_rq_pos(rq) - bfqd->last_position; + else + return bfqd->last_position - blk_rq_pos(rq); +} + +/* + * Return true if bfqq has no request pending and rq is close enough to + * bfqd->last_position, or if rq is closer to bfqd->last_position than + * bfqq->next_rq + */ +static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) +{ + return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; +} + +static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) +{ + struct rb_root *root = &bfqd->rq_pos_tree; + struct rb_node *parent, *node; + struct bfq_queue *__bfqq; + sector_t sector = bfqd->last_position; + + if (RB_EMPTY_ROOT(root)) + return NULL; + + /* + * First, if we find a request starting at the end of the last + * request, choose it. + */ + __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); + if (__bfqq != NULL) + return __bfqq; + + /* + * If the exact sector wasn't found, the parent of the NULL leaf + * will contain the closest sector (rq_pos_tree sorted by + * next_request position). + */ + __bfqq = rb_entry(parent, struct bfq_queue, pos_node); + if (bfq_rq_close(bfqd, __bfqq->next_rq)) + return __bfqq; + + if (blk_rq_pos(__bfqq->next_rq) < sector) + node = rb_next(&__bfqq->pos_node); + else + node = rb_prev(&__bfqq->pos_node); + if (node == NULL) + return NULL; + + __bfqq = rb_entry(node, struct bfq_queue, pos_node); + if (bfq_rq_close(bfqd, __bfqq->next_rq)) + return __bfqq; + + return NULL; +} + +/* + * bfqd - obvious + * cur_bfqq - passed in so that we don't decide that the current queue + * is closely cooperating with itself. + * + * We are assuming that cur_bfqq has dispatched at least one request, + * and that bfqd->last_position reflects a position on the disk associated + * with the I/O issued by cur_bfqq. + */ +static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, + struct bfq_queue *cur_bfqq) +{ + struct bfq_queue *bfqq; + + if (bfq_class_idle(cur_bfqq)) + return NULL; + if (!bfq_bfqq_sync(cur_bfqq)) + return NULL; + if (BFQQ_SEEKY(cur_bfqq)) + return NULL; + + /* If device has only one backlogged bfq_queue, don't search. */ + if (bfqd->busy_queues == 1) + return NULL; + + /* + * We should notice if some of the queues are cooperating, e.g. + * working closely on the same area of the disk. In that case, + * we can group them together and don't waste time idling. + */ + bfqq = bfqq_close(bfqd); + if (bfqq == NULL || bfqq == cur_bfqq) + return NULL; + + /* + * Do not merge queues from different bfq_groups. + */ + if (bfqq->entity.parent != cur_bfqq->entity.parent) + return NULL; + + /* + * It only makes sense to merge sync queues. + */ + if (!bfq_bfqq_sync(bfqq)) + return NULL; + if (BFQQ_SEEKY(bfqq)) + return NULL; + + /* + * Do not merge queues of different priority classes. + */ + if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) + return NULL; + + return bfqq; +} + +/* + * If enough samples have been computed, return the current max budget + * stored in bfqd, which is dynamically updated according to the + * estimated disk peak rate; otherwise return the default max budget + */ +static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) +{ + if (bfqd->budgets_assigned < 194) + return bfq_default_max_budget; + else + return bfqd->bfq_max_budget; +} + +/* + * Return min budget, which is a fraction of the current or default + * max budget (trying with 1/32) + */ +static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) +{ + if (bfqd->budgets_assigned < 194) + return bfq_default_max_budget / 32; + else + return bfqd->bfq_max_budget / 32; +} + +static void bfq_arm_slice_timer(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq = bfqd->in_service_queue; + struct bfq_io_cq *bic; + unsigned long sl; + + BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); + + /* Processes have exited, don't wait. */ + bic = bfqd->in_service_bic; + if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) + return; + + bfq_mark_bfqq_wait_request(bfqq); + + /* + * We don't want to idle for seeks, but we do want to allow + * fair distribution of slice time for a process doing back-to-back + * seeks. So allow a little bit of time for him to submit a new rq. + * + * To prevent processes with (partly) seeky workloads from + * being too ill-treated, grant them a small fraction of the + * assigned budget before reducing the waiting time to + * BFQ_MIN_TT. This happened to help reduce latency. + */ + sl = bfqd->bfq_slice_idle; + /* + * Unless the queue is being weight-raised or the scenario is + * asymmetric, grant only minimum idle time if the queue either + * has been seeky for long enough or has already proved to be + * constantly seeky. + */ + if (bfq_sample_valid(bfqq->seek_samples) && + ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > + bfq_max_budget(bfqq->bfqd) / 8) || + bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1 && + symmetric_scenario) + sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); + else if (bfqq->wr_coeff > 1) + sl = sl * 3; + bfqd->last_idling_start = ktime_get(); + mod_timer(&bfqd->idle_slice_timer, jiffies + sl); + bfq_log(bfqd, "arm idle: %u/%u ms", + jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); +} + +/* + * Set the maximum time for the in-service queue to consume its + * budget. This prevents seeky processes from lowering the disk + * throughput (always guaranteed with a time slice scheme as in CFQ). + */ +static void bfq_set_budget_timeout(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq = bfqd->in_service_queue; + unsigned int timeout_coeff; + if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) + timeout_coeff = 1; + else + timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; + + bfqd->last_budget_start = ktime_get(); + + bfq_clear_bfqq_budget_new(bfqq); + bfqq->budget_timeout = jiffies + + bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; + + bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", + jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * + timeout_coeff)); +} + +/* + * Move request from internal lists to the request queue dispatch list. + */ +static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_queue *bfqq = RQ_BFQQ(rq); + + /* + * For consistency, the next instruction should have been executed + * after removing the request from the queue and dispatching it. + * We execute instead this instruction before bfq_remove_request() + * (and hence introduce a temporary inconsistency), for efficiency. + * In fact, in a forced_dispatch, this prevents two counters related + * to bfqq->dispatched to risk to be uselessly decremented if bfqq + * is not in service, and then to be incremented again after + * incrementing bfqq->dispatched. + */ + bfqq->dispatched++; + bfq_remove_request(rq); + elv_dispatch_sort(q, rq); + + if (bfq_bfqq_sync(bfqq)) + bfqd->sync_flight++; +} + +/* + * Return expired entry, or NULL to just start from scratch in rbtree. + */ +static struct request *bfq_check_fifo(struct bfq_queue *bfqq) +{ + struct request *rq = NULL; + + if (bfq_bfqq_fifo_expire(bfqq)) + return NULL; + + bfq_mark_bfqq_fifo_expire(bfqq); + + if (list_empty(&bfqq->fifo)) + return NULL; + + rq = rq_entry_fifo(bfqq->fifo.next); + + if (time_before(jiffies, rq->fifo_time)) + return NULL; + + return rq; +} + +/* Must be called with the queue_lock held. */ +static int bfqq_process_refs(struct bfq_queue *bfqq) +{ + int process_refs, io_refs; + + io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; + process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; + BUG_ON(process_refs < 0); + return process_refs; +} + +static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +{ + int process_refs, new_process_refs; + struct bfq_queue *__bfqq; + + /* + * If there are no process references on the new_bfqq, then it is + * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain + * may have dropped their last reference (not just their last process + * reference). + */ + if (!bfqq_process_refs(new_bfqq)) + return; + + /* Avoid a circular list and skip interim queue merges. */ + while ((__bfqq = new_bfqq->new_bfqq)) { + if (__bfqq == bfqq) + return; + new_bfqq = __bfqq; + } + + process_refs = bfqq_process_refs(bfqq); + new_process_refs = bfqq_process_refs(new_bfqq); + /* + * If the process for the bfqq has gone away, there is no + * sense in merging the queues. + */ + if (process_refs == 0 || new_process_refs == 0) + return; + + /* + * Merge in the direction of the lesser amount of work. + */ + if (new_process_refs >= process_refs) { + bfqq->new_bfqq = new_bfqq; + atomic_add(process_refs, &new_bfqq->ref); + } else { + new_bfqq->new_bfqq = bfqq; + atomic_add(new_process_refs, &bfqq->ref); + } + bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", + new_bfqq->pid); +} + +static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + return entity->budget - entity->service; +} + +static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + BUG_ON(bfqq != bfqd->in_service_queue); + + __bfq_bfqd_reset_in_service(bfqd); + + /* + * If this bfqq is shared between multiple processes, check + * to make sure that those processes are still issuing I/Os + * within the mean seek distance. If not, it may be time to + * break the queues apart again. + */ + if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) + bfq_mark_bfqq_split_coop(bfqq); + + if (RB_EMPTY_ROOT(&bfqq->sort_list)) { + /* + * Overloading budget_timeout field to store the time + * at which the queue remains with no backlog; used by + * the weight-raising mechanism. + */ + bfqq->budget_timeout = jiffies; + bfq_del_bfqq_busy(bfqd, bfqq, 1); + } else { + bfq_activate_bfqq(bfqd, bfqq); + /* + * Resort priority tree of potential close cooperators. + */ + bfq_rq_pos_tree_add(bfqd, bfqq); + } +} + +/** + * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. + * @bfqd: device data. + * @bfqq: queue to update. + * @reason: reason for expiration. + * + * Handle the feedback on @bfqq budget. See the body for detailed + * comments. + */ +static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + enum bfqq_expiration reason) +{ + struct request *next_rq; + unsigned long budget, min_budget; + + budget = bfqq->max_budget; + min_budget = bfq_min_budget(bfqd); + + BUG_ON(bfqq != bfqd->in_service_queue); + + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", + bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", + budget, bfq_min_budget(bfqd)); + bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", + bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); + + if (bfq_bfqq_sync(bfqq)) { + switch (reason) { + /* + * Caveat: in all the following cases we trade latency + * for throughput. + */ + case BFQ_BFQQ_TOO_IDLE: + /* + * This is the only case where we may reduce + * the budget: if there is no request of the + * process still waiting for completion, then + * we assume (tentatively) that the timer has + * expired because the batch of requests of + * the process could have been served with a + * smaller budget. Hence, betting that + * process will behave in the same way when it + * becomes backlogged again, we reduce its + * next budget. As long as we guess right, + * this budget cut reduces the latency + * experienced by the process. + * + * However, if there are still outstanding + * requests, then the process may have not yet + * issued its next request just because it is + * still waiting for the completion of some of + * the still outstanding ones. So in this + * subcase we do not reduce its budget, on the + * contrary we increase it to possibly boost + * the throughput, as discussed in the + * comments to the BUDGET_TIMEOUT case. + */ + if (bfqq->dispatched > 0) /* still outstanding reqs */ + budget = min(budget * 2, bfqd->bfq_max_budget); + else { + if (budget > 5 * min_budget) + budget -= 4 * min_budget; + else + budget = min_budget; + } + break; + case BFQ_BFQQ_BUDGET_TIMEOUT: + /* + * We double the budget here because: 1) it + * gives the chance to boost the throughput if + * this is not a seeky process (which may have + * bumped into this timeout because of, e.g., + * ZBR), 2) together with charge_full_budget + * it helps give seeky processes higher + * timestamps, and hence be served less + * frequently. + */ + budget = min(budget * 2, bfqd->bfq_max_budget); + break; + case BFQ_BFQQ_BUDGET_EXHAUSTED: + /* + * The process still has backlog, and did not + * let either the budget timeout or the disk + * idling timeout expire. Hence it is not + * seeky, has a short thinktime and may be + * happy with a higher budget too. So + * definitely increase the budget of this good + * candidate to boost the disk throughput. + */ + budget = min(budget * 4, bfqd->bfq_max_budget); + break; + case BFQ_BFQQ_NO_MORE_REQUESTS: + /* + * Leave the budget unchanged. + */ + default: + return; + } + } else /* async queue */ + /* async queues get always the maximum possible budget + * (their ability to dispatch is limited by + * @bfqd->bfq_max_budget_async_rq). + */ + budget = bfqd->bfq_max_budget; + + bfqq->max_budget = budget; + + if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && + bfqq->max_budget > bfqd->bfq_max_budget) + bfqq->max_budget = bfqd->bfq_max_budget; + + /* + * Make sure that we have enough budget for the next request. + * Since the finish time of the bfqq must be kept in sync with + * the budget, be sure to call __bfq_bfqq_expire() after the + * update. + */ + next_rq = bfqq->next_rq; + if (next_rq != NULL) + bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + else + bfqq->entity.budget = bfqq->max_budget; + + bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", + next_rq != NULL ? blk_rq_sectors(next_rq) : 0, + bfqq->entity.budget); +} + +static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) +{ + unsigned long max_budget; + + /* + * The max_budget calculated when autotuning is equal to the + * amount of sectors transfered in timeout_sync at the + * estimated peak rate. + */ + max_budget = (unsigned long)(peak_rate * 1000 * + timeout >> BFQ_RATE_SHIFT); + + return max_budget; +} + +/* + * In addition to updating the peak rate, checks whether the process + * is "slow", and returns 1 if so. This slow flag is used, in addition + * to the budget timeout, to reduce the amount of service provided to + * seeky processes, and hence reduce their chances to lower the + * throughput. See the code for more details. + */ +static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, + int compensate, enum bfqq_expiration reason) +{ + u64 bw, usecs, expected, timeout; + ktime_t delta; + int update = 0; + + if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) + return 0; + + if (compensate) + delta = bfqd->last_idling_start; + else + delta = ktime_get(); + delta = ktime_sub(delta, bfqd->last_budget_start); + usecs = ktime_to_us(delta); + + /* Don't trust short/unrealistic values. */ + if (usecs < 100 || usecs >= LONG_MAX) + return 0; + + /* + * Calculate the bandwidth for the last slice. We use a 64 bit + * value to store the peak rate, in sectors per usec in fixed + * point math. We do so to have enough precision in the estimate + * and to avoid overflows. + */ + bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; + do_div(bw, (unsigned long)usecs); + + timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); + + /* + * Use only long (> 20ms) intervals to filter out spikes for + * the peak rate estimation. + */ + if (usecs > 20000) { + if (bw > bfqd->peak_rate || + (!BFQQ_SEEKY(bfqq) && + reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { + bfq_log(bfqd, "measured bw =%llu", bw); + /* + * To smooth oscillations use a low-pass filter with + * alpha=7/8, i.e., + * new_rate = (7/8) * old_rate + (1/8) * bw + */ + do_div(bw, 8); + if (bw == 0) + return 0; + bfqd->peak_rate *= 7; + do_div(bfqd->peak_rate, 8); + bfqd->peak_rate += bw; + update = 1; + bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); + } + + update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; + + if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) + bfqd->peak_rate_samples++; + + if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && + update) { + int dev_type = blk_queue_nonrot(bfqd->queue); + if (bfqd->bfq_user_max_budget == 0) { + bfqd->bfq_max_budget = + bfq_calc_max_budget(bfqd->peak_rate, + timeout); + bfq_log(bfqd, "new max_budget=%lu", + bfqd->bfq_max_budget); + } + if (bfqd->device_speed == BFQ_BFQD_FAST && + bfqd->peak_rate < device_speed_thresh[dev_type]) { + bfqd->device_speed = BFQ_BFQD_SLOW; + bfqd->RT_prod = R_slow[dev_type] * + T_slow[dev_type]; + } else if (bfqd->device_speed == BFQ_BFQD_SLOW && + bfqd->peak_rate > device_speed_thresh[dev_type]) { + bfqd->device_speed = BFQ_BFQD_FAST; + bfqd->RT_prod = R_fast[dev_type] * + T_fast[dev_type]; + } + } + } + + /* + * If the process has been served for a too short time + * interval to let its possible sequential accesses prevail on + * the initial seek time needed to move the disk head on the + * first sector it requested, then give the process a chance + * and for the moment return false. + */ + if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) + return 0; + + /* + * A process is considered ``slow'' (i.e., seeky, so that we + * cannot treat it fairly in the service domain, as it would + * slow down too much the other processes) if, when a slice + * ends for whatever reason, it has received service at a + * rate that would not be high enough to complete the budget + * before the budget timeout expiration. + */ + expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; + + /* + * Caveat: processes doing IO in the slower disk zones will + * tend to be slow(er) even if not seeky. And the estimated + * peak rate will actually be an average over the disk + * surface. Hence, to not be too harsh with unlucky processes, + * we keep a budget/3 margin of safety before declaring a + * process slow. + */ + return expected > (4 * bfqq->entity.budget) / 3; +} + +/* + * To be deemed as soft real-time, an application must meet two + * requirements. First, the application must not require an average + * bandwidth higher than the approximate bandwidth required to playback or + * record a compressed high-definition video. + * The next function is invoked on the completion of the last request of a + * batch, to compute the next-start time instant, soft_rt_next_start, such + * that, if the next request of the application does not arrive before + * soft_rt_next_start, then the above requirement on the bandwidth is met. + * + * The second requirement is that the request pattern of the application is + * isochronous, i.e., that, after issuing a request or a batch of requests, + * the application stops issuing new requests until all its pending requests + * have been completed. After that, the application may issue a new batch, + * and so on. + * For this reason the next function is invoked to compute + * soft_rt_next_start only for applications that meet this requirement, + * whereas soft_rt_next_start is set to infinity for applications that do + * not. + * + * Unfortunately, even a greedy application may happen to behave in an + * isochronous way if the CPU load is high. In fact, the application may + * stop issuing requests while the CPUs are busy serving other processes, + * then restart, then stop again for a while, and so on. In addition, if + * the disk achieves a low enough throughput with the request pattern + * issued by the application (e.g., because the request pattern is random + * and/or the device is slow), then the application may meet the above + * bandwidth requirement too. To prevent such a greedy application to be + * deemed as soft real-time, a further rule is used in the computation of + * soft_rt_next_start: soft_rt_next_start must be higher than the current + * time plus the maximum time for which the arrival of a request is waited + * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. + * This filters out greedy applications, as the latter issue instead their + * next request as soon as possible after the last one has been completed + * (in contrast, when a batch of requests is completed, a soft real-time + * application spends some time processing data). + * + * Unfortunately, the last filter may easily generate false positives if + * only bfqd->bfq_slice_idle is used as a reference time interval and one + * or both the following cases occur: + * 1) HZ is so low that the duration of a jiffy is comparable to or higher + * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with + * HZ=100. + * 2) jiffies, instead of increasing at a constant rate, may stop increasing + * for a while, then suddenly 'jump' by several units to recover the lost + * increments. This seems to happen, e.g., inside virtual machines. + * To address this issue, we do not use as a reference time interval just + * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In + * particular we add the minimum number of jiffies for which the filter + * seems to be quite precise also in embedded systems and KVM/QEMU virtual + * machines. + */ +static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + return max(bfqq->last_idle_bklogged + + HZ * bfqq->service_from_backlogged / + bfqd->bfq_wr_max_softrt_rate, + jiffies + bfqq->bfqd->bfq_slice_idle + 4); +} + +/* + * Return the largest-possible time instant such that, for as long as possible, + * the current time will be lower than this time instant according to the macro + * time_is_before_jiffies(). + */ +static inline unsigned long bfq_infinity_from_now(unsigned long now) +{ + return now + ULONG_MAX / 2; +} + +/** + * bfq_bfqq_expire - expire a queue. + * @bfqd: device owning the queue. + * @bfqq: the queue to expire. + * @compensate: if true, compensate for the time spent idling. + * @reason: the reason causing the expiration. + * + * + * If the process associated to the queue is slow (i.e., seeky), or in + * case of budget timeout, or, finally, if it is async, we + * artificially charge it an entire budget (independently of the + * actual service it received). As a consequence, the queue will get + * higher timestamps than the correct ones upon reactivation, and + * hence it will be rescheduled as if it had received more service + * than what it actually received. In the end, this class of processes + * will receive less service in proportion to how slowly they consume + * their budgets (and hence how seriously they tend to lower the + * throughput). + * + * In contrast, when a queue expires because it has been idling for + * too much or because it exhausted its budget, we do not touch the + * amount of service it has received. Hence when the queue will be + * reactivated and its timestamps updated, the latter will be in sync + * with the actual service received by the queue until expiration. + * + * Charging a full budget to the first type of queues and the exact + * service to the others has the effect of using the WF2Q+ policy to + * schedule the former on a timeslice basis, without violating the + * service domain guarantees of the latter. + */ +static void bfq_bfqq_expire(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + int compensate, + enum bfqq_expiration reason) +{ + int slow; + BUG_ON(bfqq != bfqd->in_service_queue); + + /* Update disk peak rate for autotuning and check whether the + * process is slow (see bfq_update_peak_rate). + */ + slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); + + /* + * As above explained, 'punish' slow (i.e., seeky), timed-out + * and async queues, to favor sequential sync workloads. + * + * Processes doing I/O in the slower disk zones will tend to be + * slow(er) even if not seeky. Hence, since the estimated peak + * rate is actually an average over the disk surface, these + * processes may timeout just for bad luck. To avoid punishing + * them we do not charge a full budget to a process that + * succeeded in consuming at least 2/3 of its budget. + */ + if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) + bfq_bfqq_charge_full_budget(bfqq); + + bfqq->service_from_backlogged += bfqq->entity.service; + + if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && + !bfq_bfqq_constantly_seeky(bfqq)) { + bfq_mark_bfqq_constantly_seeky(bfqq); + if (!blk_queue_nonrot(bfqd->queue)) + bfqd->const_seeky_busy_in_flight_queues++; + } + + if (reason == BFQ_BFQQ_TOO_IDLE && + bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) + bfq_clear_bfqq_IO_bound(bfqq); + + if (bfqd->low_latency && bfqq->wr_coeff == 1) + bfqq->last_wr_start_finish = jiffies; + + if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && + RB_EMPTY_ROOT(&bfqq->sort_list)) { + /* + * If we get here, and there are no outstanding requests, + * then the request pattern is isochronous (see the comments + * to the function bfq_bfqq_softrt_next_start()). Hence we + * can compute soft_rt_next_start. If, instead, the queue + * still has outstanding requests, then we have to wait + * for the completion of all the outstanding requests to + * discover whether the request pattern is actually + * isochronous. + */ + if (bfqq->dispatched == 0) + bfqq->soft_rt_next_start = + bfq_bfqq_softrt_next_start(bfqd, bfqq); + else { + /* + * The application is still waiting for the + * completion of one or more requests: + * prevent it from possibly being incorrectly + * deemed as soft real-time by setting its + * soft_rt_next_start to infinity. In fact, + * without this assignment, the application + * would be incorrectly deemed as soft + * real-time if: + * 1) it issued a new request before the + * completion of all its in-flight + * requests, and + * 2) at that time, its soft_rt_next_start + * happened to be in the past. + */ + bfqq->soft_rt_next_start = + bfq_infinity_from_now(jiffies); + /* + * Schedule an update of soft_rt_next_start to when + * the task may be discovered to be isochronous. + */ + bfq_mark_bfqq_softrt_update(bfqq); + } + } + + bfq_log_bfqq(bfqd, bfqq, + "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, + slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); + + /* + * Increase, decrease or leave budget unchanged according to + * reason. + */ + __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); + __bfq_bfqq_expire(bfqd, bfqq); +} + +/* + * Budget timeout is not implemented through a dedicated timer, but + * just checked on request arrivals and completions, as well as on + * idle timer expirations. + */ +static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) +{ + if (bfq_bfqq_budget_new(bfqq) || + time_before(jiffies, bfqq->budget_timeout)) + return 0; + return 1; +} + +/* + * If we expire a queue that is waiting for the arrival of a new + * request, we may prevent the fictitious timestamp back-shifting that + * allows the guarantees of the queue to be preserved (see [1] for + * this tricky aspect). Hence we return true only if this condition + * does not hold, or if the queue is slow enough to deserve only to be + * kicked off for preserving a high throughput. +*/ +static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) +{ + bfq_log_bfqq(bfqq->bfqd, bfqq, + "may_budget_timeout: wait_request %d left %d timeout %d", + bfq_bfqq_wait_request(bfqq), + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, + bfq_bfqq_budget_timeout(bfqq)); + + return (!bfq_bfqq_wait_request(bfqq) || + bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) + && + bfq_bfqq_budget_timeout(bfqq); +} + +/* + * Device idling is allowed only for the queues for which this function + * returns true. For this reason, the return value of this function plays a + * critical role for both throughput boosting and service guarantees. The + * return value is computed through a logical expression. In this rather + * long comment, we try to briefly describe all the details and motivations + * behind the components of this logical expression. + * + * First, the expression is false if bfqq is not sync, or if: bfqq happened + * to become active during a large burst of queue activations, and the + * pattern of requests bfqq contains boosts the throughput if bfqq is + * expired. In fact, queues that became active during a large burst benefit + * only from throughput, as discussed in the comments to bfq_handle_burst. + * In this respect, expiring bfqq certainly boosts the throughput on NCQ- + * capable flash-based devices, whereas, on rotational devices, it boosts + * the throughput only if bfqq contains random requests. + * + * On the opposite end, if (a) bfqq is sync, (b) the above burst-related + * condition does not hold, and (c) bfqq is being weight-raised, then the + * expression always evaluates to true, as device idling is instrumental + * for preserving low-latency guarantees (see [1]). If, instead, conditions + * (a) and (b) do hold, but (c) does not, then the expression evaluates to + * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and + * (2) at least one of the following two conditions holds. + * The first condition is that the device is not performing NCQ, because + * idling the device most certainly boosts the throughput if this condition + * holds and bfqq is I/O-bound and has been granted a non-null idle window. + * The second compound condition is made of the logical AND of two components. + * + * The first component is true only if there is no weight-raised busy + * queue. This guarantees that the device is not idled for a sync non- + * weight-raised queue when there are busy weight-raised queues. The former + * is then expired immediately if empty. Combined with the timestamping + * rules of BFQ (see [1] for details), this causes sync non-weight-raised + * queues to get a lower number of requests served, and hence to ask for a + * lower number of requests from the request pool, before the busy weight- + * raised queues get served again. + * + * This is beneficial for the processes associated with weight-raised + * queues, when the request pool is saturated (e.g., in the presence of + * write hogs). In fact, if the processes associated with the other queues + * ask for requests at a lower rate, then weight-raised processes have a + * higher probability to get a request from the pool immediately (or at + * least soon) when they need one. Hence they have a higher probability to + * actually get a fraction of the disk throughput proportional to their + * high weight. This is especially true with NCQ-capable drives, which + * enqueue several requests in advance and further reorder internally- + * queued requests. + * + * In the end, mistreating non-weight-raised queues when there are busy + * weight-raised queues seems to mitigate starvation problems in the + * presence of heavy write workloads and NCQ, and hence to guarantee a + * higher application and system responsiveness in these hostile scenarios. + * + * If the first component of the compound condition is instead true, i.e., + * there is no weight-raised busy queue, then the second component of the + * compound condition takes into account service-guarantee and throughput + * issues related to NCQ (recall that the compound condition is evaluated + * only if the device is detected as supporting NCQ). + * + * As for service guarantees, allowing the drive to enqueue more than one + * request at a time, and hence delegating de facto final scheduling + * decisions to the drive's internal scheduler, causes loss of control on + * the actual request service order. In this respect, when the drive is + * allowed to enqueue more than one request at a time, the service + * distribution enforced by the drive's internal scheduler is likely to + * coincide with the desired device-throughput distribution only in the + * following, perfectly symmetric, scenario: + * 1) all active queues have the same weight, + * 2) all active groups at the same level in the groups tree have the same + * weight, + * 3) all active groups at the same level in the groups tree have the same + * number of children. + * + * Even in such a scenario, sequential I/O may still receive a preferential + * treatment, but this is not likely to be a big issue with flash-based + * devices, because of their non-dramatic loss of throughput with random + * I/O. Things do differ with HDDs, for which additional care is taken, as + * explained after completing the discussion for flash-based devices. + * + * Unfortunately, keeping the necessary state for evaluating exactly the + * above symmetry conditions would be quite complex and time-consuming. + * Therefore BFQ evaluates instead the following stronger sub-conditions, + * for which it is much easier to maintain the needed state: + * 1) all active queues have the same weight, + * 2) all active groups have the same weight, + * 3) all active groups have at most one active child each. + * In particular, the last two conditions are always true if hierarchical + * support and the cgroups interface are not enabled, hence no state needs + * to be maintained in this case. + * + * According to the above considerations, the second component of the + * compound condition evaluates to true if any of the above symmetry + * sub-condition does not hold, or the device is not flash-based. Therefore, + * if also the first component is true, then idling is allowed for a sync + * queue. These are the only sub-conditions considered if the device is + * flash-based, as, for such a device, it is sensible to force idling only + * for service-guarantee issues. In fact, as for throughput, idling + * NCQ-capable flash-based devices would not boost the throughput even + * with sequential I/O; rather it would lower the throughput in proportion + * to how fast the device is. In the end, (only) if all the three + * sub-conditions hold and the device is flash-based, the compound + * condition evaluates to false and therefore no idling is performed. + * + * As already said, things change with a rotational device, where idling + * boosts the throughput with sequential I/O (even with NCQ). Hence, for + * such a device the second component of the compound condition evaluates + * to true also if the following additional sub-condition does not hold: + * the queue is constantly seeky. Unfortunately, this different behavior + * with respect to flash-based devices causes an additional asymmetry: if + * some sync queues enjoy idling and some other sync queues do not, then + * the latter get a low share of the device throughput, simply because the + * former get many requests served after being set as in service, whereas + * the latter do not. As a consequence, to guarantee the desired throughput + * distribution, on HDDs the compound expression evaluates to true (and + * hence device idling is performed) also if the following last symmetry + * condition does not hold: no other queue is benefiting from idling. Also + * this last condition is actually replaced with a simpler-to-maintain and + * stronger condition: there is no busy queue which is not constantly seeky + * (and hence may also benefit from idling). + * + * To sum up, when all the required symmetry and throughput-boosting + * sub-conditions hold, the second component of the compound condition + * evaluates to false, and hence no idling is performed. This helps to + * keep the drives' internal queues full on NCQ-capable devices, and hence + * to boost the throughput, without causing 'almost' any loss of service + * guarantees. The 'almost' follows from the fact that, if the internal + * queue of one such device is filled while all the sub-conditions hold, + * but at some point in time some sub-condition stops to hold, then it may + * become impossible to let requests be served in the new desired order + * until all the requests already queued in the device have been served. + */ +static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) +{ + struct bfq_data *bfqd = bfqq->bfqd; +#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ + bfqd->busy_in_flight_queues == \ + bfqd->const_seeky_busy_in_flight_queues) + +#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ + bfqd->hw_tag && \ + (blk_queue_nonrot(bfqd->queue) || \ + bfq_bfqq_constantly_seeky(bfqq))) + +/* + * Condition for expiring a non-weight-raised queue (and hence not idling + * the device). + */ +#define cond_for_expiring_non_wr (bfqd->hw_tag && \ + (bfqd->wr_busy_queues > 0 || \ + (blk_queue_nonrot(bfqd->queue) || \ + cond_for_seeky_on_ncq_hdd))) + + return bfq_bfqq_sync(bfqq) && + !cond_for_expiring_in_burst && + (bfqq->wr_coeff > 1 || !symmetric_scenario || + (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && + !cond_for_expiring_non_wr) + ); +} + +/* + * If the in-service queue is empty but sync, and the function + * bfq_bfqq_must_not_expire returns true, then: + * 1) the queue must remain in service and cannot be expired, and + * 2) the disk must be idled to wait for the possible arrival of a new + * request for the queue. + * See the comments to the function bfq_bfqq_must_not_expire for the reasons + * why performing device idling is the best choice to boost the throughput + * and preserve service guarantees when bfq_bfqq_must_not_expire itself + * returns true. + */ +static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) +{ + struct bfq_data *bfqd = bfqq->bfqd; + + return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && + bfq_bfqq_must_not_expire(bfqq); +} + +/* + * Select a queue for service. If we have a current queue in service, + * check whether to continue servicing it, or retrieve and set a new one. + */ +static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq, *new_bfqq = NULL; + struct request *next_rq; + enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; + + bfqq = bfqd->in_service_queue; + if (bfqq == NULL) + goto new_queue; + + bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); + + /* + * If another queue has a request waiting within our mean seek + * distance, let it run. The expire code will check for close + * cooperators and put the close queue at the front of the + * service tree. If possible, merge the expiring queue with the + * new bfqq. + */ + new_bfqq = bfq_close_cooperator(bfqd, bfqq); + if (new_bfqq != NULL && bfqq->new_bfqq == NULL) + bfq_setup_merge(bfqq, new_bfqq); + + if (bfq_may_expire_for_budg_timeout(bfqq) && + !timer_pending(&bfqd->idle_slice_timer) && + !bfq_bfqq_must_idle(bfqq)) + goto expire; + + next_rq = bfqq->next_rq; + /* + * If bfqq has requests queued and it has enough budget left to + * serve them, keep the queue, otherwise expire it. + */ + if (next_rq != NULL) { + if (bfq_serv_to_charge(next_rq, bfqq) > + bfq_bfqq_budget_left(bfqq)) { + reason = BFQ_BFQQ_BUDGET_EXHAUSTED; + goto expire; + } else { + /* + * The idle timer may be pending because we may + * not disable disk idling even when a new request + * arrives. + */ + if (timer_pending(&bfqd->idle_slice_timer)) { + /* + * If we get here: 1) at least a new request + * has arrived but we have not disabled the + * timer because the request was too small, + * 2) then the block layer has unplugged + * the device, causing the dispatch to be + * invoked. + * + * Since the device is unplugged, now the + * requests are probably large enough to + * provide a reasonable throughput. + * So we disable idling. + */ + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + } + if (new_bfqq == NULL) + goto keep_queue; + else + goto expire; + } + } + + /* + * No requests pending. However, if the in-service queue is idling + * for a new request, or has requests waiting for a completion and + * may idle after their completion, then keep it anyway. + */ + if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || + (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { + bfqq = NULL; + goto keep_queue; + } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { + /* + * Expiring the queue because there is a close cooperator, + * cancel timer. + */ + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + } + + reason = BFQ_BFQQ_NO_MORE_REQUESTS; +expire: + bfq_bfqq_expire(bfqd, bfqq, 0, reason); +new_queue: + bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); + bfq_log(bfqd, "select_queue: new queue %d returned", + bfqq != NULL ? bfqq->pid : 0); +keep_queue: + return bfqq; +} + +static void bfq_update_wr_data(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (bfqq->wr_coeff > 1) { /* queue is being boosted */ + struct bfq_entity *entity = &bfqq->entity; + + bfq_log_bfqq(bfqd, bfqq, + "raising period dur %u/%u msec, old coeff %u, w %d(%d)", + jiffies_to_msecs(jiffies - + bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time), + bfqq->wr_coeff, + bfqq->entity.weight, bfqq->entity.orig_weight); + + BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != + entity->orig_weight * bfqq->wr_coeff); + if (entity->ioprio_changed) + bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); + /* + * If the queue was activated in a burst, or + * too much time has elapsed from the beginning + * of this weight-raising, then end weight raising. + */ + if (bfq_bfqq_in_large_burst(bfqq) || + time_is_before_jiffies(bfqq->last_wr_start_finish + + bfqq->wr_cur_max_time)) { + bfqq->last_wr_start_finish = jiffies; + bfq_log_bfqq(bfqd, bfqq, + "wrais ending at %lu, rais_max_time %u", + bfqq->last_wr_start_finish, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + bfq_bfqq_end_wr(bfqq); + __bfq_entity_update_weight_prio( + bfq_entity_service_tree(entity), + entity); + } + } +} + +/* + * Dispatch one request from bfqq, moving it to the request queue + * dispatch list. + */ +static int bfq_dispatch_request(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + int dispatched = 0; + struct request *rq; + unsigned long service_to_charge; + + BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); + + /* Follow expired path, else get first next available. */ + rq = bfq_check_fifo(bfqq); + if (rq == NULL) + rq = bfqq->next_rq; + service_to_charge = bfq_serv_to_charge(rq, bfqq); + + if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { + /* + * This may happen if the next rq is chosen in fifo order + * instead of sector order. The budget is properly + * dimensioned to be always sufficient to serve the next + * request only if it is chosen in sector order. The reason + * is that it would be quite inefficient and little useful + * to always make sure that the budget is large enough to + * serve even the possible next rq in fifo order. + * In fact, requests are seldom served in fifo order. + * + * Expire the queue for budget exhaustion, and make sure + * that the next act_budget is enough to serve the next + * request, even if it comes from the fifo expired path. + */ + bfqq->next_rq = rq; + /* + * Since this dispatch is failed, make sure that + * a new one will be performed + */ + if (!bfqd->rq_in_driver) + bfq_schedule_dispatch(bfqd); + goto expire; + } + + /* Finally, insert request into driver dispatch list. */ + bfq_bfqq_served(bfqq, service_to_charge); + bfq_dispatch_insert(bfqd->queue, rq); + + bfq_update_wr_data(bfqd, bfqq); + + bfq_log_bfqq(bfqd, bfqq, + "dispatched %u sec req (%llu), budg left %lu", + blk_rq_sectors(rq), + (long long unsigned)blk_rq_pos(rq), + bfq_bfqq_budget_left(bfqq)); + + dispatched++; + + if (bfqd->in_service_bic == NULL) { + atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); + bfqd->in_service_bic = RQ_BIC(rq); + } + + if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && + dispatched >= bfqd->bfq_max_budget_async_rq) || + bfq_class_idle(bfqq))) + goto expire; + + return dispatched; + +expire: + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); + return dispatched; +} + +static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) +{ + int dispatched = 0; + + while (bfqq->next_rq != NULL) { + bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); + dispatched++; + } + + BUG_ON(!list_empty(&bfqq->fifo)); + return dispatched; +} + +/* + * Drain our current requests. + * Used for barriers and when switching io schedulers on-the-fly. + */ +static int bfq_forced_dispatch(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq, *n; + struct bfq_service_tree *st; + int dispatched = 0; + + bfqq = bfqd->in_service_queue; + if (bfqq != NULL) + __bfq_bfqq_expire(bfqd, bfqq); + + /* + * Loop through classes, and be careful to leave the scheduler + * in a consistent state, as feedback mechanisms and vtime + * updates cannot be disabled during the process. + */ + list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { + st = bfq_entity_service_tree(&bfqq->entity); + + dispatched += __bfq_forced_dispatch_bfqq(bfqq); + bfqq->max_budget = bfq_max_budget(bfqd); + + bfq_forget_idle(st); + } + + BUG_ON(bfqd->busy_queues != 0); + + return dispatched; +} + +static int bfq_dispatch_requests(struct request_queue *q, int force) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_queue *bfqq; + int max_dispatch; + + bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); + if (bfqd->busy_queues == 0) + return 0; + + if (unlikely(force)) + return bfq_forced_dispatch(bfqd); + + bfqq = bfq_select_queue(bfqd); + if (bfqq == NULL) + return 0; + + if (bfq_class_idle(bfqq)) + max_dispatch = 1; + + if (!bfq_bfqq_sync(bfqq)) + max_dispatch = bfqd->bfq_max_budget_async_rq; + + if (!bfq_bfqq_sync(bfqq) && bfqq->dispatched >= max_dispatch) { + if (bfqd->busy_queues > 1) + return 0; + if (bfqq->dispatched >= 4 * max_dispatch) + return 0; + } + + if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) + return 0; + + bfq_clear_bfqq_wait_request(bfqq); + BUG_ON(timer_pending(&bfqd->idle_slice_timer)); + + if (!bfq_dispatch_request(bfqd, bfqq)) + return 0; + + bfq_log_bfqq(bfqd, bfqq, "dispatched %s request", + bfq_bfqq_sync(bfqq) ? "sync" : "async"); + + return 1; +} + +/* + * Task holds one reference to the queue, dropped when task exits. Each rq + * in-flight on this queue also holds a reference, dropped when rq is freed. + * + * Queue lock must be held here. + */ +static void bfq_put_queue(struct bfq_queue *bfqq) +{ + struct bfq_data *bfqd = bfqq->bfqd; + + BUG_ON(atomic_read(&bfqq->ref) <= 0); + + bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, + atomic_read(&bfqq->ref)); + if (!atomic_dec_and_test(&bfqq->ref)) + return; + + BUG_ON(rb_first(&bfqq->sort_list) != NULL); + BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); + BUG_ON(bfqq->entity.tree != NULL); + BUG_ON(bfq_bfqq_busy(bfqq)); + BUG_ON(bfqd->in_service_queue == bfqq); + + if (bfq_bfqq_sync(bfqq)) + /* + * The fact that this queue is being destroyed does not + * invalidate the fact that this queue may have been + * activated during the current burst. As a consequence, + * although the queue does not exist anymore, and hence + * needs to be removed from the burst list if there, + * the burst size has not to be decremented. + */ + hlist_del_init(&bfqq->burst_list_node); + + bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); + + kmem_cache_free(bfq_pool, bfqq); +} + +static void bfq_put_cooperator(struct bfq_queue *bfqq) +{ + struct bfq_queue *__bfqq, *next; + + /* + * If this queue was scheduled to merge with another queue, be + * sure to drop the reference taken on that queue (and others in + * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. + */ + __bfqq = bfqq->new_bfqq; + while (__bfqq) { + if (__bfqq == bfqq) + break; + next = __bfqq->new_bfqq; + bfq_put_queue(__bfqq); + __bfqq = next; + } +} + +static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + if (bfqq == bfqd->in_service_queue) { + __bfq_bfqq_expire(bfqd, bfqq); + bfq_schedule_dispatch(bfqd); + } + + bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, + atomic_read(&bfqq->ref)); + + bfq_put_cooperator(bfqq); + + bfq_put_queue(bfqq); +} + +static inline void bfq_init_icq(struct io_cq *icq) +{ + struct bfq_io_cq *bic = icq_to_bic(icq); + + bic->ttime.last_end_request = jiffies; +} + +static void bfq_exit_icq(struct io_cq *icq) +{ + struct bfq_io_cq *bic = icq_to_bic(icq); + struct bfq_data *bfqd = bic_to_bfqd(bic); + + if (bic->bfqq[BLK_RW_ASYNC]) { + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); + bic->bfqq[BLK_RW_ASYNC] = NULL; + } + + if (bic->bfqq[BLK_RW_SYNC]) { + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); + bic->bfqq[BLK_RW_SYNC] = NULL; + } +} + +/* + * Update the entity prio values; note that the new values will not + * be used until the next (re)activation. + */ +static void bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) +{ + struct task_struct *tsk = current; + int ioprio_class; + + ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); + switch (ioprio_class) { + default: + dev_err(bfqq->bfqd->queue->backing_dev_info.dev, + "bfq: bad prio class %d\n", ioprio_class); + case IOPRIO_CLASS_NONE: + /* + * No prio set, inherit CPU scheduling settings. + */ + bfqq->entity.new_ioprio = task_nice_ioprio(tsk); + bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); + break; + case IOPRIO_CLASS_RT: + bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; + break; + case IOPRIO_CLASS_BE: + bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; + break; + case IOPRIO_CLASS_IDLE: + bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; + bfqq->entity.new_ioprio = 7; + bfq_clear_bfqq_idle_window(bfqq); + break; + } + + if (bfqq->entity.new_ioprio < 0 || + bfqq->entity.new_ioprio >= IOPRIO_BE_NR) { + printk(KERN_CRIT "bfq_set_next_ioprio_data: new_ioprio %d\n", + bfqq->entity.new_ioprio); + BUG(); + } + + bfqq->entity.new_weight = bfq_ioprio_to_weight(bfqq->entity.new_ioprio); + bfqq->entity.ioprio_changed = 1; +} + +static void bfq_check_ioprio_change(struct bfq_io_cq *bic) +{ + struct bfq_data *bfqd; + struct bfq_queue *bfqq, *new_bfqq; + struct bfq_group *bfqg; + unsigned long uninitialized_var(flags); + int ioprio = bic->icq.ioc->ioprio; + + bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), + &flags); + /* + * This condition may trigger on a newly created bic, be sure to + * drop the lock before returning. + */ + if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) + goto out; + + bic->ioprio = ioprio; + + bfqq = bic->bfqq[BLK_RW_ASYNC]; + if (bfqq != NULL) { + bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, + sched_data); + new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, + GFP_ATOMIC); + if (new_bfqq != NULL) { + bic->bfqq[BLK_RW_ASYNC] = new_bfqq; + bfq_log_bfqq(bfqd, bfqq, + "check_ioprio_change: bfqq %p %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + } + } + + bfqq = bic->bfqq[BLK_RW_SYNC]; + if (bfqq != NULL) + bfq_set_next_ioprio_data(bfqq, bic); + +out: + bfq_put_bfqd_unlock(bfqd, &flags); +} + +static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct bfq_io_cq *bic, pid_t pid, int is_sync) +{ + RB_CLEAR_NODE(&bfqq->entity.rb_node); + INIT_LIST_HEAD(&bfqq->fifo); + INIT_HLIST_NODE(&bfqq->burst_list_node); + + atomic_set(&bfqq->ref, 0); + bfqq->bfqd = bfqd; + + if (bic) + bfq_set_next_ioprio_data(bfqq, bic); + + if (is_sync) { + if (!bfq_class_idle(bfqq)) + bfq_mark_bfqq_idle_window(bfqq); + bfq_mark_bfqq_sync(bfqq); + } + bfq_mark_bfqq_IO_bound(bfqq); + + /* Tentative initial value to trade off between thr and lat */ + bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; + bfqq->pid = pid; + + bfqq->wr_coeff = 1; + bfqq->last_wr_start_finish = 0; + /* + * Set to the value for which bfqq will not be deemed as + * soft rt when it becomes backlogged. + */ + bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); +} + +static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, + struct bfq_group *bfqg, + int is_sync, + struct bfq_io_cq *bic, + gfp_t gfp_mask) +{ + struct bfq_queue *bfqq, *new_bfqq = NULL; + +retry: + /* bic always exists here */ + bfqq = bic_to_bfqq(bic, is_sync); + + /* + * Always try a new alloc if we fall back to the OOM bfqq + * originally, since it should just be a temporary situation. + */ + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { + bfqq = NULL; + if (new_bfqq != NULL) { + bfqq = new_bfqq; + new_bfqq = NULL; + } else if (gfp_mask & __GFP_WAIT) { + spin_unlock_irq(bfqd->queue->queue_lock); + new_bfqq = kmem_cache_alloc_node(bfq_pool, + gfp_mask | __GFP_ZERO, + bfqd->queue->node); + spin_lock_irq(bfqd->queue->queue_lock); + if (new_bfqq != NULL) + goto retry; + } else { + bfqq = kmem_cache_alloc_node(bfq_pool, + gfp_mask | __GFP_ZERO, + bfqd->queue->node); + } + + if (bfqq != NULL) { + bfq_init_bfqq(bfqd, bfqq, bic, current->pid, + is_sync); + bfq_init_entity(&bfqq->entity, bfqg); + bfq_log_bfqq(bfqd, bfqq, "allocated"); + } else { + bfqq = &bfqd->oom_bfqq; + bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); + } + } + + if (new_bfqq != NULL) + kmem_cache_free(bfq_pool, new_bfqq); + + return bfqq; +} + +static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, + struct bfq_group *bfqg, + int ioprio_class, int ioprio) +{ + switch (ioprio_class) { + case IOPRIO_CLASS_RT: + return &bfqg->async_bfqq[0][ioprio]; + case IOPRIO_CLASS_NONE: + ioprio = IOPRIO_NORM; + /* fall through */ + case IOPRIO_CLASS_BE: + return &bfqg->async_bfqq[1][ioprio]; + case IOPRIO_CLASS_IDLE: + return &bfqg->async_idle_bfqq; + default: + BUG(); + } +} + +static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, + struct bfq_group *bfqg, int is_sync, + struct bfq_io_cq *bic, gfp_t gfp_mask) +{ + const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); + struct bfq_queue **async_bfqq = NULL; + struct bfq_queue *bfqq = NULL; + + if (!is_sync) { + async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, + ioprio); + bfqq = *async_bfqq; + } + + if (bfqq == NULL) + bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); + + /* + * Pin the queue now that it's allocated, scheduler exit will + * prune it. + */ + if (!is_sync && *async_bfqq == NULL) { + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", + bfqq, atomic_read(&bfqq->ref)); + *async_bfqq = bfqq; + } + + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, + atomic_read(&bfqq->ref)); + return bfqq; +} + +static void bfq_update_io_thinktime(struct bfq_data *bfqd, + struct bfq_io_cq *bic) +{ + unsigned long elapsed = jiffies - bic->ttime.last_end_request; + unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); + + bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; + bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; + bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / + bic->ttime.ttime_samples; +} + +static void bfq_update_io_seektime(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct request *rq) +{ + sector_t sdist; + u64 total; + + if (bfqq->last_request_pos < blk_rq_pos(rq)) + sdist = blk_rq_pos(rq) - bfqq->last_request_pos; + else + sdist = bfqq->last_request_pos - blk_rq_pos(rq); + + /* + * Don't allow the seek distance to get too large from the + * odd fragment, pagein, etc. + */ + if (bfqq->seek_samples == 0) /* first request, not really a seek */ + sdist = 0; + else if (bfqq->seek_samples <= 60) /* second & third seek */ + sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); + else + sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); + + bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; + bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; + total = bfqq->seek_total + (bfqq->seek_samples/2); + do_div(total, bfqq->seek_samples); + bfqq->seek_mean = (sector_t)total; + + bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, + (u64)bfqq->seek_mean); +} + +/* + * Disable idle window if the process thinks too long or seeks so much that + * it doesn't matter. + */ +static void bfq_update_idle_window(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct bfq_io_cq *bic) +{ + int enable_idle; + + /* Don't idle for async or idle io prio class. */ + if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) + return; + + enable_idle = bfq_bfqq_idle_window(bfqq); + + if (atomic_read(&bic->icq.ioc->active_ref) == 0 || + bfqd->bfq_slice_idle == 0 || + (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && + bfqq->wr_coeff == 1)) + enable_idle = 0; + else if (bfq_sample_valid(bic->ttime.ttime_samples)) { + if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && + bfqq->wr_coeff == 1) + enable_idle = 0; + else + enable_idle = 1; + } + bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", + enable_idle); + + if (enable_idle) + bfq_mark_bfqq_idle_window(bfqq); + else + bfq_clear_bfqq_idle_window(bfqq); +} + +/* + * Called when a new fs request (rq) is added to bfqq. Check if there's + * something we should do about it. + */ +static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct request *rq) +{ + struct bfq_io_cq *bic = RQ_BIC(rq); + + if (rq->cmd_flags & REQ_META) + bfqq->meta_pending++; + + bfq_update_io_thinktime(bfqd, bic); + bfq_update_io_seektime(bfqd, bfqq, rq); + if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { + bfq_clear_bfqq_constantly_seeky(bfqq); + if (!blk_queue_nonrot(bfqd->queue)) { + BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); + bfqd->const_seeky_busy_in_flight_queues--; + } + } + if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || + !BFQQ_SEEKY(bfqq)) + bfq_update_idle_window(bfqd, bfqq, bic); + + bfq_log_bfqq(bfqd, bfqq, + "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", + bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), + (long long unsigned)bfqq->seek_mean); + + bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); + + if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { + int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && + blk_rq_sectors(rq) < 32; + int budget_timeout = bfq_bfqq_budget_timeout(bfqq); + + /* + * There is just this request queued: if the request + * is small and the queue is not to be expired, then + * just exit. + * + * In this way, if the disk is being idled to wait for + * a new request from the in-service queue, we avoid + * unplugging the device and committing the disk to serve + * just a small request. On the contrary, we wait for + * the block layer to decide when to unplug the device: + * hopefully, new requests will be merged to this one + * quickly, then the device will be unplugged and + * larger requests will be dispatched. + */ + if (small_req && !budget_timeout) + return; + + /* + * A large enough request arrived, or the queue is to + * be expired: in both cases disk idling is to be + * stopped, so clear wait_request flag and reset + * timer. + */ + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + + /* + * The queue is not empty, because a new request just + * arrived. Hence we can safely expire the queue, in + * case of budget timeout, without risking that the + * timestamps of the queue are not updated correctly. + * See [1] for more details. + */ + if (budget_timeout) + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); + + /* + * Let the request rip immediately, or let a new queue be + * selected if bfqq has just been expired. + */ + __blk_run_queue(bfqd->queue); + } +} + +static void bfq_insert_request(struct request_queue *q, struct request *rq) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_queue *bfqq = RQ_BFQQ(rq); + + assert_spin_locked(bfqd->queue->queue_lock); + + bfq_add_request(rq); + + rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; + list_add_tail(&rq->queuelist, &bfqq->fifo); + + bfq_rq_enqueued(bfqd, bfqq, rq); +} + +static void bfq_update_hw_tag(struct bfq_data *bfqd) +{ + bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, + bfqd->rq_in_driver); + + if (bfqd->hw_tag == 1) + return; + + /* + * This sample is valid if the number of outstanding requests + * is large enough to allow a queueing behavior. Note that the + * sum is not exact, as it's not taking into account deactivated + * requests. + */ + if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) + return; + + if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) + return; + + bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; + bfqd->max_rq_in_driver = 0; + bfqd->hw_tag_samples = 0; +} + +static void bfq_completed_request(struct request_queue *q, struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_data *bfqd = bfqq->bfqd; + bool sync = bfq_bfqq_sync(bfqq); + + bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", + blk_rq_sectors(rq), sync); + + bfq_update_hw_tag(bfqd); + + BUG_ON(!bfqd->rq_in_driver); + BUG_ON(!bfqq->dispatched); + bfqd->rq_in_driver--; + bfqq->dispatched--; + + if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { + bfq_weights_tree_remove(bfqd, &bfqq->entity, + &bfqd->queue_weights_tree); + if (!blk_queue_nonrot(bfqd->queue)) { + BUG_ON(!bfqd->busy_in_flight_queues); + bfqd->busy_in_flight_queues--; + if (bfq_bfqq_constantly_seeky(bfqq)) { + BUG_ON(!bfqd-> + const_seeky_busy_in_flight_queues); + bfqd->const_seeky_busy_in_flight_queues--; + } + } + } + + if (sync) { + bfqd->sync_flight--; + RQ_BIC(rq)->ttime.last_end_request = jiffies; + } + + /* + * If we are waiting to discover whether the request pattern of the + * task associated with the queue is actually isochronous, and + * both requisites for this condition to hold are satisfied, then + * compute soft_rt_next_start (see the comments to the function + * bfq_bfqq_softrt_next_start()). + */ + if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && + RB_EMPTY_ROOT(&bfqq->sort_list)) + bfqq->soft_rt_next_start = + bfq_bfqq_softrt_next_start(bfqd, bfqq); + + /* + * If this is the in-service queue, check if it needs to be expired, + * or if we want to idle in case it has no pending requests. + */ + if (bfqd->in_service_queue == bfqq) { + if (bfq_bfqq_budget_new(bfqq)) + bfq_set_budget_timeout(bfqd); + + if (bfq_bfqq_must_idle(bfqq)) { + bfq_arm_slice_timer(bfqd); + goto out; + } else if (bfq_may_expire_for_budg_timeout(bfqq)) + bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); + else if (RB_EMPTY_ROOT(&bfqq->sort_list) && + (bfqq->dispatched == 0 || + !bfq_bfqq_must_not_expire(bfqq))) + bfq_bfqq_expire(bfqd, bfqq, 0, + BFQ_BFQQ_NO_MORE_REQUESTS); + } + + if (!bfqd->rq_in_driver) + bfq_schedule_dispatch(bfqd); + +out: + return; +} + +static inline int __bfq_may_queue(struct bfq_queue *bfqq) +{ + if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { + bfq_clear_bfqq_must_alloc(bfqq); + return ELV_MQUEUE_MUST; + } + + return ELV_MQUEUE_MAY; +} + +static int bfq_may_queue(struct request_queue *q, int rw) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct task_struct *tsk = current; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq; + + /* + * Don't force setup of a queue from here, as a call to may_queue + * does not necessarily imply that a request actually will be + * queued. So just lookup a possibly existing queue, or return + * 'may queue' if that fails. + */ + bic = bfq_bic_lookup(bfqd, tsk->io_context); + if (bic == NULL) + return ELV_MQUEUE_MAY; + + bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); + if (bfqq != NULL) + return __bfq_may_queue(bfqq); + + return ELV_MQUEUE_MAY; +} + +/* + * Queue lock held here. + */ +static void bfq_put_request(struct request *rq) +{ + struct bfq_queue *bfqq = RQ_BFQQ(rq); + + if (bfqq != NULL) { + const int rw = rq_data_dir(rq); + + BUG_ON(!bfqq->allocated[rw]); + bfqq->allocated[rw]--; + + rq->elv.priv[0] = NULL; + rq->elv.priv[1] = NULL; + + bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + } +} + +static struct bfq_queue * +bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + struct bfq_queue *bfqq) +{ + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", + (long unsigned)bfqq->new_bfqq->pid); + bic_set_bfqq(bic, bfqq->new_bfqq, 1); + bfq_mark_bfqq_coop(bfqq->new_bfqq); + bfq_put_queue(bfqq); + return bic_to_bfqq(bic, 1); +} + +/* + * Returns NULL if a new bfqq should be allocated, or the old bfqq if this + * was the last process referring to said bfqq. + */ +static struct bfq_queue * +bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) +{ + bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); + if (bfqq_process_refs(bfqq) == 1) { + bfqq->pid = current->pid; + bfq_clear_bfqq_coop(bfqq); + bfq_clear_bfqq_split_coop(bfqq); + return bfqq; + } + + bic_set_bfqq(bic, NULL, 1); + + bfq_put_cooperator(bfqq); + + bfq_put_queue(bfqq); + return NULL; +} + +/* + * Allocate bfq data structures associated with this request. + */ +static int bfq_set_request(struct request_queue *q, struct request *rq, + struct bio *bio, gfp_t gfp_mask) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); + const int rw = rq_data_dir(rq); + const int is_sync = rq_is_sync(rq); + struct bfq_queue *bfqq; + struct bfq_group *bfqg; + unsigned long flags; + + might_sleep_if(gfp_mask & __GFP_WAIT); + + bfq_check_ioprio_change(bic); + + spin_lock_irqsave(q->queue_lock, flags); + + if (bic == NULL) + goto queue_fail; + + bfqg = bfq_bic_update_cgroup(bic); + +new_queue: + bfqq = bic_to_bfqq(bic, is_sync); + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { + bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); + bic_set_bfqq(bic, bfqq, is_sync); + } else { + /* + * If the queue was seeky for too long, break it apart. + */ + if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { + bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); + bfqq = bfq_split_bfqq(bic, bfqq); + if (!bfqq) + goto new_queue; + } + + /* + * Check to see if this queue is scheduled to merge with + * another closely cooperating queue. The merging of queues + * happens here as it must be done in process context. + * The reference on new_bfqq was taken in merge_bfqqs. + */ + if (bfqq->new_bfqq != NULL) + bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); + } + + bfqq->allocated[rw]++; + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, + atomic_read(&bfqq->ref)); + + rq->elv.priv[0] = bic; + rq->elv.priv[1] = bfqq; + + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; + +queue_fail: + bfq_schedule_dispatch(bfqd); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 1; +} + +static void bfq_kick_queue(struct work_struct *work) +{ + struct bfq_data *bfqd = + container_of(work, struct bfq_data, unplug_work); + struct request_queue *q = bfqd->queue; + + spin_lock_irq(q->queue_lock); + __blk_run_queue(q); + spin_unlock_irq(q->queue_lock); +} + +/* + * Handler of the expiration of the timer running if the in-service queue + * is idling inside its time slice. + */ +static void bfq_idle_slice_timer(unsigned long data) +{ + struct bfq_data *bfqd = (struct bfq_data *)data; + struct bfq_queue *bfqq; + unsigned long flags; + enum bfqq_expiration reason; + + spin_lock_irqsave(bfqd->queue->queue_lock, flags); + + bfqq = bfqd->in_service_queue; + /* + * Theoretical race here: the in-service queue can be NULL or + * different from the queue that was idling if the timer handler + * spins on the queue_lock and a new request arrives for the + * current queue and there is a full dispatch cycle that changes + * the in-service queue. This can hardly happen, but in the worst + * case we just expire a queue too early. + */ + if (bfqq != NULL) { + bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); + if (bfq_bfqq_budget_timeout(bfqq)) + /* + * Also here the queue can be safely expired + * for budget timeout without wasting + * guarantees + */ + reason = BFQ_BFQQ_BUDGET_TIMEOUT; + else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) + /* + * The queue may not be empty upon timer expiration, + * because we may not disable the timer when the + * first request of the in-service queue arrives + * during disk idling. + */ + reason = BFQ_BFQQ_TOO_IDLE; + else + goto schedule_dispatch; + + bfq_bfqq_expire(bfqd, bfqq, 1, reason); + } + +schedule_dispatch: + bfq_schedule_dispatch(bfqd); + + spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); +} + +static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) +{ + del_timer_sync(&bfqd->idle_slice_timer); + cancel_work_sync(&bfqd->unplug_work); +} + +static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, + struct bfq_queue **bfqq_ptr) +{ + struct bfq_group *root_group = bfqd->root_group; + struct bfq_queue *bfqq = *bfqq_ptr; + + bfq_log(bfqd, "put_async_bfqq: %p", bfqq); + if (bfqq != NULL) { + bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); + bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + *bfqq_ptr = NULL; + } +} + +/* + * Release all the bfqg references to its async queues. If we are + * deallocating the group these queues may still contain requests, so + * we reparent them to the root cgroup (i.e., the only one that will + * exist for sure until all the requests on a device are gone). + */ +static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < IOPRIO_BE_NR; j++) + __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); + + __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); +} + +static void bfq_exit_queue(struct elevator_queue *e) +{ + struct bfq_data *bfqd = e->elevator_data; + struct request_queue *q = bfqd->queue; + struct bfq_queue *bfqq, *n; + + bfq_shutdown_timer_wq(bfqd); + + spin_lock_irq(q->queue_lock); + + BUG_ON(bfqd->in_service_queue != NULL); + list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) + bfq_deactivate_bfqq(bfqd, bfqq, 0); + + bfq_disconnect_groups(bfqd); + spin_unlock_irq(q->queue_lock); + + bfq_shutdown_timer_wq(bfqd); + + synchronize_rcu(); + + BUG_ON(timer_pending(&bfqd->idle_slice_timer)); + + bfq_free_root_group(bfqd); + kfree(bfqd); +} + +static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) +{ + struct bfq_group *bfqg; + struct bfq_data *bfqd; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (eq == NULL) + return -ENOMEM; + + bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); + if (bfqd == NULL) { + kobject_put(&eq->kobj); + return -ENOMEM; + } + eq->elevator_data = bfqd; + + /* + * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. + * Grab a permanent reference to it, so that the normal code flow + * will not attempt to free it. + */ + bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, NULL, 1, 0); + atomic_inc(&bfqd->oom_bfqq.ref); + bfqd->oom_bfqq.entity.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO; + bfqd->oom_bfqq.entity.new_ioprio_class = IOPRIO_CLASS_BE; + bfqd->oom_bfqq.entity.new_weight = + bfq_ioprio_to_weight(bfqd->oom_bfqq.entity.new_ioprio); + /* + * Trigger weight initialization, according to ioprio, at the + * oom_bfqq's first activation. The oom_bfqq's ioprio and ioprio + * class won't be changed any more. + */ + bfqd->oom_bfqq.entity.ioprio_changed = 1; + + bfqd->queue = q; + + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); + + bfqg = bfq_alloc_root_group(bfqd, q->node); + if (bfqg == NULL) { + kfree(bfqd); + kobject_put(&eq->kobj); + return -ENOMEM; + } + + bfqd->root_group = bfqg; + bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group); +#ifdef CONFIG_CGROUP_BFQIO + bfqd->active_numerous_groups = 0; +#endif + + init_timer(&bfqd->idle_slice_timer); + bfqd->idle_slice_timer.function = bfq_idle_slice_timer; + bfqd->idle_slice_timer.data = (unsigned long)bfqd; + + bfqd->rq_pos_tree = RB_ROOT; + bfqd->queue_weights_tree = RB_ROOT; + bfqd->group_weights_tree = RB_ROOT; + + INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); + + INIT_LIST_HEAD(&bfqd->active_list); + INIT_LIST_HEAD(&bfqd->idle_list); + INIT_HLIST_HEAD(&bfqd->burst_list); + + bfqd->hw_tag = -1; + + bfqd->bfq_max_budget = bfq_default_max_budget; + + bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; + bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; + bfqd->bfq_back_max = bfq_back_max; + bfqd->bfq_back_penalty = bfq_back_penalty; + bfqd->bfq_slice_idle = bfq_slice_idle; + bfqd->bfq_class_idle_last_service = 0; + bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; + bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; + bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; + + bfqd->bfq_coop_thresh = 2; + bfqd->bfq_failed_cooperations = 7000; + bfqd->bfq_requests_within_timer = 120; + + bfqd->bfq_large_burst_thresh = 11; + bfqd->bfq_burst_interval = msecs_to_jiffies(500); + + bfqd->low_latency = true; + + bfqd->bfq_wr_coeff = 20; + bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); + bfqd->bfq_wr_max_time = 0; + bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); + bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); + bfqd->bfq_wr_max_softrt_rate = 7000; /* + * Approximate rate required + * to playback or record a + * high-definition compressed + * video. + */ + bfqd->wr_busy_queues = 0; + bfqd->busy_in_flight_queues = 0; + bfqd->const_seeky_busy_in_flight_queues = 0; + + /* + * Begin by assuming, optimistically, that the device peak rate is + * equal to the highest reference rate. + */ + bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * + T_fast[blk_queue_nonrot(bfqd->queue)]; + bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; + bfqd->device_speed = BFQ_BFQD_FAST; + + return 0; +} + +static void bfq_slab_kill(void) +{ + if (bfq_pool != NULL) + kmem_cache_destroy(bfq_pool); +} + +static int __init bfq_slab_setup(void) +{ + bfq_pool = KMEM_CACHE(bfq_queue, 0); + if (bfq_pool == NULL) + return -ENOMEM; + return 0; +} + +static ssize_t bfq_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t bfq_var_store(unsigned long *var, const char *page, + size_t count) +{ + unsigned long new_val; + int ret = kstrtoul(page, 10, &new_val); + + if (ret == 0) + *var = new_val; + + return count; +} + +static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) +{ + struct bfq_data *bfqd = e->elevator_data; + return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? + jiffies_to_msecs(bfqd->bfq_wr_max_time) : + jiffies_to_msecs(bfq_wr_duration(bfqd))); +} + +static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) +{ + struct bfq_queue *bfqq; + struct bfq_data *bfqd = e->elevator_data; + ssize_t num_char = 0; + + num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", + bfqd->queued); + + spin_lock_irq(bfqd->queue->queue_lock); + + num_char += sprintf(page + num_char, "Active:\n"); + list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { + num_char += sprintf(page + num_char, + "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", + bfqq->pid, + bfqq->entity.weight, + bfqq->queued[0], + bfqq->queued[1], + jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } + + num_char += sprintf(page + num_char, "Idle:\n"); + list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { + num_char += sprintf(page + num_char, + "pid%d: weight %hu, dur %d/%u\n", + bfqq->pid, + bfqq->entity.weight, + jiffies_to_msecs(jiffies - + bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time)); + } + + spin_unlock_irq(bfqd->queue->queue_lock); + + return num_char; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct bfq_data *bfqd = e->elevator_data; \ + unsigned int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return bfq_var_show(__data, (page)); \ +} +SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); +SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); +SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); +SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); +SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); +SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); +SHOW_FUNCTION(bfq_max_budget_async_rq_show, + bfqd->bfq_max_budget_async_rq, 0); +SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); +SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); +SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); +SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); +SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); +SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); +SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, + 1); +SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t \ +__FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct bfq_data *bfqd = e->elevator_data; \ + unsigned long uninitialized_var(__data); \ + int ret = bfq_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, + INT_MAX, 1); +STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, + INT_MAX, 1); +STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); +STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, + INT_MAX, 0); +STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); +STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, + 1, INT_MAX, 0); +STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, + INT_MAX, 1); +STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); +STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); +STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, + 1); +STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, + INT_MAX, 1); +STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, + &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); +STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, + INT_MAX, 0); +#undef STORE_FUNCTION + +/* do nothing for the moment */ +static ssize_t bfq_weights_store(struct elevator_queue *e, + const char *page, size_t count) +{ + return count; +} + +static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) +{ + u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); + + if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) + return bfq_calc_max_budget(bfqd->peak_rate, timeout); + else + return bfq_default_max_budget; +} + +static ssize_t bfq_max_budget_store(struct elevator_queue *e, + const char *page, size_t count) +{ + struct bfq_data *bfqd = e->elevator_data; + unsigned long uninitialized_var(__data); + int ret = bfq_var_store(&__data, (page), count); + + if (__data == 0) + bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); + else { + if (__data > INT_MAX) + __data = INT_MAX; + bfqd->bfq_max_budget = __data; + } + + bfqd->bfq_user_max_budget = __data; + + return ret; +} + +static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, + const char *page, size_t count) +{ + struct bfq_data *bfqd = e->elevator_data; + unsigned long uninitialized_var(__data); + int ret = bfq_var_store(&__data, (page), count); + + if (__data < 1) + __data = 1; + else if (__data > INT_MAX) + __data = INT_MAX; + + bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); + if (bfqd->bfq_user_max_budget == 0) + bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); + + return ret; +} + +static ssize_t bfq_low_latency_store(struct elevator_queue *e, + const char *page, size_t count) +{ + struct bfq_data *bfqd = e->elevator_data; + unsigned long uninitialized_var(__data); + int ret = bfq_var_store(&__data, (page), count); + + if (__data > 1) + __data = 1; + if (__data == 0 && bfqd->low_latency != 0) + bfq_end_wr(bfqd); + bfqd->low_latency = __data; + + return ret; +} + +#define BFQ_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) + +static struct elv_fs_entry bfq_attrs[] = { + BFQ_ATTR(fifo_expire_sync), + BFQ_ATTR(fifo_expire_async), + BFQ_ATTR(back_seek_max), + BFQ_ATTR(back_seek_penalty), + BFQ_ATTR(slice_idle), + BFQ_ATTR(max_budget), + BFQ_ATTR(max_budget_async_rq), + BFQ_ATTR(timeout_sync), + BFQ_ATTR(timeout_async), + BFQ_ATTR(low_latency), + BFQ_ATTR(wr_coeff), + BFQ_ATTR(wr_max_time), + BFQ_ATTR(wr_rt_max_time), + BFQ_ATTR(wr_min_idle_time), + BFQ_ATTR(wr_min_inter_arr_async), + BFQ_ATTR(wr_max_softrt_rate), + BFQ_ATTR(weights), + __ATTR_NULL +}; + +static struct elevator_type iosched_bfq = { + .ops = { + .elevator_merge_fn = bfq_merge, + .elevator_merged_fn = bfq_merged_request, + .elevator_merge_req_fn = bfq_merged_requests, + .elevator_allow_merge_fn = bfq_allow_merge, + .elevator_dispatch_fn = bfq_dispatch_requests, + .elevator_add_req_fn = bfq_insert_request, + .elevator_activate_req_fn = bfq_activate_request, + .elevator_deactivate_req_fn = bfq_deactivate_request, + .elevator_completed_req_fn = bfq_completed_request, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_init_icq_fn = bfq_init_icq, + .elevator_exit_icq_fn = bfq_exit_icq, + .elevator_set_req_fn = bfq_set_request, + .elevator_put_req_fn = bfq_put_request, + .elevator_may_queue_fn = bfq_may_queue, + .elevator_init_fn = bfq_init_queue, + .elevator_exit_fn = bfq_exit_queue, + }, + .icq_size = sizeof(struct bfq_io_cq), + .icq_align = __alignof__(struct bfq_io_cq), + .elevator_attrs = bfq_attrs, + .elevator_name = "bfq", + .elevator_owner = THIS_MODULE, +}; + +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; + + if (bfq_slab_setup()) + return -ENOMEM; + + /* + * Times to load large popular applications for the typical systems + * installed on the reference devices (see the comments before the + * definitions of the two arrays). + */ + T_slow[0] = msecs_to_jiffies(2600); + T_slow[1] = msecs_to_jiffies(1000); + T_fast[0] = msecs_to_jiffies(5500); + T_fast[1] = msecs_to_jiffies(2000); + + /* + * Thresholds that determine the switch between speed classes (see + * the comments before the definition of the array). + */ + device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; + device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; + + elv_register(&iosched_bfq); + pr_info("BFQ I/O-scheduler: v7r8"); + + return 0; +} + +static void __exit bfq_exit(void) +{ + elv_unregister(&iosched_bfq); + bfq_slab_kill(); +} + +module_init(bfq_init); +module_exit(bfq_exit); + +MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); +MODULE_LICENSE("GPL"); diff --git a/block/bfq-sched.c b/block/bfq-sched.c new file mode 100644 index 000000000000..c3430993ec94 --- /dev/null +++ b/block/bfq-sched.c @@ -0,0 +1,1208 @@ +/* + * BFQ: Hierarchical B-WF2Q+ scheduler. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + */ + +#ifdef CONFIG_CGROUP_BFQIO +#define for_each_entity(entity) \ + for (; entity != NULL; entity = entity->parent) + +#define for_each_entity_safe(entity, parent) \ + for (; entity && ({ parent = entity->parent; 1; }); entity = parent) + +static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, + int extract, + struct bfq_data *bfqd); + +static inline void bfq_update_budget(struct bfq_entity *next_in_service) +{ + struct bfq_entity *bfqg_entity; + struct bfq_group *bfqg; + struct bfq_sched_data *group_sd; + + BUG_ON(next_in_service == NULL); + + group_sd = next_in_service->sched_data; + + bfqg = container_of(group_sd, struct bfq_group, sched_data); + /* + * bfq_group's my_entity field is not NULL only if the group + * is not the root group. We must not touch the root entity + * as it must never become an in-service entity. + */ + bfqg_entity = bfqg->my_entity; + if (bfqg_entity != NULL) + bfqg_entity->budget = next_in_service->budget; +} + +static int bfq_update_next_in_service(struct bfq_sched_data *sd) +{ + struct bfq_entity *next_in_service; + + if (sd->in_service_entity != NULL) + /* will update/requeue at the end of service */ + return 0; + + /* + * NOTE: this can be improved in many ways, such as returning + * 1 (and thus propagating upwards the update) only when the + * budget changes, or caching the bfqq that will be scheduled + * next from this subtree. By now we worry more about + * correctness than about performance... + */ + next_in_service = bfq_lookup_next_entity(sd, 0, NULL); + sd->next_in_service = next_in_service; + + if (next_in_service != NULL) + bfq_update_budget(next_in_service); + + return 1; +} + +static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, + struct bfq_entity *entity) +{ + BUG_ON(sd->next_in_service != entity); +} +#else +#define for_each_entity(entity) \ + for (; entity != NULL; entity = NULL) + +#define for_each_entity_safe(entity, parent) \ + for (parent = NULL; entity != NULL; entity = parent) + +static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) +{ + return 0; +} + +static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, + struct bfq_entity *entity) +{ +} + +static inline void bfq_update_budget(struct bfq_entity *next_in_service) +{ +} +#endif + +/* + * Shift for timestamp calculations. This actually limits the maximum + * service allowed in one timestamp delta (small shift values increase it), + * the maximum total weight that can be used for the queues in the system + * (big shift values increase it), and the period of virtual time + * wraparounds. + */ +#define WFQ_SERVICE_SHIFT 22 + +/** + * bfq_gt - compare two timestamps. + * @a: first ts. + * @b: second ts. + * + * Return @a > @b, dealing with wrapping correctly. + */ +static inline int bfq_gt(u64 a, u64 b) +{ + return (s64)(a - b) > 0; +} + +static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = NULL; + + BUG_ON(entity == NULL); + + if (entity->my_sched_data == NULL) + bfqq = container_of(entity, struct bfq_queue, entity); + + return bfqq; +} + + +/** + * bfq_delta - map service into the virtual time domain. + * @service: amount of service. + * @weight: scale factor (weight of an entity or weight sum). + */ +static inline u64 bfq_delta(unsigned long service, + unsigned long weight) +{ + u64 d = (u64)service << WFQ_SERVICE_SHIFT; + + do_div(d, weight); + return d; +} + +/** + * bfq_calc_finish - assign the finish time to an entity. + * @entity: the entity to act upon. + * @service: the service to be charged to the entity. + */ +static inline void bfq_calc_finish(struct bfq_entity *entity, + unsigned long service) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + + BUG_ON(entity->weight == 0); + + entity->finish = entity->start + + bfq_delta(service, entity->weight); + + if (bfqq != NULL) { + bfq_log_bfqq(bfqq->bfqd, bfqq, + "calc_finish: serv %lu, w %d", + service, entity->weight); + bfq_log_bfqq(bfqq->bfqd, bfqq, + "calc_finish: start %llu, finish %llu, delta %llu", + entity->start, entity->finish, + bfq_delta(service, entity->weight)); + } +} + +/** + * bfq_entity_of - get an entity from a node. + * @node: the node field of the entity. + * + * Convert a node pointer to the relative entity. This is used only + * to simplify the logic of some functions and not as the generic + * conversion mechanism because, e.g., in the tree walking functions, + * the check for a %NULL value would be redundant. + */ +static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) +{ + struct bfq_entity *entity = NULL; + + if (node != NULL) + entity = rb_entry(node, struct bfq_entity, rb_node); + + return entity; +} + +/** + * bfq_extract - remove an entity from a tree. + * @root: the tree root. + * @entity: the entity to remove. + */ +static inline void bfq_extract(struct rb_root *root, + struct bfq_entity *entity) +{ + BUG_ON(entity->tree != root); + + entity->tree = NULL; + rb_erase(&entity->rb_node, root); +} + +/** + * bfq_idle_extract - extract an entity from the idle tree. + * @st: the service tree of the owning @entity. + * @entity: the entity being removed. + */ +static void bfq_idle_extract(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct rb_node *next; + + BUG_ON(entity->tree != &st->idle); + + if (entity == st->first_idle) { + next = rb_next(&entity->rb_node); + st->first_idle = bfq_entity_of(next); + } + + if (entity == st->last_idle) { + next = rb_prev(&entity->rb_node); + st->last_idle = bfq_entity_of(next); + } + + bfq_extract(&st->idle, entity); + + if (bfqq != NULL) + list_del(&bfqq->bfqq_list); +} + +/** + * bfq_insert - generic tree insertion. + * @root: tree root. + * @entity: entity to insert. + * + * This is used for the idle and the active tree, since they are both + * ordered by finish time. + */ +static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) +{ + struct bfq_entity *entry; + struct rb_node **node = &root->rb_node; + struct rb_node *parent = NULL; + + BUG_ON(entity->tree != NULL); + + while (*node != NULL) { + parent = *node; + entry = rb_entry(parent, struct bfq_entity, rb_node); + + if (bfq_gt(entry->finish, entity->finish)) + node = &parent->rb_left; + else + node = &parent->rb_right; + } + + rb_link_node(&entity->rb_node, parent, node); + rb_insert_color(&entity->rb_node, root); + + entity->tree = root; +} + +/** + * bfq_update_min - update the min_start field of a entity. + * @entity: the entity to update. + * @node: one of its children. + * + * This function is called when @entity may store an invalid value for + * min_start due to updates to the active tree. The function assumes + * that the subtree rooted at @node (which may be its left or its right + * child) has a valid min_start value. + */ +static inline void bfq_update_min(struct bfq_entity *entity, + struct rb_node *node) +{ + struct bfq_entity *child; + + if (node != NULL) { + child = rb_entry(node, struct bfq_entity, rb_node); + if (bfq_gt(entity->min_start, child->min_start)) + entity->min_start = child->min_start; + } +} + +/** + * bfq_update_active_node - recalculate min_start. + * @node: the node to update. + * + * @node may have changed position or one of its children may have moved, + * this function updates its min_start value. The left and right subtrees + * are assumed to hold a correct min_start value. + */ +static inline void bfq_update_active_node(struct rb_node *node) +{ + struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); + + entity->min_start = entity->start; + bfq_update_min(entity, node->rb_right); + bfq_update_min(entity, node->rb_left); +} + +/** + * bfq_update_active_tree - update min_start for the whole active tree. + * @node: the starting node. + * + * @node must be the deepest modified node after an update. This function + * updates its min_start using the values held by its children, assuming + * that they did not change, and then updates all the nodes that may have + * changed in the path to the root. The only nodes that may have changed + * are the ones in the path or their siblings. + */ +static void bfq_update_active_tree(struct rb_node *node) +{ + struct rb_node *parent; + +up: + bfq_update_active_node(node); + + parent = rb_parent(node); + if (parent == NULL) + return; + + if (node == parent->rb_left && parent->rb_right != NULL) + bfq_update_active_node(parent->rb_right); + else if (parent->rb_left != NULL) + bfq_update_active_node(parent->rb_left); + + node = parent; + goto up; +} + +static void bfq_weights_tree_add(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root); + +static void bfq_weights_tree_remove(struct bfq_data *bfqd, + struct bfq_entity *entity, + struct rb_root *root); + + +/** + * bfq_active_insert - insert an entity in the active tree of its + * group/device. + * @st: the service tree of the entity. + * @entity: the entity being inserted. + * + * The active tree is ordered by finish time, but an extra key is kept + * per each node, containing the minimum value for the start times of + * its children (and the node itself), so it's possible to search for + * the eligible node with the lowest finish time in logarithmic time. + */ +static void bfq_active_insert(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct rb_node *node = &entity->rb_node; +#ifdef CONFIG_CGROUP_BFQIO + struct bfq_sched_data *sd = NULL; + struct bfq_group *bfqg = NULL; + struct bfq_data *bfqd = NULL; +#endif + + bfq_insert(&st->active, entity); + + if (node->rb_left != NULL) + node = node->rb_left; + else if (node->rb_right != NULL) + node = node->rb_right; + + bfq_update_active_tree(node); + +#ifdef CONFIG_CGROUP_BFQIO + sd = entity->sched_data; + bfqg = container_of(sd, struct bfq_group, sched_data); + BUG_ON(!bfqg); + bfqd = (struct bfq_data *)bfqg->bfqd; +#endif + if (bfqq != NULL) + list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); +#ifdef CONFIG_CGROUP_BFQIO + else { /* bfq_group */ + BUG_ON(!bfqd); + bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); + } + if (bfqg != bfqd->root_group) { + BUG_ON(!bfqg); + BUG_ON(!bfqd); + bfqg->active_entities++; + if (bfqg->active_entities == 2) + bfqd->active_numerous_groups++; + } +#endif +} + +/** + * bfq_ioprio_to_weight - calc a weight from an ioprio. + * @ioprio: the ioprio value to convert. + */ +static inline unsigned short bfq_ioprio_to_weight(int ioprio) +{ + BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); + return IOPRIO_BE_NR - ioprio; +} + +/** + * bfq_weight_to_ioprio - calc an ioprio from a weight. + * @weight: the weight value to convert. + * + * To preserve as mush as possible the old only-ioprio user interface, + * 0 is used as an escape ioprio value for weights (numerically) equal or + * larger than IOPRIO_BE_NR + */ +static inline unsigned short bfq_weight_to_ioprio(int weight) +{ + BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); + return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; +} + +static inline void bfq_get_entity(struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + + if (bfqq != NULL) { + atomic_inc(&bfqq->ref); + bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", + bfqq, atomic_read(&bfqq->ref)); + } +} + +/** + * bfq_find_deepest - find the deepest node that an extraction can modify. + * @node: the node being removed. + * + * Do the first step of an extraction in an rb tree, looking for the + * node that will replace @node, and returning the deepest node that + * the following modifications to the tree can touch. If @node is the + * last node in the tree return %NULL. + */ +static struct rb_node *bfq_find_deepest(struct rb_node *node) +{ + struct rb_node *deepest; + + if (node->rb_right == NULL && node->rb_left == NULL) + deepest = rb_parent(node); + else if (node->rb_right == NULL) + deepest = node->rb_left; + else if (node->rb_left == NULL) + deepest = node->rb_right; + else { + deepest = rb_next(node); + if (deepest->rb_right != NULL) + deepest = deepest->rb_right; + else if (rb_parent(deepest) != node) + deepest = rb_parent(deepest); + } + + return deepest; +} + +/** + * bfq_active_extract - remove an entity from the active tree. + * @st: the service_tree containing the tree. + * @entity: the entity being removed. + */ +static void bfq_active_extract(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct rb_node *node; +#ifdef CONFIG_CGROUP_BFQIO + struct bfq_sched_data *sd = NULL; + struct bfq_group *bfqg = NULL; + struct bfq_data *bfqd = NULL; +#endif + + node = bfq_find_deepest(&entity->rb_node); + bfq_extract(&st->active, entity); + + if (node != NULL) + bfq_update_active_tree(node); + +#ifdef CONFIG_CGROUP_BFQIO + sd = entity->sched_data; + bfqg = container_of(sd, struct bfq_group, sched_data); + BUG_ON(!bfqg); + bfqd = (struct bfq_data *)bfqg->bfqd; +#endif + if (bfqq != NULL) + list_del(&bfqq->bfqq_list); +#ifdef CONFIG_CGROUP_BFQIO + else { /* bfq_group */ + BUG_ON(!bfqd); + bfq_weights_tree_remove(bfqd, entity, + &bfqd->group_weights_tree); + } + if (bfqg != bfqd->root_group) { + BUG_ON(!bfqg); + BUG_ON(!bfqd); + BUG_ON(!bfqg->active_entities); + bfqg->active_entities--; + if (bfqg->active_entities == 1) { + BUG_ON(!bfqd->active_numerous_groups); + bfqd->active_numerous_groups--; + } + } +#endif +} + +/** + * bfq_idle_insert - insert an entity into the idle tree. + * @st: the service tree containing the tree. + * @entity: the entity to insert. + */ +static void bfq_idle_insert(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct bfq_entity *first_idle = st->first_idle; + struct bfq_entity *last_idle = st->last_idle; + + if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) + st->first_idle = entity; + if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) + st->last_idle = entity; + + bfq_insert(&st->idle, entity); + + if (bfqq != NULL) + list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); +} + +/** + * bfq_forget_entity - remove an entity from the wfq trees. + * @st: the service tree. + * @entity: the entity being removed. + * + * Update the device status and forget everything about @entity, putting + * the device reference to it, if it is a queue. Entities belonging to + * groups are not refcounted. + */ +static void bfq_forget_entity(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + struct bfq_sched_data *sd; + + BUG_ON(!entity->on_st); + + entity->on_st = 0; + st->wsum -= entity->weight; + if (bfqq != NULL) { + sd = entity->sched_data; + bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", + bfqq, atomic_read(&bfqq->ref)); + bfq_put_queue(bfqq); + } +} + +/** + * bfq_put_idle_entity - release the idle tree ref of an entity. + * @st: service tree for the entity. + * @entity: the entity being released. + */ +static void bfq_put_idle_entity(struct bfq_service_tree *st, + struct bfq_entity *entity) +{ + bfq_idle_extract(st, entity); + bfq_forget_entity(st, entity); +} + +/** + * bfq_forget_idle - update the idle tree if necessary. + * @st: the service tree to act upon. + * + * To preserve the global O(log N) complexity we only remove one entry here; + * as the idle tree will not grow indefinitely this can be done safely. + */ +static void bfq_forget_idle(struct bfq_service_tree *st) +{ + struct bfq_entity *first_idle = st->first_idle; + struct bfq_entity *last_idle = st->last_idle; + + if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && + !bfq_gt(last_idle->finish, st->vtime)) { + /* + * Forget the whole idle tree, increasing the vtime past + * the last finish time of idle entities. + */ + st->vtime = last_idle->finish; + } + + if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) + bfq_put_idle_entity(st, first_idle); +} + +static struct bfq_service_tree * +__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, + struct bfq_entity *entity) +{ + struct bfq_service_tree *new_st = old_st; + + if (entity->ioprio_changed) { + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); + unsigned short prev_weight, new_weight; + struct bfq_data *bfqd = NULL; + struct rb_root *root; +#ifdef CONFIG_CGROUP_BFQIO + struct bfq_sched_data *sd; + struct bfq_group *bfqg; +#endif + + if (bfqq != NULL) + bfqd = bfqq->bfqd; +#ifdef CONFIG_CGROUP_BFQIO + else { + sd = entity->my_sched_data; + bfqg = container_of(sd, struct bfq_group, sched_data); + BUG_ON(!bfqg); + bfqd = (struct bfq_data *)bfqg->bfqd; + BUG_ON(!bfqd); + } +#endif + + BUG_ON(old_st->wsum < entity->weight); + old_st->wsum -= entity->weight; + + if (entity->new_weight != entity->orig_weight) { + if (entity->new_weight < BFQ_MIN_WEIGHT || + entity->new_weight > BFQ_MAX_WEIGHT) { + printk(KERN_CRIT "update_weight_prio: " + "new_weight %d\n", + entity->new_weight); + BUG(); + } + entity->orig_weight = entity->new_weight; + entity->ioprio = + bfq_weight_to_ioprio(entity->orig_weight); + } + + entity->ioprio_class = entity->new_ioprio_class; + entity->ioprio_changed = 0; + + /* + * NOTE: here we may be changing the weight too early, + * this will cause unfairness. The correct approach + * would have required additional complexity to defer + * weight changes to the proper time instants (i.e., + * when entity->finish <= old_st->vtime). + */ + new_st = bfq_entity_service_tree(entity); + + prev_weight = entity->weight; + new_weight = entity->orig_weight * + (bfqq != NULL ? bfqq->wr_coeff : 1); + /* + * If the weight of the entity changes, remove the entity + * from its old weight counter (if there is a counter + * associated with the entity), and add it to the counter + * associated with its new weight. + */ + if (prev_weight != new_weight) { + root = bfqq ? &bfqd->queue_weights_tree : + &bfqd->group_weights_tree; + bfq_weights_tree_remove(bfqd, entity, root); + } + entity->weight = new_weight; + /* + * Add the entity to its weights tree only if it is + * not associated with a weight-raised queue. + */ + if (prev_weight != new_weight && + (bfqq ? bfqq->wr_coeff == 1 : 1)) + /* If we get here, root has been initialized. */ + bfq_weights_tree_add(bfqd, entity, root); + + new_st->wsum += entity->weight; + + if (new_st != old_st) + entity->start = new_st->vtime; + } + + return new_st; +} + +/** + * bfq_bfqq_served - update the scheduler status after selection for + * service. + * @bfqq: the queue being served. + * @served: bytes to transfer. + * + * NOTE: this can be optimized, as the timestamps of upper level entities + * are synchronized every time a new bfqq is selected for service. By now, + * we keep it to better check consistency. + */ +static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) +{ + struct bfq_entity *entity = &bfqq->entity; + struct bfq_service_tree *st; + + for_each_entity(entity) { + st = bfq_entity_service_tree(entity); + + entity->service += served; + BUG_ON(entity->service > entity->budget); + BUG_ON(st->wsum == 0); + + st->vtime += bfq_delta(served, st->wsum); + bfq_forget_idle(st); + } + bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); +} + +/** + * bfq_bfqq_charge_full_budget - set the service to the entity budget. + * @bfqq: the queue that needs a service update. + * + * When it's not possible to be fair in the service domain, because + * a queue is not consuming its budget fast enough (the meaning of + * fast depends on the timeout parameter), we charge it a full + * budget. In this way we should obtain a sort of time-domain + * fairness among all the seeky/slow queues. + */ +static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + + bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); + + bfq_bfqq_served(bfqq, entity->budget - entity->service); +} + +/** + * __bfq_activate_entity - activate an entity. + * @entity: the entity being activated. + * + * Called whenever an entity is activated, i.e., it is not active and one + * of its children receives a new request, or has to be reactivated due to + * budget exhaustion. It uses the current budget of the entity (and the + * service received if @entity is active) of the queue to calculate its + * timestamps. + */ +static void __bfq_activate_entity(struct bfq_entity *entity) +{ + struct bfq_sched_data *sd = entity->sched_data; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); + + if (entity == sd->in_service_entity) { + BUG_ON(entity->tree != NULL); + /* + * If we are requeueing the current entity we have + * to take care of not charging to it service it has + * not received. + */ + bfq_calc_finish(entity, entity->service); + entity->start = entity->finish; + sd->in_service_entity = NULL; + } else if (entity->tree == &st->active) { + /* + * Requeueing an entity due to a change of some + * next_in_service entity below it. We reuse the + * old start time. + */ + bfq_active_extract(st, entity); + } else if (entity->tree == &st->idle) { + /* + * Must be on the idle tree, bfq_idle_extract() will + * check for that. + */ + bfq_idle_extract(st, entity); + entity->start = bfq_gt(st->vtime, entity->finish) ? + st->vtime : entity->finish; + } else { + /* + * The finish time of the entity may be invalid, and + * it is in the past for sure, otherwise the queue + * would have been on the idle tree. + */ + entity->start = st->vtime; + st->wsum += entity->weight; + bfq_get_entity(entity); + + BUG_ON(entity->on_st); + entity->on_st = 1; + } + + st = __bfq_entity_update_weight_prio(st, entity); + bfq_calc_finish(entity, entity->budget); + bfq_active_insert(st, entity); +} + +/** + * bfq_activate_entity - activate an entity and its ancestors if necessary. + * @entity: the entity to activate. + * + * Activate @entity and all the entities on the path from it to the root. + */ +static void bfq_activate_entity(struct bfq_entity *entity) +{ + struct bfq_sched_data *sd; + + for_each_entity(entity) { + __bfq_activate_entity(entity); + + sd = entity->sched_data; + if (!bfq_update_next_in_service(sd)) + /* + * No need to propagate the activation to the + * upper entities, as they will be updated when + * the in-service entity is rescheduled. + */ + break; + } +} + +/** + * __bfq_deactivate_entity - deactivate an entity from its service tree. + * @entity: the entity to deactivate. + * @requeue: if false, the entity will not be put into the idle tree. + * + * Deactivate an entity, independently from its previous state. If the + * entity was not on a service tree just return, otherwise if it is on + * any scheduler tree, extract it from that tree, and if necessary + * and if the caller did not specify @requeue, put it on the idle tree. + * + * Return %1 if the caller should update the entity hierarchy, i.e., + * if the entity was in service or if it was the next_in_service for + * its sched_data; return %0 otherwise. + */ +static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) +{ + struct bfq_sched_data *sd = entity->sched_data; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); + int was_in_service = entity == sd->in_service_entity; + int ret = 0; + + if (!entity->on_st) + return 0; + + BUG_ON(was_in_service && entity->tree != NULL); + + if (was_in_service) { + bfq_calc_finish(entity, entity->service); + sd->in_service_entity = NULL; + } else if (entity->tree == &st->active) + bfq_active_extract(st, entity); + else if (entity->tree == &st->idle) + bfq_idle_extract(st, entity); + else if (entity->tree != NULL) + BUG(); + + if (was_in_service || sd->next_in_service == entity) + ret = bfq_update_next_in_service(sd); + + if (!requeue || !bfq_gt(entity->finish, st->vtime)) + bfq_forget_entity(st, entity); + else + bfq_idle_insert(st, entity); + + BUG_ON(sd->in_service_entity == entity); + BUG_ON(sd->next_in_service == entity); + + return ret; +} + +/** + * bfq_deactivate_entity - deactivate an entity. + * @entity: the entity to deactivate. + * @requeue: true if the entity can be put on the idle tree + */ +static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) +{ + struct bfq_sched_data *sd; + struct bfq_entity *parent; + + for_each_entity_safe(entity, parent) { + sd = entity->sched_data; + + if (!__bfq_deactivate_entity(entity, requeue)) + /* + * The parent entity is still backlogged, and + * we don't need to update it as it is still + * in service. + */ + break; + + if (sd->next_in_service != NULL) + /* + * The parent entity is still backlogged and + * the budgets on the path towards the root + * need to be updated. + */ + goto update; + + /* + * If we reach there the parent is no more backlogged and + * we want to propagate the dequeue upwards. + */ + requeue = 1; + } + + return; + +update: + entity = parent; + for_each_entity(entity) { + __bfq_activate_entity(entity); + + sd = entity->sched_data; + if (!bfq_update_next_in_service(sd)) + break; + } +} + +/** + * bfq_update_vtime - update vtime if necessary. + * @st: the service tree to act upon. + * + * If necessary update the service tree vtime to have at least one + * eligible entity, skipping to its start time. Assumes that the + * active tree of the device is not empty. + * + * NOTE: this hierarchical implementation updates vtimes quite often, + * we may end up with reactivated processes getting timestamps after a + * vtime skip done because we needed a ->first_active entity on some + * intermediate node. + */ +static void bfq_update_vtime(struct bfq_service_tree *st) +{ + struct bfq_entity *entry; + struct rb_node *node = st->active.rb_node; + + entry = rb_entry(node, struct bfq_entity, rb_node); + if (bfq_gt(entry->min_start, st->vtime)) { + st->vtime = entry->min_start; + bfq_forget_idle(st); + } +} + +/** + * bfq_first_active_entity - find the eligible entity with + * the smallest finish time + * @st: the service tree to select from. + * + * This function searches the first schedulable entity, starting from the + * root of the tree and going on the left every time on this side there is + * a subtree with at least one eligible (start >= vtime) entity. The path on + * the right is followed only if a) the left subtree contains no eligible + * entities and b) no eligible entity has been found yet. + */ +static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) +{ + struct bfq_entity *entry, *first = NULL; + struct rb_node *node = st->active.rb_node; + + while (node != NULL) { + entry = rb_entry(node, struct bfq_entity, rb_node); +left: + if (!bfq_gt(entry->start, st->vtime)) + first = entry; + + BUG_ON(bfq_gt(entry->min_start, st->vtime)); + + if (node->rb_left != NULL) { + entry = rb_entry(node->rb_left, + struct bfq_entity, rb_node); + if (!bfq_gt(entry->min_start, st->vtime)) { + node = node->rb_left; + goto left; + } + } + if (first != NULL) + break; + node = node->rb_right; + } + + BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); + return first; +} + +/** + * __bfq_lookup_next_entity - return the first eligible entity in @st. + * @st: the service tree. + * + * Update the virtual time in @st and return the first eligible entity + * it contains. + */ +static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, + bool force) +{ + struct bfq_entity *entity, *new_next_in_service = NULL; + + if (RB_EMPTY_ROOT(&st->active)) + return NULL; + + bfq_update_vtime(st); + entity = bfq_first_active_entity(st); + BUG_ON(bfq_gt(entity->start, st->vtime)); + + /* + * If the chosen entity does not match with the sched_data's + * next_in_service and we are forcedly serving the IDLE priority + * class tree, bubble up budget update. + */ + if (unlikely(force && entity != entity->sched_data->next_in_service)) { + new_next_in_service = entity; + for_each_entity(new_next_in_service) + bfq_update_budget(new_next_in_service); + } + + return entity; +} + +/** + * bfq_lookup_next_entity - return the first eligible entity in @sd. + * @sd: the sched_data. + * @extract: if true the returned entity will be also extracted from @sd. + * + * NOTE: since we cache the next_in_service entity at each level of the + * hierarchy, the complexity of the lookup can be decreased with + * absolutely no effort just returning the cached next_in_service value; + * we prefer to do full lookups to test the consistency of * the data + * structures. + */ +static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, + int extract, + struct bfq_data *bfqd) +{ + struct bfq_service_tree *st = sd->service_tree; + struct bfq_entity *entity; + int i = 0; + + BUG_ON(sd->in_service_entity != NULL); + + if (bfqd != NULL && + jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { + entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, + true); + if (entity != NULL) { + i = BFQ_IOPRIO_CLASSES - 1; + bfqd->bfq_class_idle_last_service = jiffies; + sd->next_in_service = entity; + } + } + for (; i < BFQ_IOPRIO_CLASSES; i++) { + entity = __bfq_lookup_next_entity(st + i, false); + if (entity != NULL) { + if (extract) { + bfq_check_next_in_service(sd, entity); + bfq_active_extract(st + i, entity); + sd->in_service_entity = entity; + sd->next_in_service = NULL; + } + break; + } + } + + return entity; +} + +/* + * Get next queue for service. + */ +static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) +{ + struct bfq_entity *entity = NULL; + struct bfq_sched_data *sd; + struct bfq_queue *bfqq; + + BUG_ON(bfqd->in_service_queue != NULL); + + if (bfqd->busy_queues == 0) + return NULL; + + sd = &bfqd->root_group->sched_data; + for (; sd != NULL; sd = entity->my_sched_data) { + entity = bfq_lookup_next_entity(sd, 1, bfqd); + BUG_ON(entity == NULL); + entity->service = 0; + } + + bfqq = bfq_entity_to_bfqq(entity); + BUG_ON(bfqq == NULL); + + return bfqq; +} + +/* + * Forced extraction of the given queue. + */ +static void bfq_get_next_queue_forced(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + struct bfq_entity *entity; + struct bfq_sched_data *sd; + + BUG_ON(bfqd->in_service_queue != NULL); + + entity = &bfqq->entity; + /* + * Bubble up extraction/update from the leaf to the root. + */ + for_each_entity(entity) { + sd = entity->sched_data; + bfq_update_budget(entity); + bfq_update_vtime(bfq_entity_service_tree(entity)); + bfq_active_extract(bfq_entity_service_tree(entity), entity); + sd->in_service_entity = entity; + sd->next_in_service = NULL; + entity->service = 0; + } + + return; +} + +static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) +{ + if (bfqd->in_service_bic != NULL) { + put_io_context(bfqd->in_service_bic->icq.ioc); + bfqd->in_service_bic = NULL; + } + + bfqd->in_service_queue = NULL; + del_timer(&bfqd->idle_slice_timer); +} + +static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, + int requeue) +{ + struct bfq_entity *entity = &bfqq->entity; + + if (bfqq == bfqd->in_service_queue) + __bfq_bfqd_reset_in_service(bfqd); + + bfq_deactivate_entity(entity, requeue); +} + +static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + struct bfq_entity *entity = &bfqq->entity; + + bfq_activate_entity(entity); +} + +/* + * Called when the bfqq no longer has requests pending, remove it from + * the service tree. + */ +static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, + int requeue) +{ + BUG_ON(!bfq_bfqq_busy(bfqq)); + BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); + + bfq_log_bfqq(bfqd, bfqq, "del from busy"); + + bfq_clear_bfqq_busy(bfqq); + + BUG_ON(bfqd->busy_queues == 0); + bfqd->busy_queues--; + + if (!bfqq->dispatched) { + bfq_weights_tree_remove(bfqd, &bfqq->entity, + &bfqd->queue_weights_tree); + if (!blk_queue_nonrot(bfqd->queue)) { + BUG_ON(!bfqd->busy_in_flight_queues); + bfqd->busy_in_flight_queues--; + if (bfq_bfqq_constantly_seeky(bfqq)) { + BUG_ON(!bfqd-> + const_seeky_busy_in_flight_queues); + bfqd->const_seeky_busy_in_flight_queues--; + } + } + } + if (bfqq->wr_coeff > 1) + bfqd->wr_busy_queues--; + + bfq_deactivate_bfqq(bfqd, bfqq, requeue); +} + +/* + * Called when an inactive queue receives a new request. + */ +static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) +{ + BUG_ON(bfq_bfqq_busy(bfqq)); + BUG_ON(bfqq == bfqd->in_service_queue); + + bfq_log_bfqq(bfqd, bfqq, "add to busy"); + + bfq_activate_bfqq(bfqd, bfqq); + + bfq_mark_bfqq_busy(bfqq); + bfqd->busy_queues++; + + if (!bfqq->dispatched) { + if (bfqq->wr_coeff == 1) + bfq_weights_tree_add(bfqd, &bfqq->entity, + &bfqd->queue_weights_tree); + if (!blk_queue_nonrot(bfqd->queue)) { + bfqd->busy_in_flight_queues++; + if (bfq_bfqq_constantly_seeky(bfqq)) + bfqd->const_seeky_busy_in_flight_queues++; + } + } + if (bfqq->wr_coeff > 1) + bfqd->wr_busy_queues++; +} diff --git a/block/bfq.h b/block/bfq.h new file mode 100644 index 000000000000..3173b35e3853 --- /dev/null +++ b/block/bfq.h @@ -0,0 +1,771 @@ +/* + * BFQ-v7r8 for 3.18.0: data structures and common functions prototypes. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe + * + * Copyright (C) 2008 Fabio Checconi + * Paolo Valente + * + * Copyright (C) 2010 Paolo Valente + */ + +#ifndef _BFQ_H +#define _BFQ_H + +#include +#include +#include +#include + +#define BFQ_IOPRIO_CLASSES 3 +#define BFQ_CL_IDLE_TIMEOUT (HZ/5) + +#define BFQ_MIN_WEIGHT 1 +#define BFQ_MAX_WEIGHT 1000 + +#define BFQ_DEFAULT_QUEUE_IOPRIO 4 + +#define BFQ_DEFAULT_GRP_WEIGHT 10 +#define BFQ_DEFAULT_GRP_IOPRIO 0 +#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE + +struct bfq_entity; + +/** + * struct bfq_service_tree - per ioprio_class service tree. + * @active: tree for active entities (i.e., those backlogged). + * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). + * @first_idle: idle entity with minimum F_i. + * @last_idle: idle entity with maximum F_i. + * @vtime: scheduler virtual time. + * @wsum: scheduler weight sum; active and idle entities contribute to it. + * + * Each service tree represents a B-WF2Q+ scheduler on its own. Each + * ioprio_class has its own independent scheduler, and so its own + * bfq_service_tree. All the fields are protected by the queue lock + * of the containing bfqd. + */ +struct bfq_service_tree { + struct rb_root active; + struct rb_root idle; + + struct bfq_entity *first_idle; + struct bfq_entity *last_idle; + + u64 vtime; + unsigned long wsum; +}; + +/** + * struct bfq_sched_data - multi-class scheduler. + * @in_service_entity: entity in service. + * @next_in_service: head-of-the-line entity in the scheduler. + * @service_tree: array of service trees, one per ioprio_class. + * + * bfq_sched_data is the basic scheduler queue. It supports three + * ioprio_classes, and can be used either as a toplevel queue or as + * an intermediate queue on a hierarchical setup. + * @next_in_service points to the active entity of the sched_data + * service trees that will be scheduled next. + * + * The supported ioprio_classes are the same as in CFQ, in descending + * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. + * Requests from higher priority queues are served before all the + * requests from lower priority queues; among requests of the same + * queue requests are served according to B-WF2Q+. + * All the fields are protected by the queue lock of the containing bfqd. + */ +struct bfq_sched_data { + struct bfq_entity *in_service_entity; + struct bfq_entity *next_in_service; + struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; +}; + +/** + * struct bfq_weight_counter - counter of the number of all active entities + * with a given weight. + * @weight: weight of the entities that this counter refers to. + * @num_active: number of active entities with this weight. + * @weights_node: weights tree member (see bfq_data's @queue_weights_tree + * and @group_weights_tree). + */ +struct bfq_weight_counter { + short int weight; + unsigned int num_active; + struct rb_node weights_node; +}; + +/** + * struct bfq_entity - schedulable entity. + * @rb_node: service_tree member. + * @weight_counter: pointer to the weight counter associated with this entity. + * @on_st: flag, true if the entity is on a tree (either the active or + * the idle one of its service_tree). + * @finish: B-WF2Q+ finish timestamp (aka F_i). + * @start: B-WF2Q+ start timestamp (aka S_i). + * @tree: tree the entity is enqueued into; %NULL if not on a tree. + * @min_start: minimum start time of the (active) subtree rooted at + * this entity; used for O(log N) lookups into active trees. + * @service: service received during the last round of service. + * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. + * @weight: weight of the queue + * @parent: parent entity, for hierarchical scheduling. + * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the + * associated scheduler queue, %NULL on leaf nodes. + * @sched_data: the scheduler queue this entity belongs to. + * @ioprio: the ioprio in use. + * @new_weight: when a weight change is requested, the new weight value. + * @orig_weight: original weight, used to implement weight boosting + * @new_ioprio: when an ioprio change is requested, the new ioprio value. + * @ioprio_class: the ioprio_class in use. + * @new_ioprio_class: when an ioprio_class change is requested, the new + * ioprio_class value. + * @ioprio_changed: flag, true when the user requested a weight, ioprio or + * ioprio_class change. + * + * A bfq_entity is used to represent either a bfq_queue (leaf node in the + * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each + * entity belongs to the sched_data of the parent group in the cgroup + * hierarchy. Non-leaf entities have also their own sched_data, stored + * in @my_sched_data. + * + * Each entity stores independently its priority values; this would + * allow different weights on different devices, but this + * functionality is not exported to userspace by now. Priorities and + * weights are updated lazily, first storing the new values into the + * new_* fields, then setting the @ioprio_changed flag. As soon as + * there is a transition in the entity state that allows the priority + * update to take place the effective and the requested priority + * values are synchronized. + * + * Unless cgroups are used, the weight value is calculated from the + * ioprio to export the same interface as CFQ. When dealing with + * ``well-behaved'' queues (i.e., queues that do not spend too much + * time to consume their budget and have true sequential behavior, and + * when there are no external factors breaking anticipation) the + * relative weights at each level of the cgroups hierarchy should be + * guaranteed. All the fields are protected by the queue lock of the + * containing bfqd. + */ +struct bfq_entity { + struct rb_node rb_node; + struct bfq_weight_counter *weight_counter; + + int on_st; + + u64 finish; + u64 start; + + struct rb_root *tree; + + u64 min_start; + + unsigned long service, budget; + unsigned short weight, new_weight; + unsigned short orig_weight; + + struct bfq_entity *parent; + + struct bfq_sched_data *my_sched_data; + struct bfq_sched_data *sched_data; + + unsigned short ioprio, new_ioprio; + unsigned short ioprio_class, new_ioprio_class; + + int ioprio_changed; +}; + +struct bfq_group; + +/** + * struct bfq_queue - leaf schedulable entity. + * @ref: reference counter. + * @bfqd: parent bfq_data. + * @new_bfqq: shared bfq_queue if queue is cooperating with + * one or more other queues. + * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). + * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). + * @sort_list: sorted list of pending requests. + * @next_rq: if fifo isn't expired, next request to serve. + * @queued: nr of requests queued in @sort_list. + * @allocated: currently allocated requests. + * @meta_pending: pending metadata requests. + * @fifo: fifo list of requests in sort_list. + * @entity: entity representing this queue in the scheduler. + * @max_budget: maximum budget allowed from the feedback mechanism. + * @budget_timeout: budget expiration (in jiffies). + * @dispatched: number of requests on the dispatch list or inside driver. + * @flags: status flags. + * @bfqq_list: node for active/idle bfqq list inside our bfqd. + * @burst_list_node: node for the device's burst list. + * @seek_samples: number of seeks sampled + * @seek_total: sum of the distances of the seeks sampled + * @seek_mean: mean seek distance + * @last_request_pos: position of the last request enqueued + * @requests_within_timer: number of consecutive pairs of request completion + * and arrival, such that the queue becomes idle + * after the completion, but the next request arrives + * within an idle time slice; used only if the queue's + * IO_bound has been cleared. + * @pid: pid of the process owning the queue, used for logging purposes. + * @last_wr_start_finish: start time of the current weight-raising period if + * the @bfq-queue is being weight-raised, otherwise + * finish time of the last weight-raising period + * @wr_cur_max_time: current max raising time for this queue + * @soft_rt_next_start: minimum time instant such that, only if a new + * request is enqueued after this time instant in an + * idle @bfq_queue with no outstanding requests, then + * the task associated with the queue it is deemed as + * soft real-time (see the comments to the function + * bfq_bfqq_softrt_next_start()). + * @last_idle_bklogged: time of the last transition of the @bfq_queue from + * idle to backlogged + * @service_from_backlogged: cumulative service received from the @bfq_queue + * since the last transition from idle to + * backlogged + * + * A bfq_queue is a leaf request queue; it can be associated with an io_context + * or more, if it is async or shared between cooperating processes. @cgroup + * holds a reference to the cgroup, to be sure that it does not disappear while + * a bfqq still references it (mostly to avoid races between request issuing and + * task migration followed by cgroup destruction). + * All the fields are protected by the queue lock of the containing bfqd. + */ +struct bfq_queue { + atomic_t ref; + struct bfq_data *bfqd; + + /* fields for cooperating queues handling */ + struct bfq_queue *new_bfqq; + struct rb_node pos_node; + struct rb_root *pos_root; + + struct rb_root sort_list; + struct request *next_rq; + int queued[2]; + int allocated[2]; + int meta_pending; + struct list_head fifo; + + struct bfq_entity entity; + + unsigned long max_budget; + unsigned long budget_timeout; + + int dispatched; + + unsigned int flags; + + struct list_head bfqq_list; + + struct hlist_node burst_list_node; + + unsigned int seek_samples; + u64 seek_total; + sector_t seek_mean; + sector_t last_request_pos; + + unsigned int requests_within_timer; + + pid_t pid; + + /* weight-raising fields */ + unsigned long wr_cur_max_time; + unsigned long soft_rt_next_start; + unsigned long last_wr_start_finish; + unsigned int wr_coeff; + unsigned long last_idle_bklogged; + unsigned long service_from_backlogged; +}; + +/** + * struct bfq_ttime - per process thinktime stats. + * @ttime_total: total process thinktime + * @ttime_samples: number of thinktime samples + * @ttime_mean: average process thinktime + */ +struct bfq_ttime { + unsigned long last_end_request; + + unsigned long ttime_total; + unsigned long ttime_samples; + unsigned long ttime_mean; +}; + +/** + * struct bfq_io_cq - per (request_queue, io_context) structure. + * @icq: associated io_cq structure + * @bfqq: array of two process queues, the sync and the async + * @ttime: associated @bfq_ttime struct + */ +struct bfq_io_cq { + struct io_cq icq; /* must be the first member */ + struct bfq_queue *bfqq[2]; + struct bfq_ttime ttime; + int ioprio; +}; + +enum bfq_device_speed { + BFQ_BFQD_FAST, + BFQ_BFQD_SLOW, +}; + +/** + * struct bfq_data - per device data structure. + * @queue: request queue for the managed device. + * @root_group: root bfq_group for the device. + * @rq_pos_tree: rbtree sorted by next_request position, used when + * determining if two or more queues have interleaving + * requests (see bfq_close_cooperator()). + * @active_numerous_groups: number of bfq_groups containing more than one + * active @bfq_entity. + * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by + * weight. Used to keep track of whether all @bfq_queues + * have the same weight. The tree contains one counter + * for each distinct weight associated to some active + * and not weight-raised @bfq_queue (see the comments to + * the functions bfq_weights_tree_[add|remove] for + * further details). + * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted + * by weight. Used to keep track of whether all + * @bfq_groups have the same weight. The tree contains + * one counter for each distinct weight associated to + * some active @bfq_group (see the comments to the + * functions bfq_weights_tree_[add|remove] for further + * details). + * @busy_queues: number of bfq_queues containing requests (including the + * queue in service, even if it is idling). + * @busy_in_flight_queues: number of @bfq_queues containing pending or + * in-flight requests, plus the @bfq_queue in + * service, even if idle but waiting for the + * possible arrival of its next sync request. This + * field is updated only if the device is rotational, + * but used only if the device is also NCQ-capable. + * The reason why the field is updated also for non- + * NCQ-capable rotational devices is related to the + * fact that the value of @hw_tag may be set also + * later than when busy_in_flight_queues may need to + * be incremented for the first time(s). Taking also + * this possibility into account, to avoid unbalanced + * increments/decrements, would imply more overhead + * than just updating busy_in_flight_queues + * regardless of the value of @hw_tag. + * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues + * (that is, seeky queues that expired + * for budget timeout at least once) + * containing pending or in-flight + * requests, including the in-service + * @bfq_queue if constantly seeky. This + * field is updated only if the device + * is rotational, but used only if the + * device is also NCQ-capable (see the + * comments to @busy_in_flight_queues). + * @wr_busy_queues: number of weight-raised busy @bfq_queues. + * @queued: number of queued requests. + * @rq_in_driver: number of requests dispatched and waiting for completion. + * @sync_flight: number of sync requests in the driver. + * @max_rq_in_driver: max number of reqs in driver in the last + * @hw_tag_samples completed requests. + * @hw_tag_samples: nr of samples used to calculate hw_tag. + * @hw_tag: flag set to one if the driver is showing a queueing behavior. + * @budgets_assigned: number of budgets assigned. + * @idle_slice_timer: timer set when idling for the next sequential request + * from the queue in service. + * @unplug_work: delayed work to restart dispatching on the request queue. + * @in_service_queue: bfq_queue in service. + * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. + * @last_position: on-disk position of the last served request. + * @last_budget_start: beginning of the last budget. + * @last_idling_start: beginning of the last idle slice. + * @peak_rate: peak transfer rate observed for a budget. + * @peak_rate_samples: number of samples used to calculate @peak_rate. + * @bfq_max_budget: maximum budget allotted to a bfq_queue before + * rescheduling. + * @group_list: list of all the bfq_groups active on the device. + * @active_list: list of all the bfq_queues active on the device. + * @idle_list: list of all the bfq_queues idle on the device. + * @bfq_fifo_expire: timeout for async/sync requests; when it expires + * requests are served in fifo order. + * @bfq_back_penalty: weight of backward seeks wrt forward ones. + * @bfq_back_max: maximum allowed backward seek. + * @bfq_slice_idle: maximum idling time. + * @bfq_user_max_budget: user-configured max budget value + * (0 for auto-tuning). + * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to + * async queues. + * @bfq_timeout: timeout for bfq_queues to consume their budget; used to + * to prevent seeky queues to impose long latencies to well + * behaved ones (this also implies that seeky queues cannot + * receive guarantees in the service domain; after a timeout + * they are charged for the whole allocated budget, to try + * to preserve a behavior reasonably fair among them, but + * without service-domain guarantees). + * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is + * no more granted any weight-raising. + * @bfq_failed_cooperations: number of consecutive failed cooperation + * chances after which weight-raising is restored + * to a queue subject to more than bfq_coop_thresh + * queue merges. + * @bfq_requests_within_timer: number of consecutive requests that must be + * issued within the idle time slice to set + * again idling to a queue which was marked as + * non-I/O-bound (see the definition of the + * IO_bound flag for further details). + * @last_ins_in_burst: last time at which a queue entered the current + * burst of queues being activated shortly after + * each other; for more details about this and the + * following parameters related to a burst of + * activations, see the comments to the function + * @bfq_handle_burst. + * @bfq_burst_interval: reference time interval used to decide whether a + * queue has been activated shortly after + * @last_ins_in_burst. + * @burst_size: number of queues in the current burst of queue activations. + * @bfq_large_burst_thresh: maximum burst size above which the current + * queue-activation burst is deemed as 'large'. + * @large_burst: true if a large queue-activation burst is in progress. + * @burst_list: head of the burst list (as for the above fields, more details + * in the comments to the function bfq_handle_burst). + * @low_latency: if set to true, low-latency heuristics are enabled. + * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised + * queue is multiplied. + * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). + * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. + * @bfq_wr_min_idle_time: minimum idle period after which weight-raising + * may be reactivated for a queue (in jiffies). + * @bfq_wr_min_inter_arr_async: minimum period between request arrivals + * after which weight-raising may be + * reactivated for an already busy queue + * (in jiffies). + * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, + * sectors per seconds. + * @RT_prod: cached value of the product R*T used for computing the maximum + * duration of the weight raising automatically. + * @device_speed: device-speed class for the low-latency heuristic. + * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. + * + * All the fields are protected by the @queue lock. + */ +struct bfq_data { + struct request_queue *queue; + + struct bfq_group *root_group; + struct rb_root rq_pos_tree; + +#ifdef CONFIG_CGROUP_BFQIO + int active_numerous_groups; +#endif + + struct rb_root queue_weights_tree; + struct rb_root group_weights_tree; + + int busy_queues; + int busy_in_flight_queues; + int const_seeky_busy_in_flight_queues; + int wr_busy_queues; + int queued; + int rq_in_driver; + int sync_flight; + + int max_rq_in_driver; + int hw_tag_samples; + int hw_tag; + + int budgets_assigned; + + struct timer_list idle_slice_timer; + struct work_struct unplug_work; + + struct bfq_queue *in_service_queue; + struct bfq_io_cq *in_service_bic; + + sector_t last_position; + + ktime_t last_budget_start; + ktime_t last_idling_start; + int peak_rate_samples; + u64 peak_rate; + unsigned long bfq_max_budget; + + struct hlist_head group_list; + struct list_head active_list; + struct list_head idle_list; + + unsigned int bfq_fifo_expire[2]; + unsigned int bfq_back_penalty; + unsigned int bfq_back_max; + unsigned int bfq_slice_idle; + u64 bfq_class_idle_last_service; + + unsigned int bfq_user_max_budget; + unsigned int bfq_max_budget_async_rq; + unsigned int bfq_timeout[2]; + + unsigned int bfq_coop_thresh; + unsigned int bfq_failed_cooperations; + unsigned int bfq_requests_within_timer; + + unsigned long last_ins_in_burst; + unsigned long bfq_burst_interval; + int burst_size; + unsigned long bfq_large_burst_thresh; + bool large_burst; + struct hlist_head burst_list; + + bool low_latency; + + /* parameters of the low_latency heuristics */ + unsigned int bfq_wr_coeff; + unsigned int bfq_wr_max_time; + unsigned int bfq_wr_rt_max_time; + unsigned int bfq_wr_min_idle_time; + unsigned long bfq_wr_min_inter_arr_async; + unsigned int bfq_wr_max_softrt_rate; + u64 RT_prod; + enum bfq_device_speed device_speed; + + struct bfq_queue oom_bfqq; +}; + +enum bfqq_state_flags { + BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ + BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ + BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ + BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ + BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ + BFQ_BFQQ_FLAG_sync, /* synchronous queue */ + BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ + BFQ_BFQQ_FLAG_IO_bound, /* + * bfqq has timed-out at least once + * having consumed at most 2/10 of + * its budget + */ + BFQ_BFQQ_FLAG_in_large_burst, /* + * bfqq activated in a large burst, + * see comments to bfq_handle_burst. + */ + BFQ_BFQQ_FLAG_constantly_seeky, /* + * bfqq has proved to be slow and + * seeky until budget timeout + */ + BFQ_BFQQ_FLAG_softrt_update, /* + * may need softrt-next-start + * update + */ + BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ + BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ +}; + +#define BFQ_BFQQ_FNS(name) \ +static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ +{ \ + (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ +} \ +static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ +{ \ + (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ +} \ +static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ +{ \ + return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ +} + +BFQ_BFQQ_FNS(busy); +BFQ_BFQQ_FNS(wait_request); +BFQ_BFQQ_FNS(must_alloc); +BFQ_BFQQ_FNS(fifo_expire); +BFQ_BFQQ_FNS(idle_window); +BFQ_BFQQ_FNS(sync); +BFQ_BFQQ_FNS(budget_new); +BFQ_BFQQ_FNS(IO_bound); +BFQ_BFQQ_FNS(in_large_burst); +BFQ_BFQQ_FNS(constantly_seeky); +BFQ_BFQQ_FNS(coop); +BFQ_BFQQ_FNS(split_coop); +BFQ_BFQQ_FNS(softrt_update); +#undef BFQ_BFQQ_FNS + +/* Logging facilities. */ +#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ + blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) + +#define bfq_log(bfqd, fmt, args...) \ + blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) + +/* Expiration reasons. */ +enum bfqq_expiration { + BFQ_BFQQ_TOO_IDLE = 0, /* + * queue has been idling for + * too long + */ + BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ + BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ + BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ +}; + +#ifdef CONFIG_CGROUP_BFQIO +/** + * struct bfq_group - per (device, cgroup) data structure. + * @entity: schedulable entity to insert into the parent group sched_data. + * @sched_data: own sched_data, to contain child entities (they may be + * both bfq_queues and bfq_groups). + * @group_node: node to be inserted into the bfqio_cgroup->group_data + * list of the containing cgroup's bfqio_cgroup. + * @bfqd_node: node to be inserted into the @bfqd->group_list list + * of the groups active on the same device; used for cleanup. + * @bfqd: the bfq_data for the device this group acts upon. + * @async_bfqq: array of async queues for all the tasks belonging to + * the group, one queue per ioprio value per ioprio_class, + * except for the idle class that has only one queue. + * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). + * @my_entity: pointer to @entity, %NULL for the toplevel group; used + * to avoid too many special cases during group creation/ + * migration. + * @active_entities: number of active entities belonging to the group; + * unused for the root group. Used to know whether there + * are groups with more than one active @bfq_entity + * (see the comments to the function + * bfq_bfqq_must_not_expire()). + * + * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup + * there is a set of bfq_groups, each one collecting the lower-level + * entities belonging to the group that are acting on the same device. + * + * Locking works as follows: + * o @group_node is protected by the bfqio_cgroup lock, and is accessed + * via RCU from its readers. + * o @bfqd is protected by the queue lock, RCU is used to access it + * from the readers. + * o All the other fields are protected by the @bfqd queue lock. + */ +struct bfq_group { + struct bfq_entity entity; + struct bfq_sched_data sched_data; + + struct hlist_node group_node; + struct hlist_node bfqd_node; + + void *bfqd; + + struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; + struct bfq_queue *async_idle_bfqq; + + struct bfq_entity *my_entity; + + int active_entities; +}; + +/** + * struct bfqio_cgroup - bfq cgroup data structure. + * @css: subsystem state for bfq in the containing cgroup. + * @online: flag marked when the subsystem is inserted. + * @weight: cgroup weight. + * @ioprio: cgroup ioprio. + * @ioprio_class: cgroup ioprio_class. + * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. + * @group_data: list containing the bfq_group belonging to this cgroup. + * + * @group_data is accessed using RCU, with @lock protecting the updates, + * @ioprio and @ioprio_class are protected by @lock. + */ +struct bfqio_cgroup { + struct cgroup_subsys_state css; + bool online; + + unsigned short weight, ioprio, ioprio_class; + + spinlock_t lock; + struct hlist_head group_data; +}; +#else +struct bfq_group { + struct bfq_sched_data sched_data; + + struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; + struct bfq_queue *async_idle_bfqq; +}; +#endif + +static inline struct bfq_service_tree * +bfq_entity_service_tree(struct bfq_entity *entity) +{ + struct bfq_sched_data *sched_data = entity->sched_data; + unsigned int idx = entity->ioprio_class - 1; + + BUG_ON(idx >= BFQ_IOPRIO_CLASSES); + BUG_ON(sched_data == NULL); + + return sched_data->service_tree + idx; +} + +static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, + bool is_sync) +{ + return bic->bfqq[is_sync]; +} + +static inline void bic_set_bfqq(struct bfq_io_cq *bic, + struct bfq_queue *bfqq, bool is_sync) +{ + bic->bfqq[is_sync] = bfqq; +} + +static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) +{ + return bic->icq.q->elevator->elevator_data; +} + +/** + * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. + * @ptr: a pointer to a bfqd. + * @flags: storage for the flags to be saved. + * + * This function allows bfqg->bfqd to be protected by the + * queue lock of the bfqd they reference; the pointer is dereferenced + * under RCU, so the storage for bfqd is assured to be safe as long + * as the RCU read side critical section does not end. After the + * bfqd->queue->queue_lock is taken the pointer is rechecked, to be + * sure that no other writer accessed it. If we raced with a writer, + * the function returns NULL, with the queue unlocked, otherwise it + * returns the dereferenced pointer, with the queue locked. + */ +static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, + unsigned long *flags) +{ + struct bfq_data *bfqd; + + rcu_read_lock(); + bfqd = rcu_dereference(*(struct bfq_data **)ptr); + + if (bfqd != NULL) { + spin_lock_irqsave(bfqd->queue->queue_lock, *flags); + if (*ptr == bfqd) + goto out; + spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); + } + + bfqd = NULL; +out: + rcu_read_unlock(); + return bfqd; +} + +static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, + unsigned long *flags) +{ + spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); +} + +static void bfq_check_ioprio_change(struct bfq_io_cq *bic); +static void bfq_put_queue(struct bfq_queue *bfqq); +static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); +static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, + struct bfq_group *bfqg, int is_sync, + struct bfq_io_cq *bic, gfp_t gfp_mask); +static void bfq_end_wr_async_queues(struct bfq_data *bfqd, + struct bfq_group *bfqg); +static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); +static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); + +#endif /* _BFQ_H */ From cecc2d0bd7e75a736ade2a5ef5848eb139701e49 Mon Sep 17 00:00:00 2001 From: Mauro Andreolini Date: Fri, 5 Jun 2015 17:45:40 +0200 Subject: [PATCH 020/203] block, bfq: add Early Queue Merge (EQM) to BFQ-v7r8 for 3.18.0 A set of processes may happen to perform interleaved reads, i.e.,requests whose union would give rise to a sequential read pattern. There are two typical cases: in the first case, processes read fixed-size chunks of data at a fixed distance from each other, while in the second case processes may read variable-size chunks at variable distances. The latter case occurs for example with QEMU, which splits the I/O generated by the guest into multiple chunks, and lets these chunks be served by a pool of cooperating processes, iteratively assigning the next chunk of I/O to the first available process. CFQ uses actual queue merging for the first type of rocesses, whereas it uses preemption to get a sequential read pattern out of the read requests performed by the second type of processes. In the end it uses two different mechanisms to achieve the same goal: boosting the throughput with interleaved I/O. This patch introduces Early Queue Merge (EQM), a unified mechanism to get a sequential read pattern with both types of processes. The main idea is checking newly arrived requests against the next request of the active queue both in case of actual request insert and in case of request merge. By doing so, both the types of processes can be handled by just merging their queues. EQM is then simpler and more compact than the pair of mechanisms used in CFQ. Finally, EQM also preserves the typical low-latency properties of BFQ, by properly restoring the weight-raising state of a queue when it gets back to a non-merged state. Signed-off-by: Mauro Andreolini Signed-off-by: Arianna Avanzini Signed-off-by: Paolo Valente --- block/bfq-iosched.c | 750 +++++++++++++++++++++++++++++++------------- block/bfq-sched.c | 28 -- block/bfq.h | 54 +++- 3 files changed, 580 insertions(+), 252 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 773b2ee064b2..71b51c1b436c 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -573,6 +573,57 @@ static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) return dur; } +static inline unsigned +bfq_bfqq_cooperations(struct bfq_queue *bfqq) +{ + return bfqq->bic ? bfqq->bic->cooperations : 0; +} + +static inline void +bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_io_cq *bic) +{ + if (bic->saved_idle_window) + bfq_mark_bfqq_idle_window(bfqq); + else + bfq_clear_bfqq_idle_window(bfqq); + if (bic->saved_IO_bound) + bfq_mark_bfqq_IO_bound(bfqq); + else + bfq_clear_bfqq_IO_bound(bfqq); + /* Assuming that the flag in_large_burst is already correctly set */ + if (bic->wr_time_left && bfqq->bfqd->low_latency && + !bfq_bfqq_in_large_burst(bfqq) && + bic->cooperations < bfqq->bfqd->bfq_coop_thresh) { + /* + * Start a weight raising period with the duration given by + * the raising_time_left snapshot. + */ + if (bfq_bfqq_busy(bfqq)) + bfqq->bfqd->wr_busy_queues++; + bfqq->wr_coeff = bfqq->bfqd->bfq_wr_coeff; + bfqq->wr_cur_max_time = bic->wr_time_left; + bfqq->last_wr_start_finish = jiffies; + bfqq->entity.ioprio_changed = 1; + } + /* + * Clear wr_time_left to prevent bfq_bfqq_save_state() from + * getting confused about the queue's need of a weight-raising + * period. + */ + bic->wr_time_left = 0; +} + +/* Must be called with the queue_lock held. */ +static int bfqq_process_refs(struct bfq_queue *bfqq) +{ + int process_refs, io_refs; + + io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; + process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; + BUG_ON(process_refs < 0); + return process_refs; +} + /* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ static inline void bfq_reset_burst_list(struct bfq_data *bfqd, struct bfq_queue *bfqq) @@ -817,7 +868,7 @@ static void bfq_add_request(struct request *rq) bfq_rq_pos_tree_add(bfqd, bfqq); if (!bfq_bfqq_busy(bfqq)) { - bool soft_rt, + bool soft_rt, coop_or_in_burst, idle_for_long_time = time_is_before_jiffies( bfqq->budget_timeout + bfqd->bfq_wr_min_idle_time); @@ -841,11 +892,12 @@ static void bfq_add_request(struct request *rq) bfqd->last_ins_in_burst = jiffies; } + coop_or_in_burst = bfq_bfqq_in_large_burst(bfqq) || + bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh; soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && - !bfq_bfqq_in_large_burst(bfqq) && + !coop_or_in_burst && time_is_before_jiffies(bfqq->soft_rt_next_start); - interactive = !bfq_bfqq_in_large_burst(bfqq) && - idle_for_long_time; + interactive = !coop_or_in_burst && idle_for_long_time; entity->budget = max_t(unsigned long, bfqq->max_budget, bfq_serv_to_charge(next_rq, bfqq)); @@ -864,11 +916,20 @@ static void bfq_add_request(struct request *rq) if (!bfqd->low_latency) goto add_bfqq_busy; + if (bfq_bfqq_just_split(bfqq)) + goto set_ioprio_changed; + /* - * If the queue is not being boosted and has been idle - * for enough time, start a weight-raising period + * If the queue: + * - is not being boosted, + * - has been idle for enough time, + * - is not a sync queue or is linked to a bfq_io_cq (it is + * shared "for its nature" or it is not shared and its + * requests have not been redirected to a shared queue) + * start a weight-raising period. */ - if (old_wr_coeff == 1 && (interactive || soft_rt)) { + if (old_wr_coeff == 1 && (interactive || soft_rt) && + (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) { bfqq->wr_coeff = bfqd->bfq_wr_coeff; if (interactive) bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); @@ -882,7 +943,7 @@ static void bfq_add_request(struct request *rq) } else if (old_wr_coeff > 1) { if (interactive) bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); - else if (bfq_bfqq_in_large_burst(bfqq) || + else if (coop_or_in_burst || (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time && !soft_rt)) { @@ -901,18 +962,18 @@ static void bfq_add_request(struct request *rq) /* * * The remaining weight-raising time is lower - * than bfqd->bfq_wr_rt_max_time, which - * means that the application is enjoying - * weight raising either because deemed soft- - * rt in the near past, or because deemed - * interactive a long ago. In both cases, - * resetting now the current remaining weight- - * raising time for the application to the - * weight-raising duration for soft rt - * applications would not cause any latency - * increase for the application (as the new - * duration would be higher than the remaining - * time). + * than bfqd->bfq_wr_rt_max_time, which means + * that the application is enjoying weight + * raising either because deemed soft-rt in + * the near past, or because deemed interactive + * a long ago. + * In both cases, resetting now the current + * remaining weight-raising time for the + * application to the weight-raising duration + * for soft rt applications would not cause any + * latency increase for the application (as the + * new duration would be higher than the + * remaining time). * * In addition, the application is now meeting * the requirements for being deemed soft rt. @@ -947,6 +1008,7 @@ static void bfq_add_request(struct request *rq) bfqd->bfq_wr_rt_max_time; } } +set_ioprio_changed: if (old_wr_coeff != bfqq->wr_coeff) entity->ioprio_changed = 1; add_bfqq_busy: @@ -1167,90 +1229,35 @@ static void bfq_end_wr(struct bfq_data *bfqd) spin_unlock_irq(bfqd->queue->queue_lock); } -static int bfq_allow_merge(struct request_queue *q, struct request *rq, - struct bio *bio) +static inline sector_t bfq_io_struct_pos(void *io_struct, bool request) { - struct bfq_data *bfqd = q->elevator->elevator_data; - struct bfq_io_cq *bic; - struct bfq_queue *bfqq; - - /* - * Disallow merge of a sync bio into an async request. - */ - if (bfq_bio_sync(bio) && !rq_is_sync(rq)) - return 0; - - /* - * Lookup the bfqq that this bio will be queued with. Allow - * merge only if rq is queued there. - * Queue lock is held here. - */ - bic = bfq_bic_lookup(bfqd, current->io_context); - if (bic == NULL) - return 0; - - bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); - return bfqq == RQ_BFQQ(rq); -} - -static void __bfq_set_in_service_queue(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -{ - if (bfqq != NULL) { - bfq_mark_bfqq_must_alloc(bfqq); - bfq_mark_bfqq_budget_new(bfqq); - bfq_clear_bfqq_fifo_expire(bfqq); - - bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; - - bfq_log_bfqq(bfqd, bfqq, - "set_in_service_queue, cur-budget = %lu", - bfqq->entity.budget); - } - - bfqd->in_service_queue = bfqq; -} - -/* - * Get and set a new queue for service. - */ -static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -{ - if (!bfqq) - bfqq = bfq_get_next_queue(bfqd); + if (request) + return blk_rq_pos(io_struct); else - bfq_get_next_queue_forced(bfqd, bfqq); - - __bfq_set_in_service_queue(bfqd, bfqq); - return bfqq; + return ((struct bio *)io_struct)->bi_iter.bi_sector; } -static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, - struct request *rq) +static inline sector_t bfq_dist_from(sector_t pos1, + sector_t pos2) { - if (blk_rq_pos(rq) >= bfqd->last_position) - return blk_rq_pos(rq) - bfqd->last_position; + if (pos1 >= pos2) + return pos1 - pos2; else - return bfqd->last_position - blk_rq_pos(rq); + return pos2 - pos1; } -/* - * Return true if bfqq has no request pending and rq is close enough to - * bfqd->last_position, or if rq is closer to bfqd->last_position than - * bfqq->next_rq - */ -static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) +static inline int bfq_rq_close_to_sector(void *io_struct, bool request, + sector_t sector) { - return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; + return bfq_dist_from(bfq_io_struct_pos(io_struct, request), sector) <= + BFQQ_SEEK_THR; } -static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) +static struct bfq_queue *bfqq_close(struct bfq_data *bfqd, sector_t sector) { struct rb_root *root = &bfqd->rq_pos_tree; struct rb_node *parent, *node; struct bfq_queue *__bfqq; - sector_t sector = bfqd->last_position; if (RB_EMPTY_ROOT(root)) return NULL; @@ -1269,7 +1276,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) * next_request position). */ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); - if (bfq_rq_close(bfqd, __bfqq->next_rq)) + if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) return __bfqq; if (blk_rq_pos(__bfqq->next_rq) < sector) @@ -1280,7 +1287,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) return NULL; __bfqq = rb_entry(node, struct bfq_queue, pos_node); - if (bfq_rq_close(bfqd, __bfqq->next_rq)) + if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) return __bfqq; return NULL; @@ -1289,14 +1296,12 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) /* * bfqd - obvious * cur_bfqq - passed in so that we don't decide that the current queue - * is closely cooperating with itself. - * - * We are assuming that cur_bfqq has dispatched at least one request, - * and that bfqd->last_position reflects a position on the disk associated - * with the I/O issued by cur_bfqq. + * is closely cooperating with itself + * sector - used as a reference point to search for a close queue */ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, - struct bfq_queue *cur_bfqq) + struct bfq_queue *cur_bfqq, + sector_t sector) { struct bfq_queue *bfqq; @@ -1316,7 +1321,7 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, * working closely on the same area of the disk. In that case, * we can group them together and don't waste time idling. */ - bfqq = bfqq_close(bfqd); + bfqq = bfqq_close(bfqd, sector); if (bfqq == NULL || bfqq == cur_bfqq) return NULL; @@ -1343,6 +1348,315 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, return bfqq; } +static struct bfq_queue * +bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +{ + int process_refs, new_process_refs; + struct bfq_queue *__bfqq; + + /* + * If there are no process references on the new_bfqq, then it is + * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain + * may have dropped their last reference (not just their last process + * reference). + */ + if (!bfqq_process_refs(new_bfqq)) + return NULL; + + /* Avoid a circular list and skip interim queue merges. */ + while ((__bfqq = new_bfqq->new_bfqq)) { + if (__bfqq == bfqq) + return NULL; + new_bfqq = __bfqq; + } + + process_refs = bfqq_process_refs(bfqq); + new_process_refs = bfqq_process_refs(new_bfqq); + /* + * If the process for the bfqq has gone away, there is no + * sense in merging the queues. + */ + if (process_refs == 0 || new_process_refs == 0) + return NULL; + + bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", + new_bfqq->pid); + + /* + * Merging is just a redirection: the requests of the process + * owning one of the two queues are redirected to the other queue. + * The latter queue, in its turn, is set as shared if this is the + * first time that the requests of some process are redirected to + * it. + * + * We redirect bfqq to new_bfqq and not the opposite, because we + * are in the context of the process owning bfqq, hence we have + * the io_cq of this process. So we can immediately configure this + * io_cq to redirect the requests of the process to new_bfqq. + * + * NOTE, even if new_bfqq coincides with the in-service queue, the + * io_cq of new_bfqq is not available, because, if the in-service + * queue is shared, bfqd->in_service_bic may not point to the + * io_cq of the in-service queue. + * Redirecting the requests of the process owning bfqq to the + * currently in-service queue is in any case the best option, as + * we feed the in-service queue with new requests close to the + * last request served and, by doing so, hopefully increase the + * throughput. + */ + bfqq->new_bfqq = new_bfqq; + atomic_add(process_refs, &new_bfqq->ref); + return new_bfqq; +} + +/* + * Attempt to schedule a merge of bfqq with the currently in-service queue + * or with a close queue among the scheduled queues. + * Return NULL if no merge was scheduled, a pointer to the shared bfq_queue + * structure otherwise. + * + * The OOM queue is not allowed to participate to cooperation: in fact, since + * the requests temporarily redirected to the OOM queue could be redirected + * again to dedicated queues at any time, the state needed to correctly + * handle merging with the OOM queue would be quite complex and expensive + * to maintain. Besides, in such a critical condition as an out of memory, + * the benefits of queue merging may be little relevant, or even negligible. + */ +static struct bfq_queue * +bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, + void *io_struct, bool request) +{ + struct bfq_queue *in_service_bfqq, *new_bfqq; + + if (bfqq->new_bfqq) + return bfqq->new_bfqq; + + if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq)) + return NULL; + + in_service_bfqq = bfqd->in_service_queue; + + if (in_service_bfqq == NULL || in_service_bfqq == bfqq || + !bfqd->in_service_bic || + unlikely(in_service_bfqq == &bfqd->oom_bfqq)) + goto check_scheduled; + + if (bfq_class_idle(in_service_bfqq) || bfq_class_idle(bfqq)) + goto check_scheduled; + + if (bfq_class_rt(in_service_bfqq) != bfq_class_rt(bfqq)) + goto check_scheduled; + + if (in_service_bfqq->entity.parent != bfqq->entity.parent) + goto check_scheduled; + + if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && + bfq_bfqq_sync(in_service_bfqq) && bfq_bfqq_sync(bfqq)) { + new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); + if (new_bfqq != NULL) + return new_bfqq; /* Merge with in-service queue */ + } + + /* + * Check whether there is a cooperator among currently scheduled + * queues. The only thing we need is that the bio/request is not + * NULL, as we need it to establish whether a cooperator exists. + */ +check_scheduled: + new_bfqq = bfq_close_cooperator(bfqd, bfqq, + bfq_io_struct_pos(io_struct, request)); + if (new_bfqq && likely(new_bfqq != &bfqd->oom_bfqq)) + return bfq_setup_merge(bfqq, new_bfqq); + + return NULL; +} + +static inline void +bfq_bfqq_save_state(struct bfq_queue *bfqq) +{ + /* + * If bfqq->bic == NULL, the queue is already shared or its requests + * have already been redirected to a shared queue; both idle window + * and weight raising state have already been saved. Do nothing. + */ + if (bfqq->bic == NULL) + return; + if (bfqq->bic->wr_time_left) + /* + * This is the queue of a just-started process, and would + * deserve weight raising: we set wr_time_left to the full + * weight-raising duration to trigger weight-raising when + * and if the queue is split and the first request of the + * queue is enqueued. + */ + bfqq->bic->wr_time_left = bfq_wr_duration(bfqq->bfqd); + else if (bfqq->wr_coeff > 1) { + unsigned long wr_duration = + jiffies - bfqq->last_wr_start_finish; + /* + * It may happen that a queue's weight raising period lasts + * longer than its wr_cur_max_time, as weight raising is + * handled only when a request is enqueued or dispatched (it + * does not use any timer). If the weight raising period is + * about to end, don't save it. + */ + if (bfqq->wr_cur_max_time <= wr_duration) + bfqq->bic->wr_time_left = 0; + else + bfqq->bic->wr_time_left = + bfqq->wr_cur_max_time - wr_duration; + /* + * The bfq_queue is becoming shared or the requests of the + * process owning the queue are being redirected to a shared + * queue. Stop the weight raising period of the queue, as in + * both cases it should not be owned by an interactive or + * soft real-time application. + */ + bfq_bfqq_end_wr(bfqq); + } else + bfqq->bic->wr_time_left = 0; + bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq); + bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq); + bfqq->bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq); + bfqq->bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node); + bfqq->bic->cooperations++; + bfqq->bic->failed_cooperations = 0; +} + +static inline void +bfq_get_bic_reference(struct bfq_queue *bfqq) +{ + /* + * If bfqq->bic has a non-NULL value, the bic to which it belongs + * is about to begin using a shared bfq_queue. + */ + if (bfqq->bic) + atomic_long_inc(&bfqq->bic->icq.ioc->refcount); +} + +static void +bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +{ + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", + (long unsigned)new_bfqq->pid); + /* Save weight raising and idle window of the merged queues */ + bfq_bfqq_save_state(bfqq); + bfq_bfqq_save_state(new_bfqq); + if (bfq_bfqq_IO_bound(bfqq)) + bfq_mark_bfqq_IO_bound(new_bfqq); + bfq_clear_bfqq_IO_bound(bfqq); + /* + * Grab a reference to the bic, to prevent it from being destroyed + * before being possibly touched by a bfq_split_bfqq(). + */ + bfq_get_bic_reference(bfqq); + bfq_get_bic_reference(new_bfqq); + /* + * Merge queues (that is, let bic redirect its requests to new_bfqq) + */ + bic_set_bfqq(bic, new_bfqq, 1); + bfq_mark_bfqq_coop(new_bfqq); + /* + * new_bfqq now belongs to at least two bics (it is a shared queue): + * set new_bfqq->bic to NULL. bfqq either: + * - does not belong to any bic any more, and hence bfqq->bic must + * be set to NULL, or + * - is a queue whose owning bics have already been redirected to a + * different queue, hence the queue is destined to not belong to + * any bic soon and bfqq->bic is already NULL (therefore the next + * assignment causes no harm). + */ + new_bfqq->bic = NULL; + bfqq->bic = NULL; + bfq_put_queue(bfqq); +} + +static inline void bfq_bfqq_increase_failed_cooperations(struct bfq_queue *bfqq) +{ + struct bfq_io_cq *bic = bfqq->bic; + struct bfq_data *bfqd = bfqq->bfqd; + + if (bic && bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh) { + bic->failed_cooperations++; + if (bic->failed_cooperations >= bfqd->bfq_failed_cooperations) + bic->cooperations = 0; + } +} + +static int bfq_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct bfq_data *bfqd = q->elevator->elevator_data; + struct bfq_io_cq *bic; + struct bfq_queue *bfqq, *new_bfqq; + + /* + * Disallow merge of a sync bio into an async request. + */ + if (bfq_bio_sync(bio) && !rq_is_sync(rq)) + return 0; + + /* + * Lookup the bfqq that this bio will be queued with. Allow + * merge only if rq is queued there. + * Queue lock is held here. + */ + bic = bfq_bic_lookup(bfqd, current->io_context); + if (bic == NULL) + return 0; + + bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); + /* + * We take advantage of this function to perform an early merge + * of the queues of possible cooperating processes. + */ + if (bfqq != NULL) { + new_bfqq = bfq_setup_cooperator(bfqd, bfqq, bio, false); + if (new_bfqq != NULL) { + bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq); + /* + * If we get here, the bio will be queued in the + * shared queue, i.e., new_bfqq, so use new_bfqq + * to decide whether bio and rq can be merged. + */ + bfqq = new_bfqq; + } else + bfq_bfqq_increase_failed_cooperations(bfqq); + } + + return bfqq == RQ_BFQQ(rq); +} + +static void __bfq_set_in_service_queue(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +{ + if (bfqq != NULL) { + bfq_mark_bfqq_must_alloc(bfqq); + bfq_mark_bfqq_budget_new(bfqq); + bfq_clear_bfqq_fifo_expire(bfqq); + + bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; + + bfq_log_bfqq(bfqd, bfqq, + "set_in_service_queue, cur-budget = %lu", + bfqq->entity.budget); + } + + bfqd->in_service_queue = bfqq; +} + +/* + * Get and set a new queue for service. + */ +static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd) +{ + struct bfq_queue *bfqq = bfq_get_next_queue(bfqd); + + __bfq_set_in_service_queue(bfqd, bfqq); + return bfqq; +} + /* * If enough samples have been computed, return the current max budget * stored in bfqd, which is dynamically updated according to the @@ -1488,61 +1802,6 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq) return rq; } -/* Must be called with the queue_lock held. */ -static int bfqq_process_refs(struct bfq_queue *bfqq) -{ - int process_refs, io_refs; - - io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; - process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; - BUG_ON(process_refs < 0); - return process_refs; -} - -static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -{ - int process_refs, new_process_refs; - struct bfq_queue *__bfqq; - - /* - * If there are no process references on the new_bfqq, then it is - * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain - * may have dropped their last reference (not just their last process - * reference). - */ - if (!bfqq_process_refs(new_bfqq)) - return; - - /* Avoid a circular list and skip interim queue merges. */ - while ((__bfqq = new_bfqq->new_bfqq)) { - if (__bfqq == bfqq) - return; - new_bfqq = __bfqq; - } - - process_refs = bfqq_process_refs(bfqq); - new_process_refs = bfqq_process_refs(new_bfqq); - /* - * If the process for the bfqq has gone away, there is no - * sense in merging the queues. - */ - if (process_refs == 0 || new_process_refs == 0) - return; - - /* - * Merge in the direction of the lesser amount of work. - */ - if (new_process_refs >= process_refs) { - bfqq->new_bfqq = new_bfqq; - atomic_add(process_refs, &new_bfqq->ref); - } else { - new_bfqq->new_bfqq = bfqq; - atomic_add(new_process_refs, &bfqq->ref); - } - bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", - new_bfqq->pid); -} - static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) { struct bfq_entity *entity = &bfqq->entity; @@ -2269,7 +2528,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) */ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) { - struct bfq_queue *bfqq, *new_bfqq = NULL; + struct bfq_queue *bfqq; struct request *next_rq; enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; @@ -2279,17 +2538,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); - /* - * If another queue has a request waiting within our mean seek - * distance, let it run. The expire code will check for close - * cooperators and put the close queue at the front of the - * service tree. If possible, merge the expiring queue with the - * new bfqq. - */ - new_bfqq = bfq_close_cooperator(bfqd, bfqq); - if (new_bfqq != NULL && bfqq->new_bfqq == NULL) - bfq_setup_merge(bfqq, new_bfqq); - if (bfq_may_expire_for_budg_timeout(bfqq) && !timer_pending(&bfqd->idle_slice_timer) && !bfq_bfqq_must_idle(bfqq)) @@ -2328,10 +2576,7 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) bfq_clear_bfqq_wait_request(bfqq); del_timer(&bfqd->idle_slice_timer); } - if (new_bfqq == NULL) - goto keep_queue; - else - goto expire; + goto keep_queue; } } @@ -2340,40 +2585,30 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) * for a new request, or has requests waiting for a completion and * may idle after their completion, then keep it anyway. */ - if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || - (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { + if (timer_pending(&bfqd->idle_slice_timer) || + (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) { bfqq = NULL; goto keep_queue; - } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { - /* - * Expiring the queue because there is a close cooperator, - * cancel timer. - */ - bfq_clear_bfqq_wait_request(bfqq); - del_timer(&bfqd->idle_slice_timer); } reason = BFQ_BFQQ_NO_MORE_REQUESTS; expire: bfq_bfqq_expire(bfqd, bfqq, 0, reason); new_queue: - bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); + bfqq = bfq_set_in_service_queue(bfqd); bfq_log(bfqd, "select_queue: new queue %d returned", bfqq != NULL ? bfqq->pid : 0); keep_queue: return bfqq; } -static void bfq_update_wr_data(struct bfq_data *bfqd, - struct bfq_queue *bfqq) +static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq) { - if (bfqq->wr_coeff > 1) { /* queue is being boosted */ - struct bfq_entity *entity = &bfqq->entity; - + struct bfq_entity *entity = &bfqq->entity; + if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */ bfq_log_bfqq(bfqd, bfqq, "raising period dur %u/%u msec, old coeff %u, w %d(%d)", - jiffies_to_msecs(jiffies - - bfqq->last_wr_start_finish), + jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), jiffies_to_msecs(bfqq->wr_cur_max_time), bfqq->wr_coeff, bfqq->entity.weight, bfqq->entity.orig_weight); @@ -2382,12 +2617,16 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, entity->orig_weight * bfqq->wr_coeff); if (entity->ioprio_changed) bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); + /* * If the queue was activated in a burst, or * too much time has elapsed from the beginning - * of this weight-raising, then end weight raising. + * of this weight-raising period, or the queue has + * exceeded the acceptable number of cooperations, + * then end weight raising. */ if (bfq_bfqq_in_large_burst(bfqq) || + bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || time_is_before_jiffies(bfqq->last_wr_start_finish + bfqq->wr_cur_max_time)) { bfqq->last_wr_start_finish = jiffies; @@ -2396,11 +2635,13 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, bfqq->last_wr_start_finish, jiffies_to_msecs(bfqq->wr_cur_max_time)); bfq_bfqq_end_wr(bfqq); - __bfq_entity_update_weight_prio( - bfq_entity_service_tree(entity), - entity); } } + /* Update weight both if it must be raised and if it must be lowered */ + if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1)) + __bfq_entity_update_weight_prio( + bfq_entity_service_tree(entity), + entity); } /* @@ -2647,6 +2888,25 @@ static inline void bfq_init_icq(struct io_cq *icq) struct bfq_io_cq *bic = icq_to_bic(icq); bic->ttime.last_end_request = jiffies; + /* + * A newly created bic indicates that the process has just + * started doing I/O, and is probably mapping into memory its + * executable and libraries: it definitely needs weight raising. + * There is however the possibility that the process performs, + * for a while, I/O close to some other process. EQM intercepts + * this behavior and may merge the queue corresponding to the + * process with some other queue, BEFORE the weight of the queue + * is raised. Merged queues are not weight-raised (they are assumed + * to belong to processes that benefit only from high throughput). + * If the merge is basically the consequence of an accident, then + * the queue will be split soon and will get back its old weight. + * It is then important to write down somewhere that this queue + * does need weight raising, even if it did not make it to get its + * weight raised before being merged. To this purpose, we overload + * the field raising_time_left and assign 1 to it, to mark the queue + * as needing weight raising. + */ + bic->wr_time_left = 1; } static void bfq_exit_icq(struct io_cq *icq) @@ -2660,6 +2920,13 @@ static void bfq_exit_icq(struct io_cq *icq) } if (bic->bfqq[BLK_RW_SYNC]) { + /* + * If the bic is using a shared queue, put the reference + * taken on the io_context when the bic started using a + * shared bfq_queue. + */ + if (bfq_bfqq_coop(bic->bfqq[BLK_RW_SYNC])) + put_io_context(icq->ioc); bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); bic->bfqq[BLK_RW_SYNC] = NULL; } @@ -2952,6 +3219,10 @@ static void bfq_update_idle_window(struct bfq_data *bfqd, if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) return; + /* Idle window just restored, statistics are meaningless. */ + if (bfq_bfqq_just_split(bfqq)) + return; + enable_idle = bfq_bfqq_idle_window(bfqq); if (atomic_read(&bic->icq.ioc->active_ref) == 0 || @@ -2999,6 +3270,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || !BFQQ_SEEKY(bfqq)) bfq_update_idle_window(bfqd, bfqq, bic); + bfq_clear_bfqq_just_split(bfqq); bfq_log_bfqq(bfqd, bfqq, "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", @@ -3059,12 +3331,47 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, static void bfq_insert_request(struct request_queue *q, struct request *rq) { struct bfq_data *bfqd = q->elevator->elevator_data; - struct bfq_queue *bfqq = RQ_BFQQ(rq); + struct bfq_queue *bfqq = RQ_BFQQ(rq), *new_bfqq; assert_spin_locked(bfqd->queue->queue_lock); + /* + * An unplug may trigger a requeue of a request from the device + * driver: make sure we are in process context while trying to + * merge two bfq_queues. + */ + if (!in_interrupt()) { + new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true); + if (new_bfqq != NULL) { + if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq) + new_bfqq = bic_to_bfqq(RQ_BIC(rq), 1); + /* + * Release the request's reference to the old bfqq + * and make sure one is taken to the shared queue. + */ + new_bfqq->allocated[rq_data_dir(rq)]++; + bfqq->allocated[rq_data_dir(rq)]--; + atomic_inc(&new_bfqq->ref); + bfq_put_queue(bfqq); + if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) + bfq_merge_bfqqs(bfqd, RQ_BIC(rq), + bfqq, new_bfqq); + rq->elv.priv[1] = new_bfqq; + bfqq = new_bfqq; + } else + bfq_bfqq_increase_failed_cooperations(bfqq); + } + bfq_add_request(rq); + /* + * Here a newly-created bfq_queue has already started a weight-raising + * period: clear raising_time_left to prevent bfq_bfqq_save_state() + * from assigning it a full weight-raising period. See the detailed + * comments about this field in bfq_init_icq(). + */ + if (bfqq->bic != NULL) + bfqq->bic->wr_time_left = 0; rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; list_add_tail(&rq->queuelist, &bfqq->fifo); @@ -3226,18 +3533,6 @@ static void bfq_put_request(struct request *rq) } } -static struct bfq_queue * -bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, - struct bfq_queue *bfqq) -{ - bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", - (long unsigned)bfqq->new_bfqq->pid); - bic_set_bfqq(bic, bfqq->new_bfqq, 1); - bfq_mark_bfqq_coop(bfqq->new_bfqq); - bfq_put_queue(bfqq); - return bic_to_bfqq(bic, 1); -} - /* * Returns NULL if a new bfqq should be allocated, or the old bfqq if this * was the last process referring to said bfqq. @@ -3246,6 +3541,9 @@ static struct bfq_queue * bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) { bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); + + put_io_context(bic->icq.ioc); + if (bfqq_process_refs(bfqq) == 1) { bfqq->pid = current->pid; bfq_clear_bfqq_coop(bfqq); @@ -3274,6 +3572,7 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, struct bfq_queue *bfqq; struct bfq_group *bfqg; unsigned long flags; + bool split = false; might_sleep_if(gfp_mask & __GFP_WAIT); @@ -3291,25 +3590,26 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); bic_set_bfqq(bic, bfqq, is_sync); + if (split && is_sync) { + if ((bic->was_in_burst_list && bfqd->large_burst) || + bic->saved_in_large_burst) + bfq_mark_bfqq_in_large_burst(bfqq); + else { + bfq_clear_bfqq_in_large_burst(bfqq); + if (bic->was_in_burst_list) + hlist_add_head(&bfqq->burst_list_node, + &bfqd->burst_list); + } + } } else { - /* - * If the queue was seeky for too long, break it apart. - */ + /* If the queue was seeky for too long, break it apart. */ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); bfqq = bfq_split_bfqq(bic, bfqq); + split = true; if (!bfqq) goto new_queue; } - - /* - * Check to see if this queue is scheduled to merge with - * another closely cooperating queue. The merging of queues - * happens here as it must be done in process context. - * The reference on new_bfqq was taken in merge_bfqqs. - */ - if (bfqq->new_bfqq != NULL) - bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); } bfqq->allocated[rw]++; @@ -3320,6 +3620,26 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, rq->elv.priv[0] = bic; rq->elv.priv[1] = bfqq; + /* + * If a bfq_queue has only one process reference, it is owned + * by only one bfq_io_cq: we can set the bic field of the + * bfq_queue to the address of that structure. Also, if the + * queue has just been split, mark a flag so that the + * information is available to the other scheduler hooks. + */ + if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { + bfqq->bic = bic; + if (split) { + bfq_mark_bfqq_just_split(bfqq); + /* + * If the queue has just been split from a shared + * queue, restore the idle window and the possible + * weight raising period. + */ + bfq_bfqq_resume_state(bfqq, bic); + } + } + spin_unlock_irqrestore(q->queue_lock, flags); return 0; diff --git a/block/bfq-sched.c b/block/bfq-sched.c index c3430993ec94..d0890c6d4c11 100644 --- a/block/bfq-sched.c +++ b/block/bfq-sched.c @@ -1085,34 +1085,6 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) return bfqq; } -/* - * Forced extraction of the given queue. - */ -static void bfq_get_next_queue_forced(struct bfq_data *bfqd, - struct bfq_queue *bfqq) -{ - struct bfq_entity *entity; - struct bfq_sched_data *sd; - - BUG_ON(bfqd->in_service_queue != NULL); - - entity = &bfqq->entity; - /* - * Bubble up extraction/update from the leaf to the root. - */ - for_each_entity(entity) { - sd = entity->sched_data; - bfq_update_budget(entity); - bfq_update_vtime(bfq_entity_service_tree(entity)); - bfq_active_extract(bfq_entity_service_tree(entity), entity); - sd->in_service_entity = entity; - sd->next_in_service = NULL; - entity->service = 0; - } - - return; -} - static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) { if (bfqd->in_service_bic != NULL) { diff --git a/block/bfq.h b/block/bfq.h index 3173b35e3853..629c413c16ab 100644 --- a/block/bfq.h +++ b/block/bfq.h @@ -218,18 +218,21 @@ struct bfq_group; * idle @bfq_queue with no outstanding requests, then * the task associated with the queue it is deemed as * soft real-time (see the comments to the function - * bfq_bfqq_softrt_next_start()). + * bfq_bfqq_softrt_next_start()) * @last_idle_bklogged: time of the last transition of the @bfq_queue from * idle to backlogged * @service_from_backlogged: cumulative service received from the @bfq_queue * since the last transition from idle to * backlogged + * @bic: pointer to the bfq_io_cq owning the bfq_queue, set to %NULL if the + * queue is shared * - * A bfq_queue is a leaf request queue; it can be associated with an io_context - * or more, if it is async or shared between cooperating processes. @cgroup - * holds a reference to the cgroup, to be sure that it does not disappear while - * a bfqq still references it (mostly to avoid races between request issuing and - * task migration followed by cgroup destruction). + * A bfq_queue is a leaf request queue; it can be associated with an + * io_context or more, if it is async or shared between cooperating + * processes. @cgroup holds a reference to the cgroup, to be sure that it + * does not disappear while a bfqq still references it (mostly to avoid + * races between request issuing and task migration followed by cgroup + * destruction). * All the fields are protected by the queue lock of the containing bfqd. */ struct bfq_queue { @@ -269,6 +272,7 @@ struct bfq_queue { unsigned int requests_within_timer; pid_t pid; + struct bfq_io_cq *bic; /* weight-raising fields */ unsigned long wr_cur_max_time; @@ -298,12 +302,42 @@ struct bfq_ttime { * @icq: associated io_cq structure * @bfqq: array of two process queues, the sync and the async * @ttime: associated @bfq_ttime struct + * @wr_time_left: snapshot of the time left before weight raising ends + * for the sync queue associated to this process; this + * snapshot is taken to remember this value while the weight + * raising is suspended because the queue is merged with a + * shared queue, and is used to set @raising_cur_max_time + * when the queue is split from the shared queue and its + * weight is raised again + * @saved_idle_window: same purpose as the previous field for the idle + * window + * @saved_IO_bound: same purpose as the previous two fields for the I/O + * bound classification of a queue + * @saved_in_large_burst: same purpose as the previous fields for the + * value of the field keeping the queue's belonging + * to a large burst + * @was_in_burst_list: true if the queue belonged to a burst list + * before its merge with another cooperating queue + * @cooperations: counter of consecutive successful queue merges underwent + * by any of the process' @bfq_queues + * @failed_cooperations: counter of consecutive failed queue merges of any + * of the process' @bfq_queues */ struct bfq_io_cq { struct io_cq icq; /* must be the first member */ struct bfq_queue *bfqq[2]; struct bfq_ttime ttime; int ioprio; + + unsigned int wr_time_left; + bool saved_idle_window; + bool saved_IO_bound; + + bool saved_in_large_burst; + bool was_in_burst_list; + + unsigned int cooperations; + unsigned int failed_cooperations; }; enum bfq_device_speed { @@ -536,7 +570,7 @@ enum bfqq_state_flags { BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ - BFQ_BFQQ_FLAG_IO_bound, /* + BFQ_BFQQ_FLAG_IO_bound, /* * bfqq has timed-out at least once * having consumed at most 2/10 of * its budget @@ -549,12 +583,13 @@ enum bfqq_state_flags { * bfqq has proved to be slow and * seeky until budget timeout */ - BFQ_BFQQ_FLAG_softrt_update, /* + BFQ_BFQQ_FLAG_softrt_update, /* * may need softrt-next-start * update */ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ - BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ + BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be split */ + BFQ_BFQQ_FLAG_just_split, /* queue has just been split */ }; #define BFQ_BFQQ_FNS(name) \ @@ -583,6 +618,7 @@ BFQ_BFQQ_FNS(in_large_burst); BFQ_BFQQ_FNS(constantly_seeky); BFQ_BFQQ_FNS(coop); BFQ_BFQQ_FNS(split_coop); +BFQ_BFQQ_FNS(just_split); BFQ_BFQQ_FNS(softrt_update); #undef BFQ_BFQQ_FNS From 3b7e44b8137f5835ccb14a34e288c293fc014e7f Mon Sep 17 00:00:00 2001 From: flar2 Date: Wed, 6 Nov 2013 23:24:29 -0500 Subject: [PATCH 021/203] AIO: Don't plug the I/O queue in do_io_submit() Signed-off-by: flar2 --- fs/aio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 58caa7e5d81c..9891498b9e24 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1555,7 +1555,6 @@ 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; @@ -1572,8 +1571,6 @@ 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? @@ -1596,7 +1593,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (ret) break; } - blk_finish_plug(&plug); percpu_ref_put(&ctx->users); return i ? i : ret; From 8515827f7403ea0d0148b10d6710a34ab4ed8221 Mon Sep 17 00:00:00 2001 From: David Collins Date: Wed, 2 Mar 2016 13:52:52 -0800 Subject: [PATCH 022/203] clk: msm: clock-cpu-8996: round clock rates to nearest fmax frequency Modify the round_rate() callback function so that it selects the nearest configured fmax frequency instead of the closest possible supported frequency of the parent clock. This ensures that clk_round_rate() always returns power efficient frequencies for 8996 CPU clocks. Change-Id: Icc27ba64b9c8af74ee0f81443fea37c4564b9f94 CRs-Fixed: 981475 Signed-off-by: David Collins Signed-off-by: flar2 --- drivers/clk/msm/clock-cpu-8996.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/msm/clock-cpu-8996.c b/drivers/clk/msm/clock-cpu-8996.c index e0779cf63e84..9286198055e7 100644 --- a/drivers/clk/msm/clock-cpu-8996.c +++ b/drivers/clk/msm/clock-cpu-8996.c @@ -551,7 +551,13 @@ static enum handoff cpu_clk_8996_handoff(struct clk *c) static long cpu_clk_8996_round_rate(struct clk *c, unsigned long rate) { - return clk_round_rate(c->parent, rate); + int i; + + for (i = 0; i < c->num_fmax; i++) + if (rate <= c->fmax[i]) + return clk_round_rate(c->parent, c->fmax[i]); + + return clk_round_rate(c->parent, c->fmax[c->num_fmax - 1]); } static unsigned long alt_pll_perfcl_freqs[] = { From 6b9cd39b1545d809f0eaae96f617e5cd7abf1e37 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Fri, 4 Mar 2016 17:45:31 -0800 Subject: [PATCH 023/203] ARM: dts: msm: correct CE clock setting for crypto driver on msm8996 Correct CE clock setting for crypto drivers, core_clk_src should link to voting clock; otherwise, ce1 clock is set to be only half of 171M HZ during crypto operations. Change-Id: I0d9e048381a83d4788bf4f700d788137b59bd368 Signed-off-by: Zhen Kong Signed-off-by: flar2 --- arch/arm/boot/dts/qcom/msm8996.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index 8cf7b1f015ea..9a7a5d78852b 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -2438,7 +2438,7 @@ <55 512 3936000 393600>; clock-names = "core_clk_src", "core_clk", "iface_clk", "bus_clk"; - clocks = <&clock_gcc clk_ce1_clk>, + clocks = <&clock_gcc clk_qcrypto_ce1_clk>, <&clock_gcc clk_qcrypto_ce1_clk>, <&clock_gcc clk_gcc_ce1_ahb_m_clk>, <&clock_gcc clk_gcc_ce1_axi_m_clk>; @@ -2468,7 +2468,7 @@ <55 512 3936000 393600>; clock-names = "core_clk_src", "core_clk", "iface_clk", "bus_clk"; - clocks = <&clock_gcc clk_ce1_clk>, + clocks = <&clock_gcc clk_qcedev_ce1_clk>, <&clock_gcc clk_qcedev_ce1_clk>, <&clock_gcc clk_gcc_ce1_ahb_m_clk>, <&clock_gcc clk_gcc_ce1_axi_m_clk>; From 8a9bc41097d7a866a35e53a7cb24de41248289ad Mon Sep 17 00:00:00 2001 From: Vikram Mulukutla Date: Mon, 26 Oct 2015 12:32:26 -0700 Subject: [PATCH 024/203] clk: msm: clock-cpu-8996: Update calibration settings Updated characterization has shown the need to modify certain calibration settings for hardware blocks within the CPU subsystem. Modify these values. CRs-Fixed: 930377 Change-Id: I601802746224e2abb43fd0b3aedb09e049062adf Signed-off-by: Vikram Mulukutla Signed-off-by: flar2 --- drivers/clk/msm/clock-cpu-8996.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/msm/clock-cpu-8996.c b/drivers/clk/msm/clock-cpu-8996.c index 9286198055e7..ac8adbb5a411 100644 --- a/drivers/clk/msm/clock-cpu-8996.c +++ b/drivers/clk/msm/clock-cpu-8996.c @@ -143,9 +143,9 @@ static int acdtd_val_pwrcl = 0x00006A11; static int acdtd_val_perfcl = 0x00006A11; static int dvmrc_val = 0x000E0F0F; static int acdsscr_val = 0x00000601; -static int acdcr_val_pwrcl = 0x002D5FFD; +static int acdcr_val_pwrcl = 0x002C5FFD; module_param(acdcr_val_pwrcl, int, 0444); -static int acdcr_val_perfcl = 0x002D5FFD; +static int acdcr_val_perfcl = 0x002C5FFD; module_param(acdcr_val_perfcl, int, 0444); int enable_acd = 1; module_param(enable_acd, int, 0444); From 0610501a5841518a6901a0e32885da563ae61a31 Mon Sep 17 00:00:00 2001 From: Sivanesan Rajapupathi Date: Fri, 26 Feb 2016 09:54:44 -0500 Subject: [PATCH 025/203] crypto: msm: crypto driver performance improvement To minimize spinlock, the qce50 client is assumed that it can only issue request to qce50 driver one at a time. After a request is issued to qce50 from qcrypto. Without waiting for completion, other requests can still be issued until the maximum limit of outstanding requests in qce50 reaches. To cut down the chance of udp socket receive buffer overflow the following schemes are provided - The number of bunched requests in qce50 is based on the data length of the current request to cut down delay for smaller packets. In turn, with smaller delay, the number of completed requests to process in seq_response() completion function is less. The scheduling of qcrypto requests are changed from least use to round robin. This way, the distribution of requests to each engine is more even. As the result, reordering of completed requests will be less. Completed requests to handle in completion callback is less at a time. Change-Id: I723bac2f9427cddb5248101c9ac3f2b595ad0379 Acked-by: Che-Min Hsieh Signed-off-by: Sivanesan Rajapupathi --- drivers/crypto/msm/qce50.c | 114 +++++++------ drivers/crypto/msm/qce50.h | 3 +- drivers/crypto/msm/qcrypto.c | 303 +++++++++++++++++++++++++---------- 3 files changed, 289 insertions(+), 131 deletions(-) diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 36949f4b3f14..eb0e8fa1fbb2 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -1,6 +1,6 @@ /* Qualcomm Crypto Engine driver. * - * 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 @@ -69,7 +69,7 @@ static LIST_HEAD(qce50_bam_list); /* Max number of request supported */ #define MAX_QCE_BAM_REQ 8 /* Interrupt flag will be set for every SET_INTR_AT_REQ request */ -#define SET_INTR_AT_REQ (MAX_QCE_BAM_REQ - 2) +#define SET_INTR_AT_REQ (MAX_QCE_BAM_REQ / 2) /* To create extra request space to hold dummy request */ #define MAX_QCE_BAM_REQ_WITH_DUMMY_REQ (MAX_QCE_BAM_REQ + 1) /* Allocate the memory for MAX_QCE_BAM_REQ + 1 (for dummy request) */ @@ -84,6 +84,12 @@ static LIST_HEAD(qce50_bam_list); /* Index to point the dummy request */ #define DUMMY_REQ_INDEX MAX_QCE_BAM_REQ +enum qce_owner { + QCE_OWNER_NONE = 0, + QCE_OWNER_CLIENT = 1, + QCE_OWNER_TIMEOUT = 2 +}; + struct dummy_request { struct qce_sha_req sreq; uint8_t *in_buf; @@ -133,9 +139,8 @@ struct qce_device { struct ce_bam_info ce_bam_info; struct ce_request_info ce_request_info[MAX_QCE_ALLOC_BAM_REQ]; unsigned int ce_request_index; - spinlock_t lock; - spinlock_t sps_lock; - unsigned int no_of_queued_req; + enum qce_owner owner; + atomic_t no_of_queued_req; struct timer_list timer; struct dummy_request dummyreq; unsigned int mode; @@ -144,6 +149,7 @@ struct qce_device { struct qce_driver_stats qce_stats; atomic_t bunch_cmd_seq; atomic_t last_intr_seq; + bool cadence_flag; }; static void print_notify_debug(struct sps_event_notify *notify); @@ -2477,7 +2483,6 @@ static int _qce_sps_add_cmd(struct qce_device *pce_dev, uint32_t flag, static int _qce_sps_transfer(struct qce_device *pce_dev, int req_info) { int rc = 0; - unsigned long flags; struct ce_sps_data *pce_sps_data; pce_sps_data = &pce_dev->ce_request_info[req_info].ce_sps; @@ -2489,7 +2494,6 @@ static int _qce_sps_transfer(struct qce_device *pce_dev, int req_info) (unsigned int) req_info)); _qce_dump_descr_fifos_dbg(pce_dev, req_info); - spin_lock_irqsave(&pce_dev->sps_lock, flags); if (pce_sps_data->in_transfer.iovec_count) { rc = sps_transfer(pce_dev->ce_bam_info.consumer.pipe, &pce_sps_data->in_transfer); @@ -2508,7 +2512,6 @@ static int _qce_sps_transfer(struct qce_device *pce_dev, int req_info) ret: if (rc) _qce_dump_descr_fifos(pce_dev, req_info); - spin_unlock_irqrestore(&pce_dev->sps_lock, flags); return rc; } @@ -2892,23 +2895,20 @@ static inline int qce_alloc_req_info(struct qce_device *pce_dev) } } pr_warn("pcedev %d no reqs available no_of_queued_req %d\n", - pce_dev->dev_no, pce_dev->no_of_queued_req); + pce_dev->dev_no, atomic_read( + &pce_dev->no_of_queued_req)); return -EBUSY; } static inline void qce_free_req_info(struct qce_device *pce_dev, int req_info, bool is_complete) { - unsigned long flags; - - spin_lock_irqsave(&pce_dev->lock, flags); pce_dev->ce_request_info[req_info].xfer_type = QCE_XFER_TYPE_LAST; if (xchg(&pce_dev->ce_request_info[req_info].in_use, false) == true) { if (req_info < MAX_QCE_BAM_REQ && is_complete) - pce_dev->no_of_queued_req--; + atomic_dec(&pce_dev->no_of_queued_req); } else pr_warn("request info %d free already\n", req_info); - spin_unlock_irqrestore(&pce_dev->lock, flags); } static void print_notify_debug(struct sps_event_notify *notify) @@ -2955,7 +2955,6 @@ static void qce_multireq_timeout(unsigned long data) { struct qce_device *pce_dev = (struct qce_device *)data; int ret = 0; - unsigned long flags; int last_seq; last_seq = atomic_read(&pce_dev->bunch_cmd_seq); @@ -2966,27 +2965,29 @@ static void qce_multireq_timeout(unsigned long data) return; } /* last bunch mode command time out */ - spin_lock_irqsave(&pce_dev->lock, flags); + if (cmpxchg(&pce_dev->owner, QCE_OWNER_NONE, QCE_OWNER_TIMEOUT) + != QCE_OWNER_NONE) { + mod_timer(&(pce_dev->timer), (jiffies + DELAY_IN_JIFFIES)); + return; + } del_timer(&(pce_dev->timer)); pce_dev->mode = IN_INTERRUPT_MODE; pce_dev->qce_stats.no_of_timeouts++; pr_debug("pcedev %d mode switch to INTR\n", pce_dev->dev_no); - spin_unlock_irqrestore(&pce_dev->lock, flags); ret = qce_dummy_req(pce_dev); if (ret) pr_warn("pcedev %d: Failed to insert dummy req\n", pce_dev->dev_no); + cmpxchg(&pce_dev->owner, QCE_OWNER_TIMEOUT, QCE_OWNER_NONE); } void qce_get_driver_stats(void *handle) { - unsigned long flags; struct qce_device *pce_dev = (struct qce_device *) handle; if (!_qce50_disp_stats) return; - spin_lock_irqsave(&pce_dev->lock, flags); pr_info("Engine %d timeout occuured %d\n", pce_dev->dev_no, pce_dev->qce_stats.no_of_timeouts); pr_info("Engine %d dummy request inserted %d\n", pce_dev->dev_no, @@ -2996,20 +2997,16 @@ void qce_get_driver_stats(void *handle) else pr_info("Engine %d is in INTERRUPT MODE\n", pce_dev->dev_no); pr_info("Engine %d outstanding request %d\n", pce_dev->dev_no, - pce_dev->no_of_queued_req); - spin_unlock_irqrestore(&pce_dev->lock, flags); + atomic_read(&pce_dev->no_of_queued_req)); } EXPORT_SYMBOL(qce_get_driver_stats); void qce_clear_driver_stats(void *handle) { - unsigned long flags; struct qce_device *pce_dev = (struct qce_device *) handle; - spin_lock_irqsave(&pce_dev->lock, flags); pce_dev->qce_stats.no_of_timeouts = 0; pce_dev->qce_stats.no_of_dummy_reqs = 0; - spin_unlock_irqrestore(&pce_dev->lock, flags); } EXPORT_SYMBOL(qce_clear_driver_stats); @@ -3021,7 +3018,6 @@ static void _sps_producer_callback(struct sps_event_notify *notify) unsigned int req_info; struct ce_sps_data *pce_sps_data; struct ce_request_info *preq_info; - unsigned long flags; print_notify_debug(notify); @@ -3050,10 +3046,8 @@ static void _sps_producer_callback(struct sps_event_notify *notify) &pce_sps_data->out_transfer); _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); - spin_lock_irqsave(&pce_dev->sps_lock, flags); rc = sps_transfer(pce_dev->ce_bam_info.producer.pipe, &pce_sps_data->out_transfer); - spin_unlock_irqrestore(&pce_dev->sps_lock, flags); if (rc) { pr_err("sps_xfr() fail (producer pipe=0x%lx) rc = %d\n", (uintptr_t)pce_dev->ce_bam_info.producer.pipe, @@ -4527,18 +4521,27 @@ static int qce_dummy_req(struct qce_device *pce_dev) static int select_mode(struct qce_device *pce_dev, struct ce_request_info *preq_info) { - unsigned long flags; struct ce_sps_data *pce_sps_data = &preq_info->ce_sps; + unsigned int no_of_queued_req; + unsigned int cadence; if (!pce_dev->no_get_around) { _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); return 0; } - spin_lock_irqsave(&pce_dev->lock, flags); - pce_dev->no_of_queued_req++; + /* + * claim ownership of device + */ +again: + if (cmpxchg(&pce_dev->owner, QCE_OWNER_NONE, QCE_OWNER_CLIENT) + != QCE_OWNER_NONE) { + ndelay(40); + goto again; + } + no_of_queued_req = atomic_inc_return(&pce_dev->no_of_queued_req); if (pce_dev->mode == IN_INTERRUPT_MODE) { - if (pce_dev->no_of_queued_req >= MAX_BUNCH_MODE_REQ) { + if (no_of_queued_req >= MAX_BUNCH_MODE_REQ) { pce_dev->mode = IN_BUNCH_MODE; pr_debug("pcedev %d mode switch to BUNCH\n", pce_dev->dev_no); @@ -4555,17 +4558,21 @@ static int select_mode(struct qce_device *pce_dev, } } else { pce_dev->intr_cadence++; - if (pce_dev->intr_cadence >= SET_INTR_AT_REQ) { + cadence = (preq_info->req_len >> 7) + 1; + if (cadence > SET_INTR_AT_REQ) + cadence = SET_INTR_AT_REQ; + if (pce_dev->intr_cadence < cadence || ((pce_dev->intr_cadence + == cadence) && pce_dev->cadence_flag)) + atomic_inc(&pce_dev->bunch_cmd_seq); + else { _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); pce_dev->intr_cadence = 0; atomic_set(&pce_dev->bunch_cmd_seq, 0); atomic_set(&pce_dev->last_intr_seq, 0); - } else { - atomic_inc(&pce_dev->bunch_cmd_seq); + pce_dev->cadence_flag = ~pce_dev->cadence_flag; } } - spin_unlock_irqrestore(&pce_dev->lock, flags); return 0; } @@ -4675,6 +4682,7 @@ static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_AEAD; + preq_info->req_len = totallen_in; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -4712,6 +4720,7 @@ static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req) SPS_IOVEC_FLAG_INT); pce_sps_data->producer_state = QCE_PIPE_STATE_COMP; } + rc = _qce_sps_transfer(pce_dev, req_info); } else { if (_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen, &pce_sps_data->in_transfer)) @@ -4758,8 +4767,9 @@ static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req) _qce_ccm_get_around_output(pce_dev, preq_info, q_req->dir); select_mode(pce_dev, preq_info); + rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); } - rc = _qce_sps_transfer(pce_dev, req_info); if (rc) goto bad; return 0; @@ -4949,6 +4959,7 @@ int qce_aead_req(void *handle, struct qce_req *q_req) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_AEAD; + preq_info->req_len = totallen; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -4989,6 +5000,7 @@ int qce_aead_req(void *handle, struct qce_req *q_req) SPS_IOVEC_FLAG_INT); pce_sps_data->producer_state = QCE_PIPE_STATE_COMP; } + rc = _qce_sps_transfer(pce_dev, req_info); } else { if (_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen, &pce_sps_data->in_transfer)) @@ -5028,8 +5040,9 @@ int qce_aead_req(void *handle, struct qce_req *q_req) pce_sps_data->producer_state = QCE_PIPE_STATE_IDLE; } select_mode(pce_dev, preq_info); + rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); } - rc = _qce_sps_transfer(pce_dev, req_info); if (rc) goto bad; return 0; @@ -5123,6 +5136,7 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_CIPHERING; + preq_info->req_len = areq->nbytes; _qce_sps_iovec_count_init(pce_dev, req_info); if (pce_dev->support_cmd_dscr) @@ -5154,8 +5168,8 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) } select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc) goto bad; @@ -5227,6 +5241,7 @@ int qce_process_sha_req(void *handle, struct qce_sha_req *sreq) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_HASHING; + preq_info->req_len = sreq->size; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -5255,11 +5270,14 @@ int qce_process_sha_req(void *handle, struct qce_sha_req *sreq) &pce_sps_data->out_transfer)) goto bad; - if (is_dummy) + if (is_dummy) { _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); - else + rc = _qce_sps_transfer(pce_dev, req_info); + } else { select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); + } if (rc) goto bad; return 0; @@ -5347,6 +5365,7 @@ int qce_f8_req(void *handle, struct qce_f8_req *req, /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_F8; + preq_info->req_len = req->data_len; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -5372,8 +5391,8 @@ int qce_f8_req(void *handle, struct qce_f8_req *req, &pce_sps_data->out_transfer); select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc) goto bad; return 0; @@ -5462,6 +5481,7 @@ int qce_f8_multi_pkt_req(void *handle, struct qce_f8_multi_pkt_req *mreq, /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_F8; + preq_info->req_len = total; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -5486,8 +5506,8 @@ int qce_f8_multi_pkt_req(void *handle, struct qce_f8_multi_pkt_req *mreq, &pce_sps_data->out_transfer); select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc == 0) return 0; @@ -5548,6 +5568,7 @@ int qce_f9_req(void *handle, struct qce_f9_req *req, void *cookie, /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_F9; + preq_info->req_len = req->msize; _qce_sps_iovec_count_init(pce_dev, req_info); if (pce_dev->support_cmd_dscr) @@ -5567,8 +5588,8 @@ int qce_f9_req(void *handle, struct qce_f9_req *req, void *cookie, &pce_sps_data->out_transfer); select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc) goto bad; return 0; @@ -5933,9 +5954,7 @@ void *qce_open(struct platform_device *pdev, int *rc) qce_setup_ce_sps_data(pce_dev); qce_disable_clk(pce_dev); setup_dummy_req(pce_dev); - spin_lock_init(&pce_dev->lock); - spin_lock_init(&pce_dev->sps_lock); - pce_dev->no_of_queued_req = 0; + atomic_set(&pce_dev->no_of_queued_req, 0); pce_dev->mode = IN_INTERRUPT_MODE; init_timer(&(pce_dev->timer)); pce_dev->timer.function = qce_multireq_timeout; @@ -5944,6 +5963,7 @@ void *qce_open(struct platform_device *pdev, int *rc) pce_dev->intr_cadence = 0; pce_dev->dev_no = pcedev_no; pcedev_no++; + pce_dev->owner = QCE_OWNER_NONE; mutex_unlock(&qce_iomap_mutex); return pce_dev; err: diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h index 19f6edf21878..d3d558b22988 100644 --- a/drivers/crypto/msm/qce50.h +++ b/drivers/crypto/msm/qce50.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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 @@ -228,6 +228,7 @@ struct ce_request_info { dma_addr_t phy_ota_src; dma_addr_t phy_ota_dst; unsigned int ota_size; + unsigned int req_len; }; struct qce_driver_stats { diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index ddd3812c74b1..be3d3fcdebf5 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -51,7 +52,7 @@ #include "qce.h" #define DEBUG_MAX_FNAME 16 -#define DEBUG_MAX_RW_BUF 2048 +#define DEBUG_MAX_RW_BUF 4096 #define QCRYPTO_BIG_NUMBER 9999999 /* a big number */ /* @@ -131,6 +132,7 @@ struct qcrypto_req_control { struct crypto_engine *pce; struct crypto_async_request *req; struct qcrypto_resp_ctx *arsp; + int res; /* execution result */ }; struct crypto_engine { @@ -167,8 +169,14 @@ struct crypto_engine { unsigned int max_req; struct qcrypto_req_control *preq_pool; atomic_t req_count; + bool issue_req; /* an request is being issued to qce */ + bool first_engine; /* this engine is the first engine or not */ + unsigned int irq_cpu; /* the cpu running the irq of this engine */ + unsigned int max_req_used; /* debug stats */ }; +#define MAX_SMP_CPU 8 + struct crypto_priv { /* CE features supported by target device*/ struct msm_ce_hw_support platform_support; @@ -208,21 +216,37 @@ struct crypto_priv { enum resp_workq_sts sched_resp_workq_status; enum req_processing_sts ce_req_proc_sts; int cpu_getting_irqs_frm_first_ce; + struct crypto_engine *first_engine; + struct crypto_engine *scheduled_eng; /* last engine scheduled */ + + /* debug stats */ + unsigned no_avail; + unsigned resp_stop; + unsigned resp_start; + unsigned max_qlen; + unsigned int queue_work_eng3; + unsigned int queue_work_not_eng3; + unsigned int queue_work_not_eng3_nz; + unsigned int max_resp_qlen; + unsigned int max_reorder_cnt; + unsigned int cpu_req[MAX_SMP_CPU+1]; }; static struct crypto_priv qcrypto_dev; static struct crypto_engine *_qcrypto_static_assign_engine( struct crypto_priv *cp); static struct crypto_engine *_avail_eng(struct crypto_priv *cp); - static struct qcrypto_req_control *qcrypto_alloc_req_control( struct crypto_engine *pce) { int i; struct qcrypto_req_control *pqcrypto_req_control = pce->preq_pool; + unsigned int req_count; for (i = 0; i < pce->max_req; i++) { if (xchg(&pqcrypto_req_control->in_use, true) == false) { - atomic_inc(&pce->req_count); + req_count = atomic_inc_return(&pce->req_count); + if (req_count > pce->max_req_used) + pce->max_req_used = req_count; return pqcrypto_req_control; } pqcrypto_req_control++; @@ -233,11 +257,13 @@ static struct qcrypto_req_control *qcrypto_alloc_req_control( static void qcrypto_free_req_control(struct crypto_engine *pce, struct qcrypto_req_control *preq) { + /* do this before free req */ + preq->req = NULL; + preq->arsp = NULL; + /* free req */ if (xchg(&preq->in_use, false) == false) { pr_warn("request info %p free already\n", preq); } else { - preq->req = NULL; - preq->arsp = NULL; atomic_dec(&pce->req_count); } } @@ -441,7 +467,9 @@ struct qcrypto_cipher_req_ctx { #define SHA_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE #define MSM_QCRYPTO_REQ_QUEUE_LENGTH 768 -#define COMPLETION_CB_BACKLOG_LENGTH 768 +#define COMPLETION_CB_BACKLOG_LENGTH_STOP 400 +#define COMPLETION_CB_BACKLOG_LENGTH_START \ + (COMPLETION_CB_BACKLOG_LENGTH_STOP / 2) static uint8_t _std_init_vector_sha1_uint8[] = { 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, 0x89, @@ -1050,6 +1078,7 @@ static int _disp_stats(int id) unsigned long flags; struct crypto_priv *cp = &qcrypto_dev; struct crypto_engine *pe; + int i; pstat = &_qcrypto_stat; len = scnprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1, @@ -1171,6 +1200,18 @@ static int _disp_stats(int id) len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, " AHASH operation fail : %llu\n", pstat->ahash_op_fail); + len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " resp start, resp stop, max rsp queue reorder-cnt : %u %u %u %u\n", + cp->resp_start, cp->resp_stop, + cp->max_resp_qlen, cp->max_reorder_cnt); + len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " max queue legnth, no avail : %u %u\n", + cp->max_qlen, cp->no_avail); + len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " work queue : %u %u %u\n", + cp->queue_work_eng3, + cp->queue_work_not_eng3, + cp->queue_work_not_eng3_nz); len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, "\n"); spin_lock_irqsave(&cp->lock, flags); @@ -1178,8 +1219,9 @@ static int _disp_stats(int id) len += scnprintf( _debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, - " Engine %4d Req : %llu\n", + " Engine %4d Req max %d : %llu\n", pe->unit, + pe->max_req_used, pe->total_req ); len += scnprintf( @@ -1192,6 +1234,14 @@ static int _disp_stats(int id) qce_get_driver_stats(pe->qce); } spin_unlock_irqrestore(&cp->lock, flags); + + for (i = 0; i < MAX_SMP_CPU+1; i++) + if (cp->cpu_req[i]) + len += scnprintf( + _debug_read_buf + len, + DEBUG_MAX_RW_BUF - len - 1, + "CPU %d Issue Req : %d\n", + i, cp->cpu_req[i]); return len; } @@ -1201,13 +1251,25 @@ static void _qcrypto_remove_engine(struct crypto_engine *pengine) struct qcrypto_alg *q_alg; struct qcrypto_alg *n; unsigned long flags; + struct crypto_engine *pe; cp = pengine->pcp; spin_lock_irqsave(&cp->lock, flags); list_del(&pengine->elist); + if (pengine->first_engine) { + cp->first_engine = NULL; + pe = list_first_entry(&cp->engine_list, struct crypto_engine, + elist); + if (pe) { + pe->first_engine = true; + cp->first_engine = pe; + } + } if (cp->next_engine == pengine) cp->next_engine = NULL; + if (cp->scheduled_eng == pengine) + cp->scheduled_eng = NULL; spin_unlock_irqrestore(&cp->lock, flags); cp->total_units--; @@ -1414,41 +1476,15 @@ static int _qcrypto_setkey_3des(struct crypto_ablkcipher *cipher, const u8 *key, return 0; }; -static struct crypto_engine *eng_sel_avoid_first(struct crypto_priv *cp) -{ - /* - * This function need not be spinlock protected when called from - * the seq_response workq as it will not have any contentions when all - * request processing is stopped. - */ - struct crypto_engine *p; - struct crypto_engine *q = NULL; - int max_user = QCRYPTO_BIG_NUMBER; - int use_cnt; - - if (unlikely(list_empty(&cp->engine_list))) { - pr_err("%s: no valid ce to schedule\n", __func__); - return NULL; - } - - p = list_first_entry(&cp->engine_list, struct crypto_engine, - elist); - list_for_each_entry_continue(p, &cp->engine_list, elist) { - use_cnt = atomic_read(&p->req_count); - if ((use_cnt < p->max_req) && (use_cnt < max_user)) { - q = p; - max_user = use_cnt; - } - } - return q; -} - static void seq_response(struct work_struct *work) { struct crypto_priv *cp = container_of(work, struct crypto_priv, resp_work); struct llist_node *list; struct llist_node *rev = NULL; + struct crypto_engine *pengine; + unsigned long flags; + int total_unit; again: list = llist_del_all(&cp->ordered_resp_list); @@ -1467,7 +1503,6 @@ static void seq_response(struct work_struct *work) while (rev) { struct qcrypto_resp_ctx *arsp; struct crypto_async_request *areq; - struct crypto_engine *pengine; arsp = container_of(rev, struct qcrypto_resp_ctx, llist); rev = llist_next(rev); @@ -1477,12 +1512,20 @@ static void seq_response(struct work_struct *work) areq->complete(areq, arsp->res); local_bh_enable(); atomic_dec(&cp->resp_cnt); - if (ACCESS_ONCE(cp->ce_req_proc_sts) == STOPPED && - atomic_read(&cp->resp_cnt) <= - (COMPLETION_CB_BACKLOG_LENGTH / 2)) { - pengine = eng_sel_avoid_first(cp); + } + + if (atomic_read(&cp->resp_cnt) < COMPLETION_CB_BACKLOG_LENGTH_START && + (cmpxchg(&cp->ce_req_proc_sts, STOPPED, IN_PROGRESS) + == STOPPED)) { + cp->resp_start++; + for (total_unit = cp->total_units; total_unit-- > 0;) { + spin_lock_irqsave(&cp->lock, flags); + pengine = _avail_eng(cp); + spin_unlock_irqrestore(&cp->lock, flags); if (pengine) _start_qcrypto_process(cp, pengine); + else + break; } } end: @@ -1494,12 +1537,19 @@ static void seq_response(struct work_struct *work) goto end; } -static void _qcrypto_tfm_complete(struct crypto_priv *cp, u32 type, - void *tfm_ctx) +#define SCHEUDLE_RSP_QLEN_THRESHOLD 64 + +static void _qcrypto_tfm_complete(struct crypto_engine *pengine, u32 type, + void *tfm_ctx, + struct qcrypto_resp_ctx *cur_arsp, + int res) { + struct crypto_priv *cp = pengine->pcp; unsigned long flags; struct qcrypto_resp_ctx *arsp; struct list_head *plist; + unsigned int resp_qlen; + unsigned int cnt = 0; switch (type) { case CRYPTO_ALG_TYPE_AHASH: @@ -1513,6 +1563,8 @@ static void _qcrypto_tfm_complete(struct crypto_priv *cp, u32 type, } spin_lock_irqsave(&cp->lock, flags); + + cur_arsp->res = res; while (!list_empty(plist)) { arsp = list_first_entry(plist, struct qcrypto_resp_ctx, list); @@ -1521,16 +1573,51 @@ static void _qcrypto_tfm_complete(struct crypto_priv *cp, u32 type, else { list_del(&arsp->list); llist_add(&arsp->llist, &cp->ordered_resp_list); + atomic_inc(&cp->resp_cnt); + cnt++; } } + resp_qlen = atomic_read(&cp->resp_cnt); + if (resp_qlen > cp->max_resp_qlen) + cp->max_resp_qlen = resp_qlen; + if (cnt > cp->max_reorder_cnt) + cp->max_reorder_cnt = cnt; + if ((resp_qlen >= COMPLETION_CB_BACKLOG_LENGTH_STOP) && + cmpxchg(&cp->ce_req_proc_sts, IN_PROGRESS, + STOPPED) == IN_PROGRESS) { + cp->resp_stop++; + } + spin_unlock_irqrestore(&cp->lock, flags); retry: if (!llist_empty(&cp->ordered_resp_list)) { + unsigned int cpu; + + if (pengine->first_engine) { + cpu = WORK_CPU_UNBOUND; + cp->queue_work_eng3++; + } else { + cp->queue_work_not_eng3++; + cpu = cp->cpu_getting_irqs_frm_first_ce; + /* + * If source not the first engine, and there + * are outstanding requests going on first engine, + * skip scheduling of work queue to anticipate + * more may be coming. If the response queue + * length exceeds threshold, to avoid further + * delay, schedule work queue immediately. + */ + if (cp->first_engine && atomic_read( + &cp->first_engine->req_count)) { + if (resp_qlen < SCHEUDLE_RSP_QLEN_THRESHOLD) + return; + cp->queue_work_not_eng3_nz++; + } + } if (cmpxchg(&cp->sched_resp_workq_status, NOT_SCHEDULED, IS_SCHEDULED) == NOT_SCHEDULED) - queue_work_on(cp->cpu_getting_irqs_frm_first_ce, - cp->resp_wq, &cp->resp_work); + queue_work_on(cpu, cp->resp_wq, &cp->resp_work); else if (cmpxchg(&cp->sched_resp_workq_status, IS_SCHEDULED, SCHEDULE_AGAIN) == NOT_SCHEDULED) goto retry; @@ -1541,36 +1628,34 @@ static void req_done(struct qcrypto_req_control *pqcrypto_req_control) { struct crypto_engine *pengine; struct crypto_async_request *areq; - struct crypto_engine *pe; struct crypto_priv *cp; - unsigned long flags; struct qcrypto_resp_ctx *arsp; u32 type = 0; void *tfm_ctx = NULL; + unsigned int cpu; + int res; pengine = pqcrypto_req_control->pce; cp = pengine->pcp; - spin_lock_irqsave(&cp->lock, flags); areq = pqcrypto_req_control->req; arsp = pqcrypto_req_control->arsp; + res = pqcrypto_req_control->res; qcrypto_free_req_control(pengine, pqcrypto_req_control); if (areq) { type = crypto_tfm_alg_type(areq->tfm); tfm_ctx = crypto_tfm_ctx(areq->tfm); } - pe = list_first_entry(&cp->engine_list, struct crypto_engine, elist); - if (pe == pengine) - if (cp->cpu_getting_irqs_frm_first_ce != smp_processor_id()) - cp->cpu_getting_irqs_frm_first_ce = smp_processor_id(); - spin_unlock_irqrestore(&cp->lock, flags); - if (atomic_read(&cp->resp_cnt) <= COMPLETION_CB_BACKLOG_LENGTH) { - cmpxchg(&cp->ce_req_proc_sts, STOPPED, IN_PROGRESS); - _start_qcrypto_process(cp, pengine); - } else - cmpxchg(&cp->ce_req_proc_sts, IN_PROGRESS, STOPPED); + cpu = smp_processor_id(); + pengine->irq_cpu = cpu; + if (pengine->first_engine) { + if (cpu != cp->cpu_getting_irqs_frm_first_ce) + cp->cpu_getting_irqs_frm_first_ce = cpu; + } if (areq) - _qcrypto_tfm_complete(cp, type, tfm_ctx); + _qcrypto_tfm_complete(pengine, type, tfm_ctx, arsp, res); + if (ACCESS_ONCE(cp->ce_req_proc_sts) == IN_PROGRESS) + _start_qcrypto_process(cp, pengine); } static void _qce_ahash_complete(void *cookie, unsigned char *digest, @@ -1620,10 +1705,10 @@ static void _qce_ahash_complete(void *cookie, unsigned char *digest, rctx->first_blk = 0; if (ret) { - pqcrypto_req_control->arsp->res = -ENXIO; + pqcrypto_req_control->res = -ENXIO; pstat->ahash_op_fail++; } else { - pqcrypto_req_control->arsp->res = 0; + pqcrypto_req_control->res = 0; pstat->ahash_op_success++; } if (cp->ce_support.aligned_only) { @@ -1665,10 +1750,10 @@ static void _qce_ablk_cipher_complete(void *cookie, unsigned char *icb, memcpy(ctx->iv, iv, crypto_ablkcipher_ivsize(ablk)); if (ret) { - pqcrypto_req_control->arsp->res = -ENXIO; + pqcrypto_req_control->res = -ENXIO; pstat->ablk_cipher_op_fail++; } else { - pqcrypto_req_control->arsp->res = 0; + pqcrypto_req_control->res = 0; pstat->ablk_cipher_op_success++; } @@ -1811,7 +1896,7 @@ static void _qce_aead_complete(void *cookie, unsigned char *icv, else pstat->aead_op_success++; - pqcrypto_req_control->arsp->res = ret; + pqcrypto_req_control->res = ret; req_done(pqcrypto_req_control); } @@ -2272,12 +2357,24 @@ static int _start_qcrypto_process(struct crypto_priv *cp, struct aead_request *aead_req; struct qcrypto_resp_ctx *arsp; struct qcrypto_req_control *pqcrypto_req_control; + unsigned int cpu = MAX_SMP_CPU; + + if (ACCESS_ONCE(cp->ce_req_proc_sts) == STOPPED) + return 0; + + if (in_interrupt()) { + cpu = smp_processor_id(); + if (cpu >= MAX_SMP_CPU) + cpu = MAX_SMP_CPU - 1; + } else + cpu = MAX_SMP_CPU; pstat = &_qcrypto_stat; again: spin_lock_irqsave(&cp->lock, flags); - if (atomic_read(&pengine->req_count) >= (pengine->max_req)) { + if (pengine->issue_req || + atomic_read(&pengine->req_count) >= (pengine->max_req)) { spin_unlock_irqrestore(&cp->lock, flags); return 0; } @@ -2348,7 +2445,6 @@ static int _start_qcrypto_process(struct crypto_priv *cp, break; } - atomic_inc(&cp->resp_cnt); arsp->res = -EINPROGRESS; arsp->async_req = async_req; pqcrypto_req_control->pce = pengine; @@ -2357,6 +2453,10 @@ static int _start_qcrypto_process(struct crypto_priv *cp, pengine->active_seq++; pengine->check_flag = true; + pengine->issue_req = true; + cp->cpu_req[cpu]++; + smp_mb(); /* make it visible */ + spin_unlock_irqrestore(&cp->lock, flags); if (backlog_eng) backlog_eng->complete(backlog_eng, -EINPROGRESS); @@ -2376,9 +2476,12 @@ static int _start_qcrypto_process(struct crypto_priv *cp, default: ret = -EINVAL; }; + + pengine->issue_req = false; + smp_mb(); /* make it visible */ + pengine->total_req++; if (ret) { - arsp->res = ret; pengine->err_req++; qcrypto_free_req_control(pengine, pqcrypto_req_control); @@ -2390,32 +2493,48 @@ static int _start_qcrypto_process(struct crypto_priv *cp, else pstat->aead_op_fail++; - _qcrypto_tfm_complete(cp, type, tfm_ctx); + _qcrypto_tfm_complete(pengine, type, tfm_ctx, arsp, ret); goto again; }; return ret; } +static inline struct crypto_engine *_next_eng(struct crypto_priv *cp, + struct crypto_engine *p) +{ + + if (p == NULL || list_is_last(&p->elist, &cp->engine_list)) + p = list_first_entry(&cp->engine_list, struct crypto_engine, + elist); + else + p = list_entry(p->elist.next, struct crypto_engine, elist); + return p; +} static struct crypto_engine *_avail_eng(struct crypto_priv *cp) { /* call this function with spinlock set */ - struct crypto_engine *p; struct crypto_engine *q = NULL; - int max_user = QCRYPTO_BIG_NUMBER; - int use_cnt; + struct crypto_engine *p = cp->scheduled_eng; + struct crypto_engine *q1; + int eng_cnt = cp->total_units; if (unlikely(list_empty(&cp->engine_list))) { pr_err("%s: no valid ce to schedule\n", __func__); return NULL; } - list_for_each_entry(p, &cp->engine_list, elist) { - use_cnt = atomic_read(&p->req_count); - if ((use_cnt < p->max_req) && (use_cnt < max_user)) { + p = _next_eng(cp, p); + q1 = p; + while (eng_cnt-- > 0) { + if (!p->issue_req && atomic_read(&p->req_count) < p->max_req) { q = p; - max_user = use_cnt; + break; } + p = _next_eng(cp, p); + if (q1 == p) + break; } + cp->scheduled_eng = q; return q; } @@ -2433,6 +2552,8 @@ static int _qcrypto_queue_req(struct crypto_priv *cp, } else { ret = crypto_enqueue_request(&cp->req_queue, req); pengine = _avail_eng(cp); + if (cp->req_queue.qlen > cp->max_qlen) + cp->max_qlen = cp->req_queue.qlen; } if (pengine) { switch (pengine->bw_state) { @@ -2458,16 +2579,12 @@ static int _qcrypto_queue_req(struct crypto_priv *cp, pengine = NULL; break; } + } else { + cp->no_avail++; } spin_unlock_irqrestore(&cp->lock, flags); - if (pengine) { - if (atomic_read(&cp->resp_cnt) <= - COMPLETION_CB_BACKLOG_LENGTH) { - cmpxchg(&cp->ce_req_proc_sts, STOPPED, IN_PROGRESS); - _start_qcrypto_process(cp, pengine); - } else - cmpxchg(&cp->ce_req_proc_sts, IN_PROGRESS, STOPPED); - } + if (pengine && (ACCESS_ONCE(cp->ce_req_proc_sts) == IN_PROGRESS)) + _start_qcrypto_process(cp, pengine); return ret; } @@ -5082,6 +5199,8 @@ static int _qcrypto_probe(struct platform_device *pdev) pengine->active_seq = 0; pengine->last_active_seq = 0; pengine->check_flag = false; + pengine->max_req_used = 0; + pengine->issue_req = false; crypto_init_queue(&pengine->req_queue, MSM_QCRYPTO_REQ_QUEUE_LENGTH); @@ -5090,6 +5209,9 @@ static int _qcrypto_probe(struct platform_device *pdev) pengine->unit = cp->total_units; spin_lock_irqsave(&cp->lock, flags); + pengine->first_engine = list_empty(&cp->engine_list); + if (pengine->first_engine) + cp->first_engine = pengine; list_add_tail(&pengine->elist, &cp->engine_list); cp->next_engine = pengine; spin_unlock_irqrestore(&cp->lock, flags); @@ -5613,6 +5735,7 @@ static ssize_t _debug_stats_write(struct file *file, const char __user *buf, unsigned long flags; struct crypto_priv *cp = &qcrypto_dev; struct crypto_engine *pe; + int i; memset((char *)&_qcrypto_stat, 0, sizeof(struct crypto_stat)); spin_lock_irqsave(&cp->lock, flags); @@ -5620,7 +5743,19 @@ static ssize_t _debug_stats_write(struct file *file, const char __user *buf, pe->total_req = 0; pe->err_req = 0; qce_clear_driver_stats(pe->qce); + pe->max_req_used = 0; } + cp->max_qlen = 0; + cp->resp_start = 0; + cp->resp_stop = 0; + cp->no_avail = 0; + cp->max_resp_qlen = 0; + cp->queue_work_eng3 = 0; + cp->queue_work_not_eng3 = 0; + cp->queue_work_not_eng3_nz = 0; + cp->max_reorder_cnt = 0; + for (i = 0; i < MAX_SMP_CPU + 1; i++) + cp->cpu_req[i] = 0; spin_unlock_irqrestore(&cp->lock, flags); return count; } @@ -5683,6 +5818,8 @@ static int __init _qcrypto_init(void) pcp->total_units = 0; pcp->platform_support.bus_scale_table = NULL; pcp->next_engine = NULL; + pcp->scheduled_eng = NULL; + pcp->ce_req_proc_sts = IN_PROGRESS; crypto_init_queue(&pcp->req_queue, MSM_QCRYPTO_REQ_QUEUE_LENGTH); return platform_driver_register(&_qualcomm_crypto); } From a784375ab90942e5ecac054194176cf4aef443ff Mon Sep 17 00:00:00 2001 From: William Clark Date: Thu, 17 Mar 2016 16:32:18 -0700 Subject: [PATCH 026/203] crypto: fix pointer dereference Fix a few possible NULL pointer dereferences. Change-Id: Idc992d61952fc125e2898e1fc84f9ffecf9be737 Signed-off-by: William Clark --- drivers/crypto/msm/ota_crypto.c | 6 +++++- drivers/crypto/msm/qce50.c | 23 ++++++++++++++++++++--- drivers/crypto/msm/qcrypto.c | 22 ++++++++++++++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c index 9b4a001bec95..8aa0d04f14fd 100644 --- a/drivers/crypto/msm/ota_crypto.c +++ b/drivers/crypto/msm/ota_crypto.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-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 @@ -239,6 +239,10 @@ static void req_done(unsigned long data) if (!list_empty(&podev->ready_commands)) { new_req = container_of(podev->ready_commands.next, struct ota_async_req, rlist); + if (NULL == new_req) { + pr_err("ota_crypto: req_done, new_req = NULL"); + return; + } list_del(&new_req->rlist); pqce->active_command = new_req; spin_unlock_irqrestore(&podev->lock, flags); diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index eb0e8fa1fbb2..c1df97fa3554 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -213,8 +213,13 @@ static int count_sg(struct scatterlist *sg, int nbytes) { int i; - for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg)) + for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg)) { + if (NULL == sg) { + pr_err("qce50.c: count_sg, sg = NULL"); + break; + } nbytes -= sg->length; + } return i; } @@ -224,6 +229,10 @@ static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int i; for (i = 0; i < nents; ++i) { + if (NULL == sg) { + pr_err("qce50.c: qce_dma_map_sg, sg = NULL"); + break; + } dma_map_sg(dev, sg, 1, direction); sg = scatterwalk_sg_next(sg); } @@ -237,6 +246,10 @@ static int qce_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int i; for (i = 0; i < nents; ++i) { + if (NULL == sg) { + pr_err("qce50.c: qce_dma_unmap_sg, sg = NULL"); + break; + } dma_unmap_sg(dev, sg, 1, direction); sg = scatterwalk_sg_next(sg); } @@ -339,7 +352,7 @@ static int _ce_setup_hash(struct qce_device *pce_dev, struct qce_sha_req *sreq, struct qce_cmdlist_info *cmdlistinfo) { - uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)]; + uint32_t auth32[(SHA256_DIGEST_SIZE / sizeof(uint32_t))+1]; uint32_t diglen; int i; uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = { @@ -1174,7 +1187,7 @@ static void _qce_dump_descr_fifos_dbg(struct qce_device *pce_dev, int req_info) static int _ce_setup_hash_direct(struct qce_device *pce_dev, struct qce_sha_req *sreq) { - uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)]; + uint32_t auth32[(SHA256_DIGEST_SIZE / sizeof(uint32_t))+1]; uint32_t diglen; bool use_hw_key = false; bool use_pipe_key = false; @@ -2428,6 +2441,10 @@ static int _qce_sps_add_sg_data(struct qce_device *pce_dev, sps_bam_pipe->iovec_count; while (nbytes > 0) { + if (NULL == sg_src) { + pr_err("qce50.c: _qce_sps_add_sg_data, sg_src = NULL"); + break; + } len = min(nbytes, sg_dma_len(sg_src)); nbytes -= len; addr = sg_dma_address(sg_src); diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index be3d3fcdebf5..8bdf9da4d654 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -742,6 +742,10 @@ static size_t qcrypto_sg_copy_from_buffer(struct scatterlist *sgl, size_t offset, len; for (i = 0, offset = 0; i < nents; ++i) { + if (NULL == sgl) { + pr_err("qcrypto.c: qcrypto_sg_copy_from_buffer, sgl = NULL"); + break; + } len = sg_copy_from_buffer(sgl, 1, buf, buflen); buf += len; buflen -= len; @@ -759,6 +763,10 @@ static size_t qcrypto_sg_copy_to_buffer(struct scatterlist *sgl, size_t offset, len; for (i = 0, offset = 0; i < nents; ++i) { + if (NULL == sgl) { + pr_err("qcrypto.c: qcrypto_sg_copy_from_buffer, sgl = NULL"); + break; + } len = sg_copy_to_buffer(sgl, 1, buf, buflen); buf += len; buflen -= len; @@ -4010,6 +4018,10 @@ static int _sha_update(struct ahash_request *req, uint32_t sha_block_size) break; len += sg_last->length; sg_last = scatterwalk_sg_next(sg_last); + if (NULL == sg_last) { + pr_err("qcrypto.c: _sha_update, sg_last = NULL"); + break; + } } if (rctx->trailing_buf_len) { if (cp->ce_support.aligned_only) { @@ -4031,7 +4043,10 @@ static int _sha_update(struct ahash_request *req, uint32_t sha_block_size) req->src = rctx->sg; sg_mark_end(&rctx->sg[0]); } else { - sg_mark_end(sg_last); + if (sg_last) + sg_mark_end(sg_last); + else + pr_err("qcrypto: _sha_update, sg_last= NULL"); memset(rctx->sg, 0, sizeof(rctx->sg)); sg_set_buf(&rctx->sg[0], staging, rctx->trailing_buf_len); @@ -4040,7 +4055,10 @@ static int _sha_update(struct ahash_request *req, uint32_t sha_block_size) req->src = rctx->sg; } } else - sg_mark_end(sg_last); + if (sg_last) + sg_mark_end(sg_last); + else + pr_err("qcrypto.c: _sha_update, sg_last = NULL"); req->nbytes = nbytes; rctx->trailing_buf_len = trailing_buf_len; From dd6169f7597f3d7f29fda65d9b41fdabf8a03a3c Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Tue, 19 Apr 2016 12:00:23 -0700 Subject: [PATCH 027/203] ARM: dts: msm: allow dsi phy power off for nt35597 on msm8996 target Allow dsi phy power off during idle power collapse for nt35597 command mode panel on msm8996 target. Change-Id: I5e1065be9c21c10f577b1f7fea08e11725c2c675 Signed-off-by: Dhaval Patel --- arch/arm/boot/dts/qcom/msm8996-cdp.dtsi | 2 ++ arch/arm/boot/dts/qcom/msm8996-mtp.dtsi | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi index 5b68028546bd..255d96d07a6c 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi @@ -410,6 +410,7 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; qcom,partial-update-enabled; qcom,panel-roi-alignment = <720 128 720 64 720 64>; + qcom,panel-allow-phy-poweroff; }; &dsi_nt35950_4k_dsc_cmd { @@ -438,6 +439,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,panel-allow-phy-poweroff; }; &dsi_dual_sharp_1080_120hz_cmd { diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi index 76f3d738c18c..2028d8944ff6 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi @@ -398,6 +398,7 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; qcom,partial-update-enabled; qcom,panel-roi-alignment = <720 128 720 64 720 64>; + qcom,panel-allow-phy-poweroff; }; &dsi_nt35950_4k_dsc_cmd { @@ -426,6 +427,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,panel-allow-phy-poweroff; }; &dsi_dual_sharp_1080_120hz_cmd { From 82c45133703ea8b0e4c06bd3e33057669d5cba4b Mon Sep 17 00:00:00 2001 From: Archana Sathyakumar Date: Fri, 18 Sep 2015 12:03:56 -0600 Subject: [PATCH 028/203] ARM: dts: msm: Update power attributes for 8996 The attributes are updated to generate non-negative residency values. The numbers do not affect the residency values. Mode | Time Overhead | Energy OverHead | SS Power WFI(C1) | 60 | 15000 | 200.0000 FPC(C4) | 180 | 39740 | 198.0000 Best Mode below 60 us is Active Best Mode below 550 us in WFI Best Mode above 550 us is FPC Mode | Total Time Overhead | Energy OverHead | SS Power L2 CG(D1) | 85 | 65000 | 195.0000 L2 GDHS(D3) | 180 | 89070 | 180.0000 L2 FPC(D4) | 1000 | 441000 | 160.0000 Best Mode below 85us is Active Best Mode below 550us is WFI Best Mode below 11500us is GDHS Best Mode above 11500us is FPC Mode | Total Time Overhead | Energy OverHead | SS Power E1-M1 | 120 | 60000 | 192.0000 E3-M2 | 150 | 69000 | 160.0000 E4-M3 | 1200 | 1380000 | 72.0000 Best mode below 120 us is Active Best mode above 11500us is FPC Change-Id: I4ba5d1361d7a9ff72531c4921e2941c56e935484 Signed-off-by: Archana Sathyakumar --- arch/arm/boot/dts/qcom/msm8996-pm.dtsi | 66 +++++++++++++------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi index bce26c4bbb28..2b7725c1d4f8 100644 --- a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi @@ -48,8 +48,8 @@ label = "system-wfi"; qcom,psci-mode = <0>; qcom,latency-us = <100>; - qcom,ss-power = <725>; - qcom,energy-overhead = <85000>; + qcom,ss-power = <192>; + qcom,energy-overhead = <60000>; qcom,time-overhead = <120>; }; qcom,pm-cluster-level@1{ /* E3-M2 */ @@ -59,9 +59,9 @@ qcom,spm-l3-mode = "fpc"; qcom,psci-mode = <0x23>; qcom,latency-us = <350>; - qcom,ss-power = <530>; - qcom,energy-overhead = <160000>; - qcom,time-overhead = <550>; + qcom,ss-power = <160>; + qcom,energy-overhead = <69000>; + qcom,time-overhead = <150>; qcom,min-child-idx = <1>; }; qcom,pm-cluster-level@2{ /* E4-M3 */ @@ -71,9 +71,9 @@ qcom,spm-l3-mode = "fpc"; qcom,psci-mode = <0x34>; qcom,latency-us = <11000>; - qcom,ss-power = <120>; - qcom,energy-overhead = <280000>; - qcom,time-overhead = <3200>; + qcom,ss-power = <72>; + qcom,energy-overhead = <1380000>; + qcom,time-overhead = <1200>; qcom,min-child-idx = <2>; qcom,notify-rpm; qcom,is-reset; @@ -95,7 +95,7 @@ label = "pwr-l2-wfi"; qcom,psci-mode = <1>; qcom,latency-us = <40>; - qcom,ss-power = <740>; + qcom,ss-power = <195>; qcom,energy-overhead = <65000>; qcom,time-overhead = <85>; }; @@ -105,8 +105,8 @@ label = "pwr-l2-gdhs"; qcom,psci-mode = <3>; qcom,latency-us = <90>; - qcom,ss-power = <660>; - qcom,energy-overhead = <135000>; + qcom,ss-power = <180>; + qcom,energy-overhead = <89070>; qcom,time-overhead = <180>; qcom,min-child-idx = <1>; }; @@ -116,9 +116,9 @@ label = "pwr-l2-fpc"; qcom,psci-mode = <4>; qcom,latency-us = <700>; - qcom,ss-power = <450>; - qcom,energy-overhead = <210000>; - qcom,time-overhead = <11500>; + qcom,ss-power = <160>; + qcom,energy-overhead = <441000>; + qcom,time-overhead = <1000>; qcom,min-child-idx = <1>; qcom,is-reset; }; @@ -134,8 +134,8 @@ qcom,psci-cpu-mode = <1>; qcom,spm-cpu-mode = "wfi"; qcom,latency-us = <20>; - qcom,ss-power = <750>; - qcom,energy-overhead = <32000>; + qcom,ss-power = <200>; + qcom,energy-overhead = <15000>; qcom,time-overhead = <60>; }; @@ -144,9 +144,9 @@ qcom,spm-cpu-mode = "fpc"; qcom,psci-cpu-mode = <4>; qcom,latency-us = <80>; - qcom,ss-power = <700>; - qcom,energy-overhead = <126480>; - qcom,time-overhead = <160>; + qcom,ss-power = <198>; + qcom,energy-overhead = <39740>; + qcom,time-overhead = <180>; }; }; }; @@ -167,9 +167,9 @@ label = "perf-l2-wfi"; qcom,psci-mode = <1>; qcom,latency-us = <40>; - qcom,ss-power = <740>; - qcom,energy-overhead = <70000>; - qcom,time-overhead = <80>; + qcom,ss-power = <195>; + qcom,energy-overhead = <65000>; + qcom,time-overhead = <85>; }; qcom,pm-cluster-level@1{ /* D3 */ @@ -177,8 +177,8 @@ label = "perf-l2-gdhs"; qcom,psci-mode = <3>; qcom,latency-us = <80>; - qcom,ss-power = <660>; - qcom,energy-overhead = <142000>; + qcom,ss-power = <180>; + qcom,energy-overhead = <83500>; qcom,time-overhead = <180>; qcom,min-child-idx = <1>; }; @@ -188,9 +188,9 @@ label = "perf-l2-fpc"; qcom,psci-mode = <4>; qcom,latency-us = <800>; - qcom,ss-power = <450>; - qcom,energy-overhead = <240000>; - qcom,time-overhead = <11500>; + qcom,ss-power = <160>; + qcom,energy-overhead = <441000>; + qcom,time-overhead = <1000>; qcom,min-child-idx = <1>; qcom,is-reset; }; @@ -206,9 +206,9 @@ qcom,psci-cpu-mode = <1>; qcom,spm-cpu-mode = "wfi"; qcom,latency-us = <25>; - qcom,ss-power = <750>; - qcom,energy-overhead = <37000>; - qcom,time-overhead = <50>; + qcom,ss-power = <200>; + qcom,energy-overhead = <15000>; + qcom,time-overhead = <60>; }; qcom,pm-cpu-level@1 { /* C4 */ @@ -216,9 +216,9 @@ qcom,spm-cpu-mode = "fpc"; qcom,psci-cpu-mode = <4>; qcom,latency-us = <80>; - qcom,ss-power = <700>; - qcom,energy-overhead = <136480>; - qcom,time-overhead = <160>; + qcom,ss-power = <198>; + qcom,energy-overhead = <39740>; + qcom,time-overhead = <180>; }; }; }; From ec0527d5ab908dc90879963a8c6b3695adf26dd3 Mon Sep 17 00:00:00 2001 From: Archana Sathyakumar Date: Fri, 4 Dec 2015 15:55:20 -0700 Subject: [PATCH 029/203] ARM: dts: msm: Add support for FPC without psci for 8996 Add support for FPC without psci for cpus in DT. This mode helps reduce the latency associated with entering Fast Power collapse by not incurring the latency of terminating in the PSCI driver in Secure EL1. Change-Id: I1209b62d45d10b74bd36756c4ddefa137fb571a5 Signed-off-by: Archana Sathyakumar --- arch/arm/boot/dts/qcom/msm8996-pm.dtsi | 48 +++++++++++++++++++------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi index 2b7725c1d4f8..eaa90265619a 100644 --- a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi @@ -108,7 +108,7 @@ qcom,ss-power = <180>; qcom,energy-overhead = <89070>; qcom,time-overhead = <180>; - qcom,min-child-idx = <1>; + qcom,min-child-idx = <2>; }; qcom,pm-cluster-level@2{ /* D4 */ @@ -119,7 +119,7 @@ qcom,ss-power = <160>; qcom,energy-overhead = <441000>; qcom,time-overhead = <1000>; - qcom,min-child-idx = <1>; + qcom,min-child-idx = <2>; qcom,is-reset; }; @@ -135,18 +135,29 @@ qcom,spm-cpu-mode = "wfi"; qcom,latency-us = <20>; qcom,ss-power = <200>; - qcom,energy-overhead = <15000>; + qcom,energy-overhead = <9000>; qcom,time-overhead = <60>; }; qcom,pm-cpu-level@1 { /* C4 */ reg = <1>; + qcom,spm-cpu-mode = "fpc-def"; + qcom,psci-cpu-mode = <4>; + qcom,latency-us = <40>; + qcom,ss-power = <198>; + qcom,energy-overhead = <21850>; + qcom,time-overhead = <120>; + qcom,hyp-psci; + }; + + qcom,pm-cpu-level@2 { /* C4 */ + reg = <2>; qcom,spm-cpu-mode = "fpc"; qcom,psci-cpu-mode = <4>; qcom,latency-us = <80>; - qcom,ss-power = <198>; - qcom,energy-overhead = <39740>; - qcom,time-overhead = <180>; + qcom,ss-power = <196>; + qcom,energy-overhead = <45300>; + qcom,time-overhead = <210>; }; }; }; @@ -180,7 +191,7 @@ qcom,ss-power = <180>; qcom,energy-overhead = <83500>; qcom,time-overhead = <180>; - qcom,min-child-idx = <1>; + qcom,min-child-idx = <2>; }; qcom,pm-cluster-level@2{ /* D4 */ @@ -191,7 +202,7 @@ qcom,ss-power = <160>; qcom,energy-overhead = <441000>; qcom,time-overhead = <1000>; - qcom,min-child-idx = <1>; + qcom,min-child-idx = <2>; qcom,is-reset; }; @@ -207,18 +218,29 @@ qcom,spm-cpu-mode = "wfi"; qcom,latency-us = <25>; qcom,ss-power = <200>; - qcom,energy-overhead = <15000>; + qcom,energy-overhead = <9000>; qcom,time-overhead = <60>; }; - qcom,pm-cpu-level@1 { /* C4 */ + qcom,pm-cpu-level@1 { /* C4 */ reg = <1>; + qcom,spm-cpu-mode = "fpc-def"; + qcom,psci-cpu-mode = <4>; + qcom,latency-us = <40>; + qcom,ss-power = <198>; + qcom,energy-overhead = <21850>; + qcom,time-overhead = <120>; + qcom,hyp-psci; + }; + + qcom,pm-cpu-level@2 { /* C4 */ + reg = <2>; qcom,spm-cpu-mode = "fpc"; qcom,psci-cpu-mode = <4>; qcom,latency-us = <80>; - qcom,ss-power = <198>; - qcom,energy-overhead = <39740>; - qcom,time-overhead = <180>; + qcom,ss-power = <196>; + qcom,energy-overhead = <45300>; + qcom,time-overhead = <210>; }; }; }; From a709bcaf6e59324756f1491e490ab0d1b4fb8ca5 Mon Sep 17 00:00:00 2001 From: myfluxi Date: Wed, 8 Jan 2014 01:25:14 +0100 Subject: [PATCH 030/203] PM: devfreq: Use high priority workqueue It does not make sense to run kgsl on high and devfreq on regular priority. Change-Id: Ie5e6c9353a4e1324a6a49278e5ad3638462f551c Signed-off-by: flar2 --- drivers/devfreq/devfreq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 1659ef543eb3..bb19fe8a23b8 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -1092,7 +1092,9 @@ static int __init devfreq_init(void) return PTR_ERR(devfreq_class); } - devfreq_wq = create_freezable_workqueue("devfreq_wq"); + devfreq_wq = alloc_workqueue("devfreq_wq", + WQ_HIGHPRI | WQ_UNBOUND | WQ_FREEZABLE | + WQ_MEM_RECLAIM, 0); if (!devfreq_wq) { class_destroy(devfreq_class); pr_err("%s: couldn't create workqueue\n", __FILE__); From 13292ccd7395c25f62baa39d4f556e31801bb223 Mon Sep 17 00:00:00 2001 From: Manikanta Sivapala Date: Tue, 3 Nov 2015 12:26:17 +0530 Subject: [PATCH 031/203] msm: vidc: disable CPU L2 cache PC during video sessions CPU L2 cache is being power collapsed and resumed during video sessions which is consuming more power unnecessarily. So disable CPU L2 cache power collapse during video sessions using qos requests to save power. Change-Id: Iaf47231bed1304510ea221b9d50866d3b4adfed0 Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index 0f7ddf5ccd54..e63da7979b0f 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #define BASE_DEVICE_NUMBER 32 +static struct pm_qos_request msm_v4l2_vidc_pm_qos_request; struct msm_vidc_drv *vidc_driver; uint32_t msm_vidc_pwr_collapse_delay = 2000; @@ -59,6 +61,11 @@ static int msm_v4l2_open(struct file *filp) core->id, vid_dev->type); return -ENOMEM; } + + dprintk(VIDC_DBG, "pm_qos_add with latency 1000usec\n"); + pm_qos_add_request(&msm_v4l2_vidc_pm_qos_request, + PM_QOS_CPU_DMA_LATENCY, 1000); + clear_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags); filp->private_data = &(vidc_inst->event_handler); trace_msm_v4l2_vidc_open_end("msm_v4l2_open end"); @@ -79,6 +86,12 @@ static int msm_v4l2_close(struct file *filp) "Failed in %s for release output buffers\n", __func__); rc = msm_vidc_close(vidc_inst); + + dprintk(VIDC_DBG, "pm_qos_update and remove\n"); + pm_qos_update_request(&msm_v4l2_vidc_pm_qos_request, + PM_QOS_DEFAULT_VALUE); + pm_qos_remove_request(&msm_v4l2_vidc_pm_qos_request); + trace_msm_v4l2_vidc_close_end("msm_v4l2_close end"); return rc; } From c68baf509d2e6e1e36f9b5704e3f1e76132f321e Mon Sep 17 00:00:00 2001 From: flar2 Date: Mon, 23 May 2016 19:30:28 -0400 Subject: [PATCH 032/203] Allow selectable tick rate --- arch/arm64/Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b1c5bd72b390..e090f71de48f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -625,9 +625,7 @@ config ARCH_NR_GPIO source kernel/Kconfig.preempt -config HZ - int - default 100 +source kernel/Kconfig.hz config ARCH_HAS_HOLES_MEMORYMODEL def_bool y if SPARSEMEM From e749003e73b08fee646b79c4d529fa6d85a1c394 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 24 Jun 2016 02:38:58 -0400 Subject: [PATCH 033/203] wlan: quick hack for module to load --- kernel/module.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/module.c b/kernel/module.c index 835bfbc9fe35..e1a7d2aad5c7 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2685,7 +2685,8 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags) } else if (!same_magic(modmagic, vermagic, info->index.vers)) { pr_err("%s: version magic '%s' should be '%s'\n", mod->name, modmagic, vermagic); - return -ENOEXEC; + if (strncmp("wlan", mod->name, 4)) + return -ENOEXEC; } if (!get_modinfo(info, "intree")) From cf8382adfdb0e38a2e8b9a0c97e9a19f1ad55a87 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 24 Jun 2016 04:13:51 -0400 Subject: [PATCH 034/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 47 +++++++++++++++---------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 9e1103eeeafd..f1c2024bbf31 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-perf" +CONFIG_LOCALVERSION="-ElementalX-0.01" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -274,13 +274,20 @@ CONFIG_BLOCK_COMPAT=y # IO Schedulers # CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_TEST=m +# CONFIG_IOSCHED_TEST is not set CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_FIOPS=y +CONFIG_IOSCHED_SIO=y +CONFIG_IOSCHED_BFQ=y +CONFIG_CGROUP_BFQIO=y # CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_BFQ is not set # CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_DEFAULT_SIO is not set +CONFIG_DEFAULT_FIOPS=y +CONFIG_DEFAULT_IOSCHED="fiops" CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y CONFIG_MUTEX_SPIN_ON_OWNER=y @@ -358,7 +365,12 @@ CONFIG_ARCH_NR_GPIO=1024 # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_PREEMPT_COUNT=y -CONFIG_HZ=100 +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +CONFIG_HZ_300=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=300 +CONFIG_SCHED_HRTICK=y CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y @@ -593,7 +605,7 @@ CONFIG_NETWORK_SECMARK=y CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_NETFILTER_ADVANCED=y -CONFIG_BRIDGE_NETFILTER=m +CONFIG_BRIDGE_NETFILTER=y # # Core Netfilter Configuration @@ -1234,7 +1246,6 @@ CONFIG_SCSI_UFSHCD=y CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y CONFIG_SCSI_UFS_QCOM_ICE=y -CONFIG_SCSI_UFS_TEST=m # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set @@ -1566,7 +1577,7 @@ CONFIG_ATH_CARDS=y # CONFIG_ATH_DEBUG is not set # CONFIG_ATH5K_PCI is not set # CONFIG_ATH6KL is not set -CONFIG_WIL6210=m +CONFIG_WIL6210=y CONFIG_WIL6210_ISR_COR=y CONFIG_WIL6210_PLATFORM_MSM=y # CONFIG_BRCMFMAC is not set @@ -1610,7 +1621,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_EVBUG=m +# CONFIG_INPUT_EVBUG is not set CONFIG_INPUT_KEYRESET=y CONFIG_INPUT_KEYCOMBO=y @@ -1856,7 +1867,7 @@ CONFIG_DEVPORT=y CONFIG_MSM_SMD_PKT=y # CONFIG_XILLYBUS is not set CONFIG_MSM_ADSPRPC=y -CONFIG_MSM_RDBG=m +CONFIG_MSM_RDBG=y # # I2C support @@ -1962,7 +1973,7 @@ CONFIG_SPI_QUP=y # # SPI Protocol Masters # -CONFIG_SPI_SPIDEV=m +CONFIG_SPI_SPIDEV=y # CONFIG_SPI_TLE62X0 is not set # CONFIG_SPMI is not set # CONFIG_HSI is not set @@ -2103,7 +2114,6 @@ CONFIG_SMB1351_USB_CHARGER=y CONFIG_QPNP_SMBCHARGER=y CONFIG_QPNP_FG=y CONFIG_FG_BQ27541=y -CONFIG_ONEPLUS_FASTCHG=y CONFIG_BATTERY_BCL=y # CONFIG_QPNP_VM_BMS is not set # CONFIG_QPNP_BMS is not set @@ -2701,7 +2711,7 @@ CONFIG_FB_MSM_MDSS_HDMI_PANEL=y # CONFIG_FB_MSM_MDSS_XLOG_DEBUG is not set # CONFIG_FB_SSD1307 is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_CLASS_DEVICE=y # CONFIG_LCD_L4F00242T03 is not set # CONFIG_LCD_LMS283GF05 is not set # CONFIG_LCD_LTV350QV is not set @@ -2715,8 +2725,8 @@ CONFIG_LCD_CLASS_DEVICE=m # CONFIG_LCD_AMS369FG06 is not set # CONFIG_LCD_LMS501KF03 is not set # CONFIG_LCD_HX8357 is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=m -CONFIG_BACKLIGHT_GENERIC=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y # CONFIG_BACKLIGHT_PWM is not set # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set @@ -3291,8 +3301,7 @@ CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set # CONFIG_SDIO_UART is not set -CONFIG_MMC_TEST=m -CONFIG_MMC_BLOCK_TEST=m +# CONFIG_MMC_TEST is not set # # MMC/SD/SDIO Host Controller Drivers @@ -3570,7 +3579,7 @@ CONFIG_ION_MSM=y # CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m +# CONFIG_MSM_BUSPM_DEV is not set CONFIG_BUS_TOPOLOGY_ADHOC=y # CONFIG_DEBUG_BUS_VOTER is not set CONFIG_QPNP_POWER_ON=y @@ -4285,7 +4294,7 @@ CONFIG_CRYPTO_DEFLATE=y # # Random Number Generation # -CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_ANSI_CPRNG=y # CONFIG_CRYPTO_DRBG_MENU is not set # CONFIG_CRYPTO_USER_API_HASH is not set # CONFIG_CRYPTO_USER_API_SKCIPHER is not set From 00c1bf0b4e222f8378ef2a77bfcd3625cfff2342 Mon Sep 17 00:00:00 2001 From: flar2 Date: Mon, 23 May 2016 12:54:33 -0400 Subject: [PATCH 035/203] msm8996: Overclocking with cmdline option Signed-off-by: flar2 --- drivers/cpufreq/qcom-cpufreq.c | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c index 02970bde6508..bd5b5fa59a69 100755 --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c @@ -31,6 +31,42 @@ static DEFINE_MUTEX(l2bw_lock); + +static unsigned long arg_cpu_max_c1 = 1593600; + +static int __init cpufreq_read_cpu_max_c1(char *cpu_max_c1) +{ + unsigned long ui_khz; + int ret; + + ret = kstrtoul(cpu_max_c1, 0, &ui_khz); + if (ret) + return -EINVAL; + + arg_cpu_max_c1 = ui_khz; + printk("cpu_max_c1=%lu\n", arg_cpu_max_c1); + return ret; +} +__setup("cpu_max_c1=", cpufreq_read_cpu_max_c1); + +static unsigned long arg_cpu_max_c2 = 2150400; + +static int __init cpufreq_read_cpu_max_c2(char *cpu_max_c2) +{ + unsigned long ui_khz; + int ret; + + ret = kstrtoul(cpu_max_c2, 0, &ui_khz); + if (ret) + return -EINVAL; + + arg_cpu_max_c2 = ui_khz; + printk("cpu_max_c2=%lu\n", arg_cpu_max_c2); + return ret; +} +__setup("cpu_max_c2=", cpufreq_read_cpu_max_c2); + + static struct clk *cpu_clk[NR_CPUS]; static struct clk *l2_clk; static DEFINE_PER_CPU(struct cpufreq_frequency_table *, freq_table); @@ -368,6 +404,13 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, if (i > 0 && f <= ftbl[i-1].frequency) break; + //Custom max freq + if ((cpu < 2 && f > arg_cpu_max_c1) || + (cpu >= 2 && f > arg_cpu_max_c2)) { + nf = i; + break; + } + ftbl[i].driver_data = i; ftbl[i].frequency = f; } From e441a0e96a75de0739e8ffa6e8a4ccfc20bbcd77 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 24 Jun 2016 04:15:23 -0400 Subject: [PATCH 036/203] msm8996: Overclocking frequencies --- arch/arm64/boot/dts/15801_DVT/msm8996-v3.dtsi | 23 ++++++++++++------- .../arm64/boot/dts/15801_EVT2/msm8996-v3.dtsi | 23 ++++++++++++------- .../arm64/boot/dts/15801_EVT3/msm8996-v3.dtsi | 23 ++++++++++++------- arch/arm64/boot/dts/15801_PVT/msm8996-v3.dtsi | 23 ++++++++++++------- 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/arch/arm64/boot/dts/15801_DVT/msm8996-v3.dtsi b/arch/arm64/boot/dts/15801_DVT/msm8996-v3.dtsi index ca2e923e9ecf..e1732e31a678 100755 --- a/arch/arm64/boot/dts/15801_DVT/msm8996-v3.dtsi +++ b/arch/arm64/boot/dts/15801_DVT/msm8996-v3.dtsi @@ -395,7 +395,8 @@ < 1324800000 13 >, < 1401600000 14 >, < 1478400000 15 >, - < 1593600000 16 >; + < 1593600000 16 >, + < 1728000000 16 >; qcom,pwrcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -437,7 +438,8 @@ < 1920000000 22 >, < 1996800000 23 >, < 2073600000 24 >, - < 2150400000 25 >; + < 2150400000 25 >, + < 2265600000 25 >; qcom,perfcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -518,7 +520,8 @@ < 1324800 >, < 1401600 >, < 1478400 >, - < 1593600 >; + < 1593600 >, + < 1728000 >; qcom,cpufreq-table-2 = < 307200 >, < 403200 >, @@ -544,7 +547,8 @@ < 1920000 >, < 1996800 >, < 2073600 >, - < 2150400 >; + < 2150400 >, + < 2265600 >; }; &m4m_cache { @@ -588,7 +592,8 @@ < 1324800 1056000 >, < 1401600 1132800 >, < 1478400 1190400 >, - < 1593600 1382400 >; + < 1593600 1382400 >, + < 1728000 1382400 >; cpu-to-dev-map-2 = < 480000 307200 >, < 556800 307200 >, @@ -612,15 +617,17 @@ < 1920000 1459200 >, < 1996800 1593600 >, < 2073600 1593600 >, - < 2150400 1593600 >; + < 2150400 1593600 >, + < 2265600 1593600 >; }; mincpubw-cpufreq { cpu-to-dev-map-0 = - < 1593600 1525 >; + < 1728000 1525 >; cpu-to-dev-map-2 = < 2073600 1525 >, - < 2150400 5195 >; + < 2150400 5195 >, + < 2265600 5195 >; }; }; diff --git a/arch/arm64/boot/dts/15801_EVT2/msm8996-v3.dtsi b/arch/arm64/boot/dts/15801_EVT2/msm8996-v3.dtsi index ca2e923e9ecf..e1732e31a678 100755 --- a/arch/arm64/boot/dts/15801_EVT2/msm8996-v3.dtsi +++ b/arch/arm64/boot/dts/15801_EVT2/msm8996-v3.dtsi @@ -395,7 +395,8 @@ < 1324800000 13 >, < 1401600000 14 >, < 1478400000 15 >, - < 1593600000 16 >; + < 1593600000 16 >, + < 1728000000 16 >; qcom,pwrcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -437,7 +438,8 @@ < 1920000000 22 >, < 1996800000 23 >, < 2073600000 24 >, - < 2150400000 25 >; + < 2150400000 25 >, + < 2265600000 25 >; qcom,perfcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -518,7 +520,8 @@ < 1324800 >, < 1401600 >, < 1478400 >, - < 1593600 >; + < 1593600 >, + < 1728000 >; qcom,cpufreq-table-2 = < 307200 >, < 403200 >, @@ -544,7 +547,8 @@ < 1920000 >, < 1996800 >, < 2073600 >, - < 2150400 >; + < 2150400 >, + < 2265600 >; }; &m4m_cache { @@ -588,7 +592,8 @@ < 1324800 1056000 >, < 1401600 1132800 >, < 1478400 1190400 >, - < 1593600 1382400 >; + < 1593600 1382400 >, + < 1728000 1382400 >; cpu-to-dev-map-2 = < 480000 307200 >, < 556800 307200 >, @@ -612,15 +617,17 @@ < 1920000 1459200 >, < 1996800 1593600 >, < 2073600 1593600 >, - < 2150400 1593600 >; + < 2150400 1593600 >, + < 2265600 1593600 >; }; mincpubw-cpufreq { cpu-to-dev-map-0 = - < 1593600 1525 >; + < 1728000 1525 >; cpu-to-dev-map-2 = < 2073600 1525 >, - < 2150400 5195 >; + < 2150400 5195 >, + < 2265600 5195 >; }; }; diff --git a/arch/arm64/boot/dts/15801_EVT3/msm8996-v3.dtsi b/arch/arm64/boot/dts/15801_EVT3/msm8996-v3.dtsi index ca2e923e9ecf..e1732e31a678 100755 --- a/arch/arm64/boot/dts/15801_EVT3/msm8996-v3.dtsi +++ b/arch/arm64/boot/dts/15801_EVT3/msm8996-v3.dtsi @@ -395,7 +395,8 @@ < 1324800000 13 >, < 1401600000 14 >, < 1478400000 15 >, - < 1593600000 16 >; + < 1593600000 16 >, + < 1728000000 16 >; qcom,pwrcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -437,7 +438,8 @@ < 1920000000 22 >, < 1996800000 23 >, < 2073600000 24 >, - < 2150400000 25 >; + < 2150400000 25 >, + < 2265600000 25 >; qcom,perfcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -518,7 +520,8 @@ < 1324800 >, < 1401600 >, < 1478400 >, - < 1593600 >; + < 1593600 >, + < 1728000 >; qcom,cpufreq-table-2 = < 307200 >, < 403200 >, @@ -544,7 +547,8 @@ < 1920000 >, < 1996800 >, < 2073600 >, - < 2150400 >; + < 2150400 >, + < 2265600 >; }; &m4m_cache { @@ -588,7 +592,8 @@ < 1324800 1056000 >, < 1401600 1132800 >, < 1478400 1190400 >, - < 1593600 1382400 >; + < 1593600 1382400 >, + < 1728000 1382400 >; cpu-to-dev-map-2 = < 480000 307200 >, < 556800 307200 >, @@ -612,15 +617,17 @@ < 1920000 1459200 >, < 1996800 1593600 >, < 2073600 1593600 >, - < 2150400 1593600 >; + < 2150400 1593600 >, + < 2265600 1593600 >; }; mincpubw-cpufreq { cpu-to-dev-map-0 = - < 1593600 1525 >; + < 1728000 1525 >; cpu-to-dev-map-2 = < 2073600 1525 >, - < 2150400 5195 >; + < 2150400 5195 >, + < 2265600 5195 >; }; }; diff --git a/arch/arm64/boot/dts/15801_PVT/msm8996-v3.dtsi b/arch/arm64/boot/dts/15801_PVT/msm8996-v3.dtsi index ca2e923e9ecf..e1732e31a678 100644 --- a/arch/arm64/boot/dts/15801_PVT/msm8996-v3.dtsi +++ b/arch/arm64/boot/dts/15801_PVT/msm8996-v3.dtsi @@ -395,7 +395,8 @@ < 1324800000 13 >, < 1401600000 14 >, < 1478400000 15 >, - < 1593600000 16 >; + < 1593600000 16 >, + < 1728000000 16 >; qcom,pwrcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -437,7 +438,8 @@ < 1920000000 22 >, < 1996800000 23 >, < 2073600000 24 >, - < 2150400000 25 >; + < 2150400000 25 >, + < 2265600000 25 >; qcom,perfcl-speedbin1-v0 = < 0 0 >, < 307200000 1 >, @@ -518,7 +520,8 @@ < 1324800 >, < 1401600 >, < 1478400 >, - < 1593600 >; + < 1593600 >, + < 1728000 >; qcom,cpufreq-table-2 = < 307200 >, < 403200 >, @@ -544,7 +547,8 @@ < 1920000 >, < 1996800 >, < 2073600 >, - < 2150400 >; + < 2150400 >, + < 2265600 >; }; &m4m_cache { @@ -588,7 +592,8 @@ < 1324800 1056000 >, < 1401600 1132800 >, < 1478400 1190400 >, - < 1593600 1382400 >; + < 1593600 1382400 >, + < 1728000 1382400 >; cpu-to-dev-map-2 = < 480000 307200 >, < 556800 307200 >, @@ -612,15 +617,17 @@ < 1920000 1459200 >, < 1996800 1593600 >, < 2073600 1593600 >, - < 2150400 1593600 >; + < 2150400 1593600 >, + < 2265600 1593600 >; }; mincpubw-cpufreq { cpu-to-dev-map-0 = - < 1593600 1525 >; + < 1728000 1525 >; cpu-to-dev-map-2 = < 2073600 1525 >, - < 2150400 5195 >; + < 2150400 5195 >, + < 2265600 5195 >; }; }; From c369cdc531f500637e5b8ec21773a6670555c439 Mon Sep 17 00:00:00 2001 From: flar2 Date: Wed, 4 Nov 2015 20:45:15 -0500 Subject: [PATCH 037/203] platform/msm: haptic: add sysfs node for vmax_mv Call the sysfs node vmax_mv_strong for compatibility --- drivers/platform/msm/qpnp-haptic.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index caaef7d207c0..308cb7ef7725 100755 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -1294,6 +1294,44 @@ static ssize_t qpnp_hap_ramp_test_data_show(struct device *dev, } +/* sysfs show for vmax_mv_strong update */ +static ssize_t qpnp_hap_vmax_mv_strong_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", hap->vmax_mv); +} + +/* sysfs store for vmax_mv_strong */ +static ssize_t qpnp_hap_vmax_mv_strong_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct timed_output_dev *timed_dev = dev_get_drvdata(dev); + struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, + timed_dev); + u32 val; + ssize_t ret; + + ret = kstrtou32(buf, 10, &val); + if (ret) + return ret; + + if ((val < QPNP_HAP_VMAX_MIN_MV) || (val > QPNP_HAP_VMAX_MAX_MV)) + return -EINVAL; + + mutex_lock(&hap->wf_lock); + hap->vmax_mv = val; + ret = qpnp_hap_vmax_config(hap); + if (ret) + pr_err("%s: error setting vmax_mv\n", __func__); + mutex_unlock(&hap->wf_lock); + + return count; +} + /* sysfs attributes */ static struct device_attribute qpnp_hap_attrs[] = { __ATTR(wf_s0, (S_IRUGO | S_IWUSR | S_IWGRP), @@ -1341,6 +1379,9 @@ static struct device_attribute qpnp_hap_attrs[] = { __ATTR(min_max_test, (S_IRUGO | S_IWUSR | S_IWGRP), qpnp_hap_min_max_test_data_show, qpnp_hap_min_max_test_data_store), + __ATTR(vmax_mv_strong, (S_IRUGO | S_IWUSR | S_IWGRP), + qpnp_hap_vmax_mv_strong_show, + qpnp_hap_vmax_mv_strong_store), }; static void calculate_lra_code(struct qpnp_hap *hap) From c5b677ec482b3bc77ac44a6117fcdad924d2cd48 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 3 Jan 2016 12:27:47 -0500 Subject: [PATCH 038/203] msm: qpnp-haptic: disable vibration when vmax_mv_strong is set to min --- drivers/platform/msm/qpnp-haptic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index 308cb7ef7725..eb1aad575eb1 100755 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -1610,6 +1610,12 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) } hap->state = 0; } else { + + if (hap->vmax_mv == QPNP_HAP_VMAX_MIN_MV) { + mutex_unlock(&hap->lock); + return; + } + value = (value > hap->timeout_ms ? hap->timeout_ms : value); hap->state = 1; From dfd120c6debf7fc7d483c4b661078bcc258b27f1 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 8 Nov 2015 17:39:41 -0500 Subject: [PATCH 039/203] touch: sweep2sleep --- drivers/input/touchscreen/Kconfig | 5 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/sweep2sleep.c | 358 ++++++++++++++++++++++++ 3 files changed, 364 insertions(+) create mode 100644 drivers/input/touchscreen/sweep2sleep.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index d62a770a82c9..f97a7cc1cf19 100755 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1132,4 +1132,9 @@ config TOUCHSCREEN_SYNAPTICS_S3320_I2C_RMI depends on I2C help This enables support for Synaptics s1302 RMI over I2C based touch key. +config SWEEP2SLEEP + tristate "Sweep to put device to sleep" + default y + help + Say Y here to support sweep2sleep endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7b67b354ce24..0499df647628 100755 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -99,3 +99,4 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_S3320_I2C_RMI) += synaptics_driver_s3320.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_S3320_I2C_RMI) += synaptics_s3320_redremote.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_S1302_I2C_RMI) += synaptics_driver_s1302.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_S1302_I2C_RMI) += synaptics_s1302_redremote.o +obj-$(CONFIG_SWEEP2SLEEP) += sweep2sleep.o diff --git a/drivers/input/touchscreen/sweep2sleep.c b/drivers/input/touchscreen/sweep2sleep.c new file mode 100644 index 000000000000..c7105d69d8c7 --- /dev/null +++ b/drivers/input/touchscreen/sweep2sleep.c @@ -0,0 +1,358 @@ +#include +#include +#include +#include +#include +#include + +#define DRIVER_AUTHOR "flar2 (asegaert at gmail.com)" +#define DRIVER_DESCRIPTION "sweep2sleep driver" +#define DRIVER_VERSION "4.0" + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +//sweep2sleep +#define S2S_PWRKEY_DUR 60 +#define S2S_Y_MAX 1920 +#define S2S_Y_LIMIT S2S_Y_MAX-180 +#define SWEEP_RIGHT 0x01 +#define SWEEP_LEFT 0x02 +#define VIB_STRENGTH 20 + +extern void set_vibrate(int value); + +// 1=sweep right, 2=sweep left, 3=both +static int s2s_switch = 2; + +static int touch_x = 0, touch_y = 0, firstx = 0; +static bool touch_x_called = false, touch_y_called = false; +static bool scr_on_touch = false, barrier[2] = {false, false}; +static bool exec_count = true; +static struct input_dev * sweep2sleep_pwrdev; +static DEFINE_MUTEX(pwrkeyworklock); +static struct workqueue_struct *s2s_input_wq; +static struct work_struct s2s_input_work; +static int vib_strength = VIB_STRENGTH; + +/* PowerKey work func */ +static void sweep2sleep_presspwr(struct work_struct * sweep2sleep_presspwr_work) { + + if (!mutex_trylock(&pwrkeyworklock)) + return; + input_event(sweep2sleep_pwrdev, EV_KEY, KEY_POWER, 1); + input_event(sweep2sleep_pwrdev, EV_SYN, 0, 0); + msleep(S2S_PWRKEY_DUR); + input_event(sweep2sleep_pwrdev, EV_KEY, KEY_POWER, 0); + input_event(sweep2sleep_pwrdev, EV_SYN, 0, 0); + msleep(S2S_PWRKEY_DUR); + mutex_unlock(&pwrkeyworklock); + return; +} +static DECLARE_WORK(sweep2sleep_presspwr_work, sweep2sleep_presspwr); + +/* PowerKey trigger */ +static void sweep2sleep_pwrtrigger(void) { + set_vibrate(vib_strength); + schedule_work(&sweep2sleep_presspwr_work); + return; +} + +/* reset on finger release */ +static void sweep2sleep_reset(void) { + exec_count = true; + barrier[0] = false; + barrier[1] = false; + firstx = 0; + scr_on_touch = false; +} + +/* Sweep2sleep main function */ +static void detect_sweep2sleep(int x, int y, bool st) +{ + int prevx = 0, nextx = 0; + bool single_touch = st; + + if (firstx == 0) + firstx = x; + + if (s2s_switch > 3) + s2s_switch = 3; + + //left->right + if (single_touch && firstx < 810 && (s2s_switch & SWEEP_RIGHT)) { + scr_on_touch=true; + prevx = firstx; + nextx = prevx + 180; + if ((barrier[0] == true) || + ((x > prevx) && + (x < nextx) && + (y > S2S_Y_LIMIT))) { + prevx = nextx; + nextx += 200; + barrier[0] = true; + if ((barrier[1] == true) || + ((x > prevx) && + (x < nextx) && + (y > S2S_Y_LIMIT))) { + prevx = nextx; + barrier[1] = true; + if ((x > prevx) && + (y > S2S_Y_LIMIT)) { + if (x > (nextx + 180)) { + if (exec_count) { + sweep2sleep_pwrtrigger(); + exec_count = false; + } + } + } + } + } + //right->left + } else if (firstx >= 180 && (s2s_switch & SWEEP_LEFT)) { + scr_on_touch=true; + prevx = firstx; + nextx = prevx - 180; + if ((barrier[0] == true) || + ((x < prevx) && + (x > nextx) && + (y > S2S_Y_LIMIT))) { + prevx = nextx; + nextx -= 200; + barrier[0] = true; + if ((barrier[1] == true) || + ((x < prevx) && + (x > nextx) && + (y > S2S_Y_LIMIT))) { + prevx = nextx; + barrier[1] = true; + if ((x < prevx) && + (y > S2S_Y_LIMIT)) { + if (x < (nextx - 180)) { + if (exec_count) { + sweep2sleep_pwrtrigger(); + exec_count = false; + } + } + } + } + } + } +} + + +static void s2s_input_callback(struct work_struct *unused) { + + detect_sweep2sleep(touch_x, touch_y, true); + + return; +} + +static void s2s_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) { + + if (code == ABS_MT_SLOT) { + sweep2sleep_reset(); + return; + } + + if (code == ABS_MT_TRACKING_ID && value == -1) { + sweep2sleep_reset(); + return; + } + + if (code == ABS_MT_POSITION_X) { + touch_x = value; + touch_x_called = true; + } + + if (code == ABS_MT_POSITION_Y) { + touch_y = value; + touch_y_called = true; + } + + if (touch_x_called && touch_y_called) { + touch_x_called = false; + touch_y_called = false; + queue_work_on(0, s2s_input_wq, &s2s_input_work); + } +} + +static int input_dev_filter(struct input_dev *dev) { + if (strstr(dev->name, "synaptics,s3320")) { + return 0; + } else { + return 1; + } +} + +static int s2s_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) { + struct input_handle *handle; + int error; + + if (input_dev_filter(dev)) + return -ENODEV; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "s2s"; + + error = input_register_handle(handle); + + error = input_open_device(handle); + + return 0; + +} + +static void s2s_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id s2s_ids[] = { + { .driver_info = 1 }, + { }, +}; + +static struct input_handler s2s_input_handler = { + .event = s2s_input_event, + .connect = s2s_input_connect, + .disconnect = s2s_input_disconnect, + .name = "s2s_inputreq", + .id_table = s2s_ids, +}; + +static ssize_t sweep2sleep_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", s2s_switch); +} + +static ssize_t sweep2sleep_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long input; + + ret = kstrtoul(buf, 0, &input); + if (ret < 0) + return ret; + + if (input < 0 || input > 3) + input = 0; + + s2s_switch = input; + + return count; +} + +static DEVICE_ATTR(sweep2sleep, (S_IWUSR|S_IRUGO), + sweep2sleep_show, sweep2sleep_dump); + +static ssize_t vib_strength_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", vib_strength); +} + +static ssize_t vib_strength_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long input; + + ret = kstrtoul(buf, 0, &input); + if (ret < 0) + return ret; + + if (input < 0 || input > 90) + input = 20; + + vib_strength = input; + + return count; +} + +static DEVICE_ATTR(vib_strength, (S_IWUSR|S_IRUGO), + vib_strength_show, vib_strength_dump); + + +static struct kobject *sweep2sleep_kobj; + +static int __init sweep2sleep_init(void) +{ + int rc = 0; + + sweep2sleep_pwrdev = input_allocate_device(); + if (!sweep2sleep_pwrdev) { + pr_err("Failed to allocate sweep2sleep_pwrdev\n"); + goto err_alloc_dev; + } + + input_set_capability(sweep2sleep_pwrdev, EV_KEY, KEY_POWER); + + sweep2sleep_pwrdev->name = "s2s_pwrkey"; + sweep2sleep_pwrdev->phys = "s2s_pwrkey/input0"; + + rc = input_register_device(sweep2sleep_pwrdev); + if (rc) { + pr_err("%s: input_register_device err=%d\n", __func__, rc); + goto err_input_dev; + } + + s2s_input_wq = create_workqueue("s2s_iwq"); + if (!s2s_input_wq) { + pr_err("%s: Failed to create workqueue\n", __func__); + return -EFAULT; + } + INIT_WORK(&s2s_input_work, s2s_input_callback); + + rc = input_register_handler(&s2s_input_handler); + if (rc) + pr_err("%s: Failed to register s2s_input_handler\n", __func__); + + sweep2sleep_kobj = kobject_create_and_add("sweep2sleep", NULL) ; + if (sweep2sleep_kobj == NULL) { + pr_warn("%s: sweep2sleep_kobj failed\n", __func__); + } + + rc = sysfs_create_file(sweep2sleep_kobj, &dev_attr_sweep2sleep.attr); + if (rc) + pr_err("%s: sysfs_create_file failed for sweep2sleep\n", __func__); + + rc = sysfs_create_file(sweep2sleep_kobj, &dev_attr_vib_strength.attr); + if (rc) + pr_err("%s: sysfs_create_file failed for vib_strength\n", __func__); + +err_input_dev: + input_free_device(sweep2sleep_pwrdev); + +err_alloc_dev: + pr_info("%s done\n", __func__); + + return 0; +} + +static void __exit sweep2sleep_exit(void) +{ + kobject_del(sweep2sleep_kobj); + input_unregister_handler(&s2s_input_handler); + destroy_workqueue(s2s_input_wq); + input_unregister_device(sweep2sleep_pwrdev); + input_free_device(sweep2sleep_pwrdev); + + return; +} + +module_init(sweep2sleep_init); +module_exit(sweep2sleep_exit); From 8afc906f4d2b6f8b31060151e686cbf299ae8050 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 8 Nov 2015 17:39:13 -0500 Subject: [PATCH 040/203] platform/msm: haptic: expose vibrate function --- drivers/platform/msm/qpnp-haptic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index eb1aad575eb1..fa3642036dc7 100755 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -1628,6 +1628,11 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) mutex_unlock(&hap->lock); } +void set_vibrate(int value) +{ + qpnp_hap_td_enable(&ghap->timed_dev, value); +} + /* play pwm bytes */ int qpnp_hap_play_byte(u8 data, bool on) { From 0032300914a11c22ec3460f772f3c032d2beda33 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 25 Jun 2016 00:13:59 -0400 Subject: [PATCH 041/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index f1c2024bbf31..594a0ed11413 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-0.01" +CONFIG_LOCALVERSION="-ElementalX-0.02" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -1744,6 +1744,7 @@ CONFIG_OF_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_SYNAPTICS_S3508_I2C_RMI is not set CONFIG_TOUCHSCREEN_SYNAPTICS_S1302_I2C_RMI=y CONFIG_TOUCHSCREEN_SYNAPTICS_S3320_I2C_RMI=y +CONFIG_SWEEP2SLEEP=y CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_BMA150 is not set @@ -3891,7 +3892,7 @@ CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_NTFS_FS=y # CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +CONFIG_NTFS_RW=y CONFIG_EXFAT_FS=y CONFIG_EXFAT_DISCARD=y # CONFIG_EXFAT_DELAYED_SYNC is not set From d0b4b9fabadf1511346ea0189f98d66f03bbeeb3 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 26 Jun 2016 01:04:46 -0400 Subject: [PATCH 042/203] OnePlus3: Wake gestures: sweep2wake and doubletap2wake --- .../touchscreen/synaptics_driver_s3320.c | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index b3411879c2a7..64deae09ccda 100644 --- a/drivers/input/touchscreen/synaptics_driver_s3320.c +++ b/drivers/input/touchscreen/synaptics_driver_s3320.c @@ -57,6 +57,22 @@ #include #include "synaptics_baseline.h" +#define WAKE_GESTURES 1 +#ifdef WAKE_GESTURES +#define WAKE_GESTURE 0x0b +#define SWEEP_RIGHT 0x01 +#define SWEEP_LEFT 0x02 +#define SWEEP_UP 0x04 +#define SWEEP_DOWN 0x08 +static struct synaptics_ts_data *gl_ts; +static struct input_dev *gesture_dev; +struct kobject *android_touch_kobj; +EXPORT_SYMBOL_GPL(android_touch_kobj); +static int gestures_switch = 0; +static int s2w_switch = 0; +static int dt2w_switch = 0; +#endif + /*------------------------------------------------Global Define--------------------------------------------*/ #define TP_UNKNOWN 0 @@ -1172,6 +1188,55 @@ static void gesture_judge(struct synaptics_ts_data *ts) TPD_DEBUG("gesture suport LeftVee:%d RightVee:%d DouSwip:%d Circle:%d UpVee:%d DouTap:%d\n",\ LeftVee_gesture,RightVee_gesture,DouSwip_gesture,Circle_gesture,UpVee_gesture,DouTap_gesture); + +#ifdef WAKE_GESTURES + if ((gesture == Down2UpSwip && s2w_switch & SWEEP_UP) || + (gesture == Up2DownSwip && s2w_switch & SWEEP_DOWN) || + (gesture == Right2LeftSwip && s2w_switch & SWEEP_LEFT) || + (gesture == Left2RightSwip && s2w_switch & SWEEP_RIGHT) || + (gesture == DouTap && dt2w_switch)) { + + //wake gestures (requires app) + if (gestures_switch) { + int gest; + switch (gesture) { + case DouTap: + gest = 5; + break; + case Down2UpSwip: + gest = 3; + break; + case Up2DownSwip: + gest = 4; + break; + case Right2LeftSwip: + gest = 2; + break; + case Left2RightSwip: + gest = 1; + break; + } + + input_report_rel(gesture_dev, WAKE_GESTURE, gest); + input_sync(gesture_dev); + + //traditional s2w using userspace doubletap gesture from OnePlus (checks proximity sensor and vibrates) + } else if (DouTap_gesture) { + gesture_upload = DouTap; + input_report_key(ts->input_dev, keyCode, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, keyCode, 0); + input_sync(ts->input_dev); + + //traditional s2w if gestures not enabled in OnePlus settings (only turns on screen) + } else { + input_report_key(ts->input_dev, KEY_POWER, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, KEY_POWER, 0); + input_sync(ts->input_dev); + } + } else +#endif if((gesture == DouTap && DouTap_gesture)||(gesture == RightVee && RightVee_gesture)\ ||(gesture == LeftVee && LeftVee_gesture)||(gesture == UpVee && UpVee_gesture)\ ||(gesture == Circle && Circle_gesture)||(gesture == DouSwip && DouSwip_gesture)){ @@ -2302,6 +2367,10 @@ static int synaptics_input_init(struct synaptics_ts_data *ts) #ifdef SUPPORT_GESTURE set_bit(KEY_F4 , ts->input_dev->keybit);//doulbe-tap resume +#ifdef WAKE_GESTURES + set_bit(KEY_POWER, ts->input_dev->keybit); + input_set_capability(ts->input_dev, EV_KEY, KEY_POWER); +#endif #endif /* For multi touch */ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); @@ -3483,6 +3552,88 @@ static int synaptics_ts_init_virtual_key(struct synaptics_ts_data *ts ) } #endif +#ifdef WAKE_GESTURES +static void gestures_enable(void) +{ + struct synaptics_ts_data *ts = gl_ts; + ts->gesture_enable = (gestures_switch || s2w_switch || dt2w_switch || + LeftVee_gesture || RightVee_gesture || DouSwip_gesture || + Circle_gesture || UpVee_gesture || DouTap_gesture) ? 1 : 0; +} + +static ssize_t sweep2wake_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", s2w_switch); + + return count; +} + +static ssize_t sweep2wake_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int input; + sscanf(buf, "%d ", &input); + if (input < 0 || input > 15) { + s2w_switch = 0; + } else { + s2w_switch = input; + } + gestures_enable(); + + return count; +} + +static DEVICE_ATTR(sweep2wake, (S_IWUSR|S_IRUGO), + sweep2wake_show, sweep2wake_dump); + + +static ssize_t doubletap2wake_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", dt2w_switch); + + return count; +} + +static ssize_t doubletap2wake_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int input; + sscanf(buf, "%d ", &input); + dt2w_switch = (input) ? 1 : 0; + gestures_enable(); + + return count; +} + +static DEVICE_ATTR(doubletap2wake, (S_IWUSR|S_IRUGO), + doubletap2wake_show, doubletap2wake_dump); + +static ssize_t wake_gestures_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", gestures_switch); + return count; +} +static ssize_t wake_gestures_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int input; + sscanf(buf, "%d ", &input); + gestures_switch = (input) ? 1 : 0; + gestures_enable(); + + return count; +} + +static DEVICE_ATTR(wake_gestures, (S_IWUSR|S_IRUGO), + wake_gestures_show, wake_gestures_dump); +#endif + static int synaptics_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { #ifdef CONFIG_SYNAPTIC_RED @@ -3707,9 +3858,52 @@ static int synaptics_ts_probe(struct i2c_client *client, const struct i2c_device } #endif init_synaptics_proc(); + +#ifdef WAKE_GESTURES + gl_ts = ts; + + gesture_dev = input_allocate_device(); + if (!gesture_dev) { + pr_err("Can't allocate gesture device\n"); + goto exit_init_failed; + } + + gesture_dev->name = "wake_gesture"; + gesture_dev->phys = "wake_gesture/input0"; + input_set_capability(gesture_dev, EV_REL, WAKE_GESTURE); + + ret = input_register_device(gesture_dev); + if (ret) { + pr_err("%s: input_register_device err=%d\n", __func__, ret); + goto err_gesture_dev; + } + + android_touch_kobj = kobject_create_and_add("android_touch", NULL) ; + if (android_touch_kobj == NULL) { + pr_warn("%s: android_touch_kobj create_and_add failed\n", __func__); + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_sweep2wake.attr); + if (ret) { + pr_warn("%s: sysfs_create_file failed for sweep2wake\n", __func__); + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_doubletap2wake.attr); + if (ret) { + pr_warn("%s: sysfs_create_file failed for doubletap2wake\n", __func__); + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_wake_gestures.attr); + if (ret) { + pr_warn("%s: sysfs_create_file failed for wake_gestures\n", __func__); + } +#endif + TPDTM_DMESG("synaptics_ts_probe 3203: normal end\n"); return 0; +#ifdef WAKE_GESTURES +err_gesture_dev: + input_free_device(gesture_dev); +#endif + exit_init_failed: free_irq(client->irq,ts); exit_createworkqueue_failed: From 4f2a2e4246e3882c0eac811acb0ec23cce829654 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 26 Jun 2016 01:04:59 -0400 Subject: [PATCH 043/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 594a0ed11413..af09951c98c1 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-0.02" +CONFIG_LOCALVERSION="-ElementalX-0.03" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -365,11 +365,11 @@ CONFIG_ARCH_NR_GPIO=1024 # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_PREEMPT_COUNT=y -# CONFIG_HZ_100 is not set +CONFIG_HZ_100=y # CONFIG_HZ_250 is not set -CONFIG_HZ_300=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set -CONFIG_HZ=300 +CONFIG_HZ=100 CONFIG_SCHED_HRTICK=y CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y From 11e5510451a74f47a151a735adb7efca1ffd33d0 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 26 Jun 2016 23:00:04 -0400 Subject: [PATCH 044/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index af09951c98c1..dc4d797469c9 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-0.03" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.04" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 3559b100196df6fc95a3a8e49077a05a36654005 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 26 Jun 2016 23:00:51 -0400 Subject: [PATCH 045/203] Wake gestures: disable stock doubletap if dt2w_switch is disabled --- drivers/input/touchscreen/synaptics_driver_s3320.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index 64deae09ccda..51e78d5e6f4e 100644 --- a/drivers/input/touchscreen/synaptics_driver_s3320.c +++ b/drivers/input/touchscreen/synaptics_driver_s3320.c @@ -1240,6 +1240,10 @@ static void gesture_judge(struct synaptics_ts_data *ts) if((gesture == DouTap && DouTap_gesture)||(gesture == RightVee && RightVee_gesture)\ ||(gesture == LeftVee && LeftVee_gesture)||(gesture == UpVee && UpVee_gesture)\ ||(gesture == Circle && Circle_gesture)||(gesture == DouSwip && DouSwip_gesture)){ +#ifdef WAKE_GESTURES + if (!dt2w_switch && s2w_switch && gesture == DouTap) + return; +#endif gesture_upload = gesture; input_report_key(ts->input_dev, keyCode, 1); input_sync(ts->input_dev); From e416a9d17282cedb5ef07b352fcf24b5a77e743b Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 26 Jun 2016 23:06:11 -0400 Subject: [PATCH 046/203] mdss_fb: add backlight dimmer option --- drivers/video/msm/mdss/mdss_fb.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index f1ddf9fc1c93..89f1ccd6c62c 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -70,6 +70,12 @@ #define BLANK_FLAG_LP FB_BLANK_NORMAL #define BLANK_FLAG_ULP FB_BLANK_VSYNC_SUSPEND +#define MDSS_BRIGHT_TO_BL_DIM(out, v) do {\ + out = (12*v*v+1393*v+3060)/4465;\ + } while (0) +bool backlight_dimmer = false; +module_param(backlight_dimmer, bool, 0755); + static struct fb_info *fbi_list[MAX_FBI_LIST]; static int fbi_list_index; @@ -262,10 +268,14 @@ static void mdss_fb_set_bl_brightness(struct led_classdev *led_cdev, if (value > mfd->panel_info->brightness_max) value = mfd->panel_info->brightness_max; - /* This maps android backlight level 0 to 255 into - driver backlight level 0 to bl_max with rounding */ - MDSS_BRIGHT_TO_BL(bl_lvl, value, mfd->panel_info->bl_max, - mfd->panel_info->brightness_max); + if (backlight_dimmer) { + MDSS_BRIGHT_TO_BL_DIM(bl_lvl, value); + } else { + /* This maps android backlight level 0 to 255 into + driver backlight level 0 to bl_max with rounding */ + MDSS_BRIGHT_TO_BL(bl_lvl, value, mfd->panel_info->bl_max, + mfd->panel_info->brightness_max); + } if (!bl_lvl && value) bl_lvl = 1; From 20eec615b9dfd5cd45ea049177eb04b7b96c2fae Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 28 Jun 2016 22:04:08 -0400 Subject: [PATCH 047/203] otg: enable switch --- drivers/usb/dwc3/dwc3-msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 0b61258d992a..beca41dd4d8d 100755 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -244,7 +244,7 @@ struct dwc3_msm { unsigned int lpm_to_suspend_delay; bool init; }; -int otg_switch; +int otg_switch = 1; struct dwc3_msm *opmdwc; bool gadget_start = false;/*Anderson-Avoid_warning_about_irq+ */ From 2004a4581028b6d0e5f7573a664901a6909e0292 Mon Sep 17 00:00:00 2001 From: flar2 Date: Thu, 30 Jun 2016 23:27:31 -0400 Subject: [PATCH 048/203] hid-sony: fix build error --- drivers/hid/hid-sony.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 15b3475e641d..802e1d451449 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1100,7 +1100,7 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count, return 0; } -static void sony_input_configured(struct hid_device *hdev, +static int sony_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { struct sony_sc *sc = hid_get_drvdata(hdev); @@ -1114,6 +1114,8 @@ static void sony_input_configured(struct hid_device *hdev, hid_err(sc->hdev, "Unable to initialize multi-touch slots\n"); } + + return 0; } /* From 435535b08bbe1e9500c35c56b8e26acdfd19a667 Mon Sep 17 00:00:00 2001 From: flar2 Date: Thu, 30 Jun 2016 23:29:45 -0400 Subject: [PATCH 049/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index dc4d797469c9..cc589bcc2f5d 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.04" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.05" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -1607,7 +1607,7 @@ CONFIG_BUS_AUTO_SUSPEND=y # Input device support # CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set +CONFIG_INPUT_FF_MEMLESS=y # CONFIG_INPUT_POLLDEV is not set # CONFIG_INPUT_SPARSEKMAP is not set # CONFIG_INPUT_MATRIXKMAP is not set @@ -1619,7 +1619,7 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_JOYDEV=y CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set CONFIG_INPUT_KEYRESET=y @@ -2999,7 +2999,8 @@ CONFIG_HID_MULTITOUCH=y # CONFIG_HID_ROCCAT is not set # CONFIG_HID_SAITEK is not set # CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set +CONFIG_HID_SONY=y +CONFIG_SONY_FF=y # CONFIG_HID_SPEEDLINK is not set # CONFIG_HID_STEELSERIES is not set # CONFIG_HID_SUNPLUS is not set From c248e5ee0d5cd8a0107db20b2adbffdd693aac32 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 1 Jul 2016 11:57:59 -0400 Subject: [PATCH 050/203] msm-sleeper: shut down cores while screen is off --- drivers/cpufreq/Kconfig | 6 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/msm-sleeper.c | 218 ++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 drivers/cpufreq/msm-sleeper.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index a5bb7dc7ef55..653c8e25322c 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -244,6 +244,12 @@ config CPU_BOOST If in doubt, say N. +config MSM_SLEEPER + bool "Shut down cores while screen is off" + default y + help + Shut down cores while screen is off + menu "x86 CPU frequency scaling drivers" depends on X86 source "drivers/cpufreq/Kconfig.x86" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 66a9e4c6da65..593e77841142 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o +obj-$(CONFIG_MSM_SLEEPER) += msm-sleeper.o ################################################################################## # x86 drivers. diff --git a/drivers/cpufreq/msm-sleeper.c b/drivers/cpufreq/msm-sleeper.c new file mode 100644 index 000000000000..6ea17dc7d39f --- /dev/null +++ b/drivers/cpufreq/msm-sleeper.c @@ -0,0 +1,218 @@ +/* + * msm-sleeper.c + * + * Copyright (C) 2016 Aaron Segaert + * + * 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 +#include +#include +#include + +#define MSM_SLEEPER "msm_sleeper" +#define MSM_SLEEPER_MAJOR_VERSION 5 +#define MSM_SLEEPER_MINOR_VERSION 0 +#define MSM_SLEEPER_ENABLED 1 + +struct msm_sleeper_data { + unsigned int enabled; + struct notifier_block notif; + struct work_struct suspend_work; + struct work_struct resume_work; +} sleeper_data = { + .enabled = MSM_SLEEPER_ENABLED +}; + +static struct workqueue_struct *sleeper_wq; + +static void msm_sleeper_suspend(struct work_struct *work) +{ + int cpu; + + for_each_possible_cpu(cpu) { + if (cpu > 1 && cpu_online(cpu)) { + cpu_down(cpu); + } + } +} + +static void __ref msm_sleeper_resume(struct work_struct *work) +{ + int cpu; + + for_each_possible_cpu(cpu) { + if (cpu && cpu_is_offline(cpu)) { + cpu_up(cpu); + } + } +} + +static int fb_notifier_callback(struct notifier_block *this, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + + if (!sleeper_data.enabled) + return NOTIFY_OK; + + if (evdata && evdata->data && event == FB_EVENT_BLANK) { + blank = evdata->data; + switch (*blank) { + case FB_BLANK_UNBLANK: + //display on + queue_work_on(0, sleeper_wq, &sleeper_data.resume_work); + break; + case FB_BLANK_POWERDOWN: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_NORMAL: + //display off + queue_work_on(0, sleeper_wq, &sleeper_data.suspend_work); + break; + } + } + + return NOTIFY_OK; +} + +static ssize_t show_enable(struct device *dev, + struct device_attribute *msm_sleeper_attrs, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", sleeper_data.enabled); +} + +static ssize_t __ref store_enable(struct device *dev, + struct device_attribute *msm_sleeper_attrs, + const char *buf, size_t count) +{ + int ret, cpu; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + + sleeper_data.enabled = val; + + if (!sleeper_data.enabled) { + for_each_possible_cpu(cpu) { + if (cpu_is_offline(cpu)) { + cpu_up(cpu); + } + } + } + + return count; +} + +static DEVICE_ATTR(enabled, (S_IWUSR|S_IRUGO), show_enable, store_enable); + +static struct attribute *msm_sleeper_attrs[] = { + &dev_attr_enabled.attr, + NULL +}; + +static struct attribute_group attr_group = { + .attrs = msm_sleeper_attrs, +}; + +static struct platform_device msm_sleeper_device = { + .name = MSM_SLEEPER, + .id = -1, +}; + +static int msm_sleeper_probe(struct platform_device *pdev) +{ + int ret = 0; + + pr_info("msm-sleeper version %d.%d\n", + MSM_SLEEPER_MAJOR_VERSION, + MSM_SLEEPER_MINOR_VERSION); + + sleeper_wq = alloc_workqueue("msm_sleeper_wq", + WQ_HIGHPRI | WQ_FREEZABLE, 0); + if (!sleeper_wq) { + ret = -ENOMEM; + goto err_out; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &attr_group); + if (ret) { + ret = -EINVAL; + goto err_dev; + } + + sleeper_data.notif.notifier_call = fb_notifier_callback; + if (fb_register_client(&sleeper_data.notif)) { + ret = -EINVAL; + goto err_dev; + } + + INIT_WORK(&sleeper_data.resume_work, msm_sleeper_resume); + INIT_WORK(&sleeper_data.suspend_work, msm_sleeper_suspend); + + return ret; + +err_dev: + destroy_workqueue(sleeper_wq); + +err_out: + return ret; +} + +static int msm_sleeper_remove(struct platform_device *pdev) +{ + destroy_workqueue(sleeper_wq); + + return 0; +} + +static struct platform_driver msm_sleeper_driver = { + .probe = msm_sleeper_probe, + .remove = msm_sleeper_remove, + .driver = { + .name = MSM_SLEEPER, + .owner = THIS_MODULE, + }, +}; + +static int __init msm_sleeper_init(void) +{ + int ret; + + ret = platform_driver_register(&msm_sleeper_driver); + if (ret) { + pr_err("%s: Driver register failed: %d\n", MSM_SLEEPER, ret); + return ret; + } + + ret = platform_device_register(&msm_sleeper_device); + if (ret) { + pr_err("%s: Device register failed: %d\n", MSM_SLEEPER, ret); + return ret; + } + + pr_info("%s: Device init\n", MSM_SLEEPER); + + return ret; +} + +static void __exit msm_sleeper_exit(void) +{ + platform_device_unregister(&msm_sleeper_device); + platform_driver_unregister(&msm_sleeper_driver); +} + +late_initcall(msm_sleeper_init); +module_exit(msm_sleeper_exit); From c88593eefbd6e44990c2a88cdec4b141d3c83087 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 1 Jul 2016 11:58:09 -0400 Subject: [PATCH 051/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index cc589bcc2f5d..8b1b39dec8ff 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -513,6 +513,7 @@ CONFIG_CPU_FREQ_GOV_INTERACTIVE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_CPUFREQ_DT is not set CONFIG_CPU_BOOST=y +CONFIG_MSM_SLEEPER=y # # ARM CPU frequency scaling drivers From 972ad1d1b4d98a29f30e6481b966df6b25c73727 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 2 Jul 2016 17:22:45 -0400 Subject: [PATCH 052/203] Revert "msm-sleeper: shut down cores while screen is off" This reverts commit c248e5ee0d5cd8a0107db20b2adbffdd693aac32. --- drivers/cpufreq/Kconfig | 6 - drivers/cpufreq/Makefile | 1 - drivers/cpufreq/msm-sleeper.c | 218 ---------------------------------- 3 files changed, 225 deletions(-) delete mode 100644 drivers/cpufreq/msm-sleeper.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 653c8e25322c..a5bb7dc7ef55 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -244,12 +244,6 @@ config CPU_BOOST If in doubt, say N. -config MSM_SLEEPER - bool "Shut down cores while screen is off" - default y - help - Shut down cores while screen is off - menu "x86 CPU frequency scaling drivers" depends on X86 source "drivers/cpufreq/Kconfig.x86" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 593e77841142..66a9e4c6da65 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o -obj-$(CONFIG_MSM_SLEEPER) += msm-sleeper.o ################################################################################## # x86 drivers. diff --git a/drivers/cpufreq/msm-sleeper.c b/drivers/cpufreq/msm-sleeper.c deleted file mode 100644 index 6ea17dc7d39f..000000000000 --- a/drivers/cpufreq/msm-sleeper.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * msm-sleeper.c - * - * Copyright (C) 2016 Aaron Segaert - * - * 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 -#include -#include -#include - -#define MSM_SLEEPER "msm_sleeper" -#define MSM_SLEEPER_MAJOR_VERSION 5 -#define MSM_SLEEPER_MINOR_VERSION 0 -#define MSM_SLEEPER_ENABLED 1 - -struct msm_sleeper_data { - unsigned int enabled; - struct notifier_block notif; - struct work_struct suspend_work; - struct work_struct resume_work; -} sleeper_data = { - .enabled = MSM_SLEEPER_ENABLED -}; - -static struct workqueue_struct *sleeper_wq; - -static void msm_sleeper_suspend(struct work_struct *work) -{ - int cpu; - - for_each_possible_cpu(cpu) { - if (cpu > 1 && cpu_online(cpu)) { - cpu_down(cpu); - } - } -} - -static void __ref msm_sleeper_resume(struct work_struct *work) -{ - int cpu; - - for_each_possible_cpu(cpu) { - if (cpu && cpu_is_offline(cpu)) { - cpu_up(cpu); - } - } -} - -static int fb_notifier_callback(struct notifier_block *this, - unsigned long event, void *data) -{ - struct fb_event *evdata = data; - int *blank; - - if (!sleeper_data.enabled) - return NOTIFY_OK; - - if (evdata && evdata->data && event == FB_EVENT_BLANK) { - blank = evdata->data; - switch (*blank) { - case FB_BLANK_UNBLANK: - //display on - queue_work_on(0, sleeper_wq, &sleeper_data.resume_work); - break; - case FB_BLANK_POWERDOWN: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_NORMAL: - //display off - queue_work_on(0, sleeper_wq, &sleeper_data.suspend_work); - break; - } - } - - return NOTIFY_OK; -} - -static ssize_t show_enable(struct device *dev, - struct device_attribute *msm_sleeper_attrs, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", sleeper_data.enabled); -} - -static ssize_t __ref store_enable(struct device *dev, - struct device_attribute *msm_sleeper_attrs, - const char *buf, size_t count) -{ - int ret, cpu; - unsigned long val; - - ret = kstrtoul(buf, 0, &val); - if (ret < 0) - return ret; - - sleeper_data.enabled = val; - - if (!sleeper_data.enabled) { - for_each_possible_cpu(cpu) { - if (cpu_is_offline(cpu)) { - cpu_up(cpu); - } - } - } - - return count; -} - -static DEVICE_ATTR(enabled, (S_IWUSR|S_IRUGO), show_enable, store_enable); - -static struct attribute *msm_sleeper_attrs[] = { - &dev_attr_enabled.attr, - NULL -}; - -static struct attribute_group attr_group = { - .attrs = msm_sleeper_attrs, -}; - -static struct platform_device msm_sleeper_device = { - .name = MSM_SLEEPER, - .id = -1, -}; - -static int msm_sleeper_probe(struct platform_device *pdev) -{ - int ret = 0; - - pr_info("msm-sleeper version %d.%d\n", - MSM_SLEEPER_MAJOR_VERSION, - MSM_SLEEPER_MINOR_VERSION); - - sleeper_wq = alloc_workqueue("msm_sleeper_wq", - WQ_HIGHPRI | WQ_FREEZABLE, 0); - if (!sleeper_wq) { - ret = -ENOMEM; - goto err_out; - } - - ret = sysfs_create_group(&pdev->dev.kobj, &attr_group); - if (ret) { - ret = -EINVAL; - goto err_dev; - } - - sleeper_data.notif.notifier_call = fb_notifier_callback; - if (fb_register_client(&sleeper_data.notif)) { - ret = -EINVAL; - goto err_dev; - } - - INIT_WORK(&sleeper_data.resume_work, msm_sleeper_resume); - INIT_WORK(&sleeper_data.suspend_work, msm_sleeper_suspend); - - return ret; - -err_dev: - destroy_workqueue(sleeper_wq); - -err_out: - return ret; -} - -static int msm_sleeper_remove(struct platform_device *pdev) -{ - destroy_workqueue(sleeper_wq); - - return 0; -} - -static struct platform_driver msm_sleeper_driver = { - .probe = msm_sleeper_probe, - .remove = msm_sleeper_remove, - .driver = { - .name = MSM_SLEEPER, - .owner = THIS_MODULE, - }, -}; - -static int __init msm_sleeper_init(void) -{ - int ret; - - ret = platform_driver_register(&msm_sleeper_driver); - if (ret) { - pr_err("%s: Driver register failed: %d\n", MSM_SLEEPER, ret); - return ret; - } - - ret = platform_device_register(&msm_sleeper_device); - if (ret) { - pr_err("%s: Device register failed: %d\n", MSM_SLEEPER, ret); - return ret; - } - - pr_info("%s: Device init\n", MSM_SLEEPER); - - return ret; -} - -static void __exit msm_sleeper_exit(void) -{ - platform_device_unregister(&msm_sleeper_device); - platform_driver_unregister(&msm_sleeper_driver); -} - -late_initcall(msm_sleeper_init); -module_exit(msm_sleeper_exit); From 6ccf58ecf127c75c5723bcd62bc5470437206a2a Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 2 Jul 2016 17:23:56 -0400 Subject: [PATCH 053/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 8b1b39dec8ff..715edce1e8a4 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.05" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.06" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -513,7 +513,6 @@ CONFIG_CPU_FREQ_GOV_INTERACTIVE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_CPUFREQ_DT is not set CONFIG_CPU_BOOST=y -CONFIG_MSM_SLEEPER=y # # ARM CPU frequency scaling drivers From 25216d16040c54ac9ef9d9a90af43ec602d166c7 Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 5 Jul 2016 22:49:06 -0400 Subject: [PATCH 054/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 715edce1e8a4..f633e1503b26 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.06" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.07" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 3e749d8b1ab9c12cbce1417df26d50b64a24c1e8 Mon Sep 17 00:00:00 2001 From: tbalden Date: Sat, 16 Jul 2016 14:17:25 -0700 Subject: [PATCH 055/203] mdss mdp: kcal for mdss_mdp_v1_7 Adding the kcal interface by @savoca and @faux123 porting from m9 version by @flar2 Using the MDP 1_7 userspace structs to inject configurations of kcal to the pp_cache configs. Overriding userspace copy with memcpy when copy_from_user fails (in case of kcal interface used). Adding a simple mdp ctl struct caching to the kcal driver to grab ctl struct for config calls. Could be done nicer with direct interfacing to userspace, leaves some space to make the kernel crash if a third party app sends faulty configs, but there's no security issue or degradation of functionality with this memcpy patch. @tbalden Signed-off-by: flar2 --- drivers/video/msm/mdss/Kconfig | 7 + drivers/video/msm/mdss/Makefile | 1 + drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c | 730 ++++++++++++++++++ .../video/msm/mdss/mdss_mdp_pp_cache_config.c | 11 + 4 files changed, 749 insertions(+) create mode 100644 drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c diff --git a/drivers/video/msm/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig index 3029d0ef7498..f1cb76dadd4d 100644 --- a/drivers/video/msm/mdss/Kconfig +++ b/drivers/video/msm/mdss/Kconfig @@ -62,3 +62,10 @@ config FB_MSM_MDSS_XLOG_DEBUG features to: Dump MDSS registers during driver errors, panic driver during fatal errors and enable some display-driver logging into an internal buffer (this avoids logging overhead). + +config FB_MSM_MDSS_KCAL_CTRL + depends on FB_MSM_MDSS + bool "MDSS color control" + ---help--- + Enable sysfs for post-processing control of mdss-mdp5 display + controllers in MDSS. diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile index 152b7c03279d..d9e35b3456fb 100644 --- a/drivers/video/msm/mdss/Makefile +++ b/drivers/video/msm/mdss/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o mdss_util.o obj-$(CONFIG_COMPAT) += mdss_compat_utils.o +obj-$(CONFIG_FB_MSM_MDSS_KCAL_CTRL) += mdss_mdp_kcal_ctrl.o diff --git a/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c new file mode 100644 index 000000000000..a3b2e3661266 --- /dev/null +++ b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c @@ -0,0 +1,730 @@ +/* + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, LGE Inc. All rights reserved + * Copyright (c) 2014 savoca + * Copyright (c) 2014 Paul Reioux + * Copyright (c) 2016 Pal Zoltan Illes + * + * 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 +#include +#include +#include +#include +#include + +#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) && defined(CONFIG_FB) +#include +#include +#include +#elif defined(CONFIG_FB) +#include +#include +#endif + +#include "mdss_mdp.h" + +#define DEF_PCC 0x100 +#define DEF_PA 0xff +#define PCC_ADJ 0x80 + +struct kcal_lut_data { +#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) && defined(CONFIG_FB) + struct mmi_notifier panel_nb; +#elif defined(CONFIG_FB) + struct device dev; + struct notifier_block panel_nb; +#endif + bool queue_changes; + int red; + int green; + int blue; + int minimum; + int enable; + int invert; + int sat; + int hue; + int val; + int cont; +}; + +static uint32_t igc_Table_Inverted[IGC_LUT_ENTRIES] = { + 267390960, 266342368, 265293776, 264245184, + 263196592, 262148000, 261099408, 260050816, + 259002224, 257953632, 256905040, 255856448, + 254807856, 253759264, 252710672, 251662080, + 250613488, 249564896, 248516304, 247467712, + 246419120, 245370528, 244321936, 243273344, + 242224752, 241176160, 240127568, 239078976, + 238030384, 236981792, 235933200, 234884608, + 233836016, 232787424, 231738832, 230690240, + 229641648, 228593056, 227544464, 226495872, + 225447280, 224398688, 223350096, 222301504, + 221252912, 220204320, 219155728, 218107136, + 217058544, 216009952, 214961360, 213912768, + 212864176, 211815584, 210766992, 209718400, + 208669808, 207621216, 206572624, 205524032, + 204475440, 203426848, 202378256, 201329664, + 200281072, 199232480, 198183888, 197135296, + 196086704, 195038112, 193989520, 192940928, + 191892336, 190843744, 189795152, 188746560, + 187697968, 186649376, 185600784, 184552192, + 183503600, 182455008, 181406416, 180357824, + 179309232, 178260640, 177212048, 176163456, + 175114864, 174066272, 173017680, 171969088, + 170920496, 169871904, 168823312, 167774720, + 166726128, 165677536, 164628944, 163580352, + 162531760, 161483168, 160434576, 159385984, + 158337392, 157288800, 156240208, 155191616, + 154143024, 153094432, 152045840, 150997248, + 149948656, 148900064, 147851472, 146802880, + 145754288, 144705696, 143657104, 142608512, + 141559920, 140511328, 139462736, 138414144, + 137365552, 136316960, 135268368, 134219776, + 133171184, 132122592, 131074000, 130025408, + 128976816, 127928224, 126879632, 125831040, + 124782448, 123733856, 122685264, 121636672, + 120588080, 119539488, 118490896, 117442304, + 116393712, 115345120, 114296528, 113247936, + 112199344, 111150752, 110102160, 109053568, + 108004976, 106956384, 105907792, 104859200, + 103810608, 102762016, 101713424, 100664832, + 99616240, 98567648, 97519056, 96470464, + 95421872, 94373280, 93324688, 92276096, + 91227504, 90178912, 89130320, 88081728, + 87033136, 85984544, 84935952, 83887360, + 82838768, 81790176, 80741584, 79692992, + 78644400, 77595808, 76547216, 75498624, + 74450032, 73401440, 72352848, 71304256, + 70255664, 69207072, 68158480, 67109888, + 66061296, 65012704, 63964112, 62915520, + 61866928, 60818336, 59769744, 58721152, + 57672560, 56623968, 55575376, 54526784, + 53478192, 52429600, 51381008, 50332416, + 49283824, 48235232, 47186640, 46138048, + 45089456, 44040864, 42992272, 41943680, + 40895088, 39846496, 38797904, 37749312, + 36700720, 35652128, 34603536, 33554944, + 32506352, 31457760, 30409168, 29360576, + 28311984, 27263392, 26214800, 25166208, + 24117616, 23069024, 22020432, 20971840, + 19923248, 18874656, 17826064, 16777472, + 15728880, 14680288, 13631696, 12583104, + 11534512, 10485920, 9437328, 8388736, + 7340144, 6291552, 5242960, 4194368, + 3145776, 2097184, 1048592, 0 +}; + +static uint32_t igc_Table_RGB[IGC_LUT_ENTRIES] = { + 4080, 4064, 4048, 4032, 4016, 4000, 3984, 3968, 3952, 3936, 3920, 3904, + 3888, 3872, 3856, 3840, 3824, 3808, 3792, 3776, 3760, 3744, 3728, 3712, + 3696, 3680, 3664, 3648, 3632, 3616, 3600, 3584, 3568, 3552, 3536, 3520, + 3504, 3488, 3472, 3456, 3440, 3424, 3408, 3392, 3376, 3360, 3344, 3328, + 3312, 3296, 3280, 3264, 3248, 3232, 3216, 3200, 3184, 3168, 3152, 3136, + 3120, 3104, 3088, 3072, 3056, 3040, 3024, 3008, 2992, 2976, 2960, 2944, + 2928, 2912, 2896, 2880, 2864, 2848, 2832, 2816, 2800, 2784, 2768, 2752, + 2736, 2720, 2704, 2688, 2672, 2656, 2640, 2624, 2608, 2592, 2576, 2560, + 2544, 2528, 2512, 2496, 2480, 2464, 2448, 2432, 2416, 2400, 2384, 2368, + 2352, 2336, 2320, 2304, 2288, 2272, 2256, 2240, 2224, 2208, 2192, 2176, + 2160, 2144, 2128, 2112, 2096, 2080, 2064, 2048, 2032, 2016, 2000, 1984, + 1968, 1952, 1936, 1920, 1904, 1888, 1872, 1856, 1840, 1824, 1808, 1792, + 1776, 1760, 1744, 1728, 1712, 1696, 1680, 1664, 1648, 1632, 1616, 1600, + 1584, 1568, 1552, 1536, 1520, 1504, 1488, 1472, 1456, 1440, 1424, 1408, + 1392, 1376, 1360, 1344, 1328, 1312, 1296, 1280, 1264, 1248, 1232, 1216, + 1200, 1184, 1168, 1152, 1136, 1120, 1104, 1088, 1072, 1056, 1040, 1024, + 1008, 992, 976, 960, 944, 928, 912, 896, 880, 864, 848, 832, + 816, 800, 784, 768, 752, 736, 720, 704, 688, 672, 656, 640, + 624, 608, 592, 576, 560, 544, 528, 512, 496, 480, 464, 448, + 432, 416, 400, 384, 368, 352, 336, 320, 304, 288, 272, 256, + 240, 224, 208, 192, 176, 160, 144, 128, 112, 96, 80, 64, + 48, 32, 16, 0 +}; + +struct mdss_mdp_ctl *fb0_ctl = 0; + +static int mdss_mdp_kcal_store_fb0_ctl(void) +{ + int i; + struct mdss_mdp_ctl *ctl; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + if (fb0_ctl) return 1; + if (!mdata) { + pr_err("%s mdata is NULL...",__func__); + return 0; + } + + for (i = 0; i < mdata->nctl; i++) { + ctl = mdata->ctl_off + i; + if (!ctl) { + pr_err("%s ctl is NULL...\n",__func__); + return 0; + } + if (!(ctl->mfd)) { + pr_err("%s MFD is NULL...\n",__func__); + return 0; + } + pr_err("%s panel name %s\n",__func__,ctl->mfd->panel_info->panel_name); + if ( ctl->mfd->panel_info->fb_num == 0 ) { + pr_err("%s panel found...\n",__func__); + fb0_ctl = ctl; + return 1; + } + } + return 0; +} + +static bool mdss_mdp_kcal_is_panel_on(void) +{ + int i; + struct mdss_mdp_ctl *ctl; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + for (i = 0; i < mdata->nctl; i++) { + ctl = mdata->ctl_off + i; + if (mdss_mdp_ctl_is_power_on(ctl)) + return true; + } + + return false; +} + +static void mdss_mdp_kcal_update_pcc(struct kcal_lut_data *lut_data) +{ + u32 copyback = 0; + struct mdp_pcc_cfg_data pcc_config; + + struct mdp_pcc_data_v1_7 *payload; + + lut_data->red = lut_data->red < lut_data->minimum ? + lut_data->minimum : lut_data->red; + lut_data->green = lut_data->green < lut_data->minimum ? + lut_data->minimum : lut_data->green; + lut_data->blue = lut_data->blue < lut_data->minimum ? + lut_data->minimum : lut_data->blue; + + memset(&pcc_config, 0, sizeof(struct mdp_pcc_cfg_data)); + + pcc_config.version = mdp_pcc_v1_7; + pcc_config.block = MDP_LOGICAL_BLOCK_DISP_0; + pcc_config.ops = lut_data->enable ? + MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE : + MDP_PP_OPS_WRITE | MDP_PP_OPS_DISABLE; + pcc_config.r.r = lut_data->red * PCC_ADJ; + pcc_config.g.g = lut_data->green * PCC_ADJ; + pcc_config.b.b = lut_data->blue * PCC_ADJ; + + payload = kzalloc(sizeof(struct mdp_pcc_data_v1_7),GFP_USER); + payload->r.r = pcc_config.r.r; + payload->g.g = pcc_config.g.g; + payload->b.b = pcc_config.b.b; + pcc_config.cfg_payload = payload; + + if (!mdss_mdp_kcal_store_fb0_ctl()) return; + mdss_mdp_pcc_config(fb0_ctl->mfd, &pcc_config, ©back); + kfree(payload); +} + +static void mdss_mdp_kcal_update_pa(struct kcal_lut_data *lut_data) +{ + u32 copyback = 0; + struct mdp_pa_cfg_data pa_config; + struct mdp_pa_v2_cfg_data pa_v2_config; + struct mdp_pa_data_v1_7 *payload; + + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + if (!mdss_mdp_kcal_store_fb0_ctl()) return; + + if (mdata->mdp_rev < MDSS_MDP_HW_REV_103) { + memset(&pa_config, 0, sizeof(struct mdp_pa_cfg_data)); + + pa_config.block = MDP_LOGICAL_BLOCK_DISP_0; + pa_config.pa_data.flags = lut_data->enable ? + MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE : + MDP_PP_OPS_WRITE | MDP_PP_OPS_DISABLE; + pa_config.pa_data.hue_adj = lut_data->hue; + pa_config.pa_data.sat_adj = lut_data->sat; + pa_config.pa_data.val_adj = lut_data->val; + pa_config.pa_data.cont_adj = lut_data->cont; + + mdss_mdp_pa_config(fb0_ctl->mfd, &pa_config, ©back); + } else { + memset(&pa_v2_config, 0, sizeof(struct mdp_pa_v2_cfg_data)); + + pa_v2_config.version = mdp_pa_v1_7; + pa_v2_config.block = MDP_LOGICAL_BLOCK_DISP_0; + pa_v2_config.pa_v2_data.flags = lut_data->enable ? + MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE : + MDP_PP_OPS_WRITE | MDP_PP_OPS_DISABLE; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_HUE_ENABLE; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_HUE_MASK; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_SAT_ENABLE; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_SAT_MASK; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_VAL_ENABLE; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_VAL_MASK; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_CONT_ENABLE; + pa_v2_config.pa_v2_data.flags |= MDP_PP_PA_CONT_MASK; + pa_v2_config.pa_v2_data.global_hue_adj = lut_data->hue; + pa_v2_config.pa_v2_data.global_sat_adj = lut_data->sat; + pa_v2_config.pa_v2_data.global_val_adj = lut_data->val; + pa_v2_config.pa_v2_data.global_cont_adj = lut_data->cont; + pa_v2_config.flags = pa_v2_config.pa_v2_data.flags; + + payload = kzalloc(sizeof(struct mdp_pa_data_v1_7),GFP_USER); + payload->mode = pa_v2_config.flags; + payload->global_hue_adj = lut_data->hue; + payload->global_sat_adj = lut_data->sat; + payload->global_val_adj = lut_data->val; + payload->global_cont_adj = lut_data->cont; + pa_v2_config.cfg_payload = payload; + + mdss_mdp_pa_v2_config(fb0_ctl->mfd, &pa_v2_config, ©back); + kfree(payload); + } +} + +static void mdss_mdp_kcal_update_igc(struct kcal_lut_data *lut_data) +{ + u32 copyback = 0, copy_from_kernel = 1; + struct mdp_igc_lut_data igc_config; + struct mdp_igc_lut_data_v1_7 *payload; + + if (!mdss_mdp_kcal_store_fb0_ctl()) return; + + memset(&igc_config, 0, sizeof(struct mdp_igc_lut_data)); + + igc_config.version = mdp_igc_v1_7; + igc_config.block = MDP_LOGICAL_BLOCK_DISP_0; + igc_config.ops = lut_data->invert && lut_data->enable ? + MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE : + MDP_PP_OPS_WRITE | MDP_PP_OPS_DISABLE; + igc_config.len = IGC_LUT_ENTRIES; + igc_config.c0_c1_data = &igc_Table_Inverted[0]; + igc_config.c2_data = &igc_Table_RGB[0]; + + payload = kzalloc(sizeof(struct mdp_igc_lut_data_v1_7),GFP_USER); + payload->len = IGC_LUT_ENTRIES; + payload->c0_c1_data = &igc_Table_Inverted[0]; + payload->c2_data = &igc_Table_RGB[0]; + + igc_config.cfg_payload = payload; + + mdss_mdp_igc_lut_config(fb0_ctl->mfd, &igc_config, ©back, copy_from_kernel); + kfree(payload); +} + +static ssize_t kcal_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int kcal_r, kcal_g, kcal_b, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = sscanf(buf, "%d %d %d", &kcal_r, &kcal_g, &kcal_b); + if ((r != 3) || (kcal_r < 0 || kcal_r > 256) || + (kcal_g < 0 || kcal_g > 256) || (kcal_b < 0 || kcal_b > 256)) + return -EINVAL; + + lut_data->red = kcal_r; + lut_data->green = kcal_g; + lut_data->blue = kcal_b; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_pcc(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d %d %d\n", + lut_data->red, lut_data->green, lut_data->blue); +} + +static ssize_t kcal_min_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_min, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_min); + if ((r) || (kcal_min < 0 || kcal_min > 256)) + return -EINVAL; + + lut_data->minimum = kcal_min; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_pcc(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_min_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->minimum); +} + +static ssize_t kcal_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_enable, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_enable); + if ((r) || (kcal_enable != 0 && kcal_enable != 1) || + (lut_data->enable == kcal_enable)) + return -EINVAL; + + lut_data->enable = kcal_enable; + + if (mdss_mdp_kcal_is_panel_on()) { + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_update_igc(lut_data); + } else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->enable); +} + +static ssize_t kcal_invert_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_invert, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_invert); + if ((r) || (kcal_invert != 0 && kcal_invert != 1) || + (lut_data->invert == kcal_invert)) + return -EINVAL; + + lut_data->invert = kcal_invert; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_igc(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_invert_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->invert); +} + +static ssize_t kcal_sat_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_sat, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_sat); + if ((r) || ((kcal_sat < 224 || kcal_sat > 383) && kcal_sat != 128)) + return -EINVAL; + + lut_data->sat = kcal_sat; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_pa(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_sat_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->sat); +} + +static ssize_t kcal_hue_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_hue, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_hue); + if ((r) || (kcal_hue < 0 || kcal_hue > 1536)) + return -EINVAL; + + lut_data->hue = kcal_hue; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_pa(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_hue_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->hue); +} + +static ssize_t kcal_val_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_val, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_val); + if ((r) || (kcal_val < 128 || kcal_val > 383)) + return -EINVAL; + + lut_data->val = kcal_val; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_pa(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_val_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->val); +} + +static ssize_t kcal_cont_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int kcal_cont, r; + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + r = kstrtoint(buf, 10, &kcal_cont); + if ((r) || (kcal_cont < 128 || kcal_cont > 383)) + return -EINVAL; + + lut_data->cont = kcal_cont; + + if (mdss_mdp_kcal_is_panel_on()) + mdss_mdp_kcal_update_pa(lut_data); + else + lut_data->queue_changes = true; + + return count; +} + +static ssize_t kcal_cont_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", lut_data->cont); +} + +static DEVICE_ATTR(kcal, S_IWUSR | S_IRUGO, kcal_show, kcal_store); +static DEVICE_ATTR(kcal_min, S_IWUSR | S_IRUGO, kcal_min_show, kcal_min_store); +static DEVICE_ATTR(kcal_enable, S_IWUSR | S_IRUGO, kcal_enable_show, + kcal_enable_store); +static DEVICE_ATTR(kcal_invert, S_IWUSR | S_IRUGO, kcal_invert_show, + kcal_invert_store); +static DEVICE_ATTR(kcal_sat, S_IWUSR | S_IRUGO, kcal_sat_show, kcal_sat_store); +static DEVICE_ATTR(kcal_hue, S_IWUSR | S_IRUGO, kcal_hue_show, kcal_hue_store); +static DEVICE_ATTR(kcal_val, S_IWUSR | S_IRUGO, kcal_val_show, kcal_val_store); +static DEVICE_ATTR(kcal_cont, S_IWUSR | S_IRUGO, kcal_cont_show, + kcal_cont_store); + +static int mdss_mdp_kcal_update_queue(struct device *dev) +{ + struct kcal_lut_data *lut_data = dev_get_drvdata(dev); + + if (lut_data->queue_changes) { + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_update_igc(lut_data); + lut_data->queue_changes = false; + } + + return 0; +} + +#if defined(CONFIG_FB) && !defined(CONFIG_MMI_PANEL_NOTIFICATIONS) +static int fb_notifier_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int *blank; + struct fb_event *evdata = data; + struct kcal_lut_data *lut_data = + container_of(nb, struct kcal_lut_data, panel_nb); + + if (evdata && evdata->data && event == FB_EVENT_BLANK) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + mdss_mdp_kcal_update_queue(&lut_data->dev); + } + + return 0; +} +#endif + +static int kcal_ctrl_probe(struct platform_device *pdev) +{ + int ret; + struct kcal_lut_data *lut_data; + + lut_data = devm_kzalloc(&pdev->dev, sizeof(*lut_data), GFP_KERNEL); + if (!lut_data) { + pr_err("%s: failed to allocate memory for lut_data\n", + __func__); + return -ENOMEM; + } + + platform_set_drvdata(pdev, lut_data); + + lut_data->enable = 0x1; + lut_data->red = DEF_PCC; + lut_data->green = DEF_PCC; + lut_data->blue = DEF_PCC; + lut_data->minimum = 0x23; + lut_data->invert = 0x0; + lut_data->hue = 0x0; + lut_data->sat = DEF_PA; + lut_data->val = DEF_PA; + lut_data->cont = DEF_PA; + + lut_data->queue_changes = false; + + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_update_igc(lut_data); + +#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) + lut_data->panel_nb.display_on = mdss_mdp_kcal_update_queue; + lut_data->panel_nb.dev = &pdev->dev; + ret = mmi_panel_register_notifier(&lut_data->panel_nb); + if (ret) { + pr_err("%s: unable to register MMI notifier\n", __func__); + return ret; + } +#elif defined(CONFIG_FB) + lut_data->dev = pdev->dev; + lut_data->panel_nb.notifier_call = fb_notifier_callback; + ret = fb_register_client(&lut_data->panel_nb); + if (ret) { + pr_err("%s: unable to register fb notifier\n", __func__); + return ret; + } +#endif + + ret = device_create_file(&pdev->dev, &dev_attr_kcal); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_min); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_enable); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_invert); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_sat); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_hue); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_val); + ret |= device_create_file(&pdev->dev, &dev_attr_kcal_cont); + if (ret) { + pr_err("%s: unable to create sysfs entries\n", __func__); + goto out_notifier; + } + + return 0; + +out_notifier: +#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) + mmi_panel_unregister_notifier(&lut_data->panel_nb); +#elif defined(CONFIG_FB) + fb_unregister_client(&lut_data->panel_nb); +#endif + return ret; +} + +static int kcal_ctrl_remove(struct platform_device *pdev) +{ + struct kcal_lut_data *lut_data = platform_get_drvdata(pdev); + + device_remove_file(&pdev->dev, &dev_attr_kcal); + device_remove_file(&pdev->dev, &dev_attr_kcal_min); + device_remove_file(&pdev->dev, &dev_attr_kcal_enable); + device_remove_file(&pdev->dev, &dev_attr_kcal_invert); + device_remove_file(&pdev->dev, &dev_attr_kcal_sat); + device_remove_file(&pdev->dev, &dev_attr_kcal_hue); + device_remove_file(&pdev->dev, &dev_attr_kcal_val); + device_remove_file(&pdev->dev, &dev_attr_kcal_cont); + +#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) + mmi_panel_unregister_notifier(&lut_data->panel_nb); +#elif defined(CONFIG_FB) + fb_unregister_client(&lut_data->panel_nb); +#endif + + return 0; +} + +static struct platform_driver kcal_ctrl_driver = { + .probe = kcal_ctrl_probe, + .remove = kcal_ctrl_remove, + .driver = { + .name = "kcal_ctrl", + }, +}; + +static struct platform_device kcal_ctrl_device = { + .name = "kcal_ctrl", +}; + +static int __init kcal_ctrl_init(void) +{ + if (platform_driver_register(&kcal_ctrl_driver)) + return -ENODEV; + + if (platform_device_register(&kcal_ctrl_device)) + return -ENODEV; + + pr_info("%s: registered\n", __func__); + + return 0; +} + +static void __exit kcal_ctrl_exit(void) +{ + platform_device_unregister(&kcal_ctrl_device); + platform_driver_unregister(&kcal_ctrl_driver); +} + +late_initcall(kcal_ctrl_init); +module_exit(kcal_ctrl_exit); diff --git a/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c b/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c index 42deaa9d4811..f641fefed7fb 100644 --- a/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c +++ b/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c @@ -657,9 +657,14 @@ static int pp_pcc_cache_params_v1_7(struct mdp_pcc_cfg_data *config, (void *) v17_cache_data; if (copy_from_user(&v17_usr_config, config->cfg_payload, sizeof(v17_usr_config))) { +#ifdef CONFIG_FB_MSM_MDSS_KCAL_CTRL + memcpy(&v17_usr_config, config->cfg_payload, sizeof(v17_usr_config)); + ret = 0; +#else pr_err("failed to copy v17 pcc\n"); ret = -EFAULT; goto pcc_config_exit; +#endif } if ((config->ops & MDP_PP_OPS_DISABLE)) { pr_debug("disable pcc\n"); @@ -1152,9 +1157,15 @@ static int pp_pa_cache_params_v1_7(struct mdp_pa_v2_cfg_data *config, if (copy_from_user(&pa_usr_config, config->cfg_payload, sizeof(pa_usr_config))) { +#ifdef CONFIG_FB_MSM_MDSS_KCAL_CTRL + pr_err("%s Failed to copy v1_7 PA - copying in kernel \n",__func__); + memcpy(&pa_usr_config, config->cfg_payload, sizeof(pa_usr_config)); + ret = 0; +#else pr_err("Failed to copy v1_7 PA\n"); ret = -EFAULT; goto pa_config_exit; +#endif } if ((config->flags & MDP_PP_OPS_DISABLE)) { From 4f2354040403d6d246780c44d8f9c75047200c62 Mon Sep 17 00:00:00 2001 From: andip71 Date: Thu, 8 Oct 2015 09:33:42 +0200 Subject: [PATCH 056/203] leds-qpnp: Notification LED control - V1 SysFS interface : * /sys/class/leds/red/device/led_fade (rw) 0 : blink 1 : fade (default) * /sys/class/leds/red/device/led_intensity (rw) 0 : stock intensity 1-100 : 0% to 100% of stock intensity Note: Does only work for static led, not fading/blinking !!! * /sys/class/leds/red/device/led_speed (rw) 0 : stock speed 1 : continuous notification light 2-12 : 2 = very slow to 20 = very fast by andip71 (aka Lord Boeffla) Signed-off-by: engstk --- drivers/leds/leds-qpnp.c | 204 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 3 deletions(-) diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index 888b1180b981..980082d0fb38 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +// #define DEBUG + #include #include #include @@ -250,6 +252,84 @@ #define NUM_KPDBL_LEDS 4 #define KPDBL_MASTER_BIT_INDEX 0 +#define LED_SPEED_MAX 20 +#define LED_SPEED_STOCK_MODE 0 +#define LED_SPEED_CONT_MODE 1 +#define LED_INTENSITY_MAX 100 +#define LED_INTENSITY_STOCK 0 + +#define LED_CUSTOM_PAUSE_HI 1400 +#define LED_CUSTOM_PAUSE_LO 2000 +#define LED_CUSTOM_RAMP_STEP 90 + + +int led_enable_fade = 1; // default is fading +int led_intensity = 0; // default is stock intensity +int led_speed = 0; // default is stock speed + +u32 convert_pause_hi_store (u32 value) +{ + pr_debug("Boeffla-LED: pause_hi orig = %d\n", value); + + // calculate new pause time if speed is not set to stock + if (led_speed != LED_SPEED_STOCK_MODE) + value = LED_CUSTOM_PAUSE_HI / led_speed; + + pr_debug("Boeffla-LED: pause_hi new = %d\n", value); + return value; +} + +u32 convert_pause_lo_store (u32 value) +{ + pr_debug("Boeffla-LED: pause_lo orig = %d\n", value); + + // calculate new pause time if speed is not set to stock + if (led_speed != LED_SPEED_STOCK_MODE) + value = LED_CUSTOM_PAUSE_LO / led_speed; + + pr_debug("Boeffla-LED: pause_lo new = %d\n", value); + return value; +} + +u32 convert_ramp_ms_store (u32 ramp_step_ms) +{ + pr_debug("Boeffla-LED: ramp_step_ms orig = %d\n", ramp_step_ms); + + // no fading = disable ramp times + if (led_enable_fade == 0) + return 1; + + // speed is set to stock = take roms ramp times + if (led_speed == LED_SPEED_STOCK_MODE) + return ramp_step_ms; + + // calculate new ramp time + ramp_step_ms = LED_CUSTOM_RAMP_STEP / led_speed; + + pr_debug("Boeffla-LED: ramp_step_ms new = %d\n", ramp_step_ms); + return ramp_step_ms; +} + +int convert_brightness (int brightness) +{ + pr_debug("Boeffla-LED: brightness orig = %d\n", brightness); + + // 0 value is stock + if (led_intensity == LED_INTENSITY_STOCK) + return brightness; + + // 1 value is switch off in any case + if (led_intensity == 1) + return 0; + + // calculate dimmed value + brightness = (brightness * led_intensity) / LED_INTENSITY_MAX; + + pr_debug("Boeffla-LED: brightness new = %d\n", brightness); + return brightness; +} + + /** * enum qpnp_leds - QPNP supported led ids * @QPNP_ID_WLED - White led backlight @@ -907,6 +987,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) /*config pwm for brightness scaling*/ period_us = led->mpp_cfg->pwm_cfg->pwm_period_us; if (period_us > INT_MAX / NSEC_PER_USEC) { + duty_us = (period_us * led->cdev.brightness) / LED_FULL; rc = pwm_config_us( @@ -914,6 +995,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) duty_us, period_us); } else { + duty_ns = ((period_us * NSEC_PER_USEC) / LED_FULL) * led->cdev.brightness; rc = pwm_config( @@ -931,6 +1013,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) if (led->mpp_cfg->pwm_mode != MANUAL_MODE) pwm_enable(led->mpp_cfg->pwm_cfg->pwm_dev); else { + if (led->cdev.brightness < LED_MPP_CURRENT_MIN) led->cdev.brightness = LED_MPP_CURRENT_MIN; else { @@ -1810,7 +1893,9 @@ static void qpnp_led_set(struct led_classdev *led_cdev, if (value > led->cdev.max_brightness) value = led->cdev.max_brightness; - led->cdev.brightness = value; + // led->cdev.brightness = value; + led->cdev.brightness = convert_brightness(value); + if (led->in_order_command_processing) queue_work(led->workqueue, &led->work); else @@ -2234,11 +2319,13 @@ static ssize_t pwm_us_store(struct device *dev, pwm_cfg->pwm_period_us = previous_pwm_us; pwm_free(pwm_cfg->pwm_dev); qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); + qpnp_led_set(&led->cdev, led->cdev.brightness); dev_err(&led->spmi_dev->dev, "Failed to initialize pwm with new pwm_us value\n"); return ret; } + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2259,6 +2346,8 @@ static ssize_t pause_lo_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); + pause_lo = convert_pause_lo_store(pause_lo); + switch (led->id) { case QPNP_ID_LED_MPP: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2289,11 +2378,13 @@ static ssize_t pause_lo_store(struct device *dev, pwm_cfg->lut_params.lut_pause_lo = previous_pause_lo; pwm_free(pwm_cfg->pwm_dev); qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); + qpnp_led_set(&led->cdev, led->cdev.brightness); dev_err(&led->spmi_dev->dev, "Failed to initialize pwm with new pause lo value\n"); return ret; } + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2314,6 +2405,8 @@ static ssize_t pause_hi_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); + pause_hi = convert_pause_hi_store(pause_hi); + switch (led->id) { case QPNP_ID_LED_MPP: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2349,6 +2442,7 @@ static ssize_t pause_hi_store(struct device *dev, "Failed to initialize pwm with new pause hi value\n"); return ret; } + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2405,6 +2499,7 @@ static ssize_t start_idx_store(struct device *dev, "Failed to initialize pwm with new start idx value\n"); return ret; } + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2425,6 +2520,8 @@ static ssize_t ramp_step_ms_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); + ramp_step_ms = convert_ramp_ms_store(ramp_step_ms); + switch (led->id) { case QPNP_ID_LED_MPP: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2460,6 +2557,7 @@ static ssize_t ramp_step_ms_store(struct device *dev, "Failed to initialize pwm with new ramp step value\n"); return ret; } + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2515,6 +2613,7 @@ static ssize_t lut_flags_store(struct device *dev, "Failed to initialize pwm with new lut flags value\n"); return ret; } + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2600,6 +2699,7 @@ static ssize_t duty_pcts_store(struct device *dev, if (ret) goto restore; + qpnp_led_set(&led->cdev, led->cdev.brightness); return count; @@ -2612,6 +2712,7 @@ static ssize_t duty_pcts_store(struct device *dev, pwm_cfg->lut_params.idx_len = pwm_cfg->duty_cycles->num_duty_pcts; pwm_free(pwm_cfg->pwm_dev); qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); + qpnp_led_set(&led->cdev, led->cdev.brightness); return ret; } @@ -2625,6 +2726,7 @@ static void led_blink(struct qpnp_led_data *led, mutex_lock(&led->lock); if (pwm_cfg->use_blink) { if (led->cdev.brightness) { + pwm_cfg->blinking = true; if (led->id == QPNP_ID_LED_MPP) led->mpp_cfg->pwm_mode = LPG_MODE; @@ -2632,6 +2734,7 @@ static void led_blink(struct qpnp_led_data *led, led->kpdbl_cfg->pwm_mode = LPG_MODE; pwm_cfg->mode = LPG_MODE; } else { + pwm_cfg->blinking = false; pwm_cfg->mode = pwm_cfg->default_mode; if (led->id == QPNP_ID_LED_MPP) @@ -2644,6 +2747,7 @@ static void led_blink(struct qpnp_led_data *led, qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); if (led->id == QPNP_ID_RGB_RED || led->id == QPNP_ID_RGB_GREEN || led->id == QPNP_ID_RGB_BLUE) { + rc = qpnp_rgb_set(led); if (rc < 0) dev_err(&led->spmi_dev->dev, @@ -2685,7 +2789,16 @@ static ssize_t blink_store(struct device *dev, case QPNP_ID_RGB_RED: case QPNP_ID_RGB_GREEN: case QPNP_ID_RGB_BLUE: - led_blink(led, led->rgb_cfg->pwm_cfg); + if (led_speed != LED_SPEED_CONT_MODE) + led_blink(led, led->rgb_cfg->pwm_cfg); + else + { + led->cdev.brightness = convert_brightness(led->cdev.max_brightness); + if (led->in_order_command_processing) + queue_work(led->workqueue, &led->work); + else + schedule_work(&led->work); + } break; case QPNP_ID_KPDBL: led_blink(led, led->kpdbl_cfg->pwm_cfg); @@ -2697,6 +2810,86 @@ static ssize_t blink_store(struct device *dev, return count; } +static ssize_t show_led_fade(struct device *dev, + struct device_attribute *attr, char *buf) +{ + switch(led_enable_fade) + { + case 0: + return sprintf(buf, "%d - off\n", led_enable_fade); + case 1: + return sprintf(buf, "%d - on\n", led_enable_fade); + default: + return sprintf(buf, "%d - undefined\n", led_enable_fade); + } +} + +static ssize_t store_led_fade(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int enabled = -1; /* default to not set a new value */ + + sscanf(buf, "%d", &enabled); + + switch(enabled) /* Accept only if 0 or 1 */ + { + case 0: + case 1: + led_enable_fade = enabled; + default: + return count; + } +} + +static ssize_t show_led_intensity(struct device *dev, + struct device_attribute *attr, char *buf) +{ + switch(led_intensity) + { + case 0: + return sprintf(buf, "%d - Stock intensity\n", led_intensity); + default: + return sprintf(buf, "%d - Custom intensity\n", led_intensity); + } +} + +static ssize_t store_led_intensity(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int new_intensity = -1; /* default to not set a new value */ + + sscanf(buf, "%d", &new_intensity); + + /* check for valid data */ + if (new_intensity >= 0 && new_intensity <= LED_INTENSITY_MAX) + led_intensity = new_intensity; + + return count; +} + +static ssize_t show_led_speed(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d - speed\n", led_speed); +} + +static ssize_t store_led_speed(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int new_led_speed = -1; /* default to not set a new value */ + + sscanf(buf, "%d", &new_led_speed); + + /* check for valid data */ + if ((new_led_speed >= 0) && (new_led_speed <= LED_SPEED_MAX)) + led_speed = new_led_speed; + + return count; +} + static DEVICE_ATTR(led_mode, 0664, NULL, led_mode_store); static DEVICE_ATTR(strobe, 0664, NULL, led_strobe_type_store); static DEVICE_ATTR(pwm_us, 0664, NULL, pwm_us_store); @@ -2707,6 +2900,9 @@ static DEVICE_ATTR(ramp_step_ms, 0664, NULL, ramp_step_ms_store); static DEVICE_ATTR(lut_flags, 0664, NULL, lut_flags_store); static DEVICE_ATTR(duty_pcts, 0664, NULL, duty_pcts_store); static DEVICE_ATTR(blink, 0664, NULL, blink_store); +static DEVICE_ATTR(led_fade, S_IWUSR | S_IRUGO, show_led_fade, store_led_fade); +static DEVICE_ATTR(led_intensity, S_IWUSR | S_IRUGO, show_led_intensity, store_led_intensity); +static DEVICE_ATTR(led_speed, S_IWUSR | S_IRUGO, show_led_speed, store_led_speed); static struct attribute *led_attrs[] = { &dev_attr_led_mode.attr, @@ -2730,7 +2926,9 @@ static struct attribute *lpg_attrs[] = { &dev_attr_ramp_step_ms.attr, &dev_attr_lut_flags.attr, &dev_attr_duty_pcts.attr, - NULL + &dev_attr_led_fade.attr, + &dev_attr_led_intensity.attr, + &dev_attr_led_speed.attr, NULL }; static struct attribute *blink_attrs[] = { From df9e4294645f3d9cd2103749e898508a5cd29d0e Mon Sep 17 00:00:00 2001 From: andip71 Date: Mon, 30 Nov 2015 06:26:57 +0100 Subject: [PATCH 057/203] leds-qpnp: Notification LED control - V1.1 Fix issue with touch key button backlight Signed-off-by: engstk --- drivers/leds/leds-qpnp.c | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index 980082d0fb38..af15241b59dc 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -310,6 +310,14 @@ u32 convert_ramp_ms_store (u32 ramp_step_ms) return ramp_step_ms; } +int check_for_notification_led(struct led_classdev *led_cdev) +{ + if (strcmp(led_cdev->name, "button-backlight") == 0) + return 0; + + return 1; +} + int convert_brightness (int brightness) { pr_debug("Boeffla-LED: brightness orig = %d\n", brightness); @@ -987,7 +995,6 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) /*config pwm for brightness scaling*/ period_us = led->mpp_cfg->pwm_cfg->pwm_period_us; if (period_us > INT_MAX / NSEC_PER_USEC) { - duty_us = (period_us * led->cdev.brightness) / LED_FULL; rc = pwm_config_us( @@ -995,7 +1002,6 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) duty_us, period_us); } else { - duty_ns = ((period_us * NSEC_PER_USEC) / LED_FULL) * led->cdev.brightness; rc = pwm_config( @@ -1013,7 +1019,6 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) if (led->mpp_cfg->pwm_mode != MANUAL_MODE) pwm_enable(led->mpp_cfg->pwm_cfg->pwm_dev); else { - if (led->cdev.brightness < LED_MPP_CURRENT_MIN) led->cdev.brightness = LED_MPP_CURRENT_MIN; else { @@ -1893,8 +1898,10 @@ static void qpnp_led_set(struct led_classdev *led_cdev, if (value > led->cdev.max_brightness) value = led->cdev.max_brightness; - // led->cdev.brightness = value; - led->cdev.brightness = convert_brightness(value); + if (check_for_notification_led(led_cdev)) + led->cdev.brightness = convert_brightness(value); + else + led->cdev.brightness = value; if (led->in_order_command_processing) queue_work(led->workqueue, &led->work); @@ -2319,13 +2326,11 @@ static ssize_t pwm_us_store(struct device *dev, pwm_cfg->pwm_period_us = previous_pwm_us; pwm_free(pwm_cfg->pwm_dev); qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); - qpnp_led_set(&led->cdev, led->cdev.brightness); dev_err(&led->spmi_dev->dev, "Failed to initialize pwm with new pwm_us value\n"); return ret; } - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2378,13 +2383,11 @@ static ssize_t pause_lo_store(struct device *dev, pwm_cfg->lut_params.lut_pause_lo = previous_pause_lo; pwm_free(pwm_cfg->pwm_dev); qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); - qpnp_led_set(&led->cdev, led->cdev.brightness); dev_err(&led->spmi_dev->dev, "Failed to initialize pwm with new pause lo value\n"); return ret; } - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2405,7 +2408,8 @@ static ssize_t pause_hi_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); - pause_hi = convert_pause_hi_store(pause_hi); + if (check_for_notification_led(led_cdev)) + pause_hi = convert_pause_hi_store(pause_hi); switch (led->id) { case QPNP_ID_LED_MPP: @@ -2442,7 +2446,6 @@ static ssize_t pause_hi_store(struct device *dev, "Failed to initialize pwm with new pause hi value\n"); return ret; } - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2499,7 +2502,6 @@ static ssize_t start_idx_store(struct device *dev, "Failed to initialize pwm with new start idx value\n"); return ret; } - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2520,7 +2522,8 @@ static ssize_t ramp_step_ms_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); - ramp_step_ms = convert_ramp_ms_store(ramp_step_ms); + if (check_for_notification_led(led_cdev)) + ramp_step_ms = convert_ramp_ms_store(ramp_step_ms); switch (led->id) { case QPNP_ID_LED_MPP: @@ -2557,7 +2560,6 @@ static ssize_t ramp_step_ms_store(struct device *dev, "Failed to initialize pwm with new ramp step value\n"); return ret; } - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2613,7 +2615,6 @@ static ssize_t lut_flags_store(struct device *dev, "Failed to initialize pwm with new lut flags value\n"); return ret; } - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; } @@ -2699,7 +2700,6 @@ static ssize_t duty_pcts_store(struct device *dev, if (ret) goto restore; - qpnp_led_set(&led->cdev, led->cdev.brightness); return count; @@ -2712,7 +2712,6 @@ static ssize_t duty_pcts_store(struct device *dev, pwm_cfg->lut_params.idx_len = pwm_cfg->duty_cycles->num_duty_pcts; pwm_free(pwm_cfg->pwm_dev); qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); - qpnp_led_set(&led->cdev, led->cdev.brightness); return ret; } @@ -2726,7 +2725,6 @@ static void led_blink(struct qpnp_led_data *led, mutex_lock(&led->lock); if (pwm_cfg->use_blink) { if (led->cdev.brightness) { - pwm_cfg->blinking = true; if (led->id == QPNP_ID_LED_MPP) led->mpp_cfg->pwm_mode = LPG_MODE; @@ -2734,7 +2732,6 @@ static void led_blink(struct qpnp_led_data *led, led->kpdbl_cfg->pwm_mode = LPG_MODE; pwm_cfg->mode = LPG_MODE; } else { - pwm_cfg->blinking = false; pwm_cfg->mode = pwm_cfg->default_mode; if (led->id == QPNP_ID_LED_MPP) @@ -2747,7 +2744,6 @@ static void led_blink(struct qpnp_led_data *led, qpnp_pwm_init(pwm_cfg, led->spmi_dev, led->cdev.name); if (led->id == QPNP_ID_RGB_RED || led->id == QPNP_ID_RGB_GREEN || led->id == QPNP_ID_RGB_BLUE) { - rc = qpnp_rgb_set(led); if (rc < 0) dev_err(&led->spmi_dev->dev, @@ -2789,16 +2785,22 @@ static ssize_t blink_store(struct device *dev, case QPNP_ID_RGB_RED: case QPNP_ID_RGB_GREEN: case QPNP_ID_RGB_BLUE: - if (led_speed != LED_SPEED_CONT_MODE) - led_blink(led, led->rgb_cfg->pwm_cfg); - else + if (check_for_notification_led(led_cdev)) { - led->cdev.brightness = convert_brightness(led->cdev.max_brightness); - if (led->in_order_command_processing) - queue_work(led->workqueue, &led->work); + if (led_speed != LED_SPEED_CONT_MODE) + led_blink(led, led->rgb_cfg->pwm_cfg); else - schedule_work(&led->work); + { + led->cdev.brightness = convert_brightness(led->cdev.max_brightness); + if (led->in_order_command_processing) + queue_work(led->workqueue, &led->work); + else + schedule_work(&led->work); + } } + else + led_blink(led, led->rgb_cfg->pwm_cfg); + break; case QPNP_ID_KPDBL: led_blink(led, led->kpdbl_cfg->pwm_cfg); From 048bb1c2e147a1c8ff531d00c743766c632369d0 Mon Sep 17 00:00:00 2001 From: andip71 Date: Fri, 26 Feb 2016 06:11:34 +0100 Subject: [PATCH 058/203] leds-qpnp: fix torch light and potential other LEDs being affected by notification LED control Signed-off-by: engstk --- drivers/leds/leds-qpnp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index af15241b59dc..ba2f1d64bd7a 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -312,10 +312,12 @@ u32 convert_ramp_ms_store (u32 ramp_step_ms) int check_for_notification_led(struct led_classdev *led_cdev) { - if (strcmp(led_cdev->name, "button-backlight") == 0) - return 0; + if ((strcmp(led_cdev->name, "red") == 0) || + (strcmp(led_cdev->name, "green") == 0) || + (strcmp(led_cdev->name, "blue") == 0)) + return 1; - return 1; + return 0; } int convert_brightness (int brightness) From 17a80eefd5b5289f9ca727f1b4b1944f7df03671 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 17 Jul 2016 20:02:07 -0400 Subject: [PATCH 059/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index f633e1503b26..fb9cb71f5a40 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.07" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.08" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -2710,6 +2710,7 @@ CONFIG_FB_MSM_MDSS_HDMI_PANEL=y # CONFIG_FB_MSM_MDSS_EDP_PANEL is not set # CONFIG_FB_MSM_MDSS_MDP3 is not set # CONFIG_FB_MSM_MDSS_XLOG_DEBUG is not set +CONFIG_FB_MSM_MDSS_KCAL_CTRL=y # CONFIG_FB_SSD1307 is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y From 53f6c02ccca20d1dc2a6f4f7a27b508efc8ba69c Mon Sep 17 00:00:00 2001 From: flar2 Date: Wed, 20 Jul 2016 11:06:31 -0400 Subject: [PATCH 060/203] xpad: latest upstream version --- drivers/input/joystick/xpad.c | 974 +++++++++++++++++++++++----------- 1 file changed, 675 insertions(+), 299 deletions(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index fc55f0d15b70..2f6d50f477c0 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -31,12 +31,14 @@ * - the iForce driver drivers/char/joystick/iforce.c * - the skeleton-driver drivers/usb/usb-skeleton.c * - Xbox 360 information http://www.free60.org/wiki/Gamepad + * - Xbox One information https://github.com/quantus/xbox-one-controller-protocol * * Thanks to: * - ITO Takayuki for providing essential xpad information on his website * - Vojtech Pavlik - iforce driver / input subsystem * - Greg Kroah-Hartman - usb-skeleton driver * - XBOX Linux project - extra USB id's + * - Pekka Pöyry (quantus) - Xbox One controller reverse engineering * * TODO: * - fine tune axes (especially trigger axes) @@ -74,15 +76,18 @@ */ #include +#include +#include #include #include #include #include +#include #define DRIVER_AUTHOR "Marko Friedemann " #define DRIVER_DESC "X-Box pad driver" -#define XPAD_PKT_LEN 32 +#define XPAD_PKT_LEN 64 /* xbox d-pads should map to buttons, as is required for DDR pads but we map them to axes when possible to simplify things */ @@ -123,6 +128,8 @@ static const struct xpad_device { { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, @@ -147,6 +154,7 @@ static const struct xpad_device { { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4740, "Mad Catz Beat Pad", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4a01, "Mad Catz FightStick TE 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2", 0, XTYPE_XBOX360 }, { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, @@ -166,9 +174,11 @@ static const struct xpad_device { { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0139, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, @@ -176,6 +186,7 @@ static const struct xpad_device { { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, @@ -192,6 +203,7 @@ static const struct xpad_device { { 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 }, { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x542a, "Xbox ONE spectra", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, @@ -202,9 +214,11 @@ static const struct xpad_device { { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, - { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x541a, "PowerA Xbox One Mini Wired Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x543a, "PowerA Xbox One wired controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 }, @@ -240,7 +254,6 @@ static const signed short xpad_btn_triggers[] = { -1 }; - static const signed short xpad360_btn[] = { /* buttons for x360 controller */ BTN_TL, BTN_TR, /* Button LB/RB */ BTN_MODE, /* The big X button */ @@ -299,14 +312,18 @@ static struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ + XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ + XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ + XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */ XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */ XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ @@ -315,24 +332,42 @@ static struct usb_device_id xpad_table[] = { MODULE_DEVICE_TABLE(usb, xpad_table); +struct xpad_output_packet { + u8 data[XPAD_PKT_LEN]; + u8 len; + bool pending; +}; + +#define XPAD_OUT_CMD_IDX 0 +#define XPAD_OUT_FF_IDX 1 +#define XPAD_OUT_LED_IDX (1 + IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF)) +#define XPAD_NUM_OUT_PACKETS (1 + \ + IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF) + \ + IS_ENABLED(CONFIG_JOYSTICK_XPAD_LEDS)) + struct usb_xpad { struct input_dev *dev; /* input device interface */ + struct input_dev __rcu *x360w_dev; struct usb_device *udev; /* usb device */ struct usb_interface *intf; /* usb interface */ - int pad_present; + bool pad_present; + bool input_created; struct urb *irq_in; /* urb for interrupt in report */ unsigned char *idata; /* input data */ dma_addr_t idata_dma; - struct urb *bulk_out; - unsigned char *bdata; - struct urb *irq_out; /* urb for interrupt out report */ + struct usb_anchor irq_out_anchor; + bool irq_out_active; /* we must not use an active URB */ + u8 odata_serial; /* serial number for xbox one protocol */ unsigned char *odata; /* output data */ dma_addr_t odata_dma; - struct mutex odata_mutex; + spinlock_t odata_lock; + + struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS]; + int last_out_packet; #if defined(CONFIG_JOYSTICK_XPAD_LEDS) struct xpad_led *led; @@ -342,8 +377,14 @@ struct usb_xpad { int mapping; /* map d-pad to buttons or to axes */ int xtype; /* type of xbox device */ + int pad_nr; /* the order x360 pads were attached */ + const char *name; /* name of the device */ + struct work_struct work; /* init/remove device from callback */ }; +static int xpad_init_input(struct usb_xpad *xpad); +static void xpad_deinit_input(struct usb_xpad *xpad); + /* * xpad_process_packet * @@ -353,7 +394,6 @@ struct usb_xpad { * The used report descriptor was taken from ITO Takayukis website: * http://euc.jp/periphs/xbox-controller.ja.html */ - static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { struct input_dev *dev = xpad->dev; @@ -424,10 +464,12 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d * http://www.free60.org/wiki/Gamepad */ -static void xpad360_process_packet(struct usb_xpad *xpad, +static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev, u16 cmd, unsigned char *data) { - struct input_dev *dev = xpad->dev; + /* valid pad data */ + if (data[0] != 0x00) + return; /* digital pad */ if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { @@ -436,7 +478,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08); input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01); input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02); - } else { + } + + /* + * This should be a simple else block. However historically + * xbox360w has mapped DPAD to buttons while xbox360 did not. This + * made no sense, but now we can not just switch back and have to + * support both behaviors. + */ + if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) || + xpad->xtype == XTYPE_XBOX360W) { input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); input_report_abs(dev, ABS_HAT0Y, @@ -486,6 +537,31 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_sync(dev); } +static void xpad_presence_work(struct work_struct *work) +{ + struct usb_xpad *xpad = container_of(work, struct usb_xpad, work); + int error; + + if (xpad->pad_present) { + error = xpad_init_input(xpad); + if (error) { + /* complain only, not much else we can do here */ + dev_err(&xpad->dev->dev, + "unable to init device: %d\n", error); + } else { + rcu_assign_pointer(xpad->x360w_dev, xpad->dev); + } + } else { + RCU_INIT_POINTER(xpad->x360w_dev, NULL); + synchronize_rcu(); + /* + * Now that we are sure xpad360w_process_packet is not + * using input device we can get rid of it. + */ + xpad_deinit_input(xpad); + } +} + /* * xpad360w_process_packet * @@ -500,23 +576,30 @@ static void xpad360_process_packet(struct usb_xpad *xpad, * 01.1 - Pad state (Bytes 4+) valid * */ - static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { + struct input_dev *dev; + bool present; + /* Presence change */ if (data[0] & 0x08) { - if (data[1] & 0x80) { - xpad->pad_present = 1; - usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); - } else - xpad->pad_present = 0; + present = (data[1] & 0x80) != 0; + + if (xpad->pad_present != present) { + xpad->pad_present = present; + schedule_work(&xpad->work); + } } /* Valid pad data */ - if (!(data[1] & 0x1)) + if (data[1] != 0x1) return; - xpad360_process_packet(xpad, cmd, &data[4]); + rcu_read_lock(); + dev = rcu_dereference(xpad->x360w_dev); + if (dev) + xpad360_process_packet(xpad, dev, cmd, &data[4]); + rcu_read_unlock(); } /* @@ -645,7 +728,7 @@ static void xpad_irq_in(struct urb *urb) switch (xpad->xtype) { case XTYPE_XBOX360: - xpad360_process_packet(xpad, 0, xpad->idata); + xpad360_process_packet(xpad, xpad->dev, 0, xpad->idata); break; case XTYPE_XBOX360W: xpad360w_process_packet(xpad, 0, xpad->idata); @@ -664,40 +747,73 @@ static void xpad_irq_in(struct urb *urb) __func__, retval); } -static void xpad_bulk_out(struct urb *urb) +/* Callers must hold xpad->odata_lock spinlock */ +static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad) { - struct usb_xpad *xpad = urb->context; - struct device *dev = &xpad->intf->dev; + struct xpad_output_packet *pkt, *packet = NULL; + int i; + + for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) { + if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS) + xpad->last_out_packet = 0; + + pkt = &xpad->out_packets[xpad->last_out_packet]; + if (pkt->pending) { + dev_dbg(&xpad->intf->dev, + "%s - found pending output packet %d\n", + __func__, xpad->last_out_packet); + packet = pkt; + break; + } + } - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dev_dbg(dev, "%s - urb shutting down with status: %d\n", - __func__, urb->status); - break; - default: - dev_dbg(dev, "%s - nonzero urb status received: %d\n", - __func__, urb->status); + if (packet) { + memcpy(xpad->odata, packet->data, packet->len); + xpad->irq_out->transfer_buffer_length = packet->len; + packet->pending = false; + return true; } + + return false; +} + +/* Callers must hold xpad->odata_lock spinlock */ +static int xpad_try_sending_next_out_packet(struct usb_xpad *xpad) +{ + int error; + + if (!xpad->irq_out_active && xpad_prepare_next_out_packet(xpad)) { + usb_anchor_urb(xpad->irq_out, &xpad->irq_out_anchor); + error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC); + if (error) { + dev_err(&xpad->intf->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, error); + usb_unanchor_urb(xpad->irq_out); + return -EIO; + } + + xpad->irq_out_active = true; + } + + return 0; } static void xpad_irq_out(struct urb *urb) { struct usb_xpad *xpad = urb->context; struct device *dev = &xpad->intf->dev; - int retval, status; + int status = urb->status; + int error; + unsigned long flags; - status = urb->status; + spin_lock_irqsave(&xpad->odata_lock, flags); switch (status) { case 0: /* success */ - return; + xpad->irq_out_active = xpad_prepare_next_out_packet(xpad); + break; case -ECONNRESET: case -ENOENT: @@ -705,19 +821,28 @@ static void xpad_irq_out(struct urb *urb) /* this urb is terminated, clean up */ dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); - return; + xpad->irq_out_active = false; + break; default: dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); - goto exit; + break; } -exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "%s - usb_submit_urb failed with result %d\n", - __func__, retval); + if (xpad->irq_out_active) { + usb_anchor_urb(urb, &xpad->irq_out_anchor); + error = usb_submit_urb(urb, GFP_ATOMIC); + if (error) { + dev_err(dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, error); + usb_unanchor_urb(urb); + xpad->irq_out_active = false; + } + } + + spin_unlock_irqrestore(&xpad->odata_lock, flags); } static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) @@ -729,6 +854,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) if (xpad->xtype == XTYPE_UNKNOWN) return 0; + init_usb_anchor(&xpad->irq_out_anchor); + xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, GFP_KERNEL, &xpad->odata_dma); if (!xpad->odata) { @@ -736,7 +863,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) goto fail1; } - mutex_init(&xpad->odata_mutex); + spin_lock_init(&xpad->odata_lock); xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); if (!xpad->irq_out) { @@ -763,8 +890,14 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) static void xpad_stop_output(struct usb_xpad *xpad) { - if (xpad->xtype != XTYPE_UNKNOWN) - usb_kill_urb(xpad->irq_out); + if (xpad->xtype != XTYPE_UNKNOWN) { + if (!usb_wait_anchor_empty_timeout(&xpad->irq_out_anchor, + 5000)) { + dev_warn(&xpad->intf->dev, + "timed out waiting for output URB to complete, killing\n"); + usb_kill_anchored_urbs(&xpad->irq_out_anchor); + } + } } static void xpad_deinit_output(struct usb_xpad *xpad) @@ -776,72 +909,162 @@ static void xpad_deinit_output(struct usb_xpad *xpad) } } +static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) +{ + struct xpad_output_packet *packet = + &xpad->out_packets[XPAD_OUT_CMD_IDX]; + unsigned long flags; + int retval; + + spin_lock_irqsave(&xpad->odata_lock, flags); + + packet->data[0] = 0x08; + packet->data[1] = 0x00; + packet->data[2] = 0x0F; + packet->data[3] = 0xC0; + packet->data[4] = 0x00; + packet->data[5] = 0x00; + packet->data[6] = 0x00; + packet->data[7] = 0x00; + packet->data[8] = 0x00; + packet->data[9] = 0x00; + packet->data[10] = 0x00; + packet->data[11] = 0x00; + packet->len = 12; + packet->pending = true; + + /* Reset the sequence so we send out presence first */ + xpad->last_out_packet = -1; + retval = xpad_try_sending_next_out_packet(xpad); + + spin_unlock_irqrestore(&xpad->odata_lock, flags); + + return retval; +} + +static int xpad_start_xbox_one(struct usb_xpad *xpad) +{ + struct xpad_output_packet *packet = + &xpad->out_packets[XPAD_OUT_CMD_IDX]; + unsigned long flags; + int retval; + + spin_lock_irqsave(&xpad->odata_lock, flags); + + /* Xbox one controller needs to be initialized. */ + packet->data[0] = 0x05; + packet->data[1] = 0x20; + packet->data[2] = xpad->odata_serial++; /* packet serial */ + packet->data[3] = 0x01; /* rumble bit enable? */ + packet->data[4] = 0x00; + packet->len = 5; + packet->pending = true; + + /* Reset the sequence so we send out start packet first */ + xpad->last_out_packet = -1; + retval = xpad_try_sending_next_out_packet(xpad); + + spin_unlock_irqrestore(&xpad->odata_lock, flags); + + return retval; +} + #ifdef CONFIG_JOYSTICK_XPAD_FF static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { struct usb_xpad *xpad = input_get_drvdata(dev); + struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_FF_IDX]; + __u16 strong; + __u16 weak; + int retval; + unsigned long flags; - if (effect->type == FF_RUMBLE) { - __u16 strong = effect->u.rumble.strong_magnitude; - __u16 weak = effect->u.rumble.weak_magnitude; - - switch (xpad->xtype) { - - case XTYPE_XBOX: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x06; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; /* left actuator */ - xpad->odata[4] = 0x00; - xpad->odata[5] = weak / 256; /* right actuator */ - xpad->irq_out->transfer_buffer_length = 6; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOX360: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x08; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; /* left actuator? */ - xpad->odata[4] = weak / 256; /* right actuator? */ - xpad->odata[5] = 0x00; - xpad->odata[6] = 0x00; - xpad->odata[7] = 0x00; - xpad->irq_out->transfer_buffer_length = 8; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOX360W: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x01; - xpad->odata[2] = 0x0F; - xpad->odata[3] = 0xC0; - xpad->odata[4] = 0x00; - xpad->odata[5] = strong / 256; - xpad->odata[6] = weak / 256; - xpad->odata[7] = 0x00; - xpad->odata[8] = 0x00; - xpad->odata[9] = 0x00; - xpad->odata[10] = 0x00; - xpad->odata[11] = 0x00; - xpad->irq_out->transfer_buffer_length = 12; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - default: - dev_dbg(&xpad->dev->dev, - "%s - rumble command sent to unsupported xpad type: %d\n", - __func__, xpad->xtype); - return -1; - } + if (effect->type != FF_RUMBLE) + return 0; + + strong = effect->u.rumble.strong_magnitude; + weak = effect->u.rumble.weak_magnitude; + + spin_lock_irqsave(&xpad->odata_lock, flags); + + switch (xpad->xtype) { + case XTYPE_XBOX: + packet->data[0] = 0x00; + packet->data[1] = 0x06; + packet->data[2] = 0x00; + packet->data[3] = strong / 256; /* left actuator */ + packet->data[4] = 0x00; + packet->data[5] = weak / 256; /* right actuator */ + packet->len = 6; + packet->pending = true; + break; + + case XTYPE_XBOX360: + packet->data[0] = 0x00; + packet->data[1] = 0x08; + packet->data[2] = 0x00; + packet->data[3] = strong / 256; /* left actuator? */ + packet->data[4] = weak / 256; /* right actuator? */ + packet->data[5] = 0x00; + packet->data[6] = 0x00; + packet->data[7] = 0x00; + packet->len = 8; + packet->pending = true; + break; + + case XTYPE_XBOX360W: + packet->data[0] = 0x00; + packet->data[1] = 0x01; + packet->data[2] = 0x0F; + packet->data[3] = 0xC0; + packet->data[4] = 0x00; + packet->data[5] = strong / 256; + packet->data[6] = weak / 256; + packet->data[7] = 0x00; + packet->data[8] = 0x00; + packet->data[9] = 0x00; + packet->data[10] = 0x00; + packet->data[11] = 0x00; + packet->len = 12; + packet->pending = true; + break; + + case XTYPE_XBOXONE: + packet->data[0] = 0x09; /* activate rumble */ + packet->data[1] = 0x00; + packet->data[2] = xpad->odata_serial++; + packet->data[3] = 0x09; + packet->data[4] = 0x00; + packet->data[5] = 0x0F; + packet->data[6] = 0x00; + packet->data[7] = 0x00; + packet->data[8] = strong / 512; /* left actuator */ + packet->data[9] = weak / 512; /* right actuator */ + packet->data[10] = 0xFF; + packet->data[11] = 0x00; + packet->data[12] = 0x00; + packet->len = 13; + packet->pending = true; + break; + + default: + dev_dbg(&xpad->dev->dev, + "%s - rumble command sent to unsupported xpad type: %d\n", + __func__, xpad->xtype); + retval = -EINVAL; + goto out; } - return 0; + retval = xpad_try_sending_next_out_packet(xpad); + +out: + spin_unlock_irqrestore(&xpad->odata_lock, flags); + return retval; } static int xpad_init_ff(struct usb_xpad *xpad) { - if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE) + if (xpad->xtype == XTYPE_UNKNOWN) return 0; input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); @@ -855,6 +1078,9 @@ static int xpad_init_ff(struct usb_xpad *xpad) { return 0; } #if defined(CONFIG_JOYSTICK_XPAD_LEDS) #include +#include + +static DEFINE_IDA(xpad_pad_seq); struct xpad_led { char name[16]; @@ -862,17 +1088,75 @@ struct xpad_led { struct usb_xpad *xpad; }; +/** + * set the LEDs on Xbox360 / Wireless Controllers + * @param command + * 0: off + * 1: all blink, then previous setting + * 2: 1/top-left blink, then on + * 3: 2/top-right blink, then on + * 4: 3/bottom-left blink, then on + * 5: 4/bottom-right blink, then on + * 6: 1/top-left on + * 7: 2/top-right on + * 8: 3/bottom-left on + * 9: 4/bottom-right on + * 10: rotate + * 11: blink, based on previous setting + * 12: slow blink, based on previous setting + * 13: rotate with two lights + * 14: persistent slow all blink + * 15: blink once, then previous setting + */ static void xpad_send_led_command(struct usb_xpad *xpad, int command) { - if (command >= 0 && command < 14) { - mutex_lock(&xpad->odata_mutex); - xpad->odata[0] = 0x01; - xpad->odata[1] = 0x03; - xpad->odata[2] = command; - xpad->irq_out->transfer_buffer_length = 3; - usb_submit_urb(xpad->irq_out, GFP_KERNEL); - mutex_unlock(&xpad->odata_mutex); + struct xpad_output_packet *packet = + &xpad->out_packets[XPAD_OUT_LED_IDX]; + unsigned long flags; + + command %= 16; + + spin_lock_irqsave(&xpad->odata_lock, flags); + + switch (xpad->xtype) { + case XTYPE_XBOX360: + packet->data[0] = 0x01; + packet->data[1] = 0x03; + packet->data[2] = command; + packet->len = 3; + packet->pending = true; + break; + + case XTYPE_XBOX360W: + packet->data[0] = 0x00; + packet->data[1] = 0x00; + packet->data[2] = 0x08; + packet->data[3] = 0x40 + command; + packet->data[4] = 0x00; + packet->data[5] = 0x00; + packet->data[6] = 0x00; + packet->data[7] = 0x00; + packet->data[8] = 0x00; + packet->data[9] = 0x00; + packet->data[10] = 0x00; + packet->data[11] = 0x00; + packet->len = 12; + packet->pending = true; + break; } + + xpad_try_sending_next_out_packet(xpad); + + spin_unlock_irqrestore(&xpad->odata_lock, flags); +} + +/* + * Light up the segment corresponding to the pad number on + * Xbox 360 Controllers. + */ +static void xpad_identify_controller(struct usb_xpad *xpad) +{ + led_set_brightness(&xpad->led->led_cdev, (xpad->pad_nr % 4) + 2); } static void xpad_led_set(struct led_classdev *led_cdev, @@ -886,22 +1170,24 @@ static void xpad_led_set(struct led_classdev *led_cdev, static int xpad_led_probe(struct usb_xpad *xpad) { - static atomic_t led_seq = ATOMIC_INIT(0); - long led_no; struct xpad_led *led; struct led_classdev *led_cdev; int error; - if (xpad->xtype != XTYPE_XBOX360) + if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) return 0; xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); if (!led) return -ENOMEM; - led_no = (long)atomic_inc_return(&led_seq) - 1; + xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL); + if (xpad->pad_nr < 0) { + error = xpad->pad_nr; + goto err_free_mem; + } - snprintf(led->name, sizeof(led->name), "xpad%ld", led_no); + snprintf(led->name, sizeof(led->name), "xpad%d", xpad->pad_nr); led->xpad = xpad; led_cdev = &led->led_cdev; @@ -909,18 +1195,19 @@ static int xpad_led_probe(struct usb_xpad *xpad) led_cdev->brightness_set = xpad_led_set; error = led_classdev_register(&xpad->udev->dev, led_cdev); - if (error) { - kfree(led); - xpad->led = NULL; - return error; - } + if (error) + goto err_free_id; - /* - * Light up the segment corresponding to controller number - */ - xpad_send_led_command(xpad, (led_no % 4) + 2); + xpad_identify_controller(xpad); return 0; + +err_free_id: + ida_simple_remove(&xpad_pad_seq, xpad->pad_nr); +err_free_mem: + kfree(led); + xpad->led = NULL; + return error; } static void xpad_led_disconnect(struct usb_xpad *xpad) @@ -929,6 +1216,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) if (xpad_led) { led_classdev_unregister(&xpad_led->led_cdev); + ida_simple_remove(&xpad_pad_seq, xpad->pad_nr); kfree(xpad_led); } } @@ -937,38 +1225,73 @@ static int xpad_led_probe(struct usb_xpad *xpad) { return 0; } static void xpad_led_disconnect(struct usb_xpad *xpad) { } #endif - -static int xpad_open(struct input_dev *dev) +static int xpad_start_input(struct usb_xpad *xpad) { - struct usb_xpad *xpad = input_get_drvdata(dev); - - /* URB was submitted in probe */ - if (xpad->xtype == XTYPE_XBOX360W) - return 0; + int error; - xpad->irq_in->dev = xpad->udev; if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) return -EIO; if (xpad->xtype == XTYPE_XBOXONE) { - /* Xbox one controller needs to be initialized. */ - xpad->odata[0] = 0x05; - xpad->odata[1] = 0x20; - xpad->irq_out->transfer_buffer_length = 2; - return usb_submit_urb(xpad->irq_out, GFP_KERNEL); + error = xpad_start_xbox_one(xpad); + if (error) { + usb_kill_urb(xpad->irq_in); + return error; + } } return 0; } -static void xpad_close(struct input_dev *dev) +static void xpad_stop_input(struct usb_xpad *xpad) { - struct usb_xpad *xpad = input_get_drvdata(dev); + usb_kill_urb(xpad->irq_in); +} + +static int xpad360w_start_input(struct usb_xpad *xpad) +{ + int error; + + error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); + if (error) + return -EIO; - if (xpad->xtype != XTYPE_XBOX360W) + /* + * Send presence packet. + * This will force the controller to resend connection packets. + * This is useful in the case we activate the module after the + * adapter has been plugged in, as it won't automatically + * send us info about the controllers. + */ + error = xpad_inquiry_pad_presence(xpad); + if (error) { usb_kill_urb(xpad->irq_in); + return error; + } - xpad_stop_output(xpad); + return 0; +} + +static void xpad360w_stop_input(struct usb_xpad *xpad) +{ + usb_kill_urb(xpad->irq_in); + + /* Make sure we are done with presence work if it was scheduled */ + flush_work(&xpad->work); +} + +static int xpad_open(struct input_dev *dev) +{ + struct usb_xpad *xpad = input_get_drvdata(dev); + + return xpad_start_input(xpad); +} + +static void xpad_close(struct input_dev *dev) +{ + struct usb_xpad *xpad = input_get_drvdata(dev); + + xpad_stop_input(xpad); } static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) @@ -997,91 +1320,41 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) } } -static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) +static void xpad_deinit_input(struct usb_xpad *xpad) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_xpad *xpad; - struct input_dev *input_dev; - struct usb_endpoint_descriptor *ep_irq_in; - int ep_irq_in_idx; - int i, error; - - for (i = 0; xpad_device[i].idVendor; i++) { - if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && - (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) - break; + if (xpad->input_created) { + xpad->input_created = false; + xpad_led_disconnect(xpad); + input_unregister_device(xpad->dev); } +} - if (xpad_device[i].xtype == XTYPE_XBOXONE && - intf->cur_altsetting->desc.bInterfaceNumber != 0) { - /* - * The Xbox One controller lists three interfaces all with the - * same interface class, subclass and protocol. Differentiate by - * interface number. - */ - return -ENODEV; - } +static int xpad_init_input(struct usb_xpad *xpad) +{ + struct input_dev *input_dev; + int i, error; - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); input_dev = input_allocate_device(); - if (!xpad || !input_dev) { - error = -ENOMEM; - goto fail1; - } - - xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->idata_dma); - if (!xpad->idata) { - error = -ENOMEM; - goto fail1; - } - - xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->irq_in) { - error = -ENOMEM; - goto fail2; - } - - xpad->udev = udev; - xpad->intf = intf; - xpad->mapping = xpad_device[i].mapping; - xpad->xtype = xpad_device[i].xtype; - - if (xpad->xtype == XTYPE_UNKNOWN) { - if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { - if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) - xpad->xtype = XTYPE_XBOX360W; - else - xpad->xtype = XTYPE_XBOX360; - } else - xpad->xtype = XTYPE_XBOX; - - if (dpad_to_buttons) - xpad->mapping |= MAP_DPAD_TO_BUTTONS; - if (triggers_to_buttons) - xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; - if (sticks_to_null) - xpad->mapping |= MAP_STICKS_TO_NULL; - } + if (!input_dev) + return -ENOMEM; xpad->dev = input_dev; - usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); - strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); - - input_dev->name = xpad_device[i].name; + input_dev->name = xpad->name; input_dev->phys = xpad->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; + usb_to_input_id(xpad->udev, &input_dev->id); + input_dev->dev.parent = &xpad->intf->dev; input_set_drvdata(input_dev, xpad); - input_dev->open = xpad_open; - input_dev->close = xpad_close; + if (xpad->xtype != XTYPE_XBOX360W) { + input_dev->open = xpad_open; + input_dev->close = xpad_close; + } - input_dev->evbit[0] = BIT_MASK(EV_KEY); + __set_bit(EV_KEY, input_dev->evbit); if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { - input_dev->evbit[0] |= BIT_MASK(EV_ABS); + __set_bit(EV_ABS, input_dev->evbit); /* set up axes */ for (i = 0; xpad_abs[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs[i]); @@ -1104,7 +1377,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { for (i = 0; xpad_btn_pad[i] >= 0; i++) __set_bit(xpad_btn_pad[i], input_dev->keybit); - } else { + } + + /* + * This should be a simple else block. However historically + * xbox360w has mapped DPAD to buttons while xbox360 did not. This + * made no sense, but now we can not just switch back and have to + * support both behaviors. + */ + if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) || + xpad->xtype == XTYPE_XBOX360W) { for (i = 0; xpad_abs_pad[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs_pad[i]); } @@ -1117,17 +1399,108 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); } - error = xpad_init_output(intf, xpad); - if (error) - goto fail3; - error = xpad_init_ff(xpad); if (error) - goto fail4; + goto err_free_input; error = xpad_led_probe(xpad); if (error) - goto fail5; + goto err_destroy_ff; + + error = input_register_device(xpad->dev); + if (error) + goto err_disconnect_led; + + xpad->input_created = true; + return 0; + +err_disconnect_led: + xpad_led_disconnect(xpad); +err_destroy_ff: + input_ff_destroy(input_dev); +err_free_input: + input_free_device(input_dev); + return error; +} + +static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_xpad *xpad; + struct usb_endpoint_descriptor *ep_irq_in; + int ep_irq_in_idx; + int i, error; + + if (intf->cur_altsetting->desc.bNumEndpoints != 2) + return -ENODEV; + + for (i = 0; xpad_device[i].idVendor; i++) { + if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && + (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) + break; + } + + xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); + if (!xpad) + return -ENOMEM; + + usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); + strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); + + xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->idata_dma); + if (!xpad->idata) { + error = -ENOMEM; + goto err_free_mem; + } + + xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); + if (!xpad->irq_in) { + error = -ENOMEM; + goto err_free_idata; + } + + xpad->udev = udev; + xpad->intf = intf; + xpad->mapping = xpad_device[i].mapping; + xpad->xtype = xpad_device[i].xtype; + xpad->name = xpad_device[i].name; + INIT_WORK(&xpad->work, xpad_presence_work); + + if (xpad->xtype == XTYPE_UNKNOWN) { + if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { + if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) + xpad->xtype = XTYPE_XBOX360W; + else if (intf->cur_altsetting->desc.bInterfaceProtocol == 208) + xpad->xtype = XTYPE_XBOXONE; + else + xpad->xtype = XTYPE_XBOX360; + } else { + xpad->xtype = XTYPE_XBOX; + } + + if (dpad_to_buttons) + xpad->mapping |= MAP_DPAD_TO_BUTTONS; + if (triggers_to_buttons) + xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; + if (sticks_to_null) + xpad->mapping |= MAP_STICKS_TO_NULL; + } + + if (xpad->xtype == XTYPE_XBOXONE && + intf->cur_altsetting->desc.bInterfaceNumber != 0) { + /* + * The Xbox One controller lists three interfaces all with the + * same interface class, subclass and protocol. Differentiate by + * interface number. + */ + error = -ENODEV; + goto err_free_in_urb; + } + + error = xpad_init_output(intf, xpad); + if (error) + goto err_free_in_urb; /* Xbox One controller has in/out endpoints swapped. */ ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0; @@ -1140,59 +1513,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - error = input_register_device(xpad->dev); - if (error) - goto fail6; - usb_set_intfdata(intf, xpad); if (xpad->xtype == XTYPE_XBOX360W) { - /* - * Setup the message to set the LEDs on the - * controller when it shows up - */ - xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->bulk_out) { - error = -ENOMEM; - goto fail7; - } - - xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); - if (!xpad->bdata) { - error = -ENOMEM; - goto fail8; - } - - xpad->bdata[2] = 0x08; - switch (intf->cur_altsetting->desc.bInterfaceNumber) { - case 0: - xpad->bdata[3] = 0x42; - break; - case 2: - xpad->bdata[3] = 0x43; - break; - case 4: - xpad->bdata[3] = 0x44; - break; - case 6: - xpad->bdata[3] = 0x45; - } - - ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; - if (usb_endpoint_is_bulk_out(ep_irq_in)) { - usb_fill_bulk_urb(xpad->bulk_out, udev, - usb_sndbulkpipe(udev, - ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, - xpad_bulk_out, xpad); - } else { - usb_fill_int_urb(xpad->bulk_out, udev, - usb_sndintpipe(udev, - ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, - xpad_bulk_out, xpad, 0); - } - /* * Submit the int URB immediately rather than waiting for open * because we get status messages from the device whether @@ -1200,58 +1523,110 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id * exactly the message that a controller has arrived that * we're waiting for. */ - xpad->irq_in->dev = xpad->udev; - error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); + error = xpad360w_start_input(xpad); if (error) - goto fail9; + goto err_deinit_output; + /* + * Wireless controllers require RESET_RESUME to work properly + * after suspend. Ideally this quirk should be in usb core + * quirk list, but we have too many vendors producing these + * controllers and we'd need to maintain 2 identical lists + * here in this driver and in usb core. + */ + udev->quirks |= USB_QUIRK_RESET_RESUME; + } else { + error = xpad_init_input(xpad); + if (error) + goto err_deinit_output; } - return 0; - fail9: kfree(xpad->bdata); - fail8: usb_free_urb(xpad->bulk_out); - fail7: input_unregister_device(input_dev); - input_dev = NULL; - fail6: xpad_led_disconnect(xpad); - fail5: if (input_dev) - input_ff_destroy(input_dev); - fail4: xpad_deinit_output(xpad); - fail3: usb_free_urb(xpad->irq_in); - fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - fail1: input_free_device(input_dev); +err_deinit_output: + xpad_deinit_output(xpad); +err_free_in_urb: + usb_free_urb(xpad->irq_in); +err_free_idata: + usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); +err_free_mem: kfree(xpad); return error; - } static void xpad_disconnect(struct usb_interface *intf) { - struct usb_xpad *xpad = usb_get_intfdata (intf); + struct usb_xpad *xpad = usb_get_intfdata(intf); - xpad_led_disconnect(xpad); - input_unregister_device(xpad->dev); - xpad_deinit_output(xpad); + if (xpad->xtype == XTYPE_XBOX360W) + xpad360w_stop_input(xpad); - if (xpad->xtype == XTYPE_XBOX360W) { - usb_kill_urb(xpad->bulk_out); - usb_free_urb(xpad->bulk_out); - usb_kill_urb(xpad->irq_in); - } + xpad_deinit_input(xpad); + + /* + * Now that both input device and LED device are gone we can + * stop output URB. + */ + xpad_stop_output(xpad); + + xpad_deinit_output(xpad); usb_free_urb(xpad->irq_in); usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - kfree(xpad->bdata); kfree(xpad); usb_set_intfdata(intf, NULL); } +static int xpad_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + struct input_dev *input = xpad->dev; + + if (xpad->xtype == XTYPE_XBOX360W) { + /* + * Wireless controllers always listen to input so + * they are notified when controller shows up + * or goes away. + */ + xpad360w_stop_input(xpad); + } else { + mutex_lock(&input->mutex); + if (input->users) + xpad_stop_input(xpad); + mutex_unlock(&input->mutex); + } + + xpad_stop_output(xpad); + + return 0; +} + +static int xpad_resume(struct usb_interface *intf) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + struct input_dev *input = xpad->dev; + int retval = 0; + + if (xpad->xtype == XTYPE_XBOX360W) { + retval = xpad360w_start_input(xpad); + } else { + mutex_lock(&input->mutex); + if (input->users) + retval = xpad_start_input(xpad); + mutex_unlock(&input->mutex); + } + + return retval; +} + static struct usb_driver xpad_driver = { .name = "xpad", .probe = xpad_probe, .disconnect = xpad_disconnect, + .suspend = xpad_suspend, + .resume = xpad_resume, + .reset_resume = xpad_resume, .id_table = xpad_table, }; @@ -1260,3 +1635,4 @@ module_usb_driver(xpad_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + From 19d403ccfa54231b9864d01fac7266c6042ef0aa Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 20 Jul 2016 12:48:01 -0700 Subject: [PATCH 061/203] qpnp-haptic: Dejank the haptics * Remove OEM patch which actually makes the jank worse * Add mutexes and call hap_set without the workqueue for direct mode Change-Id: I98f5b8ddea572def2706ad2cfa18f9dd460757ed --- drivers/platform/msm/qpnp-haptic.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index fa3642036dc7..b13850e8ceac 100755 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -293,6 +293,7 @@ struct qpnp_hap { struct qpnp_pwm_info pwm_info; struct mutex lock; struct mutex wf_lock; + struct mutex set_lock; struct completion completion; enum qpnp_hap_mode play_mode; enum qpnp_hap_auto_res_mode auto_res_mode; @@ -334,8 +335,6 @@ struct qpnp_hap { static struct qpnp_hap *ghap; -static struct workqueue_struct *vibqueue; -/* helper to read a pmic register */ /* helper to read a pmic register */ static int qpnp_hap_read_reg(struct qpnp_hap *hap, u8 *data, u16 addr) { @@ -1526,6 +1525,8 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) u8 val = 0; unsigned long timeout_ns = POLL_TIME_AUTO_RES_ERR_NS; + mutex_lock(&hap->set_lock); + if (hap->play_mode == QPNP_HAP_PWM) { if (on) rc = pwm_enable(hap->pwm_info.pwm_dev); @@ -1539,8 +1540,10 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) qpnp_hap_auto_res_enable(hap, 0); rc = qpnp_hap_mod_enable(hap, on); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&hap->set_lock); return rc; + } rc = qpnp_hap_play(hap, on); @@ -1551,8 +1554,10 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) (AUTO_RES_ENABLE_TIMEOUT + 1)); rc = qpnp_hap_auto_res_enable(hap, 1); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&hap->set_lock); return rc; + } } if (hap->correct_lra_drive_freq) { /* @@ -1567,8 +1572,10 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) } } else { rc = qpnp_hap_play(hap, on); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&hap->set_lock); return rc; + } if (hap->correct_lra_drive_freq) { rc = qpnp_hap_read_reg(hap, &val, @@ -1586,6 +1593,7 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) } } + mutex_unlock(&hap->set_lock); return rc; } @@ -1594,6 +1602,7 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) { struct qpnp_hap *hap = container_of(dev, struct qpnp_hap, timed_dev); + flush_work(&hap->work); mutex_lock(&hap->lock); @@ -1623,9 +1632,11 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value) ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL); } - queue_work(vibqueue,&hap->work); - msleep(1); mutex_unlock(&hap->lock); + if (hap->play_mode == QPNP_HAP_DIRECT) + qpnp_hap_set(hap, hap->state); + else + schedule_work(&hap->work); } void set_vibrate(int value) @@ -2280,8 +2291,7 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) mutex_init(&hap->lock); mutex_init(&hap->wf_lock); - - vibqueue = create_singlethread_workqueue("vibthread"); + mutex_init(&hap->set_lock); INIT_WORK(&hap->work, qpnp_hap_worker); INIT_DELAYED_WORK(&hap->sc_work, qpnp_handle_sc_irq); From 69f1e1029aea5ed60d6f95449217f63efde12b6d Mon Sep 17 00:00:00 2001 From: flar2 Date: Thu, 28 Jul 2016 19:26:30 -0400 Subject: [PATCH 062/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index fb9cb71f5a40..25fa37185adf 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.08" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.09" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -365,11 +365,11 @@ CONFIG_ARCH_NR_GPIO=1024 # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_PREEMPT_COUNT=y -CONFIG_HZ_100=y +# CONFIG_HZ_100 is not set # CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set +CONFIG_HZ_300=y # CONFIG_HZ_1000 is not set -CONFIG_HZ=100 +CONFIG_HZ=300 CONFIG_SCHED_HRTICK=y CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -2115,6 +2115,7 @@ CONFIG_SMB1351_USB_CHARGER=y CONFIG_QPNP_SMBCHARGER=y CONFIG_QPNP_FG=y CONFIG_FG_BQ27541=y +CONFIG_ONEPLUS_FASTCHG=y CONFIG_BATTERY_BCL=y # CONFIG_QPNP_VM_BMS is not set # CONFIG_QPNP_BMS is not set From 2b232d2096b68efc76c38097a3e7c5a6179e8611 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 5 Aug 2016 01:11:18 -0400 Subject: [PATCH 063/203] sweep2sleep: don't create input device For some reason this breaks multirom. Use existing pnp-power-on device instead. --- drivers/input/touchscreen/sweep2sleep.c | 28 +++++-------------------- drivers/platform/msm/qpnp-power-on.c | 9 ++++++++ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/input/touchscreen/sweep2sleep.c b/drivers/input/touchscreen/sweep2sleep.c index c7105d69d8c7..35a8395f8a26 100644 --- a/drivers/input/touchscreen/sweep2sleep.c +++ b/drivers/input/touchscreen/sweep2sleep.c @@ -37,6 +37,11 @@ static struct workqueue_struct *s2s_input_wq; static struct work_struct s2s_input_work; static int vib_strength = VIB_STRENGTH; +void sweep2sleep_setdev(struct input_dev * input_device) { + sweep2sleep_pwrdev = input_device; + return; +} + /* PowerKey work func */ static void sweep2sleep_presspwr(struct work_struct * sweep2sleep_presspwr_work) { @@ -293,23 +298,6 @@ static int __init sweep2sleep_init(void) { int rc = 0; - sweep2sleep_pwrdev = input_allocate_device(); - if (!sweep2sleep_pwrdev) { - pr_err("Failed to allocate sweep2sleep_pwrdev\n"); - goto err_alloc_dev; - } - - input_set_capability(sweep2sleep_pwrdev, EV_KEY, KEY_POWER); - - sweep2sleep_pwrdev->name = "s2s_pwrkey"; - sweep2sleep_pwrdev->phys = "s2s_pwrkey/input0"; - - rc = input_register_device(sweep2sleep_pwrdev); - if (rc) { - pr_err("%s: input_register_device err=%d\n", __func__, rc); - goto err_input_dev; - } - s2s_input_wq = create_workqueue("s2s_iwq"); if (!s2s_input_wq) { pr_err("%s: Failed to create workqueue\n", __func__); @@ -334,12 +322,6 @@ static int __init sweep2sleep_init(void) if (rc) pr_err("%s: sysfs_create_file failed for vib_strength\n", __func__); -err_input_dev: - input_free_device(sweep2sleep_pwrdev); - -err_alloc_dev: - pr_info("%s done\n", __func__); - return 0; } diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c index cc11164991c0..4c555b723fa7 100644 --- a/drivers/platform/msm/qpnp-power-on.c +++ b/drivers/platform/msm/qpnp-power-on.c @@ -156,6 +156,10 @@ #define QPNP_POFF_REASON_UVLO 13 +#ifdef CONFIG_SWEEP2SLEEP +extern void sweep2sleep_setdev(struct input_dev * input_device); +#endif + enum qpnp_pon_version { QPNP_PON_GEN1_V1, QPNP_PON_GEN1_V2, @@ -1566,6 +1570,11 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon) "Can't register pon key: %d\n", rc); goto free_input_dev; } +#ifdef CONFIG_SWEEP2SLEEP + else { + sweep2sleep_setdev(pon->pon_input); + } +#endif } for (i = 0; i < pon->num_pon_config; i++) { From 863fc2528f41c6938d0d9a22cee79f4ba6d099f4 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 5 Aug 2016 01:23:13 -0400 Subject: [PATCH 064/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 25fa37185adf..e8ad8fc138bc 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.09" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.10" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 1ae896956188fe5c40a5192727147e5d74c63629 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 13 Aug 2016 18:43:33 -0400 Subject: [PATCH 065/203] ASoC: wcd9335: Sound control Add left and right headphone gain control --- sound/soc/codecs/Kconfig | 4 +++ sound/soc/codecs/wcd9335.c | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0d2c24b6dcea..61ad178485cf 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -863,4 +863,8 @@ config SND_SOC_MSM_HDMI_CODEC_RX config SND_SOC_MSM_HDMI_DBA_CODEC_RX bool "HDMI DBA Audio Playback" depends on MSM_DBA + +config SOUND_CONTROL + bool "Sound control for wcd9335" + endmenu diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 96a7cbb46b6d..ea808a4c627c 100755 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -12504,6 +12504,57 @@ static struct regulator *tasha_codec_find_ondemand_regulator( return NULL; } +#ifdef CONFIG_SOUND_CONTROL +struct snd_soc_codec *sound_control_codec_ptr; + +static ssize_t headphone_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d %d\n", + snd_soc_read(sound_control_codec_ptr, WCD9335_CDC_RX1_RX_VOL_CTL), + snd_soc_read(sound_control_codec_ptr, WCD9335_CDC_RX2_RX_VOL_CTL) + ); +} + +static ssize_t headphone_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + + int input_l, input_r; + + sscanf(buf, "%d %d", &input_l, &input_r); + + if (input_l < -10 || input_l > 20) + input_l = 0; + + if (input_r < -10 || input_r > 20) + input_r = 0; + + snd_soc_write(sound_control_codec_ptr, WCD9335_CDC_RX1_RX_VOL_MIX_CTL, input_l); + snd_soc_write(sound_control_codec_ptr, WCD9335_CDC_RX2_RX_VOL_MIX_CTL, input_r); + snd_soc_write(sound_control_codec_ptr, WCD9335_CDC_RX1_RX_VOL_CTL, input_l); + snd_soc_write(sound_control_codec_ptr, WCD9335_CDC_RX2_RX_VOL_CTL, input_r); + + return count; +} + +static struct kobj_attribute headphone_gain_attribute = + __ATTR(headphone_gain, 0664, + headphone_gain_show, + headphone_gain_store); + +static struct attribute *sound_control_attrs[] = { + &headphone_gain_attribute.attr, + NULL, +}; + +static struct attribute_group sound_control_attr_group = { + .attrs = sound_control_attrs, +}; + +static struct kobject *sound_control_kobj; +#endif + static int tasha_codec_probe(struct snd_soc_codec *codec) { struct wcd9xxx *control; @@ -12514,6 +12565,9 @@ static int tasha_codec_probe(struct snd_soc_codec *codec) void *ptr = NULL; struct regulator *supply; +#ifdef CONFIG_SOUND_CONTROL + sound_control_codec_ptr = codec; +#endif control = dev_get_drvdata(codec->dev->parent); dev_info(codec->dev, "%s()\n", __func__); @@ -13226,6 +13280,18 @@ static int tasha_probe(struct platform_device *pdev) tasha_get_codec_ver(tasha); +#ifdef CONFIG_SOUND_CONTROL + sound_control_kobj = kobject_create_and_add("sound_control", kernel_kobj); + if (sound_control_kobj == NULL) { + pr_warn("%s kobject create failed!\n", __func__); + } + + ret = sysfs_create_group(sound_control_kobj, &sound_control_attr_group); + if (ret) { + pr_warn("%s sysfs file create failed!\n", __func__); + } +#endif + return ret; resmgr_remove: From 68d14d6ed69c56615ff144ea7a0562b7abcd21b3 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 13 Aug 2016 18:49:11 -0400 Subject: [PATCH 066/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index e8ad8fc138bc..5addea209e95 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.10" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.11" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -2942,6 +2942,7 @@ CONFIG_SND_SOC_WCD_MBHC=y # CONFIG_SND_SOC_TPA6130A2 is not set CONFIG_SND_SOC_MSM_STUB=y CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=y +CONFIG_SOUND_CONTROL=y # CONFIG_SND_SIMPLE_CARD is not set # CONFIG_SOUND_PRIME is not set From 994a64960d79f9f25379b68c7a88d8d4b275792c Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Mon, 22 Feb 2016 16:30:40 -0700 Subject: [PATCH 067/203] net: ipc_router: Bind only a client port as control port IPC Router binds any port as a control port and moves it from the client port list to control port list. Misbehaving clients can exploit this incorrect behavior. IPC Router to check if the port is a client port before binding it as a control port. CRs-Fixed: 974577 Change-Id: I9f189b76967d5f85750218a7cb6537d187a69663 Signed-off-by: Karthikeyan Ramasubramanian --- net/ipc_router/ipc_router_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 99486e9ac703..3100ebde7021 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -3532,7 +3532,7 @@ int msm_ipc_router_get_curr_pkt_size(struct msm_ipc_port *port_ptr) int msm_ipc_router_bind_control_port(struct msm_ipc_port *port_ptr) { - if (!port_ptr) + if (unlikely(!port_ptr || port_ptr->type != CLIENT_PORT)) return -EINVAL; down_write(&local_ports_lock_lhc2); From fae38267a2a3c4ed73b188b0c9976c2bb188c2b4 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 20 Aug 2016 16:17:34 -0400 Subject: [PATCH 068/203] ASoC: wcd9335: add mic gain and speaker gain for OnePlus3 --- sound/soc/codecs/wcd9335.c | 73 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index ea808a4c627c..f2142de1dabb 100755 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -12505,7 +12505,7 @@ static struct regulator *tasha_codec_find_ondemand_regulator( } #ifdef CONFIG_SOUND_CONTROL -struct snd_soc_codec *sound_control_codec_ptr; +static struct snd_soc_codec *sound_control_codec_ptr; static ssize_t headphone_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -12524,10 +12524,10 @@ static ssize_t headphone_gain_store(struct kobject *kobj, sscanf(buf, "%d %d", &input_l, &input_r); - if (input_l < -10 || input_l > 20) + if (input_l < -84 || input_l > 20) input_l = 0; - if (input_r < -10 || input_r > 20) + if (input_r < -84 || input_r > 20) input_r = 0; snd_soc_write(sound_control_codec_ptr, WCD9335_CDC_RX1_RX_VOL_MIX_CTL, input_l); @@ -12543,8 +12543,75 @@ static struct kobj_attribute headphone_gain_attribute = headphone_gain_show, headphone_gain_store); +static ssize_t mic_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + snd_soc_read(sound_control_codec_ptr, WCD9335_CDC_RX0_RX_VOL_CTL)); +} + +static ssize_t mic_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int input; + + sscanf(buf, "%d", &input); + + if (input < -10 || input > 20) + input = 0; + + snd_soc_write(sound_control_codec_ptr, WCD9335_CDC_RX0_RX_VOL_CTL, input); + + return count; +} + +static struct kobj_attribute mic_gain_attribute = + __ATTR(mic_gain, 0664, + mic_gain_show, + mic_gain_store); + +struct snd_soc_codec *tfa98xx_codec_ptr; +#include "tfa9890/tfa98xx-regs.h" +#define TO_FIXED(e) e +static ssize_t speaker_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + u16 value; + + value = snd_soc_read(tfa98xx_codec_ptr, TFA98XX_AUDIO_CTR); + value >>= 8; + + return snprintf(buf, PAGE_SIZE, "%d\n", TO_FIXED(value) / -2); +} + +static ssize_t speaker_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int input; + u16 value = 0; + int volume_value; + + sscanf(buf, "%d", &input); + + volume_value = 2 * input; + if (volume_value > 255) + volume_value = 255; + value = (value & 0x00FF) | (u16)(volume_value << 8); + + snd_soc_write(tfa98xx_codec_ptr, TFA98XX_AUDIO_CTR, value); + + return count; +} + +static struct kobj_attribute speaker_gain_attribute = + __ATTR(speaker_gain, 0664, + speaker_gain_show, + speaker_gain_store); + static struct attribute *sound_control_attrs[] = { &headphone_gain_attribute.attr, + &mic_gain_attribute.attr, + &speaker_gain_attribute.attr, NULL, }; From 79f75f73e2ab4deca01d4419da7fab548de0ef58 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 20 Aug 2016 23:57:35 -0400 Subject: [PATCH 069/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 5addea209e95..181a6e595a33 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.11" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.12" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -730,6 +730,7 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y # CONFIG_NETFILTER_XT_MATCH_RATEEST is not set # CONFIG_NETFILTER_XT_MATCH_REALM is not set # CONFIG_NETFILTER_XT_MATCH_RECENT is not set @@ -765,6 +766,7 @@ CONFIG_IP_NF_MATCH_ECN=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_ULOG is not set # CONFIG_IP_NF_TARGET_SYNPROXY is not set CONFIG_IP_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y From bf23155ccfce2f9aa15149f9af8e0f4676c61054 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 21 Aug 2016 12:41:54 -0400 Subject: [PATCH 070/203] ASoC: wcd9335: fix speaker gain controls Somehow I ended up with the unfinished version in my last commit --- sound/soc/codecs/tfa9890/tfa98xx.c | 6 ++++++ sound/soc/codecs/wcd9335.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tfa9890/tfa98xx.c b/sound/soc/codecs/tfa9890/tfa98xx.c index 06c8fbc1cf6c..dcec11d5c083 100644 --- a/sound/soc/codecs/tfa9890/tfa98xx.c +++ b/sound/soc/codecs/tfa9890/tfa98xx.c @@ -787,6 +787,9 @@ static struct snd_soc_dai_driver tfa98xx_dai = { .symmetric_rates = 1, }; +#ifdef CONFIG_SOUND_CONTROL +extern struct snd_soc_codec *tfa98xx_codec_ptr; +#endif static int tfa98xx_probe(struct snd_soc_codec *codec) { struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec); @@ -795,6 +798,9 @@ static int tfa98xx_probe(struct snd_soc_codec *codec) codec->control_data = tfa98xx->regmap; tfa98xx->codec = codec; +#ifdef CONFIG_SOUND_CONTROL + tfa98xx_codec_ptr = codec; +#endif codec->cache_bypass = true; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index f2142de1dabb..a738255c79d1 100755 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -12577,11 +12577,13 @@ static ssize_t speaker_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { u16 value; + s64 vol; value = snd_soc_read(tfa98xx_codec_ptr, TFA98XX_AUDIO_CTR); value >>= 8; + vol = TO_FIXED(value) / -2; - return snprintf(buf, PAGE_SIZE, "%d\n", TO_FIXED(value) / -2); + return snprintf(buf, PAGE_SIZE, "%d\n", (int)vol); } static ssize_t speaker_gain_store(struct kobject *kobj, @@ -12592,7 +12594,10 @@ static ssize_t speaker_gain_store(struct kobject *kobj, int volume_value; sscanf(buf, "%d", &input); + if (input < 0 || input > 127) + input = 0; + value = snd_soc_read(tfa98xx_codec_ptr, TFA98XX_AUDIO_CTR); volume_value = 2 * input; if (volume_value > 255) volume_value = 255; From 49e06ec2697c3d88347018b9a782bfae18d1170c Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 21 Aug 2016 12:43:17 -0400 Subject: [PATCH 071/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 181a6e595a33..b0f08b0a379c 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.12" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.14" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 31cf0e8b11c58ede180ec7829b086345664a77cd Mon Sep 17 00:00:00 2001 From: savoca Date: Sat, 29 Aug 2015 12:19:56 -0700 Subject: [PATCH 072/203] msm: mdss: KCAL: Send a pp display commit when changes are made Sending a PP display commit when changes are made, to prevent waiting on a panel update from some other part of the kernel. Sending a display commit takes care of locking and panel state checking for us. QC MDSS also handles queue-ing already for us, so remove that functionality from KCAL. Signed-off-by: flar2 --- drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c | 155 ++++---------------- 1 file changed, 30 insertions(+), 125 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c index a3b2e3661266..74abe54846b0 100644 --- a/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c +++ b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c @@ -22,15 +22,6 @@ #include #include -#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) && defined(CONFIG_FB) -#include -#include -#include -#elif defined(CONFIG_FB) -#include -#include -#endif - #include "mdss_mdp.h" #define DEF_PCC 0x100 @@ -38,13 +29,6 @@ #define PCC_ADJ 0x80 struct kcal_lut_data { -#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) && defined(CONFIG_FB) - struct mmi_notifier panel_nb; -#elif defined(CONFIG_FB) - struct device dev; - struct notifier_block panel_nb; -#endif - bool queue_changes; int red; int green; int blue; @@ -183,19 +167,24 @@ static int mdss_mdp_kcal_store_fb0_ctl(void) return 0; } -static bool mdss_mdp_kcal_is_panel_on(void) +static int mdss_mdp_kcal_display_commit(void) { int i; + int ret = 0; struct mdss_mdp_ctl *ctl; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); for (i = 0; i < mdata->nctl; i++) { ctl = mdata->ctl_off + i; - if (mdss_mdp_ctl_is_power_on(ctl)) - return true; + /* pp setup requires mfd */ + if ((mdss_mdp_ctl_is_power_on(ctl)) && (ctl->mfd)) { + ret = mdss_mdp_pp_setup(ctl); + if (ret) + pr_err("%s: setup failed: %d\n", __func__, ret); + } } - return false; + return ret; } static void mdss_mdp_kcal_update_pcc(struct kcal_lut_data *lut_data) @@ -338,10 +327,8 @@ static ssize_t kcal_store(struct device *dev, struct device_attribute *attr, lut_data->green = kcal_g; lut_data->blue = kcal_b; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_pcc(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -367,10 +354,8 @@ static ssize_t kcal_min_store(struct device *dev, lut_data->minimum = kcal_min; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_pcc(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -396,12 +381,10 @@ static ssize_t kcal_enable_store(struct device *dev, lut_data->enable = kcal_enable; - if (mdss_mdp_kcal_is_panel_on()) { - mdss_mdp_kcal_update_pcc(lut_data); - mdss_mdp_kcal_update_pa(lut_data); - mdss_mdp_kcal_update_igc(lut_data); - } else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_update_igc(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -427,10 +410,8 @@ static ssize_t kcal_invert_store(struct device *dev, lut_data->invert = kcal_invert; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_igc(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_igc(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -455,10 +436,8 @@ static ssize_t kcal_sat_store(struct device *dev, lut_data->sat = kcal_sat; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_pa(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -483,10 +462,8 @@ static ssize_t kcal_hue_store(struct device *dev, lut_data->hue = kcal_hue; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_pa(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -511,10 +488,8 @@ static ssize_t kcal_val_store(struct device *dev, lut_data->val = kcal_val; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_pa(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -539,10 +514,8 @@ static ssize_t kcal_cont_store(struct device *dev, lut_data->cont = kcal_cont; - if (mdss_mdp_kcal_is_panel_on()) - mdss_mdp_kcal_update_pa(lut_data); - else - lut_data->queue_changes = true; + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); return count; } @@ -567,39 +540,6 @@ static DEVICE_ATTR(kcal_val, S_IWUSR | S_IRUGO, kcal_val_show, kcal_val_store); static DEVICE_ATTR(kcal_cont, S_IWUSR | S_IRUGO, kcal_cont_show, kcal_cont_store); -static int mdss_mdp_kcal_update_queue(struct device *dev) -{ - struct kcal_lut_data *lut_data = dev_get_drvdata(dev); - - if (lut_data->queue_changes) { - mdss_mdp_kcal_update_pcc(lut_data); - mdss_mdp_kcal_update_pa(lut_data); - mdss_mdp_kcal_update_igc(lut_data); - lut_data->queue_changes = false; - } - - return 0; -} - -#if defined(CONFIG_FB) && !defined(CONFIG_MMI_PANEL_NOTIFICATIONS) -static int fb_notifier_callback(struct notifier_block *nb, - unsigned long event, void *data) -{ - int *blank; - struct fb_event *evdata = data; - struct kcal_lut_data *lut_data = - container_of(nb, struct kcal_lut_data, panel_nb); - - if (evdata && evdata->data && event == FB_EVENT_BLANK) { - blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - mdss_mdp_kcal_update_queue(&lut_data->dev); - } - - return 0; -} -#endif - static int kcal_ctrl_probe(struct platform_device *pdev) { int ret; @@ -625,29 +565,10 @@ static int kcal_ctrl_probe(struct platform_device *pdev) lut_data->val = DEF_PA; lut_data->cont = DEF_PA; - lut_data->queue_changes = false; - mdss_mdp_kcal_update_pcc(lut_data); mdss_mdp_kcal_update_pa(lut_data); mdss_mdp_kcal_update_igc(lut_data); - -#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) - lut_data->panel_nb.display_on = mdss_mdp_kcal_update_queue; - lut_data->panel_nb.dev = &pdev->dev; - ret = mmi_panel_register_notifier(&lut_data->panel_nb); - if (ret) { - pr_err("%s: unable to register MMI notifier\n", __func__); - return ret; - } -#elif defined(CONFIG_FB) - lut_data->dev = pdev->dev; - lut_data->panel_nb.notifier_call = fb_notifier_callback; - ret = fb_register_client(&lut_data->panel_nb); - if (ret) { - pr_err("%s: unable to register fb notifier\n", __func__); - return ret; - } -#endif + mdss_mdp_kcal_display_commit(); ret = device_create_file(&pdev->dev, &dev_attr_kcal); ret |= device_create_file(&pdev->dev, &dev_attr_kcal_min); @@ -659,24 +580,14 @@ static int kcal_ctrl_probe(struct platform_device *pdev) ret |= device_create_file(&pdev->dev, &dev_attr_kcal_cont); if (ret) { pr_err("%s: unable to create sysfs entries\n", __func__); - goto out_notifier; + return ret; } return 0; - -out_notifier: -#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) - mmi_panel_unregister_notifier(&lut_data->panel_nb); -#elif defined(CONFIG_FB) - fb_unregister_client(&lut_data->panel_nb); -#endif - return ret; } static int kcal_ctrl_remove(struct platform_device *pdev) { - struct kcal_lut_data *lut_data = platform_get_drvdata(pdev); - device_remove_file(&pdev->dev, &dev_attr_kcal); device_remove_file(&pdev->dev, &dev_attr_kcal_min); device_remove_file(&pdev->dev, &dev_attr_kcal_enable); @@ -686,12 +597,6 @@ static int kcal_ctrl_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_kcal_val); device_remove_file(&pdev->dev, &dev_attr_kcal_cont); -#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS) - mmi_panel_unregister_notifier(&lut_data->panel_nb); -#elif defined(CONFIG_FB) - fb_unregister_client(&lut_data->panel_nb); -#endif - return 0; } @@ -726,5 +631,5 @@ static void __exit kcal_ctrl_exit(void) platform_driver_unregister(&kcal_ctrl_driver); } -late_initcall(kcal_ctrl_init); +module_init(kcal_ctrl_init); module_exit(kcal_ctrl_exit); From f3ee45aef20b7d74bc91bb7c0e997fb68b13cf86 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 26 Aug 2016 00:10:49 -0400 Subject: [PATCH 073/203] ASoC: wcd9335: add analog headphone gain -disable compander and userspace mixer control for headphones -thanks to chdloc from xda for advice and @tbalden for work on this --- sound/soc/codecs/wcd9335.c | 49 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index a738255c79d1..3cacf205fa2f 100755 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -3352,6 +3352,11 @@ static int tasha_set_compander(struct snd_kcontrol *kcontrol, kcontrol->private_value)->shift; int value = ucontrol->value.integer.value[0]; +#ifdef CONFIG_SOUND_CONTROL + if (comp == COMPANDER_1 || comp == COMPANDER_2) + value = 0; +#endif + pr_debug("%s: Compander %d enable current %d, new %d\n", __func__, comp + 1, tasha->comp_enabled[comp], value); tasha->comp_enabled[comp] = value; @@ -8325,12 +8330,12 @@ static const struct soc_enum tasha_ear_pa_gain_enum = static const struct snd_kcontrol_new tasha_analog_gain_controls[] = { SOC_ENUM_EXT("EAR PA Gain", tasha_ear_pa_gain_enum, tasha_ear_pa_gain_get, tasha_ear_pa_gain_put), - +#ifndef CONFIG_SOUND_CONTROL SOC_SINGLE_TLV("HPHL Volume", WCD9335_HPH_L_EN, 0, 20, 1, line_gain), SOC_SINGLE_TLV("HPHR Volume", WCD9335_HPH_R_EN, 0, 20, 1, line_gain), - +#endif SOC_SINGLE_TLV("ADC1 Volume", WCD9335_ANA_AMIC1, 0, 20, 0, analog_gain), SOC_SINGLE_TLV("ADC2 Volume", WCD9335_ANA_AMIC2, 0, 20, 0, @@ -12543,6 +12548,45 @@ static struct kobj_attribute headphone_gain_attribute = headphone_gain_show, headphone_gain_store); +static ssize_t headphone_pa_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + u8 hph_l_gain = snd_soc_read(sound_control_codec_ptr, WCD9335_HPH_L_EN); + u8 hph_r_gain = snd_soc_read(sound_control_codec_ptr, WCD9335_HPH_R_EN); + + return snprintf(buf, PAGE_SIZE, "%d %d\n", + hph_l_gain & 0x1F, hph_r_gain & 0x1F); +} + +static ssize_t headphone_pa_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int input_l, input_r; + struct tasha_priv *tasha = snd_soc_codec_get_drvdata(sound_control_codec_ptr); + + sscanf(buf, "%d %d", &input_l, &input_r); + + if (input_l < 1 || input_l > 20) + input_l = 1; + + if (input_r < 1 || input_r > 20) + input_r = 1; + + snd_soc_update_bits(sound_control_codec_ptr, WCD9335_HPH_L_EN, 0x1f, input_l); + snd_soc_update_bits(sound_control_codec_ptr, WCD9335_HPH_R_EN, 0x1f, input_r); + + tasha->hph_l_gain = input_l; + tasha->hph_r_gain = input_r; + + return count; +} + +static struct kobj_attribute headphone_pa_gain_attribute = + __ATTR(headphone_pa_gain, 0664, + headphone_pa_gain_show, + headphone_pa_gain_store); + + static ssize_t mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -12617,6 +12661,7 @@ static struct attribute *sound_control_attrs[] = { &headphone_gain_attribute.attr, &mic_gain_attribute.attr, &speaker_gain_attribute.attr, + &headphone_pa_gain_attribute.attr, NULL, }; From c1ef9a3a1cad61c44fb6de0817fc8e03e366b526 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 26 Aug 2016 00:12:26 -0400 Subject: [PATCH 074/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index b0f08b0a379c..1db4a9988ee6 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.14" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.15" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From c7b341bd665b17a3543fc791a3efcaafc6c49506 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 4 Sep 2016 19:35:41 -0400 Subject: [PATCH 075/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 1db4a9988ee6..c62061e041e1 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.15" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.16" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -569,8 +569,29 @@ CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_INET_UDP_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +CONFIG_TCP_CONG_HSTCP=y +CONFIG_TCP_CONG_HYBLA=y +CONFIG_TCP_CONG_VEGAS=y +CONFIG_TCP_CONG_SCALABLE=y +CONFIG_TCP_CONG_LP=y +CONFIG_TCP_CONG_VENO=y +CONFIG_TCP_CONG_YEAH=y +CONFIG_TCP_CONG_ILLINOIS=y +CONFIG_TCP_CONG_DCTCP=y +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_HYBLA is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_VENO is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_DCTCP is not set +# CONFIG_DEFAULT_RENO is not set CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y From 93b8ba3d826bf11a384b870643a26337c52db9f9 Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Sat, 16 Jul 2016 21:43:16 -0700 Subject: [PATCH 076/203] input: synaptics: s1302: Stop keypad when touchscreen is in use When the user's finger is on the touchscreen, don't process any keypad button presses, as an unintended button press will cause poor UX. Register an input handler to check when there are fingers on the touchscreen (via BTN_TOOL_FINGER) to disable/enable the keypad accordingly. Signed-off-by: Sultanxda Signed-off-by: flar2 --- .../touchscreen/synaptics_driver_s1302.c | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/synaptics_driver_s1302.c b/drivers/input/touchscreen/synaptics_driver_s1302.c index 3d1341d1ca9e..034a409f4e73 100755 --- a/drivers/input/touchscreen/synaptics_driver_s1302.c +++ b/drivers/input/touchscreen/synaptics_driver_s1302.c @@ -294,6 +294,8 @@ struct synaptics_ts_data { char fw_name[TP_FW_NAME_MAX_LEN]; char fw_id[12]; char manu_name[12]; + + bool stop_keypad; }; static int tc_hw_pwron(struct synaptics_ts_data *ts) @@ -916,7 +918,7 @@ static void synaptics_ts_report(struct synaptics_ts_data *ts ) #elif (defined SUPPORT_VIRTUAL_KEY) if (virtual_key_enable) int_virtual_key(ts); - else + else if (!ts->stop_keypad) int_key(ts); #endif } @@ -1943,6 +1945,73 @@ static int synaptics_dsx_pinctrl_init(struct synaptics_ts_data *ts) return retval; } +static void synaptics_input_event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ + struct synaptics_ts_data *ts = tc_g; + + if (code != BTN_TOOL_FINGER) + return; + + /* Disable capacitive keys when user's finger is on touchscreen */ + ts->stop_keypad = value; +} + +static int synaptics_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int ret; + + handle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "s1302_handle"; + + ret = input_register_handle(handle); + if (ret) + goto err2; + + ret = input_open_device(handle); + if (ret) + goto err1; + + return 0; + +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return ret; +} + +static void synaptics_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id synaptics_input_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT, + .keybit = { [BIT_WORD(BTN_TOOL_FINGER)] = + BIT_MASK(BTN_TOOL_FINGER) }, + }, + { }, +}; + +static struct input_handler synaptics_input_handler = { + .event = synaptics_input_event, + .connect = synaptics_input_connect, + .disconnect = synaptics_input_disconnect, + .name = "syna_input_handler", + .id_table = synaptics_input_ids, +}; + static int synaptics_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { #ifdef CONFIG_SYNAPTIC_RED @@ -2075,6 +2144,11 @@ static int synaptics_ts_probe(struct i2c_client *client, const struct i2c_device register_remote_device_s1302(premote_data); } #endif + + ret = input_register_handler(&synaptics_input_handler); + if (ret) + TPD_ERR("%s: Failed to register input handler\n", __func__); + TPDTM_DMESG("synaptics_ts_probe s1302: normal end\n"); return 0; From 064a1e86bd5293e07231d1105185305e51df47e2 Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Sat, 16 Jul 2016 21:58:45 -0700 Subject: [PATCH 077/203] misc: fpc1020: Ignore home key presses when touchscreen is in use When the user's finger is on the touchscreen, don't process any home key button presses, as an unintended button press will cause poor UX. Ignore home key presses when the Synaptics s1302 driver is ignoring keypad presses. Signed-off-by: Sultanxda Signed-off-by: flar2 --- drivers/input/misc/fpc1020_tee.c | 13 ++++++++++--- drivers/input/touchscreen/synaptics_driver_s1302.c | 7 +++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/input/misc/fpc1020_tee.c b/drivers/input/misc/fpc1020_tee.c index 18b6e7979cbf..32cfffaf4a7e 100755 --- a/drivers/input/misc/fpc1020_tee.c +++ b/drivers/input/misc/fpc1020_tee.c @@ -280,6 +280,7 @@ static DEVICE_ATTR(irq, S_IRUSR | S_IWUSR, irq_get, irq_ack); extern void int_touch(void); extern struct completion key_cm; extern bool virtual_key_enable; +extern bool s1302_is_keypad_stopped(void); bool key_home_pressed = false; EXPORT_SYMBOL(key_home_pressed); @@ -289,12 +290,18 @@ static ssize_t report_home_set(struct device *dev, { struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); unsigned long time; + bool ignore_keypad; + + if (s1302_is_keypad_stopped() || virtual_key_enable) + ignore_keypad = true; + else + ignore_keypad = false; if(ignor_home_for_ESD) return -EINVAL; if (!strncmp(buf, "down", strlen("down"))) { - if(virtual_key_enable){ + if(ignore_keypad){ key_home_pressed = true; }else{ input_report_key(fpc1020->input_dev, @@ -304,7 +311,7 @@ static ssize_t report_home_set(struct device *dev, } else if (!strncmp(buf, "up", strlen("up"))) { - if(virtual_key_enable){ + if(ignore_keypad){ key_home_pressed = false; }else{ input_report_key(fpc1020->input_dev, @@ -314,7 +321,7 @@ static ssize_t report_home_set(struct device *dev, } else return -EINVAL; - if(virtual_key_enable){ + if(ignore_keypad){ if(!key_home_pressed){ reinit_completion(&key_cm); time = wait_for_completion_timeout(&key_cm,msecs_to_jiffies(60)); diff --git a/drivers/input/touchscreen/synaptics_driver_s1302.c b/drivers/input/touchscreen/synaptics_driver_s1302.c index 034a409f4e73..a4eba802f21a 100755 --- a/drivers/input/touchscreen/synaptics_driver_s1302.c +++ b/drivers/input/touchscreen/synaptics_driver_s1302.c @@ -1945,6 +1945,13 @@ static int synaptics_dsx_pinctrl_init(struct synaptics_ts_data *ts) return retval; } +bool s1302_is_keypad_stopped(void) +{ + struct synaptics_ts_data *ts = tc_g; + + return ts->stop_keypad; +} + static void synaptics_input_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { From d00e3c82790966a38bf0be963c00feebad54f8b0 Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Fri, 15 Jul 2016 16:24:25 -0700 Subject: [PATCH 078/203] input: synaptics: s3320: Don't run baseline on resume This causes the first touch after resume to get ignored, so don't do it. Change-Id: Ia6192181f9be053f75b04046ba0c97d6dca26c67 Signed-off-by: Sultanxda --- drivers/input/touchscreen/synaptics_driver_s3320.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index cf60d11bcae7..b62bb868f7e7 100644 --- a/drivers/input/touchscreen/synaptics_driver_s3320.c +++ b/drivers/input/touchscreen/synaptics_driver_s3320.c @@ -4134,7 +4134,10 @@ static int fb_notifier_callback(struct notifier_block *self, unsigned long event { TPD_DEBUG("%s going TP resume start\n", __func__); ts->is_suspended = 0; - queue_delayed_work(get_base_report, &ts->base_work,msecs_to_jiffies(1)); + if (ts->gesture_enable) + synaptics_enable_interrupt_for_gesture(ts, false); + atomic_set(&ts->is_stop, 0); + touch_enable(ts); synaptics_ts_resume(&ts->client->dev); //atomic_set(&ts->is_stop,0); TPD_DEBUG("%s going TP resume end\n", __func__); From a0465a1451f5d9881e90775fcb3e7d3186ede60a Mon Sep 17 00:00:00 2001 From: andip71 Date: Wed, 31 Aug 2016 15:14:27 +0200 Subject: [PATCH 079/203] leds-qpnp: Notification LED control - V1.1a - add missing check for pause_lo --- drivers/leds/leds-qpnp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index ba2f1d64bd7a..81a4b11b8cae 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -2353,7 +2353,8 @@ static ssize_t pause_lo_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); - pause_lo = convert_pause_lo_store(pause_lo); + if (check_for_notification_led(led_cdev)) + pause_lo = convert_pause_lo_store(pause_lo); switch (led->id) { case QPNP_ID_LED_MPP: From 6b73cc47a339ba5015310c0b49b6ce9c7b48f198 Mon Sep 17 00:00:00 2001 From: andip71 Date: Thu, 1 Sep 2016 11:36:00 +0200 Subject: [PATCH 080/203] leds-qpnp: Notification LED control - V1.1b - update pwm configuration with every blink request - add special handling for pwm_us_ms parameter --- drivers/leds/leds-qpnp.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index 81a4b11b8cae..82d175b04a15 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -261,6 +261,7 @@ #define LED_CUSTOM_PAUSE_HI 1400 #define LED_CUSTOM_PAUSE_LO 2000 #define LED_CUSTOM_RAMP_STEP 90 +#define LED_CUSTOM_PWM_US 1000 int led_enable_fade = 1; // default is fading @@ -310,6 +311,21 @@ u32 convert_ramp_ms_store (u32 ramp_step_ms) return ramp_step_ms; } +u32 convert_pwm_us (u32 pwm_us) +{ + pr_debug("Boeffla-LED: pwm_us orig = %d\n", pwm_us); + + // speed is set to stock = take roms ramp times + if (led_speed == LED_SPEED_STOCK_MODE) + return pwm_us; + + // fix value for pwm us + pwm_us = LED_CUSTOM_PWM_US; + + pr_debug("Boeffla-LED: pwm_us new = %d\n", pwm_us); + return pwm_us; +} + int check_for_notification_led(struct led_classdev *led_cdev) { if ((strcmp(led_cdev->name, "red") == 0) || @@ -2298,6 +2314,9 @@ static ssize_t pwm_us_store(struct device *dev, if (ret) return ret; + if (check_for_notification_led(led_cdev)) + pwm_us = convert_pwm_us(pwm_us); + switch (led->id) { case QPNP_ID_LED_MPP: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2781,6 +2800,19 @@ static ssize_t blink_store(struct device *dev, led = container_of(led_cdev, struct qpnp_led_data, cdev); led->cdev.brightness = blinking ? led->cdev.max_brightness : 0; + // AP: ensure, pwm configuration is always updated to avoid issues after startup + // with apps, that do not set it completely for all LEDs (e.g. WhatsApp); + // only do the update when we are not in stock speed mode and for RGB LEDs + if (check_for_notification_led(led_cdev) && (led_speed != LED_SPEED_STOCK_MODE)) + { + pwm_free(led->rgb_cfg->pwm_cfg->pwm_dev); + led->rgb_cfg->pwm_cfg->lut_params.lut_pause_hi = convert_pause_hi_store(LED_CUSTOM_PAUSE_HI); + led->rgb_cfg->pwm_cfg->lut_params.lut_pause_lo = convert_pause_lo_store(LED_CUSTOM_PAUSE_LO); + led->rgb_cfg->pwm_cfg->pwm_period_us = convert_pwm_us(LED_CUSTOM_PWM_US); + led->rgb_cfg->pwm_cfg->lut_params.ramp_step_ms = convert_ramp_ms_store(LED_CUSTOM_RAMP_STEP); + qpnp_pwm_init(led->rgb_cfg->pwm_cfg, led->spmi_dev, led->cdev.name); + } + switch (led->id) { case QPNP_ID_LED_MPP: led_blink(led, led->mpp_cfg->pwm_cfg); From 7a9d032f54fd977b3a2974b1624a7accfbe913e9 Mon Sep 17 00:00:00 2001 From: dianlujitao Date: Fri, 17 Jun 2016 10:37:21 +0800 Subject: [PATCH 081/203] staging: qcacld-2.0: Import LA.HB.1.3.1.c1-00700-8x96.0 from CAF Change-Id: Ia9d7a537743f121eea6f1682bc259945e6bc3dbb --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/qcacld-2.0/Android.mk | 113 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt.c | 658 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt.h | 6924 +++ .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_common.h | 72 + .../CORE/CLD_TXRX/HTT/htt_fw_stats.c | 872 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_h2t.c | 990 + .../CORE/CLD_TXRX/HTT/htt_internal.h | 440 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_isoc.h | 1101 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_rx.c | 2926 ++ .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_t2h.c | 1045 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c | 911 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_types.h | 387 + .../qcacld-2.0/CORE/CLD_TXRX/HTT/rx_desc.h | 215 + .../qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c | 2624 + .../qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.h | 135 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_cfg.c | 260 + .../CORE/CLD_TXRX/TXRX/ol_ctrl_txrx_api.h | 229 + .../CORE/CLD_TXRX/TXRX/ol_osif_txrx_api.h | 50 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.c | 1423 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.h | 80 + .../CORE/CLD_TXRX/TXRX/ol_rx_defrag.c | 1195 + .../CORE/CLD_TXRX/TXRX/ol_rx_defrag.h | 263 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.c | 265 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.h | 84 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.c | 370 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.h | 122 + .../CORE/CLD_TXRX/TXRX/ol_rx_reorder.c | 831 + .../CORE/CLD_TXRX/TXRX/ol_rx_reorder.h | 105 + .../CLD_TXRX/TXRX/ol_rx_reorder_timeout.c | 227 + .../CLD_TXRX/TXRX/ol_rx_reorder_timeout.h | 71 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.c | 954 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.h | 94 + .../CORE/CLD_TXRX/TXRX/ol_tx_classify.c | 793 + .../CORE/CLD_TXRX/TXRX/ol_tx_classify.h | 99 + .../CORE/CLD_TXRX/TXRX/ol_tx_desc.c | 376 + .../CORE/CLD_TXRX/TXRX/ol_tx_desc.h | 177 + .../CORE/CLD_TXRX/TXRX/ol_tx_queue.c | 1943 + .../CORE/CLD_TXRX/TXRX/ol_tx_queue.h | 332 + .../CORE/CLD_TXRX/TXRX/ol_tx_sched.c | 1427 + .../CORE/CLD_TXRX/TXRX/ol_tx_sched.h | 128 + .../CORE/CLD_TXRX/TXRX/ol_tx_send.c | 1133 + .../CORE/CLD_TXRX/TXRX/ol_tx_send.h | 97 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c | 2630 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.h | 62 + .../CORE/CLD_TXRX/TXRX/ol_txrx_encap.c | 596 + .../CORE/CLD_TXRX/TXRX/ol_txrx_encap.h | 132 + .../CORE/CLD_TXRX/TXRX/ol_txrx_event.c | 231 + .../CORE/CLD_TXRX/TXRX/ol_txrx_internal.h | 710 + .../CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.c | 551 + .../CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.h | 130 + .../CORE/CLD_TXRX/TXRX/ol_txrx_types.h | 1088 + .../qcacld-2.0/CORE/CLD_TXRX/TXRX/txrx.h | 239 + .../CORE/EPPING/inc/epping_internal.h | 196 + .../qcacld-2.0/CORE/EPPING/inc/epping_main.h | 56 + .../qcacld-2.0/CORE/EPPING/inc/epping_test.h | 126 + .../CORE/EPPING/src/epping_helper.c | 306 + .../qcacld-2.0/CORE/EPPING/src/epping_main.c | 428 + .../qcacld-2.0/CORE/EPPING/src/epping_rx.c | 202 + .../qcacld-2.0/CORE/EPPING/src/epping_tx.c | 398 + .../qcacld-2.0/CORE/EPPING/src/epping_txrx.c | 468 + .../qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h | 277 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h | 169 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h | 4242 ++ .../CORE/HDD/inc/wlan_hdd_cfg80211.h | 1741 + .../CORE/HDD/inc/wlan_hdd_debugfs.h | 43 + .../CORE/HDD/inc/wlan_hdd_dev_pwr.h | 120 + .../CORE/HDD/inc/wlan_hdd_dp_utils.h | 127 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_ether.h | 89 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_ftm.h | 65 + .../CORE/HDD/inc/wlan_hdd_host_offload.h | 62 + .../CORE/HDD/inc/wlan_hdd_hostapd.h | 199 + .../CORE/HDD/inc/wlan_hdd_includes.h | 73 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_ipa.h | 88 + .../CORE/HDD/inc/wlan_hdd_keep_alive.h | 58 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h | 1953 + .../CORE/HDD/inc/wlan_hdd_mdns_offload.h | 44 + .../CORE/HDD/inc/wlan_hdd_memdump.h | 92 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_mib.h | 228 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_nan.h | 41 + .../CORE/HDD/inc/wlan_hdd_oemdata.h | 163 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h | 196 + .../CORE/HDD/inc/wlan_hdd_packet_filtering.h | 116 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_power.h | 107 + .../CORE/HDD/inc/wlan_hdd_softap_tx_rx.h | 312 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h | 456 + .../CORE/HDD/inc/wlan_hdd_tgt_cfg.h | 116 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_trace.h | 117 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_tsf.h | 68 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_tx_rx.h | 319 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h | 487 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_wmm.h | 398 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_wowl.h | 204 + .../qcacld-2.0/CORE/HDD/inc/wlan_qct_driver.h | 80 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c | 5298 ++ .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c | 7229 +++ .../CORE/HDD/src/wlan_hdd_cfg80211.c | 23237 +++++++++ .../CORE/HDD/src/wlan_hdd_debugfs.c | 638 + .../CORE/HDD/src/wlan_hdd_dev_pwr.c | 217 + .../CORE/HDD/src/wlan_hdd_dp_utils.c | 286 + .../CORE/HDD/src/wlan_hdd_early_suspend.c | 2284 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_ftm.c | 1136 + .../CORE/HDD/src/wlan_hdd_hostapd.c | 7114 +++ .../qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c | 4693 ++ .../qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c | 15923 ++++++ .../CORE/HDD/src/wlan_hdd_mdns_offload.c | 1425 + .../CORE/HDD/src/wlan_hdd_memdump.c | 668 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c | 2163 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.h | 288 + .../CORE/HDD/src/wlan_hdd_oemdata.c | 841 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c | 2828 ++ .../qcacld-2.0/CORE/HDD/src/wlan_hdd_scan.c | 1183 + .../CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 1513 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c | 3295 ++ .../qcacld-2.0/CORE/HDD/src/wlan_hdd_trace.c | 136 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_tsf.c | 246 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c | 2074 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c | 12526 +++++ .../qcacld-2.0/CORE/HDD/src/wlan_hdd_wmm.c | 2745 + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_wowl.c | 615 + .../qcacld-2.0/CORE/MAC/inc/aniGlobal.h | 1276 + .../qcacld-2.0/CORE/MAC/inc/aniSystemDefs.h | 239 + .../staging/qcacld-2.0/CORE/MAC/inc/logDump.h | 88 + .../qcacld-2.0/CORE/MAC/inc/macInitApi.h | 50 + .../qcacld-2.0/CORE/MAC/inc/macTrace.h | 87 + .../qcacld-2.0/CORE/MAC/inc/qwlan_version.h | 65 + .../staging/qcacld-2.0/CORE/MAC/inc/sirApi.h | 6514 +++ .../qcacld-2.0/CORE/MAC/inc/sirMacPropExts.h | 135 + .../qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h | 2326 + .../qcacld-2.0/CORE/MAC/inc/sirTypes.h | 189 + .../staging/qcacld-2.0/CORE/MAC/inc/wniApi.h | 729 + .../qcacld-2.0/CORE/MAC/inc/wniCfgAp.h | 2522 + .../qcacld-2.0/CORE/MAC/inc/wniCfgSta.h | 1615 + .../qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c | 1142 + .../qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.c | 57 + .../qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.h | 51 + .../qcacld-2.0/CORE/MAC/src/cfg/cfgDef.h | 75 + .../CORE/MAC/src/cfg/cfgParamName.c | 337 + .../qcacld-2.0/CORE/MAC/src/cfg/cfgPriv.h | 92 + .../qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c | 2979 ++ .../qcacld-2.0/CORE/MAC/src/cfg/cfgSendMsg.c | 151 + .../CORE/MAC/src/cfg/cfgUtil/cfg.txt | 4416 ++ .../CORE/MAC/src/cfg/cfgUtil/dot11f.frms | 4017 ++ .../qcacld-2.0/CORE/MAC/src/cfg/polFile.h | 173 + .../CORE/MAC/src/dph/dphHashTable.c | 515 + .../CORE/MAC/src/dph/dphHashTable.h | 100 + .../qcacld-2.0/CORE/MAC/src/include/cfgApi.h | 134 + .../CORE/MAC/src/include/cfgGlobal.h | 95 + .../qcacld-2.0/CORE/MAC/src/include/dot11f.h | 7583 +++ .../CORE/MAC/src/include/dphGlobal.h | 537 + .../CORE/MAC/src/include/parserApi.h | 1008 + .../CORE/MAC/src/include/sirCommon.h | 56 + .../CORE/MAC/src/include/sirDebug.h | 116 + .../CORE/MAC/src/include/sirParams.h | 902 + .../CORE/MAC/src/include/sysGlobal.h | 55 + .../CORE/MAC/src/include/utilsApi.h | 738 + .../CORE/MAC/src/include/utilsGlobal.h | 57 + .../CORE/MAC/src/pe/include/limAdmitControl.h | 121 + .../CORE/MAC/src/pe/include/limApi.h | 265 + .../CORE/MAC/src/pe/include/limFT.h | 78 + .../CORE/MAC/src/pe/include/limFTDefs.h | 133 + .../CORE/MAC/src/pe/include/limGlobal.h | 723 + .../CORE/MAC/src/pe/include/limSession.h | 642 + .../CORE/MAC/src/pe/include/limTrace.h | 108 + .../CORE/MAC/src/pe/include/pmmApi.h | 154 + .../CORE/MAC/src/pe/include/pmmGlobal.h | 168 + .../CORE/MAC/src/pe/include/rrmApi.h | 111 + .../CORE/MAC/src/pe/include/rrmGlobal.h | 352 + .../CORE/MAC/src/pe/include/schApi.h | 106 + .../CORE/MAC/src/pe/include/schGlobal.h | 182 + .../CORE/MAC/src/pe/include/wmmApsd.h | 50 + .../CORE/MAC/src/pe/lim/limAIDmgmt.c | 200 + .../CORE/MAC/src/pe/lim/limAdmitControl.c | 1140 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c | 2679 + .../CORE/MAC/src/pe/lim/limAssocUtils.c | 5001 ++ .../CORE/MAC/src/pe/lim/limAssocUtils.h | 196 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.c | 57 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.h | 61 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c | 2027 + .../CORE/MAC/src/pe/lim/limIbssPeerMgmt.c | 1810 + .../CORE/MAC/src/pe/lim/limIbssPeerMgmt.h | 55 + .../MAC/src/pe/lim/limLinkMonitoringAlgo.c | 522 + .../CORE/MAC/src/pe/lim/limLogDump.c | 2193 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c | 1173 + .../MAC/src/pe/lim/limProcessActionFrame.c | 2625 + .../MAC/src/pe/lim/limProcessAssocReqFrame.c | 1949 + .../MAC/src/pe/lim/limProcessAssocRspFrame.c | 1059 + .../CORE/MAC/src/pe/lim/limProcessAuthFrame.c | 1929 + .../MAC/src/pe/lim/limProcessBeaconFrame.c | 307 + .../MAC/src/pe/lim/limProcessCfgUpdates.c | 726 + .../MAC/src/pe/lim/limProcessDeauthFrame.c | 555 + .../MAC/src/pe/lim/limProcessDisassocFrame.c | 364 + .../MAC/src/pe/lim/limProcessMessageQueue.c | 2410 + .../MAC/src/pe/lim/limProcessMlmReqMessages.c | 4896 ++ .../MAC/src/pe/lim/limProcessMlmRspMessages.c | 5111 ++ .../MAC/src/pe/lim/limProcessProbeReqFrame.c | 735 + .../MAC/src/pe/lim/limProcessProbeRspFrame.c | 500 + .../MAC/src/pe/lim/limProcessSmeReqMessages.c | 7058 +++ .../CORE/MAC/src/pe/lim/limProcessTdls.c | 3326 ++ .../CORE/MAC/src/pe/lim/limPropExtsUtils.c | 306 + .../CORE/MAC/src/pe/lim/limPropExtsUtils.h | 67 + .../CORE/MAC/src/pe/lim/limRoamingAlgo.c | 324 + .../CORE/MAC/src/pe/lim/limScanResultUtils.c | 1409 + .../CORE/MAC/src/pe/lim/limScanResultUtils.h | 77 + .../CORE/MAC/src/pe/lim/limSecurityUtils.c | 1350 + .../CORE/MAC/src/pe/lim/limSecurityUtils.h | 96 + .../MAC/src/pe/lim/limSendManagementFrames.c | 6319 +++ .../CORE/MAC/src/pe/lim/limSendMessages.c | 952 + .../CORE/MAC/src/pe/lim/limSendMessages.h | 116 + .../MAC/src/pe/lim/limSendSmeRspMessages.c | 3343 ++ .../MAC/src/pe/lim/limSendSmeRspMessages.h | 135 + .../CORE/MAC/src/pe/lim/limSerDesUtils.c | 2773 + .../CORE/MAC/src/pe/lim/limSerDesUtils.h | 126 + .../CORE/MAC/src/pe/lim/limSession.c | 850 + .../CORE/MAC/src/pe/lim/limSessionUtils.c | 496 + .../CORE/MAC/src/pe/lim/limSessionUtils.h | 256 + .../CORE/MAC/src/pe/lim/limSmeReqUtils.c | 1108 + .../CORE/MAC/src/pe/lim/limSmeReqUtils.h | 60 + .../CORE/MAC/src/pe/lim/limStaHashApi.c | 76 + .../CORE/MAC/src/pe/lim/limStaHashApi.h | 50 + .../CORE/MAC/src/pe/lim/limTimerUtils.c | 2276 + .../CORE/MAC/src/pe/lim/limTimerUtils.h | 136 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limTrace.c | 503 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h | 1085 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c | 8678 ++++ .../qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h | 667 + .../qcacld-2.0/CORE/MAC/src/pe/pmm/pmmAP.c | 102 + .../qcacld-2.0/CORE/MAC/src/pe/pmm/pmmApi.c | 3694 ++ .../qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.c | 57 + .../qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.h | 54 + .../qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c | 1327 + .../qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c | 664 + .../CORE/MAC/src/pe/sch/schBeaconGen.c | 904 + .../CORE/MAC/src/pe/sch/schBeaconProcess.c | 925 + .../qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.c | 64 + .../qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.h | 53 + .../CORE/MAC/src/pe/sch/schMessage.c | 568 + .../CORE/MAC/src/pe/sch/schSysParams.h | 107 + .../staging/qcacld-2.0/CORE/SAP/inc/sapApi.h | 2385 + .../qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c | 1417 + .../qcacld-2.0/CORE/SAP/src/sapChSelect.c | 2647 + .../qcacld-2.0/CORE/SAP/src/sapChSelect.h | 208 + .../staging/qcacld-2.0/CORE/SAP/src/sapFsm.c | 4909 ++ .../qcacld-2.0/CORE/SAP/src/sapFsm_ext.h | 64 + .../qcacld-2.0/CORE/SAP/src/sapInternal.h | 1095 + .../qcacld-2.0/CORE/SAP/src/sapModule.c | 3972 ++ .../CORE/SERVICES/BMI/ar6320v2_dbg_regtable.h | 609 + .../qcacld-2.0/CORE/SERVICES/BMI/bin_sig.h | 45 + .../qcacld-2.0/CORE/SERVICES/BMI/bmi.c | 902 + .../CORE/SERVICES/BMI/bmi_internal.h | 45 + .../qcacld-2.0/CORE/SERVICES/BMI/fw_one_bin.h | 88 + .../qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c | 2717 + .../qcacld-2.0/CORE/SERVICES/BMI/ol_fw.h | 152 + .../CORE/SERVICES/COMMON/_ieee80211_common.h | 551 + .../qcacld-2.0/CORE/SERVICES/COMMON/a_debug.h | 208 + .../qcacld-2.0/CORE/SERVICES/COMMON/a_osapi.h | 71 + .../qcacld-2.0/CORE/SERVICES/COMMON/a_types.h | 52 + .../CORE/SERVICES/COMMON/a_usb_defs.h | 102 + .../CORE/SERVICES/COMMON/adf/a_base_types.h | 79 + .../CORE/SERVICES/COMMON/adf/adf_nbuf.c | 567 + .../CORE/SERVICES/COMMON/adf/adf_nbuf.h | 1194 + .../CORE/SERVICES/COMMON/adf/adf_net_types.h | 619 + .../CORE/SERVICES/COMMON/adf/adf_os_atomic.h | 124 + .../CORE/SERVICES/COMMON/adf/adf_os_bitops.h | 228 + .../CORE/SERVICES/COMMON/adf/adf_os_defer.h | 193 + .../CORE/SERVICES/COMMON/adf/adf_os_dma.h | 135 + .../CORE/SERVICES/COMMON/adf/adf_os_io.h | 207 + .../CORE/SERVICES/COMMON/adf/adf_os_lock.c | 39 + .../CORE/SERVICES/COMMON/adf/adf_os_lock.h | 177 + .../CORE/SERVICES/COMMON/adf/adf_os_mem.c | 72 + .../CORE/SERVICES/COMMON/adf/adf_os_mem.h | 247 + .../CORE/SERVICES/COMMON/adf/adf_os_module.h | 113 + .../SERVICES/COMMON/adf/adf_os_stdtypes.h | 44 + .../CORE/SERVICES/COMMON/adf/adf_os_time.h | 153 + .../CORE/SERVICES/COMMON/adf/adf_os_timer.h | 119 + .../CORE/SERVICES/COMMON/adf/adf_os_types.h | 337 + .../CORE/SERVICES/COMMON/adf/adf_os_util.h | 168 + .../SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h | 1237 + .../COMMON/adf/linux/adf_os_atomic_pvt.h | 80 + .../COMMON/adf/linux/adf_os_defer_pvt.c | 60 + .../COMMON/adf/linux/adf_os_defer_pvt.h | 162 + .../COMMON/adf/linux/adf_os_dma_pvt.h | 139 + .../SERVICES/COMMON/adf/linux/adf_os_io_pvt.h | 93 + .../COMMON/adf/linux/adf_os_lock_pvt.c | 34 + .../COMMON/adf/linux/adf_os_lock_pvt.h | 190 + .../COMMON/adf/linux/adf_os_mem_pvt.c | 39 + .../COMMON/adf/linux/adf_os_mem_pvt.h | 207 + .../COMMON/adf/linux/adf_os_module_pvt.h | 76 + .../COMMON/adf/linux/adf_os_postpack_pvt.h | 31 + .../COMMON/adf/linux/adf_os_prepack_pvt.h | 31 + .../COMMON/adf/linux/adf_os_pseudo_pvt.h | 78 + .../COMMON/adf/linux/adf_os_time_pvt.h | 133 + .../COMMON/adf/linux/adf_os_timer_pvt.h | 143 + .../SERVICES/COMMON/adf/linux/adf_os_trace.h | 55 + .../COMMON/adf/linux/adf_os_types_pvt.h | 191 + .../COMMON/adf/linux/adf_os_util_pvt.h | 131 + .../CORE/SERVICES/COMMON/ah_osdep.h | 466 + .../CORE/SERVICES/COMMON/apb_athr_wlan_map.h | 59 + .../qcacld-2.0/CORE/SERVICES/COMMON/athdefs.h | 99 + .../CORE/SERVICES/COMMON/athendpack.h | 35 + .../CORE/SERVICES/COMMON/athstartpack.h | 58 + .../qcacld-2.0/CORE/SERVICES/COMMON/bmi.h | 165 + .../qcacld-2.0/CORE/SERVICES/COMMON/bmi_msg.h | 384 + .../qcacld-2.0/CORE/SERVICES/COMMON/dbglog.h | 180 + .../CORE/SERVICES/COMMON/dbglog_host.h | 251 + .../CORE/SERVICES/COMMON/dbglog_id.h | 1621 + .../CORE/SERVICES/COMMON/debug_linux.h | 55 + .../qcacld-2.0/CORE/SERVICES/COMMON/dl_list.h | 198 + .../CORE/SERVICES/COMMON/efuse_reg.h | 154 + .../qcacld-2.0/CORE/SERVICES/COMMON/enet.h | 152 + .../qcacld-2.0/CORE/SERVICES/COMMON/hif.h | 870 + .../CORE/SERVICES/COMMON/hif_msg_based.h | 155 + .../qcacld-2.0/CORE/SERVICES/COMMON/htc.h | 472 + .../qcacld-2.0/CORE/SERVICES/COMMON/htc_api.h | 707 + .../CORE/SERVICES/COMMON/htc_packet.h | 267 + .../CORE/SERVICES/COMMON/htc_services.h | 107 + .../qcacld-2.0/CORE/SERVICES/COMMON/hwdef.h | 58 + .../CORE/SERVICES/COMMON/ieee80211_common.h | 2235 + .../CORE/SERVICES/COMMON/ieee80211_defines.h | 1381 + .../CORE/SERVICES/COMMON/if_upperproto.h | 248 + .../qcacld-2.0/CORE/SERVICES/COMMON/ip_prot.h | 61 + .../qcacld-2.0/CORE/SERVICES/COMMON/ipv4.h | 55 + .../CORE/SERVICES/COMMON/ipv6_defs.h | 110 + .../CORE/SERVICES/COMMON/isoc_hw_desc.h | 1197 + .../qcacld-2.0/CORE/SERVICES/COMMON/ol_cfg.h | 500 + .../CORE/SERVICES/COMMON/ol_ctrl_addba_api.h | 43 + .../CORE/SERVICES/COMMON/ol_ctrl_api.h | 44 + .../CORE/SERVICES/COMMON/ol_defines.h | 49 + .../CORE/SERVICES/COMMON/ol_fw_tx_dbg.h | 186 + .../CORE/SERVICES/COMMON/ol_htt_api.h | 329 + .../CORE/SERVICES/COMMON/ol_htt_rx_api.h | 879 + .../CORE/SERVICES/COMMON/ol_htt_tx_api.h | 846 + .../CORE/SERVICES/COMMON/ol_if_athvar.h | 450 + .../CORE/SERVICES/COMMON/ol_osif_api.h | 42 + .../CORE/SERVICES/COMMON/ol_params.h | 105 + .../CORE/SERVICES/COMMON/ol_txrx_api.h | 113 + .../CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h | 1334 + .../CORE/SERVICES/COMMON/ol_txrx_dbg.h | 232 + .../CORE/SERVICES/COMMON/ol_txrx_htt_api.h | 733 + .../CORE/SERVICES/COMMON/ol_txrx_osif_api.h | 211 + .../CORE/SERVICES/COMMON/ol_txrx_stats.h | 117 + .../CORE/SERVICES/COMMON/ol_vowext_dbg_defs.h | 67 + .../CORE/SERVICES/COMMON/osapi_linux.h | 480 + .../qcacld-2.0/CORE/SERVICES/COMMON/osdep.h | 105 + .../CORE/SERVICES/COMMON/osdep_adf.h | 1245 + .../qcacld-2.0/CORE/SERVICES/COMMON/pktlog.h | 39 + .../CORE/SERVICES/COMMON/pktlog_ac_fmt.h | 365 + .../qcacld-2.0/CORE/SERVICES/COMMON/queue.h | 563 + .../CORE/SERVICES/COMMON/rtc_soc_reg.h | 1966 + .../CORE/SERVICES/COMMON/sys/queue.h | 576 + .../CORE/SERVICES/COMMON/targaddrs.h | 689 + .../qcacld-2.0/CORE/SERVICES/COMMON/targcfg.h | 53 + .../CORE/SERVICES/COMMON/testmode.h | 58 + .../CORE/SERVICES/COMMON/wal_rx_desc.h | 132 + .../CORE/SERVICES/COMMON/wdi_event.h | 92 + .../CORE/SERVICES/COMMON/wdi_event_api.h | 83 + .../qcacld-2.0/CORE/SERVICES/COMMON/wdi_in.h | 1280 + .../qcacld-2.0/CORE/SERVICES/COMMON/wdi_out.h | 561 + .../CORE/SERVICES/COMMON/wdi_types.h | 124 + .../CORE/SERVICES/COMMON/wlan_defs.h | 798 + .../CORE/SERVICES/COMMON/wlan_module_ids.h | 105 + .../CORE/SERVICES/COMMON/wlan_opts.h | 103 + .../SERVICES/COMMON/wlan_tgt_def_config.h | 259 + .../SERVICES/COMMON/wlan_tgt_def_config_hl.h | 298 + .../CORE/SERVICES/COMMON/wlan_types.h | 72 + .../qcacld-2.0/CORE/SERVICES/COMMON/wma_api.h | 156 + .../CORE/SERVICES/COMMON/wma_dfs_interface.h | 225 + .../qcacld-2.0/CORE/SERVICES/COMMON/wmi.h | 203 + .../CORE/SERVICES/COMMON/wmi_services.h | 158 + .../CORE/SERVICES/COMMON/wmi_tlv_defs.h | 3041 ++ .../CORE/SERVICES/COMMON/wmi_tlv_helper.h | 156 + .../CORE/SERVICES/COMMON/wmi_unified.h | 12074 +++++ .../CORE/SERVICES/COMMON/wmi_unified_api.h | 185 + .../CORE/SERVICES/COMMON/wmi_version.h | 80 + .../SERVICES/COMMON/wmi_version_whitelist.c | 39 + .../qcacld-2.0/CORE/SERVICES/COMMON/wmix.h | 193 + .../CORE/SERVICES/DFS/inc/ath_dfs_structs.h | 253 + .../qcacld-2.0/CORE/SERVICES/DFS/inc/dfs.h | 808 + .../CORE/SERVICES/DFS/inc/dfs_interface.h | 186 + .../CORE/SERVICES/DFS/inc/radar_filters.h | 161 + .../qcacld-2.0/CORE/SERVICES/DFS/sources | 62 + .../qcacld-2.0/CORE/SERVICES/DFS/src/dfs.c | 987 + .../CORE/SERVICES/DFS/src/dfs_bindetects.c | 461 + .../CORE/SERVICES/DFS/src/dfs_debug.c | 157 + .../CORE/SERVICES/DFS/src/dfs_fcc_bin5.c | 836 + .../CORE/SERVICES/DFS/src/dfs_init.c | 376 + .../CORE/SERVICES/DFS/src/dfs_ioctl.h | 133 + .../CORE/SERVICES/DFS/src/dfs_ioctl_private.h | 115 + .../CORE/SERVICES/DFS/src/dfs_misc.c | 272 + .../CORE/SERVICES/DFS/src/dfs_nol.c | 403 + .../CORE/SERVICES/DFS/src/dfs_phyerr.h | 66 + .../CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c | 745 + .../CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h | 223 + .../SERVICES/DFS/src/dfs_process_phyerr.c | 923 + .../SERVICES/DFS/src/dfs_process_radarevent.c | 696 + .../CORE/SERVICES/DFS/src/dfs_staggered.c | 296 + .../CORE/SERVICES/HIF/PCIe/ar6320def.h | 703 + .../CORE/SERVICES/HIF/PCIe/ar6320v2def.h | 702 + .../CORE/SERVICES/HIF/PCIe/ar9888def.h | 515 + .../qcacld-2.0/CORE/SERVICES/HIF/PCIe/cepci.h | 109 + .../CORE/SERVICES/HIF/PCIe/copy_engine.c | 1678 + .../CORE/SERVICES/HIF/PCIe/copy_engine_api.h | 442 + .../SERVICES/HIF/PCIe/copy_engine_internal.h | 342 + .../CORE/SERVICES/HIF/PCIe/hif_pci.c | 3597 ++ .../CORE/SERVICES/HIF/PCIe/hif_pci.h | 230 + .../CORE/SERVICES/HIF/PCIe/if_pci.c | 3016 ++ .../CORE/SERVICES/HIF/PCIe/if_pci.h | 221 + .../CORE/SERVICES/HIF/PCIe/mp_dev.c | 282 + .../CORE/SERVICES/HIF/PCIe/regtable.c | 68 + .../CORE/SERVICES/HIF/PCIe/regtable.h | 851 + .../CORE/SERVICES/HIF/USB/ar6320def.h | 698 + .../CORE/SERVICES/HIF/USB/ar6320v2def.h | 695 + .../CORE/SERVICES/HIF/USB/ar9888def.h | 512 + .../CORE/SERVICES/HIF/USB/hif_usb.c | 1049 + .../CORE/SERVICES/HIF/USB/hif_usb_internal.h | 176 + .../qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.c | 677 + .../qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.h | 106 + .../CORE/SERVICES/HIF/USB/regtable.c | 67 + .../CORE/SERVICES/HIF/USB/regtable.h | 854 + .../qcacld-2.0/CORE/SERVICES/HIF/USB/usbdrv.c | 1156 + .../qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c | 209 + .../SERVICES/HIF/common/hif_bmi_reg_access.c | 442 + .../SERVICES/HIF/common/hif_diag_reg_access.c | 298 + .../SERVICES/HIF/common/hif_sdio_common.h | 213 + .../CORE/SERVICES/HIF/common/hif_trace.h | 47 + .../CORE/SERVICES/HIF/sdio/ar6320def.h | 646 + .../CORE/SERVICES/HIF/sdio/ar6320v2def.h | 643 + .../CORE/SERVICES/HIF/sdio/ar9888def.h | 519 + .../qcacld-2.0/CORE/SERVICES/HIF/sdio/cepci.h | 109 + .../CORE/SERVICES/HIF/sdio/hif_sdio.c | 154 + .../CORE/SERVICES/HIF/sdio/hif_sdio_dev.c | 426 + .../CORE/SERVICES/HIF/sdio/hif_sdio_dev.h | 60 + .../SERVICES/HIF/sdio/hif_sdio_internal.h | 149 + .../CORE/SERVICES/HIF/sdio/hif_sdio_recv.c | 1323 + .../CORE/SERVICES/HIF/sdio/hif_sdio_send.c | 188 + .../SERVICES/HIF/sdio/linux/if_ath_sdio.c | 427 + .../SERVICES/HIF/sdio/linux/if_ath_sdio.h | 109 + .../linux/native_sdio/include/hif_internal.h | 161 + .../HIF/sdio/linux/native_sdio/src/hif.c | 2345 + .../sdio/linux/native_sdio/src/hif_scatter.c | 412 + .../CORE/SERVICES/HIF/sdio/regtable.c | 83 + .../CORE/SERVICES/HIF/sdio/regtable.h | 773 + .../qcacld-2.0/CORE/SERVICES/HTC/htc.c | 1023 + .../qcacld-2.0/CORE/SERVICES/HTC/htc_debug.h | 43 + .../CORE/SERVICES/HTC/htc_internal.h | 343 + .../qcacld-2.0/CORE/SERVICES/HTC/htc_recv.c | 676 + .../qcacld-2.0/CORE/SERVICES/HTC/htc_send.c | 1844 + .../CORE/SERVICES/HTC/htc_services.c | 361 + .../qcacld-2.0/CORE/SERVICES/WMA/regdomain.c | 716 + .../qcacld-2.0/CORE/SERVICES/WMA/regdomain.h | 1103 + .../CORE/SERVICES/WMA/regdomain_common.h | 1864 + .../qcacld-2.0/CORE/SERVICES/WMA/wlan_nv.c | 5409 ++ .../CORE/SERVICES/WMA/wlan_qct_wma_legacy.c | 235 + .../qcacld-2.0/CORE/SERVICES/WMA/wma.c | 33004 ++++++++++++ .../qcacld-2.0/CORE/SERVICES/WMA/wma.h | 1681 + .../CORE/SERVICES/WMA/wma_dfs_interface.c | 231 + .../qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c | 1122 + .../qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.h | 67 + .../qcacld-2.0/CORE/SERVICES/WMA/wma_stub.h | 92 + .../CORE/SERVICES/WMI/wmi_tlv_helper.c | 998 + .../CORE/SERVICES/WMI/wmi_tlv_platform.c | 58 + .../CORE/SERVICES/WMI/wmi_unified.c | 1264 + .../CORE/SERVICES/WMI/wmi_unified_priv.h | 101 + .../staging/qcacld-2.0/CORE/SME/inc/btcApi.h | 323 + .../staging/qcacld-2.0/CORE/SME/inc/ccmApi.h | 114 + .../staging/qcacld-2.0/CORE/SME/inc/csrApi.h | 1864 + .../qcacld-2.0/CORE/SME/inc/csrInternal.h | 1586 + .../qcacld-2.0/CORE/SME/inc/csrLinkList.h | 118 + .../qcacld-2.0/CORE/SME/inc/csrNeighborRoam.h | 371 + .../qcacld-2.0/CORE/SME/inc/csrSupport.h | 816 + .../staging/qcacld-2.0/CORE/SME/inc/nan_Api.h | 94 + .../qcacld-2.0/CORE/SME/inc/oemDataApi.h | 142 + .../qcacld-2.0/CORE/SME/inc/oemDataInternal.h | 67 + .../staging/qcacld-2.0/CORE/SME/inc/p2p_Api.h | 114 + drivers/staging/qcacld-2.0/CORE/SME/inc/pmc.h | 451 + .../staging/qcacld-2.0/CORE/SME/inc/pmcApi.h | 579 + .../qcacld-2.0/CORE/SME/inc/smeInside.h | 350 + .../qcacld-2.0/CORE/SME/inc/smeInternal.h | 222 + .../qcacld-2.0/CORE/SME/inc/smeQosInternal.h | 251 + .../qcacld-2.0/CORE/SME/inc/smeRrmInternal.h | 110 + .../staging/qcacld-2.0/CORE/SME/inc/sme_Api.h | 4406 ++ .../qcacld-2.0/CORE/SME/inc/sme_FTApi.h | 111 + .../qcacld-2.0/CORE/SME/inc/sme_QosApi.h | 393 + .../qcacld-2.0/CORE/SME/inc/sme_RrmApi.h | 72 + .../qcacld-2.0/CORE/SME/inc/sme_Trace.h | 159 + .../qcacld-2.0/CORE/SME/inc/smsDebug.h | 53 + .../CORE/SME/inc/wlan_ps_wow_diag.h | 148 + .../qcacld-2.0/CORE/SME/src/QoS/sme_Qos.c | 8648 ++++ .../qcacld-2.0/CORE/SME/src/btc/btcApi.c | 2070 + .../qcacld-2.0/CORE/SME/src/ccm/ccmApi.c | 789 + .../qcacld-2.0/CORE/SME/src/ccm/ccmLogDump.c | 53 + .../qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c | 19681 +++++++ .../qcacld-2.0/CORE/SME/src/csr/csrApiScan.c | 8878 ++++ .../CORE/SME/src/csr/csrCmdProcess.c | 241 + .../CORE/SME/src/csr/csrInsideApi.h | 1081 + .../qcacld-2.0/CORE/SME/src/csr/csrLinkList.c | 659 + .../qcacld-2.0/CORE/SME/src/csr/csrLogDump.c | 136 + .../CORE/SME/src/csr/csrNeighborRoam.c | 6341 +++ .../CORE/SME/src/csr/csrTdlsProcess.c | 847 + .../qcacld-2.0/CORE/SME/src/csr/csrUtil.c | 6069 +++ .../qcacld-2.0/CORE/SME/src/nan/nan_Api.c | 145 + .../CORE/SME/src/oemData/oemDataApi.c | 376 + .../qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c | 511 + .../staging/qcacld-2.0/CORE/SME/src/pmc/pmc.c | 3640 ++ .../qcacld-2.0/CORE/SME/src/pmc/pmcApi.c | 4143 ++ .../qcacld-2.0/CORE/SME/src/pmc/pmcLogDump.c | 417 + .../qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c | 1625 + .../CORE/SME/src/sme_common/sme_Api.c | 17447 +++++++ .../CORE/SME/src/sme_common/sme_FTApi.c | 625 + .../CORE/SME/src/sme_common/sme_Trace.c | 227 + .../CORE/SVC/external/wlan_nlink_common.h | 211 + .../qcacld-2.0/CORE/SVC/inc/wlan_btc_svc.h | 39 + .../CORE/SVC/inc/wlan_logging_sock_svc.h | 77 + .../qcacld-2.0/CORE/SVC/inc/wlan_nlink_srv.h | 63 + .../CORE/SVC/inc/wlan_ptt_sock_svc.h | 118 + .../CORE/SVC/src/btc/wlan_btc_svc.c | 254 + .../SVC/src/logging/wlan_logging_sock_svc.c | 795 + .../CORE/SVC/src/nlink/wlan_nlink_srv.c | 311 + .../CORE/SVC/src/ptt/wlan_ptt_sock_svc.c | 190 + .../CORE/SYS/common/inc/wlan_qct_sys.h | 425 + .../CORE/SYS/common/src/wlan_qct_sys.c | 774 + .../CORE/SYS/legacy/src/pal/inc/palApi.h | 761 + .../CORE/SYS/legacy/src/pal/src/palApiComm.c | 358 + .../SYS/legacy/src/platform/inc/VossWrapper.h | 174 + .../SYS/legacy/src/platform/src/VossWrapper.c | 531 + .../CORE/SYS/legacy/src/system/inc/sysDebug.h | 47 + .../CORE/SYS/legacy/src/system/inc/sysDef.h | 180 + .../SYS/legacy/src/system/inc/sysEntryFunc.h | 53 + .../SYS/legacy/src/system/inc/sysStartup.h | 55 + .../SYS/legacy/src/system/src/macInitApi.c | 369 + .../SYS/legacy/src/system/src/sysEntryFunc.c | 269 + .../SYS/legacy/src/utils/inc/dot11fdefs.h | 100 + .../SYS/legacy/src/utils/inc/utilsParser.h | 81 + .../CORE/SYS/legacy/src/utils/src/dot11f.c | 42378 ++++++++++++++++ .../CORE/SYS/legacy/src/utils/src/logApi.c | 206 + .../CORE/SYS/legacy/src/utils/src/logDump.c | 452 + .../CORE/SYS/legacy/src/utils/src/macTrace.c | 1054 + .../CORE/SYS/legacy/src/utils/src/parserApi.c | 5720 +++ .../CORE/SYS/legacy/src/utils/src/utilsApi.c | 99 + .../SYS/legacy/src/utils/src/utilsParser.c | 820 + .../qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h | 3012 ++ .../qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c | 4261 ++ .../CORE/UTILS/PKTLOG/include/pktlog_ac.h | 164 + .../CORE/UTILS/PKTLOG/include/pktlog_ac_api.h | 116 + .../CORE/UTILS/PKTLOG/include/pktlog_ac_i.h | 65 + .../qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c | 1194 + .../qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c | 415 + .../CORE/UTILS/PKTLOG/pktlog_internal.c | 628 + .../qcacld-2.0/CORE/VOSS/inc/event_defs.h | 1918 + .../CORE/VOSS/inc/i_vos_diag_core_event.h | 105 + .../CORE/VOSS/inc/i_vos_diag_core_log.h | 142 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_event.h | 78 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_list.h | 76 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h | 93 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_packet.h | 86 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_timer.h | 80 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_trace.h | 161 + .../qcacld-2.0/CORE/VOSS/inc/i_vos_types.h | 205 + .../qcacld-2.0/CORE/VOSS/inc/log_codes.h | 2082 + .../qcacld-2.0/CORE/VOSS/inc/vos_api.h | 368 + .../CORE/VOSS/inc/vos_diag_core_event.h | 356 + .../CORE/VOSS/inc/vos_diag_core_log.h | 400 + .../qcacld-2.0/CORE/VOSS/inc/vos_event.h | 267 + .../qcacld-2.0/CORE/VOSS/inc/vos_getBin.h | 149 + .../qcacld-2.0/CORE/VOSS/inc/vos_list.h | 584 + .../qcacld-2.0/CORE/VOSS/inc/vos_lock.h | 316 + .../qcacld-2.0/CORE/VOSS/inc/vos_memory.h | 311 + .../staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h | 233 + .../qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h | 258 + .../qcacld-2.0/CORE/VOSS/inc/vos_pack_align.h | 111 + .../qcacld-2.0/CORE/VOSS/inc/vos_packet.h | 243 + .../qcacld-2.0/CORE/VOSS/inc/vos_status.h | 134 + .../qcacld-2.0/CORE/VOSS/inc/vos_threads.h | 112 + .../qcacld-2.0/CORE/VOSS/inc/vos_timer.h | 334 + .../qcacld-2.0/CORE/VOSS/inc/vos_trace.h | 199 + .../qcacld-2.0/CORE/VOSS/inc/vos_types.h | 525 + .../qcacld-2.0/CORE/VOSS/inc/vos_utils.h | 185 + .../qcacld-2.0/CORE/VOSS/inc/wcnss_api.h | 116 + .../qcacld-2.0/CORE/VOSS/inc/wlan_hdd_misc.h | 47 + .../qcacld-2.0/CORE/VOSS/src/vos_api.c | 2959 ++ .../qcacld-2.0/CORE/VOSS/src/vos_diag.c | 308 + .../qcacld-2.0/CORE/VOSS/src/vos_event.c | 445 + .../qcacld-2.0/CORE/VOSS/src/vos_getBin.c | 287 + .../qcacld-2.0/CORE/VOSS/src/vos_list.c | 945 + .../qcacld-2.0/CORE/VOSS/src/vos_lock.c | 739 + .../qcacld-2.0/CORE/VOSS/src/vos_memory.c | 777 + .../staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c | 251 + .../qcacld-2.0/CORE/VOSS/src/vos_nvitem.c | 1898 + .../qcacld-2.0/CORE/VOSS/src/vos_packet.c | 427 + .../qcacld-2.0/CORE/VOSS/src/vos_sched.c | 2562 + .../qcacld-2.0/CORE/VOSS/src/vos_sched.h | 680 + .../qcacld-2.0/CORE/VOSS/src/vos_threads.c | 133 + .../qcacld-2.0/CORE/VOSS/src/vos_timer.c | 874 + .../qcacld-2.0/CORE/VOSS/src/vos_trace.c | 701 + .../qcacld-2.0/CORE/VOSS/src/vos_types.c | 188 + .../qcacld-2.0/CORE/VOSS/src/vos_utils.c | 1232 + .../CORE/WDA/inc/legacy/halMsgApi.h | 1639 + .../qcacld-2.0/CORE/WDA/inc/legacy/halTypes.h | 437 + .../qcacld-2.0/CORE/WDA/inc/legacy/palTypes.h | 189 + .../CORE/WDA/inc/legacy/wlan_qct_hal.h | 566 + .../qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h | 1256 + .../CORE/WDA/inc/wlan_qct_wda_msg.h | 86 + .../CORE/WDA/src/wlan_qct_wda_debug.c | 60 + .../CORE/WDA/src/wlan_qct_wda_debug.h | 83 + .../CORE/WDA/src/wlan_qct_wda_legacy.c | 210 + drivers/staging/qcacld-2.0/Kbuild | 1444 + drivers/staging/qcacld-2.0/Kconfig | 72 + drivers/staging/qcacld-2.0/Makefile | 28 + .../qcacld-2.0/firmware_bin/WCNSS_cfg.dat | Bin 0 -> 10234 bytes .../firmware_bin/WCNSS_qcom_cfg.ini | 665 + .../firmware_bin/WCNSS_qcom_cfg.usb.ini | 550 + .../qcacld-2.0/wcnss/inc/halCompiler.h | 177 + .../qcacld-2.0/wcnss/inc/halLegacyPalTypes.h | 60 + .../staging/qcacld-2.0/wcnss/inc/wlan_nv.h | 837 + 615 files changed, 653872 insertions(+) create mode 100644 drivers/staging/qcacld-2.0/Android.mk create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_common.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_fw_stats.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_h2t.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_isoc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_rx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_t2h.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/rx_desc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_cfg.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_ctrl_txrx_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_osif_txrx_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_event.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.c create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/txrx.h create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_main.h create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_test.h create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_helper.c create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_rx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_tx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_txrx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_debugfs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dev_pwr.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dp_utils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ether.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ftm.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_host_offload.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_hostapd.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_includes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ipa.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_keep_alive.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mdns_offload.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mib.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_nan.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_oemdata.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_packet_filtering.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_power.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_trace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tsf.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tx_rx.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wmm.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wowl.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_qct_driver.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_debugfs.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dev_pwr.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dp_utils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ftm.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_mdns_offload.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.h create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_scan.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_trace.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tsf.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wmm.c create mode 100644 drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wowl.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/aniSystemDefs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/logDump.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/macInitApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/macTrace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacPropExts.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/sirTypes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDef.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgParamName.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgPriv.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgSendMsg.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/cfg.txt create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/dot11f.frms create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/polFile.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/dphGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirCommon.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/sysGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limAdmitControl.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFT.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFTDefs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limTrace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schGlobal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/wmmApsd.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAIDmgmt.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAdmitControl.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLogDump.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limRoamingAlgo.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTrace.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmAP.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconProcess.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schMessage.c create mode 100644 drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schSysParams.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm_ext.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapInternal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ar6320v2_dbg_regtable.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bin_sig.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/fw_one_bin.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/_ieee80211_common.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_debug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_osapi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_usb_defs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/a_base_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_net_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_atomic.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_bitops.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_defer.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_dma.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_io.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_module.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_stdtypes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_time.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_timer.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_util.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_atomic_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_dma_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_io_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_module_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_postpack_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_prepack_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_pseudo_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_timer_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_trace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_types_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_util_pvt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ah_osdep.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/apb_athr_wlan_map.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athdefs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athendpack.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athstartpack.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi_msg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_host.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_id.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/debug_linux.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dl_list.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/efuse_reg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/enet.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif_msg_based.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_packet.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_services.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hwdef.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_common.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_defines.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/if_upperproto.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ip_prot.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv4.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv6_defs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/isoc_hw_desc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_cfg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_addba_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_defines.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_fw_tx_dbg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_rx_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_tx_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_if_athvar.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_osif_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_params.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_htt_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_osif_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_stats.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_vowext_dbg_defs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osapi_linux.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep_adf.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog_ac_fmt.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/queue.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/rtc_soc_reg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/sys/queue.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targaddrs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targcfg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/testmode.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wal_rx_desc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_in.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_out.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_defs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_module_ids.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_opts.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_dfs_interface.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_services.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_defs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_helper.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version_whitelist.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmix.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/ath_dfs_structs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs_interface.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/radar_filters.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/sources create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_bindetects.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_debug.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_init.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl_private.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_misc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_nol.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_phyerr.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_radarevent.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_staggered.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320v2def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar9888def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/cepci.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/mp_dev.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320v2def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar9888def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/usbdrv.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_bmi_reg_access.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_diag_reg_access.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_sdio_common.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_trace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320v2def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar9888def.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/cepci.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_send.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif_scatter.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_debug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_internal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_recv.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_services.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_nv.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_qct_wma_legacy.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_dfs_interface.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_stub.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_helper.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_platform.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/btcApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/ccmApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/csrInternal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/csrLinkList.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/csrNeighborRoam.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/csrSupport.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/nan_Api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataInternal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/p2p_Api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/pmc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/pmcApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/smeInside.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/smeQosInternal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/smeRrmInternal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/sme_FTApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/sme_QosApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/sme_RrmApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Trace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/smsDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/inc/wlan_ps_wow_diag.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/QoS/sme_Qos.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/btc/btcApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmLogDump.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiScan.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrCmdProcess.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrInsideApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLinkList.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLogDump.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrTdlsProcess.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/nan/nan_Api.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcLogDump.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Trace.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/external/wlan_nlink_common.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_btc_svc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_logging_sock_svc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_nlink_srv.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_ptt_sock_svc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/src/btc/wlan_btc_svc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/src/nlink/wlan_nlink_srv.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/common/inc/wlan_qct_sys.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/common/src/wlan_qct_sys.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/inc/palApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/src/palApiComm.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/inc/VossWrapper.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/src/VossWrapper.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDebug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDef.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysEntryFunc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysStartup.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/macInitApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/sysEntryFunc.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/dot11fdefs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/utilsParser.h create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logDump.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsApi.c create mode 100644 drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsParser.c create mode 100644 drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac.h create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_i.h create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c create mode 100644 drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/event_defs.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_diag_core_event.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_diag_core_log.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_event.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_list.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_packet.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_timer.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_trace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/log_codes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_event.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_log.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_event.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_getBin.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_list.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_lock.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_memory.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_pack_align.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_status.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_threads.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_timer.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_trace.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_types.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/wcnss_api.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/inc/wlan_hdd_misc.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_diag.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_event.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_getBin.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_list.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_memory.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_threads.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_timer.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_trace.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_types.c create mode 100644 drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halTypes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/palTypes.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/wlan_qct_hal.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda_msg.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.c create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.h create mode 100644 drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_legacy.c create mode 100644 drivers/staging/qcacld-2.0/Kbuild create mode 100644 drivers/staging/qcacld-2.0/Kconfig create mode 100644 drivers/staging/qcacld-2.0/Makefile create mode 100755 drivers/staging/qcacld-2.0/firmware_bin/WCNSS_cfg.dat create mode 100755 drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini create mode 100644 drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini create mode 100644 drivers/staging/qcacld-2.0/wcnss/inc/halCompiler.h create mode 100644 drivers/staging/qcacld-2.0/wcnss/inc/halLegacyPalTypes.h create mode 100644 drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4690ae9a267f..a8c60e705d83 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -108,4 +108,6 @@ source "drivers/staging/skein/Kconfig" source "drivers/staging/unisys/Kconfig" +source "drivers/staging/qcacld-2.0/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 53503056d747..841e5ca8e0ee 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -45,3 +45,4 @@ obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ obj-$(CONFIG_UNISYSSPAR) += unisys/ +obj-$(CONFIG_QCA_CLD_WLAN) += qcacld-2.0/ diff --git a/drivers/staging/qcacld-2.0/Android.mk b/drivers/staging/qcacld-2.0/Android.mk new file mode 100644 index 000000000000..2ae160a2b766 --- /dev/null +++ b/drivers/staging/qcacld-2.0/Android.mk @@ -0,0 +1,113 @@ +# Android makefile for the WLAN Module + +# Assume no targets will be supported +WLAN_CHIPSET := + +ifeq ($(BOARD_HAS_QCOM_WLAN), true) +# Build/Package options for 8084/8092/8960/8992/8994/msm8996 targets +ifeq ($(call is-board-platform-in-list, apq8084 mpq8092 msm8952 msm8960 msm8992 msm8994 msm8996),true) +WLAN_CHIPSET := qca_cld +WLAN_SELECT := CONFIG_QCA_CLD_WLAN=m +endif + +# Build/Package only in case of supported target +ifneq ($(WLAN_CHIPSET),) + +LOCAL_PATH := $(call my-dir) + +# This makefile is only for DLKM +ifneq ($(findstring vendor,$(LOCAL_PATH)),) + +# Determine if we are Proprietary or Open Source +ifneq ($(findstring opensource,$(LOCAL_PATH)),) + WLAN_PROPRIETARY := 0 + WLAN_OPEN_SOURCE := 1 +else + WLAN_PROPRIETARY := 1 + WLAN_OPEN_SOURCE := 0 +endif + +ifeq ($(WLAN_PROPRIETARY),1) + WLAN_BLD_DIR := vendor/qcom/proprietary/wlan-noship +else + WLAN_BLD_DIR := vendor/qcom/opensource/wlan +endif + +# DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) +ifeq ($(call is-platform-sdk-version-at-least,16),true) + DLKM_DIR := $(TOP)/device/qcom/common/dlkm +else + DLKM_DIR := build/dlkm +endif + +# Copy WCNSS_cfg.dat and WCNSS_qcom_cfg.ini file from firmware_bin/ folder to target out directory. +ifeq ($(call is-board-platform-in-list, msm8960),true) +$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/WCNSS_cfg.dat) +$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT_ETC)/firmware/wlan/qca_cld) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_qcom_cfg.ini $(TARGET_OUT_ETC)/firmware/wlan/qca_cld) +endif + +########################################################### +# This is set once per LOCAL_PATH, not per (kernel) module +KBUILD_OPTIONS := WLAN_ROOT=../$(WLAN_BLD_DIR)/qcacld-2.0 +# We are actually building wlan.ko here, as per the +# requirement we are specifying _wlan.ko as LOCAL_MODULE. +# This means we need to rename the module to _wlan.ko +# after wlan.ko is built. +KBUILD_OPTIONS += MODNAME=wlan +KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) +KBUILD_OPTIONS += $(WLAN_SELECT) +KBUILD_OPTIONS += WLAN_OPEN_SOURCE=$(WLAN_OPEN_SOURCE) + +include $(CLEAR_VARS) +LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko +LOCAL_MODULE_KBUILD_NAME := wlan.ko +LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_DEBUG_ENABLE := true +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) +include $(DLKM_DIR)/AndroidKernelModule.mk +########################################################### + +# Create Symbolic link for built _wlan.ko driver from +# standard module location. +# TO-DO: This step needs to be moved to a post-build make target instead +# TO-DO: as this may run multiple times +$(shell mkdir -p $(TARGET_OUT)/lib/modules; \ + ln -sf /system/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ + $(TARGET_OUT)/lib/modules/wlan.ko) +$(shell ln -sf /persist/wlan_mac.bin $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/wlan_mac.bin) + +ifeq ($(call is-board-platform-in-list, msm8960),true) +$(shell ln -sf /firmware/image/bdwlan20.bin $(TARGET_OUT_ETC)/firmware/fakeboar.bin) +$(shell ln -sf /firmware/image/otp20.bin $(TARGET_OUT_ETC)/firmware/otp.bin) +$(shell ln -sf /firmware/image/utf20.bin $(TARGET_OUT_ETC)/firmware/utf.bin) +$(shell ln -sf /firmware/image/qwlan20.bin $(TARGET_OUT_ETC)/firmware/athwlan.bin) + +$(shell ln -sf /firmware/image/bdwlan20.bin $(TARGET_OUT_ETC)/firmware/bdwlan20.bin) +$(shell ln -sf /firmware/image/otp20.bin $(TARGET_OUT_ETC)/firmware/otp20.bin) +$(shell ln -sf /firmware/image/utf20.bin $(TARGET_OUT_ETC)/firmware/utf20.bin) +$(shell ln -sf /firmware/image/qwlan20.bin $(TARGET_OUT_ETC)/firmware/qwlan20.bin) + +$(shell ln -sf /firmware/image/bdwlan30.bin $(TARGET_OUT_ETC)/firmware/bdwlan30.bin) +$(shell ln -sf /firmware/image/otp30.bin $(TARGET_OUT_ETC)/firmware/otp30.bin) +$(shell ln -sf /firmware/image/utf30.bin $(TARGET_OUT_ETC)/firmware/utf30.bin) +$(shell ln -sf /firmware/image/qwlan30.bin $(TARGET_OUT_ETC)/firmware/qwlan30.bin) +endif + +# Copy config ini files to target +ifeq ($(call is-board-platform-in-list, msm8994),false) +ifeq ($(WLAN_PROPRIETARY),1) +$(shell mkdir -p $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_CHIPSET)) +$(shell mkdir -p $(TARGET_OUT)/etc/wifi) +$(shell rm -f $(TARGET_OUT)/etc/wifi/WCNSS_qcom_cfg.ini) +$(shell rm -f $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_SHIPSET)/WCNSS_cfg.dat) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_qcom_cfg.ini $(TARGET_OUT)/etc/wifi) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_CHIPSET)) +endif +endif + +endif # DLKM check + +endif # supported target check +endif # WLAN enabled check diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.c new file mode 100644 index 000000000000..d428608e8d34 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.c @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt.c + * @brief Provide functions to create+init and destroy a HTT instance. + * @details + * This file contains functions for creating a HTT instance; initializing + * the HTT instance, e.g. by allocating a pool of HTT tx descriptors and + * connecting the HTT service with HTC; and deleting a HTT instance. + */ + +#include /* adf_os_mem_alloc */ +#include /* adf_os_device_t, adf_os_print */ + +#include /* htt_tx_msdu_desc_t */ +#include +#include /* ol_tx_dowload_done_ll, etc. */ +#include + +#include +#if defined(HIF_PCI) +#include "if_pci.h" +#endif + +#define HTT_HTC_PKT_POOL_INIT_SIZE 100 /* enough for a large A-MPDU */ + +A_STATUS +htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev); + +A_STATUS +htt_h2t_rx_ring_cfg_msg_hl(struct htt_pdev_t *pdev); + +A_STATUS (*htt_h2t_rx_ring_cfg_msg)( + struct htt_pdev_t *pdev); + +#ifdef IPA_UC_OFFLOAD +A_STATUS +htt_ipa_config(htt_pdev_handle pdev, A_STATUS status) +{ + if ((A_OK == status) && + ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) { + status = htt_h2t_ipa_uc_rsc_cfg_msg(pdev); + } + return status; +} + +#define HTT_IPA_CONFIG htt_ipa_config +#else +#define HTT_IPA_CONFIG(pdev, status) status /* no-op */ +#endif /* IPA_UC_OFFLOAD */ + + +struct htt_htc_pkt * +htt_htc_pkt_alloc(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt_union *pkt = NULL; + + HTT_TX_MUTEX_ACQUIRE(&pdev->htt_tx_mutex); + if (pdev->htt_htc_pkt_freelist) { + pkt = pdev->htt_htc_pkt_freelist; + pdev->htt_htc_pkt_freelist = pdev->htt_htc_pkt_freelist->u.next; + } + HTT_TX_MUTEX_RELEASE(&pdev->htt_tx_mutex); + + if (pkt == NULL) { + pkt = adf_os_mem_alloc(pdev->osdev, sizeof(*pkt)); + } + return &pkt->u.pkt; /* not actually a dereference */ +} + +void +htt_htc_pkt_free(struct htt_pdev_t *pdev, struct htt_htc_pkt *pkt) +{ + struct htt_htc_pkt_union *u_pkt = (struct htt_htc_pkt_union *) pkt; + + HTT_TX_MUTEX_ACQUIRE(&pdev->htt_tx_mutex); + u_pkt->u.next = pdev->htt_htc_pkt_freelist; + pdev->htt_htc_pkt_freelist = u_pkt; + HTT_TX_MUTEX_RELEASE(&pdev->htt_tx_mutex); +} + +void +htt_htc_pkt_pool_free(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt_union *pkt, *next; + pkt = pdev->htt_htc_pkt_freelist; + while (pkt) { + next = pkt->u.next; + adf_os_mem_free(pkt); + pkt = next; + } + pdev->htt_htc_pkt_freelist = NULL; +} + +#ifdef ATH_11AC_TXCOMPACT +void +htt_htc_misc_pkt_list_trim(struct htt_pdev_t *pdev, int level) +{ + struct htt_htc_pkt_union *pkt, *next, *prev = NULL; + int i = 0; + adf_nbuf_t netbuf; + + HTT_TX_MUTEX_ACQUIRE(&pdev->htt_tx_mutex); + pkt = pdev->htt_htc_pkt_misclist; + while (pkt) { + next = pkt->u.next; + /* trim the out grown list*/ + if (++i > level) { + netbuf = (adf_nbuf_t)(pkt->u.pkt.htc_pkt.pNetBufContext); + adf_nbuf_unmap(pdev->osdev, netbuf, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(netbuf); + adf_os_mem_free(pkt); + pkt = NULL; + if (prev) + prev->u.next = NULL; + } + prev = pkt; + pkt = next; + } + HTT_TX_MUTEX_RELEASE(&pdev->htt_tx_mutex); +} + +void +htt_htc_misc_pkt_list_add(struct htt_pdev_t *pdev, struct htt_htc_pkt *pkt) +{ + struct htt_htc_pkt_union *u_pkt = (struct htt_htc_pkt_union *) pkt; + + HTT_TX_MUTEX_ACQUIRE(&pdev->htt_tx_mutex); + if (pdev->htt_htc_pkt_misclist) { + u_pkt->u.next = pdev->htt_htc_pkt_misclist; + pdev->htt_htc_pkt_misclist = u_pkt; + } else { + pdev->htt_htc_pkt_misclist = u_pkt; + } + HTT_TX_MUTEX_RELEASE(&pdev->htt_tx_mutex); + htt_htc_misc_pkt_list_trim(pdev, HTT_HTC_PKT_MISCLIST_SIZE); +} + +void +htt_htc_misc_pkt_pool_free(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt_union *pkt, *next; + adf_nbuf_t netbuf; + pkt = pdev->htt_htc_pkt_misclist; + + while (pkt) { + next = pkt->u.next; + netbuf = (adf_nbuf_t)(pkt->u.pkt.htc_pkt.pNetBufContext); + adf_nbuf_unmap(pdev->osdev, netbuf, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(netbuf); + adf_os_mem_free(pkt); + pkt = next; + } + pdev->htt_htc_pkt_misclist = NULL; +} +#endif + +/*---*/ + +htt_pdev_handle +htt_attach( + ol_txrx_pdev_handle txrx_pdev, + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, + adf_os_device_t osdev, + int desc_pool_size) +{ + struct htt_pdev_t *pdev; + int i; + + pdev = adf_os_mem_alloc(osdev, sizeof(*pdev)); + + if (!pdev) { + goto fail1; + } + + pdev->osdev = osdev; + pdev->ctrl_pdev = ctrl_pdev; + pdev->txrx_pdev = txrx_pdev; + pdev->htc_pdev = htc_pdev; + + adf_os_mem_set(&pdev->stats, 0, sizeof(pdev->stats)); + pdev->htt_htc_pkt_freelist = NULL; +#ifdef ATH_11AC_TXCOMPACT + pdev->htt_htc_pkt_misclist = NULL; +#endif + + /* for efficiency, store a local copy of the is_high_latency flag */ + pdev->cfg.is_high_latency = ol_cfg_is_high_latency(pdev->ctrl_pdev); + pdev->cfg.default_tx_comp_req = + !ol_cfg_tx_free_at_download(pdev->ctrl_pdev); + + pdev->cfg.is_full_reorder_offload = + ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev); + adf_os_print("is_full_reorder_offloaded? %d\n", + (int)pdev->cfg.is_full_reorder_offload); + pdev->targetdef = htc_get_targetdef(htc_pdev); + /* + * Connect to HTC service. + * This has to be done before calling htt_rx_attach, + * since htt_rx_attach involves sending a rx ring configure + * message to the target. + */ +//AR6004 don't need HTT layer. +#ifndef AR6004_HW + if (htt_htc_attach(pdev)) { + goto fail2; + } +#endif + if (htt_tx_attach(pdev, desc_pool_size)) { + goto fail2; + } + + if (htt_rx_attach(pdev)) { + goto fail3; + } + + HTT_TX_MUTEX_INIT(&pdev->htt_tx_mutex); + HTT_TX_NBUF_QUEUE_MUTEX_INIT(pdev); + + /* pre-allocate some HTC_PACKET objects */ + for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) { + struct htt_htc_pkt_union *pkt; + pkt = adf_os_mem_alloc(pdev->osdev, sizeof(*pkt)); + if (! pkt) { + break; + } + htt_htc_pkt_free(pdev, &pkt->u.pkt); + } + + if (pdev->cfg.is_high_latency) { + /* + * HL - download the whole frame. + * Specify a download length greater than the max MSDU size, + * so the downloads will be limited by the actual frame sizes. + */ + pdev->download_len = 5000; + if (ol_cfg_tx_free_at_download(pdev->ctrl_pdev)) { + pdev->tx_send_complete_part2 = ol_tx_download_done_hl_free; + } else { + pdev->tx_send_complete_part2 = ol_tx_download_done_hl_retain; + } + + /* + * For LL, the FW rx desc directly referenced at its location + * inside the rx indication message. + */ +/* + * CHECK THIS LATER: does the HL HTT version of htt_rx_mpdu_desc_list_next + * (which is not currently implemented) present the adf_nbuf_data(rx_ind_msg) + * as the abstract rx descriptor? + * If not, the rx_fw_desc_offset initialization here will have to be + * adjusted accordingly. + * NOTE: for HL, because fw rx desc is in ind msg, not in rx desc, so the + * offset should be negtive value + */ + pdev->rx_fw_desc_offset = + HTT_ENDIAN_BYTE_IDX_SWAP( + HTT_RX_IND_FW_RX_DESC_BYTE_OFFSET + - HTT_RX_IND_HL_BYTES); + + htt_h2t_rx_ring_cfg_msg = htt_h2t_rx_ring_cfg_msg_hl; + + /* initialize the txrx credit count */ + ol_tx_target_credit_update( + pdev->txrx_pdev, ol_cfg_target_tx_credit(ctrl_pdev)); + } else { + /* + * LL - download just the initial portion of the frame. + * Download enough to cover the encapsulation headers checked + * by the target's tx classification descriptor engine. + */ + enum wlan_frm_fmt frm_type; + + /* account for the 802.3 or 802.11 header */ + frm_type = ol_cfg_frame_type(pdev->ctrl_pdev); + if (frm_type == wlan_frm_fmt_native_wifi) { + pdev->download_len = HTT_TX_HDR_SIZE_NATIVE_WIFI; + } else if (frm_type == wlan_frm_fmt_802_3) { + pdev->download_len = HTT_TX_HDR_SIZE_ETHERNET; + } else { + adf_os_print("Unexpected frame type spec: %d\n", frm_type); + HTT_ASSERT0(0); + } + /* + * Account for the optional L2 / ethernet header fields: + * 802.1Q, LLC/SNAP + */ + pdev->download_len += + HTT_TX_HDR_SIZE_802_1Q + HTT_TX_HDR_SIZE_LLC_SNAP; + + /* + * Account for the portion of the L3 (IP) payload that the + * target needs for its tx classification. + */ + pdev->download_len += ol_cfg_tx_download_size(pdev->ctrl_pdev); + + /* + * Account for the HTT tx descriptor, including the + * HTC header + alignment padding. + */ + pdev->download_len += sizeof(struct htt_host_tx_desc_t); + + /* + * The TXCOMPACT htt_tx_sched function uses pdev->download_len + * to apply for all requeued tx frames. Thus, pdev->download_len + * has to be the largest download length of any tx frame that will + * be downloaded. + * This maximum download length is for management tx frames, + * which have an 802.11 header. + */ + #ifdef ATH_11AC_TXCOMPACT + pdev->download_len = + sizeof(struct htt_host_tx_desc_t) + + HTT_TX_HDR_SIZE_OUTER_HDR_MAX + /* worst case */ + HTT_TX_HDR_SIZE_802_1Q + + HTT_TX_HDR_SIZE_LLC_SNAP + + ol_cfg_tx_download_size(pdev->ctrl_pdev); + #endif + pdev->tx_send_complete_part2 = ol_tx_download_done_ll; + + /* + * For LL, the FW rx desc is alongside the HW rx desc fields in + * the htt_host_rx_desc_base struct/. + */ + pdev->rx_fw_desc_offset = RX_STD_DESC_FW_MSDU_OFFSET; + + htt_h2t_rx_ring_cfg_msg = htt_h2t_rx_ring_cfg_msg_ll; + } + + return pdev; + +fail3: + htt_tx_detach(pdev); + +fail2: + adf_os_mem_free(pdev); + +fail1: + return NULL; +} + +A_STATUS +htt_attach_target(htt_pdev_handle pdev) +{ + A_STATUS status; + status = htt_h2t_ver_req_msg(pdev); + if (status != A_OK) { + return status; + } + /* + * If applicable, send the rx ring config message to the target. + * The host could wait for the HTT version number confirmation message + * from the target before sending any further HTT messages, but it's + * reasonable to assume that the host and target HTT version numbers + * match, and proceed immediately with the remaining configuration + * handshaking. + */ + + status = htt_h2t_rx_ring_cfg_msg(pdev); + status = HTT_IPA_CONFIG(pdev, status); + + return status; +} + +void +htt_detach(htt_pdev_handle pdev) +{ + htt_rx_detach(pdev); + htt_tx_detach(pdev); + htt_htc_pkt_pool_free(pdev); +#ifdef ATH_11AC_TXCOMPACT + htt_htc_misc_pkt_pool_free(pdev); +#endif + HTT_TX_MUTEX_DESTROY(&pdev->htt_tx_mutex); + HTT_TX_NBUF_QUEUE_MUTEX_DESTROY(pdev); +#ifdef DEBUG_RX_RING_BUFFER + if (pdev->rx_buff_list) + adf_os_mem_free(pdev->rx_buff_list); +#endif + adf_os_mem_free(pdev); +} + +void +htt_detach_target(htt_pdev_handle pdev) +{ +} + +int +htt_htc_attach(struct htt_pdev_t *pdev) +{ + HTC_SERVICE_CONNECT_REQ connect; + HTC_SERVICE_CONNECT_RESP response; + A_STATUS status; + + adf_os_mem_set(&connect, 0, sizeof(connect)); + adf_os_mem_set(&response, 0, sizeof(response)); + + connect.pMetaData = NULL; + connect.MetaDataLength = 0; + connect.EpCallbacks.pContext = pdev; + connect.EpCallbacks.EpTxComplete = htt_h2t_send_complete; + connect.EpCallbacks.EpTxCompleteMultiple = NULL; + connect.EpCallbacks.EpRecv = htt_t2h_msg_handler; + connect.EpCallbacks.EpResumeTxQueue = htt_tx_resume_handler; + + /* rx buffers currently are provided by HIF, not by EpRecvRefill */ + connect.EpCallbacks.EpRecvRefill = NULL; + connect.EpCallbacks.RecvRefillWaterMark = 1; /* N/A, fill is done by HIF */ + + connect.EpCallbacks.EpSendFull = htt_h2t_full; + /* + * Specify how deep to let a queue get before HTCSendPkt will + * call the EpSendFull function due to excessive send queue depth. + */ + connect.MaxSendQueueDepth = HTT_MAX_SEND_QUEUE_DEPTH; + + /* disable flow control for HTT data message service */ +#ifdef HIF_SDIO + /* + * HTC Credit mechanism is disabled based on + * default_tx_comp_req as throughput will be lower + * if we disable htc credit mechanism with default_tx_comp_req + * set since txrx download packet will be limited by ota + * completion. + * TODO:Conditional disabling will be removed once firmware + * with reduced tx completion is pushed into release builds. + */ + if (!pdev->cfg.default_tx_comp_req) { + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; + } +#else + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; +#endif + + /* connect to control service */ + connect.ServiceID = HTT_DATA_MSG_SVC; + + status = HTCConnectService(pdev->htc_pdev, &connect, &response); + + if (status != A_OK) { + return 1; /* failure */ + } + pdev->htc_endpoint = response.Endpoint; +#if defined(HIF_PCI) + hif_pci_save_htc_htt_config_endpoint(pdev->htc_endpoint); +#endif + +#ifdef QCA_TX_HTT2_SUPPORT + /* Start TX HTT2 service if the target support it. */ + if (pdev->cfg.is_high_latency) { + adf_os_mem_set(&connect, 0, sizeof(connect)); + adf_os_mem_set(&response, 0, sizeof(response)); + + /* The same as HTT service but no RX. */ + connect.EpCallbacks.pContext = pdev; + connect.EpCallbacks.EpTxComplete = htt_h2t_send_complete; + connect.EpCallbacks.EpSendFull = htt_h2t_full; + connect.MaxSendQueueDepth = HTT_MAX_SEND_QUEUE_DEPTH; + + /* Should NOT support credit flow control. */ + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; + /* Enable HTC schedule mechanism for TX HTT2 service. */ + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_ENABLE_HTC_SCHEDULE; + + connect.ServiceID = HTT_DATA2_MSG_SVC; + + status = HTCConnectService(pdev->htc_pdev, &connect, &response); + if (status != A_OK) { + pdev->htc_tx_htt2_endpoint = ENDPOINT_UNUSED; + pdev->htc_tx_htt2_max_size = 0; + } else { + pdev->htc_tx_htt2_endpoint = response.Endpoint; + pdev->htc_tx_htt2_max_size = HTC_TX_HTT2_MAX_SIZE; + } + + adf_os_print("TX HTT %s, ep %d size %d\n", + (status == A_OK ? "ON" : "OFF"), + pdev->htc_tx_htt2_endpoint, + pdev->htc_tx_htt2_max_size); + } +#endif /* QCA_TX_HTT2_SUPPORT */ + + return 0; /* success */ +} + +#if HTT_DEBUG_LEVEL > 5 +void +htt_display(htt_pdev_handle pdev, int indent) +{ + adf_os_print("%*s%s:\n", indent, " ", "HTT"); + adf_os_print( + "%*stx desc pool: %d elems of %d bytes, " + "%d currently allocated\n", indent+4, " ", + pdev->tx_descs.pool_elems, + pdev->tx_descs.size, + pdev->tx_descs.alloc_cnt); + adf_os_print( + "%*srx ring: space for %d elems, filled with %d buffers\n", + indent+4, " ", + pdev->rx_ring.size, + pdev->rx_ring.fill_level); + adf_os_print("%*sat %p (%#x paddr)\n", indent+8, " ", + pdev->rx_ring.buf.paddrs_ring, + pdev->rx_ring.base_paddr); + adf_os_print("%*snetbuf ring @ %p\n", indent+8, " ", + pdev->rx_ring.buf.netbufs_ring); + adf_os_print("%*sFW_IDX shadow register: vaddr = %p, paddr = %#x\n", + indent+8, " ", + pdev->rx_ring.alloc_idx.vaddr, + pdev->rx_ring.alloc_idx.paddr); + adf_os_print( + "%*sSW enqueue index = %d, SW dequeue index: desc = %d, buf = %d\n", + indent+8, " ", + *pdev->rx_ring.alloc_idx.vaddr, + pdev->rx_ring.sw_rd_idx.msdu_desc, + pdev->rx_ring.sw_rd_idx.msdu_payld); +} +#endif + +/* Disable ASPM : Disable PCIe low power */ +void htt_htc_disable_aspm(void) +{ + htc_disable_aspm(); +} + +#ifdef IPA_UC_OFFLOAD +/* + * Attach resource for micro controller data path + */ +int +htt_ipa_uc_attach(struct htt_pdev_t *pdev) +{ + int error; + + /* TX resource attach */ + error = htt_tx_ipa_uc_attach(pdev, + ol_cfg_ipa_uc_tx_buf_size(pdev->ctrl_pdev), + ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev), + ol_cfg_ipa_uc_tx_partition_base(pdev->ctrl_pdev)); + if (error) { + adf_os_print("HTT IPA UC TX attach fail code %d\n", error); + HTT_ASSERT0(0); + return error; + } + + /* RX resource attach */ + error = htt_rx_ipa_uc_attach(pdev, + ol_cfg_ipa_uc_rx_ind_ring_size(pdev->ctrl_pdev)); + if (error) { + adf_os_print("HTT IPA UC RX attach fail code %d\n", error); + htt_tx_ipa_uc_detach(pdev); + HTT_ASSERT0(0); + return error; + } + + return 0; /* success */ +} + +void +htt_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + /* TX IPA micro controller detach */ + htt_tx_ipa_uc_detach(pdev); + + /* RX IPA micro controller detach */ + htt_rx_ipa_uc_detach(pdev); +} + +/* + * Distribute micro controller resource to control module + */ +int +htt_ipa_uc_get_resource(htt_pdev_handle pdev, + u_int32_t *ce_sr_base_paddr, + u_int32_t *ce_sr_ring_size, + u_int32_t *ce_reg_paddr, + u_int32_t *tx_comp_ring_base_paddr, + u_int32_t *tx_comp_ring_size, + u_int32_t *tx_num_alloc_buffer, + u_int32_t *rx_rdy_ring_base_paddr, + u_int32_t *rx_rdy_ring_size, + u_int32_t *rx_proc_done_idx_paddr) +{ + /* Release allocated resource to client */ + *tx_comp_ring_base_paddr = + (u_int32_t)pdev->ipa_uc_tx_rsc.tx_comp_base.paddr; + *tx_comp_ring_size = + (u_int32_t)ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev); + *tx_num_alloc_buffer = + (u_int32_t)pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt; + *rx_rdy_ring_base_paddr = + (u_int32_t)pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr; + *rx_rdy_ring_size = + (u_int32_t)pdev->ipa_uc_rx_rsc.rx_ind_ring_size; + *rx_proc_done_idx_paddr = + (u_int32_t)pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr; + + /* Get copy engine, bus resource */ + HTCIpaGetCEResource(pdev->htc_pdev, + ce_sr_base_paddr, ce_sr_ring_size, ce_reg_paddr); + + + return 0; +} + +/* + * Distribute micro controller doorbell register to firmware + */ +int +htt_ipa_uc_set_doorbell_paddr(htt_pdev_handle pdev, + u_int32_t ipa_uc_tx_doorbell_paddr, + u_int32_t ipa_uc_rx_doorbell_paddr) +{ + pdev->ipa_uc_tx_rsc.tx_comp_idx_paddr = ipa_uc_tx_doorbell_paddr; + pdev->ipa_uc_rx_rsc.rx_rdy_idx_paddr = ipa_uc_rx_doorbell_paddr; + return 0; +} +#endif /* IPA_UC_OFFLOAD */ + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + +void htt_dump_bundle_stats(htt_pdev_handle pdev) +{ + HTCDumpBundleStats(pdev->htc_pdev); +} + +void htt_clear_bundle_stats(htt_pdev_handle pdev) +{ + HTCClearBundleStats(pdev->htc_pdev); +} +#endif + diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.h new file mode 100644 index 000000000000..aa968503817f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt.h @@ -0,0 +1,6924 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt.h + * + * @details the public header file of HTT layer + */ + +#ifndef _HTT_H_ +#define _HTT_H_ + +#include /* A_UINT32 */ +#include /* PREPACK, POSTPACK */ +#ifdef ATHR_WIN_NWF +#pragma warning( disable:4214 ) //bit field types other than int +#endif +#include "wlan_defs.h" +#include + +/* + * Unless explicitly specified to use 64 bits to represent physical addresses + * (or more precisely, bus addresses), default to 32 bits. + */ +#ifndef HTT_PADDR64 + #define HTT_PADDR64 0 +#endif + +#ifndef offsetof +#define offsetof(type, field) ((unsigned int)(&((type *)0)->field)) +#endif + +/* + * HTT version history: + * 1.0 initial numbered version + * 1.1 modifications to STATS messages. + * These modifications are not backwards compatible, but since the + * STATS messages themselves are non-essential (they are for debugging), + * the 1.1 version of the HTT message library as a whole is compatible + * with the 1.0 version. + * 1.2 reset mask IE added to STATS_REQ message + * 1.3 stat config IE added to STATS_REQ message + *---- + * 2.0 FW rx PPDU desc added to RX_IND message + * 2.1 Enable msdu_ext/frag_desc banking change for WIFI2.0 + *---- + * 3.0 Remove HTT_H2T_MSG_TYPE_MGMT_TX message + * 3.1 Added HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND message + * 3.2 Added HTT_H2T_MSG_TYPE_WDI_IPA_CFG, + * HTT_H2T_MSG_TYPE_WDI_IPA_OP_REQUEST messages + * 3.3 Added HTT_H2T_MSG_TYPE_AGGR_CFG_EX message + * 3.4 Added tx_compl_req flag in HTT tx descriptor + * 3.5 Added flush and fail stats in rx_reorder stats structure + * 3.6 Added frag flag in HTT RX INORDER PADDR IND header + * 3.7 Made changes to support EOS Mac_core 3.0 + * 3.8 Added txq_group information element definition; + * added optional txq_group suffix to TX_CREDIT_UPDATE_IND message + * 3.9 Added HTT_T2H CHAN_CHANGE message; + * Allow buffer addresses in bus-address format to be stored as + * either 32 bits or 64 bits. + * 3.10 Add optional TLV extensions to the VERSION_REQ and VERSION_CONF + * messages to specify which HTT options to use. + * Initial TLV options cover: + * - whether to use 32 or 64 bits to represent LL bus addresses + * - whether to use TX_COMPL_IND or TX_CREDIT_UPDATE_IND in HL systems + * - how many tx queue groups to use + * 3.11 Expand rx debug stats: + * - Expand the rx_reorder_stats struct with stats about successful and + * failed rx buffer allcoations. + * - Add a new rx_remote_buffer_mgmt_stats struct with stats about + * the supply, allocation, use, and recycling of rx buffers for the + * "remote ring" of rx buffers in host member in LL systems. + * Add RX_REMOTE_RING_BUFFER_INFO stats type for uploading these stats. + * 3.12 Add "rx offload packet error" message with initial "MIC error" subtype + * 3.13 Add constants + macros to support 64-bit address format for the + * tx fragments descriptor, the rx ring buffer, and the rx ring + * index shadow register. + * 3.14 Add a method for the host to provide detailed per-frame tx specs: + * - Add htt_tx_msdu_desc_ext_t struct def. + * - Add TLV to specify whether the target supports the HTT tx MSDU + * extension descriptor. + * - Change a reserved bit in the HTT tx MSDU descriptor to an + * "extension" bit, to specify whether a HTT tx MSDU extension + * descriptor is present. + * 3.15 Add HW rx desc info to per-MSDU info elems in RX_IN_ORD_PADDR_IND msg. + * (This allows the host to obtain key information about the MSDU + * from a memory location already in the cache, rather than taking a + * cache miss for each MSDU by reading the HW rx descs.) + * 3.16 Add htt_pkt_type_eth2 and define pkt_subtype flags to indicate + * whether a copy-engine classification result is appended to TX_FRM. + * 3.17 Add a version of the WDI_IPA_CFG message; add RX_RING2 to WDI_IPA_CFG + * 3.18 Add a PEER_DEL tx completion indication status, for HL cleanup of + * tx frames in the target after the peer has already been deleted. + * 3.19 Add HTT_DBG_STATS_RX_RATE_INFO_V2 and HTT_DBG_STATS_TX_RATE_INFO_V2 + * 3.20 Expand rx_reorder_stats. + * 3.21 Add optional rx channel spec to HL RX_IND. + * 3.22 Expand rx_reorder_stats + * (distinguish duplicates within vs. outside block ack window) + * 3.23 Add HTT_T2H_MSG_TYPE_RATE_REPORT to report peer justified rate. + * The justified rate is calculated by two steps. The first is to + * multiply user-rate by (1 - PER) and the other is to smooth the + * step 1's result by a low pass filter. + * This change allows HL download scheduling to consider the WLAN + * rate that will be used for transmitting the downloaded frames. + * 3.24 Expand rx_reorder_stats + * (add counter for decrypt / MIC errors) + * 3.25 Expand rx_reorder_stats + * (add counter of frames received into both local + remote rings) + * 3.26 Add stats struct for counting rx of tx BF, MU, SU, and NDPA frames + * (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT, rx_txbf_musu_ndpa_pkts_stats) + * 3.27 Add a new interface for flow-control. The following t2h messages have + * been included: HTT_T2H_MSG_TYPE_FLOW_POOL_MAP and + * HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP + */ +#define HTT_CURRENT_VERSION_MAJOR 3 +#define HTT_CURRENT_VERSION_MINOR 27 + +#define HTT_NUM_TX_FRAG_DESC 1024 + +#define HTT_WIFI_IP_VERSION(x,y) ((x) == (y)) + +#define HTT_CHECK_SET_VAL(field, val) \ + A_ASSERT(!((val) & ~((field ## _M) >> (field ## _S)))) + +/* macros to assist in sign-extending fields from HTT messages */ +#define HTT_SIGN_BIT_MASK(field) \ + ((field ## _M + (1 << field ## _S)) >> 1) +#define HTT_SIGN_BIT(_val, field) \ + (_val & HTT_SIGN_BIT_MASK(field)) +#define HTT_SIGN_BIT_UNSHIFTED(_val, field) \ + (HTT_SIGN_BIT(_val, field) >> field ## _S) +#define HTT_SIGN_BIT_UNSHIFTED_MINUS_ONE(_val, field) \ + (HTT_SIGN_BIT_UNSHIFTED(_val, field) - 1) +#define HTT_SIGN_BIT_EXTENSION(_val, field) \ + (~(HTT_SIGN_BIT_UNSHIFTED(_val, field) | \ + HTT_SIGN_BIT_UNSHIFTED_MINUS_ONE(_val, field))) +#define HTT_SIGN_BIT_EXTENSION_MASK(_val, field) \ + (HTT_SIGN_BIT_EXTENSION(_val, field) & ~(field ## _M >> field ## _S)) + + +/* + * TEMPORARY: + * Provide HTT_H2T_MSG_TYPE_MGMT_TX as an alias for + * DEPRECATED_HTT_H2T_MSG_TYPE_MGMT_TX until all code + * that refers to HTT_H2T_MSG_TYPE_MGMT_TX has been + * updated. + */ +#define HTT_H2T_MSG_TYPE_MGMT_TX DEPRECATED_HTT_H2T_MSG_TYPE_MGMT_TX + +/* + * TEMPORARY: + * Provide HTT_T2H_MSG_TYPE_RC_UPDATE_IND as an alias for + * DEPRECATED_HTT_T2H_MSG_TYPE_RC_UPDATE_IND until all code + * that refers to HTT_T2H_MSG_TYPE_RC_UPDATE_IND has been + * updated. + */ +#define HTT_T2H_MSG_TYPE_RC_UPDATE_IND DEPRECATED_HTT_T2H_MSG_TYPE_RC_UPDATE_IND + +/* HTT Access Category values */ +enum HTT_AC_WMM { + /* WMM Access Categories */ + HTT_AC_WMM_BE = 0x0, + HTT_AC_WMM_BK = 0x1, + HTT_AC_WMM_VI = 0x2, + HTT_AC_WMM_VO = 0x3, + /* extension Access Categories */ + HTT_AC_EXT_NON_QOS = 0x4, + HTT_AC_EXT_UCAST_MGMT = 0x5, + HTT_AC_EXT_MCAST_DATA = 0x6, + HTT_AC_EXT_MCAST_MGMT = 0x7, +}; +enum HTT_AC_WMM_MASK { + /* WMM Access Categories */ + HTT_AC_WMM_BE_MASK = (1 << HTT_AC_WMM_BE), + HTT_AC_WMM_BK_MASK = (1 << HTT_AC_WMM_BK), + HTT_AC_WMM_VI_MASK = (1 << HTT_AC_WMM_VI), + HTT_AC_WMM_VO_MASK = (1 << HTT_AC_WMM_VO), + /* extension Access Categories */ + HTT_AC_EXT_NON_QOS_MASK = (1 << HTT_AC_EXT_NON_QOS), + HTT_AC_EXT_UCAST_MGMT_MASK = (1 << HTT_AC_EXT_UCAST_MGMT), + HTT_AC_EXT_MCAST_DATA_MASK = (1 << HTT_AC_EXT_MCAST_DATA), + HTT_AC_EXT_MCAST_MGMT_MASK = (1 << HTT_AC_EXT_MCAST_MGMT), +}; +#define HTT_AC_MASK_WMM \ + (HTT_AC_WMM_BE_MASK | HTT_AC_WMM_BK_MASK | \ + HTT_AC_WMM_VI_MASK | HTT_AC_WMM_VO_MASK) +#define HTT_AC_MASK_EXT \ + (HTT_AC_EXT_NON_QOS_MASK | HTT_AC_EXT_UCAST_MGMT_MASK | \ + HTT_AC_EXT_MCAST_DATA_MASK | HTT_AC_EXT_MCAST_MGMT_MASK) +#define HTT_AC_MASK_ALL (HTT_AC_MASK_WMM | HTT_AC_MASK_EXT) + +/* + * htt_dbg_stats_type - + * bit positions for each stats type within a stats type bitmask + * The bitmask contains 24 bits. + */ +enum htt_dbg_stats_type { + HTT_DBG_STATS_WAL_PDEV_TXRX = 0, /* bit 0 -> 0x1 */ + HTT_DBG_STATS_RX_REORDER = 1, /* bit 1 -> 0x2 */ + HTT_DBG_STATS_RX_RATE_INFO = 2, /* bit 2 -> 0x4 */ + HTT_DBG_STATS_TX_PPDU_LOG = 3, /* bit 3 -> 0x8 */ + HTT_DBG_STATS_TX_RATE_INFO = 4, /* bit 4 -> 0x10 */ + HTT_DBG_STATS_TIDQ = 5, /* bit 5 -> 0x20 */ + HTT_DBG_STATS_TXBF_INFO = 6, /* bit 6 -> 0x40 */ + HTT_DBG_STATS_SND_INFO = 7, /* bit 7 -> 0x80 */ + HTT_DBG_STATS_ERROR_INFO = 8, /* bit 8 -> 0x100 */ + HTT_DBG_STATS_TX_SELFGEN_INFO = 9, /* bit 9 -> 0x200 */ + HTT_DBG_STATS_TX_MU_INFO = 10, /* bit 10 -> 0x400 */ + HTT_DBG_STATS_SIFS_RESP_INFO = 11, /* bit 11 -> 0x800 */ + HTT_DBG_STATS_RX_REMOTE_RING_BUFFER_INFO = 12, /* bit 12 -> 0x1000*/ + HTT_DBG_STATS_RX_RATE_INFO_V2 = 13, /* bit 13 -> 0x2000 */ + HTT_DBG_STATS_TX_RATE_INFO_V2 = 14, /* bit 14 -> 0x4000 */ + HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT = 15, /* bit 15 -> 0x8000 */ + /* bits 16-23 currently reserved */ + + /* keep this last */ + HTT_DBG_NUM_STATS +}; + +/*=== HTT option selection TLVs === + * Certain HTT messages have alternatives or options. + * For such cases, the host and target need to agree on which option to use. + * Option specification TLVs can be appended to the VERSION_REQ and + * VERSION_CONF messages to select options other than the default. + * These TLVs are entirely optional - if they are not provided, there is a + * well-defined default for each option. If they are provided, they can be + * provided in any order. Each TLV can be present or absent independent of + * the presence / absence of other TLVs. + * + * The HTT option selection TLVs use the following format: + * |31 16|15 8|7 0| + * |---------------------------------+----------------+----------------| + * | value (payload) | length | tag | + * |-------------------------------------------------------------------| + * The value portion need not be only 2 bytes; it can be extended by any + * integer number of 4-byte units. The total length of the TLV, including + * the tag and length fields, must be a multiple of 4 bytes. The length + * field specifies the total TLV size in 4-byte units. Thus, the typical + * TLV, with a 1-byte tag field, a 1-byte length field, and a 2-byte value + * field, would store 0x1 in its length field, to show that the TLV occupies + * a single 4-byte unit. + */ + +/*--- TLV header format - applies to all HTT option TLVs ---*/ + +enum HTT_OPTION_TLV_TAGS { + HTT_OPTION_TLV_TAG_RESERVED0 = 0x0, + HTT_OPTION_TLV_TAG_LL_BUS_ADDR_SIZE = 0x1, + HTT_OPTION_TLV_TAG_HL_SUPPRESS_TX_COMPL_IND = 0x2, + HTT_OPTION_TLV_TAG_MAX_TX_QUEUE_GROUPS = 0x3, + HTT_OPTION_TLV_TAG_SUPPORT_TX_MSDU_DESC_EXT = 0x4, +}; + +PREPACK struct htt_option_tlv_header_t { + A_UINT8 tag; + A_UINT8 length; +} POSTPACK; + +#define HTT_OPTION_TLV_TAG_M 0x000000ff +#define HTT_OPTION_TLV_TAG_S 0 +#define HTT_OPTION_TLV_LENGTH_M 0x0000ff00 +#define HTT_OPTION_TLV_LENGTH_S 8 +/* + * value0 - 16 bit value field stored in word0 + * The TLV's value field may be longer than 2 bytes, in which case + * the remainder of the value is stored in word1, word2, etc. + */ +#define HTT_OPTION_TLV_VALUE0_M 0xffff0000 +#define HTT_OPTION_TLV_VALUE0_S 16 + +#define HTT_OPTION_TLV_TAG_SET(word, tag) \ + do { \ + HTT_CHECK_SET_VAL(HTT_OPTION_TLV_TAG, tag); \ + (word) |= ((tag) << HTT_OPTION_TLV_TAG_S); \ + } while (0) +#define HTT_OPTION_TLV_TAG_GET(word) \ + (((word) & HTT_OPTION_TLV_TAG_M) >> HTT_OPTION_TLV_TAG_S) + +#define HTT_OPTION_TLV_LENGTH_SET(word, tag) \ + do { \ + HTT_CHECK_SET_VAL(HTT_OPTION_TLV_LENGTH, tag); \ + (word) |= ((tag) << HTT_OPTION_TLV_LENGTH_S); \ + } while (0) +#define HTT_OPTION_TLV_LENGTH_GET(word) \ + (((word) & HTT_OPTION_TLV_LENGTH_M) >> HTT_OPTION_TLV_LENGTH_S) + +#define HTT_OPTION_TLV_VALUE0_SET(word, tag) \ + do { \ + HTT_CHECK_SET_VAL(HTT_OPTION_TLV_VALUE0, tag); \ + (word) |= ((tag) << HTT_OPTION_TLV_VALUE0_S); \ + } while (0) +#define HTT_OPTION_TLV_VALUE0_GET(word) \ + (((word) & HTT_OPTION_TLV_VALUE0_M) >> HTT_OPTION_TLV_VALUE0_S) + +/*--- format of specific HTT option TLVs ---*/ + +/* + * HTT option TLV for specifying LL bus address size + * Some chips require bus addresses used by the target to access buffers + * within the host's memory to be 32 bits; others require bus addresses + * used by the target to access buffers within the host's memory to be + * 64 bits. + * The LL_BUS_ADDR_SIZE TLV can be sent from the target to the host as + * a suffix to the VERSION_CONF message to specify which bus address format + * the target requires. + * If this LL_BUS_ADDR_SIZE TLV is not sent by the target, the host should + * default to providing bus addresses to the target in 32-bit format. + */ +enum HTT_OPTION_TLV_LL_BUS_ADDR_SIZE_VALUES { + HTT_OPTION_TLV_LL_BUS_ADDR_SIZE32 = 0x0, + HTT_OPTION_TLV_LL_BUS_ADDR_SIZE64 = 0x1, +}; +PREPACK struct htt_option_tlv_ll_bus_addr_size_t { + struct htt_option_tlv_header_t hdr; + A_UINT16 ll_bus_addr_size; /* LL_BUS_ADDR_SIZE_VALUES enum */ +} POSTPACK; + +/* + * HTT option TLV for specifying whether HL systems should indicate + * over-the-air tx completion for individual frames, or should instead + * send a bulk TX_CREDIT_UPDATE_IND except when the host explicitly + * requests an OTA tx completion for a particular tx frame. + * This option does not apply to LL systems, where the TX_COMPL_IND + * is mandatory. + * This option is primarily intended for HL systems in which the tx frame + * downloads over the host --> target bus are as slow as or slower than + * the transmissions over the WLAN PHY. For cases where the bus is faster + * than the WLAN PHY, the target will transmit relatively large A-MPDUs, + * and consquently will send one TX_COMPL_IND message that covers several + * tx frames. For cases where the WLAN PHY is faster than the bus, + * the target will end up transmitting very short A-MPDUs, and consequently + * sending many TX_COMPL_IND messages, which each cover a very small number + * of tx frames. + * The HL_SUPPRESS_TX_COMPL_IND TLV can be sent by the host to the target as + * a suffix to the VERSION_REQ message to request whether the host desires to + * use TX_CREDIT_UPDATE_IND rather than TX_COMPL_IND. The target can then + * send a HTT_SUPPRESS_TX_COMPL_IND TLV to the host as a suffix to the + * VERSION_CONF message to confirm whether TX_CREDIT_UPDATE_IND will be used + * rather than TX_COMPL_IND. TX_CREDIT_UPDATE_IND shall only be used if the + * host sends a HL_SUPPRESS_TX_COMPL_IND TLV requesting use of + * TX_CREDIT_UPDATE_IND, and the target sends a HL_SUPPRESS_TX_COMPLE_IND TLV + * back to the host confirming use of TX_CREDIT_UPDATE_IND. + * Lack of a HL_SUPPRESS_TX_COMPL_IND TLV from either host --> target or + * target --> host is equivalent to a HL_SUPPRESS_TX_COMPL_IND that + * explicitly specifies HL_ALLOW_TX_COMPL_IND in the value payload of the + * TLV. + */ +enum HTT_OPTION_TLV_HL_SUPPRESS_TX_COMPL_IND_VALUES { + HTT_OPTION_TLV_HL_ALLOW_TX_COMPL_IND = 0x0, + HTT_OPTION_TLV_HL_SUPPRESS_TX_COMPL_IND = 0x1, +}; +PREPACK struct htt_option_tlv_hl_suppress_tx_compl_ind_t { + struct htt_option_tlv_header_t hdr; + A_UINT16 hl_suppress_tx_compl_ind; /* HL_SUPPRESS_TX_COMPL_IND enum */ +} POSTPACK; + +/* + * HTT option TLV for specifying how many tx queue groups the target + * may establish. + * This TLV specifies the maximum value the target may send in the + * txq_group_id field of any TXQ_GROUP information elements sent by + * the target to the host. This allows the host to pre-allocate an + * appropriate number of tx queue group structs. + * + * The MAX_TX_QUEUE_GROUPS_TLV can be sent from the host to the target as + * a suffix to the VERSION_REQ message to specify whether the host supports + * tx queue groups at all, and if so if there is any limit on the number of + * tx queue groups that the host supports. + * The MAX_TX_QUEUE_GROUPS TLV can be sent from the target to the host as + * a suffix to the VERSION_CONF message. If the host has specified in the + * VER_REQ message a limit on the number of tx queue groups the host can + * supprt, the target shall limit its specification of the maximum tx groups + * to be no larger than this host-specified limit. + * + * If the target does not provide a MAX_TX_QUEUE_GROUPS TLV, then the host + * shall preallocate 4 tx queue group structs, and the target shall not + * specify a txq_group_id larger than 3. + */ +enum HTT_OPTION_TLV_MAX_TX_QUEUE_GROUPS_VALUES { + HTT_OPTION_TLV_TX_QUEUE_GROUPS_UNSUPPORTED = 0, + /* + * values 1 through N specify the max number of tx queue groups + * the sender supports + */ + HTT_OPTION_TLV_TX_QUEUE_GROUPS_UNLIMITED = 0xffff, +}; +/* TEMPORARY backwards-compatibility alias for a typo fix - + * The htt_option_tlv_mac_tx_queue_groups_t typo has been corrected + * to htt_option_tlv_max_tx_queue_groups_t, but an alias is provided + * to support the old name (with the typo) until all references to the + * old name are replaced with the new name. + */ +#define htt_option_tlv_mac_tx_queue_groups_t htt_option_tlv_max_tx_queue_groups_t +PREPACK struct htt_option_tlv_max_tx_queue_groups_t { + struct htt_option_tlv_header_t hdr; + A_UINT16 max_tx_queue_groups; /* max txq_group_id + 1 */ +} POSTPACK; + +/* + * HTT option TLV for specifying whether the target supports an extended + * version of the HTT tx descriptor. If the target provides this TLV + * and specifies in the TLV that the target supports an extended version + * of the HTT tx descriptor, the target must check the "extension" bit in + * the HTT tx descriptor, and if the extension bit is set, to expect a + * HTT tx MSDU extension descriptor immediately following the HTT tx MSDU + * descriptor. Furthermore, the target must provide room for the HTT + * tx MSDU extension descriptor in the target's TX_FRM buffer. + * This option is intended for systems where the host needs to explicitly + * control the transmission parameters such as tx power for individual + * tx frames. + * The SUPPORT_TX_MSDU_DESC_EXT TLB can be sent by the target to the host + * as a suffix to the VERSION_CONF message to explicitly specify whether + * the target supports the HTT tx MSDU extension descriptor. + * Lack of a SUPPORT_TX_MSDU_DESC_EXT from the target shall be interpreted + * by the host as lack of target support for the HTT tx MSDU extension + * descriptor; the host shall provide HTT tx MSDU extension descriptors in + * the HTT_H2T TX_FRM messages only if the target indicates it supports + * the HTT tx MSDU extension descriptor. + * The host is not required to provide the HTT tx MSDU extension descriptor + * just because the target supports it; the target must check the + * "extension" bit in the HTT tx MSDU descriptor to determine whether an + * extension descriptor is present. + */ +enum HTT_OPTION_TLV_SUPPORT_TX_MSDU_DESC_EXT_VALUES { + HTT_OPTION_TLV_TX_MSDU_DESC_EXT_NO_SUPPORT = 0x0, + HTT_OPTION_TLV_TX_MSDU_DESC_EXT_SUPPORT = 0x1, +}; +PREPACK struct htt_option_tlv_support_tx_msdu_desc_ext_t { + struct htt_option_tlv_header_t hdr; + A_UINT16 tx_msdu_desc_ext_support; /* SUPPORT_TX_MSDU_DESC_EXT enum */ +} POSTPACK; + + +/*=== host -> target messages ===============================================*/ + +enum htt_h2t_msg_type { + HTT_H2T_MSG_TYPE_VERSION_REQ = 0x0, + HTT_H2T_MSG_TYPE_TX_FRM = 0x1, + HTT_H2T_MSG_TYPE_RX_RING_CFG = 0x2, + HTT_H2T_MSG_TYPE_STATS_REQ = 0x3, + HTT_H2T_MSG_TYPE_SYNC = 0x4, + HTT_H2T_MSG_TYPE_AGGR_CFG = 0x5, + HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG = 0x6, + DEPRECATED_HTT_H2T_MSG_TYPE_MGMT_TX = 0x7, /* no longer used */ + HTT_H2T_MSG_TYPE_WDI_IPA_CFG = 0x8, + HTT_H2T_MSG_TYPE_WDI_IPA_OP_REQ = 0x9, + HTT_H2T_MSG_TYPE_AGGR_CFG_EX = 0xa, /* per vdev amsdu subfrm limit */ + /* keep this last */ + HTT_H2T_NUM_MSGS +}; + +/* + * HTT host to target message type - + * stored in bits 7:0 of the first word of the message + */ +#define HTT_H2T_MSG_TYPE_M 0xff +#define HTT_H2T_MSG_TYPE_S 0 + +#define HTT_H2T_MSG_TYPE_SET(word, msg_type) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_MSG_TYPE, msg_type); \ + (word) |= ((msg_type) << HTT_H2T_MSG_TYPE_S); \ + } while (0) +#define HTT_H2T_MSG_TYPE_GET(word) \ + (((word) & HTT_H2T_MSG_TYPE_M) >> HTT_H2T_MSG_TYPE_S) + +/** + * @brief target -> host version number request message definition + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | reserved | msg type | + * |-------------------------------------------------------------------| + * : option request TLV (optional) | + * :...................................................................: + * + * The VER_REQ message may consist of a single 4-byte word, or may be + * extended with TLVs that specify which HTT options the host is requesting + * from the target. + * The following option TLVs may be appended to the VER_REQ message: + * - HL_SUPPRESS_TX_COMPL_IND + * - HL_MAX_TX_QUEUE_GROUPS + * These TLVs may appear in an arbitrary order. Any number of these TLVs + * may be appended to the VER_REQ message (but only one TLV of each type). + * + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a version number request message + * Value: 0x0 + */ + +#define HTT_VER_REQ_BYTES 4 + +/* TBDXXX: figure out a reasonable number */ +#define HTT_HL_DATA_SVC_PIPE_DEPTH 24 +#define HTT_LL_DATA_SVC_PIPE_DEPTH 64 + +/** + * @brief HTT tx MSDU descriptor + * + * @details + * The HTT tx MSDU descriptor is created by the host HTT SW for each + * tx MSDU. The HTT tx MSDU descriptor contains the information that + * the target firmware needs for the FW's tx processing, particularly + * for creating the HW msdu descriptor. + * The same HTT tx descriptor is used for HL and LL systems, though + * a few fields within the tx descriptor are used only by LL or + * only by HL. + * The HTT tx descriptor is defined in two manners: by a struct with + * bitfields, and by a series of [dword offset, bit mask, bit shift] + * definitions. + * The target should use the struct def, for simplicitly and clarity, + * but the host shall use the bit-mast + bit-shift defs, to be endian- + * neutral. Specifically, the host shall use the get/set macros built + * around the mask + shift defs. + */ +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_80211_HDR_S 0 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_80211_HDR_M 0x1 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_AGGR_S 1 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_AGGR_M 0x2 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S 2 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_M 0x4 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_CLASSIFY_S 3 +#define HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_CLASSIFY_M 0x8 + +#define HTT_TX_VDEV_ID_WORD 0 +#define HTT_TX_VDEV_ID_MASK 0x3f +#define HTT_TX_VDEV_ID_SHIFT 16 + +#define HTT_TX_L3_CKSUM_OFFLOAD 1 +#define HTT_TX_L4_CKSUM_OFFLOAD 2 + +#define HTT_TX_MSDU_LEN_DWORD 1 +#define HTT_TX_MSDU_LEN_MASK 0xffff; + +/* + * HTT_VAR_PADDR macros + * Allow physical / bus addresses to be either a single 32-bit value, + * or a 64-bit value, stored as a little-endian lo,hi pair of 32-bit parts + */ +#define HTT_VAR_PADDR32(var_name) \ + A_UINT32 var_name +#define HTT_VAR_PADDR64_LE(var_name) \ + struct { \ + /* little-endian: lo precedes hi */ \ + A_UINT32 lo; \ + A_UINT32 hi; \ + } var_name + +/* + * TEMPLATE_HTT_TX_MSDU_DESC_T: + * This macro defines a htt_tx_msdu_descXXX_t in which any physical + * addresses are stored in a XXX-bit field. + * This macro is used to define both htt_tx_msdu_desc32_t and + * htt_tx_msdu_desc64_t structs. + */ +#define TEMPLATE_HTT_TX_MSDU_DESC_T(_paddr_bits_, _paddr__frags_desc_ptr_) \ +PREPACK struct htt_tx_msdu_desc ## _paddr_bits_ ## _t \ +{ \ + /* DWORD 0: flags and meta-data */ \ + A_UINT32 \ + msg_type: 8, /* HTT_H2T_MSG_TYPE_TX_FRM */ \ + \ + /* pkt_subtype - \ + * Detailed specification of the tx frame contents, extending the \ + * general specification provided by pkt_type. \ + * FIX THIS: ADD COMPLETE SPECS FOR THIS FIELDS VALUE, e.g. \ + * pkt_type | pkt_subtype \ + * ============================================================== \ + * 802.3 | bit 0:3 - Reserved \ + * | bit 4: 0x0 - Copy-Engine Classification Results \ + * | not appended to the HTT message \ + * | 0x1 - Copy-Engine Classification Results \ + * | appended to the HTT message in the \ + * | format: \ + * | [HTT tx desc, frame header, \ + * | CE classification results] \ + * | The CE classification results begin \ + * | at the next 4-byte boundary after \ + * | the frame header. \ + * ------------+------------------------------------------------- \ + * Eth2 | bit 0:3 - Reserved \ + * | bit 4: 0x0 - Copy-Engine Classification Results \ + * | not appended to the HTT message \ + * | 0x1 - Copy-Engine Classification Results \ + * | appended to the HTT message. \ + * | See the above specification of the \ + * | CE classification results location. \ + * ------------+------------------------------------------------- \ + * native WiFi | bit 0:3 - Reserved \ + * | bit 4: 0x0 - Copy-Engine Classification Results \ + * | not appended to the HTT message \ + * | 0x1 - Copy-Engine Classification Results \ + * | appended to the HTT message. \ + * | See the above specification of the \ + * | CE classification results location. \ + * ------------+------------------------------------------------- \ + * mgmt | 0x0 - 802.11 MAC header absent \ + * | 0x1 - 802.11 MAC header present \ + * ------------+------------------------------------------------- \ + * raw | bit 0: 0x0 - 802.11 MAC header absent \ + * | 0x1 - 802.11 MAC header present \ + * | bit 1: 0x0 - allow aggregation \ + * | 0x1 - don't allow aggregation \ + * | bit 2: 0x0 - perform encryption \ + * | 0x1 - don't perform encryption \ + * | bit 3: 0x0 - perform tx classification / queuing \ + * | 0x1 - don't perform tx classification; \ + * | insert the frame into the "misc" \ + * | tx queue \ + * | bit 4: 0x0 - Copy-Engine Classification Results \ + * | not appended to the HTT message \ + * | 0x1 - Copy-Engine Classification Results \ + * | appended to the HTT message. \ + * | See the above specification of the \ + * | CE classification results location. \ + */ \ + pkt_subtype: 5, \ + \ + /* pkt_type - \ + * General specification of the tx frame contents. \ + * The htt_pkt_type enum should be used to specify and check the \ + * value of this field. \ + */ \ + pkt_type: 3, \ + \ + /* vdev_id - \ + * ID for the vdev that is sending this tx frame. \ + * For certain non-standard packet types, e.g. pkt_type == raw \ + * and (pkt_subtype >> 3) == 1, this field is not relevant/valid. \ + * This field is used primarily for determining where to queue \ + * broadcast and multicast frames. \ + */ \ + vdev_id: 6, \ + /* ext_tid - \ + * The extended traffic ID. \ + * If the TID is unknown, the extended TID is set to \ + * HTT_TX_EXT_TID_INVALID. \ + * If the tx frame is QoS data, then the extended TID has the 0-15 \ + * value of the QoS TID. \ + * If the tx frame is non-QoS data, then the extended TID is set to \ + * HTT_TX_EXT_TID_NON_QOS. \ + * If the tx frame is multicast or broadcast, then the extended TID \ + * is set to HTT_TX_EXT_TID_MCAST_BCAST. \ + */ \ + ext_tid: 5, \ + \ + /* postponed - \ + * This flag indicates whether the tx frame has been downloaded to \ + * the target before but discarded by the target, and now is being \ + * downloaded again; or if this is a new frame that is being \ + * downloaded for the first time. \ + * This flag allows the target to determine the correct order for \ + * transmitting new vs. old frames. \ + * value: 0 -> new frame, 1 -> re-send of a previously sent frame \ + * This flag only applies to HL systems, since in LL systems, \ + * the tx flow control is handled entirely within the target. \ + */ \ + postponed: 1, \ + \ + /* extension - \ + * This flag indicates whether a HTT tx MSDU extension descriptor \ + * (htt_tx_msdu_desc_ext_t) follows this HTT tx MSDU descriptor. \ + * \ + * 0x0 - no extension MSDU descriptor is present \ + * 0x1 - an extension MSDU descriptor immediately follows the \ + * regular MSDU descriptor \ + */ \ + extension: 1, \ + \ + /* cksum_offload - \ + * This flag indicates whether checksum offload is enabled or not \ + * for this frame. Target FW use this flag to turn on HW checksumming \ + * 0x0 - No checksum offload \ + * 0x1 - L3 header checksum only \ + * 0x2 - L4 checksum only \ + * 0x3 - L3 header checksum + L4 checksum \ + */ \ + cksum_offload: 2, \ + \ + /* tx_comp_req - \ + * This flag indicates whether Tx Completion \ + * from fw is required or not. \ + * This flag is only relevant if tx completion is not \ + * universally enabled. \ + * For all LL systems, tx completion is mandatory, \ + * so this flag will be irrelevant. \ + * For HL systems tx completion is optional, but HL systems in which \ + * the bus throughput exceeds the WLAN throughput will \ + * probably want to always use tx completion, and thus \ + * would not check this flag. \ + * This flag is required when tx completions are not used universally, \ + * but are still required for certain tx frames for which \ + * an OTA delivery acknowledgment is needed by the host. \ + * In practice, this would be for HL systems in which the \ + * bus throughput is less than the WLAN throughput. \ + * \ + * 0x0 - Tx Completion Indication from Fw not required \ + * 0x1 - Tx Completion Indication from Fw is required \ + */ \ + tx_compl_req: 1; \ + \ + \ + /* DWORD 1: MSDU length and ID */ \ + A_UINT32 \ + len: 16, /* MSDU length, in bytes */ \ + id: 16; /* MSDU ID used to identify the MSDU to the host, \ + * and this id is used to calculate fragmentation \ + * descriptor pointer inside the target based on \ + * the base address, configured inside the target. \ + */ \ + \ + /* DWORD 2 (or 2-3): fragmentation descriptor bus address */ \ + /* frags_desc_ptr - \ + * The fragmentation descriptor pointer tells the HW's MAC DMA \ + * where the tx frame's fragments reside in memory. \ + * This field only applies to LL systems, since in HL systems the \ + * (degenerate single-fragment) fragmentation descriptor is created \ + * within the target. \ + */ \ + _paddr__frags_desc_ptr_; \ + \ + /* DWORD 3 (or 4): peerid, chanfreq */ \ + /* \ + * Peer ID : Target can use this value to know which peer-id packet \ + * destined to. \ + * It's intended to be specified by host in case of NAWDS. \ + */ \ + A_UINT16 peerid; \ + \ + /* \ + * Channel frequency: This identifies the desired channel \ + * frequency (in mhz) for tx frames. This is used by FW to help \ + * determine when it is safe to transmit or drop frames for \ + * off-channel operation. \ + * The default value of zero indicates to FW that the corresponding \ + * VDEV's home channel (if there is one) is the desired channel \ + * frequency. \ + */ \ + A_UINT16 chanfreq; \ + \ + /* Reason reserved is commented is increasing the htt structure size \ + * leads to some wierd issues. Contact Raj/Kyeyoon for more info \ + * A_UINT32 reserved_dword3_bits0_31; \ + */ \ +} POSTPACK +/* define a htt_tx_msdu_desc32_t type */ +TEMPLATE_HTT_TX_MSDU_DESC_T(32, HTT_VAR_PADDR32(frags_desc_ptr)); +/* define a htt_tx_msdu_desc64_t type */ +TEMPLATE_HTT_TX_MSDU_DESC_T(64, HTT_VAR_PADDR64_LE(frags_desc_ptr)); +/* + * Make htt_tx_msdu_desc_t be an alias for either + * htt_tx_msdu_desc32_t or htt_tx_msdu_desc64_t + */ +#if HTT_PADDR64 + #define htt_tx_msdu_desc_t htt_tx_msdu_desc64_t +#else + #define htt_tx_msdu_desc_t htt_tx_msdu_desc32_t +#endif + +/* decriptor information for Management frame*/ +/* + * THIS htt_mgmt_tx_desc_t STRUCT IS DEPRECATED - DON'T USE IT. + * BOTH MANAGEMENT AND DATA FRAMES SHOULD USE htt_tx_msdu_desc_t. + */ +#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 +extern A_UINT32 mgmt_hdr_len; +PREPACK struct htt_mgmt_tx_desc_t { + A_UINT32 msg_type; +#if HTT_PADDR64 + A_UINT64 frag_paddr; /* DMAble address of the data */ +#else + A_UINT32 frag_paddr; /* DMAble address of the data */ +#endif + A_UINT32 desc_id; /* returned to host during completion + * to free the meory*/ + A_UINT32 len; /* Fragment length */ + A_UINT32 vdev_id; /* virtual device ID*/ + A_UINT8 hdr[HTT_MGMT_FRM_HDR_DOWNLOAD_LEN]; /* frm header */ +} POSTPACK; + +PREPACK struct htt_mgmt_tx_compl_ind { + A_UINT32 desc_id; + A_UINT32 status; +} POSTPACK; + +/* + * This SDU header size comes from the summation of the following: + * 1. Max of: + * a. Native WiFi header, for native WiFi frames: 24 bytes + * (frame control, duration / ID, addr1, addr2, addr3, seq ctrl, addr4) + * b. 802.11 header, for raw frames: 36 bytes + * (frame control, duration / ID, addr1, addr2, addr3, seq ctrl, addr4, + * QoS header, HT header) + * c. 802.3 header, for ethernet frames: 14 bytes + * (destination address, source address, ethertype / length) + * 2. Max of: + * a. IPv4 header, up through the DiffServ Code Point: 2 bytes + * b. IPv6 header, up through the Traffic Class: 2 bytes + * 3. 802.1Q VLAN header: 4 bytes + * 4. LLC/SNAP header: 8 bytes + */ +#define HTT_TX_HDR_SIZE_NATIVE_WIFI 30 +#define HTT_TX_HDR_SIZE_802_11_RAW 36 +#define HTT_TX_HDR_SIZE_ETHERNET 14 + +#define HTT_TX_HDR_SIZE_OUTER_HDR_MAX HTT_TX_HDR_SIZE_802_11_RAW +A_COMPILE_TIME_ASSERT( + htt_encap_hdr_size_max_check_nwifi, + HTT_TX_HDR_SIZE_OUTER_HDR_MAX >= HTT_TX_HDR_SIZE_NATIVE_WIFI); +A_COMPILE_TIME_ASSERT( + htt_encap_hdr_size_max_check_enet, + HTT_TX_HDR_SIZE_OUTER_HDR_MAX >= HTT_TX_HDR_SIZE_ETHERNET); + +#define HTT_HL_TX_HDR_SIZE_IP 1600 /* also include payload */ +#define HTT_LL_TX_HDR_SIZE_IP 16 /* up to the end of UDP header for IPv4 case */ + +#define HTT_TX_HDR_SIZE_802_1Q 4 +#define HTT_TX_HDR_SIZE_LLC_SNAP 8 + + +#define HTT_COMMON_TX_FRM_HDR_LEN \ + (HTT_TX_HDR_SIZE_OUTER_HDR_MAX + \ + HTT_TX_HDR_SIZE_802_1Q + \ + HTT_TX_HDR_SIZE_LLC_SNAP) + +#define HTT_HL_TX_FRM_HDR_LEN \ + (HTT_COMMON_TX_FRM_HDR_LEN + HTT_HL_TX_HDR_SIZE_IP) + +#define HTT_LL_TX_FRM_HDR_LEN \ + (HTT_COMMON_TX_FRM_HDR_LEN + HTT_LL_TX_HDR_SIZE_IP) + +#define HTT_TX_DESC_LEN sizeof(struct htt_tx_msdu_desc_t) + +/* dword 0 */ +#define HTT_TX_DESC_PKT_SUBTYPE_OFFSET_BYTES 0 +#define HTT_TX_DESC_PKT_SUBTYPE_OFFSET_DWORD 0 +#define HTT_TX_DESC_PKT_SUBTYPE_M 0x00001f00 +#define HTT_TX_DESC_PKT_SUBTYPE_S 8 + +#define HTT_TX_DESC_NO_ENCRYPT_OFFSET_BYTES 0 +#define HTT_TX_DESC_NO_ENCRYPT_OFFSET_DWORD 0 +#define HTT_TX_DESC_NO_ENCRYPT_M 0x00000400 +#define HTT_TX_DESC_NO_ENCRYPT_S 10 + +#define HTT_TX_DESC_PKT_TYPE_OFFSET_BYTES 0 +#define HTT_TX_DESC_PKT_TYPE_OFFSET_DWORD 0 +#define HTT_TX_DESC_PKT_TYPE_M 0x0000e000 +#define HTT_TX_DESC_PKT_TYPE_S 13 + +#define HTT_TX_DESC_VDEV_ID_OFFSET_BYTES 0 +#define HTT_TX_DESC_VDEV_ID_OFFSET_DWORD 0 +#define HTT_TX_DESC_VDEV_ID_M 0x003f0000 +#define HTT_TX_DESC_VDEV_ID_S 16 + +#define HTT_TX_DESC_EXT_TID_OFFSET_BYTES 0 +#define HTT_TX_DESC_EXT_TID_OFFSET_DWORD 0 +#define HTT_TX_DESC_EXT_TID_M 0x07c00000 +#define HTT_TX_DESC_EXT_TID_S 22 + +#define HTT_TX_DESC_POSTPONED_OFFSET_BYTES 0 +#define HTT_TX_DESC_POSTPONED_OFFSET_DWORD 0 +#define HTT_TX_DESC_POSTPONED_M 0x08000000 +#define HTT_TX_DESC_POSTPONED_S 27 + +#define HTT_TX_DESC_CKSUM_OFFLOAD_OFFSET_BYTES 0 +#define HTT_TX_DESC_CKSUM_OFFLOAD_OFFSET_DWORD 0 +#define HTT_TX_DESC_CKSUM_OFFLOAD_M 0x60000000 +#define HTT_TX_DESC_CKSUM_OFFLOAD_S 29 + +#define HTT_TX_DESC_TX_COMP_OFFSET_BYTES 0 +#define HTT_TX_DESC_TX_COMP_OFFSET_DWORD 0 +#define HTT_TX_DESC_TX_COMP_M 0x80000000 +#define HTT_TX_DESC_TX_COMP_S 31 + +/* dword 1 */ +#define HTT_TX_DESC_FRM_LEN_OFFSET_BYTES 4 +#define HTT_TX_DESC_FRM_LEN_OFFSET_DWORD 1 +#define HTT_TX_DESC_FRM_LEN_M 0x0000ffff +#define HTT_TX_DESC_FRM_LEN_S 0 + +#define HTT_TX_DESC_FRM_ID_OFFSET_BYTES 4 +#define HTT_TX_DESC_FRM_ID_OFFSET_DWORD 1 +#define HTT_TX_DESC_FRM_ID_M 0xffff0000 +#define HTT_TX_DESC_FRM_ID_S 16 + +/* dword 2 */ +#define HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_BYTES 8 +#define HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD 2 +/* for systems using 64-bit format for bus addresses */ +#define HTT_TX_DESC_FRAGS_DESC_PADDR_HI_M 0xffffffff +#define HTT_TX_DESC_FRAGS_DESC_PADDR_HI_S 0 +#define HTT_TX_DESC_FRAGS_DESC_PADDR_LO_M 0xffffffff +#define HTT_TX_DESC_FRAGS_DESC_PADDR_LO_S 0 +/* for systems using 32-bit format for bus addresses */ +#define HTT_TX_DESC_FRAGS_DESC_PADDR_M 0xffffffff +#define HTT_TX_DESC_FRAGS_DESC_PADDR_S 0 + +/* dword 3 */ +#define HTT_TX_DESC_PEER_ID_OFFSET_BYTES_64 16 +#define HTT_TX_DESC_PEER_ID_OFFSET_BYTES_32 12 +#define HTT_TX_DESC_PEER_ID_OFFSET_DWORD_64 \ + (HTT_TX_DESC_PEER_ID_OFFSET_BYTES_64 >> 2) +#define HTT_TX_DESC_PEER_ID_OFFSET_DWORD_32 \ + (HTT_TX_DESC_PEER_ID_OFFSET_BYTES_32 >> 2) + +#if HTT_PADDR64 +#define HTT_TX_DESC_PEER_ID_OFFSET_BYTES HTT_TX_DESC_PEER_ID_OFFSET_BYTES_64 +#define HTT_TX_DESC_PEER_ID_OFFSET_DWORD HTT_TX_DESC_PEER_ID_OFFSET_DWORD_64 +#else +#define HTT_TX_DESC_PEER_ID_OFFSET_BYTES HTT_TX_DESC_PEER_ID_OFFSET_BYTES_32 +#define HTT_TX_DESC_PEER_ID_OFFSET_DWORD HTT_TX_DESC_PEER_ID_OFFSET_DWORD_32 +#endif + +#define HTT_TX_DESC_PEER_ID_M 0x0000ffff +#define HTT_TX_DESC_PEER_ID_S 0 + /* + * TEMPORARY: + * The original definitions for the PEER_ID fields contained typos + * (with _DESC_PADDR appended to this PEER_ID field name). + * Retain deprecated original names for PEER_ID fields until all code that + * refers to them has been updated. + */ + #define HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES \ + HTT_TX_DESC_PEER_ID_OFFSET_BYTES + #define HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_DWORD \ + HTT_TX_DESC_PEER_ID_OFFSET_DWORD + #define HTT_TX_DESC_PEERID_DESC_PADDR_M \ + HTT_TX_DESC_PEER_ID_M + #define HTT_TX_DESC_PEERID_DESC_PADDR_S \ + HTT_TX_DESC_PEER_ID_S + +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES_64 16 // to dword with chan freq +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES_32 12 // to dword with chan freq +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_DWORD_64 \ + (HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES_64 >> 2) +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_DWORD_32 \ + (HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES_32 >> 2) + +#if HTT_PADDR64 +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES_64 +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_DWORD HTT_TX_DESC_CHAN_FREQ_OFFSET_DWORD_64 +#else +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES_32 +#define HTT_TX_DESC_CHAN_FREQ_OFFSET_DWORD HTT_TX_DESC_CHAN_FREQ_OFFSET_DWORD_32 +#endif + +#define HTT_TX_DESC_CHAN_FREQ_M 0xffff0000 +#define HTT_TX_DESC_CHAN_FREQ_S 16 + +#define HTT_TX_DESC_PKT_SUBTYPE_GET(_var) \ + (((_var) & HTT_TX_DESC_PKT_SUBTYPE_M) >> HTT_TX_DESC_PKT_SUBTYPE_S) +#define HTT_TX_DESC_PKT_SUBTYPE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_PKT_SUBTYPE, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_PKT_SUBTYPE_S)); \ + } while (0) + +#define HTT_TX_DESC_NO_ENCRYPT_GET(_var) \ + (((_var) & HTT_TX_DESC_NO_ENCRYPT_M) >> HTT_TX_DESC_NO_ENCRYPT_S) +#define HTT_TX_DESC_NO_ENCRYPT_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_NO_ENCRYPT, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_NO_ENCRYPT_S)); \ + } while (0) + +#define HTT_TX_DESC_PKT_TYPE_GET(_var) \ + (((_var) & HTT_TX_DESC_PKT_TYPE_M) >> HTT_TX_DESC_PKT_TYPE_S) +#define HTT_TX_DESC_PKT_TYPE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_PKT_TYPE, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_PKT_TYPE_S)); \ + } while (0) + +#define HTT_TX_DESC_VDEV_ID_GET(_var) \ + (((_var) & HTT_TX_DESC_VDEV_ID_M) >> HTT_TX_DESC_VDEV_ID_S) +#define HTT_TX_DESC_VDEV_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_VDEV_ID, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_VDEV_ID_S)); \ + } while (0) + +#define HTT_TX_DESC_EXT_TID_GET(_var) \ + (((_var) & HTT_TX_DESC_EXT_TID_M) >> HTT_TX_DESC_EXT_TID_S) +#define HTT_TX_DESC_EXT_TID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_EXT_TID, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_EXT_TID_S)); \ + } while (0) + +#define HTT_TX_DESC_POSTPONED_GET(_var) \ + (((_var) & HTT_TX_DESC_POSTPONED_M) >> HTT_TX_DESC_POSTPONED_S) +#define HTT_TX_DESC_POSTPONED_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_POSTPONED, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_POSTPONED_S)); \ + } while (0) + +#define HTT_TX_DESC_FRM_LEN_GET(_var) \ + (((_var) & HTT_TX_DESC_FRM_LEN_M) >> HTT_TX_DESC_FRM_LEN_S) +#define HTT_TX_DESC_FRM_LEN_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_FRM_LEN, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_FRM_LEN_S)); \ + } while (0) + +#define HTT_TX_DESC_FRM_ID_GET(_var) \ + (((_var) & HTT_TX_DESC_FRM_ID_M) >> HTT_TX_DESC_FRM_ID_S) +#define HTT_TX_DESC_FRM_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_FRM_ID, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_FRM_ID_S)); \ + } while (0) + +#define HTT_TX_DESC_CKSUM_OFFLOAD_GET(_var) \ + (((_var) & HTT_TX_DESC_CKSUM_OFFLOAD_M) >> HTT_TX_DESC_CKSUM_OFFLOAD_S) +#define HTT_TX_DESC_CKSUM_OFFLOAD_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_CKSUM_OFFLOAD, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_CKSUM_OFFLOAD_S)); \ + } while (0) + +#define HTT_TX_DESC_TX_COMP_GET(_var) \ + (((_var) & HTT_TX_DESC_TX_COMP_M) >> HTT_TX_DESC_TX_COMP_S) +#define HTT_TX_DESC_TX_COMP_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_TX_COMP, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_TX_COMP_S)); \ + } while (0) + +#define HTT_TX_DESC_PEER_ID_GET(_var) \ + (((_var) & HTT_TX_DESC_PEER_ID_M) >> HTT_TX_DESC_PEER_ID_S) +#define HTT_TX_DESC_PEER_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_PEER_ID, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_PEER_ID_S)); \ + } while (0) + +#define HTT_TX_DESC_CHAN_FREQ_GET(_var) \ + (((_var) & HTT_TX_DESC_CHAN_FREQ_M) >> HTT_TX_DESC_CHAN_FREQ_S) +#define HTT_TX_DESC_CHAN_FREQ_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_CHAN_FREQ, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_CHAN_FREQ_S)); \ + } while (0) + + +/* enums used in the HTT tx MSDU extension descriptor */ +enum { + htt_tx_guard_interval_regular = 0, + htt_tx_guard_interval_short = 1, +}; + +enum { + htt_tx_preamble_type_ofdm = 0, + htt_tx_preamble_type_cck = 1, + htt_tx_preamble_type_ht = 2, + htt_tx_preamble_type_vht = 3, +}; + +enum { + htt_tx_bandwidth_5MHz = 0, + htt_tx_bandwidth_10MHz = 1, + htt_tx_bandwidth_20MHz = 2, + htt_tx_bandwidth_40MHz = 3, + htt_tx_bandwidth_80MHz = 4, + htt_tx_bandwidth_160MHz = 5, /* includes 80+80 */ +}; + +/** + * @brief HTT tx MSDU extension descriptor + * @details + * If the target supports HTT tx MSDU extension descriptors, the host has + * the option of appending the following struct following the regular + * HTT tx MSDU descriptor (and setting the "extension" flag in the regular + * HTT tx MSDU descriptor, to show that the extension descriptor is present). + * The HTT tx MSDU extension descriptors allows the host to provide detailed + * tx specs for each frame. + */ +PREPACK struct htt_tx_msdu_desc_ext_t { + /* DWORD 0: flags */ + A_UINT32 + valid_pwr: 1, /* bit 0: if set, tx pwr spec is valid */ + valid_mcs_mask: 1, /* bit 1: if set, tx MCS mask spec is valid */ + valid_nss_mask: 1, /* bit 2: if set, tx Nss mask spec is valid */ + valid_guard_interval: 1, /* bit 3: if set, tx guard intv spec is valid*/ + valid_preamble_type_mask: 1, /* 4: if set, tx preamble mask is valid */ + valid_chainmask: 1, /* bit 5: if set, tx chainmask spec is valid */ + valid_retries: 1, /* bit 6: if set, tx retries spec is valid */ + valid_bandwidth: 1, /* bit 7: if set, tx bandwidth spec is valid */ + valid_expire_tsf: 1, /* bit 8: if set, tx expire TSF spec is valid*/ + is_dsrc: 1, /* bit 9: if set, MSDU is a DSRC frame */ + reserved0_31_7: 22; /* bits 31:10 - unused, set to 0x0 */ + + /* DWORD 1: tx power, tx rate, tx BW */ + A_UINT32 + /* pwr - + * Specify what power the tx frame needs to be transmitted at. + * The power a signed (two's complement) value is in units of 0.5 dBm. + * The value needs to be appropriately sign-extended when extracting + * the value from the message and storing it in a variable that is + * larger than A_INT8. (The HTT_TX_MSDU_EXT_DESC_FLAG_PWR_GET macro + * automatically handles this sign-extension.) + * If the transmission uses multiple tx chains, this power spec is + * the total transmit power, assuming incoherent combination of + * per-chain power to produce the total power. + */ + pwr: 8, + + /* mcs_mask - + * Specify the allowable values for MCS index (modulation and coding) + * to use for transmitting the frame. + * + * For HT / VHT preamble types, this mask directly corresponds to + * the HT or VHT MCS indices that are allowed. For each bit N set + * within the mask, MCS index N is allowed for transmitting the frame. + * For legacy CCK and OFDM rates, separate bits are provided for CCK + * rates versus OFDM rates, so the host has the option of specifying + * that the target must transmit the frame with CCK or OFDM rates + * (not HT or VHT), but leaving the decision to the target whether + * to use CCK or OFDM. + * + * For CCK and OFDM, the bits within this mask are interpreted as + * follows: + * bit 0 -> CCK 1 Mbps rate is allowed + * bit 1 -> CCK 2 Mbps rate is allowed + * bit 2 -> CCK 5.5 Mbps rate is allowed + * bit 3 -> CCK 11 Mbps rate is allowed + * bit 4 -> OFDM BPSK modulation, 1/2 coding rate is allowed + * bit 5 -> OFDM BPSK modulation, 3/4 coding rate is allowed + * bit 6 -> OFDM QPSK modulation, 1/2 coding rate is allowed + * bit 7 -> OFDM QPSK modulation, 3/4 coding rate is allowed + * bit 8 -> OFDM 16-QAM modulation, 1/2 coding rate is allowed + * bit 9 -> OFDM 16-QAM modulation, 3/4 coding rate is allowed + * bit 10 -> OFDM 64-QAM modulation, 2/3 coding rate is allowed + * bit 11 -> OFDM 64-QAM modulation, 3/4 coding rate is allowed + * + * The MCS index specification needs to be compatible with the + * bandwidth mask specification. For example, a MCS index == 9 + * specification is inconsistent with a preamble type == VHT, + * Nss == 1, and channel bandwidth == 20 MHz. + * + * Furthermore, the host has only a limited ability to specify to + * the target to select from HT + legacy rates, or VHT + legacy rates, + * since this mcs_mask can specify either HT/VHT rates or legacy rates. + */ + mcs_mask: 12, + + /* nss_mask - + * Specify which numbers of spatial streams (MIMO factor) are permitted. + * Each bit in this mask corresponds to a Nss value: + * bit 0: if set, Nss = 1 (non-MIMO) is permitted + * bit 1: if set, Nss = 2 (2x2 MIMO) is permitted + * bit 2: if set, Nss = 3 (3x3 MIMO) is permitted + * bit 3: if set, Nss = 4 (4x4 MIMO) is permitted + * The values in the Nss mask must be suitable for the recipient, e.g. + * a value of 0x4 (Nss = 3) cannot be specified for a tx frame to a + * recipient which only supports 2x2 MIMO. + */ + nss_mask: 4, + + /* guard_interval - + * Specify a htt_tx_guard_interval enum value to indicate whether + * the transmission should use a regular guard interval or a + * short guard interval. + */ + guard_interval: 1, + + /* preamble_type_mask - + * Specify which preamble types (CCK, OFDM, HT, VHT) the target + * may choose from for transmitting this frame. + * The bits in this mask correspond to the values in the + * htt_tx_preamble_type enum. For example, to allow the target + * to transmit the frame as either CCK or OFDM, this field would + * be set to + * (1 << htt_tx_preamble_type_ofdm) | + * (1 << htt_tx_preamble_type_cck) + */ + preamble_type_mask: 4, + + reserved1_31_29: 3; /* unused, set to 0x0 */ + + /* DWORD 2: tx chain mask, tx retries */ + A_UINT32 + /* chain_mask - specify which chains to transmit from */ + chain_mask: 4, + + /* retry_limit - + * Specify the maximum number of transmissions, including the + * initial transmission, to attempt before giving up if no ack + * is received. + * If the tx rate is specified, then all retries shall use the + * same rate as the initial transmission. + * If no tx rate is specified, the target can choose whether to + * retain the original rate during the retransmissions, or to + * fall back to a more robust rate. + */ + retry_limit: 4, + + /* bandwidth_mask - + * Specify what channel widths may be used for the transmission. + * A value of zero indicates "don't care" - the target may choose + * the transmission bandwidth. + * The bits within this mask correspond to the htt_tx_bandwidth + * enum values - bit 0 is for 5 MHz, bit 1 is for 10 MHz, etc. + * The bandwidth_mask must be consistent with the preamble_type_mask + * and mcs_mask specs, if they are provided. For example, 80 MHz and + * 160 MHz can only be enabled in the mask if preamble_type == VHT. + */ + bandwidth_mask: 6, + + reserved2_31_14: 18; /* unused, set to 0x0 */ + + /* DWORD 3: tx expiry time (TSF) LSBs */ + A_UINT32 expire_tsf_lo; + + /* DWORD 4: tx expiry time (TSF) MSBs */ + A_UINT32 expire_tsf_hi; + + A_UINT32 reserved_for_future_expansion_set_to_zero[3]; +} POSTPACK; + +/* DWORD 0 */ +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_M 0x00000001 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_S 0 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_M 0x00000002 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_S 1 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_NSS_MASK_M 0x00000004 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_NSS_MASK_S 2 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_M 0x00000008 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_S 3 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_M 0x00000010 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_S 4 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_M 0x00000020 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_S 5 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_M 0x00000040 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_S 6 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_M 0x00000080 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_S 7 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_M 0x00000100 +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_S 8 +#define HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_M 0x00000200 +#define HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_S 9 + +/* DWORD 1 */ +#define HTT_TX_MSDU_EXT_DESC_PWR_M 0x000000ff +#define HTT_TX_MSDU_EXT_DESC_PWR_S 0 +#define HTT_TX_MSDU_EXT_DESC_MCS_MASK_M 0x000fff00 +#define HTT_TX_MSDU_EXT_DESC_MCS_MASK_S 8 +#define HTT_TX_MSDU_EXT_DESC_NSS_MASK_M 0x00f00000 +#define HTT_TX_MSDU_EXT_DESC_NSS_MASK_S 20 +#define HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_M 0x01000000 +#define HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_S 24 +#define HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_M 0x1c000000 +#define HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_S 25 + +/* DWORD 2 */ +#define HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_M 0x0000000f +#define HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_S 0 +#define HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_M 0x000000f0 +#define HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_S 4 +#define HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_M 0x00003f00 +#define HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_S 8 + + +/* DWORD 0 */ +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PWR_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_MCS_MASK_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL( \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL, _val); \ + ((_var) |= ((_val) \ + << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_GUARD_INTERVAL_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL( \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK, _val); \ + ((_var) |= ((_val) \ + << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_PREAMBLE_TYPE_MASK_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_CHAIN_MASK_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_RETRIES_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_BANDWIDTH_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_VALID_EXPIRE_TIME_S));\ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_M) >> \ + HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_S) +#define HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_FLAG_IS_DSRC_S)); \ + } while (0) + + +/* DWORD 1 */ +#define HTT_TX_MSDU_EXT_DESC_PWR_GET_BASE(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_PWR_M) >> \ + HTT_TX_MSDU_EXT_DESC_PWR_S) +#define HTT_TX_MSDU_EXT_DESC_PWR_GET(_var) \ + (HTT_TX_MSDU_EXT_DESC_PWR_GET_BASE(_var) | \ + HTT_SIGN_BIT_EXTENSION_MASK(_var, HTT_TX_MSDU_EXT_DESC_PWR)) +#define HTT_TX_MSDU_EXT_DESC_PWR_SET(_var, _val) \ + ((_var) |= (((_val) << HTT_TX_MSDU_EXT_DESC_PWR_S)) & \ + HTT_TX_MSDU_EXT_DESC_PWR_M) + +#define HTT_TX_MSDU_EXT_DESC_MCS_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_MCS_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_MCS_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_MCS_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_MCS_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_MCS_MASK_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_NSS_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_NSS_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_NSS_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_NSS_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_NSS_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_NSS_MASK_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_M) >> \ + HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_S) +#define HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_GUARD_INTERVAL_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_PREAMBLE_TYPE_MASK_S)); \ + } while (0) + + +/* DWORD 2 */ +#define HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_CHAIN_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_CHAIN_MASK_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_M) >> \ + HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_S) +#define HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_RETRY_LIMIT_S)); \ + } while (0) + +#define HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_GET(_var) \ + (((_var) & HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_M) >> \ + HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_S) +#define HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK, _val); \ + ((_var) |= ((_val) << HTT_TX_MSDU_EXT_DESC_BANDWIDTH_MASK_S)); \ + } while (0) + + +/** + * @brief MAC DMA rx ring setup specification + * @details + * To allow for dynamic rx ring reconfiguration and to avoid race + * conditions, the host SW never directly programs the MAC DMA rx ring(s) + * it uses. Instead, it sends this message to the target, indicating how + * the rx ring used by the host should be set up and maintained. + * The message consists of a 4-octet header followed by 1 or 2 rx ring setup + * specifications. + * + * |31 16|15 8|7 0| + * |---------------------------------------------------------------| + * header: | reserved | num rings | msg type | + * |---------------------------------------------------------------| + * payload 1: | FW_IDX shadow register physical address (bits 31:0) | +#if HTT_PADDR64 + * | FW_IDX shadow register physical address (bits 63:32) | +#endif + * |---------------------------------------------------------------| + * | rx ring base physical address (bits 31:0) | +#if HTT_PADDR64 + * | rx ring base physical address (bits 63:32) | +#endif + * |---------------------------------------------------------------| + * | rx ring buffer size | rx ring length | + * |---------------------------------------------------------------| + * | FW_IDX initial value | enabled flags | + * |---------------------------------------------------------------| + * | MSDU payload offset | 802.11 header offset | + * |---------------------------------------------------------------| + * | PPDU end offset | PPDU start offset | + * |---------------------------------------------------------------| + * | MPDU end offset | MPDU start offset | + * |---------------------------------------------------------------| + * | MSDU end offset | MSDU start offset | + * |---------------------------------------------------------------| + * | frag info offset | rx attention offset | + * |---------------------------------------------------------------| + * payload 2, if present, has the same format as payload 1 + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx ring configuration message + * Value: 0x2 + * - NUM_RINGS + * Bits 15:8 + * Purpose: indicates whether the host is setting up one rx ring or two + * Value: 1 or 2 + * Payload: + * for systems using 64-bit format for bus addresses: + * - IDX_SHADOW_REG_PADDR_LO + * Bits 31:0 + * Value: lower 4 bytes of physical address of the host's + * FW_IDX shadow register + * - IDX_SHADOW_REG_PADDR_HI + * Bits 31:0 + * Value: upper 4 bytes of physical address of the host's + * FW_IDX shadow register + * - RING_BASE_PADDR_LO + * Bits 31:0 + * Value: lower 4 bytes of physical address of the host's rx ring + * - RING_BASE_PADDR_HI + * Bits 31:0 + * Value: uppper 4 bytes of physical address of the host's rx ring + * for systems using 32-bit format for bus addresses: + * - IDX_SHADOW_REG_PADDR + * Bits 31:0 + * Value: physical address of the host's FW_IDX shadow register + * - RING_BASE_PADDR + * Bits 31:0 + * Value: physical address of the host's rx ring + * - RING_LEN + * Bits 15:0 + * Value: number of elements in the rx ring + * - RING_BUF_SZ + * Bits 31:16 + * Value: size of the buffers referenced by the rx ring, in byte units + * - ENABLED_FLAGS + * Bits 15:0 + * Value: 1-bit flags to show whether different rx fields are enabled + * bit 0: 802.11 header enabled (1) or disabled (0) + * bit 1: MSDU payload enabled (1) or disabled (0) + * bit 2: PPDU start enabled (1) or disabled (0) + * bit 3: PPDU end enabled (1) or disabled (0) + * bit 4: MPDU start enabled (1) or disabled (0) + * bit 5: MPDU end enabled (1) or disabled (0) + * bit 6: MSDU start enabled (1) or disabled (0) + * bit 7: MSDU end enabled (1) or disabled (0) + * bit 8: rx attention enabled (1) or disabled (0) + * bit 9: frag info enabled (1) or disabled (0) + * bit 10: unicast rx enabled (1) or disabled (0) + * bit 11: multicast rx enabled (1) or disabled (0) + * bit 12: ctrl rx enabled (1) or disabled (0) + * bit 13: mgmt rx enabled (1) or disabled (0) + * bit 14: null rx enabled (1) or disabled (0) + * bit 15: phy data rx enabled (1) or disabled (0) + * - IDX_INIT_VAL + * Bits 31:16 + * Purpose: Specify the initial value for the FW_IDX. + * Value: the number of buffers initially present in the host's rx ring + * - OFFSET_802_11_HDR + * Bits 15:0 + * Value: offset in QUAD-bytes of 802.11 header from the buffer start + * - OFFSET_MSDU_PAYLOAD + * Bits 31:16 + * Value: offset in QUAD-bytes of MSDU payload from the buffer start + * - OFFSET_PPDU_START + * Bits 15:0 + * Value: offset in QUAD-bytes of PPDU start rx desc from the buffer start + * - OFFSET_PPDU_END + * Bits 31:16 + * Value: offset in QUAD-bytes of PPDU end rx desc from the buffer start + * - OFFSET_MPDU_START + * Bits 15:0 + * Value: offset in QUAD-bytes of MPDU start rx desc from the buffer start + * - OFFSET_MPDU_END + * Bits 31:16 + * Value: offset in QUAD-bytes of MPDU end rx desc from the buffer start + * - OFFSET_MSDU_START + * Bits 15:0 + * Value: offset in QUAD-bytes of MSDU start rx desc from the buffer start + * - OFFSET_MSDU_END + * Bits 31:16 + * Value: offset in QUAD-bytes of MSDU end rx desc from the buffer start + * - OFFSET_RX_ATTN + * Bits 15:0 + * Value: offset in QUAD-bytes of rx attention word from the buffer start + * - OFFSET_FRAG_INFO + * Bits 31:16 + * Value: offset in QUAD-bytes of frag info table + */ +/* header fields */ +#define HTT_RX_RING_CFG_NUM_RINGS_M 0xff00 +#define HTT_RX_RING_CFG_NUM_RINGS_S 8 + +/* payload fields */ +/* for systems using a 64-bit format for bus addresses */ +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_HI_M 0xffffffff +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_HI_S 0 +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_LO_M 0xffffffff +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_LO_S 0 +#define HTT_RX_RING_CFG_BASE_PADDR_HI_M 0xffffffff +#define HTT_RX_RING_CFG_BASE_PADDR_HI_S 0 +#define HTT_RX_RING_CFG_BASE_PADDR_LO_M 0xffffffff +#define HTT_RX_RING_CFG_BASE_PADDR_LO_S 0 + +/* for systems using a 32-bit format for bus addresses */ +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_M 0xffffffff +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_S 0 +#define HTT_RX_RING_CFG_BASE_PADDR_M 0xffffffff +#define HTT_RX_RING_CFG_BASE_PADDR_S 0 + +#define HTT_RX_RING_CFG_LEN_M 0xffff +#define HTT_RX_RING_CFG_LEN_S 0 +#define HTT_RX_RING_CFG_BUF_SZ_M 0xffff0000 +#define HTT_RX_RING_CFG_BUF_SZ_S 16 +#define HTT_RX_RING_CFG_ENABLED_802_11_HDR_M 0x1 +#define HTT_RX_RING_CFG_ENABLED_802_11_HDR_S 0 +#define HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_M 0x2 +#define HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_S 1 +#define HTT_RX_RING_CFG_ENABLED_PPDU_START_M 0x4 +#define HTT_RX_RING_CFG_ENABLED_PPDU_START_S 2 +#define HTT_RX_RING_CFG_ENABLED_PPDU_END_M 0x8 +#define HTT_RX_RING_CFG_ENABLED_PPDU_END_S 3 +#define HTT_RX_RING_CFG_ENABLED_MPDU_START_M 0x10 +#define HTT_RX_RING_CFG_ENABLED_MPDU_START_S 4 +#define HTT_RX_RING_CFG_ENABLED_MPDU_END_M 0x20 +#define HTT_RX_RING_CFG_ENABLED_MPDU_END_S 5 +#define HTT_RX_RING_CFG_ENABLED_MSDU_START_M 0x40 +#define HTT_RX_RING_CFG_ENABLED_MSDU_START_S 6 +#define HTT_RX_RING_CFG_ENABLED_MSDU_END_M 0x80 +#define HTT_RX_RING_CFG_ENABLED_MSDU_END_S 7 +#define HTT_RX_RING_CFG_ENABLED_RX_ATTN_M 0x100 +#define HTT_RX_RING_CFG_ENABLED_RX_ATTN_S 8 +#define HTT_RX_RING_CFG_ENABLED_FRAG_INFO_M 0x200 +#define HTT_RX_RING_CFG_ENABLED_FRAG_INFO_S 9 +#define HTT_RX_RING_CFG_ENABLED_UCAST_M 0x400 +#define HTT_RX_RING_CFG_ENABLED_UCAST_S 10 +#define HTT_RX_RING_CFG_ENABLED_MCAST_M 0x800 +#define HTT_RX_RING_CFG_ENABLED_MCAST_S 11 +#define HTT_RX_RING_CFG_ENABLED_CTRL_M 0x1000 +#define HTT_RX_RING_CFG_ENABLED_CTRL_S 12 +#define HTT_RX_RING_CFG_ENABLED_MGMT_M 0x2000 +#define HTT_RX_RING_CFG_ENABLED_MGMT_S 13 +#define HTT_RX_RING_CFG_ENABLED_NULL_M 0x4000 +#define HTT_RX_RING_CFG_ENABLED_NULL_S 14 +#define HTT_RX_RING_CFG_ENABLED_PHY_M 0x8000 +#define HTT_RX_RING_CFG_ENABLED_PHY_S 15 +#define HTT_RX_RING_CFG_IDX_INIT_VAL_M 0xffff0000 +#define HTT_RX_RING_CFG_IDX_INIT_VAL_S 16 +#define HTT_RX_RING_CFG_OFFSET_802_11_HDR_M 0xffff +#define HTT_RX_RING_CFG_OFFSET_802_11_HDR_S 0 +#define HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_M 0xffff0000 +#define HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_S 16 +#define HTT_RX_RING_CFG_OFFSET_PPDU_START_M 0xffff +#define HTT_RX_RING_CFG_OFFSET_PPDU_START_S 0 +#define HTT_RX_RING_CFG_OFFSET_PPDU_END_M 0xffff0000 +#define HTT_RX_RING_CFG_OFFSET_PPDU_END_S 16 +#define HTT_RX_RING_CFG_OFFSET_MPDU_START_M 0xffff +#define HTT_RX_RING_CFG_OFFSET_MPDU_START_S 0 +#define HTT_RX_RING_CFG_OFFSET_MPDU_END_M 0xffff0000 +#define HTT_RX_RING_CFG_OFFSET_MPDU_END_S 16 +#define HTT_RX_RING_CFG_OFFSET_MSDU_START_M 0xffff +#define HTT_RX_RING_CFG_OFFSET_MSDU_START_S 0 +#define HTT_RX_RING_CFG_OFFSET_MSDU_END_M 0xffff0000 +#define HTT_RX_RING_CFG_OFFSET_MSDU_END_S 16 +#define HTT_RX_RING_CFG_OFFSET_RX_ATTN_M 0xffff +#define HTT_RX_RING_CFG_OFFSET_RX_ATTN_S 0 +#define HTT_RX_RING_CFG_OFFSET_FRAG_INFO_M 0xffff0000 +#define HTT_RX_RING_CFG_OFFSET_FRAG_INFO_S 16 + +#define HTT_RX_RING_CFG_HDR_BYTES 4 +#define HTT_RX_RING_CFG_PAYLD_BYTES_64 44 +#define HTT_RX_RING_CFG_PAYLD_BYTES_32 36 +#if HTT_PADDR64 + #define HTT_RX_RING_CFG_PAYLD_BYTES HTT_RX_RING_CFG_PAYLD_BYTES_64 +#else + #define HTT_RX_RING_CFG_PAYLD_BYTES HTT_RX_RING_CFG_PAYLD_BYTES_32 +#endif +#define HTT_RX_RING_CFG_BYTES(num_rings) \ + (HTT_RX_RING_CFG_HDR_BYTES + (num_rings) * HTT_RX_RING_CFG_PAYLD_BYTES) + + +#define HTT_RX_RING_CFG_NUM_RINGS_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_NUM_RINGS_M) >> HTT_RX_RING_CFG_NUM_RINGS_S) +#define HTT_RX_RING_CFG_NUM_RINGS_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_NUM_RINGS, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_NUM_RINGS_S)); \ + } while (0) + +/* degenerate case for 32-bit fields */ +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_HI_GET(_var) (_var) +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_HI_SET(_var, _val) (_var) = (_val) +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_LO_GET(_var) (_var) +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_LO_SET(_var, _val) (_var) = (_val) +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_GET(_var) (_var) +#define HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_SET(_var, _val) (_var) = (_val) + +/* degenerate case for 32-bit fields */ +#define HTT_RX_RING_CFG_BASE_PADDR_HI_GET(_var) (_var) +#define HTT_RX_RING_CFG_BASE_PADDR_HI_SET(_var, _val) (_var) = (_val) +#define HTT_RX_RING_CFG_BASE_PADDR_LO_GET(_var) (_var) +#define HTT_RX_RING_CFG_BASE_PADDR_LO_SET(_var, _val) (_var) = (_val) +#define HTT_RX_RING_CFG_BASE_PADDR_GET(_var) (_var) +#define HTT_RX_RING_CFG_BASE_PADDR_SET(_var, _val) (_var) = (_val) + +#define HTT_RX_RING_CFG_LEN_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_LEN_M) >> HTT_RX_RING_CFG_LEN_S) +#define HTT_RX_RING_CFG_LEN_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_LEN, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_LEN_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_BUF_SZ_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_BUF_SZ_M) >> HTT_RX_RING_CFG_BUF_SZ_S) +#define HTT_RX_RING_CFG_BUF_SZ_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_BUF_SZ, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_BUF_SZ_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_IDX_INIT_VAL_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_IDX_INIT_VAL_M) >> \ + HTT_RX_RING_CFG_IDX_INIT_VAL_S) +#define HTT_RX_RING_CFG_IDX_INIT_VAL_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_IDX_INIT_VAL, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_IDX_INIT_VAL_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_802_11_HDR_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_802_11_HDR_M) >> \ + HTT_RX_RING_CFG_ENABLED_802_11_HDR_S) +#define HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_802_11_HDR, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_802_11_HDR_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_M) >> \ + HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_S) +#define HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_PPDU_START_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_PPDU_START_M) >> \ + HTT_RX_RING_CFG_ENABLED_PPDU_START_S) +#define HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_PPDU_START, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_PPDU_START_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_PPDU_END_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_PPDU_END_M) >> \ + HTT_RX_RING_CFG_ENABLED_PPDU_END_S) +#define HTT_RX_RING_CFG_ENABLED_PPDU_END_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_PPDU_END, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_PPDU_END_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_MPDU_START_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MPDU_START_M) >> \ + HTT_RX_RING_CFG_ENABLED_MPDU_START_S) +#define HTT_RX_RING_CFG_ENABLED_MPDU_START_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MPDU_START, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MPDU_START_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_MPDU_END_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MPDU_END_M) >> \ + HTT_RX_RING_CFG_ENABLED_MPDU_END_S) +#define HTT_RX_RING_CFG_ENABLED_MPDU_END_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MPDU_END, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MPDU_END_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_MSDU_START_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MSDU_START_M) >> \ + HTT_RX_RING_CFG_ENABLED_MSDU_START_S) +#define HTT_RX_RING_CFG_ENABLED_MSDU_START_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MSDU_START, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MSDU_START_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_MSDU_END_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MSDU_END_M) >> \ + HTT_RX_RING_CFG_ENABLED_MSDU_END_S) +#define HTT_RX_RING_CFG_ENABLED_MSDU_END_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MSDU_END, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MSDU_END_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_RX_ATTN_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_RX_ATTN_M) >> \ + HTT_RX_RING_CFG_ENABLED_RX_ATTN_S) +#define HTT_RX_RING_CFG_ENABLED_RX_ATTN_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_RX_ATTN, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_RX_ATTN_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_FRAG_INFO_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_FRAG_INFO_M) >> \ + HTT_RX_RING_CFG_ENABLED_FRAG_INFO_S) +#define HTT_RX_RING_CFG_ENABLED_FRAG_INFO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_FRAG_INFO, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_FRAG_INFO_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_UCAST_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_UCAST_M) >> \ + HTT_RX_RING_CFG_ENABLED_UCAST_S) +#define HTT_RX_RING_CFG_ENABLED_UCAST_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_UCAST, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_UCAST_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_ENABLED_MCAST_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MCAST_M) >> \ + HTT_RX_RING_CFG_ENABLED_MCAST_S) +#define HTT_RX_RING_CFG_ENABLED_MCAST_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MCAST, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MCAST_S)); \ + } while (0) +#define HTT_RX_RING_CFG_ENABLED_CTRL_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_CTRL_M) >> \ + HTT_RX_RING_CFG_ENABLED_CTRL_S) +#define HTT_RX_RING_CFG_ENABLED_CTRL_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_CTRL, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_CTRL_S)); \ + } while (0) +#define HTT_RX_RING_CFG_ENABLED_MGMT_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_MGMT_M) >> \ + HTT_RX_RING_CFG_ENABLED_MGMT_S) +#define HTT_RX_RING_CFG_ENABLED_MGMT_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_MGMT, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_MGMT_S)); \ + } while (0) +#define HTT_RX_RING_CFG_ENABLED_NULL_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_NULL_M) >> \ + HTT_RX_RING_CFG_ENABLED_NULL_S) +#define HTT_RX_RING_CFG_ENABLED_NULL_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_NULL, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_NULL_S)); \ + } while (0) +#define HTT_RX_RING_CFG_ENABLED_PHY_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_ENABLED_PHY_M) >> \ + HTT_RX_RING_CFG_ENABLED_PHY_S) +#define HTT_RX_RING_CFG_ENABLED_PHY_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_ENABLED_PHY, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_ENABLED_PHY_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_802_11_HDR_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_802_11_HDR_M) >> \ + HTT_RX_RING_CFG_OFFSET_802_11_HDR_S) +#define HTT_RX_RING_CFG_OFFSET_802_11_HDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_802_11_HDR, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_802_11_HDR_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_M) >> \ + HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_S) +#define HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_PPDU_START_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_PPDU_START_M) >> \ + HTT_RX_RING_CFG_OFFSET_PPDU_START_S) +#define HTT_RX_RING_CFG_OFFSET_PPDU_START_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_PPDU_START, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_PPDU_START_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_PPDU_END_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_PPDU_END_M) >> \ + HTT_RX_RING_CFG_OFFSET_PPDU_END_S) +#define HTT_RX_RING_CFG_OFFSET_PPDU_END_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_PPDU_END, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_PPDU_END_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_MPDU_START_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_MPDU_START_M) >> \ + HTT_RX_RING_CFG_OFFSET_MPDU_START_S) +#define HTT_RX_RING_CFG_OFFSET_MPDU_START_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_MPDU_START, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_MPDU_START_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_MPDU_END_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_MPDU_END_M) >> \ + HTT_RX_RING_CFG_OFFSET_MPDU_END_S) +#define HTT_RX_RING_CFG_OFFSET_MPDU_END_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_MPDU_END, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_MPDU_END_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_MSDU_START_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_MSDU_START_M) >> \ + HTT_RX_RING_CFG_OFFSET_MSDU_START_S) +#define HTT_RX_RING_CFG_OFFSET_MSDU_START_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_MSDU_START, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_MSDU_START_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_MSDU_END_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_MSDU_END_M) >> \ + HTT_RX_RING_CFG_OFFSET_MSDU_END_S) +#define HTT_RX_RING_CFG_OFFSET_MSDU_END_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_MSDU_END, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_MSDU_END_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_RX_ATTN_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_RX_ATTN_M) >> \ + HTT_RX_RING_CFG_OFFSET_RX_ATTN_S) +#define HTT_RX_RING_CFG_OFFSET_RX_ATTN_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_RX_ATTN, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_RX_ATTN_S)); \ + } while (0) + +#define HTT_RX_RING_CFG_OFFSET_FRAG_INFO_GET(_var) \ + (((_var) & HTT_RX_RING_CFG_OFFSET_FRAG_INFO_M) >> \ + HTT_RX_RING_CFG_OFFSET_FRAG_INFO_S) +#define HTT_RX_RING_CFG_OFFSET_FRAG_INFO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_RING_CFG_OFFSET_FRAG_INFO, _val); \ + ((_var) |= ((_val) << HTT_RX_RING_CFG_OFFSET_FRAG_INFO_S)); \ + } while (0) + +/** + * @brief host -> target FW statistics retrieve + * + * @details + * The following field definitions describe the format of the HTT host + * to target FW stats retrieve message. The message specifies the type of + * stats host wants to retrieve. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------| + * | stats types request bitmask | msg type | + * |-----------------------------------------------------------| + * | stats types reset bitmask | reserved | + * |-----------------------------------------------------------| + * | stats type | config value | + * |-----------------------------------------------------------| + * | cookie LSBs | + * |-----------------------------------------------------------| + * | cookie MSBs | + * |-----------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this is a stats upload request message + * Value: 0x3 + * - UPLOAD_TYPES + * Bits 31:8 + * Purpose: identifies which types of FW statistics to upload + * Value: mask with bits set in positions defined by htt_dbg_stats_type + * - RESET_TYPES + * Bits 31:8 + * Purpose: identifies which types of FW statistics to reset + * Value: mask with bits set in positions defined by htt_dbg_stats_type + * - CFG_VAL + * Bits 23:0 + * Purpose: give an opaque configuration value to the specified stats type + * Value: stats-type specific configuration value + * if stats type == tx PPDU log, then CONFIG_VAL has the format: + * bits 7:0 - how many per-MPDU byte counts to include in a record + * bits 15:8 - how many per-MPDU MSDU counts to include in a record + * bits 23:16 - how many per-MSDU byte counts to include in a record + * - CFG_STAT_TYPE + * Bits 31:24 + * Purpose: specify which stats type (if any) the config value applies to + * Value: htt_dbg_stats_type value, or 0xff if the message doesn't have + * a valid configuration specification + * - COOKIE_LSBS + * Bits 31:0 + * Purpose: Provide a mechanism to match a target->host stats confirmation + * message with its preceding host->target stats request message. + * Value: LSBs of the opaque cookie specified by the host-side requestor + * - COOKIE_MSBS + * Bits 31:0 + * Purpose: Provide a mechanism to match a target->host stats confirmation + * message with its preceding host->target stats request message. + * Value: MSBs of the opaque cookie specified by the host-side requestor + */ + +#define HTT_H2T_STATS_REQ_MSG_SZ 20 /* bytes */ + +#define HTT_H2T_STATS_REQ_CFG_STAT_TYPE_INVALID 0xff + +#define HTT_H2T_STATS_REQ_UPLOAD_TYPES_M 0xffffff00 +#define HTT_H2T_STATS_REQ_UPLOAD_TYPES_S 8 + +#define HTT_H2T_STATS_REQ_RESET_TYPES_M 0xffffff00 +#define HTT_H2T_STATS_REQ_RESET_TYPES_S 8 + +#define HTT_H2T_STATS_REQ_CFG_VAL_M 0x00ffffff +#define HTT_H2T_STATS_REQ_CFG_VAL_S 0 + +#define HTT_H2T_STATS_REQ_CFG_STAT_TYPE_M 0xff000000 +#define HTT_H2T_STATS_REQ_CFG_STAT_TYPE_S 24 + +#define HTT_H2T_STATS_REQ_UPLOAD_TYPES_GET(_var) \ + (((_var) & HTT_H2T_STATS_REQ_UPLOAD_TYPES_M) >> \ + HTT_H2T_STATS_REQ_UPLOAD_TYPES_S) +#define HTT_H2T_STATS_REQ_UPLOAD_TYPES_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_STATS_REQ_UPLOAD_TYPES, _val); \ + ((_var) |= ((_val) << HTT_H2T_STATS_REQ_UPLOAD_TYPES_S)); \ + } while (0) + +#define HTT_H2T_STATS_REQ_RESET_TYPES_GET(_var) \ + (((_var) & HTT_H2T_STATS_REQ_RESET_TYPES_M) >> \ + HTT_H2T_STATS_REQ_RESET_TYPES_S) +#define HTT_H2T_STATS_REQ_RESET_TYPES_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_STATS_REQ_RESET_TYPES, _val); \ + ((_var) |= ((_val) << HTT_H2T_STATS_REQ_RESET_TYPES_S)); \ + } while (0) + +#define HTT_H2T_STATS_REQ_CFG_VAL_GET(_var) \ + (((_var) & HTT_H2T_STATS_REQ_CFG_VAL_M) >> \ + HTT_H2T_STATS_REQ_CFG_VAL_S) +#define HTT_H2T_STATS_REQ_CFG_VAL_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_STATS_REQ_CFG_VAL, _val); \ + ((_var) |= ((_val) << HTT_H2T_STATS_REQ_CFG_VAL_S)); \ + } while (0) + +#define HTT_H2T_STATS_REQ_CFG_STAT_TYPE_GET(_var) \ + (((_var) & HTT_H2T_STATS_REQ_CFG_STAT_TYPE_M) >> \ + HTT_H2T_STATS_REQ_CFG_STAT_TYPE_S) +#define HTT_H2T_STATS_REQ_CFG_STAT_TYPE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_STATS_REQ_CFG_STAT_TYPE, _val); \ + ((_var) |= ((_val) << HTT_H2T_STATS_REQ_CFG_STAT_TYPE_S)); \ + } while (0) + +/** + * @brief host -> target HTT out-of-band sync request + * + * @details + * The HTT SYNC tells the target to suspend processing of subsequent + * HTT host-to-target messages until some other target agent locally + * informs the target HTT FW that the current sync counter is equal to + * or greater than (in a modulo sense) the sync counter specified in + * the SYNC message. + * This allows other host-target components to synchronize their operation + * with HTT, e.g. to ensure that tx frames don't get transmitted until a + * security key has been downloaded to and activated by the target. + * In the absence of any explicit synchronization counter value + * specification, the target HTT FW will use zero as the default current + * sync value. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------| + * | reserved | sync count | msg type | + * |-----------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a sync message + * Value: 0x4 + * - SYNC_COUNT + * Bits 15:8 + * Purpose: specifies what sync value the HTT FW will wait for from + * an out-of-band specification to resume its operation + * Value: in-band sync counter value to compare against the out-of-band + * counter spec. + * The HTT target FW will suspend its host->target message processing + * as long as + * 0 < (in-band sync counter - out-of-band sync counter) & 0xff < 128 + */ + +#define HTT_H2T_SYNC_MSG_SZ 4 + +#define HTT_H2T_SYNC_COUNT_M 0x0000ff00 +#define HTT_H2T_SYNC_COUNT_S 8 + +#define HTT_H2T_SYNC_COUNT_GET(_var) \ + (((_var) & HTT_H2T_SYNC_COUNT_M) >> \ + HTT_H2T_SYNC_COUNT_S) +#define HTT_H2T_SYNC_COUNT_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_SYNC_COUNT, _val); \ + ((_var) |= ((_val) << HTT_H2T_SYNC_COUNT_S)); \ + } while (0) + + +/** + * @brief HTT aggregation configuration + */ +#define HTT_AGGR_CFG_MSG_SZ 4 + +#define HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_M 0xff00 +#define HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_S 8 +#define HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_M 0x1f0000 +#define HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_S 16 + +#define HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_GET(_var) \ + (((_var) & HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_M) >> \ + HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_S) +#define HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM, _val); \ + ((_var) |= ((_val) << HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_S)); \ + } while (0) + +#define HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_GET(_var) \ + (((_var) & HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_M) >> \ + HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_S) +#define HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM, _val); \ + ((_var) |= ((_val) << HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_S)); \ + } while (0) + + +/** + * @brief host -> target HTT configure max amsdu info per vdev + * + * @details + * The HTT AGGR CFG EX tells the target to configure max_amsdu info per vdev + * + * |31 21|20 16|15 8|7 0| + * |-----------------------------------------------------------| + * | reserved | vdev id | max amsdu | msg type | + * |-----------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a aggr cfg ex message + * Value: 0xa + * - MAX_NUM_AMSDU_SUBFRM + * Bits 15:8 + * Purpose: max MSDUs per A-MSDU + * - VDEV_ID + * Bits 20:16 + * Purpose: ID of the vdev to which this limit is applied + */ +#define HTT_AGGR_CFG_EX_MSG_SZ 4 + +#define HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_M 0xff00 +#define HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_S 8 +#define HTT_AGGR_CFG_EX_VDEV_ID_M 0x1f0000 +#define HTT_AGGR_CFG_EX_VDEV_ID_S 16 + +#define HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_GET(_var) \ + (((_var) & HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_M) >> \ + HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_S) +#define HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM, _val); \ + ((_var) |= ((_val) << HTT_AGGR_CFG_EX_MAX_NUM_AMSDU_SUBFRM_S)); \ + } while (0) + +#define HTT_AGGR_CFG_EX_VDEV_ID_GET(_var) \ + (((_var) & HTT_AGGR_CFG_EX_VDEV_ID_M) >> \ + HTT_AGGR_CFG_EX_VDEV_ID_S) +#define HTT_AGGR_CFG_EX_VDEV_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_AGGR_CFG_EX_VDEV_ID, _val); \ + ((_var) |= ((_val) << HTT_AGGR_CFG_EX_VDEV_ID_S)); \ + } while (0) + +/** + * @brief HTT WDI_IPA Config Message + * + * @details + * The HTT WDI_IPA config message is created/sent by host at driver + * init time. It contains information about data structures used on + * WDI_IPA TX and RX path. + * TX CE ring is used for pushing packet metadata from IPA uC + * to WLAN FW + * TX Completion ring is used for generating TX completions from + * WLAN FW to IPA uC + * RX Indication ring is used for indicating RX packets from FW + * to IPA uC + * RX Ring2 is used as either completion ring or as second + * indication ring. when Ring2 is used as completion ring, IPA uC + * puts completed RX packet meta data to Ring2. when Ring2 is used + * as second indication ring, RX packets for LTE-WLAN aggregation are + * indicated in Ring2, other RX packets (e.g. hotspot related) are + * indicated in RX Indication ring. Please see WDI_IPA specification + * for more details. + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | tx pkt pool size | Rsvd | msg_type | + * |-------------------------------------------------------------------| + * | tx comp ring base (bits 31:0) | +#if HTT_PADDR64 + * | tx comp ring base (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | tx comp ring size | + * |-------------------------------------------------------------------| + * | tx comp WR_IDX physical address (bits 31:0) | +#if HTT_PADDR64 + * | tx comp WR_IDX physical address (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | tx CE WR_IDX physical address (bits 31:0) | +#if HTT_PADDR64 + * | tx CE WR_IDX physical address (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | rx indication ring base (bits 31:0) | +#if HTT_PADDR64 + * | rx indication ring base (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | rx indication ring size | + * |-------------------------------------------------------------------| + * | rx ind RD_IDX physical address (bits 31:0) | +#if HTT_PADDR64 + * | rx ind RD_IDX physical address (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | rx ind WR_IDX physical address (bits 31:0) | +#if HTT_PADDR64 + * | rx ind WR_IDX physical address (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * |-------------------------------------------------------------------| + * | rx ring2 base (bits 31:0) | +#if HTT_PADDR64 + * | rx ring2 base (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | rx ring2 size | + * |-------------------------------------------------------------------| + * | rx ring2 RD_IDX physical address (bits 31:0) | +#if HTT_PADDR64 + * | rx ring2 RD_IDX physical address (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * | rx ring2 WR_IDX physical address (bits 31:0) | +#if HTT_PADDR64 + * | rx ring2 WR_IDX physical address (bits 63:32) | +#endif + * |-------------------------------------------------------------------| + * + * Header fields: + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: Identifies this as WDI_IPA config message + * value: = 0x8 + * - TX_PKT_POOL_SIZE + * Bits 15:0 + * Purpose: Total number of TX packet buffer pool allocated by Host for + * WDI_IPA TX path + * For systems using 32-bit format for bus addresses: + * - TX_COMP_RING_BASE_ADDR + * Bits 31:0 + * Purpose: TX Completion Ring base address in DDR + * - TX_COMP_RING_SIZE + * Bits 31:0 + * Purpose: TX Completion Ring size (must be power of 2) + * - TX_COMP_WR_IDX_ADDR + * Bits 31:0 + * Purpose: IPA doorbell register address OR DDR address where WIFI FW + * updates the Write Index for WDI_IPA TX completion ring + * - TX_CE_WR_IDX_ADDR + * Bits 31:0 + * Purpose: DDR address where IPA uC + * updates the WR Index for TX CE ring + * (needed for fusion platforms) + * - RX_IND_RING_BASE_ADDR + * Bits 31:0 + * Purpose: RX Indication Ring base address in DDR + * - RX_IND_RING_SIZE + * Bits 31:0 + * Purpose: RX Indication Ring size + * - RX_IND_RD_IDX_ADDR + * Bits 31:0 + * Purpose: DDR address where IPA uC updates the Read Index for WDI_IPA + * RX indication ring + * - RX_IND_WR_IDX_ADDR + * Bits 31:0 + * Purpose: IPA doorbell register address OR DDR address where WIFI FW + * updates the Write Index for WDI_IPA RX indication ring + * - RX_RING2_BASE_ADDR + * Bits 31:0 + * Purpose: Second RX Ring(Indication or completion)base address in DDR + * - RX_RING2_SIZE + * Bits 31:0 + * Purpose: Second RX Ring size (must be >= RX_IND_RING_SIZE) + * - RX_RING2_RD_IDX_ADDR + * Bits 31:0 + * Purpose: If Second RX ring is Indication ring, DDR address where + * IPA uC updates the Read Index for Ring2. + * If Second RX ring is completion ring, this is NOT used + * - RX_RING2_WR_IDX_ADDR + * Bits 31:0 + * Purpose: If Second RX ring is Indication ring, DDR address where + * WIFI FW updates the Write Index for WDI_IPA RX ring2 + * If second RX ring is completion ring, DDR address where + * IPA uC updates the Write Index for Ring 2. + * For systems using 64-bit format for bus addresses: + * - TX_COMP_RING_BASE_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of TX Completion Ring base physical address in DDR + * - TX_COMP_RING_BASE_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of TX Completion Ring base physical address in DDR + * - TX_COMP_RING_SIZE + * Bits 31:0 + * Purpose: TX Completion Ring size (must be power of 2) + * - TX_COMP_WR_IDX_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of IPA doorbell register address OR + * Lower 4 bytes of DDR address where WIFI FW + * updates the Write Index for WDI_IPA TX completion ring + * - TX_COMP_WR_IDX_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of IPA doorbell register address OR + * Higher 4 bytes of DDR address where WIFI FW + * updates the Write Index for WDI_IPA TX completion ring + * - TX_CE_WR_IDX_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of DDR address where IPA uC + * updates the WR Index for TX CE ring + * (needed for fusion platforms) + * - TX_CE_WR_IDX_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of DDR address where IPA uC + * updates the WR Index for TX CE ring + * (needed for fusion platforms) + * - RX_IND_RING_BASE_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of RX Indication Ring base address in DDR + * - RX_IND_RING_BASE_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of RX Indication Ring base address in DDR + * - RX_IND_RING_SIZE + * Bits 31:0 + * Purpose: RX Indication Ring size + * - RX_IND_RD_IDX_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of DDR address where IPA uC updates the Read Index + * for WDI_IPA RX indication ring + * - RX_IND_RD_IDX_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of DDR address where IPA uC updates the Read Index + * for WDI_IPA RX indication ring + * - RX_IND_WR_IDX_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of IPA doorbell register address OR + * Lower 4 bytes of DDR address where WIFI FW + * updates the Write Index for WDI_IPA RX indication ring + * - RX_IND_WR_IDX_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of IPA doorbell register address OR + * Higher 4 bytes of DDR address where WIFI FW + * updates the Write Index for WDI_IPA RX indication ring + * - RX_RING2_BASE_ADDR_LO + * Bits 31:0 + * Purpose: Lower 4 bytes of Second RX Ring(Indication OR completion)base address in DDR + * - RX_RING2_BASE_ADDR_HI + * Bits 31:0 + * Purpose: Higher 4 bytes of Second RX Ring(Indication OR completion)base address in DDR + * - RX_RING2_SIZE + * Bits 31:0 + * Purpose: Second RX Ring size (must be >= RX_IND_RING_SIZE) + * - RX_RING2_RD_IDX_ADDR_LO + * Bits 31:0 + * Purpose: If Second RX ring is Indication ring, lower 4 bytes of + * DDR address where IPA uC updates the Read Index for Ring2. + * If Second RX ring is completion ring, this is NOT used + * - RX_RING2_RD_IDX_ADDR_HI + * Bits 31:0 + * Purpose: If Second RX ring is Indication ring, higher 4 bytes of + * DDR address where IPA uC updates the Read Index for Ring2. + * If Second RX ring is completion ring, this is NOT used + * - RX_RING2_WR_IDX_ADDR_LO + * Bits 31:0 + * Purpose: If Second RX ring is Indication ring, lower 4 bytes of + * DDR address where WIFI FW updates the Write Index + * for WDI_IPA RX ring2 + * If second RX ring is completion ring, lower 4 bytes of + * DDR address where IPA uC updates the Write Index for Ring 2. + * - RX_RING2_WR_IDX_ADDR_HI + * Bits 31:0 + * Purpose: If Second RX ring is Indication ring, higher 4 bytes of + * DDR address where WIFI FW updates the Write Index + * for WDI_IPA RX ring2 + * If second RX ring is completion ring, higher 4 bytes of + * DDR address where IPA uC updates the Write Index for Ring 2. + */ + +#if HTT_PADDR64 +#define HTT_WDI_IPA_CFG_SZ 88 /* bytes */ +#else +#define HTT_WDI_IPA_CFG_SZ 52 /* bytes */ +#endif + +#define HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_M 0xffff0000 +#define HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_S 16 + +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_S 0 + +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_SIZE_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_SIZE_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_S 0 + +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_M 0xffffffff +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_S 0 + +#define HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_M) >> HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_S) +#define HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_M) >> HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_S) +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_M) >> HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_M) >> HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_S)); \ + } while (0) + +#define HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_M) >> HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_S) +#define HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_M) >> HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_S) +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_M) >> HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_M) >> HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_LO_S)); \ + } while (0) + + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_M) >> HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_S) +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_M) >> HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_M) >> HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_M) >> HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_S) +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_M) >> HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_M) >> HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_S)); \ + } while (0) + +#define HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_M) >> HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_S) +#define HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RING_SIZE, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_M) >> HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_S) +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_M) >> HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_M) >> HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_LO_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_M) >> HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_S) +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_M) >> HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_M) >> HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_M) >> HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_S) +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_M) >> HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_M) >> HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_S)); \ + } while (0) + +#define HTT_WDI_IPA_CFG_RX_RING2_SIZE_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_SIZE_M) >> HTT_WDI_IPA_CFG_RX_RING2_SIZE_S) +#define HTT_WDI_IPA_CFG_RX_RING2_SIZE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_SIZE, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_SIZE_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_M) >> HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_S) +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_M) >> HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_M) >> HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_S)); \ + } while (0) + +/* for systems using 32-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_M) >> HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_S) +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_M) >> HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_S) +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_S)); \ + } while (0) + +/* for systems using 64-bit format for bus addr */ +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_GET(_var) \ + (((_var) & HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_M) >> HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_S) +#define HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_S)); \ + } while (0) + +/* + * TEMPLATE_HTT_WDI_IPA_CONFIG_T: + * This macro defines a htt_wdi_ipa_configXXX_t in which any physical + * addresses are stored in a XXX-bit field. + * This macro is used to define both htt_wdi_ipa_config32_t and + * htt_wdi_ipa_config64_t structs. + */ +#define TEMPLATE_HTT_WDI_IPA_CONFIG_T(_paddr_bits_, \ + _paddr__tx_comp_ring_base_addr_, \ + _paddr__tx_comp_wr_idx_addr_, \ + _paddr__tx_ce_wr_idx_addr_, \ + _paddr__rx_ind_ring_base_addr_, \ + _paddr__rx_ind_rd_idx_addr_, \ + _paddr__rx_ind_wr_idx_addr_, \ + _paddr__rx_ring2_base_addr_,\ + _paddr__rx_ring2_rd_idx_addr_,\ + _paddr__rx_ring2_wr_idx_addr_) \ +PREPACK struct htt_wdi_ipa_cfg ## _paddr_bits_ ## _t \ +{ \ + /* DWORD 0: flags and meta-data */ \ + A_UINT32 \ + msg_type: 8, /* HTT_H2T_MSG_TYPE_WDI_IPA_CFG */ \ + reserved: 8, \ + tx_pkt_pool_size: 16;\ + /* DWORD 1 */\ + _paddr__tx_comp_ring_base_addr_;\ + /* DWORD 2 (or 3)*/\ + A_UINT32 tx_comp_ring_size;\ + /* DWORD 3 (or 4)*/\ + _paddr__tx_comp_wr_idx_addr_;\ + /* DWORD 4 (or 6)*/\ + _paddr__tx_ce_wr_idx_addr_;\ + /* DWORD 5 (or 8)*/\ + _paddr__rx_ind_ring_base_addr_;\ + /* DWORD 6 (or 10)*/\ + A_UINT32 rx_ind_ring_size;\ + /* DWORD 7 (or 11)*/\ + _paddr__rx_ind_rd_idx_addr_;\ + /* DWORD 8 (or 13)*/\ + _paddr__rx_ind_wr_idx_addr_;\ + /* DWORD 9 (or 15)*/\ + _paddr__rx_ring2_base_addr_;\ + /* DWORD 10 (or 17) */\ + A_UINT32 rx_ring2_size;\ + /* DWORD 11 (or 18) */\ + _paddr__rx_ring2_rd_idx_addr_;\ + /* DWORD 12 (or 20) */\ + _paddr__rx_ring2_wr_idx_addr_;\ +} POSTPACK + +/* define a htt_wdi_ipa_config32_t type */ +TEMPLATE_HTT_WDI_IPA_CONFIG_T(32, HTT_VAR_PADDR32(tx_comp_ring_base_addr), HTT_VAR_PADDR32(tx_comp_wr_idx_addr), HTT_VAR_PADDR32(tx_ce_wr_idx_addr), HTT_VAR_PADDR32(rx_ind_ring_base_addr), HTT_VAR_PADDR32(rx_ind_rd_idx_addr),HTT_VAR_PADDR32(rx_ind_wr_idx_addr), HTT_VAR_PADDR32(rx_ring2_base_addr), HTT_VAR_PADDR32(rx_ring2_rd_idx_addr), HTT_VAR_PADDR32(rx_ring2_wr_idx_addr)); + +/* define a htt_wdi_ipa_config64_t type */ +TEMPLATE_HTT_WDI_IPA_CONFIG_T(64, HTT_VAR_PADDR64_LE(tx_comp_ring_base_addr), HTT_VAR_PADDR64_LE(tx_comp_wr_idx_addr), HTT_VAR_PADDR64_LE(tx_ce_wr_idx_addr), HTT_VAR_PADDR64_LE(rx_ind_ring_base_addr), HTT_VAR_PADDR64_LE(rx_ind_rd_idx_addr), HTT_VAR_PADDR64_LE(rx_ind_wr_idx_addr), HTT_VAR_PADDR64_LE(rx_ring2_base_addr), HTT_VAR_PADDR64_LE(rx_ring2_rd_idx_addr), HTT_VAR_PADDR64_LE(rx_ring2_wr_idx_addr)); + +#if HTT_PADDR64 + #define htt_wdi_ipa_cfg_t htt_wdi_ipa_cfg64_t +#else + #define htt_wdi_ipa_cfg_t htt_wdi_ipa_cfg32_t +#endif + +enum htt_wdi_ipa_op_code { + HTT_WDI_IPA_OPCODE_TX_SUSPEND = 0, + HTT_WDI_IPA_OPCODE_TX_RESUME = 1, + HTT_WDI_IPA_OPCODE_RX_SUSPEND = 2, + HTT_WDI_IPA_OPCODE_RX_RESUME = 3, + HTT_WDI_IPA_OPCODE_DBG_STATS = 4, + /* keep this last */ + HTT_WDI_IPA_OPCODE_MAX +}; + +/** + * @brief HTT WDI_IPA Operation Request Message + * + * @details + * HTT WDI_IPA Operation Request message is sent by host + * to either suspend or resume WDI_IPA TX or RX path. + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | op_code | Rsvd | msg_type | + * |-------------------------------------------------------------------| + * + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: Identifies this as WDI_IPA Operation Request message + * value: = 0x9 + * - OP_CODE + * Bits 31:16 + * Purpose: Identifies operation host is requesting (e.g. TX suspend) + * value: = enum htt_wdi_ipa_op_code + */ + +PREPACK struct htt_wdi_ipa_op_request_t +{ + /* DWORD 0: flags and meta-data */ + A_UINT32 + msg_type: 8, /* HTT_H2T_MSG_TYPE_WDI_IPA_OP_REQUEST */ + reserved: 8, + op_code: 16; +} POSTPACK; + +#define HTT_WDI_IPA_OP_REQUEST_SZ 4 /* bytes */ + +#define HTT_WDI_IPA_OP_REQUEST_OP_CODE_M 0xffff0000 +#define HTT_WDI_IPA_OP_REQUEST_OP_CODE_S 16 + +#define HTT_WDI_IPA_OP_REQUEST_OP_CODE_GET(_var) \ + (((_var) & HTT_WDI_IPA_OP_REQUEST_OP_CODE_M) >> HTT_WDI_IPA_OP_REQUEST_OP_CODE_S) +#define HTT_WDI_IPA_OP_REQUEST_OP_CODE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_OP_REQUEST_OP_CODE, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_OP_REQUEST_OP_CODE_S)); \ + } while (0) + + + + +/*=== target -> host messages ===============================================*/ + + +enum htt_t2h_msg_type { + HTT_T2H_MSG_TYPE_VERSION_CONF = 0x0, + HTT_T2H_MSG_TYPE_RX_IND = 0x1, + HTT_T2H_MSG_TYPE_RX_FLUSH = 0x2, + HTT_T2H_MSG_TYPE_PEER_MAP = 0x3, + HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x4, + HTT_T2H_MSG_TYPE_RX_ADDBA = 0x5, + HTT_T2H_MSG_TYPE_RX_DELBA = 0x6, + HTT_T2H_MSG_TYPE_TX_COMPL_IND = 0x7, + HTT_T2H_MSG_TYPE_PKTLOG = 0x8, + HTT_T2H_MSG_TYPE_STATS_CONF = 0x9, + HTT_T2H_MSG_TYPE_RX_FRAG_IND = 0xa, + HTT_T2H_MSG_TYPE_SEC_IND = 0xb, + DEPRECATED_HTT_T2H_MSG_TYPE_RC_UPDATE_IND = 0xc, /* no longer used */ + HTT_T2H_MSG_TYPE_TX_INSPECT_IND = 0xd, + HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND = 0xe, + /* only used for HL, add HTT MSG for HTT CREDIT update */ + HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND = 0xf, + HTT_T2H_MSG_TYPE_RX_PN_IND = 0x10, + HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND = 0x11, + HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND = 0x12, + /* 0x13 is reserved for RX_RING_LOW_IND (RX Full reordering related) */ + HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE = 0x14, + HTT_T2H_MSG_TYPE_CHAN_CHANGE = 0x15, + HTT_T2H_MSG_TYPE_RX_OFLD_PKT_ERR = 0x16, + HTT_T2H_MSG_TYPE_RATE_REPORT = 0x17, + HTT_T2H_MSG_TYPE_FLOW_POOL_MAP = 0x18, + HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP = 0x19, + + HTT_T2H_MSG_TYPE_TEST, + /* keep this last */ + HTT_T2H_NUM_MSGS +}; + +/* + * HTT target to host message type - + * stored in bits 7:0 of the first word of the message + */ +#define HTT_T2H_MSG_TYPE_M 0xff +#define HTT_T2H_MSG_TYPE_S 0 + +#define HTT_T2H_MSG_TYPE_SET(word, msg_type) \ + do { \ + HTT_CHECK_SET_VAL(HTT_T2H_MSG_TYPE, msg_type); \ + (word) |= ((msg_type) << HTT_T2H_MSG_TYPE_S); \ + } while (0) +#define HTT_T2H_MSG_TYPE_GET(word) \ + (((word) & HTT_T2H_MSG_TYPE_M) >> HTT_T2H_MSG_TYPE_S) + +/** + * @brief target -> host version number confirmation message definition + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | reserved | major number | minor number | msg type | + * |-------------------------------------------------------------------| + * : option request TLV (optional) | + * :...................................................................: + * + * The VER_CONF message may consist of a single 4-byte word, or may be + * extended with TLVs that specify HTT options selected by the target. + * The following option TLVs may be appended to the VER_CONF message: + * - LL_BUS_ADDR_SIZE + * - HL_SUPPRESS_TX_COMPL_IND + * - MAX_TX_QUEUE_GROUPS + * These TLVs may appear in an arbitrary order. Any number of these TLVs + * may be appended to the VER_CONF message (but only one TLV of each type). + * + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a version number confirmation message + * Value: 0x0 + * - VER_MINOR + * Bits 15:8 + * Purpose: Specify the minor number of the HTT message library version + * in use by the target firmware. + * The minor number specifies the specific revision within a range + * of fundamentally compatible HTT message definition revisions. + * Compatible revisions involve adding new messages or perhaps + * adding new fields to existing messages, in a backwards-compatible + * manner. + * Incompatible revisions involve changing the message type values, + * or redefining existing messages. + * Value: minor number + * - VER_MAJOR + * Bits 15:8 + * Purpose: Specify the major number of the HTT message library version + * in use by the target firmware. + * The major number specifies the family of minor revisions that are + * fundamentally compatible with each other, but not with prior or + * later families. + * Value: major number + */ + +#define HTT_VER_CONF_MINOR_M 0x0000ff00 +#define HTT_VER_CONF_MINOR_S 8 +#define HTT_VER_CONF_MAJOR_M 0x00ff0000 +#define HTT_VER_CONF_MAJOR_S 16 + + +#define HTT_VER_CONF_MINOR_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_VER_CONF_MINOR, value); \ + (word) |= (value) << HTT_VER_CONF_MINOR_S; \ + } while (0) +#define HTT_VER_CONF_MINOR_GET(word) \ + (((word) & HTT_VER_CONF_MINOR_M) >> HTT_VER_CONF_MINOR_S) + +#define HTT_VER_CONF_MAJOR_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_VER_CONF_MAJOR, value); \ + (word) |= (value) << HTT_VER_CONF_MAJOR_S; \ + } while (0) +#define HTT_VER_CONF_MAJOR_GET(word) \ + (((word) & HTT_VER_CONF_MAJOR_M) >> HTT_VER_CONF_MAJOR_S) + + +#define HTT_VER_CONF_BYTES 4 + + +/** + * @brief - target -> host HTT Rx In order indication message + * + * @details + * + * |31 24|23 |15|14|13|12|11|10|9|8|7|6|5|4 0| + * |----------------+-------------------+---------------------+---------------| + * | peer ID | | F| O| ext TID | msg type | + * |--------------------------------------------------------------------------| + * | MSDU count | Reserved | vdev id | + * |--------------------------------------------------------------------------| + * | MSDU 0 bus address (bits 31:0) | +#if HTT_PADDR64 + * | MSDU 0 bus address (bits 63:32) | +#endif + * |--------------------------------------------------------------------------| + * | MSDU info | MSDU 0 FW Desc | MSDU 0 Length | + * |--------------------------------------------------------------------------| + * | MSDU 1 bus address (bits 31:0) | +#if HTT_PADDR64 + * | MSDU 1 bus address (bits 63:32) | +#endif + * |--------------------------------------------------------------------------| + * | MSDU info | MSDU 1 FW Desc | MSDU 1 Length | + * |--------------------------------------------------------------------------| + */ + + +/** @brief - MSDU info byte for TCP_CHECKSUM_OFFLOAD use + * + * @details + * bits + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * |-----+----+-------+--------+--------+---------+---------+-----------| + * | reserved | is IP | is UDP | is TCP | is IPv6 |IP chksum| TCP/UDP | + * | | frag | | | | fail |chksum fail| + * |-----+----+-------+--------+--------+---------+---------+-----------| + * (see fw_rx_msdu_info def in wal_rx_desc.h) + */ + +struct htt_rx_in_ord_paddr_ind_hdr_t +{ + A_UINT32 /* word 0 */ + msg_type: 8, + ext_tid: 5, + offload: 1, + frag: 1, + reserved_0: 1, + peer_id: 16; + + A_UINT32 /* word 1 */ + vap_id: 8, + reserved_1: 8, + msdu_cnt: 16; +}; + +struct htt_rx_in_ord_paddr_ind_msdu32_t +{ + A_UINT32 dma_addr; + A_UINT32 + length: 16, + fw_desc: 8, + msdu_info:8; +}; +struct htt_rx_in_ord_paddr_ind_msdu64_t +{ + A_UINT32 dma_addr_lo; + A_UINT32 dma_addr_hi; + A_UINT32 + length: 16, + fw_desc: 8, + msdu_info:8; +}; +#if HTT_PADDR64 + #define htt_rx_in_ord_paddr_ind_msdu_t htt_rx_in_ord_paddr_ind_msdu64_t +#else + #define htt_rx_in_ord_paddr_ind_msdu_t htt_rx_in_ord_paddr_ind_msdu32_t +#endif + + +#define HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES (sizeof(struct htt_rx_in_ord_paddr_ind_hdr_t)) +#define HTT_RX_IN_ORD_PADDR_IND_HDR_DWORDS (HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES >> 2) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTE_OFFSET HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORD_OFFSET HTT_RX_IN_ORD_PADDR_IND_HDR_DWORDS +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTES_64 (sizeof(struct htt_rx_in_ord_paddr_ind_msdu64_t)) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS_64 (HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTES_64 >> 2) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTES_32 (sizeof(struct htt_rx_in_ord_paddr_ind_msdu32_t)) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS_32 (HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTES_32 >> 2) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTES (sizeof(struct htt_rx_in_ord_paddr_ind_msdu_t)) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS (HTT_RX_IN_ORD_PADDR_IND_MSDU_BYTES >> 2) + +#define HTT_RX_IN_ORD_PADDR_IND_EXT_TID_M 0x00001f00 +#define HTT_RX_IN_ORD_PADDR_IND_EXT_TID_S 8 +#define HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_M 0x00002000 +#define HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_S 13 +#define HTT_RX_IN_ORD_PADDR_IND_FRAG_M 0x00004000 +#define HTT_RX_IN_ORD_PADDR_IND_FRAG_S 14 +#define HTT_RX_IN_ORD_PADDR_IND_PEER_ID_M 0xffff0000 +#define HTT_RX_IN_ORD_PADDR_IND_PEER_ID_S 16 +#define HTT_RX_IN_ORD_PADDR_IND_VAP_ID_M 0x000000ff +#define HTT_RX_IN_ORD_PADDR_IND_VAP_ID_S 0 +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_M 0xffff0000 +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_S 16 +/* for systems using 64-bit format for bus addresses */ +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_M 0xffffffff +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_S 0 +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_M 0xffffffff +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_S 0 +/* for systems using 32-bit format for bus addresses */ +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_M 0xffffffff +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_S 0 +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_M 0x0000ffff +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_S 0 +#define HTT_RX_IN_ORD_PADDR_IND_FW_DESC_M 0x00ff0000 +#define HTT_RX_IN_ORD_PADDR_IND_FW_DESC_S 16 +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_M 0xff000000 +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_S 24 + + +#define HTT_RX_IN_ORD_PADDR_IND_EXT_TID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_EXT_TID, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_EXT_TID_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_EXT_TID_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_EXT_TID_M) >> HTT_RX_IN_ORD_PADDR_IND_EXT_TID_S) + +#define HTT_RX_IN_ORD_PADDR_IND_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_PEER_ID, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_PEER_ID_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_PEER_ID_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_PEER_ID_M) >> HTT_RX_IN_ORD_PADDR_IND_PEER_ID_S) + +#define HTT_RX_IN_ORD_PADDR_IND_VAP_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_VAP_ID, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_VAP_ID_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_VAP_ID_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_VAP_ID_M) >> HTT_RX_IN_ORD_PADDR_IND_VAP_ID_S) + +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_M) >> HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_S) + +/* for systems using 64-bit format for bus addresses */ +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_PADDR_HI, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_M) >> HTT_RX_IN_ORD_PADDR_IND_PADDR_HI_S) +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_PADDR_LO, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_M) >> HTT_RX_IN_ORD_PADDR_IND_PADDR_LO_S) + +/* for systems using 32-bit format for bus addresses */ +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_PADDR, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_PADDR_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_PADDR_M) >> HTT_RX_IN_ORD_PADDR_IND_PADDR_S) + +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_M) >> HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_S) + +#define HTT_RX_IN_ORD_PADDR_IND_FW_DESC_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_FW_DESC, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_FW_DESC_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_FW_DESC_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_FW_DESC_M) >> HTT_RX_IN_ORD_PADDR_IND_FW_DESC_S) + +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO, value); \ + (word) |= (value) << HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_M) >> HTT_RX_IN_ORD_PADDR_IND_MSDU_INFO_S) + +#define HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_IND_OFFLOAD, value); \ + (word) |= (value) << HTT_RX_IN_ORD_IND_OFFLOAD_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_M) >> HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_S) + +#define HTT_RX_IN_ORD_PADDR_IND_FRAG_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IN_ORD_IND_FRAG, value); \ + (word) |= (value) << HTT_RX_IN_ORD_IND_FRAG_S; \ + } while (0) +#define HTT_RX_IN_ORD_PADDR_IND_FRAG_GET(word) \ + (((word) & HTT_RX_IN_ORD_PADDR_IND_FRAG_M) >> HTT_RX_IN_ORD_PADDR_IND_FRAG_S) + +/* definitions used within target -> host rx indication message */ + +PREPACK struct htt_rx_ind_hdr_prefix_t +{ + A_UINT32 /* word 0 */ + msg_type: 8, + ext_tid: 5, + release_valid: 1, + flush_valid: 1, + reserved0: 1, + peer_id: 16; + + A_UINT32 /* word 1 */ + flush_start_seq_num: 6, + flush_end_seq_num: 6, + release_start_seq_num: 6, + release_end_seq_num: 6, + num_mpdu_ranges: 8; +} POSTPACK; + +#define HTT_RX_IND_HDR_PREFIX_BYTES (sizeof(struct htt_rx_ind_hdr_prefix_t)) +#define HTT_RX_IND_HDR_PREFIX_SIZE32 (HTT_RX_IND_HDR_PREFIX_BYTES >> 2) + +#define HTT_TGT_RSSI_INVALID 0x80 + +PREPACK struct htt_rx_ppdu_desc_t +{ + #define HTT_RX_IND_PPDU_OFFSET_WORD_RSSI_CMB 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_TIMESTAMP_SUBMICROSEC 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_PHY_ERR_CODE 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_PHY_ERR 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_LEGACY_RATE 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_LEGACY_RATE_SEL 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_END_VALID 0 + #define HTT_RX_IND_PPDU_OFFSET_WORD_START_VALID 0 + A_UINT32 /* word 0 */ + rssi_cmb: 8, + timestamp_submicrosec: 8, + phy_err_code: 8, + phy_err: 1, + legacy_rate: 4, + legacy_rate_sel: 1, + end_valid: 1, + start_valid: 1; + + #define HTT_RX_IND_PPDU_OFFSET_WORD_RSSI0 1 + union { + A_UINT32 /* word 1 */ + rssi0_pri20: 8, + rssi0_ext20: 8, + rssi0_ext40: 8, + rssi0_ext80: 8; + A_UINT32 rssi0; /* access all 20/40/80 per-bandwidth RSSIs together */ + } u0; + + #define HTT_RX_IND_PPDU_OFFSET_WORD_RSSI1 2 + union { + A_UINT32 /* word 2 */ + rssi1_pri20: 8, + rssi1_ext20: 8, + rssi1_ext40: 8, + rssi1_ext80: 8; + A_UINT32 rssi1; /* access all 20/40/80 per-bandwidth RSSIs together */ + } u1; + + #define HTT_RX_IND_PPDU_OFFSET_WORD_RSSI2 3 + union { + A_UINT32 /* word 3 */ + rssi2_pri20: 8, + rssi2_ext20: 8, + rssi2_ext40: 8, + rssi2_ext80: 8; + A_UINT32 rssi2; /* access all 20/40/80 per-bandwidth RSSIs together */ + } u2; + + #define HTT_RX_IND_PPDU_OFFSET_WORD_RSSI3 4 + union { + A_UINT32 /* word 4 */ + rssi3_pri20: 8, + rssi3_ext20: 8, + rssi3_ext40: 8, + rssi3_ext80: 8; + A_UINT32 rssi3; /* access all 20/40/80 per-bandwidth RSSIs together */ + } u3; + + #define HTT_RX_IND_PPDU_OFFSET_WORD_TSF32 5 + A_UINT32 tsf32; /* word 5 */ + + #define HTT_RX_IND_PPDU_OFFSET_WORD_TIMESTAMP_MICROSEC 6 + A_UINT32 timestamp_microsec; /* word 6 */ + + #define HTT_RX_IND_PPDU_OFFSET_WORD_PREAMBLE_TYPE 7 + #define HTT_RX_IND_PPDU_OFFSET_WORD_VHT_SIG_A1 7 + A_UINT32 /* word 7 */ + vht_sig_a1: 24, + preamble_type: 8; + + #define HTT_RX_IND_PPDU_OFFSET_WORD_VHT_SIG_A2 8 + A_UINT32 /* word 8 */ + vht_sig_a2: 24, + reserved0: 8; +} POSTPACK; + +#define HTT_RX_PPDU_DESC_BYTES (sizeof(struct htt_rx_ppdu_desc_t)) +#define HTT_RX_PPDU_DESC_SIZE32 (HTT_RX_PPDU_DESC_BYTES >> 2) + +PREPACK struct htt_rx_ind_hdr_suffix_t +{ + A_UINT32 /* word 0 */ + fw_rx_desc_bytes: 16, + reserved0: 16; +} POSTPACK; + +#define HTT_RX_IND_HDR_SUFFIX_BYTES (sizeof(struct htt_rx_ind_hdr_suffix_t)) +#define HTT_RX_IND_HDR_SUFFIX_SIZE32 (HTT_RX_IND_HDR_SUFFIX_BYTES >> 2) + +PREPACK struct htt_rx_ind_hdr_t +{ + struct htt_rx_ind_hdr_prefix_t prefix; + struct htt_rx_ppdu_desc_t rx_ppdu_desc; + struct htt_rx_ind_hdr_suffix_t suffix; +} POSTPACK; + +#define HTT_RX_IND_HDR_BYTES (sizeof(struct htt_rx_ind_hdr_t)) +#define HTT_RX_IND_HDR_SIZE32 (HTT_RX_IND_HDR_BYTES >> 2) + +/* confirm that HTT_RX_IND_HDR_BYTES is a multiple of 4 */ +A_COMPILE_TIME_ASSERT(HTT_RX_IND_hdr_size_quantum, + (HTT_RX_IND_HDR_BYTES & 0x3) == 0); + +/* + * HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET: + * the offset into the HTT rx indication message at which the + * FW rx PPDU descriptor resides + */ +#define HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET HTT_RX_IND_HDR_PREFIX_BYTES + +/* + * HTT_RX_IND_HDR_SUFFIX_BYTE_OFFSET: + * the offset into the HTT rx indication message at which the + * header suffix (FW rx MSDU byte count) resides + */ +#define HTT_RX_IND_HDR_SUFFIX_BYTE_OFFSET \ + (HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET + HTT_RX_PPDU_DESC_BYTES) + +/* + * HTT_RX_IND_FW_RX_DESC_BYTE_OFFSET: + * the offset into the HTT rx indication message at which the per-MSDU + * information starts + * Bytes 0-7 are the message header; bytes 8-11 contain the length of the + * per-MSDU information portion of the message. The per-MSDU info itself + * starts at byte 12. + */ +#define HTT_RX_IND_FW_RX_DESC_BYTE_OFFSET HTT_RX_IND_HDR_BYTES + + +/** + * @brief target -> host rx indication message definition + * + * @details + * The following field definitions describe the format of the rx indication + * message sent from the target to the host. + * The message consists of three major sections: + * 1. a fixed-length header + * 2. a variable-length list of firmware rx MSDU descriptors + * 3. one or more 4-octet MPDU range information elements + * The fixed length header itself has two sub-sections + * 1. the message meta-information, including identification of the + * sender and type of the received data, and a 4-octet flush/release IE + * 2. the firmware rx PPDU descriptor + * + * The format of the message is depicted below. + * in this depiction, the following abbreviations are used for information + * elements within the message: + * - SV - start valid: this flag is set if the FW rx PPDU descriptor + * elements associated with the PPDU start are valid. + * Specifically, the following fields are valid only if SV is set: + * RSSI (all variants), L, legacy rate, preamble type, service, + * VHT-SIG-A + * - EV - end valid: this flag is set if the FW rx PPDU descriptor + * elements associated with the PPDU end are valid. + * Specifically, the following fields are valid only if EV is set: + * P, PHY err code, TSF, microsec / sub-microsec timestamp + * - L - Legacy rate selector - if legacy rates are used, this flag + * indicates whether the rate is from a CCK (L == 1) or OFDM + * (L == 0) PHY. + * - P - PHY error flag - boolean indication of whether the rx frame had + * a PHY error + * + * |31 24|23 18|17|16|15|14|13|12|11|10|9|8|7|6|5|4 0| + * |----------------+-------------------+---------------------+---------------| + * | peer ID | |RV|FV| ext TID | msg type | + * |--------------------------------------------------------------------------| + * | num | release | release | flush | flush | + * | MPDU | end | start | end | start | + * | ranges | seq num | seq num | seq num | seq num | + * |==========================================================================| + * |S|E|L| legacy |P| PHY err code | sub-microsec | combined | + * |V|V| | rate | | | timestamp | RSSI | + * |--------------------------------------------------------------------------| + * | RSSI rx0 ext80 | RSSI rx0 ext40 | RSSI rx0 ext20 | RSSI rx0 pri20| + * |--------------------------------------------------------------------------| + * | RSSI rx1 ext80 | RSSI rx1 ext40 | RSSI rx1 ext20 | RSSI rx1 pri20| + * |--------------------------------------------------------------------------| + * | RSSI rx2 ext80 | RSSI rx2 ext40 | RSSI rx2 ext20 | RSSI rx2 pri20| + * |--------------------------------------------------------------------------| + * | RSSI rx3 ext80 | RSSI rx3 ext40 | RSSI rx3 ext20 | RSSI rx3 pri20| + * |--------------------------------------------------------------------------| + * | TSF LSBs | + * |--------------------------------------------------------------------------| + * | microsec timestamp | + * |--------------------------------------------------------------------------| + * | preamble type | HT-SIG / VHT-SIG-A1 | + * |--------------------------------------------------------------------------| + * | service | HT-SIG / VHT-SIG-A2 | + * |==========================================================================| + * | reserved | FW rx desc bytes | + * |--------------------------------------------------------------------------| + * | MSDU Rx | MSDU Rx | MSDU Rx | MSDU Rx | + * | desc B3 | desc B2 | desc B1 | desc B0 | + * |--------------------------------------------------------------------------| + * : : : + * |--------------------------------------------------------------------------| + * | alignment | MSDU Rx | + * | padding | desc Bn | + * |--------------------------------------------------------------------------| + * | reserved | MPDU range status | MPDU count | + * |--------------------------------------------------------------------------| + * : reserved : MPDU range status : MPDU count : + * :- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - : + * + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx indication message + * Value: 0x1 + * - EXT_TID + * Bits 12:8 + * Purpose: identify the traffic ID of the rx data, including + * special "extended" TID values for multicast, broadcast, and + * non-QoS data frames + * Value: 0-15 for regular TIDs, or >= 16 for bcast/mcast/non-QoS + * - FLUSH_VALID (FV) + * Bit 13 + * Purpose: indicate whether the flush IE (start/end sequence numbers) + * is valid + * Value: + * 1 -> flush IE is valid and needs to be processed + * 0 -> flush IE is not valid and should be ignored + * - REL_VALID (RV) + * Bit 13 + * Purpose: indicate whether the release IE (start/end sequence numbers) + * is valid + * Value: + * 1 -> release IE is valid and needs to be processed + * 0 -> release IE is not valid and should be ignored + * - PEER_ID + * Bits 31:16 + * Purpose: Identify, by ID, which peer sent the rx data + * Value: ID of the peer who sent the rx data + * - FLUSH_SEQ_NUM_START + * Bits 5:0 + * Purpose: Indicate the start of a series of MPDUs to flush + * Not all MPDUs within this series are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + * This field is only valid if the FV bit is set. + * Value: + * The sequence number for the first MPDUs to check to flush. + * The sequence number is masked by 0x3f. + * - FLUSH_SEQ_NUM_END + * Bits 11:6 + * Purpose: Indicate the end of a series of MPDUs to flush + * Value: + * The sequence number one larger than the sequence number of the + * last MPDU to check to flush. + * The sequence number is masked by 0x3f. + * Not all MPDUs within this series are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + * This field is only valid if the FV bit is set. + * - REL_SEQ_NUM_START + * Bits 17:12 + * Purpose: Indicate the start of a series of MPDUs to release. + * All MPDUs within this series are present and valid - the host + * need not check each sequence number within this range to see if + * the corresponding MPDU is actually present. + * This field is only valid if the RV bit is set. + * Value: + * The sequence number for the first MPDUs to check to release. + * The sequence number is masked by 0x3f. + * - REL_SEQ_NUM_END + * Bits 23:18 + * Purpose: Indicate the end of a series of MPDUs to release. + * Value: + * The sequence number one larger than the sequence number of the + * last MPDU to check to release. + * The sequence number is masked by 0x3f. + * All MPDUs within this series are present and valid - the host + * need not check each sequence number within this range to see if + * the corresponding MPDU is actually present. + * This field is only valid if the RV bit is set. + * - NUM_MPDU_RANGES + * Bits 31:24 + * Purpose: Indicate how many ranges of MPDUs are present. + * Each MPDU range consists of a series of contiguous MPDUs within the + * rx frame sequence which all have the same MPDU status. + * Value: 1-63 (typically a small number, like 1-3) + * + * Rx PPDU descriptor fields: + * - RSSI_CMB + * Bits 7:0 + * Purpose: Combined RSSI from all active rx chains, across the active + * bandwidth. + * Value: RSSI dB units w.r.t. noise floor + * - TIMESTAMP_SUBMICROSEC + * Bits 15:8 + * Purpose: high-resolution timestamp + * Value: + * Sub-microsecond time of PPDU reception. + * This timestamp ranges from [0,MAC clock MHz). + * This timestamp can be used in conjunction with TIMESTAMP_MICROSEC + * to form a high-resolution, large range rx timestamp. + * - PHY_ERR_CODE + * Bits 23:16 + * Purpose: + * If the rx frame processing resulted in a PHY error, indicate what + * type of rx PHY error occurred. + * Value: + * This field is valid if the "P" (PHY_ERR) flag is set. + * TBD: document/specify the values for this field + * - PHY_ERR + * Bit 24 + * Purpose: indicate whether the rx PPDU had a PHY error + * Value: 0 -> no rx PHY error, 1 -> rx PHY error encountered + * - LEGACY_RATE + * Bits 28:25 + * Purpose: + * If the rx frame used a legacy rate rather than a HT or VHT rate, + * specify which rate was used. + * Value: + * The LEGACY_RATE field's value depends on the "L" (LEGACY_RATE_SEL) + * flag. + * If LEGACY_RATE_SEL is 0: + * 0x8: OFDM 48 Mbps + * 0x9: OFDM 24 Mbps + * 0xA: OFDM 12 Mbps + * 0xB: OFDM 6 Mbps + * 0xC: OFDM 54 Mbps + * 0xD: OFDM 36 Mbps + * 0xE: OFDM 18 Mbps + * 0xF: OFDM 9 Mbps + * If LEGACY_RATE_SEL is 1: + * 0x8: CCK 11 Mbps long preamble + * 0x9: CCK 5.5 Mbps long preamble + * 0xA: CCK 2 Mbps long preamble + * 0xB: CCK 1 Mbps long preamble + * 0xC: CCK 11 Mbps short preamble + * 0xD: CCK 5.5 Mbps short preamble + * 0xE: CCK 2 Mbps short preamble + * - LEGACY_RATE_SEL + * Bit 29 + * Purpose: if rx used a legacy rate, specify whether it was OFDM or CCK + * Value: + * This field is valid if the PREAMBLE_TYPE field indicates the rx + * used a legacy rate. + * 0 -> OFDM, 1 -> CCK + * - END_VALID + * Bit 30 + * Purpose: Indicate whether the FW rx PPDU desc fields associated with + * the start of the PPDU are valid. Specifically, the following + * fields are only valid if END_VALID is set: + * PHY_ERR, PHY_ERR_CODE, TSF32, TIMESTAMP_MICROSEC, + * TIMESTAMP_SUBMICROSEC + * Value: + * 0 -> rx PPDU desc end fields are not valid + * 1 -> rx PPDU desc end fields are valid + * - START_VALID + * Bit 31 + * Purpose: Indicate whether the FW rx PPDU desc fields associated with + * the end of the PPDU are valid. Specifically, the following + * fields are only valid if START_VALID is set: + * RSSI, LEGACY_RATE_SEL, LEGACY_RATE, PREAMBLE_TYPE, SERVICE, + * VHT-SIG-A + * Value: + * 0 -> rx PPDU desc start fields are not valid + * 1 -> rx PPDU desc start fields are valid + * - RSSI0_PRI20 + * Bits 7:0 + * Purpose: RSSI from chain 0 on the primary 20 MHz channel + * Value: RSSI dB units w.r.t. noise floor + * + * - RSSI0_EXT20 + * Bits 7:0 + * Purpose: RSSI from chain 0 on the bonded extension 20 MHz channel + * (if the rx bandwidth was >= 40 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI0_EXT40 + * Bits 7:0 + * Purpose: RSSI from chain 0 on the bonded extension 40 MHz channel + * (if the rx bandwidth was >= 80 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI0_EXT80 + * Bits 7:0 + * Purpose: RSSI from chain 0 on the bonded extension 80 MHz channel + * (if the rx bandwidth was >= 160 MHz) + * Value: RSSI dB units w.r.t. noise floor + * + * - RSSI1_PRI20 + * Bits 7:0 + * Purpose: RSSI from chain 1 on the primary 20 MHz channel + * Value: RSSI dB units w.r.t. noise floor + * - RSSI1_EXT20 + * Bits 7:0 + * Purpose: RSSI from chain 1 on the bonded extension 20 MHz channel + * (if the rx bandwidth was >= 40 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI1_EXT40 + * Bits 7:0 + * Purpose: RSSI from chain 1 on the bonded extension 40 MHz channel + * (if the rx bandwidth was >= 80 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI1_EXT80 + * Bits 7:0 + * Purpose: RSSI from chain 1 on the bonded extension 80 MHz channel + * (if the rx bandwidth was >= 160 MHz) + * Value: RSSI dB units w.r.t. noise floor + * + * - RSSI2_PRI20 + * Bits 7:0 + * Purpose: RSSI from chain 2 on the primary 20 MHz channel + * Value: RSSI dB units w.r.t. noise floor + * - RSSI2_EXT20 + * Bits 7:0 + * Purpose: RSSI from chain 2 on the bonded extension 20 MHz channel + * (if the rx bandwidth was >= 40 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI2_EXT40 + * Bits 7:0 + * Purpose: RSSI from chain 2 on the bonded extension 40 MHz channel + * (if the rx bandwidth was >= 80 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI2_EXT80 + * Bits 7:0 + * Purpose: RSSI from chain 2 on the bonded extension 80 MHz channel + * (if the rx bandwidth was >= 160 MHz) + * Value: RSSI dB units w.r.t. noise floor + * + * - RSSI3_PRI20 + * Bits 7:0 + * Purpose: RSSI from chain 3 on the primary 20 MHz channel + * Value: RSSI dB units w.r.t. noise floor + * - RSSI3_EXT20 + * Bits 7:0 + * Purpose: RSSI from chain 3 on the bonded extension 20 MHz channel + * (if the rx bandwidth was >= 40 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI3_EXT40 + * Bits 7:0 + * Purpose: RSSI from chain 3 on the bonded extension 40 MHz channel + * (if the rx bandwidth was >= 80 MHz) + * Value: RSSI dB units w.r.t. noise floor + * - RSSI3_EXT80 + * Bits 7:0 + * Purpose: RSSI from chain 3 on the bonded extension 80 MHz channel + * (if the rx bandwidth was >= 160 MHz) + * Value: RSSI dB units w.r.t. noise floor + * + * - TSF32 + * Bits 31:0 + * Purpose: specify the time the rx PPDU was received, in TSF units + * Value: 32 LSBs of the TSF + * - TIMESTAMP_MICROSEC + * Bits 31:0 + * Purpose: specify the time the rx PPDU was received, in microsecond units + * Value: PPDU rx time, in microseconds + * - VHT_SIG_A1 + * Bits 23:0 + * Purpose: Provide the HT-SIG (initial 24 bits) or VHT-SIG-A1 field + * from the rx PPDU + * Value: + * If PREAMBLE_TYPE specifies VHT, then this field contains the + * VHT-SIG-A1 data. + * If PREAMBLE_TYPE specifies HT, then this field contains the + * first 24 bits of the HT-SIG data. + * Otherwise, this field is invalid. + * Refer to the the 802.11 protocol for the definition of the + * HT-SIG and VHT-SIG-A1 fields + * - VHT_SIG_A2 + * Bits 23:0 + * Purpose: Provide the HT-SIG (final 24 bits) or VHT-SIG-A2 field + * from the rx PPDU + * Value: + * If PREAMBLE_TYPE specifies VHT, then this field contains the + * VHT-SIG-A2 data. + * If PREAMBLE_TYPE specifies HT, then this field contains the + * last 24 bits of the HT-SIG data. + * Otherwise, this field is invalid. + * Refer to the the 802.11 protocol for the definition of the + * HT-SIG and VHT-SIG-A2 fields + * - PREAMBLE_TYPE + * Bits 31:24 + * Purpose: indicate the PHY format of the received burst + * Value: + * 0x4: Legacy (OFDM/CCK) + * 0x8: HT + * 0x9: HT with TxBF + * 0xC: VHT + * 0xD: VHT with TxBF + * - SERVICE + * Bits 31:24 + * Purpose: TBD + * Value: TBD + * + * Rx MSDU descriptor fields: + * - FW_RX_DESC_BYTES + * Bits 15:0 + * Purpose: Indicate how many bytes in the Rx indication are used for + * FW Rx descriptors + * + * Payload fields: + * - MPDU_COUNT + * Bits 7:0 + * Purpose: Indicate how many sequential MPDUs share the same status. + * All MPDUs within the indicated list are from the same RA-TA-TID. + * - MPDU_STATUS + * Bits 15:8 + * Purpose: Indicate whether the (group of sequential) MPDU(s) were + * received successfully. + * Value: + * 0x1: success + * 0x2: FCS error + * 0x3: duplicate error + * 0x4: replay error + * 0x5: invalid peer + */ +/* header fields */ +#define HTT_RX_IND_EXT_TID_M 0x1f00 +#define HTT_RX_IND_EXT_TID_S 8 +#define HTT_RX_IND_FLUSH_VALID_M 0x2000 +#define HTT_RX_IND_FLUSH_VALID_S 13 +#define HTT_RX_IND_REL_VALID_M 0x4000 +#define HTT_RX_IND_REL_VALID_S 14 +#define HTT_RX_IND_PEER_ID_M 0xffff0000 +#define HTT_RX_IND_PEER_ID_S 16 + +#define HTT_RX_IND_FLUSH_SEQ_NUM_START_M 0x3f +#define HTT_RX_IND_FLUSH_SEQ_NUM_START_S 0 +#define HTT_RX_IND_FLUSH_SEQ_NUM_END_M 0xfc0 +#define HTT_RX_IND_FLUSH_SEQ_NUM_END_S 6 +#define HTT_RX_IND_REL_SEQ_NUM_START_M 0x3f000 +#define HTT_RX_IND_REL_SEQ_NUM_START_S 12 +#define HTT_RX_IND_REL_SEQ_NUM_END_M 0xfc0000 +#define HTT_RX_IND_REL_SEQ_NUM_END_S 18 +#define HTT_RX_IND_NUM_MPDU_RANGES_M 0xff000000 +#define HTT_RX_IND_NUM_MPDU_RANGES_S 24 + +/* rx PPDU descriptor fields */ +#define HTT_RX_IND_RSSI_CMB_M 0x000000ff +#define HTT_RX_IND_RSSI_CMB_S 0 +#define HTT_RX_IND_TIMESTAMP_SUBMICROSEC_M 0x0000ff00 +#define HTT_RX_IND_TIMESTAMP_SUBMICROSEC_S 8 +#define HTT_RX_IND_PHY_ERR_CODE_M 0x00ff0000 +#define HTT_RX_IND_PHY_ERR_CODE_S 16 +#define HTT_RX_IND_PHY_ERR_M 0x01000000 +#define HTT_RX_IND_PHY_ERR_S 24 +#define HTT_RX_IND_LEGACY_RATE_M 0x1e000000 +#define HTT_RX_IND_LEGACY_RATE_S 25 +#define HTT_RX_IND_LEGACY_RATE_SEL_M 0x20000000 +#define HTT_RX_IND_LEGACY_RATE_SEL_S 29 +#define HTT_RX_IND_END_VALID_M 0x40000000 +#define HTT_RX_IND_END_VALID_S 30 +#define HTT_RX_IND_START_VALID_M 0x80000000 +#define HTT_RX_IND_START_VALID_S 31 + +#define HTT_RX_IND_RSSI_PRI20_M 0x000000ff +#define HTT_RX_IND_RSSI_PRI20_S 0 +#define HTT_RX_IND_RSSI_EXT20_M 0x0000ff00 +#define HTT_RX_IND_RSSI_EXT20_S 8 +#define HTT_RX_IND_RSSI_EXT40_M 0x00ff0000 +#define HTT_RX_IND_RSSI_EXT40_S 16 +#define HTT_RX_IND_RSSI_EXT80_M 0xff000000 +#define HTT_RX_IND_RSSI_EXT80_S 24 + +#define HTT_RX_IND_VHT_SIG_A1_M 0x00ffffff +#define HTT_RX_IND_VHT_SIG_A1_S 0 +#define HTT_RX_IND_VHT_SIG_A2_M 0x00ffffff +#define HTT_RX_IND_VHT_SIG_A2_S 0 +#define HTT_RX_IND_PREAMBLE_TYPE_M 0xff000000 +#define HTT_RX_IND_PREAMBLE_TYPE_S 24 +#define HTT_RX_IND_SERVICE_M 0xff000000 +#define HTT_RX_IND_SERVICE_S 24 + +/* rx MSDU descriptor fields */ +#define HTT_RX_IND_FW_RX_DESC_BYTES_M 0xffff +#define HTT_RX_IND_FW_RX_DESC_BYTES_S 0 + +/* payload fields */ +#define HTT_RX_IND_MPDU_COUNT_M 0xff +#define HTT_RX_IND_MPDU_COUNT_S 0 +#define HTT_RX_IND_MPDU_STATUS_M 0xff00 +#define HTT_RX_IND_MPDU_STATUS_S 8 + + +#define HTT_RX_IND_EXT_TID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_EXT_TID, value); \ + (word) |= (value) << HTT_RX_IND_EXT_TID_S; \ + } while (0) +#define HTT_RX_IND_EXT_TID_GET(word) \ + (((word) & HTT_RX_IND_EXT_TID_M) >> HTT_RX_IND_EXT_TID_S) + +#define HTT_RX_IND_FLUSH_VALID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_FLUSH_VALID, value); \ + (word) |= (value) << HTT_RX_IND_FLUSH_VALID_S; \ + } while (0) +#define HTT_RX_IND_FLUSH_VALID_GET(word) \ + (((word) & HTT_RX_IND_FLUSH_VALID_M) >> HTT_RX_IND_FLUSH_VALID_S) + +#define HTT_RX_IND_REL_VALID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_REL_VALID, value); \ + (word) |= (value) << HTT_RX_IND_REL_VALID_S; \ + } while (0) +#define HTT_RX_IND_REL_VALID_GET(word) \ + (((word) & HTT_RX_IND_REL_VALID_M) >> HTT_RX_IND_REL_VALID_S) + +#define HTT_RX_IND_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_PEER_ID, value); \ + (word) |= (value) << HTT_RX_IND_PEER_ID_S; \ + } while (0) +#define HTT_RX_IND_PEER_ID_GET(word) \ + (((word) & HTT_RX_IND_PEER_ID_M) >> HTT_RX_IND_PEER_ID_S) + + +#define HTT_RX_IND_FW_RX_DESC_BYTES_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_FW_RX_DESC_BYTES, value); \ + (word) |= (value) << HTT_RX_IND_FW_RX_DESC_BYTES_S; \ + } while (0) +#define HTT_RX_IND_FW_RX_DESC_BYTES_GET(word) \ + (((word) & HTT_RX_IND_FW_RX_DESC_BYTES_M) >> HTT_RX_IND_FW_RX_DESC_BYTES_S) + + +#define HTT_RX_IND_FLUSH_SEQ_NUM_START_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_FLUSH_SEQ_NUM_START, value); \ + (word) |= (value) << HTT_RX_IND_FLUSH_SEQ_NUM_START_S; \ + } while (0) +#define HTT_RX_IND_FLUSH_SEQ_NUM_START_GET(word) \ + (((word) & HTT_RX_IND_FLUSH_SEQ_NUM_START_M) >> \ + HTT_RX_IND_FLUSH_SEQ_NUM_START_S) + +#define HTT_RX_IND_FLUSH_SEQ_NUM_END_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_FLUSH_SEQ_NUM_END, value); \ + (word) |= (value) << HTT_RX_IND_FLUSH_SEQ_NUM_END_S; \ + } while (0) +#define HTT_RX_IND_FLUSH_SEQ_NUM_END_GET(word) \ + (((word) & HTT_RX_IND_FLUSH_SEQ_NUM_END_M) >> \ + HTT_RX_IND_FLUSH_SEQ_NUM_END_S) + +#define HTT_RX_IND_REL_SEQ_NUM_START_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_REL_SEQ_NUM_START, value); \ + (word) |= (value) << HTT_RX_IND_REL_SEQ_NUM_START_S; \ + } while (0) +#define HTT_RX_IND_REL_SEQ_NUM_START_GET(word) \ + (((word) & HTT_RX_IND_REL_SEQ_NUM_START_M) >> \ + HTT_RX_IND_REL_SEQ_NUM_START_S) + +#define HTT_RX_IND_REL_SEQ_NUM_END_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_REL_SEQ_NUM_END, value); \ + (word) |= (value) << HTT_RX_IND_REL_SEQ_NUM_END_S; \ + } while (0) +#define HTT_RX_IND_REL_SEQ_NUM_END_GET(word) \ + (((word) & HTT_RX_IND_REL_SEQ_NUM_END_M) >> \ + HTT_RX_IND_REL_SEQ_NUM_END_S) + +#define HTT_RX_IND_NUM_MPDU_RANGES_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_NUM_MPDU_RANGES, value); \ + (word) |= (value) << HTT_RX_IND_NUM_MPDU_RANGES_S; \ + } while (0) +#define HTT_RX_IND_NUM_MPDU_RANGES_GET(word) \ + (((word) & HTT_RX_IND_NUM_MPDU_RANGES_M) >> \ + HTT_RX_IND_NUM_MPDU_RANGES_S) + +/* FW rx PPDU descriptor fields */ +#define HTT_RX_IND_RSSI_CMB_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_RSSI_CMB, value); \ + (word) |= (value) << HTT_RX_IND_RSSI_CMB_S; \ + } while (0) +#define HTT_RX_IND_RSSI_CMB_GET(word) \ + (((word) & HTT_RX_IND_RSSI_CMB_M) >> \ + HTT_RX_IND_RSSI_CMB_S) + +#define HTT_RX_IND_TIMESTAMP_SUBMICROSEC_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_TIMESTAMP_SUBMICROSEC, value); \ + (word) |= (value) << HTT_RX_IND_TIMESTAMP_SUBMICROSEC_S; \ + } while (0) +#define HTT_RX_IND_TIMESTAMP_SUBMICROSEC_GET(word) \ + (((word) & HTT_RX_IND_TIMESTAMP_SUBMICROSEC_M) >> \ + HTT_RX_IND_TIMESTAMP_SUBMICROSEC_S) + +#define HTT_RX_IND_PHY_ERR_CODE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_PHY_ERR_CODE, value); \ + (word) |= (value) << HTT_RX_IND_PHY_ERR_CODE_S; \ + } while (0) +#define HTT_RX_IND_PHY_ERR_CODE_GET(word) \ + (((word) & HTT_RX_IND_PHY_ERR_CODE_M) >> \ + HTT_RX_IND_PHY_ERR_CODE_S) + +#define HTT_RX_IND_PHY_ERR_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_PHY_ERR, value); \ + (word) |= (value) << HTT_RX_IND_PHY_ERR_S; \ + } while (0) +#define HTT_RX_IND_PHY_ERR_GET(word) \ + (((word) & HTT_RX_IND_PHY_ERR_M) >> \ + HTT_RX_IND_PHY_ERR_S) + +#define HTT_RX_IND_LEGACY_RATE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_LEGACY_RATE, value); \ + (word) |= (value) << HTT_RX_IND_LEGACY_RATE_S; \ + } while (0) +#define HTT_RX_IND_LEGACY_RATE_GET(word) \ + (((word) & HTT_RX_IND_LEGACY_RATE_M) >> \ + HTT_RX_IND_LEGACY_RATE_S) + +#define HTT_RX_IND_LEGACY_RATE_SEL_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_LEGACY_RATE_SEL, value); \ + (word) |= (value) << HTT_RX_IND_LEGACY_RATE_SEL_S; \ + } while (0) +#define HTT_RX_IND_LEGACY_RATE_SEL_GET(word) \ + (((word) & HTT_RX_IND_LEGACY_RATE_SEL_M) >> \ + HTT_RX_IND_LEGACY_RATE_SEL_S) + +#define HTT_RX_IND_END_VALID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_END_VALID, value); \ + (word) |= (value) << HTT_RX_IND_END_VALID_S; \ + } while (0) +#define HTT_RX_IND_END_VALID_GET(word) \ + (((word) & HTT_RX_IND_END_VALID_M) >> \ + HTT_RX_IND_END_VALID_S) + +#define HTT_RX_IND_START_VALID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_START_VALID, value); \ + (word) |= (value) << HTT_RX_IND_START_VALID_S; \ + } while (0) +#define HTT_RX_IND_START_VALID_GET(word) \ + (((word) & HTT_RX_IND_START_VALID_M) >> \ + HTT_RX_IND_START_VALID_S) + +#define HTT_RX_IND_RSSI_PRI20_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_RSSI_PRI20, value); \ + (word) |= (value) << HTT_RX_IND_RSSI_PRI20_S; \ + } while (0) +#define HTT_RX_IND_RSSI_PRI20_GET(word) \ + (((word) & HTT_RX_IND_RSSI_PRI20_M) >> \ + HTT_RX_IND_RSSI_PRI20_S) + +#define HTT_RX_IND_RSSI_EXT20_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_RSSI_EXT20, value); \ + (word) |= (value) << HTT_RX_IND_RSSI_EXT20_S; \ + } while (0) +#define HTT_RX_IND_RSSI_EXT20_GET(word) \ + (((word) & HTT_RX_IND_RSSI_EXT20_M) >> \ + HTT_RX_IND_RSSI_EXT20_S) + +#define HTT_RX_IND_RSSI_EXT40_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_RSSI_EXT40, value); \ + (word) |= (value) << HTT_RX_IND_RSSI_EXT40_S; \ + } while (0) +#define HTT_RX_IND_RSSI_EXT40_GET(word) \ + (((word) & HTT_RX_IND_RSSI_EXT40_M) >> \ + HTT_RX_IND_RSSI_EXT40_S) + +#define HTT_RX_IND_RSSI_EXT80_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_RSSI_EXT80, value); \ + (word) |= (value) << HTT_RX_IND_RSSI_EXT80_S; \ + } while (0) +#define HTT_RX_IND_RSSI_EXT80_GET(word) \ + (((word) & HTT_RX_IND_RSSI_EXT80_M) >> \ + HTT_RX_IND_RSSI_EXT80_S) + +#define HTT_RX_IND_VHT_SIG_A1_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_VHT_SIG_A1, value); \ + (word) |= (value) << HTT_RX_IND_VHT_SIG_A1_S; \ + } while (0) +#define HTT_RX_IND_VHT_SIG_A1_GET(word) \ + (((word) & HTT_RX_IND_VHT_SIG_A1_M) >> \ + HTT_RX_IND_VHT_SIG_A1_S) + +#define HTT_RX_IND_VHT_SIG_A2_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_VHT_SIG_A2, value); \ + (word) |= (value) << HTT_RX_IND_VHT_SIG_A2_S; \ + } while (0) +#define HTT_RX_IND_VHT_SIG_A2_GET(word) \ + (((word) & HTT_RX_IND_VHT_SIG_A2_M) >> \ + HTT_RX_IND_VHT_SIG_A2_S) + +#define HTT_RX_IND_PREAMBLE_TYPE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_PREAMBLE_TYPE, value); \ + (word) |= (value) << HTT_RX_IND_PREAMBLE_TYPE_S; \ + } while (0) +#define HTT_RX_IND_PREAMBLE_TYPE_GET(word) \ + (((word) & HTT_RX_IND_PREAMBLE_TYPE_M) >> \ + HTT_RX_IND_PREAMBLE_TYPE_S) + +#define HTT_RX_IND_SERVICE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_SERVICE, value); \ + (word) |= (value) << HTT_RX_IND_SERVICE_S; \ + } while (0) +#define HTT_RX_IND_SERVICE_GET(word) \ + (((word) & HTT_RX_IND_SERVICE_M) >> \ + HTT_RX_IND_SERVICE_S) + + +#define HTT_RX_IND_MPDU_COUNT_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_MPDU_COUNT, value); \ + (word) |= (value) << HTT_RX_IND_MPDU_COUNT_S; \ + } while (0) +#define HTT_RX_IND_MPDU_COUNT_GET(word) \ + (((word) & HTT_RX_IND_MPDU_COUNT_M) >> HTT_RX_IND_MPDU_COUNT_S) + +#define HTT_RX_IND_MPDU_STATUS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_IND_MPDU_STATUS, value); \ + (word) |= (value) << HTT_RX_IND_MPDU_STATUS_S; \ + } while (0) +#define HTT_RX_IND_MPDU_STATUS_GET(word) \ + (((word) & HTT_RX_IND_MPDU_STATUS_M) >> HTT_RX_IND_MPDU_STATUS_S) + + +#define HTT_RX_IND_HL_BYTES \ + (HTT_RX_IND_HDR_BYTES + \ + 4 /* single FW rx MSDU descriptor, plus padding */ + \ + 4 /* single MPDU range information element */) +#define HTT_RX_IND_HL_SIZE32 (HTT_RX_IND_HL_BYTES >> 2) + +// Could we use one macro entry? +#define HTT_WORD_SET(word, field, value) \ + do { \ + HTT_CHECK_SET_VAL(field, value); \ + (word) |= ((value) << field ## _S); \ + } while (0) +#define HTT_WORD_GET(word, field) \ + (((word) & field ## _M) >> field ## _S) + +PREPACK struct hl_htt_rx_ind_base { + A_UINT32 rx_ind_msg[HTT_RX_IND_HL_SIZE32]; /* algin with LL case rx indication message, but reduced to 5 words */ +} POSTPACK; + +/* + * HTT_RX_IND_HL_RX_DESC_BASE_OFFSET + * Currently, we use a resv field in hl_htt_rx_ind_base to store some + * HL host needed info. The field is just after the msdu fw rx desc. + */ +#define HTT_RX_IND_HL_RX_DESC_BASE_OFFSET (HTT_RX_IND_FW_RX_DESC_BYTE_OFFSET + 1) +struct htt_rx_ind_hl_rx_desc_t { + A_UINT8 ver; + A_UINT8 len; + struct { + A_UINT8 + first_msdu: 1, + last_msdu: 1, + c3_failed: 1, + c4_failed: 1, + ipv6: 1, + tcp: 1, + udp: 1, + reserved: 1; + } flags; +}; + +#define HTT_RX_IND_HL_RX_DESC_VER_OFFSET \ + (HTT_RX_IND_HL_RX_DESC_BASE_OFFSET \ + + offsetof(struct htt_rx_ind_hl_rx_desc_t, ver)) +#define HTT_RX_IND_HL_RX_DESC_VER 0 + +#define HTT_RX_IND_HL_RX_DESC_LEN_OFFSET \ + (HTT_RX_IND_HL_RX_DESC_BASE_OFFSET \ + + offsetof(struct htt_rx_ind_hl_rx_desc_t, len)) + +#define HTT_RX_IND_HL_FLAG_OFFSET \ + (HTT_RX_IND_HL_RX_DESC_BASE_OFFSET \ + + offsetof(struct htt_rx_ind_hl_rx_desc_t, flags)) + +#define HTT_RX_IND_HL_FLAG_FIRST_MSDU (0x01 << 0) +#define HTT_RX_IND_HL_FLAG_LAST_MSDU (0x01 << 1) +#define HTT_RX_IND_HL_FLAG_C3_FAILED (0x01 << 2) // L3 checksum failed +#define HTT_RX_IND_HL_FLAG_C4_FAILED (0x01 << 3) // L4 checksum failed +#define HTT_RX_IND_HL_FLAG_IPV6 (0x01 << 4) // is ipv6, or else ipv4 +#define HTT_RX_IND_HL_FLAG_TCP (0x01 << 5) // is tcp +#define HTT_RX_IND_HL_FLAG_UDP (0x01 << 6) // is udp +/* This structure is used in HL, the basic descriptor information + * used by host. the structure is translated by FW from HW desc + * or generated by FW. But in HL monitor mode, the host would use + * the same structure with LL. + */ +PREPACK struct hl_htt_rx_desc_base { + A_UINT32 + seq_num:12, + encrypted:1, + chan_info_present:1, + resv0:2, + mcast_bcast:1, + fragment:1, + key_id_oct:8, + resv1:6; + A_UINT32 + pn_31_0; + union { + struct { + A_UINT16 pn_47_32; + A_UINT16 pn_63_48; + } pn16; + A_UINT32 pn_63_32; + } u0; + A_UINT32 + pn_95_64; + A_UINT32 + pn_127_96; +} POSTPACK; + + +/* + * Channel information can optionally be appended after hl_htt_rx_desc_base. + * If so, the len field in htt_rx_ind_hl_rx_desc_t will be updated accordingly, + * and the chan_info_present flag in hl_htt_rx_desc_base will be set. + * Please see htt_chan_change_t for description of the fields. + */ +PREPACK struct htt_chan_info_t +{ + A_UINT32 primary_chan_center_freq_mhz: 16, + contig_chan1_center_freq_mhz: 16; + A_UINT32 contig_chan2_center_freq_mhz: 16, + phy_mode: 8, + reserved: 8; +} POSTPACK; + +#define HTT_CHAN_INFO_SIZE sizeof(struct htt_chan_info_t) + +#define HL_RX_DESC_SIZE (sizeof(struct hl_htt_rx_desc_base)) +#define HL_RX_DESC_SIZE_DWORD (HL_RX_STD_DESC_SIZE >> 2) + +#define HTT_HL_RX_DESC_MPDU_SEQ_NUM_M 0xfff +#define HTT_HL_RX_DESC_MPDU_SEQ_NUM_S 0 +#define HTT_HL_RX_DESC_MPDU_ENC_M 0x1000 +#define HTT_HL_RX_DESC_MPDU_ENC_S 12 +#define HTT_HL_RX_DESC_CHAN_INFO_PRESENT_M 0x2000 +#define HTT_HL_RX_DESC_CHAN_INFO_PRESENT_S 13 +#define HTT_HL_RX_DESC_MCAST_BCAST_M 0x10000 +#define HTT_HL_RX_DESC_MCAST_BCAST_S 16 +#define HTT_HL_RX_DESC_FRAGMENT_M 0x20000 +#define HTT_HL_RX_DESC_FRAGMENT_S 17 +#define HTT_HL_RX_DESC_KEY_ID_OCT_M 0x3fc0000 +#define HTT_HL_RX_DESC_KEY_ID_OCT_S 18 + +#define HTT_HL_RX_DESC_PN_OFFSET offsetof(struct hl_htt_rx_desc_base, pn_31_0) +#define HTT_HL_RX_DESC_PN_WORD_OFFSET (HTT_HL_RX_DESC_PN_OFFSET >> 2) + + +/* Channel information */ +#define HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_M 0x0000ffff +#define HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_S 0 +#define HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_M 0xffff0000 +#define HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_S 16 +#define HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_M 0x0000ffff +#define HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_S 0 +#define HTT_CHAN_INFO_PHY_MODE_M 0x00ff0000 +#define HTT_CHAN_INFO_PHY_MODE_S 16 + + +#define HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ, value); \ + (word) |= (value) << HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_S; \ + } while (0) +#define HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_GET(word) \ + (((word) & HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_M) >> HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ_S) + + +#define HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ, value); \ + (word) |= (value) << HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_S; \ + } while (0) +#define HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_GET(word) \ + (((word) & HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_M) >> HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ_S) + + +#define HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ, value); \ + (word) |= (value) << HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_S; \ + } while (0) +#define HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_GET(word) \ + (((word) & HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_M) >> HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ_S) + + +#define HTT_CHAN_INFO_PHY_MODE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_INFO_PHY_MODE, value); \ + (word) |= (value) << HTT_CHAN_INFO_PHY_MODE_S; \ + } while (0) +#define HTT_CHAN_INFO_PHY_MODE_GET(word) \ + (((word) & HTT_CHAN_INFO_PHY_MODE_M) >> HTT_CHAN_INFO_PHY_MODE_S) + + +/* + * @brief target -> host rx reorder flush message definition + * + * @details + * The following field definitions describe the format of the rx flush + * message sent from the target to the host. + * The message consists of a 4-octet header, followed by one or more + * 4-octet payload information elements. + * + * |31 24|23 8|7 0| + * |--------------------------------------------------------------| + * | TID | peer ID | msg type | + * |--------------------------------------------------------------| + * | seq num end | seq num start | MPDU status | reserved | + * |--------------------------------------------------------------| + * First DWORD: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx flush message + * Value: 0x2 + * - PEER_ID + * Bits 23:8 (only bits 18:8 actually used) + * Purpose: identify which peer's rx data is being flushed + * Value: (rx) peer ID + * - TID + * Bits 31:24 (only bits 27:24 actually used) + * Purpose: Specifies which traffic identifier's rx data is being flushed + * Value: traffic identifier + * Second DWORD: + * - MPDU_STATUS + * Bits 15:8 + * Purpose: + * Indicate whether the flushed MPDUs should be discarded or processed. + * Value: + * 0x1: send the MPDUs from the rx reorder buffer to subsequent + * stages of rx processing + * other: discard the MPDUs + * It is anticipated that flush messages will always have + * MPDU status == 1, but the status flag is included for + * flexibility. + * - SEQ_NUM_START + * Bits 23:16 + * Purpose: + * Indicate the start of a series of consecutive MPDUs being flushed. + * Not all MPDUs within this range are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + * Value: + * The sequence number for the first MPDU in the sequence. + * This sequence number is the 6 LSBs of the 802.11 sequence number. + * - SEQ_NUM_END + * Bits 30:24 + * Purpose: + * Indicate the end of a series of consecutive MPDUs being flushed. + * Value: + * The sequence number one larger than the sequence number of the + * last MPDU being flushed. + * This sequence number is the 6 LSBs of the 802.11 sequence number. + * The range of MPDUs from [SEQ_NUM_START,SEQ_NUM_END-1] inclusive + * are to be released for further rx processing. + * Not all MPDUs within this range are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + */ +/* first DWORD */ +#define HTT_RX_FLUSH_PEER_ID_M 0xffff00 +#define HTT_RX_FLUSH_PEER_ID_S 8 +#define HTT_RX_FLUSH_TID_M 0xff000000 +#define HTT_RX_FLUSH_TID_S 24 +/* second DWORD */ +#define HTT_RX_FLUSH_MPDU_STATUS_M 0x0000ff00 +#define HTT_RX_FLUSH_MPDU_STATUS_S 8 +#define HTT_RX_FLUSH_SEQ_NUM_START_M 0x00ff0000 +#define HTT_RX_FLUSH_SEQ_NUM_START_S 16 +#define HTT_RX_FLUSH_SEQ_NUM_END_M 0xff000000 +#define HTT_RX_FLUSH_SEQ_NUM_END_S 24 + +#define HTT_RX_FLUSH_BYTES 8 + +#define HTT_RX_FLUSH_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FLUSH_PEER_ID, value); \ + (word) |= (value) << HTT_RX_FLUSH_PEER_ID_S; \ + } while (0) +#define HTT_RX_FLUSH_PEER_ID_GET(word) \ + (((word) & HTT_RX_FLUSH_PEER_ID_M) >> HTT_RX_FLUSH_PEER_ID_S) + +#define HTT_RX_FLUSH_TID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FLUSH_TID, value); \ + (word) |= (value) << HTT_RX_FLUSH_TID_S; \ + } while (0) +#define HTT_RX_FLUSH_TID_GET(word) \ + (((word) & HTT_RX_FLUSH_TID_M) >> HTT_RX_FLUSH_TID_S) + +#define HTT_RX_FLUSH_MPDU_STATUS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FLUSH_MPDU_STATUS, value); \ + (word) |= (value) << HTT_RX_FLUSH_MPDU_STATUS_S; \ + } while (0) +#define HTT_RX_FLUSH_MPDU_STATUS_GET(word) \ + (((word) & HTT_RX_FLUSH_MPDU_STATUS_M) >> HTT_RX_FLUSH_MPDU_STATUS_S) + +#define HTT_RX_FLUSH_SEQ_NUM_START_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FLUSH_SEQ_NUM_START, value); \ + (word) |= (value) << HTT_RX_FLUSH_SEQ_NUM_START_S; \ + } while (0) +#define HTT_RX_FLUSH_SEQ_NUM_START_GET(word) \ + (((word) & HTT_RX_FLUSH_SEQ_NUM_START_M) >> HTT_RX_FLUSH_SEQ_NUM_START_S) + +#define HTT_RX_FLUSH_SEQ_NUM_END_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FLUSH_SEQ_NUM_END, value); \ + (word) |= (value) << HTT_RX_FLUSH_SEQ_NUM_END_S; \ + } while (0) +#define HTT_RX_FLUSH_SEQ_NUM_END_GET(word) \ + (((word) & HTT_RX_FLUSH_SEQ_NUM_END_M) >> HTT_RX_FLUSH_SEQ_NUM_END_S) + +/* + * @brief target -> host rx pn check indication message + * + * @details + * The following field definitions describe the format of the Rx PN check + * indication message sent from the target to the host. + * The message consists of a 4-octet header, followed by the start and + * end sequence numbers to be released, followed by the PN IEs. Each PN + * IE is one octet containing the sequence number that failed the PN + * check. + * + * |31 24|23 8|7 0| + * |--------------------------------------------------------------| + * | TID | peer ID | msg type | + * |--------------------------------------------------------------| + * | Reserved | PN IE count | seq num end | seq num start| + * |--------------------------------------------------------------| + * l : PN IE 2 | PN IE 1 | PN IE 0 | + * |--------------------------------------------------------------| + + * First DWORD: + * - MSG_TYPE + * Bits 7:0 + * Purpose: Identifies this as an rx pn check indication message + * Value: 0x2 + * - PEER_ID + * Bits 23:8 (only bits 18:8 actually used) + * Purpose: identify which peer + * Value: (rx) peer ID + * - TID + * Bits 31:24 (only bits 27:24 actually used) + * Purpose: identify traffic identifier + * Value: traffic identifier + * Second DWORD: + * - SEQ_NUM_START + * Bits 7:0 + * Purpose: + * Indicates the starting sequence number of the MPDU in this + * series of MPDUs that went though PN check. + * Value: + * The sequence number for the first MPDU in the sequence. + * This sequence number is the 6 LSBs of the 802.11 sequence number. + * - SEQ_NUM_END + * Bits 15:8 + * Purpose: + * Indicates the ending sequence number of the MPDU in this + * series of MPDUs that went though PN check. + * Value: + * The sequence number one larger then the sequence number of the last + * MPDU being flushed. + * This sequence number is the 6 LSBs of the 802.11 sequence number. + * The range of MPDUs from [SEQ_NUM_START,SEQ_NUM_END-1] have been checked + * for invalid PN numbers and are ready to be released for further processing. + * Not all MPDUs within this range are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + * - PN_IE_COUNT + * Bits 23:16 + * Purpose: + * Used to determine the variable number of PN information elements in this + * message + * + * PN information elements: + * - PN_IE_x- + * Purpose: + * Each PN information element contains the sequence number of the MPDU that + * has failed the target PN check. + * Value: + * Contains the 6 LSBs of the 802.11 sequence number corresponding to the MPDU + * that failed the PN check. + */ +/* first DWORD */ +#define HTT_RX_PN_IND_PEER_ID_M 0xffff00 +#define HTT_RX_PN_IND_PEER_ID_S 8 +#define HTT_RX_PN_IND_TID_M 0xff000000 +#define HTT_RX_PN_IND_TID_S 24 +/* second DWORD */ +#define HTT_RX_PN_IND_SEQ_NUM_START_M 0x000000ff +#define HTT_RX_PN_IND_SEQ_NUM_START_S 0 +#define HTT_RX_PN_IND_SEQ_NUM_END_M 0x0000ff00 +#define HTT_RX_PN_IND_SEQ_NUM_END_S 8 +#define HTT_RX_PN_IND_PN_IE_CNT_M 0x00ff0000 +#define HTT_RX_PN_IND_PN_IE_CNT_S 16 + +#define HTT_RX_PN_IND_BYTES 8 + +#define HTT_RX_PN_IND_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PN_IND_PEER_ID, value); \ + (word) |= (value) << HTT_RX_PN_IND_PEER_ID_S; \ + } while (0) +#define HTT_RX_PN_IND_PEER_ID_GET(word) \ + (((word) & HTT_RX_PN_IND_PEER_ID_M) >> HTT_RX_PN_IND_PEER_ID_S) + +#define HTT_RX_PN_IND_EXT_TID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PN_IND_TID, value); \ + (word) |= (value) << HTT_RX_PN_IND_TID_S; \ + } while (0) +#define HTT_RX_PN_IND_EXT_TID_GET(word) \ + (((word) & HTT_RX_PN_IND_TID_M) >> HTT_RX_PN_IND_TID_S) + +#define HTT_RX_PN_IND_SEQ_NUM_START_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PN_IND_SEQ_NUM_START, value); \ + (word) |= (value) << HTT_RX_PN_IND_SEQ_NUM_START_S; \ + } while (0) +#define HTT_RX_PN_IND_SEQ_NUM_START_GET(word) \ + (((word) & HTT_RX_PN_IND_SEQ_NUM_START_M) >> HTT_RX_PN_IND_SEQ_NUM_START_S) + +#define HTT_RX_PN_IND_SEQ_NUM_END_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PN_IND_SEQ_NUM_END, value); \ + (word) |= (value) << HTT_RX_PN_IND_SEQ_NUM_END_S; \ + } while (0) +#define HTT_RX_PN_IND_SEQ_NUM_END_GET(word) \ + (((word) & HTT_RX_PN_IND_SEQ_NUM_END_M) >> HTT_RX_PN_IND_SEQ_NUM_END_S) + +#define HTT_RX_PN_IND_PN_IE_CNT_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PN_IND_PN_IE_CNT, value); \ + (word) |= (value) << HTT_RX_PN_IND_PN_IE_CNT_S; \ + } while(0) +#define HTT_RX_PN_IND_PN_IE_CNT_GET(word) \ + (((word) & HTT_RX_PN_IND_PN_IE_CNT_M) >> HTT_RX_PN_IND_PN_IE_CNT_S) + +/* + * @brief target -> host rx offload deliver message for LL system + * + * @details + * In a low latency system this message is sent whenever the offload + * manager flushes out the packets it has coalesced in its coalescing buffer. + * The DMA of the actual packets into host memory is done before sending out + * this message. This message indicates only how many MSDUs to reap. The + * peer ID, vdev ID, tid and MSDU length are copied inline into the header + * portion of the MSDU while DMA'ing into the host memory. Unlike the packets + * DMA'd by the MAC directly into host memory these packets do not contain + * the MAC descriptors in the header portion of the packet. Instead they contain + * the peer ID, vdev ID, tid and MSDU length. Also when the host receives this + * message, the packets are delivered directly to the NW stack without going + * through the regular reorder buffering and PN checking path since it has + * already been done in target. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------------------| + * | Total MSDU count | reserved | msg type | + * |-----------------------------------------------------------------------| + * + * @brief target -> host rx offload deliver message for HL system + * + * @details + * In a high latency system this message is sent whenever the offload manager + * flushes out the packets it has coalesced in its coalescing buffer. The + * actual packets are also carried along with this message. When the host + * receives this message, it is expected to deliver these packets to the NW + * stack directly instead of routing them through the reorder buffering and + * PN checking path since it has already been done in target. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------------------| + * | Total MSDU count | reserved | msg type | + * |-----------------------------------------------------------------------| + * | peer ID | MSDU length | + * |-----------------------------------------------------------------------| + * | MSDU payload | FW Desc | tid | vdev ID | + * |-----------------------------------------------------------------------| + * | MSDU payload contd. | + * |-----------------------------------------------------------------------| + * | peer ID | MSDU length | + * |-----------------------------------------------------------------------| + * | MSDU payload | FW Desc | tid | vdev ID | + * |-----------------------------------------------------------------------| + * | MSDU payload contd. | + * |-----------------------------------------------------------------------| + * + */ +/* first DWORD */ +#define HTT_RX_OFFLOAD_DELIVER_IND_HDR_BYTES 4 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES 7 + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_M 0xffff0000 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_S 16 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_M 0x0000ffff +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_S 0 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_M 0xffff0000 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_S 16 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_M 0x000000ff +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_S 0 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_M 0x0000ff00 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_S 8 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_M 0x00ff0000 +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_S 16 + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_GET(word) \ + (((word) & HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_M) >> HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_S) +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT, value); \ + (word) |= (value) << HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_S; \ + } while(0) \ + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_GET(word) \ + (((word) & HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_M) >> HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_S) +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN, value); \ + (word) |= (value) << HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_S; \ + } while(0) \ + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_GET(word) \ + (((word) & HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_M) >> HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_S) +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID, value); \ + (word) |= (value) << HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_S; \ + } while(0) \ + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_GET(word) \ + (((word) & HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_M) >> HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_S) +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID, value); \ + (word) |= (value) << HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_S; \ + } while(0) \ + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_GET(word) \ + (((word) & HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_M) >> HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_S) +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID, value); \ + (word) |= (value) << HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_S; \ + } while(0) \ + +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_GET(word) \ + (((word) & HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_M) >> HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_S) +#define HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC, value); \ + (word) |= (value) << HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_S; \ + } while(0) \ + +/** + * @brief target -> host rx peer map/unmap message definition + * + * @details + * The following diagram shows the format of the rx peer map message sent + * from the target to the host. This layout assumes the target operates + * as little-endian. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------------------| + * | peer ID | VDEV ID | msg type | + * |-----------------------------------------------------------------------| + * | MAC addr 3 | MAC addr 2 | MAC addr 1 | MAC addr 0 | + * |-----------------------------------------------------------------------| + * | reserved | MAC addr 5 | MAC addr 4 | + * |-----------------------------------------------------------------------| + * + * + * The following diagram shows the format of the rx peer unmap message sent + * from the target to the host. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------------------| + * | peer ID | VDEV ID | msg type | + * |-----------------------------------------------------------------------| + * + * The following field definitions describe the format of the rx peer map + * and peer unmap messages sent from the target to the host. + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx peer map or peer unmap message + * Value: peer map -> 0x3, peer unmap -> 0x4 + * - VDEV_ID + * Bits 15:8 + * Purpose: Indicates which virtual device the peer is associated + * with. + * Value: vdev ID (used in the host to look up the vdev object) + * - PEER_ID + * Bits 31:16 + * Purpose: The peer ID (index) that WAL is allocating (map) or + * freeing (unmap) + * Value: (rx) peer ID + * - MAC_ADDR_L32 (peer map only) + * Bits 31:0 + * Purpose: Identifies which peer node the peer ID is for. + * Value: lower 4 bytes of peer node's MAC address + * - MAC_ADDR_U16 (peer map only) + * Bits 15:0 + * Purpose: Identifies which peer node the peer ID is for. + * Value: upper 2 bytes of peer node's MAC address + */ +#define HTT_RX_PEER_MAP_VDEV_ID_M 0xff00 +#define HTT_RX_PEER_MAP_VDEV_ID_S 8 +#define HTT_RX_PEER_MAP_PEER_ID_M 0xffff0000 +#define HTT_RX_PEER_MAP_PEER_ID_S 16 +#define HTT_RX_PEER_MAP_MAC_ADDR_L32_M 0xffffffff +#define HTT_RX_PEER_MAP_MAC_ADDR_L32_S 0 +#define HTT_RX_PEER_MAP_MAC_ADDR_U16_M 0xffff +#define HTT_RX_PEER_MAP_MAC_ADDR_U16_S 0 + +#define HTT_RX_PEER_MAP_VAP_ID_SET HTT_RX_PEER_MAP_VDEV_ID_SET /* deprecated */ +#define HTT_RX_PEER_MAP_VDEV_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PEER_MAP_VDEV_ID, value); \ + (word) |= (value) << HTT_RX_PEER_MAP_VDEV_ID_S; \ + } while (0) +#define HTT_RX_PEER_MAP_VAP_ID_GET HTT_RX_PEER_MAP_VDEV_ID_GET /* deprecated */ +#define HTT_RX_PEER_MAP_VDEV_ID_GET(word) \ + (((word) & HTT_RX_PEER_MAP_VDEV_ID_M) >> HTT_RX_PEER_MAP_VDEV_ID_S) + +#define HTT_RX_PEER_MAP_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_PEER_MAP_PEER_ID, value); \ + (word) |= (value) << HTT_RX_PEER_MAP_PEER_ID_S; \ + } while (0) +#define HTT_RX_PEER_MAP_PEER_ID_GET(word) \ + (((word) & HTT_RX_PEER_MAP_PEER_ID_M) >> HTT_RX_PEER_MAP_PEER_ID_S) + +#define HTT_RX_PEER_MAP_MAC_ADDR_OFFSET 4 /* bytes */ + +#define HTT_RX_PEER_MAP_BYTES 12 + + +#define HTT_RX_PEER_UNMAP_PEER_ID_M HTT_RX_PEER_MAP_PEER_ID_M +#define HTT_RX_PEER_UNMAP_PEER_ID_S HTT_RX_PEER_MAP_PEER_ID_S + +#define HTT_RX_PEER_UNMAP_PEER_ID_SET HTT_RX_PEER_MAP_PEER_ID_SET +#define HTT_RX_PEER_UNMAP_PEER_ID_GET HTT_RX_PEER_MAP_PEER_ID_GET + +#define HTT_RX_PEER_UNMAP_VDEV_ID_SET HTT_RX_PEER_MAP_VDEV_ID_SET +#define HTT_RX_PEER_UNMAP_VDEV_ID_GET HTT_RX_PEER_MAP_VDEV_ID_GET + +#define HTT_RX_PEER_UNMAP_BYTES 4 + + +/** + * @brief target -> host message specifying security parameters + * + * @details + * The following diagram shows the format of the security specification + * message sent from the target to the host. + * This security specification message tells the host whether a PN check is + * necessary on rx data frames, and if so, how large the PN counter is. + * This message also tells the host about the security processing to apply + * to defragmented rx frames - specifically, whether a Message Integrity + * Check is required, and the Michael key to use. + * + * |31 24|23 16|15|14 8|7 0| + * |-----------------------------------------------------------------------| + * | peer ID | U| security type | msg type | + * |-----------------------------------------------------------------------| + * | Michael Key K0 | + * |-----------------------------------------------------------------------| + * | Michael Key K1 | + * |-----------------------------------------------------------------------| + * | WAPI RSC Low0 | + * |-----------------------------------------------------------------------| + * | WAPI RSC Low1 | + * |-----------------------------------------------------------------------| + * | WAPI RSC Hi0 | + * |-----------------------------------------------------------------------| + * | WAPI RSC Hi1 | + * |-----------------------------------------------------------------------| + * + * The following field definitions describe the format of the security + * indication message sent from the target to the host. + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a security specification message + * Value: 0xb + * - SEC_TYPE + * Bits 14:8 + * Purpose: specifies which type of security applies to the peer + * Value: htt_sec_type enum value + * - UNICAST + * Bit 15 + * Purpose: whether this security is applied to unicast or multicast data + * Value: 1 -> unicast, 0 -> multicast + * - PEER_ID + * Bits 31:16 + * Purpose: The ID number for the peer the security specification is for + * Value: peer ID + * - MICHAEL_KEY_K0 + * Bits 31:0 + * Purpose: 4-byte word that forms the 1st half of the TKIP Michael key + * Value: Michael Key K0 (if security type is TKIP) + * - MICHAEL_KEY_K1 + * Bits 31:0 + * Purpose: 4-byte word that forms the 2nd half of the TKIP Michael key + * Value: Michael Key K1 (if security type is TKIP) + * - WAPI_RSC_LOW0 + * Bits 31:0 + * Purpose: 4-byte word that forms the 1st quarter of the 16 byte WAPI RSC + * Value: WAPI RSC Low0 (if security type is WAPI) + * - WAPI_RSC_LOW1 + * Bits 31:0 + * Purpose: 4-byte word that forms the 2nd quarter of the 16 byte WAPI RSC + * Value: WAPI RSC Low1 (if security type is WAPI) + * - WAPI_RSC_HI0 + * Bits 31:0 + * Purpose: 4-byte word that forms the 3rd quarter of the 16 byte WAPI RSC + * Value: WAPI RSC Hi0 (if security type is WAPI) + * - WAPI_RSC_HI1 + * Bits 31:0 + * Purpose: 4-byte word that forms the 4th quarter of the 16 byte WAPI RSC + * Value: WAPI RSC Hi1 (if security type is WAPI) + */ + +#define HTT_SEC_IND_SEC_TYPE_M 0x00007f00 +#define HTT_SEC_IND_SEC_TYPE_S 8 +#define HTT_SEC_IND_UNICAST_M 0x00008000 +#define HTT_SEC_IND_UNICAST_S 15 +#define HTT_SEC_IND_PEER_ID_M 0xffff0000 +#define HTT_SEC_IND_PEER_ID_S 16 + +#define HTT_SEC_IND_SEC_TYPE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_SEC_IND_SEC_TYPE, value); \ + (word) |= (value) << HTT_SEC_IND_SEC_TYPE_S; \ + } while (0) +#define HTT_SEC_IND_SEC_TYPE_GET(word) \ + (((word) & HTT_SEC_IND_SEC_TYPE_M) >> HTT_SEC_IND_SEC_TYPE_S) + +#define HTT_SEC_IND_UNICAST_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_SEC_IND_UNICAST, value); \ + (word) |= (value) << HTT_SEC_IND_UNICAST_S; \ + } while (0) +#define HTT_SEC_IND_UNICAST_GET(word) \ + (((word) & HTT_SEC_IND_UNICAST_M) >> HTT_SEC_IND_UNICAST_S) + +#define HTT_SEC_IND_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_SEC_IND_PEER_ID, value); \ + (word) |= (value) << HTT_SEC_IND_PEER_ID_S; \ + } while (0) +#define HTT_SEC_IND_PEER_ID_GET(word) \ + (((word) & HTT_SEC_IND_PEER_ID_M) >> HTT_SEC_IND_PEER_ID_S) + + +#define HTT_SEC_IND_BYTES 28 + + +/** + * @brief target -> host rx ADDBA / DELBA message definitions + * + * @details + * The following diagram shows the format of the rx ADDBA message sent + * from the target to the host: + * + * |31 20|19 16|15 8|7 0| + * |---------------------------------------------------------------------| + * | peer ID | TID | window size | msg type | + * |---------------------------------------------------------------------| + * + * The following diagram shows the format of the rx DELBA message sent + * from the target to the host: + * + * |31 20|19 16|15 8|7 0| + * |---------------------------------------------------------------------| + * | peer ID | TID | reserved | msg type | + * |---------------------------------------------------------------------| + * + * The following field definitions describe the format of the rx ADDBA + * and DELBA messages sent from the target to the host. + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx ADDBA or DELBA message + * Value: ADDBA -> 0x5, DELBA -> 0x6 + * - WIN_SIZE + * Bits 15:8 (ADDBA only) + * Purpose: Specifies the length of the block ack window (max = 64). + * Value: + * block ack window length specified by the received ADDBA + * management message. + * - TID + * Bits 19:16 + * Purpose: Specifies which traffic identifier the ADDBA / DELBA is for. + * Value: + * TID specified by the received ADDBA or DELBA management message. + * - PEER_ID + * Bits 31:20 + * Purpose: Identifies which peer sent the ADDBA / DELBA. + * Value: + * ID (hash value) used by the host for fast, direct lookup of + * host SW peer info, including rx reorder states. + */ +#define HTT_RX_ADDBA_WIN_SIZE_M 0xff00 +#define HTT_RX_ADDBA_WIN_SIZE_S 8 +#define HTT_RX_ADDBA_TID_M 0xf0000 +#define HTT_RX_ADDBA_TID_S 16 +#define HTT_RX_ADDBA_PEER_ID_M 0xfff00000 +#define HTT_RX_ADDBA_PEER_ID_S 20 + +#define HTT_RX_ADDBA_WIN_SIZE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_ADDBA_WIN_SIZE, value); \ + (word) |= (value) << HTT_RX_ADDBA_WIN_SIZE_S; \ + } while (0) +#define HTT_RX_ADDBA_WIN_SIZE_GET(word) \ + (((word) & HTT_RX_ADDBA_WIN_SIZE_M) >> HTT_RX_ADDBA_WIN_SIZE_S) + +#define HTT_RX_ADDBA_TID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_ADDBA_TID, value); \ + (word) |= (value) << HTT_RX_ADDBA_TID_S; \ + } while (0) +#define HTT_RX_ADDBA_TID_GET(word) \ + (((word) & HTT_RX_ADDBA_TID_M) >> HTT_RX_ADDBA_TID_S) + +#define HTT_RX_ADDBA_PEER_ID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_ADDBA_PEER_ID, value); \ + (word) |= (value) << HTT_RX_ADDBA_PEER_ID_S; \ + } while (0) +#define HTT_RX_ADDBA_PEER_ID_GET(word) \ + (((word) & HTT_RX_ADDBA_PEER_ID_M) >> HTT_RX_ADDBA_PEER_ID_S) + +#define HTT_RX_ADDBA_BYTES 4 + + +#define HTT_RX_DELBA_TID_M HTT_RX_ADDBA_TID_M +#define HTT_RX_DELBA_TID_S HTT_RX_ADDBA_TID_S +#define HTT_RX_DELBA_PEER_ID_M HTT_RX_ADDBA_PEER_ID_M +#define HTT_RX_DELBA_PEER_ID_S HTT_RX_ADDBA_PEER_ID_S + +#define HTT_RX_DELBA_TID_SET HTT_RX_ADDBA_TID_SET +#define HTT_RX_DELBA_TID_GET HTT_RX_ADDBA_TID_GET +#define HTT_RX_DELBA_PEER_ID_SET HTT_RX_ADDBA_PEER_ID_SET +#define HTT_RX_DELBA_PEER_ID_GET HTT_RX_ADDBA_PEER_ID_GET + +#define HTT_RX_DELBA_BYTES 4 + +/** + * @brief tx queue group information element definition + * + * @details + * The following diagram shows the format of the tx queue group + * information element, which can be included in target --> host + * messages to specify the number of tx "credits" (tx descriptors + * for LL, or tx buffers for HL) available to a particular group + * of host-side tx queues, and which host-side tx queues belong to + * the group. + * + * |31|30 24|23 16|15|14|13 0| + * |------------------------------------------------------------------------| + * | X| reserved | tx queue grp ID | A| S| credit count | + * |------------------------------------------------------------------------| + * | vdev ID mask | AC mask | + * |------------------------------------------------------------------------| + * + * The following definitions describe the fields within the tx queue group + * information element: + * - credit_count + * Bits 13:1 + * Purpose: specify how many tx credits are available to the tx queue group + * Value: An absolute or relative, positive or negative credit value + * The 'A' bit specifies whether the value is absolute or relative. + * The 'S' bit specifies whether the value is positive or negative. + * A negative value can only be relative, not absolute. + * An absolute value replaces any prior credit value the host has for + * the tx queue group in question. + * A relative value is added to the prior credit value the host has for + * the tx queue group in question. + * - sign + * Bit 14 + * Purpose: specify whether the credit count is positive or negative + * Value: 0 -> positive, 1 -> negative + * - absolute + * Bit 15 + * Purpose: specify whether the credit count is absolute or relative + * Value: 0 -> relative, 1 -> absolute + * - txq_group_id + * Bits 23:16 + * Purpose: indicate which tx queue group's credit and/or membership are + * being specified + * Value: 0 to max_tx_queue_groups-1 + * - reserved + * Bits 30:16 + * Value: 0x0 + * - eXtension + * Bit 31 + * Purpose: specify whether another tx queue group info element follows + * Value: 0 -> no more tx queue group information elements + * 1 -> another tx queue group information element immediately follows + * - ac_mask + * Bits 15:0 + * Purpose: specify which Access Categories belong to the tx queue group + * Value: bit-OR of masks for the ACs (WMM and extension) that belong to + * the tx queue group. + * The AC bit-mask values are obtained by left-shifting by the + * corresponding HTT_AC_WMM enum values, e.g. (1 << HTT_AC_WMM_BE) == 0x1 + * - vdev_id_mask + * Bits 31:16 + * Purpose: specify which vdev's tx queues belong to the tx queue group + * Value: bit-OR of masks based on the IDs of the vdevs whose tx queues + * belong to the tx queue group. + * For example, if vdev IDs 1 and 4 belong to a tx queue group, the + * vdev_id_mask would be (1 << 1) | (1 << 4) = 0x12 + */ +PREPACK struct htt_txq_group { + A_UINT32 + credit_count: 14, + sign: 1, + absolute: 1, + tx_queue_group_id: 8, + reserved0: 7, + extension: 1; + A_UINT32 + ac_mask: 16, + vdev_id_mask: 16; +} POSTPACK; + +/* first word */ +#define HTT_TXQ_GROUP_CREDIT_COUNT_S 0 +#define HTT_TXQ_GROUP_CREDIT_COUNT_M 0x00003fff +#define HTT_TXQ_GROUP_SIGN_S 14 +#define HTT_TXQ_GROUP_SIGN_M 0x00004000 +#define HTT_TXQ_GROUP_ABS_S 15 +#define HTT_TXQ_GROUP_ABS_M 0x00008000 +#define HTT_TXQ_GROUP_ID_S 16 +#define HTT_TXQ_GROUP_ID_M 0x00ff0000 +#define HTT_TXQ_GROUP_EXT_S 31 +#define HTT_TXQ_GROUP_EXT_M 0x80000000 +/* second word */ +#define HTT_TXQ_GROUP_AC_MASK_S 0 +#define HTT_TXQ_GROUP_AC_MASK_M 0x0000ffff +#define HTT_TXQ_GROUP_VDEV_ID_MASK_S 16 +#define HTT_TXQ_GROUP_VDEV_ID_MASK_M 0xffff0000 + +#define HTT_TXQ_GROUP_CREDIT_COUNT_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_CREDIT_COUNT, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_CREDIT_COUNT_S)); \ + } while (0) +#define HTT_TXQ_GROUP_CREDIT_COUNT_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_CREDIT_COUNT_M) >> HTT_TXQ_GROUP_CREDIT_COUNT_S) + +#define HTT_TXQ_GROUP_SIGN_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_SIGN, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_SIGN_S)); \ + } while (0) +#define HTT_TXQ_GROUP_SIGN_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_SIGN_M) >> HTT_TXQ_GROUP_SIGN_S) + +#define HTT_TXQ_GROUP_ABS_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_ABS, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_ABS_S)); \ + } while (0) +#define HTT_TXQ_GROUP_ABS_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_ABS_M) >> HTT_TXQ_GROUP_ABS_S) + +#define HTT_TXQ_GROUP_ID_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_ID, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_ID_S)); \ + } while (0) +#define HTT_TXQ_GROUP_ID_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_ID_M) >> HTT_TXQ_GROUP_ID_S) + +#define HTT_TXQ_GROUP_EXT_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_EXT, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_EXT_S)); \ + } while (0) +#define HTT_TXQ_GROUP_EXT_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_EXT_M) >> HTT_TXQ_GROUP_EXT_S) + +#define HTT_TXQ_GROUP_AC_MASK_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_AC_MASK, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_AC_MASK_S)); \ + } while (0) +#define HTT_TXQ_GROUP_AC_MASK_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_AC_MASK_M) >> HTT_TXQ_GROUP_AC_MASK_S) + +#define HTT_TXQ_GROUP_VDEV_ID_MASK_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TXQ_GROUP_VDEV_ID_MASK, _val); \ + ((_info) |= ((_val) << HTT_TXQ_GROUP_VDEV_ID_MASK_S)); \ + } while (0) +#define HTT_TXQ_GROUP_VDEV_ID_MASK_GET(_info) \ + (((_info) & HTT_TXQ_GROUP_VDEV_ID_MASK_M) >> HTT_TXQ_GROUP_VDEV_ID_MASK_S) + +/** + * @brief target -> host TX completion indication message definition + * + * @details + * The following diagram shows the format of the TX completion indication sent + * from the target to the host + * + * |31 25| 24|23 16| 15 |14 11|10 8|7 0| + * |-------------------------------------------------------------| + * header: | reserved |append| num | t_i| tid |status| msg_type | + * |-------------------------------------------------------------| + * payload: | MSDU1 ID | MSDU0 ID | + * |-------------------------------------------------------------| + * : MSDU3 ID : MSDU2 ID : + * |-------------------------------------------------------------| + * | struct htt_tx_compl_ind_append_retries | + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * + * The following field definitions describe the format of the TX completion + * indication sent from the target to the host + * Header fields: + * - msg_type + * Bits 7:0 + * Purpose: identifies this as HTT TX completion indication + * Value: 0x7 + * - status + * Bits 10:8 + * Purpose: the TX completion status of payload fragmentations descriptors + * Value: could be HTT_TX_COMPL_IND_STAT_OK or HTT_TX_COMPL_IND_STAT_DISCARD + * - tid + * Bits 14:11 + * Purpose: the tid associated with those fragmentation descriptors. It is + * valid or not, depending on the tid_invalid bit. + * Value: 0 to 15 + * - tid_invalid + * Bits 15:15 + * Purpose: this bit indicates whether the tid field is valid or not + * Value: 0 indicates valid; 1 indicates invalid + * - num + * Bits 23:16 + * Purpose: the number of payload in this indication + * Value: 1 to 255 + * - append + * Bits 24:24 + * Purpose: append the struct htt_tx_compl_ind_append_retries which contains + * the number of tx retries for one MSDU at the end of this message + * Value: 0 indicates no appending; 1 indicates appending + * Payload fields: + * - hmsdu_id + * Bits 15:0 + * Purpose: this ID is used to track the Tx buffer in host + * Value: 0 to "size of host MSDU descriptor pool - 1" + */ + +#define HTT_TX_COMPL_IND_STATUS_S 8 +#define HTT_TX_COMPL_IND_STATUS_M 0x00000700 +#define HTT_TX_COMPL_IND_TID_S 11 +#define HTT_TX_COMPL_IND_TID_M 0x00007800 +#define HTT_TX_COMPL_IND_TID_INV_S 15 +#define HTT_TX_COMPL_IND_TID_INV_M 0x00008000 +#define HTT_TX_COMPL_IND_NUM_S 16 +#define HTT_TX_COMPL_IND_NUM_M 0x00ff0000 +#define HTT_TX_COMPL_IND_APPEND_S 24 +#define HTT_TX_COMPL_IND_APPEND_M 0x01000000 + +#define HTT_TX_COMPL_IND_STATUS_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_COMPL_IND_STATUS, _val); \ + ((_info) |= ((_val) << HTT_TX_COMPL_IND_STATUS_S)); \ + } while (0) +#define HTT_TX_COMPL_IND_STATUS_GET(_info) \ + (((_info) & HTT_TX_COMPL_IND_STATUS_M) >> HTT_TX_COMPL_IND_STATUS_S) +#define HTT_TX_COMPL_IND_NUM_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_COMPL_IND_NUM, _val); \ + ((_info) |= ((_val) << HTT_TX_COMPL_IND_NUM_S)); \ + } while (0) +#define HTT_TX_COMPL_IND_NUM_GET(_info) \ + (((_info) & HTT_TX_COMPL_IND_NUM_M) >> HTT_TX_COMPL_IND_NUM_S) +#define HTT_TX_COMPL_IND_TID_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_COMPL_IND_TID, _val); \ + ((_info) |= ((_val) << HTT_TX_COMPL_IND_TID_S)); \ + } while (0) +#define HTT_TX_COMPL_IND_TID_GET(_info) \ + (((_info) & HTT_TX_COMPL_IND_TID_M) >> HTT_TX_COMPL_IND_TID_S) +#define HTT_TX_COMPL_IND_TID_INV_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_COMPL_IND_TID_INV, _val); \ + ((_info) |= ((_val) << HTT_TX_COMPL_IND_TID_INV_S)); \ + } while (0) +#define HTT_TX_COMPL_IND_TID_INV_GET(_info) \ + (((_info) & HTT_TX_COMPL_IND_TID_INV_M) >> \ + HTT_TX_COMPL_IND_TID_INV_S) +#define HTT_TX_COMPL_IND_APPEND_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_COMPL_IND_APPEND, _val); \ + ((_info) |= ((_val) << HTT_TX_COMPL_IND_APPEND_S)); \ + } while (0) +#define HTT_TX_COMPL_IND_APPEND_GET(_info) \ + (((_info) & HTT_TX_COMPL_IND_APPEND_M) >> HTT_TX_COMPL_IND_APPEND_S) + +#define HTT_TX_COMPL_CTXT_SZ sizeof(A_UINT16) +#define HTT_TX_COMPL_CTXT_NUM(_bytes) ((_bytes) >> 1) + +#define HTT_TX_COMPL_INV_MSDU_ID 0xffff + +#define HTT_TX_COMPL_IND_STAT_OK 0 +#define HTT_TX_COMPL_IND_STAT_DISCARD 1 +#define HTT_TX_COMPL_IND_STAT_NO_ACK 2 +#define HTT_TX_COMPL_IND_STAT_POSTPONE 3 +/* + * The PEER_DEL tx completion status is used for HL cases + * where the peer the frame is for has been deleted. + * The host has already discarded its copy of the frame, but + * it still needs the tx completion to restore its credit. + */ +#define HTT_TX_COMPL_IND_STAT_PEER_DEL 4 + + +#define HTT_TX_COMPL_IND_APPEND_SET_MORE_RETRY(f) ((f) |= 0x1) +#define HTT_TX_COMPL_IND_APPEND_CLR_MORE_RETRY(f) ((f) &= (~0x1)) + +PREPACK struct htt_tx_compl_ind_base { + A_UINT32 hdr; + A_UINT16 payload[1/*or more*/]; +} POSTPACK; + +PREPACK struct htt_tx_compl_ind_append_retries { + A_UINT16 msdu_id; + A_UINT8 tx_retries; + A_UINT8 flag; /* Bit 0, 1: another append_retries struct is appended + 0: this is the last append_retries struct */ +} POSTPACK; + +/** + * @brief target -> host rate-control update indication message + * + * @details + * The following diagram shows the format of the RC Update message + * sent from the target to the host, while processing the tx-completion + * of a transmitted PPDU. + * + * |31 24|23 16|15 8|7 0| + * |-------------------------------------------------------------| + * | peer ID | vdev ID | msg_type | + * |-------------------------------------------------------------| + * | MAC addr 3 | MAC addr 2 | MAC addr 1 | MAC addr 0 | + * |-------------------------------------------------------------| + * | reserved | num elems | MAC addr 5 | MAC addr 4 | + * |-------------------------------------------------------------| + * | : | + * : HTT_RC_TX_DONE_PARAMS (DWORD-aligned) : + * | : | + * |-------------------------------------------------------------| + * | : | + * : HTT_RC_TX_DONE_PARAMS (DWORD-aligned) : + * | : | + * |-------------------------------------------------------------| + * : : + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * + */ + +typedef struct { + A_UINT32 rate_code; /* rate code, bw, chain mask sgi */ + A_UINT32 rate_code_flags; + A_UINT32 flags; /* Encodes information such as excessive + retransmission, aggregate, some info + from .11 frame control, + STBC, LDPC, (SGI and Tx Chain Mask + are encoded in ptx_rc->flags field), + AMPDU truncation (BT/time based etc.), + RTS/CTS attempt */ + + A_UINT32 num_enqued; /* # of MPDUs (for non-AMPDU 1) for this rate */ + A_UINT32 num_retries; /* Total # of transmission attempt for this rate */ + A_UINT32 num_failed; /* # of failed MPDUs in A-MPDU, 0 otherwise */ + A_UINT32 ack_rssi; /* ACK RSSI: b'7..b'0 avg RSSI across all chain */ + A_UINT32 time_stamp ; /* ACK timestamp (helps determine age) */ + A_UINT32 is_probe; /* Valid if probing. Else, 0 */ +} HTT_RC_TX_DONE_PARAMS; + +#define HTT_RC_UPDATE_CTXT_SZ (sizeof(HTT_RC_TX_DONE_PARAMS)) /* bytes */ +#define HTT_RC_UPDATE_HDR_SZ (12) /* bytes */ + +#define HTT_RC_UPDATE_MAC_ADDR_OFFSET (4) /* bytes */ +#define HTT_RC_UPDATE_MAC_ADDR_LENGTH IEEE80211_ADDR_LEN /* bytes */ + +#define HTT_RC_UPDATE_VDEVID_S 8 +#define HTT_RC_UPDATE_VDEVID_M 0xff00 +#define HTT_RC_UPDATE_PEERID_S 16 +#define HTT_RC_UPDATE_PEERID_M 0xffff0000 + +#define HTT_RC_UPDATE_NUM_ELEMS_S 16 +#define HTT_RC_UPDATE_NUM_ELEMS_M 0x00ff0000 + +#define HTT_RC_UPDATE_VDEVID_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RC_UPDATE_VDEVID, _val); \ + ((_info) |= ((_val) << HTT_RC_UPDATE_VDEVID_S)); \ + } while (0) + +#define HTT_RC_UPDATE_VDEVID_GET(_info) \ + (((_info) & HTT_RC_UPDATE_VDEVID_M) >> HTT_RC_UPDATE_VDEVID_S) + +#define HTT_RC_UPDATE_PEERID_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RC_UPDATE_PEERID, _val); \ + ((_info) |= ((_val) << HTT_RC_UPDATE_PEERID_S)); \ + } while (0) + +#define HTT_RC_UPDATE_PEERID_GET(_info) \ + (((_info) & HTT_RC_UPDATE_PEERID_M) >> HTT_RC_UPDATE_PEERID_S) + +#define HTT_RC_UPDATE_NUM_ELEMS_SET(_info, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RC_UPDATE_NUM_ELEMS, _val); \ + ((_info) |= ((_val) << HTT_RC_UPDATE_NUM_ELEMS_S)); \ + } while (0) + +#define HTT_RC_UPDATE_NUM_ELEMS_GET(_info) \ + (((_info) & HTT_RC_UPDATE_NUM_ELEMS_M) >> HTT_RC_UPDATE_NUM_ELEMS_S) + +/** + * @brief target -> host rx fragment indication message definition + * + * @details + * The following field definitions describe the format of the rx fragment + * indication message sent from the target to the host. + * The rx fragment indication message shares the format of the + * rx indication message, but not all fields from the rx indication message + * are relevant to the rx fragment indication message. + * + * + * |31 24|23 18|17|16|15|14|13|12|11|10|9|8|7|6|5|4 0| + * |-----------+-------------------+---------------------+-------------| + * | peer ID | |FV| ext TID | msg type | + * |-------------------------------------------------------------------| + * | | flush | flush | + * | | end | start | + * | | seq num | seq num | + * |-------------------------------------------------------------------| + * | reserved | FW rx desc bytes | + * |-------------------------------------------------------------------| + * | | FW MSDU Rx | + * | | desc B0 | + * |-------------------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx fragment indication message + * Value: 0xa + * - EXT_TID + * Bits 12:8 + * Purpose: identify the traffic ID of the rx data, including + * special "extended" TID values for multicast, broadcast, and + * non-QoS data frames + * Value: 0-15 for regular TIDs, or >= 16 for bcast/mcast/non-QoS + * - FLUSH_VALID (FV) + * Bit 13 + * Purpose: indicate whether the flush IE (start/end sequence numbers) + * is valid + * Value: + * 1 -> flush IE is valid and needs to be processed + * 0 -> flush IE is not valid and should be ignored + * - PEER_ID + * Bits 31:16 + * Purpose: Identify, by ID, which peer sent the rx data + * Value: ID of the peer who sent the rx data + * - FLUSH_SEQ_NUM_START + * Bits 5:0 + * Purpose: Indicate the start of a series of MPDUs to flush + * Not all MPDUs within this series are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + * This field is only valid if the FV bit is set. + * Value: + * The sequence number for the first MPDUs to check to flush. + * The sequence number is masked by 0x3f. + * - FLUSH_SEQ_NUM_END + * Bits 11:6 + * Purpose: Indicate the end of a series of MPDUs to flush + * Value: + * The sequence number one larger than the sequence number of the + * last MPDU to check to flush. + * The sequence number is masked by 0x3f. + * Not all MPDUs within this series are necessarily valid - the host + * must check each sequence number within this range to see if the + * corresponding MPDU is actually present. + * This field is only valid if the FV bit is set. + * Rx descriptor fields: + * - FW_RX_DESC_BYTES + * Bits 15:0 + * Purpose: Indicate how many bytes in the Rx indication are used for + * FW Rx descriptors + * Value: 1 + */ +#define HTT_RX_FRAG_IND_HDR_PREFIX_SIZE32 2 + +#define HTT_RX_FRAG_IND_FW_DESC_BYTE_OFFSET 12 + +#define HTT_RX_FRAG_IND_EXT_TID_SET HTT_RX_IND_EXT_TID_SET +#define HTT_RX_FRAG_IND_EXT_TID_GET HTT_RX_IND_EXT_TID_GET + +#define HTT_RX_FRAG_IND_PEER_ID_SET HTT_RX_IND_PEER_ID_SET +#define HTT_RX_FRAG_IND_PEER_ID_GET HTT_RX_IND_PEER_ID_GET + +#define HTT_RX_FRAG_IND_FLUSH_VALID_SET HTT_RX_IND_FLUSH_VALID_SET +#define HTT_RX_FRAG_IND_FLUSH_VALID_GET HTT_RX_IND_FLUSH_VALID_GET + +#define HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_START_SET \ + HTT_RX_IND_FLUSH_SEQ_NUM_START_SET +#define HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_START_GET \ + HTT_RX_IND_FLUSH_SEQ_NUM_START_GET + +#define HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_END_SET \ + HTT_RX_IND_FLUSH_SEQ_NUM_END_SET +#define HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_END_GET \ + HTT_RX_IND_FLUSH_SEQ_NUM_END_GET + +#define HTT_RX_FRAG_IND_FW_RX_DESC_BYTES_GET HTT_RX_IND_FW_RX_DESC_BYTES_GET + +#define HTT_RX_FRAG_IND_BYTES \ + (4 /* msg hdr */ + \ + 4 /* flush spec */ + \ + 4 /* (unused) FW rx desc bytes spec */ + \ + 4 /* FW rx desc */) + +/** + * @brief target -> host test message definition + * + * @details + * The following field definitions describe the format of the test + * message sent from the target to the host. + * The message consists of a 4-octet header, followed by a variable + * number of 32-bit integer values, followed by a variable number + * of 8-bit character values. + * + * |31 16|15 8|7 0| + * |-----------------------------------------------------------| + * | num chars | num ints | msg type | + * |-----------------------------------------------------------| + * | int 0 | + * |-----------------------------------------------------------| + * | int 1 | + * |-----------------------------------------------------------| + * | ... | + * |-----------------------------------------------------------| + * | char 3 | char 2 | char 1 | char 0 | + * |-----------------------------------------------------------| + * | | | ... | char 4 | + * |-----------------------------------------------------------| + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a test message + * Value: HTT_MSG_TYPE_TEST + * - NUM_INTS + * Bits 15:8 + * Purpose: indicate how many 32-bit integers follow the message header + * - NUM_CHARS + * Bits 31:16 + * Purpose: indicate how many 8-bit charaters follow the series of integers + */ +#define HTT_RX_TEST_NUM_INTS_M 0xff00 +#define HTT_RX_TEST_NUM_INTS_S 8 +#define HTT_RX_TEST_NUM_CHARS_M 0xffff0000 +#define HTT_RX_TEST_NUM_CHARS_S 16 + +#define HTT_RX_TEST_NUM_INTS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_TEST_NUM_INTS, value); \ + (word) |= (value) << HTT_RX_TEST_NUM_INTS_S; \ + } while (0) +#define HTT_RX_TEST_NUM_INTS_GET(word) \ + (((word) & HTT_RX_TEST_NUM_INTS_M) >> HTT_RX_TEST_NUM_INTS_S) + +#define HTT_RX_TEST_NUM_CHARS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_TEST_NUM_CHARS, value); \ + (word) |= (value) << HTT_RX_TEST_NUM_CHARS_S; \ + } while (0) +#define HTT_RX_TEST_NUM_CHARS_GET(word) \ + (((word) & HTT_RX_TEST_NUM_CHARS_M) >> HTT_RX_TEST_NUM_CHARS_S) + +/** + * @brief target -> host packet log message + * + * @details + * The following field definitions describe the format of the packet log + * message sent from the target to the host. + * The message consists of a 4-octet header,followed by a variable number + * of 32-bit character values. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------| + * | | | | msg type | + * |-----------------------------------------------------------| + * | payload | + * |-----------------------------------------------------------| + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a test message + * Value: HTT_MSG_TYPE_PACKETLOG + */ +PREPACK struct htt_pktlog_msg { + A_UINT32 header; + A_UINT32 payload[1/* or more */]; +} POSTPACK; + + +/* + * Rx reorder statistics + * NB: all the fields must be defined in 4 octets size. + */ +struct rx_reorder_stats { + /* Non QoS MPDUs received */ + A_UINT32 deliver_non_qos; + /* MPDUs received in-order */ + A_UINT32 deliver_in_order; + /* Flush due to reorder timer expired */ + A_UINT32 deliver_flush_timeout; + /* Flush due to move out of window */ + A_UINT32 deliver_flush_oow; + /* Flush due to DELBA */ + A_UINT32 deliver_flush_delba; + /* MPDUs dropped due to FCS error */ + A_UINT32 fcs_error; + /* MPDUs dropped due to monitor mode non-data packet */ + A_UINT32 mgmt_ctrl; + /* Unicast-data MPDUs dropped due to invalid peer */ + A_UINT32 invalid_peer; + /* MPDUs dropped due to duplication (non aggregation) */ + A_UINT32 dup_non_aggr; + /* MPDUs dropped due to processed before */ + A_UINT32 dup_past; + /* MPDUs dropped due to duplicate in reorder queue */ + A_UINT32 dup_in_reorder; + /* Reorder timeout happened */ + A_UINT32 reorder_timeout; + /* invalid bar ssn */ + A_UINT32 invalid_bar_ssn; + /* reorder reset due to bar ssn */ + A_UINT32 ssn_reset; + /* Flush due to delete peer */ + A_UINT32 deliver_flush_delpeer; + /* Flush due to offload*/ + A_UINT32 deliver_flush_offload; + /* Flush due to out of buffer*/ + A_UINT32 deliver_flush_oob; + /* MPDUs dropped due to PN check fail */ + A_UINT32 pn_fail; + /* MPDUs dropped due to unable to allocate memory */ + A_UINT32 store_fail; + /* Number of times the tid pool alloc succeeded */ + A_UINT32 tid_pool_alloc_succ; + /* Number of times the MPDU pool alloc succeeded */ + A_UINT32 mpdu_pool_alloc_succ; + /* Number of times the MSDU pool alloc succeeded */ + A_UINT32 msdu_pool_alloc_succ; + /* Number of times the tid pool alloc failed */ + A_UINT32 tid_pool_alloc_fail; + /* Number of times the MPDU pool alloc failed */ + A_UINT32 mpdu_pool_alloc_fail; + /* Number of times the MSDU pool alloc failed */ + A_UINT32 msdu_pool_alloc_fail; + /* Number of times the tid pool freed */ + A_UINT32 tid_pool_free; + /* Number of times the MPDU pool freed */ + A_UINT32 mpdu_pool_free; + /* Number of times the MSDU pool freed */ + A_UINT32 msdu_pool_free; + /* number of MSDUs undelivered to HTT and queued to Data Rx MSDU free list*/ + A_UINT32 msdu_queued; + /* Number of MSDUs released from Data Rx MSDU list to MAC ring */ + A_UINT32 msdu_recycled; + /* Number of MPDUs with invalid peer but A2 found in AST */ + A_UINT32 invalid_peer_a2_in_ast; + /* Number of MPDUs with invalid peer but A3 found in AST */ + A_UINT32 invalid_peer_a3_in_ast; + /* Number of MPDUs with invalid peer, Broadcast or Multicast frame */ + A_UINT32 invalid_peer_bmc_mpdus; + /* Number of MSDUs with err attention word */ + A_UINT32 rxdesc_err_att; + /* Number of MSDUs with flag of peer_idx_invalid */ + A_UINT32 rxdesc_err_peer_idx_inv; + /* Number of MSDUs with flag of peer_idx_timeout */ + A_UINT32 rxdesc_err_peer_idx_to; + /* Number of MSDUs with flag of overflow */ + A_UINT32 rxdesc_err_ov; + /* Number of MSDUs with flag of msdu_length_err */ + A_UINT32 rxdesc_err_msdu_len; + /* Number of MSDUs with flag of mpdu_length_err */ + A_UINT32 rxdesc_err_mpdu_len; + /* Number of MSDUs with flag of tkip_mic_err */ + A_UINT32 rxdesc_err_tkip_mic; + /* Number of MSDUs with flag of decrypt_err */ + A_UINT32 rxdesc_err_decrypt; + /* Number of MSDUs with flag of fcs_err */ + A_UINT32 rxdesc_err_fcs; + /* Number of Unicast (bc_mc bit is not set in attention word) + * frames with invalid peer handler + */ + A_UINT32 rxdesc_uc_msdus_inv_peer; + /* Number of unicast frame directly (direct bit is set in attention word) + * to DUT with invalid peer handler + */ + A_UINT32 rxdesc_direct_msdus_inv_peer; + /* Number of Broadcast/Multicast (bc_mc bit set in attention word) + * frames with invalid peer handler + */ + A_UINT32 rxdesc_bmc_msdus_inv_peer; + /* Number of MSDUs dropped due to no first MSDU flag */ + A_UINT32 rxdesc_no_1st_msdu; + /* Number of MSDUs droped due to ring overflow */ + A_UINT32 msdu_drop_ring_ov; + /* Number of MSDUs dropped due to FC mismatch */ + A_UINT32 msdu_drop_fc_mismatch; + /* Number of MSDUs dropped due to mgt frame in Remote ring */ + A_UINT32 msdu_drop_mgmt_remote_ring; + /* Number of MSDUs dropped due to errors not reported in attention word */ + A_UINT32 msdu_drop_misc; + /* Number of MSDUs go to offload before reorder */ + A_UINT32 offload_msdu_wal; + /* Number of data frame dropped by offload after reorder */ + A_UINT32 offload_msdu_reorder; + /* Number of MPDUs with sequence number in the past and within + the BA window */ + A_UINT32 dup_past_within_window; + /* Number of MPDUs with sequence number in the past and + * outside the BA window */ + A_UINT32 dup_past_outside_window; + /* Number of MSDUs with decrypt/MIC error */ + A_UINT32 rxdesc_err_decrypt_mic; + /* Number of data MSDUs received on both local and remote rings */ + A_UINT32 data_msdus_on_both_rings; +}; + + +/* + * Rx Remote buffer statistics + * NB: all the fields must be defined in 4 octets size. + */ +struct rx_remote_buffer_mgmt_stats { + /* Total number of MSDUs reaped for Rx processing */ + A_UINT32 remote_reaped; + /* MSDUs recycled within firmware */ + A_UINT32 remote_recycled; + /* MSDUs stored by Data Rx */ + A_UINT32 data_rx_msdus_stored; + /* Number of HTT indications from WAL Rx MSDU */ + A_UINT32 wal_rx_ind; + /* Number of unconsumed HTT indications from WAL Rx MSDU */ + A_UINT32 wal_rx_ind_unconsumed; + /* Number of HTT indications from Data Rx MSDU */ + A_UINT32 data_rx_ind; + /* Number of unconsumed HTT indications from Data Rx MSDU */ + A_UINT32 data_rx_ind_unconsumed; + /* Number of HTT indications from ATHBUF */ + A_UINT32 athbuf_rx_ind; + /* Number of remote buffers requested for refill */ + A_UINT32 refill_buf_req; + /* Number of remote buffers filled by the host */ + A_UINT32 refill_buf_rsp; + /* Number of times MAC hw_index = f/w write_index */ + A_INT32 mac_no_bufs; + /* Number of times f/w write_index = f/w read_index for MAC Rx ring */ + A_INT32 fw_indices_equal; + /* Number of times f/w finds no buffers to post */ + A_INT32 host_no_bufs; +}; + +/* + * TXBF MU/SU packets and NDPA statistics + * NB: all the fields must be defined in 4 octets size. + */ +struct rx_txbf_musu_ndpa_pkts_stats { + /* number of TXBF MU packets received */ + A_UINT32 number_mu_pkts; + /* number of TXBF SU packets received */ + A_UINT32 number_su_pkts; + /* number of TXBF directed NDPA */ + A_UINT32 txbf_directed_ndpa_count; + /* number of TXBF retried NDPA */ + A_UINT32 txbf_ndpa_retry_count; + /* total number of TXBF NDPA */ + A_UINT32 txbf_total_ndpa_count; + /* must be set to 0x0 */ + A_UINT32 reserved[3]; +}; + + + +/* + * htt_dbg_stats_status - + * present - The requested stats have been delivered in full. + * This indicates that either the stats information was contained + * in its entirety within this message, or else this message + * completes the delivery of the requested stats info that was + * partially delivered through earlier STATS_CONF messages. + * partial - The requested stats have been delivered in part. + * One or more subsequent STATS_CONF messages with the same + * cookie value will be sent to deliver the remainder of the + * information. + * error - The requested stats could not be delivered, for example due + * to a shortage of memory to construct a message holding the + * requested stats. + * invalid - The requested stat type is either not recognized, or the + * target is configured to not gather the stats type in question. + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * series_done - This special value indicates that no further stats info + * elements are present within a series of stats info elems + * (within a stats upload confirmation message). + */ +enum htt_dbg_stats_status { + HTT_DBG_STATS_STATUS_PRESENT = 0, + HTT_DBG_STATS_STATUS_PARTIAL = 1, + HTT_DBG_STATS_STATUS_ERROR = 2, + HTT_DBG_STATS_STATUS_INVALID = 3, + + + HTT_DBG_STATS_STATUS_SERIES_DONE = 7 +}; + +/** + * @brief target -> host statistics upload + * + * @details + * The following field definitions describe the format of the HTT target + * to host stats upload confirmation message. + * The message contains a cookie echoed from the HTT host->target stats + * upload request, which identifies which request the confirmation is + * for, and a series of tag-length-value stats information elements. + * The tag-length header for each stats info element also includes a + * status field, to indicate whether the request for the stat type in + * question was fully met, partially met, unable to be met, or invalid + * (if the stat type in question is disabled in the target). + * A special value of all 1's in this status field is used to indicate + * the end of the series of stats info elements. + * + * + * |31 16|15 8|7 5|4 0| + * |------------------------------------------------------------| + * | reserved | msg type | + * |------------------------------------------------------------| + * | cookie LSBs | + * |------------------------------------------------------------| + * | cookie MSBs | + * |------------------------------------------------------------| + * | stats entry length | reserved | S |stat type| + * |------------------------------------------------------------| + * | | + * | type-specific stats info | + * | | + * |------------------------------------------------------------| + * | stats entry length | reserved | S |stat type| + * |------------------------------------------------------------| + * | | + * | type-specific stats info | + * | | + * |------------------------------------------------------------| + * | n/a | reserved | 111 | n/a | + * |------------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this is a statistics upload confirmation message + * Value: 0x9 + * - COOKIE_LSBS + * Bits 31:0 + * Purpose: Provide a mechanism to match a target->host stats confirmation + * message with its preceding host->target stats request message. + * Value: LSBs of the opaque cookie specified by the host-side requestor + * - COOKIE_MSBS + * Bits 31:0 + * Purpose: Provide a mechanism to match a target->host stats confirmation + * message with its preceding host->target stats request message. + * Value: MSBs of the opaque cookie specified by the host-side requestor + * + * Stats Information Element tag-length header fields: + * - STAT_TYPE + * Bits 4:0 + * Purpose: identifies the type of statistics info held in the + * following information element + * Value: htt_dbg_stats_type + * - STATUS + * Bits 7:5 + * Purpose: indicate whether the requested stats are present + * Value: htt_dbg_stats_status, including a special value (0x7) to mark + * the completion of the stats entry series + * - LENGTH + * Bits 31:16 + * Purpose: indicate the stats information size + * Value: This field specifies the number of bytes of stats information + * that follows the element tag-length header. + * It is expected but not required that this length is a multiple of + * 4 bytes. Even if the length is not an integer multiple of 4, the + * subsequent stats entry header will begin on a 4-byte aligned + * boundary. + */ +#define HTT_T2H_STATS_COOKIE_SIZE 8 + +#define HTT_T2H_STATS_CONF_TAIL_SIZE 4 + +#define HTT_T2H_STATS_CONF_HDR_SIZE 4 + +#define HTT_T2H_STATS_CONF_TLV_HDR_SIZE 4 + +#define HTT_T2H_STATS_CONF_TLV_TYPE_M 0x0000001f +#define HTT_T2H_STATS_CONF_TLV_TYPE_S 0 +#define HTT_T2H_STATS_CONF_TLV_STATUS_M 0x000000e0 +#define HTT_T2H_STATS_CONF_TLV_STATUS_S 5 +#define HTT_T2H_STATS_CONF_TLV_LENGTH_M 0xffff0000 +#define HTT_T2H_STATS_CONF_TLV_LENGTH_S 16 + +#define HTT_T2H_STATS_CONF_TLV_TYPE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_T2H_STATS_CONF_TLV_TYPE, value); \ + (word) |= (value) << HTT_T2H_STATS_CONF_TLV_TYPE_S; \ + } while (0) +#define HTT_T2H_STATS_CONF_TLV_TYPE_GET(word) \ + (((word) & HTT_T2H_STATS_CONF_TLV_TYPE_M) >> \ + HTT_T2H_STATS_CONF_TLV_TYPE_S) + +#define HTT_T2H_STATS_CONF_TLV_STATUS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_T2H_STATS_CONF_TLV_STATUS, value); \ + (word) |= (value) << HTT_T2H_STATS_CONF_TLV_STATUS_S; \ + } while (0) +#define HTT_T2H_STATS_CONF_TLV_STATUS_GET(word) \ + (((word) & HTT_T2H_STATS_CONF_TLV_STATUS_M) >> \ + HTT_T2H_STATS_CONF_TLV_STATUS_S) + +#define HTT_T2H_STATS_CONF_TLV_LENGTH_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_T2H_STATS_CONF_TLV_LENGTH, value); \ + (word) |= (value) << HTT_T2H_STATS_CONF_TLV_LENGTH_S; \ + } while (0) +#define HTT_T2H_STATS_CONF_TLV_LENGTH_GET(word) \ + (((word) & HTT_T2H_STATS_CONF_TLV_LENGTH_M) >> \ + HTT_T2H_STATS_CONF_TLV_LENGTH_S) + +#define HL_HTT_FW_RX_DESC_RSVD_SIZE 18 +#define HTT_MAX_AGGR 64 +#define HTT_HL_MAX_AGGR 18 + +/** + * @brief host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank + * + * @details + * The following field definitions describe the format of the HTT host + * to target frag_desc/msdu_ext bank configuration message. + * The message contains the based address and the min and max id of the + * MSDU_EXT/FRAG_DESC that will be used by the HTT to map MSDU DESC and + * MSDU_EXT/FRAG_DESC. + * HTT will use id in HTT descriptor instead sending the frag_desc_ptr. + * In peregrine the firmware will use fragment_desc_ptr but in WIFI2.0 + * the hardware does the mapping/translation. + * + * Total banks that can be configured is configured to 16. + * + * This should be called before any TX has be initiated by the HTT + * + * |31 16|15 8|7 5|4 0| + * |------------------------------------------------------------| + * | DESC_SIZE | NUM_BANKS | RES |SWP|pdev| msg type | + * |------------------------------------------------------------| + * | BANK0_BASE_ADDRESS (bits 31:0) | +#if HTT_PADDR64 + * | BANK0_BASE_ADDRESS (bits 63:32) | +#endif + * |------------------------------------------------------------| + * | ... | + * |------------------------------------------------------------| + * | BANK15_BASE_ADDRESS (bits 31:0) | +#if HTT_PADDR64 + * | BANK15_BASE_ADDRESS (bits 63:32) | +#endif + * |------------------------------------------------------------| + * | BANK0_MAX_ID | BANK0_MIN_ID | + * |------------------------------------------------------------| + * | ... | + * |------------------------------------------------------------| + * | BANK15_MAX_ID | BANK15_MIN_ID | + * |------------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Value: 0x6 + * for systems with 64-bit format for bus addresses: + * - BANKx_BASE_ADDRESS_LO + * Bits 31:0 + * Purpose: Provide a mechanism to specify the base address of the + * MSDU_EXT bank physical/bus address. + * Value: lower 4 bytes of MSDU_EXT bank physical / bus address + * - BANKx_BASE_ADDRESS_HI + * Bits 31:0 + * Purpose: Provide a mechanism to specify the base address of the + * MSDU_EXT bank physical/bus address. + * Value: higher 4 bytes of MSDU_EXT bank physical / bus address + * for systems with 32-bit format for bus addresses: + * - BANKx_BASE_ADDRESS + * Bits 31:0 + * Purpose: Provide a mechanism to specify the base address of the + * MSDU_EXT bank physical/bus address. + * Value: MSDU_EXT bank physical / bus address + * - BANKx_MIN_ID + * Bits 15:0 + * Purpose: Provide a mechanism to specify the min index that needs to + * mapped. + * - BANKx_MAX_ID + * Bits 31:16 + * Purpose: Provide a mechanism to specify the max index that needs to + * mapped. + * + */ + +/** @todo Compress the fields to fit MAX HTT Message size, until then configure to a + * safe value. + * @note MAX supported banks is 16. + */ +#define HTT_TX_MSDU_EXT_BANK_MAX 4 + +#define HTT_H2T_FRAG_DESC_BANK_PDEVID_M 0x300 +#define HTT_H2T_FRAG_DESC_BANK_PDEVID_S 8 + +#define HTT_H2T_FRAG_DESC_BANK_SWAP_M 0x400 +#define HTT_H2T_FRAG_DESC_BANK_SWAP_S 10 + +#define HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_M 0xff0000 +#define HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_S 16 + +#define HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_M 0xff000000 +#define HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_S 24 + +#define HTT_H2T_FRAG_DESC_BANK_MIN_IDX_M 0xffff +#define HTT_H2T_FRAG_DESC_BANK_MIN_IDX_S 0 + +#define HTT_H2T_FRAG_DESC_BANK_MAX_IDX_M 0xffff0000 +#define HTT_H2T_FRAG_DESC_BANK_MAX_IDX_S 16 + +#define HTT_H2T_FRAG_DESC_BANK_PDEVID_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_FRAG_DESC_BANK_PDEVID, value); \ + (word) |= ((value) << HTT_H2T_FRAG_DESC_BANK_PDEVID_S); \ + } while (0) +#define HTT_H2T_FRAG_DESC_BANK_PDEVID_GET(word) \ + (((word) & HTT_H2T_FRAG_DESC_BANK_PDEVID_M) >> HTT_H2T_FRAG_DESC_BANK_PDEVID_S) + +#define HTT_H2T_FRAG_DESC_BANK_SWAP_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_FRAG_DESC_BANK_SWAP, value); \ + (word) |= ((value) << HTT_H2T_FRAG_DESC_BANK_SWAP_S); \ + } while (0) +#define HTT_H2T_FRAG_DESC_BANK_SWAP_GET(word) \ + (((word) & HTT_H2T_FRAG_DESC_BANK_SWAP_M) >> HTT_H2T_FRAG_DESC_BANK_SWAP_S) + +#define HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_FRAG_DESC_BANK_NUM_BANKS, value); \ + (word) |= ((value) << HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_S); \ + } while (0) +#define HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_GET(word) \ + (((word) & HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_M) >> HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_S) + +#define HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_FRAG_DESC_BANK_DESC_SIZE, value); \ + (word) |= ((value) << HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_S); \ + } while (0) +#define HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_GET(word) \ + (((word) & HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_M) >> HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_S) + +#define HTT_H2T_FRAG_DESC_BANK_MIN_IDX_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_FRAG_DESC_BANK_MIN_IDX, value); \ + (word) |= ((value) << HTT_H2T_FRAG_DESC_BANK_MIN_IDX_S); \ + } while (0) +#define HTT_H2T_FRAG_DESC_BANK_MIN_IDX_GET(word) \ + (((word) & HTT_H2T_FRAG_DESC_BANK_MIN_IDX_M) >> HTT_H2T_FRAG_DESC_BANK_MIN_IDX_S) + +#define HTT_H2T_FRAG_DESC_BANK_MAX_IDX_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_H2T_FRAG_DESC_BANK_MAX_IDX, value); \ + (word) |= ((value) << HTT_H2T_FRAG_DESC_BANK_MAX_IDX_S); \ + } while (0) +#define HTT_H2T_FRAG_DESC_BANK_MAX_IDX_GET(word) \ + (((word) & HTT_H2T_FRAG_DESC_BANK_MAX_IDX_M) >> HTT_H2T_FRAG_DESC_BANK_MAX_IDX_S) + + +/* + * TEMPLATE_HTT_TX_FRAG_DESC_BANK_CFG_T: + * This macro defines a htt_tx_frag_descXXX_bank_cfg_t in which any physical + * addresses are stored in a XXX-bit field. + * This macro is used to define both htt_tx_frag_desc32_bank_cfg_t and + * htt_tx_frag_desc64_bank_cfg_t structs. + */ +#define TEMPLATE_HTT_TX_FRAG_DESC_BANK_CFG_T( \ + _paddr_bits_, \ + _paddr__bank_base_address_) \ +PREPACK struct htt_tx_frag_desc ## _paddr_bits_ ## _bank_cfg_t { \ + /** word 0 \ + * msg_type: 8, \ + * pdev_id: 2, \ + * swap: 1, \ + * reserved0: 5, \ + * num_banks: 8, \ + * desc_size: 8; \ + */ \ + A_UINT32 word0; \ + /* \ + * If bank_base_address is 64 bits, the upper / lower halves are stored \ + * in little-endian order (bytes 0-3 in the first A_UINT32, bytes 4-7 in \ + * the second A_UINT32). \ + */ \ + _paddr__bank_base_address_[HTT_TX_MSDU_EXT_BANK_MAX]; \ + A_UINT32 bank_info[HTT_TX_MSDU_EXT_BANK_MAX]; \ +} POSTPACK +/* define htt_tx_frag_desc32_bank_cfg_t */ +TEMPLATE_HTT_TX_FRAG_DESC_BANK_CFG_T(32, HTT_VAR_PADDR32(bank_base_address)); +/* define htt_tx_frag_desc64_bank_cfg_t */ +TEMPLATE_HTT_TX_FRAG_DESC_BANK_CFG_T(64, HTT_VAR_PADDR64_LE(bank_base_address)); +/* + * Make htt_tx_frag_desc_bank_cfg_t be an alias for either + * htt_tx_frag_desc32_bank_cfg_t or htt_tx_frag_desc64_bank_cfg_t + */ +#if HTT_PADDR64 + #define htt_tx_frag_desc_bank_cfg_t htt_tx_frag_desc64_bank_cfg_t +#else + #define htt_tx_frag_desc_bank_cfg_t htt_tx_frag_desc32_bank_cfg_t +#endif + + +/** + * @brief target -> host HTT TX Credit total count update message definition + * + *|31 16|15|14 9| 8 |7 0 | + *|---------------------+--+----------+-------+----------| + *|cur htt credit delta | Q| reserved | sign | msg type | + *|------------------------------------------------------| + * + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a htt tx credit delta update message + * Value: 0xe + * - SIGN + * Bits 8 + * identifies whether credit delta is positive or negative + * Value: + * - 0x0: credit delta is positive, rebalance in some buffers + * - 0x1: credit delta is negative, rebalance out some buffers + * - reserved + * Bits 14:9 + * Value: 0x0 + * - TXQ_GRP + * Bit 15 + * Purpose: indicates whether any tx queue group information elements + * are appended to the tx credit update message + * Value: 0 -> no tx queue group information element is present + * 1 -> a tx queue group information element immediately follows + * - DELTA_COUNT + * Bits 31:16 + * Purpose: Specify current htt credit delta absolute count + */ + +#define HTT_TX_CREDIT_SIGN_BIT_M 0x00000100 +#define HTT_TX_CREDIT_SIGN_BIT_S 8 +#define HTT_TX_CREDIT_TXQ_GRP_M 0x00008000 +#define HTT_TX_CREDIT_TXQ_GRP_S 15 +#define HTT_TX_CREDIT_DELTA_ABS_M 0xffff0000 +#define HTT_TX_CREDIT_DELTA_ABS_S 16 + + +#define HTT_TX_CREDIT_SIGN_BIT_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_CREDIT_SIGN_BIT, value); \ + (word) |= (value) << HTT_TX_CREDIT_SIGN_BIT_S; \ + } while (0) + +#define HTT_TX_CREDIT_SIGN_BIT_GET(word) \ + (((word) & HTT_TX_CREDIT_SIGN_BIT_M) >> HTT_TX_CREDIT_SIGN_BIT_S) + +#define HTT_TX_CREDIT_TXQ_GRP_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_CREDIT_TXQ_GRP, value); \ + (word) |= (value) << HTT_TX_CREDIT_TXQ_GRP_S; \ + } while (0) + +#define HTT_TX_CREDIT_TXQ_GRP_GET(word) \ + (((word) & HTT_TX_CREDIT_TXQ_GRP_M) >> HTT_TX_CREDIT_TXQ_GRP_S) + +#define HTT_TX_CREDIT_DELTA_ABS_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_CREDIT_DELTA_ABS, value); \ + (word) |= (value) << HTT_TX_CREDIT_DELTA_ABS_S; \ + } while (0) + +#define HTT_TX_CREDIT_DELTA_ABS_GET(word) \ + (((word) & HTT_TX_CREDIT_DELTA_ABS_M) >> HTT_TX_CREDIT_DELTA_ABS_S) + + +#define HTT_TX_CREDIT_MSG_BYTES 4 + +#define HTT_TX_CREDIT_SIGN_BIT_POSITIVE 0x0 +#define HTT_TX_CREDIT_SIGN_BIT_NEGATIVE 0x1 + + +/** + * @brief HTT WDI_IPA Operation Response Message + * + * @details + * HTT WDI_IPA Operation Response message is sent by target + * to host confirming suspend or resume operation. + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | op_code | Rsvd | msg_type | + * |-------------------------------------------------------------------| + * | Rsvd | Response len | + * |-------------------------------------------------------------------| + * | | + * | Response-type specific info | + * | | + * | | + * |-------------------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: Identifies this as WDI_IPA Operation Response message + * value: = 0x13 + * - OP_CODE + * Bits 31:16 + * Purpose: Identifies the operation target is responding to (e.g. TX suspend) + * value: = enum htt_wdi_ipa_op_code + * - RSP_LEN + * Bits 16:0 + * Purpose: length for the response-type specific info + * value: = length in bytes for response-type specific info + * For example, if OP_CODE == HTT_WDI_IPA_OPCODE_DBG_STATS, the + * length value will be sizeof(struct wlan_wdi_ipa_dbg_stats_t). + */ + +PREPACK struct htt_wdi_ipa_op_response_t +{ + /* DWORD 0: flags and meta-data */ + A_UINT32 + msg_type: 8, /* HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE */ + reserved1: 8, + op_code: 16; + A_UINT32 + rsp_len: 16, + reserved2: 16; +} POSTPACK; + +#define HTT_WDI_IPA_OP_RESPONSE_SZ 8 /* bytes */ + +#define HTT_WDI_IPA_OP_RESPONSE_OP_CODE_M 0xffff0000 +#define HTT_WDI_IPA_OP_RESPONSE_OP_CODE_S 16 + +#define HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_M 0x0000ffff +#define HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_S 0 + +#define HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(_var) \ + (((_var) & HTT_WDI_IPA_OP_RESPONSE_OP_CODE_M) >> HTT_WDI_IPA_OP_RESPONSE_OP_CODE_S) +#define HTT_WDI_IPA_OP_RESPONSE_OP_CODE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_OP_RESPONSE_OP_CODE, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_OP_RESPONSE_OP_CODE_S)); \ + } while (0) + +#define HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_GET(_var) \ + (((_var) & HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_M) >> HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_S) +#define HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_WDI_IPA_OP_RESPONSE_RSP_LEN, _val); \ + ((_var) |= ((_val) << HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_S)); \ + } while (0) + + +enum htt_phy_mode { + htt_phy_mode_11a = 0, + htt_phy_mode_11g = 1, + htt_phy_mode_11b = 2, + htt_phy_mode_11g_only = 3, + htt_phy_mode_11na_ht20 = 4, + htt_phy_mode_11ng_ht20 = 5, + htt_phy_mode_11na_ht40 = 6, + htt_phy_mode_11ng_ht40 = 7, + htt_phy_mode_11ac_vht20 = 8, + htt_phy_mode_11ac_vht40 = 9, + htt_phy_mode_11ac_vht80 = 10, + htt_phy_mode_11ac_vht20_2g = 11, + htt_phy_mode_11ac_vht40_2g = 12, + htt_phy_mode_11ac_vht80_2g = 13, + htt_phy_mode_11ac_vht80_80 = 14, /* 80+80 */ + htt_phy_mode_11ac_vht160 = 15, + + htt_phy_mode_max, +}; + +/** + * @brief target -> host HTT channel change indication + * @details + * Specify when a channel change occurs. + * This allows the host to precisely determine which rx frames arrived + * on the old channel and which rx frames arrived on the new channel. + * + *|31 |7 0 | + *|-------------------------------------------+----------| + *| reserved | msg type | + *|------------------------------------------------------| + *| primary_chan_center_freq_mhz | + *|------------------------------------------------------| + *| contiguous_chan1_center_freq_mhz | + *|------------------------------------------------------| + *| contiguous_chan2_center_freq_mhz | + *|------------------------------------------------------| + *| phy_mode | + *|------------------------------------------------------| + * + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a htt channel change indication message + * Value: 0x15 + * - PRIMARY_CHAN_CENTER_FREQ_MHZ + * Bits 31:0 + * Purpose: identify the (center of the) new 20 MHz primary channel + * Value: center frequency of the 20 MHz primary channel, in MHz units + * - CONTIG_CHAN1_CENTER_FREQ_MHZ + * Bits 31:0 + * Purpose: identify the (center of the) contiguous frequency range + * comprising the new channel. + * For example, if the new channel is a 80 MHz channel extending + * 60 MHz beyond the primary channel, this field would be 30 larger + * than the primary channel center frequency field. + * Value: center frequency of the contiguous frequency range comprising + * the full channel in MHz units + * (80+80 channels also use the CONTIG_CHAN2 field) + * - CONTIG_CHAN2_CENTER_FREQ_MHZ + * Bits 31:0 + * Purpose: Identify the (center of the) 80 MHz extension frequency range + * within a VHT 80+80 channel. + * This field is only relevant for VHT 80+80 channels. + * Value: center frequency of the 80 MHz extension channel in a VHT 80+80 + * channel (arbitrary value for cases besides VHT 80+80) + * - PHY_MODE + * Bits 31:0 + * Purpose: specify the PHY channel's type (legacy vs. HT vs. VHT), width, + * and band + * Value: htt_phy_mode enum value + */ + +PREPACK struct htt_chan_change_t +{ + /* DWORD 0: flags and meta-data */ + A_UINT32 + msg_type: 8, /* HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE */ + reserved1: 24; + A_UINT32 primary_chan_center_freq_mhz; + A_UINT32 contig_chan1_center_freq_mhz; + A_UINT32 contig_chan2_center_freq_mhz; + A_UINT32 phy_mode; +} POSTPACK; + +#define HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_M 0xffffffff +#define HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_S 0 +#define HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_M 0xffffffff +#define HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_S 0 +#define HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_M 0xffffffff +#define HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_S 0 +#define HTT_CHAN_CHANGE_PHY_MODE_M 0xffffffff +#define HTT_CHAN_CHANGE_PHY_MODE_S 0 + + +#define HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ, value);\ + (word) |= (value) << HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_S; \ + } while (0) +#define HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_GET(word) \ + (((word) & HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_M) \ + >> HTT_CHAN_CHANGE_PRIMARY_CHAN_CENTER_FREQ_MHZ_S) + +#define HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ, value);\ + (word) |= (value) << HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_S; \ + } while (0) +#define HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_GET(word) \ + (((word) & HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_M) \ + >> HTT_CHAN_CHANGE_CONTIG_CHAN1_CENTER_FREQ_MHZ_S) + +#define HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ, value);\ + (word) |= (value) << HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_S; \ + } while (0) +#define HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_GET(word) \ + (((word) & HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_M) \ + >> HTT_CHAN_CHANGE_CONTIG_CHAN2_CENTER_FREQ_MHZ_S) + +#define HTT_CHAN_CHANGE_PHY_MODE_SET(word, value) \ + do { \ + HTT_CHECK_SET_VAL(HTT_CHAN_CHANGE_PHY_MODE, value);\ + (word) |= (value) << HTT_CHAN_CHANGE_PHY_MODE_S; \ + } while (0) +#define HTT_CHAN_CHANGE_PHY_MODE_GET(word) \ + (((word) & HTT_CHAN_CHANGE_PHY_MODE_M) \ + >> HTT_CHAN_CHANGE_PHY_MODE_S) + +#define HTT_CHAN_CHANGE_BYTES sizeof(struct htt_chan_change_t) + + +/** + * @brief rx offload packet error message + * + * @details + * HTT_RX_OFLD_PKT_ERR message is sent by target to host to indicate err + * of target payload like mic err. + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | tid | vdev_id | msg_sub_type | msg_type | + * |-------------------------------------------------------------------| + * : (sub-type dependent content) : + * :- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -: + * Header fields: + * - msg_type + * Bits 7:0 + * Purpose: Identifies this as HTT_RX_OFLD_PKT_ERR message + * value: 0x16 (HTT_T2H_MSG_TYPE_RX_OFLD_PKT_ERR) + * - msg_sub_type + * Bits 15:8 + * Purpose: Identifies which type of rx error is reported by this message + * value: htt_rx_ofld_pkt_err_type + * - vdev_id + * Bits 23:16 + * Purpose: Identifies which vdev received the erroneous rx frame + * value: + * - tid + * Bits 31:24 + * Purpose: Identifies the traffic type of the rx frame + * value: + * + * - The payload fields used if the sub-type == MIC error are shown below. + * Note - MIC err is per MSDU, while PN is per MPDU. + * The FW will discard the whole MPDU if any MSDU within the MPDU is marked + * with MIC err in A-MSDU case, so FW will send only one HTT message + * with the PN of this MPDU attached to indicate MIC err for one MPDU + * instead of sending separate HTT messages for each wrong MSDU within + * the MPDU. + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | Rsvd | key_id | peer_id | + * |-------------------------------------------------------------------| + * | receiver MAC addr 31:0 | + * |-------------------------------------------------------------------| + * | Rsvd | receiver MAC addr 47:32 | + * |-------------------------------------------------------------------| + * | transmitter MAC addr 31:0 | + * |-------------------------------------------------------------------| + * | Rsvd | transmitter MAC addr 47:32 | + * |-------------------------------------------------------------------| + * | PN 31:0 | + * |-------------------------------------------------------------------| + * | Rsvd | PN 47:32 | + * |-------------------------------------------------------------------| + * - peer_id + * Bits 15:0 + * Purpose: identifies which peer is frame is from + * value: + * - key_id + * Bits 23:16 + * Purpose: identifies key_id of rx frame + * value: + * - RA_31_0 (receiver MAC addr 31:0) + * Bits 31:0 + * Purpose: identifies by MAC address which vdev received the frame + * value: MAC address lower 4 bytes + * - RA_47_32 (receiver MAC addr 47:32) + * Bits 15:0 + * Purpose: identifies by MAC address which vdev received the frame + * value: MAC address upper 2 bytes + * - TA_31_0 (transmitter MAC addr 31:0) + * Bits 31:0 + * Purpose: identifies by MAC address which peer transmitted the frame + * value: MAC address lower 4 bytes + * - TA_47_32 (transmitter MAC addr 47:32) + * Bits 15:0 + * Purpose: identifies by MAC address which peer transmitted the frame + * value: MAC address upper 2 bytes + * - PN_31_0 + * Bits 31:0 + * Purpose: Identifies pn of rx frame + * value: PN lower 4 bytes + * - PN_47_32 + * Bits 15:0 + * Purpose: Identifies pn of rx frame + * value: + * TKIP or CCMP: PN upper 2 bytes + * WAPI: PN bytes 6:5 (bytes 15:7 not included in this message) + */ + +enum htt_rx_ofld_pkt_err_type { + HTT_RX_OFLD_PKT_ERR_TYPE_NONE = 0, + HTT_RX_OFLD_PKT_ERR_TYPE_MIC_ERR, +}; + +/* definition for HTT_RX_OFLD_PKT_ERR msg hdr */ +#define HTT_RX_OFLD_PKT_ERR_HDR_BYTES 4 + +#define HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_M 0x0000ff00 +#define HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_S 8 + +#define HTT_RX_OFLD_PKT_ERR_VDEV_ID_M 0x00ff0000 +#define HTT_RX_OFLD_PKT_ERR_VDEV_ID_S 16 + +#define HTT_RX_OFLD_PKT_ERR_TID_M 0xff000000 +#define HTT_RX_OFLD_PKT_ERR_TID_S 24 + +#define HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_M) \ + >> HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_S) +#define HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_VDEV_ID_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_VDEV_ID_M) >> HTT_RX_OFLD_PKT_ERR_VDEV_ID_S) +#define HTT_RX_OFLD_PKT_ERR_VDEV_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_VDEV_ID, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_VDEV_ID_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_TID_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_TID_M) >> HTT_RX_OFLD_PKT_ERR_TID_S) +#define HTT_RX_OFLD_PKT_ERR_TID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_TID, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_TID_S)); \ + } while (0) + +/* definition for HTT_RX_OFLD_PKT_ERR_MIC_ERR msg sub-type payload */ +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_BYTES 28 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_M 0x0000ffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_M 0x00ff0000 +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_S 16 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_M 0xffffffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_M 0x0000ffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_M 0xffffffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_M 0x0000ffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_M 0xffffffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_M 0x0000ffff +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_S 0 + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_31_0_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_RA_47_32_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_31_0_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_TA_47_32_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_31_0_S)); \ + } while (0) + +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_GET(_var) \ + (((_var) & HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_M) >> \ + HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_S) +#define HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32, _val); \ + ((_var) |= ((_val) << HTT_RX_OFLD_PKT_ERR_MIC_ERR_PN_47_32_S)); \ + } while (0) + +/** + * @brief peer rate report message + * + * @details + * HTT_T2H_MSG_TYPE_RATE_REPORT message is sent by target to host to + * indicate the justified rate of all the peers. + * + * |31 24|23 16|15 8|7 0| + * |-------------+-------------+-------------+-------------| + * | peer_count | reserved | msg_type | + * |-------------------------------------------------------| + * : Payload (variant number of peer rate report) : + * :- - -- - - - - - - - - - - - - - - - - - - - - - - - -: + * Header fields: + * - msg_type + * Bits 7:0 + * Purpose: Identifies this as HTT_T2H_MSG_TYPE_RATE_REPORT message. + * value: 0x17 (HTT_T2H_MSG_TYPE_RATE_REPORT) + * - reserved + * Bits 15:8 + * Purpose: + * value: + * - peer_count + * Bits 31:16 + * Purpose: Specify how many peer rate report elements are present + * in the payload. + * value: + * + * Payload: + * There are variant number of peer rate report follow the first 32 + * bits. The peer rate report is defined as follows. + * + * |31 20|19 16|15 0| + * |----------------+--------+------------------------|- + * | reserved | phy | peer_id | \ + * |--------------------------------------------------| -> report #0 + * | rate | / + * |----------------+--------+------------------------|- + * | reserved | phy | peer_id | \ + * |--------------------------------------------------| -> report #1 + * | rate | / + * |----------------+--------+------------------------|- + * | reserved | phy | peer_id | \ + * |--------------------------------------------------| -> report #2 + * | rate | / + * |---- ---------------------------------------------|- + * : : + * : : + * : : + * :--------------------------------------------------: + * + * - peer_id + * Bits 15:0 + * Purpose: identify the peer + * value: + * - phy + * Bits 19:16 + * Purpose: identify which phy is in use + * value: 0=11b, 1=11a/g, 2=11n, 3=11ac. + * Please see enum htt_peer_report_phy_type for detail. + * - reserved + * Bits 31:20 + * Purpose: + * value: + * - rate + * Bits 31:0 + * Purpose: represent the justified rate of the peer specified + * by peer_id + * value: + */ + +enum htt_peer_rate_report_phy_type { + HTT_PEER_RATE_REPORT_11B = 0, + HTT_PEER_RATE_REPORT_11A_G, + HTT_PEER_RATE_REPORT_11N, + HTT_PEER_RATE_REPORT_11AC, +}; + +#define HTT_PEER_RATE_REPORT_SIZE 8 + +#define HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_M 0xffff0000 +#define HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_S 16 + +#define HTT_PEER_RATE_REPORT_MSG_PEER_ID_M 0x0000ffff +#define HTT_PEER_RATE_REPORT_MSG_PEER_ID_S 0 + +#define HTT_PEER_RATE_REPORT_MSG_PHY_M 0x000f0000 +#define HTT_PEER_RATE_REPORT_MSG_PHY_S 16 + +#define HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_GET(_var) \ + (((_var) & HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_M) \ + >> HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_S) +#define HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_PEER_RATE_REPORT_MSG_PEER_COUNT, _val); \ + ((_var) |= ((_val) << HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_S)); \ + } while (0) + +#define HTT_PEER_RATE_REPORT_MSG_PEER_ID_GET(_var) \ + (((_var) & HTT_PEER_RATE_REPORT_MSG_PEER_ID_M) \ + >> HTT_PEER_RATE_REPORT_MSG_PEER_ID_S) +#define HTT_PEER_RATE_REPORT_MSG_PEER_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_PEER_RATE_REPORT_MSG_PEER_ID, _val); \ + ((_var) |= ((_val) << HTT_PEER_RATE_REPORT_MSG_PEER_ID_S)); \ + } while (0) + +#define HTT_PEER_RATE_REPORT_MSG_PHY_GET(_var) \ + (((_var) & HTT_PEER_RATE_REPORT_MSG_PHY_M) \ + >> HTT_PEER_RATE_REPORT_MSG_PHY_S) +#define HTT_PEER_RATE_REPORT_MSG_PHY_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_PEER_RATE_REPORT_MSG_PHY, _val); \ + ((_var) |= ((_val) << HTT_PEER_RATE_REPORT_MSG_PHY_S)); \ + } while (0) + +/** + * @brief HTT_T2H_MSG_TYPE_FLOW_POOL_MAP Message + * + * @details + * HTT_T2H_MSG_TYPE_FLOW_POOL_MAP message is sent by the target when setting up + * a flow of descriptors. + * + * This message is in TLV format and indicates the parameters to be setup a + * flow in the host. Each entry indicates that a particular flow ID is ready to + * receive descriptors from a specified pool. + * + * The message would appear as follows: + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * header | reserved | num_flows | msg_type | + * |-------------------------------------------------------------------| + * | | + * : payload : + * | | + * |-------------------------------------------------------------------| + * + * The header field is one DWORD long and is interpreted as follows: + * b'0:7 - msg_type: This will be set to HTT_T2H_MSG_TYPE_FLOW_POOL_MAP + * b'8-15 - num_flows: This will indicate the number of flows being setup in + * this message + * b'16-31 - reserved: These bits are reserved for future use + * + * Payload: + * The payload would contain multiple objects of the following structure. Each + * object represents a flow. + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * header | reserved | num_flows | msg_type | + * |-------------------------------------------------------------------| + * payload0| flow_type | + * |-------------------------------------------------------------------| + * | flow_id | + * |-------------------------------------------------------------------| + * | reserved0 | flow_pool_id | + * |-------------------------------------------------------------------| + * | reserved1 | flow_pool_size | + * |-------------------------------------------------------------------| + * | reserved2 | + * |-------------------------------------------------------------------| + * payload1| flow_type | + * |-------------------------------------------------------------------| + * | flow_id | + * |-------------------------------------------------------------------| + * | reserved0 | flow_pool_id | + * |-------------------------------------------------------------------| + * | reserved1 | flow_pool_size | + * |-------------------------------------------------------------------| + * | reserved2 | + * |-------------------------------------------------------------------| + * | . | + * | . | + * | . | + * |-------------------------------------------------------------------| + * + * Each payload is 5 DWORDS long and is interpreted as follows: + * dword0 - b'0:31 - flow_type: This indicates the type of the entity to which + * this flow is associated. It can be VDEV, peer, + * or tid (AC). Based on enum htt_flow_type. + * + * dword1 - b'0:31 - flow_id: Identifier for the flow corresponding to this + * object. For flow_type vdev it is set to the + * vdevid, for peer it is peerid and for tid, it is + * tid_num. + * + * dword2 - b'0:15 - flow_pool_id: Identifier of the descriptor-pool being used + * in the host for this flow + * b'16:31 - reserved0: This field in reserved for the future. In case + * we have a hierarchical implementation (HCM) of + * pools, it can be used to indicate the ID of the + * parent-pool. + * + * dword3 - b'0:15 - flow_pool_size: Size of the pool in number of descriptors. + * Descriptors for this flow will be + * allocated from this pool in the host. + * b'16:31 - reserved1: This field in reserved for the future. In case + * we have a hierarchical implementation of pools, + * it can be used to indicate the max number of + * descriptors in the pool. The b'0:15 can be used + * to indicate min number of descriptors in the + * HCM scheme. + * + * dword4 - b'0:31 - reserved2: This field in reserved for the future. In case + * we have a hierarchical implementation of pools, + * b'0:15 can be used to indicate the + * priority-based borrowing (PBB) threshold of + * the flow's pool. The b'16:31 are still left + * reserved. + */ + +enum htt_flow_type { + FLOW_TYPE_VDEV = 0, + /* Insert new flow types above this line */ +}; + +PREPACK struct htt_flow_pool_map_payload_t { + A_UINT32 flow_type; + A_UINT32 flow_id; + A_UINT32 flow_pool_id:16, + reserved0:16; + A_UINT32 flow_pool_size:16, + reserved1:16; + A_UINT32 reserved2; +} POSTPACK; + +#define HTT_FLOW_POOL_MAP_HEADER_SZ (sizeof(A_UINT32)) + +#define HTT_FLOW_POOL_MAP_PAYLOAD_SZ \ + (sizeof(struct htt_flow_pool_map_payload_t)) + +#define HTT_FLOW_POOL_MAP_NUM_FLOWS_M 0x0000ff00 +#define HTT_FLOW_POOL_MAP_NUM_FLOWS_S 8 + +#define HTT_FLOW_POOL_MAP_FLOW_TYPE_M 0xffffffff +#define HTT_FLOW_POOL_MAP_FLOW_TYPE_S 0 + +#define HTT_FLOW_POOL_MAP_FLOW_ID_M 0xffffffff +#define HTT_FLOW_POOL_MAP_FLOW_ID_S 0 + +#define HTT_FLOW_POOL_MAP_FLOW_POOL_ID_M 0x0000ffff +#define HTT_FLOW_POOL_MAP_FLOW_POOL_ID_S 0 + +#define HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_M 0x0000ffff +#define HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_S 0 + +#define HTT_FLOW_POOL_MAP_NUM_FLOWS_GET(_var) \ + (((_var) & HTT_FLOW_POOL_MAP_NUM_FLOWS_M) >> HTT_FLOW_POOL_MAP_NUM_FLOWS_S) + +#define HTT_FLOW_POOL_MAP_FLOW_TYPE_GET(_var) \ + (((_var) & HTT_FLOW_POOL_MAP_FLOW_TYPE_M) >> HTT_FLOW_POOL_MAP_FLOW_TYPE_S) + +#define HTT_FLOW_POOL_MAP_FLOW_ID_GET(_var) \ + (((_var) & HTT_FLOW_POOL_MAP_FLOW_ID_M) >> HTT_FLOW_POOL_MAP_FLOW_ID_S) + +#define HTT_FLOW_POOL_MAP_FLOW_POOL_ID_GET(_var) \ + (((_var) & HTT_FLOW_POOL_MAP_FLOW_POOL_ID_M) >> \ + HTT_FLOW_POOL_MAP_FLOW_POOL_ID_S) + +#define HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_GET(_var) \ + (((_var) & HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_M) >> \ + HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_S) + +#define HTT_FLOW_POOL_MAP_NUM_FLOWS_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_MAP_NUM_FLOWS, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_MAP_NUM_FLOWS_S)); \ + } while (0) + +#define HTT_FLOW_POOL_MAP_FLOW_TYPE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_MAP_FLOW_TYPE, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_MAP_FLOW_TYPE_S)); \ + } while (0) + +#define HTT_FLOW_POOL_MAP_FLOW_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_MAP_FLOW_ID, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_MAP_FLOW_ID_S)); \ + } while (0) + +#define HTT_FLOW_POOL_MAP_FLOW_POOL_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_MAP_FLOW_POOL_ID, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_MAP_FLOW_POOL_ID_S)); \ + } while (0) + +#define HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_MAP_FLOW_POOL_SIZE_S)); \ + } while (0) + +/** + * @brief HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP Message + * + * @details + * HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP message is sent by the target when tearing + * down a flow of descriptors. + * This message indicates that for the flow (whose ID is provided) is wanting + * to stop receiving descriptors. This flow ID corresponds to the ID of the + * pool of descriptors from where descriptors are being allocated for this + * flow. When a flow (and its pool) are unmapped, all the child-pools will also + * be unmapped by the host. + * + * The message would appear as follows: + * + * |31 24|23 16|15 8|7 0| + * |----------------+----------------+----------------+----------------| + * | reserved0 | msg_type | + * |-------------------------------------------------------------------| + * | flow_type | + * |-------------------------------------------------------------------| + * | flow_id | + * |-------------------------------------------------------------------| + * | reserved1 | flow_pool_id | + * |-------------------------------------------------------------------| + * + * The message is interpreted as follows: + * dword0 - b'0:7 - msg_type: This will be set to + * HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP + * b'8:31 - reserved0: Reserved for future use + * + * dword1 - b'0:31 - flow_type: This indicates the type of the entity to which + * this flow is associated. It can be VDEV, peer, + * or tid (AC). Based on enum htt_flow_type. + * + * dword2 - b'0:31 - flow_id: Identifier for the flow corresponding to this + * object. For flow_type vdev it is set to the + * vdevid, for peer it is peerid and for tid, it is + * tid_num. + * + * dword3 - b'0:15 - flow_pool_id: Identifier of the descriptor-pool being + * used in the host for this flow + * b'16:31 - reserved0: This field in reserved for the future. + * + */ + +PREPACK struct htt_flow_pool_unmap_t { + A_UINT32 msg_type:8, + reserved0:24; + A_UINT32 flow_type; + A_UINT32 flow_id; + A_UINT32 flow_pool_id:16, + reserved1:16; +} POSTPACK; + +#define HTT_FLOW_POOL_UNMAP_SZ (sizeof(struct htt_flow_pool_unmap_t)) + +#define HTT_FLOW_POOL_UNMAP_FLOW_TYPE_M 0xffffffff +#define HTT_FLOW_POOL_UNMAP_FLOW_TYPE_S 0 + +#define HTT_FLOW_POOL_UNMAP_FLOW_ID_M 0xffffffff +#define HTT_FLOW_POOL_UNMAP_FLOW_ID_S 0 + +#define HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_M 0x0000ffff +#define HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_S 0 + +#define HTT_FLOW_POOL_UNMAP_FLOW_TYPE_GET(_var) \ + (((_var) & HTT_FLOW_POOL_UNMAP_FLOW_TYPE_M) >> \ + HTT_FLOW_POOL_UNMAP_FLOW_TYPE_S) + +#define HTT_FLOW_POOL_UNMAP_FLOW_ID_GET(_var) \ + (((_var) & HTT_FLOW_POOL_UNMAP_FLOW_ID_M) >> HTT_FLOW_POOL_UNMAP_FLOW_ID_S) + +#define HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_GET(_var) \ + (((_var) & HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_M) >> \ + HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_S) + +#define HTT_FLOW_POOL_UNMAP_FLOW_TYPE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_UNMAP_FLOW_TYPE, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_UNMAP_FLOW_TYPE_S)); \ + } while (0) + +#define HTT_FLOW_POOL_UNMAP_FLOW_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_UNMAP_FLOW_ID, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_UNMAP_FLOW_ID_S)); \ + } while (0) + +#define HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID, _val); \ + ((_var) |= ((_val) << HTT_FLOW_POOL_UNMAP_FLOW_POOL_ID_S)); \ + } while (0) + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_common.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_common.h new file mode 100644 index 000000000000..d187adebcdc6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_common.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_common.h + * + * @details the public header file of HTT layer shared between host and firmware + */ + +#ifndef _HTT_COMMON_H_ +#define _HTT_COMMON_H_ + +enum htt_sec_type { + htt_sec_type_none, + htt_sec_type_wep128, + htt_sec_type_wep104, + htt_sec_type_wep40, + htt_sec_type_tkip, + htt_sec_type_tkip_nomic, + htt_sec_type_aes_ccmp, + htt_sec_type_wapi, + + /* keep this last! */ + htt_num_sec_types +}; + + +enum htt_rx_ind_mpdu_status { + HTT_RX_IND_MPDU_STATUS_UNKNOWN = 0x0, + HTT_RX_IND_MPDU_STATUS_OK, + HTT_RX_IND_MPDU_STATUS_ERR_FCS, + HTT_RX_IND_MPDU_STATUS_ERR_DUP, + HTT_RX_IND_MPDU_STATUS_ERR_REPLAY, + HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER, + HTT_RX_IND_MPDU_STATUS_UNAUTH_PEER, /* only accept EAPOL frames */ + HTT_RX_IND_MPDU_STATUS_OUT_OF_SYNC, + HTT_RX_IND_MPDU_STATUS_MGMT_CTRL, /* Non-data in promiscous mode */ + HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR, + + /* + * MISC: discard for unspecified reasons. + * Leave this enum value last. + */ + HTT_RX_IND_MPDU_STATUS_ERR_MISC = 0xFF +}; + + +#endif /* _HTT_COMMON_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_fw_stats.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_fw_stats.c new file mode 100644 index 000000000000..8742c1ae61e8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_fw_stats.c @@ -0,0 +1,872 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_fw_stats.c + * @brief Provide functions to process FW status retrieved from FW. + */ + +#include /* HTC_PACKET */ +#include /* HTT_T2H_MSG_TYPE, etc. */ +#include /* adf_nbuf_t */ +#include /* adf_os_mem_set */ +#include /* ol_fw_tx_dbg_ppdu_base */ + +#include +#include /* htt_tx_status */ + +#include + +#include + +#define ROUND_UP_TO_4(val) (((val) + 3) & ~0x3) + +static void htt_t2h_stats_tx_rate_stats_print( + wlan_dbg_tx_rate_info_t *tx_rate_info, int concise) +{ + adf_os_print("TX Rate Info:\n"); + + /* MCS */ + adf_os_print("MCS counts (0..9): "); + adf_os_print("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + tx_rate_info->mcs[0], + tx_rate_info->mcs[1], + tx_rate_info->mcs[2], + tx_rate_info->mcs[3], + tx_rate_info->mcs[4], + tx_rate_info->mcs[5], + tx_rate_info->mcs[6], + tx_rate_info->mcs[7], + tx_rate_info->mcs[8], + tx_rate_info->mcs[9] + ); + + /* SGI */ + adf_os_print("SGI counts (0..9): "); + adf_os_print("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + tx_rate_info->sgi[0], + tx_rate_info->sgi[1], + tx_rate_info->sgi[2], + tx_rate_info->sgi[3], + tx_rate_info->sgi[4], + tx_rate_info->sgi[5], + tx_rate_info->sgi[6], + tx_rate_info->sgi[7], + tx_rate_info->sgi[8], + tx_rate_info->sgi[9] + ); + + /* NSS */ + adf_os_print("NSS counts: "); + adf_os_print("1x1 %d, 2x2 %d, 3x3 %d\n", + tx_rate_info->nss[0], + tx_rate_info->nss[1], + tx_rate_info->nss[2] + ); + + /* BW */ + adf_os_print("BW counts: "); + adf_os_print("20MHz %d, 40MHz %d, 80MHz %d\n", + tx_rate_info->bw[0], + tx_rate_info->bw[1], + tx_rate_info->bw[2] + ); + + /* Preamble */ + adf_os_print("Preamble (O C H V) counts: "); + adf_os_print("%d, %d, %d, %d\n", + tx_rate_info->pream[0], + tx_rate_info->pream[1], + tx_rate_info->pream[2], + tx_rate_info->pream[3] + ); + + /* STBC rate counts */ + adf_os_print("STBC rate counts (0..9): "); + adf_os_print("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + tx_rate_info->stbc[0], + tx_rate_info->stbc[1], + tx_rate_info->stbc[2], + tx_rate_info->stbc[3], + tx_rate_info->stbc[4], + tx_rate_info->stbc[5], + tx_rate_info->stbc[6], + tx_rate_info->stbc[7], + tx_rate_info->stbc[8], + tx_rate_info->stbc[9] + ); + + /* LDPC and TxBF counts */ + adf_os_print("LDPC Counts: "); + adf_os_print("%d\n", tx_rate_info->ldpc); + adf_os_print("RTS Counts: "); + adf_os_print("%d\n", tx_rate_info->rts_cnt); + /* RSSI Values for last ack frames */ + adf_os_print("Ack RSSI: %d\n",tx_rate_info->ack_rssi); +} + +static void htt_t2h_stats_rx_rate_stats_print( + wlan_dbg_rx_rate_info_t *rx_phy_info, int concise) +{ + adf_os_print("RX Rate Info:\n"); + + /* MCS */ + adf_os_print("MCS counts (0..9): "); + adf_os_print("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + rx_phy_info->mcs[0], + rx_phy_info->mcs[1], + rx_phy_info->mcs[2], + rx_phy_info->mcs[3], + rx_phy_info->mcs[4], + rx_phy_info->mcs[5], + rx_phy_info->mcs[6], + rx_phy_info->mcs[7], + rx_phy_info->mcs[8], + rx_phy_info->mcs[9] + ); + + /* SGI */ + adf_os_print("SGI counts (0..9): "); + adf_os_print("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + rx_phy_info->sgi[0], + rx_phy_info->sgi[1], + rx_phy_info->sgi[2], + rx_phy_info->sgi[3], + rx_phy_info->sgi[4], + rx_phy_info->sgi[5], + rx_phy_info->sgi[6], + rx_phy_info->sgi[7], + rx_phy_info->sgi[8], + rx_phy_info->sgi[9] + ); + + /* NSS */ + adf_os_print("NSS counts: "); + /* nss[0] just holds the count of non-stbc frames that were sent at 1x1 + * rates and nsts holds the count of frames sent with stbc. It was decided + * to not include PPDUs sent w/ STBC in nss[0] since it would be easier to + * change the value that needs to be printed (from "stbc+non-stbc count to + * only non-stbc count") if needed in the future. Hence the addition in the + * host code at this line. */ + adf_os_print("1x1 %d, 2x2 %d, 3x3 %d, 4x4 %d\n", + rx_phy_info->nss[0] + rx_phy_info->nsts, + rx_phy_info->nss[1], + rx_phy_info->nss[2], + rx_phy_info->nss[3] + ); + + /* NSTS */ + adf_os_print("NSTS count: "); + adf_os_print("%d\n", rx_phy_info->nsts); + + /* BW */ + adf_os_print("BW counts: "); + adf_os_print("20MHz %d, 40MHz %d, 80MHz %d\n", + rx_phy_info->bw[0], + rx_phy_info->bw[1], + rx_phy_info->bw[2] + ); + + /* Preamble */ + adf_os_print("Preamble counts: "); + adf_os_print("%d, %d, %d, %d, %d, %d\n", + rx_phy_info->pream[0], + rx_phy_info->pream[1], + rx_phy_info->pream[2], + rx_phy_info->pream[3], + rx_phy_info->pream[4], + rx_phy_info->pream[5] + ); + + /* STBC rate counts */ + adf_os_print("STBC rate counts (0..9): "); + adf_os_print("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + rx_phy_info->stbc[0], + rx_phy_info->stbc[1], + rx_phy_info->stbc[2], + rx_phy_info->stbc[3], + rx_phy_info->stbc[4], + rx_phy_info->stbc[5], + rx_phy_info->stbc[6], + rx_phy_info->stbc[7], + rx_phy_info->stbc[8], + rx_phy_info->stbc[9] + ); + + /* LDPC and TxBF counts */ + adf_os_print("LDPC TXBF Counts: "); + adf_os_print("%d, %d\n", rx_phy_info->ldpc, rx_phy_info->txbf); + /* RSSI Values for last received frames */ + adf_os_print("RSSI (data, mgmt): %d, %d\n",rx_phy_info->data_rssi, + rx_phy_info->mgmt_rssi); + + adf_os_print("RSSI Chain 0 (0x%02x 0x%02x 0x%02x 0x%02x)\n", + ((rx_phy_info->rssi_chain0 >> 24) & 0xff), + ((rx_phy_info->rssi_chain0 >> 16) & 0xff), + ((rx_phy_info->rssi_chain0 >> 8) & 0xff), + ((rx_phy_info->rssi_chain0 >> 0) & 0xff)); + + adf_os_print("RSSI Chain 1 (0x%02x 0x%02x 0x%02x 0x%02x)\n", + ((rx_phy_info->rssi_chain1 >> 24) & 0xff), + ((rx_phy_info->rssi_chain1 >> 16) & 0xff), + ((rx_phy_info->rssi_chain1 >> 8) & 0xff), + ((rx_phy_info->rssi_chain1 >> 0) & 0xff)); + + adf_os_print("RSSI Chain 2 (0x%02x 0x%02x 0x%02x 0x%02x)\n", + ((rx_phy_info->rssi_chain2 >> 24) & 0xff), + ((rx_phy_info->rssi_chain2 >> 16) & 0xff), + ((rx_phy_info->rssi_chain2 >> 8) & 0xff), + ((rx_phy_info->rssi_chain2 >> 0) & 0xff)); +} + + +static void +htt_t2h_stats_pdev_stats_print( + struct wlan_dbg_stats *wlan_pdev_stats, int concise) +{ + struct wlan_dbg_tx_stats *tx = &wlan_pdev_stats->tx; + struct wlan_dbg_rx_stats *rx = &wlan_pdev_stats->rx; + + adf_os_print("WAL Pdev stats:\n"); + adf_os_print("\n### Tx ###\n"); + + /* Num HTT cookies queued to dispatch list */ + adf_os_print("comp_queued :\t%d\n",tx->comp_queued); + /* Num HTT cookies dispatched */ + adf_os_print("comp_delivered :\t%d\n",tx->comp_delivered); + /* Num MSDU queued to WAL */ + adf_os_print("msdu_enqued :\t%d\n",tx->msdu_enqued); + /* Num MPDU queued to WAL */ + adf_os_print("mpdu_enqued :\t%d\n",tx->mpdu_enqued); + /* Num MSDUs dropped by WMM limit */ + adf_os_print("wmm_drop :\t%d\n",tx->wmm_drop); + /* Num Local frames queued */ + adf_os_print("local_enqued :\t%d\n",tx->local_enqued); + /* Num Local frames done */ + adf_os_print("local_freed :\t%d\n",tx->local_freed); + /* Num queued to HW */ + adf_os_print("hw_queued :\t%d\n",tx->hw_queued); + /* Num PPDU reaped from HW */ + adf_os_print("hw_reaped :\t%d\n",tx->hw_reaped); + /* Num underruns */ + adf_os_print("mac underrun :\t%d\n",tx->underrun); + /* Num underruns */ + adf_os_print("phy underrun :\t%d\n",tx->phy_underrun); + /* Num PPDUs cleaned up in TX abort */ + adf_os_print("tx_abort :\t%d\n",tx->tx_abort); + /* Num MPDUs requed by SW */ + adf_os_print("mpdus_requed :\t%d\n",tx->mpdus_requed); + /* Excessive retries */ + adf_os_print("excess retries :\t%d\n",tx->tx_ko); + /* last data rate */ + adf_os_print("last rc :\t%d\n",tx->data_rc); + /* scheduler self triggers */ + adf_os_print("sched self trig :\t%d\n",tx->self_triggers); + /* SW retry failures */ + adf_os_print("ampdu retry failed:\t%d\n",tx->sw_retry_failure); + /* ilegal phy rate errirs */ + adf_os_print("illegal rate errs :\t%d\n",tx->illgl_rate_phy_err); + /* pdev continous excessive retries */ + adf_os_print("pdev cont xretry :\t%d\n",tx->pdev_cont_xretry); + /* pdev continous excessive retries */ + adf_os_print("pdev tx timeout :\t%d\n",tx->pdev_tx_timeout); + /* pdev resets */ + adf_os_print("pdev resets :\t%d\n",tx->pdev_resets); + /* PPDU > txop duration */ + adf_os_print("ppdu txop ovf :\t%d\n",tx->txop_ovf); + + adf_os_print("\n### Rx ###\n"); + /* Cnts any change in ring routing mid-ppdu */ + adf_os_print("ppdu_route_change :\t%d\n",rx->mid_ppdu_route_change); + /* Total number of statuses processed */ + adf_os_print("status_rcvd :\t%d\n",rx->status_rcvd); + /* Extra frags on rings 0-3 */ + adf_os_print("r0_frags :\t%d\n",rx->r0_frags); + adf_os_print("r1_frags :\t%d\n",rx->r1_frags); + adf_os_print("r2_frags :\t%d\n",rx->r2_frags); + adf_os_print("r3_frags :\t%d\n",rx->r3_frags); + /* MSDUs / MPDUs delivered to HTT */ + adf_os_print("htt_msdus :\t%d\n",rx->htt_msdus); + adf_os_print("htt_mpdus :\t%d\n",rx->htt_mpdus); + /* MSDUs / MPDUs delivered to local stack */ + adf_os_print("loc_msdus :\t%d\n",rx->loc_msdus); + adf_os_print("loc_mpdus :\t%d\n",rx->loc_mpdus); + /* AMSDUs that have more MSDUs than the status ring size */ + adf_os_print("oversize_amsdu :\t%d\n",rx->oversize_amsdu); + /* Number of PHY errors */ + adf_os_print("phy_errs :\t%d\n",rx->phy_errs); + /* Number of PHY errors dropped */ + adf_os_print("phy_errs dropped :\t%d\n",rx->phy_err_drop); + /* Number of mpdu errors - FCS, MIC, ENC etc. */ + adf_os_print("mpdu_errs :\t%d\n",rx->mpdu_errs); + +} + +static void +htt_t2h_stats_rx_reorder_stats_print( + struct rx_reorder_stats *stats_ptr, int concise) +{ + adf_os_print("Rx reorder statistics:\n"); + adf_os_print(" %u non-QoS frames received\n", + stats_ptr->deliver_non_qos); + adf_os_print(" %u frames received in-order\n", + stats_ptr->deliver_in_order); + adf_os_print(" %u frames flushed due to timeout\n", + stats_ptr->deliver_flush_timeout); + adf_os_print(" %u frames flushed due to moving out of window\n", + stats_ptr->deliver_flush_oow); + adf_os_print(" %u frames flushed due to receiving DELBA\n", + stats_ptr->deliver_flush_delba); + adf_os_print(" %u frames discarded due to FCS error\n", + stats_ptr->fcs_error); + adf_os_print(" %u frames discarded due to invalid peer\n", + stats_ptr->invalid_peer); + adf_os_print(" %u frames discarded due to duplication (non aggregation)\n", + stats_ptr->dup_non_aggr); + adf_os_print(" %u frames discarded due to duplication in " + "reorder queue\n", stats_ptr->dup_in_reorder); + adf_os_print(" %u frames discarded due to processed before\n", + stats_ptr->dup_past); + adf_os_print(" %u times reorder timeout happened\n", + stats_ptr->reorder_timeout); + adf_os_print(" %u times incorrect bar received\n", + stats_ptr->invalid_bar_ssn); + adf_os_print(" %u times bar ssn reset happened\n", + stats_ptr->ssn_reset); + adf_os_print(" %u times flushed due to peer delete\n", + stats_ptr->deliver_flush_delpeer); + adf_os_print(" %u times flushed due to offload\n", + stats_ptr->deliver_flush_offload); + adf_os_print(" %u times flushed due to ouf of buffer\n", + stats_ptr->deliver_flush_oob); + adf_os_print(" %u MPDU's dropped due to PN check fail\n", + stats_ptr->pn_fail); + adf_os_print(" %u MPDU's dropped due to lack of memory\n", + stats_ptr->store_fail); + adf_os_print(" %u times tid pool alloc succeeded\n", + stats_ptr->tid_pool_alloc_succ); + adf_os_print(" %u times MPDU pool alloc succeeded\n", + stats_ptr->mpdu_pool_alloc_succ); + adf_os_print(" %u times MSDU pool alloc succeeded\n", + stats_ptr->msdu_pool_alloc_succ); + adf_os_print(" %u times tid pool alloc failed\n", + stats_ptr->tid_pool_alloc_fail); + adf_os_print(" %u times MPDU pool alloc failed\n", + stats_ptr->mpdu_pool_alloc_fail); + adf_os_print(" %u times MSDU pool alloc failed\n", + stats_ptr->msdu_pool_alloc_fail); + adf_os_print(" %u times tid pool freed\n", + stats_ptr->tid_pool_free); + adf_os_print(" %u times MPDU pool freed\n", + stats_ptr->mpdu_pool_free); + adf_os_print(" %u times MSDU pool freed\n", + stats_ptr->msdu_pool_free); + adf_os_print(" %u MSDUs undelivered to HTT, queued to Rx MSDU free list\n", + stats_ptr->msdu_queued); + adf_os_print(" %u MSDUs released from Rx MSDU list to MAC ring\n", + stats_ptr->msdu_recycled); + adf_os_print(" %u MPDUs with invalid peer but A2 found in AST\n", + stats_ptr->invalid_peer_a2_in_ast); + adf_os_print(" %u MPDUs with invalid peer but A3 found in AST\n", + stats_ptr->invalid_peer_a3_in_ast); + adf_os_print(" %u MPDUs with invalid peer, Broadcast or Mulitcast frame\n", + stats_ptr->invalid_peer_bmc_mpdus); + adf_os_print(" %u MSDUs with err attention word\n", + stats_ptr->rxdesc_err_att); + adf_os_print(" %u MSDUs with flag of peer_idx_invalid\n", + stats_ptr->rxdesc_err_peer_idx_inv); + adf_os_print(" %u MSDUs with flag of peer_idx_timeout\n", + stats_ptr->rxdesc_err_peer_idx_to); + adf_os_print(" %u MSDUs with flag of overflow\n", + stats_ptr->rxdesc_err_ov); + adf_os_print(" %u MSDUs with flag of msdu_length_err\n", + stats_ptr->rxdesc_err_msdu_len); + adf_os_print(" %u MSDUs with flag of mpdu_length_err\n", + stats_ptr->rxdesc_err_mpdu_len); + adf_os_print(" %u MSDUs with flag of tkip_mic_err\n", + stats_ptr->rxdesc_err_tkip_mic); + adf_os_print(" %u MSDUs with flag of decrypt_err\n", + stats_ptr->rxdesc_err_decrypt); + adf_os_print(" %u MSDUs with flag of fcs_err\n", + stats_ptr->rxdesc_err_fcs); + adf_os_print(" %u Unicast frames with invalid peer handler\n", + stats_ptr->rxdesc_uc_msdus_inv_peer); + adf_os_print(" %u unicast frame directly to DUT with invalid peer handler\n", + stats_ptr->rxdesc_direct_msdus_inv_peer); + adf_os_print(" %u Broadcast/Multicast frames with invalid peer handler\n", + stats_ptr->rxdesc_bmc_msdus_inv_peer); + adf_os_print(" %u MSDUs dropped due to no first MSDU flag\n", + stats_ptr->rxdesc_no_1st_msdu); + adf_os_print(" %u MSDUs dropped due to ring overflow\n", + stats_ptr->msdu_drop_ring_ov); + adf_os_print(" %u MSDUs dropped due to FC mismatch\n", + stats_ptr->msdu_drop_fc_mismatch); + adf_os_print(" %u MSDUs dropped due to mgt frame in Remote ring\n", + stats_ptr->msdu_drop_mgmt_remote_ring); + adf_os_print(" %u MSDUs dropped due to misc non error\n", + stats_ptr->msdu_drop_misc); + adf_os_print(" %u MSDUs go to offload before reorder\n", + stats_ptr->offload_msdu_wal); + adf_os_print(" %u data frame dropped by offload after reorder\n", + stats_ptr->offload_msdu_reorder); + adf_os_print(" %u MPDUs with SN in the past & within BA window\n", + stats_ptr->dup_past_within_window); + adf_os_print(" %u MPDUs with SN in the past & outside BA window\n", + stats_ptr->dup_past_outside_window); +} + +static void +htt_t2h_stats_rx_rem_buf_stats_print( + struct rx_remote_buffer_mgmt_stats *stats_ptr, int concise) +{ + adf_os_print("Rx Remote Buffer Statistics:\n"); + adf_os_print(" %u MSDU's reaped for Rx processing\n", + stats_ptr->remote_reaped); + adf_os_print(" %u MSDU's recycled within firmware\n", + stats_ptr->remote_recycled); + adf_os_print(" %u MSDU's stored by Data Rx\n", + stats_ptr->data_rx_msdus_stored); + adf_os_print(" %u HTT indications from WAL Rx MSDU\n", + stats_ptr->wal_rx_ind); + adf_os_print(" %u HTT indications unconsumed from WAL Rx MSDU\n", + stats_ptr->wal_rx_ind_unconsumed); + adf_os_print(" %u HTT indications from Data Rx MSDU\n", + stats_ptr->data_rx_ind); + adf_os_print(" %u HTT indications unconsumed from Data Rx MSDU\n", + stats_ptr->data_rx_ind_unconsumed); + adf_os_print(" %u HTT indications from ATHBUF\n", + stats_ptr->athbuf_rx_ind); + adf_os_print(" %u Remote buffers requested for refill\n", + stats_ptr->refill_buf_req); + adf_os_print(" %u Remote buffers filled by host\n", + stats_ptr->refill_buf_rsp); + adf_os_print(" %u times MAC has no buffers\n", + stats_ptr->mac_no_bufs); + adf_os_print(" %u times f/w write & read indices on MAC ring are equal\n", + stats_ptr->fw_indices_equal); + adf_os_print(" %u times f/w has no remote buffers to post to MAC\n", + stats_ptr->host_no_bufs); +} + +static void +htt_t2h_rx_musu_ndpa_pkts_stats_print( + struct rx_txbf_musu_ndpa_pkts_stats *stats_ptr, int concise) +{ + adf_os_print("Rx TXBF MU/SU Packets and NDPA Statistics:\n"); + adf_os_print(" %u Number of TXBF MU packets received\n", + stats_ptr->number_mu_pkts); + adf_os_print(" %u Number of TXBF SU packets received\n", + stats_ptr->number_su_pkts); + adf_os_print(" %u Number of TXBF directed NDPA\n", + stats_ptr->txbf_directed_ndpa_count); + adf_os_print(" %u Number of TXBF retried NDPA\n", + stats_ptr->txbf_ndpa_retry_count); + adf_os_print(" %u Total number of TXBF NDPA\n", + stats_ptr->txbf_total_ndpa_count); +} + +#define HTT_T2H_STATS_TX_PPDU_TIME_TO_MICROSEC(ticks, microsec_per_tick) \ + (ticks * microsec_per_tick) +static inline int +HTT_T2H_STATS_TX_PPDU_RATE_FLAGS_TO_MHZ(u_int8_t rate_flags) +{ + if (rate_flags & 0x20) return 40; /* WHAL_RC_FLAG_40MHZ */ + if (rate_flags & 0x40) return 80; /* WHAL_RC_FLAG_80MHZ */ + if (rate_flags & 0x80) return 160; /* WHAL_RC_FLAG_160MHZ */ + return 20; +} + +#define HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW 64 + +static void +htt_t2h_tx_ppdu_log_bitmaps_print( + u_int32_t *queued_ptr, + u_int32_t *acked_ptr) +{ + char queued_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW+1]; + char acked_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW+1]; + int i, j, word; + + adf_os_mem_set(queued_str, '0', HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW); + adf_os_mem_set(acked_str, '-', HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW); + i = 0; + for (word = 0; word < 2; word++) { + u_int32_t queued = *(queued_ptr + word); + u_int32_t acked = *(acked_ptr + word); + for (j = 0; j < 32; j++, i++) { + if (queued & (1 << j)) { + queued_str[i] = '1'; + acked_str[i] = (acked & (1 << j)) ? 'y' : 'N'; + } + } + } + queued_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW] = '\0'; + acked_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW] = '\0'; + adf_os_print("%s\n", queued_str); + adf_os_print("%s\n", acked_str); +} + +static inline u_int16_t htt_msg_read16(u_int16_t *p16) +{ +#ifdef BIG_ENDIAN_HOST + /* + * During upload, the bytes within each u_int32_t word were + * swapped by the HIF HW. This results in the lower and upper bytes + * of each u_int16_t to be in the correct big-endian order with + * respect to each other, but for each even-index u_int16_t to + * have its position switched with its successor neighbor u_int16_t. + * Undo this u_int16_t position swapping. + */ + return (((size_t) p16) & 0x2) ? *(p16 - 1) : *(p16 + 1); +#else + return *p16; +#endif +} + +static inline u_int8_t htt_msg_read8(u_int8_t *p8) +{ +#ifdef BIG_ENDIAN_HOST + /* + * During upload, the bytes within each u_int32_t word were + * swapped by the HIF HW. + * Undo this byte swapping. + */ + switch (((size_t) p8) & 0x3) { + case 0: + return *(p8 + 3); + case 1: + return *(p8 + 1); + case 2: + return *(p8 - 1); + default /* 3 */: + return *(p8 - 3); + } +#else + return *p8; +#endif +} + +void htt_make_u8_list_str( + u_int32_t *aligned_data, + char *buffer, + int space, + int max_elems) +{ + u_int8_t *p8 = (u_int8_t *) aligned_data; + char *buf_p = buffer; + while (max_elems-- > 0) { + int bytes; + u_int8_t val; + + val = htt_msg_read8(p8); + if (val == 0) { + break; /* not enough data to fill the reserved msg buffer space */ + } + bytes = adf_os_snprint(buf_p, space, "%d,", val); + space -= bytes; + if (space > 0) { + buf_p += bytes; + } else { + break; /* not enough print buffer space for all the data */ + } + p8++; + } + if (buf_p == buffer) { + *buf_p = '\0'; /* nothing was written */ + } else { + *(buf_p - 1) = '\0'; /* erase the final comma */ + } +} + +void htt_make_u16_list_str( + u_int32_t *aligned_data, + char *buffer, + int space, + int max_elems) +{ + u_int16_t *p16 = (u_int16_t *) aligned_data; + char *buf_p = buffer; + while (max_elems-- > 0) { + int bytes; + u_int16_t val; + + val = htt_msg_read16(p16); + if (val == 0) { + break; /* not enough data to fill the reserved msg buffer space */ + } + bytes = adf_os_snprint(buf_p, space, "%d,", val); + space -= bytes; + if (space > 0) { + buf_p += bytes; + } else { + break; /* not enough print buffer space for all the data */ + } + p16++; + } + if (buf_p == buffer) { + *buf_p = '\0'; /* nothing was written */ + } else { + *(buf_p - 1) = '\0'; /* erase the final comma */ + } +} + +void +htt_t2h_tx_ppdu_log_print( + struct ol_fw_tx_dbg_ppdu_msg_hdr *hdr, + struct ol_fw_tx_dbg_ppdu_base *record, + int length, int concise) +{ + int i; + int record_size; + int num_records; + + record_size = + sizeof(*record) + + hdr->mpdu_bytes_array_len * sizeof(u_int16_t) + + hdr->mpdu_msdus_array_len * sizeof(u_int8_t) + + hdr->msdu_bytes_array_len * sizeof(u_int16_t); + num_records = (length - sizeof(*hdr)) / record_size; + adf_os_print("Tx PPDU log elements:\n"); + + for (i = 0; i < num_records; i++) { + u_int16_t start_seq_num; + u_int16_t start_pn_lsbs; + u_int8_t num_mpdus; + u_int16_t peer_id; + u_int8_t ext_tid; + u_int8_t rate_code; + u_int8_t rate_flags; + u_int8_t tries; + u_int8_t complete; + u_int32_t time_enqueue_us; + u_int32_t time_completion_us; + u_int32_t *msg_word = (u_int32_t *) record; + + /* fields used for both concise and complete printouts */ + start_seq_num = + ((*(msg_word + OL_FW_TX_DBG_PPDU_START_SEQ_NUM_WORD)) & + OL_FW_TX_DBG_PPDU_START_SEQ_NUM_M) >> + OL_FW_TX_DBG_PPDU_START_SEQ_NUM_S; + complete = + ((*(msg_word + OL_FW_TX_DBG_PPDU_COMPLETE_WORD)) & + OL_FW_TX_DBG_PPDU_COMPLETE_M) >> + OL_FW_TX_DBG_PPDU_COMPLETE_S; + + /* fields used only for complete printouts */ + if (! concise) { + #define BUF_SIZE 80 + char buf[BUF_SIZE]; + u_int8_t *p8; + time_enqueue_us = HTT_T2H_STATS_TX_PPDU_TIME_TO_MICROSEC( + record->timestamp_enqueue, hdr->microsec_per_tick); + time_completion_us = HTT_T2H_STATS_TX_PPDU_TIME_TO_MICROSEC( + record->timestamp_completion, hdr->microsec_per_tick); + + start_pn_lsbs = + ((*(msg_word + OL_FW_TX_DBG_PPDU_START_PN_LSBS_WORD)) & + OL_FW_TX_DBG_PPDU_START_PN_LSBS_M) >> + OL_FW_TX_DBG_PPDU_START_PN_LSBS_S; + num_mpdus = + ((*(msg_word + OL_FW_TX_DBG_PPDU_NUM_MPDUS_WORD)) & + OL_FW_TX_DBG_PPDU_NUM_MPDUS_M) >> + OL_FW_TX_DBG_PPDU_NUM_MPDUS_S; + peer_id = + ((*(msg_word + OL_FW_TX_DBG_PPDU_PEER_ID_WORD)) & + OL_FW_TX_DBG_PPDU_PEER_ID_M) >> + OL_FW_TX_DBG_PPDU_PEER_ID_S; + ext_tid = + ((*(msg_word + OL_FW_TX_DBG_PPDU_EXT_TID_WORD)) & + OL_FW_TX_DBG_PPDU_EXT_TID_M) >> + OL_FW_TX_DBG_PPDU_EXT_TID_S; + rate_code = + ((*(msg_word + OL_FW_TX_DBG_PPDU_RATE_CODE_WORD)) & + OL_FW_TX_DBG_PPDU_RATE_CODE_M) >> + OL_FW_TX_DBG_PPDU_RATE_CODE_S; + rate_flags = + ((*(msg_word + OL_FW_TX_DBG_PPDU_RATE_FLAGS_WORD)) & + OL_FW_TX_DBG_PPDU_RATE_FLAGS_M) >> + OL_FW_TX_DBG_PPDU_RATE_FLAGS_S; + tries = + ((*(msg_word + OL_FW_TX_DBG_PPDU_TRIES_WORD)) & + OL_FW_TX_DBG_PPDU_TRIES_M) >> + OL_FW_TX_DBG_PPDU_TRIES_S; + + adf_os_print(" - PPDU tx to peer %d, TID %d\n", peer_id, ext_tid); + adf_os_print(" start seq num = %u, start PN LSBs = %#04x\n", + start_seq_num, start_pn_lsbs); + adf_os_print(" PPDU is %d MPDUs, (unknown) MSDUs, %d bytes\n", + num_mpdus, + //num_msdus, /* not yet being computed in target */ + record->num_bytes); + if (complete) { + adf_os_print(" enqueued at %u, completed at %u (microsec)\n", + time_enqueue_us, time_completion_us); + adf_os_print( + " %d total tries, last tx used rate %d " + "on %d MHz chan (flags = %#x)\n", + tries, rate_code, + HTT_T2H_STATS_TX_PPDU_RATE_FLAGS_TO_MHZ(rate_flags), + rate_flags); + adf_os_print(" enqueued and acked MPDU bitmaps:\n"); + htt_t2h_tx_ppdu_log_bitmaps_print( + msg_word + OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_WORD, + msg_word + OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_WORD); + } else { + adf_os_print( + " enqueued at %d ms (microsec), not yet completed\n", + time_enqueue_us); + } + /* skip past the regular message fields to reach the tail area */ + p8 = (u_int8_t *) record; + p8 += sizeof(struct ol_fw_tx_dbg_ppdu_base); + if (hdr->mpdu_bytes_array_len) { + htt_make_u16_list_str( + (u_int32_t *) p8, buf, BUF_SIZE, hdr->mpdu_bytes_array_len); + adf_os_print(" MPDU bytes: %s\n", buf); + } + p8 += hdr->mpdu_bytes_array_len * sizeof(u_int16_t); + if (hdr->mpdu_msdus_array_len) { + htt_make_u8_list_str( + (u_int32_t *) p8, buf, BUF_SIZE, hdr->mpdu_msdus_array_len); + adf_os_print(" MPDU MSDUs: %s\n", buf); + } + p8 += hdr->mpdu_msdus_array_len * sizeof(u_int8_t); + if (hdr->msdu_bytes_array_len) { + htt_make_u16_list_str( + (u_int32_t *) p8, buf, BUF_SIZE, hdr->msdu_bytes_array_len); + adf_os_print(" MSDU bytes: %s\n", buf); + } + } else { + /* concise */ + adf_os_print( + "start seq num = %u, enqueued and acked MPDU bitmaps:\n", + start_seq_num); + if (complete) { + htt_t2h_tx_ppdu_log_bitmaps_print( + msg_word + OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_WORD, + msg_word + OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_WORD); + } else { + adf_os_print("(not completed)\n"); + } + } + record = (struct ol_fw_tx_dbg_ppdu_base *) + (((u_int8_t *) record) + record_size); + } +} + +void +htt_t2h_stats_print(u_int8_t *stats_data, int concise) +{ + u_int32_t *msg_word = (u_int32_t *)stats_data; + enum htt_dbg_stats_type type; + enum htt_dbg_stats_status status; + int length; + + type = HTT_T2H_STATS_CONF_TLV_TYPE_GET(*msg_word); + status = HTT_T2H_STATS_CONF_TLV_STATUS_GET(*msg_word); + length = HTT_T2H_STATS_CONF_TLV_LENGTH_GET(*msg_word); + + /* check that we've been given a valid stats type */ + if (status == HTT_DBG_STATS_STATUS_SERIES_DONE) { + return; + } else if (status == HTT_DBG_STATS_STATUS_INVALID) { + adf_os_print( + "Target doesn't support stats type %d\n", type); + return; + } else if (status == HTT_DBG_STATS_STATUS_ERROR) { + adf_os_print( + "Target couldn't upload stats type %d (no mem?)\n", type); + return; + } + /* got valid (though perhaps partial) stats - process them */ + switch (type) { + case HTT_DBG_STATS_WAL_PDEV_TXRX: + { + struct wlan_dbg_stats *wlan_dbg_stats_ptr; + + wlan_dbg_stats_ptr = (struct wlan_dbg_stats *)(msg_word + 1); + htt_t2h_stats_pdev_stats_print(wlan_dbg_stats_ptr, concise); + break; + } + case HTT_DBG_STATS_RX_REORDER: + { + struct rx_reorder_stats *rx_reorder_stats_ptr; + + rx_reorder_stats_ptr = (struct rx_reorder_stats *)(msg_word + 1); + htt_t2h_stats_rx_reorder_stats_print(rx_reorder_stats_ptr, concise); + break; + } + + case HTT_DBG_STATS_RX_RATE_INFO: + { + wlan_dbg_rx_rate_info_t *rx_phy_info; + rx_phy_info = (wlan_dbg_rx_rate_info_t *)(msg_word + 1); + htt_t2h_stats_rx_rate_stats_print(rx_phy_info, concise); + break; + } + case HTT_DBG_STATS_TX_PPDU_LOG: + { + struct ol_fw_tx_dbg_ppdu_msg_hdr *hdr; + struct ol_fw_tx_dbg_ppdu_base *record; + + if (status == HTT_DBG_STATS_STATUS_PARTIAL && length == 0) { + adf_os_print("HTT_DBG_STATS_TX_PPDU_LOG -- length = 0!\n"); + break; + } + hdr = (struct ol_fw_tx_dbg_ppdu_msg_hdr *)(msg_word + 1); + record = (struct ol_fw_tx_dbg_ppdu_base *)(hdr + 1); + htt_t2h_tx_ppdu_log_print(hdr, record, length, concise); + } + break; + case HTT_DBG_STATS_TX_RATE_INFO: + { + wlan_dbg_tx_rate_info_t *tx_rate_info; + tx_rate_info = (wlan_dbg_tx_rate_info_t *)(msg_word + 1); + htt_t2h_stats_tx_rate_stats_print(tx_rate_info, concise); + break; + } + case HTT_DBG_STATS_RX_REMOTE_RING_BUFFER_INFO: + { + + struct rx_remote_buffer_mgmt_stats *rx_rem_buf; + + rx_rem_buf = (struct rx_remote_buffer_mgmt_stats *)(msg_word + 1); + htt_t2h_stats_rx_rem_buf_stats_print(rx_rem_buf, concise); + break; + } + case HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT: + { + struct rx_txbf_musu_ndpa_pkts_stats *rx_musu_ndpa_stats; + + rx_musu_ndpa_stats = (struct rx_txbf_musu_ndpa_pkts_stats *)(msg_word + 1); + htt_t2h_rx_musu_ndpa_pkts_stats_print(rx_musu_ndpa_stats, concise); + break; + } + default: + break; + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_h2t.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_h2t.c new file mode 100644 index 000000000000..c9dfe099add3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_h2t.c @@ -0,0 +1,990 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_h2t.c + * @brief Provide functions to send host->target HTT messages. + * @details + * This file contains functions related to host->target HTT messages. + * There are a couple aspects of this host->target messaging: + * 1. This file contains the function that is called by HTC when + * a host->target send completes. + * This send-completion callback is primarily relevant to HL, + * to invoke the download scheduler to set up a new download, + * and optionally free the tx frame whose download is completed. + * For both HL and LL, this completion callback frees up the + * HTC_PACKET object used to specify the download. + * 2. This file contains functions for creating messages to send + * from the host to the target. + */ + +#include /* adf_os_mem_copy */ +#include /* adf_nbuf_map_single */ +#include /* HTC_PACKET */ +#include /* HTC_HDR_ALIGNMENT_PADDING */ +#include /* HTT host->target msg defs */ +#include /* ol_tx_completion_handler, htt_tx_status */ +#include + + +#include + +#define HTT_MSG_BUF_SIZE(msg_bytes) \ + ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING) + +#ifndef container_of +#define container_of(ptr, type, member) ((type *)( \ + (char *)(ptr) - (char *)(&((type *)0)->member) ) ) +#endif + +#ifdef FEATURE_RUNTIME_PM +void +htt_tx_resume_handler(void *context) +{ + struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; + + htt_tx_sched(pdev); +} +#else +void +htt_tx_resume_handler(void *context) { } +#endif + +static void +htt_h2t_send_complete_free_netbuf( + void *pdev, A_STATUS status, adf_nbuf_t netbuf, u_int16_t msdu_id) +{ + adf_nbuf_free(netbuf); +} + +void +htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt) +{ + void (*send_complete_part2)( + void *pdev, A_STATUS status, adf_nbuf_t msdu, u_int16_t msdu_id); + struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; + struct htt_htc_pkt *htt_pkt; + adf_nbuf_t netbuf; + + send_complete_part2 = htc_pkt->pPktContext; + + htt_pkt = container_of(htc_pkt, struct htt_htc_pkt, htc_pkt); + + /* process (free or keep) the netbuf that held the message */ + netbuf = (adf_nbuf_t) htc_pkt->pNetBufContext; + if (send_complete_part2 != NULL) { + send_complete_part2( + htt_pkt->pdev_ctxt, htc_pkt->Status, netbuf, htt_pkt->msdu_id); + } + + if (pdev->cfg.is_high_latency && !pdev->cfg.default_tx_comp_req) { + int32_t credit_delta; + adf_os_atomic_add(1, &pdev->htt_tx_credit.bus_delta); + credit_delta = htt_tx_credit_update(pdev); + if (credit_delta) { + ol_tx_credit_completion_handler(pdev->txrx_pdev, credit_delta); + } + } + + /* free the htt_htc_pkt / HTC_PACKET object */ + htt_htc_pkt_free(pdev, htt_pkt); +} + +HTC_SEND_FULL_ACTION +htt_h2t_full(void *context, HTC_PACKET *pkt) +{ +/* FIX THIS */ + return HTC_SEND_FULL_KEEP; +} + +A_STATUS +htt_h2t_ver_req_msg(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + u_int32_t msg_size; + u_int32_t max_tx_group; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_ERROR; /* failure */ + } + + max_tx_group = OL_TX_GET_MAX_GROUPS(pdev->txrx_pdev); + + if (max_tx_group) { + msg_size = HTT_VER_REQ_BYTES + + sizeof(struct htt_option_tlv_mac_tx_queue_groups_t); + } else { + msg_size = HTT_VER_REQ_BYTES; + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(msg_size), + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_ERROR; /* failure */ + } + + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to adf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + adf_nbuf_put_tail(msg, msg_size); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ); + + if (max_tx_group) { + *(msg_word + 1) = 0; + /* Fill Group Info */ + HTT_OPTION_TLV_TAG_SET(*(msg_word+1), + HTT_OPTION_TLV_TAG_MAX_TX_QUEUE_GROUPS); + HTT_OPTION_TLV_LENGTH_SET(*(msg_word+1), + (sizeof(struct htt_option_tlv_mac_tx_queue_groups_t)/ + sizeof(u_int32_t))); + HTT_OPTION_TLV_VALUE0_SET(*(msg_word+1), max_tx_group); + } + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) { + htt_htc_misc_pkt_list_add(pdev, pkt); + } +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + if ((pdev->cfg.is_high_latency) && + (!pdev->cfg.default_tx_comp_req)) { + ol_tx_target_credit_update(pdev->txrx_pdev, -1); + } + return A_OK; +} + +A_STATUS +htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + int enable_ctrl_data, enable_mgmt_data, + enable_null_data, enable_phy_data, enable_hdr, + enable_ppdu_start, enable_ppdu_end; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_ERROR; /* failure */ + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_RX_RING_CFG_BYTES(1)), + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_ERROR; /* failure */ + } + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to adf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + adf_nbuf_put_tail(msg, HTT_RX_RING_CFG_BYTES(1)); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_CFG); + HTT_RX_RING_CFG_NUM_RINGS_SET(*msg_word, 1); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_SET( + *msg_word, pdev->rx_ring.alloc_idx.paddr); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_BASE_PADDR_SET(*msg_word, pdev->rx_ring.base_paddr); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_LEN_SET(*msg_word, pdev->rx_ring.size); + HTT_RX_RING_CFG_BUF_SZ_SET(*msg_word, HTT_RX_BUF_SIZE); + +/* FIX THIS: if the FW creates a complete translated rx descriptor, then the MAC DMA of the HW rx descriptor should be disabled. */ + msg_word++; + *msg_word = 0; +#ifndef REMOVE_PKT_LOG + if (ol_cfg_is_packet_log_enabled(pdev->ctrl_pdev)) + { + enable_ctrl_data = 1; + enable_mgmt_data = 1; + enable_null_data = 1; + enable_phy_data = 1; + enable_hdr = 1; + enable_ppdu_start= 1; + enable_ppdu_end = 1; + /* Disable ASPM when pkt log is enabled */ + adf_os_print("Pkt log is enabled\n"); + htt_htc_disable_aspm(); + } + else + { + adf_os_print("Pkt log is disabled\n"); + enable_ctrl_data = 0; + enable_mgmt_data = 0; + enable_null_data = 0; + enable_phy_data = 0; + enable_hdr = 0; + enable_ppdu_start= 0; + enable_ppdu_end = 0; + } +#else + enable_ctrl_data = 0; + enable_mgmt_data = 0; + enable_null_data = 0; + enable_phy_data = 0; + enable_hdr = 0; + enable_ppdu_start= 0; + enable_ppdu_end = 0; +#endif + HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(*msg_word, enable_hdr); + HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(*msg_word, enable_ppdu_start); + HTT_RX_RING_CFG_ENABLED_PPDU_END_SET(*msg_word, enable_ppdu_end); + HTT_RX_RING_CFG_ENABLED_MPDU_START_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_MPDU_END_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_MSDU_START_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_MSDU_END_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_RX_ATTN_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_FRAG_INFO_SET(*msg_word, 1); /* always present? */ + HTT_RX_RING_CFG_ENABLED_UCAST_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_MCAST_SET(*msg_word, 1); + /* Must change to dynamic enable at run time + * rather than at compile time + */ + HTT_RX_RING_CFG_ENABLED_CTRL_SET(*msg_word, enable_ctrl_data); + HTT_RX_RING_CFG_ENABLED_MGMT_SET(*msg_word, enable_mgmt_data); + HTT_RX_RING_CFG_ENABLED_NULL_SET(*msg_word, enable_null_data); + HTT_RX_RING_CFG_ENABLED_PHY_SET(*msg_word, enable_phy_data); + HTT_RX_RING_CFG_IDX_INIT_VAL_SET(*msg_word, + *pdev->rx_ring.alloc_idx.vaddr); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_802_11_HDR_SET(*msg_word, + RX_STD_DESC_HDR_STATUS_OFFSET_DWORD); + HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_SET(*msg_word, + HTT_RX_STD_DESC_RESERVATION_DWORD); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_PPDU_START_SET(*msg_word, + RX_STD_DESC_PPDU_START_OFFSET_DWORD); + HTT_RX_RING_CFG_OFFSET_PPDU_END_SET(*msg_word, + RX_STD_DESC_PPDU_END_OFFSET_DWORD); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_MPDU_START_SET(*msg_word, + RX_STD_DESC_MPDU_START_OFFSET_DWORD); + HTT_RX_RING_CFG_OFFSET_MPDU_END_SET(*msg_word, + RX_STD_DESC_MPDU_END_OFFSET_DWORD); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_MSDU_START_SET(*msg_word, + RX_STD_DESC_MSDU_START_OFFSET_DWORD); + HTT_RX_RING_CFG_OFFSET_MSDU_END_SET(*msg_word, + RX_STD_DESC_MSDU_END_OFFSET_DWORD); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_RX_ATTN_SET(*msg_word, + RX_STD_DESC_ATTN_OFFSET_DWORD); + HTT_RX_RING_CFG_OFFSET_FRAG_INFO_SET(*msg_word, + RX_STD_DESC_FRAG_INFO_OFFSET_DWORD); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + return A_OK; +} + +A_STATUS +htt_h2t_rx_ring_cfg_msg_hl(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_ERROR; /* failure */ + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_RX_RING_CFG_BYTES(1)), + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_ERROR; /* failure */ + } + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to adf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + adf_nbuf_put_tail(msg, HTT_RX_RING_CFG_BYTES(1)); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_CFG); + HTT_RX_RING_CFG_NUM_RINGS_SET(*msg_word, 1); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_SET( + *msg_word, pdev->rx_ring.alloc_idx.paddr); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_BASE_PADDR_SET(*msg_word, pdev->rx_ring.base_paddr); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_LEN_SET(*msg_word, pdev->rx_ring.size); + HTT_RX_RING_CFG_BUF_SZ_SET(*msg_word, HTT_RX_BUF_SIZE); + +/* FIX THIS: if the FW creates a complete translated rx descriptor, then the MAC DMA of the HW rx descriptor should be disabled. */ + msg_word++; + *msg_word = 0; + + HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_PPDU_END_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_MPDU_START_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_MPDU_END_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_MSDU_START_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_MSDU_END_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_RX_ATTN_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_FRAG_INFO_SET(*msg_word, 0); /* always present? */ + HTT_RX_RING_CFG_ENABLED_UCAST_SET(*msg_word, 1); + HTT_RX_RING_CFG_ENABLED_MCAST_SET(*msg_word, 1); + /* Must change to dynamic enable at run time + * rather than at compile time + */ + HTT_RX_RING_CFG_ENABLED_CTRL_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_MGMT_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_NULL_SET(*msg_word, 0); + HTT_RX_RING_CFG_ENABLED_PHY_SET(*msg_word, 0); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_802_11_HDR_SET(*msg_word, + 0); + HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_PPDU_START_SET(*msg_word, + 0); + HTT_RX_RING_CFG_OFFSET_PPDU_END_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_MPDU_START_SET(*msg_word, + 0); + HTT_RX_RING_CFG_OFFSET_MPDU_END_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_MSDU_START_SET(*msg_word, + 0); + HTT_RX_RING_CFG_OFFSET_MSDU_END_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_RX_ATTN_SET(*msg_word, + 0); + HTT_RX_RING_CFG_OFFSET_FRAG_INFO_SET(*msg_word, + 0); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) { + htt_htc_misc_pkt_list_add(pdev, pkt); + } +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + if (!pdev->cfg.default_tx_comp_req) { + ol_tx_target_credit_update(pdev->txrx_pdev, -1); + } + return A_OK; +} + +int +htt_h2t_dbg_stats_get( + struct htt_pdev_t *pdev, + u_int32_t stats_type_upload_mask, + u_int32_t stats_type_reset_mask, + u_int8_t cfg_stat_type, + u_int32_t cfg_val, + u_int64_t cookie) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + uint16_t htc_tag = 1; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return -1; /* failure */ + } + + if (stats_type_upload_mask >= 1 << HTT_DBG_NUM_STATS || + stats_type_reset_mask >= 1 << HTT_DBG_NUM_STATS) + { + /* FIX THIS - add more details? */ + adf_os_print("%#x %#x stats not supported\n", + stats_type_upload_mask, stats_type_reset_mask); + return -1; /* failure */ + } + + if (stats_type_reset_mask) + htc_tag = HTC_TX_PACKET_TAG_RUNTIME_PUT; + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_H2T_STATS_REQ_MSG_SZ), + /* reserve room for HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return -1; /* failure */ + } + /* set the length of the message */ + adf_nbuf_put_tail(msg, HTT_H2T_STATS_REQ_MSG_SZ); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_STATS_REQ); + HTT_H2T_STATS_REQ_UPLOAD_TYPES_SET(*msg_word, stats_type_upload_mask); + + msg_word++; + *msg_word = 0; + HTT_H2T_STATS_REQ_RESET_TYPES_SET(*msg_word, stats_type_reset_mask); + + msg_word++; + *msg_word = 0; + HTT_H2T_STATS_REQ_CFG_VAL_SET(*msg_word, cfg_val); + HTT_H2T_STATS_REQ_CFG_STAT_TYPE_SET(*msg_word, cfg_stat_type); + + /* cookie LSBs */ + msg_word++; + *msg_word = cookie & 0xffffffff; + + /* cookie MSBs */ + msg_word++; + *msg_word = cookie >> 32; + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + htc_tag); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) { + htt_htc_misc_pkt_list_add(pdev, pkt); + } +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + if ((pdev->cfg.is_high_latency) && + (!pdev->cfg.default_tx_comp_req)) { + ol_tx_target_credit_update(pdev->txrx_pdev, -1); + } + return 0; +} + +A_STATUS +htt_h2t_sync_msg(struct htt_pdev_t *pdev, u_int8_t sync_cnt) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_NO_MEMORY; + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_H2T_SYNC_MSG_SZ), + /* reserve room for HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_NO_MEMORY; + } + /* set the length of the message */ + adf_nbuf_put_tail(msg, HTT_H2T_SYNC_MSG_SZ); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SYNC); + HTT_H2T_SYNC_COUNT_SET(*msg_word, sync_cnt); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + if ((pdev->cfg.is_high_latency) && + (!pdev->cfg.default_tx_comp_req)) { + ol_tx_target_credit_update(pdev->txrx_pdev, -1); + } + return A_OK; +} + +int +htt_h2t_aggr_cfg_msg(struct htt_pdev_t *pdev, + int max_subfrms_ampdu, + int max_subfrms_amsdu) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return -1; /* failure */ + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_AGGR_CFG_MSG_SZ), + /* reserve room for HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return -1; /* failure */ + } + /* set the length of the message */ + adf_nbuf_put_tail(msg, HTT_AGGR_CFG_MSG_SZ); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_AGGR_CFG); + + if (max_subfrms_ampdu && (max_subfrms_ampdu <= 64)) { + HTT_AGGR_CFG_MAX_NUM_AMPDU_SUBFRM_SET(*msg_word, max_subfrms_ampdu); + } + + if (max_subfrms_amsdu && (max_subfrms_amsdu < 32)) { + HTT_AGGR_CFG_MAX_NUM_AMSDU_SUBFRM_SET(*msg_word, max_subfrms_amsdu); + } + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + if ((pdev->cfg.is_high_latency) && + (!pdev->cfg.default_tx_comp_req)) { + ol_tx_target_credit_update(pdev->txrx_pdev, -1); + } + return 0; +} + +#ifdef IPA_UC_OFFLOAD +int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_NO_MEMORY; + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_WDI_IPA_CFG_SZ), + /* reserve room for HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_NO_MEMORY; + } + /* set the length of the message */ + adf_nbuf_put_tail(msg, HTT_WDI_IPA_CFG_SZ); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_SET(*msg_word, + pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt); + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_WDI_IPA_CFG); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_SET(*msg_word, + (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_base.paddr); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_SET(*msg_word, + (unsigned int)ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev)); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_SET(*msg_word, + (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_idx_paddr); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_SET(*msg_word, + (unsigned int)pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_SET(*msg_word, + (unsigned int)pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_SET(*msg_word, + (unsigned int)ol_cfg_ipa_uc_rx_ind_ring_size(pdev->ctrl_pdev)); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_SET(*msg_word, + (unsigned int)pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_SET(*msg_word, + (unsigned int)pdev->ipa_uc_rx_rsc.rx_rdy_idx_paddr); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + + return A_OK; +} + + +int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, + a_bool_t uc_active, + a_bool_t is_tx) +{ + struct htt_htc_pkt *pkt; + adf_nbuf_t msg; + u_int32_t *msg_word; + u_int8_t active_target = 0; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_NO_MEMORY; + } + + /* show that this is not a tx frame download (not required, but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_WDI_IPA_OP_REQUEST_SZ), + /* reserve room for HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_NO_MEMORY; + } + /* set the length of the message */ + adf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + if (uc_active && is_tx) + { + active_target = HTT_WDI_IPA_OPCODE_TX_RESUME; + } + else if (!uc_active && is_tx) + { + active_target = HTT_WDI_IPA_OPCODE_TX_SUSPEND; + } + else if (uc_active && !is_tx) + { + active_target = HTT_WDI_IPA_OPCODE_RX_RESUME; + } + else if (!uc_active && !is_tx) + { + active_target = HTT_WDI_IPA_OPCODE_RX_SUSPEND; + } + HTT_WDI_IPA_OP_REQUEST_OP_CODE_SET(*msg_word, + active_target); + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_WDI_IPA_OP_REQ); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + + return A_OK; +} + + +int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt = NULL; + adf_nbuf_t msg = NULL; + u_int32_t *msg_word; + + /* New buffer alloc send */ + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return A_NO_MEMORY; + } + + /* show that this is not a tx frame download (not required, + * but helpful) */ + pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; + pkt->pdev_ctxt = NULL; /* not used during send-done callback */ + + msg = adf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_WDI_IPA_OP_REQUEST_SZ), + /* reserve room for HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return A_NO_MEMORY; + } + /* set the length of the message */ + adf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); + /* rewind beyond alignment pad to get to the HTC header reserved area */ + adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + /* fill in the message contents */ + msg_word = (u_int32_t *) adf_nbuf_data(msg); + *msg_word = 0; + HTT_WDI_IPA_OP_REQUEST_OP_CODE_SET(*msg_word, + HTT_WDI_IPA_OPCODE_DBG_STATS); + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_WDI_IPA_OP_REQ); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + adf_nbuf_data(msg), + adf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + +#ifdef ATH_11AC_TXCOMPACT + if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + return A_OK; +} +#endif /* IPA_UC_OFFLOAD */ + diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_internal.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_internal.h new file mode 100644 index 000000000000..5be1655bda81 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_internal.h @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2011, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _HTT_INTERNAL__H_ +#define _HTT_INTERNAL__H_ + +#include /* A_STATUS */ +#include /* adf_nbuf_t */ +#include /* adf_os_assert */ +#include /* HTC_PACKET */ + +#include + +#ifndef offsetof +#define offsetof(type, field) ((size_t)(&((type *)0)->field)) +#endif + +#undef MS +#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) +#undef SM +#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) +#undef WO +#define WO(_f) ((_f##_OFFSET) >> 2) + +#define GET_FIELD(_addr, _f) MS(*((A_UINT32 *)(_addr) + WO(_f)), _f) + +#include +#include /* struct rx_attention, etc */ + +struct htt_host_fw_desc_base { + union { + struct fw_rx_desc_base val; + A_UINT32 dummy_pad; /* make sure it is DOWRD aligned */ + } u; +}; + +/* + * This struct defines the basic descriptor information used by host, + * which is written either by the 11ac HW MAC into the host Rx data + * buffer ring directly or generated by FW and copied from Rx indication + */ +#define RX_HTT_HDR_STATUS_LEN 64 +struct htt_host_rx_desc_base { + struct htt_host_fw_desc_base fw_desc; + struct rx_attention attention; + struct rx_frag_info frag_info; + struct rx_mpdu_start mpdu_start; + struct rx_msdu_start msdu_start; + struct rx_msdu_end msdu_end; + struct rx_mpdu_end mpdu_end; + struct rx_ppdu_start ppdu_start; + struct rx_ppdu_end ppdu_end; + char rx_hdr_status[RX_HTT_HDR_STATUS_LEN]; +}; + +#define RX_STD_DESC_ATTN_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, attention)) +#define RX_STD_DESC_FRAG_INFO_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, frag_info)) +#define RX_STD_DESC_MPDU_START_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, mpdu_start)) +#define RX_STD_DESC_MSDU_START_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, msdu_start)) +#define RX_STD_DESC_MSDU_END_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, msdu_end)) +#define RX_STD_DESC_MPDU_END_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, mpdu_end)) +#define RX_STD_DESC_PPDU_START_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, ppdu_start)) +#define RX_STD_DESC_PPDU_END_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, ppdu_end)) +#define RX_STD_DESC_HDR_STATUS_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, rx_hdr_status)) + +#define RX_STD_DESC_FW_MSDU_OFFSET \ + (offsetof(struct htt_host_rx_desc_base, fw_desc)) + +#define RX_STD_DESC_SIZE (sizeof(struct htt_host_rx_desc_base)) + + +#define RX_STD_DESC_ATTN_OFFSET_DWORD (RX_STD_DESC_ATTN_OFFSET >> 2) +#define RX_STD_DESC_FRAG_INFO_OFFSET_DWORD (RX_STD_DESC_FRAG_INFO_OFFSET >> 2) +#define RX_STD_DESC_MPDU_START_OFFSET_DWORD (RX_STD_DESC_MPDU_START_OFFSET >> 2) +#define RX_STD_DESC_MSDU_START_OFFSET_DWORD (RX_STD_DESC_MSDU_START_OFFSET >> 2) +#define RX_STD_DESC_MSDU_END_OFFSET_DWORD (RX_STD_DESC_MSDU_END_OFFSET >> 2) +#define RX_STD_DESC_MPDU_END_OFFSET_DWORD (RX_STD_DESC_MPDU_END_OFFSET >> 2) +#define RX_STD_DESC_PPDU_START_OFFSET_DWORD (RX_STD_DESC_PPDU_START_OFFSET >> 2) +#define RX_STD_DESC_PPDU_END_OFFSET_DWORD (RX_STD_DESC_PPDU_END_OFFSET >> 2) +#define RX_STD_DESC_HDR_STATUS_OFFSET_DWORD (RX_STD_DESC_HDR_STATUS_OFFSET >> 2) + +#define RX_STD_DESC_SIZE_DWORD (RX_STD_DESC_SIZE >> 2) + +/* + * Make sure there is a minimum headroom provided in the rx netbufs + * for use by the OS shim and OS and rx data consumers. + */ +#define HTT_RX_BUF_OS_MIN_HEADROOM 32 +#define HTT_RX_STD_DESC_RESERVATION \ + ((HTT_RX_BUF_OS_MIN_HEADROOM > RX_STD_DESC_SIZE) ? \ + HTT_RX_BUF_OS_MIN_HEADROOM : RX_STD_DESC_SIZE) +#define HTT_RX_STD_DESC_RESERVATION_DWORD \ + (HTT_RX_STD_DESC_RESERVATION >> 2) + +#define HTT_RX_DESC_ALIGN_MASK 7 /* 8-byte alignment */ +static inline +struct htt_host_rx_desc_base * +htt_rx_desc(adf_nbuf_t msdu) +{ + return + (struct htt_host_rx_desc_base *) + (((size_t) (adf_nbuf_head(msdu) + HTT_RX_DESC_ALIGN_MASK)) & + ~HTT_RX_DESC_ALIGN_MASK); +} + +static inline +void +htt_print_rx_desc(struct htt_host_rx_desc_base *rx_desc) +{ + adf_os_print("----------------------RX DESC----------------------------\n"); + adf_os_print("attention: %#010x\n", + (unsigned int)(*(u_int32_t *) &rx_desc->attention)); + adf_os_print("frag_info: %#010x\n", + (unsigned int)(*(u_int32_t *) &rx_desc->frag_info)); + adf_os_print("mpdu_start: %#010x %#010x %#010x\n", + (unsigned int)(((u_int32_t *) &rx_desc->mpdu_start)[0]), + (unsigned int)(((u_int32_t *) &rx_desc->mpdu_start)[1]), + (unsigned int)(((u_int32_t *) &rx_desc->mpdu_start)[2])); + adf_os_print("msdu_start: %#010x %#010x %#010x\n", + (unsigned int)(((u_int32_t *) &rx_desc->msdu_start)[0]), + (unsigned int)(((u_int32_t *) &rx_desc->msdu_start)[1]), + (unsigned int)(((u_int32_t *) &rx_desc->msdu_start)[2])); + adf_os_print("msdu_end: %#010x %#010x %#010x %#010x %#010x\n", + (unsigned int)(((u_int32_t *) &rx_desc->msdu_end)[0]), + (unsigned int)(((u_int32_t *) &rx_desc->msdu_end)[1]), + (unsigned int)(((u_int32_t *) &rx_desc->msdu_end)[2]), + (unsigned int)(((u_int32_t *) &rx_desc->msdu_end)[3]), + (unsigned int)(((u_int32_t *) &rx_desc->msdu_end)[4])); + adf_os_print("mpdu_end: %#010x\n", + (unsigned int)(*(u_int32_t *) &rx_desc->mpdu_end)); + adf_os_print("ppdu_start: " + "%#010x %#010x %#010x %#010x %#010x\n" + "%#010x %#010x %#010x %#010x %#010x\n", + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[0]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[1]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[2]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[3]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[4]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[5]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[6]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[7]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[8]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_start)[9])); + adf_os_print("ppdu_end:" + "%#010x %#010x %#010x %#010x %#010x\n" + "%#010x %#010x %#010x %#010x %#010x\n" + "%#010x,%#010x %#010x %#010x %#010x\n" + "%#010x %#010x %#010x %#010x %#010x\n" + "%#010x %#010x\n", + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[0]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[1]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[2]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[3]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[4]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[5]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[6]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[7]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[8]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[9]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[10]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[11]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[12]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[13]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[14]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[15]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[16]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[17]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[18]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[19]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[20]), + (unsigned int)(((u_int32_t *) &rx_desc->ppdu_end)[21])); + adf_os_print("---------------------------------------------------------\n"); +} + + +#ifndef HTT_ASSERT_LEVEL +#define HTT_ASSERT_LEVEL 3 +#endif + +#define HTT_ASSERT_ALWAYS(condition) adf_os_assert_always((condition)) + +#define HTT_ASSERT0(condition) adf_os_assert((condition)) +#if HTT_ASSERT_LEVEL > 0 +#define HTT_ASSERT1(condition) adf_os_assert((condition)) +#else +#define HTT_ASSERT1(condition) +#endif + +#if HTT_ASSERT_LEVEL > 1 +#define HTT_ASSERT2(condition) adf_os_assert((condition)) +#else +#define HTT_ASSERT2(condition) +#endif + +#if HTT_ASSERT_LEVEL > 2 +#define HTT_ASSERT3(condition) adf_os_assert((condition)) +#else +#define HTT_ASSERT3(condition) +#endif + + +#define HTT_MAC_ADDR_LEN 6 + + +/* + * HTT_MAX_SEND_QUEUE_DEPTH - + * How many packets HTC should allow to accumulate in a send queue + * before calling the EpSendFull callback to see whether to retain + * or drop packets. + * This is not relevant for LL, where tx descriptors should be immediately + * downloaded to the target. + * This is not very relevant for HL either, since it is anticipated that + * the HL tx download scheduler will not work this far in advance - rather, + * it will make its decisions just-in-time, so it can be responsive to + * changing conditions. + * Hence, this queue depth threshold spec is mostly just a formality. + */ +#define HTT_MAX_SEND_QUEUE_DEPTH 64 + + +#define IS_PWR2(value) (((value) ^ ((value)-1)) == ((value) << 1) - 1) + + +/* FIX THIS + * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size, + * rounded up to a cache line size. + */ +#define HTT_RX_BUF_SIZE 1920 +/* + * DMA_MAP expects the buffer to be an integral number of cache lines. + * Rather than checking the actual cache line size, this code makes a + * conservative estimate of what the cache line size could be. + */ +#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */ +#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1) + +#ifdef BIG_ENDIAN_HOST +/* + * big-endian: bytes within a 4-byte "word" are swapped: + * pre-swap post-swap + * index index + * 0 3 + * 1 2 + * 2 1 + * 3 0 + * 4 7 + * 5 6 + * etc. + * To compute the post-swap index from the pre-swap index, compute + * the byte offset for the start of the word (index & ~0x3) and add + * the swapped byte offset within the word (3 - (index & 0x3)). + */ +#define HTT_ENDIAN_BYTE_IDX_SWAP(idx) (((idx) & ~0x3) + (3 - ((idx) & 0x3))) +#else +/* little-endian: no adjustment needed */ +#define HTT_ENDIAN_BYTE_IDX_SWAP(idx) idx +#endif + + +#define HTT_TX_MUTEX_INIT(_mutex) \ + adf_os_spinlock_init(_mutex) + +#define HTT_TX_MUTEX_ACQUIRE(_mutex) \ + adf_os_spin_lock_bh(_mutex) + +#define HTT_TX_MUTEX_RELEASE(_mutex) \ + adf_os_spin_unlock_bh(_mutex) + +#define HTT_TX_MUTEX_DESTROY(_mutex) \ + adf_os_spinlock_destroy(_mutex) + +#define HTT_TX_DESC_PADDR(_pdev, _tx_desc_vaddr) \ + ((_pdev)->tx_descs.pool_paddr + (u_int32_t) \ + ((char *)(_tx_desc_vaddr) - \ + (char *)((_pdev)->tx_descs.pool_vaddr))) + +#ifdef ATH_11AC_TXCOMPACT + +#define HTT_TX_NBUF_QUEUE_MUTEX_INIT(_pdev) \ + adf_os_spinlock_init(&_pdev->txnbufq_mutex) + +#define HTT_TX_NBUF_QUEUE_MUTEX_DESTROY(_pdev) \ + HTT_TX_MUTEX_DESTROY(&_pdev->txnbufq_mutex) + +#define HTT_TX_NBUF_QUEUE_REMOVE(_pdev, _msdu) \ + HTT_TX_MUTEX_ACQUIRE(&_pdev->txnbufq_mutex); \ + _msdu = adf_nbuf_queue_remove(&_pdev->txnbufq);\ + HTT_TX_MUTEX_RELEASE(&_pdev->txnbufq_mutex) + +#define HTT_TX_NBUF_QUEUE_ADD(_pdev, _msdu) \ + HTT_TX_MUTEX_ACQUIRE(&_pdev->txnbufq_mutex); \ + adf_nbuf_queue_add(&_pdev->txnbufq, _msdu);\ + HTT_TX_MUTEX_RELEASE(&_pdev->txnbufq_mutex) + +#define HTT_TX_NBUF_QUEUE_INSERT_HEAD(_pdev, _msdu) \ + HTT_TX_MUTEX_ACQUIRE(&_pdev->txnbufq_mutex); \ + adf_nbuf_queue_insert_head(&_pdev->txnbufq, _msdu);\ + HTT_TX_MUTEX_RELEASE(&_pdev->txnbufq_mutex) +#else + +#define HTT_TX_NBUF_QUEUE_MUTEX_INIT(_pdev) +#define HTT_TX_NBUF_QUEUE_REMOVE(_pdev, _msdu) +#define HTT_TX_NBUF_QUEUE_ADD(_pdev, _msdu) +#define HTT_TX_NBUF_QUEUE_INSERT_HEAD(_pdev, _msdu) +#define HTT_TX_NBUF_QUEUE_MUTEX_DESTROY(_pdev) + +#endif + +#ifdef ATH_11AC_TXCOMPACT +#define HTT_TX_SCHED htt_tx_sched +#else +#define HTT_TX_SCHED(pdev) /* no-op */ +#endif + +int +htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems); + +void +htt_tx_detach(struct htt_pdev_t *pdev); + +int +htt_rx_attach(struct htt_pdev_t *pdev); + +void +htt_rx_detach(struct htt_pdev_t *pdev); + +int +htt_htc_attach(struct htt_pdev_t *pdev); + +void +htt_t2h_msg_handler(void *context, HTC_PACKET *pkt); + +void +htt_tx_resume_handler(void *); + +void +htt_h2t_send_complete(void *context, HTC_PACKET *pkt); + +A_STATUS +htt_h2t_ver_req_msg(struct htt_pdev_t *pdev); + +extern A_STATUS (*htt_h2t_rx_ring_cfg_msg)( + struct htt_pdev_t *pdev); + +HTC_SEND_FULL_ACTION +htt_h2t_full(void *context, HTC_PACKET *pkt); + +struct htt_htc_pkt * +htt_htc_pkt_alloc(struct htt_pdev_t *pdev); + +void +htt_htc_pkt_free(struct htt_pdev_t *pdev, struct htt_htc_pkt *pkt); + +void +htt_htc_pkt_pool_free(struct htt_pdev_t *pdev); + +#ifdef ATH_11AC_TXCOMPACT +void +htt_htc_misc_pkt_list_add(struct htt_pdev_t *pdev, struct htt_htc_pkt *pkt); + +void +htt_htc_misc_pkt_pool_free(struct htt_pdev_t *pdev); +#endif + +void htt_htc_disable_aspm(void); + +int +htt_rx_hash_list_insert(struct htt_pdev_t *pdev, u_int32_t paddr, + adf_nbuf_t netbuf); + +adf_nbuf_t +htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, u_int32_t paddr); + +#ifdef IPA_UC_OFFLOAD +int +htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, + unsigned int uc_tx_buf_sz, + unsigned int uc_tx_buf_cnt, + unsigned int uc_tx_partition_base); + +int +htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, + unsigned int rx_ind_ring_size); + +int +htt_tx_ipa_uc_detach(struct htt_pdev_t *pdev); + +int +htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev); +#endif /* IPA_UC_OFFLOAD */ + +/* Maximum Outstanding Bus Download */ +#define HTT_MAX_BUS_CREDIT 33 + +int +htt_tx_credit_update(struct htt_pdev_t *pdev); + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +#define HTT_TX_GROUP_INDEX_OFFSET \ + (sizeof(struct htt_txq_group) / sizeof(u_int32_t)) +void htt_tx_group_credit_process(struct htt_pdev_t *pdev, u_int32_t *msg_word); +#define HTT_TX_GROUP_CREDIT_PROCESS htt_tx_group_credit_process +#else +#define HTT_TX_GROUP_CREDIT_PROCESS(pdev, msg_word) /* no-op */ +#endif + +#endif /* _HTT_INTERNAL__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_isoc.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_isoc.h new file mode 100644 index 000000000000..3285a844cfd9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_isoc.h @@ -0,0 +1,1101 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_isoc.h + * + * @details + * This file defines the target --> host messages that configure the + * host data-path SW with the information required for data transfers + * to and from the target. + */ + +#ifndef _HTT_ISOC_H_ +#define _HTT_ISOC_H_ + +#include /* A_UINT32, A_UINT8 */ + +#ifdef ATHR_WIN_NWF +#pragma warning( disable:4214 ) //bit field types other than int +#endif + +#include "htt_common.h" + +/*=== definitions that apply to all messages ================================*/ + +typedef enum htt_isoc_t2h_msg_type { + /* 0x0 reserved for VERSION message (probably not needed) */ + + /* PEER_INFO - specify ID and parameters of a new peer */ + HTT_ISOC_T2H_MSG_TYPE_PEER_INFO = 0x1, + + /* PEER_UNMAP - deallocate the ID that refers to a peer */ + HTT_ISOC_T2H_MSG_TYPE_PEER_UNMAP = 0x2, + + /* ADDBA - start rx aggregation for the specified peer-TID */ + HTT_ISOC_T2H_MSG_TYPE_RX_ADDBA = 0x3, + + /* DELBA - stop rx aggregation for the specified peer-TID */ + HTT_ISOC_T2H_MSG_TYPE_RX_DELBA = 0x4, + + /* TX_COMPL_IND - over-the-air tx completion notification for a tx frame */ + HTT_ISOC_T2H_MSG_TYPE_TX_COMPL_IND = 0x5, + + /* SEC_IND - notification of the type of security used for a new peer */ + HTT_ISOC_T2H_MSG_TYPE_SEC_IND = 0x6, + + /* PEER_TX_READY - the target is ready to transmit to a new peer */ + HTT_ISOC_T2H_MSG_TYPE_PEER_TX_READY = 0x7, + + /* RX_ERR - notification that an rx frame was discarded due to errors */ + HTT_ISOC_T2H_MSG_TYPE_RX_ERR = 0x8, + + + /* keep this last */ + HTT_ISOC_T2H_NUM_MSGS +} htt_isoc_t2h_msg_type; + +/* + * HTT ISOC target to host message type - + * stored in bits 7:0 of the first word of the message + */ +#define HTT_ISOC_T2H_MSG_TYPE_M 0xff +#define HTT_ISOC_T2H_MSG_TYPE_S 0 + +#define HTT_ISOC_T2H_MSG_TYPE_SET(msg_addr, msg_type) \ + (*((A_UINT8 *) msg_addr) = (msg_type)) +#define HTT_ISOC_T2H_MSG_TYPE_GET(msg_addr) \ + (*((A_UINT8 *) msg_addr)) + +#ifndef INLINE +/* target FW */ +#define INLINE __inline +#define HTT_ISOC_INLINE_DEF +#endif /* INLINE */ + +static INLINE void +htt_isoc_t2h_field_set( + A_UINT32 *msg_addr32, + unsigned offset32, + unsigned mask, + unsigned shift, + unsigned value) +{ + /* sanity check: make sure the value fits within the field */ + //adf_os_assert(value << shift == (value << shift) | mask); + + msg_addr32 += offset32; + /* clear the field */ + *msg_addr32 &= ~mask; + /* write the new value */ + *msg_addr32 |= (value << shift); +} + +#ifdef HTT_ISOC_INLINE_DEF +#undef HTT_ISOC_INLINE_DEF +#undef INLINE +#endif + +#define HTT_ISOC_T2H_FIELD_GET(msg_addr32, offset32, mask, shift) \ + (((*(msg_addr32 + offset32)) & mask) >> shift) + +typedef enum { + /* ASSOC - "real" peer from STA-AP association */ + HTT_ISOC_T2H_PEER_TYPE_ASSOC = 0x0, + + /* SELF - self-peer for unicast tx to unassociated peer */ + HTT_ISOC_T2H_PEER_TYPE_SELF = 0x1, + + /* BSSID - reserved for FW use for BT-AMP+IBSS */ + HTT_ISOC_T2H_PEER_TYPE_BSSID = 0x2, + + /* BCAST - self-peer for multicast / broadcast tx */ + HTT_ISOC_T2H_PEER_TYPE_BCAST = 0x3 +} HTT_ISOC_T2H_PEER_TYPE_ENUM; + +enum { + HTT_ISOC_NON_QOS = 0, + HTT_ISOC_QOS = 1 +}; + +enum { + HTT_ISOC_RMF_DISABLED = 0, + HTT_ISOC_RMF_ENABLED = 1 +}; + +enum { + HTT_ISOC_TID_MGMT = 7 +}; + + +/*=== definitions for specific messages =====================================*/ + +/*=== PEER_INFO message ===*/ + +/** + * @brief target -> host peer info message definition + * + * @details + * The following diagram shows the format of the peer info message sent + * from the target to the host. This layout assumes the target operates + * as little-endian. + * + * |31 25|24|23 18|17|16|15 11|10|9|8|7|6| 0| + * |-----------------------------------------------------------------------| + * | mgmt DPU idx | bcast DPU idx | DPU idx | msg type | + * |-----------------------------------------------------------------------| + * | mgmt DPU sig |bcast DPU sig | DPU sig | peer ID | + * |-----------------------------------------------------------------------| + * | MAC addr 1 | MAC addr 0 | vdev ID | |R| peer type | + * |-----------------------------------------------------------------------| + * | MAC addr 5 | MAC addr 4 | MAC addr 3 | MAC addr 2 | + * |-----------------------------------------------------------------------| + * + * + * The following field definitions describe the format of the peer info + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as peer info message + * Value: 0x1 + * - DPU_IDX + * Bits 15:8 + * Purpose: specify the DPU index (a.k.a. security key ID) to use for + * unicast data frames sent to this peer + * Value: key ID + * - BCAST_DPU_IDX + * Bits 23:16 + * Purpose: specify the DPU index (a.k.a. security key ID) to use for + * broadcast data frames sent by this (self) peer + * Value: key ID + * - MGMT_DPU_IDX + * Bits 31:24 + * Purpose: specify the DPU index (a.k.a. security key ID) to use for + * unicast management frames sent by this (self) peer + * Value: key ID + * WORD 1: + * - PEER_ID + * Bits 10:0 + * Purpose: The ID that the target has allocated to refer to the peer + * - DPU_SIG + * Bits 17:11 + * Purpose: specify the DPU signature (a.k.a. security key validity + * magic number) to specify for unicast data frames sent to this peer + * - BCAST_DPU_SIG + * Bits 24:18 + * Purpose: specify the DPU signature (a.k.a. security key validity + * magic number) to specify for broadcast data frames sent by this + * (self) peer + * - MGMT_DPU_SIG + * Bits 31:25 + * Purpose: specify the DPU signature (a.k.a. security key validity + * magic number) to specify for unicast management frames sent by this + * (self) peer + * WORD 2: + * - PEER_TYPE + * Bits 5:0 + * Purpose: specify whether the peer in question is a real peer or + * one of the types of "self-peer" created for the vdev + * Value: HTT_ISOC_T2H_PEER_TYPE enum + * - RMF_ENABLED (R) + * Bit 6 + * Purpose: specify whether the peer in question has enable robust + * management frames, to encrypt certain managment frames + * Value: HTT_ISOC_RMF enum + * Value: HTT_ISOC_NON_QOS or HTT_ISOC_QOS + * - VDEV_ID + * Bits 15:8 + * Purpose: For a real peer, the vdev ID indicates which virtual device + * the peer is associated with. For a self-peer, the vdev ID shows + * which virtual device the self-peer represents. + * - MAC_ADDR_L16 + * Bits 31:16 + * Purpose: Identifies which peer the peer ID is for. + * Value: lower 2 bytes of the peer's MAC address + * For a self-peer, the peer's MAC address is the MAC address of the + * vdev the self-peer represents. + * WORD 3: + * - MAC_ADDR_U32 + * Bits 31:0 + * Purpose: Identifies which peer the peer ID is for. + * Value: upper 4 bytes of the peer's MAC address + * For a self-peer, the peer's MAC address is the MAC address of the + * vdev the self-peer represents. + */ +typedef struct htt_isoc_t2h_peer_info_s { + /* word 0 */ + A_UINT32 + msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_PEER_INFO */ + dpu_idx: 8, + bcast_dpu_idx: 8, + mgmt_dpu_idx: 8; + /* word 1 */ + A_UINT32 + peer_id: 11, + dpu_sig: 7, + bcast_dpu_sig: 7, + mgmt_dpu_sig: 7; + /* word 2 */ + A_UINT32 + peer_type: 6, + rmf_enabled: 1, + reserved0: 1, + vdev_id: 8, + mac_addr_l16: 16; + /* word 3 */ + A_UINT32 mac_addr_u32; +} htt_isoc_t2h_peer_info_t; + +/* word 0 */ +#define HTT_ISOC_T2H_PEER_INFO_DPU_IDX_OFFSET32 0 +#define HTT_ISOC_T2H_PEER_INFO_DPU_IDX_M 0x0000ff00 +#define HTT_ISOC_T2H_PEER_INFO_DPU_IDX_S 8 + +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_IDX_OFFSET32 0 +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_IDX_M 0x00ff0000 +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_IDX_S 16 + +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_IDX_OFFSET32 0 +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_IDX_M 0xff000000 +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_IDX_S 24 + +/* word 1 */ +#define HTT_ISOC_T2H_PEER_INFO_PEER_ID_OFFSET32 1 +#define HTT_ISOC_T2H_PEER_INFO_PEER_ID_M 0x000007ff +#define HTT_ISOC_T2H_PEER_INFO_PEER_ID_S 0 + +#define HTT_ISOC_T2H_PEER_INFO_DPU_SIG_OFFSET32 1 +#define HTT_ISOC_T2H_PEER_INFO_DPU_SIG_M 0x0003f800 +#define HTT_ISOC_T2H_PEER_INFO_DPU_SIG_S 11 + +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_SIG_OFFSET32 1 +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_SIG_M 0x01fc0000 +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_SIG_S 18 + +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_SIG_OFFSET32 1 +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_SIG_M 0xfe000000 +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_SIG_S 25 + +/* word 2 */ +#define HTT_ISOC_T2H_PEER_INFO_PEER_TYPE_OFFSET32 2 +#define HTT_ISOC_T2H_PEER_INFO_PEER_TYPE_M 0x0000003f +#define HTT_ISOC_T2H_PEER_INFO_PEER_TYPE_S 0 + +#define HTT_ISOC_T2H_PEER_INFO_RMF_ENABLED_OFFSET32 2 +#define HTT_ISOC_T2H_PEER_INFO_RMF_ENABLED_M 0x00000040 +#define HTT_ISOC_T2H_PEER_INFO_RMF_ENABLED_S 6 + +#define HTT_ISOC_T2H_PEER_INFO_VDEV_ID_OFFSET32 2 +#define HTT_ISOC_T2H_PEER_INFO_VDEV_ID_M 0x0000ff00 +#define HTT_ISOC_T2H_PEER_INFO_VDEV_ID_S 8 + +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_OFFSET32 2 +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_M 0xffff0000 +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_S 16 + +/* word 3 */ +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_U32_OFFSET32 3 +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_U32_M 0xffffffff +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_U32_S 0 + + +/* general field access macros */ + +#define HTT_ISOC_T2H_PEER_INFO_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_PEER_INFO_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_PEER_INFO_ ## field ## _M, \ + HTT_ISOC_T2H_PEER_INFO_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_PEER_INFO_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_PEER_INFO_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_PEER_INFO_ ## field ## _M, \ + HTT_ISOC_T2H_PEER_INFO_ ## field ## _S) + +/* access macros for specific fields */ + +#define HTT_ISOC_T2H_PEER_INFO_DPU_IDX_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(DPU_IDX, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_DPU_IDX_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(DPU_IDX, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_IDX_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(BCAST_DPU_IDX, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_IDX_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(BCAST_DPU_IDX, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_IDX_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(MGMT_DPU_IDX, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_IDX_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(MGMT_DPU_IDX, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(PEER_ID, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_DPU_SIG_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(DPU_SIG, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_DPU_SIG_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(DPU_SIG, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_SIG_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(BCAST_DPU_SIG, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_BCAST_DPU_SIG_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(BCAST_DPU_SIG, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_SIG_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(MGMT_DPU_SIG, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_MGMT_DPU_SIG_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(MGMT_DPU_SIG, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_PEER_TYPE_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(PEER_TYPE, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_PEER_TYPE_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(PEER_TYPE, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_QOS_CAPABLE_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(QOS_CAPABLE, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_QOS_CAPABLE_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(QOS_CAPABLE, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_RMF_ENABLED_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(RMF_ENABLED, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_RMF_ENABLED_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(RMF_ENABLED, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_VDEV_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(VDEV_ID, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_VDEV_ID_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(VDEV_ID, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(MAC_ADDR_L16, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_L16_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(MAC_ADDR_L16, msg_addr) + +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_U32_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_SET(MAC_ADDR_U32, msg_addr, value) +#define HTT_ISOC_T2H_PEER_INFO_MAC_ADDR_U32_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_INFO_FIELD_GET(MAC_ADDR_U32, msg_addr) + +/*=== PEER_UNMAP message ===*/ + +/** + * @brief target -> host peer unmap message definition + * + * @details + * The following diagram shows the format of the peer unmap message sent + * from the target to the host. This layout assumes the target operates + * as little-endian. + * + * |31 19|18 8|7 0| + * |-----------------------------------------------------------------------| + * | reserved | peer ID | msg type | + * |-----------------------------------------------------------------------| + * + * + * The following field definitions describe the format of the peer info + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as peer unmap message + * Value: 0x2 + * - PEER_ID + * Bits 18:8 + * Purpose: The ID that the target has allocated to refer to the peer + */ +typedef struct htt_isoc_t2h_peer_unmap_s { + /* word 0 */ + A_UINT32 + msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_PEER_UNMAP */ + peer_id: 11, + reserved0: 13; +} htt_isoc_t2h_peer_unmap_t; + +/* word 0 */ +#define HTT_ISOC_T2H_PEER_UNMAP_PEER_ID_OFFSET32 0 +#define HTT_ISOC_T2H_PEER_UNMAP_PEER_ID_M 0x0007ff00 +#define HTT_ISOC_T2H_PEER_UNMAP_PEER_ID_S 8 + + +/* general field access macros */ + +#define HTT_ISOC_T2H_PEER_UNMAP_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_PEER_UNMAP_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_PEER_UNMAP_ ## field ## _M, \ + HTT_ISOC_T2H_PEER_UNMAP_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_PEER_UNMAP_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_PEER_UNMAP_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_PEER_UNMAP_ ## field ## _M, \ + HTT_ISOC_T2H_PEER_UNMAP_ ## field ## _S) + +/* access macros for specific fields */ + +#define HTT_ISOC_T2H_PEER_UNMAP_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_UNMAP_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_PEER_UNMAP_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_UNMAP_FIELD_GET(PEER_ID, msg_addr) + +/*=== ADDBA message ===*/ +enum { + htt_isoc_addba_success = 0, + /* TBD: use different failure values to specify failure causes? */ + htt_isoc_addba_fail = 1, +}; + +/** + * @brief target -> host ADDBA message definition + * + * @details + * The following diagram shows the format of the rx ADDBA message sent + * from the target to the host: + * + * |31 20|19 16|15 12|11 8|7 0| + * |---------------------------------------------------------------------| + * | peer ID | TID | window size | msg type | + * |---------------------------------------------------------------------| + * | reserved |S| start seq num | + * |---------------------------------------------------------------------| + * + * The following field definitions describe the format of the ADDBA + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an ADDBA message + * Value: 0x3 + * - WIN_SIZE + * Bits 15:8 + * Purpose: Specifies the length of the block ack window (max = 64). + * Value: + * block ack window length specified by the received ADDBA + * management message. + * - TID + * Bits 19:16 + * Purpose: Specifies which traffic identifier the ADDBA is for. + * Value: + * TID specified by the received ADDBA management message. + * - PEER_ID + * Bits 31:20 + * Purpose: Identifies which peer sent the ADDBA. + * Value: + * ID (hash value) used by the host for fast, direct lookup of + * host SW peer info, including rx reorder states. + * - START_SEQ_NUM + * Bits 11:0 + * Purpose: Specifies the initial location of the block ack window + * Value: start sequence value specified by the ADDBA-request message + * - STATUS + * Bit 12 + * Purpose: status of the WMI ADDBA request + * Value: 0 - SUCCESS, 1 - FAILURE + */ +typedef struct htt_isoc_t2h_addba_s { + /* word 0 */ + A_UINT32 msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_ADDBA */ + win_size: 8, + tid: 4, + peer_id: 12; + /* word 1 */ + A_UINT32 start_seq_num: 12, + status: 1, + reserved0: 19; +} htt_isoc_t2h_addba_t; + +/* word 0 */ +#define HTT_ISOC_T2H_ADDBA_WIN_SIZE_OFFSET32 0 +#define HTT_ISOC_T2H_ADDBA_WIN_SIZE_M 0x0000ff00 +#define HTT_ISOC_T2H_ADDBA_WIN_SIZE_S 8 + +#define HTT_ISOC_T2H_ADDBA_TID_OFFSET32 0 +#define HTT_ISOC_T2H_ADDBA_TID_M 0x000f0000 +#define HTT_ISOC_T2H_ADDBA_TID_S 16 + +#define HTT_ISOC_T2H_ADDBA_PEER_ID_OFFSET32 0 +#define HTT_ISOC_T2H_ADDBA_PEER_ID_M 0xfff00000 +#define HTT_ISOC_T2H_ADDBA_PEER_ID_S 20 + +/* word 1 */ +#define HTT_ISOC_T2H_ADDBA_START_SEQ_NUM_OFFSET32 1 +#define HTT_ISOC_T2H_ADDBA_START_SEQ_NUM_M 0x00000fff +#define HTT_ISOC_T2H_ADDBA_START_SEQ_NUM_S 0 + +#define HTT_ISOC_T2H_ADDBA_STATUS_OFFSET32 1 +#define HTT_ISOC_T2H_ADDBA_STATUS_M 0x00001000 +#define HTT_ISOC_T2H_ADDBA_STATUS_S 12 + +/* general field access macros */ +#define HTT_ISOC_T2H_ADDBA_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_ADDBA_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_ADDBA_ ## field ## _M, \ + HTT_ISOC_T2H_ADDBA_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_ADDBA_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_ADDBA_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_ADDBA_ ## field ## _M, \ + HTT_ISOC_T2H_ADDBA_ ## field ## _S) + +/* access macros for specific fields */ + +#define HTT_ISOC_T2H_ADDBA_WIN_SIZE_SET(msg_addr, value) \ + HTT_ISOC_T2H_ADDBA_FIELD_SET(WIN_SIZE, msg_addr, value) +#define HTT_ISOC_T2H_ADDBA_WIN_SIZE_GET(msg_addr) \ + HTT_ISOC_T2H_ADDBA_FIELD_GET(WIN_SIZE, msg_addr) + +#define HTT_ISOC_T2H_ADDBA_TID_SET(msg_addr, value) \ + HTT_ISOC_T2H_ADDBA_FIELD_SET(TID, msg_addr, value) +#define HTT_ISOC_T2H_ADDBA_TID_GET(msg_addr) \ + HTT_ISOC_T2H_ADDBA_FIELD_GET(TID, msg_addr) + +#define HTT_ISOC_T2H_ADDBA_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_ADDBA_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_ADDBA_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_ADDBA_FIELD_GET(PEER_ID, msg_addr) + +#define HTT_ISOC_T2H_ADDBA_START_SEQ_NUM_SET(msg_addr, value) \ + HTT_ISOC_T2H_ADDBA_FIELD_SET(START_SEQ_NUM, msg_addr, value) +#define HTT_ISOC_T2H_ADDBA_START_SEQ_NUM_GET(msg_addr) \ + HTT_ISOC_T2H_ADDBA_FIELD_GET(START_SEQ_NUM, msg_addr) + +#define HTT_ISOC_T2H_ADDBA_STATUS_SET(msg_addr, value) \ + HTT_ISOC_T2H_ADDBA_FIELD_SET(STATUS, msg_addr, value) +#define HTT_ISOC_T2H_ADDBA_STATUS_GET(msg_addr) \ + HTT_ISOC_T2H_ADDBA_FIELD_GET(STATUS, msg_addr) + +/*=== DELBA message ===*/ + +/** + * @brief target -> host DELBA message definition + * + * @details + * The following diagram shows the format of the rx DELBA message sent + * from the target to the host: + * + * |31 20|19 16|15 12|11 8|7 0| + * |---------------------------------------------------------------------| + * | peer ID | TID | reserved |S| msg type | + * |---------------------------------------------------------------------| + * + * The following field definitions describe the format of the ADDBA + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an DELBA message + * Value: 0x4 + * - TID + * Bits 19:16 + * Purpose: Specifies which traffic identifier the DELBA is for. + * Value: + * TID specified by the received DELBA management message. + * - PEER_ID + * Bits 31:20 + * Purpose: Identifies which peer sent the DELBA. + * Value: + * ID (hash value) used by the host for fast, direct lookup of + * host SW peer info, including rx reorder states. + * - STATUS + * Bit 8 + * Purpose: status of the WMI DELBA request + * Value: 0 - SUCCESS, 1 - FAILURE + */ +typedef struct htt_isoc_t2h_delba_s { + /* word 0 */ + A_UINT32 + msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_DELBA */ + status: 1, + reserved0: 7, + tid: 4, + peer_id: 12; +} htt_isoc_t2h_delba_t; + +/* word 0 */ +#define HTT_ISOC_T2H_DELBA_TID_OFFSET32 0 +#define HTT_ISOC_T2H_DELBA_TID_M 0x000f0000 +#define HTT_ISOC_T2H_DELBA_TID_S 16 + +#define HTT_ISOC_T2H_DELBA_PEER_ID_OFFSET32 0 +#define HTT_ISOC_T2H_DELBA_PEER_ID_M 0xfff00000 +#define HTT_ISOC_T2H_DELBA_PEER_ID_S 20 + +#define HTT_ISOC_T2H_DELBA_STATUS_OFFSET32 0 +#define HTT_ISOC_T2H_DELBA_STATUS_M 0x00000100 +#define HTT_ISOC_T2H_DELBA_STATUS_S 8 + +/* general field access macros */ + +#define HTT_ISOC_T2H_DELBA_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_DELBA_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_DELBA_ ## field ## _M, \ + HTT_ISOC_T2H_DELBA_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_DELBA_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_DELBA_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_DELBA_ ## field ## _M, \ + HTT_ISOC_T2H_DELBA_ ## field ## _S) + +/* access macros for specific fields */ + +#define HTT_ISOC_T2H_DELBA_TID_SET(msg_addr, value) \ + HTT_ISOC_T2H_DELBA_FIELD_SET(TID, msg_addr, value) +#define HTT_ISOC_T2H_DELBA_TID_GET(msg_addr) \ + HTT_ISOC_T2H_DELBA_FIELD_GET(TID, msg_addr) + +#define HTT_ISOC_T2H_DELBA_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_DELBA_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_DELBA_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_DELBA_FIELD_GET(PEER_ID, msg_addr) + +#define HTT_ISOC_T2H_DELBA_STATUS_SET(msg_addr, value) \ + HTT_ISOC_T2H_DELBA_FIELD_SET(STATUS, msg_addr, value) +#define HTT_ISOC_T2H_DELBA_STATUS_GET(msg_addr) \ + HTT_ISOC_T2H_DELBA_FIELD_GET(STATUS, msg_addr) + +/*=== SEC_IND message ===*/ + +/** + * @brief target -> host Security indication message definition + * + * @details + * The following diagram shows the format of the SEC_IND message sent + * from the target to the host. This layout assumes the target operates + * as little-endian. + * + * |31 25|24|23 18|17|16|15 11|10|9|8|7|6| 0| + * |-----------------------------------------------------------------------| + * | is unicast | sec type | Peer id | msg type | + * |-----------------------------------------------------------------------| + * | mic key1 | + * |-----------------------------------------------------------------------| + * | mic key2 | + * |-----------------------------------------------------------------------| + * + * + * The following field definitions describe the format of the peer info + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as SEC_IND message + * Value: 0x6 + * - PEER_ID + * Bits 15:8 + * Purpose: The ID that the target has allocated to refer to the peer + * Value: Peer ID + * - SEC_TYPE + * Bits 23:16 + * Purpose: specify the security encryption type + * Value: htt_sec_type + * - is unicast + * Bits 31:24 + * Purpose: specify unicast/bcast + * Value: 1-unicast/0-bcast + * WORD 1: + * - MIC1 + * Bits 31:0 + * Purpose: Mickey1 + * WORD 2: + * - MIC2 + * Bits 31:0 + * Purpose: Mickey2 + */ +typedef struct htt_isoc_t2h_sec_ind_s { + /* word 0 */ + A_UINT32 + msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_SEC_IND */ + peer_id: 8, + sec_type: 8, + is_unicast: 8; + /* word 1 */ + A_UINT32 mic_key1; + /* word 2 */ + A_UINT32 mic_key2; + /* word 3 */ + A_UINT32 status; +} htt_isoc_t2h_sec_ind_t; + +/* word 0 */ +#define HTT_ISOC_T2H_SEC_IND_PEER_ID_OFFSET32 0 +#define HTT_ISOC_T2H_SEC_IND_PEER_ID_M 0x0000ff00 +#define HTT_ISOC_T2H_SEC_IND_PEER_ID_S 8 + +#define HTT_ISOC_T2H_SEC_IND_SEC_TYPE_OFFSET32 0 +#define HTT_ISOC_T2H_SEC_IND_SEC_TYPE_M 0x00ff0000 +#define HTT_ISOC_T2H_SEC_IND_SEC_TYPE_S 16 + +#define HTT_ISOC_T2H_SEC_IND_IS_UNICAST_OFFSET32 0 +#define HTT_ISOC_T2H_SEC_IND_IS_UNICAST_M 0xff000000 +#define HTT_ISOC_T2H_SEC_IND_IS_UNICAST_S 24 + +/* word 1 */ +#define HTT_ISOC_T2H_SEC_IND_MIC1_OFFSET32 1 +#define HTT_ISOC_T2H_SEC_IND_MIC1_M 0xffffffff +#define HTT_ISOC_T2H_SEC_IND_MIC1_S 0 + +/* word 2 */ +#define HTT_ISOC_T2H_SEC_IND_MIC2_OFFSET32 2 +#define HTT_ISOC_T2H_SEC_IND_MIC2_M 0xffffffff +#define HTT_ISOC_T2H_SEC_IND_MIC2_S 0 + + +/* general field access macros */ +#define HTT_ISOC_T2H_SEC_IND_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_SEC_IND_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_SEC_IND_ ## field ## _M, \ + HTT_ISOC_T2H_SEC_IND_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_SEC_IND_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_SEC_IND_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_SEC_IND_ ## field ## _M, \ + HTT_ISOC_T2H_SEC_IND_ ## field ## _S) + +/* access macros for specific fields */ +#define HTT_ISOC_T2H_SEC_IND_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_SEC_IND_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_SEC_IND_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_SEC_IND_FIELD_GET(PEER_ID, msg_addr) + +#define HTT_ISOC_T2H_SEC_IND_SEC_TYPE_SET(msg_addr, value) \ + HTT_ISOC_T2H_SEC_IND_FIELD_SET(SEC_TYPE, msg_addr, value) +#define HTT_ISOC_T2H_SEC_IND_SEC_TYPE_GET(msg_addr) \ + HTT_ISOC_T2H_SEC_IND_FIELD_GET(SEC_TYPE, msg_addr) + +#define HTT_ISOC_T2H_SEC_IND_IS_UNICAST_SET(msg_addr, value) \ + HTT_ISOC_T2H_SEC_IND_FIELD_SET(IS_UNICAST, msg_addr, value) +#define HTT_ISOC_T2H_SEC_IND_IS_UNICAST_GET(msg_addr) \ + HTT_ISOC_T2H_SEC_IND_FIELD_GET(IS_UNICAST, msg_addr) + +#define HTT_ISOC_T2H_SEC_IND_MIC1_SET(msg_addr, value) \ + HTT_ISOC_T2H_SEC_IND_FIELD_SET(MIC1, msg_addr, value) +#define HTT_ISOC_T2H_SEC_IND_MIC1_GET(msg_addr) \ + HTT_ISOC_T2H_SEC_IND_FIELD_GET(MIC1, msg_addr) + +#define HTT_ISOC_T2H_SEC_IND_MIC2_SET(msg_addr, value) \ + HTT_ISOC_T2H_SEC_IND_FIELD_SET(MIC2, msg_addr, value) +#define HTT_ISOC_T2H_SEC_IND_MIC2_GET(msg_addr) \ + HTT_ISOC_T2H_SEC_IND_FIELD_GET(MIC2, msg_addr) + +/*=== PEER_TX_READY message ===*/ + +/** + * @brief target -> host peer tx ready message definition + * + * @details + * The following diagram shows the format of the peer tx ready message sent + * from the target to the host. This layout assumes the target operates + * as little-endian. + * + * |31 19|18 8|7 0| + * |-----------------------------------------------------------------------| + * | reserved | peer ID | msg type | + * |-----------------------------------------------------------------------| + * + * + * The following field definitions describe the format of the peer info + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as peer tx ready message + * Value: 0x7 + * - PEER_ID + * Bits 18:8 + * Purpose: The ID assigned to the peer by the PEER_INFO message + */ +typedef struct htt_isoc_t2h_peer_tx_ready_s { + /* word 0 */ + A_UINT32 + msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_PEER_TX_READY */ + peer_id: 11, + reserved0: 13; +} htt_isoc_t2h_peer_tx_ready_t; + +/* word 0 */ +#define HTT_ISOC_T2H_PEER_TX_READY_PEER_ID_OFFSET32 0 +#define HTT_ISOC_T2H_PEER_TX_READY_PEER_ID_M 0x0007ff00 +#define HTT_ISOC_T2H_PEER_TX_READY_PEER_ID_S 8 + + +/* general field access macros */ + +#define HTT_ISOC_T2H_PEER_TX_READY_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_PEER_TX_READY_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_PEER_TX_READY_ ## field ## _M, \ + HTT_ISOC_T2H_PEER_TX_READY_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_PEER_TX_READY_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_PEER_TX_READY_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_PEER_TX_READY_ ## field ## _M, \ + HTT_ISOC_T2H_PEER_TX_READY_ ## field ## _S) + +/* access macros for specific fields */ + +#define HTT_ISOC_T2H_PEER_TX_READY_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_PEER_TX_READY_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_PEER_TX_READY_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_PEER_TX_READY_FIELD_GET(PEER_ID, msg_addr) + + +/*=== RX_ERR message ===*/ + +/** + * @brief target -> host rx error notification message definition + * + * @details + * The following diagram shows the format of the rx err message sent + * from the target to the host. This layout assumes the target operates + * as little-endian. + * + * |31 16|15 8|7|6|5|4 0| + * |---------------------------------------------------------------------| + * | peer ID | rx err type | msg type | + * |---------------------------------------------------------------------| + * | reserved | rx err count |M| r | ext TID | + * |---------------------------------------------------------------------| + * M = multicast + * r = reserved + * + * The following field definitions describe the format of the peer info + * message sent from the target to the host. + * + * WORD 0: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as an rx err message + * Value: 0x8 + * - RX_ERR_TYPE + * Bits 15:8 + * Purpose: specifies which type of rx error is being reported + * Value: htt_rx_ind_mpdu_status enum + * - PEER_ID + * Bits 31:16 + * Purpose: specify which peer sent the frame that resulted in an error + * WORD 1: + * - EXT_TID + * Bits 4:0 + * Purpose: specifies which traffic type had the rx error + * Value: 0-15 for a real TID value, 16 for non-QoS data, 31 for unknown + * - MCAST + * Bit 6 + * Purpose: specify whether the rx error frame was unicast or multicast + * Value: 0 -> unicast, 1 -> multicast + * - L2_HDR_IS_80211 + * Bit 7 + * Purpose: specifies whether the included L2 header (if present) is in + * 802.3 or 802.11 format + * Value: 0 -> 802.3, 1 -> 802.11 + * - L2_HDR_BYTES + * Bits 15:8 + * Purpose: Specify the size of the L2 header in this rx error report. + * Value: + * If no L2 header is included, this field shall be 0. + * If a 802.3 + LLC/SNAP header is included, this field shall be + * 14 (ethernet header) + 8 (LLC/SNAP). + * If a 802.11 header is included, this field shall be 24 bytes for + * a basic header, or 26 bytes if a QoS control field is included, + * or 30 bytes if a 4th address is included, or 32 bytes if a 4th + * address and a QoS control field are included, etc. + * Though the L2 header included in the message needs to include + * padding up to a 4-byte boundary, this L2 header size field need + * not account for the padding following the L2 header. + * - SEC_HDR_BYTES + * Bits 23:16 + * Purpose: Specify the size of the security encapsulation header in + * this rx error report. + * Value: + * If no security header is included, this field shall be 0. + * If a security header is included, this field depends on the + * security type, which can be inferred from the rx error type. + * For TKIP MIC errors, the security header could be any of: + * 8 - if IV / KeyID and Extended IV are included + * 16 - if MIC is also included + * 20 - if ICV is also included + * - RX_ERR_CNT + * Bits 31:24 + * Purpose: specifies how many rx errors are reported in this message + * Value: + * Rx error reports that include a L2 header and/or security header + * will set this field to 1, to indicate that the error notification + * is for a single frame. + * Rx error reports that don't include a L2 header or security header + * can use this field to send a single message to report multiple + * erroneous rx frames. + */ +typedef struct htt_isoc_t2h_rx_err_s { + /* word 0 */ + A_UINT32 + msg_type: 8, /* HTT_ISOC_T2H_MSG_TYPE_RX_ERR */ + rx_err_type: 8, + peer_id: 16; + /* word 1 */ + A_UINT32 + ext_tid: 5, + reserved1: 1, + mcast: 1, + l2_hdr_is_80211: 1, + l2_hdr_bytes: 8, + sec_hdr_bytes: 8, + rx_err_cnt: 8; + /* words 2 - M-1: L2 header */ + /* words M - N: security header */ +} htt_isoc_t2h_rx_err_t; + +/* word 0 */ +#define HTT_ISOC_T2H_RX_ERR_TYPE_OFFSET32 0 +#define HTT_ISOC_T2H_RX_ERR_TYPE_M 0x0000ff00 +#define HTT_ISOC_T2H_RX_ERR_TYPE_ID_S 8 + +#define HTT_ISOC_T2H_RX_ERR_PEER_ID_OFFSET32 0 +#define HTT_ISOC_T2H_RX_ERR_PEER_ID_M 0xffff0000 +#define HTT_ISOC_T2H_RX_ERR_PEER_ID_S 16 + +/* word 1 */ +#define HTT_ISOC_T2H_RX_ERR_EXT_TID_OFFSET32 1 +#define HTT_ISOC_T2H_RX_ERR_EXT_TID_M 0x0000001f +#define HTT_ISOC_T2H_RX_ERR_EXT_TID_ID_S 0 + +#define HTT_ISOC_T2H_RX_ERR_MCAST_OFFSET32 1 +#define HTT_ISOC_T2H_RX_ERR_MCAST_M 0x00000040 +#define HTT_ISOC_T2H_RX_ERR_MCAST_ID_S 6 + +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_IS_80211_OFFSET32 1 +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_IS_80211_M 0x00000080 +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_IS_80211_ID_S 7 + +#define HTT_ISOC_T2H_RX_L2_HDR_BYTES_OFFSET32 1 +#define HTT_ISOC_T2H_RX_L2_HDR_BYTES_M 0x0000ff00 +#define HTT_ISOC_T2H_RX_L2_HDR_BYTES_ID_S 8 + +#define HTT_ISOC_T2H_RX_SEC_HDR_BYTES_OFFSET32 1 +#define HTT_ISOC_T2H_RX_SEC_HDR_BYTES_M 0x00ff0000 +#define HTT_ISOC_T2H_RX_SEC_HDR_BYTES_ID_S 16 + +#define HTT_ISOC_T2H_RX_ERR_CNT_OFFSET32 1 +#define HTT_ISOC_T2H_RX_ERR_CNT_M 0xff000000 +#define HTT_ISOC_T2H_RX_ERR_CNT_ID_S 24 + + +/* general field access macros */ + +#define HTT_ISOC_T2H_RX_ERR_FIELD_SET(field, msg_addr, value) \ + htt_isoc_t2h_field_set( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_RX_ERR_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_RX_ERR_ ## field ## _M, \ + HTT_ISOC_T2H_RX_ERR_ ## field ## _S, \ + value) + +#define HTT_ISOC_T2H_RX_ERR_FIELD_GET(field, msg_addr) \ + HTT_ISOC_T2H_FIELD_GET( \ + ((A_UINT32 *) msg_addr), \ + HTT_ISOC_T2H_RX_ERR_ ## field ## _OFFSET32, \ + HTT_ISOC_T2H_RX_ERR_ ## field ## _M, \ + HTT_ISOC_T2H_RX_ERR_ ## field ## _S) + +/* access macros for specific fields */ + +#define HTT_ISOC_T2H_RX_ERR_TYPE_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(TYPE, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_TYPE_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(TYPE, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_PEER_ID_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(PEER_ID, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_PEER_ID_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(PEER_ID, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_EXT_TID_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(EXT_TID, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_EXT_TID_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(EXT_TID, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_MCAST_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(MCAST, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_MCAST_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(MCAST, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_IS_80211_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(L2_HDR_IS_80211, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_IS_80211_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(L2_HDR_IS_80211, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_BYTES_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(L2_HDR_BYTES, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_L2_HDR_BYTES_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(L2_HDR_BYTES, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_SEC_HDR_BYTES_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(SEC_HDR_BYTES, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_SEC_HDR_BYTES_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(SEC_HDR_BYTES, msg_addr) + +#define HTT_ISOC_T2H_RX_ERR_CNT_SET(msg_addr, value) \ + HTT_ISOC_T2H_RX_ERR_FIELD_SET(CNT, msg_addr, value) +#define HTT_ISOC_T2H_RX_ERR_CNT_GET(msg_addr) \ + HTT_ISOC_T2H_RX_ERR_FIELD_GET(CNT, msg_addr) + + +#endif /* _HTT_ISOC_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_rx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_rx.c new file mode 100644 index 000000000000..fbfba878629f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_rx.c @@ -0,0 +1,2926 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_rx.c + * @brief Implement receive aspects of HTT. + * @details + * This file contains three categories of HTT rx code: + * 1. An abstraction of the rx descriptor, to hide the + * differences between the HL vs. LL rx descriptor. + * 2. Functions for providing access to the (series of) + * rx descriptor(s) and rx frame(s) associated with + * an rx indication message. + * 3. Functions for setting up and using the MAC DMA + * rx ring (applies to LL only). + */ + +#include /* adf_os_mem_alloc,free, etc. */ +#include /* adf_os_print, a_bool_t */ +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_timer_free */ + +#include /* HTT_HL_RX_DESC_SIZE */ +#include +#include +#include +#include /* HTT_ASSERT, htt_pdev_t, HTT_RX_BUF_SIZE */ +#include "regtable.h" + +#include /* ieee80211_frame, ieee80211_qoscntl */ +#include /* ieee80211_rx_status */ + +#include +#ifdef DEBUG_DMA_DONE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) +#include +#else +#include +#endif +#endif + +#ifdef DEBUG_DMA_DONE +extern int process_wma_set_command(int sessid, int paramid, + int sval, int vpdev); +#endif + +/* AR9888v1 WORKAROUND for EV#112367 */ +/* FIX THIS - remove this WAR when the bug is fixed */ +#define PEREGRINE_1_0_ZERO_LEN_PHY_ERR_WAR + +/*--- setup / tear-down functions -------------------------------------------*/ + +#ifndef HTT_RX_RING_SIZE_MIN +#define HTT_RX_RING_SIZE_MIN 128 /* slightly larger than one large A-MPDU */ +#endif + +#ifndef HTT_RX_RING_SIZE_MAX +#define HTT_RX_RING_SIZE_MAX 2048 /* roughly 20 ms @ 1 Gbps of 1500B MSDUs */ +#endif + +#ifndef HTT_RX_AVG_FRM_BYTES +#define HTT_RX_AVG_FRM_BYTES 1000 +#endif + +#ifndef HTT_RX_HOST_LATENCY_MAX_MS +#define HTT_RX_HOST_LATENCY_MAX_MS 20 /* ms */ /* very conservative */ +#endif + +#ifndef HTT_RX_HOST_LATENCY_WORST_LIKELY_MS +#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 10 /* ms */ /* conservative */ +#endif + +#ifndef HTT_RX_RING_REFILL_RETRY_TIME_MS +#define HTT_RX_RING_REFILL_RETRY_TIME_MS 50 +#endif + +void +htt_rx_hash_deinit(struct htt_pdev_t *pdev); + +static int +CEIL_PWR2(int value) +{ + int log2; + if (IS_PWR2(value)) { + return value; + } + log2 = 0; + while (value) { + value >>= 1; + log2++; + } + return (1 << log2); +} + +/* + * This function is used both below within this file (which the compiler + * will hopefully inline), and out-line from other files via the + * htt_rx_msdu_first_msdu_flag function pointer. + */ +static inline a_bool_t +htt_rx_msdu_first_msdu_flag_hl(htt_pdev_handle pdev, void *msdu_desc) +{ + return ((u_int8_t*)msdu_desc - sizeof(struct hl_htt_rx_ind_base)) + [HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)] & + HTT_RX_IND_HL_FLAG_FIRST_MSDU ? A_TRUE : A_FALSE; +} + +static a_bool_t +htt_rx_msdu_first_msdu_flag_ll(htt_pdev_handle pdev, void *msdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) msdu_desc; + return (a_bool_t) + (((*(((u_int32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_FIRST_MSDU_MASK) >> + RX_MSDU_END_4_FIRST_MSDU_LSB); +} + +u_int16_t +htt_rx_msdu_rx_desc_size_hl( + htt_pdev_handle pdev, + void *msdu_desc + ) +{ + return ((u_int8_t*)(msdu_desc) - HTT_RX_IND_HL_BYTES) + [HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)]; +} + +static int +htt_rx_ring_size(struct htt_pdev_t *pdev) +{ + int size; + + /* + * It is expected that the host CPU will typically be able to service + * the rx indication from one A-MPDU before the rx indication from + * the subsequent A-MPDU happens, roughly 1-2 ms later. + * However, the rx ring should be sized very conservatively, to + * accomodate the worst reasonable delay before the host CPU services + * a rx indication interrupt. + * The rx ring need not be kept full of empty buffers. In theory, + * the htt host SW can dynamically track the low-water mark in the + * rx ring, and dynamically adjust the level to which the rx ring + * is filled with empty buffers, to dynamically meet the desired + * low-water mark. + * In contrast, it's difficult to resize the rx ring itself, once + * it's in use. + * Thus, the ring itself should be sized very conservatively, while + * the degree to which the ring is filled with empty buffers should + * be sized moderately conservatively. + */ + size = + ol_cfg_max_thruput_mbps(pdev->ctrl_pdev) * + 1000 /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ / + (8 * HTT_RX_AVG_FRM_BYTES) * + HTT_RX_HOST_LATENCY_MAX_MS; + + if (size < HTT_RX_RING_SIZE_MIN) { + size = HTT_RX_RING_SIZE_MIN; + } + if (size > HTT_RX_RING_SIZE_MAX) { + size = HTT_RX_RING_SIZE_MAX; + } + size = CEIL_PWR2(size); + return size; +} + +static int +htt_rx_ring_fill_level(struct htt_pdev_t *pdev) +{ + int size; + + size = + ol_cfg_max_thruput_mbps(pdev->ctrl_pdev) * + 1000 /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ / + (8 * HTT_RX_AVG_FRM_BYTES) * + HTT_RX_HOST_LATENCY_WORST_LIKELY_MS; + /* + * Make sure the fill level is at least 1 less than the ring size. + * Leaving 1 element empty allows the SW to easily distinguish + * between a full ring vs. an empty ring. + */ + if (size >= pdev->rx_ring.size) { + size = pdev->rx_ring.size - 1; + } + return size; +} + +static void +htt_rx_ring_refill_retry(void *arg) +{ + htt_pdev_handle pdev = (htt_pdev_handle)arg; + htt_rx_msdu_buff_replenish(pdev); +} + +void +htt_rx_ring_fill_n(struct htt_pdev_t *pdev, int num) +{ + int idx; + a_status_t status; + struct htt_host_rx_desc_base *rx_desc; + + idx = *(pdev->rx_ring.alloc_idx.vaddr); + while (num > 0) { + u_int32_t paddr; + adf_nbuf_t rx_netbuf; + int headroom; + +#ifdef QCA_ARP_SPOOFING_WAR + rx_netbuf = adf_rx_nbuf_alloc(pdev->osdev, HTT_RX_BUF_SIZE, 0, 4, + FALSE); +#else + rx_netbuf = adf_nbuf_alloc(pdev->osdev, HTT_RX_BUF_SIZE, 0, 4, FALSE); +#endif + if (!rx_netbuf) { + adf_os_timer_cancel(&pdev->rx_ring.refill_retry_timer); + /* + * Failed to fill it to the desired level - + * we'll start a timer and try again next time. + * As long as enough buffers are left in the ring for + * another A-MPDU rx, no special recovery is needed. + */ +#ifdef DEBUG_DMA_DONE + pdev->rx_ring.dbg_refill_cnt++; +#endif + adf_os_timer_start(&pdev->rx_ring.refill_retry_timer, + HTT_RX_RING_REFILL_RETRY_TIME_MS); + goto fail; + } + + /* Clear rx_desc attention word before posting to Rx ring */ + rx_desc = htt_rx_desc(rx_netbuf); + *(u_int32_t *)&rx_desc->attention = 0; + +#ifdef DEBUG_DMA_DONE + *(u_int32_t *)&rx_desc->msdu_end = 1; + + #define MAGIC_PATTERN 0xDEADBEEF + *(u_int32_t *)&rx_desc->msdu_start = MAGIC_PATTERN; + + /* To ensure that attention bit is reset and msdu_end is set before + calling dma_map */ + smp_mb(); +#endif + /* + * Adjust adf_nbuf_data to point to the location in the buffer + * where the rx descriptor will be filled in. + */ + headroom = adf_nbuf_data(rx_netbuf) - (u_int8_t *) rx_desc; + adf_nbuf_push_head(rx_netbuf, headroom); + +#ifdef DEBUG_DMA_DONE + status = adf_nbuf_map(pdev->osdev, rx_netbuf, ADF_OS_DMA_BIDIRECTIONAL); +#else + status = adf_nbuf_map(pdev->osdev, rx_netbuf, ADF_OS_DMA_FROM_DEVICE); +#endif + if (status != A_STATUS_OK) { + adf_nbuf_free(rx_netbuf); + goto fail; + } + paddr = adf_nbuf_get_frag_paddr_lo(rx_netbuf, 0); + if (pdev->cfg.is_full_reorder_offload) { + if(adf_os_unlikely( + htt_rx_hash_list_insert(pdev, paddr, rx_netbuf))) { + adf_os_print("%s: hash insert failed!\n", __FUNCTION__); +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap(pdev->osdev, rx_netbuf, + ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap(pdev->osdev, rx_netbuf, ADF_OS_DMA_FROM_DEVICE); +#endif + adf_nbuf_free(rx_netbuf); + goto fail; + } +#ifdef DEBUG_RX_RING_BUFFER + if (pdev->rx_buff_list) { + pdev->rx_buff_list[pdev->rx_buff_index].paddr = paddr; + pdev->rx_buff_list[pdev->rx_buff_index].in_use = true; + pdev->rx_buff_list[pdev->rx_buff_index].vaddr = rx_netbuf; + NBUF_MAP_ID(rx_netbuf) = pdev->rx_buff_index; + if(++pdev->rx_buff_index == HTT_RX_RING_BUFF_DBG_LIST) + pdev->rx_buff_index = 0; + } +#endif + } else { + pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf; + } + pdev->rx_ring.buf.paddrs_ring[idx] = paddr; + pdev->rx_ring.fill_cnt++; + + num--; + idx++; + idx &= pdev->rx_ring.size_mask; + } + +fail: + *(pdev->rx_ring.alloc_idx.vaddr) = idx; + return; +} + +unsigned +htt_rx_ring_elems(struct htt_pdev_t *pdev) +{ + return + (*pdev->rx_ring.alloc_idx.vaddr - pdev->rx_ring.sw_rd_idx.msdu_payld) & + pdev->rx_ring.size_mask; +} + +unsigned int +htt_rx_in_order_ring_elems(struct htt_pdev_t *pdev) +{ + return + (*pdev->rx_ring.alloc_idx.vaddr - *pdev->rx_ring.target_idx.vaddr) & + pdev->rx_ring.size_mask; +} + +void +htt_rx_detach(struct htt_pdev_t *pdev) +{ + + if (pdev->cfg.is_high_latency) { + return; + } + + adf_os_timer_cancel(&pdev->rx_ring.refill_retry_timer); + adf_os_timer_free(&pdev->rx_ring.refill_retry_timer); + + if (pdev->cfg.is_full_reorder_offload) { + adf_os_mem_free_consistent( + pdev->osdev, + sizeof(u_int32_t), + pdev->rx_ring.target_idx.vaddr, + pdev->rx_ring.target_idx.paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.target_idx), memctx)); + htt_rx_hash_deinit(pdev); + } else { + int sw_rd_idx = pdev->rx_ring.sw_rd_idx.msdu_payld; + + while (sw_rd_idx != *(pdev->rx_ring.alloc_idx.vaddr)) { +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap( + pdev->osdev, pdev->rx_ring.buf.netbufs_ring[sw_rd_idx], + ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap( + pdev->osdev, pdev->rx_ring.buf.netbufs_ring[sw_rd_idx], + ADF_OS_DMA_FROM_DEVICE); +#endif + adf_nbuf_free(pdev->rx_ring.buf.netbufs_ring[sw_rd_idx]); + sw_rd_idx++; + sw_rd_idx &= pdev->rx_ring.size_mask; + } + adf_os_mem_free(pdev->rx_ring.buf.netbufs_ring); + } + + adf_os_mem_free_consistent( + pdev->osdev, + sizeof(u_int32_t), + pdev->rx_ring.alloc_idx.vaddr, + pdev->rx_ring.alloc_idx.paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.alloc_idx), memctx)); + + adf_os_mem_free_consistent( + pdev->osdev, + pdev->rx_ring.size * sizeof(u_int32_t), + pdev->rx_ring.buf.paddrs_ring, + pdev->rx_ring.base_paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.buf), memctx)); +} + +/*--- rx descriptor field access functions ----------------------------------*/ +/* + * These functions need to use bit masks and shifts to extract fields + * from the rx descriptors, rather than directly using the bitfields. + * For example, use + * (desc & FIELD_MASK) >> FIELD_LSB + * rather than + * desc.field + * This allows the functions to work correctly on either little-endian + * machines (no endianness conversion needed) or big-endian machines + * (endianness conversion provided automatically by the HW DMA's + * byte-swizzling). + */ +/* FIX THIS: APPLIES TO LL ONLY */ + +/** + * htt_rx_mpdu_desc_retry_ll() - Returns the retry bit from the Rx descriptor + * for the Low Latency driver + * @pdev: Handle (pointer) to HTT pdev. + * @mpdu_desc: Void pointer to the Rx descriptor for MPDU + * before the beginning of the payload. + * + * This function returns the retry bit of the 802.11 header for the + * provided rx MPDU descriptor. + * + * Return: boolean -- true if retry is set, false otherwise + */ +bool +htt_rx_mpdu_desc_retry_ll(htt_pdev_handle pdev, void *mpdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) mpdu_desc; + + return + (bool)(((*((uint32_t *) &rx_desc->mpdu_start)) & + RX_MPDU_START_0_RETRY_MASK) >> + RX_MPDU_START_0_RETRY_LSB); +} + +/** + * htt_rx_mpdu_desc_retry_hl() - Returns the retry bit from the Rx descriptor + * for the High Latency driver + * @pdev: Handle (pointer) to HTT pdev. + * @mpdu_desc: Void pointer to the Rx descriptor for MPDU + * before the beginning of the payload. + * + * This function returns the retry bit of the 802.11 header for the + * provided rx MPDU descriptor. For the high latency driver, this function + * pretends as if the retry bit is never set so that the mcast duplicate + * detection never fails. + * + * Return: boolean -- false always for HL + */ +bool +htt_rx_mpdu_desc_retry_hl(htt_pdev_handle pdev, void *mpdu_desc) +{ + return false; +} + +u_int16_t +htt_rx_mpdu_desc_seq_num_ll(htt_pdev_handle pdev, void *mpdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) mpdu_desc; + + return + (u_int16_t)(((*((u_int32_t *) &rx_desc->mpdu_start)) & + RX_MPDU_START_0_SEQ_NUM_MASK) >> + RX_MPDU_START_0_SEQ_NUM_LSB); +} + +u_int16_t +htt_rx_mpdu_desc_seq_num_hl(htt_pdev_handle pdev, void *mpdu_desc) +{ + if (pdev->rx_desc_size_hl) { + return pdev->cur_seq_num_hl = + (u_int16_t)(HTT_WORD_GET(*(u_int32_t*)mpdu_desc, + HTT_HL_RX_DESC_MPDU_SEQ_NUM)); + } else { + return (u_int16_t)(pdev->cur_seq_num_hl); + } +} + +/* FIX THIS: APPLIES TO LL ONLY */ +void +htt_rx_mpdu_desc_pn_ll( + htt_pdev_handle pdev, + void *mpdu_desc, + union htt_rx_pn_t *pn, + int pn_len_bits) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) mpdu_desc; + + switch (pn_len_bits) { + case 24: + /* bits 23:0 */ + pn->pn24 = + rx_desc->mpdu_start.pn_31_0 & 0xffffff; + break; + case 48: + /* bits 31:0 */ + pn->pn48 = rx_desc->mpdu_start.pn_31_0; + /* bits 47:32 */ + pn->pn48 |= + ((u_int64_t) ((*(((u_int32_t *) &rx_desc->mpdu_start) + 2)) + & RX_MPDU_START_2_PN_47_32_MASK)) + << (32 - RX_MPDU_START_2_PN_47_32_LSB); + break; + case 128: + /* bits 31:0 */ + pn->pn128[0] = rx_desc->mpdu_start.pn_31_0; + /* bits 47:32 */ + pn->pn128[0] |= + ((u_int64_t) ((*(((u_int32_t *) &rx_desc->mpdu_start) + 2)) + & RX_MPDU_START_2_PN_47_32_MASK)) + << (32 - RX_MPDU_START_2_PN_47_32_LSB); + /* bits 63:48 */ + pn->pn128[0] |= + ((u_int64_t) ((*(((u_int32_t *) &rx_desc->msdu_end) + 2)) + & RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK)) + << (48 - RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB); + /* bits 95:64 */ + pn->pn128[1] = rx_desc->msdu_end.ext_wapi_pn_95_64; + /* bits 127:96 */ + pn->pn128[1] |= + ((u_int64_t) rx_desc->msdu_end.ext_wapi_pn_127_96) << 32; + break; + default: + adf_os_print( + "Error: invalid length spec (%d bits) for PN\n", pn_len_bits); + }; +} + +/* HL case */ +void +htt_rx_mpdu_desc_pn_hl( + htt_pdev_handle pdev, + void *mpdu_desc, + union htt_rx_pn_t *pn, + int pn_len_bits) +{ + if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == A_TRUE) { + /* Fix Me: only for little endian */ + struct hl_htt_rx_desc_base *rx_desc = + (struct hl_htt_rx_desc_base *) mpdu_desc; + u_int32_t *word_ptr = (u_int32_t *)pn->pn128; + + /* TODO: for Host of big endian */ + switch (pn_len_bits) { + case 128: + /* bits 128:64 */ + *(word_ptr + 3) = rx_desc->pn_127_96; + /* bits 63:0 */ + *(word_ptr + 2) = rx_desc->pn_95_64; + case 48: + /* bits 48:0 + * copy 64 bits + */ + *(word_ptr + 1) = rx_desc->u0.pn_63_32; + case 24: + /* bits 23:0 + * copy 32 bits + */ + *(word_ptr + 0) = rx_desc->pn_31_0; + break; + default: + adf_os_print( + "Error: invalid length spec (%d bits) for PN\n", pn_len_bits); + adf_os_assert(0); + }; + } else { + /* not first msdu, no pn info */ + adf_os_print( + "Error: get pn from a not-first msdu.\n"); + adf_os_assert(0); + } +} + +/** + * htt_rx_mpdu_desc_tid_ll() - Returns the TID value from the Rx descriptor + * for Low Latency driver + * @pdev: Handle (pointer) to HTT pdev. + * @mpdu_desc: Void pointer to the Rx descriptor for the MPDU + * before the beginning of the payload. + * + * This function returns the TID set in the 802.11 QoS Control for the MPDU + * in the packet header, by looking at the mpdu_start of the Rx descriptor. + * Rx descriptor gets a copy of the TID from the MAC. + * + * Return: Actual TID set in the packet header. + */ +uint8_t +htt_rx_mpdu_desc_tid_ll(htt_pdev_handle pdev, void *mpdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) mpdu_desc; + + return + (uint8_t)(((*(((uint32_t *) &rx_desc->mpdu_start) + 2)) & + RX_MPDU_START_2_TID_MASK) >> + RX_MPDU_START_2_TID_LSB); +} + +/** + * htt_rx_mpdu_desc_tid_hl() - Returns the TID value from the Rx descriptor + * for High Latency driver + * @pdev: Handle (pointer) to HTT pdev. + * @mpdu_desc: Void pointer to the Rx descriptor for the MPDU + * before the beginning of the payload. + * + * This function returns the TID set in the 802.11 QoS Control for the MPDU + * in the packet header, by looking at the mpdu_start of the Rx descriptor. + * Rx descriptor gets a copy of the TID from the MAC. + * For the HL driver, this is currently uimplemented and always returns + * an invalid tid. It is the responsibility of the caller to make + * sure that return value is checked for valid range. + * + * Return: Invalid TID value (0xff) for HL driver. + */ +uint8_t +htt_rx_mpdu_desc_tid_hl(htt_pdev_handle pdev, void *mpdu_desc) +{ + return 0xff; /* Invalid TID */ +} + +u_int32_t +htt_rx_mpdu_desc_tsf32( + htt_pdev_handle pdev, + void *mpdu_desc) +{ +/* FIX THIS */ +return 0; +} + +/* FIX THIS: APPLIES TO LL ONLY */ +char * +htt_rx_mpdu_wifi_hdr_retrieve(htt_pdev_handle pdev, void *mpdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) mpdu_desc; + return rx_desc->rx_hdr_status; +} + +/* FIX THIS: APPLIES TO LL ONLY */ +a_bool_t +htt_rx_msdu_desc_completes_mpdu_ll(htt_pdev_handle pdev, void *msdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) msdu_desc; + return (a_bool_t) + (((*(((u_int32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_LAST_MSDU_MASK) >> + RX_MSDU_END_4_LAST_MSDU_LSB); +} + +a_bool_t +htt_rx_msdu_desc_completes_mpdu_hl(htt_pdev_handle pdev, void *msdu_desc) +{ + return ( + ((u_int8_t*)(msdu_desc) - sizeof(struct hl_htt_rx_ind_base)) + [HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)] + & HTT_RX_IND_HL_FLAG_LAST_MSDU) + ? A_TRUE : A_FALSE; +} + +/* FIX THIS: APPLIES TO LL ONLY */ +int +htt_rx_msdu_has_wlan_mcast_flag_ll(htt_pdev_handle pdev, void *msdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) msdu_desc; + /* HW rx desc: the mcast_bcast flag is only valid if first_msdu is set */ + return + ((*(((u_int32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_FIRST_MSDU_MASK) >> + RX_MSDU_END_4_FIRST_MSDU_LSB; +} + +int +htt_rx_msdu_has_wlan_mcast_flag_hl(htt_pdev_handle pdev, void *msdu_desc) +{ + /* currently, only first msdu has hl rx_desc */ + return htt_rx_msdu_first_msdu_flag_hl(pdev, msdu_desc) == A_TRUE; +} + +/* FIX THIS: APPLIES TO LL ONLY */ +a_bool_t +htt_rx_msdu_is_wlan_mcast_ll(htt_pdev_handle pdev, void *msdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) msdu_desc; + return + ((*((u_int32_t *) &rx_desc->attention)) & + RX_ATTENTION_0_MCAST_BCAST_MASK) >> + RX_ATTENTION_0_MCAST_BCAST_LSB; +} + +a_bool_t +htt_rx_msdu_is_wlan_mcast_hl(htt_pdev_handle pdev, void *msdu_desc) +{ + struct hl_htt_rx_desc_base *rx_desc = + (struct hl_htt_rx_desc_base *) msdu_desc; + return + HTT_WORD_GET(*(u_int32_t*)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST); +} + +/* FIX THIS: APPLIES TO LL ONLY */ +int +htt_rx_msdu_is_frag_ll(htt_pdev_handle pdev, void *msdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = + (struct htt_host_rx_desc_base *) msdu_desc; + return + ((*((u_int32_t *) &rx_desc->attention)) & + RX_ATTENTION_0_FRAGMENT_MASK) >> + RX_ATTENTION_0_FRAGMENT_LSB; +} + +int +htt_rx_msdu_is_frag_hl(htt_pdev_handle pdev, void *msdu_desc) +{ + struct hl_htt_rx_desc_base *rx_desc = + (struct hl_htt_rx_desc_base *) msdu_desc; + + return + HTT_WORD_GET(*(u_int32_t*)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST); +} + +static inline +u_int8_t +htt_rx_msdu_fw_desc_get(htt_pdev_handle pdev, void *msdu_desc) +{ + /* + * HL and LL use the same format for FW rx desc, but have the FW rx desc + * in different locations. + * In LL, the FW rx descriptor has been copied into the same + * htt_host_rx_desc_base struct that holds the HW rx desc. + * In HL, the FW rx descriptor, along with the MSDU payload, + * is in the same buffer as the rx indication message. + * + * Use the FW rx desc offset configured during startup to account for + * this difference between HL vs. LL. + * + * An optimization would be to define the LL and HL msdu_desc pointer + * in such a way that they both use the same offset to the FW rx desc. + * Then the following functions could be converted to macros, without + * needing to expose the htt_pdev_t definition outside HTT. + */ + return *(((u_int8_t *) msdu_desc) + pdev->rx_fw_desc_offset); +} + +int +htt_rx_msdu_discard(htt_pdev_handle pdev, void *msdu_desc) +{ + return htt_rx_msdu_fw_desc_get(pdev, msdu_desc) & FW_RX_DESC_DISCARD_M; +} + +int +htt_rx_msdu_forward(htt_pdev_handle pdev, void *msdu_desc) +{ + return htt_rx_msdu_fw_desc_get(pdev, msdu_desc) & FW_RX_DESC_FORWARD_M; +} + +int +htt_rx_msdu_inspect(htt_pdev_handle pdev, void *msdu_desc) +{ + return htt_rx_msdu_fw_desc_get(pdev, msdu_desc) & FW_RX_DESC_INSPECT_M; +} + +void +htt_rx_msdu_actions( + htt_pdev_handle pdev, + void *msdu_desc, + int *discard, + int *forward, + int *inspect) +{ + u_int8_t rx_msdu_fw_desc = htt_rx_msdu_fw_desc_get(pdev, msdu_desc); +#ifdef HTT_DEBUG_DATA + HTT_PRINT("act:0x%x ",rx_msdu_fw_desc); +#endif + *discard = rx_msdu_fw_desc & FW_RX_DESC_DISCARD_M; + *forward = rx_msdu_fw_desc & FW_RX_DESC_FORWARD_M; + *inspect = rx_msdu_fw_desc & FW_RX_DESC_INSPECT_M; +} + +static inline adf_nbuf_t +htt_rx_netbuf_pop( + htt_pdev_handle pdev) +{ + int idx; + adf_nbuf_t msdu; + + HTT_ASSERT1(htt_rx_ring_elems(pdev) != 0); + +#ifdef DEBUG_DMA_DONE + pdev->rx_ring.dbg_ring_idx++; + pdev->rx_ring.dbg_ring_idx &= pdev->rx_ring.size_mask; +#endif + + idx = pdev->rx_ring.sw_rd_idx.msdu_payld; + msdu = pdev->rx_ring.buf.netbufs_ring[idx]; + idx++; + idx &= pdev->rx_ring.size_mask; + pdev->rx_ring.sw_rd_idx.msdu_payld = idx; + pdev->rx_ring.fill_cnt--; + return msdu; +} + +static inline adf_nbuf_t +htt_rx_in_order_netbuf_pop( + htt_pdev_handle pdev, u_int32_t paddr) +{ + HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); + pdev->rx_ring.fill_cnt--; + return htt_rx_hash_list_lookup(pdev, paddr); +} + +/* FIX ME: this function applies only to LL rx descs. An equivalent for HL rx descs is needed. */ +#ifdef CHECKSUM_OFFLOAD +static inline +void +htt_set_checksum_result_ll(htt_pdev_handle pdev, adf_nbuf_t msdu, + struct htt_host_rx_desc_base *rx_desc) +{ +#define MAX_IP_VER 2 +#define MAX_PROTO_VAL 4 + struct rx_msdu_start *rx_msdu = &rx_desc->msdu_start; + unsigned int proto = (rx_msdu->tcp_proto) | (rx_msdu->udp_proto << 1); + + /* + * HW supports TCP & UDP checksum offload for ipv4 and ipv6 + */ + static const adf_nbuf_l4_rx_cksum_type_t + cksum_table[][MAX_PROTO_VAL][MAX_IP_VER] = + { + { + /* non-fragmented IP packet */ + /* non TCP/UDP packet */ + { ADF_NBUF_RX_CKSUM_NONE, ADF_NBUF_RX_CKSUM_NONE }, + /* TCP packet */ + { ADF_NBUF_RX_CKSUM_TCP, ADF_NBUF_RX_CKSUM_TCPIPV6}, + /* UDP packet */ + { ADF_NBUF_RX_CKSUM_UDP, ADF_NBUF_RX_CKSUM_UDPIPV6 }, + /* invalid packet type */ + { ADF_NBUF_RX_CKSUM_NONE, ADF_NBUF_RX_CKSUM_NONE }, + }, + { + /* fragmented IP packet */ + { ADF_NBUF_RX_CKSUM_NONE, ADF_NBUF_RX_CKSUM_NONE }, + { ADF_NBUF_RX_CKSUM_NONE, ADF_NBUF_RX_CKSUM_NONE }, + { ADF_NBUF_RX_CKSUM_NONE, ADF_NBUF_RX_CKSUM_NONE }, + { ADF_NBUF_RX_CKSUM_NONE, ADF_NBUF_RX_CKSUM_NONE }, + } + }; + + adf_nbuf_rx_cksum_t cksum = { + cksum_table[rx_msdu->ip_frag][proto][rx_msdu->ipv6_proto], + ADF_NBUF_RX_CKSUM_NONE, + 0 + } ; + + if (cksum.l4_type != (adf_nbuf_l4_rx_cksum_type_t)ADF_NBUF_RX_CKSUM_NONE) { + cksum.l4_result = ((*(u_int32_t *) &rx_desc->attention) & + RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK) ? + ADF_NBUF_RX_CKSUM_NONE : + ADF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY; + } + adf_nbuf_set_rx_cksum(msdu, &cksum ); +#undef MAX_IP_VER +#undef MAX_PROTO_VAL +} + +static inline +void +htt_set_checksum_result_hl(adf_nbuf_t msdu, + struct htt_host_rx_desc_base *rx_desc) +{ + u_int8_t flag = ((u_int8_t*)rx_desc - sizeof(struct hl_htt_rx_ind_base))[HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)]; + int is_ipv6 = flag & HTT_RX_IND_HL_FLAG_IPV6 ? 1:0; + int is_tcp = flag & HTT_RX_IND_HL_FLAG_TCP ? 1:0; + int is_udp = flag & HTT_RX_IND_HL_FLAG_UDP ? 1:0; + + adf_nbuf_rx_cksum_t cksum = { + ADF_NBUF_RX_CKSUM_NONE, + ADF_NBUF_RX_CKSUM_NONE, + 0 + } ; + + switch ((is_udp << 2) | (is_tcp << 1) | (is_ipv6 << 0)) { + case 0x4: + cksum.l4_type = ADF_NBUF_RX_CKSUM_UDP; + break; + case 0x2: + cksum.l4_type = ADF_NBUF_RX_CKSUM_TCP; + break; + case 0x5: + cksum.l4_type = ADF_NBUF_RX_CKSUM_UDPIPV6; + break; + case 0x3: + cksum.l4_type = ADF_NBUF_RX_CKSUM_TCPIPV6; + break; + default: + cksum.l4_type = ADF_NBUF_RX_CKSUM_NONE; + break; + } + if (cksum.l4_type != (adf_nbuf_l4_rx_cksum_type_t)ADF_NBUF_RX_CKSUM_NONE) { + cksum.l4_result = flag & HTT_RX_IND_HL_FLAG_C4_FAILED ? + ADF_NBUF_RX_CKSUM_NONE : ADF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY; + } + adf_nbuf_set_rx_cksum(msdu, &cksum ); +} + +#else +#define htt_set_checksum_result_ll(pdev, msdu, rx_desc) /* no-op */ +#define htt_set_checksum_result_hl(msdu, rx_desc) /* no-op */ +#endif + +#ifdef DEBUG_DMA_DONE +void +htt_rx_print_rx_indication( + adf_nbuf_t rx_ind_msg, + htt_pdev_handle pdev) +{ + u_int32_t *msg_word; + int byte_offset; + int mpdu_range, num_mpdu_range; + + msg_word = (u_int32_t *)adf_nbuf_data(rx_ind_msg); + + adf_os_print("------------------HTT RX IND-----------------------------\n"); + adf_os_print("alloc idx paddr %x (*vaddr) %d\n", + pdev->rx_ring.alloc_idx.paddr, + *pdev->rx_ring.alloc_idx.vaddr); + + adf_os_print("sw_rd_idx msdu_payld %d msdu_desc %d\n", + pdev->rx_ring.sw_rd_idx.msdu_payld, + pdev->rx_ring.sw_rd_idx.msdu_desc); + + adf_os_print("dbg_ring_idx %d\n", pdev->rx_ring.dbg_ring_idx); + + adf_os_print("fill_level %d fill_cnt %d\n",pdev->rx_ring.fill_level, + pdev->rx_ring.fill_cnt); + + adf_os_print("initial msdu_payld %d curr mpdu range %d curr mpdu cnt %d\n", + pdev->rx_ring.dbg_initial_msdu_payld, + pdev->rx_ring.dbg_mpdu_range, + pdev->rx_ring.dbg_mpdu_count); + + /* Print the RX_IND contents */ + + adf_os_print("peer id %x RV %x FV %x ext_tid %x msg_type %x\n", + HTT_RX_IND_PEER_ID_GET(*msg_word), + HTT_RX_IND_REL_VALID_GET(*msg_word), + HTT_RX_IND_FLUSH_VALID_GET(*msg_word), + HTT_RX_IND_EXT_TID_GET(*msg_word), + HTT_T2H_MSG_TYPE_GET(*msg_word)); + + adf_os_print("num_mpdu_ranges %x rel_seq_num_end %x rel_seq_num_start %x\n" + " flush_seq_num_end %x flush_seq_num_start %x\n", + HTT_RX_IND_NUM_MPDU_RANGES_GET(*(msg_word + 1)), + HTT_RX_IND_REL_SEQ_NUM_END_GET(*(msg_word + 1)), + HTT_RX_IND_REL_SEQ_NUM_START_GET(*(msg_word + 1)), + HTT_RX_IND_FLUSH_SEQ_NUM_END_GET(*(msg_word + 1)), + HTT_RX_IND_FLUSH_SEQ_NUM_START_GET(*(msg_word + 1))); + + adf_os_print("fw_rx_desc_bytes %x\n", HTT_RX_IND_FW_RX_DESC_BYTES_GET( + *(msg_word + 2 + HTT_RX_PPDU_DESC_SIZE32))); + + /* receive MSDU desc for current frame */ + byte_offset = HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_FW_RX_DESC_BYTE_OFFSET + + pdev->rx_ind_msdu_byte_idx); + + adf_os_print("msdu byte idx %x msdu desc %x\n", pdev->rx_ind_msdu_byte_idx, + HTT_RX_IND_FW_RX_DESC_BYTES_GET( + *(msg_word + 2 + HTT_RX_PPDU_DESC_SIZE32))); + + num_mpdu_range = HTT_RX_IND_NUM_MPDU_RANGES_GET(*(msg_word + 1)); + + for (mpdu_range = 0; mpdu_range < num_mpdu_range; mpdu_range++) { + enum htt_rx_status status; + int num_mpdus; + + htt_rx_ind_mpdu_range_info( + pdev, rx_ind_msg, mpdu_range, &status, &num_mpdus); + + adf_os_print("mpdu_range %x status %x num_mpdus %x\n", + pdev->rx_ind_msdu_byte_idx, status, num_mpdus); + } + adf_os_print("---------------------------------------------------------\n"); +} +#endif + +#ifdef DEBUG_DMA_DONE +#define MAX_DONE_BIT_CHECK_ITER 5 +#endif + +int +htt_rx_amsdu_pop_ll( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu) +{ + int msdu_len, msdu_chaining = 0; + adf_nbuf_t msdu; + struct htt_host_rx_desc_base *rx_desc; + u_int8_t *rx_ind_data; + u_int32_t *msg_word, num_msdu_bytes; + enum htt_t2h_msg_type msg_type; + + HTT_ASSERT1(htt_rx_ring_elems(pdev) != 0); + rx_ind_data = adf_nbuf_data(rx_ind_msg); + msg_word = (u_int32_t *)rx_ind_data; + + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + + if (adf_os_unlikely(HTT_T2H_MSG_TYPE_RX_FRAG_IND == msg_type)) { + num_msdu_bytes = HTT_RX_FRAG_IND_FW_RX_DESC_BYTES_GET( + *(msg_word + HTT_RX_FRAG_IND_HDR_PREFIX_SIZE32)); + } else { + num_msdu_bytes = HTT_RX_IND_FW_RX_DESC_BYTES_GET( + *(msg_word + HTT_RX_IND_HDR_PREFIX_SIZE32 + + HTT_RX_PPDU_DESC_SIZE32)); + } + msdu = *head_msdu = htt_rx_netbuf_pop(pdev); + while (1) { + int last_msdu, msdu_len_invalid, msdu_chained; + int byte_offset; + + /* + * Set the netbuf length to be the entire buffer length initially, + * so the unmap will unmap the entire buffer. + */ + adf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap(pdev->osdev, msdu, ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap(pdev->osdev, msdu, ADF_OS_DMA_FROM_DEVICE); +#endif + + /* cache consistency has been taken care of by the adf_nbuf_unmap */ + + /* + * Now read the rx descriptor. + * Set the length to the appropriate value. + * Check if this MSDU completes a MPDU. + */ + rx_desc = htt_rx_desc(msdu); + + /* + * Make the netbuf's data pointer point to the payload rather + * than the descriptor. + */ + adf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION); + + /* + * Sanity check - confirm the HW is finished filling in the rx data. + * If the HW and SW are working correctly, then it's guaranteed that + * the HW's MAC DMA is done before this point in the SW. + * To prevent the case that we handle a stale Rx descriptor, just + * assert for now until we have a way to recover. + */ + +#ifdef DEBUG_DMA_DONE + if (adf_os_unlikely(!((*(u_int32_t *) &rx_desc->attention) + & RX_ATTENTION_0_MSDU_DONE_MASK))) { + + int dbg_iter = MAX_DONE_BIT_CHECK_ITER; + + + adf_os_print("malformed frame\n"); + + while (dbg_iter && + (!((*(u_int32_t *) &rx_desc->attention) & + RX_ATTENTION_0_MSDU_DONE_MASK))) { + adf_os_mdelay(1); + + adf_os_invalidate_range((void *)rx_desc, + (void*)((char *)rx_desc + + HTT_RX_STD_DESC_RESERVATION)); + + adf_os_print("debug iter %d success %d\n", dbg_iter, + pdev->rx_ring.dbg_sync_success); + + dbg_iter--; + } + + if (adf_os_unlikely(!((*(u_int32_t *) &rx_desc->attention) + & RX_ATTENTION_0_MSDU_DONE_MASK))) + { + +#ifdef HTT_RX_RESTORE + adf_os_print("RX done bit error detected!\n"); + adf_nbuf_set_next(msdu, NULL); + *tail_msdu = msdu; + pdev->rx_ring.rx_reset = 1; + return msdu_chaining; +#else + process_wma_set_command(0,(int)GEN_PARAM_CRASH_INJECT, + 0, GEN_CMD); + HTT_ASSERT_ALWAYS(0); +#endif + } + pdev->rx_ring.dbg_sync_success++; + adf_os_print("debug iter %d success %d\n", dbg_iter, + pdev->rx_ring.dbg_sync_success); + } +#else + HTT_ASSERT_ALWAYS( + (*(u_int32_t *) &rx_desc->attention) & + RX_ATTENTION_0_MSDU_DONE_MASK); +#endif + /* + * Copy the FW rx descriptor for this MSDU from the rx indication + * message into the MSDU's netbuf. + * HL uses the same rx indication message definition as LL, and + * simply appends new info (fields from the HW rx desc, and the + * MSDU payload itself). + * So, the offset into the rx indication message only has to account + * for the standard offset of the per-MSDU FW rx desc info within + * the message, and how many bytes of the per-MSDU FW rx desc info + * have already been consumed. (And the endianness of the host, + * since for a big-endian host, the rx ind message contents, + * including the per-MSDU rx desc bytes, were byteswapped during + * upload.) + */ + if (pdev->rx_ind_msdu_byte_idx < num_msdu_bytes) { + if (adf_os_unlikely(HTT_T2H_MSG_TYPE_RX_FRAG_IND == msg_type)) { + byte_offset = HTT_ENDIAN_BYTE_IDX_SWAP( + HTT_RX_FRAG_IND_FW_DESC_BYTE_OFFSET); + } else { + byte_offset = HTT_ENDIAN_BYTE_IDX_SWAP( + HTT_RX_IND_FW_RX_DESC_BYTE_OFFSET + + pdev->rx_ind_msdu_byte_idx); + } + + *((u_int8_t *) &rx_desc->fw_desc.u.val) = rx_ind_data[byte_offset]; + /* + * The target is expected to only provide the basic per-MSDU rx + * descriptors. Just to be sure, verify that the target has not + * attached extension data (e.g. LRO flow ID). + */ + /* + * The assertion below currently doesn't work for RX_FRAG_IND + * messages, since their format differs from the RX_IND format + * (no FW rx PPDU desc in the current RX_FRAG_IND message). + * If the RX_FRAG_IND message format is updated to match the + * RX_IND message format, then the following assertion can be + * restored. + */ + //adf_os_assert((rx_ind_data[byte_offset] & FW_RX_DESC_EXT_M) == 0); + pdev->rx_ind_msdu_byte_idx += 1; // or more, if there's ext data + } else { + /* + * When an oversized AMSDU happened, FW will lost some of + * MSDU status - in this case, the FW descriptors provided + * will be less than the actual MSDUs inside this MPDU. + * Mark the FW descriptors so that it will still deliver to + * upper stack, if no CRC error for this MPDU. + * + * FIX THIS - the FW descriptors are actually for MSDUs in + * the end of this A-MSDU instead of the beginning. + */ + *((u_int8_t *) &rx_desc->fw_desc.u.val) = 0; + } + + /* + * TCP/UDP checksum offload support + */ + htt_set_checksum_result_ll(pdev, msdu, rx_desc); + + msdu_len_invalid = (*(u_int32_t *) &rx_desc->attention) & + RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK; + msdu_chained = (((*(u_int32_t *) &rx_desc->frag_info) & + RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK) >> + RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB); + msdu_len = + ((*((u_int32_t *) &rx_desc->msdu_start)) & + RX_MSDU_START_0_MSDU_LENGTH_MASK) >> + RX_MSDU_START_0_MSDU_LENGTH_LSB; + + do { + if (!msdu_len_invalid && !msdu_chained) { +#if defined(PEREGRINE_1_0_ZERO_LEN_PHY_ERR_WAR) + if (msdu_len > 0x3000) { + break; + } +#endif + adf_nbuf_trim_tail( + msdu, HTT_RX_BUF_SIZE - (RX_STD_DESC_SIZE + msdu_len)); + } + } while (0); + + while (msdu_chained--) { + adf_nbuf_t next = + htt_rx_netbuf_pop(pdev); + adf_nbuf_set_pktlen(next, HTT_RX_BUF_SIZE); + msdu_len -= HTT_RX_BUF_SIZE; + adf_nbuf_set_next(msdu, next); + msdu = next; + msdu_chaining = 1; + + if (msdu_chained == 0) { + /* Trim the last one to the correct size - accounting for + * inconsistent HW lengths cuasing length overflows and + * underflows + */ + if (((unsigned)msdu_len) > + ((unsigned)(HTT_RX_BUF_SIZE - RX_STD_DESC_SIZE))) { + msdu_len = (HTT_RX_BUF_SIZE - RX_STD_DESC_SIZE); + } + + adf_nbuf_trim_tail( + next, HTT_RX_BUF_SIZE - (RX_STD_DESC_SIZE + msdu_len)); + } + } + + last_msdu = + ((*(((u_int32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_LAST_MSDU_MASK) >> + RX_MSDU_END_4_LAST_MSDU_LSB; + + if (last_msdu) { + adf_nbuf_set_next(msdu, NULL); + break; + } else { + adf_nbuf_t next = htt_rx_netbuf_pop(pdev); + adf_nbuf_set_next(msdu, next); + msdu = next; + } + } + *tail_msdu = msdu; + + /* + * Don't refill the ring yet. + * First, the elements popped here are still in use - it is + * not safe to overwrite them until the matching call to + * mpdu_desc_list_next. + * Second, for efficiency it is preferable to refill the rx ring + * with 1 PPDU's worth of rx buffers (something like 32 x 3 buffers), + * rather than one MPDU's worth of rx buffers (something like 3 buffers). + * Consequently, we'll rely on the txrx SW to tell us when it is done + * pulling all the PPDU's rx buffers out of the rx ring, and then + * refill it just once. + */ + return msdu_chaining; +} + +int +htt_rx_amsdu_pop_hl( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu) +{ + pdev->rx_desc_size_hl = + (adf_nbuf_data(rx_ind_msg)) + [HTT_ENDIAN_BYTE_IDX_SWAP( + HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)]; + + /* point to the rx desc */ + adf_nbuf_pull_head(rx_ind_msg, + sizeof(struct hl_htt_rx_ind_base)); + *head_msdu = *tail_msdu = rx_ind_msg; + +#ifdef CHECKSUM_OFFLOAD + htt_set_checksum_result_hl(rx_ind_msg, (struct htt_host_rx_desc_base *)(adf_nbuf_data(rx_ind_msg))); +#endif + + adf_nbuf_set_next(*tail_msdu, NULL); + return 0; +} + +int +htt_rx_frag_pop_hl( + htt_pdev_handle pdev, + adf_nbuf_t frag_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu) +{ + adf_nbuf_pull_head(frag_msg, HTT_RX_FRAG_IND_BYTES); + pdev->rx_desc_size_hl = + (adf_nbuf_data(frag_msg)) + [HTT_ENDIAN_BYTE_IDX_SWAP( + HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)]; + + /* point to the rx desc */ + adf_nbuf_pull_head(frag_msg, + sizeof(struct hl_htt_rx_ind_base)); + *head_msdu = *tail_msdu = frag_msg; + + adf_nbuf_set_next(*tail_msdu, NULL); + return 0; +} + +int +htt_rx_offload_msdu_pop_ll( + htt_pdev_handle pdev, + adf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + u_int8_t *fw_desc, + adf_nbuf_t *head_buf, + adf_nbuf_t *tail_buf) +{ + adf_nbuf_t buf; + u_int32_t *msdu_hdr, msdu_len; + + *head_buf = *tail_buf = buf = htt_rx_netbuf_pop(pdev); + /* Fake read mpdu_desc to keep desc ptr in sync */ + htt_rx_mpdu_desc_list_next(pdev, NULL); + adf_nbuf_set_pktlen(buf, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap(pdev->osdev, buf, ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap(pdev->osdev, buf, ADF_OS_DMA_FROM_DEVICE); +#endif + msdu_hdr = (u_int32_t *)adf_nbuf_data(buf); + + /* First dword */ + msdu_len = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_GET(*msdu_hdr); + *peer_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_GET(*msdu_hdr); + + /* Second dword */ + msdu_hdr++; + *vdev_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_GET(*msdu_hdr); + *tid = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_GET(*msdu_hdr); + *fw_desc = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_GET(*msdu_hdr); + + adf_nbuf_pull_head(buf, HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES); + adf_nbuf_set_pktlen(buf, msdu_len); + return 0; +} + +int +htt_rx_offload_paddr_msdu_pop_ll( + htt_pdev_handle pdev, + u_int32_t * msg_word, + int msdu_iter, + int *vdev_id, + int *peer_id, + int *tid, + u_int8_t *fw_desc, + adf_nbuf_t *head_buf, + adf_nbuf_t *tail_buf) +{ + adf_nbuf_t buf; + u_int32_t *msdu_hdr, msdu_len; + u_int32_t * curr_msdu; + u_int32_t paddr; + + curr_msdu = msg_word + (msdu_iter * HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS); + paddr = HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*curr_msdu); + *head_buf = *tail_buf = buf = htt_rx_in_order_netbuf_pop(pdev, paddr); + + if (adf_os_unlikely(NULL == buf)) { + adf_os_print("%s: netbuf pop failed!\n", __FUNCTION__); + return 0; + } + adf_nbuf_set_pktlen(buf, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap(pdev->osdev, buf, ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap(pdev->osdev, buf, ADF_OS_DMA_FROM_DEVICE); +#endif + msdu_hdr = (u_int32_t *)adf_nbuf_data(buf); + + /* First dword */ + msdu_len = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_GET(*msdu_hdr); /* 2 bytes */ + *peer_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_GET(*msdu_hdr); /* 2 bytes */ + + /* Second dword */ + msdu_hdr++; + *vdev_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_GET(*msdu_hdr); /* 1 bytes */ + *tid = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_GET(*msdu_hdr); /* 1 bytes */ + *fw_desc = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_GET(*msdu_hdr); + + adf_nbuf_pull_head(buf, HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES); + adf_nbuf_set_pktlen(buf, msdu_len); + return 0; +} + +int +htt_rx_offload_msdu_pop_hl( + htt_pdev_handle pdev, + adf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + u_int8_t *fw_desc, + adf_nbuf_t *head_buf, + adf_nbuf_t *tail_buf) +{ + return 0; +} + +#ifdef RX_HASH_DEBUG +#define HTT_RX_CHECK_MSDU_COUNT(msdu_count) HTT_ASSERT_ALWAYS(msdu_count) +#else +#define HTT_RX_CHECK_MSDU_COUNT(msdu_count) /* no-op */ +#endif + +/* Return values: 1 - success, 0 - failure */ +int +htt_rx_amsdu_rx_in_order_pop_ll( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu) +{ + adf_nbuf_t msdu, next, prev = NULL; + u_int8_t *rx_ind_data; + u_int32_t *msg_word; + unsigned int msdu_count = 0; + u_int8_t offload_ind; + struct htt_host_rx_desc_base *rx_desc; + + HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); + + rx_ind_data = adf_nbuf_data(rx_ind_msg); + msg_word = (u_int32_t *)rx_ind_data; + + offload_ind = HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_GET(*msg_word); + + /* Get the total number of MSDUs */ + msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1)); + HTT_RX_CHECK_MSDU_COUNT(msdu_count); + + msg_word = (u_int32_t *)(rx_ind_data + HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); + if (offload_ind) { + ol_rx_offload_paddr_deliver_ind_handler(pdev, msdu_count, + msg_word); + *head_msdu = *tail_msdu = NULL; + return 0; + } + + (*head_msdu) = msdu = + htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word)); + + if (adf_os_unlikely(NULL == msdu)) { + adf_os_print("%s: netbuf pop failed!\n", __FUNCTION__); + *tail_msdu = NULL; + return 0; + } + + while (msdu_count > 0) { + + /* + * Set the netbuf length to be the entire buffer length initially, + * so the unmap will unmap the entire buffer. + */ + adf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap(pdev->osdev, msdu, ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap(pdev->osdev, msdu, ADF_OS_DMA_FROM_DEVICE); +#endif + + /* cache consistency has been taken care of by the adf_nbuf_unmap */ + + rx_desc = htt_rx_desc(msdu); + /* + * Make the netbuf's data pointer point to the payload rather + * than the descriptor. + */ + adf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION); + + adf_nbuf_trim_tail( + msdu, HTT_RX_BUF_SIZE - (RX_STD_DESC_SIZE + + HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET(*(msg_word + 1)))); + + *((u_int8_t *) &rx_desc->fw_desc.u.val) = + HTT_RX_IN_ORD_PADDR_IND_FW_DESC_GET(*(msg_word + 1)); + + msdu_count--; + + if (adf_os_unlikely((*((u_int8_t *) &rx_desc->fw_desc.u.val)) & + FW_RX_DESC_MIC_ERR_M)) { + u_int8_t tid = + HTT_RX_IN_ORD_PADDR_IND_EXT_TID_GET(*(u_int32_t *)rx_ind_data); + u_int16_t peer_id = + HTT_RX_IN_ORD_PADDR_IND_PEER_ID_GET(*(u_int32_t *)rx_ind_data); + ol_rx_mic_error_handler(pdev->txrx_pdev, tid, peer_id, rx_desc, msdu); + + htt_rx_desc_frame_free(pdev, msdu); + + /* if this is the last msdu */ + if (!msdu_count) { + /* if this is the only msdu */ + if (!prev) { + *head_msdu = *tail_msdu = NULL; + return 0; + } else { + *tail_msdu = prev; + adf_nbuf_set_next(prev, NULL); + return 1; + } + } else { /* if this is not the last msdu */ + /* get the next msdu */ + msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + next = htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word)); + if (adf_os_unlikely(NULL == next)) { + adf_os_print("%s: netbuf pop failed!\n", __FUNCTION__); + *tail_msdu = NULL; + return 0; + } + + /* if this is not the first msdu, update the next pointer of the + preceding msdu */ + if (prev) { + adf_nbuf_set_next(prev, next); + } else {/* if this is the first msdu, update the head pointer */ + *head_msdu = next; + } + msdu = next; + continue; + } + } + + /* Update checksum result */ + htt_set_checksum_result_ll(pdev, msdu, rx_desc); + + /* check if this is the last msdu */ + if (msdu_count) { + msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + next = htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word)); + if (adf_os_unlikely(NULL == next)) { + adf_os_print("%s: netbuf pop failed!\n", __FUNCTION__); + *tail_msdu = NULL; + return 0; + } + adf_nbuf_set_next(msdu, next); + prev = msdu; + msdu = next; + } + else { + *tail_msdu = msdu; + adf_nbuf_set_next(msdu, NULL); + } + } + + return 1; +} + +/* Util fake function that has same prototype as adf_nbuf_clone that just + * retures the same nbuf + */ +adf_nbuf_t +htt_rx_adf_noclone_buf(adf_nbuf_t buf) +{ + return buf; +} + +/* FIXME: This is a HW definition not provded by HW, where does it go ? */ +enum { + HW_RX_DECAP_FORMAT_RAW = 0, + HW_RX_DECAP_FORMAT_NWIFI, + HW_RX_DECAP_FORMAT_8023, + HW_RX_DECAP_FORMAT_ETH2, +}; + +#define HTT_FCS_LEN (4) + +static void +htt_rx_parse_ppdu_start_status( + struct htt_host_rx_desc_base *rx_desc, + struct ieee80211_rx_status *rs) +{ + + struct rx_ppdu_start *ppdu_start = &rx_desc->ppdu_start; + + /* RSSI */ + rs->rs_rssi = ppdu_start->rssi_comb; + + /* PHY rate */ + /* rs_ratephy coding + [b3 - b0] + 0 -> OFDM + 1 -> CCK + 2 -> HT + 3 -> VHT + OFDM / CCK + [b7 - b4 ] => LSIG rate + [b23 - b8 ] => service field (b'12 static/dynamic, b'14..b'13 BW for VHT) + [b31 - b24 ] => Reserved + HT / VHT + [b15 - b4 ] => SIG A_2 12 LSBs + [b31 - b16] => SIG A_1 16 LSBs + + */ + if (ppdu_start->preamble_type == 0x4 ) { + rs->rs_ratephy = ppdu_start->l_sig_rate_select; + rs->rs_ratephy |= ppdu_start->l_sig_rate << 4; + rs->rs_ratephy |= ppdu_start->service << 8; + } else { + rs->rs_ratephy = + (ppdu_start->preamble_type & 0x4) ? 3 : 2; + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_a_2 & 0xFFF) << 4; + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_a_1 & 0xFFFF) << 16; + } + + return; +} + + +/* This function is used by montior mode code to restitch an MSDU list + * corresponding to an MPDU back into an MPDU by linking up the skbs. + */ +adf_nbuf_t +htt_rx_restitch_mpdu_from_msdus( + htt_pdev_handle pdev, + adf_nbuf_t head_msdu, + struct ieee80211_rx_status *rx_status, + unsigned clone_not_reqd) +{ + + adf_nbuf_t msdu, mpdu_buf, prev_buf, msdu_orig, head_frag_list_cloned; + adf_nbuf_t (*clone_nbuf_fn)(adf_nbuf_t buf); + unsigned decap_format, wifi_hdr_len, sec_hdr_len, msdu_llc_len, + mpdu_buf_len, decap_hdr_pull_bytes, frag_list_sum_len, dir, + is_amsdu, is_first_frag, amsdu_pad, msdu_len; + struct htt_host_rx_desc_base *rx_desc; + char *hdr_desc; + unsigned char *dest; + struct ieee80211_frame *wh; + struct ieee80211_qoscntl*qos; + + /* If this packet does not go up the normal stack path we dont need to + * waste cycles cloning the packets + */ + clone_nbuf_fn = + clone_not_reqd ? htt_rx_adf_noclone_buf : adf_nbuf_clone; + + /* The nbuf has been pulled just beyond the status and points to the + * payload + */ + msdu_orig = head_msdu; + rx_desc = htt_rx_desc(msdu_orig); + + /* Fill out the rx_status from the PPDU start and end fields */ + if (rx_desc->attention.first_mpdu) { + htt_rx_parse_ppdu_start_status(rx_desc, rx_status); + + /* The timestamp is no longer valid - It will be valid only for the + * last MPDU + */ + rx_status->rs_tstamp.tsf = ~0; + } + + decap_format = + GET_FIELD(&rx_desc->msdu_start, RX_MSDU_START_2_DECAP_FORMAT); + + head_frag_list_cloned = NULL; + + /* Easy case - The MSDU status indicates that this is a non-decapped + * packet in RAW mode. + * return + */ + if (decap_format == HW_RX_DECAP_FORMAT_RAW) { + /* Note that this path might suffer from headroom unavailabilty - + * but the RX status is usually enough + */ + mpdu_buf = clone_nbuf_fn(head_msdu); + + prev_buf = mpdu_buf; + + frag_list_sum_len = 0; + is_first_frag = 1; + msdu_len = adf_nbuf_len(mpdu_buf); + + /* Drop the zero-length msdu */ + if (!msdu_len) { + goto mpdu_stitch_fail; + } + msdu_orig = adf_nbuf_next(head_msdu); + + while (msdu_orig) { + + /* TODO: intra AMSDU padding - do we need it ??? */ + msdu = clone_nbuf_fn(msdu_orig); + if (!msdu) { + goto mpdu_stitch_fail; + } + + if (is_first_frag) { + is_first_frag = 0; + head_frag_list_cloned = msdu; + } + + msdu_len = adf_nbuf_len(msdu); + /* Drop the zero-length msdu */ + if (!msdu_len) { + goto mpdu_stitch_fail; + } + + frag_list_sum_len += msdu_len; + + /* Maintain the linking of the cloned MSDUS */ + adf_nbuf_set_next_ext(prev_buf, msdu); + + /* Move to the next */ + prev_buf = msdu; + msdu_orig = adf_nbuf_next(msdu_orig); + } + + /* The last msdu length need be larger than HTT_FCS_LEN */ + if (msdu_len < HTT_FCS_LEN) { + goto mpdu_stitch_fail; + } + + adf_nbuf_trim_tail(prev_buf, HTT_FCS_LEN); + + /* If there were more fragments to this RAW frame */ + if (head_frag_list_cloned) { + adf_nbuf_append_ext_list(mpdu_buf, head_frag_list_cloned, + frag_list_sum_len); + } + + goto mpdu_stitch_done; + } + + /* Decap mode: + * Calculate the amount of header in decapped packet to knock off based + * on the decap type and the corresponding number of raw bytes to copy + * status header + */ + + hdr_desc = &rx_desc->rx_hdr_status[0]; + + /* Base size */ + wifi_hdr_len = sizeof(struct ieee80211_frame); + wh = (struct ieee80211_frame*)hdr_desc; + + dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; + if (dir == IEEE80211_FC1_DIR_DSTODS) { + wifi_hdr_len += 6; + } + + is_amsdu = 0; + if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { + qos = (struct ieee80211_qoscntl*) + (hdr_desc + wifi_hdr_len); + wifi_hdr_len += 2; + + is_amsdu = (qos->i_qos[0] & IEEE80211_QOS_AMSDU); + } + + /* TODO: Any security headers associated with MPDU */ + sec_hdr_len = 0; + + /* MSDU related stuff LLC - AMSDU subframe header etc */ + msdu_llc_len = is_amsdu ? (14 + 8) : 8; + + mpdu_buf_len = wifi_hdr_len + sec_hdr_len + msdu_llc_len; + + /* "Decap" header to remove from MSDU buffer */ + decap_hdr_pull_bytes = 14; + + /* Allocate a new nbuf for holding the 802.11 header retrieved from the + * status of the now decapped first msdu. Leave enough headroom for + * accomodating any radio-tap /prism like PHY header + */ +#define HTT_MAX_MONITOR_HEADER (512) + mpdu_buf = adf_nbuf_alloc(pdev->osdev, + HTT_MAX_MONITOR_HEADER + mpdu_buf_len, + HTT_MAX_MONITOR_HEADER, 4, FALSE); + + if (!mpdu_buf) { + goto mpdu_stitch_fail; + } + + /* Copy the MPDU related header and enc headers into the first buffer + * - Note that there can be a 2 byte pad between heaader and enc header + */ + + prev_buf = mpdu_buf; + dest = adf_nbuf_put_tail(prev_buf, wifi_hdr_len); + if (!dest) { + goto mpdu_stitch_fail; + } + adf_os_mem_copy(dest, hdr_desc, wifi_hdr_len); + hdr_desc += wifi_hdr_len; + + /* NOTE - This padding is present only in the RAW header status - not + * when the MSDU data payload is in RAW format. + */ + /* Skip the "IV pad" */ + if (wifi_hdr_len & 0x3) { + hdr_desc += 2; + } + +#if 0 + dest = adf_nbuf_put_tail(prev_buf, sec_hdr_len); + adf_os_mem_copy(dest, hdr_desc, sec_hdr_len); + hdr_desc += sec_hdr_len; +#endif + + /* The first LLC len is copied into the MPDU buffer */ + frag_list_sum_len = 0; + frag_list_sum_len -= msdu_llc_len; + + msdu_orig = head_msdu; + is_first_frag = 1; + amsdu_pad = 0; + + while (msdu_orig) { + + /* TODO: intra AMSDU padding - do we need it ??? */ + + msdu = clone_nbuf_fn(msdu_orig); + if (!msdu) { + goto mpdu_stitch_fail; + } + + if (is_first_frag) { + is_first_frag = 0; + head_frag_list_cloned = msdu; + } else { + + /* Maintain the linking of the cloned MSDUS */ + adf_nbuf_set_next_ext(prev_buf, msdu); + + /* Reload the hdr ptr only on non-first MSDUs */ + rx_desc = htt_rx_desc(msdu_orig); + hdr_desc = &rx_desc->rx_hdr_status[0]; + + } + + /* Copy this buffers MSDU related status into the prev buffer */ + dest = adf_nbuf_put_tail(prev_buf, msdu_llc_len + amsdu_pad); + dest += amsdu_pad; + adf_os_mem_copy(dest, hdr_desc, msdu_llc_len); + + + /* Push the MSDU buffer beyond the decap header */ + adf_nbuf_pull_head(msdu, decap_hdr_pull_bytes); + frag_list_sum_len += msdu_llc_len + adf_nbuf_len(msdu) + amsdu_pad; + + /* Set up intra-AMSDU pad to be added to start of next buffer - + * AMSDU pad is 4 byte pad on AMSDU subframe */ + amsdu_pad = (msdu_llc_len + adf_nbuf_len(msdu)) & 0x3; + amsdu_pad = amsdu_pad ? ( 4 - amsdu_pad) : 0; + + /* TODO FIXME How do we handle MSDUs that have fraglist - Should + * probably iterate all the frags cloning them along the way and + * and also updating the prev_buf pointer + */ + + /* Move to the next */ + prev_buf = msdu; + msdu_orig = adf_nbuf_next(msdu_orig); + + } + +#if 0 + /* Add in the trailer section - encryption trailer + FCS */ + adf_nbuf_put_tail(prev_buf, HTT_FCS_LEN); + frag_list_sum_len += HTT_FCS_LEN; +#endif + + /* TODO: Convert this to suitable adf routines */ + adf_nbuf_append_ext_list(mpdu_buf, head_frag_list_cloned, + frag_list_sum_len); + +mpdu_stitch_done: + /* Check if this buffer contains the PPDU end status for TSF */ + if (rx_desc->attention.last_mpdu) { + rx_status->rs_tstamp.tsf = rx_desc->ppdu_end.tsf_timestamp; + } + + /* All the nbufs have been linked into the ext list and then unlink the nbuf list */ + if (clone_not_reqd) { + msdu = head_msdu; + while (msdu) { + msdu_orig = msdu; + msdu = adf_nbuf_next(msdu); + adf_nbuf_set_next(msdu_orig, NULL); + } + } + + return (mpdu_buf); + + +mpdu_stitch_fail: + /* Free these alloced buffers and the orig buffers in non-clone case */ + if (!clone_not_reqd) { + /* Free the head buffer */ + if (mpdu_buf) { + adf_nbuf_free(mpdu_buf); + } + + /* Free the partial list */ + while (head_frag_list_cloned) { + msdu = head_frag_list_cloned; + head_frag_list_cloned = adf_nbuf_next_ext(head_frag_list_cloned); + adf_nbuf_free(msdu); + } + } else { + /* Free the alloced head buffer */ + if (decap_format != HW_RX_DECAP_FORMAT_RAW) { + if (mpdu_buf) { + adf_nbuf_free(mpdu_buf); + } + } + + /* Free the orig buffers */ + msdu = head_msdu; + while (msdu) { + msdu_orig = msdu; + msdu = adf_nbuf_next(msdu); + adf_nbuf_free(msdu_orig); + } + } + + return NULL; +} + +int16_t +htt_rx_mpdu_desc_rssi_dbm(htt_pdev_handle pdev, void *mpdu_desc) +{ + /* + * Currently the RSSI is provided only as a field in the + * HTT_T2H_RX_IND message, rather than in each rx descriptor. + */ + return HTT_RSSI_INVALID; +} + + +/* + * htt_rx_amsdu_pop - + * global function pointer that is programmed during attach to point + * to either htt_rx_amsdu_pop_ll or htt_rx_amsdu_pop_hl or + * htt_rx_amsdu_rx_in_order_pop_ll. + */ +int (*htt_rx_amsdu_pop)( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu); + +/* + * htt_rx_frag_pop - + * global function pointer that is programmed during attach to point + * to either htt_rx_amsdu_pop_ll or htt_rx_frag_pop_hl. + */ +int (*htt_rx_frag_pop)( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu); + +int +(*htt_rx_offload_msdu_pop)( + htt_pdev_handle pdev, + adf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + u_int8_t *fw_desc, + adf_nbuf_t *head_buf, + adf_nbuf_t *tail_buf); + +void *(*htt_rx_mpdu_desc_list_next)( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg); + +bool (*htt_rx_mpdu_desc_retry)( + htt_pdev_handle pdev, void *mpdu_desc); + +u_int16_t (*htt_rx_mpdu_desc_seq_num)( + htt_pdev_handle pdev, void *mpdu_desc); + +void (*htt_rx_mpdu_desc_pn)( + htt_pdev_handle pdev, + void *mpdu_desc, + union htt_rx_pn_t *pn, + int pn_len_bits); + +uint8_t (*htt_rx_mpdu_desc_tid)( + htt_pdev_handle pdev, void *mpdu_desc); + +a_bool_t (*htt_rx_msdu_desc_completes_mpdu)( + htt_pdev_handle pdev, void *msdu_desc); + +a_bool_t (*htt_rx_msdu_first_msdu_flag)( + htt_pdev_handle pdev, void *msdu_desc); + +int (*htt_rx_msdu_has_wlan_mcast_flag)( + htt_pdev_handle pdev, void *msdu_desc); + +a_bool_t (*htt_rx_msdu_is_wlan_mcast)( + htt_pdev_handle pdev, void *msdu_desc); + +int (*htt_rx_msdu_is_frag)( + htt_pdev_handle pdev, void *msdu_desc); + +void *(*htt_rx_msdu_desc_retrieve)( + htt_pdev_handle pdev, adf_nbuf_t msdu); + +a_bool_t (*htt_rx_mpdu_is_encrypted)( + htt_pdev_handle pdev, + void *mpdu_desc); + +a_bool_t (*htt_rx_msdu_desc_key_id)( + htt_pdev_handle pdev, + void *mpdu_desc, u_int8_t *key_id); + +a_bool_t (*htt_rx_msdu_chan_info_present)( + htt_pdev_handle pdev, + void *mpdu_desc); + +a_bool_t (*htt_rx_msdu_center_freq)( + htt_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + void *mpdu_desc, + uint16_t *primary_chan_center_freq_mhz, + uint16_t *contig_chan1_center_freq_mhz, + uint16_t *contig_chan2_center_freq_mhz, + uint8_t *phy_mode); + +void * +htt_rx_mpdu_desc_list_next_ll(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + int idx = pdev->rx_ring.sw_rd_idx.msdu_desc; + adf_nbuf_t netbuf = pdev->rx_ring.buf.netbufs_ring[idx]; + pdev->rx_ring.sw_rd_idx.msdu_desc = pdev->rx_ring.sw_rd_idx.msdu_payld; + return (void *) htt_rx_desc(netbuf); +} + +void * +htt_rx_in_ord_mpdu_desc_list_next_ll(htt_pdev_handle pdev, adf_nbuf_t netbuf) +{ + return (void*)htt_rx_desc(netbuf); +} + +void * +htt_rx_mpdu_desc_list_next_hl(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + /* + * for HL, the returned value is not mpdu_desc, + * it's translated hl_rx_desc just after the hl_ind_msg + */ + void *mpdu_desc = (void *) adf_nbuf_data(rx_ind_msg); + + /* for HL AMSDU, we can't point to payload now, because + * hl rx desc is not fixed, we can't retrive the desc + * by minus rx_desc_size when release. keep point to hl rx desc + * now. + */ +#if 0 + adf_nbuf_pull_head(rx_ind_msg, pdev->rx_desc_size_hl); +#endif + + return mpdu_desc; +} + +void * +htt_rx_msdu_desc_retrieve_ll(htt_pdev_handle pdev, adf_nbuf_t msdu) +{ + return htt_rx_desc(msdu); +} + +void * +htt_rx_msdu_desc_retrieve_hl(htt_pdev_handle pdev, adf_nbuf_t msdu) +{ + /* currently for HL AMSDU, we don't point to payload. + * we shift to payload in ol_rx_deliver later + */ + return adf_nbuf_data(msdu); +} + +a_bool_t htt_rx_mpdu_is_encrypted_ll(htt_pdev_handle pdev, void *mpdu_desc) +{ + struct htt_host_rx_desc_base *rx_desc = (struct htt_host_rx_desc_base *) mpdu_desc; + + return (((*((u_int32_t *) &rx_desc->mpdu_start)) & + RX_MPDU_START_0_ENCRYPTED_MASK) >> + RX_MPDU_START_0_ENCRYPTED_LSB) ? A_TRUE : A_FALSE; +} + +a_bool_t htt_rx_mpdu_is_encrypted_hl(htt_pdev_handle pdev, void *mpdu_desc) +{ + if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == A_TRUE) { + /* Fix Me: only for little endian */ + struct hl_htt_rx_desc_base *rx_desc = + (struct hl_htt_rx_desc_base *) mpdu_desc; + + return HTT_WORD_GET(*(u_int32_t*)rx_desc, HTT_HL_RX_DESC_MPDU_ENC); + }else { + /* not first msdu, no encrypt info for hl */ + adf_os_print( + "Error: get encrypted from a not-first msdu.\n"); + adf_os_assert(0); + return -1; + } +} + +a_bool_t +htt_rx_msdu_chan_info_present_ll(htt_pdev_handle pdev, void *mpdu_desc) +{ + return A_FALSE; +} + +a_bool_t +htt_rx_msdu_chan_info_present_hl(htt_pdev_handle pdev, void *mpdu_desc) +{ + if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == A_TRUE && + HTT_WORD_GET(*(u_int32_t*)mpdu_desc, + HTT_HL_RX_DESC_CHAN_INFO_PRESENT)) { + return A_TRUE; + } + + return A_FALSE; +} + +a_bool_t +htt_rx_msdu_center_freq_ll(htt_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + void *mpdu_desc, + uint16_t *primary_chan_center_freq_mhz, + uint16_t *contig_chan1_center_freq_mhz, + uint16_t *contig_chan2_center_freq_mhz, + uint8_t *phy_mode) +{ + if (primary_chan_center_freq_mhz) + *primary_chan_center_freq_mhz = 0; + if (contig_chan1_center_freq_mhz) + *contig_chan1_center_freq_mhz = 0; + if (contig_chan2_center_freq_mhz) + *contig_chan2_center_freq_mhz = 0; + if (phy_mode) + *phy_mode = 0; + return A_FALSE; +} + +a_bool_t +htt_rx_msdu_center_freq_hl(htt_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + void *mpdu_desc, + uint16_t *primary_chan_center_freq_mhz, + uint16_t *contig_chan1_center_freq_mhz, + uint16_t *contig_chan2_center_freq_mhz, + uint8_t *phy_mode) +{ + int pn_len, index; + uint32_t *chan_info; + + index = htt_rx_msdu_is_wlan_mcast(pdev, mpdu_desc) ? + txrx_sec_mcast : txrx_sec_ucast; + + pn_len = (peer ? + pdev->txrx_pdev->rx_pn[peer->security[index].sec_type].len : + 0); + chan_info = (uint32_t*) ((uint8_t*)mpdu_desc + + HTT_HL_RX_DESC_PN_OFFSET + pn_len); + + if (htt_rx_msdu_chan_info_present_hl(pdev, mpdu_desc)) { + if (primary_chan_center_freq_mhz) + *primary_chan_center_freq_mhz = + HTT_WORD_GET(*chan_info, + HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ); + if (contig_chan1_center_freq_mhz) + *contig_chan1_center_freq_mhz = + HTT_WORD_GET(*chan_info, + HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ); + chan_info++; + if (contig_chan2_center_freq_mhz) + *contig_chan2_center_freq_mhz = + HTT_WORD_GET(*chan_info, + HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ); + if (phy_mode) + *phy_mode = + HTT_WORD_GET(*chan_info, + HTT_CHAN_INFO_PHY_MODE); + return A_TRUE; + } + + if (primary_chan_center_freq_mhz) + *primary_chan_center_freq_mhz = 0; + if (contig_chan1_center_freq_mhz) + *contig_chan1_center_freq_mhz = 0; + if (contig_chan2_center_freq_mhz) + *contig_chan2_center_freq_mhz = 0; + if (phy_mode) + *phy_mode = 0; + return A_FALSE; +} + +a_bool_t +htt_rx_msdu_desc_key_id_ll(htt_pdev_handle pdev, void *mpdu_desc, + u_int8_t *key_id) +{ + struct htt_host_rx_desc_base *rx_desc = (struct htt_host_rx_desc_base *) + mpdu_desc; + + if (!htt_rx_msdu_first_msdu_flag_ll(pdev, mpdu_desc)) + return A_FALSE; + + *key_id = ((*(((u_int32_t *) &rx_desc->msdu_end) + 1)) & + (RX_MSDU_END_1_KEY_ID_OCT_MASK >> RX_MSDU_END_1_KEY_ID_OCT_LSB)); + + return A_TRUE; +} + +a_bool_t +htt_rx_msdu_desc_key_id_hl(htt_pdev_handle htt_pdev, void *mpdu_desc, u_int8_t *key_id) +{ + if (htt_rx_msdu_first_msdu_flag_hl(htt_pdev, mpdu_desc) == A_TRUE) { + /* Fix Me: only for little endian */ + struct hl_htt_rx_desc_base *rx_desc = + (struct hl_htt_rx_desc_base *) mpdu_desc; + + *key_id = rx_desc->key_id_oct; + return A_TRUE; + } + + return A_FALSE; +} + +void +htt_rx_desc_frame_free( + htt_pdev_handle htt_pdev, + adf_nbuf_t msdu) +{ + adf_nbuf_free(msdu); +} + +void +htt_rx_msdu_desc_free(htt_pdev_handle htt_pdev, adf_nbuf_t msdu) +{ + /* + * The rx descriptor is in the same buffer as the rx MSDU payload, + * and does not need to be freed separately. + */ +} + +void +htt_rx_msdu_buff_replenish(htt_pdev_handle pdev) +{ + if (adf_os_atomic_dec_and_test(&pdev->rx_ring.refill_ref_cnt)) { + if (!pdev->cfg.is_high_latency) { + int num_to_fill; + num_to_fill = pdev->rx_ring.fill_level - pdev->rx_ring.fill_cnt; + htt_rx_ring_fill_n(pdev, num_to_fill /* okay if <= 0 */); + } + } + adf_os_atomic_inc(&pdev->rx_ring.refill_ref_cnt); +} + +#define AR600P_ASSEMBLE_HW_RATECODE(_rate, _nss, _pream) \ + (((_pream) << 6) | ((_nss) << 4) | (_rate)) + +enum AR600P_HW_RATECODE_PREAM_TYPE { + AR600P_HW_RATECODE_PREAM_OFDM, + AR600P_HW_RATECODE_PREAM_CCK, + AR600P_HW_RATECODE_PREAM_HT, + AR600P_HW_RATECODE_PREAM_VHT, +}; + +#if 0 +void htt_rx_get_vowext_stats(adf_nbuf_t msdu, struct vow_extstats *vowstats) +{ + u_int32_t *ppdu; + u_int8_t preamble_type; + u_int8_t rate = 0, nss=0, bw=0, sgi = 0, mcs = 0, rs_flags=0; + struct htt_host_rx_desc_base *rx_desc; + rx_desc = htt_rx_desc(msdu); + + ppdu = ((u_int32_t *)&rx_desc->ppdu_start); + preamble_type = (ppdu[5] & 0xff000000) >> 24; + switch(preamble_type) + { + /* HT */ + case 8: /* HT w/o TxBF */ + case 9:/* HT w/ TxBF */ + mcs = (u_int8_t)(ppdu[6] & 0x7f); + nss = mcs>>3; + mcs %= 8; + bw = (u_int8_t)((ppdu[6] >> 7) & 1); + sgi = (u_int8_t)((ppdu[6] >> 7) & 1); + rate = AR600P_ASSEMBLE_HW_RATECODE(mcs, nss, AR600P_HW_RATECODE_PREAM_HT); + if (bw) { + rs_flags |= HAL_RX_40; + } + if (sgi) { + rs_flags |= HAL_RX_GI; + } + break; + /* VHT */ + case 0x0c: /* VHT w/o TxBF */ + case 0x0d: /* VHT w/ TxBF */ + mcs = (u_int8_t)((ppdu[7] >> 4) & 0xf); + nss = (u_int8_t)((ppdu[6] >> 10) & 0x7); + bw = (u_int8_t)((ppdu[6] & 3)); + sgi = (u_int8_t)((ppdu[7]) & 1); + rate = AR600P_ASSEMBLE_HW_RATECODE(mcs, nss, AR600P_HW_RATECODE_PREAM_VHT); + break; + } + + vowstats->rx_bw = bw; /* band width 0 - 20 , 1 - 40 , 2 - 80 */ + vowstats->rx_sgi = sgi; /* 1 - short GI */ + vowstats->rx_nss= nss; /* Nss */ + vowstats->rx_mcs = mcs; + vowstats->rx_ratecode = rate; + vowstats->rx_rs_flags= rs_flags; /* rsflags */ + + vowstats->rx_rssi_ctl0 = (ppdu[0] & 0x000000ff); /* rssi ctl0 */ + vowstats->rx_rssi_ctl1 = (ppdu[1] & 0x000000ff); /* rssi ctl1 */ + vowstats->rx_rssi_ctl2 = (ppdu[2] & 0x000000ff); /* rssi ctl2 */ + vowstats->rx_rssi_ext0 = (ppdu[0] & 0x0000ff00) >> 8; /* rssi ext0 */ + vowstats->rx_rssi_ext1 = (ppdu[1] & 0x0000ff00) >> 8; /* rssi ext1 */ + vowstats->rx_rssi_ext2 = (ppdu[2] & 0x0000ff00) >> 8; /* rssi ext2 */ + vowstats->rx_rssi_comb = (ppdu[4] & 0x000000ff); /* rssi comb */ + + ppdu = ((u_int32_t *)&rx_desc->ppdu_end); + /* Time stamp */ + vowstats->rx_macTs = ppdu[16]; + + ppdu = ((u_int32_t *)&rx_desc->attention); + /* more data */ + vowstats->rx_moreaggr = (ppdu[0] & RX_ATTENTION_0_MORE_DATA_MASK); + + /* sequence number */ + ppdu = ((u_int32_t *)&rx_desc->mpdu_start); + vowstats->rx_seqno = (ppdu[0] & 0x0fff0000) >> 16; + +} + +#endif + +/*--- RX In Order Hash Code --------------------------------------------------*/ + +/* Number of buckets in the hash table */ +#define RX_NUM_HASH_BUCKETS 1024 /* This should always be a power of 2 */ +#define RX_NUM_HASH_BUCKETS_MASK (RX_NUM_HASH_BUCKETS - 1) + +/* Number of hash entries allocated per bucket */ +#define RX_ENTRIES_SIZE 10 + +#define RX_HASH_FUNCTION(a) (((a >> 14) ^ (a >> 4)) & RX_NUM_HASH_BUCKETS_MASK) + +#ifdef RX_HASH_DEBUG_LOG +#define RX_HASH_LOG(x) x +#else +#define RX_HASH_LOG(x) /* no-op */ +#endif + +/* Initializes the circular linked list */ +static inline void htt_list_init(htt_list_head * head) +{ + head->prev = head; + head->next = head; +} + +/* Adds entry to the end of the linked list */ +static inline void +htt_list_add_tail(htt_list_head * head, htt_list_node * node) +{ + head->prev->next = node; + node->prev = head->prev; + node->next = head; + head->prev = node; +} + +/* Removes the entry corresponding to the input node from the linked list */ +static inline void +htt_list_remove(htt_list_node * node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; +} + +/* Helper macro to iterate through the linked list */ +#define HTT_LIST_ITER_FWD(iter, head) for( iter=(head)->next; \ + (iter)!=(head); (iter)=(iter)->next ) \ + +#ifdef RX_HASH_DEBUG +/* Hash cookie related macros */ +#define HTT_RX_HASH_COOKIE 0xDEED + +#define HTT_RX_HASH_COOKIE_SET(hash_element)\ + hash_element->cookie = HTT_RX_HASH_COOKIE + +#define HTT_RX_HASH_COOKIE_CHECK(hash_element)\ + HTT_ASSERT_ALWAYS(hash_element->cookie == HTT_RX_HASH_COOKIE) + +/* Hash count related macros */ +#define HTT_RX_HASH_COUNT_INCR(hash_bucket)\ + hash_bucket->count++ + +#define HTT_RX_HASH_COUNT_DECR(hash_bucket)\ + hash_bucket->count-- + +#define HTT_RX_HASH_COUNT_RESET(hash_bucket) hash_bucket->count = 0 + +#define HTT_RX_HASH_COUNT_PRINT(hash_bucket)\ + RX_HASH_LOG(adf_os_print(" count %d\n", hash_bucket->count)) +#else /* RX_HASH_DEBUG */ +/* Hash cookie related macros */ +#define HTT_RX_HASH_COOKIE_SET(hash_element) /* no-op */ +#define HTT_RX_HASH_COOKIE_CHECK(hash_element) /* no-op */ +/* Hash count related macros */ +#define HTT_RX_HASH_COUNT_INCR(hash_bucket) /* no-op */ +#define HTT_RX_HASH_COUNT_DECR(hash_bucket) /* no-op */ +#define HTT_RX_HASH_COUNT_PRINT(hash_bucket) /* no-op */ +#define HTT_RX_HASH_COUNT_RESET(hash_bucket) /* no-op */ +#endif /* RX_HASH_DEBUG */ + + +/* Inserts the given "physical address - network buffer" pair into the + hash table for the given pdev. This function will do the following: + 1. Determine which bucket to insert the pair into + 2. First try to allocate the hash entry for this pair from the pre-allocated + entries list + 3. If there are no more entries in the pre-allocated entries list, allocate + the hash entry from the hash memory pool + Note: this function is not thread-safe + Returns 0 - success, 1 - failure */ +int +htt_rx_hash_list_insert(struct htt_pdev_t *pdev, u_int32_t paddr, + adf_nbuf_t netbuf) +{ + int i; + struct htt_rx_hash_entry * hash_element = NULL; + + i = RX_HASH_FUNCTION(paddr); + + /* Check if there are any entries in the pre-allocated free list */ + if( pdev->rx_ring.hash_table[i]->freepool.next != + &pdev->rx_ring.hash_table[i]->freepool) { + + hash_element = + (struct htt_rx_hash_entry *)((char *)pdev->rx_ring.hash_table[i] + ->freepool.next - + pdev->rx_ring.listnode_offset); + if (adf_os_unlikely(NULL == hash_element)) { + HTT_ASSERT_ALWAYS(0); + return 1; + } + + htt_list_remove(pdev->rx_ring.hash_table[i]->freepool.next); + } + else { + hash_element = adf_os_mem_alloc(pdev->osdev, + sizeof(struct htt_rx_hash_entry)); + if (adf_os_unlikely(NULL == hash_element)) { + HTT_ASSERT_ALWAYS(0); + return 1; + } + hash_element->fromlist = 0; + } + + hash_element->netbuf = netbuf; + hash_element->paddr = paddr; + HTT_RX_HASH_COOKIE_SET(hash_element); + + htt_list_add_tail(&pdev->rx_ring.hash_table[i]->listhead, + &hash_element->listnode); + + RX_HASH_LOG(adf_os_print("rx hash: %s: paddr 0x%x netbuf %p bucket %d\n", + __FUNCTION__, paddr, netbuf,(int)i)); + + HTT_RX_HASH_COUNT_INCR(pdev->rx_ring.hash_table[i]); + HTT_RX_HASH_COUNT_PRINT(pdev->rx_ring.hash_table[i]); + + return 0; +} + +/* Given a physical address this function will find the corresponding network + buffer from the hash table. + Note: this function is not thread-safe */ +adf_nbuf_t +htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, u_int32_t paddr) +{ + u_int32_t i; + htt_list_node * list_iter = NULL; + adf_nbuf_t netbuf = NULL; + struct htt_rx_hash_entry * hash_entry; + + i = RX_HASH_FUNCTION(paddr); + + HTT_LIST_ITER_FWD(list_iter, &pdev->rx_ring.hash_table[i]->listhead) + { + hash_entry = (struct htt_rx_hash_entry *) + ((char *)list_iter - pdev->rx_ring.listnode_offset); + + HTT_RX_HASH_COOKIE_CHECK(hash_entry); + + if (hash_entry->paddr == paddr) { +#ifdef DEBUG_RX_RING_BUFFER + uint32_t index; +#endif + /* Found the entry corresponding to paddr */ + netbuf = hash_entry->netbuf; + htt_list_remove(&hash_entry->listnode); + HTT_RX_HASH_COUNT_DECR(pdev->rx_ring.hash_table[i]); + /* if the rx entry is from the pre-allocated list, return it */ + if (hash_entry->fromlist) { + htt_list_add_tail(&pdev->rx_ring.hash_table[i]->freepool, + &hash_entry->listnode); + } + else { + adf_os_mem_free(hash_entry); + } +#ifdef DEBUG_RX_RING_BUFFER + if (pdev->rx_buff_list) { + index = NBUF_MAP_ID(netbuf); + if (index < HTT_RX_RING_BUFF_DBG_LIST) { + pdev->rx_buff_list[index].in_use = false; + } + } +#endif + break; + } + } + + RX_HASH_LOG(adf_os_print("rx hash: %s: paddr 0x%x, netbuf %p, bucket %d\n", + __FUNCTION__, paddr, netbuf,(int)i)); + HTT_RX_HASH_COUNT_PRINT(pdev->rx_ring.hash_table[i]); + + if (netbuf == NULL) { + adf_os_print("rx hash: %s: no entry found for 0x%x!!!\n", + __FUNCTION__, paddr); + HTT_ASSERT_ALWAYS(0); + } + + return netbuf; +} + +/* Initialization function of the rx buffer hash table. This function will + allocate a hash table of a certain pre-determined size and initialize all + the elements */ +int +htt_rx_hash_init(struct htt_pdev_t *pdev) +{ + int i,j; + + HTT_ASSERT2(IS_PWR2(RX_NUM_HASH_BUCKETS)); + + /* hash table is array of bucket pointers */ + pdev->rx_ring.hash_table = adf_os_mem_alloc( + pdev->osdev, RX_NUM_HASH_BUCKETS * sizeof(struct htt_rx_hash_bucket *)); + + if ( NULL == pdev->rx_ring.hash_table) { + adf_os_print("rx hash table allocation failed!\n"); + return 1; + } + + for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) { + + /* pre-allocate bucket and pool of entries for this bucket */ + pdev->rx_ring.hash_table[i] = adf_os_mem_alloc( + pdev->osdev, (sizeof(struct htt_rx_hash_bucket) + + (RX_ENTRIES_SIZE * sizeof(struct htt_rx_hash_entry)))); + + HTT_RX_HASH_COUNT_RESET(pdev->rx_ring.hash_table[i]); + + /* initialize the hash table buckets */ + htt_list_init(&pdev->rx_ring.hash_table[i]->listhead); + + /* initialize the hash table free pool per bucket */ + htt_list_init(&pdev->rx_ring.hash_table[i]->freepool); + + pdev->rx_ring.hash_table[i]->entries = (struct htt_rx_hash_entry *) + ((uint8_t *)pdev->rx_ring.hash_table[i] + + sizeof(struct htt_rx_hash_bucket)); + + if (NULL == pdev->rx_ring.hash_table[i]->entries) { + adf_os_print("rx hash entries allocation for bucket %d failed!\n", + (int)i); + while (i) { + i--; + adf_os_mem_free(pdev->rx_ring.hash_table[i]); + } + adf_os_mem_free(pdev->rx_ring.hash_table); + pdev->rx_ring.hash_table = NULL; + return 1; + } + + /* initialize the free list with pre-allocated entries */ + for (j = 0; j < RX_ENTRIES_SIZE; j++) { + pdev->rx_ring.hash_table[i]->entries[j].fromlist = 1; + htt_list_add_tail(&pdev->rx_ring.hash_table[i]->freepool, + &pdev->rx_ring.hash_table[i]->entries[j].listnode); + } + } + + pdev->rx_ring.listnode_offset = + adf_os_offsetof(struct htt_rx_hash_entry, listnode); + + return 0; +} + +/* De -initialization function of the rx buffer hash table. This function will + free up the hash table which includes freeing all the pending rx buffers*/ +void +htt_rx_hash_deinit(struct htt_pdev_t *pdev) +{ + + u_int32_t i; + struct htt_rx_hash_entry * hash_entry; + htt_list_node * list_iter = NULL; + + if (NULL == pdev->rx_ring.hash_table) { + return; + } + + for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) { + /* Free the hash entries in hash bucket i */ + list_iter = pdev->rx_ring.hash_table[i]->listhead.next; + while (list_iter != &pdev->rx_ring.hash_table[i]->listhead) { + hash_entry = + (struct htt_rx_hash_entry *)((char *)list_iter - + pdev->rx_ring.listnode_offset); + if (hash_entry->netbuf) { +#ifdef DEBUG_DMA_DONE + adf_nbuf_unmap(pdev->osdev, hash_entry->netbuf, + ADF_OS_DMA_BIDIRECTIONAL); +#else + adf_nbuf_unmap(pdev->osdev, hash_entry->netbuf, + ADF_OS_DMA_FROM_DEVICE); +#endif + adf_nbuf_free(hash_entry->netbuf); + hash_entry->paddr = 0; + } + list_iter = list_iter->next; + + if (!hash_entry->fromlist) { + adf_os_mem_free(hash_entry); + } + } + + adf_os_mem_free(pdev->rx_ring.hash_table[i]); + + } + if (NULL != pdev->rx_ring.hash_table) { + adf_os_mem_free(pdev->rx_ring.hash_table); + pdev->rx_ring.hash_table = NULL; + } +} + +void +htt_rx_hash_dump_table(struct htt_pdev_t *pdev) +{ + u_int32_t i; + struct htt_rx_hash_entry * hash_entry; + htt_list_node * list_iter = NULL; + + for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) { + HTT_LIST_ITER_FWD(list_iter, &pdev->rx_ring.hash_table[i]->listhead) + { + hash_entry = + (struct htt_rx_hash_entry *)((char *)list_iter - + pdev->rx_ring.listnode_offset); + adf_os_print("hash_table[%d]: netbuf %p paddr 0x%x\n", + i, hash_entry->netbuf, hash_entry->paddr); + } + } +} + +/*--- RX In Order Hash Code --------------------------------------------------*/ + +/* move the function to the end of file + * to omit ll/hl pre-declaration + */ +int +htt_rx_attach(struct htt_pdev_t *pdev) +{ + adf_os_dma_addr_t paddr; + if (!pdev->cfg.is_high_latency) { + pdev->rx_ring.size = htt_rx_ring_size(pdev); + HTT_ASSERT2(IS_PWR2(pdev->rx_ring.size)); + pdev->rx_ring.size_mask = pdev->rx_ring.size - 1; + + /* + * Set the initial value for the level to which the rx ring should + * be filled, based on the max throughput and the worst likely + * latency for the host to fill the rx ring with new buffers. + * In theory, this fill level can be dynamically adjusted from + * the initial value set here, to reflect the actual host latency + * rather than a conservative assumption about the host latency. + */ + pdev->rx_ring.fill_level = htt_rx_ring_fill_level(pdev); + + if (pdev->cfg.is_full_reorder_offload) { + if (htt_rx_hash_init(pdev)) { + goto fail1; + } + + /* allocate the target index */ + pdev->rx_ring.target_idx.vaddr = adf_os_mem_alloc_consistent( + pdev->osdev, + sizeof(u_int32_t), + &paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.target_idx), memctx)); + if (!pdev->rx_ring.target_idx.vaddr) { + goto fail1; + } + pdev->rx_ring.target_idx.paddr = paddr; + *pdev->rx_ring.target_idx.vaddr = 0; + } else { + pdev->rx_ring.buf.netbufs_ring = adf_os_mem_alloc( + pdev->osdev, pdev->rx_ring.size * sizeof(adf_nbuf_t)); + if (!pdev->rx_ring.buf.netbufs_ring) { + goto fail1; + } + + pdev->rx_ring.sw_rd_idx.msdu_payld = 0; + pdev->rx_ring.sw_rd_idx.msdu_desc = 0; + } + + pdev->rx_ring.buf.paddrs_ring = adf_os_mem_alloc_consistent( + pdev->osdev, + pdev->rx_ring.size * sizeof(u_int32_t), + &paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.buf), memctx)); + if (!pdev->rx_ring.buf.paddrs_ring) { + goto fail2; + } + pdev->rx_ring.base_paddr = paddr; + pdev->rx_ring.alloc_idx.vaddr = adf_os_mem_alloc_consistent( + pdev->osdev, + sizeof(u_int32_t), + &paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.alloc_idx), memctx)); + if (!pdev->rx_ring.alloc_idx.vaddr) { + goto fail3; + } + pdev->rx_ring.alloc_idx.paddr = paddr; + *pdev->rx_ring.alloc_idx.vaddr = 0; + + /* + * Initialize the Rx refill reference counter to be one so that + * only one thread is allowed to refill the Rx ring. + */ + adf_os_atomic_init(&pdev->rx_ring.refill_ref_cnt); + adf_os_atomic_inc(&pdev->rx_ring.refill_ref_cnt); + + /* Initialize the Rx refill retry timer */ + adf_os_timer_init(pdev->osdev, &pdev->rx_ring.refill_retry_timer, + htt_rx_ring_refill_retry, (void *)pdev, + ADF_DEFERRABLE_TIMER); + + pdev->rx_ring.fill_cnt = 0; +#ifdef DEBUG_DMA_DONE + pdev->rx_ring.dbg_ring_idx = 0; + pdev->rx_ring.dbg_refill_cnt = 0; + pdev->rx_ring.dbg_sync_success = 0; +#endif +#ifdef HTT_RX_RESTORE + pdev->rx_ring.rx_reset = 0; + pdev->rx_ring.htt_rx_restore = 0; +#endif +#ifdef DEBUG_RX_RING_BUFFER + pdev->rx_buff_list = adf_os_mem_alloc(pdev->osdev, + HTT_RX_RING_BUFF_DBG_LIST * + sizeof(struct rx_buf_debug)); + if (!pdev->rx_buff_list) + adf_os_print("HTT: debug RX buffer allocation failed\n"); + else + adf_os_mem_set(pdev->rx_buff_list, 0, HTT_RX_RING_BUFF_DBG_LIST * + sizeof(struct rx_buf_debug)); +#endif + htt_rx_ring_fill_n(pdev, pdev->rx_ring.fill_level); + + if (pdev->cfg.is_full_reorder_offload) { + adf_os_print("HTT: full reorder offload enabled\n"); + htt_rx_amsdu_pop = htt_rx_amsdu_rx_in_order_pop_ll; + htt_rx_frag_pop = htt_rx_amsdu_rx_in_order_pop_ll; + htt_rx_mpdu_desc_list_next = htt_rx_in_ord_mpdu_desc_list_next_ll; + } else { + htt_rx_amsdu_pop = htt_rx_amsdu_pop_ll; + htt_rx_frag_pop = htt_rx_amsdu_pop_ll; + htt_rx_mpdu_desc_list_next = htt_rx_mpdu_desc_list_next_ll; + } + htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_ll; + htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_ll; + htt_rx_mpdu_desc_seq_num = htt_rx_mpdu_desc_seq_num_ll; + htt_rx_mpdu_desc_pn = htt_rx_mpdu_desc_pn_ll; + htt_rx_mpdu_desc_tid = htt_rx_mpdu_desc_tid_ll; + htt_rx_msdu_desc_completes_mpdu = htt_rx_msdu_desc_completes_mpdu_ll; + htt_rx_msdu_first_msdu_flag = htt_rx_msdu_first_msdu_flag_ll; + htt_rx_msdu_has_wlan_mcast_flag = htt_rx_msdu_has_wlan_mcast_flag_ll; + htt_rx_msdu_is_wlan_mcast = htt_rx_msdu_is_wlan_mcast_ll; + htt_rx_msdu_is_frag = htt_rx_msdu_is_frag_ll; + htt_rx_msdu_desc_retrieve = htt_rx_msdu_desc_retrieve_ll; + htt_rx_mpdu_is_encrypted = htt_rx_mpdu_is_encrypted_ll; + htt_rx_msdu_desc_key_id = htt_rx_msdu_desc_key_id_ll; + htt_rx_msdu_chan_info_present = htt_rx_msdu_chan_info_present_ll; + htt_rx_msdu_center_freq = htt_rx_msdu_center_freq_ll; + } else { + pdev->rx_ring.size = HTT_RX_RING_SIZE_MIN; + HTT_ASSERT2(IS_PWR2(pdev->rx_ring.size)); + pdev->rx_ring.size_mask = pdev->rx_ring.size - 1; + + /* host can force ring base address if it wish to do so */ + pdev->rx_ring.base_paddr = 0; + htt_rx_amsdu_pop = htt_rx_amsdu_pop_hl; + htt_rx_frag_pop = htt_rx_frag_pop_hl; + htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_hl; + htt_rx_mpdu_desc_list_next = htt_rx_mpdu_desc_list_next_hl; + htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_hl; + htt_rx_mpdu_desc_seq_num = htt_rx_mpdu_desc_seq_num_hl; + htt_rx_mpdu_desc_pn = htt_rx_mpdu_desc_pn_hl; + htt_rx_mpdu_desc_tid = htt_rx_mpdu_desc_tid_hl; + htt_rx_msdu_desc_completes_mpdu = htt_rx_msdu_desc_completes_mpdu_hl; + htt_rx_msdu_first_msdu_flag = htt_rx_msdu_first_msdu_flag_hl; + htt_rx_msdu_has_wlan_mcast_flag = htt_rx_msdu_has_wlan_mcast_flag_hl; + htt_rx_msdu_is_wlan_mcast = htt_rx_msdu_is_wlan_mcast_hl; + htt_rx_msdu_is_frag = htt_rx_msdu_is_frag_hl; + htt_rx_msdu_desc_retrieve = htt_rx_msdu_desc_retrieve_hl; + htt_rx_mpdu_is_encrypted = htt_rx_mpdu_is_encrypted_hl; + htt_rx_msdu_desc_key_id = htt_rx_msdu_desc_key_id_hl; + htt_rx_msdu_chan_info_present = htt_rx_msdu_chan_info_present_hl; + htt_rx_msdu_center_freq = htt_rx_msdu_center_freq_hl; + + /* + * HL case, the rx descriptor can be different sizes for + * different sub-types of RX_IND messages, e.g. for the + * initial vs. interior vs. final MSDUs within a PPDU. + * The size of each RX_IND message's rx desc is read from + * a field within the RX_IND message itself. + * In the meantime, until the rx_desc_size_hl variable is + * set to its real value based on the RX_IND message, + * initialize it to a reasonable value (zero). + */ + pdev->rx_desc_size_hl = 0; + } + return 0; /* success */ + +fail3: + adf_os_mem_free_consistent( + pdev->osdev, + pdev->rx_ring.size * sizeof(u_int32_t), + pdev->rx_ring.buf.paddrs_ring, + pdev->rx_ring.base_paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.buf), memctx)); + +fail2: + if (pdev->cfg.is_full_reorder_offload) { + adf_os_mem_free_consistent( + pdev->osdev, + sizeof(u_int32_t), + pdev->rx_ring.target_idx.vaddr, + pdev->rx_ring.target_idx.paddr, + adf_os_get_dma_mem_context((&pdev->rx_ring.target_idx), memctx)); + htt_rx_hash_deinit(pdev); + } else { + adf_os_mem_free(pdev->rx_ring.buf.netbufs_ring); + } + +fail1: + return 1; /* failure */ +} + +#ifdef IPA_UC_OFFLOAD +int htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, + unsigned int rx_ind_ring_elements) +{ + /* Allocate RX indication ring */ + /* RX IND ring element + * 4bytes: pointer + * 2bytes: VDEV ID + * 2bytes: length */ + pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr = + adf_os_mem_alloc_consistent(pdev->osdev, + rx_ind_ring_elements * sizeof(struct ipa_uc_rx_ring_elem_t), + &pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_rx_rsc.rx_ind_ring_base), memctx)); + if (!pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { + adf_os_print("%s: RX IND RING alloc fail", __func__); + return -1; + } + + /* RX indication ring size, by bytes */ + pdev->ipa_uc_rx_rsc.rx_ind_ring_size = rx_ind_ring_elements * + sizeof(struct ipa_uc_rx_ring_elem_t); + + /* Allocate RX process done index */ + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr = + adf_os_mem_alloc_consistent(pdev->osdev, + 4, + &pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx), memctx)); + if (!pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr) { + adf_os_print("%s: RX PROC DONE IND alloc fail", __func__); + adf_os_mem_free_consistent(pdev->osdev, + pdev->ipa_uc_rx_rsc.rx_ind_ring_size, + pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_rx_rsc.rx_ind_ring_base), memctx)); + return -2; + } + + return 0; +} + +int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + if (pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { + adf_os_mem_free_consistent(pdev->osdev, + pdev->ipa_uc_rx_rsc.rx_ind_ring_size, + pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_rx_rsc.rx_ind_ring_base), memctx)); + } + + if (pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr) { + adf_os_mem_free_consistent(pdev->osdev, + 4, + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr, + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx), memctx)); + } + + return 0; +} +#endif /* IPA_UC_OFFLOAD */ + diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_t2h.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_t2h.c new file mode 100644 index 000000000000..d768ac01f8f4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_t2h.c @@ -0,0 +1,1045 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_t2h.c + * @brief Provide functions to process target->host HTT messages. + * @details + * This file contains functions related to target->host HTT messages. + * There are two categories of functions: + * 1. A function that receives a HTT message from HTC, and dispatches it + * based on the HTT message type. + * 2. functions that provide the info elements from specific HTT messages. + */ + +#include /* HTC_PACKET */ +#include /* HTT_T2H_MSG_TYPE, etc. */ +#include /* adf_nbuf_t */ + +#include +#include +#include /* htt_tx_status */ + +#include /* HTT_TX_SCHED, etc. */ +#include +#include +#include +#include +#include +#include +#include +#include +/*--- target->host HTT message dispatch function ----------------------------*/ + +#ifndef DEBUG_CREDIT +#define DEBUG_CREDIT 0 +#endif + +static u_int8_t * +htt_t2h_mac_addr_deswizzle(u_int8_t *tgt_mac_addr, u_int8_t *buffer) +{ +#ifdef BIG_ENDIAN_HOST + /* + * The host endianness is opposite of the target endianness. + * To make u_int32_t elements come out correctly, the target->host + * upload has swizzled the bytes in each u_int32_t element of the + * message. + * For byte-array message fields like the MAC address, this + * upload swizzling puts the bytes in the wrong order, and needs + * to be undone. + */ + buffer[0] = tgt_mac_addr[3]; + buffer[1] = tgt_mac_addr[2]; + buffer[2] = tgt_mac_addr[1]; + buffer[3] = tgt_mac_addr[0]; + buffer[4] = tgt_mac_addr[7]; + buffer[5] = tgt_mac_addr[6]; + return buffer; +#else + /* + * The host endianness matches the target endianness - + * we can use the mac addr directly from the message buffer. + */ + return tgt_mac_addr; +#endif +} + +#if defined(CONFIG_HL_SUPPORT) +#define HTT_RX_FRAG_SET_LAST_MSDU(pdev, msg) /* no-op */ +#else +static void HTT_RX_FRAG_SET_LAST_MSDU( + struct htt_pdev_t *pdev, adf_nbuf_t msg) +{ + u_int32_t *msg_word; + unsigned num_msdu_bytes; + adf_nbuf_t msdu; + struct htt_host_rx_desc_base *rx_desc; + int start_idx; + u_int8_t *p_fw_msdu_rx_desc = 0; + + msg_word = (u_int32_t *) adf_nbuf_data(msg); + num_msdu_bytes = HTT_RX_FRAG_IND_FW_RX_DESC_BYTES_GET(*(msg_word + + HTT_RX_FRAG_IND_HDR_PREFIX_SIZE32)); + /* + * 1 word for the message header, + * 1 word to specify the number of MSDU bytes, + * 1 word for every 4 MSDU bytes (round up), + * 1 word for the MPDU range header + */ + pdev->rx_mpdu_range_offset_words = 3 + ((num_msdu_bytes + 3) >> 2); + pdev->rx_ind_msdu_byte_idx = 0; + + p_fw_msdu_rx_desc = ((u_int8_t *)(msg_word) + + HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_FRAG_IND_FW_DESC_BYTE_OFFSET)); + + /* + * Fix for EV126710, in which BSOD occurs due to last_msdu bit + * not set while the next pointer is deliberately set to NULL + * before calling ol_rx_pn_check_base() + * + * For fragment frames, the HW may not have set the last_msdu bit + * in the rx descriptor, but the SW expects this flag to be set, + * since each fragment is in a separate MPDU. Thus, set the flag here, + * just in case the HW didn't. + */ + start_idx = pdev->rx_ring.sw_rd_idx.msdu_payld; + msdu = pdev->rx_ring.buf.netbufs_ring[start_idx]; + adf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); + adf_nbuf_unmap(pdev->osdev, msdu, ADF_OS_DMA_FROM_DEVICE); + rx_desc = htt_rx_desc(msdu); + *((u_int8_t *) &rx_desc->fw_desc.u.val) = *p_fw_msdu_rx_desc; + rx_desc->msdu_end.last_msdu = 1; + adf_nbuf_map(pdev->osdev, msdu, ADF_OS_DMA_FROM_DEVICE); +} +#endif /* CONFIG_HL_SUPPORT */ + +/* Target to host Msg/event handler for low priority messages*/ +void +htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg ) +{ + struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; + u_int32_t *msg_word; + enum htt_t2h_msg_type msg_type; + + msg_word = (u_int32_t *) adf_nbuf_data(htt_t2h_msg); + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + switch (msg_type) { + case HTT_T2H_MSG_TYPE_VERSION_CONF: + { + htc_pm_runtime_put(pdev->htc_pdev); + pdev->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); + pdev->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); + adf_os_print("target uses HTT version %d.%d; host uses %d.%d\n", + pdev->tgt_ver.major, pdev->tgt_ver.minor, + HTT_CURRENT_VERSION_MAJOR, HTT_CURRENT_VERSION_MINOR); + if (pdev->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) { + adf_os_print("*** Incompatible host/target HTT versions!\n"); + } + /* abort if the target is incompatible with the host */ + adf_os_assert(pdev->tgt_ver.major == HTT_CURRENT_VERSION_MAJOR); + if (pdev->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) { + adf_os_print( + "*** Warning: host/target HTT versions are different, " + "though compatible!\n"); + } + break; + } + case HTT_T2H_MSG_TYPE_RX_FLUSH: + { + u_int16_t peer_id; + u_int8_t tid; + int seq_num_start, seq_num_end; + enum htt_rx_flush_action action; + + peer_id = HTT_RX_FLUSH_PEER_ID_GET(*msg_word); + tid = HTT_RX_FLUSH_TID_GET(*msg_word); + seq_num_start = HTT_RX_FLUSH_SEQ_NUM_START_GET(*(msg_word+1)); + seq_num_end = HTT_RX_FLUSH_SEQ_NUM_END_GET(*(msg_word+1)); + action = + HTT_RX_FLUSH_MPDU_STATUS_GET(*(msg_word+1)) == 1 ? + htt_rx_flush_release : htt_rx_flush_discard; + ol_rx_flush_handler( + pdev->txrx_pdev, + peer_id, tid, + seq_num_start, + seq_num_end, + action); + break; + } + case HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND: + { + int msdu_cnt; + msdu_cnt = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_GET(*msg_word); + ol_rx_offload_deliver_ind_handler( + pdev->txrx_pdev, + htt_t2h_msg, + msdu_cnt); + break; + } + case HTT_T2H_MSG_TYPE_RX_FRAG_IND: + { + u_int16_t peer_id; + u_int8_t tid; + + peer_id = HTT_RX_FRAG_IND_PEER_ID_GET(*msg_word); + tid = HTT_RX_FRAG_IND_EXT_TID_GET(*msg_word); + HTT_RX_FRAG_SET_LAST_MSDU(pdev, htt_t2h_msg); + + ol_rx_frag_indication_handler( + pdev->txrx_pdev, + htt_t2h_msg, + peer_id, + tid); + break; + } + case HTT_T2H_MSG_TYPE_RX_ADDBA: + { + u_int16_t peer_id; + u_int8_t tid; + u_int8_t win_sz; + u_int16_t start_seq_num; + + /* + * FOR NOW, the host doesn't need to know the initial + * sequence number for rx aggregation. + * Thus, any value will do - specify 0. + */ + start_seq_num = 0; + peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); + tid = HTT_RX_ADDBA_TID_GET(*msg_word); + win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); + ol_rx_addba_handler( + pdev->txrx_pdev, peer_id, tid, win_sz, start_seq_num, + 0 /* success */); + break; + } + case HTT_T2H_MSG_TYPE_RX_DELBA: + { + u_int16_t peer_id; + u_int8_t tid; + + peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word); + tid = HTT_RX_DELBA_TID_GET(*msg_word); + ol_rx_delba_handler(pdev->txrx_pdev, peer_id, tid); + break; + } + case HTT_T2H_MSG_TYPE_PEER_MAP: + { + u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; + u_int8_t *peer_mac_addr; + u_int16_t peer_id; + u_int8_t vdev_id; + + peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word); + vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word); + peer_mac_addr = htt_t2h_mac_addr_deswizzle( + (u_int8_t *) (msg_word+1), &mac_addr_deswizzle_buf[0]); + + ol_rx_peer_map_handler( + pdev->txrx_pdev, peer_id, vdev_id, peer_mac_addr, 1/*can tx*/); + break; + } + case HTT_T2H_MSG_TYPE_PEER_UNMAP: + { + u_int16_t peer_id; + peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word); + + ol_rx_peer_unmap_handler(pdev->txrx_pdev, peer_id); + break; + } + case HTT_T2H_MSG_TYPE_SEC_IND: + { + u_int16_t peer_id; + enum htt_sec_type sec_type; + int is_unicast; + + peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word); + sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word); + is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word); + msg_word++; /* point to the first part of the Michael key */ + ol_rx_sec_ind_handler( + pdev->txrx_pdev, peer_id, sec_type, is_unicast, msg_word, msg_word+2); + break; + } + case HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND: + { + struct htt_mgmt_tx_compl_ind *compl_msg; + int32_t credit_delta = 1; + + compl_msg = (struct htt_mgmt_tx_compl_ind *)(msg_word + 1); + + if (pdev->cfg.is_high_latency) { + if (!pdev->cfg.default_tx_comp_req) { + adf_os_atomic_add(credit_delta, + &pdev->htt_tx_credit.target_delta); + credit_delta = htt_tx_credit_update(pdev); + } + if (credit_delta) { + ol_tx_target_credit_update(pdev->txrx_pdev, credit_delta); + } + } + OL_TX_DESC_UPDATE_GROUP_CREDIT( + pdev->txrx_pdev, compl_msg->desc_id, 1, 0, compl_msg->status); + ol_tx_single_completion_handler( + pdev->txrx_pdev, compl_msg->status, compl_msg->desc_id); + htc_pm_runtime_put(pdev->htc_pdev); + HTT_TX_SCHED(pdev); + break; + } +#if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF + case HTT_T2H_MSG_TYPE_STATS_CONF: + { + u_int64_t cookie; + u_int8_t *stats_info_list; + + cookie = *(msg_word + 1); + cookie |= ((u_int64_t) (*(msg_word + 2))) << 32; + + stats_info_list = (u_int8_t *) (msg_word + 3); + htc_pm_runtime_put(pdev->htc_pdev); + ol_txrx_fw_stats_handler(pdev->txrx_pdev, cookie, stats_info_list); + break; + } +#endif +#ifndef REMOVE_PKT_LOG + case HTT_T2H_MSG_TYPE_PKTLOG: + { + u_int32_t *pl_hdr; + u_int32_t log_type; + pl_hdr = (msg_word + 1); + log_type = (*(pl_hdr + 1) & ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + if (log_type == PKTLOG_TYPE_TX_CTRL || + (log_type) == PKTLOG_TYPE_TX_STAT || + (log_type) == PKTLOG_TYPE_TX_MSDU_ID || + (log_type) == PKTLOG_TYPE_TX_FRM_HDR || + (log_type) == PKTLOG_TYPE_TX_VIRT_ADDR) { + wdi_event_handler(WDI_EVENT_TX_STATUS, pdev->txrx_pdev, pl_hdr); + } else if ((log_type) == PKTLOG_TYPE_RC_FIND) { + wdi_event_handler(WDI_EVENT_RATE_FIND, pdev->txrx_pdev, pl_hdr); + } else if ((log_type) == PKTLOG_TYPE_RC_UPDATE) { + wdi_event_handler( + WDI_EVENT_RATE_UPDATE, pdev->txrx_pdev, pl_hdr); + } else if ((log_type) == PKTLOG_TYPE_RX_STAT) { + wdi_event_handler(WDI_EVENT_RX_DESC, pdev->txrx_pdev, pl_hdr); + } + break; + } +#endif + case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: + { + u_int32_t htt_credit_delta_abs; + int32_t htt_credit_delta; + int sign; + + htt_credit_delta_abs = HTT_TX_CREDIT_DELTA_ABS_GET(*msg_word); + sign = HTT_TX_CREDIT_SIGN_BIT_GET(*msg_word) ? -1 : 1; + htt_credit_delta = sign * htt_credit_delta_abs; + + if (pdev->cfg.is_high_latency && + !pdev->cfg.default_tx_comp_req) { + adf_os_atomic_add(htt_credit_delta, + &pdev->htt_tx_credit.target_delta); + htt_credit_delta = htt_tx_credit_update(pdev); + } + + HTT_TX_GROUP_CREDIT_PROCESS(pdev, msg_word); + /* + * Call ol_tx_credit_completion even if htt_credit_delta is zero, + * in case there is some global credit already available, but the + * above group credit updates have removed credit restrictions, + * possibly allowing the download scheduler to perform a download + * even if htt_credit_delta == 0. + */ + ol_tx_credit_completion_handler(pdev->txrx_pdev, htt_credit_delta); + break; + } + +#ifdef IPA_UC_OFFLOAD + case HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE: + { + u_int8_t op_code; + u_int16_t len; + u_int8_t *op_msg_buffer; + u_int8_t *msg_start_ptr; + + htc_pm_runtime_put(pdev->htc_pdev); + msg_start_ptr = (u_int8_t *)msg_word; + op_code = HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(*msg_word); + msg_word++; + len = HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_GET(*msg_word); + + op_msg_buffer = adf_os_mem_alloc(NULL, + sizeof(struct htt_wdi_ipa_op_response_t) + len); + if (!op_msg_buffer) { + adf_os_print("OPCODE messsage buffer alloc fail"); + break; + } + adf_os_mem_copy(op_msg_buffer, + msg_start_ptr, + sizeof(struct htt_wdi_ipa_op_response_t) + len); + ol_txrx_ipa_uc_op_response(pdev->txrx_pdev, op_msg_buffer); + break; + } +#endif /* IPA_UC_OFFLOAD */ + case HTT_T2H_MSG_TYPE_RX_OFLD_PKT_ERR: + { + switch (HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(*msg_word)) { + case HTT_RX_OFLD_PKT_ERR_TYPE_MIC_ERR: + { + struct ol_error_info err_info; + struct ol_txrx_vdev_t *vdev; + struct ol_txrx_peer_t *peer; + u_int8_t * pn_ptr; + u_int16_t peer_id = + HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_GET(*(msg_word + 1)); + + peer = ol_txrx_peer_find_by_id(pdev->txrx_pdev, peer_id); + if (!peer) { + adf_os_print("%s: invalid peer id %d\n", __FUNCTION__, + peer_id); + break; + } + vdev = peer->vdev; + + err_info.u.mic_err.vdev_id = vdev->vdev_id; + err_info.u.mic_err.key_id = + HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_GET(*(msg_word + 1)); + adf_os_mem_copy(err_info.u.mic_err.da, + (u_int8_t *)(msg_word + 2), + OL_TXRX_MAC_ADDR_LEN); + adf_os_mem_copy(err_info.u.mic_err.sa, + (u_int8_t *)(msg_word + 4), + OL_TXRX_MAC_ADDR_LEN); + adf_os_mem_copy(err_info.u.mic_err.ta, + peer->mac_addr.raw, OL_TXRX_MAC_ADDR_LEN); + + pn_ptr = (u_int8_t *)&err_info.u.mic_err.pn; + adf_os_mem_copy(pn_ptr, (u_int8_t *)(msg_word + 6), 4); + adf_os_mem_copy((pn_ptr + 4), (u_int8_t *)(msg_word + 7), 2); + + ol_indicate_err(OL_RX_ERR_TKIP_MIC, &err_info); + break; + } + + default: + { + adf_os_print("%s: unhandled error type %d\n", __FUNCTION__, + HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(*msg_word)); + break; + } + } + } + case HTT_T2H_MSG_TYPE_RATE_REPORT: + { + u_int16_t peer_cnt = HTT_PEER_RATE_REPORT_MSG_PEER_COUNT_GET(*msg_word); + u_int16_t i; + struct rate_report_t *report, *each; + + /* Param sanity check */ + if (peer_cnt == 0) { + adf_os_print("RATE REPORT messsage peer_cnt is 0! \n"); + break; + } + + /* At least one peer and no limit apply to peer_cnt here */ + report = adf_os_mem_alloc(NULL, + sizeof(struct rate_report_t) * peer_cnt); + if (!report) { + adf_os_print("RATE REPORT messsage buffer alloc fail. peer_cnt %d\n", + peer_cnt); + break; + } + + each = report; + msg_word++; /* point to the payload */ + for (i = 0; i < peer_cnt; i++) { + each->id = + HTT_PEER_RATE_REPORT_MSG_PEER_ID_GET(*(msg_word + i*2)); + each->phy = + HTT_PEER_RATE_REPORT_MSG_PHY_GET(*(msg_word + i*2)); + each->rate = *(msg_word + i*2 + 1); + each++; + } + ol_txrx_peer_link_status_handler(pdev->txrx_pdev, peer_cnt, report); + + adf_os_mem_free(report); + break; + } + default: + break; + }; + /* Free the indication buffer */ + adf_nbuf_free(htt_t2h_msg); +} + +/* Generic Target to host Msg/event handler for low priority messages + Low priority message are handler in a different handler called from + this function . So that the most likely succes path like Rx and + Tx comp has little code foot print + */ +void +htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) +{ + struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; + adf_nbuf_t htt_t2h_msg = (adf_nbuf_t) pkt->pPktContext; + u_int32_t *msg_word; + enum htt_t2h_msg_type msg_type; + + /* check for successful message reception */ + if (pkt->Status != A_OK) { + if (pkt->Status != A_ECANCELED) { + pdev->stats.htc_err_cnt++; + } + adf_nbuf_free(htt_t2h_msg); + return; + } + +#ifdef HTT_RX_RESTORE +if (adf_os_unlikely(pdev->rx_ring.rx_reset)) { + adf_os_print("rx restore ..\n"); + adf_nbuf_free(htt_t2h_msg); + return; + } +#endif + + /* confirm alignment */ + HTT_ASSERT3((((unsigned long) adf_nbuf_data(htt_t2h_msg)) & 0x3) == 0); + + msg_word = (u_int32_t *) adf_nbuf_data(htt_t2h_msg); + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + switch (msg_type) { + case HTT_T2H_MSG_TYPE_RX_IND: + { + unsigned num_mpdu_ranges; + unsigned num_msdu_bytes; + u_int16_t peer_id; + u_int8_t tid; + + if (adf_os_unlikely(pdev->cfg.is_full_reorder_offload)) { + adf_os_print("HTT_T2H_MSG_TYPE_RX_IND not supported with full " + "reorder offload\n"); + break; + } + peer_id = HTT_RX_IND_PEER_ID_GET(*msg_word); + tid = HTT_RX_IND_EXT_TID_GET(*msg_word); + + if (tid >= OL_TXRX_NUM_EXT_TIDS) { + adf_os_print("HTT_T2H_MSG_TYPE_RX_IND, invalid tid %d\n", tid); + break; + } + + num_msdu_bytes = HTT_RX_IND_FW_RX_DESC_BYTES_GET( + *(msg_word + 2 + HTT_RX_PPDU_DESC_SIZE32)); + /* + * 1 word for the message header, + * HTT_RX_PPDU_DESC_SIZE32 words for the FW rx PPDU desc + * 1 word to specify the number of MSDU bytes, + * 1 word for every 4 MSDU bytes (round up), + * 1 word for the MPDU range header + */ + pdev->rx_mpdu_range_offset_words = + (HTT_RX_IND_HDR_BYTES + num_msdu_bytes + 3) >> 2; + num_mpdu_ranges = HTT_RX_IND_NUM_MPDU_RANGES_GET(*(msg_word + 1)); + pdev->rx_ind_msdu_byte_idx = 0; + + if (pdev->cfg.is_high_latency) { + /* + * TODO: remove copy after stopping reuse skb on HIF layer + * because SDIO HIF may reuse skb before upper layer release it + */ + ol_rx_indication_handler( + pdev->txrx_pdev, htt_t2h_msg, peer_id, tid, + num_mpdu_ranges); + + return; + } else { + ol_rx_indication_handler( + pdev->txrx_pdev, htt_t2h_msg, peer_id, tid, + num_mpdu_ranges); + } + break; + } + case HTT_T2H_MSG_TYPE_TX_COMPL_IND: + { + int num_msdus; + enum htt_tx_status status; + + /* status - no enum translation needed */ + status = HTT_TX_COMPL_IND_STATUS_GET(*msg_word); + num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); + if (num_msdus & 0x1) { + struct htt_tx_compl_ind_base *compl = (void *)msg_word; + + /* + * Host CPU endianness can be different from FW CPU. This + * can result in even and odd MSDU IDs being switched. If + * this happens, copy the switched final odd MSDU ID from + * location payload[size], to location payload[size-1], + * where the message handler function expects to find it + */ + if (compl->payload[num_msdus] != HTT_TX_COMPL_INV_MSDU_ID) { + compl->payload[num_msdus - 1] = + compl->payload[num_msdus]; + } + } + + if (pdev->cfg.is_high_latency) { + if (!pdev->cfg.default_tx_comp_req) { + int credit_delta; + adf_os_atomic_add(num_msdus, + &pdev->htt_tx_credit.target_delta); + credit_delta = htt_tx_credit_update(pdev); + if (credit_delta) { + ol_tx_target_credit_update(pdev->txrx_pdev, + credit_delta); + } + } else { + ol_tx_target_credit_update(pdev->txrx_pdev, num_msdus); + } + } + ol_tx_completion_handler( + pdev->txrx_pdev, num_msdus, status, msg_word + 1); + HTT_TX_SCHED(pdev); + break; + } + case HTT_T2H_MSG_TYPE_RX_PN_IND: + { + u_int16_t peer_id; + u_int8_t tid, pn_ie_cnt, *pn_ie=NULL; + int seq_num_start, seq_num_end; + + /*First dword */ + peer_id = HTT_RX_PN_IND_PEER_ID_GET(*msg_word); + tid = HTT_RX_PN_IND_EXT_TID_GET(*msg_word); + + msg_word++; + /*Second dword */ + seq_num_start = HTT_RX_PN_IND_SEQ_NUM_START_GET(*msg_word); + seq_num_end = HTT_RX_PN_IND_SEQ_NUM_END_GET(*msg_word); + pn_ie_cnt = HTT_RX_PN_IND_PN_IE_CNT_GET(*msg_word); + + msg_word++; + /*Third dword*/ + if (pn_ie_cnt) { + pn_ie = (u_int8_t *)msg_word; + } + + ol_rx_pn_ind_handler( + pdev->txrx_pdev, peer_id, tid, seq_num_start, seq_num_end, + pn_ie_cnt, pn_ie); + + break; + } + case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: + { + int num_msdus; + + num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); + if (num_msdus & 0x1) { + struct htt_tx_compl_ind_base *compl = (void *)msg_word; + + /* + * Host CPU endianness can be different from FW CPU. This + * can result in even and odd MSDU IDs being switched. If + * this happens, copy the switched final odd MSDU ID from + * location payload[size], to location payload[size-1], + * where the message handler function expects to find it + */ + if (compl->payload[num_msdus] != HTT_TX_COMPL_INV_MSDU_ID) { + compl->payload[num_msdus - 1] = + compl->payload[num_msdus]; + } + } + ol_tx_inspect_handler(pdev->txrx_pdev, num_msdus, msg_word + 1); + HTT_TX_SCHED(pdev); + break; + } + case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: + { + u_int16_t peer_id; + u_int8_t tid; + u_int8_t offload_ind, frag_ind; + + if (adf_os_unlikely(!pdev->cfg.is_full_reorder_offload)) { + adf_os_print("HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND not supported" + " when full reorder offload is disabled\n"); + break; + } + + if (adf_os_unlikely(pdev->cfg.is_high_latency)) { + adf_os_print("HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND not supported" + " on high latency\n"); + break; + } + + peer_id = HTT_RX_IN_ORD_PADDR_IND_PEER_ID_GET(*msg_word); + tid = HTT_RX_IN_ORD_PADDR_IND_EXT_TID_GET(*msg_word); + offload_ind = HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_GET(*msg_word); + frag_ind = HTT_RX_IN_ORD_PADDR_IND_FRAG_GET(*msg_word); + + if (adf_os_unlikely(frag_ind)) { + ol_rx_frag_indication_handler(pdev->txrx_pdev, htt_t2h_msg, + peer_id, tid); + break; + } + + ol_rx_in_order_indication_handler(pdev->txrx_pdev, htt_t2h_msg, + peer_id, tid, offload_ind); + break; + } + + default: + htt_t2h_lp_msg_handler(context, htt_t2h_msg); + return ; + + }; + + /* Free the indication buffer */ + adf_nbuf_free(htt_t2h_msg); +} + +/*--- target->host HTT message Info Element access methods ------------------*/ + +/*--- tx completion message ---*/ + +u_int16_t +htt_tx_compl_desc_id(void *iterator, int num) +{ + /* + * The MSDU IDs are packed , 2 per 32-bit word. + * Iterate on them as an array of 16-bit elements. + * This will work fine if the host endianness matches + * the target endianness. + * If the host endianness is opposite of the target's, + * this iterator will produce descriptor IDs in a different + * order than the target inserted them into the message - + * if the target puts in [0, 1, 2, 3, ...] the host will + * put out [1, 0, 3, 2, ...]. + * This is fine, except for the last ID if there are an + * odd number of IDs. But the TX_COMPL_IND handling code + * in the htt_t2h_msg_handler already added a duplicate + * of the final ID, if there were an odd number of IDs, + * so this function can safely treat the IDs as an array + * of 16-bit elements. + */ + return *(((u_int16_t *) iterator) + num); +} + +/*--- rx indication message ---*/ + +int +htt_rx_ind_flush(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) adf_nbuf_data(rx_ind_msg); + return HTT_RX_IND_FLUSH_VALID_GET(*msg_word); +} + +void +htt_rx_ind_flush_seq_num_range( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + unsigned *seq_num_start, + unsigned *seq_num_end) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) adf_nbuf_data(rx_ind_msg); + msg_word++; + *seq_num_start = HTT_RX_IND_FLUSH_SEQ_NUM_START_GET(*msg_word); + *seq_num_end = HTT_RX_IND_FLUSH_SEQ_NUM_END_GET(*msg_word); +} + +int +htt_rx_ind_release(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) adf_nbuf_data(rx_ind_msg); + return HTT_RX_IND_REL_VALID_GET(*msg_word); +} + +void +htt_rx_ind_release_seq_num_range( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + unsigned *seq_num_start, + unsigned *seq_num_end) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) adf_nbuf_data(rx_ind_msg); + msg_word++; + *seq_num_start = HTT_RX_IND_REL_SEQ_NUM_START_GET(*msg_word); + *seq_num_end = HTT_RX_IND_REL_SEQ_NUM_END_GET(*msg_word); +} + +void +htt_rx_ind_mpdu_range_info( + struct htt_pdev_t *pdev, + adf_nbuf_t rx_ind_msg, + int mpdu_range_num, + enum htt_rx_status *status, + int *mpdu_count) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) adf_nbuf_data(rx_ind_msg); + msg_word += pdev->rx_mpdu_range_offset_words + mpdu_range_num; + *status = HTT_RX_IND_MPDU_STATUS_GET(*msg_word); + *mpdu_count = HTT_RX_IND_MPDU_COUNT_GET(*msg_word); +} + +/** + * htt_rx_ind_rssi_dbm() - Return the RSSI provided in a rx indication message. + * + * @pdev: the HTT instance the rx data was received on + * @rx_ind_msg: the netbuf containing the rx indication message + * + * Return the RSSI from an rx indication message in dBm units. + * + * Return: RSSI in dBm, or HTT_INVALID_RSSI + */ +int16_t +htt_rx_ind_rssi_dbm(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + int8_t rssi; + u_int32_t *msg_word; + + msg_word = (u_int32_t *) + (adf_nbuf_data(rx_ind_msg) + HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); + + /* check if the RX_IND message contains valid rx PPDU start info */ + if (!HTT_RX_IND_START_VALID_GET(*msg_word)) { + return HTT_RSSI_INVALID; + } + + rssi = HTT_RX_IND_RSSI_CMB_GET(*msg_word); + return (HTT_TGT_RSSI_INVALID == rssi) ? + HTT_RSSI_INVALID : + rssi; +} + +/** + * htt_rx_ind_rssi_dbm_chain() - Return the RSSI for a chain provided in a rx + * indication message. + * @pdev: the HTT instance the rx data was received on + * @rx_ind_msg: the netbuf containing the rx indication message + * @chain: the index of the chain (0-4) + * + * Return the RSSI for a chain from an rx indication message in dBm units. + * + * Return: RSSI in dBm, or HTT_INVALID_RSSI + */ +int16_t +htt_rx_ind_rssi_dbm_chain(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg, + int8_t chain) +{ + int8_t rssi; + u_int32_t *msg_word; + + if (chain < 0 || chain > 3) { + return HTT_RSSI_INVALID; + } + + msg_word = (u_int32_t *) + (adf_nbuf_data(rx_ind_msg) + HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); + + /* check if the RX_IND message contains valid rx PPDU start info */ + if (!HTT_RX_IND_START_VALID_GET(*msg_word)) { + return HTT_RSSI_INVALID; + } + + msg_word += 1 + chain; + + rssi = HTT_RX_IND_RSSI_PRI20_GET(*msg_word); + return (HTT_TGT_RSSI_INVALID == rssi) ? + HTT_RSSI_INVALID : + rssi; +} + +/** + * htt_rx_ind_legacy_rate() - Return the data rate + * @pdev: the HTT instance the rx data was received on + * @rx_ind_msg: the netbuf containing the rx indication message + * @legacy_rate: (output) the data rate + * The legacy_rate parameter's value depends on the + * legacy_rate_sel value. + * If legacy_rate_sel is 0: + * 0x8: OFDM 48 Mbps + * 0x9: OFDM 24 Mbps + * 0xA: OFDM 12 Mbps + * 0xB: OFDM 6 Mbps + * 0xC: OFDM 54 Mbps + * 0xD: OFDM 36 Mbps + * 0xE: OFDM 18 Mbps + * 0xF: OFDM 9 Mbps + * If legacy_rate_sel is 1: + * 0x8: CCK 11 Mbps long preamble + * 0x9: CCK 5.5 Mbps long preamble + * 0xA: CCK 2 Mbps long preamble + * 0xB: CCK 1 Mbps long preamble + * 0xC: CCK 11 Mbps short preamble + * 0xD: CCK 5.5 Mbps short preamble + * 0xE: CCK 2 Mbps short preamble + * -1 on error. + * @legacy_rate_sel: (output) 0 to indicate OFDM, 1 to indicate CCK. + * -1 on error. + * + * Return the data rate provided in a rx indication message. + */ +void +htt_rx_ind_legacy_rate(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg, + uint8_t *legacy_rate, uint8_t *legacy_rate_sel) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) + (adf_nbuf_data(rx_ind_msg) + HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); + + /* check if the RX_IND message contains valid rx PPDU start info */ + if (!HTT_RX_IND_START_VALID_GET(*msg_word)) { + *legacy_rate = -1; + *legacy_rate_sel = -1; + return; + } + + *legacy_rate = HTT_RX_IND_LEGACY_RATE_GET(*msg_word); + *legacy_rate_sel = HTT_RX_IND_LEGACY_RATE_SEL_GET(*msg_word); +} + +/** + * htt_rx_ind_timestamp() - Return the timestamp + * @pdev: the HTT instance the rx data was received on + * @rx_ind_msg: the netbuf containing the rx indication message + * @timestamp_microsec: (output) the timestamp to microsecond resolution. + * -1 on error. + * @timestamp_submicrosec: the submicrosecond portion of the + * timestamp. -1 on error. + * + * Return the timestamp provided in a rx indication message. + */ +void +htt_rx_ind_timestamp(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg, + uint32_t *timestamp_microsec, uint8_t *timestamp_submicrosec) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) + (adf_nbuf_data(rx_ind_msg) + HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); + + /* check if the RX_IND message contains valid rx PPDU start info */ + if (!HTT_RX_IND_END_VALID_GET(*msg_word)) { + *timestamp_microsec = -1; + *timestamp_submicrosec = -1; + return; + } + + *timestamp_microsec = *(msg_word + 6); + *timestamp_submicrosec = + HTT_RX_IND_TIMESTAMP_SUBMICROSEC_GET(*msg_word); +} + +/** + * htt_rx_ind_tsf32() - Return the TSF timestamp + * @pdev: the HTT instance the rx data was received on + * @rx_ind_msg: the netbuf containing the rx indication message + * + * Return the TSF timestamp provided in a rx indication message. + * + * Return: TSF timestamp + */ +uint32_t +htt_rx_ind_tsf32(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) + (adf_nbuf_data(rx_ind_msg) + HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); + + /* check if the RX_IND message contains valid rx PPDU start info */ + if (!HTT_RX_IND_END_VALID_GET(*msg_word)) { + return -1; + } + + return *(msg_word + 5); +} + +/** + * htt_rx_ind_ext_tid() - Return the extended traffic ID provided in a rx indication message. + * @pdev: the HTT instance the rx data was received on + * @rx_ind_msg: the netbuf containing the rx indication message + * + * Return the extended traffic ID in a rx indication message. + * + * Return: Extended TID + */ +uint8_t +htt_rx_ind_ext_tid(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) + (adf_nbuf_data(rx_ind_msg)); + + return HTT_RX_IND_EXT_TID_GET(*msg_word); +} + +/*--- stats confirmation message ---*/ + +void +htt_t2h_dbg_stats_hdr_parse( + u_int8_t *stats_info_list, + enum htt_dbg_stats_type *type, + enum htt_dbg_stats_status *status, + int *length, + u_int8_t **stats_data) +{ + u_int32_t *msg_word = (u_int32_t *) stats_info_list; + *type = HTT_T2H_STATS_CONF_TLV_TYPE_GET(*msg_word); + *status = HTT_T2H_STATS_CONF_TLV_STATUS_GET(*msg_word); + *length = HTT_T2H_STATS_CONF_TLV_HDR_SIZE + /* header length */ + HTT_T2H_STATS_CONF_TLV_LENGTH_GET(*msg_word); /* data length */ + *stats_data = stats_info_list + HTT_T2H_STATS_CONF_TLV_HDR_SIZE; +} + +void +htt_rx_frag_ind_flush_seq_num_range( + htt_pdev_handle pdev, + adf_nbuf_t rx_frag_ind_msg, + int *seq_num_start, + int *seq_num_end) +{ + u_int32_t *msg_word; + + msg_word = (u_int32_t *) adf_nbuf_data(rx_frag_ind_msg); + msg_word++; + *seq_num_start = HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_START_GET(*msg_word); + *seq_num_end = HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_END_GET(*msg_word); +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c new file mode 100644 index 000000000000..82858c140f46 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c @@ -0,0 +1,911 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file htt_tx.c + * @brief Implement transmit aspects of HTT. + * @details + * This file contains three categories of HTT tx code: + * 1. An abstraction of the tx descriptor, to hide the + * differences between the HL vs. LL tx descriptor. + * 2. Functions for allocating and freeing HTT tx descriptors. + * 3. The function that accepts a tx frame from txrx and sends the + * tx frame to HTC. + */ +#include /* u_int32_t, offsetof, etc. */ +#include /* adf_os_dma_addr_t */ +#include /* adf_os_mem_alloc_consistent,free_consistent */ +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_mdelay */ + +#include /* htt_tx_msdu_desc_t */ +#include /* HTC_HDR_LENGTH */ +#include /* HTCFlushSurpriseRemove */ +#include /* ol_cfg_netbuf_frags_max, etc. */ +#include /* HTT_TX_DESC_VADDR_OFFSET */ +#include /* ol_tx_msdu_id_storage */ +#include + +#ifdef IPA_UC_OFFLOAD +/* IPA Micro controler TX data packet HTT Header Preset */ +/* 31 | 30 29 | 28 | 27 | 26 22 | 21 16 | 15 13 | 12 8 | 7 0 + *------------------------------------------------------------------------------ + * R | CS OL | R | PP | ext TID | vdev ID | pkt type | pkt subtype | msg type + * 0 | 0 | 0 | | 0x1F | 0 | 2 | 0 | 0x01 + *------------------------------------------------------------------------------ + * pkt ID | pkt length + *------------------------------------------------------------------------------ + * frag_desc_ptr + *------------------------------------------------------------------------------ + * peer_id + *------------------------------------------------------------------------------ + */ +#define HTT_IPA_UC_OFFLOAD_TX_HEADER_DEFAULT 0x07C04001 +#endif /* IPA_UC_OFFLOAD */ + +/*--- setup / tear-down functions -------------------------------------------*/ + +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS +u_int32_t *g_dbg_htt_desc_end_addr, *g_dbg_htt_desc_start_addr; +#endif + +int +htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems) +{ + int i, i_int, pool_size; + uint32_t **p; + adf_os_dma_addr_t pool_paddr = {0}; + struct htt_tx_desc_page_t *page_info; + unsigned int num_link = 0; + uint32_t page_size; + + if (pdev->cfg.is_high_latency) { + pdev->tx_descs.size = sizeof(struct htt_host_tx_desc_t); + } else { + pdev->tx_descs.size = + /* + * Start with the size of the base struct + * that actually gets downloaded. + */ + sizeof(struct htt_host_tx_desc_t) + /* + * Add the fragmentation descriptor elements. + * Add the most that the OS may deliver, plus one more in + * case the txrx code adds a prefix fragment (for TSO or + * audio interworking SNAP header) + */ + + (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev)+1) * 8 // 2x u_int32_t + + 4; /* u_int32_t fragmentation list terminator */ + } + + /* + * Make sure tx_descs.size is a multiple of 4-bytes. + * It should be, but round up just to be sure. + */ + pdev->tx_descs.size = (pdev->tx_descs.size + 3) & (~0x3); + pdev->tx_descs.pool_elems = desc_pool_elems; + pdev->tx_descs.alloc_cnt = 0; + + pool_size = pdev->tx_descs.pool_elems * pdev->tx_descs.size; + + /* Calculate required page count first */ + page_size = adf_os_mem_get_page_size(); + pdev->num_pages = pool_size / page_size; + if (pool_size % page_size) + pdev->num_pages++; + + /* Put in as many as possible descriptors into single page */ + /* calculate how many descriptors can put in single page */ + pdev->num_desc_per_page = page_size / pdev->tx_descs.size; + + /* Pages information storage */ + pdev->desc_pages = (struct htt_tx_desc_page_t *)adf_os_mem_alloc( + pdev->osdev, pdev->num_pages * sizeof(struct htt_tx_desc_page_t)); + if (!pdev->desc_pages) { + adf_os_print("HTT Attach, desc page alloc fail"); + goto fail1; + } + + page_info = pdev->desc_pages; + p = (uint32_t **) pdev->tx_descs.freelist; + /* Allocate required memory with multiple pages */ + for(i = 0; i < pdev->num_pages; i++) { + if (pdev->cfg.is_high_latency) { + page_info->page_v_addr_start = adf_os_mem_alloc( + pdev->osdev, page_size); + page_info->page_p_addr = pool_paddr; + if (!page_info->page_v_addr_start) { + page_info = pdev->desc_pages; + for (i_int = 0 ; i_int < i; i_int++) { + page_info = pdev->desc_pages + i_int; + adf_os_mem_free(page_info->page_v_addr_start); + } + goto fail2; + } + } else { + page_info->page_v_addr_start = adf_os_mem_alloc_consistent( + pdev->osdev, + page_size, + &page_info->page_p_addr, + adf_os_get_dma_mem_context((&pdev->tx_descs), memctx)); + if (!page_info->page_v_addr_start) { + page_info = pdev->desc_pages; + for (i_int = 0 ; i_int < i; i_int++) { + page_info = pdev->desc_pages + i_int; + adf_os_mem_free_consistent( + pdev->osdev, + pdev->num_desc_per_page * pdev->tx_descs.size, + page_info->page_v_addr_start, + page_info->page_p_addr, + adf_os_get_dma_mem_context((&pdev->tx_descs), memctx)); + } + goto fail2; + } + } + page_info->page_v_addr_end = page_info->page_v_addr_start + + pdev->num_desc_per_page * pdev->tx_descs.size; + page_info++; + } + + page_info = pdev->desc_pages; + pdev->tx_descs.freelist = (uint32_t *)page_info->page_v_addr_start; + p = (uint32_t **) pdev->tx_descs.freelist; + for(i = 0; i < pdev->num_pages; i++) { + for (i_int = 0; i_int < pdev->num_desc_per_page; i_int++) { + if (i_int == (pdev->num_desc_per_page - 1)) { + /* Last element on this page, should pint next page */ + if (!page_info->page_v_addr_start) { + adf_os_print("over flow num link %d\n", num_link); + goto fail3; + } + page_info++; + *p = (uint32_t *)page_info->page_v_addr_start; + } + else { + *p = (uint32_t *)(((char *) p) + pdev->tx_descs.size); + } + num_link++; + p = (uint32_t **) *p; + /* Last link established exit */ + if (num_link == (pdev->tx_descs.pool_elems - 1)) + break; + } + } + *p = NULL; + + if (pdev->cfg.is_high_latency) { + adf_os_atomic_init(&pdev->htt_tx_credit.target_delta); + adf_os_atomic_init(&pdev->htt_tx_credit.bus_delta); + adf_os_atomic_add(HTT_MAX_BUS_CREDIT,&pdev->htt_tx_credit.bus_delta); + } + return 0; /* success */ + +fail3: + if (pdev->cfg.is_high_latency) { + page_info = pdev->desc_pages; + for (i_int = 0 ; i_int < pdev->num_pages; i_int++) { + page_info = pdev->desc_pages + i_int; + adf_os_mem_free(page_info->page_v_addr_start); + } + } else { + page_info = pdev->desc_pages; + for (i_int = 0 ; i_int < pdev->num_pages; i_int++) { + page_info = pdev->desc_pages + i_int; + adf_os_mem_free_consistent( + pdev->osdev, + pdev->num_desc_per_page * pdev->tx_descs.size, + page_info->page_v_addr_start, + page_info->page_p_addr, + adf_os_get_dma_mem_context((&pdev->tx_descs), memctx)); + } + } + +fail2: + adf_os_mem_free(pdev->desc_pages); + +fail1: + return -1; +} + +void +htt_tx_detach(struct htt_pdev_t *pdev) +{ + unsigned int i; + struct htt_tx_desc_page_t *page_info; + + if (pdev){ + if (pdev->cfg.is_high_latency) { + adf_os_mem_free(pdev->tx_descs.pool_vaddr); + for (i = 0; i < pdev->num_pages; i++) { + page_info = pdev->desc_pages + i; + adf_os_mem_free(page_info->page_v_addr_start); + } + } else { + for (i = 0; i < pdev->num_pages; i++) { + page_info = pdev->desc_pages + i; + adf_os_mem_free_consistent( + pdev->osdev, + pdev->num_desc_per_page * pdev->tx_descs.size, + page_info->page_v_addr_start, + page_info->page_p_addr, + adf_os_get_dma_mem_context((&pdev->tx_descs), memctx)); + } + } + adf_os_mem_free(pdev->desc_pages); + } +} + +/** + * htt_tx_get_paddr() - get physical address for htt desc + * + * Get HTT descriptor physical address from virtaul address + * Find page first and find offset + * + * Return: Physical address of descriptor + */ +adf_os_dma_addr_t htt_tx_get_paddr(htt_pdev_handle pdev, char *target_vaddr) +{ + unsigned int i; + struct htt_tx_desc_page_t *page_info = NULL; + + for (i = 0; i < pdev->num_pages; i++) { + page_info = pdev->desc_pages + i; + if (!page_info || !page_info->page_v_addr_start) { + adf_os_assert(0); + return 0; + } + if ((target_vaddr >= page_info->page_v_addr_start) && + (target_vaddr <= page_info->page_v_addr_end)) + break; + } + if (!page_info || !page_info->page_v_addr_start || + !page_info->page_p_addr) { + adf_os_assert(0); + return 0; + } + + return page_info->page_p_addr + + (adf_os_dma_addr_t)(target_vaddr - page_info->page_v_addr_start); +} + +/*--- descriptor allocation functions ---------------------------------------*/ + +void * +htt_tx_desc_alloc(htt_pdev_handle pdev, u_int32_t *paddr_lo) +{ + struct htt_host_tx_desc_t *htt_host_tx_desc; /* includes HTC hdr space */ + struct htt_tx_msdu_desc_t *htt_tx_desc; /* doesn't include HTC hdr */ + + htt_host_tx_desc = (struct htt_host_tx_desc_t *) pdev->tx_descs.freelist; + if (! htt_host_tx_desc) { + return NULL; /* pool is exhausted */ + } + htt_tx_desc = &htt_host_tx_desc->align32.tx_desc; + + if (pdev->tx_descs.freelist) { + pdev->tx_descs.freelist = *((u_int32_t **) pdev->tx_descs.freelist); + pdev->tx_descs.alloc_cnt++; + } + /* + * For LL, set up the fragmentation descriptor address. + * Currently, this HTT tx desc allocation is performed once up front. + * If this is changed to have the allocation done during tx, then it + * would be helpful to have separate htt_tx_desc_alloc functions for + * HL vs. LL, to remove the below conditional branch. + */ + if (!pdev->cfg.is_high_latency) { + u_int32_t *fragmentation_descr_field_ptr; + + fragmentation_descr_field_ptr = (u_int32_t *) + ((u_int32_t *) htt_tx_desc) + + HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD; + /* + * The fragmentation descriptor is allocated from consistent mem. + * Therefore, we can use the address directly rather than having + * to map it from a virtual/CPU address to a physical/bus address. + */ + *fragmentation_descr_field_ptr = + (uint32_t)htt_tx_get_paddr(pdev, (char *)htt_tx_desc) + + HTT_TX_DESC_LEN; + } + /* + * Include the headroom for the HTC frame header when specifying the + * physical address for the HTT tx descriptor. + */ + *paddr_lo = (uint32_t)htt_tx_get_paddr(pdev, (char *)htt_host_tx_desc); + /* + * The allocated tx descriptor space includes headroom for a + * HTC frame header. Hide this headroom, so that we don't have + * to jump past the headroom each time we program a field within + * the tx desc, but only once when we download the tx desc (and + * the headroom) to the target via HTC. + * Skip past the headroom and return the address of the HTT tx desc. + */ + return (void *) htt_tx_desc; +} + +void +htt_tx_desc_free(htt_pdev_handle pdev, void *tx_desc) +{ + char *htt_host_tx_desc = tx_desc; + /* rewind over the HTC frame header space */ + htt_host_tx_desc -= offsetof(struct htt_host_tx_desc_t, align32.tx_desc); + *((u_int32_t **) htt_host_tx_desc) = pdev->tx_descs.freelist; + pdev->tx_descs.freelist = (u_int32_t *) htt_host_tx_desc; + pdev->tx_descs.alloc_cnt--; +} + +/*--- descriptor field access methods ---------------------------------------*/ + +void htt_tx_desc_frags_table_set( + htt_pdev_handle pdev, + void *htt_tx_desc, + u_int32_t paddr, + int reset) +{ + u_int32_t *fragmentation_descr_field_ptr; + + /* fragments table only applies to LL systems */ + if (pdev->cfg.is_high_latency) { + return; + } + fragmentation_descr_field_ptr = (u_int32_t *) + ((u_int32_t *) htt_tx_desc) + HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD; + if (reset) { + *fragmentation_descr_field_ptr = + (uint32_t)htt_tx_get_paddr(pdev, (char *)htt_tx_desc) + HTT_TX_DESC_LEN; + } else { + *fragmentation_descr_field_ptr = paddr; + } +} + +/* PUT THESE AS INLINE IN ol_htt_tx_api.h */ + +void +htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc) +{ +} + +#if !defined(CONFIG_HL_SUPPORT) +void +htt_tx_pending_discard(htt_pdev_handle pdev) +{ + HTCFlushSurpriseRemove(pdev->htc_pdev); +} +#endif + +void +htt_tx_desc_flag_batch_more(htt_pdev_handle pdev, void *desc) +{ +} + +/*--- tx send function ------------------------------------------------------*/ + +#ifdef ATH_11AC_TXCOMPACT + +/* Scheduling the Queued packets in HTT which could not be sent out because of No CE desc*/ +void +htt_tx_sched(htt_pdev_handle pdev) +{ + adf_nbuf_t msdu; + int download_len = pdev->download_len; + int packet_len; + + HTT_TX_NBUF_QUEUE_REMOVE(pdev, msdu); + while (msdu != NULL){ + int not_accepted; + /* packet length includes HTT tx desc frag added above */ + packet_len = adf_nbuf_len(msdu); + if (packet_len < download_len) { + /* + * This case of packet length being less than the nominal download + * length can happen for a couple reasons: + * In HL, the nominal download length is a large artificial value. + * In LL, the frame may not have the optional header fields + * accounted for in the nominal download size (LLC/SNAP header, + * IPv4 or IPv6 header). + */ + download_len = packet_len; + } + + + not_accepted = HTCSendDataPkt( + pdev->htc_pdev, msdu, pdev->htc_endpoint, download_len); + if (not_accepted) { + HTT_TX_NBUF_QUEUE_INSERT_HEAD(pdev, msdu); + return; + } + HTT_TX_NBUF_QUEUE_REMOVE(pdev, msdu); + } +} + + +int +htt_tx_send_std( + htt_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id) +{ + + int download_len = pdev->download_len; + + int packet_len; + + /* packet length includes HTT tx desc frag added above */ + packet_len = adf_nbuf_len(msdu); + if (packet_len < download_len) { + /* + * This case of packet length being less than the nominal download + * length can happen for a couple reasons: + * In HL, the nominal download length is a large artificial value. + * In LL, the frame may not have the optional header fields + * accounted for in the nominal download size (LLC/SNAP header, + * IPv4 or IPv6 header). + */ + download_len = packet_len; + } + + if (adf_nbuf_queue_len(&pdev->txnbufq) > 0) { + HTT_TX_NBUF_QUEUE_ADD(pdev, msdu); + htt_tx_sched(pdev); + return 0; + } + + adf_nbuf_trace_update(msdu, "HT:T:"); + if (HTCSendDataPkt(pdev->htc_pdev, msdu, pdev->htc_endpoint, download_len)){ + HTT_TX_NBUF_QUEUE_ADD(pdev, msdu); + } + + return 0; /* success */ + +} + +adf_nbuf_t +htt_tx_send_batch(htt_pdev_handle pdev, adf_nbuf_t head_msdu, int num_msdus) +{ + adf_os_print("*** %s curently only applies for HL systems\n", __func__); + adf_os_assert(0); + return head_msdu; + +} + +int +htt_tx_send_nonstd( + htt_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id, + enum htt_pkt_type pkt_type) +{ + int download_len; + + /* + * The pkt_type could be checked to see what L2 header type is present, + * and then the L2 header could be examined to determine its length. + * But for simplicity, just use the maximum possible header size, + * rather than computing the actual header size. + */ + download_len = + sizeof(struct htt_host_tx_desc_t) + + HTT_TX_HDR_SIZE_OUTER_HDR_MAX + /* worst case */ + HTT_TX_HDR_SIZE_802_1Q + + HTT_TX_HDR_SIZE_LLC_SNAP + + ol_cfg_tx_download_size(pdev->ctrl_pdev); + adf_os_assert(download_len <= pdev->download_len); + return htt_tx_send_std(pdev, msdu, msdu_id); +} + +#else /*ATH_11AC_TXCOMPACT*/ + +#ifdef QCA_TX_HTT2_SUPPORT +static inline HTC_ENDPOINT_ID +htt_tx_htt2_get_ep_id( + htt_pdev_handle pdev, + adf_nbuf_t msdu) +{ + /* + * TX HTT2 service mainly for small sized frame and check if + * this candidate frame allow or not. + */ + if ((pdev->htc_tx_htt2_endpoint != ENDPOINT_UNUSED) && + adf_nbuf_get_tx_parallel_dnload_frm(msdu) && + (adf_nbuf_len(msdu) < pdev->htc_tx_htt2_max_size)) + return pdev->htc_tx_htt2_endpoint; + else + return pdev->htc_endpoint; +} +#else +#define htt_tx_htt2_get_ep_id(pdev, msdu) (pdev->htc_endpoint) +#endif /* QCA_TX_HTT2_SUPPORT */ + +static inline int +htt_tx_send_base( + htt_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id, + int download_len, + u_int8_t more_data) +{ + struct htt_host_tx_desc_t *htt_host_tx_desc; + struct htt_htc_pkt *pkt; + int packet_len; + HTC_ENDPOINT_ID ep_id; + + /* + * The HTT tx descriptor was attached as the prefix fragment to the + * msdu netbuf during the call to htt_tx_desc_init. + * Retrieve it so we can provide its HTC header space to HTC. + */ + htt_host_tx_desc = (struct htt_host_tx_desc_t *) + adf_nbuf_get_frag_vaddr(msdu, 0); + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) { + return 1; /* failure */ + } + + pkt->msdu_id = msdu_id; + pkt->pdev_ctxt = pdev->txrx_pdev; + + /* packet length includes HTT tx desc frag added above */ + packet_len = adf_nbuf_len(msdu); + if (packet_len < download_len) { + /* + * This case of packet length being less than the nominal download + * length can happen for a couple reasons: + * In HL, the nominal download length is a large artificial value. + * In LL, the frame may not have the optional header fields + * accounted for in the nominal download size (LLC/SNAP header, + * IPv4 or IPv6 header). + */ + download_len = packet_len; + } + + ep_id = htt_tx_htt2_get_ep_id(pdev, msdu); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + pdev->tx_send_complete_part2, + (unsigned char *) htt_host_tx_desc, + download_len - HTC_HDR_LENGTH, + ep_id, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msdu); + + adf_nbuf_trace_update(msdu, "HT:T:"); + HTCSendDataPkt(pdev->htc_pdev, &pkt->htc_pkt, more_data); + + return 0; /* success */ +} + +adf_nbuf_t +htt_tx_send_batch( + htt_pdev_handle pdev, + adf_nbuf_t head_msdu, int num_msdus) +{ + adf_nbuf_t rejected = NULL; + u_int16_t *msdu_id_storage; + u_int16_t msdu_id; + adf_nbuf_t msdu; + /* + * FOR NOW, iterate through the batch, sending the frames singly. + * Eventually HTC and HIF should be able to accept a batch of + * data frames rather than singles. + */ + msdu = head_msdu; + while (num_msdus--) + { + adf_nbuf_t next_msdu = adf_nbuf_next(msdu); + msdu_id_storage = ol_tx_msdu_id_storage(msdu); + msdu_id = *msdu_id_storage; + + /* htt_tx_send_base returns 0 as success and 1 as failure */ + if (htt_tx_send_base(pdev, msdu, msdu_id, pdev->download_len, + num_msdus)) { + adf_nbuf_set_next(msdu, rejected); + rejected = msdu; + } + msdu = next_msdu; + } + return rejected; +} + +int +htt_tx_send_nonstd( + htt_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id, + enum htt_pkt_type pkt_type) +{ + int download_len; + + /* + * The pkt_type could be checked to see what L2 header type is present, + * and then the L2 header could be examined to determine its length. + * But for simplicity, just use the maximum possible header size, + * rather than computing the actual header size. + */ + download_len = + sizeof(struct htt_host_tx_desc_t) + + HTT_TX_HDR_SIZE_OUTER_HDR_MAX + /* worst case */ + HTT_TX_HDR_SIZE_802_1Q + + HTT_TX_HDR_SIZE_LLC_SNAP + + ol_cfg_tx_download_size(pdev->ctrl_pdev); + return htt_tx_send_base(pdev, msdu, msdu_id, download_len, 0); +} + +int +htt_tx_send_std( + htt_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id) +{ + return htt_tx_send_base(pdev, msdu, msdu_id, pdev->download_len, 0); +} + +#endif /*ATH_11AC_TXCOMPACT*/ +#ifdef HTT_DBG +void +htt_tx_desc_display(void *tx_desc) +{ + struct htt_tx_msdu_desc_t *htt_tx_desc; + + htt_tx_desc = (struct htt_tx_msdu_desc_t *) tx_desc; + + /* only works for little-endian */ + adf_os_print("HTT tx desc (@ %p):\n", htt_tx_desc); + adf_os_print(" msg type = %d\n", htt_tx_desc->msg_type); + adf_os_print(" pkt subtype = %d\n", htt_tx_desc->pkt_subtype); + adf_os_print(" pkt type = %d\n", htt_tx_desc->pkt_type); + adf_os_print(" vdev ID = %d\n", htt_tx_desc->vdev_id); + adf_os_print(" ext TID = %d\n", htt_tx_desc->ext_tid); + adf_os_print(" postponed = %d\n", htt_tx_desc->postponed); + adf_os_print(" batch more = %d\n", htt_tx_desc->more_in_batch); + adf_os_print(" length = %d\n", htt_tx_desc->len); + adf_os_print(" id = %d\n", htt_tx_desc->id); + adf_os_print(" frag desc addr = %#x\n", htt_tx_desc->frags_desc_ptr); + if (htt_tx_desc->frags_desc_ptr) { + int frag = 0; + u_int32_t *base; + u_int32_t addr; + u_int32_t len; + do { + base = ((u_int32_t *) htt_tx_desc->frags_desc_ptr) + (frag * 2); + addr = *base; + len = *(base + 1); + if (addr) { + adf_os_print( + " frag %d: addr = %#x, len = %d\n", frag, addr, len); + } + frag++; + } while (addr); + } +} +#endif + +#ifdef IPA_UC_OFFLOAD +int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, + unsigned int uc_tx_buf_sz, + unsigned int uc_tx_buf_cnt, + unsigned int uc_tx_partition_base) +{ + unsigned int tx_buffer_count; + adf_nbuf_t buffer_vaddr; + u_int32_t buffer_paddr; + u_int32_t *header_ptr; + u_int32_t *ring_vaddr; + int return_code = 0; + + /* Allocate CE Write Index WORD */ + pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr = + adf_os_mem_alloc_consistent(pdev->osdev, + 4, + &pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_ce_idx), memctx)); + if (!pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr) { + adf_os_print("%s: CE Write Index WORD alloc fail", __func__); + return -1; + } + + /* Allocate TX COMP Ring */ + pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr = + adf_os_mem_alloc_consistent(pdev->osdev, + uc_tx_buf_cnt * 4, + &pdev->ipa_uc_tx_rsc.tx_comp_base.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_comp_base), memctx)); + if (!pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr) { + adf_os_print("%s: TX COMP ring alloc fail", __func__); + return_code = -2; + goto free_tx_ce_idx; + } + + adf_os_mem_zero(pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr, uc_tx_buf_cnt * 4); + + /* Allocate TX BUF vAddress Storage */ + pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg = + (adf_nbuf_t *)adf_os_mem_alloc(pdev->osdev, + uc_tx_buf_cnt * sizeof(adf_nbuf_t)); + if (!pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg) { + adf_os_print("%s: TX BUF POOL vaddr storage alloc fail", + __func__); + return_code = -3; + goto free_tx_comp_base; + } + adf_os_mem_zero(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg, + uc_tx_buf_cnt * sizeof(adf_nbuf_t)); + + ring_vaddr = pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr; + /* Allocate TX buffers as many as possible */ + for (tx_buffer_count = 0; + tx_buffer_count < (uc_tx_buf_cnt - 1); + tx_buffer_count++) { + buffer_vaddr = adf_nbuf_alloc(pdev->osdev, + uc_tx_buf_sz, 0, 4, FALSE); + if (!buffer_vaddr) + { + adf_os_print("%s: TX BUF alloc fail, allocated buffer count %d", + __func__, tx_buffer_count); + break; + } + + /* Init buffer */ + adf_os_mem_zero(adf_nbuf_data(buffer_vaddr), uc_tx_buf_sz); + header_ptr = (u_int32_t *)adf_nbuf_data(buffer_vaddr); + + *header_ptr = HTT_IPA_UC_OFFLOAD_TX_HEADER_DEFAULT; + header_ptr++; + *header_ptr |= ((u_int16_t)uc_tx_partition_base + tx_buffer_count) << 16; + + adf_nbuf_map(pdev->osdev, buffer_vaddr, ADF_OS_DMA_BIDIRECTIONAL); + buffer_paddr = adf_nbuf_get_frag_paddr_lo(buffer_vaddr, 0); + header_ptr++; + *header_ptr = (u_int32_t)(buffer_paddr + 16); + + header_ptr++; + *header_ptr = 0xFFFFFFFF; + + /* FRAG Header */ + header_ptr++; + *header_ptr = buffer_paddr + 32; + + *ring_vaddr = buffer_paddr; + pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[tx_buffer_count] = + buffer_vaddr; + /* Memory barrier to ensure actual value updated */ + + ring_vaddr++; + } + + pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count; + + return 0; + +free_tx_comp_base: + adf_os_mem_free_consistent(pdev->osdev, + ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev) * 4, + pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr, + pdev->ipa_uc_tx_rsc.tx_comp_base.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_comp_base), memctx)); +free_tx_ce_idx: + adf_os_mem_free_consistent(pdev->osdev, + 4, + pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr, + pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_ce_idx), memctx)); + return return_code; +} + +int htt_tx_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + u_int16_t idx; + + if (pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr) { + adf_os_mem_free_consistent(pdev->osdev, + 4, + pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr, + pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_ce_idx), memctx)); + } + + if (pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr) { + adf_os_mem_free_consistent(pdev->osdev, + ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev) * 4, + pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr, + pdev->ipa_uc_tx_rsc.tx_comp_base.paddr, + adf_os_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_comp_base), memctx)); + } + + /* Free each single buffer */ + for(idx = 0; idx < pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt; idx++) { + if (pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx]) { + adf_nbuf_unmap(pdev->osdev, + pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx], + ADF_OS_DMA_FROM_DEVICE); + adf_nbuf_free(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx]); + } + } + + /* Free storage */ + adf_os_mem_free(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg); + + return 0; +} +#endif /* IPA_UC_OFFLOAD */ + +int htt_tx_credit_update(struct htt_pdev_t *pdev) +{ + int credit_delta; + credit_delta = MIN(adf_os_atomic_read(&pdev->htt_tx_credit.target_delta), + adf_os_atomic_read(&pdev->htt_tx_credit.bus_delta)); + if (credit_delta) { + adf_os_atomic_add(-credit_delta, &pdev->htt_tx_credit.target_delta); + adf_os_atomic_add(-credit_delta, &pdev->htt_tx_credit.bus_delta); + } + return credit_delta; +} + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +void htt_tx_group_credit_process(struct htt_pdev_t *pdev, u_int32_t *msg_word) +{ + int group_credit_sign; + int32_t group_credit; + u_int32_t group_credit_abs, vdev_id_mask, ac_mask; + u_int8_t group_abs, group_id; + u_int8_t group_offset = 0, more_group_present = 0; + + more_group_present = HTT_TX_CREDIT_TXQ_GRP_GET(*msg_word); + + while (more_group_present) { + /* Parse the Group Data */ + group_id = HTT_TXQ_GROUP_ID_GET(*(msg_word+1+group_offset)); + group_credit_abs = + HTT_TXQ_GROUP_CREDIT_COUNT_GET(*(msg_word+1+group_offset)); + group_credit_sign = + HTT_TXQ_GROUP_SIGN_GET(*(msg_word+1+group_offset)) ? -1 : 1; + group_credit = group_credit_sign * group_credit_abs; + group_abs = HTT_TXQ_GROUP_ABS_GET(*(msg_word+1+group_offset)); + + vdev_id_mask = + HTT_TXQ_GROUP_VDEV_ID_MASK_GET(*(msg_word+2+group_offset)); + ac_mask = HTT_TXQ_GROUP_AC_MASK_GET(*(msg_word+2+group_offset)); + + ol_txrx_update_tx_queue_groups(pdev->txrx_pdev, group_id, + group_credit, group_abs, + vdev_id_mask, ac_mask); + more_group_present = HTT_TXQ_GROUP_EXT_GET(*(msg_word+1+group_offset)); + group_offset += HTT_TX_GROUP_INDEX_OFFSET; + } + OL_TX_UPDATE_GROUP_CREDIT_STATS(pdev->txrx_pdev); +} +#endif + diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_types.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_types.h new file mode 100644 index 000000000000..95a1175daa95 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_types.h @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _HTT_TYPES__H_ +#define _HTT_TYPES__H_ + +#include /* u_int16_t, dma_addr_t */ +#include /* adf_os_device_t */ +#include /* adf_os_spinlock_t */ +#include /* adf_os_timer_t */ +#include /* adf_os_atomic_inc */ +#include /* adf_nbuf_t */ +#include /* HTC_PACKET */ + +#include /* ol_pdev_handle */ +#include /* ol_txrx_pdev_handle */ + +#define DEBUG_DMA_DONE + +#define HTT_TX_MUTEX_TYPE adf_os_spinlock_t + +#ifdef QCA_TX_HTT2_SUPPORT +#ifndef HTC_TX_HTT2_MAX_SIZE +/* Should sync to the target's implementation. */ +#define HTC_TX_HTT2_MAX_SIZE (120) +#endif +#endif /* QCA_TX_HTT2_SUPPORT */ + +#define HTT_INVALID_PEER 0xffff +#define HTT_INVALID_VDEV 0xff +#define HTT_NON_QOS_TID 16 +#define HTT_INVALID_TID 31 + +#define HTT_TX_EXT_TID_DEFAULT 0 +#define HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST 16 +#define HTT_TX_EXT_TID_MGMT 17 +#define HTT_TX_EXT_TID_INVALID 31 +#define HTT_TX_EXT_TID_NONPAUSE 19 + +#ifdef DEBUG_RX_RING_BUFFER +#define HTT_RX_RING_BUFF_DBG_LIST 1024 +#endif + +#define HTT_HTC_PKT_MISCLIST_SIZE 6 +/** + * @brief General specification of the tx frame contents + * + * @details + * for efficiency, the HTT packet type values correspond + * to the bit positions of the WAL packet type values, so the + * translation is a simple shift operation. + */ +enum htt_pkt_type { + htt_pkt_type_raw = 0, + htt_pkt_type_native_wifi = 1, + htt_pkt_type_ethernet = 2, + htt_pkt_type_mgmt = 3, + + /* keep this last */ + htt_pkt_num_types +}; + +struct htt_pdev_t; + +struct htt_htc_pkt { + void *pdev_ctxt; + dma_addr_t nbuf_paddr; + HTC_PACKET htc_pkt; + u_int16_t msdu_id; +}; + +struct htt_htc_pkt_union { + union { + struct htt_htc_pkt pkt; + struct htt_htc_pkt_union *next; + } u; +}; + +/* + * HTT host descriptor: + * Include the htt_tx_msdu_desc that gets downloaded to the target, + * but also include the HTC_FRAME_HDR and alignment padding that + * precede the htt_tx_msdu_desc. + * HTCSendDataPkt expects this header space at the front of the + * initial fragment (i.e. tx descriptor) that is downloaded. + */ +struct htt_host_tx_desc_t { + u_int8_t htc_header[HTC_HEADER_LEN]; + /* force the tx_desc field to begin on a 4-byte boundary */ + union { + u_int32_t dummy_force_align; + struct htt_tx_msdu_desc_t tx_desc; + } align32; +}; + +struct htt_tx_mgmt_desc_buf { + adf_nbuf_t msg_buf; + A_BOOL is_inuse; + adf_nbuf_t mgmt_frm; +}; + +struct htt_tx_mgmt_desc_ctxt { + struct htt_tx_mgmt_desc_buf *pool; + A_UINT32 pending_cnt; +}; + +typedef struct _htt_list_node { + struct _htt_list_node * prev; + struct _htt_list_node * next; +} htt_list_node; + +typedef htt_list_node htt_list_head; + +struct htt_rx_hash_entry { + A_UINT32 paddr; + adf_nbuf_t netbuf; + A_UINT8 fromlist; + htt_list_node listnode; +#ifdef RX_HASH_DEBUG + A_UINT32 cookie; +#endif +}; + +struct htt_rx_hash_bucket { + htt_list_head listhead; + struct htt_rx_hash_entry * entries; + htt_list_head freepool; +#ifdef RX_HASH_DEBUG + A_UINT32 count; +#endif +}; + +#ifdef IPA_UC_OFFLOAD + +/* IPA micro controller + wlan host driver + firmware shared memory structure */ +struct uc_shared_mem_t +{ + u_int32_t *vaddr; + adf_os_dma_addr_t paddr; + adf_os_dma_mem_context(memctx); +}; + +/* Micro controller datapath offload + * WLAN TX resources */ +struct htt_ipa_uc_tx_resource_t +{ + struct uc_shared_mem_t tx_ce_idx; + struct uc_shared_mem_t tx_comp_base; + + u_int32_t tx_comp_idx_paddr; + adf_nbuf_t *tx_buf_pool_vaddr_strg; + u_int32_t alloc_tx_buf_cnt; +}; + +/* Micro controller datapath offload + * WLAN RX resources */ +struct htt_ipa_uc_rx_resource_t +{ + adf_os_dma_addr_t rx_rdy_idx_paddr; + struct uc_shared_mem_t rx_ind_ring_base; + struct uc_shared_mem_t rx_ipa_prc_done_idx; + u_int32_t rx_ind_ring_size; +}; + +struct ipa_uc_rx_ring_elem_t +{ + u_int32_t rx_packet_paddr; + u_int16_t vdev_id; + u_int16_t rx_packet_leng; +}; +#endif /* IPA_UC_OFFLOAD */ + +struct htt_tx_credit_t +{ + adf_os_atomic_t bus_delta; + adf_os_atomic_t target_delta; +}; + +#ifdef DEBUG_RX_RING_BUFFER +struct rx_buf_debug { + uint32_t paddr; + void * vaddr; + bool in_use; +}; +#endif + +struct htt_tx_desc_page_t +{ + char* page_v_addr_start; + char* page_v_addr_end; + adf_os_dma_addr_t page_p_addr; +}; + +struct htt_pdev_t { + ol_pdev_handle ctrl_pdev; + ol_txrx_pdev_handle txrx_pdev; + HTC_HANDLE htc_pdev; + adf_os_device_t osdev; + + HTC_ENDPOINT_ID htc_endpoint; + +#ifdef QCA_TX_HTT2_SUPPORT + HTC_ENDPOINT_ID htc_tx_htt2_endpoint; + u_int16_t htc_tx_htt2_max_size; +#endif /* QCA_TX_HTT2_SUPPORT */ + +#ifdef ATH_11AC_TXCOMPACT + HTT_TX_MUTEX_TYPE txnbufq_mutex; + adf_nbuf_queue_t txnbufq; + struct htt_htc_pkt_union *htt_htc_pkt_misclist; +#endif + + struct htt_htc_pkt_union *htt_htc_pkt_freelist; + struct { + int is_high_latency; + int is_full_reorder_offload; + int default_tx_comp_req; + } cfg; + struct { + u_int8_t major; + u_int8_t minor; + } tgt_ver; + struct { + struct { + /* + * Ring of network buffer objects - + * This ring is used exclusively by the host SW. + * This ring mirrors the dev_addrs_ring that is shared + * between the host SW and the MAC HW. + * The host SW uses this netbufs ring to locate the network + * buffer objects whose data buffers the HW has filled. + */ + adf_nbuf_t *netbufs_ring; + /* + * Ring of buffer addresses - + * This ring holds the "physical" device address of the + * rx buffers the host SW provides for the MAC HW to fill. + */ + u_int32_t *paddrs_ring; + adf_os_dma_mem_context(memctx); + } buf; + /* + * Base address of ring, as a "physical" device address rather than a + * CPU address. + */ + u_int32_t base_paddr; + int size; /* how many elems in the ring (power of 2) */ + unsigned size_mask; /* size - 1 */ + + int fill_level; /* how many rx buffers to keep in the ring */ + int fill_cnt; /* how many rx buffers (full+empty) are in the ring */ + + /* + * target_idx - + * Without reorder offload: + * not used + * With reorder offload: + * points to the location in the rx ring from which rx buffers are + * available to copy into the MAC DMA ring + */ + struct { + u_int32_t *vaddr; + u_int32_t paddr; + adf_os_dma_mem_context(memctx); + } target_idx; + + /* + * alloc_idx/host_idx - + * Without reorder offload: + * where HTT SW has deposited empty buffers + * This is allocated in consistent mem, so that the FW can read + * this variable, and program the HW's FW_IDX reg with the value + * of this shadow register + * With reorder offload: + * points to the end of the available free rx buffers + */ + struct { + u_int32_t *vaddr; + u_int32_t paddr; + adf_os_dma_mem_context(memctx); + } alloc_idx; + + /* sw_rd_idx - where HTT SW has processed bufs filled by rx MAC DMA */ + struct { + unsigned msdu_desc; + unsigned msdu_payld; + } sw_rd_idx; + + /* + * refill_retry_timer - timer triggered when the ring is not + * refilled to the level expected + */ + adf_os_timer_t refill_retry_timer; + + /* + * refill_ref_cnt - ref cnt for Rx buffer replenishment - this + * variable is used to guarantee that only one thread tries + * to replenish Rx ring. + */ + adf_os_atomic_t refill_ref_cnt; +#ifdef DEBUG_DMA_DONE + u_int32_t dbg_initial_msdu_payld; + u_int32_t dbg_mpdu_range; + u_int32_t dbg_mpdu_count; + u_int32_t dbg_ring_idx; + u_int32_t dbg_refill_cnt; + u_int32_t dbg_sync_success; +#endif +#ifdef HTT_RX_RESTORE + int rx_reset; + u_int8_t htt_rx_restore; +#endif + struct htt_rx_hash_bucket **hash_table; + u_int32_t listnode_offset; + } rx_ring; + int rx_desc_size_hl; + long rx_fw_desc_offset; + int rx_mpdu_range_offset_words; + int rx_ind_msdu_byte_idx; + + struct { + int size; /* of each HTT tx desc */ + int pool_elems; + int alloc_cnt; + char *pool_vaddr; + u_int32_t pool_paddr; + u_int32_t *freelist; + adf_os_dma_mem_context(memctx); + } tx_descs; + int download_len; + void (*tx_send_complete_part2)( + void *pdev, A_STATUS status, adf_nbuf_t msdu, u_int16_t msdu_id); + + HTT_TX_MUTEX_TYPE htt_tx_mutex; + + struct { + int htc_err_cnt; + } stats; + + int cur_seq_num_hl; + struct htt_tx_mgmt_desc_ctxt tx_mgmt_desc_ctxt; + struct targetdef_s *targetdef; + +#ifdef IPA_UC_OFFLOAD + struct htt_ipa_uc_tx_resource_t ipa_uc_tx_rsc; + struct htt_ipa_uc_rx_resource_t ipa_uc_rx_rsc; +#endif /* IPA_UC_OFFLOAD */ + + struct htt_tx_credit_t htt_tx_credit; + +#ifdef DEBUG_RX_RING_BUFFER + struct rx_buf_debug *rx_buff_list; + int rx_buff_index; +#endif + + int num_pages; + int num_desc_per_page; + struct htt_tx_desc_page_t *desc_pages; +}; + +#endif /* _HTT_TYPES__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/rx_desc.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/rx_desc.h new file mode 100644 index 000000000000..6d656f7cc486 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/rx_desc.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _RX_DESC_H_ +#define _RX_DESC_H_ + +/* + * REMIND: Copy one of rx_desc related structures here for export, + * hopes they are always the same between Peregrine and Rome in future... + */ +struct rx_attention { + volatile uint32_t first_mpdu : 1, //[0] + last_mpdu : 1, //[1] + mcast_bcast : 1, //[2] + peer_idx_invalid : 1, //[3] + peer_idx_timeout : 1, //[4] + power_mgmt : 1, //[5] + non_qos : 1, //[6] + null_data : 1, //[7] + mgmt_type : 1, //[8] + ctrl_type : 1, //[9] + more_data : 1, //[10] + eosp : 1, //[11] + u_apsd_trigger : 1, //[12] + fragment : 1, //[13] + order : 1, //[14] + classification : 1, //[15] + overflow_err : 1, //[16] + msdu_length_err : 1, //[17] + tcp_udp_chksum_fail : 1, //[18] + ip_chksum_fail : 1, //[19] + sa_idx_invalid : 1, //[20] + da_idx_invalid : 1, //[21] + sa_idx_timeout : 1, //[22] + da_idx_timeout : 1, //[23] + encrypt_required : 1, //[24] + directed : 1, //[25] + buffer_fragment : 1, //[26] + mpdu_length_err : 1, //[27] + tkip_mic_err : 1, //[28] + decrypt_err : 1, //[29] + fcs_err : 1, //[30] + msdu_done : 1; //[31] +}; + +struct rx_frag_info { + volatile uint32_t ring0_more_count : 8, //[7:0] + ring1_more_count : 8, //[15:8] + ring2_more_count : 8, //[23:16] + ring3_more_count : 8; //[31:24] +}; + +struct rx_mpdu_start { + volatile uint32_t peer_idx : 11, //[10:0] + fr_ds : 1, //[11] + to_ds : 1, //[12] + encrypted : 1, //[13] + retry : 1, //[14] + txbf_h_info : 1, //[15] + seq_num : 12, //[27:16] + encrypt_type : 4; //[31:28] + volatile uint32_t pn_31_0 : 32; //[31:0] + volatile uint32_t pn_47_32 : 16, //[15:0] + directed : 1, //[16] + reserved_2 : 11, //[27:17] + tid : 4; //[31:28] +}; + +struct rx_msdu_start { + volatile uint32_t msdu_length : 14, //[13:0] + ip_offset : 6, //[19:14] + ring_mask : 4, //[23:20] + tcp_udp_offset : 7, //[30:24] + reserved_0c : 1; //[31] + volatile uint32_t flow_id_crc : 32; //[31:0] + volatile uint32_t msdu_number : 8, //[7:0] + decap_format : 2, //[9:8] + ipv4_proto : 1, //[10] + ipv6_proto : 1, //[11] + tcp_proto : 1, //[12] + udp_proto : 1, //[13] + ip_frag : 1, //[14] + tcp_only_ack : 1, //[15] + sa_idx : 11, //[26:16] + reserved_2b : 5; //[31:27] +}; + +struct rx_msdu_end { + volatile uint32_t ip_hdr_chksum : 16, //[15:0] + tcp_udp_chksum : 16; //[31:16] + volatile uint32_t key_id_octet : 8, //[7:0] + classification_filter : 8, //[15:8] + ext_wapi_pn_63_48 : 16; //[31:16] + volatile uint32_t ext_wapi_pn_95_64 : 32; //[31:0] + volatile uint32_t ext_wapi_pn_127_96 : 32; //[31:0] + volatile uint32_t reported_mpdu_length : 14, //[13:0] + first_msdu : 1, //[14] + last_msdu : 1, //[15] + reserved_3a : 14, //[29:16] + pre_delim_err : 1, //[30] + reserved_3b : 1; //[31] +}; + +struct rx_mpdu_end { + volatile uint32_t reserved_0 : 13, //[12:0] + overflow_err : 1, //[13] + last_mpdu : 1, //[14] + post_delim_err : 1, //[15] + post_delim_cnt : 12, //[27:16] + mpdu_length_err : 1, //[28] + tkip_mic_err : 1, //[29] + decrypt_err : 1, //[30] + fcs_err : 1; //[31] +}; + +struct rx_ppdu_start { + volatile uint32_t rssi_chain0_pri20 : 8, //[7:0] + rssi_chain0_sec20 : 8, //[15:8] + rssi_chain0_sec40 : 8, //[23:16] + rssi_chain0_sec80 : 8; //[31:24] + volatile uint32_t rssi_chain1_pri20 : 8, //[7:0] + rssi_chain1_sec20 : 8, //[15:8] + rssi_chain1_sec40 : 8, //[23:16] + rssi_chain1_sec80 : 8; //[31:24] + volatile uint32_t rssi_chain2_pri20 : 8, //[7:0] + rssi_chain2_sec20 : 8, //[15:8] + rssi_chain2_sec40 : 8, //[23:16] + rssi_chain2_sec80 : 8; //[31:24] + volatile uint32_t rssi_chain3_pri20 : 8, //[7:0] + rssi_chain3_sec20 : 8, //[15:8] + rssi_chain3_sec40 : 8, //[23:16] + rssi_chain3_sec80 : 8; //[31:24] + volatile uint32_t rssi_comb : 8, //[7:0] + reserved_4a : 16, //[23:8] + is_greenfield : 1, //[24] + reserved_4b : 7; //[31:25] + volatile uint32_t l_sig_rate : 4, //[3:0] + l_sig_rate_select : 1, //[4] + l_sig_length : 12, //[16:5] + l_sig_parity : 1, //[17] + l_sig_tail : 6, //[23:18] + preamble_type : 8; //[31:24] + volatile uint32_t ht_sig_vht_sig_a_1 : 24, //[23:0] + reserved_6 : 8; //[31:24] + volatile uint32_t ht_sig_vht_sig_a_2 : 24, //[23:0] + txbf_h_info : 1, //[24] + reserved_7 : 7; //[31:25] + volatile uint32_t vht_sig_b : 29, //[28:0] + reserved_8 : 3; //[31:29] + volatile uint32_t service : 16, //[15:0] + reserved_9 : 16; //[31:16] +}; + +struct rx_ppdu_end { + volatile uint32_t evm_p0 : 32; //[31:0] + volatile uint32_t evm_p1 : 32; //[31:0] + volatile uint32_t evm_p2 : 32; //[31:0] + volatile uint32_t evm_p3 : 32; //[31:0] + volatile uint32_t evm_p4 : 32; //[31:0] + volatile uint32_t evm_p5 : 32; //[31:0] + volatile uint32_t evm_p6 : 32; //[31:0] + volatile uint32_t evm_p7 : 32; //[31:0] + volatile uint32_t evm_p8 : 32; //[31:0] + volatile uint32_t evm_p9 : 32; //[31:0] + volatile uint32_t evm_p10 : 32; //[31:0] + volatile uint32_t evm_p11 : 32; //[31:0] + volatile uint32_t evm_p12 : 32; //[31:0] + volatile uint32_t evm_p13 : 32; //[31:0] + volatile uint32_t evm_p14 : 32; //[31:0] + volatile uint32_t evm_p15 : 32; //[31:0] + volatile uint32_t tsf_timestamp : 32; //[31:0] + volatile uint32_t wb_timestamp : 32; //[31:0] + volatile uint32_t locationing_timestamp : 8, //[7:0] + phy_err_code : 8, //[15:8] + phy_err : 1, //[16] + rx_location : 1, //[17] + txbf_h_info : 1, //[18] + reserved_18 : 13; //[31:19] + volatile uint32_t rx_antenna : 24, //[23:0] + tx_ht_vht_ack : 1, //[24] + bb_captured_channel : 1, //[25] + reserved_19 : 6; //[31:26] + volatile uint32_t rtt_correction_value : 24, //[23:0] + reserved_20 : 7, //[30:24] + rtt_normal_mode : 1; //[31] + volatile uint32_t bb_length : 16, //[15:0] + reserved_21 : 15, //[30:16] + ppdu_done : 1; //[31] +}; + +#endif /*_RX_DESC_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c new file mode 100644 index 000000000000..281eb4114b89 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -0,0 +1,2624 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "vos_sched.h" +#include "wlan_qct_tl.h" +#include "wdi_in.h" +#include "ol_txrx_peer_find.h" +#include "tl_shim.h" +#include "wma.h" +#include "wmi_unified_api.h" +#include "vos_packet.h" +#include "vos_memory.h" +#include "adf_os_types.h" +#include "adf_nbuf.h" +#include "adf_os_mem.h" +#include "adf_os_lock.h" +#include "adf_nbuf.h" +#include "wma_api.h" +#include "vos_utils.h" +#include "wdi_out.h" + +#define TLSHIM_PEER_AUTHORIZE_WAIT 50 + +#define ENTER() VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__) + +#define TLSHIM_LOGD(args...) \ + VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, ## args) +#define TLSHIM_LOGW(args...) \ + VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, ## args) +#define TLSHIM_LOGE(args...) \ + VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, ## args) +#define TLSHIM_LOGP(args...) \ + VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, ## args) + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + +/************************/ +/* Internal defines */ +/************************/ +#define SIZEOF_80211_HDR (sizeof(struct ieee80211_frame)) +#define LLC_SNAP_SIZE 8 + +/* Cisco Aironet SNAP hdr */ +static u_int8_t AIRONET_SNAP_HEADER[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, + 0x96, 0x00, 0x00 }; + +/* + * @brief: Creates vos_pkt_t for IAPP packet and routes them to PE/LIM. + * @detail: This function will be executed by new deferred task. It calls + * in the function to process and route IAPP frame. After IAPP + * has been processed, it will free the passed adb_nbuf_t pointer. + * This function will run in non interrupt context + * @param: ptr_work - pointer to work struct containing passed parameters + * from calling function. + */ +void +tlshim_mgmt_over_data_rx_handler(struct work_struct *ptr_work) +{ + struct deferred_iapp_work *ptr_my_work + = container_of(ptr_work, struct deferred_iapp_work, deferred_work); + pVosContextType pVosGCtx = ptr_my_work->pVosGCtx; + u_int8_t *data = adf_nbuf_data(ptr_my_work->nbuf); + u_int32_t data_len = adf_nbuf_len(ptr_my_work->nbuf); + struct ol_txrx_vdev_t *vdev = ptr_my_work->vdev; + + /* + * data : is a either data starting from snap hdr or 802.11 frame + * data_len : length of above data + */ + + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + pVosGCtx); + vos_pkt_t *rx_pkt; + adf_nbuf_t wbuf; + struct ieee80211_frame *wh; + + if (!tl_shim->mgmt_rx) { + TLSHIM_LOGE("Not registered for Mgmt rx, dropping the frame"); + /* this buffer is used now, free it */ + adf_nbuf_free(ptr_my_work->nbuf); + /* set inUse to false, so that next IAPP frame can be processed */ + ptr_my_work->inUse = false; + return; + } + + /* + * allocate rx_packet: this will be used for encapsulating a + * sk_buff which then is passed to peHandleMgmtFrame(ptr fn) + * along with vos_ctx. + */ + rx_pkt = vos_mem_malloc(sizeof(*rx_pkt)); + if (!rx_pkt) { + TLSHIM_LOGE("Failed to allocate rx packet"); + /* this buffer is used now, free it */ + adf_nbuf_free(ptr_my_work->nbuf); + /* set inUse to false, so that next IAPP frame can be processed */ + ptr_my_work->inUse = false; + return; + } + + vos_mem_zero(rx_pkt, sizeof(*rx_pkt)); + + /* + * TODO: also check if following is used for IAPP + * if yes, find out how to populate this + * rx_pkt->pkt_meta.channel = 0; + */ + rx_pkt->pkt_meta.snr = rx_pkt->pkt_meta.rssi = 0; + + rx_pkt->pkt_meta.timestamp = (u_int32_t) jiffies; + rx_pkt->pkt_meta.mpdu_hdr_len = SIZEOF_80211_HDR; + + /* + * mpdu len and data len will be different for native and non native + * format + */ + if (vdev->pdev->frame_format == wlan_frm_fmt_native_wifi) { + rx_pkt->pkt_meta.mpdu_len = data_len; + rx_pkt->pkt_meta.mpdu_data_len = data_len - + rx_pkt->pkt_meta.mpdu_hdr_len; + } + else { + rx_pkt->pkt_meta.mpdu_len = data_len + + rx_pkt->pkt_meta.mpdu_hdr_len - ETHERNET_HDR_LEN; + rx_pkt->pkt_meta.mpdu_data_len = data_len - ETHERNET_HDR_LEN; + } + + /* allocate a sk_buff with enough memory for 802.11 IAPP frame */ + wbuf = adf_nbuf_alloc(NULL, roundup(rx_pkt->pkt_meta.mpdu_len, 4), + 0, 4, FALSE); + if (!wbuf) { + TLSHIM_LOGE("Failed to allocate wbuf for mgmt rx"); + vos_mem_free(rx_pkt); + /* this buffer is used now, free it */ + adf_nbuf_free(ptr_my_work->nbuf); + /* set inUse to false, so that next IAPP frame can be processed */ + ptr_my_work->inUse = false; + return; + } + + adf_nbuf_put_tail(wbuf, data_len); + adf_nbuf_set_protocol(wbuf, ETH_P_SNAP); + + /* wh will contain 802.11 frame, it will be encpsulated inside sk_buff */ + wh = (struct ieee80211_frame *) adf_nbuf_data(wbuf); + + /* set mpdu hdr pointre to data of sk_buff */ + rx_pkt->pkt_meta.mpdu_hdr_ptr = adf_nbuf_data(wbuf); + /* set mpdu data pointer to appropriate offset from hdr */ + rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr + + rx_pkt->pkt_meta.mpdu_hdr_len; + /* encapsulate newly allocated sk_buff in rx_pkt */ + rx_pkt->pkt_buf = wbuf; + + if (vdev->pdev->frame_format == wlan_frm_fmt_native_wifi) { + /* if native wifi: copy full frame */ + adf_os_mem_copy(wh, data, data_len); + } + else { + /* + * if not native wifi populate: copy just part after 802.11 hdr + * i.e. part starting from snap header + */ + tpEseIappHdr iapp_hdr_ptr = (tpEseIappHdr)&data[ETHERNET_HDR_LEN]; + u_int8_t *snap_hdr_ptr = &(((u_int8_t*)wh)[SIZEOF_80211_HDR]); + tpSirMacFrameCtl ptr_80211_FC = (tpSirMacFrameCtl)&wh->i_fc; + ptr_80211_FC->protVer = SIR_MAC_PROTOCOL_VERSION; + ptr_80211_FC->type = SIR_MAC_DATA_FRAME; + ptr_80211_FC->subType = SIR_MAC_DATA_QOS_DATA; + ptr_80211_FC->toDS = 0; + ptr_80211_FC->fromDS = 1; + ptr_80211_FC->moreFrag = 0; + ptr_80211_FC->retry = 0; + ptr_80211_FC->powerMgmt = 0; + ptr_80211_FC->moreData = 0; + ptr_80211_FC->wep = 0; + ptr_80211_FC->order = 0; + + wh->i_dur[0] = 0; + wh->i_dur[1] = 0; + + adf_os_mem_copy(&wh->i_addr1, &iapp_hdr_ptr->DestMac[0], + ETHERNET_ADDR_LEN); + adf_os_mem_copy(&wh->i_addr2, &iapp_hdr_ptr->SrcMac[0], + ETHERNET_ADDR_LEN); + adf_os_mem_copy(&wh->i_addr3, &vdev->last_real_peer->mac_addr.raw[0], + ETHERNET_ADDR_LEN); + + wh->i_seq[0] = 0; + wh->i_seq[1] = 0; + + adf_os_mem_copy( snap_hdr_ptr, &data[ETHERNET_HDR_LEN], + data_len - ETHERNET_HDR_LEN); + } + + tl_shim->mgmt_rx(pVosGCtx, rx_pkt); + /* this buffer is used now, free it */ + adf_nbuf_free(ptr_my_work->nbuf); + /* set inUse to false, so that next IAPP frame can be processed */ + ptr_my_work->inUse = false; +} + +/* + * @brief: This function creates the deferred task and schedules it. this is + * still in interrrupt context. The deferred task is created to run + * in non interrut context as a memory allocation of vos_pkt_t is + * needed and memory allocation should not be done in interrupt + * context. + * @param - pVosGCtx - vos context + * @param - data - data containing ieee80211 IAPP frame + * @param - data_len - data len containing ieee80211 IAPP frame + * @param - vdev - virtual device + */ +void +tlshim_mgmt_over_data_rx_handler_non_interrupt_ctx(pVosContextType pVosGCtx, + adf_nbuf_t nbuf, struct ol_txrx_vdev_t *vdev) +{ + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + pVosGCtx); + + /* + * if there is already a deferred IAPP processing, do not start + * another. Instead drop it as IAPP frames are not critical and + * can be dropped without any disruptive effects. + */ + if(tl_shim->iapp_work.inUse == false) { + tl_shim->iapp_work.pVosGCtx = pVosGCtx; + tl_shim->iapp_work.nbuf = nbuf; + tl_shim->iapp_work.vdev = vdev; + tl_shim->iapp_work.inUse = true; + schedule_work(&(tl_shim->iapp_work.deferred_work)); + return; + } + + /* Previous IAPP frame is not yet processed, drop this frame */ + TLSHIM_LOGE("Dropping IAPP frame because previous is yet unprocessed"); + /* + * TODO: If needed this can changed to have queue rather + * than drop frame + */ + adf_nbuf_free(nbuf); + return; +} + +/* + * @brief: This checks if frame is IAPP and if yes routes them to PE/LIM + * @param - pVosGCtx - vos context + * @param - msdu - frame + * @param - sta_id - station ID + */ +bool +tlshim_check_n_process_iapp_frame (pVosContextType pVosGCtx, + adf_nbuf_t *msdu, u_int16_t sta_id) +{ + u_int8_t *data; + u_int8_t offset_snap_header; + struct ol_txrx_pdev_t *pdev = pVosGCtx->pdev_txrx_ctx; + struct ol_txrx_peer_t *peer = + ol_txrx_peer_find_by_local_id(pVosGCtx->pdev_txrx_ctx, sta_id); + struct ol_txrx_vdev_t *vdev = peer->vdev; + adf_nbuf_t new_head = NULL, buf, new_list = NULL, next_buf; + + /* frame format is natve wifi */ + if(pdev->frame_format == wlan_frm_fmt_native_wifi) + offset_snap_header = SIZEOF_80211_HDR; + else + offset_snap_header = ETHERNET_HDR_LEN; + + buf = *msdu; + while (buf) { + data = adf_nbuf_data(buf); + next_buf = adf_nbuf_queue_next(buf); + if (vos_mem_compare( &data[offset_snap_header], + &AIRONET_SNAP_HEADER[0], LLC_SNAP_SIZE) == VOS_TRUE) { + /* process IAPP frames */ + tlshim_mgmt_over_data_rx_handler_non_interrupt_ctx(pVosGCtx, + buf, vdev); + } else { /* Add the packet onto a new list */ + if (new_list == NULL) + new_head = buf; + else + adf_nbuf_set_next(new_list, buf); + new_list = buf; + adf_nbuf_set_next(buf, NULL); + } + buf = next_buf; + } + + if (!new_list) + return true; + + *msdu = new_head; + /* if returned false the packet will be handled by the upper layer */ + return false; +} +#endif /* defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) */ + + +/*AR9888/AR6320 noise floor approx value*/ +#define TLSHIM_TGT_NOISE_FLOOR_DBM (-96) + +#ifdef WLAN_FEATURE_11W + +/* + * @brief - This routine will find the iface based on vdev id of provided bssid + * @param - vos_ctx - vos context + * @param - mac_addr - bss MAC address of received frame + * @param - vdev_id - virtual device id + */ +static struct wma_txrx_node* +tlshim_mgmt_find_iface(void *vos_ctx, u_int8_t *mac_addr, u_int32_t *vdev_id) +{ + struct ol_txrx_vdev_t *vdev = NULL; + struct wma_txrx_node *iface = NULL; + tp_wma_handle wma = NULL; + + wma = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (wma) { + /* + * Based on received frame's bssid, we will try to + * retrieve the vdev id. If we find the vdev then we will + * override with found vdev_id else we will use supplied + * vdev_id + */ + vdev = tl_shim_get_vdev_by_addr(vos_ctx, mac_addr); + if (vdev) { + *vdev_id = vdev->vdev_id; + } + iface = &wma->interfaces[*vdev_id]; + } + return iface; +} + +/* + * @brief - This routine will extract 6 byte PN from the CCMP header + * @param - ccmp_ptr - pointer to ccmp header + */ +static u_int64_t +tl_shim_extract_ccmp_pn(u_int8_t *ccmp_ptr) +{ + u_int8_t rsvd, key, pn[6]; + u_int64_t new_pn; + + /* + * +-----+-----+------+----------+-----+-----+-----+-----+ + * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 | + * +-----+-----+------+----------+-----+-----+-----+-----+ + * CCMP Header Format + */ + + /* Extract individual bytes */ + pn[0] = (u_int8_t)*ccmp_ptr; + pn[1] = (u_int8_t)*(ccmp_ptr+1); + rsvd = (u_int8_t)*(ccmp_ptr+2); + key = (u_int8_t)*(ccmp_ptr+3); + pn[2] = (u_int8_t)*(ccmp_ptr+4); + pn[3] = (u_int8_t)*(ccmp_ptr+5); + pn[4] = (u_int8_t)*(ccmp_ptr+6); + pn[5] = (u_int8_t)*(ccmp_ptr+7); + + /* Form 6 byte PN with 6 individual bytes of PN */ + new_pn = ((uint64_t)pn[5] << 40) | + ((uint64_t)pn[4] << 32) | + ((uint64_t)pn[3] << 24) | + ((uint64_t)pn[2] << 16) | + ((uint64_t)pn[1] << 8) | + ((uint64_t)pn[0] << 0); + + TLSHIM_LOGD("PN of received packet is %llu", new_pn); + return new_pn; +} + +/* + * @brief - This routine is used to detect replay attacking using PN in CCMP + * @param - vos_ctx - vos context + * @param - wh - frame header + * @param - ccmp_ptr - pointer to ccmp header + */ +static bool +is_ccmp_pn_replay_attack(void *vos_ctx, struct ieee80211_frame *wh, + u_int8_t *ccmp_ptr) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer; + u_int8_t peer_id; + u_int8_t *last_pn_valid; + u_int64_t *last_pn, new_pn; + u_int32_t *rmf_pn_replays; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_ctx); + if (!pdev) { + TLSHIM_LOGE("%s: Failed to find pdev", __func__); + TLSHIM_LOGE("%s: Not able to validate PN", __func__); + return true; + } + + vdev = tl_shim_get_vdev_by_addr(vos_ctx, wh->i_addr2); + if (!vdev) { + TLSHIM_LOGE("%s: Failed to find vdev", __func__); + TLSHIM_LOGE("%s: Not able to validate PN", __func__); + return true; + } + + /* Retrieve the peer based on vdev and addr */ + peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, wh->i_addr2, + &peer_id); + + if (NULL == peer) { + TLSHIM_LOGE( + "%s: Failed to find peer, Not able to validate PN", __func__); + return true; + } + + new_pn = tl_shim_extract_ccmp_pn(ccmp_ptr); + last_pn_valid = &peer->last_rmf_pn_valid; + last_pn = &peer->last_rmf_pn; + rmf_pn_replays = &peer->rmf_pn_replays; + + if (*last_pn_valid) { + if (new_pn > *last_pn) { + *last_pn = new_pn; + TLSHIM_LOGD("%s: PN validation successful", __func__); + } else { + TLSHIM_LOGE("%s: PN Replay attack detected", __func__); + /* per 11W amendment, keeping track of replay attacks */ + *rmf_pn_replays += 1; + return true; + } + } else { + *last_pn_valid = 1; + *last_pn = new_pn; + } + + return false; +} +#endif + +static int tlshim_mgmt_rx_process(void *context, u_int8_t *data, + u_int32_t data_len, bool saved_beacon, u_int32_t vdev_id) +{ + void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL); + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); +#ifdef FEATURE_WLAN_D0WOW + tp_wma_handle wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); +#endif + WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL; + wmi_mgmt_rx_hdr *hdr = NULL; +#ifdef WLAN_FEATURE_11W + struct wma_txrx_node *iface = NULL; + u_int8_t *efrm, *orig_hdr; + u_int16_t key_id; + u_int8_t *ccmp; +#endif /* WLAN_FEATURE_11W */ + + vos_pkt_t *rx_pkt; + adf_nbuf_t wbuf; + struct ieee80211_frame *wh; + u_int8_t mgt_type, mgt_subtype; + + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return 0; + } + +#ifdef FEATURE_WLAN_D0WOW + if (!wma_handle) { + TLSHIM_LOGE("%s: Failed to get WMA context!", __func__); + return 0; + } +#endif + + adf_os_spin_lock_bh(&tl_shim->mgmt_lock); + param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data; + if (!param_tlvs) { + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + TLSHIM_LOGE("Get NULL point message from FW"); + return 0; + } + + hdr = param_tlvs->hdr; + if (!hdr) { + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + TLSHIM_LOGE("Rx event is NULL"); + return 0; + } + + if (hdr->buf_len < sizeof(struct ieee80211_frame)) { + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + TLSHIM_LOGE("Invalid rx mgmt packet"); + return 0; + } + + rx_pkt = vos_mem_malloc(sizeof(*rx_pkt)); + if (!rx_pkt) { + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + TLSHIM_LOGE("Failed to allocate rx packet"); + return 0; + } + + vos_mem_zero(rx_pkt, sizeof(*rx_pkt)); + + /* + * Fill in meta information needed by pe/lim + * TODO: Try to maintain rx metainfo as part of skb->data. + */ + rx_pkt->pkt_meta.channel = hdr->channel; + rx_pkt->pkt_meta.scan_src = hdr->flags; + + /* Get the rssi value from the current snr value + * using standard noise floor of -96. + */ + rx_pkt->pkt_meta.rssi = hdr->snr + TLSHIM_TGT_NOISE_FLOOR_DBM; + rx_pkt->pkt_meta.snr = hdr->snr; + + /* If absolute rssi is available from firmware, use it */ + if (hdr->rssi != 0) + rx_pkt->pkt_meta.rssi_raw = hdr->rssi; + else + rx_pkt->pkt_meta.rssi_raw = rx_pkt->pkt_meta.rssi; + + /* + * FIXME: Assigning the local timestamp as hw timestamp is not + * available. Need to see if pe/lim really uses this data. + */ + rx_pkt->pkt_meta.timestamp = (u_int32_t) jiffies; + rx_pkt->pkt_meta.mpdu_hdr_len = sizeof(struct ieee80211_frame); + rx_pkt->pkt_meta.mpdu_len = hdr->buf_len; + rx_pkt->pkt_meta.mpdu_data_len = hdr->buf_len - + rx_pkt->pkt_meta.mpdu_hdr_len; + + /* + * saved_beacon means this beacon is a duplicate of one + * sent earlier. roamCandidateInd flag is used to indicate to + * PE that roam scan finished and a better candidate AP + * was found. + */ + rx_pkt->pkt_meta.roamCandidateInd = saved_beacon ? 1 : 0; + rx_pkt->pkt_meta.sessionId = vdev_id; + /* Why not just use rx_event->hdr.buf_len? */ + wbuf = adf_nbuf_alloc(NULL, + roundup(hdr->buf_len, 4), + 0, 4, FALSE); + if (!wbuf) { + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + TLSHIM_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)", + __func__, hdr->buf_len); + vos_mem_free(rx_pkt); + return 0; + } + + adf_nbuf_put_tail(wbuf, hdr->buf_len); + adf_nbuf_set_protocol(wbuf, ETH_P_CONTROL); + wh = (struct ieee80211_frame *) adf_nbuf_data(wbuf); + + rx_pkt->pkt_meta.mpdu_hdr_ptr = adf_nbuf_data(wbuf); + rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr + + rx_pkt->pkt_meta.mpdu_hdr_len; + rx_pkt->pkt_meta.tsf_delta = hdr->tsf_delta; + rx_pkt->pkt_buf = wbuf; + +#ifdef BIG_ENDIAN_HOST + { + /* + * for big endian host, copy engine byte_swap is enabled + * But the rx mgmt frame buffer content is in network byte order + * Need to byte swap the mgmt frame buffer content - so when + * copy engine does byte_swap - host gets buffer content in the + * correct byte order. + */ + int i; + u_int32_t *destp, *srcp; + destp = (u_int32_t *) wh; + srcp = (u_int32_t *) param_tlvs->bufp; + for (i = 0; + i < (roundup(hdr->buf_len, sizeof(u_int32_t)) / 4); + i++) { + *destp = cpu_to_le32(*srcp); + destp++; srcp++; + } + } +#else + adf_os_mem_copy(wh, param_tlvs->bufp, hdr->buf_len); +#endif + + TLSHIM_LOGD( + FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d tsf_delta: %u"), + MAC_ADDR_ARRAY(wh->i_addr3), hdr->snr, + rx_pkt->pkt_meta.rssi, + rx_pkt->pkt_meta.rssi_raw, hdr->tsf_delta); + + if (!tl_shim->mgmt_rx) { + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + TLSHIM_LOGE("Not registered for Mgmt rx, dropping the frame"); + vos_pkt_return_packet(rx_pkt); + return 0; + } + + /* If it is a beacon/probe response, save it for future use */ + mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + +#ifdef FEATURE_WLAN_D0WOW + if (wma_read_d0wow_flag(wma_handle)) { + TLSHIM_LOGE("%s: Frame subtype is 0x%x", __func__, mgt_subtype); + wma_set_d0wow_flag(wma_handle, FALSE); + } +#endif + + if (!saved_beacon && mgt_type == IEEE80211_FC0_TYPE_MGT && + (mgt_subtype == IEEE80211_FC0_SUBTYPE_BEACON || mgt_subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) + { + /* remember this beacon to be used later for better_ap event */ + WMI_MGMT_RX_EVENTID_param_tlvs *last_tlvs = + (WMI_MGMT_RX_EVENTID_param_tlvs *) tl_shim->last_beacon_data; + if (tl_shim->last_beacon_data) { + /* Free the previously allocated buffers */ + if (last_tlvs->hdr) + vos_mem_free(last_tlvs->hdr); + if (last_tlvs->bufp) + vos_mem_free(last_tlvs->bufp); + vos_mem_free(tl_shim->last_beacon_data); + tl_shim->last_beacon_data = NULL; + tl_shim->last_beacon_len = 0; + } + if((tl_shim->last_beacon_data = vos_mem_malloc(sizeof(WMI_MGMT_RX_EVENTID_param_tlvs)))) { + u_int32_t buf_len = roundup(hdr->buf_len, sizeof(u_int32_t)); + + vos_mem_copy(tl_shim->last_beacon_data, data, sizeof(WMI_MGMT_RX_EVENTID_param_tlvs)); + tl_shim->last_beacon_len = sizeof(WMI_MGMT_RX_EVENTID_param_tlvs); + last_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) tl_shim->last_beacon_data; + if ((last_tlvs->hdr = vos_mem_malloc(sizeof(wmi_mgmt_rx_hdr)))) { + vos_mem_copy(last_tlvs->hdr, hdr, sizeof(wmi_mgmt_rx_hdr)); + if ((last_tlvs->bufp = vos_mem_malloc(buf_len))) { + vos_mem_copy(last_tlvs->bufp, param_tlvs->bufp, buf_len); + } else { + vos_mem_free(last_tlvs->hdr); + vos_mem_free(tl_shim->last_beacon_data); + tl_shim->last_beacon_data = NULL; + tl_shim->last_beacon_len = 0; + } + } else { + vos_mem_free(tl_shim->last_beacon_data); + tl_shim->last_beacon_data = NULL; + tl_shim->last_beacon_len = 0; + } + } + } + adf_os_spin_unlock_bh(&tl_shim->mgmt_lock); + +#ifdef WLAN_FEATURE_11W + if (mgt_type == IEEE80211_FC0_TYPE_MGT && + (mgt_subtype == IEEE80211_FC0_SUBTYPE_DISASSOC || + mgt_subtype == IEEE80211_FC0_SUBTYPE_DEAUTH || + mgt_subtype == IEEE80211_FC0_SUBTYPE_ACTION)) + { + iface = tlshim_mgmt_find_iface(vos_ctx, wh->i_addr3, &vdev_id); + if (iface && iface->rmfEnabled) + { + if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) + { + if (IEEE80211_IS_BROADCAST(wh->i_addr1) || + IEEE80211_IS_MULTICAST(wh->i_addr1)) { + TLSHIM_LOGE("Encrypted BC/MC frame" + " dropping the frame"); + vos_pkt_return_packet(rx_pkt); + return 0; + } + + orig_hdr = (u_int8_t*) adf_nbuf_data(wbuf); + /* Pointer to head of CCMP header */ + ccmp = orig_hdr + sizeof(*wh); + if (is_ccmp_pn_replay_attack(vos_ctx, wh, + ccmp)) { + TLSHIM_LOGE("Dropping the frame"); + vos_pkt_return_packet(rx_pkt); + return 0; + } + + /* Strip privacy headers (and trailer) + for a received frame */ + vos_mem_move(orig_hdr + IEEE80211_CCMP_HEADERLEN, + wh, sizeof(*wh)); + adf_nbuf_pull_head(wbuf, IEEE80211_CCMP_HEADERLEN); + adf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN); + + rx_pkt->pkt_meta.mpdu_hdr_ptr = adf_nbuf_data(wbuf); + rx_pkt->pkt_meta.mpdu_len = adf_nbuf_len(wbuf); + rx_pkt->pkt_meta.mpdu_data_len = + rx_pkt->pkt_meta.mpdu_len - + rx_pkt->pkt_meta.mpdu_hdr_len; + rx_pkt->pkt_meta.mpdu_data_ptr = + rx_pkt->pkt_meta.mpdu_hdr_ptr + + rx_pkt->pkt_meta.mpdu_hdr_len; + rx_pkt->pkt_buf = wbuf; + } + else + { + if (IEEE80211_IS_BROADCAST(wh->i_addr1) || + IEEE80211_IS_MULTICAST(wh->i_addr1)) + { + efrm = adf_nbuf_data(wbuf) + adf_nbuf_len(wbuf); + + key_id = (u_int16_t)*(efrm - vos_get_mmie_size() + 2); + if (!((key_id == WMA_IGTK_KEY_INDEX_4) || + (key_id == WMA_IGTK_KEY_INDEX_5))) { + TLSHIM_LOGE("Invalid KeyID(%d)" + " dropping the frame", key_id); + vos_pkt_return_packet(rx_pkt); + return 0; + } + + if (vos_is_mmie_valid(iface->key.key, + iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, + (u_int8_t *)wh, efrm)) + { + TLSHIM_LOGD("Protected BC/MC frame MMIE" + " validation successful"); + + /* Remove MMIE */ + adf_nbuf_trim_tail(wbuf, + vos_get_mmie_size()); + } + else + { + TLSHIM_LOGE("BC/MC MIC error or MMIE" + " not present, dropping the frame"); + vos_pkt_return_packet(rx_pkt); + return 0; + } + } + else + { + TLSHIM_LOGD("Rx unprotected unicast mgmt frame"); + rx_pkt->pkt_meta.dpuFeedback = + DPU_FEEDBACK_UNPROTECTED_ERROR; + } + + } + } + } +#endif /* WLAN_FEATURE_11W */ + return tl_shim->mgmt_rx(vos_ctx, rx_pkt); +} + +static int tlshim_mgmt_rx_wmi_handler(void *context, u_int8_t *data, + u_int32_t data_len) +{ + void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL); + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + VOS_STATUS ret = VOS_STATUS_SUCCESS; + + if (vos_is_logp_in_progress(VOS_MODULE_ID_TL, NULL)) { + TLSHIM_LOGE("%s: LOGP in progress\n", __func__); + return (-1); + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_TL, NULL)) { + TLSHIM_LOGE("%s: load/unload in progress\n", __func__); + return (-1); + } + + if (!tl_shim) { + TLSHIM_LOGE("%s: tl shim ctx is NULL\n", __func__); + return (-1); + } + + ret = tlshim_mgmt_rx_process(context, data, data_len, FALSE, 0); + + return ret; +} +/* + * tlshim_mgmt_roam_event_ind() is called from WMA layer when + * BETTER_AP_FOUND event is received from roam engine. + */ +int tlshim_mgmt_roam_event_ind(void *context, u_int32_t vdev_id) +{ + void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL); + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + VOS_STATUS ret = VOS_STATUS_SUCCESS; + + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return ret; + } + + if (tl_shim->last_beacon_data && tl_shim->last_beacon_len) { + ret = tlshim_mgmt_rx_process(context, tl_shim->last_beacon_data, + tl_shim->last_beacon_len, TRUE, vdev_id); + } + return ret; +} + +static void tl_shim_flush_rx_frames(void *vos_ctx, + struct txrx_tl_shim_ctx *tl_shim, + u_int8_t sta_id, bool drop) +{ + struct tlshim_sta_info *sta_info = &tl_shim->sta_info[sta_id]; + struct tlshim_buf *cache_buf, *tmp; + VOS_STATUS ret; + WLANTL_STARxCBType data_rx = NULL; + + if (test_and_set_bit(TLSHIM_FLUSH_CACHE_IN_PROGRESS, &sta_info->flags)) + return; + + adf_os_spin_lock_bh(&sta_info->stainfo_lock); + if (sta_info->registered) + data_rx = sta_info->data_rx; + else + drop = true; + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + list_for_each_entry_safe(cache_buf, tmp, + &sta_info->cached_bufq, list) { + list_del(&cache_buf->list); + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + if (drop) + adf_nbuf_free(cache_buf->buf); + else { + /* Flush the cached frames to HDD */ + ret = data_rx(vos_ctx, cache_buf->buf, sta_id); + if (ret != VOS_STATUS_SUCCESS) + adf_nbuf_free(cache_buf->buf); + } + adf_os_mem_free(cache_buf); + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + } + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + clear_bit(TLSHIM_FLUSH_CACHE_IN_PROGRESS, &sta_info->flags); +} + +static void tlshim_data_rx_cb(struct txrx_tl_shim_ctx *tl_shim, + adf_nbuf_t buf_list, u_int16_t staid) +{ + void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, tl_shim); + struct tlshim_sta_info *sta_info; + adf_nbuf_t buf, next_buf; + VOS_STATUS ret; + WLANTL_STARxCBType data_rx = NULL; + + if (unlikely(!vos_ctx)) + goto free_buf; + + sta_info = &tl_shim->sta_info[staid]; + adf_os_spin_lock_bh(&sta_info->stainfo_lock); + if (unlikely(!sta_info->registered)) { + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + goto free_buf; + } + data_rx = sta_info->data_rx; + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + if (!list_empty(&sta_info->cached_bufq)) { + sta_info->suspend_flush = 1; + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + /* Flush the cached frames to HDD before passing new rx frame */ + tl_shim_flush_rx_frames(vos_ctx, tl_shim, staid, 0); + } else + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + + ret = data_rx(vos_ctx, buf_list, staid); + if (ret != VOS_STATUS_SUCCESS) { + TLSHIM_LOGE("Frame Rx to HDD failed"); + goto free_buf; + } + return; + +free_buf: + TLSHIM_LOGW("%s:Dropping frames", __func__); + buf = buf_list; + while (buf) { + next_buf = adf_nbuf_queue_next(buf); + adf_nbuf_free(buf); + buf = next_buf; + } +} + +/* + * Rx callback from txrx module for data reception. + */ +static void tlshim_data_rx_handler(void *context, u_int16_t staid, + adf_nbuf_t rx_buf_list) +{ + struct txrx_tl_shim_ctx *tl_shim; + /* Firmware data path active response will use shim RX thread + * T2H MSG running on SIRQ context, + * IPA kernel module API should not be called on SIRQ CTXT */ +#if (defined(IPA_OFFLOAD) && !defined(IPA_UC_OFFLOAD))|| \ + (defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)) + void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, context); +#endif + struct tlshim_sta_info *sta_info; + adf_nbuf_t buf, next_buf; + WLANTL_STARxCBType data_rx = NULL; + + if (staid >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id :%d", staid); + goto drop_rx_buf; + } + + tl_shim = (struct txrx_tl_shim_ctx *) context; + sta_info = &tl_shim->sta_info[staid]; + + adf_os_spin_lock_bh(&sta_info->stainfo_lock); + if (sta_info->registered) + data_rx = sta_info->data_rx; + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + + /* + * If there is a data frame from peer before the peer is + * registered for data service, enqueue them on to pending queue + * which will be flushed to HDD once that station is registered. + */ + if (!data_rx) { + struct tlshim_buf *cache_buf; + buf = rx_buf_list; + while (buf) { + next_buf = adf_nbuf_queue_next(buf); + cache_buf = adf_os_mem_alloc(NULL, sizeof(*cache_buf)); + if (!cache_buf) { + TLSHIM_LOGE("Failed to allocate buf to cache the rx frames"); + adf_nbuf_free(buf); + } else { + /* Add NULL terminator */ + adf_nbuf_set_next(buf, NULL); + cache_buf->buf = buf; + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + list_add_tail(&cache_buf->list, + &sta_info->cached_bufq); + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + } + buf = next_buf; + } + } else { /* Send rx packet to HDD if there is no frame pending in cached_bufq */ + /* Suspend frames flush from timer */ + /* + * TODO: Need to see if acquiring/releasing lock even when + * there is no cached frames have any significant impact on + * performance. + */ +#if defined (IPA_OFFLOAD) && !defined(IPA_UC_OFFLOAD) + VOS_STATUS ret; + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + sta_info->suspend_flush = 1; + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + + /* Flush the cached frames to HDD before passing new rx frame */ + tl_shim_flush_rx_frames(vos_ctx, tl_shim, staid, 0); + + if (!adf_os_atomic_read(&tl_shim->vdev_active[sta_info->vdev_id])) { + TLSHIM_LOGW("INACTIVE VDEV"); + goto drop_rx_buf; + } + ret = data_rx(vos_ctx, rx_buf_list, staid); + if (ret == VOS_STATUS_E_INVAL) { +#endif + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + /* + * in case following returns true, a defered task was created + * inside function, which does following: + * 1) create vos packet + * 2) send to PE/LIM + * 3) free the involved sk_buff + */ + if (tlshim_check_n_process_iapp_frame(vos_ctx, + &rx_buf_list, staid)) + return; + + /* + * above returned false, the packet was not IAPP. + * process normally + */ +#endif +#ifdef QCA_CONFIG_SMP + /* + * If the kernel is SMP, schedule rx thread to + * better use multicores. + */ + if (!tl_shim->enable_rxthread) { + tlshim_data_rx_cb(tl_shim, rx_buf_list, staid); + } else { + pVosSchedContext sched_ctx = + get_vos_sched_ctxt(); + struct VosTlshimPkt *pkt; + + if (unlikely(!sched_ctx)) + goto drop_rx_buf; + + pkt = vos_alloc_tlshim_pkt(sched_ctx); + if (!pkt) { + TLSHIM_LOGW("No available Rx message buffer"); + goto drop_rx_buf; + } + pkt->callback = (vos_tlshim_cb) + tlshim_data_rx_cb; + pkt->context = (void *) tl_shim; + pkt->Rxpkt = (void *) rx_buf_list; + pkt->staId = staid; + vos_indicate_rxpkt(sched_ctx, pkt); + } +#else /* QCA_CONFIG_SMP */ + tlshim_data_rx_cb(tl_shim, rx_buf_list, staid); +#endif /* QCA_CONFIG_SMP */ +#if defined(IPA_OFFLOAD) && !defined(IPA_UC_OFFLOAD) + } +#endif + } + + return; + +drop_rx_buf: + TLSHIM_LOGW("Dropping rx packets"); + buf = rx_buf_list; + while (buf) { + next_buf = adf_nbuf_queue_next(buf); + adf_nbuf_free(buf); + buf = next_buf; + } +} + +static void tl_shim_cache_flush_work(struct work_struct *work) +{ + struct txrx_tl_shim_ctx *tl_shim = container_of(work, + struct txrx_tl_shim_ctx, cache_flush_work); + void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL); + struct tlshim_sta_info *sta_info; + u_int8_t i; + + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + sta_info = &tl_shim->sta_info[i]; + adf_os_spin_lock_bh(&sta_info->stainfo_lock); + if (!sta_info->registered) { + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + continue; + } + + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + if (sta_info->suspend_flush) { + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + continue; + } + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + + tl_shim_flush_rx_frames(vos_ctx, tl_shim, i, 0); + } +} + +/*************************/ +/* TL APIs */ +/*************************/ + +/* + * TL API called from WMA to register a vdev for data service with + * txrx. This API is called once vdev create succeeds. + */ +void WLANTL_RegisterVdev(void *vos_ctx, void *vdev) +{ + struct txrx_tl_shim_ctx *tl_shim; + struct ol_txrx_osif_ops txrx_ops; + struct ol_txrx_vdev_t *vdev_handle = (struct ol_txrx_vdev_t *) vdev; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return; + } + +#ifdef QCA_LL_TX_FLOW_CT + txrx_ops.tx.flow_control_cb = WLANTL_TXFlowControlCb; + tl_shim->session_flow_control[vdev_handle->vdev_id].vdev = vdev; +#endif /* QCA_LL_TX_FLOW_CT */ + txrx_ops.rx.std = tlshim_data_rx_handler; + wdi_in_osif_vdev_register(vdev_handle, tl_shim, &txrx_ops); + /* TODO: Keep vdev specific tx callback, if needed */ + tl_shim->tx = txrx_ops.tx.std; + adf_os_atomic_set(&tl_shim->vdev_active[vdev_handle->vdev_id], 1); +} + +/* + * TL API called from WMA to un-register a vdev for data service with + * txrx. This API is called once vdev delete. + */ +void WLANTL_UnRegisterVdev(void *vos_ctx, u_int8_t vdev_id) +{ + struct txrx_tl_shim_ctx *tl_shim; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return; + } + + adf_os_atomic_set(&tl_shim->vdev_active[vdev_id], 0); +#ifdef QCA_LL_TX_FLOW_CT + WLANTL_DeRegisterTXFlowControl(vos_ctx, vdev_id); +#endif /* QCA_LL_TX_FLOW_CT */ +} + +/* + * TL API to transmit a frame given by HDD. Returns NULL + * in case of success, skb pointer in case of failure. + */ +adf_nbuf_t WLANTL_SendSTA_DataFrame(void *vos_ctx, u_int8_t sta_id, + adf_nbuf_t skb +#ifdef QCA_PKT_PROTO_TRACE + , v_U8_t proto_type +#endif /* QCA_PKT_PROTO_TRACE */ + ) +{ + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + void *adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, vos_ctx); + adf_nbuf_t ret; + struct ol_txrx_peer_t *peer; + + if (!tl_shim) { + TLSHIM_LOGE("tl_shim is NULL"); + return skb; + } + + if (!adf_ctx) { + TLSHIM_LOGE("adf_ct is NULL"); + return skb; + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_TL, NULL)) { + TLSHIM_LOGW("%s: Driver load/unload in progress", __func__); + return skb; + } + /* + * TODO: How sta_id is created and used for IBSS mode?. + */ + if (sta_id >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id for data tx"); + return skb; + } + + if (!tl_shim->sta_info[sta_id].registered) { + TLSHIM_LOGW("Staion is not yet registered for data service"); + return skb; + } + + peer = ol_txrx_peer_find_by_local_id( + ((pVosContextType) vos_ctx)->pdev_txrx_ctx, + sta_id); + if (!peer) { + TLSHIM_LOGW("Invalid peer"); + return skb; + } + + /* Zero out skb's context buffer for the driver to use */ + adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); + adf_nbuf_map_single(adf_ctx, skb, ADF_OS_DMA_TO_DEVICE); + +#ifdef QCA_PKT_PROTO_TRACE + adf_nbuf_trace_set_proto_type(skb, proto_type); +#endif /* QCA_PKT_PROTO_TRACE */ + + if ((tl_shim->ip_checksum_offload) && (skb->protocol == htons(ETH_P_IP)) + && (skb->ip_summed == CHECKSUM_PARTIAL)) + skb->ip_summed = CHECKSUM_COMPLETE; + + /* Terminate the (single-element) list of tx frames */ + skb->next = NULL; + ret = tl_shim->tx(peer->vdev, skb); + if (ret) { + TLSHIM_LOGW("Failed to tx"); + adf_nbuf_unmap_single(adf_ctx, ret, ADF_OS_DMA_TO_DEVICE); + return ret; + } + + return NULL; +} + +#ifdef IPA_OFFLOAD +adf_nbuf_t WLANTL_SendIPA_DataFrame(void *vos_ctx, void *vdev, + adf_nbuf_t skb, v_U8_t interface_id) +{ + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + adf_nbuf_t ret; + + ENTER(); + if (NULL == tl_shim) { + TLSHIM_LOGW("INVALID TL SHIM CONTEXT"); + return skb; + } + + if (!adf_os_atomic_read(&tl_shim->vdev_active[interface_id])) { + TLSHIM_LOGW("INACTIVE VDEV"); + return skb; + } + + if ((tl_shim->ip_checksum_offload) && (skb->protocol == htons(ETH_P_IP)) + && (skb->ip_summed == CHECKSUM_PARTIAL)) + skb->ip_summed = CHECKSUM_COMPLETE; + + /* Terminate the (single-element) list of tx frames */ + skb->next = NULL; + ret = tl_shim->tx((struct ol_txrx_vdev_t *)vdev, skb); + if (ret) { + TLSHIM_LOGW("Failed to tx"); + return ret; + } + + return NULL; +} +#endif + +VOS_STATUS WLANTL_ResumeDataTx(void *vos_ctx, u_int8_t *sta_id) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_SuspendDataTx(void *vos_ctx, u_int8_t *sta_id, + WLANTL_SuspendCBType suspend_tx_cb) +{ + return VOS_STATUS_SUCCESS; +} + +void WLANTL_AssocFailed(u_int8_t sta_id) +{ + /* Not needed */ +} + +VOS_STATUS WLANTL_Finish_ULA(void (*cb) (void *cb_ctx), void *cb_ctx) +{ + /* Not needed */ + return VOS_STATUS_SUCCESS; +} + +void WLANTLPrintPktsRcvdPerRssi(void *vos_ctx, u_int8_t sta_id, bool flush) +{ + /* TBD */ +} + +void WLANTLPrintPktsRcvdPerRateIdx(void *vos_ctx, u_int8_t sta_id, bool flush) +{ + /* TBD */ +} + +VOS_STATUS WLANTL_TxProcessMsg(void *vos_ctx, vos_msg_t *msg) +{ + /* Not needed */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_McProcessMsg(void *vos_ctx, vos_msg_t *message) +{ + /* Not needed */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_McFreeMsg(void *vos_ctx, vos_msg_t *message) +{ + /* Not needed */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_TxFreeMsg(void *vos_ctx, vos_msg_t *message) +{ + /* Not needed */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_GetSoftAPStatistics(void *vos_ctx, + WLANTL_TRANSFER_STA_TYPE *stats_sum, + v_BOOL_t reset) +{ + /* TBD */ + return VOS_STATUS_SUCCESS; +} + +/* + * Return txrx stats for a given sta_id + */ +VOS_STATUS WLANTL_GetStatistics(void *vos_ctx, + WLANTL_TRANSFER_STA_TYPE *stats_buf, + u_int8_t sta_id) +{ + /* + * TODO: Txrx to be modified to maintain per peer stats which + * TL shim can return whenever requested. + */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_DeregRSSIIndicationCB(void *adapter, v_S7_t rssi, + u_int8_t trig_evt, + WLANTL_RSSICrossThresholdCBType func, + VOS_MODULE_ID mod_id) +{ + /* TBD */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_RegRSSIIndicationCB(void *adapter, v_S7_t rssi, + u_int8_t trig_evt, + WLANTL_RSSICrossThresholdCBType func, + VOS_MODULE_ID mod_id, void *usr_ctx) +{ + /* TBD */ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_EnableUAPSDForAC(void *vos_ctx, u_int8_t sta_id, + WLANTL_ACEnumType ac, u_int8_t tid, + u_int8_t pri, v_U32_t srvc_int, + v_U32_t sus_int, WLANTL_TSDirType dir, + u_int8_t psb, v_U32_t sessionId) +{ + tp_wma_handle wma_handle; + t_wma_trigger_uapsd_params uapsd_params; + struct txrx_tl_shim_ctx *tl_shim; + enum uapsd_ac access_category; + + ENTER(); + + if (!psb) { + TLSHIM_LOGD("No need to configure auto trigger:psb is 0"); + return VOS_STATUS_SUCCESS; + } + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (!wma_handle) { + TLSHIM_LOGE("wma_handle is NULL"); + return VOS_STATUS_E_FAILURE; + } + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("tl_shim is NULL"); + return VOS_STATUS_E_FAILURE; + } + + switch (ac) { + case WLANTL_AC_BK: + access_category = UAPSD_BK; + break; + case WLANTL_AC_BE: + access_category = UAPSD_BE; + break; + case WLANTL_AC_VI: + access_category = UAPSD_VI; + break; + case WLANTL_AC_VO: + access_category = UAPSD_VO; + break; + default: + return VOS_STATUS_E_FAILURE; + } + + uapsd_params.wmm_ac = access_category; + uapsd_params.user_priority = pri; + uapsd_params.service_interval = srvc_int; + uapsd_params.delay_interval = tl_shim->delay_interval; + uapsd_params.suspend_interval = sus_int; + + if(VOS_STATUS_SUCCESS != + wma_trigger_uapsd_params(wma_handle, sessionId, &uapsd_params)) + { + TLSHIM_LOGE("Failed to Trigger Uapsd params for sessionId %d", + sessionId); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_DisableUAPSDForAC(void *vos_ctx, u_int8_t sta_id, + WLANTL_ACEnumType ac, v_U32_t sessionId) +{ + tp_wma_handle wma_handle; + enum uapsd_ac access_category; + ENTER(); + + switch (ac) { + case WLANTL_AC_BK: + access_category = UAPSD_BK; + break; + case WLANTL_AC_BE: + access_category = UAPSD_BE; + break; + case WLANTL_AC_VI: + access_category = UAPSD_VI; + break; + case WLANTL_AC_VO: + access_category = UAPSD_VO; + break; + default: + return VOS_STATUS_E_FAILURE; + } + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (!wma_handle) { + TLSHIM_LOGE("wma handle is NULL"); + return VOS_STATUS_E_FAILURE; + } + if (VOS_STATUS_SUCCESS != + wma_disable_uapsd_per_ac(wma_handle, sessionId, access_category)) { + TLSHIM_LOGE("Failed to disable uapsd for ac %d for sessionId %d", + ac, sessionId); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_DeRegisterMgmtFrmClient(void *vos_ctx) +{ + struct txrx_tl_shim_ctx *tl_shim; + tp_wma_handle wma_handle; + ENTER(); + +#ifdef QCA_WIFI_FTM + if (vos_get_conparam() == VOS_FTM_MODE) + return VOS_STATUS_SUCCESS; +#endif + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return VOS_STATUS_E_FAILURE; + } + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (!wma_handle) { + TLSHIM_LOGE("%s: Failed to get WMA context", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle, + WMI_MGMT_RX_EVENTID) != 0) { + TLSHIM_LOGE("Failed to Unregister rx mgmt handler with wmi"); + return VOS_STATUS_E_FAILURE; + } + tl_shim->mgmt_rx = NULL; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_RegisterMgmtFrmClient(void *vos_ctx, + WLANTL_MgmtFrmRxCBType mgmt_frm_rx) +{ + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + + tp_wma_handle wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (!wma_handle) { + TLSHIM_LOGE("%s: Failed to get WMA context", __func__); + return VOS_STATUS_E_FAILURE; + } + if (wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_MGMT_RX_EVENTID, + tlshim_mgmt_rx_wmi_handler) + != 0) { + TLSHIM_LOGE("Failed to register rx mgmt handler with wmi"); + return VOS_STATUS_E_FAILURE; + } + tl_shim->mgmt_rx = mgmt_frm_rx; + + return VOS_STATUS_SUCCESS; +} + +/* + * Return the data rssi for the given peer. + */ +VOS_STATUS WLANTL_GetRssi(void *vos_ctx, u_int8_t sta_id, v_S7_t *rssi, void *pGetRssiReq) +{ + tp_wma_handle wma_handle; + struct txrx_tl_shim_ctx *tl_shim; + struct tlshim_sta_info *sta_info; + v_S7_t first_rssi; + + ENTER(); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (!wma_handle) { + TLSHIM_LOGE("wma_handle is NULL"); + return VOS_STATUS_E_FAILURE; + } + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("tl_shim is NULL"); + return VOS_STATUS_E_FAULT; + } + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id :%d", sta_id); + return VOS_STATUS_E_INVAL; + } + + sta_info = &tl_shim->sta_info[sta_id]; + first_rssi = sta_info->first_rssi; + + if(VOS_STATUS_SUCCESS != + wma_send_snr_request(wma_handle, pGetRssiReq, first_rssi)) { + TLSHIM_LOGE("Failed to Trigger wma stats request"); + return VOS_STATUS_E_FAILURE; + } + + /* dont send success, otherwise call back + * will released with out values */ + return VOS_STATUS_E_BUSY; +} + +/* + * HDD will directly call tx function with the skb for transmission. + * Txrx is reponsible to enqueue the packet and schedule it for Hight + * Latency devices, so this API is not used for CLD. + */ +VOS_STATUS WLANTL_STAPktPending(void *vos_ctx, u_int8_t sta_id, + WLANTL_ACEnumType ac) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_UpdateSTABssIdforIBSS(void *vos_ctx, u_int8_t sta_id, + u_int8_t *bssid) +{ + /* TBD */ + return VOS_STATUS_SUCCESS; +} + +/* + * In CLD, sec_type along with the peer_state will be used to + * make sure EAPOL frame after PTK is installed is getting encrypted. + * So this API is no-op. + */ +VOS_STATUS WLANTL_STAPtkInstalled(void *vos_ctx, u_int8_t sta_id) +{ + return VOS_STATUS_SUCCESS; +} + +/* + * HDD calls this to notify the state change in client. + * Txrx will do frame filtering. + */ +VOS_STATUS WLANTL_ChangeSTAState(void *vos_ctx, u_int8_t sta_id, + WLANTL_STAStateType sta_state, + v_BOOL_t roam_synch_in_progress) +{ + struct ol_txrx_peer_t *peer; + enum ol_txrx_peer_state txrx_state = ol_txrx_peer_state_invalid; + int err; + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, + vos_ctx); + + ENTER(); + + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id :%d", sta_id); + return VOS_STATUS_E_INVAL; + } + peer = ol_txrx_peer_find_by_local_id( + ((pVosContextType) vos_ctx)->pdev_txrx_ctx, + sta_id); + + if ((peer == NULL) || + (adf_os_atomic_read(&peer->delete_in_progress) == 1)) + return VOS_STATUS_E_FAULT; + + if (sta_state == WLANTL_STA_CONNECTED) + txrx_state = ol_txrx_peer_state_conn; + else if (sta_state == WLANTL_STA_AUTHENTICATED) + txrx_state = ol_txrx_peer_state_auth; + + ol_txrx_peer_state_update(peer->vdev->pdev, + (u_int8_t *) peer->mac_addr.raw, + txrx_state); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_synch_in_progress) + return VOS_STATUS_SUCCESS; +#endif + + + if (txrx_state == ol_txrx_peer_state_auth) { +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + /* make sure event is reset */ + vos_event_reset(&tl_shim->peer_authorized_events[peer->vdev->vdev_id]); +#endif + err = wma_set_peer_param( + ((pVosContextType) vos_ctx)->pWDAContext, + peer->mac_addr.raw, WMI_PEER_AUTHORIZE, + 1, peer->vdev->vdev_id); + if (err) { + TLSHIM_LOGE("Failed to set the peer state to authorized"); + return VOS_STATUS_E_FAULT; + } + + if (peer->vdev->opmode == wlan_op_mode_sta) { +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + /* + * TODO: following code waits on event without + * checking if the event was already set. Currently + * there is no vos api to check if event was already + * set fix it cleanly later. + */ + /* wait for event from firmware to set the event */ + err = vos_wait_single_event(&tl_shim->peer_authorized_events[peer->vdev->vdev_id], + TLSHIM_PEER_AUTHORIZE_WAIT); + if (err != VOS_STATUS_SUCCESS) + TLSHIM_LOGE("%s:timeout for peer_authorized_event", + __func__); + wdi_in_vdev_unpause(peer->vdev, + OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED); +#endif + } + } + + return VOS_STATUS_SUCCESS; +} + +/* + * Clear the station information. + */ +VOS_STATUS WLANTL_ClearSTAClient(void *vos_ctx, u_int8_t sta_id) +{ + struct txrx_tl_shim_ctx *tl_shim; + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id :%d", sta_id); + return VOS_STATUS_E_INVAL; + } + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return VOS_STATUS_E_FAILURE; + } + +#ifdef QCA_CONFIG_SMP + { + pVosSchedContext sched_ctx = get_vos_sched_ctxt(); + /* Drop pending Rx frames in VOSS */ + if (sched_ctx) + vos_drop_rxpkt_by_staid(sched_ctx, sta_id); + } +#endif + + /* Purge the cached rx frame queue */ + tl_shim_flush_rx_frames(vos_ctx, tl_shim, sta_id, 1); + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + tl_shim->sta_info[sta_id].suspend_flush = 0; + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + + adf_os_spin_lock_bh(&tl_shim->sta_info[sta_id].stainfo_lock); + tl_shim->sta_info[sta_id].registered = 0; + tl_shim->sta_info[sta_id].data_rx = NULL; + tl_shim->sta_info[sta_id].first_rssi = 0; + adf_os_spin_unlock_bh(&tl_shim->sta_info[sta_id].stainfo_lock); + + return VOS_STATUS_SUCCESS; +} + +/* + * Register a station for data service. This API gives flexibility + * to register different callbacks for different client though it is + * needed to register different callbacks for every vdev. Only rxcb + * is used. + */ +VOS_STATUS WLANTL_RegisterSTAClient(void *vos_ctx, + WLANTL_STARxCBType rxcb, + WLANTL_TxCompCBType tx_comp, + WLANTL_STAFetchPktCBType txpkt_fetch, + WLAN_STADescType *sta_desc, v_S7_t rssi) +{ + struct txrx_tl_shim_ctx *tl_shim; + struct ol_txrx_peer_t *peer; + ol_txrx_peer_update_param_t param; + struct tlshim_sta_info *sta_info; + privacy_exemption privacy_filter; + + ENTER(); + if (sta_desc->ucSTAId >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id :%d", sta_desc->ucSTAId); + return VOS_STATUS_E_INVAL; + } + peer = ol_txrx_peer_find_by_local_id( + ((pVosContextType) vos_ctx)->pdev_txrx_ctx, + sta_desc->ucSTAId); + if (!peer) + return VOS_STATUS_E_FAULT; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("tl_shim is NULL"); + return VOS_STATUS_E_FAULT; + } + + sta_info = &tl_shim->sta_info[sta_desc->ucSTAId]; + adf_os_spin_lock_bh(&sta_info->stainfo_lock); + sta_info->data_rx = rxcb; + sta_info->registered = true; + sta_info->first_rssi = rssi; + sta_info->vdev_id = peer->vdev->vdev_id; + adf_os_spin_unlock_bh(&sta_info->stainfo_lock); + + param.qos_capable = sta_desc->ucQosEnabled; + wdi_in_peer_update(peer->vdev, peer->mac_addr.raw, ¶m, + ol_txrx_peer_update_qos_capable); + if (sta_desc->ucIsWapiSta) { + /*Privacy filter to accept unencrypted WAI frames*/ + privacy_filter.ether_type = ETHERTYPE_WAI; + privacy_filter.filter_type = PRIVACY_FILTER_ALWAYS; + privacy_filter.packet_type = PRIVACY_FILTER_PACKET_BOTH; + ol_txrx_set_privacy_filters(peer->vdev, &privacy_filter, 1); + /* param.sec_type = ol_sec_type_wapi; */ + /* + * TODO: Peer update also updates the other security types + * but HDD will not pass this information. + + wdi_in_peer_update(peer->vdev, peer->mac_addr.raw, ¶m, + ol_txrx_peer_update_peer_security); + */ + } + + /* Schedule a worker to flush cached rx frames */ + schedule_work(&tl_shim->cache_flush_work); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WLANTL_Stop(void *vos_ctx) +{ + /* Nothing to do really */ + return VOS_STATUS_SUCCESS; +} + +/* + * Make txrx module ready + */ +VOS_STATUS WLANTL_Start(void *vos_ctx) +{ + ENTER(); + if (wdi_in_pdev_attach_target(((pVosContextType) + vos_ctx)->pdev_txrx_ctx)) + return VOS_STATUS_E_FAULT; + return VOS_STATUS_SUCCESS; +} + +/* + * Deinit txrx module + */ +VOS_STATUS WLANTL_Close(void *vos_ctx) +{ + struct txrx_tl_shim_ctx *tl_shim; +#if defined(QCA_LL_TX_FLOW_CT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) + u_int8_t i; +#endif /* QCA_LL_TX_FLOW_CT */ + + ENTER(); + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("tl_shim is NULL"); + return VOS_STATUS_E_FAILURE; + } + +#ifdef QCA_LL_TX_FLOW_CT + for (i = 0; + i < wdi_out_cfg_max_vdevs(((pVosContextType)vos_ctx)->cfg_ctx); + i++) { + adf_os_spinlock_destroy(&tl_shim->session_flow_control[i].fc_lock); + } + adf_os_mem_free(tl_shim->session_flow_control); +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + for (i = 0; + i < wdi_out_cfg_max_vdevs(((pVosContextType)vos_ctx)->cfg_ctx); + i++) { + vos_event_destroy(&tl_shim->peer_authorized_events[i]); + } + adf_os_mem_free(tl_shim->peer_authorized_events); +#endif + + adf_os_mem_free(tl_shim->vdev_active); +#ifdef FEATURE_WLAN_ESE + vos_flush_work(&tl_shim->iapp_work.deferred_work); +#endif + vos_flush_work(&tl_shim->cache_flush_work); + + wdi_in_pdev_detach(((pVosContextType) vos_ctx)->pdev_txrx_ctx, 1); + // Delete beacon buffer hanging off tl_shim + if (tl_shim->last_beacon_data) { + if (((WMI_MGMT_RX_EVENTID_param_tlvs *) tl_shim->last_beacon_data)->hdr) + vos_mem_free(((WMI_MGMT_RX_EVENTID_param_tlvs *) tl_shim->last_beacon_data)->hdr); + if (((WMI_MGMT_RX_EVENTID_param_tlvs *) tl_shim->last_beacon_data)->bufp) + vos_mem_free(((WMI_MGMT_RX_EVENTID_param_tlvs *) tl_shim->last_beacon_data)->bufp); + vos_mem_free(tl_shim->last_beacon_data); + } + vos_free_context(vos_ctx, VOS_MODULE_ID_TL, tl_shim); + return VOS_STATUS_SUCCESS; +} + +/* + * Allocate and Initialize transport layer (txrx) + */ +VOS_STATUS WLANTL_Open(void *vos_ctx, WLANTL_ConfigInfoType *tl_cfg) +{ + struct txrx_tl_shim_ctx *tl_shim; + VOS_STATUS status; + u_int8_t i; + int max_vdev; + + ENTER(); + status = vos_alloc_context(vos_ctx, VOS_MODULE_ID_TL, + (void *) &tl_shim, sizeof(*tl_shim)); + if (status != VOS_STATUS_SUCCESS) + return status; + + ((pVosContextType) vos_ctx)->pdev_txrx_ctx = + wdi_in_pdev_attach( + ((pVosContextType) vos_ctx)->cfg_ctx, + ((pVosContextType) vos_ctx)->htc_ctx, + ((pVosContextType) vos_ctx)->adf_ctx); + if (!((pVosContextType) vos_ctx)->pdev_txrx_ctx) { + TLSHIM_LOGE("Failed to allocate memory for pdev txrx handle"); + vos_free_context(vos_ctx, VOS_MODULE_ID_TL, tl_shim); + return VOS_STATUS_E_NOMEM; + } + + adf_os_spinlock_init(&tl_shim->bufq_lock); + adf_os_spinlock_init(&tl_shim->mgmt_lock); + + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + tl_shim->sta_info[i].suspend_flush = 0; + adf_os_spinlock_init(&tl_shim->sta_info[i].stainfo_lock); + tl_shim->sta_info[i].flags = 0; + INIT_LIST_HEAD(&tl_shim->sta_info[i].cached_bufq); + } + +#ifdef CONFIG_CNSS + cnss_init_work(&tl_shim->cache_flush_work, tl_shim_cache_flush_work); +#else + INIT_WORK(&tl_shim->cache_flush_work, tl_shim_cache_flush_work); +#endif + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#ifdef CONFIG_CNSS + cnss_init_work(&(tl_shim->iapp_work.deferred_work), + tlshim_mgmt_over_data_rx_handler); +#else + INIT_WORK(&(tl_shim->iapp_work.deferred_work), + tlshim_mgmt_over_data_rx_handler); +#endif +#endif + /* + * TODO: Allocate memory for tx callback for maximum supported + * vdevs to maintain tx callbacks per vdev. + */ + max_vdev = wdi_out_cfg_max_vdevs(((pVosContextType)vos_ctx)->cfg_ctx); + tl_shim->vdev_active = adf_os_mem_alloc(NULL, + max_vdev * sizeof(adf_os_atomic_t)); + for (i = 0; i < max_vdev; i++) { + adf_os_atomic_init(&tl_shim->vdev_active[i]); + adf_os_atomic_set(&tl_shim->vdev_active[i], 0); + } + +#ifdef QCA_LL_TX_FLOW_CT + tl_shim->session_flow_control = adf_os_mem_alloc(NULL, + max_vdev * sizeof(struct tlshim_session_flow_Control)); + if (!tl_shim->session_flow_control) { + TLSHIM_LOGE("Failed to allocate memory for tx flow control"); + vos_free_context(vos_ctx, VOS_MODULE_ID_TL, tl_shim); + return VOS_STATUS_E_NOMEM; + } + + for (i = 0; i < max_vdev; i++) { + tl_shim->session_flow_control[i].flowControl = NULL; + tl_shim->session_flow_control[i].sessionId = 0xFF; + tl_shim->session_flow_control[i].adpaterCtxt = NULL; + tl_shim->session_flow_control[i].vdev = NULL; + adf_os_spinlock_init(&tl_shim->session_flow_control[i].fc_lock); + } +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + tl_shim->peer_authorized_events = adf_os_mem_alloc(NULL, + max_vdev * sizeof(vos_event_t)); + if (!tl_shim->peer_authorized_events) { + TLSHIM_LOGE("Failed to allocate memory for events"); +#ifdef QCA_LL_TX_FLOW_CT + adf_os_mem_free(tl_shim->session_flow_control); +#endif + vos_free_context(vos_ctx, VOS_MODULE_ID_TL, tl_shim); + return VOS_STATUS_E_NOMEM; + } + for (i = 0; i < max_vdev; i++) { + status = vos_event_init(&tl_shim->peer_authorized_events[i]); + if (!VOS_IS_STATUS_SUCCESS(status)) { + TLSHIM_LOGE("%s: Failed to initialized a event.", + __func__); + adf_os_mem_free(tl_shim->peer_authorized_events); +#ifdef QCA_LL_TX_FLOW_CT + adf_os_mem_free(tl_shim->session_flow_control); +#endif + vos_free_context(vos_ctx, VOS_MODULE_ID_TL, tl_shim); + return status; + } + } +#endif + + tl_shim->ip_checksum_offload = tl_cfg->ip_checksum_offload; + tl_shim->delay_interval = tl_cfg->uDelayedTriggerFrmInt; + tl_shim->enable_rxthread = tl_cfg->enable_rxthread; + if (tl_shim->enable_rxthread) + TLSHIM_LOGD("TL Shim RX thread enabled"); + + return status; +} + +/* + * Funtion to retrieve BSSID for peer sta. + */ +VOS_STATUS tl_shim_get_vdevid(struct ol_txrx_peer_t *peer, u_int8_t *vdev_id) +{ + if(!peer) { + TLSHIM_LOGE("peer argument is null!!"); + return VOS_STATUS_E_FAILURE; + } + + *vdev_id = peer->vdev->vdev_id; + return VOS_STATUS_SUCCESS; +} + +/* + * Function to get vdev(tl_context) given the MAC address. + */ +void *tl_shim_get_vdev_by_addr(void *vos_context, uint8_t *mac_addr) +{ + struct ol_txrx_peer_t *peer = NULL; + ol_txrx_pdev_handle pdev = NULL; + uint8_t peer_id; + + if (vos_context == NULL || mac_addr == NULL) { + TLSHIM_LOGE("Invalid argument %p, %p", vos_context, mac_addr); + return NULL; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_context); + if (!pdev) { + TLSHIM_LOGE("PDEV [%pM] not found", mac_addr); + return NULL; + } + + peer = ol_txrx_find_peer_by_addr(pdev, mac_addr, &peer_id); + + if (!peer) { + TLSHIM_LOGE("PEER [%pM] not found", mac_addr); + return NULL; + } + + return peer->vdev; +} + +/* + * Function to get vdev(tl_context) given the TL station ID. + */ +void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id) +{ + struct ol_txrx_peer_t *peer = NULL; + ol_txrx_pdev_handle pdev = NULL; + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TLSHIM_LOGE("Invalid sta id passed"); + return NULL; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_context); + if (!pdev) { + TLSHIM_LOGE("PDEV not found for sta_id [%d]", sta_id); + return NULL; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + + if (!peer) { + TLSHIM_LOGE("PEER [%d] not found", sta_id); + return NULL; + } + + return peer->vdev; +} + +void +WLANTL_PauseUnPauseQs(void *vos_context, v_BOOL_t flag) +{ + ol_txrx_pdev_handle pdev = vos_get_context(VOS_MODULE_ID_TXRX, + vos_context); + + if (!pdev) { + TLSHIM_LOGE("%s, PDEV NULL",__func__); + return; + } + if (true == flag) + wdi_in_pdev_pause(pdev, + OL_TXQ_PAUSE_REASON_VDEV_SUSPEND); + else + wdi_in_pdev_unpause(pdev, + OL_TXQ_PAUSE_REASON_VDEV_SUSPEND); +} + +#ifdef QCA_LL_TX_FLOW_CT +/* + * WLANTL_Get_llStats - get the stats for TXRX module + * @sessionId: vdev sessionid. + * @buffer: buffer to update the stats + * @length: lenth of the buffer + * + * HDD will call this API to get the OL-TXRX module stats + * + */ +void WLANTL_Get_llStats +( + uint8_t sessionId, + char *buffer, + uint16_t length +) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_TL, NULL); + struct txrx_tl_shim_ctx *tl_shim; + struct ol_txrx_vdev_t *vdev; + + if (!vos_context) { + return; + } + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_context); + if (!tl_shim) { + TLSHIM_LOGD("%s, tl_shim is NULL", + __func__); + return; + } + + vdev = tl_shim->session_flow_control[sessionId].vdev; + if (!vdev) { + TLSHIM_LOGE("%s, vdev is NULL", __func__); + return; + } + ol_txrx_stats(vdev, buffer, (unsigned)length); + return; + +} + +/*============================================================================= + FUNCTION WLANTL_GetTxResource + + DESCRIPTION + This function will query WLAN kernel driver TX resource availability. + Per STA/VDEV instance, if TX resource is not available, should back + pressure to OS NET layer. + + DEPENDENCIES + NONE + + PARAMETERS + IN + vos_context : Pointer to VOS global context + sessionId : VDEV instance to query TX resource + low_watermark : Low threashold to block OS Q + high_watermark_offset : Offset to high watermark from low watermark + + RETURN VALUE + VOS_TRUE : Enough resource available, Not need to PAUSE TX OS Q + VOS_FALSE : TX resource is not enough, stop OS TX Q + + SIDE EFFECTS + +==============================================================================*/ +v_BOOL_t WLANTL_GetTxResource +( + void *vos_context, + v_U8_t sessionId, + unsigned int low_watermark, + unsigned int high_watermark_offset +) +{ + struct txrx_tl_shim_ctx *tl_shim; + v_BOOL_t enough_resource = VOS_TRUE; + struct ol_txrx_vdev_t *vdev; + + /* If low watermark is zero, TX flow control is not enabled at all + * return TRUE by default */ + if ((!vos_context) || (!low_watermark)) { + return VOS_TRUE; + } + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_context); + if (!tl_shim) { + TLSHIM_LOGD("%s, tl_shim is NULL", + __func__); + /* Invalid instace */ + return VOS_TRUE; + } + + adf_os_spin_lock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + if (!tl_shim->session_flow_control[sessionId].vdev) { + TLSHIM_LOGD("%s, session id %d, VDEV NULL", + __func__, sessionId); + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + return VOS_TRUE; + } + vdev = (struct ol_txrx_vdev_t *)tl_shim->session_flow_control[sessionId].vdev; + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + + enough_resource = (v_BOOL_t)wdi_in_get_tx_resource(vdev, + low_watermark, + high_watermark_offset); + + return enough_resource; +} + +/*============================================================================= + FUNCTION WLANTL_TXFlowControlCb + + DESCRIPTION + This function will be called bu TX resource management unit. + If TC resource management unit reserved enough resource for TX session, + Call this function to resume OS TX Q. + + PARAMETERS + IN + tlContext : Pointer to TL SHIM context + sessionId : STA/VDEV instance to query TX resource + resume_tx : Resume OS TX Q or not + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_TXFlowControlCb +( + void *tlContext, + v_U8_t sessionId, + v_BOOL_t resume_tx +) +{ + struct txrx_tl_shim_ctx *tl_shim; + WLANTL_TxFlowControlCBType flow_control_cb = NULL; + void *adpter_ctxt = NULL; + + tl_shim = (struct txrx_tl_shim_ctx *)tlContext; + if (!tl_shim) { + TLSHIM_LOGE("%s, tl_shim is NULL", __func__); + /* Invalid instace */ + return; + } + + adf_os_spin_lock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + if ((tl_shim->session_flow_control[sessionId].sessionId == sessionId) && + (tl_shim->session_flow_control[sessionId].flowControl)) { + flow_control_cb = tl_shim->session_flow_control[sessionId].flowControl; + adpter_ctxt = tl_shim->session_flow_control[sessionId].adpaterCtxt; + } + + if ((flow_control_cb) && (adpter_ctxt)) { + flow_control_cb(adpter_ctxt, resume_tx); + } + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + + return; +} + +/*============================================================================= + FUNCTION WLANTL_RegisterTXFlowControl + + DESCRIPTION + This function will be called by TL client. + Any device want to enable TX flow control, should register Cb function + And needed information into TL SHIM + + PARAMETERS + IN + vos_ctx : Global OS context context + sta_id : STA/VDEV instance index + flowControl : Flow control callback function pointer + sessionId : VDEV ID + adpaterCtxt : VDEV os interface adapter context + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_RegisterTXFlowControl +( + void *vos_ctx, + WLANTL_TxFlowControlCBType flowControl, + v_U8_t sessionId, + void *adpaterCtxt +) +{ + struct txrx_tl_shim_ctx *tl_shim; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if ((!tl_shim) || (!tl_shim->session_flow_control)) { + TLSHIM_LOGE("%s : Invalid ARG", __func__); + return; + } + + if (sessionId >= wdi_out_cfg_max_vdevs(((pVosContextType)vos_ctx)->cfg_ctx)) { + TLSHIM_LOGE("%s : Invalid session id", __func__); + return; + } + + adf_os_spin_lock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + tl_shim->session_flow_control[sessionId].flowControl = flowControl; + tl_shim->session_flow_control[sessionId].sessionId = sessionId; + tl_shim->session_flow_control[sessionId].adpaterCtxt = adpaterCtxt; + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + + return; +} + +/*============================================================================= + FUNCTION WLANTL_DeRegisterTXFlowControl + + DESCRIPTION + This function will be called by TL client. + Any device want to close TX flow control, should de-register Cb function + And needed information into TL SHIM + + PARAMETERS + IN + vos_ctx : Global OS context context + sessionId : VDEV instance index + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_DeRegisterTXFlowControl +( + void *vos_ctx, + v_U8_t sessionId +) +{ + struct txrx_tl_shim_ctx *tl_shim; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if (!tl_shim) { + TLSHIM_LOGE("%s : Invalid ARG", __func__); + return; + } + + if (sessionId >= wdi_out_cfg_max_vdevs(((pVosContextType)vos_ctx)->cfg_ctx)) { + TLSHIM_LOGE("%s : Invalid session id", __func__); + return; + } + + adf_os_spin_lock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + tl_shim->session_flow_control[sessionId].flowControl = NULL; + tl_shim->session_flow_control[sessionId].sessionId = 0xFF; + tl_shim->session_flow_control[sessionId].adpaterCtxt = NULL; + tl_shim->session_flow_control[sessionId].vdev = NULL; + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + + return; +} + +/*============================================================================= + FUNCTION WLANTL_SetAdapterMaxQDepth + + DESCRIPTION + This function will be called by TL client. + Based on the adapter TX available bandwidth, set different TX Pause Q size + Low Bandwidth adapter will have less count of TX Pause Q size to prevent + reserve all TX descriptors which shared with FW. + High Bandwidth adapter will have more count of TX Pause Q size + + PARAMETERS + IN + vos_ctx : Global OS context context + sessionId : adapter instance index + max_q_depth : Max pause Q depth for adapter + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetAdapterMaxQDepth +( + void *vos_ctx, + v_U8_t sessionId, + int max_q_depth +) +{ + struct txrx_tl_shim_ctx *tl_shim; + + tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + if ((!tl_shim) || (!tl_shim->session_flow_control)) { + TLSHIM_LOGE("%s: TLSHIM NULL or FC main context NULL", + __func__); + return; + } + + adf_os_spin_lock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + if (!tl_shim->session_flow_control[sessionId].vdev) { + TLSHIM_LOGD("%s, session id %d, VDEV NULL", + __func__, sessionId); + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + return; + } + wdi_in_ll_set_tx_pause_q_depth( + (struct ol_txrx_vdev_t *)tl_shim->session_flow_control[sessionId].vdev, + max_q_depth); + adf_os_spin_unlock_bh(&tl_shim->session_flow_control[sessionId].fc_lock); + + return; +} +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL +void tl_shim_set_peer_authorized_event(void *vos_ctx, v_U8_t session_id) +{ + struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); + + if (!tl_shim) { + TLSHIM_LOGE("%s: Failed to get TLSHIM context", __func__); + return; + } + + vos_event_set(&tl_shim->peer_authorized_events[session_id]); +} +#endif + +#ifdef IPA_UC_OFFLOAD +/*============================================================================= + FUNCTION WLANTL_GetIpaUcResource + + DESCRIPTION + This function will be called by TL client. + Data path resource will be used by FW should be allocated within lower layer. + Shared resource information should be propagated to IPA. + To propagate resource information, client will use this API + + PARAMETERS + IN + vos_ctx : Global OS context context + ce_sr_base_paddr : Copy Engine Source Ring base address + ce_sr_ring_size : Copy Engine Source Ring size + ce_reg_paddr : Copy engine register address + tx_comp_ring_base_paddr : TX COMP ring base address + tx_comp_ring_size : TX COMP ring size + tx_num_alloc_buffer : Number of TX allocated buffer + rx_rdy_ring_base_paddr : RX ready ring base address + rx_rdy_ring_size : RX ready ring size + rx_proc_done_idx_paddr : RX process done index physical address + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_GetIpaUcResource(void *vos_ctx, + v_U32_t *ce_sr_base_paddr, + v_U32_t *ce_sr_ring_size, + v_U32_t *ce_reg_paddr, + v_U32_t *tx_comp_ring_base_paddr, + v_U32_t *tx_comp_ring_size, + v_U32_t *tx_num_alloc_buffer, + v_U32_t *rx_rdy_ring_base_paddr, + v_U32_t *rx_rdy_ring_size, + v_U32_t *rx_proc_done_idx_paddr) +{ + if (!vos_ctx || !((pVosContextType)vos_ctx)->pdev_txrx_ctx) { + TLSHIM_LOGE("%s: Invalid context", __func__); + return; + } + + wdi_in_ipa_uc_get_resource(((pVosContextType)vos_ctx)->pdev_txrx_ctx, + ce_sr_base_paddr, + ce_sr_ring_size, + ce_reg_paddr, + tx_comp_ring_base_paddr, + tx_comp_ring_size, + tx_num_alloc_buffer, + rx_rdy_ring_base_paddr, + rx_rdy_ring_size, + rx_proc_done_idx_paddr); +} + +/*============================================================================= + FUNCTION WLANTL_SetUcDoorbellPaddr + + DESCRIPTION + This function will be called by TL client. + UC controller should provide doorbell register address to firmware + TL client will call this API to pass doorbell register address to firmware + + PARAMETERS + IN + vos_ctx : Global OS context context + ipa_tx_uc_doorbell_paddr : Micro Controller WLAN TX COMP doorbell regiser + ipa_rx_uc_doorbell_paddr : Micro Controller WLAN RX REDY doorbell regiser + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetUcDoorbellPaddr(void *vos_ctx, + v_U32_t ipa_tx_uc_doorbell_paddr, + v_U32_t ipa_rx_uc_doorbell_paddr) +{ + if (!vos_ctx || !((pVosContextType)vos_ctx)->pdev_txrx_ctx) { + TLSHIM_LOGE("%s: Invalid context", __func__); + return; + } + + wdi_in_ipa_uc_set_doorbell_paddr(((pVosContextType)vos_ctx)->pdev_txrx_ctx, + ipa_tx_uc_doorbell_paddr, + ipa_rx_uc_doorbell_paddr); +} + +/*============================================================================= + FUNCTION WLANTL_SetUcActive + + DESCRIPTION + This function will be called by TL client. + Send Micro controller data path active or inactive notification to firmware + + PARAMETERS + IN + vos_ctx : Global OS context context + uc_active : Micro Controller data path is active or not + is_tx : Micro Controller WLAN TX data path is active or not + is_rx : Micro Controller WLAN RX data path is active or not + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetUcActive(void *vos_ctx, + v_BOOL_t uc_active, + v_BOOL_t is_tx +) +{ + if (!vos_ctx || !((pVosContextType)vos_ctx)->pdev_txrx_ctx) { + TLSHIM_LOGE("%s: Invalid context", __func__); + return; + } + + TLSHIM_LOGD("%s, ACTIVE %d, TX %d", + __func__, uc_active, is_tx); + wdi_in_ipa_uc_set_active(((pVosContextType)vos_ctx)->pdev_txrx_ctx, + uc_active, is_tx); +} + +/*============================================================================= + FUNCTION WLANTL_RegisterOPCbFnc + + DESCRIPTION + This function will be called by TL client. + + PARAMETERS + IN + vos_ctx : Global OS context context + func : callback function pointer + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_RegisterOPCbFnc(void *vos_ctx, + void (*func)(v_U8_t *op_msg, void *usr_ctxt), void *usr_ctxt) +{ + wdi_in_ipa_uc_register_op_cb(((pVosContextType)vos_ctx)->pdev_txrx_ctx, + func, usr_ctxt); +} + +/*============================================================================= + FUNCTION WLANTL_disable_intrabss_fwd + + DESCRIPTION + Function to return if Intra-BSS FWD is disabled or not + + PARAMETERS + IN + vdev : vdev handle + + RETURN VALUE + bool : TRUE if Intra-BSS FWD is disabled, FALSE if not + + SIDE EFFECTS + +==============================================================================*/ +bool WLANTL_disable_intrabss_fwd(void *vdev) +{ + return ((ol_txrx_vdev_handle)vdev)->disable_intrabss_fwd; +} +#endif /* IPA_UC_OFFLOAD */ + +/*============================================================================= + FUNCTION WLANTL_RegisterOCBPeer + + DESCRIPTION + Function to register the OCB Self Peer + + PARAMETERS + IN + vos_ctx : Global OS context context + mac_addr : MAC address of self peer + + OUT + peer_id : Peer ID + + RETURN VALUE + VOS_STATUS_SUCCESS on success + VOS_STATUS_E_FAILURE on failure + + SIDE EFFECTS + +==============================================================================*/ +VOS_STATUS WLANTL_RegisterOCBPeer(void *vos_ctx, uint8_t *mac_addr, + uint8_t *peer_id) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_peer_handle peer; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_ctx); + if (!pdev) { + TLSHIM_LOGE("%s: Unable to find pdev!", __func__); + return VOS_STATUS_E_FAILURE; + } + + peer = ol_txrx_find_peer_by_addr(pdev, mac_addr, peer_id); + if (!peer) { + TLSHIM_LOGE("%s: Unable to find OCB peer!", __func__); + return VOS_STATUS_E_FAILURE; + } + + ol_txrx_set_ocb_peer(pdev, peer); + + /* Set peer state to connected */ + ol_txrx_peer_state_update(pdev, peer->mac_addr.raw, + ol_txrx_peer_state_auth); + + return VOS_STATUS_SUCCESS; +} + +void WLANTL_display_datapath_stats(void *vos_ctx, uint16_t value) +{ + ol_txrx_pdev_handle pdev; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_ctx); + if (!pdev) { + TLSHIM_LOGE("%s: Unable to find pdev!", __func__); + return; + } + + wdi_in_display_stats(pdev, value); + return; +} + +void WLANTL_clear_datapath_stats(void *vos_ctx, uint16_t bitmap) +{ + ol_txrx_pdev_handle pdev; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_ctx); + if (!pdev) { + TLSHIM_LOGE("%s: Unable to find pdev!", __func__); + return; + } + + wdi_in_clear_stats(pdev, bitmap); + return; +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.h new file mode 100644 index 000000000000..617bc5b267c5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef TXRX_TL_SHIM_H +#define TXRX_TL_SHIM_H + +#include +#include +#include + +#ifdef FEATURE_WLAN_ESE +typedef struct deferred_iapp_work { + pVosContextType pVosGCtx; + adf_nbuf_t nbuf; + struct ol_txrx_vdev_t *vdev; + bool inUse; + struct work_struct deferred_work; +} deferred_iapp_work; +#endif + +struct tlshim_buf { + struct list_head list; + adf_nbuf_t buf; +}; + +#define TLSHIM_FLUSH_CACHE_IN_PROGRESS 0 +struct tlshim_sta_info { + bool registered; + bool suspend_flush; + WLANTL_STARxCBType data_rx; + /* To protect stainfo data like registered and data_rx */ + adf_os_spinlock_t stainfo_lock; + struct list_head cached_bufq; + unsigned long flags; + v_S7_t first_rssi; + v_U8_t vdev_id; +}; + +#ifdef QCA_LL_TX_FLOW_CT +struct tlshim_session_flow_Control { + WLANTL_TxFlowControlCBType flowControl; + v_U8_t sessionId; + void *adpaterCtxt; + void *vdev; + adf_os_spinlock_t fc_lock; +}; +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef IPA_UC_OFFLOAD +typedef void(*ipa_uc_fw_op_cb)(v_U8_t *op_msg, void *usr_ctxt); +#endif /* IPA_UC_OFFLOAD */ + +struct txrx_tl_shim_ctx { + void *cfg_ctx; + ol_txrx_tx_fp tx; + WLANTL_MgmtFrmRxCBType mgmt_rx; + struct tlshim_sta_info sta_info[WLAN_MAX_STA_COUNT]; + adf_os_spinlock_t bufq_lock; + adf_os_spinlock_t mgmt_lock; + struct work_struct cache_flush_work; + +#ifdef FEATURE_WLAN_ESE + /* + * work structures to defer IAPP processing to + * non interrupt context + */ +struct deferred_iapp_work iapp_work; +#endif + v_BOOL_t ip_checksum_offload; + u_int8_t *last_beacon_data; + u_int32_t last_beacon_len; + u_int32_t delay_interval; + v_BOOL_t enable_rxthread; + adf_os_atomic_t *vdev_active; +#ifdef QCA_LL_TX_FLOW_CT + struct tlshim_session_flow_Control *session_flow_control; +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + vos_event_t *peer_authorized_events; +#endif +#ifdef IPA_UC_OFFLOAD + ipa_uc_fw_op_cb fw_op_cb; + void *usr_ctxt; +#endif /* IPA_UC_OFFLOAD */ +}; + +/* + * APIs used by CLD specific components, as of now these are used only + * in WMA. + */ +void WLANTL_RegisterVdev(void *vos_ctx, void *vdev); +void WLANTL_UnRegisterVdev(void *vos_ctx, u_int8_t vdev_id); +VOS_STATUS tl_shim_get_vdevid(struct ol_txrx_peer_t *peer, u_int8_t *vdev_id); + +/* + * tlshim_mgmt_roam_event_ind() is called from WMA layer when + * BETTER_AP_FOUND event is received from roam engine. + */ +int tlshim_mgmt_roam_event_ind(void *context, u_int32_t vdev_id); +void *tl_shim_get_vdev_by_addr(void *vos_context, uint8_t *mac_addr); +void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id); + +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL +void tl_shim_set_peer_authorized_event(void *vos_ctx, v_U8_t session_id); +#else +static inline void tl_shim_set_peer_authorized_event(void *vos_ctx, v_U8_t session_id) +{ +} +#endif +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_cfg.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_cfg.c new file mode 100644 index 000000000000..26a3f2433a16 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_cfg.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include + +unsigned int vow_config = 0; +module_param(vow_config, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(vow_config, "Do VoW Configuration"); +EXPORT_SYMBOL(vow_config); + +/* FIX THIS - + * For now, all these configuration parameters are hardcoded. + * Many of these should actually be determined dynamically instead. + */ + +ol_pdev_handle ol_pdev_cfg_attach(adf_os_device_t osdev, + struct txrx_pdev_cfg_param_t cfg_param) +{ + struct txrx_pdev_cfg_t *cfg_ctx; + + cfg_ctx = adf_os_mem_alloc(osdev, sizeof(*cfg_ctx)); + if (!cfg_ctx) { + printk(KERN_ERR "cfg ctx allocation failed\n"); + return NULL; + } + +#ifdef CONFIG_HL_SUPPORT + cfg_ctx->is_high_latency = 1; + /* 802.1Q and SNAP / LLC headers are accounted for elsewhere */ + cfg_ctx->tx_download_size = 1500; + cfg_ctx->tx_free_at_download = 0; +#else + /* + * Need to change HTT_LL_TX_HDR_SIZE_IP accordingly. + * Include payload, up to the end of UDP header for IPv4 case + */ + cfg_ctx->tx_download_size = 16; +#endif + /* temporarily diabled PN check for Riva/Pronto */ + cfg_ctx->rx_pn_check = 1; +#if CFG_TGT_DEFAULT_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK + cfg_ctx->defrag_timeout_check = 1; +#else + cfg_ctx->defrag_timeout_check = 0; +#endif + cfg_ctx->max_peer_id = 511; + cfg_ctx->max_vdev = CFG_TGT_NUM_VDEV; + cfg_ctx->pn_rx_fwd_check = 1; + cfg_ctx->frame_type = wlan_frm_fmt_802_3; + cfg_ctx->max_thruput_mbps = 800; + cfg_ctx->max_nbuf_frags = 1; + cfg_ctx->vow_config = vow_config; + cfg_ctx->target_tx_credit = CFG_TGT_NUM_MSDU_DESC; + cfg_ctx->throttle_period_ms = 40; + cfg_ctx->rx_fwd_disabled = 0; + cfg_ctx->is_packet_log_enabled = 0; + cfg_ctx->is_full_reorder_offload = cfg_param.is_full_reorder_offload; +#ifdef IPA_UC_OFFLOAD + cfg_ctx->ipa_uc_rsc.uc_offload_enabled = cfg_param.is_uc_offload_enabled; + cfg_ctx->ipa_uc_rsc.tx_max_buf_cnt = cfg_param.uc_tx_buffer_count; + cfg_ctx->ipa_uc_rsc.tx_buf_size = cfg_param.uc_tx_buffer_size; + cfg_ctx->ipa_uc_rsc.rx_ind_ring_size = cfg_param.uc_rx_indication_ring_count; + cfg_ctx->ipa_uc_rsc.tx_partition_base = cfg_param.uc_tx_partition_base; +#endif /* IPA_UC_OFFLOAD */ + return (ol_pdev_handle) cfg_ctx; +} + +int ol_cfg_is_high_latency(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->is_high_latency; +} + +int ol_cfg_max_peer_id(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + /* + * TBDXXX - this value must match the peer table + * size allocated in FW + */ + return cfg->max_peer_id; +} + +int ol_cfg_max_vdevs(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->max_vdev; +} + +int ol_cfg_rx_pn_check(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->rx_pn_check; +} + +int ol_cfg_rx_fwd_check(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->pn_rx_fwd_check; +} + +void ol_set_cfg_rx_fwd_disabled(ol_pdev_handle pdev, u_int8_t disable_rx_fwd) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + cfg->rx_fwd_disabled = disable_rx_fwd; +} + +void ol_set_cfg_packet_log_enabled(ol_pdev_handle pdev, u_int8_t val) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + cfg->is_packet_log_enabled = val; +} + +u_int8_t ol_cfg_is_packet_log_enabled(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->is_packet_log_enabled; +} + +int ol_cfg_rx_fwd_disabled(ol_pdev_handle pdev) +{ +#if defined(ATHR_WIN_NWF) + /* for Windows, let the OS handle the forwarding */ + return 1; +#else + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->rx_fwd_disabled; +#endif +} + +int ol_cfg_rx_fwd_inter_bss(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->rx_fwd_inter_bss; +} + +enum wlan_frm_fmt ol_cfg_frame_type(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->frame_type; +} + +int ol_cfg_max_thruput_mbps(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->max_thruput_mbps; +} + +int ol_cfg_netbuf_frags_max(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->max_nbuf_frags; +} + +int ol_cfg_tx_free_at_download(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->tx_free_at_download; +} + +void ol_cfg_set_tx_free_at_download(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + cfg->tx_free_at_download = 1; +} +u_int16_t ol_cfg_target_tx_credit(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; +#ifndef CONFIG_HL_SUPPORT + u_int16_t vow_max_sta = (cfg->vow_config & 0xffff0000) >> 16; + u_int16_t vow_max_desc_persta = cfg->vow_config & 0x0000ffff; + + return (cfg->target_tx_credit + + (vow_max_sta * vow_max_desc_persta)); +#else + return cfg->target_tx_credit; +#endif +} + +int ol_cfg_tx_download_size(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->tx_download_size; +} + +int ol_cfg_rx_host_defrag_timeout_duplicate_check(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->defrag_timeout_check; +} + +int ol_cfg_throttle_period_ms(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->throttle_period_ms; +} + +int ol_cfg_is_full_reorder_offload(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->is_full_reorder_offload; +} + +#ifdef IPA_UC_OFFLOAD +unsigned int ol_cfg_ipa_uc_offload_enabled(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return (unsigned int)cfg->ipa_uc_rsc.uc_offload_enabled; +} + +unsigned int ol_cfg_ipa_uc_tx_buf_size(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->ipa_uc_rsc.tx_buf_size; +} + +unsigned int ol_cfg_ipa_uc_tx_max_buf_cnt(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->ipa_uc_rsc.tx_max_buf_cnt; +} + +unsigned int ol_cfg_ipa_uc_rx_ind_ring_size(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->ipa_uc_rsc.rx_ind_ring_size; +} + +unsigned int ol_cfg_ipa_uc_tx_partition_base(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->ipa_uc_rsc.tx_partition_base; +} +#endif /* IPA_UC_OFFLOAD */ + diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_ctrl_txrx_api.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_ctrl_txrx_api.h new file mode 100644 index 000000000000..30e8d1d54f70 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_ctrl_txrx_api.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_ctrl_txrx_api.h + * @brief Define the host control API functions called by the host data SW. + */ +#ifndef _OL_CTRL_TXRX_API__H_ +#define _OL_CTRL_TXRX_API__H_ + +//#include /* u_int8_t */ +#include /* u_int8_t */ +#include /* adf_nbuf_t */ + +#include /* ol_vdev_handle */ +#include /* ol_txrx_peer_handle, etc. */ +#include /* ol_txrx_peer_handle, etc. */ +#include /*ieee80211_frame */ + +enum ol_rx_err_type { + OL_RX_ERR_DEFRAG_MIC, + OL_RX_ERR_PN, + OL_RX_ERR_UNKNOWN_PEER, + OL_RX_ERR_MALFORMED, + OL_RX_ERR_TKIP_MIC, + OL_RX_ERR_DECRYPT, + OL_RX_ERR_MPDU_LENGTH, + OL_RX_ERR_ENCRYPT_REQUIRED, + OL_RX_ERR_DUP, + OL_RX_ERR_UNKNOWN, + OL_RX_ERR_FCS, + OL_RX_ERR_PRIVACY, + OL_RX_ERR_NONE_FRAG, + OL_RX_ERR_NONE = 0xFF +}; + +#ifdef SUPPORT_HOST_STATISTICS +/** * @brief Update tx statistics + * @details + * Update tx statistics after tx complete. + * + * @param pdev - ol_pdev_handle instance + * @param vdev_id - ID of the virtual device that tx frame + * @param had_error - whether there is error when tx + */ +void ol_tx_statistics(ol_pdev_handle pdev, + u_int16_t vdev_id, + int had_error); +#else +#define ol_tx_statistics(pdev, vdev_id, had_error) +#endif + +/** * @brief Count on received packets for invalid peer case + * + * @param pdev - txrx pdev handle + * @param wh - received frame + * @param err_type - what kind of error occurred + */ +void ol_rx_err_inv_peer_statistics(ol_pdev_handle pdev, + struct ieee80211_frame *wh, + enum ol_rx_err_type err_type); + +/** + * @brief Count on received packets, both success and failed + * + * @param pdev - ol_pdev_handle handle + * @param vdev_id - ID of the virtual device received the erroneous rx frame + * @param err_type - what kind of error occurred + * @param sec_type - The cipher type the peer is using + * @param is_mcast - whether this is one multi cast frame + */ +void ol_rx_err_statistics(ol_pdev_handle pdev, + u_int8_t vdev_id, + enum ol_rx_err_type err_type, + enum ol_sec_type sec_type, + int is_mcast); + +/** + * @brief Provide notification of failure during host rx processing + * @details + * Indicate an error during host rx data processing, including what + * kind of error happened, when it happened, which peer and TID the + * erroneous rx frame is from, and what the erroneous rx frame itself + * is. + * + * @param pdev - handle to the ctrl SW's physical device object + * @param vdev_id - ID of the virtual device received the erroneous rx frame + * @param peer_mac_addr - MAC address of the peer that sent the erroneous + * rx frame + * @param tid - which TID within the peer sent the erroneous rx frame + * @param tsf32 - the timstamp in TSF units of the erroneous rx frame, or + * one of the fragments that when reassembled, constitute the rx frame + * @param err_type - what kind of error occurred + * @param rx_frame - the rx frame that had an error + * @pn - Packet sequence number + * @key_id - Key index octet received in IV of the frame + */ +void +ol_rx_err( + ol_pdev_handle pdev, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tid, + u_int32_t tsf32, + enum ol_rx_err_type err_type, + adf_nbuf_t rx_frame, + u_int64_t *pn, + u_int8_t key_id); + + +enum ol_rx_notify_type { + OL_RX_NOTIFY_IPV4_IGMP, +}; + +struct ol_mic_error_info { + u_int8_t vdev_id; + u_int32_t key_id; + u_int64_t pn; + u_int8_t sa[OL_TXRX_MAC_ADDR_LEN]; + u_int8_t da[OL_TXRX_MAC_ADDR_LEN]; + u_int8_t ta[OL_TXRX_MAC_ADDR_LEN]; +}; + +struct ol_error_info { + union { + struct ol_mic_error_info mic_err; + } u; +}; + +/** + * @brief Indicate an error to the protocol stack. + * @details + * Indicate an error from the data path to the protocol stack + * + * @param err_type - error type + * @param err_info - information associated with the error + */ +void +ol_indicate_err( + enum ol_rx_err_type err_type, + struct ol_error_info * err_info); + +/** + * @brief Provide notification of reception of data of special interest. + * @details + * Indicate when "special" data has been received. The nature of the + * data that results in it being considered special is specified in the + * notify_type argument. + * This function is currently used by the data-path SW to notify the + * control path SW when the following types of rx data are received: + * + IPv4 IGMP frames + * The control SW can use these to learn about multicast group + * membership, if it so chooses. + * + * @param pdev - handle to the ctrl SW's physical device object + * @param vdev_id - ID of the virtual device received the special data + * @param peer_mac_addr - MAC address of the peer that sent the special data + * @param tid - which TID within the peer sent the special data + * @param tsf32 - the timstamp in TSF units of the special data + * @param notify_type - what kind of special data was received + * @param rx_frame - the rx frame containing the special data + */ +void +ol_rx_notify( + ol_pdev_handle pdev, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tid, + u_int32_t tsf32, + enum ol_rx_notify_type notify_type, + adf_nbuf_t rx_frame); + +/** + * @brief Indicate when a paused STA has tx data available. + * @details + * Indicate to the control SW when a paused peer that previously + * has all its peer-TID queues empty gets a MSDU to transmit. + * Conversely, indicate when a paused peer that had data in one or more of + * its peer-TID queues has all queued data removed (e.g. due to a U-APSD + * triggered transmission), but is still paused. + * It is up to the control SW to determine whether the peer is paused due to + * being in power-save sleep, or some other reason, and thus whether it is + * necessary to set the TIM in beacons to notify a sleeping STA that it has + * data. + * The data SW will also issue this ol_tx_paused_peer_data call when an + * unpaused peer that currently has tx data in one or more of its + * peer-TID queues becomes paused. + * The data SW will not issue this ol_tx_paused_peer_data call when a + * peer with data in one or more of its peer-TID queues becomes unpaused. + * + * @param peer - the paused peer + * @param has_tx_data - + * 1 -> a paused peer that previously had no tx data now does, -OR- + * 0 -> a paused peer that previously had tx data now doesnt + */ +void +ol_tx_paused_peer_data(ol_peer_handle peer, int has_tx_data); + + +#define ol_ctrl_addba_req(pdev, peer_mac_addr, tid) ol_addba_req_reject +#define ol_ctrl_rx_addba_complete(pdev, peer_mac_addr, tid, failed) /* no-op */ + + + +#endif /* _OL_CTRL_TXRX_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_osif_txrx_api.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_osif_txrx_api.h new file mode 100644 index 000000000000..bee1f1d4b1c6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_osif_txrx_api.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_osif_txrx_api.h + * @brief Define the OS specific API functions called by txrx SW. + */ +#ifndef _OL_OSIF_TXRX_API_H_ +#define _OL_OSIF_TXRX_API_H_ + +#include /* adf_nbuf_t */ + +/** + * @brief Call tx completion handler to release the buffers + * @details + * + * Invoke tx completion handler when the tx credit goes below low water mark. + * This eliminate the packet drop in the host driver due to send routine not yielding + * the cpu when the amount of traffic pumped from the network layer is very high. + * + * @param osdev + */ + +void ol_osif_ath_tasklet(adf_os_device_t osdev); + +#endif /* _OL_OSIF_TXRX_API_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.c new file mode 100644 index 000000000000..7d0eea72d74b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.c @@ -0,0 +1,1423 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_cpu_to_le64 */ +#include /* a_bool_t */ +#include /* ieee80211_frame */ + +/* external API header files */ +#include /* ol_rx_notify */ +#include /* htt_pdev_handle */ +#include /* ol_txrx_pdev_handle */ +#include /* ol_rx_indication_handler */ +#include /* htt_rx_peer_id, etc. */ + +/* internal API header files */ +#include /* ol_txrx_vdev_t, etc. */ +#include /* ol_txrx_peer_find_by_id */ +#include /* ol_rx_reorder_store, etc. */ +#include /* OL_RX_REORDER_TIMEOUT_UPDATE */ +#include /* ol_rx_defrag_waitlist_flush */ +#include +#include +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP +#include /* ol_rx_decap_info_t, etc*/ +#endif + +/* FIX THIS: txrx should not include private header files of other modules */ +#include +#include +#include /* ethernet + SNAP/LLC header defs and ethertype values */ +#include /* IP protocol values */ +#include /* IPv4 header defs */ +#include /* IPv6 header defs */ +#include +#include + +#ifdef HTT_RX_RESTORE +#if defined(CONFIG_CNSS) +#include +#endif +#endif + +#ifdef OSIF_NEED_RX_PEER_ID +#define OL_RX_OSIF_DELIVER(vdev, peer, msdus) \ + vdev->osif_rx(vdev->osif_dev, peer->local_id, msdus) +#else +#define OL_RX_OSIF_DELIVER(vdev, peer, msdus) \ + vdev->osif_rx(vdev->osif_dev, msdus) +#endif /* OSIF_NEED_RX_PEER_ID */ + +#ifdef HTT_RX_RESTORE + +static void ol_rx_restore_handler(struct work_struct *htt_rx) +{ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "Enter: %s", __func__); + cnss_device_self_recovery(); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "Exit: %s", __func__); +} + +static DECLARE_WORK(ol_rx_restore_work, ol_rx_restore_handler); + +void ol_rx_trigger_restore(htt_pdev_handle htt_pdev, adf_nbuf_t head_msdu, + adf_nbuf_t tail_msdu) +{ + adf_nbuf_t next; + + while (head_msdu) { + next = adf_nbuf_next(head_msdu); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "freeing %p\n", head_msdu); + adf_nbuf_free(head_msdu); + head_msdu = next; + } + + if ( !htt_pdev->rx_ring.htt_rx_restore){ + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + htt_pdev->rx_ring.htt_rx_restore = 1; + schedule_work(&ol_rx_restore_work); + } +} +#endif + +static void ol_rx_process_inv_peer( + ol_txrx_pdev_handle pdev, + void *rx_mpdu_desc, + adf_nbuf_t msdu + ) +{ + a_uint8_t a1[IEEE80211_ADDR_LEN]; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + struct ol_txrx_vdev_t *vdev = NULL; + struct ieee80211_frame *wh; + struct wdi_event_rx_peer_invalid_msg msg; + + wh = (struct ieee80211_frame *) + htt_rx_mpdu_wifi_hdr_retrieve(htt_pdev, rx_mpdu_desc); + /* + * Klocwork issue #6152 + * All targets that send a "INVALID_PEER" rx status provide a + * 802.11 header for each rx MPDU, so it is certain that + * htt_rx_mpdu_wifi_hdr_retrieve will succeed. + * However, both for robustness, e.g. if this function is given a + * MSDU descriptor rather than a MPDU descriptor, and to make it + * clear to static analysis that this code is safe, add an explicit + * check that htt_rx_mpdu_wifi_hdr_retrieve provides a non-NULL value. + */ + if (wh == NULL || !IEEE80211_IS_DATA(wh)) { + return; + } + + /* ignore frames for non-existent bssids */ + adf_os_mem_copy(a1, wh->i_addr1, IEEE80211_ADDR_LEN); + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if (adf_os_mem_cmp(a1, vdev->mac_addr.raw, IEEE80211_ADDR_LEN) == 0) { + break; + } + } + if (!vdev) { + return; + } + msg.wh = wh; + msg.msdu = msdu; + msg.vdev_id = vdev->vdev_id; + #ifdef WDI_EVENT_ENABLE + wdi_event_handler(WDI_EVENT_RX_PEER_INVALID, pdev, &msg); + #endif +} + +#ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI +static inline int16_t +ol_rx_rssi_avg(struct ol_txrx_pdev_t *pdev, int16_t rssi_old, int16_t rssi_new) +{ + int rssi_old_weight; + + if (rssi_new == HTT_RSSI_INVALID) { + return rssi_old; + } + if (rssi_old == HTT_RSSI_INVALID) { + return rssi_new; + } + rssi_old_weight = (1 << pdev->rssi_update_shift) - pdev->rssi_new_weight; + return (rssi_new * pdev->rssi_new_weight + rssi_old * rssi_old_weight) >> + pdev->rssi_update_shift; +} + +static void +OL_RX_IND_RSSI_UPDATE( + struct ol_txrx_peer_t *peer, + adf_nbuf_t rx_ind_msg) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + peer->rssi_dbm = ol_rx_rssi_avg( + pdev, peer->rssi_dbm, + htt_rx_ind_rssi_dbm(pdev->htt_pdev, rx_ind_msg)); +} + +static void +OL_RX_MPDU_RSSI_UPDATE( + struct ol_txrx_peer_t *peer, + void *rx_mpdu_desc) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + if (! peer) { + return; + } + peer->rssi_dbm = ol_rx_rssi_avg( + pdev, peer->rssi_dbm, + htt_rx_mpdu_desc_rssi_dbm(pdev->htt_pdev, rx_mpdu_desc)); +} + +#else +#define OL_RX_IND_RSSI_UPDATE(peer, rx_ind_msg) /* no-op */ +#define OL_RX_MPDU_RSSI_UPDATE(peer, rx_mpdu_desc) /* no-op */ +#endif /* QCA_SUPPORT_PEER_DATA_RX_RSSI */ + +void +ol_rx_indication_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + u_int16_t peer_id, + u_int8_t tid, + int num_mpdu_ranges) +{ + int mpdu_range, i; + unsigned seq_num_start = 0, seq_num_end = 0; + a_bool_t rx_ind_release = A_FALSE; + struct ol_txrx_vdev_t *vdev = NULL; + struct ol_txrx_peer_t *peer; + htt_pdev_handle htt_pdev; + uint16_t center_freq; + uint16_t chan1; + uint16_t chan2; + uint8_t phymode; + a_bool_t ret; + + htt_pdev = pdev->htt_pdev; + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (!peer) { + /* If we can't find a peer send this packet to OCB interface using + OCB self peer */ + if (!ol_txrx_get_ocb_peer(pdev, &peer)) + peer = NULL; + } + + if (peer) { + vdev = peer->vdev; + OL_RX_IND_RSSI_UPDATE(peer, rx_ind_msg); + + if (vdev->opmode == wlan_op_mode_ocb) { + htt_rx_ind_legacy_rate(pdev->htt_pdev, rx_ind_msg, + &peer->last_pkt_legacy_rate, + &peer->last_pkt_legacy_rate_sel); + peer->last_pkt_rssi_cmb = htt_rx_ind_rssi_dbm(pdev->htt_pdev, + rx_ind_msg); + for (i = 0; i < 4; i++) + peer->last_pkt_rssi[i] = htt_rx_ind_rssi_dbm_chain( + pdev->htt_pdev, rx_ind_msg, i); + htt_rx_ind_timestamp(pdev->htt_pdev, rx_ind_msg, + &peer->last_pkt_timestamp_microsec, + &peer->last_pkt_timestamp_submicrosec); + peer->last_pkt_tsf = htt_rx_ind_tsf32(pdev->htt_pdev, rx_ind_msg); + peer->last_pkt_tid = htt_rx_ind_ext_tid(pdev->htt_pdev, rx_ind_msg); + } + } + + TXRX_STATS_INCR(pdev, priv.rx.normal.ppdus); + + OL_RX_REORDER_TIMEOUT_MUTEX_LOCK(pdev); + + if (htt_rx_ind_flush(pdev->htt_pdev, rx_ind_msg) && peer) { + htt_rx_ind_flush_seq_num_range( + pdev->htt_pdev, rx_ind_msg, &seq_num_start, &seq_num_end); + if (tid == HTT_INVALID_TID) { + /* + * host/FW reorder state went out-of sync + * for a while because FW ran out of Rx indication + * buffer. We have to discard all the buffers in + * reorder queue. + */ + ol_rx_reorder_peer_cleanup(vdev, peer); + } else { + ol_rx_reorder_flush( + vdev, peer, tid, seq_num_start, + seq_num_end, htt_rx_flush_release); + } + } + + if (htt_rx_ind_release(pdev->htt_pdev, rx_ind_msg)) { + /* the ind info of release is saved here and do release at the end. + * This is for the reason of in HL case, the adf_nbuf_t for msg and + * payload are the same buf. And the buf will be changed during + * processing */ + rx_ind_release = A_TRUE; + htt_rx_ind_release_seq_num_range( + pdev->htt_pdev, rx_ind_msg, &seq_num_start, &seq_num_end); + } + +#ifdef DEBUG_DMA_DONE + pdev->htt_pdev->rx_ring.dbg_initial_msdu_payld = + pdev->htt_pdev->rx_ring.sw_rd_idx.msdu_payld; +#endif + + for (mpdu_range = 0; mpdu_range < num_mpdu_ranges; mpdu_range++) { + enum htt_rx_status status; + int i, num_mpdus; + adf_nbuf_t head_msdu, tail_msdu, msdu; + void *rx_mpdu_desc; + +#ifdef DEBUG_DMA_DONE + pdev->htt_pdev->rx_ring.dbg_mpdu_range = mpdu_range; +#endif + + htt_rx_ind_mpdu_range_info( + pdev->htt_pdev, rx_ind_msg, mpdu_range, &status, &num_mpdus); + if ((status == htt_rx_status_ok) && peer) { + TXRX_STATS_ADD(pdev, priv.rx.normal.mpdus, num_mpdus); + /* valid frame - deposit it into the rx reordering buffer */ + for (i = 0; i < num_mpdus; i++) { + int msdu_chaining; + /* + * Get a linked list of the MSDUs that comprise this MPDU. + * This also attaches each rx MSDU descriptor to the + * corresponding rx MSDU network buffer. + * (In some systems, the rx MSDU desc is already in the + * same buffer as the MSDU payload; in other systems they + * are separate, so a pointer needs to be set in the netbuf + * to locate the corresponding rx descriptor.) + * + * It is neccessary to call htt_rx_amsdu_pop before + * htt_rx_mpdu_desc_list_next, because the (MPDU) rx + * descriptor has the DMA unmapping done during the + * htt_rx_amsdu_pop call. The rx desc should not be + * accessed until this DMA unmapping has been done, + * since the DMA unmapping involves making sure the + * cache area for the mapped buffer is flushed, so the + * data written by the MAC DMA into memory will be + * fetched, rather than garbage from the cache. + */ + +#ifdef DEBUG_DMA_DONE + pdev->htt_pdev->rx_ring.dbg_mpdu_count = i; +#endif + + msdu_chaining = htt_rx_amsdu_pop( + htt_pdev, rx_ind_msg, &head_msdu, &tail_msdu); +#ifdef HTT_RX_RESTORE + if (htt_pdev->rx_ring.rx_reset) { + ol_rx_trigger_restore(htt_pdev, head_msdu, tail_msdu); + return; + } +#endif + rx_mpdu_desc = + htt_rx_mpdu_desc_list_next(htt_pdev, rx_ind_msg); + ret = htt_rx_msdu_center_freq(htt_pdev, peer, rx_mpdu_desc, + ¢er_freq, &chan1, &chan2, &phymode); + if (ret == A_TRUE) { + peer->last_pkt_center_freq = center_freq; + } else { + peer->last_pkt_center_freq = 0; + } + + /* Pktlog */ + #ifdef WDI_EVENT_ENABLE + wdi_event_handler(WDI_EVENT_RX_DESC_REMOTE, pdev, head_msdu); + #endif + + if (msdu_chaining) { + /* + * TBDXXX - to deliver SDU with chaining, we need to + * stitch those scattered buffers into one single buffer. + * Just discard it now. + */ + while (1) { + adf_nbuf_t next; + next = adf_nbuf_next(head_msdu); + htt_rx_desc_frame_free(htt_pdev, head_msdu); + if (head_msdu == tail_msdu) { + break; + } + head_msdu = next; + } + } else { + enum htt_rx_status mpdu_status; + int reorder_idx; + reorder_idx = + htt_rx_mpdu_desc_reorder_idx(htt_pdev, rx_mpdu_desc); + OL_RX_REORDER_TRACE_ADD( + pdev, tid, reorder_idx, + htt_rx_mpdu_desc_seq_num(htt_pdev, rx_mpdu_desc), 1); + OL_RX_MPDU_RSSI_UPDATE(peer, rx_mpdu_desc); + /* + * In most cases, out-of-bounds and duplicate sequence + * number detection is performed by the target, but in + * some cases it is done by the host. + * Specifically, the host does rx out-of-bounds sequence + * number detection for: + * 1. Peregrine or Rome target for peer-TIDs that do + * not have aggregation enabled, if the + * RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK flag + * is set during the driver build. + * 2. Riva-family targets, which have rx reorder timeouts + * handled by the host rather than the target. + * (The target already does duplicate detection, but + * the host may have given up waiting for a particular + * sequence number before it arrives. In this case, + * the out-of-bounds sequence number of the late frame + * allows the host to discard it, rather than sending + * it out of order. + */ + mpdu_status = OL_RX_SEQ_NUM_CHECK( + pdev, peer, tid, rx_mpdu_desc); + + if (mpdu_status != htt_rx_status_ok) { + /* + * If the sequence number was out of bounds, + * the MPDU needs to be discarded. + */ + while (1) { + adf_nbuf_t next; + next = adf_nbuf_next(head_msdu); + htt_rx_desc_frame_free(htt_pdev, head_msdu); + if (head_msdu == tail_msdu) { + break; + } + head_msdu = next; + } + + /* + * For Peregrine and Rome, + * OL_RX_REORDER_SEQ_NUM_CHECK should only fail for + * the case of (duplicate) non-aggregates. + * + * For Riva, Pronto, and Northstar, + * there should be only one MPDU delivered at a time. + * Thus, there are no further MPDUs that need to be + * processed here. + * Just to be sure this is true, check the assumption + * that this was the only MPDU referenced by the rx + * indication. + */ + TXRX_ASSERT2(num_mpdu_ranges == 1 && num_mpdus == 1); + + /* + * The MPDU was not stored in the rx reorder array, + * so there's nothing to release. + */ + rx_ind_release = A_FALSE; + } else { + ol_rx_reorder_store( + pdev, peer, tid, reorder_idx, head_msdu, tail_msdu); + if (peer->tids_rx_reorder[tid].win_sz_mask == 0) { + peer->tids_last_seq[tid] = + htt_rx_mpdu_desc_seq_num(htt_pdev, + rx_mpdu_desc); + } + } + } + } + } else { + /* invalid frames - discard them */ + OL_RX_REORDER_TRACE_ADD( + pdev, tid, TXRX_SEQ_NUM_ERR(status), + TXRX_SEQ_NUM_ERR(status), num_mpdus); + TXRX_STATS_ADD(pdev, priv.rx.err.mpdu_bad, num_mpdus); + for (i = 0; i < num_mpdus; i++) { + /* pull the MPDU's MSDUs off the buffer queue */ + htt_rx_amsdu_pop(htt_pdev, rx_ind_msg, &msdu, &tail_msdu); +#ifdef HTT_RX_RESTORE + if (htt_pdev->rx_ring.rx_reset) { + ol_rx_trigger_restore(htt_pdev, msdu, tail_msdu); + return; + } +#endif + /* pull the MPDU desc off the desc queue */ + rx_mpdu_desc = + htt_rx_mpdu_desc_list_next(htt_pdev, rx_ind_msg); + OL_RX_ERR_STATISTICS_2( + pdev, vdev, peer, rx_mpdu_desc, msdu, status); + + if (status == htt_rx_status_tkip_mic_err && + vdev != NULL && peer != NULL) + { + union htt_rx_pn_t pn; + u_int8_t key_id; + htt_rx_mpdu_desc_pn(pdev->htt_pdev, + htt_rx_msdu_desc_retrieve(pdev->htt_pdev, + msdu), &pn, 48); + if (htt_rx_msdu_desc_key_id(pdev->htt_pdev, + htt_rx_msdu_desc_retrieve(pdev->htt_pdev, + msdu), &key_id) == A_TRUE) { + ol_rx_err(pdev->ctrl_pdev, vdev->vdev_id, + peer->mac_addr.raw, tid, 0, + OL_RX_ERR_TKIP_MIC, msdu, &pn.pn48, key_id); + } + } + + #ifdef WDI_EVENT_ENABLE + if (status != htt_rx_status_ctrl_mgmt_null) { + /* Pktlog */ + wdi_event_handler(WDI_EVENT_RX_DESC_REMOTE, pdev, msdu); + } + #endif + if (status == htt_rx_status_err_inv_peer) { + /* once per mpdu */ + ol_rx_process_inv_peer(pdev, rx_mpdu_desc, msdu); + } + while (1) { + /* Free the nbuf */ + adf_nbuf_t next; + next = adf_nbuf_next(msdu); + htt_rx_desc_frame_free(htt_pdev, msdu); + if (msdu == tail_msdu) { + break; + } + msdu = next; + } + } + } + } + /* + * Now that a whole batch of MSDUs have been pulled out of HTT + * and put into the rx reorder array, it is an appropriate time + * to request HTT to provide new rx MSDU buffers for the target + * to fill. + * This could be done after the end of this function, but it's + * better to do it now, rather than waiting until after the driver + * and OS finish processing the batch of rx MSDUs. + */ + htt_rx_msdu_buff_replenish(htt_pdev); + + if ((A_TRUE == rx_ind_release) && peer && vdev) { + ol_rx_reorder_release(vdev, peer, tid, seq_num_start, seq_num_end); + } + OL_RX_REORDER_TIMEOUT_UPDATE(peer, tid); + OL_RX_REORDER_TIMEOUT_MUTEX_UNLOCK(pdev); + + if (pdev->rx.flags.defrag_timeout_check) { + ol_rx_defrag_waitlist_flush(pdev); + } +} + +void +ol_rx_sec_ind_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + enum htt_sec_type sec_type, + int is_unicast, + u_int32_t *michael_key, + u_int32_t *rx_pn) +{ + struct ol_txrx_peer_t *peer; + int sec_index, i; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (! peer) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Couldn't find peer from ID %d - skipping security inits\n", + peer_id); + return; + } + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "sec spec for peer %p (%02x:%02x:%02x:%02x:%02x:%02x): " + "%s key of type %d\n", + peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], peer->mac_addr.raw[2], + peer->mac_addr.raw[3], peer->mac_addr.raw[4], peer->mac_addr.raw[5], + is_unicast ? "ucast" : "mcast", + sec_type); + sec_index = is_unicast ? txrx_sec_ucast : txrx_sec_mcast; + peer->security[sec_index].sec_type = sec_type; + /* michael key only valid for TKIP, but for simplicity, copy it anyway */ + adf_os_mem_copy( + &peer->security[sec_index].michael_key[0], + michael_key, + sizeof(peer->security[sec_index].michael_key)); + + if (sec_type != htt_sec_type_wapi) { + adf_os_mem_set(peer->tids_last_pn_valid, 0x00, OL_TXRX_NUM_EXT_TIDS); + } else if (sec_index == txrx_sec_mcast || peer->tids_last_pn_valid[0]) { + for (i = 0; i < OL_TXRX_NUM_EXT_TIDS; i++) { + /* + * Setting PN valid bit for WAPI sec_type, + * since WAPI PN has to be started with predefined value + */ + peer->tids_last_pn_valid[i] = 1; + adf_os_mem_copy( + (u_int8_t *) &peer->tids_last_pn[i], + (u_int8_t *) rx_pn, sizeof(union htt_rx_pn_t)); + peer->tids_last_pn[i].pn128[1] = + adf_os_cpu_to_le64(peer->tids_last_pn[i].pn128[1]); + peer->tids_last_pn[i].pn128[0] = + adf_os_cpu_to_le64(peer->tids_last_pn[i].pn128[0]); + } + } +} + +#if defined(PERE_IP_HDR_ALIGNMENT_WAR) + +#include + +static void +transcap_nwifi_to_8023(adf_nbuf_t msdu) +{ + struct ieee80211_frame *wh; + a_uint32_t hdrsize; + struct llc *llchdr; + struct ether_header *eth_hdr; + a_uint16_t ether_type = 0; + a_uint8_t a1[IEEE80211_ADDR_LEN]; + a_uint8_t a2[IEEE80211_ADDR_LEN]; + a_uint8_t a3[IEEE80211_ADDR_LEN]; + a_uint8_t fc1; + + wh = (struct ieee80211_frame *)adf_nbuf_data(msdu); + adf_os_mem_copy(a1, wh->i_addr1, IEEE80211_ADDR_LEN); + adf_os_mem_copy(a2, wh->i_addr2, IEEE80211_ADDR_LEN); + adf_os_mem_copy(a3, wh->i_addr3, IEEE80211_ADDR_LEN); + fc1 = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; + /* Native Wifi header is 80211 non-QoS header */ + hdrsize = sizeof(struct ieee80211_frame); + + llchdr = (struct llc *)(((a_uint8_t *)adf_nbuf_data(msdu)) + hdrsize); + ether_type = llchdr->llc_un.type_snap.ether_type; + + /* + * Now move the data pointer to the beginning of the mac header : + * new-header = old-hdr + (wifhdrsize + llchdrsize - ethhdrsize) + */ + adf_nbuf_pull_head( + msdu, (hdrsize + sizeof(struct llc) - sizeof(struct ether_header))); + eth_hdr = (struct ether_header *)(adf_nbuf_data(msdu)); + switch (fc1) { + case IEEE80211_FC1_DIR_NODS: + adf_os_mem_copy(eth_hdr->ether_dhost, a1, IEEE80211_ADDR_LEN); + adf_os_mem_copy(eth_hdr->ether_shost, a2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + adf_os_mem_copy(eth_hdr->ether_dhost, a3, IEEE80211_ADDR_LEN); + adf_os_mem_copy(eth_hdr->ether_shost, a2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + adf_os_mem_copy(eth_hdr->ether_dhost, a1, IEEE80211_ADDR_LEN); + adf_os_mem_copy(eth_hdr->ether_shost, a3, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + break; + } + eth_hdr->ether_type = ether_type; +} +#endif + +void ol_rx_notify(ol_pdev_handle pdev, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tid, + u_int32_t tsf32, + enum ol_rx_notify_type notify_type, + adf_nbuf_t rx_frame) +{ + /* + * NOTE: This is used in qca_main for AP mode to handle IGMP + * packets specially. Umac has a corresponding handler for this + * not sure if we need to have this for CLD as well. + */ +} + +/** + * @brief Look into a rx MSDU to see what kind of special handling it requires + * @details + * This function is called when the host rx SW sees that the target + * rx FW has marked a rx MSDU as needing inspection. + * Based on the results of the inspection, the host rx SW will infer + * what special handling to perform on the rx frame. + * Currently, the only type of frames that require special handling + * are IGMP frames. The rx data-path SW checks if the frame is IGMP + * (it should be, since the target would not have set the inspect flag + * otherwise), and then calls the ol_rx_notify function so the + * control-path SW can perform multicast group membership learning + * by sniffing the IGMP frame. + */ +#define SIZEOF_80211_HDR (sizeof(struct ieee80211_frame)) +void +ol_rx_inspect( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu, + void *rx_desc) +{ + ol_txrx_pdev_handle pdev = vdev->pdev; + u_int8_t *data, *l3_hdr; + u_int16_t ethertype; + int offset; + + data = adf_nbuf_data(msdu); + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + offset = SIZEOF_80211_HDR + LLC_SNAP_HDR_OFFSET_ETHERTYPE; + l3_hdr = data + SIZEOF_80211_HDR + LLC_SNAP_HDR_LEN; + } else { + offset = ETHERNET_ADDR_LEN * 2; + l3_hdr = data + ETHERNET_HDR_LEN; + } + ethertype = (data[offset] << 8) | data[offset+1]; + if (ethertype == ETHERTYPE_IPV4) { + offset = IPV4_HDR_OFFSET_PROTOCOL; + if (l3_hdr[offset] == IP_PROTOCOL_IGMP) { + ol_rx_notify( + pdev->ctrl_pdev, + vdev->vdev_id, + peer->mac_addr.raw, + tid, + htt_rx_mpdu_desc_tsf32(pdev->htt_pdev, rx_desc), + OL_RX_NOTIFY_IPV4_IGMP, + msdu); + } + } +} + +void +ol_rx_offload_deliver_ind_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msg, + int msdu_cnt) +{ + int vdev_id, peer_id, tid; + adf_nbuf_t head_buf, tail_buf, buf; + struct ol_txrx_peer_t *peer; + struct ol_txrx_vdev_t *vdev = NULL; + u_int8_t fw_desc; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + while (msdu_cnt) { + htt_rx_offload_msdu_pop( + htt_pdev, msg, &vdev_id, &peer_id, + &tid, &fw_desc, &head_buf, &tail_buf); + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer && peer->vdev) { + vdev = peer->vdev; + OL_RX_OSIF_DELIVER(vdev, peer, head_buf); + } else { + buf = head_buf; + while (1) { + adf_nbuf_t next; + next = adf_nbuf_next(buf); + htt_rx_desc_frame_free(htt_pdev, buf); + if (buf == tail_buf) { + break; + } + buf = next; + } + } + msdu_cnt--; + } + htt_rx_msdu_buff_replenish(htt_pdev); +} + +/** + * @brief Check the first msdu to decide whether the a-msdu should be accepted. + */ +a_bool_t +ol_rx_filter( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + adf_nbuf_t msdu, + void *rx_desc) +{ + #define FILTER_STATUS_REJECT 1 + #define FILTER_STATUS_ACCEPT 0 + u_int8_t *wh; + u_int32_t offset = 0; + u_int16_t ether_type = 0; + a_bool_t is_encrypted = A_FALSE, is_mcast = A_FALSE; + u_int8_t i; + privacy_filter_packet_type packet_type = PRIVACY_FILTER_PACKET_UNICAST; + ol_txrx_pdev_handle pdev = vdev->pdev; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + int sec_idx; + + /* + * Safemode must avoid the PrivacyExemptionList and + * ExcludeUnencrypted checking + */ + if (vdev->safemode) { + return FILTER_STATUS_ACCEPT; + } + + is_mcast = htt_rx_msdu_is_wlan_mcast(htt_pdev, rx_desc); + if (vdev->num_filters > 0) { + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + offset = SIZEOF_80211_HDR + LLC_SNAP_HDR_OFFSET_ETHERTYPE; + } else { + offset = ETHERNET_ADDR_LEN * 2; + } + /* get header info from msdu */ + wh = adf_nbuf_data(msdu); + + /* get ether type */ + ether_type = (wh[offset] << 8) | wh[offset+1]; + /* get packet type */ + if (A_TRUE == is_mcast) { + packet_type = PRIVACY_FILTER_PACKET_MULTICAST; + } else { + packet_type = PRIVACY_FILTER_PACKET_UNICAST; + } + } + /* get encrypt info */ + is_encrypted = htt_rx_mpdu_is_encrypted(htt_pdev, rx_desc); +#ifdef ATH_SUPPORT_WAPI + if ((A_TRUE == is_encrypted) && ( ETHERTYPE_WAI == ether_type )) + { + /* We expect the WAI frames to be always unencrypted when the UMAC + * gets it.*/ + return FILTER_STATUS_REJECT; + } +#endif //ATH_SUPPORT_WAPI + + for (i = 0; i < vdev->num_filters; i++) { + privacy_filter filter_type; + privacy_filter_packet_type filter_packet_type; + + /* skip if the ether type does not match */ + if (vdev->privacy_filters[i].ether_type != ether_type) { + continue; + } + + /* skip if the packet type does not match */ + filter_packet_type = vdev->privacy_filters[i].packet_type; + if (filter_packet_type != packet_type && + filter_packet_type != PRIVACY_FILTER_PACKET_BOTH) + { + continue; + } + + + filter_type = vdev->privacy_filters[i].filter_type; + if (filter_type == PRIVACY_FILTER_ALWAYS) { + /* + * In this case, we accept the frame if and only if it was + * originally NOT encrypted. + */ + if (A_TRUE == is_encrypted) { + return FILTER_STATUS_REJECT; + } else { + return FILTER_STATUS_ACCEPT; + } + } else if (filter_type == PRIVACY_FILTER_KEY_UNAVAILABLE) { + /* + * In this case, we reject the frame if it was originally NOT + * encrypted but we have the key mapping key for this frame. + */ + if (!is_encrypted && !is_mcast && + peer->security[txrx_sec_ucast].sec_type != htt_sec_type_none && + (peer->keyinstalled || !ETHERTYPE_IS_EAPOL_WAPI(ether_type))) + { + return FILTER_STATUS_REJECT; + } else { + return FILTER_STATUS_ACCEPT; + } + } else { + /* + * The privacy exemption does not apply to this frame. + */ + break; + } + } + + /* + * If the privacy exemption list does not apply to the frame, + * check ExcludeUnencrypted. + * If ExcludeUnencrypted is not set, or if this was oringially + * an encrypted frame, it will be accepted. + */ + if (!vdev->drop_unenc || (A_TRUE == is_encrypted)) { + return FILTER_STATUS_ACCEPT; + } + + /* + * If this is a open connection, it will be accepted. + */ + sec_idx = (A_TRUE == is_mcast) ? txrx_sec_mcast : txrx_sec_ucast; + if (peer->security[sec_idx].sec_type == htt_sec_type_none) { + return FILTER_STATUS_ACCEPT; + } + if ((A_FALSE == is_encrypted) && vdev->drop_unenc) { + OL_RX_ERR_STATISTICS( + pdev, vdev, OL_RX_ERR_PRIVACY, + pdev->sec_types[htt_sec_type_none], is_mcast); + } + return FILTER_STATUS_REJECT; +} + +void +ol_rx_deliver( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + ol_txrx_pdev_handle pdev = vdev->pdev; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + adf_nbuf_t deliver_list_head = NULL; + adf_nbuf_t deliver_list_tail = NULL; + adf_nbuf_t msdu; + a_bool_t filter = A_FALSE; +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + struct ol_rx_decap_info_t info; + adf_os_mem_set(&info, 0, sizeof(info)); +#endif + + msdu = msdu_list; + /* + * Check each MSDU to see whether it requires special handling, + * and free each MSDU's rx descriptor + */ + while (msdu) { + void *rx_desc; + int discard, inspect, dummy_fwd; + adf_nbuf_t next = adf_nbuf_next(msdu); + + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); + // for HL, point to payload right now + if (pdev->cfg.is_high_latency) { + adf_nbuf_pull_head(msdu, + htt_rx_msdu_rx_desc_size_hl(htt_pdev, + rx_desc)); + } + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + info.is_msdu_cmpl_mpdu = + htt_rx_msdu_desc_completes_mpdu(htt_pdev, rx_desc); + info.is_first_subfrm = htt_rx_msdu_first_msdu_flag(htt_pdev, rx_desc); + if (OL_RX_DECAP(vdev, peer, msdu, &info) != A_OK) { + discard = 1; + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "decap error %p from peer %p " + "(%02x:%02x:%02x:%02x:%02x:%02x) len %d\n", + msdu, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5], + adf_nbuf_len(msdu)); + goto DONE; + } +#endif + htt_rx_msdu_actions( + pdev->htt_pdev, rx_desc, &discard, &dummy_fwd, &inspect); + if (inspect) { + ol_rx_inspect(vdev, peer, tid, msdu, rx_desc); + } + + /* + * Check the first msdu in the mpdu, if it will be filtered out, + * then discard the entire mpdu. + */ + if (htt_rx_msdu_first_msdu_flag(htt_pdev, rx_desc)) { + filter = ol_rx_filter(vdev, peer, msdu, rx_desc); + } + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP +DONE: +#endif + htt_rx_msdu_desc_free(htt_pdev, msdu); + if (discard || (A_TRUE == filter)) { + OL_TXRX_FRMS_DUMP( + "rx discarding:", + pdev, deliver_list_head, + ol_txrx_frm_dump_tcp_seq | ol_txrx_frm_dump_contents, + 0 /* don't print contents */); + adf_nbuf_free(msdu); + /* If discarding packet is last packet of the delivery list,NULL terminator should be added for delivery list. */ + if (next == NULL && deliver_list_head){ + adf_nbuf_set_next(deliver_list_tail, NULL); /* add NULL terminator */ + } + } else { + /* If this is for OCB, then prepend the RX stats header. */ + if (vdev->opmode == wlan_op_mode_ocb) { + int i; + struct ol_txrx_ocb_chan_info *chan_info = 0; + int packet_freq = peer->last_pkt_center_freq; + for (i = 0; i < vdev->ocb_channel_count; i++) { + if (vdev->ocb_channel_info[i].chan_freq == packet_freq) { + chan_info = &vdev->ocb_channel_info[i]; + break; + } + } + if (!chan_info || !chan_info->disable_rx_stats_hdr) { + struct ether_header eth_header = { {0} }; + struct ocb_rx_stats_hdr_t rx_header = {0}; + + /* + * Construct the RX stats header and push that to the front + * of the packet. + */ + rx_header.version = 1; + rx_header.length = sizeof(rx_header); + rx_header.channel_freq = peer->last_pkt_center_freq; + rx_header.rssi_cmb = peer->last_pkt_rssi_cmb; + adf_os_mem_copy(rx_header.rssi, peer->last_pkt_rssi, + sizeof(rx_header.rssi)); + if (peer->last_pkt_legacy_rate_sel == 0) { + switch (peer->last_pkt_legacy_rate) { + case 0x8: + rx_header.datarate = 6; + break; + case 0x9: + rx_header.datarate = 4; + break; + case 0xA: + rx_header.datarate = 2; + break; + case 0xB: + rx_header.datarate = 0; + break; + case 0xC: + rx_header.datarate = 7; + break; + case 0xD: + rx_header.datarate = 5; + break; + case 0xE: + rx_header.datarate = 3; + break; + case 0xF: + rx_header.datarate = 1; + break; + default: + rx_header.datarate = 0xFF; + break; + } + } else { + rx_header.datarate = 0xFF; + } + + rx_header.timestamp_microsec = + peer->last_pkt_timestamp_microsec; + rx_header.timestamp_submicrosec = + peer->last_pkt_timestamp_submicrosec; + rx_header.tsf32 = peer->last_pkt_tsf; + rx_header.ext_tid = peer->last_pkt_tid; + + adf_nbuf_push_head(msdu, sizeof(rx_header)); + adf_os_mem_copy(adf_nbuf_data(msdu), &rx_header, + sizeof(rx_header)); + + /* Construct the ethernet header with type 0x8152 and push + that to the front of the packet to indicate the RX stats + header. */ + eth_header.ether_type = adf_os_htons(ETHERTYPE_OCB_RX); + adf_nbuf_push_head(msdu, sizeof(eth_header)); + adf_os_mem_copy(adf_nbuf_data(msdu), ð_header, + sizeof(eth_header)); + } + } + OL_RX_PEER_STATS_UPDATE(peer, msdu); + OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_desc, OL_RX_ERR_NONE); + TXRX_STATS_MSDU_INCR(vdev->pdev, rx.delivered, msdu); + + OL_TXRX_LIST_APPEND(deliver_list_head, deliver_list_tail, msdu); + } + msdu = next; + } + /* sanity check - are there any frames left to give to the OS shim? */ + if (!deliver_list_head) { + return; + } + +#if defined(PERE_IP_HDR_ALIGNMENT_WAR) + if (pdev->host_80211_enable) { + for (msdu = deliver_list_head; msdu; msdu = adf_nbuf_next(msdu)) { + transcap_nwifi_to_8023(msdu); + } + } +#endif + + OL_TXRX_FRMS_DUMP( + "rx delivering:", + pdev, deliver_list_head, + ol_txrx_frm_dump_tcp_seq | ol_txrx_frm_dump_contents, + 0 /* don't print contents */); + + OL_RX_OSIF_DELIVER(vdev, peer, deliver_list_head); +} + +void +ol_rx_discard( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + ol_txrx_pdev_handle pdev = vdev->pdev; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + while (msdu_list) { + adf_nbuf_t msdu = msdu_list; + + msdu_list = adf_nbuf_next(msdu_list); + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "discard rx %p from partly-deleted peer %p " + "(%02x:%02x:%02x:%02x:%02x:%02x)\n", + msdu, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + htt_rx_desc_frame_free(htt_pdev, msdu); + } +} + +void +ol_rx_peer_init(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer) +{ + u_int8_t tid; + for (tid = 0; tid < OL_TXRX_NUM_EXT_TIDS; tid++) { + ol_rx_reorder_init(&peer->tids_rx_reorder[tid], tid); + + /* invalid sequence number */ + peer->tids_last_seq[tid] = IEEE80211_SEQ_MAX; + } + /* + * Set security defaults: no PN check, no security. + * The target may send a HTT SEC_IND message to overwrite these defaults. + */ + peer->security[txrx_sec_ucast].sec_type = + peer->security[txrx_sec_mcast].sec_type = htt_sec_type_none; + peer->keyinstalled = 0; + adf_os_atomic_init(&peer->fw_pn_check); +} + +void +ol_rx_peer_cleanup(struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer) +{ + peer->keyinstalled = 0; + ol_rx_reorder_peer_cleanup(vdev, peer); +} + +/* + * Free frames including both rx descriptors and buffers + */ +void +ol_rx_frames_free( + htt_pdev_handle htt_pdev, + adf_nbuf_t frames) +{ + adf_nbuf_t next, frag = frames; + + while (frag) { + next = adf_nbuf_next(frag); + htt_rx_desc_frame_free(htt_pdev, frag); + frag = next; + } +} + +void +ol_rx_in_order_indication_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + u_int16_t peer_id, + u_int8_t tid, + u_int8_t is_offload ) +{ + struct ol_txrx_vdev_t *vdev = NULL; + struct ol_txrx_peer_t *peer = NULL; + htt_pdev_handle htt_pdev = NULL; + int status; + adf_nbuf_t head_msdu, tail_msdu = NULL; + + if (pdev) { + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + htt_pdev = pdev->htt_pdev; + } else { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: Invalid pdev passed!\n", __FUNCTION__); + adf_os_assert_always(pdev); + return; + } + + /* + * Get a linked list of the MSDUs in the rx in order indication. + * This also attaches each rx MSDU descriptor to the + * corresponding rx MSDU network buffer. + */ + status = htt_rx_amsdu_pop(htt_pdev, rx_ind_msg, &head_msdu, &tail_msdu); + if (adf_os_unlikely(0 == status)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s: Pop status is 0, returning here\n", __FUNCTION__); + return; + } + + /* Replenish the rx buffer ring first to provide buffers to the target + rather than waiting for the indeterminate time taken by the OS to consume + the rx frames */ + htt_rx_msdu_buff_replenish(htt_pdev); + + /* Send the chain of MSDUs to the OS */ + /* rx_opt_proc takes a NULL-terminated list of msdu netbufs */ + adf_nbuf_set_next(tail_msdu, NULL); + + /* Pktlog */ +#ifdef WDI_EVENT_ENABLE + wdi_event_handler(WDI_EVENT_RX_DESC_REMOTE, pdev, head_msdu); +#endif + + /* if this is an offload indication, peer id is carried in the rx buffer */ + if (peer) { + vdev = peer->vdev; + } else { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, + "%s: Couldn't find peer from ID 0x%x\n", __FUNCTION__, + peer_id); + while (head_msdu) { + adf_nbuf_t msdu = head_msdu; + + head_msdu = adf_nbuf_next(head_msdu); + htt_rx_desc_frame_free(htt_pdev, msdu); + } + return; + } + + peer->rx_opt_proc(vdev, peer, tid, head_msdu); +} + +/* the msdu_list passed here must be NULL terminated */ +void +ol_rx_in_order_deliver( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + adf_nbuf_t msdu; + + msdu = msdu_list; + /* + * Currently, this does not check each MSDU to see whether it requires + * special handling. MSDUs that need special handling (example: IGMP frames) + * should be sent via a seperate HTT message. Also, this does not do rx->tx + * forwarding or filtering. + */ + + while (msdu) { + adf_nbuf_t next = adf_nbuf_next(msdu); + + OL_RX_PEER_STATS_UPDATE(peer, msdu); + OL_RX_ERR_STATISTICS_1(vdev->pdev, vdev, peer, rx_desc, OL_RX_ERR_NONE); + TXRX_STATS_MSDU_INCR(vdev->pdev, rx.delivered, msdu); + + msdu = next; + } + + OL_TXRX_FRMS_DUMP( + "rx delivering:", + pdev, deliver_list_head, + ol_txrx_frm_dump_tcp_seq | ol_txrx_frm_dump_contents, + 0 /* don't print contents */); + + OL_RX_OSIF_DELIVER(vdev, peer, msdu_list); +} + +void +ol_rx_offload_paddr_deliver_ind_handler( + htt_pdev_handle htt_pdev, + u_int32_t msdu_count, + u_int32_t * msg_word ) +{ + int vdev_id, peer_id, tid; + adf_nbuf_t head_buf, tail_buf, buf; + struct ol_txrx_peer_t *peer; + struct ol_txrx_vdev_t *vdev = NULL; + u_int8_t fw_desc; + int msdu_iter = 0; + + while (msdu_count) { + htt_rx_offload_paddr_msdu_pop_ll( + htt_pdev, msg_word, msdu_iter, &vdev_id, + &peer_id, &tid, &fw_desc, &head_buf, &tail_buf); + + peer = ol_txrx_peer_find_by_id(htt_pdev->txrx_pdev, peer_id); + if (peer && peer->vdev) { + vdev = peer->vdev; + OL_RX_OSIF_DELIVER(vdev, peer, head_buf); + } else { + buf = head_buf; + while (1) { + adf_nbuf_t next; + next = adf_nbuf_next(buf); + htt_rx_desc_frame_free(htt_pdev, buf); + if (buf == tail_buf) { + break; + } + buf = next; + } + } + msdu_iter++; + msdu_count--; + } + htt_rx_msdu_buff_replenish(htt_pdev); +} + +void +ol_rx_mic_error_handler( + ol_txrx_pdev_handle pdev, + u_int8_t tid, + u_int16_t peer_id, + void * msdu_desc, + adf_nbuf_t msdu ) +{ + union htt_rx_pn_t pn = {0}; + u_int8_t key_id = 0; + + struct ol_txrx_peer_t *peer = NULL; + struct ol_txrx_vdev_t *vdev = NULL; + + if (pdev) { + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer) { + vdev = peer->vdev; + if (vdev) { + htt_rx_mpdu_desc_pn(vdev->pdev->htt_pdev, msdu_desc, &pn, 48); + + if (htt_rx_msdu_desc_key_id(vdev->pdev->htt_pdev, msdu_desc, &key_id) + == A_TRUE) { + ol_rx_err(vdev->pdev->ctrl_pdev, vdev->vdev_id, + peer->mac_addr.raw, tid, 0, + OL_RX_ERR_TKIP_MIC, msdu, &pn.pn48, key_id); + } + } + } + } +} +#if 0 +/** + * @brief populates vow ext stats in given network buffer. + * @param msdu - network buffer handle + * @param pdev - handle to htt dev. + */ +void ol_ath_add_vow_extstats(htt_pdev_handle pdev, adf_nbuf_t msdu) +{ + /* FIX THIS: + * txrx should not be directly using data types (scn) + * that are internal to other modules. + */ + struct ol_ath_softc_net80211 *scn = + (struct ol_ath_softc_net80211 *)pdev->ctrl_pdev; + + if (scn->vow_extstats == 0) { + return; + } else { + u_int8_t *data, *l3_hdr, *bp; + u_int16_t ethertype; + int offset; + struct vow_extstats vowstats; + + data = adf_nbuf_data(msdu); + + offset = ETHERNET_ADDR_LEN * 2; + l3_hdr = data + ETHERNET_HDR_LEN; + ethertype = (data[offset] << 8) | data[offset+1]; + if (ethertype == ETHERTYPE_IPV4) { + offset = IPV4_HDR_OFFSET_PROTOCOL; + if ((l3_hdr[offset] == IP_PROTOCOL_UDP) && + (l3_hdr[0] == IP_VER4_N_NO_EXTRA_HEADERS)) + { + bp = data+EXT_HDR_OFFSET; + + if ( (data[RTP_HDR_OFFSET] == UDP_PDU_RTP_EXT) && + (bp[0] == 0x12) && + (bp[1] == 0x34) && + (bp[2] == 0x00) && + (bp[3] == 0x08)) + { + /* + * Clear UDP checksum so we do not have to recalculate it + * after filling in status fields. + */ + data[UDP_CKSUM_OFFSET] = 0; + data[(UDP_CKSUM_OFFSET+1)] = 0; + + bp += IPERF3_DATA_OFFSET; + + htt_rx_get_vowext_stats(msdu, &vowstats); + + /* control channel RSSI */ + *bp++ = vowstats.rx_rssi_ctl0; + *bp++ = vowstats.rx_rssi_ctl1; + *bp++ = vowstats.rx_rssi_ctl2; + + /* rx rate info */ + *bp++ = vowstats.rx_bw; + *bp++ = vowstats.rx_sgi; + *bp++ = vowstats.rx_nss; + + *bp++ = vowstats.rx_rssi_comb; + *bp++ = vowstats.rx_rs_flags; /* rsflags */ + + /* Time stamp Lo*/ + *bp++ = (u_int8_t) + ((vowstats.rx_macTs & 0x0000ff00) >> 8); + *bp++ = (u_int8_t) + (vowstats.rx_macTs & 0x000000ff); + /* rx phy errors */ + *bp++ = (u_int8_t) + ((scn->chan_stats.phy_err_cnt >> 8) & 0xff); + *bp++ = (u_int8_t)(scn->chan_stats.phy_err_cnt & 0xff); + /* rx clear count */ + *bp++ = (u_int8_t) + ((scn->mib_cycle_cnts.rx_clear_count >> 24) & 0xff); + *bp++ = (u_int8_t) + ((scn->mib_cycle_cnts.rx_clear_count >> 16) & 0xff); + *bp++ = (u_int8_t) + ((scn->mib_cycle_cnts.rx_clear_count >> 8) & 0xff); + *bp++ = (u_int8_t) + (scn->mib_cycle_cnts.rx_clear_count & 0xff); + /* rx cycle count */ + *bp++ = (u_int8_t) + ((scn->mib_cycle_cnts.cycle_count >> 24) & 0xff); + *bp++ = (u_int8_t) + ((scn->mib_cycle_cnts.cycle_count >> 16) & 0xff); + *bp++ = (u_int8_t) + ((scn->mib_cycle_cnts.cycle_count >> 8) & 0xff); + *bp++ = (u_int8_t) + (scn->mib_cycle_cnts.cycle_count & 0xff); + + *bp++ = vowstats.rx_ratecode; + *bp++ = vowstats.rx_moreaggr; + + /* sequence number */ + *bp++ = (u_int8_t)((vowstats.rx_seqno >> 8) & 0xff); + *bp++ = (u_int8_t)(vowstats.rx_seqno & 0xff); + } + } + } + } +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.h new file mode 100644 index 000000000000..b1890025ed30 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_RX__H_ +#define _OL_RX__H_ + +#include /* adf_nbuf_t */ +#include /* ol_txrx_vdev_t, etc. */ + +void +ol_rx_deliver( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t head_msdu); + +void +ol_rx_discard( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t head_msdu); + +void +ol_rx_frames_free( + htt_pdev_handle htt_pdev, + adf_nbuf_t frames); + +void +ol_rx_peer_init(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer); + +void +ol_rx_peer_cleanup(struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer); + +void +ol_rx_in_order_deliver( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t head_msdu); + +void +ol_rx_offload_paddr_deliver_ind_handler( + htt_pdev_handle htt_pdev, + u_int32_t msdu_count, + u_int32_t * msg_word ); + +void +ol_rx_mic_error_handler( + ol_txrx_pdev_handle pdev, + u_int8_t tid, + u_int16_t peer_id, + void * msdu_desc, + adf_nbuf_t msdu ); + +#endif /* _OL_RX__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c new file mode 100644 index 000000000000..cdbcc7667d07 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c @@ -0,0 +1,1195 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*- +* Copyright (c) 2002-2007 Sam Leffler, Errno Consulting +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. 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. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* adf_os_time */ + + +#define DEFRAG_IEEE80211_ADDR_EQ(a1, a2) \ + (adf_os_mem_cmp(a1, a2, IEEE80211_ADDR_LEN) == 0) + +#define DEFRAG_IEEE80211_ADDR_COPY(dst, src) \ + adf_os_mem_copy(dst, src, IEEE80211_ADDR_LEN) + +#define DEFRAG_IEEE80211_QOS_HAS_SEQ(wh) \ + (((wh)->i_fc[0] & \ + (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \ + (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) + +#define DEFRAG_IEEE80211_QOS_GET_TID(_x) \ + ((_x)->i_qos[0] & IEEE80211_QOS_TID) + +const struct ol_rx_defrag_cipher f_ccmp = { + "AES-CCM", + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN, + IEEE80211_WEP_MICLEN, + 0, +}; + +const struct ol_rx_defrag_cipher f_tkip = { + "TKIP", + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN, + IEEE80211_WEP_CRCLEN, + IEEE80211_WEP_MICLEN, +}; + +const struct ol_rx_defrag_cipher f_wep = { + "WEP", + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN, + IEEE80211_WEP_CRCLEN, + 0, +}; + +#if defined(CONFIG_HL_SUPPORT) +static inline struct ieee80211_frame *OL_RX_FRAG_GET_MAC_HDR( + htt_pdev_handle htt_pdev, adf_nbuf_t frag) +{ + void *rx_desc; + int rx_desc_len; + + rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag); + rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev, rx_desc); + return (struct ieee80211_frame *) (adf_nbuf_data(frag) + rx_desc_len); +} +static inline void OL_RX_FRAG_PULL_HDR(htt_pdev_handle htt_pdev, + adf_nbuf_t frag, int hdrsize) +{ + void *rx_desc; + int rx_desc_len; + + rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag); + rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev, rx_desc); + adf_nbuf_pull_head(frag, rx_desc_len + hdrsize); +} +#define OL_RX_FRAG_CLONE(frag) \ + adf_nbuf_clone(frag) +#else +#define OL_RX_FRAG_GET_MAC_HDR(pdev, frag) \ + (struct ieee80211_frame *) adf_nbuf_data(frag) +#define OL_RX_FRAG_PULL_HDR(pdev, frag, hdrsize) \ + adf_nbuf_pull_head(frag, hdrsize); +#define OL_RX_FRAG_CLONE(frag) NULL/* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +static inline void +ol_rx_frag_desc_adjust( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msdu, + void **rx_desc_old_position, + void **ind_old_position, + int *rx_desc_len) +{ + if (pdev->cfg.is_high_latency) { + *rx_desc_old_position = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); + *ind_old_position = *rx_desc_old_position - HTT_RX_IND_HL_BYTES; + *rx_desc_len = htt_rx_msdu_rx_desc_size_hl(pdev->htt_pdev, + *rx_desc_old_position); + } else { + *rx_desc_old_position = NULL; + *ind_old_position = NULL; + *rx_desc_len = 0; + } +} + +static inline void +ol_rx_frag_restructure( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msdu, + void *rx_desc_old_position, + void *ind_old_position, + const struct ol_rx_defrag_cipher *f_type, + int rx_desc_len) +{ + if (pdev->cfg.is_high_latency) { + if ((ind_old_position == NULL) || (rx_desc_old_position == NULL)) { + printk(KERN_ERR "ind_old_position,rx_desc_old_position is NULL\n"); + ASSERT(0); + return; + } + /* move rx description*/ + adf_os_mem_move(rx_desc_old_position + f_type->ic_header, + rx_desc_old_position, rx_desc_len); + /* move rx indication*/ + adf_os_mem_move(ind_old_position + f_type->ic_header, ind_old_position, + HTT_RX_IND_HL_BYTES); + } else { + /* no op */ + } +} + +/* + * Process incoming fragments + */ +void +ol_rx_frag_indication_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t rx_frag_ind_msg, + u_int16_t peer_id, + u_int8_t tid) +{ + u_int16_t seq_num; + int seq_num_start, seq_num_end; + struct ol_txrx_peer_t *peer; + htt_pdev_handle htt_pdev; + adf_nbuf_t head_msdu, tail_msdu; + void *rx_mpdu_desc; + + htt_pdev = pdev->htt_pdev; + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + + /* In case of reorder offload, we will never get a flush indication */ + if (!ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev) && + htt_rx_ind_flush(pdev->htt_pdev, rx_frag_ind_msg) && peer) { + htt_rx_frag_ind_flush_seq_num_range( + pdev->htt_pdev, rx_frag_ind_msg, &seq_num_start, &seq_num_end); + /* + * Assuming flush indication for frags sent from target is seperate + * from normal frames + */ + ol_rx_reorder_flush_frag(htt_pdev, peer, tid, seq_num_start); + } + if (peer) { + htt_rx_frag_pop(htt_pdev, rx_frag_ind_msg, &head_msdu, &tail_msdu); + adf_os_assert(head_msdu == tail_msdu); + if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) { + rx_mpdu_desc = htt_rx_mpdu_desc_list_next(htt_pdev, head_msdu); + } else { + rx_mpdu_desc = htt_rx_mpdu_desc_list_next(htt_pdev, rx_frag_ind_msg); + } + seq_num = htt_rx_mpdu_desc_seq_num(htt_pdev, rx_mpdu_desc); + OL_RX_ERR_STATISTICS_1(pdev, peer->vdev, peer, rx_mpdu_desc, OL_RX_ERR_NONE_FRAG); + ol_rx_reorder_store_frag(pdev, peer, tid, seq_num, head_msdu); + } else { + /* invalid frame - discard it */ + htt_rx_frag_pop(htt_pdev, rx_frag_ind_msg, &head_msdu, &tail_msdu); + if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) { + htt_rx_msdu_desc_retrieve(htt_pdev, head_msdu); + } else { + htt_rx_mpdu_desc_list_next(htt_pdev, rx_frag_ind_msg); + } + htt_rx_desc_frame_free(htt_pdev, head_msdu); + } + /* request HTT to provide new rx MSDU buffers for the target to fill. */ + htt_rx_msdu_buff_replenish(htt_pdev); +} + +/* + * Flushing fragments + */ +void +ol_rx_reorder_flush_frag( + htt_pdev_handle htt_pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + int seq_num) +{ + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + int seq; + + seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask; + rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[seq]; + if (rx_reorder_array_elem->head) { + ol_rx_frames_free(htt_pdev, rx_reorder_array_elem->head); + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + } +} + +/* + * Reorder and store fragments + */ +void +ol_rx_reorder_store_frag( + ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + u_int16_t seq_num, + adf_nbuf_t frag) +{ + struct ieee80211_frame *fmac_hdr, *mac_hdr; + u_int8_t fragno, more_frag, all_frag_present = 0; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + u_int16_t frxseq, rxseq, seq; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask; + adf_os_assert(seq == 0); + rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[seq]; + + mac_hdr = (struct ieee80211_frame *)OL_RX_FRAG_GET_MAC_HDR(htt_pdev, frag); + rxseq = adf_os_le16_to_cpu(*(u_int16_t *) mac_hdr->i_seq) >> + IEEE80211_SEQ_SEQ_SHIFT; + fragno = adf_os_le16_to_cpu(*(u_int16_t *) mac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + more_frag = mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG; + + if ((!more_frag) && (!fragno) && (!rx_reorder_array_elem->head)) { + rx_reorder_array_elem->head = frag; + rx_reorder_array_elem->tail = frag; + adf_nbuf_set_next(frag, NULL); + ol_rx_defrag(pdev, peer, tid, rx_reorder_array_elem->head); + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + return; + } + if (rx_reorder_array_elem->head) { + fmac_hdr = (struct ieee80211_frame *)OL_RX_FRAG_GET_MAC_HDR(htt_pdev, + rx_reorder_array_elem->head); + frxseq = adf_os_le16_to_cpu(*(u_int16_t *) fmac_hdr->i_seq) >> + IEEE80211_SEQ_SEQ_SHIFT; + if (rxseq != frxseq || + !DEFRAG_IEEE80211_ADDR_EQ(mac_hdr->i_addr1, fmac_hdr->i_addr1) || + !DEFRAG_IEEE80211_ADDR_EQ(mac_hdr->i_addr2, fmac_hdr->i_addr2)) + { + ol_rx_frames_free(htt_pdev, rx_reorder_array_elem->head); + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "\n ol_rx_reorder_store: %s mismatch \n", + (rxseq == frxseq) ? "address" : "seq number"); + } + } + + ol_rx_fraglist_insert(htt_pdev, &rx_reorder_array_elem->head, + &rx_reorder_array_elem->tail, frag, &all_frag_present); + + if (pdev->rx.flags.defrag_timeout_check) { + ol_rx_defrag_waitlist_remove(peer, tid); + } + + if (all_frag_present) { + ol_rx_defrag(pdev, peer, tid, rx_reorder_array_elem->head); + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + peer->tids_rx_reorder[tid].defrag_timeout_ms = 0; + peer->tids_last_seq[tid] = seq_num; + } else if (pdev->rx.flags.defrag_timeout_check) { + u_int32_t now_ms = adf_os_ticks_to_msecs(adf_os_ticks()); + + peer->tids_rx_reorder[tid].defrag_timeout_ms = now_ms + pdev->rx.defrag.timeout_ms; + ol_rx_defrag_waitlist_add(peer, tid); + } +} + +/* + * Insert and store fragments + */ +void +ol_rx_fraglist_insert( + htt_pdev_handle htt_pdev, + adf_nbuf_t *head_addr, + adf_nbuf_t *tail_addr, + adf_nbuf_t frag, + u_int8_t *all_frag_present) +{ + adf_nbuf_t next, prev = NULL, cur = *head_addr; + struct ieee80211_frame *mac_hdr, *cmac_hdr, *next_hdr, *lmac_hdr; + u_int8_t fragno, cur_fragno, lfragno, next_fragno; + u_int8_t last_morefrag = 1, count = 0; + adf_nbuf_t frag_clone; + + adf_os_assert(frag); + frag_clone = OL_RX_FRAG_CLONE(frag); + frag = frag_clone ? frag_clone : frag; + + mac_hdr = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR(htt_pdev, frag); + fragno = adf_os_le16_to_cpu(*(u_int16_t *) mac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + + if (!(*head_addr)) { + *head_addr = frag; + *tail_addr = frag; + adf_nbuf_set_next(*tail_addr, NULL); + return; + } + /* For efficiency, compare with tail first */ + lmac_hdr = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR(htt_pdev, + *tail_addr); + lfragno = adf_os_le16_to_cpu(*(u_int16_t *) lmac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + if (fragno > lfragno) { + adf_nbuf_set_next(*tail_addr, frag); + *tail_addr = frag; + adf_nbuf_set_next(*tail_addr, NULL); + } else { + do { + cmac_hdr = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR( + htt_pdev, cur); + cur_fragno = adf_os_le16_to_cpu(*(u_int16_t *) cmac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + prev = cur; + cur = adf_nbuf_next(cur); + } while (fragno > cur_fragno); + + if (fragno == cur_fragno) { + htt_rx_desc_frame_free(htt_pdev, frag); + *all_frag_present = 0; + return; + } else { + adf_nbuf_set_next(prev, frag); + adf_nbuf_set_next(frag, cur); + } + } + next = adf_nbuf_next(*head_addr); + lmac_hdr = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR(htt_pdev, + *tail_addr); + last_morefrag = lmac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG; + if (!last_morefrag) { + do { + next_hdr = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR( + htt_pdev, next); + next_fragno = adf_os_le16_to_cpu(*(u_int16_t *) next_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + count++; + if (next_fragno != count) { + break; + } + next = adf_nbuf_next(next); + } while (next); + + if (!next) { + *all_frag_present = 1; + return; + } + } + *all_frag_present = 0; +} + +/* + * add tid to pending fragment wait list + */ +void +ol_rx_defrag_waitlist_add( + struct ol_txrx_peer_t *peer, + unsigned tid) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + struct ol_rx_reorder_t *rx_reorder = &peer->tids_rx_reorder[tid]; + + TAILQ_INSERT_TAIL(&pdev->rx.defrag.waitlist, rx_reorder, + defrag_waitlist_elem); +} + +/* + * remove tid from pending fragment wait list + */ +void +ol_rx_defrag_waitlist_remove( + struct ol_txrx_peer_t *peer, + unsigned tid) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + struct ol_rx_reorder_t *rx_reorder = &peer->tids_rx_reorder[tid]; + + if (rx_reorder->defrag_waitlist_elem.tqe_prev != NULL) { + + TAILQ_REMOVE(&pdev->rx.defrag.waitlist, rx_reorder, + defrag_waitlist_elem); + + rx_reorder->defrag_waitlist_elem.tqe_next = NULL; + rx_reorder->defrag_waitlist_elem.tqe_prev = NULL; + } else if (rx_reorder->defrag_waitlist_elem.tqe_next != NULL) { + TXRX_PRINT(TXRX_PRINT_LEVEL_FATAL_ERR, "waitlist->tqe_prv = NULL\n"); + VOS_ASSERT(0); + rx_reorder->defrag_waitlist_elem.tqe_next = NULL; + } +} + +#ifndef container_of +#define container_of(ptr, type, member) ((type *)( \ + (char *)(ptr) - (char *)(&((type *)0)->member) ) ) +#endif + +/* + * flush stale fragments from the waitlist + */ +void +ol_rx_defrag_waitlist_flush( + struct ol_txrx_pdev_t *pdev) +{ + struct ol_rx_reorder_t *rx_reorder, *tmp; + u_int32_t now_ms = adf_os_ticks_to_msecs(adf_os_ticks()); + + TAILQ_FOREACH_SAFE(rx_reorder, &pdev->rx.defrag.waitlist, + defrag_waitlist_elem, tmp) { + struct ol_txrx_peer_t *peer; + struct ol_rx_reorder_t *rx_reorder_base; + unsigned tid; + + if (rx_reorder->defrag_timeout_ms > now_ms) { + break; + } + + tid = rx_reorder->tid; + /* get index 0 of the rx_reorder array */ + rx_reorder_base = rx_reorder - tid; + peer = container_of(rx_reorder_base, struct ol_txrx_peer_t, tids_rx_reorder[0]); + + ol_rx_defrag_waitlist_remove(peer, tid); + ol_rx_reorder_flush_frag(pdev->htt_pdev, peer, tid, 0 /* fragments always stored at seq 0*/); + } +} + +/* + * Handling security checking and processing fragments + */ +void +ol_rx_defrag( + ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t frag_list) +{ + struct ol_txrx_vdev_t *vdev = NULL; + adf_nbuf_t tmp_next, msdu, prev = NULL, cur = frag_list; + u_int8_t index, tkip_demic = 0; + u_int16_t hdr_space; + void *rx_desc; + struct ieee80211_frame *wh; + u_int8_t key[DEFRAG_IEEE80211_KEY_LEN]; + + htt_pdev_handle htt_pdev = pdev->htt_pdev; + vdev = peer->vdev; + + /* bypass defrag for safe mode */ + if (vdev->safemode) { + if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) { + ol_rx_in_order_deliver(vdev, peer, tid, frag_list); + } else { + ol_rx_deliver(vdev, peer, tid, frag_list); + } + return; + } + + while (cur) { + tmp_next = adf_nbuf_next(cur); + adf_nbuf_set_next(cur, NULL); + if (!ol_rx_pn_check_base(vdev, peer, tid, cur)) { + /* PN check failed,discard frags */ + if (prev) { + adf_nbuf_set_next(prev, NULL); + ol_rx_frames_free(htt_pdev, frag_list); + } + ol_rx_frames_free(htt_pdev, tmp_next); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "ol_rx_defrag: PN Check failed\n"); + return; + } + /* remove FCS from each fragment */ + adf_nbuf_trim_tail(cur, DEFRAG_IEEE80211_FCS_LEN); + prev = cur; + adf_nbuf_set_next(cur, tmp_next); + cur = tmp_next; + } + cur = frag_list; + wh = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR(htt_pdev, cur); + hdr_space = ol_rx_frag_hdrsize(wh); + rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag_list); + adf_os_assert(htt_rx_msdu_has_wlan_mcast_flag(htt_pdev, rx_desc)); + index = htt_rx_msdu_is_wlan_mcast(htt_pdev, rx_desc) ? + txrx_sec_mcast : txrx_sec_ucast; + + switch (peer->security[index].sec_type) { + case htt_sec_type_tkip: + tkip_demic = 1; + /* fall-through to rest of tkip ops */ + case htt_sec_type_tkip_nomic: + while (cur) { + tmp_next = adf_nbuf_next(cur); + if (!ol_rx_frag_tkip_decap(pdev, cur, hdr_space)) { + /* TKIP decap failed, discard frags */ + ol_rx_frames_free(htt_pdev, frag_list); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "\n ol_rx_defrag: TKIP decap failed\n"); + return; + } + cur = tmp_next; + } + break; + + case htt_sec_type_aes_ccmp: + while (cur) { + tmp_next = adf_nbuf_next(cur); + if (!ol_rx_frag_ccmp_demic(pdev, cur, hdr_space)) { + /* CCMP demic failed, discard frags */ + ol_rx_frames_free(htt_pdev, frag_list); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "\n ol_rx_defrag: CCMP demic failed\n"); + return; + } + if (!ol_rx_frag_ccmp_decap(pdev, cur, hdr_space)) { + /* CCMP decap failed, discard frags */ + ol_rx_frames_free(htt_pdev, frag_list); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "\n ol_rx_defrag: CCMP decap failed\n"); + return; + } + cur = tmp_next; + } + break; + + case htt_sec_type_wep40: + case htt_sec_type_wep104: + case htt_sec_type_wep128: + while (cur) { + tmp_next = adf_nbuf_next(cur); + if (!ol_rx_frag_wep_decap(pdev, cur, hdr_space)) { + /* wep decap failed, discard frags */ + ol_rx_frames_free(htt_pdev, frag_list); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "\n ol_rx_defrag: wep decap failed\n"); + return; + } + cur = tmp_next; + } + break; + + default: + break; + } + + msdu = ol_rx_defrag_decap_recombine(htt_pdev, frag_list, hdr_space); + if (!msdu) { + return; + } + + if (tkip_demic) { + adf_os_mem_copy( + key, + peer->security[index].michael_key, + sizeof(peer->security[index].michael_key)); + if (!ol_rx_frag_tkip_demic(pdev, key, msdu, hdr_space)) { + htt_rx_desc_frame_free(htt_pdev, msdu); + ol_rx_err( + pdev->ctrl_pdev, + vdev->vdev_id, peer->mac_addr.raw, tid, 0, OL_RX_DEFRAG_ERR, + msdu, NULL, 0); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "\n ol_rx_defrag: TKIP demic failed\n"); + return; + } + } + wh = (struct ieee80211_frame *)OL_RX_FRAG_GET_MAC_HDR(htt_pdev, msdu); + if (DEFRAG_IEEE80211_QOS_HAS_SEQ(wh)) { + ol_rx_defrag_qos_decap(pdev, msdu, hdr_space); + } + if (ol_cfg_frame_type(pdev->ctrl_pdev) == wlan_frm_fmt_802_3) { + ol_rx_defrag_nwifi_to_8023(pdev, msdu); + } + ol_rx_fwd_check(vdev, peer, tid, msdu); +} + +/* + * Handling TKIP processing for defragmentation + */ +int +ol_rx_frag_tkip_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t hdrlen) +{ + u_int8_t *ivp, *origHdr; + + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + + ol_rx_frag_desc_adjust( + pdev, + msdu, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + /* Header should have extended IV */ + origHdr = (u_int8_t*) (adf_nbuf_data(msdu) + rx_desc_len); + + ivp = origHdr + hdrlen; + if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) { + return OL_RX_DEFRAG_ERR; + } + adf_os_mem_move(origHdr + f_tkip.ic_header, origHdr, hdrlen); + + ol_rx_frag_restructure( + pdev, + msdu, + rx_desc_old_position, + ind_old_position, + &f_tkip, + rx_desc_len); + + adf_nbuf_pull_head(msdu, f_tkip.ic_header); + adf_nbuf_trim_tail(msdu, f_tkip.ic_trailer); + return OL_RX_DEFRAG_OK; +} + +/* + * Handling WEP processing for defragmentation + */ +int +ol_rx_frag_wep_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t hdrlen) +{ + u_int8_t *origHdr; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + + ol_rx_frag_desc_adjust( + pdev, + msdu, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + origHdr = (u_int8_t*) (adf_nbuf_data(msdu) + rx_desc_len); + adf_os_mem_move(origHdr + f_wep.ic_header, origHdr, hdrlen); + + ol_rx_frag_restructure( + pdev, + msdu, + rx_desc_old_position, + ind_old_position, + &f_wep, + rx_desc_len); + adf_nbuf_pull_head(msdu, f_wep.ic_header); + adf_nbuf_trim_tail(msdu, f_wep.ic_trailer); + return OL_RX_DEFRAG_OK; +} + +/* + * Verify and strip MIC from the frame. + */ +int +ol_rx_frag_tkip_demic(ol_txrx_pdev_handle pdev, const u_int8_t *key, + adf_nbuf_t msdu, u_int16_t hdrlen) +{ + int status; + u_int32_t pktlen; + u_int8_t mic[IEEE80211_WEP_MICLEN]; + u_int8_t mic0[IEEE80211_WEP_MICLEN]; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + + ol_rx_frag_desc_adjust( + pdev, + msdu, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + + pktlen = ol_rx_defrag_len(msdu) - rx_desc_len; + + status = ol_rx_defrag_mic(pdev, key, msdu, hdrlen, + pktlen - (hdrlen + f_tkip.ic_miclen), mic); + if (status != OL_RX_DEFRAG_OK) { + return OL_RX_DEFRAG_ERR; + } + ol_rx_defrag_copydata( + msdu, pktlen - f_tkip.ic_miclen + rx_desc_len, f_tkip.ic_miclen, + (caddr_t) mic0); + if (adf_os_mem_cmp(mic, mic0, f_tkip.ic_miclen)) { + return OL_RX_DEFRAG_ERR; + } + adf_nbuf_trim_tail(msdu, f_tkip.ic_miclen); + return OL_RX_DEFRAG_OK; +} + +/* + * Handling CCMP processing for defragmentation + */ +int +ol_rx_frag_ccmp_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t nbuf, + u_int16_t hdrlen) +{ + u_int8_t *ivp, *origHdr; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + + ol_rx_frag_desc_adjust( + pdev, + nbuf, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + + origHdr = (u_int8_t *) (adf_nbuf_data(nbuf) + rx_desc_len); + ivp = origHdr + hdrlen; + if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) { + return OL_RX_DEFRAG_ERR; + } + adf_os_mem_move(origHdr + f_ccmp.ic_header, origHdr, hdrlen); + + ol_rx_frag_restructure( + pdev, + nbuf, + rx_desc_old_position, + ind_old_position, + &f_ccmp, + rx_desc_len); + + adf_nbuf_pull_head(nbuf, f_ccmp.ic_header); + + return OL_RX_DEFRAG_OK; +} + +/* + * Verify and strip MIC from the frame. + */ +int +ol_rx_frag_ccmp_demic( + ol_txrx_pdev_handle pdev, + adf_nbuf_t wbuf, + u_int16_t hdrlen) +{ + u_int8_t *ivp, *origHdr; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + + ol_rx_frag_desc_adjust( + pdev, + wbuf, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + + origHdr = (u_int8_t *) (adf_nbuf_data(wbuf) + rx_desc_len); + + ivp = origHdr + hdrlen; + if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) { + return OL_RX_DEFRAG_ERR; + } + adf_nbuf_trim_tail(wbuf, f_ccmp.ic_trailer); + + return OL_RX_DEFRAG_OK; +} + +/* + * Craft pseudo header used to calculate the MIC. + */ +void +ol_rx_defrag_michdr( + const struct ieee80211_frame *wh0, + u_int8_t hdr[]) +{ + const struct ieee80211_frame_addr4 *wh = + (const struct ieee80211_frame_addr4 *) wh0; + + switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */ + DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2); + break; + case IEEE80211_FC1_DIR_TODS: + DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */ + DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2); + break; + case IEEE80211_FC1_DIR_FROMDS: + DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */ + DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3); + break; + case IEEE80211_FC1_DIR_DSTODS: + DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */ + DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4); + break; + } + /* + * Bit 7 is IEEE80211_FC0_SUBTYPE_QOS for data frame, but + * it could also be set for deauth, disassoc, action, etc. for + * a mgt type frame. It comes into picture for MFP. + */ + if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { + const struct ieee80211_qosframe *qwh = + (const struct ieee80211_qosframe *) wh; + hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID; + } else { + hdr[12] = 0; + } + hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ +} + +/* + * Michael_mic for defragmentation + */ +int +ol_rx_defrag_mic( + ol_txrx_pdev_handle pdev, + const u_int8_t *key, + adf_nbuf_t wbuf, + u_int16_t off, + u_int16_t data_len, + u_int8_t mic[]) +{ + u_int8_t hdr[16] = {0,}; + u_int32_t l, r; + const u_int8_t *data; + u_int32_t space; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + ol_rx_frag_desc_adjust( + pdev, + wbuf, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + + ol_rx_defrag_michdr((struct ieee80211_frame *) (adf_nbuf_data(wbuf) + + rx_desc_len), hdr); + l = get_le32(key); + r = get_le32(key + 4); + + /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ + l ^= get_le32(hdr); + michael_block(l, r); + l ^= get_le32(&hdr[4]); + michael_block(l, r); + l ^= get_le32(&hdr[8]); + michael_block(l, r); + l ^= get_le32(&hdr[12]); + michael_block(l, r); + + /* first buffer has special handling */ + data = (u_int8_t *)adf_nbuf_data(wbuf) + rx_desc_len + off; + space = ol_rx_defrag_len(wbuf) - rx_desc_len - off; + for (;;) { + if (space > data_len) { + space = data_len; + } + /* collect 32-bit blocks from current buffer */ + while (space >= sizeof(u_int32_t)) { + l ^= get_le32(data); + michael_block(l, r); + data += sizeof(u_int32_t); + space -= sizeof(u_int32_t); + data_len -= sizeof(u_int32_t); + } + if (data_len < sizeof(u_int32_t)) { + break; + } + wbuf = adf_nbuf_next(wbuf); + if (wbuf == NULL) { + return OL_RX_DEFRAG_ERR; + } + if (pdev->cfg.is_high_latency) { + rx_desc_old_position = htt_rx_msdu_desc_retrieve(htt_pdev, wbuf); + rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev, + rx_desc_old_position); + } else { + rx_desc_len = 0; + } + if (space != 0) { + const u_int8_t *data_next; + /* + * Block straddles buffers, split references. + */ + data_next = (u_int8_t *)adf_nbuf_data(wbuf) + rx_desc_len; + if ((ol_rx_defrag_len(wbuf) - rx_desc_len) < + sizeof(u_int32_t) - space) { + return OL_RX_DEFRAG_ERR; + } + switch (space) { + case 1: + l ^= get_le32_split( + data[0], data_next[0], data_next[1], data_next[2]); + data = data_next + 3; + space = (ol_rx_defrag_len(wbuf) - rx_desc_len) - 3; + break; + case 2: + l ^= get_le32_split( + data[0], data[1], data_next[0], data_next[1]); + data = data_next + 2; + space = (ol_rx_defrag_len(wbuf) - rx_desc_len) - 2; + break; + case 3: + l ^= get_le32_split( + data[0], data[1], data[2], data_next[0]); + data = data_next + 1; + space = (ol_rx_defrag_len(wbuf) - rx_desc_len) - 1; + break; + } + michael_block(l, r); + data_len -= sizeof(u_int32_t); + } else { + /* + * Setup for next buffer. + */ + data = (u_int8_t*) adf_nbuf_data(wbuf) + rx_desc_len; + space = ol_rx_defrag_len(wbuf) - rx_desc_len; + } + } + /* Last block and padding (0x5a, 4..7 x 0) */ + switch (data_len) { + case 0: + l ^= get_le32_split(0x5a, 0, 0, 0); + break; + case 1: + l ^= get_le32_split(data[0], 0x5a, 0, 0); + break; + case 2: + l ^= get_le32_split(data[0], data[1], 0x5a, 0); + break; + case 3: + l ^= get_le32_split(data[0], data[1], data[2], 0x5a); + break; + } + michael_block(l, r); + michael_block(l, r); + put_le32(mic, l); + put_le32(mic + 4, r); + + return OL_RX_DEFRAG_OK; +} + +/* + * Calculate headersize + */ +u_int16_t +ol_rx_frag_hdrsize(const void *data) +{ + const struct ieee80211_frame *wh = (const struct ieee80211_frame *) data; + u_int16_t size = sizeof(struct ieee80211_frame); + + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { + size += IEEE80211_ADDR_LEN; + } + if (DEFRAG_IEEE80211_QOS_HAS_SEQ(wh)) { + size += sizeof(u_int16_t); + if (wh->i_fc[1] & IEEE80211_FC1_ORDER) { + size += sizeof(struct ieee80211_htc); + } + } + return size; +} + +/* + * Recombine and decap fragments + */ +adf_nbuf_t +ol_rx_defrag_decap_recombine( + htt_pdev_handle htt_pdev, + adf_nbuf_t frag_list, + u_int16_t hdrsize) +{ + adf_nbuf_t tmp; + adf_nbuf_t msdu = frag_list; + adf_nbuf_t rx_nbuf = frag_list; + struct ieee80211_frame* wh; + + msdu = adf_nbuf_next(msdu); + adf_nbuf_set_next(rx_nbuf, NULL); + while (msdu) { + htt_rx_msdu_desc_free(htt_pdev, msdu); + tmp = adf_nbuf_next(msdu); + adf_nbuf_set_next(msdu, NULL); + OL_RX_FRAG_PULL_HDR(htt_pdev, msdu, hdrsize); + if (!ol_rx_defrag_concat(rx_nbuf, msdu)) { + ol_rx_frames_free(htt_pdev, tmp); + htt_rx_desc_frame_free(htt_pdev, rx_nbuf); + adf_nbuf_free(msdu); /* msdu rx desc already freed above */ + return NULL; + } + msdu = tmp; + } + wh = (struct ieee80211_frame *)OL_RX_FRAG_GET_MAC_HDR(htt_pdev, rx_nbuf); + wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG; + *(u_int16_t *) wh->i_seq &= ~IEEE80211_SEQ_FRAG_MASK; + + return rx_nbuf; +} + +void +ol_rx_defrag_nwifi_to_8023(ol_txrx_pdev_handle pdev, adf_nbuf_t msdu) +{ + struct ieee80211_frame wh; + a_uint32_t hdrsize; + struct llc_snap_hdr_t llchdr; + struct ethernet_hdr_t *eth_hdr; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + struct ieee80211_frame *wh_ptr; + + ol_rx_frag_desc_adjust( + pdev, + msdu, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + + wh_ptr = (struct ieee80211_frame *) (adf_nbuf_data(msdu) + rx_desc_len); + adf_os_mem_copy(&wh, wh_ptr, sizeof(wh)); + hdrsize = sizeof(struct ieee80211_frame); + adf_os_mem_copy(&llchdr, ((a_uint8_t *) (adf_nbuf_data(msdu) + + rx_desc_len)) + hdrsize, sizeof(struct llc_snap_hdr_t)); + + /* + * Now move the data pointer to the beginning of the mac header : + * new-header = old-hdr + (wifhdrsize + llchdrsize - ethhdrsize) + */ + adf_nbuf_pull_head(msdu, (rx_desc_len + hdrsize + + sizeof(struct llc_snap_hdr_t) - sizeof(struct ethernet_hdr_t))); + eth_hdr = (struct ethernet_hdr_t *)(adf_nbuf_data(msdu)); + switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + adf_os_mem_copy(eth_hdr->dest_addr, wh.i_addr1, IEEE80211_ADDR_LEN); + adf_os_mem_copy(eth_hdr->src_addr, wh.i_addr2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + adf_os_mem_copy(eth_hdr->dest_addr, wh.i_addr3, IEEE80211_ADDR_LEN); + adf_os_mem_copy(eth_hdr->src_addr, wh.i_addr2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + adf_os_mem_copy(eth_hdr->dest_addr, wh.i_addr1, IEEE80211_ADDR_LEN); + adf_os_mem_copy(eth_hdr->src_addr, wh.i_addr3, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + break; + } + + adf_os_mem_copy( + eth_hdr->ethertype, llchdr.ethertype, sizeof(llchdr.ethertype)); + if (pdev->cfg.is_high_latency) { + adf_nbuf_push_head(msdu, rx_desc_len); + adf_os_mem_move( + adf_nbuf_data(msdu), rx_desc_old_position, rx_desc_len); + adf_os_mem_move( + adf_nbuf_data(msdu) - HTT_RX_IND_HL_BYTES, ind_old_position, + HTT_RX_IND_HL_BYTES); + } +} + +/* + * Handling QOS for defragmentation + */ +void +ol_rx_defrag_qos_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t nbuf, + u_int16_t hdrlen) +{ + struct ieee80211_frame *wh; + u_int16_t qoslen; + void *rx_desc_old_position = NULL; + void *ind_old_position = NULL; + int rx_desc_len = 0; + + ol_rx_frag_desc_adjust( + pdev, + nbuf, + &rx_desc_old_position, + &ind_old_position, + &rx_desc_len); + + wh = (struct ieee80211_frame *) (adf_nbuf_data(nbuf)+rx_desc_len); + if (DEFRAG_IEEE80211_QOS_HAS_SEQ(wh)) { + qoslen = sizeof(struct ieee80211_qoscntl); + /* Qos frame with Order bit set indicates a HTC frame */ + if (wh->i_fc[1] & IEEE80211_FC1_ORDER) { + qoslen += sizeof(struct ieee80211_htc); + } + + /* remove QoS filed from header */ + hdrlen -= qoslen; + adf_os_mem_move((u_int8_t *) wh + qoslen, wh, hdrlen); + wh = (struct ieee80211_frame *) adf_nbuf_pull_head(nbuf, + rx_desc_len + qoslen); + /* clear QoS bit */ + /* + * KW# 6154 'adf_nbuf_pull_head' in turn calls __adf_nbuf_pull_head, + * which returns NULL if there is not sufficient data to pull. + * It's guaranteed that adf_nbuf_pull_head will succeed rather than + * returning NULL, since the entire rx frame is already present in the + * rx buffer. + * However, to make it obvious to static analyzers that this code is + * safe, add an explicit check that adf_nbuf_pull_head returns a + * non-NULL value. + * Since this part of the code is not performance-critical, adding this + * explicit check is okay. + */ + if (wh) { + wh->i_fc[0] &= ~IEEE80211_FC0_SUBTYPE_QOS; + } + if (pdev->cfg.is_high_latency) { + adf_nbuf_push_head(nbuf, rx_desc_len); + adf_os_mem_move( + adf_nbuf_data(nbuf), rx_desc_old_position, rx_desc_len); + adf_os_mem_move( + adf_nbuf_data(nbuf)-HTT_RX_IND_HL_BYTES, ind_old_position, + HTT_RX_IND_HL_BYTES); + } + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.h new file mode 100644 index 000000000000..737c29987305 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_defrag.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_RX_DEFRAG_H_ +#define _OL_RX_DEFRAG_H_ + +#include +#include +#include +#include +#include +#include +#include + + +#define DEFRAG_IEEE80211_ADDR_LEN 6 +#define DEFRAG_IEEE80211_KEY_LEN 8 +#define DEFRAG_IEEE80211_FCS_LEN 4 + +struct ol_rx_defrag_cipher { + const char *ic_name; + u_int16_t ic_header; + u_int8_t ic_trailer; + u_int8_t ic_miclen; +}; + +enum { + OL_RX_DEFRAG_ERR, + OL_RX_DEFRAG_OK, + OL_RX_DEFRAG_PN_ERR +}; + +#define ol_rx_defrag_copydata(buf, offset, len, _to) \ + adf_nbuf_copy_bits(buf, offset, len, _to) + +#define ol_rx_defrag_len(buf) \ + adf_nbuf_len(buf) + +void +ol_rx_fraglist_insert( + htt_pdev_handle htt_pdev, + adf_nbuf_t *head_addr, + adf_nbuf_t *tail_addr, + adf_nbuf_t frag, + u_int8_t *all_frag_present); + +void +ol_rx_defrag_waitlist_add( + struct ol_txrx_peer_t *peer, + unsigned tid); + +void +ol_rx_defrag_waitlist_remove( + struct ol_txrx_peer_t *peer, + unsigned tid); + +void +ol_rx_defrag_waitlist_flush( + struct ol_txrx_pdev_t *pdev); + +void +ol_rx_defrag( + ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t frag_list); + +int +ol_rx_frag_tkip_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msdu, + u_int16_t hdrlen); + +int +ol_rx_frag_wep_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t nbuf, + u_int16_t hdrlen); + +void +ol_rx_defrag_nwifi_to_8023(ol_txrx_pdev_handle pdev, adf_nbuf_t msdu); + +void +ol_rx_defrag_qos_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t nbuf, + u_int16_t hdrlen); + +int +ol_rx_frag_tkip_demic( + ol_txrx_pdev_handle pdev, + const u_int8_t *key, + adf_nbuf_t msdu, + u_int16_t hdrlen); + +int +ol_rx_frag_ccmp_decap( + ol_txrx_pdev_handle pdev, + adf_nbuf_t nbuf, + u_int16_t hdrlen); + +int +ol_rx_frag_ccmp_demic( + ol_txrx_pdev_handle pdev, + adf_nbuf_t wbuf, + u_int16_t hdrlen); + +u_int16_t +ol_rx_frag_hdrsize(const void *data); + +void +ol_rx_defrag_michdr( + const struct ieee80211_frame *wh0, + u_int8_t hdr[]); + +void +ol_rx_reorder_store_frag( + ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + u_int16_t seq_num, + adf_nbuf_t frag); + +adf_nbuf_t +ol_rx_defrag_decap_recombine( + htt_pdev_handle htt_pdev, + adf_nbuf_t frag_list, + u_int16_t hdrsize); + +int +ol_rx_defrag_mic( + ol_txrx_pdev_handle pdev, + const u_int8_t *key, + adf_nbuf_t wbuf, + u_int16_t off, + u_int16_t data_len, + u_int8_t mic[]); + +void +ol_rx_reorder_flush_frag( + htt_pdev_handle htt_pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + int seq_num); + +static inline void +xor_block( + u_int8_t *b, + const u_int8_t *a, + adf_os_size_t len) +{ + adf_os_size_t i; + + for (i = 0; i < len; i++) { + b[i] ^= a[i]; + } +} + +static inline u_int32_t +rotl( + u_int32_t val, + int bits) +{ + return (val << bits) | (val >> (32 - bits)); +} + +static inline u_int32_t +rotr( + u_int32_t val, + int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + +static inline u_int32_t +xswap(u_int32_t val) +{ + return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); +} + +static inline u_int32_t +get_le32_split( + u_int8_t b0, + u_int8_t b1, + u_int8_t b2, + u_int8_t b3) +{ + return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); +} + +static inline u_int32_t +get_le32(const u_int8_t *p) +{ + return get_le32_split(p[0], p[1], p[2], p[3]); +} + +static inline void +put_le32( + u_int8_t *p, + u_int32_t v) +{ + p[0] = (v) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; +} + +static inline u_int8_t +ol_rx_defrag_concat( + adf_nbuf_t dst, + adf_nbuf_t src) +{ + /* + * Inside adf_nbuf_cat, if it is necessary to reallocate dst + * to provide space for src, the headroom portion is copied from + * the original dst buffer to the larger new dst buffer. + * (This is needed, because the headroom of the dst buffer + * contains the rx desc.) + */ + if (adf_nbuf_cat(dst, src)) { + return OL_RX_DEFRAG_ERR; + } + + return OL_RX_DEFRAG_OK; +} + +#define michael_block(l, r) \ + do { \ + r ^= rotl(l, 17); \ + l += r; \ + r ^= xswap(l); \ + l += r; \ + r ^= rotl(l, 3); \ + l += r; \ + r ^= rotr(l, 2); \ + l += r; \ + } while (0) + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.c new file mode 100644 index 000000000000..7072eef4e780 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* standard header files */ +#include /* adf_nbuf_map */ +#include /* adf_os_mem_cmp */ + +/* external header files */ +#include /* wlan_op_mode_ap, etc. */ +#include /* htt_rx_msdu_desc_retrieve */ +#include /* ieee80211_frame, etc. */ + +/* internal header files */ +#include /* ol_txrx_dev_t, etc. */ +#include /* our own defs */ +#include /* ol_rx_deliver */ +#include /* TXRX_ASSERT1 */ +#ifdef QCA_ARP_SPOOFING_WAR +#include +#endif + + +/* + * Porting from Ap11PrepareForwardedPacket. + * This routine is called when a RX data frame from an associated station is + * to be forwarded to another associated station. We will prepare the + * received packet so that it is suitable for transmission again. + * Check that this Packet is suitable for forwarding. If yes, then + * prepare the new 802.11 header. + */ +static inline +void +ol_ap_fwd_check(struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu) +{ + struct ieee80211_frame *mac_header; + unsigned char tmp_addr[6]; + unsigned char type; + unsigned char subtype; + unsigned char fromds; + unsigned char tods; + + mac_header = (struct ieee80211_frame *) (adf_nbuf_data(msdu)); + TXRX_ASSERT1(mac_header); + + type = mac_header->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + subtype = mac_header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + tods = mac_header->i_fc[1] & IEEE80211_FC1_DIR_TODS; + fromds = mac_header->i_fc[1] & IEEE80211_FC1_DIR_FROMDS; + + /* + * Make sure no QOS or any other non-data subtype + * Should be a ToDs data frame. + * Make sure that this frame is unicast and not for us. + * These packets should come up through the normal rx path and not forwarded. + */ + if (type != IEEE80211_FC0_TYPE_DATA || + subtype != 0x0 || + ((tods != 1) || (fromds != 0)) || + (adf_os_mem_cmp( + mac_header->i_addr3, vdev->mac_addr.raw, IEEE80211_ADDR_LEN) == 0)) + { +#ifdef DEBUG_HOST_RC + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "Exit: %s | Unnecessary to adjust mac header\n", __func__); +#endif + } + else + { + // Flip the ToDs bit to FromDs + mac_header->i_fc[1] &= 0xfe; + mac_header->i_fc[1] |= 0x2; + + /* + * Flip the addresses + * (ToDs, addr1, RA=BSSID) move to (FrDs, addr2, TA=BSSID) + * (ToDs, addr2, SA) move to (FrDs, addr3, SA) + * (ToDs, addr3, DA) move to (FrDs, addr1, DA) + */ + + memcpy(tmp_addr, + mac_header->i_addr2, + sizeof (tmp_addr)); + + memcpy(mac_header->i_addr2, + mac_header->i_addr1, + sizeof (tmp_addr)); + + memcpy(mac_header->i_addr1, + mac_header->i_addr3, + sizeof (tmp_addr)); + + memcpy(mac_header->i_addr3, + tmp_addr, + sizeof (tmp_addr)); + } +} + +static inline +void +ol_rx_fwd_to_tx(struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + + if (pdev->frame_format == wlan_frm_fmt_native_wifi) + { + ol_ap_fwd_check(vdev, msdu); + } + /* + * Map the netbuf, so it's accessible to the DMA that + * sends it to the target. + */ + adf_nbuf_map_single(pdev->osdev, msdu, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_set_next(msdu, NULL); /* add NULL terminator */ + + /* for HL, point to payload before send to tx again.*/ + if (pdev->cfg.is_high_latency) { + void *rx_desc; + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); + + adf_nbuf_pull_head(msdu, + htt_rx_msdu_rx_desc_size_hl(pdev->htt_pdev, + rx_desc)); + } + + msdu = vdev->tx(vdev, msdu); + + if (msdu) { + /* + * The frame was not accepted by the tx. + * We could store the frame and try again later, + * but the simplest solution is to discard the frames. + */ + adf_nbuf_unmap_single(pdev->osdev, msdu, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(msdu); + } +} + +void +ol_rx_fwd_check( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + adf_nbuf_t deliver_list_head = NULL; + adf_nbuf_t deliver_list_tail = NULL; + adf_nbuf_t msdu; + + msdu = msdu_list; + while (msdu) { + struct ol_txrx_vdev_t *tx_vdev; + void *rx_desc; + /* + * Remember the next list elem, because our processing + * may cause the MSDU to get linked into a different list. + */ + msdu_list = adf_nbuf_next(msdu); + + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); + + if (!vdev->disable_intrabss_fwd && + htt_rx_msdu_forward(pdev->htt_pdev, rx_desc)) { +#ifdef QCA_ARP_SPOOFING_WAR + void *filter_cb; +#endif + int do_not_fwd = 0; + /* + * Use the same vdev that received the frame to + * transmit the frame. + * This is exactly what we want for intra-BSS forwarding, + * like STA-to-STA forwarding and multicast echo. + * If this is a intra-BSS forwarding case (which is not + * currently supported), then the tx vdev is different + * from the rx vdev. + * On the LL host the vdevs are not actually used for tx, + * so it would still work to use the rx vdev rather than + * the tx vdev. + * For HL, the tx classification searches for the DA within + * the given vdev, so we would want to get the DA peer ID + * from the target, so we can locate the tx vdev. + */ + tx_vdev = vdev; + /* + * Copying TID value of RX packet to forwarded + * packet if the tid is other than non qos tid. + * But for non qos tid fill invalid tid so that + * Fw will take care of filling proper tid. + */ + if (tid != HTT_NON_QOS_TID) { + adf_nbuf_set_tid(msdu, tid); + } else { + adf_nbuf_set_tid(msdu, ADF_NBUF_TX_EXT_TID_INVALID); + } + +#ifdef QCA_ARP_SPOOFING_WAR + filter_cb = (void *)NBUF_CB_PTR(msdu); + if (filter_cb) { + do_not_fwd = (*(hdd_filter_cb_t)filter_cb)(vdev->vdev_id, msdu, + RX_INTRA_BSS_FWD); + } +#endif + /* + * This MSDU needs to be forwarded to the tx path. + * Check whether it also needs to be sent to the OS shim, + * in which case we need to make a copy (or clone?). + */ + if (!do_not_fwd) { + if (htt_rx_msdu_discard(pdev->htt_pdev, rx_desc)) { + htt_rx_msdu_desc_free(pdev->htt_pdev, msdu); + ol_rx_fwd_to_tx(tx_vdev, msdu); + msdu = NULL; /* already handled this MSDU */ + TXRX_STATS_ADD(pdev, pub.rx.intra_bss_fwd.packets_fwd, + 1); + } else { + adf_nbuf_t copy; + copy = adf_nbuf_copy(msdu); + if (copy) { + ol_rx_fwd_to_tx(tx_vdev, copy); + } + TXRX_STATS_ADD(pdev, + pub.rx.intra_bss_fwd.packets_stack_n_fwd, 1); + } + } + } else { + TXRX_STATS_ADD(pdev, pub.rx.intra_bss_fwd.packets_stack, 1); + } + if (msdu) { + /* send this frame to the OS */ + OL_TXRX_LIST_APPEND(deliver_list_head, deliver_list_tail, msdu); + } + msdu = msdu_list; + } + if (deliver_list_head) { + adf_nbuf_set_next(deliver_list_tail, NULL); /* add NULL terminator */ + if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) { + ol_rx_in_order_deliver(vdev, peer, tid, deliver_list_head); + } else { + ol_rx_deliver(vdev, peer, tid, deliver_list_head); + } + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.h new file mode 100644 index 000000000000..928c151625f9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_fwd.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_RX_FWD_H_ +#define _OL_RX_FWD_H_ + +#include /* adf_nbuf_t, etc. */ + +#include /* ol_txrx_peer_t, etc. */ + +adf_nbuf_t +ol_rx_fwd_mcast_check_sta( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + adf_nbuf_t msdu, + void *rx_desc, + int is_wlan_mcast); + +adf_nbuf_t +ol_rx_fwd_mcast_check_ap( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + adf_nbuf_t msdu, + void *rx_desc, + int is_wlan_mcast); + +/** + * @brief Check if rx frames should be transmitted over WLAN. + * @details + * Check if rx frames should be transmitted back over WLAN, instead of + * or in addition to delivering the rx frames to the OS. + * Rx frames will be forwarded to the transmit path under the following + * conditions: + * 1. If the destination is a STA associated to the same virtual device + * within this physical device, the rx frame will be forwarded to the + * tx path rather than being sent to the OS. If the destination is a + * STA associated to a different virtual device within this physical + * device, then the rx frame will optionally be forwarded to the tx path. + * 2. If the frame is received by an AP, but the destination is for another + * AP that the current AP is associated with for WDS forwarding, the + * intermediate AP will forward the rx frame to the tx path to transmit + * to send to the destination AP, rather than sending it to the OS. + * 3. If the AP receives a multicast frame, it will retransmit the frame + * within the BSS, in addition to sending the frame to the OS. + * + * @param vdev - which virtual device the frames were addressed to + * @param peer - which peer the rx frames belong to + * @param tid - which TID within the peer the rx frames belong to + * @param msdu_list - NULL-terminated list of MSDUs to perform the rx->tx + * forwarding check on + */ +void +ol_rx_fwd_check( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list); + + +#endif /* _OL_RX_FWD_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.c new file mode 100644 index 000000000000..5bc11c20145a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2011, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* adf_nbuf_t */ + +#include /* htt_rx_pn_t, etc. */ +#include /* ol_rx_err */ + +#include /* ol_rx_mpdu_list_next */ +#include /* ol_txrx_vdev_t, etc. */ +#include /* our own defs */ +#include /* ol_rx_fwd_check */ +#include /* ol_rx_deliver */ + +/* add the MSDUs from this MPDU to the list of good frames */ +#define ADD_MPDU_TO_LIST(head, tail, mpdu, mpdu_tail) do { \ + if (!head) { \ + head = mpdu; \ + } else { \ + adf_nbuf_set_next(tail, mpdu); \ + } \ + tail = mpdu_tail; \ + } while(0); + +int ol_rx_pn_cmp24( + union htt_rx_pn_t *new_pn, + union htt_rx_pn_t *old_pn, + int is_unicast, + int opmode) +{ + return ((new_pn->pn24 & 0xffffff) <= (old_pn->pn24 & 0xffffff)); +} + + +int ol_rx_pn_cmp48( + union htt_rx_pn_t *new_pn, + union htt_rx_pn_t *old_pn, + int is_unicast, + int opmode) +{ + return + ((new_pn->pn48 & 0xffffffffffffULL) <= + (old_pn->pn48 & 0xffffffffffffULL)); +} + +int ol_rx_pn_wapi_cmp( + union htt_rx_pn_t *new_pn, + union htt_rx_pn_t *old_pn, + int is_unicast, + int opmode) +{ + int pn_is_replay = 0; + + if (new_pn->pn128[1] == old_pn->pn128[1]) { + pn_is_replay = (new_pn->pn128[0] <= old_pn->pn128[0]); + } else { + pn_is_replay = (new_pn->pn128[1] < old_pn->pn128[1]); + } + + if (is_unicast) { + if (opmode == wlan_op_mode_ap) { + pn_is_replay |= ((new_pn->pn128[0] & 0x1ULL) != 0); + } else { + pn_is_replay |= ((new_pn->pn128[0] & 0x1ULL) != 1); + } + } + return pn_is_replay; +} + +adf_nbuf_t +ol_rx_pn_check_base( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + union htt_rx_pn_t *last_pn; + adf_nbuf_t out_list_head = NULL; + adf_nbuf_t out_list_tail = NULL; + adf_nbuf_t mpdu; + int index; /* unicast vs. multicast */ + int pn_len; + void *rx_desc; + int last_pn_valid; + + /* Make sure host pn check is not redundant */ + if ((adf_os_atomic_read(&peer->fw_pn_check)) || + (vdev->opmode == wlan_op_mode_ibss)) { + return msdu_list; + } + + /* First, check whether the PN check applies */ + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu_list); + adf_os_assert(htt_rx_msdu_has_wlan_mcast_flag(pdev->htt_pdev, rx_desc)); + index = htt_rx_msdu_is_wlan_mcast(pdev->htt_pdev, rx_desc) ? + txrx_sec_mcast : txrx_sec_ucast; + pn_len = pdev->rx_pn[peer->security[index].sec_type].len; + if (pn_len == 0) { + return msdu_list; + } + + last_pn_valid = peer->tids_last_pn_valid[tid]; + last_pn = &peer->tids_last_pn[tid]; + mpdu = msdu_list; + while (mpdu) { + adf_nbuf_t mpdu_tail, next_mpdu; + union htt_rx_pn_t new_pn; + int pn_is_replay = 0; + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, mpdu); + + /* + * Find the last MSDU within this MPDU, and + * the find the first MSDU within the next MPDU. + */ + ol_rx_mpdu_list_next(pdev, mpdu, &mpdu_tail, &next_mpdu); + + /* Don't check the PN replay for non-encrypted frames */ + if (!htt_rx_mpdu_is_encrypted(pdev->htt_pdev, rx_desc)) { + ADD_MPDU_TO_LIST(out_list_head, out_list_tail, mpdu, mpdu_tail); + mpdu = next_mpdu; + continue; + } + + /* retrieve PN from rx descriptor */ + htt_rx_mpdu_desc_pn(pdev->htt_pdev, rx_desc, &new_pn, pn_len); + + /* if there was no prior PN, there's nothing to check */ + if (last_pn_valid) { + pn_is_replay = pdev->rx_pn[peer->security[index].sec_type].cmp( + &new_pn, last_pn, index == txrx_sec_ucast, vdev->opmode); + } else { + last_pn_valid = peer->tids_last_pn_valid[tid] = 1; + } + + if (pn_is_replay) { + adf_nbuf_t msdu; + static u_int32_t last_pncheck_print_time = 0; + int log_level; + u_int32_t current_time_ms; + + /* + * This MPDU failed the PN check: + * 1. Notify the control SW of the PN failure + * (so countermeasures can be taken, if necessary) + * 2. Discard all the MSDUs from this MPDU. + */ + msdu = mpdu; + current_time_ms = adf_os_ticks_to_msecs(adf_os_ticks()); + if (TXRX_PN_CHECK_FAILURE_PRINT_PERIOD_MS < + (current_time_ms - last_pncheck_print_time)) { + last_pncheck_print_time = current_time_ms; + log_level = TXRX_PRINT_LEVEL_WARN; + } + else { + log_level = TXRX_PRINT_LEVEL_INFO2; + } + + TXRX_PRINT(log_level, + "PN check failed - TID %d, peer %p " + "(%02x:%02x:%02x:%02x:%02x:%02x) %s\n" + " old PN (u64 x2)= 0x%08llx %08llx (LSBs = %lld)\n" + " new PN (u64 x2)= 0x%08llx %08llx (LSBs = %lld)\n" + " new seq num = %d\n", + tid, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5], + (index == txrx_sec_ucast) ? "ucast" : "mcast", + last_pn->pn128[1], + last_pn->pn128[0], + last_pn->pn128[0] & 0xffffffffffffULL, + new_pn.pn128[1], + new_pn.pn128[0], + new_pn.pn128[0] & 0xffffffffffffULL, + htt_rx_mpdu_desc_seq_num(pdev->htt_pdev, rx_desc)); +#if defined(ENABLE_RX_PN_TRACE) + ol_rx_pn_trace_display(pdev, 1); +#endif /* ENABLE_RX_PN_TRACE */ + ol_rx_err( + pdev->ctrl_pdev, + vdev->vdev_id, peer->mac_addr.raw, tid, + htt_rx_mpdu_desc_tsf32(pdev->htt_pdev, rx_desc), + OL_RX_ERR_PN, mpdu, NULL, 0); + /* free all MSDUs within this MPDU */ + do { + adf_nbuf_t next_msdu; + OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_desc, OL_RX_ERR_PN); + next_msdu = adf_nbuf_next(msdu); + htt_rx_desc_frame_free(pdev->htt_pdev, msdu); + if (msdu == mpdu_tail) { + break; + } else { + msdu = next_msdu; + } + } while (1); + } else { + ADD_MPDU_TO_LIST(out_list_head, out_list_tail, mpdu, mpdu_tail); + /* + * Remember the new PN. + * For simplicity, just do 2 64-bit word copies to cover the worst + * case (WAPI), regardless of the length of the PN. + * This is more efficient than doing a conditional branch to copy + * only the relevant portion. + */ + last_pn->pn128[0] = new_pn.pn128[0]; + last_pn->pn128[1] = new_pn.pn128[1]; + OL_RX_PN_TRACE_ADD(pdev, peer, tid, rx_desc); + } + + mpdu = next_mpdu; + } + /* make sure the list is null-terminated */ + if (out_list_tail) { + adf_nbuf_set_next(out_list_tail, NULL); + } + return out_list_head; +} + +void +ol_rx_pn_check( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list); + ol_rx_fwd_check(vdev, peer, tid, msdu_list); +} + +void +ol_rx_pn_check_only( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list) +{ + msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list); + ol_rx_deliver(vdev, peer, tid, msdu_list); +} + +#if defined(ENABLE_RX_PN_TRACE) + +A_STATUS +ol_rx_pn_trace_attach(ol_txrx_pdev_handle pdev) +{ + int num_elems; + + num_elems = 1 << TXRX_RX_PN_TRACE_SIZE_LOG2; + pdev->rx_pn_trace.idx = 0; + pdev->rx_pn_trace.cnt = 0; + pdev->rx_pn_trace.mask = num_elems - 1; + pdev->rx_pn_trace.data = adf_os_mem_alloc( + pdev->osdev, sizeof(*pdev->rx_pn_trace.data) * num_elems); + if (! pdev->rx_pn_trace.data) { + return A_ERROR; + } + return A_OK; +} + +void +ol_rx_pn_trace_detach(ol_txrx_pdev_handle pdev) +{ + adf_os_mem_free(pdev->rx_pn_trace.data); +} + +void +ol_rx_pn_trace_add( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + u_int16_t tid, + void *rx_desc) +{ + u_int32_t idx = pdev->rx_pn_trace.idx; + union htt_rx_pn_t pn; + u_int32_t pn32; + u_int16_t seq_num; + u_int8_t unicast; + + htt_rx_mpdu_desc_pn(pdev->htt_pdev, rx_desc, &pn, 48); + pn32 = pn.pn48 & 0xffffffff; + seq_num = htt_rx_mpdu_desc_seq_num(pdev->htt_pdev, rx_desc); + unicast = ! htt_rx_msdu_is_wlan_mcast(pdev->htt_pdev, rx_desc); + + pdev->rx_pn_trace.data[idx].peer = peer; + pdev->rx_pn_trace.data[idx].tid = tid; + pdev->rx_pn_trace.data[idx].seq_num = seq_num; + pdev->rx_pn_trace.data[idx].unicast = unicast; + pdev->rx_pn_trace.data[idx].pn32 = pn32; + pdev->rx_pn_trace.cnt++; + idx++; + pdev->rx_pn_trace.idx = idx & pdev->rx_pn_trace.mask; +} + +void +ol_rx_pn_trace_display(ol_txrx_pdev_handle pdev, int just_once) +{ + static int print_count = 0; + u_int32_t i, start, end; + u_int64_t cnt; + int elems; + int limit = 0; /* move this to the arg list? */ + + if (print_count != 0 && just_once) { + return; + } + print_count++; + + end = pdev->rx_pn_trace.idx; + if (pdev->rx_pn_trace.cnt <= pdev->rx_pn_trace.mask) { + /* trace log has not yet wrapped around - start at the top */ + start = 0; + cnt = 0; + } else { + start = end; + cnt = pdev->rx_pn_trace.cnt - (pdev->rx_pn_trace.mask + 1); + } + elems = (end - 1 - start) & pdev->rx_pn_trace.mask; + if (limit > 0 && elems > limit) { + int delta; + delta = elems - limit; + start += delta; + start &= pdev->rx_pn_trace.mask; + cnt += delta; + } + + i = start; + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " seq PN\n"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " count idx peer tid uni num LSBs\n"); + do { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " %6lld %4d %p %2d %d %4d %8d\n", + cnt, i, + pdev->rx_pn_trace.data[i].peer, + pdev->rx_pn_trace.data[i].tid, + pdev->rx_pn_trace.data[i].unicast, + pdev->rx_pn_trace.data[i].seq_num, + pdev->rx_pn_trace.data[i].pn32); + cnt++; + i++; + i &= pdev->rx_pn_trace.mask; + } while (i != end); +} +#endif /* ENABLE_RX_PN_TRACE */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.h new file mode 100644 index 000000000000..24ba9d09c422 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_pn.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_RX_PN_H_ +#define _OL_RX_PN_H_ + +#include /* adf_nbuf_t, etc. */ + +#include /* ol_txrx_peer_t, etc. */ + +int ol_rx_pn_cmp24( + union htt_rx_pn_t *new_pn, + union htt_rx_pn_t *old_pn, + int is_unicast, + int opmode); + +int ol_rx_pn_cmp48( + union htt_rx_pn_t *new_pn, + union htt_rx_pn_t *old_pn, + int is_unicast, + int opmode); + +int ol_rx_pn_wapi_cmp( + union htt_rx_pn_t *new_pn, + union htt_rx_pn_t *old_pn, + int is_unicast, + int opmode); + +/** + * @brief If applicable, check the Packet Number to detect replays. + * @details + * Determine whether a PN check is needed, and if so, what the PN size is. + * (A PN size of 0 is used to indirectly bypass the PN check for security + * methods that don't involve a PN check.) + * This function produces event notifications for any PN failures, via the + * ol_rx_err function. + * After the PN check, call the next stage of rx processing (rx --> tx + * forwarding check). + * + * @param vdev - which virtual device the frames were addressed to + * @param peer - which peer the rx frames belong to + * @param tid - which TID within the peer the rx frames belong to + * @param msdu_list - NULL-terminated list of MSDUs to perform PN check on + * (if PN check is applicable, i.e. PN length > 0) + */ +void +ol_rx_pn_check( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list); + +/** + * @brief If applicable, check the Packet Number to detect replays. + * @details + * Determine whether a PN check is needed, and if so, what the PN size is. + * (A PN size of 0 is used to indirectly bypass the PN check for security + * methods that don't involve a PN check.) + * This function produces event notifications for any PN failures, via the + * ol_rx_err function. + * After the PN check, deliver the valid rx frames to the OS shim. + * (Don't perform a rx --> tx forwarding check.) + * + * @param vdev - which virtual device the frames were addressed to + * @param peer - which peer the rx frames belong to + * @param tid - which TID within the peer the rx frames belong to + * @param msdu_list - NULL-terminated list of MSDUs to perform PN check on + * (if PN check is applicable, i.e. PN length > 0) + */ +void +ol_rx_pn_check_only( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list); + +/** + * @brief If applicable, check the Packet Number to detect replays. + * @details + * Same as ol_rx_pn_check but return valid rx netbufs + * rather than invoking the rx --> tx forwarding check. + * + * @param vdev - which virtual device the frames were addressed to + * @param peer - which peer the rx frames belong to + * @param tid - which TID within the peer the rx frames belong to + * @param msdu_list - NULL-terminated list of MSDUs to perform PN check on + * (if PN check is applicable, i.e. PN length > 0) + * @return list of netbufs that didn't fail the PN check + */ +adf_nbuf_t +ol_rx_pn_check_base( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list); + + +#endif /* _OL_RX_PN_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c new file mode 100644 index 000000000000..c4d2e273533b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c @@ -0,0 +1,831 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=== header file includes ===*/ +/* generic utilities */ +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_mem_alloc */ + +#include /* IEEE80211_SEQ_MAX */ + +/* external interfaces */ +#include /* ol_txrx_pdev_handle */ +#include /* ol_rx_addba_handler, etc. */ +#include /* ol_ctrl_rx_addba_complete */ +#include /* htt_rx_desc_frame_free */ +#include /* ol_rx_err */ + +/* datapath internal interfaces */ +#include /* ol_txrx_peer_find_by_id */ +#include /* TXRX_ASSERT */ +#include /* OL_RX_REORDER_TIMEOUT_REMOVE, etc. */ +#include +#include + + +/*=== data types and defines ===*/ +#define OL_RX_REORDER_ROUND_PWR2(value) g_log2ceil[value] + +/*=== global variables ===*/ + +static char g_log2ceil[] = { + 1, // 0 -> 1 + 1, // 1 -> 1 + 2, // 2 -> 2 + 4, 4, // 3-4 -> 4 + 8, 8, 8, 8, // 5-8 -> 8 + 16, 16, 16, 16, 16, 16, 16, 16, // 9-16 -> 16 + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, // 17-32 -> 32 + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, // 33-64 -> 64 +}; + + +/*=== function definitions ===*/ + +/*---*/ + +#define QCA_SUPPORT_RX_REORDER_RELEASE_CHECK 0 +#define OL_RX_REORDER_IDX_START_SELF_SELECT(peer, tid, idx_start) /* no-op */ +#define OL_RX_REORDER_IDX_WRAP(idx, win_sz, win_sz_mask) idx &= win_sz_mask; +#define OL_RX_REORDER_IDX_MAX(win_sz, win_sz_mask) win_sz_mask +#define OL_RX_REORDER_IDX_INIT(seq_num, win_sz, win_sz_mask) 0 /* n/a */ +#define OL_RX_REORDER_NO_HOLES(rx_reorder) 0 +#define OL_RX_REORDER_MPDU_CNT_INCR(rx_reorder, incr) /* n/a */ +#define OL_RX_REORDER_MPDU_CNT_DECR(rx_reorder, decr) /* n/a */ + + +/*---*/ + +/* reorder array elements are known to be non-NULL */ +#define OL_RX_REORDER_PTR_CHECK(ptr) /* no-op */ +#define OL_RX_REORDER_LIST_APPEND(head_msdu, tail_msdu, rx_reorder_array_elem) \ + do { \ + if (tail_msdu) { \ + adf_nbuf_set_next(tail_msdu, rx_reorder_array_elem->head); \ + } \ + } while (0) + + +/* functions called by txrx components */ + +void ol_rx_reorder_init(struct ol_rx_reorder_t *rx_reorder, u_int8_t tid) +{ + rx_reorder->win_sz = 1; + rx_reorder->win_sz_mask = 0; + rx_reorder->array = &rx_reorder->base; + rx_reorder->base.head = rx_reorder->base.tail = NULL; + rx_reorder->tid = tid; + rx_reorder->defrag_timeout_ms = 0; + + rx_reorder->defrag_waitlist_elem.tqe_next = NULL; + rx_reorder->defrag_waitlist_elem.tqe_prev = NULL; +} + + +static enum htt_rx_status +ol_rx_reorder_seq_num_check( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned seq_num) +{ + unsigned seq_num_delta; + + /* don't check the new seq_num against last_seq if last_seq is not valid */ + if (peer->tids_last_seq[tid] == IEEE80211_SEQ_MAX) { + return htt_rx_status_ok; + } + /* + * For duplicate detection, it might be helpful to also check + * whether the retry bit is set or not - a strict duplicate packet + * should be the one with retry bit set. + * However, since many implementations do not set the retry bit, + * and since this same function is also used for filtering out + * late-arriving frames (frames that arive after their rx reorder + * timeout has expired) which are not retries, don't bother checking + * the retry bit for now. + */ + /* note: if new seq_num == old seq_num, seq_num_delta = 4095 */ + seq_num_delta = (seq_num - 1 - peer->tids_last_seq[tid]) & + (IEEE80211_SEQ_MAX-1); /* account for wraparound */ + + if (seq_num_delta > (IEEE80211_SEQ_MAX >> 1)) { + return htt_rx_status_err_replay; /* or maybe htt_rx_status_err_dup */ + } + return htt_rx_status_ok; +} + +/** + * ol_rx_seq_num_check() - Does duplicate detection for mcast packets and + * duplicate detection & check for out-of-order + * packets for unicast packets. + * @pdev: Pointer to pdev maintained by OL + * @peer: Pointer to peer structure maintained by OL + * @tid: TID value passed as part of HTT msg by f/w + * @rx_mpdu_desc: Pointer to Rx Descriptor for the given MPDU + * + * This function + * 1) For Multicast Frames -- does duplicate detection + * A frame is considered duplicate & dropped if it has a seq.number + * which is received twice in succession and with the retry bit set + * in the second case. + * A frame which is older than the last sequence number received + * is not considered duplicate but out-of-order. This function does + * perform out-of-order check for multicast frames, which is in + * keeping with the 802.11 2012 spec section 9.3.2.10 + * 2) For Unicast Frames -- does duplicate detection & out-of-order check + * only for non-aggregation tids. + * + * Return: Returns htt_rx_status_err_replay, if packet needs to be + * dropped, htt_rx_status_ok otherwise. + */ +enum htt_rx_status +ol_rx_seq_num_check(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + uint8_t tid, + void *rx_mpdu_desc) +{ + uint16_t pkt_tid = 0xffff; + uint16_t seq_num = IEEE80211_SEQ_MAX; + bool retry = 0; + + seq_num = htt_rx_mpdu_desc_seq_num(pdev->htt_pdev, rx_mpdu_desc); + + /* For mcast packets, we only the dup-detection, not re-order check */ + + if (adf_os_unlikely(OL_RX_MCAST_TID == tid)) { + + pkt_tid = htt_rx_mpdu_desc_tid(pdev->htt_pdev, rx_mpdu_desc); + + /* Invalid packet TID, expected only for HL */ + /* Pass the packet on */ + if (adf_os_unlikely(pkt_tid >= OL_TXRX_NUM_EXT_TIDS)) + return htt_rx_status_ok; + + retry = htt_rx_mpdu_desc_retry(pdev->htt_pdev, rx_mpdu_desc); + + /* + * At this point, we define frames to be duplicate if they arrive + * "ONLY" in succession with the same sequence number and the last + * one has the retry bit set. For an older frame, we consider that + * as an out of order frame, and hence do not perform the dup-detection + * or out-of-order check for multicast frames as per discussions & spec + * Hence "seq_num <= last_seq_num" check is not necessary. + */ + if (adf_os_unlikely(retry && + (seq_num == peer->tids_mcast_last_seq[pkt_tid]))) {/* drop mcast */ + TXRX_STATS_INCR(pdev, priv.rx.err.msdu_mc_dup_drop); + return htt_rx_status_err_replay; + } else { + /* + * This is a multicast packet likely to be passed on... + * Set the mcast last seq number here + * This is fairly accurate since: + * a) f/w sends multicast as separate PPDU/HTT messages + * b) Mcast packets are not aggregated & hence single + * c) Result of b) is that, flush / release bit is set always + * on the mcast packets, so likely to be immediatedly released. + */ + peer->tids_mcast_last_seq[pkt_tid] = seq_num; + return htt_rx_status_ok; + } + } else + return ol_rx_reorder_seq_num_check(pdev, peer, tid, seq_num); +} + +void +ol_rx_reorder_store( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned idx, + adf_nbuf_t head_msdu, + adf_nbuf_t tail_msdu) +{ + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + + idx &= peer->tids_rx_reorder[tid].win_sz_mask; + rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[idx]; + if (rx_reorder_array_elem->head) { + adf_nbuf_set_next(rx_reorder_array_elem->tail, head_msdu); + } else { + rx_reorder_array_elem->head = head_msdu; + OL_RX_REORDER_MPDU_CNT_INCR(&peer->tids_rx_reorder[tid], 1); + } + rx_reorder_array_elem->tail = tail_msdu; +} + +void +ol_rx_reorder_release( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned idx_start, + unsigned idx_end) +{ + unsigned idx; + unsigned win_sz, win_sz_mask; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + adf_nbuf_t head_msdu; + adf_nbuf_t tail_msdu; + + OL_RX_REORDER_IDX_START_SELF_SELECT(peer, tid, &idx_start); + peer->tids_next_rel_idx[tid] = (u_int16_t)idx_end; /* may get reset below */ + + win_sz = peer->tids_rx_reorder[tid].win_sz; + win_sz_mask = peer->tids_rx_reorder[tid].win_sz_mask; + idx_start &= win_sz_mask; + idx_end &= win_sz_mask; + rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[idx_start]; + + head_msdu = rx_reorder_array_elem->head; + tail_msdu = rx_reorder_array_elem->tail; + rx_reorder_array_elem->head = rx_reorder_array_elem->tail = NULL; + OL_RX_REORDER_PTR_CHECK(head_msdu) { + OL_RX_REORDER_MPDU_CNT_DECR(&peer->tids_rx_reorder[tid], 1); + } + + idx = (idx_start + 1); + OL_RX_REORDER_IDX_WRAP(idx, win_sz, win_sz_mask); + while (idx != idx_end) { + rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[idx]; + OL_RX_REORDER_PTR_CHECK(rx_reorder_array_elem->head) { + OL_RX_REORDER_MPDU_CNT_DECR(&peer->tids_rx_reorder[tid], 1); + OL_RX_REORDER_LIST_APPEND( + head_msdu, tail_msdu, rx_reorder_array_elem); + tail_msdu = rx_reorder_array_elem->tail; + } + rx_reorder_array_elem->head = rx_reorder_array_elem->tail = NULL; + idx++; + OL_RX_REORDER_IDX_WRAP(idx, win_sz, win_sz_mask); + } + OL_RX_REORDER_PTR_CHECK(head_msdu) { + u_int16_t seq_num; + htt_pdev_handle htt_pdev = vdev->pdev->htt_pdev; + + /* + * This logic is not quite correct - the last_seq value should be + * the sequence number of the final MPDU released rather than the + * initial MPDU released. + * However, tracking the sequence number of the first MPDU in the + * released batch works well enough: + * For Peregrine and Rome, the last_seq is checked only for + * non-aggregate cases, where only one MPDU at a time is released. + * For Riva, Pronto, and Northstar, the last_seq is checked to + * filter out late-arriving rx frames, whose sequence number will + * be less than the first MPDU in this release batch. + */ + seq_num = htt_rx_mpdu_desc_seq_num( + htt_pdev, htt_rx_msdu_desc_retrieve(htt_pdev, head_msdu)); + peer->tids_last_seq[tid] = seq_num; + /* rx_opt_proc takes a NULL-terminated list of msdu netbufs */ + adf_nbuf_set_next(tail_msdu, NULL); + peer->rx_opt_proc(vdev, peer, tid, head_msdu); + } + /* + * If the rx reorder timeout is handled by host SW rather than the + * target's rx reorder logic, then stop the timer here. + * (If there are remaining rx holes, then the timer will be restarted.) + */ + OL_RX_REORDER_TIMEOUT_REMOVE(peer, tid); +} + +void +ol_rx_reorder_flush( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned idx_start, + unsigned idx_end, + enum htt_rx_flush_action action) +{ + struct ol_txrx_pdev_t *pdev; + unsigned win_sz; + u_int8_t win_sz_mask; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + adf_nbuf_t head_msdu = NULL; + adf_nbuf_t tail_msdu = NULL; + + pdev = vdev->pdev; + win_sz = peer->tids_rx_reorder[tid].win_sz; + win_sz_mask = peer->tids_rx_reorder[tid].win_sz_mask; + + OL_RX_REORDER_IDX_START_SELF_SELECT(peer, tid, &idx_start); + /* a idx_end value of 0xffff means to flush the entire array */ + if (idx_end == 0xffff) { + idx_end = idx_start; + /* + * The array is being flushed in entirety because the block + * ack window has been shifted to a new position that does not + * overlap with the old position. (Or due to reception of a + * DELBA.) + * Thus, since the block ack window is essentially being reset, + * reset the "next release index". + */ + peer->tids_next_rel_idx[tid] = OL_RX_REORDER_IDX_INIT( + 0/*n/a*/, win_sz, win_sz_mask); + } else { + peer->tids_next_rel_idx[tid] = (u_int16_t)idx_end; + } + + idx_start &= win_sz_mask; + idx_end &= win_sz_mask; + + do { + rx_reorder_array_elem = + &peer->tids_rx_reorder[tid].array[idx_start]; + idx_start = (idx_start + 1); + OL_RX_REORDER_IDX_WRAP(idx_start, win_sz, win_sz_mask); + + if (rx_reorder_array_elem->head) { + OL_RX_REORDER_MPDU_CNT_DECR(&peer->tids_rx_reorder[tid], 1); + if (head_msdu == NULL) { + head_msdu = rx_reorder_array_elem->head; + tail_msdu = rx_reorder_array_elem->tail; + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + continue; + } + adf_nbuf_set_next(tail_msdu, rx_reorder_array_elem->head); + tail_msdu = rx_reorder_array_elem->tail; + rx_reorder_array_elem->head = rx_reorder_array_elem->tail = NULL; + } + } while (idx_start != idx_end); + + ol_rx_defrag_waitlist_remove(peer, tid); + + if (head_msdu) { + u_int16_t seq_num; + htt_pdev_handle htt_pdev = vdev->pdev->htt_pdev; + + seq_num = htt_rx_mpdu_desc_seq_num( + htt_pdev, htt_rx_msdu_desc_retrieve(htt_pdev, head_msdu)); + peer->tids_last_seq[tid] = seq_num; + /* rx_opt_proc takes a NULL-terminated list of msdu netbufs */ + adf_nbuf_set_next(tail_msdu, NULL); + if (action == htt_rx_flush_release) { + peer->rx_opt_proc(vdev, peer, tid, head_msdu); + } else { + do { + adf_nbuf_t next; + next = adf_nbuf_next(head_msdu); + htt_rx_desc_frame_free(pdev->htt_pdev, head_msdu); + head_msdu = next; + } while (head_msdu); + } + } + /* + * If the rx reorder array is empty, then reset the last_seq value - + * it is likely that a BAR or a sequence number shift caused the + * sequence number to jump, so the old last_seq value is not relevant. + */ + if (OL_RX_REORDER_NO_HOLES(&peer->tids_rx_reorder[tid])) { + peer->tids_last_seq[tid] = IEEE80211_SEQ_MAX; /* invalid */ + } + + OL_RX_REORDER_TIMEOUT_REMOVE(peer, tid); +} + +void +ol_rx_reorder_first_hole( + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned *idx_end) +{ + unsigned win_sz, win_sz_mask; + unsigned idx_start = 0, tmp_idx = 0; + + win_sz = peer->tids_rx_reorder[tid].win_sz; + win_sz_mask = peer->tids_rx_reorder[tid].win_sz_mask; + + OL_RX_REORDER_IDX_START_SELF_SELECT(peer, tid, &idx_start); + tmp_idx++; + OL_RX_REORDER_IDX_WRAP(tmp_idx, win_sz, win_sz_mask); + /* bypass the initial hole */ + while (tmp_idx != idx_start && + !peer->tids_rx_reorder[tid].array[tmp_idx].head) + { + tmp_idx++; + OL_RX_REORDER_IDX_WRAP(tmp_idx, win_sz, win_sz_mask); + } + /* bypass the present frames following the initial hole */ + while (tmp_idx != idx_start && + peer->tids_rx_reorder[tid].array[tmp_idx].head) + { + tmp_idx++; + OL_RX_REORDER_IDX_WRAP(tmp_idx, win_sz, win_sz_mask); + } + /* + * idx_end is exclusive rather than inclusive. + * In other words, it is the index of the first slot of the second + * hole, rather than the index of the final present frame following + * the first hole. + */ + *idx_end = tmp_idx; +} + +void +ol_rx_reorder_peer_cleanup( + struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer) +{ + int tid; + for (tid = 0; tid < OL_TXRX_NUM_EXT_TIDS; tid++) { + ol_rx_reorder_flush(vdev, peer, tid, 0, 0, htt_rx_flush_discard); + } + OL_RX_REORDER_TIMEOUT_PEER_CLEANUP(peer); +} + + +/* functions called by HTT */ + +void +ol_rx_addba_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid, + u_int8_t win_sz, + u_int16_t start_seq_num, + u_int8_t failed) +{ + u_int8_t round_pwr2_win_sz; + unsigned array_size; + struct ol_txrx_peer_t *peer; + struct ol_rx_reorder_t *rx_reorder; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer == NULL) { + return; + } + + if (pdev->cfg.host_addba) { + ol_ctrl_rx_addba_complete( + pdev->ctrl_pdev, &peer->mac_addr.raw[0], tid, failed); + } + if (failed) { + return; + } + + peer->tids_last_seq[tid] = IEEE80211_SEQ_MAX; /* invalid */ + rx_reorder = &peer->tids_rx_reorder[tid]; + + TXRX_ASSERT2(win_sz <= 64); + rx_reorder->win_sz = win_sz; + round_pwr2_win_sz = OL_RX_REORDER_ROUND_PWR2(win_sz); + array_size = round_pwr2_win_sz * sizeof(struct ol_rx_reorder_array_elem_t); + rx_reorder->array = adf_os_mem_alloc(pdev->osdev, array_size); + TXRX_ASSERT1(rx_reorder->array); + adf_os_mem_set(rx_reorder->array, 0x0, array_size); + + rx_reorder->win_sz_mask = round_pwr2_win_sz - 1; + rx_reorder->num_mpdus = 0; + + peer->tids_next_rel_idx[tid] = OL_RX_REORDER_IDX_INIT( + start_seq_num, rx_reorder->win_sz, rx_reorder->win_sz_mask); +} + +void +ol_rx_delba_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid) +{ + struct ol_txrx_peer_t *peer; + struct ol_rx_reorder_t *rx_reorder; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer == NULL) { + return; + } + peer->tids_next_rel_idx[tid] = 0xffff; /* invalid value */ + rx_reorder = &peer->tids_rx_reorder[tid]; + + /* check that there really was a block ack agreement */ + TXRX_ASSERT1(rx_reorder->win_sz_mask != 0); + /* + * Deallocate the old rx reorder array. + * The call to ol_rx_reorder_init below + * will reset rx_reorder->array to point to + * the single-element statically-allocated reorder array + * used for non block-ack cases. + */ + if (rx_reorder->array != &rx_reorder->base) { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s, delete reorder array, tid:%d\n", + __func__, tid); + adf_os_mem_free(rx_reorder->array); + } + + /* set up the TID with default parameters (ARQ window size = 1) */ + ol_rx_reorder_init(rx_reorder, tid); +} + +void +ol_rx_flush_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid, + u_int16_t idx_start, + u_int16_t idx_end, + enum htt_rx_flush_action action) +{ + struct ol_txrx_vdev_t *vdev = NULL; + void *rx_desc; + struct ol_txrx_peer_t *peer; + int idx; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer) { + vdev = peer->vdev; + } else { + return; + } + + OL_RX_REORDER_TIMEOUT_MUTEX_LOCK(pdev); + + idx = idx_start & peer->tids_rx_reorder[tid].win_sz_mask; + rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[idx]; + if (rx_reorder_array_elem->head) { + rx_desc = + htt_rx_msdu_desc_retrieve(htt_pdev, rx_reorder_array_elem->head); + if (htt_rx_msdu_is_frag(htt_pdev, rx_desc)) { + ol_rx_reorder_flush_frag(htt_pdev, peer, tid, idx_start); + /* + * Assuming flush message sent seperately for frags + * and for normal frames + */ + OL_RX_REORDER_TIMEOUT_MUTEX_UNLOCK(pdev); + return; + } + } + ol_rx_reorder_flush( + vdev, peer, tid, idx_start, idx_end, action); + /* + * If the rx reorder timeout is handled by host SW, see if there are + * remaining rx holes that require the timer to be restarted. + */ + OL_RX_REORDER_TIMEOUT_UPDATE(peer, tid); + OL_RX_REORDER_TIMEOUT_MUTEX_UNLOCK(pdev); +} + +void +ol_rx_pn_ind_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid, + int seq_num_start, + int seq_num_end, + u_int8_t pn_ie_cnt, + u_int8_t *pn_ie) +{ + struct ol_txrx_vdev_t *vdev = NULL; + void *rx_desc; + struct ol_txrx_peer_t *peer; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + unsigned win_sz_mask; + adf_nbuf_t head_msdu = NULL; + adf_nbuf_t tail_msdu = NULL; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + int seq_num, i=0; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + + if (!peer) { + /* If we can't find a peer send this packet to OCB interface using + OCB self peer */ + if (!ol_txrx_get_ocb_peer(pdev, &peer)) + peer = NULL; + } + + if (peer) { + vdev = peer->vdev; + } else { + return; + } + + adf_os_atomic_set(&peer->fw_pn_check, 1); + /*TODO: Fragmentation case*/ + win_sz_mask = peer->tids_rx_reorder[tid].win_sz_mask; + seq_num_start &= win_sz_mask; + seq_num_end &= win_sz_mask; + seq_num = seq_num_start; + + do { + rx_reorder_array_elem = + &peer->tids_rx_reorder[tid].array[seq_num]; + + if (rx_reorder_array_elem->head) { + if (pn_ie_cnt && seq_num == (int)(pn_ie[i])) { + adf_nbuf_t msdu, next_msdu, mpdu_head, mpdu_tail; + static u_int32_t last_pncheck_print_time = 0; + int log_level; + u_int32_t current_time_ms; + union htt_rx_pn_t pn = {0}; + int index, pn_len; + + mpdu_head = msdu = rx_reorder_array_elem->head; + mpdu_tail = rx_reorder_array_elem->tail; + + pn_ie_cnt--; + i++; + rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, msdu); + index = htt_rx_msdu_is_wlan_mcast(pdev->htt_pdev, rx_desc) ? + txrx_sec_mcast : txrx_sec_ucast; + pn_len = pdev->rx_pn[peer->security[index].sec_type].len; + htt_rx_mpdu_desc_pn(htt_pdev, rx_desc, &pn, pn_len); + + current_time_ms = adf_os_ticks_to_msecs(adf_os_ticks()); + if (TXRX_PN_CHECK_FAILURE_PRINT_PERIOD_MS < + (current_time_ms - last_pncheck_print_time)) { + last_pncheck_print_time = current_time_ms; + log_level = TXRX_PRINT_LEVEL_WARN; + } + else { + log_level = TXRX_PRINT_LEVEL_INFO2; + } + TXRX_PRINT(log_level, + "Tgt PN check failed - TID %d, peer %p " + "(%02x:%02x:%02x:%02x:%02x:%02x)\n" + " PN (u64 x2)= 0x%08llx %08llx (LSBs = %lld)\n" + " new seq num = %d\n", + tid, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5], + pn.pn128[1], + pn.pn128[0], + pn.pn128[0] & 0xffffffffffffULL, + htt_rx_mpdu_desc_seq_num(htt_pdev, rx_desc)); + ol_rx_err( + pdev->ctrl_pdev, + vdev->vdev_id, peer->mac_addr.raw, tid, + htt_rx_mpdu_desc_tsf32(htt_pdev, rx_desc), + OL_RX_ERR_PN, mpdu_head, NULL, 0); + + /* free all MSDUs within this MPDU */ + do { + next_msdu = adf_nbuf_next(msdu); + htt_rx_desc_frame_free(htt_pdev, msdu); + if (msdu == mpdu_tail) { + break; + } else { + msdu = next_msdu; + } + }while(1); + + } else { + if (head_msdu == NULL) { + head_msdu = rx_reorder_array_elem->head; + tail_msdu = rx_reorder_array_elem->tail; + } else { + adf_nbuf_set_next(tail_msdu, rx_reorder_array_elem->head); + tail_msdu = rx_reorder_array_elem->tail; + } + } + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + } + seq_num = (seq_num + 1) & win_sz_mask; + } while (seq_num != seq_num_end); + + if (head_msdu) { + /* rx_opt_proc takes a NULL-terminated list of msdu netbufs */ + adf_nbuf_set_next(tail_msdu, NULL); + peer->rx_opt_proc(vdev, peer, tid, head_msdu); + } +} + +#if defined(ENABLE_RX_REORDER_TRACE) + +A_STATUS +ol_rx_reorder_trace_attach(ol_txrx_pdev_handle pdev) +{ + int num_elems; + + num_elems = 1 << TXRX_RX_REORDER_TRACE_SIZE_LOG2; + pdev->rx_reorder_trace.idx = 0; + pdev->rx_reorder_trace.cnt = 0; + pdev->rx_reorder_trace.mask = num_elems - 1; + pdev->rx_reorder_trace.data = adf_os_mem_alloc( + pdev->osdev, sizeof(*pdev->rx_reorder_trace.data) * num_elems); + if (! pdev->rx_reorder_trace.data) { + return A_ERROR; + } + while (--num_elems >= 0) { + pdev->rx_reorder_trace.data[num_elems].seq_num = 0xffff; + } + + return A_OK; +} + +void +ol_rx_reorder_trace_detach(ol_txrx_pdev_handle pdev) +{ + adf_os_mem_free(pdev->rx_reorder_trace.data); +} + +void +ol_rx_reorder_trace_add( + ol_txrx_pdev_handle pdev, + u_int8_t tid, + u_int16_t reorder_idx, + u_int16_t seq_num, + int num_mpdus) +{ + u_int32_t idx = pdev->rx_reorder_trace.idx; + + pdev->rx_reorder_trace.data[idx].tid = tid; + pdev->rx_reorder_trace.data[idx].reorder_idx = reorder_idx; + pdev->rx_reorder_trace.data[idx].seq_num = seq_num; + pdev->rx_reorder_trace.data[idx].num_mpdus = num_mpdus; + pdev->rx_reorder_trace.cnt++; + idx++; + pdev->rx_reorder_trace.idx = idx & pdev->rx_reorder_trace.mask; +} + +void +ol_rx_reorder_trace_display(ol_txrx_pdev_handle pdev, int just_once, int limit) +{ + static int print_count = 0; + u_int32_t i, start, end; + u_int64_t cnt; + int elems; + + if (print_count != 0 && just_once) { + return; + } + print_count++; + + end = pdev->rx_reorder_trace.idx; + if (pdev->rx_reorder_trace.data[end].seq_num == 0xffff) { + /* trace log has not yet wrapped around - start at the top */ + start = 0; + cnt = 0; + } else { + start = end; + cnt = pdev->rx_reorder_trace.cnt - (pdev->rx_reorder_trace.mask + 1); + } + elems = (end - 1 - start) & pdev->rx_reorder_trace.mask; + if (limit > 0 && elems > limit) { + int delta; + delta = elems - limit; + start += delta; + start &= pdev->rx_reorder_trace.mask; + cnt += delta; + } + + i = start; + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " log array seq\n"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " count idx tid idx num (LSBs)\n"); + do { + u_int16_t seq_num, reorder_idx; + seq_num = pdev->rx_reorder_trace.data[i].seq_num; + reorder_idx = pdev->rx_reorder_trace.data[i].reorder_idx; + if (seq_num < (1 << 14)) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " %6lld %4d %3d %4d %4d (%d)\n", + cnt, i, pdev->rx_reorder_trace.data[i].tid, + reorder_idx, seq_num, seq_num & 63); + } else { + int err = TXRX_SEQ_NUM_ERR(seq_num); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " %6lld %4d err %d (%d MPDUs)\n", + cnt, i, err, pdev->rx_reorder_trace.data[i].num_mpdus); + } + cnt++; + i++; + i &= pdev->rx_reorder_trace.mask; + } while (i != end); +} + +#endif /* ENABLE_RX_REORDER_TRACE */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.h new file mode 100644 index 000000000000..df0faf0e4910 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_RX_REORDER__H_ +#define _OL_RX_REORDER__H_ + +#include /* adf_nbuf_t, etc. */ + +#include /* ol_txrx_peer_t, etc. */ + +#include /* ol_rx_reorder_t */ + +void +ol_rx_reorder_store( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned reorder_array_index, + adf_nbuf_t head_msdu, + adf_nbuf_t tail_msdu); + +void +ol_rx_reorder_release( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned seq_num_start, + unsigned seq_num_end); + +void +ol_rx_reorder_flush( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned seq_num_start, + unsigned seq_num_end, + enum htt_rx_flush_action action); + +/** + * @brief - find end of first range of present MPDUs after the initial rx hole + * @param[in] peer - which sender's data is being checked + * @param[in] tid - which type of data is being checked + * @param[out] idx_end - the reorder array index holding the last MPDU in the + * range of in-order MPDUs that following the initial hole. + * Note that this is the index of the last in-order MPDU following the + * first hole, rather than the starting index of the second hole. + */ +void +ol_rx_reorder_first_hole( + struct ol_txrx_peer_t *peer, + unsigned tid, + unsigned *idx_end); + +void +ol_rx_reorder_peer_cleanup( + struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer); + +void +ol_rx_reorder_init(struct ol_rx_reorder_t *rx_reorder, u_int8_t tid); + +enum htt_rx_status +ol_rx_seq_num_check( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + uint8_t tid, + void *rx_mpdu_desc); + +/* + * Peregrine and Rome: do sequence number checking in the host + * for peer-TIDs without aggregation enabled + */ +#define OL_RX_SEQ_NUM_CHECK(pdev, peer, tid, rx_mpdu_desc) \ + (pdev->rx.flags.dup_check && peer->tids_rx_reorder[tid].win_sz_mask == 0) ? \ + ol_rx_seq_num_check( \ + pdev, peer, tid, \ + rx_mpdu_desc) : \ + htt_rx_status_ok + + + +#endif /* _OL_RX_REORDER__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.c new file mode 100644 index 000000000000..a1deb5ccb1e2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=== header file includes ===*/ +/* generic utilities */ +#include /* adf_nbuf_t, etc. */ +#include +#include + +/* datapath internal interfaces */ +#include /* ol_txrx_pdev_t, etc. */ +#include /* TXRX_ASSERT, etc. */ +#include /* ol_rx_reorder_flush, etc. */ + +#ifdef QCA_SUPPORT_OL_RX_REORDER_TIMEOUT + +void +ol_rx_reorder_timeout_remove(struct ol_txrx_peer_t *peer, unsigned tid) +{ + struct ol_txrx_pdev_t *pdev; + struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac; + struct ol_rx_reorder_timeout_list_elem_t *list_elem; + int ac; + + pdev = peer->vdev->pdev; + ac = TXRX_TID_TO_WMM_AC(tid); + rx_reorder_timeout_ac = &pdev->rx.reorder_timeout.access_cats[ac]; + list_elem = &peer->tids_rx_reorder[tid].timeout; + if (!list_elem->active) { + /* this element has already been removed */ + return; + } + list_elem->active = 0; + TAILQ_REMOVE( + &rx_reorder_timeout_ac->virtual_timer_list, list_elem, + reorder_timeout_list_elem); +} + +static void +ol_rx_reorder_timeout_start( + struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac, + u_int32_t time_now_ms) +{ + u_int32_t duration_ms; + struct ol_rx_reorder_timeout_list_elem_t *list_elem; + + list_elem = TAILQ_FIRST(&rx_reorder_timeout_ac->virtual_timer_list); + + duration_ms = list_elem->timestamp_ms - time_now_ms; + adf_os_timer_start(&rx_reorder_timeout_ac->timer, duration_ms); +} + +static inline void +ol_rx_reorder_timeout_add(struct ol_txrx_peer_t *peer, u_int8_t tid) +{ + u_int32_t time_now_ms; + struct ol_txrx_pdev_t *pdev; + struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac; + struct ol_rx_reorder_timeout_list_elem_t *list_elem; + int ac; + int start; + + pdev = peer->vdev->pdev; + ac = TXRX_TID_TO_WMM_AC(tid); + rx_reorder_timeout_ac = &pdev->rx.reorder_timeout.access_cats[ac]; + list_elem = &peer->tids_rx_reorder[tid].timeout; + + list_elem->active = 1; + list_elem->peer = peer; + list_elem->tid = tid; + + /* set the expiration timestamp */ + time_now_ms = adf_os_ticks_to_msecs(adf_os_ticks()); + list_elem->timestamp_ms = time_now_ms + rx_reorder_timeout_ac->duration_ms; + + /* add to the queue */ + start = TAILQ_EMPTY(&rx_reorder_timeout_ac->virtual_timer_list); + TAILQ_INSERT_TAIL( + &rx_reorder_timeout_ac->virtual_timer_list, + list_elem, reorder_timeout_list_elem); + if (start) { + ol_rx_reorder_timeout_start(rx_reorder_timeout_ac, time_now_ms); + } +} + +void +ol_rx_reorder_timeout_update(struct ol_txrx_peer_t *peer, u_int8_t tid) +{ + if (!peer) return; + + /* + * If there are no holes, i.e. no queued frames, + * then timeout doesn't apply. + */ + if (peer->tids_rx_reorder[tid].num_mpdus == 0) return; + + /* + * If the virtual timer for this peer-TID is already running, + * then leave it. + */ + if (peer->tids_rx_reorder[tid].timeout.active) return; + + ol_rx_reorder_timeout_add(peer, tid); +} + +static void +ol_rx_reorder_timeout(void *arg) +{ + struct ol_txrx_pdev_t *pdev; + struct ol_rx_reorder_timeout_list_elem_t *list_elem, *tmp; + u_int32_t time_now_ms; + struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac; + + rx_reorder_timeout_ac = (struct ol_tx_reorder_cat_timeout_t *) arg; + time_now_ms = adf_os_ticks_to_msecs(adf_os_ticks()); + + pdev = rx_reorder_timeout_ac->pdev; + adf_os_spin_lock(&pdev->rx.mutex); +// TODO: conditionally take mutex lock during regular rx + TAILQ_FOREACH_SAFE( + list_elem, &rx_reorder_timeout_ac->virtual_timer_list, + reorder_timeout_list_elem, tmp) + { + unsigned idx_start, idx_end; + struct ol_txrx_peer_t *peer; + + if (list_elem->timestamp_ms > time_now_ms) { + break; /* time has not expired yet for this element */ + } + + list_elem->active = 0; + /* remove the expired element from the list */ + TAILQ_REMOVE( + &rx_reorder_timeout_ac->virtual_timer_list, list_elem, + reorder_timeout_list_elem); + + peer = list_elem->peer; + + idx_start = 0xffff; /* start from next_rel_idx */ + ol_rx_reorder_first_hole(peer, list_elem->tid, &idx_end); + ol_rx_reorder_flush( + peer->vdev, + peer, + list_elem->tid, + idx_start, + idx_end, + htt_rx_flush_release); + } + /* restart the timer if unexpired elements are left in the list */ + if (!TAILQ_EMPTY(&rx_reorder_timeout_ac->virtual_timer_list)) { + ol_rx_reorder_timeout_start(rx_reorder_timeout_ac, time_now_ms); + } + adf_os_spin_unlock(&pdev->rx.mutex); +} + +void +ol_rx_reorder_timeout_init(struct ol_txrx_pdev_t *pdev) +{ + int i; + + for (i = 0; i < ARRAY_LEN(pdev->rx.reorder_timeout.access_cats); i++) { + struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac; + rx_reorder_timeout_ac = &pdev->rx.reorder_timeout.access_cats[i]; + /* init the per-AC timers */ + adf_os_timer_init( + pdev->osdev, &rx_reorder_timeout_ac->timer, + ol_rx_reorder_timeout, rx_reorder_timeout_ac, ADF_DEFERRABLE_TIMER); + /* init the virtual timer list */ + TAILQ_INIT(&rx_reorder_timeout_ac->virtual_timer_list); + rx_reorder_timeout_ac->pdev = pdev; + } + pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_VO].duration_ms = 40; + pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_VI].duration_ms = 100; + pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_BE].duration_ms = 100; + pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_BK].duration_ms = 100; +} + +void +ol_rx_reorder_timeout_peer_cleanup(struct ol_txrx_peer_t *peer) +{ + int tid; + + for (tid = 0; tid < OL_TXRX_NUM_EXT_TIDS; tid++) { + if (peer->tids_rx_reorder[tid].timeout.active) { + ol_rx_reorder_timeout_remove(peer, tid); + } + } +} + +void +ol_rx_reorder_timeout_cleanup(struct ol_txrx_pdev_t *pdev) +{ + int i; + + for (i = 0; i < ARRAY_LEN(pdev->rx.reorder_timeout.access_cats); i++) { + struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac; + rx_reorder_timeout_ac = &pdev->rx.reorder_timeout.access_cats[i]; + adf_os_timer_cancel(&rx_reorder_timeout_ac->timer); + adf_os_timer_free(&rx_reorder_timeout_ac->timer); + } +} + +#endif /* QCA_SUPPORT_OL_RX_REORDER_TIMEOUT */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.h new file mode 100644 index 000000000000..1b9f34735bfb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_rx_reorder_timeout.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_RX_REORDER_TIMEOUT__H_ +#define _OL_RX_REORDER_TIMEOUT__H_ + +#include /* ol_txrx_pdev_t, etc. */ + +#ifdef QCA_SUPPORT_OL_RX_REORDER_TIMEOUT + +void +ol_rx_reorder_timeout_init(struct ol_txrx_pdev_t *pdev); +void +ol_rx_reorder_timeout_cleanup(struct ol_txrx_pdev_t *pdev); +void +ol_rx_reorder_timeout_remove(struct ol_txrx_peer_t *peer, unsigned tid); +void +ol_rx_reorder_timeout_update(struct ol_txrx_peer_t *peer, u_int8_t tid); +void +ol_rx_reorder_timeout_peer_cleanup(struct ol_txrx_peer_t *peer); + +#define OL_RX_REORDER_TIMEOUT_INIT ol_rx_reorder_timeout_init +#define OL_RX_REORDER_TIMEOUT_PEER_CLEANUP ol_rx_reorder_timeout_peer_cleanup +#define OL_RX_REORDER_TIMEOUT_CLEANUP ol_rx_reorder_timeout_cleanup +#define OL_RX_REORDER_TIMEOUT_REMOVE ol_rx_reorder_timeout_remove +#define OL_RX_REORDER_TIMEOUT_UPDATE ol_rx_reorder_timeout_update +#define OL_RX_REORDER_TIMEOUT_PEER_TID_INIT(peer, tid) \ + (peer)->tids_rx_reorder[(tid)].timeout.active = 0 +#define OL_RX_REORDER_TIMEOUT_MUTEX_LOCK(pdev) \ + adf_os_spin_lock(&(pdev)->rx.mutex) +#define OL_RX_REORDER_TIMEOUT_MUTEX_UNLOCK(pdev) \ + adf_os_spin_unlock(&(pdev)->rx.mutex) + +#else + +#define OL_RX_REORDER_TIMEOUT_INIT(pdev) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_PEER_CLEANUP(peer) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_CLEANUP(pdev) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_REMOVE(peer, tid) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_UPDATE(peer, tid) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_PEER_TID_INIT(peer, tid) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_MUTEX_LOCK(pdev) /* no-op */ +#define OL_RX_REORDER_TIMEOUT_MUTEX_UNLOCK(pdev) /* no-op */ + +#endif /* QCA_SUPPORT_OL_RX_REORDER_TIMEOUT */ + +#endif /* _OL_RX_REORDER_TIMEOUT__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.c new file mode 100644 index 000000000000..ad29d3245b7e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.c @@ -0,0 +1,954 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* OS abstraction libraries */ +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_atomic_read, etc. */ +#include /* adf_os_unlikely */ + +/* APIs for other modules */ +#include /* HTT_TX_EXT_TID_MGMT */ +#include /* htt_tx_desc_tid */ +#include /* ol_txrx_vdev_handle */ +#include /* ol_txrx_sync */ + +/* internal header files relevant for all systems */ +#include /* TXRX_ASSERT1 */ +#include /* pdev stats */ +#include /* ol_tx_desc */ +#include /* ol_tx_send */ +#include + +/* internal header files relevant only for HL systems */ +#include /* ol_tx_classify, ol_tx_classify_mgmt */ +#include /* ol_tx_enqueue */ +#include /* ol_tx_sched */ + +/* internal header files relevant only for specific systems (Pronto) */ +#include /* OL_TX_ENCAP, etc */ + +#define ol_tx_prepare_ll(tx_desc, vdev, msdu, msdu_info) \ + do { \ + struct ol_txrx_pdev_t *pdev = vdev->pdev; \ + /* + * The TXRX module doesn't accept tx frames unless the target has + * enough descriptors for them. + * For LL, the TXRX descriptor pool is sized to match the target's + * descriptor pool. Hence, if the descriptor allocation in TXRX + * succeeds, that guarantees that the target has room to accept + * the new tx frame. + */ \ + (msdu_info)->htt.info.frame_type = pdev->htt_pkt_type; \ + tx_desc = ol_tx_desc_ll(pdev, vdev, msdu, msdu_info); \ + if (adf_os_unlikely(! tx_desc)) { \ + TXRX_STATS_MSDU_LIST_INCR( \ + pdev, tx.dropped.host_reject, msdu); \ + return msdu; /* the list of unaccepted MSDUs */ \ + } \ + } while (0) + +adf_nbuf_t +ol_tx_ll(ol_txrx_vdev_handle vdev, adf_nbuf_t msdu_list) +{ + adf_nbuf_t msdu = msdu_list; + struct ol_txrx_msdu_info_t msdu_info; + + msdu_info.htt.info.l2_hdr_type = vdev->pdev->htt_pkt_type; + msdu_info.htt.action.tx_comp_req = 0; + /* + * The msdu_list variable could be used instead of the msdu var, + * but just to clarify which operations are done on a single MSDU + * vs. a list of MSDUs, use a distinct variable for single MSDUs + * within the list. + */ + while (msdu) { + adf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + + msdu_info.htt.info.ext_tid = adf_nbuf_get_tid(msdu); + msdu_info.peer = NULL; + + ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info); + + /* + * If debug display is enabled, show the meta-data being + * downloaded to the target via the HTT tx descriptor. + */ + htt_tx_desc_display(tx_desc->htt_tx_desc); + /* + * The netbuf may get linked into a different list inside the + * ol_tx_send function, so store the next pointer before the + * tx_send call. + */ + next = adf_nbuf_next(msdu); + ol_tx_send(vdev->pdev, tx_desc, msdu); + msdu = next; + } + return NULL; /* all MSDUs were accepted */ +} + +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ + +#define OL_TX_VDEV_PAUSE_QUEUE_SEND_MARGIN 400 +#define OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS 5 + +/** + * ol_tx_vdev_ll_pause_start_timer() - Start ll-q pause timer for specific virtual device + * @vdev: the virtual device + * + * When system comes out of suspend, it is necessary to start the timer + * which will ensure to pull out all the queued packets after expiry. + * This function restarts the ll-pause timer, for the specific vdev device. + * + * + * Return: None + */ +void +ol_tx_vdev_ll_pause_start_timer(struct ol_txrx_vdev_t *vdev) +{ + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.txq.depth) { + adf_os_timer_cancel(&vdev->ll_pause.timer); + adf_os_timer_start(&vdev->ll_pause.timer, + OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS); + } + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); +} + +static void +ol_tx_vdev_ll_pause_queue_send_base(struct ol_txrx_vdev_t *vdev) +{ + int max_to_accept; + + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.paused_reason) { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + return; + } + + /* + * Send as much of the backlog as possible, but leave some margin + * of unallocated tx descriptors that can be used for new frames + * being transmitted by other vdevs. + * Ideally there would be a scheduler, which would not only leave + * some margin for new frames for other vdevs, but also would + * fairly apportion the tx descriptors between multiple vdevs that + * have backlogs in their pause queues. + * However, the fairness benefit of having a scheduler for frames + * from multiple vdev's pause queues is not sufficient to outweigh + * the extra complexity. + */ + max_to_accept = + vdev->pdev->tx_desc.num_free - OL_TX_VDEV_PAUSE_QUEUE_SEND_MARGIN; + while (max_to_accept > 0 && vdev->ll_pause.txq.depth) { + adf_nbuf_t tx_msdu; + max_to_accept--; + vdev->ll_pause.txq.depth--; + tx_msdu = vdev->ll_pause.txq.head; + if (tx_msdu) { + vdev->ll_pause.txq.head = adf_nbuf_next(tx_msdu); + if (NULL == vdev->ll_pause.txq.head) { + vdev->ll_pause.txq.tail = NULL; + } + adf_nbuf_set_next(tx_msdu, NULL); + tx_msdu = ol_tx_ll(vdev, tx_msdu); + /* + * It is unexpected that ol_tx_ll would reject the frame, + * since we checked that there's room for it, though there's + * an infinitesimal possibility that between the time we checked + * the room available and now, a concurrent batch of tx frames + * used up all the room. + * For simplicity, just drop the frame. + */ + if (tx_msdu) { + adf_nbuf_unmap(vdev->pdev->osdev, tx_msdu, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_tx_free(tx_msdu, 1 /* error */); + } + } + } + if (vdev->ll_pause.txq.depth) { + adf_os_timer_cancel(&vdev->ll_pause.timer); + adf_os_timer_start( + &vdev->ll_pause.timer, OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS); + vdev->ll_pause.is_q_timer_on = TRUE; + if (vdev->ll_pause.txq.depth >= vdev->ll_pause.max_q_depth) { + vdev->ll_pause.q_overflow_cnt++; + } + } + + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); +} + +static adf_nbuf_t +ol_tx_vdev_pause_queue_append( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t msdu_list, + u_int8_t start_timer) +{ + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + + while (msdu_list && + vdev->ll_pause.txq.depth < vdev->ll_pause.max_q_depth) + { + adf_nbuf_t next = adf_nbuf_next(msdu_list); + + vdev->ll_pause.txq.depth++; + if (!vdev->ll_pause.txq.head) { + vdev->ll_pause.txq.head = msdu_list; + vdev->ll_pause.txq.tail = msdu_list; + } else { + adf_nbuf_set_next(vdev->ll_pause.txq.tail, msdu_list); + } + vdev->ll_pause.txq.tail = msdu_list; + + msdu_list = next; + } + if (vdev->ll_pause.txq.tail) { + adf_nbuf_set_next(vdev->ll_pause.txq.tail, NULL); + } + + adf_os_timer_cancel(&vdev->ll_pause.timer); + if (start_timer) { + adf_os_timer_start( + &vdev->ll_pause.timer, OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS); + vdev->ll_pause.is_q_timer_on = TRUE; + } + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + + return msdu_list; +} + +/* + * Store up the tx frame in the vdev's tx queue if the vdev is paused. + * If there are too many frames in the tx queue, reject it. + */ +adf_nbuf_t +ol_tx_ll_queue(ol_txrx_vdev_handle vdev, adf_nbuf_t msdu_list) +{ + u_int16_t eth_type; + u_int32_t paused_reason; + + if (msdu_list == NULL) + return NULL; + + paused_reason = vdev->ll_pause.paused_reason; + if (paused_reason) { + if (adf_os_unlikely((paused_reason & + OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED) == paused_reason)) { + eth_type = (((struct ethernet_hdr_t *) + adf_nbuf_data(msdu_list))->ethertype[0] << 8) | + (((struct ethernet_hdr_t *) + adf_nbuf_data(msdu_list))->ethertype[1]); + if (ETHERTYPE_IS_EAPOL_WAPI(eth_type)) { + msdu_list = ol_tx_ll(vdev, msdu_list); + return msdu_list; + } + } + if (paused_reason & OL_TXQ_PAUSE_REASON_VDEV_SUSPEND) + msdu_list = ol_tx_vdev_pause_queue_append(vdev, msdu_list, 0); + else + msdu_list = ol_tx_vdev_pause_queue_append(vdev, msdu_list, 1); + } else { + if (vdev->ll_pause.txq.depth > 0 || + vdev->pdev->tx_throttle.current_throttle_level != + THROTTLE_LEVEL_0) { + /* not paused, but there is a backlog of frms from a prior pause or + throttle off phase */ + msdu_list = ol_tx_vdev_pause_queue_append(vdev, msdu_list, 0); + /* if throttle is disabled or phase is "on" send the frame */ + if (vdev->pdev->tx_throttle.current_throttle_level == + THROTTLE_LEVEL_0 || + vdev->pdev->tx_throttle.current_throttle_phase == + THROTTLE_PHASE_ON) { + /* send as many frames as possible from the vdevs backlog */ + ol_tx_vdev_ll_pause_queue_send_base(vdev); + } + } else { + /* not paused, no throttle and no backlog - send the new frames */ + msdu_list = ol_tx_ll(vdev, msdu_list); + } + } + return msdu_list; +} + +/* + * Run through the transmit queues for all the vdevs and send the pending frames + */ +void +ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev) +{ + int max_to_send; /* tracks how many frames have been sent*/ + adf_nbuf_t tx_msdu; + struct ol_txrx_vdev_t *vdev = NULL; + u_int8_t more; + + if (NULL == pdev) { + return; + } + + if (pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_OFF) { + return; + } + + /* ensure that we send no more than tx_threshold frames at once */ + max_to_send = pdev->tx_throttle.tx_threshold; + + /* round robin through the vdev queues for the given pdev */ + + /* Potential improvement: download several frames from the same vdev at a + time, since it is more likely that those frames could be aggregated + together, remember which vdev was serviced last, so the next call to + this function can resume the round-robin traversing where the current + invocation left off*/ + do { + more = 0; + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.txq.depth) { + if (vdev->ll_pause.paused_reason) { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + continue; + } + + tx_msdu = vdev->ll_pause.txq.head; + if (NULL == tx_msdu) { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + continue; + } + + max_to_send--; + vdev->ll_pause.txq.depth--; + + vdev->ll_pause.txq.head = adf_nbuf_next(tx_msdu); + + if (NULL == vdev->ll_pause.txq.head) { + vdev->ll_pause.txq.tail = NULL; + } + adf_nbuf_set_next(tx_msdu, NULL); + tx_msdu = ol_tx_ll(vdev, tx_msdu); + /* + * It is unexpected that ol_tx_ll would reject the frame, + * since we checked that there's room for it, though there's + * an infinitesimal possibility that between the time we checked + * the room available and now, a concurrent batch of tx frames + * used up all the room. + * For simplicity, just drop the frame. + */ + if (tx_msdu) { + adf_nbuf_unmap(pdev->osdev, tx_msdu, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_tx_free(tx_msdu, 1 /* error */); + } + } + /*check if there are more msdus to transmit*/ + if (vdev->ll_pause.txq.depth) { + more = 1; + } + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + } + } while(more && max_to_send); + + vdev = NULL; + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.txq.depth) { + adf_os_timer_cancel(&pdev->tx_throttle.tx_timer); + adf_os_timer_start(&pdev->tx_throttle.tx_timer, + OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS); + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + return; + } + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + } +} +#endif + +void ol_tx_vdev_ll_pause_queue_send(void *context) +{ +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ + struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *) context; + + if (vdev->pdev->tx_throttle.current_throttle_level != THROTTLE_LEVEL_0 && + vdev->pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_OFF) { + return; + } + + ol_tx_vdev_ll_pause_queue_send_base(vdev); +#endif +} + +static inline int +OL_TXRX_TX_IS_RAW(enum ol_tx_spec tx_spec) +{ + return + tx_spec & + (ol_tx_spec_raw | + ol_tx_spec_no_aggr | + ol_tx_spec_no_encrypt); +} + +static inline u_int8_t +OL_TXRX_TX_RAW_SUBTYPE(enum ol_tx_spec tx_spec) +{ + u_int8_t sub_type = 0x1; /* 802.11 MAC header present */ + + if (tx_spec & ol_tx_spec_no_aggr) { + sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_AGGR_S; + } + if (tx_spec & ol_tx_spec_no_encrypt) { + sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S; + } + if (tx_spec & ol_tx_spec_nwifi_no_encrypt) { + sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S; + } + return sub_type; +} + +adf_nbuf_t +ol_tx_non_std_ll( + ol_txrx_vdev_handle vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list) +{ + adf_nbuf_t msdu = msdu_list; + htt_pdev_handle htt_pdev = vdev->pdev->htt_pdev; + struct ol_txrx_msdu_info_t msdu_info; + + msdu_info.htt.info.l2_hdr_type = vdev->pdev->htt_pkt_type; + msdu_info.htt.action.tx_comp_req = 0; + + /* + * The msdu_list variable could be used instead of the msdu var, + * but just to clarify which operations are done on a single MSDU + * vs. a list of MSDUs, use a distinct variable for single MSDUs + * within the list. + */ + while (msdu) { + adf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + + msdu_info.htt.info.ext_tid = adf_nbuf_get_tid(msdu); + msdu_info.peer = NULL; + + ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info); + + /* + * The netbuf may get linked into a different list inside the + * ol_tx_send function, so store the next pointer before the + * tx_send call. + */ + next = adf_nbuf_next(msdu); + + if (tx_spec != ol_tx_spec_std) { + if (tx_spec & ol_tx_spec_no_free) { + tx_desc->pkt_type = ol_tx_frm_no_free; + } else if (tx_spec & ol_tx_spec_tso) { + tx_desc->pkt_type = ol_tx_frm_tso; + } else if (tx_spec & ol_tx_spec_nwifi_no_encrypt) { + u_int8_t sub_type = OL_TXRX_TX_RAW_SUBTYPE(tx_spec); + htt_tx_desc_type( + htt_pdev, tx_desc->htt_tx_desc, + htt_pkt_type_native_wifi, sub_type); + } else if (OL_TXRX_TX_IS_RAW(tx_spec)) { + /* different types of raw frames */ + u_int8_t sub_type = OL_TXRX_TX_RAW_SUBTYPE(tx_spec); + htt_tx_desc_type( + htt_pdev, tx_desc->htt_tx_desc, + htt_pkt_type_raw, sub_type); + } + } + /* + * If debug display is enabled, show the meta-data being + * downloaded to the target via the HTT tx descriptor. + */ + htt_tx_desc_display(tx_desc->htt_tx_desc); + ol_tx_send(vdev->pdev, tx_desc, msdu); + msdu = next; + } + return NULL; /* all MSDUs were accepted */ +} + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP +#define OL_TX_ENCAP_WRAPPER(pdev, vdev, tx_desc, msdu, tx_msdu_info) \ + do { \ + if (OL_TX_ENCAP(vdev, tx_desc, msdu, &tx_msdu_info) != A_OK) { \ + adf_os_atomic_inc(&pdev->tx_queue.rsrc_cnt); \ + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); \ + if (tx_msdu_info.peer) { \ + /* remove the peer reference added above */ \ + ol_txrx_peer_unref_delete(tx_msdu_info.peer); \ + } \ + goto MSDU_LOOP_BOTTOM; \ + } \ + } while (0) +#else +#define OL_TX_ENCAP_WRAPPER(pdev, vdev, tx_desc, msdu, tx_msdu_info) /* no-op */ +#endif + +/* tx filtering is handled within the target FW */ +#define TX_FILTER_CHECK(tx_msdu_info) 0 /* don't filter */ + + +/** + * parse_ocb_tx_header() - Function to check for OCB + * TX control header on a packet and extract it if present + * + * @msdu: Pointer to OS packet (adf_nbuf_t) + */ +#define OCB_HEADER_VERSION 1 +static bool parse_ocb_tx_header(adf_nbuf_t msdu, + struct ocb_tx_ctrl_hdr_t *tx_ctrl) +{ + struct ether_header *eth_hdr_p; + struct ocb_tx_ctrl_hdr_t *tx_ctrl_hdr; + + /* Check if TX control header is present */ + eth_hdr_p = (struct ether_header *) adf_nbuf_data(msdu); + if (eth_hdr_p->ether_type != adf_os_htons(ETHERTYPE_OCB_TX)) + /* TX control header is not present. Nothing to do.. */ + return true; + + /* Remove the ethernet header */ + adf_nbuf_pull_head(msdu, sizeof(struct ether_header)); + + /* Parse the TX control header */ + tx_ctrl_hdr = (struct ocb_tx_ctrl_hdr_t*) adf_nbuf_data(msdu); + + if (tx_ctrl_hdr->version == OCB_HEADER_VERSION) { + if (tx_ctrl) + adf_os_mem_copy(tx_ctrl, tx_ctrl_hdr, sizeof(*tx_ctrl_hdr)); + } else { + /* The TX control header is invalid. */ + return false; + } + + /* Remove the TX control header */ + adf_nbuf_pull_head(msdu, tx_ctrl_hdr->length); + return true; +} + +static inline adf_nbuf_t +ol_tx_hl_base( + ol_txrx_vdev_handle vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list, + int tx_comp_req) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + adf_nbuf_t msdu = msdu_list; + struct ol_txrx_msdu_info_t tx_msdu_info; + struct ocb_tx_ctrl_hdr_t tx_ctrl; + + htt_pdev_handle htt_pdev = pdev->htt_pdev; + tx_msdu_info.peer = NULL; + + /* + * The msdu_list variable could be used instead of the msdu var, + * but just to clarify which operations are done on a single MSDU + * vs. a list of MSDUs, use a distinct variable for single MSDUs + * within the list. + */ + while (msdu) { + adf_nbuf_t next; + struct ol_tx_frms_queue_t *txq; + struct ol_tx_desc_t *tx_desc = NULL; + + adf_os_mem_zero(&tx_ctrl, sizeof(tx_ctrl)); + + /* + * The netbuf will get stored into a (peer-TID) tx queue list + * inside the ol_tx_classify_store function or else dropped, + * so store the next pointer immediately. + */ + next = adf_nbuf_next(msdu); + +#if defined(CONFIG_TX_DESC_HI_PRIO_RESERVE) + if (adf_os_atomic_read(&pdev->tx_queue.rsrc_cnt) > + TXRX_HL_TX_DESC_HI_PRIO_RESERVED) { + tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, &tx_msdu_info); + } else if ((adf_nbuf_is_dhcp_pkt(msdu) == A_STATUS_OK) + || (adf_nbuf_is_eapol_pkt(msdu) == A_STATUS_OK)) { + tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, &tx_msdu_info); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Provided tx descriptor from reserve pool for DHCP/EAPOL\n"); + } +#else + tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, &tx_msdu_info); +#endif + if (! tx_desc) { + /* + * If we're out of tx descs, there's no need to try to allocate + * tx descs for the remaining MSDUs. + */ + TXRX_STATS_MSDU_LIST_INCR(pdev, tx.dropped.host_reject, msdu); + return msdu; /* the list of unaccepted MSDUs */ + } + +// OL_TXRX_PROT_AN_LOG(pdev->prot_an_tx_sent, msdu); + + if (tx_spec != ol_tx_spec_std) { + #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + if (tx_spec & ol_tx_spec_no_free) { + tx_desc->pkt_type = ol_tx_frm_no_free; + } else if (tx_spec & ol_tx_spec_tso) { + #else + if (tx_spec & ol_tx_spec_tso) { + #endif + tx_desc->pkt_type = ol_tx_frm_tso; + } + if (OL_TXRX_TX_IS_RAW(tx_spec)) { + // CHECK THIS: does this need to happen after htt_tx_desc_init? + /* different types of raw frames */ + u_int8_t sub_type = OL_TXRX_TX_RAW_SUBTYPE(tx_spec); + htt_tx_desc_type( + htt_pdev, tx_desc->htt_tx_desc, + htt_pkt_type_raw, sub_type); + } + } + + tx_msdu_info.htt.info.ext_tid = adf_nbuf_get_tid(msdu); + tx_msdu_info.htt.info.vdev_id = vdev->vdev_id; + tx_msdu_info.htt.info.frame_type = htt_frm_type_data; + tx_msdu_info.htt.info.l2_hdr_type = pdev->htt_pkt_type; + tx_msdu_info.htt.action.tx_comp_req = tx_comp_req; + + /* If the vdev is in OCB mode, parse the tx control header. */ + if (vdev->opmode == wlan_op_mode_ocb) { + if (!parse_ocb_tx_header(msdu, &tx_ctrl)) { + /* There was an error parsing the header. Skip this packet. */ + goto MSDU_LOOP_BOTTOM; + } + } + + txq = ol_tx_classify(vdev, tx_desc, msdu, &tx_msdu_info); + + if ((!txq) || TX_FILTER_CHECK(&tx_msdu_info)) { + /* drop this frame, but try sending subsequent frames */ + //TXRX_STATS_MSDU_LIST_INCR(pdev, tx.dropped.no_txq, msdu); + adf_os_atomic_inc(&pdev->tx_queue.rsrc_cnt); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); + if (tx_msdu_info.peer) { + /* remove the peer reference added above */ + ol_txrx_peer_unref_delete(tx_msdu_info.peer); + } + goto MSDU_LOOP_BOTTOM; + } + + if(tx_msdu_info.peer) { + /*If the state is not associated then drop all the data packets + received for that peer*/ + if(tx_msdu_info.peer->state == ol_txrx_peer_state_disc) { + adf_os_atomic_inc(&pdev->tx_queue.rsrc_cnt); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); + ol_txrx_peer_unref_delete(tx_msdu_info.peer); + msdu = next; + continue; + } + else if (tx_msdu_info.peer->state != ol_txrx_peer_state_auth) { + + if (tx_msdu_info.htt.info.ethertype != ETHERTYPE_PAE && tx_msdu_info.htt.info.ethertype != ETHERTYPE_WAI) { + adf_os_atomic_inc(&pdev->tx_queue.rsrc_cnt); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1); + ol_txrx_peer_unref_delete(tx_msdu_info.peer); + msdu = next; + continue; + } + } + } + /* + * Initialize the HTT tx desc l2 header offset field. + * htt_tx_desc_mpdu_header needs to be called to make sure, + * the l2 header size is initialized correctly to handle cases + * where TX ENCAP is disabled or Tx Encap fails to perform Encap + */ + htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, 0); + + /* + * Note: when the driver is built without support for SW tx encap, + * the following macro is a no-op. When the driver is built with + * support for SW tx encap, it performs encap, and if an error is + * encountered, jumps to the MSDU_LOOP_BOTTOM label. + */ + OL_TX_ENCAP_WRAPPER(pdev, vdev, tx_desc, msdu, tx_msdu_info); + + /* initialize the HW tx descriptor */ + htt_tx_desc_init( + pdev->htt_pdev, tx_desc->htt_tx_desc, + tx_desc->htt_tx_desc_paddr, + ol_tx_desc_id(pdev, tx_desc), + msdu, + &tx_msdu_info.htt, &tx_ctrl, vdev->opmode == wlan_op_mode_ocb); + /* + * If debug display is enabled, show the meta-data being + * downloaded to the target via the HTT tx descriptor. + */ + htt_tx_desc_display(tx_desc->htt_tx_desc); + + ol_tx_enqueue(pdev, txq, tx_desc, &tx_msdu_info); + if (tx_msdu_info.peer) { + OL_TX_PEER_STATS_UPDATE(tx_msdu_info.peer, msdu); + /* remove the peer reference added above */ + ol_txrx_peer_unref_delete(tx_msdu_info.peer); + } +MSDU_LOOP_BOTTOM: + msdu = next; + } + ol_tx_sched(pdev); + + return NULL; /* all MSDUs were accepted */ +} + +adf_nbuf_t +ol_tx_hl(ol_txrx_vdev_handle vdev, adf_nbuf_t msdu_list) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + int tx_comp_req = pdev->cfg.default_tx_comp_req; + + return ol_tx_hl_base(vdev, ol_tx_spec_std, msdu_list, tx_comp_req); +} + +adf_nbuf_t +ol_tx_non_std_hl( + ol_txrx_vdev_handle vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + int tx_comp_req = pdev->cfg.default_tx_comp_req; + + if (!tx_comp_req) { + if ((tx_spec == ol_tx_spec_no_free) && + (pdev->tx_data_callback.func)) { + tx_comp_req = 1; + } + } + return ol_tx_hl_base(vdev, tx_spec, msdu_list, tx_comp_req); +} + +adf_nbuf_t +ol_tx_non_std( + ol_txrx_vdev_handle vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list) +{ + if (vdev->pdev->cfg.is_high_latency) { + return ol_tx_non_std_hl(vdev, tx_spec, msdu_list); + } else { + return ol_tx_non_std_ll(vdev, tx_spec, msdu_list); + } +} + +void +ol_txrx_data_tx_cb_set( + ol_txrx_vdev_handle vdev, + ol_txrx_data_tx_cb callback, + void *ctxt) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + pdev->tx_data_callback.func = callback; + pdev->tx_data_callback.ctxt = ctxt; +} + +void +ol_txrx_mgmt_tx_cb_set( + ol_txrx_pdev_handle pdev, + u_int8_t type, + ol_txrx_mgmt_tx_cb download_cb, + ol_txrx_mgmt_tx_cb ota_ack_cb, + void *ctxt) +{ + TXRX_ASSERT1(type < OL_TXRX_MGMT_NUM_TYPES); + pdev->tx_mgmt.callbacks[type].download_cb = download_cb; + pdev->tx_mgmt.callbacks[type].ota_ack_cb = ota_ack_cb; + pdev->tx_mgmt.callbacks[type].ctxt = ctxt; +} + +int +ol_txrx_mgmt_send( + ol_txrx_vdev_handle vdev, + adf_nbuf_t tx_mgmt_frm, + u_int8_t type, + u_int8_t use_6mbps, + u_int16_t chanfreq) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + struct ol_tx_desc_t *tx_desc; + struct ol_txrx_msdu_info_t tx_msdu_info; + + tx_msdu_info.htt.action.use_6mbps = use_6mbps; + tx_msdu_info.htt.info.ext_tid = HTT_TX_EXT_TID_MGMT; + tx_msdu_info.htt.info.vdev_id = vdev->vdev_id; + tx_msdu_info.htt.action.do_tx_complete = + pdev->tx_mgmt.callbacks[type].ota_ack_cb ? 1 : 0; + + /* + * FIX THIS: l2_hdr_type should only specify L2 header type + * The Peregrine/Rome HTT layer provides the FW with a "pkt type" + * that is a combination of L2 header type and 802.11 frame type. + * If the 802.11 frame type is "mgmt", then the HTT pkt type is "mgmt". + * But if the 802.11 frame type is "data", then the HTT pkt type is + * the L2 header type (more or less): 802.3 vs. Native WiFi (basic 802.11). + * (Or the header type can be "raw", which is any version of the 802.11 + * header, and also implies that some of the offloaded tx data processing + * steps may not apply.) + * For efficiency, the Peregrine/Rome HTT uses the msdu_info's l2_hdr_type + * field to program the HTT pkt type. Thus, this txrx SW needs to overload + * the l2_hdr_type to indicate whether the frame is data vs. mgmt, as well + * as 802.3 L2 header vs. 802.11 L2 header. + * To fix this, the msdu_info's l2_hdr_type should be left specifying just + * the L2 header type. For mgmt frames, there should be a separate function + * to patch the HTT pkt type to store a "mgmt" value rather than the + * L2 header type. Then the HTT pkt type can be programmed efficiently + * for data frames, and the msdu_info's l2_hdr_type field won't be + * confusingly overloaded to hold the 802.11 frame type rather than the + * L2 header type. + */ + /* + * FIX THIS: remove duplication of htt_frm_type_mgmt and htt_pkt_type_mgmt + * The htt module expects a "enum htt_pkt_type" value. + * The htt_dxe module expects a "enum htt_frm_type" value. + * This needs to be cleaned up, so both versions of htt use a + * consistent method of specifying the frame type. + */ +#ifdef QCA_SUPPORT_INTEGRATED_SOC + /* tx mgmt frames always come with a 802.11 header */ + tx_msdu_info.htt.info.l2_hdr_type = htt_pkt_type_native_wifi; + tx_msdu_info.htt.info.frame_type = htt_frm_type_mgmt; +#else + tx_msdu_info.htt.info.l2_hdr_type = htt_pkt_type_mgmt; + tx_msdu_info.htt.info.frame_type = htt_pkt_type_mgmt; +#endif + + tx_msdu_info.peer = NULL; + + adf_nbuf_map_single(pdev->osdev, tx_mgmt_frm, ADF_OS_DMA_TO_DEVICE); + if (pdev->cfg.is_high_latency) { + tx_msdu_info.htt.action.tx_comp_req = 1; + tx_desc = ol_tx_desc_hl(pdev, vdev, tx_mgmt_frm, &tx_msdu_info); + } else { + /* For LL tx_comp_req is not used so initialized to 0 */ + tx_msdu_info.htt.action.tx_comp_req = 0; + tx_desc = ol_tx_desc_ll(pdev, vdev, tx_mgmt_frm, &tx_msdu_info); + /* FIX THIS - + * The FW currently has trouble using the host's fragments table + * for management frames. Until this is fixed, rather than + * specifying the fragment table to the FW, specify just the + * address of the initial fragment. + */ + if (tx_desc) { + /* + * Following the call to ol_tx_desc_ll, frag 0 is the HTT + * tx HW descriptor, and the frame payload is in frag 1. + */ + htt_tx_desc_frags_table_set( + pdev->htt_pdev, tx_desc->htt_tx_desc, + adf_nbuf_get_frag_paddr_lo(tx_mgmt_frm, 1), 0); + } + } + if (! tx_desc) { + adf_nbuf_unmap_single(pdev->osdev, tx_mgmt_frm, ADF_OS_DMA_TO_DEVICE); + return 1; /* can't accept the tx mgmt frame */ + } + TXRX_STATS_MSDU_INCR(pdev, tx.mgmt, tx_mgmt_frm); + TXRX_ASSERT1(type < OL_TXRX_MGMT_NUM_TYPES); + tx_desc->pkt_type = type + OL_TXRX_MGMT_TYPE_BASE; + + if (pdev->cfg.is_high_latency) { + struct ol_tx_frms_queue_t *txq; + /* + * 1. Look up the peer and queue the frame in the peer's mgmt queue. + * 2. Invoke the download scheduler. + */ + txq = ol_tx_classify_mgmt(vdev, tx_desc, tx_mgmt_frm, &tx_msdu_info); + if (!txq) { + //TXRX_STATS_MSDU_LIST_INCR(vdev->pdev, tx.dropped.no_txq, msdu); + adf_os_atomic_inc(&pdev->tx_queue.rsrc_cnt); + ol_tx_desc_frame_free_nonstd(vdev->pdev, tx_desc, 1 /* error */); + if (tx_msdu_info.peer) { + /* remove the peer reference added above */ + ol_txrx_peer_unref_delete(tx_msdu_info.peer); + } + return 1; /* can't accept the tx mgmt frame */ + } + /* Initialize the HTT tx desc l2 header offset field. + * Even though tx encap does not apply to mgmt frames, + * htt_tx_desc_mpdu_header still needs to be called, + * to specifiy that there was no L2 header added by tx encap, + * so the frame's length does not need to be adjusted to account for + * an added L2 header. + */ + htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, 0); + htt_tx_desc_init( + pdev->htt_pdev, tx_desc->htt_tx_desc, + tx_desc->htt_tx_desc_paddr, + ol_tx_desc_id(pdev, tx_desc), + tx_mgmt_frm, + &tx_msdu_info.htt, NULL, 0); + htt_tx_desc_display(tx_desc->htt_tx_desc); + htt_tx_desc_set_chanfreq(tx_desc->htt_tx_desc, chanfreq); + + ol_tx_enqueue(vdev->pdev, txq, tx_desc, &tx_msdu_info); + if (tx_msdu_info.peer) { + /* remove the peer reference added above */ + ol_txrx_peer_unref_delete(tx_msdu_info.peer); + } + ol_tx_sched(vdev->pdev); + } else { + htt_tx_desc_set_chanfreq(tx_desc->htt_tx_desc, chanfreq); + ol_tx_send_nonstd(pdev, tx_desc, tx_mgmt_frm, htt_pkt_type_mgmt); + } + + return 0; /* accepted the tx mgmt frame */ +} + +void +ol_txrx_sync(ol_txrx_pdev_handle pdev, u_int8_t sync_cnt) +{ + htt_h2t_sync_msg(pdev->htt_pdev, sync_cnt); +} + +adf_nbuf_t ol_tx_reinject( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t msdu, u_int16_t peer_id) +{ + struct ol_tx_desc_t *tx_desc; + struct ol_txrx_msdu_info_t msdu_info; + + msdu_info.htt.info.l2_hdr_type = vdev->pdev->htt_pkt_type; + msdu_info.htt.info.ext_tid = HTT_TX_EXT_TID_INVALID; + msdu_info.peer = NULL; + msdu_info.htt.action.tx_comp_req = 0; + + ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info); + HTT_TX_DESC_POSTPONED_SET(*((u_int32_t *)(tx_desc->htt_tx_desc)), TRUE); + + htt_tx_desc_set_peer_id(tx_desc->htt_tx_desc, peer_id); + + ol_tx_send(vdev->pdev, tx_desc, msdu); + + return NULL; +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.h new file mode 100644 index 000000000000..a2290ae0cc6b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_tx.h + * @brief Internal definitions for the high-level tx module. + */ +#ifndef _OL_TX__H_ +#define _OL_TX__H_ + +#include /* adf_nbuf_t */ +#include +#include /* ol_txrx_vdev_handle */ + +#include /* ol_tx_desc_t, ol_txrx_msdu_info_t */ + +adf_nbuf_t +ol_tx_ll(ol_txrx_vdev_handle vdev, adf_nbuf_t msdu_list); + +adf_nbuf_t +ol_tx_ll_queue(ol_txrx_vdev_handle vdev, adf_nbuf_t msdu_list); + +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ +#define OL_TX_LL ol_tx_ll_queue +#else +#define OL_TX_LL ol_tx_ll +#endif + +void ol_tx_vdev_ll_pause_queue_send(void *context); + +adf_nbuf_t +ol_tx_non_std_ll( + ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list); + +adf_nbuf_t +ol_tx_hl(ol_txrx_vdev_handle vdev, adf_nbuf_t msdu_list); + +adf_nbuf_t +ol_tx_non_std_hl( + ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list); + +adf_nbuf_t +ol_tx_reinject(struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu, u_int16_t peer_id); + +void +ol_txrx_mgmt_tx_complete(void *ctxt, adf_nbuf_t netbuf, int err); + +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ +/** + * ol_tx_vdev_ll_pause_start_timer() - Start ll-q pause timer for specific virtual device + * @vdev: the virtual device + * + * When system comes out of suspend, it is necessary to start the timer + * which will ensure to pull out all the queued packets after expiry. + * This function restarts the ll-pause timer, for the specific vdev device. + * + * + * Return: None + */ +void +ol_tx_vdev_ll_pause_start_timer(struct ol_txrx_vdev_t *vdev); +#endif + +void +ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev); +#endif /* _OL_TX__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.c new file mode 100644 index 000000000000..01a5257ea675 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.c @@ -0,0 +1,793 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* adf_nbuf_t, etc. */ +#include /* HTT_TX_EXT_TID_MGMT */ +#include /* htt_tx_desc_tid */ +#include /* ol_txrx_vdev_handle */ +#include /* ol_txrx_sync */ +#include +#include /* TXRX_ASSERT1 */ +#include /* pdev stats */ +#include /* ol_tx_desc */ +#include /* ol_tx_send */ +#include +#include +#include +#include +#include +#include +#include /* ETHERTYPE_VLAN, etc. */ +#include /* ieee80211_frame */ + +/* + * In theory, this tx classify code could be used on the host or in the target. + * Thus, this code uses generic OS primitives, that can be aliased to either + * the host's OS primitives or the target's OS primitives. + * For now, the following #defines set up these host-specific or + * target-specific aliases. + */ + +#if defined(CONFIG_HL_SUPPORT) + +#define OL_TX_CLASSIFY_EXTENSION(vdev, tx_desc, netbuf, msdu_info, txq) +#define OL_TX_CLASSIFY_MGMT_EXTENSION(vdev, tx_desc, netbuf, msdu_info, txq) + +#ifdef QCA_TX_HTT2_SUPPORT +static void +ol_tx_classify_htt2_frm( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t tx_nbuf, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + struct htt_msdu_info_t *htt = &tx_msdu_info->htt; + A_UINT8 candi_frm = 0; + + /* + * Offload the frame re-order to L3 protocol and ONLY support + * TCP protocol now. + */ + if ((htt->info.l2_hdr_type == htt_pkt_type_ethernet) && + (htt->info.frame_type == htt_frm_type_data) && + htt->info.is_unicast && + (htt->info.ethertype == ETHERTYPE_IPV4)) + { + struct ipv4_hdr_t *ipHdr; + + ipHdr = (struct ipv4_hdr_t *)(adf_nbuf_data(tx_nbuf) + + htt->info.l3_hdr_offset); + if (ipHdr->protocol == IP_PROTOCOL_TCP) { + candi_frm = 1; + } + } + + adf_nbuf_set_tx_parallel_dnload_frm(tx_nbuf, candi_frm); +} + +#define OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, netbuf, msdu_info) \ + ol_tx_classify_htt2_frm(vdev, netbuf, msdu_info); +#else +#define OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, netbuf, msdu_info) /* no-op */ +#endif /* QCA_TX_HTT2_SUPPORT */ +/* DHCP go with voice priority; WMM_AC_VO_TID1();*/ +#define TX_DHCP_TID 6 + +#if defined(QCA_BAD_PEER_TX_FLOW_CL) +static inline A_BOOL +ol_if_tx_bad_peer_txq_overflow( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + struct ol_tx_frms_queue_t *txq) +{ + if (peer && pdev && txq && (peer->tx_limit_flag) && (txq->frms >= pdev->tx_peer_bal.peer_bal_txq_limit)) { + return TRUE; + } else { + return FALSE; + } +} +#else +static inline A_BOOL ol_if_tx_bad_peer_txq_overflow( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + struct ol_tx_frms_queue_t *txq) +{ + return FALSE; +} +#endif + +/* EAPOL go with voice priority: WMM_AC_TO_TID1(WMM_AC_VO);*/ +#define TX_EAPOL_TID 6 + +/* ARP go with voice priority: WMM_AC_TO_TID1(pdev->arp_ac_override)*/ +#define TX_ARP_TID 6 + +/* For non-IP case, use default TID */ +#define TX_DEFAULT_TID 0 + +/* + * Determine IP TOS priority + * IP Tos format : + * (Refer Pg 57 WMM-test-plan-v1.2) + * IP-TOS - 8bits + * : DSCP(6-bits) ECN(2-bits) + * : DSCP - P2 P1 P0 X X X + * where (P2 P1 P0) form 802.1D + */ +static inline A_UINT8 +ol_tx_tid_by_ipv4( + A_UINT8 *pkt) +{ + A_UINT8 ipPri, tid; + struct ipv4_hdr_t *ipHdr = (struct ipv4_hdr_t *)pkt; + + ipPri = ipHdr->tos >> 5; + tid = ipPri & 0x7; + + return tid; +} + +static inline A_UINT8 +ol_tx_tid_by_ipv6( + A_UINT8 *pkt) +{ + return (IPV6_TRAFFIC_CLASS((struct ipv6_hdr_t *) pkt) >> 5) & 0x7; +} + +static inline void +ol_tx_set_ether_type( + A_UINT8 *datap, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + A_UINT16 typeorlength; + A_UINT8 * ptr; + A_UINT8 *l3_data_ptr; + + if (tx_msdu_info->htt.info.l2_hdr_type == htt_pkt_type_raw) { + /* adjust hdr_ptr to RA */ + struct ieee80211_frame *wh = (struct ieee80211_frame *)datap; + + if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { + struct llc_snap_hdr_t *llc; + /* dot11 encapsulated frame */ + struct ieee80211_qosframe *whqos = (struct ieee80211_qosframe *)datap; + if (whqos->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { + tx_msdu_info->htt.info.l3_hdr_offset = + sizeof(struct ieee80211_qosframe); + } else { + tx_msdu_info->htt.info.l3_hdr_offset = + sizeof(struct ieee80211_frame); + } + llc = (struct llc_snap_hdr_t *) + (datap + tx_msdu_info->htt.info.l3_hdr_offset); + tx_msdu_info->htt.info.ethertype = + (llc->ethertype[0] << 8) | llc->ethertype[1]; + /* + * l3_hdr_offset refers to the end of the 802.3 or 802.11 header, + * which may be a LLC/SNAP header rather than the IP header. + * Thus, don't increment l3_hdr_offset += sizeof(*llc); rather, + * leave it as is. + */ + } else { + /* + * This function should only be applied to data frames. + * For management frames, we already know to use HTT_TX_EXT_TID_MGMT. + */ + TXRX_ASSERT2(0); + } + } else if (tx_msdu_info->htt.info.l2_hdr_type == htt_pkt_type_ethernet) { + ptr = (datap + ETHERNET_ADDR_LEN * 2); + typeorlength = (ptr[0] << 8) | ptr[1]; + l3_data_ptr = datap + sizeof(struct ethernet_hdr_t);//ETHERNET_HDR_LEN; + + if (typeorlength == ETHERTYPE_VLAN) { + ptr = (datap + ETHERNET_ADDR_LEN * 2 + ETHERTYPE_VLAN_LEN); + typeorlength = (ptr[0] << 8) | ptr[1]; + l3_data_ptr += ETHERTYPE_VLAN_LEN; + } + + if (!IS_ETHERTYPE(typeorlength)) { // 802.3 header + struct llc_snap_hdr_t *llc_hdr = (struct llc_snap_hdr_t *) l3_data_ptr; + typeorlength = (llc_hdr->ethertype[0] << 8) | llc_hdr->ethertype[1]; + l3_data_ptr += sizeof(struct llc_snap_hdr_t); + } + + tx_msdu_info->htt.info.l3_hdr_offset = (A_UINT8)(l3_data_ptr - datap); + tx_msdu_info->htt.info.ethertype = typeorlength; + } +} + +static inline A_UINT8 +ol_tx_tid_by_ether_type( + A_UINT8 *datap, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + A_UINT8 tid; + A_UINT8 *l3_data_ptr; + A_UINT16 typeorlength; + + l3_data_ptr = datap + tx_msdu_info->htt.info.l3_hdr_offset; + typeorlength = tx_msdu_info->htt.info.ethertype; + + /* IP packet, do packet inspection for TID */ + if (typeorlength == ETHERTYPE_IPV4) { + tid = ol_tx_tid_by_ipv4(l3_data_ptr); + } else if (typeorlength == ETHERTYPE_IPV6) { + tid = ol_tx_tid_by_ipv6(l3_data_ptr); + } else if (ETHERTYPE_IS_EAPOL_WAPI(typeorlength)) { + /* EAPOL go with voice priority*/ + tid = TX_EAPOL_TID; + } else if (typeorlength == ETHERTYPE_ARP) { + tid = TX_ARP_TID; + } else { + /* For non-IP case, use default TID */ + tid = TX_DEFAULT_TID; + } + return tid; +} + +static inline A_UINT8 +ol_tx_tid_by_raw_type( + A_UINT8 *datap, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + A_UINT8 tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST; + + /* adjust hdr_ptr to RA */ + struct ieee80211_frame *wh = (struct ieee80211_frame *)datap; + + /* FIXME: This code does not handle 4 address formats. The QOS field + * is not at usual location. + */ + if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { + /* dot11 encapsulated frame */ + struct ieee80211_qosframe *whqos = (struct ieee80211_qosframe *)datap; + if (whqos->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { + tid = whqos->i_qos[0] & IEEE80211_QOS_TID; + } else { + tid = HTT_NON_QOS_TID; + } + } else { + /* + * This function should only be applied to data frames. + * For management frames, we already know to use HTT_TX_EXT_TID_MGMT. + */ + adf_os_assert(0); + } + return tid; +} + +static A_UINT8 +ol_tx_tid( + struct ol_txrx_pdev_t *pdev, + adf_nbuf_t tx_nbuf, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + A_UINT8 *datap = adf_nbuf_data(tx_nbuf); + A_UINT8 tid; + + if (pdev->frame_format == wlan_frm_fmt_raw) { + tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_raw; + + ol_tx_set_ether_type(datap, tx_msdu_info); + tid = tx_msdu_info->htt.info.ext_tid == ADF_NBUF_TX_EXT_TID_INVALID ? + ol_tx_tid_by_raw_type(datap, tx_msdu_info) : + tx_msdu_info->htt.info.ext_tid; + } else if (pdev->frame_format == wlan_frm_fmt_802_3) { + tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_ethernet; + + ol_tx_set_ether_type(datap, tx_msdu_info); + if (A_STATUS_OK == adf_nbuf_is_dhcp_pkt(tx_nbuf)) { + /* DHCP frame to go with voice priority */ + tid = TX_DHCP_TID; + } else { + tid = + tx_msdu_info->htt.info.ext_tid == ADF_NBUF_TX_EXT_TID_INVALID ? + ol_tx_tid_by_ether_type(datap, tx_msdu_info) : + tx_msdu_info->htt.info.ext_tid; + } + } else if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + struct llc_snap_hdr_t *llc; + + tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_native_wifi; + tx_msdu_info->htt.info.l3_hdr_offset = sizeof(struct ieee80211_frame); + llc = (struct llc_snap_hdr_t *) + (datap + tx_msdu_info->htt.info.l3_hdr_offset); + tx_msdu_info->htt.info.ethertype = + (llc->ethertype[0] << 8) | llc->ethertype[1]; + /* + * Native WiFi is a special case of "raw" 802.11 header format. + * However, we expect that for all cases that use native WiFi, + * the TID will be directly specified out of band. + */ + tid = tx_msdu_info->htt.info.ext_tid; + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "Invalid standard frame type: %d\n", pdev->frame_format); + adf_os_assert(0); + tid = HTT_TX_EXT_TID_INVALID; + } + return tid; +} + +struct ol_tx_frms_queue_t * +ol_tx_classify( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t tx_nbuf, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + struct ol_txrx_peer_t *peer = NULL; + struct ol_tx_frms_queue_t *txq = NULL; + A_UINT8 *dest_addr; + A_UINT8 tid; +#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + u_int8_t peer_id; +#endif + + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + + dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf); + if ((IEEE80211_IS_MULTICAST(dest_addr)) + || (vdev->opmode == wlan_op_mode_ocb)) { + txq = &vdev->txqs[OL_TX_VDEV_MCAST_BCAST]; + tx_msdu_info->htt.info.ext_tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST; + if (vdev->opmode == wlan_op_mode_sta) { + /* + * The STA sends a frame with a broadcast dest addr (DA) as a + * unicast frame to the AP's receive addr (RA). + * Find the peer object that represents the AP that the STA + * is associated with. + */ + peer = ol_txrx_assoc_peer_find(vdev); + if (!peer) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Error: STA %p (%02x:%02x:%02x:%02x:%02x:%02x) " + "trying to send bcast DA tx data frame " + "w/o association\n", + vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], + vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], + vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + return NULL; /* error */ + } else if (A_STATUS_OK == + adf_nbuf_is_dhcp_pkt(tx_nbuf)) { + /* DHCP frame to go with voice priority */ + txq = &peer->txqs[TX_DHCP_TID]; + tx_msdu_info->htt.info.ext_tid = TX_DHCP_TID; + } + /* + * The following line assumes each peer object has a single ID. + * This is currently true, and is expected to remain true. + */ + tx_msdu_info->htt.info.peer_id = peer->peer_ids[0]; + } else if (vdev->opmode == wlan_op_mode_ocb) { + tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; + /* In OCB mode, don't worry about the peer. We don't need it. */ + peer = NULL; + } else { + tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; + /* + * Look up the vdev's BSS peer, so that the classify_extension + * function can check whether to encrypt multicast / broadcast + * frames. + */ + peer = ol_txrx_peer_find_hash_find(pdev, vdev->mac_addr.raw, 0, 1); + if (!peer) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Error: vdev %p (%02x:%02x:%02x:%02x:%02x:%02x) " + "trying to send bcast/mcast, but no self-peer found\n", + vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], + vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], + vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + return NULL; /* error */ + } + } + tx_msdu_info->htt.info.is_unicast = FALSE; + } else { + /* tid would be overwritten for non QoS case*/ + tid = ol_tx_tid(pdev, tx_nbuf, tx_msdu_info); + if ((HTT_TX_EXT_TID_INVALID == tid) || (tid >= OL_TX_NUM_TIDS)) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%s Error: could not classify packet into valid TID(%d).\n", + __func__, tid); + return NULL; + } + #ifdef ATH_SUPPORT_WAPI + /* Check to see if a frame is a WAI frame */ + if (tx_msdu_info->htt.info.ethertype == ETHERTYPE_WAI) { + /* WAI frames should not be encrypted */ + tx_msdu_info->htt.action.do_encrypt = 0; + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "Tx Frame is a WAI frame\n"); + } + #endif /* ATH_SUPPORT_WAPI */ + + /* + * Find the peer and increment its reference count. + * If this vdev is an AP, use the dest addr (DA) to determine + * which peer STA this unicast data frame is for. + * If this vdev is a STA, the unicast data frame is for the + * AP the STA is associated with. + */ + if (vdev->opmode == wlan_op_mode_sta) { + /* + * TO DO: + * To support TDLS, first check if there is a TDLS peer STA, + * and if so, check if the DA matches the TDLS peer STA's + * MAC address. + * If there is no peer TDLS STA, or if the DA is not the + * TDLS STA's address, then the frame is either for the AP + * itself, or is supposed to be sent to the AP for forwarding. + */ + #if 0 + if (vdev->num_tdls_peers > 0) { + peer = NULL; + for (i = 0; i < vdev->num_tdls_peers); i++) { + int differs = adf_os_mem_cmp( + vdev->tdls_peers[i]->mac_addr.raw, + dest_addr, OL_TXRX_MAC_ADDR_LEN); + if (!differs) { + peer = vdev->tdls_peers[i]; + break; + } + } + } else { + /* send to AP */ + peer = ol_txrx_assoc_peer_find(vdev); + } + #endif + #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + if (vdev->hlTdlsFlag) { + peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); + if (peer && (peer->peer_ids[0] == HTT_INVALID_PEER_ID)) + peer = NULL; + else { + if (peer) + adf_os_atomic_inc(&peer->ref_cnt); + } + } + if (!peer) + peer = ol_txrx_assoc_peer_find(vdev); + #else + peer = ol_txrx_assoc_peer_find(vdev); + #endif + } else { + peer = ol_txrx_peer_find_hash_find(pdev, dest_addr, 0, 1); + } + tx_msdu_info->htt.info.is_unicast = TRUE; + if (!peer) { + /* + * Unicast data xfer can only happen to an associated peer. + * It is illegitimate to send unicast data if there is no peer + * to send it to. + */ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Error: vdev %p (%02x:%02x:%02x:%02x:%02x:%02x) " + "trying to send unicast tx data frame to an unknown peer\n", + vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], + vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], + vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + return NULL; /* error */ + } + TX_SCHED_DEBUG_PRINT("Peer found\n"); + if (!peer->qos_capable) { + tid = OL_TX_NON_QOS_TID; + } + /* Only allow encryption when in authenticated state */ + if (ol_txrx_peer_state_auth != peer->state) { + tx_msdu_info->htt.action.do_encrypt = 0; + } + txq = &peer->txqs[tid]; + tx_msdu_info->htt.info.ext_tid = tid; + /* + * The following line assumes each peer object has a single ID. + * This is currently true, and is expected to remain true. + */ + tx_msdu_info->htt.info.peer_id = peer->peer_ids[0]; + /* + * WORKAROUND - check that the peer ID is valid. + * If tx data is provided before ol_rx_peer_map_handler is called + * to record the peer ID specified by the target, then we could + * end up here with an invalid peer ID. + * TO DO: rather than dropping the tx frame, pause the txq it + * goes into, then fill in the peer ID for the entries in the + * txq when the peer_map event provides the peer ID, and then + * unpause the txq. + */ + if (tx_msdu_info->htt.info.peer_id == HTT_INVALID_PEER_ID) { + if (peer) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: remove the peer for invalid peer_id %p\n", + __func__, peer); + /* remove the peer reference added above */ + ol_txrx_peer_unref_delete(peer); + tx_msdu_info->peer = NULL; + } + return NULL; + } + } + tx_msdu_info->peer = peer; + if (ol_if_tx_bad_peer_txq_overflow(pdev, peer, txq)) { + return NULL; + } + /* + * If relevant, do a deeper inspection to determine additional + * characteristics of the tx frame. + * If the frame is invalid, then the txq will be set to NULL to + * indicate an error. + */ + OL_TX_CLASSIFY_EXTENSION(vdev, tx_desc, tx_nbuf, tx_msdu_info, txq); + if (IEEE80211_IS_MULTICAST(dest_addr) && vdev->opmode != wlan_op_mode_sta && + tx_msdu_info->peer != NULL) { + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: remove the peer reference %p\n", __func__, peer); + /* remove the peer reference added above */ + ol_txrx_peer_unref_delete(tx_msdu_info->peer); + /* Making peer NULL in case if multicast non STA mode */ + tx_msdu_info->peer = NULL; + } + + /* Whether this frame can download though HTT2 data pipe or not. */ + OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, tx_nbuf, tx_msdu_info); + + /* Update Tx Queue info */ + tx_desc->txq = txq; + + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); + return txq; +} + +struct ol_tx_frms_queue_t * +ol_tx_classify_mgmt( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t tx_nbuf, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + struct ol_txrx_peer_t *peer = NULL; + struct ol_tx_frms_queue_t *txq = NULL; + A_UINT8 *dest_addr; + + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf); + if (IEEE80211_IS_MULTICAST(dest_addr)) { + /* + * AP: beacons are broadcast, + * public action frames (e.g. extended channel switch announce) + * may be broadcast + * STA: probe requests can be either broadcast or unicast + */ + txq = &vdev->txqs[OL_TX_VDEV_DEFAULT_MGMT]; + tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; + tx_msdu_info->peer = NULL; + tx_msdu_info->htt.info.is_unicast = 0; + } else { + /* + * Find the peer and increment its reference count. + * If this vdev is an AP, use the receiver addr (RA) to determine + * which peer STA this unicast mgmt frame is for. + * If this vdev is a STA, the unicast mgmt frame is for the + * AP the STA is associated with. + * Probe request / response and Assoc request / response are + * sent before the peer exists - in this case, use the + * vdev's default tx queue. + */ + if (vdev->opmode == wlan_op_mode_sta) { + /* + * TO DO: + * To support TDLS, first check if there is a TDLS peer STA, + * and if so, check if the DA matches the TDLS peer STA's + * MAC address. + */ + peer = ol_txrx_assoc_peer_find(vdev); + } else { + /* find the peer and increment its reference count */ + peer = ol_txrx_peer_find_hash_find(pdev, dest_addr, 0, 1); + } + tx_msdu_info->peer = peer; + if (!peer) { + txq = &vdev->txqs[OL_TX_VDEV_DEFAULT_MGMT]; + tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; + } else { + txq = &peer->txqs[HTT_TX_EXT_TID_MGMT]; + tx_msdu_info->htt.info.ext_tid = HTT_TX_EXT_TID_MGMT; + /* + * The following line assumes each peer object has a single ID. + * This is currently true, and is expected to remain true. + */ + tx_msdu_info->htt.info.peer_id = peer->peer_ids[0]; + } + tx_msdu_info->htt.info.is_unicast = 1; + } + /* + * If relevant, do a deeper inspection to determine additional + * characteristics of the tx frame. + * If the frame is invalid, then the txq will be set to NULL to + * indicate an error. + */ + OL_TX_CLASSIFY_MGMT_EXTENSION(vdev, tx_desc, tx_nbuf, tx_msdu_info, txq); + + /* Whether this frame can download though HTT2 data pipe or not. */ + OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, tx_nbuf, tx_msdu_info); + + /* Update Tx Queue info */ + tx_desc->txq = txq; + + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); + return txq; +} + +A_STATUS +ol_tx_classify_extension( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t tx_msdu, + struct ol_txrx_msdu_info_t *msdu_info) +{ + A_UINT8 *datap = adf_nbuf_data(tx_msdu); + struct ol_txrx_peer_t *peer; + int which_key; + + /* + * The following msdu_info fields were already filled in by the + * ol_tx entry function or the regular ol_tx_classify function: + * htt.info.vdev_id (ol_tx_hl or ol_tx_non_std_hl) + * htt.info.ext_tid (ol_tx_non_std_hl or ol_tx_classify) + * htt.info.frame_type (ol_tx_hl or ol_tx_non_std_hl) + * htt.info.l2_hdr_type (ol_tx_hl or ol_tx_non_std_hl) + * htt.info.is_unicast (ol_tx_classify) + * htt.info.peer_id (ol_tx_classify) + * peer (ol_tx_classify) + * if (is_unicast) { + * htt.info.ethertype (ol_tx_classify) + * htt.info.l3_hdr_offset (ol_tx_classify) + * } + * The following fields need to be filled in by this function: + * if (!is_unicast) { + * htt.info.ethertype + * htt.info.l3_hdr_offset + * } + * htt.action.band (NOT CURRENTLY USED) + * htt.action.do_encrypt + * htt.action.do_tx_complete + * The following fields are not needed for data frames, and can + * be left uninitialized: + * htt.info.frame_subtype + */ + + if (!msdu_info->htt.info.is_unicast) { + int l2_hdr_size; + A_UINT16 ethertype; + + if (msdu_info->htt.info.l2_hdr_type == htt_pkt_type_ethernet) { + struct ethernet_hdr_t *eh; + + eh = (struct ethernet_hdr_t *) datap; + l2_hdr_size = sizeof(*eh); + ethertype = (eh->ethertype[0] << 8) | eh->ethertype[1]; + + if (ethertype == ETHERTYPE_VLAN) { + struct ethernet_vlan_hdr_t *evh; + + evh = (struct ethernet_vlan_hdr_t *) datap; + l2_hdr_size = sizeof(*evh); + ethertype = (evh->ethertype[0] << 8) | evh->ethertype[1]; + } + + if (!IS_ETHERTYPE(ethertype)) { // 802.3 header + struct llc_snap_hdr_t *llc = + (struct llc_snap_hdr_t *) (datap + l2_hdr_size); + ethertype = (llc->ethertype[0] << 8) | llc->ethertype[1]; + l2_hdr_size += sizeof(*llc); + } + msdu_info->htt.info.l3_hdr_offset = l2_hdr_size; + msdu_info->htt.info.ethertype = ethertype; + } else { /* 802.11 */ + struct llc_snap_hdr_t *llc; + l2_hdr_size = ol_txrx_ieee80211_hdrsize(datap); + llc = (struct llc_snap_hdr_t *) (datap + l2_hdr_size); + ethertype = (llc->ethertype[0] << 8) | llc->ethertype[1]; + /* + * Don't include the LLC/SNAP header in l2_hdr_size, because + * l3_hdr_offset is actually supposed to refer to the header + * after the 802.3 or 802.11 header, which could be a LLC/SNAP + * header rather than the L3 header. + */ + } + msdu_info->htt.info.l3_hdr_offset = l2_hdr_size; + msdu_info->htt.info.ethertype = ethertype; + which_key = txrx_sec_mcast; + } else { + which_key = txrx_sec_ucast; + } + peer = msdu_info->peer; + /* + * msdu_info->htt.action.do_encrypt is initially set in ol_tx_desc_hl. + * Add more check here. + */ + msdu_info->htt.action.do_encrypt = (!peer) ? 0 : + (peer->security[which_key].sec_type == htt_sec_type_none) ? 0 : + msdu_info->htt.action.do_encrypt; + /* + * For systems that have a frame by frame spec for whether to receive + * a tx completion notification, use the tx completion notification only + * for certain management frames, not for data frames. + * (In the future, this may be changed slightly, e.g. to request a + * tx completion notification for the final EAPOL message sent by a + * STA during the key delivery handshake.) + */ + msdu_info->htt.action.do_tx_complete = 0; + + return A_OK; +} + +A_STATUS +ol_tx_classify_mgmt_extension( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t tx_msdu, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct ieee80211_frame *wh; + + /* + * The following msdu_info fields were already filled in by the + * ol_tx entry function or the regular ol_tx_classify_mgmt function: + * htt.info.vdev_id (ol_txrx_mgmt_send) + * htt.info.frame_type (ol_txrx_mgmt_send) + * htt.info.l2_hdr_type (ol_txrx_mgmt_send) + * htt.action.do_tx_complete (ol_txrx_mgmt_send) + * htt.info.peer_id (ol_tx_classify_mgmt) + * htt.info.ext_tid (ol_tx_classify_mgmt) + * htt.info.is_unicast (ol_tx_classify_mgmt) + * peer (ol_tx_classify_mgmt) + * The following fields need to be filled in by this function: + * htt.info.frame_subtype + * htt.info.l3_hdr_offset + * htt.action.band (NOT CURRENTLY USED) + * The following fields are not needed for mgmt frames, and can + * be left uninitialized: + * htt.info.ethertype + * htt.action.do_encrypt + * (This will be filled in by other SW, which knows whether + * the peer has robust-managment-frames enabled.) + */ + wh = (struct ieee80211_frame *) adf_nbuf_data(tx_msdu); + msdu_info->htt.info.frame_subtype = + (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >> + IEEE80211_FC0_SUBTYPE_SHIFT; + msdu_info->htt.info.l3_hdr_offset = sizeof(struct ieee80211_frame); + + return A_OK; +} + +#endif /* defined(CONFIG_HL_SUPPORT) */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.h new file mode 100644 index 000000000000..869162ecdfe4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_classify.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_tx_classify.h + * @brief API definitions for the tx classify module within the data SW. + */ +#ifndef _OL_TX_CLASSIFY__H_ +#define _OL_TX_CLASSIFY__H_ + +#include /* adf_nbuf_t */ +#include /* ol_txrx_vdev_t, etc. */ + +static inline u_int8_t * +ol_tx_dest_addr_find( + struct ol_txrx_pdev_t *pdev, + adf_nbuf_t tx_nbuf) +{ + u_int8_t *hdr_ptr; + void *datap = adf_nbuf_data(tx_nbuf); + + if (pdev->frame_format == wlan_frm_fmt_raw) { + /* adjust hdr_ptr to RA */ + struct ieee80211_frame *wh = (struct ieee80211_frame *)datap; + hdr_ptr = wh->i_addr1; + } else if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + /* adjust hdr_ptr to RA */ + struct ieee80211_frame *wh = (struct ieee80211_frame *)datap; + hdr_ptr = wh->i_addr1; + } else if (pdev->frame_format == wlan_frm_fmt_802_3) { + hdr_ptr = datap; + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid standard frame type: %d\n", + pdev->frame_format); + adf_os_assert(0); + hdr_ptr = NULL; + } + return hdr_ptr; +} + +#if defined(CONFIG_HL_SUPPORT) + +/** + * @brief Classify a tx frame to which tid queue. + * + * @param vdev - the virtual device sending the data + * (for specifying the transmitter address for multicast / broadcast data) + * @param tx_desc - descriptor object with meta-data about the tx frame + * @param netbuf - the tx frame + * @param tx_msdu_info - characteristics of the tx frame + */ +struct ol_tx_frms_queue_t * +ol_tx_classify( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *tx_msdu_info); + +struct ol_tx_frms_queue_t * +ol_tx_classify_mgmt( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *tx_msdu_info); + +#else + +#define ol_tx_classify(vdev, tx_desc, netbuf, tx_msdu_info) NULL +#define ol_tx_classify_mgmt(vdev, tx_desc, netbuf, tx_msdu_info) NULL + +#endif /* defined(CONFIG_HL_SUPPORT) */ + + +#endif /* _OL_TX_CLASSIFY__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.c new file mode 100644 index 000000000000..60dc045b05aa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* ADF_NBUF_EXEMPT_NO_EXEMPTION, etc. */ +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_assert */ +#include /* adf_os_spinlock */ +#ifdef QCA_COMPUTE_TX_DELAY +#include /* adf_os_ticks */ +#endif +#include /* TAILQ */ + +#include /* htt_tx_desc_id */ + +#include /* ol_txrx_pdev_t */ +#include +#include +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP +#include /* OL_TX_RESTORE_HDR, etc*/ +#endif +#include + +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS +extern u_int32_t *g_dbg_htt_desc_end_addr, *g_dbg_htt_desc_start_addr; +#endif + +#ifdef QCA_COMPUTE_TX_DELAY +static inline void +OL_TX_TIMESTAMP_SET(struct ol_tx_desc_t *tx_desc) +{ + tx_desc->entry_timestamp_ticks = adf_os_ticks(); +} +#else +#define OL_TX_TIMESTAMP_SET(tx_desc) /* no-op */ +#endif + +static inline struct ol_tx_desc_t * +ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev) +{ + struct ol_tx_desc_t *tx_desc = NULL; + + adf_os_spin_lock_bh(&pdev->tx_mutex); + if (pdev->tx_desc.freelist) { + pdev->tx_desc.num_free--; + tx_desc = pdev->tx_desc.freelist->tx_desc; + pdev->tx_desc.freelist = pdev->tx_desc.freelist->next; +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS + if (tx_desc->pkt_type != 0xff +#ifdef QCA_COMPUTE_TX_DELAY + || tx_desc->entry_timestamp_ticks != 0xffffffff +#endif + ) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s Potential tx_desc corruption pkt_type:0x%x pdev:0x%p", + __func__, tx_desc->pkt_type, pdev); +#ifdef QCA_COMPUTE_TX_DELAY + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s Timestamp:0x%x\n", + __func__, tx_desc->entry_timestamp_ticks); +#endif + adf_os_assert(0); + } + if ((u_int32_t *) tx_desc->htt_tx_desc < g_dbg_htt_desc_start_addr || + (u_int32_t *) tx_desc->htt_tx_desc > g_dbg_htt_desc_end_addr) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s Potential htt_desc curruption:0x%p pdev:0x%p\n", + __func__, tx_desc->htt_tx_desc, pdev); + adf_os_assert(0); + } +#endif + } + adf_os_spin_unlock_bh(&pdev->tx_mutex); + if (!tx_desc) { + return NULL; + } +#if defined(CONFIG_HL_SUPPORT) + tx_desc->vdev = vdev; +#endif +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + adf_os_atomic_inc(&vdev->tx_desc_count); +#endif + + OL_TX_TIMESTAMP_SET(tx_desc); + + return tx_desc; +} + +static inline struct ol_tx_desc_t * +ol_tx_desc_alloc_hl(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev) +{ + struct ol_tx_desc_t *tx_desc; + + tx_desc = ol_tx_desc_alloc(pdev, vdev); + if (!tx_desc) return NULL; + + + adf_os_atomic_dec(&pdev->tx_queue.rsrc_cnt); + + return tx_desc; +} + +/* TBD: make this inline in the .h file? */ +struct ol_tx_desc_t * +ol_tx_desc_find(struct ol_txrx_pdev_t *pdev, u_int16_t tx_desc_id) +{ + return pdev->tx_desc.array[tx_desc_id].tx_desc; +} + +void +ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + adf_os_spin_lock_bh(&pdev->tx_mutex); +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS + tx_desc->pkt_type = 0xff; +#ifdef QCA_COMPUTE_TX_DELAY + tx_desc->entry_timestamp_ticks = 0xffffffff; +#endif +#endif + ((struct ol_tx_desc_list_elem_t *)(tx_desc->p_link))->next = + pdev->tx_desc.freelist; + pdev->tx_desc.freelist = tx_desc->p_link; + pdev->tx_desc.num_free++; +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) +#ifdef QCA_LL_TX_FLOW_CT + if ( (adf_os_atomic_read(&tx_desc->vdev->os_q_paused)) && + (adf_os_atomic_read(&tx_desc->vdev->tx_desc_count) < + TXRX_HL_TX_FLOW_CTRL_VDEV_LOW_WATER_MARK) ) { + /* wakeup netif_queue */ + adf_os_atomic_set(&tx_desc->vdev->os_q_paused, 0); + tx_desc->vdev->osif_flow_control_cb(tx_desc->vdev->osif_dev, + tx_desc->vdev->vdev_id, A_TRUE); + } +#endif /* QCA_LL_TX_FLOW_CT */ + adf_os_atomic_dec(&tx_desc->vdev->tx_desc_count); +#endif +#if defined(CONFIG_HL_SUPPORT) + tx_desc->vdev = NULL; +#endif + adf_os_spin_unlock_bh(&pdev->tx_mutex); +} + +struct ol_tx_desc_t * +ol_tx_desc_ll( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct ol_tx_desc_t *tx_desc; + unsigned int i; + u_int32_t num_frags; + + msdu_info->htt.info.vdev_id = vdev->vdev_id; + msdu_info->htt.action.cksum_offload = adf_nbuf_get_tx_cksum(netbuf); + switch (adf_nbuf_get_exemption_type(netbuf)) { + case ADF_NBUF_EXEMPT_NO_EXEMPTION: + case ADF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE: + /* We want to encrypt this frame */ + msdu_info->htt.action.do_encrypt = 1; + break; + case ADF_NBUF_EXEMPT_ALWAYS: + /* We don't want to encrypt this frame */ + msdu_info->htt.action.do_encrypt = 0; + break; + default: + adf_os_assert(0); + break; + } + + /* allocate the descriptor */ + tx_desc = ol_tx_desc_alloc(pdev, vdev); + if (!tx_desc) return NULL; + + /* initialize the SW tx descriptor */ + tx_desc->netbuf = netbuf; + /* fix this - get pkt_type from msdu_info */ + tx_desc->pkt_type = ol_tx_frm_std; + + /* initialize the HW tx descriptor */ + htt_tx_desc_init( + pdev->htt_pdev, tx_desc->htt_tx_desc, + tx_desc->htt_tx_desc_paddr, + ol_tx_desc_id(pdev, tx_desc), + netbuf, + &msdu_info->htt, NULL, vdev->opmode == wlan_op_mode_ocb); + + /* + * Initialize the fragmentation descriptor. + * Skip the prefix fragment (HTT tx descriptor) that was added + * during the call to htt_tx_desc_init above. + */ + num_frags = adf_nbuf_get_num_frags(netbuf); + /* num_frags are expected to be 2 max */ + num_frags = (num_frags > CVG_NBUF_MAX_EXTRA_FRAGS) ? CVG_NBUF_MAX_EXTRA_FRAGS : num_frags; + htt_tx_desc_num_frags(pdev->htt_pdev, tx_desc->htt_tx_desc, num_frags-1); + for (i = 1; i < num_frags; i++) { + adf_os_size_t frag_len; + u_int32_t frag_paddr; + + frag_len = adf_nbuf_get_frag_len(netbuf, i); + frag_paddr = adf_nbuf_get_frag_paddr_lo(netbuf, i); + htt_tx_desc_frag( + pdev->htt_pdev, tx_desc->htt_tx_desc, i-1, frag_paddr, frag_len); + } + return tx_desc; +} + +struct ol_tx_desc_t * +ol_tx_desc_hl( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct ol_tx_desc_t *tx_desc; + + /* FIX THIS: these inits should probably be done by tx classify */ + msdu_info->htt.info.vdev_id = vdev->vdev_id; + msdu_info->htt.info.frame_type = pdev->htt_pkt_type; + msdu_info->htt.action.cksum_offload = adf_nbuf_get_tx_cksum(netbuf); + switch (adf_nbuf_get_exemption_type(netbuf)) { + case ADF_NBUF_EXEMPT_NO_EXEMPTION: + case ADF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE: + /* We want to encrypt this frame */ + msdu_info->htt.action.do_encrypt = 1; + break; + case ADF_NBUF_EXEMPT_ALWAYS: + /* We don't want to encrypt this frame */ + msdu_info->htt.action.do_encrypt = 0; + break; + default: + adf_os_assert(0); + break; + } + + /* allocate the descriptor */ + tx_desc = ol_tx_desc_alloc_hl(pdev, vdev); + if (!tx_desc) return NULL; + + /* initialize the SW tx descriptor */ + tx_desc->netbuf = netbuf; + /* fix this - get pkt_type from msdu_info */ + tx_desc->pkt_type = ol_tx_frm_std; + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + tx_desc->orig_l2_hdr_bytes = 0; +#endif + /* the HW tx descriptor will be initialized later by the caller */ + + return tx_desc; +} + +void ol_tx_desc_frame_list_free( + struct ol_txrx_pdev_t *pdev, + ol_tx_desc_list *tx_descs, + int had_error) +{ + struct ol_tx_desc_t *tx_desc, *tmp; + adf_nbuf_t msdus = NULL; + + TAILQ_FOREACH_SAFE(tx_desc, tx_descs, tx_desc_list_elem, tmp) { + adf_nbuf_t msdu = tx_desc->netbuf; + + adf_os_atomic_init(&tx_desc->ref_cnt); /* clear the ref cnt */ +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + OL_TX_RESTORE_HDR(tx_desc, msdu); /* restore original hdr offset */ +#endif + adf_nbuf_unmap(pdev->osdev, msdu, ADF_OS_DMA_TO_DEVICE); + /* free the tx desc */ + ol_tx_desc_free(pdev, tx_desc); + /* link the netbuf into a list to free as a batch */ + adf_nbuf_set_next(msdu, msdus); + msdus = msdu; + } + /* free the netbufs as a batch */ + adf_nbuf_tx_free(msdus, had_error); +} + +void ol_tx_desc_frame_free_nonstd( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + int had_error) +{ + int mgmt_type; + ol_txrx_mgmt_tx_cb ota_ack_cb; + char *trace_str; + + adf_os_atomic_init(&tx_desc->ref_cnt); /* clear the ref cnt */ +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + OL_TX_RESTORE_HDR(tx_desc, (tx_desc->netbuf)); /* restore original hdr offset */ +#endif + trace_str = (had_error) ? "OT:C:F:" : "OT:C:S:"; + adf_nbuf_trace_update(tx_desc->netbuf, trace_str); + if (tx_desc->pkt_type == ol_tx_frm_no_free) { + /* free the tx desc but don't unmap or free the frame */ + if (pdev->tx_data_callback.func) { + adf_nbuf_set_next(tx_desc->netbuf, NULL); + pdev->tx_data_callback.func( + pdev->tx_data_callback.ctxt, tx_desc->netbuf, had_error); + ol_tx_desc_free(pdev, tx_desc); + return; + } + /* let the code below unmap and free the frame */ + } + adf_nbuf_unmap(pdev->osdev, tx_desc->netbuf, ADF_OS_DMA_TO_DEVICE); + /* check the frame type to see what kind of special steps are needed */ + if (tx_desc->pkt_type == ol_tx_frm_tso) { +#if 0 + /* + * Free the segment's customized ethernet+IP+TCP header. + * Fragment 0 added by the WLAN driver is the HTT+HTC tx descriptor. + * Fragment 1 added by the WLAN driver is the Ethernet+IP+TCP header + * added for this TSO segment. + */ + tso_tcp_hdr = adf_nbuf_get_frag_vaddr(tx_desc->netbuf, 1); + ol_tx_tso_hdr_free(pdev, tso_tcp_hdr); +#endif + /* free the netbuf */ + adf_nbuf_set_next(tx_desc->netbuf, NULL); + adf_nbuf_tx_free(tx_desc->netbuf, had_error); + } else if ((tx_desc->pkt_type >= OL_TXRX_MGMT_TYPE_BASE) && + (tx_desc->pkt_type != 0xff)) { + /* FIX THIS - + * The FW currently has trouble using the host's fragments table + * for management frames. Until this is fixed, rather than + * specifying the fragment table to the FW, the host SW will + * specify just the address of the initial fragment. + * Now that the mgmt frame is done, the HTT tx desc's frags table + * pointer needs to be reset. + */ + htt_tx_desc_frags_table_set(pdev->htt_pdev, tx_desc->htt_tx_desc, 0, 1); + + mgmt_type = tx_desc->pkt_type - OL_TXRX_MGMT_TYPE_BASE; + /* + * we already checked the value when the mgmt frame was provided to the txrx layer. + * no need to check it a 2nd time. + */ + ota_ack_cb = pdev->tx_mgmt.callbacks[mgmt_type].ota_ack_cb; + if (ota_ack_cb) { + void *ctxt; + ctxt = pdev->tx_mgmt.callbacks[mgmt_type].ctxt; + ota_ack_cb(ctxt, tx_desc->netbuf, had_error); + } + /* free the netbuf */ + adf_nbuf_free(tx_desc->netbuf); + } else { + /* single regular frame */ + adf_nbuf_set_next(tx_desc->netbuf, NULL); + adf_nbuf_tx_free(tx_desc->netbuf, had_error); + } + /* free the tx desc */ + ol_tx_desc_free(pdev, tx_desc); +} diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.h new file mode 100644 index 000000000000..8e7ebb700719 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_desc.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_tx_desc.h + * @brief API definitions for the tx descriptor module within the data SW. + */ +#ifndef _OL_TX_DESC__H_ +#define _OL_TX_DESC__H_ + +#include /* TAILQ_HEAD */ +#include /* adf_nbuf_t */ +#include /* ol_tx_desc_t */ +#include /*TXRX_ASSERT2 */ + +/** + * @brief Allocate and initialize a tx descriptor for a LL system. + * @details + * Allocate a tx descriptor pair for a new tx frame - a SW tx descriptor + * for private use within the host data SW, and a HTT tx descriptor for + * downloading tx meta-data to the target FW/HW. + * Fill in the fields of this pair of tx descriptors based on the + * information in the netbuf. + * For LL, this includes filling in a fragmentation descriptor to + * specify to the MAC HW where to find the tx frame's fragments. + * + * @param pdev - the data physical device sending the data + * (for accessing the tx desc pool) + * @param vdev - the virtual device sending the data + * (for specifying the transmitter address for multicast / broadcast data) + * @param netbuf - the tx frame + * @param msdu_info - tx meta-data + */ +struct ol_tx_desc_t * +ol_tx_desc_ll( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *msdu_info); + +/** + * @brief Allocate and initialize a tx descriptor for a HL system. + * @details + * Allocate a tx descriptor pair for a new tx frame - a SW tx descriptor + * for private use within the host data SW, and a HTT tx descriptor for + * downloading tx meta-data to the target FW/HW. + * Fill in the fields of this pair of tx descriptors based on the + * information in the netbuf. + * + * @param pdev - the data physical device sending the data + * (for accessing the tx desc pool) + * @param vdev - the virtual device sending the data + * (for specifying the transmitter address for multicast / broadcast data) + * @param netbuf - the tx frame + * @param msdu_info - tx meta-data + */ +struct ol_tx_desc_t * +ol_tx_desc_hl( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *msdu_info); + +/** + * @brief Use a tx descriptor ID to find the corresponding desriptor object. + * + * @param pdev - the data physical device sending the data + * @param tx_desc_id - the ID of the descriptor in question + * @return the descriptor object that has the specified ID + */ +struct ol_tx_desc_t * +ol_tx_desc_find(struct ol_txrx_pdev_t *pdev, u_int16_t tx_desc_id); + +/** + * @brief Free a list of tx descriptors and the tx frames they refer to. + * @details + * Free a batch of "standard" tx descriptors and their tx frames. + * Free each tx descriptor, by returning it to the freelist. + * Unmap each netbuf, and free the netbufs as a batch. + * Irregular tx frames like TSO or managment frames that require + * special handling are processed by the ol_tx_desc_frame_free_nonstd + * function rather than this function. + * + * @param pdev - the data physical device that sent the data + * @param tx_descs - a list of SW tx descriptors for the tx frames + * @param had_error - boolean indication of whether the transmission failed. + * This is provided to callback functions that get notified of + * the tx frame completion. + */ +void ol_tx_desc_frame_list_free( + struct ol_txrx_pdev_t *pdev, + ol_tx_desc_list *tx_descs, + int had_error); + +/** + * @brief Free a non-standard tx frame and its tx descriptor. + * @details + * Check the tx frame type (e.g. TSO vs. management) to determine what + * special steps, if any, need to be performed prior to freeing the + * tx frame and its tx descriptor. + * This function can also be used to free single standard tx frames. + * After performing any special steps based on tx frame type, free the + * tx descriptor, i.e. return it to the freelist, and unmap and + * free the netbuf referenced by the tx descriptor. + * + * @param pdev - the data physical device that sent the data + * @param tx_desc - the SW tx descriptor for the tx frame that was sent + * @param had_error - boolean indication of whether the transmission failed. + * This is provided to callback functions that get notified of + * the tx frame completion. + */ +void ol_tx_desc_frame_free_nonstd( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + int had_error); + +/* + * @brief Determine the ID of a tx descriptor. + * + * @param pdev - the physical device that is sending the data + * @param tx_desc - the descriptor whose ID is being determined + * @return numeric ID that uniquely identifies the tx descriptor + */ +static inline u_int16_t +ol_tx_desc_id(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + TXRX_ASSERT2(tx_desc->id < pdev->tx_desc.pool_size); + return tx_desc->id; +} +/* + * @brief Retrieves the beacon headr for the vdev + * @param pdev - opaque pointe to scn + * @param vdevid - vdev id + * @return void pointer to the beacon header for the given vdev + */ + +void * +ol_ath_get_bcn_header(ol_pdev_handle pdev, A_UINT32 vdev_id); + +/* + * @brief Free a tx descriptor, without freeing the matching frame. + * @details + * This function is using during the function call that submits tx frames + * into the txrx layer, for cases where a tx descriptor is successfully + * allocated, but for other reasons the frame could not be accepted. + * + * @param pdev - the data physical device that is sending the data + * @param tx_desc - the descriptor being freed + */ +void +ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc); + +#endif /* _OL_TX_DESC__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c new file mode 100644 index 000000000000..26ce39279999 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c @@ -0,0 +1,1943 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_atomic_add, etc. */ +#include /* ol_cfg_addba_retry */ +#include /* HTT_TX_EXT_TID_MGMT */ +#include /* htt_tx_desc_tid */ +#include /* ol_txrx_vdev_handle */ +#include /* ol_txrx_sync, ol_tx_addba_conf */ +#include /* ol_ctrl_addba_req */ +#include /* TXRX_ASSERT1, etc. */ +#include /* pdev stats */ +#include /* ol_tx_desc, ol_tx_desc_frame_list_free */ +#include /* ol_tx_vdev_ll_pause_queue_send */ +#include /* ol_tx_sched_notify, etc. */ +#include +#include /* DEBUG_HL_LOGGING */ +#include /* ol_tx_desc_pool_size_hl */ +#include /* a_bool_t */ +#include + + +#if defined(CONFIG_HL_SUPPORT) + +#ifndef offsetof +#define offsetof(type, field) ((adf_os_size_t)(&((type *)0)->field)) +#endif + +/*--- function prototypes for optional queue log feature --------------------*/ +#if defined(DEBUG_HL_LOGGING) + +void +ol_tx_queue_log_enqueue( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_msdu_info_t *msdu_info, + int frms, int bytes); +void +ol_tx_queue_log_dequeue( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int frms, int bytes); +void +ol_tx_queue_log_free( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid, int frms, int bytes); +#define OL_TX_QUEUE_LOG_ENQUEUE ol_tx_queue_log_enqueue +#define OL_TX_QUEUE_LOG_DEQUEUE ol_tx_queue_log_dequeue +#define OL_TX_QUEUE_LOG_FREE ol_tx_queue_log_free + +#else + +#define OL_TX_QUEUE_LOG_ENQUEUE(pdev, msdu_info, frms, bytes) /* no-op */ +#define OL_TX_QUEUE_LOG_DEQUEUE(pdev, txq, frms, bytes) /* no-op */ +#define OL_TX_QUEUE_LOG_FREE(pdev, txq, tid, frms, bytes) /* no-op */ + +#endif /* TXRX_DEBUG_LEVEL > 5 */ + + +/*--- function prototypes for optional host ADDBA negotiation ---------------*/ + +#define OL_TX_QUEUE_ADDBA_CHECK(pdev, txq, tx_msdu_info) /* no-op */ + + +#ifndef container_of +#define container_of(ptr, type, member) ((type *)( \ + (char *)(ptr) - (char *)(&((type *)0)->member) ) ) +#endif +/*--- function definitions --------------------------------------------------*/ + +/* + * Try to flush pending frames in the tx queues + * no matter it's queued in the TX scheduler or not. + */ +static inline void +ol_tx_queue_vdev_flush(struct ol_txrx_pdev_t *pdev, struct ol_txrx_vdev_t *vdev) +{ +#define PEER_ARRAY_COUNT 10 + struct ol_tx_frms_queue_t *txq; + struct ol_txrx_peer_t *peer, *peers[PEER_ARRAY_COUNT]; + int i, j, peer_count; + + /* flush VDEV TX queues */ + for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { + txq = &vdev->txqs[i]; + ol_tx_queue_free(pdev, txq, (i + OL_TX_NUM_TIDS)); + } + /* flush PEER TX queues */ + do { + peer_count = 0; + /* select candidate peers */ + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + for (i = 0; i < OL_TX_NUM_TIDS; i++) { + txq = &peer->txqs[i]; + if (txq->frms) { + adf_os_atomic_inc(&peer->ref_cnt); + peers[peer_count++] = peer; + break; + } + } + if (peer_count >= PEER_ARRAY_COUNT) { + break; + } + } + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + /* flush TX queues of candidate peers */ + for (i = 0; i < peer_count; i++) { + for (j = 0; j < OL_TX_NUM_TIDS; j++) { + txq = &peers[i]->txqs[j]; + if (txq->frms) { + ol_tx_queue_free(pdev, txq, j); + } + } + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: Delete Peer %p\n", __func__, peer); + ol_txrx_peer_unref_delete(peers[i]); + } + } while (peer_count >= PEER_ARRAY_COUNT); +} + +static inline void +ol_tx_queue_flush(struct ol_txrx_pdev_t *pdev) +{ + struct ol_txrx_vdev_t *vdev; + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + ol_tx_queue_vdev_flush(pdev, vdev); + } +} + +void +ol_tx_queue_discard( + struct ol_txrx_pdev_t *pdev, + a_bool_t flush_all, + ol_tx_desc_list *tx_descs) +{ + u_int16_t num; + u_int16_t discarded, actual_discarded = 0; + + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + + if (flush_all == A_TRUE) { + /* flush all the pending tx queues in the scheduler */ + num = ol_tx_desc_pool_size_hl(pdev->ctrl_pdev) - + adf_os_atomic_read(&pdev->tx_queue.rsrc_cnt); + } else { + num = pdev->tx_queue.rsrc_threshold_hi - + pdev->tx_queue.rsrc_threshold_lo; + } + TX_SCHED_DEBUG_PRINT("+%s : %u\n,", __FUNCTION__, + adf_os_atomic_read(&pdev->tx_queue.rsrc_cnt)); + while (num > 0) { + discarded = ol_tx_sched_discard_select( + pdev, (u_int16_t)num, tx_descs, flush_all); + if (discarded == 0) { + /* + * No more packets could be discarded. + * Probably tx queues are empty. + */ + break; + } + num -= discarded; + actual_discarded += discarded; + } + adf_os_atomic_add(actual_discarded, &pdev->tx_queue.rsrc_cnt); + TX_SCHED_DEBUG_PRINT("-%s \n",__FUNCTION__); + + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + + if (flush_all == A_TRUE && num > 0) { + /* + * try to flush pending frames in the tx queues + * which are not queued in the TX scheduler. + */ + ol_tx_queue_flush(pdev); + } +} + +void +ol_tx_enqueue( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + struct ol_tx_desc_t *tx_desc, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + int bytes; + struct ol_tx_sched_notify_ctx_t notify_ctx; +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + ol_txrx_vdev_handle vdev; +#endif + + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + + /* + * If too few tx descriptors are available, drop some currently-queued + * tx frames, to provide enough tx descriptors for new frames, which + * may be higher priority than the current frames. + */ +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + vdev = tx_desc->vdev; + if (adf_os_atomic_read(&vdev->tx_desc_count) > + ((ol_tx_desc_pool_size_hl(pdev->ctrl_pdev) >> 1) + - TXRX_HL_TX_FLOW_CTRL_MGMT_RESERVED)) { +#else + if (adf_os_atomic_read(&pdev->tx_queue.rsrc_cnt) <= + pdev->tx_queue.rsrc_threshold_lo) + { +#endif + ol_tx_desc_list tx_descs; + TAILQ_INIT(&tx_descs); + ol_tx_queue_discard(pdev, A_FALSE, &tx_descs); + //Discard Frames in Discard List + ol_tx_desc_frame_list_free(pdev, &tx_descs, 1 /* error */); + } + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + TAILQ_INSERT_TAIL(&txq->head, tx_desc, tx_desc_list_elem); + + bytes = adf_nbuf_len(tx_desc->netbuf); + txq->frms++; + txq->bytes += bytes; + OL_TX_QUEUE_LOG_ENQUEUE(pdev, tx_msdu_info, 1, bytes); + + if (txq->flag != ol_tx_queue_paused) { + notify_ctx.event = OL_TX_ENQUEUE_FRAME; + notify_ctx.frames = 1; + notify_ctx.bytes = adf_nbuf_len(tx_desc->netbuf); + notify_ctx.txq = txq; + notify_ctx.info.tx_msdu_info = tx_msdu_info; + ol_tx_sched_notify(pdev, ¬ify_ctx); + txq->flag = ol_tx_queue_active; + } + + if (!ETHERTYPE_IS_EAPOL_WAPI(tx_msdu_info->htt.info.ethertype)) { + OL_TX_QUEUE_ADDBA_CHECK(pdev, txq, tx_msdu_info); + } + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +u_int16_t +ol_tx_dequeue( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + ol_tx_desc_list *head, + u_int16_t max_frames, + u_int32_t *credit, + int *bytes) +{ + u_int16_t num_frames; + int bytes_sum; + unsigned credit_sum; + + TXRX_ASSERT2(txq->flag != ol_tx_queue_paused); + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + + if (txq->frms < max_frames) { + max_frames = txq->frms; + } + bytes_sum = 0; + credit_sum = 0; + for (num_frames = 0; num_frames < max_frames; num_frames++) { + unsigned frame_credit; + struct ol_tx_desc_t *tx_desc; + tx_desc = TAILQ_FIRST(&txq->head); + + frame_credit = htt_tx_msdu_credit(tx_desc->netbuf); + if (credit_sum + frame_credit > *credit) { + break; + } + credit_sum += frame_credit; + bytes_sum += adf_nbuf_len(tx_desc->netbuf); + TAILQ_REMOVE(&txq->head, tx_desc, tx_desc_list_elem); + TAILQ_INSERT_TAIL(head, tx_desc, tx_desc_list_elem); + } + txq->frms -= num_frames; + txq->bytes -= bytes_sum; + /* a paused queue remains paused, regardless of whether it has frames */ + if (txq->frms == 0 && txq->flag == ol_tx_queue_active) { + txq->flag = ol_tx_queue_empty; + } + OL_TX_QUEUE_LOG_DEQUEUE(pdev, txq, num_frames, bytes_sum); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); + + *bytes = bytes_sum; + *credit = credit_sum; + return num_frames; +} + +void +ol_tx_queue_free( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid) +{ + int frms = 0, bytes = 0; + struct ol_tx_desc_t *tx_desc; + struct ol_tx_sched_notify_ctx_t notify_ctx; + ol_tx_desc_list tx_tmp_list; + + TAILQ_INIT(&tx_tmp_list); + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + + notify_ctx.event = OL_TX_DELETE_QUEUE; + notify_ctx.txq = txq; + notify_ctx.info.ext_tid = tid; + ol_tx_sched_notify(pdev, ¬ify_ctx); + + frms = txq->frms; + tx_desc = TAILQ_FIRST(&txq->head); + while (txq->frms) { + bytes += adf_nbuf_len(tx_desc->netbuf); + txq->frms--; + tx_desc = TAILQ_NEXT(tx_desc, tx_desc_list_elem); + } + OL_TX_QUEUE_LOG_FREE(pdev, txq, tid, frms, bytes); + txq->bytes -= bytes; + OL_TX_QUEUE_LOG_FREE(pdev, txq, tid, frms, bytes); + txq->flag = ol_tx_queue_empty; + /* txq->head gets reset during the TAILQ_CONCAT call */ + TAILQ_CONCAT(&tx_tmp_list, &txq->head, tx_desc_list_elem); + + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + /* free tx frames without holding tx_queue_spinlock */ + adf_os_atomic_add(frms, &pdev->tx_queue.rsrc_cnt); + while (frms) { + tx_desc = TAILQ_FIRST(&tx_tmp_list); + TAILQ_REMOVE(&tx_tmp_list, tx_desc, tx_desc_list_elem); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 0); + frms--; + } + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + + +/*--- queue pause / unpause functions ---------------------------------------*/ + +static inline void +ol_txrx_peer_tid_pause_base( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + int tid) +{ + struct ol_tx_frms_queue_t *txq = &peer->txqs[tid]; + + if (txq->paused_count.total++ == 0) { + struct ol_tx_sched_notify_ctx_t notify_ctx; + + notify_ctx.event = OL_TX_PAUSE_QUEUE; + notify_ctx.txq = txq; + notify_ctx.info.ext_tid = tid; + ol_tx_sched_notify(pdev, ¬ify_ctx); + txq->flag = ol_tx_queue_paused; + } +} + +static inline void +ol_txrx_peer_pause_but_no_mgmt_q_base( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + int i; + for (i = 0; i < OL_TX_MGMT_TID; i++) { + ol_txrx_peer_tid_pause_base(pdev, peer, i); + } +} + +static inline void +ol_txrx_peer_pause_base( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + int i; + for (i = 0; i < ARRAY_LEN(peer->txqs); i++) { + ol_txrx_peer_tid_pause_base(pdev, peer, i); + } +} + +static inline void +ol_txrx_peer_tid_unpause_base( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + int tid) +{ + struct ol_tx_frms_queue_t *txq = &peer->txqs[tid]; + /* + * Don't actually unpause the tx queue until all pause requests + * have been removed. + */ + TXRX_ASSERT2(txq->paused_count.total > 0); + /* return, if not already paused */ + if (txq->paused_count.total == 0) + return; + + if (--txq->paused_count.total == 0) { + struct ol_tx_sched_notify_ctx_t notify_ctx; + + notify_ctx.event = OL_TX_UNPAUSE_QUEUE; + notify_ctx.txq = txq; + notify_ctx.info.ext_tid = tid; + ol_tx_sched_notify(pdev, ¬ify_ctx); + + if (txq->frms == 0) { + txq->flag = ol_tx_queue_empty; + } else { + txq->flag = ol_tx_queue_active; + /* + * Now that the are new tx frames available to download, + * invoke the scheduling function, to see if it wants to + * download the new frames. + * Since the queue lock is currently held, and since + * the scheduler function takes the lock, temporarily + * release the lock. + */ + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + ol_tx_sched(pdev); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + } + } +} + +static inline void +ol_txrx_peer_unpause_but_no_mgmt_q_base( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + int i; + for (i = 0; i < OL_TX_MGMT_TID; i++) { + ol_txrx_peer_tid_unpause_base(pdev, peer, i); + } +} + +void +ol_txrx_peer_tid_unpause(ol_txrx_peer_handle peer, int tid) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + + /* TO DO: log the queue unpause */ + + /* acquire the mutex lock, since we'll be modifying the queues */ + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + + if (tid == -1) { + int i; + for (i = 0; i < ARRAY_LEN(peer->txqs); i++) { + ol_txrx_peer_tid_unpause_base(pdev, peer, i); + } + } else { + ol_txrx_peer_tid_unpause_base(pdev, peer, tid); + } + + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void +ol_txrx_throttle_pause(ol_txrx_pdev_handle pdev) +{ +#if defined(QCA_SUPPORT_TX_THROTTLE) + adf_os_spin_lock_bh(&pdev->tx_throttle.mutex); + + if (pdev->tx_throttle.is_paused == TRUE) { + adf_os_spin_unlock_bh(&pdev->tx_throttle.mutex); + return; + } + + pdev->tx_throttle.is_paused = TRUE; + adf_os_spin_unlock_bh(&pdev->tx_throttle.mutex); +#endif + ol_txrx_pdev_pause(pdev, 0); +} + +void +ol_txrx_throttle_unpause(ol_txrx_pdev_handle pdev) +{ +#if defined(QCA_SUPPORT_TX_THROTTLE) + adf_os_spin_lock_bh(&pdev->tx_throttle.mutex); + + if (pdev->tx_throttle.is_paused == FALSE) { + adf_os_spin_unlock_bh(&pdev->tx_throttle.mutex); + return; + } + + pdev->tx_throttle.is_paused = FALSE; + adf_os_spin_unlock_bh(&pdev->tx_throttle.mutex); +#endif + ol_txrx_pdev_unpause(pdev, 0); +} +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +/** + * ol_txrx_pdev_pause() - Suspend all tx data for the specified physical device. + * @data_pdev: the physical device being paused. + * @reason: pause reason. + * + * This function applies to HL systems - + * in LL systems, applies when txrx_vdev_pause_all is enabled. + * In some systems it is necessary to be able to temporarily + * suspend all WLAN traffic, e.g. to allow another device such as bluetooth + * to temporarily have exclusive access to shared RF chain resources. + * This function suspends tx traffic within the specified physical device. + * + * + * Return: None + */ +void +ol_txrx_pdev_pause(ol_txrx_pdev_handle pdev, u_int32_t reason) +{ + struct ol_txrx_vdev_t *vdev = NULL, *tmp; + + TAILQ_FOREACH_SAFE(vdev, &pdev->vdev_list, vdev_list_elem, tmp) { + ol_txrx_vdev_pause(vdev, reason); + } +} + +/** + * ol_txrx_pdev_unpause() - Resume tx for the specified physical device.. + * @data_pdev: the physical device being paused. + * @reason: pause reason. + * + * This function applies to HL systems - + * in LL systems, applies when txrx_vdev_pause_all is enabled. + * + * + * Return: None + */ +void +ol_txrx_pdev_unpause(ol_txrx_pdev_handle pdev, u_int32_t reason) +{ + struct ol_txrx_vdev_t *vdev = NULL, *tmp; + + TAILQ_FOREACH_SAFE(vdev, &pdev->vdev_list, vdev_list_elem, tmp) { + ol_txrx_vdev_unpause(vdev, reason); + } +} + +#ifdef QCA_BAD_PEER_TX_FLOW_CL + +/** + * ol_txrx_peer_bal_add_limit_peer() - add one peer into limit list + * @pdev: Pointer to PDEV structure. + * @peer_id: Peer Identifier. + * @peer_limit Peer limit threshold + * + * Add one peer into the limit list of pdev + * Note that the peer limit info will be also updated + * If it is the first time, start the timer + * + * Return: None + */ +void +ol_txrx_peer_bal_add_limit_peer(struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id, u_int16_t peer_limit) +{ + u_int16_t i, existed = 0; + struct ol_txrx_peer_t *peer = NULL; + + for (i = 0; i < pdev->tx_peer_bal.peer_num; i++){ + if (pdev->tx_peer_bal.limit_list[i].peer_id == peer_id) { + existed = 1; + break; + } + } + + if (!existed) { + u_int32_t peer_num = pdev->tx_peer_bal.peer_num; + /* Check if peer_num has reached the capabilit */ + if (peer_num >= MAX_NO_PEERS_IN_LIMIT) { + TX_SCHED_DEBUG_PRINT_ALWAYS( + "reach the maxinum peer num %d\n", + peer_num); + return; + } + + pdev->tx_peer_bal.limit_list[peer_num].peer_id = peer_id; + pdev->tx_peer_bal.limit_list[peer_num].limit_flag = TRUE; + pdev->tx_peer_bal.limit_list[peer_num].limit = peer_limit; + pdev->tx_peer_bal.peer_num++; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer) { + peer->tx_limit_flag = TRUE; + peer->tx_limit = peer_limit; + } + + TX_SCHED_DEBUG_PRINT_ALWAYS( + "Add one peer into limit queue, peer_id %d, cur peer num %d\n", + peer_id, + pdev->tx_peer_bal.peer_num); + } + + /* Only start the timer once */ + if (pdev->tx_peer_bal.peer_bal_timer_state == + ol_tx_peer_bal_timer_inactive) { + adf_os_timer_start(&pdev->tx_peer_bal.peer_bal_timer, + pdev->tx_peer_bal.peer_bal_period_ms); + pdev->tx_peer_bal.peer_bal_timer_state = + ol_tx_peer_bal_timer_active; + } +} + +/** + * ol_txrx_peer_bal_remove_limit_peer() - remove one peer from limit list + * @pdev: Pointer to PDEV structure. + * @peer_id: Peer Identifier. + * + * Remove one peer from the limit list of pdev + * Note that Only stop the timer if no peer in limit state + * + * Return: NULL + */ +void +ol_txrx_peer_bal_remove_limit_peer(struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id) +{ + u_int16_t i; + struct ol_txrx_peer_t *peer = NULL; + + for (i = 0; i < pdev->tx_peer_bal.peer_num; i++) { + if ( pdev->tx_peer_bal.limit_list[i].peer_id == peer_id) { + pdev->tx_peer_bal.limit_list[i] = + pdev->tx_peer_bal.limit_list[pdev->tx_peer_bal.peer_num - 1]; + pdev->tx_peer_bal.peer_num--; + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer) { + peer->tx_limit_flag = FALSE; + } + + TX_SCHED_DEBUG_PRINT( + "Remove one peer from limitq, peer_id %d, cur peer num %d\n", + peer_id, + pdev->tx_peer_bal.peer_num); + break; + } + } + + /* Only stop the timer if no peer in limit state */ + if (pdev->tx_peer_bal.peer_num == 0) { + adf_os_timer_cancel(&pdev->tx_peer_bal.peer_bal_timer); + pdev->tx_peer_bal.peer_bal_timer_state = + ol_tx_peer_bal_timer_inactive; + } +} + +void +ol_txrx_peer_pause_but_no_mgmt_q(ol_txrx_peer_handle peer) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + + /* TO DO: log the queue pause */ + + /* acquire the mutex lock, since we'll be modifying the queues */ + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + + ol_txrx_peer_pause_but_no_mgmt_q_base(pdev, peer); + + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void +ol_txrx_peer_unpause_but_no_mgmt_q(ol_txrx_peer_handle peer) +{ + struct ol_txrx_pdev_t *pdev = peer->vdev->pdev; + + /* TO DO: log the queue pause */ + + /* acquire the mutex lock, since we'll be modifying the queues */ + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + + ol_txrx_peer_unpause_but_no_mgmt_q_base(pdev, peer); + + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +u_int16_t +ol_tx_bad_peer_dequeue_check(struct ol_tx_frms_queue_t *txq, + u_int16_t max_frames, + u_int16_t *tx_limit_flag) +{ + if (txq && (txq->peer) && (txq->peer->tx_limit_flag) + && (txq->peer->tx_limit < max_frames)) { + TX_SCHED_DEBUG_PRINT("Peer ID %d goes to limit, threshold is %d\n", + txq->peer->peer_ids[0], txq->peer->tx_limit); + *tx_limit_flag = 1; + return txq->peer->tx_limit; + } else { + return max_frames; + } +} + +void +ol_tx_bad_peer_update_tx_limit(struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u_int16_t frames, + u_int16_t tx_limit_flag) +{ + adf_os_spin_lock_bh(&pdev->tx_peer_bal.mutex); + if (txq && tx_limit_flag && (txq->peer) && (txq->peer->tx_limit_flag)) { + if (txq->peer->tx_limit < frames) { + txq->peer->tx_limit = 0; + } else { + txq->peer->tx_limit -= frames; + } + TX_SCHED_DEBUG_PRINT_ALWAYS("Peer ID %d in limit, deque %d frms\n", + txq->peer->peer_ids[0], frames); + } else if (txq->peer) { + TX_SCHED_DEBUG_PRINT("Download peer_id %d, num_frames %d\n", + txq->peer->peer_ids[0], frames); + } + adf_os_spin_unlock_bh(&pdev->tx_peer_bal.mutex); +} + +void +ol_txrx_bad_peer_txctl_set_setting(struct ol_txrx_pdev_t *pdev, + int enable, int period, int txq_limit) +{ + if (enable) { + pdev->tx_peer_bal.enabled = ol_tx_peer_bal_enable; + } else { + pdev->tx_peer_bal.enabled = ol_tx_peer_bal_disable; + } + /* Set the current settingl */ + pdev->tx_peer_bal.peer_bal_period_ms = period; + pdev->tx_peer_bal.peer_bal_txq_limit = txq_limit; +} + +void +ol_txrx_bad_peer_txctl_update_threshold(struct ol_txrx_pdev_t *pdev, + int level, int tput_thresh, int tx_limit) +{ + /* Set the current settingl */ + pdev->tx_peer_bal.ctl_thresh[level].tput_thresh = + tput_thresh; + pdev->tx_peer_bal.ctl_thresh[level].tx_limit = + tx_limit; +} + +void +ol_tx_pdev_peer_bal_timer(void *context) +{ + int i; + struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)context; + + adf_os_spin_lock_bh(&pdev->tx_peer_bal.mutex); + + for (i = 0; i < pdev->tx_peer_bal.peer_num; i++) { + if (pdev->tx_peer_bal.limit_list[i].limit_flag) { + u_int16_t peer_id = + pdev->tx_peer_bal.limit_list[i].peer_id; + u_int16_t tx_limit = + pdev->tx_peer_bal.limit_list[i].limit; + + struct ol_txrx_peer_t *peer = NULL; + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + TX_SCHED_DEBUG_PRINT("%s peer_id %d peer = 0x%x tx limit %d\n", + __FUNCTION__, peer_id, + (int)peer, tx_limit); + + /* It is possible the peer limit is still not 0, + but it is the scenario should not be cared */ + if (peer) { + peer->tx_limit = tx_limit; + } else { + ol_txrx_peer_bal_remove_limit_peer(pdev, + peer_id); + TX_SCHED_DEBUG_PRINT_ALWAYS("No such a peer, peer id = %d\n", + peer_id); + } + } + } + + adf_os_spin_unlock_bh(&pdev->tx_peer_bal.mutex); + + if (pdev->tx_peer_bal.peer_num) { + ol_tx_sched(pdev); + adf_os_timer_start(&pdev->tx_peer_bal.peer_bal_timer, + pdev->tx_peer_bal.peer_bal_period_ms); + } +} + +void +ol_txrx_set_txq_peer( + struct ol_tx_frms_queue_t *txq, + struct ol_txrx_peer_t *peer) +{ + if (txq) { + txq->peer = peer; + } +} + +void ol_tx_badpeer_flow_cl_init(struct ol_txrx_pdev_t *pdev) +{ + u_int32_t timer_period; + + adf_os_spinlock_init(&pdev->tx_peer_bal.mutex); + pdev->tx_peer_bal.peer_num = 0; + pdev->tx_peer_bal.peer_bal_timer_state + = ol_tx_peer_bal_timer_inactive; + + timer_period = 2000; + pdev->tx_peer_bal.peer_bal_period_ms = timer_period; + + adf_os_timer_init( + pdev->osdev, + &pdev->tx_peer_bal.peer_bal_timer, + ol_tx_pdev_peer_bal_timer, + pdev); +} + +void ol_tx_badpeer_flow_cl_deinit(struct ol_txrx_pdev_t *pdev) +{ + adf_os_timer_cancel(&pdev->tx_peer_bal.peer_bal_timer); + pdev->tx_peer_bal.peer_bal_timer_state = + ol_tx_peer_bal_timer_inactive; + adf_os_timer_free(&pdev->tx_peer_bal.peer_bal_timer); + adf_os_spinlock_destroy(&pdev->tx_peer_bal.mutex); +} + +void +ol_txrx_peer_link_status_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_num, + struct rate_report_t* peer_link_status) +{ + u_int16_t i = 0; + struct ol_txrx_peer_t *peer = NULL; + + if (NULL == pdev) { + TX_SCHED_DEBUG_PRINT_ALWAYS("Error: NULL pdev handler \n"); + return; + } + + if (NULL == peer_link_status) { + TX_SCHED_DEBUG_PRINT_ALWAYS( + "Error:NULL link report message. peer num %d\n", + peer_num); + return; + } + + /* Check if bad peer tx flow CL is enabled */ + if (pdev->tx_peer_bal.enabled != ol_tx_peer_bal_enable){ + TX_SCHED_DEBUG_PRINT_ALWAYS( + "Bad peer tx flow CL is not enabled, ignore it\n"); + return; + } + + /* Check peer_num is reasonable */ + if (peer_num > MAX_NO_PEERS_IN_LIMIT){ + TX_SCHED_DEBUG_PRINT_ALWAYS( + "%s: Bad peer_num %d \n", __func__, peer_num); + return; + } + + TX_SCHED_DEBUG_PRINT_ALWAYS("%s: peer_num %d\n", __func__, peer_num); + + for (i = 0; i < peer_num; i++) { + u_int16_t peer_limit, peer_id; + u_int16_t pause_flag, unpause_flag; + u_int32_t peer_phy, peer_tput; + + peer_id = peer_link_status->id; + peer_phy = peer_link_status->phy; + peer_tput = peer_link_status->rate; + + TX_SCHED_DEBUG_PRINT("%s: peer id %d tput %d phy %d\n", + __func__, peer_id, peer_tput, peer_phy); + + /* Sanity check for the PHY mode value */ + if (peer_phy > TXRX_IEEE11_AC) { + TX_SCHED_DEBUG_PRINT_ALWAYS( + "%s: PHY value is illegal: %d, and the peer_id %d \n", + __func__, peer_link_status->phy, peer_id); + continue; + } + pause_flag = FALSE; + unpause_flag = FALSE; + peer_limit = 0; + + /* From now on, PHY, PER info should be all fine */ + adf_os_spin_lock_bh(&pdev->tx_peer_bal.mutex); + + /* Update link status analysis for each peer */ + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer) { + u_int32_t thresh, limit, phy; + phy = peer_link_status->phy; + thresh = pdev->tx_peer_bal.ctl_thresh[phy].tput_thresh; + limit = pdev->tx_peer_bal.ctl_thresh[phy].tx_limit; + + if (((peer->tx_pause_flag) || (peer->tx_limit_flag)) + && (peer_tput) && (peer_tput < thresh)) { + peer_limit = limit; + } + + if (peer_limit) { + ol_txrx_peer_bal_add_limit_peer(pdev, peer_id, + peer_limit); + } else if (pdev->tx_peer_bal.peer_num) { + TX_SCHED_DEBUG_PRINT("%s: Check if peer_id %d exit limit\n", + __func__, peer_id); + ol_txrx_peer_bal_remove_limit_peer(pdev, peer_id); + } + if ((peer_tput == 0) && (peer->tx_pause_flag == FALSE)) { + peer->tx_pause_flag = TRUE; + pause_flag = TRUE; + } else if (peer->tx_pause_flag){ + unpause_flag = TRUE; + peer->tx_pause_flag = FALSE; + } + } else { + TX_SCHED_DEBUG_PRINT("%s: Remove peer_id %d from limit list\n", + __func__, peer_id); + ol_txrx_peer_bal_remove_limit_peer(pdev, peer_id); + } + + peer_link_status++; + adf_os_spin_unlock_bh(&pdev->tx_peer_bal.mutex); + if (pause_flag) { + ol_txrx_peer_pause_but_no_mgmt_q(peer); + } else if (unpause_flag) { + ol_txrx_peer_unpause_but_no_mgmt_q(peer); + } + } +} +#endif /* QCA_BAD_PEER_TX_FLOW_CL */ + +void +ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, u_int32_t reason) +{ + /* TO DO: log the queue pause */ + /* acquire the mutex lock, since we'll be modifying the queues */ + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + + if (vdev->pdev->cfg.is_high_latency) { +#if defined(CONFIG_HL_SUPPORT) + struct ol_txrx_pdev_t *pdev = vdev->pdev; + struct ol_txrx_peer_t *peer; + /* use peer_ref_mutex before accessing peer_list */ + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + ol_txrx_peer_pause_base(pdev, peer); + } + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); +#endif /* defined(CONFIG_HL_SUPPORT) */ + } else { + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + vdev->ll_pause.paused_reason |= reason; + vdev->ll_pause.q_pause_cnt++; + vdev->ll_pause.is_q_paused = TRUE; + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + } + + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void +ol_txrx_vdev_unpause(ol_txrx_vdev_handle vdev, u_int32_t reason) +{ + /* TO DO: log the queue unpause */ + /* acquire the mutex lock, since we'll be modifying the queues */ + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + + if (vdev->pdev->cfg.is_high_latency) { +#if defined(CONFIG_HL_SUPPORT) + struct ol_txrx_pdev_t *pdev = vdev->pdev; + struct ol_txrx_peer_t *peer; + + /* take peer_ref_mutex before accessing peer_list */ + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + int i; + for (i = 0; i < ARRAY_LEN(peer->txqs); i++) { + ol_txrx_peer_tid_unpause_base(pdev, peer, i); + } + } + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); +#endif /* defined(CONFIG_HL_SUPPORT) */ + } else { + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.paused_reason & reason) + { + vdev->ll_pause.paused_reason &= ~reason; + vdev->ll_pause.is_q_paused = FALSE; + vdev->ll_pause.q_unpause_cnt++; +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ + if (reason == OL_TXQ_PAUSE_REASON_VDEV_SUSPEND) { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + ol_tx_vdev_ll_pause_start_timer(vdev); + } + else +#endif + if (!vdev->ll_pause.paused_reason) { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + ol_tx_vdev_ll_pause_queue_send(vdev); + } else { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + } + } else { + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + } + } + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void +ol_txrx_vdev_flush(ol_txrx_vdev_handle vdev) +{ + if (vdev->pdev->cfg.is_high_latency) { + #if defined(CONFIG_HL_SUPPORT) + ol_tx_queue_vdev_flush(vdev->pdev, vdev); + #endif + } else { + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + adf_os_timer_cancel(&vdev->ll_pause.timer); + vdev->ll_pause.is_q_timer_on = FALSE; + while (vdev->ll_pause.txq.head) { + adf_nbuf_t next = adf_nbuf_next(vdev->ll_pause.txq.head); + adf_nbuf_set_next(vdev->ll_pause.txq.head, NULL); + adf_nbuf_unmap(vdev->pdev->osdev, vdev->ll_pause.txq.head, + ADF_OS_DMA_TO_DEVICE); + adf_nbuf_tx_free(vdev->ll_pause.txq.head, 1 /* error */); + vdev->ll_pause.txq.head = next; + } + vdev->ll_pause.txq.tail = NULL; + vdev->ll_pause.txq.depth = 0; + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + } +} + +#endif // defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) + +/*--- LL tx throttle queue code --------------------------------------------*/ +#if defined(QCA_SUPPORT_TX_THROTTLE) +u_int8_t ol_tx_pdev_is_target_empty(void) +{ + /* TM TODO */ + return 1; +} + +void ol_tx_pdev_throttle_phase_timer(void *context) +{ + struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)context; + int ms = 0; + throttle_level cur_level; + throttle_phase cur_phase; + + /* update the phase */ + pdev->tx_throttle.current_throttle_phase++; + + if (pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_MAX) { + pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF; + } + + if (pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_OFF) { + if (ol_tx_pdev_is_target_empty(/*pdev*/)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "throttle phase --> OFF\n"); + + if (pdev->cfg.is_high_latency) + ol_txrx_throttle_pause(pdev); + + cur_level = pdev->tx_throttle.current_throttle_level; + cur_phase = pdev->tx_throttle.current_throttle_phase; + ms = pdev->tx_throttle.throttle_time_ms[cur_level][cur_phase]; + if (pdev->tx_throttle.current_throttle_level != + THROTTLE_LEVEL_0) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "start timer %d ms\n", ms); + adf_os_timer_start(&pdev->tx_throttle.phase_timer, ms); + } + } + } + else /* THROTTLE_PHASE_ON */ + { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "throttle phase --> ON\n"); + + if (pdev->cfg.is_high_latency) + ol_txrx_throttle_unpause(pdev); +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ + else + ol_tx_pdev_ll_pause_queue_send_all(pdev); +#endif + + cur_level = pdev->tx_throttle.current_throttle_level; + cur_phase = pdev->tx_throttle.current_throttle_phase; + ms = pdev->tx_throttle.throttle_time_ms[cur_level][cur_phase]; + if (pdev->tx_throttle.current_throttle_level != THROTTLE_LEVEL_0) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "start timer %d ms\n", ms); + adf_os_timer_start(&pdev->tx_throttle.phase_timer, ms); + } + } +} + +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ +void ol_tx_pdev_throttle_tx_timer(void *context) +{ + struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)context; + ol_tx_pdev_ll_pause_queue_send_all(pdev); +} +#endif + +void ol_tx_throttle_set_level(struct ol_txrx_pdev_t *pdev, int level) +{ + int ms = 0; + + if (level >= THROTTLE_LEVEL_MAX) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s invalid throttle level set %d, ignoring\n", + __func__, level); + return; + } + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Setting throttle level %d\n", level); + + /* Set the current throttle level */ + pdev->tx_throttle.current_throttle_level = (throttle_level)level; + + if (pdev->cfg.is_high_latency) { + + adf_os_timer_cancel(&pdev->tx_throttle.phase_timer); + + /* Set the phase */ + if (level != THROTTLE_LEVEL_0) { + pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF; + ms = pdev->tx_throttle.throttle_time_ms[level][THROTTLE_PHASE_OFF]; + /* pause all */ + ol_txrx_throttle_pause(pdev); + } else { + pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_ON; + ms = pdev->tx_throttle.throttle_time_ms[level][THROTTLE_PHASE_ON]; + /* unpause all */ + ol_txrx_throttle_unpause(pdev); + } + } else { + /* Reset the phase */ + pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF; + + /* Start with the new time */ + ms = pdev->tx_throttle.throttle_time_ms[level][THROTTLE_PHASE_OFF]; + + adf_os_timer_cancel(&pdev->tx_throttle.phase_timer); + } + + if (level != THROTTLE_LEVEL_0) { + adf_os_timer_start(&pdev->tx_throttle.phase_timer, ms); + } +} + +/* This table stores the duty cycle for each level. + Example "on" time for level 2 with duty period 100ms is: + "on" time = duty_period_ms >> throttle_duty_cycle_table[2] + "on" time = 100 ms >> 2 = 25ms */ +static u_int8_t g_throttle_duty_cycle_table[THROTTLE_LEVEL_MAX] = +{ 0, 1, 2, 4 }; + +void ol_tx_throttle_init_period(struct ol_txrx_pdev_t *pdev, int period) +{ + int i; + + /* Set the current throttle level */ + pdev->tx_throttle.throttle_period_ms = period; + + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "level OFF ON\n"); + for (i = 0; i < THROTTLE_LEVEL_MAX; i++) { + pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_ON] = + pdev->tx_throttle.throttle_period_ms >> + g_throttle_duty_cycle_table[i]; + pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_OFF] = + pdev->tx_throttle.throttle_period_ms - + pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_ON]; + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "%d %d %d\n", i, + pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_OFF], + pdev->tx_throttle.throttle_time_ms[i][THROTTLE_PHASE_ON]); + } +} + +void ol_tx_throttle_init(struct ol_txrx_pdev_t *pdev) +{ + u_int32_t throttle_period; + + pdev->tx_throttle.current_throttle_level = THROTTLE_LEVEL_0; + pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF; + adf_os_spinlock_init(&pdev->tx_throttle.mutex); + + throttle_period = ol_cfg_throttle_period_ms(pdev->ctrl_pdev); + + ol_tx_throttle_init_period(pdev, throttle_period); + + adf_os_timer_init( + pdev->osdev, + &pdev->tx_throttle.phase_timer, + ol_tx_pdev_throttle_phase_timer, + pdev, ADF_DEFERRABLE_TIMER); + +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ + adf_os_timer_init( + pdev->osdev, + &pdev->tx_throttle.tx_timer, + ol_tx_pdev_throttle_tx_timer, + pdev, ADF_DEFERRABLE_TIMER); +#endif + + pdev->tx_throttle.tx_threshold = THROTTLE_TX_THRESHOLD; +} +#endif /* QCA_SUPPORT_TX_THROTTLE */ +/*--- End of LL tx throttle queue code ---------------------------------------*/ + +#if defined(CONFIG_HL_SUPPORT) + +/*--- ADDBA triggering functions --------------------------------------------*/ + + +/*=== debug functions =======================================================*/ + +/*--- queue event log -------------------------------------------------------*/ + +#if defined(DEBUG_HL_LOGGING) + +static void +ol_tx_queue_log_entry_type_info( + u_int8_t *type, int *size, int *align, int var_size) +{ + switch (*type) { + case ol_tx_log_entry_type_enqueue: + case ol_tx_log_entry_type_dequeue: + case ol_tx_log_entry_type_queue_free: + *size = sizeof(struct ol_tx_log_queue_add_t); + *align = 2; + break; + + case ol_tx_log_entry_type_queue_state: + *size = offsetof(struct ol_tx_log_queue_state_var_sz_t, data); + *align = 4; + if (var_size) { + /* read the variable-sized record, to see how large it is */ + int align_pad; + struct ol_tx_log_queue_state_var_sz_t *record; + + align_pad = + (*align - ((((u_int32_t) type) + 1))) & (*align - 1); + record = (struct ol_tx_log_queue_state_var_sz_t *) + (type + 1 + align_pad); + *size += record->num_cats_active * + (sizeof(u_int32_t) /* bytes */ + sizeof(u_int16_t) /* frms */); + } + break; + + //case ol_tx_log_entry_type_drop: + default: + *size = 0; + *align = 0; + }; +} + +static void +ol_tx_queue_log_oldest_update(struct ol_txrx_pdev_t *pdev, int offset) +{ + int oldest_record_offset; + + /* + * If the offset of the oldest record is between the current and + * new values of the offset of the newest record, then the oldest + * record has to be dropped from the log to provide room for the + * newest record. + * Advance the offset of the oldest record until it points to a + * record that is beyond the new value of the offset of the newest + * record. + */ + if (!pdev->txq_log.wrapped) { + /* + * The log has not even filled up yet - no need to remove + * the oldest record to make room for a new record. + */ + return; + } + + if (offset > pdev->txq_log.offset) { + /* + * not wraparound - + * The oldest record offset may have already wrapped around, + * even if the newest record has not. In this case, then + * the oldest record offset is fine where it is. + */ + if (pdev->txq_log.oldest_record_offset == 0) { + return; + } + oldest_record_offset = pdev->txq_log.oldest_record_offset; + } else { + /* wraparound */ + oldest_record_offset = 0; + } + + while (oldest_record_offset < offset) { + int size, align, align_pad; + u_int8_t type; + + type = pdev->txq_log.data[oldest_record_offset]; + if (type == ol_tx_log_entry_type_wrap) { + oldest_record_offset = 0; + break; + } + ol_tx_queue_log_entry_type_info( + &pdev->txq_log.data[oldest_record_offset], &size, &align, 1); + align_pad = + (align - ((oldest_record_offset + 1/*type*/))) & (align - 1); + /* + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "TXQ LOG old alloc: offset %d, type %d, size %d (%d)\n", + oldest_record_offset, type, size, size + 1 + align_pad); + */ + oldest_record_offset += size + 1 + align_pad; + } + if (oldest_record_offset >= pdev->txq_log.size) { + oldest_record_offset = 0; + } + pdev->txq_log.oldest_record_offset = oldest_record_offset; +} + +void* +ol_tx_queue_log_alloc( + struct ol_txrx_pdev_t *pdev, + u_int8_t type /* ol_tx_log_entry_type */, + int extra_bytes) +{ + int size, align, align_pad; + int offset; + + ol_tx_queue_log_entry_type_info(&type, &size, &align, 0); + size += extra_bytes; + + offset = pdev->txq_log.offset; + align_pad = (align - ((offset + 1/*type*/))) & (align - 1); + + if (pdev->txq_log.size - offset >= size + 1 + align_pad) { + /* no need to wrap around */ + goto alloc_found; + } + if (! pdev->txq_log.allow_wrap) { + return NULL; /* log is full and can't wrap */ + } + /* handle wrap-around */ + pdev->txq_log.wrapped = 1; + offset = 0; + align_pad = (align - ((offset + 1/*type*/))) & (align - 1); + /* sanity check that the log is large enough to hold this entry */ + if (pdev->txq_log.size <= size + 1 + align_pad) { + return NULL; + } + +alloc_found: + ol_tx_queue_log_oldest_update(pdev, offset + size + 1 + align_pad); + if (offset == 0) { + pdev->txq_log.data[pdev->txq_log.offset] = ol_tx_log_entry_type_wrap; + } + /* + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "TXQ LOG new alloc: offset %d, type %d, size %d (%d)\n", + offset, type, size, size + 1 + align_pad); + */ + pdev->txq_log.data[offset] = type; + pdev->txq_log.offset = offset + size + 1 + align_pad; + if (pdev->txq_log.offset >= pdev->txq_log.size) { + pdev->txq_log.offset = 0; + pdev->txq_log.wrapped = 1; + } + return &pdev->txq_log.data[offset + 1 + align_pad]; +} + +static int +ol_tx_queue_log_record_display(struct ol_txrx_pdev_t *pdev, int offset) +{ + int size, align, align_pad; + u_int8_t type; + struct ol_txrx_peer_t *peer; + + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + type = pdev->txq_log.data[offset]; + ol_tx_queue_log_entry_type_info( + &pdev->txq_log.data[offset], &size, &align, 1); + align_pad = (align - ((offset + 1/*type*/))) & (align - 1); + + switch (type) { + case ol_tx_log_entry_type_enqueue: + { + struct ol_tx_log_queue_add_t record; + adf_os_mem_copy(&record, + &pdev->txq_log.data[offset + 1 + align_pad], + sizeof(struct ol_tx_log_queue_add_t)); + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + + if (record.peer_id != 0xffff) { + peer = ol_txrx_peer_find_by_id(pdev, record.peer_id); + if (peer != NULL) + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " Q: %6d %5d %3d %4d (%02x:%02x:%02x:%02x:%02x:%02x)", + record.num_frms, record.num_bytes, record.tid, + record.peer_id, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " Q: %6d %5d %3d %4d", + record.num_frms, record.num_bytes, + record.tid, record.peer_id); + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " Q: %6d %5d %3d from vdev", + record.num_frms, record.num_bytes, record.tid); + } + break; + } + case ol_tx_log_entry_type_dequeue: + { + struct ol_tx_log_queue_add_t record; + adf_os_mem_copy(&record, + &pdev->txq_log.data[offset + 1 + align_pad], + sizeof(struct ol_tx_log_queue_add_t)); + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + + if (record.peer_id != 0xffff) { + peer = ol_txrx_peer_find_by_id(pdev, record.peer_id); + if (peer != NULL) + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " DQ: %6d %5d %3d %4d (%02x:%02x:%02x:%02x:%02x:%02x)", + record.num_frms, record.num_bytes, record.tid, + record.peer_id, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " DQ: %6d %5d %3d %4d", + record.num_frms, record.num_bytes, + record.tid, record.peer_id); + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " DQ: %6d %5d %3d from vdev", + record.num_frms, record.num_bytes, record.tid); + } + break; + } + case ol_tx_log_entry_type_queue_free: + { + struct ol_tx_log_queue_add_t record; + adf_os_mem_copy(&record, + &pdev->txq_log.data[offset + 1 + align_pad], + sizeof(struct ol_tx_log_queue_add_t)); + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + + if (record.peer_id != 0xffff) { + peer = ol_txrx_peer_find_by_id(pdev, record.peer_id); + if (peer != NULL) + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " F: %6d %5d %3d %4d (%02x:%02x:%02x:%02x:%02x:%02x)", + record.num_frms, record.num_bytes, record.tid, + record.peer_id, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " F: %6d %5d %3d %4d", + record.num_frms, record.num_bytes, + record.tid, record.peer_id); + } else { + /* shouldn't happen */ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "Unexpected vdev queue removal\n"); + } + break; + } + + case ol_tx_log_entry_type_queue_state: + { + int i, j; + u_int32_t active_bitmap; + struct ol_tx_log_queue_state_var_sz_t record; + u_int8_t *data; + + adf_os_mem_copy(&record, + &pdev->txq_log.data[offset + 1 + align_pad], + sizeof(struct ol_tx_log_queue_state_var_sz_t)); + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " S: bitmap = %#x", + record.active_bitmap); + data = &record.data[0]; + j = 0; + i = 0; + active_bitmap = record.active_bitmap; + while (active_bitmap) { + if (active_bitmap & 0x1) { + u_int16_t frms; + u_int32_t bytes; + + frms = data[0] | (data[1] << 8); + bytes = (data[2] << 0) | (data[3] << 8) | + (data[4] << 16) | (data[5] << 24); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " cat %2d: %6d %5d", + i, frms, bytes); + data += 6; + j++; + } + i++; + active_bitmap >>= 1; + } + break; + } + + //case ol_tx_log_entry_type_drop: + + case ol_tx_log_entry_type_wrap: + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + return -1 * offset; /* go back to the top */ + + default: + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " *** invalid tx log entry type (%d)\n", type); + return 0; /* error */ + }; + + return size + 1 + align_pad; +} + +void +ol_tx_queue_log_display(struct ol_txrx_pdev_t *pdev) +{ + int offset; + int unwrap; + + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + offset = pdev->txq_log.oldest_record_offset; + unwrap = pdev->txq_log.wrapped; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + /* + * In theory, this should use mutex to guard against the offset + * being changed while in use, but since this is just for debugging, + * don't bother. + */ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Tx queue log:"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " : Frames Bytes TID PEER"); + + while (unwrap || offset != pdev->txq_log.offset) { + int delta = ol_tx_queue_log_record_display(pdev, offset); + if (delta == 0) { + return; /* error */ + } + if (delta < 0) { + unwrap = 0; + } + offset += delta; + } +} + +void +ol_tx_queue_log_enqueue( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_msdu_info_t *msdu_info, + int frms, int bytes) +{ + int tid; + u_int16_t peer_id = msdu_info->htt.info.peer_id; + struct ol_tx_log_queue_add_t *log_elem; + tid = msdu_info->htt.info.ext_tid; + + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + log_elem = ol_tx_queue_log_alloc(pdev, ol_tx_log_entry_type_enqueue, 0); + if (!log_elem) { + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + return; + } + + log_elem->num_frms = frms; + log_elem->num_bytes = bytes; + log_elem->peer_id = peer_id; + log_elem->tid = tid; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); +} + +void +ol_tx_queue_log_dequeue( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int frms, int bytes) +{ + int ext_tid; + u_int16_t peer_id; + struct ol_tx_log_queue_add_t *log_elem; + + ext_tid = txq->ext_tid; + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + log_elem = ol_tx_queue_log_alloc(pdev, ol_tx_log_entry_type_dequeue, 0); + if (!log_elem) { + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + return; + } + + if (ext_tid < OL_TX_NUM_TIDS) { + struct ol_txrx_peer_t *peer; + struct ol_tx_frms_queue_t *txq_base; + + txq_base = txq - ext_tid; + peer = container_of(txq_base, struct ol_txrx_peer_t, txqs[0]); + peer_id = peer->peer_ids[0]; + } else { + peer_id = ~0; + } + + log_elem->num_frms = frms; + log_elem->num_bytes = bytes; + log_elem->peer_id = peer_id; + log_elem->tid = ext_tid; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); +} + +void +ol_tx_queue_log_free( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid, int frms, int bytes) +{ + u_int16_t peer_id; + struct ol_tx_log_queue_add_t *log_elem; + + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + log_elem = ol_tx_queue_log_alloc(pdev, ol_tx_log_entry_type_queue_free, 0); + if (!log_elem) { + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + return; + } + + if (tid < OL_TX_NUM_TIDS) { + struct ol_txrx_peer_t *peer; + struct ol_tx_frms_queue_t *txq_base; + + txq_base = txq - tid; + peer = container_of(txq_base, struct ol_txrx_peer_t, txqs[0]); + peer_id = peer->peer_ids[0]; + } else { + peer_id = ~0; + } + + log_elem->num_frms = frms; + log_elem->num_bytes = bytes; + log_elem->peer_id = peer_id; + log_elem->tid = tid; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); +} + +void +ol_tx_queue_log_sched( + struct ol_txrx_pdev_t *pdev, + int credit, + int *num_cats, + u_int32_t **active_bitmap, + u_int8_t **data) +{ + int data_size; + struct ol_tx_log_queue_state_var_sz_t *log_elem; + + data_size = sizeof(u_int32_t) /* bytes */ + sizeof(u_int16_t) /* frms */; + data_size *= *num_cats; + + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + log_elem = ol_tx_queue_log_alloc( + pdev, ol_tx_log_entry_type_queue_state, data_size); + if (!log_elem) { + *num_cats = 0; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); + return; + } + log_elem->num_cats_active = *num_cats; + log_elem->active_bitmap = 0; + log_elem->credit = credit; + + *active_bitmap = &log_elem->active_bitmap; + *data = &log_elem->data[0]; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); +} + +void +ol_tx_queue_log_clear(struct ol_txrx_pdev_t *pdev) +{ + adf_os_spin_lock_bh(&pdev->txq_log_spinlock); + adf_os_mem_zero(&pdev->txq_log, sizeof(pdev->txq_log)); + pdev->txq_log.size = OL_TXQ_LOG_SIZE; + pdev->txq_log.oldest_record_offset = 0; + pdev->txq_log.offset = 0; + pdev->txq_log.allow_wrap = 1; + pdev->txq_log.wrapped = 0; + adf_os_spin_unlock_bh(&pdev->txq_log_spinlock); +} +#endif /* defined(DEBUG_HL_LOGGING) */ + +/*--- queue state printouts -------------------------------------------------*/ + +#if TXRX_DEBUG_LEVEL > 5 + +void +ol_tx_queue_display(struct ol_tx_frms_queue_t *txq, int indent) +{ + char *state; + + state = (txq->flag == ol_tx_queue_active) ? "active" : "paused"; + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*stxq %p (%s): %d frms, %d bytes\n", + indent, " ", txq, state, txq->frms, txq->bytes); +} + +void +ol_tx_queues_display(struct ol_txrx_pdev_t *pdev) +{ + struct ol_txrx_vdev_t *vdev; + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "pdev %p tx queues:\n", pdev); + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + struct ol_txrx_peer_t *peer; + int i; + for (i = 0; i < ARRAY_LEN(vdev->txqs); i++) { + if (vdev->txqs[i].frms == 0) { + continue; + } + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " vdev %d (%p), txq %d\n", vdev->vdev_id, vdev, i); + ol_tx_queue_display(&vdev->txqs[i], 4); + } + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + for (i = 0; i < ARRAY_LEN(peer->txqs); i++) { + if (peer->txqs[i].frms == 0) { + continue; + } + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " peer %d (%p), txq %d\n", + peer->peer_ids[0], vdev, i); + ol_tx_queue_display(&peer->txqs[i], 6); + } + } + } +} + +#endif + +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +static a_bool_t +ol_tx_vdev_has_tx_queue_group( + struct ol_tx_queue_group_t* group, + u_int8_t vdev_id) +{ + u_int16_t vdev_bitmap; + vdev_bitmap = OL_TXQ_GROUP_VDEV_ID_MASK_GET(group->membership); + if (OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(vdev_bitmap, vdev_id)) { + return A_TRUE; + } + return A_FALSE; +} + +static a_bool_t +ol_tx_ac_has_tx_queue_group( + struct ol_tx_queue_group_t* group, + u_int8_t ac) +{ + u_int16_t ac_bitmap; + ac_bitmap = OL_TXQ_GROUP_AC_MASK_GET(group->membership); + if (OL_TXQ_GROUP_AC_BIT_MASK_GET(ac_bitmap, ac)) { + return A_TRUE; + } + return A_FALSE; +} + +u_int32_t ol_tx_txq_group_credit_limit( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u_int32_t credit) +{ + u_int8_t i; + int updated_credit = credit; + /* + * If this tx queue belongs to a group, check whether the group's + * credit limit is more stringent than the global credit limit. + */ + for (i = 0; i < OL_TX_MAX_GROUPS_PER_QUEUE; i++) { + if (txq->group_ptrs[i]) { + int group_credit; + group_credit = adf_os_atomic_read(&txq->group_ptrs[i]->credit); + updated_credit = MIN(updated_credit, group_credit); + } + } + + credit = (updated_credit < 0) ? 0 : updated_credit; + + return credit; +} + +void ol_tx_txq_group_credit_update( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int32_t credit, + u_int8_t absolute) +{ + u_int8_t i; + /* + * If this tx queue belongs to a group then + * update group credit + */ + for (i = 0; i < OL_TX_MAX_GROUPS_PER_QUEUE; i++) { + if (txq->group_ptrs[i]) { + ol_txrx_update_group_credit(txq->group_ptrs[i], credit, absolute); + } + } + OL_TX_UPDATE_GROUP_CREDIT_STATS(pdev); +} + +void +ol_tx_set_vdev_group_ptr( + ol_txrx_pdev_handle pdev, + u_int8_t vdev_id, + struct ol_tx_queue_group_t *grp_ptr) +{ + struct ol_txrx_vdev_t *vdev = NULL; + struct ol_txrx_peer_t *peer = NULL; + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if (vdev->vdev_id == vdev_id) { + u_int8_t i, j; + /* update vdev queues group pointers */ + for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { + for (j = 0; j < OL_TX_MAX_GROUPS_PER_QUEUE; j++) { + vdev->txqs[i].group_ptrs[j] = grp_ptr; + } + } + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + /* Update peer queue group pointers */ + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + for (i = 0; i < OL_TX_NUM_TIDS; i++) { + for (j = 0; j < OL_TX_MAX_GROUPS_PER_QUEUE; j++) { + peer->txqs[i].group_ptrs[j] = grp_ptr; + } + } + } + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + break; + } + } +} + +void +ol_tx_txq_set_group_ptr( + struct ol_tx_frms_queue_t *txq, + struct ol_tx_queue_group_t *grp_ptr) +{ + u_int8_t i; + for (i = 0; i < OL_TX_MAX_GROUPS_PER_QUEUE; i++) { + txq->group_ptrs[i] = grp_ptr; + } +} + +void +ol_tx_set_peer_group_ptr( + ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + u_int8_t vdev_id, + u_int8_t tid) +{ + u_int8_t i, j = 0; + struct ol_tx_queue_group_t *group = NULL; + + for (i = 0; i < OL_TX_MAX_GROUPS_PER_QUEUE; i++) { + peer->txqs[tid].group_ptrs[i] = NULL; + } + for (i = 0; i < OL_TX_MAX_TXQ_GROUPS; i++) { + group = &pdev->txq_grps[i]; + if (ol_tx_vdev_has_tx_queue_group(group, vdev_id)) { + if (tid < OL_TX_NUM_QOS_TIDS) { + if (ol_tx_ac_has_tx_queue_group( + group, TXRX_TID_TO_WMM_AC(tid))) { + peer->txqs[tid].group_ptrs[j] = group; + j++; + } + } else { + peer->txqs[tid].group_ptrs[j] = group; + j++; + } + } + if (j >= OL_TX_MAX_GROUPS_PER_QUEUE) { + break; + } + } +} + +u_int32_t ol_tx_get_max_tx_groups_supported(struct ol_txrx_pdev_t *pdev) +{ +#ifdef HIF_SDIO + return OL_TX_MAX_TXQ_GROUPS; +#else + return 0; +#endif +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.h new file mode 100644 index 000000000000..4b6500403322 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_tx_queue.h + * @brief API definitions for the tx frame queue module within the data SW. + */ +#ifndef _OL_TX_QUEUE__H_ +#define _OL_TX_QUEUE__H_ + +#include /* adf_nbuf_t */ +#include /* ol_txrx_vdev_t, etc. */ +#include /* a_bool_t */ + +#if defined(CONFIG_HL_SUPPORT) + +/** + * @brief Queue a tx frame to the tid queue. + * + * @param pdev - the data virtual device sending the data + * (for storing the tx desc in the virtual dev's tx_target_list, + * and for accessing the phy dev) + * @param txq - which queue the tx frame gets stored in + * @param tx_desc - tx meta-data, including prev and next ptrs + * @param tx_msdu_info - characteristics of the tx frame + */ +void +ol_tx_enqueue( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + struct ol_tx_desc_t *tx_desc, + struct ol_txrx_msdu_info_t *tx_msdu_info); + +/** + * @brief - remove the specified number of frames from the head of a tx queue + * @details + * This function removes frames from the head of a tx queue, + * and returns them as a NULL-terminated linked list. + * The function will remove frames until one of the following happens: + * 1. The tx queue is empty + * 2. The specified number of frames have been removed + * 3. Removal of more frames would exceed the specified credit limit + * + * @param pdev - the physical device object + * @param txq - which tx queue to remove frames from + * @param head - which contains return linked-list of tx frames (descriptors) + * @param num_frames - maximum number of frames to remove + * @param[in/out] credit - + * input: max credit the dequeued frames can consume + * output: how much credit the dequeued frames consume + * @param[out] bytes - the sum of the sizes of the dequeued frames + * @return number of frames dequeued +*/ +u_int16_t +ol_tx_dequeue( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + ol_tx_desc_list *head, + u_int16_t num_frames, + u_int32_t *credit, + int *bytes); + +/** + * @brief - free all of frames from the tx queue while deletion + * @details + * This function frees all of frames from the tx queue. + * This function is called during peer or vdev deletion. + * This function notifies the scheduler, so the scheduler can update + * its state to account for the absence of the queue. + * + * @param pdev - the physical device object, which stores the txqs + * @param txq - which tx queue to free frames from + * @param tid - the extended TID that the queue belongs to + */ +void +ol_tx_queue_free( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid); + +/** + * @brief - discard pending tx frames from the tx queue + * @details + * This function is called if there are too many queues in tx scheduler. + * This function is called if we wants to flush all pending tx + * queues in tx scheduler. + * + * @param pdev - the physical device object, which stores the txqs + * @param flush_all - flush all pending tx queues if set to true + * @param tx_descs - List Of tx_descs to be discarded will be returned by this function + */ + +void +ol_tx_queue_discard( + struct ol_txrx_pdev_t *pdev, + a_bool_t flush_all, + ol_tx_desc_list *tx_descs); + +#else + +#define ol_tx_enqueue(pdev, txq, tx_desc, tx_msdu_info) /* no-op */ +#define ol_tx_dequeue(pdev, ext_tid, txq, head, num_frames, credit, bytes) 0 +#define ol_tx_queue_free(pdev, txq, tid) /* no-op */ +#define ol_tx_queue_discard(pdev, flush, tx_descs) /* no-op */ + +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + +void +ol_txrx_peer_bal_add_limit_peer( + struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id, + u_int16_t peer_limit); + +void +ol_txrx_peer_bal_remove_limit_peer( + struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id); + +void +ol_txrx_peer_pause_but_no_mgmt_q(ol_txrx_peer_handle peer); + +void +ol_txrx_peer_unpause_but_no_mgmt_q(ol_txrx_peer_handle peer); + +u_int16_t +ol_tx_bad_peer_dequeue_check(struct ol_tx_frms_queue_t *txq, + u_int16_t max_frames, + u_int16_t *tx_limit_flag); + +void +ol_tx_bad_peer_update_tx_limit(struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u_int16_t frames, + u_int16_t tx_limit_flag); + +void +ol_txrx_set_txq_peer( + struct ol_tx_frms_queue_t *txq, + struct ol_txrx_peer_t *peer); + +/** + * @brief - initialize the peer balance context + * @param pdev - the physical device object, which stores the txqs + */ +void ol_tx_badpeer_flow_cl_init(struct ol_txrx_pdev_t *pdev); + +/** + * @brief - deinitialize the peer balance context + * @param pdev - the physical device object, which stores the txqs + */ +void ol_tx_badpeer_flow_cl_deinit(struct ol_txrx_pdev_t *pdev); + +#else + +static inline void ol_txrx_peer_bal_add_limit_peer( + struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id, + u_int16_t peer_limit) +{ + /* no-op */ +} + +static inline void ol_txrx_peer_bal_remove_limit_peer( + struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id) +{ + /* no-op */ +} + +static inline void ol_txrx_peer_pause_but_no_mgmt_q(ol_txrx_peer_handle peer) +{ + /* no-op */ +} + +static inline void ol_txrx_peer_unpause_but_no_mgmt_q(ol_txrx_peer_handle peer) +{ + /* no-op */ +} + +static inline u_int16_t +ol_tx_bad_peer_dequeue_check(struct ol_tx_frms_queue_t *txq, + u_int16_t max_frames, + u_int16_t *tx_limit_flag) +{ + /* just return max_frames */ + return max_frames; +} + +static inline void +ol_tx_bad_peer_update_tx_limit(struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u_int16_t frames, + u_int16_t tx_limit_flag) +{ + /* no-op */ +} + +static inline void +ol_txrx_set_txq_peer( + struct ol_tx_frms_queue_t *txq, + struct ol_txrx_peer_t *peer) +{ + /* no-op */ +} + +static inline void ol_tx_badpeer_flow_cl_init(struct ol_txrx_pdev_t *pdev) +{ + /* no-op */ +} + +static inline void ol_tx_badpeer_flow_cl_deinit(struct ol_txrx_pdev_t *pdev) +{ + /* no-op */ +} + +#endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */ + + +#if defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING) + +void +ol_tx_queue_log_sched( + struct ol_txrx_pdev_t *pdev, + int credit, + int *num_active_tids, + u_int32_t **active_bitmap, + u_int8_t **data); + +#define OL_TX_QUEUE_LOG_SCHED ol_tx_queue_log_sched + +#else + +#define OL_TX_QUEUE_LOG_SCHED(\ + pdev, credit, num_active_tids, active_bitmap, data) + +#endif /* defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING) */ + +#if defined(CONFIG_HL_SUPPORT) && TXRX_DEBUG_LEVEL > 5 +/** + * @brief - show current state of all tx queues + * @param pdev - the physical device object, which stores the txqs + */ +void +ol_tx_queues_display(struct ol_txrx_pdev_t *pdev); +#else +#define ol_tx_queues_display(pdev) /* no-op */ +#endif + +#define ol_tx_queue_decs_reinit(peer, peer_id) /* no-op */ + +#ifdef QCA_SUPPORT_TX_THROTTLE +/** + * @brief - initialize the throttle context + * @param pdev - the physical device object, which stores the txqs + */ +void ol_tx_throttle_init(struct ol_txrx_pdev_t *pdev); +#else +#define ol_tx_throttle_init(pdev) /*no op*/ +#endif + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +#define OL_TX_IS_TXQ_LAST_SERVICED_QUEUE(pdev, txq) \ + txq == pdev->tx_sched.last_used_txq + +u_int32_t ol_tx_txq_group_credit_limit( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + u_int32_t credit); + +void ol_tx_txq_group_credit_update( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int32_t credit, + u_int8_t absolute); + +void +ol_tx_set_vdev_group_ptr( + ol_txrx_pdev_handle pdev, + u_int8_t vdev_id, + struct ol_tx_queue_group_t *grp_ptr); + +void +ol_tx_txq_set_group_ptr( + struct ol_tx_frms_queue_t *txq, + struct ol_tx_queue_group_t *grp_ptr); + +void +ol_tx_set_peer_group_ptr( + ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + u_int8_t vdev_id, + u_int8_t tid); + +#define OL_TX_TXQ_GROUP_CREDIT_LIMIT ol_tx_txq_group_credit_limit +#define OL_TX_TXQ_GROUP_CREDIT_UPDATE ol_tx_txq_group_credit_update +#define OL_TX_TXQ_SET_GROUP_PTR ol_tx_txq_set_group_ptr +#define OL_TX_SET_PEER_GROUP_PTR ol_tx_set_peer_group_ptr +#else +#define OL_TX_IS_TXQ_LAST_SERVICED_QUEUE(pdev, txq) 0 +#define OL_TX_TXQ_GROUP_CREDIT_LIMIT(pdev, txq, credit) credit +#define OL_TX_TXQ_GROUP_CREDIT_UPDATE(pdev, txq, credit, absolute) /* no-op */ +#define OL_TX_TXQ_SET_GROUP_PTR(txq,grp_ptr) /* no-op */ +#define OL_TX_SET_PEER_GROUP_PTR(pdev, peer, vdev_id, tid) /* no-op */ +#endif + +#endif /* _OL_TX_QUEUE__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.c new file mode 100644 index 000000000000..b21282c7cb7f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.c @@ -0,0 +1,1427 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* adf_nbuf_t, etc. */ +#include /* HTT_TX_EXT_TID_MGMT */ +#include /* htt_tx_desc_tid */ +#include /* ol_txrx_vdev_handle */ +#include /* ol_txrx_sync */ +#include /* TXRX_ASSERT1 */ +#include /* pdev stats, etc. */ +#include /* ol_tx_desc */ +#include /* ol_tx_send */ +#include /* OL_TX_SCHED, etc. */ +#include +#include +#include /* a_bool_t */ + +#if defined(CONFIG_HL_SUPPORT) + +#if defined(DEBUG_HL_LOGGING) +static void +ol_tx_sched_log(struct ol_txrx_pdev_t *pdev); +#define OL_TX_SCHED_LOG ol_tx_sched_log +#else +#define OL_TX_SCHED_LOG(pdev) /* no-op */ +#endif /* defined(DEBUG_HL_LOGGING) */ + +#if DEBUG_HTT_CREDIT +#define OL_TX_DISPATCH_LOG_CREDIT() \ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, \ + " TX %d bytes\n", adf_nbuf_len(msdu)); \ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, \ + " Decrease credit %d - 1 = %d, len:%d.\n", \ + adf_os_atomic_read(&pdev->target_tx_credit), \ + adf_os_atomic_read(&pdev->target_tx_credit) -1, \ + adf_nbuf_len(msdu)); +#else +#define OL_TX_DISPATCH_LOG_CREDIT() +#endif + +/*--- generic definitions used by the scheduler framework for all algs ---*/ + +struct ol_tx_sched_ctx { + ol_tx_desc_list head; + int frms; +}; + +typedef TAILQ_HEAD(ol_tx_frms_queue_list_s, ol_tx_frms_queue_t) + ol_tx_frms_queue_list; + +#define OL_A_MAX(_x, _y) ((_x) > (_y) ? (_x) : (_y)) + +#define OL_A_MIN(_x, _y) ((_x) < (_y) ? (_x) : (_y)) + +/*--- scheduler algorithm selection ---*/ + +/*--- scheduler options --------------------------------------------------- + * 1. Round-robin scheduler: + * Select the TID that is at the head of the list of active TIDs. + * Select the head tx queue for this TID. + * Move the tx queue to the back of the list of tx queues for this TID. + * Move the TID to the back of the list of active TIDs. + * Send as many frames from the tx queue as credit allows. + * 2. Weighted-round-robin advanced scheduler: + * Keep an ordered list of which TID gets selected next. + * Use a weighted-round-robin scheme to determine when to promote a TID + * within this list. + * If a TID at the head of the list is inactive, leave it at the head, + * but check the next TIDs. + * If the credit available is less than the credit threshold for the + * next active TID, don't send anything, and leave the TID at the head + * of the list. + * After a TID is selected, move it to the back of the list. + * Select the head tx queue for this TID. + * Move the tx queue to the back of the list of tx queues for this TID. + * Send no more frames than the limit specified for the TID. + */ +#define OL_TX_SCHED_RR 1 +#define OL_TX_SCHED_WRR_ADV 2 + +#ifndef OL_TX_SCHED +//#define OL_TX_SCHED OL_TX_SCHED_RR +#define OL_TX_SCHED OL_TX_SCHED_WRR_ADV /* default */ +#endif + + +#if OL_TX_SCHED == OL_TX_SCHED_RR + +#define ol_tx_sched_rr_t ol_tx_sched_t + +#define OL_TX_SCHED_NUM_CATEGORIES (OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES) + +#define ol_tx_sched_init ol_tx_sched_init_rr +#define ol_tx_sched_select_init(pdev) /* no-op */ +#define ol_tx_sched_select_batch ol_tx_sched_select_batch_rr +#define ol_tx_sched_txq_enqueue ol_tx_sched_txq_enqueue_rr +#define ol_tx_sched_txq_deactivate ol_tx_sched_txq_deactivate_rr +#define ol_tx_sched_category_tx_queues ol_tx_sched_category_tx_queues_rr +#define ol_tx_sched_txq_discard ol_tx_sched_txq_discard_rr +#define ol_tx_sched_category_info ol_tx_sched_category_info_rr +#define ol_tx_sched_discard_select_category \ + ol_tx_sched_discard_select_category_rr + +#elif OL_TX_SCHED == OL_TX_SCHED_WRR_ADV + +#define ol_tx_sched_wrr_adv_t ol_tx_sched_t + +#define OL_TX_SCHED_NUM_CATEGORIES OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES + +#define ol_tx_sched_init ol_tx_sched_init_wrr_adv +#define ol_tx_sched_select_init(pdev) \ + do { \ + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); \ + ol_tx_sched_select_init_wrr_adv(pdev); \ + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); \ + } while (0) +#define ol_tx_sched_select_batch ol_tx_sched_select_batch_wrr_adv +#define ol_tx_sched_txq_enqueue ol_tx_sched_txq_enqueue_wrr_adv +#define ol_tx_sched_txq_deactivate ol_tx_sched_txq_deactivate_wrr_adv +#define ol_tx_sched_category_tx_queues ol_tx_sched_category_tx_queues_wrr_adv +#define ol_tx_sched_txq_discard ol_tx_sched_txq_discard_wrr_adv +#define ol_tx_sched_category_info ol_tx_sched_category_info_wrr_adv +#define ol_tx_sched_discard_select_category \ + ol_tx_sched_discard_select_category_wrr_adv + +#else + +#error Unknown OL TX SCHED specification + +#endif /* OL_TX_SCHED */ + +/*--- round-robin scheduler -------------------------------------------------*/ +#if OL_TX_SCHED == OL_TX_SCHED_RR + +/*--- definitions ---*/ + +struct ol_tx_active_queues_in_tid_t { + /* list_elem is used to queue up into up level queues*/ + TAILQ_ENTRY(ol_tx_active_queues_in_tid_t) list_elem; + u_int32_t frms; + u_int32_t bytes; + ol_tx_frms_queue_list head; + bool active; + int tid; +}; + +typedef TAILQ_HEAD(ol_tx_active_tids_s, ol_tx_active_queues_in_tid_t) + ol_tx_active_tids_list; + +struct ol_tx_sched_rr_t { + struct ol_tx_active_queues_in_tid_t + tx_active_queues_in_tid_array[OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES]; + ol_tx_active_tids_list tx_active_tids_list; + u_int8_t discard_weights[OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES]; +}; + +#define TX_SCH_MAX_CREDIT_FOR_THIS_TID(tidq) 16 + +/*--- functions ---*/ + +/* + * The scheduler sync spinlock has been acquired outside this function, + * so there is no need to worry about mutex within this function. + */ +static int +ol_tx_sched_select_batch_rr( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_sched_ctx *sctx, + u_int32_t credit) +{ + struct ol_tx_sched_rr_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_active_queues_in_tid_t *txq_queue; + struct ol_tx_frms_queue_t *next_tq; + u_int16_t frames, used_credits, tx_limit, tx_limit_flag = 0; + int bytes; + + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + + if (TAILQ_EMPTY(&scheduler->tx_active_tids_list)) return; + + txq_queue = TAILQ_FIRST(&scheduler->tx_active_tids_list); + + TAILQ_REMOVE(&scheduler->tx_active_tids_list, txq_queue, list_elem); + txq_queue->active = FALSE; + + next_tq = TAILQ_FIRST(&txq_queue->head); + TAILQ_REMOVE(&txq_queue->head, next_tq, list_elem); + + credit = OL_A_MIN(credit, TX_SCH_MAX_CREDIT_FOR_THIS_TID(next_tq)); + frames = next_tq->frms; /* download as many frames as credit allows */ + tx_limit = ol_tx_bad_peer_dequeue_check(txq, category->specs.send_limit, &tx_limit_flag); + frames = ol_tx_dequeue( + pdev, txq, &sctx->head, tx_limit, &credit, &bytes); + ol_tx_bad_peer_update_tx_limit(pdev, txq, frames, tx_limit_flag); + + used_credits = credit; + txq_queue->frms -= frames; + txq_queue->bytes -= bytes; + + if (next_tq->frms > 0) { + TAILQ_INSERT_TAIL(&txq_queue->head, next_tq, list_elem); + TAILQ_INSERT_TAIL( + &scheduler->tx_active_tids_list, txq_queue, list_elem); + txq_queue->active = TRUE; + } else if (!TAILQ_EMPTY(&txq_queue->head)) { + /* + * This tx queue is empty, but there's another tx queue for the + * same TID that is not empty. Thus, the TID as a whole is active. + */ + TAILQ_INSERT_TAIL( + &scheduler->tx_active_tids_list, txq_queue, list_elem); + txq_queue->active = TRUE; + } + sctx->frms += frames; + + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); + return used_credits; +} + +static inline void +ol_tx_sched_txq_enqueue_rr( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid, + int frms, + int bytes) +{ + struct ol_tx_sched_rr_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_active_queues_in_tid_t *txq_queue; + + txq_queue = &scheduler->tx_active_queues_in_tid_array[tid]; + if (txq->flag != ol_tx_queue_active) + { + TAILQ_INSERT_TAIL(&txq_queue->head, txq, list_elem); + } + txq_queue->frms += frms; + txq_queue->bytes += bytes; + + if (!txq_queue->active) { + TAILQ_INSERT_TAIL( + &scheduler->tx_active_tids_list, txq_queue, list_elem); + txq_queue->active = TRUE; + } +} + +static inline void +ol_tx_sched_txq_deactivate_rr( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid) +{ + struct ol_tx_sched_rr_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_active_queues_in_tid_t *txq_queue; + + txq_queue = &scheduler->tx_active_queues_in_tid_array[tid]; + txq_queue->frms -= txq->frms; + txq_queue->bytes -= txq->bytes; + + TAILQ_REMOVE(&txq_queue->head, txq, list_elem); + //if (txq_queue->frms == 0 && txq_queue->active) { + if (TAILQ_EMPTY(&txq_queue->head) && txq_queue->active) { + TAILQ_REMOVE(&scheduler->tx_active_tids_list, txq_queue, list_elem); + txq_queue->active = FALSE; + } +} + +ol_tx_frms_queue_list * +ol_tx_sched_category_tx_queues_rr(struct ol_txrx_pdev_t *pdev, int tid) +{ + struct ol_tx_sched_rr_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_active_queues_in_tid_t *txq_queue; + + txq_queue = &scheduler->tx_active_queues_in_tid_array[tid]; + return &txq_queue->head; +} + +int +ol_tx_sched_discard_select_category_rr(struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_sched_rr_t *scheduler; + u_int8_t i, tid = 0; + int max_score = 0; + + scheduler = pdev->tx_sched.scheduler; + /* + * Choose which TID's tx frames to drop next based on two factors: + * 1. Which TID has the most tx frames present + * 2. The TID's priority (high-priority TIDs have a low discard_weight) + */ + for (i = 0; i < (OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES); i++) { + int score; + score = + scheduler->tx_active_queues_in_tid_array[i].frms * + scheduler->discard_weights[i]; + if (max_score == 0 || score > max_score) { + max_score = score; + tid = i; + } + } + return tid; +} + +void +ol_tx_sched_txq_discard_rr( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid, int frames, int bytes) +{ + struct ol_tx_sched_rr_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_active_queues_in_tid_t *txq_queue; + + txq_queue = &scheduler->tx_active_queues_in_tid_array[tid]; + + if (0 == txq->frms) { + TAILQ_REMOVE(&txq_queue->head, txq, list_elem); + } + + txq_queue->frms -= frames; + txq_queue->bytes -= bytes; + if (txq_queue->active == TRUE && txq_queue->frms == 0) { + TAILQ_REMOVE(&scheduler->tx_active_tids_list, txq_queue, list_elem); + txq_queue->active = FALSE; + } +} + +void +ol_tx_sched_category_info_rr( + struct ol_txrx_pdev_t *pdev, int cat, int *active, int *frms, int *bytes) +{ + struct ol_tx_sched_rr_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_active_queues_in_tid_t *txq_queue; + + txq_queue = &scheduler->tx_active_queues_in_tid_array[cat]; + + *active = txq_queue->active; + *frms = txq_queue->frms; + *bytes = txq_queue->bytes; +} + +enum { + ol_tx_sched_discard_weight_voice = 1, + ol_tx_sched_discard_weight_video = 4, + ol_tx_sched_discard_weight_ucast_default = 8, + ol_tx_sched_discard_weight_mgmt_non_qos = 1, /* 0? */ + ol_tx_sched_discard_weight_mcast = 1, /* 0? also for probe & assoc */ +}; + +void * +ol_tx_sched_init_rr( + struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_sched_rr_t *scheduler; + int i; + + scheduler = adf_os_mem_alloc(pdev->osdev, sizeof(struct ol_tx_sched_rr_t)); + if (scheduler == NULL) { + return scheduler; + } + + for (i = 0; i < (OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES); i++) { + scheduler->tx_active_queues_in_tid_array[i].tid = i; + TAILQ_INIT(&scheduler->tx_active_queues_in_tid_array[i].head); + scheduler->tx_active_queues_in_tid_array[i].active = 0; + scheduler->tx_active_queues_in_tid_array[i].frms = 0; + scheduler->tx_active_queues_in_tid_array[i].bytes = 0; + } + for (i = 0; i < OL_TX_NUM_TIDS; i++) { + scheduler->tx_active_queues_in_tid_array[i].tid = i; + if (i < OL_TX_NON_QOS_TID) { + int ac = TXRX_TID_TO_WMM_AC(i); + switch (ac) { + case TXRX_WMM_AC_VO: + scheduler->discard_weights[i] = + ol_tx_sched_discard_weight_voice; + case TXRX_WMM_AC_VI: + scheduler->discard_weights[i] = + ol_tx_sched_discard_weight_video; + default: + scheduler->discard_weights[i] = + ol_tx_sched_discard_weight_ucast_default; + }; + } else { + scheduler->discard_weights[i] = + ol_tx_sched_discard_weight_mgmt_non_qos; + } + } + for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { + int j = i + OL_TX_NUM_TIDS; + scheduler->tx_active_queues_in_tid_array[j].tid = OL_TX_NUM_TIDS - 1; + scheduler->discard_weights[j] = ol_tx_sched_discard_weight_mcast; + } + TAILQ_INIT(&scheduler->tx_active_tids_list); + + return scheduler; +} + +void +ol_txrx_set_wmm_param(ol_txrx_pdev_handle data_pdev, struct ol_tx_wmm_param_t wmm_param) +{ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "Dummy function when OL_TX_SCHED_RR is enabled\n"); +} + +#endif /* OL_TX_SCHED == OL_TX_SCHED_RR */ + +/*--- advanced scheduler ----------------------------------------------------*/ +#if OL_TX_SCHED == OL_TX_SCHED_WRR_ADV + +/*--- definitions ---*/ + +struct ol_tx_sched_wrr_adv_category_info_t { + struct { + int wrr_skip_weight; + u_int32_t credit_threshold; + u_int16_t send_limit; + int credit_reserve; + int discard_weight; + } specs; + struct { + int wrr_count; + int frms; + int bytes; + ol_tx_frms_queue_list head; + bool active; + } state; +#ifdef DEBUG_HL_LOGGING + struct + { + char *cat_name; + unsigned int queued; + unsigned int dispatched; + unsigned int discard; + } stat; +#endif +}; + +#define OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(cat, \ + wrr_skip_weight, \ + credit_threshold, \ + send_limit, \ + credit_reserve, \ + discard_weights) \ + enum { OL_TX_SCHED_WRR_ADV_ ## cat ## _WRR_SKIP_WEIGHT = \ + (wrr_skip_weight) }; \ + enum { OL_TX_SCHED_WRR_ADV_ ## cat ## _CREDIT_THRESHOLD = \ + (credit_threshold) }; \ + enum { OL_TX_SCHED_WRR_ADV_ ## cat ## _SEND_LIMIT = \ + (send_limit) }; \ + enum { OL_TX_SCHED_WRR_ADV_ ## cat ## _CREDIT_RESERVE = \ + (credit_reserve) }; \ + enum { OL_TX_SCHED_WRR_ADV_ ## cat ## _DISCARD_WEIGHT = \ + (discard_weights) } + +/* Rome: + * For high-volume traffic flows (VI, BE, BK), use a credit threshold + * roughly equal to a large A-MPDU (occupying half the target memory + * available for holding tx frames) to download AMPDU-sized batches + * of traffic. + * For high-priority, low-volume traffic flows (VO and mgmt), use no + * credit threshold, to minimize download latency. + */ +// WRR send +// skip credit limit credit disc +// wts thresh (frms) reserv wts +#ifdef HIF_SDIO +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(VO, 1, 17, 24, 0, 1); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(VI, 3, 17, 16, 1, 4); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(BE, 10, 17, 16, 1, 8); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(BK, 12, 6, 6, 1, 8); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(NON_QOS_DATA,12, 6, 4, 1, 8); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(UCAST_MGMT, 1, 1, 4, 0, 1); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(MCAST_DATA, 10, 17, 4, 1, 4); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(MCAST_MGMT, 1, 1, 4, 0, 1); +#else +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(VO, 1, 16, 24, 0, 1); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(VI, 3, 16, 16, 1, 4); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(BE, 10, 12, 12, 1, 8); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(BK, 12, 6, 6, 1, 8); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(NON_QOS_DATA,12, 6, 4, 1, 8); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(UCAST_MGMT, 1, 1, 4, 0, 1); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(MCAST_DATA, 10, 16, 4, 1, 4); +OL_TX_SCHED_WRR_ADV_CAT_CFG_SPEC(MCAST_MGMT, 1, 1, 4, 0, 1); +#endif + +#ifdef DEBUG_HL_LOGGING + +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INIT(category, scheduler) \ + do { \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category].stat.queued = 0; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category].stat.discard = 0; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category].stat.dispatched = 0; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category].stat.cat_name = #category; \ + } while (0) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_QUEUED(category, frms) \ + category->stat.queued += frms +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISCARD(category, frms) \ + category->stat.discard += frms +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISPATCHED(category, frms) \ + category->stat.dispatched += frms +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_DUMP(scheduler) \ + ol_tx_sched_wrr_adv_cat_stat_dump(scheduler) +#define OL_TX_SCHED_WRR_ADV_CAT_CUR_STATE_DUMP(scheduler) \ + ol_tx_sched_wrr_adv_cat_cur_state_dump(scheduler) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_CLEAR(scheduler) \ + ol_tx_sched_wrr_adv_cat_stat_clear(scheduler) + +#else /* DEBUG_HL_LOGGING */ + +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INIT(category, scheduler) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_QUEUED(category, frms) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISCARD(category, frms) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISPATCHED(category, frms) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_DUMP(scheduler) +#define OL_TX_SCHED_WRR_ADV_CAT_CUR_STATE_DUMP(scheduler) +#define OL_TX_SCHED_WRR_ADV_CAT_STAT_CLEAR(scheduler) + +#endif /* DEBUG_HL_LOGGING */ + +#define OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(category, scheduler) \ + do { \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category] \ + .specs.wrr_skip_weight = \ + OL_TX_SCHED_WRR_ADV_ ## category ## _WRR_SKIP_WEIGHT; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category] \ + .specs.credit_threshold = \ + OL_TX_SCHED_WRR_ADV_ ## category ## _CREDIT_THRESHOLD; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category] \ + .specs.send_limit = \ + OL_TX_SCHED_WRR_ADV_ ## category ## _SEND_LIMIT; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category] \ + .specs.credit_reserve = \ + OL_TX_SCHED_WRR_ADV_ ## category ## _CREDIT_RESERVE; \ + scheduler->categories[OL_TX_SCHED_WRR_ADV_CAT_ ## category] \ + .specs.discard_weight = \ + OL_TX_SCHED_WRR_ADV_ ## category ## _DISCARD_WEIGHT; \ + OL_TX_SCHED_WRR_ADV_CAT_STAT_INIT(category, scheduler); \ + } while (0) + +struct ol_tx_sched_wrr_adv_t { + int order[OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES]; + int index; + struct ol_tx_sched_wrr_adv_category_info_t + categories[OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES]; +}; + +#define OL_TX_AIFS_DEFAULT_VO 2 +#define OL_TX_AIFS_DEFAULT_VI 2 +#define OL_TX_AIFS_DEFAULT_BE 3 +#define OL_TX_AIFS_DEFAULT_BK 7 +#define OL_TX_CW_MIN_DEFAULT_VO 3 +#define OL_TX_CW_MIN_DEFAULT_VI 7 +#define OL_TX_CW_MIN_DEFAULT_BE 15 +#define OL_TX_CW_MIN_DEFAULT_BK 15 + +/*--- functions ---*/ + +#ifdef DEBUG_HL_LOGGING +static void ol_tx_sched_wrr_adv_cat_stat_dump + (struct ol_tx_sched_wrr_adv_t *scheduler) +{ + int i; + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,"Scheduler Stats:"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "====category(CRR,CRT,WSW): Queued Discard Dequeued frms wrr==="); + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; ++ i) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%12s(%2d, %2d, %2d): %6d %7d %8d %4d %3d", + scheduler->categories[i].stat.cat_name, + scheduler->categories[i].specs.credit_reserve, + scheduler->categories[i].specs.credit_threshold, + scheduler->categories[i].specs.wrr_skip_weight, + scheduler->categories[i].stat.queued, + scheduler->categories[i].stat.discard, + scheduler->categories[i].stat.dispatched, + scheduler->categories[i].state.frms, + scheduler->categories[i].state.wrr_count); + } +} + +static void ol_tx_sched_wrr_adv_cat_cur_state_dump + (struct ol_tx_sched_wrr_adv_t *scheduler) +{ + int i; + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,"Scheduler State Snapshot:"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "====category(CRR,CRT,WSW): IS_Active Pend_Frames Pend_bytes wrr==="); + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; ++ i) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%12s(%2d, %2d, %2d): %9d %11d %10d %3d", + scheduler->categories[i].stat.cat_name, + scheduler->categories[i].specs.credit_reserve, + scheduler->categories[i].specs.credit_threshold, + scheduler->categories[i].specs.wrr_skip_weight, + scheduler->categories[i].state.active, + scheduler->categories[i].state.frms, + scheduler->categories[i].state.bytes, + scheduler->categories[i].state.wrr_count); + } +} + +static void ol_tx_sched_wrr_adv_cat_stat_clear + (struct ol_tx_sched_wrr_adv_t *scheduler) +{ + int i; + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; ++ i) { + scheduler->categories[i].stat.queued = 0; + scheduler->categories[i].stat.discard = 0; + scheduler->categories[i].stat.dispatched = 0; + } +} + +#endif + +static void +ol_tx_sched_select_init_wrr_adv(struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + /* start selection from the front of the ordered list */ + scheduler->index = 0; + pdev->tx_sched.last_used_txq = NULL; +} + +static void +ol_tx_sched_wrr_adv_rotate_order_list_tail( + struct ol_tx_sched_wrr_adv_t *scheduler, int idx) +{ + int value; + /* remember the value of the specified element */ + value = scheduler->order[idx]; + /* shift all further elements up one space */ + for (; idx < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES-1; idx++) { + scheduler->order[idx] = scheduler->order[idx + 1]; + } + /* put the specified element at the end */ + scheduler->order[idx] = value; +} + +static void +ol_tx_sched_wrr_adv_credit_sanity_check(struct ol_txrx_pdev_t *pdev, u_int32_t credit) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + int i; + int okay = 1; + + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; i++) { + if (scheduler->categories[i].specs.credit_threshold > credit) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "*** Config error: credit (%d) not enough " + "to support category %d threshold (%d)\n", + credit, i, scheduler->categories[i].specs.credit_threshold); + okay = 0; + } + } + adf_os_assert(okay); +} + +/* + * The scheduler sync spinlock has been acquired outside this function, + * so there is no need to worry about mutex within this function. + */ +static int +ol_tx_sched_select_batch_wrr_adv( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_sched_ctx *sctx, + u_int32_t credit) +{ + static int first = 1; + int category_index = 0; + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_frms_queue_t *txq; + int index; + struct ol_tx_sched_wrr_adv_category_info_t *category = NULL; + int frames, bytes, used_credits = 0, tx_limit; + u_int16_t tx_limit_flag; + /* + * Just for good measure, do a sanity check that the initial credit + * is enough to cover every category's credit threshold. + */ + if (first) { + first = 0; + ol_tx_sched_wrr_adv_credit_sanity_check(pdev, credit); + } + + /* choose the traffic category from the ordered list */ + index = scheduler->index; + while (index < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES) { + category_index = scheduler->order[index]; + category = &scheduler->categories[category_index]; + if (!category->state.active) { + /* move on to the next category */ + index++; + continue; + } + if (++category->state.wrr_count < category->specs.wrr_skip_weight) { + /* skip this cateogry (move it to the back) */ + ol_tx_sched_wrr_adv_rotate_order_list_tail(scheduler, index); + /* try again (iterate) on the new element that was moved up */ + continue; + } + /* found the first active category whose WRR turn is present */ + break; + } + if (index >= OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES) { + /* no categories are active */ + return 0; + } + + /* is there enough credit for the selected category? */ + if (credit < category->specs.credit_threshold) { + /* + * Can't send yet - wait until more credit becomes available. + * In the meantime, restore the WRR counter (since we didn't + * service this category after all). + */ + category->state.wrr_count = category->state.wrr_count - 1; + return 0; + } + /* enough credit is available - go ahead and send some frames */ + /* + * This category was serviced - reset the WRR counter, and move this + * category to the back of the order list. + */ + category->state.wrr_count = 0; + ol_tx_sched_wrr_adv_rotate_order_list_tail(scheduler, index); + /* + * With this category moved to the back, if there's still any credit + * left, set up the next invocation of this function to start from + * where this one left off, by looking at the category that just got + * shifted forward into the position the service category was + * occupying. + */ + scheduler->index = index; + + /* + * Take the tx queue from the head of the category list. + */ + txq = TAILQ_FIRST(&category->state.head); + + if (txq){ + TAILQ_REMOVE(&category->state.head, txq, list_elem); + credit = OL_TX_TXQ_GROUP_CREDIT_LIMIT(pdev, txq, credit); + if (credit > category->specs.credit_reserve) { + credit -= category->specs.credit_reserve; + /* + * this tx queue will download some frames, + * so update last_used_txq + */ + pdev->tx_sched.last_used_txq = txq; + + tx_limit = ol_tx_bad_peer_dequeue_check(txq, category->specs.send_limit, &tx_limit_flag); + frames = ol_tx_dequeue( + pdev, txq, &sctx->head, tx_limit, &credit, &bytes); + ol_tx_bad_peer_update_tx_limit(pdev, txq, frames, tx_limit_flag); + + OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISPATCHED(category, frames); + used_credits = credit; + category->state.frms -= frames; + category->state.bytes -= bytes; + if (txq->frms > 0) { + TAILQ_INSERT_TAIL(&category->state.head, txq, list_elem); + } else { + if (category->state.frms == 0) { + category->state.active = 0; + } + } + sctx->frms += frames; + OL_TX_TXQ_GROUP_CREDIT_UPDATE(pdev, txq, -credit, 0); + } else { + if (OL_TX_IS_TXQ_LAST_SERVICED_QUEUE(pdev, txq)) { + /* + * The scheduler has looked at all the active tx queues + * but none were able to download any of their tx frames. + * Nothing is changed, so if none were able to download before, + * they wont be able to download now. + * Return that no credit has been used, which + * will cause the scheduler to stop. + */ + TAILQ_INSERT_HEAD(&category->state.head, txq, list_elem); + return 0; + } else { + TAILQ_INSERT_TAIL(&category->state.head, txq, list_elem); + if (!pdev->tx_sched.last_used_txq) { + pdev->tx_sched.last_used_txq = txq; + } + } + } + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); + } else { + used_credits = 0; + /* TODO: find its reason */ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "ol_tx_sched_select_batch_wrr_adv: error, no TXQ can be popped."); + } + return used_credits; +} + +static inline void +ol_tx_sched_txq_enqueue_wrr_adv( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid, + int frms, + int bytes) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_sched_wrr_adv_category_info_t *category; + + category = &scheduler->categories[pdev->tid_to_ac[tid]]; + category->state.frms += frms; + category->state.bytes += bytes; + OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_QUEUED(category, frms); + if (txq->flag != ol_tx_queue_active) + { + TAILQ_INSERT_TAIL(&category->state.head, txq, list_elem); + category->state.active = 1; /* may have already been active */ + } +} + +static inline void +ol_tx_sched_txq_deactivate_wrr_adv( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int tid) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_sched_wrr_adv_category_info_t *category; + + category = &scheduler->categories[pdev->tid_to_ac[tid]]; + category->state.frms -= txq->frms; + category->state.bytes -= txq->bytes; + + TAILQ_REMOVE(&category->state.head, txq, list_elem); + + if (category->state.frms == 0 && category->state.active) { + category->state.active = 0; + } +} + +ol_tx_frms_queue_list * +ol_tx_sched_category_tx_queues_wrr_adv(struct ol_txrx_pdev_t *pdev, int cat) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_sched_wrr_adv_category_info_t *category; + + category = &scheduler->categories[cat]; + return &category->state.head; +} + +int +ol_tx_sched_discard_select_category_wrr_adv(struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_sched_wrr_adv_t *scheduler; + u_int8_t i, cat = 0; + int max_score = 0; + + scheduler = pdev->tx_sched.scheduler; + /* + * Choose which category's tx frames to drop next based on two factors: + * 1. Which category has the most tx frames present + * 2. The category's priority (high-priority categories have a low + * discard_weight) + */ + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; i++) { + int score; + score = + scheduler->categories[i].state.frms * + scheduler->categories[i].specs.discard_weight; + if (max_score == 0 || score > max_score) { + max_score = score; + cat = i; + } + } + return cat; +} + +void +ol_tx_sched_txq_discard_wrr_adv( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_frms_queue_t *txq, + int cat, int frames, int bytes) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_sched_wrr_adv_category_info_t *category; + + category = &scheduler->categories[cat]; + + if (0 == txq->frms) { + TAILQ_REMOVE(&category->state.head, txq, list_elem); + } + + category->state.frms -= frames; + category->state.bytes -= bytes; + OL_TX_SCHED_WRR_ADV_CAT_STAT_INC_DISCARD(category, frames); + if (category->state.frms == 0) { + category->state.active = 0; + } +} + +void +ol_tx_sched_category_info_wrr_adv( + struct ol_txrx_pdev_t *pdev, int cat, int *active, int *frms, int *bytes) +{ + struct ol_tx_sched_wrr_adv_t *scheduler = pdev->tx_sched.scheduler; + struct ol_tx_sched_wrr_adv_category_info_t *category; + + category = &scheduler->categories[cat]; + *active = category->state.active; + *frms = category->state.frms; + *bytes = category->state.bytes; +} + +void * +ol_tx_sched_init_wrr_adv( + struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_sched_wrr_adv_t *scheduler; + int i; + + scheduler = adf_os_mem_alloc( + pdev->osdev, sizeof(struct ol_tx_sched_wrr_adv_t)); + if (scheduler == NULL) { + return scheduler; + } + adf_os_mem_zero(scheduler, sizeof(*scheduler)); + + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(VO, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(VI, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(BE, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(BK, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(NON_QOS_DATA, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(UCAST_MGMT, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(MCAST_DATA, scheduler); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(MCAST_MGMT, scheduler); + + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; i++) { + scheduler->categories[i].state.active = 0; + scheduler->categories[i].state.frms = 0; + //scheduler->categories[i].state.bytes = 0; + TAILQ_INIT(&scheduler->categories[i].state.head); + /* init categories to not be skipped before their initial selection */ + scheduler->categories[i].state.wrr_count = + scheduler->categories[i].specs.wrr_skip_weight - 1; + } + + /* + * Init the order array - the initial ordering doesn't matter, as the + * order array will get reshuffled as data arrives. + */ + for (i = 0; i < OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES; i++) { + scheduler->order[i] = i; + } + + return scheduler; +} + + +/* WMM parameters are suppposed to be passed when associate with AP. + * According to AIFS+CWMin, the function maps each queue to one of four default + * settings of the scheduler, ie. VO, VI, BE, or BK. + */ +void +ol_txrx_set_wmm_param(ol_txrx_pdev_handle data_pdev, struct ol_tx_wmm_param_t wmm_param) +{ + struct ol_tx_sched_wrr_adv_t def_cfg; + struct ol_tx_sched_wrr_adv_t *scheduler = data_pdev->tx_sched.scheduler; + u_int32_t i, ac_selected, weight[OL_TX_NUM_WMM_AC], default_edca[OL_TX_NUM_WMM_AC]; + + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(VO, (&def_cfg)); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(VI, (&def_cfg)); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(BE, (&def_cfg)); + OL_TX_SCHED_WRR_ADV_CAT_CFG_STORE(BK, (&def_cfg)); + + // default_eca = AIFS + CWMin + default_edca[OL_TX_SCHED_WRR_ADV_CAT_VO] = + OL_TX_AIFS_DEFAULT_VO + OL_TX_CW_MIN_DEFAULT_VO; + default_edca[OL_TX_SCHED_WRR_ADV_CAT_VI] = + OL_TX_AIFS_DEFAULT_VI + OL_TX_CW_MIN_DEFAULT_VI; + default_edca[OL_TX_SCHED_WRR_ADV_CAT_BE] = + OL_TX_AIFS_DEFAULT_BE + OL_TX_CW_MIN_DEFAULT_BE; + default_edca[OL_TX_SCHED_WRR_ADV_CAT_BK] = + OL_TX_AIFS_DEFAULT_BK + OL_TX_CW_MIN_DEFAULT_BK; + + weight[OL_TX_SCHED_WRR_ADV_CAT_VO] = + wmm_param.ac[OL_TX_WMM_AC_VO].aifs + wmm_param.ac[OL_TX_WMM_AC_VO].cwmin; + weight[OL_TX_SCHED_WRR_ADV_CAT_VI] = + wmm_param.ac[OL_TX_WMM_AC_VI].aifs + wmm_param.ac[OL_TX_WMM_AC_VI].cwmin; + weight[OL_TX_SCHED_WRR_ADV_CAT_BK] = + wmm_param.ac[OL_TX_WMM_AC_BK].aifs + wmm_param.ac[OL_TX_WMM_AC_BK].cwmin; + weight[OL_TX_SCHED_WRR_ADV_CAT_BE] = + wmm_param.ac[OL_TX_WMM_AC_BE].aifs + wmm_param.ac[OL_TX_WMM_AC_BE].cwmin; + + for (i = 0; i < OL_TX_NUM_WMM_AC; i++) { + + if (default_edca[OL_TX_SCHED_WRR_ADV_CAT_VO] >= weight[i]) { + ac_selected = OL_TX_SCHED_WRR_ADV_CAT_VO; + } else if (default_edca[OL_TX_SCHED_WRR_ADV_CAT_VI] >= weight[i]) { + ac_selected = OL_TX_SCHED_WRR_ADV_CAT_VI; + } else if (default_edca[OL_TX_SCHED_WRR_ADV_CAT_BE] >= weight[i]) { + ac_selected = OL_TX_SCHED_WRR_ADV_CAT_BE; + } else { + ac_selected = OL_TX_SCHED_WRR_ADV_CAT_BK; + } + + scheduler->categories[i].specs.wrr_skip_weight = + def_cfg.categories[ac_selected].specs.wrr_skip_weight; + scheduler->categories[i].specs.credit_threshold = + def_cfg.categories[ac_selected].specs.credit_threshold; + scheduler->categories[i].specs.send_limit = + def_cfg.categories[ac_selected].specs.send_limit; + scheduler->categories[i].specs.credit_reserve = + def_cfg.categories[ac_selected].specs.credit_reserve; + scheduler->categories[i].specs.discard_weight = + def_cfg.categories[ac_selected].specs.discard_weight; + } +} + +#endif /* OL_TX_SCHED == OL_TX_SCHED_WRR_ADV */ + +/*--- congestion control discard --------------------------------------------*/ + +struct ol_tx_frms_queue_t * +ol_tx_sched_discard_select_txq( + struct ol_txrx_pdev_t *pdev, + ol_tx_frms_queue_list *tx_queues) +{ + struct ol_tx_frms_queue_t *txq; + struct ol_tx_frms_queue_t *selected_txq = NULL; + int max_frms = 0; + + /* return the tx queue with the most frames */ + TAILQ_FOREACH(txq, tx_queues, list_elem) { + if (txq->frms > max_frms) { + max_frms = txq->frms; + selected_txq = txq; + } + } + return selected_txq; +} + +u_int16_t +ol_tx_sched_discard_select( + struct ol_txrx_pdev_t *pdev, + u_int16_t frms, + ol_tx_desc_list *tx_descs, + a_bool_t force) +{ + int cat; + struct ol_tx_frms_queue_t *txq; + int bytes; + u_int32_t credit; + struct ol_tx_sched_notify_ctx_t notify_ctx; + + /* first decide what category of traffic (e.g. TID or AC) to discard next */ + cat = ol_tx_sched_discard_select_category(pdev); + + /* then decide which peer within this category to discard from next */ + txq = ol_tx_sched_discard_select_txq( + pdev, ol_tx_sched_category_tx_queues(pdev, cat)); + if (NULL == txq) + { + /* No More pending Tx Packets in Tx Queue. Exit Discard loop */ + return 0; + } + + if (force == A_FALSE) { + /* + * Now decide how many frames to discard from this peer-TID. + * Don't discard more frames than the caller has specified. + * Don't discard more than a fixed quantum of frames at a time. + * Don't discard more than 50% of the queue's frames at a time, + * but if there's only 1 frame left, go ahead and discard it. + */ + #define OL_TX_DISCARD_QUANTUM 10 + if (OL_TX_DISCARD_QUANTUM < frms) { + frms = OL_TX_DISCARD_QUANTUM; + } + + if (txq->frms > 1 && frms >= (txq->frms >> 1)) { + frms = txq->frms >> 1; + } + } + + /* + * Discard from the head of the queue, because: + * 1. Front-dropping gives applications like TCP that include ARQ + * an early notification of congestion. + * 2. For time-sensitive applications like RTP, the newest frames are + * most relevant. + */ + credit = 10000; /* no credit limit */ + frms = ol_tx_dequeue(pdev, txq, tx_descs, frms, &credit, &bytes); + + notify_ctx.event = OL_TX_DISCARD_FRAMES; + notify_ctx.frames = frms; + notify_ctx.bytes = bytes; + notify_ctx.txq = txq; + notify_ctx.info.ext_tid = cat; + ol_tx_sched_notify(pdev, ¬ify_ctx); + + TX_SCHED_DEBUG_PRINT("%s Tx Drop : %d\n",__func__,frms); + return frms; +} + +/*--- scheduler framework ---------------------------------------------------*/ + +/* + * The scheduler mutex spinlock has been acquired outside this function, + * so there is need to take locks inside this function. + */ +void +ol_tx_sched_notify( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_sched_notify_ctx_t *ctx) +{ + struct ol_tx_frms_queue_t *txq = ctx->txq; + int tid; + + if (!pdev->tx_sched.scheduler) { + return; + } + + switch (ctx->event) { + case OL_TX_ENQUEUE_FRAME: + tid = ctx->info.tx_msdu_info->htt.info.ext_tid; + ol_tx_sched_txq_enqueue(pdev, txq, tid, 1, ctx->bytes); + break; + case OL_TX_DELETE_QUEUE: + tid = ctx->info.ext_tid; + if (txq->flag == ol_tx_queue_active) { + ol_tx_sched_txq_deactivate(pdev, txq, tid); + } + break; + case OL_TX_PAUSE_QUEUE: + tid = ctx->info.ext_tid; + if (txq->flag == ol_tx_queue_active) { + ol_tx_sched_txq_deactivate(pdev, txq, tid); + } + break; + case OL_TX_UNPAUSE_QUEUE: + tid = ctx->info.ext_tid; + if (txq->frms != 0) { + ol_tx_sched_txq_enqueue(pdev, txq, tid, txq->frms, txq->bytes); + } + break; + case OL_TX_DISCARD_FRAMES: + tid = ctx->info.ext_tid; /* not necessarily TID, could be category */ + ol_tx_sched_txq_discard(pdev, txq, tid, ctx->frames, ctx->bytes); + break; + default: + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Error: unknown sched notification (%d)\n", ctx->event); + adf_os_assert(0); + break; + } +} + +#define OL_TX_MSDU_ID_STORAGE_ERR(ptr) (NULL == ptr) + +void +ol_tx_sched_dispatch( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_sched_ctx *sctx) +{ + adf_nbuf_t msdu, prev = NULL, head_msdu = NULL; + struct ol_tx_desc_t *tx_desc; + + u_int16_t *msdu_id_storage; + u_int16_t msdu_id; + int num_msdus = 0; + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + while (sctx->frms) + { + tx_desc = TAILQ_FIRST(&sctx->head); + if (tx_desc == NULL){ + /* TODO: find its reason */ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%s: err, no enough tx_desc from stx->head.\n", __func__); + break; + } + msdu = tx_desc->netbuf; + TAILQ_REMOVE(&sctx->head, tx_desc, tx_desc_list_elem); + if (NULL == head_msdu) + { + head_msdu = msdu; + } + if (prev) + { + adf_nbuf_set_next(prev, msdu); + } + prev = msdu; + +#ifndef ATH_11AC_TXCOMPACT + /* + * When the tx frame is downloaded to the target, there are two + * outstanding references: + * 1. The host download SW (HTT, HTC, HIF) + * This reference is cleared by the ol_tx_send_done callback + * functions. + * 2. The target FW + * This reference is cleared by the ol_tx_completion_handler + * function. + * It is extremely probable that the download completion is processed + * before the tx completion message. However, under exceptional + * conditions the tx completion may be processed first. Thus, rather + * that assuming that reference (1) is done before reference (2), + * explicit reference tracking is needed. + * Double-increment the ref count to account for both references + * described above. + */ + adf_os_atomic_init(&tx_desc->ref_cnt); + adf_os_atomic_inc(&tx_desc->ref_cnt); + adf_os_atomic_inc(&tx_desc->ref_cnt); +#endif + + //Store the MSDU Id for each MSDU + /* store MSDU ID */ + msdu_id = ol_tx_desc_id(pdev, tx_desc); + msdu_id_storage = ol_tx_msdu_id_storage(msdu); + if (OL_TX_MSDU_ID_STORAGE_ERR(msdu_id_storage)) { + /* + * Send the prior frames as a batch, then send this as a single, + * then resume handling the remaining frames. + */ + if (head_msdu){ + ol_tx_send_batch(pdev, head_msdu, num_msdus); + } + head_msdu = prev = NULL; + num_msdus = 0; + + if (htt_tx_send_std(pdev->htt_pdev, msdu, msdu_id)) { + OL_TX_TARGET_CREDIT_INCR(pdev, msdu); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1 /* error */); + } + } else { + *msdu_id_storage = msdu_id; + num_msdus++; + } + sctx->frms--; + } + + //Send Batch Of Frames + if (head_msdu) + { + ol_tx_send_batch(pdev,head_msdu,num_msdus); + } + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void +ol_tx_sched(struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_sched_ctx sctx; + u_int32_t credit; + + TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + if (pdev->tx_sched.tx_sched_status != ol_tx_scheduler_idle) { + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + return; + } + pdev->tx_sched.tx_sched_status = ol_tx_scheduler_running; + + OL_TX_SCHED_LOG(pdev); + //adf_os_print("BEFORE tx sched:\n"); + //ol_tx_queues_display(pdev); + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + + TAILQ_INIT(&sctx.head); + sctx.frms = 0; + + ol_tx_sched_select_init(pdev); + while (adf_os_atomic_read(&pdev->target_tx_credit) > 0) { + int num_credits; + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + credit = adf_os_atomic_read(&pdev->target_tx_credit); + num_credits = ol_tx_sched_select_batch(pdev, &sctx, credit); + if (num_credits > 0){ +#if DEBUG_HTT_CREDIT + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " Decrease credit %d - %d = %d.\n", + adf_os_atomic_read(&pdev->target_tx_credit), + num_credits, + adf_os_atomic_read(&pdev->target_tx_credit) - num_credits); +#endif + adf_os_atomic_add(-num_credits, &pdev->target_tx_credit); + } + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + + if (num_credits == 0) break; + } + ol_tx_sched_dispatch(pdev, &sctx); + + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + //adf_os_print("AFTER tx sched:\n"); + //ol_tx_queues_display(pdev); + + pdev->tx_sched.tx_sched_status = ol_tx_scheduler_idle; + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void * +ol_tx_sched_attach( + struct ol_txrx_pdev_t *pdev) +{ + pdev->tx_sched.tx_sched_status = ol_tx_scheduler_idle; + return ol_tx_sched_init(pdev); +} + +void +ol_tx_sched_detach( + struct ol_txrx_pdev_t *pdev) +{ + if (pdev->tx_sched.scheduler) { + adf_os_mem_free(pdev->tx_sched.scheduler); + pdev->tx_sched.scheduler = NULL; + } +} + +/*--- debug functions -------------------------------------------------------*/ + +#if defined(DEBUG_HL_LOGGING) + +static void +ol_tx_sched_log(struct ol_txrx_pdev_t *pdev) +{ + u_int8_t *buf; + u_int32_t *active_bitmap; + int i, j, num_cats_active; + int active, frms, bytes; + int credit; + + /* don't bother recording state if credit is zero */ + credit = adf_os_atomic_read(&pdev->target_tx_credit); + if (credit == 0) { + return; + } + + /* + * See how many TIDs are active, so queue state can be stored only + * for those TIDs. + * Do an initial iteration through all categories to see if any + * are active. Doing an extra iteration is inefficient, but + * efficiency is not a dominant concern when logging is enabled. + */ + num_cats_active = 0; + for (i = 0; i < OL_TX_SCHED_NUM_CATEGORIES; i++) { + ol_tx_sched_category_info(pdev, i, &active, &frms, &bytes); + if (active) { + num_cats_active++; + } + } + /* don't bother recording state if there are no active queues */ + if (num_cats_active == 0) { + return; + } + + OL_TX_QUEUE_LOG_SCHED(pdev, credit, &num_cats_active, &active_bitmap, &buf); + + if (num_cats_active == 0) { + return; + } + *active_bitmap = 0; + for (i = 0, j = 0; + i < OL_TX_SCHED_NUM_CATEGORIES && j < num_cats_active; + i++) + { + u_int8_t *p; + ol_tx_sched_category_info(pdev, i, &active, &frms, &bytes); + if (!active) { + continue; + } + p = &buf[j*6]; + p[0] = (frms >> 0) & 0xff; + p[1] = (frms >> 8) & 0xff; + + p[2] = (bytes >> 0) & 0xff; + p[3] = (bytes >> 8) & 0xff; + p[4] = (bytes >> 16) & 0xff; + p[5] = (bytes >> 24) & 0xff; + j++; + *active_bitmap |= 1 << i; + } +} + +#endif /* defined(DEBUG_HL_LOGGING) */ + +void ol_tx_sched_stats_display(struct ol_txrx_pdev_t *pdev) +{ + OL_TX_SCHED_WRR_ADV_CAT_STAT_DUMP(pdev->tx_sched.scheduler); +} + +void ol_tx_sched_cur_state_display(struct ol_txrx_pdev_t *pdev) +{ + OL_TX_SCHED_WRR_ADV_CAT_CUR_STATE_DUMP(pdev->tx_sched.scheduler); +} + +void ol_tx_sched_stats_clear(struct ol_txrx_pdev_t *pdev) +{ + OL_TX_SCHED_WRR_ADV_CAT_STAT_CLEAR(pdev->tx_sched.scheduler); +} + +#endif /* defined(CONFIG_HL_SUPPORT) */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.h new file mode 100644 index 000000000000..7f67f971fd9e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_sched.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_tx_sched.h + * @brief API definitions for the tx scheduler module within the data SW. + */ +#ifndef _OL_TX_SCHED__H_ +#define _OL_TX_SCHED__H_ + +#include /* a_bool_t */ + +enum ol_tx_queue_action { + OL_TX_ENQUEUE_FRAME, + OL_TX_DELETE_QUEUE, + OL_TX_PAUSE_QUEUE, + OL_TX_UNPAUSE_QUEUE, + OL_TX_DISCARD_FRAMES, +}; + +struct ol_tx_sched_notify_ctx_t { + int event; + struct ol_tx_frms_queue_t *txq; + union { + int ext_tid; + struct ol_txrx_msdu_info_t *tx_msdu_info; + } info; + int frames; + int bytes; +}; + +#if defined(CONFIG_HL_SUPPORT) + +void +ol_tx_sched_notify( + struct ol_txrx_pdev_t *pdev, struct ol_tx_sched_notify_ctx_t *ctx); + +void +ol_tx_sched(struct ol_txrx_pdev_t *pdev); + +u_int16_t +ol_tx_sched_discard_select( + struct ol_txrx_pdev_t *pdev, + u_int16_t frms, + ol_tx_desc_list *tx_descs, + a_bool_t force); + +void * +ol_tx_sched_attach(struct ol_txrx_pdev_t *pdev); + +void +ol_tx_sched_detach(struct ol_txrx_pdev_t *pdev); + +void ol_tx_sched_stats_display(struct ol_txrx_pdev_t *pdev); + +void ol_tx_sched_cur_state_display(struct ol_txrx_pdev_t *pdev); + +void ol_tx_sched_stats_clear(struct ol_txrx_pdev_t *pdev); + +#else + +#define ol_tx_notify_sched(pdev, ctx) /* no-op */ +#define ol_tx_sched(pdev) /* no-op */ +#define ol_tx_sched_discard_select(pdev, frms, tx_descs, force) 0 +#define ol_tx_sched_attach(pdev) NULL +#define ol_tx_sched_detach(pdev) /* no-op */ +#define ol_tx_sched_stats_display(pdev) /* no-op */ +#define ol_tx_sched_cur_state_display(pdev) /* no-op */ +#define ol_tx_sched_stats_clear(pdev) /* no-op */ + +#endif /* defined(CONFIG_HL_SUPPORT) */ + + +#if defined(CONFIG_HL_SUPPORT) || defined(TX_CREDIT_RECLAIM_SUPPORT) +/* + * HL needs to keep track of the amount of credit available to download + * tx frames to the target - the download scheduler decides when to + * download frames, and which frames to download, based on the credit + * availability. + * LL systems that use TX_CREDIT_RECLAIM_SUPPORT also need to keep track + * of the target_tx_credit, to determine when to poll for tx completion + * messages. + */ +#define OL_TX_TARGET_CREDIT_ADJUST(factor, pdev, msdu) \ + adf_os_atomic_add( \ + factor * htt_tx_msdu_credit(msdu), &pdev->target_tx_credit) +#define OL_TX_TARGET_CREDIT_DECR(pdev, msdu) \ + OL_TX_TARGET_CREDIT_ADJUST(-1, pdev, msdu) +#define OL_TX_TARGET_CREDIT_INCR(pdev, msdu) \ + OL_TX_TARGET_CREDIT_ADJUST(1, pdev, msdu) +#else +/* + * LL does not need to keep track of target credit. + * Since the host tx descriptor pool size matches the target's, + * we know the target has space for the new tx frame if the host's + * tx descriptor allocation succeeded. + */ +#define OL_TX_TARGET_CREDIT_DECR(pdev, msdu) /* no-op */ +#define OL_TX_TARGET_CREDIT_INCR(pdev, msdu) /* no-op */ +#define OL_TX_TARGET_CREDIT_ADJUST(factor, pdev, msdu) /* no-op */ + +#endif + +#endif /* _OL_TX_SCHED__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.c new file mode 100644 index 000000000000..ce70cb302cd9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.c @@ -0,0 +1,1133 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* adf_os_atomic_inc, etc. */ +#include /* adf_os_spinlock */ +#include /* adf_os_ticks, etc. */ +#include /* adf_nbuf_t */ +#include /* ADF_NBUF_TX_EXT_TID_INVALID */ + +#include /* TAILQ */ +#ifdef QCA_COMPUTE_TX_DELAY +#include /* ieee80211_frame, etc. */ +#include /* ethernet_hdr_t, etc. */ +#include /* IPV6_TRAFFIC_CLASS */ +#endif + +#include /* ol_txrx_vdev_handle, etc. */ +#include /* htt_tx_compl_desc_id */ +#include /* htt_tx_status */ + +#include +#include /* ol_txrx_vdev_t, etc */ +#include /* ol_tx_desc_find, ol_tx_desc_frame_free */ +#ifdef QCA_COMPUTE_TX_DELAY +#include /* ol_tx_dest_addr_find */ +#endif +#include /* OL_TX_DESC_NO_REFS, etc. */ +#include +#include /* ol_tx_reinject */ + +#include /* ol_cfg_is_high_latency */ +#include +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP +#include /* OL_TX_RESTORE_HDR, etc*/ +#endif +#include +#include + +#ifdef TX_CREDIT_RECLAIM_SUPPORT + +#define OL_TX_CREDIT_RECLAIM(pdev) \ + do { \ + if (adf_os_atomic_read(&pdev->target_tx_credit) < \ + ol_cfg_tx_credit_lwm(pdev->ctrl_pdev)) { \ + ol_osif_ath_tasklet(pdev->osdev); \ + } \ + } while (0) + +#else + +#define OL_TX_CREDIT_RECLAIM(pdev) + +#endif /* TX_CREDIT_RECLAIM_SUPPORT */ + +#if defined(CONFIG_HL_SUPPORT) || defined(TX_CREDIT_RECLAIM_SUPPORT) +/* + * HL needs to keep track of the amount of credit available to download + * tx frames to the target - the download scheduler decides when to + * download frames, and which frames to download, based on the credit + * availability. + * LL systems that use TX_CREDIT_RECLAIM_SUPPORT also need to keep track + * of the target_tx_credit, to determine when to poll for tx completion + * messages. + */ +#define OL_TX_TARGET_CREDIT_ADJUST(factor, pdev, msdu) \ + adf_os_atomic_add( \ + factor * htt_tx_msdu_credit(msdu), &pdev->target_tx_credit) +#define OL_TX_TARGET_CREDIT_DECR(pdev, msdu) \ + OL_TX_TARGET_CREDIT_ADJUST(-1, pdev, msdu) +#define OL_TX_TARGET_CREDIT_INCR(pdev, msdu) \ + OL_TX_TARGET_CREDIT_ADJUST(1, pdev, msdu) +#define OL_TX_TARGET_CREDIT_DECR_INT(pdev, delta) \ + adf_os_atomic_add(-1 * delta, &pdev->target_tx_credit) +#define OL_TX_TARGET_CREDIT_INCR_INT(pdev, delta) \ + adf_os_atomic_add(delta, &pdev->target_tx_credit) +#else +/* + * LL does not need to keep track of target credit. + * Since the host tx descriptor pool size matches the target's, + * we know the target has space for the new tx frame if the host's + * tx descriptor allocation succeeded. + */ +#define OL_TX_TARGET_CREDIT_ADJUST(factor, pdev, msdu) /* no-op */ +#define OL_TX_TARGET_CREDIT_DECR(pdev, msdu) /* no-op */ +#define OL_TX_TARGET_CREDIT_INCR(pdev, msdu) /* no-op */ +#define OL_TX_TARGET_CREDIT_DECR_INT(pdev, delta) /* no-op */ +#define OL_TX_TARGET_CREDIT_INCR_INT(pdev, delta) /* no-op */ +#endif + +#ifdef QCA_LL_TX_FLOW_CT +#ifdef CONFIG_PER_VDEV_TX_DESC_POOL +#define OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev) \ +do { \ + struct ol_txrx_vdev_t *vdev; \ + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { \ + if (adf_os_atomic_read(&vdev->os_q_paused) && \ + (vdev->tx_fl_hwm != 0)) { \ + adf_os_spin_lock(&pdev->tx_mutex); \ + if (((ol_tx_desc_pool_size_hl(vdev->pdev->ctrl_pdev) >> 1) \ + - TXRX_HL_TX_FLOW_CTRL_MGMT_RESERVED) \ + - adf_os_atomic_read(&vdev->tx_desc_count) \ + > vdev->tx_fl_hwm) \ + { \ + adf_os_atomic_set(&vdev->os_q_paused, 0); \ + adf_os_spin_unlock(&pdev->tx_mutex); \ + vdev->osif_flow_control_cb(vdev->osif_dev, \ + vdev->vdev_id, A_TRUE); \ + } \ + else { \ + adf_os_spin_unlock(&pdev->tx_mutex); \ + } \ + } \ + } \ +} while(0) +#else +#define OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev) \ +do { \ + struct ol_txrx_vdev_t *vdev; \ + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { \ + if (adf_os_atomic_read(&vdev->os_q_paused) && \ + (vdev->tx_fl_hwm != 0)) { \ + adf_os_spin_lock(&pdev->tx_mutex); \ + if (pdev->tx_desc.num_free > vdev->tx_fl_hwm) { \ + adf_os_atomic_set(&vdev->os_q_paused, 0); \ + adf_os_spin_unlock(&pdev->tx_mutex); \ + vdev->osif_flow_control_cb(vdev->osif_dev, \ + vdev->vdev_id, A_TRUE); \ + } \ + else { \ + adf_os_spin_unlock(&pdev->tx_mutex); \ + } \ + } \ + } \ +} while(0) +#endif +#else +#define OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev) +#endif /* QCA_LL_TX_FLOW_CT */ + + +static inline u_int16_t +ol_tx_send_base( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu) +{ + int msdu_credit_consumed; + + TX_CREDIT_DEBUG_PRINT("TX %d bytes\n", adf_nbuf_len(msdu)); + TX_CREDIT_DEBUG_PRINT(" Decrease credit %d - 1 = %d, len:%d.\n", + adf_os_atomic_read(&pdev->target_tx_credit), + adf_os_atomic_read(&pdev->target_tx_credit) - 1, + adf_nbuf_len(msdu)); + + msdu_credit_consumed = htt_tx_msdu_credit(msdu); + OL_TX_TARGET_CREDIT_DECR_INT(pdev, msdu_credit_consumed); + OL_TX_CREDIT_RECLAIM(pdev); + + /* + * When the tx frame is downloaded to the target, there are two + * outstanding references: + * 1. The host download SW (HTT, HTC, HIF) + * This reference is cleared by the ol_tx_send_done callback + * functions. + * 2. The target FW + * This reference is cleared by the ol_tx_completion_handler + * function. + * It is extremely probable that the download completion is processed + * before the tx completion message. However, under exceptional + * conditions the tx completion may be processed first. Thus, rather + * that assuming that reference (1) is done before reference (2), + * explicit reference tracking is needed. + * Double-increment the ref count to account for both references + * described above. + */ + + OL_TX_DESC_REF_INIT(tx_desc); + OL_TX_DESC_REF_INC(tx_desc); + OL_TX_DESC_REF_INC(tx_desc); + + return msdu_credit_consumed; +} + +void +ol_tx_send( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu) +{ + int msdu_credit_consumed; + u_int16_t id; + int failed; + + msdu_credit_consumed = ol_tx_send_base(pdev, tx_desc, msdu); + id = ol_tx_desc_id(pdev, tx_desc); + failed = htt_tx_send_std(pdev->htt_pdev, msdu, id); + if (adf_os_unlikely(failed)) { + OL_TX_TARGET_CREDIT_INCR_INT(pdev, msdu_credit_consumed); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1 /* had error */); + } +} + +void +ol_tx_send_batch( + struct ol_txrx_pdev_t *pdev, + adf_nbuf_t head_msdu, int num_msdus) +{ + adf_nbuf_t rejected; + OL_TX_CREDIT_RECLAIM(pdev); + + rejected = htt_tx_send_batch(pdev->htt_pdev, head_msdu, num_msdus); + while (adf_os_unlikely(rejected)) { + struct ol_tx_desc_t *tx_desc; + u_int16_t *msdu_id_storage; + adf_nbuf_t next; + + next = adf_nbuf_next(rejected); + msdu_id_storage = ol_tx_msdu_id_storage(rejected); + tx_desc = ol_tx_desc_find(pdev, *msdu_id_storage); + + OL_TX_TARGET_CREDIT_INCR(pdev, rejected); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1 /* had error */); + + rejected = next; + } +} + +void +ol_tx_send_nonstd( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + enum htt_pkt_type pkt_type) +{ + int msdu_credit_consumed; + u_int16_t id; + int failed; + + msdu_credit_consumed = ol_tx_send_base(pdev, tx_desc, msdu); + id = ol_tx_desc_id(pdev, tx_desc); + failed = htt_tx_send_nonstd( + pdev->htt_pdev, msdu, id, pkt_type); + if (failed) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Error: freeing tx frame after htt_tx failed"); + OL_TX_TARGET_CREDIT_INCR_INT(pdev, msdu_credit_consumed); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1 /* had error */); + } +} + +static inline void +ol_tx_download_done_base( + struct ol_txrx_pdev_t *pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id) +{ + struct ol_tx_desc_t *tx_desc; + + tx_desc = ol_tx_desc_find(pdev, msdu_id); + adf_os_assert(tx_desc); + + /* + * If the download is done for + * the Management frame then + * call the download callback if registered + */ + if (tx_desc->pkt_type >= OL_TXRX_MGMT_TYPE_BASE) { + int tx_mgmt_index = tx_desc->pkt_type - OL_TXRX_MGMT_TYPE_BASE; + ol_txrx_mgmt_tx_cb download_cb = + pdev->tx_mgmt.callbacks[tx_mgmt_index].download_cb; + + if (download_cb) { + download_cb(pdev->tx_mgmt.callbacks[tx_mgmt_index].ctxt, + tx_desc->netbuf, status != A_OK); + } + } + + if (status != A_OK) { + OL_TX_TARGET_CREDIT_INCR(pdev, msdu); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, 1 /* download err */); + } else { + if (OL_TX_DESC_NO_REFS(tx_desc)) { + /* + * The decremented value was zero - free the frame. + * Use the tx status recorded previously during + * tx completion handling. + */ + ol_tx_desc_frame_free_nonstd( + pdev, tx_desc, tx_desc->status != htt_tx_status_ok); + } + } +} + +void +ol_tx_download_done_ll( + void *pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id) +{ + ol_tx_download_done_base( + (struct ol_txrx_pdev_t *) pdev, status, msdu, msdu_id); +} + +void +ol_tx_download_done_hl_retain( + void *txrx_pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id) +{ + struct ol_txrx_pdev_t *pdev = txrx_pdev; + ol_tx_download_done_base(pdev, status, msdu, msdu_id); +#if 0 /* TODO: Advanced feature */ + //ol_tx_dwl_sched(pdev, OL_TX_HL_SCHED_DOWNLOAD_DONE); +adf_os_assert(0); +#endif +} + +void +ol_tx_download_done_hl_free( + void *txrx_pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id) +{ + struct ol_txrx_pdev_t *pdev = txrx_pdev; + struct ol_tx_desc_t *tx_desc; + + tx_desc = ol_tx_desc_find(pdev, msdu_id); + adf_os_assert(tx_desc); + + ol_tx_download_done_base(pdev, status, msdu, msdu_id); + + if ((tx_desc->pkt_type != ol_tx_frm_no_free) && + (tx_desc->pkt_type < OL_TXRX_MGMT_TYPE_BASE)) { + adf_os_atomic_add(1, &pdev->tx_queue.rsrc_cnt); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, status != A_OK); + } +#if 0 /* TODO: Advanced feature */ + //ol_tx_dwl_sched(pdev, OL_TX_HL_SCHED_DOWNLOAD_DONE); +adf_os_assert(0); +#endif +} + +void +ol_tx_target_credit_init(struct ol_txrx_pdev_t *pdev, int credit_delta) +{ + adf_os_atomic_add(credit_delta, &pdev->orig_target_tx_credit); +} + +void +ol_tx_target_credit_update(struct ol_txrx_pdev_t *pdev, int credit_delta) +{ + TX_CREDIT_DEBUG_PRINT(" Increase credit %d + %d = %d\n", + adf_os_atomic_read(&pdev->target_tx_credit), + credit_delta, + adf_os_atomic_read(&pdev->target_tx_credit) + credit_delta); + adf_os_atomic_add(credit_delta, &pdev->target_tx_credit); +} + +#ifdef QCA_COMPUTE_TX_DELAY + +static void +ol_tx_delay_compute( + struct ol_txrx_pdev_t *pdev, + enum htt_tx_status status, + u_int16_t *desc_ids, + int num_msdus); +#define OL_TX_DELAY_COMPUTE ol_tx_delay_compute +#else +#define OL_TX_DELAY_COMPUTE(pdev, status, desc_ids, num_msdus) /* no-op */ +#endif /* QCA_COMPUTE_TX_DELAY */ + +#ifndef OL_TX_RESTORE_HDR +#define OL_TX_RESTORE_HDR(__tx_desc, __msdu) +#endif +/* + * The following macros could have been inline functions too. + * The only rationale for choosing macros, is to force the compiler to inline + * the implementation, which cannot be controlled for actual "inline" functions, + * since "inline" is only a hint to the compiler. + * In the performance path, we choose to force the inlining, in preference to + * type-checking offered by the actual inlined functions. + */ +#define ol_tx_msdu_complete_batch(_pdev, _tx_desc, _tx_descs, _status) \ + do { \ + TAILQ_INSERT_TAIL(&(_tx_descs), (_tx_desc), tx_desc_list_elem); \ + } while (0) +#ifndef ATH_11AC_TXCOMPACT +#define ol_tx_msdu_complete_single(_pdev, _tx_desc, _netbuf, _lcl_freelist, _tx_desc_last) \ + do { \ + adf_os_atomic_init(&(_tx_desc)->ref_cnt); /* clear the ref cnt */ \ + OL_TX_RESTORE_HDR((_tx_desc), (_netbuf)); /* restore orginal hdr offset */ \ + adf_nbuf_unmap((_pdev)->osdev, (_netbuf), ADF_OS_DMA_TO_DEVICE); \ + adf_nbuf_free((_netbuf)); \ + ((struct ol_tx_desc_list_elem_t *)(_tx_desc))->next = (_lcl_freelist); \ + if (adf_os_unlikely(!lcl_freelist)) { \ + (_tx_desc_last) = (struct ol_tx_desc_list_elem_t *)(_tx_desc); \ + } \ + (_lcl_freelist) = (struct ol_tx_desc_list_elem_t *)(_tx_desc); \ + } while (0) +#else /*!ATH_11AC_TXCOMPACT*/ + +#define ol_tx_msdu_complete_single(_pdev, _tx_desc, _netbuf, _lcl_freelist, _tx_desc_last) \ + do { \ + OL_TX_RESTORE_HDR((_tx_desc), (_netbuf)); /* restore orginal hdr offset */ \ + adf_nbuf_unmap((_pdev)->osdev, (_netbuf), ADF_OS_DMA_TO_DEVICE); \ + adf_nbuf_free((_netbuf)); \ + ((struct ol_tx_desc_list_elem_t *)(_tx_desc))->next = (_lcl_freelist); \ + if (adf_os_unlikely(!lcl_freelist)) { \ + (_tx_desc_last) = (struct ol_tx_desc_list_elem_t *)(_tx_desc); \ + } \ + (_lcl_freelist) = (struct ol_tx_desc_list_elem_t *)(_tx_desc); \ + } while (0) + + +#endif /*!ATH_11AC_TXCOMPACT*/ + +#ifdef QCA_TX_SINGLE_COMPLETIONS + #ifdef QCA_TX_STD_PATH_ONLY + #define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \ + _tx_desc_last, _status) \ + ol_tx_msdu_complete_single((_pdev), (_tx_desc), (_netbuf), (_lcl_freelist), \ + _tx_desc_last) + #else /* !QCA_TX_STD_PATH_ONLY */ + #define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \ + _tx_desc_last, _status) \ + do { \ + if (adf_os_likely((_tx_desc)->pkt_type == ol_tx_frm_std)) { \ + ol_tx_msdu_complete_single((_pdev), (_tx_desc), (_netbuf), (_lcl_freelist), \ + (_tx_desc_last)); \ + } else { \ + ol_tx_desc_frame_free_nonstd( \ + (_pdev), (_tx_desc), (_status) != htt_tx_status_ok); \ + } \ + } while (0) + #endif /* !QCA_TX_STD_PATH_ONLY */ +#else /* !QCA_TX_SINGLE_COMPLETIONS */ + #ifdef QCA_TX_STD_PATH_ONLY + #define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \ + _tx_desc_last, _status) \ + ol_tx_msdus_complete_batch((_pdev), (_tx_desc), (_tx_descs), (_status)) + #else /* !QCA_TX_STD_PATH_ONLY */ + #define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \ + _tx_desc_last, _status) \ + do { \ + if (adf_os_likely((_tx_desc)->pkt_type == ol_tx_frm_std)) { \ + ol_tx_msdu_complete_batch((_pdev), (_tx_desc), (_tx_descs), (_status)); \ + } else { \ + ol_tx_desc_frame_free_nonstd( \ + (_pdev), (_tx_desc), (_status) != htt_tx_status_ok); \ + } \ + } while (0) + #endif /* !QCA_TX_STD_PATH_ONLY */ +#endif /* QCA_TX_SINGLE_COMPLETIONS */ + +void +ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev) +{ + int i = 0; + for (i = 0; i < pdev->tx_desc.pool_size; i++) { + + /* + * Confirm that each tx descriptor is "empty", i.e. it has + * no tx frame attached. + * In particular, check that there are no frames that have + * been given to the target to transmit, for which the + * target has never provided a response. + */ + if (adf_os_atomic_read(&pdev->tx_desc.array[i].tx_desc->ref_cnt)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "Warning: freeing tx frame " + "(no tx completion from the target)\n"); + ol_tx_desc_frame_free_nonstd( + pdev, pdev->tx_desc.array[i].tx_desc, 1); + } + } +} + +void +ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits) +{ + ol_tx_target_credit_update(pdev, credits); + if (pdev->cfg.is_high_latency) { + ol_tx_sched(pdev); + } + /* UNPAUSE OS Q */ + OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev); +} + +/* WARNING: ol_tx_inspect_handler()'s bahavior is similar to that of ol_tx_completion_handler(). + * any change in ol_tx_completion_handler() must be mirrored in ol_tx_inspect_handler(). + */ +void +ol_tx_completion_handler( + ol_txrx_pdev_handle pdev, + int num_msdus, + enum htt_tx_status status, + void *tx_desc_id_iterator) +{ + int i; + u_int16_t *desc_ids = (u_int16_t *)tx_desc_id_iterator; + u_int16_t tx_desc_id; + struct ol_tx_desc_t *tx_desc; + char *trace_str; + + uint32_t byte_cnt = 0; + struct ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + adf_nbuf_t netbuf; + + struct ol_tx_desc_list_elem_t *lcl_freelist = NULL; + struct ol_tx_desc_list_elem_t *tx_desc_last = NULL; + ol_tx_desc_list tx_descs; + TAILQ_INIT(&tx_descs); + + OL_TX_DELAY_COMPUTE(pdev, status, desc_ids, num_msdus); + + trace_str = (status) ? "OT:C:F:" : "OT:C:S:"; + for (i = 0; i < num_msdus; i++) { + tx_desc_id = desc_ids[i]; + tx_desc = td_array[tx_desc_id].tx_desc; + tx_desc->status = status; + netbuf = tx_desc->netbuf; + + if (pdev->cfg.is_high_latency) { + OL_TX_DESC_UPDATE_GROUP_CREDIT(pdev, tx_desc_id, 1, 0, status); + } + + htc_pm_runtime_put(pdev->htt_pdev->htc_pdev); + adf_nbuf_trace_update(netbuf, trace_str); + /* Per SDU update of byte count */ + byte_cnt += adf_nbuf_len(netbuf); + if (OL_TX_DESC_NO_REFS(tx_desc)) { + ol_tx_statistics(pdev->ctrl_pdev, + HTT_TX_DESC_VDEV_ID_GET(*((u_int32_t *)(tx_desc->htt_tx_desc))), + status != htt_tx_status_ok); + ol_tx_msdu_complete( + pdev, tx_desc, tx_descs, netbuf, + lcl_freelist, tx_desc_last, status); + } +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS + tx_desc->pkt_type = 0xff; +#ifdef QCA_COMPUTE_TX_DELAY + tx_desc->entry_timestamp_ticks = 0xffffffff; +#endif +#endif + } + + /* One shot protected access to pdev freelist, when setup */ + if (lcl_freelist) { + adf_os_spin_lock(&pdev->tx_mutex); + tx_desc_last->next = pdev->tx_desc.freelist; + pdev->tx_desc.freelist = lcl_freelist; + pdev->tx_desc.num_free += (u_int16_t) num_msdus; + adf_os_spin_unlock(&pdev->tx_mutex); + } else { + ol_tx_desc_frame_list_free(pdev, &tx_descs, status != htt_tx_status_ok); + } + if (pdev->cfg.is_high_latency) { + /* + * Credit was already explicitly updated by HTT, + * but update the number of available tx descriptors, + * then invoke the scheduler, since new credit is probably + * available now. + */ + adf_os_atomic_add(num_msdus, &pdev->tx_queue.rsrc_cnt); + ol_tx_sched(pdev); + } else { + OL_TX_TARGET_CREDIT_ADJUST(num_msdus, pdev, NULL); + } + + /* UNPAUSE OS Q */ + OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev); + /* Do one shot statistics */ + TXRX_STATS_UPDATE_TX_STATS(pdev, status, num_msdus, byte_cnt); +} + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +void +ol_tx_desc_update_group_credit(ol_txrx_pdev_handle pdev, u_int16_t tx_desc_id, + int credit, u_int8_t absolute, enum htt_tx_status status) +{ + uint8_t i, is_member; + uint16_t vdev_id_mask; + struct ol_tx_desc_t *tx_desc; + struct ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + + tx_desc = td_array[tx_desc_id].tx_desc; + + for (i = 0; i < OL_TX_MAX_TXQ_GROUPS; i++) { + vdev_id_mask = + OL_TXQ_GROUP_VDEV_ID_MASK_GET(pdev->txq_grps[i].membership); + is_member = OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(vdev_id_mask, + tx_desc->vdev->vdev_id); + if (is_member) { + ol_txrx_update_group_credit(&pdev->txq_grps[i], + credit, absolute); + break; + } + } + OL_TX_UPDATE_GROUP_CREDIT_STATS(pdev); +} + +#ifdef DEBUG_HL_LOGGING +void +ol_tx_update_group_credit_stats(ol_txrx_pdev_handle pdev) +{ + uint16 curr_index; + uint8 i; + + adf_os_spin_lock_bh(&pdev->grp_stat_spinlock); + pdev->grp_stats.last_valid_index++; + if (pdev->grp_stats.last_valid_index > (OL_TX_GROUP_STATS_LOG_SIZE - 1)) { + pdev->grp_stats.last_valid_index -= OL_TX_GROUP_STATS_LOG_SIZE; + pdev->grp_stats.wrap_around = 1; + } + curr_index = pdev->grp_stats.last_valid_index; + + for (i = 0; i < OL_TX_MAX_TXQ_GROUPS; i++) { + pdev->grp_stats.stats[curr_index].grp[i].member_vdevs = + OL_TXQ_GROUP_VDEV_ID_MASK_GET(pdev->txq_grps[i].membership); + pdev->grp_stats.stats[curr_index].grp[i].credit = + adf_os_atomic_read(&pdev->txq_grps[i].credit); + } + + adf_os_spin_unlock_bh(&pdev->grp_stat_spinlock); +} + +void +ol_tx_dump_group_credit_stats(ol_txrx_pdev_handle pdev) +{ + uint16 i,j, is_break = 0; + int16 curr_index, old_index, wrap_around; + uint16 curr_credit, old_credit, mem_vdevs; + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,"Group credit stats:"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + " No: GrpID: Credit: Change: vdev_map"); + + adf_os_spin_lock_bh(&pdev->grp_stat_spinlock); + curr_index = pdev->grp_stats.last_valid_index; + wrap_around = pdev->grp_stats.wrap_around; + adf_os_spin_unlock_bh(&pdev->grp_stat_spinlock); + + if(curr_index < 0) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,"Not initialized"); + return; + } + + for (i = 0; i < OL_TX_GROUP_STATS_LOG_SIZE; i++) { + old_index = curr_index - 1; + if (old_index < 0) { + if (wrap_around == 0) + is_break = 1; + else + old_index = OL_TX_GROUP_STATS_LOG_SIZE - 1; + } + + for (j = 0; j < OL_TX_MAX_TXQ_GROUPS; j++) { + adf_os_spin_lock_bh(&pdev->grp_stat_spinlock); + curr_credit = pdev->grp_stats.stats[curr_index].grp[j].credit; + if (!is_break) + old_credit = pdev->grp_stats.stats[old_index].grp[j].credit; + mem_vdevs = pdev->grp_stats.stats[curr_index].grp[j].member_vdevs; + adf_os_spin_unlock_bh(&pdev->grp_stat_spinlock); + + if (!is_break) + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%4d: %5d: %6d %6d %8x",curr_index, j, + curr_credit, (curr_credit - old_credit), + mem_vdevs); + else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%4d: %5d: %6d %6s %8x",curr_index, j, + curr_credit, "NA", mem_vdevs); + } + + if (is_break) + break; + + curr_index = old_index; + } +} + +void ol_tx_clear_group_credit_stats(ol_txrx_pdev_handle pdev) +{ + adf_os_spin_lock_bh(&pdev->grp_stat_spinlock); + adf_os_mem_zero(&pdev->grp_stats, sizeof(pdev->grp_stats)); + pdev->grp_stats.last_valid_index = -1; + pdev->grp_stats.wrap_around= 0; + adf_os_spin_unlock_bh(&pdev->grp_stat_spinlock); +} +#endif +#endif + +/* + * ol_tx_single_completion_handler performs the same tx completion + * processing as ol_tx_completion_handler, but for a single frame. + * ol_tx_completion_handler is optimized to handle batch completions + * as efficiently as possible; in contrast ol_tx_single_completion_handler + * handles single frames as simply and generally as possible. + * Thus, this ol_tx_single_completion_handler function is suitable for + * intermittent usage, such as for tx mgmt frames. + */ +void +ol_tx_single_completion_handler( + ol_txrx_pdev_handle pdev, + enum htt_tx_status status, + u_int16_t tx_desc_id) +{ + struct ol_tx_desc_t *tx_desc; + struct ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + adf_nbuf_t netbuf; + + tx_desc = td_array[tx_desc_id].tx_desc; + tx_desc->status = status; + netbuf = tx_desc->netbuf; + + /* Do one shot statistics */ + TXRX_STATS_UPDATE_TX_STATS(pdev, status, 1, adf_nbuf_len(netbuf)); + + if (OL_TX_DESC_NO_REFS(tx_desc)) { + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, status != htt_tx_status_ok); + } + + TX_CREDIT_DEBUG_PRINT( + " Increase credit %d + %d = %d\n", + adf_os_atomic_read(&pdev->target_tx_credit), + 1, adf_os_atomic_read(&pdev->target_tx_credit) + 1); + + if (pdev->cfg.is_high_latency) { + /* + * Credit was already explicitly updated by HTT, + * but update the number of available tx descriptors, + * then invoke the scheduler, since new credit is probably + * available now. + */ + adf_os_atomic_add(1, &pdev->tx_queue.rsrc_cnt); + ol_tx_sched(pdev); + } else { + adf_os_atomic_add(1, &pdev->target_tx_credit); + } +} + +/* WARNING: ol_tx_inspect_handler()'s bahavior is similar to that of ol_tx_completion_handler(). + * any change in ol_tx_completion_handler() must be mirrored here. + */ +void +ol_tx_inspect_handler( + ol_txrx_pdev_handle pdev, + int num_msdus, + void *tx_desc_id_iterator) +{ + u_int16_t vdev_id, i; + struct ol_txrx_vdev_t *vdev; + u_int16_t *desc_ids = (u_int16_t *)tx_desc_id_iterator; + u_int16_t tx_desc_id; + struct ol_tx_desc_t *tx_desc; + struct ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + struct ol_tx_desc_list_elem_t *lcl_freelist = NULL; + struct ol_tx_desc_list_elem_t *tx_desc_last = NULL; + adf_nbuf_t netbuf; + ol_tx_desc_list tx_descs; + TAILQ_INIT(&tx_descs); + + for (i = 0; i < num_msdus; i++) { + tx_desc_id = desc_ids[i]; + tx_desc = td_array[tx_desc_id].tx_desc; + netbuf = tx_desc->netbuf; + + /* find the "vdev" this tx_desc belongs to */ + vdev_id = HTT_TX_DESC_VDEV_ID_GET(*((u_int32_t *)(tx_desc->htt_tx_desc))); + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if (vdev->vdev_id == vdev_id) + break; + } + + /* vdev now points to the vdev for this descriptor. */ + +#ifndef ATH_11AC_TXCOMPACT + /* save this multicast packet to local free list */ + if (adf_os_atomic_dec_and_test(&tx_desc->ref_cnt)) +#endif + { + /* for this function only, force htt status to be "htt_tx_status_ok" + * for graceful freeing of this multicast frame + */ + ol_tx_msdu_complete(pdev, tx_desc, tx_descs, netbuf, lcl_freelist, + tx_desc_last, htt_tx_status_ok); + } + } + + if (lcl_freelist) { + adf_os_spin_lock(&pdev->tx_mutex); + tx_desc_last->next = pdev->tx_desc.freelist; + pdev->tx_desc.freelist = lcl_freelist; + adf_os_spin_unlock(&pdev->tx_mutex); + } else { + ol_tx_desc_frame_list_free(pdev, &tx_descs, htt_tx_status_discard); + } + TX_CREDIT_DEBUG_PRINT(" Increase HTT credit %d + %d = %d..\n", + adf_os_atomic_read(&pdev->target_tx_credit), + num_msdus, + adf_os_atomic_read(&pdev->target_tx_credit) + num_msdus); + + if (pdev->cfg.is_high_latency) { + /* credit was already explicitly updated by HTT */ + ol_tx_sched(pdev); + } else { + OL_TX_TARGET_CREDIT_ADJUST(num_msdus, pdev, NULL) ; + } +} + +#ifdef QCA_COMPUTE_TX_DELAY + +void +ol_tx_set_compute_interval( + ol_txrx_pdev_handle pdev, + u_int32_t interval) +{ + pdev->tx_delay.avg_period_ticks = adf_os_msecs_to_ticks(interval); +} + +void +ol_tx_packet_count( + ol_txrx_pdev_handle pdev, + u_int16_t *out_packet_count, + u_int16_t *out_packet_loss_count, + int category) +{ + *out_packet_count = pdev->packet_count[category]; + *out_packet_loss_count = pdev->packet_loss_count[category]; + pdev->packet_count[category] = 0; + pdev->packet_loss_count[category] = 0; +} + +u_int32_t +ol_tx_delay_avg(u_int64_t sum, u_int32_t num) +{ + u_int32_t sum32; + int shift = 0; + /* + * To avoid doing a 64-bit divide, shift the sum down until it is + * no more than 32 bits (and shift the denominator to match). + */ + while ((sum >> 32) != 0) { + sum >>= 1; + shift++; + } + sum32 = (u_int32_t) sum; + num >>= shift; + return (sum32 + (num >> 1)) / num; /* round to nearest */ +} + +void +ol_tx_delay( + ol_txrx_pdev_handle pdev, + u_int32_t *queue_delay_microsec, + u_int32_t *tx_delay_microsec, + int category) +{ + int index; + u_int32_t avg_delay_ticks; + struct ol_tx_delay_data *data; + + adf_os_assert(category >= 0 && category < QCA_TX_DELAY_NUM_CATEGORIES); + + adf_os_spin_lock_bh(&pdev->tx_delay.mutex); + index = 1 - pdev->tx_delay.cats[category].in_progress_idx; + + data = &pdev->tx_delay.cats[category].copies[index]; + + if (data->avgs.transmit_num > 0) { + avg_delay_ticks = ol_tx_delay_avg( + data->avgs.transmit_sum_ticks, data->avgs.transmit_num); + *tx_delay_microsec = adf_os_ticks_to_msecs(avg_delay_ticks * 1000); + } else { + /* + * This case should only happen if there's a query + * within 5 sec after the first tx data frame. + */ + *tx_delay_microsec = 0; + } + if (data->avgs.queue_num > 0) { + avg_delay_ticks = ol_tx_delay_avg( + data->avgs.queue_sum_ticks, data->avgs.queue_num); + *queue_delay_microsec = adf_os_ticks_to_msecs(avg_delay_ticks * 1000); + } else { + /* + * This case should only happen if there's a query + * within 5 sec after the first tx data frame. + */ + *queue_delay_microsec = 0; + } + + adf_os_spin_unlock_bh(&pdev->tx_delay.mutex); +} + +void +ol_tx_delay_hist( + ol_txrx_pdev_handle pdev, + u_int16_t *report_bin_values, + int category) +{ + int index, i, j; + struct ol_tx_delay_data *data; + + adf_os_assert(category >= 0 && category < QCA_TX_DELAY_NUM_CATEGORIES); + + adf_os_spin_lock_bh(&pdev->tx_delay.mutex); + index = 1 - pdev->tx_delay.cats[category].in_progress_idx; + + data = &pdev->tx_delay.cats[category].copies[index]; + + for (i = 0, j = 0; i < QCA_TX_DELAY_HIST_REPORT_BINS-1; i++) { + u_int16_t internal_bin_sum = 0; + while (j < (1 << i)) { + internal_bin_sum += data->hist_bins_queue[j++]; + } + report_bin_values[i] = internal_bin_sum; + } + report_bin_values[i] = data->hist_bins_queue[j]; /* overflow */ + + adf_os_spin_unlock_bh(&pdev->tx_delay.mutex); +} + +#ifdef QCA_COMPUTE_TX_DELAY_PER_TID +static u_int8_t +ol_tx_delay_tid_from_l3_hdr( + struct ol_txrx_pdev_t *pdev, + adf_nbuf_t msdu, + struct ol_tx_desc_t *tx_desc) +{ + u_int16_t ethertype; + u_int8_t *dest_addr, *l3_hdr; + int is_mgmt, is_mcast; + int l2_hdr_size; + + dest_addr = ol_tx_dest_addr_find(pdev, msdu); + if (NULL == dest_addr) { + return ADF_NBUF_TX_EXT_TID_INVALID; + } + is_mcast = IEEE80211_IS_MULTICAST(dest_addr); + is_mgmt = tx_desc->pkt_type >= OL_TXRX_MGMT_TYPE_BASE; + if (is_mgmt) { + return (is_mcast) ? + OL_TX_NUM_TIDS + OL_TX_VDEV_DEFAULT_MGMT : + HTT_TX_EXT_TID_MGMT; + } + if (is_mcast) { + return OL_TX_NUM_TIDS + OL_TX_VDEV_MCAST_BCAST; + } + if (pdev->frame_format == wlan_frm_fmt_802_3) { + struct ethernet_hdr_t *enet_hdr; + enet_hdr = (struct ethernet_hdr_t *) adf_nbuf_data(msdu); + l2_hdr_size = sizeof(struct ethernet_hdr_t); + ethertype = (enet_hdr->ethertype[0] << 8) | enet_hdr->ethertype[1]; + if (!IS_ETHERTYPE(ethertype)) { + struct llc_snap_hdr_t *llc_hdr; + llc_hdr = (struct llc_snap_hdr_t *) + (adf_nbuf_data(msdu) + l2_hdr_size); + l2_hdr_size += sizeof(struct llc_snap_hdr_t); + ethertype = (llc_hdr->ethertype[0] << 8) | llc_hdr->ethertype[1]; + } + } else { + struct llc_snap_hdr_t *llc_hdr; + l2_hdr_size = sizeof(struct ieee80211_frame); + llc_hdr = (struct llc_snap_hdr_t *) (adf_nbuf_data(msdu) + + l2_hdr_size); + l2_hdr_size += sizeof(struct llc_snap_hdr_t); + ethertype = (llc_hdr->ethertype[0] << 8) | llc_hdr->ethertype[1]; + } + l3_hdr = adf_nbuf_data(msdu) + l2_hdr_size; + if (ETHERTYPE_IPV4 == ethertype) { + return (((struct ipv4_hdr_t *) l3_hdr)->tos >> 5) & 0x7; + } else if (ETHERTYPE_IPV6 == ethertype) { + return (IPV6_TRAFFIC_CLASS((struct ipv6_hdr_t *) l3_hdr) >> 5) & 0x7; + } else { + return ADF_NBUF_TX_EXT_TID_INVALID; + } +} +#endif + +static int +ol_tx_delay_category(struct ol_txrx_pdev_t *pdev, u_int16_t msdu_id) +{ +#ifdef QCA_COMPUTE_TX_DELAY_PER_TID + struct ol_tx_desc_t *tx_desc = pdev->tx_desc.array[msdu_id].tx_desc; + u_int8_t tid; + + adf_nbuf_t msdu = tx_desc->netbuf; + tid = adf_nbuf_get_tid(msdu); + if (tid == ADF_NBUF_TX_EXT_TID_INVALID) { + tid = ol_tx_delay_tid_from_l3_hdr(pdev, msdu, tx_desc); + if (tid == ADF_NBUF_TX_EXT_TID_INVALID) { + /* TID could not be determined (this is not an IP frame?) */ + return -1; + } + } + return tid; +#else + return 0; +#endif +} + +static inline int +ol_tx_delay_hist_bin(struct ol_txrx_pdev_t *pdev, u_int32_t delay_ticks) +{ + int bin; + /* + * For speed, multiply and shift to approximate a divide. This causes + * a small error, but the approximation error should be much less + * than the other uncertainties in the tx delay computation. + */ + bin = (delay_ticks * pdev->tx_delay.hist_internal_bin_width_mult) >> + pdev->tx_delay.hist_internal_bin_width_shift; + if (bin >= QCA_TX_DELAY_HIST_INTERNAL_BINS) { + bin = QCA_TX_DELAY_HIST_INTERNAL_BINS - 1; + } + return bin; +} + +static void +ol_tx_delay_compute( + struct ol_txrx_pdev_t *pdev, + enum htt_tx_status status, + u_int16_t *desc_ids, + int num_msdus) +{ + int i, index, cat; + u_int32_t now_ticks = adf_os_ticks(); + u_int32_t tx_delay_transmit_ticks, tx_delay_queue_ticks; + u_int32_t avg_time_ticks; + struct ol_tx_delay_data *data; + + adf_os_assert(num_msdus > 0); + + /* + * keep static counters for total packet and lost packets + * reset them in ol_tx_delay(), function used to fetch the stats + */ + + cat = ol_tx_delay_category(pdev, desc_ids[0]); + if (cat < 0 || cat >= QCA_TX_DELAY_NUM_CATEGORIES) + return; + + pdev->packet_count[cat] = pdev->packet_count[cat] + num_msdus; + if (status != htt_tx_status_ok) { + for (i = 0; i < num_msdus; i++) { + cat = ol_tx_delay_category(pdev, desc_ids[i]); + if (cat < 0 || cat >= QCA_TX_DELAY_NUM_CATEGORIES) + return; + pdev->packet_loss_count[cat]++; + } + return; + } + + /* since we may switch the ping-pong index, provide mutex w. readers */ + adf_os_spin_lock_bh(&pdev->tx_delay.mutex); + index = pdev->tx_delay.cats[cat].in_progress_idx; + + data = &pdev->tx_delay.cats[cat].copies[index]; + + if (pdev->tx_delay.tx_compl_timestamp_ticks != 0) { + tx_delay_transmit_ticks = + now_ticks - pdev->tx_delay.tx_compl_timestamp_ticks; + /* + * We'd like to account for the number of MSDUs that were + * transmitted together, but we don't know this. All we know + * is the number of MSDUs that were acked together. + * Since the frame error rate is small, this is nearly the same as + * the number of frames transmitted together. + */ + data->avgs.transmit_sum_ticks += tx_delay_transmit_ticks; + data->avgs.transmit_num += num_msdus; + } + pdev->tx_delay.tx_compl_timestamp_ticks = now_ticks; + + for (i = 0; i < num_msdus; i++) { + u_int16_t id = desc_ids[i]; + struct ol_tx_desc_t *tx_desc = pdev->tx_desc.array[id].tx_desc; + int bin; + + tx_delay_queue_ticks = now_ticks - tx_desc->entry_timestamp_ticks; + + data->avgs.queue_sum_ticks += tx_delay_queue_ticks; + data->avgs.queue_num++; + bin = ol_tx_delay_hist_bin(pdev, tx_delay_queue_ticks); + data->hist_bins_queue[bin]++; + } + + /* check if it's time to start a new average */ + avg_time_ticks = + now_ticks - pdev->tx_delay.cats[cat].avg_start_time_ticks; + if (avg_time_ticks > pdev->tx_delay.avg_period_ticks) { + pdev->tx_delay.cats[cat].avg_start_time_ticks = now_ticks; + index = 1 - index; + pdev->tx_delay.cats[cat].in_progress_idx = index; + adf_os_mem_zero( + &pdev->tx_delay.cats[cat].copies[index], + sizeof(pdev->tx_delay.cats[cat].copies[index])); + } + + adf_os_spin_unlock_bh(&pdev->tx_delay.mutex); +} + +#endif /* QCA_COMPUTE_TX_DELAY */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.h new file mode 100644 index 000000000000..2d20da995b4d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_send.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_tx_send.h + * @brief API definitions for the tx sendriptor module within the data SW. + */ +#ifndef _OL_TX_SEND__H_ +#define _OL_TX_SEND__H_ + +#include /* adf_nbuf_t */ +#include /* ol_tx_send_t */ + +#if defined(CONFIG_HL_SUPPORT) +#define ol_tx_discard_target_frms(pdev) /* no-op */ +#else + +/** + * @flush the ol tx when surprise remove. + * + */ +void +ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev); +#endif + +/** + * @brief Send a tx frame to the target. + * @details + * + * @param pdev - the phy dev + * @param vdev - the virtual device sending the data + * (for specifying the transmitter address for multicast / broadcast data) + * @param netbuf - the tx frame + */ +void +ol_tx_send( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu); + +/** + * @brief Send a tx batch download to the target. + * @details + * This function is different from above in that + * it accepts a list of msdu's to be downloaded as a batch + * + * @param pdev - the phy dev + * @param msdu_list - the Head pointer to the Tx Batch + * @param num_msdus - Total msdus chained in msdu_list + */ + +int +ol_tx_send_batch( + struct ol_txrx_pdev_t *pdev, + adf_nbuf_t msdu_list, int num_msdus); + +/** + * @brief Send a tx frame with a non-std header or payload type to the target. + * @details + * + * @param pdev - the phy dev + * @param vdev - the virtual device sending the data + * (for specifying the transmitter address for multicast / broadcast data) + * @param netbuf - the tx frame + * @param pkt_type - what kind of non-std frame is being sent + */ +void +ol_tx_send_nonstd( + struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + enum htt_pkt_type pkt_type); +#endif /* _OL_TX_SEND__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c new file mode 100644 index 000000000000..48d215d0f76f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -0,0 +1,2630 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=== includes ===*/ +/* header files for OS primitives */ +#include /* u_int32_t, etc. */ +#include /* adf_os_mem_alloc,free */ +#include /* adf_os_device_t, adf_os_print */ +#include /* adf_os_spinlock */ +#include /* adf_os_atomic_read */ + +/* header files for utilities */ +#include /* TAILQ */ + +/* header files for configuration API */ +#include /* ol_cfg_is_high_latency */ +#include + +/* header files for HTT API */ +#include +#include + +/* header files for OS shim API */ +#include + +/* header files for our own APIs */ +#include +#include +#include +#include +/* header files for our internal definitions */ +#include /* TXRX_ASSERT, etc. */ +#include /* WDI events */ +#include /* ol_txrx_pdev_t, etc. */ +#include +#include /* ol_tx_hl, ol_tx_ll */ +#include /* ol_rx_deliver */ +#include /* ol_txrx_peer_find_attach, etc. */ +#include /* ol_rx_pn_check, etc. */ +#include /* ol_rx_fwd_check, etc. */ +#include /* OL_RX_REORDER_TIMEOUT_INIT, etc. */ +#include +#include /* ol_tx_discard_target_frms */ +#include /* ol_tx_desc_frame_free */ +#include +#include /* ol_tx_sched_attach, etc. */ +#include + +/*=== function definitions ===*/ + +u_int16_t +ol_tx_desc_pool_size_hl(ol_pdev_handle ctrl_pdev) +{ + u_int16_t desc_pool_size; + u_int16_t steady_state_tx_lifetime_ms; + u_int16_t safety_factor; + + /* + * Steady-state tx latency: + * roughly 1-2 ms flight time + * + roughly 1-2 ms prep time, + * + roughly 1-2 ms target->host notification time. + * = roughly 6 ms total + * Thus, steady state number of frames = + * steady state max throughput / frame size * tx latency, e.g. + * 1 Gbps / 1500 bytes * 6 ms = 500 + * + */ + steady_state_tx_lifetime_ms = 6; + + safety_factor = 8; + + desc_pool_size = + ol_cfg_max_thruput_mbps(ctrl_pdev) * + 1000 /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ / + (8 * OL_TX_AVG_FRM_BYTES) * + steady_state_tx_lifetime_ms * + safety_factor; + + /* minimum */ + if (desc_pool_size < OL_TX_DESC_POOL_SIZE_MIN_HL) { + desc_pool_size = OL_TX_DESC_POOL_SIZE_MIN_HL; + } + /* maximum */ + if (desc_pool_size > OL_TX_DESC_POOL_SIZE_MAX_HL) { + desc_pool_size = OL_TX_DESC_POOL_SIZE_MAX_HL; + } + return desc_pool_size; +} +#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID +ol_txrx_peer_handle +ol_txrx_find_peer_by_addr_and_vdev(ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, + u_int8_t *peer_addr, + u_int8_t *peer_id) +{ + struct ol_txrx_peer_t *peer; + + peer = ol_txrx_peer_vdev_find_hash(pdev, vdev, peer_addr, 0, 1); + if (!peer) + return NULL; + *peer_id = peer->local_id; + adf_os_atomic_dec(&peer->ref_cnt); + return peer; +} + +ol_txrx_peer_handle ol_txrx_find_peer_by_addr(ol_txrx_pdev_handle pdev, + u_int8_t *peer_addr, + u_int8_t *peer_id) +{ + struct ol_txrx_peer_t *peer; + + peer = ol_txrx_peer_find_hash_find(pdev, peer_addr, 0, 1); + if (!peer) + return NULL; + *peer_id = peer->local_id; + adf_os_atomic_dec(&peer->ref_cnt); + return peer; +} + +u_int16_t +ol_txrx_local_peer_id(ol_txrx_peer_handle peer) +{ + return peer->local_id; +} + +ol_txrx_peer_handle +ol_txrx_peer_find_by_local_id( + struct ol_txrx_pdev_t *pdev, + u_int8_t local_peer_id) +{ + struct ol_txrx_peer_t *peer; + if ((local_peer_id == OL_TXRX_INVALID_LOCAL_PEER_ID) || + (local_peer_id >= OL_TXRX_NUM_LOCAL_PEER_IDS)) { + return NULL; + } + + adf_os_spin_lock_bh(&pdev->local_peer_ids.lock); + peer = pdev->local_peer_ids.map[local_peer_id]; + adf_os_spin_unlock_bh(&pdev->local_peer_ids.lock); + return peer; +} + +static void +OL_TXRX_LOCAL_PEER_ID_POOL_INIT(struct ol_txrx_pdev_t *pdev) +{ + int i; + + /* point the freelist to the first ID */ + pdev->local_peer_ids.freelist = 0; + + /* link each ID to the next one */ + for (i = 0; i < OL_TXRX_NUM_LOCAL_PEER_IDS; i++) { + pdev->local_peer_ids.pool[i] = i + 1; + pdev->local_peer_ids.map[i] = NULL; + } + + /* link the last ID to itself, to mark the end of the list */ + i = OL_TXRX_NUM_LOCAL_PEER_IDS; + pdev->local_peer_ids.pool[i] = i; + + adf_os_spinlock_init(&pdev->local_peer_ids.lock); +} + +static void +OL_TXRX_LOCAL_PEER_ID_ALLOC( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + int i; + + adf_os_spin_lock_bh(&pdev->local_peer_ids.lock); + i = pdev->local_peer_ids.freelist; + if (pdev->local_peer_ids.pool[i] == i) { + /* the list is empty, except for the list-end marker */ + peer->local_id = OL_TXRX_INVALID_LOCAL_PEER_ID; + } else { + /* take the head ID and advance the freelist */ + peer->local_id = i; + pdev->local_peer_ids.freelist = pdev->local_peer_ids.pool[i]; + pdev->local_peer_ids.map[i] = peer; + } + adf_os_spin_unlock_bh(&pdev->local_peer_ids.lock); +} + +static void +OL_TXRX_LOCAL_PEER_ID_FREE( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + int i = peer->local_id; + if ((i == OL_TXRX_INVALID_LOCAL_PEER_ID) || + (i >= OL_TXRX_NUM_LOCAL_PEER_IDS)) { + return; + } + /* put this ID on the head of the freelist */ + adf_os_spin_lock_bh(&pdev->local_peer_ids.lock); + pdev->local_peer_ids.pool[i] = pdev->local_peer_ids.freelist; + pdev->local_peer_ids.freelist = i; + pdev->local_peer_ids.map[i] = NULL; + adf_os_spin_unlock_bh(&pdev->local_peer_ids.lock); +} + +static void +OL_TXRX_LOCAL_PEER_ID_CLEANUP(struct ol_txrx_pdev_t *pdev) +{ + adf_os_spinlock_destroy(&pdev->local_peer_ids.lock); +} + +#else +#define OL_TXRX_LOCAL_PEER_ID_POOL_INIT(pdev) /* no-op */ +#define OL_TXRX_LOCAL_PEER_ID_ALLOC(pdev, peer) /* no-op */ +#define OL_TXRX_LOCAL_PEER_ID_FREE(pdev, peer) /* no-op */ +#define OL_TXRX_LOCAL_PEER_ID_CLEANUP(pdev) /* no-op */ +#endif + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +void +ol_txrx_update_group_credit( + struct ol_tx_queue_group_t *group, + int32_t credit, + u_int8_t absolute) +{ + if (absolute) { + adf_os_atomic_set(&group->credit, credit); + } else { + adf_os_atomic_add(credit, &group->credit); + } +} + +void +ol_txrx_update_tx_queue_groups( + ol_txrx_pdev_handle pdev, + u_int8_t group_id, + int32_t credit, + u_int8_t absolute, + u_int32_t vdev_id_mask, + u_int32_t ac_mask +) +{ + struct ol_tx_queue_group_t *group; + u_int32_t group_vdev_bit_mask, vdev_bit_mask, group_vdev_id_mask; + u_int32_t membership; + struct ol_txrx_vdev_t *vdev; + group = &pdev->txq_grps[group_id]; + + membership = OL_TXQ_GROUP_MEMBERSHIP_GET(vdev_id_mask,ac_mask); + + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + /* + * if the membership (vdev id mask and ac mask) + * matches then no need to update tx qeue groups. + */ + if (group->membership == membership) { + /* Update Credit Only */ + goto credit_update; + } + + /* + * membership (vdev id mask and ac mask) is not matching + * TODO: ignoring ac mask for now + */ + group_vdev_id_mask = + OL_TXQ_GROUP_VDEV_ID_MASK_GET(group->membership); + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + group_vdev_bit_mask = + OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(group_vdev_id_mask,vdev->vdev_id); + vdev_bit_mask = + OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(vdev_id_mask,vdev->vdev_id); + + if (group_vdev_bit_mask != vdev_bit_mask) { + /* + * Change in vdev tx queue group + */ + if (!vdev_bit_mask) { + /* Set Group Pointer (vdev and peer) to NULL */ + ol_tx_set_vdev_group_ptr(pdev, vdev->vdev_id, NULL); + } else { + /* Set Group Pointer (vdev and peer) */ + ol_tx_set_vdev_group_ptr(pdev, vdev->vdev_id, group); + } + } + } + /* Update membership */ + group->membership = membership; +credit_update: + /* Update Credit */ + ol_txrx_update_group_credit(group, credit, absolute); + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); +} +#endif + +ol_txrx_pdev_handle +ol_txrx_pdev_attach( + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, + adf_os_device_t osdev) +{ + int i, tid; + struct ol_txrx_pdev_t *pdev; +#ifdef WDI_EVENT_ENABLE + A_STATUS ret; +#endif + uint16_t desc_pool_size; + uint32_t page_size; + void **desc_pages = NULL; + unsigned int pages_idx; + unsigned int descs_idx; + + pdev = adf_os_mem_alloc(osdev, sizeof(*pdev)); + if (!pdev) { + goto fail0; + } + adf_os_mem_zero(pdev, sizeof(*pdev)); + + /* init LL/HL cfg here */ + pdev->cfg.is_high_latency = ol_cfg_is_high_latency(ctrl_pdev); + pdev->cfg.default_tx_comp_req = !ol_cfg_tx_free_at_download(ctrl_pdev); + + /* store provided params */ + pdev->ctrl_pdev = ctrl_pdev; + pdev->osdev = osdev; + + for (i = 0; i < htt_num_sec_types; i++) { + pdev->sec_types[i] = (enum ol_sec_type)i; + } + + TXRX_STATS_INIT(pdev); + + TAILQ_INIT(&pdev->vdev_list); + + /* do initial set up of the peer ID -> peer object lookup map */ + if (ol_txrx_peer_find_attach(pdev)) { + goto fail1; + } + + if (ol_cfg_is_high_latency(ctrl_pdev)) { + desc_pool_size = ol_tx_desc_pool_size_hl(ctrl_pdev); + adf_os_atomic_init(&pdev->tx_queue.rsrc_cnt); + adf_os_atomic_add(desc_pool_size, &pdev->tx_queue.rsrc_cnt); +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + /* + * 5% margin of unallocated desc is too much for per vdev mechanism. + * Define the value seperately. + */ + pdev->tx_queue.rsrc_threshold_lo = TXRX_HL_TX_FLOW_CTRL_MGMT_RESERVED; + + /* when freeing up descriptors, keep going until there's a 7.5% margin */ + pdev->tx_queue.rsrc_threshold_hi = ((15 * desc_pool_size)/100)/2; +#else + /* always maintain a 5% margin of unallocated descriptors */ + pdev->tx_queue.rsrc_threshold_lo = (5 * desc_pool_size)/100; + + /* when freeing up descriptors, keep going until there's a 15% margin */ + pdev->tx_queue.rsrc_threshold_hi = (15 * desc_pool_size)/100; +#endif + for (i = 0 ; i < OL_TX_MAX_TXQ_GROUPS; i++) { + adf_os_atomic_init(&pdev->txq_grps[i].credit); + } + + } else { + /* + * For LL, limit the number of host's tx descriptors to match the + * number of target FW tx descriptors. + * This simplifies the FW, by ensuring the host will never download + * more tx descriptors than the target has space for. + * The FW will drop/free low-priority tx descriptors when it starts + * to run low, so that in theory the host should never run out of + * tx descriptors. + */ + desc_pool_size = ol_cfg_target_tx_credit(ctrl_pdev); + } + + /* initialize the counter of the target's tx buffer availability */ + adf_os_atomic_init(&pdev->target_tx_credit); + adf_os_atomic_init(&pdev->orig_target_tx_credit); + /* + * LL - initialize the target credit outselves. + * HL - wait for a HTT target credit initialization during htt_attach. + */ + if (!ol_cfg_is_high_latency(ctrl_pdev)) { + adf_os_atomic_add( + ol_cfg_target_tx_credit(pdev->ctrl_pdev), &pdev->target_tx_credit); + } + + pdev->htt_pdev = htt_attach( + pdev, ctrl_pdev, htc_pdev, osdev, desc_pool_size); + if (!pdev->htt_pdev) { + goto fail2; + } + +#ifdef IPA_UC_OFFLOAD + /* Attach micro controller data path offload resource */ + if (ol_cfg_ipa_uc_offload_enabled(ctrl_pdev)) { + if (htt_ipa_uc_attach(pdev->htt_pdev)) { + goto fail3; + } + } +#endif /* IPA_UC_OFFLOAD */ + + pdev->tx_desc.array = adf_os_mem_alloc( + osdev, desc_pool_size * sizeof(struct ol_tx_desc_list_elem_t)); + if (!pdev->tx_desc.array) { + goto fail3; + } + adf_os_mem_set( + pdev->tx_desc.array, 0, + desc_pool_size * sizeof(struct ol_tx_desc_list_elem_t)); + + pdev->desc_mem_size = desc_pool_size * sizeof(struct ol_tx_desc_t); + page_size = adf_os_mem_get_page_size(); + pdev->num_descs_per_page = page_size / sizeof(struct ol_tx_desc_t); + pdev->num_desc_pages = desc_pool_size / pdev->num_descs_per_page; + if (desc_pool_size % pdev->num_descs_per_page) + pdev->num_desc_pages++; + + /* Allocate host descriptor resources */ + desc_pages = adf_os_mem_alloc( + pdev->osdev, pdev->num_desc_pages * sizeof(char *)); + if (!desc_pages) + goto fail3; + + for (pages_idx = 0; pages_idx < pdev->num_desc_pages; pages_idx++) { + desc_pages[pages_idx] = adf_os_mem_alloc(pdev->osdev, page_size); + if (!desc_pages[pages_idx]) { + for (i = 0; i < pages_idx; i++) + adf_os_mem_free(desc_pages[i]); + adf_os_mem_free(desc_pages); + goto fail3; + } + } + pdev->desc_pages = desc_pages; + + /* + * Each SW tx desc (used only within the tx datapath SW) has a + * matching HTT tx desc (used for downloading tx meta-data to FW/HW). + * Go ahead and allocate the HTT tx desc and link it with the SW tx + * desc now, to avoid doing it during time-critical transmit. + */ + pdev->tx_desc.pool_size = desc_pool_size; + + pages_idx = 0; + descs_idx = 0; + for (i = 0; i < desc_pool_size; i++) { + void *htt_tx_desc; + u_int32_t paddr_lo; + + pdev->tx_desc.array[i].tx_desc = + (struct ol_tx_desc_t *)(desc_pages[pages_idx] + + descs_idx * sizeof(struct ol_tx_desc_t)); + descs_idx++; + if (pdev->num_descs_per_page == descs_idx) { + /* Next page */ + pages_idx++; + descs_idx = 0; + } + + htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo); + if (! htt_tx_desc) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "%s: failed to alloc HTT tx desc (%d of %d)\n", + __func__, i, desc_pool_size); + while (--i >= 0) { + htt_tx_desc_free( + pdev->htt_pdev, + pdev->tx_desc.array[i].tx_desc->htt_tx_desc); + } + goto fail4; + } + pdev->tx_desc.array[i].tx_desc->htt_tx_desc = htt_tx_desc; + pdev->tx_desc.array[i].tx_desc->htt_tx_desc_paddr = paddr_lo; +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS + pdev->tx_desc.array[i].tx_desc->pkt_type = 0xff; +#ifdef QCA_COMPUTE_TX_DELAY + pdev->tx_desc.array[i].tx_desc->entry_timestamp_ticks = 0xffffffff; +#endif +#endif + pdev->tx_desc.array[i].tx_desc->p_link = (void *)&pdev->tx_desc.array[i]; + pdev->tx_desc.array[i].tx_desc->id = i; + } + + /* link SW tx descs into a freelist */ + pdev->tx_desc.num_free = desc_pool_size; + pdev->tx_desc.freelist = &pdev->tx_desc.array[0]; + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s first tx_desc:0x%p Last tx desc:0x%p\n", __func__, + (u_int32_t *) pdev->tx_desc.freelist, + (u_int32_t *) (pdev->tx_desc.freelist + desc_pool_size)); + for (i = 0; i < desc_pool_size-1; i++) { + pdev->tx_desc.array[i].next = &pdev->tx_desc.array[i+1]; + } + pdev->tx_desc.array[i].next = NULL; + + /* check what format of frames are expected to be delivered by the OS */ + pdev->frame_format = ol_cfg_frame_type(pdev->ctrl_pdev); + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + pdev->htt_pkt_type = htt_pkt_type_native_wifi; + } else if (pdev->frame_format == wlan_frm_fmt_802_3) { + pdev->htt_pkt_type = htt_pkt_type_ethernet; + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%s Invalid standard frame type: %d\n", + __func__, pdev->frame_format); + goto fail5; + } + + /* setup the global rx defrag waitlist */ + TAILQ_INIT(&pdev->rx.defrag.waitlist); + + /* configure where defrag timeout and duplicate detection is handled */ + pdev->rx.flags.defrag_timeout_check = + pdev->rx.flags.dup_check = + ol_cfg_rx_host_defrag_timeout_duplicate_check(ctrl_pdev); + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + /* Need to revisit this part. Currently,hardcode to riva's caps */ + pdev->target_tx_tran_caps = wlan_frm_tran_cap_raw; + pdev->target_rx_tran_caps = wlan_frm_tran_cap_raw; + /* + * The Riva HW de-aggregate doesn't have capability to generate 802.11 + * header for non-first subframe of A-MSDU. + */ + pdev->sw_subfrm_hdr_recovery_enable = 1; + /* + * The Riva HW doesn't have the capability to set Protected Frame bit + * in the MAC header for encrypted data frame. + */ + pdev->sw_pf_proc_enable = 1; + + if (pdev->frame_format == wlan_frm_fmt_802_3) { + /* sw llc process is only needed in 802.3 to 802.11 transform case */ + pdev->sw_tx_llc_proc_enable = 1; + pdev->sw_rx_llc_proc_enable = 1; + } else { + pdev->sw_tx_llc_proc_enable = 0; + pdev->sw_rx_llc_proc_enable = 0; + } + + switch(pdev->frame_format) { + case wlan_frm_fmt_raw: + pdev->sw_tx_encap = + pdev->target_tx_tran_caps & wlan_frm_tran_cap_raw ? 0 : 1; + pdev->sw_rx_decap = + pdev->target_rx_tran_caps & wlan_frm_tran_cap_raw ? 0 : 1; + break; + case wlan_frm_fmt_native_wifi: + pdev->sw_tx_encap = + pdev->target_tx_tran_caps & wlan_frm_tran_cap_native_wifi ? 0: 1; + pdev->sw_rx_decap = + pdev->target_rx_tran_caps & wlan_frm_tran_cap_native_wifi ? 0: 1; + break; + case wlan_frm_fmt_802_3: + pdev->sw_tx_encap = + pdev->target_tx_tran_caps & wlan_frm_tran_cap_8023 ? 0: 1; + pdev->sw_rx_decap = + pdev->target_rx_tran_caps & wlan_frm_tran_cap_8023 ? 0: 1; + break; + default: + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid standard frame type for encap/decap: fmt %x tx %x rx %x\n", + pdev->frame_format, + pdev->target_tx_tran_caps, + pdev->target_rx_tran_caps); + goto fail5; + } +#endif + + /* + * Determine what rx processing steps are done within the host. + * Possibilities: + * 1. Nothing - rx->tx forwarding and rx PN entirely within target. + * (This is unlikely; even if the target is doing rx->tx forwarding, + * the host should be doing rx->tx forwarding too, as a back up for + * the target's rx->tx forwarding, in case the target runs short on + * memory, and can't store rx->tx frames that are waiting for missing + * prior rx frames to arrive.) + * 2. Just rx -> tx forwarding. + * This is the typical configuration for HL, and a likely + * configuration for LL STA or small APs (e.g. retail APs). + * 3. Both PN check and rx -> tx forwarding. + * This is the typical configuration for large LL APs. + * Host-side PN check without rx->tx forwarding is not a valid + * configuration, since the PN check needs to be done prior to + * the rx->tx forwarding. + */ + if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) { + /* PN check, rx-tx forwarding and rx reorder is done by the target */ + if (ol_cfg_rx_fwd_disabled(pdev->ctrl_pdev)) { + pdev->rx_opt_proc = ol_rx_in_order_deliver; + } else { + pdev->rx_opt_proc = ol_rx_fwd_check; + } + } else { + if (ol_cfg_rx_pn_check(pdev->ctrl_pdev)) { + if (ol_cfg_rx_fwd_disabled(pdev->ctrl_pdev)) { + /* + * PN check done on host, rx->tx forwarding not done at all. + */ + pdev->rx_opt_proc = ol_rx_pn_check_only; + } else if (ol_cfg_rx_fwd_check(pdev->ctrl_pdev)) { + /* + * Both PN check and rx->tx forwarding done on host. + */ + pdev->rx_opt_proc = ol_rx_pn_check; + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%s: invalid config: if rx PN check is on the host," + "rx->tx forwarding check needs to also be on the host.\n", + __func__); + goto fail5; + } + } else { + /* PN check done on target */ + if ((!ol_cfg_rx_fwd_disabled(pdev->ctrl_pdev)) && + ol_cfg_rx_fwd_check(pdev->ctrl_pdev)) + { + /* + * rx->tx forwarding done on host (possibly as + * back-up for target-side primary rx->tx forwarding) + */ + pdev->rx_opt_proc = ol_rx_fwd_check; + } else { + /* rx->tx forwarding either done in target, or not done at all */ + pdev->rx_opt_proc = ol_rx_deliver; + } + } + } + + /* initialize mutexes for tx desc alloc and peer lookup */ + adf_os_spinlock_init(&pdev->tx_mutex); + adf_os_spinlock_init(&pdev->peer_ref_mutex); + adf_os_spinlock_init(&pdev->rx.mutex); + adf_os_spinlock_init(&pdev->last_real_peer_mutex); + OL_TXRX_PEER_STATS_MUTEX_INIT(pdev); + + if (ol_cfg_is_high_latency(ctrl_pdev)) { + adf_os_spinlock_init(&pdev->tx_queue_spinlock); + pdev->tx_sched.scheduler = ol_tx_sched_attach(pdev); + if (pdev->tx_sched.scheduler == NULL) { + goto fail6; + } + } + + if (OL_RX_REORDER_TRACE_ATTACH(pdev) != A_OK) { + goto fail7; + } + + if (OL_RX_PN_TRACE_ATTACH(pdev) != A_OK) { + goto fail8; + } + +#ifdef PERE_IP_HDR_ALIGNMENT_WAR + pdev->host_80211_enable = ol_scn_host_80211_enable_get(pdev->ctrl_pdev); +#endif + + /* + * WDI event attach + */ +#ifdef WDI_EVENT_ENABLE + if ((ret = wdi_event_attach(pdev)) == A_ERROR) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_WARN, + "WDI event attach unsuccessful\n"); + } +#endif + + /* + * Initialize rx PN check characteristics for different security types. + */ + adf_os_mem_set(&pdev->rx_pn[0], 0, sizeof(pdev->rx_pn)); + + /* TKIP: 48-bit TSC, CCMP: 48-bit PN */ + pdev->rx_pn[htt_sec_type_tkip].len = + pdev->rx_pn[htt_sec_type_tkip_nomic].len = + pdev->rx_pn[htt_sec_type_aes_ccmp].len = 48; + pdev->rx_pn[htt_sec_type_tkip].cmp = + pdev->rx_pn[htt_sec_type_tkip_nomic].cmp = + pdev->rx_pn[htt_sec_type_aes_ccmp].cmp = ol_rx_pn_cmp48; + + /* WAPI: 128-bit PN */ + pdev->rx_pn[htt_sec_type_wapi].len = 128; + pdev->rx_pn[htt_sec_type_wapi].cmp = ol_rx_pn_wapi_cmp; + + OL_RX_REORDER_TIMEOUT_INIT(pdev); + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "Created pdev %p\n", pdev); + + #if defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING) + adf_os_spinlock_init(&pdev->txq_log_spinlock); + pdev->txq_log.size = OL_TXQ_LOG_SIZE; + pdev->txq_log.oldest_record_offset = 0; + pdev->txq_log.offset = 0; + pdev->txq_log.allow_wrap = 1; + pdev->txq_log.wrapped = 0; + #endif /* defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING) */ + +#ifdef DEBUG_HL_LOGGING + adf_os_spinlock_init(&pdev->grp_stat_spinlock); + pdev->grp_stats.last_valid_index = -1; + pdev->grp_stats.wrap_around= 0; +#endif + pdev->cfg.host_addba = ol_cfg_host_addba(ctrl_pdev); + + #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI + #define OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT 3 + #if 1 + #define OL_TXRX_RSSI_NEW_WEIGHT_DEFAULT \ + /* avg = 100% * new + 0% * old */ \ + (1 << OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT) + #else + #define OL_TXRX_RSSI_NEW_WEIGHT_DEFAULT \ + /* avg = 25% * new + 25% * old */ \ + (1 << (OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT-2)) + #endif + pdev->rssi_update_shift = OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT; + pdev->rssi_new_weight = OL_TXRX_RSSI_NEW_WEIGHT_DEFAULT; + #endif + + OL_TXRX_LOCAL_PEER_ID_POOL_INIT(pdev); + + pdev->cfg.ll_pause_txq_limit = ol_tx_cfg_max_tx_queue_depth_ll(ctrl_pdev); + + /* TX flow control for peer who is in very bad link status */ + ol_tx_badpeer_flow_cl_init(pdev); + +#ifdef QCA_COMPUTE_TX_DELAY + adf_os_mem_zero(&pdev->tx_delay, sizeof(pdev->tx_delay)); + adf_os_spinlock_init(&pdev->tx_delay.mutex); + + /* initialize compute interval with 5 seconds (ESE default) */ + pdev->tx_delay.avg_period_ticks = adf_os_msecs_to_ticks(5000); + { + u_int32_t bin_width_1000ticks; + bin_width_1000ticks = adf_os_msecs_to_ticks( + QCA_TX_DELAY_HIST_INTERNAL_BIN_WIDTH_MS * 1000); + /* + * Compute a factor and shift that together are equal to the + * inverse of the bin_width time, so that rather than dividing + * by the bin width time, approximately the same result can be + * obtained much more efficiently by a multiply + shift. + * multiply_factor >> shift = 1 / bin_width_time, so + * multiply_factor = (1 << shift) / bin_width_time. + * + * Pick the shift semi-arbitrarily. + * If we knew statically what the bin_width would be, we could + * choose a shift that minimizes the error. + * Since the bin_width is determined dynamically, simply use a + * shift that is about half of the u_int32_t size. This should + * result in a relatively large multiplier value, which minimizes + * the error from rounding the multiplier to an integer. + * The rounding error only becomes significant if the tick units + * are on the order of 1 microsecond. In most systems, it is + * expected that the tick units will be relatively low-resolution, + * on the order of 1 millisecond. In such systems the rounding + * error is negligible. + * It would be more accurate to dynamically try out different + * shifts and choose the one that results in the smallest rounding + * error, but that extra level of fidelity is not needed. + */ + pdev->tx_delay.hist_internal_bin_width_shift = 16; + pdev->tx_delay.hist_internal_bin_width_mult = + ((1 << pdev->tx_delay.hist_internal_bin_width_shift) * + 1000 + (bin_width_1000ticks >> 1)) / bin_width_1000ticks; + } +#endif /* QCA_COMPUTE_TX_DELAY */ + +#ifdef QCA_SUPPORT_TX_THROTTLE + /* Thermal Mitigation */ + ol_tx_throttle_init(pdev); +#endif + + /* + * Init the tid --> category table. + * Regular tids (0-15) map to their AC. + * Extension tids get their own categories. + */ + for (tid = 0; tid < OL_TX_NUM_QOS_TIDS; tid++) { + int ac = TXRX_TID_TO_WMM_AC(tid); + pdev->tid_to_ac[tid] = ac; + } + pdev->tid_to_ac[OL_TX_NON_QOS_TID] = + OL_TX_SCHED_WRR_ADV_CAT_NON_QOS_DATA; + pdev->tid_to_ac[OL_TX_MGMT_TID] = + OL_TX_SCHED_WRR_ADV_CAT_UCAST_MGMT; + pdev->tid_to_ac[OL_TX_NUM_TIDS + OL_TX_VDEV_MCAST_BCAST] = + OL_TX_SCHED_WRR_ADV_CAT_MCAST_DATA; + pdev->tid_to_ac[OL_TX_NUM_TIDS + OL_TX_VDEV_DEFAULT_MGMT] = + OL_TX_SCHED_WRR_ADV_CAT_MCAST_MGMT; + + return pdev; /* success */ + +fail8: + OL_RX_REORDER_TRACE_DETACH(pdev); + +fail7: + adf_os_spinlock_destroy(&pdev->tx_mutex); + adf_os_spinlock_destroy(&pdev->peer_ref_mutex); + adf_os_spinlock_destroy(&pdev->rx.mutex); + adf_os_spinlock_destroy(&pdev->last_real_peer_mutex); + OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev); + + ol_tx_sched_detach(pdev); + +fail6: + if (ol_cfg_is_high_latency(ctrl_pdev)) { + adf_os_spinlock_destroy(&pdev->tx_queue_spinlock); + } + +fail5: + for (i = 0; i < desc_pool_size; i++) { + htt_tx_desc_free( + pdev->htt_pdev, pdev->tx_desc.array[i].tx_desc->htt_tx_desc); + } + +fail4: + for (i = 0; i < pages_idx; i++) + adf_os_mem_free(desc_pages[i]); + adf_os_mem_free(desc_pages); + + adf_os_mem_free(pdev->tx_desc.array); +#ifdef IPA_UC_OFFLOAD + if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) { + htt_ipa_uc_detach(pdev->htt_pdev); + } +#endif /* IPA_UC_OFFLOAD */ + +fail3: + htt_detach(pdev->htt_pdev); + +fail2: + ol_txrx_peer_find_detach(pdev); + +fail1: + adf_os_mem_free(pdev); + +fail0: + return NULL; /* fail */ +} + +A_STATUS ol_txrx_pdev_attach_target(ol_txrx_pdev_handle pdev) +{ + return htt_attach_target(pdev->htt_pdev); +} + +void +ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force) +{ + int i; + unsigned int page_idx; + + /*checking to ensure txrx pdev structure is not NULL */ + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "NULL pdev passed to %s\n", __func__); + return; + } + /* preconditions */ + TXRX_ASSERT2(pdev); + + /* check that the pdev has no vdevs allocated */ + TXRX_ASSERT1(TAILQ_EMPTY(&pdev->vdev_list)); + + OL_RX_REORDER_TIMEOUT_CLEANUP(pdev); + + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { + ol_tx_sched_detach(pdev); + } +#ifdef QCA_SUPPORT_TX_THROTTLE + /* Thermal Mitigation */ + adf_os_timer_cancel(&pdev->tx_throttle.phase_timer); + adf_os_timer_free(&pdev->tx_throttle.phase_timer); +#ifdef QCA_SUPPORT_TXRX_VDEV_LL_TXQ + adf_os_timer_cancel(&pdev->tx_throttle.tx_timer); + adf_os_timer_free(&pdev->tx_throttle.tx_timer); +#endif +#endif + + if (force) { + /* + * The assertion above confirms that all vdevs within this pdev + * were detached. However, they may not have actually been deleted. + * If the vdev had peers which never received a PEER_UNMAP message + * from the target, then there are still zombie peer objects, and + * the vdev parents of the zombie peers are also zombies, hanging + * around until their final peer gets deleted. + * Go through the peer hash table and delete any peers left in it. + * As a side effect, this will complete the deletion of any vdevs + * that are waiting for their peers to finish deletion. + */ + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "Force delete for pdev %p\n", pdev); + ol_txrx_peer_find_hash_erase(pdev); + } + + /* Stop the communication between HTT and target at first */ + htt_detach_target(pdev->htt_pdev); + + for (i = 0; i < pdev->tx_desc.pool_size; i++) { + void *htt_tx_desc; + + /* + * Confirm that each tx descriptor is "empty", i.e. it has + * no tx frame attached. + * In particular, check that there are no frames that have + * been given to the target to transmit, for which the + * target has never provided a response. + */ + if (adf_os_atomic_read(&pdev->tx_desc.array[i].tx_desc->ref_cnt)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "Warning: freeing tx frame " + "(no tx completion from the target)\n"); + ol_tx_desc_frame_free_nonstd( + pdev, pdev->tx_desc.array[i].tx_desc, 1); + } + htt_tx_desc = pdev->tx_desc.array[i].tx_desc->htt_tx_desc; + htt_tx_desc_free(pdev->htt_pdev, htt_tx_desc); + } + + + for (page_idx = 0; page_idx < pdev->num_desc_pages; page_idx++) { + adf_os_mem_free(pdev->desc_pages[page_idx]); + } + adf_os_mem_free(pdev->desc_pages); + + adf_os_mem_free(pdev->tx_desc.array); + +#ifdef IPA_UC_OFFLOAD + /* Detach micro controller data path offload resource */ + if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) { + htt_ipa_uc_detach(pdev->htt_pdev); + } +#endif /* IPA_UC_OFFLOAD */ + + htt_detach(pdev->htt_pdev); + + ol_txrx_peer_find_detach(pdev); + + adf_os_spinlock_destroy(&pdev->tx_mutex); + adf_os_spinlock_destroy(&pdev->peer_ref_mutex); + adf_os_spinlock_destroy(&pdev->last_real_peer_mutex); + adf_os_spinlock_destroy(&pdev->rx.mutex); +#ifdef QCA_SUPPORT_TX_THROTTLE + /* Thermal Mitigation */ + adf_os_spinlock_destroy(&pdev->tx_throttle.mutex); +#endif + + /* TX flow control for peer who is in very bad link status */ + ol_tx_badpeer_flow_cl_deinit(pdev); + + OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev); + + OL_RX_REORDER_TRACE_DETACH(pdev); + OL_RX_PN_TRACE_DETACH(pdev); + +#if defined(CONFIG_HL_SUPPORT) && defined(DEBUG_HL_LOGGING) + adf_os_spinlock_destroy(&pdev->txq_log_spinlock); +#endif + +#ifdef DEBUG_HL_LOGGING + adf_os_spinlock_destroy(&pdev->grp_stat_spinlock); +#endif + + /* + * WDI event detach + */ +#ifdef WDI_EVENT_ENABLE + if (wdi_event_detach(pdev) == A_ERROR) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_WARN, + "WDI detach unsuccessful\n"); + } +#endif + OL_TXRX_LOCAL_PEER_ID_CLEANUP(pdev); + +#ifdef QCA_COMPUTE_TX_DELAY + adf_os_spinlock_destroy(&pdev->tx_delay.mutex); +#endif + + adf_os_mem_free(pdev); +} + +ol_txrx_vdev_handle +ol_txrx_vdev_attach( + ol_txrx_pdev_handle pdev, + u_int8_t *vdev_mac_addr, + u_int8_t vdev_id, + enum wlan_op_mode op_mode) +{ + struct ol_txrx_vdev_t *vdev; + + /* preconditions */ + TXRX_ASSERT2(pdev); + TXRX_ASSERT2(vdev_mac_addr); + + vdev = adf_os_mem_alloc(pdev->osdev, sizeof(*vdev)); + if (!vdev) { + return NULL; /* failure */ + } + + /* store provided params */ + vdev->pdev = pdev; + vdev->vdev_id = vdev_id; + vdev->opmode = op_mode; + + vdev->osif_rx = NULL; + + vdev->delete.pending = 0; + vdev->safemode = 0; + vdev->drop_unenc = 1; + vdev->num_filters = 0; +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + adf_os_atomic_init(&vdev->tx_desc_count); +#endif + + adf_os_mem_copy( + &vdev->mac_addr.raw[0], vdev_mac_addr, OL_TXRX_MAC_ADDR_LEN); + + TAILQ_INIT(&vdev->peer_list); + vdev->last_real_peer = NULL; + + #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + vdev->hlTdlsFlag = false; + #endif + + #ifdef QCA_IBSS_SUPPORT + vdev->ibss_peer_num = 0; + vdev->ibss_peer_heart_beat_timer = 0; + #endif + + #if defined(CONFIG_HL_SUPPORT) + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { + u_int8_t i; + for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { + TAILQ_INIT(&vdev->txqs[i].head); + vdev->txqs[i].paused_count.total = 0; + vdev->txqs[i].frms = 0; + vdev->txqs[i].bytes = 0; + vdev->txqs[i].ext_tid = OL_TX_NUM_TIDS + i; + vdev->txqs[i].flag = ol_tx_queue_empty; + /* aggregation is not applicable for vdev tx queues */ + vdev->txqs[i].aggr_state = ol_tx_aggr_disabled; + OL_TX_TXQ_SET_GROUP_PTR(&vdev->txqs[i], NULL); + ol_txrx_set_txq_peer(&vdev->txqs[i], NULL); + } + } + #endif /* defined(CONFIG_HL_SUPPORT) */ + + adf_os_spinlock_init(&vdev->ll_pause.mutex); + vdev->ll_pause.paused_reason = 0; + vdev->ll_pause.txq.head = vdev->ll_pause.txq.tail = NULL; + vdev->ll_pause.txq.depth = 0; + adf_os_timer_init( + pdev->osdev, + &vdev->ll_pause.timer, + ol_tx_vdev_ll_pause_queue_send, + vdev, ADF_DEFERRABLE_TIMER); + adf_os_atomic_init(&vdev->os_q_paused); + adf_os_atomic_set(&vdev->os_q_paused, 0); + vdev->tx_fl_lwm = 0; + vdev->tx_fl_hwm = 0; + vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID; + vdev->osif_flow_control_cb = NULL; + /* Default MAX Q depth for every VDEV */ + vdev->ll_pause.max_q_depth = + ol_tx_cfg_max_tx_queue_depth_ll(vdev->pdev->ctrl_pdev); + /* add this vdev into the pdev's list */ + TAILQ_INSERT_TAIL(&pdev->vdev_list, vdev, vdev_list_elem); + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "Created vdev %p (%02x:%02x:%02x:%02x:%02x:%02x)\n", + vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], + vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + + /* + * We've verified that htt_op_mode == wlan_op_mode, + * so no translation is needed. + */ + htt_vdev_attach(pdev->htt_pdev, vdev_id, op_mode); + + return vdev; +} + +void ol_txrx_osif_vdev_register(ol_txrx_vdev_handle vdev, + void *osif_vdev, + struct ol_txrx_osif_ops *txrx_ops) +{ + vdev->osif_dev = osif_vdev; + vdev->osif_rx = txrx_ops->rx.std; + + if (ol_cfg_is_high_latency(vdev->pdev->ctrl_pdev)) { + txrx_ops->tx.std = vdev->tx = ol_tx_hl; + txrx_ops->tx.non_std = ol_tx_non_std_hl; + } else { + txrx_ops->tx.std = vdev->tx = OL_TX_LL; + txrx_ops->tx.non_std = ol_tx_non_std_ll; + } + #ifdef QCA_LL_TX_FLOW_CT + vdev->osif_flow_control_cb = txrx_ops->tx.flow_control_cb; + #endif /* QCA_LL_TX_FLOW_CT */ +} + +void +ol_txrx_set_curchan( + ol_txrx_pdev_handle pdev, + u_int32_t chan_mhz) +{ + return; +} + +void +ol_txrx_set_safemode( + ol_txrx_vdev_handle vdev, + u_int32_t val) +{ + vdev->safemode = val; +} + +void +ol_txrx_set_privacy_filters( + ol_txrx_vdev_handle vdev, + void *filters, + u_int32_t num) +{ + adf_os_mem_copy( + vdev->privacy_filters, filters, num*sizeof(privacy_exemption)); + vdev->num_filters = num; +} + +void +ol_txrx_set_drop_unenc( + ol_txrx_vdev_handle vdev, + u_int32_t val) +{ + vdev->drop_unenc = val; +} + +void +ol_txrx_vdev_detach( + ol_txrx_vdev_handle vdev, + ol_txrx_vdev_delete_cb callback, + void *context) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + + /* preconditions */ + TXRX_ASSERT2(vdev); + +#if defined(CONFIG_HL_SUPPORT) + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { + struct ol_tx_frms_queue_t *txq; + int i; + + for (i = 0; i < OL_TX_VDEV_NUM_QUEUES; i++) { + txq = &vdev->txqs[i]; + ol_tx_queue_free(pdev, txq, (i + OL_TX_NUM_TIDS)); + } + } + #endif /* defined(CONFIG_HL_SUPPORT) */ + + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + adf_os_timer_cancel(&vdev->ll_pause.timer); + vdev->ll_pause.is_q_timer_on = FALSE; + adf_os_timer_free(&vdev->ll_pause.timer); + while (vdev->ll_pause.txq.head) { + adf_nbuf_t next = adf_nbuf_next(vdev->ll_pause.txq.head); + adf_nbuf_set_next(vdev->ll_pause.txq.head, NULL); + adf_nbuf_unmap(pdev->osdev, vdev->ll_pause.txq.head, + ADF_OS_DMA_TO_DEVICE); + adf_nbuf_tx_free(vdev->ll_pause.txq.head, 1 /* error */); + vdev->ll_pause.txq.head = next; + } + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + adf_os_spinlock_destroy(&vdev->ll_pause.mutex); + + /* remove the vdev from its parent pdev's list */ + TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem); + + /* + * Use peer_ref_mutex while accessing peer_list, in case + * a peer is in the process of being removed from the list. + */ + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + /* check that the vdev has no peers allocated */ + if (!TAILQ_EMPTY(&vdev->peer_list)) { + /* debug print - will be removed later */ + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: not deleting vdev object %p (%02x:%02x:%02x:%02x:%02x:%02x)" + "until deletion finishes for all its peers\n", + __func__, vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], + vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], + vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + /* indicate that the vdev needs to be deleted */ + vdev->delete.pending = 1; + vdev->delete.callback = callback; + vdev->delete.context = context; + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + return; + } + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: deleting vdev object %p (%02x:%02x:%02x:%02x:%02x:%02x)\n", + __func__, vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], + vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + + htt_vdev_detach(pdev->htt_pdev, vdev->vdev_id); + + /* + * Doesn't matter if there are outstanding tx frames - + * they will be freed once the target sends a tx completion + * message for them. + */ + adf_os_mem_free(vdev); + if (callback) { + callback(context); + } +} + +ol_txrx_peer_handle +ol_txrx_peer_attach( + ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, + u_int8_t *peer_mac_addr) +{ + struct ol_txrx_peer_t *peer; + struct ol_txrx_peer_t *temp_peer; + u_int8_t i; + int differs; + bool wait_on_deletion = false; + unsigned long rc; + + /* preconditions */ + TXRX_ASSERT2(pdev); + TXRX_ASSERT2(vdev); + TXRX_ASSERT2(peer_mac_addr); + + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + /* check for duplicate exsisting peer */ + TAILQ_FOREACH(temp_peer, &vdev->peer_list, peer_list_elem) { + if (!ol_txrx_peer_find_mac_addr_cmp(&temp_peer->mac_addr, + (union ol_txrx_align_mac_addr_t *)peer_mac_addr)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "vdev_id %d (%02x:%02x:%02x:%02x:%02x:%02x) already exsist.\n", + vdev->vdev_id, + peer_mac_addr[0], peer_mac_addr[1], + peer_mac_addr[2], peer_mac_addr[3], + peer_mac_addr[4], peer_mac_addr[5]); + if (adf_os_atomic_read(&temp_peer->delete_in_progress)) { + vdev->wait_on_peer_id = temp_peer->local_id; + adf_os_init_completion(&vdev->wait_delete_comp); + wait_on_deletion = true; + } else { + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + return NULL; + } + } + } + + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + + if (wait_on_deletion) { + /* wait for peer deletion */ + rc = adf_os_wait_for_completion_timeout( + &vdev->wait_delete_comp, + adf_os_msecs_to_ticks(PEER_DELETION_TIMEOUT)); + if (!rc) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "timedout waiting for peer(%d) deletion\n", + vdev->wait_on_peer_id); + vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID; + return NULL; + } + } + + peer = adf_os_mem_alloc(pdev->osdev, sizeof(*peer)); + if (!peer) { + return NULL; /* failure */ + } + adf_os_mem_zero(peer, sizeof(*peer)); + + /* store provided params */ + peer->vdev = vdev; + adf_os_mem_copy( + &peer->mac_addr.raw[0], peer_mac_addr, OL_TXRX_MAC_ADDR_LEN); + + #if defined(CONFIG_HL_SUPPORT) + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { + adf_os_spin_lock_bh(&pdev->tx_queue_spinlock); + for (i = 0; i < OL_TX_NUM_TIDS; i++) { + TAILQ_INIT(&peer->txqs[i].head); + peer->txqs[i].paused_count.total = 0; + peer->txqs[i].frms = 0; + peer->txqs[i].bytes = 0; + peer->txqs[i].ext_tid = i; + peer->txqs[i].flag = ol_tx_queue_empty; + peer->txqs[i].aggr_state = ol_tx_aggr_untried; + OL_TX_SET_PEER_GROUP_PTR(pdev, peer, vdev->vdev_id, i); + ol_txrx_set_txq_peer(&peer->txqs[i], peer); + } + adf_os_spin_unlock_bh(&pdev->tx_queue_spinlock); + + /* aggregation is not applicable for mgmt and non-QoS tx queues */ + for (i = OL_TX_NUM_QOS_TIDS; i < OL_TX_NUM_TIDS; i++) { + peer->txqs[i].aggr_state = ol_tx_aggr_disabled; + } + } + ol_txrx_peer_pause(peer); + #endif /* defined(CONFIG_HL_SUPPORT) */ + + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + /* add this peer into the vdev's list */ + TAILQ_INSERT_TAIL(&vdev->peer_list, peer, peer_list_elem); + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + /* check whether this is a real peer (peer mac addr != vdev mac addr) */ + if (ol_txrx_peer_find_mac_addr_cmp(&vdev->mac_addr, &peer->mac_addr)) { + vdev->last_real_peer = peer; + } + + peer->rx_opt_proc = pdev->rx_opt_proc; + + ol_rx_peer_init(pdev, peer); + + /* initialize the peer_id */ + for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) { + peer->peer_ids[i] = HTT_INVALID_PEER; + } + + adf_os_atomic_init(&peer->delete_in_progress); + + adf_os_atomic_init(&peer->ref_cnt); + + /* keep one reference for attach */ + adf_os_atomic_inc(&peer->ref_cnt); + + /* keep one reference for ol_rx_peer_map_handler */ + adf_os_atomic_inc(&peer->ref_cnt); + + peer->valid = 1; + + ol_txrx_peer_find_hash_add(pdev, peer); + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, + "vdev %p created peer %p (%02x:%02x:%02x:%02x:%02x:%02x)\n", + vdev, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], peer->mac_addr.raw[2], + peer->mac_addr.raw[3], peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + /* + * For every peer MAp message search and set if bss_peer + */ + differs = adf_os_mem_cmp( + peer->mac_addr.raw, vdev->mac_addr.raw, OL_TXRX_MAC_ADDR_LEN); + if (!differs) { + peer->bss_peer = 1; + } + + /* + * The peer starts in the "disc" state while association is in progress. + * Once association completes, the peer will get updated to "auth" state + * by a call to ol_txrx_peer_state_update if the peer is in open mode, or + * else to the "conn" state. For non-open mode, the peer will progress to + * "auth" state once the authentication completes. + */ + peer->state = ol_txrx_peer_state_invalid; + ol_txrx_peer_state_update(pdev, peer->mac_addr.raw, ol_txrx_peer_state_disc); + + #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI + peer->rssi_dbm = HTT_RSSI_INVALID; + #endif + + OL_TXRX_LOCAL_PEER_ID_ALLOC(pdev, peer); + + return peer; +} + +/* + * Discarding tx filter - removes all data frames (disconnected state) + */ +static A_STATUS +ol_tx_filter_discard(struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + return A_ERROR; +} +/* + * Non-autentication tx filter - filters out data frames that are not + * related to authentication, but allows EAPOL (PAE) or WAPI (WAI) + * data frames (connected state) + */ +static A_STATUS +ol_tx_filter_non_auth(struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + return + (tx_msdu_info->htt.info.ethertype == ETHERTYPE_PAE || + tx_msdu_info->htt.info.ethertype == ETHERTYPE_WAI) ? A_OK : A_ERROR; +} + +/* + * Pass-through tx filter - lets all data frames through (authenticated state) + */ +static A_STATUS +ol_tx_filter_pass_thru(struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + return A_OK; +} + +void +ol_txrx_peer_state_update(ol_txrx_pdev_handle pdev, u_int8_t *peer_mac, + enum ol_txrx_peer_state state) +{ + struct ol_txrx_peer_t *peer; + + peer = ol_txrx_peer_find_hash_find(pdev, peer_mac, 0, 1); + + if (NULL == peer) + { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, "%s: peer is null for peer_mac" + " 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, + peer_mac[0], peer_mac[1], peer_mac[2], peer_mac[3], + peer_mac[4], peer_mac[5]); + return; + } + + + /* TODO: Should we send WMI command of the connection state? */ + /* avoid multiple auth state change. */ + if (peer->state == state) { +#ifdef TXRX_PRINT_VERBOSE_ENABLE + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO3, + "%s: no state change, returns directly\n", __FUNCTION__); +#endif + adf_os_atomic_dec(&peer->ref_cnt); + return; + } + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, "%s: change from %d to %d\n", + __FUNCTION__, peer->state, state); + + peer->tx_filter = (state == ol_txrx_peer_state_auth) ? + ol_tx_filter_pass_thru : (state == ol_txrx_peer_state_conn) ? + ol_tx_filter_non_auth : ol_tx_filter_discard; + + if (peer->vdev->pdev->cfg.host_addba) { + if (state == ol_txrx_peer_state_auth) { + int tid; + /* + * Pause all regular (non-extended) TID tx queues until data + * arrives and ADDBA negotiation has completed. + */ + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, + "%s: pause peer and unpause mgmt, non-qos\n", __func__); + ol_txrx_peer_pause(peer); /* pause all tx queues */ + /* unpause mgmt and non-QoS tx queues */ + for (tid = OL_TX_NUM_QOS_TIDS; tid < OL_TX_NUM_TIDS; tid++) { + ol_txrx_peer_tid_unpause(peer, tid); + } + } + } + adf_os_atomic_dec(&peer->ref_cnt); + + /* Set the state after the Pause to avoid the race condiction with ADDBA check in tx path */ + peer->state = state; +} + +void +ol_txrx_peer_keyinstalled_state_update( + struct ol_txrx_peer_t *peer, + u_int8_t val) +{ + peer->keyinstalled = val; +} + +void +ol_txrx_peer_update(ol_txrx_vdev_handle vdev, + u_int8_t *peer_mac, + ol_txrx_peer_update_param_t *param, + ol_txrx_peer_update_select_t select) +{ + struct ol_txrx_peer_t *peer; + + peer = ol_txrx_peer_find_hash_find(vdev->pdev, peer_mac, 0, 1); + if (!peer) + { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, "%s: peer is null", __FUNCTION__); + return; + } + + switch (select) { + case ol_txrx_peer_update_qos_capable: + { + /* save qos_capable here txrx peer, + * when HTT_ISOC_T2H_MSG_TYPE_PEER_INFO comes then save. + */ + peer->qos_capable = param->qos_capable; + /* + * The following function call assumes that the peer has a single + * ID. This is currently true, and is expected to remain true. + */ + htt_peer_qos_update( + peer->vdev->pdev->htt_pdev, + peer->peer_ids[0], + peer->qos_capable); + break; + } + case ol_txrx_peer_update_uapsdMask: + { + peer->uapsd_mask = param->uapsd_mask; + htt_peer_uapsdmask_update( + peer->vdev->pdev->htt_pdev, + peer->peer_ids[0], + peer->uapsd_mask); + break; + } + case ol_txrx_peer_update_peer_security: + { + enum ol_sec_type sec_type = param->sec_type; + enum htt_sec_type peer_sec_type = htt_sec_type_none; + + switch(sec_type) { + case ol_sec_type_none: + peer_sec_type = htt_sec_type_none; + break; + case ol_sec_type_wep128: + peer_sec_type = htt_sec_type_wep128; + break; + case ol_sec_type_wep104: + peer_sec_type = htt_sec_type_wep104; + break; + case ol_sec_type_wep40: + peer_sec_type = htt_sec_type_wep40; + break; + case ol_sec_type_tkip: + peer_sec_type = htt_sec_type_tkip; + break; + case ol_sec_type_tkip_nomic: + peer_sec_type = htt_sec_type_tkip_nomic; + break; + case ol_sec_type_aes_ccmp: + peer_sec_type = htt_sec_type_aes_ccmp; + break; + case ol_sec_type_wapi: + peer_sec_type = htt_sec_type_wapi; + break; + default: + peer_sec_type = htt_sec_type_none; + break; + } + + peer->security[txrx_sec_ucast].sec_type = + peer->security[txrx_sec_mcast].sec_type = peer_sec_type; + + break; + } + default: + { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "ERROR: unknown param %d in %s\n", select, __func__); + break; + } + } + adf_os_atomic_dec(&peer->ref_cnt); +} + +u_int8_t +ol_txrx_peer_uapsdmask_get(struct ol_txrx_pdev_t *txrx_pdev, u_int16_t peer_id) +{ + + struct ol_txrx_peer_t *peer; + peer = ol_txrx_peer_find_by_id(txrx_pdev, peer_id); + if (peer) { + return peer->uapsd_mask; + } + + return 0; +} + +u_int8_t +ol_txrx_peer_qoscapable_get (struct ol_txrx_pdev_t * txrx_pdev, u_int16_t peer_id) +{ + + struct ol_txrx_peer_t *peer_t = ol_txrx_peer_find_by_id(txrx_pdev, peer_id); + if (peer_t != NULL) + { + return peer_t->qos_capable; + } + + return 0; +} + +void +ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) +{ + struct ol_txrx_vdev_t *vdev; + struct ol_txrx_pdev_t *pdev; + int i; + + /* preconditions */ + TXRX_ASSERT2(peer); + + vdev = peer->vdev; + if (NULL == vdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "The vdev is not present anymore\n"); + return; + } + + pdev = vdev->pdev; + if (NULL == pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "The pdev is not present anymore\n"); + return; + } + + /* + * Check for the reference count before deleting the peer + * as we noticed that sometimes we are re-entering this + * function again which is leading to dead-lock. + * (A double-free should never happen, so throw an assertion if it does.) + */ + + if (0 == adf_os_atomic_read(&(peer->ref_cnt)) ) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "The Peer is not present anymore\n"); + adf_os_assert(0); + return; + } + + /* + * Hold the lock all the way from checking if the peer ref count + * is zero until the peer references are removed from the hash + * table and vdev list (if the peer ref count is zero). + * This protects against a new HL tx operation starting to use the + * peer object just after this function concludes it's done being used. + * Furthermore, the lock needs to be held while checking whether the + * vdev's list of peers is empty, to make sure that list is not modified + * concurrently with the empty check. + */ + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + if (adf_os_atomic_dec_and_test(&peer->ref_cnt)) { + u_int16_t peer_id; + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Deleting peer %p (%02x:%02x:%02x:%02x:%02x:%02x)\n", + peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + + peer_id = peer->local_id; + /* remove the reference to the peer from the hash table */ + ol_txrx_peer_find_hash_remove(pdev, peer); + + /* remove the peer from its parent vdev's list */ + TAILQ_REMOVE(&peer->vdev->peer_list, peer, peer_list_elem); + + /* cleanup the Rx reorder queues for this peer */ + ol_rx_peer_cleanup(vdev, peer); + + /* peer is removed from peer_list */ + adf_os_atomic_set(&peer->delete_in_progress, 0); + + /* Set wait_delete_comp event if the current peer id matches + * with registered peer id. + */ + if (peer_id == vdev->wait_on_peer_id) { + adf_os_complete(&vdev->wait_delete_comp); + vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID; + } + + /* check whether the parent vdev has no peers left */ + if (TAILQ_EMPTY(&vdev->peer_list)) { + /* + * Check if the parent vdev was waiting for its peers to be + * deleted, in order for it to be deleted too. + */ + if (vdev->delete.pending == 1) { + ol_txrx_vdev_delete_cb vdev_delete_cb = vdev->delete.callback; + void *vdev_delete_context = vdev->delete.context; + + /* + * Now that there are no references to the peer, we can + * release the peer reference lock. + */ + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: deleting vdev object %p " + "(%02x:%02x:%02x:%02x:%02x:%02x)" + " - its last peer is done\n", + __func__, vdev, + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], + vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], + vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + /* all peers are gone, go ahead and delete it */ + adf_os_mem_free(vdev); + if (vdev_delete_cb) { + vdev_delete_cb(vdev_delete_context); + } + } else { + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + } + } else { + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + } + + #if defined(CONFIG_HL_SUPPORT) + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { + struct ol_tx_frms_queue_t *txq; + + for (i = 0; i < OL_TX_NUM_TIDS; i++) { + txq = &peer->txqs[i]; + ol_tx_queue_free(pdev, txq, i); + } + } + #endif /* defined(CONFIG_HL_SUPPORT) */ + /* + * 'array' is allocated in addba handler and is supposed to be freed + * in delba handler. There is the case (for example, in SSR) where + * delba handler is not called. Because array points to address of + * 'base' by default and is reallocated in addba handler later, only + * free the memory when the array does not point to base. + */ + for (i = 0; i < OL_TXRX_NUM_EXT_TIDS; i++) { + if (peer->tids_rx_reorder[i].array != + &peer->tids_rx_reorder[i].base) { + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s, delete reorder array, tid:%d\n", + __func__, i); + adf_os_mem_free(peer->tids_rx_reorder[i].array); + ol_rx_reorder_init(&peer->tids_rx_reorder[i], (u_int8_t)i); + } + } + + adf_os_mem_free(peer); + } else { + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + } +} + +void +ol_txrx_peer_detach(ol_txrx_peer_handle peer) +{ + struct ol_txrx_vdev_t *vdev = peer->vdev; + + /* redirect the peer's rx delivery function to point to a discard func */ + peer->rx_opt_proc = ol_rx_discard; + + peer->valid = 0; + + OL_TXRX_LOCAL_PEER_ID_FREE(peer->vdev->pdev, peer); + + /* debug print to dump rx reorder state */ + //htt_rx_reorder_log_print(vdev->pdev->htt_pdev); + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s:peer %p (%02x:%02x:%02x:%02x:%02x:%02x)\n", + __func__, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + + if (peer->vdev->last_real_peer == peer) { + peer->vdev->last_real_peer = NULL; + } + + adf_os_spin_lock_bh(&vdev->pdev->last_real_peer_mutex); + if (vdev->last_real_peer == peer) { + vdev->last_real_peer = NULL; + } + adf_os_spin_unlock_bh(&vdev->pdev->last_real_peer_mutex); + htt_rx_reorder_log_print(peer->vdev->pdev->htt_pdev); + + /* set delete_in_progress to identify that wma + * is waiting for unmap massage for this peer */ + adf_os_atomic_set(&peer->delete_in_progress, 1); + /* + * Remove the reference added during peer_attach. + * The peer will still be left allocated until the + * PEER_UNMAP message arrives to remove the other + * reference, added by the PEER_MAP message. + */ + ol_txrx_peer_unref_delete(peer); +} + +ol_txrx_peer_handle +ol_txrx_peer_find_by_addr(struct ol_txrx_pdev_t *pdev, u_int8_t *peer_mac_addr) +{ + struct ol_txrx_peer_t *peer; + peer = ol_txrx_peer_find_hash_find(pdev, peer_mac_addr, 0, 0); + if (peer) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: Delete extra reference %p\n", __func__, peer); + /* release the extra reference */ + ol_txrx_peer_unref_delete(peer); + } + return peer; +} + +/** + * ol_txrx_dump_tx_desc() - dump tx desc info + * @pdev_handle: Pointer to pdev handle + * + * Return: none + */ +void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev_handle) +{ + struct ol_txrx_pdev_t *pdev = pdev_handle; + int total; + + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) + total = adf_os_atomic_read(&pdev->orig_target_tx_credit); + else + total = ol_cfg_target_tx_credit(pdev->ctrl_pdev); + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Total tx credits %d free_credits %d", + total, pdev->tx_desc.num_free); + + return; +} + +int +ol_txrx_get_tx_pending(ol_txrx_pdev_handle pdev_handle) +{ + struct ol_txrx_pdev_t *pdev = (ol_txrx_pdev_handle)pdev_handle; + int total; + + if (ol_cfg_is_high_latency(pdev->ctrl_pdev)) { + total = adf_os_atomic_read(&pdev->orig_target_tx_credit); + } else { + total = ol_cfg_target_tx_credit(pdev->ctrl_pdev); + } + + return (total - pdev->tx_desc.num_free); +} + +void +ol_txrx_discard_tx_pending(ol_txrx_pdev_handle pdev_handle) +{ + ol_tx_desc_list tx_descs; + /* First let hif do the adf_os_atomic_dec_and_test(&tx_desc->ref_cnt) + * then let htt do the adf_os_atomic_dec_and_test(&tx_desc->ref_cnt) + * which is tha same with normal data send complete path*/ + htt_tx_pending_discard(pdev_handle->htt_pdev); + + TAILQ_INIT(&tx_descs); + ol_tx_queue_discard(pdev_handle, A_TRUE, &tx_descs); + //Discard Frames in Discard List + ol_tx_desc_frame_list_free(pdev_handle, &tx_descs, 1 /* error */); + + ol_tx_discard_target_frms(pdev_handle); +} + +/*--- debug features --------------------------------------------------------*/ + +unsigned g_txrx_print_level = TXRX_PRINT_LEVEL_ERR; /* default */ + +void ol_txrx_print_level_set(unsigned level) +{ +#ifndef TXRX_PRINT_ENABLE + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "The driver is compiled without TXRX prints enabled.\n" + "To enable them, recompile with TXRX_PRINT_ENABLE defined.\n"); +#else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "TXRX printout level changed from %d to %d\n", + g_txrx_print_level, level); + g_txrx_print_level = level; +#endif +} + +struct ol_txrx_stats_req_internal { + struct ol_txrx_stats_req base; + int serviced; /* state of this request */ + int offset; +}; + +static inline +u_int64_t OL_TXRX_STATS_PTR_TO_U64(struct ol_txrx_stats_req_internal *req) +{ + return (u_int64_t) ((size_t) req); +} + +static inline +struct ol_txrx_stats_req_internal * OL_TXRX_U64_TO_STATS_PTR(u_int64_t cookie) +{ + return (struct ol_txrx_stats_req_internal *) ((size_t) cookie); +} + +#ifdef ATH_PERF_PWR_OFFLOAD +void +ol_txrx_fw_stats_cfg( + ol_txrx_vdev_handle vdev, + u_int8_t cfg_stats_type, + u_int32_t cfg_val) +{ + u_int64_t dummy_cookie = 0; + htt_h2t_dbg_stats_get( + vdev->pdev->htt_pdev, + 0 /* upload mask */, + 0 /* reset mask */, + cfg_stats_type, + cfg_val, + dummy_cookie); +} + +A_STATUS +ol_txrx_fw_stats_get( + ol_txrx_vdev_handle vdev, + struct ol_txrx_stats_req *req) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + u_int64_t cookie; + struct ol_txrx_stats_req_internal *non_volatile_req; + + if (!pdev || + req->stats_type_upload_mask >= 1 << HTT_DBG_NUM_STATS || + req->stats_type_reset_mask >= 1 << HTT_DBG_NUM_STATS ) + { + return A_ERROR; + } + + /* + * Allocate a non-transient stats request object. + * (The one provided as an argument is likely allocated on the stack.) + */ + non_volatile_req = adf_os_mem_alloc(pdev->osdev, sizeof(*non_volatile_req)); + if (! non_volatile_req) { + return A_NO_MEMORY; + } + /* copy the caller's specifications */ + non_volatile_req->base = *req; + non_volatile_req->serviced = 0; + non_volatile_req->offset = 0; + + /* use the non-volatile request object's address as the cookie */ + cookie = OL_TXRX_STATS_PTR_TO_U64(non_volatile_req); + + if (htt_h2t_dbg_stats_get( + pdev->htt_pdev, + req->stats_type_upload_mask, + req->stats_type_reset_mask, + HTT_H2T_STATS_REQ_CFG_STAT_TYPE_INVALID, 0, + cookie)) + { + adf_os_mem_free(non_volatile_req); + return A_ERROR; + } + + if (req->wait.blocking) { + while (adf_os_mutex_acquire(pdev->osdev, req->wait.sem_ptr)) {} + } + + return A_OK; +} +#endif +void +ol_txrx_fw_stats_handler( + ol_txrx_pdev_handle pdev, + u_int64_t cookie, + u_int8_t *stats_info_list) +{ + enum htt_dbg_stats_type type; + enum htt_dbg_stats_status status; + int length; + u_int8_t *stats_data; + struct ol_txrx_stats_req_internal *req; + int more = 0; + + req = OL_TXRX_U64_TO_STATS_PTR(cookie); + + do { + htt_t2h_dbg_stats_hdr_parse( + stats_info_list, &type, &status, &length, &stats_data); + if (status == HTT_DBG_STATS_STATUS_SERIES_DONE) { + break; + } + if (status == HTT_DBG_STATS_STATUS_PRESENT || + status == HTT_DBG_STATS_STATUS_PARTIAL) + { + u_int8_t *buf; + int bytes = 0; + + if (status == HTT_DBG_STATS_STATUS_PARTIAL) { + more = 1; + } + if (req->base.print.verbose || req->base.print.concise) { + /* provide the header along with the data */ + htt_t2h_stats_print(stats_info_list, req->base.print.concise); + } + + switch (type) { + case HTT_DBG_STATS_WAL_PDEV_TXRX: + bytes = sizeof(struct wlan_dbg_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct wlan_dbg_stats); + if (req->base.copy.byte_limit < limit) { + limit = req->base.copy.byte_limit; + } + buf = req->base.copy.buf + req->offset; + adf_os_mem_copy(buf, stats_data, limit); + } + break; + case HTT_DBG_STATS_RX_REORDER: + bytes = sizeof(struct rx_reorder_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct rx_reorder_stats); + if (req->base.copy.byte_limit < limit) { + limit = req->base.copy.byte_limit; + } + buf = req->base.copy.buf + req->offset; + adf_os_mem_copy(buf, stats_data, limit); + } + break; + case HTT_DBG_STATS_RX_RATE_INFO: + bytes = sizeof(wlan_dbg_rx_rate_info_t); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(wlan_dbg_rx_rate_info_t); + if (req->base.copy.byte_limit < limit) { + limit = req->base.copy.byte_limit; + } + buf = req->base.copy.buf + req->offset; + adf_os_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_TX_RATE_INFO: + bytes = sizeof(wlan_dbg_tx_rate_info_t); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(wlan_dbg_tx_rate_info_t); + if (req->base.copy.byte_limit < limit) { + limit = req->base.copy.byte_limit; + } + buf = req->base.copy.buf + req->offset; + adf_os_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_TX_PPDU_LOG: + bytes = 0; /* TO DO: specify how many bytes are present */ + /* TO DO: add copying to the requestor's buffer */ + break; + + case HTT_DBG_STATS_RX_REMOTE_RING_BUFFER_INFO: + + bytes = sizeof(struct rx_remote_buffer_mgmt_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct rx_remote_buffer_mgmt_stats); + if (req->base.copy.byte_limit < limit) { + limit = req->base.copy.byte_limit; + } + buf = req->base.copy.buf + req->offset; + adf_os_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT: + + bytes = sizeof(struct rx_txbf_musu_ndpa_pkts_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct rx_txbf_musu_ndpa_pkts_stats); + if (req->base.copy.byte_limit < limit) { + limit = req->base.copy.byte_limit; + } + buf = req->base.copy.buf + req->offset; + adf_os_mem_copy(buf, stats_data, limit); + } + break; + + default: + break; + } + buf = req->base.copy.buf ? req->base.copy.buf : stats_data; + if (req->base.callback.fp) { + req->base.callback.fp( + req->base.callback.ctxt, type, buf, bytes); + } + } + stats_info_list += length; + } while (1); + + if (! more) { + if (req->base.wait.blocking) { + adf_os_mutex_release(pdev->osdev, req->base.wait.sem_ptr); + } + adf_os_mem_free(req); + } +} + +#ifndef ATH_PERF_PWR_OFFLOAD /*---------------------------------------------*/ +int ol_txrx_debug(ol_txrx_vdev_handle vdev, int debug_specs) +{ + if (debug_specs & TXRX_DBG_MASK_OBJS) { + #if defined(TXRX_DEBUG_LEVEL) && TXRX_DEBUG_LEVEL > 5 + ol_txrx_pdev_display(vdev->pdev, 0); + #else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "The pdev,vdev,peer display functions are disabled.\n" + "To enable them, recompile with TXRX_DEBUG_LEVEL > 5.\n"); + #endif + } + if (debug_specs & TXRX_DBG_MASK_STATS) { + #if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF + ol_txrx_stats_display(vdev->pdev); + #else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "txrx stats collection is disabled.\n" + "To enable it, recompile with TXRX_STATS_LEVEL on.\n"); + #endif + } + if (debug_specs & TXRX_DBG_MASK_PROT_ANALYZE) { + #if defined(ENABLE_TXRX_PROT_ANALYZE) + ol_txrx_prot_ans_display(vdev->pdev); + #else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "txrx protocol analysis is disabled.\n" + "To enable it, recompile with " + "ENABLE_TXRX_PROT_ANALYZE defined.\n"); + #endif + } + if (debug_specs & TXRX_DBG_MASK_RX_REORDER_TRACE) { + #if defined(ENABLE_RX_REORDER_TRACE) + ol_rx_reorder_trace_display(vdev->pdev, 0, 0); + #else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_FATAL, + "rx reorder seq num trace is disabled.\n" + "To enable it, recompile with " + "ENABLE_RX_REORDER_TRACE defined.\n"); + #endif + + } + return 0; +} +#endif + +int ol_txrx_aggr_cfg(ol_txrx_vdev_handle vdev, + int max_subfrms_ampdu, + int max_subfrms_amsdu) +{ + return htt_h2t_aggr_cfg_msg(vdev->pdev->htt_pdev, + max_subfrms_ampdu, + max_subfrms_amsdu); +} + +#if defined(TXRX_DEBUG_LEVEL) && TXRX_DEBUG_LEVEL > 5 +void +ol_txrx_pdev_display(ol_txrx_pdev_handle pdev, int indent) +{ + struct ol_txrx_vdev_t *vdev; + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*s%s:\n", indent, " ", "txrx pdev"); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*spdev object: %p\n", indent+4, " ", pdev); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*svdev list:\n", indent+4, " "); + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + ol_txrx_vdev_display(vdev, indent+8); + } + ol_txrx_peer_find_display(pdev, indent+4); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*stx desc pool: %d elems @ %p\n", indent+4, " ", + pdev->tx_desc.pool_size, pdev->tx_desc.array); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, "\n"); + htt_display(pdev->htt_pdev, indent); +} + +void +ol_txrx_vdev_display(ol_txrx_vdev_handle vdev, int indent) +{ + struct ol_txrx_peer_t *peer; + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*stxrx vdev: %p\n", indent, " ", vdev); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*sID: %d\n", indent+4, " ", vdev->vdev_id); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*sMAC addr: %d:%d:%d:%d:%d:%d\n", + indent+4, " ", + vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], + vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*speer list:\n", indent+4, " "); + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + ol_txrx_peer_display(peer, indent+8); + } +} + +void +ol_txrx_peer_display(ol_txrx_peer_handle peer, int indent) +{ + int i; + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*stxrx peer: %p\n", indent, " ", peer); + for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) { + if (peer->peer_ids[i] != HTT_INVALID_PEER) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*sID: %d\n", indent+4, " ", peer->peer_ids[i]); + } + } +} +#endif /* TXRX_DEBUG_LEVEL */ +/** + * ol_txrx_stats() - update ol layter stats + * @vdev: pointer to vdev adapter + * @buffer: pointer to buffer + * @buf_len: length of the buffer + * * + * to update the stats + * + * Return: None + */ +void +ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, unsigned buf_len) +{ + snprintf(buffer, buf_len, + "\nTXRX stats:\n" + "\nllQueue State : %s" + "\n pause %u unpause %u" + "\n overflow %u" + "\nllQueue timer state : %s\n", + ((vdev->ll_pause.is_q_paused == FALSE) ? "UNPAUSED" : "PAUSED"), + vdev->ll_pause.q_pause_cnt, + vdev->ll_pause.q_unpause_cnt, + vdev->ll_pause.q_overflow_cnt, + ((vdev->ll_pause.is_q_timer_on == FALSE) + ? "NOT-RUNNING" : "RUNNING")); +} + +#if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF +void +ol_txrx_stats_display(ol_txrx_pdev_handle pdev) +{ + + adf_os_print("TXRX Stats:\n"); + if (TXRX_STATS_LEVEL == TXRX_STATS_LEVEL_BASIC) { + adf_os_print( + " tx: %lld msdus (%lld B) rejected %lld (%lld B) \n", + pdev->stats.pub.tx.delivered.pkts, + pdev->stats.pub.tx.delivered.bytes, + pdev->stats.pub.tx.dropped.host_reject.pkts, + pdev->stats.pub.tx.dropped.host_reject.bytes); + } else { /* full */ + adf_os_print( + " tx: sent %lld msdus (%lld B), rejected %lld (%lld B)\n" + " dropped %lld (%lld B)\n", + pdev->stats.pub.tx.delivered.pkts, + pdev->stats.pub.tx.delivered.bytes, + pdev->stats.pub.tx.dropped.host_reject.pkts, + pdev->stats.pub.tx.dropped.host_reject.bytes, + pdev->stats.pub.tx.dropped.download_fail.pkts + + pdev->stats.pub.tx.dropped.target_discard.pkts + + pdev->stats.pub.tx.dropped.no_ack.pkts, + pdev->stats.pub.tx.dropped.download_fail.bytes + + pdev->stats.pub.tx.dropped.target_discard.bytes + + pdev->stats.pub.tx.dropped.no_ack.bytes); + adf_os_print( + " download fail: %lld (%lld B), " + "target discard: %lld (%lld B), " + "no ack: %lld (%lld B)\n", + pdev->stats.pub.tx.dropped.download_fail.pkts, + pdev->stats.pub.tx.dropped.download_fail.bytes, + pdev->stats.pub.tx.dropped.target_discard.pkts, + pdev->stats.pub.tx.dropped.target_discard.bytes, + pdev->stats.pub.tx.dropped.no_ack.pkts, + pdev->stats.pub.tx.dropped.no_ack.bytes); + adf_os_print( + "Tx completion per interrupt:\n" + "Single Packet %d\n" + " 2-10 Packets %d\n" + "11-20 Packets %d\n" + "21-30 Packets %d\n" + "31-40 Packets %d\n" + "41-50 Packets %d\n" + "51-60 Packets %d\n" + " 60+ Packets %d\n", + pdev->stats.pub.tx.comp_histogram.pkts_1, + pdev->stats.pub.tx.comp_histogram.pkts_2_10, + pdev->stats.pub.tx.comp_histogram.pkts_11_20, + pdev->stats.pub.tx.comp_histogram.pkts_21_30, + pdev->stats.pub.tx.comp_histogram.pkts_31_40, + pdev->stats.pub.tx.comp_histogram.pkts_41_50, + pdev->stats.pub.tx.comp_histogram.pkts_51_60, + pdev->stats.pub.tx.comp_histogram.pkts_61_plus); + } + adf_os_print( + " rx: %lld ppdus, %lld mpdus, %lld msdus, %lld bytes, %lld errs\n", + pdev->stats.priv.rx.normal.ppdus, + pdev->stats.priv.rx.normal.mpdus, + pdev->stats.pub.rx.delivered.pkts, + pdev->stats.pub.rx.delivered.bytes, + pdev->stats.priv.rx.err.mpdu_bad); + + adf_os_print( + " fwd to stack %d, fwd to fw %d, fwd to stack & fw %d\n", + pdev->stats.pub.rx.intra_bss_fwd.packets_stack, + pdev->stats.pub.rx.intra_bss_fwd.packets_fwd, + pdev->stats.pub.rx.intra_bss_fwd.packets_stack_n_fwd); +} + +void +ol_txrx_stats_clear(ol_txrx_pdev_handle pdev) +{ + if (TXRX_STATS_LEVEL == TXRX_STATS_LEVEL_BASIC) { + pdev->stats.pub.tx.delivered.pkts = 0; + pdev->stats.pub.tx.delivered.bytes = 0; + pdev->stats.pub.tx.dropped.host_reject.pkts = 0; + pdev->stats.pub.tx.dropped.host_reject.bytes = 0; + adf_os_mem_zero(&pdev->stats.pub.rx, + sizeof(pdev->stats.pub.rx)); + adf_os_mem_zero(&pdev->stats.priv.rx, sizeof(pdev->stats.priv.rx)); + } else { /* Full */ + adf_os_mem_zero(&pdev->stats, sizeof(pdev->stats)); + } +} + +int +ol_txrx_stats_publish(ol_txrx_pdev_handle pdev, struct ol_txrx_stats *buf) +{ + adf_os_assert(buf); + adf_os_assert(pdev); + adf_os_mem_copy(buf, &pdev->stats.pub, sizeof(pdev->stats.pub)); + return TXRX_STATS_LEVEL; +} +#endif /* TXRX_STATS_LEVEL */ + +#if defined(ENABLE_TXRX_PROT_ANALYZE) + +void +ol_txrx_prot_ans_display(ol_txrx_pdev_handle pdev) +{ + ol_txrx_prot_an_display(pdev->prot_an_tx_sent); + ol_txrx_prot_an_display(pdev->prot_an_rx_sent); +} + +#endif /* ENABLE_TXRX_PROT_ANALYZE */ + +#ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI +int16_t +ol_txrx_peer_rssi(ol_txrx_peer_handle peer) +{ + return (peer->rssi_dbm == HTT_RSSI_INVALID) ? + OL_TXRX_RSSI_INVALID : peer->rssi_dbm; +} +#endif /* #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI */ + +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS +A_STATUS +ol_txrx_peer_stats_copy( + ol_txrx_pdev_handle pdev, + ol_txrx_peer_handle peer, + ol_txrx_peer_stats_t *stats) +{ + adf_os_assert(pdev && peer && stats); + adf_os_spin_lock_bh(&pdev->peer_stat_mutex); + adf_os_mem_copy(stats, &peer->stats, sizeof(*stats)); + adf_os_spin_unlock_bh(&pdev->peer_stat_mutex); + return A_OK; +} +#endif /* QCA_ENABLE_OL_TXRX_PEER_STATS */ + +void +ol_vdev_rx_set_intrabss_fwd( + ol_txrx_vdev_handle vdev, + a_bool_t val) +{ + if (NULL == vdev) + return; + + vdev->disable_intrabss_fwd = val; +} + +#ifdef QCA_LL_TX_FLOW_CT +a_bool_t +ol_txrx_get_tx_resource( + ol_txrx_vdev_handle vdev, + unsigned int low_watermark, + unsigned int high_watermark_offset +) +{ + adf_os_spin_lock_bh(&vdev->pdev->tx_mutex); +#ifdef CONFIG_PER_VDEV_TX_DESC_POOL + if (((ol_tx_desc_pool_size_hl(vdev->pdev->ctrl_pdev) >> 1) + - TXRX_HL_TX_FLOW_CTRL_MGMT_RESERVED) + - adf_os_atomic_read(&vdev->tx_desc_count) + < (u_int16_t)low_watermark) +#else + if (vdev->pdev->tx_desc.num_free < (u_int16_t)low_watermark) +#endif + { + vdev->tx_fl_lwm = (u_int16_t)low_watermark; + vdev->tx_fl_hwm = (u_int16_t)(low_watermark + high_watermark_offset); + /* Not enough free resource, stop TX OS Q */ + adf_os_atomic_set(&vdev->os_q_paused, 1); + adf_os_spin_unlock_bh(&vdev->pdev->tx_mutex); + return A_FALSE; + } + adf_os_spin_unlock_bh(&vdev->pdev->tx_mutex); + return A_TRUE; +} + +void +ol_txrx_ll_set_tx_pause_q_depth( + ol_txrx_vdev_handle vdev, + int pause_q_depth +) +{ + adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + vdev->ll_pause.max_q_depth = pause_q_depth; + adf_os_spin_unlock_bh(&vdev->ll_pause.mutex); + + return; +} +#endif /* QCA_LL_TX_FLOW_CT */ + +/** + * @brief Setter function to store OCB Peer. + */ +void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer) +{ + if (pdev == NULL) { + return; + } + + pdev->ocb_peer = peer; + pdev->ocb_peer_valid = (NULL != peer); +} + +/** + * @brief Getter function to retrieve OCB peer. + * @details + * Returns A_TRUE if ocb_peer is valid + * Otherwise, returns A_FALSE + */ +a_bool_t ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t **peer) +{ + int rc; + + if ((pdev == NULL) || (peer == NULL)) { + rc = A_FALSE; + goto exit; + } + + if (pdev->ocb_peer_valid) { + *peer = pdev->ocb_peer; + rc = A_TRUE; + } else { + rc = A_FALSE; + } + +exit: + return rc; +} + +#ifdef IPA_UC_OFFLOAD +void +ol_txrx_ipa_uc_get_resource( + ol_txrx_pdev_handle pdev, + u_int32_t *ce_sr_base_paddr, + u_int32_t *ce_sr_ring_size, + u_int32_t *ce_reg_paddr, + u_int32_t *tx_comp_ring_base_paddr, + u_int32_t *tx_comp_ring_size, + u_int32_t *tx_num_alloc_buffer, + u_int32_t *rx_rdy_ring_base_paddr, + u_int32_t *rx_rdy_ring_size, + u_int32_t *rx_proc_done_idx_paddr +) +{ + htt_ipa_uc_get_resource(pdev->htt_pdev, + ce_sr_base_paddr, + ce_sr_ring_size, + ce_reg_paddr, + tx_comp_ring_base_paddr, + tx_comp_ring_size, + tx_num_alloc_buffer, + rx_rdy_ring_base_paddr, + rx_rdy_ring_size, + rx_proc_done_idx_paddr); +} + +void +ol_txrx_ipa_uc_set_doorbell_paddr( + ol_txrx_pdev_handle pdev, + u_int32_t ipa_tx_uc_doorbell_paddr, + u_int32_t ipa_rx_uc_doorbell_paddr +) +{ + htt_ipa_uc_set_doorbell_paddr(pdev->htt_pdev, + ipa_tx_uc_doorbell_paddr, + ipa_rx_uc_doorbell_paddr); +} + +void +ol_txrx_ipa_uc_set_active( + ol_txrx_pdev_handle pdev, + a_bool_t uc_active, + a_bool_t is_tx +) +{ + htt_h2t_ipa_uc_set_active(pdev->htt_pdev, + uc_active, + is_tx); +} + +void +ol_txrx_ipa_uc_op_response( + ol_txrx_pdev_handle pdev, + u_int8_t *op_msg +) +{ + if (pdev->ipa_uc_op_cb) { + pdev->ipa_uc_op_cb(op_msg, pdev->osif_dev); + } +} + +void ol_txrx_ipa_uc_register_op_cb( + ol_txrx_pdev_handle pdev, + ipa_uc_op_cb_type op_cb, + void *osif_dev) +{ + pdev->ipa_uc_op_cb = op_cb; + pdev->osif_dev = osif_dev; +} + +void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev) +{ + htt_h2t_ipa_uc_get_stats(pdev->htt_pdev); +} + +#endif /* IPA_UC_OFFLOAD */ + +void ol_txrx_display_stats(struct ol_txrx_pdev_t *pdev, uint16_t value) +{ + + switch(value) + { + case WLAN_TXRX_STATS: + ol_txrx_stats_display(pdev); + break; +#ifdef CONFIG_HL_SUPPORT + case WLAN_SCHEDULER_STATS: + ol_tx_sched_cur_state_display(pdev); + ol_tx_sched_stats_display(pdev); + break; + case WLAN_TX_QUEUE_STATS: + ol_tx_queue_log_display(pdev); + break; +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL + case WLAN_CREDIT_STATS: + OL_TX_DUMP_GROUP_CREDIT_STATS(pdev); + break; +#endif + +#ifdef DEBUG_HL_LOGGING + case WLAN_BUNDLE_STATS: + htt_dump_bundle_stats(pdev->htt_pdev); + break; +#endif +#endif + default: + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%s: Unknown value",__func__); + break; + } +} + +void ol_txrx_clear_stats(struct ol_txrx_pdev_t *pdev, uint16_t value) +{ + + switch(value) + { + case WLAN_TXRX_STATS: + ol_txrx_stats_clear(pdev); + break; +#ifdef CONFIG_HL_SUPPORT + case WLAN_SCHEDULER_STATS: + ol_tx_sched_stats_clear(pdev); + break; + case WLAN_TX_QUEUE_STATS: + ol_tx_queue_log_clear(pdev); + break; +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL + case WLAN_CREDIT_STATS: + OL_TX_CLEAR_GROUP_CREDIT_STATS(pdev); + break; +#endif + case WLAN_BUNDLE_STATS: + htt_clear_bundle_stats(pdev->htt_pdev); + break; +#endif + default: + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "%s: Unknown value",__func__); + break; + } +} + diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.h new file mode 100644 index 000000000000..95cfd1689486 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_TXRX__H_ +#define _OL_TXRX__H_ + +#include /* adf_nbuf_t */ +#include /* ol_txrx_vdev_t, etc. */ +#include /* ol_pdev_handle */ + +void +ol_txrx_peer_unref_delete(struct ol_txrx_peer_t *peer); + +u_int16_t +ol_tx_desc_pool_size_hl(ol_pdev_handle ctrl_pdev); + + +#ifndef OL_TX_AVG_FRM_BYTES +#define OL_TX_AVG_FRM_BYTES 1000 +#endif + +#ifndef OL_TX_DESC_POOL_SIZE_MIN_HL +#define OL_TX_DESC_POOL_SIZE_MIN_HL 500 +#endif + +#ifndef OL_TX_DESC_POOL_SIZE_MAX_HL +#define OL_TX_DESC_POOL_SIZE_MAX_HL 5000 +#endif + +#ifdef CONFIG_PER_VDEV_TX_DESC_POOL +#define TXRX_HL_TX_FLOW_CTRL_VDEV_LOW_WATER_MARK 400 +#define TXRX_HL_TX_FLOW_CTRL_MGMT_RESERVED 100 +#endif + +#ifdef CONFIG_TX_DESC_HI_PRIO_RESERVE +#define TXRX_HL_TX_DESC_HI_PRIO_RESERVED 20 +#endif +#endif /* _OL_TXRX__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.c new file mode 100644 index 000000000000..f2d5ac2b6498 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_encap.c + * @brief Provide functions to encap/decap on txrx frames. + * @details + * This file contains functions for data frame encap/decap: + * ol_tx_encap: encap outgoing data frames. + * ol_rx_decap: decap incoming data frames. + */ +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + +#include /* adf_nbuf_t, etc. */ +#include /* ieee80211_frame */ +#include /* struct llc,struct struct ether_header, etc. */ +#include /* TXRX_ASSERT1 */ +#include /* struct ol_txrx_vdev_t,struct ol_txrx_pdev_t,etc. */ +#include /* struct ol_rx_decap_info_t*/ + +#define OL_TX_COPY_NATIVE_WIFI_HEADER(wh, msdu, hdsize, localbuf) \ + do { \ + wh = (struct ieee80211_frame*)adf_nbuf_data(msdu); \ + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { \ + hdsize = sizeof(struct ieee80211_frame_addr4); \ + } else { \ + hdsize = sizeof(struct ieee80211_frame); \ + } \ + if ( adf_nbuf_len(msdu) < hdsize) { \ + return A_ERROR; \ + } \ + adf_os_mem_copy(localbuf, wh, hdsize); \ + wh = (struct ieee80211_frame*)localbuf; \ + } while (0); + +static inline A_STATUS +ol_tx_copy_native_wifi_header( + adf_nbuf_t msdu, + u_int8_t *hdsize, + u_int8_t *localbuf) +{ + struct ieee80211_frame *wh = (struct ieee80211_frame*)adf_nbuf_data(msdu); + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { + *hdsize = sizeof(struct ieee80211_frame_addr4); + } else { + *hdsize = sizeof(struct ieee80211_frame); + } + if (adf_nbuf_len(msdu) < *hdsize) { + return A_ERROR; + } + adf_os_mem_copy(localbuf, wh, *hdsize); + return A_OK; +} + +static inline A_STATUS +ol_tx_encap_from_native_wifi ( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + struct ol_txrx_msdu_info_t *tx_msdu_info +) +{ + u_int8_t localbuf[sizeof(struct ieee80211_qosframe_htc_addr4)]; + struct ieee80211_frame *wh; + u_int8_t hdsize, new_hdsize; + struct ieee80211_qoscntl *qos_cntl; + struct ol_txrx_peer_t *peer; + + if (tx_msdu_info->htt.info.frame_type != htt_frm_type_data) { + return A_OK; + } + peer = tx_msdu_info->peer; + /* + * for unicast,the peer should not be NULL. + * for multicast, the peer is AP. + */ + if (tx_msdu_info->htt.info.is_unicast + && peer->qos_capable) + { + if (A_OK != ol_tx_copy_native_wifi_header(msdu, &hdsize, localbuf)) + return A_ERROR; + wh = (struct ieee80211_frame*)localbuf; + + /*add qos cntl*/ + qos_cntl = (struct ieee80211_qoscntl*)(localbuf + hdsize); + qos_cntl->i_qos[0] = tx_msdu_info->htt.info.ext_tid & IEEE80211_QOS_TID; + +#if 0 + if ( wmmParam[ac].wmep_noackPolicy ) { + qos_cntl->i_qos[0]|= 1 << IEEE80211_QOS_ACKPOLICY_S; + } +#endif + + qos_cntl->i_qos[1] = 0; + wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS; + /* count for qos field */ + new_hdsize = hdsize + sizeof(struct ieee80211_qosframe) - sizeof(struct ieee80211_frame); + + /*add ht control field if needed */ + + /* copy new hd to bd */ + adf_os_mem_copy( + (void*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, new_hdsize), + localbuf, + new_hdsize); + adf_nbuf_pull_head(msdu, hdsize); + tx_msdu_info->htt.info.l3_hdr_offset = new_hdsize; + tx_desc->orig_l2_hdr_bytes = hdsize; + } + /* Set Protected Frame bit in MAC header */ + if (vdev->pdev->sw_pf_proc_enable && tx_msdu_info->htt.action.do_encrypt) { + if (tx_desc->orig_l2_hdr_bytes) { + wh = (struct ieee80211_frame*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, + tx_msdu_info->htt.info.l3_hdr_offset); + } else { + if (A_OK != ol_tx_copy_native_wifi_header(msdu, &hdsize, localbuf)) + return A_ERROR; + wh = (struct ieee80211_frame*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, hdsize); + adf_os_mem_copy((void*)wh, localbuf, hdsize); + adf_nbuf_pull_head(msdu, hdsize); + tx_msdu_info->htt.info.l3_hdr_offset = hdsize; + tx_desc->orig_l2_hdr_bytes = hdsize; + } + wh->i_fc[1] |= IEEE80211_FC1_WEP; + } + return A_OK; +} + +static inline A_STATUS +ol_tx_encap_from_8023 ( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + struct ol_txrx_msdu_info_t *tx_msdu_info +) +{ + u_int8_t localbuf[ sizeof(struct ieee80211_qosframe_htc_addr4) \ + + sizeof(struct llc_snap_hdr_t)]; + struct llc_snap_hdr_t *llc_hdr; + struct ethernet_hdr_t *eth_hdr; + struct ieee80211_frame *wh; + u_int8_t hdsize, new_l2_hdsize, new_hdsize; + struct ieee80211_qoscntl *qos_cntl; + const u_int8_t ethernet_II_llc_snap_header_prefix[] = \ + { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + struct ol_txrx_peer_t *peer; + u_int16_t ether_type; + + if (tx_msdu_info->htt.info.frame_type != htt_frm_type_data) + return A_OK; + + /* + * for unicast,the peer should not be NULL. + * for multicast, the peer is AP. + */ + peer = tx_msdu_info->peer; + + eth_hdr = (struct ethernet_hdr_t *)adf_nbuf_data(msdu); + hdsize = sizeof(struct ethernet_hdr_t); + wh = (struct ieee80211_frame *)localbuf; + wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; + *(u_int16_t *)wh->i_dur = 0; + new_hdsize = 0; + + switch (vdev->opmode) { + case wlan_op_mode_ap: + /* DA , BSSID , SA*/ + adf_os_mem_copy(wh->i_addr1, eth_hdr->dest_addr, + IEEE80211_ADDR_LEN); + adf_os_mem_copy(wh->i_addr2, &vdev->mac_addr.raw, + IEEE80211_ADDR_LEN); + adf_os_mem_copy(wh->i_addr3, eth_hdr->src_addr, + IEEE80211_ADDR_LEN); + wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; + new_hdsize = sizeof(struct ieee80211_frame); + break; + case wlan_op_mode_ibss: + /* DA, SA, BSSID */ + adf_os_mem_copy(wh->i_addr1, eth_hdr->dest_addr, + IEEE80211_ADDR_LEN); + adf_os_mem_copy(wh->i_addr2, eth_hdr->src_addr, + IEEE80211_ADDR_LEN); + /* need to check the bssid behaviour for IBSS vdev */ + adf_os_mem_copy(wh->i_addr3, &vdev->mac_addr.raw, + IEEE80211_ADDR_LEN); + wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; + new_hdsize = sizeof(struct ieee80211_frame); + break; + case wlan_op_mode_sta: + /* BSSID, SA , DA*/ + adf_os_mem_copy(wh->i_addr1, &peer->mac_addr.raw, + IEEE80211_ADDR_LEN); + adf_os_mem_copy(wh->i_addr2, eth_hdr->src_addr, + IEEE80211_ADDR_LEN); + adf_os_mem_copy(wh->i_addr3, eth_hdr->dest_addr, + IEEE80211_ADDR_LEN); + wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; + new_hdsize = sizeof(struct ieee80211_frame); + break; + case wlan_op_mode_monitor: + default: + return A_ERROR; + } + /*add qos cntl*/ + if (tx_msdu_info->htt.info.is_unicast && peer->qos_capable ) { + qos_cntl = (struct ieee80211_qoscntl*)(localbuf + new_hdsize); + qos_cntl->i_qos[0] = tx_msdu_info->htt.info.ext_tid & IEEE80211_QOS_TID; + wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS; +#if 0 + if ( wmmParam[ac].wmep_noackPolicy ) { + qos_cntl->i_qos[0]|= 1 << IEEE80211_QOS_ACKPOLICY_S; + } +#endif + qos_cntl->i_qos[1] = 0; + new_hdsize += sizeof(struct ieee80211_qoscntl); + + /*add ht control field if needed */ + } + /* Set Protected Frame bit in MAC header */ + if (vdev->pdev->sw_pf_proc_enable && tx_msdu_info->htt.action.do_encrypt) { + wh->i_fc[1] |= IEEE80211_FC1_WEP; + } + new_l2_hdsize = new_hdsize; + /* add llc snap if needed */ + if (vdev->pdev->sw_tx_llc_proc_enable) { + llc_hdr = (struct llc_snap_hdr_t *) (localbuf + new_hdsize); + ether_type = (eth_hdr->ethertype[0]<<8) |(eth_hdr->ethertype[1]); + if ( ether_type >= IEEE8023_MAX_LEN ) { + adf_os_mem_copy(llc_hdr, + ethernet_II_llc_snap_header_prefix, + sizeof(ethernet_II_llc_snap_header_prefix)); + if ( ether_type == ETHERTYPE_AARP || ether_type == ETHERTYPE_IPX) { + llc_hdr->org_code[2] = BTEP_SNAP_ORGCODE_2;// 0xf8; bridge tunnel header + } + llc_hdr->ethertype[0] = eth_hdr->ethertype[0]; + llc_hdr->ethertype[1] = eth_hdr->ethertype[1]; + new_hdsize += sizeof(struct llc_snap_hdr_t); + } + else { + /*llc ready, and it's in payload pdu, do we need to move to BD pdu?*/ + } + } + adf_os_mem_copy( + (void*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc,new_l2_hdsize), + localbuf, + new_hdsize); + adf_nbuf_pull_head(msdu,hdsize); + tx_msdu_info->htt.info.l3_hdr_offset = new_l2_hdsize; + tx_desc->orig_l2_hdr_bytes = hdsize; + return A_OK; +} + +A_STATUS +ol_tx_encap( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + return ol_tx_encap_from_native_wifi(vdev, tx_desc, msdu,msdu_info); + } else if (pdev->frame_format == wlan_frm_fmt_802_3) { + return ol_tx_encap_from_8023(vdev, tx_desc, msdu, msdu_info); + } else { + /* todo for other types */ + return A_ERROR; + } +} + +static inline void +ol_rx_decap_to_native_wifi( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info, + struct ethernet_hdr_t *ethr_hdr) +{ + struct ieee80211_frame_addr4 *wh; + u_int16_t hdsize; + + /* + * we need to remove Qos control field and HT control. + * MSFT: http://msdn.microsoft.com/en-us/library/windows/hardware/ff552608(v=vs.85).aspx + */ + wh = (struct ieee80211_frame_addr4 *)info->hdr; + if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { + hdsize = sizeof(struct ieee80211_frame_addr4); + } + else { + hdsize = sizeof(struct ieee80211_frame); + } + wh = (struct ieee80211_frame_addr4 *) adf_nbuf_push_head(msdu, hdsize); + TXRX_ASSERT2(wh != NULL); + TXRX_ASSERT2(hdsize <= info->hdr_len); + adf_os_mem_copy ((u_int8_t *)wh, info->hdr, hdsize); + + /* amsdu subfrm handling if ethr_hdr is not NULL */ + if (ethr_hdr != NULL) { + switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + adf_os_mem_copy(wh->i_addr1, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); + adf_os_mem_copy(wh->i_addr2, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + adf_os_mem_copy(wh->i_addr2, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); + adf_os_mem_copy(wh->i_addr3, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + adf_os_mem_copy(wh->i_addr1, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); + adf_os_mem_copy(wh->i_addr3, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + adf_os_mem_copy(wh->i_addr3, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); + adf_os_mem_copy(wh->i_addr4, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); + break; + } + } + if (IEEE80211_QOS_HAS_SEQ(wh) ) { + if (wh->i_fc[1] & IEEE80211_FC1_ORDER) { + wh->i_fc[1] &= ~IEEE80211_FC1_ORDER; + } + wh->i_fc[0] &= ~IEEE80211_FC0_SUBTYPE_QOS; + } +} + +static inline void +ol_rx_decap_to_8023 ( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info, + struct ethernet_hdr_t *ethr_hdr) +{ + struct llc_snap_hdr_t *llc_hdr; + u_int16_t ether_type; + u_int16_t l2_hdr_space; + struct ieee80211_frame_addr4 *wh; + u_int8_t local_buf[ETHERNET_HDR_LEN]; + u_int8_t *buf; + + /* + * populate Ethernet header, + * if ethr_hdr is null, rx frame is 802.11 format(HW ft disabled) + * if ethr_hdr is not null, rx frame is "subfrm of amsdu". + */ + buf = (u_int8_t *)adf_nbuf_data(msdu); + llc_hdr = (struct llc_snap_hdr_t *)buf; + ether_type = (llc_hdr->ethertype[0] << 8)|llc_hdr->ethertype[1]; + /* do llc remove if needed */ + l2_hdr_space = 0; + if (IS_SNAP(llc_hdr)) { + if (IS_BTEP(llc_hdr)) { + /* remove llc*/ + l2_hdr_space += sizeof(struct llc_snap_hdr_t); + llc_hdr = NULL; + } + else if (IS_RFC1042(llc_hdr)) { + if ( !(ether_type == ETHERTYPE_AARP || + ether_type == ETHERTYPE_IPX) ) { + /* remove llc*/ + l2_hdr_space += sizeof(struct llc_snap_hdr_t); + llc_hdr = NULL; + } + } + } + if (l2_hdr_space > ETHERNET_HDR_LEN) { + buf = adf_nbuf_pull_head(msdu, l2_hdr_space - ETHERNET_HDR_LEN); + } + else if (l2_hdr_space < ETHERNET_HDR_LEN) { + buf = adf_nbuf_push_head(msdu, ETHERNET_HDR_LEN - l2_hdr_space); + } + + /* normal msdu(non-subfrm of A-MSDU) if ethr_hdr is null */ + if (ethr_hdr == NULL) { + /* mpdu hdr should be present in info,re-create ethr_hdr based on mpdu hdr*/ + TXRX_ASSERT2(info->hdr_len != 0); + wh = (struct ieee80211_frame_addr4 *)info->hdr; + ethr_hdr = (struct ethernet_hdr_t *)local_buf; + switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr2, ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr2, ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr3, ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr4, ETHERNET_ADDR_LEN); + break; + } + } + if (llc_hdr == NULL) { + ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; + ethr_hdr->ethertype[1] = (ether_type) & 0xff; + } + else { + u_int32_t pktlen = adf_nbuf_len(msdu) - sizeof(ethr_hdr->ethertype); + TXRX_ASSERT2(pktlen <= ETHERNET_MTU); + ether_type = (u_int16_t)pktlen; + ether_type = adf_nbuf_len(msdu) - sizeof(struct ethernet_hdr_t); + ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; + ethr_hdr->ethertype[1] = (ether_type) & 0xff; + } + adf_os_mem_copy(buf, ethr_hdr, ETHERNET_HDR_LEN); +} + +static inline A_STATUS +ol_rx_decap_subfrm_amsdu( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + u_int8_t * subfrm_hdr; + u_int8_t localbuf[ETHERNET_HDR_LEN]; + struct ethernet_hdr_t *ether_hdr = (struct ethernet_hdr_t*)localbuf; + + subfrm_hdr = (u_int8_t *)adf_nbuf_data(msdu); + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + /* decap to native wifi */ + adf_os_mem_copy(ether_hdr, + subfrm_hdr, + ETHERNET_HDR_LEN); + adf_nbuf_pull_head(msdu, ETHERNET_HDR_LEN); + ol_rx_decap_to_native_wifi(vdev, + msdu, + info, + ether_hdr); + } + else if (pdev->frame_format == wlan_frm_fmt_802_3) { + if (pdev->sw_rx_llc_proc_enable) { + /* remove llc snap hdr if it's necessary according to + * 802.11 table P-3 + */ + adf_os_mem_copy(ether_hdr, + subfrm_hdr, + ETHERNET_HDR_LEN); + adf_nbuf_pull_head(msdu, ETHERNET_HDR_LEN); + ol_rx_decap_to_8023(vdev, + msdu, + info, + ether_hdr); + } + else { + /* subfrm of A-MSDU is already in 802.3 format. + * if target HW or FW has done LLC rmv process, + * we do nothing here. + */ + } + } + else { + /* todo for othertype*/ + } + return A_OK; + +} + +static inline A_STATUS +ol_rx_decap_msdu( + struct ol_txrx_vdev_t *vdev, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + struct ieee80211_frame *wh; + wh = (struct ieee80211_frame *)adf_nbuf_data(msdu); + + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + /* Decap to native wifi because according to MSFT( + * MSFT: http://msdn.microsoft.com/en-us/library/windows/hardware/ff552608(v=vs.85).aspx), + * we need to remove Qos and HTC field before indicate to OS. + */ + if (IEEE80211_QOS_HAS_SEQ(wh) ) { + info->hdr_len = ol_txrx_ieee80211_hdrsize(wh); + TXRX_ASSERT2(info->hdr_len <= sizeof(info->hdr)); + adf_os_mem_copy(info->hdr, /* use info->hdr as temp buf.*/ + wh, + info->hdr_len); + adf_nbuf_pull_head(msdu, info->hdr_len); + ol_rx_decap_to_native_wifi(vdev, + msdu, + info, /* 802.11 hdr*/ + NULL); /* ethernet hdr*/ + } + } + else if (pdev->frame_format == wlan_frm_fmt_802_3) { + if (pdev->sw_rx_llc_proc_enable) { + info->hdr_len = ol_txrx_ieee80211_hdrsize(wh); + TXRX_ASSERT2(info->hdr_len <= sizeof(info->hdr)); + adf_os_mem_copy(info->hdr, /* use info->hdr as temp buf.*/ + wh, + info->hdr_len); + adf_nbuf_pull_head(msdu, info->hdr_len); + /* remove llc snap hdr if it's necessary according to + * 802.11 table P-3 + */ + ol_rx_decap_to_8023(vdev, + msdu, + info, /* 802.11 hdr*/ + NULL); /* ethernet hdr*/ + } + else { + /* Subfrm of A-MSDU is already in 802.3 format. + * And if target HW or FW has done LLC rmv process ( + * sw_rx_lc_proc_enable == 0), we do nothing here. + */ + } + } + else { + /* todo for othertype*/ + } + return A_OK; + +} + +A_STATUS +ol_rx_decap( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info) +{ + A_STATUS status; + u_int8_t *mpdu_hdr; + + if (!info->is_subfrm) { + if (info->is_msdu_cmpl_mpdu && !info->is_first_subfrm) { + /* It's normal MSDU. */ + } else { + /* It's a first subfrm of A-MSDU and may also be the last subfrm of A-MSDU */ + info->is_subfrm = 1; + info->hdr_len = 0; + if (vdev->pdev->sw_subfrm_hdr_recovery_enable) { + /* we save the first subfrm mpdu hdr for subsequent + * subfrm 802.11 header recovery in certain chip(such as Riva). + */ + mpdu_hdr = adf_nbuf_data(msdu); + info->hdr_len = ol_txrx_ieee80211_hdrsize(mpdu_hdr); + TXRX_ASSERT2(info->hdr_len <= sizeof(info->hdr)); + adf_os_mem_copy(info->hdr, mpdu_hdr, info->hdr_len); + adf_nbuf_pull_head(msdu, info->hdr_len); + } + } + } + + if (info->is_subfrm && vdev->pdev->sw_subfrm_hdr_recovery_enable) { + /* + * This case is enabled for some HWs(such as Riva).The HW de-aggregate + * doesn't have capability to generate 802.11 header for non-first subframe + * of A-MSDU.That means sw needs to cache the first subfrm mpdu header + * to generate the subsequent subfrm's 802.11 header. + */ + TXRX_ASSERT2(info->hdr_len != 0); + status = ol_rx_decap_subfrm_amsdu(vdev, msdu, info); + } else { + status = ol_rx_decap_msdu(vdev, msdu, info); + } + + if (info->is_msdu_cmpl_mpdu) { + info->is_subfrm = + info->is_first_subfrm = + info->hdr_len = 0; + } + return status; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.h new file mode 100644 index 000000000000..9d7590e329ef --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_encap.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_encap.h + * @brief definitions for txrx encap/decap function and struct + */ +#ifndef _OL_TXRX_ENCAP__H_ +#define _OL_TXRX_ENCAP__H_ + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + +#include /* adf_nbuf_t */ +#include /* ieee80211_qosframe_htc_addr4 */ +#include /* ol_tx_desc_t, ol_txrx_msdu_info_t */ + +/** + * @brief Encap outgoing frm from OS dependent format to Target + * acceptable frm format + * @details + * For native wifi format, the function will add Qos control field + * based on peer's QOS capbabilities . + * For 802.3 format, the function will transform to 802.11 format + * with or without QOS control field based on peer's QOS capabilites. + * @param vdev - handle to vdev object + * @param tx_desc - tx desc struct,some fields will be updated. + * @param msdu - adf_nbuf_t + * @param msdu_info - informations from tx classification. + * @return + * A_OK: encap operation sucessful + * other: operation failed,the msdu need be dropped. + */ +A_STATUS +ol_tx_encap( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + struct ol_txrx_msdu_info_t *msdu_info); + + +struct ol_rx_decap_info_t { + u_int8_t hdr[sizeof(struct ieee80211_qosframe_htc_addr4)]; + int hdr_len; + u_int8_t is_subfrm : 1, + is_first_subfrm :1, + is_msdu_cmpl_mpdu : 1; +}; + +/** + * @brief decap incoming frm from Target to Host OS + * acceptable frm format + * @details + * For native wifi format, the function will remove Qos control field + * and HT control field if any. + * For 802.3 format, the function will will do llc snap header process + * if Target haven't done that. + * @param vdev - handle to vdev object + * @param peer - the peer object. + * @param msdu - adf_nbuf_t + * @param info - ol_rx_decap_info_t: context info for decap + * @return + * A_OK: decap operation sucessful + * other: operation failed,the msdu need be dropped. + */ +A_STATUS +ol_rx_decap ( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info); + + +static inline A_STATUS +OL_TX_ENCAP( + struct ol_txrx_vdev_t *vdev, + struct ol_tx_desc_t *tx_desc, + adf_nbuf_t msdu, + struct ol_txrx_msdu_info_t *msdu_info) +{ + if (vdev->pdev->sw_tx_encap) { + return ol_tx_encap(vdev, tx_desc, msdu,msdu_info); + } + return A_OK; +} + +static inline A_STATUS +OL_RX_DECAP( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + adf_nbuf_t msdu, + struct ol_rx_decap_info_t *info) +{ + if (vdev->pdev->sw_rx_decap) { + return ol_rx_decap(vdev, peer, msdu, info); + } + return A_OK; +} + +#define OL_TX_RESTORE_HDR(__tx_desc,__msdu) \ + if(__tx_desc->orig_l2_hdr_bytes != 0) { \ + adf_nbuf_push_head(__msdu, __tx_desc->orig_l2_hdr_bytes); \ + } +#else +#define OL_TX_ENCAP(vdev, tx_desc, msdu, msdu_info) A_OK +#define OL_RX_DECAP(vdev, peer, msdu, info) A_OK +#define OL_TX_RESTORE_HDR(__tx_desc,__msdu) +#endif +#endif /* _OL_TXRX_ENCAP__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_event.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_event.c new file mode 100644 index 000000000000..e144ce09a2b2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_event.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "ol_txrx_types.h" + +#ifdef WDI_EVENT_ENABLE + +static inline wdi_event_subscribe * +wdi_event_next_sub(wdi_event_subscribe *wdi_sub) +{ + if (!wdi_sub) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid subscriber in %s\n", __FUNCTION__); + return NULL; + } + return wdi_sub->priv.next; +} + +static inline void +wdi_event_del_subs(wdi_event_subscribe *wdi_sub, int event_index) +{ + wdi_event_notify deallocate_sub; + while (wdi_sub) { + wdi_event_subscribe *next = wdi_event_next_sub(wdi_sub); + /* + * Context is NULL for static allocation of subs + * In dynamic allocation case notify the user + */ + if (wdi_sub->context) { + deallocate_sub = wdi_sub->context; + deallocate_sub( + WDI_EVENT_SUB_DEALLOCATE, WDI_EVENT_BASE + event_index); + } + wdi_sub = next; + } + //adf_os_mem_free(wdi_sub); +} + +static inline void +wdi_event_iter_sub( + struct ol_txrx_pdev_t *pdev, + uint32_t event_index, + wdi_event_subscribe *wdi_sub, + void *data) +{ + enum WDI_EVENT event = event_index + WDI_EVENT_BASE; + + if (wdi_sub) { + do { + wdi_sub->callback(pdev, event, data); + } while ((wdi_sub = wdi_event_next_sub(wdi_sub))); + } +} + +void +wdi_event_handler( + enum WDI_EVENT event, + struct ol_txrx_pdev_t *txrx_pdev, + void *data) +{ + uint32_t event_index; + wdi_event_subscribe *wdi_sub; + /* + * Input validation + */ + if (!event) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid WDI event in %s\n", __FUNCTION__); + return; + } + if (!txrx_pdev) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid pdev in WDI event handler\n"); + return; + } + /* + * There can be NULL data, so no validation for the data + * Subscribers must do the sanity based on the requirements + */ + event_index = event - WDI_EVENT_BASE; + + wdi_sub = txrx_pdev->wdi_event_list[event_index]; + + /* Find the subscriber */ + wdi_event_iter_sub(txrx_pdev, event_index, wdi_sub, data); +} + +A_STATUS +wdi_event_sub( + struct ol_txrx_pdev_t *txrx_pdev, + wdi_event_subscribe *event_cb_sub, + enum WDI_EVENT event) +{ + uint32_t event_index; + wdi_event_subscribe *wdi_sub; + /* Input validation */ + if (!txrx_pdev) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid txrx_pdev in %s", __FUNCTION__); + return A_ERROR; + } + if (!event_cb_sub) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid callback in %s", __FUNCTION__); + return A_ERROR; + } + if ((!event) || (event >= WDI_EVENT_LAST) || (event < WDI_EVENT_BASE)) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid event in %s", __FUNCTION__); + return A_ERROR; + } /* Input validation */ + + event_index = event - WDI_EVENT_BASE; + + wdi_sub = txrx_pdev->wdi_event_list[event_index]; + /* + * Check if it is the first subscriber of the event + */ + if (!wdi_sub) { + wdi_sub = event_cb_sub; + wdi_sub->priv.next = NULL; + wdi_sub->priv.prev = NULL; + txrx_pdev->wdi_event_list[event_index] = wdi_sub; + return A_OK; + } + event_cb_sub->priv.next = wdi_sub; + event_cb_sub->priv.prev = NULL; + wdi_sub->priv.prev = event_cb_sub; + txrx_pdev->wdi_event_list[event_index] = event_cb_sub; + + return A_OK; +} + +A_STATUS +wdi_event_unsub( + struct ol_txrx_pdev_t *txrx_pdev, + wdi_event_subscribe *event_cb_sub, + enum WDI_EVENT event) +{ + uint32_t event_index = event - WDI_EVENT_BASE; + + /* Input validation */ + if (!event_cb_sub) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid callback in %s", __FUNCTION__); + return A_ERROR; + } + if (!event_cb_sub->priv.prev) { + txrx_pdev->wdi_event_list[event_index] = event_cb_sub->priv.next; + } else { + event_cb_sub->priv.prev->priv.next = event_cb_sub->priv.next; + } + if (event_cb_sub->priv.next) { + event_cb_sub->priv.next->priv.prev = event_cb_sub->priv.prev; + } + //adf_os_mem_free(event_cb_sub); + + return A_OK; +} + +A_STATUS +wdi_event_attach(struct ol_txrx_pdev_t *txrx_pdev) +{ + /* Input validation */ + if (!txrx_pdev) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid device in %s\nWDI event attach failed", __FUNCTION__); + return A_ERROR; + } + /* Separate subscriber list for each event */ + txrx_pdev->wdi_event_list = (wdi_event_subscribe **) + adf_os_mem_alloc( + txrx_pdev->osdev, sizeof(wdi_event_subscribe *) * WDI_NUM_EVENTS); + if (!txrx_pdev->wdi_event_list) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Insufficient memory for the WDI event lists\n"); + return A_NO_MEMORY; + } + return A_OK; +} + +A_STATUS +wdi_event_detach(struct ol_txrx_pdev_t *txrx_pdev) +{ + int i; + wdi_event_subscribe *wdi_sub; + if (!txrx_pdev) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Invalid device in %s\nWDI attach failed", __FUNCTION__); + return A_ERROR; + } + if (!txrx_pdev->wdi_event_list) { + return A_ERROR; + } + for (i = 0; i < WDI_NUM_EVENTS; i++) { + wdi_sub = txrx_pdev->wdi_event_list[i]; + if (wdi_sub) { + /* Delete all the subscribers */ + wdi_event_del_subs(wdi_sub, i); + } + } + /* txrx_pdev->wdi_event_list would be non-null */ + adf_os_mem_free(txrx_pdev->wdi_event_list); + return A_OK; +} + +#endif /* WDI_EVENT_ENABLE */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_internal.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_internal.h new file mode 100644 index 000000000000..f09db5ce9901 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_internal.h @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_TXRX_INTERNAL__H_ +#define _OL_TXRX_INTERNAL__H_ + +#include /* adf_os_assert */ +#include /* adf_nbuf_t */ +#include /* adf_os_mem_set */ +#include /* ieee80211_frame */ +#include /* htt_rx_msdu_desc_completes_mpdu, etc. */ + +#include + +#include +#include /* ETHERNET_HDR_LEN, etc. */ +#include /* IPV4_HDR_LEN, etc. */ +#include /* IPV6_HDR_LEN, etc. */ +#include /* IP_PROTOCOL_TCP, etc. */ + +#ifdef ATH_11AC_TXCOMPACT +#define OL_TX_DESC_NO_REFS(tx_desc) 1 +#define OL_TX_DESC_REF_INIT(tx_desc) /* no-op */ +#define OL_TX_DESC_REF_INC(tx_desc) /* no-op */ +#else +#define OL_TX_DESC_NO_REFS(tx_desc) \ + adf_os_atomic_dec_and_test(&tx_desc->ref_cnt) +#define OL_TX_DESC_REF_INIT(tx_desc) adf_os_atomic_init(&tx_desc->ref_cnt) +#define OL_TX_DESC_REF_INC(tx_desc) adf_os_atomic_inc(&tx_desc->ref_cnt) +#endif + +#ifndef ARRAY_LEN +#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) +#endif + + +#ifndef TXRX_ASSERT_LEVEL +#define TXRX_ASSERT_LEVEL 3 +#endif + +#ifdef __KLOCWORK__ +# define TXRX_ASSERT1(x) do { if (!(x)) abort(); } while (0) +# define TXRX_ASSERT2(x) do { if (!(x)) abort(); } while (0) +#else // #ifdef __KLOCWORK__ + +#if TXRX_ASSERT_LEVEL > 0 +#define TXRX_ASSERT1(condition) adf_os_assert((condition)) +#else +#define TXRX_ASSERT1(condition) +#endif + +#if TXRX_ASSERT_LEVEL > 1 +#define TXRX_ASSERT2(condition) adf_os_assert((condition)) +#else +#define TXRX_ASSERT2(condition) +#endif +#endif // #ifdef __KLOCWORK__ +enum { + /* FATAL_ERR - print only irrecoverable error messages */ + TXRX_PRINT_LEVEL_FATAL_ERR, + + /* ERR - include non-fatal err messages */ + TXRX_PRINT_LEVEL_ERR, + + /* WARN - include warnings */ + TXRX_PRINT_LEVEL_WARN, + + /* INFO1 - include fundamental, infrequent events */ + TXRX_PRINT_LEVEL_INFO1, + + /* INFO2 - include non-fundamental but infrequent events */ + TXRX_PRINT_LEVEL_INFO2, + + /* INFO3 - include frequent events */ + /* to avoid performance impact, don't use INFO3 unless explicitly enabled */ + #ifdef TXRX_PRINT_VERBOSE_ENABLE + TXRX_PRINT_LEVEL_INFO3, + #endif /* TXRX_PRINT_VERBOSE_ENABLE */ +}; + +extern unsigned g_txrx_print_level; + +#ifdef TXRX_PRINT_ENABLE + +#include /* va_list */ +#include /* adf_os_vprint */ + +/* Supress 4296 - expression is always true + * It will fire if level is TXRX_PRINT_LEVEL_FATAL_ERR (0) + * because g_txrx_print_level is unsigned */ +#define ol_txrx_print(level, fmt, ...) \ + if (level <= g_txrx_print_level) adf_os_print(fmt, ## __VA_ARGS__) +#define TXRX_PRINT(level, fmt, ...) \ + ol_txrx_print(level, "TXRX: " fmt, ## __VA_ARGS__) + +#ifdef TXRX_PRINT_VERBOSE_ENABLE + +#define ol_txrx_print_verbose(fmt, ...) \ + if (TXRX_PRINT_LEVEL_INFO3 <= g_txrx_print_level) \ + adf_os_print(fmt, ## __VA_ARGS__) +#define TXRX_PRINT_VERBOSE(fmt, ...) \ + ol_txrx_print_verbose("TXRX: " fmt, ## __VA_ARGS__) +#else +#define TXRX_PRINT_VERBOSE(fmt, ...) +#endif /* TXRX_PRINT_VERBOSE_ENABLE */ + +/* define PN check failure message print rate + as 1 second */ +#define TXRX_PN_CHECK_FAILURE_PRINT_PERIOD_MS 1000 + +#else +#define TXRX_PRINT(level, fmt, ...) +#define TXRX_PRINT_VERBOSE(fmt, ...) +#endif /* TXRX_PRINT_ENABLE */ + +/*--- tx credit debug printouts ---*/ + +#ifndef DEBUG_CREDIT +#define DEBUG_CREDIT 0 +#endif + +#if DEBUG_CREDIT +#define TX_CREDIT_DEBUG_PRINT(fmt, ...) adf_os_print(fmt, ## __VA_ARGS__) +#else +#define TX_CREDIT_DEBUG_PRINT(fmt, ...) +#endif + +/*--- tx scheduler debug printouts ---*/ + +#ifdef HOST_TX_SCHED_DEBUG +#define TX_SCHED_DEBUG_PRINT(fmt, ...) adf_os_print(fmt, ## __VA_ARGS__) +#else +#define TX_SCHED_DEBUG_PRINT(fmt, ...) +#endif +#define TX_SCHED_DEBUG_PRINT_ALWAYS(fmt, ...) adf_os_print(fmt, ## __VA_ARGS__) + +#define OL_TXRX_LIST_APPEND(head, tail, elem) \ +do { \ + if (!(head)) { \ + (head) = (elem); \ + } else { \ + adf_nbuf_set_next((tail), (elem)); \ + } \ + (tail) = (elem); \ +} while (0) + +static inline void +ol_rx_mpdu_list_next( + struct ol_txrx_pdev_t *pdev, + void *mpdu_list, + adf_nbuf_t *mpdu_tail, + adf_nbuf_t *next_mpdu) +{ + htt_pdev_handle htt_pdev = pdev->htt_pdev; + adf_nbuf_t msdu; + + /* + * For now, we use a simply flat list of MSDUs. + * So, traverse the list until we reach the last MSDU within the MPDU. + */ + TXRX_ASSERT2(mpdu_list); + msdu = mpdu_list; + while (!htt_rx_msdu_desc_completes_mpdu( + htt_pdev, htt_rx_msdu_desc_retrieve(htt_pdev, msdu))) + { + msdu = adf_nbuf_next(msdu); + TXRX_ASSERT2(msdu); + } + /* msdu now points to the last MSDU within the first MPDU */ + *mpdu_tail = msdu; + *next_mpdu = adf_nbuf_next(msdu); +} + + +/*--- txrx stats macros ---*/ + + +/* unconditional defs */ +#define TXRX_STATS_INCR(pdev, field) TXRX_STATS_ADD(pdev, field, 1) + +/* default conditional defs (may be undefed below) */ + +#define TXRX_STATS_INIT(_pdev) \ + adf_os_mem_set(&((_pdev)->stats), 0x0, sizeof((_pdev)->stats)) +#define TXRX_STATS_ADD(_pdev, _field, _delta) \ + _pdev->stats._field += _delta +#define TXRX_STATS_MSDU_INCR(pdev, field, netbuf) \ + do { \ + TXRX_STATS_INCR((pdev), pub.field.pkts); \ + TXRX_STATS_ADD((pdev), pub.field.bytes, adf_nbuf_len(netbuf)); \ + } while (0) + +/* conditional defs based on verbosity level */ + +#if /*---*/ TXRX_STATS_LEVEL == TXRX_STATS_LEVEL_FULL + +#define TXRX_STATS_MSDU_LIST_INCR(pdev, field, netbuf_list) \ + do { \ + adf_nbuf_t tmp_list = netbuf_list; \ + while (tmp_list) { \ + TXRX_STATS_MSDU_INCR(pdev, field, tmp_list); \ + tmp_list = adf_nbuf_next(tmp_list); \ + } \ + } while (0) + +#define TXRX_STATS_MSDU_INCR_TX_STATUS(status, pdev, netbuf) \ + switch (status) { \ + case htt_tx_status_ok: \ + TXRX_STATS_MSDU_INCR(pdev, tx.delivered, netbuf); \ + break; \ + case htt_tx_status_discard: \ + TXRX_STATS_MSDU_INCR(pdev, tx.dropped.target_discard, netbuf); \ + break; \ + case htt_tx_status_no_ack: \ + TXRX_STATS_MSDU_INCR(pdev, tx.dropped.no_ack, netbuf); \ + break; \ + case htt_tx_status_download_fail: \ + TXRX_STATS_MSDU_INCR(pdev, tx.dropped.download_fail, netbuf); \ + break; \ + default: \ + break; \ + } + +#define TXRX_STATS_UPDATE_TX_COMP_HISTOGRAM(_pdev, _p_cntrs) \ +do { \ + if (_p_cntrs > 60) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_61_plus,1); \ + else if (_p_cntrs > 50) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_51_60,1); \ + else if (_p_cntrs > 40) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_41_50,1); \ + else if (_p_cntrs > 30) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_31_40,1); \ + else if (_p_cntrs > 20) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_21_30,1); \ + else if (_p_cntrs > 10) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_11_20,1); \ + else if (_p_cntrs > 2) \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_2_10,1); \ + else \ + TXRX_STATS_ADD(_pdev,pub.tx.comp_histogram.pkts_1,1); \ + \ +} while (0) + + +#define TXRX_STATS_UPDATE_TX_STATS(_pdev, _status, _p_cntrs, _b_cntrs) \ +do { \ + switch (status) { \ + case htt_tx_status_ok: \ + TXRX_STATS_ADD(_pdev, pub.tx.delivered.pkts, _p_cntrs); \ + TXRX_STATS_ADD(_pdev, pub.tx.delivered.bytes, _b_cntrs); \ + break; \ + case htt_tx_status_discard: \ + TXRX_STATS_ADD(_pdev, pub.tx.dropped.target_discard.pkts, _p_cntrs); \ + TXRX_STATS_ADD(_pdev, pub.tx.dropped.target_discard.bytes, _b_cntrs); \ + break; \ + case htt_tx_status_no_ack: \ + TXRX_STATS_ADD(_pdev, pub.tx.dropped.no_ack.pkts, _p_cntrs); \ + TXRX_STATS_ADD(_pdev, pub.tx.dropped.no_ack.bytes, _b_cntrs); \ + break; \ + case htt_tx_status_download_fail: \ + TXRX_STATS_ADD(_pdev, pub.tx.dropped.download_fail.pkts, _p_cntrs); \ + TXRX_STATS_ADD(_pdev, pub.tx.dropped.download_fail.bytes, _b_cntrs); \ + break; \ + default: \ + break; \ + } \ + TXRX_STATS_UPDATE_TX_COMP_HISTOGRAM(_pdev, _p_cntrs); \ +} while (0) + +#elif /*---*/ TXRX_STATS_LEVEL == TXRX_STATS_LEVEL_BASIC + +#define TXRX_STATS_MSDU_LIST_INCR(pdev, field, netbuf_list) \ + do { \ + adf_nbuf_t tmp_list = netbuf_list; \ + while (tmp_list) { \ + TXRX_STATS_MSDU_INCR(pdev, field, tmp_list); \ + tmp_list = adf_nbuf_next(tmp_list); \ + } \ + } while (0) + +#define TXRX_STATS_MSDU_INCR_TX_STATUS(status, pdev, netbuf) \ + do { \ + if (status == htt_tx_status_ok) { \ + TXRX_STATS_MSDU_INCR(pdev, tx.delivered, netbuf); \ + } \ + } while (0) + +#define TXRX_STATS_INIT(_pdev) \ + adf_os_mem_set(&((_pdev)->stats), 0x0, sizeof((_pdev)->stats)) + +#define TXRX_STATS_UPDATE_TX_STATS(_pdev, _status, _p_cntrs, _b_cntrs) \ +do { \ + if (adf_os_likely(_status == htt_tx_status_ok)) { \ + TXRX_STATS_ADD(_pdev, pub.tx.delivered.pkts, _p_cntrs); \ + TXRX_STATS_ADD(_pdev, pub.tx.delivered.bytes, _b_cntrs); \ + } \ +} while (0) + +#else /*---*/ /* stats off */ + +#undef TXRX_STATS_INIT +#define TXRX_STATS_INIT(_pdev) + +#undef TXRX_STATS_ADD +#define TXRX_STATS_ADD(_pdev, _field, _delta) + +#undef TXRX_STATS_MSDU_INCR +#define TXRX_STATS_MSDU_INCR(pdev, field, netbuf) + +#define TXRX_STATS_MSDU_LIST_INCR(pdev, field, netbuf_list) + +#define TXRX_STATS_MSDU_INCR_TX_STATUS(status, pdev, netbuf) + +#define TXRX_STATS_UPDATE_TX_STATS(_pdev, _status, _p_cntrs, _b_cntrs) + +#endif /*---*/ /* TXRX_STATS_LEVEL */ + + +/*--- txrx sequence number trace macros ---*/ + + +#define TXRX_SEQ_NUM_ERR(_status) (0xffff - _status) + +#if defined(ENABLE_RX_REORDER_TRACE) + +A_STATUS ol_rx_reorder_trace_attach(ol_txrx_pdev_handle pdev); +void ol_rx_reorder_trace_detach(ol_txrx_pdev_handle pdev); +void ol_rx_reorder_trace_add( + ol_txrx_pdev_handle pdev, + u_int8_t tid, + u_int16_t reorder_idx, + u_int16_t seq_num, + int num_mpdus); + +#define OL_RX_REORDER_TRACE_ATTACH ol_rx_reorder_trace_attach +#define OL_RX_REORDER_TRACE_DETACH ol_rx_reorder_trace_detach +#define OL_RX_REORDER_TRACE_ADD ol_rx_reorder_trace_add + +#else + +#define OL_RX_REORDER_TRACE_ATTACH(_pdev) A_OK +#define OL_RX_REORDER_TRACE_DETACH(_pdev) +#define OL_RX_REORDER_TRACE_ADD(pdev, tid, reorder_idx, seq_num, num_mpdus) + +#endif /* ENABLE_RX_REORDER_TRACE */ + + +/*--- txrx packet number trace macros ---*/ + + +#if defined(ENABLE_RX_PN_TRACE) + +A_STATUS ol_rx_pn_trace_attach(ol_txrx_pdev_handle pdev); +void ol_rx_pn_trace_detach(ol_txrx_pdev_handle pdev); +void ol_rx_pn_trace_add( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer, + u_int16_t tid, + void *rx_desc); + +#define OL_RX_PN_TRACE_ATTACH ol_rx_pn_trace_attach +#define OL_RX_PN_TRACE_DETACH ol_rx_pn_trace_detach +#define OL_RX_PN_TRACE_ADD ol_rx_pn_trace_add + +#else + +#define OL_RX_PN_TRACE_ATTACH(_pdev) A_OK +#define OL_RX_PN_TRACE_DETACH(_pdev) +#define OL_RX_PN_TRACE_ADD(pdev, peer, tid, rx_desc) + +#endif /* ENABLE_RX_PN_TRACE */ + +static inline int +ol_txrx_ieee80211_hdrsize(const void *data) +{ + const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data; + int size = sizeof(struct ieee80211_frame); + + /* NB: we don't handle control frames */ + TXRX_ASSERT1( + (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL); + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { + size += IEEE80211_ADDR_LEN; + } + if (IEEE80211_QOS_HAS_SEQ(wh)) { + size += sizeof(u_int16_t); + /* Qos frame with Order bit set indicates an HTC frame */ + if (wh->i_fc[1] & IEEE80211_FC1_ORDER) { + size += sizeof(struct ieee80211_htc); + } + } + return size; +} + +/*--- frame display utility ---*/ + +enum ol_txrx_frm_dump_options { + ol_txrx_frm_dump_contents = 0x1, + ol_txrx_frm_dump_tcp_seq = 0x2, +}; + +#ifdef TXRX_DEBUG_DATA +static inline void +OL_TXRX_FRMS_DUMP( + const char *name, + struct ol_txrx_pdev_t *pdev, + adf_nbuf_t frm, + enum ol_txrx_frm_dump_options display_options, + int max_len) +{ + #define TXRX_FRM_DUMP_MAX_LEN 128 + u_int8_t local_buf[TXRX_FRM_DUMP_MAX_LEN] = {0}; + u_int8_t *p; + + if (name) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, "%s\n", name); + } + while (frm) { + p = adf_nbuf_data(frm); + if (display_options & ol_txrx_frm_dump_tcp_seq) { + int tcp_offset; + int l2_hdr_size; + u_int16_t ethertype; + u_int8_t ip_prot; + + if (pdev->frame_format == wlan_frm_fmt_802_3) { + struct ethernet_hdr_t *enet_hdr = (struct ethernet_hdr_t *) p; + l2_hdr_size = ETHERNET_HDR_LEN; + + /* + * LLC/SNAP present? + */ + ethertype = + (enet_hdr->ethertype[0] << 8) | enet_hdr->ethertype[1]; + if (!IS_ETHERTYPE(ethertype)) { + /* 802.3 format */ + struct llc_snap_hdr_t *llc_hdr; + + llc_hdr = (struct llc_snap_hdr_t *) (p + l2_hdr_size); + l2_hdr_size += LLC_SNAP_HDR_LEN; + ethertype = + (llc_hdr->ethertype[0] << 8) | llc_hdr->ethertype[1]; + } + } else { + struct llc_snap_hdr_t *llc_hdr; + /* (generic?) 802.11 */ + l2_hdr_size = sizeof(struct ieee80211_frame); + llc_hdr = (struct llc_snap_hdr_t *) (p + l2_hdr_size); + l2_hdr_size += LLC_SNAP_HDR_LEN; + ethertype = + (llc_hdr->ethertype[0] << 8) | llc_hdr->ethertype[1]; + } + if (ethertype == ETHERTYPE_IPV4) { + struct ipv4_hdr_t *ipv4_hdr; + ipv4_hdr = (struct ipv4_hdr_t *) (p + l2_hdr_size); + ip_prot = ipv4_hdr->protocol; + tcp_offset = l2_hdr_size + IPV4_HDR_LEN; + } else if (ethertype == ETHERTYPE_IPV6) { + struct ipv6_hdr_t *ipv6_hdr; + ipv6_hdr = (struct ipv6_hdr_t *) (p + l2_hdr_size); + ip_prot = ipv6_hdr->next_hdr; + tcp_offset = l2_hdr_size + IPV6_HDR_LEN; + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "frame %p non-IP ethertype (%x)\n", frm, ethertype); + goto NOT_IP_TCP; + } + if (ip_prot == IP_PROTOCOL_TCP) { +#if 0 + struct tcp_hdr_t *tcp_hdr; + u_int32_t tcp_seq_num; + tcp_hdr = (struct tcp_hdr_t *) (p + tcp_offset); + tcp_seq_num = + (tcp_hdr->seq_num[0] << 24) | + (tcp_hdr->seq_num[1] << 16) | + (tcp_hdr->seq_num[1] << 8) | + (tcp_hdr->seq_num[1] << 0); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "frame %p: TCP seq num = %d\n", frm, tcp_seq_num); +#else + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "frame %p: TCP seq num = %d\n", frm, + ((*(p + tcp_offset + 4)) << 24) | + ((*(p + tcp_offset + 5)) << 16) | + ((*(p + tcp_offset + 6)) << 8) | + (*(p + tcp_offset + 7))); +#endif + } else { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "frame %p non-TCP IP protocol (%x)\n", frm, ip_prot); + } + } +NOT_IP_TCP: + if (display_options & ol_txrx_frm_dump_contents) { + int i, frag_num, len_lim; + len_lim = max_len; + if (len_lim > adf_nbuf_len(frm)) { + len_lim = adf_nbuf_len(frm); + } + if (len_lim > TXRX_FRM_DUMP_MAX_LEN) { + len_lim = TXRX_FRM_DUMP_MAX_LEN; + } + + /* + * Gather frame contents from netbuf fragments + * into a contiguous buffer. + */ + frag_num = 0; + i = 0; + while (i < len_lim) { + int frag_bytes; + frag_bytes = adf_nbuf_get_frag_len(frm, frag_num); + if (frag_bytes > len_lim - i) { + frag_bytes = len_lim - i; + } + if (frag_bytes > 0) { + p = adf_nbuf_get_frag_vaddr(frm, frag_num); + adf_os_mem_copy(&local_buf[i], p, frag_bytes); + } + frag_num++; + i += frag_bytes; + } + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "frame %p data (%p), hex dump of bytes 0-%d of %d:\n", + frm, p, len_lim-1, (int) adf_nbuf_len(frm)); + p = local_buf; + while (len_lim > 16) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " " /* indent */ + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + *(p + 0), *(p + 1), *(p + 2), *(p + 3), + *(p + 4), *(p + 5), *(p + 6), *(p + 7), + *(p + 8), *(p + 9), *(p + 10), *(p + 11), + *(p + 12), *(p + 13), *(p + 14), *(p + 15)); + p += 16; + len_lim -= 16; + } + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + " " /* indent */); + while (len_lim > 0) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, + "%02x ", *p); + p++; + len_lim--; + } + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, "\n"); + } + frm = adf_nbuf_next(frm); + } +} +#else +#define OL_TXRX_FRMS_DUMP(name, pdev, frms, display_options, max_len) +#endif /* TXRX_DEBUG_DATA */ + +#ifdef SUPPORT_HOST_STATISTICS + +#define OL_RX_ERR_STATISTICS(pdev, vdev, err_type, sec_type, is_mcast) \ + ol_rx_err_statistics(pdev->ctrl_pdev, vdev->vdev_id, err_type, \ + sec_type, is_mcast); + +#define OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_desc, err_type) \ +do { \ + int is_mcast; \ + enum htt_sec_type sec_type; \ + is_mcast = htt_rx_msdu_is_wlan_mcast(pdev->htt_pdev, rx_desc); \ + sec_type = peer->security[is_mcast ? txrx_sec_mcast : txrx_sec_ucast].sec_type; \ + OL_RX_ERR_STATISTICS(pdev, vdev, err_type, pdev->sec_types[sec_type], is_mcast); \ +} while (false) + +#define OL_RX_ERR_INV_PEER_STATISTICS(pdev, rx_msdu) \ +do { \ + struct ieee80211_frame *wh = NULL; \ + /*FIX THIS :Here htt_rx_mpdu_wifi_hdr_retrieve should be used. But at */ \ + /*present it seems it does not work.*/ \ + /*wh = (struct ieee80211_frame *)htt_rx_mpdu_wifi_hdr_retrieve(pdev->htt_pdev, rx_desc);*/ \ + \ + /* this only apply to LL device.*/ \ + if (!ol_cfg_is_high_latency(pdev->ctrl_pdev) && \ + ol_cfg_frame_type(pdev->ctrl_pdev) == wlan_frm_fmt_native_wifi) { \ + /* For windows, it is always native wifi header .*/ \ + wh = (struct ieee80211_frame*)adf_nbuf_data(rx_msdu); \ + } \ + ol_rx_err_inv_peer_statistics(pdev->ctrl_pdev, wh, OL_RX_ERR_UNKNOWN_PEER); \ +} while (false) + +#define OL_RX_ERR_STATISTICS_2(pdev, vdev, peer, rx_desc, rx_msdu, rx_status) \ +do { \ + enum ol_rx_err_type err_type = OL_RX_ERR_NONE; \ + switch (rx_status) { \ + case htt_rx_status_decrypt_err: \ + err_type = OL_RX_ERR_DECRYPT; \ + break; \ + case htt_rx_status_tkip_mic_err: \ + err_type = OL_RX_ERR_TKIP_MIC; \ + break; \ + case htt_rx_status_mpdu_length_err: \ + err_type = OL_RX_ERR_MPDU_LENGTH; \ + break; \ + case htt_rx_status_mpdu_encrypt_required_err: \ + err_type = OL_RX_ERR_ENCRYPT_REQUIRED; \ + break; \ + case htt_rx_status_err_dup: \ + err_type = OL_RX_ERR_DUP; \ + break; \ + case htt_rx_status_err_fcs: \ + err_type = OL_RX_ERR_FCS; \ + break; \ + default: \ + err_type = OL_RX_ERR_UNKNOWN; \ + break; \ + } \ + if (vdev != NULL && peer != NULL) { \ + OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_mpdu_desc, err_type); \ + } else { \ + OL_RX_ERR_INV_PEER_STATISTICS(pdev, rx_msdu); \ + } \ +} while (false) +#else +#define OL_RX_ERR_STATISTICS(pdev, vdev, err_type, sec_type, is_mcast) +#define OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_desc, err_type) +#define OL_RX_ERR_STATISTICS_2(pdev, vdev, peer, rx_desc, rx_msdu, rx_status) +#endif /* SUPPORT_HOST_STATISTICS */ + +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS +#define OL_TXRX_PEER_STATS_UPDATE_BASE(peer, tx_or_rx, type, msdu) \ + do { \ + adf_os_spin_lock_bh(&peer->vdev->pdev->peer_stat_mutex); \ + peer->stats. tx_or_rx .frms. type += 1; \ + peer->stats. tx_or_rx .bytes. type += adf_nbuf_len(msdu); \ + adf_os_spin_unlock_bh(&peer->vdev->pdev->peer_stat_mutex); \ + } while (0) +#define OL_TXRX_PEER_STATS_UPDATE(peer, tx_or_rx, msdu) \ + do { \ + struct ol_txrx_vdev_t *vdev = peer->vdev; \ + struct ol_txrx_pdev_t *pdev = vdev->pdev; \ + u_int8_t *dest_addr; \ + if (pdev->frame_format == wlan_frm_fmt_802_3) { \ + dest_addr = adf_nbuf_data(msdu); \ + } else { /* 802.11 format */ \ + struct ieee80211_frame *frm; \ + frm = (struct ieee80211_frame *) adf_nbuf_data(msdu); \ + if (vdev->opmode == wlan_op_mode_ap) { \ + dest_addr = (u_int8_t *) &(frm->i_addr1[0]); \ + } else { \ + dest_addr = (u_int8_t *) &(frm->i_addr3[0]); \ + } \ + } \ + if (adf_os_unlikely(IEEE80211_IS_BROADCAST(dest_addr))) { \ + OL_TXRX_PEER_STATS_UPDATE_BASE(peer, tx_or_rx, bcast, msdu); \ + } else if (adf_os_unlikely(IEEE80211_IS_MULTICAST(dest_addr))) { \ + OL_TXRX_PEER_STATS_UPDATE_BASE(peer, tx_or_rx, mcast, msdu); \ + } else { \ + OL_TXRX_PEER_STATS_UPDATE_BASE(peer, tx_or_rx, ucast, msdu); \ + } \ + } while (0) +#define OL_TX_PEER_STATS_UPDATE(peer, msdu) \ + OL_TXRX_PEER_STATS_UPDATE(peer, tx, msdu) +#define OL_RX_PEER_STATS_UPDATE(peer, msdu) \ + OL_TXRX_PEER_STATS_UPDATE(peer, rx, msdu) +#define OL_TXRX_PEER_STATS_MUTEX_INIT(pdev) \ + adf_os_spinlock_init(&pdev->peer_stat_mutex) +#define OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev) \ + adf_os_spinlock_destroy(&pdev->peer_stat_mutex) +#else +#define OL_TX_PEER_STATS_UPDATE(peer, msdu) /* no-op */ +#define OL_RX_PEER_STATS_UPDATE(peer, msdu) /* no-op */ +#define OL_TXRX_PEER_STATS_MUTEX_INIT(peer) /* no-op */ +#define OL_TXRX_PEER_STATS_MUTEX_DESTROY(peer) /* no-op */ +#endif + +#ifndef DEBUG_HTT_CREDIT +#define DEBUG_HTT_CREDIT 0 +#endif + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +void +ol_txrx_update_group_credit( + struct ol_tx_queue_group_t *group, + int32_t credit, + u_int8_t absolute); +#endif + +#endif /* _OL_TXRX_INTERNAL__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.c new file mode 100644 index 000000000000..5196bc369462 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.c @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=== includes ===*/ +/* header files for OS primitives */ +#include /* u_int32_t, etc. */ +#include /* adf_os_mem_alloc, etc. */ +#include /* adf_os_device_t, adf_os_print */ +/* header files for utilities */ +#include /* TAILQ */ + +/* header files for configuration API */ +#include /* ol_cfg_max_peer_id */ + +/* header files for our internal definitions */ +#include /* ol_txrx_pdev_t, etc. */ +#include /* TXRX_DEBUG_LEVEL */ +#include /* ol_txrx_pdev_t, etc. */ +#include /* ol_txrx_peer_unref_delete */ +#include /* ol_txrx_peer_find_attach, etc. */ +#include + +/*=== misc. / utility function definitions ==================================*/ + +static int +ol_txrx_log2_ceil(unsigned value) +{ + /* need to switch to unsigned math so that negative values + * will right-shift towards 0 instead of -1 + */ + unsigned tmp = value; + int log2 = -1; + + if (value == 0) + { + TXRX_ASSERT2(0); + return 0; + } + + while (tmp) { + log2++; + tmp >>= 1; + } + if (1U << log2 != value) { + log2++; + } + + return log2; +} + +static int +ol_txrx_peer_find_add_id_to_obj( + struct ol_txrx_peer_t *peer, + u_int16_t peer_id) +{ + int i; + + for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) { + if (peer->peer_ids[i] == HTT_INVALID_PEER) { + peer->peer_ids[i] = peer_id; + return 0; /* success */ + } + } + return 1; /* failure */ +} + +/*=== function definitions for peer MAC addr --> peer object hash table =====*/ + +/* + * TXRX_PEER_HASH_LOAD_FACTOR: + * Multiply by 2 and divide by 2^0 (shift by 0), then round up to a + * power of two. + * This provides at least twice as many bins in the peer hash table + * as there will be entries. + * Having substantially more bins than spaces minimizes the probability of + * having to compare MAC addresses. + * Because the MAC address comparison is fairly efficient, it is okay if the + * hash table is sparsely loaded, but it's generally better to use extra mem + * to keep the table sparse, to keep the lookups as fast as possible. + * An optimization would be to apply a more conservative loading factor for + * high latency, where the lookup happens during the tx classification of + * every tx frame, than for low-latency, where the lookup only happens + * during association, when the PEER_MAP message is received. + */ +#define TXRX_PEER_HASH_LOAD_MULT 2 +#define TXRX_PEER_HASH_LOAD_SHIFT 0 + +static int +ol_txrx_peer_find_hash_attach(struct ol_txrx_pdev_t *pdev) +{ + int i, hash_elems, log2; + + /* allocate the peer MAC address -> peer object hash table */ + hash_elems = ol_cfg_max_peer_id(pdev->ctrl_pdev) + 1; + hash_elems *= TXRX_PEER_HASH_LOAD_MULT; + hash_elems >>= TXRX_PEER_HASH_LOAD_SHIFT; + log2 = ol_txrx_log2_ceil(hash_elems); + hash_elems = 1 << log2; + + pdev->peer_hash.mask = hash_elems - 1; + pdev->peer_hash.idx_bits = log2; + /* allocate an array of TAILQ peer object lists */ + pdev->peer_hash.bins = adf_os_mem_alloc( + pdev->osdev, + hash_elems * sizeof(TAILQ_HEAD(anonymous_tail_q, ol_txrx_peer_t))); + if (!pdev->peer_hash.bins) { + return 1; /* failure */ + } + for (i = 0; i < hash_elems; i++) { + TAILQ_INIT(&pdev->peer_hash.bins[i]); + } + return 0; /* success */ +} + +static void +ol_txrx_peer_find_hash_detach(struct ol_txrx_pdev_t *pdev) +{ + adf_os_mem_free(pdev->peer_hash.bins); +} + +static inline unsigned +ol_txrx_peer_find_hash_index( + struct ol_txrx_pdev_t *pdev, + union ol_txrx_align_mac_addr_t *mac_addr) +{ + unsigned index; + + index = + mac_addr->align2.bytes_ab ^ + mac_addr->align2.bytes_cd ^ + mac_addr->align2.bytes_ef; + index ^= index >> pdev->peer_hash.idx_bits; + index &= pdev->peer_hash.mask; + return index; +} + + +void +ol_txrx_peer_find_hash_add( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + unsigned index; + + index = ol_txrx_peer_find_hash_index(pdev, &peer->mac_addr); + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + /* + * It is important to add the new peer at the tail of the peer list + * with the bin index. Together with having the hash_find function + * search from head to tail, this ensures that if two entries with + * the same MAC address are stored, the one added first will be + * found first. + */ + TAILQ_INSERT_TAIL(&pdev->peer_hash.bins[index], peer, hash_list_elem); + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); +} + +struct ol_txrx_peer_t * +ol_txrx_peer_vdev_find_hash(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + u_int8_t *peer_mac_addr, + int mac_addr_is_aligned, + u_int8_t check_valid) +{ + union ol_txrx_align_mac_addr_t local_mac_addr_aligned, *mac_addr; + unsigned index; + struct ol_txrx_peer_t *peer; + + if (mac_addr_is_aligned) { + mac_addr = (union ol_txrx_align_mac_addr_t *) peer_mac_addr; + } else { + adf_os_mem_copy( + &local_mac_addr_aligned.raw[0], + peer_mac_addr, OL_TXRX_MAC_ADDR_LEN); + mac_addr = &local_mac_addr_aligned; + } + index = ol_txrx_peer_find_hash_index(pdev, mac_addr); + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + TAILQ_FOREACH(peer, &pdev->peer_hash.bins[index], hash_list_elem) { + if (ol_txrx_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 + && (check_valid == 0 || peer->valid) && peer->vdev == vdev ) { + /* found it - increment the ref count before releasing the lock */ + adf_os_atomic_inc(&peer->ref_cnt); + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + return peer; + } + } + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + return NULL; /* failure */ +} + +struct ol_txrx_peer_t * +ol_txrx_peer_find_hash_find( + struct ol_txrx_pdev_t *pdev, + u_int8_t *peer_mac_addr, + int mac_addr_is_aligned, + u_int8_t check_valid) +{ + union ol_txrx_align_mac_addr_t local_mac_addr_aligned, *mac_addr; + unsigned index; + struct ol_txrx_peer_t *peer; + + if (mac_addr_is_aligned) { + mac_addr = (union ol_txrx_align_mac_addr_t *) peer_mac_addr; + } else { + adf_os_mem_copy( + &local_mac_addr_aligned.raw[0], + peer_mac_addr, OL_TXRX_MAC_ADDR_LEN); + mac_addr = &local_mac_addr_aligned; + } + index = ol_txrx_peer_find_hash_index(pdev, mac_addr); + adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + TAILQ_FOREACH(peer, &pdev->peer_hash.bins[index], hash_list_elem) { + if (ol_txrx_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 + && (check_valid == 0 || peer->valid)) { + /* found it - increment the ref count before releasing the lock */ + adf_os_atomic_inc(&peer->ref_cnt); + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + return peer; + } + } + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + return NULL; /* failure */ +} + +void +ol_txrx_peer_find_hash_remove( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer) +{ + unsigned index; + + index = ol_txrx_peer_find_hash_index(pdev, &peer->mac_addr); + /* + * DO NOT take the peer_ref_mutex lock here - it needs to be taken + * by the caller. + * The caller needs to hold the lock from the time the peer object's + * reference count is decremented and tested up through the time the + * reference to the peer object is removed from the hash table, by + * this function. + * Holding the lock only while removing the peer object reference + * from the hash table keeps the hash table consistent, but does not + * protect against a new HL tx context starting to use the peer object + * if it looks up the peer object from its MAC address just after the + * peer ref count is decremented to zero, but just before the peer + * object reference is removed from the hash table. + */ + //adf_os_spin_lock_bh(&pdev->peer_ref_mutex); + TAILQ_REMOVE(&pdev->peer_hash.bins[index], peer, hash_list_elem); + //adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); +} + +void +ol_txrx_peer_find_hash_erase(struct ol_txrx_pdev_t *pdev) +{ + unsigned i; + /* + * Not really necessary to take peer_ref_mutex lock - by this point, + * it's known that the pdev is no longer in use. + */ + + for (i = 0; i <= pdev->peer_hash.mask; i++) { + if (!TAILQ_EMPTY(&pdev->peer_hash.bins[i])) { + struct ol_txrx_peer_t *peer, *peer_next; + + /* + * TAILQ_FOREACH_SAFE must be used here to avoid any memory access + * violation after peer is freed + */ + TAILQ_FOREACH_SAFE( + peer, &pdev->peer_hash.bins[i], hash_list_elem, peer_next) + { + /* + * Don't remove the peer from the hash table - + * that would modify the list we are currently traversing, + * and it's not necessary anyway. + */ + /* + * Artificially adjust the peer's ref count to 1, so it + * will get deleted by ol_txrx_peer_unref_delete. + */ + adf_os_atomic_init(&peer->ref_cnt); /* set to zero */ + adf_os_atomic_inc(&peer->ref_cnt); /* incr to one */ + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Delete Peer %p\n", __func__, peer); + ol_txrx_peer_unref_delete(peer); + } + } + } +} + +/*=== function definitions for peer id --> peer object map ==================*/ + +static int +ol_txrx_peer_find_map_attach(struct ol_txrx_pdev_t *pdev) +{ + int max_peers, peer_map_size; + + /* allocate the peer ID -> peer object map */ + max_peers = ol_cfg_max_peer_id(pdev->ctrl_pdev) + 1; + peer_map_size = max_peers * sizeof(pdev->peer_id_to_obj_map[0]); + pdev->peer_id_to_obj_map = adf_os_mem_alloc(pdev->osdev, peer_map_size); + if (!pdev->peer_id_to_obj_map) { + return 1; /* failure */ + } + + /* + * The peer_id_to_obj_map doesn't really need to be initialized, + * since elements are only used after they have been individually + * initialized. + * However, it is convenient for debugging to have all elements + * that are not in use set to 0. + */ + adf_os_mem_set(pdev->peer_id_to_obj_map, 0, peer_map_size); + + return 0; /* success */ +} + +static void +ol_txrx_peer_find_map_detach(struct ol_txrx_pdev_t *pdev) +{ + adf_os_mem_free(pdev->peer_id_to_obj_map); +} + +static inline void +ol_txrx_peer_find_add_id( + struct ol_txrx_pdev_t *pdev, + u_int8_t *peer_mac_addr, + u_int16_t peer_id) +{ + struct ol_txrx_peer_t *peer; + + /* check if there's already a peer object with this MAC address */ + peer = ol_txrx_peer_find_hash_find(pdev, peer_mac_addr, 1 /* is aligned */, 0); + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: peer %p ID %d\n", __func__, peer, peer_id); + if (peer) { + /* peer's ref count was already incremented by peer_find_hash_find */ + pdev->peer_id_to_obj_map[peer_id] = peer; + /* + * remove the reference added in ol_txrx_peer_find_hash_find. + * the reference for the first peer id is already added in ol_txrx_peer_attach. + * Riva/Pronto has one peer id for each peer. + * Peregrine/Rome has two peer id for each peer. + */ + if (peer->peer_ids[0] == HTT_INVALID_PEER) { + ol_txrx_peer_unref_delete(peer); + } + if (ol_txrx_peer_find_add_id_to_obj(peer, peer_id)) { + /* TBDXXX: assert for now */ + adf_os_assert(0); + } + return; + } + /* + * Currently peer IDs are assigned for vdevs as well as peers. + * If the peer ID is for a vdev, then we will fail to find a peer + * with a matching MAC address. + */ + //TXRX_ASSERT2(0); +} + +/*=== allocation / deallocation function definitions ========================*/ + +int +ol_txrx_peer_find_attach(struct ol_txrx_pdev_t *pdev) +{ + if (ol_txrx_peer_find_map_attach(pdev)) { + return 1; + } + if (ol_txrx_peer_find_hash_attach(pdev)) { + ol_txrx_peer_find_map_detach(pdev); + return 1; + } + return 0; /* success */ +} + +void +ol_txrx_peer_find_detach(struct ol_txrx_pdev_t *pdev) +{ + ol_txrx_peer_find_map_detach(pdev); + ol_txrx_peer_find_hash_detach(pdev); +} + +/*=== function definitions for message handling =============================*/ + +void +ol_rx_peer_map_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tx_ready) +{ + ol_txrx_peer_find_add_id(pdev, peer_mac_addr, peer_id); + if (pdev->cfg.is_high_latency && !tx_ready) { + struct ol_txrx_peer_t *peer; + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (!peer) { + /* ol_txrx_peer_detach called before peer map arrived */ + return; + }else { + if (tx_ready) { +#if defined(CONFIG_HL_SUPPORT) + int i; + /* unpause all tx queues now, since the target is ready */ + for (i = 0; i < ARRAY_LEN(peer->txqs); i++) { + ol_txrx_peer_tid_unpause(peer, i); + } +#endif + } else { + /* walk through paused mgmt queue, update tx descriptors */ + ol_tx_queue_decs_reinit(peer, peer_id); + + /* keep non-mgmt tx queues paused until assoc is finished */ + /* tx queues were paused in ol_txrx_peer_attach*/ + /* unpause tx mgmt queue */ + ol_txrx_peer_tid_unpause(peer, HTT_TX_EXT_TID_MGMT); + } + } + } +} + +void +ol_txrx_peer_tx_ready_handler(ol_txrx_pdev_handle pdev, u_int16_t peer_id) +{ +#if defined(CONFIG_HL_SUPPORT) + struct ol_txrx_peer_t *peer; + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (peer) { + int i; + /* + * Unpause all data tx queues now that the target is ready. + * The mgmt tx queue was not paused, so skip it. + */ + for (i = 0; i < ARRAY_LEN(peer->txqs); i++) { + if (i == HTT_TX_EXT_TID_MGMT) { + continue; /* mgmt tx queue was not paused */ + } + ol_txrx_peer_tid_unpause(peer, i); + } + } +#endif +} + +void +ol_rx_peer_unmap_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id) +{ + struct ol_txrx_peer_t *peer; + peer = (peer_id == HTT_INVALID_PEER) ? NULL : + pdev->peer_id_to_obj_map[peer_id]; + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: peer %p with ID %d to be unmapped.\n", __func__, peer, peer_id); + pdev->peer_id_to_obj_map[peer_id] = NULL; + /* + * Currently peer IDs are assigned for vdevs as well as peers. + * If the peer ID is for a vdev, then the peer pointer stored + * in peer_id_to_obj_map will be NULL. + */ + if (!peer) return; + /* + * Remove a reference to the peer. + * If there are no more references, delete the peer object. + */ + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: Remove the ID %d reference to peer %p\n", + __func__, peer_id, peer); + ol_txrx_peer_unref_delete(peer); +} + +struct ol_txrx_peer_t * +ol_txrx_assoc_peer_find(struct ol_txrx_vdev_t *vdev) +{ + struct ol_txrx_peer_t *peer; + + adf_os_spin_lock_bh(&vdev->pdev->last_real_peer_mutex); + /* + * Check the TXRX Peer is itself valid And also + * if HTT Peer ID has been setup for this peer + */ + if (vdev->last_real_peer && vdev->last_real_peer->peer_ids[0] != HTT_INVALID_PEER_ID) + { + adf_os_atomic_inc(&vdev->last_real_peer->ref_cnt); + peer = vdev->last_real_peer; + } else { + peer = NULL; + } + adf_os_spin_unlock_bh(&vdev->pdev->last_real_peer_mutex); + return peer; +} + +/*=== function definitions for debug ========================================*/ + +#if defined (TXRX_DEBUG_LEVEL) && TXRX_DEBUG_LEVEL > 5 +void +ol_txrx_peer_find_display(ol_txrx_pdev_handle pdev, int indent) +{ + int i, max_peers; + + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*speer map:\n", indent, " "); + max_peers = ol_cfg_max_peer_id(pdev->ctrl_pdev) + 1; + for (i = 0; i < max_peers; i++) { + if (pdev->peer_id_to_obj_map[i]) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*sid %d -> %p\n", + indent+4, " ", i, pdev->peer_id_to_obj_map[i]); + } + } + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*speer hash table:\n", indent, " "); + for (i = 0; i <= pdev->peer_hash.mask; i++) { + if (!TAILQ_EMPTY(&pdev->peer_hash.bins[i])) { + struct ol_txrx_peer_t *peer; + TAILQ_FOREACH(peer, &pdev->peer_hash.bins[i], hash_list_elem) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "%*shash idx %d -> %p (%02x:%02x:%02x:%02x:%02x:%02x)\n", + indent+4, " ", i, peer, + peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], + peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + } + } + } +} +#endif /* if TXRX_DEBUG_LEVEL */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.h new file mode 100644 index 000000000000..acb7d6474237 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_peer_find.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_peer_find.h + * @brief Define the API for the rx peer lookup datapath module. + */ +#ifndef _OL_TXRX_PEER_FIND__H_ +#define _OL_TXRX_PEER_FIND__H_ + +#include /* HTT_INVALID_PEER */ +#include /* ol_txrx_pdev_t, etc. */ +#include /* TXRX_ASSERT */ + +int ol_txrx_peer_find_attach(struct ol_txrx_pdev_t *pdev); + +void ol_txrx_peer_find_detach(struct ol_txrx_pdev_t *pdev); + +static inline +int +ol_txrx_peer_find_mac_addr_cmp( + union ol_txrx_align_mac_addr_t *mac_addr1, + union ol_txrx_align_mac_addr_t *mac_addr2) +{ + return + !((mac_addr1->align4.bytes_abcd == mac_addr2->align4.bytes_abcd) + /* + * Intentionally use & rather than &&. + * because the operands are binary rather than generic boolean, + * the functionality is equivalent. + * Using && has the advantage of short-circuited evaluation, + * but using & has the advantage of no conditional branching, + * which is a more significant benefit. + */ + & + (mac_addr1->align4.bytes_ef == mac_addr2->align4.bytes_ef)); +} + +static inline +struct ol_txrx_peer_t * +ol_txrx_peer_find_by_id( + struct ol_txrx_pdev_t *pdev, + u_int16_t peer_id) +{ + struct ol_txrx_peer_t *peer; + peer = (peer_id > ol_cfg_max_peer_id(pdev->ctrl_pdev)) ? NULL : + pdev->peer_id_to_obj_map[peer_id]; + /* + * Currently, peer IDs are assigned to vdevs as well as peers. + * If the peer ID is for a vdev, the peer_id_to_obj_map entry + * will hold NULL rather than a valid peer pointer. + */ + //TXRX_ASSERT2(peer != NULL); + /* + * Only return the peer object if it is valid, + * i.e. it has not already been detached. + * If it has already been detached, then returning the + * peer object could result in unpausing the peer's tx queues + * in HL systems, which is an invalid operation following peer_detach. + */ + if (peer && peer->valid) { + return peer; + } + return NULL; +} + +void +ol_txrx_peer_find_hash_add( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer); + +struct ol_txrx_peer_t * +ol_txrx_peer_find_hash_find( + struct ol_txrx_pdev_t *pdev, + u_int8_t *peer_mac_addr, + int mac_addr_is_aligned, + u_int8_t check_valid); + +struct +ol_txrx_peer_t * +ol_txrx_peer_vdev_find_hash( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + u_int8_t *peer_mac_addr, + int mac_addr_is_aligned, + u_int8_t check_valid); + +void +ol_txrx_peer_find_hash_remove( + struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer); + +void +ol_txrx_peer_find_hash_erase( + struct ol_txrx_pdev_t *pdev); + +struct ol_txrx_peer_t * +ol_txrx_assoc_peer_find(struct ol_txrx_vdev_t *vdev); + +#if defined(TXRX_DEBUG_LEVEL) && TXRX_DEBUG_LEVEL > 5 +void ol_txrx_peer_find_display(ol_txrx_pdev_handle pdev, int indent); +#else +#define ol_txrx_peer_find_display(pdev, indent) +#endif /* TXRX_DEBUG_LEVEL */ + +#endif /* _OL_TXRX_PEER_FIND__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_types.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_types.h new file mode 100644 index 000000000000..998b899795ae --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx_types.h @@ -0,0 +1,1088 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_types.h + * @brief Define the major data types used internally by the host datapath SW. + */ +#ifndef _OL_TXRX_TYPES__H_ +#define _OL_TXRX_TYPES__H_ + +#include /* adf_nbuf_t */ +#include /* TAILQ */ +#include /* A_UINT8 */ +#include /* htt_sec_type, htt_pkt_type, etc. */ +#include /* adf_os_atomic_t */ +#include /* wdi_event_subscribe */ +#include /* adf_os_timer_t */ +#include /* adf_os_spinlock */ +#include /* ol_pktlog_dev_handle */ +#include +#include +#include "ol_txrx_htt_api.h" +#include "ol_htt_tx_api.h" +#include "ol_htt_rx_api.h" +#include "wlan_qct_tl.h" +#include + +/* + * The target may allocate multiple IDs for a peer. + * In particular, the target may allocate one ID to represent the + * multicast key the peer uses, and another ID to represent the + * unicast key the peer uses. + */ +#define MAX_NUM_PEER_ID_PER_PEER 8 + +#define OL_TXRX_MAC_ADDR_LEN 6 + +/* OL_TXRX_NUM_EXT_TIDS - + * 16 "real" TIDs + 3 pseudo-TIDs for mgmt, mcast/bcast & non-QoS data + */ +#define OL_TXRX_NUM_EXT_TIDS 19 + +#define OL_TX_NUM_QOS_TIDS 16 /* 16 regular TIDs */ +#define OL_TX_NON_QOS_TID 16 +#define OL_TX_MGMT_TID 17 +#define OL_TX_NUM_TIDS 18 + +#define OL_RX_MCAST_TID 18 /* Mcast TID only between f/w & host */ + +#define OL_TX_VDEV_MCAST_BCAST 0 // HTT_TX_EXT_TID_MCAST_BCAST +#define OL_TX_VDEV_DEFAULT_MGMT 1 // HTT_TX_EXT_TID_DEFALT_MGMT +#define OL_TX_VDEV_NUM_QUEUES 2 + +#define OL_TXRX_MGMT_TYPE_BASE htt_pkt_num_types +#define OL_TXRX_MGMT_NUM_TYPES 8 + +#define OL_TX_MUTEX_TYPE adf_os_spinlock_t +#define OL_RX_MUTEX_TYPE adf_os_spinlock_t + +/* TXRX Histogram defines */ +#define TXRX_DATA_HISTROGRAM_GRANULARITY 1000 +#define TXRX_DATA_HISTROGRAM_NUM_INTERVALS 100 + +struct ol_txrx_pdev_t; +struct ol_txrx_vdev_t; +struct ol_txrx_peer_t; + +struct ol_pdev_t; +typedef struct ol_pdev_t* ol_pdev_handle; + +struct ol_vdev_t; +typedef struct ol_vdev_t* ol_vdev_handle; + +struct ol_peer_t; +typedef struct ol_peer_t* ol_peer_handle; + +/* rx filter related */ +#define MAX_PRIVACY_FILTERS 4 /* max privacy filters */ + +typedef enum _privacy_filter { + PRIVACY_FILTER_ALWAYS, + PRIVACY_FILTER_KEY_UNAVAILABLE, +} privacy_filter ; + +typedef enum _privacy_filter_packet_type { + PRIVACY_FILTER_PACKET_UNICAST, + PRIVACY_FILTER_PACKET_MULTICAST, + PRIVACY_FILTER_PACKET_BOTH +} privacy_filter_packet_type ; + +typedef struct _privacy_excemption_filter { + /* ethertype - + * type of ethernet frames this filter applies to, in host byte order + */ + u_int16_t ether_type; + privacy_filter filter_type; + privacy_filter_packet_type packet_type; +} privacy_exemption; + +enum ol_tx_frm_type { + ol_tx_frm_std = 0, /* regular frame - no added header fragments */ + ol_tx_frm_tso, /* TSO segment, with a modified IP header added */ + ol_tx_frm_audio, /* audio frames, with a custom LLC/SNAP header added */ + ol_tx_frm_no_free, /* frame requires special tx completion callback */ +}; + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +#define MAX_NO_PEERS_IN_LIMIT (2*10 + 2) + +typedef enum _ol_tx_peer_bal_state { + ol_tx_peer_bal_enable = 0, + ol_tx_peer_bal_disable, +} ol_tx_peer_bal_state; + +typedef enum _ol_tx_peer_bal_timer_state { + ol_tx_peer_bal_timer_disable = 0, + ol_tx_peer_bal_timer_active, + ol_tx_peer_bal_timer_inactive, +} ol_tx_peer_bal_timer_state; + +typedef struct _ol_tx_limit_peer_t { + u_int16_t limit_flag; + u_int16_t peer_id; + u_int16_t limit; +} ol_tx_limit_peer_t; + +typedef enum { + TXRX_IEEE11_B = 0, + TXRX_IEEE11_A_G, + TXRX_IEEE11_N, + TXRX_IEEE11_AC, + TXRX_IEEE11_MAX, +} tx_peer_level; + +typedef struct _tx_peer_threshold{ + u_int32_t tput_thresh; + u_int32_t tx_limit; +} tx_peer_threshold; +#endif + +struct ol_tx_desc_t { + adf_nbuf_t netbuf; + void *htt_tx_desc; + u_int32_t htt_tx_desc_paddr; + adf_os_atomic_t ref_cnt; + enum htt_tx_status status; + +#ifdef QCA_COMPUTE_TX_DELAY + u_int32_t entry_timestamp_ticks; +#endif + /* + * Allow tx descriptors to be stored in (doubly-linked) lists. + * This is mainly used for HL tx queuing and scheduling, but is + * also used by LL+HL for batch processing of tx frames. + */ + TAILQ_ENTRY(ol_tx_desc_t) tx_desc_list_elem; + + /* + * Remember whether the tx frame is a regular packet, or whether + * the driver added extra header fragments (e.g. a modified IP header + * for TSO fragments, or an added LLC/SNAP header for audio interworking + * data) that need to be handled in a special manner. + * This field is filled in with the ol_tx_frm_type enum. + */ + u_int8_t pkt_type; +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + /* used by tx encap, to restore the os buf start offset after tx complete*/ + u_int8_t orig_l2_hdr_bytes; +#endif +#if defined(CONFIG_HL_SUPPORT) + struct ol_txrx_vdev_t* vdev; +#endif + void *txq; + void *p_link; + uint16_t id; +}; + +typedef TAILQ_HEAD(, ol_tx_desc_t) ol_tx_desc_list; + +struct ol_tx_desc_list_elem_t { + struct ol_tx_desc_list_elem_t *next; + struct ol_tx_desc_t *tx_desc; +}; + +union ol_txrx_align_mac_addr_t { + u_int8_t raw[OL_TXRX_MAC_ADDR_LEN]; + struct { + u_int16_t bytes_ab; + u_int16_t bytes_cd; + u_int16_t bytes_ef; + } align2; + struct { + u_int32_t bytes_abcd; + u_int16_t bytes_ef; + } align4; +}; + +struct ol_rx_reorder_timeout_list_elem_t +{ + TAILQ_ENTRY(ol_rx_reorder_timeout_list_elem_t) reorder_timeout_list_elem; + u_int32_t timestamp_ms; + struct ol_txrx_peer_t *peer; + u_int8_t tid; + u_int8_t active; +}; + +#define TXRX_TID_TO_WMM_AC(_tid) (\ + (((_tid) >> 1) == 3) ? TXRX_WMM_AC_VO : \ + (((_tid) >> 1) == 2) ? TXRX_WMM_AC_VI : \ + (((_tid) ^ ((_tid) >> 1)) & 0x1) ? TXRX_WMM_AC_BK : \ + TXRX_WMM_AC_BE) + +enum { + OL_TX_SCHED_WRR_ADV_CAT_BE, + OL_TX_SCHED_WRR_ADV_CAT_BK, + OL_TX_SCHED_WRR_ADV_CAT_VI, + OL_TX_SCHED_WRR_ADV_CAT_VO, + OL_TX_SCHED_WRR_ADV_CAT_NON_QOS_DATA, + OL_TX_SCHED_WRR_ADV_CAT_UCAST_MGMT, + OL_TX_SCHED_WRR_ADV_CAT_MCAST_DATA, + OL_TX_SCHED_WRR_ADV_CAT_MCAST_MGMT, + + OL_TX_SCHED_WRR_ADV_NUM_CATEGORIES /* must be last */ +}; + +A_COMPILE_TIME_ASSERT(ol_tx_sched_htt_ac_values, + /* check that regular WMM AC enum values match */ + ((int)OL_TX_SCHED_WRR_ADV_CAT_VO == (int)HTT_AC_WMM_VO) && + ((int)OL_TX_SCHED_WRR_ADV_CAT_VI == (int)HTT_AC_WMM_VI) && + ((int)OL_TX_SCHED_WRR_ADV_CAT_BK == (int)HTT_AC_WMM_BK) && + ((int)OL_TX_SCHED_WRR_ADV_CAT_BE == (int)HTT_AC_WMM_BE) && + + /* check that extension AC enum values match */ + ((int)OL_TX_SCHED_WRR_ADV_CAT_NON_QOS_DATA == (int)HTT_AC_EXT_NON_QOS) && + ((int)OL_TX_SCHED_WRR_ADV_CAT_UCAST_MGMT == (int)HTT_AC_EXT_UCAST_MGMT) && + ((int)OL_TX_SCHED_WRR_ADV_CAT_MCAST_DATA == (int)HTT_AC_EXT_MCAST_DATA) && + ((int)OL_TX_SCHED_WRR_ADV_CAT_MCAST_MGMT == (int)HTT_AC_EXT_MCAST_MGMT)); + +struct ol_tx_reorder_cat_timeout_t { + TAILQ_HEAD(, ol_rx_reorder_timeout_list_elem_t) virtual_timer_list; + adf_os_timer_t timer; + u_int32_t duration_ms; + struct ol_txrx_pdev_t *pdev; +}; + +enum ol_tx_scheduler_status { + ol_tx_scheduler_idle = 0, + ol_tx_scheduler_running, +}; + +enum ol_tx_queue_status { + ol_tx_queue_empty = 0, + ol_tx_queue_active, + ol_tx_queue_paused, +}; + +struct ol_txrx_msdu_info_t { + struct htt_msdu_info_t htt; + struct ol_txrx_peer_t *peer; +}; + +enum { + ol_tx_aggr_untried = 0, + ol_tx_aggr_enabled, + ol_tx_aggr_disabled, + ol_tx_aggr_retry, + ol_tx_aggr_in_progress, +}; + +#define OL_TX_MAX_GROUPS_PER_QUEUE 1 +#define OL_TX_MAX_VDEV_ID 16 +#define OL_TXQ_GROUP_VDEV_ID_MASK_GET(_membership) \ + (((_membership) & 0xffff0000) >> 16) +#define OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(_mask, _vdev_id) \ + ((_mask >> _vdev_id) & 0x01) +#define OL_TXQ_GROUP_AC_MASK_GET(_membership) \ + ((_membership) & 0x0000ffff) +#define OL_TXQ_GROUP_AC_BIT_MASK_GET(_mask, _ac_mask) \ + ((_mask >> _ac_mask) & 0x01) +#define OL_TXQ_GROUP_MEMBERSHIP_GET(_vdev_mask, _ac_mask) \ + ((_vdev_mask << 16) | _ac_mask) + +struct ol_tx_frms_queue_t { + /* list_elem - + * Allow individual tx frame queues to be linked together into + * scheduler queues of tx frame queues + */ + TAILQ_ENTRY(ol_tx_frms_queue_t) list_elem; + u_int8_t aggr_state; + struct { + u_int8_t total; + /* pause requested by ctrl SW rather than txrx SW */ + u_int8_t by_ctrl; + } paused_count; + u_int8_t ext_tid; + u_int16_t frms; + u_int32_t bytes; + ol_tx_desc_list head; + enum ol_tx_queue_status flag; + struct ol_tx_queue_group_t *group_ptrs[OL_TX_MAX_GROUPS_PER_QUEUE]; +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + struct ol_txrx_peer_t *peer; +#endif +}; + +enum { + ol_tx_log_entry_type_invalid, + ol_tx_log_entry_type_queue_state, + ol_tx_log_entry_type_enqueue, + ol_tx_log_entry_type_dequeue, + ol_tx_log_entry_type_drop, + ol_tx_log_entry_type_queue_free, + + ol_tx_log_entry_type_wrap, +}; + +struct ol_tx_log_queue_state_var_sz_t { + u_int32_t active_bitmap; + u_int16_t credit; + u_int8_t num_cats_active; + u_int8_t data[1]; +}; + +struct ol_tx_log_queue_add_t { + u_int8_t num_frms; + u_int8_t tid; + u_int16_t peer_id; + u_int16_t num_bytes; +}; + +struct ol_mac_addr { + u_int8_t mac_addr[OL_TXRX_MAC_ADDR_LEN]; +}; + +struct ol_tx_sched_t; +typedef struct ol_tx_sched_t *ol_tx_sched_handle; + +#ifndef OL_TXRX_NUM_LOCAL_PEER_IDS +#define OL_TXRX_NUM_LOCAL_PEER_IDS 33 /* default */ +#endif + +#ifndef ol_txrx_local_peer_id_t +#define ol_txrx_local_peer_id_t u_int8_t /* default */ +#endif + +#ifdef QCA_COMPUTE_TX_DELAY +/* + * Delay histogram bins: 16 bins of 10 ms each to count delays + * from 0-160 ms, plus one overflow bin for delays > 160 ms. + */ +#define QCA_TX_DELAY_HIST_INTERNAL_BINS 17 +#define QCA_TX_DELAY_HIST_INTERNAL_BIN_WIDTH_MS 10 + +struct ol_tx_delay_data { + struct { + u_int64_t transmit_sum_ticks; + u_int64_t queue_sum_ticks; + u_int32_t transmit_num; + u_int32_t queue_num; + } avgs; + u_int16_t hist_bins_queue[QCA_TX_DELAY_HIST_INTERNAL_BINS]; +}; + +#endif /* QCA_COMPUTE_TX_DELAY */ + +/* Thermal Mitigation */ + +typedef enum _throttle_level { + THROTTLE_LEVEL_0, + THROTTLE_LEVEL_1, + THROTTLE_LEVEL_2, + THROTTLE_LEVEL_3, + /* Invalid */ + THROTTLE_LEVEL_MAX, +} throttle_level ; + +typedef enum _throttle_phase { + THROTTLE_PHASE_OFF, + THROTTLE_PHASE_ON, + /* Invalid */ + THROTTLE_PHASE_MAX, +} throttle_phase ; + +#define THROTTLE_TX_THRESHOLD (100) + +#ifdef IPA_UC_OFFLOAD +typedef void (*ipa_uc_op_cb_type)(u_int8_t *op_msg, void *osif_ctxt); +#endif /* IPA_UC_OFFLOAD */ + +struct ol_tx_queue_group_t { + adf_os_atomic_t credit; + u_int32_t membership; +}; +#define OL_TX_MAX_TXQ_GROUPS 2 + +#define OL_TX_GROUP_STATS_LOG_SIZE 128 +struct ol_tx_group_credit_stats_t { + struct { + struct { + u_int16_t member_vdevs; + u_int16_t credit; + } grp[OL_TX_MAX_TXQ_GROUPS]; + }stats[OL_TX_GROUP_STATS_LOG_SIZE]; + u_int16_t last_valid_index; + u_int16_t wrap_around; +}; + +/* + * As depicted in the diagram below, the pdev contains an array of + * NUM_EXT_TID ol_tx_active_queues_in_tid_t elements. + * Each element identifies all the tx queues that are active for + * the TID, from the different peers. + * + * Each peer contains an array of NUM_EXT_TID ol_tx_frms_queue_t elements. + * Each element identifies the tx frames for the TID that need to be sent + * to the peer. + * + * + * pdev: ol_tx_active_queues_in_tid_t active_in_tids[NUM_EXT_TIDS] + * TID + * 0 1 2 17 + * +============+============+============+== ==+============+ + * | active (y) | active (n) | active (n) | | active (y) | + * |------------+------------+------------+-- --+------------| + * | queues | queues | queues | | queues | + * +============+============+============+== ==+============+ + * | | + * .--+-----------------------------------------------' + * | | + * | | peer X: peer Y: + * | | ol_tx_frms_queue_t ol_tx_frms_queue_t + * | | tx_queues[NUM_EXT_TIDS] tx_queues[NUM_EXT_TIDS] + * | | TID +======+ TID +======+ + * | `---->| next |-------------------------->| next |--X + * | 0 | prev | .------. .------. 0 | prev | .------. + * | | txq |-->|txdesc|-->|txdesc| | txq |-->|txdesc| + * | +======+ `------' `------' +======+ `------' + * | | next | | | 1 | next | | + * | 1 | prev | v v | prev | v + * | | txq | .------. .------. | txq | .------. + * | +======+ |netbuf| |netbuf| +======+ |netbuf| + * | | next | `------' `------' | next | `------' + * | 2 | prev | 2 | prev | + * | | txq | | txq | + * | +======+ +======+ + * | | | | | + * | + * | + * | | | | | + * | +======+ +======+ + * `------->| next |--X | next | + * 17 | prev | .------. 17 | prev | + * | txq |-->|txdesc| | txq | + * +======+ `------' +======+ + * | + * v + * .------. + * |netbuf| + * `------' + */ +struct ol_txrx_pdev_t { + /* ctrl_pdev - handle for querying config info */ + ol_pdev_handle ctrl_pdev; + + /* osdev - handle for mem alloc / free, map / unmap */ + adf_os_device_t osdev; + + htt_pdev_handle htt_pdev; + + struct { + int is_high_latency; + int host_addba; + int ll_pause_txq_limit; + int default_tx_comp_req; + } cfg; + + /* WDI subscriber's event list */ + wdi_event_subscribe **wdi_event_list; + +#ifndef REMOVE_PKT_LOG + /* Pktlog pdev */ + struct ol_pktlog_dev_t* pl_dev; +#endif /* #ifndef REMOVE_PKT_LOG */ + + enum ol_sec_type sec_types[htt_num_sec_types]; + /* standard frame type */ + enum wlan_frm_fmt frame_format; + enum htt_pkt_type htt_pkt_type; + +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + /* txrx encap/decap */ + u_int8_t sw_tx_encap; + u_int8_t sw_rx_decap; + u_int8_t target_tx_tran_caps; + u_int8_t target_rx_tran_caps; + /* llc process */ + u_int8_t sw_tx_llc_proc_enable; + u_int8_t sw_rx_llc_proc_enable; + /* A-MSDU */ + u_int8_t sw_subfrm_hdr_recovery_enable; + /* Protected Frame bit handling */ + u_int8_t sw_pf_proc_enable; +#endif + /* + * target tx credit - + * not needed for LL, but used for HL download scheduler to keep + * track of roughly how much space is available in the target for + * tx frames + */ + adf_os_atomic_t target_tx_credit; + adf_os_atomic_t orig_target_tx_credit; + + /* Peer mac address to staid mapping */ + struct ol_mac_addr mac_to_staid[WLAN_MAX_STA_COUNT + 3]; + + /* ol_txrx_vdev list */ + TAILQ_HEAD(, ol_txrx_vdev_t) vdev_list; + + /* peer ID to peer object map (array of pointers to peer objects) */ + struct ol_txrx_peer_t **peer_id_to_obj_map; + + struct { + unsigned mask; + unsigned idx_bits; + TAILQ_HEAD(, ol_txrx_peer_t) *bins; + } peer_hash; + + /* rx specific processing */ + struct { + struct { + TAILQ_HEAD(, ol_rx_reorder_t) waitlist; + u_int32_t timeout_ms; + } defrag; + struct { + int defrag_timeout_check; + int dup_check; + } flags; + + struct { + struct ol_tx_reorder_cat_timeout_t access_cats[TXRX_NUM_WMM_AC]; + } reorder_timeout; + adf_os_spinlock_t mutex; + } rx; + + /* rx proc function */ + void (*rx_opt_proc)( + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list); + + /* tx data delivery notification callback function */ + struct { + ol_txrx_data_tx_cb func; + void *ctxt; + } tx_data_callback; + + /* tx management delivery notification callback functions */ + struct { + struct { + ol_txrx_mgmt_tx_cb download_cb; + ol_txrx_mgmt_tx_cb ota_ack_cb; + void *ctxt; + } callbacks[OL_TXRX_MGMT_NUM_TYPES]; + } tx_mgmt; + + /* tx descriptor pool */ + struct { + u_int16_t pool_size; + u_int16_t num_free; + struct ol_tx_desc_list_elem_t *array; + struct ol_tx_desc_list_elem_t *freelist; + } tx_desc; + + struct { + int (*cmp)( + union htt_rx_pn_t *new, + union htt_rx_pn_t *old, + int is_unicast, + int opmode); + int len; + } rx_pn[htt_num_sec_types]; + + /* tx mutex */ + OL_TX_MUTEX_TYPE tx_mutex; + + /* + * peer ref mutex: + * 1. Protect peer object lookups until the returned peer object's + * reference count is incremented. + * 2. Provide mutex when accessing peer object lookup structures. + */ + OL_RX_MUTEX_TYPE peer_ref_mutex; + + /* + * last_real_peer_mutex: + * Protect lookups of any vdev's last_real_peer pointer until the + * reference count for the pointed-to peer object is incremented. + * This mutex could be in the vdev struct, but it's slightly simpler + * to have a single lock in the pdev struct. Since the lock is only + * held for an extremely short time, and since it's very unlikely for + * two vdev's to concurrently access the lock, there's no real + * benefit to having a per-vdev lock. + */ + OL_RX_MUTEX_TYPE last_real_peer_mutex; + + +#if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF + struct { + struct { + struct { + struct { + u_int64_t ppdus; + u_int64_t mpdus; + } normal; + struct { + /* + * mpdu_bad is general - + * replace it with the specific counters below + */ + u_int64_t mpdu_bad; + //u_int64_t mpdu_fcs; + //u_int64_t mpdu_duplicate; + //u_int64_t mpdu_pn_replay; + //u_int64_t mpdu_bad_sender; /* peer not found */ + //u_int64_t mpdu_flushed; + //u_int64_t msdu_defrag_mic_err; + u_int64_t msdu_mc_dup_drop; + } err; + } rx; + } priv; + struct ol_txrx_stats pub; + } stats; +#endif /* TXRX_STATS_LEVEL */ + +#if defined(ENABLE_RX_REORDER_TRACE) + struct { + u_int32_t mask; + u_int32_t idx; + u_int64_t cnt; +#define TXRX_RX_REORDER_TRACE_SIZE_LOG2 8 /* 256 entries */ + struct { + u_int16_t reorder_idx; + u_int16_t seq_num; + u_int8_t num_mpdus; + u_int8_t tid; + } *data; + } rx_reorder_trace; +#endif /* ENABLE_RX_REORDER_TRACE */ + +#if defined(ENABLE_RX_PN_TRACE) + struct { + u_int32_t mask; + u_int32_t idx; + u_int64_t cnt; +#define TXRX_RX_PN_TRACE_SIZE_LOG2 5 /* 32 entries */ + struct { + struct ol_txrx_peer_t *peer; + u_int32_t pn32; + u_int16_t seq_num; + u_int8_t unicast; + u_int8_t tid; + } *data; + } rx_pn_trace; +#endif /* ENABLE_RX_PN_TRACE */ + +#if defined(PERE_IP_HDR_ALIGNMENT_WAR) + bool host_80211_enable; +#endif + + /* + * tx_sched only applies for HL, but is defined unconditionally rather than + * only if defined(CONFIG_HL_SUPPORT). This is because the struct only + * occupies a few bytes, and to avoid the complexity of wrapping references + * to the struct members in "defined(CONFIG_HL_SUPPORT)" conditional + * compilation. + * If this struct gets expanded to a non-trivial size, then it should be + * conditionally compiled to only apply if defined(CONFIG_HL_SUPPORT). + */ + adf_os_spinlock_t tx_queue_spinlock; + struct { + enum ol_tx_scheduler_status tx_sched_status; + ol_tx_sched_handle scheduler; + struct ol_tx_frms_queue_t *last_used_txq; + } tx_sched; + /* + * tx_queue only applies for HL, but is defined unconditionally to avoid + * wrapping references to tx_queue in "defined(CONFIG_HL_SUPPORT)" + * conditional compilation. + */ + struct { + adf_os_atomic_t rsrc_cnt; + /* threshold_lo - when to start tx desc margin replenishment */ + u_int16_t rsrc_threshold_lo; + /* threshold_hi - where to stop during tx desc margin replenishment */ + u_int16_t rsrc_threshold_hi; + } tx_queue; + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) +#define OL_TXQ_LOG_SIZE 512 + adf_os_spinlock_t txq_log_spinlock; + struct { + int size; + int oldest_record_offset; + int offset; + int allow_wrap; + u_int32_t wrapped; + u_int8_t data[OL_TXQ_LOG_SIZE]; /* aligned to u_int32_t boundary */ + } txq_log; +#endif + +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS + adf_os_spinlock_t peer_stat_mutex; +#endif + + int rssi_update_shift; + int rssi_new_weight; +#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID + struct { + ol_txrx_local_peer_id_t pool[OL_TXRX_NUM_LOCAL_PEER_IDS+1]; + ol_txrx_local_peer_id_t freelist; + adf_os_spinlock_t lock; + ol_txrx_peer_handle map[OL_TXRX_NUM_LOCAL_PEER_IDS]; + } local_peer_ids; +#endif + +#ifdef QCA_COMPUTE_TX_DELAY +#ifdef QCA_COMPUTE_TX_DELAY_PER_TID +#define QCA_TX_DELAY_NUM_CATEGORIES \ + (OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES) +#else +#define QCA_TX_DELAY_NUM_CATEGORIES 1 +#endif + struct { + adf_os_spinlock_t mutex; + struct { + struct ol_tx_delay_data copies[2/*ping-pong updating*/]; + int in_progress_idx; + u_int32_t avg_start_time_ticks; + } cats[QCA_TX_DELAY_NUM_CATEGORIES]; + u_int32_t tx_compl_timestamp_ticks; + u_int32_t avg_period_ticks; + u_int32_t hist_internal_bin_width_mult; + u_int32_t hist_internal_bin_width_shift; + } tx_delay; + + u_int16_t packet_count[QCA_TX_DELAY_NUM_CATEGORIES]; + u_int16_t packet_loss_count[QCA_TX_DELAY_NUM_CATEGORIES]; + +#endif /* QCA_COMPUTE_TX_DELAY */ + + struct { + adf_os_spinlock_t mutex; + /* timer used to monitor the throttle "on" phase and "off" phase */ + adf_os_timer_t phase_timer; + /* timer used to send tx frames */ + adf_os_timer_t tx_timer; + /*This is the time in ms of the throttling window, it will include an + "on" phase and an "off" phase */ + u_int32_t throttle_period_ms; + /* Current throttle level set by the client ex. level 0, level 1, etc*/ + throttle_level current_throttle_level; + /* Index that points to the phase within the throttle period */ + throttle_phase current_throttle_phase; + /* Maximum number of frames to send to the target at one time */ + u_int32_t tx_threshold; + /* stores time in ms of on and off phase for each throttle level*/ + int throttle_time_ms[THROTTLE_LEVEL_MAX][THROTTLE_PHASE_MAX]; + /* mark as true if traffic is paused due to thermal throttling */ + a_bool_t is_paused; + } tx_throttle; + +#ifdef IPA_UC_OFFLOAD + ipa_uc_op_cb_type ipa_uc_op_cb; + void *osif_dev; +#endif /* IPA_UC_OFFLOAD */ + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + struct { + ol_tx_peer_bal_state enabled; + adf_os_spinlock_t mutex; + /* timer used to trigger more frames for bad peers */ + adf_os_timer_t peer_bal_timer; + /*This is the time in ms of the peer balance timer period */ + u_int32_t peer_bal_period_ms; + /*This is the txq limit */ + u_int32_t peer_bal_txq_limit; + /*This is the state of the peer balance timer */ + ol_tx_peer_bal_timer_state peer_bal_timer_state; + /*This is the counter about active peers which are under tx flow control */ + u_int32_t peer_num; + /*This is peer list which are under tx flow control */ + ol_tx_limit_peer_t limit_list[MAX_NO_PEERS_IN_LIMIT]; + /*This is threshold configurationl */ + tx_peer_threshold ctl_thresh[TXRX_IEEE11_MAX]; + } tx_peer_bal; +#endif /* CONFIG_Hl_SUPPORT && QCA_BAD_PEER_TX_FLOW_CL */ + + struct ol_tx_queue_group_t txq_grps[OL_TX_MAX_TXQ_GROUPS]; +#ifdef DEBUG_HL_LOGGING + adf_os_spinlock_t grp_stat_spinlock; + struct ol_tx_group_credit_stats_t grp_stats; +#endif + u_int8_t ocb_peer_valid; + struct ol_txrx_peer_t *ocb_peer; + int tid_to_ac[OL_TX_NUM_TIDS + OL_TX_VDEV_NUM_QUEUES]; + + unsigned int page_size; + unsigned int desc_mem_size; + unsigned int num_desc_pages; + unsigned int num_descs_per_page; + void **desc_pages; +}; + +struct ol_txrx_ocb_chan_info { + uint32_t chan_freq; + uint16_t disable_rx_stats_hdr:1; +}; + +struct ol_txrx_vdev_t { + /* pdev - the physical device that is the parent of this virtual device */ + struct ol_txrx_pdev_t *pdev; + + /* vdev_id - ID used to specify a particular vdev to the target */ + u_int8_t vdev_id; + + void *osif_dev; + + /* MAC address */ + union ol_txrx_align_mac_addr_t mac_addr; + + /* tx paused - NO LONGER NEEDED? */ + + /* node in the pdev's list of vdevs */ + TAILQ_ENTRY(ol_txrx_vdev_t) vdev_list_elem; + + /* ol_txrx_peer list */ + TAILQ_HEAD(peer_list_t, ol_txrx_peer_t) peer_list; + /* last real peer created for this vdev (not "self" pseudo-peer) */ + struct ol_txrx_peer_t *last_real_peer; + + /* transmit function used by this vdev */ + ol_txrx_tx_fp tx; + + /* receive function used by this vdev to hand rx frames to the OS shim */ + ol_txrx_rx_fp osif_rx; + + struct { + /* + * If the vdev object couldn't be deleted immediately because it still + * had some peer objects left, remember that a delete was requested, + * so it can be deleted once all its peers have been deleted. + */ + int pending; + /* + * Store a function pointer and a context argument to provide a + * notification for when the vdev is deleted. + */ + ol_txrx_vdev_delete_cb callback; + void *context; + } delete; + + /* safe mode control to bypass the encrypt and decipher process*/ + u_int32_t safemode; + + /* rx filter related */ + u_int32_t drop_unenc; + privacy_exemption privacy_filters[MAX_PRIVACY_FILTERS]; + u_int32_t num_filters; + + enum wlan_op_mode opmode; + +#ifdef QCA_IBSS_SUPPORT + /* ibss mode related */ + int16_t ibss_peer_num; /* the number of active peers */ + int16_t ibss_peer_heart_beat_timer; /* for detecting peer departure */ +#endif + +#if defined(CONFIG_HL_SUPPORT) + struct ol_tx_frms_queue_t txqs[OL_TX_VDEV_NUM_QUEUES]; +#endif + + struct { + struct { + adf_nbuf_t head; + adf_nbuf_t tail; + int depth; + } txq; + u_int32_t paused_reason; + adf_os_spinlock_t mutex; + adf_os_timer_t timer; + int max_q_depth; + bool is_q_paused; + bool is_q_timer_on; + u_int32_t q_pause_cnt; + u_int32_t q_unpause_cnt; + u_int32_t q_overflow_cnt; + } ll_pause; + a_bool_t disable_intrabss_fwd; + adf_os_atomic_t os_q_paused; + u_int16_t tx_fl_lwm; + u_int16_t tx_fl_hwm; + ol_txrx_tx_flow_control_fp osif_flow_control_cb; + +#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + union ol_txrx_align_mac_addr_t hl_tdls_ap_mac_addr; + bool hlTdlsFlag; +#endif +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + adf_os_atomic_t tx_desc_count; +#endif + u_int16_t wait_on_peer_id; + adf_os_comp_t wait_delete_comp; + + /* last channel change event recieved */ + struct { + bool is_valid; /* whether the rest of the members are valid */ + uint16_t mhz; + uint16_t band_center_freq1; + uint16_t band_center_freq2; + WLAN_PHY_MODE phy_mode; + } ocb_channel_event; + + /* Information about the schedules in the schedule */ + struct ol_txrx_ocb_chan_info *ocb_channel_info; + uint32_t ocb_channel_count; +}; + +struct ol_rx_reorder_array_elem_t { + adf_nbuf_t head; + adf_nbuf_t tail; +}; + +struct ol_rx_reorder_t { + u_int8_t win_sz; + u_int8_t win_sz_mask; + u_int8_t num_mpdus; + struct ol_rx_reorder_array_elem_t *array; + /* base - single rx reorder element used for non-aggr cases */ + struct ol_rx_reorder_array_elem_t base; +#if defined(QCA_SUPPORT_OL_RX_REORDER_TIMEOUT) + struct ol_rx_reorder_timeout_list_elem_t timeout; +#endif + /* only used for defrag right now */ + TAILQ_ENTRY(ol_rx_reorder_t) defrag_waitlist_elem; + u_int32_t defrag_timeout_ms; + /* get back to parent ol_txrx_peer_t when ol_rx_reorder_t is in a + * waitlist */ + u_int16_t tid; +}; + +enum { + txrx_sec_mcast = 0, + txrx_sec_ucast +}; + +typedef A_STATUS (*ol_tx_filter_func)(struct ol_txrx_msdu_info_t *tx_msdu_info); + +struct ol_txrx_peer_t { + struct ol_txrx_vdev_t *vdev; + + adf_os_atomic_t ref_cnt; + adf_os_atomic_t delete_in_progress; + + /* The peer state tracking is used for HL systems + * that don't support tx and rx filtering within the target. + * In such systems, the peer's state determines what kind of + * tx and rx filtering, if any, is done. + * This variable doesn't apply to LL systems, or to HL systems for + * which the target handles tx and rx filtering. However, it is + * simplest to declare and update this variable unconditionally, + * for all systems. + */ + enum ol_txrx_peer_state state; + ol_tx_filter_func tx_filter; + + /* peer ID(s) for this peer */ + u_int16_t peer_ids[MAX_NUM_PEER_ID_PER_PEER]; +#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID + u_int16_t local_id; +#endif + + union ol_txrx_align_mac_addr_t mac_addr; + + /* node in the vdev's list of peers */ + TAILQ_ENTRY(ol_txrx_peer_t) peer_list_elem; + /* node in the hash table bin's list of peers */ + TAILQ_ENTRY(ol_txrx_peer_t) hash_list_elem; + + /* + * per TID info - + * stored in separate arrays to avoid alignment padding mem overhead + */ + struct ol_rx_reorder_t tids_rx_reorder[OL_TXRX_NUM_EXT_TIDS]; + union htt_rx_pn_t tids_last_pn[OL_TXRX_NUM_EXT_TIDS]; + u_int8_t tids_last_pn_valid[OL_TXRX_NUM_EXT_TIDS]; + u_int16_t tids_next_rel_idx[OL_TXRX_NUM_EXT_TIDS]; + u_int16_t tids_last_seq[OL_TXRX_NUM_EXT_TIDS]; + uint16_t tids_mcast_last_seq[OL_TXRX_NUM_EXT_TIDS]; + + struct { + enum htt_sec_type sec_type; + u_int32_t michael_key[2]; /* relevant for TKIP */ + } security[2]; /* 0 -> multicast, 1 -> unicast */ + + /* + * rx proc function: this either is a copy of pdev's rx_opt_proc for + * regular rx processing, or has been redirected to a /dev/null discard + * function when peer deletion is in progress. + */ + void (*rx_opt_proc)(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, + adf_nbuf_t msdu_list); + +#if defined(CONFIG_HL_SUPPORT) + struct ol_tx_frms_queue_t txqs[OL_TX_NUM_TIDS]; +#endif + +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS + ol_txrx_peer_stats_t stats; +#endif + int16_t rssi_dbm; + + /* NAWDS Flag and Bss Peer bit */ + u_int16_t nawds_enabled:1, + bss_peer:1, + valid:1; + + /* QoS info*/ + u_int8_t qos_capable; + /* U-APSD tid mask */ + u_int8_t uapsd_mask; + /*flag indicating key installed*/ + u_int8_t keyinstalled; + + /* Bit to indicate if PN check is done in fw */ + adf_os_atomic_t fw_pn_check; + +#ifdef WLAN_FEATURE_11W + /* PN counter for Robust Management Frames */ + u_int64_t last_rmf_pn; + u_int32_t rmf_pn_replays; + u_int8_t last_rmf_pn_valid; +#endif + + /* Properties of the last received PPDU */ + int16_t last_pkt_rssi_cmb; + int16_t last_pkt_rssi[4]; + uint8_t last_pkt_legacy_rate; + uint8_t last_pkt_legacy_rate_sel; + uint32_t last_pkt_timestamp_microsec; + uint8_t last_pkt_timestamp_submicrosec; + uint32_t last_pkt_tsf; + uint8_t last_pkt_tid; + uint16_t last_pkt_center_freq; +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + u_int16_t tx_limit; + u_int16_t tx_limit_flag; + u_int16_t tx_pause_flag; +#endif +}; + +#endif /* _OL_TXRX_TYPES__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/txrx.h b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/txrx.h new file mode 100644 index 000000000000..7c132e76b360 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/txrx.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef TXRX_H +#define TXRX_H + +#include "vos_api.h" +#include "adf_nbuf.h" +#include "csrApi.h" +#include "sapApi.h" +#include "adf_nbuf.h" +#include "ol_txrx_osif_api.h" +#include "wlan_qct_tl.h" + +/* wait on peer deletion timeout value in milliseconds */ +#define PEER_DELETION_TIMEOUT 500 + +enum txrx_wmm_ac { + TXRX_WMM_AC_BE, + TXRX_WMM_AC_BK, + TXRX_WMM_AC_VI, + TXRX_WMM_AC_VO, + + TXRX_NUM_WMM_AC +}; + +struct txrx_rx_metainfo { + u8 up; + u16 dest_staid; +}; + +enum bt_frame_type { + /* BT-AMP packet of type data */ + TXRX_BT_AMP_TYPE_DATA = 0x0001, + + /* BT-AMP packet of type activity report */ + TXRX_BT_AMP_TYPE_AR = 0x0002, + + /* BT-AMP packet of type security frame */ + TXRX_BT_AMP_TYPE_SEC = 0x0003, + + /* BT-AMP packet of type Link Supervision request frame */ + TXRX_BT_AMP_TYPE_LS_REQ = 0x0004, + + /* BT-AMP packet of type Link Supervision reply frame */ + TXRX_BT_AMP_TYPE_LS_REP = 0x0005, + + /* Invalid Frame */ + TXRX_BAP_INVALID_FRAME + +}; + +enum wlan_ts_direction { + /* uplink */ + WLAN_TX_DIR = 0, + + /* downlink */ + WLAN_RX_DIR = 1, + + /*bidirectional*/ + WLAN_BI_DIR = 2, +}; + +enum wlan_sta_state { + /* Transition in this state made upon creation*/ + WLAN_STA_INIT = 0, + + /* Transition happens after Assoc success if second level authentication + is needed*/ + WLAN_STA_CONNECTED, + + /* Transition happens when second level auth is successful and keys are + properly installed */ + WLAN_STA_AUTHENTICATED, + + /* Transition happens when connectivity is lost*/ + WLAN_STA_DISCONNECTED, + + WLAN_STA_MAX_STATE +}; + +struct wlan_txrx_stats { + /* Define various txrx stats here*/ +}; + +struct ol_txrx_vdev_t; + +VOS_STATUS wlan_register_mgmt_client(void *pdev_txrx, + VOS_STATUS (*rx_mgmt)(void *g_vosctx, + void *buf)); + +typedef void (*ol_txrx_vdev_delete_cb)(void *context); + +/** + * @typedef ol_txrx_tx_fp + * @brief top-level transmit function + */ +typedef adf_nbuf_t +(*ol_txrx_tx_fp)(struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu_list); + +typedef void +(*ol_txrx_mgmt_tx_cb)(void *ctxt, adf_nbuf_t tx_mgmt_frm, int had_error); + +/* If RSSI realm is changed, send notification to Clients, SME, HDD */ +typedef VOS_STATUS (*wlan_txrx_rssi_cross_thresh) (void *adapter, u8 rssi, + void *usr_ctx, v_S7_t avg_rssi); + +struct wlan_txrx_ind_req { + u16 msgType; // message type is same as the request type + u16 msgLen; // length of the entire request + u8 sessionId; //sme Session Id + u8 rssiNotification; + u8 avgRssi; + void *tlCallback; + void *pAdapter; + void *pUserCtxt; +}; + +struct wlan_txrx_config_param { + u32 uDelayedTriggerFrmInt; + u8 uMinFramesProcThres; +}; + +/* Rx callback registered with txrx */ +typedef int (*wlan_txrx_cb_type)( void *g_vosctx, adf_nbuf_t buf, u8 sta_id, + struct txrx_rx_metainfo *rx_meta_info); + +static inline int wlan_txrx_get_rssi(void *g_vosctx, u8 sta_id, v_S7_t *rssi) +{ + return 0; +} + +static inline int wlan_txrx_enable_uapsd_ac(void *g_vosctx, u8 sta_id, + enum txrx_wmm_ac ac, u8 tid, u8 up, + u32 srv_int, u32 suspend_int, + enum wlan_ts_direction ts_dir) +{ + return 0; +} + +static inline int wlan_txrx_disable_uapsd_ac(void *g_vosctx, u8 sta_id, + enum txrx_wmm_ac ac) +{ + return 0; +} + +static inline int wlan_change_sta_state(void *g_vosctx, u8 sta_id, + enum wlan_sta_state state) +{ + return 0; +} + +static inline int wlan_deregister_mgmt_client(void *g_vosctx) +{ + return 0; +} + +static inline void wlan_assoc_failed(u8 staid) +{ +} + +static inline int wlan_get_ap_stats(void *g_vosctx, tSap_SoftapStats *buf, + bool reset) +{ + return 0; +} + +static inline int wlan_get_txrx_stats(void *g_vosctx, struct wlan_txrx_stats *stats, + u8 sta_id) +{ + return 0; +} + +static inline int wlan_txrx_update_rssi_bmps(void *g_vosctx, u8 sta_id, + v_S7_t rssi) +{ + return 0; +} + +static inline int wlan_txrx_deregister_rssi_indcb(void *g_vosctx, + v_S7_t rssi_val, + u8 trigger_event, + wlan_txrx_rssi_cross_thresh cb, + int mod_id) +{ + return 0; +} + +static inline int wlan_txrx_register_rssi_indcb(void *g_vosctx, + v_S7_t rssi_val, + u8 trigger_event, + wlan_txrx_rssi_cross_thresh cb, + int mod_id, void *usr_ctx) +{ + return 0; +} + +/* FIXME: The following stubs will be removed eventually */ +static inline int wlan_txrx_mc_process_msg(void *g_vosctx, vos_msg_t *msg) +{ + return 0; +} + +static inline int wlan_txrx_tx_process_msg(void *g_vosctx, vos_msg_t *msg) +{ + return 0; +} + +static inline void wlan_txrx_mc_free_msg(void *g_vosctx, vos_msg_t *msg) +{ +} +static inline void wlan_txrx_tx_free_msg(void *g_vosctx, vos_msg_t *msg) +{ +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_internal.h b/drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_internal.h new file mode 100644 index 000000000000..dec50d6ea25f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_internal.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef EPPING_INTERNAL_H +#define EPPING_INTERNAL_H +/**=========================================================================== + + \file epping_internal.h + + \brief Linux epping internal head file + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif +#include +#include "htc_api.h" +#include "htc_packet.h" +#include "epping_test.h" +#include + +#define EPPING_LOG_MASK (1< + +#define WLAN_EPPING_ENABLE_BIT (1 << 8) +#define WLAN_EPPING_IRQ_BIT (1 << 9) +#define WLAN_EPPING_FW_UART_BIT (1 << 10) +#define WLAN_IS_EPPING_ENABLED(x) (x & WLAN_EPPING_ENABLE_BIT) +#define WLAN_IS_EPPING_IRQ(x) (x & WLAN_EPPING_IRQ_BIT) +#define WLAN_IS_EPPING_FW_UART(x) (x & WLAN_EPPING_FW_UART_BIT) + +/* epping_main signatures */ +int epping_driver_init(int con_mode, vos_wake_lock_t *g_wake_lock, + char *pwlan_module_name); +void epping_driver_exit(v_CONTEXT_t pVosContext); +void epping_exit(v_CONTEXT_t pVosContext); +int epping_wlan_startup(struct device *dev, v_VOID_t *hif_sc); +#endif /* end #ifndef EPPING_MAIN_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_test.h b/drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_test.h new file mode 100644 index 000000000000..a39d50743429 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/inc/epping_test.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* This file contains shared definitions for the host/target endpoint ping test */ + +#ifndef EPPING_TEST_H +#define EPPING_TEST_H + +#ifndef ATH_TARGET +#include "athstartpack.h" +#endif + + /* alignment to 4-bytes */ +#define EPPING_ALIGNMENT_PAD (((sizeof(HTC_FRAME_HDR) + 3) & (~0x3)) - sizeof(HTC_FRAME_HDR)) + +#ifndef A_OFFSETOF +#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field)) +#endif + +#define EPPING_RSVD_FILL 0xCC + +#define HCI_RSVD_EXPECTED_PKT_TYPE_RECV_OFFSET 7 + +typedef PREPACK struct { + A_UINT8 _HCIRsvd[8]; /* reserved for HCI packet header (GMBOX) testing */ + A_UINT8 StreamEcho_h; /* stream no. to echo this packet on (filled by host) */ + A_UINT8 StreamEchoSent_t; /* stream no. packet was echoed to (filled by target) + When echoed: StreamEchoSent_t == StreamEcho_h */ + A_UINT8 StreamRecv_t; /* stream no. that target received this packet on (filled by target) */ + A_UINT8 StreamNo_h; /* stream number to send on (filled by host) */ + A_UINT8 Magic_h[4]; /* magic number to filter for this packet on the host*/ + A_UINT8 _rsvd[6]; /* reserved fields that must be set to a "reserved" value + since this packet maps to a 14-byte ethernet frame we want + to make sure ethertype field is set to something unknown */ + + A_UINT8 _pad[2]; /* padding for alignment */ + A_UINT8 TimeStamp[8]; /* timestamp of packet (host or target) */ + A_UINT32 HostContext_h; /* 4 byte host context, target echos this back */ + A_UINT32 SeqNo; /* sequence number (set by host or target) */ + A_UINT16 Cmd_h; /* ping command (filled by host) */ + A_UINT16 CmdFlags_h; /* optional flags */ + A_UINT8 CmdBuffer_h[8]; /* buffer for command (host -> target) */ + A_UINT8 CmdBuffer_t[8]; /* buffer for command (target -> host) */ + A_UINT16 DataLength; /* length of data */ + A_UINT16 DataCRC; /* 16 bit CRC of data */ + A_UINT16 HeaderCRC; /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */ +} POSTPACK EPPING_HEADER; + +#define EPPING_PING_MAGIC_0 0xAA +#define EPPING_PING_MAGIC_1 0x55 +#define EPPING_PING_MAGIC_2 0xCE +#define EPPING_PING_MAGIC_3 0xEC + +#define IS_EPPING_PACKET(pPkt) (((pPkt)->Magic_h[0] == EPPING_PING_MAGIC_0) && \ + ((pPkt)->Magic_h[1] == EPPING_PING_MAGIC_1) && \ + ((pPkt)->Magic_h[2] == EPPING_PING_MAGIC_2) && \ + ((pPkt)->Magic_h[3] == EPPING_PING_MAGIC_3)) + +#define SET_EPPING_PACKET_MAGIC(pPkt) { (pPkt)->Magic_h[0] = EPPING_PING_MAGIC_0; \ + (pPkt)->Magic_h[1] = EPPING_PING_MAGIC_1; \ + (pPkt)->Magic_h[2] = EPPING_PING_MAGIC_2; \ + (pPkt)->Magic_h[3] = EPPING_PING_MAGIC_3;} + +#define CMD_FLAGS_DATA_CRC (1 << 0) /* DataCRC field is valid */ +#define CMD_FLAGS_DELAY_ECHO (1 << 1) /* delay the echo of the packet */ +#define CMD_FLAGS_NO_DROP (1 << 2) /* do not drop at HTC layer no matter what the stream is */ + +#define IS_EPING_PACKET_NO_DROP(pPkt) ((pPkt)->CmdFlags_h & CMD_FLAGS_NO_DROP) + +#define EPPING_CMD_ECHO_PACKET 1 /* echo packet test */ +#define EPPING_CMD_RESET_RECV_CNT 2 /* reset recv count */ +#define EPPING_CMD_CAPTURE_RECV_CNT 3 /* fetch recv count, 4-byte count returned in CmdBuffer_t */ +#define EPPING_CMD_NO_ECHO 4 /* non-echo packet test (tx-only) */ +#define EPPING_CMD_CONT_RX_START 5 /* continous RX packets, parameters are in CmdBuffer_h */ +#define EPPING_CMD_CONT_RX_STOP 6 /* stop continuous RX packet transmission */ + + /* test command parameters may be no more than 8 bytes */ +typedef PREPACK struct { + A_UINT16 BurstCnt; /* number of packets to burst together (for HTC 2.1 testing) */ + A_UINT16 PacketLength; /* length of packet to generate including header */ + A_UINT16 Flags; /* flags */ + +#define EPPING_CONT_RX_DATA_CRC (1 << 0) /* Add CRC to all data */ +#define EPPING_CONT_RX_RANDOM_DATA (1 << 1) /* randomize the data pattern */ +#define EPPING_CONT_RX_RANDOM_LEN (1 << 2) /* randomize the packet lengths */ +#define EPPING_CONT_RX_NO_DATA_FILL (1 << 3) /* target will not fill buffers */ + A_UINT16 Context; /* flags */ + +} POSTPACK EPPING_CONT_RX_PARAMS; + +#define EPPING_HDR_CRC_OFFSET A_OFFSETOF(EPPING_HEADER,StreamNo_h) +#define EPPING_HDR_BYTES_CRC (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(A_UINT16))) + +#define HCI_TRANSPORT_STREAM_NUM 16 /* this number is higher than the define WMM AC classes so we + can use this to distinguish packets */ + +#ifndef ATH_TARGET +#include "athendpack.h" +#endif + +#endif /* EPPING_TEST_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_helper.c b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_helper.c new file mode 100644 index 000000000000..d8787e5eaa67 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_helper.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*======================================================================== + + \file epping_main.c + + \brief WLAN End Point Ping test tool implementation + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "epping_main.h" +#include "epping_internal.h" + +int epping_cookie_init(epping_context_t*pEpping_ctx) +{ + A_UINT32 i, j; + + pEpping_ctx->cookie_list = NULL; + pEpping_ctx->cookie_count = 0; + for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) { + pEpping_ctx->s_cookie_mem[i] = + vos_mem_malloc(sizeof(struct epping_cookie)*MAX_COOKIE_SLOT_SIZE); + if (pEpping_ctx->s_cookie_mem == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: no mem for cookie (idx = %d)", __func__, i); + goto error; + } + vos_mem_zero(pEpping_ctx->s_cookie_mem[i], + sizeof(struct epping_cookie)*MAX_COOKIE_SLOT_SIZE); + } + adf_os_spinlock_init(&pEpping_ctx->cookie_lock); + + for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) { + struct epping_cookie *cookie_mem = pEpping_ctx->s_cookie_mem[i]; + for (j = 0; j < MAX_COOKIE_SLOT_SIZE; j++) { + epping_free_cookie(pEpping_ctx, &cookie_mem[j]); + } + } + return 0; +error: + for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) { + if (pEpping_ctx->s_cookie_mem[i]) { + vos_mem_free(pEpping_ctx->s_cookie_mem[i]); + pEpping_ctx->s_cookie_mem[i] = NULL; + } + } + return -ENOMEM; +} + +/* cleanup cookie queue */ +void epping_cookie_cleanup(epping_context_t*pEpping_ctx) +{ + int i; + adf_os_spin_lock_bh(&pEpping_ctx->cookie_lock); + pEpping_ctx->cookie_list = NULL; + pEpping_ctx->cookie_count = 0; + adf_os_spin_unlock_bh(&pEpping_ctx->cookie_lock); + for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) { + if (pEpping_ctx->s_cookie_mem[i]) { + vos_mem_free(pEpping_ctx->s_cookie_mem[i]); + pEpping_ctx->s_cookie_mem[i] = NULL; + } + } +} + +void epping_free_cookie(epping_context_t*pEpping_ctx, + struct epping_cookie *cookie) +{ + adf_os_spin_lock_bh(&pEpping_ctx->cookie_lock); + cookie->next = pEpping_ctx->cookie_list; + pEpping_ctx->cookie_list = cookie; + pEpping_ctx->cookie_count++; + adf_os_spin_unlock_bh(&pEpping_ctx->cookie_lock); +} + +struct epping_cookie *epping_alloc_cookie(epping_context_t*pEpping_ctx) +{ + struct epping_cookie *cookie; + + adf_os_spin_lock_bh(&pEpping_ctx->cookie_lock); + cookie = pEpping_ctx->cookie_list; + if(cookie != NULL) + { + pEpping_ctx->cookie_list = cookie->next; + pEpping_ctx->cookie_count--; + } + adf_os_spin_unlock_bh(&pEpping_ctx->cookie_lock); + return cookie; +} + +void epping_get_dummy_mac_addr(tSirMacAddr macAddr) +{ + macAddr[0] = 69; /* E */ + macAddr[1] = 80; /* P */ + macAddr[2] = 80; /* P */ + macAddr[3] = 73; /* I */ + macAddr[4] = 78; /* N */ + macAddr[5] = 71; /* G */ +} + +void epping_hex_dump(void *data, int buf_len, const char *str) +{ + char *buf = (char *)data; + int i; + + printk("%s: E, %s\n", __func__, str); + for (i=0; (i+7)< buf_len; i+=8) + { + printk("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[i], + buf[i+1], + buf[i+2], + buf[i+3], + buf[i+4], + buf[i+5], + buf[i+6], + buf[i+7]); + } + + // Dump the bytes in the last line + for (; i < buf_len; i++) + { + printk("%02x ", buf[i]); + } + printk("\n%s: X %s\n", __func__, str); +} + + +void *epping_get_adf_ctx(void) +{ + VosContextType *pVosContext = NULL; + adf_os_device_t *pAdfCtx; + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + pAdfCtx = vos_get_context(VOS_MODULE_ID_ADF, pVosContext); + return pAdfCtx; +} + +void epping_log_packet(epping_adapter_t *pAdapter, + EPPING_HEADER *eppingHdr, int ret, const char *str) +{ + if (eppingHdr->Cmd_h & EPPING_LOG_MASK) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: cmd = %d, seqNo = %u, flag = 0x%x, ret = %d, " + "txCount = %lu, txDrop = %lu, txBytes = %lu," + "rxCount = %lu, rxDrop = %lu, rxBytes = %lu\n", + str, eppingHdr->Cmd_h, eppingHdr->SeqNo, + eppingHdr->CmdFlags_h, ret, + pAdapter->stats.tx_packets, + pAdapter->stats.tx_dropped, + pAdapter->stats.tx_bytes, + pAdapter->stats.rx_packets, + pAdapter->stats.rx_dropped, + pAdapter->stats.rx_bytes); + } +} + +void epping_log_stats(epping_adapter_t *pAdapter, const char *str) +{ + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: txCount = %lu, txDrop = %lu, tx_bytes = %lu, " + "rxCount = %lu, rxDrop = %lu, rx_bytes = %lu, tx_acks = %u\n", + str, + pAdapter->stats.tx_packets, + pAdapter->stats.tx_dropped, + pAdapter->stats.tx_bytes, + pAdapter->stats.rx_packets, + pAdapter->stats.rx_dropped, + pAdapter->stats.rx_bytes, + pAdapter->pEpping_ctx->total_tx_acks); +} + +void epping_set_kperf_flag(epping_adapter_t *pAdapter, + HTC_ENDPOINT_ID eid, + A_UINT8 kperf_flag) +{ + pAdapter->pEpping_ctx->kperf[eid] = kperf_flag; + pAdapter->pEpping_ctx->kperf_num_rx_recv[eid] = 0; + pAdapter->pEpping_ctx->kperf_num_tx_acks[eid] = 0; +} + +#ifdef HIF_PCI + +static int epping_tx_thread_fn(void *data) +{ + int i; + epping_poll_t *epping_poll = data; + + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: arg = %p", __func__, data); + while (!epping_poll->done) { + down(&epping_poll->sem); + adf_os_atomic_dec(&epping_poll->atm); + if (epping_poll->skb && !epping_poll->done) { + for (i = 0; i < MAX_TX_PKT_DUP_NUM; i++) { + epping_tx_dup_pkt((epping_adapter_t *)epping_poll->arg, + epping_poll->eid, epping_poll->skb); + udelay(WLAN_EPPING_DELAY_TIMEOUT_US); + } + } + } + return 0; +} + +#define EPPING_TX_THREAD "EPPINGTX" +void epping_register_tx_copier(HTC_ENDPOINT_ID eid, epping_context_t *pEpping_ctx) +{ + epping_poll_t *epping_poll = &pEpping_ctx->epping_poll[eid]; + epping_poll->eid = eid; + epping_poll->arg = pEpping_ctx->epping_adapter; + epping_poll->done = false; + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: eid = %d, arg = %p", + __func__, eid, pEpping_ctx->epping_adapter); + sema_init(&epping_poll->sem, 0); + adf_os_atomic_init(&epping_poll->atm); + epping_poll->inited = true; + epping_poll->pid = kthread_create(epping_tx_thread_fn, + epping_poll, EPPING_TX_THREAD); + wake_up_process(epping_poll->pid); +} +void epping_unregister_tx_copier(HTC_ENDPOINT_ID eid, epping_context_t *pEpping_ctx) +{ + epping_poll_t *epping_poll; + + if (eid < 0 || eid >= EPPING_MAX_NUM_EPIDS ) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: invalid eid = %d", + __func__, eid); + return; + } + + epping_poll = &pEpping_ctx->epping_poll[eid]; + + epping_poll->done = true; + if (epping_poll->inited) { + epping_tx_copier_schedule(pEpping_ctx, eid, NULL); + msleep(EPPING_KTID_KILL_WAIT_TIME_MS); + } + if (epping_poll->skb) + adf_nbuf_free(epping_poll->skb); + OS_MEMZERO(epping_poll, sizeof(epping_poll_t)); + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: eid = %d", + __func__, eid); +} +void epping_tx_copier_schedule(epping_context_t *pEpping_ctx, HTC_ENDPOINT_ID eid, adf_nbuf_t skb) +{ + epping_poll_t *epping_poll = &pEpping_ctx->epping_poll[eid]; + + if (!epping_poll->skb && skb) { + epping_poll->skb = adf_nbuf_copy(skb); + } + if (adf_os_atomic_read(&epping_poll->atm) < EPPING_MAX_WATER_MARK) { + adf_os_atomic_inc(&epping_poll->atm); + up(&epping_poll->sem); + } +} +#endif /* HIF_PCI */ diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c new file mode 100644 index 000000000000..574cacc3e2a1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*======================================================================== + + \file epping_main.c + + \brief WLAN End Point Ping test tool implementation + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bmi.h" +#include "ol_fw.h" +#include "ol_if_athvar.h" +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#elif defined(HIF_SDIO) +#include "if_ath_sdio.h" +#endif +#include "epping_main.h" +#include "epping_internal.h" + +#ifdef TIMER_MANAGER +#define TIMER_MANAGER_STR " +TIMER_MANAGER" +#else +#define TIMER_MANAGER_STR "" +#endif + +#ifdef MEMORY_DEBUG +#define MEMORY_DEBUG_STR " +MEMORY_DEBUG" +#else +#define MEMORY_DEBUG_STR "" +#endif + +#if defined(HIF_PCI) || defined(HIF_USB) +extern int hif_register_driver(void); +extern void hif_unregister_driver(void); +#endif + +/**--------------------------------------------------------------------------- + + \brief epping_driver_init() - End point ping driver Init Function + + This is the driver entry point - called in different timeline depending + on whether the driver is statically or dynamically linked + + \param - con_mode connection mode + + \return - 0 for success, negative for failure + +----------------------------------------------------------------------------*/ +int epping_driver_init(int con_mode, vos_wake_lock_t *g_wake_lock, + char *pwlan_module_name) +{ + int ret = 0; + unsigned long rc; + epping_context_t *pEpping_ctx = NULL; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); + +#ifdef TIMER_MANAGER + vos_timer_manager_init(); +#endif +#ifdef MEMORY_DEBUG + vos_mem_init(); +#endif + + pEpping_ctx = vos_mem_malloc(sizeof(epping_context_t)); + if (pEpping_ctx == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: No memory", __func__); + ret = -ENOMEM; + goto error1; + } + vos_mem_zero(pEpping_ctx, sizeof(epping_context_t)); + pEpping_ctx->g_wake_lock = g_wake_lock; + pEpping_ctx->con_mode = con_mode; + pEpping_ctx->pwlan_module_name = pwlan_module_name; + + status = vos_preOpen(&pEpping_ctx->pVosContext); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Failed to preOpen VOSS", __func__); + ret = -1; + goto error1; + } + + /* save epping_context in VOSS */ + ((VosContextType *)(pEpping_ctx->pVosContext))->pHDDContext = + (v_VOID_t*)pEpping_ctx; + +#ifdef HIF_SDIO +#define WLAN_WAIT_TIME_WLANSTART 10000 +#else +#define WLAN_WAIT_TIME_WLANSTART 2000 +#endif + init_completion(&pEpping_ctx->wlan_start_comp); + ret = hif_register_driver(); + if (!ret) { + rc = wait_for_completion_timeout( + &pEpping_ctx->wlan_start_comp, + msecs_to_jiffies(WLAN_WAIT_TIME_WLANSTART)); + if (!rc) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: timed-out waiting for hif_register_driver", __func__); + ret = -1; + } else + ret = 0; + } + if (ret) + { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: %s driver Initialization failed", + __func__, pEpping_ctx->pwlan_module_name); + hif_unregister_driver(); + vos_preClose(&pEpping_ctx->pVosContext); + ret = -ENODEV; + vos_mem_free(pEpping_ctx); + +#ifdef MEMORY_DEBUG + vos_mem_exit(); +#endif +#ifdef TIMER_MANAGER + vos_timer_exit(); +#endif + return ret; + } else { + pr_info("%s: %s driver loaded\n", + __func__, pEpping_ctx->pwlan_module_name); + return 0; + } +error1: + if (pEpping_ctx) { + vos_mem_free(pEpping_ctx); + pEpping_ctx = NULL; + } +#ifdef MEMORY_DEBUG + vos_mem_exit(); +#endif +#ifdef TIMER_MANAGER + vos_timer_exit(); +#endif + return ret; +} + +void epping_exit(v_CONTEXT_t pVosContext) +{ + epping_context_t *pEpping_ctx; + VosContextType *gpVosContext; + + pEpping_ctx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (pEpping_ctx == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: error: pEpping_ctx = NULL", + __func__); + return; + } + gpVosContext = pEpping_ctx->pVosContext; + if (pVosContext == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: error: pVosContext = NULL", + __func__); + return; + } + if (pEpping_ctx->epping_adapter) { + epping_destroy_adapter(pEpping_ctx->epping_adapter); + pEpping_ctx->epping_adapter = NULL; + } + hif_disable_isr(gpVosContext->pHIFContext); + hif_reset_soc(gpVosContext->pHIFContext); + HTCStop(gpVosContext->htc_ctx); + HTCDestroy(gpVosContext->htc_ctx); + gpVosContext->htc_ctx = NULL; +#ifdef HIF_PCI + { + int i; + for (i = 0; i < EPPING_MAX_NUM_EPIDS; i++) { + epping_unregister_tx_copier(i, pEpping_ctx); + } + } +#endif /* HIF_PCI */ + epping_cookie_cleanup(pEpping_ctx); + vos_mem_free(pEpping_ctx); +} + +void epping_driver_exit(v_CONTEXT_t pVosContext) +{ + epping_context_t *pEpping_ctx; + + pr_info("%s: unloading driver\n", __func__); + + pEpping_ctx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + + if(!pEpping_ctx) + { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: module exit called before probe",__func__); + } + else + { +#ifdef QCA_PKT_PROTO_TRACE + vos_pkt_proto_trace_close(); +#endif /* QCA_PKT_PROTO_TRACE */ + //pHddCtx->isUnloadInProgress = TRUE; + vos_set_unload_in_progress(TRUE); + vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); + } + hif_unregister_driver(); + vos_preClose( &pVosContext ); +#ifdef MEMORY_DEBUG + vos_mem_exit(); +#endif +#ifdef TIMER_MANAGER + vos_timer_exit(); +#endif + pr_info("%s: driver unloaded\n", __func__); +} + +static void epping_target_suspend_acknowledge(void *context) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + epping_context_t *pEpping_ctx = vos_get_context(VOS_MODULE_ID_HDD, + vos_context); + int wow_nack = *((int *)context); + + if (NULL == pEpping_ctx) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: epping_ctx is NULL", __func__); + return; + } + /* EPPING_TODO: do we need wow_nack? */ + pEpping_ctx->wow_nack = wow_nack; +} + +int epping_wlan_startup(struct device *parent_dev, v_VOID_t *hif_sc) +{ + int ret = 0; + epping_context_t *pEpping_ctx = NULL; + VosContextType *pVosContext = NULL; + HTC_INIT_INFO htcInfo; + struct ol_softc *scn; + tSirMacAddr adapter_macAddr; + adf_os_device_t adf_ctx; + + EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if(pVosContext == NULL) + { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Failed vos_get_global_context", __func__); + ret = -1; + return ret; + } + + pEpping_ctx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if(pEpping_ctx == NULL) + { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Failed to get pEpping_ctx", __func__); + ret = -1; + return ret; + } + pEpping_ctx->parent_dev = (void *)parent_dev; + epping_get_dummy_mac_addr(adapter_macAddr); + + ((VosContextType*)pVosContext)->pHIFContext = hif_sc; + + /* store target type and target version info in hdd ctx */ + pEpping_ctx->target_type = ((struct ol_softc *)hif_sc)->target_type; + + /* Initialize the timer module */ + vos_timer_module_init(); + + scn = vos_get_context(VOS_MODULE_ID_HIF, pVosContext); + if (!scn) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: scn is null!", __func__); + return -1; + } + scn->enableuartprint = 0; + scn->enablefwlog = 0; + + /* Initialize BMI and Download firmware */ + if (bmi_download_firmware(scn)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: BMI failed to download target", __func__); + BMICleanup(scn); + return -1; + } + + EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: bmi_download_firmware done", __func__); + + htcInfo.pContext = pVosContext->pHIFContext; + htcInfo.TargetFailure = ol_target_failure; + htcInfo.TargetSendSuspendComplete = epping_target_suspend_acknowledge; + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, pVosContext); + + /* Create HTC */ + pVosContext->htc_ctx = HTCCreate(htcInfo.pContext, &htcInfo, adf_ctx); + if (!pVosContext->htc_ctx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to Create HTC", __func__); + BMICleanup(scn); + return -1; + } + pEpping_ctx->HTCHandle = vos_get_context(VOS_MODULE_ID_HTC, pVosContext); + if (pEpping_ctx->HTCHandle == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: HTCHandle is NULL", __func__); + return -1; + } + scn->htc_handle = pEpping_ctx->HTCHandle; + + HIFClaimDevice(scn->hif_hdl, scn); + + if (bmi_done(scn)) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto error_end; + } + /* start HIF */ + if (HTCWaitTarget(scn->htc_handle) != A_OK) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: HTCWaitTarget error", __func__); + goto error_end; + } + EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: HTC ready", __func__); + + ret = epping_connect_service(pEpping_ctx); + if (ret != 0) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: HTCWaitTargetdone", __func__); + goto error_end; + } + if (HTCStart(pEpping_ctx->HTCHandle) != A_OK) { + goto error_end; + } + EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: HTC started", __func__); + + /* init the tx cookie resource */ + ret = epping_cookie_init(pEpping_ctx); + if (ret == 0) { + pEpping_ctx->epping_adapter = epping_add_adapter(pEpping_ctx, + adapter_macAddr, + WLAN_HDD_INFRA_STATION); + } + if (ret < 0 || pEpping_ctx->epping_adapter == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: epping_add_adaptererror error", __func__); + HTCStop(pEpping_ctx->HTCHandle); + epping_cookie_cleanup(pEpping_ctx); + goto error_end; + } +#ifdef HIF_PCI + { + int i; + for (i = 0; i < EPPING_MAX_NUM_EPIDS; i++) { + epping_register_tx_copier(i, pEpping_ctx); + } + } +#endif /* HIF_PCI */ + EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__); + complete(&pEpping_ctx->wlan_start_comp); + return ret; + +error_end: + HTCDestroy(pVosContext->htc_ctx); + pVosContext->htc_ctx = NULL; + BMICleanup(scn); + return -1; +} diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_rx.c b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_rx.c new file mode 100644 index 000000000000..679cf2502c18 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_rx.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*======================================================================== + + \file epping_main.c + + \brief WLAN End Point Ping test tool implementation + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "epping_main.h" +#include "epping_internal.h" +#include "epping_test.h" + +#define AR6000_MAX_RX_BUFFERS 16 +#define AR6000_BUFFER_SIZE 1664 +#define AR6000_MIN_HEAD_ROOM 64 + +static bool enb_rx_dump = 0; + +#ifdef HIF_SDIO +void epping_refill(void *ctx, HTC_ENDPOINT_ID Endpoint) +{ + epping_context_t *pEpping_ctx = (epping_context_t *)ctx; + void *osBuf; + int RxBuffers; + int buffersToRefill; + HTC_PACKET *pPacket; + HTC_PACKET_QUEUE queue; + + buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - + HTCGetNumRecvBuffers(pEpping_ctx->HTCHandle, Endpoint); + + if (buffersToRefill <= 0) { + /* fast return, nothing to fill */ + return; + } + + INIT_HTC_PACKET_QUEUE(&queue); + + EPPING_LOG(VOS_TRACE_LEVEL_INFO, + "%s: providing htc with %d buffers at eid=%d\n", + __func__, buffersToRefill, Endpoint); + + for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { + osBuf = adf_nbuf_alloc(NULL, AR6000_BUFFER_SIZE, + AR6000_MIN_HEAD_ROOM, 4, FALSE); + if (NULL == osBuf) { + break; + } + /* the HTC packet wrapper is at the head of the reserved area + * in the skb */ + pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf)); + /* set re-fill info */ + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf, + adf_nbuf_data(osBuf), + AR6000_BUFFER_SIZE,Endpoint); + SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket,osBuf); + /* add to queue */ + HTC_PACKET_ENQUEUE(&queue,pPacket); + } + + if (!HTC_QUEUE_EMPTY(&queue)) { + /* add packets */ + HTCAddReceivePktMultiple(pEpping_ctx->HTCHandle, &queue); + } +} +#endif /* HIF_SDIO */ + +void epping_rx(void *ctx, HTC_PACKET *pPacket) +{ + epping_context_t *pEpping_ctx = (epping_context_t *)ctx; + epping_adapter_t *pAdapter = pEpping_ctx->epping_adapter; + struct net_device* dev = pAdapter->dev; + A_STATUS status = pPacket->Status; + HTC_ENDPOINT_ID eid = pPacket->Endpoint; + struct sk_buff *pktSkb = (struct sk_buff *)pPacket->pPktContext; + + EPPING_LOG(VOS_TRACE_LEVEL_INFO, + "%s: pAdapter = 0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d", + __func__, pAdapter, eid, pktSkb, pPacket->pBuffer, + pPacket->ActualLength, status); + + if (status != A_OK) { + if (status != A_ECANCELED) { + printk("%s: RX ERR (%d) \n", __func__, status); + } + adf_nbuf_free(pktSkb); + return; + } + + /* deliver to up layer */ + if (pktSkb) + { + EPPING_HEADER *eppingHdr = (EPPING_HEADER *)adf_nbuf_data(pktSkb); + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PULL(pktSkb, EPPING_ALIGNMENT_PAD); + } + if (enb_rx_dump) + epping_hex_dump((void *)adf_nbuf_data(pktSkb), + pktSkb->len, __func__); + pktSkb->dev = dev; + if ((pktSkb->dev->flags & IFF_UP) == IFF_UP) { + pktSkb->protocol = eth_type_trans(pktSkb, pktSkb->dev); + ++pAdapter->stats.rx_packets; + pAdapter->stats.rx_bytes += pktSkb->len; + if (pEpping_ctx->kperf[eid] == true) { + switch (eppingHdr->Cmd_h) { + case EPPING_CMD_CONT_RX_STOP: + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: RXPERF: EID = %d, num_pkts_received = %u\n", + __func__, eid, pEpping_ctx->kperf_num_rx_recv[eid]); + OS_MEMCPY(eppingHdr->CmdBuffer_t, + &pEpping_ctx->kperf_num_rx_recv[eid], + sizeof(unsigned int)); + epping_set_kperf_flag(pAdapter, eid, false); + netif_rx_ni(pktSkb); + break; + case 0: /* RXPERF hard code 0 in FW */ + adf_nbuf_free(pktSkb); + pEpping_ctx->kperf_num_rx_recv[eid]++; + if ((pAdapter->stats.rx_packets % EPPING_STATS_LOG_COUNT) == 0) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: total_rx_pkts = %lu", + __func__, pAdapter->stats.rx_packets); + } + break; + case EPPING_CMD_CAPTURE_RECV_CNT: + epping_set_kperf_flag(pAdapter, eid, false); + netif_rx_ni(pktSkb); + break; + default: + netif_rx_ni(pktSkb); + pEpping_ctx->kperf_num_rx_recv[eid]++; + if ((pAdapter->stats.rx_packets % EPPING_STATS_LOG_COUNT) == 0) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: total_rx_pkts = %lu", + __func__, pAdapter->stats.rx_packets); + } + break; + } + } else { + netif_rx_ni(pktSkb); + if ((pAdapter->stats.rx_packets % EPPING_STATS_LOG_COUNT) == 0) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: total_rx_pkts = %lu", + __func__, pAdapter->stats.rx_packets); + } + } + } else { + ++pAdapter->stats.rx_dropped; + adf_nbuf_free(pktSkb); + } + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_tx.c b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_tx.c new file mode 100644 index 000000000000..b0c862fbd72a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_tx.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*======================================================================== + + \file epping_main.c + + \brief WLAN End Point Ping test tool implementation + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "epping_main.h" +#include "epping_internal.h" +#include "epping_test.h" + +#define TX_RETRY_TIMEOUT_IN_MS 1 + +static bool enb_tx_dump = 0; + +void epping_tx_dup_pkt(epping_adapter_t *pAdapter, + HTC_ENDPOINT_ID eid, adf_nbuf_t skb) +{ + struct epping_cookie * cookie = NULL; + int skb_len, ret; + adf_nbuf_t new_skb; + + cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); + if (cookie == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: epping_alloc_cookie returns no resource\n", __func__); + return; + } + new_skb = adf_nbuf_copy(skb); + if (!new_skb) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: adf_nbuf_copy returns no resource\n", __func__); + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + return; + } + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, adf_nbuf_data(skb), adf_nbuf_len(new_skb), eid, 0); + SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, new_skb); + skb_len = (int)adf_nbuf_len(new_skb); + /* send the packet */ + ret = HTCSendPkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); + if (ret != A_OK) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: HTCSendPkt failed, ret = %d\n", __func__, ret); + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + adf_nbuf_free(new_skb); + return; + } + pAdapter->stats.tx_bytes += skb_len; + ++pAdapter->stats.tx_packets; + if (((pAdapter->stats.tx_packets + + pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 && + (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) { + epping_log_stats(pAdapter, __func__); + } +} +static int epping_tx_send_int(adf_nbuf_t skb, + epping_adapter_t *pAdapter) +{ + EPPING_HEADER *eppingHdr = (EPPING_HEADER *)adf_nbuf_data(skb); + HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; + struct epping_cookie * cookie = NULL; + A_UINT8 ac = 0; + A_STATUS ret = A_OK; + int skb_len; + EPPING_HEADER tmpHdr = *eppingHdr; + + /* allocate resource for this packet */ + cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); + /* no resource */ + if (cookie == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: epping_alloc_cookie returns no resource\n", __func__); + return -1; + } + + if (enb_tx_dump) + epping_hex_dump((void *)eppingHdr, skb->len, __func__); + /* + * a quirk of linux, the payload of the frame is 32-bit aligned and thus + * the addition of the HTC header will mis-align the start of the HTC + * frame, so we add some padding which will be stripped off in the target + */ + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD); + } + /* prepare ep/HTC information */ + ac = eppingHdr->StreamNo_h; + eid = pAdapter->pEpping_ctx->EppingEndpoint[ac]; + if (eid < 0 || eid >= EPPING_MAX_NUM_EPIDS) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: invalid eid = %d, ac = %d\n", __func__, eid, ac); + return -1; + } + if (tmpHdr.Cmd_h == EPPING_CMD_RESET_RECV_CNT || + tmpHdr.Cmd_h == EPPING_CMD_CONT_RX_START) { + epping_set_kperf_flag(pAdapter, eid, tmpHdr.CmdBuffer_t[0]); + } + if (pAdapter->pEpping_ctx->kperf[eid]) { + switch (tmpHdr.Cmd_h) { + case EPPING_CMD_NO_ECHO: +#ifdef HIF_PCI + epping_tx_copier_schedule(pAdapter->pEpping_ctx, eid, skb); +#endif /* HIF_PCI */ + break; + default: + break; + } + } + if (pAdapter->pEpping_ctx->kperf[eid] && + tmpHdr.Cmd_h == EPPING_CMD_NO_ECHO) { + epping_tx_dup_pkt(pAdapter, eid, skb); + } + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, adf_nbuf_data(skb), adf_nbuf_len(skb), eid, 0); + SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, skb); + skb_len = skb->len; + /* send the packet */ + ret = HTCSendPkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); + epping_log_packet(pAdapter, &tmpHdr, ret, __func__); + if (ret != A_OK) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: HTCSendPkt failed, status = %d\n", __func__, ret); + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + return -1; + } + pAdapter->stats.tx_bytes += skb_len; + ++pAdapter->stats.tx_packets; + if (((pAdapter->stats.tx_packets + + pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 && + (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) { + epping_log_stats(pAdapter, __func__); + } + + return 0; +} + +void epping_tx_timer_expire(epping_adapter_t *pAdapter) +{ + adf_nbuf_t nodrop_skb; + + EPPING_LOG(VOS_TRACE_LEVEL_INFO, "%s: queue len: %d\n", __func__, + adf_nbuf_queue_len(&pAdapter->nodrop_queue)); + + if (!adf_nbuf_queue_len(&pAdapter->nodrop_queue)) { + /* nodrop queue is empty so no need to arm timer */ + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + return; + } + + /* try to flush nodrop queue */ + while ((nodrop_skb = adf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { + if (epping_tx_send_int(nodrop_skb, pAdapter)) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: nodrop: %p xmit fail in timer\n", __func__, nodrop_skb); + /* fail to xmit so put the nodrop packet to the nodrop queue */ + adf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, nodrop_skb); + break; + } else { + EPPING_LOG(VOS_TRACE_LEVEL_INFO, + "%s: nodrop: %p xmit ok in timer\n", __func__, nodrop_skb); + } + } + + /* if nodrop queue is not empty, continue to arm timer */ + if (nodrop_skb) { + adf_os_spin_lock_bh(&pAdapter->data_lock); + /* if nodrop queue is not empty, continue to arm timer */ + if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) { + pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING; + adf_os_timer_mod(&pAdapter->epping_timer, TX_RETRY_TIMEOUT_IN_MS); + } + adf_os_spin_unlock_bh(&pAdapter->data_lock); + } else { + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + } +} + +int epping_tx_send(adf_nbuf_t skb, epping_adapter_t *pAdapter) +{ + adf_nbuf_t nodrop_skb; + EPPING_HEADER *eppingHdr; + A_UINT8 ac = 0; + + eppingHdr = (EPPING_HEADER *)adf_nbuf_data(skb); + + if (!IS_EPPING_PACKET(eppingHdr)) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Recived non endpoint ping packets\n", __func__); + /* no packet to send, cleanup */ + adf_nbuf_free(skb); + return -ENOMEM; + } + + /* the stream ID is mapped to an access class */ + ac = eppingHdr->StreamNo_h; + /* hard coded two ep ids */ + if (ac != 0 && ac != 1) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: ac %d is not mapped to mboxping service\n", __func__, ac); + adf_nbuf_free(skb); + return -ENOMEM; + } + + /* + * some EPPING packets cannot be dropped no matter what access class + * it was sent on. A special care has been taken: + * 1. when there is no TX resource, queue the control packets to + * a special queue + * 2. when there is TX resource, send the queued control packets first + * and then other packets + * 3. a timer launches to check if there is queued control packets and + * flush them + */ + + /* check the nodrop queue first */ + while ((nodrop_skb = adf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { + if (epping_tx_send_int(nodrop_skb, pAdapter)) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: nodrop: %p xmit fail\n", __func__, nodrop_skb); + /* fail to xmit so put the nodrop packet to the nodrop queue */ + adf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, nodrop_skb); + /* no cookie so free the current skb */ + goto tx_fail; + } else { + EPPING_LOG(VOS_TRACE_LEVEL_INFO, + "%s: nodrop: %p xmit ok\n", __func__, nodrop_skb); + } + } + + /* send the original packet */ + if (epping_tx_send_int(skb, pAdapter)) + goto tx_fail; + + return 0; + +tx_fail: + if (!IS_EPING_PACKET_NO_DROP(eppingHdr)) { + /* allow to drop the skb so drop it */ + adf_nbuf_free(skb); + ++pAdapter->stats.tx_dropped; + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Tx skb %p dropped, stats.tx_dropped = %ld\n", + __func__, skb, pAdapter->stats.tx_dropped); + return -ENOMEM; + } else { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: nodrop: %p queued\n", __func__, skb); + adf_nbuf_queue_add(&pAdapter->nodrop_queue, skb); + adf_os_spin_lock_bh(&pAdapter->data_lock); + if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) { + pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING; + adf_os_timer_mod(&pAdapter->epping_timer, TX_RETRY_TIMEOUT_IN_MS); + } + adf_os_spin_unlock_bh(&pAdapter->data_lock); + } + + return 0; +} + +#ifdef HIF_SDIO +HTC_SEND_FULL_ACTION epping_tx_queue_full(void *Context, + HTC_PACKET *pPacket) +{ + epping_context_t *pEpping_ctx = (epping_context_t *)Context; + epping_adapter_t *pAdapter = pEpping_ctx->epping_adapter; + HTC_SEND_FULL_ACTION action = HTC_SEND_FULL_KEEP; + netif_stop_queue(pAdapter->dev); + return action; +} +#endif /* HIF_SDIO */ +void epping_tx_complete_multiple(void *ctx, + HTC_PACKET_QUEUE *pPacketQueue) +{ + epping_context_t *pEpping_ctx = (epping_context_t *)ctx; + epping_adapter_t *pAdapter = pEpping_ctx->epping_adapter; + struct net_device* dev = pAdapter->dev; + A_STATUS status; + HTC_ENDPOINT_ID eid; + adf_nbuf_t pktSkb; + struct epping_cookie *cookie; + A_BOOL flushing = FALSE; + adf_nbuf_queue_t skb_queue; + HTC_PACKET *htc_pkt; + + adf_nbuf_queue_init(&skb_queue); + + adf_os_spin_lock_bh(&pAdapter->data_lock); + + while (!HTC_QUEUE_EMPTY(pPacketQueue)) { + htc_pkt = HTC_PACKET_DEQUEUE(pPacketQueue); + if (htc_pkt == NULL) + break; + status=htc_pkt->Status; + eid=htc_pkt->Endpoint; + pktSkb=GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt); + cookie = htc_pkt->pPktContext; + + ASSERT(pktSkb); + ASSERT(htc_pkt->pBuffer == adf_nbuf_data(pktSkb)); + + /* add this to the list, use faster non-lock API */ + adf_nbuf_queue_add(&skb_queue,pktSkb); + + if (A_SUCCESS(status)) { + ASSERT(htc_pkt->ActualLength == adf_nbuf_len(pktSkb)); + } + EPPING_LOG(VOS_TRACE_LEVEL_INFO, + "%s skb=%p data=%p len=0x%x eid=%d ", + __func__, pktSkb, htc_pkt->pBuffer, + htc_pkt->ActualLength, eid); + + if (A_FAILED(status)) { + if (status == A_ECANCELED) { + /* a packet was flushed */ + flushing = TRUE; + } + if (status != A_NO_RESOURCE) { + printk("%s() -TX ERROR, status: 0x%x\n", __func__, + status); + } + } else { + EPPING_LOG(VOS_TRACE_LEVEL_INFO, "%s: OK\n", __func__); + flushing = FALSE; + } + + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + } + + adf_os_spin_unlock_bh(&pAdapter->data_lock); + + /* free all skbs in our local list */ + while (adf_nbuf_queue_len(&skb_queue)) { + /* use non-lock version */ + pktSkb = adf_nbuf_queue_remove(&skb_queue); + if (pktSkb == NULL) + break; + adf_nbuf_free(pktSkb); + pEpping_ctx->total_tx_acks++; + } + + if (!flushing) { + netif_wake_queue(dev); + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_txrx.c b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_txrx.c new file mode 100644 index 000000000000..44f505242582 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_txrx.c @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*======================================================================== + + \file epping_main.c + + \brief WLAN End Point Ping test tool implementation + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MSM_PLATFORM) && defined(HIF_PCI) +#include +#endif /* MSM_PLATFORM */ +#include +#include +#include +#include +#include +#include "epping_main.h" +#include "epping_internal.h" + +static int epping_start_adapter(epping_adapter_t *pAdapter); +static void epping_stop_adapter(epping_adapter_t *pAdapter); + +static void epping_timer_expire(void *data) +{ + struct net_device *dev = (struct net_device *) data; + epping_adapter_t *pAdapter; + + if (dev == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: netdev = NULL", __func__); + return; + } + + pAdapter = netdev_priv(dev); + if (pAdapter == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: adapter = NULL", __func__); + return; + } + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + epping_tx_timer_expire(pAdapter); +} + +static int epping_ndev_open(struct net_device *dev) +{ + epping_adapter_t *pAdapter; + int ret = 0; + + pAdapter = netdev_priv(dev); + epping_start_adapter(pAdapter); + return ret; +} + +static int epping_ndev_stop(struct net_device *dev) +{ + epping_adapter_t *pAdapter; + int ret = 0; + + pAdapter = netdev_priv(dev); + if (NULL == pAdapter) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + ret = -ENODEV; + goto end; + } + epping_stop_adapter(pAdapter); +end: + return ret; +} + +static void epping_ndev_uninit (struct net_device *dev) +{ + epping_adapter_t *pAdapter; + + pAdapter = netdev_priv(dev); + if (NULL == pAdapter) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + goto end; + } + epping_stop_adapter(pAdapter); +end: + return; +} + +void epping_tx_queue_timeout(struct net_device *dev) +{ + epping_adapter_t *pAdapter; + + pAdapter = netdev_priv(dev); + if (NULL == pAdapter) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + goto end; + } + + EPPING_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Transmission timeout occurred, pAdapter->started= %d", + __func__, pAdapter->started); + + /* Getting here implies we disabled the TX queues + * for too long. Since this is epping + * (not because of disassociation or low resource scenarios), + * try to restart the queue + */ + if (pAdapter->started) + netif_wake_queue(dev); +end: + return; + +} + +int epping_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + epping_adapter_t *pAdapter; + int ret = 0; + + pAdapter = netdev_priv(dev); + if (NULL == pAdapter) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + ret = -ENODEV; + goto end; + } + ret = epping_tx_send(skb, pAdapter); +end: + return ret; +} + +struct net_device_stats* epping_get_stats(struct net_device *dev) +{ + epping_adapter_t *pAdapter = netdev_priv(dev); + + if ( NULL == pAdapter ) + { + EPPING_LOG(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter = NULL", __func__); + return NULL; + } + + return &pAdapter->stats; +} + +int epping_ndev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + epping_adapter_t *pAdapter; + int ret = 0; + + pAdapter = netdev_priv(dev); + if (NULL == pAdapter) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + ret = -ENODEV; + goto end; + } + if (dev != pAdapter->dev) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter/dev inconsistency", __func__); + ret = -ENODEV; + goto end; + } + + if ((!ifr) || (!ifr->ifr_data)) { + ret = -EINVAL; + goto end; + } + + + switch (cmd) { + case (SIOCDEVPRIVATE + 1): + EPPING_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: do not support ioctl %d (SIOCDEVPRIVATE + 1)", + __func__, cmd); + break; + default: + EPPING_LOG(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d", + __func__, cmd); + ret = -EINVAL; + break; + } + +end: + return ret; +} + +static int epping_set_mac_address(struct net_device *dev, void *addr) +{ + epping_adapter_t *pAdapter = netdev_priv(dev); + struct sockaddr *psta_mac_addr = addr; + vos_mem_copy(&pAdapter->macAddressCurrent, + psta_mac_addr->sa_data, ETH_ALEN); + vos_mem_copy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN); + return 0; +} + +static void epping_stop_adapter(epping_adapter_t *pAdapter) +{ + if (pAdapter && pAdapter->started) { + EPPING_LOG(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + pAdapter->started = false; +#if defined(MSM_PLATFORM) && defined(HIF_PCI) && defined(CONFIG_CNSS) + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_LOW); +#endif + } +} + +static int epping_start_adapter(epping_adapter_t *pAdapter) +{ + if (!pAdapter) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: pAdapter= NULL\n", __func__); + return -1; + } + if (!pAdapter->started) { +#if defined(MSM_PLATFORM) && defined(HIF_PCI) && defined(CONFIG_CNSS) + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_HIGH); +#endif + netif_carrier_on(pAdapter->dev); + EPPING_LOG(LOG1, FL("Enabling queues")); + netif_tx_start_all_queues(pAdapter->dev); + pAdapter->started = true; + } else { + EPPING_LOG(VOS_TRACE_LEVEL_WARN, + "%s: pAdapter %p already started\n", __func__, pAdapter); + } + return 0; +} +static int epping_register_adapter(epping_adapter_t *pAdapter) +{ + int ret = 0; + + if ((ret = register_netdev(pAdapter->dev)) != 0) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: unable to register device\n", pAdapter->dev->name); + } else { + pAdapter->registered = true; + } + return ret; +} + +static void epping_unregister_adapter(epping_adapter_t *pAdapter) +{ + if (pAdapter) { + epping_stop_adapter(pAdapter); + if (pAdapter->registered) { + unregister_netdev(pAdapter->dev); + pAdapter->registered = false; + } + } else { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: pAdapter = NULL, unable to unregister device\n", + __func__); + } +} + +void epping_destroy_adapter(epping_adapter_t *pAdapter) +{ + struct net_device *dev = NULL; + epping_context_t *pEpping_ctx; + + if (!pAdapter || !pAdapter->pEpping_ctx) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: pAdapter = NULL\n", __func__); + return; + } + + dev = pAdapter->dev; + pEpping_ctx= pAdapter->pEpping_ctx; + epping_unregister_adapter(pAdapter); + + adf_os_spinlock_destroy(&pAdapter->data_lock); + adf_os_timer_free(&pAdapter->epping_timer); + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + + while (adf_nbuf_queue_len(&pAdapter->nodrop_queue)) { + adf_nbuf_t tmp_nbuf = NULL; + tmp_nbuf = adf_nbuf_queue_remove(&pAdapter->nodrop_queue); + if (tmp_nbuf) + adf_nbuf_free(tmp_nbuf); + } + + free_netdev(dev); + if (!pEpping_ctx) + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: pEpping_ctx = NULL\n", __func__); + else + pEpping_ctx->epping_adapter = NULL; +} + +static struct net_device_ops epping_drv_ops = { + .ndo_open = epping_ndev_open, + .ndo_stop = epping_ndev_stop, + .ndo_uninit = epping_ndev_uninit, + .ndo_start_xmit = epping_hard_start_xmit, + .ndo_tx_timeout = epping_tx_queue_timeout, + .ndo_get_stats = epping_get_stats, + .ndo_do_ioctl = epping_ndev_ioctl, + .ndo_set_mac_address = epping_set_mac_address, + .ndo_select_queue = NULL, + }; + +#define EPPING_TX_QUEUE_MAX_LEN 128 /* need to be power of 2 */ + +epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx, + tSirMacAddr macAddr, device_mode_t device_mode) +{ + struct net_device *dev; + epping_adapter_t *pAdapter; + + dev = alloc_netdev(sizeof(epping_adapter_t), + "wifi%d", +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) || defined(WITH_BACKPORTS) + NET_NAME_UNKNOWN, +#endif + ether_setup); + if (dev == NULL) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Cannot allocate epping_adapter_t\n", __func__); + return NULL; + } + + pAdapter = netdev_priv(dev); + vos_mem_zero(pAdapter, sizeof(*pAdapter)); + pAdapter->dev = dev; + pAdapter->pEpping_ctx = pEpping_ctx; + pAdapter->device_mode = device_mode; /* station, SAP, etc */ + vos_mem_copy(dev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr)); + vos_mem_copy(pAdapter->macAddressCurrent.bytes, + macAddr, sizeof(tSirMacAddr)); + adf_os_spinlock_init(&pAdapter->data_lock); + adf_nbuf_queue_init(&pAdapter->nodrop_queue); + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + adf_os_timer_init(epping_get_adf_ctx(), &pAdapter->epping_timer, + epping_timer_expire, dev, ADF_DEFERRABLE_TIMER); + dev->type = ARPHRD_IEEE80211; + dev->netdev_ops = &epping_drv_ops; + dev->watchdog_timeo = 5 * HZ; /* XXX */ + dev->tx_queue_len = ATH_TXBUF-1; /* 1 for mgmt frame */ + if (epping_register_adapter(pAdapter) == 0) { + EPPING_LOG(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + netif_carrier_off(dev); + return pAdapter; + } else { + epping_destroy_adapter(pAdapter); + return NULL; + } +} + +int epping_connect_service(epping_context_t *pEpping_ctx) +{ + int status, i; + HTC_SERVICE_CONNECT_REQ connect; + HTC_SERVICE_CONNECT_RESP response; + + vos_mem_zero(&connect, sizeof(connect)); + vos_mem_zero(&response, sizeof(response)); + + /* these fields are the same for all service endpoints */ + connect.EpCallbacks.pContext = pEpping_ctx; + connect.EpCallbacks.EpTxCompleteMultiple = epping_tx_complete_multiple; + connect.EpCallbacks.EpRecv = epping_rx; + /* epping_tx_complete use Multiple version */ + connect.EpCallbacks.EpTxComplete = NULL; + connect.MaxSendQueueDepth = 64; + +#ifdef HIF_SDIO + connect.EpCallbacks.EpRecvRefill = epping_refill; + connect.EpCallbacks.EpSendFull = + epping_tx_queue_full /* ar6000_tx_queue_full */; +#elif defined(HIF_USB) || defined(HIF_PCI) + connect.EpCallbacks.EpRecvRefill = NULL /* provided by HIF */; + connect.EpCallbacks.EpSendFull = NULL /* provided by HIF */; + /* disable flow control for hw flow control */ + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; +#endif + + /* connect to service */ + connect.ServiceID = WMI_DATA_BE_SVC; + status = HTCConnectService(pEpping_ctx->HTCHandle, &connect, &response); + if (status != EOK) { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "Failed to connect to Endpoint Ping BE service status:%d \n", + status); + return -1;; + } else { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "eppingtest BE endpoint:%d\n", response.Endpoint); + } + pEpping_ctx->EppingEndpoint[0] = response.Endpoint; + +#if defined(HIF_PCI) || defined(HIF_USB) + connect.ServiceID = WMI_DATA_BK_SVC; + status = HTCConnectService(pEpping_ctx->HTCHandle, + &connect, &response); + if (status != EOK) + { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "Failed to connect to Endpoint Ping BK service status:%d \n", + status); + return -1;; + } else { + EPPING_LOG(VOS_TRACE_LEVEL_FATAL, + "eppingtest BK endpoint:%d\n", response.Endpoint); + } + pEpping_ctx->EppingEndpoint[1] = response.Endpoint; + /* Since we do not create other two SVC use BK endpoint + * for rest ACs (2, 3) */ + for (i = 2; i < EPPING_MAX_NUM_EPIDS; i++) { + pEpping_ctx->EppingEndpoint[i] = response.Endpoint; + } +#else + /* we only use one endpoint for high latenance bus. + * Map all AC's EPIDs to the same endpoint ID returned by HTC */ + for (i = 0; i < EPPING_MAX_NUM_EPIDS; i++) { + pEpping_ctx->EppingEndpoint[i] = response.Endpoint; + } +#endif + return 0; +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h new file mode 100644 index 000000000000..45284c7dae17 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _QC_SAP_IOCTL_H_ +#define _QC_SAP_IOCTL_H_ + +/* + * QCSAP ioctls. + */ + +/* + * Max size of optional information elements. We artificially + * constrain this; it's limited only by the max frame size (and + * the max parameter size of the wireless extensions). + */ +#define QCSAP_MAX_OPT_IE 256 +#define QCSAP_MAX_WSC_IE 256 +#define QCSAP_MAX_GET_STA_INFO 512 + +typedef struct sSSID +{ + u_int8_t length; + u_int8_t ssId[32]; +} tSSID; + +typedef struct sSSIDInfo +{ + tSSID ssid; + u_int8_t ssidHidden; +}tSSIDInfo; + +typedef enum { + eQC_DOT11_MODE_ALL = 0, + eQC_DOT11_MODE_ABG = 0x0001, //11a/b/g only, no HT, no proprietary + eQC_DOT11_MODE_11A = 0x0002, + eQC_DOT11_MODE_11B = 0x0004, + eQC_DOT11_MODE_11G = 0x0008, + eQC_DOT11_MODE_11N = 0x0010, + eQC_DOT11_MODE_11G_ONLY = 0x0020, + eQC_DOT11_MODE_11N_ONLY = 0x0040, + eQC_DOT11_MODE_11B_ONLY = 0x0080, + eQC_DOT11_MODE_11A_ONLY = 0x0100, + //This is for WIFI test. It is same as eWNIAPI_MAC_PROTOCOL_ALL except when it starts IBSS in 11B of 2.4GHz + //It is for CSR internal use + eQC_DOT11_MODE_AUTO = 0x0200, + +} tQcPhyMode; + +#define QCSAP_ADDR_LEN 6 + +typedef u_int8_t qcmacaddr[QCSAP_ADDR_LEN]; + +struct qc_mac_acl_entry { + qcmacaddr addr; + int vlan_id; +}; + +typedef enum { + eQC_AUTH_TYPE_OPEN_SYSTEM, + eQC_AUTH_TYPE_SHARED_KEY, + eQC_AUTH_TYPE_AUTO_SWITCH +} eQcAuthType; + +typedef enum { + eQC_WPS_BEACON_IE, + eQC_WPS_PROBE_RSP_IE, + eQC_WPS_ASSOC_RSP_IE +} eQCWPSType; + + +/* + * Retrieve the WPA/RSN information element for an associated station. + */ +struct sQcSapreq_wpaie { + u_int8_t wpa_ie[QCSAP_MAX_OPT_IE]; + u_int8_t wpa_macaddr[QCSAP_ADDR_LEN]; +}; + +/* + * Retrieve the WSC information element for an associated station. + */ +struct sQcSapreq_wscie { + u_int8_t wsc_macaddr[QCSAP_ADDR_LEN]; + u_int8_t wsc_ie[QCSAP_MAX_WSC_IE]; +}; + + +/* + * Retrieve the WPS PBC Probe Request IEs. + */ +typedef struct sQcSapreq_WPSPBCProbeReqIES { + u_int8_t macaddr[QCSAP_ADDR_LEN]; + u_int16_t probeReqIELen; + u_int8_t probeReqIE[512]; +} sQcSapreq_WPSPBCProbeReqIES_t ; + +/* + * Channel List Info + */ + +typedef struct +{ + v_U8_t num_channels; + v_U8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +}tChannelListInfo, *tpChannelListInfo; + + +#ifdef __linux__ +/* + * Wireless Extensions API, private ioctl interfaces. + * + * NB: Even-numbered ioctl numbers have set semantics and are privileged! + * (regardless of the incorrect comment in wireless.h!) + */ + +#define QCSAP_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) +#define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1) +/* (SIOCIWFIRSTPRIV+2) is unused */ +#define QCSAP_IOCTL_SET_NONE_GET_THREE (SIOCIWFIRSTPRIV+3) +#define WE_GET_TSF 1 +#define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4) +#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5) +#define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6) +#define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV+7) +#define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV+8) +#define QCSAP_IOCTL_GET_CHANNEL (SIOCIWFIRSTPRIV+9) +#define QCSAP_IOCTL_ASSOC_STA_MACADDR (SIOCIWFIRSTPRIV+10) +#define QCSAP_IOCTL_DISASSOC_STA (SIOCIWFIRSTPRIV+11) +#define QCSAP_IOCTL_AP_STATS (SIOCIWFIRSTPRIV+12) +/* Private ioctls and their sub-ioctls */ +#define QCSAP_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 13) +#define QCSAP_GET_STATS 1 +#define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV+14) + +#define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV+15) +#define WE_SET_WLAN_DBG 1 +/* 2 is unused */ +#define WE_SET_SAP_CHANNELS 3 + +#define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV+16) +#define QCSAP_IOCTL_SET_CHANNEL_RANGE (SIOCIWFIRSTPRIV+17) +#define WE_LOG_DUMP_CMD 1 + +#define WE_P2P_NOA_CMD 2 +//IOCTL to configure MCC params +#define WE_MCC_CONFIG_CREDENTIAL 3 +#define WE_MCC_CONFIG_PARAMS 4 +#define WE_UNIT_TEST_CMD 7 +#ifdef MEMORY_DEBUG +#define WE_MEM_TRACE_DUMP 11 +#endif + +#define QCSAP_IOCTL_MODIFY_ACL (SIOCIWFIRSTPRIV+18) +#define QCSAP_IOCTL_GET_CHANNEL_LIST (SIOCIWFIRSTPRIV+19) +#define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV+20) +#define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV+21) +#define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV+22) +#define QCSAP_IOCTL_DATAPATH_SNAP_SHOT (SIOCIWFIRSTPRIV+23) +#define QCSAP_IOCTL_GET_INI_CFG (SIOCIWFIRSTPRIV+25) +#define QCSAP_IOCTL_SET_INI_CFG (SIOCIWFIRSTPRIV+26) +#define QCSAP_IOCTL_WOWL_CONFIG_PTRN (SIOCIWFIRSTPRIV+27) +#define WE_WOWL_ADD_PTRN 1 +#define WE_WOWL_DEL_PTRN 2 +#define QCSAP_IOCTL_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28) +#ifdef DEBUG +#define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1 +#endif + +#define MAX_VAR_ARGS 7 + +#define QCSAP_IOCTL_PRIV_GET_RSSI (SIOCIWFIRSTPRIV + 29) + +#define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31) + +#define QCSAP_IOCTL_MAX_STR_LEN 1024 + + +#define RC_2_RATE_IDX(_rc) ((_rc) & 0x7) +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) + +#define RC_2_RATE_IDX_11AC(_rc) ((_rc) & 0xf) +#define HT_RC_2_STREAMS_11AC(_rc) ((((_rc) & 0x30) >> 4) + 1) + + +enum { + QCSAP_PARAM_MAX_ASSOC = 1, + QCSAP_PARAM_GET_WLAN_DBG, + QCSAP_PARAM_CLR_ACL = 4, + QCSAP_PARAM_ACL_MODE, + QCSAP_PARAM_HIDE_SSID, + QCSAP_PARAM_AUTO_CHANNEL, + QCSAP_PARAM_SET_MC_RATE = 8, + QCSAP_PARAM_SET_TXRX_FW_STATS, + QCSAP_PARAM_SET_MCC_CHANNEL_LATENCY, + QCSAP_PARAM_SET_MCC_CHANNEL_QUOTA, + QCSAP_DBGLOG_LOG_LEVEL, + QCSAP_DBGLOG_VAP_ENABLE, + QCSAP_DBGLOG_VAP_DISABLE, + QCSAP_DBGLOG_MODULE_ENABLE, + QCSAP_DBGLOG_MODULE_DISABLE, + QCSAP_DBGLOG_MOD_LOG_LEVEL, + QCSAP_DBGLOG_TYPE, + QCSAP_DBGLOG_REPORT_ENABLE, + QCASAP_TXRX_FWSTATS_RESET, + QCSAP_PARAM_RTSCTS, + QCASAP_SET_11N_RATE, + QCASAP_SET_VHT_RATE, + QCASAP_SHORT_GI, + QCSAP_SET_AMPDU, + QCSAP_SET_AMSDU, + QCSAP_GTX_HT_MCS, + QCSAP_GTX_VHT_MCS, + QCSAP_GTX_USRCFG, + QCSAP_GTX_THRE, + QCSAP_GTX_MARGIN, + QCSAP_GTX_STEP, + QCSAP_GTX_MINTPC, + QCSAP_GTX_BWMASK, +#ifdef QCA_PKT_PROTO_TRACE + QCASAP_SET_DEBUG_LOG, +#endif + QCASAP_SET_TM_LEVEL, + QCASAP_SET_DFS_IGNORE_CAC, + QCASAP_GET_DFS_NOL, + QCASAP_SET_DFS_NOL, + QCSAP_PARAM_SET_CHANNEL_CHANGE, + QCASAP_SET_DFS_TARGET_CHNL, + QCASAP_SET_RADAR_CMD, + QCSAP_GET_ACL, + QCASAP_TX_CHAINMASK_CMD, + QCASAP_RX_CHAINMASK_CMD, + QCASAP_NSS_CMD, + QCSAP_IPA_UC_STAT, + QCASAP_SET_PHYMODE, + QCASAP_GET_TEMP_CMD, + QCSAP_GET_FW_STATUS, + QCASAP_DUMP_STATS, + QCASAP_CLEAR_STATS, + QCSAP_CAP_TSF, + QCSAP_GET_TSF, + QCASAP_PARAM_LDPC, + QCASAP_PARAM_TX_STBC, + QCASAP_PARAM_RX_STBC, + QCASAP_SET_RADAR_DBG, +}; + +int iw_softap_get_channel_list(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +#endif /* __linux__ */ + +#endif /*_QC_SAP_IOCTL_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h new file mode 100644 index 000000000000..7a965e9cd2f8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined(WLAN_HDD_ASSOC_H__) +#define WLAN_HDD_ASSOC_H__ +#include +#include + +#define HDD_MAX_NUM_IBSS_STA ( 32 ) +#ifdef FEATURE_WLAN_TDLS +#define HDD_MAX_NUM_TDLS_STA ( 8 ) +#define HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN ( 1 ) +#define TDLS_STA_INDEX_VALID(staId) \ + (((staId) >= 1) && ((staId) < 0xFF)) +#endif +#define TKIP_COUNTER_MEASURE_STARTED 1 +#define TKIP_COUNTER_MEASURE_STOPED 0 +/* Timeout (in ms) for Link to Up before Registering Station */ +#define ASSOC_LINKUP_TIMEOUT 60 + +/* In pronto case, IBSS owns the first peer for bss peer. + In Rome case, IBSS uses the 2nd peer as bss peer */ +#define IBSS_BROADCAST_STAID 1 + +typedef enum +{ + /** Not associated in Infra or participating in an IBSS / Ad-hoc network.*/ + eConnectionState_NotConnected, + + /** While connection in progress */ + eConnectionState_Connecting, + + /** Associated in an Infrastructure network.*/ + eConnectionState_Associated, + + /** Participating in an IBSS network though disconnected (no partner stations + in the IBSS).*/ + eConnectionState_IbssDisconnected, + + /** Participating in an IBSS network with partner stations also present*/ + eConnectionState_IbssConnected, + + /** Disconnecting in an Infrastructure network.*/ + eConnectionState_Disconnecting + +}eConnectionState; +/**This structure stores the connection information */ +typedef struct connection_info_s +{ + /** connection state of the NIC.*/ + eConnectionState connState; + + /** BSS type of the current connection. Comes from the MIB at the + time the connect request is issued in combination with the BssDescription + from the associated entity.*/ + + eMib_dot11DesiredBssType connDot11DesiredBssType; + /** BSSID */ + tCsrBssid bssId; + + /** SSID Info*/ + tCsrSSIDInfo SSID; + + /** Station ID */ + v_U8_t staId[ HDD_MAX_NUM_IBSS_STA ]; + /** Peer Mac Address of the IBSS Stations */ + v_MACADDR_t peerMacAddress[ HDD_MAX_NUM_IBSS_STA ]; + /** Auth Type */ + eCsrAuthType authType; + + /** Unicast Encryption Type */ + eCsrEncryptionType ucEncryptionType; + + /** Multicast Encryption Type */ + eCsrEncryptionType mcEncryptionType; + + /** Keys */ + tCsrKeys Keys; + + /** Operation Channel */ + v_U8_t operationChannel; + + /** Remembers authenticated state */ + v_U8_t uIsAuthenticated; + + /** Dot11Mode */ + tANI_U32 dot11Mode; + + v_U8_t proxyARPService; + + /** NSS and RateFlags used for this connection */ + uint8_t nss; + uint32_t rate_flags; + + /* ptk installed state */ + bool ptk_installed; + + /* gtk installed state */ + bool gtk_installed; +}connection_info_t; + +/*Forward declaration of Adapter*/ +typedef struct hdd_adapter_s hdd_adapter_t; +typedef struct hdd_context_s hdd_context_t; +typedef struct hdd_station_ctx hdd_station_ctx_t; +typedef struct hdd_ap_ctx_s hdd_ap_ctx_t; +typedef struct hdd_mon_ctx_s hdd_mon_ctx_t; + +typedef enum +{ + ePeerConnected = 1, + ePeerDisconnected +}ePeerStatus; + +extern v_BOOL_t hdd_connIsConnected( hdd_station_ctx_t *pHddStaCtx ); +extern bool hdd_is_connecting(hdd_station_ctx_t *hdd_sta_ctx); +eCsrBand hdd_connGetConnectedBand( hdd_station_ctx_t *pHddStaCtx ); +extern eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, v_U32_t roamId, + eRoamCmdStatus roamStatus, eCsrRoamResult roamResult ); + +v_BOOL_t hdd_connGetConnectedBssType( hdd_station_ctx_t *pHddCtx, + eMib_dot11DesiredBssType *pConnectedBssType ); + +int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType ); + +int hdd_set_csr_auth_type( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType ); +VOS_STATUS hdd_roamRegisterTDLSSTA(hdd_adapter_t *pAdapter, + const tANI_U8 *peerMac, tANI_U16 staId, + tANI_U8 ucastSig); +void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter); + +void hdd_SendPeerStatusIndToOemApp(v_MACADDR_t *peerMac, + tANI_U8 peerStatus, + tANI_U8 peerTimingMeasCap, + tANI_U8 sessionId, + tSirSmeChanInfo *chan_info); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +void hdd_indicateEseBcnReportNoResults(const hdd_adapter_t *pAdapter, + const tANI_U16 measurementToken, + const tANI_BOOLEAN flag, + const tANI_U8 numBss); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h new file mode 100644 index 000000000000..71e679a0b3f9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h @@ -0,0 +1,4242 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( HDD_CONFIG_H__ ) +#define HDD_CONFIG_H__ + +/**=========================================================================== + + \file hdd_Config.h + + \brief Android WLAN Adapter Configuration functions + + ==========================================================================*/ + +/* $HEADER$ */ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +#define FW_MODULE_LOG_LEVEL_STRING_LENGTH (255) + +#ifdef DHCP_SERVER_OFFLOAD +#define IPADDR_NUM_ENTRIES (4) +#define IPADDR_STRING_LENGTH (16) +#endif + +//Number of items that can be configured +#define MAX_CFG_INI_ITEMS 1024 + +#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" +#define CFG_RTS_THRESHOLD_MIN WNI_CFG_RTS_THRESHOLD_STAMIN // min is 0, meaning always use RTS. +#define CFG_RTS_THRESHOLD_MAX WNI_CFG_RTS_THRESHOLD_STAMAX // max is the max frame size +#define CFG_RTS_THRESHOLD_DEFAULT WNI_CFG_RTS_THRESHOLD_STADEF + +#define CFG_FRAG_THRESHOLD_NAME "gFragmentationThreshold" +#define CFG_FRAG_THRESHOLD_MIN WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN +#define CFG_FRAG_THRESHOLD_MAX WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX +#define CFG_FRAG_THRESHOLD_DEFAULT WNI_CFG_FRAGMENTATION_THRESHOLD_STADEF + +#define CFG_OPERATING_CHANNEL_NAME "gOperatingChannel" +#define CFG_OPERATING_CHANNEL_MIN ( 0 ) +#define CFG_OPERATING_CHANNEL_MAX ( 14 ) +#define CFG_OPERATING_CHANNEL_DEFAULT ( 1 ) + +#define CFG_SHORT_SLOT_TIME_ENABLED_NAME "gShortSlotTimeEnabled" +#define CFG_SHORT_SLOT_TIME_ENABLED_MIN WNI_CFG_SHORT_SLOT_TIME_STAMIN +#define CFG_SHORT_SLOT_TIME_ENABLED_MAX WNI_CFG_SHORT_SLOT_TIME_STAMAX +#define CFG_SHORT_SLOT_TIME_ENABLED_DEFAULT WNI_CFG_SHORT_SLOT_TIME_STADEF + +#define CFG_11D_SUPPORT_ENABLED_NAME "g11dSupportEnabled" +#define CFG_11D_SUPPORT_ENABLED_MIN WNI_CFG_11D_ENABLED_STAMIN +#define CFG_11D_SUPPORT_ENABLED_MAX WNI_CFG_11D_ENABLED_STAMAX +#define CFG_11D_SUPPORT_ENABLED_DEFAULT WNI_CFG_11D_ENABLED_STADEF // Default is ON + +#define CFG_11H_SUPPORT_ENABLED_NAME "g11hSupportEnabled" +#define CFG_11H_SUPPORT_ENABLED_MIN ( 0 ) +#define CFG_11H_SUPPORT_ENABLED_MAX ( 1 ) +#define CFG_11H_SUPPORT_ENABLED_DEFAULT ( 1 ) // Default is ON + +#define CFG_ENFORCE_11D_CHANNELS_NAME "gEnforce11dChannel" +#define CFG_ENFORCE_11D_CHANNELS_MIN ( 0 ) +#define CFG_ENFORCE_11D_CHANNELS_MAX ( 1 ) +#define CFG_ENFORCE_11D_CHANNELS_DEFAULT ( 0 ) + +//COUNTRY Code Priority +#define CFG_COUNTRY_CODE_PRIORITY_NAME "gCountryCodePriority" +#define CFG_COUNTRY_CODE_PRIORITY_MIN ( 0 ) +#define CFG_COUNTRY_CODE_PRIORITY_MAX ( 1 ) +#define CFG_COUNTRY_CODE_PRIORITY_DEFAULT ( 0 ) + +#define CFG_ENFORCE_COUNTRY_CODE_MATCH_NAME "gEnforceCountryCodeMatch" +#define CFG_ENFORCE_COUNTRY_CODE_MATCH_MIN ( 0 ) +#define CFG_ENFORCE_COUNTRY_CODE_MATCH_MAX ( 1 ) +#define CFG_ENFORCE_COUNTRY_CODE_MATCH_DEFAULT ( 0 ) + +#define CFG_ENFORCE_DEFAULT_DOMAIN_NAME "gEnforceDefaultDomain" +#define CFG_ENFORCE_DEFAULT_DOMAIN_MIN ( 0 ) +#define CFG_ENFORCE_DEFAULT_DOMAIN_MAX ( 1 ) +#define CFG_ENFORCE_DEFAULT_DOMAIN_DEFAULT ( 0 ) + +#define CFG_HEARTBEAT_THRESH_24_NAME "gHeartbeat24" +#define CFG_HEARTBEAT_THRESH_24_MIN WNI_CFG_HEART_BEAT_THRESHOLD_STAMIN +#define CFG_HEARTBEAT_THRESH_24_MAX WNI_CFG_HEART_BEAT_THRESHOLD_STAMAX +#define CFG_HEARTBEAT_THRESH_24_DEFAULT WNI_CFG_HEART_BEAT_THRESHOLD_STADEF + +#define CFG_POWER_USAGE_NAME "gPowerUsage" +#define CFG_POWER_USAGE_MIN "Min" //Minimum Power Save +#define CFG_POWER_USAGE_MAX "Max" //Maximum Power Save +#define CFG_POWER_USAGE_DEFAULT "Mod" //Moderate Power Save + +//Enable suspend on Android +#define CFG_ENABLE_SUSPEND_NAME "gEnableSuspend" +#define CFG_ENABLE_SUSPEND_MIN ( 0 ) //No support for suspend +#define CFG_ENABLE_SUSPEND_MAX ( 3 ) //Map to Deep Sleep +#define CFG_ENABLE_SUSPEND_DEFAULT ( 1 ) //Map to Standby + +//Driver start/stop command mappings +#define CFG_ENABLE_ENABLE_DRIVER_STOP_NAME "gEnableDriverStop" +#define CFG_ENABLE_ENABLE_DRIVER_STOP_MIN ( 0 ) //No support for stop +#define CFG_ENABLE_ENABLE_DRIVER_STOP_MAX ( 2 ) //Map to Deep Sleep +#define CFG_ENABLE_ENABLE_DRIVER_STOP_DEFAULT ( 0 ) + +#define CFG_WOWL_PATTERN_NAME "gWowlPattern" +#define CFG_WOWL_PATTERN_DEFAULT "" + +//IMPS = IdleModePowerSave +#define CFG_ENABLE_IMPS_NAME "gEnableImps" +#define CFG_ENABLE_IMPS_MIN ( 0 ) +#define CFG_ENABLE_IMPS_MAX ( 1 ) +#define CFG_ENABLE_IMPS_DEFAULT ( 1 ) + +#define CFG_IMPS_MINIMUM_SLEEP_TIME_NAME "gImpsMinSleepTime" +#define CFG_IMPS_MINIMUM_SLEEP_TIME_MIN ( 0 ) +#define CFG_IMPS_MINIMUM_SLEEP_TIME_MAX ( 65535 ) +#define CFG_IMPS_MINIMUM_SLEEP_TIME_DEFAULT ( 5 ) + +#define CFG_IMPS_MODERATE_SLEEP_TIME_NAME "gImpsModSleepTime" +#define CFG_IMPS_MODERATE_SLEEP_TIME_MIN ( 0 ) +#define CFG_IMPS_MODERATE_SLEEP_TIME_MAX ( 65535 ) +#define CFG_IMPS_MODERATE_SLEEP_TIME_DEFAULT ( 10) + +#define CFG_IMPS_MAXIMUM_SLEEP_TIME_NAME "gImpsMaxSleepTime" +#define CFG_IMPS_MAXIMUM_SLEEP_TIME_MIN ( 0 ) +#define CFG_IMPS_MAXIMUM_SLEEP_TIME_MAX ( 65535 ) +#define CFG_IMPS_MAXIMUM_SLEEP_TIME_DEFAULT ( 15 ) + +//BMPS = BeaconModePowerSave +#define CFG_ENABLE_BMPS_NAME "gEnableBmps" +#define CFG_ENABLE_BMPS_MIN ( 0 ) +#define CFG_ENABLE_BMPS_MAX ( 1 ) +#define CFG_ENABLE_BMPS_DEFAULT ( 1 ) + +#define CFG_BMPS_MINIMUM_LI_NAME "gBmpsMinListenInterval" +#define CFG_BMPS_MINIMUM_LI_MIN ( 1 ) +#define CFG_BMPS_MINIMUM_LI_MAX ( 65535 ) +#define CFG_BMPS_MINIMUM_LI_DEFAULT ( 1 ) + +#define CFG_BMPS_MODERATE_LI_NAME "gBmpsModListenInterval" +#define CFG_BMPS_MODERATE_LI_MIN ( 1 ) +#define CFG_BMPS_MODERATE_LI_MAX ( 65535 ) +#define CFG_BMPS_MODERATE_LI_DEFAULT ( 1 ) + +#define CFG_BMPS_MAXIMUM_LI_NAME "gBmpsMaxListenInterval" +#define CFG_BMPS_MAXIMUM_LI_MIN ( 1 ) +#define CFG_BMPS_MAXIMUM_LI_MAX ( 65535 ) +#define CFG_BMPS_MAXIMUM_LI_DEFAULT ( 1 ) + +// gEnableAutoBmpsTimer has been previously published as an externally +// configurable parameter. See analysis of CR 178211 for detailed info +// on why we want to *always* set this to 1 i.e. we no longer want +// this parameter to be configurable. the clean solution would be for +// users to not define this item in winreg so that the default value +// (which needs to be changed to 1) gets picked up but we cannot rely on that +// since this item has been published already hence the proposed +// solution to change the name of the item along with the change in the +// default value. also we could decide to not read this item from registry +// but leaving open the option of being able to configure this item for +// ASW's internal use +#define CFG_ENABLE_AUTO_BMPS_TIMER_NAME "gEnableAutoBmpsTimer_INTERNAL" +#define CFG_ENABLE_AUTO_BMPS_TIMER_MIN ( 0 ) +#define CFG_ENABLE_AUTO_BMPS_TIMER_MAX ( 1 ) +#define CFG_ENABLE_AUTO_BMPS_TIMER_DEFAULT ( 1 ) + +#define CFG_AUTO_BMPS_TIMER_VALUE_NAME "gAutoBmpsTimerValue" +#define CFG_AUTO_BMPS_TIMER_VALUE_MIN ( 1000 ) +#define CFG_AUTO_BMPS_TIMER_VALUE_MAX ( 4294967295UL ) +#define CFG_AUTO_BMPS_TIMER_VALUE_DEFAULT ( 1000 ) + +#define CFG_MAX_RX_AMPDU_FACTOR_NAME "gMaxRxAmpduFactor" +#define CFG_MAX_RX_AMPDU_FACTOR_MIN WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMIN +#define CFG_MAX_RX_AMPDU_FACTOR_MAX WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMAX +#define CFG_MAX_RX_AMPDU_FACTOR_DEFAULT WNI_CFG_MAX_RX_AMPDU_FACTOR_STADEF + +/* Configuration option for HT MPDU density (Table 8-125 802.11-2012) + * 0 for no restriction + * 1 for 1/4 micro sec + * 2 for 1/2 micro sec + * 3 for 1 micro sec + * 4 for 2 micro sec + * 5 for 4 micro sec + * 6 for 8 micro sec + * 7 for 16 micro sec + */ +#define CFG_HT_MPDU_DENSITY_NAME "ght_mpdu_density" +#define CFG_HT_MPDU_DENSITY_MIN WNI_CFG_MPDU_DENSITY_STAMIN +#define CFG_HT_MPDU_DENSITY_MAX WNI_CFG_MPDU_DENSITY_STAMAX +#define CFG_HT_MPDU_DENSITY_DEFAULT WNI_CFG_MPDU_DENSITY_STADEF + +//Configuration added to enable/disable CTS2SELF in +//Adaptive RX drain feature +#define CFG_ENABLE_ADAPT_RX_DRAIN_NAME "gEnableAdaptRxDrain" +#define CFG_ENABLE_ADAPT_RX_DRAIN_MIN WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMIN +#define CFG_ENABLE_ADAPT_RX_DRAIN_MAX WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMAX +#define CFG_ENABLE_ADAPT_RX_DRAIN_DEFAULT WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STADEF + + +#define CFG_REG_CHANGE_DEF_COUNTRY_NAME "gRegulatoryChangeCountry" +#define CFG_REG_CHANGE_DEF_COUNTRY_DEFAULT ( 0 ) +#define CFG_REG_CHANGE_DEF_COUNTRY_MIN ( 0 ) +#define CFG_REG_CHANGE_DEF_COUNTRY_MAX ( 1 ) + +#define CFG_ADVERTISE_CONCURRENT_OPERATION_NAME "gAdvertiseConcurrentOperation" +#define CFG_ADVERTISE_CONCURRENT_OPERATION_DEFAULT ( 1 ) +#define CFG_ADVERTISE_CONCURRENT_OPERATION_MIN ( 0 ) +#define CFG_ADVERTISE_CONCURRENT_OPERATION_MAX ( 1 ) + +typedef enum +{ + eHDD_DOT11_MODE_AUTO = 0, //covers all things we support + eHDD_DOT11_MODE_abg, //11a/b/g only, no HT, no proprietary + eHDD_DOT11_MODE_11b, + eHDD_DOT11_MODE_11g, + eHDD_DOT11_MODE_11n, + eHDD_DOT11_MODE_11g_ONLY, + eHDD_DOT11_MODE_11n_ONLY, + eHDD_DOT11_MODE_11b_ONLY, + eHDD_DOT11_MODE_11ac_ONLY, + eHDD_DOT11_MODE_11ac, + eHDD_DOT11_MODE_11a, +}eHddDot11Mode; + +enum +{ + WLAN_HDD_RX_HANDLE_MIN = 0, + WLAN_HDD_RX_HANDLE_IRQ = WLAN_HDD_RX_HANDLE_MIN, + WLAN_HDD_RX_HANDLE_RX_THREAD = 1, + WLAN_HDD_RX_HANDLE_RPS = 2, + WLAN_HDD_RX_HANDLE_MAX = WLAN_HDD_RX_HANDLE_RPS +}; + +#define CFG_DOT11_MODE_NAME "gDot11Mode" +#define CFG_DOT11_MODE_MIN eHDD_DOT11_MODE_AUTO +#ifdef WLAN_FEATURE_11AC +#define CFG_DOT11_MODE_DEFAULT eHDD_DOT11_MODE_11ac +#else +#define CFG_DOT11_MODE_DEFAULT eHDD_DOT11_MODE_11n +#endif +#define CFG_DOT11_MODE_MAX eHDD_DOT11_MODE_11a + +#define CFG_CHANNEL_BONDING_MODE_24GHZ_NAME "gChannelBondingMode24GHz" +#define CFG_CHANNEL_BONDING_MODE_MIN WNI_CFG_CHANNEL_BONDING_MODE_STAMIN +#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_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 +#define CFG_CHANNEL_BONDING_MODE_DEFAULT WNI_CFG_CHANNEL_BONDING_MODE_STADEF + +#define CFG_FIXED_RATE_NAME "gFixedRate" +#define CFG_FIXED_RATE_MIN WNI_CFG_FIXED_RATE_STAMIN +#define CFG_FIXED_RATE_MAX WNI_CFG_FIXED_RATE_STAMAX +#define CFG_FIXED_RATE_DEFAULT WNI_CFG_FIXED_RATE_STADEF + +#define CFG_SHORT_GI_20MHZ_NAME "gShortGI20Mhz" +#define CFG_SHORT_GI_20MHZ_MIN WNI_CFG_SHORT_GI_20MHZ_STAMIN +#define CFG_SHORT_GI_20MHZ_MAX WNI_CFG_SHORT_GI_20MHZ_STAMAX +#define CFG_SHORT_GI_20MHZ_DEFAULT WNI_CFG_SHORT_GI_20MHZ_STADEF + +#define CFG_BLOCK_ACK_AUTO_SETUP_NAME "gBlockAckAutoSetup" +#define CFG_BLOCK_ACK_AUTO_SETUP_MIN ( 0 ) +#define CFG_BLOCK_ACK_AUTO_SETUP_MAX ( 1 ) +#define CFG_BLOCK_ACK_AUTO_SETUP_DEFAULT ( 1 ) + +#define CFG_SCAN_RESULT_AGE_COUNT_NAME "gScanResultAgeCount" +#define CFG_SCAN_RESULT_AGE_COUNT_MIN ( 1 ) +#define CFG_SCAN_RESULT_AGE_COUNT_MAX ( 100 ) +#define CFG_SCAN_RESULT_AGE_COUNT_DEFAULT ( 3 ) + +//All in seconds +//Not Connect, No Power Save +#define CFG_SCAN_RESULT_AGE_TIME_NCNPS_NAME "gScanResultAgeNCNPS" +#define CFG_SCAN_RESULT_AGE_TIME_NCNPS_MIN ( 10 ) +#define CFG_SCAN_RESULT_AGE_TIME_NCNPS_MAX ( 10000 ) +#define CFG_SCAN_RESULT_AGE_TIME_NCNPS_DEFAULT ( 50 ) +//Not Connect, Power Save +#define CFG_SCAN_RESULT_AGE_TIME_NCPS_NAME "gScanResultAgeNCPS" +#define CFG_SCAN_RESULT_AGE_TIME_NCPS_MIN ( 10 ) +#define CFG_SCAN_RESULT_AGE_TIME_NCPS_MAX ( 10000 ) +#define CFG_SCAN_RESULT_AGE_TIME_NCPS_DEFAULT ( 300 ) +//Connect, No Power Save +#define CFG_SCAN_RESULT_AGE_TIME_CNPS_NAME "gScanResultAgeCNPS" +#define CFG_SCAN_RESULT_AGE_TIME_CNPS_MIN ( 10 ) +#define CFG_SCAN_RESULT_AGE_TIME_CNPS_MAX ( 10000 ) +#define CFG_SCAN_RESULT_AGE_TIME_CNPS_DEFAULT ( 150 ) +//Connect, Power Save +#define CFG_SCAN_RESULT_AGE_TIME_CPS_NAME "gScanResultAgeCPS" +#define CFG_SCAN_RESULT_AGE_TIME_CPS_MIN ( 10 ) +#define CFG_SCAN_RESULT_AGE_TIME_CPS_MAX ( 10000 ) +#define CFG_SCAN_RESULT_AGE_TIME_CPS_DEFAULT ( 600 ) + +#define CFG_RSSI_CATEGORY_GAP_NAME "gRssiCatGap" +#define CFG_RSSI_CATEGORY_GAP_MIN ( 5 ) +#define CFG_RSSI_CATEGORY_GAP_MAX ( 100 ) +#define CFG_RSSI_CATEGORY_GAP_DEFAULT ( 5 ) + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +#define CFG_ROAM_PREFER_5GHZ "gRoamPrefer5GHz" +#define CFG_ROAM_PREFER_5GHZ_MIN ( 0 ) +#define CFG_ROAM_PREFER_5GHZ_MAX ( 1 ) +#define CFG_ROAM_PREFER_5GHZ_DEFAULT ( 1 ) + +/* + To enable, set gRoamIntraBand=1 (Roaming within band) + To disable, set gRoamIntraBand=0 (Roaming across band) +*/ +#define CFG_ROAM_INTRA_BAND "gRoamIntraBand" +#define CFG_ROAM_INTRA_BAND_MIN ( 0 ) +#define CFG_ROAM_INTRA_BAND_MAX ( 1 ) +#define CFG_ROAM_INTRA_BAND_DEFAULT ( 0 ) +#endif + +#define CFG_SHORT_PREAMBLE_NAME "gShortPreamble" +#define CFG_SHORT_PREAMBLE_MIN WNI_CFG_SHORT_PREAMBLE_STAMIN +#define CFG_SHORT_PREAMBLE_MAX WNI_CFG_SHORT_PREAMBLE_STAMAX +#define CFG_SHORT_PREAMBLE_DEFAULT WNI_CFG_SHORT_PREAMBLE_STADEF + +#define CFG_IBSS_BSSID_NAME "gIbssBssid" +#define CFG_IBSS_BSSID_MIN "000000000000" +#define CFG_IBSS_BSSID_MAX "ffffffffffff" +#define CFG_IBSS_BSSID_DEFAULT "000AF5040506" + +#define CFG_INTF0_MAC_ADDR_NAME "Intf0MacAddress" +#define CFG_INTF0_MAC_ADDR_MIN "000000000000" +#define CFG_INTF0_MAC_ADDR_MAX "ffffffffffff" +#define CFG_INTF0_MAC_ADDR_DEFAULT "000AF5898980" + +#define CFG_INTF1_MAC_ADDR_NAME "Intf1MacAddress" +#define CFG_INTF1_MAC_ADDR_MIN "000000000000" +#define CFG_INTF1_MAC_ADDR_MAX "ffffffffffff" +#define CFG_INTF1_MAC_ADDR_DEFAULT "000AF5898981" + +#define CFG_INTF2_MAC_ADDR_NAME "Intf2MacAddress" +#define CFG_INTF2_MAC_ADDR_MIN "000000000000" +#define CFG_INTF2_MAC_ADDR_MAX "ffffffffffff" +#define CFG_INTF2_MAC_ADDR_DEFAULT "000AF5898982" + +#define CFG_INTF3_MAC_ADDR_NAME "Intf3MacAddress" +#define CFG_INTF3_MAC_ADDR_MIN "000000000000" +#define CFG_INTF3_MAC_ADDR_MAX "ffffffffffff" +#define CFG_INTF3_MAC_ADDR_DEFAULT "000AF5898983" + +#define CFG_AP_QOS_UAPSD_MODE_NAME "gEnableApUapsd" // ACs to setup U-APSD for at assoc +#define CFG_AP_QOS_UAPSD_MODE_MIN ( 0 ) +#define CFG_AP_QOS_UAPSD_MODE_MAX ( 1 ) +#define CFG_AP_QOS_UAPSD_MODE_DEFAULT ( 1 ) + +#define CFG_AP_COUNTRY_CODE "gAPCntryCode" +#define CFG_AP_COUNTRY_CODE_MIN "USI" +#define CFG_AP_COUNTRY_CODE_MAX "USI" +#define CFG_AP_COUNTRY_CODE_DEFAULT "FFF" + +#define CFG_AP_ENABLE_RANDOM_BSSID_NAME "gEnableApRandomBssid" +#define CFG_AP_ENABLE_RANDOM_BSSID_MIN ( 0 ) +#define CFG_AP_ENABLE_RANDOM_BSSID_MAX ( 1 ) +#define CFG_AP_ENABLE_RANDOM_BSSID_DEFAULT ( 0 ) + +#define CFG_AP_ENABLE_PROTECTION_MODE_NAME "gEnableApProt" +#define CFG_AP_ENABLE_PROTECTION_MODE_MIN ( 0 ) +#define CFG_AP_ENABLE_PROTECTION_MODE_MAX ( 1 ) +#define CFG_AP_ENABLE_PROTECTION_MODE_DEFAULT ( 1 ) + +// Bit map for CFG_AP_PROTECTION_MODE_DEFAULT +// LOWER byte for associated stations +// UPPER byte for overlapping stations +// each byte will have the following info +// bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 +// OBSS RIFS LSIG_TXOP NON_GF HT20 FROM_11G FROM_11B FROM_11A +// bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 +// OBSS RIFS LSIG_TXOP NON_GF HT_20 FROM_11G FROM_11B FROM_11A +#define CFG_AP_PROTECTION_MODE_NAME "gApProtection" +#define CFG_AP_PROTECTION_MODE_MIN ( 0x0 ) +#define CFG_AP_PROTECTION_MODE_MAX ( 0xFFFF ) +#define CFG_AP_PROTECTION_MODE_DEFAULT ( 0xBFFF ) + +#define CFG_AP_OBSS_PROTECTION_MODE_NAME "gEnableApOBSSProt" +#define CFG_AP_OBSS_PROTECTION_MODE_MIN ( 0 ) +#define CFG_AP_OBSS_PROTECTION_MODE_MAX ( 1 ) +#define CFG_AP_OBSS_PROTECTION_MODE_DEFAULT ( 0 ) + +#define CFG_AP_STA_SECURITY_SEPERATION_NAME "gDisableIntraBssFwd" +#define CFG_AP_STA_SECURITY_SEPERATION_MIN ( 0 ) +#define CFG_AP_STA_SECURITY_SEPERATION_MAX ( 1 ) +#define CFG_AP_STA_SECURITY_SEPERATION_DEFAULT ( 0 ) + +#define CFG_AP_LISTEN_MODE_NAME "gEnablePhyAgcListenMode" +#define CFG_AP_LISTEN_MODE_MIN (0) +#define CFG_AP_LISTEN_MODE_MAX (128) +#define CFG_AP_LISTEN_MODE_DEFAULT (128) + +#define CFG_AP_AUTO_SHUT_OFF "gAPAutoShutOff" +#define CFG_AP_AUTO_SHUT_OFF_MIN ( 0 ) +#define CFG_AP_AUTO_SHUT_OFF_MAX ( 4294967295UL ) +#define CFG_AP_AUTO_SHUT_OFF_DEFAULT ( 0 ) + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +#define CFG_WLAN_AUTO_SHUTDOWN "gWlanAutoShutdown" +#define CFG_WLAN_AUTO_SHUTDOWN_MIN ( 0 ) +#define CFG_WLAN_AUTO_SHUTDOWN_MAX ( 86400 ) /* Max 1 day timeout */ +#define CFG_WLAN_AUTO_SHUTDOWN_DEFAULT ( 0 ) +#endif + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE "gWlanMccToSccSwitchMode" +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MIN ( VOS_MCC_TO_SCC_SWITCH_DISABLE) +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX ( VOS_MCC_TO_SCC_SWITCH_FORCE ) +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_DEFAULT (VOS_MCC_TO_SCC_SWITCH_DISABLE) +#endif + + +#define CFG_FRAMES_PROCESSING_TH_MODE_NAME "gMinFramesProcThres" +#define CFG_FRAMES_PROCESSING_TH_MIN ( 0 ) +#define CFG_FRAMES_PROCESSING_TH_MAX ( 39 ) +#define CFG_FRAMES_PROCESSING_TH_DEFAULT ( 0 ) + +#define CFG_DISABLE_PACKET_FILTER "gDisablePacketFilter" +#define CFG_DISABLE_PACKET_FILTER_MIN (0) +#define CFG_DISABLE_PACKET_FILTER_MAX (0x1) +#define CFG_DISABLE_PACKET_FILTER_DEFAULT (0) + +#define CFG_ENABLE_LTE_COEX "gEnableLTECoex" +#define CFG_ENABLE_LTE_COEX_MIN ( 0 ) +#define CFG_ENABLE_LTE_COEX_MAX ( 1 ) +#define CFG_ENABLE_LTE_COEX_DEFAULT ( 0 ) + +#define CFG_AP_KEEP_ALIVE_PERIOD_NAME "gApKeepAlivePeriod" +#define CFG_AP_KEEP_ALIVE_PERIOD_MIN WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMIN +#define CFG_AP_KEEP_ALIVE_PERIOD_MAX WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMAX +#define CFG_AP_KEEP_ALIVE_PERIOD_DEFAULT WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STADEF + +#define CFG_GO_KEEP_ALIVE_PERIOD_NAME "gGoKeepAlivePeriod" +#define CFG_GO_KEEP_ALIVE_PERIOD_MIN WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMIN +#define CFG_GO_KEEP_ALIVE_PERIOD_MAX WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMAX +#define CFG_GO_KEEP_ALIVE_PERIOD_DEFAULT WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STADEF + +#define CFG_AP_LINK_MONITOR_PERIOD_NAME "gApLinkMonitorPeriod" +#define CFG_AP_LINK_MONITOR_PERIOD_MIN ( 3 ) +#define CFG_AP_LINK_MONITOR_PERIOD_MAX ( 50 ) +#define CFG_AP_LINK_MONITOR_PERIOD_DEFAULT ( 10 ) + +/* gGoLinkMonitorPeriod is period where link is idle and where + * we send NULL frame + */ +#define CFG_GO_LINK_MONITOR_PERIOD_NAME "gGoLinkMonitorPeriod" +#define CFG_GO_LINK_MONITOR_PERIOD_MIN ( 3 ) +#define CFG_GO_LINK_MONITOR_PERIOD_MAX ( 50 ) +#define CFG_GO_LINK_MONITOR_PERIOD_DEFAULT ( 10 ) + + +#define CFG_BEACON_INTERVAL_NAME "gBeaconInterval" +#define CFG_BEACON_INTERVAL_MIN WNI_CFG_BEACON_INTERVAL_STAMIN +#define CFG_BEACON_INTERVAL_MAX WNI_CFG_BEACON_INTERVAL_STAMAX +#define CFG_BEACON_INTERVAL_DEFAULT WNI_CFG_BEACON_INTERVAL_STADEF + +//Additional Handoff related Parameters +#define CFG_ENABLE_IDLE_SCAN_NAME "gEnableIdleScan" +#define CFG_ENABLE_IDLE_SCAN_MIN ( 0 ) +#define CFG_ENABLE_IDLE_SCAN_MAX ( 1 ) +#define CFG_ENABLE_IDLE_SCAN_DEFAULT ( 1 ) + +#define CFG_ROAMING_TIME_NAME "gRoamingTime" +#define CFG_ROAMING_TIME_MIN ( 0 ) +#define CFG_ROAMING_TIME_MAX ( 4294967UL ) +#define CFG_ROAMING_TIME_DEFAULT ( 10 ) + +#define CFG_VCC_RSSI_TRIGGER_NAME "gVccRssiTrigger" +#define CFG_VCC_RSSI_TRIGGER_MIN ( 0 ) +#define CFG_VCC_RSSI_TRIGGER_MAX ( 80 ) +#define CFG_VCC_RSSI_TRIGGER_DEFAULT ( 80 ) + +#define CFG_VCC_UL_MAC_LOSS_THRESH_NAME "gVccUlMacLossThresh" +#define CFG_VCC_UL_MAC_LOSS_THRESH_MIN ( 0 ) +#define CFG_VCC_UL_MAC_LOSS_THRESH_MAX ( 9 ) +#define CFG_VCC_UL_MAC_LOSS_THRESH_DEFAULT ( 9 ) + +#define CFG_PASSIVE_MAX_CHANNEL_TIME_NAME "gPassiveMaxChannelTime" +#define CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ( 0 ) +#define CFG_PASSIVE_MAX_CHANNEL_TIME_MAX ( 10000 ) +#define CFG_PASSIVE_MAX_CHANNEL_TIME_DEFAULT ( 110 ) + +#define CFG_PASSIVE_MIN_CHANNEL_TIME_NAME "gPassiveMinChannelTime" +#define CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ( 0 ) +#define CFG_PASSIVE_MIN_CHANNEL_TIME_MAX ( 10000 ) +#define CFG_PASSIVE_MIN_CHANNEL_TIME_DEFAULT ( 60 ) + +#define CFG_ACTIVE_MAX_CHANNEL_TIME_NAME "gActiveMaxChannelTime" +#define CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ( 0 ) +#define CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ( 10000 ) +#define CFG_ACTIVE_MAX_CHANNEL_TIME_DEFAULT ( 40 ) + +#define CFG_ACTIVE_MIN_CHANNEL_TIME_NAME "gActiveMinChannelTime" +#define CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ( 0 ) +#define CFG_ACTIVE_MIN_CHANNEL_TIME_MAX ( 10000 ) +#define CFG_ACTIVE_MIN_CHANNEL_TIME_DEFAULT ( 20 ) + +#define CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_NAME "gActiveMaxChannelTimeBtc" +#define CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_MIN ( 0 ) +#define CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_MAX ( 10000 ) +#define CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_DEFAULT ( 120 ) + +#define CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_NAME "gActiveMinChannelTimeBtc" +#define CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_MIN ( 0 ) +#define CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_MAX ( 10000 ) +#define CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_DEFAULT ( 60 ) + +#define CFG_RETRY_LIMIT_ZERO_NAME "gRetryLimitZero" +#define CFG_RETRY_LIMIT_ZERO_MIN ( 0 ) +#define CFG_RETRY_LIMIT_ZERO_MAX ( 15 ) +#define CFG_RETRY_LIMIT_ZERO_DEFAULT ( 5 ) + +#define CFG_RETRY_LIMIT_ONE_NAME "gRetryLimitOne" +#define CFG_RETRY_LIMIT_ONE_MIN ( 0 ) +#define CFG_RETRY_LIMIT_ONE_MAX ( 15 ) +#define CFG_RETRY_LIMIT_ONE_DEFAULT ( 10 ) + +#define CFG_RETRY_LIMIT_TWO_NAME "gRetryLimitTwo" +#define CFG_RETRY_LIMIT_TWO_MIN ( 0 ) +#define CFG_RETRY_LIMIT_TWO_MAX ( 15 ) +#define CFG_RETRY_LIMIT_TWO_DEFAULT ( 15 ) + +#define CFG_DISABLE_AGG_WITH_BTC_NAME "gDisableAggWithBTC" +#define CFG_DISABLE_AGG_WITH_BTC_MIN ( 0 ) +#define CFG_DISABLE_AGG_WITH_BTC_MAX ( 1 ) +#define CFG_DISABLE_AGG_WITH_BTC_DEFAULT ( 1 ) + +#ifdef WLAN_AP_STA_CONCURRENCY + +#define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME "gPassiveMaxChannelTimeConc" +#define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_MIN ( 0 ) +#define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_MAX ( 10000 ) +#define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_DEFAULT ( 110 ) + +#define CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_NAME "gPassiveMinChannelTimeConc" +#define CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_MIN ( 0 ) +#define CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_MAX ( 10000 ) +#define CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_DEFAULT ( 60 ) + +#define CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_NAME "gActiveMaxChannelTimeConc" +#define CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_MIN ( 0 ) +#define CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_MAX ( 10000 ) +#define CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_DEFAULT ( 40 ) + +#define CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_NAME "gActiveMinChannelTimeConc" +#define CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_MIN ( 0 ) +#define CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_MAX ( 10000 ) +#define CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_DEFAULT ( 20 ) + +#define CFG_REST_TIME_CONC_NAME "gRestTimeConc" +#define CFG_REST_TIME_CONC_MIN ( 0 ) +#define CFG_REST_TIME_CONC_MAX ( 10000 ) +#define CFG_REST_TIME_CONC_DEFAULT ( 100 ) + +/* Mininum time spent on home channel before moving to a new channel to scan */ +#define CFG_MIN_REST_TIME_NAME "gMinRestTimeConc" +#define CFG_MIN_REST_TIME_MIN ( 0 ) +#define CFG_MIN_REST_TIME_MAX ( 50 ) +#define CFG_MIN_REST_TIME_DEFAULT ( 50 ) + +/* Data inactivity time in msec on bss channel that will be used + * by scan engine in firmware. + * for example if this value is 25ms then firmware will check for + * data inactivity every 25ms till gRestTimeConc is reached. + * If inactive then scan engine will move from home channel to + * scan the next frequency. + */ +#define CFG_IDLE_TIME_NAME "gIdleTimeConc" +#define CFG_IDLE_TIME_MIN ( 0 ) +#define CFG_IDLE_TIME_MAX ( 25 ) +#define CFG_IDLE_TIME_DEFAULT ( 25 ) + +#define CFG_NUM_STA_CHAN_COMBINED_CONC_NAME "gNumStaChanCombinedConc" +#define CFG_NUM_STA_CHAN_COMBINED_CONC_MIN ( 1 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_MAX ( 255 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_DEFAULT ( 3 ) + +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_NAME "gNumP2PChanCombinedConc" +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_MIN ( 1 ) +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_MAX ( 255 ) +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_DEFAULT ( 1 ) +#endif + +#define CFG_MAX_PS_POLL_NAME "gMaxPsPoll" +#define CFG_MAX_PS_POLL_MIN WNI_CFG_MAX_PS_POLL_STAMIN +#define CFG_MAX_PS_POLL_MAX WNI_CFG_MAX_PS_POLL_STAMAX +#define CFG_MAX_PS_POLL_DEFAULT WNI_CFG_MAX_PS_POLL_STADEF + +#define CFG_MAX_TX_POWER_NAME "gTxPowerCap" +#define CFG_MAX_TX_POWER_MIN WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMIN +#define CFG_MAX_TX_POWER_MAX WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX +//Not to use CFG default because if no registry setting, this is ignored by SME. +#define CFG_MAX_TX_POWER_DEFAULT WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX + + +#define CFG_LOW_GAIN_OVERRIDE_NAME "gLowGainOverride" +#define CFG_LOW_GAIN_OVERRIDE_MIN WNI_CFG_LOW_GAIN_OVERRIDE_STAMIN +#define CFG_LOW_GAIN_OVERRIDE_MAX WNI_CFG_LOW_GAIN_OVERRIDE_STAMAX +#define CFG_LOW_GAIN_OVERRIDE_DEFAULT WNI_CFG_LOW_GAIN_OVERRIDE_STADEF + +#define CFG_RSSI_FILTER_PERIOD_NAME "gRssiFilterPeriod" +#define CFG_RSSI_FILTER_PERIOD_MIN WNI_CFG_RSSI_FILTER_PERIOD_STAMIN +#define CFG_RSSI_FILTER_PERIOD_MAX WNI_CFG_RSSI_FILTER_PERIOD_STAMAX +// Increased this value for Non-ESE AP. This is cause FW RSSI Monitoring +// the consumer of this value is ON by default. So to impact power numbers +// we are setting this to a high value. +#define CFG_RSSI_FILTER_PERIOD_DEFAULT WNI_CFG_RSSI_FILTER_PERIOD_STADEF + +#define CFG_IGNORE_DTIM_NAME "gIgnoreDtim" +#define CFG_IGNORE_DTIM_MIN WNI_CFG_IGNORE_DTIM_STAMIN +#define CFG_IGNORE_DTIM_MAX WNI_CFG_IGNORE_DTIM_STAMAX +#define CFG_IGNORE_DTIM_DEFAULT WNI_CFG_IGNORE_DTIM_STADEF + +#define CFG_MAX_LI_MODULATED_DTIM_NAME "gMaxLIModulatedDTIM" +#define CFG_MAX_LI_MODULATED_DTIM_MIN ( 1 ) +#define CFG_MAX_LI_MODULATED_DTIM_MAX ( 10 ) +#define CFG_MAX_LI_MODULATED_DTIM_DEFAULT ( 10 ) + +#define CFG_RX_ANT_CONFIGURATION_NAME "gNumRxAnt" +#define CFG_RX_ANT_CONFIGURATION_NAME_MIN ( 1 ) +#define CFG_RX_ANT_CONFIGURATION_NAME_MAX ( 2 ) +#define CFG_RX_ANT_CONFIGURATION_NAME_DEFAULT ( 2 ) + +#define CFG_FW_HEART_BEAT_MONITORING_NAME "gEnableFWHeartBeatMonitoring" +#define CFG_FW_HEART_BEAT_MONITORING_MIN ( 0 ) +#define CFG_FW_HEART_BEAT_MONITORING_MAX ( 1 ) +#define CFG_FW_HEART_BEAT_MONITORING_DEFAULT ( 1 ) + +#define CFG_FW_BEACON_FILTERING_NAME "gEnableFWBeaconFiltering" +#define CFG_FW_BEACON_FILTERING_MIN ( 0 ) +#define CFG_FW_BEACON_FILTERING_MAX ( 1 ) +#define CFG_FW_BEACON_FILTERING_DEFAULT ( 1 ) + +#define CFG_FW_RSSI_MONITORING_NAME "gEnableFWRssiMonitoring" +#define CFG_FW_RSSI_MONITORING_MIN ( 0 ) +#define CFG_FW_RSSI_MONITORING_MAX ( 1 ) +#define CFG_FW_RSSI_MONITORING_DEFAULT ( 1 ) + +/* enable use of long duration RTS-CTS protection when SAP goes off channel + * in MCC mode + */ +#define CFG_FW_MCC_RTS_CTS_PROT_NAME "gFWMccRtsCtsProtection" +#define CFG_FW_MCC_RTS_CTS_PROT_MIN (0) +#define CFG_FW_MCC_RTS_CTS_PROT_MAX (1) +#define CFG_FW_MCC_RTS_CTS_PROT_DEFAULT (0) + +/* Enable use of broadcast probe response to increase the detectability of + * SAP in MCC mode + */ +#define CFG_FW_MCC_BCAST_PROB_RESP_NAME "gFWMccBCastProbeResponse" +#define CFG_FW_MCC_BCAST_PROB_RESP_MIN (0) +#define CFG_FW_MCC_BCAST_PROB_RESP_MAX (1) +#define CFG_FW_MCC_BCAST_PROB_RESP_DEFAULT (0) + +#define CFG_DATA_INACTIVITY_TIMEOUT_NAME "gDataInactivityTimeout" +#define CFG_DATA_INACTIVITY_TIMEOUT_MIN ( 1 ) +#define CFG_DATA_INACTIVITY_TIMEOUT_MAX ( 255 ) +#define CFG_DATA_INACTIVITY_TIMEOUT_DEFAULT ( 20 ) + +#define CFG_NTH_BEACON_FILTER_NAME "gNthBeaconFilter" +#define CFG_NTH_BEACON_FILTER_MIN ( WNI_CFG_NTH_BEACON_FILTER_STAMIN ) +#define CFG_NTH_BEACON_FILTER_MAX ( WNI_CFG_NTH_BEACON_FILTER_STAMAX ) +#define CFG_NTH_BEACON_FILTER_DEFAULT ( WNI_CFG_NTH_BEACON_FILTER_STADEF ) + +#define CFG_RF_SETTLING_TIME_CLK_NAME "rfSettlingTimeUs" +#define CFG_RF_SETTLING_TIME_CLK_MIN ( 0 ) +#define CFG_RF_SETTLING_TIME_CLK_MAX ( 60000 ) +#define CFG_RF_SETTLING_TIME_CLK_DEFAULT ( 1500 ) + +#define CFG_INFRA_STA_KEEP_ALIVE_PERIOD_NAME "gStaKeepAlivePeriod" +#define CFG_INFRA_STA_KEEP_ALIVE_PERIOD_MIN ( 0 ) +#define CFG_INFRA_STA_KEEP_ALIVE_PERIOD_MAX ( 65535) +#define CFG_INFRA_STA_KEEP_ALIVE_PERIOD_DEFAULT ( 0 ) + +//WMM configuration +#define CFG_QOS_WMM_MODE_NAME "WmmIsEnabled" +#define CFG_QOS_WMM_MODE_MIN (0) +#define CFG_QOS_WMM_MODE_MAX (2) //HDD_WMM_NO_QOS +#define CFG_QOS_WMM_MODE_DEFAULT (0) //HDD_WMM_AUTO + +#define CFG_QOS_WMM_80211E_ENABLED_NAME "80211eIsEnabled" +#define CFG_QOS_WMM_80211E_ENABLED_MIN (0) +#define CFG_QOS_WMM_80211E_ENABLED_MAX (1) +#define CFG_QOS_WMM_80211E_ENABLED_DEFAULT (0) + +#define CFG_QOS_WMM_UAPSD_MASK_NAME "UapsdMask" // ACs to setup U-APSD for at assoc +#define CFG_QOS_WMM_UAPSD_MASK_MIN (0x00) +#define CFG_QOS_WMM_UAPSD_MASK_MAX (0xFF) +#define CFG_QOS_WMM_UAPSD_MASK_DEFAULT (0x00) + +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_NAME "InfraUapsdVoSrvIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_MAX (4294967295UL ) +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_DEFAULT (20) + +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_NAME "InfraUapsdVoSuspIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_MAX (4294967295UL ) +#define CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_DEFAULT (2000) + +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_NAME "InfraUapsdViSrvIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_DEFAULT (300) + +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_NAME "InfraUapsdViSuspIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_DEFAULT (2000) + +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_NAME "InfraUapsdBeSrvIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_DEFAULT (300) + +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_NAME "InfraUapsdBeSuspIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_DEFAULT (2000) + +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_NAME "InfraUapsdBkSrvIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_DEFAULT (300) + +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_NAME "InfraUapsdBkSuspIntv" +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_MIN (0) +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_DEFAULT (2000) + +#ifdef FEATURE_WLAN_ESE +#define CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_NAME "InfraInactivityInterval" +#define CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_MIN (0) +#define CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_MAX (4294967295UL) +#define CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_DEFAULT (0) //disabled + +#define CFG_ESE_FEATURE_ENABLED_NAME "EseEnabled" +#define CFG_ESE_FEATURE_ENABLED_MIN (0) +#define CFG_ESE_FEATURE_ENABLED_MAX (1) +#define CFG_ESE_FEATURE_ENABLED_DEFAULT (0) //disabled +#endif // FEATURE_WLAN_ESE + +#ifdef FEATURE_WLAN_LFR +#define CFG_LFR_FEATURE_ENABLED_NAME "FastRoamEnabled" +#define CFG_LFR_FEATURE_ENABLED_MIN (0) +#define CFG_LFR_FEATURE_ENABLED_MAX (1) +#define CFG_LFR_FEATURE_ENABLED_DEFAULT (0) //disabled + +#define CFG_LFR_MAWC_FEATURE_ENABLED_NAME "MAWCEnabled" +#define CFG_LFR_MAWC_FEATURE_ENABLED_MIN (0) +#define CFG_LFR_MAWC_FEATURE_ENABLED_MAX (1) +#define CFG_LFR_MAWC_FEATURE_ENABLED_DEFAULT (0) /* disabled */ +#endif // FEATURE_WLAN_LFR + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +// This flag will control fasttransition in case of 11r and ese. +// Basically with this the whole neighbor roam, pre-auth, reassoc +// can be turned ON/OFF. +// With this turned OFF 11r will completely not work. +// For 11r this flag has to be ON. +// For ESE fastroam will not work. +#define CFG_FAST_TRANSITION_ENABLED_NAME "FastTransitionEnabled" +#define CFG_FAST_TRANSITION_ENABLED_NAME_MIN (0) +#define CFG_FAST_TRANSITION_ENABLED_NAME_MAX (1) +#define CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT (1) //Enabled + +/* This parameter is used to decide whether to Roam or not. + * AP1 is the currently associated AP and AP2 is chosen for roaming. + * The Roaming will happen only if AP2 has better Signal Quality and it has a RSSI better than AP1 + * in terms of RoamRssiDiff,and RoamRssiDiff is the number of units (typically measured in dB) AP2 + * is better than AP1. + * This check is not done if the value is Zero */ +#define CFG_ROAM_RSSI_DIFF_NAME "RoamRssiDiff" +#define CFG_ROAM_RSSI_DIFF_MIN (0) +#define CFG_ROAM_RSSI_DIFF_MAX (30) +#define CFG_ROAM_RSSI_DIFF_DEFAULT (5) + +/* + * Following a scan and if potential roam candidate(s) are found, + * then determine whether to register for reassoc threshold or roam + * immediately based on this configuration parameter. If the RSSI + * of any available candidate is better than the currently associated + * AP by at least gImmediateRoamRssiDiff, then being to roam + * immediately. + * NOTE: Value of 0 means that immediate roaming is enabled by default + */ +#define CFG_IMMEDIATE_ROAM_RSSI_DIFF_NAME "gImmediateRoamRssiDiff" +#define CFG_IMMEDIATE_ROAM_RSSI_DIFF_MIN (0) +#define CFG_IMMEDIATE_ROAM_RSSI_DIFF_MAX (125) +#define CFG_IMMEDIATE_ROAM_RSSI_DIFF_DEFAULT (0) + +/*This parameter is used to set Wireless Extended Security Mode.*/ +#define CFG_ENABLE_WES_MODE_NAME "gWESModeEnabled" +#define CFG_ENABLE_WES_MODE_NAME_MIN (0) +#define CFG_ENABLE_WES_MODE_NAME_MAX (1) +#define CFG_ENABLE_WES_MODE_NAME_DEFAULT (0) + +#define CFG_ROAM_SCAN_N_PROBES "gRoamScanNProbes" +#define CFG_ROAM_SCAN_N_PROBES_MIN (1) +#define CFG_ROAM_SCAN_N_PROBES_MAX (10) +#define CFG_ROAM_SCAN_N_PROBES_DEFAULT (2) + +#define CFG_ROAM_SCAN_HOME_AWAY_TIME "gRoamScanHomeAwayTime" +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN (0) // 0 for disable +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX (300) +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT (CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) + // disabled by default + +#endif /* (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) */ + +#ifdef FEATURE_WLAN_OKC +#define CFG_OKC_FEATURE_ENABLED_NAME "OkcEnabled" +#define CFG_OKC_FEATURE_ENABLED_MIN (0) +#define CFG_OKC_FEATURE_ENABLED_MAX (1) +#define CFG_OKC_FEATURE_ENABLED_DEFAULT (1) +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED "gRoamScanOffloadEnabled" +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN (0) +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX (1) +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT (1) +#endif + +#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME "PktClassificationBasis" // DSCP or 802.1Q +#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN (0) +#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX (1) +#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_DEFAULT (0) //DSCP + +/* default TSPEC parameters for AC_VO */ +#define CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME "InfraDirAcVo" +#define CFG_QOS_WMM_INFRA_DIR_AC_VO_MIN (0) +#define CFG_QOS_WMM_INFRA_DIR_AC_VO_MAX (3) +#define CFG_QOS_WMM_INFRA_DIR_AC_VO_DEFAULT (3) //WLAN_QCT_CUST_WMM_TSDIR_BOTH + +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_NAME "InfraNomMsduSizeAcVo" +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_MIN (0x0) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_DEFAULT (0x80D0) + +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_NAME "InfraMeanDataRateAcVo" +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_DEFAULT (0x14500) + +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_NAME "InfraMinPhyRateAcVo" +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_DEFAULT (0x5B8D80) + +#define CFG_QOS_WMM_INFRA_SBA_AC_VO_NAME "InfraSbaAcVo" +#define CFG_QOS_WMM_INFRA_SBA_AC_VO_MIN (0x2001) +#define CFG_QOS_WMM_INFRA_SBA_AC_VO_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_SBA_AC_VO_DEFAULT (0x2001) + +/* default TSPEC parameters for AC_VI */ +#define CFG_QOS_WMM_INFRA_DIR_AC_VI_NAME "InfraDirAcVi" +#define CFG_QOS_WMM_INFRA_DIR_AC_VI_MIN (0) +#define CFG_QOS_WMM_INFRA_DIR_AC_VI_MAX (3) +#define CFG_QOS_WMM_INFRA_DIR_AC_VI_DEFAULT (3) //WLAN_QCT_CUST_WMM_TSDIR_BOTH + +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_NAME "InfraNomMsduSizeAcVi" +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_MIN (0x0) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_DEFAULT (0x85DC) + +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_NAME "InfraMeanDataRateAcVi" +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_DEFAULT (0x57E40) + +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_NAME "InfraMinPhyRateAcVi" +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_DEFAULT (0x5B8D80) + +#define CFG_QOS_WMM_INFRA_SBA_AC_VI_NAME "InfraSbaAcVi" +#define CFG_QOS_WMM_INFRA_SBA_AC_VI_MIN (0x2001) +#define CFG_QOS_WMM_INFRA_SBA_AC_VI_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_SBA_AC_VI_DEFAULT (0x2001) + +/* default TSPEC parameters for AC_BE*/ +#define CFG_QOS_WMM_INFRA_DIR_AC_BE_NAME "InfraDirAcBe" +#define CFG_QOS_WMM_INFRA_DIR_AC_BE_MIN (0) +#define CFG_QOS_WMM_INFRA_DIR_AC_BE_MAX (3) +#define CFG_QOS_WMM_INFRA_DIR_AC_BE_DEFAULT (3) //WLAN_QCT_CUST_WMM_TSDIR_BOTH + +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_NAME "InfraNomMsduSizeAcBe" +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_MIN (0x0) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_DEFAULT (0x85DC) + +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_NAME "InfraMeanDataRateAcBe" +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_DEFAULT (0x493E0) + +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_NAME "InfraMinPhyRateAcBe" +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_DEFAULT (0x5B8D80) + +#define CFG_QOS_WMM_INFRA_SBA_AC_BE_NAME "InfraSbaAcBe" +#define CFG_QOS_WMM_INFRA_SBA_AC_BE_MIN (0x2001) +#define CFG_QOS_WMM_INFRA_SBA_AC_BE_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_SBA_AC_BE_DEFAULT (0x2001) + +/* default TSPEC parameters for AC_Bk*/ +#define CFG_QOS_WMM_INFRA_DIR_AC_BK_NAME "InfraDirAcBk" +#define CFG_QOS_WMM_INFRA_DIR_AC_BK_MIN (0) +#define CFG_QOS_WMM_INFRA_DIR_AC_BK_MAX (3) +#define CFG_QOS_WMM_INFRA_DIR_AC_BK_DEFAULT (3) //WLAN_QCT_CUST_WMM_TSDIR_BOTH + +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_NAME "InfraNomMsduSizeAcBk" +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_MIN (0x0) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_DEFAULT (0x85DC) + +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_NAME "InfraMeanDataRateAcBk" +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_DEFAULT (0x493E0) + +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_NAME "InfraMinPhyRateAcBk" +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_MIN (0x0) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_MAX (0xFFFFFFFF) +#define CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_DEFAULT (0x5B8D80) + +#define CFG_QOS_WMM_INFRA_SBA_AC_BK_NAME "InfraSbaAcBk" +#define CFG_QOS_WMM_INFRA_SBA_AC_BK_MIN (0x2001) +#define CFG_QOS_WMM_INFRA_SBA_AC_BK_MAX (0xFFFF) +#define CFG_QOS_WMM_INFRA_SBA_AC_BK_DEFAULT (0x2001) + +// TL configuration +#define CFG_TL_DELAYED_TRGR_FRM_INT_NAME "DelayedTriggerFrmInt" +#define CFG_TL_DELAYED_TRGR_FRM_INT_MIN 1 +#define CFG_TL_DELAYED_TRGR_FRM_INT_MAX (4294967295UL) +#define CFG_TL_DELAYED_TRGR_FRM_INT_DEFAULT 3000 + +#if defined WLAN_FEATURE_VOWIFI +#define CFG_RRM_ENABLE_NAME "gRrmEnable" +#define CFG_RRM_ENABLE_MIN (0) +#define CFG_RRM_ENABLE_MAX (1) +#define CFG_RRM_ENABLE_DEFAULT (0) + +#define CFG_RRM_OPERATING_CHAN_MAX_DURATION_NAME "gRrmOperChanMax" //section 11.10.3 IEEE std. 802.11k-2008 +#define CFG_RRM_OPERATING_CHAN_MAX_DURATION_MIN (0) //Maxduration = 2^(maxDuration - 4) * bcnIntvl. +#define CFG_RRM_OPERATING_CHAN_MAX_DURATION_MAX (8) +#define CFG_RRM_OPERATING_CHAN_MAX_DURATION_DEFAULT (3) //max duration = 2^-1 * bcnIntvl (50% of bcn intvl) + +#define CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_NAME "gRrmNonOperChanMax" //Same as above. +#define CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_MIN (0) +#define CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_MAX (8) +#define CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_DEFAULT (3) + +#define CFG_RRM_MEAS_RANDOMIZATION_INTVL_NAME "gRrmRandnIntvl" +#define CFG_RRM_MEAS_RANDOMIZATION_INTVL_MIN (10) +#define CFG_RRM_MEAS_RANDOMIZATION_INTVL_MAX (100) +#define CFG_RRM_MEAS_RANDOMIZATION_INTVL_DEFAULT (100) + +/** + * This INI is used to configure RM enabled capabilities IE. + * Using this INI, we can set/unset any of the bits in 5 bytes + * (last 4bytes are reserved). Bit details are updated as per + * Draft version of 11mc spec. (Draft P802.11REVmc_D4.2) + * + * Bitwise details are defined as bit mask in rrmGlobal.h + * Comma is used as a separator for each byte. + */ +#define CFG_RM_CAPABILITY_NAME "rm_capability" +#define CFG_RM_CAPABILITY_DEFAULT "73,00,6D,00,04" +#endif + +#define CFG_QOS_IMPLICIT_SETUP_ENABLED_NAME "ImplicitQosIsEnabled" +#define CFG_QOS_IMPLICIT_SETUP_ENABLED_MIN (0) +#define CFG_QOS_IMPLICIT_SETUP_ENABLED_MAX (1) +#define CFG_QOS_IMPLICIT_SETUP_ENABLED_DEFAULT (1) + +#define CFG_ENABLE_LOGP_NAME "gEnableLogp" +#define CFG_ENABLE_LOGP_MIN ( 0 ) +#define CFG_ENABLE_LOGP_MAX ( 1 ) +#define CFG_ENABLE_LOGP_DEFAULT ( 0 ) + +#define CFG_BTC_EXECUTION_MODE_NAME "BtcExecutionMode" +#define CFG_BTC_EXECUTION_MODE_MIN ( 0 ) +#define CFG_BTC_EXECUTION_MODE_MAX ( 5 ) +#define CFG_BTC_EXECUTION_MODE_DEFAULT ( 0 ) + +#define CFG_MWS_COEX_CONFIG1_NAME "mwsCoexConfig1" +#define CFG_MWS_COEX_CONFIGX_MIN ( 0 ) +#define CFG_MWS_COEX_CONFIGX_MAX ( 0xFFFFFFFF ) +#define CFG_MWS_COEX_CONFIGX_DEFAULT ( 0 ) +#define CFG_MWS_COEX_CONFIG2_NAME "mwsCoexConfig2" +#define CFG_MWS_COEX_CONFIG3_NAME "mwsCoexConfig3" +#define CFG_MWS_COEX_CONFIG4_NAME "mwsCoexConfig4" +#define CFG_MWS_COEX_CONFIG5_NAME "mwsCoexConfig5" +#define CFG_MWS_COEX_CONFIG6_NAME "mwsCoexConfig6" + +#if defined WLAN_FEATURE_VOWIFI_11R +#define CFG_FT_RESOURCE_REQ_NAME "gFTResourceReqSupported" +#define CFG_FT_RESOURCE_REQ_MIN (0) +#define CFG_FT_RESOURCE_REQ_MAX (1) +#define CFG_FT_RESOURCE_REQ_DEFAULT (0) +#endif + +#define CFG_TELE_BCN_TRANS_LI_NAME "telescopicBeaconTransListenInterval" +#define CFG_TELE_BCN_TRANS_LI_MIN ( 0 ) +#define CFG_TELE_BCN_TRANS_LI_MAX ( 7 ) +#define CFG_TELE_BCN_TRANS_LI_DEFAULT ( 3 ) + +#define CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_NAME "telescopicBeaconTransListenIntervalNumIdleBcns" +#define CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_MIN ( 5 ) +#define CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_MAX ( 255 ) +#define CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_DEFAULT ( 10 ) + +#define CFG_TELE_BCN_MAX_LI_NAME "telescopicBeaconMaxListenInterval" +#define CFG_TELE_BCN_MAX_LI_MIN ( 0 ) +#define CFG_TELE_BCN_MAX_LI_MAX ( 7 ) +#define CFG_TELE_BCN_MAX_LI_DEFAULT ( 5 ) + +#define CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_NAME "telescopicBeaconMaxListenIntervalNumIdleBcns" +#define CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_MIN ( 5 ) +#define CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_MAX ( 255 ) +#define CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_DEFAULT ( 15 ) + +#define CFG_BCN_EARLY_TERM_WAKE_NAME "beaconEarlyTerminationWakeInterval" +#define CFG_BCN_EARLY_TERM_WAKE_MIN ( 2 ) +#define CFG_BCN_EARLY_TERM_WAKE_MAX ( 255 ) +#define CFG_BCN_EARLY_TERM_WAKE_DEFAULT ( 3 ) + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#define CFG_NEIGHBOR_SCAN_TIMER_PERIOD_NAME "gNeighborScanTimerPeriod" +#define CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN (3) +#define CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX (300) +#define CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT (200) + +#define CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_NAME "gNeighborReassocThreshold" +#define CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_MIN (10) +#define CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_MAX (125) +#define CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_DEFAULT (83) + +#define CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_NAME "gNeighborLookupThreshold" +#define CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN (10) +#define CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX (120) +#define CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT (78) + +#define CFG_DELAY_BEFORE_VDEV_STOP_NAME "gDelayBeforeVdevStop" +#define CFG_DELAY_BEFORE_VDEV_STOP_MIN (2) +#define CFG_DELAY_BEFORE_VDEV_STOP_MAX (200) +#define CFG_DELAY_BEFORE_VDEV_STOP_DEFAULT (20) + +/* + * This parameter is the drop in RSSI value that will trigger a precautionary + * scan by firmware. + * MAX value is choose so that this type of scan can be disabled by user. + */ +#define CFG_ROAM_RESCAN_RSSI_DIFF_NAME "gRoamRescanRssiDiff" +#define CFG_ROAM_RESCAN_RSSI_DIFF_MIN (0) +#define CFG_ROAM_RESCAN_RSSI_DIFF_MAX (100) +#define CFG_ROAM_RESCAN_RSSI_DIFF_DEFAULT (5) + +#define CFG_DROPPED_PKT_DISCONNECT_TH_NAME "gDroppedPktDisconnectTh" +#define CFG_DROPPED_PKT_DISCONNECT_TH_MIN (48) +#define CFG_DROPPED_PKT_DISCONNECT_TH_MAX (1024) +#define CFG_DROPPED_PKT_DISCONNECT_TH_DEFAULT (512) + +/* + * This parameter is the RSSI diff above neighbor lookup threshold, when + * opportunistic scan should be triggered. + * MAX value is choose so that this type of scan can be always enabled by user. + * MIN value will cause opportunistic scan to be triggered in neighbor lookup + * RSSI range. + */ +#define CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_NAME "gOpportunisticThresholdDiff" +#define CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_MIN (0) +#define CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_MAX (127) +#define CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_DEFAULT (0) + +#define CFG_NEIGHBOR_SCAN_CHAN_LIST_NAME "gNeighborScanChannelList" +#define CFG_NEIGHBOR_SCAN_CHAN_LIST_DEFAULT "" + +#define CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_NAME "gNeighborScanChannelMinTime" +#define CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN (10) +#define CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX (40) +#define CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT (20) + +#define CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_NAME "gNeighborScanChannelMaxTime" +#define CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN (3) +#define CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX (300) +#define CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT (30) + +#define CFG_11R_NEIGHBOR_REQ_MAX_TRIES_NAME "gMaxNeighborReqTries" +#define CFG_11R_NEIGHBOR_REQ_MAX_TRIES_MIN (1) +#define CFG_11R_NEIGHBOR_REQ_MAX_TRIES_MAX (4) +#define CFG_11R_NEIGHBOR_REQ_MAX_TRIES_DEFAULT (3) + + +#define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_NAME "gNeighborScanRefreshPeriod" +#define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN (1000) +#define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX (60000) +#define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT (20000) + +#define CFG_EMPTY_SCAN_REFRESH_PERIOD_NAME "gEmptyScanRefreshPeriod" +#define CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN (0) +#define CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX (60000) +#define CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT (0) + +#define CFG_ROAM_BMISS_FIRST_BCNT_NAME "gRoamBmissFirstBcnt" +#define CFG_ROAM_BMISS_FIRST_BCNT_MIN (5) +#define CFG_ROAM_BMISS_FIRST_BCNT_MAX (100) +#define CFG_ROAM_BMISS_FIRST_BCNT_DEFAULT (10) + +#define CFG_ROAM_BMISS_FINAL_BCNT_NAME "gRoamBmissFinalBcnt" +#define CFG_ROAM_BMISS_FINAL_BCNT_MIN (5) +#define CFG_ROAM_BMISS_FINAL_BCNT_MAX (100) +#define CFG_ROAM_BMISS_FINAL_BCNT_DEFAULT (10) + +#define CFG_ROAM_BEACON_RSSI_WEIGHT_NAME "gRoamBeaconRssiWeight" +#define CFG_ROAM_BEACON_RSSI_WEIGHT_MIN (0) +#define CFG_ROAM_BEACON_RSSI_WEIGHT_MAX (16) +#define CFG_ROAM_BEACON_RSSI_WEIGHT_DEFAULT (14) +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ + +#define CFG_QOS_WMM_BURST_SIZE_DEFN_NAME "burstSizeDefinition" +#define CFG_QOS_WMM_BURST_SIZE_DEFN_MIN (0) +#define CFG_QOS_WMM_BURST_SIZE_DEFN_MAX (1) +#define CFG_QOS_WMM_BURST_SIZE_DEFN_DEFAULT (0) + +#define CFG_QOS_WMM_TS_INFO_ACK_POLICY_NAME "tsInfoAckPolicy" +#define CFG_QOS_WMM_TS_INFO_ACK_POLICY_MIN (0x00) +#define CFG_QOS_WMM_TS_INFO_ACK_POLICY_MAX (0x01) +#define CFG_QOS_WMM_TS_INFO_ACK_POLICY_DEFAULT (0x00) + +#define CFG_SINGLE_TID_RC_NAME "SingleTIDRC" +#define CFG_SINGLE_TID_RC_MIN (0) /* Separate replay counter for all TID */ +#define CFG_SINGLE_TID_RC_MAX (1) /* Single replay counter for all TID */ +#define CFG_SINGLE_TID_RC_DEFAULT (1) + +#define CFG_MCAST_BCAST_FILTER_SETTING_NAME "McastBcastFilter" +#define CFG_MCAST_BCAST_FILTER_SETTING_MIN (0) +#define CFG_MCAST_BCAST_FILTER_SETTING_MAX (3) +#define CFG_MCAST_BCAST_FILTER_SETTING_DEFAULT (0) + +#define CFG_DYNAMIC_PSPOLL_VALUE_NAME "gDynamicPSPollvalue" +#define CFG_DYNAMIC_PSPOLL_VALUE_MIN (0) +#define CFG_DYNAMIC_PSPOLL_VALUE_MAX (255) +#define CFG_DYNAMIC_PSPOLL_VALUE_DEFAULT (0) + +#define CFG_TELE_BCN_WAKEUP_EN_NAME "gTelescopicBeaconWakeupEn" +#define CFG_TELE_BCN_WAKEUP_EN_MIN (0) +#define CFG_TELE_BCN_WAKEUP_EN_MAX (1) +#define CFG_TELE_BCN_WAKEUP_EN_DEFAULT (0) + +#define CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_NAME "gAddTSWhenACMIsOff" +#define CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_MIN (0) +#define CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_MAX (1) //Send AddTs even when ACM is not set for the AC +#define CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_DEFAULT (0) + +/* + * This flag will take effect only when Runtime PM is active. + * APPS will be awake during runtime PM, if any user space application + * needs the broadcast packets OEM's can enable gRuntimePmEnableBcastPattern. + * FW will filter the broadcast packets and wakeup host to deliver them during + * runtime suspend. + */ + +#define CFG_ENABLE_HOST_BROADCAST_NAME "gRuntimePmEnableBcastPattern" +#define CFG_ENABLE_HOST_BROADCAST_MIN (0) +#define CFG_ENABLE_HOST_BROADCAST_MAX (1) +#define CFG_ENABLE_HOST_BROADCAST_DEFAULT (0) + + +#define CFG_VALIDATE_SCAN_LIST_NAME "gValidateScanList" +#define CFG_VALIDATE_SCAN_LIST_MIN (0) +#define CFG_VALIDATE_SCAN_LIST_MAX (1) +#define CFG_VALIDATE_SCAN_LIST_DEFAULT (0) + +#define CFG_NULLDATA_AP_RESP_TIMEOUT_NAME "gNullDataApRespTimeout" +#define CFG_NULLDATA_AP_RESP_TIMEOUT_MIN ( WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMIN ) +#define CFG_NULLDATA_AP_RESP_TIMEOUT_MAX ( WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMAX ) +#define CFG_NULLDATA_AP_RESP_TIMEOUT_DEFAULT ( WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STADEF ) + +#define CFG_AP_DATA_AVAIL_POLL_PERIOD_NAME "gApDataAvailPollInterval" +#define CFG_AP_DATA_AVAIL_POLL_PERIOD_MIN ( WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMIN ) +#define CFG_AP_DATA_AVAIL_POLL_PERIOD_MAX ( WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMAX ) +#define CFG_AP_DATA_AVAIL_POLL_PERIOD_DEFAULT ( WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STADEF ) + +#define CFG_ENABLE_HOST_ARPOFFLOAD_NAME "hostArpOffload" +#define CFG_ENABLE_HOST_ARPOFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_HOST_ARPOFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_HOST_ARPOFFLOAD_DEFAULT ( 0 ) + +#define CFG_ENABLE_HOST_SSDP_NAME "ssdp" +#define CFG_ENABLE_HOST_SSDP_MIN ( 0 ) +#define CFG_ENABLE_HOST_SSDP_MAX ( 1 ) +#define CFG_ENABLE_HOST_SSDP_DEFAULT ( 1 ) + +#ifdef FEATURE_RUNTIME_PM +#define CFG_ENABLE_RUNTIME_PM "gRuntimePM" +#define CFG_ENABLE_RUNTIME_PM_MIN ( 0 ) +#define CFG_ENABLE_RUNTIME_PM_MAX ( 1 ) +#define CFG_ENABLE_RUNTIME_PM_DEFAULT ( 0 ) + +#define CFG_RUNTIME_PM_AUTO_NAME "gRuntimePMDelay" +#define CFG_RUNTIME_PM_AUTO_MIN ( 100 ) +#define CFG_RUNTIME_PM_AUTO_MAX ( 10000 ) +#define CFG_RUNTIME_PM_AUTO_DEFAULT ( 500 ) +#endif + +#ifdef FEATURE_SECURE_FIRMWARE +#define CFG_ENABLE_FW_HASH_CHECK_NAME "gEnableFWHashCheck" +#define CFG_ENABLE_FW_HASH_CHECK_MIN ( 0 ) +#define CFG_ENABLE_FW_HASH_CHECK_MAX ( 1 ) +#define CFG_ENABLE_FW_HASH_CHECK_DEFAULT ( 1 ) +#endif + +#define CFG_ENABLE_HOST_NSOFFLOAD_NAME "hostNSOffload" +#define CFG_ENABLE_HOST_NSOFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_DEFAULT ( 0 ) + + +#define CFG_BAND_CAPABILITY_NAME "BandCapability" +#define CFG_BAND_CAPABILITY_MIN (0) +#define CFG_BAND_CAPABILITY_MAX (2) +#define CFG_BAND_CAPABILITY_DEFAULT (0) + +#define CFG_ENABLE_BEACON_EARLY_TERMINATION_NAME "enableBeaconEarlyTermination" +#define CFG_ENABLE_BEACON_EARLY_TERMINATION_MIN ( 0 ) +#define CFG_ENABLE_BEACON_EARLY_TERMINATION_MAX ( 1 ) +#define CFG_ENABLE_BEACON_EARLY_TERMINATION_DEFAULT ( 0 ) + +#define CFG_ENABLE_CLOSE_LOOP_NAME "gEnableCloseLoop" +#define CFG_ENABLE_CLOSE_LOOP_MIN WNI_CFG_FIXED_RATE_STAMIN +#define CFG_ENABLE_CLOSE_LOOP_MAX WNI_CFG_FIXED_RATE_STAMAX +#define CFG_ENABLE_CLOSE_LOOP_DEFAULT WNI_CFG_FIXED_RATE_STADEF + +#define CFG_ENABLE_BYPASS_11D_NAME "gEnableBypass11d" +#define CFG_ENABLE_BYPASS_11D_MIN ( 0 ) +#define CFG_ENABLE_BYPASS_11D_MAX ( 1 ) +#define CFG_ENABLE_BYPASS_11D_DEFAULT ( 1 ) + +#define CFG_ENABLE_DFS_CHNL_SCAN_NAME "gEnableDFSChnlScan" +#define CFG_ENABLE_DFS_CHNL_SCAN_MIN ( 0 ) +#define CFG_ENABLE_DFS_CHNL_SCAN_MAX ( 1 ) +#define CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT ( 1 ) + +#define CFG_ENABLE_DFS_PNO_CHNL_SCAN_NAME "gEnableDFSPnoChnlScan" +#define CFG_ENABLE_DFS_PNO_CHNL_SCAN_MIN ( 0 ) +#define CFG_ENABLE_DFS_PNO_CHNL_SCAN_MAX ( 1 ) +#define CFG_ENABLE_DFS_PNO_CHNL_SCAN_DEFAULT ( 1 ) + +#define CFG_ENABLE_RAMDUMP_COLLECTION "gEnableDumpCollect" +#define CFG_ENABLE_RAMDUMP_COLLECTION_MIN ( 0 ) +#define CFG_ENABLE_RAMDUMP_COLLECTION_MAX ( 1 ) +#define CFG_ENABLE_RAMDUMP_COLLECTION_DEFAULT ( 1 ) + +typedef enum +{ + eHDD_LINK_SPEED_REPORT_ACTUAL = 0, + eHDD_LINK_SPEED_REPORT_MAX = 1, + eHDD_LINK_SPEED_REPORT_MAX_SCALED = 2, +}eHddLinkSpeedReportType; +#ifdef WLAN_FEATURE_11AC +#define CFG_VHT_CHANNEL_WIDTH "gVhtChannelWidth" +#define CFG_VHT_CHANNEL_WIDTH_MIN ( 0 ) +#define CFG_VHT_CHANNEL_WIDTH_MAX ( 2 ) +#define CFG_VHT_CHANNEL_WIDTH_DEFAULT ( 2 ) + +#define CFG_VHT_ENABLE_RX_MCS_8_9 "gVhtRxMCS" +#define CFG_VHT_ENABLE_RX_MCS_8_9_MIN ( 0 ) +#define CFG_VHT_ENABLE_RX_MCS_8_9_MAX ( 2 ) +#define CFG_VHT_ENABLE_RX_MCS_8_9_DEFAULT ( 0 ) + +#define CFG_VHT_ENABLE_TX_MCS_8_9 "gVhtTxMCS" +#define CFG_VHT_ENABLE_TX_MCS_8_9_MIN ( 0 ) +#define CFG_VHT_ENABLE_TX_MCS_8_9_MAX ( 2 ) +#define CFG_VHT_ENABLE_TX_MCS_8_9_DEFAULT ( 0 ) + +#define CFG_VHT_ENABLE_RX_MCS2x2_8_9 "gVhtRxMCS2x2" +#define CFG_VHT_ENABLE_RX_MCS2x2_8_9_MIN ( 0 ) +#define CFG_VHT_ENABLE_RX_MCS2x2_8_9_MAX ( 2 ) +#define CFG_VHT_ENABLE_RX_MCS2x2_8_9_DEFAULT ( 0 ) + +#define CFG_VHT_ENABLE_TX_MCS2x2_8_9 "gVhtTxMCS2x2" +#define CFG_VHT_ENABLE_TX_MCS2x2_8_9_MIN ( 0 ) +#define CFG_VHT_ENABLE_TX_MCS2x2_8_9_MAX ( 2 ) +#define CFG_VHT_ENABLE_TX_MCS2x2_8_9_DEFAULT ( 0 ) + +#define CFG_VHT_ENABLE_2x2_CAP_FEATURE "gEnable2x2" +#define CFG_VHT_ENABLE_2x2_CAP_FEATURE_MIN ( 0 ) +#define CFG_VHT_ENABLE_2x2_CAP_FEATURE_MAX ( 1 ) +#define CFG_VHT_ENABLE_2x2_CAP_FEATURE_DEFAULT ( 0 ) + +/* + * Valid chain mask values. + * 01 - enables chain0 + * 02 - enables chain1 + * 03 - enables both chain 0 and chain 1 + */ +#define CFG_CHAIN_MASK_2G "gChainMask_2g" +#define CFG_CHAIN_MASK_2G_MIN ( 1 ) +#define CFG_CHAIN_MASK_2G_MAX ( 3 ) +#define CFG_CHAIN_MASK_2G_DEFAULT ( 3 ) + +#define CFG_CHAIN_MASK_5G "gChainMask_5g" +#define CFG_CHAIN_MASK_5G_MIN ( 1 ) +#define CFG_CHAIN_MASK_5G_MAX ( 3 ) +#define CFG_CHAIN_MASK_5G_DEFAULT ( 3 ) +/* + * NSS cfg bit definition. + * STA BIT[0:1] + * SAP BIT[2:3] + * P2P_GO BIT[4:5] + * P2P_CLIENT BIT[6:7] + * IBSS BIT[8:9] + * TDLS BIT[10:11] + * P2P_DEVICE BIT[12:13] + * OCB BIT[14:15] + */ +#define CFG_VDEV_TYPE_NSS_2G "gVdevTypeNss_2g" +#define CFG_VDEV_TYPE_NSS_2G_MIN ( 0x5555 ) +#define CFG_VDEV_TYPE_NSS_2G_MAX ( 0xAAAA ) +#define CFG_VDEV_TYPE_NSS_2G_DEFAULT ( 0xAAAA ) + +#define CFG_VDEV_TYPE_NSS_5G "gVdevTypeNss_5g" +#define CFG_VDEV_TYPE_NSS_5G_MIN ( 0x5555 ) +#define CFG_VDEV_TYPE_NSS_5G_MAX ( 0xAAAA ) +#define CFG_VDEV_TYPE_NSS_5G_DEFAULT ( 0xAAAA ) + +#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE "gEnableMuBformee" +#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_MIN ( 0 ) +#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_MAX ( 1 ) +#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_DEFAULT ( 1 ) + +#define CFG_VHT_ENABLE_PAID_FEATURE "gEnablePAID" +#define CFG_VHT_ENABLE_PAID_FEATURE_MIN ( 0 ) +#define CFG_VHT_ENABLE_PAID_FEATURE_MAX ( 1 ) +#define CFG_VHT_ENABLE_PAID_FEATURE_DEFAULT ( 0 ) + +#define CFG_VHT_ENABLE_GID_FEATURE "gEnableGID" +#define CFG_VHT_ENABLE_GID_FEATURE_MIN ( 0 ) +#define CFG_VHT_ENABLE_GID_FEATURE_MAX ( 1 ) +#define CFG_VHT_ENABLE_GID_FEATURE_DEFAULT ( 0 ) +#endif + +#define CFG_VHT_ENABLE_1x1_TX_CHAINMASK "gSetTxChainmask1x1" +#define CFG_VHT_ENABLE_1x1_TX_CHAINMASK_MIN ( 1 ) +#define CFG_VHT_ENABLE_1x1_TX_CHAINMASK_MAX ( 2 ) +#define CFG_VHT_ENABLE_1x1_TX_CHAINMASK_DEFAULT ( 1 ) + +#define CFG_VHT_ENABLE_1x1_RX_CHAINMASK "gSetRxChainmask1x1" +#define CFG_VHT_ENABLE_1x1_RX_CHAINMASK_MIN ( 1 ) +#define CFG_VHT_ENABLE_1x1_RX_CHAINMASK_MAX ( 2 ) +#define CFG_VHT_ENABLE_1x1_RX_CHAINMASK_DEFAULT ( 1 ) + +#define CFG_ENABLE_AMPDUPS_FEATURE "gEnableAMPDUPS" +#define CFG_ENABLE_AMPDUPS_FEATURE_MIN ( 0 ) +#define CFG_ENABLE_AMPDUPS_FEATURE_MAX ( 1 ) +#define CFG_ENABLE_AMPDUPS_FEATURE_DEFAULT ( 0 ) + +#define CFG_HT_ENABLE_SMPS_CAP_FEATURE "gEnableHtSMPS" +#define CFG_HT_ENABLE_SMPS_CAP_FEATURE_MIN ( 0 ) +#define CFG_HT_ENABLE_SMPS_CAP_FEATURE_MAX ( 1 ) +#define CFG_HT_ENABLE_SMPS_CAP_FEATURE_DEFAULT ( 0 ) + +#define CFG_HT_SMPS_CAP_FEATURE "gHtSMPS" +#define CFG_HT_SMPS_CAP_FEATURE_MIN ( 0 ) +#define CFG_HT_SMPS_CAP_FEATURE_MAX ( 3 ) +#define CFG_HT_SMPS_CAP_FEATURE_DEFAULT ( 3 ) + +#define CFG_DISABLE_DFS_CH_SWITCH "gDisableDFSChSwitch" +#define CFG_DISABLE_DFS_CH_SWITCH_MIN ( 0 ) +#define CFG_DISABLE_DFS_CH_SWITCH_MAX ( 1 ) +#define CFG_DISABLE_DFS_CH_SWITCH_DEFAULT ( 0 ) + +#define CFG_ENABLE_DFS_MASTER_CAPABILITY "gEnableDFSMasterCap" +#define CFG_ENABLE_DFS_MASTER_CAPABILITY_MIN ( 0 ) +#define CFG_ENABLE_DFS_MASTER_CAPABILITY_MAX ( 1 ) +#define CFG_ENABLE_DFS_MASTER_CAPABILITY_DEFAULT ( 0 ) + +/* + * This parameter indicates if SAP preferred + * channel are INDOOR/OUTDOOR Channels. + * 0- Indicates no preferred channel location or + * no preferred channel restrictions. + * 1- Indicates Use only Indoor channels only. + * 2- Indicates Use outdoor channels only. + */ +#define CFG_SAP_PREFERRED_CHANNEL_LOCATION "gSapPreferredChanLocation" +#define CFG_SAP_PREFERRED_CHANNEL_LOCATION_MIN ( 0 ) +#define CFG_SAP_PREFERRED_CHANNEL_LOCATION_MAX ( 2 ) +#define CFG_SAP_PREFERRED_CHANNEL_LOCATION_DEFAULT ( 0 ) + +#define CFG_DISABLE_DFS_JAPAN_W53 "gDisableDfsJapanW53" +#define CFG_DISABLE_DFS_JAPAN_W53_MIN ( 0 ) +#define CFG_DISABLE_DFS_JAPAN_W53_MAX ( 1 ) +#define CFG_DISABLE_DFS_JAPAN_W53_DEFAULT ( 0 ) + +#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_NAME "dfsPhyerrFilterOffload" +#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_DEFAULT ( 0 ) + +#define CFG_REPORT_MAX_LINK_SPEED "gReportMaxLinkSpeed" +#define CFG_REPORT_MAX_LINK_SPEED_MIN ( eHDD_LINK_SPEED_REPORT_ACTUAL ) +#define CFG_REPORT_MAX_LINK_SPEED_MAX ( eHDD_LINK_SPEED_REPORT_MAX_SCALED ) +#define CFG_REPORT_MAX_LINK_SPEED_DEFAULT ( eHDD_LINK_SPEED_REPORT_MAX_SCALED ) + +/* + * RSSI Thresholds + * Used when eHDD_LINK_SPEED_REPORT_SCALED is selected + */ +#define CFG_LINK_SPEED_RSSI_HIGH "gLinkSpeedRssiHigh" +#define CFG_LINK_SPEED_RSSI_HIGH_MIN ( -127 ) +#define CFG_LINK_SPEED_RSSI_HIGH_MAX ( 0 ) +#define CFG_LINK_SPEED_RSSI_HIGH_DEFAULT ( -55 ) + +#define CFG_LINK_SPEED_RSSI_MID "gLinkSpeedRssiMed" +#define CFG_LINK_SPEED_RSSI_MID_MIN ( -127 ) +#define CFG_LINK_SPEED_RSSI_MID_MAX ( 0 ) +#define CFG_LINK_SPEED_RSSI_MID_DEFAULT ( -65 ) + +#define CFG_LINK_SPEED_RSSI_LOW "gLinkSpeedRssiLow" +#define CFG_LINK_SPEED_RSSI_LOW_MIN ( -127 ) +#define CFG_LINK_SPEED_RSSI_LOW_MAX ( 0 ) +#define CFG_LINK_SPEED_RSSI_LOW_DEFAULT ( -80 ) + +#define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME "isP2pDeviceAddrAdministrated" +#define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MIN ( 0 ) +#define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MAX ( 1 ) +#define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_DEFAULT ( 1 ) + + +#define CFG_ENABLE_SSR "gEnableSSR" +#define CFG_ENABLE_SSR_MIN ( 0 ) +#define CFG_ENABLE_SSR_MAX ( 1 ) +#define CFG_ENABLE_SSR_DEFAULT ( 1 ) + +#define CFG_ENABLE_OVERLAP_CH "gEnableOverLapCh" +#define CFG_ENABLE_OVERLAP_CH_MIN ( 0 ) +#define CFG_ENABLE_OVERLAP_CH_MAX ( 1 ) +#define CFG_ENABLE_OVERLAP_CH_DEFAULT ( 0 ) + +#define CFG_PPS_ENABLE_5G_EBT "gEnable5gEBT" +#define CFG_PPS_ENABLE_5G_EBT_FEATURE_MIN ( 0 ) +#define CFG_PPS_ENABLE_5G_EBT_FEATURE_MAX ( 1 ) +#define CFG_PPS_ENABLE_5G_EBT_FEATURE_DEFAULT ( 0 ) + +#define CFG_ENABLE_MEMORY_DEEP_SLEEP "gEnableMemDeepSleep" +#define CFG_ENABLE_MEMORY_DEEP_SLEEP_MIN ( 0 ) +#define CFG_ENABLE_MEMORY_DEEP_SLEEP_MAX ( 1 ) +#define CFG_ENABLE_MEMORY_DEEP_SLEEP_DEFAULT ( 1 ) + +/* 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. +*/ + +#define CFG_DEFAULT_RATE_INDEX_24GH "gDefaultRateIndex24Ghz" +#define CFG_DEFAULT_RATE_INDEX_24GH_MIN ( 1 ) +#define CFG_DEFAULT_RATE_INDEX_24GH_MAX ( 9 ) +#define CFG_DEFAULT_RATE_INDEX_24GH_DEFAULT ( 1 ) + + +#define CFG_ENABLE_PACKET_LOG "gEnablePacketLog" +#define CFG_ENABLE_PACKET_LOG_MIN (0) +#define CFG_ENABLE_PACKET_LOG_MAX (1) +#define CFG_ENABLE_PACKET_LOG_DEFAULT (1) + +/* gFwDebugLogType takes values from enum dbglog_process_t, + * make default value as DBGLOG_PROCESS_NET_RAW to give the + * logs to net link since cnss_diag service is started at boot + * time by default. + */ +#define CFG_ENABLE_FW_LOG_TYPE "gFwDebugLogType" +#define CFG_ENABLE_FW_LOG_TYPE_MIN ( 0 ) +#define CFG_ENABLE_FW_LOG_TYPE_MAX ( 255 ) +#define CFG_ENABLE_FW_LOG_TYPE_DEFAULT ( 3 ) + +/* gFwDebugLogLevel takes values from enum DBGLOG_LOG_LVL, + * make default value as DBGLOG_WARN to enable error and + * warning logs by default. + */ +#define CFG_ENABLE_FW_DEBUG_LOG_LEVEL "gFwDebugLogLevel" +#define CFG_ENABLE_FW_DEBUG_LOG_LEVEL_MIN ( 0 ) +#define CFG_ENABLE_FW_DEBUG_LOG_LEVEL_MAX ( 255 ) +#define CFG_ENABLE_FW_DEBUG_LOG_LEVEL_DEFAULT ( 4 ) + +/* For valid values of log levels check enum DBGLOG_LOG_LVL and + * for valid values of module ids check enum WLAN_MODULE_ID. + */ +#define CFG_ENABLE_FW_MODULE_LOG_LEVEL "gFwDebugModuleLoglevel" +#define CFG_ENABLE_FW_MODULE_LOG_DEFAULT "" + +/* gEnableRTSProfiles for configuring different RTS profiles + * to firmware. + * Following are the valid values for the rtsprofile: + * RTSCTS_DISABLED 0 + * RTSCTS_ENABLED_4_SECOND_RATESERIES 17 + * CTS2SELF_ENABLED_4_SECOND_RATESERIES 18 + * RTSCTS_ENABLED_4_SWRETRIES 33 + * CTS2SELF_ENABLED_4_SWRETRIES 34 + */ +#define CFG_ENABLE_FW_RTS_PROFILE "gEnableRTSProfiles" +#define CFG_ENABLE_FW_RTS_PROFILE_MIN (0) +#define CFG_ENABLE_FW_RTS_PROFILE_MAX (34) +#define CFG_ENABLE_FW_RTS_PROFILE_DEFAULT (33) + +#ifdef FEATURE_GREEN_AP +#define CFG_ENABLE_GREEN_AP_FEATURE "gEnableGreenAp" +#define CFG_ENABLE_GREEN_AP_FEATURE_MIN ( 0 ) +#define CFG_ENABLE_GREEN_AP_FEATURE_MAX ( 1 ) +#define CFG_ENABLE_GREEN_AP_FEATURE_DEFAULT ( 1 ) +#endif + +/* + * This INI item is used to control subsystem restart(SSR) test framework + * Set its value to 1 to enable APPS trigerred SSR testing + */ +#define CFG_ENABLE_CRASH_INJECT "gEnableForceTargetAssert" +#define CFG_ENABLE_CRASH_INJECT_MIN (0) +#define CFG_ENABLE_CRASH_INJECT_MAX (1) +#define CFG_ENABLE_CRASH_INJECT_DEFAULT (0) + +#ifdef FEATURE_WLAN_FORCE_SAP_SCC +#define CFG_SAP_SCC_CHAN_AVOIDANCE "gSapSccChanAvoidance" +#define CFG_SAP_SCC_CHAN_AVOIDANCE_MIN ( 0 ) +#define CFG_SAP_SCC_CHAN_AVOIDANCE_MAX ( 1 ) +#define CFG_SAP_SCC_CHAN_AVOIDANCE_DEFAULT ( 0 ) +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + +#ifdef IPA_UC_STA_OFFLOAD +#define CFG_IPA_UC_STA_OFFLOAD "gIpaUcStaOffload" +#define CFG_IPA_UC_STA_OFFLOAD_MIN ( 0 ) +#define CFG_IPA_UC_STA_OFFLOAD_MAX ( 1 ) +#define CFG_IPA_UC_STA_OFFLOAD_DEFAULT ( 0 ) +#endif /* IPA_UC_STA_OFFLOAD */ + +/* + * VOS Trace Enable Control + * Notes: + * the MIN/MAX/DEFAULT values apply for all modules + * the DEFAULT value is outside the valid range. if the DEFAULT + * value is not overridden, then no change will be made to the + * "built in" default values compiled into the code + * values are a bitmap indicating which log levels are to enabled + * (must match order of vos_trace_level enumerations) + * 00000001 FATAL + * 00000010 ERROR + * 00000100 WARN + * 00001000 INFO + * 00010000 INFO HIGH + * 00100000 INFO MED + * 01000000 INFO LOW + * 10000000 DEBUG + * + * hence a value of 0xFF would set all bits (enable all logs) + */ + +#define CFG_VOS_TRACE_ENABLE_TL_NAME "vosTraceEnableTL" +#define CFG_VOS_TRACE_ENABLE_WDI_NAME "vosTraceEnableWDI" +#define CFG_VOS_TRACE_ENABLE_HDD_NAME "vosTraceEnableHDD" +#define CFG_VOS_TRACE_ENABLE_SME_NAME "vosTraceEnableSME" +#define CFG_VOS_TRACE_ENABLE_PE_NAME "vosTraceEnablePE" +#define CFG_VOS_TRACE_ENABLE_PMC_NAME "vosTraceEnablePMC" +#define CFG_VOS_TRACE_ENABLE_WDA_NAME "vosTraceEnableWDA" +#define CFG_VOS_TRACE_ENABLE_SYS_NAME "vosTraceEnableSYS" +#define CFG_VOS_TRACE_ENABLE_VOSS_NAME "vosTraceEnableVOSS" +#define CFG_VOS_TRACE_ENABLE_SAP_NAME "vosTraceEnableSAP" +#define CFG_VOS_TRACE_ENABLE_HDD_SAP_NAME "vosTraceEnableHDDSAP" +#define CFG_VOS_TRACE_ENABLE_CFG_NAME "vosTraceEnableCFG" +#define CFG_VOS_TRACE_ENABLE_ADF_NAME "vosTraceEnableADF" +#define CFG_VOS_TRACE_ENABLE_TXRX_NAME "vosTraceEnableTXRX" +#define CFG_VOS_TRACE_ENABLE_HTC_NAME "vosTraceEnableHTC" +#define CFG_VOS_TRACE_ENABLE_HIF_NAME "vosTraceEnableHIF" +#define CFG_VOS_TRACE_ENABLE_HDD_SAP_DATA_NAME "vosTraceEnableHDDSAPDATA" +#define CFG_VOS_TRACE_ENABLE_HDD_DATA_NAME "vosTraceEnableHDDDATA" + +#define CFG_VOS_TRACE_ENABLE_MIN (0) +#define CFG_VOS_TRACE_ENABLE_MAX (0xff) +#define CFG_VOS_TRACE_ENABLE_DEFAULT (0xffff) + +#define HDD_MCASTBCASTFILTER_FILTER_NONE 0x00 +#define HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST 0x01 +#define HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST 0x02 +#define HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST 0x03 +#define HDD_MULTICAST_FILTER_LIST 0x04 +#define HDD_MULTICAST_FILTER_LIST_CLEAR 0x05 + +/* + * Driver Force ACS is reintroduced for android SAP legacy configuration method. + * If Driver force acs is enabled, channel/ hw config from hostapd is ignored. + * Driver uses INI params dot11Mode, channel bonding mode and vht chan width + * to derive ACS HW mode and operating BW. + * + * Non android platforms shall not use force ACS method and rely on hostapd + * driven ACS method for concurrent SAP ACS configuration, OBSS etc. + */ + +#define CFG_FORCE_SAP_ACS "gApAutoChannelSelection" +#define CFG_FORCE_SAP_ACS_MIN (0) +#define CFG_FORCE_SAP_ACS_MAX (1) +#define CFG_FORCE_SAP_ACS_DEFAULT (0) + +#define CFG_FORCE_SAP_ACS_START_CH "gAPChannelSelectStartChannel" +#define CFG_FORCE_SAP_ACS_START_CH_MIN (0) +#define CFG_FORCE_SAP_ACS_START_CH_MAX (0xFF) +#define CFG_FORCE_SAP_ACS_START_CH_DEFAULT (1) + +#define CFG_FORCE_SAP_ACS_END_CH "gAPChannelSelectEndChannel" +#define CFG_FORCE_SAP_ACS_END_CH_MIN (0) +#define CFG_FORCE_SAP_ACS_END_CH_MAX (0xFF) +#define CFG_FORCE_SAP_ACS_END_CH_DEFAULT (11) + +/* ACS Scan band preference + * 0 -- No preference + * 1 -- Scan 2.4G first + * 2 -- Scan 5G first +*/ +#define CFG_SAP_SCAN_BAND_PREFERENCE "gAcsScanBandPreference" +#define CFG_SAP_SCAN_BAND_PREFERENCE_MIN (0) +#define CFG_SAP_SCAN_BAND_PREFERENCE_MAX (2) +#define CFG_SAP_SCAN_BAND_PREFERENCE_DEFAULT (0) +#define CFG_ACS_BAND_SWITCH_THRESHOLD "gACSBandSwitchThreshold" +#define CFG_ACS_BAND_SWITCH_THRESHOLD_MIN (0) +#define CFG_ACS_BAND_SWITCH_THRESHOLD_MAX (4444) +/* 2 BSS, maximum RSSI -90 */ +#define CFG_ACS_BAND_SWITCH_THRESHOLD_DEFAULT (296) + +/*BMPS Logic + * Notes: + * 1 - Then Host driver and above layers control the PS mechanism + * 0 - Diver/Core Stack internally control the Power saving mechanism + */ +#define CFG_ANDRIOD_POWER_SAVE_NAME "isAndroidPsEn" +#define CFG_ANDRIOD_POWER_SAVE_MIN ( 0 ) +#define CFG_ANDRIOD_POWER_SAVE_MAX ( 1 ) +#define CFG_ANDRIOD_POWER_SAVE_DEFAULT ( 0 ) + + +/* + * Enable Dynamic DTIM + * Options + * 0 -Disable DynamicDTIM + * 1 to 5 - SLM will switch to DTIM specified here when host suspends and + * switch DTIM1 when host resumes */ +#define CFG_ENABLE_DYNAMIC_DTIM_NAME "gEnableDynamicDTIM" +#define CFG_ENABLE_DYNAMIC_DTIM_MIN ( 0 ) +#define CFG_ENABLE_DYNAMIC_DTIM_MAX ( 5 ) +#define CFG_ENABLE_DYNAMIC_DTIM_DEFAULT ( 0 ) + +/* + * Enable First Scan 2G Only + * Options + * 0 - Disable First Scan 2G Option + * 1 - Enable First Scan 2G Option + */ +#define CFG_ENABLE_FIRST_SCAN_2G_ONLY_NAME "gEnableFirstScan2GOnly" +#define CFG_ENABLE_FIRST_SCAN_2G_ONLY_MIN ( 0 ) +#define CFG_ENABLE_FIRST_SCAN_2G_ONLY_MAX ( 1 ) +#define CFG_ENABLE_FIRST_SCAN_2G_ONLY_DEFAULT ( 0 ) + +/* + * Skip DFS Channel in case of P2P Search + * Options + * 0 - Don't Skip DFS Channel in case of P2P Search + * 1 - Skip DFS Channel in case of P2P Search + */ +#define CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_NAME "gSkipDfsChannelInP2pSearch" +#define CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_MIN ( 0 ) +#define CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_MAX ( 1 ) +#define CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_DEFAULT ( 1 ) + +/* + * Ignore Dynamic Dtim in case of P2P + * Options + * 0 - Consider Dynamic Dtim incase of P2P + * 1 - Ignore Dynamic Dtim incase of P2P + */ +#define CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_NAME "gIgnoreDynamicDtimInP2pMode" +#define CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_MIN ( 0 ) +#define CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_MAX ( 1 ) +#define CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_DEFAULT ( 0 ) + + +#define CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_NAME "gEnableAutomaticTxPowerControl" +#define CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_MIN ( 0 ) +#define CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_MAX ( 1 ) +#define CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_DEFAULT ( 1 ) + +#define CFG_SHORT_GI_40MHZ_NAME "gShortGI40Mhz" +#define CFG_SHORT_GI_40MHZ_MIN 0 +#define CFG_SHORT_GI_40MHZ_MAX 1 +#define CFG_SHORT_GI_40MHZ_DEFAULT 1 + +/* + * Enable / Disable MCC feature + * Default: Enable + */ +#define CFG_ENABLE_MCC_ENABLED_NAME "gEnableMCCMode" +#define CFG_ENABLE_MCC_ENABLED_MIN ( 0 ) +#define CFG_ENABLE_MCC_ENABLED_MAX ( 1 ) +#define CFG_ENABLE_MCC_ENABLED_DEFAULT ( 1 ) + +/* + * Allow GO in MCC mode to accept different beacon interval than STA's. + * Added for Wi-Fi Cert. 5.1.12 + * Default: gAllowMCCGODiffBI = 2 + * If gAllowMCCGODiffBI = 1 // Set to 1 for WFA certification. GO Beacon + * interval is not changed. MCC GO + * doesn't work well in optimized way. + * In worst scenario, it may invite STA + * disconnection. + * gAllowMCCGODiffBI = 2 //If set to 2 workaround 1 disassoc all the clients + * and update beacon Interval + * gAllowMCCGODiffBI = 3 //If set to 3 tear down the P2P link in auto/ + * Non-autonomous -GO case + * gAllowMCCGODiffBI = 4 //If set to 4 don't disconnect the P2P client + * in autonomous/Non-autonomous -GO case update + * the BI dynamically + */ +#define CFG_ALLOW_MCC_GO_DIFF_BI_NAME "gAllowMCCGODiffBI" +#define CFG_ALLOW_MCC_GO_DIFF_BI_MIN ( 0 ) +#define CFG_ALLOW_MCC_GO_DIFF_BI_MAX ( 4 ) +#define CFG_ALLOW_MCC_GO_DIFF_BI_DEFAULT ( 4 ) + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +/* + * Enable/Disable Bad Peer TX CTL feature + * Default: Enable + */ +#define CFG_BAD_PEER_TX_CTL_ENABLE_NAME "gBadPeerTxCtlEnable" +#define CFG_BAD_PEER_TX_CTL_ENABLE_MIN ( 0 ) +#define CFG_BAD_PEER_TX_CTL_ENABLE_MAX ( 1 ) +#define CFG_BAD_PEER_TX_CTL_ENABLE_DEFAULT ( 1 ) + +#define CFG_BAD_PEER_TX_CTL_PERIOD_NAME "gBadPeerTxCtlPeriod" +#define CFG_BAD_PEER_TX_CTL_PERIOD_MIN ( 10 ) +#define CFG_BAD_PEER_TX_CTL_PERIOD_MAX ( 10000 ) +#define CFG_BAD_PEER_TX_CTL_PERIOD_DEFAULT ( 50 ) + +#define CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_NAME "gBadPeerTxCtlTxqLimit" +#define CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_MAX ( 5000 ) +#define CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_DEFAULT ( 100 ) + +#define CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_NAME "gBadPeerTxCtlTgtBackoffTime" +#define CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_MAX ( 5000 ) +#define CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_DEFAULT ( 20 ) + +#define CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_NAME "gBadPeerTxCtlTgtReportPeriod" +#define CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_MAX ( 5000 ) +#define CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_DEFAULT ( 500 ) + +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_NAME "gBadPeerTxCtlCondLevelIeeeB" +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_MAX ( 2 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_DEFAULT ( 2 ) + +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_NAME "gBadPeerTxCtlDeltaLevelIeeeB" +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_MAX ( 11 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_DEFAULT ( 2 ) + +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_NAME "gBadPeerTxCtlPctLevelIeeeB" +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_MAX ( 8 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_DEFAULT ( 1 ) + +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_NAME "gBadPeerTxCtlTputLevelIeeeB" +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_MAX ( 11 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_DEFAULT ( 2 ) + +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_NAME "gBadPeerTxCtlTxLimitLevelIeeeB" +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_MIN ( 0 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_MAX ( 50 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_DEFAULT ( 3 ) + +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_NAME "gBadPeerTxCtlCondLevelIeeeAG" +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_MAX ( 2 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_DEFAULT ( 2 ) + +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_NAME "gBadPeerTxCtlDeltaLevelIeeeAG" +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_MIN ( 6 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_MAX ( 54 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_DEFAULT ( 6 ) + +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_NAME "gBadPeerTxCtlPctLevelIeeeAG" +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_MAX ( 8 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_DEFAULT ( 1 ) + +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_NAME "gBadPeerTxCtlTputLevelIeeeAG" +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_MIN ( 6 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_MAX ( 54 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_DEFAULT ( 6 ) + +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_NAME "gBadPeerTxCtlTxLimitLevelIeeeAG" +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_MIN ( 0 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_MAX ( 50 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_DEFAULT ( 3 ) + +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_NAME "gBadPeerTxCtlCondLevelIeeeN" +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_MAX ( 2 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_DEFAULT ( 2 ) + +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_NAME "gBadPeerTxCtlDeltaLevelIeeeN" +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_MIN ( 6 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_MAX ( 72 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_DEFAULT ( 6 ) + +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_NAME "gBadPeerTxCtlPctLevelIeeeN" +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_MAX ( 8 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_DEFAULT ( 1 ) + +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_NAME "gBadPeerTxCtlTputLevelIeeeN" +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_MIN ( 6 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_MAX ( 72 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_DEFAULT ( 15 ) + +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_NAME "gBadPeerTxCtlTxLimitLevelIeeeN" +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_MIN ( 0 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_MAX ( 50 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_DEFAULT ( 3 ) + +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_NAME "gBadPeerTxCtlCondLevelIeeeAC" +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_MAX ( 2 ) +#define CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_DEFAULT ( 2 ) + +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_NAME "gBadPeerTxCtlDeltaLevelIeeeAC" +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_MIN ( 6 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_MAX ( 433 ) +#define CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_DEFAULT ( 6 ) + +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_NAME "gBadPeerTxCtlPctLevelIeeeAC" +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_MIN ( 1 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_MAX ( 8 ) +#define CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_DEFAULT ( 1 ) + +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_NAME "gBadPeerTxCtlTputLevelIeeeAC" +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_MIN ( 6 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_MAX ( 433 ) +#define CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_DEFAULT ( 15 ) + +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_NAME "gBadPeerTxCtlTxLimitLevelIeeeAC" +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_MIN ( 0 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_MAX ( 50 ) +#define CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_DEFAULT ( 3 ) +#endif + +/* + * Enable/Disable Thermal Mitigation feature + * Default: Disable + */ +#define CFG_THERMAL_MIGRATION_ENABLE_NAME "gThermalMitigationEnable" +#define CFG_THERMAL_MIGRATION_ENABLE_MIN ( 0 ) +#define CFG_THERMAL_MIGRATION_ENABLE_MAX ( 1 ) +#define CFG_THERMAL_MIGRATION_ENABLE_DEFAULT ( 1 ) + + + +#define CFG_THROTTLE_PERIOD_NAME "gThrottlePeriod" +#define CFG_THROTTLE_PERIOD_MIN ( 10 ) +#define CFG_THROTTLE_PERIOD_MAX ( 10000 ) +#define CFG_THROTTLE_PERIOD_DEFAULT ( 4000 ) + +#define CFG_THERMAL_TEMP_MIN_LEVEL0_NAME "gThermalTempMinLevel0" +#define CFG_THERMAL_TEMP_MIN_LEVEL0_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL0_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL0_DEFAULT ( 0 ) + +#define CFG_THERMAL_TEMP_MAX_LEVEL0_NAME "gThermalTempMaxLevel0" +#define CFG_THERMAL_TEMP_MAX_LEVEL0_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL0_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL0_DEFAULT ( 90 ) + +#define CFG_THERMAL_TEMP_MIN_LEVEL1_NAME "gThermalTempMinLevel1" +#define CFG_THERMAL_TEMP_MIN_LEVEL1_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL1_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL1_DEFAULT ( 70 ) + +#define CFG_THERMAL_TEMP_MAX_LEVEL1_NAME "gThermalTempMaxLevel1" +#define CFG_THERMAL_TEMP_MAX_LEVEL1_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL1_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL1_DEFAULT ( 110 ) + +#define CFG_THERMAL_TEMP_MIN_LEVEL2_NAME "gThermalTempMinLevel2" +#define CFG_THERMAL_TEMP_MIN_LEVEL2_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL2_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL2_DEFAULT ( 90 ) + +#define CFG_THERMAL_TEMP_MAX_LEVEL2_NAME "gThermalTempMaxLevel2" +#define CFG_THERMAL_TEMP_MAX_LEVEL2_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL2_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL2_DEFAULT ( 125 ) + +#define CFG_THERMAL_TEMP_MIN_LEVEL3_NAME "gThermalTempMinLevel3" +#define CFG_THERMAL_TEMP_MIN_LEVEL3_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL3_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MIN_LEVEL3_DEFAULT ( 110 ) + +#define CFG_THERMAL_TEMP_MAX_LEVEL3_NAME "gThermalTempMaxLevel3" +#define CFG_THERMAL_TEMP_MAX_LEVEL3_MIN ( 0 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL3_MAX ( 1000 ) +#define CFG_THERMAL_TEMP_MAX_LEVEL3_DEFAULT ( 0 ) + + +/* + * Enable/Disable Modulated DTIM feature + * Default: Disable + */ +#define CFG_ENABLE_MODULATED_DTIM_NAME "gEnableModulatedDTIM" +#define CFG_ENABLE_MODULATED_DTIM_MIN ( 0 ) +#define CFG_ENABLE_MODULATED_DTIM_MAX ( 5 ) +#define CFG_ENABLE_MODULATED_DTIM_DEFAULT ( 0 ) + +/* + * Enable/Disable Multicast MAC Address List feature + * Default: Disable + */ +#define CFG_MC_ADDR_LIST_ENABLE_NAME "gMCAddrListEnable" +#define CFG_MC_ADDR_LIST_ENABLE_MIN ( 0 ) +#define CFG_MC_ADDR_LIST_ENABLE_MAX ( 1 ) +#define CFG_MC_ADDR_LIST_ENABLE_DEFAULT ( 0 ) + +/* Set number of buffers to be advertised during ADDBA negotiation*/ +#define CFG_NUM_BUFF_ADVERT_NAME "gNumBuffAdvert" +#define CFG_NUM_BUFF_ADVERT_MIN ( 0 ) +#define CFG_NUM_BUFF_ADVERT_MAX ( 128 ) +#define CFG_NUM_BUFF_ADVERT_DEFAULT ( 64 ) + +/* + * Allow MCC to modify config + */ +#define CFG_MCC_CONFIG_PARAM_NAME "gMccAllowCfgModify" +#define CFG_MCC_CONFIG_PARAM_MIN ( 0x0000 ) +#define CFG_MCC_CONFIG_PARAM_MAX ( 0x01ff ) +#define CFG_MCC_CONFIG_PARAM_DEFAULT ( 0x000C ) + +#define CFG_ENABLE_RX_STBC "gEnableRXSTBC" +#define CFG_ENABLE_RX_STBC_MIN ( 0 ) +#define CFG_ENABLE_RX_STBC_MAX ( 1 ) +#define CFG_ENABLE_RX_STBC_DEFAULT ( 1 ) + +#define CFG_ENABLE_TX_STBC "gEnableTXSTBC" +#define CFG_ENABLE_TX_STBC_MIN ( 0 ) +#define CFG_ENABLE_TX_STBC_MAX ( 1 ) +#define CFG_ENABLE_TX_STBC_DEFAULT ( 0 ) + +#define CFG_ENABLE_RX_LDPC "gEnableRXLDPC" +#define CFG_ENABLE_RX_LDPC_MIN ( 0 ) +#define CFG_ENABLE_RX_LDPC_MAX ( 1 ) +#define CFG_ENABLE_RX_LDPC_DEFAULT ( 0 ) + +/* + * Enable/Disable vsta based on MAX Assoc limit + * defined in WCNSS_qcom_cfg.ini. + */ +#ifdef WLAN_SOFTAP_VSTA_FEATURE +#define CFG_VSTA_SUPPORT_ENABLE "gEnableVSTASupport" +#define CFG_VSTA_SUPPORT_ENABLE_MIN ( 0 ) +#define CFG_VSTA_SUPPORT_ENABLE_MAX ( 1 ) +#define CFG_VSTA_SUPPORT_ENABLE_DEFAULT ( 0 ) +#endif + +#ifdef FEATURE_WLAN_TDLS +#define CFG_TDLS_SUPPORT_ENABLE "gEnableTDLSSupport" +#define CFG_TDLS_SUPPORT_ENABLE_MIN ( 0 ) +#define CFG_TDLS_SUPPORT_ENABLE_MAX ( 1 ) +#define CFG_TDLS_SUPPORT_ENABLE_DEFAULT ( 0 ) + +#define CFG_TDLS_IMPLICIT_TRIGGER "gEnableTDLSImplicitTrigger" +#define CFG_TDLS_IMPLICIT_TRIGGER_MIN ( 0 ) +#define CFG_TDLS_IMPLICIT_TRIGGER_MAX ( 1 ) +#define CFG_TDLS_IMPLICIT_TRIGGER_DEFAULT ( 0 ) + +#define CFG_TDLS_TX_STATS_PERIOD "gTDLSTxStatsPeriod" +#define CFG_TDLS_TX_STATS_PERIOD_MIN ( 10 ) +#define CFG_TDLS_TX_STATS_PERIOD_MAX ( 4294967295UL ) +#define CFG_TDLS_TX_STATS_PERIOD_DEFAULT (500) + +#define CFG_TDLS_TX_PACKET_THRESHOLD "gTDLSTxPacketThreshold" +#define CFG_TDLS_TX_PACKET_THRESHOLD_MIN ( 0 ) +#define CFG_TDLS_TX_PACKET_THRESHOLD_MAX ( 4294967295UL ) +#define CFG_TDLS_TX_PACKET_THRESHOLD_DEFAULT (10) + +#define CFG_TDLS_DISCOVERY_PERIOD "gTDLSDiscoveryPeriod" +#define CFG_TDLS_DISCOVERY_PERIOD_MIN ( 5000 ) +#define CFG_TDLS_DISCOVERY_PERIOD_MAX ( 4294967295UL ) +#define CFG_TDLS_DISCOVERY_PERIOD_DEFAULT ( 20000 ) + +#define CFG_TDLS_MAX_DISCOVERY_ATTEMPT "gTDLSMaxDiscoveryAttempt" +#define CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN ( 1 ) +#define CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX ( 100 ) +#define CFG_TDLS_MAX_DISCOVERY_ATTEMPT_DEFAULT ( 5 ) + +/* teardown notification interval (gTDLSIdleTimeout) should be multiple of + * setup notification (gTDLSTxStatsPeriod) interval. + * e.g. + * if setup notification (gTDLSTxStatsPeriod) interval = 500, then + * teardown notification (gTDLSIdleTimeout) interval should be 1000, + * 1500, 2000, 2500... + */ +#define CFG_TDLS_IDLE_TIMEOUT "gTDLSIdleTimeout" +#define CFG_TDLS_IDLE_TIMEOUT_MIN (500) +#define CFG_TDLS_IDLE_TIMEOUT_MAX ( 40000 ) +#define CFG_TDLS_IDLE_TIMEOUT_DEFAULT (5000) + +#define CFG_TDLS_IDLE_PACKET_THRESHOLD "gTDLSIdlePacketThreshold" +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ( 0 ) +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX ( 40000 ) +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_DEFAULT (3) + +#define CFG_TDLS_RSSI_HYSTERESIS "gTDLSRssiHysteresis" +#define CFG_TDLS_RSSI_HYSTERESIS_MIN ( 0 ) +#define CFG_TDLS_RSSI_HYSTERESIS_MAX ( 100 ) +#define CFG_TDLS_RSSI_HYSTERESIS_DEFAULT ( 100 ) + +#define CFG_TDLS_RSSI_TRIGGER_THRESHOLD "gTDLSRSSITriggerThreshold" +#define CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN ( -120 ) +#define CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX ( 0 ) +#define CFG_TDLS_RSSI_TRIGGER_THRESHOLD_DEFAULT ( -75 ) + +#define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD "gTDLSRSSITeardownThreshold" +#define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ( -120 ) +#define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX ( 0 ) +#define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_DEFAULT ( -75 ) + +#define CFG_TDLS_RSSI_DELTA "gTDLSRSSIDelta" +#define CFG_TDLS_RSSI_DELTA_MIN ( -30 ) +#define CFG_TDLS_RSSI_DELTA_MAX ( 0 ) +#define CFG_TDLS_RSSI_DELTA_DEFAULT ( -20 ) + +#define CFG_TDLS_QOS_WMM_UAPSD_MASK_NAME "gTDLSUapsdMask" // ACs to setup U-APSD for TDLS Sta +#define CFG_TDLS_QOS_WMM_UAPSD_MASK_MIN (0) +#define CFG_TDLS_QOS_WMM_UAPSD_MASK_MAX (0x0F) +#define CFG_TDLS_QOS_WMM_UAPSD_MASK_DEFAULT (0x0F) + +#define CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE "gEnableTDLSBufferSta" +#define CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE_MIN (0) +#define CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE_MAX (1) +#define CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE_DEFAULT (1) + +#define CFG_TDLS_PUAPSD_INACTIVITY_TIME "gTDLSPuapsdInactivityTime" +#define CFG_TDLS_PUAPSD_INACTIVITY_TIME_MIN (0) +#define CFG_TDLS_PUAPSD_INACTIVITY_TIME_MAX (10) +#define CFG_TDLS_PUAPSD_INACTIVITY_TIME_DEFAULT (0) + +#define CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD "gTDLSPuapsdRxFrameThreshold" +#define CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_MIN (10) +#define CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_MAX (20) +#define CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_DEFAULT (10) + +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW "gTDLSPuapsdPTIWindow" +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW_MIN (1) +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW_MAX (5) +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW_DEFAULT (2) + +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT "gTDLSPuapsdPTRTimeout" +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT_MIN (0) +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT_MAX (10000) +#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT_DEFAULT (5000) + +#define CFG_TDLS_EXTERNAL_CONTROL "gTDLSExternalControl" +#define CFG_TDLS_EXTERNAL_CONTROL_MIN (0) +#define CFG_TDLS_EXTERNAL_CONTROL_MAX (1) +#define CFG_TDLS_EXTERNAL_CONTROL_DEFAULT (0) + +#define CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE "gEnableTDLSOffChannel" +#define CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE_MIN (0) +#define CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE_MAX (1) +#define CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE_DEFAULT (0) + +#define CFG_TDLS_WMM_MODE_ENABLE "gEnableTDLSWmmMode" +#define CFG_TDLS_WMM_MODE_ENABLE_MIN (0) +#define CFG_TDLS_WMM_MODE_ENABLE_MAX (1) +#define CFG_TDLS_WMM_MODE_ENABLE_DEFAULT (1) + +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM "gTDLSPrefOffChanNum" +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN (1) +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX (165) +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT (36) + +/* Tdls offchannel bandwidth is now represented in bits as follows. + * 0th bit - 20MHz + * 1st bit - 40MHz + * 2nd bit - 80MHz + * 3rd bit - 160MHz + * If more than one bits are set the f/w will start from the highest + * and select one, based on the capability of peer. + */ +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_BW "gTDLSPrefOffChanBandwidth" +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_BW_MIN (0) +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_BW_MAX (0x0F) +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_BW_DEFAULT (0x07) + +/* Enable TDLS Scan: Allow scan and maintain TDLS link. + * 0: If peer is not buffer STA capable and device is not sleep STA + * capable, then teardown TDLS link when scan is initiated. If peer + * is buffer STA and we can be sleep STA then TDLS link is maintained + * during scan. + * 1: Maintain TDLS link and allow scan even if peer is not buffer STA + * capable and device is not sleep STA capable. There will be loss of + * Rx pkts since peer would not know when device moves away from tdls + * channel. Tx on TDLS link would stop when device moves away from tdls + * channel. + */ +#define CFG_TDLS_SCAN_ENABLE "gEnableTDLSScan" +#define CFG_TDLS_SCAN_ENABLE_MIN (0) +#define CFG_TDLS_SCAN_ENABLE_MAX (1) +#define CFG_TDLS_SCAN_ENABLE_DEFAULT (0) + +/* TDLS peer kickout threshold to fw + * Firmware will use this value to determine, when to send TDLS + * peer kick out event to host. + * E.g. + * if peer kick out threshold is 10, then firmware will wait for 10 + * consecutive packet failures and then send TDLS kickout + * notification to host driver + */ +#define CFG_TDLS_PEER_KICKOUT_THRESHOLD "gTDLSPeerKickoutThreshold" +#define CFG_TDLS_PEER_KICKOUT_THRESHOLD_MIN (10) +#define CFG_TDLS_PEER_KICKOUT_THRESHOLD_MAX (5000) +#define CFG_TDLS_PEER_KICKOUT_THRESHOLD_DEFAULT (96) + +#endif + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE +#define CFG_ACTIVEMODE_OFFLOAD_ENABLE "gEnableActiveModeOffload" +#define CFG_ACTIVEMODE_OFFLOAD_ENABLE_MIN ( 0 ) +#define CFG_ACTIVEMODE_OFFLOAD_ENABLE_MAX ( 1 ) +#define CFG_ACTIVEMODE_OFFLOAD_ENABLE_DEFAULT ( 1 ) +#endif +/* Enable/Disable LPWR Image(cMEM uBSP) Transition */ +#define CFG_ENABLE_LPWR_IMG_TRANSITION_NAME "gEnableLpwrImgTransition" +#define CFG_ENABLE_LPWR_IMG_TRANSITION_MIN ( 0 ) +#define CFG_ENABLE_LPWR_IMG_TRANSITION_MAX ( 1 ) +#define CFG_ENABLE_LPWR_IMG_TRANSITION_DEFAULT ( 0 ) + + + +/* + * Scan Aging timeout value in seconds + */ +#define CFG_SCAN_AGING_PARAM_NAME "gScanAgingTime" +#define CFG_SCAN_AGING_PARAM_MIN ( 0 ) +#define CFG_SCAN_AGING_PARAM_MAX ( 200 ) +#define CFG_SCAN_AGING_PARAM_DEFAULT ( 60 ) + +/* Config Param to enable the txLdpc capability + * 0 - disable + * 1 - HT LDPC enable + * 2 - VHT LDPC enable + * 3 - HT & VHT LDPC enable */ +#define CFG_TX_LDPC_ENABLE_FEATURE "gTxLdpcEnable" +#define CFG_TX_LDPC_ENABLE_FEATURE_MIN ( 0 ) +#define CFG_TX_LDPC_ENABLE_FEATURE_MAX ( 3 ) +#define CFG_TX_LDPC_ENABLE_FEATURE_DEFAULT ( 0 ) + +/* + * Enable / Disable MCC Adaptive Scheduler feature + * Default: Enable + */ +#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_NAME "gEnableMCCAdaptiveScheduler" +#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MIN ( 0 ) +#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MAX ( 1 ) +#define CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_DEFAULT ( 1 ) + +#ifdef WLAN_FEATURE_11AC +#define CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE "gTxBFEnable" +#define CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_MIN ( WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMIN ) +#define CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_MAX ( WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMAX ) +#define CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_DEFAULT ( WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STADEF ) + +#define CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED "gTxBFCsnValue" +#define CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_MIN ( WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMIN ) +#define CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_MAX ( WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMAX - 1 ) +#define CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_DEFAULT ( WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMAX - 1 ) + +#define CFG_VHT_ENABLE_TXBF_IN_20MHZ "gEnableTxBFin20MHz" +#define CFG_VHT_ENABLE_TXBF_IN_20MHZ_MIN ( 0 ) +#define CFG_VHT_ENABLE_TXBF_IN_20MHZ_MAX ( 1 ) +#define CFG_VHT_ENABLE_TXBF_IN_20MHZ_DEFAULT ( 0 ) + +#endif + +//Enable debug for remain on channel issues +#define CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_NAME "gDebugP2pRemainOnChannel" +#define CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_DEFAULT ( 0 ) +#define CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_MIN ( 0 ) +#define CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_MAX ( 1 ) + +/* + * SAP ALLOW All Channels + */ +#define CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_NAME "gSapAllowAllChannel" +#define CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_MIN ( 0 ) +#define CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_MAX ( 1 ) +#define CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_DEFAULT ( 0 ) + + +#ifdef WLAN_FEATURE_11AC +#define CFG_DISABLE_LDPC_WITH_TXBF_AP "gDisableLDPCWithTxbfAP" +#define CFG_DISABLE_LDPC_WITH_TXBF_AP_MIN ( 0 ) +#define CFG_DISABLE_LDPC_WITH_TXBF_AP_MAX ( 1 ) +#define CFG_DISABLE_LDPC_WITH_TXBF_AP_DEFAULT ( 0 ) +#endif + +#define CFG_LIST_OF_NON_DFS_COUNTRY_CODE "gListOfNonDfsCountryCode" +#define CFG_LIST_OF_NON_DFS_COUNTRY_CODE_DEFAULT "JO,MA" + + +/* + * IBSS Operating Channels for 2.4G and 5GHz channels + */ +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_NAME "gAdHocChannel5G" +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_MIN ( 36 ) +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_MAX ( 165 ) +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_DEFAULT ( 44 ) + +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_NAME "gAdHocChannel24G" +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_MIN ( 1 ) +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_MAX ( 14 ) +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_DEFAULT ( 6 ) + +/* Parameter to control VHT support in 2.4 GHz band */ +#define CFG_ENABLE_VHT_FOR_24GHZ_NAME "gEnableVhtFor24GHzBand" +#define CFG_ENABLE_VHT_FOR_24GHZ_MIN (0) +#define CFG_ENABLE_VHT_FOR_24GHZ_MAX (1) +#define CFG_ENABLE_VHT_FOR_24GHZ_DEFAULT (0) + + +#define CFG_MAX_MEDIUM_TIME "gMaxMediumTime" +#define CFG_MAX_MEDIUM_TIME_STAMIN WNI_CFG_MAX_MEDIUM_TIME_STAMIN +#define CFG_MAX_MEDIUM_TIME_STAMAX WNI_CFG_MAX_MEDIUM_TIME_STAMAX +#define CFG_MAX_MEDIUM_TIME_STADEFAULT WNI_CFG_MAX_MEDIUM_TIME_STADEF + +/* + * SCAN Offload + */ +#define CFG_SCAN_OFFLOAD_NAME "gEnableDirectedScanOffload" +#define CFG_SCAN_OFFLOAD_DISABLE ( 0 ) +#define CFG_SCAN_OFFLOAD_ENABLE ( 1 ) +#define CFG_SCAN_OFFLOAD_DEFAULT ( CFG_SCAN_OFFLOAD_DISABLE ) + +/* + * Enable legacy fast roaming (LFR) on STA link during concurrent sessions + */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY "gEnableFastRoamInConcurrency" +#define CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY_MIN ( 0 ) +#define CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY_MAX ( 1 ) +#define CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY_DEFAULT ( 1 ) +#endif + +/* + * FlexConnectPowerFactor parameter + * Default: Disable (0) + */ +#define CFG_FLEX_CONNECT_POWER_FACTOR_NAME "gFlexConnectPowerFactor" +#define CFG_FLEX_CONNECT_POWER_FACTOR_MIN ( 0 ) +#define CFG_FLEX_CONNECT_POWER_FACTOR_MAX ( 9 ) +#define CFG_FLEX_CONNECT_POWER_FACTOR_DEFAULT ( 0 ) + +/* + * Enable heart beat monitoring offload to FW + */ +#define CFG_ENABLE_HEART_BEAT_OFFLOAD "gEnableIbssHeartBeatOffload" +#define CFG_ENABLE_HEART_BEAT_OFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_HEART_BEAT_OFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_HEART_BEAT_OFFLOAD_DEFAULT ( 1 ) + +#define CFG_ANTENNA_DIVERSITY_PARAM_NAME "gAntennaDiversity" +#define CFG_ANTENNA_DIVERSITY_PARAM_MIN ( 0 ) +#define CFG_ANTENNA_DIVERSITY_PARAM_MAX ( 3 ) +#define CFG_ANTENNA_DIVERSITY_PARAM_DEFAULT ( 0 ) + +#define CFG_ENABLE_SNR_MONITORING_NAME "gEnableSNRMonitoring" +#define CFG_ENABLE_SNR_MONITORING_MIN ( 0 ) +#define CFG_ENABLE_SNR_MONITORING_MAX ( 1 ) +#define CFG_ENABLE_SNR_MONITORING_DEFAULT ( 0 ) + +#ifdef FEATURE_WLAN_SCAN_PNO +#define CFG_PNO_SCAN_SUPPORT "gPNOScanSupport" +#define CFG_PNO_SCAN_SUPPORT_ENABLE ( 1 ) +#define CFG_PNO_SCAN_SUPPORT_DISABLE ( 0 ) +#define CFG_PNO_SCAN_SUPPORT_DEFAULT ( 1 ) + +#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE "gPNOScanTimerRepeatValue" +#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE_DEFAULT ( 30 ) +#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE_MIN ( 0 ) +#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE_MAX ( 0xffffffff ) + +#define CFG_PNO_SLOW_SCAN_MULTIPLIER "gPNOSlowScanMultiplier" +#define CFG_PNO_SLOW_SCAN_MULTIPLIER_DEFAULT ( 6 ) +#define CFG_PNO_SLOW_SCAN_MULTIPLIER_MIN ( 0 ) +#define CFG_PNO_SLOW_SCAN_MULTIPLIER_MAX ( 30 ) +#endif + +#define CFG_MAX_AMSDU_NUM_NAME "gMaxAmsduNum" +#define CFG_MAX_AMSDU_NUM_MIN (0) +#define CFG_MAX_AMSDU_NUM_MAX (3) +#define CFG_MAX_AMSDU_NUM_DEFAULT (1) + +/* Prefer connecting to 5G AP even if its RSSI is lower by + gSelect5GHzMargin dBm than 2.4G AP. +This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ +#define CFG_STRICT_5GHZ_PREF_BY_MARGIN "gSelect5GHzMargin" +#define CFG_STRICT_5GHZ_PREF_BY_MARGIN_MIN (0) +#define CFG_STRICT_5GHZ_PREF_BY_MARGIN_MAX (60) +#define CFG_STRICT_5GHZ_PREF_BY_MARGIN_DEFAULT (0) //set 0 to disable + +#define CFG_ENABLE_TCP_CHKSUM_OFFLOAD "gEnableTCPChkSumOffld" +#define CFG_ENABLE_TCP_CHKSUM_OFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_TCP_CHKSUM_OFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_TCP_CHKSUM_OFFLOAD_DEFAULT ( 0 ) + +#define CFG_ENABLE_IP_CHKSUM_OFFLOAD "gEnableIPChecksumOffload" +#define CFG_ENABLE_IP_CHKSUM_OFFLOAD_DISABLE ( 0 ) +#define CFG_ENABLE_IP_CHKSUM_OFFLOAD_ENABLE ( 1 ) +#define CFG_ENABLE_IP_CHKSUM_OFFLOAD_DEFAULT ( CFG_ENABLE_IP_CHKSUM_OFFLOAD_DISABLE ) + +/* + * Power Save Offload + * Power Save Offload configuration: + * Current values of gEnablePowerSaveOffload: + * 0 -> Power save offload is disabled + * 1 -> Legacy Power save enabled + Deep sleep Disabled + * 2 -> QPower enabled + Deep sleep Disabled + * 3 -> Legacy Power save enabled + Deep sleep Enabled + * 4 -> QPower enabled + Deep sleep Enabled + * 5 -> Duty cycling QPower enabled + */ +#define CFG_POWERSAVE_OFFLOAD_NAME "gEnablePowerSaveOffload" +#define CFG_POWERSAVE_OFFLOAD_MIN (0) +#define CFG_POWERSAVE_OFFLOAD_MAX (PS_DUTY_CYCLING_QPOWER) +#define CFG_POWERSAVE_OFFLOAD_DEFAULT (CFG_POWERSAVE_OFFLOAD_MIN) + +#ifdef IPA_OFFLOAD +/* + * IPA Offload configuration - Each bit enables a feature + * bit0 - IPA Enable + * bit1 - IPA Pre filter enable + * bit2 - IPv6 enable + * bit3 - IPA Resource Manager (RM) enable + * bit4 - IPA Clock scaling enable + */ +#define CFG_IPA_OFFLOAD_CONFIG_NAME "gIPAConfig" +#define CFG_IPA_OFFLOAD_CONFIG_MIN ( 0 ) +#define CFG_IPA_OFFLOAD_CONFIG_MAX ( 0xFFFFFFFF ) +#define CFG_IPA_OFFLOAD_CONFIG_DEFAULT ( CFG_IPA_OFFLOAD_CONFIG_MIN ) + +/* + * IPA DESC SIZE + */ +#define CFG_IPA_DESC_SIZE_NAME "gIPADescSize" +#define CFG_IPA_DESC_SIZE_MIN ( 800 ) +#define CFG_IPA_DESC_SIZE_MAX ( 8000 ) +#define CFG_IPA_DESC_SIZE_DEFAULT ( 800 ) + +#define CFG_IPA_HIGH_BANDWIDTH_MBPS "gIPAHighBandwidthMbps" +#define CFG_IPA_HIGH_BANDWIDTH_MBPS_MIN ( 200 ) +#define CFG_IPA_HIGH_BANDWIDTH_MBPS_MAX ( 1000 ) +#define CFG_IPA_HIGH_BANDWIDTH_MBPS_DEFAULT ( 400 ) + +#define CFG_IPA_MEDIUM_BANDWIDTH_MBPS "gIPAMediumBandwidthMbps" +#define CFG_IPA_MEDIUM_BANDWIDTH_MBPS_MIN ( 100 ) +#define CFG_IPA_MEDIUM_BANDWIDTH_MBPS_MAX ( 400 ) +#define CFG_IPA_MEDIUM_BANDWIDTH_MBPS_DEFAULT ( 200 ) + +#define CFG_IPA_LOW_BANDWIDTH_MBPS "gIPALowBandwidthMbps" +#define CFG_IPA_LOW_BANDWIDTH_MBPS_MIN ( 0 ) +#define CFG_IPA_LOW_BANDWIDTH_MBPS_MAX ( 100 ) +#define CFG_IPA_LOW_BANDWIDTH_MBPS_DEFAULT ( 100 ) +#endif + +/* + * P2P Listen Offload + */ +#define CFG_P2P_LISTEN_OFFLOAD_NAME "gEnableP2pListenOffload" +#define CFG_P2P_LISTEN_OFFLOAD_DISABLE ( 0 ) +#define CFG_P2P_LISTEN_OFFLOAD_ENABLE ( 1 ) +#define CFG_P2P_LISTEN_OFFLOAD_DEFAULT ( CFG_P2P_LISTEN_OFFLOAD_DISABLE ) + +/* + * Firmware uart print + */ +#define CFG_ENABLE_FW_UART_PRINT_NAME "gEnablefwprint" +#define CFG_ENABLE_FW_UART_PRINT_DISABLE ( 0 ) +#define CFG_ENABLE_FW_UART_PRINT_ENABLE ( 1 ) +#define CFG_ENABLE_FW_UART_PRINT_DEFAULT ( CFG_ENABLE_FW_UART_PRINT_DISABLE ) + +/* + * Firmware log + */ +#define CFG_ENABLE_FW_LOG_NAME "gEnablefwlog" +#define CFG_ENABLE_FW_LOG_DISABLE ( 0 ) +#define CFG_ENABLE_FW_LOG_ENABLE ( 1 ) +#define CFG_ENABLE_FW_LOG_DEFAULT ( CFG_ENABLE_FW_LOG_DISABLE ) + +/* + * Enable/Disable SSR for USB + */ +#define CFG_ENABLE_FW_SELF_RECOVERY_NAME "gEnableFwSelfRecovery" +#define CFG_ENABLE_FW_SELF_RECOVERY_DISABLE ( 0 ) +#define CFG_ENABLE_FW_SELF_RECOVERY_ENABLE ( 1 ) +#define CFG_ENABLE_FW_SELF_RECOVERY_DEFAULT ( CFG_ENABLE_FW_SELF_RECOVERY_DISABLE ) + +#ifdef WLAN_FEATURE_11AC +//Macro to handle maximum receive AMPDU size configuration +#define CFG_VHT_AMPDU_LEN_EXPONENT_NAME "gVhtAmpduLenExponent" +#define CFG_VHT_AMPDU_LEN_EXPONENT_MIN ( 0 ) +#define CFG_VHT_AMPDU_LEN_EXPONENT_MAX ( 7 ) +#define CFG_VHT_AMPDU_LEN_EXPONENT_DEFAULT ( 7 ) + +#define CFG_VHT_MPDU_LEN_NAME "gVhtMpduLen" +#define CFG_VHT_MPDU_LEN_MIN ( 0 ) +#define CFG_VHT_MPDU_LEN_MAX ( 2 ) +#define CFG_VHT_MPDU_LEN_DEFAULT ( 0 ) +#endif + +#define CFG_MAX_WOW_FILTERS_NAME "gMaxWoWFilters" +#define CFG_MAX_WOW_FILTERS_MIN ( 0 ) +#define CFG_MAX_WOW_FILTERS_MAX ( 22 ) +#define CFG_MAX_WOW_FILTERS_DEFAULT ( 22 ) + +/* + * WOW Enable/Disable. + * 0 - Disable both magic pattern match and pattern byte match. + * 1 - Enable magic pattern match on all interfaces. + * 2 - Enable pattern byte match on all interfaces. + * 3 - Enable both magic patter and pattern byte match on all interfaces. + */ +#define CFG_WOW_STATUS_NAME "gEnableWoW" +#define CFG_WOW_ENABLE_MIN ( 0 ) +#define CFG_WOW_ENABLE_MAX ( 3 ) +#define CFG_WOW_STATUS_DEFAULT ( 3 ) + +#define CFG_COALESING_IN_IBSS_NAME "gCoalesingInIBSS" +#define CFG_COALESING_IN_IBSS_MIN (0) +#define CFG_COALESING_IN_IBSS_MAX (1) +#define CFG_COALESING_IN_IBSS_DEFAULT (0) //disabled + +#define CFG_IBSS_ATIM_WIN_SIZE_NAME "gIbssATIMWinSize" +#define CFG_IBSS_ATIM_WIN_SIZE_MIN (0) +#define CFG_IBSS_ATIM_WIN_SIZE_MAX (50) +#define CFG_IBSS_ATIM_WIN_SIZE_DEFAULT (0) + +/* + * Indicates if IBSS Power Save is + * supported or not. When not allowed, + * IBSS station has to stay awake all + * the time and should never set PM=1 + * in its transmitted frames. This + * parameter is meaningful/valid only + * when gIbssATIMWinSize is non-zero + */ +#define CFG_IBSS_IS_POWER_SAVE_ALLOWED_NAME "gIbssIsPowerSaveAllowed" +#define CFG_IBSS_IS_POWER_SAVE_ALLOWED_MIN (0) +#define CFG_IBSS_IS_POWER_SAVE_ALLOWED_MAX (1) +#define CFG_IBSS_IS_POWER_SAVE_ALLOWED_DEFAULT (1) + +/* + * Indicates if IBSS Power Collapse + * is allowed or not. + */ +#define CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_NAME "gIbssIsPowerCollapseAllowed" +#define CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_MIN (0) +#define CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_MAX (1) +#define CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_DEFAULT (1) + +/* + * This parameter indicates whether IBSS station + * can exit power save mode and enter power active + * state whenever there is a TX/RX activity. + */ +#define CFG_IBSS_AWAKE_ON_TX_RX_NAME "gIbssAwakeOnTxRx" +#define CFG_IBSS_AWAKE_ON_TX_RX_MIN (0) +#define CFG_IBSS_AWAKE_ON_TX_RX_MAX (1) +#define CFG_IBSS_AWAKE_ON_TX_RX_DEFAULT (0) + +/* + * In IBSS mode if Awake on TX/RX activity is enabled + * Ibss Inactivity parameter indicates the data + * inactivity time in number of beacon intervals + * after which IBSS station re-inters power save + * by sending Null frame with PM=1 + */ +#define CFG_IBSS_INACTIVITY_TIME_NAME "gIbssInactivityTime" +#define CFG_IBSS_INACTIVITY_TIME_MIN (1) +#define CFG_IBSS_INACTIVITY_TIME_MAX (10) +#define CFG_IBSS_INACTIVITY_TIME_DEFAULT (1) + +/* + * In IBSS mode Tx Service Period Inactivity + * time in msecs indicates the time after + * which TX Service Period is terminated by + * sending a Qos Null frame with EOSP. + * If value is 0, TX SP is terminated with the + * last buffered packet itself instead of waiting + * for the inactivity + */ +#define CFG_IBSS_TXSP_END_INACTIVITY_NAME "gIbssTxSpEndInactivityTime" +#define CFG_IBSS_TXSP_END_INACTIVITY_MIN (0) +#define CFG_IBSS_TXSP_END_INACTIVITY_MAX (100) +#define CFG_IBSS_TXSP_END_INACTIVITY_DEFAULT (0) + +/* + * When IBSS network is initialized, PS-supporting device + * does not enter protocol sleep state during first + * gIbssPsWarmupTime seconds. + */ +#define CFG_IBSS_PS_WARMUP_TIME_NAME "gIbssPsWarmupTime" +#define CFG_IBSS_PS_WARMUP_TIME_MIN (0) +/* Allow unsigned Int Max for now */ +#define CFG_IBSS_PS_WARMUP_TIME_MAX (65535) +#define CFG_IBSS_PS_WARMUP_TIME_DEFAULT (0) + +/* + * IBSS Power Save Enable/Disable 1 RX + * chain usage during the ATIM window + */ +#define CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_NAME "gIbssPs1RxChainInAtim" +#define CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_MIN (0) +#define CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_MAX (1) +#define CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_DEFAULT (0) + +#define CFG_SAP_MAX_NO_PEERS "gSoftApMaxPeers" +#define CFG_SAP_MAX_NO_PEERS_MIN (1) +#define CFG_SAP_MAX_NO_PEERS_MAX (32) +#define CFG_SAP_MAX_NO_PEERS_DEFAULT (32) + +/* + * Connection related log Enable/Disable. + * 0x1 - Enable mgmt pkt logs (no probe req/rsp). + * 0x2 - Enable EAPOL pkt logs. + * 0x4 - Enable DHCP pkt logs. + * 0x0 - Disable all the above connection related logs. + */ +#define CFG_ENABLE_DEBUG_CONNECT_ISSUE "gEnableDebugLog" +#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_MIN (0) +#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_MAX (0xFF) +#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_DEFAULT (0) + +/* + * RX packet handling options + * 0: no rx thread, no RPS, for MDM + * 1: RX thread + * 2: RPS + * MSM default RX thread + * MDM default irq + */ +#define CFG_RX_HANDLE "rxhandle" +#define CFG_RX_HANDLE_MIN (WLAN_HDD_RX_HANDLE_MIN) +#define CFG_RX_HANDLE_MAX (WLAN_HDD_RX_HANDLE_MAX) +#ifdef MDM_PLATFORM +#define CFG_RX_HANDLE_DEFAULT (WLAN_HDD_RX_HANDLE_IRQ) +#else +#define CFG_RX_HANDLE_DEFAULT (WLAN_HDD_RX_HANDLE_RX_THREAD) +#endif /* MDM_PLATFORM */ + +/* List of RPS CPU maps for different rx queues registered by WLAN driver + * Ref - Kernel/Documentation/networking/scaling.txt + * RPS CPU map for a particular RX queue, selects CPU(s) for bottom half + * processing of RX packets. For example, for a system with 4 CPUs, + * 0xe: Use CPU1 - CPU3 and donot use CPU0. + * 0x0: RPS is disabled, packets are processed on the interrupting CPU. +.* + * WLAN driver registers NUM_TX_QUEUES queues for tx and rx each during + * alloc_netdev_mq. Hence, we need to have a cpu mask for each of the rx queues. + * + * For example, if the NUM_TX_QUEUES is 4, a sample WLAN ini entry may look like + * rpsRxQueueCpuMapList=a b c d + * For a 4 CPU system (CPU0 - CPU3), this implies: + * 0xa - (1010) use CPU1, CPU3 for rx queue 0 + * 0xb - (1011) use CPU0, CPU1 and CPU3 for rx queue 1 + * 0xc - (1100) use CPU2, CPU3 for rx queue 2 + * 0xd - (1101) use CPU0, CPU2 and CPU3 for rx queue 3 + + * In practice, we may want to avoid the cores which are heavily loaded. + */ + +/* Name of the ini file entry to specify RPS map for different RX queus */ +#define CFG_RPS_RX_QUEUE_CPU_MAP_LIST_NAME "rpsRxQueueCpuMapList" + +/* Default value of rpsRxQueueCpuMapList. Different platforms may have + * different configurations for NUM_TX_QUEUES and # of cpus, and will need to + * configure an appropriate value via ini file. Setting default value to 'e' to + * avoid use of CPU0 (since its heavily used by other system processes) by rx + * queue 0, which is currently being used for rx packet processing. + */ +#define CFG_RPS_RX_QUEUE_CPU_MAP_LIST_DEFAULT "e" + +/* Maximum length of string used to hold a list of cpu maps for various rx + * queues. Considering a 16 core system with 5 rx queues, a RPS CPU map + * list may look like - + * rpsRxQueueCpuMapList = ffff ffff ffff ffff ffff + * (all 5 rx queues can be processed on all 16 cores) + * max string len = 24 + 1(for '\0'). Considering 30 to be on safe side. + */ +#define CFG_RPS_RX_QUEUE_CPU_MAP_LIST_LEN 30 + +/* SAR Thermal limit values for 2g and 5g */ + +#define CFG_SET_TXPOWER_LIMIT2G_NAME "TxPower2g" +#define CFG_SET_TXPOWER_LIMIT2G_MIN ( 0 ) +#define CFG_SET_TXPOWER_LIMIT2G_MAX ( 30 ) +#define CFG_SET_TXPOWER_LIMIT2G_DEFAULT ( 15 ) + +#define CFG_SET_TXPOWER_LIMIT5G_NAME "TxPower5g" +#define CFG_SET_TXPOWER_LIMIT5G_MIN ( 0 ) +#define CFG_SET_TXPOWER_LIMIT5G_MAX ( 30 ) +#define CFG_SET_TXPOWER_LIMIT5G_DEFAULT ( 15 ) + +#ifdef QCA_LL_TX_FLOW_CT +/* Default, single interface case flow control parameters */ +#define CFG_LL_TX_FLOW_LWM "TxFlowLowWaterMark" +#define CFG_LL_TX_FLOW_LWM_MIN ( 0 ) +#define CFG_LL_TX_FLOW_LWM_MAX ( 1000 ) +#if defined(CONFIG_HL_SUPPORT) +#define CFG_LL_TX_FLOW_LWM_DEFAULT ( 0 ) +#else +#define CFG_LL_TX_FLOW_LWM_DEFAULT ( 300 ) +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#define CFG_LL_TX_FLOW_HWM_OFFSET "TxFlowHighWaterMarkOffset" +#define CFG_LL_TX_FLOW_HWM_OFFSET_MIN ( 0 ) +#define CFG_LL_TX_FLOW_HWM_OFFSET_MAX ( 300 ) +#if defined(CONFIG_HL_SUPPORT) +#define CFG_LL_TX_FLOW_HWM_OFFSET_DEFAULT ( 0 ) +#else +#define CFG_LL_TX_FLOW_HWM_OFFSET_DEFAULT ( 94 ) +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#define CFG_LL_TX_FLOW_MAX_Q_DEPTH "TxFlowMaxQueueDepth" +#define CFG_LL_TX_FLOW_MAX_Q_DEPTH_MIN ( 400 ) +#define CFG_LL_TX_FLOW_MAX_Q_DEPTH_MAX ( 3500 ) +#define CFG_LL_TX_FLOW_MAX_Q_DEPTH_DEFAULT ( 1500 ) + +#define CFG_LL_TX_LBW_FLOW_LWM "TxLbwFlowLowWaterMark" +#define CFG_LL_TX_LBW_FLOW_LWM_MIN ( 0 ) +#if defined(CONFIG_HL_SUPPORT) +#define CFG_LL_TX_LBW_FLOW_LWM_MAX ( 2300 ) +#define CFG_LL_TX_LBW_FLOW_LWM_DEFAULT ( 2250 ) +#else +#define CFG_LL_TX_LBW_FLOW_LWM_MAX ( 1000 ) +#define CFG_LL_TX_LBW_FLOW_LWM_DEFAULT ( 450 ) +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET "TxLbwFlowHighWaterMarkOffset" +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MIN ( 0 ) +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MAX ( 300 ) +#if defined(CONFIG_HL_SUPPORT) +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_DEFAULT ( 40 ) +#else +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_DEFAULT ( 50 ) +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH "TxLbwFlowMaxQueueDepth" +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MIN ( 400 ) +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MAX ( 3500 ) +#define CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_DEFAULT ( 750 ) + +#define CFG_LL_TX_HBW_FLOW_LWM "TxHbwFlowLowWaterMark" +#define CFG_LL_TX_HBW_FLOW_LWM_MIN ( 0 ) +#if defined(CONFIG_HL_SUPPORT) +#define CFG_LL_TX_HBW_FLOW_LWM_MAX ( 2300 ) +#define CFG_LL_TX_HBW_FLOW_LWM_DEFAULT ( 2150 ) +#else +#define CFG_LL_TX_HBW_FLOW_LWM_MAX ( 1000 ) +#define CFG_LL_TX_HBW_FLOW_LWM_DEFAULT ( 406 ) +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET "TxHbwFlowHighWaterMarkOffset" +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MIN ( 0 ) +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MAX ( 300 ) +#if defined(CONFIG_HL_SUPPORT) +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_DEFAULT ( 140 ) +#else +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_DEFAULT ( 94 ) +#endif /* defined(CONFIG_HL_SUPPORT) */ + +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH "TxHbwFlowMaxQueueDepth" +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MIN ( 400 ) +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MAX ( 3500 ) +#define CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_DEFAULT ( 1500 ) +#endif /* QCA_LL_TX_FLOW_CT */ + +#define CFG_SAP_MAX_OFFLOAD_PEERS "gMaxOffloadPeers" +#define CFG_SAP_MAX_OFFLOAD_PEERS_MIN (2) +#define CFG_SAP_MAX_OFFLOAD_PEERS_MAX (12) +#define CFG_SAP_MAX_OFFLOAD_PEERS_DEFAULT (2) + +#define CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS "gMaxOffloadReorderBuffs" +#define CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS_MIN (0) +#define CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS_MAX (12) +#define CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS_DEFAULT (2) + +#ifdef FEATURE_WLAN_RA_FILTERING +#define CFG_RA_FILTER_ENABLE_NAME "gRAFilterEnable" +#define CFG_RA_FILTER_ENABLE_MIN (0) +#define CFG_RA_FILTER_ENABLE_MAX (1) +#define CFG_RA_FILTER_ENABLE_DEFAULT (0) + +#define CFG_RA_RATE_LIMIT_INTERVAL_NAME "gRArateLimitInterval" +#define CFG_RA_RATE_LIMIT_INTERVAL_MIN (60) +#define CFG_RA_RATE_LIMIT_INTERVAL_MAX (3600) +#define CFG_RA_RATE_LIMIT_INTERVAL_DEFAULT (60)/*60 SEC*/ +#endif + +#define CFG_IGNORE_PEER_ERP_INFO_NAME "gIgnorePeerErpInfo" +#define CFG_IGNORE_PEER_ERP_INFO_MIN ( 0 ) +#define CFG_IGNORE_PEER_ERP_INFO_MAX ( 1 ) +#define CFG_IGNORE_PEER_ERP_INFO_DEFAULT ( 0 ) + +#define CFG_INITIAL_DWELL_TIME_NAME "gInitialDwellTime" +#define CFG_INITIAL_DWELL_TIME_DEFAULT (0) +#define CFG_INITIAL_DWELL_TIME_MIN (0) +#define CFG_INITIAL_DWELL_TIME_MAX (100) + +#define CFG_INITIAL_SCAN_NO_DFS_CHNL_NAME "gInitialScanNoDFSChnl" +#define CFG_INITIAL_SCAN_NO_DFS_CHNL_DEFAULT (0) +#define CFG_INITIAL_SCAN_NO_DFS_CHNL_MIN (0) +#define CFG_INITIAL_SCAN_NO_DFS_CHNL_MAX (1) + +#define CFG_OVERRIDE_COUNTRY_CODE "gStaCountryCode" +#define CFG_OVERRIDE_COUNTRY_CODE_DEFAULT "000" + +#define CFG_ROAMING_DFS_CHANNEL_NAME "gAllowDFSChannelRoam" +#define CFG_ROAMING_DFS_CHANNEL_DISABLED (0) +#define CFG_ROAMING_DFS_CHANNEL_ENABLED_NORMAL (1) +#define CFG_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE (2) +#define CFG_ROAMING_DFS_CHANNEL_MIN (CFG_ROAMING_DFS_CHANNEL_DISABLED) +#define CFG_ROAMING_DFS_CHANNEL_MAX (CFG_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE) +#define CFG_ROAMING_DFS_CHANNEL_DEFAULT (CFG_ROAMING_DFS_CHANNEL_DISABLED) + +#ifdef MSM_PLATFORM +#define CFG_BUS_BANDWIDTH_HIGH_THRESHOLD "gBusBandwidthHighThreshold" +#define CFG_BUS_BANDWIDTH_HIGH_THRESHOLD_DEFAULT ( 2000 ) +#define CFG_BUS_BANDWIDTH_HIGH_THRESHOLD_MIN ( 0 ) +#define CFG_BUS_BANDWIDTH_HIGH_THRESHOLD_MAX ( 4294967295UL ) + +#define CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD "gBusBandwidthMediumThreshold" +#define CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD_DEFAULT ( 500 ) +#define CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD_MIN ( 0 ) +#define CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD_MAX ( 4294967295UL ) + +#define CFG_BUS_BANDWIDTH_LOW_THRESHOLD "gBusBandwidthLowThreshold" +#define CFG_BUS_BANDWIDTH_LOW_THRESHOLD_DEFAULT ( 150 ) +#define CFG_BUS_BANDWIDTH_LOW_THRESHOLD_MIN ( 0 ) +#define CFG_BUS_BANDWIDTH_LOW_THRESHOLD_MAX ( 4294967295UL ) + +#define CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL "gBusBandwidthComputeInterval" +#define CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL_DEFAULT ( 100 ) +#define CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL_MIN ( 0 ) +#define CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL_MAX ( 10000 ) + +#define CFG_TCP_DELACK_THRESHOLD_HIGH "gTcpDelAckThresholdHigh" +#define CFG_TCP_DELACK_THRESHOLD_HIGH_DEFAULT ( 500 ) +#define CFG_TCP_DELACK_THRESHOLD_HIGH_MIN ( 0 ) +#define CFG_TCP_DELACK_THRESHOLD_HIGH_MAX ( 16000 ) + +#define CFG_TCP_DELACK_THRESHOLD_LOW "gTcpDelAckThresholdLow" +#define CFG_TCP_DELACK_THRESHOLD_LOW_DEFAULT ( 1000 ) +#define CFG_TCP_DELACK_THRESHOLD_LOW_MIN ( 0 ) +#define CFG_TCP_DELACK_THRESHOLD_LOW_MAX ( 10000 ) + +/* TCP_TX_HIGH_TPUT_THRESHOLD specifies the threshold of packets transmitted + * over a period of 100 ms beyond which TCP can be considered to have a high + * TX throughput requirement. The driver uses this condition to tweak TCP TX + * specific parameters (via cnss-daemon). + * default - 500 + */ +#define CFG_TCP_TX_HIGH_TPUT_THRESHOLD_NAME "gTcpTxHighTputThreshold" +#define CFG_TCP_TX_HIGH_TPUT_THRESHOLD_DEFAULT ( 500 ) +#define CFG_TCP_TX_HIGH_TPUT_THRESHOLD_MIN ( 0 ) +#define CFG_TCP_TX_HIGH_TPUT_THRESHOLD_MAX ( 16000 ) + +#endif /* MSM_PLATFORM */ + +#ifdef WLAN_FEATURE_11W +#define CFG_PMF_SA_QUERY_MAX_RETRIES_NAME "pmfSaQueryMaxRetries" +#define CFG_PMF_SA_QUERY_MAX_RETRIES_DEFAULT ( 5 ) +#define CFG_PMF_SA_QUERY_MAX_RETRIES_MIN ( 0 ) +#define CFG_PMF_SA_QUERY_MAX_RETRIES_MAX ( 20 ) + +#define CFG_PMF_SA_QUERY_RETRY_INTERVAL_NAME "pmfSaQueryRetryInterval" +#define CFG_PMF_SA_QUERY_RETRY_INTERVAL_DEFAULT ( 200 ) +#define CFG_PMF_SA_QUERY_RETRY_INTERVAL_MIN ( 0 ) +#define CFG_PMF_SA_QUERY_RETRY_INTERVAL_MAX ( 2000 ) +#endif + +#define CFG_MAX_CONCURRENT_CONNECTIONS_NAME "gMaxConcurrentActiveSessions" +#define CFG_MAX_CONCURRENT_CONNECTIONS_DEFAULT ( 2 ) +#define CFG_MAX_CONCURRENT_CONNECTIONS_MIN ( 1 ) +#define CFG_MAX_CONCURRENT_CONNECTIONS_MAX ( 4 ) + +#define CFG_IGNORE_CAC_NAME "gIgnoreCAC" +#define CFG_IGNORE_CAC_MIN ( 0 ) +#define CFG_IGNORE_CAC_MAX ( 1 ) +#define CFG_IGNORE_CAC_DEFAULT ( 0 ) + +#define CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_NAME "gEnableSAPDfsChSifsBurst" +#define CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_MIN ( 0 ) +#define CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_MAX ( 1 ) +#define CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_DEFAULT ( 1 ) + +#define CFG_DFS_RADAR_PRI_MULTIPLIER_NAME "gDFSradarMappingPriMultiplier" +#define CFG_DFS_RADAR_PRI_MULTIPLIER_DEFAULT ( 4 ) +#define CFG_DFS_RADAR_PRI_MULTIPLIER_MIN ( 0 ) +#define CFG_DFS_RADAR_PRI_MULTIPLIER_MAX ( 10 ) +#define CFG_REORDER_OFFLOAD_SUPPORT_NAME "gReorderOffloadSupported" +#define CFG_REORDER_OFFLOAD_SUPPORT_MIN ( 0 ) +#define CFG_REORDER_OFFLOAD_SUPPORT_MAX ( 1 ) +#define CFG_REORDER_OFFLOAD_SUPPORT_DEFAULT ( 0 ) + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define CFG_ROAMING_OFFLOAD_NAME "gRoamOffloadEnabled" +#define CFG_ROAMING_OFFLOAD_MIN (0) +#define CFG_ROAMING_OFFLOAD_MAX (1) +#define CFG_ROAMING_OFFLOAD_DEFAULT (0) +#endif +#ifdef IPA_UC_OFFLOAD +#define CFG_IPA_UC_OFFLOAD_ENABLED_NAME "IpaUcOffloadEnabled" +#define CFG_IPA_UC_OFFLOAD_ENABLED_MIN ( 0 ) +#define CFG_IPA_UC_OFFLOAD_ENABLED_MAX ( 1 ) +#define CFG_IPA_UC_OFFLOAD_ENABLED_DEFAULT ( 0 ) + +#define CFG_IPA_UC_TX_BUF_COUNT_NAME "IpaUcTxBufCount" +#define CFG_IPA_UC_TX_BUF_COUNT_MIN ( 0 ) +#define CFG_IPA_UC_TX_BUF_COUNT_MAX ( 2048 ) +#define CFG_IPA_UC_TX_BUF_COUNT_DEFAULT ( 512 ) + +#define CFG_IPA_UC_TX_BUF_SIZE_NAME "IpaUcTxBufSize" +#define CFG_IPA_UC_TX_BUF_SIZE_MIN ( 0 ) +#define CFG_IPA_UC_TX_BUF_SIZE_MAX ( 4096 ) +#define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT ( 2048 ) + +#define CFG_IPA_UC_RX_IND_RING_COUNT_NAME "IpaUcRxIndRingCount" +#define CFG_IPA_UC_RX_IND_RING_COUNT_MIN ( 0 ) +#define CFG_IPA_UC_RX_IND_RING_COUNT_MAX ( 2048 ) +#define CFG_IPA_UC_RX_IND_RING_COUNT_DEFAULT ( 1024 ) + +#define CFG_IPA_UC_TX_PARTITION_BASE_NAME "IpaUcTxPartitionBase" +#define CFG_IPA_UC_TX_PARTITION_BASE_MIN ( 0 ) +#define CFG_IPA_UC_TX_PARTITION_BASE_MAX ( 9000 ) +#define CFG_IPA_UC_TX_PARTITION_BASE_DEFAULT ( 3000 ) +#endif /* IPA_UC_OFFLOAD */ +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE +/* Enable WLAN Logging to app space */ +#define CFG_WLAN_LOGGING_SUPPORT_NAME "wlanLoggingEnable" +#define CFG_WLAN_LOGGING_SUPPORT_ENABLE ( 1 ) +#define CFG_WLAN_LOGGING_SUPPORT_DISABLE ( 0 ) +#define CFG_WLAN_LOGGING_SUPPORT_DEFAULT ( 1 ) + +/* Enable FATAL and ERROR logs for kmsg console */ +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_NAME "wlanLoggingFEToConsole" +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_ENABLE ( 1 ) +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_DISABLE ( 0 ) +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_DEFAULT ( 1 ) + +/* Number of buffers to be used for WLAN logging */ +#define CFG_WLAN_LOGGING_NUM_BUF_NAME "wlanLoggingNumBuf" +#define CFG_WLAN_LOGGING_NUM_BUF_MIN ( 4 ) +#define CFG_WLAN_LOGGING_NUM_BUF_MAX ( 512 ) +#define CFG_WLAN_LOGGING_NUM_BUF_DEFAULT ( 256 ) +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ + +#define CFG_ENABLE_SIFS_BURST "gEnableSifsBurst" +#define CFG_ENABLE_SIFS_BURST_MIN ( 0 ) +#define CFG_ENABLE_SIFS_BURST_MAX ( 1 ) +#define CFG_ENABLE_SIFS_BURST_DEFAULT ( 0 ) + +#ifdef WLAN_FEATURE_LPSS +#define CFG_ENABLE_LPASS_SUPPORT "gEnableLpassSupport" +#define CFG_ENABLE_LPASS_SUPPORT_DEFAULT ( 0 ) +#define CFG_ENABLE_LPASS_SUPPORT_MIN ( 0 ) +#define CFG_ENABLE_LPASS_SUPPORT_MAX ( 1 ) +#endif + +/* + * NaN feature support configuration + * gEnableNanSupport = 0 means NaN is not supported + * gEnableNanSupport = 1 means NaN is supported + */ +#ifdef WLAN_FEATURE_NAN +#define CFG_ENABLE_NAN_SUPPORT "gEnableNanSupport" +#define CFG_ENABLE_NAN_SUPPORT_DEFAULT (0) +#define CFG_ENABLE_NAN_SUPPORT_MIN (0) +#define CFG_ENABLE_NAN_SUPPORT_MAX (1) +#endif + +#define CFG_ENABLE_SELF_RECOVERY "gEnableSelfRecovery" +#define CFG_ENABLE_SELF_RECOVERY_MIN ( 0 ) +#define CFG_ENABLE_SELF_RECOVERY_MAX ( 1 ) +#define CFG_ENABLE_SELF_RECOVERY_DEFAULT ( 0 ) + +#define CFG_ENABLE_SAP_SUSPEND "gEnableSapSuspend" +#define CFG_ENABLE_SAP_SUSPEND_MIN ( 0 ) +#define CFG_ENABLE_SAP_SUSPEND_MAX ( 1 ) +#define CFG_ENABLE_SAP_SUSPEND_DEFAULT ( 1 ) + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define CFG_EXTWOW_GO_TO_SUSPEND "gExtWoWgotoSuspend" +#define CFG_EXTWOW_GO_TO_SUSPEND_MIN ( 0 ) +#define CFG_EXTWOW_GO_TO_SUSPEND_MAX ( 1 ) +#define CFG_EXTWOW_GO_TO_SUSPEND_DEFAULT ( 1 ) + +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER "gExtWowApp1WakeupPinNumber" +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_MIN ( 0 ) +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_MAX ( 255 ) +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_DEFAULT ( 12 ) + +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER "gExtWowApp2WakeupPinNumber" +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_MIN ( 0 ) +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_MAX ( 255 ) +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_DEFAULT ( 16 ) + +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL "gExtWoWApp2KAInitPingInterval" +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL_MIN ( 0 ) +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL_MAX ( 0xffffffff ) +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL_DEFAULT ( 240 ) + +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL "gExtWoWApp2KAMinPingInterval" +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL_MIN ( 0 ) +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL_MAX ( 0xffffffff ) +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL_DEFAULT ( 240 ) + +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL "gExtWoWApp2KAMaxPingInterval" +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL_MIN ( 0 ) +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL_MAX ( 0xffffffff ) +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL_DEFAULT ( 1280 ) + +#define CFG_EXTWOW_KA_INC_PING_INTERVAL "gExtWoWApp2KAIncPingInterval" +#define CFG_EXTWOW_KA_INC_PING_INTERVAL_MIN ( 0 ) +#define CFG_EXTWOW_KA_INC_PING_INTERVAL_MAX ( 0xffffffff ) +#define CFG_EXTWOW_KA_INC_PING_INTERVAL_DEFAULT ( 4 ) + +#define CFG_EXTWOW_TCP_SRC_PORT "gExtWoWApp2TcpSrcPort" +#define CFG_EXTWOW_TCP_SRC_PORT_MIN ( 0 ) +#define CFG_EXTWOW_TCP_SRC_PORT_MAX ( 65535 ) +#define CFG_EXTWOW_TCP_SRC_PORT_DEFAULT ( 5000 ) + +#define CFG_EXTWOW_TCP_DST_PORT "gExtWoWApp2TcpDstPort" +#define CFG_EXTWOW_TCP_DST_PORT_MIN ( 0 ) +#define CFG_EXTWOW_TCP_DST_PORT_MAX ( 65535 ) +#define CFG_EXTWOW_TCP_DST_PORT_DEFAULT ( 5001 ) + +#define CFG_EXTWOW_TCP_TX_TIMEOUT "gExtWoWApp2TcpTxTimeout" +#define CFG_EXTWOW_TCP_TX_TIMEOUT_MIN ( 0 ) +#define CFG_EXTWOW_TCP_TX_TIMEOUT_MAX ( 0xffffffff ) +#define CFG_EXTWOW_TCP_TX_TIMEOUT_DEFAULT ( 200 ) + +#define CFG_EXTWOW_TCP_RX_TIMEOUT "gExtWoWApp2TcpRxTimeout" +#define CFG_EXTWOW_TCP_RX_TIMEOUT_MIN ( 0 ) +#define CFG_EXTWOW_TCP_RX_TIMEOUT_MAX ( 0xffffffff ) +#define CFG_EXTWOW_TCP_RX_TIMEOUT_DEFAULT ( 200 ) +#endif + +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_NAME "gEnableDeauthToDisassocMap" +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_MIN ( 0 ) +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_MAX ( 1 ) +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_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 ( CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MIN ) + +/* 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 ( 10 ) +#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_DEFAULT ( CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MAX ) + +/* Starting address assigned to DHCP client */ +#define CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_NAME "gDHCPClientStartIP" +#define CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_MIN ( 100 ) +#define CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_MAX ( 255 ) +#define CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_DEFAULT ( CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_MIN ) + +/* DHCP Server IP*/ +#define CFG_DHCP_SERVER_IP_NAME "gDHCPServerIP" +#define CFG_DHCP_SERVER_IP_DEFAULT "" +#endif /* DHCP_SERVER_OFFLOAD */ + +/* + * If last disconnection was due to HB failure and we reconnect + * to same AP next time, send Deauth before starting connection + */ +#define CFG_ENABLE_DEAUTH_BEFORE_CONNECTION "gSendDeauthBeforeCon" +#define CFG_ENABLE_DEAUTH_BEFORE_CONNECTION_MIN (0) +#define CFG_ENABLE_DEAUTH_BEFORE_CONNECTION_MAX (1) +#define CFG_ENABLE_DEAUTH_BEFORE_CONNECTION_DEFAULT (0) + +#define CFG_ENABLE_MAC_ADDR_SPOOFING "gEnableMacAddrSpoof" +#define CFG_ENABLE_MAC_ADDR_SPOOFING_MIN (0) +#define CFG_ENABLE_MAC_ADDR_SPOOFING_MAX (1) +#define CFG_ENABLE_MAC_ADDR_SPOOFING_DEFAULT (1) + +#define CFG_SAP_DOT11MC "gSapDot11mc" +#define CFG_SAP_DOT11MC_MIN (0) +#define CFG_SAP_DOT11MC_MAX (1) +#define CFG_SAP_DOT11MC_DEFAULT (0) + +/* + * Custom concurrency rule1: + * If SAP comes up first and STA comes up later then SAP + * needs to follow STA's channel. + */ +#define CFG_ENABLE_CUSTOM_CONC_RULE1_NAME "gEnableCustomConcRule1" +#define CFG_ENABLE_CUSTOM_CONC_RULE1_NAME_MIN (0) +#define CFG_ENABLE_CUSTOM_CONC_RULE1_NAME_MAX (1) +#define CFG_ENABLE_CUSTOM_CONC_RULE1_NAME_DEFAULT (0) + +#define CFG_ENABLE_CUSTOM_CONC_RULE2_NAME "gEnableCustomConcRule2" +#define CFG_ENABLE_CUSTOM_CONC_RULE2_NAME_MIN (0) +#define CFG_ENABLE_CUSTOM_CONC_RULE2_NAME_MAX (1) +#define CFG_ENABLE_CUSTOM_CONC_RULE2_NAME_DEFAULT (0) + +#define CFG_ENABLE_STA_CONNECTION_IN_5GHZ "gEnableStaConnectionIn5Ghz" +#define CFG_ENABLE_STA_CONNECTION_IN_5GHZ_MIN (0) +#define CFG_ENABLE_STA_CONNECTION_IN_5GHZ_MAX (1) +#define CFG_ENABLE_STA_CONNECTION_IN_5GHZ_DEFAULT (1) + +#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 ( CFG_MDNS_OFFLOAD_SUPPORT_MIN ) + +/* Set FQDN string for mDNS */ +#define CFG_MDNS_FQDN_NAME "gMDNSFqdn" +#define CFG_MDNS_FQDN_DEFAULT "" + +/* Set UFQDN string for mDNS */ +#define CFG_MDNS_UNIQUE_FQDN_NAME "gMDNSUniqueFqdn" +#define CFG_MDNS_UNIQUE_FQDN_DEFAULT "" + +/* Set the response Type A to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_A_NAME "gMDNSResponseTypeA" +#define CFG_MDNS_RESPONSE_TYPE_A_DEFAULT "" +#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 ( 0xffffffff ) + +/* Set the response Type TXT to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_TXT_NAME "gMDNSResponseTypeTXT" +#define CFG_MDNS_RESPONSE_TYPE_TXT_DEFAULT "" +#define CFG_MDNS_RESPONSE_TYPE_TXT_CNT_NAME "gMDNSResponseTypeTXTContent" +#define CFG_MDNS_RESPONSE_TYPE_TXT_CNT_DEFAULT "" + +/* Set the response Type PTR to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_PTR_NAME "gMDNSResponseTypePTR" +#define CFG_MDNS_RESPONSE_TYPE_PTR_DEFAULT "" +#define CFG_MDNS_RESPONSE_TYPE_PTR_DN_NAME "gMDNSResponseTypePTRDomainName" +#define CFG_MDNS_RESPONSE_TYPE_PTR_DN_DEFAULT "" + +/* Set the response Type SRV to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_SRV_NAME "gMDNSResponseTypeSRV" +#define CFG_MDNS_RESPONSE_TYPE_SRV_DEFAULT "" + +/* 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 ( CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_MIN ) + +/* 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 ( CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_MIN ) + +/* 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 "" +#endif /* MDNS_OFFLOAD */ + +#ifdef SAP_AUTH_OFFLOAD +/* Enable/Disable SAP Authentication offload + * Default: Disable + */ +#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 ( 0 ) + +/* 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 */ + +enum dot11p_mode { + WLAN_HDD_11P_DISABLED = 0, + WLAN_HDD_11P_STANDALONE, + WLAN_HDD_11P_CONCURRENT, +}; + +#define CFG_DOT11P_MODE_NAME "gDot11PMode" +#define CFG_DOT11P_MODE_DEFAULT ( WLAN_HDD_11P_DISABLED ) +#define CFG_DOT11P_MODE_MIN ( WLAN_HDD_11P_DISABLED ) +#define CFG_DOT11P_MODE_MAX ( WLAN_HDD_11P_CONCURRENT ) + +#define CFG_P2P_LISTEN_DEFER_INTERVAL_NAME "gP2PListenDeferInterval" +#define CFG_P2P_LISTEN_DEFER_INTERVAL_MIN (100) +#define CFG_P2P_LISTEN_DEFER_INTERVAL_MAX (200) +#define CFG_P2P_LISTEN_DEFER_INTERVAL_DEFAULT (100) + +#define CFG_STA_MIRACAST_MCC_REST_TIME_VAL "gStaMiracastMccRestTimeVal" +#define CFG_STA_MIRACAST_MCC_REST_TIME_VAL_MIN (100) +#define CFG_STA_MIRACAST_MCC_REST_TIME_VAL_MAX (500) +#define CFG_STA_MIRACAST_MCC_REST_TIME_VAL_DEFAULT (400) + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define CFG_SAP_MCC_CHANNEL_AVOIDANCE_NAME "gSapChannelAvoidance" +#define CFG_SAP_MCC_CHANNEL_AVOIDANCE_MIN ( 0 ) +#define CFG_SAP_MCC_CHANNEL_AVOIDANCE_MAX ( 1 ) +#define CFG_SAP_MCC_CHANNEL_AVOIDANCE_DEFAULT ( 0 ) +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#define CFG_SAP_P2P_11AC_OVERRIDE_NAME "gAP11ACOverride" +#define CFG_SAP_P2P_11AC_OVERRIDE_MIN (0) +#define CFG_SAP_P2P_11AC_OVERRIDE_MAX (1) +#define CFG_SAP_P2P_11AC_OVERRIDE_DEFAULT (1) + +#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR "gPreferNonDfsChanOnRadar" +#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MIN (0) +#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MAX (1) +#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_DEFAULT (0) + +/* Parameters for roaming scans performed at high RSSI */ + +/* Maximum number of scans after RSSI change */ +#define CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_NAME "gRoamScanHiRssiMaxCount" +#define CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_MIN (0) +#define CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_MAX (10) +#define CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_DEFAULT (3) + +/* Change in RSSI at which scan is triggered */ +#define CFG_ROAM_SCAN_HI_RSSI_DELTA_NAME "gRoamScanHiRssiDelta" +#define CFG_ROAM_SCAN_HI_RSSI_DELTA_MIN (0) +#define CFG_ROAM_SCAN_HI_RSSI_DELTA_MAX (16) +#define CFG_ROAM_SCAN_HI_RSSI_DELTA_DEFAULT (10) + +/* Delay between consecutive scans in milliseconds */ +#define CFG_ROAM_SCAN_HI_RSSI_DELAY_NAME "gRoamScanHiRssiDelay" +#define CFG_ROAM_SCAN_HI_RSSI_DELAY_MIN (5000) +#define CFG_ROAM_SCAN_HI_RSSI_DELAY_MAX (0x7fffffff) +#define CFG_ROAM_SCAN_HI_RSSI_DELAY_DEFAULT (15000) + +/* Upper bound after which scan will not be performed */ +#define CFG_ROAM_SCAN_HI_RSSI_UB_NAME "gRoamScanHiRssiUpperBound" +#define CFG_ROAM_SCAN_HI_RSSI_UB_MIN (-66) +#define CFG_ROAM_SCAN_HI_RSSI_UB_MAX (0) +#define CFG_ROAM_SCAN_HI_RSSI_UB_DEFAULT (-30) + +/* Option to report rssi in cfg80211_inform_bss_frame() + * 0 = use rssi value based on noise floor = -96 dBm + * 1 = use rssi value based on actual noise floor in hardware + */ +#define CFG_INFORM_BSS_RSSI_RAW_NAME "gInformBssRssiRaw" +#define CFG_INFORM_BSS_RSSI_RAW_MIN (0) +#define CFG_INFORM_BSS_RSSI_RAW_MAX (1) +#define CFG_INFORM_BSS_RSSI_RAW_DEFAULT (1) + +/* GPIO pin to toogle when capture tsf */ +#define CFG_SET_TSF_GPIO_PIN_NAME "gtsf_gpio_pin" +#define CFG_SET_TSF_GPIO_PIN_MIN (0) +#define CFG_SET_TSF_GPIO_PIN_MAX (255) +#define CFG_SET_TSF_GPIO_PIN_DEFAULT (34) + +#define CFG_MULTICAST_HOST_FW_MSGS "gMulticastHostFwMsgs" +#define CFG_MULTICAST_HOST_FW_MSGS_MIN (0) +#define CFG_MULTICAST_HOST_FW_MSGS_MAX (1) +#define CFG_MULTICAST_HOST_FW_MSGS_DEFAULT (1) + +#define CFG_TX_CHAIN_MASK_CCK "gCckChainMaskEnable" +#define CFG_TX_CHAIN_MASK_CCK_MIN (0) +#define CFG_TX_CHAIN_MASK_CCK_MAX (1) +#define CFG_TX_CHAIN_MASK_CCK_DEFAULT (0) + +#define CFG_TX_CHAIN_MASK_1SS "gTxChainMask1ss" +#define CFG_TX_CHAIN_MASK_1SS_MIN (0) +#define CFG_TX_CHAIN_MASK_1SS_MAX (3) +#define CFG_TX_CHAIN_MASK_1SS_DEFAULT (1) + +#define CFG_SELF_GEN_FRM_PWR "gSelfGenFrmPwr" +#define CFG_SELF_GEN_FRM_PWR_MIN (0) +#define CFG_SELF_GEN_FRM_PWR_MAX (0xffff) +#define CFG_SELF_GEN_FRM_PWR_DEFAULT (0) + +/* + * fine timing measurement capability information + * + * <----- fine_time_meas_cap (in bits) -----> + *+----------+-----+-----+------+------+-------+-------+-----+-----+ + *| 9-31 | 8 | 7 | 5 | 4 | 3 | 2 | 1 | 0 | + *+----------+-----+-----+------+------+-------+-------+-----+-----+ + *| reserved | SAP | SAP |P2P-GO|P2P-GO|P2P-CLI|P2P-CLI| STA | STA | + *| |resp |init |resp |init |resp |init |resp |init | + *+----------+-----+-----+------+------+-------+-------+-----+-----+ + * + * resp - responder role; init- initiator role + * + * CFG_FINE_TIME_MEAS_CAPABILITY_MAX computed based on the table + * +-----------------+-----------------+-----------+ + * | Device Role | Initiator | Responder | + * +-----------------+-----------------+-----------+ + * | Station | Y | N | + * | P2P-CLI | Y | Y | + * | P2P-GO | Y | Y | + * | SAP | N | Y | + * +-----------------+-----------------+-----------+ + */ +#define CFG_FINE_TIME_MEAS_CAPABILITY "gfine_time_meas_cap" +#define CFG_FINE_TIME_MEAS_CAPABILITY_MIN (0x0000) +#define CFG_FINE_TIME_MEAS_CAPABILITY_MAX (0x00BD) +#define CFG_FINE_TIME_MEAS_CAPABILITY_DEFAULT (0x000D) + +#ifdef FEATURE_WLAN_EXTSCAN +#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_NAME "gExtScanPassiveMaxChannelTime" +#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_MIN (0) +#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_MAX (500) +#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_DEFAULT (110) + +#define CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_NAME "gExtScanPassiveMinChannelTime" +#define CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_MIN (0) +#define CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_MAX (500) +#define CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_DEFAULT (60) + +#define CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_NAME "gExtScanActiveMaxChannelTime" +#define CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_MIN (0) +#define CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_MAX (110) +#define CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_DEFAULT (40) + +#define CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_NAME "gExtScanActiveMinChannelTime" +#define CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_MIN (0) +#define CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_MAX (110) +#define CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_DEFAULT (20) +#endif + +/* client failure connection count*/ +#define CFG_CONNECT_FAIL_COUNT_NAME "gconnect_fail_count" +#define CFG_CONNECT_FAIL_COUNT_MIN ( 0 ) +#define CFG_CONNECT_FAIL_COUNT_MAX ( 10 ) +#define CFG_CONNECT_FAIL_COUNT_DEFAULT ( 0 ) + +/* time during which the client's failure connection attempts are recorded */ +#define CFG_CONNECT_FAIL_DURATION_NAME "gconnect_fail_duration" +#define CFG_CONNECT_FAIL_DURATION_MIN ( 1000 ) +#define CFG_CONNECT_FAIL_DURATION_MAX ( 0xffffffff ) +#define CFG_CONNECT_FAIL_DURATION_DEFAULT ( 60000 ) + +/* client are not permitted to connect to sap in this duration */ +#define CFG_CONNECT_BLOCK_DURATION_NAME "gconnect_block_duration" +#define CFG_CONNECT_BLOCK_DURATION_MIN ( 1000 ) +#define CFG_CONNECT_BLOCK_DURATION_MAX ( 0xffffffff ) +#define CFG_CONNECT_BLOCK_DURATION_DEFAULT ( 60000 ) + + + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD +/* + * Enable/Disable UDP response offload feature + * Default : Disable + */ +#define CFG_UDP_RESP_OFFLOAD_SUPPORT_NAME "gudp_resp_offload_support" +#define CFG_UDP_RESP_OFFLOAD_SUPPORT_MIN (0) +#define CFG_UDP_RESP_OFFLOAD_SUPPORT_MAX (1) +#define CFG_UDP_RESP_OFFLOAD_SUPPORT_DEFAULT (CFG_UDP_RESP_OFFLOAD_SUPPORT_MIN) + +/* Dest port of specific UDP packet */ +#define CFG_UDP_RESP_OFFLOAD_DEST_PORT_NAME "gudp_resp_offload_dest_port" +#define CFG_UDP_RESP_OFFLOAD_DEST_PORT_MIN (0) +#define CFG_UDP_RESP_OFFLOAD_DEST_PORT_MAX (65535) +#define CFG_UDP_RESP_OFFLOAD_DEST_PORT_DEFAULT (CFG_UDP_RESP_OFFLOAD_DEST_PORT_MAX) + +/* + * Payload filter of specific UDP packet + * Firmware will use this filter to identify the specific UDP packet + */ +#define CFG_UDP_RESP_OFFLOAD_PAYLOAD_FILTER_NAME "gudp_resp_offload_payload_filter" +#define CFG_UDP_RESP_OFFLOAD_PAYLOAD_FILTER_DEFAULT "" + +/* + * Payload of the response UDP + * The specific response UDP packet payload + */ +#define CFG_UDP_RESP_OFFLOAD_RESPONSE_PAYLOAD_NAME "gudp_resp_offload_response_payload" +#define CFG_UDP_RESP_OFFLOAD_RESPONSE_PAYLOAD_DEFAULT "status=off" +#endif + +/* + * Debug configuration variable to inject firmware crash on + * consecutive management tx failure. + * Value set as 0 will disable the feature. + */ +#define CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_NAME "gmax_mgmt_tx_failure_count" +#define CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_MIN (0) +#define CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_MAX (500) +#define CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_DEFAULT (0) + +/* + * This parameter will configure the first scan bucket + * threshold to the mentioned value and all the AP's which + * have RSSI under this threshold will fall under this + * bucket. + * This is a configuration item used to tweak and test the input + * for internal algorithm. It should not be modified externally. + */ +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_NAME "gfirst_scan_bucket_threshold" +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_MIN (-50) +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX (-30) +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_DEFAULT (-30) + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + +typedef struct +{ + //Bitmap to track what is explicitly configured + DECLARE_BITMAP(bExplicitCfg, MAX_CFG_INI_ITEMS); + + //Config parameters + v_U32_t RTSThreshold; + v_U32_t FragmentationThreshold; + v_U8_t OperatingChannel; + v_BOOL_t ShortSlotTimeEnabled; + v_BOOL_t Is11dSupportEnabled; + v_BOOL_t Is11hSupportEnabled; + v_BOOL_t fEnforce11dChannels; + v_BOOL_t fSupplicantCountryCodeHasPriority; + v_BOOL_t fEnforceCountryCodeMatch; + v_BOOL_t fEnforceDefaultDomain; + v_U32_t HeartbeatThresh24; + char PowerUsageControl[4]; + v_U8_t nEnableSuspend; + v_U8_t nEnableDriverStop; + v_BOOL_t fIsLogpEnabled; + v_U8_t btcExecutionMode; + v_U32_t mwsCoexConfig[6]; + v_BOOL_t fIsImpsEnabled; + v_U32_t nImpsModSleepTime; + v_U32_t nImpsMaxSleepTime; + v_U32_t nImpsMinSleepTime; + v_BOOL_t fIsBmpsEnabled; + v_U32_t nBmpsModListenInterval; + v_U32_t nBmpsMaxListenInterval; + v_U32_t nBmpsMinListenInterval; + v_BOOL_t fIsAutoBmpsTimerEnabled; + v_U32_t nAutoBmpsTimerValue; + eHddDot11Mode dot11Mode; + v_U32_t nChannelBondingMode24GHz; + v_U32_t nChannelBondingMode5GHz; + v_U32_t MaxRxAmpduFactor; + v_U16_t TxRate; + v_U32_t ShortGI20MhzEnable; + v_U32_t BlockAckAutoSetup; + v_U32_t ScanResultAgeCount; + v_U32_t nScanAgeTimeNCNPS; + v_U32_t nScanAgeTimeNCPS; + v_U32_t nScanAgeTimeCNPS; + v_U32_t nScanAgeTimeCPS; + v_U8_t nRssiCatGap; + v_BOOL_t fIsShortPreamble; + v_MACADDR_t IbssBssid; + v_U32_t AdHocChannel5G; + v_U32_t AdHocChannel24G; + v_U8_t intfAddrMask; + v_MACADDR_t intfMacAddr[VOS_MAX_CONCURRENCY_PERSONA]; + + v_BOOL_t apUapsdEnabled; + v_BOOL_t apRandomBssidEnabled; + v_BOOL_t apProtEnabled; + v_U16_t apProtection; + v_BOOL_t apOBSSProtEnabled; + v_U8_t MinFramesProcThres; + v_U8_t apCntryCode[4]; + v_BOOL_t apDisableIntraBssFwd; + v_U8_t nEnableListenMode; + v_U32_t nAPAutoShutOff; + v_U8_t enableLTECoex; + v_U32_t apKeepAlivePeriod; + v_U32_t goKeepAlivePeriod; + v_U32_t apLinkMonitorPeriod; + v_U32_t goLinkMonitorPeriod; + v_U32_t nBeaconInterval; + v_U8_t nTxPowerCap; //In dBm + v_BOOL_t fIsLowGainOverride; + v_U8_t disablePacketFilter; +#if defined WLAN_FEATURE_VOWIFI + v_BOOL_t fRrmEnable; + v_U8_t nInChanMeasMaxDuration; + v_U8_t nOutChanMeasMaxDuration; + v_U16_t nRrmRandnIntvl; + /* length includes separator */ + char rm_capability[3 * DOT11F_IE_RRMENABLEDCAP_MAX_LEN]; +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + //Vowifi 11r params + v_BOOL_t fFTResourceReqSupported; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + v_U16_t nNeighborScanPeriod; + v_U8_t nNeighborReassocRssiThreshold; + v_U8_t nNeighborLookupRssiThreshold; + v_U8_t delay_before_vdev_stop; + v_U8_t nOpportunisticThresholdDiff; + v_U8_t nRoamRescanRssiDiff; + v_U8_t neighborScanChanList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + v_U16_t nNeighborScanMinChanTime; + v_U16_t nNeighborScanMaxChanTime; + v_U16_t nMaxNeighborReqTries; + v_U16_t nNeighborResultsRefreshPeriod; + v_U16_t nEmptyScanRefreshPeriod; + v_U8_t nRoamBmissFirstBcnt; + v_U8_t nRoamBmissFinalBcnt; + v_U8_t nRoamBeaconRssiWeight; + uint32_t nhi_rssi_scan_max_count; + uint32_t nhi_rssi_scan_rssi_delta; + uint32_t nhi_rssi_scan_delay; + int32_t nhi_rssi_scan_rssi_ub; +#endif + + //Additional Handoff params + v_BOOL_t nEnableIdleScan; + v_U32_t nRoamingTime; + v_U16_t nVccRssiTrigger; + v_U32_t nVccUlMacLossThreshold; + + v_U32_t nPassiveMinChnTime; //in units of milliseconds + v_U32_t nPassiveMaxChnTime; //in units of milliseconds + v_U32_t nActiveMinChnTime; //in units of milliseconds + v_U32_t nActiveMaxChnTime; //in units of milliseconds + + v_U32_t nInitialDwellTime; //in units of milliseconds + bool initial_scan_no_dfs_chnl; + + v_U32_t nActiveMinChnTimeBtc; //in units of milliseconds + v_U32_t nActiveMaxChnTimeBtc; //in units of milliseconds +#ifdef WLAN_AP_STA_CONCURRENCY + v_U32_t nPassiveMinChnTimeConc; //in units of milliseconds + v_U32_t nPassiveMaxChnTimeConc; //in units of milliseconds + v_U32_t nActiveMinChnTimeConc; //in units of milliseconds + v_U32_t nActiveMaxChnTimeConc; //in units of milliseconds + v_U32_t nRestTimeConc; //in units of milliseconds + /* In units of milliseconds */ + uint32_t min_rest_time_conc; + /* In units of milliseconds */ + uint32_t idle_time_conc; + + v_U8_t nNumStaChanCombinedConc; //number of channels combined for + //STA in each split scan operation + v_U8_t nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation +#endif + + v_U8_t nMaxPsPoll; + + v_U8_t nRssiFilterPeriod; + v_BOOL_t fIgnoreDtim; + v_U8_t fMaxLIModulatedDTIM; + + v_U8_t nRxAnt; + v_U8_t fEnableFwHeartBeatMonitoring; + v_U8_t fEnableFwBeaconFiltering; + v_BOOL_t fEnableFwRssiMonitoring; + bool mcc_rts_cts_prot_enable; + bool mcc_bcast_prob_resp_enable; + v_U8_t nDataInactivityTimeout; + v_U8_t nthBeaconFilter; + + //WMM QoS Configuration + hdd_wmm_user_mode_t WmmMode; + v_BOOL_t b80211eIsEnabled; + v_U8_t UapsdMask; // what ACs to setup U-APSD for at assoc + v_U32_t InfraUapsdVoSrvIntv; + v_U32_t InfraUapsdVoSuspIntv; + v_U32_t InfraUapsdViSrvIntv; + v_U32_t InfraUapsdViSuspIntv; + v_U32_t InfraUapsdBeSrvIntv; + v_U32_t InfraUapsdBeSuspIntv; + v_U32_t InfraUapsdBkSrvIntv; + v_U32_t InfraUapsdBkSuspIntv; +#ifdef FEATURE_WLAN_LFR + v_BOOL_t isFastRoamIniFeatureEnabled; + v_BOOL_t MAWCEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + v_U32_t InfraInactivityInterval; + v_BOOL_t isEseIniFeatureEnabled; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + v_BOOL_t isFastTransitionEnabled; + v_U8_t RoamRssiDiff; + v_U8_t nImmediateRoamRssiDiff; + v_BOOL_t isWESModeEnabled; +#endif +#ifdef FEATURE_WLAN_OKC + v_BOOL_t isOkcIniFeatureEnabled; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + v_BOOL_t isRoamOffloadScanEnabled; +#endif + hdd_wmm_classification_t PktClassificationBasis; // DSCP or 802.1Q + v_BOOL_t bImplicitQosEnabled; + + /* default TSPEC parameters for AC_VO */ + sme_QosWmmDirType InfraDirAcVo; + v_U16_t InfraNomMsduSizeAcVo; + v_U32_t InfraMeanDataRateAcVo; + v_U32_t InfraMinPhyRateAcVo; + v_U16_t InfraSbaAcVo; + + /* default TSPEC parameters for AC_VI */ + sme_QosWmmDirType InfraDirAcVi; + v_U16_t InfraNomMsduSizeAcVi; + v_U32_t InfraMeanDataRateAcVi; + v_U32_t InfraMinPhyRateAcVi; + v_U16_t InfraSbaAcVi; + + /* default TSPEC parameters for AC_BE */ + sme_QosWmmDirType InfraDirAcBe; + v_U16_t InfraNomMsduSizeAcBe; + v_U32_t InfraMeanDataRateAcBe; + v_U32_t InfraMinPhyRateAcBe; + v_U16_t InfraSbaAcBe; + + /* default TSPEC parameters for AC_BK */ + sme_QosWmmDirType InfraDirAcBk; + v_U16_t InfraNomMsduSizeAcBk; + v_U32_t InfraMeanDataRateAcBk; + v_U32_t InfraMinPhyRateAcBk; + v_U16_t InfraSbaAcBk; + + /* TL related configuration */ + v_U32_t DelayedTriggerFrmInt; + + /* Wowl pattern */ + char wowlPattern[1024]; + + /* Control for Replay counter. value 1 means + single replay counter for all TID*/ + v_BOOL_t bSingleTidRc; + v_U8_t mcastBcastFilterSetting; + v_BOOL_t fhostArpOffload; + bool bcastptrn; + v_BOOL_t ssdp; + +#ifdef FEATURE_RUNTIME_PM + v_BOOL_t runtime_pm; + v_U32_t runtime_pm_delay; +#endif + +#ifdef FEATURE_WLAN_RA_FILTERING + v_BOOL_t IsRArateLimitEnabled; + v_U16_t RArateLimitInterval; +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + v_BOOL_t PnoOffload; +#endif + v_BOOL_t fhostNSOffload; + v_BOOL_t burstSizeDefinition; + v_U8_t tsInfoAckPolicy; + + /* RF Settling Time Clock */ + v_U32_t rfSettlingTimeUs; + + v_U8_t dynamicPsPollValue; + v_BOOL_t AddTSWhenACMIsOff; + v_BOOL_t fValidateScanList; + + v_U32_t infraStaKeepAlivePeriod; + v_U8_t nNullDataApRespTimeout; + v_U8_t nBandCapability; + + v_U32_t apDataAvailPollPeriodInMs; + v_BOOL_t fEnableBeaconEarlyTermination; + v_BOOL_t teleBcnWakeupEn; + +/* VOS Trace Control*/ + v_U16_t vosTraceEnableTL; + v_U16_t vosTraceEnableWDI; + v_U16_t vosTraceEnableHDD; + v_U16_t vosTraceEnableSME; + v_U16_t vosTraceEnablePE; + v_U16_t vosTraceEnablePMC; + v_U16_t vosTraceEnableWDA; + v_U16_t vosTraceEnableSYS; + v_U16_t vosTraceEnableVOSS; + v_U16_t vosTraceEnableSAP; + v_U16_t vosTraceEnableHDDSAP; + v_U16_t vosTraceEnableCFG; + v_U16_t vosTraceEnableADF; + v_U16_t vosTraceEnableTXRX; + v_U16_t vosTraceEnableHTC; + v_U16_t vosTraceEnableHIF; + v_U16_t vosTraceEnableHDDSAPDATA; + v_U16_t vosTraceEnableHDDDATA; + + v_U16_t nTeleBcnTransListenInterval; + v_U16_t nTeleBcnMaxListenInterval; + v_U16_t nTeleBcnTransLiNumIdleBeacons; + v_U16_t nTeleBcnMaxLiNumIdleBeacons; + v_U8_t bcnEarlyTermWakeInterval; + v_U32_t enableCloseLoop; + v_U8_t enableBypass11d; + v_U8_t enableDFSChnlScan; + v_U8_t enable_dfs_pno_chnl_scan; + v_U8_t enableDynamicDTIM; + v_U8_t enableAutomaticTxPowerControl; + v_U8_t ShortGI40MhzEnable; + eHddLinkSpeedReportType reportMaxLinkSpeed; + v_S31_t linkSpeedRssiHigh; + v_S31_t linkSpeedRssiMid; + v_S31_t linkSpeedRssiLow; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + v_BOOL_t nRoamPrefer5GHz; + v_BOOL_t nRoamIntraBand; + v_U8_t nProbes; + v_U16_t nRoamScanHomeAwayTime; +#endif + v_U8_t enableMCC; + v_U8_t allowMCCGODiffBI; + v_BOOL_t isP2pDeviceAddrAdministrated; + v_U8_t thermalMitigationEnable; + v_U32_t throttlePeriod; +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + bool bad_peer_txctl_enable; + uint32_t bad_peer_txctl_prd; + uint32_t bad_peer_txctl_txq_lmt; + uint32_t bad_peer_tgt_backoff; + uint32_t bad_peer_tgt_report_prd; + uint32_t bad_peer_cond_ieee80211b; + uint32_t bad_peer_delta_ieee80211b; + uint32_t bad_peer_pct_ieee80211b; + uint32_t bad_peer_tput_ieee80211b; + uint32_t bad_peer_limit_ieee80211b; + uint32_t bad_peer_cond_ieee80211ag; + uint32_t bad_peer_delta_ieee80211ag; + uint32_t bad_peer_pct_ieee80211ag; + uint32_t bad_peer_tput_ieee80211ag; + uint32_t bad_peer_limit_ieee80211ag; + uint32_t bad_peer_cond_ieee80211n; + uint32_t bad_peer_delta_ieee80211n; + uint32_t bad_peer_pct_ieee80211n; + uint32_t bad_peer_tput_ieee80211n; + uint32_t bad_peer_limit_ieee80211n; + uint32_t bad_peer_cond_ieee80211ac; + uint32_t bad_peer_delta_ieee80211ac; + uint32_t bad_peer_pct_ieee80211ac; + uint32_t bad_peer_tput_ieee80211ac; + uint32_t bad_peer_limit_ieee80211ac; +#endif + v_U8_t vhtChannelWidth; + v_U8_t vhtRxMCS; + v_U8_t vhtTxMCS; + v_BOOL_t enableTxBF; + v_U8_t txBFCsnValue; + v_U8_t vhtRxMCS2x2; + v_U8_t vhtTxMCS2x2; + v_BOOL_t enable2x2; + uint8_t chain_mask_2g; + uint8_t chain_mask_5g; + uint32_t vdev_type_nss_2g; + uint32_t vdev_type_nss_5g; + v_BOOL_t txchainmask1x1; + v_BOOL_t rxchainmask1x1; + v_BOOL_t enableMuBformee; + v_BOOL_t enableVhtpAid; + v_BOOL_t enableVhtGid; + v_BOOL_t enableTxBFin20MHz; + v_U8_t enableAmpduPs; + v_U8_t enableHtSmps; + v_U8_t htSmps; + v_U8_t enableModulatedDTIM; + v_U32_t fEnableMCAddrList; + v_BOOL_t enableFirstScan2GOnly; + v_BOOL_t skipDfsChnlInP2pSearch; + v_BOOL_t ignoreDynamicDtimInP2pMode; + v_U16_t configMccParam; + v_U32_t numBuffAdvert; + v_BOOL_t enableRxSTBC; + v_BOOL_t enableTxSTBC; + v_BOOL_t enableRxLDPC; + v_BOOL_t enable5gEBT; +#ifdef FEATURE_WLAN_TDLS + v_BOOL_t fEnableTDLSSupport; + v_BOOL_t fEnableTDLSImplicitTrigger; + v_U32_t fTDLSTxStatsPeriod; + v_U32_t fTDLSTxPacketThreshold; + v_U32_t fTDLSDiscoveryPeriod; + v_U32_t fTDLSMaxDiscoveryAttempt; + v_U32_t fTDLSIdleTimeout; + v_U32_t fTDLSIdlePacketThreshold; + v_U32_t fTDLSRSSIHysteresis; + v_S31_t fTDLSRSSITriggerThreshold; + v_S31_t fTDLSRSSITeardownThreshold; + v_S31_t fTDLSRSSIDelta; + v_U32_t fTDLSUapsdMask; // what ACs to setup U-APSD for TDLS + v_U32_t fEnableTDLSBufferSta; + v_U32_t fEnableTDLSSleepSta; + v_U32_t fTDLSPuapsdInactivityTimer; + v_U32_t fTDLSRxFrameThreshold; + v_U32_t fTDLSPuapsdPTIWindow; + v_U32_t fTDLSPuapsdPTRTimeout; + v_BOOL_t fTDLSExternalControl; + v_U32_t fEnableTDLSOffChannel; + v_U32_t fEnableTDLSWmmMode; + v_U8_t fTDLSPrefOffChanNum; + v_U8_t fTDLSPrefOffChanBandwidth; + uint8_t enable_tdls_scan; + uint32_t tdls_peer_kickout_threshold; +#endif +#ifdef WLAN_SOFTAP_VSTA_FEATURE + v_BOOL_t fEnableVSTASupport; +#endif +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + v_BOOL_t fEnableActiveModeOffload; +#endif + v_U32_t enableLpwrImgTransition; + v_U8_t scanAgingTimeout; + v_BOOL_t enableTxLdpc; + v_U8_t disableLDPCWithTxbfAP; + v_U8_t enableMCCAdaptiveScheduler; + v_BOOL_t isAndroidPsEn; + v_BOOL_t sapAllowAllChannel; + v_U8_t retryLimitZero; + v_U8_t retryLimitOne; + v_U8_t retryLimitTwo; + v_U8_t disableAggWithBtc; + char listOfNonDfsCountryCode[128]; + v_BOOL_t enableSSR; + v_U32_t cfgMaxMediumTime; + v_BOOL_t enableVhtFor24GHzBand; + v_U8_t fScanOffload; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* Flag indicating whether legacy fast roam during concurrency is enabled in cfg.ini or not */ + v_BOOL_t bFastRoamInConIniFeatureEnabled; +#endif + v_BOOL_t fEnableAdaptRxDrain; + v_U8_t flexConnectPowerFactor; + v_BOOL_t enableIbssHeartBeatOffload; + v_U32_t antennaDiversity; + v_BOOL_t fEnableSNRMonitoring; + /*PNO related parameters */ +#ifdef FEATURE_WLAN_SCAN_PNO + v_BOOL_t configPNOScanSupport; + v_U32_t configPNOScanTimerRepeatValue; + uint32_t pno_slow_scan_multiplier; +#endif + v_U8_t max_amsdu_num; + v_U8_t nSelect5GHzMargin; + v_U8_t isCoalesingInIBSSAllowed; + + /* IBSS Power Save related parameters */ + v_U32_t ibssATIMWinSize; + v_U8_t isIbssPowerSaveAllowed; + v_U8_t isIbssPowerCollapseAllowed; + v_U8_t isIbssAwakeOnTxRx; + v_U32_t ibssInactivityCount; + v_U32_t ibssTxSpEndInactivityTime; + v_U32_t ibssPsWarmupTime; + v_U32_t ibssPs1RxChainInAtimEnable; + + v_BOOL_t enableTCPChkSumOffld; + v_BOOL_t enableIPChecksumOffload; + v_BOOL_t enablePowersaveOffload; + v_BOOL_t enablefwprint; + v_BOOL_t enablefwlog; + v_BOOL_t enableFwSelfRecovery; + v_BOOL_t fP2pListenOffload; +#ifdef WLAN_FEATURE_11AC + v_U8_t fVhtAmpduLenExponent; + v_U32_t vhtMpduLen; +#endif +#ifdef IPA_OFFLOAD + v_U32_t IpaConfig; + v_BOOL_t IpaClkScalingEnable; + v_U32_t IpaDescSize; + v_U32_t IpaHighBandwidthMbps; + v_U32_t IpaMediumBandwidthMbps; + v_U32_t IpaLowBandwidthMbps; +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + v_U32_t WlanMccToSccSwitchMode; +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + v_U32_t WlanAutoShutdown; +#endif + v_U8_t maxWoWFilters; + v_U8_t wowEnable; + v_U8_t maxNumberOfPeers; + v_U8_t disableDFSChSwitch; + v_U8_t enableDFSMasterCap; + v_U16_t thermalTempMinLevel0; + v_U16_t thermalTempMaxLevel0; + v_U16_t thermalTempMinLevel1; + v_U16_t thermalTempMaxLevel1; + v_U16_t thermalTempMinLevel2; + v_U16_t thermalTempMaxLevel2; + v_U16_t thermalTempMinLevel3; + v_U16_t thermalTempMaxLevel3; + v_U32_t TxPower2g; + v_U32_t TxPower5g; + v_U32_t gEnableDebugLog; + v_U8_t rxhandle; + uint8_t cpu_map_list[CFG_RPS_RX_QUEUE_CPU_MAP_LIST_LEN]; + v_BOOL_t fDfsPhyerrFilterOffload; + v_U8_t gSapPreferredChanLocation; + v_U8_t gDisableDfsJapanW53; + v_BOOL_t gEnableOverLapCh; + v_BOOL_t fRegChangeDefCountry; + v_U8_t acsScanBandPreference; +#ifdef QCA_LL_TX_FLOW_CT + v_U32_t TxFlowLowWaterMark; + v_U32_t TxFlowHighWaterMarkOffset; + v_U32_t TxFlowMaxQueueDepth; + v_U32_t TxLbwFlowLowWaterMark; + v_U32_t TxLbwFlowHighWaterMarkOffset; + v_U32_t TxLbwFlowMaxQueueDepth; + v_U32_t TxHbwFlowLowWaterMark; + v_U32_t TxHbwFlowHighWaterMarkOffset; + v_U32_t TxHbwFlowMaxQueueDepth; +#endif /* QCA_LL_TX_FLOW_CT */ + uint8_t force_sap_acs; + uint8_t force_sap_acs_st_ch; + uint8_t force_sap_acs_end_ch; + v_U16_t acsBandSwitchThreshold; + v_U8_t apMaxOffloadPeers; + v_U8_t apMaxOffloadReorderBuffs; + v_BOOL_t advertiseConcurrentOperation; + v_BOOL_t enableMemDeepSleep; + + v_U32_t defaultRateIndex24Ghz; + char overrideCountryCode[4]; + + v_U8_t allowDFSChannelRoam; + + v_BOOL_t debugP2pRemainOnChannel; + + v_BOOL_t enablePacketLog; +#ifdef MSM_PLATFORM + v_U32_t busBandwidthHighThreshold; + v_U32_t busBandwidthMediumThreshold; + v_U32_t busBandwidthLowThreshold; + v_U32_t busBandwidthComputeInterval; + v_U32_t tcpDelackThresholdHigh; + v_U32_t tcpDelackThresholdLow; + uint32_t tcp_tx_high_tput_thres; +#endif /* MSM_PLATFORM */ + + /* FW debug log parameters */ + v_U32_t enableFwLogType; + v_U32_t enableFwLogLevel; + v_U8_t enableFwModuleLogLevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH]; + + /* RTS profile parameter */ + uint32_t rts_profile; + +#ifdef WLAN_FEATURE_11W + v_U32_t pmfSaQueryMaxRetries; + v_U32_t pmfSaQueryRetryInterval; +#endif + + v_U8_t gMaxConcurrentActiveSessions; + + v_U8_t ignoreCAC; + v_BOOL_t IsSapDfsChSifsBurstEnabled; + +#ifdef FEATURE_GREEN_AP + v_BOOL_t enableGreenAP; +#endif + + bool crash_inject_enabled; + v_S31_t dfsRadarPriMultiplier; + v_U8_t reorderOffloadSupport; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + v_BOOL_t isRoamOffloadEnabled; +#endif + +#ifdef IPA_UC_OFFLOAD + v_U8_t IpaUcOffloadEnabled; + v_U32_t IpaUcTxBufCount; + v_U32_t IpaUcTxBufSize; + v_U32_t IpaUcRxIndRingCount; + v_U32_t IpaUcTxPartitionBase; +#endif /* IPA_UC_OFFLOAD */ +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + /* WLAN Logging */ + v_U32_t wlanLoggingEnable; + v_U32_t wlanLoggingFEToConsole; + v_U32_t wlanLoggingNumBuf; +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ + + v_BOOL_t enableSifsBurst; + +#ifdef WLAN_FEATURE_LPSS + v_BOOL_t enablelpasssupport; +#endif +#ifdef WLAN_FEATURE_NAN + bool enable_nan_support; +#endif + v_BOOL_t enableSelfRecovery; +#ifdef FEATURE_WLAN_FORCE_SAP_SCC + v_U8_t SapSccChanAvoidance; +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + + v_BOOL_t enableSapSuspend; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + v_U8_t extWowGotoSuspend; + v_U8_t extWowApp1WakeupPinNumber; + v_U8_t extWowApp2WakeupPinNumber; + v_U32_t extWowApp2KAInitPingInterval; + v_U32_t extWowApp2KAMinPingInterval; + v_U32_t extWowApp2KAMaxPingInterval; + v_U32_t extWowApp2KAIncPingInterval; + v_U16_t extWowApp2TcpSrcPort; + v_U16_t extWowApp2TcpDstPort; + v_U32_t extWowApp2TcpTxTimeout; + v_U32_t extWowApp2TcpRxTimeout; +#endif + v_BOOL_t gEnableDeauthToDisassocMap; + +#ifdef DHCP_SERVER_OFFLOAD + v_BOOL_t enableDHCPServerOffload; + v_U32_t dhcpMaxNumClients; + uint32_t dhcp_client_start_ip; + v_U8_t dhcpServerIP[IPADDR_STRING_LENGTH]; +#endif /* DHCP_SERVER_OFFLOAD */ + + bool enable_mac_spoofing; +#ifdef IPA_UC_STA_OFFLOAD + bool ipa_uc_sta_offload; +#endif + uint8_t conc_custom_rule1; + uint8_t conc_custom_rule2; + uint8_t is_sta_connection_in_5gz_enabled; + +#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 */ + +#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]; + uint32_t connect_fail_count; + uint32_t connect_fail_duration; + uint32_t connect_block_duration; +#endif /* SAP_AUTH_OFFLOAD */ + uint8_t dot11p_mode; + bool is_ramdump_enabled; + uint16_t p2p_listen_defer_interval; + uint8_t sap_dot11mc; + uint32_t sta_miracast_mcc_rest_time_val; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + bool sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + uint8_t sap_p2p_11ac_override; + uint8_t prefer_non_dfs_on_radar; + uint8_t inform_bss_rssi_raw; +#ifdef WLAN_FEATURE_TSF + uint32_t tsf_gpio_pin; +#endif + uint8_t multicast_host_fw_msgs; + uint32_t fine_time_meas_cap; +#ifdef FEATURE_SECURE_FIRMWARE + bool enable_fw_hash_check; +#endif + v_BOOL_t sendDeauthBeforeCon; + v_BOOL_t ignorePeerErpInfo; + uint16_t pkt_err_disconn_th; + bool tx_chain_mask_cck; + uint8_t tx_chain_mask_1ss; + uint16_t self_gen_frm_pwr; + +#ifdef FEATURE_WLAN_EXTSCAN + uint32_t extscan_passive_max_chn_time; + uint32_t extscan_passive_min_chn_time; + uint32_t extscan_active_max_chn_time; + uint32_t extscan_active_min_chn_time; +#endif + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD + bool udp_resp_offload_support; + uint32_t dest_port; + char payload_filter[MAX_LEN_UDP_RESP_OFFLOAD]; + char response_payload[MAX_LEN_UDP_RESP_OFFLOAD]; +#endif + uint16_t max_mgmt_tx_fail_count; + int8_t first_scan_bucket_threshold; + uint8_t ht_mpdu_density; +} hdd_config_t; + +#ifdef WLAN_FEATURE_MBSSID +typedef struct mbssid_sap_dyn_ini_config { + /* ACS Parameters */ + v_U8_t acsScanBandPreference; + v_U16_t acsBandSwitchThreshold; +} mbssid_sap_dyn_ini_config_t; +#endif + +#define VAR_OFFSET( _Struct, _Var ) (offsetof(_Struct, _Var)) +#define VAR_SIZE( _Struct, _Var ) (sizeof(((_Struct *)0)->_Var)) + +#define VAR_FLAGS_NONE ( 0 ) +#define VAR_FLAGS_REQUIRED ( 1 << 0 ) // bit 0 is Required or Optional +#define VAR_FLAGS_OPTIONAL ( 0 << 0 ) + +#define VAR_FLAGS_RANGE_CHECK ( 1 << 1 ) // bit 1 tells if range checking is required. + // If less than MIN, assume MIN. + // If greater than MAX, assume MAX. + +#define VAR_FLAGS_RANGE_CHECK_ASSUME_MINMAX ( VAR_FLAGS_RANGE_CHECK ) + +/* + * bit 2 is range checking that assumes the DEFAULT value + * If less than MIN, assume DEFAULT, + * If greater than MAX, assume DEFAULT. + */ +#define VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT ( 1 << 2 ) + +/* + * Bit 3 indicates that the config item can be modified dynamically + * on a running system + */ +#define VAR_FLAGS_DYNAMIC_CFG ( 1 << 3 ) + +typedef enum +{ + WLAN_PARAM_Integer, + WLAN_PARAM_SignedInteger, + WLAN_PARAM_HexInteger, + WLAN_PARAM_String, + WLAN_PARAM_MacAddr, +}WLAN_PARAMETER_TYPE; + +#define REG_VARIABLE( _Name, _Type, _Struct, _VarName, \ + _Flags, _Default, _Min, _Max ) \ +{ \ + ( _Name ), \ + ( _Type ), \ + ( _Flags ), \ + VAR_OFFSET( _Struct, _VarName ), \ + VAR_SIZE( _Struct, _VarName ), \ + ( _Default ), \ + ( _Min ), \ + ( _Max ), \ + NULL, \ + 0 \ +} + +#define REG_DYNAMIC_VARIABLE( _Name, _Type, _Struct, _VarName, \ + _Flags, _Default, _Min, _Max, \ + _CBFunc, _CBParam ) \ +{ \ + ( _Name ), \ + ( _Type ), \ + ( VAR_FLAGS_DYNAMIC_CFG | ( _Flags ) ), \ + VAR_OFFSET( _Struct, _VarName ), \ + VAR_SIZE( _Struct, _VarName ), \ + ( _Default ), \ + ( _Min ), \ + ( _Max ), \ + ( _CBFunc ), \ + ( _CBParam ) \ +} + +#define REG_VARIABLE_STRING( _Name, _Type, _Struct, _VarName, \ + _Flags, _Default ) \ +{ \ + ( _Name ), \ + ( _Type ), \ + ( _Flags ), \ + VAR_OFFSET( _Struct, _VarName ), \ + VAR_SIZE( _Struct, _VarName ), \ + (unsigned long)( _Default ), \ + 0, \ + 0, \ + NULL, \ + 0 \ +} + +typedef struct tREG_TABLE_ENTRY { + + char* RegName; // variable name in the qcom_cfg.ini file + WLAN_PARAMETER_TYPE RegType; // variable type in the hdd_config_t structure + unsigned long Flags; // Specify optional parms and if RangeCheck is performed + unsigned short VarOffset; // offset to field from the base address of the structure + unsigned short VarSize; // size (in bytes) of the field + unsigned long VarDefault; // default value to use + unsigned long VarMin; // minimum value, for range checking + unsigned long VarMax; // maximum value, for range checking + // Dynamic modification notifier + void (*pfnDynamicNotify)(hdd_context_t *pHddCtx, unsigned long NotifyId); + unsigned long NotifyId; // Dynamic modification identifier +} REG_TABLE_ENTRY; + +static __inline unsigned long utilMin( unsigned long a, unsigned long b ) +{ + return( ( a < b ) ? a : b ); +} + +/*--------------------------------------------------------------------------- + Function declarations and documentation + -------------------------------------------------------------------------*/ +VOS_STATUS hdd_parse_config_ini(hdd_context_t *pHddCtx); +VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx); +VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx); +v_BOOL_t hdd_update_config_dat ( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_cfg_get_global_config(hdd_context_t *pHddCtx, char *pBuf, + int buflen); +#ifdef WLAN_FEATURE_MBSSID +VOS_STATUS hdd_cfg_get_sap_dyn_config(hdd_adapter_t *pAdapter, char *pBuf, + int buflen); +#endif +eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode( eHddDot11Mode dot11Mode ); +VOS_STATUS hdd_execute_global_config_command(hdd_context_t *pHddCtx, + char *command); +#ifdef WLAN_FEATURE_MBSSID +VOS_STATUS hdd_execute_sap_dyn_config_command(hdd_adapter_t *pAdapter, + char *command); +#endif +tANI_BOOLEAN hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx); +VOS_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, v_U32_t val); + +void hdd_update_tgt_cfg(void *context, void *param); +bool hdd_dfs_indicate_radar(void *context, void *param); + +VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, + tANI_U8 intArrayMaxLen); +VOS_STATUS hdd_hex_string_to_u8_array(char *str, uint8_t *array, uint8_t *len, + uint8_t array_max_len); + +VOS_STATUS hdd_hex_string_to_u16_array(char *str, + uint16_t *int_array, uint8_t *len, uint8_t int_array_max_len); + + +#ifdef MDNS_OFFLOAD +VOS_STATUS 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 + +#ifdef WLAN_FEATURE_MBSSID +v_VOID_t hdd_mbssid_apply_def_cfg_ini(hdd_adapter_t *pAdapter); +#endif + +void print_hdd_cfg(hdd_context_t *pHddCtx); +VOS_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h new file mode 100644 index 000000000000..4b78b372f643 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -0,0 +1,1741 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( HDD_CFG80211_H__ ) +#define HDD_CFG80211_H__ + + +/**=========================================================================== + + \file wlan_hdd_cfg80211.h + + \brief cfg80211 functions declarations + + ==========================================================================*/ + +/* $HEADER$ */ + + +//value for initial part of frames and number of bytes to be compared +#define GAS_INITIAL_REQ "\x04\x0a" +#define GAS_INITIAL_REQ_SIZE 2 + +#define GAS_INITIAL_RSP "\x04\x0b" +#define GAS_INITIAL_RSP_SIZE 2 + +#define GAS_COMEBACK_REQ "\x04\x0c" +#define GAS_COMEBACK_REQ_SIZE 2 + +#define GAS_COMEBACK_RSP "\x04\x0d" +#define GAS_COMEBACK_RSP_SIZE 2 + +#define P2P_PUBLIC_ACTION_FRAME "\x04\x09\x50\x6f\x9a\x09" +#define P2P_PUBLIC_ACTION_FRAME_SIZE 6 + +#define P2P_ACTION_FRAME "\x7f\x50\x6f\x9a\x09" +#define P2P_ACTION_FRAME_SIZE 5 + +#define SA_QUERY_FRAME_REQ "\x08\x00" +#define SA_QUERY_FRAME_REQ_SIZE 2 + +#define SA_QUERY_FRAME_RSP "\x08\x01" +#define SA_QUERY_FRAME_RSP_SIZE 2 + +#define HDD_P2P_WILDCARD_SSID "DIRECT-" //TODO Put it in proper place; +#define HDD_P2P_WILDCARD_SSID_LEN 7 + +#define WNM_BSS_ACTION_FRAME "\x0a\x07" +#define WNM_BSS_ACTION_FRAME_SIZE 2 + +#define WNM_NOTIFICATION_FRAME "\x0a\x1a" +#define WNM_NOTIFICATION_FRAME_SIZE 2 + +#define WPA_OUI_TYPE "\x00\x50\xf2\x01" +#define BLACKLIST_OUI_TYPE "\x00\x50\x00\x00" +#define WHITELIST_OUI_TYPE "\x00\x50\x00\x01" +#define WPA_OUI_TYPE_SIZE 4 +#define WMM_OUI_TYPE "\x00\x50\xf2\x02\x01" +#define WMM_OUI_TYPE_SIZE 5 + +#define WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126 +#define WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 +#define BASIC_RATE_MASK 0x80 +#define RATE_MASK 0x7f + +#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS +/* GPS application requirement */ +#define QCOM_VENDOR_IE_ID 221 +#define QCOM_OUI1 0x00 +#define QCOM_OUI2 0xA0 +#define QCOM_OUI3 0xC6 +#define QCOM_VENDOR_IE_AGE_TYPE 0x100 +#define QCOM_VENDOR_IE_AGE_LEN (sizeof(qcom_ie_age) - 2) + +#ifdef FEATURE_WLAN_TDLS +#define WLAN_IS_TDLS_SETUP_ACTION(action) \ + ((SIR_MAC_TDLS_SETUP_REQ <= action) && (SIR_MAC_TDLS_SETUP_CNF >= action)) +#if !defined (TDLS_MGMT_VERSION2) +#define TDLS_MGMT_VERSION2 0 +#endif +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) \ + || defined(BACKPORTED_CHANNEL_SWITCH_PRESENT) +#define CHANNEL_SWITCH_SUPPORTED +#endif + + +#define MAX_CHANNEL (MAX_2_4GHZ_CHANNEL + NUM_5GHZ_CHANNELS) + +typedef struct { + u8 element_id; + u8 len; + u8 oui_1; + u8 oui_2; + u8 oui_3; + u32 type; + u32 age; + u32 tsf_delta; +}__attribute__((packed)) qcom_ie_age ; +#endif + +/* Vendor id to be used in vendor specific command and events + * to user space. + * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID, + * vendor subcmd definitions prefixed with QCA_NL80211_VENDOR_SUBCMD, and + * qca_wlan_vendor_attr is open source file src/common/qca-vendor.h in + * git://w1.fi/srv/git/hostap.git; the values here are just a copy of that + */ + +#define QCA_NL80211_VENDOR_ID 0x001374 +#define MAX_REQUEST_ID 0xFFFFFFFF + +enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, + QCA_NL80211_VENDOR_SUBCMD_TEST = 1, + /* subcmds 2..9 not yet allocated */ + QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10, + QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11, + QCA_NL80211_VENDOR_SUBCMD_NAN = 12, + QCA_NL80211_VENDOR_SUBCMD_STATS_EXT = 13, + /* subcommands for link layer statistics start here */ + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET = 14, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET = 15, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR = 16, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS = 17, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS = 18, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS = 19, + /* subcommands for extscan start here */ + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START = 20, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP = 21, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS = 22, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES = 23, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS = 24, + /* Used when report_threshold is reached in scan cache. */ + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE = 25, + /* Used to report scan results when each probe rsp. is received, + * if report_events enabled in wifi_scan_cmd_params. + */ + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT = 26, + /* Indicates progress of scanning state-machine. */ + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT = 27, + /* Indicates BSSID Hotlist. */ + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND = 28, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST = 29, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST = 30, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE = 31, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE = 32, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE = 33, + /* EXT TDLS */ + QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE = 34, + QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE = 35, + QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS = 36, + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE = 37, + /* Get supported features */ + QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES = 38, + + /* Set scanning_mac_oui */ + QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI = 39, + /* Set nodfs_flag */ + QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG = 40, + + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST = 41, + + /* Get Concurrency Matrix */ + QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX = 42, + + /* Get the security keys for key management offload */ + QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY = 50, + + /* Send the roaming and authentication info after roaming */ + QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH = 51, + + QCA_NL80211_VENDOR_SUBCMD_APFIND = 52, + + /* Deprecated */ + QCA_NL80211_VENDOR_SUBCMD_OCB_SET_SCHED = 53, + + QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54, + + /* Get the supported features by the driver */ + QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES = 55, + + /* Off loaded DFS events */ + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED = 56, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED = 57, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60, + + /* Get Wifi Specific Info */ + QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61, + /* Start Wifi Logger */ + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START = 62, + /* Start Wifi Memory Dump */ + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63, + QCA_NL80211_VENDOR_SUBCMD_ROAM = 64, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST = 65, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST = 66, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND = 67, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST = 68, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST = 69, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST = 70, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST = 71, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND = 72, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND = 73, + + /* Wi-Fi Configuration subcommands */ + QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, + QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75, + + QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET = 76, + QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA = 77, + QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES = 78, + + QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS = 79, + QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80, + + + /* OCB commands */ + QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92, + QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93, + QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT = 94, + QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT = 95, + QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER = 96, + QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS = 97, + QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS = 98, + QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL = 99, + QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT = 100, + + /* subcommand to get link properties */ + QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101, + QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105, +}; + +enum qca_nl80211_vendor_subcmds_index { +#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC) + QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX = 0, +#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */ + +#ifdef WLAN_FEATURE_NAN + QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX, +#endif /* WLAN_FEATURE_NAN */ + +#ifdef WLAN_FEATURE_STATS_EXT + QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX, +#endif /* WLAN_FEATURE_STATS_EXT */ + +#ifdef FEATURE_WLAN_EXTSCAN + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX, +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX, + QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX, +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + /* EXT TDLS */ + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX, + /* ACS OBSS Coex*/ + QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX, +#endif + /* DFS */ + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX, + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX, +#ifdef FEATURE_WLAN_EXTSCAN + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX, +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef FEATURE_WLAN_EXTSCAN + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX, +#endif + /* OCB events */ + QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX, +#ifdef WLAN_FEATURE_MEMDUMP + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX, +#endif /* WLAN_FEATURE_MEMDUMP */ + QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX, +}; + +/* EXT TDLS */ +enum qca_wlan_vendor_attr_tdls_enable { + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR, + /* signed 32-bit value, but lets keep as unsigned for now */ + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_tdls_disable { + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_tdls_get_status { + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR, + /* signed 32-bit value, but lets keep as unsigned for now */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_tdls_state { + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR, + /* signed 32-bit value, but lets keep as unsigned for now */ + QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_AFTER_LAST - 1, +}; + +/* enum's to provide TDLS capabilites */ +enum qca_wlan_vendor_attr_get_tdls_capabilities { + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS = 1, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr { + QCA_WLAN_VENDOR_ATTR_INVALID = 0, + /* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */ + QCA_WLAN_VENDOR_ATTR_DFS = 1, + /* used by QCA_NL80211_VENDOR_SUBCMD_NAN */ + QCA_WLAN_VENDOR_ATTR_NAN = 2, + /* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */ + QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3, + QCA_WLAN_VENDOR_ATTR_IFINDEX = 4, + + /* used by QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES */ + QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6, + + /* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */ + QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7, + + /* Unsigned 32-bit value from enum qca_set_band */ + QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MAX = + QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1 +}; + +#ifdef FEATURE_WLAN_EXTSCAN +enum qca_wlan_vendor_attr_extscan_config_params +{ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0, + + /* Unsigned 32-bit value; Middleware provides it to the driver. Middle ware + * either gets it from caller, e.g., framework, or generates one if + * framework doesn't provide it. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, + + /* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS sub command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS, + + /* NL attributes for input params used by + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START sub command. + */ + + /* Unsigned 32-bit value; channel frequency */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL, + /* Unsigned 32-bit value; dwell time in ms. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME, + /* Unsigned 8-bit value; 0: active; 1: passive; N/A for DFS */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE, + /* Unsigned 8-bit value; channel class */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS, + + /* Unsigned 8-bit value; bucket index, 0 based */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX, + /* Unsigned 8-bit value; band. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND, + /* Unsigned 32-bit value; desired period, in ms. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD, + /* Unsigned 8-bit value; report events semantics. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS, + /* Unsigned 32-bit value. + * Followed by a nested array of EXTSCAN_CHANNEL_SPEC_* attributes. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS, + + /* Array of QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC, + + /* Unsigned 32-bit value; base timer period in ms. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD, + /* Unsigned 32-bit value; number of APs to store in each scan in the + * BSSID/RSSI history buffer (keep the highest RSSI APs). + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN, + /* Unsigned 8-bit value; in %, when scan buffer is this much full, wake up + * APPS. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT, + /* Unsigned 8-bit value; number of scan bucket specs; followed by a nested + * array of_EXTSCAN_BUCKET_SPEC_* attributes and values. The size of the + * array is determined by NUM_BUCKETS. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS, + + /* Array of QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC, + + /* Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH, + /* Unsigned 32-bit value; maximum number of results to be returned. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX, + + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL, + + /* Number of hotlist APs as unsigned 32-bit value, followed by a nested + * array of AP_THRESHOLD_PARAM attributes and values. The size of the + * array is determined by NUM_AP. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP, + + /* Array of QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM, + + /* Unsigned 32bit value; number of samples for averaging RSSI. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE, + /* Unsigned 32bit value; number of samples to confirm AP loss. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE, + /* Unsigned 32bit value; number of APs breaching threshold. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING, + /* Unsigned 32bit value; number of APs. Followed by an array of + * AP_THRESHOLD_PARAM attributes. Size of the array is NUM_AP. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP, + /* Unsigned 32bit value; number of samples to confirm AP loss. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE, + + /* Unsigned 32-bit value. If max_period is non zero or different than + * period, then this bucket is an exponential backoff bucket. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD, + /* Unsigned 32-bit value. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT, + /* Unsigned 32-bit value. For exponential back off bucket, number of scans + * performed at a given period and until the exponent is applied. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT, + /* Unsigned 8-bit value; in number of scans, wake up AP after these + * many scans. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS, + + /* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST sub command. + */ + /* Unsigned 32bit value; number of samples to confirm SSID loss. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE, + /* Number of hotlist SSIDs as unsigned 32-bit value, followed by a nested + * array of SSID_THRESHOLD_PARAM_* attributes and values. The size of the + * array is determined by NUM_SSID. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID, + /* Array of QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM, + + /* An array of 33 x Unsigned 8-bit value; NULL terminated SSID */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID, + /* Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH, + + /* Unsigned 32-bit value; a bitmask w/additional extscan config flag. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX = + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_extscan_results +{ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_INVALID = 0, + + /* Unsigned 32-bit value; must match the request Id supplied by Wi-Fi HAL + * in the corresponding subcmd NL msg + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + + /* Unsigned 32-bit value; used to indicate the status response from + * firmware/driver for the vendor sub-command. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, + + /* EXTSCAN Valid Channels attributes */ + /* Unsigned 32bit value; followed by a nested array of CHANNELS. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS, + /* An array of NUM_CHANNELS x Unsigned 32bit value integers representing + * channel numbers + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS, + + /* EXTSCAN Capabilities attributes */ + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE, + /* Signed 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES, + + /* EXTSCAN Attributes used with + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE sub-command. + */ + + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + + + /* EXTSCAN attributes used with + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT sub-command. + */ + + /* An array of NUM_RESULTS_AVAILABLE x + * QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_* + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST, + + /* Unsigned 64-bit value; age of sample at the time of retrieval */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, + /* 33 x unsigned 8-bit value; NULL terminated SSID */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, + /* Unsigned 32-bit value; channel frequency in MHz */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, + /* Unsigned 16-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD, + /* Unsigned 16-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY, + /* Unsigned 32-bit value; size of the IE DATA blob */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH, + /* An array of IE_LENGTH x Unsigned 8-bit value; blob of all the + * information elements found in the beacon; this data should be a + * packed list of wifi_information_element objects, one after the other. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA, + /* Unsigned 8-bit value; set by driver to indicate more scan results are + * available. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE + * to indicate number of wifi scan results/bssids retrieved by the scan. + * Also, use QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST to indicate the list + * of wifi scan results returned for each cached result block. + */ + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT sub-command. + */ + /* Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_STATUS, + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND sub-command. + */ + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE + * to indicate number of results. + */ + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE sub-command. + */ + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL, + /* Unsigned 32-bit value. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI, + /* A nested array of signed 32-bit RSSI values. Size of the array is + * determined by (NUM_RSSI of SIGNIFICANT_CHANGE_RESULT_NUM_RSSI. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST, + + /* EXTSCAN attributes used with + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS sub-command. + */ + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE + * to indicate number of gscan cached results returned. + * Also, use QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST to indicate + * the list of gscan cached results. + */ + + /* An array of NUM_RESULTS_AVAILABLE x + * QCA_NL80211_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_* + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST, + /* Unsigned 32-bit value; a unique identifier for the scan unit. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID, + /* Unsigned 32-bit value; a bitmask w/additional information about scan. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS, + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE + * to indicate number of wifi scan results/bssids retrieved by the scan. + * Also, use QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST to indicate the list + * of wifi scan results returned for each cached result block. + */ + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND sub-command. + */ + /* Use QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE for number + * of results. + * Use QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST to indicate the nested + * list of wifi scan results returned for each wifi_passpoint_match_result block. + * Array size: QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE. + */ + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND sub-command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES, + /* A nested array of + * QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_* + * attributes. Array size = + * *_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST, + + /* Unsigned 32-bit value; network block id for the matched network */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID, + /* Use QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST to indicate the nested + * list of wifi scan results returned for each wifi_passpoint_match_result block. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN, + /* An array size of PASSPOINT_MATCH_ANQP_LEN of unsigned 8-bit values; + * ANQP data in the information_element format. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP, + + /* Unsigned 32bit value; a EXTSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS, + /* Unsigned 32bit value; a EXTSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS, + /* Unsigned 32bit value; a EXTSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID, + /* Unsigned 32bit value; a EXTSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID, + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND sub-command & + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST sub-command + */ + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE + * to indicate number of results. + */ + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX = + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_AFTER_LAST - 1, +}; + +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +enum qca_wlan_vendor_attr_ll_stats_set +{ + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD = 1, + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST - 1 +}; + +enum qca_wlan_vendor_attr_ll_stats_get +{ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID = 0, + /* Unsigned 32bit value provided by the caller issuing the GET stats + * command. When reporting the stats results, the driver uses the same + * value to indicate which GET request the results correspond to. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID, + /* Unsigned 34bit value - bit mask to identify what + * statistics are requested for retrieval. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST - 1 +}; + +enum qca_wlan_vendor_attr_ll_stats_clr +{ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_ll_stats_results_type - ll stats result type + * + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_INVALID: Initial invalid value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO: Link layer stats type radio + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_IFACE: Link layer stats type interface + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_PEER: Link layer stats type peer + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_AFTER_LAST: Last value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_MAX: Max value + */ +enum qca_wlan_vendor_attr_ll_stats_results_type { + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO = 1, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_IFACE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_PEER, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_AFTER_LAST - 1 +}; + +enum qca_wlan_vendor_attr_ll_stats_results +{ + QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID = 0, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID = 1, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA, + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK, + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_* are + * nested within the interface stats. + */ + + /* Interface mode, e.g., STA, SOFTAP, IBSS, etc. + * Type = enum wifi_interface_mode */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE, + /* Interface MAC address. An array of 6 Unsigned int8 */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR, + /* Type = enum wifi_connection_state, + * e.g., DISCONNECTED, AUTHENTICATING, etc. + * valid for STA, CLI only. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE, + /* Type = enum wifi_roam_state. Roaming state, + * e.g., IDLE or ACTIVE (is that valid for STA only?) + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING, + /* Unsigned 32bit value. WIFI_CAPABILITY_XXX */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES, + /* NULL terminated SSID. An array of 33 Unsigned 8bit values */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID, + /* BSSID. An array of 6 Unsigned 8bit values */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID, + /* Country string advertised by AP. An array of 3 Unsigned 8bit values */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR, + /* Country string for this association. An array of 3 Unsigned 8bit values*/ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* could + * be nested within the interface stats. + */ + + /* Type = enum wifi_traffic_ac, e.g., V0, VI, BE and BK */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES, + /* Unsigned 32bit value. Number of peers */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* are + * nested within the interface stats. + */ + + /* Type = enum wifi_peer_type. Peer type, e.g., STA, AP, P2P GO etc. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE, + /* MAC addr corresponding to respective peer. + * An array of 6 Unsigned 8bit values. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS, + /* Unsigned int 32bit value representing capabilities + * corresponding to respective peer. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES, + /* Unsigned 32bit value. Number of rates */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES, + + /* Attributes nested within the rate stats.*/ + /* Unsigned 8bit value */ + /* Unsigned int 8bit value; 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE, + /* Unsigned int 8bit value; 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS, + /* Unsigned int 8bit value; 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW, + /* Unsigned int 8bit value; OFDM/CCK rate code would be as per IEEE Std + * in the units of 0.5mbps HT/VHT it would be mcs index */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX, + + /* Unsigned 32bit value. Bit rate in units of 100Kbps */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_* could be + * nested within the peer info stats. + */ + + /* Unsigned int 32bit value. Number of successfully transmitted data pkts, + * i.e., with ACK received *corresponding to the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU, + /* Unsigned int 32bit value. Number of received data pkts + * corresponding to the respective rate. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU, + /* Unsigned int 32bit value. Number of data pkts losses, i.e., + * no ACK received corresponding to *the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST, + /* Unsigned int 32bit value. Total number of data pkt retries for + * the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES, + /* Unsigned int 32bit value. Total number of short data pkt retries for + the respective rate. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT, + /* Unsigned int 32bit value. Total number of long data pkt retries for + * the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID, + /* Unsigned 32bit value. Total number of msecs the radio is awake + * accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME, + /* Unsigned 32bit value. Total number of msecs the radio is + * transmitting accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME, + /* Unsigned 32bit value. Total number of msecs the radio is + * in active receive accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME, + /* Unsigned 32bit value. Total number of msecs the radio is + * awake due to all scan accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN, + /* Unsigned 32bit value. Total number of msecs the radio is + * awake due to NAN accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD, + /* Unsigned 32bit value. Total number of msecs the radio is + * awake due to GSCAN accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN, + /* Unsigned 32bit value. Total number of msecs the radio is + * awake due to roam scan accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN, + /* Unsigned 32bit value. Total number of msecs the radio is + * awake due to PNO scan accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN, + /* Unsigned 32bit value. Total number of msecs the radio is + * awake due to HS2.0 scans and GAS exchange accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20, + /* Unsigned 32bit value. Number of channels. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_ + * could be nested within the channel stats. + */ + + /* Type = enum wifi_channel_width. Channel width, e.g., 20, 40, 80, etc.*/ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH, + /* Unsigned 32bit value. Primary 20MHz channel. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ, + /* Unsigned 32bit value. Center frequency (MHz) first segment. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0, + /* Unsigned 32bit value. Center frequency (MHz) second segment. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ could be + * nested within the radio stats. + */ + + /* Unsigned int 32bit value representing total number of msecs the radio + * s awake on that *channel accruing over time, corresponding to + * the respective channel. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME, + /* Unsigned int 32bit value representing total number of msecs the + * CCA register is busy accruing *over time corresponding to the + * respective channel. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO, + + /* Unsigned 8bit value. Used by the driver; if set to 1, it indicates that + * more stats, e.g., peers or radio, are to follow in the next + * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_*_RESULTS event. + * Otherwise, it is set to 0. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA, + + /* Unsigned 64bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET, + + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED, + + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED, + + /* Unsigned 32bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME, + + /* Unsigned 32bit value to indicate ll stats result type */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST -1 +}; + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +enum qca_wlan_vendor_attr_get_supported_features { + QCA_WLAN_VENDOR_ATTR_FEATURE_SET_INVALID = 0, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_FEATURE_SET = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_FEATURE_SET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX = + QCA_WLAN_VENDOR_ATTR_FEATURE_SET_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_set_scanning_mac_oui { + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_INVALID = 0, + /* An array of 3 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX = + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_set_no_dfs_flag +{ + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_INVALID = 0, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX = + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_roam_auth - vendor event for roaming + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID: BSSID of the roamed AP + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE: Request IE + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE: Response IE + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED: Authorization Status + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR: Replay Counter + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK: KCK of the PTK + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK: KEK of the PTK + */ +enum qca_wlan_vendor_attr_roam_auth { + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1 +}; + +/* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX sub command. + */ +enum qca_wlan_vendor_attr_get_concurrency_matrix { + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_INVALID = 0, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX = 1, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE = 2, + /* An array of SET_SIZE x Unsigned 32bit values representing + * concurrency combinations. + */ + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET = 3, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX = + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_AFTER_LAST - 1, +}; + +enum qca_wlan_epno_type { + QCA_WLAN_EPNO, + QCA_WLAN_PNO +}; + +enum qca_wlan_vendor_attr_pno_config_params { + QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0, + /* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST sub command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM = 1, + /* Array of nested QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_* + * attributes. Array size = + * QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY = 2, + + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID = 3, + /* An array of 256 x Unsigned 8-bit value; NULL terminated UTF8 encoded + * realm, 0 if unspecified. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM = 4, + /* An array of 16 x Unsigned 32-bit value; roaming consortium ids + * to match, 0 if unspecified. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID = 5, + /* An array of 6 x Unsigned 8-bit value; mcc/mnc combination, 0s if + * unspecified. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN = 6, + + /* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST sub command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS = 7, + /* Array of nested + * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_* + * attributes. Array size = + * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS. + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST = 8, + /* An array of 33 x Unsigned 8-bit value; NULL terminated SSID */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID = 9, + /* Signed 8-bit value; threshold for considering this SSID as found, + * required granularity for this threshold is 4dBm to 8dBm + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD = 10, + /* Unsigned 8-bit value; WIFI_PNO_FLAG_XXX */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS = 11, + /* Unsigned 8-bit value; auth bit field for matching WPA IE */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT = 12, + + /* Unsigned 8-bit to indicate ePNO type; + * It takes values from qca_wlan_epno_type + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_TYPE = 13, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PNO_MAX = + QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_roaming_config_params { + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1, + QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2, + + /* Attributes for wifi_set_ssid_white_list */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5, + + /* Attributes for set_roam_params */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD = 7, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR = 8, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR = 9, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST = 10, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS = 11, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER = 12, + + /* Attribute for set_lazy_roam */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE = 13, + + /* Attribute for set_lazy_roam with preferences */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS = 14, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID = 15, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID = 16, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER = 17, + + /* Attribute for set_ blacklist bssid params */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX = + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1, +}; + +/* + * QCA_NL80211_VENDOR_SUBCMD_ROAM sub commands. + */ +enum qca_wlan_vendor_attr_roam_subcmd +{ + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST = 1, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS = 2, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM = 3, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS = 4, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PARAMS = 5, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID = 6, + + /* KEEP LAST */ + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST - 1, +}; + +/* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO sub command. + */ +enum qca_wlan_vendor_attr_get_wifi_info { + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION = 1, + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_get_logger_features - value for logger + * supported features + * @QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID - Invalid + * @QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED - Indicate the supported features + * @QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - To keep track of the last enum + * @QCA_WLAN_VENDOR_ATTR_LOGGER_MAX - max value possible for this type + * + * enum values are used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET sub command. + */ +enum qca_wlan_vendor_attr_get_logger_features { + QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED = 1, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LOGGER_MAX = + QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1, +}; + +/* NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES. + */ +enum qca_wlan_vendor_attr_link_properties { + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID = 0, + /* Unsigned 8bit value for specifying nof spatial streams */ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS = 1, + /* Unsigned 8bit value for the rate flags */ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS = 2, + /* Unsigned 32bit value for operating frequency */ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ = 3, + + /* KEEP LAST */ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAX = + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_features - vendor device/driver features + * @QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD: Device supports key + * management offload, a mechanism where the station's firmware + * does the exchange with the AP to establish the temporal keys + * after roaming, rather than having the supplicant do it. + */ +enum qca_wlan_vendor_features { + QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, + /* Additional features need to be added above this */ + NUM_QCA_WLAN_VENDOR_FEATURES +}; + +/* Feature defines */ +#define WIFI_FEATURE_INFRA 0x0001 /* Basic infrastructure mode */ +#define WIFI_FEATURE_INFRA_5G 0x0002 /* Support for 5 GHz Band */ +#define WIFI_FEATURE_HOTSPOT 0x0004 /* Support for GAS/ANQP */ +#define WIFI_FEATURE_P2P 0x0008 /* Wifi-Direct */ +#define WIFI_FEATURE_SOFT_AP 0x0010 /* Soft AP */ +#define WIFI_FEATURE_EXTSCAN 0x0020 /* Extended Scan APIs */ +#define WIFI_FEATURE_NAN 0x0040 /* Neighbor Awareness + Networking */ +#define WIFI_FEATURE_D2D_RTT 0x0080 /* Device-to-device RTT */ +#define WIFI_FEATURE_D2AP_RTT 0x0100 /* Device-to-AP RTT */ +#define WIFI_FEATURE_BATCH_SCAN 0x0200 /* Batched Scan (legacy) */ +#define WIFI_FEATURE_PNO 0x0400 /* Preferred network offload */ +#define WIFI_FEATURE_ADDITIONAL_STA 0x0800 /* Support for two STAs */ +#define WIFI_FEATURE_TDLS 0x1000 /* Tunnel directed link + setup */ +#define WIFI_FEATURE_TDLS_OFFCHANNEL 0x2000 /* Support for TDLS off + channel */ +#define WIFI_FEATURE_EPR 0x4000 /* Enhanced power reporting */ +#define WIFI_FEATURE_AP_STA 0x8000 /* Support for AP STA + Concurrency */ +#define WIFI_FEATURE_LINK_LAYER_STATS 0x10000 /* Link layer stats */ +#define WIFI_FEATURE_LOGGER 0x20000 /* WiFi Logger */ +#define WIFI_FEATURE_HAL_EPNO 0x40000 /* WiFi PNO enhanced */ +#define WIFI_FEATURE_RSSI_MONITOR 0x80000 /* RSSI Monitor */ + +/* Add more features here */ +#define WIFI_TDLS_SUPPORT BIT(0) +#define WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT BIT(1) +#define WIIF_TDLS_OFFCHANNEL_SUPPORT BIT(2) + +/** + * enum wifi_logger_supported_features - values for supported logger features + * @WIFI_LOGGER_MEMORY_DUMP_SUPPORTED - Memory dump of FW + * @WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED - Per packet statistics + * @WIFI_LOGGER_CONNECT_EVENT_SUPPORTED - Logging of Connectivity events + * @WIFI_LOGGER_POWER_EVENT_SUPPORTED - Power of driver + * @WIFI_LOGGER_WAKE_LOCK_SUPPORTED - Wakelock of driver + * @WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED - monitor FW health + */ +enum wifi_logger_supported_features { + WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), + WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), + WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), + WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), + WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), + WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), + WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), +}; + + +#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC) +#define HDD_MAX_AVOID_FREQ_RANGES 4 +typedef struct sHddAvoidFreqRange +{ + u32 startFreq; + u32 endFreq; +} tHddAvoidFreqRange; + +typedef struct sHddAvoidFreqList +{ + u32 avoidFreqRangeCount; + tHddAvoidFreqRange avoidFreqRange[HDD_MAX_AVOID_FREQ_RANGES]; +} tHddAvoidFreqList; +#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */ + +enum qca_wlan_vendor_attr_acs_offload { + QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, + QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED, + QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED, + QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH, + QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ACS_MAX = + QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST - 1 +}; + +enum qca_wlan_vendor_acs_hw_mode { + QCA_ACS_MODE_IEEE80211B, + QCA_ACS_MODE_IEEE80211G, + QCA_ACS_MODE_IEEE80211A, + QCA_ACS_MODE_IEEE80211AD, +}; + +/** + * enum qca_wlan_vendor_config: wifi config attr + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID: invalid config + * @QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM: dynamic dtim + * @QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR: stats avg. factor + * @QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME: guard time + * @QCA_WLAN_VENDOR_ATTR_CONFIG_LAST: last config + * @QCA_WLAN_VENDOR_ATTR_CONFIG_MAX: max config + */ +enum qca_wlan_vendor_config { + QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM, + QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, + QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_wifi_logger_start - Enum for wifi logger starting + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID: Invalid attribute + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID: Ring ID + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL: Verbose level + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS: Flag + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST: Last value + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX: Max value + */ +enum qca_wlan_vendor_attr_wifi_logger_start { + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID = 1, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL = 2, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS = 3, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST - 1, +}; + +/* + * enum qca_wlan_vendor_attr_wifi_logger_get_ring_data - Get ring data + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_INVALID: Invalid attribute + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID: Ring ID + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_AFTER_LAST: Last value + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX: Max value + */ +enum qca_wlan_vendor_attr_wifi_logger_get_ring_data { + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_AFTER_LAST - 1, +}; + +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS +/** + * enum wlan_offloaded_packets_control - control commands + * @WLAN_START_OFFLOADED_PACKETS: start offloaded packets + * @WLAN_STOP_OFFLOADED_PACKETS: stop offloaded packets + * + */ +enum wlan_offloaded_packets_control { + WLAN_START_OFFLOADED_PACKETS = 1, + WLAN_STOP_OFFLOADED_PACKETS = 2 +}; + +/** + * enum qca_wlan_vendor_attr_offloaded_packets - offloaded packets + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID: invalid + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL: control + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID: request id + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA: ip packet data + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR: src mac address + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR: destination mac address + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD: period in milli seconds + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX: max + */ +enum qca_wlan_vendor_attr_offloaded_packets { + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID, + + /* Packet in hex format */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX = + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST - 1, +}; +#endif + +/** + * enum qca_wlan_rssi_monitoring_control - rssi control commands + * @QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID: invalid + * @QCA_WLAN_RSSI_MONITORING_START: rssi monitoring start + * @QCA_WLAN_RSSI_MONITORING_STOP: rssi monitoring stop + */ +enum qca_wlan_rssi_monitoring_control { + QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID = 0, + QCA_WLAN_RSSI_MONITORING_START, + QCA_WLAN_RSSI_MONITORING_STOP, +}; + +/** + * enum qca_wlan_vendor_attr_rssi_monitoring - rssi monitoring + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID: Invalid + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL: control + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI: max rssi + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI: min rssi + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID: current bssid + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI: current rssi + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX: max + */ +enum qca_wlan_vendor_attr_rssi_monitoring { + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, + + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI, + + /* attributes to be used/received in callback */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX = + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1, +}; + +struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo + ); + +#ifdef FEATURE_WLAN_LFR +int wlan_hdd_cfg80211_pmksa_candidate_notify( + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + int index, bool preauth ); +#endif + +#ifdef FEATURE_WLAN_LFR_METRICS +VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo); + +VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status( + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status); + +VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo); +#endif + +#ifdef FEATURE_WLAN_WAPI +void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, + u8 key_index, const u8 *mac_addr, + const u8 *key , int key_Len); +#endif +struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size); + +int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request); + +int wlan_hdd_cfg80211_init(struct device *dev, + struct wiphy *wiphy, + hdd_config_t *pCfg + ); + +void wlan_hdd_update_wiphy(struct wiphy *wiphy, + hdd_config_t *pCfg); + +int wlan_hdd_cfg80211_register( struct wiphy *wiphy); +void wlan_hdd_cfg80211_register_frames(hdd_adapter_t* pAdapter); + +void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t* pAdapter); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) +void wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); +#else +int wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); +#endif + +extern v_VOID_t hdd_connSetConnectionState(hdd_adapter_t *pAdapter, + eConnectionState connState); +VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel); +#ifdef FEATURE_WLAN_TDLS +int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy, + struct net_device *dev, u8 *peer); +#endif +#ifdef WLAN_FEATURE_GTK_OFFLOAD +extern void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext, + tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp); +#endif +void* wlan_hdd_change_country_code_cb(void *pAdapter); +void hdd_select_cbmode(hdd_adapter_t *pAdapter, v_U8_t operationChannel, + uint16_t *ch_width); + +v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(const v_U8_t *pIes, + int length, + v_U8_t eid); + +#ifdef CFG80211_DEL_STA_V2 +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *param); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, const u8 *mac); +#else +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, u8 *mac); +#endif +#endif + +#if defined(QCA_WIFI_FTM) && defined(CONFIG_NL80211_TESTMODE) +void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len); +#endif + +void hdd_suspend_wlan(void (*callback)(void *callbackContext, boolean suspended), + void *callbackContext); +void hdd_resume_wlan(void); + +#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC) +int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, + tHddAvoidFreqList *pAvoidFreqList); +#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC*/ + +#ifdef FEATURE_WLAN_EXTSCAN +void wlan_hdd_cfg80211_extscan_callback(void *ctx, + const tANI_U16 evType, + void *pMsg); +#endif /* FEATURE_WLAN_EXTSCAN */ + +void hdd_rssi_threshold_breached(void *hddctx, + struct rssi_breach_event *data); + +struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_list( + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo); + +int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); +void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, + uint8_t *req_rsn_ie, uint32_t req_rsn_length, + uint8_t *rsp_rsn_ie, uint32_t rsp_rsn_length, + tCsrRoamInfo *roam_info_ptr); +#else +static inline int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, + uint8_t *bssid, uint8_t *req_rsn_ie, uint32_t req_rsn_length, + uint8_t *rsp_rsn_ie, uint32_t rsp_rsn_length, + tCsrRoamInfo *roam_info_ptr) +{ + return 0; +} +#endif +int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *pHddCtx, + hdd_adapter_t *pAdapter, + u32 no_dfs_flag); + +int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter); + +#if !(defined (SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) +static inline struct sk_buff * +backported_cfg80211_vendor_event_alloc(struct wiphy *wiphy, + struct wireless_dev *wdev, + int approxlen, + int event_idx, gfp_t gfp) +{ + return cfg80211_vendor_event_alloc(wiphy, approxlen, event_idx, gfp); +} +#define cfg80211_vendor_event_alloc backported_cfg80211_vendor_event_alloc +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_debugfs.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_debugfs.h new file mode 100644 index 000000000000..40415fd154e0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_debugfs.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WLAN_HDD_DEBUGFS_H +#define _WLAN_HDD_DEBUGFS_H + +#ifdef WLAN_OPEN_SOURCE +VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter); +void hdd_debugfs_exit(hdd_context_t *pHddCtx); +#else +inline VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter) +{ + return VOS_STATUS_SUCCESS; +} +inline void hdd_debugfs_exit(hdd_context_t *pHddCtx) +{ +} +#endif /* #ifdef WLAN_OPEN_SOURCE */ +#endif /* #ifndef _WLAN_HDD_DEBUGFS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dev_pwr.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dev_pwr.h new file mode 100644 index 000000000000..c17b1b0a6031 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dev_pwr.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_DEV_PWR_H +#define __WLAN_HDD_DEV_PWR_H + +#include +#include +#include +#include + + +/*---------------------------------------------------------------------------- + + @brief Registration function. + Register suspend, resume callback functions with platform driver. + + @param hdd_context_t pHddCtx + Global hdd context + + @return General status code + VOS_STATUS_SUCCESS Registration Success + VOS_STATUS_E_FAILURE Registration Fail + +----------------------------------------------------------------------------*/ +static inline VOS_STATUS hddRegisterPmOps(hdd_context_t *pHddCtx) +{ + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + @brief De-registration function. + Deregister the suspend, resume callback functions with platform driver + + @param hdd_context_t pHddCtx + Global hdd context + + @return General status code + VOS_STATUS_SUCCESS De-Registration Success + VOS_STATUS_E_FAILURE De-Registration Fail + +----------------------------------------------------------------------------*/ +static inline VOS_STATUS hddDeregisterPmOps(hdd_context_t *pHddCtx) +{ + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + @brief TM Level Change handler + Received Tm Level changed notification + + @param dev : Device context + changedTmLevel : Changed new TM level + + @return + +----------------------------------------------------------------------------*/ +static inline void hddDevTmLevelChangedHandler(struct device *dev, + int changedTmLevel) +{ + return; +} + +/*---------------------------------------------------------------------------- + + @brief Register function + Register Thermal Mitigation Level Changed handle callback function + + @param hdd_context_t pHddCtx + Global hdd context + + @return General status code + VOS_STATUS_SUCCESS Registration Success + VOS_STATUS_E_FAILURE Registration Fail + +----------------------------------------------------------------------------*/ +VOS_STATUS hddDevTmRegisterNotifyCallback(hdd_context_t *pHddCtx); + +/*---------------------------------------------------------------------------- + + @brief Un-Register function + Un-Register Thermal Mitigation Level Changed handle callback function + + @param hdd_context_t pHddCtx + Global hdd context + + @return General status code + VOS_STATUS_SUCCESS Un-Registration Success + VOS_STATUS_E_FAILURE Un-Registration Fail + +----------------------------------------------------------------------------*/ +VOS_STATUS hddDevTmUnregisterNotifyCallback(hdd_context_t *pHddCtx); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dp_utils.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dp_utils.h new file mode 100644 index 000000000000..34134abf40ba --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_dp_utils.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __WLAN_HDD_DP_UTILS_H ) +#define __WLAN_HDD_DP_UTILS_H + +/**============================================================================= + wlan_hdd_dp_utils.h + + \brief Utility functions for data path module + + Description... + + ==============================================================================**/ +/* $HEADER$ */ + +/**----------------------------------------------------------------------------- + Include files + ----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include + +/**----------------------------------------------------------------------------- + Preprocessor definitions and constants + ----------------------------------------------------------------------------*/ + +/**----------------------------------------------------------------------------- + Type declarations + ----------------------------------------------------------------------------*/ +typedef struct list_head hdd_list_node_t; + +typedef struct hdd_list_s +{ + hdd_list_node_t anchor; + v_SIZE_t count; + v_SIZE_t max_size; + spinlock_t lock; +} hdd_list_t; + +typedef struct +{ + hdd_list_node_t anchor; + struct sk_buff *skb; + int userPriority; +} skb_list_node_t; + +//FIXME Need a helper function to cleanup skbs in a queue. Required for cleanup/shutdown + +/**----------------------------------------------------------------------------- + Function declarations and documentation + ----------------------------------------------------------------------------*/ +VOS_INLINE_FN v_VOID_t hdd_list_init( hdd_list_t *pList, v_SIZE_t max_size) +{ + INIT_LIST_HEAD( &pList->anchor ); + pList->count = 0; + pList->max_size = max_size; + spin_lock_init(&pList->lock); +} + +VOS_INLINE_FN v_VOID_t hdd_list_destroy( hdd_list_t *pList ) +{ + if ( pList->count !=0 ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "%s: list length not equal to zero",__func__); + } +} + +VOS_INLINE_FN v_VOID_t hdd_list_size( hdd_list_t *pList, v_SIZE_t *pSize ) +{ + *pSize = pList->count; +} + +VOS_STATUS hdd_list_insert_front( hdd_list_t *pList, hdd_list_node_t *pNode ); + +VOS_STATUS hdd_list_insert_back( hdd_list_t *pList, hdd_list_node_t *pNode ); + +VOS_STATUS hdd_list_insert_back_size( hdd_list_t *pList, hdd_list_node_t *pNode, v_SIZE_t *pSize ); + +VOS_STATUS hdd_list_remove_front( hdd_list_t *pList, hdd_list_node_t **ppNode ); + +VOS_STATUS hdd_list_remove_back( hdd_list_t *pList, hdd_list_node_t **ppNode ); + +VOS_STATUS hdd_list_remove_node( hdd_list_t *pList, hdd_list_node_t *pNodeToRemove ); +VOS_STATUS hdd_list_peek_front( hdd_list_t *pList, hdd_list_node_t **ppNode ); +VOS_STATUS hdd_list_peek_next( hdd_list_t *pList, hdd_list_node_t *pNode, + hdd_list_node_t **ppNode ); +VOS_STATUS hdd_string_to_hex( char *pSrcMac, int length, char *pDescMac ); +struct hdd_context_s; +#ifdef QCA_FEATURE_RPS +void hdd_dp_util_send_rps_ind(struct hdd_context_s *hdd_ctx); +#else +static inline void hdd_dp_util_send_rps_ind(struct hdd_context_s *hdd_ctx) +{ + return; +} +#endif /* QCA_FEATURE_RPS */ +#endif //__WLAN_HDD_DP_UTILS_H diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ether.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ether.h new file mode 100644 index 000000000000..76c21020878b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ether.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WLAN_HDD_ETHER_H +#define _WLAN_HDD_ETHER_H +/*============================================================================ + @file wlan_hdd_ether.h + + This module describes Ethernet packet formats for processing by HDD. +============================================================================*/ +/* $Header$ */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define WLAN_SNAP_OUI_LEN 3 +#define WLAN_SNAP_DSAP 0xAAU +#define WLAN_SNAP_SSAP 0xAAU +#define WLAN_SNAP_CTRL 0x03 +#define WLAN_MIN_PROTO 0x0600 + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +struct wlan_snap_hdr { + unsigned char dsap; + unsigned char ssap; + unsigned char ctrl; + unsigned char oui[WLAN_SNAP_OUI_LEN]; +} __packed; + +struct wlan_8023 { + unsigned char h_dest[ETH_ALEN]; + unsigned char h_source[ETH_ALEN]; + __be16 h_len; + struct wlan_snap_hdr h_snap; + __be16 h_proto; +} __packed; + +struct wlan_8023_vlan { + unsigned char h_dest[ETH_ALEN]; + unsigned char h_source[ETH_ALEN]; + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + __be16 h_len; + struct wlan_snap_hdr h_snap; + __be16 h_proto; +} __packed; + +union generic_ethhdr { + struct ethhdr eth_II; + struct vlan_ethhdr eth_IIv; + struct wlan_8023 eth_8023; + struct wlan_8023_vlan eth_8023v; +}; + +#endif /* #ifndef _WLAN_HDD_ETHER_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ftm.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ftm.h new file mode 100644 index 000000000000..d470d24e13e9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ftm.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WLAN_HDD_FTM_H +#define WLAN_HDD_FTM_H +#include "vos_status.h" +#include "vos_mq.h" +#include "vos_api.h" +#include "msg.h" +#include "halTypes.h" +#include "vos_types.h" +#include + +#define WLAN_FTM_SUCCESS 0 +#define WLAN_FTM_FAILURE 1 + +typedef enum { + WLAN_FTM_INITIALIZED, + WLAN_FTM_STOPPED, + WLAN_FTM_STARTED, +} wlan_hdd_ftm_state; +typedef struct wlan_hdd_ftm_status_s +{ + v_U8_t ftm_state; + /**vos event */ + vos_event_t ftm_vos_event; + + /** completion variable for ftm command to complete*/ + struct completion ftm_comp_var; + v_BOOL_t IsCmdPending; +} wlan_hdd_ftm_status_t; + +int wlan_hdd_ftm_open(hdd_context_t *pHddCtx); +int wlan_hdd_ftm_close(hdd_context_t *pHddCtx); + +#if defined(QCA_WIFI_FTM) +VOS_STATUS wlan_hdd_ftm_testmode_cmd(void *data, int len); +int wlan_hdd_qcmbr_unified_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr); +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_host_offload.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_host_offload.h new file mode 100644 index 000000000000..5082fe3b5a0d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_host_offload.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_HOST_OFFLOAD_H__ +#define __WLAN_HDD_HOST_OFFLOAD_H__ + +/**=========================================================================== + + \file wlan_hdd_host_offload.h + + \brief Android WLAN HDD Host Offload API + +==========================================================================*/ + +/* Offload types. */ +#define WLAN_IPV4_ARP_REPLY_OFFLOAD 0 +#define WLAN_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 + +/* Enable or disable offload. */ +#define WLAN_OFFLOAD_DISABLE 0 +#define WLAN_OFFLOAD_ENABLE 0x1 +#define WLAN_OFFLOAD_BC_FILTER_ENABLE 0x2 +#define WLAN_OFFLOAD_ARP_AND_BC_FILTER_ENABLE (WLAN_OFFLOAD_ENABLE | WLAN_OFFLOAD_BC_FILTER_ENABLE) + +/* Offload request. */ +typedef struct +{ + v_U8_t offloadType; + v_U8_t enableOrDisable; + union + { + v_U8_t hostIpv4Addr [4]; + v_U8_t hostIpv6Addr [16]; + } params; + v_MACADDR_t bssId; +} tHostOffloadRequest, *tpHostOffloadRequest; + +#endif // __WLAN_HDD_HOST_OFFLOAD_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_hostapd.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_hostapd.h new file mode 100644 index 000000000000..31338bb602d3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_hostapd.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( WLAN_HDD_HOSTAPD_H ) +#define WLAN_HDD_HOSTAPD_H + +/**=========================================================================== + + \file WLAN_HDD_HOSTAPD_H.h + + \brief Linux HDD HOSTAPD include file + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include +#include + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ + +/* max length of command string in hostapd ioctl */ +#define HOSTAPD_IOCTL_COMMAND_STRLEN_MAX 8192 + +hdd_adapter_t* hdd_wlan_create_ap_dev( hdd_context_t *pHddCtx, tSirMacAddr macAddr, tANI_U8 *name); + +VOS_STATUS hdd_register_hostapd(hdd_adapter_t *pAdapter, tANI_U8 rtnl_held); + +VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, bool rtnl_held); + +eCsrAuthType +hdd_TranslateRSNToCsrAuthType( u_int8_t auth_suite[4]); + +eCsrEncryptionType +hdd_TranslateRSNToCsrEncryptionType(u_int8_t cipher_suite[4]); + +eCsrEncryptionType +hdd_TranslateRSNToCsrEncryptionType(u_int8_t cipher_suite[4]); + +eCsrAuthType +hdd_TranslateWPAToCsrAuthType(u_int8_t auth_suite[4]); + +eCsrEncryptionType +hdd_TranslateWPAToCsrEncryptionType(u_int8_t cipher_suite[4]); + +VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t*, struct tagCsrDelStaParams*); +void hdd_softap_sta_disassoc(hdd_adapter_t*, struct tagCsrDelStaParams*); +void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t*,v_BOOL_t); +int hdd_softap_unpackIE( tHalHandle halHandle, + eCsrEncryptionType *pEncryptType, + eCsrEncryptionType *mcEncryptType, + eCsrAuthType *pAuthType, + v_BOOL_t *pMFPCapable, + v_BOOL_t *pMFPRequired, + u_int16_t gen_ie_len, + u_int8_t *gen_ie ); + +VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback); +VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter ); +void hdd_set_ap_ops( struct net_device *pWlanHostapdDev ); +int hdd_hostapd_stop (struct net_device *dev); +void hdd_hostapd_channel_wakelock_init(hdd_context_t *pHddCtx); +void hdd_hostapd_channel_wakelock_deinit(hdd_context_t *pHddCtx); +#ifdef FEATURE_WLAN_FORCE_SAP_SCC +void hdd_restart_softap (hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter); +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ +#ifdef QCA_HT_2040_COEX +VOS_STATUS hdd_set_sap_ht2040_mode(hdd_adapter_t *pHostapdAdapter, + tANI_U8 channel_type); +#endif + +#ifdef SAP_AUTH_OFFLOAD +void hdd_set_sap_auth_offload(hdd_adapter_t *pHostapdAdapter, + bool enabled); + +int hdd_set_client_block_info(hdd_adapter_t *padapter); +#else +static inline int hdd_set_client_block_info(hdd_adapter_t *padapter) +{ + return 0; +} + +static inline void +hdd_set_sap_auth_offload(hdd_adapter_t *pHostapdAdapter, bool enabled) +{ +} +#endif /* SAP_AUTH_OFFLOAD */ +int hdd_softap_set_channel_change(struct net_device *dev, int target_channel); + +/** + * hdd_is_sta_connection_pending() - This function will check if sta connection + * is pending or not. + * @hdd_ctx: pointer to hdd context + * + * This function will return the status of flag is_sta_connection_pending + * + * Return: true or false + */ +static inline bool +hdd_is_sta_connection_pending(hdd_context_t *hdd_ctx) +{ + bool status; + spin_lock(&hdd_ctx->sta_update_info_lock); + status = hdd_ctx->is_sta_connection_pending; + spin_unlock(&hdd_ctx->sta_update_info_lock); + return status; +} + +/** + * hdd_change_sta_conn_pending_status() - This function will change the value + * of is_sta_connection_pending + * @hdd_ctx: pointer to hdd context + * @value: value to set + * + * This function will change the value of is_sta_connection_pending + * + * Return: none + */ +static inline void +hdd_change_sta_conn_pending_status(hdd_context_t *hdd_ctx, + bool value) +{ + spin_lock(&hdd_ctx->sta_update_info_lock); + hdd_ctx->is_sta_connection_pending = value; + spin_unlock(&hdd_ctx->sta_update_info_lock); +} + +/** + * hdd_is_sap_restart_required() - This function will check if sap restart + * is pending or not. + * @hdd_ctx: pointer to hdd context. + * + * This function will return the status of flag is_sap_restart_required. + * + * Return: true or false + */ +static inline bool +hdd_is_sap_restart_required(hdd_context_t *hdd_ctx) +{ + bool status; + spin_lock(&hdd_ctx->sap_update_info_lock); + status = hdd_ctx->is_sap_restart_required; + spin_unlock(&hdd_ctx->sap_update_info_lock); + return status; +} + +/** + * hdd_change_sap_restart_required_status() - This function will change the + * value of is_sap_restart_required + * @hdd_ctx: pointer to hdd context + * @value: value to set + * + * This function will change the value of is_sap_restart_required + * + * Return: none + */ +static inline void +hdd_change_sap_restart_required_status(hdd_context_t *hdd_ctx, + bool value) +{ + spin_lock(&hdd_ctx->sap_update_info_lock); + hdd_ctx->is_sap_restart_required = value; + spin_unlock(&hdd_ctx->sap_update_info_lock); +} + +#endif // end #if !defined( WLAN_HDD_HOSTAPD_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_includes.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_includes.h new file mode 100644 index 000000000000..239e7920b911 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_includes.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( HDD_INCLUDES_H__ ) +#define HDD_INCLUDES_H__ + +/**=========================================================================== + + \file wlan_hdd_includes.h + + \brief Internal includes for the Linux HDD + + ==========================================================================*/ + +/* $HEADER$ */ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ + +// throw all the includes in here f to get the .c files in the HDD to compile. + +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include + +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_dp_utils.h" +#include "wlan_hdd_mib.h" +#include "wlan_hdd_wext.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_tx_rx.h" + +#ifdef FEATURE_OEM_DATA_SUPPORT +/*include for oem data req specific structures*/ +/*and function declarations*/ +#include "wlan_hdd_oemdata.h" +#endif + +#endif // end #if !defined( HDD_INCLUDES_H__ ) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ipa.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ipa.h new file mode 100644 index 000000000000..0fa516030b94 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_ipa.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef HDD_IPA_H__ +#define HDD_IPA_H__ + +/**=========================================================================== + + \file wlan_hdd_ipa.h + + \brief WLAN IPA interface module headers + + ==========================================================================*/ + +/* $HEADER$ */ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#ifdef IPA_OFFLOAD +#include + +VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx); +VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx); +int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, + enum ipa_wlan_event type, uint8_t *mac_addr); +VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rxBuf, + v_U8_t sta_id); +bool hdd_ipa_is_enabled(hdd_context_t *pHddCtx); + +int hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets, + uint64_t rx_packets); + +int hdd_ipa_suspend(hdd_context_t *hdd_ctx); +int hdd_ipa_resume(hdd_context_t *hdd_ctx); + +#ifdef IPA_UC_STA_OFFLOAD +int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx, bool mcc_mode); +#endif + +#ifdef IPA_UC_OFFLOAD +void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx); +int hdd_ipa_uc_ssr_reinit(void); +int hdd_ipa_uc_ssr_deinit(void); +void hdd_ipa_uc_stat_query(hdd_context_t *pHddCtx, + uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff); +void hdd_ipa_uc_stat_request( hdd_adapter_t *adapter, uint8_t reason); +void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx); +#endif /* IPA_UC_OFFLOAD */ +#endif /* IPA_OFFLOAD */ + +#if !defined(IPA_OFFLOAD) || !defined(IPA_UC_OFFLOAD) +static inline +void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) +{ + return; +} +static inline +void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx) +{ + return; +} +#endif +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_keep_alive.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_keep_alive.h new file mode 100644 index 000000000000..a33074c7c272 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_keep_alive.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_KEEP_ALIVE_H__ +#define __WLAN_HDD_KEEP_ALIVE_H__ + +/**=========================================================================== + + \file wlan_hdd_keep_alive.h + + \brief Android WLAN HDD Keep-Alive API + +==========================================================================*/ + +/* Packet Types. */ +#define WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 +#define WLAN_KEEP_ALIVE_NULL_PKT 1 + +/* Enable or disable offload. */ +#define WLAN_KEEP_ALIVE_DISABLE 0 +#define WLAN_KEEP_ALIVE_ENABLE 0x1 + +/* Offload request. */ +typedef struct +{ + v_U8_t packetType; + v_U32_t timePeriod; + v_U8_t hostIpv4Addr[4]; + v_U8_t destIpv4Addr[4]; + v_U8_t destMacAddr [6]; + v_U8_t bssIdx; +} tKeepAliveRequest, *tpKeepAliveRequest; + +#endif // __WLAN_HDD_KEEP_ALIVE_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h new file mode 100644 index 000000000000..aeb1a6136ea3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h @@ -0,0 +1,1953 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( WLAN_HDD_MAIN_H ) +#define WLAN_HDD_MAIN_H +/**=========================================================================== + + \file WLAN_HDD_MAIN_H.h + + \brief Linux HDD Adapter Type + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include "sirMacProtDef.h" +#include "csrApi.h" +#include +#include +#include +#include +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif +#include +#ifdef FEATURE_WLAN_TDLS +#include "wlan_hdd_tdls.h" +#endif +#include "wlan_hdd_cfg80211.h" +#include +#ifdef WLAN_FEATURE_MBSSID +#include "sapApi.h" +#endif + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ +/** Number of Tx Queues */ +#define NUM_TX_QUEUES 4 +/** HDD's internal Tx Queue Length. Needs to be a power of 2 */ +#define HDD_TX_QUEUE_MAX_LEN 128 +/** HDD internal Tx Queue Low Watermark. Net Device TX queue is disabled + * when HDD queue becomes full. This Low watermark is used to enable + * the Net Device queue again */ +#define HDD_TX_QUEUE_LOW_WATER_MARK (HDD_TX_QUEUE_MAX_LEN*3/4) + +/** Length of the TX queue for the netdev */ +#define HDD_NETDEV_TX_QUEUE_LEN (3000) + +/** Bytes to reserve in the headroom */ +#if (!defined(QCA_WIFI_2_0)) || (defined(HIF_USB)) +#define HDD_HW_NEEDED_HEADROOM 128 +#else +#define HDD_HW_NEEDED_HEADROOM 0 +#endif + +/** Hdd Tx Time out value */ +#ifdef LIBRA_LINUX_PC +#define HDD_TX_TIMEOUT (8000) +#else +#define HDD_TX_TIMEOUT msecs_to_jiffies(5000) +#endif +/** Hdd Default MTU */ +#define HDD_DEFAULT_MTU (1500) + +#ifdef QCA_CONFIG_SMP +#define NUM_CPUS NR_CPUS +#else +#define NUM_CPUS 1 +#endif + +/**event flags registered net device*/ +#define NET_DEVICE_REGISTERED (0) +#define SME_SESSION_OPENED (1) +#define INIT_TX_RX_SUCCESS (2) +#define WMM_INIT_DONE (3) +#define SOFTAP_BSS_STARTED (4) +#define DEVICE_IFACE_OPENED (5) +#define TDLS_INIT_DONE (6) +#define ACS_PENDING (7) + +/* HDD global event flags */ +#define ACS_IN_PROGRESS (0) + +/** Maximum time(ms)to wait for disconnect to complete **/ +#define WLAN_WAIT_TIME_DISCONNECT 2000 +#define WLAN_WAIT_TIME_STATS 800 +#define WLAN_WAIT_TIME_POWER 800 +#define WLAN_WAIT_TIME_COUNTRY 1000 +#define WLAN_WAIT_TIME_LINK_STATUS 800 +/* 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 */ +#define WLAN_WAIT_TIME_SESSIONOPENCLOSE 15000 +#define WLAN_WAIT_TIME_ABORTSCAN 2000 +#define WLAN_WAIT_TIME_EXTSCAN 1000 +#define WLAN_WAIT_TIME_LL_STATS 5000 + +#define WLAN_WAIT_SMPS_FORCE_MODE 500 + +/** Maximum time(ms) to wait for mc thread suspend **/ +#define WLAN_WAIT_TIME_MCTHREAD_SUSPEND 1200 + +/** Maximum time(ms) to wait for target to be ready for suspend **/ +#define WLAN_WAIT_TIME_READY_TO_SUSPEND 2000 + + +/** Maximum time(ms) to wait for tdls add sta to complete **/ +#define WAIT_TIME_TDLS_ADD_STA 1500 + +/** Maximum time(ms) to wait for tdls del sta to complete **/ +#define WAIT_TIME_TDLS_DEL_STA 1500 + +/** Maximum time(ms) to wait for Link Establish Req to complete **/ +#define WAIT_TIME_TDLS_LINK_ESTABLISH_REQ 1500 + +/** Maximum time(ms) to wait for tdls mgmt to complete **/ +#define WAIT_TIME_TDLS_MGMT 11000 + +/** Maximum time(ms) to wait for tdls initiator to start direct communication **/ +#define WAIT_TIME_TDLS_INITIATOR 600 + +/* Scan Req Timeout */ +#define WLAN_WAIT_TIME_SCAN_REQ 100 + +#define MAX_NUMBER_OF_ADAPTERS 4 + +#define MAX_CFG_STRING_LEN 255 + +#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +/** Mac Address string **/ +#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ADDRESS_STR_LEN 18 /* Including null terminator */ +#define MAX_GENIE_LEN 255 + +#define WLAN_CHIP_VERSION "WCNSS" + +#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 WLAN_HDD_GET_PRIV_PTR(__dev__) (hdd_adapter_t*)(netdev_priv((__dev__))) + +#define MAX_EXIT_ATTEMPTS_DURING_LOGP 20 + +#define MAX_NO_OF_2_4_CHANNELS 14 + +#define WLAN_HDD_PUBLIC_ACTION_FRAME 4 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET 24 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET 24 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET 30 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET 0 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET 1 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET 2 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET 5 +#define WLAN_HDD_VENDOR_SPECIFIC_ACTION 0x09 +#define WLAN_HDD_WFA_OUI 0x506F9A +#define WLAN_HDD_WFA_P2P_OUI_TYPE 0x09 +#define WLAN_HDD_P2P_SOCIAL_CHANNELS 3 +#define WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN 1 +#define WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET 6 + +#define WLAN_HDD_IS_SOCIAL_CHANNEL(center_freq) \ +(((center_freq) == 2412) || ((center_freq) == 2437) || ((center_freq) == 2462)) + +#define WLAN_HDD_CHANNEL_IN_UNII_1_BAND(center_freq) \ +(((center_freq) == 5180 ) || ((center_freq) == 5200) \ +|| ((center_freq) == 5220) || ((center_freq) == 5240)) + +#ifdef WLAN_FEATURE_11W +#define WLAN_HDD_SA_QUERY_ACTION_FRAME 8 +#endif + +#define WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP 14 +#define WLAN_HDD_TDLS_ACTION_FRAME 12 +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK +#define HDD_WAKE_LOCK_DURATION 50 //in msecs +#endif + +#define WLAN_HDD_QOS_ACTION_FRAME 1 +#define WLAN_HDD_QOS_MAP_CONFIGURE 4 +#define HDD_SAP_WAKE_LOCK_DURATION 10000 //in msecs + +#define HDD_MOD_EXIT_SSR_MAX_RETRIES 75 + +/* Maximum number of interfaces allowed(STA, P2P Device, P2P Interfaces) */ +#ifndef WLAN_OPEN_P2P_INTERFACE +#define WLAN_MAX_INTERFACES 3 +#else +#define WLAN_MAX_INTERFACES 4 +#endif + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define GTK_OFFLOAD_ENABLE 0 +#define GTK_OFFLOAD_DISABLE 1 +#endif + +#define MAX_USER_COMMAND_SIZE 4096 + +#define HDD_MAC_ADDR_LEN 6 +#define HDD_SESSION_ID_ANY 50 //This should be same as CSR_SESSION_ID_ANY + +#define HDD_MIN_TX_POWER (-100) // minimum tx power +#define HDD_MAX_TX_POWER (+100) // maximum tx power + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) +#ifdef CONFIG_CNSS +#define cfg80211_vendor_cmd_reply(skb) cnss_vendor_cmd_reply(skb) +#endif +#endif + +typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN]; + +/* + * Generic asynchronous request/response support + * + * Many of the APIs supported by HDD require a call to SME to + * perform an action or to retrieve some data. In most cases SME + * performs the operation asynchronously, and will execute a provided + * callback function when the request has completed. In order to + * synchronize this the HDD API allocates a context which is then + * passed to SME, and which is then, in turn, passed back to the + * callback function when the operation completes. The callback + * function then sets a completion variable inside the context which + * the HDD API is waiting on. In an ideal world the HDD API would + * wait forever (or at least for a long time) for the response to be + * received and for the completion variable to be set. However in + * most cases these HDD APIs are being invoked in the context of a + * user space thread which has invoked either a cfg80211 API or a + * wireless extensions ioctl and which has taken the kernel rtnl_lock. + * Since this lock is used to synchronize many of the kernel tasks, we + * do not want to hold it for a long time. In addition we do not want + * to block user space threads (such as the wpa supplicant's main + * thread) for an extended time. Therefore we only block for a short + * time waiting for the response before we timeout. This means that + * it is possible for the HDD API to timeout, and for the callback to + * be invoked afterwards. In order for the callback function to + * determine if the HDD API is still waiting, a magic value is also + * stored in the shared context. Only if the context has a valid + * magic will the callback routine do any work. In order to further + * synchronize these activities a spinlock is used so that if any HDD + * API timeout coincides with its callback, the operations of the two + * threads will be serialized. + */ + +struct statsContext +{ + struct completion completion; + hdd_adapter_t *pAdapter; + unsigned int magic; + union iwreq_data *wrqu; + char *extra; +}; + +struct linkspeedContext +{ + struct completion completion; + hdd_adapter_t *pAdapter; + unsigned int magic; +}; + +extern spinlock_t hdd_context_lock; + +#define STATS_CONTEXT_MAGIC 0x53544154 //STAT +#define RSSI_CONTEXT_MAGIC 0x52535349 //RSSI +#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR +#define SNR_CONTEXT_MAGIC 0x534E5200 //SNR +#define LINK_CONTEXT_MAGIC 0x4C494E4B //LINKSPEED +#define LINK_STATUS_MAGIC 0x4C4B5354 //LINKSTATUS(LNST) +#define TEMP_CONTEXT_MAGIC 0x74656d70 // TEMP (temperature) +#define FW_STATUS_MAGIC 0x46575354 /* FWSTATUS(FWST) */ + +#ifdef QCA_LL_TX_FLOW_CT +/* MAX OS Q block time value in msec + * Prevent from permanent stall, resume OS Q if timer expired */ +#define WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME 1000 +#define WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME 100 +#define WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH 14 +#endif /* QCA_LL_TX_FLOW_CT */ + +#define NUM_TX_RX_HISTOGRAM 1024 +#define NUM_TX_RX_HISTOGRAM_MASK (NUM_TX_RX_HISTOGRAM - 1) + +/** + * struct hdd_tx_rx_histogram - structure to keep track of tx and rx packets + received over 100ms intervals + * @interval_rx # of rx packets received in the last 100ms interval + * @interval_tx # of tx packets received in the last 100ms interval + * @total_rx # of total rx packets received on interface + * @total_rx # of total tx packets received on interface + * @next_vote_level cnss_bus_width_type voting level (high or low) determined + on the basis of total tx and rx packets received in the + last 100ms interval + * @next_rx_level cnss_bus_width_type voting level (high or low) determined + on the basis of rx packets received in the last 100ms + interval + * @next_tx_level cnss_bus_width_type voting level (high or low) determined + on the basis of tx packets received in the last 100ms + interval + + * The structure keeps track of throughput requirements of wlan driver in 100ms + * intervals for later analysis. + */ +struct hdd_tx_rx_histogram +{ + uint64_t interval_rx; + uint64_t interval_tx; + uint64_t total_rx; + uint64_t total_tx; + uint32_t next_vote_level; + uint32_t next_rx_level; + uint32_t next_tx_level; +}; + +typedef struct hdd_tx_rx_stats_s +{ + // start_xmit stats + __u32 txXmitCalled; + __u32 txXmitDropped; + __u32 txXmitClassifiedAC[NUM_TX_QUEUES]; + __u32 txXmitDroppedAC[NUM_TX_QUEUES]; + // complete_cbk_stats + __u32 txCompleted; + // rx stats + __u32 rxPackets[NUM_CPUS]; + __u32 rxDropped[NUM_CPUS]; + __u32 rxDelivered[NUM_CPUS]; + __u32 rxRefused[NUM_CPUS]; + + __u32 netq_disable_cnt; + __u32 netq_enable_cnt; + bool netq_state_off; + + bool is_txflow_paused; + __u32 txflow_pause_cnt; + __u32 txflow_unpause_cnt; + __u32 txflow_timer_cnt; +} hdd_tx_rx_stats_t; + +#ifdef WLAN_FEATURE_11W +typedef struct hdd_pmf_stats_s +{ + uint8 numUnprotDeauthRx; + uint8 numUnprotDisassocRx; +} hdd_pmf_stats_t; +#endif + +typedef struct hdd_stats_s +{ + tCsrSummaryStatsInfo summary_stat; + tCsrGlobalClassAStatsInfo ClassA_stat; + tCsrGlobalClassBStatsInfo ClassB_stat; + tCsrGlobalClassCStatsInfo ClassC_stat; + tCsrGlobalClassDStatsInfo ClassD_stat; + tCsrPerStaStatsInfo perStaStats; + hdd_tx_rx_stats_t hddTxRxStats; +#ifdef WLAN_FEATURE_11W + hdd_pmf_stats_t hddPmfStats; +#endif +} hdd_stats_t; + +typedef enum +{ + HDD_ROAM_STATE_NONE, + + // Issuing a disconnect due to transition into low power states. + HDD_ROAM_STATE_DISCONNECTING_POWER, + + // move to this state when HDD sets a key with SME/CSR. Note this is + // an important state to get right because we will get calls into our SME + // callback routine for SetKey activity that we did not initiate! + HDD_ROAM_STATE_SETTING_KEY, +} HDD_ROAM_STATE; + +typedef enum +{ + eHDD_SUSPEND_NONE = 0, + eHDD_SUSPEND_DEEP_SLEEP, + eHDD_SUSPEND_STANDBY, +} hdd_ps_state_t; + +typedef struct roaming_info_s +{ + HDD_ROAM_STATE roamingState; + vos_event_t roamingEvent; + + tWlanHddMacAddr bssid; + tWlanHddMacAddr peerMac; + tANI_U32 roamId; + eRoamCmdStatus roamStatus; + v_BOOL_t deferKeyComplete; + +} roaming_info_t; + +#ifdef FEATURE_WLAN_WAPI +/* Define WAPI macros for Length, BKID count etc*/ +#define MAX_WPI_KEY_LENGTH 16 +#define MAX_NUM_PN 16 +#define MAC_ADDR_LEN 6 +#define MAX_ADDR_INDEX 12 +#define MAX_NUM_AKM_SUITES 16 +#define MAX_NUM_UNI_SUITES 16 +#define MAX_NUM_BKIDS 16 + +/** WAPI AUTH mode definition */ +enum _WAPIAuthMode +{ + WAPI_AUTH_MODE_OPEN = 0, + WAPI_AUTH_MODE_PSK = 1, + WAPI_AUTH_MODE_CERT +} __packed; +typedef enum _WAPIAuthMode WAPIAuthMode; + +/** WAPI Work mode structure definition */ +#define WZC_ORIGINAL 0 +#define WAPI_EXTENTION 1 + +struct _WAPI_FUNCTION_MODE +{ + unsigned char wapiMode; +}__packed; + +typedef struct _WAPI_FUNCTION_MODE WAPI_FUNCTION_MODE; + +typedef struct _WAPI_BKID +{ + v_U8_t bkid[16]; +}WAPI_BKID, *pWAPI_BKID; + +/** WAPI Association information structure definition */ +struct _WAPI_AssocInfo +{ + v_U8_t elementID; + v_U8_t length; + v_U16_t version; + v_U16_t akmSuiteCount; + v_U32_t akmSuite[MAX_NUM_AKM_SUITES]; + v_U16_t unicastSuiteCount; + v_U32_t unicastSuite[MAX_NUM_UNI_SUITES]; + v_U32_t multicastSuite; + v_U16_t wapiCability; + v_U16_t bkidCount; + WAPI_BKID bkidList[MAX_NUM_BKIDS]; +} __packed; + +typedef struct _WAPI_AssocInfo WAPI_AssocInfo; +typedef struct _WAPI_AssocInfo *pWAPI_IEAssocInfo; + +/** WAPI KEY Type definition */ +enum _WAPIKeyType +{ + PAIRWISE_KEY, //0 + GROUP_KEY //1 +}__packed; +typedef enum _WAPIKeyType WAPIKeyType; + +/** WAPI KEY Direction definition */ +enum _KEY_DIRECTION +{ + None, + Rx, + Tx, + Rx_Tx +}__packed; + +typedef enum _KEY_DIRECTION WAPI_KEY_DIRECTION; + +/* WAPI KEY structure definition */ +struct WLAN_WAPI_KEY +{ + WAPIKeyType keyType; + WAPI_KEY_DIRECTION keyDirection; /*reserved for future use*/ + v_U8_t keyId; + v_U8_t addrIndex[MAX_ADDR_INDEX]; /*reserved for future use*/ + int wpiekLen; + v_U8_t wpiek[MAX_WPI_KEY_LENGTH]; + int wpickLen; + v_U8_t wpick[MAX_WPI_KEY_LENGTH]; + v_U8_t pn[MAX_NUM_PN]; /*reserved for future use*/ +}__packed; + +typedef struct WLAN_WAPI_KEY WLAN_WAPI_KEY; +typedef struct WLAN_WAPI_KEY *pWLAN_WAPI_KEY; + +#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) +#define WPA_GET_BE24(a) ((u32) ( (a[0] << 16) | (a[1] << 8) | a[2])) +#define WLAN_EID_WAPI 68 +#define WAPI_PSK_AKM_SUITE 0x02721400 +#define WAPI_CERT_AKM_SUITE 0x01721400 + +/* WAPI BKID List structure definition */ +struct _WLAN_BKID_LIST +{ + v_U32_t length; + v_U32_t BKIDCount; + WAPI_BKID BKID[1]; +}__packed; + +typedef struct _WLAN_BKID_LIST WLAN_BKID_LIST; +typedef struct _WLAN_BKID_LIST *pWLAN_BKID_LIST; + + +/* WAPI Information structure definition */ +struct hdd_wapi_info_s +{ + v_U32_t nWapiMode; + v_BOOL_t fIsWapiSta; + v_MACADDR_t cachedMacAddr; + v_UCHAR_t wapiAuthMode; +}__packed; +typedef struct hdd_wapi_info_s hdd_wapi_info_t; +#endif /* FEATURE_WLAN_WAPI */ + +typedef struct beacon_data_s { + u8 *head; + u8 *tail; + u8 *proberesp_ies; + u8 *assocresp_ies; + int head_len; + int tail_len; + int proberesp_ies_len; + int assocresp_ies_len; + int dtim_period; +} beacon_data_t; + +typedef enum device_mode +{ /* MAINTAIN 1 - 1 CORRESPONDENCE WITH tVOS_CON_MODE*/ + WLAN_HDD_INFRA_STATION, + WLAN_HDD_SOFTAP, + WLAN_HDD_P2P_CLIENT, + WLAN_HDD_P2P_GO, + WLAN_HDD_MONITOR, + WLAN_HDD_FTM, + WLAN_HDD_IBSS, + WLAN_HDD_P2P_DEVICE, + WLAN_HDD_OCB +}device_mode_t; + +typedef enum rem_on_channel_request_type +{ + REMAIN_ON_CHANNEL_REQUEST, + OFF_CHANNEL_ACTION_TX, +}rem_on_channel_request_type_t; + +/* Thermal mitigation Level Enum Type */ +typedef enum +{ + WLAN_HDD_TM_LEVEL_0, + WLAN_HDD_TM_LEVEL_1, + WLAN_HDD_TM_LEVEL_2, + WLAN_HDD_TM_LEVEL_3, + WLAN_HDD_TM_LEVEL_4, + WLAN_HDD_TM_LEVEL_MAX +} WLAN_TmLevelEnumType; + +/* Driver Action based on thermal mitigation level structure */ +typedef struct +{ + v_BOOL_t ampduEnable; + v_BOOL_t enterImps; + v_U32_t txSleepDuration; + v_U32_t txOperationDuration; + v_U32_t txBlockFrameCountThreshold; +} hdd_tmLevelAction_t; + +/* Thermal Mitigation control context structure */ +typedef struct +{ + WLAN_TmLevelEnumType currentTmLevel; + hdd_tmLevelAction_t tmAction; + vos_timer_t txSleepTimer; + struct mutex tmOperationLock; + vos_event_t setTmDoneEvent; + v_U32_t txFrameCount; + v_TIME_t lastblockTs; + v_TIME_t lastOpenTs; + struct netdev_queue *blockedQueue; + v_BOOL_t qBlocked; +} hdd_thermal_mitigation_info_t; + +typedef struct action_pkt_buffer +{ + tANI_U8* frame_ptr; + tANI_U32 frame_length; + tANI_U16 freq; +}action_pkt_buffer_t; + +typedef struct hdd_remain_on_chan_ctx +{ + struct net_device *dev; + struct ieee80211_channel chan; + enum nl80211_channel_type chan_type; + unsigned int duration; + u64 cookie; + rem_on_channel_request_type_t rem_on_chan_request; + v_U32_t p2pRemOnChanTimeStamp; + vos_timer_t hdd_remain_on_chan_timer; + action_pkt_buffer_t action_pkt_buff; + v_BOOL_t hdd_remain_on_chan_cancel_in_progress; +}hdd_remain_on_chan_ctx_t; + +/* RoC Request entry */ +typedef struct hdd_roc_req +{ + hdd_list_node_t node; /* MUST be first element */ + hdd_adapter_t *pAdapter; + hdd_remain_on_chan_ctx_t *pRemainChanCtx; +}hdd_roc_req_t; + +typedef enum{ + HDD_IDLE, + HDD_PD_REQ_ACK_PENDING, + HDD_GO_NEG_REQ_ACK_PENDING, + HDD_INVALID_STATE, +}eP2PActionFrameState; + +typedef enum { + WLAN_HDD_GO_NEG_REQ, + WLAN_HDD_GO_NEG_RESP, + WLAN_HDD_GO_NEG_CNF, + WLAN_HDD_INVITATION_REQ, + WLAN_HDD_INVITATION_RESP, + WLAN_HDD_DEV_DIS_REQ, + WLAN_HDD_DEV_DIS_RESP, + WLAN_HDD_PROV_DIS_REQ, + WLAN_HDD_PROV_DIS_RESP, +}tActionFrmType; + +typedef struct hdd_cfg80211_state_s +{ + tANI_U16 current_freq; + u64 action_cookie; + tANI_U8 *buf; + size_t len; + struct sk_buff *skb; + hdd_remain_on_chan_ctx_t* remain_on_chan_ctx; + struct mutex remain_on_chan_ctx_lock; + eP2PActionFrameState actionFrmState; +}hdd_cfg80211_state_t; + + +typedef enum{ + HDD_SSR_NOT_REQUIRED, + HDD_SSR_REQUIRED, + HDD_SSR_DISABLED, +}e_hdd_ssr_required; + +struct hdd_station_ctx +{ + /** Handle to the Wireless Extension State */ + hdd_wext_state_t WextState; + +#ifdef FEATURE_WLAN_TDLS + tdlsCtx_t *pHddTdlsCtx; +#endif + + + /**Connection information*/ + connection_info_t conn_info; + + roaming_info_t roam_info; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + int ft_carrier_on; +#endif + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + tSirGtkOffloadParams gtkOffloadReqParams; +#endif + /*Increment whenever ibss New peer joins and departs the network */ + int ibss_sta_generation; + + /* Indication of wep/wpa-none keys installation */ + v_BOOL_t ibss_enc_key_installed; + + /*Save the wep/wpa-none keys*/ + tCsrRoamSetKey ibss_enc_key; + v_BOOL_t hdd_ReassocScenario; + + /* STA ctx debug variables */ + int staDebugState; +}; + +#define BSS_STOP 0 +#define BSS_START 1 +typedef struct hdd_hostapd_state_s +{ + int bssState; + vos_event_t vosEvent; + vos_event_t stop_bss_event; + VOS_STATUS vosStatus; + v_BOOL_t bCommit; + +} hdd_hostapd_state_t; + + +/* + * Per station structure kept in HDD for multiple station support for SoftAP +*/ +typedef struct { + /** The station entry is used or not */ + v_BOOL_t isUsed; + + /** Station ID reported back from HAL (through SAP). Broadcast + * uses station ID zero by default in both libra and volans. */ + v_U8_t ucSTAId; + + /** MAC address of the station */ + v_MACADDR_t macAddrSTA; + + /** Current Station state so HDD knows how to deal with packet + * queue. Most recent states used to change TL STA state. */ + WLANTL_STAStateType tlSTAState; + + /** Transmit queues for each AC (VO,VI,BE etc). */ + hdd_list_t wmm_tx_queue[NUM_TX_QUEUES]; + + /** Might need to differentiate queue depth in contention case */ + v_U16_t aTxQueueDepth[NUM_TX_QUEUES]; + + /**Track whether OS TX queue has been disabled.*/ + v_BOOL_t txSuspended[NUM_TX_QUEUES]; + + /**Track whether 3/4th of resources are used */ + v_BOOL_t vosLowResource; + + /** Track QoS status of station */ + v_BOOL_t isQosEnabled; + + /** The station entry for which Deauth is in progress */ + v_BOOL_t isDeauthInProgress; + + /** Number of spatial streams supported */ + uint8_t nss; + + /** Rate Flags for this connection */ + uint32_t rate_flags; +} hdd_station_info_t; + +struct hdd_ap_ctx_s +{ + hdd_hostapd_state_t HostapdState; + + // Memory differentiation mode is enabled + //v_U16_t uMemoryDiffThreshold; + //v_U8_t uNumActiveAC; + //v_U8_t uActiveACMask; + //v_U8_t aTxQueueLimit[NUM_TX_QUEUES]; + + /** Packet Count to update uNumActiveAC and uActiveACMask */ + //v_U16_t uUpdatePktCount; + + /** Station ID assigned after BSS starts */ + v_U8_t uBCStaId; + + v_U8_t uPrivacy; // The privacy bits of configuration + + tSirWPSPBCProbeReq WPSPBCProbeReq; + + tsap_Config_t sapConfig; + + struct semaphore semWpsPBCOverlapInd; + + v_BOOL_t apDisableIntraBssFwd; + + vos_timer_t hdd_ap_inactivity_timer; + + v_U8_t operatingChannel; + + v_BOOL_t uIsAuthenticated; + + eCsrEncryptionType ucEncryptType; + + //This will point to group key data, if it is received before start bss. + tCsrRoamSetKey groupKey; + // This will have WEP key data, if it is received before start bss + tCsrRoamSetKey wepKey[CSR_MAX_NUM_KEY]; + + beacon_data_t *beacon; + + v_BOOL_t bApActive; +#ifdef WLAN_FEATURE_MBSSID + /* SAP Context */ + v_PVOID_t sapContext; +#endif + v_BOOL_t dfs_cac_block_tx; +}; + +struct hdd_mon_ctx_s +{ + hdd_adapter_t *pAdapterForTx; +}; + +typedef struct hdd_scaninfo_s +{ + /* The scan id */ + v_U32_t scanId; + + /* The scan pending */ + v_U32_t mScanPending; + + /* Counter for mScanPending so that the scan pending + error log is not printed for more than 5 times */ + v_U32_t mScanPendingCounter; + + /* Client Wait Scan Result */ + v_U32_t waitScanResult; + + /* Additional IE for scan */ + tSirAddie scanAddIE; + + /* Scan mode*/ + tSirScanType scan_mode; + + /* Scan Completion Event */ + struct completion scan_req_completion_event; + + /* completion variable for abortscan */ + struct completion abortscan_event_var; + + vos_event_t scan_finished_event; + + hdd_scan_pending_option_e scan_pending_option; + +}hdd_scaninfo_t; + +#define WLAN_HDD_MAX_MC_ADDR_LIST 10 + +#ifdef WLAN_FEATURE_PACKET_FILTERING +typedef struct multicast_addr_list +{ + v_U8_t isFilterApplied; + v_U8_t mc_cnt; + v_U8_t addr[WLAN_HDD_MAX_MC_ADDR_LIST][ETH_ALEN]; +} t_multicast_add_list; +#endif + +#define WLAN_HDD_ADAPTER_MAGIC 0x574c414e //ASCII "WLAN" + +/** + * struct hdd_runtime_pm_context - context to prevent/allow runtime pm + * @scan: scan context to prevent/allow runtime pm + * @roc : remain on channel runtime pm context + * @dfs : Dynamic frequency selection runtime pm context + * + * Prevent Runtime PM for scan, roc and dfs. + */ +struct hdd_runtime_pm_context { + void *scan; + void *roc; + void *dfs; +}; + +/** + * struct hdd_adapter_pm_context - Context/Adapter to prevent/allow runtime pm + * @connect : Connect context per adapter + * + * Structure to hold runtime pm contexts for each adapter + */ +struct hdd_adapter_pm_context { + void *connect; +}; + +struct hdd_adapter_s +{ + /* Magic cookie for adapter sanity verification. Note that this + * needs to be at the beginning of the private data structure so + * that it will exists at the beginning of dev->priv and hence + * will always be in mapped memory + */ + v_U32_t magic; + + void *pHddCtx; + + /** Handle to the network device */ + struct net_device *dev; + + device_mode_t device_mode; + + /** IPv4 notifier callback for handling ARP offload on change in IP */ + struct work_struct ipv4NotifierWorkQueue; +#ifdef WLAN_NS_OFFLOAD + /** IPv6 notifier callback for handling NS offload on change in IP */ + struct work_struct ipv6NotifierWorkQueue; +#endif + + //TODO Move this to sta Ctx + struct wireless_dev wdev ; + struct cfg80211_scan_request *request ; + + /** ops checks if Opportunistic Power Save is Enable or Not + * ctw stores ctWindow value once we receive Opps command from + * wpa_supplicant then using ctWindow value we need to Enable + * Opportunistic Power Save + */ + tANI_U8 ops; + tANI_U32 ctw; + + /** Current MAC Address for the adapter */ + v_MACADDR_t macAddressCurrent; + + /**Event Flags*/ + unsigned long event_flags; + + /**Device TX/RX statistics*/ + struct net_device_stats stats; + /** HDD statistics*/ + hdd_stats_t hdd_stats; + /** linkspeed statistics */ + tSirLinkSpeedInfo ls_stats; + /**Mib information*/ + sHddMib_t hdd_mib; + + tANI_U8 sessionId; + + /* Completion variable for session close */ + struct completion session_close_comp_var; + + /* Completion variable for session open */ + struct completion session_open_comp_var; + + /* Completion variable for smps force mode command */ + struct completion smps_force_mode_comp_var; + int8_t smps_force_mode_status; + + //TODO: move these to sta ctx. These may not be used in AP + /** completion variable for disconnect callback */ + struct completion disconnect_comp_var; + + /** Completion of change country code */ + struct completion change_country_code; + + /* completion variable for Linkup Event */ + struct completion linkup_event_var; + + /* completion variable for cancel remain on channel Event */ + struct completion cancel_rem_on_chan_var; + + /* completion variable for off channel remain on channel Event */ + struct completion offchannel_tx_event; + /* Completion variable for action frame */ + struct completion tx_action_cnf_event; + /* Completion variable for remain on channel ready */ + struct completion rem_on_chan_ready_event; + + /* Completion variable for Upper Layer Authentication */ + struct completion ula_complete; + +#ifdef FEATURE_WLAN_TDLS + struct completion tdls_add_station_comp; + struct completion tdls_del_station_comp; + struct completion tdls_mgmt_comp; + struct completion tdls_link_establish_req_comp; + eHalStatus tdlsAddStaStatus; +#endif + + /* Track whether the linkup handling is needed */ + v_BOOL_t isLinkUpSvcNeeded; + + /* Mgmt Frames TX completion status code */ + tANI_U32 mgmtTxCompletionStatus; + +/************************************************************* + * Tx Queues + */ + /** Transmit queues for each AC (VO,VI,BE etc) */ + hdd_list_t wmm_tx_queue[NUM_TX_QUEUES]; + /**Track whether VOS is in a low resource state*/ + v_BOOL_t isVosOutOfResource; + + /**Track whether 3/4th of resources are used */ + v_BOOL_t isVosLowResource; + + /**Track whether OS TX queue has been disabled.*/ + v_BOOL_t isTxSuspended[NUM_TX_QUEUES]; + + /** WMM Status */ + hdd_wmm_status_t hddWmmStatus; +/************************************************************* + */ +/************************************************************* + * TODO - Remove it later + */ + /** Multiple station supports */ + /** Per-station structure */ + spinlock_t staInfo_lock; //To protect access to station Info + hdd_station_info_t aStaInfo[WLAN_MAX_STA_COUNT]; + //v_U8_t uNumActiveStation; + + v_U16_t aTxQueueLimit[NUM_TX_QUEUES]; +/************************************************************* + */ + +#ifdef FEATURE_WLAN_WAPI + hdd_wapi_info_t wapi_info; +#endif + + v_S7_t rssi; + int8_t rssi_on_disconnect; +#ifdef WLAN_FEATURE_LPSS + v_BOOL_t rssi_send; +#endif + + tANI_U8 snr; + + struct work_struct monTxWorkQueue; + struct sk_buff *skb_to_tx; + + union { + hdd_station_ctx_t station; + hdd_ap_ctx_t ap; + hdd_mon_ctx_t monitor; + }sessionCtx; + +#ifdef WLAN_FEATURE_TSF + /* tsf value get from firmware */ + uint32_t tsf_low; + uint32_t tsf_high; + /* current in capture tsf state or not */ + enum hdd_tsf_capture_state tsf_state; +#endif + + hdd_cfg80211_state_t cfg80211State; + +#ifdef WLAN_FEATURE_PACKET_FILTERING + t_multicast_add_list mc_addr_list; +#endif + uint8_t addr_filter_pattern; + + v_BOOL_t higherDtimTransition; + v_BOOL_t survey_idx; + + hdd_scaninfo_t scan_info; +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + tAniTrafStrmMetrics tsmStats; +#endif + /* Flag to ensure PSB is configured through framework */ + v_U8_t psbChanged; + /* UAPSD psb value configured through framework */ + v_U8_t configuredPsb; +#ifdef IPA_OFFLOAD + void *ipa_context; +#endif +#ifdef WLAN_FEATURE_MBSSID + /* this need to be adapter struct since adapter type can be dyn changed */ + mbssid_sap_dyn_ini_config_t sap_dyn_ini_cfg; +#endif + struct work_struct scan_block_work; + /* Using delayed work for ACS for Primary AP Startup to complete + * since CSR Config is same for both AP */ + struct delayed_work acs_pending_work; +#ifdef MSM_PLATFORM + unsigned long prev_rx_packets; + unsigned long prev_tx_packets; + int connection; +#endif + v_BOOL_t is_roc_inprogress; + +#ifdef QCA_LL_TX_FLOW_CT + vos_timer_t tx_flow_control_timer; + v_BOOL_t tx_flow_timer_initialized; + unsigned int tx_flow_low_watermark; + unsigned int tx_flow_high_watermark_offset; +#endif /* QCA_LL_TX_FLOW_CT */ + v_BOOL_t offloads_configured; + + /* DSCP to UP QoS Mapping */ + sme_QosWmmUpType hddWmmDscpToUpMap[WLAN_HDD_MAX_DSCP+1]; + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + v_BOOL_t isLinkLayerStatsSet; +#endif + v_U8_t linkStatus; + + /* variable for temperature in Celsius */ + int temperature; + + /* Time stamp for last completed RoC request */ + v_TIME_t lastRocTs; + + /* Time stamp for start RoC request */ + v_TIME_t startRocTs; + + /* State for synchronous OCB requests to WMI */ + struct sir_ocb_set_config_response ocb_set_config_resp; + struct sir_ocb_get_tsf_timer_response ocb_get_tsf_timer_resp; + struct sir_dcc_get_stats_response *dcc_get_stats_resp; + struct sir_dcc_update_ndl_response dcc_update_ndl_resp; + + /* MAC addresses used for OCB interfaces */ + tSirMacAddr ocb_mac_address[VOS_MAX_CONCURRENCY_PERSONA]; + int ocb_mac_addr_count; + struct hdd_adapter_pm_context runtime_context; +}; + +#define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) +#define WLAN_HDD_GET_AP_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap) +#define WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.station.WextState) +#define WLAN_HDD_GET_CTX(pAdapter) ((hdd_context_t*)pAdapter->pHddCtx) +#define WLAN_HDD_GET_HAL_CTX(pAdapter) (((hdd_context_t*)(pAdapter->pHddCtx))->hHal) +#define WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap.HostapdState) +#define WLAN_HDD_GET_CFG_STATE_PTR(pAdapter) (&(pAdapter)->cfg80211State) +#ifdef WLAN_FEATURE_MBSSID +#define WLAN_HDD_GET_SAP_CTX_PTR(pAdapter) (pAdapter->sessionCtx.ap.sapContext) +#endif +#ifdef FEATURE_WLAN_TDLS +#define WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter) \ + (((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && \ + (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode)) ? 0 : 1) +#define WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter) \ + ((WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) ? \ + (tdlsCtx_t*)(pAdapter)->sessionCtx.station.pHddTdlsCtx : NULL) +#endif + +/* Set mac address locally administered bit */ +#define WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macaddr) (macaddr[0] &= 0xFD) + +#define HDD_DEFAULT_MCC_P2P_QUOTA 70 +#define HDD_RESET_MCC_P2P_QUOTA 50 + +typedef struct hdd_adapter_list_node +{ + hdd_list_node_t node; // MUST be first element + hdd_adapter_t *pAdapter; +}hdd_adapter_list_node_t; + +typedef struct hdd_priv_data_s +{ + tANI_U8 *buf; + int used_len; + int total_len; +}hdd_priv_data_t; + +#ifdef FEATURE_GREEN_AP + +#define GREEN_AP_PS_ON_TIME (0) +#define GREEN_AP_PS_DELAY_TIME (20) + +/* + * Green-AP power save state + */ +typedef enum +{ + GREEN_AP_PS_IDLE_STATE = 1, + GREEN_AP_PS_OFF_STATE, + GREEN_AP_PS_WAIT_STATE, + GREEN_AP_PS_ON_STATE, +}hdd_green_ap_ps_state_t; + +typedef enum +{ + GREEN_AP_PS_START_EVENT = 1, + GREEN_AP_PS_STOP_EVENT, + GREEN_AP_ADD_STA_EVENT, + GREEN_AP_DEL_STA_EVENT, + GREEN_AP_PS_ON_EVENT, + GREEN_AP_PS_WAIT_EVENT, +}hdd_green_ap_event_t; + +typedef struct +{ + uint64_t ps_on_count; + v_TIME_t ps_on_prev_ticks; + v_TIME_t ps_on_ticks; + + uint64_t ps_off_count; + v_TIME_t ps_off_prev_ticks; + v_TIME_t ps_off_ticks; + +}hdd_green_ap_stats; + +/* + * Green-AP context + */ +typedef struct +{ + v_CONTEXT_t pHddContext; + + v_U8_t ps_enable; + v_U32_t ps_on_time; + v_U32_t ps_delay_time; + v_U32_t num_nodes; + + hdd_green_ap_ps_state_t ps_state; + hdd_green_ap_event_t ps_event; + + vos_timer_t ps_timer; + + hdd_green_ap_stats stats; + +}hdd_green_ap_ctx_t; +#endif /* FEATURE_GREEN_AP */ + +#define MAX_MOD_LOGLEVEL 10 +typedef struct +{ + v_U8_t enable; + v_U8_t dl_type; + v_U8_t dl_report; + v_U8_t dl_loglevel; + v_U8_t index; + v_U32_t dl_mod_loglevel[MAX_MOD_LOGLEVEL]; + +}fw_log_info; + +/** + * enum antenna_mode - number of TX/RX chains + * @HDD_ANTENNA_MODE_INVALID: Invalid mode place holder + * @HDD_ANTENNA_MODE_1X1: Number of TX/RX chains equals 1 + * @HDD_ANTENNA_MODE_2X2: Number of TX/RX chains equals 2 + * @HDD_ANTENNA_MODE_MAX: Place holder for max mode + */ +enum antenna_mode { + HDD_ANTENNA_MODE_INVALID, + HDD_ANTENNA_MODE_1X1, + HDD_ANTENNA_MODE_2X2, + HDD_ANTENNA_MODE_MAX +}; + +/** + * enum smps_mode - SM power save mode + * @HDD_SMPS_MODE_STATIC: Static power save + * @HDD_SMPS_MODE_DYNAMIC: Dynamic power save + * @HDD_SMPS_MODE_RESERVED: Reserved + * @HDD_SMPS_MODE_DISABLED: Disable power save + * @HDD_SMPS_MODE_MAX: Place holder for max mode + */ +enum smps_mode { + HDD_SMPS_MODE_STATIC, + HDD_SMPS_MODE_DYNAMIC, + HDD_SMPS_MODE_RESERVED, + HDD_SMPS_MODE_DISABLED, + HDD_SMPS_MODE_MAX +}; + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * struct hdd_ext_scan_context - hdd ext scan context + * + * @request_id: userspace-assigned ID associated with the request + * @response_event: Ext scan wait event + * @response_status: Status returned by FW in response to a request + * @ignore_cached_results: Flag to ignore cached results or not + * @capability_response: Ext scan capability response data from target + */ +struct hdd_ext_scan_context { + uint32_t request_id; + int response_status; + bool ignore_cached_results; + struct completion response_event; + struct ext_scan_capabilities_response capability_response; +}; +#endif /* End of FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +/** + * struct hdd_ll_stats_context - hdd link layer stats context + * + * @request_id: userspace-assigned link layer stats request id + * @request_bitmap: userspace-assigned link layer stats request bitmap + * @response_event: LL stats request wait event + */ +struct hdd_ll_stats_context { + uint32_t request_id; + uint32_t request_bitmap; + struct completion response_event; +}; +#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS +/** + * struct hdd_offloaded_packets - request id to pattern id mapping + * @request_id: request id + * @pattern_id: pattern id + * + */ +struct hdd_offloaded_packets { + uint32_t request_id; + uint8_t pattern_id; +}; + +/** + * struct hdd_offloaded_packets_ctx - offloaded packets context + * @op_table: request id to pattern id table + * @op_lock: mutex lock + */ +struct hdd_offloaded_packets_ctx { + struct hdd_offloaded_packets op_table[MAXNUM_PERIODIC_TX_PTRNS]; + struct mutex op_lock; +}; +#endif + +/** Adapter stucture definition */ + +struct hdd_context_s +{ + /** Global VOS context */ + v_CONTEXT_t pvosContext; + + /** HAL handle...*/ + tHalHandle hHal; + + struct wiphy *wiphy ; + //TODO Remove this from here. + + hdd_list_t hddAdapters; //List of adapters + + /* One per STA: 1 for BCMC_STA_ID, 1 for each SAP_SELF_STA_ID, 1 for WDS_STAID */ + hdd_adapter_t *sta_to_adapter[WLAN_MAX_STA_COUNT + VOS_MAX_NO_OF_SAP_MODE + 2]; //One per sta. For quick reference. + + /** Pointer for firmware image data */ + const struct firmware *fw; + + /** Pointer for configuration data */ + const struct firmware *cfg; + + /** Pointer for nv data */ + const struct firmware *nv; + + /** Pointer to the parent device */ + struct device *parent_dev; + + /** Config values read from qcom_cfg.ini file */ + hdd_config_t *cfg_ini; + wlan_hdd_ftm_status_t ftm; + /** completion variable for full power callback */ + struct completion full_pwr_comp_var; + /** completion variable for Request BMPS callback */ + struct completion req_bmps_comp_var; + + /** completion variable for standby callback */ + struct completion standby_comp_var; + + /* Completion variable to indicate Rx Thread Suspended */ + struct completion rx_sus_event_var; + + /* Completion variable to indicate Tx Thread Suspended */ + struct completion tx_sus_event_var; + + /* Completion variable to indicate Mc Thread Suspended */ + struct completion mc_sus_event_var; + + struct completion reg_init; + + v_BOOL_t isWlanSuspended; + + v_BOOL_t isTxThreadSuspended; + + v_BOOL_t isMcThreadSuspended; + + v_BOOL_t isRxThreadSuspended; + +#ifdef QCA_CONFIG_SMP + v_BOOL_t isTlshimRxThreadSuspended; +#endif + + volatile v_BOOL_t isLogpInProgress; + + v_BOOL_t isLoadInProgress; + + v_BOOL_t isUnloadInProgress; + + /**Track whether driver has been suspended.*/ + hdd_ps_state_t hdd_ps_state; + + /* Track whether Mcast/Bcast Filter is enabled.*/ + v_BOOL_t hdd_mcastbcast_filter_set; + + /* Track whether ignore DTIM is enabled*/ + v_BOOL_t hdd_ignore_dtim_enabled; + v_U32_t hdd_actual_ignore_DTIM_value; + v_U32_t hdd_actual_LI_value; + + + v_BOOL_t hdd_wlan_suspended; + v_BOOL_t suspended; + + spinlock_t filter_lock; + + /* Lock to avoid race condition during start/stop bss */ + struct mutex sap_lock; + + /** ptt Process ID*/ + v_SINT_t ptt_pid; +#ifdef WLAN_KD_READY_NOTIFIER + v_BOOL_t kd_nl_init; +#endif /* WLAN_KD_READY_NOTIFIER */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + /* OEM App registered or not */ + v_BOOL_t oem_app_registered; + + /* OEM App Process ID */ + v_SINT_t oem_pid; +#endif + + v_U8_t change_iface; + + /** Concurrency Parameters*/ + tVOS_CONCURRENCY_MODE concurrency_mode; + + v_U8_t no_of_open_sessions[VOS_MAX_NO_OF_MODE]; + v_U8_t no_of_active_sessions[VOS_MAX_NO_OF_MODE]; + + /* Number of times riva restarted */ + v_U32_t hddRivaResetStats; + + /* Can we allow AMP connection right now*/ + v_BOOL_t isAmpAllowed; + + /** P2P Device MAC Address for the adapter */ + v_MACADDR_t p2pDeviceAddress; + + /* Thermal mitigation information */ + hdd_thermal_mitigation_info_t tmInfo; + +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + vos_wake_lock_t rx_wake_lock; +#endif + + /* + * Framework initiated driver restarting + * hdd_reload_timer : Restart retry timer + * isRestartInProgress: Restart in progress + * hdd_restart_retries: Restart retries + * + */ + vos_timer_t hdd_restart_timer; + atomic_t isRestartInProgress; + u_int8_t hdd_restart_retries; + + vos_wake_lock_t sap_wake_lock; + +#ifdef FEATURE_WLAN_TDLS + eTDLSSupportMode tdls_mode; + eTDLSSupportMode tdls_mode_last; + tdlsConnInfo_t tdlsConnInfo[HDD_MAX_NUM_TDLS_STA]; + /* maximum TDLS station number allowed upon runtime condition */ + tANI_U16 max_num_tdls_sta; + /* TDLS peer connected count */ + tANI_U16 connected_peer_count; + tdls_scan_context_t tdls_scan_ctxt; + /* Lock to avoid race condition during TDLS operations*/ + struct mutex tdls_lock; + tANI_U8 tdls_off_channel; + tANI_U16 tdls_channel_offset; + int32_t tdls_fw_off_chan_mode; + bool tdls_nss_switch_in_progress; + bool tdls_nss_teardown_complete; + int32_t tdls_nss_transition_mode; + int32_t tdls_teardown_peers_cnt; +#endif + +#ifdef IPA_OFFLOAD + void *hdd_ipa; +#ifdef IPA_UC_OFFLOAD + /* CE resources */ + v_U32_t ce_sr_base_paddr; + v_U32_t ce_sr_ring_size; + v_U32_t ce_reg_paddr; + + /* WLAN TX:IPA->WLAN */ + v_U32_t tx_comp_ring_base_paddr; + v_U32_t tx_comp_ring_size; + v_U32_t tx_num_alloc_buffer; + + /* WLAN RX:WLAN->IPA */ + v_U32_t rx_rdy_ring_base_paddr; + v_U32_t rx_rdy_ring_size; + v_U32_t rx_proc_done_idx_paddr; + + /* IPA UC doorbell registers paddr */ + v_U32_t tx_comp_doorbell_paddr; + v_U32_t rx_ready_doorbell_paddr; +#endif /* IPA_UC_OFFLOAD */ +#endif + /* MC/BC Filter state variable + * This always contains the value that is currently + * configured + * */ + v_U8_t configuredMcastBcastFilter; + + v_U8_t sus_res_mcastbcast_filter; + + v_BOOL_t sus_res_mcastbcast_filter_valid; + + /* debugfs entry */ + struct dentry *debugfs_phy; + + /* Use below lock to protect access to isSchedScanUpdatePending + * since it will be accessed in two different contexts. + */ + spinlock_t schedScan_lock; + + // Flag keeps track of wiphy suspend/resume + v_BOOL_t isWiphySuspended; + + // Indicates about pending sched_scan results + v_BOOL_t isSchedScanUpdatePending; + +#ifdef MSM_PLATFORM + /* DDR bus bandwidth compute timer + */ + vos_timer_t bus_bw_timer; + int cur_vote_level; + spinlock_t bus_bw_lock; + int cur_rx_level; + uint64_t prev_rx; + int cur_tx_level; + uint64_t prev_tx; +#endif + + /* VHT80 allowed*/ + v_BOOL_t isVHT80Allowed; + + struct completion ready_to_suspend; + /* defining the solution type */ + v_U32_t target_type; + + /* defining the firmware version */ + v_U32_t target_fw_version; + v_U32_t dfs_radar_found; + + /* defining the chip/rom version */ + v_U32_t target_hw_version; + /* defining the chip/rom revision */ + v_U32_t target_hw_revision; + /* chip/rom name */ + const char *target_hw_name; + struct regulatory reg; +#ifdef FEATURE_WLAN_CH_AVOID + v_U16_t unsafe_channel_count; + v_U16_t unsafe_channel_list[NUM_20MHZ_RF_CHANNELS]; +#endif /* FEATURE_WLAN_CH_AVOID */ + + v_U8_t max_intf_count; + v_U8_t current_intf_count; +#ifdef WLAN_FEATURE_LPSS + v_U8_t lpss_support; +#endif + uint8_t ap_arpns_support; + tSirScanType ioctl_scan_mode; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + adf_os_work_t sta_ap_intf_check_work; +#endif + + struct work_struct sap_start_work; + bool is_sap_restart_required; + bool is_sta_connection_pending; + spinlock_t sap_update_info_lock; + spinlock_t sta_update_info_lock; + + v_U8_t dev_dfs_cac_status; + + v_BOOL_t btCoexModeSet; +#ifdef FEATURE_GREEN_AP + hdd_green_ap_ctx_t *green_ap_ctx; +#endif + fw_log_info fw_log_settings; +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + vos_timer_t skip_acs_scan_timer; + v_U8_t skip_acs_scan_status; +#endif + + vos_wake_lock_t sap_dfs_wakelock; + atomic_t sap_dfs_ref_cnt; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + v_BOOL_t is_extwow_app_type1_param_set; + v_BOOL_t is_extwow_app_type2_param_set; + v_BOOL_t ext_wow_should_suspend; + struct completion ready_to_extwow; +#endif + + /* Time since boot up to extscan start (in micro seconds) */ + v_U64_t ext_scan_start_since_boot; + + /* RoC request queue and work */ + struct delayed_work rocReqWork; + hdd_list_t hdd_roc_req_q; + bool mcc_mode; + unsigned long g_event_flags; + uint8_t miracast_value; + /* Dfs lock used to syncronize on sap channel switch during + * radar found indication and application triggered channel + * switch + */ + spinlock_t dfs_lock; + +#ifdef FEATURE_WLAN_EXTSCAN + struct hdd_ext_scan_context ext_scan_context; +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + struct hdd_ll_stats_context ll_stats_context; +#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_FEATURE_MEMDUMP + uint8_t *fw_dump_loc; + uint32_t dump_loc_paddr; + vos_timer_t memdump_cleanup_timer; + struct mutex memdump_lock; + bool memdump_in_progress; +#endif /* WLAN_FEATURE_MEMDUMP */ + + /* number of rf chains supported by target */ + uint32_t num_rf_chains; + + /* Is htTxSTBC supported by target */ + uint8_t ht_tx_stbc_supported; + +#ifdef WLAN_NS_OFFLOAD + /* IPv6 notifier callback for handling NS offload on change in IP */ + struct notifier_block ipv6_notifier; +#endif + /* IPv4 notifier callback for handling ARP offload on change in IP */ + struct notifier_block ipv4_notifier; + +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS + struct hdd_offloaded_packets_ctx op_ctx; +#endif + bool per_band_chainmask_supp; + uint16_t hdd_txrx_hist_idx; + struct hdd_tx_rx_histogram *hdd_txrx_hist; + struct hdd_runtime_pm_context runtime_context; + bool hbw_requested; + uint8_t supp_2g_chain_mask; + uint8_t supp_5g_chain_mask; + /* Current number of TX X RX chains being used */ + enum antenna_mode current_antenna_mode; +}; + +/*--------------------------------------------------------------------------- + Function declarations and documentation + -------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +void wlan_hdd_check_sta_ap_concurrent_ch_intf(void *sta_pAdapter); +#endif + +const char* hdd_device_mode_to_string(uint8_t device_mode); + +VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t** ppAdapterNode); + +VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode, + hdd_adapter_list_node_t** pNextAdapterNode); + +VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode); + +VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t** ppAdapterNode); + +VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode); + +VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode); + +hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, + const char* name, tSirMacAddr macAddr, + tANI_U8 rtnl_held ); +VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held ); +VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx ); +void hdd_dump_concurrency_info(hdd_context_t *pHddCtx); +hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name ); +hdd_adapter_t * hdd_get_adapter_by_vdev( hdd_context_t *pHddCtx, + tANI_U32 vdev_id ); +hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx, tSirMacAddr macAddr ); +hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx ); +VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ); +hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode ); +void hdd_deinit_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + bool rtnl_held); +VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + const v_BOOL_t bCloseSession); +void hdd_set_station_ops( struct net_device *pWlanDev ); +tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx); +void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr); +v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode ); + +void hdd_set_conparam ( v_UINT_t newParam ); +tVOS_CON_MODE hdd_get_conparam( void ); + +void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext); +v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx); +void hdd_abort_mac_scan(hdd_context_t* pHddCtx, tANI_U8 sessionId, + eCsrAbortReason reason); +void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); +void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); + +void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id); +void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, + tVOS_CON_MODE mode); +void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, + tVOS_CON_MODE mode); +void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, + tVOS_CON_MODE mode); +void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, + tVOS_CON_MODE mode); +uint8_t wlan_hdd_get_active_session_count(hdd_context_t *pHddCtx); +void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter); +void hdd_prevent_suspend(uint32_t reason); +void hdd_allow_suspend(uint32_t reason); +void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason); +bool hdd_is_ssr_required(void); +void hdd_set_ssr_required(e_hdd_ssr_required value); + +VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx); +VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type); + +void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy); +VOS_STATUS hdd_setIbssPowerSaveParams(hdd_adapter_t *pAdapter); +VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx); +void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx); +void hdd_set_pwrparams(hdd_context_t *pHddCtx); +void hdd_reset_pwrparams(hdd_context_t *pHddCtx); +int wlan_hdd_validate_context(hdd_context_t *pHddCtx); +v_BOOL_t hdd_is_valid_mac_address(const tANI_U8* pMacAddr); +VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx); +void hdd_ipv4_notifier_work_queue(struct work_struct *work); +bool hdd_isConnectionInProgress(hdd_context_t *pHddCtx); +#ifdef WLAN_FEATURE_PACKET_FILTERING +int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, tANI_U8 sessionId); +#endif + +#ifdef WLAN_NS_OFFLOAD +void hdd_ipv6_notifier_work_queue(struct work_struct *work); +#endif + + +void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx); + +int hdd_wmmps_helper(hdd_adapter_t *pAdapter, tANI_U8 *ptr); +int wlan_hdd_set_mc_rate(hdd_adapter_t *pAdapter, int targetRate); +#ifdef MSM_PLATFORM +void hdd_start_bus_bw_compute_timer(hdd_adapter_t *pAdapter); +void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *pAdapter); +#else +static inline void hdd_start_bus_bw_compute_timer(hdd_adapter_t *pAdapter) +{ + return; +} + +static inline void hdd_stop_bus_bw_computer_timer(hdd_adapter_t *pAdapter) +{ + return; +} +#endif + +int hdd_wlan_startup(struct device *dev, void *hif_sc); +void __hdd_wlan_exit(void); +int hdd_wlan_notify_modem_power_state(int state); +#ifdef QCA_HT_2040_COEX +int hdd_wlan_set_ht2040_mode(hdd_adapter_t *pAdapter, v_U16_t staId, + v_MACADDR_t macAddrSTA, int width); +#endif + +VOS_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *pHddCtx); + + +#ifdef WLAN_FEATURE_LPSS +void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter, + hdd_station_ctx_t *pHddStaCtx, + v_U8_t is_on, + v_U8_t is_connected); +void wlan_hdd_send_version_pkg(v_U32_t fw_version, + v_U32_t chip_id, + const char *chip_name); +void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx); +#endif +void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len); +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, v_U8_t enable); +#endif + +hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter, + bool check_start_bss); + +boolean hdd_is_5g_supported(hdd_context_t * pHddCtx); + +int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter); + +#ifdef FEATURE_GREEN_AP +void hdd_wlan_green_ap_mc(hdd_context_t *pHddCtx, + hdd_green_ap_event_t event); +#endif + +#ifdef WLAN_FEATURE_STATS_EXT +void wlan_hdd_cfg80211_stats_ext_init(hdd_context_t *pHddCtx); +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +void wlan_hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx); +#endif + +void hdd_update_macaddr(hdd_config_t *cfg_ini, v_MACADDR_t hw_macaddr); +#if defined(FEATURE_WLAN_LFR) && defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) +void wlan_hdd_disable_roaming(hdd_adapter_t *pAdapter); +void wlan_hdd_enable_roaming(hdd_adapter_t *pAdapter); +#endif +int hdd_set_miracast_mode(hdd_adapter_t *pAdapter, tANI_U8 *command); +VOS_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter, + hdd_adapter_t *ap_adapter, + tCsrRoamProfile *roam_profile, + tScanResultHandle *scan_cache, + bool *concurrent_chnl_same); +#ifdef WLAN_FEATURE_MBSSID +void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter); +void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter); +#else +static inline void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) {} +static inline void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) {} +#endif +int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed); +int hdd_wlan_go_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, + uint32_t set_value); +int hdd_wlan_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, + uint32_t set_value); +int hdd_set_mas(hdd_adapter_t *hostapd_adapter, uint8_t filter_type); +uint8_t hdd_is_mcc_in_24G(hdd_context_t *hdd_ctx); +bool wlan_hdd_get_fw_state(hdd_adapter_t *adapter); + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +static inline bool hdd_link_layer_stats_supported(void) +{ + return true; +} + +/** + * hdd_init_ll_stats_ctx() - initialize link layer stats context + * @hdd_ctx: Pointer to hdd context + * + * Return: none + */ +static inline void hdd_init_ll_stats_ctx(hdd_context_t *hdd_ctx) +{ + init_completion(&hdd_ctx->ll_stats_context.response_event); + hdd_ctx->ll_stats_context.request_bitmap = 0; + + return; +} +#else +static inline bool hdd_link_layer_stats_supported(void) +{ + return false; +} +static inline void hdd_init_ll_stats_ctx(hdd_context_t *hdd_ctx) +{ + return; +} +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +void hdd_get_fw_version(hdd_context_t *hdd_ctx, + uint32_t *major_spid, uint32_t *minor_spid, + uint32_t *siid, uint32_t *crmid); + +bool hdd_is_memdump_supported(void); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) +static inline void +hdd_set_needed_headroom(struct net_device *wlan_dev, uint16_t len) +{ + wlan_dev->needed_headroom = len; +} +#else +static inline void +hdd_set_needed_headroom(struct net_device *wlan_dev, uint16_t len) +{ + /* no-op */ +} +#endif /* LINUX_VERSION_CODE */ + +#ifdef QCA_CONFIG_SMP +int wlan_hdd_get_cpu(void); +#else +static inline int wlan_hdd_get_cpu(void) +{ + return 0; +} +#endif + +const char *hdd_get_fwpath(void); + +uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, + uint8_t bw_offset); + +#ifdef QCA_LL_TX_FLOW_CT +void wlan_hdd_clean_tx_flow_control_timer(hdd_context_t *hddctx, + hdd_adapter_t *adapter); +#else +static inline void +wlan_hdd_clean_tx_flow_control_timer(hdd_context_t *hddctx, + hdd_adapter_t *adapter) +{ +} +#endif + +void hdd_connect_result(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 * resp_ie, size_t resp_ie_len, + u16 status, gfp_t gfp); + +int wlan_hdd_init_tx_rx_histogram(hdd_context_t *pHddCtx); +void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *pHddCtx); +void wlan_hdd_display_tx_rx_histogram(hdd_context_t *pHddCtx); +void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *pHddCtx); + +void hdd_runtime_suspend_init(hdd_context_t *); +void hdd_runtime_suspend_deinit(hdd_context_t *); + +int wlan_hdd_update_txrx_chain_mask(hdd_context_t *hdd_ctx, + uint8_t chain_mask); + +#endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mdns_offload.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mdns_offload.h new file mode 100644 index 000000000000..5b5d8e817a95 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mdns_offload.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_MDNS_OFFLOAD_H__ +#define __WLAN_HDD_MDNS_OFFLOAD_H__ + +/** + * wlan_hdd_mdns_offload.h - WLAN HDD mDNS Offload API + */ + +#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 + +#endif /* __WLAN_HDD_MDNS_OFFLOAD_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h new file mode 100644 index 000000000000..c3fa8391a9ea --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * DOC : wlan_hdd_memdump.h + * + * WLAN Host Device Driver file for dumping firmware memory + * + */ + +#if !defined(WLAN_HDD_MEMDUMP_H) +#define WLAN_HDD_MEMDUMP_H + +#include "wlan_hdd_main.h" + +#ifdef WLAN_FEATURE_MEMDUMP +/** + * enum qca_wlan_vendor_attr_memory_dump - values for memory dump attributes + * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID - Invalid + * @QCA_WLAN_VENDOR_ATTR_REQUEST_ID - Indicate request ID + * @QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE - Indicate size of the memory dump + * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST - To keep track of the last enum + * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_MAX - max value possible for this type + * + * enum values are used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP sub command. + */ +enum qca_wlan_vendor_attr_memory_dump { + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_REQUEST_ID = 1, + QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE = 2, + + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_MAX = + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST - 1, +}; + +/* Size of fw memory dump is estimated to be 327680 bytes */ +#define FW_MEM_DUMP_SIZE 327680 +#define FW_DRAM_LOCATION 0x00400000 +#define FW_MEM_DUMP_REQ_ID 1 +#define FW_MEM_DUMP_NUM_SEG 1 +#define MEMDUMP_COMPLETION_TIME_MS 5000 + +int memdump_init(void); +void memdump_deinit(void); +int wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); +#else +static inline int memdump_init(void) +{ + return -ENOTSUPP; +} + +static inline void memdump_deinit(void) +{ +} + +static inline int wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + return -ENOTSUPP; +} +#endif + +#endif /* if !defined(WLAN_HDD_MEMDUMP_H)*/ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mib.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mib.h new file mode 100644 index 000000000000..baceec8b3a80 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_mib.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( WLAN_HDD_MIB_h__ ) +#define WLAN_HDD_MIB_h__ + + +#include + +typedef enum +{ + eMib_dot11DesiredBssType_infrastructure = 1, + eMib_dot11DesiredBssType_independent = 2, + eMib_dot11DesiredBssType_infra_ap =3, + eMib_dot11DesiredBssType_any = 4 + +} eMib_dot11DesiredBssType; + + +/** This is the maximum number of BSSIDs supported in the + dot11DesiredBssidList. All the code operates off of + this maximum BSSID list count. */ +#define MIB_DOT11_DESIRED_BSSID_LIST_MAX_COUNT ( 1 ) + +typedef struct +{ + v_U32_t cEntries; + + v_MACADDR_t BSSIDs[ MIB_DOT11_DESIRED_BSSID_LIST_MAX_COUNT ]; + +} sMib_dot11DesiredBssidList; + + + +/** This is the maximum number of SSIDs supported in the + dot11DesiredSsidList. All the code operates off of + this maximum SSID list count. */ + +#define MIB_DOT11_DESIRED_SSID_LIST_MAX_COUNT ( 1 ) + +#define MIB_DOT11_SSID_MAX_LENGTH ( 32 ) + +typedef struct +{ + v_U32_t ssidLength; + v_U8_t ssid[ MIB_DOT11_SSID_MAX_LENGTH ]; + +} sDot11Ssid; + +typedef struct +{ + v_U32_t cEntries; + + sDot11Ssid SSIDs[ MIB_DOT11_DESIRED_SSID_LIST_MAX_COUNT ]; + +} sMib_dot11DesiredSsidList; + + + +typedef enum +{ + // these are bitmasks.... + eMib_dot11AutoConfigEnabled_None = 0U, + eMib_dot11AutoConfigEnabled_Phy = 0x00000001U, + eMib_dot11AutoConfigEnabled_Mac = 0x00000002U + +} eMib_dot11AutoConfigEnabled; + + + +#define MIB_DOT11_SUPPORTED_PHY_TYPES_MAX_COUNT ( 3 ) + +typedef enum tagMib_dot11PhyType +{ + eMib_dot11PhyType_11b, + eMib_dot11PhyType_11a, + eMib_dot11PhyType_11g, + eMib_dot11PhyType_all +} eMib_dot11PhyType; + +typedef struct tagMib_dot11SupportedPhyTypes +{ + v_U32_t cEntries; + eMib_dot11PhyType phyTypes[ MIB_DOT11_SUPPORTED_PHY_TYPES_MAX_COUNT ]; +} sMib_dot11SupportedPhyTypes; + + +typedef enum +{ + eMib_DevicePowerState_D0, + eMib_DevicePowerState_D1, + eMib_DevicePowerState_D2, + eMib_DevicePowerState_D3 + +} eMib_DevicePowerState; + + +typedef enum +{ + eMib_dot11NICPowerState_OFF = VOS_FALSE, + eMib_dot11NICPowerState_ON = VOS_TRUE + +} eMib_dot11NICPowerState; + + +typedef enum +{ + eMib_dot11HardwarePHYState_OFF = VOS_FALSE, + eMib_dot11HardwarePHYState_ON = VOS_TRUE + +} eMib_dot11HardwarePHYState; + + +typedef enum +{ + eMib_dot11PowerSavingLevel_None, + eMib_dot11PowerSavingLevel_MaxPS, + eMib_dot11PowerSavingLevel_FastPS, + eMib_dot11PowerSavingLevel_MaximumLevel + +} eMib_dot11PowerSavingLevel; + + +#define MIB_DOT11_MAC_EXCLUSION_LIST_MAX_COUNT 4 +typedef struct +{ + v_U32_t cEntries; + + v_MACADDR_t macAddrs[ MIB_DOT11_MAC_EXCLUSION_LIST_MAX_COUNT ]; + +} sMib_dot11MacExcludeList; + +#define MIB_DOT11_PRIVACY_EXEMPT_LIST_MAX_COUNT 32 + +typedef enum +{ + eMib_dot11ExemptionAction_Always, + eMib_dot11ExemptionAction_OnKeyMapUnavailable + +}eMib_dot11ExemptAction; + +typedef enum +{ + eMib_dot11ExemptPacket_Unicast, + eMib_dot11ExemptPacket_Multicast, + eMib_dot11ExemptPacket_Both + +}eMib_dot11ExemptPacket; + +typedef struct +{ + v_U16_t uEtherType; + eMib_dot11ExemptAction exemptAction; + eMib_dot11ExemptPacket exemptPacket; + +}sMib_dot11PrivacyExemption; + +typedef struct +{ + v_U32_t cEntries; + + sMib_dot11PrivacyExemption privacyExemptList[ MIB_DOT11_PRIVACY_EXEMPT_LIST_MAX_COUNT ]; + +} sMib_dot11PrivacyExemptionList; + +typedef struct sHddMib_s +{ + eMib_dot11DesiredBssType mibDot11DesiredBssType; + + sMib_dot11DesiredBssidList mibDot11DesiredBssidList; + + sMib_dot11DesiredSsidList mibDot11DesiredSsidList; + + eMib_dot11AutoConfigEnabled mibDot11AutoConfigEnabled; + + // the device power state for the device (the D-state... you know D0, D1, D2, etc. + eMib_DevicePowerState mibDevicePowerState; + + // dot11NICPowerState is really the on/off state of the PHY. This can be + /* Manipulated through OIDs like a software control for radio on/off. */ + eMib_dot11NICPowerState mibDot11NICPowerState; + + // Hardware PHY state is the on/off state of the hardware PHY. + eMib_dot11HardwarePHYState mibDot11HardwarePHYState; + + // dot11 Power Saving level is the 802.11 power saving level/state for the 802.11 + // NIC. Typically this is mapped to 802.11 BMPS in some fashion. We are not going + // to disappoint; the Libra NIC maps these to different BMPS settings. + eMib_dot11PowerSavingLevel mibDot11PowerSavingLevel; + + sMib_dot11MacExcludeList mibDot11MacExcludeList; + + sMib_dot11PrivacyExemptionList mibDot11PrivacyExemptionList; + + sMib_dot11SupportedPhyTypes mibDot11SupportedPhyTypes; + eMib_dot11PhyType mibDot11CurrentPhyType; + + v_BOOL_t dot11IbssJoinOnly; + v_BOOL_t HiddenNetworkEnabled; + + +}sHddMib_t; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_nan.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_nan.h new file mode 100644 index 000000000000..b3015e258f9d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_nan.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef __WLAN_HDD_NAN_H +#define __WLAN_HDD_NAN_H +/*========================================================================= + + \file wlan_hdd_nan.h + + \brief Linux HDD NAN include file + +==========================================================================*/ + +void wlan_hdd_cfg80211_nan_init(hdd_context_t *pHddCtx); + +#endif /* __WLAN_HDD_NAN_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_oemdata.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_oemdata.h new file mode 100644 index 000000000000..1d4ba472473c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_oemdata.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/**=========================================================================== + + \file wlan_hdd_oemdata.h + + \brief Internal includes for the oem data + + ==========================================================================*/ + + +#ifndef __WLAN_HDD_OEM_DATA_H__ +#define __WLAN_HDD_OEM_DATA_H__ + +#ifndef OEM_DATA_REQ_SIZE +#define OEM_DATA_REQ_SIZE 280 +#endif + +#ifndef OEM_DATA_RSP_SIZE +#define OEM_DATA_RSP_SIZE 1724 +#endif + +#define OEM_APP_SIGNATURE_LEN 16 +#define OEM_APP_SIGNATURE_STR "QUALCOMM-OEM-APP" + +#define OEM_TARGET_SIGNATURE_LEN 8 +#define OEM_TARGET_SIGNATURE "QUALCOMM" + +#define OEM_CAP_MAX_NUM_CHANNELS 128 + +typedef enum +{ + /* Error null context */ + OEM_ERR_NULL_CONTEXT = 1, + + /* OEM App is not registered */ + OEM_ERR_APP_NOT_REGISTERED, + + /* Invalid signature */ + OEM_ERR_INVALID_SIGNATURE, + + /* Invalid message type */ + OEM_ERR_NULL_MESSAGE_HEADER, + + /* Invalid message type */ + OEM_ERR_INVALID_MESSAGE_TYPE, + + /* Invalid length in message body */ + OEM_ERR_INVALID_MESSAGE_LENGTH +} eOemErrorCode; + +int oem_activate_service(void *pAdapter); + +int iw_get_oem_data_cap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 major; + tANI_U8 minor; + tANI_U8 patch; + tANI_U8 build; +} tDriverVersion; + +typedef PACKED_PRE struct PACKED_POST +{ + /* Signature of chip set vendor, e.g. QUALCOMM */ + tANI_U8 oem_target_signature[OEM_TARGET_SIGNATURE_LEN]; + tANI_U32 oem_target_type; /* Chip type */ + tANI_U32 oem_fw_version; /* FW version */ + tDriverVersion driver_version; /* CLD version */ + tANI_U16 allowed_dwell_time_min; /* Channel dwell time - allowed min */ + tANI_U16 allowed_dwell_time_max; /* Channel dwell time - allowed max */ + tANI_U16 curr_dwell_time_min; /* Channel dwell time - current min */ + tANI_U16 curr_dwell_time_max; /* Channel dwell time - current max */ + tANI_U16 supported_bands; /* 2.4G or 5G Hz */ + tANI_U16 num_channels; /* Num of channels IDs to follow */ + tANI_U8 channel_list[OEM_CAP_MAX_NUM_CHANNELS]; /* List of channel IDs */ +} t_iw_oem_data_cap; + +typedef PACKED_PRE struct PACKED_POST +{ + /* channel id */ + tANI_U32 chan_id; + + /* reserved0 */ + tANI_U32 reserved0; + + /* Primary 20 MHz channel frequency in MHz */ + tANI_U32 mhz; + + /* Center frequency 1 in MHz */ + tANI_U32 band_center_freq1; + + /* Center frequency 2 in MHz - valid only for 11acvht 80plus80 mode */ + tANI_U32 band_center_freq2; + + /* channel info described below */ + tANI_U32 info; + + /* contains min power, max power, reg power and reg class id */ + tANI_U32 reg_info_1; + + /* contains antennamax */ + tANI_U32 reg_info_2; +} tHddChannelInfo; + +typedef PACKED_PRE struct PACKED_POST +{ + /* peer mac address */ + tANI_U8 peer_mac_addr[6]; + + /* peer status: 1: CONNECTED, 2: DISCONNECTED */ + tANI_U8 peer_status; + + /* vdev_id for the peer mac */ + tANI_U8 vdev_id; + + /* peer capability: + * 0: RTT/RTT2 + * 1: RTT3(timing Meas Capability) + * 2: RTT3(fine timing Meas Capability) + * Default is 0 + */ + tANI_U32 peer_capability; + + /* reserved0 */ + tANI_U32 reserved0; + + /* channel info on which peer is connected */ + tHddChannelInfo peer_chan_info; +} tPeerStatusInfo; + +#endif //__WLAN_HDD_OEM_DATA_H__ + +#endif //FEATURE_OEM_DATA_SUPPORT diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h new file mode 100644 index 000000000000..7d9f01b7b716 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __P2P_H +#define __P2P_H +/**=========================================================================== + +\file wlan_hdd_p2p.h + +\brief Linux HDD P2P include file + +==========================================================================*/ +#define ACTION_FRAME_TX_TIMEOUT 2000 +#define WAIT_CANCEL_REM_CHAN 1000 +#define WAIT_REM_CHAN_READY 1000 +#define WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX 3000 +#define READY_EVENT_PROPOGATE_TIME 2 +#define ESTIMATED_ROC_DUR_REQD_FOR_ACTION_TX 20 +#define COMPLETE_EVENT_PROPOGATE_TIME 10 + +#define ACTION_FRAME_DEFAULT_WAIT 200 + +#define WLAN_HDD_GET_TYPE_FRM_FC(__fc__) (((__fc__) & 0x0F) >> 2) +#define WLAN_HDD_GET_SUBTYPE_FRM_FC(__fc__) (((__fc__) & 0xF0) >> 4) +#define WLAN_HDD_80211_FRM_DA_OFFSET 4 +#define P2P_WILDCARD_SSID_LEN 7 +#define P2P_WILDCARD_SSID "DIRECT-" + +#define P2P_ROC_DURATION_MULTIPLIER_GO_PRESENT 2 +#define P2P_ROC_DURATION_MULTIPLIER_GO_ABSENT 5 + +#ifdef WLAN_FEATURE_11W +#define WLAN_HDD_SET_WEP_FRM_FC(__fc__) ( (__fc__) = ((__fc__) | 0x40)) +#endif //WLAN_FEATURE_11W + +#define HDD_P2P_MAX_ROC_DURATION 1000 + +enum hdd_rx_flags { + HDD_RX_FLAG_DECRYPTED = 1 << 0, + HDD_RX_FLAG_MMIC_STRIPPED = 1 << 1, + HDD_RX_FLAG_IV_STRIPPED = 1 << 2, +}; + + +#define P2P_POWER_SAVE_TYPE_OPPORTUNISTIC (1 << 0) +#define P2P_POWER_SAVE_TYPE_PERIODIC_NOA (1 << 1) +#define P2P_POWER_SAVE_TYPE_SINGLE_NOA (1 << 2) + +#ifdef WLAN_FEATURE_P2P_DEBUG +typedef enum { P2P_NOT_ACTIVE, + P2P_GO_NEG_PROCESS, + P2P_GO_NEG_COMPLETED, + P2P_CLIENT_CONNECTING_STATE_1, + P2P_GO_COMPLETED_STATE, + P2P_CLIENT_CONNECTED_STATE_1, + P2P_CLIENT_DISCONNECTED_STATE, + P2P_CLIENT_CONNECTING_STATE_2, + P2P_CLIENT_COMPLETED_STATE + }tP2PConnectionStatus; + +extern tP2PConnectionStatus globalP2PConnectionStatus; +#endif + +typedef struct p2p_app_setP2pPs{ + tANI_U8 opp_ps; + tANI_U32 ctWindow; + tANI_U8 count; + tANI_U32 duration; + tANI_U32 interval; + tANI_U32 single_noa_duration; + tANI_U8 psSelection; +}p2p_app_setP2pPs_t; + +int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 *cookie ); + +int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie ); + +int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie); + +int hdd_setP2pPs( struct net_device *dev, void *msgData ); +int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command ); +int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command ); + +void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, + tANI_U32 nFrameLength, tANI_U8* pbFrames, + tANI_U8 frameType, + tANI_U32 rxChan, tANI_S8 rxRssi); + +void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ); +void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess ); +int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter); +void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, + bool channel_type_valid, +#endif + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie ); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) +int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie ); +#else +int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, u64 *cookie ); +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) || defined(WITH_BACKPORTS) +struct wireless_dev* wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, const char *name, + enum nl80211_iftype type, + u32 *flags, struct vif_params *params ); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +struct wireless_dev* wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params ); +#else +struct net_device* wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params ); +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev ); +#else +int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev ); +#endif + +void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter); + +/* Max entry for RoC request */ +#define MAX_ROC_REQ_QUEUE_ENTRY 10 + +void wlan_hdd_roc_request_dequeue(struct work_struct *work); +#endif // __P2P_H diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_packet_filtering.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_packet_filtering.h new file mode 100644 index 000000000000..ad7f76587e81 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_packet_filtering.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/****************************************************************************** +* +* Name: wlan_hdd_packet_filtering.h +* +* Description: Packet Filter Definitions. +* +* +******************************************************************************/ + +#ifndef __WLAN_HDD_PACKET_FILTERING_H__ +#define __WLAN_HDD_PACKET_FILTERING_H__ + + + +#ifdef WLAN_FEATURE_PACKET_FILTERING + +#define HDD_MAX_CMP_PER_PACKET_FILTER 5 +#define HDD_FILTER_IPV6_MC_UC 1 +#define HDD_FILTER_IPV6_MC 0 +#define HDD_FILTER_ID_IPV6_MC 10 +#define HDD_FILTER_ID_IPV6_UC 11 + +#define HDD_IPV6_MC_CMP_DATA 0x33 +#define HDD_IPV6_UC_CMP_DATA 0x01 +#define HDD_IPV6_CMP_DATA_0 0x86 +#define HDD_IPV6_CMP_DATA_1 0xDD + +#define HDD_WLAN_MAC_ADDR_LEN 6 +#define HDD_MAX_NUM_MULTICAST_ADDRESS 10 + +typedef enum +{ + HDD_FILTER_PROTO_TYPE_INVALID = 0, + HDD_FILTER_PROTO_TYPE_MAC = 1, + HDD_FILTER_PROTO_TYPE_ARP = 2, + HDD_FILTER_PROTO_TYPE_IPV4 =3 , + HDD_FILTER_PROTO_TYPE_IPV6 = 4, + HDD_FILTER_PROTO_TYPE_UDP = 5, + HDD_FILTER_PROTO_TYPE_MAX +} eProtoLayer; + +typedef enum +{ + HDD_RCV_FILTER_INVALID = 0, + HDD_RCV_FILTER_SET = 1, + HDD_RCV_FILTER_CLEAR = 2, + HDD_RCV_FILTER_MAX +}eFilterAction; + +typedef enum +{ + HDD_FILTER_CMP_TYPE_INVALID = 0, + HDD_FILTER_CMP_TYPE_EQUAL = 1, + HDD_FILTER_CMP_TYPE_MASK_EQUAL = 2, + HDD_FILTER_CMP_TYPE_NOT_EQUAL = 3, + HDD_FILTER_CMP_TYPE_MASK_NOT_EQUAL = 4, + HDD_FILTER_CMP_TYPE_MAX +}eCompareFlag; + +struct PacketFilterParamsCfg +{ + v_U8_t protocolLayer; + v_U8_t cmpFlag; + v_U8_t dataOffset; + v_U8_t dataLength; + v_U8_t compareData[8]; + v_U8_t dataMask[8]; +}; + +typedef struct +{ + v_U8_t filterAction; + v_U8_t filterId; + v_U8_t numParams; + struct PacketFilterParamsCfg paramsData [HDD_MAX_CMP_PER_PACKET_FILTER]; +}tPacketFilterCfg, *tpPacketFilterCfg; + +typedef v_U8_t tHddMacAddr[HDD_WLAN_MAC_ADDR_LEN]; + +typedef struct +{ + v_U8_t mcastBcastFilterSetting; + v_U8_t mcast_addr_cnt; + tHddMacAddr multicastAddr[HDD_MAX_NUM_MULTICAST_ADDRESS]; +} tRcvFltMcAddrList, *tpRcvFltMcAddrList; + +#endif +#endif // __WLAN_HDD_PACKET_FILTERING_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_power.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_power.h new file mode 100644 index 000000000000..511db6f18594 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_power.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_POWER_H +#define __WLAN_HDD_POWER_H + +/**=========================================================================== + + \file wlan_hdd_power.h + + \brief Linux HDD Power + + ==========================================================================*/ + + +/*-------------------------------------------------------------------------- + * Include Files + *------------------------------------------------------------------------*/ +#include "wlan_hdd_main.h" + +/*--------------------------------------------------------------------------- + * Preprocessor definitions and constants + *-------------------------------------------------------------------------*/ + //gEnableSuspend = 1 in INI file implies suspend to standby + #define WLAN_MAP_SUSPEND_TO_STANDBY 1 + + //gEnableSuspend = 2 in INI file implies suspend to deep sleep + #define WLAN_MAP_SUSPEND_TO_DEEP_SLEEP 2 + + //gEnableSuspend = 3 in INI file implies suspend to set MCAST/BCAST filter + #define WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER 3 + + //gEnableDriverStop = 1 implies map driver stop to standby + #define WLAN_MAP_DRIVER_STOP_TO_STANDBY 1 + + /* gEnableDriverStop = 2 implies map driver stop to deep sleep */ + #define WLAN_MAP_DRIVER_STOP_TO_DEEP_SLEEP 2 + + //Maximum time (ms) to wait for standby to complete + #define WLAN_WAIT_TIME_STANDBY 3000 + + //Maximum time (ms) to wait for full pwr to complete + #define WLAN_WAIT_TIME_FULL_PWR 3000 + + +/*--------------------------------------------------------------------------- + * Type declarations + *-------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + * Function declarations and documentation + * ------------------------------------------------------------------------*/ + eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx); + VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, + hdd_adapter_t* pAdapter); + VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx); + VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, + hdd_adapter_t* pAdapter); +#ifdef CONFIG_HAS_EARLYSUSPEND + VOS_STATUS hdd_wlan_reset(void); + VOS_STATUS hdd_wlan_reset_initialization(void) ; +#endif + /* SSR shutdown & re-init functions */ + VOS_STATUS hdd_wlan_shutdown(void); + VOS_STATUS hdd_wlan_re_init(void *hif_sc); + +void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter); +VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t* pAdapter, int fenable); +/* + * Function: hdd_conf_hostoffload + * Central function to configure the supported offloads, + * either enable or disable them. + */ +void hdd_conf_hostoffload(hdd_adapter_t * pAdapter, v_BOOL_t fenable); + +int wlan_hdd_ipv4_changed(struct notifier_block *nb, + unsigned long data, void *arg); + +int wlan_hdd_ipv6_changed(struct notifier_block *nb, + unsigned long data, void *arg); + + +#endif // if !defined __WLAN_QCT_DRIVER_H diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h new file mode 100644 index 000000000000..1f863c44c2ba --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_softap_tx_rx.h @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( WLAN_HDD_SOFTAP_TX_RX_H ) +#define WLAN_HDD_SOFTAP_TX_RX_H + +/**=========================================================================== + + \file wlan_hdd_softap_tx_rx.h + + \brief Linux HDD SOFTAP Tx/RX APIs + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ +#define HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN (82*2) +#define HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN (78*2) +#define HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN (74*2) +#define HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN (70*2) + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Function declarations and documentation + -------------------------------------------------------------------------*/ + +/**============================================================================ + @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS for + transmitting packets + + @param skb : [in] pointer to OS packet (sk_buff) + @param dev : [in] pointer to Libra softap network device + + @return : NET_XMIT_DROP if packets are dropped + : NET_XMIT_SUCCESS if packet is enqueued successfully + ===========================================================================*/ +extern int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); + +/**============================================================================ + @brief hdd_softap_tx_timeout() - Function called by OS if there is any + timeout during transmission. Since HDD simply enqueues packet + and returns control to OS right away, this would never be invoked + + @param dev : [in] pointer to Libra network device + @return : None + ===========================================================================*/ +extern void hdd_softap_tx_timeout(struct net_device *dev); + +/**============================================================================ + @brief hdd_softap_stats() - Function registered with the Linux OS for + device TX/RX statistics + + @param dev : [in] pointer to Libra network device + + @return : pointer to net_device_stats structure + ===========================================================================*/ +extern struct net_device_stats* hdd_softap_stats(struct net_device *dev); + +/**============================================================================ + @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deinit + @param pmacAddrSTA : [in] pointer to the MAC address of the station + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA); + +/**============================================================================ + @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a station + in Tx/RX modules in HDD + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deinit + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId ); + +/**============================================================================ + @brief hdd_tx_complete_cbk() - Callback function invoked by TL + to indicate that a packet has been transmitted across the SDIO bus + successfully. OS packet resources can be released after this cbk. + + @param vosContext : [in] pointer to VOS context + @param pVosPacket : [in] pointer to VOS packet (containing skb) + @param vosStatusIn : [in] status of the transmission + + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext, + vos_pkt_t *pVosPacket, + VOS_STATUS vosStatusIn ); + +/**============================================================================ + @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to + fetch a packet for transmission. + + @param vosContext : [in] pointer to VOS context + @param staId : [in] Station for which TL is requesting a pkt + @param ucAC : [in] pointer to access category requested by TL + @param pVosPacket : [out] pointer to VOS packet packet pointer + @param pPktMetaInfo : [out] pointer to meta info for the pkt + + @return : VOS_STATUS_E_EMPTY if no packets to transmit + : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext, + v_U8_t *pStaId, + WLANTL_ACEnumType ucAC, + vos_pkt_t **ppVosPacket, + WLANTL_MetaInfoType *pPktMetaInfo ); + +/**============================================================================ + @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the + case where VOS packets are not available at the time of the call to get + packets. This callback function is invoked by VOS when packets are + available. + + @param pVosPacket : [in] pointer to VOS packet + @param userData : [in] opaque user data that was passed initially + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + =============================================================================*/ +extern VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket, + v_VOID_t *userData ); + +/**============================================================================ + @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL. + TL will call this to notify the HDD when a packet was received + for a registered STA. + + @param vosContext : [in] pointer to VOS context + @param rxBufChain : [in] pointer to adf_nbuf rx chain + @param staId : [in] Station Id + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_rx_packet_cbk(v_VOID_t *vosContext, + adf_nbuf_t rxBufChain, + v_U8_t staId); + +/**============================================================================ + @brief hdd_softap_DeregisterSTA - Deregister a station from TL block + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deregister + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ); + +/**============================================================================ + @brief hdd_softap_RegisterSTA - Register a station into TL block + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deregister + @param fAuthRequired: [in] Station requires further security negotiation or not + @param fPrivacyBit : [in] privacy bit needs to be set or not + @param ucastSig : [in] Unicast Signature send to TL + @param bcastSig : [in] Broadcast Signature send to TL + @param pPeerMacAddress : [in] station MAC address + @param fWmmEnabled : [in] Wmm enabled sta or not + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + =========================================================================== */ +extern VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter, + v_BOOL_t fAuthRequired, + v_BOOL_t fPrivacyBit, + v_U8_t staId, + v_U8_t ucastSig, + v_U8_t bcastSig, + v_MACADDR_t *pPeerMacAddress, + v_BOOL_t fWmmEnabled); + +/**============================================================================ + @brief hdd_softap_Register_BC_STA - Register a default broadcast station into TL block + + @param pAdapter : [in] pointer to adapter context + @param fPrivacyBit : [in] privacy bit needs to be set or not + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + =========================================================================== */ +extern VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit); + +/**============================================================================ + @brief hdd_softap_DeregisterSTA - DeRegister the default broadcast station into TL block + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + =========================================================================== */ +extern VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter); + +/**============================================================================ + @brief hdd_softap_stop_bss - Helper function to stop bss and do cleanup in HDD and TL + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + =========================================================================== */ +extern VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pHostapdAdapter); + + +/**============================================================================ + @brief hdd_softap_change_STA_state - Helper function to change station state by MAC address + + @param pAdapter : [in] pointer to adapter context + @param pDestMacAddress : [in] pointer to station MAC address + @param state : [in] new station state + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + =========================================================================== */ +extern VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state); + +/**============================================================================ + @brief hdd_softap_GetStaId - Helper function to get station Id from MAC address + + @param pAdapter : [in] pointer to adapter context + @param pDestMacAddress : [in] pointer to station MAC address + @param staId : [out] station id + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + =========================================================================== */ +extern VOS_STATUS hdd_softap_GetStaId( hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId); + +#ifdef QCA_LL_TX_FLOW_CT +/**============================================================================ + @brief hdd_softap_tx_resume_timer_expired_handler() - Resume OS TX Q timer + expired handler for SAP and P2P GO interface. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully for SAP and P2P GO interface. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context); + +/**============================================================================ + @brief hdd_softap_tx_resume_cb() - Resume OS TX Q. + Q was stopped due to WLAN TX path low resource condition + + @param adapter_context : [in] pointer to vdev adapter + @param tx_resume : [in] TX Q resume trigger + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_cb(void *adapter_context, + v_BOOL_t tx_resume); +#endif /* QCA_LL_TX_FLOW_CT */ +#endif // end #if !defined( WLAN_HDD_SOFTAP_TX_RX_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h new file mode 100644 index 000000000000..86558bfbd95b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __HDD_TDSL_H +#define __HDD_TDSL_H +/**=========================================================================== + +\file wlan_hdd_tdls.h + +\brief Linux HDD TDLS include file +==========================================================================*/ + +#ifdef FEATURE_WLAN_TDLS + +#define MAX_NUM_TDLS_PEER 3 + +#define TDLS_SUB_DISCOVERY_PERIOD 100 + +#define TDLS_MAX_DISCOVER_REQS_PER_TIMER 1 + +#define TDLS_DISCOVERY_PERIOD 3600000 + +#define TDLS_TX_STATS_PERIOD 3600000 + +#define TDLS_IMPLICIT_TRIGGER_PKT_THRESHOLD 100 + +#define TDLS_RX_IDLE_TIMEOUT 5000 + +#define TDLS_RSSI_TRIGGER_HYSTERESIS 50 + +/* before UpdateTimer expires, we want to timeout discovery response. +should not be more than 2000 */ +#define TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE 1000 + +#define TDLS_CTX_MAGIC 0x54444c53 // "TDLS" + +#define TDLS_MAX_SCAN_SCHEDULE 10 +#define TDLS_MAX_SCAN_REJECT 5 +#define TDLS_DELAY_SCAN_PER_CONNECTION 100 +#define TDLS_MAX_CONNECTED_PEERS_TO_ALLOW_SCAN 1 + +#define TDLS_IS_CONNECTED(peer) \ + ((eTDLS_LINK_CONNECTED == (peer)->link_status) || \ + (eTDLS_LINK_TEARING == (peer)->link_status)) + +/* bit mask flag for tdls_option to FW */ +#define ENA_TDLS_OFFCHAN (1 << 0) /* TDLS Off Channel support */ +#define ENA_TDLS_BUFFER_STA (1 << 1) /* TDLS Buffer STA support */ +#define ENA_TDLS_SLEEP_STA (1 << 2) /* TDLS Sleep STA support */ +#define TDLS_SEC_OFFCHAN_OFFSET_0 0 +#define TDLS_SEC_OFFCHAN_OFFSET_40PLUS 40 +#define TDLS_SEC_OFFCHAN_OFFSET_40MINUS (-40) +#define TDLS_SEC_OFFCHAN_OFFSET_80 80 +#define TDLS_SEC_OFFCHAN_OFFSET_160 160 + +#define TDLS_PEER_LIST_SIZE 256 + +typedef struct +{ + tANI_U32 tdls; + tANI_U32 tx_period_t; + tANI_U32 tx_packet_n; + tANI_U32 discovery_period_t; + tANI_U32 discovery_tries_n; + tANI_U32 idle_timeout_t; + tANI_U32 idle_packet_n; + tANI_U32 rssi_hysteresis; + tANI_S32 rssi_trigger_threshold; + tANI_S32 rssi_teardown_threshold; + tANI_S32 rssi_delta; +} tdls_config_params_t; + +typedef struct +{ + struct wiphy *wiphy; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev; +#endif + struct cfg80211_scan_request *scan_request; + int magic; + int attempt; + int reject; + struct delayed_work tdls_scan_work; +} tdls_scan_context_t; + +typedef enum { + eTDLS_SUPPORT_NOT_ENABLED = 0, + eTDLS_SUPPORT_DISABLED, /* suppress implicit trigger and not respond to the peer */ + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY, /* suppress implicit trigger, but respond to the peer */ + eTDLS_SUPPORT_ENABLED, /* implicit trigger */ + /* External control means implicit trigger + * but only to a peer mac configured by user space. + */ + eTDLS_SUPPORT_EXTERNAL_CONTROL +} eTDLSSupportMode; + +enum tdls_spatial_streams { + TDLS_NSS_1x1_MODE = 0, + TDLS_NSS_2x2_MODE = 0xff, +}; + +/** + * enum tdls_nss_transition_type - TDLS NSS transition states + * @TDLS_NSS_TRANSITION_UNKNOWN: default state + * @TDLS_NSS_TRANSITION_2x2_to_1x1: transition from 2x2 to 1x1 stream + * @TDLS_NSS_TRANSITION_1x1_to_2x2: transition from 1x1 to 2x2 stream + */ +enum tdls_nss_transition_type { + TDLS_NSS_TRANSITION_UNKNOWN = 0, + TDLS_NSS_TRANSITION_2x2_to_1x1, + TDLS_NSS_TRANSITION_1x1_to_2x2, +}; + +typedef enum eTDLSCapType{ + eTDLS_CAP_NOT_SUPPORTED = -1, + eTDLS_CAP_UNKNOWN = 0, + eTDLS_CAP_SUPPORTED = 1, +} tTDLSCapType; + +typedef enum eTDLSLinkStatus { + eTDLS_LINK_IDLE = 0, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_DISCOVERED, + eTDLS_LINK_CONNECTING, + eTDLS_LINK_CONNECTED, + eTDLS_LINK_TEARING, +} tTDLSLinkStatus; + + +typedef enum { + eTDLS_LINK_SUCCESS, /* Success */ + eTDLS_LINK_UNSPECIFIED = -1, /* Unspecified reason */ + eTDLS_LINK_NOT_SUPPORTED = -2, /* Remote side doesn't support TDLS */ + eTDLS_LINK_UNSUPPORTED_BAND = -3, /* Remote side doesn't support this + band */ + eTDLS_LINK_NOT_BENEFICIAL = -4, /* Going to AP is better than direct */ + eTDLS_LINK_DROPPED_BY_REMOTE = -5 /* Remote side doesn't want it anymore */ +} tTDLSLinkReason; + +typedef struct { + int channel; /* channel hint, in channel number + (NOT frequency ) */ + int global_operating_class; /* operating class to use */ + int max_latency_ms; /* max latency that can be tolerated + by apps */ + int min_bandwidth_kbps; /* bandwidth required by apps, in kilo + bits per second */ +} tdls_req_params_t; + +typedef enum { + QCA_WIFI_HAL_TDLS_DISABLED = 1, /* TDLS is not enabled, or is disabled + now */ + QCA_WIFI_HAL_TDLS_ENABLED, /* TDLS is enabled, but not yet tried */ + QCA_WIFI_HAL_TDLS_ESTABLISHED, /* Direct link is established */ + QCA_WIFI_HAL_TDLS_ESTABLISHED_OFF_CHANNEL, /* Direct link is established + using MCC */ + QCA_WIFI_HAL_TDLS_DROPPED, /* Direct link was established, but is + now dropped */ + QCA_WIFI_HAL_TDLS_FAILED /* Direct link failed */ +} tdls_state_t; + +typedef int (*cfg80211_exttdls_callback)(const tANI_U8* mac, + uint32_t opclass, + uint32_t channel, + tANI_U32 state, + tANI_S32 reason, + void *ctx); +typedef struct { + tANI_U16 period; + tANI_U16 bytes; +} tdls_tx_tput_config_t; + +typedef struct { + tANI_U16 period; + tANI_U16 tries; +} tdls_discovery_config_t; + +typedef struct { + tANI_U16 timeout; +} tdls_rx_idle_config_t; + +typedef struct { + tANI_U16 rssi_thres; +} tdls_rssi_config_t; + +struct _hddTdlsPeer_t; + +typedef struct { + struct list_head peer_list[TDLS_PEER_LIST_SIZE]; + hdd_adapter_t *pAdapter; + vos_timer_t peerDiscoveryTimeoutTimer; + tdls_config_params_t threshold_config; + tANI_U32 discovery_sent_cnt; + tANI_S8 ap_rssi; + struct _hddTdlsPeer_t *curr_candidate; + struct work_struct implicit_setup; + v_U32_t magic; +} tdlsCtx_t; + +typedef struct _hddTdlsPeer_t { + struct list_head node; + tdlsCtx_t *pHddTdlsCtx; + tSirMacAddr peerMac; + tANI_U16 staId ; + tANI_S8 rssi; + tTDLSCapType tdls_support; + tTDLSLinkStatus link_status; + tANI_U8 signature; + tANI_U8 is_responder; + tANI_U8 discovery_processed; + tANI_U16 discovery_attempt; + tANI_U16 tx_pkt; + tANI_U16 rx_pkt; + tANI_U8 uapsdQueues; + tANI_U8 maxSp; + tANI_U8 isBufSta; + tANI_U8 isOffChannelSupported; + tANI_U8 supported_channels_len; + tANI_U8 supported_channels[SIR_MAC_MAX_SUPP_CHANNELS]; + tANI_U8 supported_oper_classes_len; + tANI_U8 supported_oper_classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; + tANI_BOOLEAN isForcedPeer; + tANI_U8 op_class_for_pref_off_chan; + tANI_U8 pref_off_chan_num; + tANI_U8 op_class_for_pref_off_chan_is_set; + uint8_t spatial_streams; + /* EXT TDLS */ + tTDLSLinkReason reason; + cfg80211_exttdls_callback state_change_notification; +} hddTdlsPeer_t; + +typedef struct { + /* Session ID */ + tANI_U8 sessionId; + /*TDLS peer station id */ + v_U8_t staId; + /* TDLS peer mac Address */ + v_MACADDR_t peerMac; +} tdlsConnInfo_t; + +typedef struct { + tANI_U32 vdev_id; + tANI_U32 tdls_state; + tANI_U32 notification_interval_ms; + tANI_U32 tx_discovery_threshold; + tANI_U32 tx_teardown_threshold; + tANI_S32 rssi_teardown_threshold; + tANI_S32 rssi_delta; + tANI_U32 tdls_options; + tANI_U32 peer_traffic_ind_window; + tANI_U32 peer_traffic_response_timeout; + tANI_U32 puapsd_mask; + tANI_U32 puapsd_inactivity_time; + tANI_U32 puapsd_rx_frame_threshold; + uint32_t teardown_notification_ms; + uint32_t tdls_peer_kickout_threshold; +} tdlsInfo_t; + +int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac); + +void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac); + +int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, const u8 *mac, + u8 tx); + +int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, const u8 *mac, u8 staId); + +hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, + const u8 *mac, tANI_BOOLEAN mutexLock); + +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, + const u8 *mac); + +int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter, + const u8 *mac, + tCsrTdlsLinkEstablishParams* tdlsLinkEstablishParams); +hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac); + +int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, const u8* mac, + tTDLSCapType cap); + +void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, + tTDLSLinkStatus status, + tTDLSLinkReason reason); +void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, + const u8* mac, + tTDLSLinkStatus linkStatus, + tTDLSLinkReason reason); + +int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac); + +int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, + const u8 *mac, + tCsrStaParams *StaParams, + tANI_BOOLEAN isBufSta, + tANI_BOOLEAN isOffChannelSupported); + +int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_S8 rxRssi); + +int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_U8 responder); + +int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_U8 uSignature); + +int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config); + +int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const u8 *mac); + +tANI_U16 wlan_hdd_tdlsConnectedPeers(hdd_adapter_t *pAdapter); + +int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen); + +void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode); + +void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter); + +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, + const u8* mac, + u8 skip_self); + +int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request); + +int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request); + +void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter, + vos_timer_t *timer, + v_U32_t expirationTime); +void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, + hddTdlsPeer_t *curr_peer, + tANI_U16 reason); + +#ifdef CONFIG_TDLS_IMPLICIT +void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t *pHddTdlsCtx, + hddTdlsPeer_t *curr_candidate); +#endif + +int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, + const uint8_t *mac, + uint32_t chan, + uint32_t max_latency, + uint32_t op_class, + uint32_t min_bandwidth); + +int wlan_hdd_tdls_set_force_peer(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_BOOLEAN forcePeer); +int wlan_hdd_tdls_update_peer_mac(hdd_adapter_t *pAdapter, + const uint8_t *mac, + uint32_t peerState); + +int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, + const u8 *peer); +int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, + const u8 *peer, + cfg80211_exttdls_callback callback, + uint32_t chan, + uint32_t max_latency, + uint32_t op_class, + uint32_t min_bandwidth); +void hdd_tdls_notify_mode_change(hdd_adapter_t *pAdapter, + hdd_context_t *pHddCtx); +void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *pHddCtx); + +/* EXT TDLS */ +int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, + const tANI_U8* mac, + uint32_t *opclass, + uint32_t *channel, + tANI_U32 *state, + tANI_S32 *reason); +void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, + tANI_U32 *state, + tANI_S32 *reason); +int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, + cfg80211_exttdls_callback callback); +int hdd_set_tdls_offchannel(hdd_context_t *pHddCtx, int offchannel); +int hdd_set_tdls_secoffchanneloffset(hdd_context_t *pHddCtx, int offchanoffset); +int hdd_set_tdls_offchannelmode(hdd_adapter_t *pAdapter, int offchanmode); +void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, + bool tdls_chan_swit_prohibited); +int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val); +int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + uint32_t mode); + + +#else +static inline void hdd_tdls_notify_mode_change(hdd_adapter_t *pAdapter, + hdd_context_t *pHddCtx) +{ +} +static inline void +wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *pHddCtx) +{ +} +static inline void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) +{ +} +static inline int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + uint32_t mode) +{ + return 0; +} +#endif + +#endif // __HDD_TDSL_H diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h new file mode 100644 index 000000000000..7fe2aa6c5e2c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef HDD_TGT_CFG_H +#define HDD_TGT_CFG_H + +/* TODO: Find it from the max number of supported vdev */ +#define INTF_MACADDR_MASK 0x7 + +struct hdd_tgt_services { + u_int32_t sta_power_save; + u_int32_t uapsd; + u_int32_t ap_dfs; + u_int32_t en_11ac; + u_int32_t arp_offload; + u_int32_t early_rx; +#ifdef FEATURE_WLAN_SCAN_PNO + v_BOOL_t pno_offload; +#endif + v_BOOL_t beacon_offload; + u_int32_t lte_coex_ant_share; + uint8_t chain_mask_2g; + uint8_t chain_mask_5g; + bool per_band_chainmask_supp; +#ifdef FEATURE_WLAN_TDLS + v_BOOL_t en_tdls; + v_BOOL_t en_tdls_offchan; + v_BOOL_t en_tdls_uapsd_buf_sta; + v_BOOL_t en_tdls_uapsd_sleep_sta; +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + v_BOOL_t en_roam_offload; +#endif +#ifdef SAP_AUTH_OFFLOAD + bool sap_auth_offload_service; +#endif +}; + +struct hdd_tgt_ht_cap { + u_int32_t mpdu_density; + bool ht_rx_stbc; + bool ht_tx_stbc; + bool ht_rx_ldpc; + bool ht_sgi_20; + bool ht_sgi_40; + u_int32_t num_rf_chains; +}; + +#ifdef WLAN_FEATURE_11AC +struct hdd_tgt_vht_cap { + u_int32_t vht_max_mpdu; + u_int32_t supp_chan_width; + u_int32_t vht_rx_ldpc; + u_int32_t vht_short_gi_80; + u_int32_t vht_short_gi_160; + u_int32_t vht_tx_stbc; + u_int32_t vht_rx_stbc; + u_int32_t vht_su_bformer; + u_int32_t vht_su_bformee; + u_int32_t vht_mu_bformer; + u_int32_t vht_mu_bformee; + u_int32_t vht_max_ampdu_len_exp; + u_int32_t vht_txop_ps; +}; +#endif + + +struct hdd_tgt_cfg { + u_int32_t target_fw_version; + u_int8_t band_cap; + u_int32_t reg_domain; + u_int32_t eeprom_rd_ext; + v_MACADDR_t hw_macaddr; + struct hdd_tgt_services services; + struct hdd_tgt_ht_cap ht_cap; +#ifdef WLAN_FEATURE_11AC + struct hdd_tgt_vht_cap vht_cap; +#endif + v_U8_t max_intf_count; +#ifdef WLAN_FEATURE_LPSS + v_U8_t lpss_support; +#endif + uint8_t ap_arpns_support; +}; + +struct hdd_dfs_radar_ind { + u_int8_t ieee_chan_number; + u_int32_t chan_freq; + u_int32_t dfs_radar_status; +}; + +#endif /* HDD_TGT_CFG_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_trace.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_trace.h new file mode 100644 index 000000000000..b28619b316fa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_trace.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_TRACE_H__ +#define __WLAN_HDD_TRACE_H__ + +#include "macTrace.h" + +#define NO_SESSION 0xFF +#define TRACE_CODE_HDD_RX_SME_MSG 0xFF + +enum { + TRACE_CODE_HDD_OPEN_REQUEST, + TRACE_CODE_HDD_STOP_REQUEST, + TRACE_CODE_HDD_TX_TIMEOUT, + TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL, + TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL, + TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL, + TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL, + TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL, + TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL, + TRACE_CODE_HDD_SETROAMDELTA_IOCTL, + TRACE_CODE_HDD_GETROAMDELTA_IOCTL, + TRACE_CODE_HDD_GETBAND_IOCTL, + TRACE_CODE_HDD_GETCOUNTRYREV_IOCTL, + TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL, + TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL, + TRACE_CODE_HDD_HOSTAPD_OPEN_REQUEST, + TRACE_CODE_HDD_HOSTAPD_STOP_REQUEST, + TRACE_CODE_HDD_HOSTAPD_UNINIT_REQUEST, + TRACE_CODE_HDD_SOFTAP_TX_TIMEOUT, + TRACE_CODE_HDD_HOSTAPD_SET_MAC_ADDR, + TRACE_CODE_HDD_HOSTAPD_P2P_SET_NOA_IOCTL, + TRACE_CODE_HDD_HOSTAPD_P2P_SET_PS_IOCTL, + TRACE_CODE_HDD_HOSTAPD_SET_SAP_CHANNEL_LIST_IOCTL, + TRACE_CODE_HDD_ADD_VIRTUAL_INTF, + TRACE_CODE_HDD_DEL_VIRTUAL_INTF, + TRACE_CODE_HDD_CHANGE_VIRTUAL_INTF, + TRACE_CODE_HDD_CFG80211_START_AP, + TRACE_CODE_HDD_CFG80211_CHANGE_BEACON, + TRACE_CODE_HDD_CFG80211_STOP_AP, + TRACE_CODE_HDD_CFG80211_CHANGE_BSS, + TRACE_CODE_HDD_CFG80211_ADD_KEY, + TRACE_CODE_HDD_CFG80211_GET_KEY, + TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY, + TRACE_CODE_HDD_CFG80211_CONNECT, + TRACE_CODE_HDD_CFG80211_DISCONNECT, + TRACE_CODE_HDD_CFG80211_JOIN_IBSS, + TRACE_CODE_HDD_CFG80211_LEAVE_IBSS, + TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS, + TRACE_CODE_HDD_CFG80211_SET_TXPOWER, + TRACE_CODE_HDD_CFG80211_GET_TXPOWER, + TRACE_CODE_HDD_CFG80211_SET_CHANNEL, + TRACE_CODE_HDD_CFG80211_ADD_BEACON, + TRACE_CODE_HDD_CFG80211_SET_BEACON, + TRACE_CODE_HDD_CFG80211_CHANGE_IFACE, + TRACE_CODE_HDD_CHANGE_STATION, + TRACE_CODE_HDD_CFG80211_UPDATE_BSS, + TRACE_CODE_HDD_CFG80211_SCAN, + TRACE_CODE_HDD_CFG80211_SCHED_SCAN_START, + TRACE_CODE_HDD_CFG80211_SCHED_SCAN_STOP, + TRACE_CODE_HDD_REMAIN_ON_CHANNEL, + TRACE_CODE_HDD_REMAINCHANREADYHANDLER, + TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL, + TRACE_CODE_HDD_ACTION, + TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, + TRACE_CODE_HDD_CFG80211_GET_STA, + TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT, + TRACE_CODE_HDD_CFG80211_DEL_STA, + TRACE_CODE_HDD_CFG80211_ADD_STA, + TRACE_CODE_HDD_CFG80211_SET_PMKSA, + TRACE_CODE_HDD_CFG80211_DEL_PMKSA, + TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES, + TRACE_CODE_HDD_CFG80211_TDLS_MGMT, + TRACE_CODE_HDD_CFG80211_TDLS_OPER, + TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA, + TRACE_CODE_HDD_UNSUPPORTED_IOCTL, + TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL, + TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL, + TRACE_CODE_HDD_STORE_JOIN_REQ, + TRACE_CODE_HDD_CLEAR_JOIN_REQ, + TRACE_CODE_HDD_ISSUE_JOIN_REQ, + TRACE_CODE_HDD_CFG80211_RESUME_WLAN, + TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN, + TRACE_CODE_HDD_CFG80211_SET_MAC_ACL, + TRACE_CODE_HDD_CFG80211_TESTMODE, + TRACE_CODE_HDD_CFG80211_DUMP_SURVEY, +}; + +extern void hddTraceDump(void *pMac, tpvosTraceRecord pRecord, + tANI_U16 recIndex); +extern void hddTraceInit(void); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tsf.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tsf.h new file mode 100644 index 000000000000..c3da0cf8f622 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tsf.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined WLAN_HDD_TSF_H +#define WLAN_HDD_TSF_H + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Function declarations and documentation + -------------------------------------------------------------------------*/ + +#ifdef WLAN_FEATURE_TSF +void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx); +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_context_t *hdd_ctx) +{ + 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 + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tx_rx.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tx_rx.h new file mode 100644 index 000000000000..725d4c6b9db9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( WLAN_HDD_TX_RX_H ) +#define WLAN_HDD_TX_RX_H + +/**=========================================================================== + + \file wlan_hdd_tx_rx.h + + \brief Linux HDD Tx/RX APIs + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ +#define HDD_ETHERTYPE_802_1_X ( 0x888E ) +#define HDD_ETHERTYPE_802_1_X_FRAME_OFFSET ( 12 ) +#define HDD_ETHERTYPE_802_1_X_SIZE ( 2 ) +#ifdef FEATURE_WLAN_WAPI +#define HDD_ETHERTYPE_WAI ( 0x88b4 ) +#endif + +#define HDD_80211_HEADER_LEN 24 +#define HDD_80211_HEADER_QOS_CTL 2 +#define HDD_LLC_HDR_LEN 6 +#define HDD_FRAME_TYPE_MASK 0x0c +#define HDD_FRAME_SUBTYPE_MASK 0xf0 +#define HDD_FRAME_TYPE_DATA 0x08 +#define HDD_FRAME_TYPE_MGMT 0x00 +#define HDD_FRAME_SUBTYPE_QOSDATA 0x80 +#define HDD_FRAME_SUBTYPE_DEAUTH 0xC0 +#define HDD_FRAME_SUBTYPE_DISASSOC 0xA0 +#define HDD_DEST_ADDR_OFFSET 6 + +#define HDD_MAC_HDR_SIZE 6 + +#define HDD_PSB_CFG_INVALID 0xFF +#define HDD_PSB_CHANGED 0xFF +#define SME_QOS_UAPSD_CFG_BK_CHANGED_MASK 0xF1 +#define SME_QOS_UAPSD_CFG_BE_CHANGED_MASK 0xF2 +#define SME_QOS_UAPSD_CFG_VI_CHANGED_MASK 0xF4 +#define SME_QOS_UAPSD_CFG_VO_CHANGED_MASK 0xF8 + +#define HDD_ETH_HEADER_LEN 14 + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Function declarations and documentation + -------------------------------------------------------------------------*/ + +/**============================================================================ + @brief hdd_hard_start_xmit() - Function registered with the Linux OS for + transmitting packets + + @param skb : [in] pointer to OS packet (sk_buff) + @param dev : [in] pointer to Libra network device + + @return : NET_XMIT_DROP if packets are dropped + : NET_XMIT_SUCCESS if packet is enqueued successfully + ===========================================================================*/ +extern int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); + +extern int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); +/**============================================================================ + @brief hdd_tx_timeout() - Function called by OS if there is any + timeout during transmission. Since HDD simply enqueues packet + and returns control to OS right away, this would never be invoked + + @param dev : [in] pointer to Libra network device + @return : None + ===========================================================================*/ +extern void hdd_tx_timeout(struct net_device *dev); + +/**============================================================================ + @brief hdd_stats() - Function registered with the Linux OS for + device TX/RX statistics + + @param dev : [in] pointer to Libra network device + + @return : pointer to net_device_stats structure + ===========================================================================*/ +extern struct net_device_stats* hdd_stats(struct net_device *dev); + +/**============================================================================ + @brief hdd_init_tx_rx() - Init function to initialize Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_tx_complete_cbk() - Callback function invoked by TL + to indicate that a packet has been transmitted across the SDIO bus + succesfully. OS packet resources can be released after this cbk. + + @param vosContext : [in] pointer to VOS context + @param pVosPacket : [in] pointer to VOS packet (containing skb) + @param vosStatusIn : [in] status of the transmission + + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext, + vos_pkt_t *pVosPacket, + VOS_STATUS vosStatusIn ); + +/**============================================================================ + @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to + fetch a packet for transmission. + + @param vosContext : [in] pointer to VOS context + @param staId : [in] Station for which TL is requesting a pkt + @param ucAC : [in] pointer to access category requested by TL + @param pVosPacket : [out] pointer to VOS packet packet pointer + @param pPktMetaInfo : [out] pointer to meta info for the pkt + + @return : VOS_STATUS_E_EMPTY if no packets to transmit + : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext, + v_U8_t *pStaId, + WLANTL_ACEnumType ucAC, + vos_pkt_t **ppVosPacket, + WLANTL_MetaInfoType *pPktMetaInfo ); + +/**============================================================================ + @brief hdd_tx_low_resource_cbk() - Callback function invoked in the + case where VOS packets are not available at the time of the call to get + packets. This callback function is invoked by VOS when packets are + available. + + @param pVosPacket : [in] pointer to VOS packet + @param userData : [in] opaque user data that was passed initially + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + =============================================================================*/ +extern VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket, + v_VOID_t *userData ); + +/**============================================================================ + @brief hdd_rx_packet_cbk() - Receive callback registered with TL. + TL will call this to notify the HDD when a packet was received + for a registered STA. + + @param vosContext : [in] pointer to VOS context + @param rxBufChain : [in] pointer to adf_nbuf rx chain + @param staId : [in] Station Id + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +extern VOS_STATUS hdd_rx_packet_cbk(v_VOID_t *vosContext, adf_nbuf_t rxBufChain, + v_U8_t staId); + +/**============================================================================ + @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not. + + @param pVosPacket : [in] pointer to vos packet + @return : VOS_TRUE if the packet is EAPOL + : VOS_FALSE otherwise + ===========================================================================*/ +extern v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket ); + +/**============================================================================ + @brief hdd_mon_tx_mgmt_pkt() - Transmit MGMT packet received on monitor + interface. + + @param pAdapter: [in] SAP/P2P GO adapter. + ===========================================================================*/ +void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter); + +/**============================================================================ + @brief hdd_mon_tx_work_queue() - work queue handler for transmitting + mgmt packets. + + @param work: [in] work queue structure. + ===========================================================================*/ +void hdd_mon_tx_work_queue(struct work_struct *work); + +/**============================================================================ + @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address + @param pHddStaCtx : [in] pointer to HDD Station Context + pMacAddress [in] pointer to Peer Mac address + staID [out] pointer to Station Index + @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE + ===========================================================================*/ +VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, + v_MACADDR_t *pMacAddress, v_U8_t *staId); + +/**============================================================================ + @brief hdd_flush_ibss_tx_queues() - + Flush tx queues in IBSS mode + @param pAdapter: Hdd adapter + @param STAId: Sta index + @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE + ===========================================================================*/ +void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId); + +/**========================================================================= + @brief hdd_wmm_acquire_access_required()- + Determine whether wmm ac acquire access is required + @param pAdapter : pointer to Adapter context + @param acType : AC + @return : void + ========================================================================*/ +void hdd_wmm_acquire_access_required(hdd_adapter_t *pAdapter, + WLANTL_ACEnumType acType); + +#ifdef QCA_LL_TX_FLOW_CT +/**============================================================================ + @brief hdd_tx_resume_cb() - Resume OS TX Q. + Q was stopped due to WLAN TX path low resource condition + + @param adapter_context : [in] pointer to vdev adapter + @param tx_resume : [in] TX Q resume trigger + + @return : NONE + ===========================================================================*/ +void hdd_tx_resume_cb(void *adapter_context, + v_BOOL_t tx_resume); + +/**============================================================================ + @brief hdd_tx_resume_timer_expired_handler() - Resume OS TX Q timer expired + handler. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_tx_resume_timer_expired_handler(void *adapter_context); +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * wlan_hdd_log_eapol() - Function to check and extract EAPOL params + * @skb: skb data + * @event_type: One of enum wifi_connectivity_events to indicate Tx/Rx + * + * This function parses the input skb data to get the EAPOL params,if the + * packet is EAPOL and store it in the pointer passed as input + * + * Return: None + * + */ +void wlan_hdd_log_eapol(struct sk_buff *skb, + uint8_t event_type); +#else +static inline void wlan_hdd_log_eapol(struct sk_buff *skb, + uint8_t event_type) +{ + +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +#endif // end #if !defined( WLAN_HDD_TX_RX_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h new file mode 100644 index 000000000000..0dd4beaf2eb4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WEXT_IW_H__ +#define __WEXT_IW_H__ + +#include +#include +#include +#include +#include +#include +#include "vos_event.h" + +/* + * order of parameters in addTs private ioctl + */ +#define HDD_WLAN_WMM_PARAM_HANDLE 0 +#define HDD_WLAN_WMM_PARAM_TID 1 +#define HDD_WLAN_WMM_PARAM_DIRECTION 2 +#define HDD_WLAN_WMM_PARAM_APSD 3 +#define HDD_WLAN_WMM_PARAM_USER_PRIORITY 4 +#define HDD_WLAN_WMM_PARAM_NOMINAL_MSDU_SIZE 5 +#define HDD_WLAN_WMM_PARAM_MAXIMUM_MSDU_SIZE 6 +#define HDD_WLAN_WMM_PARAM_MINIMUM_DATA_RATE 7 +#define HDD_WLAN_WMM_PARAM_MEAN_DATA_RATE 8 +#define HDD_WLAN_WMM_PARAM_PEAK_DATA_RATE 9 +#define HDD_WLAN_WMM_PARAM_MAX_BURST_SIZE 10 +#define HDD_WLAN_WMM_PARAM_MINIMUM_PHY_RATE 11 +#define HDD_WLAN_WMM_PARAM_SURPLUS_BANDWIDTH_ALLOWANCE 12 +#define HDD_WLAN_WMM_PARAM_SERVICE_INTERVAL 13 +#define HDD_WLAN_WMM_PARAM_SUSPENSION_INTERVAL 14 +#define HDD_WLAN_WMM_PARAM_BURST_SIZE_DEFN 15 +#define HDD_WLAN_WMM_PARAM_ACK_POLICY 16 +#define HDD_WLAN_WMM_PARAM_INACTIVITY_INTERVAL 17 +#define HDD_WLAN_WMM_PARAM_MAX_SERVICE_INTERVAL 18 +#define HDD_WLAN_WMM_PARAM_COUNT 19 + +#define MHZ 6 + +#define WE_MAX_STR_LEN IW_PRIV_SIZE_MASK +#define WLAN_HDD_UI_BAND_AUTO 0 +#define WLAN_HDD_UI_BAND_5_GHZ 1 +#define WLAN_HDD_UI_BAND_2_4_GHZ 2 +/* SETBAND x */ +/* 012345678 */ +#define WLAN_HDD_UI_SET_BAND_VALUE_OFFSET 8 + +typedef enum +{ + HDD_WLAN_WMM_DIRECTION_UPSTREAM = 0, + HDD_WLAN_WMM_DIRECTION_DOWNSTREAM = 1, + HDD_WLAN_WMM_DIRECTION_BIDIRECTIONAL = 2, +} hdd_wlan_wmm_direction_e; + +typedef enum +{ + HDD_WLAN_WMM_POWER_SAVE_LEGACY = 0, + HDD_WLAN_WMM_POWER_SAVE_UAPSD = 1, +} hdd_wlan_wmm_power_save_e; + +typedef enum +{ + // TSPEC/re-assoc done, async + HDD_WLAN_WMM_STATUS_SETUP_SUCCESS = 0, + // no need to setup TSPEC since ACM=0 and no UAPSD desired, sync + async + HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD = 1, + // no need to setup TSPEC since ACM=0 and UAPSD already exists, sync + async + HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING = 2, + // TSPEC result pending, sync + HDD_WLAN_WMM_STATUS_SETUP_PENDING = 3, + // TSPEC/re-assoc failed, sync + async + HDD_WLAN_WMM_STATUS_SETUP_FAILED = 4, + // Request rejected due to invalid params, sync + async + HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM = 5, + // TSPEC request rejected since AP!=QAP, sync + HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM = 6, + + // TSPEC modification/re-assoc successful, async + HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS = 7, + // TSPEC modification a no-op since ACM=0 and no change in UAPSD, sync + async + HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD = 8, + // TSPEC modification a no-op since ACM=0 and requested U-APSD already exists, sync + async + HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING = 9, + // TSPEC result pending, sync + HDD_WLAN_WMM_STATUS_MODIFY_PENDING = 10, + // TSPEC modification failed, prev TSPEC in effect, sync + async + HDD_WLAN_WMM_STATUS_MODIFY_FAILED = 11, + // TSPEC modification request rejected due to invalid params, sync + async + HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM = 12, + + // TSPEC release successful, sync and also async + HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS = 13, + // TSPEC release pending, sync + HDD_WLAN_WMM_STATUS_RELEASE_PENDING = 14, + // TSPEC release failed, sync + async + HDD_WLAN_WMM_STATUS_RELEASE_FAILED = 15, + // TSPEC release rejected due to invalid params, sync + HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM = 16, + // TSPEC modified due to the mux'ing of requests on ACs, async + + HDD_WLAN_WMM_STATUS_MODIFIED = 17, + // TSPEC revoked by AP, async + HDD_WLAN_WMM_STATUS_LOST = 18, + // some internal failure like memory allocation failure, etc, sync + HDD_WLAN_WMM_STATUS_INTERNAL_FAILURE = 19, + + /* U-APSD failed during setup but OTA setup (whether TSPEC exchange or + re-assoc) was done so app should release this QoS, async */ + HDD_WLAN_WMM_STATUS_SETUP_UAPSD_SET_FAILED = 20, + /* U-APSD failed during modify, but OTA setup (whether TSPEC exchange or + re-assoc) was done so app should release this QoS, async */ + HDD_WLAN_WMM_STATUS_MODIFY_UAPSD_SET_FAILED = 21 + +} hdd_wlan_wmm_status_e; + +/** TS Info Ack Policy */ +typedef enum +{ + HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK = 0, + HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK = 1, +} hdd_wlan_wmm_ts_info_ack_policy_e; + +/** vendor element ID */ +#define IE_EID_VENDOR ( 221 ) /* 0xDD */ +#define IE_LEN_SIZE 1 +#define IE_EID_SIZE 1 +#define IE_VENDOR_OUI_SIZE 4 + +/** Maximum Length of WPA/RSN IE */ +#define MAX_WPA_RSN_IE_LEN 40 + +/** Maximum Number of WEP KEYS */ +#define MAX_WEP_KEYS 4 + +/** Ether Address Length */ +#define ETHER_ADDR_LEN 6 + +/** Enable 11d */ +#define ENABLE_11D 1 + +/** Disable 11d */ +#define DISABLE_11D 0 + +/* + refer wpa.h in wpa supplicant code for REASON_MICHAEL_MIC_FAILURE + + supplicant sets REASON_MICHAEL_MIC_FAILURE as the reason code when it sends the MLME deauth IOCTL + for TKIP counter measures +*/ +#define HDD_REASON_MICHAEL_MIC_FAILURE 14 + +/* + * These are for TLV fields in WPS IE + */ +#define HDD_WPS_UUID_LEN 16 +#define HDD_WPS_ELEM_VERSION 0x104a +#define HDD_WPS_ELEM_REQUEST_TYPE 0x103a +#define HDD_WPS_ELEM_CONFIG_METHODS 0x1008 +#define HDD_WPS_ELEM_UUID_E 0x1047 +#define HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE 0x1054 +#define HDD_WPS_ELEM_RF_BANDS 0x103c +#define HDD_WPS_ELEM_ASSOCIATION_STATE 0x1002 +#define HDD_WPS_ELEM_CONFIGURATION_ERROR 0x1009 +#define HDD_WPS_ELEM_DEVICE_PASSWORD_ID 0x1012 + +#define HDD_WPA_ELEM_VENDOR_EXTENSION 0x1049 + +#define HDD_WPS_MANUFACTURER_LEN 64 +#define HDD_WPS_MODEL_NAME_LEN 32 +#define HDD_WPS_MODEL_NUM_LEN 32 +#define HDD_WPS_SERIAL_NUM_LEN 32 +#define HDD_WPS_DEVICE_OUI_LEN 4 +#define HDD_WPS_DEVICE_NAME_LEN 32 + +#define HDD_WPS_ELEM_WPS_STATE 0x1044 +#define HDD_WPS_ELEM_APSETUPLOCK 0x1057 +#define HDD_WPS_ELEM_SELECTEDREGISTRA 0x1041 +#define HDD_WPS_ELEM_RSP_TYPE 0x103B +#define HDD_WPS_ELEM_MANUFACTURER 0x1021 +#define HDD_WPS_ELEM_MODEL_NAME 0x1023 +#define HDD_WPS_ELEM_MODEL_NUM 0x1024 +#define HDD_WPS_ELEM_SERIAL_NUM 0x1042 +#define HDD_WPS_ELEM_DEVICE_NAME 0x1011 +#define HDD_WPS_ELEM_REGISTRA_CONF_METHODS 0x1053 + +#define HDD_RTSCTS_EN_MASK 0xF +#define HDD_RTSCTS_ENABLE 1 +#define HDD_CTS_ENABLE 2 + +#define WPS_OUI_TYPE "\x00\x50\xf2\x04" +#define WPS_OUI_TYPE_SIZE 4 + +#define SS_OUI_TYPE "\x00\x16\x32" +#define SS_OUI_TYPE_SIZE 3 + +#define P2P_OUI_TYPE "\x50\x6f\x9a\x09" +#define P2P_OUI_TYPE_SIZE 4 + +#define HS20_OUI_TYPE "\x50\x6f\x9a\x10" +#define HS20_OUI_TYPE_SIZE 4 + +#define OSEN_OUI_TYPE "\x50\x6f\x9a\x12" +#define OSEN_OUI_TYPE_SIZE 4 + +#ifdef WLAN_FEATURE_WFD +#define WFD_OUI_TYPE "\x50\x6f\x9a\x0a" +#define WFD_OUI_TYPE_SIZE 4 +#endif + +typedef enum +{ + eWEXT_WPS_OFF = 0, + eWEXT_WPS_ON = 1, +}hdd_wps_mode_e; + +typedef enum +{ + DRIVER_POWER_MODE_AUTO = 0, + DRIVER_POWER_MODE_ACTIVE = 1, +} hdd_power_mode_e; + +typedef enum +{ + WEXT_SCAN_PENDING_GIVEUP = 0, + WEXT_SCAN_PENDING_PIGGYBACK = 1, + WEXT_SCAN_PENDING_DELAY = 2, + WEXT_SCAN_PENDING_MAX +} hdd_scan_pending_option_e; + +/** + * 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 +}; + +/* + * This structure contains the interface level (granularity) + * configuration information in support of wireless extensions. + */ +typedef struct hdd_wext_state_s +{ + /** The CSR "desired" Profile */ + tCsrRoamProfile roamProfile; + + /** BSSID to which connect request is received */ + tCsrBssid req_bssId; + + /** The association status code */ + v_U32_t statusCode; + + /** wpa version WPA/WPA2/None*/ + v_S31_t wpaVersion; + + /**WPA or RSN IE*/ + u_int8_t WPARSNIE[MAX_WPA_RSN_IE_LEN]; + + /**gen IE */ + tSirAddie genIE; + + /**Additional IE for assoc */ + tSirAddie assocAddIE; + + /**auth key mgmt */ + v_S31_t authKeyMgmt; + + /**vos event */ + vos_event_t vosevent; + + vos_event_t scanevent; + + /**Counter measure state, Started/Stopped*/ + v_BOOL_t mTKIPCounterMeasures; + + /**Completion Variable*/ + struct completion completion_var; + +#ifdef FEATURE_OEM_DATA_SUPPORT + /* oem data req in Progress */ + v_BOOL_t oemDataReqInProgress; + + /* oem data req ID */ + v_U32_t oemDataReqID; +#endif + +#ifdef FEATURE_WLAN_ESE + /* ESE state variables */ + v_BOOL_t isESEConnection; + eCsrAuthType collectedAuthType; /* Collected from ALL SIOCSIWAUTH Ioctls. Will be negotiatedAuthType - in tCsrProfile */ +#endif +}hdd_wext_state_t; + +typedef struct ccp_freq_chan_map_s{ + // List of frequencies + v_U32_t freq; + v_U32_t chan; +}hdd_freq_chan_map_t; + +#define wlan_hdd_get_wps_ie_ptr(ie, ie_len) \ + wlan_hdd_get_vendor_oui_ie_ptr(WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE, ie, ie_len) + +#define wlan_hdd_get_p2p_ie_ptr(ie, ie_len) \ + wlan_hdd_get_vendor_oui_ie_ptr(P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE, ie, ie_len) + +#ifdef WLAN_FEATURE_WFD +#define wlan_hdd_get_wfd_ie_ptr(ie, ie_len) \ + wlan_hdd_get_vendor_oui_ie_ptr(WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE, ie, ie_len) +#endif + +extern int hdd_UnregisterWext(struct net_device *dev); +extern int hdd_register_wext(struct net_device *dev); +extern int hdd_wlan_get_freq(v_U32_t chan,v_U32_t *freq); +extern int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu); +extern int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu); +extern void hdd_wlan_get_version(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu, char *extra); + +extern void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, + char *buffer, v_U16_t buf_len); + +extern void hdd_wlan_dump_stats(hdd_adapter_t *pAdapter, int value); + +extern int iw_get_scan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_set_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_set_cscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_set_essid(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_get_essid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra); + + +extern int iw_set_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_get_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_set_auth(struct net_device *dev,struct iw_request_info *info, + union iwreq_data *wrqu,char *extra); + +extern int iw_get_auth(struct net_device *dev,struct iw_request_info *info, + union iwreq_data *wrqu,char *extra); + +int iw_set_pno(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, int nOffset); + +VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, int nOffset); + +void ccmCfgSetCallback(tHalHandle halHandle, tANI_S32 result); + +extern int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int iw_set_three_ints_getnone(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int hdd_priv_get_data(struct iw_point *p_priv_data, + union iwreq_data *wrqu); + +extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len); + +extern VOS_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, + tSirMacAddr macAddress); +void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter); +void hdd_GetClassA_statisticsCB(void *pStats, void *pContext); +void hdd_GetLink_SpeedCB(tSirLinkSpeedInfo *pLinkSpeed, void *pContext); + +VOS_STATUS wlan_hdd_check_ula_done(hdd_adapter_t *pAdapter); + +v_U8_t* wlan_hdd_get_vendor_oui_ie_ptr(v_U8_t *oui, v_U8_t oui_size, + v_U8_t *ie, int ie_len); + +VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode); + +VOS_STATUS wlan_hdd_exit_lowpower(hdd_context_t *pHddCtx, + hdd_adapter_t *pAdapter); + +VOS_STATUS wlan_hdd_enter_lowpower(hdd_context_t *pHddCtx); + +VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter); + +VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter); + +VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value); + +VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr); + +int hdd_get_ldpc(hdd_adapter_t *adapter, int *value); +int hdd_set_ldpc(hdd_adapter_t *adapter, int value); +int hdd_get_tx_stbc(hdd_adapter_t *adapter, int *value); +int hdd_set_tx_stbc(hdd_adapter_t *adapter, int value); +int hdd_get_rx_stbc(hdd_adapter_t *adapter, int *value); +int hdd_set_rx_stbc(hdd_adapter_t *adapter, int value); + +void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter); + +#ifdef FEATURE_WLAN_TDLS +VOS_STATUS iw_set_tdls_params(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra, int nOffset); +#endif + +#ifdef WLAN_FEATURE_PACKET_FILTERING +void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set); +#endif +void* wlan_hdd_change_country_code_callback(void *pAdapter); + +VOS_STATUS wlan_hdd_set_powersave(hdd_adapter_t *pAdapter, int mode); + +int hdd_setBand(struct net_device *dev, u8 ui_band); +int hdd_setBand_helper(struct net_device *dev, const char *command); +int wlan_hdd_update_phymode(struct net_device *net, tHalHandle hal, + int new_phymode, + hdd_context_t *phddctx); + +int process_wma_set_command_twoargs(int sessid, int paramid, + int sval, int ssecval, int vpdev); + +void hdd_GetTemperatureCB(int temperature, void *pContext); +VOS_STATUS wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu, char *extra); +#endif // __WEXT_IW_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wmm.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wmm.h new file mode 100644 index 000000000000..5e992866b94c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wmm.h @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _WLAN_HDD_WMM_H +#define _WLAN_HDD_WMM_H +/*============================================================================ + @file wlan_hdd_wmm.h + + This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation) + houses all the logic for WMM in HDD. + + On the control path, it has the logic to setup QoS, modify QoS and delete + QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an + explicit application invoked and an internal HDD invoked. The implicit QoS + is for applications that do NOT call the custom QCT WLAN OIDs for QoS but + which DO mark their traffic for prioritization. It also has logic to start, + update and stop the U-APSD trigger frame generation. It also has logic to + read WMM related config parameters from the registry. + + On the data path, it has the logic to figure out the WMM AC of an egress + packet and when to signal TL to serve a particular AC queue. It also has the + logic to retrieve a packet based on WMM priority in response to a fetch from + TL. + + The remaining functions are utility functions for information hiding. +============================================================================*/ +/* $Header$ */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +// #define HDD_WMM_DEBUG 1 + +#define HDD_WMM_CTX_MAGIC 0x574d4d58 // "WMMX" + +#define HDD_WMM_HANDLE_IMPLICIT 0xFFFFFFFF + +#define HDD_WLAN_INVALID_STA_ID 0xFF + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +/*! @brief AC/Queue Index values for Linux Qdisc to operate on different traffic. +*/ +typedef enum +{ + HDD_LINUX_AC_VO = 0, + HDD_LINUX_AC_VI = 1, + HDD_LINUX_AC_BE = 2, + HDD_LINUX_AC_BK = 3 + +} hdd_wmm_linuxac_t; + +/*! @brief types of classification supported +*/ +typedef enum +{ + HDD_WMM_CLASSIFICATION_DSCP = 0, + HDD_WMM_CLASSIFICATION_802_1Q = 1 + +} hdd_wmm_classification_t; + +/*! @brief UAPSD state +*/ +typedef enum +{ + HDD_WMM_NON_UAPSD = 0, + HDD_WMM_UAPSD = 1 + +} hdd_wmm_uapsd_state_t; + + +typedef enum +{ + //STA can associate with any AP, & HDD looks at the SME notification after + // association to find out if associated with QAP and acts accordingly + HDD_WMM_USER_MODE_AUTO = 0, + //SME will add the extra logic to make sure STA associates with a QAP only + HDD_WMM_USER_MODE_QBSS_ONLY = 1, + //SME will not join a QoS AP, unless the phy mode setting says "Auto". In + // that case, STA is free to join 11n AP. Although from HDD point of view, + // it will not be doing any packet classifications + HDD_WMM_USER_MODE_NO_QOS = 2, + +} hdd_wmm_user_mode_t; + +// UAPSD Mask bits +// (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored) +#define HDD_AC_VO 0x1 +#define HDD_AC_VI 0x2 +#define HDD_AC_BK 0x4 +#define HDD_AC_BE 0x8 + +/*! @brief WMM Qos instance control block +*/ +typedef struct +{ + struct list_head node; + v_U32_t handle; + v_U32_t qosFlowId; + hdd_adapter_t* pAdapter; + WLANTL_ACEnumType acType; + hdd_wlan_wmm_status_e lastStatus; + struct work_struct wmmAcSetupImplicitQos; + v_U32_t magic; + bool is_inactivity_timer_running; +} hdd_wmm_qos_context_t; + +/*! @brief WMM related per-AC state & status info +*/ +typedef struct +{ + // does the AP require access to this AC? + v_BOOL_t wmmAcAccessRequired; + + // does the worker thread need to acquire access to this AC? + v_BOOL_t wmmAcAccessNeeded; + + // is implicit QoS negotiation currently taking place? + v_BOOL_t wmmAcAccessPending; + + // has implicit QoS negotiation already failed? + v_BOOL_t wmmAcAccessFailed; + + // has implicit QoS negotiation already succeeded? + v_BOOL_t wmmAcAccessGranted; + + /* + * Is access to this AC allowed, either because we are not doing + * WMM, we are not doing implicit QoS, implicit QoS has completed, + * or explicit QoS has completed? + */ + v_BOOL_t wmmAcAccessAllowed; + + // is the wmmAcTspecInfo valid? + v_BOOL_t wmmAcTspecValid; + + // are the wmmAcUapsd* fields valid? + v_BOOL_t wmmAcUapsdInfoValid; + + // current (possibly aggregate) Tspec for this AC + sme_QosWmmTspecInfo wmmAcTspecInfo; + + // current U-APSD parameters + v_BOOL_t wmmAcIsUapsdEnabled; + v_U32_t wmmAcUapsdServiceInterval; + v_U32_t wmmAcUapsdSuspensionInterval; + sme_QosWmmDirType wmmAcUapsdDirection; + +#ifdef FEATURE_WLAN_ESE + // Inactivity time parameters for TSPEC + v_U32_t wmmInactivityTime; + v_U32_t wmmPrevTrafficCnt; + vos_timer_t wmmInactivityTimer; +#endif + +} hdd_wmm_ac_status_t; + +/*! @brief WMM state & status info +*/ +typedef struct +{ + struct list_head wmmContextList; + struct mutex wmmLock; + hdd_wmm_ac_status_t wmmAcStatus[WLANTL_MAX_AC]; + v_BOOL_t wmmQap; + v_BOOL_t wmmQosConnection; +} hdd_wmm_status_t; + +extern const v_U8_t hdd_QdiscAcToTlAC[]; +extern const v_U8_t hddWmmUpToAcMap[]; +extern const v_U8_t hddLinuxUpToAcMap[]; + +#define WLAN_HDD_MAX_DSCP 0x3f + +/**============================================================================ + @brief hdd_wmm_init() - Function which will initialize the WMM configuration + and status to an initial state. The configuration can later be overwritten + via application APIs + + @param pAdapter : [in] pointer to Adapter context + + @return : VOS_STATUS_SUCCESS if succssful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_init ( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_wmm_adapter_init() - Function which will initialize the WMM + configuration and status to an initial state. + The configuration can later be overwritten via application APIs + + @param pAdapter : [in] pointer to Adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_adapter_init( hdd_adapter_t *pAdapter ); + +/**============================================================================ + @brief hdd_wmm_adapter_close() - Function which will perform any necessary work to + to clean up the WMM functionality prior to the kernel module unload + + @param pAdapter : [in] pointer to adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_adapter_close ( hdd_adapter_t* pAdapter ); + +/**============================================================================ + @brief hdd_wmm_select_queue() - Function which will classify an OS packet + into Linux Qdisc expectation + + @param dev : [in] pointer to net_device structure + @param skb : [in] pointer to OS packet (sk_buff) + + @return : queue_index/Linux AC value. + ===========================================================================*/ +v_U16_t hdd_wmm_select_queue(struct net_device * dev, struct sk_buff *skb); + +/**============================================================================ + @brief hdd_hostapd_select_queue() - Function which will classify the packet + according to Linux qdisc expectation. + + + @param dev : [in] pointer to net_device structure + @param skb : [in] pointer to os packet + + @return : Qdisc queue index + ===========================================================================*/ + +v_U16_t hdd_hostapd_select_queue(struct net_device * dev, struct sk_buff *skb +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) + , void *accel_priv +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + , select_queue_fallback_t fallback +#endif +); + +/**============================================================================ + @brief hdd_wmm_acquire_access() - Function which will attempt to acquire + admittance for a WMM AC + + @param pAdapter : [in] pointer to adapter context + @param acType : [in] WMM AC type of OS packet + @param pGranted : [out] pointer to boolean flag when indicates if access + has been granted or not + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_acquire_access( hdd_adapter_t* pAdapter, + WLANTL_ACEnumType acType, + v_BOOL_t * pGranted ); + +/**============================================================================ + @brief hdd_wmm_assoc() - Function which will handle the housekeeping + required by WMM when association takes place + + @param pAdapter : [in] pointer to adapter context + @param pRoamInfo: [in] pointer to roam information + @param eBssType : [in] type of BSS + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_assoc( hdd_adapter_t* pAdapter, + tCsrRoamInfo *pRoamInfo, + eCsrRoamBssType eBssType ); + +/**============================================================================ + @brief hdd_wmm_connect() - Function which will handle the housekeeping + required by WMM when a connection is established + + @param pAdapter : [in] pointer to adapter context + @param pRoamInfo: [in] pointer to roam information + @param eBssType : [in] type of BSS + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_connect( hdd_adapter_t* pAdapter, + tCsrRoamInfo *pRoamInfo, + eCsrRoamBssType eBssType ); + +/**============================================================================ + @brief hdd_wmm_get_uapsd_mask() - Function which will calculate the + initial value of the UAPSD mask based upon the device configuration + + @param pAdapter : [in] pointer to adapter context + @param pUapsdMask: [in] pointer to where the UAPSD Mask is to be stored + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_get_uapsd_mask( hdd_adapter_t* pAdapter, + tANI_U8 *pUapsdMask ); + +/**============================================================================ + @brief hdd_wmm_is_active() - Function which will determine if WMM is + active on the current connection + + @param pAdapter : [in] pointer to adapter context + + @return : VOS_TRUE if WMM is enabled + : VOS_FALSE if WMM is not enabled + ===========================================================================*/ +v_BOOL_t hdd_wmm_is_active( hdd_adapter_t* pAdapter ); + +/**============================================================================ + @brief hdd_wmm_addts() - Function which will add a traffic spec at the + request of an application + + @param pAdapter : [in] pointer to adapter context + @param handle : [in] handle to uniquely identify a TS + @param pTspec : [in] pointer to the traffic spec + + @return : HDD_WLAN_WMM_STATUS_* + ===========================================================================*/ +hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter, + v_U32_t handle, + sme_QosWmmTspecInfo* pTspec ); + +/**============================================================================ + @brief hdd_wmm_delts() - Function which will delete a traffic spec at the + request of an application + + @param pAdapter : [in] pointer to adapter context + @param handle : [in] handle to uniquely identify a TS + + @return : HDD_WLAN_WMM_STATUS_* + ===========================================================================*/ +hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter, + v_U32_t handle ); + +/**============================================================================ + @brief hdd_wmm_checkts() - Function which will return the status of a traffic + spec at the request of an application + + @param pAdapter : [in] pointer to adapter context + @param handle : [in] handle to uniquely identify a TS + + @return : HDD_WLAN_WMM_STATUS_* + ===========================================================================*/ +hdd_wlan_wmm_status_e hdd_wmm_checkts( hdd_adapter_t* pAdapter, + v_U32_t handle ); +/**============================================================================ + @brief hdd_wmm_adapter_clear() - Function which will clear the WMM status + of all ACs + @param pAdapter : [in] pointer to adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_adapter_clear( hdd_adapter_t *pAdapter ); + +#endif /* #ifndef _WLAN_HDD_WMM_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wowl.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wowl.h new file mode 100644 index 000000000000..398a2425bc5d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wowl.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WLAN_HDD_WOWL_H +#define _WLAN_HDD_WOWL_H + +/*============================================================================ + @file wlan_hdd_wowl.h + + This module houses all the logic for WOWL in HDD. + + It provides the following APIs + + - Ability to enable/disable following WoWL modes + 1) Magic packet (MP) mode + 2) Pattern Byte Matching (PBM) mode + - Ability to add/remove patterns for PBM + + A Magic Packet is a packet that contains 6 0xFFs followed by 16 contiguous + copies of the receiving NIC's Ethernet address. There is no API to configure + Magic Packet Pattern. + + Wakeup pattern (used for PBM) is defined as following: + typedef struct + { + U8 PatternSize; // Non-Zero pattern size + U8 PatternMaskSize; // Non-zero pattern mask size + U8 PatternMask[PatternMaskSize]; // Pattern mask + U8 Pattern[PatternSize]; // Pattern + } hdd_wowl_ptrn_t; + + PatternSize and PatternMaskSize indicate size of the variable length Pattern + and PatternMask. PatternMask indicates which bytes of an incoming packet + should be compared with corresponding bytes in the pattern. + + Maximum allowed pattern size is 128 bytes. Maximum allowed PatternMaskSize + is 16 bytes. + + Maximum number of patterns that can be configured is 8 + + HDD will add following 2 commonly used patterns for PBM by default: + 1) ARP Broadcast Pattern + 2) Unicast Pattern + + However note that WoWL will not be enabled by default by HDD. WoWL needs to + enabled explicitly by exercising the iwpriv command. + + HDD will expose an API that accepts patterns as Hex string in the following + format: "PatternSize:PatternMaskSize:PatternMask:Pattern". Multiple patterns + can be specified by delimiting each pattern with the ';' token. + "PatternSize1:PatternMaskSize1:PatternMask1:Pattern1;PatternSize2:...." + + Patterns can be configured dynamically via iwpriv cmd or statically via + qcom_cfg.ini file + + PBM (when enabled) can perform filtering on unicast data or broadcast data or + both. These configurations are part of factory defaults (cfg.dat) and + the default behavior is to perform filtering on both unicast and data frames. + + MP filtering (when enabled) is performed ALWAYS on both unicast and broadcast + data frames. + + Management frames are not subjected to WoWL filtering and are discarded when + WoWL is enabled. + + Whenever a pattern match succeeds, RX path is restored and packets (both + management and data) will be pushed to the host from that point onwards. + Therefore, exit from WoWL is implicit and happens automatically when the + first packet match succeeds. + + WoWL works on top of BMPS. So when WoWL is requested, SME will attempt to put + the device in BMPS mode (if not already in BMPS). If attempt to BMPS fails, + request for WoWL will be rejected. + +============================================================================*/ +/* $Header$ */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define WOWL_PTRN_MAX_SIZE 146 +#define WOWL_PTRN_MASK_MAX_SIZE 19 +#define WOWL_MAX_PTRNS_ALLOWED 22 + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/**============================================================================ + @brief hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be + used when PBM filtering is enabled + + @param ptrn : [in] pointer to the pattern string to be added + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn); + +/**============================================================================ + @brief hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern + + @param ptrn : [in] pointer to the pattern string to be removed + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_del_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn); + +/**============================================================================ + @brief hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern + sent from debugfs interface + + @param pAdapter : [in] pointer to the adapter + pattern_idx : [in] index of the pattern to be added + pattern_offset : [in] offset of the pattern in the frame payload + pattern_buf : [in] pointer to the pattern hex string to be added + pattern_mask : [in] pointer to the pattern mask hex string + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx, + v_U8_t pattern_offset, char *pattern_buf, + char *pattern_mask); + +/**============================================================================ + @brief hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern + sent from debugfs interface + + @param pAdapter : [in] pointer to the adapter + pattern_idx : [in] index of the pattern to be removed + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx); + +/**============================================================================ + @brief hdd_enter_wowl() - Function which will enable WoWL. Atleast one + of MP and PBM must be enabled + + @param enable_mp : [in] Whether to enable magic packet WoWL mode + @param enable_pbm : [in] Whether to enable pattern byte matching WoWL mode + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_enter_wowl (hdd_adapter_t *pAdapter, v_BOOL_t enable_mp, v_BOOL_t enable_pbm); + +/**============================================================================ + @brief hdd_exit_wowl() - Function which will disable WoWL + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_exit_wowl (hdd_adapter_t*pAdapter); + +/**============================================================================ + @brief hdd_init_wowl() - Init function which will initialize the WoWL module + and perform any required initial configuration + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_init_wowl (hdd_adapter_t* pAdapter); + +/**============================================================================ + @brief hdd_parse_hex() - function returns integer equivalent of hexa decimal + + @return : integer equivalent of hexa decimal + ===========================================================================*/ +int hdd_parse_hex(unsigned char c); + +#endif /* #ifndef _WLAN_HDD_WOWL_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_qct_driver.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_qct_driver.h new file mode 100644 index 000000000000..31c30706b9c7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_qct_driver.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __WLAN_QCT_DRIVER_H ) +#define __WLAN_QCT_DRIVER_H + +/**======================================================================== + + \file wlan_qct_driver.h + + \brief Header file for Wireless LAN Host Device Driver Kernel Module + + ========================================================================*/ + +/**======================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 04/05/09 kanand Created module. + + ===========================================================================*/ + +/*-------------------------------------------------------------------------- + * Include Files + *------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Preprocessor definitions and constants + *-------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Type declarations + *-------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + * Function declarations and documentation + * ------------------------------------------------------------------------*/ + +#endif // if !defined __WLAN_QCT_DRIVER_H diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c new file mode 100644 index 000000000000..6ba25063e076 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c @@ -0,0 +1,5298 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_assoc.c + \brief WLAN Host Device Driver implementation + + ========================================================================*/ +/**========================================================================= + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 05/06/09 Shailender Created module. + ==========================================================================*/ + +#include "wlan_hdd_includes.h" +#include +#include "dot11f.h" +#include "wlan_nlink_common.h" +#include "wlan_btc_svc.h" +#include "wlan_hdd_power.h" +#include "wlan_hdd_trace.h" +#include +#include +#include +#include "wlan_hdd_cfg80211.h" +#include "csrInsideApi.h" +#include "wlan_hdd_p2p.h" +#ifdef FEATURE_WLAN_TDLS +#include "wlan_hdd_tdls.h" +#endif +#include "sme_Api.h" +#include "wlan_hdd_hostapd.h" +#ifdef IPA_OFFLOAD +#include +#endif +#include + +struct ether_addr +{ + u_char ether_addr_octet[6]; +}; +// These are needed to recognize WPA and RSN suite types +#define HDD_WPA_OUI_SIZE 4 +v_U8_t ccpWpaOui00[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x00 }; +v_U8_t ccpWpaOui01[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x01 }; +v_U8_t ccpWpaOui02[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x02 }; +v_U8_t ccpWpaOui03[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x03 }; +v_U8_t ccpWpaOui04[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x04 }; +v_U8_t ccpWpaOui05[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x05 }; +#ifdef FEATURE_WLAN_ESE +v_U8_t ccpWpaOui06[ HDD_WPA_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM +#endif /* FEATURE_WLAN_ESE */ +#define HDD_RSN_OUI_SIZE 4 +v_U8_t ccpRSNOui00[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x00 }; // group cipher +v_U8_t ccpRSNOui01[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x01 }; // WEP-40 or RSN +v_U8_t ccpRSNOui02[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x02 }; // TKIP or RSN-PSK +v_U8_t ccpRSNOui03[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x03 }; // Reserved +v_U8_t ccpRSNOui04[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x04 }; // AES-CCMP +v_U8_t ccpRSNOui05[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; // WEP-104 +#ifdef FEATURE_WLAN_ESE +v_U8_t ccpRSNOui06[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_11W +v_U8_t ccpRSNOui07[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x06 }; // RSN-PSK-SHA256 +/* RSN-8021X-SHA256 */ +v_U8_t ccpRSNOui08[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; +#endif + +#if defined(WLAN_FEATURE_VOWIFI_11R) +// Offset where the EID-Len-IE, start. +#define FT_ASSOC_RSP_IES_OFFSET 6 /* Capability(2) + AID(2) + Status Code(2)*/ +#define FT_ASSOC_REQ_IES_OFFSET 4 /* Capability(2) + LI(2) */ +#endif + +#define BEACON_FRAME_IES_OFFSET 12 + +static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ); + +static v_VOID_t +hdd_connSetAuthenticated(hdd_adapter_t *pAdapter, v_U8_t authState) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + /* save the new connection state */ + hddLog(LOG1, FL("Authenticated state Changed from oldState:%d to State:%d"), + pHddStaCtx->conn_info.uIsAuthenticated, authState); + pHddStaCtx->conn_info.uIsAuthenticated = authState; + + /* Check is pending ROC request or not when auth state changed */ + schedule_delayed_work(&pHddCtx->rocReqWork, 0); +} + +v_VOID_t hdd_connSetConnectionState( hdd_adapter_t *pAdapter, + eConnectionState connState ) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + /* save the new connection state */ + hddLog(LOG1, FL("ConnectionState Changed from oldState:%d to State:%d"), + pHddStaCtx->conn_info.connState,connState); + pHddStaCtx->conn_info.connState = connState; + + /* Check is pending ROC request or not when connection state changed */ + schedule_delayed_work(&pHddCtx->rocReqWork, 0); +} + +// returns FALSE if not connected. +// returns TRUE for the two 'connected' states (Infra Associated or IBSS Connected ). +// returns the connection state. Can specify NULL if you dont' want to get the actual state. + +static inline v_BOOL_t hdd_connGetConnectionState( hdd_station_ctx_t *pHddStaCtx, + eConnectionState *pConnState ) +{ + v_BOOL_t fConnected; + eConnectionState connState; + + // get the connection state. + connState = pHddStaCtx->conn_info.connState; + // Set the fConnected return variable based on the Connected State. + if ( eConnectionState_Associated == connState || + eConnectionState_IbssConnected == connState || + eConnectionState_IbssDisconnected == connState) + { + fConnected = VOS_TRUE; + } + else + { + fConnected = VOS_FALSE; + } + + if ( pConnState ) + { + *pConnState = connState; + } + + return( fConnected ); +} + +v_BOOL_t hdd_connIsConnected( hdd_station_ctx_t *pHddStaCtx ) +{ + return( hdd_connGetConnectionState( pHddStaCtx, NULL ) ); +} + +bool hdd_is_connecting(hdd_station_ctx_t *hdd_sta_ctx) +{ + return (hdd_sta_ctx->conn_info.connState == + eConnectionState_Connecting); +} + +eCsrBand hdd_connGetConnectedBand( hdd_station_ctx_t *pHddStaCtx ) +{ + v_U8_t staChannel = 0; + + if ( eConnectionState_Associated == pHddStaCtx->conn_info.connState ) + { + staChannel = pHddStaCtx->conn_info.operationChannel; + } + + if ( staChannel > 0 && staChannel < 14 ) + return eCSR_BAND_24; + else if (staChannel >= 36 && staChannel <= 184 ) + return eCSR_BAND_5G; + else /* If station is not connected return as eCSR_BAND_ALL */ + return eCSR_BAND_ALL; +} + +static inline v_BOOL_t hdd_connGetConnectedCipherAlgo( hdd_station_ctx_t *pHddStaCtx, eCsrEncryptionType *pConnectedCipherAlgo ) +{ + v_BOOL_t fConnected = VOS_FALSE; + + fConnected = hdd_connGetConnectionState( pHddStaCtx, NULL ); + + if ( pConnectedCipherAlgo ) + { + *pConnectedCipherAlgo = pHddStaCtx->conn_info.ucEncryptionType; + } + + return( fConnected ); +} + +inline v_BOOL_t hdd_connGetConnectedBssType( hdd_station_ctx_t *pHddStaCtx, eMib_dot11DesiredBssType *pConnectedBssType ) +{ + v_BOOL_t fConnected = VOS_FALSE; + + fConnected = hdd_connGetConnectionState( pHddStaCtx, NULL ); + + if ( pConnectedBssType ) + { + *pConnectedBssType = pHddStaCtx->conn_info.connDot11DesiredBssType; + } + + return( fConnected ); +} + +static inline void hdd_connSaveConnectedBssType( hdd_station_ctx_t *pHddStaCtx, eCsrRoamBssType csrRoamBssType ) +{ + switch( csrRoamBssType ) + { + case eCSR_BSS_TYPE_INFRASTRUCTURE: + pHddStaCtx->conn_info.connDot11DesiredBssType = eMib_dot11DesiredBssType_infrastructure; + break; + + case eCSR_BSS_TYPE_IBSS: + case eCSR_BSS_TYPE_START_IBSS: + pHddStaCtx->conn_info.connDot11DesiredBssType = eMib_dot11DesiredBssType_independent; + break; + + /** We will never set the BssType to 'any' when attempting a connection + so CSR should never send this back to us.*/ + case eCSR_BSS_TYPE_ANY: + default: + VOS_ASSERT( 0 ); + break; + } + +} + +static void +hdd_connSaveConnectInfo(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + eCsrRoamBssType eBssType) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + eCsrEncryptionType encryptType = eCSR_ENCRYPT_TYPE_NONE; + + VOS_ASSERT( pRoamInfo ); + + if ( pRoamInfo ) + { + // Save the BSSID for the connection... + if ( eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType ) + { + VOS_ASSERT( pRoamInfo->pBssDesc ); + vos_mem_copy(pHddStaCtx->conn_info.bssId, pRoamInfo->bssid,6 ); + + // Save the Station ID for this station from the 'Roam Info'. + //For IBSS mode, staId is assigned in NEW_PEER_IND + //For reassoc, the staID doesn't change and it may be invalid in this structure + //so no change here. + if( !pRoamInfo->fReassocReq ) + { + pHddStaCtx->conn_info.staId [0]= pRoamInfo->staId; + } + } + else if ( eCSR_BSS_TYPE_IBSS == eBssType ) + { + vos_mem_copy(pHddStaCtx->conn_info.bssId, pRoamInfo->bssid,sizeof(pRoamInfo->bssid) ); + } + else + { + // can't happen. We need a valid IBSS or Infra setting in the BSSDescription + // or we can't function. + VOS_ASSERT( 0 ); + } + + // notify WMM + hdd_wmm_connect(pAdapter, pRoamInfo, eBssType); + + if( !pRoamInfo->u.pConnectedProfile ) + { + VOS_ASSERT( pRoamInfo->u.pConnectedProfile ); + } + else + { + // Get Multicast Encryption Type + encryptType = pRoamInfo->u.pConnectedProfile->mcEncryptionType; + pHddStaCtx->conn_info.mcEncryptionType = encryptType; + /* Get Unicast Encryption Type */ + encryptType = pRoamInfo->u.pConnectedProfile->EncryptionType; + pHddStaCtx->conn_info.ucEncryptionType = encryptType; + + pHddStaCtx->conn_info.authType = pRoamInfo->u.pConnectedProfile->AuthType; + + pHddStaCtx->conn_info.operationChannel = pRoamInfo->u.pConnectedProfile->operationChannel; + + // Save the ssid for the connection + vos_mem_copy( &pHddStaCtx->conn_info.SSID.SSID, &pRoamInfo->u.pConnectedProfile->SSID, sizeof( tSirMacSSid ) ); + + // Save dot11mode in which STA associated to AP + pHddStaCtx->conn_info.dot11Mode = pRoamInfo->u.pConnectedProfile->dot11Mode; + + pHddStaCtx->conn_info.proxyARPService = pRoamInfo->u.pConnectedProfile->proxyARPService; + pHddStaCtx->conn_info.nss = pRoamInfo->chan_info.nss; + pHddStaCtx->conn_info.rate_flags = pRoamInfo->chan_info.rate_flags; + } + } + + // save the connected BssType + hdd_connSaveConnectedBssType( pHddStaCtx, eBssType ); + +} + +#if defined(WLAN_FEATURE_VOWIFI_11R) +/* + * Send the 11R key information to the supplicant. + * Only then can the supplicant generate the PMK-R1. + * (BTW, the ESE supplicant also needs the Assoc Resp IEs + * for the same purpose.) + * + * Mainly the Assoc Rsp IEs are passed here. For the IMDA + * this contains the R1KHID, R0KHID and the MDID. + * For FT, this consists of the Reassoc Rsp FTIEs. + * This is the Assoc Response. + */ +static void hdd_SendFTAssocResponse(struct net_device *dev, hdd_adapter_t *pAdapter, + tCsrRoamInfo *pCsrRoamInfo) +{ + union iwreq_data wrqu; + char *buff; + unsigned int len = 0; + u8 *pFTAssocRsp = NULL; + + if (pCsrRoamInfo->nAssocRspLength == 0) + { + hddLog(LOGE, + "%s: pCsrRoamInfo->nAssocRspLength=%d", + __func__, (int)pCsrRoamInfo->nAssocRspLength); + return; + } + + pFTAssocRsp = (u8 *)(pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength + + pCsrRoamInfo->nAssocReqLength); + if (pFTAssocRsp == NULL) + { + hddLog(LOGE, "%s: AssocReq or AssocRsp is NULL", __func__); + return; + } + + // pFTAssocRsp needs to point to the IEs + pFTAssocRsp += FT_ASSOC_RSP_IES_OFFSET; + hddLog(LOG1, "%s: AssocRsp is now at %02x%02x", __func__, + (unsigned int)pFTAssocRsp[0], + (unsigned int)pFTAssocRsp[1]); + + // We need to send the IEs to the supplicant. + buff = kmalloc(IW_GENERIC_IE_MAX, GFP_ATOMIC); + if (buff == NULL) + { + hddLog(LOGE, "%s: kmalloc unable to allocate memory", __func__); + return; + } + + // Send the Assoc Resp, the supplicant needs this for initial Auth. + len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; + wrqu.data.length = len; + memset(buff, 0, IW_GENERIC_IE_MAX); + memcpy(buff, pFTAssocRsp, len); + wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, buff); + + kfree(buff); +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +#ifdef WLAN_FEATURE_VOWIFI_11R + +/*--------------------------------------------------- + * + * Send the FTIEs, RIC IEs during FT. This is eventually + * used to send the FT events to the supplicant + * + * At the reception of Auth2 we send the RIC followed + * by the auth response IEs to the supplicant. + * Once both are received in the supplicant, an FT + * event is generated to the supplicant. + * + *--------------------------------------------------- + */ +void hdd_SendFTEvent(hdd_adapter_t *pAdapter) +{ + tANI_U16 auth_resp_len = 0; + tANI_U32 ric_ies_length = 0; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + +#if defined(KERNEL_SUPPORT_11R_CFG80211) + struct cfg80211_ft_event_params ftEvent; + v_U8_t ftIe[DOT11F_IE_FTINFO_MAX_LEN]; + v_U8_t ricIe[DOT11F_IE_RICDESCRIPTOR_MAX_LEN]; + struct net_device *dev = pAdapter->dev; +#else + char *buff; + union iwreq_data wrqu; + tANI_U16 str_len; +#endif + +#if defined(KERNEL_SUPPORT_11R_CFG80211) + vos_mem_zero(ftIe, DOT11F_IE_FTINFO_MAX_LEN); + vos_mem_zero(ricIe, DOT11F_IE_RICDESCRIPTOR_MAX_LEN); + + sme_GetRICIEs( pHddCtx->hHal, pAdapter->sessionId, (u8 *)ricIe, + DOT11F_IE_RICDESCRIPTOR_MAX_LEN, &ric_ies_length ); + if (ric_ies_length == 0) + { + hddLog(LOGW, + "%s: RIC IEs is of length 0 not sending RIC Information for now", + __func__); + } + + ftEvent.ric_ies = ricIe; + ftEvent.ric_ies_len = ric_ies_length; + hddLog(LOG1, "%s: RIC IEs is of length %d", __func__, (int)ric_ies_length); + + sme_GetFTPreAuthResponse(pHddCtx->hHal, pAdapter->sessionId, (u8 *)ftIe, + DOT11F_IE_FTINFO_MAX_LEN, &auth_resp_len); + + if (auth_resp_len == 0) + { + hddLog(LOGE, "%s: AuthRsp FTIES is of length 0", __func__); + return; + } + + sme_SetFTPreAuthState(pHddCtx->hHal, pAdapter->sessionId, VOS_TRUE); + + ftEvent.target_ap = ftIe; + + ftEvent.ies = (u8 *)(ftIe + SIR_MAC_ADDR_LENGTH); + ftEvent.ies_len = auth_resp_len - SIR_MAC_ADDR_LENGTH; + + hddLog(LOG1, "%s ftEvent.ies_len %zu", __FUNCTION__, ftEvent.ies_len); + hddLog(LOG1, "%s ftEvent.ric_ies_len %zu", + __FUNCTION__, ftEvent.ric_ies_len ); + hddLog(LOG1, "%s ftEvent.target_ap %2x-%2x-%2x-%2x-%2x-%2x ", + __FUNCTION__, ftEvent.target_ap[0], ftEvent.target_ap[1], + ftEvent.target_ap[2], ftEvent.target_ap[3], ftEvent.target_ap[4], + ftEvent.target_ap[5]); + + (void)cfg80211_ft_event(dev, &ftEvent); + +#else + // We need to send the IEs to the supplicant + buff = kmalloc(IW_CUSTOM_MAX, GFP_ATOMIC); + if (buff == NULL) + { + hddLog(LOGE, "%s: kmalloc unable to allocate memory", __func__); + return; + } + vos_mem_zero(buff, IW_CUSTOM_MAX); + + // Sme needs to send the RIC IEs first + str_len = strlcpy(buff, "RIC=", IW_CUSTOM_MAX); + sme_GetRICIEs( pHddCtx->hHal, pAdapter->sessionId, (u8 *)&(buff[str_len]), + (IW_CUSTOM_MAX - str_len), &ric_ies_length ); + if (ric_ies_length == 0) + { + hddLog(LOGW, + "%s: RIC IEs is of length 0 not sending RIC Information for now", + __func__); + } + else + { + wrqu.data.length = str_len + ric_ies_length; + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff); + } + + // Sme needs to provide the Auth Resp + vos_mem_zero(buff, IW_CUSTOM_MAX); + str_len = strlcpy(buff, "AUTH=", IW_CUSTOM_MAX); + sme_GetFTPreAuthResponse(pHddCtx->hHal, pAdapter->sessionId, + (u8 *)&buff[str_len], + (IW_CUSTOM_MAX - str_len), + &auth_resp_len); + + if (auth_resp_len == 0) + { + hddLog(LOGE, "%s: AuthRsp FTIES is of length 0", __func__); + kfree(buff); + return; + } + + wrqu.data.length = str_len + auth_resp_len; + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff); + + kfree(buff); +#endif +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +#ifdef FEATURE_WLAN_ESE + +/* + * Send the ESE required "new AP Channel info" to the supplicant. + * (This keeps the supplicant "up to date" on the current channel.) + * + * The current (new AP) channel information is passed in. + */ +static void hdd_SendNewAPChannelInfo(struct net_device *dev, hdd_adapter_t *pAdapter, + tCsrRoamInfo *pCsrRoamInfo) +{ + union iwreq_data wrqu; + tSirBssDescription *descriptor = pCsrRoamInfo->pBssDesc; + + + if (descriptor == NULL) + { + hddLog(LOGE, + "%s: pCsrRoamInfo->pBssDesc=%p", + __func__, descriptor); + return; + } + + // Send the Channel event, the supplicant needs this to generate the Adjacent AP report. + hddLog(LOGW, "%s: Sending up an SIOCGIWFREQ, channelId=%d", __func__, descriptor->channelId); + memset(&wrqu, '\0', sizeof(wrqu)); + wrqu.freq.m = descriptor->channelId; + wrqu.freq.e = 0; + wrqu.freq.i = 0; + wireless_send_event(pAdapter->dev, SIOCGIWFREQ, &wrqu, NULL); +} + +#endif /* FEATURE_WLAN_ESE */ + +static void +hdd_SendUpdateBeaconIEsEvent(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pCsrRoamInfo) +{ + union iwreq_data wrqu; + u8 *pBeaconIes; + u8 currentLen = 0; + char *buff; + int totalIeLen = 0, currentOffset = 0, strLen; + + memset(&wrqu, '\0', sizeof(wrqu)); + + if (0 == pCsrRoamInfo->nBeaconLength) + { + hddLog(LOGW, "%s: pCsrRoamInfo->nBeaconFrameLength = 0", __func__); + return; + } + pBeaconIes = (u8 *)(pCsrRoamInfo->pbFrames + BEACON_FRAME_IES_OFFSET); + if (pBeaconIes == NULL) + { + hddLog(LOGW, "%s: Beacon IEs is NULL", __func__); + return; + } + + // pBeaconIes needs to point to the IEs + hddLog(LOG1, "%s: Beacon IEs is now at %02x%02x", __func__, + (unsigned int)pBeaconIes[0], + (unsigned int)pBeaconIes[1]); + hddLog(LOG1, "%s: Beacon IEs length = %d", __func__, pCsrRoamInfo->nBeaconLength - BEACON_FRAME_IES_OFFSET); + + // We need to send the IEs to the supplicant. + buff = kmalloc(IW_CUSTOM_MAX, GFP_ATOMIC); + if (buff == NULL) + { + hddLog(LOGE, "%s: kmalloc unable to allocate memory", __func__); + return; + } + vos_mem_zero(buff, IW_CUSTOM_MAX); + + strLen = strlcpy(buff,"BEACONIEs=", IW_CUSTOM_MAX); + currentLen = strLen + 1; + + totalIeLen = pCsrRoamInfo->nBeaconLength - BEACON_FRAME_IES_OFFSET; + do + { + /* If the beacon size exceeds max CUSTOM event size, break it into chunks of CUSTOM event + * max size and send it to supplicant. Changes are done in supplicant to handle this */ + vos_mem_zero(&buff[strLen + 1], IW_CUSTOM_MAX - (strLen + 1)); + currentLen = VOS_MIN(totalIeLen, IW_CUSTOM_MAX - (strLen + 1) - 1); + vos_mem_copy(&buff[strLen + 1], pBeaconIes+currentOffset, currentLen); + currentOffset += currentLen; + totalIeLen -= currentLen; + wrqu.data.length = strLen + 1 + currentLen; + if (totalIeLen) + buff[strLen] = 1; // This tells supplicant more chunks are pending + else + buff[strLen] = 0; // For last chunk of beacon IE to supplicant + + hddLog(LOG1, "%s: Beacon IEs length to supplicant = %d", __func__, currentLen); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff); + } while (totalIeLen > 0); + + kfree(buff); +} + +static void hdd_SendAssociationEvent(struct net_device *dev,tCsrRoamInfo *pCsrRoamInfo) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + union iwreq_data wrqu; + int we_event; + char *msg; + int type = -1; + v_MACADDR_t peerMacAddr; + +#if defined (WLAN_FEATURE_VOWIFI_11R) + // Added to find the auth type on the fly at run time + // rather than with cfg to see if FT is enabled + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile* pRoamProfile = &(pWextState->roamProfile); +#endif + + memset(&wrqu, '\0', sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + we_event = SIOCGIWAP; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (NULL != pCsrRoamInfo) + if (pCsrRoamInfo->roamSynchInProgress) + /* change logging before release */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + "LFR3:hdd_SendAssociationEvent"); +#endif + if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)/* Associated */ + { + if (!pCsrRoamInfo) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: STA in associated state but pCsrRoamInfo is null", + __func__); + return; + } + + wlan_hdd_incr_active_session(pHddCtx, pAdapter->device_mode); + memcpy(wrqu.ap_addr.sa_data, pCsrRoamInfo->pBssDesc->bssId, sizeof(pCsrRoamInfo->pBssDesc->bssId)); + type = WLAN_STA_ASSOC_DONE_IND; + +#ifdef WLAN_FEATURE_P2P_DEBUG + if(pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + { + if(globalP2PConnectionStatus == P2P_CLIENT_CONNECTING_STATE_1) + { + globalP2PConnectionStatus = P2P_CLIENT_CONNECTED_STATE_1; + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from " + "Connecting state to Connected State for 8-way " + "Handshake"); + } + else if(globalP2PConnectionStatus == P2P_CLIENT_CONNECTING_STATE_2) + { + globalP2PConnectionStatus = P2P_CLIENT_COMPLETED_STATE; + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from " + "Connecting state to P2P Client Connection Completed"); + } + } +#endif + pr_info("wlan: " MAC_ADDRESS_STR " connected to " MAC_ADDRESS_STR "\n", + MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes), + MAC_ADDR_ARRAY(wrqu.ap_addr.sa_data)); + hdd_SendUpdateBeaconIEsEvent(pAdapter, pCsrRoamInfo); + + + /* Send IWEVASSOCRESPIE Event if WLAN_FEATURE_CIQ_METRICS is Enabled Or + * Send IWEVASSOCRESPIE Event if WLAN_FEATURE_VOWIFI_11R is Enabled + * and fFTEnable is TRUE */ +#ifdef WLAN_FEATURE_VOWIFI_11R + // Send FT Keys to the supplicant when FT is enabled + if ((pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_FT_RSN_PSK) || + (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_FT_RSN) +#ifdef FEATURE_WLAN_ESE + || (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_RSN) || + (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_WPA) +#endif + ) + { + hdd_SendFTAssocResponse(dev, pAdapter, pCsrRoamInfo); + } +#endif + if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + { + tSirSmeChanInfo chan_info; + vos_mem_copy(peerMacAddr.bytes, pHddStaCtx->conn_info.bssId, + sizeof(pHddStaCtx->conn_info.bssId)); + chan_info.chan_id = pCsrRoamInfo->chan_info.chan_id; + chan_info.mhz = pCsrRoamInfo->chan_info.mhz; + chan_info.info = pCsrRoamInfo->chan_info.info; + chan_info.band_center_freq1 = pCsrRoamInfo->chan_info.band_center_freq1; + chan_info.band_center_freq2 = pCsrRoamInfo->chan_info.band_center_freq2; + chan_info.reg_info_1 = pCsrRoamInfo->chan_info.reg_info_1; + chan_info.reg_info_2 = pCsrRoamInfo->chan_info.reg_info_2; + + /* send peer status indication to oem app */ + hdd_SendPeerStatusIndToOemApp(&peerMacAddr, ePeerConnected, + pCsrRoamInfo->timingMeasCap, + pAdapter->sessionId, + &chan_info); + } + +#ifdef FEATURE_WLAN_TDLS + if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) { + hddLog(LOG1, + FL("tdls_prohibited: %d, tdls_chan_swit_prohibited: %d"), + pCsrRoamInfo->tdls_prohibited, + pCsrRoamInfo->tdls_chan_swit_prohibited); + + wlan_hdd_update_tdls_info(pAdapter, pCsrRoamInfo->tdls_prohibited, + pCsrRoamInfo->tdls_chan_swit_prohibited); + } +#endif + +#ifdef MSM_PLATFORM +#ifdef CONFIG_CNSS + /* start timer in sta/p2p_cli */ + spin_lock_bh(&pHddCtx->bus_bw_lock); + pAdapter->prev_tx_packets = pAdapter->stats.tx_packets; + pAdapter->prev_rx_packets = pAdapter->stats.rx_packets; + spin_unlock_bh(&pHddCtx->bus_bw_lock); + hdd_start_bus_bw_compute_timer(pAdapter); +#endif +#endif + } + else if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState) // IBss Associated + { + wlan_hdd_incr_active_session(pHddCtx, pAdapter->device_mode); + memcpy(wrqu.ap_addr.sa_data, pHddStaCtx->conn_info.bssId, ETH_ALEN); + type = WLAN_STA_ASSOC_DONE_IND; + pr_info("wlan: new IBSS connection to " MAC_ADDRESS_STR"\n", + MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId)); + } + else /* Not Associated */ + { + pr_info("wlan: disconnected\n"); + type = WLAN_STA_DISASSOC_DONE_IND; + memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN); + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); +#if defined(FEATURE_WLAN_LFR) && defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) + wlan_hdd_enable_roaming(pAdapter); +#endif + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_TRUE); +#endif + + if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + { + vos_mem_copy(peerMacAddr.bytes, pHddStaCtx->conn_info.bssId, + sizeof(pHddStaCtx->conn_info.bssId)); + + /* send peer status indication to oem app */ + hdd_SendPeerStatusIndToOemApp(&peerMacAddr, ePeerDisconnected, + 0, pAdapter->sessionId, + NULL); + } + +#ifdef WLAN_FEATURE_LPSS + pAdapter->rssi_send = VOS_FALSE; + if (pHddCtx->isUnloadInProgress != TRUE) + wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 0); +#endif + +#ifdef MSM_PLATFORM + /* stop timer in sta/p2p_cli */ + spin_lock_bh(&pHddCtx->bus_bw_lock); + pAdapter->prev_tx_packets = 0; + pAdapter->prev_rx_packets = 0; + spin_unlock_bh(&pHddCtx->bus_bw_lock); + hdd_stop_bus_bw_compute_timer(pAdapter); +#endif + } + hdd_dump_concurrency_info(pHddCtx); + + msg = NULL; + /*During the WLAN uninitialization,supplicant is stopped before the + driver so not sending the status of the connection to supplicant*/ + if ((pHddCtx->isLoadInProgress != TRUE) && + (pHddCtx->isUnloadInProgress != TRUE)) + { + wireless_send_event(dev, we_event, &wrqu, msg); +#ifdef FEATURE_WLAN_ESE + if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)/* Associated */ + { + if ( (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_RSN) || + (pRoamProfile->AuthType.authType[0] == eCSR_AUTH_TYPE_CCKM_WPA) ) + hdd_SendNewAPChannelInfo(dev, pAdapter, pCsrRoamInfo); + } +#endif + } + send_btc_nlink_msg(type, 0); +} + +static void hdd_connRemoveConnectInfo(hdd_station_ctx_t *pHddStaCtx) +{ + // Remove staId, bssId and peerMacAddress + pHddStaCtx->conn_info.staId [ 0 ] = 0; + vos_mem_zero( &pHddStaCtx->conn_info.bssId, sizeof( v_MACADDR_t ) ); + vos_mem_zero( &pHddStaCtx->conn_info.peerMacAddress[ 0 ], sizeof( v_MACADDR_t ) ); + + // Clear all security settings + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + pHddStaCtx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE; + pHddStaCtx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE; + + vos_mem_zero( &pHddStaCtx->conn_info.Keys, sizeof( tCsrKeys ) ); + vos_mem_zero( &pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey) ); + + // Set not-connected state + pHddStaCtx->conn_info.connDot11DesiredBssType = eCSR_BSS_TYPE_ANY; + pHddStaCtx->conn_info.proxyARPService = 0; + + vos_mem_zero( &pHddStaCtx->conn_info.SSID, sizeof( tCsrSSIDInfo ) ); +} +/* TODO Revisit this function. and data path */ +static VOS_STATUS hdd_roamDeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) +{ + VOS_STATUS vosStatus; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (WLAN_HDD_IBSS != pAdapter->device_mode) + { + hdd_disconnect_tx_rx(pAdapter); + } + else + { + // Need to cleanup all queues only if the last peer leaves + if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState) + { + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + hdd_disconnect_tx_rx(pAdapter); + } + else + { + // There is atleast one more peer, do not cleanup all queues + hdd_flush_ibss_tx_queues(pAdapter, staId); + } + } + + vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANTL_ClearSTAClient() failed to for staID %d. " + "Status= %d [0x%08X]", + __func__, staId, vosStatus, vosStatus ); + } + return( vosStatus ); +} + + +static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vstatus; + struct net_device *dev = pAdapter->dev; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + v_U8_t sta_id; + v_BOOL_t sendDisconInd = TRUE; + + // Sanity check + if(dev == NULL) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: net_dev is released return", __func__); + return eHAL_STATUS_FAILURE; + } + + // notify apps that we can't pass traffic anymore + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + netif_carrier_off(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; + +#ifdef IPA_OFFLOAD + if (hdd_ipa_is_enabled(pHddCtx)) + hdd_ipa_wlan_evt(pAdapter, pHddStaCtx->conn_info.staId[0], + WLAN_STA_DISCONNECT, pHddStaCtx->conn_info.bssId); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_TRUE); +#endif + +#ifdef QCA_PKT_PROTO_TRACE + /* STA disconnected, update into trace buffer */ + if (pHddCtx->cfg_ini->gEnableDebugLog) + { + vos_pkt_trace_buf_update("ST:DISASC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + + /* HDD has initiated disconnect, do not send disconnect indication + * to kernel. Sending disconnected event to kernel for userspace + * initiated disconnect will be handled by hdd_DisConnectHandler call + * to cfg80211_disconnected + */ + if ((eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState) || + (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL(" HDD has initiated a disconnect, no need to send" + " disconnect indication to kernel")); + sendDisconInd = FALSE; + } + + if(pHddStaCtx->conn_info.connState != eConnectionState_Disconnecting) + { + INIT_COMPLETION(pAdapter->disconnect_comp_var); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_Disconnecting", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_Disconnecting); + } + + /* If only STA mode is on */ + if((pHddCtx->concurrency_mode <= 1) && + (pHddCtx->no_of_open_sessions[WLAN_HDD_INFRA_STATION] <=1)) + { + pHddCtx->isAmpAllowed = VOS_TRUE; + } + hdd_clearRoamProfileIe( pAdapter ); + hdd_wmm_init( pAdapter ); + + // indicate 'disconnect' status to wpa_supplicant... + hdd_SendAssociationEvent(dev,pRoamInfo); + /* indicate disconnected event to nl80211 */ + if(roamStatus != eCSR_ROAM_IBSS_LEAVE) + { + /* Only send indication to kernel if not initiated by kernel */ + if (sendDisconInd) { + /* To avoid wpa_supplicant sending "HANGED" CMD to ICS UI */ + if (eCSR_ROAM_LOSTLINK == roamStatus) + { + if (pRoamInfo->reasonCode == + eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON) + pr_info( + "wlan: disconnected due to poor signal, rssi is %d dB\n", + pRoamInfo->rxRssi); + cfg80211_disconnected(dev, pRoamInfo->reasonCode, NULL, 0, + GFP_KERNEL); + } + else + cfg80211_disconnected(dev, WLAN_REASON_UNSPECIFIED, NULL, 0, + GFP_KERNEL); + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("sent disconnected event to nl80211, reason code %d"), + (eCSR_ROAM_LOSTLINK == roamStatus) ? + pRoamInfo->reasonCode : WLAN_REASON_UNSPECIFIED); + } + + if ((pHddCtx->isLoadInProgress != TRUE) && + (pHddCtx->isUnloadInProgress != TRUE)) + { +#ifdef WLAN_FEATURE_P2P_DEBUG + if(pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + { + if(globalP2PConnectionStatus == P2P_CLIENT_CONNECTED_STATE_1) + { + globalP2PConnectionStatus = P2P_CLIENT_DISCONNECTED_STATE; + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] 8 way Handshake completed " + "and moved to disconnected state"); + } + else if(globalP2PConnectionStatus == P2P_CLIENT_COMPLETED_STATE) + { + globalP2PConnectionStatus = P2P_NOT_ACTIVE; + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] P2P Client is removed " + "and moved to inactive state"); + } + } +#endif + + //If the Device Mode is Station + // and the P2P Client is Connected + //Enable BMPS + + /* + * In case of JB, as Change-Iface may or may not be called for p2p0 + * Enable BMPS/IMPS in case P2P_CLIENT disconnected + * If power save offload is enabled, Fw will take care + * of power save in case of concurrency. + */ + if((VOS_STATUS_SUCCESS == hdd_issta_p2p_clientconnected(pHddCtx)) + && !pHddCtx->cfg_ini->enablePowersaveOffload) + { + //Enable BMPS only of other Session is P2P Client + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); + + if (NULL != pVosContext) + { + pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); + + if(NULL != pHddCtx) + { + //Only P2P Client is there Enable Bmps back + if((0 == pHddCtx->no_of_open_sessions[VOS_STA_SAP_MODE]) && + (0 == pHddCtx->no_of_open_sessions[VOS_P2P_GO_MODE])) + { + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); + } + } + } + } + } + } + + hdd_wmm_adapter_clear(pAdapter); +#if defined(WLAN_FEATURE_VOWIFI_11R) + sme_FTReset(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId); +#endif + if (eCSR_ROAM_IBSS_LEAVE == roamStatus) { + v_U8_t i; + + sta_id = IBSS_BROADCAST_STAID; + vstatus = hdd_roamDeregisterSTA(pAdapter, sta_id); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) { + hddLog(LOGE, + FL("hdd_roamDeregisterSTA() failed for staID %d Status=%d [0x%x]"), + sta_id, status, status); + status = eHAL_STATUS_FAILURE; + } + pHddCtx->sta_to_adapter[sta_id] = NULL; + + /*Clear all the peer sta register with TL.*/ + for (i =0; i < HDD_MAX_NUM_IBSS_STA; i++) { + if (0 != pHddStaCtx->conn_info.staId[i]) { + sta_id = pHddStaCtx->conn_info.staId[i]; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Deregister StaID %d"),sta_id); + vstatus = hdd_roamDeregisterSTA( pAdapter, sta_id ); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("hdd_roamDeregisterSTA() failed to for staID %d. " + "Status= %d [0x%x]"), + sta_id, status, status); + status = eHAL_STATUS_FAILURE; + } + + /*set the staid and peer mac as 0, all other reset are + * done in hdd_connRemoveConnectInfo. + */ + pHddStaCtx->conn_info.staId[i]= 0; + vos_mem_zero(&pHddStaCtx->conn_info.peerMacAddress[i], sizeof(v_MACADDR_t)); + if (sta_id < (WLAN_MAX_STA_COUNT + 3)) + pHddCtx->sta_to_adapter[sta_id] = NULL; + } + } + } else { + sta_id = pHddStaCtx->conn_info.staId[0]; + //We should clear all sta register with TL, for now, only one. + vstatus = hdd_roamDeregisterSTA( pAdapter, sta_id ); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("hdd_roamDeregisterSTA() failed to for staID %d. " + "Status= %d [0x%x]"), + sta_id, status, status); + + status = eHAL_STATUS_FAILURE; + } + pHddCtx->sta_to_adapter[sta_id] = NULL; + } + + + // Clear saved connection information in HDD + hdd_connRemoveConnectInfo( pHddStaCtx ); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_NotConnected", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_NotConnected); +#ifdef WLAN_FEATURE_GTK_OFFLOAD + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + memset(&pHddStaCtx->gtkOffloadReqParams, 0, + sizeof (tSirGtkOffloadParams)); + pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE; + } +#endif + +#ifdef FEATURE_WLAN_TDLS + if (eCSR_ROAM_IBSS_LEAVE != roamStatus) + { + wlan_hdd_tdls_disconnection_callback(pAdapter); + } +#endif + + if (pHddCtx->cfg_ini->enablePowersaveOffload && + ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))) + { + sme_PsOffloadDisableDeferredPowerSave( + WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + } + + //Unblock anyone waiting for disconnect to complete + complete(&pAdapter->disconnect_comp_var); + return( status ); +} +static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + v_U8_t staId, + v_MACADDR_t *pPeerMacAddress, + tSirBssDescription *pBssDesc ) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + WLAN_STADescType staDesc = {0}; + eCsrEncryptionType connectedCipherAlgo; + v_BOOL_t fConnected; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ( NULL == pBssDesc) + { + return VOS_STATUS_E_FAILURE; + } + /* Get the Station ID from the one saved during the association */ + staDesc.ucSTAId = staId; + + if ( pHddStaCtx->conn_info.connDot11DesiredBssType == eMib_dot11DesiredBssType_infrastructure) + { + staDesc.wSTAType = WLAN_STA_INFRA; + + // grab the bssid from the connection info in the adapter structure and hand that + // over to TL when registering. + vos_mem_copy( staDesc.vSTAMACAddress.bytes, pHddStaCtx->conn_info.bssId,sizeof(pHddStaCtx->conn_info.bssId) ); + } + else + { + // for an IBSS 'connect', setup the Station Descriptor for TL. + staDesc.wSTAType = WLAN_STA_IBSS; + + /* + * Note that for IBSS, the STA MAC address and BSSID are going to be + * different where in infrastructure, they are the same (BSSID is the + * MAC address of the AP). So, for IBSS we have a second field to pass + * to TL in the STA descriptor that we don't pass when making an + * Infrastructure connection. + */ + vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) ); + vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, pHddStaCtx->conn_info.bssId,6 ); + } + + vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent ); + + // set the QoS field appropriately + if (hdd_wmm_is_active(pAdapter)) + { + staDesc.ucQosEnabled = 1; + } + else + { + staDesc.ucQosEnabled = 0; + } + + fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo ); + if ( connectedCipherAlgo != eCSR_ENCRYPT_TYPE_NONE ) + { + staDesc.ucProtectedFrame = 1; + } + else + { + staDesc.ucProtectedFrame = 0; + + } + +#ifdef FEATURE_WLAN_ESE + staDesc.ucIsEseSta = pRoamInfo->isESEAssoc; +#endif //FEATURE_WLAN_ESE + +#ifdef VOLANS_ENABLE_SW_REPLAY_CHECK + /* check whether replay check is valid for the station or not */ + if( (eCSR_ENCRYPT_TYPE_TKIP == connectedCipherAlgo) || (eCSR_ENCRYPT_TYPE_AES == connectedCipherAlgo)) + { + /* Encryption mode is either TKIP or AES + and replay check is valid for only these + two encryption modes */ + staDesc.ucIsReplayCheckValid = VOS_TRUE; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "HDD register TL ucIsReplayCheckValid %d: Replay check is needed for station", staDesc.ucIsReplayCheckValid); + } + + else + { + /* For other encryption modes replay check is + not needed */ + staDesc.ucIsReplayCheckValid = VOS_FALSE; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "HDD register TL ucIsReplayCheckValid %d", staDesc.ucIsReplayCheckValid); + } +#endif + +#ifdef FEATURE_WLAN_WAPI + hddLog(LOG1, "%s: WAPI STA Registered: %d", __func__, pAdapter->wapi_info.fIsWapiSta); + if (pAdapter->wapi_info.fIsWapiSta) + { + staDesc.ucIsWapiSta = 1; + } + else + { + staDesc.ucIsWapiSta = 0; + } +#endif /* FEATURE_WLAN_WAPI */ + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "HDD register TL Sec_enabled= %d.", staDesc.ucProtectedFrame ); + + // UMA is Not ready yet, Xlation will be done by TL + staDesc.ucSwFrameTXXlation = 1; + staDesc.ucSwFrameRXXlation = 1; + staDesc.ucAddRmvLLC = 1; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "HDD register TL QoS_enabled=%d", + staDesc.ucQosEnabled ); + // Initialize signatures and state + staDesc.ucUcastSig = pRoamInfo->ucastSig; + staDesc.ucBcastSig = pRoamInfo->bcastSig; + staDesc.ucInitState = pRoamInfo->fAuthRequired ? + WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED; + // Register the Station with TL... + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "%s: HDD register TL ucInitState=%d", __func__, staDesc.ucInitState ); + + /* Incase Micro controller data path offload enabled, + * All the traffic routed to WLAN host driver, do not need to + * route IPA. It should be routed kernel network stack */ +#if defined(IPA_OFFLOAD) && !defined(IPA_UC_OFFLOAD) + if (hdd_ipa_is_enabled(pHddCtx)) + vosStatus = WLANTL_RegisterSTAClient( pHddCtx->pvosContext, + hdd_ipa_process_rxt, + hdd_tx_complete_cbk, + hdd_tx_fetch_packet_cbk, &staDesc, + pBssDesc->rssi ); + else +#endif + vosStatus = WLANTL_RegisterSTAClient( pHddCtx->pvosContext, + hdd_rx_packet_cbk, + hdd_tx_complete_cbk, + hdd_tx_fetch_packet_cbk, &staDesc, + pBssDesc->rssi ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]", + vosStatus, vosStatus ); + return vosStatus; + } + + // if (WPA), tell TL to go to 'connected' and after keys come to the driver, + // then go to 'authenticated'. For all other authentication types + // (those that donot require upper layer authentication) we can put + // TL directly into 'authenticated' state. + if (staDesc.wSTAType != WLAN_STA_IBSS) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "STA type %d fConnected %d", staDesc.wSTAType, fConnected); + } + + + if ( !pRoamInfo->fAuthRequired ) + { + // Connections that do not need Upper layer auth, transition TL directly + // to 'Authenticated' state. + vosStatus = WLANTL_ChangeSTAState(pHddCtx->pvosContext, staDesc.ucSTAId, + WLANTL_STA_AUTHENTICATED, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + VOS_FALSE +#endif + ); + + hdd_connSetAuthenticated(pAdapter, VOS_TRUE); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "ULA auth StaId= %d. Changing TL state to CONNECTED" + "at Join time", pHddStaCtx->conn_info.staId[0] ); + vosStatus = WLANTL_ChangeSTAState(pHddCtx->pvosContext, staDesc.ucSTAId, + WLANTL_STA_CONNECTED, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + VOS_FALSE +#endif + ); + hdd_connSetAuthenticated(pAdapter, VOS_FALSE); + } + return( vosStatus ); +} + +static void hdd_SendReAssocEvent(struct net_device *dev, + hdd_adapter_t *pAdapter, + tCsrRoamInfo *pCsrRoamInfo, v_U8_t *reqRsnIe, + tANI_U32 reqRsnLength) +{ + unsigned int len = 0; + u8 *pFTAssocRsp = NULL; + v_U8_t *rspRsnIe = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); + tANI_U32 rspRsnLength = 0; + struct ieee80211_channel *chan; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + uint8_t buf_ssid_ie[2 + SIR_MAC_SSID_EID_MAX]; /* 2 bytes for EID and len */ + uint8_t *buf_ptr, ssid_ie_len; + struct cfg80211_bss *bss = NULL; + uint8_t *final_req_ie = NULL; + tCsrRoamConnectedProfile roam_profile; + tHalHandle hal_handle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + if (!rspRsnIe) { + hddLog(LOGE, FL("Unable to allocate RSN IE")); + return; + } + + if (pCsrRoamInfo == NULL) { + hddLog(LOGE, FL("Invalid CSR roam info")); + goto done; + } + + if (pCsrRoamInfo->nAssocRspLength == 0) { + hddLog(LOGE, FL("Invalid assoc response length")); + goto done; + } + + pFTAssocRsp = (u8 *)(pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength + + pCsrRoamInfo->nAssocReqLength); + if (pFTAssocRsp == NULL) + goto done; + + /* pFTAssocRsp needs to point to the IEs */ + pFTAssocRsp += FT_ASSOC_RSP_IES_OFFSET; + hddLog(LOG1, FL("AssocRsp is now at %02x%02x"), + (unsigned int)pFTAssocRsp[0], (unsigned int)pFTAssocRsp[1]); + + /* Active session count is decremented upon disconnection, but during + * roaming, there is no disconnect indication and hence active session + * count is not decremented. + * After roaming is completed, active session count is incremented + * as a part of connect indication but effectively after roaming the + * active session count should still be the same and hence upon + * successful reassoc decrement the active session count here */ + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); + + /* Send the Assoc Resp, the supplicant needs this for initial Auth */ + len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; + rspRsnLength = len; + memcpy(rspRsnIe, pFTAssocRsp, len); + memset(rspRsnIe + len, 0, IW_GENERIC_IE_MAX - len); + + chan = ieee80211_get_channel(pAdapter->wdev.wiphy, + (int)pCsrRoamInfo->pBssDesc->channelId); + memset(&roam_profile, 0, sizeof(tCsrRoamConnectedProfile)); + sme_RoamGetConnectProfile(hal_handle, pAdapter->sessionId, &roam_profile); + bss = cfg80211_get_bss(pAdapter->wdev.wiphy, chan, pCsrRoamInfo->bssid, + &roam_profile.SSID.ssId[0], roam_profile.SSID.length, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS) \ + && !defined(IEEE80211_PRIVACY) + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); +#else + IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#endif + + if (bss == NULL) + hddLog(LOGE, FL("Get BSS returned NULL")); + buf_ptr = buf_ssid_ie; + *buf_ptr = SIR_MAC_SSID_EID; + buf_ptr++; + *buf_ptr = roam_profile.SSID.length; /*len of ssid*/ + buf_ptr++; + vos_mem_copy(buf_ptr, &roam_profile.SSID.ssId[0], + roam_profile.SSID.length); + ssid_ie_len = 2 + roam_profile.SSID.length; + hddLog(LOG2, FL("SSIDIE:")); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + buf_ssid_ie, ssid_ie_len); + final_req_ie = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); + if (final_req_ie == NULL) + goto done; + buf_ptr = final_req_ie; + vos_mem_copy(buf_ptr, buf_ssid_ie, ssid_ie_len); + buf_ptr += ssid_ie_len; + vos_mem_copy(buf_ptr, reqRsnIe, reqRsnLength); + memcpy(rspRsnIe, pFTAssocRsp, len); + memset(final_req_ie + (ssid_ie_len + reqRsnLength), 0, + IW_GENERIC_IE_MAX - (ssid_ie_len + reqRsnLength)); + hddLog(LOG2, FL("Req RSN IE:")); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + final_req_ie, (ssid_ie_len +reqRsnLength)); + cfg80211_roamed_bss(dev, bss, + final_req_ie, (ssid_ie_len + reqRsnLength), + rspRsnIe, rspRsnLength, GFP_KERNEL); + + if (pHddCtx->cfg_ini->isRoamOffloadEnabled && + pCsrRoamInfo->roamSynchInProgress) + wlan_hdd_send_roam_auth_event(pHddCtx, pCsrRoamInfo->bssid, + reqRsnIe, reqRsnLength, rspRsnIe, + rspRsnLength, pCsrRoamInfo); +done: + sme_RoamFreeConnectProfile(hal_handle, &roam_profile); + if (final_req_ie) + kfree(final_req_ie); + kfree(rspRsnIe); +} + +/** + * hdd_is_roam_sync_in_progress()- Check if roam offloaded + * + * Return: roam sync status if roaming offloaded else false + */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static inline bool hdd_is_roam_sync_in_progress(tCsrRoamInfo *roaminfo) +{ + return roaminfo->roamSynchInProgress; +} +#else +static inline bool hdd_is_roam_sync_in_progress(tCsrRoamInfo *roaminfo) +{ + return false; +} +#endif + + +/** + * hdd_change_sta_state_authenticated()- + * This function changes STA state to authenticated + * @adapter: pointer to the adapter structure. + * @roaminfo: pointer to the RoamInfo structure. + * + * This is called from hdd_RoamSetKeyCompleteHandler + * in context to eCSR_ROAM_SET_KEY_COMPLETE event from fw. + * + * Return: 0 on success and errno on failure + */ +static int hdd_change_sta_state_authenticated(hdd_adapter_t *adapter, + tCsrRoamInfo *roaminfo) +{ + int ret; + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(adapter); + hdd_station_ctx_t *hddstactx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + hddLog(LOG1, + "Changing TL state to AUTHENTICATED for StaId= %d", + hddstactx->conn_info.staId[0]); + + /* Connections that do not need Upper layer authentication, + * transition TL to 'Authenticated' state after the keys are set + */ + ret = WLANTL_ChangeSTAState(hddctx->pvosContext, + hddstactx->conn_info.staId[0], + WLANTL_STA_AUTHENTICATED, + hdd_is_roam_sync_in_progress(roaminfo)); + hdd_connSetAuthenticated(adapter, VOS_TRUE); + if (hddctx->cfg_ini->enablePowersaveOffload && + ((WLAN_HDD_INFRA_STATION == adapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == adapter->device_mode))) { + sme_PsOffloadEnableDeferredPowerSave( + WLAN_HDD_GET_HAL_CTX(adapter), + adapter->sessionId, + hddstactx->hdd_ReassocScenario); + } + + return ret; +} + +void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamInfo roamInfo; + roamInfo.fAuthRequired = FALSE; + vos_mem_copy(roamInfo.bssid, + pHddStaCtx->roam_info.bssid, + VOS_MAC_ADDR_SIZE); + vos_mem_copy(roamInfo.peerMac, + pHddStaCtx->roam_info.peerMac, + VOS_MAC_ADDR_SIZE); + + halStatus = hdd_RoamSetKeyCompleteHandler(pAdapter, + &roamInfo, + pHddStaCtx->roam_info.roamId, + pHddStaCtx->roam_info.roamStatus, + eCSR_ROAM_RESULT_AUTHENTICATED); + if (halStatus != eHAL_STATUS_SUCCESS) + { + hddLog(LOGE, "%s: Set Key complete failure", __func__); + } + pHddStaCtx->roam_info.deferKeyComplete = FALSE; +} + +/** + * hdd_sap_restart_handle() - to handle restarting of SAP + * @work: name of the work + * + * Purpose of this function is to trigger sap start. this function + * will be called from workqueue. + * + * Return: void. + */ +static void hdd_sap_restart_handle(struct work_struct *work) +{ + hdd_adapter_t *sap_adapter; + hdd_context_t *hdd_ctx = container_of(work, + hdd_context_t, + sap_start_work); + vos_ssr_protect(__func__); + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + vos_ssr_unprotect(__func__); + return; + } + sap_adapter = hdd_get_adapter(hdd_ctx, + WLAN_HDD_SOFTAP); + if (sap_adapter == NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("sap_adapter is NULL")); + vos_ssr_unprotect(__func__); + return; + } + wlan_hdd_start_sap(sap_adapter); + + hdd_change_sap_restart_required_status(hdd_ctx, false); + vos_ssr_unprotect(__func__); +} + +static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ) +{ + struct net_device *dev = pAdapter->dev; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +#ifdef FEATURE_WLAN_FORCE_SAP_SCC + hdd_adapter_t *pHostapdAdapter; +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + v_U8_t reqRsnIe[DOT11F_IE_RSN_MAX_LEN]; + tANI_U32 reqRsnLength = DOT11F_IE_RSN_MAX_LEN; +#if defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) || defined (WLAN_FEATURE_VOWIFI_11R) + int ft_carrier_on = FALSE; +#endif + v_BOOL_t hddDisconInProgress = FALSE; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + unsigned long rc; + hdd_adapter_t *sap_adapter; + hdd_ap_ctx_t *hdd_ap_ctx; + uint8_t default_sap_channel = 6; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pRoamInfo && pRoamInfo->roamSynchInProgress) { + /* change logging before release */ + hddLog(VOS_TRACE_LEVEL_DEBUG, "LFR3:hdd_AssociationCompletionHandler"); + } +#endif + + /* HDD has initiated disconnect, do not send connect result indication + * to kernel as it will be handled by __cfg80211_disconnect. + */ + if(((eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState) || + (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState)) && + ((eCSR_ROAM_RESULT_ASSOCIATED == roamResult) || + (eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL(" Disconnect from HDD in progress ")); + hddDisconInProgress = TRUE; + } + + if ( eCSR_ROAM_RESULT_ASSOCIATED == roamResult ) + { + if (NULL == pRoamInfo) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pRoamInfo is NULL")); + return eHAL_STATUS_FAILURE; + } + if ( !hddDisconInProgress ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_Associated", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_Associated); + } + + // Save the connection info from CSR... + hdd_connSaveConnectInfo( pAdapter, pRoamInfo, eCSR_BSS_TYPE_INFRASTRUCTURE ); +#ifdef FEATURE_WLAN_WAPI + if ( pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE || + pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_WAPI_WAI_PSK ) + { + pAdapter->wapi_info.fIsWapiSta = 1; + } + else + { + pAdapter->wapi_info.fIsWapiSta = 0; + } +#endif /* FEATURE_WLAN_WAPI */ + + /* Indicate 'connect' status to user space */ + hdd_SendAssociationEvent(dev,pRoamInfo); + + if (hdd_is_mcc_in_24G(pHddCtx)) { + if ((pMac != NULL) && (pHddCtx->miracast_value)) { + hdd_set_mas(pAdapter, pHddCtx->miracast_value); + } + } + + // Initialize the Linkup event completion variable + INIT_COMPLETION(pAdapter->linkup_event_var); + + /* + Sometimes Switching ON the Carrier is taking time to activate the device properly. Before allowing any + packet to go up to the application, device activation has to be ensured for proper queue mapping by the + kernel. we have registered net device notifier for device change notification. With this we will come to + know that the device is getting activated properly. + */ +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (pHddStaCtx->ft_carrier_on == FALSE) + { +#endif + // Enable Linkup Event Servicing which allows the net device notifier to set the linkup event variable + pAdapter->isLinkUpSvcNeeded = TRUE; + + // Enable Linkup Event Servicing which allows the net device notifier to set the linkup event variable + pAdapter->isLinkUpSvcNeeded = TRUE; + + // Switch on the Carrier to activate the device + netif_carrier_on(dev); + + // Wait for the Link to up to ensure all the queues are set properly by the kernel + rc = wait_for_completion_timeout(&pAdapter->linkup_event_var, + msecs_to_jiffies(ASSOC_LINKUP_TIMEOUT)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning:ASSOC_LINKUP_TIMEOUT", __func__); + } + + // Disable Linkup Event Servicing - no more service required from the net device notifier call + pAdapter->isLinkUpSvcNeeded = FALSE; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + } + else { + pHddStaCtx->ft_carrier_on = FALSE; + ft_carrier_on = TRUE; + } +#endif + /* Check for STAID */ + if ((WLAN_MAX_STA_COUNT + 3) > pRoamInfo->staId) + pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; + else + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Wrong Staid: %d", __func__, + pRoamInfo->staId); + +#ifdef IPA_OFFLOAD + if (hdd_ipa_is_enabled(pHddCtx)) + hdd_ipa_wlan_evt(pAdapter, pRoamInfo->staId, WLAN_STA_CONNECT, + pRoamInfo->bssid); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_FALSE); +#endif + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if ((pHddCtx->cfg_ini->WlanMccToSccSwitchMode + != VOS_MCC_TO_SCC_SWITCH_DISABLE) && + ((0 == pHddCtx->cfg_ini->conc_custom_rule1) && + (0 == pHddCtx->cfg_ini->conc_custom_rule2)) +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + && !VOS_IS_DFS_CH(pHddStaCtx->conn_info.operationChannel) +#endif + ) { + adf_os_create_work(0, &pHddCtx->sta_ap_intf_check_work, + wlan_hdd_check_sta_ap_concurrent_ch_intf, (void *)pAdapter); + adf_os_sched_work(0, &pHddCtx->sta_ap_intf_check_work); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Checking for Concurrent Change interference"); + } +#endif + +#ifdef FEATURE_WLAN_TDLS + wlan_hdd_tdls_connection_callback(pAdapter); +#endif + +#ifdef QCA_PKT_PROTO_TRACE + /* STA Associated, update into trace buffer */ + if (pHddCtx->cfg_ini->gEnableDebugLog) + { + vos_pkt_trace_buf_update("ST:ASSOC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + //For reassoc, the station is already registered, all we need is to change the state + //of the STA in TL. + //If authentication is required (WPA/WPA2/DWEP), change TL to CONNECTED instead of AUTHENTICATED + if( !pRoamInfo->fReassocReq ) + { + struct cfg80211_bss *bss; +#ifdef WLAN_FEATURE_VOWIFI_11R + u8 *pFTAssocRsp = NULL; + unsigned int assocRsplen = 0; + u8 *pFTAssocReq = NULL; + unsigned int assocReqlen = 0; + struct ieee80211_channel *chan; +#endif + v_U8_t rspRsnIe[DOT11F_IE_RSN_MAX_LEN]; + tANI_U32 rspRsnLength = DOT11F_IE_RSN_MAX_LEN; + + /* add bss_id to cfg80211 data base */ + bss = wlan_hdd_cfg80211_update_bss_db(pAdapter, pRoamInfo); + if (NULL == bss) { + pr_err("wlan: Not able to create BSS entry\n"); + netif_carrier_off(dev); + return eHAL_STATUS_FAILURE; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if(pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_FT_RSN || + pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_FT_RSN_PSK ) + { + + //Association Response + pFTAssocRsp = (u8 *)(pRoamInfo->pbFrames + pRoamInfo->nBeaconLength + + pRoamInfo->nAssocReqLength); + if (pFTAssocRsp != NULL) + { + // pFTAssocRsp needs to point to the IEs + pFTAssocRsp += FT_ASSOC_RSP_IES_OFFSET; + hddLog(LOG1, "%s: AssocRsp is now at %02x%02x", __func__, + (unsigned int)pFTAssocRsp[0], + (unsigned int)pFTAssocRsp[1]); + assocRsplen = pRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; + } + else + { + hddLog(LOGE, "%s:AssocRsp is NULL", __func__); + assocRsplen = 0; + } + + //Association Request + pFTAssocReq = (u8 *)(pRoamInfo->pbFrames + + pRoamInfo->nBeaconLength); + if (pFTAssocReq != NULL) + { + if(!ft_carrier_on) + { + // pFTAssocReq needs to point to the IEs + pFTAssocReq += FT_ASSOC_REQ_IES_OFFSET; + hddLog(LOG1, "%s: pFTAssocReq is now at %02x%02x", __func__, + (unsigned int)pFTAssocReq[0], + (unsigned int)pFTAssocReq[1]); + assocReqlen = pRoamInfo->nAssocReqLength - FT_ASSOC_REQ_IES_OFFSET; + } + else + { + /* This should contain only the FTIEs */ + assocReqlen = pRoamInfo->nAssocReqLength; + } + } + else + { + hddLog(LOGE, "%s:AssocReq is NULL", __func__); + assocReqlen = 0; + } + + if(ft_carrier_on) + { + if ( !hddDisconInProgress ) + { + /* After roaming is completed, active session count is + * incremented as a part of connect indication but + * effectively the active session count should still + * be the same and hence upon successful reassoc + * decrement the active session count here */ + wlan_hdd_decr_active_session(pHddCtx, + pAdapter->device_mode); + + hddLog(LOG1, "%s ft_carrier_on is %d, sending roamed " + "indication", __FUNCTION__, ft_carrier_on); + chan = ieee80211_get_channel(pAdapter->wdev.wiphy, + (int)pRoamInfo->pBssDesc->channelId); + hddLog(LOG1, "assocReqlen %d assocRsplen %d", assocReqlen, + assocRsplen); + cfg80211_roamed(dev,chan, pRoamInfo->bssid, + pFTAssocReq, assocReqlen, pFTAssocRsp, assocRsplen, + GFP_KERNEL); + } + if (sme_GetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId)) + { + sme_SetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, FALSE); + pRoamInfo->fAuthRequired = FALSE; + + vos_mem_copy(pHddStaCtx->roam_info.bssid, + pRoamInfo->bssid, + HDD_MAC_ADDR_LEN); + vos_mem_copy(pHddStaCtx->roam_info.peerMac, + pRoamInfo->peerMac, + HDD_MAC_ADDR_LEN); + pHddStaCtx->roam_info.roamId = roamId; + pHddStaCtx->roam_info.roamStatus = roamStatus; + pHddStaCtx->roam_info.deferKeyComplete = TRUE; + } + } + else if ( !hddDisconInProgress ) + { + hddLog(LOG1, "%s ft_carrier_on is %d, sending connect " + "indication", __FUNCTION__, ft_carrier_on); + + hdd_connect_result(dev, pRoamInfo->bssid, + pFTAssocReq, assocReqlen, + pFTAssocRsp, assocRsplen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + } + else +#endif + { + /* wpa supplicant expecting WPA/RSN IE in connect result */ + csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &reqRsnLength, + reqRsnIe); + + csrRoamGetWpaRsnRspIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &rspRsnLength, + rspRsnIe); + if ( !hddDisconInProgress ) + { +#if defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if(ft_carrier_on) + hdd_SendReAssocEvent(dev, pAdapter, pRoamInfo, reqRsnIe, reqRsnLength); + else +#endif /* FEATURE_WLAN_ESE */ + + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: sending connect indication to nl80211:for bssid " MAC_ADDRESS_STR " reason:%d and Status:%d", + __func__, MAC_ADDR_ARRAY(pRoamInfo->bssid), + roamResult, roamStatus); + + /* inform connect result to nl80211 */ + hdd_connect_result(dev, pRoamInfo->bssid, + reqRsnIe, reqRsnLength, + rspRsnIe, rspRsnLength, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + } + } + if ( !hddDisconInProgress ) + { + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + pHddCtx->wiphy, +#endif + bss); + + // perform any WMM-related association processing + hdd_wmm_assoc(pAdapter, pRoamInfo, eCSR_BSS_TYPE_INFRASTRUCTURE); + + /* Start the Queue - Start tx queues before hdd_roamRegisterSTA, + since hdd_roamRegisterSTA will flush any cached data frames + immediately */ + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_enable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = FALSE; + + // Register the Station with TL after associated... + vosStatus = hdd_roamRegisterSTA( pAdapter, + pRoamInfo, + pHddStaCtx->conn_info.staId[ 0 ], + NULL, + pRoamInfo->pBssDesc ); + } + } + else + { + /* wpa supplicant expecting WPA/RSN IE in connect result */ + /* in case of reassociation also need to indicate it to supplicant */ + csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &reqRsnLength, + reqRsnIe); + + hdd_SendReAssocEvent(dev, pAdapter, pRoamInfo, reqRsnIe, reqRsnLength); + //Reassoc successfully + if( pRoamInfo->fAuthRequired ) + { + vosStatus = WLANTL_ChangeSTAState(pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[0], + WLANTL_STA_CONNECTED, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + VOS_FALSE +#endif + ); + hdd_connSetAuthenticated(pAdapter, VOS_FALSE); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: staId: %d Changing TL state to AUTHENTICATED", + __func__, pHddStaCtx->conn_info.staId[ 0 ] ); + vosStatus = WLANTL_ChangeSTAState(pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[0], + WLANTL_STA_AUTHENTICATED, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + VOS_FALSE +#endif + ); + hdd_connSetAuthenticated(pAdapter, VOS_TRUE); + } + + if ( VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + // perform any WMM-related association processing + hdd_wmm_assoc(pAdapter, pRoamInfo, eCSR_BSS_TYPE_INFRASTRUCTURE); + } + + /* Start the tx queues */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pRoamInfo->roamSynchInProgress) { + hddLog(VOS_TRACE_LEVEL_DEBUG, "LFR3:netif_tx_wake_all_queues"); + } +#endif + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_enable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = FALSE; + } + + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Cannot register STA with TL. Failed with vosStatus = %d [%08X]", + vosStatus, vosStatus ); + } +#ifdef WLAN_FEATURE_11W + vos_mem_zero( &pAdapter->hdd_stats.hddPmfStats, + sizeof(pAdapter->hdd_stats.hddPmfStats) ); +#endif + } + else + { + hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + if (pRoamInfo) + pr_info("wlan: connection failed with " MAC_ADDRESS_STR + " reason:%d and Status:%d\n", + MAC_ADDR_ARRAY(pRoamInfo->bssid), + roamResult, roamStatus); + else + pr_info("wlan: connection failed with " MAC_ADDRESS_STR + " reason:%d and Status:%d\n", + MAC_ADDR_ARRAY(pWextState->req_bssId), + roamResult, roamStatus); + + /* Set connection state to eConnectionState_NotConnected only when CSR + * has completed operation - with a ASSOCIATION_FAILURE status + */ + if ( eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus && !hddDisconInProgress ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_NotConnected", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_NotConnected); + } + if((pHddCtx->concurrency_mode <= 1) && + (pHddCtx->no_of_open_sessions[WLAN_HDD_INFRA_STATION] <=1)) + { + pHddCtx->isAmpAllowed = VOS_TRUE; + } + + //If the Device Mode is Station + // and the P2P Client is Connected + //Enable BMPS + + /* + * In case of JB, as Change-Iface may or may not be called for p2p0 + * Enable BMPS/IMPS in case P2P_CLIENT disconnected + * If ps offload is enabled, fw will take care in case of concurrency. + */ + if(((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) && + (vos_concurrent_open_sessions_running()) && + !pHddCtx->cfg_ini->enablePowersaveOffload) + { + //Enable BMPS only of other Session is P2P Client + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); + + if (NULL != pVosContext) + { + pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); + + if(NULL != pHddCtx) + { + //Only P2P Client is there Enable Bmps back + if((0 == pHddCtx->no_of_open_sessions[VOS_STA_SAP_MODE]) && + (0 == pHddCtx->no_of_open_sessions[VOS_P2P_GO_MODE])) + { + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); + } + } + } + } + + /* CR465478: Only send up a connection failure result when CSR has + * completed operation - with a ASSOCIATION_FAILURE status.*/ + if ( eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus && !hddDisconInProgress ) + { + if (pRoamInfo) + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: send connect failure to nl80211: for bssid " MAC_ADDRESS_STR" reason:%d and Status:%d " , + __func__, MAC_ADDR_ARRAY(pRoamInfo->bssid), + roamResult, roamStatus); + else + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: connect failed: for bssid " MAC_ADDRESS_STR " reason:%d and Status:%d " , + __func__, MAC_ADDR_ARRAY(pWextState->req_bssId), + roamResult, roamStatus); + + /* Clear the roam profile */ + hdd_clearRoamProfileIe(pAdapter); + + /* inform association failure event to nl80211 */ + if ( eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL == roamResult ) + { + if (pRoamInfo) + hdd_connect_result(dev, pRoamInfo->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + else + hdd_connect_result(dev, pWextState->req_bssId, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } + else + { + if (pRoamInfo) { + eCsrAuthType authType = + pWextState->roamProfile.AuthType.authType[0]; + v_BOOL_t isWep = (authType == eCSR_AUTH_TYPE_OPEN_SYSTEM) || + (authType == eCSR_AUTH_TYPE_SHARED_KEY); + + /* In case of OPEN-WEP or SHARED-WEP authentication, + * send exact protocol reason code. This enables user + * applications to reconnect the station with correct + * configuration. + */ + hdd_connect_result(dev, pRoamInfo->bssid, + NULL, 0, NULL, 0, + isWep ? pRoamInfo->reasonCode : + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else + hdd_connect_result(dev, pWextState->req_bssId, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } + } + + if (pRoamInfo) { + if ((eSIR_SME_JOIN_TIMEOUT_RESULT_CODE == pRoamInfo->statusCode) || + (eSIR_SME_AUTH_TIMEOUT_RESULT_CODE == pRoamInfo->statusCode) || + (eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE == pRoamInfo->statusCode)) { + wlan_hdd_cfg80211_update_bss_list(pAdapter, pRoamInfo); + } + } + + hdd_wmm_init( pAdapter ); + + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + netif_carrier_off(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; + + } + + if (pHddCtx->cfg_ini->conc_custom_rule1 && + (true == hdd_is_sap_restart_required(pHddCtx))) { + sap_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP); + if (sap_adapter == NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("sap_adapter is NULL")); + return eHAL_STATUS_FAILURE; + } + + if (test_bit(SOFTAP_BSS_STARTED, &sap_adapter->event_flags)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Oops SAP is already in started state")); + return eHAL_STATUS_FAILURE; + } + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(sap_adapter); + if ((eCSR_ROAM_RESULT_ASSOCIATED == roamResult) && + pHddStaCtx->conn_info.operationChannel < SIR_11A_CHANNEL_BEGIN) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Starting SAP on channel [%d] after STA assoc complete"), + pHddStaCtx->conn_info.operationChannel); + hdd_ap_ctx->operatingChannel = + pHddStaCtx->conn_info.operationChannel; + } else { + /* start on default SAP channel */ + hdd_ap_ctx->operatingChannel = + default_sap_channel; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Starting SAP on channel [%d] after STA assoc failed"), + default_sap_channel); + } + hdd_ap_ctx->sapConfig.vht_channel_width = + hdd_ap_ctx->sapConfig.ch_width_orig; + sme_SelectCBMode(WLAN_HDD_GET_HAL_CTX(sap_adapter), + hdd_ap_ctx->sapConfig.SapHw_mode, + hdd_ap_ctx->operatingChannel, + hdd_ap_ctx->sapConfig.sec_ch, + &hdd_ap_ctx->sapConfig.vht_channel_width, + hdd_ap_ctx->sapConfig.ch_width_orig); + /* + * Create a workqueue and let the workqueue handle the restarting + * sap task. if we directly call sap restart function without + * creating workqueue then our main thread might go to sleep which + * is not acceptable. + */ +#ifdef CONFIG_CNSS + cnss_init_work(&pHddCtx->sap_start_work, + hdd_sap_restart_handle); +#else + INIT_WORK(&pHddCtx->sap_start_work, + hdd_sap_restart_handle); +#endif + schedule_work(&pHddCtx->sap_start_work); + + + } + +#ifdef FEATURE_WLAN_FORCE_SAP_SCC + if (eCSR_ROAM_RESULT_ASSOCIATED == roamResult && + pHddCtx->cfg_ini->SapSccChanAvoidance) { + pHostapdAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP); + if (pHostapdAdapter != NULL) { + /* Restart SAP if its operating channel is different + * from AP channel. + */ + if (pHostapdAdapter->sessionCtx.ap.operatingChannel != + pRoamInfo->pBssDesc->channelId) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Restart Sap as SAP channel is %d and STA channel is %d", + pHostapdAdapter->sessionCtx.ap.operatingChannel, + pRoamInfo->pBssDesc->channelId); + hdd_restart_softap(pHddCtx, pHostapdAdapter); + } + } + } +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + return eHAL_STATUS_SUCCESS; +} + +/**============================================================================ + * + @brief hdd_RoamIbssIndicationHandler() - Here we update the status of the + Ibss when we receive information that we have started/joined an ibss session + + ===========================================================================*/ +static void hdd_RoamIbssIndicationHandler( hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ) +{ + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s: id %d, status %d, result %d", + __func__, pAdapter->dev->name, roamId, roamStatus, roamResult); + + switch( roamResult ) + { + // both IBSS Started and IBSS Join should come in here. + case eCSR_ROAM_RESULT_IBSS_STARTED: + case eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS: + case eCSR_ROAM_RESULT_IBSS_COALESCED: + { + hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + + if (NULL == pRoamInfo) + { + VOS_ASSERT(0); + return; + } + + /* When IBSS Started comes from CSR, we need to move + * connection state to IBSS Disconnected (meaning no peers + * are in the IBSS). + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_IbssDisconnected", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_IbssDisconnected); + /* Notify wmm */ + hdd_wmm_connect(pAdapter, pRoamInfo, eCSR_BSS_TYPE_IBSS); + pHddCtx->sta_to_adapter[IBSS_BROADCAST_STAID] = pAdapter; + hdd_roamRegisterSTA (pAdapter, pRoamInfo, + IBSS_BROADCAST_STAID, + &broadcastMacAddr, pRoamInfo->pBssDesc); + + if (pRoamInfo->pBssDesc) + { + struct cfg80211_bss *bss; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)) || defined(WITH_BACKPORTS) + struct ieee80211_channel *chan; + int chan_no; + unsigned int freq; +#endif + /* we created the IBSS, notify supplicant */ + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s: created ibss " + MAC_ADDRESS_STR, + __func__, pAdapter->dev->name, + MAC_ADDR_ARRAY(pRoamInfo->pBssDesc->bssId)); + + /* we must first give cfg80211 the BSS information */ + bss = wlan_hdd_cfg80211_update_bss_db(pAdapter, pRoamInfo); + if (NULL == bss) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: %s: unable to create IBSS entry", + __func__, pAdapter->dev->name); + return; + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)) || defined(WITH_BACKPORTS) + chan_no = pRoamInfo->pBssDesc->channelId; + + if (chan_no <= 14) + freq = ieee80211_channel_to_frequency(chan_no, + IEEE80211_BAND_2GHZ); + else + freq = ieee80211_channel_to_frequency(chan_no, + IEEE80211_BAND_5GHZ); + + chan = ieee80211_get_channel(pAdapter->wdev.wiphy, freq); + + if (chan) + cfg80211_ibss_joined(pAdapter->dev, bss->bssid, + chan, GFP_KERNEL); + else + hddLog(LOGE, FL("%s: chanId: %d, can't find channel"), + pAdapter->dev->name, + (int)pRoamInfo->pBssDesc->channelId); +#else + cfg80211_ibss_joined(pAdapter->dev, bss->bssid, GFP_KERNEL); +#endif + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + pHddCtx->wiphy, +#endif + bss); + } + + break; + } + + case eCSR_ROAM_RESULT_IBSS_START_FAILED: + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s: unable to create IBSS", + __func__, pAdapter->dev->name); + break; + } + + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s: unexpected result %d", + __func__, pAdapter->dev->name, (int)roamResult); + break; + } + + return; +} + +/**============================================================================ + * + @brief roamSaveIbssStation() - Save the IBSS peer MAC address in the adapter. + This information is passed to iwconfig later. The peer that joined + last is passed as information to iwconfig. + If we add HDD_MAX_NUM_IBSS_STA or less STA we return success else we + return FALSE. + + ===========================================================================*/ +static int roamSaveIbssStation( hdd_station_ctx_t *pHddStaCtx, v_U8_t staId, v_MACADDR_t *peerMacAddress ) +{ + int fSuccess = FALSE; + int idx = 0; + + for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) + { + if ( 0 == pHddStaCtx->conn_info.staId[ idx ] ) + { + pHddStaCtx->conn_info.staId[ idx ] = staId; + + vos_copy_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ idx ], peerMacAddress ); + + fSuccess = TRUE; + break; + } + } + + return( fSuccess ); +} +/**============================================================================ + * + @brief roamRemoveIbssStation() - Remove the IBSS peer MAC address in the adapter. + If we remove HDD_MAX_NUM_IBSS_STA or less STA we return success else we + return FALSE. + + ===========================================================================*/ +static int roamRemoveIbssStation( hdd_adapter_t *pAdapter, v_U8_t staId ) +{ + int fSuccess = FALSE; + int idx = 0; + v_U8_t valid_idx = 0; + v_U8_t del_idx = 0; + v_U8_t empty_slots = 0; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) + { + if ( staId == pHddStaCtx->conn_info.staId[ idx ] ) + { + pHddStaCtx->conn_info.staId[ idx ] = 0; + + vos_zero_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ idx ] ); + + fSuccess = TRUE; + + // Note the deleted Index, if its 0 we need special handling + del_idx = idx; + + empty_slots++; + } + else + { + if (pHddStaCtx->conn_info.staId[idx] != 0) + { + valid_idx = idx; + } + else + { + // Found an empty slot + empty_slots++; + } + } + } + + if (HDD_MAX_NUM_IBSS_STA == empty_slots) + { + // Last peer departed, set the IBSS state appropriately + pHddStaCtx->conn_info.connState = eConnectionState_IbssDisconnected; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Last IBSS Peer Departed!!!" ); + } + + // Find next active staId, to have a valid sta trigger for TL. + if (fSuccess == TRUE) + { + if (del_idx == 0) + { + if (pHddStaCtx->conn_info.staId[valid_idx] != 0) + { + pHddStaCtx->conn_info.staId[0] = pHddStaCtx->conn_info.staId[valid_idx]; + vos_copy_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ 0 ], + &pHddStaCtx->conn_info.peerMacAddress[ valid_idx ]); + + pHddStaCtx->conn_info.staId[valid_idx] = 0; + vos_zero_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ valid_idx ] ); + } + } + } + return( fSuccess ); +} + +/**============================================================================ + * + @brief roamIbssConnectHandler() : We update the status of the IBSS to + connected in this function. + + ===========================================================================*/ +static eHalStatus roamIbssConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo ) +{ + struct cfg80211_bss *bss; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: IBSS Connect Indication from SME!!! " + "Set HDD connState to eConnectionState_IbssConnected", + __func__); + // Set the internal connection state to show 'IBSS Connected' (IBSS with a partner stations)... + hdd_connSetConnectionState(pAdapter, + eConnectionState_IbssConnected); + + // Save the connection info from CSR... + hdd_connSaveConnectInfo( pAdapter, pRoamInfo, eCSR_BSS_TYPE_IBSS ); + + // Send the bssid address to the wext. + hdd_SendAssociationEvent(pAdapter->dev, pRoamInfo); + /* add bss_id to cfg80211 data base */ + bss = wlan_hdd_cfg80211_update_bss_db(pAdapter, pRoamInfo); + if (NULL == bss) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: %s: unable to create IBSS entry", + __func__, pAdapter->dev->name); + return eHAL_STATUS_FAILURE; + } + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + WLAN_HDD_GET_CTX(pAdapter)->wiphy, +#endif + bss); + + return( eHAL_STATUS_SUCCESS ); +} +/**============================================================================ + * + @brief hdd_RoamSetKeyCompleteHandler() - Update the security parameters. + + ===========================================================================*/ +static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ) +{ + eCsrEncryptionType connectedCipherAlgo; + v_BOOL_t fConnected = FALSE; + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + ENTER(); + + if (NULL == pRoamInfo) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "pRoamInfo is NULL"); + return eHAL_STATUS_FAILURE; + } + // if ( WPA ), tell TL to go to 'authenticated' after the keys are set. + // then go to 'authenticated'. For all other authentication types (those that do + // not require upper layer authentication) we can put TL directly into 'authenticated' + // state. + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Set Key completion roamStatus=%d roamResult=%d encryptionType=%d " + MAC_ADDRESS_STR, roamStatus, roamResult, + pHddStaCtx->conn_info.ucEncryptionType, + MAC_ADDR_ARRAY(pRoamInfo->peerMac)); + + fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo ); + if( fConnected ) + { + if ( WLAN_HDD_IBSS == pAdapter->device_mode ) + { + v_U8_t staId; + + v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + + if ( 0 == memcmp( pRoamInfo->peerMac, + &broadcastMacAddr, VOS_MAC_ADDR_SIZE ) ) + { + vosStatus = WLANTL_STAPtkInstalled( pHddCtx->pvosContext, + IBSS_BROADCAST_STAID); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + else + { + vosStatus = hdd_Ibss_GetStaId(pHddStaCtx, + (v_MACADDR_t*)pRoamInfo->peerMac, + &staId); + if ( VOS_STATUS_SUCCESS == vosStatus ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "WLAN TL STA Ptk Installed for STAID=%d", staId); + vosStatus = WLANTL_STAPtkInstalled( pHddCtx->pvosContext, + staId); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + } + } + else + { + /* + * TODO: Considering getting a state machine in HDD later. + * This routine is invoked twice. 1)set PTK 2)set GTK. + * The following if statement will be TRUE when setting GTK. + * At this time we don't handle the state in detail. + * Related CR: 174048 - TL not in authenticated state + */ + if (eCSR_ROAM_RESULT_AUTHENTICATED == roamResult) { + pHddStaCtx->conn_info.gtk_installed = true; + /* + * PTK exchange happens in preauthentication itself if key_mgmt is + * FT-PSK, ptk_installed was false as there is no set PTK after + * roaming. STA TL state moves to athenticated only if ptk_installed + * is true. So, make ptk_installed to true in case of 11R roaming. + */ +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pRoamInfo->is11rAssoc) + pHddStaCtx->conn_info.ptk_installed = true; +#endif + } else { + pHddStaCtx->conn_info.ptk_installed = true; + } + + /* In WPA case move STA to authenticated when ptk is installed. + * Earlier in WEP case STA was moved to AUTHENTICATED prior to + * setting the unicast key and it was resulting in sending + * few un-encrypted packet. Now in WEP case STA state will + * be moved to AUTHENTICATED after we set the unicast + * and broadcast key. + */ + if ((pHddStaCtx->conn_info.ucEncryptionType == + eCSR_ENCRYPT_TYPE_WEP40) || + (pHddStaCtx->conn_info.ucEncryptionType == + eCSR_ENCRYPT_TYPE_WEP104) || + (pHddStaCtx->conn_info.ucEncryptionType == + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) || + (pHddStaCtx->conn_info.ucEncryptionType == + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY)) { + if (pHddStaCtx->conn_info.gtk_installed && + pHddStaCtx->conn_info.ptk_installed) + vosStatus = hdd_change_sta_state_authenticated(pAdapter, + pRoamInfo); + } else if (pHddStaCtx->conn_info.ptk_installed) + vosStatus = hdd_change_sta_state_authenticated(pAdapter, + pRoamInfo); + + if (pHddStaCtx->conn_info.gtk_installed && + pHddStaCtx->conn_info.ptk_installed) { + pHddStaCtx->conn_info.gtk_installed = false; + pHddStaCtx->conn_info.ptk_installed = false; + } + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + } + else + { + // possible disassoc after issuing set key and waiting set key complete + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + + EXIT(); + return( eHAL_STATUS_SUCCESS ); +} +/**============================================================================ + * + @brief hdd_RoamMicErrorIndicationHandler() - This function indicates the Mic failure to the supplicant. + ===========================================================================*/ +static eHalStatus hdd_RoamMicErrorIndicationHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, eCsrRoamResult roamResult ) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if( eConnectionState_Associated == pHddStaCtx->conn_info.connState && + TKIP_COUNTER_MEASURE_STOPED == pHddStaCtx->WextState.mTKIPCounterMeasures ) + { + struct iw_michaelmicfailure msg; + union iwreq_data wreq; + memset(&msg, '\0', sizeof(msg)); + msg.src_addr.sa_family = ARPHRD_ETHER; + memcpy(msg.src_addr.sa_data, pRoamInfo->u.pMICFailureInfo->taMacAddr, sizeof(pRoamInfo->u.pMICFailureInfo->taMacAddr)); + hddLog(LOG1, "MIC MAC " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(msg.src_addr.sa_data)); + + if(pRoamInfo->u.pMICFailureInfo->multicast == eSIR_TRUE) + msg.flags = IW_MICFAILURE_GROUP; + else + msg.flags = IW_MICFAILURE_PAIRWISE; + memset(&wreq, 0, sizeof(wreq)); + wreq.data.length = sizeof(msg); + wireless_send_event(pAdapter->dev, IWEVMICHAELMICFAILURE, &wreq, (char *)&msg); + /* inform mic failure to nl80211 */ + cfg80211_michael_mic_failure(pAdapter->dev, + pRoamInfo->u.pMICFailureInfo->taMacAddr, + ((pRoamInfo->u.pMICFailureInfo->multicast == eSIR_TRUE) ? + NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE), + pRoamInfo->u.pMICFailureInfo->keyId, + pRoamInfo->u.pMICFailureInfo->TSC, + GFP_KERNEL); + + } + + return( eHAL_STATUS_SUCCESS ); +} + +/**============================================================================ + * + @brief roamRoamConnectStatusUpdateHandler() - The Ibss connection status is + updated regularly here in this function. + + ===========================================================================*/ +static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ) +{ + VOS_STATUS vosStatus; + + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + switch( roamResult ) + { + case eCSR_ROAM_RESULT_IBSS_NEW_PEER: + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + struct station_info staInfo; + + pr_info ( "IBSS New Peer indication from SME " + "with peerMac " MAC_ADDRESS_STR " BSSID: " MAC_ADDRESS_STR " and stationID= %d", + MAC_ADDR_ARRAY(pRoamInfo->peerMac), + MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId), + pRoamInfo->staId ); + + if ( !roamSaveIbssStation( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pRoamInfo->staId, (v_MACADDR_t *)pRoamInfo->peerMac ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "New IBSS peer but we already have the max we can handle. Can't register this one" ); + break; + } + + pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; + + pHddCtx->sta_to_adapter[IBSS_BROADCAST_STAID] = pAdapter; + WLANTL_UpdateSTABssIdforIBSS(pHddCtx->pvosContext, + IBSS_BROADCAST_STAID,pHddStaCtx->conn_info.bssId); + + // Register the Station with TL for the new peer. + vosStatus = hdd_roamRegisterSTA( pAdapter, + pRoamInfo, + pRoamInfo->staId, + (v_MACADDR_t *)pRoamInfo->peerMac, + pRoamInfo->pBssDesc ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Cannot register STA with TL for IBSS. Failed with vosStatus = %d [%08X]", + vosStatus, vosStatus ); + } + pHddStaCtx->ibss_sta_generation++; + memset(&staInfo, 0, sizeof(staInfo)); + staInfo.filled = 0; + staInfo.generation = pHddStaCtx->ibss_sta_generation; + + cfg80211_new_sta(pAdapter->dev, + (const u8 *)pRoamInfo->peerMac, + &staInfo, GFP_KERNEL); + + if ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddStaCtx->ibss_enc_key.encType + ||eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddStaCtx->ibss_enc_key.encType + ||eCSR_ENCRYPT_TYPE_TKIP == pHddStaCtx->ibss_enc_key.encType + ||eCSR_ENCRYPT_TYPE_AES == pHddStaCtx->ibss_enc_key.encType ) + { + pHddStaCtx->ibss_enc_key.keyDirection = eSIR_TX_RX; + memcpy(&pHddStaCtx->ibss_enc_key.peerMac, + pRoamInfo->peerMac, VOS_MAC_ADDR_SIZE); + + VOS_TRACE( VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_INFO_HIGH, "New peer joined set PTK encType=%d", + pHddStaCtx->ibss_enc_key.encType); + + vosStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &pHddStaCtx->ibss_enc_key, &roamId ); + + if ( VOS_STATUS_SUCCESS != vosStatus ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed, returned %d", + __func__, vosStatus); + return VOS_STATUS_E_FAILURE; + } + } + netif_carrier_on(pAdapter->dev); + hddLog(LOG1, FL("Enabling queues")); + netif_tx_start_all_queues(pAdapter->dev); + break; + } + + case eCSR_ROAM_RESULT_IBSS_CONNECT: + { + + roamIbssConnectHandler( pAdapter, pRoamInfo ); + + break; + } + case eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED: + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (!roamRemoveIbssStation(pAdapter, pRoamInfo->staId)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "IBSS peer departed by cannot find peer in our registration table with TL" ); + } + + pr_info ( "IBSS Peer Departed from SME " + "with peerMac " MAC_ADDRESS_STR " BSSID: " MAC_ADDRESS_STR " and stationID= %d", + MAC_ADDR_ARRAY(pRoamInfo->peerMac), + MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId), + pRoamInfo->staId ); + + hdd_roamDeregisterSTA( pAdapter, pRoamInfo->staId ); + + pHddCtx->sta_to_adapter[pRoamInfo->staId] = NULL; + pHddStaCtx->ibss_sta_generation++; + + cfg80211_del_sta(pAdapter->dev, + (const u8 *)&pRoamInfo->peerMac, + GFP_KERNEL); + break; + } + case eCSR_ROAM_RESULT_IBSS_INACTIVE: + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "Received eCSR_ROAM_RESULT_IBSS_INACTIVE from SME"); + // Stop only when we are inactive + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_NotConnected", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_NotConnected); + + // Send the bssid address to the wext. + hdd_SendAssociationEvent(pAdapter->dev, pRoamInfo); + // clean up data path + hdd_disconnect_tx_rx(pAdapter); + break; + } + default: + break; + + } + + return( eHAL_STATUS_SUCCESS ); +} + +#ifdef FEATURE_WLAN_TDLS +/**============================================================================ + * + @brief hdd_roamRegisterTDLSSTA() - Construct the staDesc and register with + TL the new STA. This is called as part of ADD_STA in the TDLS setup + Return: VOS_STATUS + + ===========================================================================*/ +VOS_STATUS hdd_roamRegisterTDLSSTA(hdd_adapter_t *pAdapter, + const tANI_U8 *peerMac, tANI_U16 staId, + tANI_U8 ucastSig) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + WLAN_STADescType staDesc = {0}; + eCsrEncryptionType connectedCipherAlgo = eCSR_ENCRYPT_TYPE_UNKNOWN; + v_BOOL_t fConnected = FALSE; + + fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo ); + if (!fConnected) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s not connected. ignored", __func__); + return VOS_FALSE; + } + + /* + * TDLS sta in BSS should be set as STA type TDLS and STA MAC should + * be peer MAC, here we are working on direct Link + */ + staDesc.ucSTAId = staId ; + + staDesc.wSTAType = WLAN_STA_TDLS ; + + vos_mem_copy( staDesc.vSTAMACAddress.bytes, peerMac, + sizeof(tSirMacAddr) ); + + vos_mem_copy(staDesc.vBSSIDforIBSS.bytes, pHddStaCtx->conn_info.bssId,6 ); + vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent ); + + /* set the QoS field appropriately ..*/ + (hdd_wmm_is_active(pAdapter)) ? (staDesc.ucQosEnabled = 1) + : (staDesc.ucQosEnabled = 0) ; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "HDD register TL QoS_enabled=%d", staDesc.ucQosEnabled ); + + staDesc.ucProtectedFrame = (connectedCipherAlgo != eCSR_ENCRYPT_TYPE_NONE) ; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "HDD register TL Sec_enabled= %d.", staDesc.ucProtectedFrame ); + + /* + * UMA is ready we inform TL to do frame translation. + */ + staDesc.ucSwFrameTXXlation = 1; + staDesc.ucSwFrameRXXlation = 1; + staDesc.ucAddRmvLLC = 1; + + /* Initialize signatures and state */ + staDesc.ucUcastSig = ucastSig ; + + /* tdls Direct Link do not need bcastSig */ + staDesc.ucBcastSig = 0 ; + +#ifdef VOLANS_ENABLE_SW_REPLAY_CHECK + if(staDesc.ucProtectedFrame) + staDesc.ucIsReplayCheckValid = VOS_TRUE; + else + staDesc.ucIsReplayCheckValid = VOS_FALSE; +#endif + + staDesc.ucInitState = WLANTL_STA_CONNECTED ; + + /* Register the Station with TL... */ + /* Incase Micro controller data path offload enabled, + * All the traffic routed to WLAN host driver, do not need to + * route IPA. It should be routed kernel network stack */ +#if defined(IPA_OFFLOAD) && !defined(IPA_UC_OFFLOAD) + if (hdd_ipa_is_enabled(WLAN_HDD_GET_CTX(pAdapter))) + vosStatus = WLANTL_RegisterSTAClient( pVosContext, + hdd_ipa_process_rxt, + hdd_tx_complete_cbk, + hdd_tx_fetch_packet_cbk, &staDesc, 0 ); + else +#endif + vosStatus = WLANTL_RegisterSTAClient( pVosContext, + hdd_rx_packet_cbk, + hdd_tx_complete_cbk, + hdd_tx_fetch_packet_cbk, &staDesc, 0 ); + + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANTL_RegisterSTAClient() failed to register. " + "Status= %d [0x%08X]", __func__, vosStatus, vosStatus ); + return vosStatus; + } + + return( vosStatus ); +} + +static VOS_STATUS hdd_roamDeregisterTDLSSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) +{ + VOS_STATUS vosStatus; + vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: WLANTL_ClearSTAClient() failed to for staID %d. " + "Status= %d [0x%08X]", + __func__, staId, vosStatus, vosStatus ); + } + return( vosStatus ); +} + + +/* + * HDD interface between SME and TL to ensure TDLS client registration with + * TL in case of new TDLS client is added and deregistration at the time + * TDLS client is deleted. + */ + +static eHalStatus +hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +#ifdef CONFIG_TDLS_IMPLICIT + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); +#endif + tSmeTdlsPeerStateParams smeTdlsPeerStateParams; + eHalStatus status = eHAL_STATUS_FAILURE ; + tANI_U8 staIdx; + hddTdlsPeer_t *curr_peer; + tANI_U32 reason; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + ("hdd_tdlsStatusUpdate: %s staIdx %d " MAC_ADDRESS_STR), + roamResult == eCSR_ROAM_RESULT_ADD_TDLS_PEER ? "ADD_TDLS_PEER" : + roamResult == eCSR_ROAM_RESULT_DELETE_TDLS_PEER ? "DEL_TDLS_PEER" : + roamResult == eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND ? "DEL_TDLS_PEER_IND" : + roamResult == eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND? "DEL_ALL_TDLS_PEER_IND" : + roamResult == eCSR_ROAM_RESULT_UPDATE_TDLS_PEER? "UPDATE_TDLS_PEER" : + roamResult == eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP? "LINK_ESTABLISH_REQ_RSP" : + roamResult == eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER? "TDLS_SHOULD_DISCOVER" : + roamResult == eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN? "TDLS_SHOULD_TEARDOWN" : + roamResult == eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED? "TDLS_SHOULD_PEER_DISCONNECTED" : + "UNKNOWN", + pRoamInfo->staId, + MAC_ADDR_ARRAY(pRoamInfo->peerMac)) ; + +#ifdef CONFIG_TDLS_IMPLICIT + if (!pHddTdlsCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: TDLS ctx is null, ignore roamResult (%d)", + __func__, roamResult); + return status; + } +#endif + + switch( roamResult ) + { + case eCSR_ROAM_RESULT_ADD_TDLS_PEER: + { + if(eSIR_SME_SUCCESS != pRoamInfo->statusCode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("%s: Add Sta is failed. %d"),__func__, pRoamInfo->statusCode); + } + else + { + + /* check if there is available index for this new TDLS STA */ + for ( staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++ ) + { + if (0 == pHddCtx->tdlsConnInfo[staIdx].staId ) + { + pHddCtx->tdlsConnInfo[staIdx].sessionId = pRoamInfo->sessionId; + pHddCtx->tdlsConnInfo[staIdx].staId = pRoamInfo->staId; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + ("TDLS: STA IDX at %d is %d " + "of mac " MAC_ADDRESS_STR), + staIdx, pHddCtx->tdlsConnInfo[staIdx].staId, + MAC_ADDR_ARRAY(pRoamInfo->peerMac)); + + vos_copy_macaddr(&pHddCtx->tdlsConnInfo[staIdx].peerMac, + (v_MACADDR_t *)pRoamInfo->peerMac) ; + status = eHAL_STATUS_SUCCESS ; + break ; + } + } + if (staIdx < pHddCtx->max_num_tdls_sta) + { + if (-1 == wlan_hdd_tdls_set_sta_id(pAdapter, pRoamInfo->peerMac, pRoamInfo->staId)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "wlan_hdd_tdls_set_sta_id() failed"); + return VOS_FALSE; + } + + (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = pAdapter; + /* store the ucast signature , if required for further reference. */ + + wlan_hdd_tdls_set_signature( pAdapter, pRoamInfo->peerMac, pRoamInfo->ucastSig ); + } + else + { + status = eHAL_STATUS_FAILURE; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: no available slot in conn_info. staId %d cannot be stored", __func__, pRoamInfo->staId); + } + pAdapter->tdlsAddStaStatus = status; + } + complete(&pAdapter->tdls_add_station_comp); + break ; + } + case eCSR_ROAM_RESULT_UPDATE_TDLS_PEER: + { + if (eSIR_SME_SUCCESS != pRoamInfo->statusCode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Add Sta is failed. %d", __func__, pRoamInfo->statusCode); + } + /* store the ucast signature which will be used later when + * registering to TL + */ + pAdapter->tdlsAddStaStatus = pRoamInfo->statusCode; + complete(&pAdapter->tdls_add_station_comp); + break; + } + case eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP: + { + if (eSIR_SME_SUCCESS != pRoamInfo->statusCode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Link Establish Request failed. %d", __func__, pRoamInfo->statusCode); + } + complete(&pAdapter->tdls_link_establish_req_comp); + break; + } + case eCSR_ROAM_RESULT_DELETE_TDLS_PEER: + { + for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) + { + if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pRoamInfo->sessionId) && + pRoamInfo->staId == pHddCtx->tdlsConnInfo[staIdx].staId) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + ("HDD: del STA IDX = %x"), pRoamInfo->staId) ; + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac, TRUE); + if (NULL != curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " Current status for peer" MAC_ADDRESS_STR "is %d", + MAC_ADDR_ARRAY(pRoamInfo->peerMac), curr_peer->link_status); + if (TDLS_IS_CONNECTED(curr_peer)) + { + hdd_roamDeregisterTDLSSTA ( pAdapter, pRoamInfo->staId ); + wlan_hdd_tdls_decrement_peer_count(pAdapter); + } + else if (eTDLS_LINK_CONNECTING == curr_peer->link_status) + { + hdd_roamDeregisterTDLSSTA ( pAdapter, pRoamInfo->staId ); + } + } + wlan_hdd_tdls_reset_peer(pAdapter, pRoamInfo->peerMac); + + pHddCtx->tdlsConnInfo[staIdx].staId = 0 ; + pHddCtx->tdlsConnInfo[staIdx].sessionId = 255; + vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac, + sizeof(v_MACADDR_t)) ; + wlan_hdd_tdls_check_bmps(pAdapter); + status = eHAL_STATUS_SUCCESS ; + break ; + } + } + complete(&pAdapter->tdls_del_station_comp); + } + break ; + case eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND: + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Sending teardown to supplicant with reason code %u", + __func__, pRoamInfo->reasonCode); + +#ifdef CONFIG_TDLS_IMPLICIT + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac, TRUE); + wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, pRoamInfo->reasonCode); +#endif + status = eHAL_STATUS_SUCCESS ; + break ; + } + case eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND: + { + /* 0 staIdx is assigned to AP we dont want to touch that */ + for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) + { + if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pRoamInfo->sessionId) && + pHddCtx->tdlsConnInfo[staIdx].staId) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + ("hdd_tdlsStatusUpdate: staIdx %d " MAC_ADDRESS_STR), + pHddCtx->tdlsConnInfo[staIdx].staId, + MAC_ADDR_ARRAY(pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes)); + wlan_hdd_tdls_reset_peer(pAdapter, pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes); + hdd_roamDeregisterTDLSSTA ( pAdapter, pHddCtx->tdlsConnInfo[staIdx].staId ); + vos_mem_zero(&smeTdlsPeerStateParams, + sizeof(smeTdlsPeerStateParams)); + smeTdlsPeerStateParams.vdevId = + pHddCtx->tdlsConnInfo[staIdx].sessionId; + vos_mem_copy(&smeTdlsPeerStateParams.peerMacAddr, + &pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes, + VOS_MAC_ADDR_SIZE); + smeTdlsPeerStateParams.peerState = + eSME_TDLS_PEER_STATE_TEARDOWN; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("hdd_tdlsStatusUpdate: calling sme_UpdateTdlsPeerState for staIdx %d " MAC_ADDRESS_STR), + pHddCtx->tdlsConnInfo[staIdx].staId, + MAC_ADDR_ARRAY(pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes)); + status = sme_UpdateTdlsPeerState(pHddCtx->hHal, + &smeTdlsPeerStateParams); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_UpdateTdlsPeerState failed for " + MAC_ADDRESS_STR, __func__, + MAC_ADDR_ARRAY(pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes)); + } + wlan_hdd_tdls_decrement_peer_count(pAdapter); + + vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac, + sizeof(v_MACADDR_t)) ; + pHddCtx->tdlsConnInfo[staIdx].staId = 0 ; + pHddCtx->tdlsConnInfo[staIdx].sessionId = 255; + + status = eHAL_STATUS_SUCCESS ; + } + } + wlan_hdd_tdls_check_bmps(pAdapter); + break ; + } + case eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER: + { +#ifdef CONFIG_TDLS_IMPLICIT + /* ignore TDLS_SHOULD_DISCOVER if any concurrency detected */ + if (((1 << VOS_STA_MODE) != pHddCtx->concurrency_mode) || + (pHddCtx->no_of_active_sessions[VOS_STA_MODE] > 1)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("concurrency detected. ignore SHOULD_DISCOVER concurrency_mode: 0x%x, active_sessions: %d"), + pHddCtx->concurrency_mode, + pHddCtx->no_of_active_sessions[VOS_STA_MODE]); + status = eHAL_STATUS_FAILURE; + break; + } + + if (pHddCtx->tdls_nss_switch_in_progress) { + hddLog(LOGE, + FL("TDLS antenna switch is in progress, ignore SHOULD_DISCOVER")); + status = eHAL_STATUS_SUCCESS; + break; + } + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, pRoamInfo->peerMac); + if (!curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: curr_peer null", __func__); + status = eHAL_STATUS_FAILURE; + } + else + { + if (eTDLS_LINK_CONNECTED == curr_peer->link_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: TDLS link status is connected, ignore SHOULD_DISCOVER", __func__); + } + else + { + /* if external control is enabled then initiate TDLS + * only if forced peer is set otherwise ignore + * Should Discover trigger from fw + */ + if (pHddCtx->cfg_ini->fTDLSExternalControl && + (FALSE == curr_peer->isForcedPeer)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("TDLS ExternalControl enabled but curr_peer is not forced, ignore SHOULD_DISCOVER")); + status = eHAL_STATUS_SUCCESS; + break; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("initiate TDLS setup on SHOULD_DISCOVER, fTDLSExternalControl: %d, curr_peer->isForcedPeer: %d, reason: %d"), + pHddCtx->cfg_ini->fTDLSExternalControl, + curr_peer->isForcedPeer, + pRoamInfo->reasonCode); + } + wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer); + } + status = eHAL_STATUS_SUCCESS; + } +#else + status = eHAL_STATUS_SUCCESS; +#endif + break ; + } + + case eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN: + { +#ifdef CONFIG_TDLS_IMPLICIT + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac, TRUE); + if (!curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: curr_peer null", __func__); + status = eHAL_STATUS_FAILURE; + } + else + { + if (eTDLS_LINK_CONNECTED == curr_peer->link_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Received SHOULD_TEARDOWN for peer " + MAC_ADDRESS_STR " staId: %d, reason: %d"), + MAC_ADDR_ARRAY(pRoamInfo->peerMac), + pRoamInfo->staId, + pRoamInfo->reasonCode); + + if (pRoamInfo->reasonCode == + eWNI_TDLS_TEARDOWN_REASON_RSSI || + pRoamInfo->reasonCode == + eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE || + pRoamInfo->reasonCode == + eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT || + pRoamInfo->reasonCode == + eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE) + { + reason = eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE; + } + else + reason = eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON; + + wlan_hdd_tdls_indicate_teardown(pHddTdlsCtx->pAdapter, + curr_peer, + reason); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("TDLS link is not connected, ignore SHOULD_TEARDOWN, reason: %d"), + pRoamInfo->reasonCode); + } + status = eHAL_STATUS_SUCCESS; + } +#else + status = eHAL_STATUS_SUCCESS; +#endif + break ; + } + + case eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED: + { +#ifdef CONFIG_TDLS_IMPLICIT + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac, TRUE); + if (!curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: curr_peer null", __func__); + status = eHAL_STATUS_FAILURE; + } + else + { + if (eTDLS_LINK_CONNECTED == curr_peer->link_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Received SHOULD_PEER_DISCONNECTED for peer " + MAC_ADDRESS_STR " staId: %d, reason: %d"), + MAC_ADDR_ARRAY(pRoamInfo->peerMac), + pRoamInfo->staId, + pRoamInfo->reasonCode); + + if (pRoamInfo->reasonCode == + eWNI_TDLS_TEARDOWN_REASON_RSSI || + pRoamInfo->reasonCode == + eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE || + pRoamInfo->reasonCode == + eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT || + pRoamInfo->reasonCode == + eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE) + { + reason = eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE; + } + else + reason = eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON; + + wlan_hdd_tdls_indicate_teardown(pHddTdlsCtx->pAdapter, + curr_peer, + reason); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("TDLS link is not connected, ignore SHOULD_PEER_DISCONNECTED, reason: %d"), + pRoamInfo->reasonCode); + } + status = eHAL_STATUS_SUCCESS; + } +#else + status = eHAL_STATUS_SUCCESS; +#endif + break ; + } + default: + { + break ; + } + } + + return status ; +} +#endif + +static void iw_full_power_cbfn (void *pContext, eHalStatus status) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext; + hdd_context_t *pHddCtx = NULL; + int ret; + + ENTER(); + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pAdapter [%p]", + __func__, pAdapter); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return; + + if (pHddCtx->cfg_ini->fIsBmpsEnabled) + { + sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), NULL, NULL); + } + EXIT(); +} + +#ifdef WLAN_FEATURE_11W +/** + * hdd_indicateUnprotMgmtFrame() - indicate unprotected management frame + * @pAdapter: pointer to the adapter + * @nFrameLength: Length of the unprotected frame being passed + * @pbFrames: Pointer to the frame buffer + * @frameType: 802.11 frame type + * + * This function forwards the unprotected management frame to the supplicant. + * + * Return: nothing + */ +static void +hdd_indicateUnprotMgmtFrame(hdd_adapter_t *pAdapter, tANI_U32 nFrameLength, + tANI_U8* pbFrames, tANI_U8 frameType) +{ + tANI_U8 type = 0; + tANI_U8 subType = 0; + + hddLog(LOG1, FL("Frame Type(%d) Frame Length(%d)"), + frameType, nFrameLength); + + /* Sanity Checks */ + if (NULL == pAdapter) { + hddLog(LOGE, FL("pAdapter is NULL")); + return; + } + + if (NULL == pAdapter->dev) { + hddLog(LOGE, FL("pAdapter->dev is NULL")); + return; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + hddLog(LOGE, FL("pAdapter has invalid magic")); + return; + } + + if(!nFrameLength) { + hddLog(LOGE, FL("Frame Length is Invalid ZERO")); + return; + } + + if (NULL == pbFrames) { + hddLog(LOGE, FL("pbFrames is NULL")); + return; + } + + type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]); + subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]); + + /* Get pAdapter from Destination mac address of the frame */ + if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DISASSOC) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) || defined(WITH_BACKPORTS) + cfg80211_rx_unprot_mlme_mgmt(pAdapter->dev, pbFrames, nFrameLength); +#else + cfg80211_send_unprot_disassoc(pAdapter->dev, pbFrames, nFrameLength); +#endif + pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx++; + } else if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DEAUTH) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) || defined(WITH_BACKPORTS) + cfg80211_rx_unprot_mlme_mgmt(pAdapter->dev, pbFrames, nFrameLength); +#else + cfg80211_send_unprot_deauth(pAdapter->dev, pbFrames, nFrameLength); +#endif + pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx++; + } else { + hddLog(LOGE, FL("Frame type %d and subtype %d are not valid"), type, subType); + return; + } +} +#endif + +#if defined (FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +static void +hdd_indicateTsmIe(hdd_adapter_t *pAdapter, tANI_U8 tid, + tANI_U8 state, tANI_U16 measInterval) +{ + union iwreq_data wrqu; + char buf[IW_CUSTOM_MAX + 1]; + int nBytes = 0; + + if (NULL == pAdapter) + return; + + // create the event + memset(&wrqu, '\0', sizeof(wrqu)); + memset(buf, '\0', sizeof(buf)); + + hddLog(VOS_TRACE_LEVEL_INFO, "TSM Ind tid(%d) state(%d) MeasInt(%d)", + tid, state, measInterval); + + nBytes = snprintf(buf, IW_CUSTOM_MAX, "TSMIE=%d:%d:%d",tid,state,measInterval); + + wrqu.data.pointer = buf; + wrqu.data.length = nBytes; + // send the event + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +} + +void hdd_indicateCckmPreAuth(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo) +{ + union iwreq_data wrqu; + char buf[IW_CUSTOM_MAX + 1]; + char *pos = buf; + int nBytes = 0, freeBytes = IW_CUSTOM_MAX; + + if ((NULL == pAdapter) || (NULL == pRoamInfo)) + return; + + // create the event + memset(&wrqu, '\0', sizeof(wrqu)); + memset(buf, '\0', sizeof(buf)); + + /* Timestamp0 is lower 32 bits and Timestamp1 is upper 32 bits */ + hddLog(VOS_TRACE_LEVEL_INFO, + "CCXPREAUTHNOTIFY=" MAC_ADDRESS_STR" %d:%d", + MAC_ADDR_ARRAY(pRoamInfo->bssid), + pRoamInfo->timestamp[0], + pRoamInfo->timestamp[1]); + + nBytes = snprintf(pos, freeBytes, "CCXPREAUTHNOTIFY="); + pos += nBytes; + freeBytes -= nBytes; + + vos_mem_copy(pos, pRoamInfo->bssid, VOS_MAC_ADDR_SIZE); + pos += VOS_MAC_ADDR_SIZE; + freeBytes -= VOS_MAC_ADDR_SIZE; + + nBytes = snprintf(pos, freeBytes, " %u:%u", + pRoamInfo->timestamp[0], pRoamInfo->timestamp[1]); + freeBytes -= nBytes; + + wrqu.data.pointer = buf; + wrqu.data.length = (IW_CUSTOM_MAX - freeBytes); + + // send the event + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +} + +static void +hdd_indicateEseAdjApRepInd(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo) +{ + union iwreq_data wrqu; + char buf[IW_CUSTOM_MAX + 1]; + int nBytes = 0; + + if ((NULL == pAdapter) || (NULL == pRoamInfo)) + return; + + // create the event + memset(&wrqu, '\0', sizeof(wrqu)); + memset(buf, '\0', sizeof(buf)); + + hddLog(VOS_TRACE_LEVEL_INFO, "CCXADJAPREP=%u", pRoamInfo->tsmRoamDelay); + + nBytes = snprintf(buf, IW_CUSTOM_MAX, "CCXADJAPREP=%u", pRoamInfo->tsmRoamDelay); + + wrqu.data.pointer = buf; + wrqu.data.length = nBytes; + + // send the event + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +} + +void hdd_indicateEseBcnReportNoResults(const hdd_adapter_t *pAdapter, + const tANI_U16 measurementToken, + const tANI_BOOLEAN flag, + const tANI_U8 numBss) +{ + union iwreq_data wrqu; + char buf[IW_CUSTOM_MAX]; + char *pos = buf; + int nBytes = 0, freeBytes = IW_CUSTOM_MAX; + + memset(&wrqu, '\0', sizeof(wrqu)); + memset(buf, '\0', sizeof(buf)); + + hddLog(VOS_TRACE_LEVEL_INFO, FL("CCXBCNREP=%d %d %d"), measurementToken, flag, + numBss); + + nBytes = snprintf(pos, freeBytes, "CCXBCNREP=%d %d %d", measurementToken, + flag, numBss); + + wrqu.data.pointer = buf; + wrqu.data.length = nBytes; + // send the event + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +} + +static void +hdd_indicateEseBcnReportInd(const hdd_adapter_t *pAdapter, + const tCsrRoamInfo *pRoamInfo) +{ + union iwreq_data wrqu; + char buf[IW_CUSTOM_MAX]; + char *pos = buf; + int nBytes = 0, freeBytes = IW_CUSTOM_MAX; + tANI_U8 i = 0, len = 0; + tANI_U8 tot_bcn_ieLen = 0; /* total size of the beacon report data */ + tANI_U8 lastSent = 0, sendBss = 0; + int bcnRepFieldSize = sizeof(pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[0].bcnReportFields); + tANI_U8 ieLenByte = 1; + /* CCXBCNREP=meas_tokflagno_of_bsstot_bcn_ie_len = 18 bytes */ +#define ESEBCNREPHEADER_LEN (18) + + if ((NULL == pAdapter) || (NULL == pRoamInfo)) + return; + + /* Custom event can pass maximum of 256 bytes of data, + based on the IE len we need to identify how many BSS info can + be filled in to custom event data */ + /* + meas_tokflagno_of_bsstot_bcn_ie_len bcn_rep_data + bcn_rep_data will have bcn_rep_fields,ie_len,ie without any spaces + CCXBCNREP=meas_tokflagno_of_bsstot_bcn_ie_len = 18 bytes + */ + + if ((pRoamInfo->pEseBcnReportRsp->flag >> 1) && (!pRoamInfo->pEseBcnReportRsp->numBss)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "Measurement Done but no scan results"); + /* If the measurement is none and no scan results found, + indicate the supplicant about measurement done */ + hdd_indicateEseBcnReportNoResults(pAdapter, + pRoamInfo->pEseBcnReportRsp->measurementToken, + pRoamInfo->pEseBcnReportRsp->flag, + pRoamInfo->pEseBcnReportRsp->numBss); + } + else + { + while (lastSent < pRoamInfo->pEseBcnReportRsp->numBss) + { + memset(&wrqu, '\0', sizeof(wrqu)); + memset(buf, '\0', sizeof(buf)); + tot_bcn_ieLen = 0; + sendBss = 0; + pos = buf; + freeBytes = IW_CUSTOM_MAX; + + for (i = lastSent; i < pRoamInfo->pEseBcnReportRsp->numBss; i++) + { + len = bcnRepFieldSize + ieLenByte + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i].ieLen; + if ((len + tot_bcn_ieLen) > (IW_CUSTOM_MAX - ESEBCNREPHEADER_LEN)) + { + break; + } + tot_bcn_ieLen += len; + sendBss++; + hddLog(VOS_TRACE_LEVEL_INFO, "i(%d) sizeof bcnReportFields(%d)" + "IeLength(%d) Length of Ie(%d) totLen(%d)", + i, bcnRepFieldSize, 1, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i].ieLen, + tot_bcn_ieLen); + } + + hddLog(VOS_TRACE_LEVEL_INFO, "Sending %d BSS Info", sendBss); + hddLog(VOS_TRACE_LEVEL_INFO, "CCXBCNREP=%d %d %d %d", + pRoamInfo->pEseBcnReportRsp->measurementToken, pRoamInfo->pEseBcnReportRsp->flag, + sendBss, tot_bcn_ieLen); + + nBytes = snprintf(pos, freeBytes, "CCXBCNREP=%d %d %d ", + pRoamInfo->pEseBcnReportRsp->measurementToken, pRoamInfo->pEseBcnReportRsp->flag, + sendBss); + pos += nBytes; + freeBytes -= nBytes; + + /* Copy total Beacon report data length */ + vos_mem_copy(pos, (char*)&tot_bcn_ieLen, sizeof(tot_bcn_ieLen)); + pos += sizeof(tot_bcn_ieLen); + freeBytes -= sizeof(tot_bcn_ieLen); + + for (i = 0; i < sendBss; i++) + { + hddLog(VOS_TRACE_LEVEL_INFO, "ChanNum(%d) Spare(%d) MeasDuration(%d)" + " PhyType(%d) RecvSigPower(%d) ParentTSF(%u)" + " TargetTSF[0](%u) TargetTSF[1](%u) BeaconInterval(%u)" + " CapabilityInfo(%d) BSSID(%02X:%02X:%02X:%02X:%02X:%02X)", + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.ChanNum, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Spare, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.MeasDuration, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.PhyType, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.RecvSigPower, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.ParentTsf, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.TargetTsf[0], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.TargetTsf[1], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.BcnInterval, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.CapabilityInfo, + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Bssid[0], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Bssid[1], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Bssid[2], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Bssid[3], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Bssid[4], + pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields.Bssid[5]); + + /* bcn report fields are copied */ + len = sizeof(pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields); + vos_mem_copy(pos, (char*)&pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].bcnReportFields, len); + pos += len; + freeBytes -= len; + + /* Add 1 byte of ie len */ + len = pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].ieLen; + vos_mem_copy(pos, (char*)&len, sizeof(len)); + pos += sizeof(len); + freeBytes -= sizeof(len); + + /* copy IE from scan results */ + vos_mem_copy(pos, (char*)pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[i+lastSent].pBuf, len); + pos += len; + freeBytes -= len; + } + + wrqu.data.pointer = buf; + wrqu.data.length = IW_CUSTOM_MAX - freeBytes; + + // send the event + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); + lastSent += sendBss; + } + } +} + +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + + +eHalStatus +hdd_smeRoamCallback(void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, + eRoamCmdStatus roamStatus, eCsrRoamResult roamResult) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext; + hdd_wext_state_t *pWextState = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx = NULL; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "CSR Callback: status= %d result= %d roamID=%d", + roamStatus, roamResult, roamId ); + + /* Sanity check */ + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter or adapter has invalid magic"); + return eHAL_STATUS_FAILURE; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_RX_SME_MSG, + pAdapter->sessionId, roamStatus)); + switch( roamStatus ) + { + case eCSR_ROAM_SESSION_OPENED: + set_bit(SME_SESSION_OPENED, &pAdapter->event_flags); + complete(&pAdapter->session_open_comp_var); + break; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + /* We did pre-auth,then we attempted a 11r or ese reassoc. + * reassoc failed due to failure, timeout, reject from ap + * in any case tell the OS, our carrier is off and mark + * interface down */ + case eCSR_ROAM_FT_REASSOC_FAILED: + hddLog(LOGE, FL("Reassoc Failed with roamStatus: %d roamResult: %d SessionID: %d"), + roamStatus, roamResult, pAdapter->sessionId); + halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); + /* Check if Mcast/Bcast Filters are set, if yes clear the filters here */ + if ((WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set == TRUE) { + (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE; + } + pHddStaCtx->ft_carrier_on = FALSE; + pHddStaCtx->hdd_ReassocScenario = FALSE; + hddLog(LOG1, + FL("hdd_ReassocScenario set to: %d, ReAssoc Failed, session: %d"), + pHddStaCtx->hdd_ReassocScenario, pAdapter->sessionId); + break; + + case eCSR_ROAM_FT_START: + // When we roam for ESE and 11r, we dont want the + // OS to be informed that the link is down. So mark + // the link ready for ft_start. After this the + // eCSR_ROAM_SHOULD_ROAM will be received. + // Where in we will not mark the link down + // Also we want to stop tx at this point when we will be + // doing disassoc at this time. This saves 30-60 msec + // after reassoc. + { + struct net_device *dev = pAdapter->dev; + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; + /* + * Deregister for this STA with TL with the objective to flush + * all the packets for this STA from wmm_tx_queue. If not done here, + * we would run into a race condition (CR390567) wherein TX + * thread would schedule packets from wmm_tx_queue AFTER peer STA has + * been deleted. And, these packets get assigned with a STA idx of + * self-sta (since the peer STA has been deleted) and get transmitted + * on the new channel before the reassoc request. Since there will be + * no ACK on the new channel, each packet gets retransmitted which + * takes several seconds before the transmission of reassoc request. + * This leads to reassoc-timeout and roam failure. + */ + status = hdd_roamDeregisterSTA( pAdapter, pHddStaCtx->conn_info.staId [0] ); + if ( !VOS_IS_STATUS_SUCCESS(status ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("hdd_roamDeregisterSTA() failed to for staID %d. Status= %d [0x%x]"), + pHddStaCtx->conn_info.staId[0], status, status ); + halStatus = eHAL_STATUS_FAILURE; + } + } + pHddStaCtx->ft_carrier_on = TRUE; + pHddStaCtx->hdd_ReassocScenario = VOS_TRUE; + hddLog(LOG1, + FL("hdd_ReassocScenario set to: %d due to eCSR_ROAM_FT_START, session: %d"), + pHddStaCtx->hdd_ReassocScenario, pAdapter->sessionId); + break; +#endif + + case eCSR_ROAM_SHOULD_ROAM: + // Dont need to do anything + { + struct net_device *dev = pAdapter->dev; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + // notify apps that we can't pass traffic anymore + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (pHddStaCtx->ft_carrier_on == FALSE) + { +#endif + netif_carrier_off(dev); +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + } +#endif + +#if !(defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)) + //We should clear all sta register with TL, for now, only one. + status = hdd_roamDeregisterSTA( pAdapter, pHddStaCtx->conn_info.staId [0] ); + if ( !VOS_IS_STATUS_SUCCESS(status ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("hdd_roamDeregisterSTA() failed to for staID %d. Status= %d [0x%x]"), + pHddStaCtx->conn_info.staId[0], status, status ); + halStatus = eHAL_STATUS_FAILURE; + } +#endif + } + break; + case eCSR_ROAM_LOSTLINK: + if(roamResult == eCSR_ROAM_RESULT_LOSTLINK) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Roaming started due to connection lost"); + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; + break; + } + case eCSR_ROAM_DISASSOCIATED: + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "****eCSR_ROAM_DISASSOCIATED****"); + halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); + /* Check if Mcast/Bcast Filters are set, if yes clear the filters here */ + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (pHddCtx->hdd_mcastbcast_filter_set == TRUE) + { + hdd_conf_mcastbcast_filter(pHddCtx, FALSE); + + if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: disassociation happening, restoring configuredMcastBcastFilter"); + hddLog(VOS_TRACE_LEVEL_INFO,"McastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: already called mcastbcast filter"); + (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE; + } +#ifdef WLAN_FEATURE_PACKET_FILTERING + /* Call to clear any MC Addr List filter applied after + * successful connection. + */ + wlan_hdd_set_mc_addr_list(pAdapter, FALSE); +#endif + } + break; + case eCSR_ROAM_IBSS_LEAVE: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "****eCSR_ROAM_IBSS_LEAVE****"); + halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); + break; + case eCSR_ROAM_ASSOCIATION_COMPLETION: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "****eCSR_ROAM_ASSOCIATION_COMPLETION****"); + // To Do - address probable memory leak with WEP encryption upon successful association + if (eCSR_ROAM_RESULT_ASSOCIATED != roamResult) + { + //Clear saved connection information in HDD + hdd_connRemoveConnectInfo( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) ); + } + halStatus = hdd_AssociationCompletionHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pRoamInfo) + pRoamInfo->roamSynchInProgress = VOS_FALSE; +#endif + break; + case eCSR_ROAM_ASSOCIATION_FAILURE: + halStatus = hdd_AssociationCompletionHandler( pAdapter, + pRoamInfo, roamId, roamStatus, roamResult ); + break; + case eCSR_ROAM_IBSS_IND: + hdd_RoamIbssIndicationHandler( pAdapter, pRoamInfo, roamId, + roamStatus, roamResult ); + break; + + case eCSR_ROAM_CONNECT_STATUS_UPDATE: + halStatus = roamRoamConnectStatusUpdateHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); + break; + + case eCSR_ROAM_MIC_ERROR_IND: + halStatus = hdd_RoamMicErrorIndicationHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); + break; + + case eCSR_ROAM_SET_KEY_COMPLETE: + { + hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + + if((pHddCtx) && + (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario) && + (TRUE == pHddCtx->hdd_wlan_suspended) && + (eCSR_ROAM_RESULT_NONE == roamResult)) + { + /* Send DTIM period to the FW; only if the wlan is already + in suspend. This is the case with roaming (reassoc), + DELETE_BSS_REQ zeroes out Modulated/Dynamic DTIM sent in + previous suspend_wlan. Sending SET_POWER_PARAMS_REQ + before the ENTER_BMPS_REQ ensures Listen Interval is + regained back to LI * Modulated DTIM */ + hdd_set_pwrparams(pHddCtx); + + /* At this point, device should not be in BMPS; + if due to unexpected scenario, if we are in BMPS, + then trigger Exit and Enter BMPS to take DTIM period + effective */ + if (BMPS == pmcGetPmcState(pHddCtx->hHal)) + { + hddLog( LOGE, FL("Not expected: device is already in BMPS mode, Exit & Enter BMPS again!")); + + sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), + iw_full_power_cbfn, pAdapter, + eSME_FULL_PWR_NEEDED_BY_HDD); + } + } + halStatus = hdd_RoamSetKeyCompleteHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); + if (eCSR_ROAM_RESULT_AUTHENTICATED == roamResult) { + pHddStaCtx->hdd_ReassocScenario = VOS_FALSE; + hddLog(LOG1, + FL("hdd_ReassocScenario set to: %d, set key complete, session: %d"), + pHddStaCtx->hdd_ReassocScenario, + pAdapter->sessionId); + } + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pRoamInfo != NULL) + pRoamInfo->roamSynchInProgress = VOS_FALSE; +#endif + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_ROAM_FT_RESPONSE: + hdd_SendFTEvent(pAdapter); + break; +#endif +#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) \ + || defined(WITH_BACKPORTS) + case eCSR_ROAM_PMK_NOTIFY: + if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType || + eCSR_AUTH_TYPE_RSN_8021X_SHA256 == + pHddStaCtx->conn_info.authType) + { + /* Notify the supplicant of a new candidate */ + halStatus = wlan_hdd_cfg80211_pmksa_candidate_notify(pAdapter, pRoamInfo, 1, false); + } + break; +#endif + +#ifdef FEATURE_WLAN_LFR_METRICS + case eCSR_ROAM_PREAUTH_INIT_NOTIFY: + /* This event is to notify pre-auth initiation */ + if (VOS_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_preauth(pAdapter, pRoamInfo)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + case eCSR_ROAM_PREAUTH_STATUS_SUCCESS: + /* This event will notify pre-auth completion in case of success */ + if (VOS_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_preauth_status(pAdapter, + pRoamInfo, 1)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + case eCSR_ROAM_PREAUTH_STATUS_FAILURE: + /* This event will notify pre-auth completion in case of failure. */ + if (VOS_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_preauth_status(pAdapter, + pRoamInfo, 0)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + case eCSR_ROAM_HANDOVER_SUCCESS: + /* This event is to notify handover success. + It will be only invoked on success */ + if (VOS_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_handover(pAdapter, pRoamInfo)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; +#endif + + case eCSR_ROAM_INDICATE_MGMT_FRAME: + hdd_indicateMgmtFrame( pAdapter, + pRoamInfo->nFrameLength, + pRoamInfo->pbFrames, + pRoamInfo->frameType, + pRoamInfo->rxChan, + pRoamInfo->rxRssi ); + break; + case eCSR_ROAM_REMAIN_CHAN_READY: + hdd_remainChanReadyHandler( pAdapter ); + break; + case eCSR_ROAM_SEND_ACTION_CNF: + hdd_sendActionCnf( pAdapter, + (roamResult == eCSR_ROAM_RESULT_NONE) ? TRUE : FALSE ); + break; +#ifdef FEATURE_WLAN_TDLS + case eCSR_ROAM_TDLS_STATUS_UPDATE: + halStatus = hdd_RoamTdlsStatusUpdateHandler( pAdapter, pRoamInfo, + roamId, roamStatus, roamResult ); + break ; + case eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND: + wlan_hdd_tdls_mgmt_completion_callback(pAdapter, pRoamInfo->reasonCode); + break; +#endif +#ifdef WLAN_FEATURE_11W + case eCSR_ROAM_UNPROT_MGMT_FRAME_IND: + hdd_indicateUnprotMgmtFrame(pAdapter, pRoamInfo->nFrameLength, + pRoamInfo->pbFrames, + pRoamInfo->frameType); + break; +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eCSR_ROAM_TSM_IE_IND: + hdd_indicateTsmIe(pAdapter, pRoamInfo->tsmIe.tsid, + pRoamInfo->tsmIe.state, pRoamInfo->tsmIe.msmt_interval); + break; + + case eCSR_ROAM_CCKM_PREAUTH_NOTIFY: + { + if (eCSR_AUTH_TYPE_CCKM_WPA == pHddStaCtx->conn_info.authType || + eCSR_AUTH_TYPE_CCKM_RSN == pHddStaCtx->conn_info.authType) + { + hdd_indicateCckmPreAuth(pAdapter, pRoamInfo); + } + break; + } + + case eCSR_ROAM_ESE_ADJ_AP_REPORT_IND: + { + hdd_indicateEseAdjApRepInd(pAdapter, pRoamInfo); + break; + } + + case eCSR_ROAM_ESE_BCN_REPORT_IND: + { + hdd_indicateEseBcnReportInd(pAdapter, pRoamInfo); + break; + } +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + default: + break; + } + return( halStatus ); +} +eCsrAuthType hdd_TranslateRSNToCsrAuthType( u_int8_t auth_suite[4]) +{ + eCsrAuthType auth_type; + // is the auth type supported? + if ( memcmp(auth_suite , ccpRSNOui01, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_RSN; + } else + if (memcmp(auth_suite , ccpRSNOui02, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_RSN_PSK; + } else +#ifdef WLAN_FEATURE_VOWIFI_11R + if (memcmp(auth_suite , ccpRSNOui04, 4) == 0) + { + // Check for 11r FT Authentication with PSK + auth_type = eCSR_AUTH_TYPE_FT_RSN_PSK; + } else + if (memcmp(auth_suite , ccpRSNOui03, 4) == 0) + { + // Check for 11R FT Authentication with 802.1X + auth_type = eCSR_AUTH_TYPE_FT_RSN; + } else +#endif +#ifdef FEATURE_WLAN_ESE + if (memcmp(auth_suite , ccpRSNOui06, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_CCKM_RSN; + } else +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_11W + if (memcmp(auth_suite , ccpRSNOui07, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256; + } else + if (memcmp(auth_suite , ccpRSNOui08, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_RSN_8021X_SHA256; + } else +#endif + { + auth_type = eCSR_AUTH_TYPE_UNKNOWN; + } + return auth_type; +} + +eCsrAuthType +hdd_TranslateWPAToCsrAuthType(u_int8_t auth_suite[4]) +{ + eCsrAuthType auth_type; + // is the auth type supported? + if ( memcmp(auth_suite , ccpWpaOui01, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_WPA; + } else + if (memcmp(auth_suite , ccpWpaOui02, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_WPA_PSK; + } else +#ifdef FEATURE_WLAN_ESE + if (memcmp(auth_suite , ccpWpaOui06, 4) == 0) + { + auth_type = eCSR_AUTH_TYPE_CCKM_WPA; + } else +#endif /* FEATURE_WLAN_ESE */ + { + auth_type = eCSR_AUTH_TYPE_UNKNOWN; + } + hddLog(LOG1, FL("auth_type: %d"), auth_type); + return auth_type; +} + +eCsrEncryptionType +hdd_TranslateRSNToCsrEncryptionType(u_int8_t cipher_suite[4]) +{ + eCsrEncryptionType cipher_type; + // is the cipher type supported? + if ( memcmp(cipher_suite , ccpRSNOui04, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_AES; + } + else if (memcmp(cipher_suite , ccpRSNOui02, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_TKIP; + } + else if (memcmp(cipher_suite , ccpRSNOui00, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_NONE; + } + else if (memcmp(cipher_suite , ccpRSNOui01, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + else if (memcmp(cipher_suite , ccpRSNOui05, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + } + else + { + cipher_type = eCSR_ENCRYPT_TYPE_FAILED; + } + hddLog(LOG1, FL("cipher_type: %d"), cipher_type); + return cipher_type; +} +/* To find if the MAC address is NULL */ +static tANI_U8 hdd_IsMACAddrNULL (tANI_U8 *macAddr, tANI_U8 length) +{ + int i; + for (i = 0; i < length; i++) + { + if (0x00 != (macAddr[i])) + { + return FALSE; + } + } + return TRUE; +} /****** end hdd_IsMACAddrNULL() ******/ + +eCsrEncryptionType +hdd_TranslateWPAToCsrEncryptionType(u_int8_t cipher_suite[4]) +{ + eCsrEncryptionType cipher_type; + // is the cipher type supported? + if ( memcmp(cipher_suite , ccpWpaOui04, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_AES; + } else + if (memcmp(cipher_suite , ccpWpaOui02, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_TKIP; + } else + if (memcmp(cipher_suite , ccpWpaOui00, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_NONE; + } else + if (memcmp(cipher_suite , ccpWpaOui01, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } else + if (memcmp(cipher_suite , ccpWpaOui05, 4) == 0) + { + cipher_type = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + } else + { + cipher_type = eCSR_ENCRYPT_TYPE_FAILED; + } + hddLog(LOG1, FL("cipher_type: %d"), cipher_type); + return cipher_type; +} + +static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter, + struct ether_addr *pBssid, + eCsrEncryptionType *pEncryptType, + eCsrEncryptionType *mcEncryptType, + eCsrAuthType *pAuthType, +#ifdef WLAN_FEATURE_11W + u_int8_t *pMfpRequired, + u_int8_t *pMfpCapable, +#endif + u_int16_t gen_ie_len, + u_int8_t *gen_ie) +{ + tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + eHalStatus result; + tDot11fIERSN dot11RSNIE; + tDot11fIEWPA dot11WPAIE; + tANI_U32 i; + tANI_U8 *pRsnIe; + tANI_U16 RSNIeLen; + tPmkidCacheInfo PMKIDCache[4]; // Local transfer memory + v_BOOL_t updatePMKCache = FALSE; + + /* Clear struct of tDot11fIERSN and tDot11fIEWPA specifically setting present + flag to 0 */ + memset( &dot11WPAIE, 0 , sizeof(tDot11fIEWPA) ); + memset( &dot11RSNIE, 0 , sizeof(tDot11fIERSN) ); + + // Type check + if ( gen_ie[0] == DOT11F_EID_RSN) + { + // Validity checks + if ((gen_ie_len < DOT11F_IE_RSN_MIN_LEN ) || + (gen_ie_len > DOT11F_IE_RSN_MAX_LEN) ) + { + hddLog(LOGE, "%s: Invalid DOT11F RSN IE length :%d", + __func__, gen_ie_len); + return -EINVAL; + } + // Skip past the EID byte and length byte + pRsnIe = gen_ie + 2; + RSNIeLen = gen_ie_len - 2; + // Unpack the RSN IE + dot11fUnpackIeRSN((tpAniSirGlobal) halHandle, + pRsnIe, + RSNIeLen, + &dot11RSNIE); + // Copy out the encryption and authentication types + hddLog(LOG1, FL("%s: pairwise cipher suite count: %d"), + __func__, dot11RSNIE.pwise_cipher_suite_count ); + hddLog(LOG1, FL("%s: authentication suite count: %d"), + __func__, dot11RSNIE.akm_suite_count); + /*Here we have followed the apple base code, + but probably I suspect we can do something different*/ + //dot11RSNIE.akm_suite_count + // Just translate the FIRST one + *pAuthType = hdd_TranslateRSNToCsrAuthType(dot11RSNIE.akm_suites[0]); + //dot11RSNIE.pwise_cipher_suite_count + *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]); + //dot11RSNIE.gp_cipher_suite_count + *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite); +#ifdef WLAN_FEATURE_11W + *pMfpRequired = (dot11RSNIE.RSN_Cap[0] >> 6) & 0x1 ; + *pMfpCapable = (dot11RSNIE.RSN_Cap[0] >> 7) & 0x1 ; +#endif + // Set the PMKSA ID Cache for this interface + for (i=0; iether_addr_octet , 6)) + { + hddLog(LOGE, "%s: Invalid MAC adrr", __func__); + break; + } + updatePMKCache = TRUE; + // For right now, I assume setASSOCIATE() has passed in the bssid. + vos_mem_copy(PMKIDCache[i].BSSID, + pBssid, ETHER_ADDR_LEN); + vos_mem_copy(PMKIDCache[i].PMKID, + dot11RSNIE.pmkid[i], + CSR_RSN_PMKID_SIZE); + } + + if (updatePMKCache) + { + // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache + hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with cache entry %d."), + __func__, i ); + // Finally set the PMKSA ID Cache in CSR + result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId, + PMKIDCache, + dot11RSNIE.pmkid_count, + FALSE); + } + } + else if (gen_ie[0] == DOT11F_EID_WPA) + { + // Validity checks + if ((gen_ie_len < DOT11F_IE_WPA_MIN_LEN ) || + (gen_ie_len > DOT11F_IE_WPA_MAX_LEN)) + { + hddLog(LOGE, "%s: Invalid DOT11F WPA IE length :%d", + __func__, gen_ie_len); + return -EINVAL; + } + // Skip past the EID byte and length byte - and four byte WiFi OUI + pRsnIe = gen_ie + 2 + 4; + RSNIeLen = gen_ie_len - (2 + 4); + // Unpack the WPA IE + dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, + pRsnIe, + RSNIeLen, + &dot11WPAIE); + // Copy out the encryption and authentication types + hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d"), + __func__, dot11WPAIE.unicast_cipher_count ); + hddLog(LOG1, FL("%s: WPA authentication suite count: %d"), + __func__, dot11WPAIE.auth_suite_count); + //dot11WPAIE.auth_suite_count + // Just translate the FIRST one + *pAuthType = hdd_TranslateWPAToCsrAuthType(dot11WPAIE.auth_suites[0]); + //dot11WPAIE.unicast_cipher_count + *pEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.unicast_ciphers[0]); + //dot11WPAIE.unicast_cipher_count + *mcEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher); + } + else + { + hddLog(LOGW, FL("gen_ie[0]: %d"), gen_ie[0]); + return -EINVAL; + } + return 0; +} +int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + v_U32_t status = 0; + eCsrEncryptionType RSNEncryptType; + eCsrEncryptionType mcRSNEncryptType; +#ifdef WLAN_FEATURE_11W + u_int8_t RSNMfpRequired = 0; + u_int8_t RSNMfpCapable = 0; +#endif + struct ether_addr bSsid; // MAC address of assoc peer + // MAC address of assoc peer + // But, this routine is only called when we are NOT associated. + vos_mem_copy(bSsid.ether_addr_octet, + pWextState->roamProfile.BSSIDs.bssid, + sizeof(bSsid.ether_addr_octet)); + if (pWextState->WPARSNIE[0] == DOT11F_EID_RSN || pWextState->WPARSNIE[0] == DOT11F_EID_WPA) + { + //continue + } + else + { + return 0; + } + // The actual processing may eventually be more extensive than this. + // Right now, just consume any PMKIDs that are sent in by the app. + status = hdd_ProcessGENIE(pAdapter, + &bSsid, // MAC address of assoc peer + &RSNEncryptType, + &mcRSNEncryptType, + RSNAuthType, +#ifdef WLAN_FEATURE_11W + &RSNMfpRequired, + &RSNMfpCapable, +#endif + pWextState->WPARSNIE[1]+2, + pWextState->WPARSNIE); + if (status == 0) + { + // Now copy over all the security attributes you have parsed out + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.mcEncryptionType.numEntries = 1; + + pWextState->roamProfile.EncryptionType.encryptionType[0] = RSNEncryptType; // Use the cipher type in the RSN IE + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = mcRSNEncryptType; + + if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && + ((eCSR_ENCRYPT_TYPE_AES == mcRSNEncryptType) || + (eCSR_ENCRYPT_TYPE_TKIP == mcRSNEncryptType))) + { + /*For wpa none supplicant sends the WPA IE with unicast cipher as + eCSR_ENCRYPT_TYPE_NONE ,where as the multicast cipher as + either AES/TKIP based on group cipher configuration + mentioned in the wpa_supplicant.conf.*/ + + /*Set the unicast cipher same as multicast cipher*/ + pWextState->roamProfile.EncryptionType.encryptionType[0] + = mcRSNEncryptType; + } + +#ifdef WLAN_FEATURE_11W + hddLog( LOG1, FL("RSNMfpRequired = %d, RSNMfpCapable = %d"), + RSNMfpRequired, RSNMfpCapable); + pWextState->roamProfile.MFPRequired = RSNMfpRequired; + pWextState->roamProfile.MFPCapable = RSNMfpCapable; +#endif + hddLog( LOG1, + FL("CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d"), + *RSNAuthType, RSNEncryptType, mcRSNEncryptType); + } + return 0; +} +int hdd_set_csr_auth_type ( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile* pRoamProfile = &(pWextState->roamProfile); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + ENTER(); + + pRoamProfile->AuthType.numEntries = 1; + hddLog( LOG1, "%s: pHddStaCtx->conn_info.authType = %d", __func__, pHddStaCtx->conn_info.authType); + + switch( pHddStaCtx->conn_info.authType) + { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: +#ifdef FEATURE_WLAN_ESE + case eCSR_AUTH_TYPE_CCKM_WPA: + case eCSR_AUTH_TYPE_CCKM_RSN: +#endif + if (pWextState->wpaVersion & IW_AUTH_WPA_VERSION_DISABLED) { + + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM ; + } else + if (pWextState->wpaVersion & IW_AUTH_WPA_VERSION_WPA) { + +#ifdef FEATURE_WLAN_ESE + if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_WPA) && + ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) + == IW_AUTH_KEY_MGMT_802_1X)) { + hddLog( LOG1, "%s: set authType to CCKM WPA. AKM also 802.1X.", __func__); + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_WPA; + } else + if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_WPA)) { + hddLog( LOG1, "%s: Last chance to set authType to CCKM WPA.", __func__); + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_WPA; + } else +#endif + if((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) + == IW_AUTH_KEY_MGMT_802_1X) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WPA; + } else + if ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_PSK) + == IW_AUTH_KEY_MGMT_PSK) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WPA_PSK; + } else { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WPA_NONE; + } + } + if (pWextState->wpaVersion & IW_AUTH_WPA_VERSION_WPA2) { +#ifdef FEATURE_WLAN_ESE + if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_RSN) && + ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) + == IW_AUTH_KEY_MGMT_802_1X)) { + hddLog( LOG1, "%s: set authType to CCKM RSN. AKM also 802.1X.", __func__); + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_RSN; + } else + if ((RSNAuthType == eCSR_AUTH_TYPE_CCKM_RSN)) { + hddLog( LOG1, "%s: Last chance to set authType to CCKM RSN.", __func__); + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_CCKM_RSN; + } else +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + if ((RSNAuthType == eCSR_AUTH_TYPE_FT_RSN) && + ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) + == IW_AUTH_KEY_MGMT_802_1X)) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_FT_RSN; + }else + if ((RSNAuthType == eCSR_AUTH_TYPE_FT_RSN_PSK) && + ((pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_PSK) + == IW_AUTH_KEY_MGMT_PSK)) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_FT_RSN_PSK; + } else +#endif + +#ifdef WLAN_FEATURE_11W + if (RSNAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN_PSK_SHA256; + } else + if (RSNAuthType == eCSR_AUTH_TYPE_RSN_8021X_SHA256) { + pRoamProfile->AuthType.authType[0] = + eCSR_AUTH_TYPE_RSN_8021X_SHA256; + } else +#endif + + if( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) + == IW_AUTH_KEY_MGMT_802_1X) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN; + } else + if ( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_PSK) + == IW_AUTH_KEY_MGMT_PSK) { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN_PSK; + } else { + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_UNKNOWN; + } + } + break; + + case eCSR_AUTH_TYPE_SHARED_KEY: + + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_SHARED_KEY; + break; + default: + +#ifdef FEATURE_WLAN_ESE + hddLog( LOG1, "%s: In default, unknown auth type.", __func__); +#endif /* FEATURE_WLAN_ESE */ + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_UNKNOWN; + break; + } + + hddLog( LOG1, "%s Set roam Authtype to %d", + __func__, pWextState->roamProfile.AuthType.authType[0]); + + EXIT(); + return 0; +} + +/** + * __iw_set_essid() - This function sets the ssid received from wpa_supplicant + * to the CSR roam profile. + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure + */ +static int __iw_set_essid(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + unsigned long rc; + v_U32_t status = 0; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + v_U32_t roamId; + tCsrRoamProfile *pRoamProfile; + hdd_context_t *pHddCtx; + eMib_dot11DesiredBssType connectedBssType; + eCsrAuthType RSNAuthType; + uint16_t ch_width; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ret; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION && + pAdapter->device_mode != WLAN_HDD_P2P_CLIENT) { + hddLog(LOGW, FL("Device mode %s(%d) is not allowed"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return -EINVAL; + } + + if(pWextState->mTKIPCounterMeasures == TKIP_COUNTER_MEASURE_STARTED) { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s :Counter measure is in progress", __func__); + return -EBUSY; + } + if( SIR_MAC_MAX_SSID_LENGTH < wrqu->essid.length ) + return -EINVAL; + + pRoamProfile = &pWextState->roamProfile; + 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) { + rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hddLog( LOGE, FL("Disconnect event timed out")); + } + } + } + + /** when cfg80211 defined, wpa_supplicant wext driver uses + zero-length, null-string ssid for force disconnection. + after disconnection (if previously connected) and cleaning ssid, + driver MUST return success */ + if ( 0 == wrqu->essid.length ) { + return 0; + } + + status = hdd_wmm_get_uapsd_mask(pAdapter, + &pWextState->roamProfile.uapsd_mask); + if (VOS_STATUS_SUCCESS != status) + { + pWextState->roamProfile.uapsd_mask = 0; + } + pWextState->roamProfile.SSIDs.numOfSSIDs = 1; + + pWextState->roamProfile.SSIDs.SSIDList->SSID.length = wrqu->essid.length; + + vos_mem_zero(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId, sizeof(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId)); + vos_mem_copy((void *)(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId), extra, wrqu->essid.length); + if (IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion || + IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion ) { + + //set gen ie + hdd_SetGENIEToCsr(pAdapter, &RSNAuthType); + + //set auth + hdd_set_csr_auth_type(pAdapter, RSNAuthType); + } +#ifdef FEATURE_WLAN_WAPI + hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__); + if (pAdapter->wapi_info.nWapiMode) + { + switch (pAdapter->wapi_info.wapiAuthMode) + { + case WAPI_AUTH_MODE_PSK: + { + hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__, pAdapter->wapi_info.wapiAuthMode); + pRoamProfile->AuthType.numEntries = 1; + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK; + break; + } + case WAPI_AUTH_MODE_CERT: + { + hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__, pAdapter->wapi_info.wapiAuthMode); + pRoamProfile->AuthType.numEntries = 1; + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE; + break; + } + } // End of switch + if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK || + pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT) + { + hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__); + pRoamProfile->EncryptionType.numEntries = 1; + pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI; + pRoamProfile->mcEncryptionType.numEntries = 1; + pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI; + } + } +#endif /* FEATURE_WLAN_WAPI */ + /* if previous genIE is not NULL, update AssocIE */ + if (0 != pWextState->genIE.length) + { + memset( &pWextState->assocAddIE, 0, sizeof(pWextState->assocAddIE) ); + memcpy( pWextState->assocAddIE.addIEdata, pWextState->genIE.addIEdata, + pWextState->genIE.length); + pWextState->assocAddIE.length = pWextState->genIE.length; + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + + /* clear previous genIE after use it */ + memset( &pWextState->genIE, 0, sizeof(pWextState->genIE) ); + } + + /* assumes it is not WPS Association by default, except when pAddIEAssoc has WPS IE */ + pWextState->roamProfile.bWPSAssociation = FALSE; + + if (NULL != wlan_hdd_get_wps_ie_ptr(pWextState->roamProfile.pAddIEAssoc, + pWextState->roamProfile.nAddIEAssocLength)) + pWextState->roamProfile.bWPSAssociation = TRUE; + + + // Disable auto BMPS entry by PMC until DHCP is done + sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter), TRUE); + + pWextState->roamProfile.csrPersona = pAdapter->device_mode; + (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE; + + if ( eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType ) + { + hdd_select_cbmode(pAdapter, pHddCtx->cfg_ini->AdHocChannel5G, + &ch_width); + pRoamProfile->vht_channel_width = ch_width; + } + status = sme_RoamConnect( hHal,pAdapter->sessionId, + &(pWextState->roamProfile), &roamId); + pRoamProfile->ChannelInfo.ChannelList = NULL; + pRoamProfile->ChannelInfo.numOfChannels = 0; + + EXIT(); + return status; +} + +/** + * iw_set_essid() - set essid handler function + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure + */ +int iw_set_essid(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_essid(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_essid() - This function returns the essid to the wpa_supplicant + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure + */ +static int __iw_get_essid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + hdd_wext_state_t *wextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if((pHddStaCtx->conn_info.connState == eConnectionState_Associated && + wextBuf->roamProfile.SSIDs.SSIDList->SSID.length > 0) || + ((pHddStaCtx->conn_info.connState == eConnectionState_IbssConnected || + pHddStaCtx->conn_info.connState == eConnectionState_IbssDisconnected) && + wextBuf->roamProfile.SSIDs.SSIDList->SSID.length > 0)) + { + dwrq->length = pHddStaCtx->conn_info.SSID.SSID.length; + memcpy(extra, pHddStaCtx->conn_info.SSID.SSID.ssId, dwrq->length); + dwrq->flags = 1; + } else { + memset(extra, 0, dwrq->length); + dwrq->length = 0; + dwrq->flags = 0; + } + EXIT(); + return 0; +} + +/** + * iw_get_essid() - get essid handler function + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure + */ +int iw_get_essid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_essid(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_auth() - This function sets the auth type received + * from the wpa_supplicant. + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +static int __iw_set_auth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; + eCsrEncryptionType mcEncryptionType; + eCsrEncryptionType ucEncryptionType; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch(wrqu->param.flags & IW_AUTH_INDEX) + { + case IW_AUTH_WPA_VERSION: + + pWextState->wpaVersion = wrqu->param.value; + + break; + + case IW_AUTH_CIPHER_PAIRWISE: + { + if(wrqu->param.value & IW_AUTH_CIPHER_NONE) { + ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE; + } + else if(wrqu->param.value & IW_AUTH_CIPHER_TKIP) { + ucEncryptionType = eCSR_ENCRYPT_TYPE_TKIP; + } + else if(wrqu->param.value & IW_AUTH_CIPHER_CCMP) { + ucEncryptionType = eCSR_ENCRYPT_TYPE_AES; + } + + else if(wrqu->param.value & IW_AUTH_CIPHER_WEP40) { + + if( (IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) ) + && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) ) + /*Dynamic WEP key*/ + ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP40; + else + /*Static WEP key*/ + ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + else if(wrqu->param.value & IW_AUTH_CIPHER_WEP104) { + + if( ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) ) + && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) + /*Dynamic WEP key*/ + ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP104; + else + /*Static WEP key*/ + ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + + } + else { + + hddLog(LOGW, "%s value %d UNKNOWN IW_AUTH_CIPHER", + __func__, wrqu->param.value); + return -EINVAL; + } + + pRoamProfile->EncryptionType.numEntries = 1; + pRoamProfile->EncryptionType.encryptionType[0] = ucEncryptionType; + } + break; + case IW_AUTH_CIPHER_GROUP: + { + if(wrqu->param.value & IW_AUTH_CIPHER_NONE) { + mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE; + } + + else if(wrqu->param.value & IW_AUTH_CIPHER_TKIP) { + mcEncryptionType = eCSR_ENCRYPT_TYPE_TKIP; + } + + else if(wrqu->param.value & IW_AUTH_CIPHER_CCMP) { + mcEncryptionType = eCSR_ENCRYPT_TYPE_AES; + } + + else if(wrqu->param.value & IW_AUTH_CIPHER_WEP40) { + + if( ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X )) + && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) + + mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP40; + + else + mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + + else if(wrqu->param.value & IW_AUTH_CIPHER_WEP104) + { + /*Dynamic WEP keys won't work with shared keys*/ + if( ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) + && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) + { + mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP104; + } + else + { + mcEncryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + } + } + else { + + hddLog(LOGW, "%s value %d UNKNOWN IW_AUTH_CIPHER", + __func__, wrqu->param.value); + return -EINVAL; + } + + pRoamProfile->mcEncryptionType.numEntries = 1; + pRoamProfile->mcEncryptionType.encryptionType[0] = mcEncryptionType; + } + break; + + case IW_AUTH_80211_AUTH_ALG: + { + /*Save the auth algo here and set auth type to SME Roam profile + in the iw_set_ap_address*/ + if( wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + else if(wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY; + + else if(wrqu->param.value & IW_AUTH_ALG_LEAP) + /*Not supported*/ + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + pWextState->roamProfile.AuthType.authType[0] = pHddStaCtx->conn_info.authType; + } + break; + + case IW_AUTH_KEY_MGMT: + { +#ifdef FEATURE_WLAN_ESE +#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */ + /*Check for CCKM AKM type */ + if ( wrqu->param.value & IW_AUTH_KEY_MGMT_CCKM) { + hddLog(VOS_TRACE_LEVEL_INFO,"%s: CCKM AKM Set %d", + __func__, wrqu->param.value); + /* Set the CCKM bit in authKeyMgmt */ + /* Right now, this breaks all ref to authKeyMgmt because our + * code doesn't realize it is a "bitfield" + */ + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM; + /*Set the key management to 802.1X*/ + //pWextState->authKeyMgmt = IW_AUTH_KEY_MGMT_802_1X; + pWextState->isESEConnection = eANI_BOOLEAN_TRUE; + //This is test code. I need to actually KNOW whether this is an RSN Assoc or WPA. + pWextState->collectedAuthType = eCSR_AUTH_TYPE_CCKM_RSN; + } else if ( wrqu->param.value & IW_AUTH_KEY_MGMT_PSK) { + /*Save the key management*/ + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK; + //pWextState->authKeyMgmt = wrqu->param.value; + //This is test code. I need to actually KNOW whether this is an RSN Assoc or WPA. + pWextState->collectedAuthType = eCSR_AUTH_TYPE_RSN; + } else if (!( wrqu->param.value & IW_AUTH_KEY_MGMT_802_1X)) { + pWextState->collectedAuthType = eCSR_AUTH_TYPE_NONE; //eCSR_AUTH_TYPE_WPA_NONE + /*Save the key management anyway*/ + pWextState->authKeyMgmt = wrqu->param.value; + } else { // It must be IW_AUTH_KEY_MGMT_802_1X + /*Save the key management*/ + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X; + //pWextState->authKeyMgmt = wrqu->param.value; + //This is test code. I need to actually KNOW whether this is an RSN Assoc or WPA. + pWextState->collectedAuthType = eCSR_AUTH_TYPE_RSN; + } +#else + /*Save the key management*/ + pWextState->authKeyMgmt = wrqu->param.value; +#endif /* FEATURE_WLAN_ESE */ + } + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + { + if(wrqu->param.value) { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "Counter Measure started %d", wrqu->param.value); + pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STARTED; + } + else { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "Counter Measure stopped=%d", wrqu->param.value); + pWextState->mTKIPCounterMeasures = TKIP_COUNTER_MEASURE_STOPED; + } + } + break; + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + + default: + + hddLog(LOGW, "%s called with unsupported auth type %d", __func__, + wrqu->param.flags & IW_AUTH_INDEX); + break; + } + + EXIT(); + return 0; +} + +/** + * iw_set_auth() - set auth callback function + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +int iw_set_auth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_auth(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_auth() - This function returns the auth type to the wpa_supplicant. + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +static int __iw_get_auth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t* pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch(pRoamProfile->negotiatedAuthType) + { + case eCSR_AUTH_TYPE_WPA_NONE: + wrqu->param.flags = IW_AUTH_WPA_VERSION; + wrqu->param.value = IW_AUTH_WPA_VERSION_DISABLED; + break; + case eCSR_AUTH_TYPE_WPA: + wrqu->param.flags = IW_AUTH_WPA_VERSION; + wrqu->param.value = IW_AUTH_WPA_VERSION_WPA; + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: +#endif + case eCSR_AUTH_TYPE_RSN: + wrqu->param.flags = IW_AUTH_WPA_VERSION; + wrqu->param.value = IW_AUTH_WPA_VERSION_WPA2; + break; + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case eCSR_AUTH_TYPE_SHARED_KEY: + wrqu->param.value = IW_AUTH_ALG_SHARED_KEY; + break; + case eCSR_AUTH_TYPE_UNKNOWN: + hddLog(LOG1,"%s called with unknown auth type", __func__); + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + hddLog(LOG1,"%s called with WPA PSK auth type", __func__); + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + return -EIO; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN_PSK: +#endif + case eCSR_AUTH_TYPE_RSN_PSK: +#ifdef WLAN_FEATURE_11W + case eCSR_AUTH_TYPE_RSN_PSK_SHA256: + case eCSR_AUTH_TYPE_RSN_8021X_SHA256: +#endif + hddLog(LOG1,"%s called with RSN PSK auth type", __func__); + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + return -EIO; + default: + hddLog(LOGE,"%s called with unknown auth type", __func__); + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + return -EIO; + } + if(((wrqu->param.flags & IW_AUTH_INDEX) == IW_AUTH_CIPHER_PAIRWISE)) + { + switch(pRoamProfile->negotiatedUCEncryptionType) + { + case eCSR_ENCRYPT_TYPE_NONE: + wrqu->param.value = IW_AUTH_CIPHER_NONE; + break; + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + wrqu->param.value = IW_AUTH_CIPHER_WEP40; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + wrqu->param.value = IW_AUTH_CIPHER_TKIP; + break; + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + wrqu->param.value = IW_AUTH_CIPHER_WEP104; + break; + case eCSR_ENCRYPT_TYPE_AES: + wrqu->param.value = IW_AUTH_CIPHER_CCMP; + break; + default: + hddLog(LOG1, "%s called with unknown auth type %d ", + __func__, pRoamProfile->negotiatedUCEncryptionType); + return -EIO; + } + } + + if(((wrqu->param.flags & IW_AUTH_INDEX) == IW_AUTH_CIPHER_GROUP)) + { + switch(pRoamProfile->negotiatedMCEncryptionType) + { + case eCSR_ENCRYPT_TYPE_NONE: + wrqu->param.value = IW_AUTH_CIPHER_NONE; + break; + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + wrqu->param.value = IW_AUTH_CIPHER_WEP40; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + wrqu->param.value = IW_AUTH_CIPHER_TKIP; + break; + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + wrqu->param.value = IW_AUTH_CIPHER_WEP104; + break; + case eCSR_ENCRYPT_TYPE_AES: + wrqu->param.value = IW_AUTH_CIPHER_CCMP; + break; + default: + hddLog(LOG1, "%s called with unknown auth type %d ", + __func__, pRoamProfile->negotiatedMCEncryptionType); + return -EIO; + } + } + + hddLog(LOG1, "%s called with auth type %d", + __func__, pRoamProfile->AuthType.authType[0]); + EXIT(); + return 0; +} + +/** + * iw_get_auth() - get auth callback function + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +int iw_get_auth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_auth(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_ap_address() - This function calls the sme_RoamConnect function + * to associate to the AP with the specified + * BSSID received from the wpa_supplicant. + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +static int __iw_set_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(WLAN_HDD_GET_PRIV_PTR(dev)); + v_U8_t *pMacAddress=NULL; + int ret; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pMacAddress = (v_U8_t*) wrqu->ap_addr.sa_data; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s "MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(pMacAddress)); + vos_mem_copy( pHddStaCtx->conn_info.bssId, pMacAddress, sizeof( tCsrBssid )); + EXIT(); + + return 0; +} + +/** + * iw_set_ap_address() - set ap addresses callback function + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +int iw_set_ap_address(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_ap_address(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_ap_address() - This function returns the BSSID to the wpa_supplicant + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +static int __iw_get_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) || + (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) + { + memcpy(wrqu->ap_addr.sa_data,pHddStaCtx->conn_info.bssId,ETH_ALEN); + } + else + { + memset(wrqu->ap_addr.sa_data,0,sizeof(wrqu->ap_addr.sa_data)); + } + EXIT(); + return 0; +} + +/** + * iw_get_ap_address() - get ap addresses callback function + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 for success, error number on failure. + */ +int iw_get_ap_address(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_ap_address(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c new file mode 100644 index 000000000000..52be11dd330f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c @@ -0,0 +1,7229 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 07/27/09 kanand Created module. + + ==========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +static void +cbNotifySetRoamPrefer5GHz(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamPrefer5GHz(pHddCtx->hHal, pHddCtx->cfg_ini->nRoamPrefer5GHz); +} + +static void +cbNotifySetImmediateRoamRssiDiff(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateImmediateRoamRssiDiff(pHddCtx->hHal, + pHddCtx->cfg_ini->nImmediateRoamRssiDiff, + 0); +} + +static void +cbNotifySetRoamRssiDiff(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamRssiDiff(pHddCtx->hHal, + 0, + pHddCtx->cfg_ini->RoamRssiDiff); +} + +static void +cbNotifySetFastTransitionEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateFastTransitionEnabled(pHddCtx->hHal, + pHddCtx->cfg_ini->isFastTransitionEnabled); +} + +static void +cbNotifySetRoamIntraBand(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_setRoamIntraBand(pHddCtx->hHal, pHddCtx->cfg_ini->nRoamIntraBand); +} + +static void +cbNotifySetWESMode(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateWESMode(pHddCtx->hHal, + pHddCtx->cfg_ini->isWESModeEnabled, + 0); +} + +static void +cbNotifySetRoamScanNProbes(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanNProbes(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nProbes); +} + +static void +cbNotifySetRoamScanHomeAwayTime(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanHomeAwayTime(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nRoamScanHomeAwayTime, + eANI_BOOLEAN_TRUE); +} +#endif + +#ifdef FEATURE_WLAN_OKC +static void +cbNotifySetOkcFeatureEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ +} +#endif + +#ifdef FEATURE_WLAN_LFR +static void +NotifyIsFastRoamIniFeatureEnabled(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateIsFastRoamIniFeatureEnabled(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled ); +} + +static void +NotifyIsMAWCIniFeatureEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateIsMAWCIniFeatureEnabled(pHddCtx->hHal, + pHddCtx->cfg_ini->MAWCEnabled ); +} +#endif + +#ifdef FEATURE_WLAN_ESE +static void +cbNotifySetEseFeatureEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateIsEseFeatureEnabled(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->isEseIniFeatureEnabled ); +} +#endif + +static void +cbNotifySetFwRssiMonitoring(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateConfigFwRssiMonitoring(pHddCtx->hHal, + pHddCtx->cfg_ini->fEnableFwRssiMonitoring); +} + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +static void cbNotifySetOpportunisticScanThresholdDiff(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_SetRoamOpportunisticScanThresholdDiff(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nOpportunisticThresholdDiff ); +} + +static void cbNotifySetRoamRescanRssiDiff(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_SetRoamRescanRssiDiff(pHddCtx->hHal, + 0, + pHddCtx->cfg_ini->nRoamRescanRssiDiff); +} + +static void +cbNotifySetNeighborLookupRssiThreshold(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_setNeighborLookupRssiThreshold(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nNeighborLookupRssiThreshold); +} + +static void +cb_notify_set_delay_before_vdev_stop(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_set_delay_before_vdev_stop(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->delay_before_vdev_stop); +} + +static void +cbNotifySetNeighborScanPeriod(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_setNeighborScanPeriod(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nNeighborScanPeriod ); +} + +static void +cbNotifySetNeighborResultsRefreshPeriod(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_setNeighborScanRefreshPeriod(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod); +} + +static void +cbNotifySetEmptyScanRefreshPeriod(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateEmptyScanRefreshPeriod(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nEmptyScanRefreshPeriod); +} + +static void +cbNotifySetNeighborScanMinChanTime(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_setNeighborScanMinChanTime(pHddCtx->hHal, + pHddCtx->cfg_ini->nNeighborScanMinChanTime, + 0); +} + +static void +cbNotifySetNeighborScanMaxChanTime(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + sme_setNeighborScanMaxChanTime(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nNeighborScanMaxChanTime); +} +static void cbNotifySetRoamBmissFirstBcnt(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_SetRoamBmissFirstBcnt(pHddCtx->hHal, + 0, + pHddCtx->cfg_ini->nRoamBmissFirstBcnt); +} + +static void cbNotifySetRoamBmissFinalBcnt(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + sme_SetRoamBmissFinalBcnt(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nRoamBmissFinalBcnt); +} + +static void cbNotifySetRoamBeaconRssiWeight(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + sme_SetRoamBeaconRssiWeight(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->nRoamBeaconRssiWeight); +} + +static void +cbNotifySetDFSScanMode(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + /* At the point this routine is called, the value in the cfg_ini + table has already been updated */ + sme_UpdateDFSScanMode(pHddCtx->hHal, 0, + pHddCtx->cfg_ini->allowDFSChannelRoam); +} + +#endif + +static void cbNotifySetEnableSSR(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateEnableSSR(pHddCtx->hHal, pHddCtx->cfg_ini->enableSSR); +} + + +static void cbNotify_set_gSapPreferredChanLocation(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + WLANSAP_set_Dfs_Preferred_Channel_location(pHddCtx->hHal, + pHddCtx->cfg_ini->gSapPreferredChanLocation); +} + + +static void chNotify_set_gDisableDfsJapanW53(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + WLANSAP_set_Dfs_Restrict_JapanW53(pHddCtx->hHal, + pHddCtx->cfg_ini->gDisableDfsJapanW53); +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static void +cbNotifyUpdateRoamScanOffloadEnabled(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + sme_UpdateRoamScanOffloadEnabled(pHddCtx->hHal, + pHddCtx->cfg_ini->isRoamOffloadScanEnabled); + if (0 == pHddCtx->cfg_ini->isRoamOffloadScanEnabled) { + pHddCtx->cfg_ini->bFastRoamInConIniFeatureEnabled = 0; + sme_UpdateEnableFastRoamInConcurrency(pHddCtx->hHal, + pHddCtx->cfg_ini->bFastRoamInConIniFeatureEnabled); + } +} + +static void +cbNotifySetEnableFastRoamInConcurrency(hdd_context_t *pHddCtx, + unsigned long NotifyId) +{ + sme_UpdateEnableFastRoamInConcurrency(pHddCtx->hHal, + pHddCtx->cfg_ini->bFastRoamInConIniFeatureEnabled); +} + +#endif + +/** + * cb_notify_set_roam_scan_hi_rssi_scan_params() - configure hi rssi + * scan params from cfg to sme. + * @hdd_ctx: HDD context data structure + * @notify_id: Identifies 1 of the 4 parameters to be modified + * + * Picks up the value from hd configuration and passes it to SME. + * Return: void + */ + +static void +cb_notify_set_roam_scan_hi_rssi_scan_params(hdd_context_t *hdd_ctx, + unsigned long notify_id) +{ + int32_t val; + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is invalid")); + return; + } + + switch (notify_id) { + case eCSR_HI_RSSI_SCAN_MAXCOUNT_ID: + val = hdd_ctx->cfg_ini->nhi_rssi_scan_max_count; + break; + + case eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID: + val = hdd_ctx->cfg_ini->nhi_rssi_scan_rssi_delta; + break; + + case eCSR_HI_RSSI_SCAN_DELAY_ID: + val = hdd_ctx->cfg_ini->nhi_rssi_scan_delay; + break; + + case eCSR_HI_RSSI_SCAN_RSSI_UB_ID: + val = hdd_ctx->cfg_ini->nhi_rssi_scan_rssi_ub; + break; + + default: + return; + } + + sme_update_roam_scan_hi_rssi_scan_params(hdd_ctx->hHal, 0, + notify_id, val); +} + + +REG_TABLE_ENTRY g_registry_table[] = +{ + REG_VARIABLE( CFG_RTS_THRESHOLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, RTSThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RTS_THRESHOLD_DEFAULT, + CFG_RTS_THRESHOLD_MIN, + CFG_RTS_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_FRAG_THRESHOLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, FragmentationThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FRAG_THRESHOLD_DEFAULT, + CFG_FRAG_THRESHOLD_MIN, + CFG_FRAG_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_OPERATING_CHANNEL_NAME, WLAN_PARAM_Integer, + hdd_config_t, OperatingChannel, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OPERATING_CHANNEL_DEFAULT, + CFG_OPERATING_CHANNEL_MIN, + CFG_OPERATING_CHANNEL_MAX ), + + REG_VARIABLE( CFG_SHORT_SLOT_TIME_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, ShortSlotTimeEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SHORT_SLOT_TIME_ENABLED_DEFAULT, + CFG_SHORT_SLOT_TIME_ENABLED_MIN, + CFG_SHORT_SLOT_TIME_ENABLED_MAX ), + + REG_VARIABLE( CFG_11D_SUPPORT_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, Is11dSupportEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_11D_SUPPORT_ENABLED_DEFAULT, + CFG_11D_SUPPORT_ENABLED_MIN, + CFG_11D_SUPPORT_ENABLED_MAX ), + + REG_VARIABLE( CFG_11H_SUPPORT_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, Is11hSupportEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_11H_SUPPORT_ENABLED_DEFAULT, + CFG_11H_SUPPORT_ENABLED_MIN, + CFG_11H_SUPPORT_ENABLED_MAX ), + + REG_VARIABLE( CFG_ENFORCE_11D_CHANNELS_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnforce11dChannels, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENFORCE_11D_CHANNELS_DEFAULT, + CFG_ENFORCE_11D_CHANNELS_MIN, + CFG_ENFORCE_11D_CHANNELS_MAX ), + + REG_VARIABLE( CFG_COUNTRY_CODE_PRIORITY_NAME, WLAN_PARAM_Integer, + hdd_config_t, fSupplicantCountryCodeHasPriority, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_COUNTRY_CODE_PRIORITY_DEFAULT, + CFG_COUNTRY_CODE_PRIORITY_MIN, + CFG_COUNTRY_CODE_PRIORITY_MAX), + + REG_VARIABLE( CFG_ENFORCE_COUNTRY_CODE_MATCH_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnforceCountryCodeMatch, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENFORCE_COUNTRY_CODE_MATCH_DEFAULT, + CFG_ENFORCE_COUNTRY_CODE_MATCH_MIN, + CFG_ENFORCE_COUNTRY_CODE_MATCH_MAX ), + + REG_VARIABLE( CFG_ENFORCE_DEFAULT_DOMAIN_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnforceDefaultDomain, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENFORCE_DEFAULT_DOMAIN_DEFAULT, + CFG_ENFORCE_DEFAULT_DOMAIN_MIN, + CFG_ENFORCE_DEFAULT_DOMAIN_MAX ), + + REG_VARIABLE( CFG_HEARTBEAT_THRESH_24_NAME, WLAN_PARAM_Integer, + hdd_config_t, HeartbeatThresh24, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_HEARTBEAT_THRESH_24_DEFAULT, + CFG_HEARTBEAT_THRESH_24_MIN, + CFG_HEARTBEAT_THRESH_24_MAX ), + + REG_VARIABLE_STRING( CFG_POWER_USAGE_NAME, WLAN_PARAM_String, + hdd_config_t, PowerUsageControl, + VAR_FLAGS_OPTIONAL, + (void *)CFG_POWER_USAGE_DEFAULT ), + + REG_VARIABLE( CFG_ENABLE_SUSPEND_NAME, WLAN_PARAM_Integer, + hdd_config_t, nEnableSuspend, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SUSPEND_DEFAULT, + CFG_ENABLE_SUSPEND_MIN, + CFG_ENABLE_SUSPEND_MAX ), + + REG_VARIABLE( CFG_ENABLE_ENABLE_DRIVER_STOP_NAME, WLAN_PARAM_Integer, + hdd_config_t, nEnableDriverStop, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_ENABLE_DRIVER_STOP_DEFAULT, + CFG_ENABLE_ENABLE_DRIVER_STOP_MIN, + CFG_ENABLE_ENABLE_DRIVER_STOP_MAX ), + + REG_VARIABLE( CFG_ENABLE_LOGP_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIsLogpEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LOGP_DEFAULT, + CFG_ENABLE_LOGP_MIN, + CFG_ENABLE_LOGP_MAX ), + + REG_VARIABLE( CFG_ENABLE_IMPS_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIsImpsEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_IMPS_DEFAULT, + CFG_ENABLE_IMPS_MIN, + CFG_ENABLE_IMPS_MAX ), + + REG_VARIABLE( CFG_IMPS_MINIMUM_SLEEP_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nImpsMinSleepTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IMPS_MINIMUM_SLEEP_TIME_DEFAULT, + CFG_IMPS_MINIMUM_SLEEP_TIME_MIN, + CFG_IMPS_MINIMUM_SLEEP_TIME_MAX ), + + REG_VARIABLE( CFG_IMPS_MAXIMUM_SLEEP_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nImpsMaxSleepTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IMPS_MAXIMUM_SLEEP_TIME_DEFAULT, + CFG_IMPS_MAXIMUM_SLEEP_TIME_MIN, + CFG_IMPS_MAXIMUM_SLEEP_TIME_MAX ), + + REG_VARIABLE( CFG_IMPS_MODERATE_SLEEP_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nImpsModSleepTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IMPS_MODERATE_SLEEP_TIME_DEFAULT, + CFG_IMPS_MODERATE_SLEEP_TIME_MIN, + CFG_IMPS_MODERATE_SLEEP_TIME_MAX ), + + REG_VARIABLE( CFG_ENABLE_BMPS_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIsBmpsEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_BMPS_DEFAULT, + CFG_ENABLE_BMPS_MIN, + CFG_ENABLE_BMPS_MAX ), + + REG_VARIABLE( CFG_BMPS_MINIMUM_LI_NAME, WLAN_PARAM_Integer, + hdd_config_t, nBmpsMinListenInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BMPS_MINIMUM_LI_DEFAULT, + CFG_BMPS_MINIMUM_LI_MIN, + CFG_BMPS_MINIMUM_LI_MAX ), + + REG_VARIABLE( CFG_BMPS_MAXIMUM_LI_NAME, WLAN_PARAM_Integer, + hdd_config_t, nBmpsMaxListenInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BMPS_MAXIMUM_LI_DEFAULT, + CFG_BMPS_MAXIMUM_LI_MIN, + CFG_BMPS_MAXIMUM_LI_MAX ), + + REG_VARIABLE( CFG_BMPS_MODERATE_LI_NAME, WLAN_PARAM_Integer, + hdd_config_t, nBmpsModListenInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BMPS_MODERATE_LI_DEFAULT, + CFG_BMPS_MODERATE_LI_MIN, + CFG_BMPS_MODERATE_LI_MAX ), + + REG_VARIABLE( CFG_ENABLE_AUTO_BMPS_TIMER_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIsAutoBmpsTimerEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_AUTO_BMPS_TIMER_DEFAULT, + CFG_ENABLE_AUTO_BMPS_TIMER_MIN, + CFG_ENABLE_AUTO_BMPS_TIMER_MAX ), + + REG_VARIABLE( CFG_AUTO_BMPS_TIMER_VALUE_NAME, WLAN_PARAM_Integer, + hdd_config_t, nAutoBmpsTimerValue, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AUTO_BMPS_TIMER_VALUE_DEFAULT, + CFG_AUTO_BMPS_TIMER_VALUE_MIN, + CFG_AUTO_BMPS_TIMER_VALUE_MAX ), + + REG_VARIABLE( CFG_DOT11_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, dot11Mode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_DOT11_MODE_DEFAULT, + CFG_DOT11_MODE_MIN, + CFG_DOT11_MODE_MAX ), + + REG_VARIABLE( CFG_CHANNEL_BONDING_MODE_24GHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, nChannelBondingMode24GHz, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_CHANNEL_BONDING_MODE_DEFAULT, + CFG_CHANNEL_BONDING_MODE_MIN, + CFG_CHANNEL_BONDING_MODE_MAX), + + REG_VARIABLE( CFG_CHANNEL_BONDING_MODE_5GHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, nChannelBondingMode5GHz, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_CHANNEL_BONDING_MODE_DEFAULT, + CFG_CHANNEL_BONDING_MODE_MIN, + CFG_CHANNEL_BONDING_MODE_MAX), + + REG_VARIABLE( CFG_MAX_RX_AMPDU_FACTOR_NAME, WLAN_PARAM_Integer, + hdd_config_t, MaxRxAmpduFactor, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_MAX_RX_AMPDU_FACTOR_DEFAULT, + CFG_MAX_RX_AMPDU_FACTOR_MIN, + CFG_MAX_RX_AMPDU_FACTOR_MAX), + + REG_VARIABLE(CFG_HT_MPDU_DENSITY_NAME, WLAN_PARAM_Integer, + hdd_config_t, ht_mpdu_density, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_HT_MPDU_DENSITY_DEFAULT, + CFG_HT_MPDU_DENSITY_MIN, + CFG_HT_MPDU_DENSITY_MAX), + + REG_VARIABLE( CFG_FIXED_RATE_NAME, WLAN_PARAM_Integer, + hdd_config_t, TxRate, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_FIXED_RATE_DEFAULT, + CFG_FIXED_RATE_MIN, + CFG_FIXED_RATE_MAX ), + + REG_VARIABLE( CFG_SHORT_GI_20MHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, ShortGI20MhzEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SHORT_GI_20MHZ_DEFAULT, + CFG_SHORT_GI_20MHZ_MIN, + CFG_SHORT_GI_20MHZ_MAX ), + + REG_VARIABLE( CFG_BLOCK_ACK_AUTO_SETUP_NAME, WLAN_PARAM_Integer, + hdd_config_t, BlockAckAutoSetup, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_BLOCK_ACK_AUTO_SETUP_DEFAULT, + CFG_BLOCK_ACK_AUTO_SETUP_MIN, + CFG_BLOCK_ACK_AUTO_SETUP_MAX ), + + REG_VARIABLE( CFG_SCAN_RESULT_AGE_COUNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, ScanResultAgeCount, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SCAN_RESULT_AGE_COUNT_DEFAULT, + CFG_SCAN_RESULT_AGE_COUNT_MIN, + CFG_SCAN_RESULT_AGE_COUNT_MAX ), + + REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_NCNPS_NAME, WLAN_PARAM_Integer, + hdd_config_t, nScanAgeTimeNCNPS, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SCAN_RESULT_AGE_TIME_NCNPS_DEFAULT, + CFG_SCAN_RESULT_AGE_TIME_NCNPS_MIN, + CFG_SCAN_RESULT_AGE_TIME_NCNPS_MAX ), + + REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_NCPS_NAME, WLAN_PARAM_Integer, + hdd_config_t, nScanAgeTimeNCPS, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SCAN_RESULT_AGE_TIME_NCPS_DEFAULT, + CFG_SCAN_RESULT_AGE_TIME_NCPS_MIN, + CFG_SCAN_RESULT_AGE_TIME_NCPS_MAX ), + + REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_CNPS_NAME, WLAN_PARAM_Integer, + hdd_config_t, nScanAgeTimeCNPS, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SCAN_RESULT_AGE_TIME_CNPS_DEFAULT, + CFG_SCAN_RESULT_AGE_TIME_CNPS_MIN, + CFG_SCAN_RESULT_AGE_TIME_CNPS_MAX ), + + REG_VARIABLE( CFG_SCAN_RESULT_AGE_TIME_CPS_NAME, WLAN_PARAM_Integer, + hdd_config_t, nScanAgeTimeCPS, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SCAN_RESULT_AGE_TIME_CPS_DEFAULT, + CFG_SCAN_RESULT_AGE_TIME_CPS_MIN, + CFG_SCAN_RESULT_AGE_TIME_CPS_MAX ), + + REG_VARIABLE( CFG_RSSI_CATEGORY_GAP_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRssiCatGap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RSSI_CATEGORY_GAP_DEFAULT, + CFG_RSSI_CATEGORY_GAP_MIN, + CFG_RSSI_CATEGORY_GAP_MAX ), + + REG_VARIABLE( CFG_SHORT_PREAMBLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIsShortPreamble, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SHORT_PREAMBLE_DEFAULT, + CFG_SHORT_PREAMBLE_MIN, + CFG_SHORT_PREAMBLE_MAX ), + + REG_VARIABLE_STRING( CFG_IBSS_BSSID_NAME, WLAN_PARAM_MacAddr, + hdd_config_t, IbssBssid, + VAR_FLAGS_OPTIONAL, + (void *)CFG_IBSS_BSSID_DEFAULT ), + + REG_VARIABLE_STRING( CFG_INTF0_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + hdd_config_t, intfMacAddr[0], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF0_MAC_ADDR_DEFAULT ), + + REG_VARIABLE_STRING( CFG_INTF1_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + hdd_config_t, intfMacAddr[1], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF1_MAC_ADDR_DEFAULT ), + + REG_VARIABLE_STRING( CFG_INTF2_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + hdd_config_t, intfMacAddr[2], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF2_MAC_ADDR_DEFAULT ), + + REG_VARIABLE_STRING( CFG_INTF3_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + hdd_config_t, intfMacAddr[3], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF3_MAC_ADDR_DEFAULT ), + + REG_VARIABLE( CFG_AP_QOS_UAPSD_MODE_NAME , WLAN_PARAM_Integer, + hdd_config_t, apUapsdEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_QOS_UAPSD_MODE_DEFAULT, + CFG_AP_QOS_UAPSD_MODE_MIN, + CFG_AP_QOS_UAPSD_MODE_MAX ), + + REG_VARIABLE_STRING( CFG_AP_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, apCntryCode, + VAR_FLAGS_OPTIONAL, + (void *)CFG_AP_COUNTRY_CODE_DEFAULT ), + + REG_VARIABLE( CFG_AP_ENABLE_RANDOM_BSSID_NAME, WLAN_PARAM_Integer, + hdd_config_t, apRandomBssidEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_ENABLE_RANDOM_BSSID_DEFAULT, + CFG_AP_ENABLE_RANDOM_BSSID_MIN, + CFG_AP_ENABLE_RANDOM_BSSID_MAX ), + + REG_VARIABLE( CFG_AP_ENABLE_PROTECTION_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, apProtEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_ENABLE_PROTECTION_MODE_DEFAULT, + CFG_AP_ENABLE_PROTECTION_MODE_MIN, + CFG_AP_ENABLE_PROTECTION_MODE_MAX ), + + REG_VARIABLE( CFG_AP_PROTECTION_MODE_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, apProtection, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_PROTECTION_MODE_DEFAULT, + CFG_AP_PROTECTION_MODE_MIN, + CFG_AP_PROTECTION_MODE_MAX ), + + REG_VARIABLE( CFG_AP_OBSS_PROTECTION_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, apOBSSProtEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_OBSS_PROTECTION_MODE_DEFAULT, + CFG_AP_OBSS_PROTECTION_MODE_MIN, + CFG_AP_OBSS_PROTECTION_MODE_MAX ), + + REG_VARIABLE( CFG_AP_STA_SECURITY_SEPERATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, apDisableIntraBssFwd, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_STA_SECURITY_SEPERATION_DEFAULT, + CFG_AP_STA_SECURITY_SEPERATION_MIN, + CFG_AP_STA_SECURITY_SEPERATION_MAX ), + + REG_VARIABLE( CFG_FRAMES_PROCESSING_TH_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, MinFramesProcThres, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FRAMES_PROCESSING_TH_DEFAULT, + CFG_FRAMES_PROCESSING_TH_MIN, + CFG_FRAMES_PROCESSING_TH_MAX ), + + REG_VARIABLE(CFG_FORCE_SAP_ACS, WLAN_PARAM_Integer, + hdd_config_t, force_sap_acs, + VAR_FLAGS_DYNAMIC_CFG | + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FORCE_SAP_ACS_DEFAULT, + CFG_FORCE_SAP_ACS_MIN, + CFG_FORCE_SAP_ACS_MAX), + + REG_VARIABLE(CFG_FORCE_SAP_ACS_START_CH, WLAN_PARAM_Integer, + hdd_config_t, force_sap_acs_st_ch, + VAR_FLAGS_DYNAMIC_CFG | + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FORCE_SAP_ACS_START_CH_DEFAULT, + CFG_FORCE_SAP_ACS_START_CH_MIN, + CFG_FORCE_SAP_ACS_START_CH_MAX), + + REG_VARIABLE(CFG_FORCE_SAP_ACS_END_CH, WLAN_PARAM_Integer, + hdd_config_t, force_sap_acs_end_ch, + VAR_FLAGS_DYNAMIC_CFG | + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FORCE_SAP_ACS_END_CH_DEFAULT, + CFG_FORCE_SAP_ACS_END_CH_MIN, + CFG_FORCE_SAP_ACS_END_CH_MAX), + + + REG_VARIABLE( CFG_ENABLE_LTE_COEX , WLAN_PARAM_Integer, + hdd_config_t, enableLTECoex, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LTE_COEX_DEFAULT, + CFG_ENABLE_LTE_COEX_MIN, + CFG_ENABLE_LTE_COEX_MAX ), + + REG_VARIABLE( CFG_AP_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, apKeepAlivePeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_KEEP_ALIVE_PERIOD_DEFAULT, + CFG_AP_KEEP_ALIVE_PERIOD_MIN, + CFG_AP_KEEP_ALIVE_PERIOD_MAX), + + REG_VARIABLE( CFG_GO_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, goKeepAlivePeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_GO_KEEP_ALIVE_PERIOD_DEFAULT, + CFG_GO_KEEP_ALIVE_PERIOD_MIN, + CFG_GO_KEEP_ALIVE_PERIOD_MAX), + + REG_VARIABLE( CFG_AP_LINK_MONITOR_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, apLinkMonitorPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_LINK_MONITOR_PERIOD_DEFAULT, + CFG_AP_LINK_MONITOR_PERIOD_MIN, + CFG_AP_LINK_MONITOR_PERIOD_MAX), + + REG_VARIABLE( CFG_GO_LINK_MONITOR_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, goLinkMonitorPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_GO_LINK_MONITOR_PERIOD_DEFAULT, + CFG_GO_LINK_MONITOR_PERIOD_MIN, + CFG_GO_LINK_MONITOR_PERIOD_MAX), + + REG_VARIABLE( CFG_DISABLE_PACKET_FILTER , WLAN_PARAM_Integer, + hdd_config_t, disablePacketFilter, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_PACKET_FILTER_DEFAULT, + CFG_DISABLE_PACKET_FILTER_MIN, + CFG_DISABLE_PACKET_FILTER_MAX ), + + REG_VARIABLE( CFG_BEACON_INTERVAL_NAME, WLAN_PARAM_Integer, + hdd_config_t, nBeaconInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_BEACON_INTERVAL_DEFAULT, + CFG_BEACON_INTERVAL_MIN, + CFG_BEACON_INTERVAL_MAX ), + + REG_VARIABLE( CFG_ENABLE_IDLE_SCAN_NAME , WLAN_PARAM_Integer, + hdd_config_t, nEnableIdleScan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_IDLE_SCAN_DEFAULT, + CFG_ENABLE_IDLE_SCAN_MIN, + CFG_ENABLE_IDLE_SCAN_MAX ), + + REG_VARIABLE( CFG_ROAMING_TIME_NAME , WLAN_PARAM_Integer, + hdd_config_t, nRoamingTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAMING_TIME_DEFAULT, + CFG_ROAMING_TIME_MIN, + CFG_ROAMING_TIME_MAX ), + + REG_VARIABLE( CFG_VCC_RSSI_TRIGGER_NAME , WLAN_PARAM_Integer, + hdd_config_t, nVccRssiTrigger, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VCC_RSSI_TRIGGER_DEFAULT, + CFG_VCC_RSSI_TRIGGER_MIN, + CFG_VCC_RSSI_TRIGGER_MAX ), + + REG_VARIABLE( CFG_VCC_UL_MAC_LOSS_THRESH_NAME , WLAN_PARAM_Integer, + hdd_config_t, nVccUlMacLossThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VCC_UL_MAC_LOSS_THRESH_DEFAULT, + CFG_VCC_UL_MAC_LOSS_THRESH_MIN, + CFG_VCC_UL_MAC_LOSS_THRESH_MAX ), + + REG_VARIABLE( CFG_PASSIVE_MAX_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nPassiveMaxChnTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PASSIVE_MAX_CHANNEL_TIME_DEFAULT, + CFG_PASSIVE_MAX_CHANNEL_TIME_MIN, + CFG_PASSIVE_MAX_CHANNEL_TIME_MAX ), + + REG_VARIABLE( CFG_PASSIVE_MIN_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nPassiveMinChnTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PASSIVE_MIN_CHANNEL_TIME_DEFAULT, + CFG_PASSIVE_MIN_CHANNEL_TIME_MIN, + CFG_PASSIVE_MIN_CHANNEL_TIME_MAX ), + + REG_VARIABLE( CFG_ACTIVE_MAX_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nActiveMaxChnTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MAX_CHANNEL_TIME_DEFAULT, + CFG_ACTIVE_MAX_CHANNEL_TIME_MIN, + CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ), + + REG_VARIABLE( CFG_ACTIVE_MIN_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nActiveMinChnTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MIN_CHANNEL_TIME_DEFAULT, + CFG_ACTIVE_MIN_CHANNEL_TIME_MIN, + CFG_ACTIVE_MIN_CHANNEL_TIME_MAX ), + + REG_VARIABLE( CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nActiveMaxChnTimeBtc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_DEFAULT, + CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_MIN, + CFG_ACTIVE_MAX_CHANNEL_TIME_BTC_MAX ), + + REG_VARIABLE( CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nActiveMinChnTimeBtc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_DEFAULT, + CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_MIN, + CFG_ACTIVE_MIN_CHANNEL_TIME_BTC_MAX ), + + REG_VARIABLE( CFG_RETRY_LIMIT_ZERO_NAME, WLAN_PARAM_Integer, + hdd_config_t, retryLimitZero, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RETRY_LIMIT_ZERO_DEFAULT, + CFG_RETRY_LIMIT_ZERO_MIN, + CFG_RETRY_LIMIT_ZERO_MAX ), + + REG_VARIABLE( CFG_RETRY_LIMIT_ONE_NAME, WLAN_PARAM_Integer, + hdd_config_t, retryLimitOne, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RETRY_LIMIT_ONE_DEFAULT, + CFG_RETRY_LIMIT_ONE_MIN, + CFG_RETRY_LIMIT_ONE_MAX ), + + REG_VARIABLE( CFG_RETRY_LIMIT_TWO_NAME, WLAN_PARAM_Integer, + hdd_config_t, retryLimitTwo, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RETRY_LIMIT_TWO_DEFAULT, + CFG_RETRY_LIMIT_TWO_MIN, + CFG_RETRY_LIMIT_TWO_MAX ), + + REG_VARIABLE( CFG_DISABLE_AGG_WITH_BTC_NAME, WLAN_PARAM_Integer, + hdd_config_t, disableAggWithBtc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_AGG_WITH_BTC_DEFAULT, + CFG_DISABLE_AGG_WITH_BTC_MIN, + CFG_DISABLE_AGG_WITH_BTC_MAX ), + +#ifdef WLAN_AP_STA_CONCURRENCY + REG_VARIABLE( CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nPassiveMaxChnTimeConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_DEFAULT, + CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_MIN, + CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_MAX ), + + REG_VARIABLE( CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nPassiveMinChnTimeConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_DEFAULT, + CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_MIN, + CFG_PASSIVE_MIN_CHANNEL_TIME_CONC_MAX ), + + REG_VARIABLE( CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nActiveMaxChnTimeConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_DEFAULT, + CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_MIN, + CFG_ACTIVE_MAX_CHANNEL_TIME_CONC_MAX ), + + REG_VARIABLE( CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nActiveMinChnTimeConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_DEFAULT, + CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_MIN, + CFG_ACTIVE_MIN_CHANNEL_TIME_CONC_MAX ), + + REG_VARIABLE( CFG_REST_TIME_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRestTimeConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_REST_TIME_CONC_DEFAULT, + CFG_REST_TIME_CONC_MIN, + CFG_REST_TIME_CONC_MAX ), + + REG_VARIABLE( CFG_MIN_REST_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, min_rest_time_conc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MIN_REST_TIME_DEFAULT, + CFG_MIN_REST_TIME_MIN, + CFG_MIN_REST_TIME_MAX ), + + REG_VARIABLE( CFG_IDLE_TIME_NAME , WLAN_PARAM_Integer, + hdd_config_t, idle_time_conc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IDLE_TIME_DEFAULT, + CFG_IDLE_TIME_MIN, + CFG_IDLE_TIME_MAX ), + + + REG_VARIABLE( CFG_NUM_STA_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNumStaChanCombinedConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NUM_STA_CHAN_COMBINED_CONC_DEFAULT, + CFG_NUM_STA_CHAN_COMBINED_CONC_MIN, + CFG_NUM_STA_CHAN_COMBINED_CONC_MAX ), + + REG_VARIABLE( CFG_NUM_P2P_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNumP2PChanCombinedConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NUM_P2P_CHAN_COMBINED_CONC_DEFAULT, + CFG_NUM_P2P_CHAN_COMBINED_CONC_MIN, + CFG_NUM_P2P_CHAN_COMBINED_CONC_MAX ), +#endif + + REG_VARIABLE( CFG_MAX_PS_POLL_NAME, WLAN_PARAM_Integer, + hdd_config_t, nMaxPsPoll, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_PS_POLL_DEFAULT, + CFG_MAX_PS_POLL_MIN, + CFG_MAX_PS_POLL_MAX ), + + REG_VARIABLE( CFG_MAX_TX_POWER_NAME, WLAN_PARAM_Integer, + hdd_config_t, nTxPowerCap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_TX_POWER_DEFAULT, + CFG_MAX_TX_POWER_MIN, + CFG_MAX_TX_POWER_MAX ), + + REG_VARIABLE( CFG_LOW_GAIN_OVERRIDE_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIsLowGainOverride, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LOW_GAIN_OVERRIDE_DEFAULT, + CFG_LOW_GAIN_OVERRIDE_MIN, + CFG_LOW_GAIN_OVERRIDE_MAX ), + + REG_VARIABLE( CFG_RSSI_FILTER_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRssiFilterPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RSSI_FILTER_PERIOD_DEFAULT, + CFG_RSSI_FILTER_PERIOD_MIN, + CFG_RSSI_FILTER_PERIOD_MAX ), + + REG_VARIABLE( CFG_IGNORE_DTIM_NAME, WLAN_PARAM_Integer, + hdd_config_t, fIgnoreDtim, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IGNORE_DTIM_DEFAULT, + CFG_IGNORE_DTIM_MIN, + CFG_IGNORE_DTIM_MAX ), + + REG_VARIABLE( CFG_MAX_LI_MODULATED_DTIM_NAME, WLAN_PARAM_Integer, + hdd_config_t, fMaxLIModulatedDTIM, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_LI_MODULATED_DTIM_DEFAULT, + CFG_MAX_LI_MODULATED_DTIM_MIN, + CFG_MAX_LI_MODULATED_DTIM_MAX ), + + REG_VARIABLE( CFG_RX_ANT_CONFIGURATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRxAnt, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RX_ANT_CONFIGURATION_NAME_DEFAULT, + CFG_RX_ANT_CONFIGURATION_NAME_MIN, + CFG_RX_ANT_CONFIGURATION_NAME_MAX ), + + REG_VARIABLE( CFG_FW_HEART_BEAT_MONITORING_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableFwHeartBeatMonitoring, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FW_HEART_BEAT_MONITORING_DEFAULT, + CFG_FW_HEART_BEAT_MONITORING_MIN, + CFG_FW_HEART_BEAT_MONITORING_MAX ), + + REG_VARIABLE( CFG_FW_BEACON_FILTERING_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableFwBeaconFiltering, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FW_BEACON_FILTERING_DEFAULT, + CFG_FW_BEACON_FILTERING_MIN, + CFG_FW_BEACON_FILTERING_MAX ), + + REG_DYNAMIC_VARIABLE( CFG_FW_RSSI_MONITORING_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableFwRssiMonitoring, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FW_RSSI_MONITORING_DEFAULT, + CFG_FW_RSSI_MONITORING_MIN, + CFG_FW_RSSI_MONITORING_MAX, + cbNotifySetFwRssiMonitoring, 0 ), + + REG_VARIABLE(CFG_FW_MCC_RTS_CTS_PROT_NAME, WLAN_PARAM_Integer, + hdd_config_t, mcc_rts_cts_prot_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FW_MCC_RTS_CTS_PROT_DEFAULT, + CFG_FW_MCC_RTS_CTS_PROT_MIN, + CFG_FW_MCC_RTS_CTS_PROT_MAX), + + REG_VARIABLE(CFG_FW_MCC_BCAST_PROB_RESP_NAME, WLAN_PARAM_Integer, + hdd_config_t, mcc_bcast_prob_resp_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FW_MCC_BCAST_PROB_RESP_DEFAULT, + CFG_FW_MCC_BCAST_PROB_RESP_MIN, + CFG_FW_MCC_BCAST_PROB_RESP_MAX), + + REG_VARIABLE( CFG_DATA_INACTIVITY_TIMEOUT_NAME, WLAN_PARAM_Integer, + hdd_config_t, nDataInactivityTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DATA_INACTIVITY_TIMEOUT_DEFAULT, + CFG_DATA_INACTIVITY_TIMEOUT_MIN, + CFG_DATA_INACTIVITY_TIMEOUT_MAX ), + + REG_VARIABLE( CFG_NTH_BEACON_FILTER_NAME, WLAN_PARAM_Integer, + hdd_config_t, nthBeaconFilter, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NTH_BEACON_FILTER_DEFAULT, + CFG_NTH_BEACON_FILTER_MIN, + CFG_NTH_BEACON_FILTER_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_MODE_NAME , WLAN_PARAM_Integer, + hdd_config_t, WmmMode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_MODE_DEFAULT, + CFG_QOS_WMM_MODE_MIN, + CFG_QOS_WMM_MODE_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_80211E_ENABLED_NAME , WLAN_PARAM_Integer, + hdd_config_t, b80211eIsEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_80211E_ENABLED_DEFAULT, + CFG_QOS_WMM_80211E_ENABLED_MIN, + CFG_QOS_WMM_80211E_ENABLED_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_UAPSD_MASK_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, UapsdMask, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_UAPSD_MASK_DEFAULT, + CFG_QOS_WMM_UAPSD_MASK_MIN, + CFG_QOS_WMM_UAPSD_MASK_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdVoSrvIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_VO_SRV_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdVoSuspIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_VO_SUS_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdViSrvIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_VI_SRV_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdViSuspIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_VI_SUS_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdBeSrvIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_BE_SRV_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdBeSuspIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_BE_SUS_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdBkSrvIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_BK_SRV_INTV_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraUapsdBkSuspIntv, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_DEFAULT, + CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_MIN, + CFG_QOS_WMM_INFRA_UAPSD_BK_SUS_INTV_MAX ), + +#ifdef FEATURE_WLAN_ESE + REG_VARIABLE( CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_NAME, WLAN_PARAM_Integer, + hdd_config_t, InfraInactivityInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_DEFAULT, + CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_MIN, + CFG_QOS_WMM_INFRA_INACTIVITY_INTERVAL_MAX), + + REG_DYNAMIC_VARIABLE( CFG_ESE_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, isEseIniFeatureEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ESE_FEATURE_ENABLED_DEFAULT, + CFG_ESE_FEATURE_ENABLED_MIN, + CFG_ESE_FEATURE_ENABLED_MAX, + cbNotifySetEseFeatureEnabled, 0 ), +#endif // FEATURE_WLAN_ESE + +#ifdef FEATURE_WLAN_LFR + // flag to turn ON/OFF Legacy Fast Roaming + REG_DYNAMIC_VARIABLE( CFG_LFR_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, isFastRoamIniFeatureEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LFR_FEATURE_ENABLED_DEFAULT, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX, + NotifyIsFastRoamIniFeatureEnabled, 0 ), + + /* flag to turn ON/OFF Motion assistance for Legacy Fast Roaming */ + REG_DYNAMIC_VARIABLE( CFG_LFR_MAWC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, MAWCEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LFR_MAWC_FEATURE_ENABLED_DEFAULT, + CFG_LFR_MAWC_FEATURE_ENABLED_MIN, + CFG_LFR_MAWC_FEATURE_ENABLED_MAX, + NotifyIsMAWCIniFeatureEnabled, 0 ), + +#endif // FEATURE_WLAN_LFR + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + // flag to turn ON/OFF 11r and ESE FastTransition + REG_DYNAMIC_VARIABLE( CFG_FAST_TRANSITION_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, isFastTransitionEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT, + CFG_FAST_TRANSITION_ENABLED_NAME_MIN, + CFG_FAST_TRANSITION_ENABLED_NAME_MAX, + cbNotifySetFastTransitionEnabled, 0 ), + + /* Variable to specify the delta/difference between the RSSI of current AP + * and roamable AP while roaming */ + REG_DYNAMIC_VARIABLE( CFG_ROAM_RSSI_DIFF_NAME, WLAN_PARAM_Integer, + hdd_config_t, RoamRssiDiff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_RSSI_DIFF_DEFAULT, + CFG_ROAM_RSSI_DIFF_MIN, + CFG_ROAM_RSSI_DIFF_MAX, + cbNotifySetRoamRssiDiff, 0), + + REG_DYNAMIC_VARIABLE( CFG_IMMEDIATE_ROAM_RSSI_DIFF_NAME, WLAN_PARAM_Integer, + hdd_config_t, nImmediateRoamRssiDiff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IMMEDIATE_ROAM_RSSI_DIFF_DEFAULT, + CFG_IMMEDIATE_ROAM_RSSI_DIFF_MIN, + CFG_IMMEDIATE_ROAM_RSSI_DIFF_MAX, + cbNotifySetImmediateRoamRssiDiff, 0), + + REG_DYNAMIC_VARIABLE( CFG_ENABLE_WES_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, isWESModeEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_WES_MODE_NAME_DEFAULT, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX, + cbNotifySetWESMode, 0), +#endif +#ifdef FEATURE_WLAN_OKC + REG_DYNAMIC_VARIABLE( CFG_OKC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, isOkcIniFeatureEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OKC_FEATURE_ENABLED_DEFAULT, + CFG_OKC_FEATURE_ENABLED_MIN, + CFG_OKC_FEATURE_ENABLED_MAX, + cbNotifySetOkcFeatureEnabled, 0 ), +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_OFFLOAD_ENABLED, WLAN_PARAM_Integer, + hdd_config_t, isRoamOffloadScanEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX, + cbNotifyUpdateRoamScanOffloadEnabled, 0), +#endif + REG_VARIABLE( CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME , WLAN_PARAM_Integer, + hdd_config_t, PktClassificationBasis, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_PKT_CLASSIFY_BASIS_DEFAULT, + CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN, + CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraDirAcVo, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_VO_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_VO_MIN, + CFG_QOS_WMM_INFRA_DIR_AC_VO_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraNomMsduSizeAcVo, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_MIN, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VO_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMeanDataRateAcVo, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_MIN, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VO_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMinPhyRateAcVo, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_MIN, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VO_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_VO_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraSbaAcVo, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_VO_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_VO_MIN, + CFG_QOS_WMM_INFRA_SBA_AC_VO_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_VI_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraDirAcVi, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_VI_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_VI_MIN, + CFG_QOS_WMM_INFRA_DIR_AC_VI_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraNomMsduSizeAcVi, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_MIN, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_VI_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMeanDataRateAcVi, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_MIN, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_VI_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMinPhyRateAcVi, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_MIN, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_VI_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_VI_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraSbaAcVi, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_VI_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_VI_MIN, + CFG_QOS_WMM_INFRA_SBA_AC_VI_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_BE_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraDirAcBe, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_BE_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_BE_MIN, + CFG_QOS_WMM_INFRA_DIR_AC_BE_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraNomMsduSizeAcBe, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_MIN, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BE_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMeanDataRateAcBe, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_MIN, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BE_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMinPhyRateAcBe, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_MIN, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BE_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_BE_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraSbaAcBe, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_BE_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_BE_MIN, + CFG_QOS_WMM_INFRA_SBA_AC_BE_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_BK_NAME , WLAN_PARAM_Integer, + hdd_config_t, InfraDirAcBk, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_BK_DEFAULT, + CFG_QOS_WMM_INFRA_DIR_AC_BK_MIN, + CFG_QOS_WMM_INFRA_DIR_AC_BK_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraNomMsduSizeAcBk, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_DEFAULT, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_MIN, + CFG_QOS_WMM_INFRA_NOM_MSDU_SIZE_AC_BK_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMeanDataRateAcBk, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_DEFAULT, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_MIN, + CFG_QOS_WMM_INFRA_MEAN_DATA_RATE_AC_BK_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraMinPhyRateAcBk, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_DEFAULT, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_MIN, + CFG_QOS_WMM_INFRA_MIN_PHY_RATE_AC_BK_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_INFRA_SBA_AC_BK_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, InfraSbaAcBk, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_BK_DEFAULT, + CFG_QOS_WMM_INFRA_SBA_AC_BK_MIN, + CFG_QOS_WMM_INFRA_SBA_AC_BK_MAX ), + + REG_VARIABLE( CFG_TL_DELAYED_TRGR_FRM_INT_NAME , WLAN_PARAM_Integer, + hdd_config_t, DelayedTriggerFrmInt, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TL_DELAYED_TRGR_FRM_INT_DEFAULT, + CFG_TL_DELAYED_TRGR_FRM_INT_MIN, + CFG_TL_DELAYED_TRGR_FRM_INT_MAX ), + + REG_VARIABLE_STRING( CFG_WOWL_PATTERN_NAME, WLAN_PARAM_String, + hdd_config_t, wowlPattern, + VAR_FLAGS_OPTIONAL, + (void *)CFG_WOWL_PATTERN_DEFAULT ), + + REG_VARIABLE( CFG_QOS_IMPLICIT_SETUP_ENABLED_NAME , WLAN_PARAM_Integer, + hdd_config_t, bImplicitQosEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_IMPLICIT_SETUP_ENABLED_DEFAULT, + CFG_QOS_IMPLICIT_SETUP_ENABLED_MIN, + CFG_QOS_IMPLICIT_SETUP_ENABLED_MAX ), + + REG_VARIABLE( CFG_BTC_EXECUTION_MODE_NAME , WLAN_PARAM_Integer, + hdd_config_t, btcExecutionMode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_EXECUTION_MODE_DEFAULT, + CFG_BTC_EXECUTION_MODE_MIN, + CFG_BTC_EXECUTION_MODE_MAX ), + + REG_VARIABLE( CFG_MWS_COEX_CONFIG1_NAME , WLAN_PARAM_Integer, + hdd_config_t, mwsCoexConfig[0], + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MWS_COEX_CONFIGX_DEFAULT, + CFG_MWS_COEX_CONFIGX_MIN, + CFG_MWS_COEX_CONFIGX_MAX ), + + REG_VARIABLE( CFG_MWS_COEX_CONFIG2_NAME , WLAN_PARAM_Integer, + hdd_config_t, mwsCoexConfig[1], + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MWS_COEX_CONFIGX_DEFAULT, + CFG_MWS_COEX_CONFIGX_MIN, + CFG_MWS_COEX_CONFIGX_MAX ), + + REG_VARIABLE( CFG_MWS_COEX_CONFIG3_NAME , WLAN_PARAM_Integer, + hdd_config_t, mwsCoexConfig[2], + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MWS_COEX_CONFIGX_DEFAULT, + CFG_MWS_COEX_CONFIGX_MIN, + CFG_MWS_COEX_CONFIGX_MAX ), + + REG_VARIABLE( CFG_MWS_COEX_CONFIG4_NAME , WLAN_PARAM_Integer, + hdd_config_t, mwsCoexConfig[3], + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MWS_COEX_CONFIGX_DEFAULT, + CFG_MWS_COEX_CONFIGX_MIN, + CFG_MWS_COEX_CONFIGX_MAX ), + + REG_VARIABLE( CFG_MWS_COEX_CONFIG5_NAME , WLAN_PARAM_Integer, + hdd_config_t, mwsCoexConfig[4], + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MWS_COEX_CONFIGX_DEFAULT, + CFG_MWS_COEX_CONFIGX_MIN, + CFG_MWS_COEX_CONFIGX_MAX ), + + REG_VARIABLE( CFG_MWS_COEX_CONFIG6_NAME , WLAN_PARAM_Integer, + hdd_config_t, mwsCoexConfig[5], + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MWS_COEX_CONFIGX_DEFAULT, + CFG_MWS_COEX_CONFIGX_MIN, + CFG_MWS_COEX_CONFIGX_MAX ), + + REG_VARIABLE( CFG_AP_LISTEN_MODE_NAME , WLAN_PARAM_Integer, + hdd_config_t, nEnableListenMode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_LISTEN_MODE_DEFAULT, + CFG_AP_LISTEN_MODE_MIN, + CFG_AP_LISTEN_MODE_MAX ), + + REG_VARIABLE( CFG_AP_AUTO_SHUT_OFF , WLAN_PARAM_Integer, + hdd_config_t, nAPAutoShutOff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AP_AUTO_SHUT_OFF_DEFAULT, + CFG_AP_AUTO_SHUT_OFF_MIN, + CFG_AP_AUTO_SHUT_OFF_MAX ), + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + REG_VARIABLE( CFG_WLAN_MCC_TO_SCC_SWITCH_MODE , WLAN_PARAM_Integer, + hdd_config_t, WlanMccToSccSwitchMode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_DEFAULT, + CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MIN, + CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX ), +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + REG_VARIABLE( CFG_WLAN_AUTO_SHUTDOWN , WLAN_PARAM_Integer, + hdd_config_t, WlanAutoShutdown, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_WLAN_AUTO_SHUTDOWN_DEFAULT, + CFG_WLAN_AUTO_SHUTDOWN_MIN, + CFG_WLAN_AUTO_SHUTDOWN_MAX ), +#endif +#if defined WLAN_FEATURE_VOWIFI + REG_VARIABLE( CFG_RRM_ENABLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, fRrmEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RRM_ENABLE_DEFAULT, + CFG_RRM_ENABLE_MIN, + CFG_RRM_ENABLE_MAX ), + + REG_VARIABLE( CFG_RRM_OPERATING_CHAN_MAX_DURATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, nInChanMeasMaxDuration, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RRM_OPERATING_CHAN_MAX_DURATION_DEFAULT, + CFG_RRM_OPERATING_CHAN_MAX_DURATION_MIN, + CFG_RRM_OPERATING_CHAN_MAX_DURATION_MAX ), + + REG_VARIABLE( CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, nOutChanMeasMaxDuration, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_DEFAULT, + CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_MIN, + CFG_RRM_NON_OPERATING_CHAN_MAX_DURATION_MAX ), + + REG_VARIABLE( CFG_RRM_MEAS_RANDOMIZATION_INTVL_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRrmRandnIntvl, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RRM_MEAS_RANDOMIZATION_INTVL_DEFAULT, + CFG_RRM_MEAS_RANDOMIZATION_INTVL_MIN, + CFG_RRM_MEAS_RANDOMIZATION_INTVL_MAX ), + + REG_VARIABLE_STRING(CFG_RM_CAPABILITY_NAME, WLAN_PARAM_String, + hdd_config_t, rm_capability, VAR_FLAGS_OPTIONAL, + (void *) CFG_RM_CAPABILITY_DEFAULT), +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + REG_VARIABLE( CFG_FT_RESOURCE_REQ_NAME, WLAN_PARAM_Integer, + hdd_config_t, fFTResourceReqSupported, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FT_RESOURCE_REQ_DEFAULT, + CFG_FT_RESOURCE_REQ_MIN, + CFG_FT_RESOURCE_REQ_MAX ), +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + REG_DYNAMIC_VARIABLE( CFG_NEIGHBOR_SCAN_TIMER_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNeighborScanPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX, + cbNotifySetNeighborScanPeriod, 0 ), + + REG_VARIABLE( CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNeighborReassocRssiThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_DEFAULT, + CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_MIN, + CFG_NEIGHBOR_REASSOC_RSSI_THRESHOLD_MAX ), + + REG_DYNAMIC_VARIABLE( CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNeighborLookupRssiThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX, + cbNotifySetNeighborLookupRssiThreshold, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_NAME, WLAN_PARAM_Integer, + hdd_config_t, nOpportunisticThresholdDiff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_DEFAULT, + CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_MIN, + CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_MAX, + cbNotifySetOpportunisticScanThresholdDiff, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_RESCAN_RSSI_DIFF_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRoamRescanRssiDiff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_RESCAN_RSSI_DIFF_DEFAULT, + CFG_ROAM_RESCAN_RSSI_DIFF_MIN, + CFG_ROAM_RESCAN_RSSI_DIFF_MAX, + cbNotifySetRoamRescanRssiDiff, 0 ), + + REG_VARIABLE_STRING( CFG_NEIGHBOR_SCAN_CHAN_LIST_NAME, WLAN_PARAM_String, + hdd_config_t, neighborScanChanList, + VAR_FLAGS_OPTIONAL, + (void *)CFG_NEIGHBOR_SCAN_CHAN_LIST_DEFAULT ), + + REG_DYNAMIC_VARIABLE( CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNeighborScanMinChanTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX, + cbNotifySetNeighborScanMinChanTime, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNeighborScanMaxChanTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX, + cbNotifySetNeighborScanMaxChanTime, 0 ), + + REG_VARIABLE( CFG_11R_NEIGHBOR_REQ_MAX_TRIES_NAME, WLAN_PARAM_Integer, + hdd_config_t, nMaxNeighborReqTries, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_11R_NEIGHBOR_REQ_MAX_TRIES_DEFAULT, + CFG_11R_NEIGHBOR_REQ_MAX_TRIES_MIN, + CFG_11R_NEIGHBOR_REQ_MAX_TRIES_MAX), + + REG_DYNAMIC_VARIABLE( CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNeighborResultsRefreshPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT, + CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN, + CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX, + cbNotifySetNeighborResultsRefreshPeriod, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_EMPTY_SCAN_REFRESH_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, nEmptyScanRefreshPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT, + CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN, + CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX, + cbNotifySetEmptyScanRefreshPeriod, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_BMISS_FIRST_BCNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRoamBmissFirstBcnt, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_BMISS_FIRST_BCNT_DEFAULT, + CFG_ROAM_BMISS_FIRST_BCNT_MIN, + CFG_ROAM_BMISS_FIRST_BCNT_MAX, + cbNotifySetRoamBmissFirstBcnt, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_BMISS_FINAL_BCNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRoamBmissFinalBcnt, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_BMISS_FINAL_BCNT_DEFAULT, + CFG_ROAM_BMISS_FINAL_BCNT_MIN, + CFG_ROAM_BMISS_FINAL_BCNT_MAX, + cbNotifySetRoamBmissFinalBcnt, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_BEACON_RSSI_WEIGHT_NAME, WLAN_PARAM_Integer, + hdd_config_t, nRoamBeaconRssiWeight, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_BEACON_RSSI_WEIGHT_DEFAULT, + CFG_ROAM_BEACON_RSSI_WEIGHT_MIN, + CFG_ROAM_BEACON_RSSI_WEIGHT_MAX, + cbNotifySetRoamBeaconRssiWeight, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAMING_DFS_CHANNEL_NAME , WLAN_PARAM_Integer, + hdd_config_t, allowDFSChannelRoam, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAMING_DFS_CHANNEL_DEFAULT, + CFG_ROAMING_DFS_CHANNEL_MIN, + CFG_ROAMING_DFS_CHANNEL_MAX, + cbNotifySetDFSScanMode, 0), + + REG_DYNAMIC_VARIABLE( CFG_DELAY_BEFORE_VDEV_STOP_NAME, WLAN_PARAM_Integer, + hdd_config_t, delay_before_vdev_stop, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DELAY_BEFORE_VDEV_STOP_DEFAULT, + CFG_DELAY_BEFORE_VDEV_STOP_MIN, + CFG_DELAY_BEFORE_VDEV_STOP_MAX, + cb_notify_set_delay_before_vdev_stop, 0 ), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_NAME, + WLAN_PARAM_Integer, + hdd_config_t, nhi_rssi_scan_max_count, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_MIN, + CFG_ROAM_SCAN_HI_RSSI_MAXCOUNT_MAX, + cb_notify_set_roam_scan_hi_rssi_scan_params, + eCSR_HI_RSSI_SCAN_MAXCOUNT_ID), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_HI_RSSI_DELTA_NAME, WLAN_PARAM_Integer, + hdd_config_t, nhi_rssi_scan_rssi_delta, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_DELTA_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_DELTA_MIN, + CFG_ROAM_SCAN_HI_RSSI_DELTA_MAX, + cb_notify_set_roam_scan_hi_rssi_scan_params, + eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_HI_RSSI_DELAY_NAME, WLAN_PARAM_Integer, + hdd_config_t, nhi_rssi_scan_delay, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_DELAY_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_DELAY_MIN, + CFG_ROAM_SCAN_HI_RSSI_DELAY_MAX, + cb_notify_set_roam_scan_hi_rssi_scan_params, + eCSR_HI_RSSI_SCAN_DELAY_ID), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_HI_RSSI_UB_NAME, + WLAN_PARAM_SignedInteger, + hdd_config_t, nhi_rssi_scan_rssi_ub, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_UB_DEFAULT, + CFG_ROAM_SCAN_HI_RSSI_UB_MIN, + CFG_ROAM_SCAN_HI_RSSI_UB_MAX, + cb_notify_set_roam_scan_hi_rssi_scan_params, + eCSR_HI_RSSI_SCAN_RSSI_UB_ID), + + +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ + + REG_VARIABLE( CFG_QOS_WMM_BURST_SIZE_DEFN_NAME , WLAN_PARAM_Integer, + hdd_config_t, burstSizeDefinition, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_BURST_SIZE_DEFN_DEFAULT, + CFG_QOS_WMM_BURST_SIZE_DEFN_MIN, + CFG_QOS_WMM_BURST_SIZE_DEFN_MAX ), + + REG_VARIABLE( CFG_MCAST_BCAST_FILTER_SETTING_NAME, WLAN_PARAM_Integer, + hdd_config_t, mcastBcastFilterSetting, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MCAST_BCAST_FILTER_SETTING_DEFAULT, + CFG_MCAST_BCAST_FILTER_SETTING_MIN, + CFG_MCAST_BCAST_FILTER_SETTING_MAX ), + + REG_VARIABLE( CFG_ENABLE_HOST_ARPOFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fhostArpOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HOST_ARPOFFLOAD_DEFAULT, + CFG_ENABLE_HOST_ARPOFFLOAD_MIN, + CFG_ENABLE_HOST_ARPOFFLOAD_MAX ), + +#ifdef FEATURE_WLAN_RA_FILTERING + REG_VARIABLE( CFG_RA_FILTER_ENABLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, IsRArateLimitEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RA_FILTER_ENABLE_DEFAULT, + CFG_RA_FILTER_ENABLE_MIN, + CFG_RA_FILTER_ENABLE_MAX ), + + REG_VARIABLE( CFG_RA_RATE_LIMIT_INTERVAL_NAME, WLAN_PARAM_Integer, + hdd_config_t, RArateLimitInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RA_RATE_LIMIT_INTERVAL_DEFAULT, + CFG_RA_RATE_LIMIT_INTERVAL_MIN, + CFG_RA_RATE_LIMIT_INTERVAL_MAX ), +#endif + + REG_VARIABLE( CFG_ENABLE_HOST_SSDP_NAME, WLAN_PARAM_Integer, + hdd_config_t, ssdp, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HOST_SSDP_DEFAULT, + CFG_ENABLE_HOST_SSDP_MIN, + CFG_ENABLE_HOST_SSDP_MAX ), + + REG_VARIABLE( CFG_ENABLE_HOST_BROADCAST_NAME, WLAN_PARAM_Integer, + hdd_config_t, bcastptrn, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HOST_BROADCAST_DEFAULT, + CFG_ENABLE_HOST_BROADCAST_MIN, + CFG_ENABLE_HOST_BROADCAST_MAX ), + +#ifdef FEATURE_RUNTIME_PM + REG_VARIABLE( CFG_ENABLE_RUNTIME_PM, WLAN_PARAM_Integer, + hdd_config_t, runtime_pm, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_RUNTIME_PM_DEFAULT, + CFG_ENABLE_RUNTIME_PM_MIN, + CFG_ENABLE_RUNTIME_PM_MAX ), + + REG_VARIABLE( CFG_RUNTIME_PM_AUTO_NAME, WLAN_PARAM_Integer, + hdd_config_t, runtime_pm_delay, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RUNTIME_PM_AUTO_DEFAULT, + CFG_RUNTIME_PM_AUTO_MIN, + CFG_RUNTIME_PM_AUTO_MAX ), +#endif + +#ifdef FEATURE_SECURE_FIRMWARE + REG_VARIABLE(CFG_ENABLE_FW_HASH_CHECK_NAME, WLAN_PARAM_Integer, + hdd_config_t, enable_fw_hash_check, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_HASH_CHECK_DEFAULT, + CFG_ENABLE_FW_HASH_CHECK_MIN, + CFG_ENABLE_FW_HASH_CHECK_MAX), +#endif + + REG_VARIABLE( CFG_ENABLE_HOST_NSOFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fhostNSOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HOST_NSOFFLOAD_DEFAULT, + CFG_ENABLE_HOST_NSOFFLOAD_MIN, + CFG_ENABLE_HOST_NSOFFLOAD_MAX ), + + REG_VARIABLE( CFG_QOS_WMM_TS_INFO_ACK_POLICY_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, tsInfoAckPolicy, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_WMM_TS_INFO_ACK_POLICY_DEFAULT, + CFG_QOS_WMM_TS_INFO_ACK_POLICY_MIN, + CFG_QOS_WMM_TS_INFO_ACK_POLICY_MAX ), + + REG_VARIABLE( CFG_SINGLE_TID_RC_NAME, WLAN_PARAM_Integer, + hdd_config_t, bSingleTidRc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SINGLE_TID_RC_DEFAULT, + CFG_SINGLE_TID_RC_MIN, + CFG_SINGLE_TID_RC_MAX), + + REG_VARIABLE( CFG_DYNAMIC_PSPOLL_VALUE_NAME, WLAN_PARAM_Integer, + hdd_config_t, dynamicPsPollValue, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DYNAMIC_PSPOLL_VALUE_DEFAULT, + CFG_DYNAMIC_PSPOLL_VALUE_MIN, + CFG_DYNAMIC_PSPOLL_VALUE_MAX ), + + REG_VARIABLE( CFG_TELE_BCN_WAKEUP_EN_NAME, WLAN_PARAM_Integer, + hdd_config_t, teleBcnWakeupEn, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TELE_BCN_WAKEUP_EN_DEFAULT, + CFG_TELE_BCN_WAKEUP_EN_MIN, + CFG_TELE_BCN_WAKEUP_EN_MAX ), + + REG_VARIABLE( CFG_INFRA_STA_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, infraStaKeepAlivePeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_INFRA_STA_KEEP_ALIVE_PERIOD_DEFAULT, + CFG_INFRA_STA_KEEP_ALIVE_PERIOD_MIN, + CFG_INFRA_STA_KEEP_ALIVE_PERIOD_MAX), + + REG_VARIABLE( CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_NAME , WLAN_PARAM_Integer, + hdd_config_t, AddTSWhenACMIsOff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_DEFAULT, + CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_MIN, + CFG_QOS_ADDTS_WHEN_ACM_IS_OFF_MAX ), + + + REG_VARIABLE( CFG_VALIDATE_SCAN_LIST_NAME , WLAN_PARAM_Integer, + hdd_config_t, fValidateScanList, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VALIDATE_SCAN_LIST_DEFAULT, + CFG_VALIDATE_SCAN_LIST_MIN, + CFG_VALIDATE_SCAN_LIST_MAX ), + + REG_VARIABLE( CFG_NULLDATA_AP_RESP_TIMEOUT_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNullDataApRespTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NULLDATA_AP_RESP_TIMEOUT_DEFAULT, + CFG_NULLDATA_AP_RESP_TIMEOUT_MIN, + CFG_NULLDATA_AP_RESP_TIMEOUT_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_BAND_CAPABILITY_NAME, WLAN_PARAM_Integer, + hdd_config_t, nBandCapability, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAND_CAPABILITY_DEFAULT, + CFG_BAND_CAPABILITY_MIN, + CFG_BAND_CAPABILITY_MAX ), + + REG_VARIABLE( CFG_ENABLE_BEACON_EARLY_TERMINATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableBeaconEarlyTermination, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_BEACON_EARLY_TERMINATION_DEFAULT, + CFG_ENABLE_BEACON_EARLY_TERMINATION_MIN, + CFG_ENABLE_BEACON_EARLY_TERMINATION_MAX ), + +/* CFG_VOS_TRACE_ENABLE Parameters */ + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_TL_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableTL, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_WDI_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableWDI, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_HDD_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableHDD, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_SME_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableSME, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_PE_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnablePE, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_PMC_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnablePMC, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_WDA_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableWDA, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_SYS_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableSYS, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_VOSS_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableVOSS, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_SAP_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableSAP, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE( CFG_VOS_TRACE_ENABLE_HDD_SAP_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableHDDSAP, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX ), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_CFG_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableCFG, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_ADF_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableADF, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_TXRX_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableTXRX, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_HTC_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableHTC, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_HIF_NAME , WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableHIF, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_HDD_SAP_DATA_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableHDDSAPDATA, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_VOS_TRACE_ENABLE_HDD_DATA_NAME, WLAN_PARAM_Integer, + hdd_config_t, vosTraceEnableHDDDATA, + VAR_FLAGS_OPTIONAL, + CFG_VOS_TRACE_ENABLE_DEFAULT, + CFG_VOS_TRACE_ENABLE_MIN, + CFG_VOS_TRACE_ENABLE_MAX), + + REG_VARIABLE( CFG_TELE_BCN_TRANS_LI_NAME, WLAN_PARAM_Integer, + hdd_config_t, nTeleBcnTransListenInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TELE_BCN_TRANS_LI_DEFAULT, + CFG_TELE_BCN_TRANS_LI_MIN, + CFG_TELE_BCN_TRANS_LI_MAX ), + + REG_VARIABLE( CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_NAME, WLAN_PARAM_Integer, + hdd_config_t, nTeleBcnTransLiNumIdleBeacons, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_DEFAULT, + CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_MIN, + CFG_TELE_BCN_TRANS_LI_NUM_IDLE_BCNS_MAX ), + + REG_VARIABLE( CFG_TELE_BCN_MAX_LI_NAME, WLAN_PARAM_Integer, + hdd_config_t, nTeleBcnMaxListenInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TELE_BCN_MAX_LI_DEFAULT, + CFG_TELE_BCN_MAX_LI_MIN, + CFG_TELE_BCN_MAX_LI_MAX ), + + REG_VARIABLE( CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_NAME, WLAN_PARAM_Integer, + hdd_config_t, nTeleBcnMaxLiNumIdleBeacons, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_DEFAULT, + CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_MIN, + CFG_TELE_BCN_MAX_LI_NUM_IDLE_BCNS_MAX ), + + REG_VARIABLE( CFG_BCN_EARLY_TERM_WAKE_NAME, WLAN_PARAM_Integer, + hdd_config_t, bcnEarlyTermWakeInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BCN_EARLY_TERM_WAKE_DEFAULT, + 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, + CFG_ENABLE_CLOSE_LOOP_DEFAULT, + CFG_ENABLE_CLOSE_LOOP_MIN, + CFG_ENABLE_CLOSE_LOOP_MAX ), + + REG_VARIABLE( CFG_ENABLE_BYPASS_11D_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableBypass11d, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_BYPASS_11D_DEFAULT, + CFG_ENABLE_BYPASS_11D_MIN, + CFG_ENABLE_BYPASS_11D_MAX ), + + REG_VARIABLE( CFG_ENABLE_DFS_CHNL_SCAN_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableDFSChnlScan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT, + CFG_ENABLE_DFS_CHNL_SCAN_MIN, + CFG_ENABLE_DFS_CHNL_SCAN_MAX ), + + REG_VARIABLE( CFG_ENABLE_DFS_PNO_CHNL_SCAN_NAME, WLAN_PARAM_Integer, + hdd_config_t, enable_dfs_pno_chnl_scan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DFS_PNO_CHNL_SCAN_DEFAULT, + CFG_ENABLE_DFS_PNO_CHNL_SCAN_MIN, + CFG_ENABLE_DFS_PNO_CHNL_SCAN_MAX ), + + REG_VARIABLE( CFG_ENABLE_DYNAMIC_DTIM_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableDynamicDTIM, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DYNAMIC_DTIM_DEFAULT, + CFG_ENABLE_DYNAMIC_DTIM_MIN, + CFG_ENABLE_DYNAMIC_DTIM_MAX ), + + REG_VARIABLE( CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableAutomaticTxPowerControl, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_DEFAULT, + CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_MIN, + CFG_ENABLE_AUTOMATIC_TX_POWER_CONTROL_MAX ), + + REG_VARIABLE( CFG_SHORT_GI_40MHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, ShortGI40MhzEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SHORT_GI_40MHZ_DEFAULT, + CFG_SHORT_GI_40MHZ_MIN, + CFG_SHORT_GI_40MHZ_MAX ), + + REG_DYNAMIC_VARIABLE( CFG_REPORT_MAX_LINK_SPEED, WLAN_PARAM_Integer, + hdd_config_t, reportMaxLinkSpeed, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_REPORT_MAX_LINK_SPEED_DEFAULT, + CFG_REPORT_MAX_LINK_SPEED_MIN, + CFG_REPORT_MAX_LINK_SPEED_MAX, + NULL, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_LINK_SPEED_RSSI_HIGH, WLAN_PARAM_SignedInteger, + hdd_config_t, linkSpeedRssiHigh, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LINK_SPEED_RSSI_HIGH_DEFAULT, + CFG_LINK_SPEED_RSSI_HIGH_MIN, + CFG_LINK_SPEED_RSSI_HIGH_MAX, + NULL, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_LINK_SPEED_RSSI_MID, WLAN_PARAM_SignedInteger, + hdd_config_t, linkSpeedRssiMid, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LINK_SPEED_RSSI_MID_DEFAULT, + CFG_LINK_SPEED_RSSI_MID_MIN, + CFG_LINK_SPEED_RSSI_MID_MAX, + NULL, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_LINK_SPEED_RSSI_LOW, WLAN_PARAM_SignedInteger, + hdd_config_t, linkSpeedRssiLow, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LINK_SPEED_RSSI_LOW_DEFAULT, + CFG_LINK_SPEED_RSSI_LOW_MIN, + CFG_LINK_SPEED_RSSI_LOW_MAX, + NULL, 0 ), + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + REG_DYNAMIC_VARIABLE( CFG_ROAM_PREFER_5GHZ, WLAN_PARAM_Integer, + hdd_config_t, nRoamPrefer5GHz, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_PREFER_5GHZ_DEFAULT, + CFG_ROAM_PREFER_5GHZ_MIN, + CFG_ROAM_PREFER_5GHZ_MAX, + cbNotifySetRoamPrefer5GHz, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_INTRA_BAND, WLAN_PARAM_Integer, + hdd_config_t, nRoamIntraBand, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_INTRA_BAND_DEFAULT, + CFG_ROAM_INTRA_BAND_MIN, + CFG_ROAM_INTRA_BAND_MAX, + cbNotifySetRoamIntraBand, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_N_PROBES, WLAN_PARAM_Integer, + hdd_config_t, nProbes, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_N_PROBES_DEFAULT, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX, + cbNotifySetRoamScanNProbes, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_HOME_AWAY_TIME, WLAN_PARAM_Integer, + hdd_config_t, nRoamScanHomeAwayTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX, + cbNotifySetRoamScanHomeAwayTime, 0 ), + +#endif + + REG_VARIABLE( CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME, WLAN_PARAM_Integer, + hdd_config_t, isP2pDeviceAddrAdministrated, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_DEFAULT, + CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MIN, + CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MAX ), + + REG_VARIABLE( CFG_ENABLE_MCC_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableMCC, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_MCC_ENABLED_DEFAULT, + CFG_ENABLE_MCC_ENABLED_MIN, + CFG_ENABLE_MCC_ENABLED_MAX ), + + REG_VARIABLE( CFG_ALLOW_MCC_GO_DIFF_BI_NAME, WLAN_PARAM_Integer, + hdd_config_t, allowMCCGODiffBI, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ALLOW_MCC_GO_DIFF_BI_DEFAULT, + CFG_ALLOW_MCC_GO_DIFF_BI_MIN, + CFG_ALLOW_MCC_GO_DIFF_BI_MAX ), + + REG_VARIABLE( CFG_THERMAL_MIGRATION_ENABLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalMitigationEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_MIGRATION_ENABLE_DEFAULT, + CFG_THERMAL_MIGRATION_ENABLE_MIN, + CFG_THERMAL_MIGRATION_ENABLE_MAX ), + + REG_VARIABLE( CFG_THROTTLE_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, throttlePeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THROTTLE_PERIOD_DEFAULT, + CFG_THROTTLE_PERIOD_MIN, + CFG_THROTTLE_PERIOD_MAX ), + + REG_VARIABLE( CFG_ENABLE_MODULATED_DTIM_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableModulatedDTIM, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_MODULATED_DTIM_DEFAULT, + CFG_ENABLE_MODULATED_DTIM_MIN, + CFG_ENABLE_MODULATED_DTIM_MAX ), + + REG_VARIABLE( CFG_MC_ADDR_LIST_ENABLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableMCAddrList, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MC_ADDR_LIST_ENABLE_DEFAULT, + CFG_MC_ADDR_LIST_ENABLE_MIN, + CFG_MC_ADDR_LIST_ENABLE_MAX ), + +#ifdef WLAN_FEATURE_11AC + REG_VARIABLE( CFG_VHT_CHANNEL_WIDTH, WLAN_PARAM_Integer, + hdd_config_t, vhtChannelWidth, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_VHT_CHANNEL_WIDTH_DEFAULT, + CFG_VHT_CHANNEL_WIDTH_MIN, + CFG_VHT_CHANNEL_WIDTH_MAX), + + REG_VARIABLE( CFG_VHT_ENABLE_RX_MCS_8_9, WLAN_PARAM_Integer, + hdd_config_t, vhtRxMCS, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_VHT_ENABLE_RX_MCS_8_9_DEFAULT, + CFG_VHT_ENABLE_RX_MCS_8_9_MIN, + CFG_VHT_ENABLE_RX_MCS_8_9_MAX), + + REG_VARIABLE( CFG_VHT_ENABLE_TX_MCS_8_9, WLAN_PARAM_Integer, + hdd_config_t, vhtTxMCS, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_VHT_ENABLE_TX_MCS_8_9_DEFAULT, + CFG_VHT_ENABLE_TX_MCS_8_9_MIN, + CFG_VHT_ENABLE_TX_MCS_8_9_MAX), + + REG_VARIABLE( CFG_VHT_ENABLE_RX_MCS2x2_8_9, WLAN_PARAM_Integer, + hdd_config_t, vhtRxMCS2x2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_VHT_ENABLE_RX_MCS2x2_8_9_DEFAULT, + CFG_VHT_ENABLE_RX_MCS2x2_8_9_MIN, + CFG_VHT_ENABLE_RX_MCS2x2_8_9_MAX), + + REG_VARIABLE( CFG_VHT_ENABLE_TX_MCS2x2_8_9, WLAN_PARAM_Integer, + hdd_config_t, vhtTxMCS2x2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_VHT_ENABLE_TX_MCS2x2_8_9_DEFAULT, + CFG_VHT_ENABLE_TX_MCS2x2_8_9_MIN, + CFG_VHT_ENABLE_TX_MCS2x2_8_9_MAX), + + REG_VARIABLE( CFG_VHT_ENABLE_2x2_CAP_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enable2x2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_2x2_CAP_FEATURE_DEFAULT, + CFG_VHT_ENABLE_2x2_CAP_FEATURE_MIN, + CFG_VHT_ENABLE_2x2_CAP_FEATURE_MAX ), + + REG_VARIABLE( CFG_CHAIN_MASK_2G, WLAN_PARAM_Integer, + hdd_config_t, chain_mask_2g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CHAIN_MASK_2G_DEFAULT, + CFG_CHAIN_MASK_2G_MIN, + CFG_CHAIN_MASK_2G_MAX ), + + REG_VARIABLE( CFG_CHAIN_MASK_5G, WLAN_PARAM_Integer, + hdd_config_t, chain_mask_5g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CHAIN_MASK_5G_DEFAULT, + CFG_CHAIN_MASK_5G_MIN, + CFG_CHAIN_MASK_5G_MAX ), + + REG_VARIABLE( CFG_VDEV_TYPE_NSS_2G, WLAN_PARAM_Integer, + hdd_config_t, vdev_type_nss_2g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VDEV_TYPE_NSS_2G_DEFAULT, + CFG_VDEV_TYPE_NSS_2G_MIN, + CFG_VDEV_TYPE_NSS_2G_MAX ), + + REG_VARIABLE( CFG_VDEV_TYPE_NSS_5G, WLAN_PARAM_Integer, + hdd_config_t, vdev_type_nss_5g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VDEV_TYPE_NSS_5G_DEFAULT, + CFG_VDEV_TYPE_NSS_5G_MIN, + CFG_VDEV_TYPE_NSS_5G_MAX ), + + REG_VARIABLE( CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableMuBformee, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_DEFAULT, + CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_MIN, + CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_MAX ), + + REG_VARIABLE( CFG_VHT_ENABLE_PAID_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableVhtpAid, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_PAID_FEATURE_DEFAULT, + CFG_VHT_ENABLE_PAID_FEATURE_MIN, + CFG_VHT_ENABLE_PAID_FEATURE_MAX ), + + REG_VARIABLE( CFG_VHT_ENABLE_GID_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableVhtGid, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_GID_FEATURE_DEFAULT, + CFG_VHT_ENABLE_GID_FEATURE_MIN, + CFG_VHT_ENABLE_GID_FEATURE_MAX ), +#endif + + REG_VARIABLE( CFG_VHT_ENABLE_1x1_TX_CHAINMASK, WLAN_PARAM_Integer, + hdd_config_t, txchainmask1x1, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_1x1_TX_CHAINMASK_DEFAULT, + CFG_VHT_ENABLE_1x1_TX_CHAINMASK_MIN, + CFG_VHT_ENABLE_1x1_TX_CHAINMASK_MAX ), + + REG_VARIABLE( CFG_VHT_ENABLE_1x1_RX_CHAINMASK, WLAN_PARAM_Integer, + hdd_config_t, rxchainmask1x1, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_1x1_RX_CHAINMASK_DEFAULT, + CFG_VHT_ENABLE_1x1_RX_CHAINMASK_MIN, + CFG_VHT_ENABLE_1x1_RX_CHAINMASK_MAX ), + + REG_VARIABLE( CFG_ENABLE_AMPDUPS_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableAmpduPs, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_AMPDUPS_FEATURE_DEFAULT, + CFG_ENABLE_AMPDUPS_FEATURE_MIN, + CFG_ENABLE_AMPDUPS_FEATURE_MAX ), + + REG_VARIABLE( CFG_HT_ENABLE_SMPS_CAP_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableHtSmps, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_HT_ENABLE_SMPS_CAP_FEATURE_DEFAULT, + CFG_HT_ENABLE_SMPS_CAP_FEATURE_MIN, + CFG_HT_ENABLE_SMPS_CAP_FEATURE_MAX ), + + REG_VARIABLE( CFG_HT_SMPS_CAP_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, htSmps, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_HT_SMPS_CAP_FEATURE_DEFAULT, + CFG_HT_SMPS_CAP_FEATURE_MIN, + CFG_HT_SMPS_CAP_FEATURE_MAX ), + + REG_VARIABLE( CFG_DISABLE_DFS_CH_SWITCH, WLAN_PARAM_Integer, + hdd_config_t, disableDFSChSwitch, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_DFS_CH_SWITCH_DEFAULT, + CFG_DISABLE_DFS_CH_SWITCH_MIN, + CFG_DISABLE_DFS_CH_SWITCH_MAX ), + + REG_VARIABLE( CFG_ENABLE_DFS_MASTER_CAPABILITY, WLAN_PARAM_Integer, + hdd_config_t, enableDFSMasterCap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DFS_MASTER_CAPABILITY_DEFAULT, + CFG_ENABLE_DFS_MASTER_CAPABILITY_MIN, + CFG_ENABLE_DFS_MASTER_CAPABILITY_MAX ), + + REG_DYNAMIC_VARIABLE( CFG_SAP_PREFERRED_CHANNEL_LOCATION, WLAN_PARAM_Integer, + hdd_config_t, gSapPreferredChanLocation, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_PREFERRED_CHANNEL_LOCATION_DEFAULT, + CFG_SAP_PREFERRED_CHANNEL_LOCATION_MIN, + CFG_SAP_PREFERRED_CHANNEL_LOCATION_MAX, + cbNotify_set_gSapPreferredChanLocation, 0), + + REG_DYNAMIC_VARIABLE( CFG_DISABLE_DFS_JAPAN_W53, WLAN_PARAM_Integer, + hdd_config_t, gDisableDfsJapanW53, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_DFS_JAPAN_W53_DEFAULT, + CFG_DISABLE_DFS_JAPAN_W53_MIN, + CFG_DISABLE_DFS_JAPAN_W53_MAX, + chNotify_set_gDisableDfsJapanW53, 0), + + REG_VARIABLE( CFG_ENABLE_FIRST_SCAN_2G_ONLY_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableFirstScan2GOnly, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FIRST_SCAN_2G_ONLY_DEFAULT, + CFG_ENABLE_FIRST_SCAN_2G_ONLY_MIN, + CFG_ENABLE_FIRST_SCAN_2G_ONLY_MAX ), + + REG_VARIABLE( CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_NAME, WLAN_PARAM_Integer, + hdd_config_t, skipDfsChnlInP2pSearch, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_DEFAULT, + CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_MIN, + CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH_MAX ), + + REG_VARIABLE( CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, ignoreDynamicDtimInP2pMode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_DEFAULT, + CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_MIN, + CFG_IGNORE_DYNAMIC_DTIM_IN_P2P_MODE_MAX ), + + REG_VARIABLE( CFG_NUM_BUFF_ADVERT_NAME, WLAN_PARAM_Integer, + hdd_config_t,numBuffAdvert , + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_NUM_BUFF_ADVERT_DEFAULT, + CFG_NUM_BUFF_ADVERT_MIN, + CFG_NUM_BUFF_ADVERT_MAX ), + + REG_VARIABLE( CFG_MCC_CONFIG_PARAM_NAME, WLAN_PARAM_Integer, + hdd_config_t, configMccParam, + VAR_FLAGS_OPTIONAL, + CFG_MCC_CONFIG_PARAM_DEFAULT, + CFG_MCC_CONFIG_PARAM_MIN, + CFG_MCC_CONFIG_PARAM_MAX ), + + REG_VARIABLE( CFG_ENABLE_RX_STBC, WLAN_PARAM_Integer, + hdd_config_t, enableRxSTBC, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_RX_STBC_DEFAULT, + CFG_ENABLE_RX_STBC_MIN, + CFG_ENABLE_RX_STBC_MAX ), + + REG_VARIABLE( CFG_ENABLE_TX_STBC, WLAN_PARAM_Integer, + hdd_config_t, enableTxSTBC, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_TX_STBC_DEFAULT, + CFG_ENABLE_TX_STBC_MIN, + CFG_ENABLE_TX_STBC_MAX ), + + REG_VARIABLE( CFG_ENABLE_RX_LDPC, WLAN_PARAM_Integer, + hdd_config_t, enableRxLDPC, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_RX_LDPC_DEFAULT, + CFG_ENABLE_RX_LDPC_MIN, + CFG_ENABLE_RX_LDPC_MAX ), + + REG_VARIABLE( CFG_PPS_ENABLE_5G_EBT, WLAN_PARAM_Integer, + hdd_config_t, enable5gEBT, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PPS_ENABLE_5G_EBT_FEATURE_DEFAULT, + CFG_PPS_ENABLE_5G_EBT_FEATURE_MIN, + CFG_PPS_ENABLE_5G_EBT_FEATURE_MAX ), + +#ifdef FEATURE_WLAN_TDLS + REG_VARIABLE( CFG_TDLS_SUPPORT_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, fEnableTDLSSupport, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_SUPPORT_ENABLE_DEFAULT, + CFG_TDLS_SUPPORT_ENABLE_MIN, + CFG_TDLS_SUPPORT_ENABLE_MAX ), + + REG_VARIABLE( CFG_TDLS_IMPLICIT_TRIGGER, WLAN_PARAM_Integer, + hdd_config_t, fEnableTDLSImplicitTrigger, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_IMPLICIT_TRIGGER_DEFAULT, + CFG_TDLS_IMPLICIT_TRIGGER_MIN, + CFG_TDLS_IMPLICIT_TRIGGER_MAX ), + + REG_VARIABLE( CFG_TDLS_TX_STATS_PERIOD, WLAN_PARAM_Integer, + hdd_config_t, fTDLSTxStatsPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_TX_STATS_PERIOD_DEFAULT, + CFG_TDLS_TX_STATS_PERIOD_MIN, + CFG_TDLS_TX_STATS_PERIOD_MAX ), + + REG_VARIABLE( CFG_TDLS_TX_PACKET_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, fTDLSTxPacketThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_TX_PACKET_THRESHOLD_DEFAULT, + CFG_TDLS_TX_PACKET_THRESHOLD_MIN, + CFG_TDLS_TX_PACKET_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_TDLS_DISCOVERY_PERIOD, WLAN_PARAM_Integer, + hdd_config_t, fTDLSDiscoveryPeriod, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_DISCOVERY_PERIOD_DEFAULT, + CFG_TDLS_DISCOVERY_PERIOD_MIN, + CFG_TDLS_DISCOVERY_PERIOD_MAX ), + + REG_VARIABLE( CFG_TDLS_MAX_DISCOVERY_ATTEMPT, WLAN_PARAM_Integer, + hdd_config_t, fTDLSMaxDiscoveryAttempt, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_DEFAULT, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX ), + + REG_VARIABLE( CFG_TDLS_IDLE_TIMEOUT, WLAN_PARAM_Integer, + hdd_config_t, fTDLSIdleTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_IDLE_TIMEOUT_DEFAULT, + CFG_TDLS_IDLE_TIMEOUT_MIN, + CFG_TDLS_IDLE_TIMEOUT_MAX ), + + REG_VARIABLE( CFG_TDLS_IDLE_PACKET_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, fTDLSIdlePacketThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_IDLE_PACKET_THRESHOLD_DEFAULT, + CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, + CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_TDLS_RSSI_HYSTERESIS, WLAN_PARAM_Integer, + hdd_config_t, fTDLSRSSIHysteresis, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_RSSI_HYSTERESIS_DEFAULT, + CFG_TDLS_RSSI_HYSTERESIS_MIN, + CFG_TDLS_RSSI_HYSTERESIS_MAX ), + + REG_VARIABLE( CFG_TDLS_RSSI_TRIGGER_THRESHOLD, WLAN_PARAM_SignedInteger, + hdd_config_t, fTDLSRSSITriggerThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_DEFAULT, + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_TDLS_RSSI_TEARDOWN_THRESHOLD, WLAN_PARAM_SignedInteger, + hdd_config_t, fTDLSRSSITeardownThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_DEFAULT, + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_TDLS_RSSI_DELTA, WLAN_PARAM_SignedInteger, + hdd_config_t, fTDLSRSSIDelta, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_RSSI_DELTA_DEFAULT, + CFG_TDLS_RSSI_DELTA_MIN, + CFG_TDLS_RSSI_DELTA_MAX ), + + REG_VARIABLE( CFG_TDLS_QOS_WMM_UAPSD_MASK_NAME , WLAN_PARAM_HexInteger, + hdd_config_t, fTDLSUapsdMask, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_QOS_WMM_UAPSD_MASK_DEFAULT, + CFG_TDLS_QOS_WMM_UAPSD_MASK_MIN, + CFG_TDLS_QOS_WMM_UAPSD_MASK_MAX ), + + REG_VARIABLE( CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, fEnableTDLSBufferSta, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE_DEFAULT, + CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE_MIN, + CFG_TDLS_BUFFER_STA_SUPPORT_ENABLE_MAX ), + + REG_VARIABLE( CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, fEnableTDLSOffChannel, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE_DEFAULT, + CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE_MIN, + CFG_TDLS_OFF_CHANNEL_SUPPORT_ENABLE_MAX ), + + REG_VARIABLE( CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM, WLAN_PARAM_Integer, + hdd_config_t, fTDLSPrefOffChanNum, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT, + CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN, + CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX ), + + REG_VARIABLE( CFG_TDLS_PREFERRED_OFF_CHANNEL_BW, WLAN_PARAM_Integer, + hdd_config_t, fTDLSPrefOffChanBandwidth, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PREFERRED_OFF_CHANNEL_BW_DEFAULT, + CFG_TDLS_PREFERRED_OFF_CHANNEL_BW_MIN, + CFG_TDLS_PREFERRED_OFF_CHANNEL_BW_MAX ), + + REG_VARIABLE( CFG_TDLS_PUAPSD_INACTIVITY_TIME, WLAN_PARAM_Integer, + hdd_config_t, fTDLSPuapsdInactivityTimer, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PUAPSD_INACTIVITY_TIME_DEFAULT, + CFG_TDLS_PUAPSD_INACTIVITY_TIME_MIN, + CFG_TDLS_PUAPSD_INACTIVITY_TIME_MAX ), + + REG_VARIABLE( CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, fTDLSRxFrameThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_DEFAULT, + CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_MIN, + CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW, WLAN_PARAM_Integer, + hdd_config_t, fTDLSPuapsdPTIWindow, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW_DEFAULT, + CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW_MIN, + CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW_MAX ), + + REG_VARIABLE( CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT, WLAN_PARAM_Integer, + hdd_config_t, fTDLSPuapsdPTRTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT_DEFAULT, + CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT_MIN, + CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT_MAX ), + + REG_VARIABLE( CFG_TDLS_EXTERNAL_CONTROL, WLAN_PARAM_Integer, + hdd_config_t, fTDLSExternalControl, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_EXTERNAL_CONTROL_DEFAULT, + CFG_TDLS_EXTERNAL_CONTROL_MIN, + CFG_TDLS_EXTERNAL_CONTROL_MAX ), + + REG_VARIABLE( CFG_TDLS_WMM_MODE_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, fEnableTDLSWmmMode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_WMM_MODE_ENABLE_DEFAULT, + CFG_TDLS_WMM_MODE_ENABLE_MIN, + CFG_TDLS_WMM_MODE_ENABLE_MAX ), + + REG_VARIABLE( CFG_TDLS_SCAN_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, enable_tdls_scan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_SCAN_ENABLE_DEFAULT, + CFG_TDLS_SCAN_ENABLE_MIN, + CFG_TDLS_SCAN_ENABLE_MAX ), + + REG_VARIABLE( CFG_TDLS_PEER_KICKOUT_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, tdls_peer_kickout_threshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_PEER_KICKOUT_THRESHOLD_DEFAULT, + CFG_TDLS_PEER_KICKOUT_THRESHOLD_MIN, + CFG_TDLS_PEER_KICKOUT_THRESHOLD_MAX ), + +#endif + +#ifdef WLAN_SOFTAP_VSTA_FEATURE + REG_VARIABLE( CFG_VSTA_SUPPORT_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, fEnableVSTASupport, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VSTA_SUPPORT_ENABLE_DEFAULT, + CFG_VSTA_SUPPORT_ENABLE_MIN, + CFG_VSTA_SUPPORT_ENABLE_MAX ), +#endif + REG_VARIABLE( CFG_ENABLE_LPWR_IMG_TRANSITION_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableLpwrImgTransition, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LPWR_IMG_TRANSITION_DEFAULT, + CFG_ENABLE_LPWR_IMG_TRANSITION_MIN, + CFG_ENABLE_LPWR_IMG_TRANSITION_MAX ), + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + REG_VARIABLE( CFG_ACTIVEMODE_OFFLOAD_ENABLE, WLAN_PARAM_Integer, + hdd_config_t, fEnableActiveModeOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVEMODE_OFFLOAD_ENABLE_DEFAULT, + CFG_ACTIVEMODE_OFFLOAD_ENABLE_MIN, + CFG_ACTIVEMODE_OFFLOAD_ENABLE_MAX ), +#endif + REG_VARIABLE( CFG_ENABLE_LPWR_IMG_TRANSITION_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableLpwrImgTransition, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LPWR_IMG_TRANSITION_DEFAULT, + CFG_ENABLE_LPWR_IMG_TRANSITION_MIN, + CFG_ENABLE_LPWR_IMG_TRANSITION_MAX ), + + + REG_VARIABLE( CFG_SCAN_AGING_PARAM_NAME, WLAN_PARAM_Integer, + hdd_config_t, scanAgingTimeout, + VAR_FLAGS_OPTIONAL, + CFG_SCAN_AGING_PARAM_DEFAULT, + CFG_SCAN_AGING_PARAM_MIN, + CFG_SCAN_AGING_PARAM_MAX ), + + REG_VARIABLE( CFG_TX_LDPC_ENABLE_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableTxLdpc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TX_LDPC_ENABLE_FEATURE_DEFAULT, + CFG_TX_LDPC_ENABLE_FEATURE_MIN, + CFG_TX_LDPC_ENABLE_FEATURE_MAX ), + + REG_VARIABLE( CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableMCCAdaptiveScheduler, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_DEFAULT, + CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MIN, + CFG_ENABLE_MCC_ADATIVE_SCHEDULER_ENABLED_MAX ), + + REG_VARIABLE( CFG_ANDRIOD_POWER_SAVE_NAME, WLAN_PARAM_Integer, + hdd_config_t, isAndroidPsEn, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ANDRIOD_POWER_SAVE_DEFAULT, + CFG_ANDRIOD_POWER_SAVE_MIN, + CFG_ANDRIOD_POWER_SAVE_MAX), + + REG_VARIABLE( CFG_IBSS_ADHOC_CHANNEL_5GHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, AdHocChannel5G, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_ADHOC_CHANNEL_5GHZ_DEFAULT, + CFG_IBSS_ADHOC_CHANNEL_5GHZ_MIN, + CFG_IBSS_ADHOC_CHANNEL_5GHZ_MAX), + + REG_VARIABLE( CFG_IBSS_ADHOC_CHANNEL_24GHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, AdHocChannel24G, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_ADHOC_CHANNEL_24GHZ_DEFAULT, + CFG_IBSS_ADHOC_CHANNEL_24GHZ_MIN, + CFG_IBSS_ADHOC_CHANNEL_24GHZ_MAX), + +#ifdef WLAN_FEATURE_11AC + REG_VARIABLE( CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableTxBF, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_DEFAULT, + CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_MIN, + CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_MAX ), + + REG_VARIABLE( CFG_VHT_ENABLE_TXBF_IN_20MHZ, WLAN_PARAM_Integer, + hdd_config_t, enableTxBFin20MHz, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_TXBF_IN_20MHZ_DEFAULT, + CFG_VHT_ENABLE_TXBF_IN_20MHZ_MIN, + CFG_VHT_ENABLE_TXBF_IN_20MHZ_MAX ), + + REG_VARIABLE( CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, WLAN_PARAM_Integer, + hdd_config_t, txBFCsnValue, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_DEFAULT, + CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_MIN, + CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_MAX ), +#endif + + REG_VARIABLE( CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_NAME, WLAN_PARAM_Integer, + hdd_config_t, sapAllowAllChannel, + VAR_FLAGS_OPTIONAL, + CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_DEFAULT, + CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_MIN, + CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_MAX ), + +#ifdef WLAN_FEATURE_11AC + REG_VARIABLE( CFG_DISABLE_LDPC_WITH_TXBF_AP, WLAN_PARAM_Integer, + hdd_config_t, disableLDPCWithTxbfAP, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_LDPC_WITH_TXBF_AP_DEFAULT, + CFG_DISABLE_LDPC_WITH_TXBF_AP_MIN, + CFG_DISABLE_LDPC_WITH_TXBF_AP_MAX ), +#endif + + REG_VARIABLE_STRING( CFG_LIST_OF_NON_DFS_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, listOfNonDfsCountryCode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + (void *)CFG_LIST_OF_NON_DFS_COUNTRY_CODE_DEFAULT), + + REG_DYNAMIC_VARIABLE( CFG_ENABLE_SSR, WLAN_PARAM_Integer, + hdd_config_t, enableSSR, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SSR_DEFAULT, + CFG_ENABLE_SSR_MIN, + CFG_ENABLE_SSR_MAX, + cbNotifySetEnableSSR, 0 ), + + REG_VARIABLE( CFG_MAX_MEDIUM_TIME, WLAN_PARAM_Integer, + hdd_config_t, cfgMaxMediumTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_MEDIUM_TIME_STADEFAULT, + CFG_MAX_MEDIUM_TIME_STAMIN, + CFG_MAX_MEDIUM_TIME_STAMAX ), + +#ifdef WLAN_FEATURE_11AC + REG_VARIABLE( CFG_ENABLE_VHT_FOR_24GHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableVhtFor24GHzBand, + VAR_FLAGS_OPTIONAL, + CFG_ENABLE_VHT_FOR_24GHZ_DEFAULT, + CFG_ENABLE_VHT_FOR_24GHZ_MIN, + CFG_ENABLE_VHT_FOR_24GHZ_MAX), +#endif + + REG_VARIABLE( CFG_SCAN_OFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fScanOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SCAN_OFFLOAD_DEFAULT, + CFG_SCAN_OFFLOAD_DISABLE, + CFG_SCAN_OFFLOAD_ENABLE ), + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + REG_DYNAMIC_VARIABLE( CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY, WLAN_PARAM_Integer, + hdd_config_t, bFastRoamInConIniFeatureEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY_DEFAULT, + CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY_MIN, + CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY_MAX, + cbNotifySetEnableFastRoamInConcurrency, 0 ), +#endif + + REG_VARIABLE( CFG_ENABLE_ADAPT_RX_DRAIN_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableAdaptRxDrain, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_ENABLE_ADAPT_RX_DRAIN_DEFAULT, + CFG_ENABLE_ADAPT_RX_DRAIN_MIN, + CFG_ENABLE_ADAPT_RX_DRAIN_MAX), + + REG_VARIABLE( CFG_FLEX_CONNECT_POWER_FACTOR_NAME, WLAN_PARAM_Integer, + hdd_config_t, flexConnectPowerFactor, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_MINMAX, + CFG_FLEX_CONNECT_POWER_FACTOR_DEFAULT, + CFG_FLEX_CONNECT_POWER_FACTOR_MIN, + CFG_FLEX_CONNECT_POWER_FACTOR_MAX ), + + REG_VARIABLE( CFG_ENABLE_HEART_BEAT_OFFLOAD, WLAN_PARAM_Integer, + hdd_config_t, enableIbssHeartBeatOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HEART_BEAT_OFFLOAD_DEFAULT, + CFG_ENABLE_HEART_BEAT_OFFLOAD_MIN, + CFG_ENABLE_HEART_BEAT_OFFLOAD_MAX), + + REG_VARIABLE( CFG_ANTENNA_DIVERSITY_PARAM_NAME, WLAN_PARAM_Integer, + hdd_config_t, antennaDiversity, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ANTENNA_DIVERSITY_PARAM_DEFAULT, + CFG_ANTENNA_DIVERSITY_PARAM_MIN, + CFG_ANTENNA_DIVERSITY_PARAM_MAX), + + REG_VARIABLE( CFG_ENABLE_SNR_MONITORING_NAME, WLAN_PARAM_Integer, + hdd_config_t, fEnableSNRMonitoring, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_ENABLE_SNR_MONITORING_DEFAULT, + CFG_ENABLE_SNR_MONITORING_MIN, + CFG_ENABLE_SNR_MONITORING_MAX), + +#ifdef FEATURE_WLAN_SCAN_PNO + REG_VARIABLE( CFG_PNO_SCAN_SUPPORT, WLAN_PARAM_Integer, + hdd_config_t, configPNOScanSupport, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PNO_SCAN_SUPPORT_DEFAULT, + CFG_PNO_SCAN_SUPPORT_DISABLE, + CFG_PNO_SCAN_SUPPORT_ENABLE), + + REG_VARIABLE( CFG_PNO_SCAN_TIMER_REPEAT_VALUE, WLAN_PARAM_Integer, + hdd_config_t, configPNOScanTimerRepeatValue, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PNO_SCAN_TIMER_REPEAT_VALUE_DEFAULT, + CFG_PNO_SCAN_TIMER_REPEAT_VALUE_MIN, + CFG_PNO_SCAN_TIMER_REPEAT_VALUE_MAX), + + REG_VARIABLE( CFG_PNO_SLOW_SCAN_MULTIPLIER, WLAN_PARAM_Integer, + hdd_config_t, pno_slow_scan_multiplier, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PNO_SLOW_SCAN_MULTIPLIER_DEFAULT, + CFG_PNO_SLOW_SCAN_MULTIPLIER_MIN, + CFG_PNO_SLOW_SCAN_MULTIPLIER_MAX), +#endif + REG_VARIABLE(CFG_MAX_AMSDU_NUM_NAME , WLAN_PARAM_Integer, + hdd_config_t, max_amsdu_num, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_AMSDU_NUM_DEFAULT, + CFG_MAX_AMSDU_NUM_MIN, + CFG_MAX_AMSDU_NUM_MAX), + + REG_VARIABLE( CFG_STRICT_5GHZ_PREF_BY_MARGIN , WLAN_PARAM_Integer, + hdd_config_t, nSelect5GHzMargin, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_STRICT_5GHZ_PREF_BY_MARGIN_DEFAULT, + CFG_STRICT_5GHZ_PREF_BY_MARGIN_MIN, + CFG_STRICT_5GHZ_PREF_BY_MARGIN_MAX ), + + REG_VARIABLE( CFG_ENABLE_TCP_CHKSUM_OFFLOAD, WLAN_PARAM_Integer, + hdd_config_t, enableTCPChkSumOffld, + VAR_FLAGS_OPTIONAL, + CFG_ENABLE_TCP_CHKSUM_OFFLOAD_DEFAULT, + CFG_ENABLE_TCP_CHKSUM_OFFLOAD_MIN, + CFG_ENABLE_TCP_CHKSUM_OFFLOAD_MAX), + + REG_VARIABLE( CFG_ENABLE_IP_CHKSUM_OFFLOAD, WLAN_PARAM_Integer, + hdd_config_t, enableIPChecksumOffload, + VAR_FLAGS_OPTIONAL, + CFG_ENABLE_IP_CHKSUM_OFFLOAD_DEFAULT, + CFG_ENABLE_IP_CHKSUM_OFFLOAD_DISABLE, + CFG_ENABLE_IP_CHKSUM_OFFLOAD_ENABLE ), + + REG_VARIABLE( CFG_POWERSAVE_OFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, enablePowersaveOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_POWERSAVE_OFFLOAD_DEFAULT, + CFG_POWERSAVE_OFFLOAD_MIN, + CFG_POWERSAVE_OFFLOAD_MAX ), + + REG_VARIABLE( CFG_ENABLE_FW_UART_PRINT_NAME, WLAN_PARAM_Integer, + hdd_config_t, enablefwprint, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_UART_PRINT_DEFAULT, + CFG_ENABLE_FW_UART_PRINT_DISABLE, + CFG_ENABLE_FW_UART_PRINT_ENABLE), + + REG_VARIABLE( CFG_ENABLE_FW_LOG_NAME, WLAN_PARAM_Integer, + hdd_config_t, enablefwlog, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_LOG_DEFAULT, + CFG_ENABLE_FW_LOG_DISABLE, + CFG_ENABLE_FW_LOG_ENABLE), + + REG_VARIABLE( CFG_ENABLE_FW_SELF_RECOVERY_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableFwSelfRecovery, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_SELF_RECOVERY_DEFAULT, + CFG_ENABLE_FW_SELF_RECOVERY_DISABLE, + CFG_ENABLE_FW_SELF_RECOVERY_ENABLE), + +#ifdef IPA_OFFLOAD + REG_VARIABLE( CFG_IPA_OFFLOAD_CONFIG_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, IpaConfig, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IPA_OFFLOAD_CONFIG_DEFAULT, + CFG_IPA_OFFLOAD_CONFIG_MIN, + CFG_IPA_OFFLOAD_CONFIG_MAX), + + REG_VARIABLE( CFG_IPA_DESC_SIZE_NAME, WLAN_PARAM_Integer, + hdd_config_t, IpaDescSize, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IPA_DESC_SIZE_DEFAULT, + CFG_IPA_DESC_SIZE_MIN, + CFG_IPA_DESC_SIZE_MAX ), + + REG_VARIABLE( CFG_IPA_HIGH_BANDWIDTH_MBPS, WLAN_PARAM_Integer, + hdd_config_t, IpaHighBandwidthMbps, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IPA_HIGH_BANDWIDTH_MBPS_DEFAULT, + CFG_IPA_HIGH_BANDWIDTH_MBPS_MIN, + CFG_IPA_HIGH_BANDWIDTH_MBPS_MAX), + + REG_VARIABLE( CFG_IPA_MEDIUM_BANDWIDTH_MBPS, WLAN_PARAM_Integer, + hdd_config_t, IpaMediumBandwidthMbps, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IPA_MEDIUM_BANDWIDTH_MBPS_DEFAULT, + CFG_IPA_MEDIUM_BANDWIDTH_MBPS_MIN, + CFG_IPA_MEDIUM_BANDWIDTH_MBPS_MAX), + + REG_VARIABLE( CFG_IPA_LOW_BANDWIDTH_MBPS, WLAN_PARAM_Integer, + hdd_config_t, IpaLowBandwidthMbps, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IPA_LOW_BANDWIDTH_MBPS_DEFAULT, + CFG_IPA_LOW_BANDWIDTH_MBPS_MIN, + CFG_IPA_LOW_BANDWIDTH_MBPS_MAX), +#endif + REG_VARIABLE( CFG_P2P_LISTEN_OFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fP2pListenOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_P2P_LISTEN_OFFLOAD_DEFAULT, + CFG_P2P_LISTEN_OFFLOAD_DISABLE, + CFG_P2P_LISTEN_OFFLOAD_ENABLE ), + +#ifdef WLAN_FEATURE_11AC + REG_VARIABLE( CFG_VHT_AMPDU_LEN_EXPONENT_NAME, WLAN_PARAM_Integer, + hdd_config_t, fVhtAmpduLenExponent, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_VHT_AMPDU_LEN_EXPONENT_DEFAULT, + CFG_VHT_AMPDU_LEN_EXPONENT_MIN, + CFG_VHT_AMPDU_LEN_EXPONENT_MAX), + + REG_VARIABLE( CFG_VHT_MPDU_LEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, vhtMpduLen, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_VHT_MPDU_LEN_DEFAULT, + CFG_VHT_MPDU_LEN_MIN, + CFG_VHT_MPDU_LEN_MAX), +#endif + + REG_VARIABLE( CFG_MAX_WOW_FILTERS_NAME, WLAN_PARAM_Integer, + hdd_config_t, maxWoWFilters, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , + CFG_MAX_WOW_FILTERS_DEFAULT, + CFG_MAX_WOW_FILTERS_MIN, + CFG_MAX_WOW_FILTERS_MAX), + + REG_VARIABLE( CFG_WOW_STATUS_NAME, WLAN_PARAM_Integer, + hdd_config_t, wowEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_WOW_STATUS_DEFAULT, + CFG_WOW_ENABLE_MIN, + CFG_WOW_ENABLE_MAX), + + REG_VARIABLE( CFG_COALESING_IN_IBSS_NAME , WLAN_PARAM_Integer, + hdd_config_t, isCoalesingInIBSSAllowed, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_COALESING_IN_IBSS_DEFAULT, + CFG_COALESING_IN_IBSS_MIN, + CFG_COALESING_IN_IBSS_MAX ), + + REG_VARIABLE( CFG_IBSS_ATIM_WIN_SIZE_NAME , WLAN_PARAM_Integer, + hdd_config_t, ibssATIMWinSize, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_ATIM_WIN_SIZE_DEFAULT, + CFG_IBSS_ATIM_WIN_SIZE_MIN, + CFG_IBSS_ATIM_WIN_SIZE_MAX ), + + REG_VARIABLE( CFG_SAP_MAX_NO_PEERS, WLAN_PARAM_Integer, + hdd_config_t, maxNumberOfPeers, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_MAX_NO_PEERS_DEFAULT, + CFG_SAP_MAX_NO_PEERS_MIN, + CFG_SAP_MAX_NO_PEERS_MAX), + + REG_VARIABLE( CFG_IBSS_IS_POWER_SAVE_ALLOWED_NAME , WLAN_PARAM_Integer, + hdd_config_t, isIbssPowerSaveAllowed, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_IS_POWER_SAVE_ALLOWED_DEFAULT, + CFG_IBSS_IS_POWER_SAVE_ALLOWED_MIN, + CFG_IBSS_IS_POWER_SAVE_ALLOWED_MAX ), + + REG_VARIABLE( CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_NAME , WLAN_PARAM_Integer, + hdd_config_t, isIbssPowerCollapseAllowed, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_DEFAULT, + CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_MIN, + CFG_IBSS_IS_POWER_COLLAPSE_ALLOWED_MAX ), + + REG_VARIABLE( CFG_IBSS_AWAKE_ON_TX_RX_NAME , WLAN_PARAM_Integer, + hdd_config_t, isIbssAwakeOnTxRx, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_AWAKE_ON_TX_RX_DEFAULT, + CFG_IBSS_AWAKE_ON_TX_RX_MIN, + CFG_IBSS_AWAKE_ON_TX_RX_MAX ), + + REG_VARIABLE( CFG_IBSS_INACTIVITY_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, ibssInactivityCount, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_INACTIVITY_TIME_DEFAULT, + CFG_IBSS_INACTIVITY_TIME_MIN, + CFG_IBSS_INACTIVITY_TIME_MAX ), + + REG_VARIABLE( CFG_IBSS_TXSP_END_INACTIVITY_NAME, WLAN_PARAM_Integer, + hdd_config_t, ibssTxSpEndInactivityTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_TXSP_END_INACTIVITY_DEFAULT, + CFG_IBSS_TXSP_END_INACTIVITY_MIN, + CFG_IBSS_TXSP_END_INACTIVITY_MAX ), + + REG_VARIABLE( CFG_IBSS_PS_WARMUP_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, ibssPsWarmupTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_PS_WARMUP_TIME_DEFAULT, + CFG_IBSS_PS_WARMUP_TIME_MIN, + CFG_IBSS_PS_WARMUP_TIME_MAX ), + + REG_VARIABLE( CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_NAME, WLAN_PARAM_Integer, + hdd_config_t, ibssPs1RxChainInAtimEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_DEFAULT, + CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_MIN, + CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_MAX ), + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_ENABLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_txctl_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_ENABLE_DEFAULT, + CFG_BAD_PEER_TX_CTL_ENABLE_MIN, + CFG_BAD_PEER_TX_CTL_ENABLE_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_PERIOD_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_txctl_prd, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_PERIOD_DEFAULT, + CFG_BAD_PEER_TX_CTL_PERIOD_MIN, + CFG_BAD_PEER_TX_CTL_PERIOD_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_txctl_txq_lmt, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_DEFAULT, + CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_MIN, + CFG_BAD_PEER_TX_CTL_TXQ_LIMIT_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_tgt_backoff, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_DEFAULT, + CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_MIN, + CFG_BAD_PEER_TX_CTL_TGT_BACKOFF_T_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_tgt_report_prd, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_DEFAULT, + CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_MIN, + CFG_BAD_PEER_TX_CTL_TGT_REPORT_PRD_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_cond_ieee80211b, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_MIN, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEB_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_delta_ieee80211b, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_MIN, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEB_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_pct_ieee80211b, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_MIN, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_MAX, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEB_DEFAULT ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_tput_ieee80211b, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_MIN, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEB_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_limit_ieee80211b, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_MIN, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEB_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_cond_ieee80211ag, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_MIN, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAG_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_delta_ieee80211ag, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_MIN, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAG_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_pct_ieee80211ag, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_MIN, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAG_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_tput_ieee80211ag, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_MIN, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAG_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_limit_ieee80211ag, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_MIN, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAG_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_cond_ieee80211n, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_MIN, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEN_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_delta_ieee80211n, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_MIN, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEN_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_pct_ieee80211n, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_MIN, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEN_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_tput_ieee80211n, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_MIN, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEN_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_limit_ieee80211n, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_MIN, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEN_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_cond_ieee80211ac, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_DEFAULT, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_MIN, + CFG_BAD_PEER_TX_CTL_COND_LEVEL_IEEEAC_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_delta_ieee80211ac, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_DEFAULT, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_MIN, + CFG_BAD_PEER_TX_CTL_DELTA_LEVEL_IEEEAC_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_pct_ieee80211ac, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_DEFAULT, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_MIN, + CFG_BAD_PEER_TX_CTL_PCT_LEVEL_IEEEAC_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_tput_ieee80211ac, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_DEFAULT, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_MIN, + CFG_BAD_PEER_TX_CTL_TPUT_LEVEL_IEEEAC_MAX ), + + REG_VARIABLE( CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_NAME, WLAN_PARAM_Integer, + hdd_config_t, bad_peer_limit_ieee80211ac, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_DEFAULT, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_MIN, + CFG_BAD_PEER_TX_CTL_TX_LIMIT_LEVEL_IEEEAC_MAX ), +#endif + REG_VARIABLE( CFG_THERMAL_TEMP_MIN_LEVEL0_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMinLevel0, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL0_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL0_MIN, + CFG_THERMAL_TEMP_MIN_LEVEL0_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MAX_LEVEL0_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMaxLevel0, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL0_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL0_MIN, + CFG_THERMAL_TEMP_MAX_LEVEL0_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MIN_LEVEL1_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMinLevel1, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL1_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL1_MIN, + CFG_THERMAL_TEMP_MIN_LEVEL1_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MAX_LEVEL1_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMaxLevel1, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL1_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL1_MIN, + CFG_THERMAL_TEMP_MAX_LEVEL1_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MIN_LEVEL2_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMinLevel2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL2_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL2_MIN, + CFG_THERMAL_TEMP_MIN_LEVEL2_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MAX_LEVEL2_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMaxLevel2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL2_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL2_MIN, + CFG_THERMAL_TEMP_MAX_LEVEL2_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MIN_LEVEL3_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMinLevel3, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL3_DEFAULT, + CFG_THERMAL_TEMP_MIN_LEVEL3_MIN, + CFG_THERMAL_TEMP_MIN_LEVEL3_MAX ), + + REG_VARIABLE( CFG_THERMAL_TEMP_MAX_LEVEL3_NAME, WLAN_PARAM_Integer, + hdd_config_t, thermalTempMaxLevel3, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL3_DEFAULT, + CFG_THERMAL_TEMP_MAX_LEVEL3_MIN, + CFG_THERMAL_TEMP_MAX_LEVEL3_MAX ), + + REG_VARIABLE( CFG_SET_TXPOWER_LIMIT2G_NAME , WLAN_PARAM_Integer, + hdd_config_t, TxPower2g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SET_TXPOWER_LIMIT2G_DEFAULT, + CFG_SET_TXPOWER_LIMIT2G_MIN, + CFG_SET_TXPOWER_LIMIT2G_MAX ), + + REG_VARIABLE( CFG_SET_TXPOWER_LIMIT5G_NAME , WLAN_PARAM_Integer, + hdd_config_t, TxPower5g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SET_TXPOWER_LIMIT5G_DEFAULT, + CFG_SET_TXPOWER_LIMIT5G_MIN, + CFG_SET_TXPOWER_LIMIT5G_MAX ), + + REG_VARIABLE( CFG_ENABLE_DEBUG_CONNECT_ISSUE, WLAN_PARAM_Integer, + hdd_config_t, gEnableDebugLog, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DEBUG_CONNECT_ISSUE_DEFAULT, + CFG_ENABLE_DEBUG_CONNECT_ISSUE_MIN , + CFG_ENABLE_DEBUG_CONNECT_ISSUE_MAX), + + REG_VARIABLE( CFG_RX_HANDLE, WLAN_PARAM_Integer, + hdd_config_t, rxhandle, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RX_HANDLE_DEFAULT, + CFG_RX_HANDLE_MIN, + CFG_RX_HANDLE_MAX), + + REG_VARIABLE_STRING( CFG_RPS_RX_QUEUE_CPU_MAP_LIST_NAME, WLAN_PARAM_String, + hdd_config_t, cpu_map_list, + VAR_FLAGS_OPTIONAL, + (void *)CFG_RPS_RX_QUEUE_CPU_MAP_LIST_DEFAULT ), + + REG_VARIABLE( CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fDfsPhyerrFilterOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_DEFAULT, + CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MIN, + CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MAX ), + + REG_VARIABLE( CFG_ENABLE_OVERLAP_CH, WLAN_PARAM_Integer, + hdd_config_t, gEnableOverLapCh, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENABLE_OVERLAP_CH_DEFAULT, + CFG_ENABLE_OVERLAP_CH_MIN, + CFG_ENABLE_OVERLAP_CH_MAX ), + + REG_VARIABLE( CFG_REG_CHANGE_DEF_COUNTRY_NAME, WLAN_PARAM_Integer, + hdd_config_t, fRegChangeDefCountry, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_REG_CHANGE_DEF_COUNTRY_DEFAULT, + CFG_REG_CHANGE_DEF_COUNTRY_MIN, + CFG_REG_CHANGE_DEF_COUNTRY_MAX), + + REG_VARIABLE( CFG_SAP_SCAN_BAND_PREFERENCE, WLAN_PARAM_Integer, + hdd_config_t, acsScanBandPreference, +#ifndef WLAN_FEATURE_MBSSID + VAR_FLAGS_DYNAMIC_CFG | +#endif + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SAP_SCAN_BAND_PREFERENCE_DEFAULT, + CFG_SAP_SCAN_BAND_PREFERENCE_MIN, + CFG_SAP_SCAN_BAND_PREFERENCE_MAX ), + +#ifdef QCA_LL_TX_FLOW_CT + REG_VARIABLE( CFG_LL_TX_FLOW_LWM, WLAN_PARAM_Integer, + hdd_config_t, TxFlowLowWaterMark, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_FLOW_LWM_DEFAULT, + CFG_LL_TX_FLOW_LWM_MIN, + CFG_LL_TX_FLOW_LWM_MAX ), + + REG_VARIABLE( CFG_LL_TX_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, + hdd_config_t, TxFlowHighWaterMarkOffset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_FLOW_HWM_OFFSET_DEFAULT, + CFG_LL_TX_FLOW_HWM_OFFSET_MIN, + CFG_LL_TX_FLOW_HWM_OFFSET_MAX ), + + REG_VARIABLE( CFG_LL_TX_FLOW_MAX_Q_DEPTH, WLAN_PARAM_Integer, + hdd_config_t, TxFlowMaxQueueDepth, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_FLOW_MAX_Q_DEPTH_DEFAULT, + CFG_LL_TX_FLOW_MAX_Q_DEPTH_MIN, + CFG_LL_TX_FLOW_MAX_Q_DEPTH_MAX ), + + REG_VARIABLE( CFG_LL_TX_LBW_FLOW_LWM, WLAN_PARAM_Integer, + hdd_config_t, TxLbwFlowLowWaterMark, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_LBW_FLOW_LWM_DEFAULT, + CFG_LL_TX_LBW_FLOW_LWM_MIN, + CFG_LL_TX_LBW_FLOW_LWM_MAX ), + + REG_VARIABLE( CFG_LL_TX_LBW_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, + hdd_config_t, TxLbwFlowHighWaterMarkOffset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_LBW_FLOW_HWM_OFFSET_DEFAULT, + CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MIN, + CFG_LL_TX_LBW_FLOW_HWM_OFFSET_MAX ), + + REG_VARIABLE( CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH, WLAN_PARAM_Integer, + hdd_config_t, TxLbwFlowMaxQueueDepth, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_DEFAULT, + CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MIN, + CFG_LL_TX_LBW_FLOW_MAX_Q_DEPTH_MAX ), + + REG_VARIABLE( CFG_LL_TX_HBW_FLOW_LWM, WLAN_PARAM_Integer, + hdd_config_t, TxHbwFlowLowWaterMark, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_HBW_FLOW_LWM_DEFAULT, + CFG_LL_TX_HBW_FLOW_LWM_MIN, + CFG_LL_TX_HBW_FLOW_LWM_MAX ), + + REG_VARIABLE( CFG_LL_TX_HBW_FLOW_HWM_OFFSET, WLAN_PARAM_Integer, + hdd_config_t, TxHbwFlowHighWaterMarkOffset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_HBW_FLOW_HWM_OFFSET_DEFAULT, + CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MIN, + CFG_LL_TX_HBW_FLOW_HWM_OFFSET_MAX ), + + REG_VARIABLE( CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH, WLAN_PARAM_Integer, + hdd_config_t, TxHbwFlowMaxQueueDepth, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_DEFAULT, + CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MIN, + CFG_LL_TX_HBW_FLOW_MAX_Q_DEPTH_MAX ), +#endif /* QCA_LL_TX_FLOW_CT */ + + REG_VARIABLE( CFG_INITIAL_DWELL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, nInitialDwellTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_INITIAL_DWELL_TIME_DEFAULT, + CFG_INITIAL_DWELL_TIME_MIN, + CFG_INITIAL_DWELL_TIME_MAX ), + + REG_VARIABLE( CFG_INITIAL_SCAN_NO_DFS_CHNL_NAME, WLAN_PARAM_Integer, + hdd_config_t, initial_scan_no_dfs_chnl, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_INITIAL_SCAN_NO_DFS_CHNL_DEFAULT, + CFG_INITIAL_SCAN_NO_DFS_CHNL_MIN, + CFG_INITIAL_SCAN_NO_DFS_CHNL_MAX ), + + REG_VARIABLE( CFG_ACS_BAND_SWITCH_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, acsBandSwitchThreshold, +#ifndef WLAN_FEATURE_MBSSID + VAR_FLAGS_DYNAMIC_CFG | +#endif + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ACS_BAND_SWITCH_THRESHOLD_DEFAULT, + CFG_ACS_BAND_SWITCH_THRESHOLD_MIN, + CFG_ACS_BAND_SWITCH_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_SAP_MAX_OFFLOAD_PEERS, WLAN_PARAM_Integer, + hdd_config_t, apMaxOffloadPeers, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SAP_MAX_OFFLOAD_PEERS_DEFAULT, + CFG_SAP_MAX_OFFLOAD_PEERS_MIN, + CFG_SAP_MAX_OFFLOAD_PEERS_MAX ), + + REG_VARIABLE( CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS, WLAN_PARAM_Integer, + hdd_config_t, apMaxOffloadReorderBuffs, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS_DEFAULT, + CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS_MIN, + CFG_SAP_MAX_OFFLOAD_REORDER_BUFFS_MAX ), + + REG_VARIABLE( CFG_ADVERTISE_CONCURRENT_OPERATION_NAME , WLAN_PARAM_Integer, + hdd_config_t, advertiseConcurrentOperation, + VAR_FLAGS_OPTIONAL, + CFG_ADVERTISE_CONCURRENT_OPERATION_DEFAULT, + CFG_ADVERTISE_CONCURRENT_OPERATION_MIN, + CFG_ADVERTISE_CONCURRENT_OPERATION_MAX ), + + REG_VARIABLE( CFG_ENABLE_MEMORY_DEEP_SLEEP, WLAN_PARAM_Integer, + hdd_config_t, enableMemDeepSleep, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_MEMORY_DEEP_SLEEP_DEFAULT, + CFG_ENABLE_MEMORY_DEEP_SLEEP_MIN, + CFG_ENABLE_MEMORY_DEEP_SLEEP_MAX ), + + REG_VARIABLE( CFG_DEFAULT_RATE_INDEX_24GH, WLAN_PARAM_Integer, + hdd_config_t, defaultRateIndex24Ghz, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DEFAULT_RATE_INDEX_24GH_DEFAULT, + CFG_DEFAULT_RATE_INDEX_24GH_MIN, + CFG_DEFAULT_RATE_INDEX_24GH_MAX ), + + REG_VARIABLE_STRING( CFG_OVERRIDE_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, overrideCountryCode, + VAR_FLAGS_OPTIONAL, + (void *)CFG_OVERRIDE_COUNTRY_CODE_DEFAULT), + + REG_VARIABLE( CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_NAME, WLAN_PARAM_Integer, + hdd_config_t, debugP2pRemainOnChannel, + VAR_FLAGS_OPTIONAL, + CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_DEFAULT, + CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_MIN, + CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_MAX ), + + REG_VARIABLE( CFG_ENABLE_PACKET_LOG, WLAN_PARAM_Integer, + hdd_config_t, enablePacketLog, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_PACKET_LOG_DEFAULT, + CFG_ENABLE_PACKET_LOG_MIN, + CFG_ENABLE_PACKET_LOG_MAX ), + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + REG_VARIABLE( CFG_ROAMING_OFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, isRoamOffloadEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ROAMING_OFFLOAD_DEFAULT, + CFG_ROAMING_OFFLOAD_MIN, + CFG_ROAMING_OFFLOAD_MAX), +#endif +#ifdef MSM_PLATFORM + REG_VARIABLE( CFG_BUS_BANDWIDTH_HIGH_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, busBandwidthHighThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BUS_BANDWIDTH_HIGH_THRESHOLD_DEFAULT, + CFG_BUS_BANDWIDTH_HIGH_THRESHOLD_MIN, + CFG_BUS_BANDWIDTH_HIGH_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, busBandwidthMediumThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD_DEFAULT, + CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD_MIN, + CFG_BUS_BANDWIDTH_MEDIUM_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_BUS_BANDWIDTH_LOW_THRESHOLD, WLAN_PARAM_Integer, + hdd_config_t, busBandwidthLowThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BUS_BANDWIDTH_LOW_THRESHOLD_DEFAULT, + CFG_BUS_BANDWIDTH_LOW_THRESHOLD_MIN, + CFG_BUS_BANDWIDTH_LOW_THRESHOLD_MAX ), + + REG_VARIABLE( CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL, WLAN_PARAM_Integer, + hdd_config_t, busBandwidthComputeInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL_DEFAULT, + CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL_MIN, + CFG_BUS_BANDWIDTH_COMPUTE_INTERVAL_MAX), + + REG_VARIABLE( CFG_TCP_DELACK_THRESHOLD_HIGH, WLAN_PARAM_Integer, + hdd_config_t, tcpDelackThresholdHigh, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TCP_DELACK_THRESHOLD_HIGH_DEFAULT, + CFG_TCP_DELACK_THRESHOLD_HIGH_MIN, + CFG_TCP_DELACK_THRESHOLD_HIGH_MAX ), + + REG_VARIABLE( CFG_TCP_DELACK_THRESHOLD_LOW, WLAN_PARAM_Integer, + hdd_config_t, tcpDelackThresholdLow, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TCP_DELACK_THRESHOLD_LOW_DEFAULT, + CFG_TCP_DELACK_THRESHOLD_LOW_MIN, + CFG_TCP_DELACK_THRESHOLD_LOW_MAX ), + + REG_VARIABLE( CFG_TCP_TX_HIGH_TPUT_THRESHOLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, tcp_tx_high_tput_thres, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TCP_TX_HIGH_TPUT_THRESHOLD_DEFAULT, + CFG_TCP_TX_HIGH_TPUT_THRESHOLD_MIN, + CFG_TCP_TX_HIGH_TPUT_THRESHOLD_MAX ), + +#endif + + + REG_VARIABLE( CFG_ENABLE_FW_LOG_TYPE , WLAN_PARAM_Integer, + hdd_config_t, enableFwLogType, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_LOG_TYPE_DEFAULT, + CFG_ENABLE_FW_LOG_TYPE_MIN, + CFG_ENABLE_FW_LOG_TYPE_MAX ), + + REG_VARIABLE( CFG_ENABLE_FW_DEBUG_LOG_LEVEL, WLAN_PARAM_Integer, + hdd_config_t, enableFwLogLevel, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_DEBUG_LOG_LEVEL_DEFAULT, + CFG_ENABLE_FW_DEBUG_LOG_LEVEL_MIN, + CFG_ENABLE_FW_DEBUG_LOG_LEVEL_MAX ), + + REG_VARIABLE( CFG_ENABLE_FW_RTS_PROFILE, WLAN_PARAM_Integer, + hdd_config_t, rts_profile, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FW_RTS_PROFILE_DEFAULT, + CFG_ENABLE_FW_RTS_PROFILE_MIN, + CFG_ENABLE_FW_RTS_PROFILE_MAX ), + + REG_VARIABLE_STRING( CFG_ENABLE_FW_MODULE_LOG_LEVEL, WLAN_PARAM_String, + hdd_config_t, enableFwModuleLogLevel, + VAR_FLAGS_OPTIONAL, + (void *) CFG_ENABLE_FW_MODULE_LOG_DEFAULT), + + + +#ifdef WLAN_FEATURE_11W + REG_VARIABLE(CFG_PMF_SA_QUERY_MAX_RETRIES_NAME, WLAN_PARAM_Integer, + hdd_config_t, pmfSaQueryMaxRetries, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PMF_SA_QUERY_MAX_RETRIES_DEFAULT, + CFG_PMF_SA_QUERY_MAX_RETRIES_MIN, + CFG_PMF_SA_QUERY_MAX_RETRIES_MAX ), + + REG_VARIABLE(CFG_PMF_SA_QUERY_RETRY_INTERVAL_NAME, WLAN_PARAM_Integer, + hdd_config_t, pmfSaQueryRetryInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PMF_SA_QUERY_RETRY_INTERVAL_DEFAULT, + CFG_PMF_SA_QUERY_RETRY_INTERVAL_MIN, + CFG_PMF_SA_QUERY_RETRY_INTERVAL_MAX ), +#endif + REG_VARIABLE(CFG_MAX_CONCURRENT_CONNECTIONS_NAME, WLAN_PARAM_Integer, + hdd_config_t, gMaxConcurrentActiveSessions, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_CONCURRENT_CONNECTIONS_DEFAULT, + CFG_MAX_CONCURRENT_CONNECTIONS_MIN, + CFG_MAX_CONCURRENT_CONNECTIONS_MAX ), + +#ifdef FEATURE_GREEN_AP + REG_VARIABLE( CFG_ENABLE_GREEN_AP_FEATURE, WLAN_PARAM_Integer, + hdd_config_t, enableGreenAP, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_GREEN_AP_FEATURE_DEFAULT, + CFG_ENABLE_GREEN_AP_FEATURE_MIN, + CFG_ENABLE_GREEN_AP_FEATURE_MAX ), +#endif + + REG_VARIABLE(CFG_ENABLE_CRASH_INJECT, WLAN_PARAM_Integer, + hdd_config_t, crash_inject_enabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_CRASH_INJECT_DEFAULT, + CFG_ENABLE_CRASH_INJECT_MIN, + CFG_ENABLE_CRASH_INJECT_MAX), + + REG_VARIABLE(CFG_IGNORE_CAC_NAME, WLAN_PARAM_Integer, + hdd_config_t, ignoreCAC, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IGNORE_CAC_DEFAULT, + CFG_IGNORE_CAC_MIN, + CFG_IGNORE_CAC_MAX), + + REG_VARIABLE(CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_NAME, WLAN_PARAM_Integer, + hdd_config_t, IsSapDfsChSifsBurstEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_DEFAULT, + CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_MIN, + CFG_ENABLE_SAP_DFS_CH_SIFS_BURST_MAX ), + + REG_VARIABLE(CFG_DFS_RADAR_PRI_MULTIPLIER_NAME, WLAN_PARAM_Integer, + hdd_config_t, dfsRadarPriMultiplier, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DFS_RADAR_PRI_MULTIPLIER_DEFAULT, + CFG_DFS_RADAR_PRI_MULTIPLIER_MIN, + CFG_DFS_RADAR_PRI_MULTIPLIER_MAX), + + REG_VARIABLE( CFG_REORDER_OFFLOAD_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, reorderOffloadSupport, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_REORDER_OFFLOAD_SUPPORT_DEFAULT, + CFG_REORDER_OFFLOAD_SUPPORT_MIN, + CFG_REORDER_OFFLOAD_SUPPORT_MAX ), +#ifdef IPA_UC_OFFLOAD + REG_VARIABLE( CFG_IPA_UC_OFFLOAD_ENABLED_NAME, WLAN_PARAM_Integer, + hdd_config_t, IpaUcOffloadEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_IPA_UC_OFFLOAD_ENABLED_DEFAULT, + CFG_IPA_UC_OFFLOAD_ENABLED_MIN, + CFG_IPA_UC_OFFLOAD_ENABLED_MAX ), + + REG_VARIABLE( CFG_IPA_UC_TX_BUF_COUNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, IpaUcTxBufCount, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_IPA_UC_TX_BUF_COUNT_DEFAULT, + CFG_IPA_UC_TX_BUF_COUNT_MIN, + CFG_IPA_UC_TX_BUF_COUNT_MAX ), + + REG_VARIABLE( CFG_IPA_UC_TX_BUF_SIZE_NAME, WLAN_PARAM_Integer, + hdd_config_t, IpaUcTxBufSize, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_IPA_UC_TX_BUF_SIZE_DEFAULT, + CFG_IPA_UC_TX_BUF_SIZE_MIN, + CFG_IPA_UC_TX_BUF_SIZE_MAX ), + + REG_VARIABLE( CFG_IPA_UC_RX_IND_RING_COUNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, IpaUcRxIndRingCount, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_IPA_UC_RX_IND_RING_COUNT_DEFAULT, + CFG_IPA_UC_RX_IND_RING_COUNT_MIN, + CFG_IPA_UC_RX_IND_RING_COUNT_MAX ), + + REG_VARIABLE( CFG_IPA_UC_TX_PARTITION_BASE_NAME, WLAN_PARAM_Integer, + hdd_config_t, IpaUcTxPartitionBase, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_IPA_UC_TX_PARTITION_BASE_DEFAULT, + CFG_IPA_UC_TX_PARTITION_BASE_MIN, + CFG_IPA_UC_TX_PARTITION_BASE_MAX ), +#endif /* IPA_UC_OFFLOAD */ +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + REG_VARIABLE(CFG_WLAN_LOGGING_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, wlanLoggingEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_WLAN_LOGGING_SUPPORT_DEFAULT, + CFG_WLAN_LOGGING_SUPPORT_DISABLE, + CFG_WLAN_LOGGING_SUPPORT_ENABLE ), + + REG_VARIABLE(CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, wlanLoggingFEToConsole, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_DEFAULT, + CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_DISABLE, + CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_ENABLE ), + + REG_VARIABLE(CFG_WLAN_LOGGING_NUM_BUF_NAME, WLAN_PARAM_Integer, + hdd_config_t, wlanLoggingNumBuf, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_WLAN_LOGGING_NUM_BUF_DEFAULT, + CFG_WLAN_LOGGING_NUM_BUF_MIN, + CFG_WLAN_LOGGING_NUM_BUF_MAX ), +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ + + REG_VARIABLE( CFG_ENABLE_SIFS_BURST, WLAN_PARAM_Integer, + hdd_config_t, enableSifsBurst, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SIFS_BURST_DEFAULT, + CFG_ENABLE_SIFS_BURST_MIN, + CFG_ENABLE_SIFS_BURST_MAX ), + +#ifdef WLAN_FEATURE_LPSS + REG_VARIABLE(CFG_ENABLE_LPASS_SUPPORT, WLAN_PARAM_Integer, + hdd_config_t, enablelpasssupport, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LPASS_SUPPORT_DEFAULT, + CFG_ENABLE_LPASS_SUPPORT_MIN, + CFG_ENABLE_LPASS_SUPPORT_MAX), +#endif + +#ifdef WLAN_FEATURE_NAN + REG_VARIABLE(CFG_ENABLE_NAN_SUPPORT, WLAN_PARAM_Integer, + hdd_config_t, enable_nan_support, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_NAN_SUPPORT_DEFAULT, + CFG_ENABLE_NAN_SUPPORT_MIN, + CFG_ENABLE_NAN_SUPPORT_MAX), +#endif + + REG_VARIABLE( CFG_ENABLE_SELF_RECOVERY, WLAN_PARAM_Integer, + hdd_config_t, enableSelfRecovery, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SELF_RECOVERY_DEFAULT, + CFG_ENABLE_SELF_RECOVERY_MIN, + CFG_ENABLE_SELF_RECOVERY_MAX ), + +#ifdef FEATURE_WLAN_FORCE_SAP_SCC + REG_VARIABLE(CFG_SAP_SCC_CHAN_AVOIDANCE, WLAN_PARAM_Integer, + hdd_config_t, SapSccChanAvoidance, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_SCC_CHAN_AVOIDANCE_DEFAULT, + CFG_SAP_SCC_CHAN_AVOIDANCE_MIN, + CFG_SAP_SCC_CHAN_AVOIDANCE_MAX), +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + + REG_VARIABLE( CFG_ENABLE_SAP_SUSPEND, WLAN_PARAM_Integer, + hdd_config_t, enableSapSuspend, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SAP_SUSPEND_DEFAULT, + CFG_ENABLE_SAP_SUSPEND_MIN, + CFG_ENABLE_SAP_SUSPEND_MAX ), + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + REG_VARIABLE( CFG_EXTWOW_GO_TO_SUSPEND, WLAN_PARAM_Integer, + hdd_config_t, extWowGotoSuspend, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_GO_TO_SUSPEND_DEFAULT, + CFG_EXTWOW_GO_TO_SUSPEND_MIN, + CFG_EXTWOW_GO_TO_SUSPEND_MAX ), + + REG_VARIABLE( CFG_EXTWOW_APP1_WAKE_PIN_NUMBER, WLAN_PARAM_Integer, + hdd_config_t, extWowApp1WakeupPinNumber, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_DEFAULT, + CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_MIN, + CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_MAX ), + + REG_VARIABLE( CFG_EXTWOW_APP2_WAKE_PIN_NUMBER, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2WakeupPinNumber, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_DEFAULT, + CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_MIN, + CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_MAX ), + + REG_VARIABLE( CFG_EXTWOW_KA_INIT_PING_INTERVAL, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2KAInitPingInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_KA_INIT_PING_INTERVAL_DEFAULT, + CFG_EXTWOW_KA_INIT_PING_INTERVAL_MIN, + CFG_EXTWOW_KA_INIT_PING_INTERVAL_MAX ), + + REG_VARIABLE( CFG_EXTWOW_KA_MIN_PING_INTERVAL, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2KAMinPingInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_KA_MIN_PING_INTERVAL_DEFAULT, + CFG_EXTWOW_KA_MIN_PING_INTERVAL_MIN, + CFG_EXTWOW_KA_MIN_PING_INTERVAL_MAX ), + + REG_VARIABLE( CFG_EXTWOW_KA_MAX_PING_INTERVAL, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2KAMaxPingInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_KA_MAX_PING_INTERVAL_DEFAULT, + CFG_EXTWOW_KA_MAX_PING_INTERVAL_MIN, + CFG_EXTWOW_KA_MAX_PING_INTERVAL_MAX ), + + REG_VARIABLE( CFG_EXTWOW_KA_INC_PING_INTERVAL, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2KAIncPingInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_KA_INC_PING_INTERVAL_DEFAULT, + CFG_EXTWOW_KA_INC_PING_INTERVAL_MIN, + CFG_EXTWOW_KA_INC_PING_INTERVAL_MAX ), + + REG_VARIABLE( CFG_EXTWOW_TCP_SRC_PORT, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2TcpSrcPort, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_TCP_SRC_PORT_DEFAULT, + CFG_EXTWOW_TCP_SRC_PORT_MIN, + CFG_EXTWOW_TCP_SRC_PORT_MAX ), + + REG_VARIABLE( CFG_EXTWOW_TCP_DST_PORT, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2TcpDstPort, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_TCP_DST_PORT_DEFAULT, + CFG_EXTWOW_TCP_DST_PORT_MIN, + CFG_EXTWOW_TCP_DST_PORT_MAX ), + + REG_VARIABLE( CFG_EXTWOW_TCP_TX_TIMEOUT, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2TcpTxTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_TCP_TX_TIMEOUT_DEFAULT, + CFG_EXTWOW_TCP_TX_TIMEOUT_MIN, + CFG_EXTWOW_TCP_TX_TIMEOUT_MAX ), + + REG_VARIABLE( CFG_EXTWOW_TCP_RX_TIMEOUT, WLAN_PARAM_Integer, + hdd_config_t, extWowApp2TcpRxTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTWOW_TCP_RX_TIMEOUT_DEFAULT, + CFG_EXTWOW_TCP_RX_TIMEOUT_MIN, + CFG_EXTWOW_TCP_RX_TIMEOUT_MAX ), +#endif + REG_VARIABLE( CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_NAME, WLAN_PARAM_Integer, + hdd_config_t, gEnableDeauthToDisassocMap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_DEFAULT, + CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_MIN, + CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_MAX ), + +#ifdef DHCP_SERVER_OFFLOAD + REG_VARIABLE( CFG_DHCP_SERVER_OFFLOAD_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, enableDHCPServerOffload, + 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, dhcpMaxNumClients, + 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( CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_NAME, + WLAN_PARAM_Integer, hdd_config_t, dhcp_client_start_ip, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_MIN, + CFG_DHCP_SERVER_OFFLOAD_CLIENT_IPBASE_MAX ), + + REG_VARIABLE_STRING( CFG_DHCP_SERVER_IP_NAME, WLAN_PARAM_String, + hdd_config_t, dhcpServerIP, + VAR_FLAGS_OPTIONAL, + (void *) CFG_DHCP_SERVER_IP_DEFAULT ), +#endif /* DHCP_SERVER_OFFLOAD */ + + REG_VARIABLE(CFG_ENABLE_DEAUTH_BEFORE_CONNECTION, WLAN_PARAM_Integer, + hdd_config_t, sendDeauthBeforeCon, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_DEAUTH_BEFORE_CONNECTION_DEFAULT, + CFG_ENABLE_DEAUTH_BEFORE_CONNECTION_MIN, + CFG_ENABLE_DEAUTH_BEFORE_CONNECTION_MAX), + + REG_VARIABLE( CFG_IGNORE_PEER_ERP_INFO_NAME, WLAN_PARAM_Integer, + hdd_config_t, ignorePeerErpInfo, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IGNORE_PEER_ERP_INFO_DEFAULT, + CFG_IGNORE_PEER_ERP_INFO_MIN, + CFG_IGNORE_PEER_ERP_INFO_MAX ), + + REG_VARIABLE( CFG_ENABLE_MAC_ADDR_SPOOFING, WLAN_PARAM_Integer, + hdd_config_t, enable_mac_spoofing, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_MAC_ADDR_SPOOFING_DEFAULT, + CFG_ENABLE_MAC_ADDR_SPOOFING_MIN, + CFG_ENABLE_MAC_ADDR_SPOOFING_MAX ), +#ifdef IPA_UC_STA_OFFLOAD + REG_VARIABLE( CFG_IPA_UC_STA_OFFLOAD, WLAN_PARAM_Integer, + hdd_config_t, ipa_uc_sta_offload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IPA_UC_STA_OFFLOAD_DEFAULT, + CFG_IPA_UC_STA_OFFLOAD_MIN, + CFG_IPA_UC_STA_OFFLOAD_MAX ), +#endif + + REG_VARIABLE( CFG_ENABLE_CUSTOM_CONC_RULE1_NAME, WLAN_PARAM_Integer, + hdd_config_t, conc_custom_rule1, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENABLE_CUSTOM_CONC_RULE1_NAME_DEFAULT, + CFG_ENABLE_CUSTOM_CONC_RULE1_NAME_MIN, + CFG_ENABLE_CUSTOM_CONC_RULE1_NAME_MAX), + + REG_VARIABLE( CFG_ENABLE_CUSTOM_CONC_RULE2_NAME, WLAN_PARAM_Integer, + hdd_config_t, conc_custom_rule2, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENABLE_CUSTOM_CONC_RULE2_NAME_DEFAULT, + CFG_ENABLE_CUSTOM_CONC_RULE2_NAME_MIN, + CFG_ENABLE_CUSTOM_CONC_RULE2_NAME_MAX), + + REG_VARIABLE( CFG_ENABLE_STA_CONNECTION_IN_5GHZ, WLAN_PARAM_Integer, + hdd_config_t, is_sta_connection_in_5gz_enabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_ENABLE_STA_CONNECTION_IN_5GHZ_DEFAULT, + CFG_ENABLE_STA_CONNECTION_IN_5GHZ_MIN, + CFG_ENABLE_STA_CONNECTION_IN_5GHZ_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 */ + +#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 ), + + REG_VARIABLE( CFG_CONNECT_FAIL_COUNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, connect_fail_count, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CONNECT_FAIL_COUNT_DEFAULT, + CFG_CONNECT_FAIL_COUNT_MIN, + CFG_CONNECT_FAIL_COUNT_MAX ), + + REG_VARIABLE( CFG_CONNECT_FAIL_DURATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, connect_fail_duration, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CONNECT_FAIL_DURATION_DEFAULT, + CFG_CONNECT_FAIL_DURATION_MIN, + CFG_CONNECT_FAIL_DURATION_MAX ), + + REG_VARIABLE( CFG_CONNECT_BLOCK_DURATION_NAME, WLAN_PARAM_Integer, + hdd_config_t, connect_block_duration, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CONNECT_BLOCK_DURATION_DEFAULT, + CFG_CONNECT_BLOCK_DURATION_MIN, + CFG_CONNECT_BLOCK_DURATION_MAX ), +#endif /* SAP_AUTH_OFFLOAD */ + + REG_VARIABLE(CFG_DOT11P_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, dot11p_mode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DOT11P_MODE_DEFAULT, + CFG_DOT11P_MODE_MIN, + CFG_DOT11P_MODE_MAX), + + REG_VARIABLE( CFG_ENABLE_RAMDUMP_COLLECTION, WLAN_PARAM_Integer, + hdd_config_t, is_ramdump_enabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_RAMDUMP_COLLECTION_DEFAULT, + CFG_ENABLE_RAMDUMP_COLLECTION_MIN, + CFG_ENABLE_RAMDUMP_COLLECTION_MAX ), + + REG_VARIABLE(CFG_SAP_DOT11MC, WLAN_PARAM_Integer, + hdd_config_t, sap_dot11mc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_DOT11MC_DEFAULT, + CFG_SAP_DOT11MC_MIN, + CFG_SAP_DOT11MC_MAX ), + + REG_VARIABLE( CFG_STA_MIRACAST_MCC_REST_TIME_VAL, WLAN_PARAM_Integer, + hdd_config_t, sta_miracast_mcc_rest_time_val, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_STA_MIRACAST_MCC_REST_TIME_VAL_DEFAULT, + CFG_STA_MIRACAST_MCC_REST_TIME_VAL_MIN, + CFG_STA_MIRACAST_MCC_REST_TIME_VAL_MAX ), + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + REG_VARIABLE(CFG_SAP_MCC_CHANNEL_AVOIDANCE_NAME, + WLAN_PARAM_Integer, + hdd_config_t, + sap_channel_avoidance, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_SAP_MCC_CHANNEL_AVOIDANCE_DEFAULT, + CFG_SAP_MCC_CHANNEL_AVOIDANCE_MIN, + CFG_SAP_MCC_CHANNEL_AVOIDANCE_MAX ), +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + REG_VARIABLE(CFG_SAP_P2P_11AC_OVERRIDE_NAME, WLAN_PARAM_Integer, + hdd_config_t, sap_p2p_11ac_override, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_P2P_11AC_OVERRIDE_DEFAULT, + CFG_SAP_P2P_11AC_OVERRIDE_MIN, + CFG_SAP_P2P_11AC_OVERRIDE_MAX), + + REG_VARIABLE(CFG_ENABLE_NON_DFS_CHAN_ON_RADAR, WLAN_PARAM_Integer, + hdd_config_t, prefer_non_dfs_on_radar, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_DEFAULT, + CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MIN, + CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MAX), + + REG_VARIABLE(CFG_INFORM_BSS_RSSI_RAW_NAME, WLAN_PARAM_Integer, + hdd_config_t, inform_bss_rssi_raw, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_INFORM_BSS_RSSI_RAW_DEFAULT, + CFG_INFORM_BSS_RSSI_RAW_MIN, + CFG_INFORM_BSS_RSSI_RAW_MAX), +#ifdef WLAN_FEATURE_TSF + REG_VARIABLE(CFG_SET_TSF_GPIO_PIN_NAME, WLAN_PARAM_Integer, + hdd_config_t, tsf_gpio_pin, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SET_TSF_GPIO_PIN_DEFAULT, + CFG_SET_TSF_GPIO_PIN_MIN, + CFG_SET_TSF_GPIO_PIN_MAX), +#endif + REG_VARIABLE(CFG_FINE_TIME_MEAS_CAPABILITY, WLAN_PARAM_HexInteger, + hdd_config_t, fine_time_meas_cap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FINE_TIME_MEAS_CAPABILITY_DEFAULT, + CFG_FINE_TIME_MEAS_CAPABILITY_MIN, + CFG_FINE_TIME_MEAS_CAPABILITY_MAX), + + REG_VARIABLE(CFG_P2P_LISTEN_DEFER_INTERVAL_NAME, WLAN_PARAM_Integer, + hdd_config_t, p2p_listen_defer_interval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_P2P_LISTEN_DEFER_INTERVAL_DEFAULT, + CFG_P2P_LISTEN_DEFER_INTERVAL_MIN, + CFG_P2P_LISTEN_DEFER_INTERVAL_MAX), + + REG_VARIABLE(CFG_MULTICAST_HOST_FW_MSGS, WLAN_PARAM_Integer, + hdd_config_t, multicast_host_fw_msgs, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MULTICAST_HOST_FW_MSGS_DEFAULT, + CFG_MULTICAST_HOST_FW_MSGS_MIN, + CFG_MULTICAST_HOST_FW_MSGS_MAX), + + REG_VARIABLE(CFG_DROPPED_PKT_DISCONNECT_TH_NAME, WLAN_PARAM_Integer, + hdd_config_t, pkt_err_disconn_th, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DROPPED_PKT_DISCONNECT_TH_DEFAULT, + CFG_DROPPED_PKT_DISCONNECT_TH_MIN, + CFG_DROPPED_PKT_DISCONNECT_TH_MAX), + + REG_VARIABLE(CFG_TX_CHAIN_MASK_CCK, WLAN_PARAM_Integer, + hdd_config_t, tx_chain_mask_cck, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TX_CHAIN_MASK_CCK_DEFAULT, + CFG_TX_CHAIN_MASK_CCK_MIN, + CFG_TX_CHAIN_MASK_CCK_MAX), + + REG_VARIABLE(CFG_TX_CHAIN_MASK_1SS, WLAN_PARAM_Integer, + hdd_config_t, tx_chain_mask_1ss, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TX_CHAIN_MASK_1SS_DEFAULT, + CFG_TX_CHAIN_MASK_1SS_MIN, + CFG_TX_CHAIN_MASK_1SS_MAX), + + REG_VARIABLE(CFG_SELF_GEN_FRM_PWR, WLAN_PARAM_Integer, + hdd_config_t, self_gen_frm_pwr, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SELF_GEN_FRM_PWR_DEFAULT, + CFG_SELF_GEN_FRM_PWR_MIN, + CFG_SELF_GEN_FRM_PWR_MAX), + +#ifdef FEATURE_WLAN_EXTSCAN + REG_VARIABLE(CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, extscan_passive_max_chn_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_DEFAULT, + CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_MIN, + CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_MAX ), + + REG_VARIABLE(CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, extscan_passive_min_chn_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_DEFAULT, + CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_MIN, + CFG_EXTSCAN_PASSIVE_MIN_CHANNEL_TIME_MAX), + + REG_VARIABLE(CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, extscan_active_max_chn_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_DEFAULT, + CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_MIN, + CFG_EXTSCAN_ACTIVE_MAX_CHANNEL_TIME_MAX), + + REG_VARIABLE(CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_NAME, WLAN_PARAM_Integer, + hdd_config_t, extscan_active_min_chn_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_DEFAULT, + CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_MIN, + CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_MAX), +#endif + + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD + REG_VARIABLE(CFG_UDP_RESP_OFFLOAD_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, udp_resp_offload_support, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_UDP_RESP_OFFLOAD_SUPPORT_DEFAULT, + CFG_UDP_RESP_OFFLOAD_SUPPORT_MIN, + CFG_UDP_RESP_OFFLOAD_SUPPORT_MAX), + + REG_VARIABLE(CFG_UDP_RESP_OFFLOAD_DEST_PORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, dest_port, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_UDP_RESP_OFFLOAD_DEST_PORT_DEFAULT, + CFG_UDP_RESP_OFFLOAD_DEST_PORT_MIN, + CFG_UDP_RESP_OFFLOAD_DEST_PORT_MAX), + + REG_VARIABLE_STRING(CFG_UDP_RESP_OFFLOAD_PAYLOAD_FILTER_NAME, + WLAN_PARAM_String, + hdd_config_t, payload_filter, + VAR_FLAGS_OPTIONAL, + (void *)CFG_UDP_RESP_OFFLOAD_PAYLOAD_FILTER_DEFAULT), + + REG_VARIABLE_STRING(CFG_UDP_RESP_OFFLOAD_RESPONSE_PAYLOAD_NAME, + WLAN_PARAM_String, + hdd_config_t, response_payload, + VAR_FLAGS_OPTIONAL, + (void *)CFG_UDP_RESP_OFFLOAD_RESPONSE_PAYLOAD_DEFAULT), + +#endif + + + REG_VARIABLE(CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_NAME, WLAN_PARAM_Integer, + hdd_config_t, max_mgmt_tx_fail_count, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_DEFAULT, + CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_MIN, + CFG_DBG_MAX_MGMT_TX_FAILURE_COUNT_MAX), + + REG_VARIABLE(CFG_FIRST_SCAN_BUCKET_THRESHOLD_NAME, WLAN_PARAM_SignedInteger, + hdd_config_t, first_scan_bucket_threshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_FIRST_SCAN_BUCKET_THRESHOLD_DEFAULT, + CFG_FIRST_SCAN_BUCKET_THRESHOLD_MIN, + CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX), +}; + +#ifdef WLAN_FEATURE_MBSSID +REG_TABLE_ENTRY mbssid_sap_dyn_ini_reg_table[] = +{ + REG_VARIABLE( CFG_SAP_SCAN_BAND_PREFERENCE, WLAN_PARAM_Integer, + mbssid_sap_dyn_ini_config_t, acsScanBandPreference, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK + | VAR_FLAGS_DYNAMIC_CFG, + CFG_SAP_SCAN_BAND_PREFERENCE_DEFAULT, + CFG_SAP_SCAN_BAND_PREFERENCE_MIN, + CFG_SAP_SCAN_BAND_PREFERENCE_MAX ), + + REG_VARIABLE( CFG_ACS_BAND_SWITCH_THRESHOLD, WLAN_PARAM_Integer, + mbssid_sap_dyn_ini_config_t, acsBandSwitchThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK + | VAR_FLAGS_DYNAMIC_CFG, + CFG_ACS_BAND_SWITCH_THRESHOLD_DEFAULT, + CFG_ACS_BAND_SWITCH_THRESHOLD_MIN, + CFG_ACS_BAND_SWITCH_THRESHOLD_MAX ), +}; +#endif + +/* + * This function returns a pointer to the character after the occurrence + * of a new line character. It also modifies the original string by replacing + * the '\n' character with the null character. + * Function returns NULL if no new line character was found before end of + * string was reached + */ +static char* get_next_line(char* str) +{ + char c; + + if( str == NULL || *str == '\0') { + return NULL; + } + + c = *str; + while(c != '\n' && c != '\0' && c != 0xd) { + str = str + 1; + c = *str; + } + + if (c == '\0' ) { + return NULL; + } + else + { + *str = '\0'; + return (str+1); + } + + return NULL; +} + +// look for space. Ascii values to look are - +// 0x09 == horizontal tab +// 0x0a == Newline ("\n") +// 0x0b == vertical tab +// 0x0c == Newpage or feed form. +// 0x0d == carriage return (CR or "\r") +// Null ('\0') should not considered as space. +#define i_isspace(ch) (((ch) >= 0x09 && (ch) <= 0x0d) || (ch) == ' ') + +/* + * This function trims any leading and trailing white spaces + */ +static char *i_trim(char *str) + +{ + char *ptr; + + if(*str == '\0') return str; + + /* Find the first non white-space*/ + for (ptr = str; i_isspace(*ptr); ptr++); + if (*ptr == '\0') + return str; + + /* This is the new start of the string*/ + str = ptr; + + /* Find the last non white-space */ + ptr += strlen(ptr) - 1; + for (; ptr != str && i_isspace(*ptr); ptr--); + /* Null terminate the following character */ + ptr[1] = '\0'; + + return str; +} + + +//Structure to store each entry in qcom_cfg.ini file +typedef struct +{ + char *name; + char *value; +}tCfgIniEntry; + +static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t * pHddCtx, + tCfgIniEntry* iniTable, unsigned long entries); + +#ifdef WLAN_CFG_DEBUG +void dump_cfg_ini (tCfgIniEntry* iniTable, unsigned long entries) +{ + unsigned long i; + + for (i = 0; i < entries; i++) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "%s entry Name=[%s] value=[%s]", + WLAN_INI_FILE, iniTable[i].name, iniTable[i].value); + } +} +#endif + +/* + * This function reads the qcom_cfg.ini file and + * parses each 'Name=Value' pair in the ini file + */ +VOS_STATUS hdd_parse_config_ini(hdd_context_t* pHddCtx) +{ + int status, i=0; + /** Pointer for firmware image data */ + const struct firmware *fw = NULL; + char *buffer, *line, *pTemp = NULL; + size_t size; + char *name, *value; + /* cfgIniTable is static to avoid excess stack usage */ + static tCfgIniEntry cfgIniTable[MAX_CFG_INI_ITEMS]; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + memset(cfgIniTable, 0, sizeof(cfgIniTable)); + + status = request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev); + + if(status) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: request_firmware failed %d",__func__, status); + vos_status = VOS_STATUS_E_FAILURE; + goto config_exit; + } + if(!fw || !fw->data || !fw->size) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: %s download failed", + __func__, WLAN_INI_FILE); + vos_status = VOS_STATUS_E_FAILURE; + goto config_exit; + } + + hddLog(LOG1, "%s: qcom_cfg.ini Size %zu", __func__, fw->size); + + buffer = (char*)vos_mem_malloc(fw->size); + + if(NULL == buffer) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: kmalloc failure",__func__); + release_firmware(fw); + return VOS_STATUS_E_FAILURE; + } + pTemp = buffer; + + vos_mem_copy((void*)buffer,(void *)fw->data, fw->size); + size = fw->size; + + while (buffer != NULL) + { + line = get_next_line(buffer); + buffer = i_trim(buffer); + + hddLog(LOG1, "%s: item", buffer); + + if(strlen((char*)buffer) == 0 || *buffer == '#') { + buffer = line; + continue; + } + else if(strncmp(buffer, "END", 3) == 0 ) { + break; + } + else + { + name = buffer; + while(*buffer != '=' && *buffer != '\0') + buffer++; + if(*buffer != '\0') { + *buffer++ = '\0'; + i_trim(name); + if(strlen (name) != 0) { + buffer = i_trim(buffer); + if(strlen(buffer)>0) { + value = buffer; + while (*buffer != '\0') + buffer++; + *buffer = '\0'; + cfgIniTable[i].name= name; + cfgIniTable[i++].value= value; + if(i >= MAX_CFG_INI_ITEMS) { + hddLog(LOGE,"%s: Number of items in %s > %d", + __func__, WLAN_INI_FILE, MAX_CFG_INI_ITEMS); + break; + } + } + } + } + } + buffer = line; + } + + //Loop through the registry table and apply all these configs + vos_status = hdd_apply_cfg_ini(pHddCtx, cfgIniTable, i); + +config_exit: + release_firmware(fw); + vos_mem_free(pTemp); + return vos_status; +} + + +void print_hdd_cfg(hdd_context_t *pHddCtx) +{ + int i; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "*********Config values in HDD Adapter*******"); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [RTSThreshold] Value = %u",pHddCtx->cfg_ini->RTSThreshold) ; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [OperatingChannel] Value = [%u]",pHddCtx->cfg_ini->OperatingChannel); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [PowerUsageControl] Value = [%s]",pHddCtx->cfg_ini->PowerUsageControl); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fIsImpsEnabled] Value = [%u]",pHddCtx->cfg_ini->fIsImpsEnabled); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [AutoBmpsTimerEnabled] Value = [%u]",pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nAutoBmpsTimerValue] Value = [%u]",pHddCtx->cfg_ini->nAutoBmpsTimerValue); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nVccRssiTrigger] Value = [%u]",pHddCtx->cfg_ini->nVccRssiTrigger); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssBssid] Value =["MAC_ADDRESS_STR"]", + MAC_ADDR_ARRAY(pHddCtx->cfg_ini->IbssBssid.bytes)); + + for (i=0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [Intf%dMacAddress] Value =["MAC_ADDRESS_STR"]", + i, MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes)); + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApEnableUapsd] value = [%u]",pHddCtx->cfg_ini->apUapsdEnabled); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAPCntryCode] Value =[%c%c%c]", + pHddCtx->cfg_ini->apCntryCode[0],pHddCtx->cfg_ini->apCntryCode[1], + pHddCtx->cfg_ini->apCntryCode[2]); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableApProt] value = [%u]", pHddCtx->cfg_ini->apProtEnabled); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAPAutoShutOff] Value = [%u]", pHddCtx->cfg_ini->nAPAutoShutOff); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gWlanMccToSccSwitchMode] Value = [%u]", pHddCtx->cfg_ini->WlanMccToSccSwitchMode); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gWlanAutoShutdown] Value = [%u]", pHddCtx->cfg_ini->WlanAutoShutdown); +#endif + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableListenMode] Value = [%u]", pHddCtx->cfg_ini->nEnableListenMode); + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApProtection] value = [%u]",pHddCtx->cfg_ini->apProtection); + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableApOBSSProt] value = [%u]",pHddCtx->cfg_ini->apOBSSProtEnabled); +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + VOS_TRACE (VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [sap_channel_avoidance] value = [%u]", + pHddCtx->cfg_ini->sap_channel_avoidance); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_SAP_P2P_11AC_OVERRIDE_NAME, + pHddCtx->cfg_ini->sap_p2p_11ac_override); + + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_FORCE_SAP_ACS, + pHddCtx->cfg_ini->force_sap_acs); + + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_FORCE_SAP_ACS_START_CH, + pHddCtx->cfg_ini->force_sap_acs_st_ch); + + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_FORCE_SAP_ACS_END_CH, + pHddCtx->cfg_ini->force_sap_acs_end_ch); + + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gACSBandSwitchThreshold] value = [%u]", pHddCtx->cfg_ini->acsBandSwitchThreshold); + + 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 = [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); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [UapsdMask] Value = [0x%x] ",pHddCtx->cfg_ini->UapsdMask); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [PktClassificationBasis] Value = [%u] ",pHddCtx->cfg_ini->PktClassificationBasis); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ImplicitQosIsEnabled] Value = [%u]",(int)pHddCtx->cfg_ini->bImplicitQosEnabled); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdVoSrvIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdVoSrvIntv); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdVoSuspIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdVoSuspIntv); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdViSrvIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdViSrvIntv); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdViSuspIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdViSuspIntv); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBeSrvIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdBeSrvIntv); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBeSuspIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdBeSuspIntv); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBkSrvIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdBkSrvIntv); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraUapsdBkSuspIntv] Value = [%u] ",pHddCtx->cfg_ini->InfraUapsdBkSuspIntv); +#ifdef FEATURE_WLAN_ESE + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraInactivityInterval] Value = [%u] ",pHddCtx->cfg_ini->InfraInactivityInterval); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [EseEnabled] Value = [%u] ",pHddCtx->cfg_ini->isEseIniFeatureEnabled); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [FastTransitionEnabled] Value = [%u] ",pHddCtx->cfg_ini->isFastTransitionEnabled); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gTxPowerCap] Value = [%u] dBm ",pHddCtx->cfg_ini->nTxPowerCap); +#endif +#ifdef FEATURE_WLAN_LFR + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [FastRoamEnabled] Value = [%u] ",pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [MAWCEnabled] Value = [%u] ",pHddCtx->cfg_ini->MAWCEnabled); +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [RoamRssiDiff] Value = [%u] ",pHddCtx->cfg_ini->RoamRssiDiff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ImmediateRoamRssiDiff] Value = [%u] ",pHddCtx->cfg_ini->nImmediateRoamRssiDiff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [isWESModeEnabled] Value = [%u] ",pHddCtx->cfg_ini->isWESModeEnabled); +#endif +#ifdef FEATURE_WLAN_OKC + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [OkcEnabled] Value = [%u] ",pHddCtx->cfg_ini->isOkcIniFeatureEnabled); +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [configPNOScanSupport] Value = [%u] ",pHddCtx->cfg_ini->configPNOScanSupport); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [configPNOScanTimerRepeatValue] Value = [%u] ",pHddCtx->cfg_ini->configPNOScanTimerRepeatValue); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [pno_slow_scan_multiplier] Value = [%u] ",pHddCtx->cfg_ini->pno_slow_scan_multiplier); +#endif +#ifdef FEATURE_WLAN_TDLS + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fEnableTDLSSupport] Value = [%u] ",pHddCtx->cfg_ini->fEnableTDLSSupport); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fEnableTDLSImplicitTrigger] Value = [%u] ",pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fTDLSExternalControl] Value = [%u] ",pHddCtx->cfg_ini->fTDLSExternalControl); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fTDLSUapsdMask] Value = [%u] ",pHddCtx->cfg_ini->fTDLSUapsdMask); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fEnableTDLSBufferSta] Value = [%u] ",pHddCtx->cfg_ini->fEnableTDLSBufferSta); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fEnableTDLSWmmMode] Value = [%u] ",pHddCtx->cfg_ini->fEnableTDLSWmmMode); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [enable_tdls_scan] Value = [%u]", + pHddCtx->cfg_ini->enable_tdls_scan); +#endif + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcVo] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcVo); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcVo] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcVo); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcVo] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMeanDataRateAcVo); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcVo] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMinPhyRateAcVo); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcVo] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcVo); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcVi] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcVi); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcVi] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcVi); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcVi] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMeanDataRateAcVi); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcVi] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMinPhyRateAcVi); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcVi] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcVi); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcBe] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcBe); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcBe] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcBe); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcBe] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMeanDataRateAcBe); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcBe] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMinPhyRateAcBe); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcBe] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcBe); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraDirAcBk] Value = [%u] ",pHddCtx->cfg_ini->InfraDirAcBk); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraNomMsduSizeAcBk] Value = [0x%x] ",pHddCtx->cfg_ini->InfraNomMsduSizeAcBk); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMeanDataRateAcBk] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMeanDataRateAcBk); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraMinPhyRateAcBk] Value = [0x%x] ",pHddCtx->cfg_ini->InfraMinPhyRateAcBk); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [InfraSbaAcBk] Value = [0x%x] ",pHddCtx->cfg_ini->InfraSbaAcBk); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [DelayedTriggerFrmInt] Value = [%u] ",pHddCtx->cfg_ini->DelayedTriggerFrmInt); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [mcastBcastFilterSetting] Value = [%u] ",pHddCtx->cfg_ini->mcastBcastFilterSetting); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fhostArpOffload] Value = [%u] ",pHddCtx->cfg_ini->fhostArpOffload); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ssdp] Value = [%u] ", pHddCtx->cfg_ini->ssdp); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [%s] Value = [%u] ", CFG_ENABLE_HOST_BROADCAST_NAME, pHddCtx->cfg_ini->bcastptrn); +#ifdef FEATURE_RUNTIME_PM + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [runtime_pm] Value = [%u] ", pHddCtx->cfg_ini->runtime_pm); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [runtime_pm_delay] Value = [%u] ", pHddCtx->cfg_ini->runtime_pm_delay); +#endif +#ifdef FEATURE_SECURE_FIRMWARE + hddLog(LOG2, "Name = [enable_fw_hash_check] Value = [%u]", + pHddCtx->cfg_ini->enable_fw_hash_check); +#endif +#ifdef FEATURE_WLAN_RA_FILTERING + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [RArateLimitInterval] Value = [%u] ", pHddCtx->cfg_ini->RArateLimitInterval); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [IsRArateLimitEnabled] Value = [%u] ", pHddCtx->cfg_ini->IsRArateLimitEnabled); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fFTResourceReqSupported] Value = [%u] ",pHddCtx->cfg_ini->fFTResourceReqSupported); +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborReassocRssiThreshold] Value = [%u] ",pHddCtx->cfg_ini->nNeighborReassocRssiThreshold); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborLookupRssiThreshold] Value = [%u] ",pHddCtx->cfg_ini->nNeighborLookupRssiThreshold); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nOpportunisticThresholdDiff] Value = [%u] ", + pHddCtx->cfg_ini->nOpportunisticThresholdDiff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamRescanRssiDiff] Value = [%u] ", + pHddCtx->cfg_ini->nRoamRescanRssiDiff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanMinChanTime] Value = [%u] ",pHddCtx->cfg_ini->nNeighborScanMinChanTime); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanMaxChanTime] Value = [%u] ",pHddCtx->cfg_ini->nNeighborScanMaxChanTime); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nMaxNeighborRetries] Value = [%u] ",pHddCtx->cfg_ini->nMaxNeighborReqTries); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanPeriod] Value = [%u] ",pHddCtx->cfg_ini->nNeighborScanPeriod); + 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 = [nRoamBmissFirstBcnt] Value = [%u] ", + pHddCtx->cfg_ini->nRoamBmissFirstBcnt); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamBmissFinalBcnt] Value = [%u] ", + pHddCtx->cfg_ini->nRoamBmissFinalBcnt); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamBeaconRssiWeight] Value = [%u] ", + pHddCtx->cfg_ini->nRoamBeaconRssiWeight); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [allowDFSChannelRoam] Value = [%u] ", + pHddCtx->cfg_ini->allowDFSChannelRoam); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_max_count] Value = [%u] ", + pHddCtx->cfg_ini->nhi_rssi_scan_max_count); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_rssi_delta] Value = [%u] ", + pHddCtx->cfg_ini->nhi_rssi_scan_rssi_delta); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_delay] Value = [%u] ", + pHddCtx->cfg_ini->nhi_rssi_scan_delay); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_rssi_ub] Value = [%u] ", + pHddCtx->cfg_ini->nhi_rssi_scan_rssi_ub); +#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); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [rfSettlingTimeUs] Value = [%u] ",pHddCtx->cfg_ini->rfSettlingTimeUs); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [bSingleTidRc] Value = [%u] ",pHddCtx->cfg_ini->bSingleTidRc); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gDynamicPSPollvalue] Value = [%u] ",pHddCtx->cfg_ini->dynamicPsPollValue); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAddTSWhenACMIsOff] Value = [%u] ",pHddCtx->cfg_ini->AddTSWhenACMIsOff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gValidateScanList] Value = [%u] ",pHddCtx->cfg_ini->fValidateScanList); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gStaKeepAlivePeriod] Value = [%u] ",pHddCtx->cfg_ini->infraStaKeepAlivePeriod); + 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 = [BandCapability] Value = [%u] ",pHddCtx->cfg_ini->nBandCapability); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fEnableBeaconEarlyTermination] Value = [%u] ",pHddCtx->cfg_ini->fEnableBeaconEarlyTermination); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [teleBcnWakeupEnable] Value = [%u] ",pHddCtx->cfg_ini->teleBcnWakeupEn); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [transListenInterval] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnTransListenInterval); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [transLiNumIdleBeacons] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnTransLiNumIdleBeacons); + 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->enable_dfs_pno_chnl_scan); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gReportMaxLinkSpeed] Value = [%u] ",pHddCtx->cfg_ini->reportMaxLinkSpeed); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [thermalMitigationEnable] Value = [%u] ",pHddCtx->cfg_ini->thermalMitigationEnable); +#ifdef WLAN_FEATURE_11AC + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gVhtChannelWidth] value = [%u]",pHddCtx->cfg_ini->vhtChannelWidth); +#endif + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [enableFirstScan2GOnly] Value = [%u] ",pHddCtx->cfg_ini->enableFirstScan2GOnly); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [skipDfsChnlInP2pSearch] Value = [%u] ",pHddCtx->cfg_ini->skipDfsChnlInP2pSearch); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ignoreDynamicDtimInP2pMode] Value = [%u] ",pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [enableRxSTBC] Value = [%u] ",pHddCtx->cfg_ini->enableRxSTBC); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableLpwrImgTransition] Value = [%u] ",pHddCtx->cfg_ini->enableLpwrImgTransition); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableSSR] Value = [%u] ",pHddCtx->cfg_ini->enableSSR); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableVhtFor24GHzBand] Value = [%u] ",pHddCtx->cfg_ini->enableVhtFor24GHzBand); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gFlexConnectPowerFactor] Value = [%u] ", pHddCtx->cfg_ini->flexConnectPowerFactor); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableIbssHeartBeatOffload] Value = [%u] ", pHddCtx->cfg_ini->enableIbssHeartBeatOffload); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAntennaDiversity] Value = [%u] ", pHddCtx->cfg_ini->antennaDiversity); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gGoLinkMonitorPeriod] Value = [%u]",pHddCtx->cfg_ini->goLinkMonitorPeriod); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApLinkMonitorPeriod] Value = [%u]",pHddCtx->cfg_ini->apLinkMonitorPeriod); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gGoKeepAlivePeriod] Value = [%u]",pHddCtx->cfg_ini->goKeepAlivePeriod); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApKeepAlivePeriod]Value = [%u]",pHddCtx->cfg_ini->apKeepAlivePeriod); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMaxAmsduNum] Value = [%u] ", pHddCtx->cfg_ini->max_amsdu_num); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nSelect5GHzMargin] Value = [%u] ",pHddCtx->cfg_ini->nSelect5GHzMargin); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gCoalesingInIBSS] Value = [%u] ",pHddCtx->cfg_ini->isCoalesingInIBSSAllowed); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssATIMWinSize] Value = [%u] ",pHddCtx->cfg_ini->ibssATIMWinSize); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssIsPowerSaveAllowed] Value = [%u] ",pHddCtx->cfg_ini->isIbssPowerSaveAllowed); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssIsPowerCollapseAllowed] Value = [%u] ",pHddCtx->cfg_ini->isIbssPowerCollapseAllowed); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssAwakeOnTxRx] Value = [%u] ",pHddCtx->cfg_ini->isIbssAwakeOnTxRx); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssInactivityTime] Value = [%u] ",pHddCtx->cfg_ini->ibssInactivityCount); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssTxSpEndInactivityTime] Value = [%u] ",pHddCtx->cfg_ini->ibssTxSpEndInactivityTime); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIbssPsWarmupTime] Value = [%u] ",pHddCtx->cfg_ini->ibssPsWarmupTime); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssPs1RxChainInAtim] Value = [%u] ", + pHddCtx->cfg_ini->ibssPs1RxChainInAtimEnable); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gIgnorePeerErpInfo] Value = [%u] ", + pHddCtx->cfg_ini->ignorePeerErpInfo); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [fDfsPhyerrFilterOffload] Value = [%u] ",pHddCtx->cfg_ini->fDfsPhyerrFilterOffload); + +#ifdef IPA_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIPAConfig] Value = [0x%x] ",pHddCtx->cfg_ini->IpaConfig); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIPADescSize] Value = [%u] ",pHddCtx->cfg_ini->IpaDescSize); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [IpaHighBandwidthMbpsg] Value = [%u] ",pHddCtx->cfg_ini->IpaHighBandwidthMbps); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [IpaMediumBandwidthMbps] Value = [%u] ",pHddCtx->cfg_ini->IpaMediumBandwidthMbps); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [IpaLowBandwidthMbps] Value = [%u] ",pHddCtx->cfg_ini->IpaLowBandwidthMbps); +#endif + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableOverLapCh] Value = [%u] ",pHddCtx->cfg_ini->gEnableOverLapCh); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAcsScanBandPreference] Value = [%u] ",pHddCtx->cfg_ini->acsScanBandPreference); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gMaxOffloadPeers] Value = [%u] ",pHddCtx->cfg_ini->apMaxOffloadPeers); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gMaxOffloadReorderBuffs] value = [%u] ",pHddCtx->cfg_ini->apMaxOffloadReorderBuffs); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [overrideCountryCode] Value = [%s] ",pHddCtx->cfg_ini->overrideCountryCode); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAllowDFSChannelRoam] Value = [%u] ",pHddCtx->cfg_ini->allowDFSChannelRoam); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gMaxConcurrentActiveSessions] Value = [%u] ", pHddCtx->cfg_ini->gMaxConcurrentActiveSessions); + +#ifdef MSM_PLATFORM + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gBusBandwidthHighThreshold] Value = [%u] ", + pHddCtx->cfg_ini->busBandwidthHighThreshold); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gBusBandwidthMediumThreshold] Value = [%u] ", + pHddCtx->cfg_ini->busBandwidthMediumThreshold); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gBusBandwidthLowThreshold] Value = [%u] ", + pHddCtx->cfg_ini->busBandwidthLowThreshold); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gbusBandwidthComputeInterval] Value = [%u] ", + pHddCtx->cfg_ini->busBandwidthComputeInterval); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gTcpDelAckThresholdHigh] Value = [%u] ", + pHddCtx->cfg_ini->tcpDelackThresholdHigh); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gTcpDelAckThresholdLow] Value = [%u] ", + pHddCtx->cfg_ini->tcpDelackThresholdLow); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] Value = [%u] ", CFG_TCP_TX_HIGH_TPUT_THRESHOLD_NAME, + pHddCtx->cfg_ini->tcp_tx_high_tput_thres); + +#endif + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gIgnoreCAC] Value = [%u] ", + pHddCtx->cfg_ini->ignoreCAC); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gSapPreferredChanLocation] Value = [%u] ", + pHddCtx->cfg_ini->gSapPreferredChanLocation); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDisableDfsJapanW53] Value = [%u] ", + pHddCtx->cfg_ini->gDisableDfsJapanW53); +#ifdef FEATURE_GREEN_AP + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableGreenAp] Value = [%u] ", + pHddCtx->cfg_ini->enableGreenAP); +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [isRoamOffloadEnabled] Value = [%u]", + pHddCtx->cfg_ini->isRoamOffloadEnabled); +#endif + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSifsBurst] Value = [%u]", + pHddCtx->cfg_ini->enableSifsBurst); + +#ifdef WLAN_FEATURE_LPSS + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableLpassSupport] Value = [%u] ", + pHddCtx->cfg_ini->enablelpasssupport); +#endif + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSelfRecovery] Value = [%u]", + pHddCtx->cfg_ini->enableSelfRecovery); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSapSuspend] Value = [%u]", + pHddCtx->cfg_ini->enableSapSuspend); + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWgotoSuspend] Value = [%u]", + pHddCtx->cfg_ini->extWowGotoSuspend); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWowApp1WakeupPinNumber] Value = [%u]", + pHddCtx->cfg_ini->extWowApp1WakeupPinNumber); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWowApp2WakeupPinNumber] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2WakeupPinNumber); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAInitPingInterval] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2KAInitPingInterval); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAMinPingInterval] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2KAMinPingInterval); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAMaxPingInterval] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2KAMaxPingInterval); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAIncPingInterval] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2KAIncPingInterval); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpSrcPort] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2TcpSrcPort); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpDstPort] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2TcpDstPort); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpTxTimeout] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2TcpTxTimeout); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpRxTimeout] Value = [%u]", + pHddCtx->cfg_ini->extWowApp2TcpRxTimeout); +#endif +#ifdef IPA_UC_STA_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gIpaUcStaOffload] Value = [%u] ", + pHddCtx->cfg_ini->ipa_uc_sta_offload); +#endif + +#ifdef DHCP_SERVER_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPServerOffloadEnable] Value = [%u]", + pHddCtx->cfg_ini->enableDHCPServerOffload); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPMaxNumClients] Value = [%u]", + pHddCtx->cfg_ini->dhcpMaxNumClients); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPClientStartIP] Value = [%u]", + pHddCtx->cfg_ini->dhcp_client_start_ip); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPServerIP] Value = [%s]", + pHddCtx->cfg_ini->dhcpServerIP); +#endif + +#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 + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableDumpCollect] Value = [%u]", + pHddCtx->cfg_ini->is_ramdump_enabled); + + hddLog(LOG2, "Name = [gP2PListenDeferInterval] Value = [%u]", + pHddCtx->cfg_ini->p2p_listen_defer_interval); + + hddLog(LOG2, "Name = [gfine_time_meas_cap] Value = [%u]", + pHddCtx->cfg_ini->fine_time_meas_cap); + hddLog(LOG2, "Name = [gmax_mgmt_tx_failure_count] Value = [%u]", + pHddCtx->cfg_ini->max_mgmt_tx_fail_count); + hddLog(LOG2, "Name = [%s] Value = [%d]", + CFG_FIRST_SCAN_BUCKET_THRESHOLD_NAME, + pHddCtx->cfg_ini->first_scan_bucket_threshold); + hddLog(LOG2, "Name = [ght_mpdu_density] Value = [%u]", + pHddCtx->cfg_ini->ht_mpdu_density); + hddLog(LOG2, "Name = [gMinRestTimeConc] Value = [%u]", + pHddCtx->cfg_ini->min_rest_time_conc); + hddLog(LOG2, "Name = [gIdleTimeConc] Value = [%u]", + pHddCtx->cfg_ini->idle_time_conc); + +} + +#define CFG_VALUE_MAX_LEN 256 +#define CFG_ENTRY_MAX_LEN (32+CFG_VALUE_MAX_LEN) +static VOS_STATUS hdd_cfg_get_config(REG_TABLE_ENTRY *reg_table, + unsigned long cRegTableEntries, + v_U8_t *ini_struct, + hdd_context_t *pHddCtx, char *pBuf, int buflen) +{ + unsigned int idx; + REG_TABLE_ENTRY *pRegEntry = reg_table; + v_U32_t value; + char valueStr[CFG_VALUE_MAX_LEN]; + char configStr[CFG_ENTRY_MAX_LEN]; + char *fmt; + void *pField; + v_MACADDR_t *pMacAddr; + char *pCur = pBuf; + int curlen; + + // start with an empty string + *pCur = '\0'; + + for ( idx = 0; idx < cRegTableEntries; idx++, pRegEntry++ ) + { + pField = ini_struct + pRegEntry->VarOffset; + + if ( ( WLAN_PARAM_Integer == pRegEntry->RegType ) || + ( WLAN_PARAM_SignedInteger == pRegEntry->RegType ) || + ( WLAN_PARAM_HexInteger == pRegEntry->RegType ) ) + { + value = 0; + memcpy( &value, pField, pRegEntry->VarSize ); + if ( WLAN_PARAM_HexInteger == pRegEntry->RegType ) + { + fmt = "%x"; + } + else if ( WLAN_PARAM_SignedInteger == pRegEntry->RegType ) + { + fmt = "%d"; + } + else + { + fmt = "%u"; + } + snprintf(valueStr, CFG_VALUE_MAX_LEN, fmt, value); + } + else if ( WLAN_PARAM_String == pRegEntry->RegType ) + { + snprintf(valueStr, CFG_VALUE_MAX_LEN, "%s", (char *)pField); + } + else if ( WLAN_PARAM_MacAddr == pRegEntry->RegType ) + { + pMacAddr = (v_MACADDR_t *) pField; + snprintf(valueStr, CFG_VALUE_MAX_LEN, + "%02x:%02x:%02x:%02x:%02x:%02x", + pMacAddr->bytes[0], + pMacAddr->bytes[1], + pMacAddr->bytes[2], + pMacAddr->bytes[3], + pMacAddr->bytes[4], + pMacAddr->bytes[5]); + } + else + { + snprintf(valueStr, CFG_VALUE_MAX_LEN, "(unhandled)"); + } + curlen = scnprintf(configStr, CFG_ENTRY_MAX_LEN, + "%s=[%s]%s\n", + pRegEntry->RegName, + valueStr, + test_bit(idx, (void *)&pHddCtx->cfg_ini->bExplicitCfg) ? + "*" : ""); + + // ideally we want to return the config to the application + // however the config is too big so we just printk() for now +#ifdef RETURN_IN_BUFFER + if (curlen <= buflen) + { + // copy string + '\0' + memcpy(pCur, configStr, curlen+1); + + // account for addition; + pCur += curlen; + buflen -= curlen; + } + else + { + // buffer space exhausted, return what we have + return VOS_STATUS_E_RESOURCES; + } +#else + printk(KERN_INFO "%s", configStr); +#endif // RETURN_IN_BUFFER + +} + +#ifndef RETURN_IN_BUFFER + // notify application that output is in system log + snprintf(pCur, buflen, "WLAN configuration written to system log"); +#endif // RETURN_IN_BUFFER + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_cfg_get_global_config(hdd_context_t *pHddCtx, char *pBuf, + int buflen) +{ + return hdd_cfg_get_config(g_registry_table, ARRAY_SIZE(g_registry_table), + (v_U8_t *) pHddCtx->cfg_ini, + pHddCtx, pBuf, buflen); +} + +#ifdef WLAN_FEATURE_MBSSID +VOS_STATUS hdd_cfg_get_sap_dyn_config(hdd_adapter_t *pAdapter, char *pBuf, + int buflen) +{ + return hdd_cfg_get_config(mbssid_sap_dyn_ini_reg_table, + ARRAY_SIZE(mbssid_sap_dyn_ini_reg_table), + (v_U8_t *) &pAdapter->sap_dyn_ini_cfg, + WLAN_HDD_GET_CTX(pAdapter), + pBuf, buflen); +} +#endif + +static VOS_STATUS find_cfg_item (tCfgIniEntry* iniTable, unsigned long entries, + char *name, char** value) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; + unsigned long i; + + for (i = 0; i < entries; i++) { + if (strcmp(iniTable[i].name, name) == 0) { + *value = iniTable[i].value; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Found %s entry for Name=[%s] Value=[%s] ", + WLAN_INI_FILE, name, *value); + return VOS_STATUS_SUCCESS; + } + } + + return status; +} + +static int parseHexDigit(char c) +{ + if (c >= '0' && c <= '9') + return c-'0'; + if (c >= 'a' && c <= 'f') + return c-'a'+10; + if (c >= 'A' && c <= 'F') + return c-'A'+10; + + return 0; +} + +/* convert string to 6 bytes mac address + * 00AA00BB00CC -> 0x00 0xAA 0x00 0xBB 0x00 0xCC + */ +static void update_mac_from_string(hdd_context_t *pHddCtx, tCfgIniEntry *macTable, int num) +{ + int i = 0, j = 0, res = 0; + char *candidate = NULL; + v_MACADDR_t macaddr[VOS_MAX_CONCURRENCY_PERSONA]; + + memset(macaddr, 0, sizeof(macaddr)); + + for (i = 0; i < num; i++) + { + candidate = macTable[i].value; + for (j = 0; j < VOS_MAC_ADDR_SIZE; j++) { + res = hex2bin(&macaddr[i].bytes[j], &candidate[(j<<1)], 1); + if (res < 0) + break; + } + if (res == 0 && !vos_is_macaddr_zero(&macaddr[i])) { + vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], + (v_U8_t *)&macaddr[i].bytes[0], VOS_MAC_ADDR_SIZE); + } + } +} + +/* + * This function tries to update mac address from cfg file. + * It overwrites the MAC address if config file exist. + */ +VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx) +{ + int status, i = 0; + const struct firmware *fw = NULL; + char *line, *buffer = NULL; + char *name, *value; + tCfgIniEntry macTable[VOS_MAX_CONCURRENCY_PERSONA]; + tSirMacAddr customMacAddr; + + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + memset(macTable, 0, sizeof(macTable)); + status = request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); + + if (status) + { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: request_firmware failed %d", + __func__, status); + vos_status = VOS_STATUS_E_FAILURE; + return vos_status; + } + if (!fw || !fw->data || !fw->size) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: invalid firmware", __func__); + vos_status = VOS_STATUS_E_INVAL; + goto config_exit; + } + + buffer = (char *)fw->data; + + /* data format: + * Intf0MacAddress=00AA00BB00CC + * Intf1MacAddress=00AA00BB00CD + * END + */ + while (buffer != NULL) + { + line = get_next_line(buffer); + buffer = i_trim(buffer); + + if (strlen((char *)buffer) == 0 || *buffer == '#') { + buffer = line; + continue; + } + if (strncmp(buffer, "END", 3) == 0) + break; + + name = buffer; + buffer = strchr(buffer, '='); + if (buffer) { + *buffer++ = '\0'; + i_trim(name); + if (strlen(name) != 0) { + buffer = i_trim(buffer); + if (strlen(buffer) == 12) { + value = buffer; + macTable[i].name = name; + macTable[i++].value = value; + if (i >= VOS_MAX_CONCURRENCY_PERSONA) + break; + } + } + } + buffer = line; + } + if (i <= VOS_MAX_CONCURRENCY_PERSONA) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %d Mac addresses provided", __func__, i); + } + else { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: invalid number of Mac address provided, nMac = %d", + __func__, i); + vos_status = VOS_STATUS_E_INVAL; + goto config_exit; + } + + update_mac_from_string(pHddCtx, &macTable[0], i); + + vos_mem_copy(&customMacAddr, + &pHddCtx->cfg_ini->intfMacAddr[0].bytes[0], + sizeof(tSirMacAddr)); + sme_SetCustomMacAddr(customMacAddr); + +config_exit: + release_firmware(fw); + return vos_status; +} + +static VOS_STATUS hdd_apply_cfg_ini( hdd_context_t *pHddCtx, tCfgIniEntry* iniTable, unsigned long entries) +{ + VOS_STATUS match_status = VOS_STATUS_E_FAILURE; + VOS_STATUS ret_status = VOS_STATUS_SUCCESS; + unsigned int idx; + void *pField; + char *value_str = NULL; + unsigned long len_value_str; + char *candidate; + v_U32_t value; + v_S31_t svalue; + void *pStructBase = pHddCtx->cfg_ini; + REG_TABLE_ENTRY *pRegEntry = g_registry_table; + unsigned long cRegTableEntries = sizeof(g_registry_table) / sizeof( g_registry_table[ 0 ]); + v_U32_t cbOutString; + int i; + int rv; + + if (MAX_CFG_INI_ITEMS < cRegTableEntries) { + hddLog(LOGE, FL("MAX_CFG_INI_ITEMS too small, must be at least %ld"), + cRegTableEntries); + WARN_ON(1); + } + + for ( idx = 0; idx < cRegTableEntries; idx++, pRegEntry++ ) + { + //Calculate the address of the destination field in the structure. + pField = ( (v_U8_t *)pStructBase )+ pRegEntry->VarOffset; + + match_status = find_cfg_item(iniTable, entries, pRegEntry->RegName, &value_str); + + if( (match_status != VOS_STATUS_SUCCESS) && ( pRegEntry->Flags & VAR_FLAGS_REQUIRED ) ) + { + // If we could not read the cfg item and it is required, this is an error. + hddLog(LOGE, "%s: Failed to read required config parameter %s", + __func__, pRegEntry->RegName); + ret_status = VOS_STATUS_E_FAILURE; + break; + } + + if ( ( WLAN_PARAM_Integer == pRegEntry->RegType ) || + ( WLAN_PARAM_HexInteger == pRegEntry->RegType ) ) + { + // If successfully read from the registry, use the value read. + // If not, use the default value. + if ( match_status == VOS_STATUS_SUCCESS && (WLAN_PARAM_Integer == pRegEntry->RegType)) { + rv = kstrtou32(value_str, 10, &value); + if (rv < 0) { + hddLog(LOGE, "%s: Reg Parameter %s invalid. Enforcing default", + __func__, pRegEntry->RegName); + value = pRegEntry->VarDefault; + } + } + else if ( match_status == VOS_STATUS_SUCCESS && (WLAN_PARAM_HexInteger == pRegEntry->RegType)) { + rv = kstrtou32(value_str, 16, &value); + if (rv < 0) { + hddLog(LOGE, "%s: Reg paramter %s invalid. Enforcing default", + __func__, pRegEntry->RegName); + value = pRegEntry->VarDefault; + } + } + else { + value = pRegEntry->VarDefault; + } + + // If this parameter needs range checking, do it here. + if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK ) + { + if ( value > pRegEntry->VarMax ) + { + hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum [%u > %lu]. Enforcing Maximum", + __func__, pRegEntry->RegName, value, pRegEntry->VarMax ); + value = pRegEntry->VarMax; + } + + if ( value < pRegEntry->VarMin ) + { + hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum [%u < %lu]. Enforcing Minimum", + __func__, pRegEntry->RegName, value, pRegEntry->VarMin); + value = pRegEntry->VarMin; + } + } + // If this parameter needs range checking, do it here. + else if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT ) + { + if ( value > pRegEntry->VarMax ) + { + hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum [%u > %lu]. Enforcing Default= %lu", + __func__, pRegEntry->RegName, value, pRegEntry->VarMax, pRegEntry->VarDefault ); + value = pRegEntry->VarDefault; + } + + if ( value < pRegEntry->VarMin ) + { + hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum [%u < %lu]. Enforcing Default= %lu", + __func__, pRegEntry->RegName, value, pRegEntry->VarMin, pRegEntry->VarDefault ); + value = pRegEntry->VarDefault; + } + } + + // Move the variable into the output field. + memcpy( pField, &value, pRegEntry->VarSize ); + } + else if ( WLAN_PARAM_SignedInteger == pRegEntry->RegType ) + { + // If successfully read from the registry, use the value read. + // If not, use the default value. + if (VOS_STATUS_SUCCESS == match_status) + { + rv = kstrtos32(value_str, 10, &svalue); + if (rv < 0) { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Reg Parameter %s invalid. Enforcing Default", + __func__, pRegEntry->RegName); + svalue = (v_S31_t)pRegEntry->VarDefault; + } + } + else + { + svalue = (v_S31_t)pRegEntry->VarDefault; + } + + // If this parameter needs range checking, do it here. + if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK ) + { + if ( svalue > (v_S31_t)pRegEntry->VarMax ) + { + hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum " + "[%d > %d]. Enforcing Maximum", __func__, + pRegEntry->RegName, svalue, (int)pRegEntry->VarMax ); + svalue = (v_S31_t)pRegEntry->VarMax; + } + + if ( svalue < (v_S31_t)pRegEntry->VarMin ) + { + hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum " + "[%d < %d]. Enforcing Minimum", __func__, + pRegEntry->RegName, svalue, (int)pRegEntry->VarMin); + svalue = (v_S31_t)pRegEntry->VarMin; + } + } + // If this parameter needs range checking, do it here. + else if ( pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT ) + { + if ( svalue > (v_S31_t)pRegEntry->VarMax ) + { + hddLog(LOGE, "%s: Reg Parameter %s > allowed Maximum " + "[%d > %d]. Enforcing Default= %d", + __func__, pRegEntry->RegName, svalue, + (int)pRegEntry->VarMax, + (int)pRegEntry->VarDefault ); + svalue = (v_S31_t)pRegEntry->VarDefault; + } + + if ( svalue < (v_S31_t)pRegEntry->VarMin ) + { + hddLog(LOGE, "%s: Reg Parameter %s < allowed Minimum " + "[%d < %d]. Enforcing Default= %d", + __func__, pRegEntry->RegName, svalue, + (int)pRegEntry->VarMin, + (int)pRegEntry->VarDefault); + svalue = pRegEntry->VarDefault; + } + } + + // Move the variable into the output field. + memcpy( pField, &svalue, pRegEntry->VarSize ); + } + // Handle string parameters + else if ( WLAN_PARAM_String == pRegEntry->RegType ) + { +#ifdef WLAN_CFG_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "RegName = %s, VarOffset %u VarSize %u VarDefault %s", + pRegEntry->RegName, pRegEntry->VarOffset, pRegEntry->VarSize, (char*)pRegEntry->VarDefault); +#endif + if ( match_status == VOS_STATUS_SUCCESS) + { + len_value_str = strlen(value_str); + + if(len_value_str > (pRegEntry->VarSize - 1)) { + hddLog(LOGE, "%s: Invalid Value=[%s] specified for Name=[%s] in %s", + __func__, value_str, pRegEntry->RegName, WLAN_INI_FILE); + cbOutString = utilMin( strlen( (char *)pRegEntry->VarDefault ), pRegEntry->VarSize - 1 ); + memcpy( pField, (void *)(pRegEntry->VarDefault), cbOutString ); + ( (v_U8_t *)pField )[ cbOutString ] = '\0'; + } + else + { + memcpy( pField, (void *)(value_str), len_value_str); + ( (v_U8_t *)pField )[ len_value_str ] = '\0'; + } + } + else + { + // Failed to read the string parameter from the registry. Use the default. + cbOutString = utilMin( strlen( (char *)pRegEntry->VarDefault ), pRegEntry->VarSize - 1 ); + memcpy( pField, (void *)(pRegEntry->VarDefault), cbOutString ); + ( (v_U8_t *)pField )[ cbOutString ] = '\0'; + } + } + else if ( WLAN_PARAM_MacAddr == pRegEntry->RegType ) + { + if(pRegEntry->VarSize != VOS_MAC_ADDR_SIZE) { + hddLog(LOGE, "%s: Invalid VarSize %u for Name=[%s]", + __func__, pRegEntry->VarSize, pRegEntry->RegName); + continue; + } + candidate = (char*)pRegEntry->VarDefault; + if ( match_status == VOS_STATUS_SUCCESS) { + len_value_str = strlen(value_str); + if(len_value_str != (VOS_MAC_ADDR_SIZE*2)) { + hddLog(LOGE, "%s: Invalid MAC addr [%s] specified for Name=[%s] in %s", + __func__, value_str, pRegEntry->RegName, WLAN_INI_FILE); + } + else + candidate = value_str; + } + //parse the string and store it in the byte array + for(i=0; iRegName); + } + + // did we successfully parse a cfg item for this parameter? + if( (match_status == VOS_STATUS_SUCCESS) && + (idx < MAX_CFG_INI_ITEMS) ) + { + set_bit(idx, (void *)&pHddCtx->cfg_ini->bExplicitCfg); + } + } + + print_hdd_cfg(pHddCtx); + + return( ret_status ); +} + +#ifdef WLAN_FEATURE_MBSSID +v_VOID_t hdd_mbssid_apply_def_cfg_ini(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *iniConfig = pHddCtx->cfg_ini; + mbssid_sap_dyn_ini_config_t *sap_ini_cfg = &pAdapter->sap_dyn_ini_cfg; + + sap_ini_cfg->acsScanBandPreference = iniConfig->acsScanBandPreference; + sap_ini_cfg->acsBandSwitchThreshold = iniConfig->acsBandSwitchThreshold; +} +#endif + +eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode( eHddDot11Mode dot11Mode ) +{ + switch (dot11Mode) + { + case (eHDD_DOT11_MODE_abg): + return eCSR_DOT11_MODE_abg; + case (eHDD_DOT11_MODE_11b): + return eCSR_DOT11_MODE_11b; + case (eHDD_DOT11_MODE_11g): + return eCSR_DOT11_MODE_11g; + default: + case (eHDD_DOT11_MODE_11n): + return eCSR_DOT11_MODE_11n; + case (eHDD_DOT11_MODE_11g_ONLY): + return eCSR_DOT11_MODE_11g_ONLY; + case (eHDD_DOT11_MODE_11n_ONLY): + return eCSR_DOT11_MODE_11n_ONLY; + case (eHDD_DOT11_MODE_11b_ONLY): + return eCSR_DOT11_MODE_11b_ONLY; +#ifdef WLAN_FEATURE_11AC + case (eHDD_DOT11_MODE_11ac_ONLY): + return eCSR_DOT11_MODE_11ac_ONLY; + case (eHDD_DOT11_MODE_11ac): + return eCSR_DOT11_MODE_11ac; +#else + /* If 11AC support is not compiled set Auto mode */ + case (eHDD_DOT11_MODE_11ac): + case (eHDD_DOT11_MODE_11ac_ONLY): + return eCSR_DOT11_MODE_AUTO; +#endif + case (eHDD_DOT11_MODE_AUTO): + return eCSR_DOT11_MODE_AUTO; + case (eHDD_DOT11_MODE_11a): + return eCSR_DOT11_MODE_11a; + } + +} + +static void hdd_set_btc_config(hdd_context_t *pHddCtx) +{ + hdd_config_t *pConfig = pHddCtx->cfg_ini; + tSmeBtcConfig btcParams; + int i; + + sme_BtcGetConfig(pHddCtx->hHal, &btcParams); + + btcParams.btcExecutionMode = pConfig->btcExecutionMode; + + for (i = 0; i < 6; i++) { + btcParams.mwsCoexConfig[i] = pConfig->mwsCoexConfig[i]; + } + + sme_BtcSetConfig(pHddCtx->hHal, &btcParams); +} + +static void hdd_set_power_save_config(hdd_context_t *pHddCtx, tSmeConfigParams *smeConfig) +{ + hdd_config_t *pConfig = pHddCtx->cfg_ini; + + tPmcBmpsConfigParams bmpsParams; + + sme_GetConfigPowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE, &bmpsParams); + + if (strcmp(pConfig->PowerUsageControl, "Min") == 0) + { + smeConfig->csrConfig.impsSleepTime = pConfig->nImpsMinSleepTime; + bmpsParams.bmpsPeriod = pConfig->nBmpsMinListenInterval; + bmpsParams.enableBeaconEarlyTermination = pConfig->fEnableBeaconEarlyTermination; + bmpsParams.bcnEarlyTermWakeInterval = pConfig->bcnEarlyTermWakeInterval; + } + if (strcmp(pConfig->PowerUsageControl, "Max") == 0) + { + smeConfig->csrConfig.impsSleepTime = pConfig->nImpsMaxSleepTime; + bmpsParams.bmpsPeriod = pConfig->nBmpsMaxListenInterval; + bmpsParams.enableBeaconEarlyTermination = pConfig->fEnableBeaconEarlyTermination; + bmpsParams.bcnEarlyTermWakeInterval = pConfig->bcnEarlyTermWakeInterval; + } + if (strcmp(pConfig->PowerUsageControl, "Mod") == 0) + { + smeConfig->csrConfig.impsSleepTime = pConfig->nImpsModSleepTime; + bmpsParams.bmpsPeriod = pConfig->nBmpsModListenInterval; + bmpsParams.enableBeaconEarlyTermination = pConfig->fEnableBeaconEarlyTermination; + bmpsParams.bcnEarlyTermWakeInterval = pConfig->bcnEarlyTermWakeInterval; + } + + if (pConfig->fIsImpsEnabled) + { + sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + } + else + { + sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + } + + /*If isAndroidPsEn is 1 then Host driver and above layers control the PS mechanism + If Value set to 0 Driver/Core Stack internally control the Power saving mechanism */ + sme_SetHostPowerSave (pHddCtx->hHal, pConfig->isAndroidPsEn); + + if (pConfig->fIsBmpsEnabled) + { + sme_EnablePowerSave (pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + } + else + { + sme_DisablePowerSave (pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + } + + bmpsParams.trafficMeasurePeriod = pConfig->nAutoBmpsTimerValue; + + if (sme_SetConfigPowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE, &bmpsParams)== eHAL_STATUS_FAILURE) + { + hddLog(LOGE, "SetConfigPowerSave failed to set BMPS params"); + } + + if(pConfig->fIsAutoBmpsTimerEnabled) + { + sme_StartAutoBmpsTimer(pHddCtx->hHal); + } + +} + +static void hdd_set_power_save_offload_config(hdd_context_t *pHddCtx) +{ + hdd_config_t *pConfig = pHddCtx->cfg_ini; + tANI_U32 listenInterval = 0; + + if (strcmp(pConfig->PowerUsageControl, "Min") == 0) + { + listenInterval = pConfig->nBmpsMinListenInterval; + } + else if (strcmp(pConfig->PowerUsageControl, "Max") == 0) + { + listenInterval = pConfig->nBmpsMaxListenInterval; + } + else if (strcmp(pConfig->PowerUsageControl, "Mod") == 0) + { + listenInterval = pConfig->nBmpsModListenInterval; + } + + /* + * Based on Mode Set the LI + * Otherwise default LI value of 1 will + * be taken + */ + if (listenInterval) + { + /* + * setcfg for listenInterval. + * Make sure CFG is updated because PE reads this + * from CFG at the time of assoc or reassoc + */ + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, listenInterval, + NULL, eANI_BOOLEAN_FALSE); + } + + if(pConfig->fIsBmpsEnabled) + { + sme_ConfigEnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + } + else + { + sme_ConfigDisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + } +} + +VOS_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, v_U32_t val) +{ + hdd_config_t *pConfig = pHddCtx->cfg_ini; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + hddLog(LOG1, "hdd_set_idle_ps_config: Enter Val %d", val); + + if(pConfig->fIsImpsEnabled) + { + status = sme_SetIdlePowersaveConfig(pHddCtx->pvosContext, val); + if(VOS_STATUS_SUCCESS != status) + { + hddLog(LOGE, "Fail to Set Idle PS Config val %d", val); + } + } + else + { + hddLog(LOG1, "hdd_set_idle_ps_config: IMPS not enabled in ini"); + } + return status; +} + +/** + * hdd_set_fine_time_meas_cap() - set fine timing measurement capability + * @hdd_ctx: HDD context + * @sme_config: pointer to SME config + * + * This function is used to pass fine timing measurement capability coming + * from INI to SME. This function make sure that configure INI is supported + * by the device. Use bit mask to mask out the unsupported capabilities. + * + * Return: None + */ +static void hdd_set_fine_time_meas_cap(hdd_context_t *hdd_ctx, + tSmeConfigParams *sme_config) +{ + hdd_config_t *config = hdd_ctx->cfg_ini; + uint32_t capability = config->fine_time_meas_cap; + + /* Make sure only supported capabilities are enabled in INI */ + capability &= CFG_FINE_TIME_MEAS_CAPABILITY_MAX; + sme_config->fine_time_meas_cap = capability; + + hddLog(LOG1, FL("fine time meas capability - INI: %04x Enabled: %04x"), + config->fine_time_meas_cap, sme_config->fine_time_meas_cap); + + return; +} + +/** + * hdd_convert_string_to_u8_array() - used to convert string into u8 array + * @str: String to be converted + * @hex_array: Array where converted value is stored + * @len: Length of the populated array + * @array_max_len: Maximum length of the array + * @to_hex: true, if conversion required for hex string + * + * This API is called to convert string (each byte separated by + * a comma) into an u8 array + * + * Return: VOS_STATUS + */ + +static VOS_STATUS hdd_convert_string_to_array(char *str, uint8_t *array, + uint8_t *len, uint8_t array_max_len, bool to_hex) +{ + char *format, *s = str; + + if (str == NULL || array == NULL || len == NULL) + return VOS_STATUS_E_INVAL; + + format = (to_hex) ? "%02x" : "%d"; + + *len = 0; + while ((s != NULL) && (*len < array_max_len)) { + int val; + /* Increment length only if sscanf successfully extracted + * one element. Any other return value means error. + * Ignore it. */ + if (sscanf(s, format, &val) == 1) { + array[*len] = (tANI_U8) val; + *len += 1; + } + + s = strpbrk(s, ","); + if (s) + s++; + } + + return VOS_STATUS_SUCCESS; +} + +/** + * hdd_hex_string_to_u8_array() - used to convert hex string into u8 array + * @str: Hexadecimal string + * @hex_array: Array where converted value is stored + * @len: Length of the populated array + * @array_max_len: Maximum length of the array + * + * This API is called to convert hexadecimal string (each byte separated by + * a comma) into an u8 array + * + * Return: VOS_STATUS + */ +VOS_STATUS hdd_hex_string_to_u8_array(char *str, uint8_t *hex_array, + uint8_t *len, uint8_t array_max_len) +{ + return hdd_convert_string_to_array(str, hex_array, len, + array_max_len, true); +} + +/** + * hdd_string_to_u8_array() - used to convert decimal string into u8 array + * @str: Decimal string + * @hex_array: Array where converted value is stored + * @len: Length of the populated array + * @array_max_len: Maximum length of the array + * + * This API is called to convert decimal string (each byte separated by + * a comma) into an u8 array + * + * Return: VOS_STATUS + */ + +VOS_STATUS hdd_string_to_u8_array(char *str, uint8_t *array, + uint8_t *len, uint8_t array_max_len) +{ + return hdd_convert_string_to_array(str, array, len, + array_max_len, false); +} + +/** + * hdd_hex_string_to_u16_array() - convert a hex string to a uint16 array + * @str: input string + * @int_array: pointer to input array of type uint16 + * @len: pointer to number of elements which the function adds to the array + * @int_array_max_len: maximum number of elements in input uint16 array + * + * This function is used to convert a space separated hex string to an array of + * uint16_t. For example, an input string str = "a b c d" would be converted to + * a unint16 array, int_array = {0xa, 0xb, 0xc, 0xd}, *len = 4. + * This assumes that input value int_array_max_len >= 4. + * + * Return: VOS_STATUS_SUCCESS - if the conversion is successful + * non zero value - if the conversion is a failure + */ +VOS_STATUS hdd_hex_string_to_u16_array(char *str, + uint16_t *int_array, uint8_t *len, uint8_t int_array_max_len) +{ + char *s = str; + int val = 0; + if (str == NULL || int_array == NULL || len == NULL) + return VOS_STATUS_E_INVAL; + + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("str %p intArray %p intArrayMaxLen %d"), + s, int_array, int_array_max_len); + + *len = 0; + + while ((s != NULL) && (*len < int_array_max_len)) { + /* + * Increment length only if sscanf successfully extracted one + * element. Any other return value means error. Ignore it. + */ + if (sscanf(s, "%x", &val) == 1) { + int_array[*len] = (uint16_t) val; + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("s %p val %x intArray[%d]=0x%x"), + s, val, *len, int_array[*len]); + *len += 1; + } + s = strpbrk(s, " "); + if (s) + s++; + } + return VOS_STATUS_SUCCESS; +} + +#ifdef MDNS_OFFLOAD +VOS_STATUS 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 = data; + char *field; + + if ((data == NULL) || ( datalist == NULL) || (num_entries == NULL)) + return VOS_STATUS_E_INVAL; + + /* 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 NUL to terminate the data */ + *str++ = '\0'; + strlcpy((char *)(datalist + (num * max_len_entry)), + field, max_len_entry); + num++; + } + *num_entries = num; + + return VOS_STATUS_SUCCESS; +} +#endif + +v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) +{ + v_BOOL_t fStatus = TRUE; + tANI_U32 val; + tANI_U16 val16; + + hdd_config_t *pConfig = pHddCtx->cfg_ini; + tSirMacHTCapabilityInfo *phtCapInfo; + + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SHORT_GI_20MHZ, + pConfig->ShortGI20MhzEnable, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_SHORT_GI_20MHZ to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BA_AUTO_SETUP, pConfig->BlockAckAutoSetup, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_BA_AUTO_SETUP to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_FIXED_RATE, pConfig->TxRate, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_FIXED_RATE to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_RX_AMPDU_FACTOR, + pConfig->MaxRxAmpduFactor, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Could not pass on WNI_CFG_HT_AMPDU_PARAMS_MAX_RX_AMPDU_FACTOR to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MPDU_DENSITY, + pConfig->ht_mpdu_density, NULL, eANI_BOOLEAN_FALSE) == + eHAL_STATUS_FAILURE) { + fStatus = FALSE; + hddLog(LOGE, FL("Could not pass on WNI_CFG_MPDU_DENSITY to CCM")); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SHORT_PREAMBLE, pConfig->fIsShortPreamble, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Could not pass on WNI_CFG_SHORT_PREAMBLE to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME, + pConfig->nPassiveMinChnTime, NULL, + eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME" + " to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pConfig->nPassiveMaxChnTime, NULL, + eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME" + " to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BEACON_INTERVAL, pConfig->nBeaconInterval, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_BEACON_INTERVAL to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_PS_POLL, pConfig->nMaxPsPoll, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_MAX_PS_POLL to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_CURRENT_RX_ANTENNA, pConfig-> nRxAnt, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Failure: Could not pass on WNI_CFG_CURRENT_RX_ANTENNA configuration info to HAL"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LOW_GAIN_OVERRIDE, pConfig->fIsLowGainOverride, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_LOW_GAIN_OVERRIDE to HAL"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RSSI_FILTER_PERIOD, pConfig->nRssiFilterPeriod, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_RSSI_FILTER_PERIOD to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, pConfig->fIgnoreDtim, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_IGNORE_DTIM configuration to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_ENABLE_HEART_BEAT, pConfig->fEnableFwHeartBeatMonitoring, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Failure: Could not pass on WNI_CFG_PS_HEART_BEAT configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_ENABLE_BCN_FILTER, pConfig->fEnableFwBeaconFiltering, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Failure: Could not pass on WNI_CFG_PS_BCN_FILTER configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_ENABLE_RSSI_MONITOR, pConfig->fEnableFwRssiMonitoring, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Failure: Could not pass on WNI_CFG_PS_RSSI_MONITOR configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, pConfig->nDataInactivityTimeout, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_NTH_BEACON_FILTER, pConfig->nthBeaconFilter, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_NTH_BEACON_FILTER configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_LTE_COEX, pConfig->enableLTECoex, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_LTE_COEX to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE, pConfig->nEnableListenMode, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_AP_KEEP_ALIVE_TIMEOUT, pConfig->apKeepAlivePeriod, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_AP_KEEP_ALIVE_TIMEOUT to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_GO_KEEP_ALIVE_TIMEOUT, pConfig->goKeepAlivePeriod, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_GO_KEEP_ALIVE_TIMEOUT to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_AP_LINK_MONITOR_TIMEOUT, pConfig->apLinkMonitorPeriod, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_AP_LINK_MONITOR_TIMEOUT to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_GO_LINK_MONITOR_TIMEOUT, pConfig->goLinkMonitorPeriod, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_GO_LINK_MONITOR_TIMEOUT to CCM"); + } + + +#if defined WLAN_FEATURE_VOWIFI + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MCAST_BCAST_FILTER_SETTING, pConfig->mcastBcastFilterSetting, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) +#endif + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SINGLE_TID_RC, pConfig->bSingleTidRc, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_SINGLE_TID_RC configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_WAKEUP_EN, pConfig->teleBcnWakeupEn, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_WAKEUP_EN configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_TRANS_LI, pConfig->nTeleBcnTransListenInterval, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_TRANS_LI configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_MAX_LI, pConfig->nTeleBcnMaxListenInterval, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_MAX_LI configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS, pConfig->nTeleBcnTransLiNumIdleBeacons, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS, pConfig->nTeleBcnMaxLiNumIdleBeacons, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RF_SETTLING_TIME_CLK, pConfig->rfSettlingTimeUs, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RF_SETTLING_TIME_CLK configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD, pConfig->infraStaKeepAlivePeriod, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD configuration info to CCM"); + } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DYNAMIC_PS_POLL_VALUE, pConfig->dynamicPsPollValue, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_DYNAMIC_PS_POLL_VALUE configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT, pConfig->nNullDataApRespTimeout, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_PS_NULLDATA_DELAY_TIMEOUT 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_FRAGMENTATION_THRESHOLD, pConfig->FragmentationThreshold, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_FRAGMENTATION_THRESHOLD configuration info to CCM"); + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RTS_THRESHOLD, pConfig->RTSThreshold, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_RTS_THRESHOLD configuration info to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_11D_ENABLED, pConfig->Is11dSupportEnabled, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_11D_ENABLED configuration info to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DFS_MASTER_ENABLED, + pConfig->enableDFSMasterCap, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + fStatus = FALSE; + hddLog(LOGE, + "Failure: Could not set value for WNI_CFG_DFS_MASTER_ENABLED"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + pConfig->enableTxBFin20MHz, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + fStatus = FALSE; + hddLog(LOGE, + "Failure: Could not set value for WNI_CFG_VHT_ENABLE_TXBF_20MHZ"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_HEART_BEAT_THRESHOLD, pConfig->HeartbeatThresh24, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + 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) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_CLOSE_LOOP to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TX_PWR_CTRL_ENABLE, + pConfig->enableAutomaticTxPowerControl, NULL, eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TX_PWR_CTRL_ENABLE to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SHORT_GI_40MHZ, + pConfig->ShortGI40MhzEnable, NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_SHORT_GI_40MHZ to CCM"); + } + + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_MC_ADDR_LIST, pConfig->fEnableMCAddrList, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_MC_ADDR_LIST to CCM"); + } + +#ifdef WLAN_FEATURE_11AC + /* Based on cfg.ini, update the Basic MCS set, RX/TX MCS map in the cfg.dat */ + /* valid values are 0(MCS0-7), 1(MCS0-8), 2(MCS0-9) */ + /* we update only the least significant 2 bits in the corresponding fields */ + if( (pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO) || + (pConfig->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) || + (pConfig->dot11Mode == eHDD_DOT11_MODE_11ac) ) + { + { + /* Currently shortGI40Mhz is used for shortGI80Mhz */ + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ, + pConfig->ShortGI40MhzEnable, NULL, eANI_BOOLEAN_FALSE) + == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass WNI_VHT_SHORT_GI_80MHZ to CCM"); + } + // Hardware is capable of doing 128K AMPDU in 11AC mode + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + pConfig->fVhtAmpduLenExponent, NULL, + eANI_BOOLEAN_FALSE) + == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_AMPDU_LEN_EXPONENT to CCM"); + } + + /* Change MU Bformee only when TxBF is enabled */ + if (pConfig->enableTxBF) + { + ccmCfgGetInt(pHddCtx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + &val); + + if(val != pConfig->enableMuBformee) + { + if(ccmCfgSetInt(pHddCtx->hHal, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + pConfig->enableMuBformee, NULL, + eANI_BOOLEAN_FALSE) ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_MU_BEAMFORMEE_CAP to CCM"); + } + } + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH, + pConfig->vhtMpduLen, NULL, + eANI_BOOLEAN_FALSE) + == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_MAX_MPDU_LENGTH to CCM"); + } + } + } +#endif + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_NUM_BUFF_ADVERT,pConfig->numBuffAdvert, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_NUM_BUFF_ADVERT to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_HT_RX_STBC, + pConfig->enableRxSTBC, NULL, eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_HT_RX_STBC to CCM"); + } + + ccmCfgGetInt(pHddCtx->hHal, WNI_CFG_HT_CAP_INFO, &val); + val16 = (tANI_U16)val; + phtCapInfo = (tSirMacHTCapabilityInfo *)&val16; + phtCapInfo->rxSTBC = pConfig->enableRxSTBC; + phtCapInfo->advCodingCap = pConfig->enableRxLDPC; + val = val16; + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_HT_CAP_INFO, + val, NULL, eANI_BOOLEAN_FALSE) + == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_HT_CAP_INFO to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_RXSTBC, + pConfig->enableRxSTBC, NULL, eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_RXSTBC to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_TXSTBC, + pConfig->enableTxSTBC, NULL, eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_TXSTBC to CCM"); + } + + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP, + pConfig->enableRxLDPC, NULL, eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_LDPC_CODING_CAP to CCM"); + } + +#ifdef WLAN_SOFTAP_VSTA_FEATURE + if(pConfig->fEnableVSTASupport) + { + ccmCfgGetInt(pHddCtx->hHal, WNI_CFG_ASSOC_STA_LIMIT, &val); + if( val <= WNI_CFG_ASSOC_STA_LIMIT_STADEF) + val = WNI_CFG_ASSOC_STA_LIMIT_STAMAX; + } + else + { + val = pConfig->maxNumberOfPeers; + + } + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ASSOC_STA_LIMIT, val, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE,"Failure: Could not pass on WNI_CFG_ASSOC_STA_LIMIT configuration info to CCM"); + } +#endif + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_LPWR_IMG_TRANSITION, + pConfig->enableLpwrImgTransition, NULL, eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_LPWR_IMG_TRANSITION to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, pConfig->enableMCCAdaptiveScheduler, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CCM"); + } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, pConfig->disableLDPCWithTxbfAP, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DYNAMIC_THRESHOLD_ZERO, pConfig->retryLimitZero, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_ZERO to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DYNAMIC_THRESHOLD_ONE, pConfig->retryLimitOne, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_ONE to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DYNAMIC_THRESHOLD_TWO, pConfig->retryLimitTwo, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_TWO to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_MEDIUM_TIME, pConfig->cfgMaxMediumTime, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_MAX_MEDIUM_TIME to CCM"); + } + +#ifdef FEATURE_WLAN_TDLS + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, + pConfig->fTDLSUapsdMask, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK to CCM"); + } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TDLS_BUF_STA_ENABLED, + pConfig->fEnableTDLSBufferSta, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TDLS_BUF_STA_ENABLED to CCM"); + } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TDLS_PUAPSD_INACT_TIME, + pConfig->fTDLSPuapsdInactivityTimer, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TDLS_PUAPSD_INACT_TIME to CCM"); + } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TDLS_RX_FRAME_THRESHOLD, + pConfig->fTDLSRxFrameThreshold, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TDLS_RX_FRAME_THRESHOLD to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, + pConfig->fEnableTDLSOffChannel, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TDLS_BUF_STA_ENABLED to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TDLS_WMM_MODE_ENABLED, + pConfig->fEnableTDLSWmmMode, NULL, + eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TDLS_WMM_MODE_ENABLED to CCM"); + } + +#endif + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_ADAPT_RX_DRAIN, + pConfig->fEnableAdaptRxDrain, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_ADAPT_RX_DRAIN to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_FLEX_CONNECT_POWER_FACTOR, + pConfig->flexConnectPowerFactor, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Failure: Could not pass on " + "WNI_CFG_FLEX_CONNECT_POWER_FACTOR to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ANTENNA_DIVESITY, + pConfig->antennaDiversity, NULL, + eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_ANTENNA_DIVESITY to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, + WNI_CFG_DEFAULT_RATE_INDEX_24GHZ, + pConfig->defaultRateIndex24Ghz, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_DEFAULT_RATE_INDEX_24GHZ to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, + WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL, + pConfig->debugP2pRemainOnChannel, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, + "Could not pass on WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL to CCM"); + } + +#ifdef WLAN_FEATURE_11W + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + pConfig->pmfSaQueryMaxRetries, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_SA_QUERY_MAX_RETRIES to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + pConfig->pmfSaQueryRetryInterval, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_SA_QUERY_RETRY_INTERVAL to CCM"); + } +#endif + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_ATIM_WIN_SIZE, + pConfig->ibssATIMWinSize, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"); + } + return fStatus; +} + + +/**--------------------------------------------------------------------------- + + \brief hdd_set_sme_config() - + + This function initializes the sme configuration parameters + + \param - pHddCtx - Pointer to the HDD Adapter. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + eHalStatus halStatus; + tSmeConfigParams *smeConfig; + uint8_t rrm_capab_len; + + hdd_config_t *pConfig = pHddCtx->cfg_ini; + + smeConfig = vos_mem_malloc(sizeof(*smeConfig)); + if (NULL == smeConfig) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: unable to allocate smeConfig", __func__); + return VOS_STATUS_E_NOMEM; + } + vos_mem_zero(smeConfig, sizeof(*smeConfig)); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "%s bWmmIsEnabled=%d 802_11e_enabled=%d dot11Mode=%d", __func__, + pConfig->WmmMode, pConfig->b80211eIsEnabled, pConfig->dot11Mode); + + // Config params obtained from the registry + /* To Do */ + // set regulatory information here + + smeConfig->csrConfig.RTSThreshold = pConfig->RTSThreshold; + smeConfig->csrConfig.FragmentationThreshold = pConfig->FragmentationThreshold; + smeConfig->csrConfig.shortSlotTime = pConfig->ShortSlotTimeEnabled; + smeConfig->csrConfig.Is11dSupportEnabled = pConfig->Is11dSupportEnabled; + smeConfig->csrConfig.HeartbeatThresh24 = pConfig->HeartbeatThresh24; + + smeConfig->csrConfig.phyMode = hdd_cfg_xlate_to_csr_phy_mode ( pConfig->dot11Mode ); + + if (pConfig->dot11Mode == eHDD_DOT11_MODE_abg || + pConfig->dot11Mode == eHDD_DOT11_MODE_11b || + pConfig->dot11Mode == eHDD_DOT11_MODE_11g || + pConfig->dot11Mode == eHDD_DOT11_MODE_11b_ONLY || + pConfig->dot11Mode == eHDD_DOT11_MODE_11g_ONLY) { + smeConfig->csrConfig.channelBondingMode24GHz = 0; + smeConfig->csrConfig.channelBondingMode5GHz = 0; + } else { + smeConfig->csrConfig.channelBondingMode24GHz = + pConfig->nChannelBondingMode24GHz; + smeConfig->csrConfig.channelBondingMode5GHz = + pConfig->nChannelBondingMode5GHz; + } + smeConfig->csrConfig.TxRate = pConfig->TxRate; + smeConfig->csrConfig.nScanResultAgeCount = pConfig->ScanResultAgeCount; + smeConfig->csrConfig.scanAgeTimeNCNPS = pConfig->nScanAgeTimeNCNPS; + smeConfig->csrConfig.scanAgeTimeNCPS = pConfig->nScanAgeTimeNCPS; + smeConfig->csrConfig.scanAgeTimeCNPS = pConfig->nScanAgeTimeCNPS; + smeConfig->csrConfig.scanAgeTimeCPS = pConfig->nScanAgeTimeCPS; + smeConfig->csrConfig.AdHocChannel24 = pConfig->OperatingChannel; + smeConfig->csrConfig.fEnforce11dChannels = pConfig->fEnforce11dChannels; + smeConfig->csrConfig.fSupplicantCountryCodeHasPriority = pConfig->fSupplicantCountryCodeHasPriority; + smeConfig->csrConfig.fEnforceCountryCodeMatch = pConfig->fEnforceCountryCodeMatch; + smeConfig->csrConfig.fEnforceDefaultDomain = pConfig->fEnforceDefaultDomain; + smeConfig->csrConfig.bCatRssiOffset = pConfig->nRssiCatGap; + smeConfig->csrConfig.vccRssiThreshold = pConfig->nVccRssiTrigger; + smeConfig->csrConfig.vccUlMacLossThreshold = pConfig->nVccUlMacLossThreshold; + smeConfig->csrConfig.nRoamingTime = pConfig->nRoamingTime; + smeConfig->csrConfig.IsIdleScanEnabled = pConfig->nEnableIdleScan; + smeConfig->csrConfig.nInitialDwellTime = pConfig->nInitialDwellTime; + smeConfig->csrConfig.initial_scan_no_dfs_chnl = + pConfig->initial_scan_no_dfs_chnl; + smeConfig->csrConfig.nActiveMaxChnTime = pConfig->nActiveMaxChnTime; + smeConfig->csrConfig.nActiveMinChnTime = pConfig->nActiveMinChnTime; + smeConfig->csrConfig.nPassiveMaxChnTime = pConfig->nPassiveMaxChnTime; + smeConfig->csrConfig.nPassiveMinChnTime = pConfig->nPassiveMinChnTime; + smeConfig->csrConfig.nActiveMaxChnTimeBtc = pConfig->nActiveMaxChnTimeBtc; + smeConfig->csrConfig.nActiveMinChnTimeBtc = pConfig->nActiveMinChnTimeBtc; + smeConfig->csrConfig.disableAggWithBtc = pConfig->disableAggWithBtc; +#ifdef WLAN_AP_STA_CONCURRENCY + smeConfig->csrConfig.nActiveMaxChnTimeConc = pConfig->nActiveMaxChnTimeConc; + smeConfig->csrConfig.nActiveMinChnTimeConc = pConfig->nActiveMinChnTimeConc; + smeConfig->csrConfig.nPassiveMaxChnTimeConc = pConfig->nPassiveMaxChnTimeConc; + smeConfig->csrConfig.nPassiveMinChnTimeConc = pConfig->nPassiveMinChnTimeConc; + smeConfig->csrConfig.nRestTimeConc = pConfig->nRestTimeConc; + smeConfig->csrConfig.min_rest_time_conc = pConfig->min_rest_time_conc; + smeConfig->csrConfig.idle_time_conc = pConfig->idle_time_conc; + + smeConfig->csrConfig.nNumStaChanCombinedConc = pConfig->nNumStaChanCombinedConc; + smeConfig->csrConfig.nNumP2PChanCombinedConc = pConfig->nNumP2PChanCombinedConc; + +#endif + smeConfig->csrConfig.Is11eSupportEnabled = pConfig->b80211eIsEnabled; + smeConfig->csrConfig.WMMSupportMode = pConfig->WmmMode; + /* + * -channelBondingMode5GHz is getting updated by SAP + * so stacbmode will be used for STA connection. + * -Rome STA doesnt support HT40 in 2.4Ghz so interested in only + * 5GHz configuration. + */ + smeConfig->csrConfig.stacbmode = + pConfig->nChannelBondingMode5GHz; +#if defined WLAN_FEATURE_VOWIFI + smeConfig->rrmConfig.rrm_enabled = pConfig->fRrmEnable; + smeConfig->rrmConfig.max_randn_interval = pConfig->nRrmRandnIntvl; + hdd_hex_string_to_u8_array(pConfig->rm_capability, + smeConfig->rrmConfig.rm_capability, &rrm_capab_len, + DOT11F_IE_RRMENABLEDCAP_MAX_LEN); +#endif + //Remaining config params not obtained from registry + // On RF EVB beacon using channel 1. +#ifdef WLAN_FEATURE_11AC + smeConfig->csrConfig.nVhtChannelWidth = pConfig->vhtChannelWidth; + smeConfig->csrConfig.enableTxBF = pConfig->enableTxBF; + smeConfig->csrConfig.txBFCsnValue = pConfig->txBFCsnValue; + smeConfig->csrConfig.enable2x2 = pConfig->enable2x2; + smeConfig->csrConfig.enableVhtFor24GHz = pConfig->enableVhtFor24GHzBand; + smeConfig->csrConfig.enableMuBformee = pConfig->enableMuBformee; + smeConfig->csrConfig.enableVhtpAid = pConfig->enableVhtpAid; + smeConfig->csrConfig.enableVhtGid = pConfig->enableVhtGid; +#endif + smeConfig->csrConfig.enableAmpduPs = pConfig->enableAmpduPs; + smeConfig->csrConfig.enableHtSmps = pConfig->enableHtSmps; + smeConfig->csrConfig.htSmps = pConfig->htSmps; + smeConfig->csrConfig.AdHocChannel5G = pConfig->AdHocChannel5G; + smeConfig->csrConfig.AdHocChannel24 = pConfig->AdHocChannel24G; + smeConfig->csrConfig.ProprietaryRatesEnabled = 0; + smeConfig->csrConfig.HeartbeatThresh50 = 40; + smeConfig->csrConfig.bandCapability = pConfig->nBandCapability; + if (pConfig->nBandCapability == eCSR_BAND_24) + { + smeConfig->csrConfig.Is11hSupportEnabled = 0; + } else { + smeConfig->csrConfig.Is11hSupportEnabled = pConfig->Is11hSupportEnabled; + } + smeConfig->csrConfig.cbChoice = 0; + smeConfig->csrConfig.bgScanInterval = 0; + smeConfig->csrConfig.eBand = pConfig->nBandCapability; + smeConfig->csrConfig.nTxPowerCap = pConfig->nTxPowerCap; + smeConfig->csrConfig.fEnableBypass11d = pConfig->enableBypass11d; + smeConfig->csrConfig.fEnableDFSChnlScan = pConfig->enableDFSChnlScan; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + smeConfig->csrConfig.nRoamPrefer5GHz = pConfig->nRoamPrefer5GHz; + smeConfig->csrConfig.nRoamIntraBand = pConfig->nRoamIntraBand; + smeConfig->csrConfig.nProbes = pConfig->nProbes; + + smeConfig->csrConfig.nRoamScanHomeAwayTime = pConfig->nRoamScanHomeAwayTime; +#endif + smeConfig->csrConfig.fFirstScanOnly2GChnl = pConfig->enableFirstScan2GOnly; + + //FIXME 11d config is hardcoded + if ( VOS_STA_SAP_MODE != hdd_get_conparam()) + { + smeConfig->csrConfig.Csr11dinfo.Channels.numChannels = 0; + + /* if there is a requirement that HDD will control the default + * channel list & country code (say from .ini file) we need to + * add some logic here. Otherwise the default 11d info should + * come from NV as per our current implementation */ + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "AP country Code %s", pConfig->apCntryCode); + + if (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0) + sme_setRegInfo(pHddCtx->hHal, pConfig->apCntryCode); + sme_set11dinfo(pHddCtx->hHal, smeConfig); + } + + if (!pConfig->enablePowersaveOffload) + { + hdd_set_power_save_config(pHddCtx, smeConfig); + } + else + { + hdd_set_power_save_offload_config(pHddCtx); + } + + hdd_set_btc_config(pHddCtx); + +#ifdef WLAN_FEATURE_VOWIFI_11R + smeConfig->csrConfig.csr11rConfig.IsFTResourceReqSupported = pConfig->fFTResourceReqSupported; +#endif +#ifdef FEATURE_WLAN_LFR + smeConfig->csrConfig.isFastRoamIniFeatureEnabled = pConfig->isFastRoamIniFeatureEnabled; + smeConfig->csrConfig.MAWCEnabled = pConfig->MAWCEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + smeConfig->csrConfig.isEseIniFeatureEnabled = pConfig->isEseIniFeatureEnabled; + if( pConfig->isEseIniFeatureEnabled ) + { + pConfig->isFastTransitionEnabled = TRUE; + } +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + smeConfig->csrConfig.isFastTransitionEnabled = pConfig->isFastTransitionEnabled; + smeConfig->csrConfig.RoamRssiDiff = pConfig->RoamRssiDiff; + smeConfig->csrConfig.nImmediateRoamRssiDiff = pConfig->nImmediateRoamRssiDiff; + smeConfig->csrConfig.isWESModeEnabled = pConfig->isWESModeEnabled; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + smeConfig->csrConfig.isRoamOffloadScanEnabled = pConfig->isRoamOffloadScanEnabled; + smeConfig->csrConfig.bFastRoamInConIniFeatureEnabled = pConfig->bFastRoamInConIniFeatureEnabled; + + if (0 == smeConfig->csrConfig.isRoamOffloadScanEnabled) + { + /* Disable roaming in concurrency if roam scan offload is disabled */ + smeConfig->csrConfig.bFastRoamInConIniFeatureEnabled = 0; + } +#endif +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + smeConfig->csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold; + smeConfig->csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold; + smeConfig->csrConfig.neighborRoamConfig.delay_before_vdev_stop = + pConfig->delay_before_vdev_stop; + + smeConfig->csrConfig.neighborRoamConfig.nOpportunisticThresholdDiff = + pConfig->nOpportunisticThresholdDiff; + smeConfig->csrConfig.neighborRoamConfig.nRoamRescanRssiDiff = + pConfig->nRoamRescanRssiDiff; + smeConfig->csrConfig.neighborRoamConfig.nNeighborScanMaxChanTime = pConfig->nNeighborScanMaxChanTime; + smeConfig->csrConfig.neighborRoamConfig.nNeighborScanMinChanTime = pConfig->nNeighborScanMinChanTime; + smeConfig->csrConfig.neighborRoamConfig.nNeighborScanTimerPeriod = pConfig->nNeighborScanPeriod; + smeConfig->csrConfig.neighborRoamConfig.nMaxNeighborRetries = pConfig->nMaxNeighborReqTries; + smeConfig->csrConfig.neighborRoamConfig.nNeighborResultsRefreshPeriod = pConfig->nNeighborResultsRefreshPeriod; + smeConfig->csrConfig.neighborRoamConfig.nEmptyScanRefreshPeriod = pConfig->nEmptyScanRefreshPeriod; + hdd_string_to_u8_array( pConfig->neighborScanChanList, + smeConfig->csrConfig.neighborRoamConfig.neighborScanChanList.channelList, + &smeConfig->csrConfig.neighborRoamConfig.neighborScanChanList.numChannels, + WNI_CFG_VALID_CHANNEL_LIST_LEN); + smeConfig->csrConfig.neighborRoamConfig.nRoamBmissFirstBcnt = pConfig->nRoamBmissFirstBcnt; + smeConfig->csrConfig.neighborRoamConfig.nRoamBmissFinalBcnt = pConfig->nRoamBmissFinalBcnt; + smeConfig->csrConfig.neighborRoamConfig.nRoamBeaconRssiWeight = + pConfig->nRoamBeaconRssiWeight; + smeConfig->csrConfig.neighborRoamConfig.nhi_rssi_scan_max_count = + pConfig->nhi_rssi_scan_max_count; + smeConfig->csrConfig.neighborRoamConfig.nhi_rssi_scan_rssi_delta = + pConfig->nhi_rssi_scan_rssi_delta; + smeConfig->csrConfig.neighborRoamConfig.nhi_rssi_scan_delay = + pConfig->nhi_rssi_scan_delay; + smeConfig->csrConfig.neighborRoamConfig.nhi_rssi_scan_rssi_ub = + pConfig->nhi_rssi_scan_rssi_ub; +#endif + + smeConfig->csrConfig.addTSWhenACMIsOff = pConfig->AddTSWhenACMIsOff; + smeConfig->csrConfig.fValidateList = pConfig->fValidateScanList; + smeConfig->csrConfig.allowDFSChannelRoam = pConfig->allowDFSChannelRoam; + + //Enable/Disable MCC + smeConfig->csrConfig.fEnableMCCMode = pConfig->enableMCC; + smeConfig->csrConfig.mcc_rts_cts_prot_enable = + pConfig->mcc_rts_cts_prot_enable; + smeConfig->csrConfig.mcc_bcast_prob_resp_enable = + pConfig->mcc_bcast_prob_resp_enable; + smeConfig->csrConfig.fAllowMCCGODiffBI = pConfig->allowMCCGODiffBI; + + //Scan Results Aging Time out value + smeConfig->csrConfig.scanCfgAgingTime = pConfig->scanAgingTimeout; + + smeConfig->csrConfig.enableTxLdpc = pConfig->enableTxLdpc; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + smeConfig->csrConfig.cc_switch_mode = pConfig->WlanMccToSccSwitchMode; +#endif + + smeConfig->csrConfig.max_amsdu_num = pConfig->max_amsdu_num; + smeConfig->csrConfig.nSelect5GHzMargin = pConfig->nSelect5GHzMargin; + + smeConfig->csrConfig.isCoalesingInIBSSAllowed = + pHddCtx->cfg_ini->isCoalesingInIBSSAllowed; + /* update SSR config */ + sme_UpdateEnableSSR((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->enableSSR); + /* Update the Directed scan offload setting */ + smeConfig->fScanOffload = pHddCtx->cfg_ini->fScanOffload; + + /* Update the p2p listen offload setting */ + smeConfig->fP2pListenOffload = pHddCtx->cfg_ini->fP2pListenOffload; + smeConfig->csrConfig.scanBandPreference = + pHddCtx->cfg_ini->acsScanBandPreference; + +#ifdef FEATURE_WLAN_SCAN_PNO + /* Update PNO offload status */ + smeConfig->pnoOffload = pHddCtx->cfg_ini->PnoOffload; +#endif + /* Update maximum interfaces information */ + smeConfig->max_intf_count = pHddCtx->max_intf_count; + + smeConfig->fEnableDebugLog = pHddCtx->cfg_ini->gEnableDebugLog; + + smeConfig->enable5gEBT = pHddCtx->cfg_ini->enable5gEBT; + + smeConfig->enableSelfRecovery = pHddCtx->cfg_ini->enableSelfRecovery; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + smeConfig->csrConfig.isRoamOffloadEnabled = + pHddCtx->cfg_ini->isRoamOffloadEnabled; +#endif + smeConfig->csrConfig.conc_custom_rule1 = + pHddCtx->cfg_ini->conc_custom_rule1; + smeConfig->csrConfig.conc_custom_rule2 = + pHddCtx->cfg_ini->conc_custom_rule2; + smeConfig->csrConfig.is_sta_connection_in_5gz_enabled = + pHddCtx->cfg_ini->is_sta_connection_in_5gz_enabled; + + /* Update 802.11p config */ + smeConfig->csrConfig.enable_dot11p = (pHddCtx->cfg_ini->dot11p_mode != + WLAN_HDD_11P_DISABLED); + + smeConfig->f_sta_miracast_mcc_rest_time_val = + pHddCtx->cfg_ini->sta_miracast_mcc_rest_time_val; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + smeConfig->sap_channel_avoidance = + pHddCtx->cfg_ini->sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + smeConfig->csrConfig.pkt_err_disconn_th = + pHddCtx->cfg_ini->pkt_err_disconn_th; + smeConfig->f_prefer_non_dfs_on_radar = + pHddCtx->cfg_ini->prefer_non_dfs_on_radar; + smeConfig->csrConfig.first_scan_bucket_threshold = + pHddCtx->cfg_ini->first_scan_bucket_threshold; + + vos_set_multicast_logging(pHddCtx->cfg_ini->multicast_host_fw_msgs); + hdd_set_fine_time_meas_cap(pHddCtx, smeConfig); + + smeConfig->csrConfig.sendDeauthBeforeCon = pConfig->sendDeauthBeforeCon; + smeConfig->csrConfig.ignorePeerErpInfo = pConfig->ignorePeerErpInfo; + halStatus = sme_UpdateConfig( pHddCtx->hHal, smeConfig); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + status = VOS_STATUS_E_FAILURE; + hddLog(LOGE, "sme_UpdateConfig() return failure %d", halStatus); + } + + vos_mem_free(smeConfig); + return status; +} + + +/**--------------------------------------------------------------------------- + + \brief hdd_execute_config_command() - + + This function executes an arbitrary configuration set command + + \param - pHddCtx - Pointer to the HDD Adapter. + \parmm - command - a configuration command of the form: + = + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +static VOS_STATUS hdd_execute_config_command(REG_TABLE_ENTRY *reg_table, + unsigned long tableSize, v_U8_t *ini_struct, + hdd_context_t *pHddCtx, char *command) +{ + REG_TABLE_ENTRY *pRegEntry; + char *clone; + char *pCmd; + void *pField; + char *name; + char *value_str; + v_U32_t value; + v_S31_t svalue; + size_t len_value_str; + unsigned int idx; + unsigned int i; + VOS_STATUS vstatus; + int rv; + + // assume failure until proven otherwise + vstatus = VOS_STATUS_E_FAILURE; + + // clone the command so that we can manipulate it + clone = kstrdup(command, GFP_ATOMIC); + if (NULL == clone) + { + hddLog(LOGE, "%s: memory allocation failure, unable to process [%s]", + __func__, command); + return vstatus; + } + + // 'clone' will point to the beginning of the string so it can be freed + // 'pCmd' will be used to walk/parse the command + pCmd = clone; + + // get rid of leading/trailing whitespace + pCmd = i_trim(pCmd); + if ('\0' == *pCmd) + { + // only whitespace + hddLog(LOGE, "%s: invalid command, only whitespace:[%s]", + __func__, command); + goto done; + } + + // parse the = + name = pCmd; + while (('=' != *pCmd) && ('\0' != *pCmd)) + { + pCmd++; + } + if ('\0' == *pCmd) + { + // did not find '=' + hddLog(LOGE, "%s: invalid command, no '=':[%s]", + __func__, command); + goto done; + } + + // replace '=' with NUL to terminate the + *pCmd++ = '\0'; + name = i_trim(name); + if ('\0' == *name) + { + // did not find a name + hddLog(LOGE, "%s: invalid command, no :[%s]", + __func__, command); + goto done; + } + + value_str = i_trim(pCmd); + if ('\0' == *value_str) + { + // did not find a value + hddLog(LOGE, "%s: invalid command, no :[%s]", + __func__, command); + goto done; + } + + // lookup the configuration item + for (idx = 0; idx < tableSize; idx++) + { + if (0 == strcmp(name, reg_table[idx].RegName)) + { + // found a match + break; + } + } + if (tableSize == idx) + { + // did not match the name + hddLog(LOGE, "%s: invalid command, unknown configuration item:[%s]", + __func__, command); + goto done; + } + + pRegEntry = ®_table[idx]; + if (!(pRegEntry->Flags & VAR_FLAGS_DYNAMIC_CFG)) + { + // does not support dynamic configuration + hddLog(LOGE, "%s: Global_Registry_Table.%s does not support " + "dynamic configuration", __func__, name); + vstatus = VOS_STATUS_E_PERM; + goto done; + } + + pField = ini_struct + pRegEntry->VarOffset; + + switch (pRegEntry->RegType) + { + case WLAN_PARAM_Integer: + rv = kstrtou32(value_str, 10, &value); + if (rv < 0) + goto done; + if (value < pRegEntry->VarMin) + { + // out of range + hddLog(LOGE, "%s: invalid command, value %u < min value %lu", + __func__, value, pRegEntry->VarMin); + goto done; + } + if (value > pRegEntry->VarMax) + { + // out of range + hddLog(LOGE, "%s: invalid command, value %u > max value %lu", + __func__, value, pRegEntry->VarMax); + goto done; + } + memcpy(pField, &value, pRegEntry->VarSize); + break; + + case WLAN_PARAM_HexInteger: + rv = kstrtou32(value_str, 16, &value); + if (rv < 0) + goto done; + if (value < pRegEntry->VarMin) + { + // out of range + hddLog(LOGE, "%s: invalid command, value %x < min value %lx", + __func__, value, pRegEntry->VarMin); + goto done; + } + if (value > pRegEntry->VarMax) + { + // out of range + hddLog(LOGE, "%s: invalid command, value %x > max value %lx", + __func__, value, pRegEntry->VarMax); + goto done; + } + memcpy(pField, &value, pRegEntry->VarSize); + break; + + case WLAN_PARAM_SignedInteger: + rv = kstrtos32(value_str, 10, &svalue); + if (rv < 0) + goto done; + if (svalue < (v_S31_t)pRegEntry->VarMin) + { + // out of range + hddLog(LOGE, "%s: invalid command, value %d < min value %d", + __func__, svalue, (int)pRegEntry->VarMin); + goto done; + } + if (svalue > (v_S31_t)pRegEntry->VarMax) + { + // out of range + hddLog(LOGE, "%s: invalid command, value %d > max value %d", + __func__, svalue, (int)pRegEntry->VarMax); + goto done; + } + memcpy(pField, &svalue, pRegEntry->VarSize); + break; + + case WLAN_PARAM_String: + len_value_str = strlen(value_str); + if (len_value_str > (pRegEntry->VarSize - 1)) + { + // too big + hddLog(LOGE, + "%s: invalid command, string [%s] length " + "%zu exceeds maximum length %u", + __func__, value_str, + len_value_str, (pRegEntry->VarSize - 1)); + goto done; + } + // copy string plus NUL + memcpy(pField, value_str, (len_value_str + 1)); + break; + + case WLAN_PARAM_MacAddr: + len_value_str = strlen(value_str); + if (len_value_str != (VOS_MAC_ADDR_SIZE * 2)) + { + // out of range + hddLog(LOGE, + "%s: invalid command, MAC address [%s] length " + "%zu is not expected length %u", + __func__, value_str, + len_value_str, (VOS_MAC_ADDR_SIZE * 2)); + goto done; + } + //parse the string and store it in the byte array + for (i = 0; i < VOS_MAC_ADDR_SIZE; i++) + { + ((char*)pField)[i] = (char) + ((parseHexDigit(value_str[(i * 2)]) * 16) + + parseHexDigit(value_str[(i * 2) + 1])); + } + break; + + default: + goto done; + } + + // if we get here, we had a successful modification + vstatus = VOS_STATUS_SUCCESS; + + // config table has been modified, is there a notifier? + if (NULL != pRegEntry->pfnDynamicNotify) + { + (pRegEntry->pfnDynamicNotify)(pHddCtx, pRegEntry->NotifyId); + } + + // note that this item was explicitly configured + if (idx < MAX_CFG_INI_ITEMS) + { + set_bit(idx, (void *)&pHddCtx->cfg_ini->bExplicitCfg); + } + done: + kfree(clone); + return vstatus; +} + +VOS_STATUS hdd_execute_global_config_command(hdd_context_t *pHddCtx, + char *command) +{ + return hdd_execute_config_command(g_registry_table, + ARRAY_SIZE(g_registry_table), + (v_U8_t *) pHddCtx->cfg_ini, + pHddCtx, command); +} + +#ifdef WLAN_FEATURE_MBSSID +VOS_STATUS hdd_execute_sap_dyn_config_command(hdd_adapter_t *pAdapter, + char *command) +{ + return hdd_execute_config_command(mbssid_sap_dyn_ini_reg_table, + ARRAY_SIZE(mbssid_sap_dyn_ini_reg_table), + (v_U8_t *) &pAdapter->sap_dyn_ini_cfg, + WLAN_HDD_GET_CTX(pAdapter), command); +} +#endif +/**--------------------------------------------------------------------------- + + \brief hdd_is_okc_mode_enabled() - + + This function returns whether OKC mode is enabled or not + + \param - pHddCtx - Pointer to the HDD Adapter. + + \return - 1 for enabled, zero for disabled + + --------------------------------------------------------------------------*/ + +tANI_BOOLEAN hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx) +{ + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pHddCtx is NULL", __func__); + return -EINVAL; + } + +#ifdef FEATURE_WLAN_OKC + return pHddCtx->cfg_ini->isOkcIniFeatureEnabled; +#else + return eANI_BOOLEAN_FALSE; +#endif +} + +/** + * hdd_update_nss() - configures the provided nss value to the driver + * + * @hdd_ctx: the pointer to hdd context + * @nss : the number of spatial streams to be updated + * + * Return: VOS_STATUS_SUCCESS if nss is correctly updated, + * otherwise VOS_STATUS_E_FAILURE would be returned + */ +VOS_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss) +{ + hdd_config_t *hdd_config = hdd_ctx->cfg_ini; + uint32_t temp = 0; + uint32_t rx_supp_data_rate, tx_supp_data_rate; + uint8_t status = TRUE; + tSirMacHTCapabilityInfo *ht_cap_info; + uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET] = {0}; + uint8_t mcs_set_temp[SIZE_OF_SUPPORTED_MCS_SET]; + uint32_t val; + uint16_t val16; + uint8_t enable2x2; + + if ((nss == 2) && (hdd_ctx->num_rf_chains != 2)) { + hddLog(LOGE, "No support for 2 spatial streams"); + return VOS_STATUS_E_FAILURE; + } + + enable2x2 = (nss == 1) ? 0 : 1; + + if (hdd_config->enable2x2 == enable2x2) { + hddLog(LOGE, "NSS same as requested"); + return VOS_STATUS_SUCCESS; + } + + if (TRUE == sme_is_any_session_in_connected_state(hdd_ctx->hHal)) { + hddLog(LOGE, "Connected sessions present, Do not change NSS"); + return VOS_STATUS_E_FAILURE; + } + + hdd_config->enable2x2 = enable2x2; + + if (!hdd_config->enable2x2) { + /* 1x1 */ + rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } else { + /* 2x2 */ + rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2; + tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2; + } + + /* Update Rx Highest Long GI data Rate */ + if (ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + rx_supp_data_rate, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"); + } + + /* Update Tx Highest Long GI data Rate */ + if (ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + tx_supp_data_rate, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, + "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"); + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &temp); + val16 = (uint16_t)temp; + ht_cap_info = (tSirMacHTCapabilityInfo *)&val16; + if (!(hdd_ctx->ht_tx_stbc_supported && hdd_config->enable2x2)) + ht_cap_info->txSTBC = 0; + else + ht_cap_info->txSTBC = hdd_config->enableTxSTBC; + temp = val16; + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, + temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_HT_CAP_INFO to CCM"); + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp); + temp = (temp & 0xFFFC) | hdd_config->vhtRxMCS; + if (hdd_config->enable2x2) + temp = (temp & 0xFFF3) | (hdd_config->vhtRxMCS2x2 << 2); + else + temp |= 0x000C; + + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, + temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_BASIC_MCS_SET to CCM"); + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp); + temp = (temp & 0xFFFC) | hdd_config->vhtRxMCS; + if (hdd_config->enable2x2) + temp = (temp & 0xFFF3) | (hdd_config->vhtRxMCS2x2 << 2); + else + temp |= 0x000C; + + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, + temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_RX_MCS_MAP to CCM"); + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp); + temp = (temp & 0xFFFC) | hdd_config->vhtTxMCS; + if (hdd_config->enable2x2) + temp = (temp & 0xFFF3) | (hdd_config->vhtTxMCS2x2 << 2); + else + temp |= 0x000C; + + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, + temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_TX_MCS_MAP to CCM"); + } + +#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff + val = SIZE_OF_SUPPORTED_MCS_SET; + ccmCfgGetStr(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, + mcs_set_temp, &val); + + mcs_set[0] = mcs_set_temp[0]; + if (hdd_config->enable2x2) + for (val = 0; val < nss; val++) + mcs_set[val] = WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES; + + if (ccmCfgSetStr(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, + mcs_set, SIZE_OF_SUPPORTED_MCS_SET, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + status = FALSE; + hddLog(LOGE, "Could not pass on MCS SET to CCM"); + } +#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES + + if (eHAL_STATUS_SUCCESS != sme_update_nss(hdd_ctx->hHal, nss)) + status = FALSE; + + return (status == FALSE) ? VOS_STATUS_E_FAILURE : VOS_STATUS_SUCCESS; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c new file mode 100644 index 000000000000..df76d87a0bfe --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -0,0 +1,23237 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_cfg80211.c + + \brief WLAN Host Device Driver implementation + + ========================================================================*/ + +/**========================================================================= + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 21/12/09 Ashwani Created module. + + 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID + Ganesh K + ==========================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#endif +#include +#include +#include +#include "ccmApi.h" +#include "sirParams.h" +#include "dot11f.h" +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_wext.h" +#include "sme_Api.h" +#include "wlan_hdd_p2p.h" +#include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_hostapd.h" +#include "wlan_hdd_softap_tx_rx.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_power.h" +#include "wlan_hdd_trace.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "vos_utils.h" +#include "vos_sched.h" +#include +#include "wlan_hdd_tdls.h" +#include "wlan_hdd_wmm.h" +#include "wlan_qct_wda.h" +#include "wlan_nv.h" +#include "wlan_hdd_dev_pwr.h" +#ifdef CONFIG_CNSS +#include +#endif +#include "wlan_hdd_misc.h" +#ifdef WLAN_FEATURE_NAN +#include "nan_Api.h" +#include "wlan_hdd_nan.h" +#endif +#ifdef IPA_OFFLOAD +#include +#endif +#include "wlan_hdd_mdns_offload.h" +#include "wlan_hdd_ocb.h" +#include "qwlan_version.h" + +#include "wlan_hdd_memdump.h" + +#include "wlan_logging_sock_svc.h" + +#define g_mode_rates_size (12) +#define a_mode_rates_size (8) +#define FREQ_BASE_80211G (2407) +#define FREQ_BAND_DIFF_80211G (5) +#define MAX_SCAN_SSID 10 +#define MAX_PENDING_LOG 5 +#define MAX_HT_MCS_IDX 8 +#define MAX_VHT_MCS_IDX 10 +#define INVALID_MCS_IDX 255 +#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \ + ((uintptr_t)OFFSET_OF( tSirBssDescription, ieFields))) +/* + * Android CTS verifier needs atleast this much wait time (in msec) + */ +#define MAX_REMAIN_ON_CHANNEL_DURATION (5000) +#define HDD_WAKE_LOCK_SCAN_DURATION (5 * 1000) /* in msec */ + +/* For IBSS, enable obss, fromllb, overlapOBSS & overlapFromllb protection + check. The bit map is defined in: + + typedef struct sCfgProtection + { + tANI_U32 overlapFromlla:1; + tANI_U32 overlapFromllb:1; + tANI_U32 overlapFromllg:1; + tANI_U32 overlapHt20:1; + tANI_U32 overlapNonGf:1; + tANI_U32 overlapLsigTxop:1; + tANI_U32 overlapRifs:1; + tANI_U32 overlapOBSS:1; + tANI_U32 fromlla:1; + tANI_U32 fromllb:1; + tANI_U32 fromllg:1; + tANI_U32 ht20:1; + tANI_U32 nonGf:1; + tANI_U32 lsigTxop:1; + tANI_U32 rifs:1; + tANI_U32 obss:1; + }tCfgProtection, *tpCfgProtection; + +*/ +#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282 + +#define HDD2GHZCHAN(freq, chan, flag) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (freq), \ + .hw_value = (chan),\ + .flags = (flag), \ + .max_antenna_gain = 0 ,\ + .max_power = 30, \ +} + +#define HDD5GHZCHAN(freq, chan, flag) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = (freq), \ + .hw_value = (chan),\ + .flags = (flag), \ + .max_antenna_gain = 0 ,\ + .max_power = 30, \ +} + +#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\ +{\ + .bitrate = rate, \ + .hw_value = rate_id, \ + .flags = flag, \ +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#endif + +#define HDD_CHANNEL_14 14 +#define WLAN_HDD_MAX_FEATURE_SET 8 + +#ifdef FEATURE_WLAN_EXTSCAN +/* + * Used to allocate the size of 4096 for the EXTScan NL data. + * The size of 4096 is considered assuming that all data per + * respective event fit with in the limit.Please take a call + * on the limit based on the data requirements. + */ + +#define EXTSCAN_EVENT_BUF_SIZE 4096 +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +/* + * Used to allocate the size of 4096 for the link layer stats. + * The size of 4096 is considered assuming that all data per + * respective event fit with in the limit.Please take a call + * on the limit based on the data requirements on link layer + * statistics. + */ +#define LL_STATS_EVENT_BUF_SIZE 4096 +#endif + +/* EXT TDLS */ +/* + * Used to allocate the size of 4096 for the TDLS. + * The size of 4096 is considered assuming that all data per + * respective event fit with in the limit.Please take a call + * on the limit based on the data requirements on link layer + * statistics. + */ +#define EXTTDLS_EVENT_BUF_SIZE 4096 + +static const u32 hdd_cipher_suites[] = +{ + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, +#ifdef FEATURE_WLAN_ESE +#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */ +#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */ + WLAN_CIPHER_SUITE_BTK, + WLAN_CIPHER_SUITE_KRK, + WLAN_CIPHER_SUITE_CCMP, +#else + WLAN_CIPHER_SUITE_CCMP, +#endif +#ifdef FEATURE_WLAN_WAPI + WLAN_CIPHER_SUITE_SMS4, +#endif +#ifdef WLAN_FEATURE_11W + WLAN_CIPHER_SUITE_AES_CMAC, +#endif +}; + +static struct ieee80211_channel hdd_channels_2_4_GHZ[] = +{ + HDD2GHZCHAN(2412, 1, 0) , + HDD2GHZCHAN(2417, 2, 0) , + HDD2GHZCHAN(2422, 3, 0) , + HDD2GHZCHAN(2427, 4, 0) , + HDD2GHZCHAN(2432, 5, 0) , + HDD2GHZCHAN(2437, 6, 0) , + HDD2GHZCHAN(2442, 7, 0) , + HDD2GHZCHAN(2447, 8, 0) , + HDD2GHZCHAN(2452, 9, 0) , + HDD2GHZCHAN(2457, 10, 0) , + HDD2GHZCHAN(2462, 11, 0) , + HDD2GHZCHAN(2467, 12, 0) , + HDD2GHZCHAN(2472, 13, 0) , + HDD2GHZCHAN(2484, 14, 0) , +}; + +static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] = +{ + HDD2GHZCHAN(2412, 1, 0) , + HDD2GHZCHAN(2437, 6, 0) , + HDD2GHZCHAN(2462, 11, 0) , +}; + +static struct ieee80211_channel hdd_channels_5_GHZ[] = +{ + HDD5GHZCHAN(4920, 240, 0) , + HDD5GHZCHAN(4940, 244, 0) , + HDD5GHZCHAN(4960, 248, 0) , + HDD5GHZCHAN(4980, 252, 0) , + HDD5GHZCHAN(5040, 208, 0) , + HDD5GHZCHAN(5060, 212, 0) , + HDD5GHZCHAN(5080, 216, 0) , + HDD5GHZCHAN(5180, 36, 0) , + HDD5GHZCHAN(5200, 40, 0) , + HDD5GHZCHAN(5220, 44, 0) , + HDD5GHZCHAN(5240, 48, 0) , + HDD5GHZCHAN(5260, 52, 0) , + HDD5GHZCHAN(5280, 56, 0) , + HDD5GHZCHAN(5300, 60, 0) , + HDD5GHZCHAN(5320, 64, 0) , + HDD5GHZCHAN(5500,100, 0) , + HDD5GHZCHAN(5520,104, 0) , + HDD5GHZCHAN(5540,108, 0) , + HDD5GHZCHAN(5560,112, 0) , + HDD5GHZCHAN(5580,116, 0) , + HDD5GHZCHAN(5600,120, 0) , + HDD5GHZCHAN(5620,124, 0) , + HDD5GHZCHAN(5640,128, 0) , + HDD5GHZCHAN(5660,132, 0) , + HDD5GHZCHAN(5680,136, 0) , + HDD5GHZCHAN(5700,140, 0) , +#ifdef FEATURE_WLAN_CH144 + HDD5GHZCHAN(5720,144, 0) , +#endif /* FEATURE_WLAN_CH144 */ + HDD5GHZCHAN(5745,149, 0) , + HDD5GHZCHAN(5765,153, 0) , + HDD5GHZCHAN(5785,157, 0) , + HDD5GHZCHAN(5805,161, 0) , + HDD5GHZCHAN(5825,165, 0) , +#ifndef FEATURE_STATICALLY_ADD_11P_CHANNELS + HDD5GHZCHAN(5852,170, 0) , + HDD5GHZCHAN(5855,171, 0) , + HDD5GHZCHAN(5860,172, 0) , + HDD5GHZCHAN(5865,173, 0) , + HDD5GHZCHAN(5870,174, 0) , + HDD5GHZCHAN(5875,175, 0) , + HDD5GHZCHAN(5880,176, 0) , + HDD5GHZCHAN(5885,177, 0) , + HDD5GHZCHAN(5890,178, 0) , + HDD5GHZCHAN(5895,179, 0) , + HDD5GHZCHAN(5900,180, 0) , + HDD5GHZCHAN(5905,181, 0) , + HDD5GHZCHAN(5910,182, 0) , + HDD5GHZCHAN(5915,183, 0) , + HDD5GHZCHAN(5920,184, 0) , +#endif +}; + +static struct ieee80211_rate g_mode_rates[] = +{ + HDD_G_MODE_RATETAB(10, 0x1, 0), + HDD_G_MODE_RATETAB(20, 0x2, 0), + HDD_G_MODE_RATETAB(55, 0x4, 0), + HDD_G_MODE_RATETAB(110, 0x8, 0), + HDD_G_MODE_RATETAB(60, 0x10, 0), + HDD_G_MODE_RATETAB(90, 0x20, 0), + HDD_G_MODE_RATETAB(120, 0x40, 0), + HDD_G_MODE_RATETAB(180, 0x80, 0), + HDD_G_MODE_RATETAB(240, 0x100, 0), + HDD_G_MODE_RATETAB(360, 0x200, 0), + HDD_G_MODE_RATETAB(480, 0x400, 0), + HDD_G_MODE_RATETAB(540, 0x800, 0), +}; + +static struct ieee80211_rate a_mode_rates[] = +{ + HDD_G_MODE_RATETAB(60, 0x10, 0), + HDD_G_MODE_RATETAB(90, 0x20, 0), + HDD_G_MODE_RATETAB(120, 0x40, 0), + HDD_G_MODE_RATETAB(180, 0x80, 0), + HDD_G_MODE_RATETAB(240, 0x100, 0), + HDD_G_MODE_RATETAB(360, 0x200, 0), + HDD_G_MODE_RATETAB(480, 0x400, 0), + HDD_G_MODE_RATETAB(540, 0x800, 0), +}; + +static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ = +{ + .channels = hdd_channels_2_4_GHZ, + .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ), + .band = IEEE80211_BAND_2GHZ, + .bitrates = g_mode_rates, + .n_bitrates = g_mode_rates_size, + .ht_cap.ht_supported = 1, + .ht_cap.cap = IEEE80211_HT_CAP_SGI_20 + | IEEE80211_HT_CAP_GRN_FLD + | IEEE80211_HT_CAP_DSSSCCK40 + | IEEE80211_HT_CAP_LSIG_TXOP_PROT + | IEEE80211_HT_CAP_SGI_40 + | IEEE80211_HT_CAP_SUP_WIDTH_20_40, + .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ), + .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, + .vht_cap.cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 + | IEEE80211_VHT_CAP_SHORT_GI_80 + | IEEE80211_VHT_CAP_TXSTBC +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0)) || defined(WITH_BACKPORTS) + | (IEEE80211_VHT_CAP_RXSTBC_MASK & + ( IEEE80211_VHT_CAP_RXSTBC_1 + | IEEE80211_VHT_CAP_RXSTBC_2)) +#endif + | IEEE80211_VHT_CAP_RXLDPC, +}; + +static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ = +{ + .channels = hdd_social_channels_2_4_GHZ, + .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ), + .band = IEEE80211_BAND_2GHZ, + .bitrates = g_mode_rates, + .n_bitrates = g_mode_rates_size, + .ht_cap.ht_supported = 1, + .ht_cap.cap = IEEE80211_HT_CAP_SGI_20 + | IEEE80211_HT_CAP_GRN_FLD + | IEEE80211_HT_CAP_DSSSCCK40 + | IEEE80211_HT_CAP_LSIG_TXOP_PROT, + .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ), + .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, +}; + +static struct ieee80211_supported_band wlan_hdd_band_5_GHZ = +{ + .channels = hdd_channels_5_GHZ, + .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ), + .band = IEEE80211_BAND_5GHZ, + .bitrates = a_mode_rates, + .n_bitrates = a_mode_rates_size, + .ht_cap.ht_supported = 1, + .ht_cap.cap = IEEE80211_HT_CAP_SGI_20 + | IEEE80211_HT_CAP_GRN_FLD + | IEEE80211_HT_CAP_DSSSCCK40 + | IEEE80211_HT_CAP_LSIG_TXOP_PROT + | IEEE80211_HT_CAP_SGI_40 + | IEEE80211_HT_CAP_SUP_WIDTH_20_40, + .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, + .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ), + .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, + .vht_cap.vht_supported = 1, + .vht_cap.cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 + | IEEE80211_VHT_CAP_SHORT_GI_80 + | IEEE80211_VHT_CAP_TXSTBC +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0)) + | (IEEE80211_VHT_CAP_RXSTBC_MASK & + ( IEEE80211_VHT_CAP_RXSTBC_1 + | IEEE80211_VHT_CAP_RXSTBC_2)) +#endif + | IEEE80211_VHT_CAP_RXLDPC +}; + +/* This structure contain information what kind of frame are expected in + TX/RX direction for each kind of interface */ +static const struct ieee80211_txrx_stypes +wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(SIR_MAC_MGMT_ACTION) | + BIT(SIR_MAC_MGMT_PROBE_REQ), + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) | + BIT(SIR_MAC_MGMT_REASSOC_REQ) | + BIT(SIR_MAC_MGMT_PROBE_REQ) | + BIT(SIR_MAC_MGMT_DISASSOC) | + BIT(SIR_MAC_MGMT_AUTH) | + BIT(SIR_MAC_MGMT_DEAUTH) | + BIT(SIR_MAC_MGMT_ACTION), + }, + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) | + BIT(SIR_MAC_MGMT_REASSOC_REQ) | + BIT(SIR_MAC_MGMT_PROBE_REQ) | + BIT(SIR_MAC_MGMT_DISASSOC) | + BIT(SIR_MAC_MGMT_AUTH) | + BIT(SIR_MAC_MGMT_DEAUTH) | + BIT(SIR_MAC_MGMT_ACTION), + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(SIR_MAC_MGMT_ACTION) | + BIT(SIR_MAC_MGMT_PROBE_REQ), + }, + [NL80211_IFTYPE_P2P_GO] = { + /* This is also same as for SoftAP */ + .tx = 0xffff, + .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) | + BIT(SIR_MAC_MGMT_REASSOC_REQ) | + BIT(SIR_MAC_MGMT_PROBE_REQ) | + BIT(SIR_MAC_MGMT_DISASSOC) | + BIT(SIR_MAC_MGMT_AUTH) | + BIT(SIR_MAC_MGMT_DEAUTH) | + BIT(SIR_MAC_MGMT_ACTION), + }, +}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) || defined(WITH_BACKPORTS) +/* Interface limits and combinations registered by the driver */ + +/* STA ( + STA ) combination */ +static const struct ieee80211_iface_limit +wlan_hdd_sta_iface_limit[] = { + { + .max = 3, /* p2p0 is a STA as well */ + .types = BIT(NL80211_IFTYPE_STATION), + }, +}; + +/* ADHOC (IBSS) limit */ +static const struct ieee80211_iface_limit +wlan_hdd_adhoc_iface_limit[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_ADHOC), + }, +}; + +/* AP ( + AP ) combination */ +static const struct ieee80211_iface_limit +wlan_hdd_ap_iface_limit[] = { + { + .max = (VOS_MAX_NO_OF_SAP_MODE + + SAP_MAX_OBSS_STA_CNT), + .types = BIT(NL80211_IFTYPE_AP), + }, +}; + +/* P2P limit */ +static const struct ieee80211_iface_limit +wlan_hdd_p2p_iface_limit[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_CLIENT), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO), + }, +}; + +static const struct ieee80211_iface_limit +wlan_hdd_sta_ap_iface_limit[] = { + { + /* We need 1 extra STA interface for OBSS scan when SAP starts + * with HT40 in STA+SAP concurrency mode + */ + .max = (1 + SAP_MAX_OBSS_STA_CNT), + .types = BIT(NL80211_IFTYPE_STATION), + }, + { + .max = VOS_MAX_NO_OF_SAP_MODE, + .types = BIT(NL80211_IFTYPE_AP), + }, +}; + +/* STA + P2P combination */ +static const struct ieee80211_iface_limit +wlan_hdd_sta_p2p_iface_limit[] = { + { + /* One reserved for dedicated P2PDEV usage */ + .max = 2, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + /* Support for two identical (GO + GO or CLI + CLI) + * or dissimilar (GO + CLI) P2P interfaces + */ + .max = 2, + .types = BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_CLIENT), + }, +}; + +/* STA + AP + P2PGO combination */ +static const struct ieee80211_iface_limit +wlan_hdd_sta_ap_p2pgo_iface_limit[] = { + /* Support for AP+P2PGO interfaces */ + { + .max = 2, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) + } +}; + +static struct ieee80211_iface_combination +wlan_hdd_iface_combination[] = { + /* STA */ + { + .limits = wlan_hdd_sta_iface_limit, + .num_different_channels = 2, + .max_interfaces = 3, + .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit), + }, + /* ADHOC */ + { + .limits = wlan_hdd_adhoc_iface_limit, + .num_different_channels = 1, + .max_interfaces = 2, + .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit), + }, + /* AP */ + { + .limits = wlan_hdd_ap_iface_limit, + .num_different_channels = 2, + .max_interfaces = (SAP_MAX_OBSS_STA_CNT + + VOS_MAX_NO_OF_SAP_MODE), + .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit), + }, + /* P2P */ + { + .limits = wlan_hdd_p2p_iface_limit, + .num_different_channels = 2, + .max_interfaces = 2, + .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit), + }, + /* STA + AP */ + { + .limits = wlan_hdd_sta_ap_iface_limit, + .num_different_channels = 2, + .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + + VOS_MAX_NO_OF_SAP_MODE), + .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit), + .beacon_int_infra_match = true, + }, + /* STA + P2P */ + { + .limits = wlan_hdd_sta_p2p_iface_limit, + .num_different_channels = 2, + /* one interface reserved for P2PDEV dedicated usage */ + .max_interfaces = 4, + .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit), + .beacon_int_infra_match = true, + }, + /* STA + P2P GO + SAP */ + { + .limits = wlan_hdd_sta_ap_p2pgo_iface_limit, + /* we can allow 3 channels for three different persona + * but due to firmware limitation, allow max 2 concurrent channels. + */ + .num_different_channels = 2, + /* one interface reserved for P2PDEV dedicated usage */ + .max_interfaces = 4, + .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit), + .beacon_int_infra_match = true, + }, +}; +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) || + defined(WITH_BACKPORTS) */ + + +static struct cfg80211_ops wlan_hdd_cfg80211_ops; + +/* Data rate 100KBPS based on IE Index */ +struct index_data_rate_type +{ + v_U8_t beacon_rate_index; + v_U16_t supported_rate[4]; +}; + +/* 11B, 11G Rate table include Basic rate and Extended rate + The IDX field is the rate index + The HI field is the rate when RSSI is strong or being ignored + (in this case we report actual rate) + The MID field is the rate when RSSI is moderate + (in this case we cap 11b rates at 5.5 and 11g rates at 24) + The LO field is the rate when RSSI is low + (in this case we don't report rates, actual current rate used) + */ +static const struct +{ + v_U8_t beacon_rate_index; + v_U16_t supported_rate[4]; +} supported_data_rate[] = +{ +/* IDX HI HM LM LO (RSSI-based index */ + {2, { 10, 10, 10, 0}}, + {4, { 20, 20, 10, 0}}, + {11, { 55, 20, 10, 0}}, + {12, { 60, 55, 20, 0}}, + {18, { 90, 55, 20, 0}}, + {22, {110, 55, 20, 0}}, + {24, {120, 90, 60, 0}}, + {36, {180, 120, 60, 0}}, + {44, {220, 180, 60, 0}}, + {48, {240, 180, 90, 0}}, + {66, {330, 180, 90, 0}}, + {72, {360, 240, 90, 0}}, + {96, {480, 240, 120, 0}}, + {108, {540, 240, 120, 0}} +}; + +/* MCS Based rate table */ +/* HT MCS parameters with Nss = 1 */ +static struct index_data_rate_type supported_mcs_rate_nss1[] = +{ +/* MCS L20 L40 S20 S40 */ + {0, {65, 135, 72, 150}}, + {1, {130, 270, 144, 300}}, + {2, {195, 405, 217, 450}}, + {3, {260, 540, 289, 600}}, + {4, {390, 810, 433, 900}}, + {5, {520, 1080, 578, 1200}}, + {6, {585, 1215, 650, 1350}}, + {7, {650, 1350, 722, 1500}} +}; +/* HT MCS parameters with Nss = 2 */ +static struct index_data_rate_type supported_mcs_rate_nss2[] = +{ +/* MCS L20 L40 S20 S40 */ + {0, {130, 270, 144, 300}}, + {1, {260, 540, 289, 600}}, + {2, {390, 810, 433, 900}}, + {3, {520, 1080, 578, 1200}}, + {4, {780, 1620, 867, 1800}}, + {5, {1040, 2160, 1156, 2400}}, + {6, {1170, 2430, 1300, 2700}}, + {7, {1300, 2700, 1444, 3000}} +}; + +#ifdef WLAN_FEATURE_11AC + +#define DATA_RATE_11AC_MCS_MASK 0x03 + +struct index_vht_data_rate_type +{ + v_U8_t beacon_rate_index; + v_U16_t supported_VHT80_rate[2]; + v_U16_t supported_VHT40_rate[2]; + v_U16_t supported_VHT20_rate[2]; +}; + +typedef enum +{ + DATA_RATE_11AC_MAX_MCS_7, + DATA_RATE_11AC_MAX_MCS_8, + DATA_RATE_11AC_MAX_MCS_9, + DATA_RATE_11AC_MAX_MCS_NA +} eDataRate11ACMaxMcs; + +/* SSID broadcast type */ +typedef enum eSSIDBcastType +{ + eBCAST_UNKNOWN = 0, + eBCAST_NORMAL = 1, + eBCAST_HIDDEN = 2, +} tSSIDBcastType; + +/* MCS Based VHT rate table */ +/* MCS parameters with Nss = 1*/ +static struct index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = +{ +/* MCS L80 S80 L40 S40 L20 S40*/ + {0, {293, 325}, {135, 150}, {65, 72}}, + {1, {585, 650}, {270, 300}, {130, 144}}, + {2, {878, 975}, {405, 450}, {195, 217}}, + {3, {1170, 1300}, {540, 600}, {260, 289}}, + {4, {1755, 1950}, {810, 900}, {390, 433}}, + {5, {2340, 2600}, {1080, 1200}, {520, 578}}, + {6, {2633, 2925}, {1215, 1350}, {585, 650}}, + {7, {2925, 3250}, {1350, 1500}, {650, 722}}, + {8, {3510, 3900}, {1620, 1800}, {780, 867}}, + {9, {3900, 4333}, {1800, 2000}, {780, 867}} +}; + +/*MCS parameters with Nss = 2*/ +static struct index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = +{ +/* MCS L80 S80 L40 S40 L20 S40*/ + {0, {585, 650}, {270, 300}, {130, 144}}, + {1, {1170, 1300}, {540, 600}, {260, 289}}, + {2, {1755, 1950}, {810, 900}, {390, 433}}, + {3, {2340, 2600}, {1080, 1200}, {520, 578}}, + {4, {3510, 3900}, {1620, 1800}, {780, 867}}, + {5, {4680, 5200}, {2160, 2400}, {1040, 1156}}, + {6, {5265, 5850}, {2430, 2700}, {1170, 1300}}, + {7, {5850, 6500}, {2700, 3000}, {1300, 1444}}, + {8, {7020, 7800}, {3240, 3600}, {1560, 1733}}, + {9, {7800, 8667}, {3600, 4000}, {1560, 1733}} +}; +#endif /* WLAN_FEATURE_11AC */ + +/* Array index points to MCS and array value points respective rssi */ +static int rssiMcsTbl[][10] = +{ +/*MCS 0 1 2 3 4 5 6 7 8 9*/ + {-82, -79, -77, -74, -70, -66, -65, -64, -59, -57}, //20 + {-79, -76, -74, -71, -67, -63, -62, -61, -56, -54}, //40 + {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} //80 +}; + +extern struct net_device_ops net_ops_struct; + +#ifdef WLAN_NL80211_TESTMODE +enum wlan_hdd_tm_attr +{ + WLAN_HDD_TM_ATTR_INVALID = 0, + WLAN_HDD_TM_ATTR_CMD = 1, + WLAN_HDD_TM_ATTR_DATA = 2, + WLAN_HDD_TM_ATTR_STREAM_ID = 3, + WLAN_HDD_TM_ATTR_TYPE = 4, + /* keep last */ + WLAN_HDD_TM_ATTR_AFTER_LAST, + WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1, +}; + +enum wlan_hdd_tm_cmd +{ + WLAN_HDD_TM_CMD_WLAN_FTM = 0, + WLAN_HDD_TM_CMD_WLAN_HB = 1, +}; + +#define WLAN_HDD_TM_DATA_MAX_LEN 5000 + +static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = +{ + [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 }, + [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY, + .len = WLAN_HDD_TM_DATA_MAX_LEN }, +}; +#endif /* WLAN_NL80211_TESTMODE */ + +#ifdef FEATURE_WLAN_EXTSCAN + +static const struct nla_policy +wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = +{ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = { .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 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = { .type = NLA_U8 }, + + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = { .type = NLA_U8 }, + + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = { .type = NLA_UNSPEC }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN }, + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD] = { .type = NLA_S8 }, + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN + 1 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = { .type = NLA_U32 }, +}; + +static const struct nla_policy +wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = +{ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = { .type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = { .type = NLA_U16 }, +}; + + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) +static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = { + .flags = WIPHY_WOWLAN_MAGIC_PKT, + .n_patterns = WOWL_MAX_PTRNS_ALLOWED, + .pattern_min_len = 1, + .pattern_max_len = WOWL_PTRN_MAX_SIZE, +}; +#endif + +#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC) +/* + * FUNCTION: wlan_hdd_send_avoid_freq_event + * This is called when wlan driver needs to send vendor specific + * avoid frequency range event to user space + */ +int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, + tHddAvoidFreqList *pAvoidFreqList) +{ + struct sk_buff *vendor_event; + + ENTER(); + + if (!pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is null", __func__); + return -1; + } + + if (!pAvoidFreqList) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: pAvoidFreqList is null", __func__); + return -1; + } + + vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + sizeof(tHddAvoidFreqList), + QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX, + GFP_KERNEL); + if (!vendor_event) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: cfg80211_vendor_event_alloc failed", __func__); + return -1; + } + + memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)), + (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList)); + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + EXIT(); + return 0; +} +#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */ + +#ifdef WLAN_FEATURE_NAN +/** + * __wlan_hdd_cfg80211_nan_request() - handle NAN request + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This function is called by userspace to send a NAN request to + * firmware. + * + * Return: 0 on success, negative errno on failure + */ +static int __wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) + +{ + tNanRequestReq nan_req; + VOS_STATUS status; + int ret_val = -EINVAL; + 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; + } + + if (!hdd_ctx->cfg_ini->enable_nan_support) { + hddLog(LOGE, FL("NaN is not suported")); + return -EPERM; + } + + nan_req.request_data_len = data_len; + nan_req.request_data = data; + + status = sme_NanRequest(&nan_req); + if (VOS_STATUS_SUCCESS != status) { + ret_val = -EINVAL; + } + return ret_val; +} + +/** + * wlan_hdd_cfg80211_nan_request() - handle NAN request + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This function is called by userspace to send a NAN request to + * firmware. This is an SSR-protected wrapper function. + * + * Return: 0 on success, negative errno on failure + */ +static int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) + +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_nan_request(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_nan_callback + * This is a callback function and it gets called + * when we need to report nan response event to + * upper layers. + */ +static void wlan_hdd_cfg80211_nan_callback(void* ctx, tSirNanEvent* msg) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *vendor_event; + int status; + tSirNanEvent *data; + + if (NULL == msg) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL(" msg received here is null")); + return; + } + data = msg; + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return; + } + + vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + data->event_data_len + + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return; + } + if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NAN, + data->event_data_len, data->event_data)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR_NAN put fail")); + kfree_skb(vendor_event); + return; + } + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +} + +/* + * FUNCTION: wlan_hdd_cfg80211_nan_init + * This function is called to register the callback to sme layer + */ +void wlan_hdd_cfg80211_nan_init(hdd_context_t *pHddCtx) +{ + sme_NanRegisterCallback(pHddCtx->hHal, wlan_hdd_cfg80211_nan_callback); +} + +#endif + +#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 */ + +/* vendor specific events */ +static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = +{ +#ifdef FEATURE_WLAN_CH_AVOID + [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY + }, +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef WLAN_FEATURE_NAN + [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN + }, +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT + }, +#endif /* WLAN_FEATURE_STATS_EXT */ +#ifdef FEATURE_WLAN_EXTSCAN + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST + }, +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET + }, + [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET + }, + [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR + }, + [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS + }, + [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS + }, + [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS + }, +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +/* EXT TDLS */ + [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE + }, + [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS + }, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH + }, +#endif + [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED + }, + [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED + }, + [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED + }, + [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED + }, + [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED + }, +#ifdef FEATURE_WLAN_EXTSCAN + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST + }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST + }, +#endif /* FEATURE_WLAN_EXTSCAN */ + /* OCB events */ + [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT + }, +#ifdef WLAN_FEATURE_MEMDUMP + [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP + }, +#endif /* WLAN_FEATURE_MEMDUMP */ + [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI + }, +}; + +/** + * __is_driver_dfs_capable() - get driver DFS capability + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This function is called by userspace to indicate whether or not + * the driver supports DFS offload. + * + * Return: 0 on success, negative errno on failure + */ +static int __is_driver_dfs_capable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + u32 dfs_capability = 0; + struct sk_buff *temp_skbuff; + 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; + } + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0)) || \ + defined (DFS_MASTER_OFFLOAD_IND_SUPPORT) || defined(WITH_BACKPORTS) + dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD); +#endif + + temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + NLMSG_HDRLEN); + + if (temp_skbuff != NULL) + { + + ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS, + dfs_capability); + if (ret_val) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: QCA_WLAN_VENDOR_ATTR_DFS put fail", __func__); + kfree_skb(temp_skbuff); + + return ret_val; + } + + return cfg80211_vendor_cmd_reply(temp_skbuff); + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: dfs capability: buffer alloc fail", __func__); + return -ENOMEM; +} + +/** + * is_driver_dfs_capable() - get driver DFS capability + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This function is called by userspace to indicate whether or not + * the driver supports DFS offload. This is an SSR-protected + * wrapper function. + * + * Return: 0 on success, negative errno on failure + */ +static int is_driver_dfs_capable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + + +static int +__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct sk_buff *skb = NULL; + tANI_U32 fset = 0; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return -EINVAL; + + if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { + hddLog(LOG1, FL("Infra Station mode is supported by driver")); + fset |= WIFI_FEATURE_INFRA; + } + + if (TRUE == hdd_is_5g_supported(pHddCtx)) { + hddLog(LOG1, FL("INFRA_5G is supported by firmware")); + fset |= WIFI_FEATURE_INFRA_5G; + } + +#ifdef WLAN_FEATURE_P2P + if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) && + (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) { + hddLog(LOG1, FL("WiFi-Direct is supported by driver")); + fset |= WIFI_FEATURE_P2P; + } +#endif + + /* Soft-AP is supported currently by default */ + fset |= WIFI_FEATURE_SOFT_AP; + + /* HOTSPOT is a supplicant feature, enable it by default */ + fset |= WIFI_FEATURE_HOTSPOT; + +#ifdef FEATURE_WLAN_EXTSCAN + if (sme_IsFeatureSupportedByFW(EXTENDED_SCAN)) { + hddLog(LOG1, FL("EXTScan is supported by firmware")); + fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO; + } +#endif + +#ifdef WLAN_FEATURE_NAN + if (sme_IsFeatureSupportedByFW(NAN)) { + hddLog(LOG1, FL("NAN is supported by firmware")); + fset |= WIFI_FEATURE_NAN; + } +#endif + + if (sme_IsFeatureSupportedByFW(RTT)) { + hddLog(LOG1, FL("RTT is supported by firmware")); + fset |= WIFI_FEATURE_D2D_RTT; + fset |= WIFI_FEATURE_D2AP_RTT; + } + +#ifdef FEATURE_WLAN_SCAN_PNO + if (pHddCtx->cfg_ini->configPNOScanSupport && + sme_IsFeatureSupportedByFW(PNO)) { + hddLog(LOG1, FL("PNO is supported by firmware")); + fset |= WIFI_FEATURE_PNO; + } +#endif + + /* STA+STA is supported currently by default */ + fset |= WIFI_FEATURE_ADDITIONAL_STA; + +#ifdef FEATURE_WLAN_TDLS + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSSupport) && + sme_IsFeatureSupportedByFW(TDLS)) { + hddLog(LOG1, FL("TDLS is supported by firmware")); + fset |= WIFI_FEATURE_TDLS; + } + + if (sme_IsFeatureSupportedByFW(TDLS) && + (TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + sme_IsFeatureSupportedByFW(TDLS_OFF_CHANNEL)) { + hddLog(LOG1, FL("TDLS off-channel is supported by firmware")); + fset |= WIFI_FEATURE_TDLS_OFFCHANNEL; + } +#endif + +#ifdef WLAN_AP_STA_CONCURRENCY + /* AP+STA concurrency is supported currently by default */ + fset |= WIFI_FEATURE_AP_STA; +#endif + fset |= WIFI_FEATURE_RSSI_MONITOR; + + if (hdd_link_layer_stats_supported()) + fset |= WIFI_FEATURE_LINK_LAYER_STATS; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) + + NLMSG_HDRLEN); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -EINVAL; + } + hddLog(LOG1, FL("Supported Features : 0x%x"), fset); + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) { + hddLog(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + ret = cfg80211_vendor_cmd_reply(skb); + EXIT(); + return ret; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_get_supported_features() - get supported features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Set the MAC address that is to be used for scanning. + * + * Return: Return the Success or Failure code. + */ +static int +__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirScanMacOui pReqMsg = NULL; + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1]; + eHalStatus status; + int ret; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (FALSE == pHddCtx->cfg_ini->enable_mac_spoofing) { + hddLog(LOGW, FL("MAC address spoofing is not enabled")); + return -ENOTSUPP; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX, + data, data_len, + NULL)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch oui */ + if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) { + hddLog(LOGE, FL("attr mac oui failed")); + goto fail; + } + + nla_memcpy(&pReqMsg->oui[0], + tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI], + sizeof(pReqMsg->oui)); + + hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0], pReqMsg->oui[1], + pReqMsg->oui[2]); + + status = sme_SetScanningMacOui(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("sme_SetScanningMacOui failed(err=%d)"), status); + goto fail; + } + + return 0; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Set the MAC address that is to be used for scanning. This is an + * SSR-protecting wrapper function. + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int +__wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint32_t feature_set_matrix[WLAN_HDD_MAX_FEATURE_SET] = {0}; + uint8_t i, feature_sets, max_feature_sets; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1]; + struct sk_buff *reply_skb; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int ret; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX, + data, data_len, NULL)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch max feature set */ + if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) { + hddLog(LOGE, FL("Attr max feature set size failed")); + return -EINVAL; + } + max_feature_sets = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]); + hddLog(LOG1, FL("Max feature set size (%d)"), max_feature_sets); + + /* Fill feature combination matrix */ + feature_sets = 0; + feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA | + WIFI_FEATURE_P2P; + + /* Add more feature combinations here */ + + feature_sets = VOS_MIN(feature_sets, max_feature_sets); + hddLog(LOG1, FL("Number of feature sets (%d)"), feature_sets); + hddLog(LOG1, "Feature set matrix"); + for (i = 0; i < feature_sets; i++) + hddLog(LOG1, "[%d] 0x%02X", i, feature_set_matrix[i]); + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + sizeof(u32) * feature_sets + + NLMSG_HDRLEN); + + if (reply_skb) { + if (nla_put_u32(reply_skb, + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE, + feature_sets) || + nla_put(reply_skb, + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET, + sizeof(u32) * feature_sets, feature_set_matrix)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(reply_skb); + return -EINVAL; + } + + ret = cfg80211_vendor_cmd_reply(reply_skb); + EXIT(); + return ret; + } + hddLog(LOGE, FL("Feature set matrix: buffer alloc fail")); + return -ENOMEM; +} + +/** + * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + return ret; +} + +static int +__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + uint8_t session_id; + struct roam_ext_params roam_params; + uint32_t cmd_type, req_id; + struct nlattr *curr_attr; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + data, data_len, + NULL)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + /* Parse and fetch Command Type*/ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) { + hddLog(LOGE, FL("roam cmd type failed")); + goto fail; + } + session_id = pAdapter->sessionId; + vos_mem_set(&roam_params, sizeof(roam_params),0); + cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]); + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + req_id = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]); + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id); + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type); + switch(cmd_type) { + case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST: + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST], + rem) { + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX, + nla_data(curr_attr), nla_len(curr_attr), + NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + /* Parse and Fetch allowed SSID list*/ + if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) { + hddLog(LOGE, FL("attr allowed ssid failed")); + goto fail; + } + buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]); + /* + * Upper Layers include a null termination character. + * Check for the actual permissible length of SSID and + * also ensure not to copy the NULL termination + * character to the driver buffer. + */ + if (buf_len && (i < MAX_SSID_ALLOWED_LIST) && + ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) { + nla_memcpy(roam_params.ssid_allowed_list[i].ssId, + tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID], + buf_len - 1); + roam_params.ssid_allowed_list[i].length = + buf_len - 1; + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("SSID[%d]: %.*s,length = %d"), i, + roam_params.ssid_allowed_list[i].length, + roam_params.ssid_allowed_list[i].ssId, + roam_params.ssid_allowed_list[i].length); + i++; + } + else { + hddLog(LOGE, FL("Invalid SSID len %d,idx %d"), + buf_len, i); + } + } + roam_params.num_ssid_allowed_list = i; + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"), + roam_params.num_ssid_allowed_list); + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_SSID_ALLOWED); + break; + case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS: + /* Parse and fetch 5G Boost Threshold */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) { + hddLog(LOGE, FL("5G boost threshold failed")); + goto fail; + } + roam_params.raise_rssi_thresh_5g = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("5G Boost Threshold (%d)"), + roam_params.raise_rssi_thresh_5g); + /* Parse and fetch 5G Penalty Threshold */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) { + hddLog(LOGE, FL("5G penalty threshold failed")); + goto fail; + } + roam_params.drop_rssi_thresh_5g = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("5G Penalty Threshold (%d)"), + roam_params.drop_rssi_thresh_5g); + /* Parse and fetch 5G Boost Factor */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) { + hddLog(LOGE, FL("5G boost Factor failed")); + goto fail; + } + roam_params.raise_factor_5g = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]); + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"), + roam_params.raise_factor_5g); + /* Parse and fetch 5G Penalty factor */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) { + hddLog(LOGE, FL("5G Penalty Factor failed")); + goto fail; + } + roam_params.drop_factor_5g = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("5G Penalty factor (%d)"), + roam_params.drop_factor_5g); + /* Parse and fetch 5G Max Boost */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) { + hddLog(LOGE, FL("5G Max Boost failed")); + goto fail; + } + roam_params.max_raise_rssi_5g = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]); + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"), + roam_params.max_raise_rssi_5g); + /* Parse and fetch Rssi Diff */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) { + hddLog(LOGE, FL("Rssi Diff failed")); + goto fail; + } + roam_params.rssi_diff = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]); + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"), + roam_params.rssi_diff); + /* Parse and fetch Good Rssi Threshold */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) { + hddLog(LOGE, FL("Alert Rssi Threshold failed")); + goto fail; + } + roam_params.alert_rssi_threshold = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("Alert RSSI Threshold (%d)"), + roam_params.alert_rssi_threshold); + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, + REASON_ROAM_EXT_SCAN_PARAMS_CHANGED); + break; + case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM: + /* Parse and fetch Activate Good Rssi Roam */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) { + hddLog(LOGE, FL("Activate Good Rssi Roam failed")); + goto fail; + } + roam_params.good_rssi_roam = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("Activate Good Rssi Roam (%d)"), + roam_params.good_rssi_roam); + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_GOOD_RSSI_CHANGED); + break; + case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS: + /* Parse and fetch number of preferred BSSID */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) { + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } + roam_params.num_bssid_favored = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("Num of Preferred BSSID (%d)"), + roam_params.num_bssid_favored); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), + NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + /* Parse and fetch MAC address */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) { + hddLog(LOGE, FL("attr mac address failed")); + goto fail; + } + nla_memcpy(roam_params.bssid_favored[i], + tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID], + sizeof(tSirMacAddr)); + hddLog(VOS_TRACE_LEVEL_DEBUG, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(roam_params.bssid_favored[i])); + /* Parse and fetch preference factor*/ + if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) { + hddLog(LOGE, FL("BSSID Preference score failed")); + goto fail; + } + roam_params.bssid_favored_factor[i] = nla_get_u32( + tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("BSSID Preference score (%d)"), + roam_params.bssid_favored_factor[i]); + i++; + } + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; + case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID: + /* Parse and fetch number of blacklist BSSID */ + if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) { + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } + roam_params.num_bssid_avoid_list = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("Num of blacklist BSSID (%d)"), + roam_params.num_bssid_avoid_list); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), + NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + /* Parse and fetch MAC address */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) { + hddLog(LOGE, FL("attr blacklist addr failed")); + goto fail; + } + nla_memcpy(roam_params.bssid_avoid_list[i], + tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID], + sizeof(tSirMacAddr)); + hddLog(VOS_TRACE_LEVEL_DEBUG, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY( + roam_params.bssid_avoid_list[i])); + i++; + } + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; + } + return 0; +fail: + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_STATS_EXT +/** + * __wlan_hdd_cfg80211_stats_ext_request() - ext stats request + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +static int __wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tStatsExtRequestReq stats_ext_req; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int ret_val; + eHalStatus status; + 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 -EINVAL; + } + + stats_ext_req.request_data_len = data_len; + stats_ext_req.request_data = (void *)data; + + status = sme_StatsExtRequest(pAdapter->sessionId, &stats_ext_req); + + if (eHAL_STATUS_SUCCESS != status) + ret_val = -EINVAL; + + return ret_val; +} + +/** + * wlan_hdd_cfg80211_stats_ext_request() - ext stats request + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +static int wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_stats_ext_request(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static void wlan_hdd_cfg80211_stats_ext_callback(void* ctx, tStatsExtEvent* msg) +{ + + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *vendor_event; + int status; + int ret_val; + tStatsExtEvent *data = msg; + hdd_adapter_t *pAdapter = NULL; + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return; + } + + pAdapter = hdd_get_adapter_by_vdev( pHddCtx, data->vdev_id); + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vdev_id %d does not exist with host", + __func__, data->vdev_id); + return; + } + + + vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + data->event_data_len + + sizeof(tANI_U32) + + NLMSG_HDRLEN + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX, + GFP_KERNEL); + + if (!vendor_event) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: cfg80211_vendor_event_alloc failed", __func__); + return; + } + + ret_val = nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_IFINDEX, + pAdapter->dev->ifindex); + if (ret_val) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: QCA_WLAN_VENDOR_ATTR_IFINDEX put fail", __func__); + kfree_skb(vendor_event); + + return; + } + + + ret_val = nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_STATS_EXT, + data->event_data_len, data->event_data); + + if (ret_val) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: QCA_WLAN_VENDOR_ATTR_STATS_EXT put fail", __func__); + kfree_skb(vendor_event); + + return; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + +} + + +void wlan_hdd_cfg80211_stats_ext_init(hdd_context_t *pHddCtx) +{ + sme_StatsExtRegisterCallback(pHddCtx->hHal, + wlan_hdd_cfg80211_stats_ext_callback); +} + +#endif + +#ifdef FEATURE_WLAN_EXTSCAN + +/* + * define short names for the global vendor params + * used by wlan_hdd_send_ext_scan_capability() + */ +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID +#define PARAM_STATUS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS +#define MAX_SCAN_CACHE_SIZE \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE +#define MAX_SCAN_BUCKETS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS +#define MAX_AP_CACHE_PER_SCAN \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN +#define MAX_RSSI_SAMPLE_SIZE \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE +#define MAX_SCAN_RPT_THRHOLD \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD +#define MAX_HOTLIST_BSSIDS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS +#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS +#define MAX_BSSID_HISTORY_ENTRIES \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES +#define MAX_HOTLIST_SSIDS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS +#define MAX_NUM_EPNO_NETS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS +#define MAX_NUM_EPNO_NETS_BY_SSID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID +#define MAX_NUM_WHITELISTED_SSID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID + +/** + * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space + * @hdd_ctx: Pointer to hdd context + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx) +{ + int ret; + struct sk_buff *skb; + struct ext_scan_capabilities_response *data; + uint32_t nl_buf_len; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("hdd_context is invalid")); + return ret; + } + + data = &(hdd_ctx->ext_scan_context.capability_response); + + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) + + (sizeof(data->status) + NLA_HDRLEN) + + (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) + + (sizeof(data->max_scan_buckets) + NLA_HDRLEN) + + (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) + + (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) + + (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) + + (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) + + (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) + + (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) + + (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) + + (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) + + (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) + + (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + hddLog(LOG1, "Req Id (%u)", data->requestId); + hddLog(LOG1, "Status (%u)", data->status); + hddLog(LOG1, "Scan cache size (%u)", data->max_scan_cache_size); + hddLog(LOG1, "Scan buckets (%u)", data->max_scan_buckets); + hddLog(LOG1, "Max AP per scan (%u)", data->max_ap_cache_per_scan); + hddLog(LOG1, "max_rssi_sample_size (%u)", + data->max_rssi_sample_size); + hddLog(LOG1, "max_scan_reporting_threshold (%u)", + data->max_scan_reporting_threshold); + hddLog(LOG1, "max_hotlist_bssids (%u)", data->max_hotlist_bssids); + hddLog(LOG1, "max_significant_wifi_change_aps (%u)", + data->max_significant_wifi_change_aps); + hddLog(LOG1, "max_bssid_history_entries (%u)", + data->max_bssid_history_entries); + hddLog(LOG1, "max_hotlist_ssids (%u)", data->max_hotlist_ssids); + hddLog(LOG1, "max_number_epno_networks (%u)", + data->max_number_epno_networks); + hddLog(LOG1, "max_number_epno_networks_by_ssid (%u)", + data->max_number_epno_networks_by_ssid); + hddLog(LOG1, "max_number_of_white_listed_ssid (%u)", + data->max_number_of_white_listed_ssid); + + if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) || + nla_put_u32(skb, PARAM_STATUS, data->status) || + nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) || + nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) || + nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN, + data->max_ap_cache_per_scan) || + nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE, + data->max_rssi_sample_size) || + nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD, + data->max_scan_reporting_threshold) || + nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) || + nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS, + data->max_significant_wifi_change_aps) || + nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES, + data->max_bssid_history_entries) || + nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) || + nla_put_u32(skb, MAX_NUM_EPNO_NETS, + data->max_number_epno_networks) || + nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID, + data->max_number_epno_networks_by_ssid) || + nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID, + data->max_number_of_white_listed_ssid)) { + hddLog(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_cmd_reply(skb); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} +/* + * done with short names for the global vendor params + * used by wlan_hdd_send_ext_scan_capability() + */ +#undef PARAM_REQUEST_ID +#undef PARAM_STATUS +#undef MAX_SCAN_CACHE_SIZE +#undef MAX_SCAN_BUCKETS +#undef MAX_AP_CACHE_PER_SCAN +#undef MAX_RSSI_SAMPLE_SIZE +#undef MAX_SCAN_RPT_THRHOLD +#undef MAX_HOTLIST_BSSIDS +#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS +#undef MAX_BSSID_HISTORY_ENTRIES +#undef MAX_HOTLIST_SSIDS +#undef MAX_NUM_EPNO_NETS +#undef MAX_NUM_EPNO_NETS_BY_SSID +#undef MAX_NUM_WHITELISTED_SSID + +static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + unsigned long rc; + struct hdd_ext_scan_context *context; + tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + eHalStatus status; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id %d"), pReqMsg->requestId); + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id %d"), pReqMsg->sessionId); + + spin_lock(&hdd_context_lock); + context = &pHddCtx->ext_scan_context; + context->request_id = pReqMsg->requestId; + INIT_COMPLETION(context->response_event); + spin_unlock(&hdd_context_lock); + + + status = sme_ExtScanGetCapabilities(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("sme_ExtScanGetCapabilities failed(err=%d)"), status); + goto fail; + } + + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + if (!rc) { + hddLog(LOGE, FL("Target response timed out")); + return -ETIMEDOUT; + } + + ret = wlan_hdd_send_ext_scan_capability(pHddCtx); + if (ret) + hddLog(LOGE, FL("Failed to send ext scan capability to user space")); + + EXIT(); + return ret; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + + + +/* + * define short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_get_cached_results() + */ +#define PARAM_MAX \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID +#define PARAM_FLUSH \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH +/** + * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * This function parses the incoming NL vendor command data attributes and + * invokes the SME Api and blocks on a completion variable. + * Each WMI event with cached scan results data chunk results in + * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each + * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb. + * + * If timeout happens before receiving all of the data, this function sets + * a context variable @ignore_cached_results to %true, all of the next data + * chunks are checked against this variable and dropped. + * + * Return: 0 on success; error number otherwise. + */ +static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct hdd_ext_scan_context *context; + struct nlattr *tb[PARAM_MAX + 1]; + eHalStatus status; + int retval = 0; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL; + + if (nla_parse(tb, PARAM_MAX, data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]); + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Req Id %u Session Id %d"), + pReqMsg->requestId, pReqMsg->sessionId); + + /* Parse and fetch flush parameter */ + if (!tb[PARAM_FLUSH]) { + hddLog(LOGE, FL("attr flush failed")); + goto fail; + } + pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]); + hddLog(LOG1, FL("Flush %d"), pReqMsg->flush); + + spin_lock(&hdd_context_lock); + context = &pHddCtx->ext_scan_context; + context->request_id = pReqMsg->requestId; + context->ignore_cached_results = false; + INIT_COMPLETION(context->response_event); + spin_unlock(&hdd_context_lock); + + status = sme_getCachedResults(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_getCachedResults failed(err=%d)"), status); + goto fail; + } + + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + if (!rc) { + hddLog(LOGE, FL("Target response timed out")); + retval = -ETIMEDOUT; + spin_lock(&hdd_context_lock); + context->ignore_cached_results = true; + spin_unlock(&hdd_context_lock); + } else { + spin_lock(&hdd_context_lock); + retval = context->response_status; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} +/* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_get_cached_results() + */ +#undef PARAM_MAX +#undef PARAM_REQUEST_ID +#undef PARAM_FLUSH + +/** + * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * This function parses the incoming NL vendor command data attributes and + * invokes the SME Api and blocks on a completion variable. + * Each WMI event with cached scan results data chunk results in + * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each + * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb. + * + * If timeout happens before receiving all of the data, this function sets + * a context variable @ignore_cached_results to %true, all of the next data + * chunks are checked against this variable and dropped. + * + * Return: 0 on success; error number otherwise. + */ +static int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + + +static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *apTh; + struct hdd_ext_scan_context *context; + uint32_t request_id; + eHalStatus status; + tANI_U8 i; + int rem, retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + hddLog(LOG1, FL("Req Id %d"), pReqMsg->requestId); + + /* Parse and fetch number of APs */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) { + hddLog(LOGE, FL("attr number of AP failed")); + goto fail; + } + pReqMsg->numAp = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]); + hddLog(LOG1, FL("Number of AP %d"), pReqMsg->numAp); + + /* Parse and fetch lost ap sample size */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) { + hddLog(LOGE, FL("attr lost ap sample size failed")); + goto fail; + } + + pReqMsg->lost_ap_sample_size = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]); + hddLog(LOG1, FL("Lost ap sample size %d"), pReqMsg->lost_ap_sample_size); + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Session Id %d"), pReqMsg->sessionId); + + i = 0; + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { + if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + + /* Parse and fetch MAC address */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) { + hddLog(LOGE, FL("attr mac address failed")); + goto fail; + } + nla_memcpy(pReqMsg->ap[i].bssid, + tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID], + sizeof(tSirMacAddr)); + hddLog(LOG1, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid)); + + /* Parse and fetch low RSSI */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) { + hddLog(LOGE, FL("attr low RSSI failed")); + goto fail; + } + pReqMsg->ap[i].low = nla_get_s32( + tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]); + hddLog(LOG1, FL("RSSI low %d"), pReqMsg->ap[i].low); + + /* Parse and fetch high RSSI */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) { + hddLog(LOGE, FL("attr high RSSI failed")); + goto fail; + } + pReqMsg->ap[i].high = nla_get_s32( + tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]); + hddLog(LOG1, FL("RSSI High %d"), pReqMsg->ap[i].high); + i++; + } + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&hdd_context_lock); + + status = sme_SetBssHotlist(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_SetBssHotlist failed(err=%d)"), status); + goto fail; + } + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + + if (!rc) { + hddLog(LOGE, FL("sme_SetBssHotlist timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + + +/* + * define short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist() + */ +#define PARAM_MAX \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID +#define PARAMS_LOST_SSID_SAMPLE_SIZE \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE +#define PARAMS_NUM_SSID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID +#define THRESHOLD_PARAM \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM +#define PARAM_SSID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID +#define PARAM_BAND \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND +#define PARAM_RSSI_LOW \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW +#define PARAM_RSSI_HIGH \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH + +/** + * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct sir_set_ssid_hotlist_request *request; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[PARAM_MAX + 1]; + struct nlattr *tb2[PARAM_MAX + 1]; + struct nlattr *ssids; + struct hdd_ext_scan_context *context; + uint32_t request_id; + char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1]; + int ssid_len; + eHalStatus status; + int i, rem, retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(hdd_ctx); + if (0 != retval) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb, PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + request = vos_mem_malloc(sizeof(*request)); + if (!request) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); + hddLog(LOG1, FL("Request Id %d"), request->request_id); + + /* Parse and fetch lost SSID sample size */ + if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) { + hddLog(LOGE, FL("attr number of Ssid failed")); + goto fail; + } + request->lost_ssid_sample_size = + nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]); + hddLog(LOG1, FL("Lost SSID Sample Size %d"), + request->lost_ssid_sample_size); + + /* Parse and fetch number of hotlist SSID */ + if (!tb[PARAMS_NUM_SSID]) { + hddLog(LOGE, FL("attr number of Ssid failed")); + goto fail; + } + request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]); + hddLog(LOG1, FL("Number of SSID %d"), request->ssid_count); + + request->session_id = adapter->sessionId; + hddLog(LOG1, FL("Session Id (%d)"), request->session_id); + + i = 0; + nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) { + if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) { + hddLog(LOGE, + FL("Too Many SSIDs, %d exceeds %d"), + i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS); + break; + } + if (nla_parse(tb2, PARAM_MAX, + nla_data(ssids), nla_len(ssids), + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + + /* Parse and fetch SSID */ + if (!tb2[PARAM_SSID]) { + hddLog(LOGE, FL("attr ssid failed")); + goto fail; + } + nla_memcpy(ssid_string, + tb2[PARAM_SSID], + sizeof(ssid_string)); + hddLog(LOG1, FL("SSID %s"), + ssid_string); + ssid_len = strlen(ssid_string); + memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len); + request->ssids[i].ssid.length = ssid_len; + + /* Parse and fetch low RSSI */ + if (!tb2[PARAM_BAND]) { + hddLog(LOGE, FL("attr band failed")); + goto fail; + } + request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]); + hddLog(LOG1, FL("band %d"), request->ssids[i].band); + + /* Parse and fetch low RSSI */ + if (!tb2[PARAM_RSSI_LOW]) { + hddLog(LOGE, FL("attr low RSSI failed")); + goto fail; + } + request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]); + hddLog(LOG1, FL("RSSI low %d"), request->ssids[i].rssi_low); + + /* Parse and fetch high RSSI */ + if (!tb2[PARAM_RSSI_HIGH]) { + hddLog(LOGE, FL("attr high RSSI failed")); + goto fail; + } + request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]); + hddLog(LOG1, FL("RSSI high %d"), request->ssids[i].rssi_high); + i++; + } + + context = &hdd_ctx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = request->request_id; + spin_unlock(&hdd_context_lock); + + status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_ssid_hotlist failed(err=%d)"), status); + goto fail; + } + + vos_mem_free(request); + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies + (WLAN_WAIT_TIME_EXTSCAN)); + if (!rc) { + hddLog(LOGE, FL("sme_set_ssid_hotlist timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + + return retval; + +fail: + vos_mem_free(request); + return -EINVAL; +} + +/* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist() + */ +#undef PARAM_MAX +#undef PARAM_REQUEST_ID +#undef PARAMS_NUM_SSID +#undef THRESHOLD_PARAM +#undef PARAM_SSID +#undef PARAM_BAND +#undef PARAM_RSSI_LOW +#undef PARAM_RSSI_HIGH + +/** + * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int +wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_extscan_set_significant_change( + struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirExtScanSetSigChangeReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *apTh; + struct hdd_ext_scan_context *context; + uint32_t request_id; + eHalStatus status; + tANI_U8 i; + int rem; + int retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + hddLog(LOG1, FL("Req Id %d"), pReqMsg->requestId); + + /* Parse and fetch RSSI sample size */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) + { + hddLog(LOGE, FL("attr RSSI sample size failed")); + goto fail; + } + pReqMsg->rssiSampleSize = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]); + hddLog(LOG1, FL("RSSI sample size %u"), pReqMsg->rssiSampleSize); + + /* Parse and fetch lost AP sample size */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) + { + hddLog(LOGE, FL("attr lost AP sample size failed")); + goto fail; + } + pReqMsg->lostApSampleSize = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]); + hddLog(LOG1, FL("Lost AP sample size %u"), pReqMsg->lostApSampleSize); + + /* Parse and fetch AP min breaching */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) + { + hddLog(LOGE, FL("attr AP min breaching")); + goto fail; + } + pReqMsg->minBreaching = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]); + hddLog(LOG1, FL("AP min breaching %u"), pReqMsg->minBreaching); + + /* Parse and fetch number of APs */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) { + hddLog(LOGE, FL("attr number of AP failed")); + goto fail; + } + pReqMsg->numAp = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]); + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Number of AP %d Session Id %d"), pReqMsg->numAp, + pReqMsg->sessionId); + + i = 0; + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + + /* Parse and fetch MAC address */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) { + hddLog(LOGE, FL("attr mac address failed")); + goto fail; + } + nla_memcpy(pReqMsg->ap[i].bssid, + tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID], + sizeof(tSirMacAddr)); + hddLog(LOG1, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid)); + + /* Parse and fetch low RSSI */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) { + hddLog(LOGE, FL("attr low RSSI failed")); + goto fail; + } + pReqMsg->ap[i].low = nla_get_s32( + tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]); + hddLog(LOG1, FL("RSSI low %d"), pReqMsg->ap[i].low); + + /* Parse and fetch high RSSI */ + if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) { + hddLog(LOGE, FL("attr high RSSI failed")); + goto fail; + } + pReqMsg->ap[i].high = nla_get_s32( + tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]); + hddLog(LOG1, FL("RSSI High %d"), pReqMsg->ap[i].high); + + i++; + } + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&hdd_context_lock); + + status = sme_SetSignificantChange(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_SetSignificantChange failed(err=%d)"), status); + goto fail; + } + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + + if (!rc) { + hddLog(LOGE, FL("sme_SetSignificantChange timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + uint8_t num_channels = 0; + uint8_t num_chan_new = 0; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + tANI_U32 requestId, maxChannels; + tWifiBand wifiBand; + eHalStatus status; + struct sk_buff *reply_skb; + tANI_U8 i, j, k; + int retval; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + return -EINVAL; + } + requestId = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + hddLog(LOG1, FL("Req Id %d"), requestId); + + /* Parse and fetch wifi band */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) { + hddLog(LOGE, FL("attr wifi band failed")); + return -EINVAL; + } + wifiBand = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]); + hddLog(LOG1, FL("Wifi band %d"), wifiBand); + + /* Parse and fetch max channels */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) { + hddLog(LOGE, FL("attr max channels failed")); + return -EINVAL; + } + maxChannels = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]); + hddLog(LOG1, FL("Max channels %d"), maxChannels); + + status = sme_GetValidChannelsByBand((tHalHandle)(pHddCtx->hHal), + wifiBand, chan_list, + &num_channels); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("sme_GetValidChannelsByBand failed (err=%d)"), status); + return -EINVAL; + } + + num_channels = VOS_MIN(num_channels, maxChannels); + + /* remove the DSRC channels from the list */ + num_chan_new = 0; + for (i = 0; i < num_channels; i++) { + if (!vos_is_dsrc_channel(chan_list[i])) { + chan_list[num_chan_new] = chan_list[i]; + num_chan_new++; + } + } + + num_channels = num_chan_new; + + /* remove the indoor only channels if iface is SAP */ + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + !strncmp(hdd_get_fwpath(), "ap", 2)) { + num_chan_new = 0; + for (i = 0; i < num_channels; i++) + for (j = 0; j < IEEE80211_NUM_BANDS; j++) { + if (wiphy->bands[j] == NULL) + continue; + for (k = 0; k < wiphy->bands[j]->n_channels; k++) { + if ((chan_list[i] == + wiphy->bands[j]->channels[k].center_freq) && + (!(wiphy->bands[j]->channels[k].flags & + IEEE80211_CHAN_INDOOR_ONLY))) { + chan_list[num_chan_new] = chan_list[i]; + num_chan_new++; + } + } + } + } + + hddLog(LOG1, FL("Number of channels %d"), num_chan_new); + for (i = 0; i < num_chan_new; i++) + hddLog(LOG1, "Channel: %u ", chan_list[i]); + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + sizeof(u32) * num_chan_new + + NLMSG_HDRLEN); + + if (reply_skb) { + if (nla_put_u32(reply_skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS, + num_chan_new) || + nla_put(reply_skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS, + sizeof(u32) * num_chan_new, chan_list)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(reply_skb); + return -EINVAL; + } + + retval = cfg80211_vendor_cmd_reply(reply_skb); + EXIT(); + return retval; + } + hddLog(LOGE, FL("valid channels: buffer alloc fail")); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_extscan_update_dwell_time_limits() - update dwell times + * @req_msg: Pointer to request message + * @bkt_idx: Index of current bucket being processed + * @active_min: minimum active dwell time + * @active_max: maximum active dwell time + * @passive_min: minimum passive dwell time + * @passive_max: maximum passive dwell time + * + * Return: none + */ +static void hdd_extscan_update_dwell_time_limits( + tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx, + uint32_t active_min, uint32_t active_max, + uint32_t passive_min, uint32_t passive_max) +{ + /* update per-bucket dwell times */ + if (req_msg->buckets[bkt_idx].min_dwell_time_active > + active_min) { + req_msg->buckets[bkt_idx].min_dwell_time_active = + active_min; + } + if (req_msg->buckets[bkt_idx].max_dwell_time_active < + active_max) { + req_msg->buckets[bkt_idx].max_dwell_time_active = + active_max; + } + if (req_msg->buckets[bkt_idx].min_dwell_time_passive > + passive_min) { + req_msg->buckets[bkt_idx].min_dwell_time_passive = + passive_min; + } + if (req_msg->buckets[bkt_idx].max_dwell_time_passive < + passive_max) { + req_msg->buckets[bkt_idx].max_dwell_time_passive = + passive_max; + } + /* update dwell-time across all buckets */ + if (req_msg->min_dwell_time_active > + req_msg->buckets[bkt_idx].min_dwell_time_active) { + req_msg->min_dwell_time_active = + req_msg->buckets[bkt_idx].min_dwell_time_active; + } + if (req_msg->max_dwell_time_active < + req_msg->buckets[bkt_idx].max_dwell_time_active) { + req_msg->max_dwell_time_active = + req_msg->buckets[bkt_idx].max_dwell_time_active; + } + if (req_msg->min_dwell_time_passive > + req_msg->buckets[bkt_idx].min_dwell_time_passive) { + req_msg->min_dwell_time_passive = + req_msg->buckets[bkt_idx].min_dwell_time_passive; + } + if (req_msg->max_dwell_time_passive > + req_msg->buckets[bkt_idx].max_dwell_time_passive) { + req_msg->max_dwell_time_passive = + req_msg->buckets[bkt_idx].max_dwell_time_passive; + } +} + +/** + * hdd_extscan_channel_max_reached() - channel max reached + * @req: extscan request structure + * @total_channels: total number of channels + * + * Return: true if total channels reached max, false otherwise + */ +static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req, + uint8_t total_channels) +{ + if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) { + hddLog(LOGW, + FL("max #of channels %d reached, taking only first %d bucket(s)"), + total_channels, req->numBuckets); + return true; + } + return false; +} + +static int hdd_extscan_start_fill_bucket_channel_spec( + hdd_context_t *pHddCtx, + tpSirWifiScanCmdReqParams pReqMsg, + struct nlattr **tb) +{ + struct nlattr *bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *buckets; + struct nlattr *channels; + int rem1, rem2; + eHalStatus status; + uint8_t bktIndex, j, numChannels, total_channels = 0; + uint32_t chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + + uint32_t min_dwell_time_active_bucket = + pHddCtx->cfg_ini->extscan_active_max_chn_time; + uint32_t max_dwell_time_active_bucket = + pHddCtx->cfg_ini->extscan_active_max_chn_time; + uint32_t min_dwell_time_passive_bucket = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + uint32_t max_dwell_time_passive_bucket = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + + bktIndex = 0; + pReqMsg->min_dwell_time_active = + pReqMsg->max_dwell_time_active = + pHddCtx->cfg_ini->extscan_active_max_chn_time; + + pReqMsg->min_dwell_time_passive = + pReqMsg->max_dwell_time_passive = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + pReqMsg->numBuckets = 0; + + nla_for_each_nested(buckets, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) { + if (nla_parse(bucket, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(buckets), nla_len(buckets), NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } + + /* Parse and fetch bucket spec */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) { + hddLog(LOGE, FL("attr bucket index failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].bucket = nla_get_u8( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]); + hddLog(LOG1, FL("Bucket spec Index %d"), + pReqMsg->buckets[bktIndex].bucket); + + /* Parse and fetch wifi band */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) { + hddLog(LOGE, FL("attr wifi band failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].band = nla_get_u8( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]); + hddLog(LOG1, FL("Wifi band %d"), + pReqMsg->buckets[bktIndex].band); + + /* Parse and fetch period */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) { + hddLog(LOGE, FL("attr period failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].period = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]); + hddLog(LOG1, FL("period %d"), + pReqMsg->buckets[bktIndex].period); + + /* Parse and fetch report events */ + if (!bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) { + hddLog(LOGE, FL("attr report events failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].reportEvents = nla_get_u8( + bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]); + hddLog(LOG1, FL("report events %d"), + pReqMsg->buckets[bktIndex].reportEvents); + + /* Parse and fetch max period */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) { + hddLog(LOGE, FL("attr max period failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].max_period = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]); + hddLog(LOG1, FL("max period %u"), + pReqMsg->buckets[bktIndex].max_period); + + /* Parse and fetch exponent */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT]) { + hddLog(LOGE, FL("attr exponent failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].exponent = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT]); + hddLog(LOG1, FL("exponent %u"), + pReqMsg->buckets[bktIndex].exponent); + + /* Parse and fetch step count */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) { + hddLog(LOGE, FL("attr step count failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].step_count = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]); + hddLog(LOG1, FL("Step count %u"), + pReqMsg->buckets[bktIndex].step_count); + + /* start with known good values for bucket dwell times */ + pReqMsg->buckets[bktIndex].min_dwell_time_active = + pReqMsg->buckets[bktIndex].max_dwell_time_active = + pHddCtx->cfg_ini->extscan_active_max_chn_time; + + pReqMsg->buckets[bktIndex].min_dwell_time_passive = + pReqMsg->buckets[bktIndex].max_dwell_time_passive = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + + /* Framework shall pass the channel list if the input WiFi band is + * WIFI_BAND_UNSPECIFIED. + * If the input WiFi band is specified (any value other than + * WIFI_BAND_UNSPECIFIED) then driver populates the channel list + */ + if (pReqMsg->buckets[bktIndex].band != WIFI_BAND_UNSPECIFIED) { + if (hdd_extscan_channel_max_reached(pReqMsg, + total_channels)) + return 0; + + numChannels = 0; + hddLog(LOG1, "WiFi band is specified, driver to fill channel list"); + status = sme_GetValidChannelsByBand(pHddCtx->hHal, + pReqMsg->buckets[bktIndex].band, + chanList, &numChannels); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_GetValidChannelsByBand failed (err=%d)"), + status); + return -EINVAL; + } + hddLog(LOG1, FL("before trimming, num_channels: %d"), + numChannels); + + pReqMsg->buckets[bktIndex].numChannels = + VOS_MIN(numChannels, + (WLAN_EXTSCAN_MAX_CHANNELS - total_channels)); + hddLog(LOG1, + FL("Adj Num channels/bucket: %d total_channels: %d"), + pReqMsg->buckets[bktIndex].numChannels, + total_channels); + + total_channels += pReqMsg->buckets[bktIndex].numChannels; + + for (j = 0; j < pReqMsg->buckets[bktIndex].numChannels; + j++) { + pReqMsg->buckets[bktIndex].channels[j].channel = + chanList[j]; + pReqMsg->buckets[bktIndex].channels[j]. + chnlClass = 0; + if (CSR_IS_CHANNEL_DFS( + vos_freq_to_chan(chanList[j]))) { + pReqMsg->buckets[bktIndex].channels[j]. + passive = 1; + pReqMsg->buckets[bktIndex].channels[j]. + dwellTimeMs = + pHddCtx->cfg_ini-> + extscan_passive_max_chn_time; + /* reconfigure per-bucket dwell time */ + if (min_dwell_time_passive_bucket > + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + min_dwell_time_passive_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + if (max_dwell_time_passive_bucket < + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + max_dwell_time_passive_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + } else { + pReqMsg->buckets[bktIndex].channels[j]. + passive = 0; + pReqMsg->buckets[bktIndex].channels[j]. + dwellTimeMs = + pHddCtx->cfg_ini->extscan_active_max_chn_time; + /* reconfigure per-bucket dwell times */ + if (min_dwell_time_active_bucket > + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + min_dwell_time_active_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + if (max_dwell_time_active_bucket < + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + max_dwell_time_active_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + } + + hddLog(LOG1, + "Channel %u Passive %u Dwell time %u ms Class %u", + pReqMsg->buckets[bktIndex].channels[j].channel, + pReqMsg->buckets[bktIndex].channels[j].passive, + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs, + pReqMsg->buckets[bktIndex].channels[j].chnlClass); + } + + hdd_extscan_update_dwell_time_limits( + pReqMsg, bktIndex, + min_dwell_time_active_bucket, + max_dwell_time_active_bucket, + min_dwell_time_passive_bucket, + max_dwell_time_passive_bucket); + + hddLog(LOG1, FL("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d"), + bktIndex, + pReqMsg->buckets[bktIndex].min_dwell_time_active, + pReqMsg->buckets[bktIndex].max_dwell_time_active, + pReqMsg->buckets[bktIndex].min_dwell_time_passive, + pReqMsg->buckets[bktIndex].max_dwell_time_passive); + + bktIndex++; + pReqMsg->numBuckets++; + continue; + } + + /* Parse and fetch number of channels */ + if (!bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) { + hddLog(LOGE, FL("attr num channels failed")); + return -EINVAL; + } + + pReqMsg->buckets[bktIndex].numChannels = + nla_get_u32(bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]); + hddLog(LOG1, FL("before trimming: num channels %d"), + pReqMsg->buckets[bktIndex].numChannels); + pReqMsg->buckets[bktIndex].numChannels = + VOS_MIN(pReqMsg->buckets[bktIndex].numChannels, + (WLAN_EXTSCAN_MAX_CHANNELS - total_channels)); + hddLog(LOG1, + FL("Num channels/bucket: %d total_channels: %d"), + pReqMsg->buckets[bktIndex].numChannels, + total_channels); + if (hdd_extscan_channel_max_reached(pReqMsg, total_channels)) + return 0; + + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) { + hddLog(LOGE, FL("attr channel spec failed")); + return -EINVAL; + } + + j = 0; + nla_for_each_nested(channels, + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) { + if ((j >= pReqMsg->buckets[bktIndex].numChannels) || + hdd_extscan_channel_max_reached(pReqMsg, + total_channels)) + break; + + if (nla_parse(channel, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(channels), nla_len(channels), + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } + + /* Parse and fetch channel */ + if (!channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) { + hddLog(LOGE, FL("attr channel failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].channels[j].channel = + nla_get_u32(channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]); + hddLog(LOG1, FL("channel %u"), + pReqMsg->buckets[bktIndex].channels[j].channel); + + /* Parse and fetch dwell time */ + if (!channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) { + hddLog(LOGE, FL("attr dwelltime failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs = + nla_get_u32(channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]); + + /* Override dwell time if required */ + if (pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs < + pHddCtx->cfg_ini->extscan_active_min_chn_time || + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs > + pHddCtx->cfg_ini->extscan_active_max_chn_time) { + hddLog(LOG1, + FL("WiFi band is unspecified, dwellTime:%d"), + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs); + + if (CSR_IS_CHANNEL_DFS( + vos_freq_to_chan( + pReqMsg->buckets[bktIndex].channels[j].channel))) { + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + } else { + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs = + pHddCtx->cfg_ini->extscan_active_max_chn_time; + } + } + + hddLog(LOG1, FL("New Dwell time (%u ms)"), + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs); + + if (CSR_IS_CHANNEL_DFS( + vos_freq_to_chan( + pReqMsg->buckets[bktIndex].channels[j].channel))) { + if(min_dwell_time_passive_bucket > + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + min_dwell_time_passive_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + if(max_dwell_time_passive_bucket < + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + max_dwell_time_passive_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + } else { + if(min_dwell_time_active_bucket > + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + min_dwell_time_active_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + if(max_dwell_time_active_bucket < + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs) { + max_dwell_time_active_bucket = + pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs; + } + } + + /* Parse and fetch channel spec passive */ + if (!channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) { + hddLog(LOGE, + FL("attr channel spec passive failed")); + return -EINVAL; + } + pReqMsg->buckets[bktIndex].channels[j].passive = + nla_get_u8(channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]); + hddLog(LOG1, FL("Chnl spec passive %u"), + pReqMsg->buckets[bktIndex].channels[j].passive); + + /* Override scan type if required */ + if (CSR_IS_CHANNEL_DFS( + vos_freq_to_chan( + pReqMsg->buckets[bktIndex].channels[j].channel))) { + pReqMsg->buckets[bktIndex].channels[j].passive = TRUE; + } else { + pReqMsg->buckets[bktIndex].channels[j].passive = FALSE; + } + + j++; + total_channels++; + } + + hdd_extscan_update_dwell_time_limits( + pReqMsg, bktIndex, + min_dwell_time_active_bucket, + max_dwell_time_active_bucket, + min_dwell_time_passive_bucket, + max_dwell_time_passive_bucket); + + hddLog(LOG1, FL("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d"), + bktIndex, + pReqMsg->buckets[bktIndex].min_dwell_time_active, + pReqMsg->buckets[bktIndex].max_dwell_time_active, + pReqMsg->buckets[bktIndex].min_dwell_time_passive, + pReqMsg->buckets[bktIndex].max_dwell_time_passive); + + bktIndex++; + pReqMsg->numBuckets++; + } + + hddLog(LOG1, FL("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d"), + pReqMsg->min_dwell_time_active, + pReqMsg->max_dwell_time_active, + pReqMsg->min_dwell_time_passive, + pReqMsg->max_dwell_time_passive); + + return 0; +} + +/* + * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags + * @config_flags - [input] configuration flags. + * + * This function maps user space received configuration flags to + * driver representation. + * + * Return: configuration flags + */ +static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags) +{ + uint32_t configuration_flags = 0; + + if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING) + configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING; + + return configuration_flags; +} + +/* + * define short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_start() + */ +#define PARAM_MAX \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID +#define PARAM_BASE_PERIOD \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD +#define PARAM_MAX_AP_PER_SCAN \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN +#define PARAM_RPT_THRHLD_PERCENT \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT +#define PARAM_RPT_THRHLD_NUM_SCANS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS +#define PARAM_NUM_BUCKETS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS +#define PARAM_CONFIG_FLAGS \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS + +/** + * __wlan_hdd_cfg80211_extscan_start() - start extscan + * @wiphy: Pointer to wireless phy. + * @wdev: Pointer to wireless device. + * @data: Pointer to input data. + * @data_len: Length of @data. + * + * Return: 0 on success, negative errno on failure + */ +static int __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirWifiScanCmdReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[PARAM_MAX + 1]; + struct hdd_ext_scan_context *context; + uint32_t request_id, num_buckets; + eHalStatus status; + int retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) + return -EINVAL; + + if (nla_parse(tb, PARAM_MAX, data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]); + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Req Id %d Session Id %d"), + pReqMsg->requestId, pReqMsg->sessionId); + + /* Parse and fetch base period */ + if (!tb[PARAM_BASE_PERIOD]) { + hddLog(LOGE, FL("attr base period failed")); + goto fail; + } + pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]); + hddLog(LOG1, FL("Base Period %d"), pReqMsg->basePeriod); + + /* Parse and fetch max AP per scan */ + if (!tb[PARAM_MAX_AP_PER_SCAN]) { + hddLog(LOGE, FL("attr max_ap_per_scan failed")); + goto fail; + } + pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]); + hddLog(LOG1, FL("Max AP per Scan %d"), pReqMsg->maxAPperScan); + + /* Parse and fetch report threshold percent */ + if (!tb[PARAM_RPT_THRHLD_PERCENT]) { + hddLog(LOGE, FL("attr report_threshold percent failed")); + goto fail; + } + pReqMsg->report_threshold_percent = nla_get_u8( + tb[PARAM_RPT_THRHLD_PERCENT]); + hddLog(LOG1, FL("Report Threshold percent %d"), + pReqMsg->report_threshold_percent); + + /* Parse and fetch report threshold num scans */ + if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) { + hddLog(LOGE, FL("attr report_threshold num scans failed")); + goto fail; + } + pReqMsg->report_threshold_num_scans = nla_get_u8( + tb[PARAM_RPT_THRHLD_NUM_SCANS]); + hddLog(LOG1, FL("Report Threshold num scans %d"), + pReqMsg->report_threshold_num_scans); + + /* Parse and fetch number of buckets */ + if (!tb[PARAM_NUM_BUCKETS]) { + hddLog(LOGE, FL("attr number of buckets failed")); + goto fail; + } + num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]); + if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) { + hddLog(LOGW, + FL("Exceeded MAX number of buckets: %d"), + WLAN_EXTSCAN_MAX_BUCKETS); + } + hddLog(LOG1, FL("Input: Number of Buckets %d"), num_buckets); + + /* This is optional attribute, if not present set it to 0 */ + if (!tb[PARAM_CONFIG_FLAGS]) + pReqMsg->configuration_flags = 0; + else + pReqMsg->configuration_flags = + hdd_extscan_map_usr_drv_config_flags( + nla_get_u32(tb[PARAM_CONFIG_FLAGS])); + + hddLog(LOG1, FL("Configuration flags: %u"), + pReqMsg->configuration_flags); + + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) { + hddLog(LOGE, FL("attr bucket spec failed")); + goto fail; + } + + if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb)) + goto fail; + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&hdd_context_lock); + + status = sme_ExtScanStart(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_ExtScanStart failed(err=%d)"), status); + goto fail; + } + + pHddCtx->ext_scan_start_since_boot = vos_get_monotonic_boottime(); + hddLog(LOG1, FL("Timestamp since boot: %llu"), + pHddCtx->ext_scan_start_since_boot); + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + + if (!rc) { + hddLog(LOGE, FL("sme_ExtScanStart timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} +/* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_start() + */ +#undef PARAM_MAX +#undef PARAM_REQUEST_ID +#undef PARAM_BASE_PERIOD +#undef PARAMS_MAX_AP_PER_SCAN +#undef PARAMS_RPT_THRHLD_PERCENT +#undef PARAMS_RPT_THRHLD_NUM_SCANS +#undef PARAMS_NUM_BUCKETS +#undef PARAM_CONFIG_FLAGS + +/** + * wlan_hdd_cfg80211_extscan_start() - start extscan + * @wiphy: Pointer to wireless phy. + * @wdev: Pointer to wireless device. + * @data: Pointer to input data. + * @data_len: Length of @data. + * + * Return: 0 on success, negative errno on failure + */ +static int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * define short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_stop() + */ +#define PARAM_MAX \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID + +/** + * wlan_hdd_cfg80211_extscan_stop() - stop extscan + * @wiphy: Pointer to wireless phy. + * @wdev: Pointer to wireless device. + * @data: Pointer to input data. + * @data_len: Length of @data. + * + * Return: 0 on success, negative errno on failure + */ +static int __wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirExtScanStopReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct hdd_ext_scan_context *context; + struct nlattr *tb[PARAM_MAX + 1]; + uint32_t request_id; + eHalStatus status; + int retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) + return -EINVAL; + + if (nla_parse(tb, PARAM_MAX, data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]); + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Req Id %d Session Id %d"), + pReqMsg->requestId, pReqMsg->sessionId); + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&hdd_context_lock); + + status = sme_ExtScanStop(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_ExtScanStop failed(err=%d)"), status); + goto fail; + } + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + + if (!rc) { + hddLog(LOGE, FL("sme_ExtScanStop timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_stop() - stop extscan + * @wiphy: Pointer to wireless phy. + * @wdev: Pointer to wireless device. + * @data: Pointer to input data. + * @data_len: Length of @data. + * + * Return: 0 on success, negative errno on failure + */ +static int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_stop() + */ +#undef PARAM_MAX +#undef PARAM_REQUEST_ID + +static int __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct hdd_ext_scan_context *context; + uint32_t request_id; + eHalStatus status; + int retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Req Id %d Session Id %d"), + pReqMsg->requestId, pReqMsg->sessionId); + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&hdd_context_lock); + + status = sme_ResetBssHotlist(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_ResetBssHotlist failed(err=%d)"), status); + goto fail; + } + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + if (!rc) { + hddLog(LOGE, FL("sme_ResetBssHotlist timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/* + * define short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() + */ +#define PARAM_MAX \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID + +/** + * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct sir_set_ssid_hotlist_request *request; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[PARAM_MAX + 1]; + struct hdd_ext_scan_context *context; + uint32_t request_id; + eHalStatus status; + int retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(hdd_ctx); + if (0 != retval) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb, PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + request = vos_mem_malloc(sizeof(*request)); + if (!request) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); + request->session_id = adapter->sessionId; + hddLog(LOG1, FL("Request Id %d Session Id %d"), request->request_id, + request->session_id); + + request->lost_ssid_sample_size = 0; + request->ssid_count = 0; + + context = &hdd_ctx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = request->request_id; + spin_unlock(&hdd_context_lock); + + status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_reset_ssid_hotlist failed(err=%d)"), status); + goto fail; + } + + vos_mem_free(request); + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies + (WLAN_WAIT_TIME_EXTSCAN)); + if (!rc) { + hddLog(LOGE, FL("sme_reset_ssid_hotlist timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + + return retval; + +fail: + vos_mem_free(request); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int +wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} +/* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() + */ +#undef PARAM_MAX +#undef PARAM_REQUEST_ID + +static int __wlan_hdd_cfg80211_extscan_reset_significant_change( + struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct hdd_ext_scan_context *context; + uint32_t request_id; + eHalStatus status; + int retval; + unsigned long rc; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = vos_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + pReqMsg->requestId = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Req Id %d Session Id %d"), + pReqMsg->requestId, pReqMsg->sessionId); + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&hdd_context_lock); + + status = sme_ResetSignificantChange(pHddCtx->hHal, pReqMsg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_ResetSignificantChange failed(err=%d)"), status); + goto fail; + } + + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN)); + + if (!rc) { + hddLog(LOGE, FL("sme_ResetSignificantChange timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&hdd_context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&hdd_context_lock); + } + EXIT(); + return retval; + +fail: + vos_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant + * change + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static +int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + + +/** + * hdd_extscan_epno_fill_network_list() - epno fill network list + * @hddctx: HDD context + * @req_msg: request message + * @tb: vendor attribute table + * + * This function reads the network block NL vendor attributes from %tb and + * fill in the epno request message. + * + * Return: 0 on success, error number otherwise + */ +static int hdd_extscan_epno_fill_network_list( + hdd_context_t *hddctx, + struct wifi_epno_params *req_msg, + struct nlattr **tb) +{ + struct nlattr *network[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; + struct nlattr *networks; + int rem1, ssid_len; + uint8_t index, *ssid; + + index = 0; + nla_for_each_nested(networks, + tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], + rem1) { + if (nla_parse(network, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(networks), nla_len(networks), NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } + + /* Parse and fetch ssid */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) { + hddLog(LOGE, FL("attr network ssid failed")); + return -EINVAL; + } + ssid_len = nla_len( + network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]); + + /* Decrement by 1, don't count null character */ + ssid_len--; + + req_msg->networks[index].ssid.length = ssid_len; + hddLog(LOG1, FL("network ssid length %d"), ssid_len); + ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]); + vos_mem_copy(req_msg->networks[index].ssid.ssId, ssid, ssid_len); + hddLog(LOG1, FL("Ssid: %.*s"), + req_msg->networks[index].ssid.length, + req_msg->networks[index].ssid.ssId); + + /* Parse and fetch rssi threshold */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]) { + hddLog(LOGE, FL("attr rssi threshold failed")); + return -EINVAL; + } + req_msg->networks[index].rssi_threshold = nla_get_s8( + network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]); + hddLog(LOG1, FL("rssi threshold %d"), + req_msg->networks[index].rssi_threshold); + + /* Parse and fetch epno flags */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) { + hddLog(LOGE, FL("attr epno flags failed")); + return -EINVAL; + } + req_msg->networks[index].flags = nla_get_u8( + network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]); + hddLog(LOG1, FL("flags %u"), req_msg->networks[index].flags); + + /* Parse and fetch auth bit */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) { + hddLog(LOGE, FL("attr auth bit failed")); + return -EINVAL; + } + req_msg->networks[index].auth_bit_field = nla_get_u8( + network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]); + hddLog(LOG1, FL("auth bit %u"), + req_msg->networks[index].auth_bit_field); + + index++; + } + return 0; +} + +/** + * __wlan_hdd_cfg80211_set_epno_list() - epno set network list + * @wiphy: wiphy + * @wdev: pointer to wireless dev + * @data: data pointer + * @data_len: data length + * + * This function reads the NL vendor attributes from %tb and + * fill in the epno request message. + * + * Return: 0 on success, error number otherwise + */ +static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct wifi_epno_params *req_msg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[ + QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1]; + eHalStatus status; + uint32_t num_networks, len; + int ret_val; + + 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 -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, + data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch number of networks */ + if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) { + hddLog(LOGE, FL("attr num networks failed")); + return -EINVAL; + } + num_networks = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]); + hddLog(LOG1, FL("num networks %u"), num_networks); + + len = sizeof(*req_msg) + + (num_networks * sizeof(struct wifi_epno_network)); + req_msg = vos_mem_malloc(len); + if (!req_msg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + vos_mem_zero(req_msg, len); + req_msg->num_networks = num_networks; + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + req_msg->request_id = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + + req_msg->session_id = adapter->sessionId; + hddLog(LOG1, FL("Req Id %u Session Id %d"), + req_msg->request_id, req_msg->session_id); + + if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb)) + goto fail; + + status = sme_set_epno_list(hdd_ctx->hHal, req_msg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_set_epno_list failed(err=%d)"), status); + goto fail; + } + + EXIT(); + vos_mem_free(req_msg); + return 0; + +fail: + vos_mem_free(req_msg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_set_epno_list() - epno set network list + * @wiphy: wiphy + * @wdev: pointer to wireless dev + * @data: data pointer + * @data_len: data length + * + * This function reads the NL vendor attributes from %tb and + * fill in the epno request message. + * + * Return: 0 on success, error number otherwise + */ +static int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list + * @hddctx: HDD context + * @req_msg: request message + * @tb: vendor attribute table + * + * This function reads the network block NL vendor attributes from %tb and + * fill in the passpoint request message. + * + * Return: 0 on success, error number otherwise + */ +static int hdd_extscan_passpoint_fill_network_list( + hdd_context_t *hddctx, + struct wifi_passpoint_req *req_msg, + struct nlattr **tb) +{ + struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1]; + struct nlattr *networks; + int rem1, len; + uint8_t index; + + index = 0; + nla_for_each_nested(networks, + tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY], + rem1) { + if (nla_parse(network, + QCA_WLAN_VENDOR_ATTR_PNO_MAX, + nla_data(networks), nla_len(networks), NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } + + /* Parse and fetch identifier */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) { + hddLog(LOGE, FL("attr passpoint id failed")); + return -EINVAL; + } + req_msg->networks[index].id = nla_get_u32( + network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]); + hddLog(LOG1, FL("Id %u"), req_msg->networks[index].id); + + /* Parse and fetch realm */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) { + hddLog(LOGE, FL("attr realm failed")); + return -EINVAL; + } + len = nla_len( + network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]); + if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) { + hddLog(LOGE, FL("Invalid realm size %d"), len); + return -EINVAL; + } + vos_mem_copy(req_msg->networks[index].realm, + nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]), + len); + hddLog(LOG1, FL("realm len %d"), len); + hddLog(LOG1, FL("realm: %s"), req_msg->networks[index].realm); + + /* Parse and fetch roaming consortium ids */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) { + hddLog(LOGE, FL("attr roaming consortium ids failed")); + return -EINVAL; + } + nla_memcpy(&req_msg->networks[index].roaming_consortium_ids, + network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID], + sizeof(req_msg->networks[0].roaming_consortium_ids)); + hddLog(LOG1, FL("roaming consortium ids")); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + req_msg->networks[index].roaming_consortium_ids, + sizeof(req_msg->networks[0].roaming_consortium_ids)); + + /* Parse and fetch plmn */ + if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) { + hddLog(LOGE, FL("attr plmn failed")); + return -EINVAL; + } + nla_memcpy(&req_msg->networks[index].plmn, + network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN], + SIR_PASSPOINT_PLMN_LEN); + hddLog(LOG1, FL("plmn %02x:%02x:%02x"), + req_msg->networks[index].plmn[0], + req_msg->networks[index].plmn[1], + req_msg->networks[index].plmn[2]); + + index++; + } + return 0; +} + +/** + * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list + * @wiphy: wiphy + * @wdev: pointer to wireless dev + * @data: data pointer + * @data_len: data length + * + * This function reads the NL vendor attributes from %tb and + * fill in the passpoint request message. + * + * Return: 0 on success, error number otherwise + */ +static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct wifi_passpoint_req *req_msg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1]; + eHalStatus status; + uint32_t num_networks = 0; + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch number of networks */ + if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) { + hddLog(LOGE, FL("attr num networks failed")); + return -EINVAL; + } + num_networks = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]); + hddLog(LOG1, FL("num networks %u"), num_networks); + + req_msg = vos_mem_malloc(sizeof(*req_msg) + + (num_networks * sizeof(req_msg->networks[0]))); + if (!req_msg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + req_msg->num_networks = num_networks; + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + req_msg->request_id = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + + req_msg->session_id = adapter->sessionId; + hddLog(LOG1, FL("Req Id %u Session Id %d"), req_msg->request_id, + req_msg->session_id); + + if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb)) + goto fail; + + status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_passpoint_list failed(err=%d)"), status); + goto fail; + } + + EXIT(); + vos_mem_free(req_msg); + return 0; + +fail: + vos_mem_free(req_msg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list + * @wiphy: wiphy + * @wdev: pointer to wireless dev + * @data: data pointer + * @data_len: data length + * + * This function reads the NL vendor attributes from %tb and + * fill in the passpoint request message. + * + * Return: 0 on success, error number otherwise + */ +static int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list + * @wiphy: wiphy + * @wdev: pointer to wireless dev + * @data: data pointer + * @data_len: data length + * + * This function resets passpoint networks list + * + * Return: 0 on success, error number otherwise + */ +static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct wifi_passpoint_req *req_msg = NULL; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1]; + eHalStatus status; + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len, + wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + req_msg = vos_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + req_msg->request_id = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); + + req_msg->session_id = adapter->sessionId; + hddLog(LOG1, FL("Req Id %u Session Id %d"), + req_msg->request_id, req_msg->session_id); + + status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_reset_passpoint_list failed(err=%d)"), status); + goto fail; + } + + EXIT(); + vos_mem_free(req_msg); + return 0; + +fail: + vos_mem_free(req_msg); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list + * @wiphy: wiphy + * @wdev: pointer to wireless dev + * @data: data pointer + * @data_len: data length + * + * This function resets passpoint networks list + * + * Return: 0 on success, error number otherwise + */ +static int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif /* FEATURE_WLAN_EXTSCAN */ + +/** + * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features + * @feature_flags: pointer to the byte array of features. + * @feature: Feature to be turned ON in the byte array. + * + * Return: None + * + * This is called to turn ON or SET the feature flag for the requested feature. + */ +#define NUM_BITS_IN_BYTE 8 +void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature) +{ + uint32_t index; + uint8_t bit_mask; + + index = feature / NUM_BITS_IN_BYTE; + bit_mask = 1 << (feature % NUM_BITS_IN_BYTE); + feature_flags[index] |= bit_mask; +} + +/** + * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called when wlan driver needs to send supported feature set to + * supplicant upon a request/query from the supplicant. + * + * Return: Return the Success or Failure code. + */ +static int +__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct sk_buff *skb = NULL; + uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0}; + int ret_val; + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + + ret_val = wlan_hdd_validate_context(pHddCtx); + if (ret_val) + return ret_val; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pHddCtx->cfg_ini->isRoamOffloadEnabled) { + hddLog(LOG1, FL("Key Mgmt Offload is supported")); + wlan_hdd_cfg80211_set_feature (feature_flags, + QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD); + } +#endif + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) + + NLMSG_HDRLEN); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + if (nla_put(skb, + QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS, + sizeof(feature_flags), feature_flags)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called when wlan driver needs to send supported feature set to + * supplicant upon a request/query from the supplicant. + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_get_features(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +static bool put_wifi_rate_stat( tpSirWifiRateStat stats, + struct sk_buff *vendor_event) +{ + if (nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE, + stats->rate.preamble) || + nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS, + stats->rate.nss) || + nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW, + stats->rate.bw) || + nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX, + stats->rate.rateMcsIdx) || + nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE, + stats->rate.bitrate ) || + nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU, + stats->txMpdu ) || + nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU, + stats->rxMpdu ) || + nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST, + stats->mpduLost ) || + nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES, + stats->retries) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT, + stats->retriesShort ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG, + stats->retriesLong)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + return FALSE; + } + + return TRUE; +} + +static bool put_wifi_peer_info( tpSirWifiPeerInfo stats, + struct sk_buff *vendor_event) +{ + u32 i = 0; + tpSirWifiRateStat pRateStats; + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE, + stats->type) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS, + VOS_MAC_ADDR_SIZE, &stats->peerMacAddress[0]) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES, + stats->capabilities) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES, + stats->numRate)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + goto error; + } + + if (stats->numRate) + { + struct nlattr *rateInfo; + struct nlattr *rates; + + rateInfo = nla_nest_start(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO); + if (rateInfo == NULL) + goto error; + + for (i = 0; i < stats->numRate; i++) + { + pRateStats = (tpSirWifiRateStat )((uint8 *) + stats->rateStats + + (i * sizeof(tSirWifiRateStat))); + rates = nla_nest_start(vendor_event, i); + if (rates == NULL) + goto error; + + if (FALSE == put_wifi_rate_stat(pRateStats, vendor_event)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + return FALSE; + } + nla_nest_end(vendor_event, rates); + } + nla_nest_end(vendor_event, rateInfo); + } + + return TRUE; +error: + return FALSE; +} + +static bool put_wifi_wmm_ac_stat( tpSirWifiWmmAcStat stats, + struct sk_buff *vendor_event) +{ + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC, + stats->ac ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU, + stats->txMpdu ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU, + stats->rxMpdu ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST, + stats->txMcast ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST, + stats->rxMcast ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU, + stats->rxAmpdu ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU, + stats->txAmpdu ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST, + stats->mpduLost )|| + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES, + stats->retries ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT, + stats->retriesShort ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG, + stats->retriesLong ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN, + stats->contentionTimeMin ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX, + stats->contentionTimeMax ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG, + stats->contentionTimeAvg ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES, + stats->contentionNumSamples )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail") ); + return FALSE; + } + + return TRUE; +} + +static bool put_wifi_interface_info(tpSirWifiInterfaceInfo stats, + struct sk_buff *vendor_event) +{ + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE, + stats->mode ) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR, + VOS_MAC_ADDR_SIZE, stats->macAddr) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE, + stats->state ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING, + stats->roaming ) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES, + stats->capabilities ) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID, + strlen(stats->ssid), stats->ssid) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID, + VOS_MAC_ADDR_SIZE, stats->bssid) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR, + WNI_CFG_COUNTRY_CODE_LEN, stats->apCountryStr) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR, + WNI_CFG_COUNTRY_CODE_LEN, stats->countryStr)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail") ); + return FALSE; + } + + return TRUE; +} + +static bool put_wifi_iface_stats(tpSirWifiIfaceStat pWifiIfaceStat, + u32 num_peers, + struct sk_buff *vendor_event) +{ + int i = 0; + struct nlattr *wmmInfo; + struct nlattr *wmmStats; + u64 average_tsf_offset; + + if (FALSE == put_wifi_interface_info( + &pWifiIfaceStat->info, + vendor_event)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail") ); + return FALSE; + + } + + average_tsf_offset = pWifiIfaceStat->avg_bcn_spread_offset_high; + average_tsf_offset = (average_tsf_offset << 32) | + pWifiIfaceStat->avg_bcn_spread_offset_low ; + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_IFACE) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS, + num_peers) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX, + pWifiIfaceStat->beaconRx) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX, + pWifiIfaceStat->mgmtRx) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX, + pWifiIfaceStat->mgmtActionRx) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX, + pWifiIfaceStat->mgmtActionTx) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT, + pWifiIfaceStat->rssiMgmt) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA, + pWifiIfaceStat->rssiData) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK, + pWifiIfaceStat->rssiAck) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED, + pWifiIfaceStat->is_leaky_ap) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED, + pWifiIfaceStat->avg_rx_frms_leaked) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME, + pWifiIfaceStat->rx_leak_window) || + nla_put_u64(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET, + average_tsf_offset)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + return FALSE; + } + + wmmInfo = nla_nest_start(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO); + if (wmmInfo == NULL) + return FALSE; + + for (i = 0; i < WIFI_AC_MAX; i++) + { + wmmStats = nla_nest_start(vendor_event, i); + if (wmmStats == NULL) + return FALSE; + + if (FALSE == put_wifi_wmm_ac_stat( + &pWifiIfaceStat->AccessclassStats[i], + vendor_event)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("put_wifi_wmm_ac_stat Fail")); + return FALSE; + } + + nla_nest_end(vendor_event, wmmStats); + } + nla_nest_end(vendor_event, wmmInfo); + return TRUE; +} + +static tSirWifiInterfaceMode +hdd_map_device_to_ll_iface_mode ( int deviceMode ) +{ + switch (deviceMode) + { + case WLAN_HDD_INFRA_STATION: + return WIFI_INTERFACE_STA; + case WLAN_HDD_SOFTAP: + return WIFI_INTERFACE_SOFTAP; + case WLAN_HDD_P2P_CLIENT: + return WIFI_INTERFACE_P2P_CLIENT; + case WLAN_HDD_P2P_GO: + return WIFI_INTERFACE_P2P_GO; + case WLAN_HDD_IBSS: + return WIFI_INTERFACE_IBSS; + default: + /* Return Interface Mode as STA for all the unsupported modes */ + return WIFI_INTERFACE_STA; + } +} + +static bool hdd_get_interface_info(hdd_adapter_t *pAdapter, + tpSirWifiInterfaceInfo pInfo) +{ + v_U8_t *staMac = NULL; + hdd_station_ctx_t *pHddStaCtx; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pInfo->mode = hdd_map_device_to_ll_iface_mode(pAdapter->device_mode); + + vos_mem_copy(pInfo->macAddr, + pAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t)); + + if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))) + { + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState) + { + pInfo->state = WIFI_DISCONNECTED; + } + if (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Session ID %d, Connection is in progress", __func__, + pAdapter->sessionId); + pInfo->state = WIFI_ASSOCIATING; + } + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated)) + { + staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]); + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: client " MAC_ADDRESS_STR + " is in the middle of WPS/EAPOL exchange.", __func__, + MAC_ADDR_ARRAY(staMac)); + pInfo->state = WIFI_AUTHENTICATING; + } + if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) + { + pInfo->state = WIFI_ASSOCIATED; + vos_mem_copy(pInfo->bssid, + &pHddStaCtx->conn_info.bssId, VOS_MAC_ADDR_SIZE); + vos_mem_copy(pInfo->ssid, + pHddStaCtx->conn_info.SSID.SSID.ssId, + pHddStaCtx->conn_info.SSID.SSID.length); + /* + * NULL Terminate the string + */ + pInfo->ssid[pHddStaCtx->conn_info.SSID.SSID.length] = 0; + } + } + + vos_mem_copy(pInfo->countryStr, + pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); + + vos_mem_copy(pInfo->apCountryStr, + pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); + + return TRUE; +} + +/* + * hdd_link_layer_process_peer_stats () - This function is called after + * receiving Link Layer Peer statistics from FW.This function converts + * the firmware data to the NL data and sends the same to the kernel/upper + * layers. + */ +static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter, + u32 more_data, + tpSirWifiPeerStat pData) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tpSirWifiPeerStat pWifiPeerStat; + tpSirWifiPeerInfo pWifiPeerInfo; + struct sk_buff *vendor_event; + int status, i; + struct nlattr *peers; + int numRate; + + ENTER(); + + pWifiPeerStat = pData; + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return; + + hddLog(VOS_TRACE_LEVEL_INFO, + "LL_STATS_PEER_ALL : numPeers %u, more data = %u", + pWifiPeerStat->numPeers, + more_data); + + /* + * Allocate a size of 4096 for the peer stats comprising + * each of size = sizeof (tSirWifiPeerInfo) + numRate * + * sizeof (tSirWifiRateStat).Each field is put with an + * NL attribute.The size of 4096 is considered assuming + * that number of rates shall not exceed beyond 50 with + * the sizeof (tSirWifiRateStat) being 32. + */ + vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, + LL_STATS_EVENT_BUF_SIZE); + + if (!vendor_event) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: cfg80211_vendor_cmd_alloc_reply_skb failed", + __func__); + return; + } + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_PEER) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA, + more_data) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS, + pWifiPeerStat->numPeers)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: QCA_WLAN_VENDOR_ATTR put fail", __func__); + + kfree_skb(vendor_event); + return; + } + + + pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8 *) + pWifiPeerStat->peerInfo); + + if (pWifiPeerStat->numPeers) + { + struct nlattr *peerInfo; + peerInfo = nla_nest_start(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO); + if (peerInfo == NULL) { + hddLog(LOGE, FL("nla_nest_start failed")); + kfree_skb(vendor_event); + return; + } + + for (i = 1; i <= pWifiPeerStat->numPeers; i++) + { + peers = nla_nest_start(vendor_event, i); + if (peers == NULL) { + hddLog(LOGE, FL("nla_nest_start failed")); + kfree_skb(vendor_event); + return; + } + + numRate = pWifiPeerInfo->numRate; + + if (FALSE == put_wifi_peer_info( + pWifiPeerInfo, vendor_event)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("put_wifi_peer_info fail")); + kfree_skb(vendor_event); + return; + } + + pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8 *) + pWifiPeerStat->peerInfo + + (i * sizeof(tSirWifiPeerInfo)) + + (numRate * sizeof (tSirWifiRateStat))); + nla_nest_end(vendor_event, peers); + } + nla_nest_end(vendor_event, peerInfo); + } + cfg80211_vendor_cmd_reply(vendor_event); + EXIT(); +} + +/* + * hdd_link_layer_process_iface_stats () - This function is called after + * receiving Link Layer Interface statistics from FW.This function converts + * the firmware data to the NL data and sends the same to the kernel/upper + * layers. + */ +static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter, + tpSirWifiIfaceStat pData, + u32 num_peers) +{ + tpSirWifiIfaceStat pWifiIfaceStat; + struct sk_buff *vendor_event; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int status; + + ENTER(); + + pWifiIfaceStat = pData; + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return; + + /* + * Allocate a size of 4096 for the interface stats comprising + * sizeof (tpSirWifiIfaceStat).The size of 4096 is considered + * assuming that all these fit with in the limit.Please take + * a call on the limit based on the data requirements on + * interface statistics. + */ + vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, + LL_STATS_EVENT_BUF_SIZE); + + if (!vendor_event) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_cmd_alloc_reply_skb failed") ); + return; + } + + hddLog(VOS_TRACE_LEVEL_INFO, "WMI_LINK_STATS_IFACE Data"); + + if (FALSE == hdd_get_interface_info(pAdapter, + &pWifiIfaceStat->info)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("hdd_get_interface_info get fail")); + kfree_skb(vendor_event); + return; + } + + if (FALSE == put_wifi_iface_stats(pWifiIfaceStat, num_peers, vendor_event)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("put_wifi_iface_stats fail")); + kfree_skb(vendor_event); + return; + } + + cfg80211_vendor_cmd_reply(vendor_event); + EXIT(); +} + +/* + * hdd_link_layer_process_radio_stats () - This function is called after + * receiving Link Layer Radio statistics from FW.This function converts + * the firmware data to the NL data and sends the same to the kernel/upper + * layers. + */ +static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter, + u32 more_data, + tpSirWifiRadioStat pData, + u32 num_radio) +{ + int status, i; + tpSirWifiRadioStat pWifiRadioStat; + tpSirWifiChannelStats pWifiChannelStats; + struct sk_buff *vendor_event; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + pWifiRadioStat = pData; + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return; + + hddLog(VOS_TRACE_LEVEL_INFO, + "LL_STATS_RADIO" + " number of radios = %u" + " radio is %d onTime is %u" + " txTime is %u rxTime is %u" + " onTimeScan is %u onTimeNbd is %u" + " onTimeGscan is %u onTimeRoamScan is %u" + " onTimePnoScan is %u onTimeHs20 is %u" + " numChannels is %u", + num_radio, + pWifiRadioStat->radio, + pWifiRadioStat->onTime, + pWifiRadioStat->txTime, + pWifiRadioStat->rxTime, + pWifiRadioStat->onTimeScan, + pWifiRadioStat->onTimeNbd, + pWifiRadioStat->onTimeGscan, + pWifiRadioStat->onTimeRoamScan, + pWifiRadioStat->onTimePnoScan, + pWifiRadioStat->onTimeHs20, + pWifiRadioStat->numChannels); + + /* + * Allocate a size of 4096 for the Radio stats comprising + * sizeof (tSirWifiRadioStat) + numChannels * sizeof + * (tSirWifiChannelStats).Each channel data is put with an + * NL attribute.The size of 4096 is considered assuming that + * number of channels shall not exceed beyond 60 with the + * sizeof (tSirWifiChannelStats) being 24 bytes. + */ + + vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, + LL_STATS_EVENT_BUF_SIZE); + + if (!vendor_event) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return; + } + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA, + more_data) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS, + num_radio) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID, + pWifiRadioStat->radio) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME, + pWifiRadioStat->onTime) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME, + pWifiRadioStat->txTime) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME, + pWifiRadioStat->rxTime) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN, + pWifiRadioStat->onTimeScan) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD, + pWifiRadioStat->onTimeNbd) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN, + pWifiRadioStat->onTimeGscan)|| + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN, + pWifiRadioStat->onTimeRoamScan) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN, + pWifiRadioStat->onTimePnoScan) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20, + pWifiRadioStat->onTimeHs20) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, + pWifiRadioStat->numChannels)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + + kfree_skb(vendor_event); + return ; + } + + if (pWifiRadioStat->numChannels) + { + struct nlattr *chList; + struct nlattr *chInfo; + + chList = nla_nest_start(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO); + if (chList == NULL) { + hddLog(LOGE, FL("nla_nest_start failed")); + kfree_skb(vendor_event); + return; + } + + for (i = 0; i < pWifiRadioStat->numChannels; i++) + { + pWifiChannelStats = (tpSirWifiChannelStats) ((uint8*) + pWifiRadioStat->channels + + (i * sizeof(tSirWifiChannelStats))); + + chInfo = nla_nest_start(vendor_event, i); + if (chInfo == NULL) { + hddLog(LOGE, FL("nla_nest_start failed")); + kfree_skb(vendor_event); + return; + } + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH, + pWifiChannelStats->channel.width) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ, + pWifiChannelStats->channel.centerFreq) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0, + pWifiChannelStats->channel.centerFreq0) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1, + pWifiChannelStats->channel.centerFreq1) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME, + pWifiChannelStats->onTime) || + nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME, + pWifiChannelStats->ccaBusyTime)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_put failed")); + kfree_skb(vendor_event); + return ; + } + nla_nest_end(vendor_event, chInfo); + } + nla_nest_end(vendor_event, chList); + } + cfg80211_vendor_cmd_reply(vendor_event); + EXIT(); +} + +/* + * wlan_hdd_cfg80211_link_layer_stats_callback () - This function is called + * after receiving Link Layer indications from FW.This callback converts the + * firmware data to the NL data and send the same to the kernel/upper layers. + */ +static void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, + int indType, + void *pRsp) +{ + hdd_adapter_t *pAdapter = NULL; + struct hdd_ll_stats_context *context; + hdd_context_t *pHddCtx = ctx; + tpSirLLStatsResults linkLayerStatsResults = (tpSirLLStatsResults)pRsp; + int status; + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return; + } + + pAdapter = hdd_get_adapter_by_vdev(pHddCtx, + linkLayerStatsResults->ifaceId); + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vdev_id %d does not exist with host", + __func__, linkLayerStatsResults->ifaceId); + return; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Link Layer Indication indType: %d", __func__, indType); + + switch (indType) + { + case SIR_HAL_LL_STATS_RESULTS_RSP: + { + hddLog(VOS_TRACE_LEVEL_INFO, + "LL_STATS RESP paramID = 0x%x, ifaceId = %u respId = %u, moreResultToFollow = %u, num radio = %u result = %p", + linkLayerStatsResults->paramId, linkLayerStatsResults->ifaceId, + linkLayerStatsResults->rspId, + linkLayerStatsResults->moreResultToFollow, + linkLayerStatsResults->num_radio, + linkLayerStatsResults->results); + + spin_lock(&hdd_context_lock); + context = &pHddCtx->ll_stats_context; + /* validate response received from target */ + if ((context->request_id != linkLayerStatsResults->rspId) || + !(context->request_bitmap & linkLayerStatsResults->paramId)) { + spin_unlock(&hdd_context_lock); + hddLog(LOGE, + FL("Error : Request id %d response id %d request bitmap 0x%x response bitmap 0x%x"), + context->request_id, linkLayerStatsResults->rspId, + context->request_bitmap, linkLayerStatsResults->paramId); + return; + } + spin_unlock(&hdd_context_lock); + + if (linkLayerStatsResults->paramId & WMI_LINK_STATS_RADIO ) + { + hdd_link_layer_process_radio_stats(pAdapter, + linkLayerStatsResults->moreResultToFollow, + (tpSirWifiRadioStat) + linkLayerStatsResults->results, + linkLayerStatsResults->num_radio); + + spin_lock(&hdd_context_lock); + if (!linkLayerStatsResults->moreResultToFollow) + context->request_bitmap &= ~(WMI_LINK_STATS_RADIO); + spin_unlock(&hdd_context_lock); + + } + else if (linkLayerStatsResults->paramId & WMI_LINK_STATS_IFACE ) + { + hdd_link_layer_process_iface_stats(pAdapter, + (tpSirWifiIfaceStat) + linkLayerStatsResults->results, + linkLayerStatsResults->num_peers); + + spin_lock(&hdd_context_lock); + /* Firmware doesn't send peerstats event if no peers are + * connected. HDD should not wait for any peerstats in this case + * and return the status to middlewre after receiving iface + * stats + */ + if (!linkLayerStatsResults->num_peers) + context->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + context->request_bitmap &= ~(WMI_LINK_STATS_IFACE); + spin_unlock(&hdd_context_lock); + + } + else if (linkLayerStatsResults->paramId & WMI_LINK_STATS_ALL_PEER ) + { + hdd_link_layer_process_peer_stats(pAdapter, + linkLayerStatsResults->moreResultToFollow, + (tpSirWifiPeerStat) + linkLayerStatsResults->results); + + spin_lock(&hdd_context_lock); + if (!linkLayerStatsResults->moreResultToFollow) + context->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + spin_unlock(&hdd_context_lock); + + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("INVALID LL_STATS_NOTIFY RESPONSE ***********")); + } + + spin_lock(&hdd_context_lock); + /* complete response event if all requests bitmaps are cleared */ + if (0 == context->request_bitmap) + complete(&context->response_event); + spin_unlock(&hdd_context_lock); + + break; + } + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "invalid event type %d", indType); + break; + } + + return; +} + + +void wlan_hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx) +{ + sme_SetLinkLayerStatsIndCB(pHddCtx->hHal, + wlan_hdd_cfg80211_link_layer_stats_callback); +} + + +const struct +nla_policy +qca_wlan_vendor_ll_set_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING] = + { .type = NLA_U32 }, +}; + +static int __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int status; + struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1]; + tSirLLStatsSetReq LinkLayerStatsSetReq; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL; + + if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX, + (struct nlattr *)data, + data_len, qca_wlan_vendor_ll_set_policy)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("maximum attribute not present")); + return -EINVAL; + } + + if (!tb_vendor + [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("MPDU size Not present")); + return -EINVAL; + } + + if (!tb_vendor[ + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Stats Gathering Not Present")); + return -EINVAL; + } + + /* Shall take the request Id if the Upper layers pass. 1 For now.*/ + LinkLayerStatsSetReq.reqId = 1; + + LinkLayerStatsSetReq.mpduSizeThreshold = + nla_get_u32( + tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]); + + LinkLayerStatsSetReq.aggressiveStatisticsGathering = + nla_get_u32( + tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]); + + LinkLayerStatsSetReq.staId = pAdapter->sessionId; + + hddLog(VOS_TRACE_LEVEL_INFO, + "LL_STATS_SET reqId = %d, staId = %d, mpduSizeThreshold = %d Statistics Gathering = %d ", + LinkLayerStatsSetReq.reqId, LinkLayerStatsSetReq.staId, + LinkLayerStatsSetReq.mpduSizeThreshold, + LinkLayerStatsSetReq.aggressiveStatisticsGathering); + + + + if (eHAL_STATUS_SUCCESS != sme_LLStatsSetReq(pHddCtx->hHal, + &LinkLayerStatsSetReq)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s:" + "sme_LLStatsSetReq Failed", __func__); + return -EINVAL; + } + + pAdapter->isLinkLayerStatsSet = 1; + + EXIT(); + return 0; +} + +/** + * wlan_hdd_cfg80211_ll_stats_set() - set ll stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 if success, non-zero for failure + */ +static int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ll_stats_set(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +const struct +nla_policy +qca_wlan_vendor_ll_get_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX +1] = +{ + /* Unsigned 32bit value provided by the caller issuing the GET stats + * command. When reporting + * the stats results, the driver uses the same value to indicate + * which GET request the results + * correspond to. + */ + [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID] = { .type = NLA_U32 }, + + /* Unsigned 32bit value . bit mask to identify what statistics are + requested for retrieval */ + [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = { .type = NLA_U32 } +}; + +static int __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + unsigned long rc; + struct hdd_ll_stats_context *context; + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1]; + tSirLLStatsGetReq LinkLayerStatsGetReq; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL ; + + if (!pAdapter->isLinkLayerStatsSet) { + hddLog(LOGW, FL("isLinkLayerStatsSet : %d"), + pAdapter->isLinkLayerStatsSet); + return -EINVAL; + } + + if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX, + (struct nlattr *)data, + data_len, qca_wlan_vendor_ll_get_policy)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("max attribute not present")); + return -EINVAL; + } + + if (!tb_vendor + [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request Id Not present")); + return -EINVAL; + } + + if (!tb_vendor + [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Req Mask Not present")); + return -EINVAL; + } + + LinkLayerStatsGetReq.reqId = + nla_get_u32(tb_vendor[ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]); + LinkLayerStatsGetReq.paramIdMask = + nla_get_u32(tb_vendor[ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]); + + LinkLayerStatsGetReq.staId = pAdapter->sessionId; + + hddLog(VOS_TRACE_LEVEL_INFO, + "LL_STATS_GET reqId = %d, StaId = %d, paramIdMask = %d", + LinkLayerStatsGetReq.reqId, LinkLayerStatsGetReq.staId, + LinkLayerStatsGetReq.paramIdMask); + + + spin_lock(&hdd_context_lock); + context = &pHddCtx->ll_stats_context; + context->request_id = LinkLayerStatsGetReq.reqId; + context->request_bitmap = LinkLayerStatsGetReq.paramIdMask; + INIT_COMPLETION(context->response_event); + spin_unlock(&hdd_context_lock); + + if (eHAL_STATUS_SUCCESS != sme_LLStatsGetReq(pHddCtx->hHal, + &LinkLayerStatsGetReq)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s:" + "sme_LLStatsGetReq Failed", __func__); + return -EINVAL; + } + + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(WLAN_WAIT_TIME_LL_STATS)); + if (!rc) { + hddLog(LOGE, + FL("Target response timed out request id %d request bitmap 0x%x"), + context->request_id, context->request_bitmap); + return -ETIMEDOUT; + } + EXIT(); + return 0; +} + +/** + * wlan_hdd_cfg80211_ll_stats_get() - get ll stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 if success, non-zero for failure + */ +static int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +const struct +nla_policy +qca_wlan_vendor_ll_clr_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP] = {.type = NLA_U8 }, +}; + +static int __wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1]; + tSirLLStatsClearReq LinkLayerStatsClearReq; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + u32 statsClearReqMask; + u8 stopReq; + int status; + struct sk_buff *temp_skbuff; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL; + + if (!pAdapter->isLinkLayerStatsSet) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: isLinkLayerStatsSet : %d", + __func__, pAdapter->isLinkLayerStatsSet); + return -EINVAL; + } + + if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX, + (struct nlattr *)data, + data_len, qca_wlan_vendor_ll_clr_policy)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("STATS_CLR_MAX is not present")); + return -EINVAL; + } + + if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] || + !tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Error in LL_STATS CLR CONFIG PARA")); + return -EINVAL; + } + + statsClearReqMask = LinkLayerStatsClearReq.statsClearReqMask = + nla_get_u32( + tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK]); + + stopReq = LinkLayerStatsClearReq.stopReq = + nla_get_u8( + tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]); + + /* + * Shall take the request Id if the Upper layers pass. 1 For now. + */ + LinkLayerStatsClearReq.reqId = 1; + + LinkLayerStatsClearReq.staId = pAdapter->sessionId; + + hddLog(VOS_TRACE_LEVEL_INFO, + "LL_STATS_CLEAR reqId = %d, staId = %d, statsClearReqMask = 0x%X, stopReq = %d", + LinkLayerStatsClearReq.reqId, + LinkLayerStatsClearReq.staId, + LinkLayerStatsClearReq.statsClearReqMask, + LinkLayerStatsClearReq.stopReq); + + + if (eHAL_STATUS_SUCCESS == sme_LLStatsClearReq(pHddCtx->hHal, + &LinkLayerStatsClearReq)) + { + temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + 2 * sizeof(u32) + + 2 * NLMSG_HDRLEN); + if (temp_skbuff != NULL) + { + if (nla_put_u32(temp_skbuff, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK, + statsClearReqMask) || + nla_put_u32(temp_skbuff, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP, + stopReq)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("LL_STATS_CLR put fail")); + kfree_skb(temp_skbuff); + return -EINVAL; + } + + /* If the ask is to stop the stats collection as part of clear + * (stopReq = 1) , ensure that no further requests of get + * go to the firmware by having isLinkLayerStatsSet set to 0. + * However it the stopReq as part of the clear request is 0 , + * the request to get the statistics are honoured as in this + * case the firmware is just asked to clear the statistics. + */ + if (stopReq == 1) + pAdapter->isLinkLayerStatsSet = 0; + + return cfg80211_vendor_cmd_reply(temp_skbuff); + } + EXIT(); + return -ENOMEM; + } + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_ll_stats_clear() - clear ll stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 if success, non-zero for failure + */ +static int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ll_stats_clear(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the Key data + * @data_len:Length of the data passed + * + * This is called when wlan driver needs to save the keys received via + * vendor specific command. + * + * Return: Return the Success or Failure code. + */ +static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE]; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx_ptr; + int status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((data == NULL) || (data_len == 0) || + (data_len > SIR_ROAM_SCAN_PSK_SIZE)) { + hddLog(LOGE, FL("Invalid data")); + return -EINVAL; + } + + hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr); + if (!hdd_ctx_ptr) { + hddLog(LOGE, FL("HDD context is null")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx_ptr); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return status; + } + sme_UpdateRoamKeyMgmtOffloadEnabled(hdd_ctx_ptr->hHal, + hdd_adapter_ptr->sessionId, + TRUE); + vos_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE); + vos_mem_copy(local_pmk, data, data_len); + sme_RoamSetPSK_PMK(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr), + hdd_adapter_ptr->sessionId, local_pmk, data_len); + return 0; +} + +/** + * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the Key data + * @data_len:Length of the data passed + * + * This is called when wlan driver needs to save the keys received via + * vendor specific command. + * + * Return: Return the Success or Failure code. + */ +static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static const struct +nla_policy +qca_wlan_vendor_get_wifi_info_policy[ + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX +1] = { + [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 }, +}; + +/** + * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called when wlan driver needs to send wifi driver related info + * (driver/fw version) to the user space application upon request. + * + * Return: Return the Success or Failure code. + */ +static int +__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1]; + tSirVersionString version; + uint32_t version_len; + uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0; + uint8_t attr; + int status; + struct sk_buff *reply_skb = NULL; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data, + data_len, qca_wlan_vendor_get_wifi_info_policy)) { + hddLog(LOGE, FL("WIFI_INFO_GET NL CMD parsing failed")); + return -EINVAL; + } + + if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) { + hddLog(LOG1, FL("Rcvd req for Driver version")); + strlcpy(version, QWLAN_VERSIONSTR, sizeof(version)); + attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION; + } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) { + hddLog(LOG1, FL("Rcvd req for FW version")); + hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid, + &crmid); + snprintf(version, sizeof(version), "%d:%d:%d:%d", + major_spid, minor_spid, siid, crmid); + attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION; + } else { + hddLog(LOGE, FL("Invalid attribute in get wifi info request")); + return -EINVAL; + } + + version_len = strlen(version); + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + version_len + NLA_HDRLEN + NLMSG_HDRLEN); + if (!reply_skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + if (nla_put(reply_skb, attr, version_len, version)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(reply_skb); + return -EINVAL; + } + + return cfg80211_vendor_cmd_reply(reply_skb); +} + +/** + * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called when wlan driver needs to send wifi driver related info + * (driver/fw version) to the user space application upon request. + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called by userspace to know the supported logger features + * + * Return: Return the Success or Failure code. + */ +static int +__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int status; + uint32_t features; + struct sk_buff *reply_skb = NULL; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + features = 0; + + if (hdd_is_memdump_supported()) + features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; + features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED; + features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; + features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED; + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN); + if (!reply_skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + hddLog(LOG1, FL("Supported logger features: 0x%0x"), features); + if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED, + features)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(reply_skb); + return -EINVAL; + } + + return cfg80211_vendor_cmd_reply(reply_skb); +} + +/** + * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This is called by userspace to know the supported logger features + * + * Return: Return the Success or Failure code. + */ +static int +wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event + * @hdd_ctx_ptr: pointer to HDD Context. + * @bssid: pointer to bssid of roamed AP. + * @req_rsn_ie: Pointer to request RSN IE + * @req_rsn_len: Length of the request RSN IE + * @rsp_rsn_ie: Pointer to response RSN IE + * @rsp_rsn_len: Length of the response RSN IE + * @roam_info_ptr: Pointer to the roaming related information + * + * This is called when wlan driver needs to send the roaming and + * authorization information after roaming. + * + * The information that would be sent is the request RSN IE, response + * RSN IE and BSSID of the newly roamed AP. + * + * If the Authorized status is authenticated, then additional parameters + * like PTK's KCK and KEK and Replay Counter would also be passed to the + * supplicant. + * + * The supplicant upon receiving this event would ignore the legacy + * cfg80211_roamed call and use the entire information from this event. + * The cfg80211_roamed should still co-exist since the kernel will + * make use of the parameters even if the supplicant ignores it. + * + * Return: Return the Success or Failure code. + */ +int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, + uint8_t *req_rsn_ie, uint32_t req_rsn_len, + uint8_t *rsp_rsn_ie, uint32_t rsp_rsn_len, + tCsrRoamInfo *roam_info_ptr) +{ + struct sk_buff *skb = NULL; + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx_ptr)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid ")); + return -EINVAL; + } + + skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy, + NULL, + ETH_ALEN + req_rsn_len + rsp_rsn_len + + sizeof(uint8) + SIR_REPLAY_CTR_LEN + + SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN + + (7 * NLMSG_HDRLEN), + QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX, + GFP_KERNEL); + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + + if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, + ETH_ALEN, bssid) || + nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, + req_rsn_len, req_rsn_ie) || + nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, + rsp_rsn_len, rsp_rsn_ie)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"), + roam_info_ptr->synchAuthStatus); + if (roam_info_ptr->synchAuthStatus == + CSR_ROAM_AUTH_STATUS_AUTHENTICATED) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's")); + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, + TRUE) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, + SIR_REPLAY_CTR_LEN, roam_info_ptr->replay_ctr) + || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, + SIR_KCK_KEY_LEN, roam_info_ptr->kck) + || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, + SIR_KEK_KEY_LEN, roam_info_ptr->kek)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + } else { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's")); + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, + FALSE)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + + +#endif + +#ifdef FEATURE_WLAN_TDLS +/* EXT TDLS */ +static const struct nla_policy +wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = + {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type = NLA_S32 }, + +}; + +static const struct nla_policy +wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, + +}; + +static const struct nla_policy +wlan_hdd_tdls_config_state_change_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {.type = NLA_UNSPEC }, + [QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS] = + {.type = NLA_U32 }, + +}; + +static const struct nla_policy +wlan_hdd_tdls_config_get_status_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {.type = NLA_UNSPEC }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS] + = {.type = NLA_U32 }, + +}; +static int __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint8_t peer[6] = {0}; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX + 1]; + eHalStatus ret; + tANI_U32 state; + tANI_S32 reason; + uint32_t global_operating_class = 0; + uint32_t channel = 0; + struct sk_buff *skb = NULL; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return -EINVAL; + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + return -ENOTSUPP; + } + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX, + data, data_len, + wlan_hdd_tdls_config_get_status_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid attribute")); + return -EINVAL; + } + + /* Parse and fetch mac address */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed")); + return -EINVAL; + } + + memcpy(peer, nla_data( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]), + sizeof(peer)); + hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer)); + + ret = wlan_hdd_tdls_get_status(pAdapter, peer, &global_operating_class, + &channel, &state, &reason); + + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("get status Failed")); + return -EINVAL; + } + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + 4 * sizeof(int32_t) + + NLMSG_HDRLEN); + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Reason %d Status %d class %d channel %d peer " MAC_ADDRESS_STR), + reason, state, global_operating_class, + channel, MAC_ADDR_ARRAY(peer)); + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE, + state) || + nla_put_s32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON, + reason) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS, + global_operating_class) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL, + channel)) { + + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + + ret = cfg80211_vendor_cmd_reply(skb); + EXIT(); + return ret; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_exttdls_get_status() - get ext tdls status + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_exttdls_get_status(wiphy, wdev, data, + data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int wlan_hdd_cfg80211_exttdls_callback(const tANI_U8* mac, + uint32_t global_operating_class, + uint32_t channel, + tANI_U32 state, + tANI_S32 reason, + void *ctx) +{ + hdd_adapter_t* pAdapter = (hdd_adapter_t*)ctx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + struct sk_buff *skb = NULL; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return -EINVAL; + + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + return -ENOTSUPP; + } + skb = cfg80211_vendor_event_alloc( + pHddCtx->wiphy, + NULL, + EXTTDLS_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX, + GFP_KERNEL); + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Reason %d Status %d class %d channel %d peer " MAC_ADDRESS_STR), + reason, state, global_operating_class, + channel, MAC_ADDR_ARRAY(mac)); + + if (nla_put(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR, + VOS_MAC_ADDR_SIZE, mac) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE, + state) || + nla_put_s32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON, + reason) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL, + channel) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS, + global_operating_class) + ) { + + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + EXIT(); + return (0); + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +static int __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint8_t peer[6] = {0}; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX + 1]; + eHalStatus status; + tdls_req_params_t pReqMsg = {0}; + int ret; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL; + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("TDLS External Control is not enabled")); + return -ENOTSUPP; + } + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX, + data, data_len, + wlan_hdd_tdls_config_enable_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch mac address */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed")); + return -EINVAL; + } + + memcpy(peer, nla_data( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]), + sizeof(peer)); + hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer)); + + /* Parse and fetch channel */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed")); + return -EINVAL; + } + pReqMsg.channel = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Channel Num (%d)"), pReqMsg.channel); + + /* Parse and fetch global operating class */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr operating class failed")); + return -EINVAL; + } + pReqMsg.global_operating_class = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Operating class (%d)"), + pReqMsg.global_operating_class); + + /* Parse and fetch latency ms */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr latency failed")); + return -EINVAL; + } + pReqMsg.max_latency_ms = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Latency (%d)"), + pReqMsg.max_latency_ms); + + /* Parse and fetch required bandwidth kbps */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bandwidth failed")); + return -EINVAL; + } + + pReqMsg.min_bandwidth_kbps = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Bandwidth (%d)"), + pReqMsg.min_bandwidth_kbps); + + ret = wlan_hdd_tdls_extctrl_config_peer(pAdapter, + peer, + wlan_hdd_cfg80211_exttdls_callback, + pReqMsg.channel, + pReqMsg.max_latency_ms, + pReqMsg.global_operating_class, + pReqMsg.min_bandwidth_kbps); + EXIT(); + return ret; +} + +/** + * wlan_hdd_cfg80211_exttdls_enable() - enable ext tdls + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_exttdls_enable(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + u8 peer[6] = {0}; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX + 1]; + eHalStatus status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return -EINVAL; + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + + return -ENOTSUPP; + } + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX, + data, data_len, + wlan_hdd_tdls_config_disable_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + /* Parse and fetch mac address */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed")); + return -EINVAL; + } + + memcpy(peer, nla_data( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]), + sizeof(peer)); + hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer)); + + status = wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer); + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_exttdls_disable() - disable ext tdls + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_exttdls_disable(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#endif + + +static const struct nla_policy +wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + +1] = +{ + [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 }, +}; + +/** + * wlan_hdd_disable_dfs_chan_scan () - disable/enable DFS channels + * + * @pHddCtx: HDD context within host driver + * @pAdapter: Adapter pointer + * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning + * + * Loops through devices to see who is operating on DFS channels + * and then disables/enables DFS channels by calling SME API. + * Fails the disable request if any device is active on a DFS channel. + * + * Return: EOK or other error codes. + */ + +int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *pHddCtx, + hdd_adapter_t *pAdapter, + u32 no_dfs_flag) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_adapter_list_node_t *p_adapter_node = NULL, *p_next = NULL; + hdd_adapter_t *p_adapter; + VOS_STATUS vos_status; + hdd_ap_ctx_t *p_ap_ctx; + hdd_station_ctx_t *p_sta_ctx; + eHalStatus status; + int ret_val = -EPERM; + + if (no_dfs_flag == pHddCtx->cfg_ini->enableDFSChnlScan) { + if (no_dfs_flag) { + vos_status = hdd_get_front_adapter( pHddCtx, &p_adapter_node); + while ((NULL != p_adapter_node) && + (VOS_STATUS_SUCCESS == vos_status)) + { + p_adapter = p_adapter_node->pAdapter; + + if (WLAN_HDD_SOFTAP == p_adapter->device_mode) { + p_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(p_adapter); + + /* if there is SAP already running on DFS channel, + do not disable scan on dfs channels. Note that with + SAP on DFS, there cannot be conurrency on single + radio. But then we can have multiple radios !!!!! */ + if (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState( + p_ap_ctx->operatingChannel)) { + hddLog(LOGE, FL("SAP running on DFS channel")); + return -EOPNOTSUPP; + } + } + + if (WLAN_HDD_INFRA_STATION == p_adapter->device_mode) { + p_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(p_adapter); + + /* if STA is already connected on DFS channel, + do not disable scan on dfs channels */ + if (hdd_connIsConnected(p_sta_ctx) && + (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState( + p_sta_ctx->conn_info.operationChannel))) { + hddLog(LOGE, FL("client connected on DFS channel")); + return -EOPNOTSUPP; + } + } + + vos_status = hdd_get_next_adapter(pHddCtx, p_adapter_node, + &p_next); + p_adapter_node = p_next; + } + } + + pHddCtx->cfg_ini->enableDFSChnlScan = !no_dfs_flag; + + hdd_abort_mac_scan_all_adapters(pHddCtx); + + /* call the SME API to tunnel down the new channel list + to the firmware */ + status = sme_handle_dfs_chan_scan(hHal, + pHddCtx->cfg_ini->enableDFSChnlScan); + + if (eHAL_STATUS_SUCCESS == status) { + ret_val = 0; + + /* Clear the SME scan cache also. Note that the clearing of scan + * results is independent of session; so no need to iterate over + * all sessions + */ + status = sme_ScanFlushResult(hHal, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != status) + ret_val = -EPERM; + } + } else { + hddLog(LOG1, FL(" the DFS flag has not changed")); + ret_val = 0; + } + return ret_val; +} + +/** + * __wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command + * + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendof command data buffer + * @data_len: Buffer length + * + * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and + * call wlan_hdd_disable_dfs_chan_scan to send it to firmware. + * + * Return: EOK or other error codes. + */ + +static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1]; + int ret_val = -EPERM; + u32 no_dfs_flag = 0; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((ret_val = wlan_hdd_validate_context(pHddCtx))) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret_val; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX, + data, data_len, + wlan_hdd_set_no_dfs_flag_config_policy)) { + hddLog(LOGE, FL("invalid attr")); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) { + hddLog(LOGE, FL("attr dfs flag failed")); + return -EINVAL; + } + + no_dfs_flag = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]); + + hddLog(LOG1, FL(" DFS flag = %d"), + no_dfs_flag); + + if (no_dfs_flag > 1) { + hddLog(LOGE, FL("invalid value of dfs flag")); + return -EINVAL; + } + + ret_val = wlan_hdd_disable_dfs_chan_scan(pHddCtx, pAdapter, no_dfs_flag); + return ret_val; +} + +/** + * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command + * + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendof command data buffer + * @data_len: Buffer length + * + * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and + * call wlan_hdd_disable_dfs_chan_scan to send it to firmware. + * + * Return: EOK or other error codes. + */ + +static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check + * + * @adapter: SAP adapter pointer + * + * DFS in MCC is not supported for Multi bssid SAP mode due to single physical + * radio. So in case of DFS MCC scenario override current SAP given config + * to follow concurrent SAP DFS config + * + * Return: 0 - No DFS issue, 1 - Override done and negative error codes + */ + +#ifdef WLAN_FEATURE_MBSSID +static int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter) +{ + hdd_adapter_t *con_sap_adapter; + tsap_Config_t *sap_config, *con_sap_config; + int con_ch; + + /* + * Check if AP+AP case, once primary AP chooses a DFS + * channel secondary AP should always follow primary APs channel + */ + if (!vos_concurrent_beaconing_sessions_running()) + return 0; + + con_sap_adapter = hdd_get_con_sap_adapter(adapter, true); + if (!con_sap_adapter) + return 0; + + sap_config = &adapter->sessionCtx.ap.sapConfig; + con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig; + con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel; + + if (!VOS_IS_DFS_CH(con_ch)) + return 0; + + hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"), + sap_config->channel, con_ch); + hddLog(LOG1, FL("Overriding guest AP's channel")); + sap_config->channel = con_ch; + + if (con_sap_config->acs_cfg.acs_mode == true) { + if (con_ch != con_sap_config->acs_cfg.pri_ch && + con_ch != con_sap_config->acs_cfg.ht_sec_ch) { + hddLog(LOGE, FL("Primary AP channel config error")); + hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"), + con_ch, con_sap_config->acs_cfg.pri_ch, + con_sap_config->acs_cfg.ht_sec_ch); + return -EINVAL; + } + /* Sec AP ACS info is overwritten with Pri AP due to DFS + * MCC restriction. So free ch list allocated in do_acs + * func for Sec AP and realloc for Pri AP ch list size + */ + if (sap_config->acs_cfg.ch_list) + vos_mem_free(sap_config->acs_cfg.ch_list); + + vos_mem_copy(&sap_config->acs_cfg, + &con_sap_config->acs_cfg, + sizeof(struct sap_acs_cfg)); + sap_config->acs_cfg.ch_list = vos_mem_malloc( + sizeof(uint8_t) * + con_sap_config->acs_cfg.ch_list_count); + if (!sap_config->acs_cfg.ch_list) { + hddLog(LOGE, FL("ACS config alloc fail")); + return -ENOMEM; + } + + vos_mem_copy(sap_config->acs_cfg.ch_list, + con_sap_config->acs_cfg.ch_list, + con_sap_config->acs_cfg.ch_list_count); + + } else { + sap_config->acs_cfg.pri_ch = con_ch; + if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ) + sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch; + } + + return con_ch; +} +#else +static int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter) +{ + return 0; +} +#endif + + + +static int wlan_hdd_config_acs(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) +{ + tsap_Config_t *sap_config; + hdd_config_t *ini_config; + tHalHandle hal; + + hal = WLAN_HDD_GET_HAL_CTX(adapter); + sap_config = &adapter->sessionCtx.ap.sapConfig; + ini_config = hdd_ctx->cfg_ini; + + sap_config->enOverLapCh = !!hdd_ctx->cfg_ini->gEnableOverLapCh; +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + hddLog(LOG1, FL("HDD_ACS_SKIP_STATUS = %d"), hdd_ctx->skip_acs_scan_status); + + if (hdd_ctx->skip_acs_scan_status == eSAP_SKIP_ACS_SCAN) { + hdd_adapter_t *con_sap_adapter; + tsap_Config_t *con_sap_config = NULL; + + con_sap_adapter = hdd_get_con_sap_adapter(adapter, false); + + if (con_sap_adapter) + con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig; + + sap_config->acs_cfg.skip_scan_status = eSAP_DO_NEW_ACS_SCAN; + + if (con_sap_config && con_sap_config->acs_cfg.acs_mode == true && + hdd_ctx->skip_acs_scan_status == eSAP_SKIP_ACS_SCAN) { + + if (con_sap_config->acs_cfg.hw_mode == sap_config->acs_cfg.hw_mode) { + v_U8_t con_sap_st_ch, con_sap_end_ch; + v_U8_t cur_sap_st_ch, cur_sap_end_ch; + v_U8_t bandStartChannel, bandEndChannel; + + con_sap_st_ch = con_sap_config->acs_cfg.start_ch; + con_sap_end_ch = con_sap_config->acs_cfg.end_ch; + cur_sap_st_ch = sap_config->acs_cfg.start_ch; + cur_sap_end_ch = sap_config->acs_cfg.end_ch; + + WLANSAP_extend_to_acs_range(&cur_sap_st_ch, &cur_sap_end_ch, + &bandStartChannel, &bandEndChannel); + + WLANSAP_extend_to_acs_range(&con_sap_st_ch, &con_sap_end_ch, + &bandStartChannel, &bandEndChannel); + + if (con_sap_st_ch <= cur_sap_st_ch && + con_sap_end_ch >= cur_sap_end_ch) { + + sap_config->acs_cfg.skip_scan_status = eSAP_SKIP_ACS_SCAN; + + } else if (con_sap_st_ch >= cur_sap_st_ch && + con_sap_end_ch >= cur_sap_end_ch) { + + sap_config->acs_cfg.skip_scan_status = eSAP_DO_PAR_ACS_SCAN; + + sap_config->acs_cfg.skip_scan_range1_stch = cur_sap_st_ch; + sap_config->acs_cfg.skip_scan_range1_endch = + con_sap_st_ch - 1; + sap_config->acs_cfg.skip_scan_range2_stch = 0; + sap_config->acs_cfg.skip_scan_range2_endch = 0; + + } else if (con_sap_st_ch <= cur_sap_st_ch && + con_sap_end_ch <= cur_sap_end_ch) { + + sap_config->acs_cfg.skip_scan_status = eSAP_DO_PAR_ACS_SCAN; + + sap_config->acs_cfg.skip_scan_range1_stch = + con_sap_end_ch + 1; + sap_config->acs_cfg.skip_scan_range1_endch = cur_sap_end_ch; + sap_config->acs_cfg.skip_scan_range2_stch = 0; + sap_config->acs_cfg.skip_scan_range2_endch = 0; + + } else if (con_sap_st_ch >= cur_sap_st_ch && + con_sap_end_ch <= cur_sap_end_ch) { + + sap_config->acs_cfg.skip_scan_status = eSAP_DO_PAR_ACS_SCAN; + + sap_config->acs_cfg.skip_scan_range1_stch = cur_sap_st_ch; + sap_config->acs_cfg.skip_scan_range1_endch = + con_sap_st_ch - 1; + sap_config->acs_cfg.skip_scan_range2_stch = con_sap_end_ch; + sap_config->acs_cfg.skip_scan_range2_endch = + cur_sap_end_ch + 1; + + } else + sap_config->acs_cfg.skip_scan_status = eSAP_DO_NEW_ACS_SCAN; + } + hddLog(LOG1, + FL("SecAP ACS Skip = %d, ACS CH RANGE = %d-%d, %d-%d"), + sap_config->acs_cfg.skip_scan_status, + sap_config->acs_cfg.skip_scan_range1_stch, + sap_config->acs_cfg.skip_scan_range1_endch, + sap_config->acs_cfg.skip_scan_range2_stch, + sap_config->acs_cfg.skip_scan_range2_endch); + } + } +#endif + + return 0; +} + +/** + * wlan_hdd_set_acs_ch_range : Start ACS channel range values + * @sap_cfg: pointer to SAP config struct + * + * This function sets the default ACS start and end channel for the given band + * and also parses the given ACS channel list. + * + * Return: None + */ + +static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled, + bool vht_enabled) +{ + int i; + if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) { + sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b; + sap_cfg->acs_cfg.start_ch = rfChannels[RF_CHAN_1].channelNum; + sap_cfg->acs_cfg.end_ch = rfChannels[RF_CHAN_14].channelNum; + } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) { + sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g; + sap_cfg->acs_cfg.start_ch = rfChannels[RF_CHAN_1].channelNum; + sap_cfg->acs_cfg.end_ch = rfChannels[RF_CHAN_13].channelNum; + } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) { + sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a; + sap_cfg->acs_cfg.start_ch = rfChannels[RF_CHAN_36].channelNum; + sap_cfg->acs_cfg.end_ch = rfChannels[RF_CHAN_165].channelNum; + } + if (ht_enabled) + sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n; + + if (vht_enabled) + sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac; + + + /* Parse ACS Chan list from hostapd */ + if (!sap_cfg->acs_cfg.ch_list) + return; + + sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0]; + sap_cfg->acs_cfg.end_ch = + sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1]; + for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) { + if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i]) + sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i]; + if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i]) + sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i]; + } + +} + + +static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work); + +/** + * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP + * @adapter: pointer to SAP adapter struct + * + * This function starts the ACS procedure if there are no + * constraints like MBSSID DFS restrictions. + * + * Return: Status of ACS Start procedure + */ + +static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter) +{ + + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tsap_Config_t *sap_config; + tpWLAN_SAPEventCB acs_event_callback; + int status; + + sap_config = &adapter->sessionCtx.ap.sapConfig; + sap_config->channel = AUTO_CHANNEL_SELECT; + status = wlan_hdd_sap_cfg_dfs_override(adapter); + if (status < 0) { + return status; + } else { + if (status > 0) { + /* notify hostapd about channel override */ + wlan_hdd_cfg80211_acs_ch_select_evt(adapter); + clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags); + return 0; + } + } + + status = wlan_hdd_config_acs(hdd_ctx, adapter); + if (status) { + hddLog(LOGE, FL("ACS config failed")); + return -EINVAL; + } + + acs_event_callback = hdd_hostapd_SAPEventCB; + + vos_mem_copy(sap_config->self_macaddr.bytes, + adapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t)); + hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex); + status = WLANSAP_ACS_CHSelect( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(adapter), +#else + hdd_ctx->pvosContext, +#endif + acs_event_callback, sap_config, (v_PVOID_t)adapter->dev); + + + if (status) { + hddLog(LOGE, FL("ACS channel select failed")); + return -EINVAL; + } + sap_config->acs_cfg.acs_mode = true; + set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags); + + return 0; +} + +/** + * __wlan_hdd_cfg80211_do_acs : CFG80211 handler fucntion for DO_ACS Vendor CMD + * @wiphy: Linux wiphy struct pointer + * @wdev: Linux wireless device struct pointer + * @data: ACS information from hostapd + * @data_len: ACS information len + * + * This function handle DO_ACS Vendor command from hostapd, parses ACS config + * and starts ACS procedure. + * + * Return: ACS procedure start status + */ + +static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct net_device *ndev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + tsap_Config_t *sap_config; + struct sk_buff *temp_skbuff; + int status = -EINVAL, i = 0; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1]; + bool ht_enabled, ht40_enabled, vht_enabled; + uint8_t ch_width; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (hdd_ctx->cfg_ini->force_sap_acs) { + hddLog(LOGE, FL("Hostapd ACS rejected as driver INI force ACS is enabled")); + return -EPERM; + } + + /* ***Note*** Donot set SME config related to ACS operation here because + * ACS operation is not synchronouse and ACS for Second AP may come when + * ACS operation for first AP is going on. So only do_acs is split to + * seperate start_acs routine. Also SME-PMAC struct that is used to + * pass paremeters from HDD to SAP is global. Thus All ACS related SME + * config shall be set only from start_acs. + */ + + /* nla_policy Policy template. Policy not applied as some attributes are + * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length + * + * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, + * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, + * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, + * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, + * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, + * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED }, + */ + + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + sap_config = &adapter->sessionCtx.ap.sapConfig; + vos_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg)); + + status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len, + NULL); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + goto out; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed")); + goto out; + } + sap_config->acs_cfg.hw_mode = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]); + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]) + ht_enabled = + nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]); + else + ht_enabled = 0; + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]) + ht40_enabled = + nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]); + else + ht40_enabled = 0; + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]) + vht_enabled = + nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]); + else + vht_enabled = 0; + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) { + ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]); + } else { + if (ht_enabled && ht40_enabled) + ch_width = 40; + else + ch_width = 20; + } + if (ch_width == 80) + sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_80MHZ; + else if (ch_width == 40) + sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ; + else + sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_20MHZ; + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) { + char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]); + sap_config->acs_cfg.ch_list_count = nla_len( + tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]); + if (sap_config->acs_cfg.ch_list_count) { + sap_config->acs_cfg.ch_list = vos_mem_malloc( + sizeof(uint8_t) * + sap_config->acs_cfg.ch_list_count); + if (sap_config->acs_cfg.ch_list == NULL) { + hddLog(LOGE, FL("ACS config alloc fail")); + status = -ENOMEM; + goto out; + } + vos_mem_copy(sap_config->acs_cfg.ch_list, tmp, + sap_config->acs_cfg.ch_list_count); + } + } + wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled); + + /* ACS override for android */ + if (hdd_ctx->cfg_ini->sap_p2p_11ac_override && ht_enabled) { + hddLog(LOG1, FL("ACS Config override for 11AC")); + vht_enabled = 1; + sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac; + sap_config->acs_cfg.ch_width = + hdd_ctx->cfg_ini->vhtChannelWidth; + /* No VHT80 in 2.4G so perform ACS accordingly */ + if (sap_config->acs_cfg.end_ch <= 14 && + sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) + sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ; + } + + hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"), + adapter->dev->ifindex, sap_config->acs_cfg.hw_mode, + ch_width, ht_enabled, vht_enabled, + sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch); + + if (sap_config->acs_cfg.ch_list_count) { + hddLog(LOG1, FL("ACS channel list: len: %d"), + sap_config->acs_cfg.ch_list_count); + for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) + hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]); + } + sap_config->acs_cfg.acs_mode = true; + if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) { + /* ***Note*** Completion variable usage is not allowed here since + * ACS scan operation may take max 2.2 sec for 5G band. + * 9 Active channel X 40 ms active scan time + + * 16 Passive channel X 110ms passive scan time + * Since this CFG80211 call lock rtnl mutex, we cannot hold on + * for this long. So we split up the scanning part. + */ + set_bit(ACS_PENDING, &adapter->event_flags); + hddLog(LOG1, FL("ACS Pending for wlan%d"), + adapter->dev->ifindex); + status = 0; + } else { + status = wlan_hdd_cfg80211_start_acs(adapter); + } + +out: + if (0 == status) { + temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + NLMSG_HDRLEN); + if (temp_skbuff != NULL) + return cfg80211_vendor_cmd_reply(temp_skbuff); + } + + clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags); + + return status; +} + +/** + * wlan_hdd_cfg80211_do_acs : CFG80211 handler fucntion for DO_ACS Vendor CMD + * @wiphy: Linux wiphy struct pointer + * @wdev: Linux wireless device struct pointer + * @data: ACS information from hostapd + * @data_len: ACS information len + * + * This function handle DO_ACS Vendor command from hostapd, parses ACS config + * and starts ACS procedure. + * + * Return: ACS procedure start status + */ + +static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP + * @work: Linux workqueue struct pointer for ACS work + * + * This function starts the ACS procedure which was marked pending when an ACS + * procedure was in progress for a concurrent SAP interface. + * + * Return: None + */ + +static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work) +{ + hdd_adapter_t *adapter = container_of(work, hdd_adapter_t, + acs_pending_work.work); + wlan_hdd_cfg80211_start_acs(adapter); +} + +/** + * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt + * @adapter: Pointer to SAP adapter struct + * @pri_channel: SAP ACS procedure selected Primary channel + * @sec_channel: SAP ACS procedure selected secondary channel + * + * This is a callback function from SAP module on ACS procedure is completed. + * This function send the ACS selected channel information to hostapd + * + * Return: None + */ + +void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig; + struct sk_buff *vendor_event; + int ret_val; + struct nlattr *nla; + hdd_adapter_t *con_sap_adapter; + uint16_t ch_width; + + vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, + NULL, + 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + /* Send the IF INDEX to differentiate the ACS event for each interface + * TODO: To be update once cfg80211 APIs are updated to accept if_index + */ + nla_nest_cancel(vendor_event, ((void **)vendor_event->cb)[2]); + + ret_val = nla_put_u32(vendor_event, NL80211_ATTR_IFINDEX, + adapter->dev->ifindex); + if (ret_val) { + hddLog(LOGE, FL("NL80211_ATTR_IFINDEX put fail")); + kfree_skb(vendor_event); + return; + } + + nla = nla_nest_start(vendor_event, NL80211_ATTR_VENDOR_DATA); + ((void **)vendor_event->cb)[2] = nla; + + ret_val = nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, + sap_cfg->acs_cfg.pri_ch); + if (ret_val) { + hddLog(LOGE, + FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail")); + kfree_skb(vendor_event); + return; + } + + ret_val = nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, + sap_cfg->acs_cfg.ht_sec_ch); + if (ret_val) { + hddLog(LOGE, + FL( + "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail")); + kfree_skb(vendor_event); + return; + } + + ret_val = nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, + sap_cfg->acs_cfg.vht_seg0_center_ch); + if (ret_val) { + hddLog(LOGE, + FL( + "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail")); + kfree_skb(vendor_event); + return; + } + + ret_val = nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + sap_cfg->acs_cfg.vht_seg1_center_ch); + if (ret_val) { + hddLog(LOGE, + FL( + "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail")); + kfree_skb(vendor_event); + return; + } + + if (sap_cfg->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) + ch_width = 80; + else if (sap_cfg->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_40MHZ) + ch_width = 40; + else + ch_width = 20; + + ret_val = nla_put_u16(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH, + ch_width); + if (ret_val) { + hddLog(LOGE, + FL( + "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail")); + kfree_skb(vendor_event); + return; + } + + hddLog(LOG1, + FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"), + adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch, + sap_cfg->acs_cfg.ht_sec_ch,sap_cfg->acs_cfg.vht_seg0_center_ch, + sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width); + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + /* ***Note*** As already mentioned Completion variable usage is not + * allowed here since ACS scan operation may take max 2.2 sec. + * Further in AP-AP mode pending ACS is resumed here to serailize ACS + * operation. + * TODO: Delayed operation is used since SME-PMAC strut is global. Thus + * when Primary AP ACS is complete and secondary AP ACS is started here + * immediately, Primary AP start_bss may come inbetween ACS operation + * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with + * delay. This path and below constraint will be removed on sessionizing + * SAP acs parameters and decoupling SAP from PMAC (WIP). + * As per design constraint user space control application must take + * care of serailizing hostapd start for each VIF in AP-AP mode to avoid + * this code path. Sec AP hostapd should be started after Primary AP + * start beaconing which can be confirmed by getchannel iwpriv command + */ + + con_sap_adapter = hdd_get_con_sap_adapter(adapter, false); + if (con_sap_adapter && + test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) { +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&con_sap_adapter->acs_pending_work, + wlan_hdd_cfg80211_start_pending_acs); +#else + INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work, + wlan_hdd_cfg80211_start_pending_acs); +#endif + /* Lets give 500ms for OBSS + START_BSS to complete */ + schedule_delayed_work(&con_sap_adapter->acs_pending_work, + msecs_to_jiffies(500)); + clear_bit(ACS_PENDING, &con_sap_adapter->event_flags); + } + + return; +} + +static const struct nla_policy +wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + +1] = +{ + [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 }, +}; + + +/** + * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration + * vendor command + * + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendor command data buffer + * @data_len: Buffer length + * + * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX. + * + * Return: EOK or other error codes. + */ +static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1]; + int ret_val = 0; + u32 modulated_dtim; + u16 stats_avg_factor; + u32 guard_time; + eHalStatus status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret_val = wlan_hdd_validate_context(pHddCtx); + if (ret_val) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret_val; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, + data, data_len, + wlan_hdd_wifi_config_policy)) { + hddLog(LOGE, FL("invalid attr")); + return -EINVAL; + } + + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) { + modulated_dtim = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]); + + status = sme_configure_modulated_dtim(pHddCtx->hHal, + pAdapter->sessionId, + modulated_dtim); + + if (eHAL_STATUS_SUCCESS != status) + ret_val = -EPERM; + } + + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) { + stats_avg_factor = nla_get_u16( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]); + status = sme_configure_stats_avg_factor(pHddCtx->hHal, + pAdapter->sessionId, + stats_avg_factor); + + if (eHAL_STATUS_SUCCESS != status) + ret_val = -EPERM; + } + + + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) { + guard_time = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]); + status = sme_configure_guard_time(pHddCtx->hHal, + pAdapter->sessionId, + guard_time); + + if (eHAL_STATUS_SUCCESS != status) + ret_val = -EPERM; + } + + return ret_val; +} + +/** + * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration + * vendor command + * + * @wiphy: wiphy device pointer + * @wdev: wireless device pointer + * @data: Vendor command data buffer + * @data_len: Buffer length + * + * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX. + * + * Return: EOK or other error codes. + */ +static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef FEATURE_WLAN_TDLS + +/* TDLS capabilities params */ +#define PARAM_MAX_TDLS_SESSION \ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS +#define PARAM_TDLS_FEATURE_SUPPORT \ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED + +/** + * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites. + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function provides TDLS capabilities + * + * Return: 0 on success and errno on failure + */ +static int +__wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int status; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct sk_buff *skb; + uint32_t set = 0; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (status) + return status; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) + + NLMSG_HDRLEN); + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + goto fail; + } + + if (FALSE == hdd_ctx->cfg_ini->fEnableTDLSSupport) { + hddLog(LOGE, + FL("TDLS feature not Enabled or Not supported in FW")); + if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) || + nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) { + hddLog(LOGE, FL("nla put fail")); + goto fail; + } + } else { + set = set | WIFI_TDLS_SUPPORT; + set = set | (hdd_ctx->cfg_ini->fTDLSExternalControl ? + WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0); + set = set | (hdd_ctx->cfg_ini->fEnableTDLSOffChannel ? + WIIF_TDLS_OFFCHANNEL_SUPPORT : 0); + hddLog(LOG1, FL("TDLS Feature supported value %x"), set); + if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, + hdd_ctx->max_num_tdls_sta) || + nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, + set)) { + hddLog(LOGE, FL("nla put fail")); + goto fail; + } + } + return cfg80211_vendor_cmd_reply(skb); +fail: + if (skb) + kfree_skb(skb); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites. + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function provides TDLS capabilities + * + * Return: 0 on success and errno on failure + */ +static int +wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +static const struct +nla_policy +qca_wlan_vendor_wifi_logger_start_policy +[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID] + = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL] + = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS] + = {.type = NLA_U32 }, +}; + +/** + * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable + * or disable the collection of packet statistics from the firmware + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function is used to enable or disable the collection of packet + * statistics from the firmware + * + * Return: 0 on success and errno on failure + */ +static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + eHalStatus status; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1]; + struct sir_wifi_start_log start_log; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX, + data, data_len, + qca_wlan_vendor_wifi_logger_start_policy)) { + hddLog(LOGE, FL("Invalid attribute")); + return -EINVAL; + } + + /* Parse and fetch ring id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) { + hddLog(LOGE, FL("attr ATTR failed")); + return -EINVAL; + } + start_log.ring_id = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]); + hddLog(LOG1, FL("Ring ID=%d"), start_log.ring_id); + + /* Parse and fetch verbose level */ + if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) { + hddLog(LOGE, FL("attr verbose_level failed")); + return -EINVAL; + } + start_log.verbose_level = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]); + hddLog(LOG1, FL("verbose_level=%d"), start_log.verbose_level); + + /* Parse and fetch flag */ + if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) { + hddLog(LOGE, FL("attr flag failed")); + return -EINVAL; + } + start_log.flag = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]); + hddLog(LOG1, FL("flag=%d"), start_log.flag); + + vos_set_ring_log_level(start_log.ring_id, start_log.verbose_level); + + if (start_log.ring_id == RING_ID_WAKELOCK) { + /* Start/stop wakelock events */ + if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF) + vos_set_wakelock_logging(true); + else + vos_set_wakelock_logging(false); + return 0; + } + + status = sme_wifi_start_logger(hdd_ctx->hHal, start_log); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"), + status); + return -EINVAL; + } + return 0; +} + +static const struct +nla_policy +qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = { + [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC }, +}; + +/** + * __wlan_hdd_cfg80211_get_link_properties() - This function is used to + * get link properties like nss, rate flags and operating frequency for + * the connection with the given peer. + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function return the above link properties on success. + * + * Return: 0 on success and errno on failure + */ +static int __wlan_hdd_cfg80211_get_link_properties(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); + hdd_station_ctx_t *hdd_sta_ctx; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1]; + uint8_t peer_mac[VOS_MAC_ADDR_SIZE]; + uint32_t sta_id; + struct sk_buff *reply_skb; + uint32_t rate_flags = 0; + uint8_t nss; + uint8_t final_rate_flags = 0; + uint32_t freq; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, + qca_wlan_vendor_attr_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid attribute")); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Attribute peerMac not provided for mode=%d"), + adapter->device_mode); + return -EINVAL; + } + + memcpy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]), + sizeof(peer_mac)); + hddLog(VOS_TRACE_LEVEL_INFO, + FL("peerMac="MAC_ADDRESS_STR" for device_mode:%d"), + MAC_ADDR_ARRAY(peer_mac), adapter->device_mode); + + 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) || + !vos_mem_compare(hdd_sta_ctx->conn_info.bssId, peer_mac, + VOS_MAC_ADDRESS_LEN)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Not Associated to mac "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(peer_mac)); + return -EINVAL; + } + + nss = hdd_sta_ctx->conn_info.nss; + freq = vos_chan_to_freq( + hdd_sta_ctx->conn_info.operationChannel); + rate_flags = hdd_sta_ctx->conn_info.rate_flags; + } else if (adapter->device_mode == WLAN_HDD_P2P_GO || + adapter->device_mode == WLAN_HDD_SOFTAP) { + + for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { + if (adapter->aStaInfo[sta_id].isUsed && + !vos_is_macaddr_broadcast( + &adapter->aStaInfo[sta_id].macAddrSTA) && + vos_mem_compare( + &adapter->aStaInfo[sta_id].macAddrSTA, + peer_mac, VOS_MAC_ADDRESS_LEN)) + break; + } + + if (WLAN_MAX_STA_COUNT == sta_id) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("No active peer with mac="MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(peer_mac)); + return -EINVAL; + } + + nss = adapter->aStaInfo[sta_id].nss; + freq = vos_chan_to_freq( + (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel); + rate_flags = adapter->aStaInfo[sta_id].rate_flags; + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Not Associated! with mac"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(peer_mac)); + return -EINVAL; + } + + if (!(rate_flags & eHAL_TX_RATE_LEGACY)) { + if (rate_flags & eHAL_TX_RATE_VHT80) { + final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS; + final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + } else if (rate_flags & eHAL_TX_RATE_VHT40) { + final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS; + final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } else if (rate_flags & eHAL_TX_RATE_VHT20) { + final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS; + } else if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) { + final_rate_flags |= RATE_INFO_FLAGS_MCS; + if (rate_flags & eHAL_TX_RATE_HT40) + final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } + + if (rate_flags & eHAL_TX_RATE_SGI) { + if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS)) + final_rate_flags |= RATE_INFO_FLAGS_MCS; + final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI; + } + } + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN); + + if (NULL == reply_skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("getLinkProperties: skb alloc failed")); + return -EINVAL; + } + + if (nla_put_u8(reply_skb, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS, + nss) || + nla_put_u8(reply_skb, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS, + final_rate_flags) || + nla_put_u32(reply_skb, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ, + freq)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_put failed")); + kfree_skb(reply_skb); + return -EINVAL; + } + + return cfg80211_vendor_cmd_reply(reply_skb); +} + +/** + * wlan_hdd_cfg80211_get_link_properties() - This function is used to + * get link properties like nss, rate flags and operating frequency for + * the connection with the given peer. + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function return the above link properties on success. + * + * Return: 0 on success and errno on failure + */ +static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable + * or disable the collection of packet statistics from the firmware + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function is used to enable or disable the collection of packet + * statistics from the firmware + * + * Return: 0 on success and errno on failure + */ +static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, + wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +static const struct +nla_policy +qca_wlan_vendor_wifi_logger_get_ring_data_policy +[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID] + = {.type = NLA_U32 }, +}; + +/** + * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function is used to flush or retrieve the per packet statistics from + * the driver + * + * Return: 0 on success and errno on failure + */ +static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + eHalStatus status; + VOS_STATUS ret; + uint32_t ring_id; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb + [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1]; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX, + data, data_len, + qca_wlan_vendor_wifi_logger_get_ring_data_policy)) { + hddLog(LOGE, FL("Invalid attribute")); + return -EINVAL; + } + + /* Parse and fetch ring id */ + if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) { + hddLog(LOGE, FL("attr ATTR failed")); + return -EINVAL; + } + + ring_id = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]); + + if (ring_id == RING_ID_PER_PACKET_STATS) { + wlan_logging_set_per_pkt_stats(); + hddLog(LOG1, FL("Flushing/Retrieving packet stats")); + } + + hddLog(LOG1, FL("Bug report triggered by framework")); + + ret = vos_flush_logs(WLAN_LOG_TYPE_NON_FATAL, + WLAN_LOG_INDICATOR_FRAMEWORK, + WLAN_LOG_REASON_CODE_UNUSED); + if (VOS_STATUS_SUCCESS != ret) { + hddLog(LOGE, FL("Failed to trigger bug report")); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats + * @wiphy: WIPHY structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of the data received + * + * This function is used to flush or retrieve the per packet statistics from + * the driver + * + * Return: 0 on success and errno on failure + */ +static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, + wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS +/** + * hdd_map_req_id_to_pattern_id() - map request id to pattern id + * @hdd_ctx: HDD context + * @request_id: [input] request id + * @pattern_id: [output] pattern id + * + * This function loops through request id to pattern id array + * if the slot is available, store the request id and return pattern id + * if entry exists, return the pattern id + * + * Return: 0 on success and errno on failure + */ +static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx, + uint32_t request_id, + uint8_t *pattern_id) +{ + uint32_t i; + + mutex_lock(&hdd_ctx->op_ctx.op_lock); + for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) { + if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) { + hdd_ctx->op_ctx.op_table[i].request_id = request_id; + *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id; + mutex_unlock(&hdd_ctx->op_ctx.op_lock); + return 0; + } else if (hdd_ctx->op_ctx.op_table[i].request_id == + request_id) { + *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id; + mutex_unlock(&hdd_ctx->op_ctx.op_lock); + return 0; + } + } + mutex_unlock(&hdd_ctx->op_ctx.op_lock); + return -EINVAL; +} + +/** + * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id + * @hdd_ctx: HDD context + * @request_id: [input] request id + * @pattern_id: [output] pattern id + * + * This function loops through request id to pattern id array + * reset request id to 0 (slot available again) and + * return pattern id + * + * Return: 0 on success and errno on failure + */ +static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx, + uint32_t request_id, + uint8_t *pattern_id) +{ + uint32_t i; + + mutex_lock(&hdd_ctx->op_ctx.op_lock); + for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) { + if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) { + hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID; + *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id; + mutex_unlock(&hdd_ctx->op_ctx.op_lock); + return 0; + } + } + mutex_unlock(&hdd_ctx->op_ctx.op_lock); + return -EINVAL; +} + + +/* + * define short names for the global vendor params + * used by __wlan_hdd_cfg80211_offloaded_packets() + */ +#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX +#define PARAM_REQUEST_ID \ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID +#define PARAM_CONTROL \ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL +#define PARAM_IP_PACKET \ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA +#define PARAM_SRC_MAC_ADDR \ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR +#define PARAM_DST_MAC_ADDR \ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR +#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD + +/** + * wlan_hdd_add_tx_ptrn() - add tx pattern + * @adapter: adapter pointer + * @hdd_ctx: hdd context + * @tb: nl attributes + * + * This function reads the NL attributes and forms a AddTxPtrn message + * posts it to SME. + * + */ +static int +wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx, + struct nlattr **tb) +{ + struct sSirAddPeriodicTxPtrn *add_req; + eHalStatus status; + uint32_t request_id, ret, len; + uint8_t pattern_id = 0; + v_MACADDR_t dst_addr; + uint16_t eth_type = htons(ETH_P_IP); + + if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + hddLog(LOGE, FL("Not in Connected state!")); + return -ENOTSUPP; + } + + add_req = vos_mem_malloc(sizeof(*add_req)); + if (!add_req) { + hddLog(LOGE, FL("memory allocation failed")); + return -ENOMEM; + } + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + + request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); + if (request_id == MAX_REQUEST_ID) { + hddLog(LOGE, FL("request_id cannot be MAX")); + return -EINVAL; + } + + hddLog(LOG1, FL("Request Id: %u"), request_id); + + if (!tb[PARAM_PERIOD]) { + hddLog(LOGE, FL("attr period failed")); + goto fail; + } + add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]); + hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs); + if (add_req->usPtrnIntervalMs == 0) { + hddLog(LOGE, FL("Invalid interval zero, return failure")); + goto fail; + } + + if (!tb[PARAM_SRC_MAC_ADDR]) { + hddLog(LOGE, FL("attr source mac address failed")); + goto fail; + } + nla_memcpy(add_req->macAddress, tb[PARAM_SRC_MAC_ADDR], + VOS_MAC_ADDR_SIZE); + hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(add_req->macAddress)); + + if (memcmp(add_req->macAddress, adapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE)) { + hddLog(LOGE, FL("input src mac address and connected ap bssid are different")); + goto fail; + } + + if (!tb[PARAM_DST_MAC_ADDR]) { + hddLog(LOGE, FL("attr dst mac address failed")); + goto fail; + } + nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], VOS_MAC_ADDR_SIZE); + hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(dst_addr.bytes)); + + if (!tb[PARAM_IP_PACKET]) { + hddLog(LOGE, FL("attr ip packet failed")); + goto fail; + } + add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]); + hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize); + + if (add_req->ucPtrnSize < 0 || + add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE - + HDD_ETH_HEADER_LEN)) { + hddLog(LOGE, FL("Invalid IP packet len: %d"), + add_req->ucPtrnSize); + goto fail; + } + + len = 0; + vos_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, VOS_MAC_ADDR_SIZE); + len += VOS_MAC_ADDR_SIZE; + vos_mem_copy(&add_req->ucPattern[len], add_req->macAddress, + VOS_MAC_ADDR_SIZE); + len += VOS_MAC_ADDR_SIZE; + vos_mem_copy(&add_req->ucPattern[len], ð_type, 2); + len += 2; + + /* + * This is the IP packet, add 14 bytes Ethernet (802.3) header + * ------------------------------------------------------------ + * | 14 bytes Ethernet (802.3) header | IP header and payload | + * ------------------------------------------------------------ + */ + vos_mem_copy(&add_req->ucPattern[len], + nla_data(tb[PARAM_IP_PACKET]), + add_req->ucPtrnSize); + add_req->ucPtrnSize += len; + + ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id); + if (ret) { + hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret); + goto fail; + } + add_req->ucPtrnId = pattern_id; + hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId); + + status = sme_AddPeriodicTxPtrn(hdd_ctx->hHal, add_req); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_AddPeriodicTxPtrn failed (err=%d)"), status); + goto fail; + } + + EXIT(); + vos_mem_free(add_req); + return 0; + +fail: + vos_mem_free(add_req); + return -EINVAL; +} + +/** + * wlan_hdd_del_tx_ptrn() - delete tx pattern + * @adapter: adapter pointer + * @hdd_ctx: hdd context + * @tb: nl attributes + * + * This function reads the NL attributes and forms a DelTxPtrn message + * posts it to SME. + * + */ +static int +wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx, + struct nlattr **tb) +{ + struct sSirDelPeriodicTxPtrn *del_req; + eHalStatus status; + uint32_t request_id, ret; + uint8_t pattern_id = 0; + + /* Parse and fetch request Id */ + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + return -EINVAL; + } + + request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); + if (request_id == MAX_REQUEST_ID) { + hddLog(LOGE, FL("request_id cannot be MAX")); + return -EINVAL; + } + + ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id); + if (ret) { + hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret); + return -EINVAL; + } + + del_req = vos_mem_malloc(sizeof(*del_req)); + if (!del_req) { + hddLog(LOGE, FL("memory allocation failed")); + return -ENOMEM; + } + + vos_mem_copy(del_req->macAddress, adapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + hddLog(LOG1, MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->macAddress)); + del_req->ucPtrnId = pattern_id; + hddLog(LOG1, FL("Request Id: %u Pattern id: %d"), + request_id, del_req->ucPtrnId); + + status = sme_DelPeriodicTxPtrn(hdd_ctx->hHal, del_req); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_DelPeriodicTxPtrn failed (err=%d)"), status); + goto fail; + } + + EXIT(); + vos_mem_free(del_req); + return 0; + +fail: + vos_mem_free(del_req); + return -EINVAL; +} + + +/** + * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[PARAM_MAX + 1]; + uint8_t control; + int ret; + static const struct nla_policy policy[PARAM_MAX + 1] = { + [PARAM_REQUEST_ID] = { .type = NLA_U32 }, + [PARAM_CONTROL] = { .type = NLA_U32 }, + [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY, + .len = VOS_MAC_ADDR_SIZE }, + [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY, + .len = VOS_MAC_ADDR_SIZE }, + [PARAM_PERIOD] = { .type = NLA_U32 }, + }; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (!sme_IsFeatureSupportedByFW(WLAN_PERIODIC_TX_PTRN)) { + hddLog(LOGE, + FL("Periodic Tx Pattern Offload feature is not supported in FW!")); + return -ENOTSUPP; + } + + if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + if (!tb[PARAM_CONTROL]) { + hddLog(LOGE, FL("attr control failed")); + return -EINVAL; + } + control = nla_get_u32(tb[PARAM_CONTROL]); + hddLog(LOG1, FL("Control: %d"), control); + + if (control == WLAN_START_OFFLOADED_PACKETS) + return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb); + else if (control == WLAN_STOP_OFFLOADED_PACKETS) + return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb); + else { + hddLog(LOGE, FL("Invalid control: %d"), control); + return -EINVAL; + } +} + +/* + * done with short names for the global vendor params + * used by __wlan_hdd_cfg80211_offloaded_packets() + */ +#undef PARAM_MAX +#undef PARAM_REQUEST_ID +#undef PARAM_CONTROL +#undef PARAM_IP_PACKET +#undef PARAM_SRC_MAC_ADDR +#undef PARAM_DST_MAC_ADDR +#undef PARAM_PERIOD + +/** + * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Return: 0 on success; errno on failure + */ +static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy, + wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +/* + * define short names for the global vendor params + * used by __wlan_hdd_cfg80211_monitor_rssi() + */ +#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX +#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID +#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL +#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI +#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI + +/** + * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[PARAM_MAX + 1]; + struct rssi_monitor_req req; + eHalStatus status; + int ret; + uint32_t control; + static const struct nla_policy policy[PARAM_MAX + 1] = { + [PARAM_REQUEST_ID] = { .type = NLA_U32 }, + [PARAM_CONTROL] = { .type = NLA_U32 }, + [PARAM_MIN_RSSI] = { .type = NLA_S8 }, + [PARAM_MAX_RSSI] = { .type = NLA_S8 }, + }; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + hddLog(LOGE, FL("Not in Connected state!")); + return -ENOTSUPP; + } + + if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + if (!tb[PARAM_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + return -EINVAL; + } + + if (!tb[PARAM_CONTROL]) { + hddLog(LOGE, FL("attr control failed")); + return -EINVAL; + } + + req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); + req.session_id = adapter->sessionId; + control = nla_get_u32(tb[PARAM_CONTROL]); + + if (control == QCA_WLAN_RSSI_MONITORING_START) { + req.control = true; + if (!tb[PARAM_MIN_RSSI]) { + hddLog(LOGE, FL("attr min rssi failed")); + return -EINVAL; + } + + if (!tb[PARAM_MAX_RSSI]) { + hddLog(LOGE, FL("attr max rssi failed")); + return -EINVAL; + } + + req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]); + req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]); + + if (!(req.min_rssi < req.max_rssi)) { + hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"), + req.min_rssi, req.max_rssi); + return -EINVAL; + } + hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"), + req.min_rssi, req.max_rssi); + + } else if (control == QCA_WLAN_RSSI_MONITORING_STOP) + req.control = false; + else { + hddLog(LOGE, FL("Invalid control cmd: %d"), control); + return -EINVAL; + } + hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"), + req.request_id, req.session_id, req.control); + + status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req); + if (!HAL_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_rssi_monitoring failed(err=%d)"), status); + return -EINVAL; + } + + return 0; +} + +/* + * done with short names for the global vendor params + * used by __wlan_hdd_cfg80211_monitor_rssi() + */ +#undef PARAM_MAX +#undef PARAM_CONTROL +#undef PARAM_REQUEST_ID +#undef PARAM_MAX_RSSI +#undef PARAM_MIN_RSSI + +/** + * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Return: 0 on success; errno on failure + */ +static int +wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_rssi_threshold_breached() - rssi breached NL event + * @hddctx: HDD context + * @data: rssi breached event data + * + * This function reads the rssi breached event %data and fill in the skb with + * NL attributes and send up the NL event. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +void hdd_rssi_threshold_breached(void *hddctx, + struct rssi_breach_event *data) +{ + hdd_context_t *hdd_ctx = hddctx; + struct sk_buff *skb; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx) || !data) { + hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), + data); + return; + } + + skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + hddLog(LOG1, "Req Id: %u Current rssi: %d", + data->request_id, data->curr_rssi); + hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(data->curr_bssid.bytes)); + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, + data->request_id) || + nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, + sizeof(data->curr_bssid), data->curr_bssid.bytes) || + nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI, + data->curr_rssi)) { + hddLog(LOGE, FL("nla put fail")); + goto fail; + } + + cfg80211_vendor_event(skb, flags); + return; + +fail: + kfree_skb(skb); + return; +} + +/** + * __wlan_hdd_cfg80211_setband() - set band + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_setband(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct net_device *dev = wdev->netdev; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1]; + int ret; + static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] + = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } }; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) { + hddLog(LOGE, FL("attr SETBAND_VALUE failed")); + return -EINVAL; + } + + return hdd_setBand(dev, + nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE])); +} + +/** + * wlan_hdd_cfg80211_setband() - Wrapper to setband + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Return: 0 on success; errno on failure + */ +static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = +{ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = is_driver_dfs_capable + }, + +#ifdef WLAN_FEATURE_NAN + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_nan_request + }, +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_stats_ext_request + }, +#endif +#ifdef FEATURE_WLAN_EXTSCAN + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_start + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_stop + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_extscan_get_valid_channels + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_get_capabilities + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_get_cached_results + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_set_significant_change + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_reset_significant_change + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_epno_list + }, +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ll_stats_clear + }, + + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ll_stats_set + }, + + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ll_stats_get + }, +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +#ifdef FEATURE_WLAN_TDLS +/* EXT TDLS */ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_exttdls_enable + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_exttdls_disable + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_exttdls_get_status + }, +#endif + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_get_supported_features + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_set_scanning_mac_oui + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_get_concurrency_matrix + }, +#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_DO_ACS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_do_acs + }, + + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_get_features + }, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_keymgmt_set_key + }, +#endif + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_wifi_configuration_set + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_set_ext_roam_params + }, +#ifdef FEATURE_WLAN_EXTSCAN + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_passpoint_list + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_reset_passpoint_list + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist + }, +#endif /* FEATURE_WLAN_EXTSCAN */ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_get_wifi_info + }, + /* OCB commands */ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ocb_set_config + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ocb_set_utc_time + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ocb_start_timing_advert + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_dcc_get_stats + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_dcc_clear_stats + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_dcc_update_ndl + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_logger_supp_feature + }, + +#ifdef WLAN_FEATURE_MEMDUMP + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_fw_mem_dump + }, +#endif /* WLAN_FEATURE_MEMDUMP */ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_wifi_logger_start + }, +#ifdef FEATURE_WLAN_TDLS + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_tdls_capabilities + }, +#endif + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_link_properties + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data + }, +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_offloaded_packets + }, +#endif + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_monitor_rssi + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_setband + }, +}; + + +/* + * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc + * This function is called by hdd_wlan_startup() + * during initialization. + * This function is used to allocate wiphy structure. + */ +struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) +{ + struct wiphy *wiphy; + ENTER(); + + /* + * Create wiphy device + */ + wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size); + + if (!wiphy) + { + /* Print error and jump into err label and free the memory */ + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__); + return NULL; + } + + return wiphy; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_update_band + * This function is called from the supplicant through a + * private ioctl to change the band value + */ +int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) +{ + int i, j; + eNVChannelEnabledType channelEnabledState; + + ENTER(); + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + { + + if (NULL == wiphy->bands[i]) + continue; + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + channelEnabledState = vos_nv_getChannelEnabledState( + band->channels[j].hw_value); + + if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only + { +#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY + // Enable Social channels for P2P + if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) && + NV_CHANNEL_ENABLE == channelEnabledState) + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + else +#endif + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + + if (NV_CHANNEL_DISABLE == channelEnabledState || + NV_CHANNEL_INVALID == channelEnabledState) + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + } + else if (NV_CHANNEL_DFS == channelEnabledState) + { + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + band->channels[j].flags |= IEEE80211_CHAN_RADAR; + } + else + { + band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED + |IEEE80211_CHAN_RADAR); + } + } + } + return 0; +} +/* + * FUNCTION: wlan_hdd_cfg80211_init + * This function is called by hdd_wlan_startup() + * during initialization. + * This function is used to initialize and register wiphy structure. + */ +int wlan_hdd_cfg80211_init(struct device *dev, + struct wiphy *wiphy, + hdd_config_t *pCfg + ) +{ + int i, j; + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + + ENTER(); + + /* Now bind the underlying wlan device with wiphy */ + set_wiphy_dev(wiphy, dev); + + wiphy->mgmt_stypes = wlan_hdd_txrx_stypes; + + + /* This will disable updating of NL channels from passive to + * active if a beacon is received on passive channel. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; +#else + wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) || defined(WITH_BACKPORTS) + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME + | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL +#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME + | WIPHY_FLAG_4ADDR_STATION +#endif + | WIPHY_FLAG_OFFCHAN_TX; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags = REGULATORY_COUNTRY_IE_IGNORE; +#else + wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE; +#endif +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) + wiphy->wowlan = &wowlan_support_cfg80211_init; +#else + wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; + wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED; + wiphy->wowlan.pattern_min_len = 1; + wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE; +#endif + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (pCfg->isFastTransitionEnabled +#ifdef FEATURE_WLAN_LFR + || pCfg->isFastRoamIniFeatureEnabled +#endif +#ifdef FEATURE_WLAN_ESE + || pCfg->isEseIniFeatureEnabled +#endif + ) + { + wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; + } +#endif +#ifdef FEATURE_WLAN_TDLS + wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS + | WIPHY_FLAG_TDLS_EXTERNAL_SETUP; +#endif + + wiphy->features |= NL80211_FEATURE_HT_IBSS; + +#ifdef FEATURE_WLAN_SCAN_PNO + if (pCfg->configPNOScanSupport) + { + wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS; + wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS; + wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH; + } +#endif/*FEATURE_WLAN_SCAN_PNO*/ + +#if defined QCA_WIFI_FTM + if (vos_get_conparam() != VOS_FTM_MODE) { +#endif + + /* even with WIPHY_FLAG_CUSTOM_REGULATORY, + driver can still register regulatory callback and + it will get regulatory settings in wiphy->band[], but + driver need to determine what to do with both + regulatory settings */ + + wiphy->reg_notifier = wlan_hdd_linux_reg_notifier; + +#if defined QCA_WIFI_FTM + } +#endif + + wiphy->max_scan_ssids = MAX_SCAN_SSID; + + wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH; + + wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS; + + /* Supports STATION & AD-HOC modes right now */ + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_AP); + + if( pCfg->advertiseConcurrentOperation ) + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) || defined(WITH_BACKPORTS) + if( pCfg->enableMCC ) { + int i; + for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination); i++) { + if( !pCfg->allowMCCGODiffBI ) + wlan_hdd_iface_combination[i].beacon_int_infra_match = true; + } + } + wiphy->n_iface_combinations = ARRAY_SIZE(wlan_hdd_iface_combination); + wiphy->iface_combinations = wlan_hdd_iface_combination; +#endif + } + + /* Before registering we need to update the HT capability based + * on ini values */ + if( !pCfg->ShortGI20MhzEnable ) + { + wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; + wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; + wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; + } + + if( !pCfg->ShortGI40MhzEnable ) + { + wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } + + if( !pCfg->nChannelBondingMode5GHz ) + { + wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + + wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; + if (true == hdd_is_5g_supported(pHddCtx)) + { + wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + } + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + { + + if (NULL == wiphy->bands[i]) + continue; + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only + { +#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY + // Enable social channels for P2P + if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq)) + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + else +#endif + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + } + } + /*Initialise the supported cipher suite details*/ + wiphy->cipher_suites = hdd_cipher_suites; + wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites); + + /*signal strength in mBm (100*dBm) */ + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION; + wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands); + wiphy->vendor_commands = hdd_wiphy_vendor_commands; + + wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events; + wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0)) || \ + defined (DFS_MASTER_OFFLOAD_IND_SUPPORT) || defined(WITH_BACKPORTS) + if (pCfg->enableDFSMasterCap) { + wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD; + } +#endif + + wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers; +#ifdef QCA_HT_2040_COEX + wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; +#endif + +#ifdef CHANNEL_SWITCH_SUPPORTED + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; +#endif + + EXIT(); + return 0; +} + +/* + * In this function, wiphy structure is updated after VOSS + * initialization. In wlan_hdd_cfg80211_init, only the + * default values will be initialized. The final initialization + * of all required members can be done here. + */ +void wlan_hdd_update_wiphy(struct wiphy *wiphy, + hdd_config_t *pCfg) +{ + wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers; +} + +/* In this function we are registering wiphy. */ +int wlan_hdd_cfg80211_register(struct wiphy *wiphy) +{ + ENTER(); + /* Register our wiphy dev with cfg80211 */ + if (0 > wiphy_register(wiphy)) + { + /* print error */ + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__); + return -EIO; + } + + EXIT(); + return 0; +} + +/* + HDD function to update wiphy capability based on target offload status. + + wlan_hdd_cfg80211_init() does initialization of all wiphy related + capability even before downloading firmware to the target. In discrete + case, host will get know certain offload capability (say sched_scan + caps) only after downloading firmware to the target and target boots up. + This function is used to override setting done in wlan_hdd_cfg80211_init() + based on target capability. +*/ +void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy) +{ +#ifdef FEATURE_WLAN_SCAN_PNO + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + hdd_config_t *pCfg = pHddCtx->cfg_ini; + + /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before + * control comes here. Here just we need to clear it if firmware doesn't + * have PNO support. */ + if (!pCfg->PnoOffload) { + wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + wiphy->max_sched_scan_ssids = 0; + wiphy->max_match_sets = 0; + wiphy->max_sched_scan_ie_len = 0; + } +#endif +} + +/* This function registers for all frame which supplicant is interested in */ +void wlan_hdd_cfg80211_register_frames(hdd_adapter_t* pAdapter) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + /* Register for all P2P action, public action etc frames */ + v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4); + + ENTER(); + + /* Right now we are registering these frame when driver is getting + initialized. Once we will move to 2.6.37 kernel, in which we have + frame register ops, we will move this code as a part of that */ + /* GAS Initial Request */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE ); + + /* GAS Initial Response */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE ); + + /* GAS Comeback Request */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE ); + + /* GAS Comeback Response */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE ); + + /* P2P Public Action */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, + P2P_PUBLIC_ACTION_FRAME_SIZE ); + + /* P2P Action */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)P2P_ACTION_FRAME, + P2P_ACTION_FRAME_SIZE ); + + /* WNM BSS Transition Request frame */ + sme_RegisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)WNM_BSS_ACTION_FRAME, + WNM_BSS_ACTION_FRAME_SIZE ); + + /* WNM-Notification */ + sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, + (v_U8_t*)WNM_NOTIFICATION_FRAME, + WNM_NOTIFICATION_FRAME_SIZE ); +} + +void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t* pAdapter) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + /* Register for all P2P action, public action etc frames */ + v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4); + + ENTER(); + + /* Right now we are registering these frame when driver is getting + initialized. Once we will move to 2.6.37 kernel, in which we have + frame register ops, we will move this code as a part of that */ + /* GAS Initial Request */ + + sme_DeregisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE ); + + /* GAS Initial Response */ + sme_DeregisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE ); + + /* GAS Comeback Request */ + sme_DeregisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE ); + + /* GAS Comeback Response */ + sme_DeregisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE ); + + /* P2P Public Action */ + sme_DeregisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, + P2P_PUBLIC_ACTION_FRAME_SIZE ); + + /* P2P Action */ + sme_DeregisterMgmtFrame(hHal, HDD_SESSION_ID_ANY, type, + (v_U8_t*)P2P_ACTION_FRAME, + P2P_ACTION_FRAME_SIZE ); + + /* WNM-Notification */ + sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, + (v_U8_t*)WNM_NOTIFICATION_FRAME, + WNM_NOTIFICATION_FRAME_SIZE ); +} + +#ifdef FEATURE_WLAN_WAPI +void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index, + const u8 *mac_addr, const u8 *key , + int key_Len) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamSetKey setKey; + v_BOOL_t isConnected = TRUE; + int status = 0; + v_U32_t roamId= 0xFF; + tANI_U8 *pKeyPtr = NULL; + int n = 0; + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey)); + setKey.keyId = key_index; // Store Key ID + setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption + setKey.keyDirection = eSIR_TX_RX; /* Key Direction both TX and RX */ + setKey.paeRole = 0 ; // the PAE role + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + { + vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac ); + } + else + { + vos_mem_copy(setKey.peerMac, mac_addr, VOS_MAC_ADDR_SIZE); + } + setKey.keyLength = key_Len; + pKeyPtr = setKey.Key; + memcpy( pKeyPtr, key, key_Len); + + hddLog(VOS_TRACE_LEVEL_INFO,"%s: WAPI KEY LENGTH:0x%04x", + __func__, key_Len); + for (n = 0 ; n < key_Len; n++) + hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ", + __func__,n,setKey.Key[n]); + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + if ( isConnected ) + { + status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId ); + } + if ( status != 0 ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] sme_RoamSetKey returned ERROR status= %d", + __LINE__, status ); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } +} +#endif /* FEATURE_WLAN_WAPI*/ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, + beacon_data_t **ppBeacon, + struct beacon_parameters *params) +#else +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, + beacon_data_t **ppBeacon, + struct cfg80211_beacon_data *params, + int dtim_period) +#endif +{ + int size; + beacon_data_t *beacon = NULL; + beacon_data_t *old = NULL; + int head_len, tail_len, proberesp_ies_len, assocresp_ies_len; + const u8 *head, *tail, *proberesp_ies, *assocresp_ies; + + ENTER(); + if (params->head && !params->head_len) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("head_len is NULL")); + return -EINVAL; + } + + old = pAdapter->sessionCtx.ap.beacon; + + if (!params->head && !old) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("session(%d) old and new heads point to NULL"), + pAdapter->sessionId); + return -EINVAL; + } + + if (params->head) { + head_len = params->head_len; + head = params->head; + } else { + head_len = old->head_len; + head = old->head; + } + + if (params->tail || !old) { + tail_len = params->tail_len; + tail = params->tail; + } else { + tail_len = old->tail_len; + tail = old->tail; + } + + if (params->proberesp_ies || !old) { + proberesp_ies_len = params->proberesp_ies_len; + proberesp_ies = params->proberesp_ies; + } else { + proberesp_ies_len = old->proberesp_ies_len; + proberesp_ies = old->proberesp_ies; + } + + if (params->assocresp_ies || !old) { + assocresp_ies_len = params->assocresp_ies_len; + assocresp_ies = params->assocresp_ies; + } else { + assocresp_ies_len = old->assocresp_ies_len; + assocresp_ies = old->assocresp_ies; + } + + size = sizeof(beacon_data_t) + head_len + tail_len + + proberesp_ies_len + assocresp_ies_len; + + beacon = kzalloc(size, GFP_KERNEL); + + if (beacon == NULL) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Mem allocation for beacon failed")); + return -ENOMEM; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) + if (params->dtim_period) + beacon->dtim_period = params->dtim_period; + else if (old) + beacon->dtim_period = old->dtim_period; +#else + if (dtim_period) + beacon->dtim_period = dtim_period; + else if (old) + beacon->dtim_period = old->dtim_period; +#endif + + /* ----------------------------------------------- + * | head | tail | proberesp_ies | assocresp_ies | + * ----------------------------------------------- + */ + beacon->head = ((u8 *)beacon) + sizeof(beacon_data_t); + beacon->tail = beacon->head + head_len; + beacon->proberesp_ies = beacon->tail + tail_len; + beacon->assocresp_ies = beacon->proberesp_ies + proberesp_ies_len; + + beacon->head_len = head_len; + beacon->tail_len = tail_len; + beacon->proberesp_ies_len = proberesp_ies_len; + beacon->assocresp_ies_len= assocresp_ies_len; + + if (head && head_len) + memcpy(beacon->head, head, head_len); + if (tail && tail_len) + memcpy(beacon->tail, tail, tail_len); + if (proberesp_ies && proberesp_ies_len) + memcpy(beacon->proberesp_ies, proberesp_ies, proberesp_ies_len); + if (assocresp_ies && assocresp_ies_len) + memcpy(beacon->assocresp_ies, assocresp_ies, assocresp_ies_len); + + *ppBeacon = beacon; + + kfree(old); + + return 0; +} + +v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(const v_U8_t *pIes, int length, v_U8_t eid) +{ + int left = length; + v_U8_t *ptr = (v_U8_t *)pIes; + v_U8_t elem_id,elem_len; + + while(left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), + eid,elem_len,left); + return NULL; + } + if (elem_id == eid) + { + return ptr; + } + + left -= elem_len; + ptr += (elem_len + 2); + } + return NULL; +} + +/* Check if rate is 11g rate or not */ +static int wlan_hdd_rate_is_11g(u8 rate) +{ + static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */ + u8 i; + for (i = 0; i < 8; i++) + { + if(rate == gRateArray[i]) + return TRUE; + } + return FALSE; +} + +/* Check for 11g rate and set proper 11g only mode */ +static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht, u8* require_vht, + u8* pCheckRatesfor11g, eCsrPhyMode* pSapHw_mode) +{ + u8 i, num_rates = pIe[0]; + + pIe += 1; + for ( i = 0; i < num_rates; i++) + { + if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK))) + { + /* If rate set have 11g rate than change the mode to 11G */ + *pSapHw_mode = eCSR_DOT11_MODE_11g; + if (pIe[i] & BASIC_RATE_MASK) + { + /* If we have 11g rate as basic rate, it means mode + is 11g only mode. + */ + *pSapHw_mode = eCSR_DOT11_MODE_11g_ONLY; + *pCheckRatesfor11g = FALSE; + } + } + else if ((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == + pIe[i]) { + *require_ht = TRUE; + } + else if ((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY) == + pIe[i]) { + *require_vht = TRUE; + } + } + return; +} + +#ifdef QCA_HT_2040_COEX +static bool wlan_hdd_get_sap_obss(hdd_adapter_t *pHostapdAdapter) +{ + uint8_t ht_cap_ie[DOT11F_IE_HTCAPS_MAX_LEN]; + tDot11fIEHTCaps dot11_ht_cap_ie = {0}; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + beacon_data_t *beacon = pHostapdAdapter->sessionCtx.ap.beacon; + uint8_t *ie = NULL; + + ie = wlan_hdd_cfg80211_get_ie_ptr(beacon->tail, beacon->tail_len, + WLAN_EID_HT_CAPABILITY); + if (ie && ie[1]) { + vos_mem_copy(ht_cap_ie, &ie[2], DOT11F_IE_HTCAPS_MAX_LEN); + dot11fUnpackIeHTCaps((tpAniSirGlobal)hdd_ctx->hHal, ht_cap_ie, ie[1], + &dot11_ht_cap_ie); + return dot11_ht_cap_ie.supportedChannelWidthSet; + } + + return false; +} +#else +static bool wlan_hdd_get_sap_obss(hdd_adapter_t *pHostapdAdapter) +{ + return false; +} +#endif + +static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter) +{ + tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig; + beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head; + u8 checkRatesfor11g = TRUE; + u8 require_ht = FALSE, require_vht = false; + u8 *pIe=NULL; + + pConfig->SapHw_mode= eCSR_DOT11_MODE_11b; + + pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0], + pBeacon->head_len, WLAN_EID_SUPP_RATES); + if (pIe != NULL) { + pIe += 1; + wlan_hdd_check_11gmode(pIe, &require_ht, &require_vht, &checkRatesfor11g, + &pConfig->SapHw_mode); + } + + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + WLAN_EID_EXT_SUPP_RATES); + if (pIe != NULL) { + pIe += 1; + wlan_hdd_check_11gmode(pIe, &require_ht, &require_vht, &checkRatesfor11g, + &pConfig->SapHw_mode); + } + + if (pConfig->channel > 14) + pConfig->SapHw_mode= eCSR_DOT11_MODE_11a; + + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + WLAN_EID_HT_CAPABILITY); + if (pIe) { + pConfig->SapHw_mode= eCSR_DOT11_MODE_11n; + if (require_ht) + pConfig->SapHw_mode= eCSR_DOT11_MODE_11n_ONLY; + } + + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + WLAN_EID_VHT_CAPABILITY); + if (pIe) { + pConfig->SapHw_mode= eCSR_DOT11_MODE_11ac; + if (require_vht) + pConfig->SapHw_mode= eCSR_DOT11_MODE_11ac_ONLY; + } +} + +static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie, + v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size) +{ + v_U16_t ielen = 0; + v_U8_t *pIe = NULL; + beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + + pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size, + pBeacon->tail, pBeacon->tail_len); + + if (pIe) + { + ielen = pIe[1] + 2; + if ((*total_ielen + ielen) <= MAX_GENIE_LEN) + { + vos_mem_copy(&genie[*total_ielen], pIe, ielen); + } + else + { + hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***"); + return -EINVAL; + } + *total_ielen += ielen; + } + return 0; +} + +static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter, + v_U8_t *genie, v_U8_t *total_ielen) +{ + beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + int left = pBeacon->tail_len; + v_U8_t *ptr = pBeacon->tail; + v_U8_t elem_id, elem_len; + v_U16_t ielen = 0; + + if ( NULL == ptr || 0 == left ) + return; + + while (left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if (elem_len > left) + { + hddLog( VOS_TRACE_LEVEL_ERROR, + "****Invalid IEs eid = %d elem_len=%d left=%d*****", + elem_id, elem_len, left); + return; + } + if (IE_EID_VENDOR == elem_id) + { + /* skipping the VSIE's which we don't want to include or + * it will be included by existing code + */ + if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) && +#ifdef WLAN_FEATURE_WFD + (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) && +#endif + (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) && + (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) && + (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) && + (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) && + (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0)) + { + ielen = ptr[1] + 2; + if ((*total_ielen + ielen) <= MAX_GENIE_LEN) + { + vos_mem_copy(&genie[*total_ielen], ptr, ielen); + *total_ielen += ielen; + } + else + { + hddLog( VOS_TRACE_LEVEL_ERROR, + "IE Length is too big " + "IEs eid=%d elem_len=%d total_ie_lent=%d", + elem_id, elem_len, *total_ielen); + } + } + } + + left -= elem_len; + ptr += (elem_len + 2); + } + return; +} + +static void wlan_hdd_add_extra_ie(hdd_adapter_t* pHostapdAdapter, + v_U8_t *genie, v_U8_t *total_ielen, + v_U8_t temp_ie_id) +{ + beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + int left = pBeacon->tail_len; + v_U8_t *ptr = pBeacon->tail; + v_U8_t elem_id, elem_len; + v_U16_t ielen = 0; + + if ( NULL == ptr || 0 == left ) + return; + + while (left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if (elem_len > left) + { + hddLog( VOS_TRACE_LEVEL_ERROR, + "****Invalid IEs eid = %d elem_len=%d left=%d*****", + elem_id, elem_len, left); + return; + } + + if (temp_ie_id == elem_id) + { + ielen = ptr[1] + 2; + if ((*total_ielen + ielen) <= MAX_GENIE_LEN) + { + vos_mem_copy(&genie[*total_ielen], ptr, ielen); + *total_ielen += ielen; + } + else + { + hddLog( VOS_TRACE_LEVEL_ERROR, + "IE Length is too big " + "IEs eid=%d elem_len=%d total_ie_lent=%d", + elem_id, elem_len, *total_ielen); + } + } + + left -= elem_len; + ptr += (elem_len + 2); + } + return; +} + +#ifdef QCA_HT_2040_COEX +static void wlan_hdd_add_sap_obss_scan_ie( + hdd_adapter_t *pHostapdAdapter, v_U8_t *ie_buf, v_U8_t *ie_len) +{ + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { + if (wlan_hdd_get_sap_obss(pHostapdAdapter)) + wlan_hdd_add_extra_ie(pHostapdAdapter, ie_buf, ie_len, + WLAN_EID_OVERLAP_BSS_SCAN_PARAM); + } +} +#else +static void wlan_hdd_add_sap_obss_scan_ie( + hdd_adapter_t* pHostapdAdapter, v_U8_t *ie_buf, v_U8_t *ie_len) +{ +} +#endif + +int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter) +{ + v_U8_t *genie; + v_U8_t total_ielen = 0; + int ret = 0; + tsap_Config_t *pConfig; + tSirUpdateIE updateIE; + beacon_data_t *pBeacon = NULL; + + pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig; + pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + + genie = vos_mem_malloc(MAX_GENIE_LEN); + + if(genie == NULL) { + + return -ENOMEM; + } + + if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie, + &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE)) + { + hddLog(LOGE, FL("Adding WPS IE failed")); + ret = -EINVAL; + goto done; + } + +#ifdef WLAN_FEATURE_WFD + if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie, + &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE)) + { + hddLog(LOGE, FL("Adding WFD IE failed")); + ret = -EINVAL; + goto done; + } +#endif + +#ifdef FEATURE_WLAN_WAPI + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) + { + wlan_hdd_add_extra_ie(pHostapdAdapter, genie, &total_ielen, + WLAN_EID_WAPI); + } +#endif + + if ((WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) + { + wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen); + } + + wlan_hdd_add_sap_obss_scan_ie(pHostapdAdapter, genie, &total_ielen); + + vos_mem_copy(updateIE.bssid, pHostapdAdapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = pHostapdAdapter->sessionId; + + if (wlan_hdd_add_ie(pHostapdAdapter, genie, + &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0) { + hddLog(LOGE, FL("Adding P2P IE failed")); + ret = -EINVAL; + goto done; + } + + + if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { + updateIE.ieBufferlength = total_ielen; + updateIE.pAdditionIEBuffer = genie; + updateIE.append = VOS_FALSE; + updateIE.notify = VOS_TRUE; + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter), + &updateIE, eUPDATE_IE_PROBE_BCN) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on Add Ie probe beacon data")); + ret = -EINVAL; + goto done; + } + WLANSAP_ResetSapConfigAddIE(pConfig , eUPDATE_IE_PROBE_BCN); + } else { + WLANSAP_UpdateSapConfigAddIE(pConfig, + genie, + total_ielen, + eUPDATE_IE_PROBE_BCN); + } + + /* Added for Probe Response IE */ + total_ielen = 0; + if (pBeacon->proberesp_ies_len > 0 && + pBeacon->proberesp_ies_len <= MAX_GENIE_LEN) { + vos_mem_copy(genie, pBeacon->proberesp_ies, pBeacon->proberesp_ies_len); + total_ielen = pBeacon->proberesp_ies_len; + } + wlan_hdd_add_sap_obss_scan_ie(pHostapdAdapter, genie, &total_ielen); + + if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { + updateIE.ieBufferlength = total_ielen; + updateIE.pAdditionIEBuffer = genie; + updateIE.append = VOS_FALSE; + updateIE.notify = VOS_FALSE; + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter), + &updateIE, eUPDATE_IE_PROBE_RESP) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RESP add Ie data")); + ret = -EINVAL; + goto done; + } + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_PROBE_RESP); + } else { + WLANSAP_UpdateSapConfigAddIE(pConfig, genie, total_ielen, + eUPDATE_IE_PROBE_RESP); + } + + /* Assoc resp Add ie Data */ + if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { + updateIE.ieBufferlength = pBeacon->assocresp_ies_len; + updateIE.pAdditionIEBuffer = (tANI_U8*)pBeacon->assocresp_ies; + updateIE.append = VOS_FALSE; + updateIE.notify = VOS_FALSE; + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter), + &updateIE, eUPDATE_IE_ASSOC_RESP) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on Add Ie Assoc Response data")); + ret = -EINVAL; + goto done; + } + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ASSOC_RESP); + } else { + WLANSAP_UpdateSapConfigAddIE(pConfig, + pBeacon->assocresp_ies, + pBeacon->assocresp_ies_len, + eUPDATE_IE_ASSOC_RESP); + } + +done: + vos_mem_free(genie); + return ret; +} + +/* + * FUNCTION: wlan_hdd_validate_operation_channel + * called by wlan_hdd_cfg80211_start_bss() and + * wlan_hdd_cfg80211_set_channel() + * This function validates whether given channel is part of valid + * channel list. + */ +VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel) +{ + + v_U32_t num_ch = 0; + u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + u32 indx = 0; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U8_t fValidChannel = FALSE, count = 0; + hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + + num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if ( hdd_pConfig_ini->sapAllowAllChannel) + { + /* Validate the channel */ + for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++) + { + if ( channel == rfChannels[count].channelNum ) + { + fValidChannel = TRUE; + break; + } + } + if (fValidChannel != TRUE) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return VOS_STATUS_E_FAILURE; + } + } + else + { + if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, + valid_ch, &num_ch)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to get valid channel list", __func__); + return VOS_STATUS_E_FAILURE; + } + for (indx = 0; indx < num_ch; indx++) + { + if (channel == valid_ch[indx]) + { + break; + } + } + + if (indx >= num_ch) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return VOS_STATUS_E_FAILURE; + } + } + return VOS_STATUS_SUCCESS; + +} + +/** + * __wlan_hdd_cfg80211_set_channel() - cfg80211 set channel + * @wiphy: pointer to wiphy structure + * @dev: pointer to net_device structure + * @chan: pointer to ieee80211_channel structure + * @channel_type: channel type + * + * This function is used to set the channel number + * + * Return; 0 on success, error number otherwise + */ +static int +__wlan_hdd_cfg80211_set_channel(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + hdd_adapter_t *pAdapter = NULL; + v_U32_t num_ch = 0; + int channel = 0; + int freq = chan->center_freq; /* freq is in MHZ */ + hdd_context_t *pHddCtx; + int status; + tSmeConfigParams smeConfig; + tsap_Config_t *sap_config; + + ENTER(); + + if( NULL == dev ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Called with dev = NULL.", __func__); + return -ENODEV; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_CHANNEL, pAdapter->sessionId, + channel_type )); + hddLog(LOG1, FL("Device_mode %s(%d) freq = %d"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, chan->center_freq); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + return status; + + /* + * Do freq to chan conversion + * TODO: for 11a + */ + + channel = ieee80211_frequency_to_channel(freq); + + /* Check freq range */ + if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) || + (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Channel [%d] is outside valid range from %d to %d", + __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN, + WNI_CFG_CURRENT_CHANNEL_STAMAX); + return -EINVAL; + } + + num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) && + (WLAN_HDD_P2P_GO != pAdapter->device_mode)) + { + if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return -EINVAL; + } + hddLog(LOG2, FL("set channel to [%d] for device mode %s(%d)"), + channel, hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + } + if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + ) + { + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState) + { + /* Link is up then return cant set channel*/ + hddLog( VOS_TRACE_LEVEL_ERROR, + "%s: IBSS Associated, can't set the channel", __func__); + return -EINVAL; + } + + num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1; + pHddStaCtx->conn_info.operationChannel = channel; + pRoamProfile->ChannelInfo.ChannelList = + &pHddStaCtx->conn_info.operationChannel; + } + else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + || (pAdapter->device_mode == WLAN_HDD_P2P_GO) + ) + { + sap_config = &((WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig); + if (WLAN_HDD_P2P_GO == pAdapter->device_mode) + { + if(VOS_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter,channel)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return -EINVAL; + } + sap_config->channel = channel; + } + else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) + { + + /* set channel to what hostapd configured */ + if (VOS_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter,channel)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return -EINVAL; + } + sap_config->channel = channel; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + sap_config->ch_width_orig = eHT_CHANNEL_WIDTH_40MHZ; +#endif + vos_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_GetConfigParam(pHddCtx->hHal, &smeConfig); + + switch (channel_type) { + case NL80211_CHAN_HT20: + case NL80211_CHAN_NO_HT: + if (channel <= 14) + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + else + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + sap_config->sec_ch = 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + sap_config->ch_width_orig = eHT_CHANNEL_WIDTH_20MHZ; +#endif + sap_config->sec_ch = 0; + break; + + case NL80211_CHAN_HT40MINUS: + if (channel <= 14) + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + else + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + + sap_config->sec_ch = sap_config->channel - 4; + break; + case NL80211_CHAN_HT40PLUS: + if (channel <= 14) + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + else + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + + sap_config->sec_ch = sap_config->channel + 4; + break; + default: + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s:Error!!! Invalid HT20/40 mode !", + __func__); + return -EINVAL; + } + smeConfig.csrConfig.obssEnabled = wlan_hdd_get_sap_obss(pAdapter); + sme_UpdateConfig (pHddCtx->hHal, &smeConfig); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: Invalid device mode failed to set valid channel", __func__); + return -EINVAL; + } + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_set_channel() - cfg80211 set channel + * @wiphy: pointer to wiphy structure + * @dev: pointer to net_device structure + * @chan: pointer to ieee80211_channel structure + * @channel_type: channel type + * + * This is the cfg80211 set channel handler function which invokes + * the internal function @__wlan_hdd_cfg80211_set_channel with + * SSR protection. + * + * Return; 0 on success, error number otherwise + */ +static int wlan_hdd_cfg80211_set_channel(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_channel(wiphy, dev, chan, channel_type); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef DHCP_SERVER_OFFLOAD +static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + tpSirDhcpSrvOffloadInfo pDhcpSrvInfo; + tANI_U8 numEntries = 0; + tANI_U8 srv_ip[IPADDR_NUM_ENTRIES]; + tANI_U8 num; + tANI_U32 temp; + + /* Prepare the request to send to SME */ + pDhcpSrvInfo = vos_mem_malloc(sizeof(*pDhcpSrvInfo)); + if (NULL == pDhcpSrvInfo) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: could not allocate tDhcpSrvOffloadInfo!", __func__); + return; + } + + vos_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo)); + + pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId; + pDhcpSrvInfo->dhcpSrvOffloadEnabled = TRUE; + pDhcpSrvInfo->dhcpClientNum = pHddCtx->cfg_ini->dhcpMaxNumClients; + pDhcpSrvInfo->dhcp_client_start_ip = + pHddCtx->cfg_ini->dhcp_client_start_ip; + + hdd_string_to_u8_array(pHddCtx->cfg_ini->dhcpServerIP, + srv_ip, + &numEntries, + IPADDR_NUM_ENTRIES); + if (numEntries != IPADDR_NUM_ENTRIES) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: incorrect IP address (%s) assigned for DHCP server!", + __func__, pHddCtx->cfg_ini->dhcpServerIP); + goto end; + } + + 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__, pHddCtx->cfg_ini->dhcpServerIP); + goto end; + } + + if (srv_ip[IPADDR_NUM_ENTRIES-1] >= 100) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: invalid IP address (%s)! The last field must be less than 100!", + __func__, pHddCtx->cfg_ini->dhcpServerIP); + goto end; + } + + for (num = 0; num < numEntries; num++) { + temp = srv_ip[num]; + pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num)); + } + + if (eHAL_STATUS_SUCCESS != + sme_setDhcpSrvOffload(pHddCtx->hHal, pDhcpSrvInfo)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_setDHCPSrvOffload fail!", __func__); + goto end; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: enable DHCP Server offload successfully!", __func__); + +end: + vos_mem_free(pDhcpSrvInfo); + return; +} +#endif /* DHCP_SERVER_OFFLOAD */ + + +/** + * wlan_hdd_setup_driver_overrides : Overrides SAP / P2P GO Params + * @adapter: pointer to adapter struct + * + * This function overrides SAP / P2P Go configuration based on driver INI + * parameters for 11AC override and ACS. This overrides are done to support + * android legacy configuration method. + * + * NOTE: Non android platform supports concurrency and these overrides shall + * not be used. Also future driver based overrides shall be consolidated in this + * function only. Avoid random overrides in other location based on ini. + * + * Return: 0 for Success or Negative error codes. + */ +int wlan_hdd_setup_driver_overrides(hdd_adapter_t *ap_adapter) +{ + tsap_Config_t *sap_cfg = &ap_adapter->sessionCtx.ap.sapConfig; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); + tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(ap_adapter); + + if (ap_adapter->device_mode == WLAN_HDD_SOFTAP && + hdd_ctx->cfg_ini->force_sap_acs) + goto setup_acs_overrides; + + /* Fixed channel 11AC override: + * 11AC override in qcacld is introduced for following reasons: + * 1. P2P GO also follows start_bss and since p2p GO could not be + * configured to setup VHT channel width in wpa_supplicant + * 2. Android UI does not provide advanced configuration options for SAP + * + * Default override enabled (for android). MDM shall disable this in ini + */ + if (hdd_ctx->cfg_ini->sap_p2p_11ac_override && + (sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11n || + sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11ac || + sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11ac_ONLY)) { + hddLog(LOG1, FL("** Driver force 11AC override for SAP/Go **")); + + /* 11n only shall not be overridden since it may be on purpose*/ + if (sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11n) + sap_cfg->SapHw_mode = eCSR_DOT11_MODE_11ac; + + if (sap_cfg->channel >= 36) + sap_cfg->ch_width_orig = + hdd_ctx->cfg_ini->vhtChannelWidth; + else + sap_cfg->ch_width_orig = + hdd_ctx->cfg_ini->nChannelBondingMode24GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + + } + + sap_cfg->vht_channel_width = sap_cfg->ch_width_orig; + + sme_SelectCBMode(h_hal, sap_cfg->SapHw_mode, sap_cfg->channel, + sap_cfg->sec_ch, &sap_cfg->vht_channel_width, + sap_cfg->ch_width_orig); + return 0; + +setup_acs_overrides: + hddLog(LOGE, FL("** Driver force ACS override **")); + + sap_cfg->channel = AUTO_CHANNEL_SELECT; + sap_cfg->acs_cfg.acs_mode = true; + sap_cfg->acs_cfg.start_ch = hdd_ctx->cfg_ini->force_sap_acs_st_ch; + sap_cfg->acs_cfg.end_ch = hdd_ctx->cfg_ini->force_sap_acs_end_ch; + + if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.end_ch) { + hddLog(LOGE, FL("Driver force ACS start ch (%d) > end ch (%d)"), + sap_cfg->acs_cfg.start_ch, sap_cfg->acs_cfg.end_ch); + return -EINVAL; + } + + /* Derive ACS HW mode */ + sap_cfg->SapHw_mode = hdd_cfg_xlate_to_csr_phy_mode( + hdd_ctx->cfg_ini->dot11Mode); + if (sap_cfg->SapHw_mode == eCSR_DOT11_MODE_AUTO) + sap_cfg->SapHw_mode = eCSR_DOT11_MODE_11ac; + + if ((sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11b || + sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11g || + sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11g_ONLY) && + sap_cfg->acs_cfg.start_ch > 14) { + hddLog(LOGE, FL("Invalid ACS Dot11Mode %d & CH range <%d - %d> Combination"), + sap_cfg->SapHw_mode, sap_cfg->acs_cfg.start_ch, + sap_cfg->acs_cfg.end_ch); + return -EINVAL; + } + sap_cfg->acs_cfg.hw_mode = sap_cfg->SapHw_mode; + + /* Derive ACS BW */ + sap_cfg->ch_width_orig = eHT_CHANNEL_WIDTH_20MHZ; + if (sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11ac || + sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11ac_ONLY) { + + sap_cfg->ch_width_orig = hdd_ctx->cfg_ini->vhtChannelWidth; + /* VHT in 2.4G depends on gChannelBondingMode24GHz INI param */ + if (sap_cfg->acs_cfg.end_ch <= 14) + sap_cfg->ch_width_orig = + hdd_ctx->cfg_ini->nChannelBondingMode24GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + } + + if (sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11n || + sap_cfg->SapHw_mode == eCSR_DOT11_MODE_11n_ONLY) { + if (sap_cfg->acs_cfg.end_ch <= 14) + sap_cfg->ch_width_orig = + hdd_ctx->cfg_ini->nChannelBondingMode24GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + else + sap_cfg->ch_width_orig = + hdd_ctx->cfg_ini->nChannelBondingMode5GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + } + sap_cfg->acs_cfg.ch_width = sap_cfg->ch_width_orig; + + hddLog(LOGE, FL("Force ACS Config: HW_MODE: %d ACS_BW: %d ST_CH: %d END_CH: %d"), + sap_cfg->acs_cfg.hw_mode, sap_cfg->acs_cfg.ch_width, + sap_cfg->acs_cfg.start_ch, sap_cfg->acs_cfg.end_ch); + + return 0; +} + + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD +/** + * wlan_hdd_set_udp_resp_offload() - get specific udp and response udp info from + * ini file + * @padapter: hdd adapter pointer + * @enable: enable or disable the specific udp and response behaviour + * + * This function reads specific udp and response udp related info from ini file, + * these configurations will be sent to fw through wmi. + * + * Return: 0 on success, otherwise error value + */ +static int wlan_hdd_set_udp_resp_offload(hdd_adapter_t *padapter, bool enable) +{ + hdd_context_t *phddctx = WLAN_HDD_GET_CTX(padapter); + hdd_config_t *pcfg_ini = phddctx->cfg_ini; + struct udp_resp_offload udp_resp_cmd_info; + VOS_STATUS status; + uint8 udp_payload_filter_len; + uint8 udp_response_payload_len; + + hddLog(LOG1, FL("udp_resp_offload enable flag is %d"), enable); + + /* prepare the request to send to SME */ + if ((enable == TRUE) && + (pcfg_ini->udp_resp_offload_support)) { + if (pcfg_ini->response_payload[0] != '\0') { + udp_resp_cmd_info.vdev_id = padapter->sessionId; + udp_resp_cmd_info.enable = 1; + udp_resp_cmd_info.dest_port = + pcfg_ini->dest_port; + + udp_payload_filter_len = + strlen(pcfg_ini->payload_filter); + hddLog(LOG2, "payload_filter[%s]", + pcfg_ini->payload_filter); + udp_response_payload_len = + strlen(pcfg_ini->response_payload); + hddLog(LOG2, "response_payload[%s]", + pcfg_ini->response_payload); + + vos_mem_copy(udp_resp_cmd_info.udp_payload_filter, + pcfg_ini->payload_filter, + udp_payload_filter_len + 1); + + vos_mem_copy(udp_resp_cmd_info.udp_response_payload, + pcfg_ini->response_payload, + udp_response_payload_len + 1); + + status = sme_set_udp_resp_offload(&udp_resp_cmd_info); + if (VOS_STATUS_E_FAILURE == status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_set_udp_resp_offload failure!", + __func__); + return -EIO; + } + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sme_set_udp_resp_offload success!", + __func__); + } + } else { + udp_resp_cmd_info.vdev_id = padapter->sessionId; + udp_resp_cmd_info.enable = 0; + udp_resp_cmd_info.dest_port = 0; + udp_resp_cmd_info.udp_payload_filter[0] = '\0'; + udp_resp_cmd_info.udp_response_payload[0] = '\0'; + status = sme_set_udp_resp_offload(&udp_resp_cmd_info); + if (VOS_STATUS_E_FAILURE == status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_set_udp_resp_offload fialure!", __func__); + return -EIO; + } + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sme_set_udp_resp_offload success!", __func__); + } + return 0; +} +#else +static inline int wlan_hdd_set_udp_resp_offload(hdd_adapter_t *padapter, + bool enable) +{ + return 0; +} +#endif + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) +static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, + struct beacon_parameters *params) +#else +static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, + struct cfg80211_beacon_data *params, + const u8 *ssid, size_t ssid_len, + enum nl80211_hidden_ssid hidden_ssid) +#endif +{ + tsap_Config_t *pConfig; + beacon_data_t *pBeacon = NULL; + struct ieee80211_mgmt *pMgmt_frame; + v_U8_t *pIe=NULL; + v_U16_t capab_info; + eCsrAuthType RSNAuthType; + eCsrEncryptionType RSNEncryptType; + eCsrEncryptionType mcRSNEncryptType; + int status = VOS_STATUS_SUCCESS; + tpWLAN_SAPEventCB pSapEventCallback; + hdd_hostapd_state_t *pHostapdState; + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + struct qc_mac_acl_entry *acl_entry = NULL; + v_SINT_t i; + hdd_config_t *iniConfig; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + tSmeConfigParams sme_config; + v_BOOL_t MFPCapable = VOS_FALSE; + v_BOOL_t MFPRequired = VOS_FALSE; + u_int16_t prev_rsn_length = 0; + int ret; + ENTER(); + + iniConfig = pHddCtx->cfg_ini; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + + clear_bit(ACS_PENDING, &pHostapdAdapter->event_flags); + clear_bit(ACS_IN_PROGRESS, &pHddCtx->g_event_flags); + + pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig; + + pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + + pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head; + + pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int; + + pConfig->disableDFSChSwitch = iniConfig->disableDFSChSwitch; + + //channel is already set in the set_channel Call back + //pConfig->channel = pCommitConfig->channel; + + /*Protection parameter to enable or disable*/ + pConfig->protEnabled = iniConfig->apProtEnabled; + + pConfig->dtim_period = pBeacon->dtim_period; + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***", + pConfig->dtim_period); + + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) + { +#ifndef QCA_HT_2040_COEX + /* + * Restore the channel bonding parameter to avoid + * falling to previous SAP configuration in concurrency + * scenarios. + */ + tSmeConfigParams *sme_config; + + sme_config = vos_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + hddLog(LOGE, FL("memory allocation failed for sme_config")); + return -ENOMEM; + } + + vos_mem_zero(sme_config, sizeof(*sme_config)); + sme_GetConfigParam(hHal, sme_config); + sme_config->csrConfig.channelBondingMode5GHz = + pHddCtx->cfg_ini->nChannelBondingMode5GHz; + sme_UpdateConfig(hHal, sme_config); + vos_mem_free(sme_config); +#endif + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + WLAN_EID_COUNTRY); + if(memcmp(pHddCtx->cfg_ini->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0) + { + tANI_BOOLEAN restartNeeded; + pConfig->ieee80211d = 1; + vos_mem_copy(pConfig->countryCode, pHddCtx->cfg_ini->apCntryCode, 3); + sme_setRegInfo(hHal, pConfig->countryCode); + sme_ResetCountryCodeInformation(hHal, &restartNeeded); + } + else if(pIe) + { + tANI_BOOLEAN restartNeeded; + pConfig->ieee80211d = 1; + vos_mem_copy(pConfig->countryCode, &pIe[2], 3); + sme_setRegInfo(hHal, pConfig->countryCode); + sme_ResetCountryCodeInformation(hHal, &restartNeeded); + } + else + { + pConfig->countryCode[0] = pHddCtx->reg.alpha2[0]; + pConfig->countryCode[1] = pHddCtx->reg.alpha2[1]; + pConfig->ieee80211d = 0; + } + + ret = wlan_hdd_sap_cfg_dfs_override(pHostapdAdapter); + if (ret < 0) { + goto error; + } else { + if (ret == 0) { + if (VOS_IS_DFS_CH(pConfig->channel)) + pHddCtx->dev_dfs_cac_status = DFS_CAC_NEVER_DONE; + } + } + + if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, pConfig->channel); + ret = -EINVAL; + goto error; + } + + /* reject SAP if DFS channel scan is not allowed */ + if ((pHddCtx->cfg_ini->enableDFSChnlScan == false) && + (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(pConfig->channel))) { + hddLog(LOGE, FL("not allowed to start SAP on DFS channel")); + ret = -EOPNOTSUPP; + goto error; + } + + /* + * Set the JAPAN W53 disabled INI param + * in to SAP DFS for restricting these + * channel from being picked during DFS + * random channel selection. + */ + WLANSAP_set_Dfs_Restrict_JapanW53(hHal, + iniConfig->gDisableDfsJapanW53); + + /* + * Set the SAP Indoor/Outdoor preferred + * operating channel location. This + * prameter will restrict SAP picking + * channel from only Indoor/outdoor + * channels list only based up on the + * this parameter. + */ + WLANSAP_set_Dfs_Preferred_Channel_location(hHal, + iniConfig->gSapPreferredChanLocation); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + wlan_sap_set_channel_avoidance(hHal, iniConfig->sap_channel_avoidance); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + } + else if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) + { + pConfig->countryCode[0] = pHddCtx->reg.alpha2[0]; + pConfig->countryCode[1] = pHddCtx->reg.alpha2[1]; + pConfig->ieee80211d = 0; + } + else + { + pConfig->ieee80211d = 0; + } + + WLANSAP_Set_Dfs_Ignore_CAC(hHal, iniConfig->ignoreCAC); + + capab_info = pMgmt_frame->u.beacon.capab_info; + + pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & + WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE; + + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy; + + /*Set wps station to configured*/ + pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len); + + if(pIe) + { + if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE)) + { + hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***"); + ret = -EINVAL; + goto error; + } + else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0) + { + hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2)); + /* Check 15 bit of WPS IE as it contain information for wps state + * WPS state + */ + if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15]) + { + pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED; + } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15]) + { + pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED; + } + } + } + else + { + hddLog(LOG1, "WPS disabled"); + pConfig->wps_state = SAP_WPS_DISABLED; + } + pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up + + pConfig->RSNEncryptType = eCSR_ENCRYPT_TYPE_NONE; + pConfig->mcRSNEncryptType = eCSR_ENCRYPT_TYPE_NONE; + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType = + eCSR_ENCRYPT_TYPE_NONE; + + + pConfig->RSNWPAReqIELength = 0; + memset(&pConfig->RSNWPAReqIE[0], 0, sizeof(pConfig->RSNWPAReqIE)); + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + WLAN_EID_RSN); + if(pIe && pIe[1]) + { + pConfig->RSNWPAReqIELength = pIe[1] + 2; + if (pConfig->RSNWPAReqIELength < sizeof(pConfig->RSNWPAReqIE)) + memcpy(&pConfig->RSNWPAReqIE[0], pIe, + pConfig->RSNWPAReqIELength); + else + hddLog(LOGE, "RSNWPA IE MAX Length exceeded; length =%d", + pConfig->RSNWPAReqIELength); + /* The actual processing may eventually be more extensive than + * this. Right now, just consume any PMKIDs that are sent in + * by the app. + * */ + status = hdd_softap_unpackIE( + vos_get_context( VOS_MODULE_ID_SME, pVosContext), + &RSNEncryptType, + &mcRSNEncryptType, + &RSNAuthType, + &MFPCapable, + &MFPRequired, + pConfig->RSNWPAReqIE[1]+2, + pConfig->RSNWPAReqIE ); + + if( VOS_STATUS_SUCCESS == status ) + { + /* Now copy over all the security attributes you have + * parsed out + * */ + pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE + pConfig->mcRSNEncryptType = mcRSNEncryptType; + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType + = RSNEncryptType; + hddLog( LOG1, FL("CSR AuthType = %d, " + "EncryptionType = %d mcEncryptionType = %d"), + RSNAuthType, RSNEncryptType, mcRSNEncryptType); + } + } + + pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE, + pBeacon->tail, pBeacon->tail_len); + + if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA)) + { + if (pConfig->RSNWPAReqIE[0]) + { + /*Mixed mode WPA/WPA2*/ + prev_rsn_length = pConfig->RSNWPAReqIELength; + pConfig->RSNWPAReqIELength += pIe[1] + 2; + if (pConfig->RSNWPAReqIELength < sizeof(pConfig->RSNWPAReqIE)) + memcpy(&pConfig->RSNWPAReqIE[0] + prev_rsn_length, pIe, + pIe[1] + 2); + else + hddLog(LOGE, "RSNWPA IE MAX Length exceeded; length =%d", + pConfig->RSNWPAReqIELength); + } + else + { + pConfig->RSNWPAReqIELength = pIe[1] + 2; + if (pConfig->RSNWPAReqIELength < sizeof(pConfig->RSNWPAReqIE)) + memcpy(&pConfig->RSNWPAReqIE[0], pIe, + pConfig->RSNWPAReqIELength); + else + hddLog(LOGE, "RSNWPA IE MAX Length exceeded; length =%d", + pConfig->RSNWPAReqIELength); + status = hdd_softap_unpackIE( + vos_get_context( VOS_MODULE_ID_SME, pVosContext), + &RSNEncryptType, + &mcRSNEncryptType, + &RSNAuthType, + &MFPCapable, + &MFPRequired, + pConfig->RSNWPAReqIE[1]+2, + pConfig->RSNWPAReqIE ); + + if( VOS_STATUS_SUCCESS == status ) + { + /* Now copy over all the security attributes you have + * parsed out + * */ + pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE + pConfig->mcRSNEncryptType = mcRSNEncryptType; + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType + = RSNEncryptType; + hddLog( LOG1, FL("CSR AuthType = %d, " + "EncryptionType = %d mcEncryptionType = %d"), + RSNAuthType, RSNEncryptType, mcRSNEncryptType); + } + } + } + + if (pConfig->RSNWPAReqIELength > sizeof(pConfig->RSNWPAReqIE)) { + hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***"); + ret = -EINVAL; + goto error; + } + + pConfig->SSIDinfo.ssidHidden = VOS_FALSE; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) + if (params->ssid != NULL) + { + vos_mem_copy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len); + pConfig->SSIDinfo.ssid.length = params->ssid_len; + + switch (params->hidden_ssid) { + case NL80211_HIDDEN_SSID_NOT_IN_USE: + hddLog(LOG1, "HIDDEN_SSID_NOT_IN_USE"); + pConfig->SSIDinfo.ssidHidden = eHIDDEN_SSID_NOT_IN_USE; + break; + case NL80211_HIDDEN_SSID_ZERO_LEN: + hddLog(LOG1, "HIDDEN_SSID_ZERO_LEN"); + pConfig->SSIDinfo.ssidHidden = eHIDDEN_SSID_ZERO_LEN; + break; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + hddLog(LOG1, "HIDDEN_SSID_ZERO_CONTENTS"); + pConfig->SSIDinfo.ssidHidden = eHIDDEN_SSID_ZERO_CONTENTS; + break; + default: + hddLog(LOGE, "Wrong hidden_ssid param %d", params->hidden_ssid); + break; + } + } +#else + if (ssid != NULL) + { + vos_mem_copy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len); + pConfig->SSIDinfo.ssid.length = ssid_len; + + switch (hidden_ssid) { + case NL80211_HIDDEN_SSID_NOT_IN_USE: + hddLog(LOG1, "HIDDEN_SSID_NOT_IN_USE"); + pConfig->SSIDinfo.ssidHidden = eHIDDEN_SSID_NOT_IN_USE; + break; + case NL80211_HIDDEN_SSID_ZERO_LEN: + hddLog(LOG1, "HIDDEN_SSID_ZERO_LEN"); + pConfig->SSIDinfo.ssidHidden = eHIDDEN_SSID_ZERO_LEN; + break; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + hddLog(LOG1, "HIDDEN_SSID_ZERO_CONTENTS"); + pConfig->SSIDinfo.ssidHidden = eHIDDEN_SSID_ZERO_CONTENTS; + break; + default: + hddLog(LOGE, "Wrong hidden_ssid param %d", hidden_ssid); + break; + } + } +#endif + + vos_mem_copy(pConfig->self_macaddr.bytes, + pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t)); + + /* default value */ + pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED; + pConfig->num_accept_mac = 0; + pConfig->num_deny_mac = 0; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + /* + * We don't want P2PGO to follow STA's channel + * so lets limit the logic for SAP only. + * Later if we decide to make p2pgo follow STA's + * channel then remove this check. + */ + if ((0 == pHddCtx->cfg_ini->conc_custom_rule1) || + (pHddCtx->cfg_ini->conc_custom_rule1 && + WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)) + pConfig->cc_switch_mode = iniConfig->WlanMccToSccSwitchMode; +#endif + + pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE, + pBeacon->tail, pBeacon->tail_len); + + /* pIe for black list is following form: + type : 1 byte + length : 1 byte + OUI : 4 bytes + acl type : 1 byte + no of mac addr in black list: 1 byte + list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id + */ + if ((pIe != NULL) && (pIe[1] != 0)) + { + pConfig->SapMacaddr_acl = pIe[6]; + pConfig->num_deny_mac = pIe[7]; + hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d", + pIe[6], pIe[7]); + if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS) + pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS; + acl_entry = (struct qc_mac_acl_entry *)(pIe + 8); + for (i = 0; i < pConfig->num_deny_mac; i++) + { + vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr)); + acl_entry++; + } + } + pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE, + pBeacon->tail, pBeacon->tail_len); + + /* pIe for white list is following form: + type : 1 byte + length : 1 byte + OUI : 4 bytes + acl type : 1 byte + no of mac addr in white list: 1 byte + list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id + */ + if ((pIe != NULL) && (pIe[1] != 0)) + { + pConfig->SapMacaddr_acl = pIe[6]; + pConfig->num_accept_mac = pIe[7]; + hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d", + pIe[6], pIe[7]); + if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS) + pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS; + acl_entry = (struct qc_mac_acl_entry *)(pIe + 8); + for (i = 0; i < pConfig->num_accept_mac; i++) + { + vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr)); + acl_entry++; + } + } + + wlan_hdd_set_sapHwmode(pHostapdAdapter); + /* Override hostapd.conf wmm_enabled only for 11n and 11AC configs (IOT) + * As per spec 11n/11AC STA are QOS STA and may not connect to nonQOS 11n AP + * Default enable QOS for SAP + */ + vos_mem_zero(&sme_config, sizeof(tSmeConfigParams)); + sme_GetConfigParam(pHddCtx->hHal, &sme_config); + sme_config.csrConfig.WMMSupportMode = eCsrRoamWmmAuto; + pIe = wlan_hdd_get_vendor_oui_ie_ptr(WMM_OUI_TYPE, WMM_OUI_TYPE_SIZE, + pBeacon->tail, pBeacon->tail_len); + if (!pIe && (pConfig->SapHw_mode == eCSR_DOT11_MODE_11a || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11g || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11b)) + sme_config.csrConfig.WMMSupportMode = eCsrRoamWmmNoQos; + sme_UpdateConfig(pHddCtx->hHal, &sme_config); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + /* Linux kernel < 3.8 does not support ch width param. So for + * 11AC get from ch width from ini file only if ht40 is enabled. + * VHT80 depends on HT40 config. + */ + if (pConfig->SapHw_mode == eCSR_DOT11_MODE_11ac) + if (pConfig->ch_width_orig == NL80211_CHAN_WIDTH_40) + pConfig->ch_width_orig = iniConfig->vhtChannelWidth; +#endif + + if (pConfig->ch_width_orig == NL80211_CHAN_WIDTH_80) { + if (pHddCtx->isVHT80Allowed == false) + pConfig->ch_width_orig = eHT_CHANNEL_WIDTH_40MHZ; + else + pConfig->ch_width_orig = eHT_CHANNEL_WIDTH_80MHZ; + } else if (pConfig->ch_width_orig == NL80211_CHAN_WIDTH_40) + pConfig->ch_width_orig = eHT_CHANNEL_WIDTH_40MHZ; + else + pConfig->ch_width_orig = eHT_CHANNEL_WIDTH_20MHZ; + + if (wlan_hdd_setup_driver_overrides(pHostapdAdapter)) { + ret = -EINVAL; + goto error; + } + + // ht_capab is not what the name conveys,this is used for protection bitmap + pConfig->ht_capab = iniConfig->apProtection; + + if (0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter)) + { + hddLog(LOGE, FL("SAP Not able to set AP IEs")); + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ALL); + ret = -EINVAL; + goto error; + } + + //Uapsd Enabled Bit + pConfig->UapsdEnable = iniConfig->apUapsdEnabled; + //Enable OBSS protection + pConfig->obssProtEnabled = iniConfig->apOBSSProtEnabled; + + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) { + pConfig->sap_dot11mc = iniConfig->sap_dot11mc; + } else { /* for P2P-Go case */ + pConfig->sap_dot11mc = 1; + } + hddLog(LOG1, FL("11MC Support Enabled : %d\n"), + pConfig->sap_dot11mc); + +#ifdef WLAN_FEATURE_11W + pConfig->mfpCapable = MFPCapable; + pConfig->mfpRequired = MFPRequired; + hddLog(LOG1, FL("Soft AP MFP capable %d, MFP required %d\n"), + pConfig->mfpCapable, pConfig->mfpRequired); +#endif + + hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes)); + hddLog(LOGW,FL("ssid =%s, beaconint=%d, channel=%d"), + pConfig->SSIDinfo.ssid.ssId, (int)pConfig->beacon_int, + (int)pConfig->channel); + hddLog(LOGW,FL("hw_mode=%x, privacy=%d, authType=%d"), + pConfig->SapHw_mode, pConfig->privacy, + pConfig->authType); + hddLog(LOGW,FL("RSN/WPALen=%d, Uapsd = %d"), + (int)pConfig->RSNWPAReqIELength, pConfig->UapsdEnable); + hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d"), + pConfig->protEnabled, pConfig->obssProtEnabled); + + if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) + { + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ALL); + //Bss already started. just return. + //TODO Probably it should update some beacon params. + hddLog( LOGE, "Bss Already started...Ignore the request"); + EXIT(); + return 0; + } + + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Reached max concurrent connections")); + ret = -EINVAL; + goto error; + } + + pConfig->persona = pHostapdAdapter->device_mode; + + pSapEventCallback = hdd_hostapd_SAPEventCB; + + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->dfs_cac_block_tx = VOS_TRUE; + + vos_event_reset(&pHostapdState->vosEvent); + status = WLANSAP_StartBss( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), +#else + pVosContext, +#endif + pSapEventCallback, pConfig, (v_PVOID_t)pHostapdAdapter->dev); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ALL); + hddLog(LOGE,FL("SAP Start Bss fail")); + ret = -EINVAL; + goto error; + } + + hddLog(LOG1, + FL("Waiting for Scan to complete(auto mode) and BSS to start")); + + status = vos_wait_single_event(&pHostapdState->vosEvent, 10000); + + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ALL); + + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("%s: ERROR: HDD vos wait for single_event failed!!"), + __func__); + smeGetCommandQStatus(hHal); +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_StopBss(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + WLANSAP_StopBss(pHddCtx->pvosContext); +#endif + VOS_ASSERT(0); + ret = -EINVAL; + goto error; + } + + /* Successfully started Bss update the state bit. */ + set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + /* 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->enableDHCPServerOffload) { + wlan_hdd_set_dhcp_server_offload(pHostapdAdapter); + wlan_hdd_set_mdns_offload(pHostapdAdapter); + } +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_P2P_DEBUG + if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) + { + if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) + { + globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE; + hddLog(LOGE,"[P2P State] From Go nego completed to " + "Non-autonomous Group started"); + } + else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE) + { + globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE; + hddLog(LOGE,"[P2P State] From Inactive to " + "Autonomous Group started"); + } + } +#endif + + pHostapdState->bCommit = TRUE; + EXIT(); + + return 0; + +error: + if (pHostapdAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) { + vos_mem_free(pHostapdAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list); + pHostapdAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL; + } + + return ret; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) +static int __wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_ADD_BEACON, + pAdapter->sessionId, params->interval)); + hddLog(LOG2, FL("Device mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Reached max concurrent connections")); + return -EINVAL; + } + + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + beacon_data_t *old, *new; + + old = pAdapter->sessionCtx.ap.beacon; + + if (old) { + hddLog(VOS_TRACE_LEVEL_WARN, + FL("already beacon info added to session(%d)"), + pAdapter->sessionId); + return -EALREADY; + } + + status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params); + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("Error!!! Allocating the new beacon")); + return -EINVAL; + } + + pAdapter->sessionCtx.ap.beacon = new; + + status = wlan_hdd_cfg80211_start_bss(pAdapter, params); + if (0 != status) { + pAdapter->sessionCtx.ap.beacon = NULL; + kfree(new); + } + } + + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_add_beacon() - add beacon in sap mode + * @wiphy: Pointer to wiphy + * @dev: Pointer to netdev + * @param: Pointer to beacon parameters + * + * Return: zero for success non-zero for failure + */ +static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_add_beacon(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_BEACON, + pAdapter->sessionId, pHddStaCtx->conn_info.authType)); + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + beacon_data_t *old, *new; + + old = pAdapter->sessionCtx.ap.beacon; + + if (!old) { + hddLog(LOGE, + FL("session(%d) old and new heads points to NULL"), + pAdapter->sessionId); + return -ENOENT; + } + + status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params); + + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("Error!!! Allocating the new beacon")); + return -EINVAL; + } + + pAdapter->sessionCtx.ap.beacon = new; + status = wlan_hdd_cfg80211_start_bss(pAdapter, params); + } + + EXIT(); + return status; +} +/** + * wlan_hdd_cfg80211_set_beacon() - set beacon in sap mode + * @wiphy: Pointer to wiphy + * @dev: Pointer to netdev + * @param: Pointer to beacon parameters + * + * Return: zero for success non-zero for failure + */ +static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_beacon(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && + !defined(WITH_BACKPORTS) */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WITH_BACKPORTS) +static int __wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, + struct net_device *dev) +#else +static int __wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, + struct net_device *dev) +#endif +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = NULL; + hdd_scaninfo_t *pScanInfo = NULL; + hdd_adapter_t *staAdapter = NULL; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + tSirUpdateIE updateIE; + beacon_data_t *old; + int ret; + unsigned long rc; + hdd_adapter_list_node_t *pAdapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_STOP_AP, + pAdapter->sessionId, pAdapter->device_mode)); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + return -EOPNOTSUPP; + } + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + staAdapter = pAdapterNode->pAdapter; + + if (WLAN_HDD_INFRA_STATION == staAdapter->device_mode || + (WLAN_HDD_P2P_CLIENT == staAdapter->device_mode) || + (WLAN_HDD_P2P_GO == staAdapter->device_mode)) { + pScanInfo = &staAdapter->scan_info; + + if (pScanInfo && pScanInfo->mScanPending) { + hddLog(LOG1, FL("Aborting pending scan for device mode:%d"), + staAdapter->device_mode); + INIT_COMPLETION(pScanInfo->abortscan_event_var); + hdd_abort_mac_scan(staAdapter->pHddCtx, staAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + rc = wait_for_completion_timeout( + &pScanInfo->abortscan_event_var, + msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN)); + if (!rc) { + hddLog(LOGE, + FL("Timeout occurred while waiting for abortscan")); + VOS_ASSERT(pScanInfo->mScanPending); + } + } + } + + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + /* + * When ever stop ap adapter gets called, we need to check + * whether any restart AP work is pending. If any restart is pending + * then lets finish it and go ahead from there. + */ + if (pHddCtx->cfg_ini->conc_custom_rule1 && + (WLAN_HDD_SOFTAP == pAdapter->device_mode)) { + vos_flush_work(&pHddCtx->sap_start_work); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("Canceled the pending restart work")); + hdd_change_sap_restart_required_status(pHddCtx, false); + } + + pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false; + if (pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) + vos_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list); + vos_mem_zero(&pAdapter->sessionCtx.ap.sapConfig.acs_cfg, + sizeof(struct sap_acs_cfg)); + + hdd_hostapd_stop(dev); + + old = pAdapter->sessionCtx.ap.beacon; + if (!old) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Session(%d) beacon data points to NULL"), + pAdapter->sessionId); + return -EINVAL; + } + + hdd_cleanup_actionframe(pHddCtx, pAdapter); + + mutex_lock(&pHddCtx->sap_lock); + if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) { + hdd_hostapd_state_t *pHostapdState = + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + vos_event_reset(&pHostapdState->stop_bss_event); +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_StopBss(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter)); +#else + status = WLANSAP_StopBss(pHddCtx->pvosContext); +#endif + if (VOS_IS_STATUS_SUCCESS(status)) { + status = vos_wait_single_event(&pHostapdState->stop_bss_event, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("HDD vos wait for single_event failed!!")); + VOS_ASSERT(0); + } + } + clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags); + /* BSS stopped, clear the active sessions for this device mode */ + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); + + pAdapter->sessionCtx.ap.beacon = NULL; + kfree(old); + } + mutex_unlock(&pHddCtx->sap_lock); + + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_FATAL, FL("Stopping the BSS")); + return -EINVAL; + } + + vos_mem_copy(updateIE.bssid, pAdapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = pAdapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = VOS_TRUE; + updateIE.notify = VOS_TRUE; + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, eUPDATE_IE_PROBE_BCN) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE")); + } + + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, eUPDATE_IE_ASSOC_RESP) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on ASSOC_RSP data to PE")); + } + + // Reset WNI_CFG_PROBE_RSP Flags + wlan_hdd_reset_prob_rspies(pAdapter); + +#ifdef WLAN_FEATURE_P2P_DEBUG + if((pAdapter->device_mode == WLAN_HDD_P2P_GO) && + (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE)) { + hddLog(LOGE,"[P2P State] From GO completed to Inactive state " + "GO got removed"); + globalP2PConnectionStatus = P2P_NOT_ACTIVE; + } +#endif + EXIT(); + return ret; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WITH_BACKPORTS) +/** + * wlan_hdd_cfg80211_del_beacon() - delete beacon in sap mode + * @wiphy: Pointer to wiphy + * @dev: Pointer to netdev + * + * Return: zero for success non-zero for failure + */ +static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_del_beacon(wiphy, dev); + vos_ssr_unprotect(__func__); + + return ret; +} +#else +/** + * wlan_hdd_cfg80211_stop_ap() - stop sap + * @wiphy: Pointer to wiphy + * @dev: Pointer to netdev + * + * Return: zero for success non-zero for failure + */ +static int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_stop_ap(wiphy, dev); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0)) || defined(WITH_BACKPORTS) + +static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *params) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_START_AP, pAdapter->sessionId, + params->beacon_interval)); + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter magic is invalid", __func__); + return -ENODEV; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hddLog(LOG2, FL("pAdapter = %p, device mode %s(%d)"), + pAdapter, hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Reached max concurrent connections")); + return -EINVAL; + } + + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + || (pAdapter->device_mode == WLAN_HDD_P2P_GO) + ) + { + beacon_data_t *old, *new; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) || defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type; +#endif + old = pAdapter->sessionCtx.ap.beacon; + + if (old) + return -EALREADY; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) + status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, + &new, + ¶ms->beacon); +#else + status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, + &new, + ¶ms->beacon, + params->dtim_period); +#endif + if (status != 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s:Error!!! Allocating the new beacon", __func__); + return -EINVAL; + } + pAdapter->sessionCtx.ap.beacon = new; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) || defined(WITH_BACKPORTS) + if (params->chandef.width < NL80211_CHAN_WIDTH_80) + channel_type = cfg80211_get_chandef_type(&(params->chandef)); + else + channel_type = NL80211_CHAN_HT40PLUS; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + wlan_hdd_cfg80211_set_channel(wiphy, dev, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + params->channel, params->channel_type); +#else + params->chandef.chan, channel_type); +#endif +#endif + /* set authentication type */ + switch ( params->auth_type ) + { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + pAdapter->sessionCtx.ap.sapConfig.authType = eSAP_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + pAdapter->sessionCtx.ap.sapConfig.authType = eSAP_SHARED_KEY; + break; + default: + pAdapter->sessionCtx.ap.sapConfig.authType = eSAP_AUTO_SWITCH; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) || defined(WITH_BACKPORTS) + pAdapter->sessionCtx.ap.sapConfig.ch_width_orig = + params->chandef.width; +#endif + status = wlan_hdd_cfg80211_start_bss(pAdapter, ¶ms->beacon, params->ssid, + params->ssid_len, params->hidden_ssid); + if (status == 0) { + if (0 != wlan_hdd_set_udp_resp_offload(pAdapter, TRUE)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: set udp resp cmd failed %d", + __func__, status); + } + } + } + + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_start_ap() - start sap + * @wiphy: Pointer to wiphy + * @dev: Pointer to netdev + * @params: Pointer to start ap configuration parameters + * + * Return: zero for success non-zero for failure + */ +static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_start_ap(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + + +static int __wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *params) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + beacon_data_t *old,*new; + int status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_CHANGE_BEACON, + pAdapter->sessionId, pAdapter->device_mode)); + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + return -EOPNOTSUPP; + } + + old = pAdapter->sessionCtx.ap.beacon; + + if (!old) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("session(%d) beacon data points to NULL"), + pAdapter->sessionId); + return -EINVAL; + } + + status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0); + + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_FATAL, FL("new beacon alloc failed")); + return -EINVAL; + } + + pAdapter->sessionCtx.ap.beacon = new; + status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0); + + EXIT(); + return status; +} +/** + * wlan_hdd_cfg80211_change_beacon() - change beacon content in sap mode + * @wiphy: Pointer to wiphy + * @dev: Pointer to netdev + * @params: Pointer to change beacon parameters + * + * Return: zero for success non-zero for failure + */ +static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_change_beacon(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int ret = 0; + eHalStatus halStatus; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_CHANGE_BSS, + pAdapter->sessionId, params->ap_isolate)); + hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, params->ap_isolate); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + return -EOPNOTSUPP; + } + + /* ap_isolate == -1 means that in change bss, upper layer doesn't + * want to update this parameter */ + if (-1 != params->ap_isolate) { + pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate; + + halStatus = sme_ApDisableIntraBssFwd(pHddCtx->hHal, + pAdapter->sessionId, + pAdapter->sessionCtx.ap.apDisableIntraBssFwd); + if (!HAL_STATUS_SUCCESS(halStatus)) { + ret = -EINVAL; + } + } + + EXIT(); + return ret; +} + +static int +wlan_hdd_change_iface_to_adhoc(struct net_device *ndev, + tCsrRoamProfile *pRoamProfile, + enum nl80211_iftype type) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *pConfig = pHddCtx->cfg_ini; + struct wireless_dev *wdev = ndev->ieee80211_ptr; + + pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; + pRoamProfile->phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); + pAdapter->device_mode = WLAN_HDD_IBSS; + wdev->iftype = type; + + return 0; +} + +static int wlan_hdd_change_iface_to_sta_mode(struct net_device *ndev, + enum nl80211_iftype type) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_wext_state_t *wext; + struct wireless_dev *wdev; + VOS_STATUS status; + + ENTER(); + + if (test_bit(ACS_IN_PROGRESS, &pHddCtx->g_event_flags)) + { + hddLog(LOG1, FL("ACS is in progress, don't change iface!")); + return 0; + } + + wdev = ndev->ieee80211_ptr; + hdd_stop_adapter(pHddCtx, pAdapter, VOS_TRUE); + hdd_deinit_adapter(pHddCtx, pAdapter, true); + wdev->iftype = type; + /*Check for sub-string p2p to confirm its a p2p interface*/ + if (NULL != strnstr(ndev->name, "p2p", 3)) { + pAdapter->device_mode = + (type == NL80211_IFTYPE_STATION)? + WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT; + } else { + pAdapter->device_mode = + (type == NL80211_IFTYPE_STATION) ? + WLAN_HDD_INFRA_STATION : WLAN_HDD_P2P_CLIENT; + } + + // set con_mode to STA only when no SAP concurrency mode + if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO))) + hdd_set_conparam(0); + pHddCtx->change_iface = type; + memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx)); + hdd_set_station_ops(pAdapter->dev); + status = hdd_init_station_mode(pAdapter); + wext = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + wext->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata; + wext->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length; + EXIT(); + return status; +} + +static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} +/* FUNCTION: wlan_hdd_change_country_code_cd +* to wait for country code completion +*/ +void* wlan_hdd_change_country_code_cb(void *pAdapter) +{ + hdd_adapter_t *call_back_pAdapter = pAdapter; + complete(&call_back_pAdapter->change_country_code); + return NULL; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_change_iface + * This function is used to set the interface type (INFRASTRUCTURE/ADHOC) + */ +static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct wireless_dev *wdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *pHddCtx; + tCsrRoamProfile *pRoamProfile = NULL; + eCsrRoamBssType LastBSSType; + hdd_config_t *pConfig = NULL; + eMib_dot11DesiredBssType connectedBssType; + unsigned long rc; + VOS_STATUS vstatus; + eHalStatus hstatus; + int status; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_CHANGE_IFACE, + pAdapter->sessionId, type)); + + hddLog(LOG1, FL("Device_mode %s(%d), IFTYPE = 0x%x"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, type); + + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Reached max concurrent connections")); + return -EINVAL; + } + + pConfig = pHddCtx->cfg_ini; + wdev = ndev->ieee80211_ptr; + + /* Reset the current device mode bit mask */ + wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode); + + hdd_tdls_notify_mode_change(pAdapter, pHddCtx); + + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) || + (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)) { + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + pRoamProfile = &pWextState->roamProfile; + LastBSSType = pRoamProfile->BSSType; + + switch (type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: + vstatus = wlan_hdd_change_iface_to_sta_mode(ndev, type); + if (vstatus != VOS_STATUS_SUCCESS) + return -EINVAL; + +#ifdef QCA_LL_TX_FLOW_CT + if (pAdapter->tx_flow_timer_initialized == VOS_FALSE) { + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_tx_resume_timer_expired_handler, + pAdapter); + pAdapter->tx_flow_timer_initialized = VOS_TRUE; + } + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ + + goto done; + + case NL80211_IFTYPE_ADHOC: + wlan_hdd_tdls_exit(pAdapter); + wlan_hdd_clean_tx_flow_control_timer(pHddCtx, pAdapter); + hddLog(LOG1, FL("Setting interface Type to ADHOC")); + wlan_hdd_change_iface_to_adhoc(ndev, pRoamProfile, type); + break; + + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("Setting interface Type to %s"), + (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo"); + + /* Cancel any remain on channel for GO mode */ + if (NL80211_IFTYPE_P2P_GO == type) { + wlan_hdd_cancel_existing_remain_on_channel(pAdapter); + } + + if (NL80211_IFTYPE_AP == type) { + /* As Loading WLAN Driver one interface being created for + * p2p device address. This will take one HW STA and the + * max number of clients that can connect to softAP will be + * reduced by one. so while changing the interface type to + * NL80211_IFTYPE_AP (SoftAP) remove p2p0 interface as it is + * not required in SoftAP mode. + */ + + /* Get P2P Adapter */ + hdd_adapter_t *pP2pAdapter = NULL; + pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE); + + if (pP2pAdapter) { + hdd_stop_adapter(pHddCtx, pP2pAdapter, VOS_TRUE); + hdd_deinit_adapter(pHddCtx, pP2pAdapter, true); + hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE); + } + } + hdd_stop_adapter(pHddCtx, pAdapter, VOS_TRUE); + + /* De-init the adapter */ + hdd_deinit_adapter(pHddCtx, pAdapter, true); + memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx)); + pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ? + WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO; + + /* + * If Powersave Offload is enabled + * Fw will take care incase of concurrency + */ + if (!pHddCtx->cfg_ini->enablePowersaveOffload) { + /* Disable BMPS and IMPS if enabled before starting Go */ + if (WLAN_HDD_P2P_GO == pAdapter->device_mode) { + if(VOS_STATUS_E_FAILURE == + hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO)) { + /* Fail to Exit BMPS */ + VOS_ASSERT(0); + } + } + } + + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) && + (pConfig->apRandomBssidEnabled)) { + /* To meet Android requirements create a randomized + MAC address of the form 02:1A:11:Fx:xx:xx */ + get_random_bytes(&ndev->dev_addr[3], 3); + ndev->dev_addr[0] = 0x02; + ndev->dev_addr[1] = 0x1A; + ndev->dev_addr[2] = 0x11; + ndev->dev_addr[3] |= 0xF0; + memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr, + VOS_MAC_ADDR_SIZE); + pr_info("wlan: Generated HotSpot BSSID "MAC_ADDRESS_STR"\n", + MAC_ADDR_ARRAY(ndev->dev_addr)); + } + + hdd_set_ap_ops(pAdapter->dev); + + /* This is for only SAP mode where users can + * control country through ini. + * P2P GO follows station country code + * acquired during the STA scanning. */ + if ((NL80211_IFTYPE_AP == type) && + (memcmp(pConfig->apCntryCode, + CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)) { + hddLog(LOG1, FL("Setting country code from INI")); + init_completion(&pAdapter->change_country_code); + hstatus = sme_ChangeCountryCode(pHddCtx->hHal, + (void *)(tSmeChangeCountryCallback) + wlan_hdd_change_country_code_cb, + pConfig->apCntryCode, pAdapter, + pHddCtx->pvosContext, + eSIR_FALSE, eSIR_TRUE); + if (eHAL_STATUS_SUCCESS == hstatus) { + /* Wait for completion */ + rc = wait_for_completion_timeout( + &pAdapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (!rc) { + hddLog(LOGE, + FL("SME Timed out while setting country code")); + } + } else { + hddLog(LOGE, FL("SME Change Country code failed")); + return -EINVAL; + } + } + + vstatus = hdd_init_ap_mode(pAdapter); + if (vstatus != VOS_STATUS_SUCCESS) { + hddLog(LOGP, FL("Error initializing the ap mode")); + return -EINVAL; + } + hdd_set_conparam(1); + +#ifdef QCA_LL_TX_FLOW_CT + if (pAdapter->tx_flow_timer_initialized == VOS_FALSE) { + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_softap_tx_resume_timer_expired_handler, + pAdapter); + pAdapter->tx_flow_timer_initialized = VOS_TRUE; + } + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_softap_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ + + /* Interface type changed update in wiphy structure */ + if (wdev) { + wdev->iftype = type; + pHddCtx->change_iface = type; + } else { + hddLog(LOGE, FL("Wireless dev is NULL")); + return -EINVAL; + } + goto done; + } + + default: + hddLog(LOGE, FL("Unsupported interface type (%d)"), type); + return -EOPNOTSUPP; + } + } else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + switch (type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_ADHOC: + status = wlan_hdd_change_iface_to_sta_mode(ndev, type); + if (status != VOS_STATUS_SUCCESS) + return status; + +#ifdef QCA_LL_TX_FLOW_CT + if ((NL80211_IFTYPE_P2P_CLIENT == type) || + (NL80211_IFTYPE_STATION == type)) { + if (pAdapter->tx_flow_timer_initialized == VOS_FALSE) { + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_tx_resume_timer_expired_handler, + pAdapter); + pAdapter->tx_flow_timer_initialized = VOS_TRUE; + } + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); + } +#endif /* QCA_LL_TX_FLOW_CT */ + + /* FW will take care if PS offload is enabled. */ + if (pHddCtx->cfg_ini->enablePowersaveOffload) + goto done; + + if (pHddCtx->hdd_wlan_suspended) { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); + goto done; + + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + wdev->iftype = type; + pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ? + WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO; +#ifdef QCA_LL_TX_FLOW_CT + if (pAdapter->tx_flow_timer_initialized == VOS_FALSE) { + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_softap_tx_resume_timer_expired_handler, + pAdapter); + pAdapter->tx_flow_timer_initialized = VOS_TRUE; + } + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_softap_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ + goto done; + + default: + hddLog(LOGE, FL("Unsupported interface type(%d)"), type); + return -EOPNOTSUPP; + } + } else { + hddLog(LOGE, FL("Unsupported device mode(%d)"), pAdapter->device_mode); + return -EOPNOTSUPP; + } + + if (LastBSSType != pRoamProfile->BSSType) { + /* Interface type changed update in wiphy structure */ + wdev->iftype = type; + + /* The BSS mode changed, We need to issue disconnect + if connected or in IBSS disconnect state */ + if (hdd_connGetConnectedBssType( + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType) || + (eCSR_BSS_TYPE_START_IBSS == LastBSSType)) { + /* Need to issue a disconnect to CSR.*/ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + if (eHAL_STATUS_SUCCESS == + sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED)) { + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hddLog(LOGE, + FL("Wait on disconnect_comp_var failed")); + } + } + } + } + +done: + /* Set bitmask based on updated value */ + wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode); + + /* Only STA mode support TM now + * all other mode, TM feature should be disabled */ + if ((pHddCtx->cfg_ini->thermalMitigationEnable) && + (~VOS_STA & pHddCtx->concurrency_mode)) { + hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0); + } + + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_all_scan_intf_info(pHddCtx); +#endif + + EXIT(); + return 0; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_change_iface + * wrapper function to protect the actual implementation from SSR. + */ +static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef FEATURE_WLAN_TDLS +static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + bool update, + tCsrStaParams *StaParams) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + VOS_STATUS status; + hddTdlsPeer_t *pTdlsPeer; + tANI_U16 numCurrTdlsPeers; + unsigned long rc; + long ret; + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return ret; + } + + if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) || + (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: TDLS mode is disabled OR not enabled in FW." + MAC_ADDRESS_STR " Request declined.", + __func__, MAC_ADDR_ARRAY(mac)); + return -ENOTSUPP; + } + + pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac); + + if ( NULL == pTdlsPeer ) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid", + __func__, MAC_ADDR_ARRAY(mac), update); + return -EINVAL; + } + + /* in add station, we accept existing valid staId if there is */ + if ((0 == update) && + ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) || + (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR + " link_status %d. staId %d. add station ignored.", + __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId); + return 0; + } + /* in change station, we accept only when staId is valid */ + if ((1 == update) && + ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) || + (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId)))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " link status %d. staId %d. change station %s.", + __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId, + (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined"); + return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM; + } + + /* when others are on-going, we want to change link_status to idle */ + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " TDLS setup is ongoing. Request declined.", + __func__, MAC_ADDR_ARRAY(mac)); + goto error; + } + + /* first to check if we reached to maximum supported TDLS peer. + TODO: for now, return -EPERM looks working fine, + but need to check if any other errno fit into this category.*/ + numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter); + if (pHddCtx->max_num_tdls_sta <= numCurrTdlsPeers) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " TDLS Max peer already connected. Request declined." + " Num of peers (%d), Max allowed (%d).", + __func__, MAC_ADDR_ARRAY(mac), numCurrTdlsPeers, + pHddCtx->max_num_tdls_sta); + goto error; + } + else + { + hddTdlsPeer_t *pTdlsPeer; + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); + if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " already connected. Request declined.", + __func__, MAC_ADDR_ARRAY(mac)); + return -EPERM; + } + } + if (0 == update) + wlan_hdd_tdls_set_link_status(pAdapter, + mac, + eTDLS_LINK_CONNECTING, + eTDLS_LINK_SUCCESS); + + /* debug code */ + if (NULL != StaParams) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: TDLS Peer Parameters.", __func__); + if(StaParams->htcap_present) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "ht_capa->extended_capabilities: %0x", + StaParams->HTCap.extendedHtCapInfo); + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "params->capability: %0x",StaParams->capability); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "params->ext_capab_len: %0x",StaParams->extn_capability[0]); + if(StaParams->vhtcap_present) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x", + StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest, + StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest); + } + { + int i = 0; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:"); + for (i = 0; i < sizeof(StaParams->supported_rates); i++) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "[%d]: %x ", i, StaParams->supported_rates[i]); + } + } /* end debug code */ + else if ((1 == update) && (NULL == StaParams)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s : update is true, but staParams is NULL. Error!", __func__); + return -EPERM; + } + + INIT_COMPLETION(pAdapter->tdls_add_station_comp); + + /* Update the number of stream for each peer */ + if ((NULL != StaParams) && (StaParams->htcap_present)) { + hddTdlsPeer_t *tdls_peer; + tdls_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); + if (NULL != tdls_peer) + tdls_peer->spatial_streams = StaParams->HTCap.suppMcsSet[1]; + } + + if (!update) + { + status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, mac); + } + else + { + status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, mac, StaParams); + } + + rc = wait_for_completion_timeout(&pAdapter->tdls_add_station_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA)); + + if (!rc) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: timeout waiting for tdls add station indication", + __func__); + return -EPERM; + } + + if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Add Station is unsuccessful", __func__); + return -EPERM; + } + + return 0; + +error: + wlan_hdd_tdls_set_link_status(pAdapter, + mac, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + return -EPERM; + +} + +static bool wlan_hdd_is_duplicate_channel(tANI_U8 *arr, + int index, + tANI_U8 match) +{ + int i; + for (i = 0; i < index; i++) { + if (arr[i] == match) + return TRUE; + } + return FALSE; +} +#endif /* FEATURE_WLAN_TDLS */ + +/** + * __wlan_hdd_change_station() - change station + * @wiphy: Pointer to the wiphy structure + * @dev: Pointer to the net device. + * @mac: bssid + * @params: Pointer to station parameters + * + * Return: 0 for success, error number on failure. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS) +static int __wlan_hdd_change_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +#else +static int __wlan_hdd_change_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac, + struct station_parameters *params) +#endif +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + v_MACADDR_t STAMacAddress; +#ifdef FEATURE_WLAN_TDLS + tCsrStaParams StaParams = {0}; + tANI_U8 isBufSta = 0; + tANI_U8 isOffChannelSupported = 0; +#endif + int ret; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CHANGE_STATION, + pAdapter->sessionId, params->listen_interval)); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t)); + + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { + status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress, + WLANTL_STA_AUTHENTICATED); + + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Not able to change TL state to AUTHENTICATED")); + return -EINVAL; + } + } + } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { +#ifdef FEATURE_WLAN_TDLS + if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { + StaParams.capability = params->capability; + StaParams.uapsd_queues = params->uapsd_queues; + StaParams.max_sp = params->max_sp; + + /* Convert (first channel , number of channels) tuple to + * the total list of channels. This goes with the assumption + * that if the first channel is < 14, then the next channels + * are an incremental of 1 else an incremental of 4 till the number + * of channels. + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: params->supported_channels_len: %d", + __func__, params->supported_channels_len); + if (0 != params->supported_channels_len) { + int i = 0, j = 0, k = 0, no_of_channels = 0; + int num_unique_channels; + int next; + for (i = 0 ; i < params->supported_channels_len && + j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) { + int wifi_chan_index; + if (!wlan_hdd_is_duplicate_channel( + StaParams.supported_channels, + j, + params->supported_channels[i])){ + StaParams.supported_channels[j] = + params->supported_channels[i]; + } else { + continue; + } + wifi_chan_index = + ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 ); + no_of_channels = params->supported_channels[i + 1]; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d", + __func__, i, j, k, j, + StaParams.supported_channels[j], + wifi_chan_index, + no_of_channels); + + for (k = 1; k <= no_of_channels && + j < SIR_MAC_MAX_SUPP_CHANNELS - 1; k++) { + next = StaParams.supported_channels[j] + wifi_chan_index; + if (!wlan_hdd_is_duplicate_channel( + StaParams.supported_channels, + j+1, + next)){ + StaParams.supported_channels[j + 1] = next; + } else { + continue; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", + __func__, i, j, k, j+1, + StaParams.supported_channels[j+1]); + j += 1; + } + } + num_unique_channels = j+1; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Unique Channel List", __func__); + for (i = 0; i < num_unique_channels; i++) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: StaParams.supported_channels[%d]: %d,", + __func__, i, StaParams.supported_channels[i]); + } + /* num of channels should not be more than max + * number of channels in 2.4GHz and 5GHz + */ + if (MAX_CHANNEL < num_unique_channels) + num_unique_channels = MAX_CHANNEL; + + StaParams.supported_channels_len = num_unique_channels; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: After removing duplcates StaParams.supported_channels_len: %d", + __func__, StaParams.supported_channels_len); + } + vos_mem_copy(StaParams.supported_oper_classes, + params->supported_oper_classes, + params->supported_oper_classes_len); + StaParams.supported_oper_classes_len = + params->supported_oper_classes_len; + + if (0 != params->ext_capab_len) + vos_mem_copy(StaParams.extn_capability, params->ext_capab, + sizeof(StaParams.extn_capability)); + + if (NULL != params->ht_capa) { + StaParams.htcap_present = 1; + vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap)); + } + + StaParams.supported_rates_len = params->supported_rates_len; + + /* + * Note : The Maximum sizeof supported_rates sent by the Supplicant + * is 32. The supported_rates array, for all the structures + * propagating till Add Sta to the firmware has to be modified, + * if the supplicant (ieee80211) is modified to send more rates. + */ + + /* To avoid Data Corruption, set to max length + to SIR_MAC_MAX_SUPP_RATES */ + if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES) + StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES; + + if (0 != StaParams.supported_rates_len) { + int i = 0; + vos_mem_copy(StaParams.supported_rates, params->supported_rates, + StaParams.supported_rates_len); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Supported Rates with Length %d", StaParams.supported_rates_len); + for (i=0; i < StaParams.supported_rates_len; i++) + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "[%d]: %0x", i, StaParams.supported_rates[i]); + } + + if (NULL != params->vht_capa) { + StaParams.vhtcap_present = 1; + vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap)); + } + + if (0 != params->ext_capab_len ) { + /*Define A Macro : TODO Sunil*/ + if ((1<<4) & StaParams.extn_capability[3]) { + isBufSta = 1; + } + /* TDLS Channel Switching Support */ + if ((1<<6) & StaParams.extn_capability[3]) { + isOffChannelSupported = 1; + } + } + + status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac, + &StaParams, isBufSta, + isOffChannelSupported); + if (VOS_STATUS_SUCCESS != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wlan_hdd_tdls_set_peer_caps failed!")); + return -EINVAL; + } + + status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams); + if (VOS_STATUS_SUCCESS != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wlan_hdd_tdls_add_station failed!")); + return -EINVAL; + } + } +#endif + } + EXIT(); + return ret; +} + +/** + * wlan_hdd_change_station() - cfg80211 change station handler function + * @wiphy: Pointer to the wiphy structure + * @dev: Pointer to the net device. + * @mac: bssid + * @params: Pointer to station parameters + * + * This is the cfg80211 change station handler function which invokes + * the internal function @__wlan_hdd_change_station with + * SSR protection. + * + * Return: 0 for success, error number on failure. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS) +static int wlan_hdd_change_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +#else +static int wlan_hdd_change_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac, + struct station_parameters *params) +#endif +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_change_station(wiphy, dev, mac, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_add_key + * This function is used to initialize the key information + */ +static int __wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params + ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + tCsrRoamSetKey setKey; + u8 groupmacaddr[VOS_MAC_ADDR_SIZE] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int status; + v_U32_t roamId= 0xFF; +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; +#endif + hdd_hostapd_state_t *pHostapdState; + eHalStatus halStatus; + hdd_context_t *pHddCtx; + hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_ADD_KEY, + pAdapter->sessionId, params->key_len)); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + if (CSR_MAX_NUM_KEY <= key_index) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, + key_index); + + return -EINVAL; + } + + if (CSR_MAX_KEY_LEN < params->key_len) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__, + params->key_len); + + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: called with key index = %d & key length %d", + __func__, key_index, params->key_len); + + /*extract key idx, key len and key*/ + vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); + setKey.keyId = key_index; + setKey.keyLength = params->key_len; + vos_mem_copy(&setKey.Key[0],params->key, params->key_len); + + switch (params->cipher) + { + case WLAN_CIPHER_SUITE_WEP40: + setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + break; + + case WLAN_CIPHER_SUITE_WEP104: + setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + break; + + case WLAN_CIPHER_SUITE_TKIP: + { + u8 *pKey = &setKey.Key[0]; + setKey.encType = eCSR_ENCRYPT_TYPE_TKIP; + + + vos_mem_zero(pKey, CSR_MAX_KEY_LEN); + + /*Supplicant sends the 32bytes key in this order + + |--------------|----------|----------| + | Tk1 |TX-MIC | RX Mic | + |--------------|----------|----------| + <---16bytes---><--8bytes--><--8bytes--> + + */ + /*Sme expects the 32 bytes key to be in the below order + + |--------------|----------|----------| + | Tk1 |RX-MIC | TX Mic | + |--------------|----------|----------| + <---16bytes---><--8bytes--><--8bytes--> + */ + /* Copy the Temporal Key 1 (TK1) */ + vos_mem_copy(pKey, params->key, 16); + + /*Copy the rx mic first*/ + vos_mem_copy(&pKey[16], ¶ms->key[24], 8); + + /*Copy the tx mic */ + vos_mem_copy(&pKey[24], ¶ms->key[16], 8); + + + break; + } + + case WLAN_CIPHER_SUITE_CCMP: + setKey.encType = eCSR_ENCRYPT_TYPE_AES; + break; + +#ifdef FEATURE_WLAN_WAPI + case WLAN_CIPHER_SUITE_SMS4: + { + vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); + wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr, + params->key, params->key_len); + return 0; + } +#endif + +#ifdef FEATURE_WLAN_ESE + case WLAN_CIPHER_SUITE_KRK: + setKey.encType = eCSR_ENCRYPT_TYPE_KRK; + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WLAN_CIPHER_SUITE_BTK: + setKey.encType = eCSR_ENCRYPT_TYPE_BTK; + break; +#endif +#endif + +#ifdef WLAN_FEATURE_11W + case WLAN_CIPHER_SUITE_AES_CMAC: + setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC; + break; +#endif + + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u", + __func__, params->cipher); + return -EOPNOTSUPP; + } + + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d", + __func__, setKey.encType); + + if (!pairwise) + { + /* set group key*/ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s- %d: setting Broadcast key", + __func__, __LINE__); + setKey.keyDirection = eSIR_RX_ONLY; + vos_mem_copy(setKey.peerMac,groupmacaddr, VOS_MAC_ADDR_SIZE); + } + else + { + /* set pairwise key*/ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s- %d: setting pairwise key", + __func__, __LINE__); + setKey.keyDirection = eSIR_TX_RX; + vos_mem_copy(setKey.peerMac, mac_addr, VOS_MAC_ADDR_SIZE); + } + if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise) + { + /* if a key is already installed, block all subsequent ones */ + if (pAdapter->sessionCtx.station.ibss_enc_key_installed) { + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: IBSS key installed already", __func__); + return 0; + } + + setKey.keyDirection = eSIR_TX_RX; + /*Set the group key*/ + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId ); + + if ( 0 != status ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed, returned %d", __func__, status); + return -EINVAL; + } + /*Save the keys here and call sme_RoamSetKey for setting + the PTK after peer joins the IBSS network*/ + vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key, + &setKey, sizeof(tCsrRoamSetKey)); + + pAdapter->sessionCtx.station.ibss_enc_key_installed = 1; + return status; + } + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) + { + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + if( pHostapdState->bssState == BSS_START ) + { +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_SetKeySta( WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), + &setKey); +#else + status = WLANSAP_SetKeySta( pVosContext, &setKey); +#endif + if ( status != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] WLANSAP_SetKeySta returned ERROR status= %d", + __LINE__, status ); + } + } + + if (pairwise || + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType || + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType) + vos_mem_copy(&ap_ctx->wepKey[key_index], &setKey, + sizeof(tCsrRoamSetKey)); + else + vos_mem_copy(&ap_ctx->groupKey, &setKey, + sizeof(tCsrRoamSetKey)); + + } + else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ) + { + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (!pairwise) + { + /* set group key*/ + if (pHddStaCtx->roam_info.deferKeyComplete) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s- %d: Perform Set key Complete", + __func__, __LINE__); + hdd_PerformRoamSetKeyComplete(pAdapter); + } + } + + pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len; + + pWextState->roamProfile.Keys.defaultIndex = key_index; + + + vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0], + params->key, params->key_len); + + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d", + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5], + setKey.keyDirection); + + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* The supplicant may attempt to set the PTK once pre-authentication + is done. Save the key in the UMAC and include it in the ADD BSS + request */ + halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey); + if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } + else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); + return -EINVAL; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + /* issue set key request to SME*/ + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId ); + + if ( 0 != status ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed, returned %d", __func__, status); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + return -EINVAL; + } + + + /* in case of IBSS as there was no information available about WEP keys during + * IBSS join, group key initialized with NULL key, so re-initialize group key + * with correct value*/ + if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) && + !( ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) + && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) + ) + && + ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher) + || (WLAN_CIPHER_SUITE_WEP104 == params->cipher) + ) + ) + { + setKey.keyDirection = eSIR_RX_ONLY; + vos_mem_copy(setKey.peerMac,groupmacaddr, VOS_MAC_ADDR_SIZE); + + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d", + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5], + setKey.keyDirection); + + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId ); + + if ( 0 != status ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed for group key (IBSS), returned %d", + __func__, status); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + return -EINVAL; + } + } + } + EXIT(); + return 0; +} + +static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params + ) +{ + int ret; + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise, + mac_addr, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_get_key + * This function is used to get the key information + */ +static int __wlan_hdd_cfg80211_get_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params*) + ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); + struct key_params params; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + memset(¶ms, 0, sizeof(params)); + + if (CSR_MAX_NUM_KEY <= key_index) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid key index %d"), key_index); + return -EINVAL; + } + + switch (pRoamProfile->EncryptionType.encryptionType[0]) { + case eCSR_ENCRYPT_TYPE_NONE: + params.cipher = IW_AUTH_CIPHER_NONE; + break; + + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + params.cipher = WLAN_CIPHER_SUITE_WEP40; + break; + + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104: + params.cipher = WLAN_CIPHER_SUITE_WEP104; + break; + + case eCSR_ENCRYPT_TYPE_TKIP: + params.cipher = WLAN_CIPHER_SUITE_TKIP; + break; + + case eCSR_ENCRYPT_TYPE_AES: + params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; + break; + + default: + params.cipher = IW_AUTH_CIPHER_NONE; + break; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_GET_KEY, + pAdapter->sessionId, params.cipher)); + + params.key_len = pRoamProfile->Keys.KeyLength[key_index]; + params.seq_len = 0; + params.seq = NULL; + params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0]; + callback(cookie, ¶ms); + + EXIT(); + return 0; +} + +static int wlan_hdd_cfg80211_get_key( + struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params*) + ) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise, + mac_addr, cookie, callback); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_del_key() - cfg80211 delete key + * @wiphy: Pointer to wiphy structure. + * @ndev: Pointer to net_device structure. + * @key_index: key index + * @pairwise: pairwise + * @mac_addr: mac address + * + * This function is used to delete the key information + * + * Return: 0 for success, error number on failure. + */ +static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, const u8 *mac_addr) +{ + int status = 0; + + //This code needs to be revisited. There is sme_removeKey API, we should + //plan to use that. After the change to use correct index in setkey, + //it is observed that this is invalidating peer + //key index whenever re-key is done. This is affecting data link. + //It should be ok to ignore del_key. +#if 0 + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; + u8 groupmacaddr[VOS_MAC_ADDR_SIZE] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + tCsrRoamSetKey setKey; + v_U32_t roamId= 0xFF; + + ENTER(); + + hddLog(LOG2, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + if (CSR_MAX_NUM_KEY <= key_index) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, + key_index); + + return -EINVAL; + } + + vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); + setKey.keyId = key_index; + + if (mac_addr) + vos_mem_copy(setKey.peerMac, mac_addr, VOS_MAC_ADDR_SIZE); + else + vos_mem_copy(setKey.peerMac, groupmacaddr, VOS_MAC_ADDR_SIZE); + + setKey.encType = eCSR_ENCRYPT_TYPE_NONE; + + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + || (pAdapter->device_mode == WLAN_HDD_P2P_GO) + ) + { + + hdd_hostapd_state_t *pHostapdState = + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + if( pHostapdState->bssState == BSS_START) + { +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_SetKeySta( WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), + &setKey); +#else + status = WLANSAP_SetKeySta( pVosContext, &setKey); +#endif + + if ( status != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] WLANSAP_SetKeySta returned ERROR status= %d", + __LINE__, status ); + } + } + } + else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + ) + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x", + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5]); + if(pAdapter->sessionCtx.station.conn_info.connState == + eConnectionState_Associated) + { + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId ); + + if ( 0 != status ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failure, returned %d", + __func__, status); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + return -EINVAL; + } + } + } +#endif + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function + * @wiphy: Pointer to wiphy structure. + * @dev: Pointer to net_device structure. + * @key_index: key index + * @pairwise: pairwise + * @mac_addr: mac address + * + * This is the cfg80211 delete key handler function which invokes + * the internal function @__wlan_hdd_cfg80211_del_key with + * SSR protection. + * + * Return: 0 for success, error number on failure. + */ +static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_index, + bool pairwise, const u8 *mac_addr) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index, + pairwise, mac_addr); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_set_default_key + * This function is used to set the default tx key index + */ +static int __wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool unicast, bool multicast) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY, + pAdapter->sessionId, key_index)); + + hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, key_index); + + if (CSR_MAX_NUM_KEY <= key_index) { + hddLog(LOGE, FL("Invalid key index %d"), key_index); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { + if ((eCSR_ENCRYPT_TYPE_TKIP != + pHddStaCtx->conn_info.ucEncryptionType) && + (eCSR_ENCRYPT_TYPE_AES != + pHddStaCtx->conn_info.ucEncryptionType)) { + /* If default key index is not same as previous one, + * then update the default key index */ + + tCsrRoamSetKey setKey; + v_U32_t roamId= 0xFF; + tCsrKeys *Keys = &pWextState->roamProfile.Keys; + + hddLog(LOG2, FL("Default tx key index %d"), key_index); + + Keys->defaultIndex = (u8)key_index; + vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey)); + setKey.keyId = key_index; + setKey.keyLength = Keys->KeyLength[key_index]; + + vos_mem_copy(&setKey.Key[0], + &Keys->KeyMaterial[key_index][0], + Keys->KeyLength[key_index]); + + setKey.keyDirection = eSIR_TX_RX; + + vos_mem_copy(setKey.peerMac, + &pHddStaCtx->conn_info.bssId[0], VOS_MAC_ADDR_SIZE); + + if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN && + pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP104) { + /* + * In the case of dynamic wep supplicant hardcodes DWEP type + * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for + * WEP-40 encryption. In this case the key length is 5 but the + * encryption type is 104 hence checking the key length(5) and + * encryption type(104) and switching encryption type to 40. + */ + pWextState->roamProfile.EncryptionType.encryptionType[0] = + eCSR_ENCRYPT_TYPE_WEP40; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = + eCSR_ENCRYPT_TYPE_WEP40; + } + + setKey.encType = + pWextState->roamProfile.EncryptionType.encryptionType[0]; + + /* Issue set key request */ + status = sme_RoamSetKey(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId); + + if (0 != status) { + hddLog(LOGE, FL("sme_RoamSetKey failed, returned %d"), status); + return -EINVAL; + } + } + } else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) { + /* In SoftAp mode setting key direction for default mode */ + if ((eCSR_ENCRYPT_TYPE_TKIP != + pWextState->roamProfile.EncryptionType.encryptionType[0]) && + (eCSR_ENCRYPT_TYPE_AES != + pWextState->roamProfile.EncryptionType.encryptionType[0])) { + /* Saving key direction for default key index to TX default */ + hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT; + hddLog(LOG1, + FL("key index passed for sme_RoamSetDefaultKeyIndex %d"), + key_index); + sme_roam_set_default_key_index(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, key_index); + } + } + + EXIT(); + return status; +} + +static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool unicast, bool multicast) +{ + int ret; + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast, + multicast); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_update_bss_list + * This function is used to inform nl80211 interface that BSS might have + * been lost. + */ +struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_list( + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo) +{ + struct net_device *dev = pAdapter->dev; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc; + int chan_no; + unsigned int freq; + struct ieee80211_channel *chan; + struct cfg80211_bss *bss = NULL; + + ENTER(); + + if (NULL == pBssDesc) { + hddLog(LOGE, FL("pBssDesc is NULL")); + return bss; + } + + if (NULL == pRoamInfo->pProfile) { + hddLog(LOGE, FL("Roam profile is NULL")); + return bss; + } + + chan_no = pBssDesc->channelId; + + if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ)) { + freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ); + } else { + freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ); + } + + chan = __ieee80211_get_channel(wiphy, freq); + + if (!chan) { + hddLog(LOGE, FL("chan pointer is NULL")); + return NULL; + } + + bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId, + &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.ssId[0], + pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS) \ + && !defined(IEEE80211_PRIVACY) + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); +#else + IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); +#endif + if (bss == NULL) { + hddLog(LOGE, FL("BSS not present")); + } else { + hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pBssDesc->bssId)); + cfg80211_unlink_bss(wiphy, bss); + } + return bss; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame + * This function is used to inform the BSS details to nl80211 interface. + */ +struct cfg80211_bss* +wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, + tSirBssDescription *bss_desc + ) +{ + /* + cfg80211_inform_bss() is not updating ie field of bss entry, if entry + already exists in bss data base of cfg80211 for that particular BSS ID. + Using cfg80211_inform_bss_frame to update the bss entry instead of + cfg80211_inform_bss, But this call expects mgmt packet as input. As of + now there is no possibility to get the mgmt(probe response) frame from PE, + converting bss_desc to ieee80211_mgmt(probe response) and passing to + cfg80211_inform_bss_frame. + */ + struct net_device *dev = pAdapter->dev; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + int chan_no = bss_desc->channelId; +#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS + qcom_ie_age *qie_age = NULL; + int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age); +#else + int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ); +#endif + const char *ie = + ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL); + unsigned int freq; + struct ieee80211_channel *chan; + struct ieee80211_mgmt *mgmt = NULL; + struct cfg80211_bss *bss_status = NULL; + size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length; + int rssi = 0; + hdd_context_t *pHddCtx; + int status; +#ifdef CONFIG_CNSS + struct timespec ts; +#endif + hdd_config_t *cfg_param = NULL; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return NULL; + + cfg_param = pHddCtx->cfg_ini; + mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL); + if (!mgmt) { + hddLog(LOGE, FL("memory allocation failed")); + return NULL; + } + + memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN); + +#ifdef CONFIG_CNSS + /* Android does not want the time stamp from the frame. + Instead it wants a monotonic increasing value */ + cnss_get_monotonic_boottime(&ts); + mgmt->u.probe_resp.timestamp = + ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); +#else + /* keep old behavior for non-open source (for now) */ + memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp, + sizeof (bss_desc->timeStamp)); + +#endif + + mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval; + mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo; + +#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS + /* GPS Requirement: need age ie per entry. Using vendor specific. */ + /* Assuming this is the last IE, copy at the end */ + ie_length -=sizeof(qcom_ie_age); + qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length); + qie_age->element_id = QCOM_VENDOR_IE_ID; + qie_age->len = QCOM_VENDOR_IE_AGE_LEN; + qie_age->oui_1 = QCOM_OUI1; + qie_age->oui_2 = QCOM_OUI2; + qie_age->oui_3 = QCOM_OUI3; + qie_age->type = QCOM_VENDOR_IE_AGE_TYPE; + qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime; + qie_age->tsf_delta = bss_desc->tsf_delta; +#endif + + memcpy(mgmt->u.probe_resp.variable, ie, ie_length); + if (bss_desc->fProbeRsp) { + mgmt->frame_control |= + (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); + } else { + mgmt->frame_control |= + (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); + } + + if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) && + (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) { + freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ); + } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) && + (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) { + freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ); + } else { + hddLog(LOGE, FL("Invalid chan_no %d"), chan_no); + kfree(mgmt); + return NULL; + } + + chan = __ieee80211_get_channel(wiphy, freq); + /* + * When the band is changed on the fly using the GUI, three things are done + * 1. scan abort + * 2. flush scan results from cache + * 3. update the band with the new band user specified (refer to the + * hdd_setBand_helper function) as part of the scan abort, message will be + * queued to PE and we proceed with flushing and changing the band. + * PE will stop the scanning further and report back the results what ever + * it had till now by calling the call back function. + * if the time between update band and scandone call back is sufficient + * enough the band change reflects in SME, SME validates the channels + * and discards the channels corresponding to previous band and calls back + * with zero bss results. but if the time between band update and scan done + * callback is very small then band change will not reflect in SME and SME + * reports to HDD all the channels corresponding to previous band.this is + * due to race condition.but those channels are invalid to the new band and + * so this function __ieee80211_get_channel will return NULL.Each time we + * report scan result with this pointer null warning kernel trace is printed + * if the scan results contain large number of APs continuously kernel + * warning trace is printed and it will lead to apps watch dog bark. + * So drop the bss and continue to next bss. + */ + if (chan == NULL) { + hddLog(LOGE, FL("chan pointer is NULL")); + kfree(mgmt); + return NULL; + } + + /* Based on .ini configuration, raw rssi can be reported for bss. + * Raw rssi is typically used for estimating power. + */ + + rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw : + bss_desc->rssi; + + /* Supplicant takes the signal strength in terms of mBm(100*dBm) */ + rssi = (VOS_MIN(rssi, 0)) * 100; + + hddLog(LOG1, FL("BSSID: "MAC_ADDRESS_STR" Channel:%d RSSI:%d"), + MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq, (int)(rssi/100)); + + bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi, + GFP_KERNEL); + kfree(mgmt); + EXIT(); + return bss_status; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_update_bss_db + * This function is used to update the BSS data base of CFG8011 + */ +struct cfg80211_bss* +wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo) +{ + tCsrRoamConnectedProfile roamProfile; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + struct cfg80211_bss *bss = NULL; + + ENTER(); + + memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile)); + sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile); + + if (NULL != roamProfile.pBssDesc) { + bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter, + roamProfile.pBssDesc); + + if (NULL == bss) { + hddLog(LOG1, FL("wlan_hdd_cfg80211_inform_bss_frame return NULL")); + } + + sme_RoamFreeConnectProfile(hHal, &roamProfile); + } else { + hddLog(LOGE, FL("roamProfile.pBssDesc is NULL")); + } + EXIT(); + return bss; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_update_bss + */ +static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, + hdd_adapter_t *pAdapter + ) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tCsrScanResultInfo *pScanResult; + eHalStatus status = 0; + tScanResultHandle pResult; + struct cfg80211_bss *bss_status = NULL; + hdd_context_t *pHddCtx; + int ret; + bool is_p2p_scan = false; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_UPDATE_BSS, + NO_SESSION, pAdapter->sessionId)); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (pAdapter->request != NULL) + { + if ((pAdapter->request->n_ssids == 1) + && (pAdapter->request->ssids != NULL) + && vos_mem_compare(&pAdapter->request->ssids[0], "DIRECT-", 7)) + is_p2p_scan = true; + } + + /* + * start getting scan results and populate cgf80211 BSS database + */ + status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult); + + /* no scan results */ + if (NULL == pResult) { + hddLog(LOG1, FL("No scan result Status %d"), status); + return status; + } + + pScanResult = sme_ScanResultGetFirst(hHal, pResult); + + while (pScanResult) { + /* + * cfg80211_inform_bss() is not updating ie field of bss entry, if + * entry already exists in bss data base of cfg80211 for that + * particular BSS ID. Using cfg80211_inform_bss_frame to update the + * bss entry instead of cfg80211_inform_bss, But this call expects + * mgmt packet as input. As of now there is no possibility to get + * the mgmt(probe response) frame from PE, converting bss_desc to + * ieee80211_mgmt(probe response) and passing to c + * fg80211_inform_bss_frame. + * */ + + if(is_p2p_scan && (pScanResult->ssId.ssId != NULL) && + !vos_mem_compare( pScanResult->ssId.ssId, "DIRECT-", 7) ) + { + pScanResult = sme_ScanResultGetNext(hHal, pResult); + continue; //Skip the non p2p bss entries + } + + bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter, + &pScanResult->BssDescriptor); + + + if (NULL == bss_status) { + hddLog(LOG1, FL("NULL returned by cfg80211_inform_bss_frame")); + } else { + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + wiphy, +#endif + bss_status); + } + + pScanResult = sme_ScanResultGetNext(hHal, pResult); + } + + sme_ScanResultPurge(hHal, pResult); + + /* + * For SAP mode, scan is invoked by hostapd during SAP start, if hostapd is + * restarted, we need to flush previous scan result so that it will reflect + * environment change + */ + if (pAdapter->device_mode == WLAN_HDD_SOFTAP +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN +#endif + ) + sme_ScanFlushResult(hHal, pAdapter->sessionId); + + EXIT(); + is_p2p_scan = false; + return 0; +} + +#define dump_pmkid(pMac, pmkid) \ +{ \ + hddLog(LOG1, "PMKSA-ID: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", \ + pmkid[0], pmkid[1], pmkid[2], pmkid[3], pmkid[4], pmkid[5], \ + pmkid[6], pmkid[7], pmkid[8], pmkid[9], pmkid[10], \ + pmkid[11], pmkid[12], pmkid[13], pmkid[14], pmkid[15]); \ +} + +#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))\ + || defined(WITH_BACKPORTS) +/* + * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify + * This function is used to notify the supplicant of a new PMKSA candidate. + */ +int wlan_hdd_cfg80211_pmksa_candidate_notify( + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + int index, bool preauth ) +{ +#ifdef FEATURE_WLAN_OKC + struct net_device *dev = pAdapter->dev; + hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + + ENTER(); + hddLog(LOG1, FL("is going to notify supplicant of:")); + + if (NULL == pRoamInfo) { + hddLog(LOGP, FL("pRoamInfo is NULL")); + return -EINVAL; + } + + if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx)) { + hddLog(VOS_TRACE_LEVEL_INFO, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pRoamInfo->bssid)); + cfg80211_pmksa_candidate_notify(dev, index, pRoamInfo->bssid, + preauth, GFP_KERNEL); + } +#endif /* FEATURE_WLAN_OKC */ + return 0; +} +#endif //FEATURE_WLAN_LFR + +#ifdef FEATURE_WLAN_LFR_METRICS +/* + * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth + * 802.11r/LFR metrics reporting function to report preauth initiation + * + */ +#define MAX_LFR_METRICS_EVENT_LENGTH 100 +VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo) +{ + unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1]; + union iwreq_data wrqu; + + ENTER(); + + if (NULL == pAdapter) + { + hddLog(LOGE, "%s: pAdapter is NULL!", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* create the event */ + memset(&wrqu, 0, sizeof(wrqu)); + memset(metrics_notification, 0, sizeof(metrics_notification)); + + wrqu.data.pointer = metrics_notification; + wrqu.data.length = scnprintf(metrics_notification, + sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT " + MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid)); + + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification); + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status + * 802.11r/LFR metrics reporting function to report preauth completion + * or failure + */ +VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status( + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status) +{ + unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1]; + union iwreq_data wrqu; + + ENTER(); + + if (NULL == pAdapter) + { + hddLog(LOGE, "%s: pAdapter is NULL!", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* create the event */ + memset(&wrqu, 0, sizeof(wrqu)); + memset(metrics_notification, 0, sizeof(metrics_notification)); + + scnprintf(metrics_notification, sizeof(metrics_notification), + "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pRoamInfo->bssid)); + + if (1 == preauth_status) + strncat(metrics_notification, " TRUE", 5); + else + strncat(metrics_notification, " FALSE", 6); + + wrqu.data.pointer = metrics_notification; + wrqu.data.length = strlen(metrics_notification); + + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification); + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover + * 802.11r/LFR metrics reporting function to report handover initiation + * + */ +VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter, + tCsrRoamInfo *pRoamInfo) +{ + unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1]; + union iwreq_data wrqu; + + ENTER(); + + if (NULL == pAdapter) + { + hddLog(LOGE, "%s: pAdapter is NULL!", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* create the event */ + memset(&wrqu, 0, sizeof(wrqu)); + memset(metrics_notification, 0, sizeof(metrics_notification)); + + wrqu.data.pointer = metrics_notification; + wrqu.data.length = scnprintf(metrics_notification, + sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER " + MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid)); + + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification); + + EXIT(); + + return VOS_STATUS_SUCCESS; +} +#endif + +/* + * FUNCTION: hdd_cfg80211_scan_done_callback + * scanning callback function, called after finishing scan + * + */ +static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, + void *pContext, + tANI_U8 sessionId, + tANI_U32 scanId, + eCsrScanStatus status) +{ + struct net_device *dev = (struct net_device *) pContext; + //struct wireless_dev *wdev = dev->ieee80211_ptr; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info; + struct cfg80211_scan_request *req = NULL; + hdd_context_t *pHddCtx = NULL; + bool aborted = false; + unsigned long rc; + int ret = 0; + + ENTER(); + + if (!pAdapter || pAdapter->magic != WLAN_HDD_ADAPTER_MAGIC) { + hddLog(LOGE, FL("pAdapter is not valid!")); + return eHAL_STATUS_FAILURE; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (!pHddCtx) { + hddLog(LOGE, FL("HDD context is not valid!")); + return eHAL_STATUS_FAILURE; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s called with halHandle = %p, pContext = %p," + "scanID = %d, returned status = %d", + __func__, halHandle, pContext, (int) scanId, (int) status); + + pScanInfo->mScanPendingCounter = 0; + + //Block on scan req completion variable. Can't wait forever though. + rc = wait_for_completion_timeout( + &pScanInfo->scan_req_completion_event, + msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s wait on scan_req_completion_event timed out", __func__); + VOS_ASSERT(pScanInfo->mScanPending); + goto allow_suspend; + } + + if (pScanInfo->mScanPending != VOS_TRUE) + { + VOS_ASSERT(pScanInfo->mScanPending); + goto allow_suspend; + } + + /* Check the scanId */ + if (pScanInfo->scanId != scanId) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s called with mismatched scanId pScanInfo->scanId = %d " + "scanId = %d", __func__, (int) pScanInfo->scanId, + (int) scanId); + } + + ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, + pAdapter); + + if (0 > ret) + hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + + + /* If any client wait scan result through WEXT + * send scan done event to client */ + if (pAdapter->scan_info.waitScanResult) + { + /* The other scan request waiting for current scan finish + * Send event to notify current scan finished */ + if(WEXT_SCAN_PENDING_DELAY == pAdapter->scan_info.scan_pending_option) + { + vos_event_set(&pAdapter->scan_info.scan_finished_event); + } + /* Send notify to WEXT client */ + else if(WEXT_SCAN_PENDING_PIGGYBACK == pAdapter->scan_info.scan_pending_option) + { + struct net_device *dev = pAdapter->dev; + union iwreq_data wrqu; + int we_event; + char *msg; + + memset(&wrqu, '\0', sizeof(wrqu)); + we_event = SIOCGIWSCAN; + msg = NULL; + wireless_send_event(dev, we_event, &wrqu, msg); + } + } + pAdapter->scan_info.waitScanResult = FALSE; + + /* Get the Scan Req */ + req = pAdapter->request; + pAdapter->request = NULL; + + if (!req || req->wiphy == NULL) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL"); + pScanInfo->mScanPending = VOS_FALSE; + complete(&pScanInfo->abortscan_event_var); + goto allow_suspend; + } + + /* Scan is no longer pending */ + pScanInfo->mScanPending = VOS_FALSE; + + /* + * cfg80211_scan_done informing NL80211 about completion + * of scanning + */ + if (status == eCSR_SCAN_ABORT || status == eCSR_SCAN_FAILURE) + { + aborted = true; + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + if (pAdapter->dev->flags & IFF_UP) +#endif + cfg80211_scan_done(req, aborted); + + complete(&pScanInfo->abortscan_event_var); + +allow_suspend: + + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.scan); + /* release the wake lock at the end of the scan*/ + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN); + /* Acquire wakelock to handle the case where APP's tries to suspend + * immediately after the driver gets connect request(i.e after scan) + * from supplicant, this result in app's is suspending and not able + * to process the connect request to AP */ + hdd_prevent_suspend_timeout(1000, WIFI_POWER_EVENT_WAKELOCK_SCAN); + +#ifdef FEATURE_WLAN_TDLS + if (!(eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)) + { + wlan_hdd_tdls_scan_done_callback(pAdapter); + } +#endif + + EXIT(); + return 0; +} + +/* + * hdd_isConnectionInProgress() - HDD function to check connection in progress + * @pHddCtx - HDD context + * @is_roc - roc + * + * Go through each adapter and check if Connection is in progress + * + * Return: true if connection in progress; false otherwise. + */ +bool hdd_isConnectionInProgress(hdd_context_t *pHddCtx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + hdd_adapter_t *pAdapter = NULL; + VOS_STATUS status = 0; + v_U8_t staId = 0; + v_U8_t *staMac = NULL; + + if (TRUE == pHddCtx->btCoexModeSet) { + hddLog(LOG1, FL("BTCoex Mode operation in progress")); + return true; + } + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + + if (pAdapter) { + hddLog(LOG1, FL("Adapter with device mode %s(%d) exists"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + if (((WLAN_HDD_INFRA_STATION == + pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == + pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == + pAdapter->device_mode)) && + (eConnectionState_Connecting == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))-> + conn_info.connState)) { + hddLog(LOGE, + FL("%p(%d) Connection is in progress"), + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), + pAdapter->sessionId); + return true; + } + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + smeNeighborMiddleOfRoaming( + WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: %p(%d) Reassociation is in progress", __func__, + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId); + return VOS_TRUE; + } + if ((WLAN_HDD_INFRA_STATION == + pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == + pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == + pAdapter->device_mode)) { + pHddStaCtx = + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if ((eConnectionState_Associated == + pHddStaCtx->conn_info.connState) && + (VOS_FALSE == + pHddStaCtx->conn_info. + uIsAuthenticated)) { + staMac = (v_U8_t *) &(pAdapter-> + macAddressCurrent.bytes[0]); + hddLog(LOGE, + FL("client " MAC_ADDRESS_STR " is in the middle of WPS/EAPOL exchange."), + MAC_ADDR_ARRAY(staMac)); + return true; + } + } else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { + for (staId = 0; staId < WLAN_MAX_STA_COUNT; + staId++) { + if ((pAdapter->aStaInfo[staId]. + isUsed) && + (WLANTL_STA_CONNECTED == + pAdapter->aStaInfo[staId]. + tlSTAState)) { + staMac = (v_U8_t *) &(pAdapter-> + aStaInfo[staId]. + macAddrSTA.bytes[0]); + + hddLog(LOGE, + FL("client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the " + "middle of WPS/EAPOL exchange."), + MAC_ADDR_ARRAY(staMac)); + return true; + } + } + } + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + return false; +} + +static void wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work) +{ + hdd_adapter_t *adapter = container_of(work, + hdd_adapter_t, scan_block_work); + struct cfg80211_scan_request *request = NULL; + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter context is invalid", __func__); + return; + } + + request = adapter->request; + if (request) { + request->n_ssids = 0; + request->n_channels = 0; + + hddLog(LOGE, + "%s:##In DFS Master mode. Scan aborted. Null result sent", + __func__); + cfg80211_scan_done(request, true); + adapter->request = NULL; + } +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_scan + * this scan respond to scan trigger and update cfg80211 scan database + * later, scan dump command can be used to receive scan results + */ +int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct net_device *dev = request->wdev->netdev; +#endif + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_config_t *cfg_param = NULL; + tCsrScanRequest scanRequest; + tANI_U8 *channelList = NULL, i; + v_U32_t scanId = 0; + int status; + hdd_scaninfo_t *pScanInfo = NULL; + v_U8_t* pP2pIe = NULL; + hdd_adapter_t *con_sap_adapter; + uint16_t con_dfs_ch; + bool is_p2p_scan = false; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SCAN, + pAdapter->sessionId, request->n_channels)); + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + cfg_param = pHddCtx->cfg_ini; + pScanInfo = &pAdapter->scan_info; + + /* Block All Scan during DFS operation and send null scan result */ + con_sap_adapter = hdd_get_con_sap_adapter(pAdapter, true); + if (con_sap_adapter) { + con_dfs_ch = con_sap_adapter->sessionCtx.ap.operatingChannel; + + if (VOS_IS_DFS_CH(con_dfs_ch)) { + /* Provide empty scan result during DFS operation since scanning + * not supported during DFS. Reason is following case: + * DFS is supported only in SCC for MBSSID Mode. + * We shall not return EBUSY or ENOTSUPP as when Primary AP is + * operating in DFS channel and secondary AP is started. Though we + * force SCC in driver, the hostapd issues obss scan before + * starting secAP. This results in MCC in DFS mode. + * Thus we return null scan result. If we return scan failure + * hostapd fails secondary AP startup. + */ + pAdapter->request = request; + +#ifdef CONFIG_CNSS + cnss_init_work(&pAdapter->scan_block_work, + wlan_hdd_cfg80211_scan_block_cb); +#else + INIT_WORK(&pAdapter->scan_block_work, + wlan_hdd_cfg80211_scan_block_cb); +#endif + + schedule_work(&pAdapter->scan_block_work); + return 0; + } + } + + if (TRUE == pScanInfo->mScanPending) + { + if ( MAX_PENDING_LOG > pScanInfo->mScanPendingCounter++ ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mScanPending is TRUE", __func__); + } + return -EBUSY; + } + + //Don't Allow Scan and return busy if Remain On + //Channel and action frame is pending + //Otherwise Cancel Remain On Channel and allow Scan + //If no action frame pending + if (0 != wlan_hdd_check_remain_on_channel(pAdapter)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Remain On Channel Pending", __func__); + return -EBUSY; + } +#ifdef FEATURE_WLAN_TDLS + /* if tdls disagree scan right now, return immediately. + tdls will schedule the scan when scan is allowed. (return SUCCESS) + or will reject the scan if any TDLS is in progress. (return -EBUSY) + */ + status = wlan_hdd_tdls_scan_callback (pAdapter, + wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + dev, +#endif + request); + if (status <= 0) + { + if (!status) + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS in progress.scan rejected %d", + __func__, status); + else + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS teardown is ongoing %d", + __func__, status); + + return status; + } +#endif + + if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, + "%s: Acquire lock fail", __func__); + return -EAGAIN; + } + if (TRUE == pHddCtx->tmInfo.tmAction.enterImps) + { + mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: MAX TM Level Scan not allowed", __func__); + return -EBUSY; + } + mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); + + /* Check if scan is allowed at this point of time. + */ + if (hdd_isConnectionInProgress(pHddCtx)) { + hddLog(LOGE, FL("Scan not allowed")); + return -EBUSY; + } + + vos_mem_zero( &scanRequest, sizeof(scanRequest)); + + /* Even though supplicant doesn't provide any SSIDs, n_ssids is + * set to 1. Because of this, driver is assuming that this is not + * wildcard scan and so is not aging out the scan results. + */ + if ((request->ssids) && (request->n_ssids == 1) && + ('\0' == request->ssids->ssid[0])) + { + request->n_ssids = 0; + } + + if ((request->ssids) && (0 < request->n_ssids)) + { + tCsrSSIDInfo *SsidInfo; + int j; + scanRequest.SSIDs.numOfSSIDs = request->n_ssids; + /* Allocate num_ssid tCsrSSIDInfo structure */ + SsidInfo = scanRequest.SSIDs.SSIDList = + vos_mem_malloc(request->n_ssids * sizeof(tCsrSSIDInfo)); + + if (NULL == scanRequest.SSIDs.SSIDList) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: memory alloc failed SSIDInfo buffer", __func__); + return -ENOMEM; + } + + /* copy all the ssid's and their length */ + for (j = 0; j < request->n_ssids; j++, SsidInfo++) + { + /* get the ssid length */ + SsidInfo->SSID.length = request->ssids[j].ssid_len; + vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0], + SsidInfo->SSID.length); + SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0'; + hddLog(VOS_TRACE_LEVEL_INFO, "SSID number %d: %s", + j, SsidInfo->SSID.ssId); + } + /* set the scan type to active */ + scanRequest.scanType = eSIR_ACTIVE_SCAN; + } + else if (WLAN_HDD_P2P_GO == pAdapter->device_mode) + { + /* set the scan type to active */ + scanRequest.scanType = eSIR_ACTIVE_SCAN; + } + else + { + /* + *Set the scan type to passive if there is no ssid list provided else + *set default type configured in the driver. + */ + if (!request->ssids) + scanRequest.scanType = eSIR_PASSIVE_SCAN; + else + scanRequest.scanType = pHddCtx->ioctl_scan_mode; + } + scanRequest.minChnTime = cfg_param->nActiveMinChnTime; + scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime; + + /* set BSSType to default type */ + scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + + if (MAX_CHANNEL < request->n_channels) + { + hddLog(VOS_TRACE_LEVEL_WARN, "No of Scan Channels exceeded limit: %d", + request->n_channels); + request->n_channels = MAX_CHANNEL; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "No of Scan Channels: %d", request->n_channels); + + if (request->n_channels) + { + char chList [(request->n_channels*5)+1]; + int len; + channelList = vos_mem_malloc(request->n_channels); + if (NULL == channelList) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "channelList memory alloc failed channelList"); + status = -ENOMEM; + goto free_mem; + } + for (i = 0, len = 0; i < request->n_channels ; i++ ) + { + channelList[i] = request->channels[i]->hw_value; + len += snprintf(chList+len, 5, "%d ", channelList[i]); + } + + hddLog(VOS_TRACE_LEVEL_INFO, "Channel-List: %s", chList); + + } + scanRequest.ChannelInfo.numOfChannels = request->n_channels; + scanRequest.ChannelInfo.ChannelList = channelList; + + /* set requestType to full scan */ + scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + + /* Flush the scan results(only p2p beacons) for STA scan and P2P + * search (Flush on both full scan and social scan but not on single + * channel scan).P2P search happens on 3 social channels (1, 6, 11) + */ + + /* Supplicant does single channel scan after 8-way handshake + * and in that case driver shouldn't flush scan results. If + * driver flushes the scan results here and unfortunately if + * the AP doesn't respond to our probe req then association + * fails which is not desired + */ + + if ((request->n_ssids == 1) + && (request->ssids != NULL) + && vos_mem_compare(&request->ssids[0], "DIRECT-", 7)) + is_p2p_scan = true; + + if (is_p2p_scan || + (request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN)) + { + hddLog(VOS_TRACE_LEVEL_DEBUG, "Flushing P2P Results"); + sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId ); + } + + if (request->ie_len) + { + /* save this for future association (join requires this) */ + memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) ); + memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len); + pScanInfo->scanAddIE.length = request->ie_len; + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) + ) + { + pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata; + pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length; + } + + scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length; + scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata; + + pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie, + request->ie_len); + if (pP2pIe != NULL) + { +#ifdef WLAN_FEATURE_P2P_DEBUG + if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) || + (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) && + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1; + hddLog(VOS_TRACE_LEVEL_ERROR, + "[P2P State] Changing state from Go nego completed to Connection is started"); + hddLog(VOS_TRACE_LEVEL_ERROR, + "[P2P]P2P Scanning is started for 8way Handshake"); + } + else if ((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) && + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2; + hddLog(VOS_TRACE_LEVEL_ERROR, + "[P2P State] Changing state from Disconnected state to Connection is started"); + hddLog(VOS_TRACE_LEVEL_ERROR, + "[P2P]P2P Scanning is started for 4way Handshake"); + } +#endif + + /* no_cck will be set during p2p find to disable 11b rates */ + if (request->no_cck) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: This is a P2P Search", __func__); + scanRequest.p2pSearch = 1; + + if (request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS) + { + /* set requestType to P2P Discovery */ + scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY; + } + + /* + * Skip Dfs Channel in case of P2P Search if it is set in + * ini file + */ + if (cfg_param->skipDfsChnlInP2pSearch) + { + scanRequest.skipDfsChnlInP2pSearch = 1; + } + else + { + scanRequest.skipDfsChnlInP2pSearch = 0; + } + + } + } + } + + INIT_COMPLETION(pScanInfo->scan_req_completion_event); + + /* acquire the wakelock to avoid the apps suspend during the scan. To + * address the following issues. + * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in + * BMPS/IMPS this result in android trying to suspend aggressively and backing off + * for long time, this result in apps running at full power for long time. + * 2) Connected scenario: If we allow the suspend during the scan, RIVA will + * be stuck in full power because of resume BMPS + */ + hdd_prevent_suspend_timeout(HDD_WAKE_LOCK_SCAN_DURATION, + WIFI_POWER_EVENT_WAKELOCK_SCAN); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "requestType %d, scanType %d, minChnTime %d, maxChnTime %d,p2pSearch %d, skipDfsChnlIn P2pSearch %d", + scanRequest.requestType, scanRequest.scanType, + scanRequest.minChnTime, scanRequest.maxChnTime, + scanRequest.p2pSearch, scanRequest.skipDfsChnlInP2pSearch); + + vos_runtime_pm_prevent_suspend(pHddCtx->runtime_context.scan); + status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &scanRequest, &scanId, + &hdd_cfg80211_scan_done_callback, dev ); + + if (eHAL_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_ScanRequest returned error %d", __func__, status); + complete(&pScanInfo->scan_req_completion_event); + if(eHAL_STATUS_RESOURCES == status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HO is in progress.So defer the scan by informing busy", + __func__); + status = -EBUSY; + } + else + { + status = -EIO; + } + + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.scan); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN); + goto free_mem; + } + + pScanInfo->mScanPending = TRUE; + pAdapter->request = request; + pScanInfo->scanId = scanId; + + complete(&pScanInfo->scan_req_completion_event); + +free_mem: + if( scanRequest.SSIDs.SSIDList ) + { + vos_mem_free(scanRequest.SSIDs.SSIDList); + } + + if( channelList ) + vos_mem_free( channelList ); + + EXIT(); + return status; +} + +int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_scan(wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + dev, +#endif + request); + vos_ssr_unprotect(__func__); + + return ret; +} + +void hdd_select_cbmode(hdd_adapter_t *pAdapter, v_U8_t operationChannel, + uint16_t *vht_channel_width) +{ + v_U8_t iniDot11Mode = + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode; + eHddDot11Mode hddDot11Mode = iniDot11Mode; + hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), + iniDot11Mode); + *vht_channel_width = + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->vhtChannelWidth; + switch ( iniDot11Mode ) + { + case eHDD_DOT11_MODE_AUTO: + case eHDD_DOT11_MODE_11ac: + case eHDD_DOT11_MODE_11ac_ONLY: +#ifdef WLAN_FEATURE_11AC + if (sme_IsFeatureSupportedByFW(DOT11AC)) + hddDot11Mode = eHDD_DOT11_MODE_11ac; + else + hddDot11Mode = eHDD_DOT11_MODE_11n; +#else + hddDot11Mode = eHDD_DOT11_MODE_11n; +#endif + break; + case eHDD_DOT11_MODE_11n: + case eHDD_DOT11_MODE_11n_ONLY: + hddDot11Mode = eHDD_DOT11_MODE_11n; + break; + default: + hddDot11Mode = iniDot11Mode; + break; + } + /* This call decides required channel bonding mode */ + sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal), + hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode), + operationChannel, 0, + vht_channel_width, + *vht_channel_width); +} + +/** + * wlan_hdd_sta_sap_concur_handle() - This function will handle Station and sap + * concurrency. + * @hdd_ctx: pointer to hdd context. + * @sta_adapter: pointer to station adapter. + * @roam_profile: pointer to station's roam profile. + * + * This function will find the AP to which station is likely to make the + * the connection, if that AP's channel happens to be different than + * SAP's channel then this function will stop the SAP. + * + * Return: true or false based on function's overall success. + */ +static bool wlan_hdd_sta_sap_concur_handle(hdd_context_t *hdd_ctx, + hdd_adapter_t *sta_adapter, + tCsrRoamProfile *roam_profile) +{ + hdd_adapter_t *ap_adapter = hdd_get_adapter(hdd_ctx, + WLAN_HDD_SOFTAP); + bool are_cc_channels_same = false; + tScanResultHandle scan_cache = NULL; + VOS_STATUS status; + + if ((ap_adapter != NULL) && + test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { + status = + wlan_hdd_check_custom_con_channel_rules(sta_adapter, ap_adapter, + roam_profile, &scan_cache, + &are_cc_channels_same); + sme_ScanResultPurge(WLAN_HDD_GET_HAL_CTX(sta_adapter), + scan_cache); + /* + * are_cc_channels_same will be false incase if SAP and STA + * channel is different or STA channel is zero. + * incase if STA channel is zero then lets stop the AP and + * restart flag set, so later whenever STA channel is defined + * we can restart our SAP in that channel. + */ + if (false == are_cc_channels_same) { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("Stop AP due to mismatch with STA channel")); + wlan_hdd_stop_sap(ap_adapter); + hdd_change_sap_restart_required_status(hdd_ctx, true); + return false; + } else { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("sap channels are same")); + } + } + return true; +} + +#ifdef FEATURE_WLAN_CH_AVOID +/** + * wlan_hdd_sta_p2pgo_concur_handle() - This function will handle Station and GO + * concurrency. + * @hdd_ctx: pointer to hdd context. + * @sta_adapter: pointer to station adapter. + * @roam_profile: pointer to station's roam profile. + * @roam_id: reference to roam_id variable being passed. + * + * This function will find the AP to which station is likely to make the + * the connection, if that AP's channel happens to be different than our + * P2PGO's channel then this function will send avoid frequency event to + * framework to make P2PGO stop and also caches station's connect request. + * + * Return: true or false based on function's overall success. + */ +static bool wlan_hdd_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, + hdd_adapter_t *sta_adapter, + tCsrRoamProfile *roam_profile, + uint32_t *roam_id) +{ + hdd_adapter_t *p2pgo_adapter = hdd_get_adapter(hdd_ctx, + WLAN_HDD_P2P_GO); + bool are_cc_channels_same = false; + tScanResultHandle scan_cache = NULL; + uint32_t p2pgo_channel_num, freq; + tHddAvoidFreqList hdd_avoid_freq_list; + VOS_STATUS status; + + if ((p2pgo_adapter != NULL) && + test_bit(SOFTAP_BSS_STARTED, &p2pgo_adapter->event_flags)) { + status = + wlan_hdd_check_custom_con_channel_rules(sta_adapter, p2pgo_adapter, + roam_profile, &scan_cache, + &are_cc_channels_same); + /* + * are_cc_channels_same will be false incase if P2PGO and STA + * channel is different or STA channel is zero. + */ + if (false == are_cc_channels_same) { + if (true == hdd_is_sta_connection_pending(hdd_ctx)) { + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CLEAR_JOIN_REQ, + sta_adapter->sessionId, *roam_id)); + sme_clear_joinreq_param(WLAN_HDD_GET_HAL_CTX(sta_adapter), + sta_adapter->sessionId); + hdd_change_sta_conn_pending_status(hdd_ctx, false); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("===>Clear pending join req")); + } + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_STORE_JOIN_REQ, + sta_adapter->sessionId, *roam_id)); + /* store the scan cache here */ + sme_store_joinreq_param(WLAN_HDD_GET_HAL_CTX(sta_adapter), + roam_profile, + scan_cache, + roam_id, + sta_adapter->sessionId); + hdd_change_sta_conn_pending_status(hdd_ctx, true); + /* + * fill frequency avoidance event and send it up + * so, p2pgo stop event should get trigger from upper layer + */ + p2pgo_channel_num = + WLAN_HDD_GET_AP_CTX_PTR(p2pgo_adapter)->operatingChannel; + if (p2pgo_channel_num <= ARRAY_SIZE(hdd_channels_2_4_GHZ)) { + freq = ieee80211_channel_to_frequency(p2pgo_channel_num, + IEEE80211_BAND_2GHZ); + } else { + freq = ieee80211_channel_to_frequency(p2pgo_channel_num, + IEEE80211_BAND_5GHZ); + } + vos_mem_zero(&hdd_avoid_freq_list, + sizeof(hdd_avoid_freq_list)); + hdd_avoid_freq_list.avoidFreqRangeCount = 1; + hdd_avoid_freq_list.avoidFreqRange[0].startFreq = freq; + hdd_avoid_freq_list.avoidFreqRange[0].endFreq = freq; + wlan_hdd_send_avoid_freq_event(hdd_ctx, + &hdd_avoid_freq_list); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("===>Sending chnl_avoid ch[%d] freq[%d]"), + p2pgo_channel_num, freq); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("===>Stop GO due to mismatch with STA channel")); + return false; + } else { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("===>p2pgo channels are same")); + sme_ScanResultPurge(WLAN_HDD_GET_HAL_CTX(sta_adapter), + scan_cache); + } + } + return true; +} +#endif + +/* + * Time in msec + * Time for complete association including DHCP + */ +#define WLAN_HDD_CONNECTION_TIME (30 * 1000) + +/* + * FUNCTION: wlan_hdd_cfg80211_connect_start + * This function is used to start the association process + */ +int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, + const u8 *ssid, size_t ssid_len, const u8 *bssid, + const u8 *bssid_hint, u8 operatingChannel) +{ + int status = 0; + hdd_wext_state_t *pWextState; + hdd_context_t *pHddCtx; + v_U32_t roamId; + tCsrRoamProfile *pRoamProfile; + eCsrAuthType RSNAuthType; + uint16_t ch_width; + + ENTER(); + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + status = wlan_hdd_validate_context(pHddCtx); + if (status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__); + return -EINVAL; + } + + pRoamProfile = &pWextState->roamProfile; + + if (pRoamProfile) + { + hdd_station_ctx_t *pHddStaCtx; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (HDD_WMM_USER_MODE_NO_QOS == + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode) + { + /*QoS not enabled in cfg file*/ + pRoamProfile->uapsd_mask = 0; + } + else + { + /*QoS enabled, update uapsd mask from cfg file*/ + pRoamProfile->uapsd_mask = + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask; + } + + pRoamProfile->SSIDs.numOfSSIDs = 1; + pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len; + vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId, + sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId)); + vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId), + ssid, ssid_len); + + if (bssid) + { + pRoamProfile->BSSIDs.numOfBSSIDs = 1; + vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid, + VOS_MAC_ADDR_SIZE); + /* Save BSSID in separate variable as well, as RoamProfile + BSSID is getting zeroed out in the association process. And in + case of join failure we should send valid BSSID to supplicant + */ + vos_mem_copy((void *)(pWextState->req_bssId), bssid, + VOS_MAC_ADDR_SIZE); + } + else if (bssid_hint) + { + pRoamProfile->BSSIDs.numOfBSSIDs = 1; + vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid_hint, + VOS_MAC_ADDR_SIZE); + /* Save BSSID in separate variable as well, as RoamProfile + BSSID is getting zeroed out in the association process. And in + case of join failure we should send valid BSSID to supplicant + */ + vos_mem_copy((void *)(pWextState->req_bssId), bssid_hint, + VOS_MAC_ADDR_SIZE); + hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(bssid_hint)); + + } + else + { + vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid), VOS_MAC_ADDR_SIZE); + } + + hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"), + pRoamProfile->SSIDs.SSIDList->SSID.length, + pRoamProfile->SSIDs.SSIDList->SSID.ssId, + operatingChannel); + + if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) || + (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) + { + /*set gen ie*/ + hdd_SetGENIEToCsr(pAdapter, &RSNAuthType); + /*set auth*/ + hdd_set_csr_auth_type(pAdapter, RSNAuthType); + } +#ifdef FEATURE_WLAN_WAPI + if (pAdapter->wapi_info.nWapiMode) + { + hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__); + switch (pAdapter->wapi_info.wapiAuthMode) + { + case WAPI_AUTH_MODE_PSK: + { + hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__, + pAdapter->wapi_info.wapiAuthMode); + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK; + break; + } + case WAPI_AUTH_MODE_CERT: + { + hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__, + pAdapter->wapi_info.wapiAuthMode); + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE; + break; + } + } // End of switch + if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK || + pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT) + { + hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__); + pRoamProfile->AuthType.numEntries = 1; + pRoamProfile->EncryptionType.numEntries = 1; + pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI; + pRoamProfile->mcEncryptionType.numEntries = 1; + pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI; + } + } +#endif /* FEATURE_WLAN_WAPI */ +#ifdef WLAN_FEATURE_GTK_OFFLOAD + /* Initializing gtkOffloadReqParams */ + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + memset(&pHddStaCtx->gtkOffloadReqParams, 0, + sizeof (tSirGtkOffloadParams)); + pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE; + } +#endif + pRoamProfile->csrPersona = pAdapter->device_mode; + + if( operatingChannel ) + { + pRoamProfile->ChannelInfo.ChannelList = &operatingChannel; + pRoamProfile->ChannelInfo.numOfChannels = 1; + } + else + { + pRoamProfile->ChannelInfo.ChannelList = NULL; + pRoamProfile->ChannelInfo.numOfChannels = 0; + } + + if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel) + { + /* + * Need to post the IBSS power save parameters + * to WMA. WMA will configure this parameters + * to firmware if power save is enabled by the + * firmware. + */ + status = hdd_setIbssPowerSaveParams(pAdapter); + + if (VOS_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Set IBSS Power Save Params Failed", __func__); + return -EINVAL; + } + hdd_select_cbmode(pAdapter,operatingChannel, &ch_width); + pRoamProfile->vht_channel_width = ch_width; + } + + /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect() + * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state + * If direct path, conn_state will be accordingly changed to NotConnected or Associated + * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback() + * if sme_RomConnect is to be queued, Connecting state will remain until it is completed. + */ + if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_Connecting", + __func__); + hdd_connSetConnectionState(pAdapter, + eConnectionState_Connecting); + } + + /* After 8-way handshake supplicant should give the scan command + * in that it update the additional IEs, But because of scan + * enhancements, the supplicant is not issuing the scan command now. + * So the unicast frames which are sent from the host are not having + * the additional IEs. If it is P2P CLIENT and there is no additional + * IE present in roamProfile, then use the additional IE form scan_info + */ + + if ((pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) && + (!pRoamProfile->pAddIEScan)) + { + pRoamProfile->pAddIEScan = &pAdapter->scan_info.scanAddIE.addIEdata[0]; + pRoamProfile->nAddIEScanLength = pAdapter->scan_info.scanAddIE.length; + } + /* + * Custom concurrency rule1: As per this rule if station is trying to + * connect to some AP in 2.4Ghz and SAP is already in started state then + * SAP should restart in station's channel. + */ + if (pHddCtx->cfg_ini->conc_custom_rule1 && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)) { + + wlan_hdd_sta_sap_concur_handle (pHddCtx, pAdapter, pRoamProfile); + } +#ifdef FEATURE_WLAN_CH_AVOID + /* + * Custom concurrency rule2: As per this rule if station is trying to + * connect to some AP in 5Ghz and P2PGO is already in started state then + * P2PGO should restart in station's channel. + */ + if (pHddCtx->cfg_ini->conc_custom_rule2 && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)) { + if (false == + wlan_hdd_sta_p2pgo_concur_handle(pHddCtx, pAdapter, + pRoamProfile, &roamId)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("P2PGO - STA chnl diff, cached join req")); + return 0; + } + } +#endif + + vos_runtime_pm_prevent_suspend(pAdapter->runtime_context.connect); + + status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, pRoamProfile, &roamId); + + if ((eHAL_STATUS_SUCCESS != status) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with " + "status %d. -> NotConnected", __func__, pAdapter->sessionId, status); + /* change back to NotAssociated */ + hdd_connSetConnectionState(pAdapter, + eConnectionState_NotConnected); + vos_runtime_pm_allow_suspend(pAdapter->runtime_context.connect); + } + + pRoamProfile->ChannelInfo.ChannelList = NULL; + pRoamProfile->ChannelInfo.numOfChannels = 0; + + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__); + return -EINVAL; + } + EXIT(); + return status; +} + +/* + * FUNCTION: wlan_hdd_set_cfg80211_auth_type + * This function is used to set the authentication type (OPEN/SHARED). + * + */ +static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, + enum nl80211_auth_type auth_type) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + ENTER(); + + /*set authentication type*/ + switch (auth_type) + { + case NL80211_AUTHTYPE_AUTOMATIC: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set authentication type to AUTOSWITCH", __func__); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH; + break; + + case NL80211_AUTHTYPE_OPEN_SYSTEM: +#ifdef WLAN_FEATURE_VOWIFI_11R + case NL80211_AUTHTYPE_FT: +#endif /* WLAN_FEATURE_VOWIFI_11R */ + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set authentication type to OPEN", __func__); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + break; + + case NL80211_AUTHTYPE_SHARED_KEY: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set authentication type to SHARED", __func__); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY; + break; +#ifdef FEATURE_WLAN_ESE + case NL80211_AUTHTYPE_NETWORK_EAP: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set authentication type to CCKM WPA", __func__); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required. + break; +#endif + + + default: + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unsupported authentication type %d", __func__, + auth_type); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN; + return -EINVAL; + } + + pWextState->roamProfile.AuthType.authType[0] = + pHddStaCtx->conn_info.authType; + return 0; +} + +/* + * FUNCTION: wlan_hdd_set_akm_suite + * This function is used to set the key mgmt type(PSK/8021x). + * + */ +static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, + u32 key_mgmt + ) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + ENTER(); + /* Should be in ieee802_11_defs.h */ +#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 +#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 + /*set key mgmt type*/ + switch(key_mgmt) + { + case WLAN_AKM_SUITE_PSK: + case WLAN_AKM_SUITE_PSK_SHA256: +#ifdef WLAN_FEATURE_VOWIFI_11R + case WLAN_AKM_SUITE_FT_PSK: +#endif + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK", + __func__); + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK; + break; + + case WLAN_AKM_SUITE_8021X_SHA256: + case WLAN_AKM_SUITE_8021X: +#ifdef WLAN_FEATURE_VOWIFI_11R + case WLAN_AKM_SUITE_FT_8021X: +#endif + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x", + __func__); + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X; + break; +#ifdef FEATURE_WLAN_ESE +#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */ +#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */ + case WLAN_AKM_SUITE_CCKM: + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM", + __func__); + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM; + break; +#endif +#ifndef WLAN_AKM_SUITE_OSEN +#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */ +#endif + case WLAN_AKM_SUITE_OSEN: + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to OSEN", + __func__); + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X; + break; + + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d", + __func__, key_mgmt); + return -EINVAL; + + } + return 0; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_set_cipher + * This function is used to set the encryption type + * (NONE/WEP40/WEP104/TKIP/CCMP). + */ +static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, + u32 cipher, + bool ucast + ) +{ + eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + ENTER(); + + if (!cipher) { + hddLog(LOG1, FL("received cipher %d - considering none"), cipher); + encryptionType = eCSR_ENCRYPT_TYPE_NONE; + } else { + + /*set encryption method*/ + switch (cipher) + { + case IW_AUTH_CIPHER_NONE: + encryptionType = eCSR_ENCRYPT_TYPE_NONE; + break; + + case WLAN_CIPHER_SUITE_WEP40: + encryptionType = eCSR_ENCRYPT_TYPE_WEP40; + break; + + case WLAN_CIPHER_SUITE_WEP104: + encryptionType = eCSR_ENCRYPT_TYPE_WEP104; + break; + + case WLAN_CIPHER_SUITE_TKIP: + encryptionType = eCSR_ENCRYPT_TYPE_TKIP; + break; + + case WLAN_CIPHER_SUITE_CCMP: + encryptionType = eCSR_ENCRYPT_TYPE_AES; + break; +#ifdef FEATURE_WLAN_WAPI + case WLAN_CIPHER_SUITE_SMS4: + encryptionType = eCSR_ENCRYPT_TYPE_WPI; + break; +#endif + +#ifdef FEATURE_WLAN_ESE + case WLAN_CIPHER_SUITE_KRK: + encryptionType = eCSR_ENCRYPT_TYPE_KRK; + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WLAN_CIPHER_SUITE_BTK: + encryptionType = eCSR_ENCRYPT_TYPE_BTK; + break; +#endif +#endif + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d", + __func__, cipher); + return -EOPNOTSUPP; + } + } + + if (ucast) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d", + __func__, encryptionType); + pHddStaCtx->conn_info.ucEncryptionType = encryptionType; + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.EncryptionType.encryptionType[0] = + encryptionType; + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d", + __func__, encryptionType); + pHddStaCtx->conn_info.mcEncryptionType = encryptionType; + pWextState->roamProfile.mcEncryptionType.numEntries = 1; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType; + } + + return 0; +} + + +/* + * FUNCTION: wlan_hdd_cfg80211_set_ie + * This function is used to parse WPA/RSN IE's. + */ +int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, + const u8 *ie, + size_t ie_len) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + const u8 *genie = ie; + v_U16_t remLen = ie_len; +#ifdef FEATURE_WLAN_WAPI + v_U32_t akmsuite[MAX_NUM_AKM_SUITES]; + u16 *tmp; + v_U16_t akmsuiteCount; + int *akmlist; +#endif + ENTER(); + + /* clear previous assocAddIE */ + pWextState->assocAddIE.length = 0; + pWextState->roamProfile.bWPSAssociation = VOS_FALSE; + pWextState->roamProfile.bOSENAssociation = VOS_FALSE; + + while (remLen >= 2) + { + v_U16_t eLen = 0; + v_U8_t elementId; + elementId = *genie++; + eLen = *genie++; + remLen -= 2; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]", + __func__, elementId, eLen); + + switch ( elementId ) + { + case DOT11F_EID_WPA: + if (4 > eLen) /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */ + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid WPA IE", __func__); + return -EINVAL; + } + else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) + { + v_U16_t curAddIELen = pWextState->assocAddIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)", + __func__, eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. " + "Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE + memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.bWPSAssociation = VOS_TRUE; + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + } + else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) + { + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2); + memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); + memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/); + pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE; + pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len; + } + else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE, + P2P_OUI_TYPE_SIZE))) + { + v_U16_t curAddIELen = pWextState->assocAddIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)", + __func__, eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " + "Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE + memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + } +#ifdef WLAN_FEATURE_WFD + else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE, + WFD_OUI_TYPE_SIZE)) + /*Consider WFD IE, only for P2P Client */ + && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ) + { + v_U16_t curAddIELen = pWextState->assocAddIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)", + __func__, eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " + "Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + // WFD IE is saved to Additional IE ; it should be accumulated to handle + // WPS IE + P2P IE + WFD IE + memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + } +#endif + /* Appending HS 2.0 Indication Element in Association Request */ + else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE, + HS20_OUI_TYPE_SIZE)) ) + { + v_U16_t curAddIELen = pWextState->assocAddIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)", + __func__, eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " + "Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + } + /* Appending OSEN Information Element in Association Request */ + else if ( (0 == memcmp(&genie[0], OSEN_OUI_TYPE, + OSEN_OUI_TYPE_SIZE)) ) + { + v_U16_t curAddIELen = pWextState->assocAddIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OSEN IE(len %d)", + __func__, eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " + "Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.bOSENAssociation = VOS_TRUE; + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + } + else + { + uint16_t curAddIELen = pWextState->assocAddIE.length; + if ((pWextState->assocAddIE.length + eLen) > + SIR_MAC_MAX_IE_LENGTH) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "Cannot accommodate assocAddIE Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + + memcpy(pWextState->assocAddIE.addIEdata + curAddIELen, + genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.pAddIEAssoc = + pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = + pWextState->assocAddIE.length; + } + break; + case DOT11F_EID_RSN: + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2); + memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); + memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/); + pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE; + pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len; + break; + /* Appending Extended Capabilities with Interworking or + * bsstransition bit set in Assoc Req. + * + * In assoc req this EXT Cap will only be taken into account if + * interworkingService or bsstransition bit is set to 1. + * Currently driver is only interested in interworkingService + * and bsstransition capability from supplicant. + * If in future any other EXT Cap info is + * required from supplicant, it needs to be handled while + * sending Assoc Req in LIM. + */ + case DOT11F_EID_EXTCAP: + { + v_U16_t curAddIELen = pWextState->assocAddIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)", + __func__, eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " + "Need bigger buffer space"); + VOS_ASSERT(0); + return -ENOMEM; + } + memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; + break; + } +#ifdef FEATURE_WLAN_WAPI + case WLAN_EID_WAPI: + pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1 + hddLog(VOS_TRACE_LEVEL_INFO, "WAPI MODE IS %u", + pAdapter->wapi_info.nWapiMode); + tmp = (u16 *)ie; + tmp = tmp + 2; // Skip element Id and Len, Version + akmsuiteCount = WPA_GET_LE16(tmp); + tmp = tmp + 1; + akmlist = (int *)(tmp); + if(akmsuiteCount <= MAX_NUM_AKM_SUITES) + { + memcpy(akmsuite, akmlist, (4*akmsuiteCount)); + } + else + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count"); + VOS_ASSERT(0); + return -EINVAL; + } + + if (WAPI_PSK_AKM_SUITE == akmsuite[0]) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK", + __func__); + pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK; + } + if (WAPI_CERT_AKM_SUITE == akmsuite[0]) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE", + __func__); + pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT; + } + break; +#endif + default: + hddLog (VOS_TRACE_LEVEL_ERROR, + "%s Set UNKNOWN IE %X", __func__, elementId); + /* when Unknown IE is received we should break and continue + * to the next IE in the buffer instead we were returning + * so changing this to break */ + break; + } + genie += eLen; + remLen -= eLen; + } + EXIT(); + return 0; +} + +/* + * FUNCTION: hdd_isWPAIEPresent + * Parse the received IE to find the WPA IE + * + */ +static bool hdd_isWPAIEPresent(const u8 *ie, u8 ie_len) +{ + v_U8_t eLen = 0; + v_U16_t remLen = ie_len; + v_U8_t elementId = 0; + + while (remLen >= 2) + { + elementId = *ie++; + eLen = *ie++; + remLen -= 2; + if (eLen > remLen) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: IE length is wrong %d", __func__, eLen); + return FALSE; + } + if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) + { + /* OUI - 0x00 0X50 0XF2 + WPA Information Element - 0x01 + WPA version - 0x01*/ + if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5)) + return TRUE; + } + ie += eLen; + remLen -= eLen; + } + return FALSE; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_set_privacy + * This function is used to initialize the security + * parameters during connect operation. + */ +int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter, + struct cfg80211_connect_params *req + ) +{ + int status = 0; + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + ENTER(); + + /*set wpa version*/ + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + + if (req->crypto.wpa_versions) + { + if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) + { + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA; + } + else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) + { + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2; + } + } + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__, + pWextState->wpaVersion); + + /*set authentication type*/ + status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type); + + if (0 > status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to set authentication type ", __func__); + return status; + } + + /*set key mgmt type*/ + if (req->crypto.n_akm_suites) + { + status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]); + if (0 > status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite", + __func__); + return status; + } + } + + /*set pairwise cipher type*/ + if (req->crypto.n_ciphers_pairwise) + { + status = wlan_hdd_cfg80211_set_cipher(pAdapter, + req->crypto.ciphers_pairwise[0], true); + if (0 > status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to set unicast cipher type", __func__); + return status; + } + } + else + { + /*Reset previous cipher suite to none*/ + status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true); + if (0 > status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to set unicast cipher type", __func__); + return status; + } + } + + /*set group cipher type*/ + status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group, + false); + + if (0 > status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type", + __func__); + return status; + } + +#ifdef WLAN_FEATURE_11W + pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED); +#endif + + /* Parse WPA/RSN IE, and set the corresponding fields in Roam profile */ + if (req->ie_len) + { + status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len); + if (0 > status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed to parse the WPA/RSN IE")); + return status; + } + } + + /*incase of WEP set default key information*/ + if (req->key && req->key_len) + { + if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0]) + || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0]) + ) + { + if ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported", + __func__); + return -EOPNOTSUPP; + } + else + { + u8 key_len = req->key_len; + u8 key_idx = req->key_idx; + + if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len) + && (CSR_MAX_NUM_KEY > key_idx) + ) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: setting default wep key, key_idx = %hu key_len %hu", + __func__, key_idx, key_len); + vos_mem_copy( + &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0], + req->key, key_len); + pWextState->roamProfile.Keys.KeyLength[key_idx] = + (u8)key_len; + pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx; + } + } + } + } + + return status; +} + +/* + * FUNCTION: wlan_hdd_try_disconnect + * This function is used to disconnect from previous + * connection + */ +static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter ) +{ + unsigned long rc; + hdd_station_ctx_t *pHddStaCtx; + eMib_dot11DesiredBssType connectedBssType; + int status, result = 0; + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType ); + + if((eMib_dot11DesiredBssType_independent == connectedBssType) || + (eConnectionState_Associated == pHddStaCtx->conn_info.connState) || + (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) || + (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) + { + hdd_connSetConnectionState(pAdapter, eConnectionState_Disconnecting); + /* Issue disconnect to CSR */ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + + status = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + /* + * 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. + */ + if (eHAL_STATUS_CMD_NOT_QUEUED == status) { + hddLog(LOG1, + FL("Already disconnected or connect was in sme/roam pending list and removed by disconnect")); + } else if (0 != status) { + hddLog(LOGE, + FL("csrRoamDisconnect failure, returned %d"), + (int)status ); + pHddStaCtx->staDebugState = status; + result = -EINVAL; + goto disconnected; + } + + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc && (eHAL_STATUS_CMD_NOT_QUEUED != status)) { + hddLog(LOGE, FL("Sme disconnect event timed out session Id %d" + " staDebugState %d"), pAdapter->sessionId, + pHddStaCtx->staDebugState); + result = -ETIMEDOUT; + } + } + else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState) + { + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hddLog(LOGE, FL("Disconnect event timed out session Id %d" + " staDebugState %d"), pAdapter->sessionId, + pHddStaCtx->staDebugState); + result = -ETIMEDOUT; + } + } +disconnected: + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_NotConnected")); + hdd_connSetConnectionState(pAdapter, + eConnectionState_NotConnected); + return result; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_connect + * This function is used to start the association process + */ +static int __wlan_hdd_cfg80211_connect( struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *req + ) +{ + int status; + u16 channel; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \ + defined(CFG80211_BSSID_HINT_BACKPORT) + const u8 *bssid_hint = req->bssid_hint; +#else + const u8 *bssid_hint = NULL; +#endif + + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL; + hdd_context_t *pHddCtx; + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_CONNECT, + pAdapter->sessionId, pAdapter->device_mode)); + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION && + pAdapter->device_mode != WLAN_HDD_P2P_CLIENT) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: device_mode is not supported", __func__); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (!pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is null", __func__); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Reached max concurrent connections")); + return -ECONNREFUSED; + } + +#if defined(FEATURE_WLAN_LFR) && defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) + wlan_hdd_disable_roaming(pAdapter); +#endif + + + //If Device Mode is Station Concurrent Sessions Exit BMps + //P2P Mode will be taken care in Open/close adapter + if (!pHddCtx->cfg_ini->enablePowersaveOffload && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + (vos_concurrent_open_sessions_running())) { + exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, + WLAN_HDD_INFRA_STATION); + } + + /*Try disconnecting if already in connected state*/ + status = wlan_hdd_try_disconnect(pAdapter); + if ( 0 > status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing" + " connection")); + return -EALREADY; + } + + /*initialise security parameters*/ + status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); + + if (0 > status) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params", + __func__); + return status; + } + + if (req->channel) + channel = req->channel->hw_value; + else + channel = 0; + + status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, + req->ssid_len, req->bssid, + bssid_hint, channel); + + if (0 != status) { + //ReEnable BMPS if disabled + // If PS offload is enabled, fw will take care of +// ps in cae of concurrency. + if((VOS_STATUS_SUCCESS == exitbmpsStatus) && + (NULL != pHddCtx) && !pHddCtx->cfg_ini->enablePowersaveOffload) { + if (pHddCtx->hdd_wlan_suspended) { + hdd_set_pwrparams(pHddCtx); + } + //ReEnable Bmps and Imps back + hdd_enable_bmps_imps(pHddCtx); + } + + hddLog(VOS_TRACE_LEVEL_ERROR, FL("connect failed")); + return status; + } + pHddCtx->isAmpAllowed = VOS_FALSE; + EXIT(); + return status; +} + +static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *req) +{ + int ret; + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: wlan_hdd_disconnect + * This function is used to issue a disconnect request to SME + */ +int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) +{ + int status, result = 0; + unsigned long rc; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + /*stop tx queues*/ + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + pHddCtx->isAmpAllowed = VOS_TRUE; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_Disconnecting", + __func__); + pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting; + INIT_COMPLETION(pAdapter->disconnect_comp_var); + + /*issue disconnect*/ + + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, reason); + /* + * 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. + */ + if (eHAL_STATUS_CMD_NOT_QUEUED == status) { + hddLog(LOG1, + FL("Already disconnected or connect was in sme/roam pending list and removed by disconnect")); + } else if (0 != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s csrRoamDisconnect failure, returned %d", + __func__, (int)status ); + pHddStaCtx->staDebugState = status; + result = -EINVAL; + goto disconnected; + } + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + + if (!rc && (eHAL_STATUS_CMD_NOT_QUEUED != status)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failed to disconnect, timed out", __func__); + result = -ETIMEDOUT; + } + +disconnected: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Set HDD connState to eConnectionState_NotConnected")); + hdd_connSetConnectionState(pAdapter, + eConnectionState_NotConnected); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + /* Sending disconnect event to userspace for kernel version < 3.11 + * is handled by __cfg80211_disconnect call to __cfg80211_disconnected + */ + hddLog(LOG1, FL("Send disconnected event to userspace")); + cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, + NULL, 0, GFP_KERNEL); +#endif + + EXIT(); + return result; +} + +/** + * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code + * @reason: ieee80211 reason code. + * + * This utility function helps log string conversion of reason code. + * + * Return: string conversion of reason code, if match found; + * "Unknown" otherwise. + */ +static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason) +{ + switch (reason) { + CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED); + CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID); + CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY); + CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); + CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT); + CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN); + CASE_RETURN_STRING(WLAN_REASON_INVALID_IE); + CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE); + CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT); + CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT); + CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT); + CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER); + CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER); + CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP); + CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION); + CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP); + CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED); + CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK); + CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP); + CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS); + CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE); + CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP); + CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT); + CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP); + CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED); + CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS); + CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG); + CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE); + CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES); + CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT); + CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK); + CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM); + CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY); + CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR); + CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD); + CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE); + CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS); + CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY); + CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN); + default: + return "Unknown"; + } +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_disconnect + * This function is used to issue a disconnect request to SME + */ +static int __wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, + struct net_device *dev, + u16 reason + ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + int status; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +#ifdef FEATURE_WLAN_TDLS + tANI_U8 staIdx; +#endif + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_DISCONNECT, + pAdapter->sessionId, reason)); + hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, reason); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return status; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* Issue disconnect request to SME, if station is in connected state */ + if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) || + (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) { + eCsrRoamDisconnectReason reasonCode = + eCSR_DISCONNECT_REASON_UNSPECIFIED; + hdd_scaninfo_t *pScanInfo; + switch (reason) { + case WLAN_REASON_MIC_FAILURE: + reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR; + break; + + case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY: + case WLAN_REASON_DISASSOC_AP_BUSY: + case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA: + reasonCode = eCSR_DISCONNECT_REASON_DISASSOC; + break; + + case WLAN_REASON_PREV_AUTH_NOT_VALID: + case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA: + reasonCode = eCSR_DISCONNECT_REASON_DEAUTH; + break; + + case WLAN_REASON_DEAUTH_LEAVING: + reasonCode = pHddCtx->cfg_ini->gEnableDeauthToDisassocMap ? + eCSR_DISCONNECT_REASON_STA_HAS_LEFT : + eCSR_DISCONNECT_REASON_DEAUTH; + break; + case WLAN_REASON_DISASSOC_STA_HAS_LEFT: + reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT; + break; + default: + reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED; + break; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("convert to internal reason %d to reasonCode %d"), + reason, reasonCode); + pScanInfo = &pAdapter->scan_info; + if (pScanInfo->mScanPending) { + hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, " + "Aborting Scan"); + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + + wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter); +#ifdef FEATURE_WLAN_TDLS + /* First clean up the tdls peers if any */ + for (staIdx = 0 ; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) { + if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) && + (pHddCtx->tdlsConnInfo[staIdx].staId)) { + uint8 *mac; + mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes; + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR, + __func__, pHddCtx->tdlsConnInfo[staIdx].staId, + pAdapter->sessionId, + MAC_ADDR_ARRAY(mac)); + sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + mac); + } + } +#endif + hddLog(LOGE, + FL("Disconnect request from user space with reason: %s"), + hdd_ieee80211_reason_code_to_str(reason)); + status = wlan_hdd_disconnect(pAdapter, reasonCode); + if (0 != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("failure, returned %d"), status); + return -EINVAL; + } + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("unexpected cfg disconnect called while in state (%d)"), + pHddStaCtx->conn_info.connState); + } + + return status; +} + +static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, + struct net_device *dev, + u16 reason + ) +{ + int ret; + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss + * This function is used to initialize the security + * settings in IBSS mode. + */ +static int wlan_hdd_cfg80211_set_privacy_ibss( + hdd_adapter_t *pAdapter, + struct cfg80211_ibss_params *params + ) +{ + int status = 0; + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + ENTER(); + + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey)); + pHddStaCtx->ibss_enc_key_installed = 0; + + if (params->ie_len && (NULL != params->ie)) + { + if (wlan_hdd_cfg80211_get_ie_ptr(params->ie, + params->ie_len, WLAN_EID_RSN)) + { + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2; + encryptionType = eCSR_ENCRYPT_TYPE_AES; + } + else if (hdd_isWPAIEPresent(params->ie, params->ie_len)) + { + tDot11fIEWPA dot11WPAIE; + tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + u8 *ie; + + memset(&dot11WPAIE, 0, sizeof(dot11WPAIE)); + ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie, + params->ie_len, DOT11F_EID_WPA); + if (NULL != ie) + { + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA; + // Unpack the WPA IE + //Skip past the EID byte and length byte - and four byte WiFi OUI + dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, + &ie[2+4], + ie[1] - 4, + &dot11WPAIE); + /*Extract the multicast cipher, the encType for unicast + cipher for wpa-none is none*/ + encryptionType = + hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher); + } + } + + status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len); + + if (0 > status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to parse WPA/RSN IE")); + return status; + } + } + + pWextState->roamProfile.AuthType.authType[0] = + pHddStaCtx->conn_info.authType = + eCSR_AUTH_TYPE_OPEN_SYSTEM; + + if (params->privacy) + { + /* Security enabled IBSS, At this time there is no information available + * about the security parameters, so initialise the encryption type to + * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY. + * The correct security parameters will be updated later in + * wlan_hdd_cfg80211_add_key */ + /* Hal expects encryption type to be set inorder + *enable privacy bit in beacons */ + + encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "encryptionType=%d", encryptionType); + pHddStaCtx->conn_info.ucEncryptionType = encryptionType; + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType; + + return status; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_join_ibss + * This function is used to create/join an IBSS + */ +static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile; + int status; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tSirMacAddr bssid; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_JOIN_IBSS, + pAdapter->sessionId, pAdapter->device_mode)); + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Reached max concurrent connections")); + return -ECONNREFUSED; + } + + /*Try disconnecting if already in connected state*/ + status = wlan_hdd_try_disconnect(pAdapter); + if ( 0 > status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing" + " IBSS connection")); + return -EALREADY; + } + + pRoamProfile = &pWextState->roamProfile; + + if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType ) + { + hddLog (VOS_TRACE_LEVEL_ERROR, + "%s Interface type is not set to IBSS", __func__); + return -EINVAL; + } + + /* enable selected protection checks in IBSS mode */ + pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK; + + if (eHAL_STATUS_FAILURE == ccmCfgSetInt( pHddCtx->hHal, + WNI_CFG_IBSS_ATIM_WIN_SIZE, + pHddCtx->cfg_ini->ibssATIMWinSize, + NULL, + eANI_BOOLEAN_FALSE)) + { + hddLog(LOGE, + "%s: Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM", + __func__); + } + + /* BSSID is provided by upper layers hence no need to AUTO generate */ + if (NULL != params->bssid) { + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) { + hddLog (VOS_TRACE_LEVEL_ERROR, + "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__); + return -EIO; + } + vos_mem_copy((v_U8_t *)bssid, (v_U8_t *)params->bssid, sizeof(bssid)); + } + else if(pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0) + { + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + hddLog (VOS_TRACE_LEVEL_ERROR, + "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__); + return -EIO; + } + vos_mem_copy((v_U8_t *)bssid, + (v_U8_t *)&pHddCtx->cfg_ini->IbssBssid.bytes[0], + sizeof(bssid)); + } + if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN) + && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX)) + pRoamProfile->beaconInterval = params->beacon_interval; + else { + pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT; + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: input beacon interval %d TU is invalid, use default %d TU", + __func__, params->beacon_interval, + pRoamProfile->beaconInterval); + } + + /* Set Channel */ + if (NULL != +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) || defined(WITH_BACKPORTS) + params->chandef.chan) +#else + params->channel) +#endif + { + u8 channelNum; + v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + int indx; + + /* Get channel number */ + channelNum = + ieee80211_frequency_to_channel( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) || defined(WITH_BACKPORTS) + params->chandef.chan->center_freq); +#else + params->channel->center_freq); +#endif + + if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, + validChan, &numChans)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list", + __func__); + return -EOPNOTSUPP; + } + + for (indx = 0; indx < numChans; indx++) + { + if (channelNum == validChan[indx]) + { + break; + } + } + if (indx >= numChans) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d", + __func__, channelNum); + return -EINVAL; + } + /* Set the Operational Channel */ + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__, + channelNum); + pRoamProfile->ChannelInfo.numOfChannels = 1; + pHddStaCtx->conn_info.operationChannel = channelNum; + pRoamProfile->ChannelInfo.ChannelList = + &pHddStaCtx->conn_info.operationChannel; + } + + /* Initialize security parameters */ + status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params); + + if (status < 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed to set security parameters status: %d"), status); + return status; + } + + /* Issue connect start */ + status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid, + params->ssid_len, bssid, NULL, + pHddStaCtx->conn_info.operationChannel); + + if (0 > status) + hddLog(VOS_TRACE_LEVEL_ERROR, FL("connect failed status: %d"), status); + + EXIT(); + return status; +} + +static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_leave_ibss + * This function is used to leave an IBSS + */ +static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int status; + eHalStatus hal_status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_LEAVE_IBSS, + pAdapter->sessionId, eCSR_DISCONNECT_REASON_IBSS_LEAVE)); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + if (NULL == pWextState) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Data Storage Corruption")); + return -EIO; + } + + pRoamProfile = &pWextState->roamProfile; + + /* Issue disconnect only if interface type is set to IBSS */ + if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) { + hddLog (VOS_TRACE_LEVEL_ERROR, FL("BSS Type is not set to IBSS")); + return -EINVAL; + } + + /* Issue Disconnect request */ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + 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; + } + EXIT(); + return 0; +} + +static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_set_wiphy_params + * This function is used to set the phy parameters + * (RTS Threshold/FRAG Threshold/Retry Count etc ...) + */ +static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, + u32 changed) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + tHalHandle hHal = pHddCtx->hHal; + int status; + + ENTER(); + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS, + NO_SESSION, wiphy->rts_threshold)); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + { + u32 rts_threshold = (wiphy->rts_threshold == -1) ? + WNI_CFG_RTS_THRESHOLD_STAMAX : + wiphy->rts_threshold; + + if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) || + (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid RTS Threshold value %u", + __func__, rts_threshold); + return -EINVAL; + } + + if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, + rts_threshold, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for rts_threshold value %u", + __func__, rts_threshold); + return -EIO; + } + + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %u", __func__, + rts_threshold); + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + { + u16 frag_threshold = (wiphy->frag_threshold == -1) ? + WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX : + wiphy->frag_threshold; + + if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)|| + (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid frag_threshold value %hu", __func__, + frag_threshold); + return -EINVAL; + } + + if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, + frag_threshold, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for frag_threshold value %hu", + __func__, frag_threshold); + return -EIO; + } + + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__, + frag_threshold); + } + + if ((changed & WIPHY_PARAM_RETRY_SHORT) + || (changed & WIPHY_PARAM_RETRY_LONG)) + { + u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ? + wiphy->retry_short : + wiphy->retry_long; + + if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) || + (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu", + __func__, retry_value); + return -EINVAL; + } + + if (changed & WIPHY_PARAM_RETRY_SHORT) + { + if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, + retry_value, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for long retry count %hu", + __func__, retry_value); + return -EIO; + } + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu", + __func__, retry_value); + } + else if (changed & WIPHY_PARAM_RETRY_SHORT) + { + if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, + retry_value, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for short retry count %hu", + __func__, retry_value); + return -EIO; + } + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu", + __func__, retry_value); + } + } + + EXIT(); + return 0; +} + +static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, + u32 changed) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_set_txpower + * This function is used to set the txpower + */ +static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#endif + enum nl80211_tx_power_setting type, + int dbm) +{ + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + tHalHandle hHal = NULL; + tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int status; + + ENTER(); + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_TXPOWER, + NO_SESSION, type )); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hHal = pHddCtx->hHal; + + if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, + dbm, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) { + hddLog(LOGE, FL("ccmCfgSetInt failed for tx power %hu"), dbm); + return -EIO; + } + + hddLog(VOS_TRACE_LEVEL_INFO_MED, FL("Set tx power level %d dbm"), dbm); + + switch (type) { + /* Automatically determine transmit power */ + case NL80211_TX_POWER_AUTOMATIC: + /* Fall through */ + case NL80211_TX_POWER_LIMITED: /* Limit TX power by the mBm parameter */ + if (sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Setting maximum tx power failed")); + return -EIO; + } + break; + + case NL80211_TX_POWER_FIXED: /* Fix TX power to the mBm parameter */ + hddLog(LOGE, FL("NL80211_TX_POWER_FIXED not supported")); + return -EOPNOTSUPP; + break; + + default: + hddLog(LOGE, FL("Invalid power setting type %d"), type); + return -EIO; + } + + EXIT(); + return 0; +} + +static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#endif + enum nl80211_tx_power_setting type, + int dbm) +{ + int ret; + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_txpower(wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) || defined(WITH_BACKPORTS) + wdev, +#endif + type, + dbm); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_get_txpower() - cfg80211 get txpower + * @wiphy: Pointer to wiphy structure. + * @wdev: Pointer to wireless_dev structure. + * @dbm: dbm + * + * This function is used to read the txpower + * + * Return: 0 for success, error number on failure. + */ +static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#endif + int *dbm) +{ + + hdd_adapter_t *pAdapter; + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + int status; + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + *dbm = 0; + return status; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (NULL == pAdapter) { + hddLog(VOS_TRACE_LEVEL_FATAL, FL("pAdapter is NULL")); + return -ENOENT; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_GET_TXPOWER, + pAdapter->sessionId, pAdapter->device_mode)); + wlan_hdd_get_classAstats(pAdapter); + *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr; + + EXIT(); + return 0; +} + +/** + * wlan_hdd_cfg80211_get_txpower() - cfg80211 get power handler function + * @wiphy: Pointer to wiphy structure. + * @wdev: Pointer to wireless_dev structure. + * @dbm: dbm + * + * This is the cfg80211 get txpower handler function which invokes + * the internal function @__wlan_hdd_cfg80211_get_txpower with + * SSR protection. + * + * Return: 0 for success, error number on failure. + */ +static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#endif + int *dbm) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_txpower(wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) || defined(WITH_BACKPORTS) + wdev, +#endif + dbm); + vos_ssr_unprotect(__func__); + + return ret; +} + + +static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, + const u8* mac, + struct station_info *sinfo) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length; + tANI_U8 rate_flags; + + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + hdd_config_t *pCfg = pHddCtx->cfg_ini; + + tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX]; + tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX; + tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX]; + tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX; + tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET]; + tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET; + tANI_U16 maxRate = 0; + tANI_U16 myRate; + tANI_U16 currentRate = 0; + tANI_U8 maxSpeedMCS = 0; + tANI_U8 maxMCSIdx = 0; + tANI_U8 rateFlag = 1; + tANI_U8 i, j, rssidx; + tANI_U8 nss = 1; + int status, mode = 0, maxHtIdx; + struct index_vht_data_rate_type *supported_vht_mcs_rate; + struct index_data_rate_type *supported_mcs_rate; + +#ifdef WLAN_FEATURE_11AC + tANI_U32 vht_mcs_map; + eDataRate11ACMaxMcs vhtMaxMcs; +#endif /* WLAN_FEATURE_11AC */ + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || + (0 == ssidlen)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or" + " Invalid ssidlen, %d", __func__, ssidlen); + /*To keep GUI happy*/ + return 0; + } + + if (true == pHddStaCtx->hdd_ReassocScenario) { + hddLog(LOG1, + FL("Roaming is in progress, cannot continue with this request")); + return 0; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + wlan_hdd_get_rssi(pAdapter, &sinfo->signal); + sinfo->filled |= STATION_INFO_SIGNAL; + +#ifdef WLAN_FEATURE_LPSS + if (!pAdapter->rssi_send) { + pAdapter->rssi_send = VOS_TRUE; + wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 1); + } +#endif + + wlan_hdd_get_station_stats(pAdapter); + rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags; + + //convert to the UI units of 100kbps + myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5; + if (!(rate_flags & eHAL_TX_RATE_LEGACY)) { + nss = pAdapter->hdd_stats.ClassA_stat.rx_frag_cnt; + + if (eHDD_LINK_SPEED_REPORT_ACTUAL == pCfg->reportMaxLinkSpeed) { + /* Get current rate flags if report actual */ + rate_flags = pAdapter->hdd_stats.ClassA_stat.promiscuous_rx_frag_cnt; + } + + if (pAdapter->hdd_stats.ClassA_stat.mcs_index == INVALID_MCS_IDX) { + rate_flags = eHAL_TX_RATE_LEGACY; + pAdapter->hdd_stats.ClassA_stat.mcs_index = 0; + } + } + + hddLog(LOG1, + FL("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d"), + sinfo->signal, + pCfg->reportMaxLinkSpeed, + myRate, + (int) pCfg->linkSpeedRssiHigh, + (int) pCfg->linkSpeedRssiMid, + (int) pCfg->linkSpeedRssiLow, + (int) rate_flags, + (int) pAdapter->hdd_stats.ClassA_stat.mcs_index); + + if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed) + { + // we do not want to necessarily report the current speed + if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed) + { + // report the max possible speed + rssidx = 0; + } + else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed) + { + // report the max possible speed with RSSI scaling + if (sinfo->signal >= pCfg->linkSpeedRssiHigh) + { + // report the max possible speed + rssidx = 0; + } + else if (sinfo->signal >= pCfg->linkSpeedRssiMid) + { + // report middle speed + rssidx = 1; + } + else if (sinfo->signal >= pCfg->linkSpeedRssiLow) + { + // report middle speed + rssidx = 2; + } + else + { + // report actual speed + rssidx = 3; + } + } + else + { + // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid value for reportMaxLinkSpeed: %u", + __func__, pCfg->reportMaxLinkSpeed); + rssidx = 0; + } + + maxRate = 0; + + /* Get Basic Rate Set */ + if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET, + OperationalRates, &ORLeng)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__); + /*To keep GUI happy*/ + return 0; + } + + for (i = 0; i < ORLeng; i++) + { + for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++) + { + /* Validate Rate Set */ + if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F)) + { + currentRate = supported_data_rate[j].supported_rate[rssidx]; + break; + } + } + /* Update MAX rate */ + maxRate = (currentRate > maxRate)?currentRate:maxRate; + } + + /* Get Extended Rate Set */ + if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + ExtendedRates, &ERLeng)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__); + /*To keep GUI happy*/ + return 0; + } + + for (i = 0; i < ERLeng; i++) + { + for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++) + { + if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F)) + { + currentRate = supported_data_rate[j].supported_rate[rssidx]; + break; + } + } + /* Update MAX rate */ + maxRate = (currentRate > maxRate)?currentRate:maxRate; + } + /* Get MCS Rate Set -- + Only if we are connected in non legacy mode and not reporting + actual speed */ + if ((3 != rssidx) && + !(rate_flags & eHAL_TX_RATE_LEGACY)) + { + if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET, + MCSRates, &MCSLeng)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__); + /*To keep GUI happy*/ + return 0; + } + rateFlag = 0; +#ifdef WLAN_FEATURE_11AC + supported_vht_mcs_rate = (struct index_vht_data_rate_type *) + ((nss == 1)? + &supported_vht_mcs_rate_nss1 : + &supported_vht_mcs_rate_nss2); + + if (rate_flags & eHAL_TX_RATE_VHT80) + mode = 2; + else if ((rate_flags & eHAL_TX_RATE_VHT40) || + (rate_flags & eHAL_TX_RATE_HT40)) + mode = 1; + else + mode = 0; + + /* VHT80 rate has separate rate table */ + if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80)) + { + ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map); + vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK ); + if (rate_flags & eHAL_TX_RATE_SGI) + { + rateFlag |= 1; + } + if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs) + { + maxMCSIdx = 7; + } + else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs) + { + maxMCSIdx = 8; + } + else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs) + { + //VHT20 is supporting 0~8 + if (rate_flags & eHAL_TX_RATE_VHT20) + maxMCSIdx = 8; + else + maxMCSIdx = 9; + } + + if (rssidx != 0) + { + for (i=0; i <= maxMCSIdx ; i++) + { + if (sinfo->signal <= rssiMcsTbl[mode][i]) + { + maxMCSIdx = i; + break; + } + } + } + + if (rate_flags & eHAL_TX_RATE_VHT80) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag]; + } + else if (rate_flags & eHAL_TX_RATE_VHT40) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag]; + } + else if (rate_flags & eHAL_TX_RATE_VHT20) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag]; + } + + maxSpeedMCS = 1; + if (currentRate > maxRate) + { + maxRate = currentRate; + } + + } + else +#endif /* WLAN_FEATURE_11AC */ + { + if (rate_flags & eHAL_TX_RATE_HT40) + { + rateFlag |= 1; + } + if (rate_flags & eHAL_TX_RATE_SGI) + { + rateFlag |= 2; + } + + supported_mcs_rate = (struct index_data_rate_type *) + ((nss == 1)? &supported_mcs_rate_nss1 : + &supported_mcs_rate_nss2); + + maxHtIdx = MAX_HT_MCS_IDX; + if (rssidx != 0) + { + for (i=0; i < MAX_HT_MCS_IDX; i++) + { + if (sinfo->signal <= rssiMcsTbl[mode][i]) + { + maxHtIdx = i + 1; + break; + } + } + } + + for (i = 0; i < MCSLeng; i++) + { + for (j = 0; j < maxHtIdx; j++) + { + if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i]) + { + currentRate = supported_mcs_rate[j].supported_rate[rateFlag]; + maxMCSIdx = supported_mcs_rate[j].beacon_rate_index; + break; + } + } + + if ((j < MAX_HT_MCS_IDX) && (currentRate > maxRate)) + { + maxRate = currentRate; + } + maxSpeedMCS = 1; + } + } + } + + else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) + { + maxRate = myRate; + maxSpeedMCS = 1; + maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index; + } + + // make sure we report a value at least as big as our current rate + if ((maxRate < myRate) || (0 == maxRate)) + { + maxRate = myRate; + if (rate_flags & eHAL_TX_RATE_LEGACY) + { + maxSpeedMCS = 0; + } + else + { + maxSpeedMCS = 1; + maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index; + } + } + + if (rate_flags & eHAL_TX_RATE_LEGACY) + { + sinfo->txrate.legacy = maxRate; +#ifdef LINKSPEED_DEBUG_ENABLED + pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy); +#endif //LINKSPEED_DEBUG_ENABLED + } + else + { + sinfo->txrate.mcs = maxMCSIdx; +#ifdef WLAN_FEATURE_11AC + sinfo->txrate.nss = nss; + if (rate_flags & eHAL_TX_RATE_VHT80) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + } + else if (rate_flags & eHAL_TX_RATE_VHT40) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } + else if (rate_flags & eHAL_TX_RATE_VHT20) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + } + else + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; +#endif /* WLAN_FEATURE_11AC */ + if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + if (rate_flags & eHAL_TX_RATE_HT40) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } + } + if (rate_flags & eHAL_TX_RATE_SGI) + { + if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_VHT_MCS)) + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + } + +#ifdef LINKSPEED_DEBUG_ENABLED + pr_info("Reporting MCS rate %d flags %x\n", + sinfo->txrate.mcs, + sinfo->txrate.flags ); +#endif //LINKSPEED_DEBUG_ENABLED + } + } + else + { + // report current rate instead of max rate + + if (rate_flags & eHAL_TX_RATE_LEGACY) + { + //provide to the UI in units of 100kbps + sinfo->txrate.legacy = myRate; +#ifdef LINKSPEED_DEBUG_ENABLED + pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy); +#endif //LINKSPEED_DEBUG_ENABLED + } + else + { + //must be MCS + sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index; +#ifdef WLAN_FEATURE_11AC + sinfo->txrate.nss = nss; + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + if (rate_flags & eHAL_TX_RATE_VHT80) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + } + else if (rate_flags & eHAL_TX_RATE_VHT40) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } +#endif /* WLAN_FEATURE_11AC */ + if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + if (rate_flags & eHAL_TX_RATE_HT40) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } + } + if (rate_flags & eHAL_TX_RATE_SGI) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + } +#ifdef LINKSPEED_DEBUG_ENABLED + pr_info("Reporting actual MCS rate %d flags %x\n", + sinfo->txrate.mcs, + sinfo->txrate.flags ); +#endif //LINKSPEED_DEBUG_ENABLED + } + } + + if (rate_flags & eHAL_TX_RATE_LEGACY) + hddLog(LOG1, FL("Reporting legacy rate %d"), sinfo->txrate.legacy); + else + hddLog(LOG1, FL("Reporting MCS rate %d flags 0x%x"), + sinfo->txrate.mcs, sinfo->txrate.flags); + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + sinfo->tx_bytes = pAdapter->stats.tx_bytes; + sinfo->filled |= STATION_INFO_TX_BYTES; + + sinfo->tx_packets = + pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] + + pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] + + pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] + + pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3]; + + sinfo->tx_retries = + pAdapter->hdd_stats.summary_stat.retry_cnt[0] + + pAdapter->hdd_stats.summary_stat.retry_cnt[1] + + pAdapter->hdd_stats.summary_stat.retry_cnt[2] + + pAdapter->hdd_stats.summary_stat.retry_cnt[3]; + + sinfo->tx_failed = + pAdapter->hdd_stats.summary_stat.fail_cnt[0] + + pAdapter->hdd_stats.summary_stat.fail_cnt[1] + + pAdapter->hdd_stats.summary_stat.fail_cnt[2] + + pAdapter->hdd_stats.summary_stat.fail_cnt[3]; + + sinfo->filled |= + STATION_INFO_TX_PACKETS | + STATION_INFO_TX_RETRIES | + STATION_INFO_TX_FAILED; + + sinfo->rx_bytes = pAdapter->stats.rx_bytes; + sinfo->filled |= STATION_INFO_RX_BYTES; + + sinfo->rx_packets = pAdapter->stats.rx_packets; + sinfo->filled |= STATION_INFO_RX_PACKETS; + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_GET_STA, + pAdapter->sessionId, maxRate)); + EXIT(); + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS) +static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, + const u8* mac, + struct station_info *sinfo) +#else +static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, + u8* mac, + struct station_info *sinfo) +#endif +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, bool mode, int timeout) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + VOS_STATUS vos_status; + int status; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT, + pAdapter->sessionId, timeout)); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((DRIVER_POWER_MODE_AUTO == !mode) && + (TRUE == pHddCtx->hdd_wlan_suspended) && + (pHddCtx->cfg_ini->fhostArpOffload) && + (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + { + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: in cfg80211_set_power_mgmt, calling arp offload"); + vos_status = hdd_conf_arp_offload(pAdapter, TRUE); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s:Failed to enable ARPOFFLOAD Feature %d", + __func__, vos_status); + } + } + + /**The get power cmd from the supplicant gets updated by the nl only + *on successful execution of the function call + *we are oppositely mapped w.r.t mode in the driver + **/ + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + vos_status = wlan_hdd_enter_bmps(pAdapter, !mode); + else + vos_status = wlan_hdd_set_powersave(pAdapter, !mode); + + if (!mode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + "%s: DHCP start indicated through power save", __func__); + vos_runtime_pm_prevent_suspend(pAdapter->runtime_context.connect); + sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode, + pAdapter->macAddressCurrent.bytes, pAdapter->sessionId); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + "%s: DHCP stop indicated through power save", __func__); + vos_runtime_pm_allow_suspend(pAdapter->runtime_context.connect); + sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode, + pAdapter->macAddressCurrent.bytes, pAdapter->sessionId); + } + + if (VOS_STATUS_E_FAILURE == vos_status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to enter bmps mode", __func__); + return -EINVAL; + } + EXIT(); + return 0; +} + + +static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, bool mode, int timeout) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, mode, timeout); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_set_default_mgmt_key() - set default mgmt key + * @wiphy: pointer to wiphy + * @netdev: pointer to net_device structure + * @key_index: key index + * + * Return: 0 on success + */ +static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *netdev, + u8 key_index) +{ + ENTER(); + return 0; +} + +/** + * wlan_hdd_set_default_mgmt_key() - SSR wrapper for + * wlan_hdd_set_default_mgmt_key + * @wiphy: pointer to wiphy + * @netdev: pointer to net_device structure + * @key_index: key index + * + * Return: 0 on success, error number on failure + */ +static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *netdev, + u8 key_index) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_set_txq_params() - set tx queue parameters + * @wiphy: pointer to wiphy + * @netdev: pointer to net_device structure + * @params: pointer to ieee80211_txq_params + * + * Return: 0 on success + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WITH_BACKPORTS) +static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_txq_params *params) +{ + ENTER(); + return 0; +} +#else +static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct ieee80211_txq_params *params) +{ + ENTER(); + return 0; +} +#endif + +/** + * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params + * @wiphy: pointer to wiphy + * @netdev: pointer to net_device structure + * @params: pointer to ieee80211_txq_params + * + * Return: 0 on success, error number on failure + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WITH_BACKPORTS) +static int wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_txq_params *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_set_txq_params(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} +#else +static int wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct ieee80211_txq_params *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_set_txq_params(wiphy, params); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif //LINUX_VERSION_CODE + +static int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct tagCsrDelStaParams *pDelStaParams) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + hdd_hostapd_state_t *pHostapdState; + int status; + v_U8_t staId; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_DEL_STA, + pAdapter->sessionId, pAdapter->device_mode)); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + if (!pHostapdState) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: pHostapdState is Null", __func__); + return 0; + } + + if (vos_is_macaddr_broadcast((v_MACADDR_t *)pDelStaParams->peerMacAddr)) + { + v_U16_t i; + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if ((pAdapter->aStaInfo[i].isUsed) && + (!pAdapter->aStaInfo[i].isDeauthInProgress)) { + vos_mem_copy(pDelStaParams->peerMacAddr, + pAdapter->aStaInfo[i].macAddrSTA.bytes, + ETHER_ADDR_LEN); + +#ifdef IPA_UC_OFFLOAD + if (pHddCtx->cfg_ini->IpaUcOffloadEnabled) { + hdd_ipa_wlan_evt(pAdapter, pAdapter->aStaInfo[i].ucSTAId, + WLAN_CLIENT_DISCONNECT, pDelStaParams->peerMacAddr); + } +#endif /* IPA_UC_OFFLOAD */ + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Delete STA with MAC::"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr)); + + /* Case: SAP in ACS selected DFS ch and station connected. + * Now Radar detected. Then if random channel is another DFS + * ch then new CAC is initiated and no TX allowed. Thus + * do not send any mgmt frames as it will timeout during CAC + */ + if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) + goto fn_end; + + /* Send disassoc and deauth both to avoid some IOT issues */ + vos_event_reset(&pHostapdState->vosEvent); + hdd_softap_sta_disassoc(pAdapter, pDelStaParams); + + vos_status = hdd_softap_sta_deauth(pAdapter, pDelStaParams); + if (VOS_IS_STATUS_SUCCESS(vos_status)) { + pAdapter->aStaInfo[i].isDeauthInProgress = TRUE; + vos_status = vos_wait_single_event( + &pHostapdState->vosEvent, 1000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(VOS_TRACE_LEVEL_ERROR, + "!!%s: ERROR: Deauth wait expired!!", __func__); + } + } + } + } else { + vos_status = hdd_softap_GetStaId(pAdapter, + (v_MACADDR_t *)pDelStaParams->peerMacAddr, &staId); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Skip DEL STA as this is not used::"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr)); + return -ENOENT; + } + +#ifdef IPA_UC_OFFLOAD + if (pHddCtx->cfg_ini->IpaUcOffloadEnabled) { + hdd_ipa_wlan_evt(pAdapter, staId, + WLAN_CLIENT_DISCONNECT, pDelStaParams->peerMacAddr); + } +#endif /* IPA_UC_OFFLOAD */ + + if (pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Skip DEL STA as deauth is in progress::" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr)); + return -ENOENT; + } + + pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE; + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Delete STA with MAC::"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr)); + + if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) + goto fn_end; + + /* Send disassoc and deauth both to avoid some IOT issues */ + vos_event_reset(&pHostapdState->vosEvent); + hdd_softap_sta_disassoc(pAdapter, pDelStaParams); + vos_status = hdd_softap_sta_deauth(pAdapter, pDelStaParams); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE; + hddLog(VOS_TRACE_LEVEL_INFO, + FL("STA removal failed for ::"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr)); + return -ENOENT; + } else { + vos_status = vos_wait_single_event(&pHostapdState->vosEvent, + 1000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(VOS_TRACE_LEVEL_ERROR, + "!!%s: ERROR: Deauth wait expired!!", __func__); + } + } + } + +fn_end: + EXIT(); + return 0; +} + +#ifdef CFG80211_DEL_STA_V2 +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *param) +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, const u8 *mac) +#else +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, u8 *mac) +#endif +#endif +{ + int ret; + struct tagCsrDelStaParams delStaParams; + + vos_ssr_protect(__func__); +#ifdef CFG80211_DEL_STA_V2 + if (NULL == param) { + hddLog(LOGE, FL("Invalid argument passed")); + vos_ssr_unprotect(__func__); + return -EINVAL; + } + + WLANSAP_PopulateDelStaParams(param->mac, param->reason_code, + param->subtype, &delStaParams); + +#else + WLANSAP_PopulateDelStaParams(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams); +#endif + ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + int status = -EPERM; +#ifdef FEATURE_WLAN_TDLS + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + u32 mask, set; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_ADD_STA, + pAdapter->sessionId, params->listen_interval)); + + if (0 != wlan_hdd_validate_context(pHddCtx)) + return -EINVAL; + + mask = params->sta_flags_mask; + set = params->sta_flags_set; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), + mask, set, MAC_ADDR_ARRAY(mac)); + + if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { + if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { + status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL); + } + } +#endif + EXIT(); + return status; +} + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS) +static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +#else +static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac, + struct station_parameters *params) +#endif +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef FEATURE_WLAN_LFR +static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_pmksa *pmksa) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle halHandle; + eHalStatus result = eHAL_STATUS_SUCCESS; + int status; + tPmkidCacheInfo pmk_id; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (!pmksa) { + hddLog(LOGE, FL("pmksa is NULL")); + return -EINVAL; + } + + if (!pmksa->bssid || !pmksa->pmkid) { + hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"), + pmksa->bssid, pmksa->pmkid); + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("set PMKSA for "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pmksa->bssid)); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + vos_mem_copy(pmk_id.BSSID, pmksa->bssid, ETHER_ADDR_LEN); + vos_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE); + + /* Add to the PMKSA ID Cache in CSR */ + result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId, + &pmk_id, 1, FALSE); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_PMKSA, + pAdapter->sessionId, result)); + EXIT(); + return HAL_STATUS_SUCCESS(result) ? 0 : -EINVAL; +} + +static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_pmksa *pmksa) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa); + vos_ssr_unprotect(__func__); + + return ret; +} + + +static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_pmksa *pmksa) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle halHandle; + int status = 0; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (!pmksa) { + hddLog(LOGE, FL("pmksa is NULL")); + return -EINVAL; + } + + if (!pmksa->bssid) { + hddLog(LOGE, FL("pmksa->bssid is NULL")); + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pmksa->bssid)); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_DEL_PMKSA, + pAdapter->sessionId, 0)); + + /* Delete the PMKID CSR cache */ + if (eHAL_STATUS_SUCCESS != + sme_RoamDelPMKIDfromCache(halHandle, + pAdapter->sessionId, pmksa->bssid, FALSE)) { + hddLog(LOGE, FL("Failed to delete PMKSA for "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pmksa->bssid)); + status = -EINVAL; + } + EXIT(); + return status; +} + + +static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_pmksa *pmksa) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa); + vos_ssr_unprotect(__func__); + + return ret; + +} + +static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle halHandle; + int status = 0; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* Retrieve halHandle */ + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + /* Flush the PMKID cache in CSR */ + if (eHAL_STATUS_SUCCESS != + sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, NULL, TRUE)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Cannot flush PMKIDCache")); + status = -EINVAL; + } + EXIT(); + return status; +} + +static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211) +static int +__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int status; + + status = wlan_hdd_validate_context(hdd_ctx); + if (status) + return status; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES, + pAdapter->sessionId, pHddStaCtx->conn_info.connState)); + // Added for debug on reception of Re-assoc Req. + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + hddLog(LOGE, FL("Called with Ie of length = %zu when not associated"), + ftie->ie_len); + hddLog(LOGE, FL("Should be Re-assoc Req IEs")); + } + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__, + ftie->ie_len); +#endif + + // Pass the received FT IEs to SME + sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, + (const u8 *)ftie->ie, + ftie->ie_len); + EXIT(); + return 0; +} + +static int +wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO +int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_scaninfo_t *pScanInfo = NULL; + unsigned long rc; + + pScanInfo = &pAdapter->scan_info; + + if (pScanInfo->mScanPending && pAdapter->request) + { + INIT_COMPLETION(pScanInfo->abortscan_event_var); + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + + rc = wait_for_completion_timeout( + &pScanInfo->abortscan_event_var, + msecs_to_jiffies(5000)); + if (!rc) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout occurred while waiting for abort scan" , + __func__); + return -ETIME; + } + } + return 0; +} +void hdd_cfg80211_sched_scan_done_callback(void *callbackContext, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + int ret; + hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext; + hdd_context_t *pHddCtx; + + ENTER(); + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter is Null", __func__); + return ; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null!!!", __func__); + return ; + } + + spin_lock(&pHddCtx->schedScan_lock); + if (TRUE == pHddCtx->isWiphySuspended) + { + pHddCtx->isSchedScanUpdatePending = TRUE; + spin_unlock(&pHddCtx->schedScan_lock); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Update cfg80211 scan database after it resume", __func__); + return ; + } + spin_unlock(&pHddCtx->schedScan_lock); + + ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter); + + if (0 > ret) + hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + + cfg80211_sched_scan_results(pHddCtx->wiphy); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: cfg80211 scan result database updated", __func__); +} + +/** + * wlan_hdd_is_pno_allowed() - Check if PNO is allowed + * @adapter: HDD Device Adapter + * + * The PNO Start request is coming from upper layers. + * It is to be allowed only for Infra STA device type + * and the link should be in a disconnected state. + * + * Return: Success if PNO is allowed, Failure otherwise. + */ +static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *adapter) +{ + hddLog(LOG1, + FL("dev_mode=%d, conn_state=%d, session ID=%d"), + adapter->device_mode, + adapter->sessionCtx.station.conn_info.connState, + adapter->sessionId); + if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) && + (eConnectionState_NotConnected == + adapter->sessionCtx.station.conn_info.connState)) + return eHAL_STATUS_SUCCESS; + else + return eHAL_STATUS_FAILURE; + +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_sched_scan_start + * Function to enable PNO + */ +static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_sched_scan_request *request) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpSirPNOScanReq pPnoRequest = NULL; + hdd_context_t *pHddCtx; + tHalHandle hHal; + 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; + eHalStatus status = eHAL_STATUS_FAILURE; + int ret = 0; + hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info; + hdd_config_t *config = NULL; + v_U32_t num_ignore_dfs_ch = 0; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + config = pHddCtx->cfg_ini; + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HAL context is Null!!!", __func__); + return -EINVAL; + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + (eConnectionState_Connecting == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: %p(%d) Connection in progress: sched_scan_start denied (EBUSY)", + __func__, + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId); + return -EBUSY; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SCHED_SCAN_START, + pAdapter->sessionId, pAdapter->device_mode)); + /* + * The current umac is unable to handle the SCAN_PREEMPT and SCAN_DEQUEUED + * so its necessary to terminate the existing scan which is already issued + * otherwise the host won't enter into the suspend state due to the reason + * that the wlan wakelock which was held in the wlan_hdd_cfg80211_scan + * function. + */ + sme_ScanFlushResult(hHal, pAdapter->sessionId); + if (TRUE == pScanInfo->mScanPending) + { + ret = wlan_hdd_scan_abort(pAdapter); + if(ret < 0){ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: aborting the existing scan is unsuccessful", __func__); + return -EBUSY; + } + } + + if (eHAL_STATUS_FAILURE == wlan_hdd_is_pno_allowed(pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: pno is not allowed", __func__); + return -ENOTSUPP; + } + + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + if (NULL == pPnoRequest) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + memset(pPnoRequest, 0, sizeof (tSirPNOScanReq)); + pPnoRequest->enable = 1; /*Enable PNO */ + pPnoRequest->ucNetworksCount = request->n_match_sets; + if ((!pPnoRequest->ucNetworksCount ) || + (pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS )) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Network input is not correct %d", + __func__, pPnoRequest->ucNetworksCount); + ret = -EINVAL; + goto error; + } + + if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Incorrect number of channels %d", + __func__, request->n_channels); + ret = -EINVAL; + goto error; + } + + /* Framework provides one set of channels(all) + * common for all saved profile */ + if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, + channels_allowed, &num_channels_allowed)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to get valid channel list", __func__); + ret = -EINVAL; + goto error; + } + /* Checking each channel against allowed channel list */ + num_ch = 0; + if (request->n_channels) + { + char chList [(request->n_channels*5)+1]; + int len; + for (i = 0, len = 0; i < request->n_channels; i++) + { + for (indx = 0; indx < num_channels_allowed; indx++) + { + if (request->channels[i]->hw_value == channels_allowed[indx]) + { + if ((!config->enable_dfs_pno_chnl_scan) && + (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(channels_allowed[indx]))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : Dropping DFS channel : %d", + __func__,channels_allowed[indx]); + num_ignore_dfs_ch++; + break; + } + + valid_ch[num_ch++] = request->channels[i]->hw_value; + len += snprintf(chList+len, 5, "%d ", + request->channels[i]->hw_value); + break ; + } + } + } + hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList); + + /*If all channels are DFS and dropped, then ignore the PNO request*/ + if (num_ignore_dfs_ch == request->n_channels) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : All requested channels are DFS channels", __func__); + ret = -EINVAL; + goto error; + } + } + + /* Filling per profile params */ + for (i = 0; i < pPnoRequest->ucNetworksCount; i++) + { + pPnoRequest->aNetworks[i].ssId.length = + request->match_sets[i].ssid.ssid_len; + + if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) || + ( pPnoRequest->aNetworks[i].ssId.length > 32 ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: SSID Len %d is not correct for network %d", + __func__, pPnoRequest->aNetworks[i].ssId.length, i); + ret = -EINVAL; + goto error; + } + + memcpy(pPnoRequest->aNetworks[i].ssId.ssId, + request->match_sets[i].ssid.ssid, + request->match_sets[i].ssid.ssid_len); + pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/ + pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/ + pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/ + + /*Copying list of valid channel into request */ + memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch); + pPnoRequest->aNetworks[i].ucChannelCount = num_ch; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) || defined(WITH_BACKPORTS) + pPnoRequest->aNetworks[i].rssiThreshold = + request->match_sets[i].rssi_thold; +#else + pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value +#endif + } + /* set scan to passive if no SSIDs are specified in the request */ + if (0 == request->n_ssids) + pPnoRequest->do_passive_scan = true; + else + pPnoRequest->do_passive_scan = false; + + for (i = 0; i < request->n_ssids; i++) { + j = 0; + while (j < pPnoRequest->ucNetworksCount) { + if ((pPnoRequest->aNetworks[j].ssId.length == + request->ssids[i].ssid_len) && + (0 == memcmp(pPnoRequest->aNetworks[j].ssId.ssId, + request->ssids[i].ssid, + pPnoRequest->aNetworks[j].ssId.length))) { + pPnoRequest->aNetworks[j].bcastNetwType = eBCAST_HIDDEN; + break; + } + j++; + } + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Number of hidden networks being Configured = %d", + request->n_ssids); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "request->ie_len = %zu", request->ie_len); + if ((0 < request->ie_len) && (NULL != request->ie)) + { + pPnoRequest->us24GProbeTemplateLen = request->ie_len; + memcpy(&pPnoRequest->p24GProbeTemplate, request->ie, + pPnoRequest->us24GProbeTemplateLen); + + pPnoRequest->us5GProbeTemplateLen = request->ie_len; + memcpy(&pPnoRequest->p5GProbeTemplate, request->ie, + pPnoRequest->us5GProbeTemplateLen); + } + + /* + * Driver gets only one time interval which is hard coded in + * supplicant for 10000ms. Taking power consumption into account + * firmware after gPNOScanTimerRepeatValue times fast_scan_period switches + * slow_scan_period. This is less frequent scans and firmware shall be + * in slow_scan_period mode until next PNO Start. + */ + pPnoRequest->fast_scan_period = request->interval; + pPnoRequest->fast_scan_max_cycles = + pHddCtx->cfg_ini->configPNOScanTimerRepeatValue; + pPnoRequest->slow_scan_period = pHddCtx->cfg_ini->pno_slow_scan_multiplier * + pPnoRequest->fast_scan_period; + + hddLog(LOG1, "Base scan interval: %d sec PNOScanTimerRepeatValue: %d", + (request->interval / 1000), + pHddCtx->cfg_ini->configPNOScanTimerRepeatValue); + + pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "SessionId %d, enable %d, modePNO %d", + pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO); + + status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), + pPnoRequest, pAdapter->sessionId, + hdd_cfg80211_sched_scan_done_callback, pAdapter); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to enable PNO", __func__); + ret = -EINVAL; + goto error; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO scanRequest offloaded"); + +error: + vos_mem_free(pPnoRequest); + EXIT(); + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_sched_scan_start + * NL interface to enable PNO + */ +static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_sched_scan_request *request) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_sched_scan_start(wiphy, dev, request); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_sched_scan_stop + * Function to disable PNO + */ +static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + tHalHandle hHal; + tpSirPNOScanReq pPnoRequest = NULL; + int ret = 0; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return -ENODEV; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* The return 0 is intentional when isLogpInProgress and + * isLoadUnloadInProgress. We did observe a crash due to a return of + * failure in sched_scan_stop , especially for a case where the unload + * of the happens at the same time. The function __cfg80211_stop_sched_scan + * was clearing rdev->sched_scan_req only when the sched_scan_stop returns + * success. If it returns a failure , then its next invocation due to the + * clean up of the second interface will have the dev pointer corresponding + * to the first one leading to a crash. + */ + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return ret; + } + + if ((pHddCtx->isLoadInProgress) || + (pHddCtx->isUnloadInProgress)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return ret; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HAL context is Null!!!", __func__); + return -EINVAL; + } + + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + if (NULL == pPnoRequest) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + memset(pPnoRequest, 0, sizeof (tSirPNOScanReq)); + pPnoRequest->enable = 0; /* Disable PNO */ + pPnoRequest->ucNetworksCount = 0; + + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SCHED_SCAN_STOP, + pAdapter->sessionId, pAdapter->device_mode)); + status = sme_SetPreferredNetworkList(hHal, pPnoRequest, + pAdapter->sessionId, + NULL, pAdapter); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to disabled PNO"); + ret = -EINVAL; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: PNO scan disabled", __func__); + + vos_mem_free(pPnoRequest); + + EXIT(); + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop + * NL interface to disable PNO + */ +static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_sched_scan_stop(wiphy, dev); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif /*FEATURE_WLAN_SCAN_PNO*/ + +#ifdef FEATURE_WLAN_TDLS + +/** + * __wlan_hdd_cfg80211_tdls_mgmt() - cfg80211 tdls mgmt handler function + * @wiphy: Pointer to wiphy structure. + * @dev: Pointer to net_device structure. + * @peer: peer address + * @action_code: action code + * @dialog_token: dialog token + * @status_code: status code + * @peer_capability: peer capability + * @buf: buffer + * @len: Length of @buf + * + * Return: 0 for success, error number on failure. + */ +#if TDLS_MGMT_VERSION2 +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +#else /* TDLS_MGMT_VERSION2 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + u32 peer_capability, bool initiator, + const u8 *buf, size_t len) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + u32 peer_capability, const u8 *buf, + size_t len) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +#else +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, + u16 status_code, const u8 *buf, + size_t len) +#endif +#endif +{ + + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + VOS_STATUS status; + int max_sta_failed = 0; + int responder; + unsigned long rc; + tANI_U16 numCurrTdlsPeers; +#if !(TDLS_MGMT_VERSION2) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) + u32 peer_capability; + peer_capability = 0; +#endif + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_TDLS_MGMT, + pAdapter->sessionId, action_code)); + + if (0 != wlan_hdd_validate_context(pHddCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return -EINVAL; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: TDLS mode is disabled OR not enabled in FW." + MAC_ADDRESS_STR " action %d declined.", + __func__, MAC_ADDR_ARRAY(peer), action_code); + return -ENOTSUPP; + } + /* If any concurrency is detected */ + if (((1 << VOS_STA_MODE) != pHddCtx->concurrency_mode) || + (pHddCtx->no_of_active_sessions[VOS_STA_MODE] > 1)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Multiple STA OR Concurrency detected. Ignore TDLS MGMT frame. action_code=%d, concurrency_mode: 0x%x, active_sessions: %d"), + action_code, + pHddCtx->concurrency_mode, + pHddCtx->no_of_active_sessions[VOS_STA_MODE]); + return -EPERM; + } + /* other than teardown frame, mgmt frames are not sent if disabled */ + if (SIR_MAC_TDLS_TEARDOWN != action_code) + { + /* if tdls_mode is disabled to respond to peer's request */ + if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " TDLS mode is disabled. action %d declined.", + __func__, MAC_ADDR_ARRAY(peer), action_code); + + return -ENOTSUPP; + } else if (pHddCtx->tdls_nss_switch_in_progress) { + hddLog(LOGE, + FL("TDLS antenna switch in progress, action %d declined for " + MAC_ADDRESS_STR), action_code, MAC_ADDR_ARRAY(peer)); + return -EAGAIN; + } + } + if (WLAN_IS_TDLS_SETUP_ACTION(action_code)) + { + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " TDLS setup is ongoing. action %d declined.", + __func__, MAC_ADDR_ARRAY(peer), action_code); + return -EPERM; + } + } + + if (SIR_MAC_TDLS_SETUP_REQ == action_code || + SIR_MAC_TDLS_SETUP_RSP == action_code ) + { + numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter); + if (pHddCtx->max_num_tdls_sta <= numCurrTdlsPeers) + { + /* supplicant still sends tdls_mgmt(SETUP_REQ) even after + we return error code at 'add_station()'. Hence we have this + check again in addition to add_station(). + Anyway, there is no hard to double-check. */ + if (SIR_MAC_TDLS_SETUP_REQ == action_code) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " TDLS Max peer already connected. action (%d) declined. Num of peers (%d), Max allowed (%d).", + __func__, MAC_ADDR_ARRAY(peer), action_code, + numCurrTdlsPeers, pHddCtx->max_num_tdls_sta); + return -EINVAL; + } + else + { + /* maximum reached. tweak to send error code to peer and return + error code to supplicant */ + status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " TDLS Max peer already connected, send response status (%d). Num of peers (%d), Max allowed (%d).", + __func__, MAC_ADDR_ARRAY(peer), status_code, + numCurrTdlsPeers, pHddCtx->max_num_tdls_sta); + max_sta_failed = -EPERM; + /* fall through to send setup resp with failure status + code */ + } + } + else + { + hddTdlsPeer_t *pTdlsPeer; + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE); + if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:" MAC_ADDRESS_STR " already connected. action %d declined.", + __func__, MAC_ADDR_ARRAY(peer), action_code); + return -EPERM; + } + } + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %zu", + "tdls_mgmt", MAC_ADDR_ARRAY(peer), + action_code, dialog_token, status_code, len); + + /*Except teardown responder will not be used so just make 0*/ + responder = 0; + if (SIR_MAC_TDLS_TEARDOWN == action_code) + { + + hddTdlsPeer_t *pTdlsPeer; + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE); + + if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) + responder = pTdlsPeer->is_responder; + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %zu", + __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status, + dialog_token, status_code, len); + return -EPERM; + } + } + + /* For explicit trigger of DIS_REQ come out of BMPS for + successfully receiving DIS_RSP from peer. */ + if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || + (SIR_MAC_TDLS_DIS_RSP == action_code) || + (SIR_MAC_TDLS_DIS_REQ == action_code)) + { + /* Fw will take care if PS offload is enabled. */ + if (!pHddCtx->cfg_ini->enablePowersaveOffload) + { + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Sending frame action_code %u.Disable BMPS", + __func__, action_code); + hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); + } + } + if (SIR_MAC_TDLS_DIS_REQ != action_code) + wlan_hdd_tdls_set_cap(pAdapter, peer, eTDLS_CAP_SUPPORTED); + } + + /* make sure doesn't call send_mgmt() while it is pending */ + if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY", + __func__, MAC_ADDR_ARRAY(peer), action_code); + return -EBUSY; + } + + pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC; + INIT_COMPLETION(pAdapter->tdls_mgmt_comp); + + status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, peer, action_code, + dialog_token, status_code, peer_capability, + (tANI_U8 *)buf, len, !responder); + + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_SendTdlsMgmtFrame failed!", __func__); + pAdapter->mgmtTxCompletionStatus = FALSE; + + wlan_hdd_tdls_check_bmps(pAdapter); + return -EINVAL; + } + + if (SIR_MAC_TDLS_TEARDOWN == action_code && + pHddCtx->tdls_nss_switch_in_progress) { + mutex_lock(&pHddCtx->tdls_lock); + if (pHddCtx->tdls_teardown_peers_cnt != 0) + pHddCtx->tdls_teardown_peers_cnt--; + if (pHddCtx->tdls_teardown_peers_cnt == 0) { + if (pHddCtx->tdls_nss_transition_mode == + TDLS_NSS_TRANSITION_1x1_to_2x2) { + /* TDLS NSS switch is fully completed, so reset the flags */ + hddLog(LOG1, FL("TDLS NSS switch is fully completed")); + pHddCtx->tdls_nss_switch_in_progress = false; + pHddCtx->tdls_nss_teardown_complete = false; + } else { + /* TDLS NSS switch is not yet completed, but tdls teardown + * is completed for all the peers. + */ + hddLog(LOG1, + FL("TDLS NSS switch is not completed, but teardown completed for all peers" + )); + pHddCtx->tdls_nss_teardown_complete = true; + } + } + mutex_unlock(&pHddCtx->tdls_lock); + } + + rc = wait_for_completion_timeout(&pAdapter->tdls_mgmt_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); + + if ((0 == rc) || (TRUE != pAdapter->mgmtTxCompletionStatus)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Mgmt Tx Completion timed out TxCompletion %u", + __func__, pAdapter->mgmtTxCompletionStatus); + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + + if (pHddCtx->isUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + + pAdapter->mgmtTxCompletionStatus = FALSE; + wlan_hdd_tdls_check_bmps(pAdapter); + return -EINVAL; + } + + if (max_sta_failed) + { + wlan_hdd_tdls_check_bmps(pAdapter); + return max_sta_failed; + } + + if (SIR_MAC_TDLS_SETUP_RSP == action_code) + { + return wlan_hdd_tdls_set_responder(pAdapter, peer, FALSE); + } + else if (SIR_MAC_TDLS_SETUP_CNF == action_code) + { + return wlan_hdd_tdls_set_responder(pAdapter, peer, TRUE); + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_tdls_mgmt() - cfg80211 tdls mgmt handler function + * @wiphy: Pointer to wiphy structure. + * @dev: Pointer to net_device structure. + * @peer: peer address + * @action_code: action code + * @dialog_token: dialog token + * @status_code: status code + * @peer_capability: peer capability + * @buf: buffer + * @len: Length of @buf + * + * This is the cfg80211 tdls mgmt handler function which invokes + * the internal function @__wlan_hdd_cfg80211_tdls_mgmt with + * SSR protection. + * + * Return: 0 for success, error number on failure. + */ +#if TDLS_MGMT_VERSION2 +static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +#else /* TDLS_MGMT_VERSION2 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) +static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + u32 peer_capability, bool initiator, + const u8 *buf, size_t len) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, u8 action_code, + u8 dialog_token, u16 status_code, + u32 peer_capability, const u8 *buf, + size_t len) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) +static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len) +#else +static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, u8 action_code, + u8 dialog_token, + u16 status_code, const u8 *buf, + size_t len) +#endif +#endif +{ + int ret; + + vos_ssr_protect(__func__); +#if TDLS_MGMT_VERSION2 + ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, + peer_capability, buf, len); +#else /* TDLS_MGMT_VERSION2 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) + ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, + peer_capability, initiator, + buf, len); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) + ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, + peer_capability, buf, len); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, + peer_capability, buf, len); +#else + ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code, + dialog_token, status_code, buf, len); +#endif +#endif + + vos_ssr_unprotect(__func__); + + return ret; +} + +int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, + const u8 *peer, + cfg80211_exttdls_callback callback, + u32 chan, + u32 max_latency, + u32 op_class, + u32 min_bandwidth) +{ + hddTdlsPeer_t *pTdlsPeer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + + if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) || + (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s TDLS External control or Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + /* To cater the requirement of establishing the TDLS link + * irrespective of the data traffic , get an entry of TDLS peer. + */ + pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer); + if (pTdlsPeer == NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: peer " MAC_ADDRESS_STR " does not exist", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS Add Force Peer Failed", + __func__); + return -EINVAL; + } + + /* Update the peer mac to firmware, so firmware + * could update the connection table + */ + if (0 != wlan_hdd_tdls_update_peer_mac(pAdapter, peer, + eSME_TDLS_PEER_ADD_MAC_ADDR)) { + hddLog(LOGE, FL("TDLS Peer mac update Failed " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + /* validate if off channel is DFS channel */ + if (VOS_IS_DFS_CH(chan)) { + hddLog(LOGE, + FL("Resetting TDLS off-channel from %d to %d"), + chan, CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT); + chan = CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT; + } + + if ( 0 != wlan_hdd_tdls_set_extctrl_param(pAdapter, peer, + chan, max_latency, + op_class, min_bandwidth) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS Set Peer's External Ctrl Parameter Failed", + __func__); + return -EINVAL; + } + + if ( 0 != wlan_hdd_set_callback(pTdlsPeer, callback) ) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS set callback Failed", + __func__); + return -EINVAL; + } + + return(0); +} + +int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, const u8 *peer) +{ + hddTdlsPeer_t *pTdlsPeer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + + if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) || + (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s TDLS External control or Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE); + + if ( NULL == pTdlsPeer ) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR + "peer matching MAC_ADDRESS_STR not found", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + else { + wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } + + if (0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s Failed", + __func__); + return -EINVAL; + } + + /* Update the peer mac to firmware, so firmware + * could update the connection table + */ + if (0 != wlan_hdd_tdls_update_peer_mac(pAdapter, peer, + eSME_TDLS_PEER_REMOVE_MAC_ADDR)) { + hddLog(LOGE, FL("TDLS Peer mac update Failed " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + /* EXT TDLS */ + if ( 0 != wlan_hdd_set_callback(pTdlsPeer, NULL )) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS set callback Failed", + __func__); + return -EINVAL; + } + return(0); +} + +static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + enum nl80211_tdls_operation oper) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + int status; + tSmeTdlsPeerStateParams smeTdlsPeerStateParams; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + hddTdlsPeer_t *pTdlsPeer; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_TDLS_OPER, + pAdapter->sessionId, oper)); + if ( NULL == peer ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid arguments", __func__); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* QCA 2.0 Discrete ANDs feature capability in cfg_ini with that + * received from target, so cfg_ini gives combined intersected result + */ + if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "TDLS Disabled in INI OR not enabled in FW. " + "Cannot process TDLS commands"); + return -ENOTSUPP; + } + + switch (oper) { + case NL80211_TDLS_ENABLE_LINK: + { + VOS_STATUS status; + unsigned long rc; + tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams; + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE); + + if (NULL == pTdlsPeer) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: peer matching "MAC_ADDRESS_STR + " not found, ignore NL80211_TDLS_ENABLE_LINK", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: NL80211_TDLS_ENABLE_LINK for peer " + MAC_ADDRESS_STR" link_status: %d", + __func__, MAC_ADDR_ARRAY(peer), + pTdlsPeer->link_status); + + if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid sta index %u for " + MAC_ADDRESS_STR" TDLS_ENABLE_LINK failed", + __func__, pTdlsPeer->staId, + MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status) + { + if (IS_ADVANCE_TDLS_ENABLE) { + + if (0 != wlan_hdd_tdls_get_link_establish_params( + pAdapter, peer, &tdlsLinkEstablishParams)) + return -EINVAL; + + INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp); + + sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + peer, + &tdlsLinkEstablishParams); + /* Send TDLS peer UAPSD capabilities to the firmware and + * register with the TL on after the response for this operation + * is received . + */ + rc = wait_for_completion_timeout( + &pAdapter->tdls_link_establish_req_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ)); + if (!rc) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Link Establish Request timed out", __func__); + return -EINVAL; + } + } + wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, + eTDLS_LINK_CONNECTED, + eTDLS_LINK_SUCCESS); + /* start TDLS client registration with TL */ + status = hdd_roamRegisterTDLSSTA(pAdapter, peer, + pTdlsPeer->staId, + pTdlsPeer->signature); + if (VOS_STATUS_SUCCESS == status) + { + tANI_U8 i; + + vos_mem_zero(&smeTdlsPeerStateParams, + sizeof(tSmeTdlsPeerStateParams)); + + smeTdlsPeerStateParams.vdevId = pAdapter->sessionId; + vos_mem_copy(&smeTdlsPeerStateParams.peerMacAddr, + &pTdlsPeer->peerMac, + sizeof(tSirMacAddr)); + smeTdlsPeerStateParams.peerState = + eSME_TDLS_PEER_STATE_CONNECTED; + smeTdlsPeerStateParams.peerCap.isPeerResponder = + pTdlsPeer->is_responder; + smeTdlsPeerStateParams.peerCap.peerUapsdQueue = + pTdlsPeer->uapsdQueues; + smeTdlsPeerStateParams.peerCap.peerMaxSp = + pTdlsPeer->maxSp; + smeTdlsPeerStateParams.peerCap.peerBuffStaSupport = + pTdlsPeer->isBufSta; + smeTdlsPeerStateParams.peerCap.peerOffChanSupport = + pTdlsPeer->isOffChannelSupported; + smeTdlsPeerStateParams.peerCap.peerCurrOperClass = 0; + smeTdlsPeerStateParams.peerCap.selfCurrOperClass = 0; + smeTdlsPeerStateParams.peerCap.peerChanLen = + pTdlsPeer->supported_channels_len; + smeTdlsPeerStateParams.peerCap.prefOffChanNum = + pTdlsPeer->pref_off_chan_num; + smeTdlsPeerStateParams.peerCap.prefOffChanBandwidth = + pHddCtx->cfg_ini->fTDLSPrefOffChanBandwidth; + smeTdlsPeerStateParams.peerCap.opClassForPrefOffChan = + pTdlsPeer->op_class_for_pref_off_chan; + + if (VOS_IS_DFS_CH( + smeTdlsPeerStateParams.peerCap.prefOffChanNum)) { + hddLog(LOGE, + FL("Resetting TDLS off-channel from %d to %d"), + smeTdlsPeerStateParams.peerCap.prefOffChanNum, + CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT); + smeTdlsPeerStateParams.peerCap.prefOffChanNum = + CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Peer " MAC_ADDRESS_STR " vdevId: %d, peerState: %d, isPeerResponder: %d, uapsdQueues: 0x%x, maxSp: 0x%x, peerBuffStaSupport: %d, peerOffChanSupport: %d, peerCurrOperClass: %d, selfCurrOperClass: %d, peerChanLen: %d, peerOperClassLen: %d, prefOffChanNum: %d, prefOffChanBandwidth: %d, op_class_for_pref_off_chan: %d", + __func__, MAC_ADDR_ARRAY(peer), + smeTdlsPeerStateParams.vdevId, + smeTdlsPeerStateParams.peerState, + smeTdlsPeerStateParams.peerCap.isPeerResponder, + smeTdlsPeerStateParams.peerCap.peerUapsdQueue, + smeTdlsPeerStateParams.peerCap.peerMaxSp, + smeTdlsPeerStateParams.peerCap.peerBuffStaSupport, + smeTdlsPeerStateParams.peerCap.peerOffChanSupport, + smeTdlsPeerStateParams.peerCap.peerCurrOperClass, + smeTdlsPeerStateParams.peerCap.selfCurrOperClass, + smeTdlsPeerStateParams.peerCap.peerChanLen, + smeTdlsPeerStateParams.peerCap.peerOperClassLen, + smeTdlsPeerStateParams.peerCap.prefOffChanNum, + smeTdlsPeerStateParams.peerCap.prefOffChanBandwidth, + pTdlsPeer->op_class_for_pref_off_chan); + + for (i = 0; i < pTdlsPeer->supported_channels_len; i++) + { + smeTdlsPeerStateParams.peerCap.peerChan[i] = + pTdlsPeer->supported_channels[i]; + } + smeTdlsPeerStateParams.peerCap.peerOperClassLen = + pTdlsPeer->supported_oper_classes_len; + for (i = 0; i < pTdlsPeer->supported_oper_classes_len; i++) + { + smeTdlsPeerStateParams.peerCap.peerOperClass[i] = + pTdlsPeer->supported_oper_classes[i]; + } + + halStatus = sme_UpdateTdlsPeerState(pHddCtx->hHal, + &smeTdlsPeerStateParams); + if (eHAL_STATUS_SUCCESS != halStatus) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_UpdateTdlsPeerState failed for " + MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + return -EPERM; + } + wlan_hdd_tdls_increment_peer_count(pAdapter); + } + wlan_hdd_tdls_check_bmps(pAdapter); + + /* Update TL about the UAPSD masks , to route the packets to firmware */ + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta) + || pHddCtx->cfg_ini->fTDLSUapsdMask ) + { + int ac; + uint8 ucAc[4] = { WLANTL_AC_VO, + WLANTL_AC_VI, + WLANTL_AC_BK, + WLANTL_AC_BE }; + uint8 tlTid[4] = { 7, 5, 2, 3 } ; + for(ac=0; ac < 4; ac++) + { + status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + pTdlsPeer->staId, ucAc[ac], + tlTid[ac], tlTid[ac], 0, 0, + WLANTL_BI_DIR, + 1, + pAdapter->sessionId ); + } + } + } + + } + break; + case NL80211_TDLS_DISABLE_LINK: + { + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE); + + if ( NULL == pTdlsPeer ) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: peer matching "MAC_ADDRESS_STR + " not found, ignore NL80211_TDLS_DISABLE_LINK", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: NL80211_TDLS_DISABLE_LINK for peer " + MAC_ADDRESS_STR " link_status: %d", + __func__, MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status); + + if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) + { + unsigned long rc; + + INIT_COMPLETION(pAdapter->tdls_del_station_comp); + + sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, peer); + + rc = wait_for_completion_timeout(&pAdapter->tdls_del_station_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA)); + if (!rc) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Del station timed out", __func__); + return -EPERM; + } + wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, + eTDLS_LINK_IDLE, + (pTdlsPeer->link_status == eTDLS_LINK_TEARING)? + eTDLS_LINK_UNSPECIFIED: + eTDLS_LINK_DROPPED_BY_REMOTE); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: TDLS Peer Station doesn't exist.", __func__); + } + } + break; + case NL80211_TDLS_TEARDOWN: + { + status = wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Error in TDLS Teardown")); + return status; + } + } + break; + case NL80211_TDLS_SETUP: + { + status = wlan_hdd_tdls_extctrl_config_peer(pAdapter, peer, + NULL, pHddCtx->cfg_ini->fTDLSPrefOffChanNum, + 0, 0, 0); + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Error in TDLS Setup")); + return status; + } + } + break; + case NL80211_TDLS_DISCOVERY_REQ: + /* We don't support in-driver setup/teardown/discovery */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: Driver doesn't support in-driver setup/teardown/discovery", + __func__); + return -ENOTSUPP; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: unsupported event", __func__); + return -ENOTSUPP; + } + EXIT(); + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) || defined(WITH_BACKPORTS) +static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const u8 *peer, + enum nl80211_tdls_operation oper) +#else +static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + u8 *peer, + enum nl80211_tdls_operation oper) +#endif +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_tdls_oper(wiphy, dev, peer, oper); + vos_ssr_unprotect(__func__); + + return ret; +} + +int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy, + struct net_device *dev, u8 *peer) +{ + hddLog(VOS_TRACE_LEVEL_INFO, + "tdls send discover req: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer)); + +#if TDLS_MGMT_VERSION2 + return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, + WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) || defined(WITH_BACKPORTS) + return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, + WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, 0, NULL, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) + return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, + WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)) + return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, + WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0); +#else + return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, + WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0); +#endif /* KERNEL_VERSION */ + +#endif +} +#endif + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/* + * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback + * Callback routine called upon receiving response for + * get offload info + */ +void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext, + tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp) +{ + + hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext; + tANI_U8 tempReplayCounter[8]; + hdd_station_ctx_t *pHddStaCtx; + + ENTER(); + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter is Null", __func__); + return ; + } + + if (NULL == pGtkOffloadGetInfoRsp) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: pGtkOffloadGetInfoRsp is Null", __func__); + return ; + } + + if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: wlan Failed to get replay counter value", + __func__); + return ; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + /* Update replay counter */ + pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter = + pGtkOffloadGetInfoRsp->ullKeyReplayCounter; + + { + /* changing from little to big endian since supplicant + * works on big endian format + */ + int i; + tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter; + + for (i = 0; i < 8; i++) + { + tempReplayCounter[7-i] = (tANI_U8)p[i]; + } + } + + /* Update replay counter to NL */ + cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId, + tempReplayCounter, GFP_KERNEL); +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_set_rekey_data + * This function is used to offload GTK rekeying job to the firmware. + */ +int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + hdd_station_ctx_t *pHddStaCtx; + tHalHandle hHal; + int result; + tSirGtkOffloadParams hddGtkOffloadReqParams; + eHalStatus status = eHAL_STATUS_FAILURE; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA, + pAdapter->sessionId, pAdapter->device_mode)); + + result = wlan_hdd_validate_context(pHddCtx); + if (0 != result) + return result; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal){ + hddLog(LOGE, FL("HAL context is Null!!!")); + return -EAGAIN; + } + + pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE; + memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN); + memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN); + memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId, + VOS_MAC_ADDR_SIZE); + { + /* changing from big to little endian since driver + * works on little endian format + */ + tANI_U8 *p = + (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter; + int i; + + for (i = 0; i < 8; i++) { + p[7-i] = data->replay_ctr[i]; + } + } + + if (TRUE == pHddCtx->hdd_wlan_suspended) { + /* if wlan is suspended, enable GTK offload directly from here */ + memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); + status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams, + pAdapter->sessionId); + + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("sme_SetGTKOffload failed, status(%d)"), status); + return -EINVAL; + } + hddLog(LOG1, FL("sme_SetGTKOffload successful")); + } else { + hddLog(LOG1, FL("wlan not suspended GTKOffload request is stored")); + } + EXIT(); + return result; +} + +int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif /*WLAN_FEATURE_GTK_OFFLOAD*/ + +/** + * __wlan_hdd_cfg80211_set_mac_acl() - Set access control policy + * @wiphy: pointer to wiphy structure + * @dev: pointer to net_device + * @params: pointer to cfg80211_acl_data + * + * Return; 0 on success, error number otherwise + */ +static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, + struct net_device *dev, + const struct cfg80211_acl_data *params) +{ + int i; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_hostapd_state_t *pHostapdState; + tsap_Config_t *pConfig; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx; + int status; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + ENTER(); + + if (NULL == params) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: params is Null", __func__); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pVosContext = pHddCtx->pvosContext; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + if (NULL == pHostapdState) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: pHostapdState is Null", __func__); + return -EINVAL; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d" + "no acl entries = %d", params->acl_policy, params->n_acl_entries); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_SET_MAC_ACL, + pAdapter->sessionId, pAdapter->device_mode)); + if (WLAN_HDD_SOFTAP == pAdapter->device_mode) { + pConfig = &pAdapter->sessionCtx.ap.sapConfig; + + /* default value */ + pConfig->num_accept_mac = 0; + pConfig->num_deny_mac = 0; + + /** + * access control policy + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in hostapd.deny file. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are + * listed in hostapd.accept file. + */ + if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) + { + pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED; + } + else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy) + { + pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Acl Policy : %d is not supported", + __func__, params->acl_policy); + return -ENOTSUPP; + } + + if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) + { + pConfig->num_accept_mac = params->n_acl_entries; + for (i = 0; i < params->n_acl_entries; i++) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "** Add ACL MAC entry %i in WhiletList :" + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(params->mac_addrs[i].addr)); + + vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } + else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) + { + pConfig->num_deny_mac = params->n_acl_entries; + for (i = 0; i < params->n_acl_entries; i++) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "** Add ACL MAC entry %i in BlackList :" + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(params->mac_addrs[i].addr)); + + vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } + +#ifdef WLAN_FEATURE_MBSSID + vos_status = WLANSAP_SetMacACL(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig); +#else + vos_status = WLANSAP_SetMacACL(pVosContext, pConfig); +#endif + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: SAP Set Mac Acl fail", __func__); + return -EINVAL; + } + } else { + hddLog(LOGE, FL("Invalid device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return -EINVAL; + } + EXIT(); + return 0; +} + +/** + * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for + * __wlan_hdd_cfg80211_set_mac_acl + * @wiphy: pointer to wiphy structure + * @dev: pointer to net_device + * @params: pointer to cfg80211_acl_data + * + * Return; 0 on success, error number otherwise + */ +static int +wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, + struct net_device *dev, + const struct cfg80211_acl_data *params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_NL80211_TESTMODE +#ifdef FEATURE_WLAN_LPHB +void wlan_hdd_cfg80211_lphb_ind_handler +( + void *pHddCtx, + tSirLPHBInd *lphbInd +) +{ + struct sk_buff *skb; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "LPHB indication arrived"); + + if (0 != wlan_hdd_validate_context((hdd_context_t *)pHddCtx)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid argument pHddCtx", __func__); + return; + } + + if (NULL == lphbInd) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid argument lphbInd", __func__); + return; + } + + skb = cfg80211_testmode_alloc_event_skb( + ((hdd_context_t *)pHddCtx)->wiphy, + sizeof(tSirLPHBInd), + GFP_ATOMIC); + if (!skb) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "LPHB timeout, NL buffer alloc fail"); + return; + } + + if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WLAN_HDD_TM_ATTR_CMD put fail"); + goto nla_put_failure; + } + if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WLAN_HDD_TM_ATTR_TYPE put fail"); + goto nla_put_failure; + } + if(nla_put(skb, WLAN_HDD_TM_ATTR_DATA, + sizeof(tSirLPHBInd), lphbInd)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WLAN_HDD_TM_ATTR_DATA put fail"); + goto nla_put_failure; + } + cfg80211_testmode_event(skb, GFP_ATOMIC); + return; + +nla_put_failure: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "NLA Put fail"); + kfree_skb(skb); + + return; +} +#endif /* FEATURE_WLAN_LPHB */ + +static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, + void *data, int len) +{ + struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1]; + int err; + hdd_context_t *pHddCtx = wiphy_priv(wiphy); +#ifdef FEATURE_WLAN_LPHB + eHalStatus smeStatus; +#endif /* FEATURE_WLAN_LPHB */ + + err = wlan_hdd_validate_context(pHddCtx); + if (err) + return err; + + ENTER(); + + err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy); + if (err) { + hddLog(LOGE, FL("Testmode INV ATTR")); + return err; + } + + if (!tb[WLAN_HDD_TM_ATTR_CMD]) { + hddLog(LOGE, FL("Testmode INV CMD")); + return -EINVAL; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_TESTMODE, + NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))); + switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) + { +#ifdef FEATURE_WLAN_LPHB + /* Low Power Heartbeat configuration request */ + case WLAN_HDD_TM_CMD_WLAN_HB: + { + int buf_len; + void *buf; + tSirLPHBReq *hb_params = NULL; + tSirLPHBReq *hb_params_temp = NULL; + + if (!tb[WLAN_HDD_TM_ATTR_DATA]) { + hddLog(LOGE, FL("Testmode INV DATA")); + return -EINVAL; + } + + buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]); + buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]); + + hb_params_temp =(tSirLPHBReq *)buf; + if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID) && + (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0)) + return -EINVAL; + + hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq)); + if (NULL == hb_params) { + hddLog(LOGE, FL("Request Buffer Alloc Fail")); + return -ENOMEM; + } + + vos_mem_copy(hb_params, buf, buf_len); + smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal), + hb_params, + wlan_hdd_cfg80211_lphb_ind_handler); + if (eHAL_STATUS_SUCCESS != smeStatus) { + hddLog(LOGE, "LPHB Config Fail, disable"); + vos_mem_free(hb_params); + } + return 0; + } +#endif /* FEATURE_WLAN_LPHB */ + +#if defined(QCA_WIFI_FTM) + case WLAN_HDD_TM_CMD_WLAN_FTM: + { + int buf_len; + void *buf; + VOS_STATUS status; + if (!tb[WLAN_HDD_TM_ATTR_DATA]) { + hddLog(LOGE, + FL("WLAN_HDD_TM_ATTR_DATA attribute is invalid")); + return -EINVAL; + } + + buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]); + buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]); + + pr_info("****FTM Tx cmd len = %d*****\n", buf_len); + + status = wlan_hdd_ftm_testmode_cmd(buf, buf_len); + + if (status != VOS_STATUS_SUCCESS) + err = -EBUSY; + break; + } +#endif + + default: + hddLog(LOGE, FL("command %d not supported"), + nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])); + return -EOPNOTSUPP; + } + EXIT(); + return err; +} + +static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#endif + void *data, int len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#if defined(QCA_WIFI_FTM) +void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len) +{ + struct sk_buff *skb; + hdd_context_t *hdd_ctx; + void *vos_global_ctx; + + if (!buf || !buf_len) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: buf or buf_len invalid, buf = %p buf_len = %zu", + __func__, buf, buf_len); + return; + } + + vos_global_ctx = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + + if (!vos_global_ctx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: voss global context invalid", + __func__); + return; + } + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_global_ctx); + + if (!hdd_ctx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: hdd context invalid", + __func__); + return; + } + + skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy, + buf_len, GFP_KERNEL); + if (!skb) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to allocate testmode rx skb!", + __func__); + return; + } + + if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) || + nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf)) + goto nla_put_failure; + + pr_info("****FTM Rx cmd len = %zu*****\n", buf_len); + + cfg80211_testmode_event(skb, GFP_KERNEL); + return; + +nla_put_failure: + kfree_skb(skb); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: nla_put failed on testmode rx skb!", + __func__); +} +#endif +#endif /* CONFIG_NL80211_TESTMODE */ + +static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, + struct net_device *dev, + int idx, struct survey_info *survey) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + tHalHandle halHandle; + v_U32_t channel = 0, freq = 0; /* Initialization Required */ + v_S7_t snr,rssi; + int status, i, j, filled = 0; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring || + 0 != pAdapter->survey_idx || + eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + /* The survey dump ops when implemented completely is expected to + * return a survey of all channels and the ops is called by the + * kernel with incremental values of the argument 'idx' till it + * returns -ENONET. But we can only support the survey for the + * operating channel for now. survey_idx is used to track + * that the ops is called only once and then return -ENONET for + * the next iteration + */ + pAdapter->survey_idx = 0; + return -ENONET; + } + + if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Roaming in progress, hence return ", __func__); + return -ENONET; + } + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + wlan_hdd_get_snr(pAdapter, &snr); + wlan_hdd_get_rssi(pAdapter, &rssi); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_DUMP_SURVEY, + pAdapter->sessionId, pAdapter->device_mode)); + sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId); + hdd_wlan_get_freq(channel, &freq); + + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + { + if (NULL == wiphy->bands[i]) + continue; + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + if (band->channels[j].center_freq == (v_U16_t)freq) + { + survey->channel = &band->channels[j]; + /* The Rx BDs contain SNR values in dB for the received frames + * while the supplicant expects noise. So we calculate and + * return the value of noise (dBm) + * SNR (dB) = RSSI (dBm) - NOISE (dBm) + */ + survey->noise = rssi - snr; + survey->filled = SURVEY_INFO_NOISE_DBM; + filled = 1; + } + } + } + + if (filled) + pAdapter->survey_idx = 1; + else + { + pAdapter->survey_idx = 0; + return -ENONET; + } + EXIT(); + return 0; +} + +static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, + struct net_device *dev, + int idx, struct survey_info *survey) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dump_survey(wiphy, dev, idx, survey); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef CHANNEL_SWITCH_SUPPORTED +/** + * __wlan_hdd_cfg80211_channel_switch()- function to switch + * channel in SAP/GO + * @wiphy: wiphy pointer + * @dev: dev pointer. + * @csa_params: Change channel params + * + * This function is called to switch channel in SAP/GO + * + * Return: 0 if success else return non zero + */ +static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *csa_params) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + v_U8_t channel; + v_U16_t freq; + int ret; + + hddLog(LOG1, FL(" Set Freq %d"), csa_params->chandef.chan->center_freq); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + + if (0 != ret) { + return ret; + } + + if ((WLAN_HDD_P2P_GO != adapter->device_mode) && + (WLAN_HDD_SOFTAP != adapter->device_mode)) + return -ENOTSUPP; + + freq = csa_params->chandef.chan->center_freq; + channel = vos_freq_to_chan(freq); + + ret = hdd_softap_set_channel_change(dev, channel); + return ret; +} + +/** + * wlan_hdd_cfg80211_channel_switch()- function to switch + * channel in SAP/GO + * @wiphy: wiphy pointer + * @dev: dev pointer. + * @csa_params: Change channel params + * + * This function is called to switch channel in SAP/GO + * + * Return: 0 if success else return non zero + */ +static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_csa_settings *csa_params) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params); + vos_ssr_unprotect(__func__); + return ret; +} +#endif + +/* + * FUNCTION: __wlan_hdd_cfg80211_resume_wlan + * this is called when cfg80211 driver resume + * driver updates latest sched_scan scan result(if any) to cfg80211 database + */ +int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + hdd_adapter_t *pAdapter; + hdd_adapter_list_node_t *pAdapterNode, *pNext; + VOS_STATUS status = VOS_STATUS_SUCCESS; + int result; + pVosSchedContext vosSchedContext = get_vos_sched_ctxt(); + + ENTER(); + + result = wlan_hdd_validate_context(pHddCtx); + if (0 != result) + return result; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + +#ifdef CONFIG_CNSS + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_MEDIUM); +#endif + + /* Resume MC thread */ + if (pHddCtx->isMcThreadSuspended) { + complete(&vosSchedContext->ResumeMcEvent); + pHddCtx->isMcThreadSuspended = FALSE; + } + +#ifdef QCA_CONFIG_SMP + /* Resume tlshim Rx thread */ + if (pHddCtx->isTlshimRxThreadSuspended) { + complete(&vosSchedContext->ResumeTlshimRxEvent); + pHddCtx->isTlshimRxThreadSuspended = FALSE; + } + +#endif + + hdd_resume_wlan(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_RESUME_WLAN, + NO_SESSION, pHddCtx->isWiphySuspended)); + spin_lock(&pHddCtx->schedScan_lock); + pHddCtx->isWiphySuspended = FALSE; + if (TRUE != pHddCtx->isSchedScanUpdatePending) { + spin_unlock(&pHddCtx->schedScan_lock); + hddLog(LOG1, FL("Return resume is not due to PNO indication")); + return 0; + } + /* Reset flag to avoid updating cfg80211 data old results again */ + pHddCtx->isSchedScanUpdatePending = FALSE; + spin_unlock(&pHddCtx->schedScan_lock); + + status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + if ((NULL != pAdapter) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)) { + if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter)) { + hddLog(LOGW, FL("NO SCAN result")); + } else { + /* Acquire wakelock to handle the case where APP's tries to + * suspend immediately after updating the scan results. This + * results in app's is in suspended state and not able to + * process the connect request to AP + */ + hdd_prevent_suspend_timeout(2000, + WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN); + cfg80211_sched_scan_results(pHddCtx->wiphy); + } + + hddLog(LOG1, FL("cfg80211 scan result database updated")); + EXIT(); + return result; + } + status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + hddLog(LOG1, FL("Failed to find Adapter")); + EXIT(); + return result; +} + +void wlan_hdd_cfg80211_ready_to_suspend(void *callbackContext, boolean suspended) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)callbackContext; + pHddCtx->suspended = suspended; + complete(&pHddCtx->ready_to_suspend); +} + +int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_resume_wlan(wiphy); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * FUNCTION: __wlan_hdd_cfg80211_suspend_wlan + * this is called when cfg80211 driver suspends + */ +int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ +#ifdef QCA_CONFIG_SMP +#define RX_TLSHIM_SUSPEND_TIMEOUT 200 /* msecs */ +#endif + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + pVosSchedContext vosSchedContext = get_vos_sched_ctxt(); + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + hdd_scaninfo_t *pScanInfo; + VOS_STATUS status; + int rc; + + ENTER(); + + rc = wlan_hdd_validate_context(pHddCtx); + if (0 != rc) + return rc; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* If RADAR detection is in progress (HDD), prevent suspend. The flag + * "dfs_cac_block_tx" is set to TRUE when RADAR is found and stay TRUE until + * CAC is done for a SoftAP which is in started state. + */ + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + if (WLAN_HDD_SOFTAP == pAdapter->device_mode) { + if (BSS_START == + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter)->bssState && + VOS_TRUE == + WLAN_HDD_GET_AP_CTX_PTR(pAdapter)->dfs_cac_block_tx) { + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("RADAR detection in progress, do not allow suspend")); + return -EAGAIN; + } else if (!pHddCtx->cfg_ini->enableSapSuspend) { + /* return -EOPNOTSUPP if SAP does not support suspend + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:SAP does not support suspend!!", __func__); + return -EOPNOTSUPP; + } + } else if (WLAN_HDD_P2P_GO == pAdapter->device_mode) { + if (!pHddCtx->cfg_ini->enableSapSuspend) { + /* return -EOPNOTSUPP if GO does not support suspend + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:GO does not support suspend!!", __func__); + return -EOPNOTSUPP; + } + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + /* Stop ongoing scan on each interface */ + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + pScanInfo = &pAdapter->scan_info; + + if (sme_staInMiddleOfRoaming(pHddCtx->hHal, pAdapter->sessionId)) { + hddLog(LOG1, FL("Roaming in progress, do not allow suspend")); + return -EAGAIN; + } + + if (pHddCtx->cfg_ini->enablePowersaveOffload && + pHddCtx->cfg_ini->fIsBmpsEnabled && + ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))) { + if (!sme_PsOffloadIsStaInPowerSave(pHddCtx->hHal, + pAdapter->sessionId)) { + hddLog(VOS_TRACE_LEVEL_DEBUG, + FL("STA is not in power save, Do not allow suspend")); + return -EAGAIN; + } + } + + if (pScanInfo->mScanPending && pAdapter->request) + { + INIT_COMPLETION(pScanInfo->abortscan_event_var); + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + + status = wait_for_completion_timeout( + &pScanInfo->abortscan_event_var, + msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN)); + if (!status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout occurred while waiting for abort scan" , + __func__); + return -ETIME; + } + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + +#ifdef IPA_OFFLOAD + /* + * Suspend IPA early before proceeding to suspend other entities like + * firmware to avoid any race conditions. + */ + if (hdd_ipa_suspend(pHddCtx)) { + hddLog(VOS_TRACE_LEVEL_DEBUG, FL("IPA not ready to suspend!")); + return -EAGAIN; + } +#endif + + /* Wait for the target to be ready for suspend */ + INIT_COMPLETION(pHddCtx->ready_to_suspend); + + hdd_suspend_wlan(&wlan_hdd_cfg80211_ready_to_suspend, pHddCtx); + + rc = wait_for_completion_timeout(&pHddCtx->ready_to_suspend, + msecs_to_jiffies(WLAN_WAIT_TIME_READY_TO_SUSPEND)); + if (!rc) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to get ready to suspend", __func__); + goto resume_tx; + } + + if (!pHddCtx->suspended) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Faied as suspend_status is wrong:%d", + __func__, pHddCtx->suspended); + goto resume_tx; + } + + /* Suspend MC thread */ + set_bit(MC_SUSPEND_EVENT_MASK, &vosSchedContext->mcEventFlag); + wake_up_interruptible(&vosSchedContext->mcWaitQueue); + + /* Wait for suspend confirmation from MC thread */ + rc = wait_for_completion_timeout(&pHddCtx->mc_sus_event_var, + msecs_to_jiffies(WLAN_WAIT_TIME_MCTHREAD_SUSPEND)); + if (!rc) + { + clear_bit(MC_SUSPEND_EVENT_MASK, &vosSchedContext->mcEventFlag); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop mc thread", __func__); + goto resume_tx; + } + + pHddCtx->isMcThreadSuspended = TRUE; + +#ifdef QCA_CONFIG_SMP + /* Suspend tlshim rx thread */ + set_bit(RX_SUSPEND_EVENT_MASK, &vosSchedContext->tlshimRxEvtFlg); + wake_up_interruptible(&vosSchedContext->tlshimRxWaitQueue); + rc = wait_for_completion_timeout( + &vosSchedContext->SuspndTlshimRxEvent, + msecs_to_jiffies(RX_TLSHIM_SUSPEND_TIMEOUT)); + if (!rc) { + clear_bit(RX_SUSPEND_EVENT_MASK, &vosSchedContext->tlshimRxEvtFlg); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop tl_shim rx thread", __func__); + goto resume_all; + } + pHddCtx->isTlshimRxThreadSuspended = TRUE; +#endif + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN, + NO_SESSION, pHddCtx->isWiphySuspended)); + pHddCtx->isWiphySuspended = TRUE; + +#ifdef CONFIG_CNSS + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); +#endif + + EXIT(); + return 0; + +#ifdef QCA_CONFIG_SMP +resume_all: + + complete(&vosSchedContext->ResumeMcEvent); + pHddCtx->isMcThreadSuspended = FALSE; +#endif + +resume_tx: + + hdd_resume_wlan(); + + return -ETIME; +} + +int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef QCA_HT_2040_COEX +/** + * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @chandef: Pointer to channel definition parameter + * + * Return: 0 for success, non-zero for failure + */ +static int +__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + VOS_STATUS status; + tSmeConfigParams smeConfig; + bool cbModeChange; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams)); + sme_GetConfigParam(pHddCtx->hHal, &smeConfig); + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20: + if (smeConfig.csrConfig.channelBondingMode24GHz != + eCSR_INI_SINGLE_CHANNEL_CENTERED) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + sme_UpdateConfig(pHddCtx->hHal, &smeConfig); + cbModeChange = TRUE; + } + break; + + case NL80211_CHAN_WIDTH_40: + if (smeConfig.csrConfig.channelBondingMode24GHz == + eCSR_INI_SINGLE_CHANNEL_CENTERED) { + if ( NL80211_CHAN_HT40MINUS == cfg80211_get_chandef_type(chandef)) + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + else + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + sme_UpdateConfig(pHddCtx->hHal, &smeConfig); + cbModeChange = TRUE; + } + break; + + default: + hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !")); + return -EINVAL; + } + + if (!cbModeChange) + return 0; + + if (WLAN_HDD_SOFTAP != pAdapter->device_mode) + return 0; + + hddLog(LOG1, FL("Channel bonding changed to %d"), + smeConfig.csrConfig.channelBondingMode24GHz); + + /* Change SAP ht2040 mode */ + status = hdd_set_sap_ht2040_mode(pAdapter, + cfg80211_get_chandef_type(chandef)); + if (status != VOS_STATUS_SUCCESS) { + hddLog(LOGE, + FL("Error!!! Cannot set SAP HT20/40 mode!")); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @chandef: Pointer to channel definition parameter + * + * Return: 0 for success, non-zero for failure + */ +static int +wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target + * @ctx: hdd global context + * @data: capabilities data + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx, + struct ext_scan_capabilities_response *data) +{ + struct hdd_ext_scan_context *context; + hdd_context_t *hdd_ctx = (hdd_context_t *)ctx; + + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx) || !data) { + hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), + data); + return; + } + + spin_lock(&hdd_context_lock); + + context = &hdd_ctx->ext_scan_context; + /* validate response received from target*/ + if (context->request_id != data->requestId) { + spin_unlock(&hdd_context_lock); + hddLog(LOGE, + FL("Target response id did not match: request_id %d resposne_id %d"), + context->request_id, data->requestId); + return; + } else { + context->capability_response = *data; + complete(&context->response_event); + } + + spin_unlock(&hdd_context_lock); + + return; +} + +/* + * define short names for the global vendor params + * used by hdd_extscan_nl_fill_bss() + */ +#define PARAM_TIME_STAMP \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP +#define PARAM_SSID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID +#define PARAM_BSSID \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID +#define PARAM_CHANNEL \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL +#define PARAM_RSSI \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI +#define PARAM_RTT \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT +#define PARAM_RTT_SD \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD +#define PARAM_BEACON_PERIOD \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD +#define PARAM_CAPABILITY \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY +#define PARAM_IE_LENGTH \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH +#define PARAM_IE_DATA \ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA + +/** hdd_extscan_nl_fill_bss() - extscan nl fill bss + * @skb: socket buffer + * @ap: bss information + * @idx: nesting index + * + * Return: 0 on success; error number otherwise + */ +static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap, + int idx) +{ + struct nlattr *nla_ap; + + nla_ap = nla_nest_start(skb, idx); + if (!nla_ap) + return -EINVAL; + + if (nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) || + nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) || + nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid) || + nla_put_u32(skb, PARAM_CHANNEL, ap->channel) || + nla_put_s32(skb, PARAM_RSSI, ap->rssi) || + nla_put_u32(skb, PARAM_RTT, ap->rtt) || + nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) || + nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) || + nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) || + nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) { + hddLog(LOGE, FL("put fail")); + return -EINVAL; + } + + if (ap->ieLength) + if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) { + hddLog(LOGE, FL("put fail")); + return -EINVAL; + } + + nla_nest_end(skb, nla_ap); + + return 0; +} +/* + * done with short names for the global vendor params + * used by hdd_extscan_nl_fill_bss() + */ +#undef PARAM_TIME_STAMP +#undef PARAM_SSID +#undef PARAM_BSSID +#undef PARAM_CHANNEL +#undef PARAM_RSSI +#undef PARAM_RTT +#undef PARAM_RTT_SD +#undef PARAM_BEACON_PERIOD +#undef PARAM_CAPABILITY +#undef PARAM_IE_LENGTH +#undef PARAM_IE_DATA + + +/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results + * @ctx: hdd global context + * @data: cached results + * + * This function reads the cached results %data, populates the NL + * attributes and sends the NL event to the upper layer. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx, + struct extscan_cached_scan_results *data) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct extscan_cached_scan_result *result; + struct hdd_ext_scan_context *context; + struct sk_buff *skb = NULL; + tSirWifiScanResult *ap; + uint32_t i, j, nl_buf_len; + bool ignore_cached_results = false; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!data) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("data is null")); + return; + } + spin_lock(&hdd_context_lock); + context = &pHddCtx->ext_scan_context; + ignore_cached_results = context->ignore_cached_results; + spin_unlock(&hdd_context_lock); + + if (ignore_cached_results) { + hddLog(LOGE, + FL("Ignore the cached results received after timeout")); + return; + } + +#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN +#define EXTSCAN_CACHED_NL_FIXED_TLV \ + (sizeof(data->request_id) + NLA_HDRLEN) + \ + (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \ + (sizeof(data->more_data) + NLA_HDRLEN) +#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \ + (sizeof(result->scan_id) + NLA_HDRLEN) + \ + (sizeof(result->flags) + NLA_HDRLEN) + \ + (sizeof(result->num_results) + NLA_HDRLEN) +#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \ + (sizeof(ap->ts) + NLA_HDRLEN) + \ + (sizeof(ap->ssid) + NLA_HDRLEN) + \ + (sizeof(ap->bssid) + NLA_HDRLEN) + \ + (sizeof(ap->channel) + NLA_HDRLEN) + \ + (sizeof(ap->rssi) + NLA_HDRLEN) + \ + (sizeof(ap->rtt) + NLA_HDRLEN) + \ + (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \ + (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \ + (sizeof(ap->capability) + NLA_HDRLEN) + \ + (sizeof(ap->ieLength) + NLA_HDRLEN) +#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \ + (ap->ieLength + NLA_HDRLEN) + + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV; + if (data->num_scan_ids) { + nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN; + nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN; + result = &data->result[0]; + for (i = 0; i < data->num_scan_ids; i++) { + nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN; + nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV; + nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN; + + ap = &result->ap[0]; + for (j = 0; j < result->num_results; j++) { + nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN; + nl_buf_len += + EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV; + if (ap->ieLength) + nl_buf_len += + EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV; + ap++; + } + result++; + } + } + + hddLog(LOG2, FL("nl_buf_len = %u"), nl_buf_len); + skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + goto fail; + } + hddLog(LOG1, "Req Id %u Num_scan_ids %u More Data %u", + data->request_id, data->num_scan_ids, data->more_data); + + result = &data->result[0]; + for (i = 0; i < data->num_scan_ids; i++) { + hddLog(LOG1, "[i=%d] scan_id %u flags %u num_results %u", + i, result->scan_id, result->flags, result->num_results); + + ap = &result->ap[0]; + for (j = 0; j < result->num_results; j++) { + /* + * Firmware returns timestamp from ext scan start till + * BSSID was cached (in micro seconds). Add this with + * time gap between system boot up to ext scan start + * to derive the time since boot when the + * BSSID was cached. + */ + ap->ts += pHddCtx->ext_scan_start_since_boot; + hddLog(LOG1, "Timestamp %llu " + "Ssid: %s " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "Rssi %d " + "RTT %u " + "RTT_SD %u " + "Beacon Period %u " + "Capability 0x%x " + "Ie length %d", + ap->ts, + ap->ssid, + MAC_ADDR_ARRAY(ap->bssid), + ap->channel, + ap->rssi, + ap->rtt, + ap->rtt_sd, + ap->beaconPeriod, + ap->capability, + ap->ieLength); + ap++; + } + result++; + } + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + data->request_id) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + data->num_scan_ids) || + nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + data->more_data)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + + if (data->num_scan_ids) { + struct nlattr *nla_results; + result = &data->result[0]; + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID, + result->scan_id)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + nla_results = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST); + if (!nla_results) + goto fail; + + for (i = 0; i < data->num_scan_ids; i++) { + struct nlattr *nla_result; + struct nlattr *nla_aps; + + nla_result = nla_nest_start(skb, i); + if(!nla_result) + goto fail; + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID, + result->scan_id) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS, + result->flags) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + result->num_results)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + + nla_aps = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); + if (!nla_aps) + goto fail; + + ap = &result->ap[0]; + for (j = 0; j < result->num_results; j++) { + if (hdd_extscan_nl_fill_bss(skb, ap, j)) + goto fail; + ap++; + } + nla_nest_end(skb, nla_aps); + nla_nest_end(skb, nla_result); + result++; + } + nla_nest_end(skb, nla_results); + } + + cfg80211_vendor_cmd_reply(skb); + + if (!data->more_data) { + spin_lock(&hdd_context_lock); + context->response_status = 0; + complete(&context->response_event); + spin_unlock(&hdd_context_lock); + } + EXIT(); + return; + +fail: + if (skb) + kfree_skb(skb); + + spin_lock(&hdd_context_lock); + context->response_status = -EINVAL; + spin_unlock(&hdd_context_lock); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hotlist match callback + * @hddctx: HDD context + * @data: event data + * + * This function reads the hotlist matched event %data and fill in the skb with + * NL attributes and send up the NL event. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, + struct extscan_hotlist_match *data) +{ + hdd_context_t *pHddCtx = ctx; + struct sk_buff *skb = NULL; + uint32_t i, index; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!data) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("data is null")); + return; + } + + if (data->ap_found) + index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX; + else + index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX; + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + index, flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + hddLog(LOG1, "Req Id: %u Num_APs: %u MoreData: %u ap_found: %u", + data->requestId, data->numOfAps, data->moreData, + data->ap_found); + + for (i = 0; i < data->numOfAps; i++) { + data->ap[i].ts = vos_get_monotonic_boottime(); + + hddLog(LOG1, "[i=%d] Timestamp %llu " + "Ssid: %s " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "Rssi %d " + "RTT %u " + "RTT_SD %u", + i, + data->ap[i].ts, + data->ap[i].ssid, + MAC_ADDR_ARRAY(data->ap[i].bssid), + data->ap[i].channel, + data->ap[i].rssi, + data->ap[i].rtt, + data->ap[i].rtt_sd); + } + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + data->requestId) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + data->numOfAps)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + + if (data->numOfAps) { + struct nlattr *aps; + + aps = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); + if (!aps) + goto fail; + + for (i = 0; i < data->numOfAps; i++) { + struct nlattr *ap; + + ap = nla_nest_start(skb, i); + if (!ap) + goto fail; + + if (nla_put_u64(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, + data->ap[i].ts) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, + sizeof(data->ap[i].ssid), + data->ap[i].ssid) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, + sizeof(data->ap[i].bssid), + data->ap[i].bssid) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, + data->ap[i].channel) || + nla_put_s32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, + data->ap[i].rssi) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, + data->ap[i].rtt) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, + data->ap[i].rtt_sd)) + goto fail; + + nla_nest_end(skb, ap); + } + nla_nest_end(skb, aps); + + if (nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + data->moreData)) + goto fail; + } + + cfg80211_vendor_event(skb, flags); + EXIT(); + return; + +fail: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_generic_rsp() - + * Handle a generic ExtScan Response message + * @ctx: HDD context registered with SME + * @response: The ExtScan response from firmware + * + * This function will handle a generic ExtScan response message from + * firmware and will communicate the result to the userspace thread + * that is waiting for the response. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_generic_rsp + (void *ctx, + struct sir_extscan_generic_response *response) +{ + hdd_context_t *hdd_ctx = ctx; + struct hdd_ext_scan_context *context; + + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx) || !response) { + hddLog(LOGE, + FL("HDD context is not valid or response(%p) is null"), + response); + return; + } + + hddLog(LOG1, FL("request %u status %d"), + response->request_id, response->status); + + context = &hdd_ctx->ext_scan_context; + spin_lock(&hdd_context_lock); + if (context->request_id == response->request_id) { + context->response_status = response->status ? -EINVAL : 0; + complete(&context->response_event); + } + spin_unlock(&hdd_context_lock); + + return; +} + +/** + * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() - + * Handle an SSID hotlist match event + * @ctx: HDD context registered with SME + * @event: The SSID hotlist match event + * + * This function will take an SSID match event that was generated by + * firmware and will convert it into a cfg80211 vendor event which is + * sent to userspace. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, + tpSirWifiScanResultEvent event) +{ + hdd_context_t *hdd_ctx = ctx; + struct sk_buff *skb; + unsigned i; + unsigned index; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx) || !event) { + hddLog(LOGE, + FL("HDD context is not valid or event(%p) is null"), + event); + return; + } + + if (event->ap_found) { + index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX; + hddLog(LOG1, "SSID hotlist found"); + } else { + index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX; + hddLog(LOG1, "SSID hotlist lost"); + } + + skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + index, flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + hddLog(LOG1, "Req Id %u, Num results %u, More Data (%u)", + event->requestId, event->numOfAps, event->moreData); + + for (i = 0; i < event->numOfAps; i++) { + hddLog(LOG1, "[i=%d] Timestamp %llu " + "Ssid: %s " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "Rssi %d " + "RTT %u " + "RTT_SD %u", + i, + event->ap[i].ts, + event->ap[i].ssid, + MAC_ADDR_ARRAY(event->ap[i].bssid), + event->ap[i].channel, + event->ap[i].rssi, + event->ap[i].rtt, + event->ap[i].rtt_sd); + } + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + event->requestId) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + event->numOfAps)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + + if (event->numOfAps) { + struct nlattr *aps; + aps = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); + if (!aps) { + hddLog(LOGE, FL("nest fail")); + goto fail; + } + + for (i = 0; i < event->numOfAps; i++) { + struct nlattr *ap; + + ap = nla_nest_start(skb, i); + if (!ap) { + hddLog(LOGE, FL("nest fail")); + goto fail; + } + + if (nla_put_u64(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, + event->ap[i].ts) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, + sizeof(event->ap[i].ssid), + event->ap[i].ssid) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, + sizeof(event->ap[i].bssid), + event->ap[i].bssid) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, + event->ap[i].channel) || + nla_put_s32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, + event->ap[i].rssi) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, + event->ap[i].rtt) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, + event->ap[i].rtt_sd)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + nla_nest_end(skb, ap); + } + nla_nest_end(skb, aps); + + if (nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + event->moreData)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + } + + cfg80211_vendor_event(skb, flags); + return; + +fail: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() - results callback + * @hddctx: HDD context + * @data: event data + * + * This function reads the event %data and fill in the skb with + * NL attributes and send up the NL event. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind( + void *ctx, + tpSirWifiSignificantChangeEvent pData) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *skb = NULL; + tSirWifiSignificantChange *ap_info; + tANI_S32 *rssi; + tANI_U32 i, j; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !pData) { + hddLog(LOGE, FL("HDD context is invalid or pData(%p) is null"), pData); + return; + } + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + hddLog(LOG1, "Req Id %u Num results %u More Data %u", pData->requestId, + pData->numResults, pData->moreData); + + ap_info = &pData->ap[0]; + for (i = 0; i < pData->numResults; i++) { + hddLog(LOG1, "[i=%d] " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "numOfRssi %d", + i, + MAC_ADDR_ARRAY(ap_info->bssid), + ap_info->channel, + ap_info->numOfRssi); + rssi = &(ap_info)->rssi[0]; + for (j = 0; j < ap_info->numOfRssi; j++) + hddLog(LOG1, "Rssi %d", *rssi++); + + ap_info += ap_info->numOfRssi * sizeof(*rssi); + } + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + pData->requestId) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + pData->numResults)) { + hddLog(LOGE, FL("put fail")); + goto fail; + } + + if (pData->numResults) { + struct nlattr *aps; + + aps = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); + if (!aps) + goto fail; + + ap_info = &pData->ap[0]; + for (i = 0; i < pData->numResults; i++) { + struct nlattr *ap; + + ap = nla_nest_start(skb, i); + if (!ap) + goto fail; + + if (nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID, + sizeof(tSirMacAddr), ap_info->bssid) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL, + ap_info->channel) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI, + ap_info->numOfRssi) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST, + sizeof(s32) * ap_info->numOfRssi, &(ap_info)->rssi[0])) + goto fail; + + nla_nest_end(skb, ap); + + ap_info += ap_info->numOfRssi * sizeof(*rssi); + } + nla_nest_end(skb, aps); + + if (nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + pData->moreData)) + goto fail; + } + + cfg80211_vendor_event(skb, flags); + return; + +fail: + kfree_skb(skb); + return; + +} + +/** + * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan results event + * @hddctx: HDD context + * @data: event data + * + * This function reads the event %data and fill in the skb with + * NL attributes and send up the NL event. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, + tpSirWifiFullScanResultEvent pData) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *skb = NULL; +#ifdef CONFIG_CNSS + struct timespec ts; +#endif + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return; + + if (!pData) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("pData is null")); + return; + } + /* + * If the full scan result including IE data exceeds NL 4K size + * limitation, drop that beacon/probe rsp frame. + */ + if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) { + hddLog(LOGE, FL("Frame exceeded NL size limilation, drop it!")); + return; + } + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + pData->ap.channel = vos_chan_to_freq(pData->ap.channel); +#ifdef CONFIG_CNSS + /* Android does not want the time stamp from the frame. + Instead it wants a monotonic increasing value since boot */ + cnss_get_monotonic_boottime(&ts); + pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); +#endif + hddLog(LOG1, "Req Id %u More Data %u", + pData->requestId, pData->moreData); + hddLog(LOG1, "AP Info: Timestamp %llu Ssid: %s " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "Rssi %d " + "RTT %u " + "RTT_SD %u " + "Bcn Period %d " + "Capability 0x%X " + "IE Length %d", + pData->ap.ts, + pData->ap.ssid, + MAC_ADDR_ARRAY(pData->ap.bssid), + pData->ap.channel, + pData->ap.rssi, + pData->ap.rtt, + pData->ap.rtt_sd, + pData->ap.beaconPeriod, + pData->ap.capability, + pData->ap.ieLength); + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + pData->requestId) || + nla_put_u64(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, + pData->ap.ts) || + nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, + sizeof(pData->ap.ssid), + pData->ap.ssid) || + nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, + sizeof(pData->ap.bssid), + pData->ap.bssid) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, + pData->ap.channel) || + nla_put_s32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, + pData->ap.rssi) || + nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, + pData->ap.rtt) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, + pData->ap.rtt_sd) || + nla_put_u16(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD, + pData->ap.beaconPeriod) || + nla_put_u16(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY, + pData->ap.capability) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH, + pData->ap.ieLength) || + nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + pData->moreData)) { + hddLog(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + if (pData->ap.ieLength) { + if (nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA, + pData->ap.ieLength, pData->ap.ieData)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, flags); + EXIT(); + return; + +nla_put_failure: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found + * @hddctx: HDD context + * @data: matched network data + * + * This function reads the matched network data and fills NL vendor attributes + * and send it to upper layer. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: 0 on success, error number otherwise + */ +static void +wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx, + struct pno_match_found *data) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *skb = NULL; + uint32_t len, i; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !data) { + hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), + data); + return; + } + + /* + * If the number of match found APs including IE data exceeds NL 4K size + * limitation, drop that beacon/probe rsp frame. + */ + len = sizeof(*data) + + (data->num_results + sizeof(tSirWifiScanResult)); + for (i = 0; i < data->num_results; i++) { + len += data->ap[i].ieLength; + } + if (len >= EXTSCAN_EVENT_BUF_SIZE) { + hddLog(LOGE, FL("Frame exceeded NL size limitation, drop it!")); + return; +} + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + hddLog(LOG1, "Req Id %u More Data %u num_results %d", + data->request_id, data->more_data, data->num_results); + for (i = 0; i < data->num_results; i++) { + data->ap[i].channel = vos_chan_to_freq(data->ap[i].channel); + hddLog(LOG1, "AP Info: Timestamp %llu Ssid: %s " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "Rssi %d " + "RTT %u " + "RTT_SD %u " + "Bcn Period %d " + "Capability 0x%X " + "IE Length %d", + data->ap[i].ts, + data->ap[i].ssid, + MAC_ADDR_ARRAY(data->ap[i].bssid), + data->ap[i].channel, + data->ap[i].rssi, + data->ap[i].rtt, + data->ap[i].rtt_sd, + data->ap[i].beaconPeriod, + data->ap[i].capability, + data->ap[i].ieLength); + } + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + data->request_id) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + data->num_results) || + nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + data->more_data)) { + hddLog(LOGE, FL("nla put fail")); + goto fail; + } + + if (data->num_results) { + struct nlattr *nla_aps; + nla_aps = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); + if (!nla_aps) + goto fail; + + for (i = 0; i < data->num_results; i++) { + if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i)) + goto fail; + } + nla_nest_end(skb, nla_aps); + } + + cfg80211_vendor_event(skb, flags); + return; + +fail: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan available event + * @hddctx: HDD context + * @data: event data + * + * This function reads the event %data and fill in the skb with + * NL attributes and send up the NL event. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_scan_res_available_event(void *ctx, + tpSirExtScanResultsAvailableIndParams pData) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *skb = NULL; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!pData) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("pData is null")); + return; + } + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + hddLog(LOG1, "Req Id %u Num results %u", pData->requestId, + pData->numResultsAvailable); + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + pData->requestId) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + pData->numResultsAvailable)) { + hddLog(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, flags); + EXIT(); + return; + +nla_put_failure: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event + * @hddctx: HDD context + * @data: event data + * + * This function reads the event %data and fill in the skb with + * NL attributes and send up the NL event. + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, + tpSirExtScanOnScanEventIndParams pData) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + struct sk_buff *skb = NULL; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!pData) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("pData is null")); + return; + } + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + hddLog(LOG1, "Request Id %u Scan event type %u Scan event status %u", + pData->requestId, pData->scanEventType, pData->status); + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + pData->requestId) || + nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE, + pData->scanEventType) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_STATUS, + pData->status)) { + hddLog(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, flags); + EXIT(); + return; + +nla_put_failure: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found + * @hddctx: HDD context + * @data: matched network data + * + * This function reads the match network %data and fill in the skb with + * NL attributes and send up the NL event + * This callback execute in atomic context and must not invoke any + * blocking calls. + * + * Return: none + */ +static void +wlan_hdd_cfg80211_passpoint_match_found(void *ctx, + struct wifi_passpoint_match *data) +{ + hdd_context_t *pHddCtx = ctx; + struct sk_buff *skb = NULL; + uint32_t len, i, num_matches = 1, more_data = 0; + struct nlattr *nla_aps; + struct nlattr *nla_bss; + int flags = vos_get_gfp_flags(); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !data) { + hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), + data); + return; + } + + len = sizeof(*data) + data->ap.ieLength + data->anqp_len; + if (len >= EXTSCAN_EVENT_BUF_SIZE) { + hddLog(LOGE, FL("Result exceeded NL size limitation, drop it")); + return; + } + + skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX, + flags); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + hddLog(LOG1, "Req Id %u Id %u ANQP length %u num_matches %u", + data->request_id, data->id, data->anqp_len, num_matches); + for (i = 0; i < num_matches; i++) { + hddLog(LOG1, "AP Info: Timestamp %llu Ssid: %s " + "Bssid (" MAC_ADDRESS_STR ") " + "Channel %u " + "Rssi %d " + "RTT %u " + "RTT_SD %u " + "Bcn Period %d " + "Capability 0x%X " + "IE Length %d", + data->ap.ts, + data->ap.ssid, + MAC_ADDR_ARRAY(data->ap.bssid), + data->ap.channel, + data->ap.rssi, + data->ap.rtt, + data->ap.rtt_sd, + data->ap.beaconPeriod, + data->ap.capability, + data->ap.ieLength); + } + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + data->request_id) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES, + num_matches) || + nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, + more_data)) { + hddLog(LOGE, FL("nla put fail")); + goto fail; + } + + nla_aps = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST); + if (!nla_aps) + goto fail; + + for (i = 0; i < num_matches; i++) { + struct nlattr *nla_ap; + + nla_ap = nla_nest_start(skb, i); + if (!nla_ap) + goto fail; + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID, + data->id) || + nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN, + data->anqp_len)) { + goto fail; + } + + if (data->anqp_len) + if (nla_put(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP, + data->anqp_len, data->anqp)) + goto fail; + + nla_bss = nla_nest_start(skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); + if (!nla_bss) + goto fail; + + if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0)) + goto fail; + nla_nest_end(skb, nla_bss); + nla_nest_end(skb, nla_ap); + } + nla_nest_end(skb, nla_aps); + + cfg80211_vendor_event(skb, flags); + return; + +fail: + kfree_skb(skb); + return; +} + +void wlan_hdd_cfg80211_extscan_callback(void *ctx, const tANI_U16 evType, + void *pMsg) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)ctx; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) + return; + + hddLog(LOG1, FL("Rcvd Event %d"), evType); + + switch (evType) { + case eSIR_EXTSCAN_CACHED_RESULTS_RSP: + /* There is no need to send this response to upper layer + Just log the message */ + hddLog(LOG2, FL("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP")); + break; + + case eSIR_EXTSCAN_GET_CAPABILITIES_IND: + wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx, + (struct ext_scan_capabilities_response *)pMsg); + break; + + case eSIR_EXTSCAN_HOTLIST_MATCH_IND: + wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg); + break; + + case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND: + wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind( + ctx, + (tpSirWifiSignificantChangeEvent)pMsg); + break; + + case eSIR_EXTSCAN_CACHED_RESULTS_IND: + wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg); + break; + + case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND: + wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx, + (tpSirExtScanResultsAvailableIndParams)pMsg); + break; + + case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND: + wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx, + (tpSirWifiFullScanResultEvent)pMsg); + break; + + case eSIR_EPNO_NETWORK_FOUND_IND: + wlan_hdd_cfg80211_extscan_epno_match_found(ctx, + (struct pno_match_found *)pMsg); + break; + + case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND: + wlan_hdd_cfg80211_extscan_scan_progress_event(ctx, + (tpSirExtScanOnScanEventIndParams)pMsg); + break; + + case eSIR_PASSPOINT_NETWORK_FOUND_IND: + wlan_hdd_cfg80211_passpoint_match_found(ctx, + (struct wifi_passpoint_match *) pMsg); + break; + + case eSIR_EXTSCAN_START_RSP: + case eSIR_EXTSCAN_STOP_RSP: + case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP: + case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP: + case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP: + case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP: + case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP: + case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP: + wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg); + break; + + case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND: + wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx, + (tpSirWifiScanResultEvent)pMsg); + break; + + default: + hddLog(LOGE, FL("Unknown event type %u"), evType); + break; + } + EXIT(); +} + +#endif /* FEATURE_WLAN_EXTSCAN */ + + +/* cfg80211_ops */ +static struct cfg80211_ops wlan_hdd_cfg80211_ops = +{ + .add_virtual_intf = wlan_hdd_add_virtual_intf, + .del_virtual_intf = wlan_hdd_del_virtual_intf, + .change_virtual_intf = wlan_hdd_cfg80211_change_iface, + .change_station = wlan_hdd_change_station, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) && !defined(WITH_BACKPORTS) + .add_beacon = wlan_hdd_cfg80211_add_beacon, + .del_beacon = wlan_hdd_cfg80211_del_beacon, + .set_beacon = wlan_hdd_cfg80211_set_beacon, +#else + .start_ap = wlan_hdd_cfg80211_start_ap, + .change_beacon = wlan_hdd_cfg80211_change_beacon, + .stop_ap = wlan_hdd_cfg80211_stop_ap, +#endif + .change_bss = wlan_hdd_cfg80211_change_bss, + .add_key = wlan_hdd_cfg80211_add_key, + .get_key = wlan_hdd_cfg80211_get_key, + .del_key = wlan_hdd_cfg80211_del_key, + .set_default_key = wlan_hdd_cfg80211_set_default_key, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + .set_channel = wlan_hdd_cfg80211_set_channel, +#endif + .scan = wlan_hdd_cfg80211_scan, + .connect = wlan_hdd_cfg80211_connect, + .disconnect = wlan_hdd_cfg80211_disconnect, + .join_ibss = wlan_hdd_cfg80211_join_ibss, + .leave_ibss = wlan_hdd_cfg80211_leave_ibss, + .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params, + .set_tx_power = wlan_hdd_cfg80211_set_txpower, + .get_tx_power = wlan_hdd_cfg80211_get_txpower, + .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel, + .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel, + .mgmt_tx = wlan_hdd_mgmt_tx, + .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait, + .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key, + .set_txq_params = wlan_hdd_set_txq_params, + .get_station = wlan_hdd_cfg80211_get_station, + .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt, + .del_station = wlan_hdd_cfg80211_del_station, + .add_station = wlan_hdd_cfg80211_add_station, +#ifdef FEATURE_WLAN_LFR + .set_pmksa = wlan_hdd_cfg80211_set_pmksa, + .del_pmksa = wlan_hdd_cfg80211_del_pmksa, + .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa, +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211) + .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies, +#endif +#ifdef FEATURE_WLAN_TDLS + .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt, + .tdls_oper = wlan_hdd_cfg80211_tdls_oper, +#endif +#ifdef WLAN_FEATURE_GTK_OFFLOAD + .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data, +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ +#ifdef FEATURE_WLAN_SCAN_PNO + .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start, + .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop, +#endif /*FEATURE_WLAN_SCAN_PNO */ + .resume = wlan_hdd_cfg80211_resume_wlan, + .suspend = wlan_hdd_cfg80211_suspend_wlan, + .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl, +#ifdef WLAN_NL80211_TESTMODE + .testmode_cmd = wlan_hdd_cfg80211_testmode, +#endif +#ifdef QCA_HT_2040_COEX + .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width, +#endif + .dump_survey = wlan_hdd_cfg80211_dump_survey, +#ifdef CHANNEL_SWITCH_SUPPORTED + .channel_switch = wlan_hdd_cfg80211_channel_switch, +#endif + +}; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_debugfs.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_debugfs.c new file mode 100644 index 000000000000..5871ae6a54af --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_debugfs.c @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef WLAN_OPEN_SOURCE +#include +#include +#include + +#define MAX_USER_COMMAND_SIZE_WOWL_ENABLE 8 +#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512 +#define MAX_USER_COMMAND_SIZE_FRAME 4096 + +/** + * __wcnss_wowenable_write() - write wow enable + * @file: file pointer + * @buf: buffer + * @count: count + * @ppos: position pointer + * + * Return: 0 on success, error number otherwise + */ +static ssize_t __wcnss_wowenable_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + + hdd_adapter_t *pAdapter; + hdd_context_t *hdd_ctx; + char cmd[MAX_USER_COMMAND_SIZE_WOWL_ENABLE + 1]; + char *sptr, *token; + v_U8_t wow_enable = 0; + v_U8_t wow_mp = 0; + v_U8_t wow_pbm = 0; + int ret; + + ENTER(); + + pAdapter = (hdd_adapter_t *)file->private_data; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Invalid adapter or adapter has invalid magic.", + __func__); + + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!sme_IsFeatureSupportedByFW(WOW)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Wake-on-Wireless feature is not supported " + "in firmware!", __func__); + + return -EINVAL; + } + + if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Command length is larger than %d bytes.", + __func__, MAX_USER_COMMAND_SIZE_WOWL_ENABLE); + + return -EINVAL; + } + + /* Get command from user */ + if (copy_from_user(cmd, buf, count)) + return -EFAULT; + cmd[count] = '\0'; + sptr = cmd; + + /* Get enable or disable wow */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &wow_enable)) + return -EINVAL; + + /* Disable wow */ + if (!wow_enable) { + if (!hdd_exit_wowl(pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: hdd_exit_wowl failed!", __func__); + + return -EFAULT; + } + + return count; + } + + /* Get enable or disable magic packet mode */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &wow_mp)) + return -EINVAL; + if (wow_mp > 1) + wow_mp = 1; + + /* Get enable or disable pattern byte matching mode */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &wow_pbm)) + return -EINVAL; + if (wow_pbm > 1) + wow_pbm = 1; + + if (!hdd_enter_wowl(pAdapter, wow_mp, wow_pbm)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: hdd_enter_wowl failed!", __func__); + + return -EFAULT; + } + EXIT(); + return count; +} + +/** + * wcnss_wowenable_write() - SSR wrapper for wcnss_wowenable_write + * @file: file pointer + * @buf: buffer + * @count: count + * @ppos: position pointer + * + * Return: 0 on success, error number otherwise + */ +static ssize_t wcnss_wowenable_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + + vos_ssr_protect(__func__); + ret = __wcnss_wowenable_write(file, buf, count, ppos); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wcnss_wowpattern_write() - write wow pattern + * @file: file pointer + * @buf: buffer + * @count: count + * @ppos: position pointer + * + * Return: 0 on success, error number otherwise + */ +static ssize_t __wcnss_wowpattern_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data; + hdd_context_t *hdd_ctx; + char cmd[MAX_USER_COMMAND_SIZE_WOWL_PATTERN + 1]; + char *sptr, *token; + v_U8_t pattern_idx = 0; + v_U8_t pattern_offset = 0; + char *pattern_buf; + char *pattern_mask; + int ret; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Invalid adapter or adapter has invalid magic.", + __func__); + + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!sme_IsFeatureSupportedByFW(WOW)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Wake-on-Wireless feature is not supported " + "in firmware!", __func__); + + return -EINVAL; + } + + if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Command length is larger than %d bytes.", + __func__, MAX_USER_COMMAND_SIZE_WOWL_PATTERN); + + return -EINVAL; + } + + /* Get command from user */ + if (copy_from_user(cmd, buf, count)) + return -EFAULT; + cmd[count] = '\0'; + sptr = cmd; + + /* Get pattern idx */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + + if (kstrtou8(token, 0, &pattern_idx)) + return -EINVAL; + + /* Get pattern offset */ + token = strsep(&sptr, " "); + + /* Delete pattern if no further argument */ + if (!token) { + hdd_del_wowl_ptrn_debugfs(pAdapter, pattern_idx); + + return count; + } + + if (kstrtou8(token, 0, &pattern_offset)) + return -EINVAL; + + /* Get pattern */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + + pattern_buf = token; + + /* Get pattern mask */ + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + + pattern_mask = token; + pattern_mask[strlen(pattern_mask) - 1] = '\0'; + + hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset, + pattern_buf, pattern_mask); + EXIT(); + return count; +} + +/** + * wcnss_wowpattern_write() - SSR wrapper for __wcnss_wowpattern_write + * @file: file pointer + * @buf: buffer + * @count: count + * @ppos: position pointer + * + * Return: 0 on success, error number otherwise + */ +static ssize_t wcnss_wowpattern_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + + vos_ssr_protect(__func__); + ret = __wcnss_wowpattern_write(file, buf, count, ppos); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wcnss_patterngen_write() - write pattern + * @file: file pointer + * @buf: buffer + * @count: count + * @ppos: position pointer + * + * Return: 0 on success, error number otherwise + */ +static ssize_t __wcnss_patterngen_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + hdd_adapter_t *pAdapter; + hdd_context_t *pHddCtx; + tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams; + tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams; + + char *cmd, *sptr, *token; + v_U8_t pattern_idx = 0; + v_U8_t pattern_duration = 0; + char *pattern_buf; + v_U16_t pattern_len = 0; + v_U16_t i = 0; + int ret; + + ENTER(); + + pAdapter = (hdd_adapter_t *)file->private_data; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Invalid adapter or adapter has invalid magic.", + __func__); + + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (!sme_IsFeatureSupportedByFW(WLAN_PERIODIC_TX_PTRN)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Periodic Tx Pattern Offload feature is not supported " + "in firmware!", __func__); + return -EINVAL; + } + + /* Get command from user */ + if (count <= MAX_USER_COMMAND_SIZE_FRAME) + cmd = vos_mem_malloc(count + 1); + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Command length is larger than %d bytes.", + __func__, MAX_USER_COMMAND_SIZE_FRAME); + + return -EINVAL; + } + + if (!cmd) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation for cmd failed!", __func__); + + return -EFAULT; + } + + if (copy_from_user(cmd, buf, count)) + { + vos_mem_free(cmd); + return -EFAULT; + } + cmd[count] = '\0'; + sptr = cmd; + + /* Get pattern idx */ + token = strsep(&sptr, " "); + if (!token) + goto failure; + if (kstrtou8(token, 0, &pattern_idx)) + goto failure; + + if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Pattern index %d is not in the range (0 ~ %d).", + __func__, pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1); + + goto failure; + } + + /* Get pattern duration */ + token = strsep(&sptr, " "); + if (!token) + goto failure; + if (kstrtou8(token, 0, &pattern_duration)) + goto failure; + + /* Delete pattern using index if duration is 0 */ + if (!pattern_duration) + { + delPeriodicTxPtrnParams = + vos_mem_malloc(sizeof(tSirDelPeriodicTxPtrn)); + if (!delPeriodicTxPtrnParams) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation for delPeriodicTxPtrnParams " + "failed!", __func__); + + vos_mem_free(cmd); + return -EFAULT; + } + delPeriodicTxPtrnParams->ucPtrnId = pattern_idx; + delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx; + vos_mem_copy(delPeriodicTxPtrnParams->macAddress, + pAdapter->macAddressCurrent.bytes, 6); + + /* Delete pattern */ + if (eHAL_STATUS_SUCCESS != sme_DelPeriodicTxPtrn(pHddCtx->hHal, + delPeriodicTxPtrnParams)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_DelPeriodicTxPtrn() failed!", __func__); + + vos_mem_free(delPeriodicTxPtrnParams); + goto failure; + } + vos_mem_free(cmd); + vos_mem_free(delPeriodicTxPtrnParams); + return count; + } + + /* Check if it's in connected state only when adding patterns */ + if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Not in Connected state!", __func__); + + goto failure; + } + + /* Get pattern */ + token = strsep(&sptr, " "); + if (!token) + goto failure; + + pattern_buf = token; + pattern_buf[strlen(pattern_buf) - 1] = '\0'; + pattern_len = strlen(pattern_buf); + + /* Since the pattern is a hex string, 2 characters represent 1 byte. */ + if (pattern_len % 2) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Malformed pattern!", __func__); + + goto failure; + } + else + pattern_len >>= 1; + + if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Not an 802.3 frame!", __func__); + + goto failure; + } + + addPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirAddPeriodicTxPtrn)); + if (!addPeriodicTxPtrnParams) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation for addPeriodicTxPtrnParams " + "failed!", __func__); + + vos_mem_free(cmd); + return -EFAULT; + } + + addPeriodicTxPtrnParams->ucPtrnId = pattern_idx; + addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500; + addPeriodicTxPtrnParams->ucPtrnSize = pattern_len; + vos_mem_copy(addPeriodicTxPtrnParams->macAddress, + pAdapter->macAddressCurrent.bytes, 6); + + /* Extract the pattern */ + for(i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) + { + addPeriodicTxPtrnParams->ucPattern[i] = + (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]); + + /* Skip to next byte */ + pattern_buf += 2; + } + + /* Add pattern */ + if (eHAL_STATUS_SUCCESS != sme_AddPeriodicTxPtrn(pHddCtx->hHal, + addPeriodicTxPtrnParams)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AddPeriodicTxPtrn() failed!", __func__); + + vos_mem_free(addPeriodicTxPtrnParams); + goto failure; + } + vos_mem_free(cmd); + vos_mem_free(addPeriodicTxPtrnParams); + EXIT(); + return count; + +failure: + vos_mem_free(cmd); + return -EINVAL; +} + +/** + * wcnss_patterngen_write() - SSR wrapper for __wcnss_patterngen_write + * @file: file pointer + * @buf: buffer + * @count: count + * @ppos: position pointer + * + * Return: 0 on success, error number otherwise + */ +static ssize_t wcnss_patterngen_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + + vos_ssr_protect(__func__); + ret = __wcnss_patterngen_write(file, buf, count, ppos); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wcnss_debugfs_open() - open debugfs + * @inode: inode pointer + * @file: file pointer + * + * Return: 0 on success, error number otherwise + */ +static int __wcnss_debugfs_open(struct inode *inode, struct file *file) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + if (inode->i_private) + file->private_data = inode->i_private; + + adapter = (hdd_adapter_t *)file->private_data; + if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Invalid adapter or adapter has invalid magic.", + __func__); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + EXIT(); + return 0; +} + +/** + * wcnss_debugfs_open() - SSR wrapper for __wcnss_debugfs_open + * @inode: inode pointer + * @file: file pointer + * + * Return: 0 on success, error number otherwise + */ +static int wcnss_debugfs_open(struct inode *inode, struct file *file) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wcnss_debugfs_open(inode, file); + vos_ssr_unprotect(__func__); + + return ret; +} + +static const struct file_operations fops_wowenable = { + .write = wcnss_wowenable_write, + .open = wcnss_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static const struct file_operations fops_wowpattern = { + .write = wcnss_wowpattern_write, + .open = wcnss_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static const struct file_operations fops_patterngen = { + .write = wcnss_patterngen_write, + .open = wcnss_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + pHddCtx->debugfs_phy = debugfs_create_dir("wlan_wcnss", 0); + + if (NULL == pHddCtx->debugfs_phy) + return VOS_STATUS_E_FAILURE; + + if (NULL == debugfs_create_file("wow_enable", S_IRUSR | S_IWUSR, + pHddCtx->debugfs_phy, pAdapter, &fops_wowenable)) + return VOS_STATUS_E_FAILURE; + + if (NULL == debugfs_create_file("wow_pattern", S_IRUSR | S_IWUSR, + pHddCtx->debugfs_phy, pAdapter, &fops_wowpattern)) + return VOS_STATUS_E_FAILURE; + + if (NULL == debugfs_create_file("pattern_gen", S_IRUSR | S_IWUSR, + pHddCtx->debugfs_phy, pAdapter, &fops_patterngen)) + return VOS_STATUS_E_FAILURE; + + return VOS_STATUS_SUCCESS; +} + +void hdd_debugfs_exit(hdd_context_t *pHddCtx) +{ + debugfs_remove_recursive(pHddCtx->debugfs_phy); +} +#endif /* #ifdef WLAN_OPEN_SOURCE */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dev_pwr.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dev_pwr.c new file mode 100644 index 000000000000..f30edac4607b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dev_pwr.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 03/29/11 tbh Created module. + + ==========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include +#include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------- + * Global variables. + *-------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + * Local variables. + *-------------------------------------------------------------------------*/ +/* Reference VoIP, 100msec delay make disconnect. + * So TX sleep must be less than 100msec + * Every 20msec TX frame will goes out. + * 10 frame means 2seconds TX operation */ +static const hdd_tmLevelAction_t thermalMigrationAction[WLAN_HDD_TM_LEVEL_MAX] = +{ + /* TM Level 0, Do nothing, just normal operation */ + {1, 0, 0, 0, 0xFFFFF}, + /* Tm Level 1, disable TX AMPDU */ + {0, 0, 0, 0, 0xFFFFF}, + /* TM Level 2, disable AMDPU, + * TX sleep 100msec if TX frame count is larger than 16 during 300msec */ + {0, 0, 100, 300, 16}, + /* TM Level 3, disable AMDPU, + * TX sleep 500msec if TX frame count is larger than 11 during 500msec */ + {0, 0, 500, 500, 11}, + /* TM Level 4, MAX TM level, enter IMPS */ + {0, 1, 1000, 500, 10} +}; +#ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY +static bool suspend_notify_sent; +#endif + + +/*---------------------------------------------------------------------------- + + @brief TX frame block timeout handler + Resume TX, and reset TX frame count + + @param hdd_context_t pHddCtx + Global hdd context + + @return NONE + +----------------------------------------------------------------------------*/ +void hddDevTmTxBlockTimeoutHandler(void *usrData) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)usrData; + hdd_adapter_t *staAdapater; + /* Sanity, This should not happen */ + if(NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, + "%s: NULL Context", __func__); + VOS_ASSERT(0); + return; + } + + staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + + if ((NULL == staAdapater) || + (WLAN_HDD_ADAPTER_MAGIC != staAdapater->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, + FL("invalid Adapter %p"), staAdapater); + VOS_ASSERT(0); + return; + } + + if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, + "%s: Acquire lock fail", __func__); + return; + } + pHddCtx->tmInfo.txFrameCount = 0; + + /* Resume TX flow */ + + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(staAdapater->dev); + pHddCtx->tmInfo.qBlocked = VOS_FALSE; + mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); + + return; +} + +/*---------------------------------------------------------------------------- + + @brief Register function + Register Thermal Mitigation Level Changed handle callback function + + @param hdd_context_t pHddCtx + Global hdd context + + @return General status code + VOS_STATUS_SUCCESS Registration Success + VOS_STATUS_E_FAILURE Registration Fail + +----------------------------------------------------------------------------*/ +VOS_STATUS hddDevTmRegisterNotifyCallback(hdd_context_t *pHddCtx) +{ + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO, + "%s: Register TM Handler", __func__); + + wcnss_register_thermal_mitigation(pHddCtx->parent_dev ,hddDevTmLevelChangedHandler); + + /* Set Default TM Level as Lowest, do nothing */ + pHddCtx->tmInfo.currentTmLevel = WLAN_HDD_TM_LEVEL_0; + vos_mem_zero(&pHddCtx->tmInfo.tmAction, sizeof(hdd_tmLevelAction_t)); + vos_timer_init(&pHddCtx->tmInfo.txSleepTimer, + VOS_TIMER_TYPE_SW, + hddDevTmTxBlockTimeoutHandler, + (void *)pHddCtx); + mutex_init(&pHddCtx->tmInfo.tmOperationLock); + pHddCtx->tmInfo.txFrameCount = 0; + pHddCtx->tmInfo.blockedQueue = NULL; + pHddCtx->tmInfo.qBlocked = VOS_FALSE; + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + @brief Un-Register function + Un-Register Thermal Mitigation Level Changed handle callback function + + @param hdd_context_t pHddCtx + Global hdd context + + @return General status code + VOS_STATUS_SUCCESS Un-Registration Success + VOS_STATUS_E_FAILURE Un-Registration Fail + +----------------------------------------------------------------------------*/ +VOS_STATUS hddDevTmUnregisterNotifyCallback(hdd_context_t *pHddCtx) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + wcnss_unregister_thermal_mitigation(hddDevTmLevelChangedHandler); + + if(VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer)) + { + vosStatus = vos_timer_stop(&pHddCtx->tmInfo.txSleepTimer); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Timer stop fail", __func__); + } + } + + // Destroy the vos timer... + vosStatus = vos_timer_destroy(&pHddCtx->tmInfo.txSleepTimer); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, + "%s: Fail to destroy timer", __func__); + } + + return VOS_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dp_utils.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dp_utils.c new file mode 100644 index 000000000000..16a153151295 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_dp_utils.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**============================================================================= + wlan_hdd_dp_utils.c + + \brief Utility functions for data path module + + Description... + + ==============================================================================**/ +/* $HEADER$ */ + +/**----------------------------------------------------------------------------- + Include files + ----------------------------------------------------------------------------*/ +#include +#include +#include + +/**----------------------------------------------------------------------------- + Preprocessor definitions and constants + ----------------------------------------------------------------------------*/ + +/**----------------------------------------------------------------------------- + Type declarations + ----------------------------------------------------------------------------*/ + +/**----------------------------------------------------------------------------- + Function declarations and documentation + ----------------------------------------------------------------------------*/ + + +VOS_STATUS hdd_list_insert_front( hdd_list_t *pList, hdd_list_node_t *pNode ) +{ + list_add( pNode, &pList->anchor ); + pList->count++; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_insert_back( hdd_list_t *pList, hdd_list_node_t *pNode ) +{ + list_add_tail( pNode, &pList->anchor ); + pList->count++; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_insert_back_size( hdd_list_t *pList, hdd_list_node_t *pNode, v_SIZE_t *pSize ) +{ + list_add_tail( pNode, &pList->anchor ); + pList->count++; + *pSize = pList->count; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_remove_front( hdd_list_t *pList, hdd_list_node_t **ppNode ) +{ + struct list_head * listptr; + + if ( list_empty( &pList->anchor ) ) + { + return VOS_STATUS_E_EMPTY; + } + + listptr = pList->anchor.next; + *ppNode = listptr; + list_del(pList->anchor.next); + pList->count--; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_remove_back( hdd_list_t *pList, hdd_list_node_t **ppNode ) +{ + struct list_head * listptr; + + if ( list_empty( &pList->anchor ) ) + { + return VOS_STATUS_E_EMPTY; + } + + listptr = pList->anchor.prev; + *ppNode = listptr; + list_del(pList->anchor.prev); + pList->count--; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_remove_node( hdd_list_t *pList, + hdd_list_node_t *pNodeToRemove ) +{ + hdd_list_node_t *tmp; + int found = 0; + + if ( list_empty( &pList->anchor ) ) + { + return VOS_STATUS_E_EMPTY; + } + + // verify that pNodeToRemove is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNodeToRemove) + { + found = 1; + break; + } + } + if (found == 0) + return VOS_STATUS_E_INVAL; + + list_del(pNodeToRemove); + pList->count--; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_peek_front( hdd_list_t *pList, + hdd_list_node_t **ppNode ) +{ + struct list_head * listptr; + if ( list_empty( &pList->anchor ) ) + { + return VOS_STATUS_E_EMPTY; + } + + listptr = pList->anchor.next; + *ppNode = listptr; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_list_peek_next( hdd_list_t *pList, hdd_list_node_t *pNode, + hdd_list_node_t **ppNode ) +{ + struct list_head * listptr; + int found = 0; + hdd_list_node_t *tmp; + + if ( ( pList == NULL) || ( pNode == NULL) || (ppNode == NULL)) + { + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + return VOS_STATUS_E_EMPTY; + } + + // verify that pNode is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNode) + { + found = 1; + break; + } + } + + if (found == 0) + { + return VOS_STATUS_E_INVAL; + } + + listptr = pNode->next; + if (listptr == &pList->anchor) + { + return VOS_STATUS_E_EMPTY; + } + + *ppNode = listptr; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_string_to_hex( char *pSrcMac, int length, char *pDescMac ) +{ + int i; + int k; + char temp[3] = {0}; + int rv; + + //18 is MAC Address length plus the colons + if ( !pSrcMac && (length > 18 || length < 18) ) + { + return VOS_STATUS_E_FAILURE; + } + i = k = 0; + while ( i < length ) + { + memcpy(temp, pSrcMac+i, 2); + rv = kstrtou8(temp, 16, &pDescMac[k++]); + if (rv < 0) + return VOS_STATUS_E_FAILURE; + i += 3; + } + + return VOS_STATUS_SUCCESS; +} + +#ifdef QCA_FEATURE_RPS +/** + * hdd_dp_util_send_rps_ind() - send rps indication to daemon + * @hdd_ctxt: hdd context pointer + * + * If RPS feature enabled by INI, send RPS enable indication to daemon + * Indication contents is the name of interface to find correct sysfs node + * Should send all available interfaces + * + * Return: none + */ +void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt) +{ + int i = 0; + uint8_t cpu_map_list_len = 0; + hdd_adapter_t *adapter; + hdd_adapter_list_node_t *adapter_node, *next; + VOS_STATUS status = VOS_STATUS_SUCCESS; + struct wlan_rps_data rps_data; + + rps_data.num_queues = NUM_TX_QUEUES; + + hddLog(LOG1, FL("cpu_map_list '%s'"), hdd_ctxt->cfg_ini->cpu_map_list); + + /* in case no cpu map list is provided, simply return */ + if (!strlen(hdd_ctxt->cfg_ini->cpu_map_list)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("no cpu map list found")); + return; + } + + if (VOS_STATUS_SUCCESS != + hdd_hex_string_to_u16_array(hdd_ctxt->cfg_ini->cpu_map_list, + rps_data.cpu_map_list, + &cpu_map_list_len, + WLAN_SVC_IFACE_NUM_QUEUES)) { + return; + } + + rps_data.num_queues = + (cpu_map_list_len < rps_data.num_queues) ? + cpu_map_list_len : rps_data.num_queues; + + for (i = 0; i < rps_data.num_queues; i++) { + hddLog(LOG1, FL("cpu_map_list[%d] = 0x%x"), + i, rps_data.cpu_map_list[i]); + } + + status = hdd_get_front_adapter (hdd_ctxt, &adapter_node); + while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { + adapter = adapter_node->pAdapter; + if (NULL != adapter) { + strlcpy(rps_data.ifname, adapter->dev->name, + sizeof(rps_data.ifname)); + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_RPS_ENABLE_IND, + &rps_data, sizeof(rps_data)); + } + status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next); + adapter_node = next; + } +} +#endif /* QCA_FEATURE_RPS */ + diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c new file mode 100644 index 000000000000..d4a785df6ffe --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -0,0 +1,2284 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**============================================================================= +* wlan_hdd_early_suspend.c +* +* \brief power management functions +* +* Description + +* +==============================================================================**/ +/* $HEADER$ */ + +/**----------------------------------------------------------------------------- +* Include files +* ----------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif +#include "halTypes.h" +#include "sme_Api.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "cfgApi.h" + + +#include +#include +#include +#include +#include +#ifdef IPA_OFFLOAD +#include +#endif + +/**----------------------------------------------------------------------------- +* Preprocessor definitions and constants +* ----------------------------------------------------------------------------*/ + +/**----------------------------------------------------------------------------- +* Type declarations +* ----------------------------------------------------------------------------*/ + +/**----------------------------------------------------------------------------- +* Function and variables declarations +* ----------------------------------------------------------------------------*/ +#include "wlan_hdd_power.h" +#include "wlan_hdd_packet_filtering.h" + +#include +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#elif defined(HIF_SDIO) +#include "if_ath_sdio.h" +#endif + +#include "ol_fw.h" +/* Time in msec */ +#ifdef CONFIG_SLUB_DEBUG_ON +#define HDD_SSR_BRING_UP_TIME 40000 +#else +#define HDD_SSR_BRING_UP_TIME 30000 +#endif + +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 struct notifier_block hdd_netdev_notifier; +extern tVOS_CON_MODE hdd_get_conparam ( void ); + +static struct timer_list ssr_timer; +static bool ssr_timer_started; + +//Callback invoked by PMC to report status of standby request +void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status) +{ + hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status); + g_standby_status = status; + + if(eHAL_STATUS_SUCCESS == status) + { + pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY; + } + else + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__); + } + + complete(&pHddCtx->standby_comp_var); +} + +//Callback invoked by PMC to report status of full power request +void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status) +{ + hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status); + g_full_pwr_status = status; + + if(eHAL_STATUS_SUCCESS == status) + { + pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE; + } + else + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__); + } + + complete(&pHddCtx->full_pwr_comp_var); +} + +eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx) +{ + eHalStatus status = VOS_STATUS_SUCCESS; + unsigned long rc; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__); + INIT_COMPLETION(pHddCtx->full_pwr_comp_var); + + g_full_pwr_status = eHAL_STATUS_FAILURE; + status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx, + eSME_FULL_PWR_NEEDED_BY_HDD); + + if(status == eHAL_STATUS_PMC_PENDING) + { + //Block on a completion variable. Can't wait forever though + rc = wait_for_completion_timeout( + &pHddCtx->full_pwr_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wait on full_pwr_comp_var failed")); + } + status = g_full_pwr_status; + if(g_full_pwr_status != eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__); + VOS_ASSERT(0); + goto failure; + } + } + else if(status != eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d", + __func__, status); + VOS_ASSERT(0); + goto failure; + } + else + pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE; + +failure: + //No blocking to reduce latency. No other device should be depending on WLAN + //to finish resume and WLAN won't be instantly on after resume + return status; +} + + +//Helper routine to put the chip into standby +VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + unsigned long rc; + + //Disable IMPS/BMPS as we do not want the device to enter any power + //save mode on its own during suspend sequence + sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + + //Note we do not disable queues unnecessarily. Queues should already be disabled + //if STA is disconnected or the queue will be disabled as and when disconnect + //happens because of standby procedure. + + //Ensure that device is in full power first. There is scope for optimization + //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS. + //Core s/w needs to be optimized to handle this. Until then we request full + //power before issuing request for standby. + INIT_COMPLETION(pHddCtx->full_pwr_comp_var); + g_full_pwr_status = eHAL_STATUS_FAILURE; + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, + pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); + + if(halStatus == eHAL_STATUS_PMC_PENDING) + { + //Block on a completion variable. Can't wait forever though + rc = wait_for_completion_timeout( + &pHddCtx->full_pwr_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wait on full_pwr_comp_var failed")); + } + + if(g_full_pwr_status != eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__); + VOS_ASSERT(0); + vosStatus = VOS_STATUS_E_FAILURE; + goto failure; + } + } + else if(halStatus != eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d", + __func__, halStatus); + VOS_ASSERT(0); + vosStatus = VOS_STATUS_E_FAILURE; + goto failure; + } + + if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) { + hdd_conf_mcastbcast_filter(pHddCtx, FALSE); + pHddCtx->hdd_mcastbcast_filter_set = FALSE; + } + + //Request standby. Standby will cause the STA to disassociate first. TX queues + //will be disabled (by HDD) when STA disconnects. You do not want to disable TX + //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC + //will send this failure code in case of concurrent sessions. Power Save cannot be supported + //when there are concurrent sessions. + INIT_COMPLETION(pHddCtx->standby_comp_var); + g_standby_status = eHAL_STATUS_FAILURE; + halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx); + + if (halStatus == eHAL_STATUS_PMC_PENDING) + { + //Wait till WLAN device enters standby mode + rc = wait_for_completion_timeout(&pHddCtx->standby_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wait on standby_comp_var failed")); + } + + if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__); + VOS_ASSERT(0); + vosStatus = VOS_STATUS_E_FAILURE; + goto failure; + } + } + else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d", + __func__, halStatus); + VOS_ASSERT(0); + vosStatus = VOS_STATUS_E_FAILURE; + goto failure; + } + else + pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY; + +failure: + //Restore IMPS config + if(pHddCtx->cfg_ini->fIsImpsEnabled) + sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + + //Restore BMPS config + if(pHddCtx->cfg_ini->fIsBmpsEnabled) + sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + + return vosStatus; +} + + +//Helper routine for Deep sleep entry +VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) +{ + eHalStatus halStatus; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + unsigned long rc; + + //Stop the Interface TX queue. + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + + //Disable IMPS,BMPS as we do not want the device to enter any power + //save mode on it own during suspend sequence + sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + + //Ensure that device is in full power as we will touch H/W during vos_Stop + INIT_COMPLETION(pHddCtx->full_pwr_comp_var); + g_full_pwr_status = eHAL_STATUS_FAILURE; + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, + pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); + + if(halStatus == eHAL_STATUS_PMC_PENDING) + { + //Block on a completion variable. Can't wait forever though + rc = wait_for_completion_timeout( + &pHddCtx->full_pwr_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wait on full_pwr_comp_var failed")); + } + + if(g_full_pwr_status != eHAL_STATUS_SUCCESS){ + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__); + VOS_ASSERT(0); + } + } + else if(halStatus != eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__); + VOS_ASSERT(0); + } + + //Issue a disconnect. This is required to inform the supplicant that + //STA is getting disassociated and for GUI to be updated properly + INIT_COMPLETION(pAdapter->disconnect_comp_var); + halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + + //Success implies disconnect command got queued up successfully + if(halStatus == eHAL_STATUS_SUCCESS) + { + //Block on a completion variable. Can't wait forever though. + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("wait on disconnect_comp_var failed")); + } + } + //None of the steps should fail after this. Continue even in case of failure + vosStatus = vos_stop( pHddCtx->pvosContext ); + if (!VOS_IS_STATUS_SUCCESS( vosStatus )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_stop return failed %d", + __func__, vosStatus); + VOS_ASSERT(0); + } + + pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP; + + //Restore IMPS config + if(pHddCtx->cfg_ini->fIsImpsEnabled) + sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + + //Restore BMPS config + if(pHddCtx->cfg_ini->fIsBmpsEnabled) + sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + + return vosStatus; +} + +VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) +{ + VOS_STATUS vosStatus; + eHalStatus halStatus; + tANI_U32 type, subType; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: calling hdd_set_sme_config",__func__); + vosStatus = hdd_set_sme_config( pHddCtx ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed in hdd_set_sme_config",__func__); + goto err_deep_sleep; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: calling vos_start",__func__); + vosStatus = vos_start( pHddCtx->pvosContext ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed in vos_start",__func__); + goto err_deep_sleep; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: calling hdd_post_voss_start_config",__func__); + vosStatus = hdd_post_voss_start_config( pHddCtx ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed in hdd_post_voss_start_config",__func__); + goto err_voss_stop; + } + + vosStatus = vos_get_vdev_types(pAdapter->device_mode, &type, &subType); + if (VOS_STATUS_SUCCESS != vosStatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "failed to get vdev type"); + goto err_voss_stop; + } + + //Open a SME session for future operation + halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter, + (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId, + type, subType); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08x]", + halStatus, halStatus ); + goto err_voss_stop; + + } + + pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE; + + //Trigger the initial scan + hdd_wlan_initial_scan(pHddCtx); + + return VOS_STATUS_SUCCESS; + +err_voss_stop: + vos_stop(pHddCtx->pvosContext); +err_deep_sleep: + return VOS_STATUS_E_FAILURE; + +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +{ + eHalStatus ret; + tSirGtkOffloadParams hddGtkOffloadReqParams; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if(fenable) + { + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags )) + { + vos_mem_copy(&hddGtkOffloadReqParams, + &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); + + ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_SetGTKOffload failed, returned %d", + __func__, ret); + return; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_SetGTKOffload successful", __func__); + } + + } + else + { + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId, + &pHddStaCtx->conn_info.bssId, VOS_MAC_ADDR_SIZE)) && + (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags)) + { + + /* Host driver has previously offloaded GTK rekey */ + ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlan_hdd_cfg80211_update_replayCounterCallback, + pAdapter, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_GetGTKOffload failed, returned %d", + __func__, ret); + return; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_GetGTKOffload successful", + __func__); + + /* Sending GTK offload disable */ + memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); + hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE; + ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to disable GTK offload, returned %d", + __func__, ret); + return; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: successfully disabled GTK offload request to HAL", + __func__); + } + } + } + return; +} +#endif /*WLAN_FEATURE_GTK_OFFLOAD*/ + +#ifdef WLAN_NS_OFFLOAD + +static int __wlan_hdd_ipv6_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg; + struct net_device *ndev = ifa->idev->dev; + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + int status; + + hdd_ctx = container_of(nb, hdd_context_t, ipv6_notifier); + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return NOTIFY_DONE; + } + + adapter = WLAN_HDD_GET_PRIV_PTR(ndev); + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) return NOTIFY_DONE; + if (adapter->dev != ndev) return NOTIFY_DONE; + if (WLAN_HDD_GET_CTX(adapter) != hdd_ctx) return NOTIFY_DONE; + + if (adapter->device_mode == WLAN_HDD_INFRA_STATION || + (adapter->device_mode == WLAN_HDD_P2P_CLIENT)) { + if (hdd_ctx->cfg_ini->nEnableSuspend == + WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) + schedule_work(&adapter->ipv6NotifierWorkQueue); + else + hddLog(LOG1, FL("Not scheduling ipv6 wq nEnableSuspend: %d"), + hdd_ctx->cfg_ini->nEnableSuspend); + } + + return NOTIFY_DONE; +} + +/** + * wlan_hdd_ipv6_changed() - IPv6 change notifier callback + * @nb: pointer to notifier block + * @data: data + * @arg: arg + * + * This is the IPv6 notifier callback function gets invoked + * if any change in IP and then invoke the function @__wlan_hdd_ipv6_changed + * to reconfigure the offload parameters. + * + * Return: 0 on success, error number otherwise. + */ +int wlan_hdd_ipv6_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_ipv6_changed(nb, data, arg); + vos_ssr_unprotect(__func__); + + return ret; +} + +/**---------------------------------------------------------------------------- + + \brief hdd_conf_ns_offload() - Configure NS offload + + Called during SUSPEND to configure the NS offload (MC BC filter) which + reduces power consumption. + + \param - pAdapter - Adapter context for which NS offload is to be configured + \param - fenable - 0 - disable. + 1 - enable. (with IPv6 notifier registration) + 2 - enable. (without IPv6 notifier registration) + + \return - void + + ---------------------------------------------------------------------------*/ +static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) +{ + struct inet6_dev *in6_dev; + struct inet6_ifaddr *ifp; + struct list_head *p; + tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}}; + tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0}; + tSirHostOffloadReq offLoadRequest; + hdd_context_t *pHddCtx; + + int i =0; + eHalStatus returnStatus; + uint32_t count = 0, scope; + + ENTER(); + hddLog(LOG1, FL(" fenable = %d"), fenable); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + /* In SAP/P2PGo mode, ARP/NS offload feature capability + * is controlled by one bit. + */ + + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode || + WLAN_HDD_P2P_GO == pAdapter->device_mode) && + !pHddCtx->ap_arpns_support) { + hddLog(LOG1, FL("NS Offload is not supported in SAP/P2PGO mode")); + return; + } + + if (fenable) { + in6_dev = __in6_dev_get(pAdapter->dev); + if (NULL != in6_dev) { + list_for_each(p, &in6_dev->addr_list) { + if (count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) { + hddLog(LOG1, FL("Reached max supported NS Offload addresses")); + break; + } + ifp = list_entry(p, struct inet6_ifaddr, if_list); + scope = ipv6_addr_src_scope(&ifp->addr); + switch (scope) { + case IPV6_ADDR_SCOPE_GLOBAL: + case IPV6_ADDR_SCOPE_LINKLOCAL: + vos_mem_copy(&selfIPv6Addr[count], &ifp->addr.s6_addr, + sizeof(ifp->addr.s6_addr)); + selfIPv6AddrValid[count] = SIR_IPV6_ADDR_VALID; + hddLog (LOG1, + FL("Index %d scope = %s Address : %pI6"), + count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ? + "LINK LOCAL": "GLOBAL", selfIPv6Addr[count]); + count += 1; + break; + default: + hddLog(LOGE, "The Scope %d is not supported", + ipv6_addr_src_scope(&ifp->addr)); + } + + } + vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); + for (i = 0; i < count; i++) { + /* Filling up the request structure + * Filling the selfIPv6Addr with solicited address + * A Solicited-Node multicast address is created by + * taking the last 24 bits of a unicast or anycast + * address and appending them to the prefix + * + * FF02:0000:0000:0000:0000:0001:FFXX:XXXX + * + * here XX is the unicast/anycast bits + */ + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][0] = 0xFF; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][1] = 0x02; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][11] = 0x01; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][12] = 0xFF; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][13] = + selfIPv6Addr[i][13]; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][14] = + selfIPv6Addr[i][14]; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[i][15] = + selfIPv6Addr[i][15]; + offLoadRequest.nsOffloadInfo.slotIdx = i; + + vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], + &selfIPv6Addr[i][0], SIR_MAC_IPV6_ADDR_LEN); + + offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[i] = + SIR_IPV6_ADDR_VALID; + + hddLog (LOG1, + FL("configuredMcastBcastFilter: %d"), + pHddCtx->configuredMcastBcastFilter); + + if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) + && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST == + pHddCtx->sus_res_mcastbcast_filter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter))) { + hddLog(LOG1, + FL("Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE")); + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE; + } + + vos_mem_copy(&offLoadRequest.params.hostIpv6Addr, + &offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], + sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN); + + hddLog (LOG1, + FL("Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6, Index %d"), + &offLoadRequest.nsOffloadInfo.selfIPv6Addr[i], + &offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], i); + } + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; + vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr, + &pAdapter->macAddressCurrent.bytes, SIR_MAC_ADDR_LEN); + /* set number of ns offload address count */ + offLoadRequest.num_ns_offload_count = count; + /* Configure the Firmware with this */ + returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest); + if (eHAL_STATUS_SUCCESS != returnStatus) { + hddLog(LOGE, + FL("Failed to enable HostOffload feature with status: %d"), + returnStatus); + } + } + else { + hddLog(LOGE, + FL("IPv6 dev does not exist. Failed to request NSOffload")); + return; + } + } else { + /* Disable NSOffload */ + vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); + offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) { + hddLog(LOGE, FL("Failed to disable NS Offload")); + } + } + EXIT(); + return; +} + +/** + * __hdd_ipv6_notifier_work_queue() - IP V6 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +static void __hdd_ipv6_notifier_work_queue(struct work_struct *work) +{ + hdd_adapter_t* pAdapter = + container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue); + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return; + + if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) + { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + && (pHddCtx->hdd_wlan_suspended)) + { + /* + * This invocation being part of the IPv6 registration callback, + * we are passing second parameter as 2 to avoid registration + * of IPv6 notifier again + */ + if (pHddCtx->cfg_ini->fhostNSOffload) + hdd_conf_ns_offload(pAdapter, 2); + } + EXIT(); +} + +/** + * hdd_ipv6_notifier_work_queue() - IP V6 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +void hdd_ipv6_notifier_work_queue(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __hdd_ipv6_notifier_work_queue(work); + vos_ssr_unprotect(__func__); +} + + +#endif + +/* + * Function: hdd_conf_hostoffload + * Central function to configure the supported offloads, + * either enable or disable them. + */ +void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t *pVosContext = NULL; + VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; + + ENTER(); + + hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"), + fenable); + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL == pVosContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null")); + return; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__); + return; + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) + { + if (fenable) + { + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) || + (WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) + { + if ((pHddCtx->cfg_ini->fhostArpOffload)) + { + /* + * Configure the ARP Offload. + * Even if it fails we have to reconfigure the MC/BC + * filter flag as we want RIVA not to drop BroadCast + * Packets + */ + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Calling ARP Offload with flag: %d"), fenable); + vstatus = hdd_conf_arp_offload(pAdapter, fenable); + pHddCtx->configuredMcastBcastFilter &= + ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); + + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to enable ARPOFfloadFeature %d", + vstatus); + } + } + //Configure GTK_OFFLOAD +#ifdef WLAN_FEATURE_GTK_OFFLOAD + hdd_conf_gtk_offload(pAdapter, fenable); +#endif + +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + /* + * Configure the NS Offload. + * Even if it fails we have to reconfigure the MC/BC filter flag + * as we want RIVA not to drop Multicast Packets + */ + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Calling NS Offload with flag: %d"), fenable); + hdd_conf_ns_offload(pAdapter, fenable); + pHddCtx->configuredMcastBcastFilter &= + ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); + } + +#endif + /* + * This variable saves the state if offload were configured + * or not. helps in recovering when pcie fails to suspend + * because of ongoing scan and state is no longer associated. + */ + pAdapter->offloads_configured = TRUE; + } + } + else + { + //Disable ARPOFFLOAD + if ( (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) || + (pAdapter->offloads_configured == TRUE) + ) + { + pAdapter->offloads_configured = FALSE; + + if (pHddCtx->cfg_ini->fhostArpOffload) + { + vstatus = hdd_conf_arp_offload(pAdapter, fenable); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to disable ARPOffload Feature %d", vstatus); + } + } + //Disable GTK_OFFLOAD +#ifdef WLAN_FEATURE_GTK_OFFLOAD + hdd_conf_gtk_offload(pAdapter, fenable); +#endif + +#ifdef WLAN_NS_OFFLOAD + //Disable NSOFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + hdd_conf_ns_offload(pAdapter, fenable); + } +#endif + } + } + } + EXIT(); + return; +} + +/** + * __hdd_ipv4_notifier_work_queue() - IP V4 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +static void __hdd_ipv4_notifier_work_queue(struct work_struct *work) +{ + hdd_adapter_t* pAdapter = + container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue); + hdd_context_t *pHddCtx; + int status; + + hddLog(LOG1, FL("Reconfiguring ARP Offload")); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + hddLog(LOGE, FL("HDD context is invalid")); + return; + } + + if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) + { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + && (pHddCtx->hdd_wlan_suspended)) + { + // This invocation being part of the IPv4 registration callback, + // we are passing second parameter as 2 to avoid registration + // of IPv4 notifier again. + hdd_conf_arp_offload(pAdapter, 2); + } +} + +/** + * hdd_ipv4_notifier_work_queue() - IP V4 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +void hdd_ipv4_notifier_work_queue(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __hdd_ipv4_notifier_work_queue(work); + vos_ssr_unprotect(__func__); +} + +static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)arg; + struct in_ifaddr **ifap = NULL; + struct in_device *in_dev; + struct net_device *ndev = ifa->ifa_dev->dev; + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + int status; + + hdd_ctx = container_of(nb, hdd_context_t, ipv4_notifier); + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return NOTIFY_DONE; + } + + adapter = WLAN_HDD_GET_PRIV_PTR(ndev); + if (!adapter) return NOTIFY_DONE; + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) return NOTIFY_DONE; + if (adapter->dev != ndev) return NOTIFY_DONE; + if (WLAN_HDD_GET_CTX(adapter) != hdd_ctx) return NOTIFY_DONE; + if (!(adapter->device_mode == WLAN_HDD_INFRA_STATION || + adapter->device_mode == WLAN_HDD_P2P_CLIENT)) + return NOTIFY_DONE; + + if ((hdd_ctx->cfg_ini->nEnableSuspend != + WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) || + (!hdd_ctx->cfg_ini->fhostArpOffload)) { + hddLog(LOG1, FL("Offload not enabled MCBC=%d, ARPOffload=%d"), + hdd_ctx->cfg_ini->nEnableSuspend, + hdd_ctx->cfg_ini->fhostArpOffload); + + return NOTIFY_DONE; + } + + in_dev = __in_dev_get_rtnl(adapter->dev); + if (in_dev != NULL) { + for (ifap = &in_dev->ifa_list; + (ifa = *ifap) != NULL; + ifap = &ifa->ifa_next) { + if (!strcmp(adapter->dev->name, + ifa->ifa_label)) + break; /* found */ + } + } + + if (ifa && ifa->ifa_local) + schedule_work(&adapter->ipv4NotifierWorkQueue); + + return NOTIFY_DONE; +} + +/** + * wlan_hdd_ipv4_changed() - IPv4 change notifier callback + * @nb: pointer to notifier block + * @data: data + * @arg: arg + * + * This is the IPv4 notifier callback function gets invoked + * if any change in IP and then invoke the function @__wlan_hdd_ipv4_changed + * to reconfigure the offload parameters. + * + * Return: 0 on success, error number otherwise. + */ +int wlan_hdd_ipv4_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_ipv4_changed(nb, data, arg); + vos_ssr_unprotect(__func__); + + return ret; +} + +/**---------------------------------------------------------------------------- + + \brief hdd_conf_arp_offload() - Configure ARP offload + + Called during SUSPEND to configure the ARP offload (MC BC filter) which + reduces power consumption. + + \param - pAdapter -Adapter context for which ARP offload is to be configured + \param - fenable - 0 - disable. + 1 - enable. (with IPv4 notifier registration) + 2 - enable. (without IPv4 notifier registration) + + \return - + VOS_STATUS_SUCCESS - on successful operation + VOS_STATUS_E_FAILURE - on failure of operation +-----------------------------------------------------------------------------*/ +VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable) +{ + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + struct in_device *in_dev; + int i = 0; + tSirHostOffloadReq offLoadRequest; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + hddLog(LOG1, FL("fenable = %d"), fenable); + + /* In SAP/P2PGo mode, ARP/NS offload feature capability + * is controlled by one bit. + */ + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode || + WLAN_HDD_P2P_GO == pAdapter->device_mode) && + !pHddCtx->ap_arpns_support) { + hddLog(LOG1, FL("APR Offload is not supported in SAP/P2PGO mode")); + return VOS_STATUS_SUCCESS; + } + + if(fenable) + { + if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL) + { + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + ifap = &ifa->ifa_next) + { + if (!strcmp(pAdapter->dev->name, ifa->ifa_label)) + { + break; /* found */ + } + } + } + if(ifa && ifa->ifa_local) + { + offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; + offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__); + + if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter)) && + (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)) + { + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: inside arp offload conditional check"); + } + + hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d", + offLoadRequest.enableOrDisable); + + //converting u32 to IPV4 address + for(i = 0 ; i < 4; i++) + { + offLoadRequest.params.hostIpv4Addr[i] = + (ifa->ifa_local >> (i*8) ) & 0xFF ; + } + hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d", + offLoadRequest.params.hostIpv4Addr[0], + offLoadRequest.params.hostIpv4Addr[1], + offLoadRequest.params.hostIpv4Addr[2], + offLoadRequest.params.hostIpv4Addr[3]); + + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload " + "feature", __func__); + return VOS_STATUS_E_FAILURE; + } + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n")); + } + + return VOS_STATUS_SUCCESS; + } + else + { + vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); + offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; + offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; + + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host " + "offload feature", __func__); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; + } +} + +/* + * This function is called before setting mcbc filters + * to modify filter value considering Different Offloads + */ + +void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, + tANI_U8 *pMcBcFilter) +{ + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed")); + return; + } + + *pMcBcFilter = pHddCtx->configuredMcastBcastFilter; + if (pHddCtx->cfg_ini->fhostArpOffload) + { + /* ARP offload is enabled, do not block bcast packets at RXP + * Will be using Bitmasking to reset the filter. As we have + * disable Broadcast filtering, Anding with the negation + * of Broadcast BIT + */ + hddLog(VOS_TRACE_LEVEL_INFO, FL("ARP offload is enabled")); + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); + } + +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + /* NS offload is enabled, do not block mcast packets at RXP + * Will be using Bitmasking to reset the filter. As we have + * disable Multicast filtering, Anding with the negation + * of Multicast BIT + */ + hddLog(VOS_TRACE_LEVEL_INFO, FL("NS offload is enabled")); + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); + } +#endif + + pHddCtx->configuredMcastBcastFilter = *pMcBcFilter; +} + +void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + tpSirWlanSetRxpFilters wlanRxpFilterParam = + vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_alloc failed ", __func__); + return; + } + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter); + if (TRUE == setfilter) + { + hdd_mcbc_filter_modification(pHddCtx, + &wlanRxpFilterParam->configuredMcstBcstFilterSetting); + } + else + { + /*Use the current configured value to clear*/ + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + } + + wlanRxpFilterParam->setMcstBcstFilter = setfilter; + halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam); + + if (setfilter && (eHAL_STATUS_SUCCESS == halStatus)) + pHddCtx->hdd_mcastbcast_filter_set = TRUE; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s to post set/reset filter to" + "lower mac with status %d" + "configuredMcstBcstFilterSetting = %d" + "setMcstBcstFilter = %d",(eHAL_STATUS_SUCCESS != halStatus) ? + "Failed" : "Success", halStatus, + wlanRxpFilterParam->configuredMcstBcstFilterSetting, + wlanRxpFilterParam->setMcstBcstFilter); + + if (eHAL_STATUS_SUCCESS != halStatus) + vos_mem_free(wlanRxpFilterParam); +} + +static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, + hdd_adapter_t *pAdapter, + void (*callback)(void *callbackContext, + boolean suspended), + void *callbackContext) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + tpSirWlanSuspendParam wlanSuspendParam = + vos_mem_malloc(sizeof(tSirWlanSuspendParam)); + + if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind"); + hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d", + pHddCtx->configuredMcastBcastFilter); + + } + + + if(NULL == wlanSuspendParam) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_alloc failed ", __func__); + return; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: send wlan suspend indication", __func__); + + if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER)) + { + //Configure supported OffLoads + hdd_conf_hostoffload(pAdapter, TRUE); + wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) || + (eConnectionState_IbssConnected == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + wlanSuspendParam->connectedState = TRUE; + else + wlanSuspendParam->connectedState = FALSE; + + wlanSuspendParam->sessionId = pAdapter->sessionId; + halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam, + callback, callbackContext); + if(eHAL_STATUS_SUCCESS == halStatus) + { + pHddCtx->hdd_mcastbcast_filter_set = TRUE; + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("sme_ConfigureSuspendInd returned failure %d"), halStatus); + + vos_mem_free(wlanSuspendParam); + } +} + +static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) +{ + hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + + halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, + NULL + ); + + if (eHAL_STATUS_SUCCESS != halStatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_ConfigureResumeReq return failure %d", + __func__, halStatus); + + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: send wlan resume indication", __func__); + /* Disable supported OffLoads */ + hdd_conf_hostoffload(pAdapter, FALSE); + pHddCtx->hdd_mcastbcast_filter_set = FALSE; + + if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter"); + hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); +} + +//Suspend routine registered with Android OS +void hdd_suspend_wlan(void (*callback)(void *callbackContext, boolean suspended), + void *callbackContext) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + + VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + bool hdd_enter_bmps = FALSE; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__); + + //Get the global VOSS context. + 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; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return; + } + + if (pHddCtx->isLogpInProgress) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Ignore suspend wlan, LOGP in progress!", __func__); + return; + } + + hdd_set_pwrparams(pHddCtx); + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode) + && (WLAN_HDD_SOFTAP != pAdapter->device_mode) + && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) ) + + { + goto send_suspend_ind; + } + /* Avoid multiple enter/exit BMPS in this while loop using + * hdd_enter_bmps flag + */ + if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal))) + { + hdd_enter_bmps = TRUE; + + /* If device was already in BMPS, and dynamic DTIM is set, + * exit(set the device to full power) and enter BMPS again + * to reflect new DTIM value */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); + + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + + pHddCtx->hdd_ignore_dtim_enabled = TRUE; + } +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY) + { + //stop the interface before putting the chip to standby + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + } + else if (pHddCtx->cfg_ini->nEnableSuspend == + WLAN_MAP_SUSPEND_TO_DEEP_SLEEP) + { + //Execute deep sleep procedure + hdd_enter_deep_sleep(pHddCtx, pAdapter); + } +#endif + +send_suspend_ind: + //stop all TX queues before suspend + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + WLANTL_PauseUnPauseQs(pVosContext, true); + + /* Keep this suspend indication at the end (before processing next adaptor) + * for discrete. This indication is considered as trigger point to start + * WOW (if wow is enabled). */ + /*Suspend notification sent down to driver*/ + hdd_conf_suspend_ind(pHddCtx, pAdapter, callback, callbackContext); + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + pHddCtx->hdd_wlan_suspended = TRUE; + +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY) + { + hdd_enter_standby(pHddCtx); + } +#endif + + return; +} + +static void hdd_PowerStateChangedCB +( + v_PVOID_t callbackContext, + tPmcState newState +) +{ + hdd_context_t *pHddCtx = callbackContext; + /* if the driver was not in BMPS during early suspend, + * the dynamic DTIM is now updated at Riva */ + if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended + && pHddCtx->cfg_ini->enableDynamicDTIM + && (pHddCtx->hdd_ignore_dtim_enabled == FALSE)) + { + pHddCtx->hdd_ignore_dtim_enabled = TRUE; + } + spin_lock(&pHddCtx->filter_lock); + if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended) + { + spin_unlock(&pHddCtx->filter_lock); + if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) + { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + + hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated"); + hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: calling hdd_conf_mcastbcast_filter"); + + } + + hdd_conf_mcastbcast_filter(pHddCtx, TRUE); + if(pHddCtx->hdd_mcastbcast_filter_set != TRUE) + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__); + } + else + { + /* Android framework can send resume request when the WCN chip is + * in IMPS mode. When the chip exits IMPS mode the firmware will + * restore all the registers to the state they were before the chip + * entered IMPS and so our hardware filter settings configured by the + * resume request will be lost. So reconfigure the filters on detecting + * a change in the power state of the WCN chip. + */ + spin_unlock(&pHddCtx->filter_lock); + if (IMPS != newState) + { + spin_lock(&pHddCtx->filter_lock); + if (FALSE == pHddCtx->hdd_wlan_suspended) + { + spin_unlock(&pHddCtx->filter_lock); + hddLog(VOS_TRACE_LEVEL_INFO, + "Not in IMPS/BMPS and suspended state"); + hdd_conf_mcastbcast_filter(pHddCtx, FALSE); + } + else + { + spin_unlock(&pHddCtx->filter_lock); + } + } + } +} + + + +void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx) +{ + v_CONTEXT_t pVosContext; + tHalHandle smeContext; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (NULL == pVosContext) + { + hddLog(LOGE, "%s: Invalid pContext", __func__); + return; + } + smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext); + if (NULL == smeContext) + { + hddLog(LOGE, "%s: Invalid smeContext", __func__); + return; + } + + spin_lock_init(&pHddCtx->filter_lock); + if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER == + pHddCtx->cfg_ini->nEnableSuspend) + { + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + { + pmcRegisterDeviceStateUpdateInd(smeContext, + hdd_PowerStateChangedCB, pHddCtx); + } + /* TODO: For Power Save Offload case */ + } +} + +void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx) +{ + v_CONTEXT_t pVosContext; + tHalHandle smeContext; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (NULL == pVosContext) + { + hddLog(LOGE, "%s: Invalid pContext", __func__); + return; + } + smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext); + if (NULL == smeContext) + { + hddLog(LOGE, "%s: Invalid smeContext", __func__); + return; + } + + if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER == + pHddCtx->cfg_ini->nEnableSuspend) + { + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + { + pmcDeregisterDeviceStateUpdateInd(smeContext, + hdd_PowerStateChangedCB); + } + /* TODO: For Power Save Offload case */ + } +} + +void hdd_resume_wlan(void) +{ + hdd_context_t *pHddCtx = NULL; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + v_CONTEXT_t pVosContext = NULL; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__); + + //Get the global VOSS context. + 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; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return; + } + + if (pHddCtx->isLogpInProgress) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Ignore resume wlan, LOGP in progress!", __func__); + return; + } + + pHddCtx->hdd_wlan_suspended = FALSE; + + /*loop through all adapters. Concurrency */ + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode) + && (WLAN_HDD_SOFTAP != pAdapter->device_mode) + && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) ) + { + goto send_resume_ind; + } + + +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__); + hdd_exit_deep_sleep(pAdapter); + } +#endif + + if(pHddCtx->hdd_ignore_dtim_enabled == TRUE) + { + /*Switch back to DTIM 1*/ + tSirSetPowerParamsReq powerRequest = { 0 }; + + powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value; + powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; + + /*Disabled ModulatedDTIM if enabled on suspend*/ + if(pHddCtx->cfg_ini->enableModulatedDTIM) + powerRequest.uDTIMPeriod = 0; + + /* Update ignoreDTIM and ListedInterval in CFG with default values */ + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + NULL, eANI_BOOLEAN_FALSE); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Switch to DTIM%d",powerRequest.uListenInterval); + sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); + + if (BMPS == pmcGetPmcState(pHddCtx->hHal)) + { + /* 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; + } + } + +send_resume_ind: + //wake the tx queues + hddLog(LOG1, FL("Enabling queues")); + WLANTL_PauseUnPauseQs(pVosContext, false); + + netif_tx_wake_all_queues(pAdapter->dev); + + hdd_conf_resume_ind(pAdapter); + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + +#ifdef IPA_OFFLOAD + hdd_ipa_resume(pHddCtx); +#endif + +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY) + { + hdd_exit_standby(pHddCtx); + } +#endif + + return; +} + +VOS_STATUS hdd_wlan_reset_initialization(void) +{ + v_CONTEXT_t pVosContext = NULL; + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__); + + //Get the global VOSS context. + 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 VOS_STATUS_E_FAILURE; + } + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__); + + // Prevent the phone from going to sleep + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); + + return VOS_STATUS_SUCCESS; +} + +static void hdd_ssr_timer_init(void) +{ + init_timer(&ssr_timer); +} + +static void hdd_ssr_timer_del(void) +{ + del_timer(&ssr_timer); + ssr_timer_started = false; +} + +static void hdd_ssr_timer_cb(unsigned long data) +{ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired!", __func__); + VOS_BUG(0); +} + +static void hdd_ssr_timer_start(int msec) +{ + if(ssr_timer_started) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Trying to start SSR timer when " + "it's running!", __func__); + } + ssr_timer.expires = jiffies + msecs_to_jiffies(msec); + ssr_timer.function = hdd_ssr_timer_cb; + add_timer(&ssr_timer); + ssr_timer_started = true; +} + +/* the HDD interface to WLAN driver shutdown, + * the primary shutdown function in SSR + */ +VOS_STATUS hdd_wlan_shutdown(void) +{ + VOS_STATUS vosStatus; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + pVosSchedContext vosSchedContext = NULL; + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__); + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); +#endif + + /* If SSR never completes, then do kernel panic. */ + hdd_ssr_timer_init(); + hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME); + + /* Get the global VOSS context. */ + 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 VOS_STATUS_E_FAILURE; + } + /* Get the HDD context. */ + pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return VOS_STATUS_E_FAILURE; + } + + pHddCtx->isLogpInProgress = TRUE; + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + + vos_clear_concurrent_session_count(); + +#ifdef MSM_PLATFORM + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->bus_bw_timer)) + { + vos_timer_stop(&pHddCtx->bus_bw_timer); + } +#endif + + hdd_reset_all_adapters(pHddCtx); + +#ifdef IPA_UC_OFFLOAD + hdd_ipa_uc_ssr_deinit(); +#endif + + vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__); + } + + /* Disable IMPS/BMPS as we do not want the device to enter any power + * save mode on its own during reset sequence + */ + sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE); + + vosSchedContext = get_vos_sched_ctxt(); + + /* Wakeup all driver threads */ + if(TRUE == pHddCtx->isMcThreadSuspended){ + complete(&vosSchedContext->ResumeMcEvent); + pHddCtx->isMcThreadSuspended= FALSE; + } + if(TRUE == pHddCtx->isTxThreadSuspended){ + complete(&vosSchedContext->ResumeTxEvent); + pHddCtx->isTxThreadSuspended= FALSE; + } + if(TRUE == pHddCtx->isRxThreadSuspended){ + complete(&vosSchedContext->ResumeRxEvent); + pHddCtx->isRxThreadSuspended= FALSE; + } +#ifdef QCA_CONFIG_SMP + if (TRUE == pHddCtx->isTlshimRxThreadSuspended) { + complete(&vosSchedContext->ResumeTlshimRxEvent); + pHddCtx->isTlshimRxThreadSuspended = FALSE; + } +#endif + + /* Reset the Suspend Variable */ + pHddCtx->isWlanSuspended = FALSE; + + /* Stop all the threads; we do not want any messages to be a processed, + * any more and the best way to ensure that is to terminate the threads + * gracefully. + */ + /* Wait for MC to exit */ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__); + set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag); + set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag); + wake_up_interruptible(&vosSchedContext->mcWaitQueue); + wait_for_completion(&vosSchedContext->McShutdown); + + /* Wait for TX to exit */ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__); + set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag); + set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag); + wake_up_interruptible(&vosSchedContext->txWaitQueue); + wait_for_completion(&vosSchedContext->TxShutdown); + + /* Wait for RX to exit */ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__); + set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag); + set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag); + wake_up_interruptible(&vosSchedContext->rxWaitQueue); + wait_for_completion(&vosSchedContext->RxShutdown); + +#ifdef QCA_CONFIG_SMP + /* Wait for TLshim RX to exit */ + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TLshim RX thread", + __func__); + unregister_hotcpu_notifier(vosSchedContext->cpuHotPlugNotifier); + set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->tlshimRxEvtFlg); + set_bit(RX_POST_EVENT_MASK, &vosSchedContext->tlshimRxEvtFlg); + wake_up_interruptible(&vosSchedContext->tlshimRxWaitQueue); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Waiting for TLshim RX thread to exit", + __func__); + wait_for_completion(&vosSchedContext->TlshimRxShutdown); + vosSchedContext->TlshimRxThread = NULL; + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Waiting for dropping RX packets", + __func__); + vos_drop_rxpkt_by_staid(vosSchedContext, WLAN_MAX_STA_COUNT); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Waiting for freeing freeQ", __func__); + vos_free_tlshim_pkt_freeq(vosSchedContext); +#endif + + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing WDA STOP", __func__); + vosStatus = WDA_stop(pVosContext, HAL_STOP_TYPE_RF_KILL); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop WDA", __func__); + VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); + WDA_setNeedShutdown(pVosContext); + } + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__); + /* Stop SME - Cannot invoke vos_stop as vos_stop relies + * on threads being running to process the SYS Stop + */ + vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop sme %d", __func__, vosStatus); + VOS_ASSERT(0); + } + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__); + /* Stop MAC (PE and HAL) */ + vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop mac %d", __func__, vosStatus); + VOS_ASSERT(0); + } + + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__); + /* Stop TL */ + vosStatus = WLANTL_Stop(pVosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop TL %d", __func__, vosStatus); + VOS_ASSERT(0); + } + + hdd_unregister_mcast_bcast_filter(pHddCtx); + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__); + /* Clean up message queues of TX, RX and MC thread */ + vos_sched_flush_mc_mqs(vosSchedContext); + vos_sched_flush_tx_mqs(vosSchedContext); + vos_sched_flush_rx_mqs(vosSchedContext); + + /* Deinit all the TX, RX and MC queues */ + vos_sched_deinit_mqs(vosSchedContext); + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__); + /* shutdown VOSS */ + vos_shutdown(pVosContext); + + /*mac context has already been released in mac_close call + so setting it to NULL in hdd context*/ + pHddCtx->hHal = (tHalHandle)NULL; + + if (free_riva_power_on_lock("wlan")) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock", + __func__); + } + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete" + ,__func__); + return VOS_STATUS_SUCCESS; +} + + + +/* the HDD interface to WLAN driver re-init. + * This is called to initialize/start WLAN driver after a shutdown. + */ +VOS_STATUS hdd_wlan_re_init(void *hif_sc) +{ + VOS_STATUS vosStatus; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + eHalStatus halStatus; + + hdd_adapter_t *pAdapter; + int i; + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); + + vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE); + + /* Get the VOS context */ + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if(pVosContext == NULL) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed vos_get_global_context", + __func__); + goto err_re_init; + } + + /* Get the HDD context */ + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if(!pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is Null", __func__); + goto err_re_init; + } + + if (!hif_sc) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hif_sc is NULL", __func__); + goto err_re_init; + } + + ((VosContextType*)pVosContext)->pHIFContext = hif_sc; + + /* The driver should always be initialized in STA mode after SSR */ + hdd_set_conparam(0); + + /* Re-open VOSS, it is a re-open b'se control transport was never closed. */ + vosStatus = vos_open(&pVosContext, 0); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__); + goto err_re_init; + } + +#if !defined(REMOVE_PKT_LOG) + hif_init_pdev_txrx_handle(hif_sc, + vos_get_context(VOS_MODULE_ID_TXRX, pVosContext)); +#endif + + /* Save the hal context in Adapter */ + pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext ); + if ( NULL == pHddCtx->hHal ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__); + goto err_vosclose; + } + + /* Set the SME configuration parameters. */ + vosStatus = hdd_set_sme_config(pHddCtx); + if ( VOS_STATUS_SUCCESS != vosStatus ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__); + goto err_vosclose; + } + + vosStatus = vos_preStart( pHddCtx->pvosContext ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__); + goto err_vosclose; + } + + vosStatus = hdd_set_sme_chan_list(pHddCtx); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: Failed to init channel list", __func__); + goto err_vosclose; + } + + /* In the integrated architecture we update the configuration from + the INI file and from NV before vOSS has been started so that + the final contents are available to send down to the cCPU */ + /* Apply the cfg.ini to cfg.dat */ + if (FALSE == hdd_update_config_dat(pHddCtx)) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ ); + goto err_vosclose; + } + + /* Set the MAC Address, currently this is used by HAL to add self sta. + * Remove this once self sta is added as part of session open. */ + halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID, + (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0], + sizeof(pHddCtx->cfg_ini->intfMacAddr[0])); + if (!HAL_STATUS_SUCCESS(halStatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. " + "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus); + goto err_vosclose; + } + + /* Start VOSS which starts up the SME/MAC/HAL modules and everything else + Note: Firmware image will be read and downloaded inside vos_start API */ + vosStatus = vos_start( pVosContext ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__); + goto err_vosclose; + } +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_ssr_reinit()) + hddLog(LOGE, "%s: HDD IPA UC reinit failed", __func__); +#endif + + + vosStatus = hdd_post_voss_start_config( pHddCtx ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed", + __func__); + goto err_vosstop; + } + + /* Try to get an adapter from mode ID */ + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (!pAdapter) { + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP); + if (!pAdapter) { + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS); + if (!pAdapter) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to get Adapter!", + __func__); + } + } + } + + /* Get WLAN Host/FW/HW version */ + if (pAdapter) + hdd_wlan_get_version(pAdapter, NULL, NULL); + + /* Pass FW version to HIF layer */ + hif_set_fw_info(hif_sc, pHddCtx->target_fw_version); + + /* Restart all adapters */ + hdd_start_all_adapters(pHddCtx); + + /* Reconfigure FW logs after SSR */ + if (pAdapter) { + if (pHddCtx->fw_log_settings.enable != 0) { + process_wma_set_command(pAdapter->sessionId, + WMI_DBGLOG_MODULE_ENABLE, + pHddCtx->fw_log_settings.enable , DBG_CMD); + } else { + process_wma_set_command(pAdapter->sessionId, + WMI_DBGLOG_MODULE_DISABLE, + pHddCtx->fw_log_settings.enable, DBG_CMD); + } + + if (pHddCtx->fw_log_settings.dl_report != 0) { + process_wma_set_command(pAdapter->sessionId, + WMI_DBGLOG_REPORT_ENABLE, + pHddCtx->fw_log_settings.dl_report, DBG_CMD); + + process_wma_set_command(pAdapter->sessionId, + WMI_DBGLOG_TYPE, + pHddCtx->fw_log_settings.dl_type, DBG_CMD); + + process_wma_set_command(pAdapter->sessionId, + WMI_DBGLOG_LOG_LEVEL, + pHddCtx->fw_log_settings.dl_loglevel, DBG_CMD); + + for (i = 0; i < MAX_MOD_LOGLEVEL; i++) { + if (pHddCtx->fw_log_settings.dl_mod_loglevel[i] != 0) { + process_wma_set_command(pAdapter->sessionId, + WMI_DBGLOG_MOD_LOG_LEVEL, + pHddCtx->fw_log_settings.dl_mod_loglevel[i], + DBG_CMD); + } + } + } + } + + /* Register TM level change handler function to the platform */ + hddDevTmRegisterNotifyCallback(pHddCtx); + + pHddCtx->hdd_mcastbcast_filter_set = FALSE; + pHddCtx->btCoexModeSet = false; + hdd_register_mcast_bcast_filter(pHddCtx); + hdd_ssr_timer_del(); + + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_FW_CRASHED_IND, NULL, 0); + + /* Allow the phone to go to sleep */ + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); + /* register for riva power on lock */ + if (req_riva_power_on_lock("wlan")) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed", + __func__); + goto err_unregister_pmops; + } + vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE); +#ifdef FEATURE_WLAN_EXTSCAN + sme_ExtScanRegisterCallback(pHddCtx->hHal, + wlan_hdd_cfg80211_extscan_callback); +#endif /* FEATURE_WLAN_EXTSCAN */ + sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached); + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_all_scan_intf_info(pHddCtx); + wlan_hdd_send_version_pkg(pHddCtx->target_fw_version, + pHddCtx->target_hw_version, + pHddCtx->target_hw_name); +#endif + ol_pktlog_init(hif_sc); + goto success; + +err_unregister_pmops: +#ifdef CONFIG_HAS_EARLYSUSPEND + hdd_unregister_mcast_bcast_filter(pHddCtx); +#endif + hdd_close_all_adapters(pHddCtx); + +err_vosstop: + vos_stop(pVosContext); + +err_vosclose: + vos_close(pVosContext); + vos_sched_close(pVosContext); + if (pHddCtx) + { + /* Unregister the Net Device Notifier */ + unregister_netdevice_notifier(&hdd_netdev_notifier); + /* Clean up HDD Nlink Service */ + send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); +#ifdef WLAN_KD_READY_NOTIFIER + cnss_diag_notify_wlan_close(); + nl_srv_exit(pHddCtx->ptt_pid); +#else + nl_srv_exit(); +#endif /* WLAN_KD_READY_NOTIFIER */ + /* Free up dynamically allocated members inside HDD Adapter */ + kfree(pHddCtx->cfg_ini); + pHddCtx->cfg_ini= NULL; + wlan_hdd_deinit_tx_rx_histogram(pHddCtx); + wiphy_unregister(pHddCtx->wiphy); + wiphy_free(pHddCtx->wiphy); + } + vos_preClose(&pVosContext); + +#ifdef MEMORY_DEBUG + vos_mem_exit(); +#endif + +err_re_init: + /* Allow the phone to go to sleep */ + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); + vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE); + VOS_BUG(0); + return -EPERM; + +success: + /* Trigger replay of BTC events */ + send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); + pHddCtx->isLogpInProgress = FALSE; + return VOS_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ftm.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ftm.c new file mode 100644 index 000000000000..fcfe34875b21 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ftm.c @@ -0,0 +1,1136 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_ftm.c + + \brief This file contains the WLAN factory test mode implementation + + ========================================================================*/ + +/**========================================================================= + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 07/18/14 kanand Cleanup. Remove legacy Prima code and retain support for Rome only + 04/20/11 Leo/Henri Convergence for Prima and Volans. Single image for FTM and mission mode + 04/05/09 Shailender Created module. + + ==========================================================================*/ +#include +#include "vos_sched.h" +#include +#include "sirTypes.h" +#include "halTypes.h" +#include "sirApi.h" +#include "sirMacProtDef.h" +#include "sme_Api.h" +#include "macInitApi.h" +#include "wlan_qct_sys.h" +#include "wlan_qct_tl.h" +#include "wlan_hdd_misc.h" +#include "i_vos_packet.h" +#include "vos_nvitem.h" +#include "wlan_hdd_main.h" +#include "qwlan_version.h" +#include "wlan_nv.h" +#include "wlan_qct_wda.h" +#include "cfgApi.h" + +#if defined(QCA_WIFI_FTM) +#include "bmi.h" +#include "ol_fw.h" +#include "testmode.h" +#include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_main.h" +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#include +#elif defined(HIF_SDIO) +#include "if_ath_sdio.h" +#endif +#endif + +#if defined(QCA_WIFI_FTM) +#if defined(LINUX_QCMBR) +#define ATH_XIOCTL_UNIFIED_UTF_CMD 0x1000 +#define ATH_XIOCTL_UNIFIED_UTF_RSP 0x1001 +#define MAX_UTF_LENGTH 1024 +typedef struct qcmbr_data_s { + unsigned int cmd; + unsigned int length; + unsigned char buf[MAX_UTF_LENGTH + 4]; + unsigned int copy_to_user; +} qcmbr_data_t; +typedef struct qcmbr_queue_s { + unsigned char utf_buf[MAX_UTF_LENGTH + 4]; + struct list_head list; +} qcmbr_queue_t; +LIST_HEAD(qcmbr_queue_head); +DEFINE_SPINLOCK(qcmbr_queue_lock); +#endif +#endif + +#define HDD_FTM_WMA_PRE_START_TIMEOUT (30000) /* 30 seconds */ + +/**--------------------------------------------------------------------------- + + \brief wlan_ftm_postmsg() - + + The function used for sending the command to the halphy. + + \param - cmd_ptr - Pointer command buffer. + + \param - cmd_len - Command length. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +static v_U32_t wlan_ftm_postmsg(v_U8_t *cmd_ptr, v_U16_t cmd_len) +{ + vos_msg_t *ftmReqMsg; + vos_msg_t ftmMsg; + ENTER(); + + ftmReqMsg = (vos_msg_t *) cmd_ptr; + + ftmMsg.type = WDA_FTM_CMD_REQ; + ftmMsg.reserved = 0; + ftmMsg.bodyptr = (v_U8_t*)cmd_ptr; + ftmMsg.bodyval = 0; + + /* Use Vos messaging mechanism to send the command to halPhy */ + if (VOS_STATUS_SUCCESS != vos_mq_post_message( + VOS_MODULE_ID_WDA, + (vos_msg_t *)&ftmMsg)) { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL", __func__); + + return VOS_STATUS_E_FAILURE; + } + + EXIT(); + return VOS_STATUS_SUCCESS; +} + +static void wlan_hdd_ftm_update_tgt_cfg(void *context, void *param) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context; + struct hdd_tgt_cfg *cfg = (struct hdd_tgt_cfg *)param; + + if (!vos_is_macaddr_zero(&cfg->hw_macaddr)) { + hdd_update_macaddr(hdd_ctx->cfg_ini, cfg->hw_macaddr); + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid MAC passed from target, using MAC from ini file" + MAC_ADDRESS_STR, __func__, + MAC_ADDR_ARRAY(hdd_ctx->cfg_ini->intfMacAddr[0].bytes)); + } +} + +/*--------------------------------------------------------------------------- + + \brief wlan_ftm_vos_open() - Open the vOSS Module + + The \a wlan_ftm_vos_open() function opens the vOSS Scheduler + Upon successful initialization: + + - All VOS submodules should have been initialized + + - The VOS scheduler should have opened + + - All the WLAN SW components should have been opened. This include + MAC. + + + \param hddContextSize: Size of the HDD context to allocate. + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initialize the scheduler + + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa wlan_ftm_vos_open() + +---------------------------------------------------------------------------*/ +static VOS_STATUS wlan_ftm_vos_open( v_CONTEXT_t pVosContext, v_SIZE_t hddContextSize ) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + int iter = 0; + tSirRetStatus sirStatus = eSIR_SUCCESS; + tMacOpenParameters macOpenParms; + pVosContextType gpVosContext = (pVosContextType)pVosContext; +#if defined(QCA_WIFI_FTM) + adf_os_device_t adf_ctx; + HTC_INIT_INFO htcInfo; + v_PVOID_t pHifContext = NULL; + v_PVOID_t pHtcContext = NULL; +#endif + hdd_context_t *pHddCtx; + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Opening VOSS", __func__); + + if (NULL == gpVosContext) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Trying to open VOSS without a PreOpen",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* Initialize the probe event */ + if (vos_event_init(&gpVosContext->ProbeEvent) != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to init probeEvent",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + if(vos_event_init(&(gpVosContext->wdaCompleteEvent)) != VOS_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to init wdaCompleteEvent",__func__); + VOS_ASSERT(0); + + goto err_probe_event; + } + + /* Initialize the free message queue */ + vStatus = vos_mq_init(&gpVosContext->freeVosMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to initialize VOS free message queue %d", + __func__, vStatus); + VOS_ASSERT(0); + goto err_wda_complete_event; + } + + for (iter = 0; iter < VOS_CORE_MAX_MESSAGES; iter++) + { + (gpVosContext->aMsgWrappers[iter]).pVosMsg = + &(gpVosContext->aMsgBuffers[iter]); + INIT_LIST_HEAD(&gpVosContext->aMsgWrappers[iter].msgNode); + vos_mq_put(&gpVosContext->freeVosMq, &(gpVosContext->aMsgWrappers[iter])); + } + + /* Now Open the VOS Scheduler */ + vStatus= vos_sched_open(gpVosContext, &gpVosContext->vosSched, + sizeof(VosSchedContext)); + + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to open VOS Scheduler %d", __func__, vStatus); + VOS_ASSERT(0); + goto err_msg_queue; + } + +#if defined(QCA_WIFI_FTM) + /* Initialize BMI and Download firmware */ + pHifContext = vos_get_context(VOS_MODULE_ID_HIF, gpVosContext); + if (!pHifContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: failed to get HIF context", __func__); + goto err_sched_close; + } + + if (bmi_download_firmware(pHifContext)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: BMI failed to download target", __func__); + goto err_bmi_close; + } + htcInfo.pContext = gpVosContext->pHIFContext; + htcInfo.TargetFailure = ol_target_failure; + htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, gpVosContext); + + /* Create HTC */ + gpVosContext->htc_ctx = HTCCreate(htcInfo.pContext, &htcInfo, adf_ctx); + if (!gpVosContext->htc_ctx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to Create HTC", __func__); + goto err_bmi_close; + goto err_sched_close; + } + + if (bmi_done(pHifContext)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_htc_close; + } +#endif /* QCA_WIFI_FTM */ + + /* Open the SYS module */ + vStatus = sysOpen(gpVosContext); + + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to open SYS module %d", __func__, vStatus); + VOS_ASSERT(0); + goto err_sched_close; + } + + /*Open the WDA module */ + vos_mem_set(&macOpenParms, sizeof(macOpenParms), 0); + macOpenParms.driverType = eDRIVER_TYPE_MFG; + + pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext); + if((NULL == pHddCtx) || + (NULL == pHddCtx->cfg_ini)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Hdd Context is Null", __func__); + VOS_ASSERT(0); + goto err_sys_close; + } + + ((struct ol_softc *)pHifContext)->enableRamdumpCollection = + pHddCtx->cfg_ini->is_ramdump_enabled; + + macOpenParms.powersaveOffloadEnabled = + pHddCtx->cfg_ini->enablePowersaveOffload; + vStatus = WDA_open(gpVosContext, gpVosContext->pHDDContext, + wlan_hdd_ftm_update_tgt_cfg, NULL, + &macOpenParms); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to open WDA module %d", __func__, vStatus); + VOS_ASSERT(0); + goto err_sys_close; + } + +#if defined(QCA_WIFI_FTM) + pHtcContext = vos_get_context(VOS_MODULE_ID_HTC, gpVosContext); + if (!pHtcContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: failed to get HTC context", __func__); + goto err_wda_close; + } + if (HTCWaitTarget(pHtcContext)) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_wda_close; + } +#endif + + /* initialize the NV module */ + vStatus = vos_nv_open(); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + // NV module cannot be initialized, however the driver is allowed + // to proceed + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to initialize the NV module %d", __func__, vStatus); + goto err_wda_close; + } + + /* If we arrive here, both threads dispatching messages correctly */ + + /* Now proceed to open the MAC */ + + /* UMA is supported in hardware for performing the + frame translation 802.11 <-> 802.3 */ + macOpenParms.frameTransRequired = 1; + + sirStatus = macOpen(&(gpVosContext->pMACContext), gpVosContext->pHDDContext, + &macOpenParms); + + if (eSIR_SUCCESS != sirStatus) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to open MAC %d", __func__, sirStatus); + VOS_ASSERT(0); + goto err_nv_close; + } + +#ifndef QCA_WIFI_FTM + /* Now proceed to open the SME */ + vStatus = sme_Open(gpVosContext->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to open SME %d", __func__, vStatus); + goto err_mac_close; + } + + vStatus = sme_init_chan_list(gpVosContext->pMACContext, + pHddCtx->reg.alpha2, pHddCtx->reg.cc_src); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init sme channel list", __func__); + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS successfully Opened", __func__); + return VOS_STATUS_SUCCESS; + } +#else + return VOS_STATUS_SUCCESS; +#endif + +#ifndef QCA_WIFI_FTM +err_mac_close: +#endif + macClose(gpVosContext->pMACContext); + +err_nv_close: + vos_nv_close(); + +err_wda_close: + WDA_close(gpVosContext); + +err_sys_close: + sysClose(gpVosContext); + +#if defined(QCA_WIFI_FTM) +err_htc_close: + if (gpVosContext->htc_ctx) { + HTCDestroy(gpVosContext->htc_ctx); + gpVosContext->htc_ctx = NULL; + } + +err_bmi_close: + BMICleanup(pHifContext); +#endif /* QCA_WIFI_FTM */ + +err_sched_close: + vos_sched_close(gpVosContext); +err_msg_queue: + vos_mq_deinit(&gpVosContext->freeVosMq); + +err_wda_complete_event: + vos_event_destroy(&gpVosContext->wdaCompleteEvent); + +err_probe_event: + vos_event_destroy(&gpVosContext->ProbeEvent); + + return VOS_STATUS_E_FAILURE; + +} /* wlan_ftm_vos_open() */ + +/*--------------------------------------------------------------------------- + + \brief wlan_ftm_vos_close() - Close the vOSS Module + + The \a wlan_ftm_vos_close() function closes the vOSS Module + + \param vosContext context of vos + + \return VOS_STATUS_SUCCESS - successfully closed + + \sa wlan_ftm_vos_close() + +---------------------------------------------------------------------------*/ + +static VOS_STATUS wlan_ftm_vos_close( v_CONTEXT_t vosContext ) +{ + VOS_STATUS vosStatus; + pVosContextType gpVosContext = (pVosContextType)vosContext; + +#ifndef QCA_WIFI_FTM + vosStatus = sme_Close(((pVosContextType)vosContext)->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close SME %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } +#endif + + vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close MAC %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + ((pVosContextType)vosContext)->pMACContext = NULL; + + vosStatus = vos_nv_close(); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close NV %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + + vosStatus = sysClose( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close SYS %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = WDA_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close WDA %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + +#if defined(QCA_WIFI_FTM) + if (gpVosContext->htc_ctx) + { + HTCStop(gpVosContext->htc_ctx); + HTCDestroy(gpVosContext->htc_ctx); + gpVosContext->htc_ctx = NULL; + } + vosStatus = wma_wmi_service_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + hif_disable_isr(gpVosContext->pHIFContext); +#endif + + vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq); + + vosStatus = vos_event_destroy(&gpVosContext->ProbeEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to destroy ProbeEvent %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = vos_event_destroy(&gpVosContext->wdaCompleteEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to destroy wdaCompleteEvent %d", __func__, vosStatus); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + return VOS_STATUS_SUCCESS; +} + +/*--------------------------------------------------------------------------- + + \brief vos_ftm_preStart() - + + The \a vos_ftm_preStart() function to download CFG. + including: + - ccmStart + + - WDA: triggers the CFG download + + + \param pVosContext: The VOS context + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initialize the scheduler + + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_start + +---------------------------------------------------------------------------*/ +static VOS_STATUS vos_ftm_preStart(v_CONTEXT_t vosContext) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + pVosContextType pVosContext = (pVosContextType)vosContext; +#if defined(QCA_WIFI_FTM) + pVosContextType gpVosContext = vos_get_global_context(VOS_MODULE_ID_VOSS, + NULL); +#endif + + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "vos prestart"); + if (NULL == pVosContext->pWDAContext) + { + VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: WDA NULL context", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* call macPreStart */ + vStatus = macPreStart(pVosContext->pMACContext); + if ( !VOS_IS_STATUS_SUCCESS(vStatus) ) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Failed at macPreStart "); + return VOS_STATUS_E_FAILURE; + } + + /* call ccmStart */ + ccmStart(pVosContext->pMACContext); + + /* Reset wda wait event */ + vos_event_reset(&pVosContext->wdaCompleteEvent); + + + /*call WDA pre start*/ + vStatus = WDA_preStart(pVosContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Failed to WDA prestart "); + ccmStop(pVosContext->pMACContext); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* Need to update time out of complete */ + vStatus = vos_wait_single_event(&pVosContext->wdaCompleteEvent, + HDD_FTM_WMA_PRE_START_TIMEOUT); + if ( vStatus != VOS_STATUS_SUCCESS ) + { + if ( vStatus == VOS_STATUS_E_TIMEOUT ) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout occurred before WDA complete", __func__); + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: WDA_preStart reporting other error", __func__); + } + VOS_ASSERT( 0 ); + return VOS_STATUS_E_FAILURE; + } + +#if defined(QCA_WIFI_FTM) + vStatus = HTCStart(gpVosContext->htc_ctx); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, + "Failed to Start HTC"); + ccmStop(gpVosContext->pMACContext); + VOS_ASSERT( 0 ); + return VOS_STATUS_E_FAILURE; + } + wma_wait_for_ready_event(gpVosContext->pWDAContext); +#endif /* QCA_WIFI_FTM */ + + return VOS_STATUS_SUCCESS; +} + +/**--------------------------------------------------------------------------- + + \brief wlan_hdd_ftm_open() - + + The function hdd_wlan_startup calls this function to initialize the FTM specific modules. + + \param - pAdapter - Pointer HDD Context. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + pVosContextType pVosContext= NULL; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Opening VOSS", __func__); + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL == pVosContext) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Trying to open VOSS without a PreOpen", __func__); + VOS_ASSERT(0); + goto err_vos_status_failure; + } + + vStatus = wlan_ftm_vos_open( pVosContext, 0); + + if ( !VOS_IS_STATUS_SUCCESS( vStatus )) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed", __func__); + goto err_vos_status_failure; + } + + /* + * For Integrated SOC, only needed to start WDA, + * which happens in wlan_hdd_ftm_start() + */ + /* Save the hal context in Adapter */ + pHddCtx->hHal = (tHalHandle)vos_get_context(VOS_MODULE_ID_SME, pVosContext ); + + if ( NULL == pHddCtx->hHal ) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: HAL context is null", __func__); + goto err_ftm_close; + } + + return VOS_STATUS_SUCCESS; + +err_ftm_close: + wlan_ftm_vos_close(pVosContext); + +err_vos_status_failure: + return VOS_STATUS_E_FAILURE; +} + +static int hdd_ftm_service_registration(hdd_context_t *pHddCtx) +{ + hdd_adapter_t *pAdapter; + pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_FTM, "wlan%d", + wlan_hdd_get_intf_addr(pHddCtx), FALSE); + if( NULL == pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed", __func__); + goto err_adapter_open_failure; + } + + /* Initialize the ftm vos event */ + if (vos_event_init(&pHddCtx->ftm.ftm_vos_event) != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to init probeEvent", __func__); + VOS_ASSERT(0); + goto err_adapter_close; + } + + pHddCtx->ftm.ftm_state = WLAN_FTM_INITIALIZED; + + return VOS_STATUS_SUCCESS; + +err_adapter_close: +hdd_close_all_adapters( pHddCtx ); + +err_adapter_open_failure: + + return VOS_STATUS_E_FAILURE; +} + +static int wlan_ftm_stop(hdd_context_t *pHddCtx) +{ + if (pHddCtx->ftm.ftm_state != WLAN_FTM_STARTED) { + hddLog(LOGP, FL("FTM has not started. No need to stop")); + return VOS_STATUS_E_FAILURE; + } + + WDA_stop(pHddCtx->pvosContext, HAL_STOP_TYPE_RF_KILL); + return WLAN_FTM_SUCCESS; +} + +int wlan_hdd_ftm_close(hdd_context_t *pHddCtx) +{ + VOS_STATUS vosStatus; + v_CONTEXT_t vosContext = pHddCtx->pvosContext; + + hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_FTM); + ENTER(); + if(pAdapter == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__); + return VOS_STATUS_E_NOMEM; + } + + if (pHddCtx->ftm.IsCmdPending == TRUE) + { + if (vos_event_set(&pHddCtx->ftm.ftm_vos_event)!= VOS_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos_event_set failed", __func__); + } + } + + if(WLAN_FTM_STARTED == pHddCtx->ftm.ftm_state) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Ftm has been started. stopping ftm", __func__); + wlan_ftm_stop(pHddCtx); + } + + hdd_close_all_adapters( pHddCtx ); + + vosStatus = vos_sched_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close VOSS Scheduler",__func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + //Close VOSS + wlan_ftm_vos_close(vosContext); + + + vosStatus = vos_event_destroy(&pHddCtx->ftm.ftm_vos_event); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to destroy ftm_vos Event",__func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + +#if defined(QCA_WIFI_FTM) && defined(LINUX_QCMBR) + spin_lock_bh(&qcmbr_queue_lock); + if (!list_empty(&qcmbr_queue_head)) { + qcmbr_queue_t *msg_buf, *tmp_buf; + list_for_each_entry_safe(msg_buf, tmp_buf, &qcmbr_queue_head, list) { + list_del(&msg_buf->list); + kfree(msg_buf); + } + } + spin_unlock_bh(&qcmbr_queue_lock); +#endif + + return 0; + +} + +/**--------------------------------------------------------------------------- + + \brief wlan_hdd_ftm_start() - + + This function starts the following modules. + 1) WDA Start. + 2) HTC Start. + 3) MAC Start to download the firmware. + + + \param - pAdapter - Pointer HDD Context. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +static int wlan_hdd_ftm_start(hdd_context_t *pHddCtx) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + pVosContextType pVosContext = (pVosContextType)(pHddCtx->pvosContext); + + if (WLAN_FTM_STARTED == pHddCtx->ftm.ftm_state) + { + return VOS_STATUS_SUCCESS; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Starting CLD SW", __func__); + + /* We support only one instance for now ...*/ + if (pVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: mismatch in context",__func__); + goto err_status_failure; + } + + + if (pVosContext->pMACContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: MAC NULL context",__func__); + goto err_status_failure; + } + + /* Vos preStart is calling */ + if ( !VOS_IS_STATUS_SUCCESS(vos_ftm_preStart(pHddCtx->pvosContext) ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__); + goto err_status_failure; + } + + + + vStatus = WDA_start(pVosContext); + if (vStatus != VOS_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to start WDA",__func__); + goto err_status_failure; + } + + if (hdd_ftm_service_registration(pHddCtx)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed", __func__); + goto err_ftm_service_reg; + } + + pHddCtx->ftm.ftm_state = WLAN_FTM_STARTED; + + return VOS_STATUS_SUCCESS; + +err_ftm_service_reg: + wlan_hdd_ftm_close(pHddCtx); + + +err_status_failure: + + return VOS_STATUS_E_FAILURE; + +} + +#if defined(QCA_WIFI_FTM) +int hdd_ftm_start(hdd_context_t *pHddCtx) +{ + return wlan_hdd_ftm_start(pHddCtx); +} +#endif + +#if defined(QCA_WIFI_FTM) +int hdd_ftm_stop(hdd_context_t *pHddCtx) +{ + return wlan_ftm_stop(pHddCtx); +} +#endif + +#if defined(QCA_WIFI_FTM) +#if defined(LINUX_QCMBR) +static int wlan_hdd_qcmbr_command(hdd_adapter_t *pAdapter, qcmbr_data_t *pqcmbr_data) +{ + int ret = 0; + qcmbr_queue_t *qcmbr_buf = NULL; + + switch (pqcmbr_data->cmd) { + case ATH_XIOCTL_UNIFIED_UTF_CMD: { + pqcmbr_data->copy_to_user = 0; + if (pqcmbr_data->length) { + if (wlan_hdd_ftm_testmode_cmd(pqcmbr_data->buf, + pqcmbr_data->length) + != VOS_STATUS_SUCCESS) { + ret = -EBUSY; + } else { + ret = 0; + } + } + } + break; + + case ATH_XIOCTL_UNIFIED_UTF_RSP: { + pqcmbr_data->copy_to_user = 1; + if (!list_empty(&qcmbr_queue_head)) { + spin_lock_bh(&qcmbr_queue_lock); + qcmbr_buf = list_first_entry(&qcmbr_queue_head, + qcmbr_queue_t, list); + list_del(&qcmbr_buf->list); + spin_unlock_bh(&qcmbr_queue_lock); + ret = 0; + } else { + ret = -1; + } + + if (!ret) { + memcpy(pqcmbr_data->buf, qcmbr_buf->utf_buf, + (MAX_UTF_LENGTH + 4)); + kfree(qcmbr_buf); + } else { + ret = -EAGAIN; + } + } + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static int wlan_hdd_qcmbr_compat_ioctl(hdd_adapter_t *pAdapter, + struct ifreq *ifr) +{ + qcmbr_data_t *qcmbr_data; + int ret = 0; + + qcmbr_data = kzalloc(sizeof(qcmbr_data_t), GFP_KERNEL); + if (qcmbr_data == NULL) + return -ENOMEM; + + if (copy_from_user(qcmbr_data, ifr->ifr_data, sizeof(*qcmbr_data))) { + ret = -EFAULT; + goto exit; + } + + ret = wlan_hdd_qcmbr_command(pAdapter, qcmbr_data); + if (qcmbr_data->copy_to_user) { + ret = copy_to_user(ifr->ifr_data, qcmbr_data->buf, + (MAX_UTF_LENGTH + 4)); + } + +exit: + kfree(qcmbr_data); + return ret; +} +#else /* CONFIG_COMPAT */ +static int wlan_hdd_qcmbr_compat_ioctl(hdd_adapter_t *pAdapter, + struct ifreq *ifr) +{ + return 0; +} +#endif /* CONFIG_COMPAT */ + +static int wlan_hdd_qcmbr_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr) +{ + qcmbr_data_t *qcmbr_data; + int ret = 0; + + qcmbr_data = kzalloc(sizeof(qcmbr_data_t), GFP_KERNEL); + if (qcmbr_data == NULL) + return -ENOMEM; + + if (copy_from_user(qcmbr_data, ifr->ifr_data, sizeof(*qcmbr_data))) { + ret = -EFAULT; + goto exit; + } + + ret = wlan_hdd_qcmbr_command(pAdapter, qcmbr_data); + if (qcmbr_data->copy_to_user) { + ret = copy_to_user(ifr->ifr_data, qcmbr_data->buf, + (MAX_UTF_LENGTH + 4)); + } + +exit: + kfree(qcmbr_data); + return ret; +} + +int wlan_hdd_qcmbr_unified_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr) +{ + int ret = 0; + + if (is_compat_task()) { + ret = wlan_hdd_qcmbr_compat_ioctl(pAdapter, ifr); + } else { + ret = wlan_hdd_qcmbr_ioctl(pAdapter, ifr); + } + + return ret; +} + +static void WLANQCMBR_McProcessMsg(v_VOID_t *message) +{ + qcmbr_queue_t *qcmbr_buf = NULL; + u_int32_t data_len; + + data_len = *((u_int32_t *)message) + sizeof(u_int32_t); + qcmbr_buf = kzalloc(sizeof(qcmbr_queue_t), GFP_KERNEL); + if (qcmbr_buf != NULL) { + memcpy(qcmbr_buf->utf_buf, message, data_len); + spin_lock_bh(&qcmbr_queue_lock); + list_add_tail(&(qcmbr_buf->list), &qcmbr_queue_head); + spin_unlock_bh(&qcmbr_queue_lock); + } +} +#endif /*LINUX_QCMBR*/ + +VOS_STATUS WLANFTM_McProcessMsg (v_VOID_t *message) +{ + void *data; + u_int32_t data_len; + + if (!message) + return VOS_STATUS_E_INVAL; + + data_len = *((u_int32_t *)message); + data = (u_int32_t *)message + 1; + +#if defined(LINUX_QCMBR) + WLANQCMBR_McProcessMsg(message); +#else +#ifdef CONFIG_NL80211_TESTMODE + wlan_hdd_testmode_rx_event(data, (size_t)data_len); +#endif +#endif + + vos_mem_free(message); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wlan_hdd_ftm_testmode_cmd(void *data, int len) +{ + struct ar6k_testmode_cmd_data *cmd_data; + + cmd_data = (struct ar6k_testmode_cmd_data *) + vos_mem_malloc(sizeof(*cmd_data)); + + if (!cmd_data) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("Failed to allocate FTM command data")); + return VOS_STATUS_E_NOMEM; + } + + cmd_data->data = vos_mem_malloc(len); + + if (!cmd_data->data) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("Failed to allocate FTM command data buffer")); + vos_mem_free(cmd_data); + return VOS_STATUS_E_NOMEM; + } + + cmd_data->len = len; + vos_mem_copy(cmd_data->data, data, len); + + if (wlan_ftm_postmsg((v_U8_t *)cmd_data, sizeof(*cmd_data))) { + vos_mem_free(cmd_data->data); + vos_mem_free(cmd_data); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} +#endif /*QCA_WIFI_FTM*/ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c new file mode 100644 index 000000000000..3367c97b4b34 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c @@ -0,0 +1,7114 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_hostapd.c + \brief WLAN Host Device Driver implementation + + ========================================================================*/ +/**========================================================================= + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 04/5/09 Shailender Created module. + 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure + ==========================================================================*/ +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlan_nlink_common.h" +#include "wlan_btc_svc.h" +#include "wlan_hdd_p2p.h" +#ifdef IPA_OFFLOAD +#include +#endif +#include "cfgApi.h" +#include "wniCfgAp.h" +#include "wlan_hdd_misc.h" +#include +#if defined CONFIG_CNSS +#include +#endif + +#include "wma.h" +#ifdef DEBUG +#include "wma_api.h" +#endif +extern int process_wma_set_command(int sessid, int paramid, + int sval, int vpdev); +#include "wlan_hdd_trace.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "wlan_hdd_cfg.h" +#include +#include "wlan_hdd_tsf.h" + +#define IS_UP(_dev) \ + (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP)) +#define IS_UP_AUTO(_ic) \ + (IS_UP((_ic)->ic_dev) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO) +#define WE_WLAN_VERSION 1 +#define WE_GET_STA_INFO_SIZE 30 +/* WEXT limitation: MAX allowed buf len for any * + * IW_PRIV_TYPE_CHAR is 2Kbytes * + */ +#define WE_SAP_MAX_STA_INFO 0x7FF + +#define RC_2_RATE_IDX(_rc) ((_rc) & 0x7) +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) +#define RC_2_RATE_IDX_11AC(_rc) ((_rc) & 0xf) +#define HT_RC_2_STREAMS_11AC(_rc) ((((_rc) & 0x30) >> 4) + 1) + +#define SAP_24GHZ_CH_COUNT (14) +#define ACS_SCAN_EXPIRY_TIMEOUT_S 4 + +/*--------------------------------------------------------------------------- + * Function definitions + *-------------------------------------------------------------------------*/ + +/**--------------------------------------------------------------------------- + + \brief hdd_hostapd_channel_wakelock_init + + \param - Pointer to HDD context + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_hostapd_channel_wakelock_init(hdd_context_t *pHddCtx) +{ + /* Initialize the wakelock */ + vos_wake_lock_init(&pHddCtx->sap_dfs_wakelock, "sap_dfs_wakelock"); + atomic_set(&pHddCtx->sap_dfs_ref_cnt, 0); +} + +/**--------------------------------------------------------------------------- + + \brief hdd_hostapd_channel_allow_suspend - Allow suspend in a channel. + + Called when, + 1. BSS stopped + 2. Channel switch + + \param - pAdapter, channel + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_hostapd_channel_allow_suspend(hdd_adapter_t *pAdapter, + u_int8_t channel) +{ + + hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx); + hdd_hostapd_state_t *pHostapdState = + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + hddLog(LOG1, FL("bssState: %d, channel: %d, dfs_ref_cnt: %d"), + pHostapdState->bssState, channel, + atomic_read(&pHddCtx->sap_dfs_ref_cnt)); + + /* Return if BSS is already stopped */ + if (pHostapdState->bssState == BSS_STOP) + return; + + /* Release wakelock when no more DFS channels are used */ + if (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(channel)) { + if (atomic_dec_and_test(&pHddCtx->sap_dfs_ref_cnt)) { + hddLog(LOGE, FL("DFS: allowing suspend (chan %d)"), channel); + vos_wake_lock_release(&pHddCtx->sap_dfs_wakelock, + WIFI_POWER_EVENT_WAKELOCK_DFS); + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.dfs); + } + } +} + +/**--------------------------------------------------------------------------- + + \brief hdd_hostapd_channel_prevent_suspend - Prevent suspend in a channel. + + Called when, + 1. BSS started + 2. Channel switch + + \param - pAdapter, channel + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_hostapd_channel_prevent_suspend(hdd_adapter_t *pAdapter, + u_int8_t channel) +{ + hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx); + hdd_hostapd_state_t *pHostapdState = + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + hddLog(LOG1, FL("bssState: %d, channel: %d, dfs_ref_cnt: %d"), + pHostapdState->bssState, channel, + atomic_read(&pHddCtx->sap_dfs_ref_cnt)); + + /* Return if BSS is already started && wakelock is acquired */ + if ((pHostapdState->bssState == BSS_START) && + (atomic_read(&pHddCtx->sap_dfs_ref_cnt) >= 1)) + return; + + /* Acquire wakelock if we have at least one DFS channel in use */ + if (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(channel)) { + if (atomic_inc_return(&pHddCtx->sap_dfs_ref_cnt) == 1) { + hddLog(LOGE, FL("DFS: preventing suspend (chan %d)"), channel); + vos_runtime_pm_prevent_suspend(pHddCtx->runtime_context.dfs); + vos_wake_lock_acquire(&pHddCtx->sap_dfs_wakelock, + WIFI_POWER_EVENT_WAKELOCK_DFS); + } + } +} + +/**--------------------------------------------------------------------------- + + \brief hdd_hostapd_channel_wakelock_deinit + + \param - Pointer to HDD context + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_hostapd_channel_wakelock_deinit(hdd_context_t *pHddCtx) +{ + if (atomic_read(&pHddCtx->sap_dfs_ref_cnt)) { + /* Release wakelock */ + vos_wake_lock_release(&pHddCtx->sap_dfs_wakelock, + WIFI_POWER_EVENT_WAKELOCK_DRIVER_EXIT); + /* Reset the reference count */ + atomic_set(&pHddCtx->sap_dfs_ref_cnt, 0); + hddLog(LOGE, FL("DFS: allowing suspend")); + } + + /* Destroy lock */ + vos_wake_lock_destroy(&pHddCtx->sap_dfs_wakelock); +} + +/** + * __hdd_hostapd_open() - HDD Open function for hostapd interface + * @dev: pointer to net device + * + * This is called in response to ifconfig up + * + * Return: 0 on success, error number otherwise + */ +static int __hdd_hostapd_open(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = netdev_priv(dev); + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_HOSTAPD_OPEN_REQUEST, NO_SESSION, 0)); + + if (WLAN_HDD_GET_CTX(pAdapter)->isLoadInProgress || + WLAN_HDD_GET_CTX(pAdapter)->isUnloadInProgress) + { + hddLog(LOGE, FL("Driver load/unload in progress, ignore adapter open")); + goto done; + } + + //Turn ON carrier state + netif_carrier_on(dev); + //Enable all Tx queues + hddLog(LOG1, FL("Enabling queues")); + netif_tx_start_all_queues(dev); +done: + EXIT(); + return 0; +} + +/** + * hdd_hostapd_open() - SSR wrapper for __hdd_hostapd_open + * @dev: pointer to net device + * + * Return: 0 on success, error number otherwise + */ +static int hdd_hostapd_open(struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_hostapd_open(dev); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_hostapd_stop() - HDD stop function for hostapd interface + * @dev: pointer to net_device + * + * This is called in response to ifconfig down + * + * Return: 0 on success, error number otherwise + */ +static int __hdd_hostapd_stop(struct net_device *dev) +{ + ENTER(); + + if (NULL != dev) { + //Stop all tx queues + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + + //Turn OFF carrier state + netif_carrier_off(dev); + } + + EXIT(); + return 0; +} + +/** + * hdd_hostapd_stop() - SSR wrapper for__hdd_hostapd_stop + * @dev: pointer to net_device + * + * This is called in response to ifconfig down + * + * Return: 0 on success, error number otherwise + */ +int hdd_hostapd_stop(struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_hostapd_stop(dev); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_hostapd_uninit() - HDD uninit function + * @dev: pointer to net_device + * + * This is called during the netdev unregister to uninitialize all data + * associated with the device + * + * Return: 0 on success, error number otherwise + */ +static void __hdd_hostapd_uninit(struct net_device *dev) +{ + hdd_adapter_t *adapter = netdev_priv(dev); + hdd_context_t *hdd_ctx; + + ENTER(); + + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + hddLog(LOGE, FL("Invalid magic")); + return; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (NULL == hdd_ctx) { + hddLog(LOGE, FL("NULL hdd_ctx")); + return; + } + + hdd_deinit_adapter(hdd_ctx, adapter, true); + + /* after uninit our adapter structure will no longer be valid */ + adapter->dev = NULL; + adapter->magic = 0; + + EXIT(); +} + +/** + * hdd_hostapd_uninit() - SSR wrapper for __hdd_hostapd_uninit + * @dev: pointer to net_device + * + * Return: 0 on success, error number otherwise + */ +static void hdd_hostapd_uninit(struct net_device *dev) +{ + vos_ssr_protect(__func__); + __hdd_hostapd_uninit(dev); + vos_ssr_unprotect(__func__); +} + +/** + * __hdd_hostapd_change_mtu() - change mtu + * @dev: pointer to net_device + * @new_mtu: new mtu + * + * Return: 0 on success, error number otherwise + */ +static int __hdd_hostapd_change_mtu(struct net_device *dev, int new_mtu) +{ + return 0; +} + +/** + * hdd_hostapd_change_mtu() - SSR wrapper for __hdd_hostapd_change_mtu + * @dev: pointer to net_device + * @new_mtu: new mtu + * + * Return: 0 on success, error number otherwise + */ +static int hdd_hostapd_change_mtu(struct net_device *dev, int new_mtu) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_hostapd_change_mtu(dev, new_mtu); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int hdd_hostapd_driver_command(hdd_adapter_t *pAdapter, + hdd_priv_data_t *priv_data) +{ + tANI_U8 *command = NULL; + int ret = 0; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* + * Note that valid pointers are provided by caller + */ + + ENTER(); + + if (priv_data->total_len <= 0 || + priv_data->total_len > HOSTAPD_IOCTL_COMMAND_STRLEN_MAX) + { + /* below we allocate one more byte for command buffer. + * To avoid addition overflow total_len should be + * smaller than INT_MAX. */ + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: integer out of range len %d", + __func__, priv_data->total_len); + ret = -EFAULT; + goto exit; + } + + /* Allocate +1 for '\0' */ + command = kmalloc((priv_data->total_len + 1), GFP_KERNEL); + if (!command) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to allocate memory", __func__); + ret = -ENOMEM; + goto exit; + } + + if (copy_from_user(command, priv_data->buf, priv_data->total_len)) + { + ret = -EFAULT; + goto exit; + } + + /* Make sure the command is NUL-terminated */ + command[priv_data->total_len] = '\0'; + + hddLog(VOS_TRACE_LEVEL_INFO, + "***HOSTAPD*** : Received %s cmd from Wi-Fi GUI***", command); + + if (strncmp(command, "P2P_SET_NOA", 11) == 0) + { + hdd_setP2pNoa(pAdapter->dev, command); + } + else if (strncmp(command, "P2P_SET_PS", 10) == 0) + { + hdd_setP2pOpps(pAdapter->dev, command); + } + else if (strncmp(command, "MIRACAST", 8) == 0) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Received MIRACAST command", __func__); + ret = hdd_set_miracast_mode(pAdapter, command); + } +exit: + if (command) + { + kfree(command); + } + EXIT(); + return ret; +} + +#ifdef CONFIG_COMPAT +static int hdd_hostapd_driver_compat_ioctl(hdd_adapter_t *pAdapter, + struct ifreq *ifr) +{ + struct { + compat_uptr_t buf; + int used_len; + int total_len; + } compat_priv_data; + hdd_priv_data_t priv_data; + int ret = 0; + + /* + * Note that pAdapter and ifr have already been verified by caller, + * and HDD context has also been validated + */ + if (copy_from_user(&compat_priv_data, ifr->ifr_data, + sizeof(compat_priv_data))) { + ret = -EFAULT; + goto exit; + } + priv_data.buf = compat_ptr(compat_priv_data.buf); + priv_data.used_len = compat_priv_data.used_len; + priv_data.total_len = compat_priv_data.total_len; + ret = hdd_hostapd_driver_command(pAdapter, &priv_data); + exit: + return ret; +} +#else /* CONFIG_COMPAT */ +static int hdd_hostapd_driver_compat_ioctl(hdd_adapter_t *pAdapter, + struct ifreq *ifr) +{ + /* will never be invoked */ + return 0; +} +#endif /* CONFIG_COMPAT */ + +static int hdd_hostapd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr) +{ + hdd_priv_data_t priv_data; + int ret = 0; + + /* + * Note that pAdapter and ifr have already been verified by caller, + * and HDD context has also been validated + */ + if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) { + ret = -EFAULT; + } else { + ret = hdd_hostapd_driver_command(pAdapter, &priv_data); + } + return ret; +} + +/** + * __hdd_hostapd_ioctl() - hostapd ioctl + * @dev: pointer to net_device + * @ifr: pointer to ifreq structure + * @cmd: command + * + * Return; 0 on success, error number otherwise + */ +static int __hdd_hostapd_ioctl(struct net_device *dev, + struct ifreq *ifr, int cmd) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int ret; + + ENTER(); + + if (dev != pAdapter->dev) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter/dev inconsistency", __func__); + ret = -ENODEV; + goto exit; + } + + if ((!ifr) || (!ifr->ifr_data)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("ifr or ifr->ifr_data is NULL")); + ret = -EINVAL; + goto exit; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret) { + ret = -EBUSY; + goto exit; + } + + switch (cmd) { + case (SIOCDEVPRIVATE + 1): + if (is_compat_task()) + ret = hdd_hostapd_driver_compat_ioctl(pAdapter, ifr); + else + ret = hdd_hostapd_driver_ioctl(pAdapter, ifr); + break; + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d", + __func__, cmd); + ret = -EINVAL; + break; + } + exit: + EXIT(); + return ret; +} + +/** + * hdd_hostapd_ioctl() - SSR wrapper for __hdd_hostapd_ioctl + * @dev: pointer to net_device + * @ifr: pointer to ifreq structure + * @cmd: command + * + * Return; 0 on success, error number otherwise + */ +static int hdd_hostapd_ioctl(struct net_device *dev, + struct ifreq *ifr, int cmd) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_hostapd_ioctl(dev, ifr, cmd); + vos_ssr_unprotect(__func__); + + return ret; +} + + +#ifdef QCA_HT_2040_COEX +VOS_STATUS hdd_set_sap_ht2040_mode(hdd_adapter_t *pHostapdAdapter, + tANI_U8 channel_type) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: change HT20/40 mode", __func__); + + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + if ( NULL == hHal ) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Hal ctx is null", __func__); + return VOS_STATUS_E_FAULT; + } + halStatus = sme_SetHT2040Mode(hHal, pHostapdAdapter->sessionId, + channel_type, eANI_BOOLEAN_TRUE); + if (halStatus == eHAL_STATUS_FAILURE ) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to change HT20/40 mode", __func__); + return VOS_STATUS_E_FAILURE; + } + } + return VOS_STATUS_SUCCESS; +} +#endif + +#ifdef FEATURE_WLAN_FORCE_SAP_SCC +/**--------------------------------------------------------------------------- + \brief hdd_restart_softap() - + Restart SAP on STA channel to support + STA + SAP concurrency. + + --------------------------------------------------------------------------*/ +void hdd_restart_softap(hdd_context_t *pHddCtx, + hdd_adapter_t *pHostapdAdapter) +{ + tHddAvoidFreqList hdd_avoid_freq_list; + + /* generate vendor specific event */ + vos_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList)); + hdd_avoid_freq_list.avoidFreqRange[0].startFreq = + vos_chan_to_freq(pHostapdAdapter->sessionCtx.ap.operatingChannel); + hdd_avoid_freq_list.avoidFreqRange[0].endFreq = + vos_chan_to_freq(pHostapdAdapter->sessionCtx.ap.operatingChannel); + hdd_avoid_freq_list.avoidFreqRangeCount = 1; + wlan_hdd_send_avoid_freq_event(pHddCtx, &hdd_avoid_freq_list); +} +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + +/** + * __hdd_hostapd_set_mac_address() - set mac address + * @dev: pointer to net_device + * @addr: mac address + * + * This function sets the user specified mac address using + * the command ifconfig wlanX hw ether . + * + * Return: 0 on success, error number otherwise + */ +static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *psta_mac_addr = addr; + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret = 0; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN); + EXIT(); + return 0; +} + +/** + * hdd_hostapd_set_mac_address() - set mac address + * @dev: pointer to net_device + * @addr: mac address + * + * Return: 0 on success, error number otherwise + */ +static int hdd_hostapd_set_mac_address(struct net_device *dev, void *addr) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_hostapd_set_mac_address(dev, addr); + vos_ssr_unprotect(__func__); + + return ret; +} + +void hdd_hostapd_inactivity_timer_cb(v_PVOID_t usrDataForCallback) +{ + struct net_device *dev = (struct net_device *)usrDataForCallback; + v_BYTE_t we_custom_event[64]; + union iwreq_data wrqu; +#ifdef DISABLE_CONCURRENCY_AUTOSAVE + VOS_STATUS vos_status; + hdd_adapter_t *pHostapdAdapter; + hdd_ap_ctx_t *pHddApCtx; +#endif /*DISABLE_CONCURRENCY_AUTOSAVE */ + + /* event_name space-delimiter driver_module_name */ + /* Format of the event is "AUTO-SHUT.indication" " " "module_name" */ + char * autoShutEvent = "AUTO-SHUT.indication" " " KBUILD_MODNAME; + int event_len = strlen(autoShutEvent) + 1; /* For the NULL at the end */ + + ENTER(); + +#ifdef DISABLE_CONCURRENCY_AUTOSAVE + if (vos_concurrent_open_sessions_running()) + { + /* + This timer routine is going to be called only when AP + persona is up. + If there are concurrent sessions running we do not want + to shut down the Bss.Instead we run the timer again so + that if Autosave is enabled next time and other session + was down only then we bring down AP + */ + pHostapdAdapter = netdev_priv(dev); + if ((NULL == pHostapdAdapter) || + (WLAN_HDD_ADAPTER_MAGIC != pHostapdAdapter->magic)) + { + hddLog(LOGE, FL("invalid adapter: %p"), pHostapdAdapter); + return; + } + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + vos_status = vos_timer_start( + &pHddApCtx->hdd_ap_inactivity_timer, + (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff + * 1000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + hddLog(LOGE, FL("Failed to init AP inactivity timer")); + } + EXIT(); + return; + } +#endif /*DISABLE_CONCURRENCY_AUTOSAVE */ + memset(&we_custom_event, '\0', sizeof(we_custom_event)); + memcpy(&we_custom_event, autoShutEvent, event_len); + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = event_len; + + hddLog(LOG1, FL("Shutting down AP interface due to inactivity")); + wireless_send_event(dev, IWEVCUSTOM, &wrqu, (char *)we_custom_event); + + EXIT(); +} + +static VOS_STATUS +hdd_change_mcc_go_beacon_interval(hdd_adapter_t *pHostapdAdapter) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: UPDATE Beacon Params", __func__); + + if(VOS_STA_SAP_MODE == vos_get_conparam ( )){ + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + if ( NULL == hHal ){ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Hal ctx is null", __func__); + return VOS_STATUS_E_FAULT; + } + halStatus = sme_ChangeMCCBeaconInterval(hHal, pHostapdAdapter->sessionId); + if(halStatus == eHAL_STATUS_FAILURE ){ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to update Beacon Params", __func__); + return VOS_STATUS_E_FAILURE; + } + } + return VOS_STATUS_SUCCESS; +} + +void hdd_clear_all_sta(hdd_adapter_t *pHostapdAdapter, v_PVOID_t usrDataForCallback) +{ + v_U8_t staId = 0; + struct net_device *dev; + struct tagCsrDelStaParams delStaParams; + dev = (struct net_device *)usrDataForCallback; + + hddLog(LOGE, FL("Clearing all the STA entry....")); + for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) + { + if ( pHostapdAdapter->aStaInfo[staId].isUsed && + ( staId != (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uBCStaId)) + { + WLANSAP_PopulateDelStaParams(&pHostapdAdapter->aStaInfo[staId].macAddrSTA.bytes[0], + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + (SIR_MAC_MGMT_DISASSOC >> 4), + &delStaParams); + //Disconnect all the stations + hdd_softap_sta_disassoc(pHostapdAdapter, &delStaParams); + } + } +} + +static int hdd_stop_bss_link(hdd_adapter_t *pHostapdAdapter, + v_PVOID_t usrDataForCallback) +{ + struct net_device *dev; + hdd_context_t *pHddCtx = NULL; + VOS_STATUS status = VOS_STATUS_SUCCESS; + dev = (struct net_device *)usrDataForCallback; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) + { +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_StopBss(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext); +#endif + if (VOS_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("Deleting SAP/P2P link!!!!!!")); + + clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + wlan_hdd_decr_active_session(pHddCtx, pHostapdAdapter->device_mode); + } + EXIT(); + return (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY; +} + +#ifdef SAP_AUTH_OFFLOAD +void 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 = NULL; + + /* Prepare the request to send to SME */ + sap_offload_info = vos_mem_malloc(sizeof(*sap_offload_info)); + if (NULL == sap_offload_info) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: could not allocate tSirSapOffloadInfo!", __func__); + return; + } + + vos_mem_zero(sap_offload_info, sizeof(*sap_offload_info)); + + sap_offload_info->vdev_id = pHostapdAdapter->sessionId; + sap_offload_info->sap_auth_offload_enable = + pHddCtx->cfg_ini->enable_sap_auth_offload && 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) { + 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); + goto end; + } + } + + 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__); + goto end; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sme_set_sap_auth_offload successfully!", __func__); + +end: + vos_mem_free(sap_offload_info); + return; +} + + +/** + * hdd_set_client_block_info - get client block info from ini file + * @padapter: hdd adapter pointer + * + * This function reads client block related info from ini file, these + * configurations will be sent to fw through wmi. + * + * Return: 0 on success, otherwise error value + */ +int hdd_set_client_block_info(hdd_adapter_t *padapter) +{ + hdd_context_t *phddctx = WLAN_HDD_GET_CTX(padapter); + struct sblock_info client_block_info; + eHalStatus status; + + /* prepare the request to send to SME */ + client_block_info.vdev_id = padapter->sessionId; + client_block_info.reconnect_cnt = + phddctx->cfg_ini->connect_fail_count; + + client_block_info.con_fail_duration = + phddctx->cfg_ini->connect_fail_duration; + + client_block_info.block_duration = + phddctx->cfg_ini->connect_block_duration; + + status = sme_set_client_block_info(phddctx->hHal, &client_block_info); + if (eHAL_STATUS_FAILURE == status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_set_client_block_info!", __func__); + return -EIO; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sme_set_client_block_info success!", __func__); + + return 0; +} +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * hdd_issue_stored_joinreq() - This function will trigger stations's + * cached connect request to proceed. + * @hdd_ctx: pointer to hdd context. + * @sta_adapter: pointer to station adapter. + * + * This function will call SME to release station's stored/cached connect + * request to proceed. + * + * Return: none. + */ +static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter, + hdd_context_t *hdd_ctx) +{ + tHalHandle hal_handle; + uint32_t roam_id; + + if (NULL == sta_adapter) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Invalid station adapter, ignore issueing join req")); + return; + } + hal_handle = WLAN_HDD_GET_HAL_CTX(sta_adapter); + + if (true == hdd_is_sta_connection_pending(hdd_ctx)) { + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_ISSUE_JOIN_REQ, + sta_adapter->sessionId, roam_id)); + if (VOS_STATUS_SUCCESS != + sme_issue_stored_joinreq(hal_handle, + &roam_id, + sta_adapter->sessionId)) { + /* change back to NotAssociated */ + hdd_connSetConnectionState(sta_adapter, + eConnectionState_NotConnected); + } + hdd_change_sta_conn_pending_status(hdd_ctx, false); + } +} + +/** + * hdd_chan_change_notify() - Function to notify hostapd about channel change + * @hostapd_adapter hostapd adapter + * @dev: Net device structure + * @oper_chan: New operating channel + * + * This function is used to notify hostapd about the channel change + * + * Return: Success on intimating userspace + * + */ +VOS_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, + struct net_device *dev, + uint8_t oper_chan) +{ + struct ieee80211_channel *chan; + struct cfg80211_chan_def chandef; + enum nl80211_channel_type channel_type; + eCsrPhyMode phy_mode; + ePhyChanBondState cb_mode; + uint32_t freq; + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(hostapd_adapter); + + if (NULL == hal) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: hal is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + freq = vos_chan_to_freq(oper_chan); + + chan = __ieee80211_get_channel(hostapd_adapter->wdev.wiphy, freq); + + if (!chan) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid input frequency for channel conversion", + __func__); + return VOS_STATUS_E_FAILURE; + } + +#ifdef WLAN_FEATURE_MBSSID + phy_mode = wlansap_get_phymode(WLAN_HDD_GET_SAP_CTX_PTR(hostapd_adapter)); +#else + phy_mode = wlansap_get_phymode( + (WLAN_HDD_GET_CTX(hostapd_adapter))->pvosContext); +#endif + + if (oper_chan <= 14) + cb_mode = sme_GetCBPhyStateFromCBIniValue( + sme_GetChannelBondingMode24G(hal)); + else + cb_mode = sme_GetCBPhyStateFromCBIniValue( + sme_GetChannelBondingMode5G(hal)); + + switch (phy_mode) { + case eCSR_DOT11_MODE_11n: + case eCSR_DOT11_MODE_11n_ONLY: + case eCSR_DOT11_MODE_11ac: + case eCSR_DOT11_MODE_11ac_ONLY: + if (cb_mode == PHY_SINGLE_CHANNEL_CENTERED) + channel_type = NL80211_CHAN_HT20; + else if (cb_mode == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + channel_type = NL80211_CHAN_HT40MINUS; + else if (cb_mode == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + channel_type = NL80211_CHAN_HT40PLUS; + else + channel_type = NL80211_CHAN_HT40PLUS; + break; + default: + channel_type = NL80211_CHAN_NO_HT; + break; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: phy_mode %d cb_mode %d chann_type %d oper_chan %d", + __func__, phy_mode, cb_mode, channel_type, oper_chan); + + cfg80211_chandef_create(&chandef, chan, channel_type); + + cfg80211_ch_switch_notify(dev, &chandef); + + return VOS_STATUS_SUCCESS; +} + +/** + * hdd_send_radar_event() - Function to send radar events to user space + * @hdd_context: HDD context + * @event: Type of radar event + * @dfs_info: Structure containing DFS channel and country + * @wdev: Wireless device structure + * + * This function is used to send radar events such as CAC start, CAC + * end etc., to userspace + * + * Return: Success on sending notifying userspace + * + */ +VOS_STATUS hdd_send_radar_event(hdd_context_t *hdd_context, + eSapHddEvent event, + struct wlan_dfs_info dfs_info, + struct wireless_dev *wdev) +{ + + struct sk_buff *vendor_event; + enum qca_nl80211_vendor_subcmds_index index; + uint32_t freq, ret; + uint32_t data_size; + + if (!hdd_context) { + hddLog(LOGE, FL("HDD context is NULL")); + return VOS_STATUS_E_FAILURE; + } + + freq = vos_chan_to_freq(dfs_info.channel); + + switch (event) { + case eSAP_DFS_CAC_START: + index = + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX; + data_size = sizeof(uint32_t); + break; + case eSAP_DFS_CAC_END: + index = + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX; + data_size = sizeof(uint32_t); + break; + case eSAP_DFS_RADAR_DETECT: + index = + QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX; + data_size = sizeof(uint32_t); + break; + default: + return VOS_STATUS_E_FAILURE; + } + + vendor_event = cfg80211_vendor_event_alloc(hdd_context->wiphy, + wdev, + data_size + NLMSG_HDRLEN, + index, + GFP_KERNEL); + if (!vendor_event) { + hddLog(LOGE, + FL("cfg80211_vendor_event_alloc failed for %d"), index); + return VOS_STATUS_E_FAILURE; + } + + ret = nla_put_u32(vendor_event, NL80211_ATTR_WIPHY_FREQ, freq); + + if (ret) { + hddLog(LOGE, FL("NL80211_ATTR_WIPHY_FREQ put fail")); + kfree_skb(vendor_event); + return VOS_STATUS_E_FAILURE; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback) +{ + hdd_adapter_t *pHostapdAdapter; + hdd_ap_ctx_t *pHddApCtx; + hdd_hostapd_state_t *pHostapdState; + struct net_device *dev; + eSapHddEvent sapEvent; + union iwreq_data wrqu; + v_BYTE_t *we_custom_event_generic = NULL; + int we_event = 0; + int i = 0; + v_U8_t staId; + VOS_STATUS vos_status; + v_BOOL_t bWPSState; + v_BOOL_t bAuthRequired = TRUE; + tpSap_AssocMacAddr pAssocStasArray = NULL; + char unknownSTAEvent[IW_CUSTOM_MAX+1]; + char maxAssocExceededEvent[IW_CUSTOM_MAX+1]; + v_BYTE_t we_custom_start_event[64]; + char *startBssEvent; + hdd_context_t *pHddCtx; + hdd_scaninfo_t *pScanInfo = NULL; + struct iw_michaelmicfailure msg; + v_U8_t ignoreCAC = 0; + hdd_config_t *cfg = NULL; + struct wlan_dfs_info dfs_info; + v_U8_t cc_len = WLAN_SVC_COUNTRY_CODE_LEN; + hdd_adapter_t *con_sap_adapter; + VOS_STATUS status = VOS_STATUS_SUCCESS; +#if defined CONFIG_CNSS + int ret = 0; +#endif + + dev = (struct net_device *)usrDataForCallback; + if (!dev) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: usrDataForCallback is null", __func__); + return eHAL_STATUS_FAILURE; + } + + pHostapdAdapter = netdev_priv(dev); + + if ((NULL == pHostapdAdapter) || + (WLAN_HDD_ADAPTER_MAGIC != pHostapdAdapter->magic)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter or adapter has invalid magic"); + return eHAL_STATUS_FAILURE; + } + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + + if (!pSapEvent) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: pSapEvent is null", __func__); + return eHAL_STATUS_FAILURE; + } + + sapEvent = pSapEvent->sapHddEventCode; + memset(&wrqu, '\0', sizeof(wrqu)); + pHddCtx = (hdd_context_t*)(pHostapdAdapter->pHddCtx); + + if (!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is null")); + return eHAL_STATUS_FAILURE; + } + + cfg = pHddCtx->cfg_ini; + + if (!cfg) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD config is null")); + return eHAL_STATUS_FAILURE; + } + + dfs_info.channel = pHddApCtx->operatingChannel; + sme_GetCountryCode(pHddCtx->hHal, dfs_info.country_code, &cc_len); + + switch(sapEvent) + { + case eSAP_START_BSS_EVENT : + hddLog(LOG1, FL("BSS configured status = %s, channel = %u, bc sta Id = %d"), + pSapEvent->sapevt.sapStartBssCompleteEvent.status ? "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS", + pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel, + pSapEvent->sapevt.sapStartBssCompleteEvent.staId); + + pHostapdAdapter->sessionId = + pSapEvent->sapevt.sapStartBssCompleteEvent.sessionId; + + pHostapdState->vosStatus = pSapEvent->sapevt.sapStartBssCompleteEvent.status; + vos_status = vos_event_set(&pHostapdState->vosEvent); + + if (!VOS_IS_STATUS_SUCCESS(vos_status) || pHostapdState->vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: startbss event failed!!")); + goto stopbss; + } + else + { +#ifdef FEATURE_WLAN_CH_AVOID + sme_ChAvoidUpdateReq(pHddCtx->hHal); +#endif /* FEATURE_WLAN_CH_AVOID */ + + pHddApCtx->uBCStaId = pSapEvent->sapevt.sapStartBssCompleteEvent.staId; + +#ifdef QCA_LL_TX_FLOW_CT + if (pHostapdAdapter->tx_flow_timer_initialized == VOS_FALSE) + { + vos_timer_init(&pHostapdAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_tx_resume_timer_expired_handler, + pHostapdAdapter); + pHostapdAdapter->tx_flow_timer_initialized = VOS_TRUE; + } + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_tx_resume_cb, + pHostapdAdapter->sessionId, + (void *)pHostapdAdapter); +#endif + + //@@@ need wep logic here to set privacy bit + vos_status = hdd_softap_Register_BC_STA(pHostapdAdapter, pHddApCtx->uPrivacy); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGW, FL("Failed to register BC STA %d"), vos_status); + hdd_stop_bss_link(pHostapdAdapter, usrDataForCallback); + } + } +#ifdef IPA_OFFLOAD + if (hdd_ipa_is_enabled(pHddCtx)) + { + status = hdd_ipa_wlan_evt(pHostapdAdapter, pHddApCtx->uBCStaId, + WLAN_AP_CONNECT, pHostapdAdapter->dev->dev_addr); + + if (status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("ERROR: WLAN_AP_CONNECT event failed!!")); + goto stopbss; + } + } +#endif + + if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff) + { + // AP Inactivity timer init and start + vos_status = vos_timer_init( &pHddApCtx->hdd_ap_inactivity_timer, VOS_TIMER_TYPE_SW, + hdd_hostapd_inactivity_timer_cb, (v_PVOID_t)dev ); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to init AP inactivity timer")); + + vos_status = vos_timer_start( &pHddApCtx->hdd_ap_inactivity_timer, (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff * 1000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to init AP inactivity timer")); + + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_TRUE); +#endif + pHddApCtx->operatingChannel = pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel; + + hdd_hostapd_channel_prevent_suspend(pHostapdAdapter, + pHddApCtx->operatingChannel); + + pHostapdState->bssState = BSS_START; + +#ifdef FEATURE_GREEN_AP + if (!(VOS_STA & pHddCtx->concurrency_mode) && + cfg->enable2x2 && + cfg->enableGreenAP) { + hdd_wlan_green_ap_mc(pHddCtx, GREEN_AP_PS_START_EVENT); + } else { + hdd_wlan_green_ap_mc(pHddCtx, GREEN_AP_PS_STOP_EVENT); + hddLog(VOS_TRACE_LEVEL_INFO, + "Green-AP: is disabled, due to sta_concurrency: %d, enable2x2: %d, enableGreenAP: %d", + VOS_STA & pHddCtx->concurrency_mode, + cfg->enable2x2, + cfg->enableGreenAP); + } +#endif + // Send current operating channel of SoftAP to BTC-ES + send_btc_nlink_msg(WLAN_BTC_SOFTAP_BSS_START, 0); + + //Set group key / WEP key every time when BSS is restarted + if( pHddApCtx->groupKey.keyLength ) + { + status = WLANSAP_SetKeySta( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), +#else + (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, +#endif + &pHddApCtx->groupKey); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANSAP_SetKeySta failed", __func__); + } + } + else + { + for ( i = 0; i < CSR_MAX_NUM_KEY; i++ ) + { + if ( !pHddApCtx->wepKey[i].keyLength ) + continue; + + status = WLANSAP_SetKeySta( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), +#else + (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, +#endif + &pHddApCtx->wepKey[i]); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANSAP_SetKeySta failed idx %d", __func__, i); + } + } + } + + spin_lock_bh(&pHddCtx->dfs_lock); + pHddCtx->dfs_radar_found = VOS_FALSE; + spin_unlock_bh(&pHddCtx->dfs_lock); + WLANSAP_Get_Dfs_Ignore_CAC(pHddCtx->hHal, &ignoreCAC); + if ((NV_CHANNEL_DFS != + vos_nv_getChannelEnabledState(pHddApCtx->operatingChannel)) + || ignoreCAC + || pHddCtx->dev_dfs_cac_status == DFS_CAC_ALREADY_DONE) + { + pHddApCtx->dfs_cac_block_tx = VOS_FALSE; + } else { + /* + * DFS requirement: Do not transmit during CAC. + * This flag will be reset when BSS starts + * (if not in a DFS channel) or CAC ends. + */ + pHddApCtx->dfs_cac_block_tx = VOS_TRUE; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "The value of dfs_cac_block_tx[%d] for ApCtx[%p]", + pHddApCtx->dfs_cac_block_tx, pHddApCtx); + + if ((NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(pHddApCtx->operatingChannel)) && + (pHddCtx->cfg_ini->IsSapDfsChSifsBurstEnabled == 0)) + { + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Setting SIFS Burst disable for DFS channel %d", + __func__, pHddApCtx->operatingChannel); + + if (process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + 0, PDEV_CMD)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to Set SIFS Burst for DFS channel %d", + __func__, pHddApCtx->operatingChannel); + } + } + + //Fill the params for sending IWEVCUSTOM Event with SOFTAP.enabled + startBssEvent = "SOFTAP.enabled"; + memset(&we_custom_start_event, '\0', sizeof(we_custom_start_event)); + memcpy(&we_custom_start_event, startBssEvent, strlen(startBssEvent)); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlen(startBssEvent); + we_event = IWEVCUSTOM; + we_custom_event_generic = we_custom_start_event; + hdd_dump_concurrency_info(pHddCtx); + break; //Event will be sent after Switch-Case stmt + + case eSAP_STOP_BSS_EVENT: + hddLog(LOG1, FL("BSS stop status = %s"),pSapEvent->sapevt.sapStopBssCompleteEvent.status ? + "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS"); + + hdd_set_sap_auth_offload(pHostapdAdapter, FALSE); + + hdd_hostapd_channel_allow_suspend(pHostapdAdapter, + pHddApCtx->operatingChannel); + +#ifdef FEATURE_GREEN_AP + hdd_wlan_green_ap_mc(pHddCtx, GREEN_AP_PS_STOP_EVENT); +#endif + //Free up Channel List incase if it is set +#ifdef WLAN_FEATURE_MBSSID + sapCleanupChannelList(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + sapCleanupChannelList(); +#endif + + pHddApCtx->operatingChannel = 0; //Invalidate the channel info. +#ifdef IPA_OFFLOAD + if (hdd_ipa_is_enabled(pHddCtx)) + { + status = hdd_ipa_wlan_evt(pHostapdAdapter, pHddApCtx->uBCStaId, + WLAN_AP_DISCONNECT, pHostapdAdapter->dev->dev_addr); + + if (status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("ERROR: WLAN_AP_DISCONNECT event failed!!")); + goto stopbss; + } + } +#endif + /* reset the dfs_cac_status and dfs_cac_block_tx flag only when + * the last BSS is stopped + */ + con_sap_adapter = hdd_get_con_sap_adapter(pHostapdAdapter, true); + if (!con_sap_adapter) { + pHddApCtx->dfs_cac_block_tx = TRUE; + pHddCtx->dev_dfs_cac_status = DFS_CAC_NEVER_DONE; + } + if (pHddCtx->cfg_ini->conc_custom_rule2 && + (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) { + + hdd_adapter_t *sta_adapter = hdd_get_adapter(pHddCtx, + WLAN_HDD_INFRA_STATION); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + FL("P2PGO is going down now")); + hdd_issue_stored_joinreq(sta_adapter, pHddCtx); + } + goto stopbss; + + case eSAP_DFS_CAC_START: + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_DFS_CAC_START_IND, + &dfs_info, sizeof(struct wlan_dfs_info)); + pHddCtx->dev_dfs_cac_status = DFS_CAC_IN_PROGRESS; + if (VOS_STATUS_SUCCESS != + hdd_send_radar_event(pHddCtx, eSAP_DFS_CAC_START, + dfs_info, &pHostapdAdapter->wdev)) { + hddLog(LOGE, FL("Unable to indicate CAC start NL event")); + } else { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Sent CAC start to user space")); + } + pHddCtx->dfs_radar_found = VOS_FALSE; + break; + + case eSAP_DFS_CAC_INTERRUPTED: + /* + * The CAC timer did not run completely and a radar was detected + * during the CAC time. This new state will keep the tx path + * blocked since we do not want any transmission on the DFS + * channel. CAC end will only be reported here since the user + * space applications are waiting on CAC end for their state + * management. + */ + if (VOS_STATUS_SUCCESS != + hdd_send_radar_event(pHddCtx, eSAP_DFS_CAC_END, + dfs_info, &pHostapdAdapter->wdev)) { + hddLog(LOGE, + FL("Unable to indicate CAC end (interrupted) event")); + } else { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Sent CAC end (interrupted) to user space")); + } + break; + + case eSAP_DFS_CAC_END: + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_DFS_CAC_END_IND, + &dfs_info, sizeof(struct wlan_dfs_info)); + pHddApCtx->dfs_cac_block_tx = VOS_FALSE; + pHddCtx->dev_dfs_cac_status = DFS_CAC_ALREADY_DONE; + if (VOS_STATUS_SUCCESS != + hdd_send_radar_event(pHddCtx, eSAP_DFS_CAC_END, + dfs_info, &pHostapdAdapter->wdev)) { + hddLog(LOGE, FL("Unable to indicate CAC end NL event")); + } else { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Sent CAC end to user space")); + } + break; + + case eSAP_DFS_RADAR_DETECT: + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_DFS_RADAR_DETECT_IND, + &dfs_info, sizeof(struct wlan_dfs_info)); + pHddCtx->dev_dfs_cac_status = DFS_CAC_NEVER_DONE; + if (VOS_STATUS_SUCCESS != + hdd_send_radar_event(pHddCtx, eSAP_DFS_RADAR_DETECT, + dfs_info, &pHostapdAdapter->wdev)) { + hddLog(LOGE, FL("Unable to indicate Radar detect NL event")); + } else { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Sent radar detected to user space")); + } + break; + + case eSAP_DFS_NO_AVAILABLE_CHANNEL: + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND, + &dfs_info, sizeof(struct wlan_dfs_info)); + break; + + case eSAP_STA_SET_KEY_EVENT: + /* TODO: forward the message to hostapd once implementation + is done for now just print */ + hddLog(LOG1, FL("SET Key: configured status = %s"),pSapEvent->sapevt.sapStationSetKeyCompleteEvent.status ? + "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS"); + return VOS_STATUS_SUCCESS; + case eSAP_STA_DEL_KEY_EVENT: + /* TODO: forward the message to hostapd once implementation + is done for now just print */ + hddLog(LOG1, FL("Event received %s"),"eSAP_STA_DEL_KEY_EVENT"); + return VOS_STATUS_SUCCESS; + case eSAP_STA_MIC_FAILURE_EVENT: + { + memset(&msg, '\0', sizeof(msg)); + msg.src_addr.sa_family = ARPHRD_ETHER; + memcpy(msg.src_addr.sa_data, &pSapEvent->sapevt.sapStationMICFailureEvent.staMac, sizeof(v_MACADDR_t)); + hddLog(LOG1, "MIC MAC "MAC_ADDRESS_STR, MAC_ADDR_ARRAY(msg.src_addr.sa_data)); + if(pSapEvent->sapevt.sapStationMICFailureEvent.multicast == eSAP_TRUE) + msg.flags = IW_MICFAILURE_GROUP; + else + msg.flags = IW_MICFAILURE_PAIRWISE; + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(msg); + we_event = IWEVMICHAELMICFAILURE; + we_custom_event_generic = (v_BYTE_t *)&msg; + } + /* inform mic failure to nl80211 */ + cfg80211_michael_mic_failure(dev, + pSapEvent->sapevt. + sapStationMICFailureEvent.staMac.bytes, + ((pSapEvent->sapevt.sapStationMICFailureEvent.multicast == eSAP_TRUE) ? + NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE), + pSapEvent->sapevt.sapStationMICFailureEvent.keyId, + pSapEvent->sapevt.sapStationMICFailureEvent.TSC, + GFP_KERNEL); + break; + + case eSAP_STA_ASSOC_EVENT: + case eSAP_STA_REASSOC_EVENT: + wrqu.addr.sa_family = ARPHRD_ETHER; + memcpy(wrqu.addr.sa_data, &pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac, + sizeof(v_MACADDR_t)); + hddLog(LOG1, " associated "MAC_ADDRESS_STR, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + we_event = IWEVREGISTERED; + +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_Get_WPS_State(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), &bWPSState); +#else + WLANSAP_Get_WPS_State((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &bWPSState); +#endif + + if ( (eCSR_ENCRYPT_TYPE_NONE == pHddApCtx->ucEncryptType) || + ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddApCtx->ucEncryptType ) || + ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddApCtx->ucEncryptType ) ) + { + bAuthRequired = FALSE; + } + + if (bAuthRequired || bWPSState == eANI_BOOLEAN_TRUE ) + { + vos_status = hdd_softap_RegisterSTA(pHostapdAdapter, + TRUE, + pHddApCtx->uPrivacy, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId, + 0, + 0, + (v_MACADDR_t *)wrqu.addr.sa_data, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGW, FL("Failed to register STA %d "MAC_ADDRESS_STR""), + vos_status, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + } + else + { + vos_status = hdd_softap_RegisterSTA(pHostapdAdapter, + FALSE, + pHddApCtx->uPrivacy, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId, + 0, + 0, + (v_MACADDR_t *)wrqu.addr.sa_data, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGW, FL("Failed to register STA %d "MAC_ADDRESS_STR""), + vos_status, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + } + + staId = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId; + if (VOS_IS_STATUS_SUCCESS(vos_status)) { + pHostapdAdapter->aStaInfo[staId].nss = + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.chan_info.nss; + pHostapdAdapter->aStaInfo[staId].rate_flags = + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.chan_info.rate_flags; + } + +#ifdef IPA_OFFLOAD + if (hdd_ipa_is_enabled(pHddCtx)) + { + status = hdd_ipa_wlan_evt(pHostapdAdapter, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId, + WLAN_CLIENT_CONNECT_EX, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes); + if (status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: WLAN_CLIENT_CONNECT_EX event failed!!")); + goto stopbss; + } + } +#endif +#ifdef QCA_PKT_PROTO_TRACE + /* Peer associated, update into trace buffer */ + if (pHddCtx->cfg_ini->gEnableDebugLog) + { + vos_pkt_trace_buf_update("HA:ASSOC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef MSM_PLATFORM + /* start timer in sap/p2p_go */ + if (pHddApCtx->bApActive == VOS_FALSE) + { + spin_lock_bh(&pHddCtx->bus_bw_lock); + pHostapdAdapter->prev_tx_packets = pHostapdAdapter->stats.tx_packets; + pHostapdAdapter->prev_rx_packets = pHostapdAdapter->stats.rx_packets; + spin_unlock_bh(&pHddCtx->bus_bw_lock); + hdd_start_bus_bw_compute_timer(pHostapdAdapter); + } +#endif + pHddApCtx->bApActive = VOS_TRUE; + // Stop AP inactivity timer + if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_RUNNING) + { + vos_status = vos_timer_stop(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to start AP inactivity timer")); + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_FALSE); +#endif + vos_wake_lock_timeout_acquire(&pHddCtx->sap_wake_lock, + HDD_SAP_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_SAP); + { + struct station_info staInfo; + v_U16_t iesLen = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.iesLen; + + memset(&staInfo, 0, sizeof(staInfo)); + if (iesLen <= MAX_ASSOC_IND_IE_LEN ) + { + staInfo.assoc_req_ies = + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0]; + staInfo.assoc_req_ies_len = iesLen; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31)) || defined(WITH_BACKPORTS) + staInfo.filled |= STATION_INFO_ASSOC_REQ_IES; +#endif + cfg80211_new_sta(dev, + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes[0], + &staInfo, GFP_KERNEL); + } + else + { + hddLog(LOGE, FL(" Assoc Ie length is too long")); + } + } + + pScanInfo = &pHostapdAdapter->scan_info; + // Lets do abort scan to ensure smooth authentication for client + if ((pScanInfo != NULL) && pScanInfo->mScanPending) + { + hdd_abort_mac_scan(pHddCtx, pHostapdAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) + { + /* send peer status indication to oem app */ + hdd_SendPeerStatusIndToOemApp( + &pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac, + ePeerConnected, + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.timingMeasCap, + pHostapdAdapter->sessionId, + &pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.chan_info); + } + +#ifdef FEATURE_GREEN_AP + hdd_wlan_green_ap_mc(pHddCtx, GREEN_AP_ADD_STA_EVENT); +#endif + break; + case eSAP_STA_DISASSOC_EVENT: + memcpy(wrqu.addr.sa_data, &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac, + sizeof(v_MACADDR_t)); + hddLog(LOG1, " disassociated "MAC_ADDRESS_STR, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + + vos_status = vos_event_set(&pHostapdState->vosEvent); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(VOS_TRACE_LEVEL_ERROR, + "ERROR: Station deauth event reporting failed!!"); + + if (pSapEvent->sapevt.sapStationDisassocCompleteEvent.reason == eSAP_USR_INITATED_DISASSOC) + hddLog(LOG1," User initiated disassociation"); + else + hddLog(LOG1," MAC initiated disassociation"); + we_event = IWEVEXPIRED; + vos_status = hdd_softap_GetStaId(pHostapdAdapter, &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac, &staId); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!")); + return VOS_STATUS_E_FAILURE; + } +#ifdef IPA_OFFLOAD + if (hdd_ipa_is_enabled(pHddCtx)) + { + status = hdd_ipa_wlan_evt(pHostapdAdapter, staId, WLAN_CLIENT_DISCONNECT, + pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac.bytes); + + if (status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("ERROR: WLAN_CLIENT_DISCONNECT event failed!!")); + goto stopbss; + } + } +#endif +#ifdef QCA_PKT_PROTO_TRACE + /* Peer dis-associated, update into trace buffer */ + if (pHddCtx->cfg_ini->gEnableDebugLog) + { + vos_pkt_trace_buf_update("HA:DISASC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + hdd_softap_DeregisterSTA(pHostapdAdapter, staId); + + pHddApCtx->bApActive = VOS_FALSE; + spin_lock_bh( &pHostapdAdapter->staInfo_lock ); + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) + { + if (pHostapdAdapter->aStaInfo[i].isUsed && i != (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uBCStaId) + { + pHddApCtx->bApActive = VOS_TRUE; + break; + } + } + spin_unlock_bh( &pHostapdAdapter->staInfo_lock ); + + // Start AP inactivity timer if no stations associated with it + if ((0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff)) + { + if (pHddApCtx->bApActive == FALSE) + { + if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_STOPPED) + { + vos_status = vos_timer_start(&pHddApCtx->hdd_ap_inactivity_timer, (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff * 1000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to init AP inactivity timer")); + } + else + VOS_ASSERT(vos_timer_getCurrentState(&pHddApCtx->hdd_ap_inactivity_timer) == VOS_TIMER_STATE_STOPPED); + } + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_TRUE); +#endif + + if (pSapEvent->sapevt.sapStationDisassocCompleteEvent.statusCode == + eSIR_SME_SAP_AUTH_OFFLOAD_PEER_UPDATE_STATUS) { + /** eSIR_SME_SAP_AUTH_OFFLOAD_PEER_UPDATE_STATUS indicates: + * The existing sta connection needs to be updated instead + * of clean up the sta. This condition could only happens + * when Host SAP sleep with WOW and SAP Auth offload enabled. + */ + + hddLog(LOG1,"SAP peer update sta:Id=%d, Mac="MAC_ADDRESS_STR, + pSapEvent->sapevt.sapStationDisassocCompleteEvent.staId, + MAC_ADDR_ARRAY(pSapEvent->sapevt. + sapStationDisassocCompleteEvent.staMac.bytes)); + } else { + hddLog(LOG1,"SAP del sta: staId=%d, staMac="MAC_ADDRESS_STR, + pSapEvent->sapevt.sapStationDisassocCompleteEvent.staId, + MAC_ADDR_ARRAY(pSapEvent->sapevt. + sapStationDisassocCompleteEvent.staMac.bytes)); + + cfg80211_del_sta(dev, + (const u8 *)&pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac.bytes[0], + GFP_KERNEL); + } + + //Update the beacon Interval if it is P2P GO + vos_status = hdd_change_mcc_go_beacon_interval(pHostapdAdapter); + if (VOS_STATUS_SUCCESS != vos_status) + { + hddLog(LOGE, "%s: failed to update Beacon interval %d", + __func__, vos_status); + } + if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) + { + /* send peer status indication to oem app */ + hdd_SendPeerStatusIndToOemApp( + &pSapEvent->sapevt.sapStationDisassocCompleteEvent.staMac, + ePeerDisconnected, 0, + pHostapdAdapter->sessionId, NULL); + } + +#ifdef MSM_PLATFORM + /*stop timer in sap/p2p_go */ + if (pHddApCtx->bApActive == FALSE) + { + spin_lock_bh(&pHddCtx->bus_bw_lock); + pHostapdAdapter->prev_tx_packets = 0; + pHostapdAdapter->prev_rx_packets = 0; + spin_unlock_bh(&pHddCtx->bus_bw_lock); + hdd_stop_bus_bw_compute_timer(pHostapdAdapter); + } +#endif +#ifdef FEATURE_GREEN_AP + hdd_wlan_green_ap_mc(pHddCtx, GREEN_AP_DEL_STA_EVENT); +#endif + break; + case eSAP_WPS_PBC_PROBE_REQ_EVENT: + { + static const char * message ="MLMEWPSPBCPROBEREQ.indication"; + union iwreq_data wreq; + + down(&pHddApCtx->semWpsPBCOverlapInd); + pHddApCtx->WPSPBCProbeReq.probeReqIELen = pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.probeReqIELen; + + vos_mem_copy(pHddApCtx->WPSPBCProbeReq.probeReqIE, pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.probeReqIE, + pHddApCtx->WPSPBCProbeReq.probeReqIELen); + + vos_mem_copy(pHddApCtx->WPSPBCProbeReq.peerMacAddr, pSapEvent->sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq.peerMacAddr, sizeof(v_MACADDR_t)); + hddLog(LOG1, "WPS PBC probe req "MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pHddApCtx->WPSPBCProbeReq.peerMacAddr)); + memset(&wreq, 0, sizeof(wreq)); + wreq.data.length = strlen(message); // This is length of message + wireless_send_event(dev, IWEVCUSTOM, &wreq, (char *)message); + + return VOS_STATUS_SUCCESS; + } + case eSAP_ASSOC_STA_CALLBACK_EVENT: + pAssocStasArray = pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas; + if (pSapEvent->sapevt.sapAssocStaListEvent.noOfAssocSta != 0) + { // List of associated stations + for (i = 0; i < pSapEvent->sapevt.sapAssocStaListEvent.noOfAssocSta; i++) + { + hddLog(LOG1,"Associated Sta Num %d:assocId=%d, staId=%d, staMac="MAC_ADDRESS_STR, + i+1, + pAssocStasArray->assocId, + pAssocStasArray->staId, + MAC_ADDR_ARRAY(pAssocStasArray->staMac.bytes)); + pAssocStasArray++; + } + } + vos_mem_free(pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas);// Release caller allocated memory here + pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas = NULL; + return VOS_STATUS_SUCCESS; + case eSAP_INDICATE_MGMT_FRAME: + hdd_indicateMgmtFrame( pHostapdAdapter, + pSapEvent->sapevt.sapManagementFrameInfo.nFrameLength, + pSapEvent->sapevt.sapManagementFrameInfo.pbFrames, + pSapEvent->sapevt.sapManagementFrameInfo.frameType, + pSapEvent->sapevt.sapManagementFrameInfo.rxChan, 0); + return VOS_STATUS_SUCCESS; + case eSAP_REMAIN_CHAN_READY: + hdd_remainChanReadyHandler( pHostapdAdapter ); + return VOS_STATUS_SUCCESS; + case eSAP_SEND_ACTION_CNF: + hdd_sendActionCnf( pHostapdAdapter, + ( eSAP_STATUS_SUCCESS == + pSapEvent->sapevt.sapActionCnf.actionSendSuccess ) ? + TRUE : FALSE ); + return VOS_STATUS_SUCCESS; + case eSAP_UNKNOWN_STA_JOIN: + snprintf(unknownSTAEvent, IW_CUSTOM_MAX, "JOIN_UNKNOWN_STA-%02x:%02x:%02x:%02x:%02x:%02x", + pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[0], + pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[1], + pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[2], + pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[3], + pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[4], + pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[5]); + we_event = IWEVCUSTOM; /* Discovered a new node (AP mode). */ + wrqu.data.pointer = unknownSTAEvent; + wrqu.data.length = strlen(unknownSTAEvent); + we_custom_event_generic = (v_BYTE_t *)unknownSTAEvent; + hddLog(LOGE,"%s", unknownSTAEvent); + break; + + case eSAP_MAX_ASSOC_EXCEEDED: + snprintf(maxAssocExceededEvent, IW_CUSTOM_MAX, "Peer %02x:%02x:%02x:%02x:%02x:%02x denied" + " assoc due to Maximum Mobile Hotspot connections reached. Please disconnect" + " one or more devices to enable the new device connection", + pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[0], + pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[1], + pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[2], + pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[3], + pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[4], + pSapEvent->sapevt.sapMaxAssocExceeded.macaddr.bytes[5]); + we_event = IWEVCUSTOM; /* Discovered a new node (AP mode). */ + wrqu.data.pointer = maxAssocExceededEvent; + wrqu.data.length = strlen(maxAssocExceededEvent); + we_custom_event_generic = (v_BYTE_t *)maxAssocExceededEvent; + hddLog(LOG1,"%s", maxAssocExceededEvent); + break; + case eSAP_STA_ASSOC_IND: + return VOS_STATUS_SUCCESS; + + case eSAP_DISCONNECT_ALL_P2P_CLIENT: + hddLog(LOG1, FL(" Disconnecting all the P2P Clients....")); + hdd_clear_all_sta(pHostapdAdapter, usrDataForCallback); + return VOS_STATUS_SUCCESS; + + case eSAP_MAC_TRIG_STOP_BSS_EVENT : + vos_status = hdd_stop_bss_link(pHostapdAdapter, usrDataForCallback); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGW, FL("hdd_stop_bss_link failed %d"), vos_status); + + return VOS_STATUS_SUCCESS; + + case eSAP_CHANNEL_CHANGE_EVENT: + hddLog(LOG1, FL("Received eSAP_CHANNEL_CHANGE_EVENT event")); + /* Prevent suspend for new channel */ + hdd_hostapd_channel_prevent_suspend(pHostapdAdapter, + pSapEvent->sapevt.sapChSelected.pri_ch); + /* Allow suspend for old channel */ + hdd_hostapd_channel_allow_suspend(pHostapdAdapter, + pHddApCtx->operatingChannel); + /* SME/PE is already updated for new operation channel. So update + * HDD layer also here. This resolves issue in AP-AP mode where + * AP1 channel is changed due to RADAR then CAC is going on and + * START_BSS on new channel has not come to HDD. At this case if + * AP2 is start it needs current operation channel for MCC DFS + * restiction + */ + pHddApCtx->operatingChannel = + pSapEvent->sapevt.sapChSelected.pri_ch; + pHddApCtx->sapConfig.acs_cfg.pri_ch = + pSapEvent->sapevt.sapChSelected.pri_ch; + pHddApCtx->sapConfig.acs_cfg.ht_sec_ch = + pSapEvent->sapevt.sapChSelected.ht_sec_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg0_center_ch = + pSapEvent->sapevt.sapChSelected.vht_seg0_center_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg1_center_ch = + pSapEvent->sapevt.sapChSelected.vht_seg1_center_ch; + pHddApCtx->sapConfig.acs_cfg.ch_width = + pSapEvent->sapevt.sapChSelected.ch_width; + + /* Indicate operating channel change to hostapd + * only for non driver override acs + */ + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP && + pHddCtx->cfg_ini->force_sap_acs) + return VOS_STATUS_SUCCESS; + else + return hdd_chan_change_notify(pHostapdAdapter, dev, + pSapEvent->sapevt.sapChSelected.pri_ch); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + case eSAP_ACS_SCAN_SUCCESS_EVENT: + pHddCtx->skip_acs_scan_status = eSAP_SKIP_ACS_SCAN; + hddLog(LOG1, FL("Reusing Last ACS scan result for %d sec"), + ACS_SCAN_EXPIRY_TIMEOUT_S); + vos_timer_stop( &pHddCtx->skip_acs_scan_timer); + vos_status = vos_timer_start( &pHddCtx->skip_acs_scan_timer, + ACS_SCAN_EXPIRY_TIMEOUT_S * 1000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to start ACS scan expiry timer")); + return VOS_STATUS_SUCCESS; +#endif + + case eSAP_DFS_NOL_GET: + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Received eSAP_DFS_NOL_GET event")); +#if defined CONFIG_CNSS + /* get the dfs nol from cnss */ + ret = cnss_wlan_get_dfs_nol( + pSapEvent->sapevt.sapDfsNolInfo.pDfsList, + pSapEvent->sapevt.sapDfsNolInfo.sDfsList); + + if (ret > 0) { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Get %d bytes of dfs nol from cnss", + __func__, ret); + return VOS_STATUS_SUCCESS; + } else { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: No dfs nol entry in CNSS, ret: %d", + __func__, ret); + return VOS_STATUS_E_FAULT; + } +#else + return VOS_STATUS_E_FAILURE; +#endif + case eSAP_DFS_NOL_SET: + hddLog(VOS_TRACE_LEVEL_INFO, FL("Received eSAP_DFS_NOL_SET event")); +#if defined CONFIG_CNSS + /* set the dfs nol to cnss */ + ret = cnss_wlan_set_dfs_nol( + pSapEvent->sapevt.sapDfsNolInfo.pDfsList, + pSapEvent->sapevt.sapDfsNolInfo.sDfsList); + + if (ret) { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Failed to set dfs nol - ret: %d", + __func__, ret); + } else { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Set %d bytes dfs nol to cnss", + __func__, + pSapEvent->sapevt.sapDfsNolInfo.sDfsList); + } +#else + return VOS_STATUS_E_FAILURE; +#endif + return VOS_STATUS_SUCCESS; + case eSAP_ACS_CHANNEL_SELECTED: + hddLog(LOG1, FL("ACS Completed for wlan%d"), + pHostapdAdapter->dev->ifindex); + clear_bit(ACS_PENDING, &pHostapdAdapter->event_flags); + clear_bit(ACS_IN_PROGRESS, &pHddCtx->g_event_flags); + pHddApCtx->sapConfig.acs_cfg.pri_ch = + pSapEvent->sapevt.sapChSelected.pri_ch; + pHddApCtx->sapConfig.acs_cfg.ht_sec_ch = + pSapEvent->sapevt.sapChSelected.ht_sec_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg0_center_ch = + pSapEvent->sapevt.sapChSelected.vht_seg0_center_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg1_center_ch = + pSapEvent->sapevt.sapChSelected.vht_seg1_center_ch; + pHddApCtx->sapConfig.acs_cfg.ch_width = + pSapEvent->sapevt.sapChSelected.ch_width; + /* send vendor event to hostapd only for hostapd based acs */ + if (!pHddCtx->cfg_ini->force_sap_acs) + wlan_hdd_cfg80211_acs_ch_select_evt(pHostapdAdapter); + + return VOS_STATUS_SUCCESS; + case eSAP_ECSA_CHANGE_CHAN_IND: + hddLog(LOG1, + FL("Channel change indication from peer for channel %d"), + pSapEvent->sapevt.sap_chan_cng_ind.new_chan); + if (hdd_softap_set_channel_change(dev, + pSapEvent->sapevt.sap_chan_cng_ind.new_chan)) + return VOS_STATUS_E_FAILURE; + else + return VOS_STATUS_SUCCESS; + default: + hddLog(LOG1,"SAP message is not handled"); + goto stopbss; + return VOS_STATUS_SUCCESS; + } + wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic); + return VOS_STATUS_SUCCESS; + +stopbss : + { + v_BYTE_t we_custom_event[64]; + char *stopBssEvent = "STOP-BSS.response";//17 + int event_len = strlen(stopBssEvent); + + hddLog(LOG1, FL("BSS stop status = %s"), + pSapEvent->sapevt.sapStopBssCompleteEvent.status ? + "eSAP_STATUS_FAILURE" : "eSAP_STATUS_SUCCESS"); + + /* Change the BSS state now since, as we are shutting things down, + * we don't want interfaces to become re-enabled */ + pHostapdState->bssState = BSS_STOP; + + if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff) + { + if (VOS_TIMER_STATE_RUNNING == pHddApCtx->hdd_ap_inactivity_timer.state) + { + vos_status = vos_timer_stop(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to stop AP inactivity timer")); + } + + vos_status = vos_timer_destroy(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to Destroy AP inactivity timer")); + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, VOS_TRUE); +#endif + + /* Stop the pkts from n/w stack as we are going to free all of + * the TX WMM queues for all STAID's */ + hdd_hostapd_stop(dev); + + /* reclaim all resources allocated to the BSS */ + vos_status = hdd_softap_stop_bss(pHostapdAdapter); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGW, FL("hdd_softap_stop_bss failed %d"), vos_status); + + /* once the event is set, structure dev/pHostapdAdapter should + * not be touched since they are now subject to being deleted + * by another thread */ + if (eSAP_STOP_BSS_EVENT == sapEvent) + vos_event_set(&pHostapdState->stop_bss_event); + + /* Notify user space that the BSS has stopped */ + memset(&we_custom_event, '\0', sizeof(we_custom_event)); + memcpy(&we_custom_event, stopBssEvent, event_len); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = event_len; + we_event = IWEVCUSTOM; + we_custom_event_generic = we_custom_event; + wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic); + hdd_dump_concurrency_info(pHddCtx); + } + return VOS_STATUS_SUCCESS; +} + +int hdd_softap_unpackIE( + tHalHandle halHandle, + eCsrEncryptionType *pEncryptType, + eCsrEncryptionType *mcEncryptType, + eCsrAuthType *pAuthType, + v_BOOL_t *pMFPCapable, + v_BOOL_t *pMFPRequired, + u_int16_t gen_ie_len, + u_int8_t *gen_ie ) +{ + tDot11fIERSN dot11RSNIE; + tDot11fIEWPA dot11WPAIE; + + tANI_U8 *pRsnIe; + tANI_U16 RSNIeLen; + + if (NULL == halHandle) + { + hddLog(LOGE, FL("Error haHandle returned NULL")); + return -EINVAL; + } + + // Validity checks + if ((gen_ie_len < VOS_MIN(DOT11F_IE_RSN_MIN_LEN, DOT11F_IE_WPA_MIN_LEN)) || + (gen_ie_len > VOS_MAX(DOT11F_IE_RSN_MAX_LEN, DOT11F_IE_WPA_MAX_LEN)) ) + return -EINVAL; + // Type check + if ( gen_ie[0] == DOT11F_EID_RSN) + { + // Validity checks + if ((gen_ie_len < DOT11F_IE_RSN_MIN_LEN ) || + (gen_ie_len > DOT11F_IE_RSN_MAX_LEN) ) + { + return VOS_STATUS_E_FAILURE; + } + // Skip past the EID byte and length byte + pRsnIe = gen_ie + 2; + RSNIeLen = gen_ie_len - 2; + // Unpack the RSN IE + memset(&dot11RSNIE, 0, sizeof(tDot11fIERSN)); + dot11fUnpackIeRSN((tpAniSirGlobal) halHandle, + pRsnIe, + RSNIeLen, + &dot11RSNIE); + // Copy out the encryption and authentication types + hddLog(LOG1, FL("%s: pairwise cipher suite count: %d"), + __func__, dot11RSNIE.pwise_cipher_suite_count ); + hddLog(LOG1, FL("%s: authentication suite count: %d"), + __func__, dot11RSNIE.akm_suite_count); + /*Here we have followed the apple base code, + but probably I suspect we can do something different*/ + //dot11RSNIE.akm_suite_count + // Just translate the FIRST one + *pAuthType = hdd_TranslateRSNToCsrAuthType(dot11RSNIE.akm_suites[0]); + //dot11RSNIE.pwise_cipher_suite_count + *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]); + //dot11RSNIE.gp_cipher_suite_count + *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite); + // Set the PMKSA ID Cache for this interface + *pMFPCapable = 0 != (dot11RSNIE.RSN_Cap[0] & 0x80); + *pMFPRequired = 0 != (dot11RSNIE.RSN_Cap[0] & 0x40); + // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache + } else + if (gen_ie[0] == DOT11F_EID_WPA) + { + // Validity checks + if ((gen_ie_len < DOT11F_IE_WPA_MIN_LEN ) || + (gen_ie_len > DOT11F_IE_WPA_MAX_LEN)) + { + return VOS_STATUS_E_FAILURE; + } + // Skip past the EID byte and length byte - and four byte WiFi OUI + pRsnIe = gen_ie + 2 + 4; + RSNIeLen = gen_ie_len - (2 + 4); + // Unpack the WPA IE + memset(&dot11WPAIE, 0, sizeof(tDot11fIEWPA)); + dot11fUnpackIeWPA((tpAniSirGlobal) halHandle, + pRsnIe, + RSNIeLen, + &dot11WPAIE); + // Copy out the encryption and authentication types + hddLog(LOG1, FL("%s: WPA unicast cipher suite count: %d"), + __func__, dot11WPAIE.unicast_cipher_count ); + hddLog(LOG1, FL("%s: WPA authentication suite count: %d"), + __func__, dot11WPAIE.auth_suite_count); + //dot11WPAIE.auth_suite_count + // Just translate the FIRST one + *pAuthType = hdd_TranslateWPAToCsrAuthType(dot11WPAIE.auth_suites[0]); + //dot11WPAIE.unicast_cipher_count + *pEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.unicast_ciphers[0]); + //dot11WPAIE.unicast_cipher_count + *mcEncryptType = hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher); + *pMFPCapable = VOS_FALSE; + *pMFPRequired = VOS_FALSE; + } + else + { + hddLog(LOGW, FL("%s: gen_ie[0]: %d"), __func__, gen_ie[0]); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + + /**--------------------------------------------------------------------------- + + \brief hdd_softap_set_channel_change() - + This function to support SAP channel change with CSA IE + set in the beacons. + + \param - dev - Pointer to the net device. + - target_channel - target channel number. + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) +{ + VOS_STATUS status; + int ret = 0; + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx = NULL; + hdd_adapter_t *sta_adapter = NULL; + hdd_station_ctx_t *sta_ctx; + +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext; +#endif + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: invalid HDD context", __func__); + return ret; + } + + sta_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + /* + * conc_custom_rule1: + * Force SCC for SAP + STA + * if STA is already connected then we shouldn't allow + * channel switch in SAP interface + */ + if (sta_adapter && pHddCtx->cfg_ini->conc_custom_rule1) + { + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); + if (hdd_connIsConnected(sta_ctx)) + { + hddLog(LOGE, FL("Channel switch not allowed after STA connection with conc_custom_rule1 enabled")); + return -EBUSY; + } + } + + spin_lock_bh(&pHddCtx->dfs_lock); + if (pHddCtx->dfs_radar_found == VOS_TRUE) + { + spin_unlock_bh(&pHddCtx->dfs_lock); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Channel switch in progress!!", + __func__); + ret = -EBUSY; + return ret; + } + /* + * Set the dfs_radar_found flag to mimic channel change + * when a radar is found. This will enable synchronizing + * SAP and HDD states similar to that of radar indication. + * Suspend the netif queues to stop queuing Tx frames + * from upper layers. netif queues will be resumed + * once the channel change is completed and SAP will + * post eSAP_START_BSS_EVENT success event to HDD. + */ + pHddCtx->dfs_radar_found = VOS_TRUE; + + spin_unlock_bh(&pHddCtx->dfs_lock); + /* + * Post the Channel Change request to SAP. + */ + status = WLANSAP_SetChannelChangeWithCsa( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), +#else + pVosContext, +#endif + (v_U32_t) target_channel); + + if (VOS_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SAP set channel failed for channel = %d", + __func__, target_channel); + /* + * If channel change command fails then clear the + * radar found flag and also restart the netif + * queues. + */ + + spin_lock_bh(&pHddCtx->dfs_lock); + pHddCtx->dfs_radar_found = VOS_FALSE; + spin_unlock_bh(&pHddCtx->dfs_lock); + + ret = -EINVAL; + } + + return ret; +} + +int +static __iw_softap_set_ini_cfg(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOS_STATUS vstatus; + int ret = 0; /* success */ + hdd_adapter_t *pAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx; + + if (pAdapter == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL!", __func__); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret != 0) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return ret; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received data %s", __func__, extra); + + vstatus = hdd_execute_global_config_command(pHddCtx, extra); +#ifdef WLAN_FEATURE_MBSSID + if (vstatus == VOS_STATUS_E_PERM) { + vstatus = hdd_execute_sap_dyn_config_command(pAdapter, extra); + if (vstatus == VOS_STATUS_SUCCESS) + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Stored in Dynamic SAP ini config", __func__); + } +#endif + if (VOS_STATUS_SUCCESS != vstatus) + { + ret = -EINVAL; + } + + return ret; +} + +int +static iw_softap_set_ini_cfg(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_set_ini_cfg(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_get_ini_cfg(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int ret = 0; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret != 0) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return ret; + } + +#ifdef WLAN_FEATURE_MBSSID + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Printing Adapter MBSSID SAP Dyn INI Config", __func__); + hdd_cfg_get_sap_dyn_config(pAdapter, extra, QCSAP_IOCTL_MAX_STR_LEN); + /* Overwrite extra buffer with global ini config if need to return in buf */ +#endif + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Printing CLD global INI Config", __func__); + hdd_cfg_get_global_config(pHddCtx, extra, QCSAP_IOCTL_MAX_STR_LEN); + wrqu->data.length = strlen(extra)+1; + + return 0; +} + +int +static iw_softap_get_ini_cfg(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_ini_cfg(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_softap_set_two_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int *value = (int *)extra; + int sub_cmd = value[0]; + int ret = 0; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret != 0) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid!", __func__); + goto out; + } + + switch(sub_cmd) { +#ifdef DEBUG + case QCSAP_IOCTL_SET_FW_CRASH_INJECT: + hddLog(LOGE, "WE_SET_FW_CRASH_INJECT: %d %d", value[1], value[2]); + if (!pHddCtx->cfg_ini->crash_inject_enabled) { + hddLog(LOGE, "Crash Inject ini disabled, Ignore Crash Inject"); + return 0; + } + ret = process_wma_set_command_twoargs((int) pAdapter->sessionId, + (int) GEN_PARAM_CRASH_INJECT, + value[1], value[2], GEN_CMD); + break; +#endif + default: + hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); + break; + } + +out: + return ret; +} + +static int iw_softap_set_two_ints_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_set_two_ints_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_wowl_config_pattern(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 = (netdev_priv(dev)); + struct iw_point s_priv_data; + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + + /* 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"); + hdd_add_wowl_ptrn(pAdapter, pBuffer); + break; + case WE_WOWL_DEL_PTRN: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN"); + hdd_del_wowl_ptrn(pAdapter, pBuffer); + break; + default: + hddLog(LOGE, "%s: Invalid sub command %d", __func__, sub_cmd); + ret = -EINVAL; + break; + } + kfree(pBuffer); + return ret; +} + +int +static iw_softap_wowl_config_pattern(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_wowl_config_pattern(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static void print_mac_list(v_MACADDR_t *macList, v_U8_t size) +{ + int i; + v_BYTE_t *macArray; + + for (i = 0; i < size; i++) { + macArray = (macList + i)->bytes; + pr_info("** ACL entry %i - %02x:%02x:%02x:%02x:%02x:%02x \n", + i, MAC_ADDR_ARRAY(macArray)); + } + return; +} + +static VOS_STATUS hdd_print_acl(hdd_adapter_t *pHostapdAdapter) +{ + eSapMacAddrACL acl_mode; + v_MACADDR_t MacList[MAX_ACL_MAC_ADDRESS]; + v_U8_t listnum; + v_PVOID_t pvosGCtx = NULL; + +#ifdef WLAN_FEATURE_MBSSID + pvosGCtx = WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter); +#else + pvosGCtx = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext; +#endif + vos_mem_zero(&MacList[0], sizeof(MacList)); + if (VOS_STATUS_SUCCESS == WLANSAP_GetACLMode(pvosGCtx, &acl_mode)) { + pr_info("******** ACL MODE *********\n"); + switch (acl_mode) { + case eSAP_ACCEPT_UNLESS_DENIED: + pr_info("ACL Mode = ACCEPT_UNLESS_DENIED\n"); + break; + case eSAP_DENY_UNLESS_ACCEPTED: + pr_info("ACL Mode = DENY_UNLESS_ACCEPTED\n"); + break; + case eSAP_SUPPORT_ACCEPT_AND_DENY: + pr_info("ACL Mode = ACCEPT_AND_DENY\n"); + break; + case eSAP_ALLOW_ALL: + pr_info("ACL Mode = ALLOW_ALL\n"); + break; + default: + pr_info("Invalid SAP ACL Mode = %d\n", acl_mode); + return VOS_STATUS_E_FAILURE; + } + } else { + return VOS_STATUS_E_FAILURE; + } + + if (VOS_STATUS_SUCCESS == WLANSAP_GetACLAcceptList(pvosGCtx, + &MacList[0], &listnum)) { + pr_info("******* WHITE LIST ***********\n"); + if (listnum <= MAX_ACL_MAC_ADDRESS) + print_mac_list(&MacList[0], listnum); + } else { + return VOS_STATUS_E_FAILURE; + } + + if (VOS_STATUS_SUCCESS == WLANSAP_GetACLDenyList(pvosGCtx, + &MacList[0], &listnum)) { + pr_info("******* BLACK LIST ***********\n"); + if (listnum <= MAX_ACL_MAC_ADDRESS) + print_mac_list(&MacList[0], listnum); + } else { + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +int +static __iw_softap_setparam(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + tHalHandle hHal; + int *value = (int *)extra; + int sub_cmd = value[0]; + int set_value = value[1]; + eHalStatus status; + int ret = 0; /* success */ + v_CONTEXT_t pVosContext; + hdd_context_t *pHddCtx = NULL; + + ENTER(); + + if (NULL == pHostapdAdapter) { + hddLog(LOGE, FL("hostapd Adapter is null")); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return -EINVAL; + + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + if (!hHal) { + hddLog(LOGE, FL("Hal ctx is null")); + return -EINVAL; + } + + pVosContext = pHddCtx->pvosContext; + if (!pVosContext) { + hddLog(LOGE, FL("Vos ctx is null")); + return -EINVAL; + } + + switch(sub_cmd) + { + case QCASAP_SET_RADAR_DBG: + hddLog(LOG1, FL("QCASAP_SET_RADAR_DBG called with: value: %d"), + set_value); + sme_enable_phy_error_logs(hHal, (bool) set_value); + break; + + case QCSAP_PARAM_CLR_ACL: + if (VOS_STATUS_SUCCESS != WLANSAP_ClearACL( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter) +#else + pVosContext +#endif + )) + { + ret = -EIO; + } + break; + + case QCSAP_PARAM_ACL_MODE: + if ((eSAP_ALLOW_ALL < (eSapMacAddrACL)set_value) || + (eSAP_ACCEPT_UNLESS_DENIED > (eSapMacAddrACL)set_value)) + { + hddLog(LOGE, FL("Invalid ACL Mode value %d"), set_value); + ret = -EINVAL; + } + else + { +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_SetMode(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), set_value); +#else + WLANSAP_SetMode(pVosContext, set_value); +#endif + + } + break; + + case QCSAP_PARAM_AUTO_CHANNEL: + if (set_value == 0 || set_value == 1) + (WLAN_HDD_GET_CTX( + pHostapdAdapter))->cfg_ini->force_sap_acs = + set_value; + else + ret = -EINVAL; + break; + + case QCSAP_PARAM_SET_CHANNEL_CHANGE: + if ((WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)|| + (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) { + hddLog(LOG1, "SET Channel Change to new channel= %d", + set_value); + ret = hdd_softap_set_channel_change(dev, set_value); + } else { + hddLog(LOGE, + FL("Channel Change Failed, Device in test mode")); + ret = -EINVAL; + } + break; + + case QCSAP_PARAM_MAX_ASSOC: + if (WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) + { + hddLog(LOGE, FL("Invalid setMaxAssoc value %d"), set_value); + ret = -EINVAL; + } + else + { + if (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value) + { + hddLog(LOGW, FL("setMaxAssoc value %d higher than max allowed %d." + "Setting it to max allowed and continuing"), + set_value, WNI_CFG_ASSOC_STA_LIMIT_STAMAX); + set_value = WNI_CFG_ASSOC_STA_LIMIT_STAMAX; + } + status = ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, + set_value, NULL, eANI_BOOLEAN_FALSE); + if ( status != eHAL_STATUS_SUCCESS ) + { + hddLog(LOGE, FL("setMaxAssoc failure, status %d"), + status); + ret = -EIO; + } + } + break; + + case QCSAP_PARAM_HIDE_SSID: + { + eHalStatus status = eHAL_STATUS_SUCCESS; + status = sme_HideSSID(hHal, pHostapdAdapter->sessionId, set_value); + if(eHAL_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: QCSAP_PARAM_HIDE_SSID failed", + __func__); + return status; + } + break; + } + case QCSAP_PARAM_SET_MC_RATE: + { + tSirRateUpdateInd rateUpdate = {0}; + hdd_config_t *pConfig = pHddCtx->cfg_ini; + + hddLog(VOS_TRACE_LEVEL_INFO, "MC Target rate %d", set_value); + memcpy(rateUpdate.bssid, + pHostapdAdapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + rateUpdate.nss = (pConfig->enable2x2 == 0) ? 0 : 1; + rateUpdate.dev_mode = pHostapdAdapter->device_mode; + rateUpdate.mcastDataRate24GHz = set_value; + rateUpdate.mcastDataRate24GHzTxFlag = 1; + rateUpdate.mcastDataRate5GHz = set_value; + rateUpdate.bcastDataRate = -1; + if (sme_SendRateUpdateInd(hHal, &rateUpdate) != + eHAL_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SET_MC_RATE failed", + __func__); + ret = -1; + } + break; + } + + case QCSAP_PARAM_SET_TXRX_FW_STATS: + { + hddLog(LOG1, "QCSAP_PARAM_SET_TXRX_FW_STATS val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID, + set_value, VDEV_CMD); + break; + } + /* Firmware debug log */ + case QCSAP_DBGLOG_LOG_LEVEL: + { + hddLog(LOG1, "QCSAP_DBGLOG_LOG_LEVEL val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_LOG_LEVEL, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_VAP_ENABLE: + { + hddLog(LOG1, "QCSAP_DBGLOG_VAP_ENABLE val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_VAP_ENABLE, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_VAP_DISABLE: + { + hddLog(LOG1, "QCSAP_DBGLOG_VAP_DISABLE val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_VAP_DISABLE, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_MODULE_ENABLE: + { + hddLog(LOG1, "QCSAP_DBGLOG_MODULE_ENABLE val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_MODULE_ENABLE, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_MODULE_DISABLE: + { + hddLog(LOG1, "QCSAP_DBGLOG_MODULE_DISABLE val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_MODULE_DISABLE, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_MOD_LOG_LEVEL: + { + hddLog(LOG1, "QCSAP_DBGLOG_MOD_LOG_LEVEL val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_MOD_LOG_LEVEL, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_TYPE: + { + hddLog(LOG1, "QCSAP_DBGLOG_TYPE val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_TYPE, + set_value, DBG_CMD); + break; + } + case QCSAP_DBGLOG_REPORT_ENABLE: + { + hddLog(LOG1, "QCSAP_DBGLOG_REPORT_ENABLE val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_DBGLOG_REPORT_ENABLE, + set_value, DBG_CMD); + break; + } + case QCSAP_PARAM_SET_MCC_CHANNEL_LATENCY: + { + tVOS_CONCURRENCY_MODE concurrent_state = 0; + v_U8_t first_adapter_operating_channel = 0; + int ret = 0; /* success */ + hddLog(LOG1, "%s: iwpriv cmd to set MCC latency with val: " + "%dms", __func__, set_value); + concurrent_state = hdd_get_concurrency_mode(); + /** + * Check if concurrency mode is active. + * Need to modify this code to support MCC modes other than + * STA/P2P GO + */ + if (concurrent_state == (VOS_STA | VOS_P2P_GO)) + { + hddLog(LOG1, "%s: STA & P2P are both enabled", __func__); + /** + * The channel number and latency are formatted in + * a bit vector then passed on to WMA layer. + +**********************************************+ + | bits 31-16 | bits 15-8 | bits 7-0 | + | Unused | latency - Chan. 1 | channel no.| + +**********************************************+ + */ + + /* Get the operating channel of the designated vdev */ + first_adapter_operating_channel = + hdd_get_operating_channel + ( + pHostapdAdapter->pHddCtx, + pHostapdAdapter->device_mode + ); + /* Move the time latency for the adapter to bits 15-8 */ + set_value = set_value << 8; + /* Store the channel number at bits 7-0 of the bit vector + * as per the bit format above. + */ + set_value = set_value | first_adapter_operating_channel; + /* Send command to WMA */ + ret = process_wma_set_command + ( + (int)pHostapdAdapter->sessionId, + (int)WMA_VDEV_MCC_SET_TIME_LATENCY, + set_value, VDEV_CMD + ); + } + else + { + hddLog(LOG1, "%s: MCC is not active. Exit w/o setting" + " latency", __func__); + } + break; + } + + case QCSAP_PARAM_SET_MCC_CHANNEL_QUOTA: + { + hddLog(LOG1, "%s: iwpriv cmd to set MCC quota value %dms", + __func__, set_value); + ret = hdd_wlan_go_set_mcc_p2p_quota(pHostapdAdapter, + set_value); + break; + } + + case QCASAP_TXRX_FWSTATS_RESET: + { + hddLog(LOG1, "WE_TXRX_FWSTATS_RESET val %d", set_value); + if (set_value != WMA_FW_TXRX_FWSTATS_RESET) { + hddLog(LOGE, "Invalid arg %d in FWSTATS_RESET IOCTL", + set_value); + return -EINVAL; + } + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMA_VDEV_TXRX_FWSTATS_RESET_CMDID, + set_value, VDEV_CMD); + break; + } + + case QCSAP_PARAM_RTSCTS: + { + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, + set_value, VDEV_CMD); + if (ret) { + hddLog(LOGE, "FAILED TO SET RTSCTS at SAP"); + ret = -EIO; + } + break; + } + case QCASAP_SET_11N_RATE: + { + u_int8_t preamble = 0, nss = 0, rix = 0; + tsap_Config_t *pConfig = + &pHostapdAdapter->sessionCtx.ap.sapConfig; + + hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d", set_value); + + if (set_value != 0xff) { + rix = RC_2_RATE_IDX(set_value); + if (set_value & 0x80) { + if (pConfig->SapHw_mode == eCSR_DOT11_MODE_11b || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11b_ONLY || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11g || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11g_ONLY || + pConfig->SapHw_mode == eCSR_DOT11_MODE_abg || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11a) { + hddLog(LOGE, "Not valid mode for HT"); + ret = -EIO; + break; + } + preamble = WMI_RATE_PREAMBLE_HT; + nss = HT_RC_2_STREAMS(set_value) - 1; + } else if (set_value & 0x10) { + if (pConfig->SapHw_mode == eCSR_DOT11_MODE_11a) { + hddLog(VOS_TRACE_LEVEL_ERROR, "Not valid for cck"); + ret = -EIO; + break; + } + preamble = WMI_RATE_PREAMBLE_CCK; + /* Enable Short preamble always for CCK except 1mbps */ + if (rix != 0x3) + rix |= 0x4; + } else { + if (pConfig->SapHw_mode == eCSR_DOT11_MODE_11b || + pConfig->SapHw_mode == eCSR_DOT11_MODE_11b_ONLY) { + hddLog(VOS_TRACE_LEVEL_ERROR, "Not valid for OFDM"); + ret = -EIO; + break; + } + preamble = WMI_RATE_PREAMBLE_OFDM; + } + + set_value = (preamble << 6) | (nss << 4) | rix; + } + hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d rix %d " + "preamble %x nss %d", set_value, rix, preamble, nss); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case QCASAP_SET_VHT_RATE: + { + u_int8_t preamble = 0, nss = 0, rix = 0; + tsap_Config_t *pConfig = + &pHostapdAdapter->sessionCtx.ap.sapConfig; + + if (pConfig->SapHw_mode != eCSR_DOT11_MODE_11ac && + pConfig->SapHw_mode != eCSR_DOT11_MODE_11ac_ONLY) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SET_VHT_RATE error: SapHw_mode= 0x%x, ch = %d", + __func__, pConfig->SapHw_mode, pConfig->channel); + ret = -EIO; + break; + } + + if (set_value != 0xff) { + rix = RC_2_RATE_IDX_11AC(set_value); + preamble = WMI_RATE_PREAMBLE_VHT; + nss = HT_RC_2_STREAMS_11AC(set_value) - 1; + + set_value = (preamble << 6) | (nss << 4) | rix; + } + hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d rix %d " + "preamble %x nss %d", set_value, rix, preamble, nss); + + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case QCASAP_SHORT_GI: + { + hddLog(LOG1, "QCASAP_SET_SHORT_GI val %d", set_value); + + ret = sme_UpdateHTConfig(hHal, pHostapdAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ, /* same as 40MHZ */ + set_value); + if (ret) + hddLog(LOGE, "Failed to set ShortGI value ret(%d)", ret); + break; + } + + case QCSAP_SET_AMPDU: + { + hddLog(LOG1, "QCSAP_SET_AMPDU val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMPDU, + set_value, GEN_CMD); + break; + } + + case QCSAP_SET_AMSDU: + { + hddLog(LOG1, "QCSAP_SET_AMSDU val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMSDU, + set_value, GEN_CMD); + break; + } + case QCSAP_GTX_HT_MCS: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_HT_MCS %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_HT_MCS, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_VHT_MCS: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_VHT_MCS %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_VHT_MCS, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_USRCFG: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_USR_CFG %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_USR_CFG, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_THRE: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_THRE %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_THRE, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_MARGIN: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_MARGIN %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MARGIN, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_STEP: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_STEP %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_STEP, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_MINTPC: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_MINTPC %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MINTPC, + set_value, GTX_CMD); + break; + } + + case QCSAP_GTX_BWMASK: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_BWMASK %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_BW_MASK, + set_value, GTX_CMD); + break; + } + + + +#ifdef QCA_PKT_PROTO_TRACE + case QCASAP_SET_DEBUG_LOG: + { + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + + hddLog(LOG1, "QCASAP_SET_DEBUG_LOG val %d", set_value); + /* Trace buffer dump only */ + if (VOS_PKT_TRAC_DUMP_CMD == set_value) + { + vos_pkt_trace_buf_dump(); + break; + } + pHddCtx->cfg_ini->gEnableDebugLog = set_value; + break; + } +#endif /* QCA_PKT_PROTO_TRACE */ + + case QCASAP_SET_TM_LEVEL: + { + hddLog(VOS_TRACE_LEVEL_INFO, "Set Thermal Mitigation Level %d", + set_value); + (void)sme_SetThermalLevel(hHal, set_value); + break; + } + + + case QCASAP_SET_DFS_IGNORE_CAC: + { + hddLog(VOS_TRACE_LEVEL_INFO, "Set Dfs ignore CAC %d", + set_value); + + if (pHostapdAdapter->device_mode != WLAN_HDD_SOFTAP) + return -EINVAL; + + ret = WLANSAP_Set_Dfs_Ignore_CAC(hHal, set_value); + break; + } + + case QCASAP_SET_DFS_TARGET_CHNL: + { + hddLog(VOS_TRACE_LEVEL_INFO, "Set Dfs target channel %d", + set_value); + + if (pHostapdAdapter->device_mode != WLAN_HDD_SOFTAP) + return -EINVAL; + + ret = WLANSAP_Set_Dfs_Target_Chnl(hHal, set_value); + break; + } + + + case QCASAP_SET_DFS_NOL: + WLANSAP_Set_DfsNol( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), +#else + pVosContext, +#endif + (eSapDfsNolType)set_value + ); + break; + + case QCASAP_SET_RADAR_CMD: + { + hdd_context_t *pHddCtx = + WLAN_HDD_GET_CTX(pHostapdAdapter); + v_U8_t ch = + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->operatingChannel; + v_BOOL_t isDfsch; + + isDfsch = (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(ch)); + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Set QCASAP_SET_RADAR_CMD val %d"), set_value); + + if (!pHddCtx->dfs_radar_found && isDfsch) { + ret = process_wma_set_command( + (int)pHostapdAdapter->sessionId, + (int)WMA_VDEV_DFS_CONTROL_CMDID, + set_value, VDEV_CMD); + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Ignore command due to " + "dfs_radar_found: %d, is_dfs_channel: %d"), + pHddCtx->dfs_radar_found, isDfsch); + } + break; + } + case QCASAP_TX_CHAINMASK_CMD: + { + hddLog(LOG1, "QCASAP_TX_CHAINMASK_CMD val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, + set_value, PDEV_CMD); + break; + } + + case QCASAP_RX_CHAINMASK_CMD: + { + hddLog(LOG1, "QCASAP_RX_CHAINMASK_CMD val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, + set_value, PDEV_CMD); + break; + } + + case QCASAP_NSS_CMD: + { + hddLog(LOG1, "QCASAP_NSS_CMD val %d", set_value); + ret = process_wma_set_command((int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_NSS, + set_value, VDEV_CMD); + break; + } +#ifdef IPA_UC_OFFLOAD + case QCSAP_IPA_UC_STAT: + { + /* If input value is non-zero get stats */ + if (1 == set_value) { + hdd_ipa_uc_stat_request(pHostapdAdapter, set_value); + } else if (3 == set_value) { + hdd_ipa_uc_rt_debug_host_dump( + WLAN_HDD_GET_CTX(pHostapdAdapter)); + } else { + /* place holder for stats clean up + * Stats clean not implemented yet on firmware and ipa */ + } + + return ret; + } +#endif /* IPA_UC_OFFLOAD */ + case QCASAP_SET_PHYMODE: + { + hdd_context_t *phddctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + + ret = wlan_hdd_update_phymode(dev, hHal, set_value, phddctx); + break; + } + case QCASAP_DUMP_STATS: + { + hddLog(LOG1, "QCASAP_DUMP_STATS val %d", set_value); + hdd_wlan_dump_stats(pHostapdAdapter, set_value); + break; + } + case QCASAP_CLEAR_STATS: + { + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + + hddLog(LOG1, "QCASAP_CLEAR_STATS val %d", set_value); + + if (set_value == WLAN_HDD_STATS) { + memset(&pHostapdAdapter->stats, 0, + sizeof(pHostapdAdapter->stats)); + memset(&pHostapdAdapter->hdd_stats, 0, + sizeof(pHostapdAdapter->hdd_stats)); + } else { + WLANTL_clear_datapath_stats(hdd_ctx->pvosContext, + set_value); + } + + break; + } + + case QCASAP_PARAM_LDPC: + ret = hdd_set_ldpc(pHostapdAdapter, set_value); + break; + + case QCASAP_PARAM_TX_STBC: + ret = hdd_set_tx_stbc(pHostapdAdapter, set_value); + break; + + case QCASAP_PARAM_RX_STBC: + ret = hdd_set_rx_stbc(pHostapdAdapter, set_value); + break; + + default: + hddLog(LOGE, FL("Invalid setparam command %d value %d"), + sub_cmd, set_value); + ret = -EINVAL; + break; + } + EXIT(); + 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_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; +} + + +int +static iw_softap_setparam(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_setparam(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_getparam(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + int *value = (int *)extra; + int sub_cmd = value[0]; + eHalStatus status; + int ret; + hdd_context_t *pHddCtx; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + switch (sub_cmd) + { + case QCSAP_PARAM_MAX_ASSOC: + status = ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to get WNI_CFG_ASSOC_STA_LIMIT from cfg %d"),status); + ret = -EIO; + } + break; + + case QCSAP_PARAM_GET_WLAN_DBG: + { + vos_trace_display(); + *value = 0; + break; + } + + case QCSAP_PARAM_AUTO_CHANNEL: + *value = (WLAN_HDD_GET_CTX + (pHostapdAdapter))->cfg_ini->force_sap_acs; + + case QCSAP_PARAM_RTSCTS: + { + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, + VDEV_CMD); + break; + } + + case QCASAP_SHORT_GI: + { + *value = (int)sme_GetHTConfig(hHal, + pHostapdAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ); + break; + } + + case QCSAP_GTX_HT_MCS: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_HT_MCS"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_HT_MCS, + GTX_CMD); + break; + } + + case QCSAP_GTX_VHT_MCS: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_VHT_MCS"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_VHT_MCS, + GTX_CMD); + break; + } + + case QCSAP_GTX_USRCFG: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_USR_CFG"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_USR_CFG, + GTX_CMD); + break; + } + + case QCSAP_GTX_THRE: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_THRE"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_THRE, + GTX_CMD); + break; + } + + case QCSAP_GTX_MARGIN: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_MARGIN"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MARGIN, + GTX_CMD); + break; + } + + case QCSAP_GTX_STEP: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_STEP"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_STEP, + GTX_CMD); + break; + } + + case QCSAP_GTX_MINTPC: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_MINTPC"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MINTPC, + GTX_CMD); + break; + } + + case QCSAP_GTX_BWMASK: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_BW_MASK"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_BW_MASK, + GTX_CMD); + break; + } + + case QCASAP_GET_DFS_NOL: + { + WLANSAP_Get_DfsNol( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter) +#else + pHddCtx->pvosContext +#endif + ); + } + break; + + case QCSAP_GET_ACL: + { + hddLog(LOG1, FL("QCSAP_GET_ACL")); + if (hdd_print_acl(pHostapdAdapter) != VOS_STATUS_SUCCESS) { + hddLog(LOGE, FL("QCSAP_GET_ACL returned Error: not completed")); + } + *value = 0; + break; + } + + case QCASAP_TX_CHAINMASK_CMD: + { + hddLog(LOG1, "QCASAP_TX_CHAINMASK_CMD"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, + PDEV_CMD); + break; + } + + case QCASAP_RX_CHAINMASK_CMD: + { + hddLog(LOG1, "QCASAP_RX_CHAINMASK_CMD"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, + PDEV_CMD); + break; + } + + case QCASAP_NSS_CMD: + { + hddLog(LOG1, "QCASAP_NSS_CMD"); + *value = wma_cli_get_command(pHddCtx->pvosContext, + (int)pHostapdAdapter->sessionId, + (int)WMI_VDEV_PARAM_NSS, + VDEV_CMD); + break; + } + case QCASAP_GET_TEMP_CMD: + { + hddLog(VOS_TRACE_LEVEL_INFO, "QCASAP_GET_TEMP_CMD"); + ret = wlan_hdd_get_temperature(pHostapdAdapter, wrqu, extra); + break; + } + case QCSAP_GET_FW_STATUS: + { + hddLog(LOG1, "QCSAP_GET_FW_STATUS"); + *value = wlan_hdd_get_fw_state(pHostapdAdapter); + break; + } + case QCSAP_CAP_TSF: + { + ret = hdd_capture_tsf(pHostapdAdapter, (uint32_t *)value, 1); + break; + } + case QCASAP_PARAM_LDPC: + ret = hdd_get_ldpc(pHostapdAdapter, value); + break; + + case QCASAP_PARAM_TX_STBC: + ret = hdd_get_tx_stbc(pHostapdAdapter, value); + break; + + case QCASAP_PARAM_RX_STBC: + ret = hdd_get_rx_stbc(pHostapdAdapter, value); + break; + + default: + hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd); + ret = -EINVAL; + break; + } + EXIT(); + return ret; +} + +int +static iw_softap_getparam(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_getparam(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* Usage: + BLACK_LIST = 0 + WHITE_LIST = 1 + ADD MAC = 0 + REMOVE MAC = 1 + + mac addr will be accepted as a 6 octet mac address with each octet inputted in hex + for e.g. 00:0a:f5:11:22:33 will be represented as 0x00 0x0a 0xf5 0x11 0x22 0x33 + while using this ioctl + + Syntax: + iwpriv softap.0 modify_acl + <6 octet mac addr> + + Examples: + eg 1. to add a mac addr 00:0a:f5:89:89:90 to the black list + iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 0 0 + eg 2. to delete a mac addr 00:0a:f5:89:89:90 from white list + iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 1 1 +*/ +static +int __iw_softap_modify_acl(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = hdd_ctx->pvosContext; +#endif + v_BYTE_t *value = (v_BYTE_t*)extra; + v_U8_t pPeerStaMac[VOS_MAC_ADDR_SIZE]; + int listType, cmd, i; + int ret; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + +#ifndef WLAN_FEATURE_MBSSID + if (NULL == pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Vos Context is NULL", __func__); + return -EINVAL; + } +#endif + + for (i=0; ievent_flags)) + *value = (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->operatingChannel; + EXIT(); + return 0; +} + +int +static iw_softap_getchannel(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_getchannel(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_set_max_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + int *value = (int *)extra; + int set_value; + tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int ret; + + ENTER(); + + if (NULL == value) + return -ENOMEM; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* Assign correct slef MAC address */ + vos_mem_copy(bssid, pHostapdAdapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + vos_mem_copy(selfMac, pHostapdAdapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + + set_value = value[0]; + if (eHAL_STATUS_SUCCESS != sme_SetMaxTxPower(hHal, bssid, selfMac, set_value)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", + __func__); + return -EIO; + } + EXIT(); + return 0; +} + +int +static iw_softap_set_max_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_set_max_tx_power(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_display_data_path_snapshot(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + /* Function initiating dumping states of + * HDD(WMM Tx Queues) + * TL State (with Per Client infor) + * DXE Snapshot (Called at the end of TL Snapshot) + */ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + + ENTER(); + + hdd_wmm_tx_snapshot(pHostapdAdapter); + WLANTL_TLDebugMessage(VOS_TRUE); + EXIT(); + return 0; +} + +int +static iw_display_data_path_snapshot(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_display_data_path_snapshot(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_set_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + hdd_context_t *hdd_ctx; + int *value = (int *)extra; + int set_value; + tSirMacAddr bssid; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (NULL == value) + return -ENOMEM; + + vos_mem_copy(bssid, pHostapdAdapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + + set_value = value[0]; + if (eHAL_STATUS_SUCCESS != sme_SetTxPower(hHal, pHostapdAdapter->sessionId, bssid, + pHostapdAdapter->device_mode, + set_value)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting tx power failed", + __func__); + return -EIO; + } + EXIT(); + return 0; +} + +int +static iw_softap_set_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_set_tx_power(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +#define IS_BROADCAST_MAC(x) (((x[0] & x[1] & x[2] & x[3] & x[4] & x[5]) == 0xff) ? 1 : 0) + +int +static __iw_softap_getassoc_stamacaddr(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_station_info_t *pStaInfo = pHostapdAdapter->aStaInfo; + hdd_context_t *hdd_ctx; + char *buf; + int cnt = 0; + int left; + int ret; + /* maclist_index must be u32 to match user space */ + u32 maclist_index; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* + * NOTE WELL: this is a "get" ioctl but it uses an even ioctl + * number, and even numbered iocts are supposed to have "set" + * semantics. Hence the wireless extensions support in the kernel + * won't correctly copy the result to user space, so the ioctl + * handler itself must copy the data. Output format is 32-bit + * record length, followed by 0 or more 6-byte STA MAC addresses. + * + * Further note that due to the incorrect semantics, the "iwpriv" + * user space application is unable to correctly invoke this API, + * hence it is not registered in the hostapd_private_args. This + * API can only be invoked by directly invoking the ioctl() system + * call. + */ + + /* Make sure user space allocated a reasonable buffer size */ + if (wrqu->data.length < sizeof(maclist_index)) { + hddLog(LOG1, "%s: invalid userspace buffer", __func__); + return -EINVAL; + } + + /* allocate local buffer to build the response */ + buf = kmalloc(wrqu->data.length, GFP_KERNEL); + if (!buf) { + hddLog(LOG1, "%s: failed to allocate response buffer", __func__); + return -ENOMEM; + } + + /* start indexing beyond where the record count will be written */ + maclist_index = sizeof(maclist_index); + left = wrqu->data.length - maclist_index; + + spin_lock_bh(&pHostapdAdapter->staInfo_lock); + while ((cnt < WLAN_MAX_STA_COUNT) && (left >= VOS_MAC_ADDR_SIZE)) { + if ((pStaInfo[cnt].isUsed) && + (!IS_BROADCAST_MAC(pStaInfo[cnt].macAddrSTA.bytes))) { + memcpy(&buf[maclist_index], &(pStaInfo[cnt].macAddrSTA), + VOS_MAC_ADDR_SIZE); + maclist_index += VOS_MAC_ADDR_SIZE; + left -= VOS_MAC_ADDR_SIZE; + } + cnt++; + } + spin_unlock_bh(&pHostapdAdapter->staInfo_lock); + + *((u32 *)buf) = maclist_index; + wrqu->data.length = maclist_index; + if (copy_to_user(wrqu->data.pointer, buf, maclist_index)) { + hddLog(LOG1, "%s: failed to copy response to user buffer", __func__); + ret = -EFAULT; + } + kfree(buf); + EXIT(); + return ret; +} + +int +static iw_softap_getassoc_stamacaddr(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_getassoc_stamacaddr(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* Usage: + mac addr will be accepted as a 6 octet mac address with each octet inputted in hex + for e.g. 00:0a:f5:11:22:33 will be represented as 0x00 0x0a 0xf5 0x11 0x22 0x33 + while using this ioctl + + Syntax: + iwpriv softap.0 disassoc_sta <6 octet mac address> + + e.g. + disassociate sta with mac addr 00:0a:f5:11:22:33 from softap + iwpriv softap.0 disassoc_sta 0x00 0x0a 0xf5 0x11 0x22 0x33 +*/ + +int +static __iw_softap_disassoc_sta(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx; + v_U8_t *peerMacAddr; + struct tagCsrDelStaParams delStaParams; + int ret; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* iwpriv tool or framework calls this ioctl with + * data passed in extra (less than 16 octets); + */ + peerMacAddr = (v_U8_t *)(extra); + + hddLog(LOG1, "%s data " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peerMacAddr)); + + + WLANSAP_PopulateDelStaParams(peerMacAddr, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + (SIR_MAC_MGMT_DISASSOC >> 4), + &delStaParams); + + hdd_softap_sta_disassoc(pHostapdAdapter, &delStaParams); + EXIT(); + return 0; +} + +int +static iw_softap_disassoc_sta(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_disassoc_sta(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_ap_stats(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + WLANTL_TRANSFER_STA_TYPE statBuffer; + char *pstatbuf; + int len; + + ENTER(); + + memset(&statBuffer, 0, sizeof(statBuffer)); + WLANSAP_GetStatistics((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, + &statBuffer, (v_BOOL_t)wrqu->data.flags); + + pstatbuf = kmalloc(wrqu->data.length, GFP_KERNEL); + if(NULL == pstatbuf) { + hddLog(LOG1, "unable to allocate memory"); + return -ENOMEM; + } + len = scnprintf(pstatbuf, wrqu->data.length, + "RUF=%d RMF=%d RBF=%d " + "RUB=%d RMB=%d RBB=%d " + "TUF=%d TMF=%d TBF=%d " + "TUB=%d TMB=%d TBB=%d", + (int)statBuffer.rxUCFcnt, (int)statBuffer.rxMCFcnt, + (int)statBuffer.rxBCFcnt, (int)statBuffer.rxUCBcnt, + (int)statBuffer.rxMCBcnt, (int)statBuffer.rxBCBcnt, + (int)statBuffer.txUCFcnt, (int)statBuffer.txMCFcnt, + (int)statBuffer.txBCFcnt, (int)statBuffer.txUCBcnt, + (int)statBuffer.txMCBcnt, (int)statBuffer.txBCBcnt); + + if (len > wrqu->data.length || + copy_to_user((void *)wrqu->data.pointer, (void *)pstatbuf, len)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + kfree(pstatbuf); + return -EFAULT; + } + wrqu->data.length -= len; + kfree(pstatbuf); + EXIT(); + return 0; +} + +int +static iw_softap_ap_stats(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_ap_stats(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_get_char_setnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int sub_cmd = wrqu->data.flags; + ENTER(); + if (NULL == WLAN_HDD_GET_CTX(pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD Context is NULL!", __func__); + + return -EINVAL; + } + + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + switch(sub_cmd) + { + case QCSAP_GET_STATS: + { + hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; + } + } + return 0; +} + +static int iw_get_char_setnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_char_setnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int wlan_hdd_set_force_acs_ch_range(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int *value = (int *)extra; + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + if (wlan_hdd_validate_operation_channel(adapter, value[0]) != + VOS_STATUS_SUCCESS || + wlan_hdd_validate_operation_channel(adapter, value[1]) != + VOS_STATUS_SUCCESS) { + return -EINVAL; + } else { + hdd_ctx->cfg_ini->force_sap_acs_st_ch = value[0]; + hdd_ctx->cfg_ini->force_sap_acs_end_ch = value[1]; + } + + return 0; +} + +static int iw_softap_set_force_acs_ch_range(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + vos_ssr_protect(__func__); + ret = wlan_hdd_set_force_acs_ch_range(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + return ret; +} + +static int __iw_softap_get_channel_list(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + v_U32_t num_channels = 0; + v_U8_t i = 0; + v_U8_t bandStartChannel = RF_CHAN_1; + v_U8_t bandEndChannel = RF_CHAN_184; + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + tpChannelListInfo channel_list = (tpChannelListInfo) extra; + eCsrBand curBand = eCSR_BAND_ALL; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (eHAL_STATUS_SUCCESS != sme_GetFreqBand(hHal, &curBand)) + { + hddLog(LOGE,FL("not able get the current frequency band")); + return -EIO; + } + wrqu->data.length = sizeof(tChannelListInfo); + ENTER(); + + if (eCSR_BAND_24 == curBand) + { + bandStartChannel = RF_CHAN_1; + bandEndChannel = RF_CHAN_14; + } + else if (eCSR_BAND_5G == curBand) + { + bandStartChannel = RF_CHAN_36; + bandEndChannel = RF_CHAN_184; + } + + hddLog(LOG1, FL("curBand = %d, bandStartChannel = %hu, " + "bandEndChannel = %hu "), curBand, + bandStartChannel, bandEndChannel ); + + for( i = bandStartChannel; i <= bandEndChannel; i++ ) + { + if ((NV_CHANNEL_ENABLE == regChannels[i].enabled) || + (NV_CHANNEL_DFS == regChannels[i].enabled)) + { + channel_list->channels[num_channels] = rfChannels[i].channelNum; + num_channels++; + } + } + + + hddLog(LOG1,FL(" number of channels %d"), num_channels); + + if (num_channels > IW_MAX_FREQUENCIES) + { + num_channels = IW_MAX_FREQUENCIES; + } + + channel_list->num_channels = num_channels; + EXIT(); + + return 0; +} + +int iw_softap_get_channel_list(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_channel_list(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static +int __iw_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx; + int ret; +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext; +#endif + eHalStatus status; + v_U32_t length = DOT11F_IE_RSN_MAX_LEN; + v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN]; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + +#ifndef WLAN_FEATURE_MBSSID + pVosContext = hdd_ctx->pvosContext; + if (NULL == pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is not valid ", __func__); + return -EINVAL; + } +#endif + + // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.) + status = WLANSap_getstationIE_information( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), +#else + pVosContext, +#endif + &length, + genIeBytes + ); + + length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN); + if (wrqu->data.length < length || + copy_to_user(wrqu->data.pointer, + (v_VOID_t*)genIeBytes, length)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } + wrqu->data.length = length; + + hddLog(LOG1,FL(" RSN IE of %d bytes returned"), wrqu->data.length ); + + + EXIT(); + return 0; +} + +static +int iw_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_genie(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static +int __iw_get_WPSPBCProbeReqIEs(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + sQcSapreq_WPSPBCProbeReqIES_t WPSPBCProbeReqIEs; + hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + memset((void*)&WPSPBCProbeReqIEs, 0, sizeof(WPSPBCProbeReqIEs)); + + WPSPBCProbeReqIEs.probeReqIELen = pHddApCtx->WPSPBCProbeReq.probeReqIELen; + vos_mem_copy(&WPSPBCProbeReqIEs.probeReqIE, + pHddApCtx->WPSPBCProbeReq.probeReqIE, + WPSPBCProbeReqIEs.probeReqIELen); + vos_mem_copy(&WPSPBCProbeReqIEs.macaddr, + pHddApCtx->WPSPBCProbeReq.peerMacAddr, + sizeof(v_MACADDR_t)); + if (copy_to_user(wrqu->data.pointer, + (void *)&WPSPBCProbeReqIEs, + sizeof(WPSPBCProbeReqIEs))) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } + wrqu->data.length = 12 + WPSPBCProbeReqIEs.probeReqIELen; + hddLog(LOG1, FL("Macaddress : "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(WPSPBCProbeReqIEs.macaddr)); + up(&pHddApCtx->semWpsPBCOverlapInd); + EXIT(); + return 0; +} + +static +int iw_get_WPSPBCProbeReqIEs(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_WPSPBCProbeReqIEs(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_auth_hostap() - This function sets the auth type received + * from the wpa_supplicant. + * + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int +__iw_set_auth_hostap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_TKIP_COUNTERMEASURES: + if (wrqu->param.value) { + hddLog(LOG2, + FL("Counter Measure started(%d)"), + wrqu->param.value); + pWextState->mTKIPCounterMeasures = + TKIP_COUNTER_MEASURE_STARTED; + } else { + hddLog(LOG2, + FL("Counter Measure stopped(%d)"), + wrqu->param.value); + pWextState->mTKIPCounterMeasures = + TKIP_COUNTER_MEASURE_STOPED; + } + + hdd_softap_tkip_mic_fail_counter_measure(pAdapter, + wrqu->param.value); + break; + + default: + hddLog(LOGW, FL("called with unsupported auth type %d"), + wrqu->param.flags & IW_AUTH_INDEX); + break; + } + + EXIT(); + return 0; +} + +/** + * iw_set_auth_hostap() - Wrapper function to protect __iw_set_auth_hostap + * from the SSR. + * + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int +iw_set_auth_hostap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_auth_hostap(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_ap_encodeext() - set ap encode + * + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int __iw_set_ap_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext; +#endif + hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + hdd_context_t *hdd_ctx; + int ret; + VOS_STATUS vstatus; + struct iw_encode_ext *ext = (struct iw_encode_ext*)extra; + v_U8_t groupmacaddr[VOS_MAC_ADDR_SIZE] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int key_index; + struct iw_point *encoding = &wrqu->encoding; + tCsrRoamSetKey setKey; +// tCsrRoamRemoveKey RemoveKey; + int i; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + +#ifndef WLAN_FEATURE_MBSSID + pVosContext = hdd_ctx->pvosContext; + if (NULL == pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: pVosContext is NULL", __func__); + return -EINVAL; + } +#endif + + key_index = encoding->flags & IW_ENCODE_INDEX; + + key_index = encoding->flags & IW_ENCODE_INDEX; + + if(key_index > 0) { + + /*Convert from 1-based to 0-based keying*/ + key_index--; + } + if(!ext->key_len) { +#if 0 + /*Set the encryption type to NONE*/ +#if 0 + pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; +#endif + + RemoveKey.keyId = key_index; + if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /*Key direction for group is RX only*/ + vos_mem_copy(RemoveKey.peerMac,groupmacaddr, VOS_MAC_ADDR_SIZE); + } + else { + vos_mem_copy(RemoveKey.peerMac,ext->addr.sa_data, VOS_MAC_ADDR_SIZE); + } + switch(ext->alg) + { + case IW_ENCODE_ALG_NONE: + RemoveKey.encType = eCSR_ENCRYPT_TYPE_NONE; + break; + case IW_ENCODE_ALG_WEP: + RemoveKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104; + break; + case IW_ENCODE_ALG_TKIP: + RemoveKey.encType = eCSR_ENCRYPT_TYPE_TKIP; + break; + case IW_ENCODE_ALG_CCMP: + RemoveKey.encType = eCSR_ENCRYPT_TYPE_AES; + break; + default: + RemoveKey.encType = eCSR_ENCRYPT_TYPE_NONE; + break; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Remove key cipher_alg:%d key_len%d *pEncryptionType :%d", + __func__,(int)ext->alg,(int)ext->key_len,RemoveKey.encType); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Peer Mac = "MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(RemoveKey.peerMac)); + ); +#ifdef WLAN_FEATURE_MBSSID + vstatus = WLANSAP_DelKeySta( WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), &RemoveKey ); +#else + vstatus = WLANSAP_DelKeySta( pVosContext, &RemoveKey ); +#endif + + if ( vstatus != VOS_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "[%4d] WLANSAP_DeleteKeysSta returned ERROR status= %d", + __LINE__, vstatus ); + retval = -EINVAL; + } +#endif + return ret; + + } + + vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); + + setKey.keyId = key_index; + setKey.keyLength = ext->key_len; + + if(ext->key_len <= CSR_MAX_KEY_LEN) { + vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len); + } + + if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /*Key direction for group is RX only*/ + setKey.keyDirection = eSIR_RX_ONLY; + vos_mem_copy(setKey.peerMac,groupmacaddr, VOS_MAC_ADDR_SIZE); + } + else { + + setKey.keyDirection = eSIR_TX_RX; + vos_mem_copy(setKey.peerMac,ext->addr.sa_data, VOS_MAC_ADDR_SIZE); + } + if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + setKey.keyDirection = eSIR_TX_DEFAULT; + vos_mem_copy(setKey.peerMac,ext->addr.sa_data, VOS_MAC_ADDR_SIZE); + } + + /*For supplicant pae role is zero*/ + setKey.paeRole = 0; + + switch(ext->alg) + { + case IW_ENCODE_ALG_NONE: + setKey.encType = eCSR_ENCRYPT_TYPE_NONE; + break; + + case IW_ENCODE_ALG_WEP: + setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104; + pHddApCtx->uPrivacy = 1; + hddLog(LOG1, "(%s) uPrivacy=%d", __func__, pHddApCtx->uPrivacy); + break; + + case IW_ENCODE_ALG_TKIP: + { + v_U8_t *pKey = &setKey.Key[0]; + + setKey.encType = eCSR_ENCRYPT_TYPE_TKIP; + + vos_mem_zero(pKey, CSR_MAX_KEY_LEN); + + /*Supplicant sends the 32bytes key in this order + + |--------------|----------|----------| + | Tk1 |TX-MIC | RX Mic | + |--------------|----------|----------| + <---16bytes---><--8bytes--><--8bytes--> + + */ + /*Sme expects the 32 bytes key to be in the below order + + |--------------|----------|----------| + | Tk1 |RX-MIC | TX Mic | + |--------------|----------|----------| + <---16bytes---><--8bytes--><--8bytes--> + */ + /* Copy the Temporal Key 1 (TK1) */ + vos_mem_copy(pKey,ext->key,16); + + /*Copy the rx mic first*/ + vos_mem_copy(&pKey[16],&ext->key[24],8); + + /*Copy the tx mic */ + vos_mem_copy(&pKey[24],&ext->key[16],8); + + } + break; + + case IW_ENCODE_ALG_CCMP: + setKey.encType = eCSR_ENCRYPT_TYPE_AES; + break; + + default: + setKey.encType = eCSR_ENCRYPT_TYPE_NONE; + break; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("%s:EncryptionType:%d key_len:%d, KeyId:%d"), __func__, setKey.encType, setKey.keyLength, + setKey.keyId); + for(i=0; i< ext->key_len; i++) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("%02x"), setKey.Key[i]); + +#ifdef WLAN_FEATURE_MBSSID + vstatus = WLANSAP_SetKeySta( WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), &setKey ); +#else + vstatus = WLANSAP_SetKeySta( pVosContext, &setKey ); +#endif + + if ( vstatus != VOS_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] WLANSAP_SetKeySta returned ERROR status= %d", __LINE__, vstatus ); + ret = -EINVAL; + } + + EXIT(); + return ret; +} + +/** + * iw_set_ap_encodeext() - Wrapper function to protect __iw_set_ap_encodeext + * from the SSR. + * + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int iw_set_ap_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_ap_encodeext(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_ap_mlme() - set ap mlme + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu; pointer to iwreq_data + * @extra: extra + * + * Return; 0 on success, error number otherwise + */ +static int __iw_set_ap_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ +#if 0 + hdd_adapter_t *pAdapter = (netdev_priv(dev)); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + + ENTER(); + + //reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED + switch (mlme->cmd) { + case IW_MLME_DISASSOC: + case IW_MLME_DEAUTH: + hddLog(LOG1, "Station disassociate"); + if( pAdapter->conn_info.connState == eConnectionState_Associated ) + { + eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED; + + if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE ) + reason = eCSR_DISCONNECT_REASON_MIC_ERROR; + + status = sme_RoamDisconnect( pAdapter->hHal,pAdapter->sessionId, reason); + + //clear all the reason codes + if (status != 0) + { + hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d", __func__, (int)mlme->cmd, (int)status ); + } + + netif_stop_queue(dev); + netif_carrier_off(dev); + } + else + { + hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state", __func__, (int)mlme->cmd ); + } + default: + hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate", __func__, (int)mlme->cmd ); + return -EINVAL; + }//end of switch + EXIT(); +#endif + return 0; +// return status; +} + +/** + * iw_set_ap_mlme() - SSR wrapper for __iw_set_ap_mlme + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu; pointer to iwreq_data + * @extra: extra + * + * Return; 0 on success, error number otherwise + */ +static int iw_set_ap_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_ap_mlme(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + + +/** + * __iw_get_ap_rts_threshold() - get ap rts threshold + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int __iw_get_ap_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = netdev_priv(dev); + int ret; + hdd_context_t *hdd_ctx; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + ret = hdd_wlan_get_rts_threshold(pHostapdAdapter, wrqu); + + return ret; +} + +/** + * iw_get_ap_rts_threshold() - Wrapper function to protect + * __iw_get_ap_rts_threshold from the SSR. + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int iw_get_ap_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_ap_rts_threshold(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_ap_frag_threshold() - get ap fragmentation threshold + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int __iw_get_ap_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = netdev_priv(dev); + hdd_context_t *hdd_ctx; + int ret = 0; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + ret = hdd_wlan_get_frag_threshold(pHostapdAdapter, wrqu); + + return ret; +} + +/** + * iw_get_ap_frag_threshold() - Wrapper function to protect + * __iw_get_ap_frag_threshold from the SSR. + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int iw_get_ap_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_ap_frag_threshold(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_ap_freq() - get ap frequency + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int __iw_get_ap_freq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *fwrq, char *extra) +{ + v_U32_t status = FALSE, channel = 0, freq = 0; + hdd_adapter_t *pHostapdAdapter = netdev_priv(dev); + hdd_context_t *hdd_ctx; + tHalHandle hHal; + hdd_hostapd_state_t *pHostapdState; + hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + + if(pHostapdState->bssState == BSS_STOP ) + { + if (ccmCfgGetInt(hHal, WNI_CFG_CURRENT_CHANNEL, &channel) + != eHAL_STATUS_SUCCESS) + { + return -EIO; + } + else + { + status = hdd_wlan_get_freq(channel, &freq); + if( TRUE == status) + { + /* Set Exponent parameter as 6 (MHZ) in struct iw_freq + * iwlist & iwconfig command shows frequency into proper + * format (2.412 GHz instead of 246.2 MHz)*/ + fwrq->m = freq; + fwrq->e = MHZ; + } + } + } + else + { + channel = pHddApCtx->operatingChannel; + status = hdd_wlan_get_freq(channel, &freq); + if( TRUE == status) + { + /* Set Exponent parameter as 6 (MHZ) in struct iw_freq + * iwlist & iwconfig command shows frequency into proper + * format (2.412 GHz instead of 246.2 MHz)*/ + fwrq->m = freq; + fwrq->e = MHZ; + } + } + EXIT(); + return 0; +} + +/** + * iw_get_ap_freq() - Wrapper function to protect + * __iw_get_ap_freq from the SSR. + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int iw_get_ap_freq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_ap_freq(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_mode() - get mode + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int __iw_get_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + wrqu->mode = IW_MODE_MASTER; + + return ret; +} + +/** + * iw_get_mode() - Wrapper function to protect __iw_get_mode from the SSR. + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int iw_get_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_mode(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + + +static int __iw_softap_setwpsie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext; +#endif + hdd_hostapd_state_t *pHostapdState; + eHalStatus halStatus= eHAL_STATUS_SUCCESS; + u_int8_t *wps_genie; + u_int8_t *fwps_genie; + u_int8_t *pos; + tpSap_WPSIE pSap_WPSIe; + u_int8_t WPSIeType; + u_int16_t length; + struct iw_point s_priv_data; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + +#ifndef WLAN_FEATURE_MBSSID + pVosContext = hdd_ctx->pvosContext; + if (NULL == pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: VOS context is not valid ", __func__); + return -EINVAL; + } +#endif + + /* helper function to get iwreq_data with compat handling. */ + if (hdd_priv_get_data(&s_priv_data, wrqu)) { + return -EINVAL; + } + + if ((NULL == s_priv_data.pointer) || + (s_priv_data.length < QCSAP_MAX_WSC_IE)) { + return -EINVAL; + } + + wps_genie = mem_alloc_copy_from_user_helper(s_priv_data.pointer, + s_priv_data.length); + + if (NULL == wps_genie) { + hddLog(LOG1, + "%s: failed to alloc memory and copy data from user buffer", + __func__); + return -EFAULT; + } + + fwps_genie = wps_genie; + + pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE)); + if (NULL == pSap_WPSIe) + { + hddLog(LOGE, "VOS unable to allocate memory"); + kfree(fwps_genie); + return -ENOMEM; + } + vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE)); + + hddLog(LOG1,"%s WPS IE type[0x%X] IE[0x%X], LEN[%d]", __func__, wps_genie[0], wps_genie[1], wps_genie[2]); + WPSIeType = wps_genie[0]; + if ( wps_genie[0] == eQC_WPS_BEACON_IE) + { + pSap_WPSIe->sapWPSIECode = eSAP_WPS_BEACON_IE; + wps_genie = wps_genie + 1; + switch ( wps_genie[0] ) + { + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { + ret = -EINVAL; + goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { + hddLog (LOG1, "%s Set WPS BEACON IE(len %d)",__func__, wps_genie[1]+2); + pos = &wps_genie[6]; + while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) + { + switch((u_int16_t)(*pos<<8) | *(pos+1)) + { + case HDD_WPS_ELEM_VERSION: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version = *pos; + hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_VER_PRESENT; + pos += 1; + break; + + case HDD_WPS_ELEM_WPS_STATE: + pos +=4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState = *pos; + hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_STATE_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_APSETUPLOCK: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked = *pos; + hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_APSETUPLOCK_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_SELECTEDREGISTRA: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra = *pos; + hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRA_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID = (*pos<<8) | *(pos+1); + hddLog(LOG1, "Password ID: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_DEVICEPASSWORDID_PRESENT; + pos += 2; + break; + case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); + hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT; + pos += 2; + break; + + case HDD_WPS_ELEM_UUID_E: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) + { + ret = -EINVAL; + goto exit; + } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; + pos += length; + break; + case HDD_WPS_ELEM_RF_BANDS: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand = *pos; + hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_RF_BANDS_PRESENT; + pos += 1; + break; + + default: + hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); + ret = -EINVAL; + goto exit; + } + } + } + else { + hddLog (LOGE, "%s WPS IE Mismatch %X", + __func__, wps_genie[0]); + } + break; + + default: + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); + ret = -EINVAL; + goto exit; + } + } + else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) + { + pSap_WPSIe->sapWPSIECode = eSAP_WPS_PROBE_RSP_IE; + wps_genie = wps_genie + 1; + switch ( wps_genie[0] ) + { + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { + ret = -EINVAL; + goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { + hddLog (LOG1, "%s Set WPS PROBE RSP IE(len %d)",__func__, wps_genie[1]+2); + pos = &wps_genie[6]; + while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) + { + switch((u_int16_t)(*pos<<8) | *(pos+1)) + { + case HDD_WPS_ELEM_VERSION: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version = *pos; + hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_VER_PRESENT; + pos += 1; + break; + + case HDD_WPS_ELEM_WPS_STATE: + pos +=4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState = *pos; + hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_STATE_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_APSETUPLOCK: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked = *pos; + hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_APSETUPLOCK_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_SELECTEDREGISTRA: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra = *pos; + hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRA_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID = (*pos<<8) | *(pos+1); + hddLog(LOG1, "Password ID: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICEPASSWORDID_PRESENT; + pos += 2; + break; + case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); + hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT; + pos += 2; + break; + case HDD_WPS_ELEM_RSP_TYPE: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType = *pos; + hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RESPONSETYPE_PRESENT; + pos += 1; + break; + case HDD_WPS_ELEM_UUID_E: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) + { + ret = -EINVAL; + goto exit; + } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; + pos += length; + break; + + case HDD_WPS_ELEM_MANUFACTURER: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) + { + ret = -EINVAL; + goto exit; + } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; + pos += length; + break; + + case HDD_WPS_ELEM_MODEL_NAME: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) + { + ret = -EINVAL; + goto exit; + } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; + pos += length; + break; + case HDD_WPS_ELEM_MODEL_NUM: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) + { + ret = -EINVAL; + goto exit; + } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; + pos += length; + break; + case HDD_WPS_ELEM_SERIAL_NUM: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) + { + ret = -EINVAL; + goto exit; + } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; + pos += length; + break; + case HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory = (*pos<<8 | *(pos+1)); + hddLog(LOG1, "primary dev category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory); + pos += 2; + + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceOUI, pos, HDD_WPS_DEVICE_OUI_LEN); + hddLog(LOG1, "primary dev oui: %02x, %02x, %02x, %02x", pos[0], pos[1], pos[2], pos[3]); + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory = (*pos<<8 | *(pos+1)); + hddLog(LOG1, "primary dev sub category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory); + pos += 2; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT; + break; + case HDD_WPS_ELEM_DEVICE_NAME: + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; + if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) + { + ret = -EINVAL; + goto exit; + } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); + pos += length; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICENAME_PRESENT; + break; + case HDD_WPS_ELEM_CONFIG_METHODS: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ConfigMethod = (*pos<<8) | *(pos+1); + hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); + pos += 2; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_CONFIGMETHODS_PRESENT; + break; + + case HDD_WPS_ELEM_RF_BANDS: + pos += 4; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand = *pos; + hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand); + pos += 1; + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RF_BANDS_PRESENT; + break; + } // switch + } + } + else + { + hddLog (LOGE, "%s WPS IE Mismatch %X",__func__, wps_genie[0]); + } + + } // switch + } + +#ifdef WLAN_FEATURE_MBSSID + halStatus = WLANSAP_Set_WpsIe(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), pSap_WPSIe); +#else + halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); +#endif + if (halStatus != eHAL_STATUS_SUCCESS) + ret = -EINVAL; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) + { + //hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + //v_CONTEXT_t pVosContext = pHostapdAdapter->pvosContext; +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_Update_WpsIe ( WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter) ); +#else + WLANSAP_Update_WpsIe ( pVosContext ); +#endif + } +exit: + vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); + EXIT(); + return ret; +} + +static int iw_softap_setwpsie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_setwpsie(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_softap_stopbss(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) + { + hdd_hostapd_state_t *pHostapdState = + WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + vos_event_reset(&pHostapdState->stop_bss_event); +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_StopBss(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext); +#endif + if (VOS_IS_STATUS_SUCCESS(status)) + { + status = vos_wait_single_event(&pHostapdState->stop_bss_event, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("%s: ERROR: HDD vos wait for single_event failed!!"), + __func__); + VOS_ASSERT(0); + } + } + clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + wlan_hdd_decr_active_session(pHddCtx, pHostapdAdapter->device_mode); + } + EXIT(); + return (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY; +} + +static int iw_softap_stopbss(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_stopbss(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_softap_version(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pHostapdAdapter = netdev_priv(dev); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + hdd_wlan_get_version(pHostapdAdapter, wrqu, extra); + EXIT(); + + return ret; +} + +static int iw_softap_version(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_version(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static VOS_STATUS +hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int buf_len) +{ + v_U8_t i; + v_U8_t maxSta = 0; + int len = 0; + const char sta_info_header[] = "staId staAddress"; + hdd_context_t *pHddCtx; + int ret; + + ENTER(); + + if (NULL == pAdapter) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Adapter is NULL", __func__); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + len = scnprintf(pBuf, buf_len, sta_info_header); + pBuf += len; + buf_len -= len; + + maxSta = pHddCtx->cfg_ini->maxNumberOfPeers; + + for (i = 0; i <= maxSta; i++) + { + if(pAdapter->aStaInfo[i].isUsed) + { + len = scnprintf(pBuf, buf_len, "%5d .%02x:%02x:%02x:%02x:%02x:%02x", + pAdapter->aStaInfo[i].ucSTAId, + pAdapter->aStaInfo[i].macAddrSTA.bytes[0], + pAdapter->aStaInfo[i].macAddrSTA.bytes[1], + pAdapter->aStaInfo[i].macAddrSTA.bytes[2], + pAdapter->aStaInfo[i].macAddrSTA.bytes[3], + pAdapter->aStaInfo[i].macAddrSTA.bytes[4], + pAdapter->aStaInfo[i].macAddrSTA.bytes[5]); + pBuf += len; + buf_len -= len; + } + if(WE_GET_STA_INFO_SIZE > buf_len) + { + break; + } + } + EXIT(); + return VOS_STATUS_SUCCESS; +} + +static int __iw_softap_get_sta_info(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + VOS_STATUS status; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + status = hdd_softap_get_sta_info(pHostapdAdapter, extra, WE_SAP_MAX_STA_INFO); + if ( !VOS_IS_STATUS_SUCCESS( status ) ) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!",__func__); + return -EINVAL; + } + wrqu->data.length = strlen(extra); + EXIT(); + return 0; +} + +static int iw_softap_get_sta_info(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_sta_info(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_ap_genie() - set ap wpa/rsn ie + * + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int __iw_set_ap_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext; +#endif + eHalStatus halStatus= eHAL_STATUS_SUCCESS; + u_int8_t *genie = (u_int8_t *)extra; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + +#ifndef WLAN_FEATURE_MBSSID + pVosContext = hdd_ctx->pvosContext; + if (NULL == pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: VOS Context is NULL", __func__); + return -EINVAL; + } +#endif + + if(!wrqu->data.length) + { + EXIT(); + return 0; + } + + switch (genie[0]) + { + case DOT11F_EID_WPA: + case DOT11F_EID_RSN: + if((WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy == 0) + { + hdd_softap_Deregister_BC_STA(pHostapdAdapter); + hdd_softap_Register_BC_STA(pHostapdAdapter, 1); + } + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = 1; +#ifdef WLAN_FEATURE_MBSSID + halStatus = WLANSAP_Set_WPARSNIes(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), genie, wrqu->data.length); +#else + halStatus = WLANSAP_Set_WPARSNIes(pVosContext, genie, wrqu->data.length); +#endif + break; + + default: + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, genie[0]); + halStatus = 0; + } + + EXIT(); + return halStatus; +} + +/** + * iw_set_ap_genie() - Wrapper function to protect __iw_set_ap_genie + * from the SSR. + * + * @dev - Pointer to the net device. + * @info - Pointer to the iw_request_info. + * @wrqu - Pointer to the iwreq_data. + * @extra - Pointer to the data. + * + * Return: 0 for success, non zero for failure. + */ +static int +iw_set_ap_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_ap_genie(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + + +VOS_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, + tSirMacAddr macAddress) +{ + eHalStatus hstatus; + unsigned long rc; + struct linkspeedContext context; + tSirLinkSpeedInfo *linkspeed_req; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); + return VOS_STATUS_E_FAULT; + } + linkspeed_req = (tSirLinkSpeedInfo *)vos_mem_malloc(sizeof(*linkspeed_req)); + if (NULL == linkspeed_req) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s Request Buffer Alloc Fail", __func__); + return VOS_STATUS_E_INVAL; + } + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = LINK_CONTEXT_MAGIC; + + vos_mem_copy(linkspeed_req->peer_macaddr, macAddress, sizeof(tSirMacAddr) ); + hstatus = sme_GetLinkSpeed( WLAN_HDD_GET_HAL_CTX(pAdapter), + linkspeed_req, + &context, + hdd_GetLink_SpeedCB); + if (eHAL_STATUS_SUCCESS != hstatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics for link speed", + __func__); + vos_mem_free(linkspeed_req); + } + else + { + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME timed out while retrieving link speed", + __func__); + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + return VOS_STATUS_SUCCESS; +} + + +static int +__iw_get_softap_linkspeed(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx; + char *pLinkSpeed = (char*)extra; + char *pmacAddress; + v_U32_t link_speed = 0; + int len = sizeof(v_U32_t)+1; + tSirMacAddr macAddress; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + int rc, valid, i; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + valid = wlan_hdd_validate_context(pHddCtx); + if (0 != valid) + return valid; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s wrqu->data.length= %d\n", __func__, wrqu->data.length); + + if (wrqu->data.length >= MAC_ADDRESS_STR_LEN - 1) + { + pmacAddress = kmalloc(MAC_ADDRESS_STR_LEN, GFP_KERNEL); + if (NULL == pmacAddress) { + hddLog(LOG1, "unable to allocate memory"); + return -ENOMEM; + } + if (copy_from_user((void *)pmacAddress, + wrqu->data.pointer, MAC_ADDRESS_STR_LEN)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + kfree(pmacAddress); + return -EFAULT; + } + pmacAddress[MAC_ADDRESS_STR_LEN] = '\0'; + + status = hdd_string_to_hex (pmacAddress, MAC_ADDRESS_STR_LEN, macAddress ); + kfree(pmacAddress); + + if (!VOS_IS_STATUS_SUCCESS(status )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("String to Hex conversion Failed")); + } + } + /* If no mac address is passed and/or its length is less than 17, + * link speed for first connected client will be returned. + */ + if (wrqu->data.length < 17 || !VOS_IS_STATUS_SUCCESS(status )) { + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if (pHostapdAdapter->aStaInfo[i].isUsed && + (!vos_is_macaddr_broadcast(&pHostapdAdapter->aStaInfo[i].macAddrSTA))) { + vos_copy_macaddr((v_MACADDR_t *)macAddress, + &pHostapdAdapter->aStaInfo[i].macAddrSTA); + status = VOS_STATUS_SUCCESS; + break; + } + } + } + if (!VOS_IS_STATUS_SUCCESS(status )) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid peer macaddress")); + return -EINVAL; + } + status = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, + macAddress); + if (!VOS_IS_STATUS_SUCCESS(status )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME linkspeed")); + return -EINVAL; + } + + link_speed = pHostapdAdapter->ls_stats.estLinkSpeed; + + /* linkspeed in units of 500 kbps */ + link_speed = link_speed / 500; + wrqu->data.length = len; + rc = snprintf(pLinkSpeed, len, "%u", link_speed); + if ((rc < 0) || (rc >= len)) + { + // encoding or length error? + hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed")); + return -EIO; + } + EXIT(); + return 0; +} + +static int +iw_get_softap_linkspeed(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_softap_linkspeed(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_get_rssi_cb() - get station's rssi callback + * @sta_rssi: pointer of rssi information + * @context: get rssi callback context + * + * This function will fill rssi information to hostapd + * adapter + * + */ +void hdd_get_rssi_cb(struct sir_rssi_resp *sta_rssi, void *context) +{ + struct statsContext *get_rssi_context; + struct sir_rssi_info *rssi_info; + uint8_t peer_num; + int i; + int buf = 0; + int length = 0; + char *rssi_info_output; + union iwreq_data *wrqu; + + if ((NULL == sta_rssi) || (NULL == context)) { + + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, sta_rssi [%p] context [%p]", + __func__, sta_rssi, context); + return; + } + + spin_lock(&hdd_context_lock); + /* + * there is a race condition that exists between this callback + * function and the caller since the caller could time out either + * before or while this code is executing. we use a spinlock to + * serialize these actions + */ + get_rssi_context = context; + if (RSSI_CONTEXT_MAGIC != + get_rssi_context->magic) { + + /* + * the caller presumably timed out so there is nothing + * we can do + */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, magic [%08x]", + __func__, + get_rssi_context->magic); + return; + } + + rssi_info_output = get_rssi_context->extra; + wrqu = get_rssi_context->wrqu; + peer_num = sta_rssi->count; + rssi_info = sta_rssi->info; + get_rssi_context->magic = 0; + + hddLog(LOG1, "%s : %d peers", __func__, peer_num); + + + /* + * The iwpriv tool default print is before mac addr and rssi. + * Add '\n' before first rssi item to align the frist rssi item + * with others + * + * wlan getRSSI: + * [macaddr1] [rssi1] + * [macaddr2] [rssi2] + * [macaddr3] [rssi3] + */ + length = scnprintf((rssi_info_output), WE_MAX_STR_LEN, "\n"); + for (i = 0; i < peer_num; i++) { + buf = scnprintf + ( + (rssi_info_output + length), WE_MAX_STR_LEN - length, + "[%pM] [%d]\n", + rssi_info[i].peer_macaddr, + rssi_info[i].rssi + ); + length += buf; + } + wrqu->data.length = length + 1; + + /* notify the caller */ + complete(&get_rssi_context->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/** + * wlan_hdd_get_peer_rssi() - get station's rssi + * @adapter: hostapd interface + * @macaddress: iwpriv request information + * @wrqu: iwpriv command parameter + * @extra + * + * This function will call sme_get_rssi to get rssi + * + * Return: 0 on success, otherwise error value + */ +static int wlan_hdd_get_peer_rssi(hdd_adapter_t *adapter, + v_MACADDR_t macaddress, + char *extra, + union iwreq_data *wrqu) +{ + eHalStatus hstatus; + int ret; + struct statsContext context; + struct sir_rssi_req rssi_req; + + if (NULL == adapter) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", + __func__); + return -EFAULT; + } + + init_completion(&context.completion); + context.magic = RSSI_CONTEXT_MAGIC; + context.extra = extra; + context.wrqu = wrqu; + + vos_mem_copy(&(rssi_req.peer_macaddr), &macaddress, + VOS_MAC_ADDR_SIZE); + rssi_req.sessionId = adapter->sessionId; + hstatus = sme_get_rssi(WLAN_HDD_GET_HAL_CTX(adapter), + rssi_req, + &context, + hdd_get_rssi_cb); + if (eHAL_STATUS_SUCCESS != hstatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics for rssi", + __func__); + ret = -EFAULT; + } else { + if (!wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME timed out while retrieving rssi", + __func__); + ret = -EFAULT; + } else + ret = 0; + } + /* + * either we never sent a request, we sent a request and received a + * response or we sent a request and timed out. if we never sent a + * request or if we sent a request and got a response, we want to + * clear the magic out of paranoia. if we timed out there is a + * race condition such that the callback function could be + * executing at the same time we are. of primary concern is if the + * callback function had already verified the "magic" but had not + * yet set the completion variable when a timeout occurred. we + * serialize these activities by invalidating the magic while + * holding a shared spinlock which will cause us to block if the + * callback is currently executing + */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + return ret; +} + +/** + * __iw_get_peer_rssi() - get station's rssi + * @dev: net device + * @info: iwpriv request information + * @wrqu: iwpriv command parameter + * @extra + * + * This function will call wlan_hdd_get_peer_rssi + * to get rssi + * + * Return: 0 on success, otherwise error value + */ +static int +__iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter = (netdev_priv(dev)); + hdd_context_t *hddctx; + char macaddrarray[18]; + v_MACADDR_t macaddress = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + int ret; + + ENTER(); + + hddctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hddctx); + if (0 != ret) + return ret; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s wrqu->data.length= %d", + __func__, wrqu->data.length); + + if (wrqu->data.length >= MAC_ADDRESS_STR_LEN - 1) { + + if (copy_from_user(macaddrarray, + wrqu->data.pointer, MAC_ADDRESS_STR_LEN - 1)) { + + hddLog(LOG1, "%s: failed to copy data to user buffer", + __func__); + return -EFAULT; + } + + macaddrarray[MAC_ADDRESS_STR_LEN - 1] = '\0'; + hddLog(LOG1, "%s, %s", + __func__, macaddrarray); + + status = hdd_string_to_hex(macaddrarray, + MAC_ADDRESS_STR_LEN, macaddress.bytes ); + + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("String to Hex conversion Failed")); + } + } + + return wlan_hdd_get_peer_rssi(adapter, macaddress, extra, wrqu); +} + +/** + * iw_get_peer_rssi() - get station's rssi + * @dev: net device + * @info: iwpriv request information + * @wrqu: iwpriv command parameter + * @extra + * + * This function will call __iw_get_peer_rssi + * + * Return: 0 on success, otherwise error value + */ +static int +iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_peer_rssi(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static const iw_handler hostapd_handler[] = +{ + (iw_handler) NULL, /* SIOCSIWCOMMIT */ + (iw_handler) NULL, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) NULL, /* SIOCSIWFREQ */ + (iw_handler) iw_get_ap_freq, /* SIOCGIWFREQ */ + (iw_handler) NULL, /* SIOCSIWMODE */ + (iw_handler) iw_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) NULL, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) NULL, /* SIOCSIWAP */ + (iw_handler) NULL, /* SIOCGIWAP */ + (iw_handler) iw_set_ap_mlme, /* SIOCSIWMLME */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ + (iw_handler) NULL, /* SIOCSIWSCAN */ + (iw_handler) NULL, /* SIOCGIWSCAN */ + (iw_handler) NULL, /* SIOCSIWESSID */ + (iw_handler) NULL, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) NULL, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWRATE */ + (iw_handler) NULL, /* SIOCGIWRATE */ + (iw_handler) NULL, /* SIOCSIWRTS */ + (iw_handler) iw_get_ap_rts_threshold, /* SIOCGIWRTS */ + (iw_handler) NULL, /* SIOCSIWFRAG */ + (iw_handler) iw_get_ap_frag_threshold, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + (iw_handler) NULL, /* SIOCSIWENCODE */ + (iw_handler) NULL, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) iw_set_ap_genie, /* SIOCSIWGENIE */ + (iw_handler) NULL, /* SIOCGIWGENIE */ + (iw_handler) iw_set_auth_hostap, /* SIOCSIWAUTH */ + (iw_handler) NULL, /* SIOCGIWAUTH */ + (iw_handler) iw_set_ap_encodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) NULL, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL, /* SIOCSIWPMKSA */ +}; + +/* + * Note that the following ioctls were defined with semantics which + * cannot be handled by the "iwpriv" userspace application and hence + * they are not included in the hostapd_private_args array + * QCSAP_IOCTL_ASSOC_STA_MACADDR + */ + +static const struct iw_priv_args hostapd_private_args[] = { + { QCSAP_IOCTL_SETPARAM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam" }, + { QCSAP_IOCTL_SETPARAM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, + { QCSAP_PARAM_MAX_ASSOC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMaxAssoc" }, + { QCSAP_PARAM_HIDE_SSID, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hideSSID" }, + { QCSAP_PARAM_SET_MC_RATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMcRate" }, + { QCSAP_PARAM_SET_TXRX_FW_STATS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txrx_fw_stats" }, + { QCSAP_PARAM_SET_MCC_CHANNEL_LATENCY, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMccLatency" }, + { QCSAP_PARAM_SET_MCC_CHANNEL_QUOTA, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMccQuota" }, + { QCSAP_PARAM_AUTO_CHANNEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setAutoChannel" }, + { QCSAP_PARAM_SET_CHANNEL_CHANGE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setChanChange" }, + + /* Sub-cmds DBGLOG specific commands */ + { QCSAP_DBGLOG_LOG_LEVEL , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_loglevel" }, + + { QCSAP_DBGLOG_VAP_ENABLE , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_vapon" }, + + { QCSAP_DBGLOG_VAP_DISABLE , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_vapoff" }, + + { QCSAP_DBGLOG_MODULE_ENABLE , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_modon" }, + + { QCSAP_DBGLOG_MODULE_DISABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_modoff" }, + + { QCSAP_DBGLOG_MOD_LOG_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_mod_loglevel" }, + + { QCSAP_DBGLOG_TYPE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_type" }, + { QCSAP_DBGLOG_REPORT_ENABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_report" }, + { QCASAP_TXRX_FWSTATS_RESET, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "txrx_fw_st_rst" }, + { QCSAP_PARAM_RTSCTS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "enablertscts" }, + + { QCASAP_SET_11N_RATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set11NRates" }, + + { QCASAP_SET_VHT_RATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set11ACRates" }, + + { QCASAP_SHORT_GI, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "enable_short_gi" }, + + { QCSAP_SET_AMPDU, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "ampdu" }, + + { QCSAP_SET_AMSDU, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "amsdu" }, + + { QCSAP_GTX_HT_MCS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxHTMcs" }, + + { QCSAP_GTX_VHT_MCS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxVHTMcs" }, + + { QCSAP_GTX_USRCFG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxUsrCfg" }, + + { QCSAP_GTX_THRE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxThre" }, + + { QCSAP_GTX_MARGIN, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxMargin" }, + + { QCSAP_GTX_STEP, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxStep" }, + + { QCSAP_GTX_MINTPC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxMinTpc" }, + + { QCSAP_GTX_BWMASK, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxBWMask" }, + + { QCSAP_PARAM_CLR_ACL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setClearAcl" }, + + { QCSAP_PARAM_ACL_MODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setAclMode" }, + +#ifdef QCA_PKT_PROTO_TRACE + { QCASAP_SET_DEBUG_LOG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setDbgLvl" }, +#endif /* QCA_PKT_PROTO_TRACE */ + + { QCASAP_SET_TM_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setTmLevel" }, + + { QCASAP_SET_DFS_IGNORE_CAC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setDfsIgnoreCAC" }, + + { QCASAP_SET_DFS_NOL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setdfsnol" }, + + { QCASAP_SET_DFS_TARGET_CHNL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setNextChnl" }, + + { QCASAP_SET_RADAR_CMD, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setRadar" }, +#ifdef IPA_UC_OFFLOAD + { QCSAP_IPA_UC_STAT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "ipaucstat" }, +#endif /* IPA_UC_OFFLOAD */ + + { QCASAP_TX_CHAINMASK_CMD, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set_txchainmask" }, + + { QCASAP_RX_CHAINMASK_CMD, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set_rxchainmask" }, + + { QCASAP_NSS_CMD, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set_nss" }, + + { QCASAP_SET_PHYMODE, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "setphymode" }, + + { QCASAP_DUMP_STATS, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "dumpStats" }, + + { QCASAP_CLEAR_STATS, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "clearStats" }, + { QCASAP_PARAM_LDPC, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "set_ldpc" }, + { QCASAP_PARAM_TX_STBC, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "set_tx_stbc" }, + { QCASAP_PARAM_RX_STBC, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "set_rx_stbc" }, + + { QCSAP_IOCTL_GETPARAM, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" }, + { QCSAP_IOCTL_GETPARAM, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" }, + { QCSAP_PARAM_MAX_ASSOC, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getMaxAssoc" }, + { QCSAP_PARAM_GET_WLAN_DBG, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwlandbg" }, + { QCSAP_PARAM_AUTO_CHANNEL, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getAutoChannel" }, + { QCSAP_GTX_BWMASK, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxBWMask" }, + { QCSAP_GTX_MINTPC, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxMinTpc" }, + { QCSAP_GTX_STEP, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxStep" }, + { QCSAP_GTX_MARGIN, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxMargin" }, + { QCSAP_GTX_THRE, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxThre" }, + { QCSAP_GTX_USRCFG, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxUsrCfg" }, + { QCSAP_GTX_VHT_MCS, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxVHTMcs" }, + { QCSAP_GTX_HT_MCS, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_gtxHTMcs" }, + { QCASAP_SHORT_GI, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_short_gi" }, + { QCSAP_PARAM_RTSCTS, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rtscts" }, + { QCASAP_GET_DFS_NOL, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdfsnol" }, + { QCSAP_GET_ACL, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_acl_list" }, + { QCASAP_PARAM_LDPC, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_ldpc" }, + { QCASAP_PARAM_TX_STBC, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_tx_stbc" }, + { QCASAP_PARAM_RX_STBC, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rx_stbc" }, +#ifdef WLAN_FEATURE_TSF + { QCSAP_CAP_TSF, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "cap_tsf" }, +#endif + { QCSAP_IOCTL_SET_NONE_GET_THREE, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, "" }, +#ifdef WLAN_FEATURE_TSF + { QCSAP_GET_TSF, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, "get_tsf" }, +#endif + { QCASAP_TX_CHAINMASK_CMD, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_txchainmask" }, + { QCASAP_RX_CHAINMASK_CMD, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rxchainmask" }, + { QCASAP_NSS_CMD, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_nss" }, + { QCASAP_GET_TEMP_CMD, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_temp" }, + { QCSAP_GET_FW_STATUS, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_fwstate" }, + + { QCSAP_IOCTL_GET_STAWPAIE, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "get_staWPAIE" }, + { QCSAP_IOCTL_SETWPAIE, + IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE | IW_PRIV_SIZE_FIXED, 0, "setwpaie" }, + { QCSAP_IOCTL_STOPBSS, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" }, + { QCSAP_IOCTL_VERSION, 0, + IW_PRIV_TYPE_CHAR | QCSAP_MAX_WSC_IE, "version" }, + { QCSAP_IOCTL_GET_STA_INFO, 0, + IW_PRIV_TYPE_CHAR | WE_SAP_MAX_STA_INFO, "get_sta_info" }, + { QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES, + IW_PRIV_TYPE_BYTE | sizeof(sQcSapreq_WPSPBCProbeReqIES_t) | IW_PRIV_SIZE_FIXED, 0, "getProbeReqIEs" }, + { QCSAP_IOCTL_GET_CHANNEL, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel" }, + { QCSAP_IOCTL_DISASSOC_STA, + 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" }, + /* handler for main ioctl */ + { QCSAP_PRIV_GET_CHAR_SET_NONE, 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN,"" }, + /* handler for sub-ioctl */ + { QCSAP_GET_STATS, 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats" }, + { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED, + IW_PRIV_TYPE_CHAR | 18, + IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, + { QCSAP_IOCTL_PRIV_GET_RSSI, + IW_PRIV_TYPE_CHAR | 18, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getRSSI" }, + { QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" }, + /* handlers for sub-ioctl */ + { WE_SET_WLAN_DBG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "setwlandbg" }, + + { WE_SET_SAP_CHANNELS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "setsapchannels" }, + + /* handlers for main ioctl */ + { QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "" }, + + /* handlers for sub-ioctl */ + { WE_LOG_DUMP_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "dump" }, + { WE_P2P_NOA_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "SetP2pPs" }, + /* handlers for sub ioctl */ + { + WE_MCC_CONFIG_CREDENTIAL, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setMccCrdnl" }, + + /* handlers for sub ioctl */ + { + WE_MCC_CONFIG_PARAMS, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setMccConfig" }, + + { + WE_UNIT_TEST_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setUnitTestCmd" }, + +#ifdef MEMORY_DEBUG + /* handlers for sub ioctl */ + { WE_MEM_TRACE_DUMP, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "memTraceLog" }, +#endif + + /* handlers for main ioctl */ + { QCSAP_IOCTL_MODIFY_ACL, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 8, + 0, + "modify_acl" }, + + /* handlers for main ioctl */ + { QCSAP_IOCTL_GET_CHANNEL_LIST, + 0, + IW_PRIV_TYPE_BYTE | sizeof(tChannelListInfo), + "getChannelList" }, + + /* handlers for main ioctl */ + { QCSAP_IOCTL_SET_TX_POWER, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "setTxPower" }, + + /* handlers for main ioctl */ + { QCSAP_IOCTL_SET_MAX_TX_POWER, + IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, + 0, + "setTxMaxPower" }, + + { QCSAP_IOCTL_DATAPATH_SNAP_SHOT, + IW_PRIV_TYPE_NONE | IW_PRIV_TYPE_NONE, + 0, + "dataSnapshot" }, + + /* Set HDD CFG Ini param */ + { QCSAP_IOCTL_SET_INI_CFG, + IW_PRIV_TYPE_CHAR | QCSAP_IOCTL_MAX_STR_LEN, + 0, + "setConfig" }, + + /* Get HDD CFG Ini param */ + { QCSAP_IOCTL_GET_INI_CFG, + 0, + IW_PRIV_TYPE_CHAR | QCSAP_IOCTL_MAX_STR_LEN, + "getConfig" }, + + /* handlers for main ioctl */ + { QCSAP_IOCTL_SET_TWO_INT_GET_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, + "" }, + /* handlers for sub-ioctl */ +#ifdef DEBUG + { QCSAP_IOCTL_SET_FW_CRASH_INJECT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, + "crash_inject" }, +#endif + + /* handlers for main ioctl */ + { QCSAP_IOCTL_WOWL_CONFIG_PTRN, + 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" }, + + { QCASAP_SET_RADAR_DBG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setRadarDbg" }, +}; + +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_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] = iw_softap_get_three, + [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE + [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie, + [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss + [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version + [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = iw_get_WPSPBCProbeReqIEs, + [QCSAP_IOCTL_GET_CHANNEL - SIOCIWFIRSTPRIV] = iw_softap_getchannel, + [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_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_get_char_setnone, + [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_force_acs_ch_range, + [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV] = iw_softap_modify_acl, + [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = iw_softap_get_channel_list, + [QCSAP_IOCTL_GET_STA_INFO - SIOCIWFIRSTPRIV] = iw_softap_get_sta_info, + [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_softap_linkspeed, + [QCSAP_IOCTL_PRIV_GET_RSSI - SIOCIWFIRSTPRIV] = iw_get_peer_rssi, + [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_tx_power, + [QCSAP_IOCTL_SET_MAX_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_max_tx_power, + [QCSAP_IOCTL_DATAPATH_SNAP_SHOT - SIOCIWFIRSTPRIV] = iw_display_data_path_snapshot, + [QCSAP_IOCTL_SET_INI_CFG - SIOCIWFIRSTPRIV] = iw_softap_set_ini_cfg, + [QCSAP_IOCTL_GET_INI_CFG - SIOCIWFIRSTPRIV] = iw_softap_get_ini_cfg, + [QCSAP_IOCTL_SET_TWO_INT_GET_NONE - SIOCIWFIRSTPRIV] = + iw_softap_set_two_ints_getnone, + [QCSAP_IOCTL_WOWL_CONFIG_PTRN - SIOCIWFIRSTPRIV] = iw_softap_wowl_config_pattern, +}; +const struct iw_handler_def hostapd_handler_def = { + .num_standard = sizeof(hostapd_handler) / sizeof(hostapd_handler[0]), + .num_private = sizeof(hostapd_private) / sizeof(hostapd_private[0]), + .num_private_args = sizeof(hostapd_private_args) / sizeof(hostapd_private_args[0]), + .standard = (iw_handler *)hostapd_handler, + .private = (iw_handler *)hostapd_private, + .private_args = hostapd_private_args, + .get_wireless_stats = NULL, +}; + +struct net_device_ops net_ops_struct = { + .ndo_open = hdd_hostapd_open, + .ndo_stop = hdd_hostapd_stop, + .ndo_uninit = hdd_hostapd_uninit, + .ndo_start_xmit = hdd_softap_hard_start_xmit, + .ndo_tx_timeout = hdd_softap_tx_timeout, + .ndo_get_stats = hdd_softap_stats, + .ndo_set_mac_address = hdd_hostapd_set_mac_address, + .ndo_do_ioctl = hdd_hostapd_ioctl, + .ndo_change_mtu = hdd_hostapd_change_mtu, + .ndo_select_queue = hdd_hostapd_select_queue, + }; + +static int hdd_set_hostapd(hdd_adapter_t *pAdapter) +{ + return VOS_STATUS_SUCCESS; +} + +void hdd_set_ap_ops( struct net_device *pWlanHostapdDev ) +{ + pWlanHostapdDev->netdev_ops = &net_ops_struct; +} + +VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter ) +{ + hdd_hostapd_state_t * phostapdBuf; + struct net_device *dev = pAdapter->dev; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + VOS_STATUS status; +#ifdef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; + v_CONTEXT_t sapContext=NULL; +#endif + int ret; + + ENTER(); + + hdd_set_sap_auth_offload(pAdapter, TRUE); + + ret = hdd_set_client_block_info(pAdapter); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: set client block info failed %d", + __func__, ret); + } + +#ifdef WLAN_FEATURE_MBSSID + sapContext = WLANSAP_Open(pVosContext); + if (sapContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: WLANSAP_Open failed!!")); + return VOS_STATUS_E_FAULT; + } + + pAdapter->sessionCtx.ap.sapContext = sapContext; + + status = WLANSAP_Start(sapContext); + if ( ! VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: WLANSAP_Start failed!!")); + WLANSAP_Close(sapContext); + return status; + } +#endif + + // Allocate the Wireless Extensions state structure + phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter ); + + sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode); + + // Zero the memory. This zeros the profile structure. + memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t)); + + // Set up the pointer to the Wireless Extensions state structure + // NOP + status = hdd_set_hostapd(pAdapter); + if(!VOS_IS_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,("ERROR: hdd_set_hostapd failed!!")); +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_Close(sapContext); +#endif + return status; + } + + status = vos_event_init(&phostapdBuf->vosEvent); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!")); +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_Close(sapContext); +#endif + return status; + } + + status = vos_event_init(&phostapdBuf->stop_bss_event); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_ERROR, + "ERROR: Hostapd HDD stop bss event init failed!!"); +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_Close(sapContext); +#endif + return status; + } + + init_completion(&pAdapter->session_close_comp_var); + init_completion(&pAdapter->session_open_comp_var); + + sema_init(&(WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->semWpsPBCOverlapInd, 1); + + // Register as a wireless device + dev->wireless_handlers = (struct iw_handler_def *)& hostapd_handler_def; + + //Initialize the data path module + status = hdd_softap_init_tx_rx(pAdapter); + if ( !VOS_IS_STATUS_SUCCESS( status )) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_softap_init_tx_rx failed", __func__); + } + + status = hdd_wmm_adapter_init( pAdapter ); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "hdd_wmm_adapter_init() failed with status code %08d [x%08x]", + status, status ); + goto error_wmm_init; + } + + set_bit(WMM_INIT_DONE, &pAdapter->event_flags); + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + (int)pHddCtx->cfg_ini->enableSifsBurst, + PDEV_CMD); + + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_BURST_ENABLE set failed %d", + __func__, ret); + } + + wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), pAdapter ); + pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false; + vos_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list); + vos_mem_zero(&pAdapter->sessionCtx.ap.sapConfig.acs_cfg, + sizeof(struct sap_acs_cfg)); + return status; + +error_wmm_init: + hdd_softap_deinit_tx_rx( pAdapter ); +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_Close(sapContext); +#endif + EXIT(); + return status; +} + +hdd_adapter_t* hdd_wlan_create_ap_dev( hdd_context_t *pHddCtx, tSirMacAddr macAddr, tANI_U8 *iface_name ) +{ + struct net_device *pWlanHostapdDev = NULL; + hdd_adapter_t *pHostapdAdapter = NULL; + + hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: iface_name = %s", __func__, iface_name); + + pWlanHostapdDev = alloc_netdev_mq(sizeof(hdd_adapter_t), + iface_name, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) || defined(WITH_BACKPORTS) + NET_NAME_UNKNOWN, +#endif + ether_setup, + NUM_TX_QUEUES); + + if (pWlanHostapdDev != NULL) + { + pHostapdAdapter = netdev_priv(pWlanHostapdDev); + + //Init the net_device structure + ether_setup(pWlanHostapdDev); + + //Initialize the adapter context to zeros. + vos_mem_zero(pHostapdAdapter, sizeof( hdd_adapter_t )); + pHostapdAdapter->dev = pWlanHostapdDev; + pHostapdAdapter->pHddCtx = pHddCtx; + pHostapdAdapter->magic = WLAN_HDD_ADAPTER_MAGIC; + + hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: pWlanHostapdDev = %p, " + "pHostapdAdapter = %p, " + "concurrency_mode=0x%x", __func__, + pWlanHostapdDev, + pHostapdAdapter, + (int)vos_get_concurrency_mode()); + + //Init the net_device structure + strlcpy(pWlanHostapdDev->name, (const char *)iface_name, IFNAMSIZ); + + hdd_set_ap_ops( pHostapdAdapter->dev ); + + pWlanHostapdDev->watchdog_timeo = HDD_TX_TIMEOUT; + pWlanHostapdDev->mtu = HDD_DEFAULT_MTU; + pWlanHostapdDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN; + + vos_mem_copy(pWlanHostapdDev->dev_addr, (void *)macAddr,sizeof(tSirMacAddr)); + vos_mem_copy(pHostapdAdapter->macAddressCurrent.bytes, (void *)macAddr, sizeof(tSirMacAddr)); + + pHostapdAdapter->offloads_configured = FALSE; + pWlanHostapdDev->destructor = free_netdev; + pWlanHostapdDev->ieee80211_ptr = &pHostapdAdapter->wdev ; + pHostapdAdapter->wdev.wiphy = pHddCtx->wiphy; + pHostapdAdapter->wdev.netdev = pWlanHostapdDev; + init_completion(&pHostapdAdapter->tx_action_cnf_event); + init_completion(&pHostapdAdapter->cancel_rem_on_chan_var); + init_completion(&pHostapdAdapter->rem_on_chan_ready_event); + init_completion(&pHostapdAdapter->ula_complete); + init_completion(&pHostapdAdapter->offchannel_tx_event); + init_completion(&pHostapdAdapter->scan_info.scan_req_completion_event); + init_completion(&pHostapdAdapter->scan_info.abortscan_event_var); + vos_event_init(&pHostapdAdapter->scan_info.scan_finished_event); + pHostapdAdapter->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP; + /* + * kernel will consume ethernet header length buffer for hard_header, + * so just reserve it + */ + hdd_set_needed_headroom(pWlanHostapdDev, + pWlanHostapdDev->hard_header_len); + + SET_NETDEV_DEV(pWlanHostapdDev, pHddCtx->parent_dev); + } + return pHostapdAdapter; +} + +VOS_STATUS hdd_register_hostapd( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held ) +{ + struct net_device *dev = pAdapter->dev; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + ENTER(); + + if( rtnl_lock_held ) + { + if (strnchr(dev->name, strlen(dev->name), '%')) { + if( dev_alloc_name(dev, dev->name) < 0 ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s:Failed:dev_alloc_name", __func__); + return VOS_STATUS_E_FAILURE; + } + } + if (register_netdevice(dev)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s:Failed:register_netdevice", __func__); + return VOS_STATUS_E_FAILURE; + } + } + else + { + if (register_netdev(dev)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed:register_netdev", __func__); + return VOS_STATUS_E_FAILURE; + } + } + set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags); + + EXIT(); + return status; +} + +VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, bool rtnl_held) +{ +#ifdef WLAN_FEATURE_MBSSID + VOS_STATUS status; + v_PVOID_t sapContext=WLAN_HDD_GET_SAP_CTX_PTR(pAdapter); +#endif + + ENTER(); + + hdd_softap_deinit_tx_rx(pAdapter); + + /* if we are being called during driver unload, then the dev has already + been invalidated. if we are being called at other times, then we can + detach the wireless device handlers */ + if (pAdapter->dev) + { + if (rtnl_held) + pAdapter->dev->wireless_handlers = NULL; + else { + rtnl_lock(); + pAdapter->dev->wireless_handlers = NULL; + rtnl_unlock(); + } + } + +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_Stop(sapContext); + if ( ! VOS_IS_STATUS_SUCCESS( status ) ) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed:WLANSAP_Stop", __func__); + } + + status = WLANSAP_Close(sapContext); + if ( ! VOS_IS_STATUS_SUCCESS( status ) ) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed:WLANSAP_close", __func__); + } + pAdapter->sessionCtx.ap.sapContext = NULL; +#endif + + EXIT(); + return 0; +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c new file mode 100644 index 000000000000..37e5a0ebdee8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c @@ -0,0 +1,4693 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +/*======================================================================== + +\file wlan_hdd_ipa.c + +\brief WLAN HDD and ipa interface implementation + +========================================================================*/ + +/*-------------------------------------------------------------------------- +Include Files +------------------------------------------------------------------------*/ +#ifdef IPA_OFFLOAD +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vos_sched.h" +#include "tl_shim.h" +#include "wlan_qct_tl.h" + +#ifdef IPA_UC_OFFLOAD +#include "wma.h" +#include "wma_api.h" +#endif /* IPA_UC_OFFLOAD */ + +#define HDD_IPA_DESC_BUFFER_RATIO 4 +#define HDD_IPA_IPV4_NAME_EXT "_ipv4" +#define HDD_IPA_IPV6_NAME_EXT "_ipv6" + +#define HDD_IPA_RX_INACTIVITY_MSEC_DELAY 1000 +#ifdef IPA_UC_OFFLOAD +#define HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET 12 +#define HDD_IPA_UC_WLAN_8023_HDR_SIZE 14 +/* WDI TX and RX PIPE */ +#define HDD_IPA_UC_NUM_WDI_PIPE 2 +#define HDD_IPA_UC_MAX_PENDING_EVENT 33 + +#define HDD_IPA_UC_DEBUG_DUMMY_MEM_SIZE 32000 +#define HDD_IPA_UC_RT_DEBUG_PERIOD 300 +#define HDD_IPA_UC_RT_DEBUG_BUF_COUNT 30 +#define HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL 10000 + +#define MAX_PENDING_EVENT_COUNT 20 +#endif /* IPA_UC_OFFLOAD */ + +#ifdef IPA_UC_OFFLOAD +typedef enum { + HDD_IPA_UC_OPCODE_TX_SUSPEND = 0, + HDD_IPA_UC_OPCODE_TX_RESUME = 1, + HDD_IPA_UC_OPCODE_RX_SUSPEND = 2, + HDD_IPA_UC_OPCODE_RX_RESUME = 3, + HDD_IPA_UC_OPCODE_STATS = 4, + HDD_IPA_UC_OPCODE_UC_READY = 5, + /* keep this last */ + HDD_IPA_UC_OPCODE_MAX +} hdd_ipa_uc_op_code; + +typedef enum { + HDD_IPA_UC_STAT_REASON_NONE, + HDD_IPA_UC_STAT_REASON_DEBUG, + HDD_IPA_UC_STAT_REASON_BW_CAL +} hdd_ipa_uc_stat_reason; +#endif /* IPA_UC_OFFLOAD */ + +struct llc_snap_hdr { + uint8_t dsap; + uint8_t ssap; + uint8_t resv[4]; + __be16 eth_type; +} __packed; + +struct hdd_ipa_tx_hdr { + struct ethhdr eth; + struct llc_snap_hdr llc_snap; +} __packed; + +/* For Tx pipes, use 802.3 Header format */ +static struct hdd_ipa_tx_hdr ipa_tx_hdr = { + { + {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF}, + {0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0xFF}, + 0x00 /* length can be zero */ + }, + { + /* LLC SNAP header 8 bytes */ + 0xaa, 0xaa, + {0x03, 0x00, 0x00, 0x00}, + 0x0008 /* type value(2 bytes) ,filled by wlan */ + /* 0x0800 - IPV4, 0x86dd - IPV6 */ + } +}; + +#ifdef IPA_UC_OFFLOAD +struct frag_header { + uint32 + length:16, /* length field is LSB of the FRAG DESC */ + reserved16:16; + uint32 reserved32; +} __packed; + +struct ipa_header { + uint32 + vdev_id:8, /* vdev_id field is LSB of IPA DESC */ + reserved:24; +} __packed; + +struct hdd_ipa_uc_tx_hdr { + struct frag_header frag_hd; + struct ipa_header ipa_hd; + struct ethhdr eth; +} __packed; + +/* For Tx pipes, use Ethernet-II Header format */ +struct hdd_ipa_uc_tx_hdr ipa_uc_tx_hdr = { + { + 0x00000000, + 0x00000000 + }, + { + 0x00000000 + }, + { + {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc}, + {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff}, + 0x0008 + } +}; +#endif /* IPA_UC_OFFLOAD */ + +/* + +----------+----------+--------------+--------+ + | Reserved | QCMAP ID | interface id | STA ID | + +----------+----------+--------------+--------+ + */ +struct hdd_ipa_cld_hdr { + uint8_t reserved[2]; + uint8_t iface_id; + uint8_t sta_id; +} __packed; + +struct hdd_ipa_rx_hdr { + struct hdd_ipa_cld_hdr cld_hdr; + struct ethhdr eth; +} __packed; + +struct hdd_ipa_pm_tx_cb { + struct hdd_ipa_iface_context *iface_context; + struct ipa_rx_data *ipa_tx_desc; +}; + +#ifdef IPA_UC_OFFLOAD +struct hdd_ipa_uc_rx_hdr { + struct ethhdr eth; +} __packed; +#endif /* IPA_UC_OFFLOAD */ + +#define HDD_IPA_WLAN_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr) +#ifdef IPA_UC_OFFLOAD +#define HDD_IPA_UC_WLAN_CLD_HDR_LEN 0 +#endif /* IPA_UC_OFFLOAD */ + +#define HDD_IPA_WLAN_TX_HDR_LEN sizeof(ipa_tx_hdr) +#ifdef IPA_UC_OFFLOAD +#define HDD_IPA_UC_WLAN_TX_HDR_LEN sizeof(ipa_uc_tx_hdr) +#endif /* IPA_UC_OFFLOAD */ + +#define HDD_IPA_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_rx_hdr) +#ifdef IPA_UC_OFFLOAD +#define HDD_IPA_UC_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_uc_rx_hdr) +#endif /* IPA_UC_OFFLOAD */ + +#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0 + +#define HDD_IPA_GET_IFACE_ID(_data) \ + (((struct hdd_ipa_cld_hdr *) (_data))->iface_id) + + +#define HDD_IPA_LOG(LVL, fmt, args...) VOS_TRACE(VOS_MODULE_ID_HDD, LVL, \ + "%s:%d: "fmt, __func__, __LINE__, ## args) + +#define HDD_IPA_DBG_DUMP(_lvl, _prefix, _buf, _len) \ + do {\ + VOS_TRACE(VOS_MODULE_ID_HDD, _lvl, "%s:", _prefix); \ + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_HDD, _lvl, _buf, _len); \ + } while(0) + +enum hdd_ipa_rm_state { + HDD_IPA_RM_RELEASED, + HDD_IPA_RM_GRANT_PENDING, + HDD_IPA_RM_GRANTED, +}; + +#define HDD_IPA_MAX_IFACE 3 +#define HDD_IPA_MAX_SYSBAM_PIPE 4 +#define HDD_IPA_RX_PIPE HDD_IPA_MAX_IFACE + +static struct hdd_ipa_adapter_2_client { + enum ipa_client_type cons_client; + enum ipa_client_type prod_client; +} hdd_ipa_adapter_2_client[HDD_IPA_MAX_IFACE] = { +#ifdef IPA_UC_OFFLOAD + {IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN1_PROD}, + {IPA_CLIENT_WLAN3_CONS, IPA_CLIENT_WLAN1_PROD}, + {IPA_CLIENT_WLAN4_CONS, IPA_CLIENT_WLAN1_PROD}, +#else + {IPA_CLIENT_WLAN1_CONS, IPA_CLIENT_WLAN1_PROD}, + {IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN1_PROD}, + {IPA_CLIENT_WLAN3_CONS, IPA_CLIENT_WLAN1_PROD}, +#endif +}; + +struct hdd_ipa_sys_pipe { + uint32_t conn_hdl; + uint8_t conn_hdl_valid; + struct ipa_sys_connect_params ipa_sys_params; +}; + +struct hdd_ipa_iface_stats { + uint64_t num_tx; + uint64_t num_tx_drop; + uint64_t num_tx_err; + uint64_t num_tx_cac_drop; + uint64_t num_rx_prefilter; + uint64_t num_rx_ipa_excep; + uint64_t num_rx_recv; + uint64_t num_rx_recv_mul; + uint64_t num_rx_send_desc_err; + uint64_t max_rx_mul; +}; + +struct hdd_ipa_priv; + +struct hdd_ipa_iface_context { + struct hdd_ipa_priv *hdd_ipa; + hdd_adapter_t *adapter; + void *tl_context; + + enum ipa_client_type cons_client; + enum ipa_client_type prod_client; + + uint8_t iface_id; /* This iface ID */ + uint8_t sta_id; /* This iface station ID */ + adf_os_spinlock_t interface_lock; + uint32_t ifa_address; + struct hdd_ipa_iface_stats stats; +}; + + +struct hdd_ipa_stats { + uint32_t event[IPA_WLAN_EVENT_MAX]; + uint64_t num_send_msg; + uint64_t num_free_msg; + + uint64_t num_rm_grant; + uint64_t num_rm_release; + uint64_t num_rm_grant_imm; + uint64_t num_cons_perf_req; + uint64_t num_prod_perf_req; + + uint64_t num_rx_drop; + uint64_t num_rx_ipa_tx_dp; + uint64_t num_rx_ipa_splice; + uint64_t num_rx_ipa_loop; + uint64_t num_rx_ipa_tx_dp_err; + uint64_t num_rx_ipa_write_done; + uint64_t num_max_ipa_tx_mul; + uint64_t num_rx_ipa_hw_maxed_out; + uint64_t max_pend_q_cnt; + + uint64_t num_tx_comp_cnt; + uint64_t num_tx_queued; + uint64_t num_tx_dequeued; + uint64_t num_max_pm_queue; + + uint64_t num_freeq_empty; + uint64_t num_pri_freeq_empty; + uint64_t num_rx_excep; + uint64_t num_tx_bcmc; + uint64_t num_tx_bcmc_err; +}; + +#ifdef IPA_UC_OFFLOAD +struct ipa_uc_stas_map { + v_BOOL_t is_reserved; + uint8_t sta_id; +}; + +struct op_msg_type { + uint8_t msg_t; + uint8_t rsvd; + uint16_t op_code; + uint16_t len; + uint16_t rsvd_snd; +}; + +struct ipa_uc_fw_stats { + uint32_t tx_comp_ring_base; + uint32_t tx_comp_ring_size; + uint32_t tx_comp_ring_dbell_addr; + uint32_t tx_comp_ring_dbell_ind_val; + uint32_t tx_comp_ring_dbell_cached_val; + uint32_t tx_pkts_enqueued; + uint32_t tx_pkts_completed; + uint32_t tx_is_suspend; + uint32_t tx_reserved; + uint32_t rx_ind_ring_base; + uint32_t rx_ind_ring_size; + uint32_t rx_ind_ring_dbell_addr; + uint32_t rx_ind_ring_dbell_ind_val; + uint32_t rx_ind_ring_dbell_ind_cached_val; + uint32_t rx_ind_ring_rdidx_addr; + uint32_t rx_ind_ring_rd_idx_cached_val; + uint32_t rx_refill_idx; + uint32_t rx_num_pkts_indicated; + uint32_t rx_buf_refilled; + uint32_t rx_num_ind_drop_no_space; + uint32_t rx_num_ind_drop_no_buf; + uint32_t rx_is_suspend; + uint32_t rx_reserved; +}; + +struct ipa_uc_pending_event { + vos_list_node_t node; + hdd_adapter_t *adapter; + enum ipa_wlan_event type; + uint8_t sta_id; + uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; +}; + +static const char *op_string[HDD_IPA_UC_OPCODE_MAX] = { + "TX_SUSPEND", + "TX_RESUME", + "RX_SUSPEND", + "RX_RESUME", + "STATS", + "OPCODE_MAX" +}; + +struct uc_rm_work_struct { + struct work_struct work; + enum ipa_rm_event event; +}; + +struct uc_op_work_struct { + struct work_struct work; + struct op_msg_type *msg; +}; +static uint8_t vdev_to_iface[CSR_ROAM_SESSION_MAX]; + +struct uc_rt_debug_info { + v_TIME_t time; + uint64_t ipa_excp_count; + uint64_t rx_drop_count; + uint64_t net_sent_count; + uint64_t rx_discard_count; + uint64_t rx_mcbc_count; + uint64_t tx_mcbc_count; + uint64_t tx_fwd_count; + uint64_t rx_destructor_call; +}; +#endif /* IPA_UC_OFFLOAD */ + +struct hdd_ipa_priv { + struct hdd_ipa_sys_pipe sys_pipe[HDD_IPA_MAX_SYSBAM_PIPE]; + struct hdd_ipa_iface_context iface_context[HDD_IPA_MAX_IFACE]; + uint8_t num_iface; + enum hdd_ipa_rm_state rm_state; + /* + * IPA driver can send RM notifications with IRQ disabled so using adf + * APIs as it is taken care gracefully. Without this, kernel would throw + * an warning if spin_lock_bh is used while IRQ is disabled + */ + adf_os_spinlock_t rm_lock; + struct work_struct rm_work; +#ifdef IPA_UC_OFFLOAD + struct uc_rm_work_struct uc_rm_work; + struct uc_op_work_struct uc_op_work[HDD_IPA_UC_OPCODE_MAX]; +#endif + vos_wake_lock_t wake_lock; + struct delayed_work wake_lock_work; + bool wake_lock_released; + + enum ipa_client_type prod_client; + + atomic_t tx_ref_cnt; + adf_nbuf_queue_t pm_queue_head; + struct work_struct pm_work; + adf_os_spinlock_t pm_lock; + bool suspended; + + uint32_t pending_hw_desc_cnt; + uint32_t hw_desc_cnt; + spinlock_t q_lock; + uint32_t freeq_cnt; + struct list_head free_desc_head; + + uint32_t pend_q_cnt; + struct list_head pend_desc_head; + + hdd_context_t *hdd_ctx; + + struct dentry *debugfs_dir; + struct hdd_ipa_stats stats; + + struct notifier_block ipv4_notifier; + uint32_t curr_prod_bw; + uint32_t curr_cons_bw; + +#ifdef IPA_UC_OFFLOAD + uint8_t activated_fw_pipe; + uint8_t sap_num_connected_sta; +#ifdef IPA_UC_STA_OFFLOAD + uint8_t sta_connected; +#endif + uint32_t tx_pipe_handle; + uint32_t rx_pipe_handle; + v_BOOL_t resource_loading; + v_BOOL_t resource_unloading; + v_BOOL_t pending_cons_req; + struct ipa_uc_stas_map assoc_stas_map[WLAN_MAX_STA_COUNT]; + vos_list_t pending_event; + vos_lock_t event_lock; + uint32_t ipa_tx_packets_diff; + uint32_t ipa_rx_packets_diff; + uint32_t ipa_p_tx_packets; + uint32_t ipa_p_rx_packets; + uint64_t ipa_tx_forward; + uint64_t ipa_rx_discard; + uint64_t ipa_rx_net_send_count; + uint64_t ipa_rx_internel_drop_count; + uint64_t ipa_rx_destructor_count; + hdd_ipa_uc_stat_reason stat_req_reason; + struct ipa_wdi_in_params cons_pipe_in; + struct ipa_wdi_in_params prod_pipe_in; + v_BOOL_t uc_loaded; + v_BOOL_t wdi_enabled; + bool ipa_pipes_down; + vos_timer_t rt_debug_timer; + struct uc_rt_debug_info rt_bug_buffer[HDD_IPA_UC_RT_DEBUG_BUF_COUNT]; + unsigned int rt_buf_fill_index; + vos_timer_t rt_debug_fill_timer; + vos_lock_t rt_debug_lock; + vos_lock_t ipa_lock; +#endif /* IPA_UC_OFFLOAD */ +}; + +static struct hdd_ipa_priv *ghdd_ipa; + +#define HDD_IPA_ENABLE_MASK BIT(0) +#define HDD_IPA_PRE_FILTER_ENABLE_MASK BIT(1) +#define HDD_IPA_IPV6_ENABLE_MASK BIT(2) +#define HDD_IPA_RM_ENABLE_MASK BIT(3) +#define HDD_IPA_CLK_SCALING_ENABLE_MASK BIT(4) +#define HDD_IPA_REAL_TIME_DEBUGGING BIT(8) + +#define HDD_IPA_IS_CONFIG_ENABLED(_hdd_ctx, _mask)\ + (((_hdd_ctx)->cfg_ini->IpaConfig & (_mask)) == (_mask)) + +#ifdef IPA_UC_OFFLOAD +#define HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa) \ + hdd_ipa->ipa_rx_internel_drop_count++ +#define HDD_IPA_INCREASE_NET_SEND_COUNT(hdd_ipa) \ + hdd_ipa->ipa_rx_net_send_count++ +#else +#define HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa) {} +#define HDD_IPA_INCREASE_NET_SEND_COUNT(hdd_ipa) {} +#endif /* IPA_UC_OFFLOAD */ + +/* Local Function Prototypes */ +static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, + unsigned long data); +static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, + unsigned long data); +static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type); + +#ifdef IPA_UC_OFFLOAD +extern int process_wma_set_command(int sessid, int paramid, + int sval, int vpdev); +#endif /* IPA_UC_OFFLOAD */ +static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context); + +bool hdd_ipa_is_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_ENABLE_MASK); +} + +static inline bool hdd_ipa_uc_is_enabled(struct hdd_ipa_priv *hdd_ipa) +{ +#ifdef IPA_UC_OFFLOAD + return (hdd_ipa && hdd_ipa->hdd_ctx->cfg_ini->IpaUcOffloadEnabled); +#else + return false; +#endif /* IPA_UC_OFFLOAD */ +} + +static inline bool hdd_ipa_uc_sta_is_enabled(struct hdd_ipa_priv *hdd_ipa) +{ +#ifdef IPA_UC_STA_OFFLOAD + return (hdd_ipa_uc_is_enabled(hdd_ipa) && + hdd_ipa->hdd_ctx->cfg_ini->ipa_uc_sta_offload); +#else + return false; +#endif /* IPA_UC_STA_OFFLOAD */ +} + +static inline bool hdd_ipa_is_pre_filter_enabled(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_PRE_FILTER_ENABLE_MASK); +} + +static inline bool hdd_ipa_is_ipv6_enabled(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_IPV6_ENABLE_MASK); +} + +static inline bool hdd_ipa_is_rm_enabled(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_RM_ENABLE_MASK); +} + +static inline bool hdd_ipa_is_clk_scaling_enabled(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_context_t *hdd_ctx = hdd_ipa->hdd_ctx; + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, + HDD_IPA_CLK_SCALING_ENABLE_MASK | + HDD_IPA_RM_ENABLE_MASK); +} + +static inline bool hdd_ipa_is_rt_debugging_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_REAL_TIME_DEBUGGING); +} + +static struct ipa_tx_data_desc *hdd_ipa_alloc_data_desc( + struct hdd_ipa_priv *hdd_ipa, int priority) +{ + struct ipa_tx_data_desc *desc = NULL; + + spin_lock_bh(&hdd_ipa->q_lock); + + /* Keep the descriptors for priority alloc which can be used for + * anchor nodes + */ + if (hdd_ipa->freeq_cnt < (HDD_IPA_DESC_BUFFER_RATIO * 2) && !priority) { + hdd_ipa->stats.num_freeq_empty++; + goto end; + } + + if (!list_empty(&hdd_ipa->free_desc_head)) { + desc = list_first_entry(&hdd_ipa->free_desc_head, + struct ipa_tx_data_desc, link); + list_del(&desc->link); + hdd_ipa->freeq_cnt--; + } else { + hdd_ipa->stats.num_pri_freeq_empty++; + } + +end: + spin_unlock_bh(&hdd_ipa->q_lock); + + return desc; +} + +static void hdd_ipa_free_data_desc(struct hdd_ipa_priv *hdd_ipa, + struct ipa_tx_data_desc *desc) +{ + desc->priv = NULL; + desc->pyld_buffer = NULL; + desc->pyld_len = 0; + spin_lock_bh(&hdd_ipa->q_lock); + list_add_tail(&desc->link, &hdd_ipa->free_desc_head); + hdd_ipa->freeq_cnt++; + spin_unlock_bh(&hdd_ipa->q_lock); +} + +static struct iphdr * hdd_ipa_get_ip_pkt(void *data, uint16_t *eth_type) +{ + struct ethhdr *eth = (struct ethhdr *)data; + struct llc_snap_hdr *ls_hdr; + struct iphdr *ip_hdr; + + ip_hdr = NULL; + *eth_type = be16_to_cpu(eth->h_proto); + if (*eth_type < 0x600) { + /* Non Ethernet II framing format */ + ls_hdr = (struct llc_snap_hdr *)((uint8_t *)data + + sizeof(struct ethhdr)); + + if (((ls_hdr->dsap == 0xAA) && (ls_hdr->ssap == 0xAA)) || + ((ls_hdr->dsap == 0xAB) && (ls_hdr->ssap == 0xAB))) + *eth_type = be16_to_cpu(ls_hdr->eth_type); + ip_hdr = (struct iphdr *)((uint8_t *)data + + sizeof(struct ethhdr) + sizeof(struct llc_snap_hdr)); + } else if (*eth_type == ETH_P_IP) { + ip_hdr = (struct iphdr *)((uint8_t *)data + + sizeof(struct ethhdr)); + } + + return ip_hdr; +} + +static bool hdd_ipa_can_send_to_ipa(hdd_adapter_t *adapter, struct hdd_ipa_priv *hdd_ipa, void *data) +{ + uint16_t eth_type; + struct iphdr *ip_hdr = NULL; + + if (!hdd_ipa_is_pre_filter_enabled(hdd_ipa)) + return true; + ip_hdr = hdd_ipa_get_ip_pkt(data, ð_type); + + /* Check if the dest IP address is itself, then bypass IPA */ + if (eth_type == ETH_P_IP) { + if (ip_hdr->daddr != ((struct hdd_ipa_iface_context *)(adapter->ipa_context))->ifa_address) + return true; + else + return false; + } + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa) && eth_type == ETH_P_IPV6) + return true; + + return false; +} + +#ifdef IPA_UC_OFFLOAD +/** + * hdd_ipa_uc_rt_debug_host_fill() - fill rt debug buffer + * @ctext: pointer to hdd context. + * + * If rt debug enabled, periodically called, and fill debug buffer + * + * Return: none + */ +static void hdd_ipa_uc_rt_debug_host_fill(void *ctext) +{ + hdd_context_t *hdd_ctx = ctext; + struct hdd_ipa_priv *hdd_ipa; + struct uc_rt_debug_info *dump_info = NULL; + + if (wlan_hdd_validate_context(hdd_ctx)) + return; + + if (!hdd_ctx->hdd_ipa || + !hdd_ipa_uc_is_enabled((struct hdd_ipa_priv *)hdd_ctx->hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA UC is not enabled", __func__); + return; + } + + hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + + vos_lock_acquire(&hdd_ipa->rt_debug_lock); + dump_info = &hdd_ipa->rt_bug_buffer[ + hdd_ipa->rt_buf_fill_index % HDD_IPA_UC_RT_DEBUG_BUF_COUNT]; + if (!dump_info) { + vos_lock_release(&hdd_ipa->rt_debug_lock); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: invalid dump pointer", __func__); + return; + } + + dump_info->time = vos_timer_get_system_time(); + dump_info->ipa_excp_count = hdd_ipa->stats.num_rx_excep; + dump_info->rx_drop_count = hdd_ipa->ipa_rx_internel_drop_count; + dump_info->net_sent_count = hdd_ipa->ipa_rx_net_send_count; + dump_info->rx_discard_count = hdd_ipa->ipa_rx_discard; + dump_info->tx_mcbc_count = hdd_ipa->stats.num_tx_bcmc; + dump_info->tx_fwd_count = hdd_ipa->ipa_tx_forward; + dump_info->rx_destructor_call = hdd_ipa->ipa_rx_destructor_count; + hdd_ipa->rt_buf_fill_index++; + vos_lock_release(&hdd_ipa->rt_debug_lock); + + vos_timer_start(&hdd_ipa->rt_debug_fill_timer, + HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL); +} + +/** + * hdd_ipa_uc_rt_debug_host_dump() - dump rt debug buffer + * @pHddCtx: pointer to hdd context. + * + * If rt debug enabled, dump debug buffer contents based on requirement + * + * Return: none + */ +void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa; + unsigned int dump_count; + unsigned int dump_index; + struct uc_rt_debug_info *dump_info = NULL; + + if (wlan_hdd_validate_context(hdd_ctx)) + return; + + hdd_ipa = hdd_ctx->hdd_ipa; + if (!hdd_ipa || + !hdd_ipa_uc_is_enabled((struct hdd_ipa_priv *)hdd_ctx->hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA UC is not enabled", __func__); + return; + } + + pr_err("========= WLAN-IPA DEBUG BUF DUMP ==========\n"); + pr_err(" TM : EXEP : DROP : NETS : MCBC : TXFD : DSTR : DSCD\n"); + + vos_lock_acquire(&hdd_ipa->rt_debug_lock); + for (dump_count = 0; + dump_count < HDD_IPA_UC_RT_DEBUG_BUF_COUNT; + dump_count++) { + dump_index = (hdd_ipa->rt_buf_fill_index + dump_count) % + HDD_IPA_UC_RT_DEBUG_BUF_COUNT; + dump_info = &hdd_ipa->rt_bug_buffer[dump_index]; + if ((dump_index > HDD_IPA_UC_RT_DEBUG_BUF_COUNT) || + (!dump_info)) { + vos_lock_release(&hdd_ipa->rt_debug_lock); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "INVALID"); + return; + } + pr_err("%12lu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n", + dump_info->time, dump_info->ipa_excp_count, + dump_info->rx_drop_count, dump_info->net_sent_count, + dump_info->tx_mcbc_count, dump_info->tx_fwd_count, + dump_info->rx_destructor_call, + dump_info->rx_discard_count); + } + vos_lock_release(&hdd_ipa->rt_debug_lock); + pr_err("======= WLAN-IPA DEBUG BUF DUMP END ========\n"); +} + +/** + * hdd_ipa_uc_rt_debug_handler - periodic memory health monitor handler + * @ctext: pointer to hdd context. + * + * periodically called by timer expire + * will try to alloc dummy memory and detect out of memory condition + * if out of memory detected, dump wlan-ipa stats + * + * Return: none + */ +static void hdd_ipa_uc_rt_debug_handler(void *ctext) +{ + hdd_context_t *hdd_ctx= ctext; + struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa; + void *dummy_ptr; + + if (wlan_hdd_validate_context(hdd_ctx)) + return; + + if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: IPA RT debug is not enabled", __func__); + return; + } + + /* + * Allocate dummy buffer periodically and free immediately + * This will proactively detect OOM condition + * And if allocation fail, will dump WLAN IPA stats + */ + dummy_ptr = kmalloc(HDD_IPA_UC_DEBUG_DUMMY_MEM_SIZE, + GFP_KERNEL | GFP_ATOMIC); + if (!dummy_ptr) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: Dummy alloc fail", __func__); + hdd_ipa_uc_rt_debug_host_dump(hdd_ctx); + hdd_ipa_uc_stat_request( + hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP), 1); + } else { + kfree(dummy_ptr); + } + + vos_timer_start(&hdd_ipa->rt_debug_timer, + HDD_IPA_UC_RT_DEBUG_PERIOD); +} + +/** + * hdd_ipa_uc_rt_debug_destructor - called by data packet free + * @skb: packet pinter + * + * when free data packet, will be invoked by wlan client and will increase + * free counter + * + * Return: none + */ +void hdd_ipa_uc_rt_debug_destructor(struct sk_buff *skb) +{ + if (!ghdd_ipa) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: invalid hdd context", __func__); + return; + } + + ghdd_ipa->ipa_rx_destructor_count++; +} + +/** + * hdd_ipa_uc_rt_debug_deinit - remove resources to handle rt debugging + * @pHddCtx: hdd main context + * + * free all rt debugging resources + * + * Return: none + */ +static void hdd_ipa_uc_rt_debug_deinit(hdd_context_t *pHddCtx) +{ + struct hdd_ipa_priv *hdd_ipa = pHddCtx->hdd_ipa; + + if ( VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&hdd_ipa->rt_debug_fill_timer)) { + vos_timer_stop(&hdd_ipa->rt_debug_fill_timer); + } + vos_timer_destroy(&hdd_ipa->rt_debug_fill_timer); + vos_lock_destroy(&hdd_ipa->rt_debug_lock); + + if (!hdd_ipa_is_rt_debugging_enabled(pHddCtx)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: IPA RT debug is not enabled", __func__); + return; + } + + if ( VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&hdd_ipa->rt_debug_timer)) { + vos_timer_stop(&hdd_ipa->rt_debug_timer); + } + vos_timer_destroy(&hdd_ipa->rt_debug_timer); +} + +/** + * hdd_ipa_uc_rt_debug_init - intialize resources to handle rt debugging + * @pHddCtx: hdd main context + * + * alloc and initialize all rt debugging resources + * + * Return: none + */ +static void hdd_ipa_uc_rt_debug_init(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa; + + /* Histogram intialize by default */ + vos_lock_init(&hdd_ipa->rt_debug_lock); + vos_timer_init(&hdd_ipa->rt_debug_fill_timer, VOS_TIMER_TYPE_SW, + hdd_ipa_uc_rt_debug_host_fill, (void *)hdd_ctx); + + hdd_ipa->rt_buf_fill_index = 0; + vos_mem_zero(hdd_ipa->rt_bug_buffer, + sizeof(struct uc_rt_debug_info) * HDD_IPA_UC_RT_DEBUG_BUF_COUNT); + hdd_ipa->ipa_tx_forward = 0; + hdd_ipa->ipa_rx_discard = 0; + hdd_ipa->ipa_rx_net_send_count = 0; + hdd_ipa->ipa_rx_internel_drop_count = 0; + hdd_ipa->ipa_rx_destructor_count = 0; + + vos_timer_start(&hdd_ipa->rt_debug_fill_timer, + HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL); + + /* Realtime debug enable only when feature enabled */ + if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA RT debug is not enabled", __func__); + return; + } + vos_timer_init(&hdd_ipa->rt_debug_timer, VOS_TIMER_TYPE_SW, + hdd_ipa_uc_rt_debug_handler, (void *)hdd_ctx); + + vos_timer_start(&hdd_ipa->rt_debug_timer, + HDD_IPA_UC_RT_DEBUG_PERIOD); +} + +void hdd_ipa_uc_stat_query(hdd_context_t *pHddCtx, + uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff) +{ + struct hdd_ipa_priv *hdd_ipa; + + hdd_ipa = (struct hdd_ipa_priv *)pHddCtx->hdd_ipa; + *ipa_tx_diff = 0; + *ipa_rx_diff = 0; + + if (!hdd_ipa_is_enabled(pHddCtx) || + !(hdd_ipa_uc_is_enabled(hdd_ipa))) { + return; + } + + vos_lock_acquire(&hdd_ipa->ipa_lock); + if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) && + (VOS_FALSE == hdd_ipa->resource_loading)) { + *ipa_tx_diff = hdd_ipa->ipa_tx_packets_diff; + *ipa_rx_diff = hdd_ipa->ipa_rx_packets_diff; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: STAT Query TX DIFF %d, RX DIFF %d", + __func__, *ipa_tx_diff, *ipa_rx_diff); + } + vos_lock_release(&hdd_ipa->ipa_lock); + return; +} + +void hdd_ipa_uc_stat_request( hdd_adapter_t *adapter, uint8_t reason) +{ + hdd_context_t *pHddCtx; + struct hdd_ipa_priv *hdd_ipa; + + if (!adapter) { + return; + } + + pHddCtx = (hdd_context_t *)adapter->pHddCtx; + hdd_ipa = (struct hdd_ipa_priv *)pHddCtx->hdd_ipa; + if (!hdd_ipa_is_enabled(pHddCtx) || + !(hdd_ipa_uc_is_enabled(hdd_ipa))) { + return; + } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: STAT REQ Reason %d", + __func__, reason); + vos_lock_acquire(&hdd_ipa->ipa_lock); + if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) && + (VOS_FALSE == hdd_ipa->resource_loading)) { + hdd_ipa->stat_req_reason = (hdd_ipa_uc_stat_reason)reason; + process_wma_set_command( + (int)adapter->sessionId, + (int)WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID, + 0, VDEV_CMD); + } + vos_lock_release(&hdd_ipa->ipa_lock); +} + +static v_BOOL_t hdd_ipa_uc_find_add_assoc_sta( + struct hdd_ipa_priv *hdd_ipa, + v_BOOL_t sta_add, + uint8_t sta_id) +{ + /* Found associated sta */ + v_BOOL_t sta_found = VOS_FALSE; + uint8_t idx; + + for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) { + if ((hdd_ipa->assoc_stas_map[idx].is_reserved) && + (hdd_ipa->assoc_stas_map[idx].sta_id == sta_id)) { + sta_found = VOS_TRUE; + break; + } + } + + /* Try to add sta which is already in + * If the sta is already in, just return sta_found */ + if (sta_add && sta_found) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: STA ID %d already exist, cannot add", + __func__, sta_id); + return sta_found; + } + + if (sta_add) { + /* Find first empty slot */ + for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) { + if (!hdd_ipa->assoc_stas_map[idx].is_reserved) { + hdd_ipa->assoc_stas_map[idx].is_reserved = + VOS_TRUE; + hdd_ipa->assoc_stas_map[idx].sta_id = sta_id; + return sta_found; + } + } + } + + /* Delete STA from map, but could not find STA within the map + * Error case, add error log */ + if (!sta_add && !sta_found) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: STA ID %d does not exist, cannot delete", + __func__, sta_id); + return sta_found; + } + + if (!sta_add) { + for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) { + if ((hdd_ipa->assoc_stas_map[idx].is_reserved) && + (hdd_ipa->assoc_stas_map[idx].sta_id == sta_id)) { + hdd_ipa->assoc_stas_map[idx].is_reserved = + VOS_FALSE; + hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF; + return sta_found; + } + } + } + + return sta_found; +} + +static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa) +{ + int result; + + /* ACTIVATE TX PIPE */ + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Enable TX PIPE(tx_pipe_handle=%d)", + __func__, hdd_ipa->tx_pipe_handle); + result = ipa_enable_wdi_pipe(hdd_ipa->tx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Enable TX PIPE fail, code %d", + __func__, result); + return result; + } + result = ipa_resume_wdi_pipe(hdd_ipa->tx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Resume TX PIPE fail, code %d", + __func__, result); + return result; + } + WLANTL_SetUcActive(hdd_ipa->hdd_ctx->pvosContext, + VOS_TRUE, VOS_TRUE); + + /* ACTIVATE RX PIPE */ + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Enable RX PIPE(rx_pipe_handle=%d)" + , __func__, hdd_ipa->rx_pipe_handle); + result = ipa_enable_wdi_pipe(hdd_ipa->rx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Enable RX PIPE fail, code %d", + __func__, result); + return result; + } + result = ipa_resume_wdi_pipe(hdd_ipa->rx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Resume RX PIPE fail, code %d", + __func__, result); + return result; + } + WLANTL_SetUcActive(hdd_ipa->hdd_ctx->pvosContext, + VOS_TRUE, VOS_FALSE); + + hdd_ipa->ipa_pipes_down = false; + return 0; +} + +static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa) +{ + int result; + + hdd_ipa->ipa_pipes_down = true; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Disable RX PIPE", __func__); + result = ipa_suspend_wdi_pipe(hdd_ipa->rx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Suspend RX PIPE fail, code %d", + __func__, result); + return result; + } + result = ipa_disable_wdi_pipe(hdd_ipa->rx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Disable RX PIPE fail, code %d", + __func__, result); + return result; + } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Disable TX PIPE", __func__); + result = ipa_suspend_wdi_pipe(hdd_ipa->tx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Suspend TX PIPE fail, code %d", + __func__, result); + return result; + } + result = ipa_disable_wdi_pipe(hdd_ipa->tx_pipe_handle); + if (result) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Disable TX PIPE fail, code %d", + __func__, result); + return result; + } + + return 0; +} + +static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_ipa->activated_fw_pipe = 0; + hdd_ipa->resource_loading = VOS_TRUE; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "+%s", __func__); + + /* If RM feature enabled + * Request PROD Resource first + * PROD resource may return sync or async manners */ + if (hdd_ipa_is_rm_enabled(hdd_ipa)) { + if (!ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD)) { + /* RM PROD request sync return + * enable pipe immediately */ + if (hdd_ipa_uc_enable_pipes(hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA WDI Pipes activate fail", __func__); + hdd_ipa->resource_loading = VOS_FALSE; + return -EBUSY; + } + } + } else { + /* RM Disabled + * Just enabled all the PIPEs */ + if (hdd_ipa_uc_enable_pipes(hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA WDI Pipes activate fail", __func__); + hdd_ipa->resource_loading = VOS_FALSE; + return -EBUSY; + } + } + return 0; +} + +static int hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa) +{ + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "+%s", __func__); + + hdd_ipa->resource_unloading = VOS_TRUE; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Disable FW RX PIPE", __func__); + WLANTL_SetUcActive(hdd_ipa->hdd_ctx->pvosContext, + VOS_FALSE, VOS_FALSE); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Disable FW TX PIPE", __func__); + WLANTL_SetUcActive(hdd_ipa->hdd_ctx->pvosContext, + VOS_FALSE, VOS_TRUE); + return 0; +} + +static void hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event) +{ + struct hdd_ipa_priv *hdd_ipa = context; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + /* + * When SSR is going on or driver is unloading, just return. + */ + status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx); + if (0 != status) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "HDD context is not valid"); + return; + } + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + return; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s, event code %d", + __func__, event); + + switch (event) { + case IPA_RM_RESOURCE_GRANTED: + /* Differed RM Granted */ + vos_lock_acquire(&hdd_ipa->ipa_lock); + if ((VOS_FALSE == hdd_ipa->resource_unloading) && + (!hdd_ipa->activated_fw_pipe)) { + hdd_ipa_uc_enable_pipes(hdd_ipa); + } + vos_lock_release(&hdd_ipa->ipa_lock); + break; + + case IPA_RM_RESOURCE_RELEASED: + /* Differed RM Released */ + hdd_ipa->resource_unloading = VOS_FALSE; + break; + + default: + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s, invalid event code %d", + __func__, event); + break; + } +} + +static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work) +{ + enum ipa_rm_event event; + struct uc_rm_work_struct *uc_rm_work = container_of(work, + struct uc_rm_work_struct, work); + struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work, + struct hdd_ipa_priv, uc_rm_work); + + vos_ssr_protect(__func__); + event = uc_rm_work->event; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "%s, posted event %d", __func__, event); + + hdd_ipa_uc_rm_notify_handler(hdd_ipa, event); + vos_ssr_unprotect(__func__); + + return; +} + +static int hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa) +{ + v_SIZE_t pending_event_count; + struct ipa_uc_pending_event *pending_event = NULL; + + vos_list_size(&hdd_ipa->pending_event, &pending_event_count); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s, Pending Event Count %d", __func__, pending_event_count); + if (!pending_event_count) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s, No Pending Event", __func__); + return 0; + } + + vos_list_remove_front(&hdd_ipa->pending_event, + (vos_list_node_t **)&pending_event); + while (pending_event != NULL) { + hdd_ipa_wlan_evt(pending_event->adapter, + pending_event->type, + pending_event->sta_id, + pending_event->mac_addr); + vos_mem_free(pending_event); + pending_event = NULL; + vos_list_remove_front(&hdd_ipa->pending_event, + (vos_list_node_t **)&pending_event); + } + return 0; +} + +static void hdd_ipa_uc_loaded_handler(struct hdd_ipa_priv *ipa_ctxt) +{ + hdd_context_t *hdd_ctx = ipa_ctxt->hdd_ctx; + struct ipa_wdi_out_params pipe_out; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s : UC READY", __func__); + if (VOS_TRUE == ipa_ctxt->uc_loaded) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "%s : UC already loaded", __func__); + return; + } + + ipa_ctxt->uc_loaded = VOS_TRUE; + /* Connect pipe */ + ipa_connect_wdi_pipe(&ipa_ctxt->cons_pipe_in, &pipe_out); + ipa_ctxt->tx_pipe_handle = pipe_out.clnt_hdl; + hdd_ctx->tx_comp_doorbell_paddr = (v_U32_t)pipe_out.uc_door_bell_pa; + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s : TX PIPE Handle %d, DBPA 0x%x", + __func__, ipa_ctxt->tx_pipe_handle, (v_U32_t)pipe_out.uc_door_bell_pa); + + ipa_connect_wdi_pipe(&ipa_ctxt->prod_pipe_in, &pipe_out); + ipa_ctxt->rx_pipe_handle = pipe_out.clnt_hdl; + hdd_ctx->rx_ready_doorbell_paddr = pipe_out.uc_door_bell_pa; + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s : RX PIPE Handle %d, DBPA 0x%x", + __func__, ipa_ctxt->rx_pipe_handle, (v_U32_t)pipe_out.uc_door_bell_pa); + + /* If already any STA connected, enable IPA/FW PIPEs */ + if (ipa_ctxt->sap_num_connected_sta) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "Client already connected, enable IPA/FW PIPEs"); + hdd_ipa_uc_handle_first_con(ipa_ctxt); + } +} +void hdd_ipa_uc_loaded_uc_cb(void *priv_ctxt) +{ + struct hdd_ipa_priv *hdd_ipa; + struct op_msg_type *msg; + struct uc_op_work_struct *uc_op_work; + + if (NULL == priv_ctxt) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid IPA context"); + return; + } + + hdd_ipa = (struct hdd_ipa_priv *)priv_ctxt; + msg = (struct op_msg_type *)adf_os_mem_alloc(NULL, + sizeof(struct op_msg_type)); + if (!msg) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "op_msg allocation fails"); + return; + } + + msg->op_code = HDD_IPA_UC_OPCODE_UC_READY; + + uc_op_work = &hdd_ipa->uc_op_work[msg->op_code]; + if (uc_op_work->msg) + /* When the same uC OPCODE is already pended, just return */ + return; + + uc_op_work->msg = msg; + schedule_work(&uc_op_work->work); + return; +} + +#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) +static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) +{ + struct op_msg_type *msg = op_msg; + struct ipa_uc_fw_stats *uc_fw_stat; + struct IpaHwStatsWDIInfoData_t ipa_stat; + struct hdd_ipa_priv *hdd_ipa; + hdd_context_t *hdd_ctx; + VOS_STATUS status = VOS_STATUS_SUCCESS; + struct ipa_msg_meta meta; + struct ipa_wlan_msg *ipa_msg; + int ret = 0; + + if (!op_msg || !usr_ctxt) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s, INVALID ARG", __func__); + return; + } + + if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s, INVALID OPCODE %d", __func__, msg->op_code); + adf_os_mem_free(op_msg); + return; + } + + hdd_ctx = (hdd_context_t *)usr_ctxt; + hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + + /* + * When SSR is going on or driver is unloading, just return. + */ + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "HDD context is not valid"); + adf_os_mem_free(op_msg); + return; + } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, + "%s, OPCODE %s", __func__, op_string[msg->op_code]); + + if ((HDD_IPA_UC_OPCODE_TX_RESUME == msg->op_code) || + (HDD_IPA_UC_OPCODE_RX_RESUME == msg->op_code)) { + vos_lock_acquire(&hdd_ipa->ipa_lock); + hdd_ipa->activated_fw_pipe++; + if (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) { + hdd_ipa->resource_loading = VOS_FALSE; + if (VOS_FALSE == hdd_ipa->wdi_enabled) { + hdd_ipa->wdi_enabled = VOS_TRUE; + /* WDI enable message to IPA */ + meta.msg_len = sizeof(*ipa_msg); + ipa_msg = adf_os_mem_alloc(NULL, meta.msg_len); + if (ipa_msg == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "msg allocation failed"); + adf_os_mem_free(op_msg); + vos_lock_release(&hdd_ipa->ipa_lock); + return; + } + + meta.msg_type = WLAN_WDI_ENABLE; + hddLog(VOS_TRACE_LEVEL_INFO, + "ipa_send_msg(Evt:%d)", meta.msg_type); + ret = ipa_send_msg(&meta, ipa_msg, + hdd_ipa_msg_free_fn); + if (ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "ipa_send_msg(Evt:%d)-fail=%d", + meta.msg_type, ret); + adf_os_mem_free(ipa_msg); + } +#ifdef IPA_UC_STA_OFFLOAD + else { + /* Send SCC/MCC Switching event to IPA */ + hdd_ipa_send_mcc_scc_msg(hdd_ctx, + hdd_ctx->mcc_mode); + } +#endif + } + + hdd_ipa_uc_proc_pending_event(hdd_ipa); + + if (hdd_ipa->pending_cons_req) + ipa_rm_notify_completion( + IPA_RM_RESOURCE_GRANTED, + IPA_RM_RESOURCE_WLAN_CONS); + hdd_ipa->pending_cons_req = VOS_FALSE; + } + vos_lock_release(&hdd_ipa->ipa_lock); + } else if ((HDD_IPA_UC_OPCODE_TX_SUSPEND == msg->op_code) || + (HDD_IPA_UC_OPCODE_RX_SUSPEND == msg->op_code)) { + vos_lock_acquire(&hdd_ipa->ipa_lock); + hdd_ipa->activated_fw_pipe--; + if (!hdd_ipa->activated_fw_pipe) { + hdd_ipa_uc_disable_pipes(hdd_ipa); + if (hdd_ipa_is_rm_enabled(hdd_ipa)) + ipa_rm_release_resource( + IPA_RM_RESOURCE_WLAN_PROD); + /* Sync return success from IPA + * Enable/resume all the PIPEs */ + hdd_ipa->resource_unloading = VOS_FALSE; + hdd_ipa_uc_proc_pending_event(hdd_ipa); + hdd_ipa->pending_cons_req = VOS_FALSE; + } + vos_lock_release(&hdd_ipa->ipa_lock); + } + + if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) && + (HDD_IPA_UC_STAT_REASON_DEBUG == hdd_ipa->stat_req_reason)) { + /* STATs from host */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_HOST CE ====\n" + "CE RING BASE: 0x%x\n" + "CE RING SIZE: %d\n" + "CE REG ADDR : 0x%x", + hdd_ctx->ce_sr_base_paddr, + hdd_ctx->ce_sr_ring_size, + hdd_ctx->ce_reg_paddr); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_HOST TX ====\n" + "COMP RING BASE: 0x%x\n" + "COMP RING SIZE: %d\n" + "NUM ALLOC BUF: %d\n" + "COMP RING DBELL : 0x%x", + hdd_ctx->tx_comp_ring_base_paddr, + hdd_ctx->tx_comp_ring_size, + hdd_ctx->tx_num_alloc_buffer, + hdd_ctx->tx_comp_doorbell_paddr); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_HOST RX ====\n" + "IND RING BASE: 0x%x\n" + "IND RING SIZE: %d\n" + "IND RING DBELL : 0x%x\n" + "PROC DONE IND ADDR : 0x%x\n" + "NUM EXCP PKT : %llu\n" + "NUM TX BCMC : %llu\n" + "NUM TX BCMC ERR : %llu", + hdd_ctx->rx_rdy_ring_base_paddr, + hdd_ctx->rx_rdy_ring_size, + hdd_ctx->rx_ready_doorbell_paddr, + hdd_ctx->rx_proc_done_idx_paddr, + hdd_ipa->stats.num_rx_excep, + hdd_ipa->stats.num_tx_bcmc, + hdd_ipa->stats.num_tx_bcmc_err); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_HOST CONTROL ====\n" + "SAP NUM STAs: %d\n" +#ifdef IPA_UC_STA_OFFLOAD + "STA CONNECTED: %d\n" +#endif + "TX PIPE HDL: %d\n" + "RX PIPE HDL : %d\n" + "RSC LOADING : %d\n" + "RSC UNLOADING : %d\n" + "PNDNG CNS RQT : %d", + hdd_ipa->sap_num_connected_sta, +#ifdef IPA_UC_STA_OFFLOAD + hdd_ipa->sta_connected, +#endif + hdd_ipa->tx_pipe_handle, + hdd_ipa->rx_pipe_handle, + (unsigned int)hdd_ipa->resource_loading, + (unsigned int)hdd_ipa->resource_unloading, + (unsigned int)hdd_ipa->pending_cons_req); + + /* STATs from FW */ + uc_fw_stat = (struct ipa_uc_fw_stats *) + ((v_U8_t *)op_msg + sizeof(struct op_msg_type)); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_FW TX ====\n" + "COMP RING BASE: 0x%x\n" + "COMP RING SIZE: %d\n" + "COMP RING DBELL : 0x%x\n" + "COMP RING DBELL IND VAL : %d\n" + "COMP RING DBELL CACHED VAL : %d\n" + "COMP RING DBELL CACHED VAL : %d\n" + "PKTS ENQ : %d\n" + "PKTS COMP : %d\n" + "IS SUSPEND : %d\n" + "RSVD : 0x%x", + uc_fw_stat->tx_comp_ring_base, + uc_fw_stat->tx_comp_ring_size, + uc_fw_stat->tx_comp_ring_dbell_addr, + uc_fw_stat->tx_comp_ring_dbell_ind_val, + uc_fw_stat->tx_comp_ring_dbell_cached_val, + uc_fw_stat->tx_comp_ring_dbell_cached_val, + uc_fw_stat->tx_pkts_enqueued, + uc_fw_stat->tx_pkts_completed, + uc_fw_stat->tx_is_suspend, + uc_fw_stat->tx_reserved); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_FW RX ====\n" + "IND RING BASE: 0x%x\n" + "IND RING SIZE: %d\n" + "IND RING DBELL : 0x%x\n" + "IND RING DBELL IND VAL : %d\n" + "IND RING DBELL CACHED VAL : %d\n" + "RDY IND ADDR : 0x%x\n" + "RDY IND CACHE VAL : %d\n" + "RFIL IND : %d\n" + "NUM PKT INDICAT : %d\n" + "BUF REFIL : %d\n" + "NUM DROP NO SPC : %d\n" + "NUM DROP NO BUF : %d\n" + "IS SUSPND : %d\n" + "RSVD : 0x%x\n", + uc_fw_stat->rx_ind_ring_base, + uc_fw_stat->rx_ind_ring_size, + uc_fw_stat->rx_ind_ring_dbell_addr, + uc_fw_stat->rx_ind_ring_dbell_ind_val, + uc_fw_stat->rx_ind_ring_dbell_ind_cached_val, + uc_fw_stat->rx_ind_ring_rdidx_addr, + uc_fw_stat->rx_ind_ring_rd_idx_cached_val, + uc_fw_stat->rx_refill_idx, + uc_fw_stat->rx_num_pkts_indicated, + uc_fw_stat->rx_buf_refilled, + uc_fw_stat->rx_num_ind_drop_no_space, + uc_fw_stat->rx_num_ind_drop_no_buf, + uc_fw_stat->rx_is_suspend, + uc_fw_stat->rx_reserved); + /* STATs from IPA */ + ipa_get_wdi_stats(&ipa_stat); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC IPA TX ====\n" + "NUM PROCD : %d\n" + "CE DBELL : 0x%x\n" + "NUM DBELL FIRED : %d\n" + "COMP RNG FULL : %d\n" + "COMP RNG EMPT : %d\n" + "COMP RNG USE HGH : %d\n" + "COMP RNG USE LOW : %d\n" + "BAM FIFO FULL : %d\n" + "BAM FIFO EMPT : %d\n" + "BAM FIFO USE HGH : %d\n" + "BAM FIFO USE LOW : %d\n" + "NUM DBELL : %d\n" + "NUM UNEXP DBELL : %d\n" + "NUM BAM INT HDL : 0x%x\n" + "NUM BAM INT NON-RUN : 0x%x\n" + "NUM QMB INT HDL : 0x%x", + ipa_stat.tx_ch_stats.num_pkts_processed, + ipa_stat.tx_ch_stats.copy_engine_doorbell_value, + ipa_stat.tx_ch_stats.num_db_fired, + ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringFull, + ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringEmpty, + ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh, + ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageLow, + ipa_stat.tx_ch_stats.bam_stats.bamFifoFull, + ipa_stat.tx_ch_stats.bam_stats.bamFifoEmpty, + ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageHigh, + ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageLow, + ipa_stat.tx_ch_stats.num_db, + ipa_stat.tx_ch_stats.num_unexpected_db, + ipa_stat.tx_ch_stats.num_bam_int_handled, + ipa_stat.tx_ch_stats.num_bam_int_in_non_runnning_state, + ipa_stat.tx_ch_stats.num_qmb_int_handled); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "==== IPA_UC IPA RX ====\n" + "MAX OST PKT : %d\n" + "NUM PKT PRCSD : %d\n" + "RNG RP : 0x%x\n" + "COMP RNG FULL : %d\n" + "COMP RNG EMPT : %d\n" + "COMP RNG USE HGH : %d\n" + "COMP RNG USE LOW : %d\n" + "BAM FIFO FULL : %d\n" + "BAM FIFO EMPT : %d\n" + "BAM FIFO USE HGH : %d\n" + "BAM FIFO USE LOW : %d\n" + "NUM DB : %d\n" + "NUM UNEXP DB : %d\n" + "NUM BAM INT HNDL : 0x%x\n", + ipa_stat.rx_ch_stats.max_outstanding_pkts, + ipa_stat.rx_ch_stats.num_pkts_processed, + ipa_stat.rx_ch_stats.rx_ring_rp_value, + ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringFull, + ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringEmpty, + ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh, + ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageLow, + ipa_stat.rx_ch_stats.bam_stats.bamFifoFull, + ipa_stat.rx_ch_stats.bam_stats.bamFifoEmpty, + ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageHigh, + ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageLow, + ipa_stat.rx_ch_stats.num_db, + ipa_stat.rx_ch_stats.num_unexpected_db, + ipa_stat.rx_ch_stats.num_bam_int_handled); + } else if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) && + (HDD_IPA_UC_STAT_REASON_BW_CAL == hdd_ipa->stat_req_reason)) { + /* STATs from FW */ + uc_fw_stat = (struct ipa_uc_fw_stats *) + ((v_U8_t *)op_msg + sizeof(struct op_msg_type)); + vos_lock_acquire(&hdd_ipa->ipa_lock); + hdd_ipa->ipa_tx_packets_diff = HDD_BW_GET_DIFF( + uc_fw_stat->tx_pkts_completed, + hdd_ipa->ipa_p_tx_packets); + hdd_ipa->ipa_rx_packets_diff = HDD_BW_GET_DIFF( + (uc_fw_stat->rx_num_ind_drop_no_space + + uc_fw_stat->rx_num_ind_drop_no_buf + + uc_fw_stat->rx_num_pkts_indicated), + hdd_ipa->ipa_p_rx_packets); + + hdd_ipa->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed; + hdd_ipa->ipa_p_rx_packets = + (uc_fw_stat->rx_num_ind_drop_no_space + + uc_fw_stat->rx_num_ind_drop_no_buf + + uc_fw_stat->rx_num_pkts_indicated); + vos_lock_release(&hdd_ipa->ipa_lock); + } else if (HDD_IPA_UC_OPCODE_UC_READY == msg->op_code) { + vos_lock_acquire(&hdd_ipa->ipa_lock); + hdd_ipa_uc_loaded_handler(hdd_ipa); + vos_lock_release(&hdd_ipa->ipa_lock); + } + + adf_os_mem_free(op_msg); +} + +static void hdd_ipa_uc_fw_op_event_handler(struct work_struct *work) +{ + struct op_msg_type *msg; + struct uc_op_work_struct *uc_op_work = container_of(work, + struct uc_op_work_struct, work); + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + + vos_ssr_protect(__func__); + + msg = uc_op_work->msg; + uc_op_work->msg = NULL; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "%s, posted msg %d", __func__, msg->op_code); + + hdd_ipa_uc_op_cb(msg, hdd_ipa->hdd_ctx); + + vos_ssr_unprotect(__func__); + + return; +} + +static void hdd_ipa_uc_op_event_handler(v_U8_t *op_msg, void *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa; + struct op_msg_type *msg; + struct uc_op_work_struct *uc_op_work; + + if (NULL == hdd_ctx) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid HDD context"); + goto end; + } + + msg = (struct op_msg_type *)op_msg; + hdd_ipa = ((hdd_context_t *)hdd_ctx)->hdd_ipa; + + if (unlikely(!hdd_ipa)) + goto end; + + if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "%s: Invalid OP Code (%d)", + __func__, msg->op_code); + goto end; + } + + uc_op_work = &hdd_ipa->uc_op_work[msg->op_code]; + if (uc_op_work->msg) + /* When the same uC OPCODE is already pended, just return */ + goto end; + + uc_op_work->msg = msg; + schedule_work(&uc_op_work->work); + return; + +end: + adf_os_mem_free(op_msg); +} + +static VOS_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) +{ + struct ipa_wdi_in_params pipe_in; + struct ipa_wdi_out_params pipe_out; + struct hdd_ipa_priv *ipa_ctxt = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + uint8_t i; + struct ipa_wdi_db_params dbpa; + + vos_mem_zero(&ipa_ctxt->cons_pipe_in, sizeof(struct ipa_wdi_in_params)); + vos_mem_zero(&ipa_ctxt->prod_pipe_in, sizeof(struct ipa_wdi_in_params)); + + vos_mem_zero(&pipe_in, sizeof(struct ipa_wdi_in_params)); + vos_mem_zero(&pipe_out, sizeof(struct ipa_wdi_out_params)); + + vos_list_init(&ipa_ctxt->pending_event); + vos_lock_init(&ipa_ctxt->event_lock); + vos_lock_init(&ipa_ctxt->ipa_lock); + + /* TX PIPE */ + pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_additional_const_len = + HDD_IPA_UC_WLAN_8023_HDR_SIZE; + pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC; + pipe_in.sys.client = IPA_CLIENT_WLAN1_CONS; + pipe_in.sys.desc_fifo_sz = hdd_ctx->cfg_ini->IpaDescSize; + pipe_in.sys.priv = hdd_ctx->hdd_ipa; + pipe_in.sys.ipa_ep_cfg.hdr_ext.hdr_little_endian = true; + pipe_in.sys.notify = hdd_ipa_i2w_cb; + if (!hdd_ipa_is_rm_enabled(ghdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: IPA RM DISABLED, IPA AWAKE", __func__); + pipe_in.sys.keep_ipa_awake = TRUE; + } + + pipe_in.u.dl.comp_ring_base_pa = hdd_ctx->tx_comp_ring_base_paddr; + pipe_in.u.dl.comp_ring_size = hdd_ctx->tx_comp_ring_size * 4; + pipe_in.u.dl.ce_ring_base_pa = hdd_ctx->ce_sr_base_paddr; + pipe_in.u.dl.ce_door_bell_pa = hdd_ctx->ce_reg_paddr; + pipe_in.u.dl.ce_ring_size = hdd_ctx->ce_sr_ring_size * 8; + pipe_in.u.dl.num_tx_buffers = hdd_ctx->tx_num_alloc_buffer; + + vos_mem_copy(&ipa_ctxt->cons_pipe_in, + &pipe_in, + sizeof(struct ipa_wdi_in_params)); + dbpa.client = IPA_CLIENT_WLAN1_CONS; + ipa_uc_wdi_get_dbpa(&dbpa); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s CONS DB get dbpa 0x%x", + __func__, (unsigned int)dbpa.uc_door_bell_pa); + hdd_ctx->tx_comp_doorbell_paddr = dbpa.uc_door_bell_pa; + if (VOS_TRUE == ipa_ctxt->uc_loaded) { + /* Connect WDI IPA PIPE */ + ipa_connect_wdi_pipe(&ipa_ctxt->cons_pipe_in, &pipe_out); + /* Micro Controller Doorbell register */ + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s CONS DB pipe out 0x%x", + __func__, (unsigned int)pipe_out.uc_door_bell_pa); + + hdd_ctx->tx_comp_doorbell_paddr = (v_U32_t)pipe_out.uc_door_bell_pa; + /* WLAN TX PIPE Handle */ + ipa_ctxt->tx_pipe_handle = pipe_out.clnt_hdl; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "TX : CRBPA 0x%x, CRS %d, CERBPA 0x%x, CEDPA 0x%x," + " CERZ %d, NB %d, CDBPAD 0x%x", + (unsigned int)pipe_in.u.dl.comp_ring_base_pa, + pipe_in.u.dl.comp_ring_size, + (unsigned int)pipe_in.u.dl.ce_ring_base_pa, + (unsigned int)pipe_in.u.dl.ce_door_bell_pa, + pipe_in.u.dl.ce_ring_size, + pipe_in.u.dl.num_tx_buffers, + (unsigned int)hdd_ctx->tx_comp_doorbell_paddr); + } + + /* RX PIPE */ + pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_RX_HDR_LEN; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 0; + pipe_in.sys.ipa_ep_cfg.hdr.hdr_metadata_reg_valid = 1; + pipe_in.sys.ipa_ep_cfg.mode.mode = IPA_BASIC; + pipe_in.sys.client = IPA_CLIENT_WLAN1_PROD; + pipe_in.sys.desc_fifo_sz = hdd_ctx->cfg_ini->IpaDescSize + + sizeof(struct sps_iovec); + pipe_in.sys.notify = hdd_ipa_w2i_cb; + if (!hdd_ipa_is_rm_enabled(ghdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA RM DISABLED, IPA AWAKE", __func__); + pipe_in.sys.keep_ipa_awake = TRUE; + } + + pipe_in.u.ul.rdy_ring_base_pa = hdd_ctx->rx_rdy_ring_base_paddr; + pipe_in.u.ul.rdy_ring_size = hdd_ctx->rx_rdy_ring_size; + pipe_in.u.ul.rdy_ring_rp_pa = hdd_ctx->rx_proc_done_idx_paddr; + + vos_mem_copy(&ipa_ctxt->prod_pipe_in, + &pipe_in, + sizeof(struct ipa_wdi_in_params)); + dbpa.client = IPA_CLIENT_WLAN1_PROD; + ipa_uc_wdi_get_dbpa(&dbpa); + hdd_ctx->rx_ready_doorbell_paddr = dbpa.uc_door_bell_pa; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s PROD DB get dbpa 0x%x", + __func__, (unsigned int)dbpa.uc_door_bell_pa); + if (VOS_TRUE == ipa_ctxt->uc_loaded) { + ipa_connect_wdi_pipe(&ipa_ctxt->prod_pipe_in, &pipe_out); + hdd_ctx->rx_ready_doorbell_paddr = pipe_out.uc_door_bell_pa; + ipa_ctxt->rx_pipe_handle = pipe_out.clnt_hdl; + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s PROD DB pipe out 0x%x", + __func__, (unsigned int)pipe_out.uc_door_bell_pa); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "RX : RRBPA 0x%x, RRS %d, PDIPA 0x%x, RDY_DB_PAD 0x%x", + (unsigned int)pipe_in.u.ul.rdy_ring_base_pa, + pipe_in.u.ul.rdy_ring_size, + (unsigned int)pipe_in.u.ul.rdy_ring_rp_pa, + (unsigned int)hdd_ctx->rx_ready_doorbell_paddr); + } + WLANTL_SetUcDoorbellPaddr((pVosContextType)(hdd_ctx->pvosContext), + (v_U32_t)hdd_ctx->tx_comp_doorbell_paddr, + (v_U32_t)hdd_ctx->rx_ready_doorbell_paddr); + + WLANTL_RegisterOPCbFnc((pVosContextType)(hdd_ctx->pvosContext), + hdd_ipa_uc_op_event_handler, (void *)hdd_ctx); + + for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) { + cnss_init_work(&ipa_ctxt->uc_op_work[i].work, + hdd_ipa_uc_fw_op_event_handler); + ipa_ctxt->uc_op_work[i].msg = NULL; + } + + return VOS_STATUS_SUCCESS; +} + +/** + * hdd_ipa_uc_force_pipe_shutdown() - Force shutdown IPA pipe + * @hdd_ctx: hdd main context + * + * Force shutdown IPA pipe + * Independent of FW pipe status, IPA pipe shutdonw progress + * in case, any STA does not leave properly, IPA HW pipe should cleaned up + * independent from FW pipe status + * + * Return: NONE + */ +void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa; + + if (!hdd_ipa_is_enabled(hdd_ctx) || !hdd_ctx->hdd_ipa) + return; + + hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + if (false == hdd_ipa->ipa_pipes_down) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "IPA pipes are not down yet, force shutdown"); + hdd_ipa_uc_disable_pipes(hdd_ipa); + } else { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "IPA pipes are down, do nothing"); + } + + return; +} + +/** + * hdd_ipa_uc_ssr_deinit() - handle ipa deinit for SSR + * + * Deinit basic IPA UC host side to be in sync reloaded FW during + * SSR + * + * Return: 0 - Success + */ +int hdd_ipa_uc_ssr_deinit() +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + int idx; + struct hdd_ipa_iface_context *iface_context; + + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) + return 0; + + /* Clean up HDD IPA interfaces */ + for (idx = 0; (hdd_ipa->num_iface > 0) && + (idx < HDD_IPA_MAX_IFACE); idx++) { + iface_context = &hdd_ipa->iface_context[idx]; + if (iface_context && iface_context->adapter) + hdd_ipa_cleanup_iface(iface_context); + } + + /* After SSR, wlan driver reloads FW again. But we need to protect + * IPA submodule during SSR transient state. So deinit basic IPA + * UC host side to be in sync with reloaded FW during SSR + */ + hdd_ipa_uc_disable_pipes(hdd_ipa); + + vos_lock_acquire(&hdd_ipa->ipa_lock); + for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) { + hdd_ipa->assoc_stas_map[idx].is_reserved = false; + hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF; + } + vos_lock_release(&hdd_ipa->ipa_lock); + + /* Full IPA driver cleanup not required since wlan driver is now + * unloaded and reloaded after SSR. + */ + return 0; +} + +/** + * hdd_ipa_uc_ssr_reinit() - handle ipa reinit after SSR + * + * Init basic IPA UC host side to be in sync with reloaded FW after + * SSR to resume IPA UC operations + * + * Return: 0 - Success + */ +int hdd_ipa_uc_ssr_reinit() +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) + return 0; + + /* After SSR is complete, IPA UC can resume operation. But now wlan + * driver will be unloaded and reloaded, which takes care of IPA cleanup + * and initialization. + * This is a placeholder func if IPA has to resume operations without + * driver reload. + */ + return 0; +} +#else +/** + * hdd_ipa_uc_rt_debug_destructor - called by data packet free + * @skb: packet pinter + * + * when free data packet, will be invoked by wlan client and will increase + * free counter + * + * Return: none + */ +void hdd_ipa_uc_rt_debug_destructor(struct sk_buff *skb) +{ + return; +} +#endif /* IPA_UC_OFFLOAD */ + +static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa) +{ + int ret = 0; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + return 0; + + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + + switch(hdd_ipa->rm_state) { + case HDD_IPA_RM_GRANTED: + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + return 0; + case HDD_IPA_RM_GRANT_PENDING: + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + return -EINPROGRESS; + case HDD_IPA_RM_RELEASED: + hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING; + break; + } + + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + + ret = ipa_rm_inactivity_timer_request_resource( + IPA_RM_RESOURCE_WLAN_PROD); + + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + if (ret == 0) { + hdd_ipa->rm_state = HDD_IPA_RM_GRANTED; + hdd_ipa->stats.num_rm_grant_imm++; + } + + cancel_delayed_work(&hdd_ipa->wake_lock_work); + if (hdd_ipa->wake_lock_released) { + vos_wake_lock_acquire(&hdd_ipa->wake_lock, + WIFI_POWER_EVENT_WAKELOCK_IPA); + hdd_ipa->wake_lock_released = false; + } + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + + return ret; +} + +static void hdd_ipa_wake_lock_timer_func(struct work_struct *work) +{ + struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work), + struct hdd_ipa_priv, wake_lock_work); + + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + + if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED) + goto end; + + hdd_ipa->wake_lock_released = true; + vos_wake_lock_release(&hdd_ipa->wake_lock, + WIFI_POWER_EVENT_WAKELOCK_IPA); + +end: + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); +} + +static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa) +{ + int ret = 0; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + return 0; + + if (atomic_read(&hdd_ipa->tx_ref_cnt)) + return -EAGAIN; + +#ifndef IPA_UC_STA_OFFLOAD + spin_lock_bh(&hdd_ipa->q_lock); + if (hdd_ipa->pending_hw_desc_cnt || hdd_ipa->pend_q_cnt) { + spin_unlock_bh(&hdd_ipa->q_lock); + return -EAGAIN; + } + spin_unlock_bh(&hdd_ipa->q_lock); +#endif + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + + if (!adf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) { + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + return -EAGAIN; + } + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + switch(hdd_ipa->rm_state) { + case HDD_IPA_RM_GRANTED: + break; + case HDD_IPA_RM_GRANT_PENDING: + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + return -EINPROGRESS; + case HDD_IPA_RM_RELEASED: + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + return 0; + } + + /* IPA driver returns immediately so set the state here to avoid any + * race condition. + */ + hdd_ipa->rm_state = HDD_IPA_RM_RELEASED; + hdd_ipa->stats.num_rm_release++; + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + + ret = ipa_rm_inactivity_timer_release_resource( + IPA_RM_RESOURCE_WLAN_PROD); + + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + if (unlikely(ret != 0)) { + hdd_ipa->rm_state = HDD_IPA_RM_GRANTED; + WARN_ON(1); + } + + /* + * If wake_lock is released immediately, kernel would try to suspend + * immediately as well, Just avoid ping-pong between suspend-resume + * while there is healthy amount of data transfer going on by + * releasing the wake_lock after some delay. + */ + schedule_delayed_work(&hdd_ipa->wake_lock_work, + msecs_to_jiffies(HDD_IPA_RX_INACTIVITY_MSEC_DELAY)); + + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + + return ret; +} + +static void hdd_ipa_send_pkt_to_ipa(struct hdd_ipa_priv *hdd_ipa) +{ + struct ipa_tx_data_desc *send_desc, *desc, *tmp; + uint32_t cur_send_cnt = 0, pend_q_cnt; + adf_nbuf_t buf; + struct ipa_tx_data_desc *send_desc_head = NULL; + + /* Unloading is in progress so do not proceed to send the packets to + * IPA + */ + if (hdd_ipa->hdd_ctx->isUnloadInProgress) + return; + + /* Make it priority queue request as send descriptor */ + send_desc_head = hdd_ipa_alloc_data_desc(hdd_ipa, 1); + + /* Try again later when descriptors are available */ + if (!send_desc_head) + return; + + INIT_LIST_HEAD(&send_desc_head->link); + + spin_lock_bh(&hdd_ipa->q_lock); + + if (hdd_ipa->pending_hw_desc_cnt >= hdd_ipa->hw_desc_cnt) { + hdd_ipa->stats.num_rx_ipa_hw_maxed_out++; + spin_unlock_bh(&hdd_ipa->q_lock); + hdd_ipa_free_data_desc(hdd_ipa, send_desc_head); + return; + } + + pend_q_cnt = hdd_ipa->pend_q_cnt; + + if (pend_q_cnt == 0) { + spin_unlock_bh(&hdd_ipa->q_lock); + hdd_ipa_free_data_desc(hdd_ipa, send_desc_head); + return; + } + + /* If hardware has more room than what is pending in the queue update + * the send_desc_head right away without going through the loop + */ + if ((hdd_ipa->pending_hw_desc_cnt + pend_q_cnt) < + hdd_ipa->hw_desc_cnt) { + list_splice_tail_init(&hdd_ipa->pend_desc_head, + &send_desc_head->link); + cur_send_cnt = pend_q_cnt; + hdd_ipa->pend_q_cnt = 0; + hdd_ipa->stats.num_rx_ipa_splice++; + } else { + while (((hdd_ipa->pending_hw_desc_cnt + cur_send_cnt) < + hdd_ipa->hw_desc_cnt) && pend_q_cnt > 0) + { + send_desc = list_first_entry(&hdd_ipa->pend_desc_head, + struct ipa_tx_data_desc, link); + list_del(&send_desc->link); + list_add_tail(&send_desc->link, &send_desc_head->link); + cur_send_cnt++; + pend_q_cnt--; + } + hdd_ipa->stats.num_rx_ipa_loop++; + + hdd_ipa->pend_q_cnt -= cur_send_cnt; + + VOS_ASSERT(hdd_ipa->pend_q_cnt == pend_q_cnt); + } + + hdd_ipa->pending_hw_desc_cnt += cur_send_cnt; + spin_unlock_bh(&hdd_ipa->q_lock); + + if (ipa_tx_dp_mul(hdd_ipa->prod_client, send_desc_head) != 0) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "ipa_tx_dp_mul failed: %u, q_cnt: %u!", + hdd_ipa->pending_hw_desc_cnt, + hdd_ipa->pend_q_cnt); + goto ipa_tx_failed; + } + + hdd_ipa->stats.num_rx_ipa_tx_dp += cur_send_cnt; + if (cur_send_cnt > hdd_ipa->stats.num_max_ipa_tx_mul) + hdd_ipa->stats.num_max_ipa_tx_mul = cur_send_cnt; + + return; + +ipa_tx_failed: + + spin_lock_bh(&hdd_ipa->q_lock); + hdd_ipa->pending_hw_desc_cnt -= cur_send_cnt; + spin_unlock_bh(&hdd_ipa->q_lock); + + list_for_each_entry_safe(desc, tmp, &send_desc_head->link, link) { + list_del(&desc->link); + buf = desc->priv; + adf_nbuf_free(buf); + hdd_ipa_free_data_desc(hdd_ipa, desc); + hdd_ipa->stats.num_rx_ipa_tx_dp_err++; + } + + /* Return anchor node */ + hdd_ipa_free_data_desc(hdd_ipa, send_desc_head); +} + + +static void hdd_ipa_rm_send_pkt_to_ipa(struct work_struct *work) +{ + struct hdd_ipa_priv *hdd_ipa = container_of(work, + struct hdd_ipa_priv, rm_work); + + return hdd_ipa_send_pkt_to_ipa(hdd_ipa); +} + +static void hdd_ipa_rm_notify(void *user_data, enum ipa_rm_event event, + unsigned long data) +{ + struct hdd_ipa_priv *hdd_ipa = user_data; + + if (unlikely(!hdd_ipa)) + return; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + return; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Evt: %d", event); + + switch(event) { + case IPA_RM_RESOURCE_GRANTED: +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + /* RM Notification comes with ISR context + * it should be serialized into work queue to avoid + * ISR sleep problem */ + hdd_ipa->uc_rm_work.event = event; + schedule_work(&hdd_ipa->uc_rm_work.work); + break; + } +#endif /* IPA_UC_OFFLOAD */ + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + hdd_ipa->rm_state = HDD_IPA_RM_GRANTED; + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + hdd_ipa->stats.num_rm_grant++; + + schedule_work(&hdd_ipa->rm_work); + break; + case IPA_RM_RESOURCE_RELEASED: + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "RM Release"); +#ifdef IPA_UC_OFFLOAD + hdd_ipa->resource_unloading = VOS_FALSE; +#endif /* IPA_UC_OFFLOAD */ + break; + default: + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event); + break; + } +} + +static int hdd_ipa_rm_cons_release(void) +{ +#ifdef IPA_UC_OFFLOAD + /* Do Nothing */ +#endif /* IPA_UC_OFFLOAD */ + return 0; +} + +static int hdd_ipa_rm_cons_request(void) +{ + int ret = 0; + +#ifdef IPA_UC_OFFLOAD + if (ghdd_ipa->resource_loading) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: ipa resource loading in progress", + __func__); + ghdd_ipa->pending_cons_req = VOS_TRUE; + ret= -EINPROGRESS; + } else if (ghdd_ipa->resource_unloading) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, + "%s: ipa resource unloading in progress", + __func__); + ghdd_ipa->pending_cons_req = VOS_TRUE; + ret = -EPERM; + } +#endif /* IPA_UC_OFFLOAD */ + return ret; +} + +int hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets, + uint64_t rx_packets) +{ + uint32_t next_cons_bw, next_prod_bw; + struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa; + struct ipa_rm_perf_profile profile; + int ret; + + if ((!hdd_ipa_is_enabled(hdd_ctx)) || + (!hdd_ipa_is_clk_scaling_enabled(hdd_ipa))) + return 0; + + memset(&profile, 0, sizeof(profile)); + + if (tx_packets > (hdd_ctx->cfg_ini->busBandwidthHighThreshold / 2)) + next_cons_bw = hdd_ctx->cfg_ini->IpaHighBandwidthMbps; + else if (tx_packets > + (hdd_ctx->cfg_ini->busBandwidthMediumThreshold / 2)) + next_cons_bw = hdd_ctx->cfg_ini->IpaMediumBandwidthMbps; + else + next_cons_bw = hdd_ctx->cfg_ini->IpaLowBandwidthMbps; + + if (rx_packets > (hdd_ctx->cfg_ini->busBandwidthHighThreshold / 2)) + next_prod_bw = hdd_ctx->cfg_ini->IpaHighBandwidthMbps; + else if (rx_packets > + (hdd_ctx->cfg_ini->busBandwidthMediumThreshold / 2)) + next_prod_bw = hdd_ctx->cfg_ini->IpaMediumBandwidthMbps; + else + next_prod_bw = hdd_ctx->cfg_ini->IpaLowBandwidthMbps; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "CONS perf curr: %d, next: %d", + hdd_ipa->curr_cons_bw, next_cons_bw); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "PROD perf curr: %d, next: %d", + hdd_ipa->curr_prod_bw, next_prod_bw); + + if (hdd_ipa->curr_cons_bw != next_cons_bw) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "Requesting CONS perf curr: %d, next: %d", + hdd_ipa->curr_cons_bw, next_cons_bw); + profile.max_supported_bandwidth_mbps = next_cons_bw; + ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_CONS, + &profile); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "RM CONS set perf profile failed: %d", + ret); + + return ret; + } + hdd_ipa->curr_cons_bw = next_cons_bw; + hdd_ipa->stats.num_cons_perf_req++; + } + + if (hdd_ipa->curr_prod_bw != next_prod_bw) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "Requesting PROD perf curr: %d, next: %d", + hdd_ipa->curr_prod_bw, next_prod_bw); + profile.max_supported_bandwidth_mbps = next_prod_bw; + ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_PROD, + &profile); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "RM PROD set perf profile failed: %d", + ret); + return ret; + } + hdd_ipa->curr_prod_bw = next_prod_bw; + hdd_ipa->stats.num_prod_perf_req++; + } + + return 0; +} + +static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa) +{ + struct ipa_rm_create_params create_params = {0}; + int ret; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + return 0; + +#ifdef CONFIG_CNSS + cnss_init_work(&hdd_ipa->rm_work, hdd_ipa_rm_send_pkt_to_ipa); +#else + INIT_WORK(&hdd_ipa->rm_work, hdd_ipa_rm_send_pkt_to_ipa); +#endif +#ifdef IPA_UC_OFFLOAD + cnss_init_work(&hdd_ipa->uc_rm_work.work, hdd_ipa_uc_rm_notify_defer); +#endif + memset(&create_params, 0, sizeof(create_params)); + create_params.name = IPA_RM_RESOURCE_WLAN_PROD; + create_params.reg_params.user_data = hdd_ipa; + create_params.reg_params.notify_cb = hdd_ipa_rm_notify; + create_params.floor_voltage = IPA_VOLTAGE_SVS; + + ret = ipa_rm_create_resource(&create_params); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Create RM resource failed: %d", + ret); + goto setup_rm_fail; + } + + memset(&create_params, 0, sizeof(create_params)); + create_params.name = IPA_RM_RESOURCE_WLAN_CONS; + create_params.request_resource= hdd_ipa_rm_cons_request; + create_params.release_resource= hdd_ipa_rm_cons_release; + create_params.floor_voltage = IPA_VOLTAGE_SVS; + + ret = ipa_rm_create_resource(&create_params); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Create RM CONS resource failed: %d", ret); + goto delete_prod; + } + + ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD, + IPA_RM_RESOURCE_APPS_CONS); + + ret = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD, + HDD_IPA_RX_INACTIVITY_MSEC_DELAY); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Timer init failed: %d", + ret); + goto timer_init_failed; + } + + /* Set the lowest bandwidth to start with */ + ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0); + + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Set perf level failed: %d", ret); + goto set_perf_failed; + } + + vos_wake_lock_init(&hdd_ipa->wake_lock, "wlan_ipa"); +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&hdd_ipa->wake_lock_work, + hdd_ipa_wake_lock_timer_func); +#else + INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work, + hdd_ipa_wake_lock_timer_func); +#endif + adf_os_spinlock_init(&hdd_ipa->rm_lock); + hdd_ipa->rm_state = HDD_IPA_RM_RELEASED; + hdd_ipa->wake_lock_released = true; + atomic_set(&hdd_ipa->tx_ref_cnt, 0); + + return ret; + +set_perf_failed: + ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD); + +timer_init_failed: + ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS); + +delete_prod: + ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD); + +setup_rm_fail: + return ret; +} + +static void hdd_ipa_destory_rm_resource(struct hdd_ipa_priv *hdd_ipa) +{ + int ret; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + return; + + cancel_delayed_work_sync(&hdd_ipa->wake_lock_work); + vos_wake_lock_destroy(&hdd_ipa->wake_lock); + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&hdd_ipa->rm_work); +#ifdef IPA_UC_OFFLOAD + cancel_work_sync(&hdd_ipa->uc_rm_work.work); +#endif +#endif + adf_os_spinlock_destroy(&hdd_ipa->rm_lock); + + ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD); + + ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD); + if (ret) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "RM PROD resource delete failed %d", ret); + + ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS); + if (ret) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "RM CONS resource delete failed %d", ret); +} + +#define IPA_WLAN_RX_SOFTIRQ_THRESH 16 + +static void hdd_ipa_send_skb_to_network(adf_nbuf_t skb, hdd_adapter_t *adapter) +{ + int result; + + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + unsigned int cpu_index; + + if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_LOW, "Invalid adapter: 0x%p", + adapter); + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + adf_nbuf_free(skb); + return; + } + + if (hdd_ipa->hdd_ctx->isUnloadInProgress) { + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + adf_nbuf_free(skb); + return; + } + + skb->destructor = hdd_ipa_uc_rt_debug_destructor; + skb->dev = adapter->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + skb->ip_summed = CHECKSUM_NONE; + + cpu_index = wlan_hdd_get_cpu(); + + ++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; +#ifdef QCA_CONFIG_SMP + result = netif_rx_ni(skb); +#else + if (hdd_ipa->stats.num_rx_excep % IPA_WLAN_RX_SOFTIRQ_THRESH == 0) + result = netif_rx_ni(skb); + else + result = netif_rx(skb); +#endif + if (result == NET_RX_SUCCESS) + ++adapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index]; + else + ++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index]; + + HDD_IPA_INCREASE_NET_SEND_COUNT(hdd_ipa); + adapter->dev->last_rx = jiffies; +} + +VOS_STATUS hdd_ipa_process_rxt(v_VOID_t *vosContext, adf_nbuf_t rx_buf_list, + v_U8_t sta_id) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + hdd_adapter_t *adapter = NULL; + struct hdd_ipa_iface_context *iface_context = NULL; + adf_nbuf_t buf, next_buf; + uint8_t cur_cnt = 0; + struct hdd_ipa_cld_hdr *cld_hdr; + struct ipa_tx_data_desc *send_desc = NULL; + + if (!hdd_ipa_is_enabled(hdd_ipa->hdd_ctx)) + return VOS_STATUS_E_INVAL; + + adapter = hdd_ipa->hdd_ctx->sta_to_adapter[sta_id]; + if (!adapter || !adapter->ipa_context || + adapter->magic != WLAN_HDD_ADAPTER_MAGIC) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_LOW, "Invalid sta_id: %d", + sta_id); + hdd_ipa->stats.num_rx_drop++; + if (adapter) + adapter->stats.rx_dropped++; + return VOS_STATUS_E_FAILURE; + } + + iface_context = (struct hdd_ipa_iface_context *) adapter->ipa_context; + + buf = rx_buf_list; + while (buf) { + HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG, "RX data", + buf->data, 24); + + next_buf = adf_nbuf_queue_next(buf); + adf_nbuf_set_next(buf, NULL); + + adapter->stats.rx_packets++; + adapter->stats.rx_bytes += buf->len; + /* + * we want to send Rx packets to IPA only when it is + * IPV4 or IPV6 (if IPV6 is enabled). All other packets + * will be sent to network stack directly. + */ + if (!hdd_ipa_can_send_to_ipa(adapter, hdd_ipa, buf->data)) { + iface_context->stats.num_rx_prefilter++; + hdd_ipa_send_skb_to_network(buf, adapter); + buf = next_buf; + continue; + } + + cld_hdr = (struct hdd_ipa_cld_hdr *) skb_push(buf, + HDD_IPA_WLAN_CLD_HDR_LEN); + cld_hdr->sta_id = sta_id; + cld_hdr->iface_id = iface_context->iface_id; + + send_desc = hdd_ipa_alloc_data_desc(hdd_ipa, 0); + if (!send_desc) { + adf_nbuf_free(buf); /*No desc available; drop*/ + buf = next_buf; + iface_context->stats.num_rx_send_desc_err++; + continue; + } + + send_desc->priv = buf; + send_desc->pyld_buffer = buf->data; + send_desc->pyld_len = buf->len; + spin_lock_bh(&hdd_ipa->q_lock); + list_add_tail(&send_desc->link, &hdd_ipa->pend_desc_head); + hdd_ipa->pend_q_cnt++; + spin_unlock_bh(&hdd_ipa->q_lock); + cur_cnt++; + buf = next_buf; + } + + iface_context->stats.num_rx_recv += cur_cnt; + if (cur_cnt > 1) + iface_context->stats.num_rx_recv_mul++; + + if (cur_cnt > iface_context->stats.max_rx_mul) + iface_context->stats.max_rx_mul = cur_cnt; + + if (hdd_ipa->pend_q_cnt > hdd_ipa->stats.max_pend_q_cnt) + hdd_ipa->stats.max_pend_q_cnt = hdd_ipa->pend_q_cnt; + + if (cur_cnt && hdd_ipa_rm_request(hdd_ipa) == 0) { + hdd_ipa_send_pkt_to_ipa(hdd_ipa); + } + + return VOS_STATUS_SUCCESS; +} + +static void hdd_ipa_set_adapter_ip_filter(hdd_adapter_t *adapter) +{ + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + struct in_device *in_dev; + struct net_device *dev; + struct hdd_ipa_iface_context *iface_context; + + iface_context = (struct hdd_ipa_iface_context *)adapter->ipa_context; + dev = adapter->dev; + if (!dev || !iface_context) { + return; + } + /* This optimization not needed for Station mode one of + * the reason being sta-usb tethered mode + */ + if (adapter->device_mode == WLAN_HDD_INFRA_STATION) { + iface_context->ifa_address = 0; + return; + } + + + /* Get IP address */ + if (dev->priv_flags & IFF_BRIDGE_PORT) { +#ifdef WLAN_OPEN_SOURCE + rcu_read_lock(); +#endif + dev = netdev_master_upper_dev_get_rcu(adapter->dev); +#ifdef WLAN_OPEN_SOURCE + rcu_read_unlock(); +#endif + if (!dev) + return; + } + if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + ifap = &ifa->ifa_next) { + if (dev->name && !strcmp(dev->name, ifa->ifa_label)) + break; /* found */ + } + } + if(ifa && ifa->ifa_address) { + iface_context->ifa_address = ifa->ifa_address; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO,"%s: %d.%d.%d.%d", dev->name, + iface_context->ifa_address & 0x000000ff, + iface_context->ifa_address >> 8 & 0x000000ff, + iface_context->ifa_address >> 16 & 0x000000ff, + iface_context->ifa_address >> 24 & 0x000000ff); + } +} + +static int hdd_ipa_ipv4_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + hdd_adapter_list_node_t *padapter_node = NULL, *pnext = NULL; + hdd_adapter_t *padapter; + VOS_STATUS status; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "IPv4 Change detected. Updating wlan IPv4 local filters"); + + status = hdd_get_front_adapter(hdd_ipa->hdd_ctx, &padapter_node); + while (padapter_node && VOS_STATUS_SUCCESS == status) { + padapter = padapter_node->pAdapter; + if (padapter) + hdd_ipa_set_adapter_ip_filter(padapter); + + status = hdd_get_next_adapter(hdd_ipa->hdd_ctx, padapter_node, &pnext); + padapter_node = pnext; + } + return 0; +} + + +#define FW_RX_DESC_DISCARD_M 0x1 +#define FW_RX_DESC_FORWARD_M 0x2 + +static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, + unsigned long data) +{ + struct hdd_ipa_priv *hdd_ipa = NULL; + hdd_adapter_t *adapter = NULL; + struct ipa_tx_data_desc *done_desc_head, *done_desc, *tmp; + adf_nbuf_t skb; + uint8_t iface_id; + struct hdd_ipa_iface_context *iface_context; +#ifdef IPA_UC_OFFLOAD + uint8_t session_id; +#ifdef INTRA_BSS_FWD_OFFLOAD + adf_nbuf_t copy; + uint8_t fw_desc; + int ret; +#endif +#endif + adf_nbuf_t buf; + + hdd_ipa = (struct hdd_ipa_priv *)priv; + + switch (evt) { + case IPA_RECEIVE: + skb = (adf_nbuf_t) data; + +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + session_id = (uint8_t)skb->cb[0]; + iface_id = vdev_to_iface[session_id]; + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "IPA_RECEIVE: session_id=%u, iface_id=%u", + session_id, iface_id); + } else +#endif /* IPA_UC_OFFLOAD */ + { + iface_id = HDD_IPA_GET_IFACE_ID(skb->data); + } + + if (iface_id >= HDD_IPA_MAX_IFACE) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "IPA_RECEIVE: Invalid iface_id: %u", + iface_id); + HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_INFO_HIGH, + "w2i -- skb", skb->data, 8); + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + adf_nbuf_free(skb); + return; + } + + iface_context = &hdd_ipa->iface_context[iface_id]; + adapter = iface_context->adapter; + + HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG, + "w2i -- skb", skb->data, 16); +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + hdd_ipa->stats.num_rx_excep++; + skb_pull(skb, HDD_IPA_UC_WLAN_CLD_HDR_LEN); + } else +#endif /* IPA_UC_OFFLOAD */ + { + skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN); + } + + iface_context->stats.num_rx_ipa_excep++; + +#if defined(IPA_UC_OFFLOAD) && defined(INTRA_BSS_FWD_OFFLOAD) + /* Disable to forward Intra-BSS Rx packets when + * ap_isolate=1 in hostapd.conf + */ + if ((NULL != iface_context->tl_context) && + !WLANTL_disable_intrabss_fwd(iface_context->tl_context)) + { + /* + * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send + * all Rx packets to IPA uC, which need to be forwarded + * to other interface. + * And, IPA driver will send back to WLAN host driver + * through exception pipe with fw_desc field set by FW. + * Here we are checking fw_desc field for FORWARD bit + * set, and forward to Tx. Then copy to kernel stack + * only when DISCARD bit is not set. + */ + fw_desc = (uint8_t)skb->cb[1]; + + if (fw_desc & FW_RX_DESC_FORWARD_M) { + HDD_IPA_LOG( + VOS_TRACE_LEVEL_INFO, + "Forward packet to Tx (fw_desc=%d)", + fw_desc); + copy = adf_nbuf_copy(skb); + if (copy) { + hdd_ipa->ipa_tx_forward++; + ret = hdd_softap_hard_start_xmit( + (struct sk_buff *)copy, + adapter->dev); + if (ret) { + HDD_IPA_LOG( + VOS_TRACE_LEVEL_ERROR, + "Forward packet Tx fail" + ); + hdd_ipa->stats. + num_tx_bcmc_err++; + } else { + hdd_ipa->stats.num_tx_bcmc++; + } + } + } + + if (fw_desc & FW_RX_DESC_DISCARD_M) { + hdd_ipa->ipa_rx_internel_drop_count++; + hdd_ipa->ipa_rx_discard++; + adf_nbuf_free(skb); + break; + } + + } + else + { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO_HIGH, + "Intra-BSS FWD is disabled-skip forward to Tx"); + } +#endif + + hdd_ipa_send_skb_to_network(skb, adapter); + break; + case IPA_WRITE_DONE: + done_desc_head = (struct ipa_tx_data_desc *)data; + list_for_each_entry_safe(done_desc, tmp, + &done_desc_head->link, link) { + list_del(&done_desc->link); + buf = done_desc->priv; + adf_nbuf_free(buf); + hdd_ipa_free_data_desc(hdd_ipa, done_desc); + spin_lock_bh(&hdd_ipa->q_lock); + hdd_ipa->pending_hw_desc_cnt--; + spin_unlock_bh(&hdd_ipa->q_lock); + hdd_ipa->stats.num_rx_ipa_write_done++; + } + /* add anchor node also back to free list */ + hdd_ipa_free_data_desc(hdd_ipa, done_desc_head); + + hdd_ipa_send_pkt_to_ipa(hdd_ipa); + + hdd_ipa_rm_try_release(hdd_ipa); + break; + default: + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "w2i cb wrong event: 0x%x", evt); + return; + } +} + +#ifdef QCA_MDM_DEVICE +static void hdd_ipa_nbuf_cb(adf_nbuf_t skb) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "%lx", NBUF_OWNER_PRIV_DATA(skb)); + ipa_free_skb((struct ipa_rx_data *) NBUF_OWNER_PRIV_DATA(skb)); + + hdd_ipa->stats.num_tx_comp_cnt++; + + atomic_dec(&hdd_ipa->tx_ref_cnt); + + hdd_ipa_rm_try_release(hdd_ipa); +} +#endif /* QCA_MDM_DEVICE */ + +static void hdd_ipa_send_pkt_to_tl(struct hdd_ipa_iface_context *iface_context, + struct ipa_rx_data *ipa_tx_desc) +{ + struct hdd_ipa_priv *hdd_ipa = iface_context->hdd_ipa; + v_U8_t interface_id; + hdd_adapter_t *adapter = NULL; + adf_nbuf_t skb; + + adf_os_spin_lock_bh(&iface_context->interface_lock); + adapter = iface_context->adapter; + if (!adapter) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN, "Interface Down"); + ipa_free_skb(ipa_tx_desc); + iface_context->stats.num_tx_drop++; + adf_os_spin_unlock_bh(&iface_context->interface_lock); + hdd_ipa_rm_try_release(hdd_ipa); + return; + } + + /* + * During CAC period, data packets shouldn't be sent over the air so + * drop all the packets here + */ + if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->dfs_cac_block_tx) { + ipa_free_skb(ipa_tx_desc); + adf_os_spin_unlock_bh(&iface_context->interface_lock); + iface_context->stats.num_tx_cac_drop++; + hdd_ipa_rm_try_release(hdd_ipa); + return; + } + + interface_id = adapter->sessionId; + ++adapter->stats.tx_packets; + + adf_os_spin_unlock_bh(&iface_context->interface_lock); + + skb = ipa_tx_desc->skb; + + adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); +#ifdef QCA_MDM_DEVICE + NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID; + NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb; +#ifdef IPA_UC_STA_OFFLOAD + NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dma_addr + + sizeof(struct frag_header) + sizeof(struct ipa_header); + ipa_tx_desc->skb->len -= + sizeof(struct frag_header) + sizeof(struct ipa_header); +#else + NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dma_addr; +#endif + + NBUF_OWNER_PRIV_DATA(skb) = (unsigned long)ipa_tx_desc; +#endif /* QCA_MDM_DEVICE */ + + adapter->stats.tx_bytes += ipa_tx_desc->skb->len; + + skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext, + iface_context->tl_context, ipa_tx_desc->skb, + interface_id); + if (skb) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, "TLSHIM tx fail"); + ipa_free_skb(ipa_tx_desc); + iface_context->stats.num_tx_err++; + hdd_ipa_rm_try_release(hdd_ipa); + return; + } + + atomic_inc(&hdd_ipa->tx_ref_cnt); + + iface_context->stats.num_tx++; + +} + +static void hdd_ipa_pm_send_pkt_to_tl(struct work_struct *work) +{ + struct hdd_ipa_priv *hdd_ipa = container_of(work, + struct hdd_ipa_priv, pm_work); + struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL; + adf_nbuf_t skb; + uint32_t dequeued = 0; + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + + while (((skb = adf_nbuf_queue_remove(&hdd_ipa->pm_queue_head)) != + NULL)) { + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb; + + dequeued++; + + hdd_ipa_send_pkt_to_tl(pm_tx_cb->iface_context, + pm_tx_cb->ipa_tx_desc); + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + } + + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + hdd_ipa->stats.num_tx_dequeued += dequeued; + if (dequeued > hdd_ipa->stats.num_max_pm_queue) + hdd_ipa->stats.num_max_pm_queue = dequeued; +} + +static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, + unsigned long data) +{ + struct hdd_ipa_priv *hdd_ipa = NULL; + struct ipa_rx_data *ipa_tx_desc; + struct hdd_ipa_iface_context *iface_context; + adf_nbuf_t skb; + struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + iface_context = (struct hdd_ipa_iface_context *) priv; + if (evt != IPA_RECEIVE) { + skb = (adf_nbuf_t) data; + dev_kfree_skb_any(skb); + iface_context->stats.num_tx_drop++; + return; + } + ipa_tx_desc = (struct ipa_rx_data *)data; + hdd_ipa = iface_context->hdd_ipa; + + /* + * When SSR is going on or driver is unloading, just drop the packets. + * During SSR, there is no use in queueing the packets as STA has to + * connect back any way + */ + status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx); + if (0 != status) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "HDD context is not valid"); + ipa_free_skb(ipa_tx_desc); + iface_context->stats.num_tx_drop++; + return; + } + + skb = ipa_tx_desc->skb; + + HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG, "i2w", skb->data, 8); + + /* + * If PROD resource is not requested here then there may be cases where + * IPA hardware may be clocked down because of not having proper + * dependency graph between WLAN CONS and modem PROD pipes. Adding the + * workaround to request PROD resource while data is going over CONS + * pipe to prevent the IPA hardware clockdown. + */ + hdd_ipa_rm_request(hdd_ipa); + + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + /* + * If host is still suspended then queue the packets and these will be + * drained later when resume completes. When packet is arrived here and + * host is suspended, this means that there is already resume is in + * progress. + */ + if (hdd_ipa->suspended) { + adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); + pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb; + pm_tx_cb->iface_context = iface_context; + pm_tx_cb->ipa_tx_desc = ipa_tx_desc; + adf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb); + hdd_ipa->stats.num_tx_queued++; + + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + return; + } + + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + /* + * If we are here means, host is not suspended, wait for the work queue + * to finish. + */ +#ifdef WLAN_OPEN_SOURCE + flush_work(&hdd_ipa->pm_work); +#endif + + return hdd_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc); +} + +int hdd_ipa_suspend(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa; + + if (!hdd_ipa_is_enabled(hdd_ctx)) + return 0; + + /* + * Check if IPA is ready for suspend, If we are here means, there is + * high chance that suspend would go through but just to avoid any race + * condition after suspend started, these checks are conducted before + * allowing to suspend. + */ + if (atomic_read(&hdd_ipa->tx_ref_cnt)) + return -EAGAIN; + + adf_os_spin_lock_bh(&hdd_ipa->rm_lock); + + if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED) { + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + return -EAGAIN; + } + adf_os_spin_unlock_bh(&hdd_ipa->rm_lock); + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + hdd_ipa->suspended = true; + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + return 0; +} + +int hdd_ipa_resume(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa; + + if (!hdd_ipa_is_enabled(hdd_ctx)) + return 0; + + schedule_work(&hdd_ipa->pm_work); + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + hdd_ipa->suspended = false; + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + return 0; +} + +static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa) +{ + int i, ret = 0; + struct ipa_sys_connect_params *ipa; + uint32_t desc_fifo_sz; + + /* The maximum number of descriptors that can be provided to a BAM at + * once is one less than the total number of descriptors that the buffer + * can contain. + * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof + * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can + * be provided at once. + * Because of above requirement, one extra descriptor will be added to + * make sure hardware always has one descriptor. + */ + desc_fifo_sz = hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize + + sizeof(struct sps_iovec); + + /*setup TX pipes */ + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + ipa = &hdd_ipa->sys_pipe[i].ipa_sys_params; + + ipa->client = hdd_ipa_adapter_2_client[i].cons_client; + ipa->desc_fifo_sz = desc_fifo_sz; + ipa->priv = &hdd_ipa->iface_context[i]; + ipa->notify = hdd_ipa_i2w_cb; + +#ifdef IPA_UC_STA_OFFLOAD + ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN; + ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; + ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1; + ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0; + ipa->ipa_ep_cfg.hdr.hdr_additional_const_len = + HDD_IPA_UC_WLAN_8023_HDR_SIZE; + ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true; +#else + ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_TX_HDR_LEN; +#endif + ipa->ipa_ep_cfg.mode.mode = IPA_BASIC; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + ipa->keep_ipa_awake = 1; + + ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl)); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Failed for pipe %d" + " ret: %d", i, ret); + goto setup_sys_pipe_fail; + } + hdd_ipa->sys_pipe[i].conn_hdl_valid = 1; + } + +#ifndef IPA_UC_STA_OFFLOAD + /* + * Hard code it here, this can be extended if in case PROD pipe is also + * per interface. Right now there is no advantage of doing this. + */ + hdd_ipa->prod_client = IPA_CLIENT_WLAN1_PROD; + + ipa = &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].ipa_sys_params; + + ipa->client = hdd_ipa->prod_client; + + ipa->desc_fifo_sz = desc_fifo_sz; + ipa->priv = hdd_ipa; + ipa->notify = hdd_ipa_w2i_cb; + + ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; + ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_RX_HDR_LEN; + ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1; + ipa->ipa_ep_cfg.mode.mode = IPA_BASIC; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + ipa->keep_ipa_awake = 1; + + ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl)); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Failed for RX pipe: %d", + ret); + goto setup_sys_pipe_fail; + } + hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl_valid = 1; +#endif /* IPA_UC_STA_OFFLOAD */ + + return ret; + +setup_sys_pipe_fail: + + while (--i >= 0) { + ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].conn_hdl); + adf_os_mem_zero(&hdd_ipa->sys_pipe[i], + sizeof(struct hdd_ipa_sys_pipe )); + } + + return ret; +} + +/* Disconnect all the Sys pipes */ +static void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa) +{ + int ret = 0, i; + for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) { + if (hdd_ipa->sys_pipe[i].conn_hdl_valid) { + ret = ipa_teardown_sys_pipe( + hdd_ipa->sys_pipe[i].conn_hdl); + if (ret) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Failed: %d", + ret); + + hdd_ipa->sys_pipe[i].conn_hdl_valid = 0; + } + } +} + +static int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, + struct hdd_ipa_iface_context *iface_context) +{ + struct ipa_tx_intf tx_intf; + struct ipa_rx_intf rx_intf; + struct ipa_ioc_tx_intf_prop *tx_prop = NULL; + struct ipa_ioc_rx_intf_prop *rx_prop = NULL; + char *ifname = iface_context->adapter->dev->name; + + char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX]; + char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX]; + + int num_prop = 1; + int ret = 0; + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) + num_prop++; + + /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */ + tx_prop = adf_os_mem_alloc(NULL, + sizeof(struct ipa_ioc_tx_intf_prop) * num_prop); + if (!tx_prop) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "tx_prop allocation failed"); + goto register_interface_fail; + } + + /* Allocate RX properties, 1 each for IPv4 & IPv6 */ + rx_prop = adf_os_mem_alloc(NULL, + sizeof(struct ipa_ioc_rx_intf_prop) * num_prop); + if (!rx_prop) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "rx_prop allocation failed"); + goto register_interface_fail; + } + + adf_os_mem_zero(&tx_intf, sizeof(tx_intf)); + adf_os_mem_zero(&rx_intf, sizeof(rx_intf)); + + snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV4_NAME_EXT); + snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV6_NAME_EXT); + + rx_prop[IPA_IP_v4].ip = IPA_IP_v4; + rx_prop[IPA_IP_v4].src_pipe = iface_context->prod_client; +#ifdef IPA_UC_OFFLOAD + rx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; +#endif + + rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA; + + /* + * Interface ID is 3rd byte in the CLD header. Add the meta data and + * mask to identify the interface in IPA hardware + */ + rx_prop[IPA_IP_v4].attrib.meta_data = + htonl(iface_context->adapter->sessionId<< 16); + rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000); + + rx_intf.num_props++; + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { + rx_prop[IPA_IP_v6].ip = IPA_IP_v6; + rx_prop[IPA_IP_v6].src_pipe = iface_context->prod_client; +#ifdef IPA_UC_OFFLOAD + rx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; +#endif + + rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA; + rx_prop[IPA_IP_v4].attrib.meta_data = + htonl(iface_context->adapter->sessionId<< 16); + rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000); + + rx_intf.num_props++; + } + + tx_prop[IPA_IP_v4].ip = IPA_IP_v4; +#ifdef IPA_UC_OFFLOAD + tx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; + tx_prop[IPA_IP_v4].dst_pipe = IPA_CLIENT_WLAN1_CONS; + tx_prop[IPA_IP_v4].alt_dst_pipe = iface_context->cons_client; +#else + tx_prop[IPA_IP_v4].dst_pipe = iface_context->cons_client; +#endif + strlcpy(tx_prop[IPA_IP_v4].hdr_name, ipv4_hdr_name, + IPA_RESOURCE_NAME_MAX); + tx_intf.num_props++; + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { + tx_prop[IPA_IP_v6].ip = IPA_IP_v6; +#ifdef IPA_UC_OFFLOAD + tx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; + tx_prop[IPA_IP_v6].dst_pipe = IPA_CLIENT_WLAN1_CONS; + tx_prop[IPA_IP_v6].alt_dst_pipe = iface_context->cons_client; +#else + tx_prop[IPA_IP_v6].dst_pipe = iface_context->cons_client; +#endif + strlcpy(tx_prop[IPA_IP_v6].hdr_name, ipv6_hdr_name, + IPA_RESOURCE_NAME_MAX); + tx_intf.num_props++; + } + + tx_intf.prop = tx_prop; + rx_intf.prop = rx_prop; + + /* Call the ipa api to register interface */ + ret = ipa_register_intf(ifname, &tx_intf, &rx_intf); + +register_interface_fail: + adf_os_mem_free(tx_prop); + adf_os_mem_free(rx_prop); + return ret; +} + +static void hdd_remove_ipa_header(char *name) +{ + struct ipa_ioc_get_hdr hdrlookup; + int ret = 0, len; + struct ipa_ioc_del_hdr *ipa_hdr; + + adf_os_mem_zero(&hdrlookup, sizeof(hdrlookup)); + strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name)); + ret = ipa_get_hdr(&hdrlookup); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Hdr deleted already %s, %d", + name, ret); + return; + } + + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "hdl: 0x%x", hdrlookup.hdl); + len = sizeof(struct ipa_ioc_del_hdr) + sizeof(struct ipa_hdr_del)*1; + ipa_hdr = (struct ipa_ioc_del_hdr *) adf_os_mem_alloc(NULL, len); + if (ipa_hdr == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "ipa_hdr allocation failed"); + return; + } + ipa_hdr->num_hdls = 1; + ipa_hdr->commit = 0; + ipa_hdr->hdl[0].hdl = hdrlookup.hdl; + ipa_hdr->hdl[0].status = -1; + ret = ipa_del_hdr(ipa_hdr); + if (ret != 0) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Delete header failed: %d", + ret); + + adf_os_mem_free(ipa_hdr); +} + + +static int hdd_ipa_add_header_info(struct hdd_ipa_priv *hdd_ipa, + struct hdd_ipa_iface_context *iface_context, uint8_t *mac_addr) +{ + hdd_adapter_t *adapter = iface_context->adapter; + char *ifname; + struct ipa_ioc_add_hdr *ipa_hdr = NULL; + int ret = -EINVAL; + struct hdd_ipa_tx_hdr *tx_hdr = NULL; +#ifdef IPA_UC_OFFLOAD + struct hdd_ipa_uc_tx_hdr *uc_tx_hdr = NULL; +#endif /* IPA_UC_OFFLOAD */ + + ifname = adapter->dev->name; + + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "Add Partial hdr: %s, %pM", + ifname, mac_addr); + + /* dynamically allocate the memory to add the hdrs */ + ipa_hdr = adf_os_mem_alloc(NULL, sizeof(struct ipa_ioc_add_hdr) + + sizeof(struct ipa_hdr_add)); + if (!ipa_hdr) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: ipa_hdr allocation failed", ifname); + ret = -ENOMEM; + goto end; + } + + ipa_hdr->commit = 0; + ipa_hdr->num_hdrs = 1; + + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { +#ifdef IPA_UC_OFFLOAD + uc_tx_hdr = (struct hdd_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr; + memcpy(uc_tx_hdr, &ipa_uc_tx_hdr, HDD_IPA_UC_WLAN_TX_HDR_LEN); + memcpy(uc_tx_hdr->eth.h_source, mac_addr, ETH_ALEN); + uc_tx_hdr->ipa_hd.vdev_id = iface_context->adapter->sessionId; + HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG, + "ifname=%s, vdev_id=%d", + ifname, uc_tx_hdr->ipa_hd.vdev_id); + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV4_NAME_EXT); + ipa_hdr->hdr[0].hdr_len = HDD_IPA_UC_WLAN_TX_HDR_LEN; + ipa_hdr->hdr[0].type = IPA_HDR_L2_ETHERNET_II; + ipa_hdr->hdr[0].is_partial = 1; + ipa_hdr->hdr[0].hdr_hdl = 0; + ipa_hdr->hdr[0].is_eth2_ofst_valid = 1; + ipa_hdr->hdr[0].eth2_ofst = HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET; + + ret = ipa_add_hdr(ipa_hdr); +#endif /* IPA_UC_OFFLOAD */ + } else { + tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr; + + /* Set the Source MAC */ + memcpy(tx_hdr, &ipa_tx_hdr, HDD_IPA_WLAN_TX_HDR_LEN); + memcpy(tx_hdr->eth.h_source, mac_addr, ETH_ALEN); + + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV4_NAME_EXT); + ipa_hdr->hdr[0].hdr_len = HDD_IPA_WLAN_TX_HDR_LEN; + ipa_hdr->hdr[0].is_partial = 1; + ipa_hdr->hdr[0].hdr_hdl = 0; + ipa_hdr->hdr[0].is_eth2_ofst_valid = 1; + ipa_hdr->hdr[0].eth2_ofst = HDD_IPA_WLAN_HDR_DES_MAC_OFFSET; + + /* Set the type to IPV4 in the header*/ + tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IP); + + ret = ipa_add_hdr(ipa_hdr); + } + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "%s IPv4 add hdr failed: %d", + ifname, ret); + goto end; + } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: IPv4 hdr_hdl: 0x%x", + ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl); + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV6_NAME_EXT); + +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + /* Set the type to IPV6 in the header*/ + uc_tx_hdr = (struct hdd_ipa_uc_tx_hdr *)ipa_hdr->hdr[0].hdr; + uc_tx_hdr->eth.h_proto = cpu_to_be16(ETH_P_IPV6); + } else +#endif /* IPA_UC_OFFLOAD */ + { + /* Set the type to IPV6 in the header*/ + tx_hdr = (struct hdd_ipa_tx_hdr *)ipa_hdr->hdr[0].hdr; + tx_hdr->llc_snap.eth_type = cpu_to_be16(ETH_P_IPV6); + } + + ret = ipa_add_hdr(ipa_hdr); + + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPv6 add hdr failed: %d", + ifname, ret); + goto clean_ipv4_hdr; + } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: IPv6 hdr_hdl: 0x%x", + ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl); + } + + adf_os_mem_free(ipa_hdr); + + return ret; + +clean_ipv4_hdr: + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV4_NAME_EXT); + hdd_remove_ipa_header(ipa_hdr->hdr[0].name); +end: + if(ipa_hdr) + adf_os_mem_free(ipa_hdr); + + return ret; +} + +static void hdd_ipa_clean_hdr(hdd_adapter_t *adapter) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + int ret; + char name_ipa[IPA_RESOURCE_NAME_MAX]; + + /* Remove the headers */ + snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", + adapter->dev->name, HDD_IPA_IPV4_NAME_EXT); + hdd_remove_ipa_header(name_ipa); + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa)) { + snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", + adapter->dev->name, HDD_IPA_IPV6_NAME_EXT); + hdd_remove_ipa_header(name_ipa); + } + /* unregister the interface with IPA */ + ret = ipa_deregister_intf(adapter->dev->name); + if (ret) + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: ipa_deregister_intf fail: %d", + adapter->dev->name, ret); +} + +static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context) +{ + if (iface_context == NULL) + return; + + hdd_ipa_clean_hdr(iface_context->adapter); + + adf_os_spin_lock_bh(&iface_context->interface_lock); + iface_context->adapter->ipa_context = NULL; + iface_context->adapter = NULL; + iface_context->tl_context = NULL; + adf_os_spin_unlock_bh(&iface_context->interface_lock); + iface_context->ifa_address = 0; + if (!iface_context->hdd_ipa->num_iface) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "NUM INTF 0, Invalid"); + VOS_ASSERT(0); + } + iface_context->hdd_ipa->num_iface--; +} + + +static int hdd_ipa_setup_iface(struct hdd_ipa_priv *hdd_ipa, + hdd_adapter_t *adapter, uint8_t sta_id) +{ + struct hdd_ipa_iface_context *iface_context = NULL; + void *tl_context = NULL; + int i, ret = 0; + + /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during + * channel change indication. Since these indications are sent by lower + * layer as SAP updates and IPA doesn't have to do anything for these + * updates so ignoring! + */ + if (WLAN_HDD_SOFTAP == adapter->device_mode && adapter->ipa_context) + return 0; + + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + if (hdd_ipa->iface_context[i].adapter == NULL) { + iface_context = &(hdd_ipa->iface_context[i]); + break; + } + } + + if (iface_context == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "All the IPA interfaces are in use"); + ret = -ENOMEM; + goto end; + } + + + adapter->ipa_context = iface_context; + iface_context->adapter = adapter; + iface_context->sta_id = sta_id; + tl_context = tl_shim_get_vdev_by_sta_id(hdd_ipa->hdd_ctx->pvosContext, + sta_id); + + if (tl_context == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Not able to get TL context sta_id: %d", + sta_id); + ret = -EINVAL; + goto end; + } + + iface_context->tl_context = tl_context; + + ret = hdd_ipa_add_header_info(hdd_ipa, iface_context, + adapter->dev->dev_addr); + + if (ret) + goto end; + + /* Configure the TX and RX pipes filter rules */ + ret = hdd_ipa_register_interface(hdd_ipa, iface_context); + if (ret) + goto cleanup_header; + + hdd_ipa->num_iface++; + return ret; + +cleanup_header: + + hdd_ipa_clean_hdr(adapter); +end: + if (iface_context) + hdd_ipa_cleanup_iface(iface_context); + return ret; +} + + +static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type) +{ + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "msg type:%d, len:%d", type, len); + ghdd_ipa->stats.num_free_msg++; + adf_os_mem_free(buff); +} + +#ifdef IPA_UC_STA_OFFLOAD +int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx, bool mcc_mode) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + struct ipa_msg_meta meta; + struct ipa_wlan_msg *msg; + int ret; + + if (!hdd_ipa_uc_sta_is_enabled(hdd_ipa)) + return -EINVAL; + + if (!mcc_mode) { + /* Flush TxRx queue for each adapter before switch to SCC */ + status = hdd_get_front_adapter (hdd_ctx, &adapter_node); + while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { + pAdapter = adapter_node->pAdapter; + if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_SOFTAP) { + hddLog(LOG1, + "MCC->SCC: Flush TxRx queue(d_mode %s(%d))", + hdd_device_mode_to_string( + pAdapter->device_mode), + pAdapter->device_mode); + hdd_deinit_tx_rx(pAdapter); + } + status = hdd_get_next_adapter( + hdd_ctx, adapter_node, &next); + adapter_node = next; + } + } + + /* Send SCC/MCC Switching event to IPA */ + meta.msg_len = sizeof(*msg); + msg = adf_os_mem_alloc(NULL, meta.msg_len); + if (msg == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, "msg allocation failed"); + return -ENOMEM; + } + + meta.msg_type = mcc_mode ? WLAN_SWITCH_TO_MCC : WLAN_SWITCH_TO_SCC; + hddLog(VOS_TRACE_LEVEL_INFO, "ipa_send_msg(Evt:%d)", meta.msg_type); + + ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn); + + if (ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, "ipa_send_msg(Evt:%d) - fail=%d", + meta.msg_type, ret); + adf_os_mem_free(msg); + } + + return ret; +} +#endif + +static inline char *hdd_ipa_wlan_event_to_str(enum ipa_wlan_event event) +{ + switch(event) { + case WLAN_CLIENT_CONNECT: return "WLAN_CLIENT_CONNECT"; + case WLAN_CLIENT_DISCONNECT: return "WLAN_CLIENT_DISCONNECT"; + case WLAN_CLIENT_POWER_SAVE_MODE: return "WLAN_CLIENT_POWER_SAVE_MODE"; + case WLAN_CLIENT_NORMAL_MODE: return "WLAN_CLIENT_NORMAL_MODE"; + case SW_ROUTING_ENABLE: return "SW_ROUTING_ENABLE"; + case SW_ROUTING_DISABLE: return "SW_ROUTING_DISABLE"; + case WLAN_AP_CONNECT: return "WLAN_AP_CONNECT"; + case WLAN_AP_DISCONNECT: return "WLAN_AP_DISCONNECT"; + case WLAN_STA_CONNECT: return "WLAN_STA_CONNECT"; + case WLAN_STA_DISCONNECT: return "WLAN_STA_DISCONNECT"; + case WLAN_CLIENT_CONNECT_EX: return "WLAN_CLIENT_CONNECT_EX"; + + case IPA_WLAN_EVENT_MAX: + default: + return "UNKNOWN"; + } +} + +#ifdef IPA_UC_OFFLOAD +static void hdd_ipa_uc_offload_enable_disable(hdd_adapter_t *adapter, + tANI_U32 offload_type, tANI_U32 enable) +{ + struct sir_ipa_offload_enable_disable ipa_offload_enable_disable; + + /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during + * channel change indication. Since these indications are sent by lower + * layer as SAP updates and IPA doesn't have to do anything for these + * updates so ignoring! + */ + if (adapter->ipa_context) + return; + + vos_mem_zero(&ipa_offload_enable_disable, + sizeof(ipa_offload_enable_disable)); + ipa_offload_enable_disable.offload_type = offload_type; + ipa_offload_enable_disable.vdev_id = adapter->sessionId; + ipa_offload_enable_disable.enable = enable; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: offload_type=%d, vdev_id=%d, enable=%d", __func__, + ipa_offload_enable_disable.offload_type, + ipa_offload_enable_disable.vdev_id, + ipa_offload_enable_disable.enable); + + if (eHAL_STATUS_SUCCESS != + sme_ipa_offload_enable_disable(WLAN_HDD_GET_HAL_CTX(adapter), + adapter->sessionId, &ipa_offload_enable_disable)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to enable IPA offload \ + (offload_type=%d, vdev_id=%d, enable=%d)", __func__, + ipa_offload_enable_disable.offload_type, + ipa_offload_enable_disable.vdev_id, + ipa_offload_enable_disable.enable); + } +} +#endif + +int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, + enum ipa_wlan_event type, uint8_t *mac_addr) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + struct ipa_msg_meta meta; + struct ipa_wlan_msg *msg; + struct ipa_wlan_msg_ex *msg_ex = NULL; + int ret; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: %s evt, MAC: %pM sta_id: %d", + adapter->dev->name, hdd_ipa_wlan_event_to_str(type), + mac_addr, + sta_id); + + if (type >= IPA_WLAN_EVENT_MAX) + return -EINVAL; + + if (WARN_ON(is_zero_ether_addr(mac_addr))) + return -EINVAL; + + if (!hdd_ipa || !hdd_ipa_is_enabled(hdd_ipa->hdd_ctx)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "IPA OFFLOAD NOT ENABLED"); + return -EINVAL; + } + +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa) && +#ifdef IPA_UC_STA_OFFLOAD + !hdd_ipa_uc_sta_is_enabled(hdd_ipa) && +#endif + (WLAN_HDD_SOFTAP != adapter->device_mode)) { + return 0; + } + + /* During IPA UC resource loading/unloading + * new event issued. + * Store event seperatly and handle later */ + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + if (hdd_ipa->resource_loading) { + v_SIZE_t pending_event_count; + struct ipa_uc_pending_event *pending_event = NULL; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA resource load inprogress", __func__); + + vos_list_size(&hdd_ipa->pending_event, + &pending_event_count); + if (pending_event_count >= MAX_PENDING_EVENT_COUNT) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Reached max pending event count", + __func__); + vos_list_remove_front(&hdd_ipa->pending_event, + (vos_list_node_t **)&pending_event); + } else { + pending_event = (struct ipa_uc_pending_event *) + vos_mem_malloc(sizeof( + struct ipa_uc_pending_event)); + } + + if (!pending_event) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Pending event memory alloc fail"); + return -ENOMEM; + } + pending_event->adapter = adapter; + pending_event->sta_id = sta_id; + pending_event->type = type; + vos_mem_copy(pending_event->mac_addr, + mac_addr, + VOS_MAC_ADDR_SIZE); + vos_list_insert_back(&hdd_ipa->pending_event, + &pending_event->node); + return 0; + } else if (hdd_ipa->resource_unloading) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: IPA resource unload inprogress", __func__); + return 0; + } + } +#endif /* IPA_UC_OFFLOAD */ + + hdd_ipa->stats.event[type]++; + + switch (type) { + case WLAN_STA_CONNECT: +#if defined(IPA_UC_OFFLOAD) && defined(IPA_UC_STA_OFFLOAD) + /* STA alreadu connected and without disconnect, connect again + * This is Roaming scenario */ + if (hdd_ipa->sta_connected) { + hdd_ipa_cleanup_iface(adapter->ipa_context); + } + + if ((hdd_ipa_uc_sta_is_enabled(hdd_ipa)) && + (!hdd_ipa->sta_connected)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 1); + } + + vos_lock_acquire(&hdd_ipa->event_lock); + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED", + msg_ex->name, meta.msg_type); + } else if ((!hdd_ipa->sap_num_connected_sta) && + (!hdd_ipa->sta_connected)) { + /* Enable IPA UC TX PIPE when STA connected */ + ret = hdd_ipa_uc_handle_first_con(hdd_ipa); + if (ret) { + vos_lock_release(&hdd_ipa->event_lock); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "handle 1st con ret %d", ret); + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 0); + goto end; + } + } +#endif + ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id); + if (ret) { +#ifdef IPA_UC_OFFLOAD + vos_lock_release(&hdd_ipa->event_lock); + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 0); +#endif /* IPA_UC_OFFLOAD */ + goto end; + } + +#ifdef IPA_UC_OFFLOAD + vdev_to_iface[adapter->sessionId] = + ((struct hdd_ipa_iface_context *) + (adapter->ipa_context))->iface_id; +#ifdef IPA_UC_STA_OFFLOAD + hdd_ipa->sta_connected = 1; +#endif + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + break; + + case WLAN_AP_CONNECT: + /* For DFS channel we get two start_bss event (before and after + * CAC). Also when ACS range includes both DFS and non DFS + * channels, we could possibly change channel many times due to + * RADAR detection and chosen channel may not be a DFS channels. + * So dont return error here. Just discard the event. + */ + if (adapter->ipa_context) + return 0; + +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_AP_RX_DATA_OFFLOAD, 1); + } + vos_lock_acquire(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id); + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Evt: %d, Interface setup failed", + msg_ex->name, meta.msg_type); +#ifdef IPA_UC_OFFLOAD + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + goto end; + } + +#ifdef IPA_UC_OFFLOAD + vdev_to_iface[adapter->sessionId] = + ((struct hdd_ipa_iface_context *) + (adapter->ipa_context))->iface_id; + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + break; + + case WLAN_STA_DISCONNECT: +#ifdef IPA_UC_OFFLOAD + vos_lock_acquire(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + hdd_ipa_cleanup_iface(adapter->ipa_context); + +#if defined(IPA_UC_OFFLOAD) && defined(IPA_UC_STA_OFFLOAD) + if (!hdd_ipa->sta_connected) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Evt: %d, STA already disconnected", + msg_ex->name, meta.msg_type); + vos_lock_release(&hdd_ipa->event_lock); + return -EINVAL; + } + hdd_ipa->sta_connected = 0; + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: IPA UC OFFLOAD NOT ENABLED", + msg_ex->name); + } else { + /* Disable IPA UC TX PIPE when STA disconnected */ + if ((!hdd_ipa->sap_num_connected_sta) || + ((!hdd_ipa->num_iface) && + (HDD_IPA_UC_NUM_WDI_PIPE == + hdd_ipa->activated_fw_pipe))) { + hdd_ipa_uc_handle_last_discon(hdd_ipa); + } + } + + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 0); + vdev_to_iface[adapter->sessionId] = HDD_IPA_MAX_IFACE; + } +#endif +#ifdef IPA_UC_OFFLOAD + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + break; + + case WLAN_AP_DISCONNECT: + if (!adapter->ipa_context) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Evt: %d, SAP already disconnected", + msg_ex->name, meta.msg_type); + return -EINVAL; + } + +#ifdef IPA_UC_OFFLOAD + vos_lock_acquire(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + hdd_ipa_cleanup_iface(adapter->ipa_context); + +#ifdef IPA_UC_OFFLOAD + if ((!hdd_ipa->num_iface) && + (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe)) { + if (hdd_ipa->hdd_ctx->isUnloadInProgress) { + /* We disable WDI pipes directly here since + * IPA_OPCODE_TX/RX_SUSPEND message will not be + * processed when unloding WLAN driver is in + * progress + */ + hdd_ipa_uc_disable_pipes(hdd_ipa); + } else { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "NO INTF left, " + "but still pipe clean up"); + hdd_ipa_uc_handle_last_discon(hdd_ipa); + } + } + + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_AP_RX_DATA_OFFLOAD, 0); + vdev_to_iface[adapter->sessionId] = HDD_IPA_MAX_IFACE; + } + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + break; + + case WLAN_CLIENT_CONNECT_EX: + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%d %d", + adapter->dev->ifindex, sta_id); + +#ifdef IPA_UC_OFFLOAD + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED", + adapter->dev->name, meta.msg_type); + return 0; + } + + vos_lock_acquire(&hdd_ipa->event_lock); + if (hdd_ipa_uc_find_add_assoc_sta(hdd_ipa, + VOS_TRUE, sta_id)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: STA ID %d found, not valid", + adapter->dev->name, sta_id); + vos_lock_release(&hdd_ipa->event_lock); + return 0; + } + vos_lock_release(&hdd_ipa->event_lock); +#endif + + meta.msg_type = type; + meta.msg_len = (sizeof(struct ipa_wlan_msg_ex) + + sizeof(struct ipa_wlan_hdr_attrib_val)); + msg_ex = adf_os_mem_alloc (NULL, meta.msg_len); + + if (msg_ex == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "msg_ex allocation failed"); + return -ENOMEM; + } + strlcpy(msg_ex->name, adapter->dev->name, + IPA_RESOURCE_NAME_MAX); + msg_ex->num_of_attribs = 1; + msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR; +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + msg_ex->attribs[0].offset = + HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET; + } else +#endif /* IPA_UC_OFFLOAD */ + { + msg_ex->attribs[0].offset = + HDD_IPA_WLAN_HDR_DES_MAC_OFFSET; + } + memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr, + IPA_MAC_ADDR_SIZE); + + ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn); + + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: Evt: %d : %d", + msg_ex->name, meta.msg_type, ret); + adf_os_mem_free(msg_ex); + return ret; + } + hdd_ipa->stats.num_send_msg++; +#ifdef IPA_UC_OFFLOAD + vos_lock_acquire(&hdd_ipa->event_lock); + /* Enable IPA UC Data PIPEs when first STA connected */ + if ((0 == hdd_ipa->sap_num_connected_sta) +#ifdef IPA_UC_STA_OFFLOAD + && (!hdd_ipa_uc_sta_is_enabled(hdd_ipa) + || !hdd_ipa->sta_connected) +#endif + && (VOS_TRUE == hdd_ipa->uc_loaded) + ) { + ret = hdd_ipa_uc_handle_first_con(hdd_ipa); + if (ret) { + vos_lock_release(&hdd_ipa->event_lock); + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: handle 1st con ret %d", + adapter->dev->name, ret); + return ret; + } + } + + hdd_ipa->sap_num_connected_sta++; + + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + return ret; + + case WLAN_CLIENT_DISCONNECT: +#ifdef IPA_UC_OFFLOAD + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: IPA UC OFFLOAD NOT ENABLED", + msg_ex->name); + return 0; + } + + vos_lock_acquire(&hdd_ipa->event_lock); + if (!hdd_ipa_uc_find_add_assoc_sta(hdd_ipa, + VOS_FALSE, + sta_id)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "%s: STA ID %d NOT found, not valid", + msg_ex->name, sta_id); + vos_lock_release(&hdd_ipa->event_lock); + return 0; + } + hdd_ipa->sap_num_connected_sta--; + /* Disable IPA UC TX PIPE when last STA disconnected */ + if (!hdd_ipa->sap_num_connected_sta +#ifdef IPA_UC_STA_OFFLOAD + && (!hdd_ipa_uc_sta_is_enabled(hdd_ipa) || + !hdd_ipa->sta_connected) +#endif + && (VOS_TRUE == hdd_ipa->uc_loaded) + && (VOS_FALSE == hdd_ipa->resource_unloading) + && (HDD_IPA_UC_NUM_WDI_PIPE == + hdd_ipa->activated_fw_pipe) + ) { + hdd_ipa_uc_handle_last_discon(hdd_ipa); + } + vos_lock_release(&hdd_ipa->event_lock); +#endif /* IPA_UC_OFFLOAD */ + break; + + default: + return 0; + } + + meta.msg_len = sizeof(struct ipa_wlan_msg); + msg = adf_os_mem_alloc(NULL, meta.msg_len); + if (msg == NULL) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "msg allocation failed"); + return -ENOMEM; + } + + meta.msg_type = type; + strlcpy(msg->name, adapter->dev->name, IPA_RESOURCE_NAME_MAX); + memcpy(msg->mac_addr, mac_addr, ETH_ALEN); + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: Evt: %d", + msg->name, meta.msg_type); + + ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn); + + if (ret) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, "%s: Evt: %d fail:%d", + msg->name, meta.msg_type, ret); + adf_os_mem_free(msg); + return ret; + } + + hdd_ipa->stats.num_send_msg++; + +end: + return ret; +} + + +static void hdd_ipa_rx_pipe_desc_free(void) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + uint32_t i = 0, max_desc_cnt; + struct ipa_tx_data_desc *desc, *tmp; + + max_desc_cnt = hdd_ipa->hw_desc_cnt * HDD_IPA_DESC_BUFFER_RATIO; + + spin_lock_bh(&hdd_ipa->q_lock); + + list_for_each_entry_safe(desc, tmp, &hdd_ipa->pend_desc_head, link) { + list_del(&desc->link); + adf_nbuf_free(desc->priv); + spin_unlock_bh(&hdd_ipa->q_lock); + hdd_ipa_free_data_desc(hdd_ipa, desc); + spin_lock_bh(&hdd_ipa->q_lock); + } + + list_for_each_entry_safe(desc, tmp, &hdd_ipa->free_desc_head, link) { + list_del(&desc->link); + spin_unlock_bh(&hdd_ipa->q_lock); + adf_os_mem_free(desc); + spin_lock_bh(&hdd_ipa->q_lock); + i++; + } + spin_unlock_bh(&hdd_ipa->q_lock); + + if (i != max_desc_cnt) + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "free desc leak: %u, %u", i, + max_desc_cnt); + +} + + +static int hdd_ipa_rx_pipe_desc_alloc(void) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + uint32_t i, max_desc_cnt; + int ret = 0; + struct ipa_tx_data_desc *tmp_desc; + + hdd_ipa->hw_desc_cnt = IPA_NUM_OF_FIFO_DESC( + hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize); + max_desc_cnt = hdd_ipa->hw_desc_cnt * HDD_IPA_DESC_BUFFER_RATIO; + + spin_lock_init(&hdd_ipa->q_lock); + + INIT_LIST_HEAD(&hdd_ipa->free_desc_head); + INIT_LIST_HEAD(&hdd_ipa->pend_desc_head); + hdd_ipa->freeq_cnt = max_desc_cnt; + for (i = 0; i < max_desc_cnt; i++) { + tmp_desc = adf_os_mem_alloc(NULL, + sizeof(struct ipa_tx_data_desc)); + if (!tmp_desc) { + ret = -ENOMEM; + + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "Descriptor allocation failed"); + goto fail; + } + spin_lock_bh(&hdd_ipa->q_lock); + list_add_tail(&tmp_desc->link, &hdd_ipa->free_desc_head); + spin_unlock_bh(&hdd_ipa->q_lock); + } + + + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "Desc sz:%d h_desc_cnt:%d freeq_cnt:%u", + hdd_ipa->hdd_ctx->cfg_ini->IpaDescSize, hdd_ipa->hw_desc_cnt, + hdd_ipa->freeq_cnt); + return ret; +fail: + hdd_ipa_rx_pipe_desc_free(); + return ret; +} + +static inline char *hdd_ipa_rm_state_to_str(enum hdd_ipa_rm_state state) +{ + switch (state) { + case HDD_IPA_RM_RELEASED: return "RELEASED"; + case HDD_IPA_RM_GRANT_PENDING: return "GRANT_PENDING"; + case HDD_IPA_RM_GRANTED: return "GRANTED"; + } + + return "UNKNOWN"; +} + +static ssize_t hdd_ipa_debugfs_read_ipa_stats(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct hdd_ipa_priv *hdd_ipa = file->private_data; + char *buf; + unsigned int len = 0, buf_len = 4096; + ssize_t ret_cnt; + int i; + struct hdd_ipa_iface_context *iface_context = NULL; +#define HDD_IPA_STATS(_buf, _len, _hdd_ipa, _name) \ + scnprintf(_buf, _len, "%30s: %llu\n", #_name, _hdd_ipa->stats._name) + +#define HDD_IPA_IFACE_STATS(_buf, _len, _iface, _name) \ + scnprintf(_buf, _len, "%30s: %llu\n", #_name, _iface->stats._name) + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += scnprintf(buf + len, buf_len - len, + "\nhw_desc_cnt/pending_cnt: %u/%u, " + "freeq_cnt/pend_q_cnt: %u/%u\n", hdd_ipa->hw_desc_cnt, + hdd_ipa->pending_hw_desc_cnt, hdd_ipa->freeq_cnt, + hdd_ipa->pend_q_cnt); + + len += scnprintf(buf + len, buf_len - len, + "\n<------------------ WLAN EVENTS STATS" + " ------------------>\n"); + for (i = 0; i < IPA_WLAN_EVENT_MAX; i++) { + len += scnprintf(buf + len, buf_len - len, "%30s: %u\n", + hdd_ipa_wlan_event_to_str(i), + hdd_ipa->stats.event[i]); + } + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_send_msg); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_free_msg); + + if (!hdd_ipa_is_rm_enabled(hdd_ipa)) + goto skip; + + len += scnprintf(buf + len, buf_len - len, + "\n<------------------ IPA RM STATS" + " ------------------>\n"); + + len += scnprintf(buf + len, buf_len - len, "%30s: %s\n", "rm_state", + hdd_ipa_rm_state_to_str(hdd_ipa->rm_state)); + + len += scnprintf(buf + len, buf_len - len, "%30s: %s\n", "wake_lock", + hdd_ipa->wake_lock_released ? "RELEASED" : "ACQUIRED"); + + len += scnprintf(buf + len, buf_len - len, "%30s: %d\n", "tx_ref_cnt", + atomic_read(&hdd_ipa->tx_ref_cnt)); + + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_rm_grant); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_rm_release); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rm_grant_imm); + + if (!hdd_ipa_is_clk_scaling_enabled(hdd_ipa)) + goto skip; + + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_cons_perf_req); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_prod_perf_req); + len += scnprintf(buf + len, buf_len - len, "%30s: %u\n", "curr_prod_bw", + hdd_ipa->curr_prod_bw); + len += scnprintf(buf + len, buf_len - len, "%30s: %u\n", "curr_cons_bw", + hdd_ipa->curr_cons_bw); + +skip: + len += scnprintf(buf + len, buf_len - len, + "\n<------------------ IPA STATS" + " ------------------>\n"); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, num_rx_drop); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rx_ipa_tx_dp); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rx_ipa_splice); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rx_ipa_loop); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rx_ipa_tx_dp_err); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rx_ipa_write_done); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_max_ipa_tx_mul); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_rx_ipa_hw_maxed_out); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + max_pend_q_cnt); + + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_tx_comp_cnt); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_tx_queued); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_tx_dequeued); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_max_pm_queue); + + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_freeq_empty); + len += HDD_IPA_STATS(buf + len, buf_len - len, hdd_ipa, + num_pri_freeq_empty); + + len += scnprintf(buf + len, buf_len - len, + "\n<------------------ IPA IFACE STATS" + " ------------------>\n"); + + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + + iface_context = &hdd_ipa->iface_context[i]; + + if (iface_context->adapter == NULL) + continue; + + len += scnprintf(buf + len, buf_len - len, + "\n%s: iface_id: %u, sta_id: %u," + " device_mode: %u\n", + iface_context->adapter->dev->name, + iface_context->iface_id, + iface_context->sta_id, + iface_context->adapter->device_mode); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_tx); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_tx_drop); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_tx_err); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_tx_cac_drop); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_rx_prefilter); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_rx_ipa_excep); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_rx_recv); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_rx_recv_mul); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, num_rx_send_desc_err); + len += HDD_IPA_IFACE_STATS(buf + len, buf_len - len, + iface_context, max_rx_mul); + } + + ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); + + kfree(buf); + return ret_cnt; +#undef HDD_IPA_STATS +#undef HDD_IPA_IFACE_STATS +} + +static ssize_t hdd_ipa_debugfs_write_ipa_stats(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct hdd_ipa_priv *hdd_ipa = file->private_data; + struct hdd_ipa_iface_context *iface_context = NULL; + int ret; + uint32_t val; + int i; + + ret = kstrtou32_from_user(user_buf, count, 0, &val); + + if (ret) + return ret; + + if (val == 0) { + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + iface_context = &hdd_ipa->iface_context[i]; + memset(&iface_context->stats, 0, + sizeof(iface_context->stats)); + } + + memset(&hdd_ipa->stats, 0, sizeof(hdd_ipa->stats)); + } + + return count; +} + +static const struct file_operations fops_ipa_stats = { + .read = hdd_ipa_debugfs_read_ipa_stats, + .write = hdd_ipa_debugfs_write_ipa_stats, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + + +static int hdd_ipa_debugfs_init(struct hdd_ipa_priv *hdd_ipa) +{ +#ifdef WLAN_OPEN_SOURCE + hdd_ipa->debugfs_dir = debugfs_create_dir("cld", + hdd_ipa->hdd_ctx->wiphy->debugfsdir); + if (!hdd_ipa->debugfs_dir) + return -ENOMEM; + + debugfs_create_file("ipa-stats", S_IRUSR, hdd_ipa->debugfs_dir, + hdd_ipa, &fops_ipa_stats); +#endif + return 0; +} + +static void hdd_ipa_debugfs_remove(struct hdd_ipa_priv *hdd_ipa) +{ +#ifdef WLAN_OPEN_SOURCE + debugfs_remove_recursive(hdd_ipa->debugfs_dir); +#endif +} + +/** +* hdd_ipa_init() - Allocate hdd_ipa resources, ipa pipe resource and register +* wlan interface with IPA module. +* @param +* hdd_ctx : [in] pointer to HDD context +* @return : VOS_STATUS_E_FAILURE - Errors +* : VOS_STATUS_SUCCESS - Ok +*/ +VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = NULL; + int ret=0, i; + struct hdd_ipa_iface_context *iface_context = NULL; +#ifdef IPA_UC_OFFLOAD + struct ipa_wdi_uc_ready_params uc_ready_param; + struct ipa_msg_meta meta; + struct ipa_wlan_msg *ipa_msg; +#endif /* IPA_UC_OFFLOAD */ + + if (!hdd_ipa_is_enabled(hdd_ctx)) + return VOS_STATUS_SUCCESS; + + hdd_ipa = adf_os_mem_alloc(NULL, sizeof(*hdd_ipa)); + if (!hdd_ipa) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_FATAL, "hdd_ipa allocation failed"); + goto fail_setup_rm; + } + adf_os_mem_zero(hdd_ipa, sizeof(*hdd_ipa)); + + hdd_ctx->hdd_ipa = hdd_ipa; + ghdd_ipa = hdd_ipa; + hdd_ipa->hdd_ctx = hdd_ctx; + hdd_ipa->num_iface = 0; + + /* Create the interface context */ + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + iface_context = &hdd_ipa->iface_context[i]; + iface_context->hdd_ipa = hdd_ipa; + iface_context->cons_client = + hdd_ipa_adapter_2_client[i].cons_client; + iface_context->prod_client = + hdd_ipa_adapter_2_client[i].prod_client; + iface_context->iface_id = i; + iface_context->adapter = NULL; + adf_os_spinlock_init(&iface_context->interface_lock); + } + +#ifdef CONFIG_CNSS + cnss_init_work(&hdd_ipa->pm_work, hdd_ipa_pm_send_pkt_to_tl); +#else + INIT_WORK(&hdd_ipa->pm_work, hdd_ipa_pm_send_pkt_to_tl); +#endif + adf_os_spinlock_init(&hdd_ipa->pm_lock); + adf_nbuf_queue_init(&hdd_ipa->pm_queue_head); + + ret = hdd_ipa_setup_rm(hdd_ipa); + if (ret) + goto fail_setup_rm; + +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + hdd_ipa_uc_rt_debug_init(hdd_ctx); + vos_mem_zero(&hdd_ipa->stats, sizeof(hdd_ipa->stats)); + hdd_ipa->sap_num_connected_sta = 0; + hdd_ipa->ipa_tx_packets_diff = 0; + hdd_ipa->ipa_rx_packets_diff = 0; + hdd_ipa->ipa_p_tx_packets = 0; + hdd_ipa->ipa_p_rx_packets = 0; + hdd_ipa->resource_loading = VOS_FALSE; + hdd_ipa->resource_unloading = VOS_FALSE; +#ifdef IPA_UC_STA_OFFLOAD + hdd_ipa->sta_connected = 0; + + /* Setup IPA sys_pipe for MCC */ + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa)) { + ret = hdd_ipa_setup_sys_pipe(hdd_ipa); + if (ret) + goto fail_create_sys_pipe; + } +#endif + hdd_ipa->wdi_enabled = VOS_FALSE; + hdd_ipa->uc_loaded = VOS_FALSE; + hdd_ipa->ipa_pipes_down = true; + uc_ready_param.priv = (void *)hdd_ipa; + uc_ready_param.notify = hdd_ipa_uc_loaded_uc_cb; + if (ipa_uc_reg_rdyCB(&uc_ready_param)) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "UC Ready CB register fail"); + goto fail_setup_rm; + } + if (TRUE == uc_ready_param.is_uC_ready) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "UC Ready"); + hdd_ipa->uc_loaded = VOS_TRUE; + } else { + /* WDI disable message to IPA */ + meta.msg_len = sizeof(*ipa_msg); + ipa_msg = adf_os_mem_alloc(NULL, meta.msg_len); + if (ipa_msg == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "msg allocation failed"); + goto fail_setup_rm; + } + meta.msg_type = WLAN_WDI_DISABLE; + hddLog(VOS_TRACE_LEVEL_INFO, + "ipa_send_msg(Evt:%d)", meta.msg_type); + ret = ipa_send_msg(&meta, ipa_msg, hdd_ipa_msg_free_fn); + if (ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "ipa_send_msg(Evt:%d) - fail=%d", + meta.msg_type, ret); + adf_os_mem_free(ipa_msg); + goto fail_setup_rm; + } + } + hdd_ipa_uc_ol_init(hdd_ctx); + } else +#endif /* IPA_UC_OFFLOAD */ + { + ret = hdd_ipa_setup_sys_pipe(hdd_ipa); + if (ret) + goto fail_create_sys_pipe; + + ret = hdd_ipa_rx_pipe_desc_alloc(); + if (ret) + goto fail_alloc_rx_pipe_desc; + } + + ret = hdd_ipa_debugfs_init(hdd_ipa); + if (ret) + goto fail_alloc_rx_pipe_desc; + + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) { + hdd_ipa->ipv4_notifier.notifier_call = hdd_ipa_ipv4_changed; + ret = register_inetaddr_notifier(&hdd_ipa->ipv4_notifier); + if (ret) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "WLAN IPv4 local filter register failed"); + } + + return VOS_STATUS_SUCCESS; +fail_alloc_rx_pipe_desc: + hdd_ipa_rx_pipe_desc_free(); +fail_create_sys_pipe: + hdd_ipa_destory_rm_resource(hdd_ipa); +fail_setup_rm: + if (hdd_ipa) + adf_os_mem_free(hdd_ipa); + + return VOS_STATUS_E_FAILURE; +} + +#ifdef IPA_UC_OFFLOAD +/** +* hdd_ipa_cleanup_pending_event() - Cleanup IPA pending event list +* @param +* hdd_ipa : [in] pointer to HDD IPA struct +* @return : none +*/ +void hdd_ipa_cleanup_pending_event(struct hdd_ipa_priv *hdd_ipa) +{ + struct ipa_uc_pending_event *pending_event = NULL; + + while(vos_list_remove_front(&hdd_ipa->pending_event, + (vos_list_node_t **)&pending_event) == VOS_STATUS_SUCCESS) { + vos_mem_free(pending_event); + } + + vos_list_destroy(&hdd_ipa->pending_event); +} +#endif + +VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa; + int i; + struct hdd_ipa_iface_context *iface_context = NULL; + adf_nbuf_t skb; + struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL; + + if (!hdd_ipa_is_enabled(hdd_ctx)) + return VOS_STATUS_SUCCESS; + + if (!hdd_ipa_uc_is_enabled(hdd_ipa)) { + unregister_inetaddr_notifier(&hdd_ipa->ipv4_notifier); + hdd_ipa_teardown_sys_pipe(hdd_ipa); + } + +#ifdef IPA_UC_STA_OFFLOAD + /* Teardown IPA sys_pipe for MCC */ + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa)) + hdd_ipa_teardown_sys_pipe(hdd_ipa); +#endif + + hdd_ipa_destory_rm_resource(hdd_ipa); + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&hdd_ipa->pm_work); +#endif + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + + while (((skb = adf_nbuf_queue_remove(&hdd_ipa->pm_queue_head)) != + NULL)) { + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb; + ipa_free_skb(pm_tx_cb->ipa_tx_desc); + + adf_os_spin_lock_bh(&hdd_ipa->pm_lock); + } + adf_os_spin_unlock_bh(&hdd_ipa->pm_lock); + + adf_os_spinlock_destroy(&hdd_ipa->pm_lock); + + /* Destroy the interface lock */ + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + iface_context = &hdd_ipa->iface_context[i]; + adf_os_spinlock_destroy(&iface_context->interface_lock); + } + + hdd_ipa_debugfs_remove(hdd_ipa); + + /* This should never hit but still make sure that there are no pending + * descriptor in IPA hardware + */ + if (hdd_ipa->pending_hw_desc_cnt != 0) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "IPA Pending write done: %d Waiting!", + hdd_ipa->pending_hw_desc_cnt); + + for (i = 0; hdd_ipa->pending_hw_desc_cnt != 0 && i < 10; i++) { + usleep_range(100, 100); + } + + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "IPA Pending write done: desc: %d %s(%d)!", + hdd_ipa->pending_hw_desc_cnt, + hdd_ipa->pending_hw_desc_cnt == 0 ? "completed" + : "leak", i); + } + +#ifdef IPA_UC_OFFLOAD + if (hdd_ipa_uc_is_enabled(hdd_ipa)) { + if (ipa_uc_dereg_rdyCB()) + HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, + "UC Ready CB deregister fail"); + hdd_ipa_uc_rt_debug_deinit(hdd_ctx); + if (VOS_TRUE == hdd_ipa->uc_loaded) { + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Disconnect TX PIPE", __func__); + ipa_disconnect_wdi_pipe(hdd_ipa->tx_pipe_handle); + HDD_IPA_LOG(VOS_TRACE_LEVEL_INFO, + "%s: Disconnect RX PIPE", __func__); + ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle); + } + vos_lock_destroy(&hdd_ipa->event_lock); + hdd_ipa_cleanup_pending_event(hdd_ipa); + vos_lock_destroy(&hdd_ipa->ipa_lock); +#ifdef WLAN_OPEN_SOURCE + for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) { + cancel_work_sync(&hdd_ipa->uc_op_work[i].work); + hdd_ipa->uc_op_work[i].msg = NULL; + } +#endif + } else +#endif /* IPA_UC_OFFLOAD */ + { + hdd_ipa_rx_pipe_desc_free(); + } + + adf_os_mem_free(hdd_ipa); + hdd_ctx->hdd_ipa = NULL; + + return VOS_STATUS_SUCCESS; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c new file mode 100644 index 000000000000..58d731f47940 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -0,0 +1,15923 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/*======================================================================== + + \file wlan_hdd_main.c + + \brief WLAN Host Device Driver implementation + + ========================================================================*/ + +/**========================================================================= + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 04/5/09 Shailender Created module. + 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module + 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure + ==========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#ifdef WLAN_FEATURE_LPSS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlan_hdd_trace.h" +#include "vos_types.h" +#include "vos_trace.h" + +#include +#include +#include +#include +#include +#include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_p2p.h" +#include +#include "sapApi.h" +#include +#include +#include +#ifdef MSM_PLATFORM +#ifdef CONFIG_CNSS +#include +#endif +#endif +#include +#include +#include "cfgApi.h" +#include "wlan_hdd_dev_pwr.h" +#include "qwlan_version.h" +#include "wlan_qct_wda.h" +#include "wlan_hdd_tdls.h" +#ifdef FEATURE_WLAN_CH_AVOID +#ifdef CONFIG_CNSS +#include +#endif +#include "regdomain_common.h" + +extern int hdd_hostapd_stop (struct net_device *dev); +void hdd_ch_avoid_cb(void *hdd_context,void *indi_param); +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef WLAN_FEATURE_NAN +#include "wlan_hdd_nan.h" +#endif /* WLAN_FEATURE_NAN */ + +#include "wlan_hdd_debugfs.h" +#include "epping_main.h" +#include "wlan_hdd_memdump.h" + +#include +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#elif defined(HIF_SDIO) +#include "if_ath_sdio.h" +#endif +#include "wma.h" +#include "ol_fw.h" +#include "wlan_hdd_ocb.h" +#include "wlan_hdd_tsf.h" + +#if defined(LINUX_QCMBR) +#define SIOCIOCTLTX99 (SIOCDEVPRIVATE+13) +#endif + +#ifdef QCA_ARP_SPOOFING_WAR +#include "ol_if_athvar.h" +#define HDD_ARP_PACKET_TYPE_OFFSET 12 +#endif + +#ifdef MODULE +#define WLAN_MODULE_NAME module_name(THIS_MODULE) +#else +#define WLAN_MODULE_NAME "wlan" +#endif + +#ifdef TIMER_MANAGER +#define TIMER_MANAGER_STR " +TIMER_MANAGER" +#else +#define TIMER_MANAGER_STR "" +#endif + +#ifdef MEMORY_DEBUG +#define MEMORY_DEBUG_STR " +MEMORY_DEBUG" +#else +#define MEMORY_DEBUG_STR "" +#endif + +#define DISABLE_KRAIT_IDLE_PS_VAL 1 +#ifdef IPA_UC_OFFLOAD +/* If IPA UC data path is enabled, target should reserve extra tx descriptors + * for IPA WDI data path. + * Then host data path should allow less TX packet pumping in case + * IPA WDI data path enabled */ +#define WLAN_TFC_IPAUC_TX_DESC_RESERVE 100 +#endif /* IPA_UC_OFFLOAD */ + +/* the Android framework expects this param even though we don't use it */ +#define BUF_LEN 20 +static char fwpath_buffer[BUF_LEN]; +static struct kparam_string fwpath = { + .string = fwpath_buffer, + .maxlen = BUF_LEN, +}; + +static char *country_code; +static int enable_11d = -1; +static int enable_dfs_chan_scan = -1; + +#ifndef MODULE +static int wlan_hdd_inited; +#endif + +/* + * spinlock for synchronizing asynchronous request/response + * (full description of use in wlan_hdd_main.h) + */ +DEFINE_SPINLOCK(hdd_context_lock); + +/* + * The rate at which the driver sends RESTART event to supplicant + * once the function 'vos_wlanRestart()' is called + * + */ +#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */ +#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */ + +/* + * Size of Driver command strings from upper layer + */ +#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */ +#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define TID_MIN_VALUE 0 +#define TID_MAX_VALUE 15 +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +/* + * Maximum buffer size used for returning the data back to user space + */ +#define WLAN_MAX_BUF_SIZE 1024 +#define WLAN_PRIV_DATA_MAX_LEN 8192 +/* + * Driver miracast parameters 0-Disabled + * 1-Source, 2-Sink + */ +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0 +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2 + +/* + * When ever we need to print IBSSPEERINFOALL for more than 16 STA + * we will split the printing. + */ +#define NUM_OF_STA_DATA_TO_PRINT 16 + +/* + * Android DRIVER command structures + */ +struct android_wifi_reassoc_params { + unsigned char bssid[18]; + int channel; +}; + +#define ANDROID_WIFI_ACTION_FRAME_SIZE 1040 +struct android_wifi_af_params { + unsigned char bssid[18]; + int channel; + int dwell_time; + int len; + unsigned char data[ANDROID_WIFI_ACTION_FRAME_SIZE]; +} ; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define WLAN_HDD_MAX_TCP_PORT 65535 +#define WLAN_WAIT_TIME_READY_TO_EXTWOW 2000 +#endif + +#define AUTO_SUSPEND_DELAY_MS 1500 + +static vos_wake_lock_t wlan_wake_lock; +/* set when SSR is needed after unload */ +static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED; + +#define WOW_MAX_FILTER_LISTS 1 +#define WOW_MAX_FILTERS_PER_LIST 4 +#define WOW_MIN_PATTERN_SIZE 6 +#define WOW_MAX_PATTERN_SIZE 64 + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) +static const struct wiphy_wowlan_support wowlan_support_reg_init = { + .flags = WIPHY_WOWLAN_ANY | + WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE | + WIPHY_WOWLAN_RFKILL_RELEASE, + .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST, + .pattern_min_len = WOW_MIN_PATTERN_SIZE, + .pattern_max_len = WOW_MAX_PATTERN_SIZE, +}; +#endif + +/* Internal function declarations */ +static int hdd_driver_init(void); +static void hdd_driver_exit(void); + +void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback); + +struct completion wlan_start_comp; +#ifdef QCA_WIFI_FTM +extern int hdd_ftm_start(hdd_context_t *pHddCtx); +extern int hdd_ftm_stop(hdd_context_t *pHddCtx); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +v_VOID_t wlan_hdd_auto_shutdown_cb(v_VOID_t); +#endif + +/* Store WLAN driver version info in a global variable such that crash debugger + can extract it from driver debug symbol and crashdump for post processing */ +tANI_U8 g_wlan_driver_version[ ] = QWLAN_VERSIONSTR; + +/** + * hdd_device_mode_to_string() - return string conversion of device mode + * @device_mode: device mode + * + * This utility function helps log string conversion of device mode. + * + * Return: string conversion of device mode, if match found; + * "Unknown" otherwise. + */ +const char* hdd_device_mode_to_string(uint8_t device_mode) +{ + switch (device_mode) { + CASE_RETURN_STRING(WLAN_HDD_INFRA_STATION); + CASE_RETURN_STRING(WLAN_HDD_SOFTAP); + CASE_RETURN_STRING(WLAN_HDD_P2P_CLIENT); + CASE_RETURN_STRING(WLAN_HDD_P2P_GO); + CASE_RETURN_STRING(WLAN_HDD_MONITOR); + CASE_RETURN_STRING(WLAN_HDD_FTM); + CASE_RETURN_STRING(WLAN_HDD_IBSS); + CASE_RETURN_STRING(WLAN_HDD_P2P_DEVICE); + CASE_RETURN_STRING(WLAN_HDD_OCB); + default: + return "Unknown"; + } +} + +#ifdef QCA_LL_TX_FLOW_CT + +/** + * wlan_hdd_clean_tx_flow_control_timer - Function cleans tx flow control timer + * @hddctx: pointer to hddctx + * @hdd_adapter_t: pointer to hdd_adapter_t + * + * Function deregister's, destroy tx flow control timer + * + * Return: None + */ +void wlan_hdd_clean_tx_flow_control_timer(hdd_context_t *hddctx, + hdd_adapter_t *adapter) +{ + WLANTL_DeRegisterTXFlowControl(hddctx->pvosContext, + adapter->sessionId); + if (adapter->tx_flow_timer_initialized == VOS_TRUE) { + vos_timer_destroy(&adapter->tx_flow_control_timer); + adapter->tx_flow_timer_initialized = VOS_FALSE; + } +} + +#endif + +/** + * wlan_hdd_find_opclass() - Find operating class for a channel + * @hal: handler to HAL + * @channel: channel id + * @bw_offset: bandwidth offset + * + * Function invokes sme api to find the operating class + * + * Return: operating class + */ +uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, + uint8_t bw_offset) +{ + uint8_t opclass = 0; + + sme_get_opclass(hal, channel, bw_offset, &opclass); + return opclass; +} + +#ifdef CONFIG_CNSS +/** + * hdd_request_pm_qos() - vote performance management qos + * @val: Memory latency usec requirement to ensure + * + * To endure CPU hardware wake up, vote to performance management module. + * Current voting will prevent hardware power collapse then can reduce CPU + * wake up latency. + * Performance QoS voting will ensure WLAN performance. + * Start up time and throughput + * + * Return: none + */ +static inline void hdd_request_pm_qos(int val) +{ + cnss_request_pm_qos(val); +} + +/** + * hdd_remove_pm_qos() - Cancel performance voting + * + * Not need to stay wake up CPU any more. Remove voting to release CPU + * + * Return: none + */ +static inline void hdd_remove_pm_qos(void) +{ + cnss_remove_pm_qos(); +} +#else +/** + * hdd_request_pm_qos() - vote performance management qos + * @val: Memory latency usec requirement to ensure + * + * To endure CPU hardware wake up, vote to performance management module. + * Current voting will prevent hardware power collapse then can reduce CPU + * wake up latency. + * Performance QoS votign will ensure WLAN performance. + * Start up time and throughput + * + * Return: none + */ +static inline void hdd_request_pm_qos(int val) +{ +} + +/** + * hdd_remove_pm_qos() - Cancel performance voting + * + * Not need to stay wake up CPU any more. Remove voting to release CPU + * + * Return: none + */ +static inline void hdd_remove_pm_qos(void) +{ +} +#endif + +#ifdef FEATURE_GREEN_AP + +static void hdd_wlan_green_ap_timer_fn(void *phddctx) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)phddctx; + hdd_green_ap_ctx_t *green_ap; + + if (0 != wlan_hdd_validate_context(pHddCtx)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return; + } + green_ap = pHddCtx->green_ap_ctx; + + if (green_ap) + hdd_wlan_green_ap_mc(pHddCtx, green_ap->ps_event); +} + +static VOS_STATUS hdd_wlan_green_ap_attach(hdd_context_t *pHddCtx) +{ + hdd_green_ap_ctx_t *green_ap; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + ENTER(); + + green_ap = vos_mem_malloc(sizeof(hdd_green_ap_ctx_t)); + + if (!green_ap) { + hddLog(LOGP, FL("Memory allocation for Green-AP failed!")); + status = VOS_STATUS_E_NOMEM; + goto error; + } + + vos_mem_zero((void *)green_ap, sizeof(*green_ap)); + green_ap->pHddContext = pHddCtx; + pHddCtx->green_ap_ctx = green_ap; + + green_ap->ps_state = GREEN_AP_PS_OFF_STATE; + green_ap->ps_event = 0; + green_ap->num_nodes = 0; + green_ap->ps_on_time = GREEN_AP_PS_ON_TIME; + green_ap->ps_delay_time = GREEN_AP_PS_DELAY_TIME; + + vos_timer_init(&green_ap->ps_timer, + VOS_TIMER_TYPE_SW, + hdd_wlan_green_ap_timer_fn, + (void *)pHddCtx); + +error: + + EXIT(); + return status; +} + +static VOS_STATUS hdd_wlan_green_ap_deattach(hdd_context_t *pHddCtx) +{ + hdd_green_ap_ctx_t *green_ap = pHddCtx->green_ap_ctx; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + ENTER(); + + if (green_ap == NULL) { + hddLog(LOG1, FL("Green-AP is not enabled")); + status = VOS_STATUS_E_NOSUPPORT; + goto done; + } + + /* check if the timer status is destroyed */ + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&green_ap->ps_timer)) + { + vos_timer_stop(&green_ap->ps_timer); + } + + /* Destroy the Green AP timer */ + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy( + &green_ap->ps_timer))) + { + hddLog(LOG1, FL("Cannot deallocate Green-AP's timer")); + } + + /* release memory */ + vos_mem_zero((void *)green_ap, sizeof(*green_ap)); + vos_mem_free(green_ap); + pHddCtx->green_ap_ctx = NULL; + +done: + + EXIT(); + return status; +} + +static void hdd_wlan_green_ap_update(hdd_context_t *pHddCtx, + hdd_green_ap_ps_state_t state, + hdd_green_ap_event_t event) +{ + hdd_green_ap_ctx_t *green_ap = pHddCtx->green_ap_ctx; + + green_ap->ps_state = state; + green_ap->ps_event = event; +} + +static int hdd_wlan_green_ap_enable(hdd_adapter_t *pHostapdAdapter, + v_U8_t enable) +{ + int ret = 0; + + hddLog(LOG1, "%s: Set Green-AP val: %d", __func__, enable); + + ret = process_wma_set_command( + (int)pHostapdAdapter->sessionId, + (int)WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, + enable, + DBG_CMD); + + return ret; +} + +void hdd_wlan_green_ap_mc(hdd_context_t *pHddCtx, + hdd_green_ap_event_t event) +{ + hdd_green_ap_ctx_t *green_ap = pHddCtx->green_ap_ctx; + hdd_adapter_t *pAdapter = NULL; + + if (green_ap == NULL) + return ; + + hddLog(LOG1, "%s: Green-AP event: %d, state: %d, num_nodes: %d", + __func__, event, green_ap->ps_state, green_ap->num_nodes); + + /* handle the green ap ps event */ + switch(event) { + case GREEN_AP_PS_START_EVENT: + green_ap->ps_enable = 1; + break; + + case GREEN_AP_PS_STOP_EVENT: + if (!(hdd_get_concurrency_mode() & VOS_SAP)) + green_ap->ps_enable = 0; + break; + + case GREEN_AP_ADD_STA_EVENT: + green_ap->num_nodes++; + break; + + case GREEN_AP_DEL_STA_EVENT: + if (green_ap->num_nodes) + green_ap->num_nodes--; + break; + + case GREEN_AP_PS_ON_EVENT: + case GREEN_AP_PS_WAIT_EVENT: + break; + + default: + hddLog(LOGE, "%s: invalid event %d", __func__, event); + break; + } + + /* Confirm that power save is enabled before doing state transitions */ + if (!green_ap->ps_enable) { + hddLog(VOS_TRACE_LEVEL_INFO, FL("Green-AP is disabled")); + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_IDLE_STATE, GREEN_AP_PS_WAIT_EVENT); + goto done; + } + + pAdapter = hdd_get_adapter (pHddCtx, WLAN_HDD_SOFTAP ); + + if (pAdapter == NULL) { + hddLog(LOGE, FL("Green-AP no SAP adapter")); + goto done; + } + + /* handle the green ap ps state */ + switch(green_ap->ps_state) { + case GREEN_AP_PS_IDLE_STATE: + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_OFF_STATE, GREEN_AP_PS_WAIT_EVENT); + break; + + case GREEN_AP_PS_OFF_STATE: + if (!green_ap->num_nodes) { + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_WAIT_STATE, GREEN_AP_PS_WAIT_EVENT); + vos_timer_start(&green_ap->ps_timer, + green_ap->ps_delay_time); + } + break; + + case GREEN_AP_PS_WAIT_STATE: + if (!green_ap->num_nodes) { + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_ON_STATE, GREEN_AP_PS_WAIT_EVENT); + + hdd_wlan_green_ap_enable(pAdapter, 1); + + if (green_ap->ps_on_time) { + hdd_wlan_green_ap_update(pHddCtx, + 0, GREEN_AP_PS_WAIT_EVENT); + vos_timer_start(&green_ap->ps_timer, + green_ap->ps_on_time); + } + } else { + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_OFF_STATE, GREEN_AP_PS_WAIT_EVENT); + } + break; + + case GREEN_AP_PS_ON_STATE: + if (green_ap->num_nodes) { + if (hdd_wlan_green_ap_enable(pAdapter, 0)) { + hddLog(LOGE, FL("FAILED TO SET GREEN-AP mode")); + goto done; + } + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_OFF_STATE, GREEN_AP_PS_WAIT_EVENT); + } else if ((green_ap->ps_event == GREEN_AP_PS_WAIT_EVENT) && + (green_ap->ps_on_time)) { + + /* ps_on_time timeout, switch to ps off */ + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_WAIT_STATE, GREEN_AP_PS_ON_EVENT); + + if (hdd_wlan_green_ap_enable(pAdapter, 0)) { + hddLog(LOGE, FL("FAILED TO SET GREEN-AP mode")); + goto done; + } + + vos_timer_start(&green_ap->ps_timer, + green_ap->ps_delay_time); + } + break; + + default: + hddLog(LOGE, "%s: invalid state %d", __func__, green_ap->ps_state); + hdd_wlan_green_ap_update(pHddCtx, + GREEN_AP_PS_OFF_STATE, GREEN_AP_PS_WAIT_EVENT); + break; + } + +done: + return; +} + +#endif /* FEATURE_GREEN_AP */ + +/** + * hdd_lost_link_info_cb() - callback function to get lost link information + * @context: HDD context + * @lost_link_info: lost link information + * + * Return: none + */ +static void hdd_lost_link_info_cb(void *context, + struct sir_lost_link_info *lost_link_info) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context; + int status; + hdd_adapter_t *adapter; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, "%s: HDD context is not valid", __func__); + return; + } + + if (NULL == lost_link_info) { + hddLog(LOGE, "%s: lost_link_info is NULL", __func__); + return; + } + + adapter = hdd_get_adapter_by_vdev(hdd_ctx, lost_link_info->vdev_id); + if (NULL == adapter) { + hddLog(LOGE, "%s: invalid adapter", __func__); + return; + } + + adapter->rssi_on_disconnect = lost_link_info->rssi; + hddLog(LOG1, "%s: rssi on disconnect %d", + __func__, adapter->rssi_on_disconnect); +} + +/** + * __hdd_smps_force_mode_cb() - callback for smps force mode + * event + * @context: HDD context + * @smps_mode_event: smps force mode event info + * + * Return: none + */ +static void __hdd_smps_force_mode_cb(void *context, + struct sir_smps_force_mode_event *smps_mode_event) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context; + int status; + hdd_adapter_t *adapter; + + ENTER(); + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return; + + if (NULL == smps_mode_event) { + hddLog(LOGE, FL("smps_mode_event is NULL")); + return; + } + + adapter = hdd_get_adapter_by_vdev(hdd_ctx, smps_mode_event->vdev_id); + if (NULL == adapter) { + hddLog(LOGE, FL("Invalid adapter")); + return; + } + + adapter->smps_force_mode_status = smps_mode_event->status; + + complete(&adapter->smps_force_mode_comp_var); + + hddLog(LOG1, FL("status %d vdev_id: %d"), + smps_mode_event->status, smps_mode_event->vdev_id); +} + +/** + * hdd_smps_force_mode_cb() - Wrapper to protect + * __hdd_smps_force_mode_cb callback for smps force mode event + * @context: HDD context + * @smps_mode_event: smps force mode event info + * + * Return: none + */ +static void hdd_smps_force_mode_cb(void *context, + struct sir_smps_force_mode_event *smps_mode_event) +{ + vos_ssr_protect(__func__); + __hdd_smps_force_mode_cb(context, smps_mode_event); + vos_ssr_unprotect(__func__); + +} + +#if defined (FEATURE_WLAN_MCC_TO_SCC_SWITCH) || defined (FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) +/**--------------------------------------------------------------------------- + + \brief wlan_hdd_restart_sap() - This function is used to restart SAP in + driver internally + + \param - ap_adapter - Pointer to SAP hdd_adapter_t structure + + \return - void + + --------------------------------------------------------------------------*/ + +static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *pHddApCtx; + hdd_hostapd_state_t *pHostapdState; + VOS_STATUS vos_status; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter); +#ifdef CFG80211_DEL_STA_V2 + struct station_del_parameters delStaParams; +#endif + tsap_Config_t *pConfig; + + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + pConfig = &ap_adapter->sessionCtx.ap.sapConfig; + + mutex_lock(&pHddCtx->sap_lock); + if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { +#ifdef CFG80211_DEL_STA_V2 + delStaParams.mac = NULL; + delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4; + delStaParams.reason_code = eCsrForcedDeauthSta; + wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev, + &delStaParams); +#else + wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev, + NULL); +#endif + hdd_cleanup_actionframe(pHddCtx, ap_adapter); + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); + vos_event_reset(&pHostapdState->stop_bss_event); + + if ( VOS_STATUS_SUCCESS == WLANSAP_StopBss( +#ifdef WLAN_FEATURE_MBSSID + pHddApCtx->sapContext +#else + (WLAN_HDD_GET_CTX(ap_adapter))->pvosContext +#endif + )) { + vos_status = vos_wait_single_event(&pHostapdState->stop_bss_event, + 10000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + goto end; + } + } + clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode); + hddLog(LOGE, FL("SAP Stop Success")); + + if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) { + hddLog(LOGE, FL("SAP Not able to set AP IEs")); + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ALL); + goto end; + } + + if (WLANSAP_StartBss( +#ifdef WLAN_FEATURE_MBSSID + pHddApCtx->sapContext, +#else + pHddCtx->pvosContext, +#endif + hdd_hostapd_SAPEventCB, &pHddApCtx->sapConfig, + (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) { + hddLog(LOGE, FL("SAP Start Bss fail")); + goto end; + } + + hddLog(LOG1, FL("Waiting for SAP to start")); + vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("SAP Start failed")); + goto end; + } + hddLog(LOGE, FL("SAP Start Success")); + set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode); + pHostapdState->bCommit = TRUE; + } +end: + mutex_unlock(&pHddCtx->sap_lock); + return; +} +#endif + +static int __hdd_netdev_notifier_call(struct notifier_block * nb, + unsigned long state, + void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) + struct netdev_notifier_info *dev_notif_info = data; + struct net_device *dev = dev_notif_info->dev; +#else + struct net_device *dev = data; +#endif + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + + //Make sure that this callback corresponds to our device. + if ((strncmp(dev->name, "wlan", 4)) && + (strncmp(dev->name, "p2p", 3))) + return NOTIFY_DONE; + + if ((pAdapter->magic != WLAN_HDD_ADAPTER_MAGIC) && + (pAdapter->dev != dev)) { + hddLog(LOGE, FL("device adapter is not matching!!!")); + return NOTIFY_DONE; + } + + if (!dev->ieee80211_ptr) { + hddLog(LOGE, FL("ieee80211_ptr is NULL!!!")); + return NOTIFY_DONE; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__); + VOS_ASSERT(0); + return NOTIFY_DONE; + } + if (pHddCtx->isLogpInProgress) + return NOTIFY_DONE; + + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu", + __func__, dev->name, state); + + switch (state) { + case NETDEV_REGISTER: + break; + + case NETDEV_UNREGISTER: + break; + + case NETDEV_UP: +#ifdef FEATURE_WLAN_CH_AVOID + sme_ChAvoidUpdateReq(pHddCtx->hHal); +#endif + break; + + case NETDEV_DOWN: + break; + + case NETDEV_CHANGE: + if(TRUE == pAdapter->isLinkUpSvcNeeded) + complete(&pAdapter->linkup_event_var); + break; + + case NETDEV_GOING_DOWN: + if( pAdapter->scan_info.mScanPending != FALSE ) + { + unsigned long rc; + INIT_COMPLETION(pAdapter->scan_info.abortscan_event_var); + hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + rc = wait_for_completion_timeout( + &pAdapter->scan_info.abortscan_event_var, + msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN)); + if (!rc) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout occurred while waiting for abortscan", + __func__); + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Scan is not Pending from user" , __func__); + } + break; + + default: + break; + } + + return NOTIFY_DONE; +} + +/** + * hdd_netdev_notifier_call() - netdev notifier callback function + * @nb: pointer to notifier block + * @state: state + * @ndev: ndev pointer + * + * Return: 0 on success, error number otherwise. + */ +static int hdd_netdev_notifier_call(struct notifier_block * nb, + unsigned long state, + void *ndev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_netdev_notifier_call(nb, state, ndev); + vos_ssr_unprotect(__func__); + + return ret; +} + +struct notifier_block hdd_netdev_notifier = { + .notifier_call = hdd_netdev_notifier_call, +}; + +/*--------------------------------------------------------------------------- + * Function definitions + *-------------------------------------------------------------------------*/ +void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx); +void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx); +//variable to hold the insmod parameters +static int con_mode; +#ifndef MODULE +/* current con_mode - used only for statically linked driver + * con_mode is changed by user space to indicate a mode change which will + * result in calling the module exit and init functions. The module + * exit function will clean up based on the value of con_mode prior to it + * being changed by user space. So curr_con_mode records the current con_mode + * for exit when con_mode becomes the next mode for init + */ +static int curr_con_mode; +#endif + +/**--------------------------------------------------------------------------- + + \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable + + Called immediately after the cfg.ini is read in order to configure + the desired trace levels. + + \param - moduleId - module whose trace level is being configured + \param - bitmask - bitmask of log levels to be enabled + + \return - void + + --------------------------------------------------------------------------*/ +static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask) +{ + VOS_TRACE_LEVEL level; + + /* if the bitmask is the default value, then a bitmask was not + specified in cfg.ini, so leave the logging level alone (it + will remain at the "compiled in" default value) */ + if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask) + { + return; + } + + /* a mask was specified. start by disabling all logging */ + vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0); + + /* now cycle through the bitmask until all "set" bits are serviced */ + level = VOS_TRACE_LEVEL_FATAL; + while (0 != bitmask) + { + if (bitmask & 1) + { + vos_trace_setValue(moduleId, level, 1); + } + level++; + bitmask >>= 1; + } +} + + +/* + * FUNCTION: wlan_hdd_validate_context + * This function is used to check the HDD context + */ +int wlan_hdd_validate_context(hdd_context_t *pHddCtx) +{ + + if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini) { + hddLog(LOG1, FL("HDD context is Null")); + return -ENODEV; + } + + if (pHddCtx->isLogpInProgress) { + hddLog(LOG1, FL("LOGP in Progress. Ignore!!!")); + return -EAGAIN; + } + + if ((pHddCtx->isLoadInProgress) || + (pHddCtx->isUnloadInProgress)) { + hddLog(LOG1, FL("Unloading/Loading in Progress. Ignore!!!")); + return -EAGAIN; + } + return 0; +} + + +void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx) +{ + hdd_adapter_t *pAdapter = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + eCsrPhyMode phyMode; + hdd_config_t *cfg_param = NULL; + + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD Context is null !!"); + return ; + } + + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "pAdapter is null !!"); + return ; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + cfg_param = pHddCtx->cfg_ini; + if (NULL == cfg_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "cfg_params not available !!"); + return ; + } + + phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter)); + + if (!pHddCtx->isVHT80Allowed) + { + if ((eCSR_DOT11_MODE_AUTO == phyMode) || + (eCSR_DOT11_MODE_11ac == phyMode) || + (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Setting phymode to 11n!!"); + sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n); + } + } + else + { + /*New country Supports 11ac as well resetting value back from .ini*/ + sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), + hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode)); + return ; + } + + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) || + (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode))) + { + VOS_STATUS vosStatus; + + // need to issue a disconnect to CSR. + INIT_COMPLETION(pAdapter->disconnect_comp_var); + vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED ); + + if (VOS_STATUS_SUCCESS == vosStatus) + { + unsigned long rc; + + rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(LOGE, FL("failure waiting for disconnect_comp_var")); + } + } +} + +static void +hdd_checkandupdate_dfssetting(hdd_adapter_t *pAdapter, char *country_code) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param; + + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD Context is null !!"); + return ; + } + + cfg_param = pHddCtx->cfg_ini; + + if (NULL == cfg_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "cfg_params not available !!"); + return ; + } + + if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, 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); + } + +} + +#ifdef IPA_UC_STA_OFFLOAD +static void hdd_set_thermal_level_cb(hdd_context_t *pHddCtx, u_int8_t level) +{ + /* Change IPA to SW path when throttle level greater than 0 */ + if (level > THROTTLE_LEVEL_0) + hdd_ipa_send_mcc_scc_msg(pHddCtx, TRUE); + else + /* restore original concurrency mode */ + hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); +} +#else +static void hdd_set_thermal_level_cb(hdd_context_t *pHddCtx, u_int8_t level) +{ +} +#endif + +/**--------------------------------------------------------------------------- + + \brief hdd_setIbssPowerSaveParams - update IBSS Power Save params to WMA. + + This function sets the IBSS power save config parameters to WMA + which will send it to firmware if FW supports IBSS power save + before vdev start. + + \param - hdd_adapter_t Hdd adapter. + + \return - VOS_STATUS VOS_STATUS_SUCCESS on Success and VOS_STATUS_E_FAILURE + on failure. + + --------------------------------------------------------------------------*/ +VOS_STATUS hdd_setIbssPowerSaveParams(hdd_adapter_t *pAdapter) +{ + int ret; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + + if (pHddCtx == NULL) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is null", __func__); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE, + pHddCtx->cfg_ini->ibssATIMWinSize, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED, + pHddCtx->cfg_ini->isIbssPowerSaveAllowed, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED, + pHddCtx->cfg_ini->isIbssPowerCollapseAllowed, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX, + pHddCtx->cfg_ini->isIbssAwakeOnTxRx, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_SET_INACTIVITY_TIME, + pHddCtx->cfg_ini->ibssInactivityCount, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME, + pHddCtx->cfg_ini->ibssTxSpEndInactivityTime, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS, + pHddCtx->cfg_ini->ibssPsWarmupTime, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = process_wma_set_command(pAdapter->sessionId, + WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW, + pHddCtx->cfg_ini->ibssPs1RxChainInAtimEnable, + VDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"), + ret); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/** + * hdd_parse_reassoc_command_data() - HDD Parse reassoc command data + * @pValue: Pointer to input data (its a NUL terminated string) + * @pTargetApBssid: Pointer to target Ap bssid + * @pChannel: Pointer to the Target AP channel + * + * This function parses the reasoc command data passed in the format + * REASSOC + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue, + tANI_U8 *pTargetApBssid, + tANI_U8 *pChannel) +{ + const tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + tANI_U8 tempBuf[32]; + /* 12 hexa decimal digits, 5 ':' and '\0' */ + tANI_U8 macAddress[18]; + + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) { + return -EINVAL; + } else if (SPACE_ASCII_VALUE != *inPtr) { + /*no space after the command*/ + return -EINVAL; + } + + /* Removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + + v = sscanf(inPtr, "%17s", macAddress); + if (!((1 == v) && hdd_is_valid_mac_address(macAddress))) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid MAC address or All hex inputs are not read (%d)", v); + return -EINVAL; + } + + pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | + hdd_parse_hex(macAddress[1]); + pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | + hdd_parse_hex(macAddress[4]); + pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | + hdd_parse_hex(macAddress[7]); + pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | + hdd_parse_hex(macAddress[10]); + pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | + hdd_parse_hex(macAddress[13]); + pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | + hdd_parse_hex(macAddress[16]); + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) return -EINVAL; + + /* Removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) { + return -EINVAL; + } + + /*getting the next argument ie the channel number */ + v = sscanf(inPtr, "%31s ", tempBuf); + if (1 != v) return -EINVAL; + + /* + * Sigma DUT sends connected bssid and channel 0 to indicate + * driver to issue reassoc to same AP. + * Hence do not treat channel 0 as invalid. + */ + v = kstrtos32(tempBuf, 10, &tempInt); + if ((v < 0) || + (tempInt < 0) || + (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX)) { + return -EINVAL; + } + + *pChannel = tempInt; + return VOS_STATUS_SUCCESS; +} + +/* + \brief hdd_reassoc() - perform a user space-directed reassoc + + \param - pAdapter - Adapter upon which the command was received + \param - bssid - BSSID with which to reassociate + \param - channel - channel upon which to reassociate + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid, const tANI_U8 channel) +{ + hdd_station_ctx_t *pHddStaCtx; + int ret = 0; + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* if not associated, no need to proceed with reassoc */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated", __func__); + ret = -EINVAL; + goto exit; + } + + /* if the target bssid is same as currently associated AP, + then no need to proceed with reassoc */ + if (!memcmp(bssid, pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Reassoc BSSID is same as currently associated AP bssid", + __func__); + ret = -EINVAL; + goto exit; + } + + /* Check channel number is a valid channel number */ + if (VOS_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, channel)) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Channel %d", + __func__, channel); + ret = -EINVAL; + goto exit; + } + + /* Proceed with reassoc */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + { + tCsrHandoffRequest handoffInfo; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + handoffInfo.channel = channel; + handoffInfo.src = REASSOC; + memcpy(handoffInfo.bssid, bssid, sizeof(tSirMacAddr)); + sme_HandoffRequest(pHddCtx->hHal, pAdapter->sessionId, &handoffInfo); + } +#endif + exit: + return ret; +} + +/* + \brief hdd_parse_reassoc_v1() - parse version 1 of the REASSOC command + + This function parses the v1 REASSOC command with the format + + REASSOC xx:xx:xx:xx:xx:xx CH + + Where "xx:xx:xx:xx:xx:xx" is the Hex-ASCII representation of the + BSSID and CH is the ASCII representation of the channel. For + example + + REASSOC 00:0a:0b:11:22:33 48 + + \param - pAdapter - Adapter upon which the command was received + \param - command - ASCII text command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_reassoc_v1(hdd_adapter_t *pAdapter, const char *command) +{ + tANI_U8 channel = 0; + tSirMacAddr bssid; + int ret; + + ret = hdd_parse_reassoc_command_v1_data(command, bssid, &channel); + if (ret) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse reassoc command data", __func__); + } else { + ret = hdd_reassoc(pAdapter, bssid, channel); + } + return ret; +} + +/* + \brief hdd_parse_reassoc_v2() - parse version 2 of the REASSOC command + + This function parses the v2 REASSOC command with the format + + REASSOC + + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received, ASCII command followed + by binary data + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, + const char *command) +{ + struct android_wifi_reassoc_params params; + tSirMacAddr bssid; + int ret; + + /* The params are located after "REASSOC " */ + memcpy(¶ms, command + 8, sizeof(params)); + + if (!mac_pton(params.bssid, (u8 *)&bssid)) { + hddLog(LOGE, "%s: MAC address parsing failed", __func__); + ret = -EINVAL; + } else { + ret = hdd_reassoc(pAdapter, bssid, params.channel); + } + return ret; +} + +/* + \brief hdd_parse_reassoc() - parse the REASSOC command + + There are two different versions of the REASSOC command. Version 1 + of the command contains a parameter list that is ASCII characters + whereas version 2 contains a combination of ASCII and binary + payload. Determine if a version 1 or a version 2 command is being + parsed by examining the parameters, and then dispatch the parser + that is appropriate for the command. + + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command) +{ + int ret; + + /* both versions start with "REASSOC " + * v1 has a bssid and channel # as an ASCII string + * REASSOC xx:xx:xx:xx:xx:xx CH + * v2 has a C struct + * REASSOC + * + * The first field in the v2 struct is also the bssid in ASCII. + * But in the case of a v2 message the BSSID is NUL-terminated. + * Hence we can peek at that offset to see if this is V1 or V2 + * REASSOC xx:xx:xx:xx:xx:xx* + * 1111111111222222 + * 01234567890123456789012345 + */ + if (command[25]) { + ret = hdd_parse_reassoc_v1(pAdapter, command); + } else { + ret = hdd_parse_reassoc_v2(pAdapter, command); + } + + return ret; +} + +/** + * hdd_parse_send_action_frame_v1_data() - HDD Parse send action frame data + * @pValue: Pointer to input data (its a NUL terminated string) + * @pTargetApBssid: Pointer to target Ap bssid + * @pChannel: Pointer to the Target AP channel + * @pDwellTime: pDwellTime Pointer to the time to stay off-channel + * after transmitting action frame + * @pBuf: Pointer to data + * @pBufLen: Pointer to data length + * + * This function parses the send action frame data passed in the format + * SENDACTIONFRAME + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_send_action_frame_v1_data(const tANI_U8 *pValue, + tANI_U8 *pTargetApBssid, + tANI_U8 *pChannel, tANI_U8 *pDwellTime, + tANI_U8 **pBuf, tANI_U8 *pBufLen) +{ + const tANI_U8 *inPtr = pValue; + const tANI_U8 *dataEnd; + int tempInt; + int j = 0; + int i = 0; + int v = 0; + tANI_U8 tempBuf[32]; + tANI_U8 tempByte = 0; + /* 12 hexa decimal digits, 5 ':' and '\0' */ + tANI_U8 macAddress[18]; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) { + return -EINVAL; + } else if (SPACE_ASCII_VALUE != *inPtr) { + /* no space after the command */ + return -EINVAL; + } + + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) { + return -EINVAL; + } + + v = sscanf(inPtr, "%17s", macAddress); + if (!((1 == v) && hdd_is_valid_mac_address(macAddress))) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid MAC address or All hex inputs are not read (%d)", v); + return -EINVAL; + } + + pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | + hdd_parse_hex(macAddress[1]); + pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | + hdd_parse_hex(macAddress[4]); + pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | + hdd_parse_hex(macAddress[7]); + pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | + hdd_parse_hex(macAddress[10]); + pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | + hdd_parse_hex(macAddress[13]); + pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | + hdd_parse_hex(macAddress[16]); + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) return -EINVAL; + + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + + /* getting the next argument ie the channel number */ + v = sscanf(inPtr, "%31s ", tempBuf); + if (1 != v) return -EINVAL; + + v = kstrtos32(tempBuf, 10, &tempInt); + if (v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX) + return -EINVAL; + + *pChannel = tempInt; + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) return -EINVAL; + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + + /* Getting the next argument ie the dwell time */ + v = sscanf(inPtr, "%31s ", tempBuf); + if (1 != v) return -EINVAL; + + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0 || tempInt < 0) return -EINVAL; + + *pDwellTime = tempInt; + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) return -EINVAL; + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + + /* find the length of data */ + dataEnd = inPtr; + while('\0' != *dataEnd) { + dataEnd++; + } + *pBufLen = dataEnd - inPtr ; + if (*pBufLen <= 0) return -EINVAL; + + /* Allocate the number of bytes based on the number of input characters + whether it is even or odd. + if the number of input characters are even, then we need N/2 byte. + if the number of input characters are odd, then we need do (N+1)/2 to + compensate rounding off. + For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough. + If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */ + *pBuf = vos_mem_malloc((*pBufLen + 1)/2); + if (NULL == *pBuf) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_alloc failed ", __func__); + return -EINVAL; + } + + /* the buffer received from the upper layer is character buffer, + we need to prepare the buffer taking 2 characters in to a U8 hex decimal number + for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st + and f0 in 3rd location */ + for (i = 0, j = 0; j < *pBufLen; j += 2) { + if( j+1 == *pBufLen) { + tempByte = hdd_parse_hex(inPtr[j]); + } else { + tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1])); + } + (*pBuf)[i++] = tempByte; + } + *pBufLen = i; + return 0; +} + +/* + \brief hdd_sendactionframe() - send a user space supplied action frame + + \param - pAdapter - Adapter upon which the command was received + \param - bssid - BSSID target of the action frame + \param - channel - channel upon which to send the frame + \param - dwell_time - amount of time to dwell when the frame is sent + \param - payload_len - length of the payload + \param - payload - payload of the frame + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_sendactionframe(hdd_adapter_t *pAdapter, const tANI_U8 *bssid, + const tANI_U8 channel, const tANI_U8 dwell_time, + const tANI_U8 payload_len, const tANI_U8 *payload) +{ + struct ieee80211_channel chan; + tANI_U8 frame_len; + tANI_U8 *frame; + struct ieee80211_hdr_3addr *hdr; + u64 cookie; + hdd_station_ctx_t *pHddStaCtx; + hdd_context_t *pHddCtx; + int ret = 0; + tpSirMacVendorSpecificFrameHdr pVendorSpecific = + (tpSirMacVendorSpecificFrameHdr) payload; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + struct cfg80211_mgmt_tx_params params; +#endif + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + /* if not associated, no need to send action frame */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated", __func__); + ret = -EINVAL; + goto exit; + } + + /* if the target bssid is different from currently associated AP, + then no need to send action frame */ + if (memcmp(bssid, pHddStaCtx->conn_info.bssId, VOS_MAC_ADDR_SIZE)) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: STA is not associated to this AP", + __func__); + ret = -EINVAL; + goto exit; + } + + chan.center_freq = sme_ChnToFreq(channel); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* Check if it is specific action frame */ + if (pVendorSpecific->category == SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY) { + static const tANI_U8 Oui[] = { 0x00, 0x00, 0xf0 }; + if (vos_mem_compare(pVendorSpecific->Oui, (void *) Oui, 3)) { + /* if the channel number is different from operating channel then + no need to send action frame */ + if (channel != 0) { + if (channel != pHddStaCtx->conn_info.operationChannel) { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: channel(%d) is different from operating channel(%d)", + __func__, channel, + pHddStaCtx->conn_info.operationChannel); + ret = -EINVAL; + goto exit; + } + /* If channel number is specified and same as home channel, + * ensure that action frame is sent immediately by cancelling + * roaming scans. Otherwise large dwell times may cause long + * delays in sending action frames. + */ + sme_abortRoamScan(pHddCtx->hHal, pAdapter->sessionId); + } else { + /* 0 is accepted as current home channel, delayed + * transmission of action frame is ok. + */ + chan.center_freq = + sme_ChnToFreq(pHddStaCtx->conn_info.operationChannel); + } + } + } +#endif //#if WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (chan.center_freq == 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s:invalid channel number %d", + __func__, channel); + ret = -EINVAL; + goto exit; + } + + frame_len = payload_len + 24; + frame = vos_mem_malloc(frame_len); + if (!frame) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed", __func__); + ret = -ENOMEM; + goto exit; + } + vos_mem_zero(frame, frame_len); + + hdr = (struct ieee80211_hdr_3addr *)frame; + hdr->frame_control = + cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); + vos_mem_copy(hdr->addr1, bssid, VOS_MAC_ADDR_SIZE); + vos_mem_copy(hdr->addr2, pAdapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + vos_mem_copy(hdr->addr3, bssid, VOS_MAC_ADDR_SIZE); + vos_mem_copy(hdr + 1, payload, payload_len); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + params.chan = &chan; + params.offchan = 0; + params.wait = dwell_time; + params.buf = frame; + params.len = frame_len; + params.no_cck = 1; + params.dont_wait_for_ack = 1; + ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, ¶ms, &cookie); +#else + ret = wlan_hdd_mgmt_tx(NULL, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + &(pAdapter->wdev), +#else + pAdapter->dev, +#endif + &chan, 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + NL80211_CHAN_HT20, 1, +#endif + dwell_time, frame, frame_len, 1, 1, &cookie ); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/ + + vos_mem_free(frame); + exit: + return ret; +} + +/* + \brief hdd_parse_sendactionframe_v1() - parse version 1 of the + SENDACTIONFRAME command + + This function parses the v1 SENDACTIONFRAME command with the format + + SENDACTIONFRAME xx:xx:xx:xx:xx:xx CH DW xxxxxx + + Where "xx:xx:xx:xx:xx:xx" is the Hex-ASCII representation of the + BSSID, CH is the ASCII representation of the channel, DW is the + ASCII representation of the dwell time, and xxxxxx is the Hex-ASCII + payload. For example + + SENDACTIONFRAME 00:0a:0b:11:22:33 48 40 aabbccddee + + \param - pAdapter - Adapter upon which the command was received + \param - command - ASCII text command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_sendactionframe_v1(hdd_adapter_t *pAdapter, const char *command) +{ + tANI_U8 channel = 0; + tANI_U8 dwell_time = 0; + tANI_U8 payload_len = 0; + tANI_U8 *payload = NULL; + tSirMacAddr bssid; + int ret; + + ret = hdd_parse_send_action_frame_v1_data(command, bssid, &channel, + &dwell_time, &payload, + &payload_len); + if (ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse send action frame data", __func__); + } else { + ret = hdd_sendactionframe(pAdapter, bssid, channel, dwell_time, + payload_len, payload); + vos_mem_free(payload); + } + + return ret; +} + +/* + \brief hdd_parse_sendactionframe_v2() - parse version 2 of the + SENDACTIONFRAME command + + This function parses the v2 SENDACTIONFRAME command with the format + + SENDACTIONFRAME + + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received, ASCII command followed + by binary data + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_sendactionframe_v2(hdd_adapter_t *pAdapter, + const char *command) +{ + struct android_wifi_af_params *params; + tSirMacAddr bssid; + int ret; + + /* params are large so keep off the stack */ + params = kmalloc(sizeof(*params), GFP_KERNEL); + if (!params) return -ENOMEM; + + /* The params are located after "SENDACTIONFRAME " */ + memcpy(params, command + 16, sizeof(*params)); + + if (!mac_pton(params->bssid, (u8 *)&bssid)) { + hddLog(LOGE, "%s: MAC address parsing failed", __func__); + ret = -EINVAL; + } else { + ret = hdd_sendactionframe(pAdapter, bssid, params->channel, + params->dwell_time, params->len, params->data); + } + kfree(params); + return ret; +} + +/* + \brief hdd_parse_sendactionframe() - parse the SENDACTIONFRAME command + + There are two different versions of the SENDACTIONFRAME command. + Version 1 of the command contains a parameter list that is ASCII + characters whereas version 2 contains a combination of ASCII and + binary payload. Determine if a version 1 or a version 2 command is + being parsed by examining the parameters, and then dispatch the + parser that is appropriate for the version of the command. + + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_sendactionframe(hdd_adapter_t *pAdapter, const char *command) +{ + int ret; + + /* both versions start with "SENDACTIONFRAME " + * v1 has a bssid and other parameters as an ASCII string + * SENDACTIONFRAME xx:xx:xx:xx:xx:xx CH DWELL LEN FRAME + * v2 has a C struct + * SENDACTIONFRAME + * + * The first field in the v2 struct is also the bssid in ASCII. + * But in the case of a v2 message the BSSID is NUL-terminated. + * Hence we can peek at that offset to see if this is V1 or V2 + * SENDACTIONFRAME xx:xx:xx:xx:xx:xx* + * 111111111122222222223333 + * 0123456789012345678901234567890123 + */ + if (command[33]) { + ret = hdd_parse_sendactionframe_v1(pAdapter, command); + } else { + ret = hdd_parse_sendactionframe_v2(pAdapter, command); + } + + return ret; +} + +static void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand) +{ + eCsrBand band = -1; + sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band); + switch (band) { + case eCSR_BAND_ALL: + *pBand = WLAN_HDD_UI_BAND_AUTO; + break; + + case eCSR_BAND_24: + *pBand = WLAN_HDD_UI_BAND_2_4_GHZ; + break; + + case eCSR_BAND_5G: + *pBand = WLAN_HDD_UI_BAND_5_GHZ; + break; + + default: + hddLog(LOGW, FL("Invalid Band %d"), band); + *pBand = -1; + break; + } +} + + +/** + * hdd_parse_channellist() - HDD Parse channel list + * @pValue: Pointer to input data + * @pChannelList: Pointer to input channel list + * @pNumChannels: Pointer to number of roam scan channels + * + * This function parses the channel list passed in the format + * SETROAMSCANCHANNELSChannel 1 + * Channel 2Channel N + * if the Number of channels (N) does not match with the actual number of + * channels passed then take the minimum of N and count of (Ch1, Ch2, ...Ch M) + * For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall + * be taken. + * If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48. + * This function does not take care of removing duplicate channels from the list + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_channellist(const tANI_U8 *pValue, tANI_U8 *pChannelList, + tANI_U8 *pNumChannels) +{ + const tANI_U8 *inPtr = pValue; + int tempInt; + int j = 0; + int v = 0; + char buf[32]; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) { + return -EINVAL; + } else if (SPACE_ASCII_VALUE != *inPtr) { + /* no space after the command */ + return -EINVAL; + } + + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + + /*getting the first argument ie the number of channels*/ + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) return -EINVAL; + + v = kstrtos32(buf, 10, &tempInt); + if ((v < 0) || + (tempInt <= 0) || + (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN)) { + return -EINVAL; + } + + *pNumChannels = tempInt; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Number of channels are: %d", *pNumChannels); + + for (j = 0; j < (*pNumChannels); j++) { + /* inPtr pointing to the beginning of first space after number of + channels*/ + inPtr = strpbrk( inPtr, " " ); + /* no channel list after the number of channels argument */ + if (NULL == inPtr) { + if (0 != j) { + *pNumChannels = j; + return 0; + } else { + return -EINVAL; + } + } + + /* removing empty space */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + /*no channel list after the number of channels argument and spaces*/ + if ('\0' == *inPtr) { + if (0 != j) { + *pNumChannels = j; + return 0; + } else { + return -EINVAL; + } + } + + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) return -EINVAL; + + v = kstrtos32(buf, 10, &tempInt); + if ((v < 0) || + (tempInt <= 0) || + (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX)) { + return -EINVAL; + } + pChannelList[j] = tempInt; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Channel %d added to preferred channel list", + pChannelList[j] ); + } + + return 0; +} + +/* + \brief hdd_parse_set_roam_scan_channels_v1() - parse version 1 of the + SETROAMSCANCHANNELS command + + This function parses the v1 SETROAMSCANCHANNELS command with the format + + SETROAMSCANCHANNELS N C1 C2 ... Cn + + Where "N" is the ASCII representation of the number of channels and + C1 thru Cn is the ASCII representation of the channels. For example + + SETROAMSCANCHANNELS 4 36 40 44 48 + + \param - pAdapter - Adapter upon which the command was received + \param - command - ASCII text command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_set_roam_scan_channels_v1(hdd_adapter_t *pAdapter, + const char *command) +{ + tANI_U8 channel_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tANI_U8 num_chan = 0; + eHalStatus status; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int ret; + + ret = hdd_parse_channellist(command, channel_list, &num_chan); + if (ret) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse channel list information", __func__); + goto exit; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL, + pAdapter->sessionId, num_chan)); + + if (num_chan > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: number of channels (%d) supported exceeded max (%d)", + __func__, num_chan, WNI_CFG_VALID_CHANNEL_LIST_LEN); + ret = -EINVAL; + goto exit; + } + + status = sme_ChangeRoamScanChannelList(pHddCtx->hHal, pAdapter->sessionId, + channel_list, num_chan); + if (eHAL_STATUS_SUCCESS != status) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to update channel list information", __func__); + ret = -EINVAL; + goto exit; + } + exit: + return ret; +} + +/* + \brief hdd_parse_set_roam_scan_channels_v2() - parse version 2 of the + SETROAMSCANCHANNELS command + + This function parses the v2 SETROAMSCANCHANNELS command with the format + + SETROAMSCANCHANNELS [N][C1][C2][Cn] + + The command begins with SETROAMSCANCHANNELS followed by a space, but + what follows the space is an array of u08 parameters. For example + + SETROAMSCANCHANNELS [0x04 0x24 0x28 0x2c 0x30] + + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received, ASCII command followed + by binary data + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_set_roam_scan_channels_v2(hdd_adapter_t *pAdapter, + const char *command) +{ + const tANI_U8 *value; + tANI_U8 channel_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tANI_U8 channel; + tANI_U8 num_chan; + int i; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + eHalStatus status; + int ret = 0; + + /* array of values begins after "SETROAMSCANCHANNELS " */ + value = command + 20; + + num_chan = *value++; + if (num_chan > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: number of channels (%d) supported exceeded max (%d)", + __func__, num_chan, WNI_CFG_VALID_CHANNEL_LIST_LEN); + ret = -EINVAL; + goto exit; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL, + pAdapter->sessionId, num_chan)); + + for (i = 0; i < num_chan; i++) { + channel = *value++; + if (channel > WNI_CFG_CURRENT_CHANNEL_STAMAX) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: index %d invalid channel %d", __func__, i, channel); + ret = -EINVAL; + goto exit; + } + channel_list[i] = channel; + } + status = sme_ChangeRoamScanChannelList(pHddCtx->hHal, pAdapter->sessionId, + channel_list, num_chan); + if (eHAL_STATUS_SUCCESS != status) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to update channel list information", __func__); + ret = -EINVAL; + goto exit; + } + exit: + return ret; +} + +/* + \brief hdd_parse_set_roam_scan_channels() - parse the + SETROAMSCANCHANNELS command + + There are two different versions of the SETROAMSCANCHANNELS command. + Version 1 of the command contains a parameter list that is ASCII + characters whereas version 2 contains a binary payload. Determine + if a version 1 or a version 2 command is being parsed by examining + the parameters, and then dispatch the parser that is appropriate for + the command. + + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_set_roam_scan_channels(hdd_adapter_t *pAdapter, + const char *command) +{ + const char *cursor; + char ch; + bool v1; + int ret; + + /* start after "SETROAMSCANCHANNELS " */ + cursor = command + 20; + + /* assume we have a version 1 command until proven otherwise */ + v1 = true; + + /* v1 params will only contain ASCII digits and space */ + while ((ch = *cursor++) && v1) { + if (!(isdigit(ch) || isspace(ch))) { + v1 = false; + } + } + if (v1) { + ret = hdd_parse_set_roam_scan_channels_v1(pAdapter, command); + } else { + ret = hdd_parse_set_roam_scan_channels_v2(pAdapter, command); + } + + return ret; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ + +/**--------------------------------------------------------------------------- + + \brief hdd_parse_setrmcrate_command() - HDD Parse reliable multicast + set rate command + + This function parses the SETRMCTXRATE command passed in the format + SETRMCTXRATEX(multicast rate in Mbps) + For example input commands: + 1) SETRMCTXRATE 6 -> This is translated into set RMC multicast rate + to 6 Mbps + 1) SETRMCTXRATE 0 -> This is translated into disabling fixed multicast rate + and enabling multicast RA in firmware + + \param - pValue Pointer to SETRMCTXRATE command + \param - pRate Pointer to local RMC multicast rate variable + \param - pTxFlags Pointer to local RMC multicast rate variable + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int hdd_parse_setrmcrate_command(tANI_U8 *pValue, + tANI_U32 *pRate, tTxrateinfoflags *pTxFlags) +{ + tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + char buf[32]; + *pRate = 0; + *pTxFlags = 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; + } + + /* + * getting the first argument which sets multicast rate. + */ + sscanf(inPtr, "%32s ", buf); + v = kstrtos32(buf, 10, &tempInt); + if ( v < 0) + { + return -EINVAL; + } + + /* + * Validate the multicast rate. + */ + switch (tempInt) + { + default: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "Unsupported rate: %d", tempInt); + return -EINVAL; + case 0: + case 6: + case 9: + case 12: + case 18: + case 24: + case 36: + case 48: + case 54: + *pTxFlags = eHAL_TX_RATE_LEGACY; + *pRate = tempInt * 10; + break; + case 65: + *pTxFlags = eHAL_TX_RATE_HT20; + *pRate = tempInt * 10; + break; + case 72: + *pTxFlags = eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; + *pRate = 722; /* fractional rate 72.2 Mbps */ + break; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Rate: %d", *pRate); + + return 0; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/**--------------------------------------------------------------------------- + + \brief hdd_parse_plm_cmd() - HDD Parse Plm command + + This function parses the plm command passed in the format + CCXPLMREQ + + + + + + \param - pValue Pointer to input data + \param - pPlmRequest Pointer to output struct tpSirPlmReq + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static eHalStatus hdd_parse_plm_cmd(tANI_U8 *pValue, tSirPlmReq *pPlmRequest) +{ + tANI_U8 *cmdPtr = NULL; + int count, content = 0, ret = 0; + char buf[32]; + + /* moving to argument list */ + cmdPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*no space after the command*/ + if (SPACE_ASCII_VALUE != *cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* START/STOP PLM req */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + pPlmRequest->enable = content; + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* Dialog token of radio meas req containing meas reqIE */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + pPlmRequest->diag_token = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "diag token %d", pPlmRequest->diag_token); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* measurement token of meas req IE */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + pPlmRequest->meas_token = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "meas token %d", pPlmRequest->meas_token); + + hddLog(VOS_TRACE_LEVEL_ERROR, + "PLM req %s", pPlmRequest->enable ? "START" : "STOP"); + if (pPlmRequest->enable) { + + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* total number of bursts after which STA stops sending */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content < 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->numBursts= content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "num burst %d", pPlmRequest->numBursts); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* burst interval in seconds */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content <= 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->burstInt = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "burst Int %d", pPlmRequest->burstInt); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* Meas dur in TU's,STA goes off-ch and transmit PLM bursts */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content <= 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->measDuration = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "measDur %d", pPlmRequest->measDuration); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* burst length of PLM bursts */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content <= 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->burstLen = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "burstLen %d", pPlmRequest->burstLen); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* desired tx power for transmission of PLM bursts */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content <= 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->desiredTxPwr = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, + "desiredTxPwr %d", pPlmRequest->desiredTxPwr); + + for (count = 0; count < VOS_MAC_ADDR_SIZE; count++) + { + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 16, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + pPlmRequest->macAddr[count] = content; + } + + hddLog(VOS_TRACE_LEVEL_DEBUG, "MC addr "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPlmRequest->macAddr)); + + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* number of channels */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content < 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->plmNumCh = content; + hddLog(VOS_TRACE_LEVEL_DEBUG, "numch %d", pPlmRequest->plmNumCh); + + /* Channel numbers */ + for (count = 0; count < pPlmRequest->plmNumCh; count++) + { + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return eHAL_STATUS_FAILURE; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) return eHAL_STATUS_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if ( ret < 0) return eHAL_STATUS_FAILURE; + + if (content <= 0) + return eHAL_STATUS_FAILURE; + + pPlmRequest->plmChList[count]= content; + hddLog(VOS_TRACE_LEVEL_DEBUG, " ch- %d", + pPlmRequest->plmChList[count]); + } + } /* If PLM START */ + + return eHAL_STATUS_SUCCESS; +} +#endif +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +static void wlan_hdd_ready_to_extwow(void *callbackContext, + boolean is_success) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)callbackContext; + int rc; + + rc = wlan_hdd_validate_context(pHddCtx); + if (0 != rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return; + } + pHddCtx->ext_wow_should_suspend = is_success; + complete(&pHddCtx->ready_to_extwow); +} + +static int hdd_enable_ext_wow(hdd_adapter_t *pAdapter, + tpSirExtWoWParams arg_params) +{ + tSirExtWoWParams params; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + int rc; + + vos_mem_copy(¶ms, arg_params, sizeof(params)); + + INIT_COMPLETION(pHddCtx->ready_to_extwow); + + halStatus = sme_ConfigureExtWoW(hHal, ¶ms, + &wlan_hdd_ready_to_extwow, pHddCtx); + if (eHAL_STATUS_SUCCESS != halStatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("sme_ConfigureExtWoW returned failure %d"), halStatus); + return -EPERM; + } + + rc = wait_for_completion_timeout(&pHddCtx->ready_to_extwow, + msecs_to_jiffies(WLAN_WAIT_TIME_READY_TO_EXTWOW)); + if (!rc) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to get ready to extwow", __func__); + return -EPERM; + } + + if (pHddCtx->ext_wow_should_suspend) { + if (pHddCtx->cfg_ini->extWowGotoSuspend) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received ready to ExtWoW. Going to suspend", __func__); + + wlan_hdd_cfg80211_suspend_wlan(pHddCtx->wiphy, NULL); + wlan_hif_pci_suspend(); + } + } else { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Received ready to ExtWoW failure", __func__); + return -EPERM; + } + + return 0; +} + +static int hdd_enable_ext_wow_parser(hdd_adapter_t *pAdapter, int vdev_id, + int value) +{ + tSirExtWoWParams params; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int rc; + + rc = wlan_hdd_validate_context(pHddCtx); + if (0 != rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + if (value < EXT_WOW_TYPE_APP_TYPE1 || value > EXT_WOW_TYPE_APP_TYPE1_2 ) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid type")); + return -EINVAL; + } + + if (value == EXT_WOW_TYPE_APP_TYPE1 && + pHddCtx->is_extwow_app_type1_param_set) + params.type = value; + else if (value == EXT_WOW_TYPE_APP_TYPE2 && + pHddCtx->is_extwow_app_type2_param_set) + params.type = value; + else if (value == EXT_WOW_TYPE_APP_TYPE1_2 && + pHddCtx->is_extwow_app_type1_param_set && + pHddCtx->is_extwow_app_type2_param_set) + params.type = value; + else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Set app params before enable it value %d"),value); + return -EINVAL; + } + + params.vdev_id = vdev_id; + params.wakeup_pin_num = pHddCtx->cfg_ini->extWowApp1WakeupPinNumber | + (pHddCtx->cfg_ini->extWowApp2WakeupPinNumber << 8); + + return hdd_enable_ext_wow(pAdapter, ¶ms); +} + +static int hdd_set_app_type1_params(tHalHandle hHal, + tpSirAppType1Params arg_params) +{ + tSirAppType1Params params; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + vos_mem_copy(¶ms, arg_params, sizeof(params)); + + halStatus = sme_ConfigureAppType1Params(hHal, ¶ms); + if (eHAL_STATUS_SUCCESS != halStatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("sme_ConfigureAppType1Params returned failure %d"), halStatus); + return -EPERM; + } + + return 0; +} + +static int hdd_set_app_type1_parser(hdd_adapter_t *pAdapter, + char *arg, int len) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + char id[20], password[20]; + tSirAppType1Params params; + int rc, i; + + rc = wlan_hdd_validate_context(pHddCtx); + if (0 != rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + if (2 != sscanf(arg, "%8s %16s", id, password)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid Number of arguments")); + return -EINVAL; + } + + memset(¶ms, 0, sizeof(tSirAppType1Params)); + params.vdev_id = pAdapter->sessionId; + for (i = 0; i < ETHER_ADDR_LEN; i++) + params.wakee_mac_addr[i] = pAdapter->macAddressCurrent.bytes[i]; + + params.id_length = strlen(id); + vos_mem_copy(params.identification_id, id, params.id_length); + params.pass_length = strlen(password); + vos_mem_copy(params.password, password, params.pass_length); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: %d %pM %.8s %u %.16s %u", + __func__, params.vdev_id, params.wakee_mac_addr, + params.identification_id, params.id_length, + params.password, params.pass_length ); + + return hdd_set_app_type1_params(hHal, ¶ms); +} + +static int hdd_set_app_type2_params(tHalHandle hHal, + tpSirAppType2Params arg_params) +{ + tSirAppType2Params params; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + vos_mem_copy(¶ms, arg_params, sizeof(params)); + + halStatus = sme_ConfigureAppType2Params(hHal, ¶ms); + if (eHAL_STATUS_SUCCESS != halStatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("sme_ConfigureAppType2Params returned failure %d"), halStatus); + return -EPERM; + } + + return 0; +} + +static int hdd_set_app_type2_parser(hdd_adapter_t *pAdapter, + char *arg, int len) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + char mac_addr[20], rc4_key[20]; + unsigned int gateway_mac[6], i; + tSirAppType2Params params; + int ret; + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + memset(¶ms, 0, sizeof(tSirAppType2Params)); + + ret = sscanf(arg, "%17s %16s %x %x %x %u %u %hu %hu %u %u %u %u %u %u", + mac_addr, rc4_key, (unsigned int *)¶ms.ip_id, + (unsigned int*)¶ms.ip_device_ip, + (unsigned int*)¶ms.ip_server_ip, + (unsigned int*)¶ms.tcp_seq, (unsigned int*)¶ms.tcp_ack_seq, + (uint16_t*)¶ms.tcp_src_port, + (uint16_t*)¶ms.tcp_dst_port, + (unsigned int*)¶ms.keepalive_init, + (unsigned int*)¶ms.keepalive_min, + (unsigned int*)¶ms.keepalive_max, + (unsigned int*)¶ms.keepalive_inc, + (unsigned int*)¶ms.tcp_tx_timeout_val, + (unsigned int*)¶ms.tcp_rx_timeout_val); + + + if (ret != 15 && ret != 7) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid Number of arguments"); + return -EINVAL; + } + + if (6 != sscanf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", &gateway_mac[0], + &gateway_mac[1], &gateway_mac[2], &gateway_mac[3], + &gateway_mac[4], &gateway_mac[5])) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid MacAddress Input %s", mac_addr); + return -EINVAL; + } + + if (params.tcp_src_port > WLAN_HDD_MAX_TCP_PORT || + params.tcp_dst_port > WLAN_HDD_MAX_TCP_PORT) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid TCP Port Number"); + return -EINVAL; + } + + for (i = 0; i < ETHER_ADDR_LEN; i++) + params.gateway_mac[i] = (uint8_t) gateway_mac[i]; + + params.rc4_key_len = strlen(rc4_key); + vos_mem_copy(params.rc4_key, rc4_key, params.rc4_key_len); + + params.vdev_id = pAdapter->sessionId; + params.tcp_src_port = (params.tcp_src_port != 0)? + params.tcp_src_port : pHddCtx->cfg_ini->extWowApp2TcpSrcPort; + params.tcp_dst_port = (params.tcp_dst_port != 0)? + params.tcp_dst_port : pHddCtx->cfg_ini->extWowApp2TcpDstPort; + params.keepalive_init = (params.keepalive_init != 0)? + params.keepalive_init : pHddCtx->cfg_ini->extWowApp2KAInitPingInterval; + params.keepalive_min = (params.keepalive_min != 0)? + params.keepalive_min : pHddCtx->cfg_ini->extWowApp2KAMinPingInterval; + params.keepalive_max = (params.keepalive_max != 0)? + params.keepalive_max : pHddCtx->cfg_ini->extWowApp2KAMaxPingInterval; + params.keepalive_inc = (params.keepalive_inc != 0)? + params.keepalive_inc : pHddCtx->cfg_ini->extWowApp2KAIncPingInterval; + params.tcp_tx_timeout_val = (params.tcp_tx_timeout_val != 0)? + params.tcp_tx_timeout_val : pHddCtx->cfg_ini->extWowApp2TcpTxTimeout; + params.tcp_rx_timeout_val = (params.tcp_rx_timeout_val != 0)? + params.tcp_rx_timeout_val : pHddCtx->cfg_ini->extWowApp2TcpRxTimeout; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: %pM %.16s %u %u %u %u %u %u %u %u %u %u %u %u %u", + __func__, gateway_mac, rc4_key, params.ip_id, params.ip_device_ip, + params.ip_server_ip, params.tcp_seq, params.tcp_ack_seq, + params.tcp_src_port, params.tcp_dst_port, params.keepalive_init, + params.keepalive_min, params.keepalive_max, + params.keepalive_inc, params.tcp_tx_timeout_val, + params.tcp_rx_timeout_val); + + return hdd_set_app_type2_params(hHal, ¶ms); +} + +#endif + +int wlan_hdd_set_mc_rate(hdd_adapter_t *pAdapter, int targetRate) +{ + tSirRateUpdateInd rateUpdate = {0}; + eHalStatus status; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *pConfig = NULL; + + if (pHddCtx == NULL) { + hddLog(LOGE, FL("HDD context is null")); + return -EINVAL; + } + + if ((WLAN_HDD_IBSS != pAdapter->device_mode) && + (WLAN_HDD_SOFTAP != pAdapter->device_mode) && + (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)) { + hddLog(LOGE, FL("Received SETMCRATE cmd in invalid device mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + hddLog(LOGE, + FL("SETMCRATE cmd is allowed only in STA, IBSS or SOFTAP mode")); + return -EINVAL; + } + + pConfig = pHddCtx->cfg_ini; + rateUpdate.nss = (pConfig->enable2x2 == 0) ? 0 : 1; + rateUpdate.dev_mode = pAdapter->device_mode; + rateUpdate.mcastDataRate24GHz = targetRate; + rateUpdate.mcastDataRate24GHzTxFlag = 1; + rateUpdate.mcastDataRate5GHz = targetRate; + rateUpdate.bcastDataRate = -1; + memcpy(rateUpdate.bssid, pAdapter->macAddressCurrent.bytes, + sizeof(rateUpdate.bssid)); + hddLog(LOG1, FL("MC Target rate %d, mac = %pM, dev_mode %s(%d)"), + rateUpdate.mcastDataRate24GHz, rateUpdate.bssid, + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + status = sme_SendRateUpdateInd(pHddCtx->hHal, &rateUpdate); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("SETMCRATE failed")); + return -EFAULT; + } + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_parse_setmaxtxpower_command() - HDD Parse MAXTXPOWER command + + This function parses the MAXTXPOWER command passed in the format + MAXTXPOWERX(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 + + \param - pValue Pointer to MAXTXPOWER command + \param - pDbm Pointer to tx power + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int hdd_parse_setmaxtxpower_command(tANI_U8 *pValue, int *pTxPower) +{ + tANI_U8 *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; +} /*End of hdd_parse_setmaxtxpower_command*/ + + +static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len) +{ + int ret = 0; + + if (!pCfg || !command || !extra || !len) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for GETDWELLTIME is incorrect", __func__); + ret = -EINVAL; + return ret; + } + + if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0) + { + *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n", + (int)pCfg->nActiveMaxChnTime); + return ret; + } + else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0) + { + *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n", + (int)pCfg->nActiveMinChnTime); + return ret; + } + else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0) + { + *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n", + (int)pCfg->nPassiveMaxChnTime); + return ret; + } + else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0) + { + *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n", + (int)pCfg->nPassiveMinChnTime); + return ret; + } + else if (strncmp(command, "GETDWELLTIME", 12) == 0) + { + *len = scnprintf(extra, n, "GETDWELLTIME %u \n", + (int)pCfg->nActiveMaxChnTime); + return ret; + } + else + { + ret = -EINVAL; + } + + return ret; +} + +static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) +{ + tHalHandle hHal; + hdd_config_t *pCfg; + tANI_U8 *value = command; + tSmeConfigParams smeConfig; + int val = 0, ret = 0, temp = 0; + + if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini) + || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter)))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME is incorrect", __func__); + ret = -EINVAL; + return ret; + } + + vos_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_GetConfigParam(hHal, &smeConfig); + + if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 ) + { + value = value + 24; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__); + ret = -EFAULT; + return ret; + } + pCfg->nActiveMaxChnTime = val; + smeConfig.csrConfig.nActiveMaxChnTime = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0) + { + value = value + 24; + temp = kstrtou32(value, 10, &val); + if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN || + val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME ACTIVE MIN is incorrect", __func__); + ret = -EFAULT; + return ret; + } + pCfg->nActiveMinChnTime = val; + smeConfig.csrConfig.nActiveMinChnTime = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0) + { + value = value + 25; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN || + val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__); + ret = -EFAULT; + return ret; + } + pCfg->nPassiveMaxChnTime = val; + smeConfig.csrConfig.nPassiveMaxChnTime = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0) + { + value = value + 25; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN || + val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__); + ret = -EFAULT; + return ret; + } + pCfg->nPassiveMinChnTime = val; + smeConfig.csrConfig.nPassiveMinChnTime = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else if (strncmp(command, "SETDWELLTIME", 12) == 0) + { + value = value + 13; + temp = kstrtou32(value, 10, &val); + if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME is incorrect", __func__); + ret = -EFAULT; + return ret; + } + pCfg->nActiveMaxChnTime = val; + smeConfig.csrConfig.nActiveMaxChnTime = val; + sme_UpdateConfig(hHal, &smeConfig); + } + else + { + ret = -EINVAL; + } + + return ret; +} + +static void hdd_GetLink_statusCB(v_U8_t status, void *pContext) +{ + struct statsContext *pLinkContext; + hdd_adapter_t *pAdapter; + + if (NULL == pContext) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Bad pContext [%p]", + __func__, pContext); + return; + } + + pLinkContext = pContext; + pAdapter = pLinkContext->pAdapter; + + spin_lock(&hdd_context_lock); + + if ((NULL == pAdapter) || (LINK_STATUS_MAGIC != pLinkContext->magic)) { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pLinkContext->magic); + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pLinkContext->magic = 0; + + /* copy over the status */ + pAdapter->linkStatus = status; + + /* notify the caller */ + complete(&pLinkContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/** + * hdd_get_fw_state_cb() - validates the context and notifies the caller + * @callback_context: caller context + * + * Return: none + */ +static void hdd_get_fw_state_cb(void *callback_context) +{ + struct statsContext *context; + hdd_adapter_t *adapter; + + if (NULL == callback_context) { + hddLog(LOGE, FL("Bad pContext [%p]"), callback_context); + return; + } + + context = callback_context; + adapter = context->pAdapter; + + spin_lock(&hdd_context_lock); + + if ((NULL == adapter) || (FW_STATUS_MAGIC != context->magic)) { + /* the caller presumably timed out so there is + * nothing we can do + */ + spin_unlock(&hdd_context_lock); + hddLog(LOGE, FL("Invalid context, Adapter [%p] magic [%08x]"), + adapter, context->magic); + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + context->magic = 0; + + /* notify the caller */ + complete(&context->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/** + * wlan_hdd_get_fw_state() - get firmware state + * @adapter: pointer to the adapter + * + * This function sends a request to firmware and waits + * on a timer to invoke the callback. if the callback is invoked then + * true will be returned or otherwise fail status will be returned. + * + * Return: true, firmware is active. + * false, firmware is in bad state. + */ +bool wlan_hdd_get_fw_state(hdd_adapter_t *adapter) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct statsContext context; + eHalStatus hstatus = eHAL_STATUS_SUCCESS; + unsigned long rc; + bool fw_active = true; + + if (wlan_hdd_validate_context(hdd_ctx) != 0) { + hddLog(LOGE, FL("HDD context is not valid!!!")); + return false; + } + + init_completion(&context.completion); + context.pAdapter = adapter; + context.magic = FW_STATUS_MAGIC; + hstatus = sme_get_fw_state(WLAN_HDD_GET_HAL_CTX(adapter), + hdd_get_fw_state_cb, + &context); + + if (eHAL_STATUS_SUCCESS != hstatus) { + hddLog(LOGE, FL("Unable to retrieve firmware status")); + fw_active = false; + } else { + /* request is sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_LINK_STATUS)); + if (!rc) { + hddLog(LOGE, + FL("SME timed out while retrieving firmware status")); + fw_active = false; + } + } + + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + return fw_active; +} + +/** + * wlan_hdd_get_link_status() - get link status + * @pAdapter: pointer to the adapter + * + * This function sends a request to query the link status and waits + * on a timer to invoke the callback. if the callback is invoked then + * latest link status shall be returned or otherwise cached value + * will be returned. + * + * Return: On success, link status shall be returned. + * On error or not associated, link status 0 will be returned. + */ +static int wlan_hdd_get_link_status(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + struct statsContext context; + eHalStatus hstatus; + unsigned long rc; + + if (pHddCtx->isLogpInProgress) { + hddLog(LOGW, FL("LOGP in Progress. Ignore!!!")); + return 0; + } + + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + /* If not associated, then expected link status return value is 0 */ + hddLog(LOG1, FL("Not associated!")); + return 0; + } + + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = LINK_STATUS_MAGIC; + hstatus = sme_getLinkStatus(WLAN_HDD_GET_HAL_CTX(pAdapter), + hdd_GetLink_statusCB, + &context, + pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != hstatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve link status", __func__); + /* return a cached value */ + } else { + /* request is sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_LINK_STATUS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving link status")); + } + } + + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + /* either callback updated pAdapter stats or it has cached data */ + return pAdapter->linkStatus; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static void hdd_wma_send_fastreassoc_cmd(int sessionId, tSirMacAddr bssid, + int channel) +{ + t_wma_roam_invoke_cmd *fastreassoc; + vos_msg_t msg = {0}; + + fastreassoc = vos_mem_malloc(sizeof(*fastreassoc)); + if (NULL == fastreassoc) { + hddLog(LOGE, FL("vos_mem_alloc failed for fastreassoc")); + return; + } + fastreassoc->vdev_id = sessionId; + fastreassoc->channel = channel; + fastreassoc->bssid[0] = bssid[0]; + fastreassoc->bssid[1] = bssid[1]; + fastreassoc->bssid[2] = bssid[2]; + fastreassoc->bssid[3] = bssid[3]; + fastreassoc->bssid[4] = bssid[4]; + fastreassoc->bssid[5] = bssid[5]; + + msg.type = SIR_HAL_ROAM_INVOKE; + msg.reserved = 0; + msg.bodyptr = fastreassoc; + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, + &msg)) { + vos_mem_free(fastreassoc); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Not able to post ROAM_INVOKE_CMD message to WMA")); + } +} +#endif + +/** + * hdd_set_miracast_mode() - function used to set the miracast mode value + * @pAdapter: pointer to the adapter of the interface. + * @command: pointer to the command buffer "MIRACAST ". + * Return: 0 on success -EINVAL on failure. + */ +int hdd_set_miracast_mode(hdd_adapter_t *pAdapter, tANI_U8 *command) +{ + tHalHandle hHal; + tANI_U8 filterType = 0; + hdd_context_t *pHddCtx = NULL; + tANI_U8 *value; + int ret; + eHalStatus ret_status; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (0 != wlan_hdd_validate_context(pHddCtx)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid, Unable to set miracast mode")); + return -EINVAL; + } + + hHal = pHddCtx->hHal; + + value = command + 9; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &filterType); + if (ret < 0) { + /* If the input value is greater than max value of datatype, + * then also kstrtou8 fails + */ + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: kstrtou8 failed range", __func__); + return -EINVAL; + } + + /* Filtertype value should be either 0-Disabled, 1-Source, 2-sink */ + if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) || + (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL)) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Accepted Values are 0 to 2." + "0-Disabled, 1-Source, 2-Sink", __func__); + return -EINVAL; + } + hddLog(VOS_TRACE_LEVEL_INFO, "%s: miracast mode %hu", __func__, filterType); + pHddCtx->miracast_value = filterType; + + ret_status = sme_set_miracast(hHal, filterType); + if (eHAL_STATUS_SUCCESS != ret_status) { + hddLog(LOGE, "Failed to set miracast"); + return -EBUSY; + } + + if (hdd_is_mcc_in_24G(pHddCtx)) { + return hdd_set_mas(pAdapter, filterType); + } + + return 0; +} + +/** + * hdd_set_mas() - Function to set MAS value to UMAC + * @adapter: Pointer to HDD adapter + * @mas_value: 0-Disable, 1-Enable MAS + * + * This function passes down the value of MAS to UMAC + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +int32_t hdd_set_mas(hdd_adapter_t *adapter, tANI_U8 mas_value) +{ + hdd_context_t *hdd_ctx = NULL; + eHalStatus ret_status; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) + return -EFAULT; + + if (mas_value) { + /* Miracast is ON. Disable MAS and configure P2P quota */ + if (hdd_ctx->cfg_ini->enableMCCAdaptiveScheduler) { + if (cfgSetInt(hdd_ctx->hHal, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, 0) + != eSIR_SUCCESS) { + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CCM"); + } + + ret_status = sme_set_mas(false); + if (eHAL_STATUS_SUCCESS != ret_status) { + hddLog(LOGE, "Failed to disable MAS"); + return -EBUSY; + } + } + + /* Config p2p quota */ + if (adapter->device_mode == WLAN_HDD_INFRA_STATION) + hdd_wlan_set_mcc_p2p_quota(adapter, + 100 - HDD_DEFAULT_MCC_P2P_QUOTA); + else if (adapter->device_mode == WLAN_HDD_P2P_GO) + hdd_wlan_go_set_mcc_p2p_quota(adapter, + HDD_DEFAULT_MCC_P2P_QUOTA); + else + hdd_wlan_set_mcc_p2p_quota(adapter, + HDD_DEFAULT_MCC_P2P_QUOTA); + } else { + /* Reset p2p quota */ + if (adapter->device_mode == WLAN_HDD_P2P_GO) + hdd_wlan_go_set_mcc_p2p_quota(adapter, + HDD_RESET_MCC_P2P_QUOTA); + else + hdd_wlan_set_mcc_p2p_quota(adapter, + HDD_RESET_MCC_P2P_QUOTA); + + /* Miracast is OFF. Enable MAS and reset P2P quota */ + if (hdd_ctx->cfg_ini->enableMCCAdaptiveScheduler) { + if (cfgSetInt(hdd_ctx->hHal, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, 1) + != eSIR_SUCCESS) { + hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CCM"); + } + + /* Enable MAS */ + ret_status = sme_set_mas(true); + if (eHAL_STATUS_SUCCESS != ret_status) { + hddLog(LOGE, "Unable to enable MAS"); + return -EBUSY; + } + } + } + + return 0; +} + +/** + * hdd_is_mcc_in_24G() - Function to check for MCC in 2.4GHz + * @hdd_ctx: Pointer to HDD context + * + * This function is used to check for MCC operation in 2.4GHz band. + * STA, P2P and SAP adapters are only considered. + * + * Return: Non zero value if MCC is detected in 2.4GHz band + * + */ +uint8_t hdd_is_mcc_in_24G(hdd_context_t *hdd_ctx) +{ + VOS_STATUS status; + hdd_adapter_t *hdd_adapter = NULL; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + uint8_t ret = 0; + hdd_station_ctx_t *sta_ctx; + hdd_ap_ctx_t *ap_ctx; + uint8_t ch1 = 0, ch2 = 0; + uint8_t channel = 0; + hdd_hostapd_state_t *hostapd_state; + + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + + /* loop through all adapters and check MCC for STA,P2P,SAP adapters */ + while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { + hdd_adapter = adapter_node->pAdapter; + + if (!((hdd_adapter->device_mode >= WLAN_HDD_INFRA_STATION) + || (hdd_adapter->device_mode + <= WLAN_HDD_P2P_GO))) { + /* skip for other adapters */ + status = hdd_get_next_adapter(hdd_ctx, + adapter_node, &next); + adapter_node = next; + continue; + } else { + if (WLAN_HDD_INFRA_STATION == + hdd_adapter->device_mode || + WLAN_HDD_P2P_CLIENT == + hdd_adapter->device_mode) { + sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR( + hdd_adapter); + if (eConnectionState_Associated == + sta_ctx->conn_info.connState) + channel = + sta_ctx->conn_info. + operationChannel; + } else if (WLAN_HDD_P2P_GO == + hdd_adapter->device_mode || + WLAN_HDD_SOFTAP == + hdd_adapter->device_mode) { + ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hdd_adapter); + hostapd_state = + WLAN_HDD_GET_HOSTAP_STATE_PTR( + hdd_adapter); + if (hostapd_state->bssState == BSS_START && + hostapd_state->vosStatus == + VOS_STATUS_SUCCESS) + channel = ap_ctx->operatingChannel; + } + + if ((ch1 == 0) || + ((ch2 != 0) && (ch2 != channel))) { + ch1 = channel; + } else if ((ch2 == 0) || + ((ch1 != 0) && (ch1 != channel))) { + ch2 = channel; + } + + if ((ch1 != 0 && ch2 != 0) && (ch1 != ch2) && + ((ch1 <= SIR_11B_CHANNEL_END) && + (ch2 <= SIR_11B_CHANNEL_END))) { + hddLog(LOGE, + "MCC in 2.4Ghz on channels %d and %d", + ch1, ch2); + return 1; + } + + status = hdd_get_next_adapter(hdd_ctx, + adapter_node, &next); + adapter_node = next; + } + } + return ret; +} + +/** + * wlan_hdd_get_link_speed() - get link speed + * @pAdapter: pointer to the adapter + * @link_speed: pointer to link speed + * + * This function fetches per bssid link speed. + * + * Return: if associated, link speed shall be returned. + * if not associated, link speed of 0 is returned. + * On error, error number will be returned. + */ +int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed) +{ + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(sta_adapter); + hdd_station_ctx_t *hdd_stactx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); + int ret; + + ret = wlan_hdd_validate_context(hddctx); + + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (eConnectionState_Associated != hdd_stactx->conn_info.connState) { + /* we are not connected so we don't have a classAstats */ + *link_speed = 0; + } else { + VOS_STATUS status; + tSirMacAddr bssid; + + vos_mem_copy(bssid, hdd_stactx->conn_info.bssId, VOS_MAC_ADDR_SIZE); + + status = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("Unable to retrieve SME linkspeed")); + return -EINVAL; + } + *link_speed = sta_adapter->ls_stats.estLinkSpeed; + /* linkspeed in units of 500 kbps */ + *link_speed = (*link_speed) / 500; + } + return 0; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * hdd_parse_ese_beacon_req() - Parse ese beacon request + * @pValue: Pointer to input data (its a NUL terminated string) + * @pEseBcnReq: pEseBcnReq output pointer to store parsed ie information + * + * This function parses the ese beacon request passed in the format + * CCXBEACONREQ + * Channel 1Scan Mode Meas DurationChannel N + * Scan Mode NMeas Duration N + * if the Number of bcn req fields (N) does not match with the actual number of + * fields passed then take N. + * and are treated as one pair + * For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40. + * This function does not take care of removing duplicate channels from the list + * + * Return: 0 for success non-zero for failure + */ +static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, + tCsrEseBeaconReq *pEseBcnReq) +{ + tANI_U8 *inPtr = pValue; + int tempInt = 0; + int j = 0, i = 0, v = 0; + char buf[32]; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) { + return -EINVAL; + } else if (SPACE_ASCII_VALUE != *inPtr) { + /* no space after the command */ + return -EINVAL; + } + + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) return -EINVAL; + + /* Getting the first argument ie measurement token */ + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) return -EINVAL; + + v = kstrtos32(buf, 10, &tempInt); + if (v < 0) return -EINVAL; + + pEseBcnReq->numBcnReqIe = tempInt; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe); + + for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++) { + for (i = 0; i < 4; i++) { + /* inPtr pointing to the beginning of first space after number of + ie fields */ + inPtr = strpbrk( inPtr, " " ); + /* no ie data after the number of ie fields argument */ + if (NULL == inPtr) return -EINVAL; + + /* removing empty space */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + /* no ie data after the number of ie fields argument and spaces */ + if ('\0' == *inPtr) return -EINVAL; + + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) return -EINVAL; + + v = kstrtos32(buf, 10, &tempInt); + if (v < 0) return -EINVAL; + + switch (i) { + case 0: /* Measurement token */ + if (tempInt <= 0) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid Measurement Token(%d)", tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].measurementToken = tempInt; + break; + + case 1: /* Channel number */ + if ((tempInt <= 0) || + (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid Channel Number(%d)", tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].channel = tempInt; + break; + + case 2: /* Scan mode */ + if ((tempInt < eSIR_PASSIVE_SCAN) || + (tempInt > eSIR_BEACON_TABLE)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].scanMode= tempInt; + break; + + case 3: /* Measurement duration */ + if (((tempInt <= 0) && + (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) || + ((tempInt < 0) && + (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE))) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid Measurement Duration(%d)", tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].measurementDuration = tempInt; + break; + } + } + } + + for (j = 0; j < pEseBcnReq->numBcnReqIe; j++) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Index(%d) Measurement Token(%u) Channel(%u) Scan Mode(%u) Measurement Duration(%u)", + j, + pEseBcnReq->bcnReq[j].measurementToken, + pEseBcnReq->bcnReq[j].channel, + pEseBcnReq->bcnReq[j].scanMode, + pEseBcnReq->bcnReq[j].measurementDuration); + } + + return VOS_STATUS_SUCCESS; +} + +static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, + const tANI_U32 staId, + void *pContext ) +{ + struct statsContext *pStatsContext = NULL; + hdd_adapter_t *pAdapter = NULL; + + if (NULL == pContext) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pContext [%p]", + __func__, pContext); + return; + } + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + pStatsContext = pContext; + pAdapter = pStatsContext->pAdapter; + if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pStatsContext->magic); + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pStatsContext->magic = 0; + + /* copy over the tsm stats */ + pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly; + vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist, + tsmMetrics.UplinkPktQueueDlyHist, + sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/ + sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0])); + pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly; + pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss; + pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount; + pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount; + pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly; + + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, + const tANI_U8 tid, + tAniTrafStrmMetrics* pTsmMetrics) +{ + hdd_station_ctx_t *pHddStaCtx = NULL; + eHalStatus hstatus; + VOS_STATUS vstatus = VOS_STATUS_SUCCESS; + unsigned long rc; + struct statsContext context; + hdd_context_t *pHddCtx = NULL; + + if (NULL == pAdapter) { + hddLog(LOGE, FL("pAdapter is NULL")); + return VOS_STATUS_E_FAULT; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* we are connected prepare our callback context */ + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = STATS_CONTEXT_MAGIC; + + /* query tsm stats */ + hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB, + pHddStaCtx->conn_info.staId[ 0 ], + pHddStaCtx->conn_info.bssId, + &context, pHddCtx->pvosContext, tid); + if (eHAL_STATUS_SUCCESS != hstatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics", + __func__); + vstatus = VOS_STATUS_E_FAULT; + } else { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME timed out while retrieving statistics", + __func__); + vstatus = VOS_STATUS_E_TIMEOUT; + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + if (VOS_STATUS_SUCCESS == vstatus) { + pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly; + vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist, + pAdapter->tsmStats.UplinkPktQueueDlyHist, + sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/ + sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0])); + pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly; + pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss; + pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount; + pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount; + pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly; + } + return vstatus; +} + +/** + * hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE + * @pValue: Pointer to input data + * @pCckmIe: Pointer to output cckm Ie + * @pCckmIeLen: Pointer to output cckm ie length + * + * This function parses the SETCCKM IE command + * + * Return: 0 for success non-zero for failure + */ +static VOS_STATUS +hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen) +{ + tANI_U8 *inPtr = pValue; + tANI_U8 *dataEnd; + int j = 0; + int i = 0; + tANI_U8 tempByte = 0; + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) { + return -EINVAL; + } else if (SPACE_ASCII_VALUE != *inPtr) { + /* no space after the command */ + return -EINVAL; + } + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + /* find the length of data */ + dataEnd = inPtr; + while('\0' != *dataEnd) { + dataEnd++; + ++(*pCckmIeLen); + } + if (*pCckmIeLen <= 0) return -EINVAL; + /* + * Allocate the number of bytes based on the number of input characters + * whether it is even or odd. + * if the number of input characters are even, then we need N/2 byte. + * if the number of input characters are odd, then we need do (N+1)/2 to + * compensate rounding off. + * For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough. + * If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes + */ + *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2); + if (NULL == *pCckmIe) { + hddLog(LOGP, FL("vos_mem_alloc failed")); + return -ENOMEM; + } + vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2); + /* + * the buffer received from the upper layer is character buffer, + * we need to prepare the buffer taking 2 characters in to a U8 hex + * decimal number for example 7f0000f0...form a buffer to contain + * 7f in 0th location, 00 in 1st and f0 in 3rd location + */ + for (i = 0, j = 0; j < *pCckmIeLen; j += 2) { + tempByte = (hdd_parse_hex(inPtr[j]) << 4) + | (hdd_parse_hex(inPtr[j + 1])); + (*pCckmIe)[i++] = tempByte; + } + *pCckmIeLen = i; + return VOS_STATUS_SUCCESS; +} + +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/** + * drv_cmd_set_fcc_channel() - handle fcc constraint request + * @hdd_ctx: HDD context + * @cmd: command ptr + * @cmd_len: command len + * + * Return: status + */ +static int drv_cmd_set_fcc_channel(hdd_context_t *hdd_ctx, uint8_t *cmd, + uint8_t cmd_len) +{ + uint8_t *value; + uint8_t fcc_constraint; + eHalStatus status; + int ret = 0; + + value = cmd + cmd_len + 1; + + ret = kstrtou8(value, 10, &fcc_constraint); + if ((ret < 0) || (fcc_constraint > 1)) { + /* + * If the input value is greater than max value of datatype, + * then also it is a failure + */ + hddLog(LOGE, FL("value out of range")); + return -EINVAL; + } + + status = sme_disable_non_fcc_channel(hdd_ctx->hHal, !fcc_constraint); + if (status != eHAL_STATUS_SUCCESS) + ret = -EPERM; + + return ret; +} + +/** + * hdd_set_rx_filter() - set RX filter + * @adapter: Pointer to adapter + * @action: Filter action + * @pattern: Address pattern + * + * Address pattern is most significant byte of address for example + * 0x01 for IPV4 multicast address + * 0x33 for IPV6 multicast address + * 0xFF for broadcast address + * + * Return: 0 for success, non-zero for failure + */ +static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, + uint8_t pattern) +{ + int ret; + uint8_t i; + tHalHandle handle; + tSirRcvFltMcAddrList *filter; + hdd_context_t* hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + handle = hdd_ctx->hHal; + + if (NULL == handle) { + hddLog(LOGE, FL("HAL Handle is NULL")); + return -EINVAL; + } + + /* + * If action is false it means start dropping packets + * Set addr_filter_pattern which will be used when sending + * MC/BC address list to target + */ + if (!action) + adapter->addr_filter_pattern = pattern; + else + adapter->addr_filter_pattern = 0; + + if (((adapter->device_mode == WLAN_HDD_INFRA_STATION) || + (adapter->device_mode == WLAN_HDD_P2P_CLIENT)) && + adapter->mc_addr_list.mc_cnt && + hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + + + filter = vos_mem_malloc(sizeof(*filter)); + if (NULL == filter) { + hddLog(LOGE, FL("Could not allocate Memory")); + return -ENOMEM; + } + vos_mem_zero(filter, sizeof(*filter)); + filter->action = action; + for (i = 0; i < adapter->mc_addr_list.mc_cnt; i++) { + if (!memcmp(adapter->mc_addr_list.addr[i], + &pattern, 1)) { + memcpy(filter->multicastAddr[i], + adapter->mc_addr_list.addr[i], + sizeof(adapter->mc_addr_list.addr[i])); + filter->ulMulticastAddrCnt++; + hddLog(LOG1, "%s RX filter : addr =" + MAC_ADDRESS_STR, + action ? "setting" : "clearing", + MAC_ADDR_ARRAY(filter->multicastAddr[i])); + } + } + /* Set rx filter */ + sme_8023MulticastList(handle, adapter->sessionId, filter); + vos_mem_free(filter); + } else { + hddLog(LOGW, FL("mode %d mc_cnt %d"), + adapter->device_mode, adapter->mc_addr_list.mc_cnt); + } + + return 0; +} + +/** + * hdd_driver_rxfilter_comand_handler() - RXFILTER driver command handler + * @command: Pointer to input string driver command + * @adapter: Pointer to adapter + * @action: Action to enable/disable filtering + * + * If action == false + * Start filtering out data packets based on type + * RXFILTER-REMOVE 0 -> Start filtering out unicast data packets + * RXFILTER-REMOVE 1 -> Start filtering out broadcast data packets + * RXFILTER-REMOVE 2 -> Start filtering out IPV4 mcast data packets + * RXFILTER-REMOVE 3 -> Start filtering out IPV6 mcast data packets + * + * if action == true + * Stop filtering data packets based on type + * RXFILTER-ADD 0 -> Stop filtering unicast data packets + * RXFILTER-ADD 1 -> Stop filtering broadcast data packets + * RXFILTER-ADD 2 -> Stop filtering IPV4 mcast data packets + * RXFILTER-ADD 3 -> Stop filtering IPV6 mcast data packets + * + * Current implementation only supports IPV4 address filtering by + * selectively allowing IPV4 multicast data packest based on + * address list received in .ndo_set_rx_mode + * + * Return: 0 for success, non-zero for failure + */ +static int hdd_driver_rxfilter_comand_handler(uint8_t *command, + hdd_adapter_t *adapter, + bool action) +{ + int ret = 0; + uint8_t *value; + uint8_t type; + + value = command; + /* Skip space after RXFILTER-REMOVE OR RXFILTER-ADD based on action */ + if (!action) + value = command + 16; + else + value = command + 13; + ret = kstrtou8(value, 10, &type); + if (ret < 0) { + hddLog(LOGE, + FL("kstrtou8 failed invalid input value %d"), type); + return -EINVAL; + } + + switch (type) { + case 2: + /* Set rx filter for IPV4 multicast data packets */ + ret = hdd_set_rx_filter(adapter, action, 0x01); + break; + default: + hddLog(LOG1, FL("Unsupported RXFILTER type %d"), type); + break; + } + + return ret; +} + +/** + * hdd_parse_setantennamode_command() - HDD Parse SETANTENNAMODE + * command + * @value: Pointer to SETANTENNAMODE command + * @mode: Pointer to antenna mode + * + * This function parses the SETANTENNAMODE command passed in the format + * SETANTENNAMODEmode + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_setantennamode_command(const uint8_t *value, + int *mode) +{ + const uint8_t *in_ptr = value; + int tmp, v; + char arg1[32]; + *mode = 0; + + in_ptr = strnchr(value, strlen(value), SPACE_ASCII_VALUE); + + /* no argument after the command */ + if (NULL == in_ptr) { + hddLog(LOGE, FL("No argument after the command")); + return -EINVAL; + } + + /* no space after the command */ + if (SPACE_ASCII_VALUE != *in_ptr) { + hddLog(LOGE, FL("No space after the command")); + return -EINVAL; + } + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *in_ptr) && ('\0' != *in_ptr)) + in_ptr++; + + /* no argument followed by spaces */ + if ('\0' == *in_ptr) { + hddLog(LOGE, FL("No argument followed by spaces")); + return -EINVAL; + } + + /* get the argument i.e. antenna mode */ + v = sscanf(in_ptr, "%31s ", arg1); + if (1 != v) { + hddLog(LOGE, FL("argument retrieval from cmd string failed")); + return -EINVAL; + } + + v = kstrtos32(arg1, 10, &tmp); + if (v < 0) { + hddLog(LOGE, FL("argument string to integer conversion failed")); + return -EINVAL; + } + *mode = tmp; + + return 0; +} + +/** + * hdd_is_supported_chain_mask_2x2() - Verify if supported chain + * mask is 2x2 mode + * @hdd_ctx: Pointer to hdd contex + * + * Return: true if supported chain mask 2x2 else false + */ +static bool hdd_is_supported_chain_mask_2x2(hdd_context_t *hdd_ctx) +{ + hdd_config_t *config = hdd_ctx->cfg_ini; + + if (hdd_ctx->per_band_chainmask_supp == 0x01) { + return (((hdd_ctx->supp_2g_chain_mask & 0x03) + == 0x03) || + ((hdd_ctx->supp_5g_chain_mask & 0x03) + == 0x03)) ? true : false; + } + + return (config->enable2x2 == 0x01) ? true : false; +} + +/** + * hdd_is_supported_chain_mask_1x1() - Verify if the supported + * chain mask is 1x1 + * @hdd_ctx: Pointer to hdd contex + * + * Return: true if supported chain mask 1x1 else false + */ +static bool hdd_is_supported_chain_mask_1x1(hdd_context_t *hdd_ctx) +{ + hdd_config_t *config = hdd_ctx->cfg_ini; + + if (hdd_ctx->per_band_chainmask_supp == 0x01) { + return ((hdd_ctx->supp_2g_chain_mask <= 0x02) && + (hdd_ctx->supp_5g_chain_mask <= 0x02)) ? + true : false; + } + + return (!config->enable2x2) ? true : false; +} + +/** + * switch_antenna_mode_non_conn_state() - Dynamic switch to 1x1 + * antenna mode when there are no connections + * @hdd_ctx: Pointer to hdd contex + * @adapter: Pointer to hdd adapter + * @chains: Number of TX/RX chains to set + * + * Return: 0 if success else non zero + */ +static int switch_antenna_mode_non_conn_state(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + uint8_t chains) +{ + int ret; + eHalStatus hal_status; + bool enable_smps; + int smps_mode; + + ret = wlan_hdd_update_txrx_chain_mask(hdd_ctx, + (chains == 2) ? 0x3 : 0x1); + + if (0 != ret) { + hddLog(LOGE, + FL("Failed to update chain mask: %d"), + chains); + return ret; + } + + /* Update HT SMPS as static/disabled in the SME configuration + * If there is STA connection followed by dynamic switch + * to 1x1 protocol stack would include SM power save IE as + * static in the assoc mgmt frame and after association + * SMPS force mode command will be sent to FW to initiate + * SMPS action frames to AP. In this case, SMPS force mode + * command event can be expected from firmware with the + * TX status of SMPS action frames. Inclusion of SM power + * save IE and sending of SMPS action frames will not happen + * for switch to 2x2 mode. But SME config should still be + * updated to disabled. + */ + adapter->smps_force_mode_status = 0; + + enable_smps = (chains == 1) ? true : false; + smps_mode = (chains == 1) ? HDD_SMPS_MODE_STATIC : + HDD_SMPS_MODE_DISABLED; + + hal_status = sme_update_mimo_power_save(hdd_ctx->hHal, + enable_smps, smps_mode); + if (eHAL_STATUS_SUCCESS != hal_status) { + hddLog(LOG1, + FL("Update MIMO power SME config failed: %d"), + hal_status); + return -EFAULT; + } + + hddLog(LOG1, FL("Updated SME config enable smps: %d mode: %d"), + enable_smps, smps_mode); + + return 0; +} + +/** + * switch_to_1x1_connected_sta_state() - Dynamic switch to 1x1 + * antenna mode in standalone station + * @hdd_ctx: Pointer to hdd contex + * @adapter: Pointer to hdd adapter + * + * Return: 0 if success else non zero + */ +static int switch_to_1x1_connected_sta_state(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + int ret; + eHalStatus hal_status; + bool send_smps; + + /* Check TDLS status and update antenna mode */ + ret = wlan_hdd_tdls_antenna_switch(hdd_ctx, adapter, + HDD_ANTENNA_MODE_1X1); + if (0 != ret) + return ret; + + /* If intersection of sta and AP NSS is 1x1 then + * skip SMPS indication to AP. Only update the chain mask + * and other configuration. + */ + send_smps = sme_is_sta_smps_allowed(hdd_ctx->hHal, + adapter->sessionId); + if (!send_smps) { + hddLog(LOGE, FL("Need not indicate SMPS to AP")); + goto chain_mask; + } + + INIT_COMPLETION(adapter->smps_force_mode_comp_var); + + hddLog(LOG1, FL("Send SMPS force mode command")); + ret = process_wma_set_command((int)adapter->sessionId, + WMI_STA_SMPS_FORCE_MODE_CMDID, + WMI_SMPS_FORCED_MODE_STATIC, + VDEV_CMD); + if (0 != ret) { + hddLog(LOGE, + FL("Failed to send SMPS force mode to static")); + return ret; + } + + /* Block on SMPS force mode event only for mode static */ + ret = wait_for_completion_timeout( + &adapter->smps_force_mode_comp_var, + msecs_to_jiffies(WLAN_WAIT_SMPS_FORCE_MODE)); + if (!ret) { + hddLog(LOGE, + FL("SMPS force mode event timeout: %d"), + ret); + return -EFAULT; + } + ret = adapter->smps_force_mode_status; + adapter->smps_force_mode_status = 0; + if (0 != ret) { + hddLog(LOGE, FL("SMPS force mode status: %d "), + ret); + return ret; + } + +chain_mask: + hddLog(LOG1, FL("Update chain mask to 1x1")); + ret = wlan_hdd_update_txrx_chain_mask(hdd_ctx, 1); + if (0 != ret) { + hddLog(LOGE, FL("Failed to switch to 1x1 mode")); + return ret; + } + + /* Update SME SM power save config */ + hal_status = sme_update_mimo_power_save(hdd_ctx->hHal, + true, HDD_SMPS_MODE_STATIC); + if (eHAL_STATUS_SUCCESS != hal_status) { + hddLog(LOG1, + FL("Failed to update SMPS config to static: %d"), + hal_status); + return -EFAULT; + } + + hddLog(LOG1, FL("Successfully switched to 1x1 mode")); + return 0; +} + +/** + * switch_to_2x2_connected_sta_state() - Dynamic switch to 2x2 + * antenna mode in standalone station + * @hdd_ctx: Pointer to hdd contex + * @adapter: Pointer to hdd adapter + * + * Return: 0 if success else non zero + */ +static int switch_to_2x2_connected_sta_state(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + int ret; + eHalStatus hal_status; + bool send_smps; + + /* Check TDLS status and update antenna mode */ + ret = wlan_hdd_tdls_antenna_switch(hdd_ctx, adapter, + HDD_ANTENNA_MODE_2X2); + if (0 != ret) + return ret; + + hddLog(LOG1, FL("Update chain mask to 2x2")); + ret = wlan_hdd_update_txrx_chain_mask(hdd_ctx, 3); + if (0 != ret) { + hddLog(LOGE, FL("Failed to switch to 2x2 mode")); + return ret; + } + + /* If intersection of sta and AP NSS is 1x1 then + * skip SMPS indication to AP. + */ + send_smps = sme_is_sta_smps_allowed(hdd_ctx->hHal, + adapter->sessionId); + if (!send_smps) { + hddLog(LOGE, FL("Need not indicate SMPS to AP")); + goto exit; + } + + hddLog(LOG1, FL("Send SMPS force mode command ")); + + /* No need to block on SMPS force mode event when + * the mode switch is 2x2 since the chain mask + * has already been updated to 2x2 + */ + ret = process_wma_set_command((int)adapter->sessionId, + WMI_STA_SMPS_FORCE_MODE_CMDID, + WMI_SMPS_FORCED_MODE_DISABLED, + VDEV_CMD); + if (0 != ret) { + hddLog(LOGE, + FL("Failed to send SMPS force mode to disabled")); + return ret; + } + +exit: + /* Update SME SM power save config */ + hal_status = sme_update_mimo_power_save(hdd_ctx->hHal, + false, HDD_SMPS_MODE_DISABLED); + if (eHAL_STATUS_SUCCESS != hal_status) { + hddLog(LOG1, + FL("Failed to update SMPS config to disable: %d"), + hal_status); + return -EFAULT; + } + + hddLog(LOG1, FL("Successfully switched to 2x2 mode")); + return 0; +} + +/** + * drv_cmd_set_antenna_mode() - SET ANTENNA MODE driver command + * handler + * @hdd_ctx: Pointer to hdd context + * @cmd: Pointer to input command + * @command_len: Command length + * + * Return: 0 for success non-zero for failure + */ +static int drv_cmd_set_antenna_mode(hdd_adapter_t *adapter, + uint8_t *command, + uint8_t cmd_len) +{ + int ret; + int mode; + uint8_t *value = command; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if ((hdd_ctx->concurrency_mode > 1) || + (hdd_ctx->no_of_active_sessions[WLAN_HDD_INFRA_STATION] > 1)) { + hddLog(LOGE, FL("Operation invalid in non sta or concurrent mode")); + ret = -EPERM; + goto exit; + } + + ret = hdd_parse_setantennamode_command(value, &mode); + if (0 != ret) { + hddLog(LOGE, FL("Invalid SETANTENNA command")); + goto exit; + } + + hddLog(LOG1, FL("Request to switch antenna mode to: %d"), mode); + + if (hdd_ctx->current_antenna_mode == mode) { + hddLog(LOGE, FL("System already in the requested mode")); + ret = 0; + goto exit; + } + + if ((HDD_ANTENNA_MODE_2X2 == mode) && + (!hdd_is_supported_chain_mask_2x2(hdd_ctx))) { + hddLog(LOGE, FL("System does not support 2x2 mode")); + ret = -EPERM; + goto exit; + } + + if ((HDD_ANTENNA_MODE_1X1 == mode) && + hdd_is_supported_chain_mask_1x1(hdd_ctx)) { + hddLog(LOGE, FL("System already in 1x1 mode")); + ret = 0; + goto exit; + } + + /* Non connected state */ + if (0 == wlan_hdd_get_active_session_count(hdd_ctx)) { + hddLog(LOG1, + FL("Switch to %d x %d in non connected state"), + mode, mode); + + ret = switch_antenna_mode_non_conn_state( + hdd_ctx, adapter, mode); + if (0 != ret) { + hddLog(LOGE, + FL("Failed to switch to %d x %d mode"), + mode, mode); + goto exit; + } + + hdd_ctx->current_antenna_mode = (mode == 1) ? + HDD_ANTENNA_MODE_1X1 : HDD_ANTENNA_MODE_2X2; + + } else if ((hdd_ctx->concurrency_mode <= 1) && + (hdd_ctx->no_of_active_sessions[ + WLAN_HDD_INFRA_STATION] <= 1)) { + hddLog(LOG1, + FL("Switch to %d x %d in connected sta state"), + mode, mode); + + if (HDD_ANTENNA_MODE_1X1 == mode) { + ret = switch_to_1x1_connected_sta_state( + hdd_ctx, adapter); + if (0 != ret) { + hddLog(LOGE, + FL("Failed to switch to 1x1 mode")); + goto exit; + } + hdd_ctx->current_antenna_mode = + HDD_ANTENNA_MODE_1X1; + + } else if (HDD_ANTENNA_MODE_2X2 == mode) { + ret = switch_to_2x2_connected_sta_state( + hdd_ctx, adapter); + if (0 != ret) { + hddLog(LOGE, + FL("Failed to switch to 2x2 mode")); + goto exit; + } + hdd_ctx->current_antenna_mode = + HDD_ANTENNA_MODE_2X2; + } + } + + /* Update the user requested nss in the mac context. + * This will be used in tdls protocol engine to form tdls + * Management frames. + */ + sme_update_user_configured_nss( + hdd_ctx->hHal, + hdd_ctx->current_antenna_mode); + +exit: +#ifdef FEATURE_WLAN_TDLS + /* Reset tdls NSS flags */ + if (hdd_ctx->tdls_nss_switch_in_progress && + hdd_ctx->tdls_nss_teardown_complete) { + hdd_ctx->tdls_nss_switch_in_progress = false; + hdd_ctx->tdls_nss_teardown_complete = false; + } + + hddLog(LOG1, + FL("tdls_nss_switch_in_progress: %d tdls_nss_teardown_complete: %d"), + hdd_ctx->tdls_nss_switch_in_progress, + hdd_ctx->tdls_nss_teardown_complete); +#endif + hddLog(LOG1, FL("Set antenna status: %d current mode: %d"), + ret, hdd_ctx->current_antenna_mode); + return ret; +} + +/** + * drv_cmd_get_antenna_mode() - GET ANTENNA MODE driver command + * handler + * @adapter: Pointer to hdd adapter + * @hdd_ctx: Pointer to hdd context + * @command: Pointer to input command + * @command_len: length of the command + * @priv_data: private data coming with the driver command + * + * Return: 0 for success non-zero for failure + */ +static inline int drv_cmd_get_antenna_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + uint32_t antenna_mode = 0; + char extra[32]; + uint8_t len = 0; + + antenna_mode = hdd_ctx->current_antenna_mode; + len = scnprintf(extra, sizeof(extra), "%s %d", command, + antenna_mode); + len = VOS_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + hddLog(LOGE, FL("Failed to copy data to user buffer")); + return -EFAULT; + } + + return 0; +} + +static int hdd_driver_command(hdd_adapter_t *pAdapter, + hdd_priv_data_t *ppriv_data) +{ + hdd_priv_data_t priv_data; + tANI_U8 *command = NULL; + int ret = 0; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* + * Note that valid pointers are provided by caller + */ + + /* copy to local struct to avoid numerous changes to legacy code */ + priv_data = *ppriv_data; + + if (priv_data.total_len <= 0 || + priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN) + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s:invalid priv_data.total_len(%d)!!!", __func__, + priv_data.total_len); + ret = -EINVAL; + goto exit; + } + + /* Allocate +1 for '\0' */ + command = kmalloc(priv_data.total_len + 1, GFP_KERNEL); + if (!command) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to allocate memory", __func__); + ret = -ENOMEM; + goto exit; + } + + if (copy_from_user(command, priv_data.buf, priv_data.total_len)) + { + ret = -EFAULT; + goto exit; + } + + /* Make sure the command is NUL-terminated */ + command[priv_data.total_len] = '\0'; + + /* at one time the following block of code was conditional. braces + * have been retained to avoid re-indenting the legacy code + */ + { + hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Received %s cmd from Wi-Fi GUI***", __func__, command); + + if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 ) + { + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL, + pAdapter->sessionId, (unsigned) + (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 | + *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 | + *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 | + *(pHddCtx->p2pDeviceAddress.bytes+5)))); + if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes, + sizeof(tSirMacAddr))) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + } + } + else if (strncmp(command, "SETBAND", 7) == 0) + { + tANI_U8 *ptr = command ; + int ret = 0 ; + + /* Change band request received */ + + /* First 8 bytes will have "SETBAND " and + * 9 byte will have band setting value */ + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: SetBandCommand Info comm %s UL %d, TL %d", + __func__, command, priv_data.used_len, priv_data.total_len); + /* Change band request received */ + ret = hdd_setBand_helper(pAdapter->dev, ptr); + } + else if (strncmp(command, "SETWMMPS", 8) == 0) + { + tANI_U8 *ptr = command; + ret = hdd_wmmps_helper(pAdapter, ptr); + } + else if (strncasecmp(command, "COUNTRY", 7) == 0) + { + eHalStatus status; + unsigned long rc; + char *country_code; + + country_code = command + 8; + + INIT_COMPLETION(pAdapter->change_country_code); + hdd_checkandupdate_dfssetting(pAdapter, country_code); + + status = + sme_ChangeCountryCode(pHddCtx->hHal, + (void *)(tSmeChangeCountryCallback) + wlan_hdd_change_country_code_callback, + country_code, pAdapter, + pHddCtx->pvosContext, + eSIR_TRUE, eSIR_TRUE); + if (status == eHAL_STATUS_SUCCESS) + { + rc = wait_for_completion_timeout( + &pAdapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME while setting country code timed out", + __func__); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME Change Country code fail, status=%d", + __func__, status); + ret = -EINVAL; + } + + } + else if (strncmp(command, "SETSUSPENDMODE", 14) == 0) + { + } +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + else if (strncmp(command, "SETROAMTRIGGER", 14) == 0) + { + tANI_U8 *value = command; + tANI_S8 rssi = 0; + tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT; + eHalStatus status = eHAL_STATUS_SUCCESS; + + /* Move pointer to ahead of SETROAMTRIGGER */ + value = value + 15; + + /* Convert the value from ascii to integer */ + ret = kstrtos8(value, 10, &rssi); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", + __func__, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX); + ret = -EINVAL; + goto exit; + } + + lookUpThreshold = abs(rssi); + + if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) || + (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Neighbor lookup threshold value %d is out of range" + " (Min: %d Max: %d)", lookUpThreshold, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX); + ret = -EINVAL; + goto exit; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL, + pAdapter->sessionId, lookUpThreshold)); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set Roam trigger" + " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold); + + pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold; + status = sme_setNeighborLookupRssiThreshold(pHddCtx->hHal, + pAdapter->sessionId, + lookUpThreshold); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to set roam trigger, try again", __func__); + ret = -EPERM; + goto exit; + } + + /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */ + pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = + lookUpThreshold + 5; + sme_setNeighborReassocRssiThreshold(pHddCtx->hHal, + pAdapter->sessionId, + lookUpThreshold + 5); + } + else if (strncmp(command, "GETROAMTRIGGER", 14) == 0) + { + tANI_U8 lookUpThreshold = + sme_getNeighborLookupRssiThreshold(pHddCtx->hHal); + int rssi = (-1) * lookUpThreshold; + char extra[32]; + tANI_U8 len = 0; + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL, + pAdapter->sessionId, lookUpThreshold)); + len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0) + { + tANI_U8 *value = command; + tANI_U8 roamScanPeriod = 0; + tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT; + + /* input refresh period is in terms of seconds */ + /* Move pointer to ahead of SETROAMSCANPERIOD */ + value = value + 18; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &roamScanPeriod); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", + __func__, + (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000), + (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)); + ret = -EINVAL; + goto exit; + } + + if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) || + (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Roam scan period value %d is out of range" + " (Min: %d Max: %d)", roamScanPeriod, + (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000), + (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)); + ret = -EINVAL; + goto exit; + } + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL, + pAdapter->sessionId, roamScanPeriod)); + neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan period" + " (Empty Scan refresh period) = %d", __func__, roamScanPeriod); + + pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod; + sme_UpdateEmptyScanRefreshPeriod(pHddCtx->hHal, + pAdapter->sessionId, + neighborEmptyScanRefreshPeriod); + } + else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0) + { + tANI_U16 nEmptyScanRefreshPeriod = + sme_getEmptyScanRefreshPeriod(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL, + pAdapter->sessionId, nEmptyScanRefreshPeriod)); + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000)); + /* Returned value is in units of seconds */ + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0) + { + tANI_U8 *value = command; + tANI_U8 roamScanRefreshPeriod = 0; + tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT; + + /* input refresh period is in terms of seconds */ + /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD */ + value = value + 25; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &roamScanRefreshPeriod); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", + __func__, + (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000), + (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)); + ret = -EINVAL; + goto exit; + } + + if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) || + (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Neighbor scan results refresh period value %d is out of range" + " (Min: %d Max: %d)", roamScanRefreshPeriod, + (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000), + (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)); + ret = -EINVAL; + goto exit; + } + neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan refresh period" + " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod); + + pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod; + sme_setNeighborScanRefreshPeriod(pHddCtx->hHal, + pAdapter->sessionId, + neighborScanRefreshPeriod); + } + else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0) + { + tANI_U16 value = sme_getNeighborScanRefreshPeriod(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMSCANREFRESHPERIOD", (value/1000)); + /* Returned value is in units of seconds */ + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#ifdef FEATURE_WLAN_LFR + /* SETROAMMODE */ + else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + + /* Move pointer to ahead of SETROAMMODE */ + value = value + SIZE_OF_SETROAMMODE + 1; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) || + (roamMode > CFG_LFR_FEATURE_ENABLED_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Roam Mode value %d is out of range" + " (Min: %d Max: %d)", roamMode, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + "%s: Received Command to Set Roam Mode = %d", __func__, roamMode); + /* + * Note that + * SETROAMMODE 0 is to enable LFR while + * SETROAMMODE 1 is to disable LFR, but + * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable. + * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */ + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */ + + pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode; + /* LFR2 is dependent on Fast Roam. So, enable/disable LFR2 + * variable. if Fast Roam has been changed from disabled to enabled, + * then enable LFR2 and send the LFR START command to the firmware. + * Otherwise, send the LFR STOP command to the firmware and then + * disable LFR2.The sequence is different. + */ + if (roamMode) { + pHddCtx->cfg_ini->isRoamOffloadScanEnabled = roamMode; + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), + pHddCtx->cfg_ini->isRoamOffloadScanEnabled); + sme_UpdateIsFastRoamIniFeatureEnabled(pHddCtx->hHal, + pAdapter->sessionId, + roamMode); + } else { + sme_UpdateIsFastRoamIniFeatureEnabled(pHddCtx->hHal, + pAdapter->sessionId, + roamMode); + pHddCtx->cfg_ini->isRoamOffloadScanEnabled = roamMode; + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), + pHddCtx->cfg_ini->isRoamOffloadScanEnabled); + } + } + /* GETROAMMODE */ + else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0) + { + tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + /* + * roamMode value shall be inverted because the semantics is + * different. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#endif +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + else if (strncmp(command, "SETROAMDELTA", 12) == 0) + { + tANI_U8 *value = command; + tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT; + + /* Move pointer to ahead of SETROAMDELTA */ + value = value + 13; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &roamRssiDiff); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_RSSI_DIFF_MIN, + CFG_ROAM_RSSI_DIFF_MAX); + ret = -EINVAL; + goto exit; + } + + if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) || + (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Roam rssi diff value %d is out of range" + " (Min: %d Max: %d)", roamRssiDiff, + CFG_ROAM_RSSI_DIFF_MIN, + CFG_ROAM_RSSI_DIFF_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff); + + pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff; + sme_UpdateRoamRssiDiff(pHddCtx->hHal, + pAdapter->sessionId, roamRssiDiff); + } + else if (strncmp(command, "GETROAMDELTA", 12) == 0) + { + tANI_U8 roamRssiDiff = sme_getRoamRssiDiff(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMDELTA_IOCTL, + pAdapter->sessionId, roamRssiDiff)); + len = scnprintf(extra, sizeof(extra), "%s %d", + command, roamRssiDiff); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + else if (strncmp(command, "GETBAND", 7) == 0) + { + int band = -1; + char extra[32]; + tANI_U8 len = 0; + hdd_getBand_helper(pHddCtx, &band); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_GETBAND_IOCTL, + pAdapter->sessionId, band)); + len = scnprintf(extra, sizeof(extra), "%s %d", command, band); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETROAMSCANCHANNELS ", 20) == 0) + { + ret = hdd_parse_set_roam_scan_channels(pAdapter, command); + } + else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0) + { + tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tANI_U8 numChannels = 0; + tANI_U8 j = 0; + char extra[128] = {0}; + int len; + + if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( + pHddCtx->hHal, + ChannelList, + &numChannels, + pAdapter->sessionId)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: failed to get roam scan channel list", __func__); + ret = -EFAULT; + goto exit; + } + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL, + pAdapter->sessionId, numChannels)); + /* output channel list is of the format + [Number of roam scan channels][Channel1][Channel2]... */ + /* copy the number of channels in the 0th index */ + len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels); + for (j = 0; (j < numChannels); j++) + { + len += scnprintf(extra + len, sizeof(extra) - len, " %d", + ChannelList[j]); + } + + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "GETCCXMODE", 10) == 0) + { + tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + /* Check if the features OKC/ESE/11R are supported simultaneously, + then this operation is not permitted (return FAILURE) */ + if (eseMode && + hdd_is_okc_mode_enabled(pHddCtx) && + sme_getIsFtFeatureEnabled(pHddCtx->hHal)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: OKC/ESE/11R are supported simultaneously" + " hence this operation is not permitted!", __func__); + ret = -EPERM; + goto exit; + } + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETCCXMODE", eseMode); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "GETOKCMODE", 10) == 0) + { + tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx); + char extra[32]; + tANI_U8 len = 0; + + /* Check if the features OKC/ESE/11R are supported simultaneously, + then this operation is not permitted (return FAILURE) */ + if (okcMode && + sme_getIsEseFeatureEnabled(pHddCtx->hHal) && + sme_getIsFtFeatureEnabled(pHddCtx->hHal)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: OKC/ESE/11R are supported simultaneously" + " hence this operation is not permitted!", __func__); + ret = -EPERM; + goto exit; + } + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETOKCMODE", okcMode); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "GETFASTROAM", 11) == 0) + { + tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETFASTROAM", lfrMode); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "GETFASTTRANSITION", 17) == 0) + { + tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETFASTTRANSITION", ft); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0) + { + tANI_U8 *value = command; + tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT; + + /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME */ + value = value + 26; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &minTime); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX); + ret = -EINVAL; + goto exit; + } + if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) || + (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "scan min channel time value %d is out of range" + " (Min: %d Max: %d)", minTime, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN, + CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL, + pAdapter->sessionId, minTime)); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change channel min time = %d", __func__, minTime); + + pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime; + sme_setNeighborScanMinChanTime(pHddCtx->hHal, + minTime, pAdapter->sessionId); + } + else if (strncmp(command, "SENDACTIONFRAME", 15) == 0) + { + ret = hdd_parse_sendactionframe(pAdapter, command); + } + else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0) + { + tANI_U16 val = sme_getNeighborScanMinChanTime( + pHddCtx->hHal, + pAdapter->sessionId); + char extra[32]; + tANI_U8 len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMSCANCHANNELMINTIME", val); + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL, + pAdapter->sessionId, val)); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0) + { + tANI_U8 *value = command; + tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT; + + /* Move pointer to ahead of SETSCANCHANNELTIME */ + value = value + 19; + /* Convert the value from ascii to integer */ + ret = kstrtou16(value, 10, &maxTime); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou16 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou16 failed range [%d - %d]", __func__, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) || + (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "lfr mode value %d is out of range" + " (Min: %d Max: %d)", maxTime, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN, + CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change channel max time = %d", __func__, maxTime); + + pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime; + sme_setNeighborScanMaxChanTime(pHddCtx->hHal, + pAdapter->sessionId, maxTime); + } + else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0) + { + tANI_U16 val = sme_getNeighborScanMaxChanTime(pHddCtx->hHal, + pAdapter->sessionId); + char extra[32]; + tANI_U8 len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETSCANCHANNELTIME", val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETSCANHOMETIME", 15) == 0) + { + tANI_U8 *value = command; + tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT; + + /* Move pointer to ahead of SETSCANHOMETIME */ + value = value + 16; + /* Convert the value from ascii to integer */ + ret = kstrtou16(value, 10, &val); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou16 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou16 failed range [%d - %d]", __func__, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX); + ret = -EINVAL; + goto exit; + } + + if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) || + (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "scan home time value %d is out of range" + " (Min: %d Max: %d)", val, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN, + CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change scan home time = %d", __func__, val); + + pHddCtx->cfg_ini->nNeighborScanPeriod = val; + sme_setNeighborScanPeriod(pHddCtx->hHal, + pAdapter->sessionId, val); + } + else if (strncmp(command, "GETSCANHOMETIME", 15) == 0) + { + tANI_U16 val = sme_getNeighborScanPeriod(pHddCtx->hHal, + pAdapter->sessionId); + char extra[32]; + tANI_U8 len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETSCANHOMETIME", val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETROAMINTRABAND", 16) == 0) + { + tANI_U8 *value = command; + tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT; + + /* Move pointer to ahead of SETROAMINTRABAND */ + value = value + 17; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &val); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_INTRA_BAND_MIN, + CFG_ROAM_INTRA_BAND_MAX); + ret = -EINVAL; + goto exit; + } + + if ((val < CFG_ROAM_INTRA_BAND_MIN) || + (val > CFG_ROAM_INTRA_BAND_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "intra band mode value %d is out of range" + " (Min: %d Max: %d)", val, + CFG_ROAM_INTRA_BAND_MIN, + CFG_ROAM_INTRA_BAND_MAX); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change intra band = %d", __func__, val); + + pHddCtx->cfg_ini->nRoamIntraBand = val; + sme_setRoamIntraBand(pHddCtx->hHal, val); + } + else if (strncmp(command, "GETROAMINTRABAND", 16) == 0) + { + tANI_U16 val = sme_getRoamIntraBand(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMINTRABAND", val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETSCANNPROBES", 14) == 0) + { + tANI_U8 *value = command; + tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT; + + /* Move pointer to ahead of SETSCANNPROBES */ + value = value + 15; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &nProbes); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX); + ret = -EINVAL; + goto exit; + } + + if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) || + (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "NProbes value %d is out of range" + " (Min: %d Max: %d)", nProbes, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set nProbes = %d", __func__, nProbes); + + pHddCtx->cfg_ini->nProbes = nProbes; + sme_UpdateRoamScanNProbes(pHddCtx->hHal, pAdapter->sessionId, + nProbes); + } + else if (strncmp(command, "GETSCANNPROBES", 14) == 0) + { + tANI_U8 val = sme_getRoamScanNProbes(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0) + { + tANI_U8 *value = command; + tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT; + + /* Move pointer to ahead of SETSCANHOMEAWAYTIME */ + /* input value is in units of msec */ + value = value + 20; + /* Convert the value from ascii to integer */ + ret = kstrtou16(value, 10, &homeAwayTime); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) || + (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "homeAwayTime value %d is out of range" + " (Min: %d Max: %d)", homeAwayTime, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime); + if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime) + { + pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime; + sme_UpdateRoamScanHomeAwayTime(pHddCtx->hHal, + pAdapter->sessionId, + homeAwayTime, eANI_BOOLEAN_TRUE); + } + } + else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0) + { + tANI_U16 val = sme_getRoamScanHomeAwayTime(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "REASSOC", 7) == 0) + { + ret = hdd_parse_reassoc(pAdapter, command); + } + else if (strncmp(command, "SETWESMODE", 10) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT; + + /* Move pointer to ahead of SETWESMODE */ + value = value + 11; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &wesMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX); + ret = -EINVAL; + goto exit; + } + + if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) || + (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WES Mode value %d is out of range" + " (Min: %d Max: %d)", wesMode, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode); + + pHddCtx->cfg_ini->isWESModeEnabled = wesMode; + sme_UpdateWESMode(pHddCtx->hHal, wesMode, pAdapter->sessionId); + } + else if (strncmp(command, "GETWESMODE", 10) == 0) + { + tANI_BOOLEAN wesMode = sme_GetWESMode(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETOPPORTUNISTICRSSIDIFF", 24) == 0) + { + tANI_U8 *value = command; + tANI_U8 nOpportunisticThresholdDiff = CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_DEFAULT; + + /* Move pointer to ahead of SETOPPORTUNISTICRSSIDIFF */ + value = value + 25; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &nOpportunisticThresholdDiff); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed.", __func__); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set Opportunistic Threshold diff = %d", + __func__, + nOpportunisticThresholdDiff); + + sme_SetRoamOpportunisticScanThresholdDiff(pHddCtx->hHal, + pAdapter->sessionId, + nOpportunisticThresholdDiff); + } + else if (strncmp(priv_data.buf, "GETOPPORTUNISTICRSSIDIFF", 24) == 0) + { + tANI_S8 val = sme_GetRoamOpportunisticScanThresholdDiff( + pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETROAMRESCANRSSIDIFF", 21) == 0) + { + tANI_U8 *value = command; + tANI_U8 nRoamRescanRssiDiff = CFG_ROAM_RESCAN_RSSI_DIFF_DEFAULT; + + /* Move pointer to ahead of SETROAMRESCANRSSIDIFF */ + value = value + 22; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &nRoamRescanRssiDiff); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed.", __func__); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set Roam Rescan RSSI Diff = %d", + __func__, + nRoamRescanRssiDiff); + sme_SetRoamRescanRssiDiff(pHddCtx->hHal, + pAdapter->sessionId, + nRoamRescanRssiDiff); + } + else if (strncmp(priv_data.buf, "GETROAMRESCANRSSIDIFF", 21) == 0) + { + tANI_U8 val = sme_GetRoamRescanRssiDiff(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ +#ifdef FEATURE_WLAN_LFR + else if (strncmp(command, "SETFASTROAM", 11) == 0) + { + tANI_U8 *value = command; + tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + + /* Move pointer to ahead of SETFASTROAM */ + value = value + 12; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &lfrMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) || + (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "lfr mode value %d is out of range" + " (Min: %d Max: %d)", lfrMode, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change lfr mode = %d", __func__, lfrMode); + + pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode; + sme_UpdateIsFastRoamIniFeatureEnabled(pHddCtx->hHal, + pAdapter->sessionId, + lfrMode); + } +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + else if (strncmp(command, "SETFASTTRANSITION", 17) == 0) + { + tANI_U8 *value = command; + tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT; + + /* Move pointer to ahead of SETFASTROAM */ + value = value + 18; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &ft); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_FAST_TRANSITION_ENABLED_NAME_MIN, + CFG_FAST_TRANSITION_ENABLED_NAME_MAX); + ret = -EINVAL; + goto exit; + } + + if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) || + (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "ft mode value %d is out of range" + " (Min: %d Max: %d)", ft, + CFG_FAST_TRANSITION_ENABLED_NAME_MIN, + CFG_FAST_TRANSITION_ENABLED_NAME_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change ft mode = %d", __func__, ft); + + pHddCtx->cfg_ini->isFastTransitionEnabled = ft; + sme_UpdateFastTransitionEnabled(pHddCtx->hHal, ft); + } + + else if (strncmp(command, "FASTREASSOC", 11) == 0) + { + tANI_U8 *value = command; + tANI_U8 channel = 0; + tSirMacAddr targetApBssid; + tHalHandle hHal; + v_U32_t roamId = 0; + tCsrRoamModifyProfileFields modProfileFields; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tCsrHandoffRequest handoffInfo; +#endif + hdd_station_ctx_t *pHddStaCtx = NULL; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + + /* if not associated, no need to proceed with reassoc */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__); + ret = -EINVAL; + goto exit; + } + + ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, + &channel); + if (ret) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse reassoc command data", __func__); + goto exit; + } + + /* if the target bssid is same as currently associated AP, + issue reassoc to same AP */ + if (VOS_TRUE == vos_mem_compare(targetApBssid, + pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) + { + /* Reassoc to same AP, only supported for Open Security*/ + if ((pHddStaCtx->conn_info.ucEncryptionType || + pHddStaCtx->conn_info.mcEncryptionType)) { + hddLog(LOGE, + FL("Reassoc to same AP, only supported for Open Security")); + ret = -ENOTSUPP; + goto exit; + } + hddLog(LOG1, + FL("Reassoc BSSID is same as currently associated AP bssid")); + sme_GetModifyProfileFields(hHal, pAdapter->sessionId, + &modProfileFields); + sme_RoamReassoc(hHal, pAdapter->sessionId, + NULL, modProfileFields, &roamId, 1); + ret = 0; + goto exit; + } + + /* Check channel number is a valid channel number */ + if(VOS_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, channel)) + { + hddLog(LOGE, FL("Invalid Channel [%d]"), channel); + + ret = -EINVAL; + goto exit; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pHddCtx->cfg_ini->isRoamOffloadEnabled) { + hdd_wma_send_fastreassoc_cmd((int)pAdapter->sessionId, targetApBssid, + (int) channel); + goto exit; + } +#endif + /* Proceed with reassoc */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + handoffInfo.channel = channel; + handoffInfo.src = FASTREASSOC; + vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr)); + sme_HandoffRequest(pHddCtx->hHal, pAdapter->sessionId, &handoffInfo); +#endif + } +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + else if (strncmp(command, "CCXPLMREQ", 9) == 0) + { + tANI_U8 *value = command; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpSirPlmReq pPlmRequest = NULL; + + pPlmRequest = vos_mem_malloc(sizeof(tSirPlmReq)); + if (NULL == pPlmRequest){ + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_plm_cmd(value, pPlmRequest); + if (eHAL_STATUS_SUCCESS != status){ + vos_mem_free(pPlmRequest); + pPlmRequest = NULL; + ret = -EINVAL; + goto exit; + } + pPlmRequest->sessionId = pAdapter->sessionId; + + status = sme_SetPlmRequest(pHddCtx->hHal, pPlmRequest); + if (eHAL_STATUS_SUCCESS != status) + { + vos_mem_free(pPlmRequest); + pPlmRequest = NULL; + ret = -EINVAL; + goto exit; + } + } +#endif +#ifdef FEATURE_WLAN_ESE + else if (strncmp(command, "SETCCXMODE", 10) == 0) + { + tANI_U8 *value = command; + tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT; + + /* Check if the features OKC/ESE/11R are supported simultaneously, + then this operation is not permitted (return FAILURE) */ + if (sme_getIsEseFeatureEnabled(pHddCtx->hHal) && + hdd_is_okc_mode_enabled(pHddCtx) && + sme_getIsFtFeatureEnabled(pHddCtx->hHal)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: OKC/ESE/11R are supported simultaneously" + " hence this operation is not permitted!", __func__); + ret = -EPERM; + goto exit; + } + + /* Move pointer to ahead of SETCCXMODE */ + value = value + 11; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &eseMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ESE_FEATURE_ENABLED_MIN, + CFG_ESE_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) || + (eseMode > CFG_ESE_FEATURE_ENABLED_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Ese mode value %d is out of range" + " (Min: %d Max: %d)", eseMode, + CFG_ESE_FEATURE_ENABLED_MIN, + CFG_ESE_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change ese mode = %d", __func__, eseMode); + + pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode; + sme_UpdateIsEseFeatureEnabled(pHddCtx->hHal, pAdapter->sessionId, + eseMode); + } +#endif + else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN roamScanControl = 0; + + /* Move pointer to ahead of SETROAMSCANCONTROL */ + value = value + 19; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &roamScanControl); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed ", __func__); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl); + + if (0 != roamScanControl) + { + ret = 0; /* return success but ignore param value "TRUE" */ + goto exit; + } + + sme_SetRoamScanControl(pHddCtx->hHal, + pAdapter->sessionId, roamScanControl); + } +#ifdef FEATURE_WLAN_OKC + else if (strncmp(command, "SETOKCMODE", 10) == 0) + { + tANI_U8 *value = command; + tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT; + + /* Check if the features OKC/ESE/11R are supported simultaneously, + then this operation is not permitted (return FAILURE) */ + if (sme_getIsEseFeatureEnabled(pHddCtx->hHal) && + hdd_is_okc_mode_enabled(pHddCtx) && + sme_getIsFtFeatureEnabled(pHddCtx->hHal)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: OKC/ESE/11R are supported simultaneously" + " hence this operation is not permitted!", __func__); + ret = -EPERM; + goto exit; + } + + /* Move pointer to ahead of SETOKCMODE */ + value = value + 11; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &okcMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_OKC_FEATURE_ENABLED_MIN, + CFG_OKC_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) || + (okcMode > CFG_OKC_FEATURE_ENABLED_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Okc mode value %d is out of range" + " (Min: %d Max: %d)", okcMode, + CFG_OKC_FEATURE_ENABLED_MIN, + CFG_OKC_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to change okc mode = %d", __func__, okcMode); + pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode; + } +#endif /* FEATURE_WLAN_OKC */ + else if (strncmp(command, "BTCOEXMODE", 10) == 0 ) + { + char *bcMode; + int ret; + + bcMode = command + 11; + if ('1' == *bcMode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + FL("BTCOEXMODE %d"), *bcMode); + pHddCtx->btCoexModeSet = TRUE; + ret = wlan_hdd_scan_abort(pAdapter); + if (ret < 0) { + hddLog(LOGE, + FL("Failed to abort existing scan status:%d"), ret); + } + } + else if ('2' == *bcMode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + FL("BTCOEXMODE %d"), *bcMode); + pHddCtx->btCoexModeSet = FALSE; + } + } + else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0) + { + tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + command, roamScanControl); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#ifdef WLAN_FEATURE_PACKET_FILTERING + else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0) + { + tANI_U8 filterType = 0; + tANI_U8 *value = command; + + /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6 */ + value = value + 22; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &filterType); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, + * then also kstrtou8 fails + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range ", __func__); + ret = -EINVAL; + goto exit; + } + + if (filterType != 0 && filterType != 1) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Accepted Values are 0 and 1 ", __func__); + ret = -EINVAL; + goto exit; + } + wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType, + pAdapter->sessionId); + } +#endif + else if (strncmp(command, "BTCOEXMODE", 10) == 0 ) + { + char *bcMode; + bcMode = command + 11; + if ('1' == *bcMode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + FL("BTCOEXMODE %d"), *bcMode); + pHddCtx->btCoexModeSet = TRUE; + } + else if ('2' == *bcMode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + FL("BTCOEXMODE %d"), *bcMode); + pHddCtx->btCoexModeSet = FALSE; + } + } + else if (strncmp(command, "SCAN-ACTIVE", 11) == 0) + { + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("making default scan to ACTIVE")); + pHddCtx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + } + else if (strncmp(command, "SCAN-PASSIVE", 12) == 0) + { + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("making default scan to PASSIVE")); + pHddCtx->ioctl_scan_mode = eSIR_PASSIVE_SCAN; + } + else if (strncmp(command, "GETDWELLTIME", 12) == 0) + { + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + char extra[32]; + tANI_U8 len = 0; + + memset(extra, 0, sizeof(extra)); + ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len); + len = VOS_MIN(priv_data.total_len, len + 1); + if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + ret = len; + } + else if (strncmp(command, "SETDWELLTIME", 12) == 0) + { + ret = hdd_set_dwell_time(pAdapter, command); + } + else if ( strncasecmp(command, "MIRACAST", 8) == 0 ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received MIRACAST command", __func__); + + ret = hdd_set_miracast_mode(pAdapter, command); + } + else if (strncmp(command, "SETRMCTXRATE", 12) == 0) + { + tANI_U8 *value = command; + tANI_U32 uRate = 0; + tTxrateinfoflags txFlags = 0; + tSirRateUpdateInd rateUpdateParams = {0}; + int status; + hdd_config_t *pConfig = pHddCtx->cfg_ini; + + if ((WLAN_HDD_IBSS != pAdapter->device_mode) && + (WLAN_HDD_SOFTAP != pAdapter->device_mode)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Received SETRMCTXRATE command in invalid mode %d" + "SETRMC command is only allowed in IBSS or SOFTAP mode", + pAdapter->device_mode); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags); + if (status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid SETRMCTXRATE command "); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: uRate %d ", __func__, uRate); + + /* -1 implies ignore this param */ + rateUpdateParams.ucastDataRate = -1; + + /* + * Fill the user specified RMC rate param + * and the derived tx flags. + */ + rateUpdateParams.nss = (pConfig->enable2x2 == 0) ? 0 : 1; + rateUpdateParams.reliableMcastDataRate = uRate; + rateUpdateParams.reliableMcastDataRateTxFlag = txFlags; + rateUpdateParams.dev_mode = pAdapter->device_mode; + rateUpdateParams.bcastDataRate = -1; + memcpy(rateUpdateParams.bssid, pAdapter->macAddressCurrent.bytes, + sizeof(rateUpdateParams.bssid)); + status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), + &rateUpdateParams); + } +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0) + { + tANI_U8 *value = command; + tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tANI_U8 numChannels = 0; + eHalStatus status; + ret = hdd_parse_channellist(value, ChannelList, &numChannels); + if (ret) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse channel list information", __func__); + goto exit; + } + if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE( VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_ERROR, + "%s: number of channels (%d) supported exceeded max (%d)", + __func__, + numChannels, + WNI_CFG_VALID_CHANNEL_LIST_LEN); + ret = -EINVAL; + goto exit; + } + status = sme_SetEseRoamScanChannelList(pHddCtx->hHal, + pAdapter->sessionId, + ChannelList, + numChannels); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to update channel list information", __func__); + ret = -EINVAL; + goto exit; + } + } + else if (strncmp(command, "GETTSMSTATS", 11) == 0) + { + tANI_U8 *value = command; + char extra[128] = {0}; + int len = 0; + tANI_U8 tid = 0; + hdd_station_ctx_t *pHddStaCtx = NULL; + tAniTrafStrmMetrics tsmMetrics; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + /* if not associated, return error */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_ERROR, + "%s:Not associated!", + __func__); + ret = -EINVAL; + goto exit; + } + /* Move pointer to ahead of GETTSMSTATS */ + value = value + 12; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &tid); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, + * then also + * kstrtou8 fails + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + TID_MIN_VALUE, + TID_MAX_VALUE); + ret = -EINVAL; + goto exit; + } + if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "tid value %d is out of range" + " (Min: %d Max: %d)", tid, + TID_MIN_VALUE, + TID_MAX_VALUE); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_INFO, + "%s: Received Command to get tsm stats tid = %d", + __func__, + tid); + if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to get tsm stats", __func__); + ret = -EFAULT; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_INFO, + "UplinkPktQueueDly(%d)" + "UplinkPktQueueDlyHist[0](%d)" + "UplinkPktQueueDlyHist[1](%d)" + "UplinkPktQueueDlyHist[2](%d)" + "UplinkPktQueueDlyHist[3](%d)" + "UplinkPktTxDly(%u)" + "UplinkPktLoss(%d)" + "UplinkPktCount(%d)" + "RoamingCount(%d)" + "RoamingDly(%d)", + tsmMetrics.UplinkPktQueueDly, + tsmMetrics.UplinkPktQueueDlyHist[0], + tsmMetrics.UplinkPktQueueDlyHist[1], + tsmMetrics.UplinkPktQueueDlyHist[2], + tsmMetrics.UplinkPktQueueDlyHist[3], + tsmMetrics.UplinkPktTxDly, + tsmMetrics.UplinkPktLoss, + tsmMetrics.UplinkPktCount, + tsmMetrics.RoamingCount, + tsmMetrics.RoamingDly); + /* Output TSM stats is of the format + * GETTSMSTATS [PktQueueDly] + * [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly] + * eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */ + len = scnprintf(extra, + sizeof(extra), + "%s %d %d:%d:%d:%d %u %d %d %d %d", + command, + tsmMetrics.UplinkPktQueueDly, + tsmMetrics.UplinkPktQueueDlyHist[0], + tsmMetrics.UplinkPktQueueDlyHist[1], + tsmMetrics.UplinkPktQueueDlyHist[2], + tsmMetrics.UplinkPktQueueDlyHist[3], + tsmMetrics.UplinkPktTxDly, + tsmMetrics.UplinkPktLoss, + tsmMetrics.UplinkPktCount, + tsmMetrics.RoamingCount, + tsmMetrics.RoamingDly); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETCCKMIE", 9) == 0) + { + tANI_U8 *value = command; + tANI_U8 *cckmIe = NULL; + tANI_U8 cckmIeLen = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse cckm ie data", __func__); + ret = -EINVAL; + goto exit; + } + if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: CCKM Ie input length is more than max[%d]", __func__, + DOT11F_IE_RSN_MAX_LEN); + if (NULL != cckmIe) + { + vos_mem_free(cckmIe); + cckmIe = NULL; + } + ret = -EINVAL; + goto exit; + } + sme_SetCCKMIe(pHddCtx->hHal, pAdapter->sessionId, cckmIe, cckmIeLen); + if (NULL != cckmIe) + { + vos_mem_free(cckmIe); + cckmIe = NULL; + } + } + else if (strncmp(command, "CCXBEACONREQ", 12) == 0) + { + tANI_U8 *value = command; + tCsrEseBeaconReq eseBcnReq; + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = hdd_parse_ese_beacon_req(value, &eseBcnReq); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse ese beacon req", __func__); + ret = -EINVAL; + goto exit; + } + + if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { + hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated")); + hdd_indicateEseBcnReportNoResults (pAdapter, + eseBcnReq.bcnReq[0].measurementToken, + 0x02, //BIT(1) set for measurement done + 0); // no BSS + goto exit; + } + + status = sme_SetEseBeaconRequest(pHddCtx->hHal, + pAdapter->sessionId, + &eseBcnReq); + + if (eHAL_STATUS_RESOURCES == status) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("sme_SetEseBeaconRequest failed (%d)," + " a request already in progress"), status); + ret = -EBUSY; + goto exit; + } else if (eHAL_STATUS_SUCCESS != status) { + VOS_TRACE( VOS_MODULE_ID_HDD, + VOS_TRACE_LEVEL_ERROR, + "%s: sme_SetEseBeaconRequest failed (%d)", + __func__, + status); + ret = -EINVAL; + goto exit; + } + } +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + else if (strncmp(command, "SETMCRATE", 9) == 0) + { + tANI_U8 *value = command; + int targetRate; + /* Move pointer to ahead of SETMCRATE */ + /* input value is in units of hundred kbps */ + value = value + 10; + /* Convert the value from ascii to integer, decimal base */ + ret = kstrtouint(value, 10, &targetRate); + ret = wlan_hdd_set_mc_rate(pAdapter, targetRate); + } + else if (strncmp(command, "MAXTXPOWER", 10) == 0) + { + int status; + int txPower; + VOS_STATUS vosStatus; + eHalStatus smeStatus; + tANI_U8 *value = command; + hdd_adapter_t *pAdapter; + tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + + 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; + } + + vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == vosStatus ) + { + pAdapter = pAdapterNode->pAdapter; + /* Assign correct self MAC address */ + vos_mem_copy(bssid, pAdapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + vos_mem_copy(selfMac, pAdapter->macAddressCurrent.bytes, + VOS_MAC_ADDR_SIZE); + + hddLog(VOS_TRACE_LEVEL_INFO, "Device mode %d max tx power %d" + " selfMac: " MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ", + pAdapter->device_mode, txPower, MAC_ADDR_ARRAY(selfMac), + MAC_ADDR_ARRAY(bssid)); + smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal), bssid, + selfMac, txPower); + if (eHAL_STATUS_SUCCESS != status) + { + 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__); + vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + } + else if (strncmp(command, "SETDFSSCANMODE", 14) == 0) + { + tANI_U8 *value = command; + tANI_U8 dfsScanMode = CFG_ROAMING_DFS_CHANNEL_DEFAULT; + + /* Move pointer to ahead of SETDFSSCANMODE */ + value = value + 15; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &dfsScanMode); + if (ret < 0) + { + /* If the input value is greater than max value of + * datatype, then also kstrtou8 fails + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAMING_DFS_CHANNEL_MIN, + CFG_ROAMING_DFS_CHANNEL_MAX); + ret = -EINVAL; + goto exit; + } + + if ((dfsScanMode < CFG_ROAMING_DFS_CHANNEL_MIN) || + (dfsScanMode > CFG_ROAMING_DFS_CHANNEL_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "dfsScanMode value %d is out of range" + " (Min: %d Max: %d)", dfsScanMode, + CFG_ROAMING_DFS_CHANNEL_MIN, + CFG_ROAMING_DFS_CHANNEL_MAX); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set DFS Scan Mode = %d", + __func__, dfsScanMode); + + /* When DFS scanning is disabled, the DFS channels need to be + * removed from the operation of device. + */ + ret = wlan_hdd_disable_dfs_chan_scan(pHddCtx, pAdapter, + (dfsScanMode == CFG_ROAMING_DFS_CHANNEL_DISABLED)); + if (ret < 0) { + /* Some conditions prevented it from disabling DFS channels + */ + hddLog(LOGE, + FL("disable/enable DFS channel request was denied")); + goto exit; + } + + pHddCtx->cfg_ini->allowDFSChannelRoam = dfsScanMode; + sme_UpdateDFSScanMode(pHddCtx->hHal, pAdapter->sessionId, + dfsScanMode); + } + else if (strncmp(command, "GETDFSSCANMODE", 14) == 0) + { + tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "GETLINKSTATUS", 13) == 0) { + int value = wlan_hdd_get_link_status(pAdapter); + char extra[32]; + tANI_U8 len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, value); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + else if (strncmp(command, "ENABLEEXTWOW", 12) == 0) { + + tANI_U8 *value = command; + int set_value; + + /* Move pointer to ahead of ENABLEEXTWOW*/ + value += 12; + if (!(sscanf(value, "%d", &set_value))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("No input identified")); + ret = -EINVAL; + goto exit; + } + ret = hdd_enable_ext_wow_parser(pAdapter, + pAdapter->sessionId, set_value); + + } else if (strncmp(command, "SETAPP1PARAMS", 13) == 0) { + tANI_U8 *value = command; + + /* Move pointer to ahead of SETAPP1PARAMS*/ + value += 13; + ret = hdd_set_app_type1_parser(pAdapter, + value, strlen(value)); + if (ret >= 0) + pHddCtx->is_extwow_app_type1_param_set = TRUE; + + } else if (strncmp(command, "SETAPP2PARAMS", 13) == 0) { + tANI_U8 *value = command; + + /* Move pointer to ahead of SETAPP2PARAMS*/ + value += 13; + ret = hdd_set_app_type2_parser(pAdapter, + value, strlen(value)); + if (ret >= 0) + pHddCtx->is_extwow_app_type2_param_set = TRUE; + } +#endif +#ifdef FEATURE_WLAN_TDLS + else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) { + tANI_U8 *value = command; + int set_value; + /* Move pointer to point the string */ + value += 26; + if (!(sscanf(value, "%d", &set_value))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("No input identified")); + ret = -EINVAL; + goto exit; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Tdls offchannel offset:%d"), + set_value); + ret = hdd_set_tdls_secoffchanneloffset(pHddCtx, set_value); + } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) { + tANI_U8 *value = command; + int set_value; + /* Move pointer to point the string */ + value += 18; + if (!(sscanf(value, "%d", &set_value))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("No input identified")); + ret = -EINVAL; + goto exit; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Tdls offchannel mode:%d"), + set_value); + ret = hdd_set_tdls_offchannelmode(pAdapter, set_value); + } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) { + tANI_U8 *value = command; + int set_value; + /* Move pointer to point the string */ + value += 14; + ret = sscanf(value, "%d", &set_value); + if (ret != 1) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Wrong value is given for hdd_set_tdls_offchannel"); + ret = -EINVAL; + goto exit; + } + + if (VOS_IS_DFS_CH(set_value)) { + hddLog(LOGE, + FL("DFS channel %d is passed for hdd_set_tdls_offchannel"), + set_value); + ret = -EINVAL; + goto exit; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Tdls offchannel num: %d"), set_value); + ret = hdd_set_tdls_offchannel(pHddCtx, set_value); + } else if (strncmp(command, "TDLSSCAN", 8) == 0) { + uint8_t *value = command; + int set_value; + /* Move pointer to point the string */ + value += 8; + ret = sscanf(value, "%d", &set_value); + if (ret != 1) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Wrong value is given for tdls_scan_type"); + ret = -EINVAL; + goto exit; + } + hddLog(LOG1, FL("Tdls scan type val: %d"), + set_value); + ret = hdd_set_tdls_scan_type(pHddCtx, set_value); + } +#endif + else if (strncasecmp(command, "RSSI", 4) == 0) { + v_S7_t s7Rssi = 0; + char extra[32]; + tANI_U8 len = 0; + + wlan_hdd_get_rssi(pAdapter, &s7Rssi); + + len = scnprintf(extra, sizeof(extra), "%s %d", command, s7Rssi); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + hddLog(LOGE, FL("Failed to copy data to user buffer")); + ret = -EFAULT; + goto exit; + } + } else if (strncasecmp(command, "LINKSPEED", 9) == 0) { + uint32_t link_speed = 0; + char extra[32]; + uint8_t len = 0; + + ret = wlan_hdd_get_link_speed(pAdapter, &link_speed); + if (0 != ret) + goto exit; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, link_speed); + len = VOS_MIN(priv_data.total_len, len + 1); + if (copy_to_user(priv_data.buf, &extra, len)) { + hddLog(LOGE, FL("Failed to copy data to user buffer")); + ret = -EFAULT; + goto exit; + } + } else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0) { + /* + * 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. + * But it can be turned back on. Otherwise; when APM is turned back + * off, WLAN wld turn back on. So at that point the command is + * expected to come down. 0 means disable, 1 means enable. The + * constraint is removed when parameter 1 is set or different + * country code is set + */ + + ret = drv_cmd_set_fcc_channel(pHddCtx, command, 15); + + } else if (strncmp(command, "RXFILTER-REMOVE", 15) == 0) { + + ret = hdd_driver_rxfilter_comand_handler(command, pAdapter, false); + + } else if (strncmp(command, "RXFILTER-ADD", 12) == 0) { + + ret = hdd_driver_rxfilter_comand_handler(command, pAdapter, true); + + } else if (strncasecmp(command, "SETANTENNAMODE", 14) == 0) { + ret = drv_cmd_set_antenna_mode(pAdapter, command, 14); + hddLog(LOG1, FL("set antenna mode ret: %d"), ret); + } else if (strncasecmp(command, "GETANTENNAMODE", 14) == 0) { + + ret = drv_cmd_get_antenna_mode(pAdapter, pHddCtx, command, + 14, &priv_data); + hddLog(LOG1, FL("Get antenna mode ret: %d mode: %s"), + ret, priv_data.buf); + } else { + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_UNSUPPORTED_IOCTL, + pAdapter->sessionId, 0)); + hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", + __func__, command); + } + + } +exit: + if (command) + { + kfree(command); + } + EXIT(); + return ret; +} + +#ifdef CONFIG_COMPAT +static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr) +{ + struct { + compat_uptr_t buf; + int used_len; + int total_len; + } compat_priv_data; + hdd_priv_data_t priv_data; + int ret = 0; + + /* + * Note that pAdapter and ifr have already been verified by caller, + * and HDD context has also been validated + */ + if (copy_from_user(&compat_priv_data, ifr->ifr_data, + sizeof(compat_priv_data))) { + ret = -EFAULT; + goto exit; + } + priv_data.buf = compat_ptr(compat_priv_data.buf); + priv_data.used_len = compat_priv_data.used_len; + priv_data.total_len = compat_priv_data.total_len; + ret = hdd_driver_command(pAdapter, &priv_data); + exit: + return ret; +} +#else /* CONFIG_COMPAT */ +static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr) +{ + /* will never be invoked */ + return 0; +} +#endif /* CONFIG_COMPAT */ + +static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr) +{ + hdd_priv_data_t priv_data; + int ret = 0; + + /* + * Note that pAdapter and ifr have already been verified by caller, + * and HDD context has also been validated + */ + if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) { + ret = -EFAULT; + } else { + ret = hdd_driver_command(pAdapter, &priv_data); + } + return ret; +} + +/** + * __hdd_ioctl() - HDD ioctl handler + * @dev: pointer to net_device structure + * @ifr: pointer to ifreq structure + * @cmd: ioctl command + * + * Return: 0 for success and error number for failure. + */ +static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + long ret = 0; + + ENTER(); + + if (dev != pAdapter->dev) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter/dev inconsistency", __func__); + ret = -ENODEV; + goto exit; + } + + if ((!ifr) || (!ifr->ifr_data)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid data", __func__); + ret = -EINVAL; + goto exit; + } + +#if defined(QCA_WIFI_FTM) && defined(LINUX_QCMBR) + if (VOS_FTM_MODE == hdd_get_conparam()) { + if (SIOCIOCTLTX99 == cmd) { + ret = wlan_hdd_qcmbr_unified_ioctl(pAdapter, ifr); + goto exit; + } + } +#endif + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret) { + ret = -EBUSY; + goto exit; + } + + switch (cmd) { + case (SIOCDEVPRIVATE + 1): + if (is_compat_task()) + ret = hdd_driver_compat_ioctl(pAdapter, ifr); + else + ret = hdd_driver_ioctl(pAdapter, ifr); + break; + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d", + __func__, cmd); + ret = -EINVAL; + break; + } + exit: + EXIT(); + return ret; +} + +/** + * hdd_ioctl() - Wrapper function to protect __hdd_ioctl() function from SSR + * @dev: pointer to net_device structure + * @ifr: pointer to ifreq structure + * @cmd: ioctl command + * + * Return: 0 for success and error number for failure. + */ +static int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_ioctl(dev, ifr, cmd); + vos_ssr_unprotect(__func__); + + return ret; +} + + +/* + * Mac address for multiple virtual interface is found as following + * i) The mac address of the first interface is just the actual hw mac address. + * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to + * define the mac address for the remaining interfaces and locally + * administered bit is set. INTF_MACADDR_MASK is based on the number of + * supported virtual interfaces, right now this is 0x07 (meaning 8 interface). + * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1, + * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc. + */ + +void hdd_update_macaddr(hdd_config_t *cfg_ini, v_MACADDR_t hw_macaddr) +{ + int8_t i; + u_int8_t macaddr_b3, tmp_br3; + + vos_mem_copy(cfg_ini->intfMacAddr[0].bytes, hw_macaddr.bytes, + VOS_MAC_ADDR_SIZE); + for (i = 1; i < VOS_MAX_CONCURRENCY_PERSONA; i++) { + vos_mem_copy(cfg_ini->intfMacAddr[i].bytes, hw_macaddr.bytes, + VOS_MAC_ADDR_SIZE); + macaddr_b3 = cfg_ini->intfMacAddr[i].bytes[3]; + tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) & + INTF_MACADDR_MASK; + macaddr_b3 += tmp_br3; + + /* XOR-ing bit-24 of the mac address. This will give enough + * mac address range before collision + */ + macaddr_b3 ^= (1 << 7); + + /* Set locally administered bit */ + cfg_ini->intfMacAddr[i].bytes[0] |= 0x02; + cfg_ini->intfMacAddr[i].bytes[3] = macaddr_b3; + hddLog(VOS_TRACE_LEVEL_INFO, "cfg_ini->intfMacAddr[%d]: " + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(cfg_ini->intfMacAddr[i].bytes)); + } +} + +static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, + struct hdd_tgt_services *cfg) +{ + hdd_config_t *cfg_ini = hdd_ctx->cfg_ini; + + /* Set up UAPSD */ + cfg_ini->apUapsdEnabled &= cfg->uapsd; + +#ifdef WLAN_FEATURE_11AC + /* 11AC mode support */ + if ((cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac || + cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && + !cfg->en_11ac) + cfg_ini->dot11Mode = eHDD_DOT11_MODE_AUTO; +#endif /* #ifdef WLAN_FEATURE_11AC */ + + /* ARP offload: override user setting if invalid */ + cfg_ini->fhostArpOffload &= cfg->arp_offload; + +#ifdef FEATURE_WLAN_SCAN_PNO + /* PNO offload */ + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: PNO Capability in f/w = %d", + __func__,cfg->pno_offload); + if (cfg->pno_offload) + cfg_ini->PnoOffload = TRUE; +#endif + sme_set_lte_coex_supp(hdd_ctx->hHal, + cfg->lte_coex_ant_share); + hdd_ctx->per_band_chainmask_supp = cfg->per_band_chainmask_supp; + sme_set_per_band_chainmask_supp(hdd_ctx->hHal, + cfg->per_band_chainmask_supp); +#ifdef FEATURE_WLAN_TDLS + cfg_ini->fEnableTDLSSupport &= cfg->en_tdls; + cfg_ini->fEnableTDLSOffChannel &= cfg->en_tdls_offchan; + cfg_ini->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta; + if (cfg_ini->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) + { + cfg_ini->fEnableTDLSSleepSta = TRUE; + } + else + { + cfg_ini->fEnableTDLSSleepSta = FALSE; + } +#endif + sme_set_bcon_offload_supp(hdd_ctx->hHal, cfg->beacon_offload); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + cfg_ini->isRoamOffloadEnabled &= cfg->en_roam_offload; +#endif + +#ifdef SAP_AUTH_OFFLOAD + cfg_ini->enable_sap_auth_offload &= cfg->sap_auth_offload_service; +#endif +} + +/** + * hdd_update_chain_mask_vdev_nss() - sets the chain mask and vdev nss + * @hdd_ctx: HDD context + * @cfg: Pointer to target services. + * + * Sets the chain masks for 2G and 5G bands based on target supported + * values and INI values. And sets the Nss per vdev type based on INI + * and configured chain mask value. + * + * Return: None + */ +static void hdd_update_chain_mask_vdev_nss(hdd_context_t *hdd_ctx, + struct hdd_tgt_services *cfg) +{ + hdd_config_t *cfg_ini = hdd_ctx->cfg_ini; + uint8_t chain_mask, ret; + uint8_t max_supp_nss = 1; + + cfg_ini->enable2x2 = 0; + chain_mask = cfg->chain_mask_2g & cfg_ini->chain_mask_2g; + if (!chain_mask) + chain_mask = cfg->chain_mask_2g; + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set 2G chain mask value %d", + __func__, chain_mask); + ret = process_wma_set_command(0, WMI_PDEV_PARAM_RX_CHAIN_MASK_2G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: set WMI_PDEV_PARAM_RX_CHAIN_MASK_2G failed %d", + __func__, ret); + } + ret = process_wma_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_2G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_2G set failed %d", + __func__, ret); + } + max_supp_nss += ((chain_mask & 0x3) == 0x3); + + if (max_supp_nss == 2) + cfg_ini->enable2x2 = 1; + sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss, + cfg_ini->vdev_type_nss_2g, eCSR_BAND_24); + hdd_ctx->supp_2g_chain_mask = chain_mask; + + max_supp_nss = 1; + chain_mask = cfg->chain_mask_5g & cfg_ini->chain_mask_5g; + if (!chain_mask) + chain_mask = cfg->chain_mask_5g; + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set 5G chain mask value %d", + __func__, chain_mask); + ret = process_wma_set_command(0, WMI_PDEV_PARAM_RX_CHAIN_MASK_5G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: set WMI_PDEV_PARAM_RX_CHAIN_MASK_5G failed %d", + __func__, ret); + } + ret = process_wma_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_5G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_5G set failed %d", + __func__, ret); + } + max_supp_nss += ((chain_mask & 0x3) == 0x3); + + if (max_supp_nss == 2) + cfg_ini->enable2x2 = 1; + sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss, + cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G); + hdd_ctx->supp_5g_chain_mask = chain_mask; + hddLog(LOG1, FL("Supported chain mask 2G: %d 5G: %d"), + hdd_ctx->supp_2g_chain_mask, + hdd_ctx->supp_5g_chain_mask); +} + +static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx, + struct hdd_tgt_ht_cap *cfg) +{ + eHalStatus status; + tANI_U32 value, val32; + tANI_U16 val16; + hdd_config_t *pconfig = hdd_ctx->cfg_ini; + tSirMacHTCapabilityInfo *phtCapInfo; + tANI_U8 mcs_set[SIZE_OF_SUPPORTED_MCS_SET]; + uint8_t enable_tx_stbc; + + /* check and update RX STBC */ + if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc) + pconfig->enableRxSTBC = cfg->ht_rx_stbc; + + /* get the MPDU density */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get MPDU DENSITY", + __func__); + value = 0; + } + + /* + * MPDU density: + * override user's setting if value is larger + * than the one supported by target + */ + if (value > cfg->mpdu_density) { + status = ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, + cfg->mpdu_density, + NULL, eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set MPDU DENSITY to CCM", + __func__); + } + + /* get the HT capability info*/ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32); + if (eHAL_STATUS_SUCCESS != status) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get HT capability info", + __func__); + return; + } + val16 = (tANI_U16)val32; + phtCapInfo = (tSirMacHTCapabilityInfo *)&val16; + + /* Set the LDPC capability */ + phtCapInfo->advCodingCap = cfg->ht_rx_ldpc; + + + if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20) + pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20; + + if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40) + pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40; + + hdd_ctx->num_rf_chains = cfg->num_rf_chains; + hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc; + + enable_tx_stbc = pconfig->enableTxSTBC; + + if (pconfig->enable2x2 && (hdd_ctx->per_band_chainmask_supp || + (!hdd_ctx->per_band_chainmask_supp && (cfg->num_rf_chains == 2)))) + { + pconfig->enable2x2 = 1; + } + else + { + pconfig->enable2x2 = 0; + enable_tx_stbc = 0; + + /* 1x1 */ + /* Update Rx Highest Long GI data Rate */ + if (ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + hddLog(LOGE, "Could not pass on " + "WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"); + } + + /* Update Tx Highest Long GI data Rate */ + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + hddLog(LOGE, "Could not pass on " + "HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"); + } + } + if (!(cfg->ht_tx_stbc && pconfig->enable2x2)) + { + enable_tx_stbc = 0; + } + phtCapInfo->txSTBC = enable_tx_stbc; + val32 = val16; + status = ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, + val32, NULL, eANI_BOOLEAN_FALSE); + if (status != eHAL_STATUS_SUCCESS) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set HT capability to CCM", + __func__); +#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff + value = SIZE_OF_SUPPORTED_MCS_SET; + if (ccmCfgGetStr(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set, + &value) == eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Read MCS rate set", __func__); + + if (pconfig->enable2x2) + { + for (value = 0; value < 2; value++) + mcs_set[value] = WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES; + + status = ccmCfgSetStr(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, + mcs_set, SIZE_OF_SUPPORTED_MCS_SET, NULL, + eANI_BOOLEAN_FALSE); + if (status == eHAL_STATUS_FAILURE) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set MCS SET to CCM", __func__); + } + } +#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES +} + +#ifdef WLAN_FEATURE_11AC +static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx, + struct hdd_tgt_vht_cap *cfg) +{ + eHalStatus status; + tANI_U32 value = 0; + hdd_config_t *pconfig = hdd_ctx->cfg_ini; + tANI_U32 temp = 0; + + /* Get the current MPDU length */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get MPDU LENGTH", + __func__); + value = 0; + } + + /* + * VHT max MPDU length: + * override if user configured value is too high + * that the target cannot support + */ + if (value > cfg->vht_max_mpdu) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_MAX_MPDU_LENGTH, + cfg->vht_max_mpdu, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set VHT MAX MPDU LENGTH", + __func__); + } + } + + /* Get the current supported chan width */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, + &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get MPDU LENGTH", + __func__); + value = 0; + } + + /* + * Update VHT supported chan width: + * if user setting is invalid, override it with + * target capability + */ + if ((value == eHT_CHANNEL_WIDTH_80MHZ && + !(cfg->supp_chan_width & eHT_CHANNEL_WIDTH_80MHZ)) || + (value == eHT_CHANNEL_WIDTH_160MHZ && + !(cfg->supp_chan_width & eHT_CHANNEL_WIDTH_160MHZ))) { + u_int32_t width = eHT_CHANNEL_WIDTH_20MHZ; + + if (cfg->supp_chan_width & eHT_CHANNEL_WIDTH_160MHZ) + width = eHT_CHANNEL_WIDTH_160MHZ; + else if (cfg->supp_chan_width & eHT_CHANNEL_WIDTH_80MHZ) + width = eHT_CHANNEL_WIDTH_80MHZ; + + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, + width, NULL, eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set VHT SUPPORTED CHAN WIDTH", + __func__); + } + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp); + temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS; + + if (pconfig->enable2x2) + temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2); + + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_BASIC_MCS_SET to CCM"); + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp); + temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS; + if (pconfig->enable2x2) + temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2); + + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_RX_MCS_MAP to CCM"); + } + + ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp); + temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS; + if (pconfig->enable2x2) + temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "vhtRxMCS2x2 - %x temp - %u enable2x2 %d", + pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2); + + if (ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_TX_MCS_MAP to CCM"); + } + /* Get the current RX LDPC setting */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT LDPC CODING CAP", + __func__); + value = 0; + } + + /* Set the LDPC capability */ + if (value && !cfg->vht_rx_ldpc) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_LDPC_CODING_CAP, + cfg->vht_rx_ldpc, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set VHT LDPC CODING CAP to CCM", + __func__); + } + } + + /* Get current GI 80 value */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get SHORT GI 80MHZ", + __func__); + value = 0; + } + + /* set the Guard interval 80MHz */ + if (value && !cfg->vht_short_gi_80) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_SHORT_GI_80MHZ, + cfg->vht_short_gi_80, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set SHORT GI 80MHZ to CCM", + __func__); + } + } + + /* Get current GI 160 value */ + status = ccmCfgGetInt(hdd_ctx->hHal, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get SHORT GI 80 & 160", + __func__); + value = 0; + } + + /* set the Guard interval 160MHz */ + if (value && !cfg->vht_short_gi_160) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + cfg->vht_short_gi_160, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set SHORT GI 80 & 160 to CCM", + __func__); + } + } + + /* Get VHT TX STBC cap */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT TX STBC", + __func__); + value = 0; + } + + /* VHT TX STBC cap */ + if (value && !cfg->vht_tx_stbc) { + status = ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, + cfg->vht_tx_stbc, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set the VHT TX STBC to CCM", + __func__); + } + } + + /* Get VHT RX STBC cap */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT RX STBC", + __func__); + value = 0; + } + + /* VHT RX STBC cap */ + if (value && !cfg->vht_rx_stbc) { + status = ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, + cfg->vht_rx_stbc, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set the VHT RX STBC to CCM", + __func__); + } + } + + /* Get VHT SU Beamformer cap */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP, + &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT SU BEAMFORMER CAP", + __func__); + value = 0; + } + + /* set VHT SU Beamformer cap */ + if (value && !cfg->vht_su_bformer) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_SU_BEAMFORMER_CAP, + cfg->vht_su_bformer, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set VHT SU BEAMFORMER CAP", + __func__); + } + } + + /* check and update SU BEAMFORMEE capability*/ + if (pconfig->enableTxBF && !cfg->vht_su_bformee) + pconfig->enableTxBF = cfg->vht_su_bformee; + + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + pconfig->enableTxBF, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set VHT SU BEAMFORMEE CAP", + __func__); + } + + /* Get VHT MU Beamformer cap */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP, + &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT MU BEAMFORMER CAP", + __func__); + value = 0; + } + + /* set VHT MU Beamformer cap */ + if (value && !cfg->vht_mu_bformer) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_MU_BEAMFORMER_CAP, + cfg->vht_mu_bformer, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set the VHT MU BEAMFORMER CAP to CCM", + __func__); + } + } + + /* Get VHT MU Beamformee cap */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT MU BEAMFORMEE CAP", + __func__); + value = 0; + } + + /* set VHT MU Beamformee cap */ + if (value && !cfg->vht_mu_bformee) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + cfg->vht_mu_bformee, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set VHT MU BEAMFORMER CAP", + __func__); + } + } + + /* Get VHT MAX AMPDU Len exp */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT AMPDU LEN", + __func__); + value = 0; + } + + /* + * VHT max AMPDU len exp: + * override if user configured value is too high + * that the target cannot support. + * Even though Rome publish ampdu_len=7, it can + * only support 4 because of some h/w bug. + */ + + if (value > cfg->vht_max_ampdu_len_exp) { + status = ccmCfgSetInt(hdd_ctx->hHal, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + cfg->vht_max_ampdu_len_exp, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set the VHT AMPDU LEN EXP", + __func__); + } + } + + /* Get VHT TXOP PS CAP */ + status = ccmCfgGetInt(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get VHT TXOP PS", + __func__); + value = 0; + } + + /* set VHT TXOP PS cap */ + if (value && !cfg->vht_txop_ps) { + status = ccmCfgSetInt(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, + cfg->vht_txop_ps, NULL, + eANI_BOOLEAN_FALSE); + + if (status == eHAL_STATUS_FAILURE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: could not set the VHT TXOP PS", + __func__); + } + } +} +#endif /* #ifdef WLAN_FEATURE_11AC */ + +void hdd_update_tgt_cfg(void *context, void *param) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context; + struct hdd_tgt_cfg *cfg = (struct hdd_tgt_cfg *)param; + tANI_U8 temp_band_cap; + + /* first store the INI band capability */ + temp_band_cap = hdd_ctx->cfg_ini->nBandCapability; + + hdd_ctx->cfg_ini->nBandCapability = cfg->band_cap; + + /* now overwrite the target band capability with INI + setting if INI setting is a subset */ + + if ((hdd_ctx->cfg_ini->nBandCapability == eCSR_BAND_ALL) && + (temp_band_cap != eCSR_BAND_ALL)) + hdd_ctx->cfg_ini->nBandCapability = temp_band_cap; + else if ((hdd_ctx->cfg_ini->nBandCapability != eCSR_BAND_ALL) && + (temp_band_cap != eCSR_BAND_ALL) && + (hdd_ctx->cfg_ini->nBandCapability != temp_band_cap)) { + hddLog(VOS_TRACE_LEVEL_WARN, + FL("ini BandCapability not supported by the target")); + } + + if (!hdd_ctx->isLogpInProgress) { + hdd_ctx->reg.reg_domain = cfg->reg_domain; + hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext; + } + + /* This can be extended to other configurations like ht, vht cap... */ + + if (!vos_is_macaddr_zero(&cfg->hw_macaddr)) + { + hdd_update_macaddr(hdd_ctx->cfg_ini, cfg->hw_macaddr); + } + else { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid MAC passed from target, using MAC from ini file" + MAC_ADDRESS_STR, __func__, + MAC_ADDR_ARRAY(hdd_ctx->cfg_ini->intfMacAddr[0].bytes)); + } + + hdd_ctx->target_fw_version = cfg->target_fw_version; + + hdd_ctx->max_intf_count = cfg->max_intf_count; + +#ifdef WLAN_FEATURE_LPSS + hdd_ctx->lpss_support = cfg->lpss_support; +#endif + + hdd_ctx->ap_arpns_support = cfg->ap_arpns_support; + hdd_update_tgt_services(hdd_ctx, &cfg->services); + if (hdd_ctx->per_band_chainmask_supp) + hdd_update_chain_mask_vdev_nss(hdd_ctx, &cfg->services); + else + sme_set_vdev_nss(hdd_ctx->hHal, hdd_ctx->cfg_ini->enable2x2); + + hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap); + +#ifdef WLAN_FEATURE_11AC + hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap); +#endif /* #ifdef WLAN_FEATURE_11AC */ + + hdd_ctx->current_antenna_mode = + hdd_is_supported_chain_mask_2x2(hdd_ctx) ? + HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1; + hddLog(LOG1, FL("Current antenna mode: %d"), + hdd_ctx->current_antenna_mode); +} + +/* This function is invoked in atomic context when a radar + * is found on the SAP current operating channel and Data + * Tx from netif has to be stopped to honor the DFS regulations. + * Actions: Stop the netif Tx queues,Indicate Radar present + * in HDD context for future usage. + */ +bool hdd_dfs_indicate_radar(void *context, void *param) +{ + hdd_context_t *pHddCtx= (hdd_context_t *)context; + struct hdd_dfs_radar_ind *hdd_radar_event = + (struct hdd_dfs_radar_ind*)param; + hdd_adapter_list_node_t *pAdapterNode = NULL, + *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + if (!pHddCtx || !hdd_radar_event || pHddCtx->cfg_ini->disableDFSChSwitch) + return true; + + if (VOS_TRUE == hdd_radar_event->dfs_radar_status) + { + spin_lock_bh(&pHddCtx->dfs_lock); + if (pHddCtx->dfs_radar_found) + { + /* Application already triggered channel switch + * on current channel, so return here + */ + spin_unlock_bh(&pHddCtx->dfs_lock); + return false; + } + + pHddCtx->dfs_radar_found = VOS_TRUE; + spin_unlock_bh(&pHddCtx->dfs_lock); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if (WLAN_HDD_SOFTAP == pAdapter->device_mode || + WLAN_HDD_P2P_GO == pAdapter->device_mode) + { + WLAN_HDD_GET_AP_CTX_PTR(pAdapter)->dfs_cac_block_tx = VOS_TRUE; + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + } + + return true; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_is_valid_mac_address() - Validate MAC address + + This function validates whether the given MAC address is valid or not + Expected MAC address is of the format XX:XX:XX:XX:XX:XX + where X is the hexa decimal digit character and separated by ':' + This algorithm works even if MAC address is not separated by ':' + + This code checks given input string mac contains exactly 12 hexadecimal digits. + and a separator colon : appears in the input string only after + an even number of hex digits. + + \param - pMacAddr pointer to the input MAC address + \return - 1 for valid and 0 for invalid + + --------------------------------------------------------------------------*/ + +v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr) +{ + int xdigit = 0; + int separator = 0; + while (*pMacAddr) + { + if (isxdigit(*pMacAddr)) + { + xdigit++; + } + else if (':' == *pMacAddr) + { + if (0 == xdigit || ((xdigit / 2) - 1) != separator) + break; + + ++separator; + } + else + { + /* Invalid MAC found */ + return 0; + } + ++pMacAddr; + } + return (xdigit == 12 && (separator == 5 || separator == 0)); +} + +/** + * __hdd_open() - HDD Open function + * @dev: pointer to net_device structure + * + * This is called in response to ifconfig up + * + * Return: 0 for success and error number for failure + */ +static int __hdd_open(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + int ret; + v_BOOL_t in_standby = TRUE; + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, + pAdapter->sessionId, pAdapter->device_mode)); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); + while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status)) { + if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags)) { + hddLog(LOG1, FL("chip already out of standby")); + in_standby = FALSE; + break; + } else { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + } + + if (TRUE == in_standby) { + if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter)) { + hddLog(LOGE, FL("Failed to bring wlan out of power save")); + return -EINVAL; + } + } + + set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); + if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { + hddLog(LOG1, FL("Enabling Tx Queues")); + /* Enable TX queues only when we are connected */ + netif_tx_start_all_queues(dev); + } + + return ret; +} + +/** + * hdd_open() - Wrapper function for __hdd_open to protect it from SSR + * @dev: pointer to net_device structure + * + * This is called in response to ifconfig up + * + * Return: 0 for success and error number for failure + */ +static int hdd_open(struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_open(dev); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_mon_open() - HDD monitor open + * @dev: pointer to net_device + * + * Return: 0 for success and error number for failure + */ +static int __hdd_mon_open(struct net_device *dev) +{ + netif_start_queue(dev); + return 0; +} + +/** + * hdd_mon_open() - SSR wrapper function for __hdd_mon_open + * @dev: pointer to net_device + * + * Return: 0 for success and error number for failure + */ +static int hdd_mon_open(struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_mon_open(dev); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef MODULE +/** + * wlan_hdd_stop_enter_lowpower() - Enter low power mode + * @hdd_ctx: HDD context + * + * For module, when all the interfaces are down, enter low power mode. + */ +static inline void wlan_hdd_stop_enter_lowpower(hdd_context_t *hdd_ctx) +{ + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: All Interfaces are Down entering standby", + __func__); + if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(hdd_ctx)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failed to put wlan in power save", + __func__); + } +} + +/** + * wlan_hdd_stop_can_enter_lowpower() - Enter low power mode + * @adapter: Adapter context + * + * Check if hardware can enter low power mode when all the interfaces are down. + */ +static inline int wlan_hdd_stop_can_enter_lowpower(hdd_adapter_t *adapter) +{ + /* SoftAP ifaces should never go in power save mode making + * sure same here. + */ + if ((WLAN_HDD_SOFTAP == adapter->device_mode) || + (WLAN_HDD_MONITOR == adapter->device_mode) || + (WLAN_HDD_P2P_GO == adapter->device_mode)) + return 0; + + return 1; +} +#else + +/** + * kickstart_driver_handler() - Work queue handler for kickstart_driver + * + * Use worker queue to exit if it is not possible to call kickstart_driver() + * directly in the caller context like in interface down context + */ +static void kickstart_driver_handler(struct work_struct *work) +{ + hdd_driver_exit(); + wlan_hdd_inited = 0; +} + +static DECLARE_WORK(kickstart_driver_work, kickstart_driver_handler); + +/** + * kickstart_driver() - Initialize and Clean-up driver + * @load: True: initialize, False: Clean-up driver + * + * Delayed driver initialization when driver is statically linked and Clean-up + * when all the interfaces are down or any other condition which requires to + * save power by bringing down hardware. + * This routine is invoked when module parameter fwpath is modified from user + * space to signal the initialization of the WLAN driver or when all the + * interfaces are down and user space no longer need WLAN interfaces. Userspace + * needs to write to fwpath again to get the WLAN interfaces + * + * Return: 0 on success, non zero on failure + */ +static int kickstart_driver(bool load) +{ + int ret_status; + + pr_info("%s: load: %d wlan_hdd_inited: %d, caller: %pf\n", __func__, + load, wlan_hdd_inited, (void *)_RET_IP_); + + /* Make sure unload and load are synchronized */ + flush_work(&kickstart_driver_work); + + /* No-Op, If unload requested even though driver is not loaded */ + if (!load && !wlan_hdd_inited) + return 0; + + /* Unload is requested */ + if (!load && wlan_hdd_inited) { + schedule_work(&kickstart_driver_work); + return 0; + } + + if (!wlan_hdd_inited) { + ret_status = hdd_driver_init(); + wlan_hdd_inited = ret_status ? 0 : 1; + return ret_status; + } + + hdd_driver_exit(); + + msleep(200); + + ret_status = hdd_driver_init(); + wlan_hdd_inited = ret_status ? 0 : 1; + return ret_status; +} + +/** + * wlan_hdd_stop_enter_lowpower() - Enter low power mode + * @hdd_ctx: HDD context + * + * For static driver, when all the interfaces are down, enter low power mode by + * bringing down WLAN hardware. + */ +static inline void wlan_hdd_stop_enter_lowpower(hdd_context_t *hdd_ctx) +{ + kickstart_driver(false); +} + +/** + * wlan_hdd_stop_can_enter_lowpower() - Enter low power mode + * @adapter: Adapter context + * + * Check if hardware can enter low power mode when all the interfaces are down. + * For static driver, hardware can enter low power mode for all types of + * interfaces. + */ +static inline int wlan_hdd_stop_can_enter_lowpower(hdd_adapter_t *adapter) +{ + return 1; +} +#endif + +/** + * __hdd_stop() - HDD stop function + * @dev: pointer to net_device structure + * + * This is called in response to ifconfig down + * + * Return: 0 for success and error number for failure + */ +static int __hdd_stop(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + v_BOOL_t enter_standby = TRUE; + int ret; + + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST, + pAdapter->sessionId, pAdapter->device_mode)); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + /* Nothing to be done if the interface is not opened */ + if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: NETDEV Interface is not OPENED", __func__); + return -ENODEV; + } + + /* Make sure the interface is marked as closed */ + clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__); + + /* Disable TX on the interface, after this hard_start_xmit() will not + * be called on that interface + */ + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + + /* Mark the interface status as "down" for outside world */ + netif_carrier_off(pAdapter->dev); + + /* The interface is marked as down for outside world (aka kernel) + * But the driver is pretty much alive inside. The driver needs to + * tear down the existing connection on the netdev (session) + * cleanup the data pipes and wait until the control plane is stabilized + * for this interface. The call also needs to wait until the above + * mentioned actions are completed before returning to the caller. + * Notice that the hdd_stop_adapter is requested not to close the session + * That is intentional to be able to scan if it is a STA/P2P interface + */ + hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE); + + /* DeInit the adapter. This ensures datapath cleanup as well */ + hdd_deinit_adapter(pHddCtx, pAdapter, true); + + /* SoftAP ifaces should never go in power save mode + making sure same here. */ + if (!wlan_hdd_stop_can_enter_lowpower(pAdapter)) + { + /* SoftAP mode, so return from here */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: In SAP MODE", __func__); + EXIT(); + return 0; + } + + /* Find if any iface is up. If any iface is up then can't put device to + * sleep/power save mode + */ + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) ) + { + if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot " + "put device to sleep", __func__); + enter_standby = FALSE; + break; + } + else + { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + } + + if (TRUE == enter_standby) + wlan_hdd_stop_enter_lowpower(pHddCtx); + + EXIT(); + return 0; +} + +/** + * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR + * @dev: pointer to net_device structure + * + * This is called in response to ifconfig down + * + * Return: 0 for success and error number for failure + */ +static int hdd_stop (struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_stop(dev); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_uninit() - HDD uninit function + * @dev: pointer to net_device structure + * + * This is called during the netdev unregister to uninitialize all data + * associated with the device + * + * Return: none + */ +static void __hdd_uninit(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + + ENTER(); + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + hddLog(LOGP, FL("Invalid magic")); + return; + } + + if (NULL == pAdapter->pHddCtx) { + hddLog(LOGP, FL("NULL pHddCtx")); + return; + } + + if (dev != pAdapter->dev) + hddLog(LOGP, FL("Invalid device reference")); + + hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter, true); + + /* After uninit our adapter structure will no longer be valid */ + pAdapter->dev = NULL; + pAdapter->magic = 0; + + EXIT(); +} + +/** + * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR + * @dev: pointer to net_device structure + * + * This is called during the netdev unregister to uninitialize all data + * associated with the device + * + * Return: none + */ +static void hdd_uninit(struct net_device *dev) +{ + vos_ssr_protect(__func__); + __hdd_uninit(dev); + vos_ssr_unprotect(__func__); +} + + +/**--------------------------------------------------------------------------- + \brief hdd_full_pwr_cbk() - HDD full power callback function + + This is the function invoked by SME to inform the result of a full power + request issued by HDD + + \param - callback context - Pointer to cookie + status - result of request + + \return - None + +--------------------------------------------------------------------------*/ +void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status) +{ + hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext; + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status); + if(&pHddCtx->full_pwr_comp_var) + { + complete(&pHddCtx->full_pwr_comp_var); + } +} + +/**--------------------------------------------------------------------------- + + \brief hdd_get_cfg_file_size() - + + This function reads the configuration file using the request firmware + API and returns the configuration file size. + + \param - pCtx - Pointer to the adapter . + - pFileName - Pointer to the file name. + - pBufSize - Pointer to the buffer size. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize) +{ + int status; + hdd_context_t *pHddCtx = (hdd_context_t*)pCtx; + + ENTER(); + + status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); + + if(status || !pHddCtx->fw || !pHddCtx->fw->data) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__); + status = VOS_STATUS_E_FAILURE; + } + else { + *pBufSize = pHddCtx->fw->size; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize); + release_firmware(pHddCtx->fw); + pHddCtx->fw = NULL; + } + + EXIT(); + return VOS_STATUS_SUCCESS; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_read_cfg_file() - + + This function reads the configuration file using the request firmware + API and returns the cfg data and the buffer size of the configuration file. + + \param - pCtx - Pointer to the adapter . + - pFileName - Pointer to the file name. + - pBuffer - Pointer to the data buffer. + - pBufSize - Pointer to the buffer size. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName, + v_VOID_t *pBuffer, v_SIZE_t *pBufSize) +{ + int status; + hdd_context_t *pHddCtx = (hdd_context_t*)pCtx; + + ENTER(); + + status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); + + if(status || !pHddCtx->fw || !pHddCtx->fw->data) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__); + return VOS_STATUS_E_FAILURE; + } + else { + if(*pBufSize != pHddCtx->fw->size) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG " + "file size", __func__); + release_firmware(pHddCtx->fw); + pHddCtx->fw = NULL; + return VOS_STATUS_E_FAILURE; + } + else { + if(pBuffer) { + vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize); + } + release_firmware(pHddCtx->fw); + pHddCtx->fw = NULL; + } + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +/** + * __hdd_set_mac_address() - HDD set mac address + * @dev: pointer to net_device structure + * @addr: Pointer to the sockaddr + * + * This function sets the user specified mac address using + * the command ifconfig wlanX hw ether . + * + * Return: 0 for success. + */ +static int __hdd_set_mac_address(struct net_device *dev, void *addr) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + struct sockaddr *psta_mac_addr = addr; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN); + memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN); + + EXIT(); + return 0; +} + +/** + * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address() + * function from SSR + * @dev: pointer to net_device structure + * @addr: Pointer to the sockaddr + * + * This function sets the user specified mac address using + * the command ifconfig wlanX hw ether . + * + * Return: 0 for success. + */ +static int hdd_set_mac_address(struct net_device *dev, void *addr) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_set_mac_address(dev, addr); + vos_ssr_unprotect(__func__); + + return ret; +} + +tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx) +{ + int i; + for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) + { + if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i))) + break; + } + + if( VOS_MAX_CONCURRENCY_PERSONA == i) + return NULL; + + pHddCtx->cfg_ini->intfAddrMask |= (1 << i); + return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0]; +} + +void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr) +{ + int i; + for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++) + { + if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) ) + { + pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i); + break; + } + } + return; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/** + * __hdd_set_multicast_list() - set the multicast address list + * @dev: pointer to net_device + * + * Return: none + */ +static void __hdd_set_multicast_list(struct net_device *dev) +{ + static const uint8_t ipv6_router_solicitation[] = + {0x33, 0x33, 0x00, 0x00, 0x00, 0x02}; + hdd_adapter_t *pAdapter; + hdd_context_t *pHddCtx; + int mc_count; + int i = 0; + struct netdev_hw_addr *ha; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) + return; + + pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (0 != wlan_hdd_validate_context(pHddCtx)) + return; + + /* Delete already configured multicast address list */ + wlan_hdd_set_mc_addr_list(pAdapter, false); + + if (dev->flags & IFF_ALLMULTI) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: allow all multicast frames", __func__); + pAdapter->mc_addr_list.mc_cnt = 0; + } + else + { + mc_count = netdev_mc_count(dev); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: mc_count = %u", __func__, mc_count); + if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: No free filter available; allow all multicast frames", __func__); + pAdapter->mc_addr_list.mc_cnt = 0; + return; + } + + pAdapter->mc_addr_list.mc_cnt = mc_count; + + netdev_for_each_mc_addr(ha, dev) { + if (i == mc_count) + break; + /* + * Skip following addresses: + * 1)IPv6 router solicitation address + * 2)Any other address pattern if its set during RXFILTER REMOVE + * driver command based on addr_filter_pattern + */ + if ((!memcmp(ha->addr, ipv6_router_solicitation, ETH_ALEN)) || + (pAdapter->addr_filter_pattern && (!memcmp(ha->addr, + &pAdapter->addr_filter_pattern, 1)))) { + hddLog(LOG1, FL("MC/BC filtering Skip addr ="MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(ha->addr)); + + pAdapter->mc_addr_list.mc_cnt--; + continue; + } + memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN); + memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR, + __func__, i, + MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i])); + i++; + } + } + + /* Configure the updated multicast address list */ + wlan_hdd_set_mc_addr_list(pAdapter, true); + + EXIT(); + return; +} + +/** + * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list + * @dev: pointer to net_device + * + * Return: none + */ +static void hdd_set_multicast_list(struct net_device *dev) +{ + vos_ssr_protect(__func__); + __hdd_set_multicast_list(dev); + vos_ssr_unprotect(__func__); +} +#endif + +/**--------------------------------------------------------------------------- + + \brief hdd_select_queue() - + + This function is registered with the Linux OS for network + core to decide which queue to use first. + + \param - dev - Pointer to the WLAN device. + - skb - Pointer to OS packet (sk_buff). + \return - ac, Queue Index/access category corresponding to UP in IP header + + --------------------------------------------------------------------------*/ +static v_U16_t hdd_select_queue(struct net_device *dev, + struct sk_buff *skb +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) + , void *accel_priv +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + , select_queue_fallback_t fallback +#endif +) +{ + return hdd_wmm_select_queue(dev, skb); +} + +static struct net_device_ops wlan_drv_ops = { + .ndo_open = hdd_open, + .ndo_stop = hdd_stop, + .ndo_uninit = hdd_uninit, + .ndo_start_xmit = hdd_hard_start_xmit, + .ndo_tx_timeout = hdd_tx_timeout, + .ndo_get_stats = hdd_stats, + .ndo_do_ioctl = hdd_ioctl, + .ndo_set_mac_address = hdd_set_mac_address, + .ndo_select_queue = hdd_select_queue, +#ifdef WLAN_FEATURE_PACKET_FILTERING +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0)) || defined(WITH_BACKPORTS) + .ndo_set_rx_mode = hdd_set_multicast_list, +#else + .ndo_set_multicast_list = hdd_set_multicast_list, +#endif //LINUX_VERSION_CODE +#endif + }; + static struct net_device_ops wlan_mon_drv_ops = { + .ndo_open = hdd_mon_open, + .ndo_stop = hdd_stop, + .ndo_uninit = hdd_uninit, + .ndo_start_xmit = hdd_mon_hard_start_xmit, + .ndo_tx_timeout = hdd_tx_timeout, + .ndo_get_stats = hdd_stats, + .ndo_do_ioctl = hdd_ioctl, + .ndo_set_mac_address = hdd_set_mac_address, +}; + + +void hdd_set_station_ops( struct net_device *pWlanDev ) +{ + pWlanDev->netdev_ops = &wlan_drv_ops; +} + +#ifdef FEATURE_RUNTIME_PM +/** + * hdd_runtime_suspend_init() - API to initialize runtime pm context + * @hdd_ctx: HDD Context + * + * The API initializes the context to prevent runtime pm for various use + * cases like scan, roc, dfs. + * This API can be extended to initialize the context to prevent runtime pm + * + * Return: void + */ +void hdd_runtime_suspend_init(hdd_context_t *hdd_ctx) +{ + struct hdd_runtime_pm_context *context = &hdd_ctx->runtime_context; + + context->scan = vos_runtime_pm_prevent_suspend_init("scan"); + context->roc = vos_runtime_pm_prevent_suspend_init("roc"); + context->dfs = vos_runtime_pm_prevent_suspend_init("dfs"); +} + +/** + * hdd_runtime_suspend_deinit() - API to deinit runtime pm context + * @hdd_ctx: HDD context + * + * The API deinit the context to prevent runtime pm. + * + * Return: void + */ +void hdd_runtime_suspend_deinit(hdd_context_t *hdd_ctx) +{ + struct hdd_runtime_pm_context *context = &hdd_ctx->runtime_context; + + vos_runtime_pm_prevent_suspend_deinit(context->scan); + context->scan = NULL; + vos_runtime_pm_prevent_suspend_deinit(context->roc); + context->roc = NULL; + vos_runtime_pm_prevent_suspend_deinit(context->dfs); + context->dfs = NULL; +} + +/** + * hdd_adapter_runtime_suspend_init() - API to init runtime pm context/adapter + * @adapter: Interface Adapter + * + * API is used to init the context to prevent runtime pm/adapter + * + * Return: void + */ +static void +hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) +{ + struct hdd_adapter_pm_context *context = &adapter->runtime_context; + + context->connect = vos_runtime_pm_prevent_suspend_init("connect"); +} + +/** + * hdd_adapter_runtime_suspend_denit() - API to deinit runtime pm/adapter + * @adapter: Interface Adapter + * + * API is used to deinit the context to prevent runtime pm/adapter + * + * Return: void + */ +static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) +{ + struct hdd_adapter_pm_context *context = &adapter->runtime_context; + + vos_runtime_pm_prevent_suspend_deinit(context->connect); + context->connect = NULL; +} + +#else +void hdd_runtime_suspend_init(hdd_context_t *hdd_ctx) { } +void hdd_runtime_suspend_deinit(hdd_context_t *hdd_ctx) { } +static inline void +hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) { } +static inline void +hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) { } +#endif + +static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name ) +{ + struct net_device *pWlanDev = NULL; + hdd_adapter_t *pAdapter = NULL; + /* + * cfg80211 initialization and registration.... + */ + pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), + name, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) || defined(WITH_BACKPORTS) + NET_NAME_UNKNOWN, +#endif + ether_setup, + NUM_TX_QUEUES); + + if(pWlanDev != NULL) + { + + //Save the pointer to the net_device in the HDD adapter + pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev ); + + vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) ); + + pAdapter->dev = pWlanDev; + pAdapter->pHddCtx = pHddCtx; + pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC; + + init_completion(&pAdapter->session_open_comp_var); + init_completion(&pAdapter->smps_force_mode_comp_var); + init_completion(&pAdapter->session_close_comp_var); + init_completion(&pAdapter->disconnect_comp_var); + init_completion(&pAdapter->linkup_event_var); + init_completion(&pAdapter->cancel_rem_on_chan_var); + init_completion(&pAdapter->rem_on_chan_ready_event); + init_completion(&pAdapter->offchannel_tx_event); + init_completion(&pAdapter->tx_action_cnf_event); +#ifdef FEATURE_WLAN_TDLS + init_completion(&pAdapter->tdls_add_station_comp); + init_completion(&pAdapter->tdls_del_station_comp); + init_completion(&pAdapter->tdls_mgmt_comp); + init_completion(&pAdapter->tdls_link_establish_req_comp); +#endif + + init_completion(&pHddCtx->mc_sus_event_var); + init_completion(&pHddCtx->tx_sus_event_var); + init_completion(&pHddCtx->rx_sus_event_var); + init_completion(&pHddCtx->ready_to_suspend); + init_completion(&pAdapter->ula_complete); + init_completion(&pAdapter->change_country_code); + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + init_completion(&pHddCtx->ready_to_extwow); +#endif + + init_completion(&pAdapter->scan_info.scan_req_completion_event); + init_completion(&pAdapter->scan_info.abortscan_event_var); + + vos_event_init(&pAdapter->scan_info.scan_finished_event); + pAdapter->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP; + + pAdapter->offloads_configured = FALSE; + pAdapter->isLinkUpSvcNeeded = FALSE; + pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE; + //Init the net_device structure + strlcpy(pWlanDev->name, name, IFNAMSIZ); + + vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr)); + vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr)); + pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT; + /* + * kernel will consume ethernet header length buffer for hard_header, + * so just reserve it + */ + hdd_set_needed_headroom(pWlanDev, pWlanDev->hard_header_len); + pWlanDev->hard_header_len += HDD_HW_NEEDED_HEADROOM; + + if (pHddCtx->cfg_ini->enableIPChecksumOffload) + pWlanDev->features |= NETIF_F_HW_CSUM; + else if (pHddCtx->cfg_ini->enableTCPChkSumOffld) + pWlanDev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + pWlanDev->features |= NETIF_F_RXCSUM; + hdd_set_station_ops( pAdapter->dev ); + + pWlanDev->destructor = free_netdev; + pWlanDev->ieee80211_ptr = &pAdapter->wdev ; + pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN; + pAdapter->wdev.wiphy = pHddCtx->wiphy; + pAdapter->wdev.netdev = pWlanDev; + /* set pWlanDev's parent to underlying device */ + SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev); + hdd_wmm_init( pAdapter ); + hdd_adapter_runtime_suspend_init(pAdapter); + } + + return pAdapter; +} + +VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held ) +{ + struct net_device *pWlanDev = pAdapter->dev; + //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; + //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + //eHalStatus halStatus = eHAL_STATUS_SUCCESS; + + if( rtnl_lock_held ) + { + if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) { + if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 ) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__); + return VOS_STATUS_E_FAILURE; + } + } + if (register_netdevice(pWlanDev)) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__); + return VOS_STATUS_E_FAILURE; + } + } + else + { + if(register_netdev(pWlanDev)) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__); + return VOS_STATUS_E_FAILURE; + } + } + set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags); + + return VOS_STATUS_SUCCESS; +} + +static eHalStatus hdd_smeCloseSessionCallback(void *pContext) +{ + hdd_adapter_t *pAdapter = pContext; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__); + return eHAL_STATUS_INVALID_PARAMETER; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__); + return eHAL_STATUS_NOT_INITIALIZED; + } + + clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags); + +#if !defined (CONFIG_CNSS) && \ + !defined (WLAN_OPEN_SOURCE) + /* need to make sure all of our scheduled work has completed. + * This callback is called from MC thread context, so it is safe to + * to call below flush work queue API from here. + * + * Even though this is called from MC thread context, if there is a faulty + * work item in the system, that can hang this call forever. So flushing + * this global work queue is not safe; and now we make sure that + * individual work queues are stopped correctly. But the cancel work queue + * is a GPL only API, so the proprietary version of the driver would still + * rely on the global work queue flush. + */ + flush_scheduled_work(); +#endif + + /* We can be blocked while waiting for scheduled work to be + * flushed, and the adapter structure can potentially be freed, in + * which case the magic will have been reset. So make sure the + * magic is still good, and hence the adapter structure is still + * valid, before signalling completion */ + if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic) + { + complete(&pAdapter->session_close_comp_var); + } + + return eHAL_STATUS_SUCCESS; +} + +VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ) +{ + struct net_device *pWlanDev = pAdapter->dev; + hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + tANI_U32 type, subType; + unsigned long rc; + int ret_val; + + INIT_COMPLETION(pAdapter->session_open_comp_var); + sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode); + sme_set_pdev_ht_vht_ies(pHddCtx->hHal, pHddCtx->cfg_ini->enable2x2); + status = vos_get_vdev_types(pAdapter->device_mode, &type, &subType); + if (VOS_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "failed to get vdev type"); + goto error_sme_open; + } + //Open a SME session for future operation + halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter, + (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId, + type, subType); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "sme_OpenSession() failed with status code %08d [x%08x]", + halStatus, halStatus ); + status = VOS_STATUS_E_FAILURE; + goto error_sme_open; + } + + //Block on a completion variable. Can't wait forever though. + rc = wait_for_completion_timeout( + &pAdapter->session_open_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("Session is not opened within timeout period code %ld"), + rc ); + status = VOS_STATUS_E_FAILURE; + goto error_sme_open; + } + + // Register wireless extensions + if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev))) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "hdd_register_wext() failed with status code %08d [x%08x]", + halStatus, halStatus ); + status = VOS_STATUS_E_FAILURE; + goto error_register_wext; + } + + //Set the Connection State to Not Connected + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_NotConnected", + __func__); + pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; + + //Set the default operation channel + pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel; + + /* Make the default Auth Type as OPEN*/ + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "hdd_init_tx_rx() failed with status code %08d [x%08x]", + status, status ); + goto error_init_txrx; + } + + set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags); + + if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "hdd_wmm_adapter_init() failed with status code %08d [x%08x]", + status, status ); + goto error_wmm_init; + } + + set_bit(WMM_INIT_DONE, &pAdapter->event_flags); + + ret_val = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + (int)pHddCtx->cfg_ini->enableSifsBurst, + PDEV_CMD); + + if (0 != ret_val) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_BURST_ENABLE set failed %d", + __func__, ret_val); + } + +#ifdef FEATURE_WLAN_TDLS + if(0 != wlan_hdd_tdls_init(pAdapter)) + { + status = VOS_STATUS_E_FAILURE; + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__); + goto error_tdls_init; + } + set_bit(TDLS_INIT_DONE, &pAdapter->event_flags); +#endif + + return VOS_STATUS_SUCCESS; + +#ifdef FEATURE_WLAN_TDLS +error_tdls_init: + clear_bit(WMM_INIT_DONE, &pAdapter->event_flags); + hdd_wmm_adapter_close(pAdapter); +#endif +error_wmm_init: + clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags); + hdd_deinit_tx_rx(pAdapter); +error_init_txrx: + hdd_UnregisterWext(pWlanDev); +error_register_wext: + if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) + { + INIT_COMPLETION(pAdapter->session_close_comp_var); + if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal, + pAdapter->sessionId, + hdd_smeCloseSessionCallback, pAdapter)) + { + unsigned long rc; + + //Block on a completion variable. Can't wait forever though. + rc = wait_for_completion_timeout( + &pAdapter->session_close_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + if (rc <= 0) + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Session is not opened within timeout period code %ld"), + rc); + } + } +error_sme_open: + return status; +} + +void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) +{ + hdd_cfg80211_state_t *cfgState; + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + + if( NULL != cfgState->buf ) + { + unsigned long rc; + INIT_COMPLETION(pAdapter->tx_action_cnf_event); + rc = wait_for_completion_timeout( + &pAdapter->tx_action_cnf_event, + msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT)); + if (!rc) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s HDD Wait for Action Confirmation Failed!!", + __func__); + /* Inform tx status as FAILURE to upper layer and free + * cfgState->buf */ + hdd_sendActionCnf( pAdapter, FALSE ); + } + } + return; +} + +void hdd_deinit_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + bool rtnl_held) +{ + ENTER(); + switch ( pAdapter->device_mode ) + { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + { + if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags)) + { + hdd_deinit_tx_rx( pAdapter ); + clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags); + } + + if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags)) + { + hdd_wmm_adapter_close( pAdapter ); + clear_bit(WMM_INIT_DONE, &pAdapter->event_flags); + } + + hdd_cleanup_actionframe(pHddCtx, pAdapter); + wlan_hdd_tdls_exit(pAdapter); + break; + } + + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + { + + if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags)) + { + hdd_wmm_adapter_close( pAdapter ); + clear_bit(WMM_INIT_DONE, &pAdapter->event_flags); + } + + hdd_cleanup_actionframe(pHddCtx, pAdapter); + + hdd_unregister_hostapd(pAdapter, rtnl_held); + + // set con_mode to STA only when no SAP concurrency mode + if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO))) + hdd_set_conparam( 0 ); + wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL ); + break; + } + + case WLAN_HDD_MONITOR: + { + hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx; + if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags)) + { + hdd_deinit_tx_rx( pAdapter ); + clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags); + } + if(NULL != pAdapterforTx) + { + hdd_cleanup_actionframe(pHddCtx, pAdapterforTx); + } + break; + } + + + default: + break; + } + + EXIT(); +} + +void hdd_cleanup_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + tANI_U8 rtnl_held) +{ + struct net_device *pWlanDev = NULL; + + if (pAdapter) + pWlanDev = pAdapter->dev; + else { + hddLog(LOGE, FL("pAdapter is Null")); + return; + } + + hdd_adapter_runtime_suspend_denit(pAdapter); + /* The adapter is marked as closed. When hdd_wlan_exit() call returns, + * the driver is almost closed and cannot handle either control + * messages or data. However, unregister_netdevice() call above will + * eventually invoke hdd_stop (ndo_close) driver callback, which attempts + * to close the active connections (basically excites control path) which + * is not right. Setting this flag helps hdd_stop() to recognize that + * the interface is closed and restricts any operations on that + */ + clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); + + if (test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) { + if (rtnl_held) { + unregister_netdevice(pWlanDev); + } else { + unregister_netdev(pWlanDev); + } + /* Note that the pAdapter is no longer valid at this point + since the memory has been reclaimed */ + } +} + +void hdd_set_pwrparams(hdd_context_t *pHddCtx) +{ + VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + /*loop through all adapters.*/ + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode) + && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) ) + + { // we skip this registration for modes other than STA and P2P client modes. + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + continue; + } + + //Apply Dynamic DTIM For P2P + //Only if ignoreDynamicDtimInP2pMode is not set in ini + if ((pHddCtx->cfg_ini->enableDynamicDTIM || + pHddCtx->cfg_ini->enableModulatedDTIM) && + ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) && + !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) && + (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && + (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) && + (pHddCtx->cfg_ini->fIsBmpsEnabled)) + { + tSirSetPowerParamsReq powerRequest = { 0 }; + + powerRequest.uIgnoreDTIM = 1; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; + + if (pHddCtx->cfg_ini->enableModulatedDTIM) + { + powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; + powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + } + else + { + powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; + } + + /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM + * specified during Enter/Exit BMPS when LCD off*/ + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + NULL, eANI_BOOLEAN_FALSE); + + /* switch to the DTIM specified in cfg.ini */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Switch to DTIM %d", powerRequest.uListenInterval); + sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE); + break; + + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } +} + +void hdd_reset_pwrparams(hdd_context_t *pHddCtx) +{ + /*Switch back to DTIM 1*/ + tSirSetPowerParamsReq powerRequest = { 0 }; + + powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value; + powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; + + /* Update ignoreDTIM and ListedInterval in CFG with default values */ + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + NULL, eANI_BOOLEAN_FALSE); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Switch to DTIM%d",powerRequest.uListenInterval); + sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE); + +} + +VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + + if (0 != wlan_hdd_validate_context(pHddCtx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return VOS_STATUS_E_PERM; + } + + if(pHddCtx->cfg_ini->fIsBmpsEnabled) + { + sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + } + + if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled) + { + sme_StartAutoBmpsTimer(pHddCtx->hHal); + } + + if (pHddCtx->cfg_ini->fIsImpsEnabled) + { + sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + } + + return status; +} + +VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type) +{ + hdd_adapter_t *pAdapter = NULL; + eHalStatus halStatus; + VOS_STATUS status = VOS_STATUS_E_INVAL; + v_BOOL_t disableBmps = FALSE; + v_BOOL_t disableImps = FALSE; + + switch(session_type) + { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_GO: + //Exit BMPS -> Is Sta/P2P Client is already connected + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if((NULL != pAdapter)&& + hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) + { + disableBmps = TRUE; + } + + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT); + if((NULL != pAdapter)&& + hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) + { + disableBmps = TRUE; + } + + //Exit both Bmps and Imps incase of Go/SAP Mode + if((WLAN_HDD_SOFTAP == session_type) || + (WLAN_HDD_P2P_GO == session_type)) + { + disableBmps = TRUE; + disableImps = TRUE; + } + + if(TRUE == disableImps) + { + if (pHddCtx->cfg_ini->fIsImpsEnabled) + { + sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + } + } + + if(TRUE == disableBmps) + { + if(pHddCtx->cfg_ini->fIsBmpsEnabled) + { + halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + + if(eHAL_STATUS_SUCCESS != halStatus) + { + status = VOS_STATUS_E_FAILURE; + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__); + VOS_ASSERT(0); + return status; + } + } + + if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled) + { + halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal); + + if(eHAL_STATUS_SUCCESS != halStatus) + { + status = VOS_STATUS_E_FAILURE; + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__); + VOS_ASSERT(0); + return status; + } + } + } + + if((TRUE == disableBmps) || + (TRUE == disableImps)) + { + /* Now, get the chip into Full Power now */ + INIT_COMPLETION(pHddCtx->full_pwr_comp_var); + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk, + pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); + + if(halStatus != eHAL_STATUS_SUCCESS) + { + if(halStatus == eHAL_STATUS_PMC_PENDING) + { + unsigned long rc; + //Block on a completion variable. Can't wait forever though + rc = wait_for_completion_timeout( + &pHddCtx->full_pwr_comp_var, + msecs_to_jiffies(1000)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: wait on full_pwr_comp_var failed", + __func__); +} + } + else + { + status = VOS_STATUS_E_FAILURE; + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__); + VOS_ASSERT(0); + return status; + } + } + + status = VOS_STATUS_SUCCESS; + } + + break; + } + return status; +} + +VOS_STATUS hdd_check_for_existing_macaddr( hdd_context_t *pHddCtx, + tSirMacAddr macAddr ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + + if (pAdapter && vos_mem_compare(pAdapter->macAddressCurrent.bytes, + macAddr, sizeof(tSirMacAddr))) { + return VOS_STATUS_E_FAILURE; + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + return VOS_STATUS_SUCCESS; +} + +hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, + const char *iface_name, tSirMacAddr macAddr, + tANI_U8 rtnl_held ) +{ + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pHddAdapterNode = NULL; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + VOS_STATUS exitbmpsStatus = VOS_STATUS_E_FAILURE; + hdd_cfg80211_state_t *cfgState; + int ret; + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: iface =%s type = %d\n", __func__, + iface_name, session_type); + + if (pHddCtx->current_intf_count >= pHddCtx->max_intf_count){ + /* Max limit reached on the number of vdevs configured by the host. + * Return error + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d", + __func__,pHddCtx->current_intf_count, pHddCtx->max_intf_count); + return NULL; + } + + if(macAddr == NULL) + { + /* Not received valid macAddr */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Unable to add virtual intf: Not able to get" + "valid mac address",__func__); + return NULL; + } + + status = hdd_check_for_existing_macaddr(pHddCtx, macAddr); + if (VOS_STATUS_E_FAILURE == status) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Duplicate MAC addr: "MAC_ADDRESS_STR" already exists", + __func__, MAC_ADDR_ARRAY(macAddr)); + return NULL; + } + + /* + * If Powersave Offload is enabled + * Fw will take care incase of concurrency + */ + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + { + //Disable BMPS incase of Concurrency + exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type); + + if(VOS_STATUS_E_FAILURE == exitbmpsStatus) + { + //Fail to Exit BMPS + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Fail to Exit BMPS")); + VOS_ASSERT(0); + return NULL; + } + } + + switch(session_type) + { + case WLAN_HDD_INFRA_STATION: + /* Reset locally administered bit if the device mode is STA */ + WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr); + /* fall through */ + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + case WLAN_HDD_OCB: + { + pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name ); + + if( NULL == pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("failed to allocate adapter for session %d"), session_type); + return NULL; + } + + if (session_type == WLAN_HDD_P2P_CLIENT) + pAdapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) || defined(WITH_BACKPORTS) + else if (session_type == WLAN_HDD_P2P_DEVICE) + pAdapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE; +#endif + else + pAdapter->wdev.iftype = NL80211_IFTYPE_STATION; + + pAdapter->device_mode = session_type; + + status = hdd_init_station_mode( pAdapter ); + if( VOS_STATUS_SUCCESS != status ) + goto err_free_netdev; + + // Workqueue which gets scheduled in IPv4 notification callback +#ifdef CONFIG_CNSS + cnss_init_work(&pAdapter->ipv4NotifierWorkQueue, + hdd_ipv4_notifier_work_queue); +#else +#ifdef WLAN_OPEN_SOURCE + INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, + hdd_ipv4_notifier_work_queue); +#endif +#endif + +#ifdef WLAN_NS_OFFLOAD + // Workqueue which gets scheduled in IPv6 notification callback. +#ifdef CONFIG_CNSS + cnss_init_work(&pAdapter->ipv6NotifierWorkQueue, + hdd_ipv6_notifier_work_queue); +#else +#ifdef WLAN_OPEN_SOURCE + INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, + hdd_ipv6_notifier_work_queue); +#endif +#endif +#endif + status = hdd_register_interface(pAdapter, rtnl_held); + if (VOS_STATUS_SUCCESS != status) { + hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held); + goto err_free_netdev; + } + + //Stop the Interface TX queue. + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + //netif_tx_disable(pWlanDev); + netif_carrier_off(pAdapter->dev); + +#ifdef QCA_LL_TX_FLOW_CT + /* SAT mode default TX Flow control instance + * This instance will be used for + * STA mode, IBSS mode and TDLS mode */ + if (pAdapter->tx_flow_timer_initialized == VOS_FALSE) { + vos_timer_init(&pAdapter->tx_flow_control_timer, + VOS_TIMER_TYPE_SW, + hdd_tx_resume_timer_expired_handler, + pAdapter); + pAdapter->tx_flow_timer_initialized = VOS_TRUE; + } + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, + hdd_tx_resume_cb, + pAdapter->sessionId, + (void *)pAdapter); +#endif /* QCA_LL_TX_FLOW_CT */ + + break; + } + + case WLAN_HDD_P2P_GO: + case WLAN_HDD_SOFTAP: + { + pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name ); + if( NULL == pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("failed to allocate adapter for session %d"), session_type); + return NULL; + } + + pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ? + NL80211_IFTYPE_AP: + NL80211_IFTYPE_P2P_GO; + pAdapter->device_mode = session_type; + + status = hdd_init_ap_mode(pAdapter); + if( VOS_STATUS_SUCCESS != status ) + goto err_free_netdev; + + status = hdd_register_hostapd( pAdapter, rtnl_held ); + if( VOS_STATUS_SUCCESS != status ) + { + hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held); + goto err_free_netdev; + } + + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + + hdd_set_conparam( 1 ); + + break; + } + case WLAN_HDD_MONITOR: + { + pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name ); + if( NULL == pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("failed to allocate adapter for session %d"), session_type); + return NULL; + } + + pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR; + pAdapter->device_mode = session_type; + status = hdd_register_interface( pAdapter, rtnl_held ); + pAdapter->dev->netdev_ops = &wlan_mon_drv_ops; + hdd_init_tx_rx( pAdapter ); + set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags); + //Set adapter to be used for data tx. It will use either GO or softap. + pAdapter->sessionCtx.monitor.pAdapterForTx = + hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP); + if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) + { + pAdapter->sessionCtx.monitor.pAdapterForTx = + hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO); + } + /* This work queue will be used to transmit management packet over + * monitor interface. */ + if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__); + return NULL; + } + +#ifdef CONFIG_CNSS + cnss_init_work(&pAdapter->sessionCtx.monitor.pAdapterForTx-> + monTxWorkQueue, hdd_mon_tx_work_queue); +#else +#ifdef WLAN_OPEN_SOURCE + INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue, + hdd_mon_tx_work_queue); +#endif +#endif + } + break; + case WLAN_HDD_FTM: + { + pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name ); + + if( NULL == pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("failed to allocate adapter for session %d"), session_type); + return NULL; + } + + /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning + * message while loading driver in FTM mode. */ + pAdapter->wdev.iftype = NL80211_IFTYPE_STATION; + pAdapter->device_mode = session_type; + status = hdd_register_interface( pAdapter, rtnl_held ); + + hdd_init_tx_rx( pAdapter ); + + //Stop the Interface TX queue. + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + } + break; + default: + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d", + __func__, session_type); + VOS_ASSERT(0); + return NULL; + } + } + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + mutex_init(&cfgState->remain_on_chan_ctx_lock); + + if( VOS_STATUS_SUCCESS == status ) + { +#ifdef WLAN_FEATURE_MBSSID + hdd_mbssid_apply_def_cfg_ini(pAdapter); +#endif + //Add it to the hdd's session list. + pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) ); + if( NULL == pHddAdapterNode ) + { + status = VOS_STATUS_E_NOMEM; + } + else + { + pHddAdapterNode->pAdapter = pAdapter; + status = hdd_add_adapter_back ( pHddCtx, + pHddAdapterNode ); + } + } + + if( VOS_STATUS_SUCCESS != status ) + { + if( NULL != pAdapter ) + { + hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held ); + pAdapter = NULL; + } + if( NULL != pHddAdapterNode ) + { + vos_mem_free( pHddAdapterNode ); + } + + goto resume_bmps; + } + + 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; + } + + /* Adapter successfully added. Increment the vdev count */ + pHddCtx->current_intf_count++; + + hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: current_intf_count=%d", __func__, + pHddCtx->current_intf_count); +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + if (vos_get_concurrency_mode() == VOS_STA_SAP) { + hdd_adapter_t *ap_adapter; + + ap_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP); + if (ap_adapter != NULL && + test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags) && + VOS_IS_DFS_CH(ap_adapter->sessionCtx.ap.operatingChannel)) { + + hddLog(VOS_TRACE_LEVEL_WARN, + "STA-AP Mode DFS not supported. Restart SAP with Non DFS ACS" + ); + ap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT; + ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = true; + wlan_hdd_restart_sap(ap_adapter); + } + } +#endif + } + + if ((vos_get_conparam() != VOS_FTM_MODE) && (!pHddCtx->cfg_ini->enable2x2)) + { +#define HDD_DTIM_1CHAIN_RX_ID 0x5 +#define HDD_SMPS_PARAM_VALUE_S 29 + + /* Disable DTIM 1 chain Rx when in 1x1, we are passing two values as + param_id << 29 | param_value. Below param_value = 0(disable) */ + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_SMPS_PARAM_CMDID, + HDD_DTIM_1CHAIN_RX_ID << HDD_SMPS_PARAM_VALUE_S, + VDEV_CMD); + + if (ret != 0) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: DTIM 1 chain set failed %d", __func__, ret); + goto err_free_netdev; + } + + if (!pHddCtx->per_band_chainmask_supp) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, + (int)pHddCtx->cfg_ini->txchainmask1x1, PDEV_CMD); + if (ret != 0) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: PDEV_PARAM_TX_CHAIN_MASK set failed %d", + __func__, ret); + goto err_free_netdev; + } + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, + (int)pHddCtx->cfg_ini->rxchainmask1x1, PDEV_CMD); + if (ret != 0) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d", + __func__, ret); + goto err_free_netdev; + } + } +#undef HDD_DTIM_1CHAIN_RX_ID +#undef HDD_SMPS_PARAM_VALUE_S + } + + if (VOS_FTM_MODE != vos_get_conparam()) + { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_HYST_EN, + (int)pHddCtx->cfg_ini->enableMemDeepSleep, + PDEV_CMD); + + if (ret != 0) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: WMI_PDEV_PARAM_HYST_EN set" + " failed %d", __func__, ret); + goto err_free_netdev; + } + + hddLog(LOG1, FL("SET AMSDU num %d"), pHddCtx->cfg_ini->max_amsdu_num); + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMSDU, + (int)pHddCtx->cfg_ini->max_amsdu_num, + GEN_CMD); + if (ret != 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("GEN_VDEV_PARAM_AMSDU set failed %d"), ret); + goto err_free_netdev; + } + } + + +#ifdef CONFIG_FW_LOGS_BASED_ON_INI + + /* Enable FW logs based on INI configuration */ + if ((VOS_FTM_MODE != vos_get_conparam()) && + (pHddCtx->cfg_ini->enablefwlog)) + { + tANI_U8 count = 0; + tANI_U32 value = 0; + tANI_U8 numEntries = 0; + tANI_U8 moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH]; + + pHddCtx->fw_log_settings.dl_type = pHddCtx->cfg_ini->enableFwLogType; + ret = process_wma_set_command( (int)pAdapter->sessionId, + (int)WMI_DBGLOG_TYPE, + pHddCtx->cfg_ini->enableFwLogType, DBG_CMD ); + if (ret != 0) + { + hddLog(LOGE, FL("Failed to enable FW log type ret %d"), ret); + } + + pHddCtx->fw_log_settings.dl_loglevel = pHddCtx->cfg_ini->enableFwLogLevel; + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_LOG_LEVEL, + pHddCtx->cfg_ini->enableFwLogLevel, DBG_CMD); + if (ret != 0) + { + hddLog(LOGE, FL("Failed to enable FW log level ret %d"), ret); + } + + hdd_string_to_u8_array( pHddCtx->cfg_ini->enableFwModuleLogLevel, + moduleLoglevel, + &numEntries, + FW_MODULE_LOG_LEVEL_STRING_LENGTH); + + while (count < numEntries) + { + /* FW module log level input string looks like below: + gFwDebugModuleLoglevel=, , so on.... + For example: + gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6,8,7 + Above input string means : + For FW module ID 1 enable log level 0 + For FW module ID 2 enable log level 1 + For FW module ID 3 enable log level 2 + For FW module ID 4 enable log level 3 + For FW module ID 5 enable log level 4 + For FW module ID 6 enable log level 5 + For FW module ID 7 enable log level 6 + For FW module ID 8 enable log level 7 + */ + /* FW expects WMI command value = Module ID * 10 + Module Log level */ + value = ( (moduleLoglevel[count] * 10) + moduleLoglevel[count + 1] ); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_MOD_LOG_LEVEL, + value, DBG_CMD); + if (ret != 0) + { + hddLog(LOGE, FL("Failed to enable FW module log level %d ret %d"), + value, ret); + } + + count += 2; + } + } + +#endif + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, + pHddCtx->cfg_ini->rts_profile, VDEV_CMD); + if (ret != 0) + hddLog(LOGE, "FAILED TO SET RTSCTS Profile ret:%d", ret); + + + return pAdapter; + +err_free_netdev: + free_netdev(pAdapter->dev); + wlan_hdd_release_intf_addr( pHddCtx, + pAdapter->macAddressCurrent.bytes ); + +resume_bmps: + //If bmps disabled enable it + if (!pHddCtx->cfg_ini->enablePowersaveOffload) + { + if(VOS_STATUS_SUCCESS == exitbmpsStatus) + { + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); + } + } + + return NULL; +} + +VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + tANI_U8 rtnl_held ) +{ + hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext; + VOS_STATUS status; + + status = hdd_get_front_adapter ( pHddCtx, &pCurrent ); + if( VOS_STATUS_SUCCESS != status ) + { + hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d", + __func__, status); + return status; + } + + while ( pCurrent->pAdapter != pAdapter ) + { + status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext ); + if( VOS_STATUS_SUCCESS != status ) + break; + + pCurrent = pNext; + } + pAdapterNode = pCurrent; + if( VOS_STATUS_SUCCESS == status ) + { + wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode); + hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held ); + + hdd_remove_adapter( pHddCtx, pAdapterNode ); + vos_mem_free( pAdapterNode ); + pAdapterNode = NULL; + + /* Adapter removed. Decrement vdev count */ + if (pHddCtx->current_intf_count != 0) + pHddCtx->current_intf_count--; + + /* + * If Powersave Offload is enabled, + * Fw will take care incase of concurrency + */ + if(pHddCtx->cfg_ini->enablePowersaveOffload) + return VOS_STATUS_SUCCESS; + + /* If there is a single session of STA/P2P client, re-enable BMPS */ + if ((!vos_concurrent_open_sessions_running()) && + ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) || + (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1))) + { + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); + } + + return VOS_STATUS_SUCCESS; + } + + return VOS_STATUS_E_FAILURE; +} + +VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx ) +{ + hdd_adapter_list_node_t *pHddAdapterNode; + VOS_STATUS status; + + ENTER(); + + do + { + status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode ); + if( pHddAdapterNode && VOS_STATUS_SUCCESS == status ) + { + hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE ); + vos_mem_free( pHddAdapterNode ); + } + }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status ); + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter) +{ + tANI_U8 *bssid = NULL; + tSirUpdateIE updateIE; + switch (pHostapdAdapter->device_mode) + { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + { + hdd_station_ctx_t * pHddStaCtx = + WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter); + bssid = (tANI_U8*)&pHddStaCtx->conn_info.bssId; + break; + } + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + case WLAN_HDD_IBSS: + { + bssid = pHostapdAdapter->macAddressCurrent.bytes; + break; + } + case WLAN_HDD_MONITOR: + case WLAN_HDD_FTM: + case WLAN_HDD_P2P_DEVICE: + default: + /* + * wlan_hdd_reset_prob_rspies should not have been called + * for these kind of devices + */ + hddLog(LOGE, FL("Unexpected request for the current device type %d"), + pHostapdAdapter->device_mode); + return; + } + + vos_mem_copy(updateIE.bssid, bssid, sizeof(tSirMacAddr)); + updateIE.smeSessionId = pHostapdAdapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = VOS_TRUE; + updateIE.notify = VOS_FALSE; + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter), + &updateIE, eUPDATE_IE_PROBE_RESP) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE")); + } +} + +VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + const v_BOOL_t bCloseSession) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + union iwreq_data wrqu; + tSirUpdateIE updateIE ; + unsigned long rc; + + ENTER(); + + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + switch(pAdapter->device_mode) + { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_IBSS: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)) || + hdd_is_connecting(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) + { + if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS) + halStatus = sme_RoamDisconnect(pHddCtx->hHal, + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + else + halStatus = sme_RoamDisconnect(pHddCtx->hHal, + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + //success implies disconnect command got queued up successfully + if(halStatus == eHAL_STATUS_SUCCESS) + { + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: wait on disconnect_comp_var failed", + __func__); + } + } + else + { + hddLog(LOGE, "%s: failed to post disconnect event to SME", + __func__); + } + memset(&wrqu, '\0', sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN); + wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL); + } + else + { + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + if ((pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) || + (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)) { + wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter); + } + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue); +#endif + + wlan_hdd_clean_tx_flow_control_timer(pHddCtx, pAdapter); + +#ifdef WLAN_NS_OFFLOAD +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue); +#endif +#endif + + /* It is possible that the caller of this function does not + * wish to close the session + */ + if (VOS_TRUE == bCloseSession && + test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) + { + INIT_COMPLETION(pAdapter->session_close_comp_var); + if (eHAL_STATUS_SUCCESS == + sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, + hdd_smeCloseSessionCallback, pAdapter)) + { + //Block on a completion variable. Can't wait forever though. + rc = wait_for_completion_timeout( + &pAdapter->session_close_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + if (!rc) { + hddLog(LOGE, "%s: failure waiting for session_close_comp_var", + __func__); + } + } + } + break; + + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + if (pHddCtx->cfg_ini->conc_custom_rule1 && + (WLAN_HDD_SOFTAP == pAdapter->device_mode)) { + /* + * Before stopping the sap adapter, lets make sure there is + * no sap restart work pending. + */ + vos_flush_work(&pHddCtx->sap_start_work); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Canceled the pending SAP restart work")); + hdd_change_sap_restart_required_status(pHddCtx, false); + } + //Any softap specific cleanup here... + if (pAdapter->device_mode == WLAN_HDD_P2P_GO) { + wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter); + } + + hdd_set_sap_auth_offload(pAdapter, FALSE); + + wlan_hdd_clean_tx_flow_control_timer(pHddCtx, pAdapter); + + mutex_lock(&pHddCtx->sap_lock); + if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) + { + VOS_STATUS status; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_hostapd_state_t *pHostapdState = + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + vos_event_reset(&pHostapdState->stop_bss_event); + + //Stop Bss. +#ifdef WLAN_FEATURE_MBSSID + status = WLANSAP_StopBss(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter)); +#else + status = WLANSAP_StopBss(pHddCtx->pvosContext); +#endif + + if (VOS_IS_STATUS_SUCCESS(status)) + { + status = vos_wait_single_event(&pHostapdState->stop_bss_event, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d", + __func__, status); + } + } + else + { + hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__); + } + clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags); + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); + + vos_mem_copy(updateIE.bssid, pAdapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = pAdapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = VOS_FALSE; + updateIE.notify = VOS_FALSE; + /* Probe bcn reset */ + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, eUPDATE_IE_PROBE_BCN) + == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE")); + } + /* Assoc resp reset */ + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, eUPDATE_IE_ASSOC_RESP) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on ASSOC_RSP data to PE")); + } + + // Reset WNI_CFG_PROBE_RSP Flags + wlan_hdd_reset_prob_rspies(pAdapter); + kfree(pAdapter->sessionCtx.ap.beacon); + pAdapter->sessionCtx.ap.beacon = NULL; + } + mutex_unlock(&pHddCtx->sap_lock); + break; + + case WLAN_HDD_MONITOR: +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue); +#endif + break; + + case WLAN_HDD_OCB: + hdd_disconnect_tx_rx(pAdapter); + WLANTL_ClearSTAClient(WLAN_HDD_GET_CTX(pAdapter)->pvosContext, + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)->conn_info.staId[0]); + break; + + default: + break; + } + + EXIT(); + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + + ENTER(); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE ); + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + + ENTER(); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(pAdapter->dev); + netif_carrier_off(pAdapter->dev); + + pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; + + hdd_deinit_tx_rx(pAdapter); + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); + if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags)) + { + hdd_wmm_adapter_close( pAdapter ); + clear_bit(WMM_INIT_DONE, &pAdapter->event_flags); + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +/** + * hdd_connect_result() - API to send connection status to supplicant + * @dev: network device + * @bssid: bssid to which we want to associate + * @req_ie: Request Information Element + * @req_ie_len: len of the req IE + * @resp_ie: Response IE + * @resp_ie_len: len of ht response IE + * @status: status + * @gfp: Kernel Flag + * + * The API is a wrapper to send connection status to supplicant + * and allow runtime suspend + * + * Return: Void + */ + +void hdd_connect_result(struct net_device *dev, + const u8 *bssid, + const u8 *req_ie, + size_t req_ie_len, + const u8 * resp_ie, + size_t resp_ie_len, + u16 status, + gfp_t gfp) +{ + hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev); + + cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, + resp_ie, resp_ie_len, status, gfp); + + vos_runtime_pm_allow_suspend(padapter->runtime_context.connect); +} + + +VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; +#if !defined(MSM_PLATFORM) || defined(WITH_BACKPORTS) + v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER; +#endif + eConnectionState connState; + + ENTER(); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + hdd_wmm_init( pAdapter ); + + switch(pAdapter->device_mode) + { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + + connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState; + + hdd_init_station_mode(pAdapter); + /* Open the gates for HDD to receive Wext commands */ + pAdapter->isLinkUpSvcNeeded = FALSE; + pAdapter->scan_info.mScanPending = FALSE; + pAdapter->scan_info.waitScanResult = FALSE; + + //Indicate disconnect event to supplicant if associated previously + if (eConnectionState_Associated == connState || + eConnectionState_IbssConnected == connState || + eConnectionState_NotConnected == connState || + eConnectionState_IbssDisconnected == connState || + eConnectionState_Disconnecting == connState) + { + union iwreq_data wrqu; + memset(&wrqu, '\0', sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN); + wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL); + pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; + + /* indicate disconnected event to nl80211 */ + cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, + NULL, 0, GFP_KERNEL); + } + else if (eConnectionState_Connecting == connState) + { + /* + * Indicate connect failure to supplicant if we were in the + * process of connecting + */ + hdd_connect_result(pAdapter->dev, NULL, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } + +#ifdef QCA_LL_TX_FLOW_CT + WLANTL_RegisterTXFlowControl(pHddCtx->pvosContext, hdd_tx_resume_cb, + pAdapter->sessionId, (void *)pAdapter); +#endif + + break; + + case WLAN_HDD_SOFTAP: + /* softAP can handle SSR */ + break; + + case WLAN_HDD_P2P_GO: +#if defined(MSM_PLATFORM) && !defined(WITH_BACKPORTS) + hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant", + __func__); + cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL); +#else + hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant", + __func__); + /* event supplicant to restart */ + cfg80211_del_sta(pAdapter->dev, + (const u8 *)&bcastMac.bytes[0], GFP_KERNEL); +#endif + break; + + case WLAN_HDD_MONITOR: + /* monitor interface start */ + break; + default: + break; + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + v_U32_t roamId; + unsigned long rc; + + ENTER(); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ) + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Set HDD connState to eConnectionState_NotConnected", + __func__); + if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) { + wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode); + } + pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; + init_completion(&pAdapter->disconnect_comp_var); + sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(LOGE, "%s: failure waiting for disconnect_comp_var", + __func__); + pWextState->roamProfile.csrPersona = pAdapter->device_mode; + pHddCtx->isAmpAllowed = VOS_FALSE; + sme_RoamConnect(pHddCtx->hHal, + pAdapter->sessionId, &(pWextState->roamProfile), + &roamId); + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +void hdd_dump_concurrency_info(hdd_context_t *pHddCtx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + hdd_station_ctx_t *pHddStaCtx; + hdd_ap_ctx_t *pHddApCtx; + hdd_hostapd_state_t * pHostapdState; + tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }; + tCsrBssid apBssid = { 0 }, apBssid1 = { 0 }, apBssid2 = { 0 }; + v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0; + v_U8_t apChannel1 = 0, apChannel2 = 0; + const char *p2pMode = "DEV"; + bool mcc_mode = FALSE; + +#ifdef QCA_LL_TX_FLOW_CT + v_U8_t targetChannel = 0; + v_U8_t preAdapterChannel = 0; + v_U8_t channel24; + v_U8_t channel5; + hdd_adapter_t *preAdapterContext = NULL; + hdd_adapter_t *pAdapter2_4 = NULL; + hdd_adapter_t *pAdapter5 = NULL; +#endif /* QCA_LL_TX_FLOW_CT */ + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + switch (pAdapter->device_mode) { + case WLAN_HDD_INFRA_STATION: + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) { + staChannel = pHddStaCtx->conn_info.operationChannel; + memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid)); +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = staChannel; +#endif /* QCA_LL_TX_FLOW_CT */ + } + break; + case WLAN_HDD_P2P_CLIENT: + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) { + p2pChannel = pHddStaCtx->conn_info.operationChannel; + memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid)); + p2pMode = "CLI"; +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = p2pChannel; +#endif /* QCA_LL_TX_FLOW_CT */ + } + break; + case WLAN_HDD_P2P_GO: + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) { + p2pChannel = pHddApCtx->operatingChannel; + memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid)); +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = p2pChannel; +#endif /* QCA_LL_TX_FLOW_CT */ + } + p2pMode = "GO"; + break; + case WLAN_HDD_SOFTAP: + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) { + apChannel = pHddApCtx->operatingChannel; + memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid)); + if (!pHddApCtx->uBCStaId) { + apChannel1 = apChannel; + memcpy(apBssid1, apBssid, sizeof(apBssid)); + } else { + apChannel2 = apChannel; + memcpy(apBssid2, apBssid, sizeof(apBssid)); + } +#ifdef QCA_LL_TX_FLOW_CT + targetChannel = apChannel; +#endif /* QCA_LL_TX_FLOW_CT */ + } + break; + case WLAN_HDD_IBSS: + return; /* skip printing station message below */ + default: + break; + } +#ifdef QCA_LL_TX_FLOW_CT + if (targetChannel) + { + /* This is first adapter detected as active + * set as default for none concurrency case */ + if (!preAdapterChannel) + { +#ifdef IPA_UC_OFFLOAD + /* If IPA UC data path is enabled, + * target should reserve extra tx descriptors + * for IPA WDI data path. + * Then host data path should allow less TX packet pumping in case + * IPA WDI data path enabled */ + if ((pHddCtx->cfg_ini->IpaUcOffloadEnabled) && + (WLAN_HDD_SOFTAP == pAdapter->device_mode)) { + pAdapter->tx_flow_low_watermark = + pHddCtx->cfg_ini->TxFlowLowWaterMark + + WLAN_TFC_IPAUC_TX_DESC_RESERVE; + } else +#endif /* IPA_UC_OFFLOAD */ +#ifdef CONFIG_HL_SUPPORT + { + pAdapter->tx_flow_low_watermark = 0; + } + pAdapter->tx_flow_high_watermark_offset = 0; +#else + { + pAdapter->tx_flow_low_watermark = + pHddCtx->cfg_ini->TxFlowLowWaterMark; + } + pAdapter->tx_flow_high_watermark_offset = + pHddCtx->cfg_ini->TxFlowHighWaterMarkOffset; +#endif + WLANTL_SetAdapterMaxQDepth(pHddCtx->pvosContext, + pAdapter->sessionId, + pHddCtx->cfg_ini->TxFlowMaxQueueDepth); + /* Temporary set log level as error + * TX Flow control feature settled down, will lower log level */ + hddLog(LOG1, + "MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, + targetChannel, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_low_watermark + + pAdapter->tx_flow_high_watermark_offset, + pHddCtx->cfg_ini->TxFlowMaxQueueDepth); + preAdapterChannel = targetChannel; + preAdapterContext = pAdapter; + } + else + { + /* SCC, disable TX flow control for both + * SCC each adapter cannot reserve dedicated channel resource + * as a result, if any adapter blocked OS Q by flow control, + * blocked adapter will lost chance to recover */ + if (preAdapterChannel == targetChannel) + { + /* Current adapter */ + pAdapter->tx_flow_low_watermark = 0; + pAdapter->tx_flow_high_watermark_offset = 0; + WLANTL_SetAdapterMaxQDepth(pHddCtx->pvosContext, + pAdapter->sessionId, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + hddLog(LOG1, + "SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, + targetChannel, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_low_watermark + + pAdapter->tx_flow_high_watermark_offset, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + + if (!preAdapterContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "SCC: Previous adapter context NULL"); + continue; + } + + /* Previous adapter */ + preAdapterContext->tx_flow_low_watermark = 0; + preAdapterContext->tx_flow_high_watermark_offset = 0; + WLANTL_SetAdapterMaxQDepth(pHddCtx->pvosContext, + preAdapterContext->sessionId, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + /* Temporary set log level as error + * TX Flow control feature settled down, will lower log level */ + hddLog(LOG1, + "SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string(preAdapterContext->device_mode), + preAdapterContext->device_mode, + targetChannel, + preAdapterContext->tx_flow_low_watermark, + preAdapterContext->tx_flow_low_watermark + + preAdapterContext->tx_flow_high_watermark_offset, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + } + /* MCC, each adapter will have dedicated resource */ + else + { + /* current channel is 2.4 */ + if (targetChannel <= WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH) + { + channel24 = targetChannel; + channel5 = preAdapterChannel; + pAdapter2_4 = pAdapter; + pAdapter5 = preAdapterContext; + } + /* Current channel is 5 */ + else + { + channel24 = preAdapterChannel; + channel5 = targetChannel; + pAdapter2_4 = preAdapterContext; + pAdapter5 = pAdapter; + } + + if (!pAdapter5) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "MCC: 5GHz adapter context NULL"); + continue; + } + pAdapter5->tx_flow_low_watermark = + pHddCtx->cfg_ini->TxHbwFlowLowWaterMark; + pAdapter5->tx_flow_high_watermark_offset = + pHddCtx->cfg_ini->TxHbwFlowHighWaterMarkOffset; + WLANTL_SetAdapterMaxQDepth(pHddCtx->pvosContext, + pAdapter5->sessionId, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + /* Temporary set log level as error + * TX Flow control feature settled down, will lower log level */ + hddLog(LOG1, + "MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string(pAdapter5->device_mode), + pAdapter5->device_mode, + channel5, + pAdapter5->tx_flow_low_watermark, + pAdapter5->tx_flow_low_watermark + + pAdapter5->tx_flow_high_watermark_offset, + pHddCtx->cfg_ini->TxHbwFlowMaxQueueDepth); + + if (!pAdapter2_4) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "MCC: 2.4GHz adapter context NULL"); + continue; + } + pAdapter2_4->tx_flow_low_watermark = + pHddCtx->cfg_ini->TxLbwFlowLowWaterMark; + pAdapter2_4->tx_flow_high_watermark_offset = + pHddCtx->cfg_ini->TxLbwFlowHighWaterMarkOffset; + WLANTL_SetAdapterMaxQDepth(pHddCtx->pvosContext, + pAdapter2_4->sessionId, + pHddCtx->cfg_ini->TxLbwFlowMaxQueueDepth); + /* Temporary set log level as error + * TX Flow control feature settled down, will lower log level */ + hddLog(LOG1, + "MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string(pAdapter2_4->device_mode), + pAdapter2_4->device_mode, + channel24, + pAdapter2_4->tx_flow_low_watermark, + pAdapter2_4->tx_flow_low_watermark + + pAdapter2_4->tx_flow_high_watermark_offset, + pHddCtx->cfg_ini->TxLbwFlowMaxQueueDepth); + } + } + } + targetChannel = 0; +#endif /* QCA_LL_TX_FLOW_CT */ + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + /* + * Determine SCC/MSS + * Remind that this only considered STA+AP and AP+AP concurrency + * Need to expand for futher concurreny in the future + */ + if (apChannel1 > 0 && apChannel2 > 0) { + mcc_mode = apChannel1 != apChannel2; + } else if (staChannel > 0 && (apChannel1 > 0 || p2pChannel > 0)) { + mcc_mode = !(p2pChannel==staChannel || apChannel1==staChannel); + } + if (pHddCtx->mcc_mode != mcc_mode) { +#ifdef IPA_UC_STA_OFFLOAD + /* Send SCC/MCC Switching event to IPA */ + hdd_ipa_send_mcc_scc_msg(pHddCtx, mcc_mode); +#endif + pHddCtx->mcc_mode = mcc_mode; + } + hddLog(VOS_TRACE_LEVEL_INFO, "wlan(%d) " MAC_ADDRESS_STR " %s", + staChannel, MAC_ADDR_ARRAY(staBssid), mcc_mode ? "MCC" : "SCC"); + if (p2pChannel > 0) { + hddLog(VOS_TRACE_LEVEL_INFO, "p2p-%s(%d) " MAC_ADDRESS_STR, + p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid)); + } + if (apChannel1 > 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR, + apChannel1, MAC_ADDR_ARRAY(apBssid1)); + } + if (apChannel2 > 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR, + apChannel2, MAC_ADDR_ARRAY(apBssid2)); + } + + if (p2pChannel > 0 && apChannel1 > 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Error concurrent SAP %d and P2P %d which is not support"), + apChannel1, p2pChannel); + } +} + +bool hdd_is_ssr_required( void) +{ + return (isSsrRequired == HDD_SSR_REQUIRED); +} + +/* Once SSR is disabled then it cannot be set. */ +void hdd_set_ssr_required( e_hdd_ssr_required value) +{ + if (HDD_SSR_DISABLED == isSsrRequired) + return; + + isSsrRequired = value; +} + +VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t** ppAdapterNode) +{ + VOS_STATUS status; + spin_lock_bh(&pHddCtx->hddAdapters.lock); + status = hdd_list_peek_front ( &pHddCtx->hddAdapters, + (hdd_list_node_t**) ppAdapterNode ); + spin_unlock_bh(&pHddCtx->hddAdapters.lock); + return status; +} + +VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode, + hdd_adapter_list_node_t** pNextAdapterNode) +{ + VOS_STATUS status; + spin_lock_bh(&pHddCtx->hddAdapters.lock); + status = hdd_list_peek_next ( &pHddCtx->hddAdapters, + (hdd_list_node_t*) pAdapterNode, + (hdd_list_node_t**)pNextAdapterNode ); + + spin_unlock_bh(&pHddCtx->hddAdapters.lock); + return status; +} + +VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode) +{ + VOS_STATUS status; + spin_lock_bh(&pHddCtx->hddAdapters.lock); + status = hdd_list_remove_node ( &pHddCtx->hddAdapters, + &pAdapterNode->node ); + spin_unlock_bh(&pHddCtx->hddAdapters.lock); + return status; +} + +VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t** ppAdapterNode) +{ + VOS_STATUS status; + spin_lock_bh(&pHddCtx->hddAdapters.lock); + status = hdd_list_remove_front( &pHddCtx->hddAdapters, + (hdd_list_node_t**) ppAdapterNode ); + spin_unlock_bh(&pHddCtx->hddAdapters.lock); + return status; +} + +VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode) +{ + VOS_STATUS status; + spin_lock_bh(&pHddCtx->hddAdapters.lock); + status = hdd_list_insert_back ( &pHddCtx->hddAdapters, + (hdd_list_node_t*) pAdapterNode ); + spin_unlock_bh(&pHddCtx->hddAdapters.lock); + return status; +} + +VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx, + hdd_adapter_list_node_t* pAdapterNode) +{ + VOS_STATUS status; + spin_lock_bh(&pHddCtx->hddAdapters.lock); + status = hdd_list_insert_front ( &pHddCtx->hddAdapters, + (hdd_list_node_t*) pAdapterNode ); + spin_unlock_bh(&pHddCtx->hddAdapters.lock); + return status; +} + +hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx, + tSirMacAddr macAddr ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes, + macAddr, sizeof(tSirMacAddr) ) ) + { + return pAdapter; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + return NULL; + +} + +hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name, + IFNAMSIZ ) ) + { + return pAdapter; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + return NULL; + +} + +hdd_adapter_t *hdd_get_adapter_by_vdev( hdd_context_t *pHddCtx, + tANI_U32 vdev_id ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS vos_status; + + + vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode); + + while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status)) + { + pAdapter = pAdapterNode->pAdapter; + + if (pAdapter->sessionId == vdev_id) + return pAdapter; + + vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vdev_id %d does not exist with host", + __func__, vdev_id); + + return NULL; +} + +hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if( pAdapter && (mode == pAdapter->device_mode) ) + { + return pAdapter; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + return NULL; + +} + +//Remove this function later +hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + VOS_STATUS status; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode ) + { + return pAdapter; + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + return NULL; + +} + +/**--------------------------------------------------------------------------- + + \brief hdd_set_monitor_tx_adapter() - + + This API initializes the adapter to be used while transmitting on monitor + adapter. + + \param - pHddCtx - Pointer to the HDD context. + pAdapter - Adapter that will used for TX. This can be NULL. + \return - None. + --------------------------------------------------------------------------*/ +void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) +{ + hdd_adapter_t *pMonAdapter; + + pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR ); + + if( NULL != pMonAdapter ) + { + pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter; + } +} +/**--------------------------------------------------------------------------- + + \brief hdd_get_operating_channel() - + + This API returns the operating channel of the requested device mode + + \param - pHddCtx - Pointer to the HDD context. + - mode - Device mode for which operating channel is required + supported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT + WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO. + \return - channel number. "0" id the requested device is not found OR it is not connected. + --------------------------------------------------------------------------*/ +v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode ) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + v_U8_t operatingChannel = 0; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if( mode == pAdapter->device_mode ) + { + switch(pAdapter->device_mode) + { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ) + operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel; + break; + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + /*softap connection info */ + if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) + operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel; + break; + default: + break; + } + + break; //Found the device of interest. break the loop + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + return operatingChannel; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_wlan_initial_scan() - + + This function triggers the initial scan + + \param - pAdapter - Pointer to the HDD adapter. + + --------------------------------------------------------------------------*/ +void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter) +{ + tCsrScanRequest scanReq; + tCsrChannelInfo channelInfo; + eHalStatus halStatus; + tANI_U32 scanId; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + vos_mem_zero(&scanReq, sizeof(tCsrScanRequest)); + vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff); + scanReq.BSSType = eCSR_BSS_TYPE_ANY; + + if(sme_Is11dSupported(pHddCtx->hHal)) + { + halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo ); + if ( HAL_STATUS_SUCCESS( halStatus ) ) + { + scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels); + if( !scanReq.ChannelInfo.ChannelList ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__); + vos_mem_free(channelInfo.ChannelList); + channelInfo.ChannelList = NULL; + return; + } + vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList, + channelInfo.numOfChannels); + scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels; + vos_mem_free(channelInfo.ChannelList); + channelInfo.ChannelList = NULL; + } + + scanReq.scanType = eSIR_PASSIVE_SCAN; + scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN; + scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime; + scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime; + } + else + { + scanReq.scanType = eSIR_ACTIVE_SCAN; + scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime; + scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime; + } + + halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d", + __func__, halStatus ); + } + + if(sme_Is11dSupported(pHddCtx->hHal)) + vos_mem_free(scanReq.ChannelInfo.ChannelList); +} + +/**--------------------------------------------------------------------------- + + \brief hdd_full_power_callback() - HDD full power callback function + + This is the function invoked by SME to inform the result of a full power + request issued by HDD + + \param - callback context - Pointer to cookie + \param - status - result of request + + \return - None + + --------------------------------------------------------------------------*/ +static void hdd_full_power_callback(void *callbackContext, eHalStatus status) +{ + struct statsContext *pContext = callbackContext; + + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: context = %p, status = %d", __func__, pContext, status); + + if (NULL == callbackContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, context [%p]", + __func__, callbackContext); + return; + } + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + if (POWER_CONTEXT_MAGIC != pContext->magic) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, magic [%08x]", + __func__, pContext->magic); + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pContext->magic = 0; + + /* notify the caller */ + complete(&pContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +static inline VOS_STATUS hdd_UnregisterWext_all_adapters(hdd_context_t *pHddCtx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + + ENTER(); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) || + (pAdapter->device_mode == WLAN_HDD_IBSS) || + (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) || + (pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + wlan_hdd_cfg80211_deregister_frames(pAdapter); + hdd_UnregisterWext(pAdapter->dev); + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *pHddCtx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + + ENTER(); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) + { + pAdapter = pAdapterNode->pAdapter; + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) || + (pAdapter->device_mode == WLAN_HDD_IBSS) || + (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) || + (pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + EXIT(); + + return VOS_STATUS_SUCCESS; +} + +/** + * wlan_hdd_restart_init() - restart init + * @pHddCtx: Pointer to hdd context + * + * This function initializes restart timer/flag. An internal function. + * + * Return: None + */ +static void wlan_hdd_restart_init(hdd_context_t *pHddCtx) +{ + /* Initialize */ + pHddCtx->hdd_restart_retries = 0; + atomic_set(&pHddCtx->isRestartInProgress, 0); + vos_timer_init(&pHddCtx->hdd_restart_timer, + VOS_TIMER_TYPE_SW, + wlan_hdd_restart_timer_cb, + pHddCtx); +} + +/** + * wlan_hdd_restart_deinit() - restart deinit + * @pHddCtx: Pointer to hdd context + * + * This function cleans up the resources used. An internal function. + * + * Return: None + */ +static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx) +{ + VOS_STATUS vos_status; + /* Block any further calls */ + atomic_set(&pHddCtx->isRestartInProgress, 1); + /* Cleanup */ + vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer ); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to stop HDD restart timer")); + vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to destroy HDD restart timer")); +} + +#ifdef WLAN_NS_OFFLOAD +/** + * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier + * @hdd_ctx: Pointer to hdd context + * + * Return: None + */ +static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) +{ + unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier); + + return; +} + +/** + * hdd_wlan_register_ip6_notifier() - register IP6 change notifier + * @hdd_ctx: Pointer to hdd context + * + * Return: None + */ +static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) +{ + int ret; + + hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed; + ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier); + if (ret) + hddLog(LOGE, FL("Failed to register IPv6 notifier")); + else + hddLog(LOG1, FL("Registered IPv6 notifier")); + + return; +} +#else +/** + * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier + * @hdd_ctx: Pointer to hdd context + * + * Return: None + */ +static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) +{ +} +/** + * hdd_wlan_register_ip6_notifier() - register IP6 change notifier + * @hdd_ctx: Pointer to hdd context + * + * Return: None + */ +static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) +{ +} +#endif + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE +/** + * wlan_hdd_logging_sock_activate_svc() - Activate logging + * @hdd_ctx: HDD context + * + * Activates the logging service + * + * Return: Zero in case of success, negative value otherwise + */ +static int wlan_hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) +{ + if (hdd_ctx->cfg_ini->wlanLoggingEnable) { + if (wlan_logging_sock_activate_svc( + hdd_ctx->cfg_ini->wlanLoggingFEToConsole, + hdd_ctx->cfg_ini->wlanLoggingNumBuf)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: wlan_logging_sock_activate_svc failed", + __func__); + return -EINVAL; + } + } + return 0; +} +/** + * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging + * @hdd_ctx: HDD context + * + * Deactivates the logging service + * + * Return: 0 on deactivating the logging service + */ +static int wlan_hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) +{ + if (hdd_ctx && hdd_ctx->cfg_ini->wlanLoggingEnable) + return wlan_logging_sock_deactivate_svc(); + + return 0; +} +#else +static inline int wlan_hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) +{ + return 0; +} + +static inline int wlan_hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) +{ + return 0; +} +#endif + +/**--------------------------------------------------------------------------- + + \brief hdd_wlan_exit() - HDD WLAN exit function + + This is the driver exit point (invoked during rmmod) + + \param - pHddCtx - Pointer to the HDD Context + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_wlan_exit(hdd_context_t *pHddCtx) +{ + eHalStatus halStatus; + v_CONTEXT_t pVosContext = pHddCtx->pvosContext; + VOS_STATUS vosStatus; + struct wiphy *wiphy = pHddCtx->wiphy; + struct statsContext powerContext; + unsigned long rc; + hdd_config_t *pConfig = pHddCtx->cfg_ini; + + ENTER(); + + hddLog(LOGE, FL("Unregister IPv6 notifier")); + hdd_wlan_unregister_ip6_notifier(pHddCtx); + hddLog(LOGE, FL("Unregister IPv4 notifier")); + unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier); + + if (VOS_FTM_MODE != hdd_get_conparam()) + { + // Unloading, restart logic is no more required. + wlan_hdd_restart_deinit(pHddCtx); + } + + hdd_UnregisterWext_all_adapters(pHddCtx); + + if (VOS_FTM_MODE == hdd_get_conparam()) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: FTM MODE", __func__); +#if defined(QCA_WIFI_FTM) + if (hdd_ftm_stop(pHddCtx)) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_ftm_stop Failed",__func__); + VOS_ASSERT(0); + } + pHddCtx->ftm.ftm_state = WLAN_FTM_STOPPED; +#endif + wlan_hdd_ftm_close(pHddCtx); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: FTM driver unloaded", __func__); + goto free_hdd_ctx; + } + + /* DeRegister with platform driver as client for Suspend/Resume */ + vosStatus = hddDeregisterPmOps(pHddCtx); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__); + VOS_ASSERT(0); + } + + vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__); + } + + /* + * Cancel any outstanding scan requests. We are about to close all + * of our adapters, but an adapter structure is what SME passes back + * to our callback function. Hence if there are any outstanding scan + * requests then there is a race condition between when the adapter + * is closed and when the callback is invoked. We try to resolve that + * race condition here by cancelling any outstanding scans before we + * close the adapters. + * Note that the scans may be cancelled in an asynchronous manner, so + * ideally there needs to be some kind of synchronization. Rather than + * introduce a new synchronization here, we will utilize the fact that + * we are about to Request Full Power, and since that is synchronized, + * the expectation is that by the time Request Full Power has completed, + * all scans will be cancelled. + */ + hdd_abort_mac_scan_all_adapters(pHddCtx); + +#ifdef MSM_PLATFORM + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->bus_bw_timer)) + { + vos_timer_stop(&pHddCtx->bus_bw_timer); + } + + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy( + &pHddCtx->bus_bw_timer))) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Cannot deallocate Bus bandwidth timer", __func__); + } +#endif + +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->skip_acs_scan_timer)) { + vos_timer_stop(&pHddCtx->skip_acs_scan_timer); + } + + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy( + &pHddCtx->skip_acs_scan_timer))) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Cannot deallocate ACS Skip timer", __func__); + } +#endif + + if (pConfig && !pConfig->enablePowersaveOffload) + { + //Disable IMPS/BMPS as we do not want the device to enter any power + //save mode during shutdown + sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); + sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE); + sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE); + + //Ensure that device is in full power as we will touch H/W during vos_Stop + init_completion(&powerContext.completion); + powerContext.magic = POWER_CONTEXT_MAGIC; + + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback, + &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD); + + if (eHAL_STATUS_SUCCESS != halStatus) + { + if (eHAL_STATUS_PMC_PENDING == halStatus) + { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout( + &powerContext.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: timed out while requesting full power", + __func__); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Request for Full Power failed, status %d", + __func__, halStatus); + /* continue -- need to clean up as much as possible */ + } + } + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + powerContext.magic = 0; + spin_unlock(&hdd_context_lock); + } + else + { + /* + * Powersave Offload Case + * Disable Idle Power Save Mode + */ + hdd_set_idle_ps_config(pHddCtx, FALSE); + } + + hdd_debugfs_exit(pHddCtx); + + // Unregister the Net Device Notifier + unregister_netdevice_notifier(&hdd_netdev_notifier); + + /* Stop all adapters, this will ensure the termination of active + * connections on the interface. Make sure the vos_scheduler is + * still available to handle those control messages + */ + hdd_stop_all_adapters( pHddCtx ); + + + //Stop all the modules + vosStatus = vos_stop( pVosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to stop VOSS",__func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + //This requires pMac access, Call this before vos_close(). + hdd_unregister_mcast_bcast_filter(pHddCtx); + + //Close the scheduler before calling vos_close to make sure no thread is + // scheduled after the each module close is called i.e after all the data + // structures are freed. + vosStatus = vos_sched_close( pVosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to close VOSS Scheduler",__func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + /* Destroy the wake lock */ + vos_wake_lock_destroy(&pHddCtx->rx_wake_lock); +#endif + /* Destroy the wake lock */ + vos_wake_lock_destroy(&pHddCtx->sap_wake_lock); + + hdd_hostapd_channel_wakelock_deinit(pHddCtx); + + vosStatus = vos_nv_close(); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close NV", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + //Close VOSS + //This frees pMac(HAL) context. There should not be any call that requires pMac access after this. + vos_close(pVosContext); + +#ifdef FEATURE_GREEN_AP + if (!VOS_IS_STATUS_SUCCESS( + hdd_wlan_green_ap_deattach(pHddCtx))) + { + hddLog(LOGE, FL("Cannot deallocate Green-AP resource")); + } +#endif + + //Close Watchdog + if (pConfig && pConfig->fIsLogpEnabled) + vos_watchdog_close(pVosContext); + + //Clean up HDD Nlink Service + send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); + + if (VOS_FTM_MODE != hdd_get_conparam()) + wlan_hdd_logging_sock_deactivate_svc(pHddCtx); + +#ifdef WLAN_KD_READY_NOTIFIER + cnss_diag_notify_wlan_close(); + nl_srv_exit(pHddCtx->ptt_pid); +#else + nl_srv_exit(); +#endif /* WLAN_KD_READY_NOTIFIER */ + + + hdd_runtime_suspend_deinit(pHddCtx); + hdd_close_all_adapters( pHddCtx ); + +#ifdef IPA_OFFLOAD + hdd_ipa_cleanup(pHddCtx); +#endif + + /* free the power on lock from platform driver */ + if (free_riva_power_on_lock("wlan")) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock", + __func__); + } + + /* Free up RoC request queue and flush workqueue */ + vos_flush_work(&pHddCtx->rocReqWork); + hdd_list_destroy(&pHddCtx->hdd_roc_req_q); + +free_hdd_ctx: + + /* Free up dynamically allocated members inside HDD Adapter */ + if (pHddCtx->cfg_ini) { + kfree(pHddCtx->cfg_ini); + pHddCtx->cfg_ini= NULL; + } + + wlan_hdd_deinit_tx_rx_histogram(pHddCtx); + wiphy_unregister(wiphy) ; + + wiphy_free(wiphy) ; + if (hdd_is_ssr_required()) + { +#ifdef MSM_PLATFORM +#ifdef CONFIG_CNSS + /* WDI timeout had happened during unload, so SSR is needed here */ + subsystem_restart("wcnss"); +#endif +#endif + msleep(5000); + } + hdd_set_ssr_required (VOS_FALSE); +} + +void __hdd_wlan_exit(void) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + + ENTER(); + + //Get the global vos context + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!pVosContext) + return; + if (WLAN_IS_EPPING_ENABLED(con_mode)) { + epping_exit(pVosContext); + return; + } + + if(NULL == pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:Invalid global VOSS context", __func__); + EXIT(); + return; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, + pVosContext); + + if(NULL == pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:Invalid HDD Context", __func__); + EXIT(); + return; + } + + /* module exit should never proceed if SSR is not completed */ + while(pHddCtx->isLogpInProgress){ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR in Progress; block rmmod for 1 second!!!", + __func__); + msleep(1000); + } + + pHddCtx->isUnloadInProgress = TRUE; + + vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); + vos_set_unload_in_progress(TRUE); + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); +#endif + + //Do all the cleanup before deregistering the driver + hdd_wlan_exit(pHddCtx); + EXIT(); +} + +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE +void hdd_skip_acs_scan_timer_handler(void * data) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) data; + hdd_adapter_t *ap_adapter; + + hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip")); + hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN; + + /* Get first SAP adapter to clear results */ + ap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (!hdd_ctx->hHal || !ap_adapter) + return; + sme_ScanFlushResult(hdd_ctx->hHal, ap_adapter->sessionId); +} +#endif + +#ifdef QCA_HT_2040_COEX +/**-------------------------------------------------------------------------- + + \brief notify FW with HT20/HT40 mode + + -------------------------------------------------------------------------*/ +int hdd_wlan_set_ht2040_mode(hdd_adapter_t *pAdapter, v_U16_t staId, + v_MACADDR_t macAddrSTA, int channel_type) +{ + int status; + VOS_STATUS vosStatus; + hdd_context_t *pHddCtx = NULL; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return -1; + } + if (!pHddCtx->hHal) + return -1; + + vosStatus = sme_notify_ht2040_mode(pHddCtx->hHal, staId, macAddrSTA, + pAdapter->sessionId, channel_type); + if (VOS_STATUS_SUCCESS != vosStatus) { + hddLog(LOGE, "Fail to send notification with ht2040 mode\n"); + return -1; + } + + return 0; +} +#endif + + +/**-------------------------------------------------------------------------- + + \brief notify FW with modem power status + + -------------------------------------------------------------------------*/ +int hdd_wlan_notify_modem_power_state(int state) +{ + int status; + VOS_STATUS vosStatus; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!pVosContext) + return -1; + + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return -1; + } + if (!pHddCtx->hHal) + return -1; + + vosStatus = sme_notify_modem_power_state(pHddCtx->hHal, state); + if (VOS_STATUS_SUCCESS != vosStatus) { + hddLog(LOGE, "Fail to send notification with modem power state %d", + state); + return -1; + } + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_post_voss_start_config() - HDD post voss start config helper + + \param - pAdapter - Pointer to the HDD + + \return - None + + --------------------------------------------------------------------------*/ +VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx) +{ + eHalStatus halStatus; + v_U32_t listenInterval; + tANI_U32 ignoreDtim; + + + // Send ready indication to the HDD. This will kick off the MAC + // into a 'running' state and should kick off an initial scan. + halStatus = sme_HDDReadyInd( pHddCtx->hHal ); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status " + "code %08d [x%08x]",__func__, halStatus, halStatus ); + return VOS_STATUS_E_FAILURE; + } + + // Set default LI and ignoreDtim into HDD context, + // otherwise under some race condition, HDD will set 0 LI value into RIVA, + // And RIVA will crash + wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval); + pHddCtx->hdd_actual_LI_value = listenInterval; + wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim); + pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim; + + + return VOS_STATUS_SUCCESS; +} + +/* wake lock APIs for HDD */ +void hdd_prevent_suspend(uint32_t reason) +{ + vos_wake_lock_acquire(&wlan_wake_lock, reason); +} + +void hdd_allow_suspend(uint32_t reason) +{ + vos_wake_lock_release(&wlan_wake_lock, reason); +} + +void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason) +{ + vos_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, + reason); +} + +/**--------------------------------------------------------------------------- + + \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability + information between Host and Riva + + This function gets reported version of FW + It also finds the version of Riva headers used to compile the host + It compares the above two and prints a warning if they are different + It gets the SW and HW version string + Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg + indicating the features they support through a bitmap + + \param - pHddCtx - Pointer to HDD context + + \return - void + + --------------------------------------------------------------------------*/ + +void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx) +{ + + tSirVersionType versionCompiled; + tSirVersionType versionReported; + tSirVersionString versionString; + tANI_U8 fwFeatCapsMsgSupported = 0; + VOS_STATUS vstatus; + + memset(&versionCompiled, 0, sizeof(versionCompiled)); + memset(&versionReported, 0, sizeof(versionReported)); + + /* retrieve and display WCNSS version information */ + do { + + vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal, + &versionCompiled); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: unable to retrieve WCNSS WLAN compiled version", + __func__); + break; + } + + vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal, + &versionReported); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: unable to retrieve WCNSS WLAN reported version", + __func__); + break; + } + + if ((versionCompiled.major != versionReported.major) || + (versionCompiled.minor != versionReported.minor) || + (versionCompiled.version != versionReported.version) || + (versionCompiled.revision != versionReported.revision)) + { + pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, " + "Host expected %u.%u.%u.%u\n", + WLAN_MODULE_NAME, + (int)versionReported.major, + (int)versionReported.minor, + (int)versionReported.version, + (int)versionReported.revision, + (int)versionCompiled.major, + (int)versionCompiled.minor, + (int)versionCompiled.version, + (int)versionCompiled.revision); + } + else + { + pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n", + WLAN_MODULE_NAME, + (int)versionReported.major, + (int)versionReported.minor, + (int)versionReported.version, + (int)versionReported.revision); + } + + vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal, + versionString, + sizeof(versionString)); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: unable to retrieve WCNSS software version string", + __func__); + break; + } + + pr_info("%s: WCNSS software version %s\n", + WLAN_MODULE_NAME, versionString); + + vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal, + versionString, + sizeof(versionString)); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: unable to retrieve WCNSS hardware version string", + __func__); + break; + } + + pr_info("%s: WCNSS hardware version %s\n", + WLAN_MODULE_NAME, versionString); + + /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message + 2.Host-FW capability exchange message is only present on riva 1.1 so + send the message only if it the riva is 1.1 + minor numbers for different riva branches: + 0 -> (1.0)Mainline Build + 1 -> (1.1)Mainline Build + 2->(1.04) Stability Build + */ + if (((versionReported.major>0) || (versionReported.minor>1) || + ((versionReported.minor>=1) && (versionReported.version>=1))) + && ((versionReported.major == 1) && (versionReported.minor >= 1))) + fwFeatCapsMsgSupported = 1; + + if (fwFeatCapsMsgSupported) + { +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(!pHddCtx->cfg_ini->fEnableActiveModeOffload) + sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD); +#endif + /* Indicate if IBSS heartbeat monitoring needs to be offloaded */ + if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload) + { + sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD); + } + + sme_featureCapsExchange(pHddCtx->hHal); + } + + } while (0); + +} + +/* Initialize channel list in sme based on the country code */ +VOS_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx) +{ + return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2, + hdd_ctx->reg.cc_src); +} + +/**--------------------------------------------------------------------------- + + \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz + + \param - pHddCtx - Pointer to the hdd context + + \return - true if hardware supports 5GHz + + --------------------------------------------------------------------------*/ +boolean hdd_is_5g_supported(hdd_context_t * pHddCtx) +{ + /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1); + * then hardware support 5Ghz. + */ + return true; +} + +static VOS_STATUS wlan_hdd_reg_init(hdd_context_t *hdd_ctx) +{ + struct wiphy *wiphy; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + wiphy = hdd_ctx->wiphy; + + /* initialize the NV module. This is required so that + we can initialize the channel information in wiphy + from the NV.bin data. The channel information in + wiphy needs to be initialized before wiphy registration */ + + status = vos_init_wiphy_from_eeprom(); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + /* NV module cannot be initialized */ + hddLog( VOS_TRACE_LEVEL_FATAL, + "%s: vos_init_wiphy failed", __func__); + return status; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) + wiphy->wowlan = &wowlan_support_reg_init; +#else + wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | + WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE | + WIPHY_WOWLAN_RFKILL_RELEASE; + + wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS * + WOW_MAX_FILTERS_PER_LIST); + wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE; + wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE; +#endif + + /* registration of wiphy dev with cfg80211 */ + if (0 > wlan_hdd_cfg80211_register(wiphy)) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__); + status = VOS_STATUS_E_FAILURE; + } + + return status; +} + + +#ifdef MSM_PLATFORM +void hdd_cnss_request_bus_bandwidth(hdd_context_t *pHddCtx, + const uint64_t tx_packets, const uint64_t rx_packets) +{ +#ifdef CONFIG_CNSS + uint64_t total = tx_packets + rx_packets; + uint64_t temp_rx = 0; + uint64_t temp_tx = 0; + enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE; + enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE; + enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE; + + + if (total > pHddCtx->cfg_ini->busBandwidthHighThreshold) + next_vote_level = CNSS_BUS_WIDTH_HIGH; + else if (total > pHddCtx->cfg_ini->busBandwidthMediumThreshold) + next_vote_level = CNSS_BUS_WIDTH_MEDIUM; + else if (total > pHddCtx->cfg_ini->busBandwidthLowThreshold) + next_vote_level = CNSS_BUS_WIDTH_LOW; + else + next_vote_level = CNSS_BUS_WIDTH_NONE; + + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].next_vote_level + = next_vote_level; + + if (pHddCtx->cur_vote_level != next_vote_level) { + hddLog(VOS_TRACE_LEVEL_DEBUG, + "%s: trigger level %d, tx_packets: %lld, rx_packets: %lld", + __func__, next_vote_level, tx_packets, rx_packets); + pHddCtx->cur_vote_level = next_vote_level; + cnss_request_bus_bandwidth(next_vote_level); + + if (next_vote_level <= CNSS_BUS_WIDTH_LOW) { + if (pHddCtx->hbw_requested) { + hdd_remove_pm_qos(); + pHddCtx->hbw_requested = false; + } + if (vos_sched_handle_throughput_req(false)) + hddLog(LOGE, FL("low bandwidth set rx affinity fail")); + } else { + if (!pHddCtx->hbw_requested) { + hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); + pHddCtx->hbw_requested = true; + } + if (vos_sched_handle_throughput_req(true)) + hddLog(LOGE, FL("high bandwidth set rx affinity fail")); + } + } + + /* fine-tuning parameters for RX Flows */ + temp_rx = (rx_packets + pHddCtx->prev_rx) / 2; + pHddCtx->prev_rx = rx_packets; + if (temp_rx > pHddCtx->cfg_ini->tcpDelackThresholdHigh) + next_rx_level = WLAN_SVC_TP_HIGH; + else + next_rx_level = WLAN_SVC_TP_LOW; + + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].next_rx_level + = next_rx_level; + + if (pHddCtx->cur_rx_level != next_rx_level) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG, + "%s: TCP DELACK trigger level %d, average_rx: %llu", + __func__, next_rx_level, temp_rx); + pHddCtx->cur_rx_level = next_rx_level; + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, + &next_rx_level, + sizeof(next_rx_level)); + } + + /* fine-tuning parameters for TX Flows */ + temp_tx = (tx_packets + pHddCtx->prev_tx) / 2; + pHddCtx->prev_tx = tx_packets; + if (temp_tx > pHddCtx->cfg_ini->tcp_tx_high_tput_thres) + next_tx_level = WLAN_SVC_TP_HIGH; + else + next_tx_level = WLAN_SVC_TP_LOW; + + if (pHddCtx->cur_tx_level != next_tx_level) { + hddLog(VOS_TRACE_LEVEL_DEBUG, + "%s: change TCP TX trigger level %d, average_tx: %llu ", + __func__, next_tx_level, temp_tx); + pHddCtx->cur_tx_level = next_tx_level; + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND, + &next_tx_level, + sizeof(next_tx_level)); + } + + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].next_tx_level + = next_tx_level; + + pHddCtx->hdd_txrx_hist_idx++; + pHddCtx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK; + +#endif +} + +#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x))) + +static void hdd_bus_bw_compute_cbk(void *priv) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)priv; + hdd_adapter_t *pAdapter = NULL; + uint64_t tx_packets= 0, rx_packets= 0; + uint64_t total_tx = 0, total_rx = 0; + hdd_adapter_list_node_t *pAdapterNode = NULL; + VOS_STATUS status = 0; + v_BOOL_t connected = FALSE; +#ifdef IPA_UC_OFFLOAD + uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0; + hdd_adapter_t *pValidAdapter = NULL; +#endif /* IPA_UC_OFFLOAD */ + + if (wlan_hdd_validate_context(pHddCtx)) + return; + + for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + NULL != pAdapterNode && VOS_STATUS_SUCCESS == status; + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) + { + + if ((pAdapter = pAdapterNode->pAdapter) == NULL) + continue; + +#ifdef IPA_UC_OFFLOAD + pValidAdapter = pAdapter; +#endif /* IPA_UC_OFFLOAD */ + + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) && + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)->conn_info.connState + != eConnectionState_Associated) { + + continue; + } + + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO) && + WLAN_HDD_GET_AP_CTX_PTR(pAdapter)->bApActive == VOS_FALSE) { + + continue; + } + + tx_packets += HDD_BW_GET_DIFF(pAdapter->stats.tx_packets, + pAdapter->prev_tx_packets); + rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets, + pAdapter->prev_rx_packets); + + total_rx += pAdapter->stats.rx_packets; + total_tx += pAdapter->stats.tx_packets; + + + spin_lock_bh(&pHddCtx->bus_bw_lock); + pAdapter->prev_tx_packets = pAdapter->stats.tx_packets; + pAdapter->prev_rx_packets = pAdapter->stats.rx_packets; + spin_unlock_bh(&pHddCtx->bus_bw_lock); + connected = TRUE; + } + + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].total_rx = total_rx; + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].total_tx = total_tx; + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].interval_rx = rx_packets; + pHddCtx->hdd_txrx_hist[pHddCtx->hdd_txrx_hist_idx].interval_tx = tx_packets; + +#ifdef IPA_UC_OFFLOAD + hdd_ipa_uc_stat_query(pHddCtx, &ipa_tx_packets, &ipa_rx_packets); + tx_packets += (uint64_t)ipa_tx_packets; + rx_packets += (uint64_t)ipa_rx_packets; +#endif /* IPA_UC_OFFLOAD */ + if (!connected) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "bus bandwidth timer running in disconnected state"); + return; + } + + hdd_cnss_request_bus_bandwidth(pHddCtx, tx_packets, rx_packets); + +#ifdef IPA_OFFLOAD + hdd_ipa_set_perf_level(pHddCtx, tx_packets, rx_packets); +#ifdef IPA_UC_OFFLOAD + hdd_ipa_uc_stat_request(pValidAdapter, 2); +#endif /* IPA_UC_OFFLOAD */ +#endif + + vos_timer_start(&pHddCtx->bus_bw_timer, + pHddCtx->cfg_ini->busBandwidthComputeInterval); +} +#endif + +/** + * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats + * @pHddCtx: hdd context + * + * Return: 0 for success + */ +int wlan_hdd_init_tx_rx_histogram(hdd_context_t *pHddCtx) +{ + pHddCtx->hdd_txrx_hist = vos_mem_malloc( + (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM)); + if (pHddCtx->hdd_txrx_hist == NULL) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: Failed malloc for hdd_txrx_hist",__func__); + return -ENOMEM; + } + return 0; +} + +/** + * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats + * @pHddCtx: hdd context + * + * Return: none + */ +void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *pHddCtx) +{ + if (pHddCtx->hdd_txrx_hist) { + vos_mem_free(pHddCtx->hdd_txrx_hist); + pHddCtx->hdd_txrx_hist = NULL; + } +} + +void wlan_hdd_display_tx_rx_histogram(hdd_context_t *pHddCtx) +{ + int i; + +#ifdef MSM_PLATFORM + hddLog(VOS_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d", + pHddCtx->cfg_ini->busBandwidthComputeInterval, + pHddCtx->hdd_txrx_hist_idx); + hddLog(VOS_TRACE_LEVEL_ERROR, "BW High TH: %d BW Med TH: %d BW Low TH: %d", + pHddCtx->cfg_ini->busBandwidthHighThreshold, + pHddCtx->cfg_ini->busBandwidthMediumThreshold, + pHddCtx->cfg_ini->busBandwidthLowThreshold); + hddLog(VOS_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d", + pHddCtx->cfg_ini->tcpDelackThresholdHigh, + pHddCtx->cfg_ini->tcpDelackThresholdLow); +#endif + + hddLog(VOS_TRACE_LEVEL_ERROR, + "index, total_rx, interval_rx, total_tx, interval_tx, next_vote_level, next_rx_level, next_tx_level"); + for (i=0; i < NUM_TX_RX_HISTOGRAM; i++){ + hddLog(VOS_TRACE_LEVEL_ERROR, + "%d: %llu, %llu, %llu, %llu, %d, %d, %d", + i, pHddCtx->hdd_txrx_hist[i].total_rx, + pHddCtx->hdd_txrx_hist[i].interval_rx, + pHddCtx->hdd_txrx_hist[i].total_tx, + pHddCtx->hdd_txrx_hist[i].interval_tx, + pHddCtx->hdd_txrx_hist[i].next_vote_level, + pHddCtx->hdd_txrx_hist[i].next_rx_level, + pHddCtx->hdd_txrx_hist[i].next_tx_level); + } + return; +} + +void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *pHddCtx) +{ + pHddCtx->hdd_txrx_hist_idx = 0; + vos_mem_zero(pHddCtx->hdd_txrx_hist, + (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM)); +} + +/**--------------------------------------------------------------------------- + \brief hdd_11d_scan_done - callback to be executed when 11d scan is + completed to flush out the scan results + + 11d scan is done during driver load and is a passive scan on all + channels supported by the device, 11d scans may find some APs on + frequencies which are forbidden to be used in the regulatory domain + the device is operating in. If these APs are notified to the supplicant + it may try to connect to these APs, thus flush out all the scan results + which are present in SME after 11d scan is done. + + \return - eHalStatus + + --------------------------------------------------------------------------*/ +static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext, + tANI_U8 sessionId, tANI_U32 scanId, + eCsrScanStatus status) +{ + ENTER(); + + sme_ScanFlushResult(halHandle, 0); + + EXIT(); + + return eHAL_STATUS_SUCCESS; +} + +#ifdef QCA_ARP_SPOOFING_WAR +int wlan_check_xxx(struct net_device *dev, int if_idex, void *data) +{ + hddLog(VOS_TRACE_LEVEL_INFO, "Checking for arp spoof packtes\n"); + return 0; +} + +int hdd_filter_cb(tANI_U32 vdev_id, adf_nbuf_t skb, tANI_U32 type) +{ + hdd_adapter_t *pAdapter = NULL; + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + int ret = 0; + + switch (type) { + case RX_INTRA_BSS_FWD: + pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + if(!pVosContext) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); + goto out; + } + + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + goto out; + } + + pAdapter = hdd_get_adapter_by_vdev(pHddCtx, vdev_id); + if (NULL == pAdapter) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vdev_id %d does not exist with host", + __func__, vdev_id); + goto out; + } + + if (*((unsigned short *)(skb->data + HDD_ARP_PACKET_TYPE_OFFSET)) + == htons(ETH_P_ARP)) { + + ret = wlan_check_xxx(pAdapter->dev, pAdapter->dev->ifindex, + skb->data); + } + break; + default: + hddLog(VOS_TRACE_LEVEL_WARN, "Invalid filter type"); + goto out; + } +out: + return ret; +} +#endif +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +/** + * wlan_hdd_bad_peer_txctl() - HDD API to initialize the bad peer + * tx flow control parameters + * @pHddCtx: HDD context which contains INI setting. + * + * Read configuation from INI setting, and then update the setting + * of SME module. + * + * Return: NULL + */ +static void wlan_hdd_bad_peer_txctl(hdd_context_t *p_hdd_ctx) +{ + struct sme_bad_peer_txctl_param bad_peer_txctl; + enum sme_max_bad_peer_thresh_levels level = IEEE80211_B_LEVEL; + + bad_peer_txctl.enabled = + p_hdd_ctx->cfg_ini->bad_peer_txctl_enable; + bad_peer_txctl.period = + p_hdd_ctx->cfg_ini->bad_peer_txctl_prd; + bad_peer_txctl.txq_limit = + p_hdd_ctx->cfg_ini->bad_peer_txctl_txq_lmt; + bad_peer_txctl.tgt_backoff = + p_hdd_ctx->cfg_ini->bad_peer_tgt_backoff; + bad_peer_txctl.tgt_report_prd = + p_hdd_ctx->cfg_ini->bad_peer_tgt_report_prd; + + bad_peer_txctl.thresh[level].cond = + p_hdd_ctx->cfg_ini->bad_peer_cond_ieee80211b; + bad_peer_txctl.thresh[level].delta = + p_hdd_ctx->cfg_ini->bad_peer_delta_ieee80211b; + bad_peer_txctl.thresh[level].percentage = + p_hdd_ctx->cfg_ini->bad_peer_pct_ieee80211b; + bad_peer_txctl.thresh[level].thresh = + p_hdd_ctx->cfg_ini->bad_peer_tput_ieee80211b; + bad_peer_txctl.thresh[level].limit = + p_hdd_ctx->cfg_ini->bad_peer_limit_ieee80211b; + + level++; + bad_peer_txctl.thresh[level].cond = + p_hdd_ctx->cfg_ini->bad_peer_cond_ieee80211ag; + bad_peer_txctl.thresh[level].delta = + p_hdd_ctx->cfg_ini->bad_peer_delta_ieee80211ag; + bad_peer_txctl.thresh[level].percentage = + p_hdd_ctx->cfg_ini->bad_peer_pct_ieee80211ag; + bad_peer_txctl.thresh[level].thresh = + p_hdd_ctx->cfg_ini->bad_peer_tput_ieee80211ag; + bad_peer_txctl.thresh[level].limit = + p_hdd_ctx->cfg_ini->bad_peer_limit_ieee80211ag; + + level++; + bad_peer_txctl.thresh[level].cond = + p_hdd_ctx->cfg_ini->bad_peer_cond_ieee80211n; + bad_peer_txctl.thresh[level].delta = + p_hdd_ctx->cfg_ini->bad_peer_delta_ieee80211n; + bad_peer_txctl.thresh[level].percentage = + p_hdd_ctx->cfg_ini->bad_peer_pct_ieee80211n; + bad_peer_txctl.thresh[level].thresh = + p_hdd_ctx->cfg_ini->bad_peer_tput_ieee80211n; + bad_peer_txctl.thresh[level].limit = + p_hdd_ctx->cfg_ini->bad_peer_limit_ieee80211n; + + level++; + bad_peer_txctl.thresh[level].cond = + p_hdd_ctx->cfg_ini->bad_peer_cond_ieee80211ag; + bad_peer_txctl.thresh[level].delta = + p_hdd_ctx->cfg_ini->bad_peer_delta_ieee80211ac; + bad_peer_txctl.thresh[level].percentage = + p_hdd_ctx->cfg_ini->bad_peer_pct_ieee80211ac; + bad_peer_txctl.thresh[level].thresh = + p_hdd_ctx->cfg_ini->bad_peer_tput_ieee80211ac; + bad_peer_txctl.thresh[level].limit = + p_hdd_ctx->cfg_ini->bad_peer_limit_ieee80211ac; + + if (eHAL_STATUS_SUCCESS != + sme_init_bad_peer_txctl_info(p_hdd_ctx->hHal, bad_peer_txctl)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Error while initializing bad peer Txctl infor", + __func__); + } +} +#else +static inline void wlan_hdd_bad_peer_txctl(hdd_context_t *p_hdd_ctx) +{ + /* no-op */ +} +#endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */ + +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS +/** + * hdd_init_offloaded_packets_ctx() - Initialize offload packets context + * @hdd_ctx: hdd global context + * + * Return: none + */ +static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx) +{ + uint8_t i; + + mutex_init(&hdd_ctx->op_ctx.op_lock); + for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) { + hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID; + hdd_ctx->op_ctx.op_table[i].pattern_id = i; + } +} +#else +static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx) +{ +} +#endif + +/** + * hdd_tsf_init() - Initialize the TSF synchronization interface + * @hdd_ctx: HDD global context + * + * When TSF synchronization via GPIO is supported by the driver and + * has been enabled in the configuration file, this function plumbs + * the GPIO value down to firmware via SME. + * + * Return: None + */ +#ifdef WLAN_FEATURE_TSF +static void hdd_tsf_init(hdd_context_t *hdd_ctx) +{ + eHalStatus hal_status; + + if (hdd_ctx->cfg_ini->tsf_gpio_pin == TSF_GPIO_PIN_INVALID) + return; + + hal_status = sme_set_tsf_gpio(hdd_ctx->hHal, + hdd_ctx->cfg_ini->tsf_gpio_pin); + if (eHAL_STATUS_SUCCESS != hal_status) + hddLog(LOGE, FL("set tsf GPIO failed, status: %d"), + hal_status); +} +#else +static void hdd_tsf_init(hdd_context_t *hdd_ctx) +{ +} +#endif + +/**--------------------------------------------------------------------------- + + \brief hdd_wlan_startup() - HDD init function + + This is the driver startup code executed once a WLAN device has been detected + + \param - dev - Pointer to the underlying device + + \return - 0 for success, < 0 for failure + + --------------------------------------------------------------------------*/ + +int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) +{ + VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; +#ifdef WLAN_OPEN_P2P_INTERFACE + hdd_adapter_t *pP2pAdapter = NULL; +#endif + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext= NULL; + eHalStatus hal_status; + int ret; + int i; + struct wiphy *wiphy; + unsigned long rc; + tSmeThermalParams thermalParam; + tSirTxPowerLimit *hddtxlimit; +#ifdef FEATURE_WLAN_CH_AVOID +#ifdef CONFIG_CNSS + uint16_t unsafe_channel_count; + int unsafeChannelIndex; +#endif +#endif + tANI_U8 rtnl_lock_enable; + tANI_U8 reg_netdev_notifier_done = FALSE; + hdd_adapter_t *dot11_adapter = NULL; +#ifdef QCA_ARP_SPOOFING_WAR + adf_os_device_t adf_ctx; +#endif + + ENTER(); + + if (WLAN_IS_EPPING_ENABLED(con_mode)) { + /* if epping enabled redirect start to epping module */ + ret = epping_wlan_startup(dev, hif_sc); + EXIT(); + return ret; + } + /* + * cfg80211: wiphy allocation + */ + wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ; + + if(wiphy == NULL) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__); + return -EIO; + } + + pHddCtx = wiphy_priv(wiphy); + + //Initialize the adapter context to zeros. + vos_mem_zero(pHddCtx, sizeof( hdd_context_t )); + + pHddCtx->wiphy = wiphy; + pHddCtx->isLoadInProgress = TRUE; + pHddCtx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + vos_set_wakelock_logging(false); + + vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); + + /*Get vos context here bcoz vos_open requires it*/ + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if(pVosContext == NULL) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__); + goto err_free_hdd_context; + } +#ifdef QCA_ARP_SPOOFING_WAR + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, pVosContext); + if (adf_ctx == NULL) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__); + goto err_free_hdd_context; + } + adf_ctx->filter_cb = (void *)hdd_filter_cb; +#endif + + //Save the Global VOSS context in adapter context for future. + pHddCtx->pvosContext = pVosContext; + + //Save the adapter context in global context for future. + ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx; + + pHddCtx->parent_dev = dev; + + init_completion(&pHddCtx->full_pwr_comp_var); + init_completion(&pHddCtx->standby_comp_var); + init_completion(&pHddCtx->req_bmps_comp_var); +#ifdef FEATURE_WLAN_EXTSCAN + init_completion(&pHddCtx->ext_scan_context.response_event); +#endif /* FEATURE_WLAN_EXTSCAN */ + + hdd_init_ll_stats_ctx(pHddCtx); + + spin_lock_init(&pHddCtx->schedScan_lock); + + hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS ); + +#ifdef FEATURE_WLAN_TDLS + /* tdls_lock is initialized before an hdd_open_adapter ( which is + * invoked by other instances also) to protect the concurrent + * access for the Adapters by TDLS module. + */ + mutex_init(&pHddCtx->tdls_lock); +#endif + + status = wlan_hdd_init_tx_rx_histogram(pHddCtx); + if (status != 0) { + goto err_free_hdd_context; + } + + spin_lock_init(&pHddCtx->dfs_lock); + hdd_init_offloaded_packets_ctx(pHddCtx); + // Load all config first as TL config is needed during vos_open + pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL); + if(pHddCtx->cfg_ini == NULL) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__); + goto err_histogram; + } + + vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t )); + + // Read and parse the qcom_cfg.ini file + status = hdd_parse_config_ini( pHddCtx ); + if ( VOS_STATUS_SUCCESS != status ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s", + __func__, WLAN_INI_FILE); + goto err_config; + } + + ((VosContextType*)pVosContext)->pHIFContext = hif_sc; + + /* store target type and target version info in hdd ctx */ + pHddCtx->target_type = ((struct ol_softc *)hif_sc)->target_type; + + pHddCtx->current_intf_count=0; + pHddCtx->max_intf_count = CSR_ROAM_SESSION_MAX; + + /* INI has been read, initialise the configuredMcastBcastFilter with + * INI value as this will serve as the default value + */ + pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; + hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d", + pHddCtx->cfg_ini->mcastBcastFilterSetting); + + if (false == hdd_is_5g_supported(pHddCtx)) + { + //5Ghz is not supported. + if (1 != pHddCtx->cfg_ini->nBandCapability) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__); + pHddCtx->cfg_ini->nBandCapability = 1; + } + } + + /* + * If SNR Monitoring is enabled, FW has to parse all beacons + * for calculating and storing the average SNR, so set Nth beacon + * filter to 1 to enable FW to parse all the beacons + */ + if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring) + { + /* The log level is deliberately set to WARN as overriding + * nthBeaconFilter to 1 will increase power consumption and this + * might just prove helpful to detect the power issue. + */ + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__); + pHddCtx->cfg_ini->nthBeaconFilter = 1; + } + /* + * cfg80211: Initialization ... + */ + if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini)) { + hddLog(LOGE, + "%s: wlan_hdd_cfg80211_init return failure", __func__); + goto err_config; + } + + /* Initialize struct for saving f/w log setting will be used + after ssr */ + pHddCtx->fw_log_settings.enable = pHddCtx->cfg_ini->enablefwlog; + pHddCtx->fw_log_settings.dl_type = 0; + pHddCtx->fw_log_settings.dl_report = 0; + pHddCtx->fw_log_settings.dl_loglevel = 0; + pHddCtx->fw_log_settings.index = 0; + for (i = 0; i < MAX_MOD_LOGLEVEL; i++) { + pHddCtx->fw_log_settings.dl_mod_loglevel[i] = 0; + } + + if (VOS_FTM_MODE != hdd_get_conparam()) { + vos_set_multicast_logging(pHddCtx->cfg_ini->multicast_host_fw_msgs); + + if (wlan_hdd_logging_sock_activate_svc(pHddCtx) < 0) + goto err_config; + + /* + * Update VOS trace levels based upon the code. The multicast log + * log levels of the code need not be set when the logger thread + * is not enabled. + */ + if (vos_is_multicast_logging()) + wlan_logging_set_log_level(); + } + + /* + * Update VOS trace levels based upon the cfg.ini + */ + hdd_vos_trace_enable(VOS_MODULE_ID_TL, + pHddCtx->cfg_ini->vosTraceEnableTL); + hdd_vos_trace_enable(VOS_MODULE_ID_WDI, + pHddCtx->cfg_ini->vosTraceEnableWDI); + hdd_vos_trace_enable(VOS_MODULE_ID_HDD, + pHddCtx->cfg_ini->vosTraceEnableHDD); + hdd_vos_trace_enable(VOS_MODULE_ID_SME, + pHddCtx->cfg_ini->vosTraceEnableSME); + hdd_vos_trace_enable(VOS_MODULE_ID_PE, + pHddCtx->cfg_ini->vosTraceEnablePE); + hdd_vos_trace_enable(VOS_MODULE_ID_PMC, + pHddCtx->cfg_ini->vosTraceEnablePMC); + hdd_vos_trace_enable(VOS_MODULE_ID_WDA, + pHddCtx->cfg_ini->vosTraceEnableWDA); + hdd_vos_trace_enable(VOS_MODULE_ID_SYS, + pHddCtx->cfg_ini->vosTraceEnableSYS); + hdd_vos_trace_enable(VOS_MODULE_ID_VOSS, + pHddCtx->cfg_ini->vosTraceEnableVOSS); + hdd_vos_trace_enable(VOS_MODULE_ID_SAP, + pHddCtx->cfg_ini->vosTraceEnableSAP); + hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP, + pHddCtx->cfg_ini->vosTraceEnableHDDSAP); + hdd_vos_trace_enable(VOS_MODULE_ID_HDD_DATA, + pHddCtx->cfg_ini->vosTraceEnableHDDDATA); + hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SAP_DATA, + pHddCtx->cfg_ini->vosTraceEnableHDDSAPDATA); + hdd_vos_trace_enable(VOS_MODULE_ID_HIF, + pHddCtx->cfg_ini->vosTraceEnableHIF); + hdd_vos_trace_enable(VOS_MODULE_ID_TXRX, + pHddCtx->cfg_ini->vosTraceEnableTXRX); + hdd_vos_trace_enable(VOS_MODULE_ID_HTC, + pHddCtx->cfg_ini->vosTraceEnableHTC); + hdd_vos_trace_enable(VOS_MODULE_ID_ADF, + pHddCtx->cfg_ini->vosTraceEnableADF); + hdd_vos_trace_enable(VOS_MODULE_ID_CFG, + pHddCtx->cfg_ini->vosTraceEnableCFG); + + print_hdd_cfg(pHddCtx); + + if (VOS_FTM_MODE == hdd_get_conparam()) + goto ftm_processing; + + //Open watchdog module + if(pHddCtx->cfg_ini->fIsLogpEnabled) + { + status = vos_watchdog_open(pVosContext, + &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext)); + + if(!VOS_IS_STATUS_SUCCESS( status )) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__); + goto err_wdclose; + } + } + + pHddCtx->isLogpInProgress = FALSE; + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE); + + status = vos_nv_open(); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + /* NV module cannot be initialized */ + hddLog( VOS_TRACE_LEVEL_FATAL, + "%s: vos_nv_open failed", __func__); + goto err_wdclose; + } + + status = vos_open( &pVosContext, 0); + if ( !VOS_IS_STATUS_SUCCESS( status )) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__); + goto err_vos_nv_close; + } + + wlan_hdd_update_wiphy(wiphy, pHddCtx->cfg_ini); + +#if !defined(REMOVE_PKT_LOG) + hif_init_pdev_txrx_handle(hif_sc, + vos_get_context(VOS_MODULE_ID_TXRX, pVosContext)); +#endif + + pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext ); + + if ( NULL == pHddCtx->hHal ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__); + goto err_vosclose; + } + + status = vos_preStart( pHddCtx->pvosContext ); + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__); + goto err_vosclose; + } + + status = wlan_hdd_reg_init(pHddCtx); + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: Failed to init channel list", __func__); + goto err_vosclose; + } + + /* Set 802.11p config + * TODO-OCB: This has been temporarily added here to ensure this paramter + * is set in CSR when we init the channel list. This should be removed + * once the 5.9 GHz channels are added to the regulatory domain. + */ + hdd_set_dot11p_config(pHddCtx); + + if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) + { + pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d", + __func__, enable_dfs_chan_scan); + } + if (0 == enable_11d || 1 == enable_11d) + { + pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d", + __func__, enable_11d); + } + + /* Note that the vos_preStart() sequence triggers the cfg download. + The cfg download must occur before we update the SME config + since the SME config operation must access the cfg database */ + status = hdd_set_sme_config( pHddCtx ); + + if ( VOS_STATUS_SUCCESS != status ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__); + goto err_wiphy_unregister; + } + + ret = process_wma_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS, + pHddCtx->cfg_ini->tx_chain_mask_1ss, + PDEV_CMD); + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", + __func__, ret); + } + + status = hdd_set_sme_chan_list(pHddCtx); + if (status != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: Failed to init channel list", __func__); + goto err_wiphy_unregister; + } + + /* In the integrated architecture we update the configuration from + the INI file and from NV before vOSS has been started so that + the final contents are available to send down to the cCPU */ + + // Apply the cfg.ini to cfg.dat + if (FALSE == hdd_update_config_dat(pHddCtx)) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ ); + goto err_wiphy_unregister; + } + + if ( VOS_STATUS_SUCCESS != hdd_update_mac_config( pHddCtx ) ) + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: can't update mac config, using MAC from ini file", + __func__); + } + + { + eHalStatus halStatus; + /* Set the MAC Address Currently this is used by HAL to + * add self sta. Remove this once self sta is added as + * part of session open. + */ + halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID, + (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0], + sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) ); + + if (!HAL_STATUS_SUCCESS( halStatus )) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. " + "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus ); + goto err_wiphy_unregister; + } + } + +#ifdef IPA_OFFLOAD + if (hdd_ipa_init(pHddCtx) == VOS_STATUS_E_FAILURE) + goto err_wiphy_unregister; +#endif + + /*Start VOSS which starts up the SME/MAC/HAL modules and everything else */ + status = vos_start( pHddCtx->pvosContext ); + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__); +#ifdef IPA_OFFLOAD + goto err_ipa_cleanup; +#else + goto err_wiphy_unregister; +#endif + } + +#ifdef FEATURE_WLAN_CH_AVOID +#ifdef CONFIG_CNSS + cnss_get_wlan_unsafe_channel(pHddCtx->unsafe_channel_list, + &(pHddCtx->unsafe_channel_count), + sizeof(v_U16_t) * NUM_20MHZ_RF_CHANNELS); + + hddLog(LOG1,"%s: num of unsafe channels is %d. ", + __func__, + pHddCtx->unsafe_channel_count); + + unsafe_channel_count = VOS_MIN((uint16_t)pHddCtx->unsafe_channel_count, + (uint16_t)NUM_20MHZ_RF_CHANNELS); + + for (unsafeChannelIndex = 0; + unsafeChannelIndex < unsafe_channel_count; + unsafeChannelIndex++) { + hddLog(LOG1,"%s: channel %d is not safe. ", + __func__, pHddCtx->unsafe_channel_list[unsafeChannelIndex]); + } + + /* Plug in avoid channel notification callback */ + sme_AddChAvoidCallback(pHddCtx->hHal, + hdd_ch_avoid_cb); +#endif +#endif /* FEATURE_WLAN_CH_AVOID */ + + status = hdd_post_voss_start_config( pHddCtx ); + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed", + __func__); + goto err_vosstop; + } + +#ifdef QCA_PKT_PROTO_TRACE + vos_pkt_proto_trace_init(); +#endif /* QCA_PKT_PROTO_TRACE */ + + ftm_processing: + if (VOS_FTM_MODE == hdd_get_conparam()) + { + if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__); + goto err_config; + } +#if defined(QCA_WIFI_FTM) + if (hdd_ftm_start(pHddCtx)) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_ftm_start Failed",__func__); + goto err_free_ftm_open; + } +#endif + + /* registration of wiphy dev with cfg80211 */ + if (0 > wlan_hdd_cfg80211_register(wiphy)) { + hddLog(LOGE, FL("wiphy register failed")); + goto err_free_ftm_open; + } + + vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE); + pHddCtx->isLoadInProgress = FALSE; + + hddLog(LOGE, FL("FTM driver loaded")); + complete(&wlan_start_comp); + return VOS_STATUS_SUCCESS; + } + +#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) + rtnl_lock(); + rtnl_lock_enable = TRUE; +#else + rtnl_lock_enable = FALSE; +#endif + + if (pHddCtx->cfg_ini->dot11p_mode == WLAN_HDD_11P_STANDALONE) { + /* Create only 802.11p interface */ + pAdapter = hdd_open_adapter(pHddCtx, WLAN_HDD_OCB, + "wlanocb%d", wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable); + } else { + pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d", + wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable ); + +#ifdef WLAN_OPEN_P2P_INTERFACE + /* Open P2P device interface */ + if (pAdapter != NULL) { + if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && + !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02)) { + vos_mem_copy(pHddCtx->p2pDeviceAddress.bytes, + pHddCtx->cfg_ini->intfMacAddr[0].bytes, + sizeof(tSirMacAddr)); + + /* Generate the P2P Device Address. This consists of the device's + * primary MAC address with the locally administered bit set. + */ + pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02; + } else { + uint8_t* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx); + if (p2p_dev_addr != NULL) { + vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0], + p2p_dev_addr, VOS_MAC_ADDR_SIZE); + } else { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("Failed to allocate mac_address for p2p_device")); + goto err_close_adapter; + } + } + + pP2pAdapter = hdd_open_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d", + &pHddCtx->p2pDeviceAddress.bytes[0], + rtnl_lock_enable); + + if (NULL == pP2pAdapter) { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("Failed to do hdd_open_adapter for P2P Device Interface")); + goto err_close_adapter; + } + } +#endif /* WLAN_OPEN_P2P_INTERFACE */ + + /* Open 802.11p Interface */ + if (pAdapter != NULL) { + if (pHddCtx->cfg_ini->dot11p_mode == WLAN_HDD_11P_CONCURRENT) { + dot11_adapter = hdd_open_adapter(pHddCtx, WLAN_HDD_OCB, + "wlanocb%d", wlan_hdd_get_intf_addr(pHddCtx), + rtnl_lock_enable); + + if (dot11_adapter == NULL) { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("hdd_open_adapter() failed for 802.11p Interface")); + goto err_close_adapter; + } + } + } + } + + if( pAdapter == NULL ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__); + goto err_close_adapter; + } + + + /* Target hw version/revision would only be retrieved after + firmware download */ + hif_get_hw_info(hif_sc, &pHddCtx->target_hw_version, + &pHddCtx->target_hw_revision); + + /* Get the wlan hw/fw version */ + hdd_wlan_get_version(pAdapter, NULL, NULL); + + /* pass target_fw_version to HIF layer */ + hif_set_fw_info(hif_sc, pHddCtx->target_fw_version); + + if (country_code) + { + eHalStatus ret; + + INIT_COMPLETION(pAdapter->change_country_code); + hdd_checkandupdate_dfssetting(pAdapter, country_code); + + ret = sme_ChangeCountryCode(pHddCtx->hHal, + (void *)(tSmeChangeCountryCallback) + wlan_hdd_change_country_code_callback, + country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE); + if (eHAL_STATUS_SUCCESS == ret) + { + rc = wait_for_completion_timeout( + &pAdapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME while setting country code timed out", __func__); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME Change Country code from module param fail ret=%d", __func__, ret); + ret = -EINVAL; + } + } + + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE)) + { + hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__); + pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0; + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), + pHddCtx->cfg_ini->isRoamOffloadScanEnabled); + } +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + /*SME must send channel update configuration to FW*/ + sme_UpdateChannelConfig(pHddCtx->hHal); +#endif + sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done); + + /* Fwr capabilities received, Set the Dot11 mode */ + sme_SetDefDot11Mode(pHddCtx->hHal); + /* Register with platform driver as client for Suspend/Resume */ + status = hddRegisterPmOps(pHddCtx); + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__); + goto err_close_adapter; + } + + /* Open debugfs interface */ + if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: hdd_debugfs_init failed!", __func__); + } + + /* Register TM level change handler function to the platform */ + status = hddDevTmRegisterNotifyCallback(pHddCtx); + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__); + goto err_unregister_pmops; + } + + /* register for riva power on lock to platform driver */ + if (req_riva_power_on_lock("wlan")) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed", + __func__); + goto err_unregister_pmops; + } +#if !defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) + // register net device notifier for device change notification + ret = register_netdevice_notifier(&hdd_netdev_notifier); + + if(ret < 0) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__); + goto err_free_power_on_lock; + } + reg_netdev_notifier_done = TRUE; +#endif + + //Initialize the nlink service + if(nl_srv_init() != 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__); + goto err_reg_netdev; + } + +#ifdef WLAN_KD_READY_NOTIFIER + pHddCtx->kd_nl_init = 1; +#endif /* WLAN_KD_READY_NOTIFIER */ + + //Initialize the BTC service + if(btc_activate_service(pHddCtx) != 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__); + goto err_nl_srv; + } + +#ifdef FEATURE_OEM_DATA_SUPPORT + //Initialize the OEM service + if (oem_activate_service(pHddCtx) != 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: oem_activate_service failed", __func__); + goto err_nl_srv; + } +#endif + +#ifdef PTT_SOCK_SVC_ENABLE + //Initialize the PTT service + if(ptt_sock_activate_svc(pHddCtx) != 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__); + goto err_nl_srv; + } +#endif + + //Initialize the CNSS-DIAG service + if (cnss_diag_activate_service() < 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: cnss_diag_activate_service failed", __func__); + goto err_nl_srv; + } + + hdd_register_mcast_bcast_filter(pHddCtx); + if (VOS_STA_SAP_MODE != hdd_get_conparam()) + { + /* Action frame registered in one adapter which will + * applicable to all interfaces + */ + wlan_hdd_cfg80211_register_frames(pAdapter); + } + + mutex_init(&pHddCtx->sap_lock); + +#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) + if (rtnl_lock_enable == TRUE) { + rtnl_lock_enable = FALSE; + rtnl_unlock(); + } + /* register net device notifier for device change notification */ + ret = register_netdevice_notifier(&hdd_netdev_notifier); + if (ret < 0) { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed", + __func__); + goto err_nl_srv; + } + reg_netdev_notifier_done = TRUE; +#endif + +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + /* Initialize the wake lcok */ + vos_wake_lock_init(&pHddCtx->rx_wake_lock, + "qcom_rx_wakelock"); +#endif + /* Initialize the wake lcok */ + vos_wake_lock_init(&pHddCtx->sap_wake_lock, + "qcom_sap_wakelock"); + + hdd_hostapd_channel_wakelock_init(pHddCtx); + + // Initialize the restart logic + wlan_hdd_restart_init(pHddCtx); + + if(pHddCtx->cfg_ini->enablePowersaveOffload) + { + hdd_set_idle_ps_config(pHddCtx, TRUE); + } + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + if (pHddCtx->cfg_ini->WlanAutoShutdown != 0) + if (sme_set_auto_shutdown_cb(pHddCtx->hHal, wlan_hdd_auto_shutdown_cb) + != eHAL_STATUS_SUCCESS) + hddLog(LOGE, FL("Auto shutdown feature could not be enabled")); +#endif + +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + status = vos_timer_init(&pHddCtx->skip_acs_scan_timer, VOS_TIMER_TYPE_SW, + hdd_skip_acs_scan_timer_handler, (void *)pHddCtx); + if (!VOS_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("Failed to init ACS Skip timer\n")); +#endif + +#ifdef FEATURE_GREEN_AP + if (!VOS_IS_STATUS_SUCCESS( + hdd_wlan_green_ap_attach(pHddCtx))) { + hddLog(LOGE, FL("Failed to allocate Green-AP resource")); + } +#endif + +#ifdef WLAN_FEATURE_NAN + wlan_hdd_cfg80211_nan_init(pHddCtx); +#endif + + /* Thermal Mitigation */ + thermalParam.smeThermalMgmtEnabled = + pHddCtx->cfg_ini->thermalMitigationEnable; + thermalParam.smeThrottlePeriod = pHddCtx->cfg_ini->throttlePeriod; + + thermalParam.smeThermalLevels[0].smeMinTempThreshold = + pHddCtx->cfg_ini->thermalTempMinLevel0; + thermalParam.smeThermalLevels[0].smeMaxTempThreshold = + pHddCtx->cfg_ini->thermalTempMaxLevel0; + thermalParam.smeThermalLevels[1].smeMinTempThreshold = + pHddCtx->cfg_ini->thermalTempMinLevel1; + thermalParam.smeThermalLevels[1].smeMaxTempThreshold = + pHddCtx->cfg_ini->thermalTempMaxLevel1; + thermalParam.smeThermalLevels[2].smeMinTempThreshold = + pHddCtx->cfg_ini->thermalTempMinLevel2; + thermalParam.smeThermalLevels[2].smeMaxTempThreshold = + pHddCtx->cfg_ini->thermalTempMaxLevel2; + thermalParam.smeThermalLevels[3].smeMinTempThreshold = + pHddCtx->cfg_ini->thermalTempMinLevel3; + thermalParam.smeThermalLevels[3].smeMaxTempThreshold = + pHddCtx->cfg_ini->thermalTempMaxLevel3; + + if (eHAL_STATUS_SUCCESS != sme_InitThermalInfo(pHddCtx->hHal,thermalParam)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Error while initializing thermal information", __func__); + } + + /* Plug in set thermal level callback */ + sme_add_set_thermal_level_callback(pHddCtx->hHal, + (tSmeSetThermalLevelCallback)hdd_set_thermal_level_cb); + + /* Bad peer tx flow control */ + wlan_hdd_bad_peer_txctl(pHddCtx); + + /* SAR power limit */ + hddtxlimit = vos_mem_malloc(sizeof(tSirTxPowerLimit)); + if (!hddtxlimit) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation for TxPowerLimit " + "failed!", __func__); + goto err_nl_srv; + } + hddtxlimit->txPower2g = pHddCtx->cfg_ini->TxPower2g; + hddtxlimit->txPower5g = pHddCtx->cfg_ini->TxPower5g; + + if (eHAL_STATUS_SUCCESS != sme_TxpowerLimit(pHddCtx->hHal,hddtxlimit)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Error setting txlimit in sme", __func__); + } + + hdd_tsf_init(pHddCtx); + +#ifdef MSM_PLATFORM + spin_lock_init(&pHddCtx->bus_bw_lock); + vos_timer_init(&pHddCtx->bus_bw_timer, + VOS_TIMER_TYPE_SW, + hdd_bus_bw_compute_cbk, + (void *)pHddCtx); +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + wlan_hdd_cfg80211_stats_ext_init(pHddCtx); +#endif +#ifdef FEATURE_WLAN_EXTSCAN + sme_ExtScanRegisterCallback(pHddCtx->hHal, + wlan_hdd_cfg80211_extscan_callback); +#endif /* FEATURE_WLAN_EXTSCAN */ + sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached); +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + wlan_hdd_cfg80211_link_layer_stats_init(pHddCtx); +#endif + + wlan_hdd_tsf_init(pHddCtx); + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_all_scan_intf_info(pHddCtx); + wlan_hdd_send_version_pkg(pHddCtx->target_fw_version, + pHddCtx->target_hw_version, + pHddCtx->target_hw_name); +#endif + + if (WLAN_HDD_RX_HANDLE_RPS == pHddCtx->cfg_ini->rxhandle) + hdd_dp_util_send_rps_ind(pHddCtx); + + hal_status = sme_set_lost_link_info_cb(pHddCtx->hHal, + hdd_lost_link_info_cb); + /* print error and not block the startup process */ + if (eHAL_STATUS_SUCCESS != hal_status) + hddLog(LOGE, "%s: set lost link info callback failed", __func__); + + hal_status = sme_set_smps_force_mode_cb(pHddCtx->hHal, + hdd_smps_force_mode_cb); + if (eHAL_STATUS_SUCCESS != hal_status) + hddLog(LOGE, FL("set smps force mode callback failed")); + + /* Initialize the RoC Request queue and work. */ + hdd_list_init((&pHddCtx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY); +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&pHddCtx->rocReqWork, wlan_hdd_roc_request_dequeue); +#else + INIT_DELAYED_WORK(&pHddCtx->rocReqWork, wlan_hdd_roc_request_dequeue); +#endif + + wlan_hdd_dcc_register_for_dcc_stats_event(pHddCtx); + + /* + * Register IPv6 notifier to notify if any change in IP + * So that we can reconfigure the offload parameters + */ + hdd_wlan_register_ip6_notifier(pHddCtx); + + /* + * 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; + ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier); + if (ret) + hddLog(LOGE, FL("Failed to register IPv4 notifier")); + else + hddLog(LOG1, FL("Registered IPv4 notifier")); + + ol_pktlog_init(hif_sc); + hdd_runtime_suspend_init(pHddCtx); + pHddCtx->isLoadInProgress = FALSE; + vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE); + complete(&wlan_start_comp); + goto success; + +err_nl_srv: +#ifdef WLAN_KD_READY_NOTIFIER + cnss_diag_notify_wlan_close(); + nl_srv_exit(pHddCtx->ptt_pid); +#else + nl_srv_exit(); +#endif /* WLAN_KD_READY_NOTIFIER */ + +err_reg_netdev: + if (rtnl_lock_enable == TRUE) { + rtnl_lock_enable = FALSE; + rtnl_unlock(); + } + if (reg_netdev_notifier_done == TRUE) { + unregister_netdevice_notifier(&hdd_netdev_notifier); + reg_netdev_notifier_done = FALSE; + } + +#if !defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) +err_free_power_on_lock: +#endif + free_riva_power_on_lock("wlan"); + +err_unregister_pmops: + hddDevTmUnregisterNotifyCallback(pHddCtx); + hddDeregisterPmOps(pHddCtx); + + hdd_debugfs_exit(pHddCtx); + + + +err_close_adapter: +#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) + if (rtnl_lock_enable == TRUE) { + rtnl_lock_enable = FALSE; + rtnl_unlock(); + } +#endif + hdd_close_all_adapters( pHddCtx ); + +err_vosstop: + vos_stop(pVosContext); + +#ifdef IPA_OFFLOAD +err_ipa_cleanup: + hdd_ipa_cleanup(pHddCtx); +#endif + +err_wiphy_unregister: + wiphy_unregister(wiphy); + +err_vosclose: + status = vos_sched_close( pVosContext ); + if (!VOS_IS_STATUS_SUCCESS(status)) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to close VOSS Scheduler", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) ); + } + vos_close(pVosContext ); + +err_vos_nv_close: + + vos_nv_close(); + +err_wdclose: + if(pHddCtx->cfg_ini->fIsLogpEnabled) + vos_watchdog_close(pVosContext); + +if (VOS_FTM_MODE == hdd_get_conparam()) +{ +#if defined(QCA_WIFI_FTM) +err_free_ftm_open: + wlan_hdd_ftm_close(pHddCtx); +#endif +} + + if (VOS_FTM_MODE != hdd_get_conparam()) + wlan_hdd_logging_sock_deactivate_svc(pHddCtx); + +err_config: + kfree(pHddCtx->cfg_ini); + pHddCtx->cfg_ini= NULL; + +err_histogram: + wlan_hdd_deinit_tx_rx_histogram(pHddCtx); + +err_free_hdd_context: + /* wiphy_free() will free the HDD context so remove global reference */ + if (pVosContext) + ((VosContextType*)(pVosContext))->pHDDContext = NULL; + + wiphy_free(wiphy) ; + //kfree(wdev) ; + VOS_BUG(1); + + if (hdd_is_ssr_required()) + { +#ifdef MSM_PLATFORM +#ifdef CONFIG_CNSS + /* WDI timeout had happened during load, so SSR is needed here */ + subsystem_restart("wcnss"); +#endif +#endif + msleep(5000); + } + hdd_set_ssr_required (VOS_FALSE); + + return -EIO; + +success: + EXIT(); + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_driver_init() - Core Driver Init Function + + This is the driver entry point - called in different time line depending + on whether the driver is statically or dynamically linked + + \param - None + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +static int hdd_driver_init( void) +{ + VOS_STATUS status; + v_CONTEXT_t pVosContext = NULL; + int ret_status = 0; + unsigned long rc; + u_int64_t start; + + start = adf_get_boottime(); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_init_svc(); +#endif + + ENTER(); + +#ifdef TIMER_MANAGER + vos_timer_manager_init(); +#endif + +#ifdef MEMORY_DEBUG + vos_mem_init(); +#endif + + vos_wake_lock_init(&wlan_wake_lock, "wlan"); + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + + /* + * In BMI Phase we are only sending small chunk (256 bytes) of the FW image + * at a time, and wait for the completion interrupt to start the next + * transfer. During this phase, the KRAIT is entering IDLE/StandAlone(SA) + * Power Save(PS). The delay incurred for resuming from IDLE/SA PS is huge + * during driver load. So prevent APPS IDLE/SA PS during driver load for + * reducing interrupt latency. + */ + hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); + + vos_ssr_protect_init(); + + pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + + do { + +#ifndef MODULE + if (WLAN_IS_EPPING_ENABLED(con_mode)) { + ret_status = epping_driver_init(con_mode, &wlan_wake_lock, + WLAN_MODULE_NAME); + if (ret_status < 0) { + hdd_remove_pm_qos(); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + vos_wake_lock_destroy(&wlan_wake_lock); + } + return ret_status; + } +#else + if (WLAN_IS_EPPING_ENABLED(hdd_get_conparam())) { + ret_status = epping_driver_init(hdd_get_conparam(), + &wlan_wake_lock, WLAN_MODULE_NAME); + if (ret_status < 0) { + hdd_remove_pm_qos(); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + vos_wake_lock_destroy(&wlan_wake_lock); + } + return ret_status; + } +#endif + + /* Preopen VOSS so that it is ready to start at least SAL */ + status = vos_preOpen(&pVosContext); + + if (!VOS_IS_STATUS_SUCCESS(status)) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__); + ret_status = -1; + break; + } + +#ifdef HDD_TRACE_RECORD + MTRACE(hddTraceInit()); +#endif + +#ifndef MODULE + /* For statically linked driver, call hdd_set_conparam to update curr_con_mode + */ + hdd_set_conparam((v_UINT_t)con_mode); +#endif + +#define HDD_WLAN_START_WAIT_TIME VOS_WDA_TIMEOUT + 5000 + + init_completion(&wlan_start_comp); + + ret_status = hif_register_driver(); + if (!ret_status) { + rc = wait_for_completion_timeout( + &wlan_start_comp, + msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: timed-out waiting for hif_register_driver", __func__); + ret_status = -1; + } else + ret_status = 0; + } + + hdd_remove_pm_qos(); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + + if (ret_status) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN Driver Initialization failed", + __func__); + hif_unregister_driver(); + vos_preClose( &pVosContext ); + ret_status = -ENODEV; + break; + } else { + memdump_init(); + pr_info("%s: driver loaded in %lld\n", WLAN_MODULE_NAME, + adf_get_boottime() - start); + return 0; + } + + + } while (0); + + if (0 != ret_status) + { +#ifdef TIMER_MANAGER + vos_timer_exit(); +#endif +#ifdef MEMORY_DEBUG + vos_mem_exit(); +#endif + vos_wake_lock_destroy(&wlan_wake_lock); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_deinit_svc(); +#endif + pr_err("%s: driver load failure\n", WLAN_MODULE_NAME); + } + + EXIT(); + + return ret_status; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_module_init() - Init Function + + This is the driver entry point (invoked when module is loaded using insmod) + + \param - None + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +#ifdef MODULE +static int __init hdd_module_init ( void) +{ + return hdd_driver_init(); +} +#else /* #ifdef MODULE */ +static int __init hdd_module_init ( void) +{ + /* Driver initialization is delayed to fwpath_changed_handler */ + return 0; +} +#endif /* #ifdef MODULE */ + +/**--------------------------------------------------------------------------- + + \brief hdd_driver_exit() - Exit function + + This is the driver exit point (invoked when module is unloaded using rmmod + or con_mode was changed by user space) + + \param - None + + \return - None + + --------------------------------------------------------------------------*/ +static void hdd_driver_exit(void) +{ + hdd_context_t *pHddCtx = NULL; + int retry = 0; + v_CONTEXT_t pVosContext = NULL; + + pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR); + + //Get the global vos context + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if(!pVosContext) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); + goto done; + } + + if (WLAN_IS_EPPING_ENABLED(con_mode)) { + epping_driver_exit(pVosContext); + goto done; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + + if(!pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__); + } + else + { + /* + * Check IPA HW pipe shutdown properly or not + * If not, force shut down HW pipe + */ + hdd_ipa_uc_force_pipe_shutdown(pHddCtx); + +#ifdef QCA_PKT_PROTO_TRACE + vos_pkt_proto_trace_close(); +#endif /* QCA_PKT_PROTO_TRACE */ + while(pHddCtx->isLogpInProgress || + vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR in Progress; block rmmod for 1 second!!!", __func__); + msleep(1000); + + if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR never completed, fatal error", __func__); + VOS_BUG(0); + } + } + + rtnl_lock(); + pHddCtx->isUnloadInProgress = TRUE; + vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); + vos_set_unload_in_progress(TRUE); + rtnl_unlock(); + } + + vos_wait_for_work_thread_completion(__func__); + memdump_deinit(); + + hif_unregister_driver(); + + vos_preClose( &pVosContext ); + +#ifdef TIMER_MANAGER + vos_timer_exit(); +#endif +#ifdef MEMORY_DEBUG + vos_mem_exit(); +#endif + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_deinit_svc(); +#endif + +done: + vos_wake_lock_destroy(&wlan_wake_lock); + pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME); +} + +/**--------------------------------------------------------------------------- + + \brief hdd_module_exit() - Exit function + + This is the driver exit point (invoked when module is unloaded using rmmod) + + \param - None + + \return - None + + --------------------------------------------------------------------------*/ +static void __exit hdd_module_exit(void) +{ + hdd_driver_exit(); +} + +#ifdef MODULE +static int fwpath_changed_handler(const char *kmessage, + struct kernel_param *kp) +{ + return param_set_copystring(kmessage, kp); +} + +#if ! defined(QCA_WIFI_FTM) +static int con_mode_handler(const char *kmessage, + struct kernel_param *kp) +{ + return param_set_int(kmessage, kp); +} +#endif +#else /* #ifdef MODULE */ + +/**--------------------------------------------------------------------------- + + \brief fwpath_changed_handler() - Handler Function + + Handle changes to the fwpath parameter + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +static int fwpath_changed_handler(const char *kmessage, + struct kernel_param *kp) +{ + int ret; + + ret = param_set_copystring(kmessage, kp); + if (0 == ret) + ret = kickstart_driver(true); + return ret; +} + +#if ! defined(QCA_WIFI_FTM) +/**--------------------------------------------------------------------------- + + \brief con_mode_handler() - + + Handler function for module param con_mode when it is changed by user space + Dynamically linked - do nothing + Statically linked - exit and init driver, as in rmmod and insmod + + \param - + + \return - + + --------------------------------------------------------------------------*/ +static int con_mode_handler(const char *kmessage, struct kernel_param *kp) +{ + int ret; + + ret = param_set_int(kmessage, kp); + if (0 == ret) + ret = kickstart_driver(true); + return ret; +} +#endif +#endif /* #ifdef MODULE */ + +/**--------------------------------------------------------------------------- + + \brief hdd_get_conparam() - + + This is the driver exit point (invoked when module is unloaded using rmmod) + + \param - None + + \return - tVOS_CON_MODE + + --------------------------------------------------------------------------*/ +tVOS_CON_MODE hdd_get_conparam ( void ) +{ +#ifdef MODULE + return (tVOS_CON_MODE)con_mode; +#else + return (tVOS_CON_MODE)curr_con_mode; +#endif +} +void hdd_set_conparam ( v_UINT_t newParam ) +{ + con_mode = newParam; +#ifndef MODULE + curr_con_mode = con_mode; +#endif +} +/**--------------------------------------------------------------------------- + + \brief hdd_softap_sta_deauth() - function + + This to take counter measure to handle deauth req from HDD + + \param - pAdapter - Pointer to the HDD + + \param - enable - boolean value + + \return - None + + --------------------------------------------------------------------------*/ + +VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, + struct tagCsrDelStaParams *pDelStaParams) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; +#endif + VOS_STATUS vosStatus = VOS_STATUS_E_FAULT; + + ENTER(); + + hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)", + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + + //Ignore request to deauth bcmc station + if (pDelStaParams->peerMacAddr[0] & 0x1) + return vosStatus; + +#ifdef WLAN_FEATURE_MBSSID + vosStatus = WLANSAP_DeauthSta(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), + pDelStaParams); +#else + vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams); +#endif + + EXIT(); + return vosStatus; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_softap_sta_disassoc() - function + + This to take counter measure to handle deauth req from HDD + + \param - pAdapter - Pointer to the HDD + + \param - enable - boolean value + + \return - None + + --------------------------------------------------------------------------*/ + +void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter, + struct tagCsrDelStaParams *pDelStaParams) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; +#endif + + ENTER(); + + hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + + //Ignore request to disassoc bcmc station + if( pDelStaParams->peerMacAddr[0] & 0x1 ) + return; + +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_DisassocSta(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pDelStaParams); +#else + WLANSAP_DisassocSta(pVosContext, pDelStaParams); +#endif +} + +void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; +#endif + + ENTER(); + + hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_SetCounterMeasure(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), (v_BOOL_t)enable); +#else + WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable); +#endif +} + +/**--------------------------------------------------------------------------- + * + * \brief hdd_get__concurrency_mode() - + * + * + * \param - None + * + * \return - CONCURRENCY MODE + * + * --------------------------------------------------------------------------*/ +tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void ) +{ + v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); + hdd_context_t *pHddCtx; + + if (NULL != pVosContext) + { + pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x", __func__, + pHddCtx->concurrency_mode); + return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode; + } + } + + /* we are in an invalid state :( */ + hddLog(LOGE, "%s: Invalid context", __func__); + return VOS_STA; +} + +/* Decides whether to send suspend notification to Riva + * if any adapter is in BMPS; then it is required */ +v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx) +{ + tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal); + hdd_config_t *pConfig = pHddCtx->cfg_ini; + + if (pConfig->fIsBmpsEnabled && (pmcState == BMPS)) + { + return TRUE; + } + return FALSE; +} + +void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode) +{ + switch (mode) { + case VOS_STA_MODE: + case VOS_P2P_CLIENT_MODE: + case VOS_P2P_GO_MODE: + case VOS_STA_SAP_MODE: + pHddCtx->concurrency_mode |= (1 << mode); + pHddCtx->no_of_open_sessions[mode]++; + break; + default: + break; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x " + "Number of open sessions for mode %d = %d"), + pHddCtx->concurrency_mode, mode, + pHddCtx->no_of_open_sessions[mode]); +} + + +void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode) + { + switch (mode) { + case VOS_STA_MODE: + case VOS_P2P_CLIENT_MODE: + case VOS_P2P_GO_MODE: + case VOS_STA_SAP_MODE: + pHddCtx->no_of_open_sessions[mode]--; + if (!(pHddCtx->no_of_open_sessions[mode])) + pHddCtx->concurrency_mode &= (~(1 << mode)); + break; + default: + break; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x " + "Number of open sessions for mode %d = %d"), + pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]); + } + +/**--------------------------------------------------------------------------- + * + * \brief wlan_hdd_incr_active_session() + * + * This function increments the number of active sessions + * maintained per device mode + * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented + * Incase of SAP/P2P GO upon bss start it is incremented + * + * \param pHddCtx - HDD Context + * \param mode - device mode + * + * \return - None + * + * --------------------------------------------------------------------------*/ +void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode) +{ + switch (mode) { + case VOS_STA_MODE: + case VOS_P2P_CLIENT_MODE: + case VOS_P2P_GO_MODE: + case VOS_STA_SAP_MODE: + pHddCtx->no_of_active_sessions[mode]++; + break; + default: + break; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"), + mode, + pHddCtx->no_of_active_sessions[mode]); +} + +/**--------------------------------------------------------------------------- + * + * \brief wlan_hdd_decr_active_session() + * + * This function decrements the number of active sessions + * maintained per device mode + * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented + * Incase of SAP/P2P GO upon bss stop it is decremented + * + * \param pHddCtx - HDD Context + * \param mode - device mode + * + * \return - None + * + * --------------------------------------------------------------------------*/ +void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode) +{ + switch (mode) { + case VOS_STA_MODE: + case VOS_P2P_CLIENT_MODE: + case VOS_P2P_GO_MODE: + case VOS_STA_SAP_MODE: + if (pHddCtx->no_of_active_sessions[mode]) + pHddCtx->no_of_active_sessions[mode]--; + break; + default: + break; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"), + mode, + pHddCtx->no_of_active_sessions[mode]); +} + +/** + * wlan_hdd_get_active_session_count() - get active session + * connection count + * @hdd_ctx: Pointer to hdd context + * + * Return: count of active connections + */ +uint8_t wlan_hdd_get_active_session_count(hdd_context_t *hdd_ctx) +{ + uint8_t i = 0; + uint8_t count = 0; + + for (i = 0; i < VOS_MAX_NO_OF_MODE; i++) { + count += hdd_ctx->no_of_active_sessions[i]; + } + return count; +} + +/** + * wlan_hdd_update_txrx_chain_mask() - updates the TX/RX chain + * mask to FW + * @hdd_ctx: Pointer to hdd context + * @chain_mask : Vlaue of the chain_mask to be updated + * + * Return: 0 for success non-zero for failure + */ +int wlan_hdd_update_txrx_chain_mask(hdd_context_t *hdd_ctx, + uint8_t chain_mask) +{ + int ret; + + if (hdd_ctx->per_band_chainmask_supp == 1) { + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_RX_CHAIN_MASK_2G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(LOGE, FL("Failed to set 2G RX chain mask: %d"), + chain_mask); + return -EFAULT; + } + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_TX_CHAIN_MASK_2G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(LOGE, FL("Failed to set 2G TX chain mask: %d"), + chain_mask); + return -EFAULT; + } + + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_RX_CHAIN_MASK_5G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(LOGE, FL("Failed to set 5G RX chain mask: %d"), + chain_mask); + return -EFAULT; + } + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_TX_CHAIN_MASK_5G, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(LOGE, FL("Failed to set 5G TX chain mask: %d"), + chain_mask); + return -EFAULT; + } + } else { + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_RX_CHAIN_MASK, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(LOGE, FL("Failed to set RX chain mask: %d"), + chain_mask); + return -EFAULT; + } + + ret = process_wma_set_command(0, + WMI_PDEV_PARAM_TX_CHAIN_MASK, + chain_mask, PDEV_CMD); + if (0 != ret) { + hddLog(LOGE, FL("Failed to set TX chain mask: %d"), + chain_mask); + return -EFAULT; + } + } + + hddLog(LOG1, FL("Sucessfully updated the TX/RX chain mask to: %d"), + chain_mask); + return 0; +} + +/**--------------------------------------------------------------------------- + * + * \brief wlan_hdd_framework_restart + * + * This function uses a cfg80211 API to start a framework initiated WLAN + * driver module unload/load. + * + * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT). + * + * + * \param - pHddCtx + * + * \return - VOS_STATUS_SUCCESS: Success + * VOS_STATUS_E_EMPTY: Adapter is Empty + * VOS_STATUS_E_NOMEM: No memory + + * --------------------------------------------------------------------------*/ + +static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + int len = (sizeof (struct ieee80211_mgmt)); + struct ieee80211_mgmt *mgmt = NULL; + + /* Prepare the DEAUTH management frame with reason code */ + mgmt = kzalloc(len, GFP_KERNEL); + if(mgmt == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: memory allocation failed (%d bytes)", __func__, len); + return VOS_STATUS_E_NOMEM; + } + mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK; + + /* Iterate over all adapters/devices */ + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("fail to get adapter: %p %d"), pAdapterNode, status); + goto end; + } + do + { + if(pAdapterNode->pAdapter && + WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic) { + hddLog(LOGP, + "restarting the driver(intf:\'%s\' mode:%s(%d) :try %d)", + pAdapterNode->pAdapter->dev->name, + hdd_device_mode_to_string(pAdapterNode->pAdapter->device_mode), + pAdapterNode->pAdapter->device_mode, + pHddCtx->hdd_restart_retries + 1); + /* + * CFG80211 event to restart the driver + * + * 'cfg80211_send_unprot_deauth' sends a + * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state + * of SME(Linux Kernel) state machine. + * + * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart + * the driver. + * + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) || defined(WITH_BACKPORTS) + cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, + (u_int8_t*)mgmt, len); +#else + cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, + (u_int8_t*)mgmt, len); +#endif + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status)); + + end: + /* Free the allocated management frame */ + kfree(mgmt); + + /* Retry until we unload or reach max count */ + if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT) + vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS); + + return status; + +} +/**--------------------------------------------------------------------------- + * + * \brief wlan_hdd_restart_timer_cb + * + * Restart timer callback. An internal function. + * + * \param - User data: + * + * \return - None + * + * --------------------------------------------------------------------------*/ + +void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback) +{ + hdd_context_t *pHddCtx = usrDataForCallback; + wlan_hdd_framework_restart(pHddCtx); + return; + +} + + +/**--------------------------------------------------------------------------- + * + * \brief wlan_hdd_restart_driver + * + * This function sends an event to supplicant to restart the WLAN driver. + * + * This function is called from vos_wlanRestart. + * + * \param - pHddCtx + * + * \return - VOS_STATUS_SUCCESS: Success + * VOS_STATUS_E_EMPTY: Adapter is Empty + * VOS_STATUS_E_ALREADY: Request already in progress + + * --------------------------------------------------------------------------*/ +VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + + /* A tight check to make sure reentrancy */ + if(atomic_xchg(&pHddCtx->isRestartInProgress, 1)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: WLAN restart is already in progress", __func__); + + return VOS_STATUS_E_ALREADY; + } + /* Send reset FIQ to WCNSS to invoke SSR. */ +#ifdef HAVE_WCNSS_RESET_INTR + wcnss_reset_intr(); +#endif + + return status; +} + +/* + * API to find if there is any STA or P2P-Client is connected + */ +VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx) +{ + return sme_isSta_p2p_clientConnected(pHddCtx->hHal); +} + +#ifdef FEATURE_WLAN_CH_AVOID +/** + * hdd_find_prefd_safe_chnl : Finds safe channel within preferred channel + * @hdd_ctxt: hdd context pointer + * @ap_adapter: hdd hostapd adapter pointer + * + * If auto channel selection enabled: + * Preferred and safe channel should be used + * If no overlapping, preferred channel should be used + * + * Return: + * 1: found preferred safe channel + * 0: could not found preferred safe channel + */ + +static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt, + hdd_adapter_t *ap_adapter) +{ + uint16_t safe_channels[NUM_20MHZ_RF_CHANNELS]; + uint16_t safe_channel_count; + uint16_t unsafe_channel_count; + uint8_t is_unsafe = 1; + uint16_t i; + uint16_t channel_loop; + + if (!hdd_ctxt || !ap_adapter) { + hddLog(LOGE, "%s : Invalid arguments: hdd_ctxt=%p, ap_adapter=%p", + __func__, hdd_ctxt, ap_adapter); + return 0; + } + + safe_channel_count = 0; + unsafe_channel_count = VOS_MIN((uint16_t)hdd_ctxt->unsafe_channel_count, + (uint16_t)NUM_20MHZ_RF_CHANNELS); + + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { + is_unsafe = 0; + for (channel_loop = 0; + channel_loop < unsafe_channel_count; channel_loop++) { + if (rfChannels[i].channelNum == + hdd_ctxt->unsafe_channel_list[channel_loop]) { + is_unsafe = 1; + break; + } + } + if (!is_unsafe) { + safe_channels[safe_channel_count] = rfChannels[i].channelNum; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "safe channel %d", safe_channels[safe_channel_count]); + safe_channel_count++; + } + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "perferred range %d - %d", + ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch, + ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch); + for (i = 0; i < safe_channel_count; i++) { + if ((safe_channels[i] >= + ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) && + (safe_channels[i] <= + ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "safe channel %d is in perferred range", safe_channels[i]); + return 1; + } + } + + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_ch_avoid_cb() - + + Avoid channel notification from FW handler. + FW will send un-safe channel list to avoid over wrapping. + hostapd should not use notified channel + + \param - pAdapter HDD adapter pointer + indParam channel avoid notification parameter + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_ch_avoid_cb +( + void *hdd_context, + void *indi_param +) +{ + hdd_adapter_t *hostapd_adapter = NULL; + hdd_context_t *hdd_ctxt; + tSirChAvoidIndType *ch_avoid_indi; + v_U8_t range_loop; + eRfChannels channel_loop, start_channel_idx = INVALID_RF_CHANNEL, + end_channel_idx = INVALID_RF_CHANNEL; + v_U16_t start_channel; + v_U16_t end_channel; + v_CONTEXT_t vos_context; + static int restart_sap_in_progress = 0; + tHddAvoidFreqList hdd_avoid_freq_list; + tANI_U32 i; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + VOS_STATUS status; + + /* Basic sanity */ + if (!hdd_context || !indi_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s : Invalid arguments", __func__); + return; + } + + hdd_ctxt = (hdd_context_t *)hdd_context; + ch_avoid_indi = (tSirChAvoidIndType *)indi_param; + vos_context = hdd_ctxt->pvosContext; + + /* Make unsafe channel list */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : band count %d", + __func__, ch_avoid_indi->avoid_range_count); + + /* generate vendor specific event */ + vos_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList)); + for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) + { + hdd_avoid_freq_list.avoidFreqRange[i].startFreq = + ch_avoid_indi->avoid_freq_range[i].start_freq; + hdd_avoid_freq_list.avoidFreqRange[i].endFreq = + ch_avoid_indi->avoid_freq_range[i].end_freq; + } + hdd_avoid_freq_list.avoidFreqRangeCount = ch_avoid_indi->avoid_range_count; + + wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list); + + /* clear existing unsafe channel cache */ + hdd_ctxt->unsafe_channel_count = 0; + vos_mem_zero(hdd_ctxt->unsafe_channel_list, + sizeof(hdd_ctxt->unsafe_channel_list)); + + for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count; + range_loop++) { + if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) { + hddLog(LOGW, FL("LTE Coex unsafe channel list full")); + break; + } + + start_channel = ieee80211_frequency_to_channel( + ch_avoid_indi->avoid_freq_range[range_loop].start_freq); + end_channel = ieee80211_frequency_to_channel( + ch_avoid_indi->avoid_freq_range[range_loop].end_freq); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : start %d : %d, end %d : %d", __func__, + ch_avoid_indi->avoid_freq_range[range_loop].start_freq, + start_channel, + ch_avoid_indi->avoid_freq_range[range_loop].end_freq, + end_channel); + + /* do not process frequency bands that are not mapped to predefined + * channels + */ + if (start_channel == 0 || end_channel == 0) + continue; + + for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <= + MAX_20MHZ_RF_CHANNEL; channel_loop++) { + if (rfChannels[channel_loop].targetFreq >= + ch_avoid_indi->avoid_freq_range[range_loop].start_freq) { + start_channel_idx = channel_loop; + break; + } + } + for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <= + MAX_20MHZ_RF_CHANNEL; channel_loop++) { + if (rfChannels[channel_loop].targetFreq >= + ch_avoid_indi->avoid_freq_range[range_loop].end_freq) { + end_channel_idx = channel_loop; + if (rfChannels[channel_loop].targetFreq > + ch_avoid_indi->avoid_freq_range[range_loop].end_freq) + end_channel_idx--; + break; + } + } + + if (start_channel_idx == INVALID_RF_CHANNEL || + end_channel_idx == INVALID_RF_CHANNEL) + continue; + + for (channel_loop = start_channel_idx; channel_loop <= + end_channel_idx; channel_loop++) { + hdd_ctxt->unsafe_channel_list[hdd_ctxt->unsafe_channel_count++] + = rfChannels[channel_loop].channelNum; + if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) { + hddLog(LOGW, FL("LTE Coex unsafe channel list full")); + break; + } + } + } + +#ifdef CONFIG_CNSS + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : number of unsafe channels is %d ", + __func__, hdd_ctxt->unsafe_channel_count); + + if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list, + hdd_ctxt->unsafe_channel_count)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to set unsafe channel", + __func__); + + /* clear existing unsafe channel cache */ + hdd_ctxt->unsafe_channel_count = 0; + vos_mem_zero(hdd_ctxt->unsafe_channel_list, + sizeof(v_U16_t) * NUM_20MHZ_RF_CHANNELS); + + return; + } + + for (channel_loop = 0; + channel_loop < hdd_ctxt->unsafe_channel_count; + channel_loop++) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: channel %d is not safe ", __func__, + hdd_ctxt->unsafe_channel_list[channel_loop]); + } +#endif + + if (0 == hdd_ctxt->unsafe_channel_count) + return; + + status = hdd_get_front_adapter(hdd_ctxt, &adapter_node); + while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { + hostapd_adapter = adapter_node->pAdapter; + + if( hostapd_adapter && (WLAN_HDD_SOFTAP == + hostapd_adapter->device_mode)) { + /* If auto channel select is enabled + * preferred channel is in safe channel, + * re-start softap interface with safe channel. + * no overlap with preferred channel and safe channel + * do not re-start softap interface + * stay current operating channel. + */ + if ((hostapd_adapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode) && + (!hdd_find_prefd_safe_chnl(hdd_ctxt, hostapd_adapter))) + return; + + hddLog(LOG1, FL("Current operation channel %d"), + hostapd_adapter->sessionCtx.ap.operatingChannel); + + hddLog(LOG1, FL("sessionCtx.ap.sapConfig.channel %d"), + hostapd_adapter->sessionCtx.ap.sapConfig.channel); + + for (channel_loop = 0; + channel_loop < hdd_ctxt->unsafe_channel_count; + channel_loop++) { + if (((hdd_ctxt->unsafe_channel_list[channel_loop] == + hostapd_adapter->sessionCtx.ap.operatingChannel)) && + (hostapd_adapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode + == true) + && !restart_sap_in_progress) { + + hddLog(LOG1, FL("Restarting SAP")); + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_LTE_COEX_IND, NULL, 0); + restart_sap_in_progress = 1; + /* current operating channel is un-safe channel, + * restart driver + */ + hdd_hostapd_stop(hostapd_adapter->dev); + return; + } + } + } + status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next); + adapter_node = next; + } + return; +} +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef WLAN_FEATURE_LPSS +int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data, + hdd_adapter_t *pAdapter, + hdd_station_ctx_t *pHddStaCtx, + v_U8_t is_on, + v_U8_t is_connected) +{ + hdd_context_t *pHddCtx = NULL; + tANI_U8 buflen = WLAN_SVC_COUNTRY_CODE_LEN; + + if (!data) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid data pointer", __func__); + return (-1); + } + if (!pAdapter) { + if (is_on) { + /* no active interface */ + data->lpss_support = 0; + data->is_on = is_on; + return 0; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid adapter pointer", __func__); + return (-1); + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (pHddCtx->lpss_support && pHddCtx->cfg_ini->enablelpasssupport) + data->lpss_support = 1; + else + data->lpss_support = 0; + data->numChannels = WLAN_SVC_MAX_NUM_CHAN; + sme_GetCfgValidChannels(pHddCtx->hHal, data->channel_list, + &data->numChannels); + sme_GetCountryCode(pHddCtx->hHal, data->country_code, &buflen); + data->is_on = is_on; + data->vdev_id = pAdapter->sessionId; + data->vdev_mode = pAdapter->device_mode; + if (pHddStaCtx) { + data->is_connected = is_connected; + data->rssi = pAdapter->rssi; + data->freq = vos_chan_to_freq(pHddStaCtx->conn_info.operationChannel); + if (WLAN_SVC_MAX_SSID_LEN >= pHddStaCtx->conn_info.SSID.SSID.length) { + data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length; + memcpy(data->ssid, + pHddStaCtx->conn_info.SSID.SSID.ssId, + pHddStaCtx->conn_info.SSID.SSID.length); + } + if (WLAN_SVC_MAX_BSSID_LEN >= sizeof(pHddStaCtx->conn_info.bssId)) + memcpy(data->bssid, + pHddStaCtx->conn_info.bssId, + sizeof(pHddStaCtx->conn_info.bssId)); + } + return 0; +} + +int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data, + v_U32_t fw_version, + v_U32_t chip_id, + const char *chip_name) +{ + if (!data) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid data pointer", __func__); + return (-1); + } + + data->chip_id = chip_id; + strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN); + if (strncmp(chip_name, "Unknown", 7)) + strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN); + else + strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN); + strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN); + scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d", + (fw_version & 0xf0000000) >> 28, + (fw_version & 0xf000000) >> 24, + (fw_version & 0xf00000) >> 20, + (fw_version & 0x7fff)); + return 0; +} +#endif + +#if defined(FEATURE_WLAN_LFR) && defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) +/**--------------------------------------------------------------------------- + + \brief wlan_hdd_disable_roaming() + + This function loop through each adapter and disable roaming on each STA + device mode except the input adapter. + Note: On the input adapter roaming is not enabled yet hence no need to + disable. + + \param - pAdapter HDD adapter pointer + + \return - None + + --------------------------------------------------------------------------*/ +void wlan_hdd_disable_roaming(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_adapter_t *pAdapterIdx = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + VOS_STATUS status; + + if (pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled && + pHddCtx->cfg_ini->isRoamOffloadScanEnabled && + WLAN_HDD_INFRA_STATION == pAdapter->device_mode && + vos_is_sta_active_connection_exists()) { + hddLog(LOG1, FL("Connect received on STA sessionId(%d)"), + pAdapter->sessionId); + /* Loop through adapter and disable roaming for each STA device mode + except the input adapter. */ + + status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pAdapterIdx = pAdapterNode->pAdapter; + + if (WLAN_HDD_INFRA_STATION == pAdapterIdx->device_mode && + pAdapter->sessionId != pAdapterIdx->sessionId) { + hddLog(LOG1, FL("Disable Roaming on sessionId(%d)"), + pAdapterIdx->sessionId); + sme_stopRoaming(WLAN_HDD_GET_HAL_CTX(pAdapterIdx), + pAdapterIdx->sessionId, 0); + } + + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + } +} + +/**--------------------------------------------------------------------------- + + \brief wlan_hdd_enable_roaming() + + This function loop through each adapter and enable roaming on each STA + device mode except the input adapter. + Note: On the input adapter no need to enable roaming because link got + disconnected on this. + + \param - pAdapter HDD adapter pointer + + \return - None + + --------------------------------------------------------------------------*/ +void wlan_hdd_enable_roaming(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_adapter_t *pAdapterIdx = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + VOS_STATUS status; + + if (pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled && + pHddCtx->cfg_ini->isRoamOffloadScanEnabled && + WLAN_HDD_INFRA_STATION == pAdapter->device_mode && + vos_is_sta_active_connection_exists()) { + hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"), + pAdapter->sessionId); + /* Loop through adapter and enable roaming for each STA device mode + except the input adapter. */ + + status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pAdapterIdx = pAdapterNode->pAdapter; + + if (WLAN_HDD_INFRA_STATION == pAdapterIdx->device_mode && + pAdapter->sessionId != pAdapterIdx->sessionId) { + hddLog(LOG1, FL("Enabling Roaming on sessionId(%d)"), + pAdapterIdx->sessionId); + sme_startRoaming(WLAN_HDD_GET_HAL_CTX(pAdapterIdx), + pAdapterIdx->sessionId, + REASON_CONNECT); + } + + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + } +} +#endif + + +void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *ani_hdr; + void *nl_data = NULL; + int flags = GFP_KERNEL; + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + + skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags); + + if(skb == NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_SVC; + + ani_hdr = NLMSG_DATA(nlh); + ani_hdr->type = type; + + switch(type) { + case WLAN_SVC_FW_CRASHED_IND: + case WLAN_SVC_LTE_COEX_IND: +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND: +#endif + ani_hdr->length = 0; + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr))); + skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr))); + break; + case WLAN_SVC_WLAN_STATUS_IND: + case WLAN_SVC_WLAN_VERSION_IND: + case WLAN_SVC_DFS_CAC_START_IND: + case WLAN_SVC_DFS_CAC_END_IND: + case WLAN_SVC_DFS_RADAR_DETECT_IND: + case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND: + case WLAN_SVC_WLAN_TP_IND: + case WLAN_SVC_WLAN_TP_TX_IND: + case WLAN_SVC_RPS_ENABLE_IND: + ani_hdr->length = len; + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len)); + nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr); + memcpy(nl_data, data, len); + skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len)); + break; + + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WLAN SVC: Attempt to send unknown nlink message %d", type); + kfree_skb(skb); + return; + } + + nl_srv_bcast(skb); + + return; +} + +#ifdef WLAN_FEATURE_LPSS +void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter, + hdd_station_ctx_t *pHddStaCtx, + v_U8_t is_on, + v_U8_t is_connected) +{ + int ret = 0; + struct wlan_status_data data; + + if (VOS_FTM_MODE == hdd_get_conparam()) + return; + + memset(&data, 0, sizeof(struct wlan_status_data)); + if (is_on) + ret = wlan_hdd_gen_wlan_status_pack(&data, pAdapter, pHddStaCtx, + is_on, is_connected); + if (!ret) + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND, + &data, sizeof(struct wlan_status_data)); +} + +void wlan_hdd_send_version_pkg(v_U32_t fw_version, + v_U32_t chip_id, + const char *chip_name) +{ + int ret = 0; + struct wlan_version_data data; + + if (VOS_FTM_MODE == hdd_get_conparam()) + return; + + memset(&data, 0, sizeof(struct wlan_version_data)); + ret = wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id, chip_name); + if (!ret) + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND, + &data, sizeof(struct wlan_version_data)); +} + +void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx) +{ + hdd_adapter_t *pDataAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + v_BOOL_t scan_intf_found = VOS_FALSE; + VOS_STATUS status; + + if (!pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer for pHddCtx", + __func__); + return; + } + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { + pDataAdapter = pAdapterNode->pAdapter; + if (pDataAdapter) { + if (pDataAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pDataAdapter->device_mode == WLAN_HDD_P2P_CLIENT || + pDataAdapter->device_mode == WLAN_HDD_P2P_DEVICE) { + scan_intf_found = VOS_TRUE; + wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0); + } + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + if (!scan_intf_found) + wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0); +} +#endif + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +v_VOID_t wlan_hdd_auto_shutdown_cb(v_VOID_t) +{ + hddLog(LOGE, FL("%s: Wlan Idle. Sending Shutdown event.."),__func__); + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0); +} + +void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, v_BOOL_t enable) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + v_BOOL_t ap_connected = VOS_FALSE, sta_connected = VOS_FALSE; + tHalHandle hHal; + + hHal = hdd_ctx->hHal; + if (hHal == NULL) + return; + + if (hdd_ctx->cfg_ini->WlanAutoShutdown == 0) + return; + + if (enable == VOS_FALSE) { + if (sme_set_auto_shutdown_timer(hHal, 0) != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Failed to stop wlan auto shutdown timer")); + } + return; + } + + /* To enable shutdown timer check concurrency */ + if (vos_concurrent_open_sessions_running()) { + status = hdd_get_front_adapter ( hdd_ctx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { + pAdapter = pAdapterNode->pAdapter; + if (pAdapter && pAdapter->device_mode == WLAN_HDD_INFRA_STATION) { + if (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)->conn_info.connState + == eConnectionState_Associated) { + sta_connected = VOS_TRUE; + break; + } + } + if (pAdapter && pAdapter->device_mode == WLAN_HDD_SOFTAP) { + if(WLAN_HDD_GET_AP_CTX_PTR(pAdapter)->bApActive == VOS_TRUE) { + ap_connected = VOS_TRUE; + break; + } + } + status = hdd_get_next_adapter ( hdd_ctx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + } + + if (ap_connected == VOS_TRUE || sta_connected == VOS_TRUE) { + hddLog(LOG1, FL("CC Session active. Shutdown timer not enabled")); + return; + } else { + if (sme_set_auto_shutdown_timer(hHal, + hdd_ctx->cfg_ini->WlanAutoShutdown) + != eHAL_STATUS_SUCCESS) + hddLog(LOGE, FL("Failed to start wlan auto shutdown timer")); + else + hddLog(LOG1, FL("Auto Shutdown timer for %d seconds enabled"), + hdd_ctx->cfg_ini->WlanAutoShutdown); + + } +} +#endif + +hdd_adapter_t * hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter, + bool check_start_bss) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(this_sap_adapter); + hdd_adapter_t *pAdapter, *con_sap_adapter; + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + + con_sap_adapter = NULL; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { + pAdapter = pAdapterNode->pAdapter; + if (pAdapter && ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) && + pAdapter != this_sap_adapter) { + if (check_start_bss) { + if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) { + con_sap_adapter = pAdapter; + break; + } + } else { + con_sap_adapter = pAdapter; + break; + } + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + return con_sap_adapter; +} + +#ifdef MSM_PLATFORM +void hdd_start_bus_bw_compute_timer(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->bus_bw_timer)) + return; + + vos_timer_start(&pHddCtx->bus_bw_timer, + pHddCtx->cfg_ini->busBandwidthComputeInterval); +} + +void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *pAdapter) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + v_BOOL_t can_stop = VOS_TRUE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->bus_bw_timer)) { + /* trying to stop timer, when not running is not good */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "bus band width compute timer is not running"); + return; + } + + if (vos_concurrent_open_sessions_running()) { + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { + pAdapter = pAdapterNode->pAdapter; + if (pAdapter && (pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) && + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)->conn_info.connState + == eConnectionState_Associated) { + can_stop = VOS_FALSE; + break; + } + if (pAdapter && (pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO) && + WLAN_HDD_GET_AP_CTX_PTR(pAdapter)->bApActive == VOS_TRUE) { + can_stop = VOS_FALSE; + break; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + } + + if(can_stop == VOS_TRUE) + vos_timer_stop(&pHddCtx->bus_bw_timer); +} +#endif + + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +void wlan_hdd_check_sta_ap_concurrent_ch_intf(void *data) +{ + hdd_adapter_t *ap_adapter = NULL, *sta_adapter = (hdd_adapter_t *)data; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(sta_adapter); + tHalHandle hHal; + hdd_ap_ctx_t *pHddApCtx; + uint16_t intf_ch = 0, vht_channel_width = 0; + + if ((pHddCtx->cfg_ini->WlanMccToSccSwitchMode == VOS_MCC_TO_SCC_SWITCH_DISABLE) + || !(vos_concurrent_open_sessions_running() + || !(vos_get_concurrency_mode() == VOS_STA_SAP))) + return; + + ap_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP); + if (ap_adapter == NULL) + return; + + if (!test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) + return; + + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + hHal = WLAN_HDD_GET_HAL_CTX(ap_adapter); + + if (hHal == NULL) + return; + +#ifdef WLAN_FEATURE_MBSSID + intf_ch = WLANSAP_CheckCCIntf(pHddApCtx->sapContext); + vht_channel_width = wlan_sap_get_vht_ch_width(pHddApCtx->sapContext); +#else + intf_ch = WLANSAP_CheckCCIntf(pHddCtx->pvosContext); + vht_channel_width = wlan_sap_get_vht_ch_width(pHddApCtx->pvosContext); +#endif + if (intf_ch == 0) + return; + + pHddApCtx->sapConfig.channel = intf_ch; + sme_SelectCBMode(hHal, + pHddApCtx->sapConfig.SapHw_mode, + pHddApCtx->sapConfig.channel, + pHddApCtx->sapConfig.sec_ch, + &vht_channel_width, pHddApCtx->sapConfig.ch_width_orig); +#ifdef WLAN_FEATURE_MBSSID + wlan_sap_set_vht_ch_width(pHddApCtx->sapContext, vht_channel_width); +#else + wlan_sap_set_vht_ch_width(pHddApCtx->pvosContext, vht_channel_width); +#endif + wlan_hdd_restart_sap(ap_adapter); +} +#endif + +/** + * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's + * and sta's operating channel. + * @sta_adapter: Describe the first argument to foobar. + * @ap_adapter: Describe the second argument to foobar. + * @roam_profile: Roam profile of AP to which STA wants to connect. + * @concurrent_chnl_same: If both SAP and STA channels are same then + * set this flag to true else false. + * + * This function checks the sap's operating channel and sta's operating channel. + * if both are same then it will return false else it will restart the sap in + * sta's channel and return true. + * + * + * Return: VOS_STATUS_SUCCESS or VOS_STATUS_E_FAILURE. + */ +VOS_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter, + hdd_adapter_t *ap_adapter, + tCsrRoamProfile *roam_profile, + tScanResultHandle *scan_cache, + bool *concurrent_chnl_same) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + uint8_t channel_id; + VOS_STATUS status; + device_mode_t device_mode = ap_adapter->device_mode; + *concurrent_chnl_same = true; + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + status = + sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter), + roam_profile, + scan_cache, + &channel_id); + if ((VOS_STATUS_SUCCESS == status)) { + if ((WLAN_HDD_SOFTAP == device_mode) && + (channel_id < SIR_11A_CHANNEL_BEGIN)) { + if (hdd_ap_ctx->operatingChannel != channel_id) { + *concurrent_chnl_same = false; + hddLog(VOS_TRACE_LEVEL_INFO_MED, + FL("channels are different")); + } + } else if ((WLAN_HDD_P2P_GO == device_mode) && + (channel_id >= SIR_11A_CHANNEL_BEGIN)) { + if (hdd_ap_ctx->operatingChannel != channel_id) { + *concurrent_chnl_same = false; + hddLog(VOS_TRACE_LEVEL_INFO_MED, + FL("channels are different")); + } + } + } else { + /* + * Lets handle worst case scenario here, Scan cache lookup is failed + * so we have to stop the SAP to avoid any channel discrepancy between + * SAP's channel and STA's channel. Return the status as failure so + * caller function could know that scan look up is failed. + */ + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Finding AP from scan cache failed")); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_MBSSID +/** + * wlan_hdd_stop_sap() - This function stops bss of SAP. + * @ap_adapter: SAP adapter + * + * This function will process the stopping of sap adapter. + * + * Return: void. + */ +void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + VOS_STATUS vos_status; + hdd_context_t *hdd_ctx; +#ifdef CFG80211_DEL_STA_V2 + struct station_del_parameters delStaParams; +#endif + + if (NULL == ap_adapter) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("ap_adapter is NULL here")); + return; + } + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); + if (0 != wlan_hdd_validate_context(hdd_ctx)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return; + } + mutex_lock(&hdd_ctx->sap_lock); + if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { +#ifdef CFG80211_DEL_STA_V2 + delStaParams.mac = NULL; + delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4; + delStaParams.reason_code = eCsrForcedDeauthSta; + wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev, + &delStaParams); +#else + wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev, + NULL); +#endif + hdd_cleanup_actionframe(hdd_ctx, ap_adapter); + hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Now doing SAP STOPBSS")); + if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(hdd_ap_ctx->sapContext)) { + vos_status = vos_wait_single_event(&hostapd_state->stop_bss_event, + 10000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + mutex_unlock(&hdd_ctx->sap_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("SAP Stop Failed")); + return; + } + } + clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + wlan_hdd_decr_active_session(hdd_ctx, ap_adapter->device_mode); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP Stop Success")); + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Can't stop ap because its not started")); + } + mutex_unlock(&hdd_ctx->sap_lock); + return; +} + +/** + * wlan_hdd_start_sap() - This function starts bss of SAP. + * @ap_adapter: SAP adapter + * + * This function will process the starting of sap adapter. + * + * Return: void. + */ +void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + VOS_STATUS vos_status; + hdd_context_t *hdd_ctx; + tsap_Config_t *pConfig; + + if (NULL == ap_adapter) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("ap_adapter is NULL here")); + return; + } + + hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); + pConfig = &ap_adapter->sessionCtx.ap.sapConfig; + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return; + } + mutex_lock(&hdd_ctx->sap_lock); + if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) + goto end; + + if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) { + hddLog(LOGE, FL("SAP Not able to set AP IEs")); + WLANSAP_ResetSapConfigAddIE(pConfig, eUPDATE_IE_ALL); + goto end; + } + + if (WLANSAP_StartBss(hdd_ap_ctx->sapContext, hdd_hostapd_SAPEventCB, + &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev) + != VOS_STATUS_SUCCESS) { + goto end; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Waiting for SAP to start")); + vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("SAP Start failed")); + goto end; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP Start Success")); + set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode); + hostapd_state->bCommit = TRUE; + +end: + mutex_unlock(&hdd_ctx->sap_lock); + return; +} +#endif + +/** + * hdd_wlan_go_set_mcc_p2p_quota() - Function to set quota for P2P GO + * @hostapd_adapter: Pointer to HDD adapter + * @set_value: Qouta value for the interface + * + * This function is used to set the quota for P2P GO cases + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +int32_t hdd_wlan_go_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, + uint32_t set_value) +{ + uint8_t first_adapter_operating_channel = 0; + uint8_t second_adapter_opertaing_channel = 0; + tVOS_CONCURRENCY_MODE concurrent_state = 0; + hdd_adapter_t *staAdapter = NULL; + int32_t ret = 0; /* success */ + + /* + * Check if concurrency mode is active. + * Need to modify this code to support MCC modes other than + * STA/P2P GO + */ + + concurrent_state = hdd_get_concurrency_mode(); + if (concurrent_state == (VOS_STA | VOS_P2P_GO)) { + hddLog(LOG1, "%s: STA & P2P are both enabled", __func__); + + /* + * The channel numbers for both adapters and the time + * quota for the 1st adapter, i.e., one specified in cmd + * are formatted as a bit vector then passed on to WMA + * +************************************************+ + * |bit 31-24 |bit 23-16 | bits 15-8 |bits 7-0 | + * | Unused | Quota for| chan. # for |chan. # for| + * | | 1st chan.| 1st chan. |2nd chan. | + * +************************************************+ + */ + + /* Get the operating channel of the specified vdev */ + first_adapter_operating_channel = + hdd_get_operating_channel(hostapd_adapter->pHddCtx, + hostapd_adapter->device_mode); + + hddLog(LOG1, "%s: 1st channel No.:%d and quota:%dms", + __func__, first_adapter_operating_channel, + set_value); + + /* Move the time quota for first adapter to bits 15-8 */ + set_value = set_value << 8; + /* + * Store the operating channel number of 1st adapter at + * the lower 8-bits of bit vector. + */ + set_value = set_value | first_adapter_operating_channel; + if (hostapd_adapter->device_mode == + WLAN_HDD_INFRA_STATION) { + /* iwpriv cmd issued on wlan0; get p2p0 vdev chan */ + if ((concurrent_state & VOS_P2P_CLIENT) != 0) { + /* The 2nd MCC vdev is P2P client */ + staAdapter = hdd_get_adapter + ( + hostapd_adapter->pHddCtx, + WLAN_HDD_P2P_CLIENT + ); + } else { + /* The 2nd MCC vdev is P2P GO */ + staAdapter = hdd_get_adapter + ( + hostapd_adapter->pHddCtx, + WLAN_HDD_P2P_GO + ); + } + } else { + /* iwpriv cmd issued on p2p0; get channel for wlan0 */ + staAdapter = hdd_get_adapter + ( + hostapd_adapter->pHddCtx, + WLAN_HDD_INFRA_STATION + ); + } + if (staAdapter != NULL) { + second_adapter_opertaing_channel = + hdd_get_operating_channel + ( + staAdapter->pHddCtx, + staAdapter->device_mode + ); + hddLog(LOG1, "%s: 2nd vdev channel No. is:%d", + __func__, + second_adapter_opertaing_channel); + + if (second_adapter_opertaing_channel == 0 || + first_adapter_operating_channel == 0) { + hddLog(LOGE, "Invalid channel"); + return -EINVAL; + } + + /* + * Move the time quota and operating channel number + * for the first adapter to bits 23-16 & bits 15-8 + * of set_value vector, respectively. + */ + set_value = set_value << 8; + /* + * Store the channel number for 2nd MCC vdev at bits + * 7-0 of set_value vector as per the bit format above. + */ + set_value = set_value | + second_adapter_opertaing_channel; + ret = process_wma_set_command + ( + (int32_t)hostapd_adapter->sessionId, + (int32_t)WMA_VDEV_MCC_SET_TIME_QUOTA, + set_value, + VDEV_CMD + ); + } else { + hddLog(LOGE, "%s: NULL adapter handle. Exit", + __func__); + } + } else { + hddLog(LOG1, "%s: MCC is not active. " + "Exit w/o setting latency", __func__); + } + return ret; +} + +/** + * hdd_wlan_set_mcc_p2p_quota() - Function to set quota for P2P + * @hostapd_adapter: Pointer to HDD adapter + * @set_value: Qouta value for the interface + * + * This function is used to set the quota for P2P cases + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +int32_t hdd_wlan_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapater, + uint32_t set_value) +{ + uint8_t first_adapter_operating_channel = 0; + uint8_t second_adapter_opertaing_channel = 0; + hdd_adapter_t *staAdapter = NULL; + int32_t ret = 0; /* success */ + + tVOS_CONCURRENCY_MODE concurrent_state = hdd_get_concurrency_mode(); + hddLog(LOG1, "iwpriv cmd to set MCC quota with val %dms", + set_value); + /* + * Check if concurrency mode is active. + * Need to modify this code to support MCC modes other than STA/P2P + */ + if ((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) || + (concurrent_state == (VOS_STA | VOS_P2P_GO))) { + hddLog(LOG1, "STA & P2P are both enabled"); + /* + * The channel numbers for both adapters and the time + * quota for the 1st adapter, i.e., one specified in cmd + * are formatted as a bit vector then passed on to WMA + * +***********************************************************+ + * |bit 31-24 | bit 23-16 | bits 15-8 | bits 7-0 | + * | Unused | Quota for | chan. # for | chan. # for | + * | | 1st chan. | 1st chan. | 2nd chan. | + * +***********************************************************+ + */ + /* Get the operating channel of the specified vdev */ + first_adapter_operating_channel = + hdd_get_operating_channel + ( + hostapd_adapater->pHddCtx, + hostapd_adapater->device_mode + ); + hddLog(LOG1, "1st channel No.:%d and quota:%dms", + first_adapter_operating_channel, set_value); + /* Move the time quota for first channel to bits 15-8 */ + set_value = set_value << 8; + /* + * Store the channel number of 1st channel at bits 7-0 + * of the bit vector + */ + set_value = set_value | first_adapter_operating_channel; + /* Find out the 2nd MCC adapter and its operating channel */ + if (hostapd_adapater->device_mode == WLAN_HDD_INFRA_STATION) { + /* + * iwpriv cmd was issued on wlan0; + * get p2p0 vdev channel + */ + if ((concurrent_state & VOS_P2P_CLIENT) != 0) { + /* The 2nd MCC vdev is P2P client */ + staAdapter = hdd_get_adapter( + hostapd_adapater->pHddCtx, + WLAN_HDD_P2P_CLIENT); + } else { + /* The 2nd MCC vdev is P2P GO */ + staAdapter = hdd_get_adapter( + hostapd_adapater->pHddCtx, + WLAN_HDD_P2P_GO); + } + } else { + /* + * iwpriv cmd was issued on p2p0; + * get wlan0 vdev channel + */ + staAdapter = hdd_get_adapter(hostapd_adapater->pHddCtx, + WLAN_HDD_INFRA_STATION); + } + if (staAdapter != NULL) { + second_adapter_opertaing_channel = + hdd_get_operating_channel + ( + staAdapter->pHddCtx, + staAdapter->device_mode + ); + hddLog(LOG1, "2nd vdev channel No. is:%d", + second_adapter_opertaing_channel); + + if (second_adapter_opertaing_channel == 0 || + first_adapter_operating_channel == 0) { + hddLog(LOGE, "Invalid channel"); + return -EINVAL; + } + /* + * Now move the time quota and channel number of the + * 1st adapter to bits 23-16 and bits 15-8 of the bit + * vector, respectively. + */ + set_value = set_value << 8; + /* + * Store the channel number for 2nd MCC vdev at bits + * 7-0 of set_value + */ + set_value = set_value | + second_adapter_opertaing_channel; + ret = process_wma_set_command( + (int32_t)hostapd_adapater->sessionId, + (int32_t)WMA_VDEV_MCC_SET_TIME_QUOTA, + set_value, VDEV_CMD); + } else { + hddLog(LOGE, "NULL adapter handle. Exit"); + } + } else { + hddLog(LOG1, "%s: MCC is not active. Exit w/o setting latency", + __func__); + } + return ret; +} + +/** + * hdd_get_fw_version() - Get FW version + * @hdd_ctx: pointer to HDD context. + * @major_spid: FW version - major spid. + * @minor_spid: FW version - minor spid + * @ssid: FW version - ssid + * @crmid: FW version - crmid + * + * This function is called to get the firmware build version stored + * as part of the HDD context + * + * Return: None + */ + +void hdd_get_fw_version(hdd_context_t *hdd_ctx, + uint32_t *major_spid, uint32_t *minor_spid, + uint32_t *siid, uint32_t *crmid) +{ + *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28; + *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24; + *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20; + *crmid = hdd_ctx->target_fw_version & 0x7fff; +} + +/** + * hdd_is_memdump_supported() - to check if memdump feature support + * + * This function is used to check if memdump feature is supported in + * the host driver + * + * Return: true if supported and false otherwise + */ +bool hdd_is_memdump_supported(void) +{ +#ifdef WLAN_FEATURE_MEMDUMP + return true; +#endif + return false; +} + +#ifdef QCA_CONFIG_SMP +int wlan_hdd_get_cpu() +{ + int cpu_index = get_cpu(); + put_cpu(); + return cpu_index; +} +#endif + +/** + * hdd_get_fwpath() - get framework path + * + * This function is used to get the string written by + * userspace to start the wlan driver + * + * Return: string + */ +const char *hdd_get_fwpath(void) +{ + return fwpath.string; +} + +//Register the module init/exit functions +module_init(hdd_module_init); +module_exit(hdd_module_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Qualcomm Atheros, Inc."); +MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER"); + +#if defined(QCA_WIFI_FTM) +module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#else +module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif + +module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +module_param(enable_dfs_chan_scan, int, + S_IRUSR | S_IRGRP | S_IROTH); + +module_param(enable_11d, int, + S_IRUSR | S_IRGRP | S_IROTH); + +module_param(country_code, charp, + S_IRUSR | S_IRGRP | S_IROTH); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_mdns_offload.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_mdns_offload.c new file mode 100644 index 000000000000..1fc55efa3670 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_mdns_offload.c @@ -0,0 +1,1425 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * wlan_hdd_mdns_offload.c - WLAN Host Device Driver implementation + */ + + +#include "wlan_hdd_main.h" +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_trace.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "sme_Api.h" +#include "wlan_hdd_mdns_offload.h" + +#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 + +/* 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; +}; + +/** + * 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, + tpSirMDNSResponseInfo 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, + tpSirMDNSResponseInfo 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, + tpSirMDNSResponseInfo 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, + tpSirMDNSResponseInfo resp_info) +{ + uint16_t len; + + if (resp_info == NULL) { + hddLog(LOGE, FL("resp_info is NULL!")); + return FALSE; + } + + 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; + } + + /* 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(tpSirMDNSResponseInfo 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, + tpSirMDNSResponseInfo resp_info, + struct hdd_mdns_resp_info *resptype_a) +{ + uint16_t value; + uint32_t len; + + 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); + + 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, + tpSirMDNSResponseInfo 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; + + 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(LOGE, FL("index = %d, len = %d, str = %s"), + num, len, &resptype_content.data[idx]); + } + + 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, + tpSirMDNSResponseInfo 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, + tpSirMDNSResponseInfo 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; + + 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; + } + + 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, + tpSirMDNSResponseInfo 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, + tpSirMDNSResponseInfo 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]; + + 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; + } + + 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, + tpSirMDNSResponseInfo 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; + + 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); + + 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 *pHddCtx = WLAN_HDD_GET_CTX(hostapd_adapter); + tpSirMDNSOffloadInfo mdns_offload_info; + tpSirMDNSFqdnInfo mdns_fqdn_info; + tpSirMDNSResponseInfo mdns_resp_info; + uint32_t fqdn_len, ufqdn_len; + + if (pHddCtx->cfg_ini->enable_mdns_offload != + CFG_MDNS_OFFLOAD_SUPPORT_ENABLE) + return FALSE; + + /* 1. Prepare the MDNS fqdn request to send to SME */ + fqdn_len = strlen(pHddCtx->cfg_ini->mdns_fqdn); + ufqdn_len = strlen(pHddCtx->cfg_ini->mdns_uniquefqdn); + if ((fqdn_len == 0) && (ufqdn_len == 0)) { + hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned!")); + 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->vdev_id = hostapd_adapter->sessionId; + mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL; + mdns_fqdn_info->fqdn_len = fqdn_len; + vos_mem_copy(mdns_fqdn_info->fqdn_data, + pHddCtx->cfg_ini->mdns_fqdn, + mdns_fqdn_info->fqdn_len); + + if (eHAL_STATUS_SUCCESS != + sme_setMDNSFqdn(pHddCtx->hHal, mdns_fqdn_info)) { + hddLog(LOGE, FL("sme_setMDNSFqdn 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->vdev_id = hostapd_adapter->sessionId; + mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE; + mdns_fqdn_info->fqdn_len = ufqdn_len; + vos_mem_copy(mdns_fqdn_info->fqdn_data, + pHddCtx->cfg_ini->mdns_uniquefqdn, + mdns_fqdn_info->fqdn_len); + + if (eHAL_STATUS_SUCCESS != + sme_setMDNSFqdn(pHddCtx->hHal, mdns_fqdn_info)) { + hddLog(LOGE, FL("sme_setMDNSFqdn 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->vdev_id = hostapd_adapter->sessionId; + + if (!wlan_hdd_mdns_pack_response(pHddCtx->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_setMDNSResponse(pHddCtx->hHal, mdns_resp_info)) { + hddLog(LOGE, FL("sme_setMDNSResponse 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->vdev_id = hostapd_adapter->sessionId; + mdns_offload_info->mDNSOffloadEnabled = + pHddCtx->cfg_ini->enable_mdns_offload; + + if (eHAL_STATUS_SUCCESS != + sme_setMDNSOffload(pHddCtx->hHal, mdns_offload_info)) { + hddLog(LOGE, FL("sme_setMDNSOffload 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 */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c new file mode 100644 index 000000000000..6d02cdd82fde --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * DOC : wlan_hdd_memdump.c + * + * WLAN Host Device Driver file for dumping firmware memory + * + */ + +#include +#include +#include "wlan_hdd_memdump.h" +#include "vos_sched.h" +#include +#include +#include +#include /* Necessary because we use the proc fs */ +#include /* for copy_to_user */ + +/** + * hdd_fw_dump_context - hdd firmware memory dump context + * + * @request_id: userspace assigned firmware memory dump request ID + * @response_event: firmware memory dump request wait event + */ +struct hdd_fw_dump_context { + uint32_t request_id; + struct completion response_event; +}; +static struct hdd_fw_dump_context fw_dump_context; + +/** + * memdump_cleanup_timer_cb() - Timer callback function for memory dump cleanup. + * + * @data: Callback data (used to stored HDD context) + * + * Callback function registered for memory dump cleanup VOS timer. + * + * Return: none + */ + +static void memdump_cleanup_timer_cb(void *data) +{ + int status; + hdd_context_t *hdd_ctx = data; + adf_os_dma_addr_t paddr; + adf_os_dma_addr_t dma_ctx; + adf_os_device_t adf_ctx; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return; + } + + if (!hdd_ctx->fw_dump_loc) { + hddLog(LOG1, FL("Memory dump already freed")); + return; + } + + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, hdd_ctx->pvosContext); + if (!adf_ctx) { + hddLog(LOGE, FL("ADF context is NULL")); + return; + } + + paddr = hdd_ctx->dump_loc_paddr; + mutex_lock(&hdd_ctx->memdump_lock); + adf_os_mem_free_consistent(adf_ctx, + FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); + hdd_ctx->fw_dump_loc = NULL; + hdd_ctx->memdump_in_progress = false; + mutex_unlock(&hdd_ctx->memdump_lock); + +} + +/** + * wlan_hdd_cfg80211_fw_mem_dump_cb() - Callback to receive FW memory dump + * @ctx: pointer to HDD context. + * @rsp: pointer to fw dump copy complete response + * + * This is a callback function used to indicate user space about the + * availability for firmware memory dump via vendor event. + * + * Return: None + */ +static void wlan_hdd_cfg80211_fw_mem_dump_cb(void *ctx, + struct fw_dump_rsp *dump_rsp) +{ + hdd_context_t *hdd_ctx = ctx; + struct hdd_fw_dump_context *context; + int status; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return; + } + + spin_lock(&hdd_context_lock); + context = &fw_dump_context; + /* validate the response received */ + if (!dump_rsp->dump_complete || + context->request_id != dump_rsp->request_id) { + spin_unlock(&hdd_context_lock); + hddLog(LOGE, + FL("Error @ request_id: %d response_id: %d status: %d"), + context->request_id, dump_rsp->request_id, + dump_rsp->dump_complete); + return; + } else { + complete(&context->response_event); + } + spin_unlock(&hdd_context_lock); + + return; +} + +/** + * wlan_hdd_send_memdump_rsp - send memory dump response to user space + * @hdd_ctx: Pointer to hdd context + * + * Return: 0 for success; non-zero for failure + */ +static int wlan_hdd_send_memdump_rsp(hdd_context_t *hdd_ctx) +{ + struct sk_buff *skb; + int status; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, + NLMSG_HDRLEN + NLA_HDRLEN + sizeof(uint32_t)); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE, + FW_MEM_DUMP_SIZE)) { + hddLog(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_cmd_reply(skb); + hddLog(LOG1, FL("Memdump event sent successfully to user space")); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * __wlan_hdd_cfg80211_get_fw_mem_dump() - Get FW memory dump + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the NL data. + * @data_len:Length of @data + * + * This is called when wlan driver needs to get the firmware memory dump + * via vendor specific command. + * + * Return: 0 on success, error number otherwise. + */ +static int +__wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int status; + VOS_STATUS sme_status; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct fw_dump_req fw_mem_dump_req; + struct fw_dump_seg_req* seg_req; + uint8_t loop; + adf_os_dma_addr_t paddr; + adf_os_dma_addr_t dma_ctx; + adf_os_device_t adf_ctx; + unsigned long rc; + struct hdd_fw_dump_context *context; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return status; + } + + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, hdd_ctx->pvosContext); + if (!adf_ctx) { + hddLog(LOGE, FL("ADF context is NULL")); + return -EINVAL; + } + + if (hdd_ctx->memdump_in_progress) { + hddLog(LOGE, FL("Already a memdump req in progress.")); + return -EBUSY; + } + + /* + * Allocate memory for fw memory dump. Memory allocated should be + * contiguous. Physical address of the allocated memory is passed + * to the FW for copy + * + * Reuse the memory if available. + */ + mutex_lock(&hdd_ctx->memdump_lock); + if (!hdd_ctx->fw_dump_loc) { + hdd_ctx->fw_dump_loc = adf_os_mem_alloc_consistent( + adf_ctx, FW_MEM_DUMP_SIZE, &paddr, dma_ctx); + if (!hdd_ctx->fw_dump_loc) { + mutex_unlock(&hdd_ctx->memdump_lock); + hddLog(LOGE, FL("adf_os_mem_alloc_consistent failed")); + return -ENOMEM; + } + hdd_ctx->dump_loc_paddr = paddr; + } + mutex_unlock(&hdd_ctx->memdump_lock); + + /* + * Currently request_id and num_seg is assumed to be default(1) + * It is assumed that firmware dump requested is for DRAM section + * only + */ + + fw_mem_dump_req.request_id = FW_MEM_DUMP_REQ_ID; + fw_mem_dump_req.num_seg = FW_MEM_DUMP_NUM_SEG; + + hddLog(LOG1, FL("request_id:%d num_seg:%d"), + fw_mem_dump_req.request_id, fw_mem_dump_req.num_seg); + seg_req = (struct fw_dump_seg_req *) fw_mem_dump_req.segment; + for (loop = 0; loop < fw_mem_dump_req.num_seg; loop++) { + seg_req->seg_id = 1; + seg_req->seg_start_addr_lo = FW_DRAM_LOCATION; + seg_req->seg_start_addr_hi = 0; + seg_req->seg_length = FW_MEM_DUMP_SIZE; + seg_req->dst_addr_lo = hdd_ctx->dump_loc_paddr; + seg_req->dst_addr_hi = 0; + hddLog(LOG1, FL("seg_number:%d"), loop); + hddLog(LOG1, + FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"), + seg_req->seg_id, seg_req->seg_start_addr_lo, + seg_req->seg_start_addr_hi); + hddLog(LOG1, + FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"), + seg_req->seg_length, seg_req->dst_addr_lo, + seg_req->dst_addr_hi); + seg_req++; + } + + /** + * Start the cleanup timer. + * Memory allocated for this request will be freed up + * once the timer expires. Memory dump request is expected to be + * completed by this time. + * + * User space will not be able to access the dump after this time. + * New request should be issued to get the dump again. + */ + vos_timer_start(&hdd_ctx->memdump_cleanup_timer, + MEMDUMP_COMPLETION_TIME_MS); + hdd_ctx->memdump_in_progress = true; + + spin_lock(&hdd_context_lock); + context = &fw_dump_context; + context->request_id = fw_mem_dump_req.request_id; + INIT_COMPLETION(context->response_event); + spin_unlock(&hdd_context_lock); + + sme_status = sme_fw_mem_dump(hdd_ctx->hHal, &fw_mem_dump_req); + if (VOS_STATUS_SUCCESS != sme_status) { + hddLog(LOGE, FL("sme_fw_mem_dump Failed")); + mutex_lock(&hdd_ctx->memdump_lock); + adf_os_mem_free_consistent(adf_ctx, + FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); + hdd_ctx->fw_dump_loc = NULL; + mutex_unlock(&hdd_ctx->memdump_lock); + hdd_ctx->memdump_in_progress = false; + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&hdd_ctx->memdump_cleanup_timer)) { + vos_timer_stop(&hdd_ctx->memdump_cleanup_timer); + } + return -EINVAL; + } + + rc = wait_for_completion_timeout(&context->response_event, + msecs_to_jiffies(MEMDUMP_COMPLETION_TIME_MS)); + if (!rc) { + hddLog(LOGE, FL("Target response timed out for request_id: %d"), + context->request_id); + return -ETIMEDOUT; + } + + status = wlan_hdd_send_memdump_rsp(hdd_ctx); + if (status) + hddLog(LOGE, + FL("Failed to send FW memory dump rsp to user space")); + + return status; +} + +/** + * wlan_hdd_cfg80211_get_fw_mem_dump() - Get FW memory dump + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the NL data. + * @data_len:Length of @data + * + * This is called when wlan driver needs to get the firmware memory dump + * via vendor specific command. + * + * Return: 0 on success, error number otherwise. + */ +int wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_fw_mem_dump(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +#define PROCFS_MEMDUMP_DIR "debug" +#define PROCFS_MEMDUMP_NAME "fwdump" +#define PROCFS_MEMDUMP_PERM 0444 + +static struct proc_dir_entry *proc_file, *proc_dir; + +/** memdump_get_file_data() - get data available in proc file + * + * @file - handle for the proc file. + * + * This function is used to retrieve the data passed while + * creating proc file entry. + * + * Return: void pointer to hdd_context + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) || defined(WITH_BACKPORTS) +static void *memdump_get_file_data(struct file *file) +{ + void *hdd_ctx; + + hdd_ctx = PDE_DATA(file_inode(file)); + return hdd_ctx; +} +#else +static void *memdump_get_file_data(struct file *file) +{ + void *hdd_ctx; + + hdd_ctx = PDE(file->f_path.dentry->d_inode)->data; + return hdd_ctx; +} +#endif + +/** + * memdump_read() - perform read operation in memory dump proc file + * + * @file - handle for the proc file. + * @buf - pointer to user space buffer. + * @count - number of bytes to be read. + * @pos - offset in the from buffer. + * + * This function performs read operation for the memory dump proc file. + * + * Return: number of bytes read on success, error code otherwise. + */ +static ssize_t memdump_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + int status; + hdd_context_t *hdd_ctx; + adf_os_dma_addr_t paddr; + adf_os_dma_addr_t dma_ctx; + adf_os_device_t adf_ctx; + + hdd_ctx = memdump_get_file_data(file); + + hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos); + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, hdd_ctx->pvosContext); + if (!adf_ctx) { + hddLog(LOGE, FL("ADF context is NULL")); + return -EINVAL; + } + + if (!hdd_ctx->memdump_in_progress) { + hddLog(LOGE, FL("Current mem dump request timed out/failed")); + return -EINVAL; + } + + if (*pos < 0) { + hddLog(LOGE, FL("Invalid start offset for memdump read")); + return -EINVAL; + } else if (*pos >= FW_MEM_DUMP_SIZE || !count) { + hddLog(LOGE, FL("No more data to copy")); + return 0; + } else if (count > FW_MEM_DUMP_SIZE - *pos) { + count = FW_MEM_DUMP_SIZE - *pos; + } + + if (!hdd_ctx->fw_dump_loc) { + hddLog(LOGE, FL("Invalid fw mem dump location")); + return -EINVAL; + } + + if (copy_to_user(buf, hdd_ctx->fw_dump_loc + *pos, count)) { + hddLog(LOGE, FL("copy to user space failed")); + return -EFAULT; + } + + /* offset(pos) should be updated here based on the copy done*/ + *pos += count; + + /* Entire FW memory dump copy completed */ + if (*pos >= FW_MEM_DUMP_SIZE) { + paddr = hdd_ctx->dump_loc_paddr; + mutex_lock(&hdd_ctx->memdump_lock); + adf_os_mem_free_consistent(adf_ctx, + FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); + hdd_ctx->fw_dump_loc = NULL; + hdd_ctx->memdump_in_progress = false; + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&hdd_ctx->memdump_cleanup_timer)) { + vos_timer_stop(&hdd_ctx->memdump_cleanup_timer); + } + mutex_unlock(&hdd_ctx->memdump_lock); + } + + return count; +} + +/** + * struct memdump_fops - file operations for memory dump feature + * @read - read function for memory dump operation. + * + * This structure initialize the file operation handle for memory + * dump feature + */ +static const struct file_operations memdump_fops = { + read: memdump_read +}; + +/** + * memdump_procfs_init() - Initialize procfs for memory dump + * + * @vos_ctx - Global vos context. + * + * This function create file under proc file system to be used later for + * processing firmware memory dump + * + * Return: 0 on success, error code otherwise. + */ +static int memdump_procfs_init(void *vos_ctx) +{ + hdd_context_t *hdd_ctx; + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx); + if (!hdd_ctx) { + hddLog(LOGE , FL("Invalid HDD context")); + return -EINVAL; + } + + proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL); + if (proc_dir == NULL) { + remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL); + pr_debug("Error: Could not initialize /proc/%s\n", + PROCFS_MEMDUMP_DIR); + return -ENOMEM; + } + + proc_file = proc_create_data(PROCFS_MEMDUMP_NAME, + PROCFS_MEMDUMP_PERM, proc_dir, + &memdump_fops, hdd_ctx); + if (proc_file == NULL) { + remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir); + pr_debug("Error: Could not initialize /proc/%s\n", + PROCFS_MEMDUMP_NAME); + return -ENOMEM; + } + + pr_debug("/proc/%s/%s created\n", PROCFS_MEMDUMP_DIR, + PROCFS_MEMDUMP_NAME); + return 0; +} + +/** + * memdump_procfs_remove() - Remove file/dir under procfs for memory dump + * + * This function removes file/dir under proc file system that was + * processing firmware memory dump + * + * Return: None + */ +static void memdump_procfs_remove(void) +{ + remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir); + pr_debug("/proc/%s/%s removed\n", PROCFS_MEMDUMP_DIR, + PROCFS_MEMDUMP_NAME); + remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL); + pr_debug("/proc/%s removed\n", PROCFS_MEMDUMP_DIR); +} + +/** + * memdump_init() - Intialization function for memory dump feature + * + * This function creates proc file for memdump feature and registers + * HDD callback function with SME. + * + * Return - 0 on success, error otherwise + */ +int memdump_init(void) +{ + hdd_context_t *hdd_ctx; + void *vos_ctx; + int status = 0; + eHalStatus cb_status; + VOS_STATUS vos_status; + + vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_ctx) { + hddLog(LOGE, FL("Invalid VOS context")); + return -EINVAL; + } + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx); + if (!hdd_ctx) { + hddLog(LOGE , FL("Invalid HDD context")); + return -EINVAL; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Not initializing memdump in FTM mode")); + return -EINVAL; + } + + cb_status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal, + wlan_hdd_cfg80211_fw_mem_dump_cb); + if (eHAL_STATUS_SUCCESS != cb_status) { + hddLog(LOGE , FL("Failed to register the callback")); + return -EINVAL; + } + + status = memdump_procfs_init(vos_ctx); + if (status) { + hddLog(LOGE , FL("Failed to create proc file")); + return status; + } + + init_completion(&fw_dump_context.response_event); + + vos_status = vos_timer_init(&hdd_ctx->memdump_cleanup_timer, + VOS_TIMER_TYPE_SW, memdump_cleanup_timer_cb, + (void *)hdd_ctx); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("Failed to init memdump cleanup timer")); + return -EINVAL; + } + + mutex_init(&hdd_ctx->memdump_lock); + + return 0; +} + +/** + * memdump_deinit() - De initialize memdump feature + * + * This function removes proc file created for memdump feature. + * + * Return: None + */ +void memdump_deinit(void) { + hdd_context_t *hdd_ctx; + void *vos_ctx; + adf_os_dma_addr_t paddr; + adf_os_dma_addr_t dma_ctx; + adf_os_device_t adf_ctx; + VOS_STATUS vos_status; + + vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_ctx) { + hddLog(LOGE, FL("Invalid VOS context")); + return; + } + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx); + if(!hdd_ctx) { + hddLog(LOGE , FL("Invalid HDD context")); + return; + } + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Not deinitializing memdump in FTM mode")); + return; + } + + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, hdd_ctx->pvosContext); + if (!adf_ctx) { + hddLog(LOGE, FL("ADF context is NULL")); + return; + } + + memdump_procfs_remove(); + sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal); + + mutex_lock(&hdd_ctx->memdump_lock); + if (hdd_ctx->fw_dump_loc) { + paddr = hdd_ctx->dump_loc_paddr; + adf_os_mem_free_consistent(adf_ctx, + FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); + hdd_ctx->fw_dump_loc = NULL; + hdd_ctx->memdump_in_progress = false; + } + mutex_unlock(&hdd_ctx->memdump_lock); + + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&hdd_ctx->memdump_cleanup_timer)) { + vos_timer_stop(&hdd_ctx->memdump_cleanup_timer); + } + + vos_status = vos_timer_destroy(&hdd_ctx->memdump_cleanup_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("Failed to deallocate timer")); + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c new file mode 100644 index 000000000000..70d50f77a92f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c @@ -0,0 +1,2163 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * DOC: wma_hdd_ocb.c + * + * WLAN Host Device Driver 802.11p OCB implementation + */ + +#include "vos_sched.h" +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_ocb.h" +#include "wlan_hdd_trace.h" +#include "wlan_tgt_def_config.h" +#include "schApi.h" +#include "wma.h" + +/* Structure definitions for WLAN_SET_DOT11P_CHANNEL_SCHED */ +#define AIFSN_MIN (2) +#define AIFSN_MAX (15) +#define CW_MIN (1) +#define CW_MAX (10) + +/* Maximum time(ms) to wait for OCB operations */ +#define WLAN_WAIT_TIME_OCB_CMD 1500 +#define HDD_OCB_MAGIC 0x489a154f + +/** + * struct hdd_ocb_ctxt - Context for OCB operations + * adapter: the ocb adapter + * completion_evt: the completion event + * status: status of the request + */ +struct hdd_ocb_ctxt { + uint32_t magic; + hdd_adapter_t *adapter; + struct completion completion_evt; + int status; +}; + +/** + * hdd_set_dot11p_config() - Set 802.11p config flag + * @hdd_ctx: HDD Context pointer + * + * TODO-OCB: This has been temporarily added to ensure this paramter + * is set in CSR when we init the channel list. This should be removed + * once the 5.9 GHz channels are added to the regulatory domain. + */ +void hdd_set_dot11p_config(hdd_context_t *hdd_ctx) +{ + sme_set_dot11p_config(hdd_ctx->hHal, + hdd_ctx->cfg_ini->dot11p_mode != + WLAN_HDD_11P_DISABLED); +} + +/** + * dot11p_validate_qos_params() - Check if QoS parameters are valid + * @qos_params: Array of QoS parameters + * + * Return: 0 on success. error code on failure. + */ +static int dot11p_validate_qos_params(struct sir_qos_params qos_params[]) +{ + int i; + + for (i = 0; i < MAX_NUM_AC; i++) { + if ((!qos_params[i].aifsn) && (!qos_params[i].cwmin) + && (!qos_params[i].cwmax)) + continue; + + /* Validate AIFSN */ + if ((qos_params[i].aifsn < AIFSN_MIN) + || (qos_params[i].aifsn > AIFSN_MAX)) { + hddLog(LOGE, FL("Invalid QoS parameter aifsn %d"), + qos_params[i].aifsn); + return -EINVAL; + } + + /* Validate CWMin */ + if ((qos_params[i].cwmin < CW_MIN) + || (qos_params[i].cwmin > CW_MAX)) { + hddLog(LOGE, FL("Invalid QoS parameter cwmin %d"), + qos_params[i].cwmin); + return -EINVAL; + } + + /* Validate CWMax */ + if ((qos_params[i].cwmax < CW_MIN) + || (qos_params[i].cwmax > CW_MAX)) { + hddLog(LOGE, FL("Invalid QoS parameter cwmax %d"), + qos_params[i].cwmax); + return -EINVAL; + } + } + + return 0; +} + +#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS + +#define DOT11P_TX_PWR_MAX 30 +#define DOT11P_TX_ANTENNA_MAX 6 +#define NUM_DOT11P_CHANNELS 10 +/* + * If FEATURE_STATICALLY_ADD_11P_CHANNELS + * is defined, IEEE80211_CHAN_NO_10MHZ, + * and IEEE80211_CHAN_NO_20MHZ won't + * be defined. + */ +#define IEEE80211_CHAN_NO_20MHZ (1<<11) +#define IEEE80211_CHAN_NO_10MHZ (1<<12) + +/** + * struct chan_info - information for the channel + * @center_freq: center frequency + * @max_bandwidth: maximum bandwidth of the channel in MHz + */ +struct chan_info { + uint32_t center_freq; + uint32_t max_bandwidth; +}; + +struct chan_info valid_dot11p_channels[NUM_DOT11P_CHANNELS] = { + {5860, 10}, + {5870, 10}, + {5880, 10}, + {5890, 10}, + {5900, 10}, + {5910, 10}, + {5920, 10}, + {5875, 20}, + {5905, 20}, + {5852, 5} +}; + +/** + * dot11p_validate_channel_static_channels() - validate a DSRC channel + * @center_freq: the channel's center frequency + * @bandwidth: the channel's bandwidth + * @tx_power: transmit power + * @reg_power: (output) the max tx power from the regulatory domain + * @antenna_max: (output) the max antenna gain from the regulatory domain + * + * This function of the function checks the channel parameters against a + * hardcoded list of valid channels based on the FCC rules. + * + * Return: 0 if the channel is valid, error code otherwise. + */ +static int dot11p_validate_channel_static_channels(struct wiphy *wiphy, + uint32_t channel_freq, uint32_t bandwidth, uint32_t tx_power, + uint8_t *reg_power, uint8_t *antenna_max) +{ + int i; + + for (i = 0; i < NUM_DOT11P_CHANNELS; i++) { + if (channel_freq == valid_dot11p_channels[i].center_freq) { + if (reg_power) + *reg_power = DOT11P_TX_PWR_MAX; + if (antenna_max) + *antenna_max = DOT11P_TX_ANTENNA_MAX; + + if (bandwidth == 0) + bandwidth = + valid_dot11p_channels[i].max_bandwidth; + else if (bandwidth > + valid_dot11p_channels[i].max_bandwidth) + return -EINVAL; + + if (bandwidth != 5 && bandwidth != 10 && + bandwidth != 20) + return -EINVAL; + if (tx_power > DOT11P_TX_PWR_MAX) + return -EINVAL; + + return 0; + } + } + + return -EINVAL; +} +#else +/** + * dot11p_validate_channel_static_channels() - validate a DSRC channel + * @center_freq: the channel's center frequency + * @bandwidth: the channel's bandwidth + * @tx_power: transmit power + * @reg_power: (output) the max tx power from the regulatory domain + * @antenna_max: (output) the max antenna gain from the regulatory domain + * + * This function of the function checks the channel parameters against a + * hardcoded list of valid channels based on the FCC rules. + * + * Return: 0 if the channel is valid, error code otherwise. + */ +static int dot11p_validate_channel_static_channels(struct wiphy *wiphy, + uint32_t channel_freq, uint32_t bandwidth, uint32_t tx_power, + uint8_t *reg_power, uint8_t *antenna_max) +{ + return -EINVAL; +} +#endif /* FEATURE_STATICALLY_ADD_11P_CHANNELS */ + +/** + * dot11p_validate_channel() - validates a DSRC channel + * @center_freq: the channel's center frequency + * @bandwidth: the channel's bandwidth + * @tx_power: transmit power + * @reg_power: (output) the max tx power from the regulatory domain + * @antenna_max: (output) the max antenna gain from the regulatory domain + * + * Return: 0 if the channel is valid, error code otherwise. + */ +static int dot11p_validate_channel(struct wiphy *wiphy, + uint32_t channel_freq, uint32_t bandwidth, + uint32_t tx_power, uint8_t *reg_power, + uint8_t *antenna_max) +{ + int band_idx, channel_idx; + struct ieee80211_supported_band *current_band; + struct ieee80211_channel *current_channel; + + for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) { + current_band = wiphy->bands[band_idx]; + if (!current_band) + continue; + + for (channel_idx = 0; channel_idx < current_band->n_channels; + channel_idx++) { + current_channel = ¤t_band->channels[channel_idx]; + + if (channel_freq == current_channel->center_freq) { + if (current_channel->flags & + IEEE80211_CHAN_DISABLED) + return -EINVAL; + + if (reg_power) + *reg_power = + current_channel->max_reg_power; + if (antenna_max) + *antenna_max = + current_channel->max_antenna_gain; + + switch (bandwidth) { + case 0: + if (current_channel->flags & + IEEE80211_CHAN_NO_10MHZ) + bandwidth = 5; + else if (current_channel->flags & + IEEE80211_CHAN_NO_20MHZ) + bandwidth = 10; + else + bandwidth = 20; + break; + case 5: + break; + case 10: + if (current_channel->flags & + IEEE80211_CHAN_NO_10MHZ) + return -EINVAL; + break; + case 20: + if (current_channel->flags & + IEEE80211_CHAN_NO_20MHZ) + return -EINVAL; + break; + default: + return -EINVAL; + } + + if (tx_power > current_channel->max_power) + return -EINVAL; + + return 0; + } + } + } + + return dot11p_validate_channel_static_channels(wiphy, channel_freq, + bandwidth, tx_power, reg_power, antenna_max); +} + +/** + * hdd_ocb_validate_config() - Validates the config data + * @config: configuration to be validated + * + * Return: 0 on success. + */ +static int hdd_ocb_validate_config(hdd_adapter_t *adapter, + struct sir_ocb_config *config) +{ + int i; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + for (i = 0; i < config->channel_count; i++) { + if (dot11p_validate_channel(hdd_ctx->wiphy, + config->channels[i].chan_freq, + config->channels[i].bandwidth, + config->channels[i].max_pwr, + &config->channels[i].reg_pwr, + &config->channels[i].antenna_max)) { + hddLog(LOGE, FL("Invalid channel frequency %d"), + config->channels[i].chan_freq); + return -EINVAL; + } + if (dot11p_validate_qos_params(config->channels[i].qos_params)) + return -EINVAL; + } + + return 0; +} + +/** + * hdd_ocb_register_sta() - Register station with Transport Layer + * @adapter: Pointer to HDD Adapter + * + * This function should be invoked in the OCB Set Schedule callback + * to enable the data path in the TL by calling RegisterSTAClient + * + * Return: 0 on success. -1 on failure. + */ +static int hdd_ocb_register_sta(hdd_adapter_t *adapter) +{ + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + WLAN_STADescType sta_desc = {0}; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + u_int8_t peer_id; + v_MACADDR_t wildcardBSSID = { + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }; + + vos_status = WLANTL_RegisterOCBPeer(hdd_ctx->pvosContext, + adapter->macAddressCurrent.bytes, + &peer_id); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("Error registering OCB Self Peer!")); + return -EINVAL; + } + + hdd_ctx->sta_to_adapter[peer_id] = adapter; + + sta_desc.ucSTAId = peer_id; + /* Fill in MAC addresses */ + vos_copy_macaddr(&sta_desc.vSelfMACAddress, + &adapter->macAddressCurrent); + vos_copy_macaddr(&sta_desc.vSTAMACAddress, &adapter->macAddressCurrent); + vos_copy_macaddr(&sta_desc.vBSSIDforIBSS, &wildcardBSSID); + + sta_desc.wSTAType = WLAN_STA_OCB; + sta_desc.ucQosEnabled = 1; + sta_desc.ucInitState = WLANTL_STA_AUTHENTICATED; + + vos_status = WLANTL_RegisterSTAClient(hdd_ctx->pvosContext, + hdd_rx_packet_cbk, + hdd_tx_complete_cbk, + hdd_tx_fetch_packet_cbk, + &sta_desc, + 0); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("Failed to register STA client. ret=[0x%08X]"), + vos_status); + return -EINVAL; + } + + if (pHddStaCtx->conn_info.staId[0] != 0 && + pHddStaCtx->conn_info.staId[0] != peer_id) { + hddLog(LOGE, FL("The ID for the OCB station has changed.")); + } + + pHddStaCtx->conn_info.staId[0] = peer_id; + vos_copy_macaddr(&pHddStaCtx->conn_info.peerMacAddress[0], + &adapter->macAddressCurrent); + + return 0; +} + +/** + * hdd_ocb_config_new() - Creates a new OCB configuration + * @num_channels: the number of channels + * @num_schedule: the schedule size + * @ndl_chan_list_len: length in bytes of the NDL chan blob + * @ndl_active_state_list_len: length in bytes of the active state blob + * + * Return: A pointer to the OCB configuration struct, NULL on failure. + */ +static struct sir_ocb_config *hdd_ocb_config_new(int num_channels, + int num_schedule, + int ndl_chan_list_len, + int ndl_active_state_list_len) +{ + struct sir_ocb_config *ret = 0; + uint32_t len; + void *cursor; + + if (num_channels > CFG_TGT_NUM_OCB_CHANNELS || + num_schedule > CFG_TGT_NUM_OCB_SCHEDULES) + return NULL; + + len = sizeof(*ret) + + num_channels * sizeof(struct sir_ocb_config_channel) + + num_schedule * sizeof(struct sir_ocb_config_sched) + + ndl_chan_list_len + + ndl_active_state_list_len; + + cursor = vos_mem_malloc(len); + if (!cursor) + goto fail; + + vos_mem_zero(cursor, len); + ret = cursor; + cursor += sizeof(*ret); + + ret->channel_count = num_channels; + ret->channels = cursor; + cursor += num_channels * sizeof(*ret->channels); + + ret->schedule_size = num_schedule; + ret->schedule = cursor; + cursor += num_schedule * sizeof(*ret->schedule); + + ret->dcc_ndl_chan_list = cursor; + cursor += ndl_chan_list_len; + + ret->dcc_ndl_active_state_list = cursor; + cursor += ndl_active_state_list_len; + + return ret; + +fail: + vos_mem_free(ret); + return NULL; +} + +/** + * hdd_ocb_set_config_callback() - OCB set config callback function + * @context_ptr: OCB call context + * @response_ptr: Pointer to response structure + * + * This function is registered as a callback with the lower layers + * and is used to respond with the status of a OCB set config command. + */ +static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr) +{ + struct hdd_ocb_ctxt *context = context_ptr; + struct sir_ocb_set_config_response *resp = response_ptr; + + if (!context) + return; + + if (resp && resp->status) + hddLog(LOGE, FL("Operation failed: %d"), resp->status); + + spin_lock(&hdd_context_lock); + if (context->magic == HDD_OCB_MAGIC) { + hdd_adapter_t *adapter = context->adapter; + if (!resp) { + context->status = -EINVAL; + complete(&context->completion_evt); + spin_unlock(&hdd_context_lock); + return; + } + + context->adapter->ocb_set_config_resp = *resp; + spin_unlock(&hdd_context_lock); + if (!resp->status) { + /* + * OCB set config command successful. + * Open the TX data path + */ + if (!hdd_ocb_register_sta(adapter)) { + netif_carrier_on(adapter->dev); + netif_tx_start_all_queues( + adapter->dev); + } + } + + spin_lock(&hdd_context_lock); + if (context->magic == HDD_OCB_MAGIC) + complete(&context->completion_evt); + spin_unlock(&hdd_context_lock); + } else { + spin_unlock(&hdd_context_lock); + } +} + +/** + * hdd_ocb_set_config_req() - Send an OCB set config request + * @adapter: a pointer to the adapter + * @config: a pointer to the OCB configuration + * + * Return: 0 on success. + */ +static int hdd_ocb_set_config_req(hdd_adapter_t *adapter, + struct sir_ocb_config *config) +{ + int rc; + eHalStatus halStatus; + struct hdd_ocb_ctxt context = {0}; + + if (hdd_ocb_validate_config(adapter, config)) { + hddLog(LOGE, FL("The configuration is invalid")); + return -EINVAL; + } + + init_completion(&context.completion_evt); + context.adapter = adapter; + context.magic = HDD_OCB_MAGIC; + + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(adapter->dev); + netif_carrier_off(adapter->dev); + + /* Call the SME API to set the config */ + halStatus = sme_ocb_set_config( + ((hdd_context_t *)adapter->pHddCtx)->hHal, &context, + hdd_ocb_set_config_callback, config); + if (halStatus != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error calling SME function.")); + /* Convert from eHalStatus to errno */ + return -EINVAL; + } + + /* Wait for the function to complete. */ + rc = wait_for_completion_timeout(&context.completion_evt, + msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); + if (rc == 0) { + rc = -ETIMEDOUT; + goto end; + } + rc = 0; + + if (context.status) { + rc = context.status; + goto end; + } + + if (adapter->ocb_set_config_resp.status) { + rc = -EINVAL; + goto end; + } + + /* fall through */ +end: + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + if (rc) + hddLog(LOGE, FL("Operation failed: %d"), rc); + return rc; +} + +/** + * __iw_set_dot11p_channel_sched() - Handler for WLAN_SET_DOT11P_CHANNEL_SCHED + * ioctl + * @dev: Pointer to net_device structure + * @iw_request_info: IW Request Info + * @wrqu: IW Request Userspace Data Pointer + * @extra: IW Request Kernel Data Pointer + * + * Return: 0 on success + */ +static int __iw_set_dot11p_channel_sched(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int rc = 0; + struct dot11p_channel_sched *sched; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct sir_ocb_config *config = NULL; + uint8_t *mac_addr; + int i, j; + + if (wlan_hdd_validate_context(WLAN_HDD_GET_CTX(adapter))) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + sched = (struct dot11p_channel_sched *)extra; + + /* Scheduled slots same as num channels for compatibility */ + config = hdd_ocb_config_new(sched->num_channels, sched->num_channels, + 0, 0); + if (config == NULL) { + hddLog(LOGE, FL("Failed to allocate memory!")); + return -ENOMEM; + } + + /* Identify the vdev interface */ + config->session_id = adapter->sessionId; + + /* Release all the mac addresses used for OCB */ + for (i = 0; i < adapter->ocb_mac_addr_count; i++) { + wlan_hdd_release_intf_addr(adapter->pHddCtx, + adapter->ocb_mac_address[i]); + } + adapter->ocb_mac_addr_count = 0; + + config->channel_count = 0; + for (i = 0; i < sched->num_channels; i++) { + if (0 == sched->channels[i].channel_freq) { + continue; + } + + config->channels[config->channel_count].chan_freq = + sched->channels[i].channel_freq; + /* + * tx_power is divided by 2 because ocb_channel.tx_power is + * in half dB increments and sir_ocb_config_channel.max_pwr + * is in 1 dB increments. + */ + config->channels[config->channel_count].max_pwr = + sched->channels[i].tx_power / 2; + config->channels[config->channel_count].bandwidth = + sched->channels[i].channel_bandwidth; + /* assume 10 as default if not provided */ + if (config->channels[config->channel_count].bandwidth == 0) { + config->channels[config->channel_count].bandwidth = 10; + } + + /* + * Setup locally administered mac addresses for each channel. + * First channel uses the adapter's address. + */ + if (i == 0) { + vos_mem_copy(config->channels[config->channel_count].mac_address, + adapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + } else { + mac_addr = wlan_hdd_get_intf_addr(adapter->pHddCtx); + if (mac_addr == NULL) { + hddLog(LOGE, FL("Cannot obtain mac address")); + rc = -EINVAL; + goto fail; + } + vos_mem_copy(config->channels[ + config->channel_count].mac_address, + mac_addr, sizeof(tSirMacAddr)); + /* Save the mac address to release later */ + vos_mem_copy(adapter->ocb_mac_address[ + adapter->ocb_mac_addr_count], + mac_addr, + sizeof(adapter->ocb_mac_address[ + adapter->ocb_mac_addr_count])); + adapter->ocb_mac_addr_count++; + } + + for (j = 0; j < MAX_NUM_AC; j++) { + config->channels[config->channel_count].qos_params[j].aifsn = + sched->channels[i].qos_params[j].aifsn; + config->channels[config->channel_count].qos_params[j].cwmin = + sched->channels[i].qos_params[j].cwmin; + config->channels[config->channel_count].qos_params[j].cwmax = + sched->channels[i].qos_params[j].cwmax; + } + + config->channel_count++; + } + + /* + * Scheduled slots same as num channels for compatibility with + * legacy use. + */ + for (i = 0; i < sched->num_channels; i++) { + config->schedule[i].chan_freq = sched->channels[i].channel_freq; + config->schedule[i].guard_interval = + sched->channels[i].start_guard_interval; + config->schedule[i].total_duration = + sched->channels[i].duration; + } + + rc = hdd_ocb_set_config_req(adapter, config); + if (rc) { + hddLog(LOGE, FL("Error while setting OCB config")); + goto fail; + } + + rc = 0; + +fail: + vos_mem_free(config); + return rc; +} + +/** + * iw_set_dot11p_channel_sched() - IOCTL interface for setting channel schedule + * @dev: Pointer to net_device structure + * @iw_request_info: IW Request Info + * @wrqu: IW Request Userspace Data Pointer + * @extra: IW Request Kernel Data Pointer + * + * Return: 0 on success. + */ +int iw_set_dot11p_channel_sched(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_dot11p_channel_sched(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static const struct nla_policy qca_wlan_vendor_ocb_set_config_policy[ + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY] = { + .type = NLA_BINARY + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY] = { + .type = NLA_BINARY + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY] = { + .type = NLA_BINARY + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY] = { + .type = NLA_BINARY + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS] = { + .type = NLA_U32 + }, +}; + +static const struct nla_policy qca_wlan_vendor_ocb_set_utc_time_policy[ + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE] = { + .type = NLA_BINARY, .len = SIZE_UTC_TIME + }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR] = { + .type = NLA_BINARY, .len = SIZE_UTC_TIME_ERROR + }, +}; + +static const struct nla_policy qca_wlan_vendor_ocb_start_timing_advert_policy[ + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE] = { + .type = NLA_U32 + }, +}; + +static const struct nla_policy qca_wlan_vendor_ocb_stop_timing_advert_policy[ + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ] = { + .type = NLA_U32 + }, +}; + +static const struct nla_policy qca_wlan_vendor_ocb_get_tsf_timer_resp[] = { + [QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW] = { + .type = NLA_U32 + }, +}; + +static const struct nla_policy qca_wlan_vendor_dcc_get_stats[] = { + [QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY] = { + .type = NLA_BINARY + }, +}; + +static const struct nla_policy qca_wlan_vendor_dcc_get_stats_resp[] = { + [QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY] = { + .type = NLA_BINARY + }, +}; + +static const struct nla_policy qca_wlan_vendor_dcc_clear_stats[] = { + [QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP] = { + .type = NLA_U32 + }, +}; + +static const struct nla_policy qca_wlan_vendor_dcc_update_ndl[ + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT] = { + .type = NLA_U32 + }, + [QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY] = { + .type = NLA_BINARY + }, + [QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY] = { + .type = NLA_BINARY + }, +}; + +/** + * struct wlan_hdd_ocb_config_channel + * @chan_freq: frequency of the channel + * @bandwidth: bandwidth of the channel, either 10 or 20 MHz + * @mac_address: MAC address assigned to this channel + * @qos_params: QoS parameters + * @max_pwr: maximum transmit power of the channel (1/2 dBm) + * @min_pwr: minimum transmit power of the channel (1/2 dBm) + */ +struct wlan_hdd_ocb_config_channel { + uint32_t chan_freq; + uint32_t bandwidth; + uint16_t flags; + uint8_t reserved[4]; + sir_qos_params_t qos_params[MAX_NUM_AC]; + uint32_t max_pwr; + uint32_t min_pwr; +}; + +static void wlan_hdd_ocb_config_channel_to_sir_ocb_config_channel( + struct sir_ocb_config_channel *dest, + struct wlan_hdd_ocb_config_channel *src, + uint32_t channel_count) +{ + uint32_t i; + + vos_mem_zero(dest, channel_count * sizeof(*dest)); + + for (i = 0; i < channel_count; i++) { + dest[i].chan_freq = src[i].chan_freq; + dest[i].bandwidth = src[i].bandwidth; + vos_mem_copy(dest[i].qos_params, src[i].qos_params, + sizeof(dest[i].qos_params)); + /* + * max_pwr and min_pwr are divided by 2 because + * wlan_hdd_ocb_config_channel.max_pwr and min_pwr + * are in 1/2 dB increments and + * sir_ocb_config_channel.max_pwr and min_pwr are in + * 1 dB increments. + */ + dest[i].max_pwr = src[i].max_pwr / 2; + dest[i].min_pwr = (src[i].min_pwr + 1) / 2; + dest[i].flags = src[i].flags; + } +} + +/** + * __wlan_hdd_cfg80211_ocb_set_config() - Interface for set config command + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int __wlan_hdd_cfg80211_ocb_set_config(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_OCB_SET_CONFIG_MAX + 1]; + struct nlattr *channel_array; + struct nlattr *sched_array; + struct nlattr *ndl_chan_list; + uint32_t ndl_chan_list_len; + struct nlattr *ndl_active_state_list; + uint32_t ndl_active_state_list_len; + uint32_t flags = 0; + int i; + int channel_count, schedule_size; + struct sir_ocb_config *config; + int rc = -EINVAL; + uint8_t *mac_addr; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX, + data, + data_len, qca_wlan_vendor_ocb_set_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Get the number of channels in the schedule */ + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT]) { + hddLog(LOGE, FL("CHANNEL_COUNT is not present")); + return -EINVAL; + } + channel_count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT]); + + /* Get the size of the channel schedule */ + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE]) { + hddLog(LOGE, FL("SCHEDULE_SIZE is not present")); + return -EINVAL; + } + schedule_size = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE]); + + /* Get the ndl chan array and the ndl active state array. */ + ndl_chan_list = + tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY]; + ndl_chan_list_len = (ndl_chan_list ? nla_len(ndl_chan_list) : 0); + + ndl_active_state_list = + tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY]; + ndl_active_state_list_len = (ndl_active_state_list ? + nla_len(ndl_active_state_list) : 0); + + /* Get the flags */ + if (tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS]) + flags = nla_get_u32(tb[ + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS]); + + config = hdd_ocb_config_new(channel_count, schedule_size, + ndl_chan_list_len, + ndl_active_state_list_len); + if (config == NULL) { + hddLog(LOGE, FL("Failed to allocate memory!")); + return -ENOMEM; + } + + config->channel_count = channel_count; + config->schedule_size = schedule_size; + config->flags = flags; + + /* Read the channel array */ + channel_array = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY]; + if (!channel_array) { + hddLog(LOGE, FL("No channel present")); + goto fail; + } + if (nla_len(channel_array) != channel_count * + sizeof(struct wlan_hdd_ocb_config_channel)) { + hddLog(LOGE, FL("CHANNEL_ARRAY is not the correct size")); + goto fail; + } + wlan_hdd_ocb_config_channel_to_sir_ocb_config_channel( + config->channels, nla_data(channel_array), channel_count); + + /* Identify the vdev interface */ + config->session_id = adapter->sessionId; + + /* Release all the mac addresses used for OCB */ + for (i = 0; i < adapter->ocb_mac_addr_count; i++) { + wlan_hdd_release_intf_addr(adapter->pHddCtx, + adapter->ocb_mac_address[i]); + } + adapter->ocb_mac_addr_count = 0; + + /* + * Setup locally administered mac addresses for each channel. + * First channel uses the adapter's address. + */ + for (i = 0; i < config->channel_count; i++) { + if (i == 0) { + vos_mem_copy(config->channels[i].mac_address, + adapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + } else { + mac_addr = wlan_hdd_get_intf_addr(adapter->pHddCtx); + if (mac_addr == NULL) { + hddLog(LOGE, FL("Cannot obtain mac address")); + goto fail; + } + vos_mem_copy(config->channels[i].mac_address, + mac_addr, sizeof(tSirMacAddr)); + /* Save the mac address to release later */ + vos_mem_copy(adapter->ocb_mac_address[ + adapter->ocb_mac_addr_count], + config->channels[i].mac_address, + sizeof(adapter->ocb_mac_address[ + adapter->ocb_mac_addr_count])); + adapter->ocb_mac_addr_count++; + } + } + + /* Read the schedule array */ + sched_array = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY]; + if (!sched_array) { + hddLog(LOGE, FL("No channel present")); + goto fail; + } + if (nla_len(sched_array) != schedule_size * sizeof(*config->schedule)) { + hddLog(LOGE, FL("SCHEDULE_ARRAY is not the correct size")); + goto fail; + } + vos_mem_copy(config->schedule, nla_data(sched_array), + nla_len(sched_array)); + + /* Copy the NDL chan array */ + if (ndl_chan_list_len) { + config->dcc_ndl_chan_list_len = ndl_chan_list_len; + vos_mem_copy(config->dcc_ndl_chan_list, nla_data(ndl_chan_list), + nla_len(ndl_chan_list)); + } + + /* Copy the NDL active state array */ + if (ndl_active_state_list_len) { + config->dcc_ndl_active_state_list_len = + ndl_active_state_list_len; + vos_mem_copy(config->dcc_ndl_active_state_list, + nla_data(ndl_active_state_list), + nla_len(ndl_active_state_list)); + } + + rc = hdd_ocb_set_config_req(adapter, config); + if (rc) + hddLog(LOGE, FL("Error while setting OCB config: %d"), rc); + +fail: + vos_mem_free(config); + return rc; +} + +/** + * wlan_hdd_cfg80211_ocb_set_config() - Interface for set config command + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_set_config(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_ocb_set_utc_time() - Interface for set UTC time command + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int __wlan_hdd_cfg80211_ocb_set_utc_time(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_OCB_SET_UTC_TIME_MAX + 1]; + struct nlattr *utc_attr; + struct nlattr *time_error_attr; + struct sir_ocb_utc *utc; + int rc = -EINVAL; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX, + data, + data_len, qca_wlan_vendor_ocb_set_utc_time_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Read the UTC time */ + utc_attr = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE]; + if (!utc_attr) { + hddLog(LOGE, FL("UTC_TIME is not present")); + return -EINVAL; + } + if (nla_len(utc_attr) != SIZE_UTC_TIME) { + hddLog(LOGE, FL("UTC_TIME is not the correct size")); + return -EINVAL; + } + + /* Read the time error */ + time_error_attr = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR]; + if (!time_error_attr) { + hddLog(LOGE, FL("UTC_TIME is not present")); + return -EINVAL; + } + if (nla_len(time_error_attr) != SIZE_UTC_TIME_ERROR) { + hddLog(LOGE, FL("UTC_TIME is not the correct size")); + return -EINVAL; + } + + utc = vos_mem_malloc(sizeof(*utc)); + if (!utc) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + utc->vdev_id = adapter->sessionId; + vos_mem_copy(utc->utc_time, nla_data(utc_attr), SIZE_UTC_TIME); + vos_mem_copy(utc->time_error, nla_data(time_error_attr), + SIZE_UTC_TIME_ERROR); + + if (sme_ocb_set_utc_time(utc) != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error while setting UTC time")); + rc = -EINVAL; + } else { + rc = 0; + } + + vos_mem_free(utc); + return rc; +} + +/** + * wlan_hdd_cfg80211_ocb_set_utc_time() - Interface for the set UTC time command + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_set_utc_time(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_ocb_start_timing_advert() - Interface for start TA cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int +__wlan_hdd_cfg80211_ocb_start_timing_advert(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); + tpAniSirGlobal mac_ctx = PMAC_STRUCT(WLAN_HDD_GET_HAL_CTX(adapter)); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX + 1]; + struct sir_ocb_timing_advert *timing_advert; + int rc = -EINVAL; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + timing_advert = vos_mem_malloc(sizeof(*timing_advert)); + if (!timing_advert) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + vos_mem_zero(timing_advert, sizeof(*timing_advert)); + timing_advert->vdev_id = adapter->sessionId; + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX, + data, + data_len, + qca_wlan_vendor_ocb_start_timing_advert_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + goto fail; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ]) { + hddLog(LOGE, FL("CHANNEL_FREQ is not present")); + goto fail; + } + timing_advert->chan_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE]) { + hddLog(LOGE, FL("REPEAT_RATE is not present")); + goto fail; + } + timing_advert->repeat_rate = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE]); + + timing_advert->template_length = + schGenTimingAdvertFrame(mac_ctx, + *(tSirMacAddr *)&adapter->macAddressCurrent.bytes, + &timing_advert->template_value, + &timing_advert->timestamp_offset, + &timing_advert->time_value_offset); + if (timing_advert->template_length <= 0) { + hddLog(LOGE, FL("Error while generating the TA frame")); + goto fail; + } + + if (sme_ocb_start_timing_advert(timing_advert) != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error while starting timing advert")); + rc = -EINVAL; + } else { + rc = 0; + } + +fail: + if (timing_advert->template_value) + vos_mem_free(timing_advert->template_value); + vos_mem_free(timing_advert); + return rc; +} + +/** + * wlan_hdd_cfg80211_ocb_start_timing_advert() - Interface for the start TA cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_start_timing_advert(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_ocb_stop_timing_advert() - Interface for the stop TA cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int +__wlan_hdd_cfg80211_ocb_stop_timing_advert(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_OCB_STOP_TIMING_ADVERT_MAX + 1]; + struct sir_ocb_timing_advert *timing_advert; + int rc = -EINVAL; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + timing_advert = vos_mem_malloc(sizeof(*timing_advert)); + if (!timing_advert) { + hddLog(LOGE, FL("vos_mem_malloc failed")); + return -ENOMEM; + } + vos_mem_zero(timing_advert, sizeof(sizeof(*timing_advert))); + timing_advert->vdev_id = adapter->sessionId; + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX, + data, + data_len, + qca_wlan_vendor_ocb_stop_timing_advert_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + goto fail; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ]) { + hddLog(LOGE, FL("CHANNEL_FREQ is not present")); + goto fail; + } + timing_advert->chan_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ]); + + if (sme_ocb_stop_timing_advert(timing_advert) != eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error while stopping timing advert")); + rc = -EINVAL; + } else { + rc = 0; + } + +fail: + vos_mem_free(timing_advert); + return rc; +} + +/** + * wlan_hdd_cfg80211_ocb_stop_timing_advert() - Interface for the stop TA cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_stop_timing_advert(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_ocb_get_tsf_timer_callback() - Callback to get TSF command + * @context_ptr: request context + * @response_ptr: response data + */ +static void hdd_ocb_get_tsf_timer_callback(void *context_ptr, + void *response_ptr) +{ + struct hdd_ocb_ctxt *context = context_ptr; + struct sir_ocb_get_tsf_timer_response *response = response_ptr; + + if (!context) + return; + + spin_lock(&hdd_context_lock); + if (context->magic == HDD_OCB_MAGIC) { + if (response) { + context->adapter->ocb_get_tsf_timer_resp = *response; + context->status = 0; + } else { + context->status = -EINVAL; + } + complete(&context->completion_evt); + } + spin_unlock(&hdd_context_lock); +} + +/** + * __wlan_hdd_cfg80211_ocb_get_tsf_timer() - Interface for get TSF timer cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int +__wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + struct sk_buff *nl_resp = 0; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + int rc = -EINVAL; + struct sir_ocb_get_tsf_timer request = {0}; + struct hdd_ocb_ctxt context = {0}; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + /* Initialize the callback context */ + init_completion(&context.completion_evt); + context.adapter = adapter; + context.magic = HDD_OCB_MAGIC; + + request.vdev_id = adapter->sessionId; + /* Call the SME function */ + rc = sme_ocb_get_tsf_timer(hdd_ctx->hHal, &context, + hdd_ocb_get_tsf_timer_callback, + &request); + if (rc) { + hddLog(LOGE, FL("Error calling SME function")); + /* Need to convert from eHalStatus to errno. */ + return -EINVAL; + } + + rc = wait_for_completion_timeout(&context.completion_evt, + msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); + if (rc == 0) { + hddLog(LOGE, FL("Operation timed out")); + rc = -ETIMEDOUT; + goto end; + } + rc = 0; + + if (context.status) { + hddLog(LOGE, FL("Operation failed: %d"), context.status); + rc = context.status; + goto end; + } + + /* Allocate the buffer for the response. */ + nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + 2 * sizeof(uint32_t) + NLMSG_HDRLEN); + + if (!nl_resp) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + rc = -ENOMEM; + goto end; + } + + hddLog(LOGE, FL("Got TSF timer response, high=%d, low=%d"), + adapter->ocb_get_tsf_timer_resp.timer_high, + adapter->ocb_get_tsf_timer_resp.timer_low); + + /* Populate the response. */ + rc = nla_put_u32(nl_resp, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH, + adapter->ocb_get_tsf_timer_resp.timer_high); + if (rc) + goto end; + rc = nla_put_u32(nl_resp, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW, + adapter->ocb_get_tsf_timer_resp.timer_low); + if (rc) + goto end; + + /* Send the response. */ + rc = cfg80211_vendor_cmd_reply(nl_resp); + nl_resp = NULL; + if (rc) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_reply failed: %d"), rc); + goto end; + } + +end: + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + if (nl_resp) + kfree_skb(nl_resp); + return rc; +} + +/** + * wlan_hdd_cfg80211_ocb_get_tsf_timer() - Interface for get TSF timer cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_get_tsf_timer(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_dcc_get_stats_callback() - Callback to get stats command + * @context_ptr: request context + * @response_ptr: response data + */ +static void hdd_dcc_get_stats_callback(void *context_ptr, void *response_ptr) +{ + struct hdd_ocb_ctxt *context = context_ptr; + struct sir_dcc_get_stats_response *response = response_ptr; + struct sir_dcc_get_stats_response *hdd_resp; + + if (!context) + return; + + spin_lock(&hdd_context_lock); + if (context->magic == HDD_OCB_MAGIC) { + if (response) { + /* + * If the response is hanging around from the previous + * request, delete it + */ + if (context->adapter->dcc_get_stats_resp) { + vos_mem_free( + context->adapter->dcc_get_stats_resp); + } + context->adapter->dcc_get_stats_resp = + vos_mem_malloc(sizeof( + *context->adapter->dcc_get_stats_resp) + + response->channel_stats_array_len); + if (context->adapter->dcc_get_stats_resp) { + hdd_resp = context->adapter->dcc_get_stats_resp; + *hdd_resp = *response; + hdd_resp->channel_stats_array = + (void *)hdd_resp + sizeof(*hdd_resp); + vos_mem_copy(hdd_resp->channel_stats_array, + response->channel_stats_array, + response->channel_stats_array_len); + context->status = 0; + } else { + context->status = -ENOMEM; + } + } else { + context->status = -EINVAL; + } + complete(&context->completion_evt); + } + spin_unlock(&hdd_context_lock); +} + +/** + * __wlan_hdd_cfg80211_dcc_get_stats() - Interface for get dcc stats + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint32_t channel_count = 0; + uint32_t request_array_len = 0; + void *request_array = 0; + 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_DCC_GET_STATS_MAX + 1]; + struct sk_buff *nl_resp = 0; + int rc = -EINVAL; + struct sir_dcc_get_stats request = {0}; + struct hdd_ocb_ctxt context = {0}; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX, + data, + data_len, + qca_wlan_vendor_dcc_get_stats)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Validate all the parameters are present */ + if (!tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT] || + !tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]) { + hddLog(LOGE, FL("Parameters are not present.")); + return -EINVAL; + } + + channel_count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT]); + request_array_len = nla_len( + tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]); + request_array = nla_data( + tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]); + + /* Initialize the callback context */ + init_completion(&context.completion_evt); + context.adapter = adapter; + context.magic = HDD_OCB_MAGIC; + + request.vdev_id = adapter->sessionId; + request.channel_count = channel_count; + request.request_array_len = request_array_len; + request.request_array = request_array; + + /* Call the SME function. */ + rc = sme_dcc_get_stats(hdd_ctx->hHal, &context, + hdd_dcc_get_stats_callback, + &request); + if (rc) { + hddLog(LOGE, FL("Error calling SME function")); + /* Need to convert from eHalStatus to errno. */ + return -EINVAL; + } + + /* Wait for the function to complete. */ + rc = wait_for_completion_timeout(&context.completion_evt, + msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); + if (rc == 0) { + hddLog(LOGE, FL("Operation failed: %d"), rc); + rc = -ETIMEDOUT; + goto end; + } + + if (context.status) { + hddLog(LOGE, FL("There was error: %d"), context.status); + rc = context.status; + goto end; + } + + if (!adapter->dcc_get_stats_resp) { + hddLog(LOGE, FL("The response was NULL")); + rc = -EINVAL; + goto end; + } + + /* Allocate the buffer for the response. */ + nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(uint32_t) + + adapter->dcc_get_stats_resp->channel_stats_array_len + + NLMSG_HDRLEN); + if (!nl_resp) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + rc = -ENOMEM; + goto end; + } + + /* Populate the response. */ + rc = nla_put_u32(nl_resp, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT, + adapter->dcc_get_stats_resp->num_channels); + if (rc) + goto end; + rc = nla_put(nl_resp, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY, + adapter->dcc_get_stats_resp->channel_stats_array_len, + adapter->dcc_get_stats_resp->channel_stats_array); + if (rc) + goto end; + + /* Send the response. */ + rc = cfg80211_vendor_cmd_reply(nl_resp); + nl_resp = NULL; + if (rc) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_reply failed: %d"), rc); + goto end; + } + + /* fall through */ +end: + spin_lock(&hdd_context_lock); + context.magic = 0; + vos_mem_free(adapter->dcc_get_stats_resp); + adapter->dcc_get_stats_resp = NULL; + spin_unlock(&hdd_context_lock); + if (nl_resp) + kfree_skb(nl_resp); + return rc; +} + +/** + * wlan_hdd_cfg80211_dcc_get_stats() - Interface for get dcc stats + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dcc_get_stats(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_dcc_clear_stats() - Interface for clear dcc stats cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int __wlan_hdd_cfg80211_dcc_clear_stats(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_DCC_CLEAR_STATS_MAX + 1]; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_MAX, + data, + data_len, + qca_wlan_vendor_dcc_clear_stats)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Verify that the parameter is present */ + if (!tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP]) { + hddLog(LOGE, FL("Parameters are not present.")); + return -EINVAL; + } + + /* Call the SME function */ + if (sme_dcc_clear_stats(adapter->sessionId, + nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP])) != + eHAL_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error calling SME function.")); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_dcc_clear_stats() - Interface for clear dcc stats cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dcc_clear_stats(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_dcc_update_ndl_callback() - Callback to update NDL command + * @context_ptr: request context + * @response_ptr: response data + */ +static void hdd_dcc_update_ndl_callback(void *context_ptr, void *response_ptr) +{ + struct hdd_ocb_ctxt *context = context_ptr; + struct sir_dcc_update_ndl_response *response = response_ptr; + + if (!context) + return; + + spin_lock(&hdd_context_lock); + if (context->magic == HDD_OCB_MAGIC) { + if (response) { + context->adapter->dcc_update_ndl_resp = *response; + context->status = 0; + } else { + context->status = -EINVAL; + } + complete(&context->completion_evt); + } + spin_unlock(&hdd_context_lock); +} + +/** + * __wlan_hdd_cfg80211_dcc_update_ndl() - Interface for update dcc cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +static int __wlan_hdd_cfg80211_dcc_update_ndl(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_DCC_UPDATE_NDL_MAX + 1]; + struct sir_dcc_update_ndl request; + uint32_t channel_count; + uint32_t ndl_channel_array_len; + void *ndl_channel_array; + uint32_t ndl_active_state_array_len; + void *ndl_active_state_array; + int rc = -EINVAL; + struct hdd_ocb_ctxt context = {0}; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + goto end; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + goto end; + } + + if (!wma_is_vdev_up(adapter->sessionId)) { + hddLog(LOGE, FL("The device has not been started")); + return -EINVAL; + } + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX, + data, + data_len, + qca_wlan_vendor_dcc_update_ndl)) { + hddLog(LOGE, FL("Invalid ATTR")); + goto end; + } + + /* Verify that the parameter is present */ + if (!tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT] || + !tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY] || + !tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]) { + hddLog(LOGE, FL("Parameters are not present.")); + return -EINVAL; + } + + channel_count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT]); + ndl_channel_array_len = nla_len( + tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY]); + ndl_channel_array = nla_data( + tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY]); + ndl_active_state_array_len = nla_len( + tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]); + ndl_active_state_array = nla_data( + tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]); + + /* Initialize the callback context */ + init_completion(&context.completion_evt); + context.adapter = adapter; + context.magic = HDD_OCB_MAGIC; + + /* Copy the parameters to the request structure. */ + request.vdev_id = adapter->sessionId; + request.channel_count = channel_count; + request.dcc_ndl_chan_list_len = ndl_channel_array_len; + request.dcc_ndl_chan_list = ndl_channel_array; + request.dcc_ndl_active_state_list_len = ndl_active_state_array_len; + request.dcc_ndl_active_state_list = ndl_active_state_array; + + /* Call the SME function */ + rc = sme_dcc_update_ndl(hdd_ctx->hHal, &context, + hdd_dcc_update_ndl_callback, + &request); + if (rc) { + hddLog(LOGE, FL("Error calling SME function.")); + /* Convert from eHalStatus to errno */ + return -EINVAL; + } + + /* Wait for the function to complete. */ + rc = wait_for_completion_timeout(&context.completion_evt, + msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD)); + if (rc == 0) { + hddLog(LOGE, FL("Operation timed out")); + rc = -ETIMEDOUT; + goto end; + } + rc = 0; + + if (context.status) { + hddLog(LOGE, FL("Operation failed: %d"), context.status); + rc = context.status; + goto end; + } + + if (adapter->dcc_update_ndl_resp.status) { + hddLog(LOGE, FL("Operation returned: %d"), + adapter->dcc_update_ndl_resp.status); + rc = -EINVAL; + goto end; + } + + /* fall through */ +end: + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + return rc; +} + +/** + * wlan_hdd_cfg80211_dcc_update_ndl() - Interface for update dcc cmd + * @wiphy: pointer to the wiphy + * @wdev: pointer to the wdev + * @data: The netlink data + * @data_len: The length of the netlink data in bytes + * + * Return: 0 on success. + */ +int wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dcc_update_ndl(wiphy, wdev, + data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_dcc_stats_event_callback() - Callback to get stats event + * @context_ptr: request context + * @response_ptr: response data + */ +static void wlan_hdd_dcc_stats_event_callback(void *context_ptr, + void *response_ptr) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr; + struct sir_dcc_get_stats_response *resp = response_ptr; + struct sk_buff *vendor_event; + + ENTER(); + + vendor_event = + cfg80211_vendor_event_alloc(hdd_ctx->wiphy, + NULL, sizeof(uint32_t) + resp->channel_stats_array_len + + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT, + resp->num_channels) || + nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY, + resp->channel_stats_array_len, + resp->channel_stats_array)) { + hddLog(LOGE, FL("nla put failed")); + kfree_skb(vendor_event); + return; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +} + +/** + * wlan_hdd_dcc_register_for_dcc_stats_event() - Register for dcc stats events + * @hdd_ctx: hdd context + */ +void wlan_hdd_dcc_register_for_dcc_stats_event(hdd_context_t *hdd_ctx) +{ + int rc; + + rc = sme_register_for_dcc_stats_event(hdd_ctx->hHal, hdd_ctx, + wlan_hdd_dcc_stats_event_callback); + if (rc) + hddLog(LOGE, FL("Register callback failed: %d"), rc); +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.h b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.h new file mode 100644 index 000000000000..6f3cf1abe3fc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.h @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_HDD_OCB_H +#define __WLAN_HDD_OCB_H + +#include +#include "sirApi.h" + +#define WLAN_OCB_CHANNEL_MAX 5 + +/** + * struct ocb_qos_params - QoS Parameters for each AC + * @aifsn: Arbitration Inter-Frame Spacing + * @cwmin: Contention Window (Min) + * @cwmax: Contention Window (Max) + */ +struct ocb_qos_params { + uint8_t aifsn; + uint8_t cwmin; + uint8_t cwmax; +}; + +/** + * struct ocb_channel - Parameters for each OCB channel + * @channel_freq: Channel Center Frequency (MHz) + * @duration: Channel Duration (ms) + * @start_guard_interval: Start Guard Interval (ms) + * @channel_bandwidth: Channel Bandwidth (MHz) + * @tx_power: Transmit Power (1/2 dBm) + * @tx_rate: Transmit Data Rate (mbit) + * @qos_params: Array of QoS Parameters + * @per_packet_rx_stats: Enable per packet RX statistics + */ +struct ocb_channel { + uint32_t channel_freq; + uint32_t duration; + uint32_t start_guard_interval; + uint32_t channel_bandwidth; + uint32_t tx_power; + uint32_t tx_rate; + struct ocb_qos_params qos_params[MAX_NUM_AC]; + uint32_t per_packet_rx_stats; +}; + +/** + * struct dot11p_channel_sched - OCB channel schedule + * @num_channels: Number of channels + * @channels: Array of channel parameters + * @off_channel_tx: Enable off channel TX + */ +struct dot11p_channel_sched { + uint32_t num_channels; + struct ocb_channel channels[WLAN_OCB_CHANNEL_MAX]; + uint32_t off_channel_tx; +}; + +/** + * enum qca_wlan_vendor_attr_ocb_set_config - vendor subcmd to set ocb config + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT: + * number of channels in the configuration + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE: size of the schedule + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY: array of channels + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY: + * array of channels to be scheduled + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY: + * array of NDL channel information + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY: + * array of NDL active state configuration + */ +enum qca_wlan_vendor_attr_ocb_set_config { + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_ocb_set_utc_time - vendor subcmd to set UTC time + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE: + * the UTC time as an array of 10 bytes + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR: + * the time error as an array of 5 bytes + */ +enum qca_wlan_vendor_attr_ocb_set_utc_time { + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_ocb_start_timing_advert - vendor subcmd to start + sending timing advert + frames + * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ: + * channel frequency on which to send the frames + * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE: + * number of times the frame is sent in 5 seconds + */ +enum qca_wlan_vendor_attr_ocb_start_timing_advert { + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_ocb_stop_timing_advert - vendor subcmd to stop + * timing advert + * @QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ: + * the channel frequency on which to stop the timing advert + */ +enum qca_wlan_vendor_attr_ocb_stop_timing_advert { + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ, + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_dcc_get_tsf_response - vendor subcmd to get TSF + * timer value + * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH: + * higher 32 bits of the timer + * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW: + * lower 32 bits of the timer + */ +enum qca_wlan_vendor_attr_ocb_get_tsf_resp { + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_dcc_get_stats - vendor subcmd to get + * dcc stats + * @QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT: + * the number of channels in the request array + * @QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY + * array of the channel and information being requested + */ +enum qca_wlan_vendor_attr_dcc_get_stats { + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_CHANNEL_COUNT, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX = + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_dcc_get_stats_resp - response event from get + * dcc stats + * @QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT: + * the number of channels in the request array + * @QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY + * array of the information being requested + */ +enum qca_wlan_vendor_attr_dcc_get_stats_resp { + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_MAX = + QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_dcc_clear_stats - vendor subcmd to clear DCC stats + * @QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP: + * mask of the type of stats to be cleared + */ +enum qca_wlan_vendor_attr_dcc_clear_stats { + QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP, + QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_MAX = + QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_ocb_set_config - vendor subcmd to update dcc + * @QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT: + * number of channels in the configuration + * @QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY: the array of NDL + * channel info + * @QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY: the array of + * NDL active states + */ +enum qca_wlan_vendor_attr_dcc_update_ndl { + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_COUNT, + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_CHANNEL_ARRAY, + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY, + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX = + QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_AFTER_LAST - 1, +}; + +void hdd_set_dot11p_config(hdd_context_t *hdd_ctx); + +int iw_set_dot11p_channel_sched(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +void wlan_hdd_dcc_register_for_dcc_stats_event(hdd_context_t *hdd_ctx); + +#endif /* __WLAN_HDD_OCB_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c new file mode 100644 index 000000000000..104e54efe692 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c @@ -0,0 +1,841 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/*================================================================================ + \file wlan_hdd_oemdata.c + + \brief Linux Wireless Extensions for oem data req/rsp + + $Id: wlan_hdd_oemdata.c,v 1.34 2010/04/15 01:49:23 -- VINAY + +================================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qwlan_version.h" +#include "vos_utils.h" +#include "wma.h" +static struct hdd_context_s *pHddCtx; + + +/**--------------------------------------------------------------------------- + + \brief iw_get_oem_data_cap() + + This function gets the capability information for OEM Data Request + and Response. + + \param - dev - Pointer to the net device + - info - Pointer to the t_iw_oem_data_cap + - wrqu - Pointer to the iwreq data + - extra - Pointer to the data + + \return - 0 for success, non zero for failure + +----------------------------------------------------------------------------*/ +int iw_get_oem_data_cap( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + eHalStatus status; + t_iw_oem_data_cap oemDataCap; + t_iw_oem_data_cap *pHddOemDataCap; + hdd_adapter_t *pAdapter = netdev_priv(dev); + hdd_context_t *pHddContext; + hdd_config_t *pConfig; + tANI_U32 numChannels; + tANI_U8 chanList[OEM_CAP_MAX_NUM_CHANNELS]; + tANI_U32 i; + int ret; + + ENTER(); + + if (!pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Invalid context, pAdapter is null", __func__); + return -EINVAL; + } + + pHddContext = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddContext); + if (0 != ret) + return ret; + + pConfig = pHddContext->cfg_ini; + + do + { + vos_mem_zero(&oemDataCap, sizeof(oemDataCap)); + strlcpy(oemDataCap.oem_target_signature, OEM_TARGET_SIGNATURE, + OEM_TARGET_SIGNATURE_LEN); + oemDataCap.oem_target_type = pHddContext->target_type; + oemDataCap.oem_fw_version = pHddContext->target_fw_version; + oemDataCap.driver_version.major = QWLAN_VERSION_MAJOR; + oemDataCap.driver_version.minor = QWLAN_VERSION_MINOR; + oemDataCap.driver_version.patch = QWLAN_VERSION_PATCH; + oemDataCap.driver_version.build = QWLAN_VERSION_BUILD; + oemDataCap.allowed_dwell_time_min = pConfig->nNeighborScanMinChanTime; + oemDataCap.allowed_dwell_time_max = pConfig->nNeighborScanMaxChanTime; + oemDataCap.curr_dwell_time_min = + sme_getNeighborScanMinChanTime(pHddContext->hHal, + pAdapter->sessionId); + oemDataCap.curr_dwell_time_max = + sme_getNeighborScanMaxChanTime(pHddContext->hHal, + pAdapter->sessionId); + oemDataCap.supported_bands = pConfig->nBandCapability; + + /* request for max num of channels */ + numChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + status = sme_GetCfgValidChannels(pHddContext->hHal, + &chanList[0], + &numChannels); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:failed to get valid channel list", __func__); + return -ENOENT; + } + else + { + /* make sure num channels is not more than chan list array */ + if (numChannels > OEM_CAP_MAX_NUM_CHANNELS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Num of channels(%d) more than length(%d) of chanlist", + __func__, numChannels, OEM_CAP_MAX_NUM_CHANNELS); + return -ENOMEM; + } + + oemDataCap.num_channels = numChannels; + for (i = 0; i < numChannels; i++) + { + oemDataCap.channel_list[i] = chanList[i]; + } + } + + pHddOemDataCap = (t_iw_oem_data_cap *)(extra); + vos_mem_copy(pHddOemDataCap, &oemDataCap, sizeof(*pHddOemDataCap)); + } while (0); + + EXIT(); + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief send_oem_reg_rsp_nlink_msg() - send oem registration response + + This function sends oem message to registered application process + + \param - + - none + + \return - none + + --------------------------------------------------------------------------*/ +static void send_oem_reg_rsp_nlink_msg(void) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tANI_U8 *buf; + tANI_U8 *numInterfaces; + tANI_U8 *deviceMode; + tANI_U8 *vdevId; + hdd_adapter_list_node_t *pAdapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + VOS_STATUS status = 0; + + /* OEM message is always to a specific process and cannot be a broadcast */ + if (pHddCtx->oem_pid == 0) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid dest pid", __func__); + return; + } + + skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL); + if (skb == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_OEM; + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = ANI_MSG_APP_REG_RSP; + + /* Fill message body: + * First byte will be number of interfaces, followed by + * two bytes for each interfaces + * - one byte for device mode + * - one byte for vdev id + */ + buf = (char *) ((char *)aniHdr + sizeof(tAniMsgHdr)); + numInterfaces = buf++; + *numInterfaces = 0; + + /* Iterate through each of the adapters and fill device mode and vdev id */ + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while ((VOS_STATUS_SUCCESS == status) && pAdapterNode) + { + pAdapter = pAdapterNode->pAdapter; + if (pAdapter) + { + deviceMode = buf++; + vdevId = buf++; + *deviceMode = pAdapter->device_mode; + *vdevId = pAdapter->sessionId; + (*numInterfaces)++; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: numInterfaces: %d, deviceMode: %d, vdevId: %d", + __func__, *numInterfaces, *deviceMode, *vdevId); + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + aniHdr->length = sizeof(tANI_U8) + (*numInterfaces) * 2 * sizeof(tANI_U8); + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length)); + + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sending App Reg Response length (%d) to process pid (%d)", + __func__, aniHdr->length, pHddCtx->oem_pid); + + (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT); + + return; +} + +/**--------------------------------------------------------------------------- + + \brief send_oem_err_rsp_nlink_msg() - send oem error response + + This function sends error response to oem app + + \param - + - app_pid - PID of oem application process + + \return - none + + --------------------------------------------------------------------------*/ +static void send_oem_err_rsp_nlink_msg(v_SINT_t app_pid, tANI_U8 error_code) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tANI_U8 *buf; + + skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL); + if (skb == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_OEM; + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = ANI_MSG_OEM_ERROR; + aniHdr->length = sizeof(tANI_U8); + nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + aniHdr->length); + + /* message body will contain one byte of error code */ + buf = (char *) ((char *) aniHdr + sizeof(tAniMsgHdr)); + *buf = error_code; + + skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + aniHdr->length)); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sending oem error response to process pid (%d)", + __func__, app_pid); + + (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT); + + return; +} + +/**--------------------------------------------------------------------------- + + \brief send_oem_data_rsp_msg() - send oem data response + + This function sends oem data rsp message to registered application process + over the netlink socket. + + \param - + - oemDataRsp - Pointer to OEM Data Response struct + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +void send_oem_data_rsp_msg(int length, tANI_U8 *oemDataRsp) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tANI_U8 *oemData; + + /* OEM message is always to a specific process and cannot be a broadcast */ + if (pHddCtx->oem_pid == 0) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid dest pid", __func__); + return; + } + + if (length > OEM_DATA_RSP_SIZE) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid length of Oem Data response", __func__); + return; + } + + skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + OEM_DATA_RSP_SIZE), + GFP_KERNEL); + if (skb == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_OEM; + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = ANI_MSG_OEM_DATA_RSP; + + aniHdr->length = length; + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length)); + oemData = (tANI_U8 *) ((char *)aniHdr + sizeof(tAniMsgHdr)); + vos_mem_copy(oemData, oemDataRsp, length); + + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sending Oem Data Response of len (%d) to process pid (%d)", + __func__, length, pHddCtx->oem_pid); + + (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT); + + return; +} + +/**--------------------------------------------------------------------------- + + \brief oem_process_data_req_msg() - process oem data request + + This function sends oem message to SME + + \param - + - oemDataLen - Length to OEM Data buffer + - oemData - Pointer to OEM Data buffer + + \return - eHalStatus enumeration + + --------------------------------------------------------------------------*/ +static eHalStatus oem_process_data_req_msg(int oemDataLen, char *oemData) +{ + hdd_adapter_t *pAdapter = NULL; + tOemDataReqConfig oemDataReqConfig; + tANI_U32 oemDataReqID = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + + /* for now, STA interface only */ + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (!pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: No adapter for STA mode", __func__); + return eHAL_STATUS_FAILURE; + } + + if (!oemData) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: oemData is null", __func__); + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig)); + + vos_mem_copy((&oemDataReqConfig)->oemDataReq, oemData, oemDataLen); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: calling sme_OemDataReq", __func__); + + status = sme_OemDataReq(pHddCtx->hHal, + pAdapter->sessionId, + &oemDataReqConfig, + &oemDataReqID); + return status; +} + +/**--------------------------------------------------------------------------- + + \brief oem_process_channel_info_req_msg() - process oem channel_info request + + This function responds with channel info to oem process + + \param - + - numOfChannels - number of channels + - chanList - channel list + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tHddChannelInfo *pHddChanInfo; + tHddChannelInfo hddChanInfo; + tANI_U8 chanId; + tANI_U32 reg_info_1; + tANI_U32 reg_info_2; + eHalStatus status = eHAL_STATUS_FAILURE; + int i; + tANI_U8 *buf; + + /* OEM message is always to a specific process and cannot be a broadcast */ + if (pHddCtx->oem_pid == 0) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: invalid dest pid", __func__); + return -1; + } + + skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(tANI_U8) + + numOfChannels * sizeof(tHddChannelInfo)), GFP_KERNEL); + if (skb == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return -1; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_OEM; + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = ANI_MSG_CHANNEL_INFO_RSP; + + aniHdr->length = sizeof(tANI_U8) + numOfChannels * sizeof(tHddChannelInfo); + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length)); + + /* First byte of message body will have num of channels */ + buf = (char *) ((char *)aniHdr + sizeof(tAniMsgHdr)); + *buf++ = numOfChannels; + + /* Next follows channel info struct for each channel id. + * If chan id is wrong or SME returns failure for a channel + * then fill in 0 in channel info for that particular channel + */ + for (i = 0 ; i < numOfChannels; i++) + { + pHddChanInfo = (tHddChannelInfo *) ((char *) buf + + i * sizeof(tHddChannelInfo)); + + chanId = chanList[i]; + status = sme_getRegInfo(pHddCtx->hHal, chanId, + ®_info_1, ®_info_2); + if (eHAL_STATUS_SUCCESS == status) + { + /* band center freq1, and freq2 depends on peer's capability + * and at this time we might not be associated on the given channel, + * so fill freq1=mhz, and freq2=0 + */ + hddChanInfo.chan_id = chanId; + hddChanInfo.reserved0 = 0; + hddChanInfo.mhz = vos_chan_to_freq(chanId); + hddChanInfo.band_center_freq1 = hddChanInfo.mhz; + hddChanInfo.band_center_freq2 = 0; + + /* set only DFS flag in info, rest of the fields will be filled in + * by the OEM App + */ + hddChanInfo.info = 0; + if (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(chanId)) + WMI_SET_CHANNEL_FLAG(&hddChanInfo, WMI_CHAN_FLAG_DFS); + + hddChanInfo.reg_info_1 = reg_info_1; + hddChanInfo.reg_info_2 = reg_info_2; + } + else + { + /* chanId passed to sme_getRegInfo is not valid, fill in zeros + * in channel info struct + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_getRegInfo failed for chan (%d), return info 0", + __func__, chanId); + hddChanInfo.chan_id = chanId; + hddChanInfo.reserved0 = 0; + hddChanInfo.mhz = 0; + hddChanInfo.band_center_freq1 = 0; + hddChanInfo.band_center_freq2 = 0; + hddChanInfo.info = 0; + hddChanInfo.reg_info_1 = 0; + hddChanInfo.reg_info_2 = 0; + } + vos_mem_copy(pHddChanInfo, &hddChanInfo, sizeof(tHddChannelInfo)); + } + + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sending channel info resp for num channels (%d) to pid (%d)", + __func__, numOfChannels, pHddCtx->oem_pid); + + (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT); + + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_SendPeerStatusIndToOemApp() + + This function sends peer status indication to registered oem application + + \param - + - peerMac : MAC address of peer + - peerStatus : ePeerConnected or ePeerDisconnected + - peerTimingMeasCap : 0: RTT/RTT2, 1: RTT3. Default is 0 + - sessionId : SME session id, i.e. vdev_id + - chanId: operating channel id + + \return - None + + --------------------------------------------------------------------------*/ +void hdd_SendPeerStatusIndToOemApp(v_MACADDR_t *peerMac, + tANI_U8 peerStatus, + tANI_U8 peerTimingMeasCap, + tANI_U8 sessionId, + tSirSmeChanInfo *chan_info) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tPeerStatusInfo *pPeerInfo; + + + if (!pHddCtx || !pHddCtx->hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Either HDD Ctx is null or Hal Ctx is null", __func__); + return; + } + + /* check if oem app has registered and pid is valid */ + if ((!pHddCtx->oem_app_registered) || (pHddCtx->oem_pid == 0)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: OEM app is not registered(%d) or pid is invalid(%d)", + __func__, pHddCtx->oem_app_registered, pHddCtx->oem_pid); + return; + } + + skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(tPeerStatusInfo)), + GFP_KERNEL); + if (skb == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_OEM; + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = ANI_MSG_PEER_STATUS_IND; + + aniHdr->length = sizeof(tPeerStatusInfo); + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length)); + + pPeerInfo = (tPeerStatusInfo *) ((char *)aniHdr + sizeof(tAniMsgHdr)); + + vos_mem_copy(pPeerInfo->peer_mac_addr, peerMac->bytes, + sizeof(peerMac->bytes)); + pPeerInfo->peer_status = peerStatus; + pPeerInfo->vdev_id = sessionId; + /* peerTimingMeasCap - bit mask for timing and fine timing Meas Cap */ + pPeerInfo->peer_capability = peerTimingMeasCap; + pPeerInfo->reserved0 = 0; + + if (chan_info) { + pPeerInfo->peer_chan_info.chan_id = chan_info->chan_id; + pPeerInfo->peer_chan_info.reserved0 = 0; + pPeerInfo->peer_chan_info.mhz = chan_info->mhz; + pPeerInfo->peer_chan_info.band_center_freq1 = + chan_info->band_center_freq1; + pPeerInfo->peer_chan_info.band_center_freq2 = + chan_info->band_center_freq2; + pPeerInfo->peer_chan_info.info = chan_info->info; + pPeerInfo->peer_chan_info.reg_info_1 = chan_info->reg_info_1; + pPeerInfo->peer_chan_info.reg_info_2 = chan_info->reg_info_2; + } else { + pPeerInfo->peer_chan_info.chan_id = 0; + pPeerInfo->peer_chan_info.reserved0 = 0; + pPeerInfo->peer_chan_info.mhz = 0; + pPeerInfo->peer_chan_info.band_center_freq1 = 0; + pPeerInfo->peer_chan_info.band_center_freq2 = 0; + pPeerInfo->peer_chan_info.info = 0; + pPeerInfo->peer_chan_info.reg_info_1 = 0; + pPeerInfo->peer_chan_info.reg_info_2 = 0; + } + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sending peer "MAC_ADDRESS_STR + " status(%d), peerTimingMeasCap(%d), vdevId(%d), chanId(%d)" + " to oem app pid(%d), center freq 1 (%d), center freq 2 (%d)," + " info (0x%x), frequency (%d),reg info 1 (0x%x)," + " reg info 2 (0x%x)",__func__, MAC_ADDR_ARRAY(peerMac->bytes), + peerStatus, peerTimingMeasCap, sessionId, + pPeerInfo->peer_chan_info.chan_id, pHddCtx->oem_pid, + pPeerInfo->peer_chan_info.band_center_freq1, + pPeerInfo->peer_chan_info.band_center_freq2, + pPeerInfo->peer_chan_info.info, + pPeerInfo->peer_chan_info.mhz, + pPeerInfo->peer_chan_info.reg_info_1, + pPeerInfo->peer_chan_info.reg_info_2); + + (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT); + + return; +} + +/* + * Callback function invoked by Netlink service for all netlink + * messages (from user space) addressed to WLAN_NL_MSG_OEM + */ + +/** + * oem_msg_callback() - callback invoked by netlink service + * @skb: skb with netlink message + * + * This function gets invoked by netlink service when a message + * is received from user space addressed to WLAN_NL_MSG_OEM + * + * Return: zero on success + * On error, error number will be returned. + */ +static int oem_msg_callback(struct sk_buff *skb) +{ + struct nlmsghdr *nlh; + tAniMsgHdr *msg_hdr; + int ret; + char *sign_str = NULL; + nlh = (struct nlmsghdr *)skb->data; + + if (!nlh) { + hddLog(LOGE, FL("Netlink header null")); + return -EPERM; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + msg_hdr = NLMSG_DATA(nlh); + + if (!msg_hdr) { + hddLog(LOGE, FL("Message header null")); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, OEM_ERR_NULL_MESSAGE_HEADER); + return -EPERM; + } + + if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr) + msg_hdr->length)) { + hddLog(LOGE, FL("Invalid nl msg len, nlh->nlmsg_len (%d), msg_hdr->len (%d)"), + nlh->nlmsg_len, msg_hdr->length); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_INVALID_MESSAGE_LENGTH); + return -EPERM; + } + + switch (msg_hdr->type) { + case ANI_MSG_APP_REG_REQ: + /* Registration request is only allowed for Qualcomm Application */ + hddLog(LOG1, FL("Received App Req Req from App process pid(%d), len(%d)"), + nlh->nlmsg_pid, msg_hdr->length); + + sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr)); + if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) && + (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR, + OEM_APP_SIGNATURE_LEN))) { + hddLog(LOG1, FL("Valid App Req Req from oem app process pid(%d)"), + nlh->nlmsg_pid); + + pHddCtx->oem_app_registered = TRUE; + pHddCtx->oem_pid = nlh->nlmsg_pid; + send_oem_reg_rsp_nlink_msg(); + } else { + hddLog(LOGE, FL("Invalid signature in App Reg Request from pid(%d)"), + nlh->nlmsg_pid); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_INVALID_SIGNATURE); + return -EPERM; + } + break; + + case ANI_MSG_OEM_DATA_REQ: + hddLog(LOG1, FL("Received Oem Data Request length(%d) from pid: %d"), + msg_hdr->length, nlh->nlmsg_pid); + + if ((!pHddCtx->oem_app_registered) || + (nlh->nlmsg_pid != pHddCtx->oem_pid)) { + /* either oem app is not registered yet or pid is different */ + hddLog(LOGE, FL("OEM DataReq: app not registered(%d) or incorrect pid(%d)"), + pHddCtx->oem_app_registered, nlh->nlmsg_pid); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_APP_NOT_REGISTERED); + return -EPERM; + } + + if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) { + hddLog(LOGE, FL("Invalid length (%d) in Oem Data Request"), + msg_hdr->length); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_INVALID_MESSAGE_LENGTH); + return -EPERM; + } + oem_process_data_req_msg(msg_hdr->length, + (char *) ((char *)msg_hdr + + sizeof(tAniMsgHdr))); + break; + + case ANI_MSG_CHANNEL_INFO_REQ: + hddLog(LOG1, + FL("Received channel info request, num channel(%d) from pid: %d"), + msg_hdr->length, nlh->nlmsg_pid); + + if ((!pHddCtx->oem_app_registered) || + (nlh->nlmsg_pid != pHddCtx->oem_pid)) { + /* either oem app is not registered yet or pid is different */ + hddLog(LOGE, + FL("Chan InfoReq: app not registered(%d) or incorrect pid(%d)"), + pHddCtx->oem_app_registered, nlh->nlmsg_pid); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_APP_NOT_REGISTERED); + return -EPERM; + } + + /* message length contains list of channel ids */ + if ((!msg_hdr->length) || + (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) { + hddLog(LOGE, + FL("Invalid length (%d) in channel info request"), + msg_hdr->length); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_INVALID_MESSAGE_LENGTH); + return -EPERM; + } + oem_process_channel_info_req_msg(msg_hdr->length, + (char *)((char*)msg_hdr + sizeof(tAniMsgHdr))); + break; + + default: + hddLog(LOGE, + FL("Received Invalid message type (%d), length (%d)"), + msg_hdr->type, msg_hdr->length); + send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, + OEM_ERR_INVALID_MESSAGE_TYPE); + return -EPERM; + } + return 0; +} + +static int __oem_msg_callback(struct sk_buff *skb) +{ + int ret; + + vos_ssr_protect(__func__); + ret = oem_msg_callback(skb); + vos_ssr_unprotect(__func__); + + return ret; +} + +/**--------------------------------------------------------------------------- + + \brief oem_activate_service() - Activate oem message handler + + This function registers a handler to receive netlink message from + an OEM application process. + + \param - + - pAdapter - pointer to HDD adapter + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +int oem_activate_service(void *pAdapter) +{ + pHddCtx = (struct hdd_context_s*) pAdapter; + + /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */ + nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback); + return 0; +} + + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c new file mode 100644 index 000000000000..81e457f249fa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c @@ -0,0 +1,2828 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_p2p.c + + \brief WLAN Host Device Driver implementation for P2P commands interface + + ========================================================================*/ + +#include +#include +#include +#include "sme_Api.h" +#include "sme_QosApi.h" +#include "wlan_hdd_p2p.h" +#include "sapApi.h" +#include "wlan_hdd_main.h" +#include "vos_trace.h" +#include +#include +#include +#include +#include "wlan_hdd_tdls.h" +#include "wlan_hdd_trace.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "vos_sched.h" + +//Ms to Micro Sec +#define MS_TO_MUS(x) ((x)*1000) + +static tANI_U8* hdd_getActionString(tANI_U16 MsgType) +{ + switch (MsgType) + { + CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT); + CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT); + CASE_RETURN_STRING(SIR_MAC_ACTION_DLP); + CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK); + CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE); + CASE_RETURN_STRING(SIR_MAC_ACTION_RRM); + CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST); + CASE_RETURN_STRING(SIR_MAC_ACTION_HT); + CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY); + CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB); + CASE_RETURN_STRING(SIR_MAC_ACTION_WNM); + CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM); + CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS); + CASE_RETURN_STRING(SIR_MAC_ACITON_MESH); + CASE_RETURN_STRING(SIR_MAC_ACTION_MHF); + CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED); + CASE_RETURN_STRING(SIR_MAC_ACTION_WME); + CASE_RETURN_STRING(SIR_MAC_ACTION_VHT); + default: + return ("UNKNOWN"); + } +} + +#ifdef WLAN_FEATURE_P2P_DEBUG +#define MAX_P2P_ACTION_FRAME_TYPE 9 +const char *p2p_action_frame_type[]={"GO Negotiation Request", + "GO Negotiation Response", + "GO Negotiation Confirmation", + "P2P Invitation Request", + "P2P Invitation Response", + "Device Discoverability Request", + "Device Discoverability Response", + "Provision Discovery Request", + "Provision Discovery Response"}; + +/* We no need to protect this variable since + * there is no chance of race to condition + * and also not make any complicating the code + * just for debugging log + */ +tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE; + +#endif +#define MAX_TDLS_ACTION_FRAME_TYPE 11 +const char *tdls_action_frame_type[] = {"TDLS Setup Request", + "TDLS Setup Response", + "TDLS Setup Confirm", + "TDLS Teardown", + "TDLS Peer Traffic Indication", + "TDLS Channel Switch Request", + "TDLS Channel Switch Response", + "TDLS Peer PSM Request", + "TDLS Peer PSM Response", + "TDLS Peer Traffic Response", + "TDLS Discovery Request" }; + +extern struct net_device_ops net_ops_struct; + +static bool wlan_hdd_is_type_p2p_action( const u8 *buf ) +{ + const u8 *ouiPtr; + + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] != + WLAN_HDD_PUBLIC_ACTION_FRAME ) { + return FALSE; + } + + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] != + WLAN_HDD_VENDOR_SPECIFIC_ACTION ) { + return FALSE; + } + + ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET]; + + if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) { + return FALSE; + } + + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] != + WLAN_HDD_WFA_P2P_OUI_TYPE ) { + return FALSE; + } + + return TRUE; +} + +static bool hdd_p2p_is_action_type_rsp( const u8 *buf ) +{ + tActionFrmType actionFrmType; + + if ( wlan_hdd_is_type_p2p_action(buf) ) + { + actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET]; + if ( actionFrmType != WLAN_HDD_INVITATION_REQ && + actionFrmType != WLAN_HDD_GO_NEG_REQ && + actionFrmType != WLAN_HDD_DEV_DIS_REQ && + actionFrmType != WLAN_HDD_PROV_DIS_REQ ) + return TRUE; + } + + return FALSE; +} + +static eHalStatus +wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, + eHalStatus status) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx; + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("Invalid HDD context")); + return eHAL_STATUS_FAILURE; + } + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + + if( pRemainChanCtx == NULL ) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog( LOGW, + "%s: No Rem on channel pending for which Rsp is received", __func__); + return eHAL_STATUS_SUCCESS; + } + + hddLog( LOG1, "Received remain on channel rsp"); + vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer); + vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer); + + cfgState->remain_on_chan_ctx = NULL; + /* + * Resetting the roc in progress early ensures that the subsequent + * roc requests are immediately processed without being queued + */ + pAdapter->is_roc_inprogress = false; + vos_runtime_pm_allow_suspend(hdd_ctx->runtime_context.roc); + /* + * If the allow suspend is done later, the scheduled roc wil prevent + * the system from going into suspend and immediately this logic + * will allow the system to go to suspend breaking the exising logic. + * Basically, the system must not go into suspend while roc is in progress. + */ + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) + { + if( cfgState->buf ) + { + hddLog( LOG1, + "%s: We need to receive yet an ack from one of tx packet", + __func__); + } + cfg80211_remain_on_channel_expired( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + pRemainChanCtx->dev->ieee80211_ptr, +#else + pRemainChanCtx->dev, +#endif + pRemainChanCtx->cookie, + &pRemainChanCtx->chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + pRemainChanCtx->chan_type, +#endif + GFP_KERNEL); + pAdapter->lastRocTs = vos_timer_get_system_time(); + } + + /* Schedule any pending RoC: Any new roc request during this time + * would have got queued in 'wlan_hdd_request_remain_on_channel' + * since the queue is not empty. So, the roc at the head of the + * queue will only get the priority. Scheduling the work queue + * after sending any cancel remain on channel event will also + * ensure that the cancel roc is sent without any delays. + */ + schedule_delayed_work(&hdd_ctx->rocReqWork, 0); + + if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) + ) + { + tANI_U8 sessionId = pAdapter->sessionId; + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) + { + sme_DeregisterMgmtFrame( + hHal, sessionId, + (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4), + NULL, 0 ); + } + } + else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) || + ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) + ) + { + WLANSAP_DeRegisterMgmtFrame( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, +#endif + (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4), + NULL, 0 ); + + } + + if(pRemainChanCtx->action_pkt_buff.frame_ptr != NULL + && pRemainChanCtx->action_pkt_buff.frame_length != 0 ) + { + vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr); + pRemainChanCtx->action_pkt_buff.frame_ptr = NULL; + pRemainChanCtx->action_pkt_buff.frame_length = 0; + } + vos_mem_free( pRemainChanCtx ); + complete(&pAdapter->cancel_rem_on_chan_var); + if (eHAL_STATUS_SUCCESS != status) + complete(&pAdapter->rem_on_chan_ready_event); + return eHAL_STATUS_SUCCESS; +} + +void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter) +{ + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + unsigned long rc; + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + if(cfgState->remain_on_chan_ctx != NULL) + { + hddLog(LOGE, "Cancel Existing Remain on Channel"); + + if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState( + &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer)) + vos_timer_stop(&cfgState->remain_on_chan_ctx-> + hdd_remain_on_chan_timer); + + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(LOGE, + "ROC timer cancellation in progress," + " wait for completion"); + rc = wait_for_completion_timeout(&pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + if (!rc) { + hddLog(LOGE, + "%s:wait on cancel_rem_on_chan_var timed out", + __func__); + } + return; + } + pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + /* Wait till remain on channel ready indication before issuing cancel + * remain on channel request, otherwise if remain on channel not + * received and if the driver issues cancel remain on channel then lim + * will be in unknown state. + */ + rc = wait_for_completion_timeout(&pAdapter->rem_on_chan_ready_event, + msecs_to_jiffies(WAIT_REM_CHAN_READY)); + if (!rc) { + hddLog( LOGE, + "%s: timeout waiting for remain on channel ready indication", + __func__); + } + + INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); + + /* Issue abort remain on chan request to sme. + * The remain on channel callback will make sure the remain_on_chan + * expired event is sent. + */ + if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) + ) + { + sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ), + pAdapter->sessionId ); + } + else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) + { + WLANSAP_CancelRemainOnChannel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter)); +#else + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); +#endif + } + + rc = wait_for_completion_timeout(&pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + + if (!rc) { + hddLog( LOGE, + "%s: timeout waiting for cancel remain on channel ready" + " indication", + __func__); + } + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.roc); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + } else + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); +} + +int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter) +{ + int status = 0; + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + + if(WLAN_HDD_P2P_GO != pAdapter->device_mode) + { + //Cancel Existing Remain On Channel + //If no action frame is pending + if( cfgState->remain_on_chan_ctx != NULL) + { + //Check whether Action Frame is pending or not + if( cfgState->buf == NULL) + { + wlan_hdd_cancel_existing_remain_on_channel(pAdapter); + } + else + { + hddLog( LOG1, "Cannot Cancel Existing Remain on Channel"); + status = -EBUSY; + } + } + } + return status; +} +/* Clean up RoC context at hdd_stop_adapter*/ +void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter) +{ + unsigned long rc; + v_U8_t retry = 0; + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter); + hdd_remain_on_chan_ctx_t *roc_ctx; + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + while (pAdapter->is_roc_inprogress) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: ROC in progress for session %d!!!", + __func__, pAdapter->sessionId); + msleep(500); + if (retry++ > 3) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: ROC completion is not received.!!!", __func__); + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + roc_ctx = cfgState->remain_on_chan_ctx; + if (roc_ctx->hdd_remain_on_chan_cancel_in_progress == true) { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(LOG1, FL("roc cancel already in progress")); + /* + * Since a cancel roc is already issued and is + * in progress, we need not send another + * cancel roc again. Instead we can just wait + * for cancel roc completion + */ + goto wait; + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + if (pAdapter->device_mode == WLAN_HDD_P2P_GO) + { + WLANSAP_CancelRemainOnChannel( + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + } else if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT || + pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) + { + sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + } +wait: + rc = wait_for_completion_timeout(&pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + if (!rc) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout occurred while waiting for RoC Cancellation" , + __func__); + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + roc_ctx = cfgState->remain_on_chan_ctx; + if (roc_ctx != NULL) + { + cfgState->remain_on_chan_ctx = NULL; + vos_timer_stop(&roc_ctx->hdd_remain_on_chan_timer); + vos_timer_destroy(&roc_ctx->hdd_remain_on_chan_timer); + if (roc_ctx->action_pkt_buff.frame_ptr != NULL + && roc_ctx->action_pkt_buff.frame_length != 0) + { + vos_mem_free(roc_ctx->action_pkt_buff.frame_ptr); + roc_ctx->action_pkt_buff.frame_ptr = NULL; + roc_ctx->action_pkt_buff.frame_length = 0; + } + vos_mem_free(roc_ctx); + pAdapter->is_roc_inprogress = FALSE; + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + } + /* hold the lock before break from the loop */ + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + break; + } + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + } /* end of while */ + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + +} + +void wlan_hdd_remain_on_chan_timeout(void *data) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)data; + hdd_context_t *pHddCtx; + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_cfg80211_state_t *cfgState; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("pAdapter is invalid %p !!!"), pAdapter); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + + if(NULL == pRemainChanCtx) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog( LOGE,"%s: No Remain on channel is pending", __func__); + return; + } + + if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress ) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog( LOGE, FL("Cancellation already in progress")); + return; + } + + pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__); + + if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) + ) + { + sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ), + pAdapter->sessionId ); + } + else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) + { + WLANSAP_CancelRemainOnChannel( + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + } + + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.roc); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); +} + +static int wlan_hdd_execute_remain_on_channel(hdd_adapter_t *pAdapter, + hdd_remain_on_chan_ctx_t *pRemainChanCtx) +{ + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter_temp; + VOS_STATUS status; + v_BOOL_t isGoPresent = VOS_FALSE; + unsigned int duration; + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + if (pAdapter->is_roc_inprogress == TRUE) { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("remain on channel request is in execution")); + return -EBUSY; + } + cfgState->remain_on_chan_ctx = pRemainChanCtx; + cfgState->current_freq = pRemainChanCtx->chan.center_freq; + pAdapter->is_roc_inprogress = TRUE; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + /* Initialize Remain on chan timer */ + vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer, + VOS_TIMER_TYPE_SW, + wlan_hdd_remain_on_chan_timeout, + pAdapter); + if (vos_status != VOS_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Not able to initialize remain_on_chan timer")); + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + cfgState->remain_on_chan_ctx = NULL; + pAdapter->is_roc_inprogress = FALSE; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + vos_mem_free(pRemainChanCtx); + return -EINVAL; + } + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter_temp = pAdapterNode->pAdapter; + if(pAdapter_temp->device_mode == WLAN_HDD_P2P_GO) + { + isGoPresent = VOS_TRUE; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + //Extending duration for proactive extension logic for RoC + duration = pRemainChanCtx->duration; + if (isGoPresent == VOS_TRUE) + duration = P2P_ROC_DURATION_MULTIPLIER_GO_PRESENT * duration; + else + duration = P2P_ROC_DURATION_MULTIPLIER_GO_ABSENT * duration; + + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + vos_runtime_pm_prevent_suspend(pHddCtx->runtime_context.roc); + INIT_COMPLETION(pAdapter->rem_on_chan_ready_event); + + //call sme API to start remain on channel. + if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) + ) + { + tANI_U8 sessionId = pAdapter->sessionId; + //call sme API to start remain on channel. + + if (eHAL_STATUS_SUCCESS != sme_RemainOnChannel( + WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, + pRemainChanCtx->chan.hw_value, duration, + wlan_hdd_remain_on_channel_callback, pAdapter, + (tANI_U8)(pRemainChanCtx->rem_on_chan_request + == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE)) { + hddLog(LOGE, FL("sme_RemainOnChannel returned failure")); + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + cfgState->remain_on_chan_ctx = NULL; + pAdapter->is_roc_inprogress = FALSE; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer); + vos_mem_free(pRemainChanCtx); + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.roc); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + return -EINVAL; + } + + if (REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { + if (eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame( + WLAN_HDD_GET_HAL_CTX(pAdapter), + sessionId, (SIR_MAC_MGMT_FRAME << 2) | + (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0)) + hddLog(LOGE, FL("sme_RegisterMgmtFrame returned failure")); + } + } + else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) || + ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) + ) + { + //call sme API to start remain on channel. + if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, +#endif + pRemainChanCtx->chan.hw_value, duration, + wlan_hdd_remain_on_channel_callback, pAdapter)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANSAP_RemainOnChannel returned fail", __func__); + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + cfgState->remain_on_chan_ctx = NULL; + pAdapter->is_roc_inprogress = FALSE; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer); + vos_mem_free (pRemainChanCtx); + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.roc); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + return -EINVAL; + } + + + if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, +#endif + (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4), + NULL, 0)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__); + WLANSAP_CancelRemainOnChannel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter)); +#else + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); +#endif + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.roc); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + return -EINVAL; + } + + } + return 0; +} + +/** + * wlan_hdd_roc_request_enqueue() - enqueue remain on channel request + * @adapter: Pointer to the adapter + * @remain_chan_ctx: Pointer to the remain on channel context + * + * Return: 0 on success, error number otherwise + */ +static int wlan_hdd_roc_request_enqueue(hdd_adapter_t *adapter, + hdd_remain_on_chan_ctx_t *remain_chan_ctx) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_roc_req_t *hdd_roc_req; + VOS_STATUS status; + + /* + * "Driver is busy" OR "there is already RoC request inside the queue" + * so enqueue this RoC Request and execute sequentially later. + */ + + hdd_roc_req = vos_mem_malloc(sizeof(*hdd_roc_req)); + + if (NULL == hdd_roc_req) { + hddLog(LOGP, FL("malloc failed for roc req context")); + return -ENOMEM; + } + + hdd_roc_req->pAdapter = adapter; + hdd_roc_req->pRemainChanCtx = remain_chan_ctx; + + /* Enqueue this RoC request */ + spin_lock(&hdd_ctx->hdd_roc_req_q.lock); + status = hdd_list_insert_back(&hdd_ctx->hdd_roc_req_q, + &hdd_roc_req->node); + spin_unlock(&hdd_ctx->hdd_roc_req_q.lock); + + if (VOS_STATUS_SUCCESS != status) { + hddLog(LOGP, FL("Not able to enqueue RoC Req context")); + vos_mem_free(hdd_roc_req); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_indicate_roc_drop() - Indicate roc drop to userspace + * @adapter: HDD adapter + * @ctx: Remain on channel context + * + * Send remain on channel ready and cancel event for the queued + * roc that is being dropped. This will ensure that the userspace + * will send more roc requests. If this drop is not indicated to + * userspace, subsequent roc will not be sent to the driver since + * the userspace times out waiting for the remain on channel ready + * event. + * + * Return: None + */ +void wlan_hdd_indicate_roc_drop(hdd_adapter_t *adapter, + hdd_remain_on_chan_ctx_t *ctx) +{ + hddLog(LOG1, FL("indicate roc drop to userspace")); + cfg80211_ready_on_channel( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + adapter->dev->ieee80211_ptr, +#else + adapter->dev, +#endif + (uintptr_t)ctx, + &ctx->chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + ctx->chan_type, +#endif + ctx->duration, GFP_KERNEL); + + cfg80211_remain_on_channel_expired( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + ctx->dev->ieee80211_ptr, +#else + ctx->dev, +#endif + ctx->cookie, + &ctx->chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + ctx->chan_type, +#endif + GFP_KERNEL); +} + +/** + * wlan_hdd_roc_request_dequeue() - dequeue remain on channel request + * @work: Pointer to work queue struct + * + * Return: none + */ +void wlan_hdd_roc_request_dequeue(struct work_struct *work) +{ + VOS_STATUS status; + int ret = 0; + hdd_roc_req_t *hdd_roc_req; + hdd_context_t *hdd_ctx = + container_of(work, hdd_context_t, rocReqWork.work); + + hddLog(LOG1, FL("going to dequeue roc")); + + if (0 != (wlan_hdd_validate_context(hdd_ctx))) + return; + + /* + * The queued roc requests is dequeued and processed one at a time. + * Callback 'wlan_hdd_remain_on_channel_callback' ensures + * that any pending roc in the queue will be scheduled + * on the current roc completion by scheduling the work queue. + */ + spin_lock(&hdd_ctx->hdd_roc_req_q.lock); + if (list_empty(&hdd_ctx->hdd_roc_req_q.anchor)) { + spin_unlock(&hdd_ctx->hdd_roc_req_q.lock); + hddLog(LOG1, FL("list is empty")); + return; + } + status = hdd_list_remove_front(&hdd_ctx->hdd_roc_req_q, + (hdd_list_node_t **) &hdd_roc_req); + spin_unlock(&hdd_ctx->hdd_roc_req_q.lock); + if (VOS_STATUS_SUCCESS != status) { + hddLog(LOG1, FL("unable to remove roc element from list")); + return; + } + ret = wlan_hdd_execute_remain_on_channel( + hdd_roc_req->pAdapter, + hdd_roc_req->pRemainChanCtx); + if (ret == -EBUSY) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("dropping RoC request")); + wlan_hdd_indicate_roc_drop(hdd_roc_req->pAdapter, + hdd_roc_req->pRemainChanCtx); + vos_mem_free(hdd_roc_req->pRemainChanCtx); + } + vos_mem_free(hdd_roc_req); +} + +static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 *cookie, + rem_on_channel_request_type_t request_type ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = NULL; + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + v_BOOL_t isBusy = VOS_FALSE; + v_SIZE_t size = 0; + hdd_adapter_t *sta_adapter; + int ret = 0; + int status = 0; + + ENTER(); + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + hddLog( LOG1, + "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d", + chan->hw_value, chan->center_freq, channel_type, duration ); +#else + hddLog( LOG1, + "chan(hw_val)0x%x chan(centerfreq) %d, duration %d", + chan->hw_value, chan->center_freq, duration ); +#endif + + /* + * When P2P-GO and if we are trying to unload the driver then + * wlan driver is keep on receiving the remain on channel command + * and which is resulting in crash. So not allowing any remain on + * channel requets when Load/Unload is in progress + */ + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx)) { + hddLog(LOGE, FL("Connection is in progress")); + isBusy = VOS_TRUE; + } + + pRemainChanCtx = vos_mem_malloc(sizeof(hdd_remain_on_chan_ctx_t)); + if (NULL == pRemainChanCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: Not able to allocate memory for Channel context", + __func__); + return -ENOMEM; + } + + vos_mem_zero(pRemainChanCtx, sizeof(*pRemainChanCtx)); + vos_mem_copy(&pRemainChanCtx->chan, chan, + sizeof(struct ieee80211_channel)); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + pRemainChanCtx->chan_type = channel_type; +#endif + pRemainChanCtx->duration = duration; + pRemainChanCtx->p2pRemOnChanTimeStamp = vos_timer_get_system_time(); + pRemainChanCtx->dev = dev; + *cookie = (uintptr_t) pRemainChanCtx; + pRemainChanCtx->cookie = *cookie; + pRemainChanCtx->rem_on_chan_request = request_type; + + pRemainChanCtx->action_pkt_buff.freq = 0; + pRemainChanCtx->action_pkt_buff.frame_ptr = NULL; + pRemainChanCtx->action_pkt_buff.frame_length = 0; + pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE; + + if (REMAIN_ON_CHANNEL_REQUEST == request_type) { + sta_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if ((NULL != sta_adapter)&& + hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter))) { + if (pAdapter->lastRocTs !=0 && + ((vos_timer_get_system_time() - pAdapter->lastRocTs ) + < pHddCtx->cfg_ini->p2p_listen_defer_interval)) { + if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION) + pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION; + + wlan_hdd_roc_request_enqueue(pAdapter, pRemainChanCtx); + schedule_delayed_work(&pHddCtx->rocReqWork, + msecs_to_jiffies(pHddCtx->cfg_ini->p2p_listen_defer_interval)); + hddLog(LOG1, "Defer interval is %hu, pAdapter %p", + pHddCtx->cfg_ini->p2p_listen_defer_interval, pAdapter); + return 0; + } + } + } + + /* Check roc_req_Q has pending RoC Request or not */ + hdd_list_size(&(pHddCtx->hdd_roc_req_q), &size); + + if ((isBusy == VOS_FALSE) && (!size)) { + /* Media is free and no RoC request is in queue, execute directly */ + status = wlan_hdd_execute_remain_on_channel(pAdapter, + pRemainChanCtx); + if (status == -EBUSY) { + if (wlan_hdd_roc_request_enqueue(pAdapter, pRemainChanCtx)) { + vos_mem_free(pRemainChanCtx); + return -EAGAIN; + } + } + return 0; + } else { + if (wlan_hdd_roc_request_enqueue(pAdapter, pRemainChanCtx)) { + vos_mem_free(pRemainChanCtx); + return -EAGAIN; + } + } + + /* + * If a connection is not in progress (isBusy), before scheduling + * the work queue it is necessary to check if a roc in in progress + * or not because: if an roc is in progress, the dequeued roc + * that will be processed will be dropped. To ensure that this new + * roc request is not dropped, it is suggested to check if an roc + * is in progress or not. The existing roc completion will provide + * the trigger to dequeue the next roc request. + */ + if (isBusy == VOS_FALSE && pAdapter->is_roc_inprogress == false) { + hddLog(LOG1, FL("scheduling delayed work: no connection/roc active")); + schedule_delayed_work(&pHddCtx->rocReqWork, 0); + } + EXIT(); + return 0; +} + +int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 *cookie ) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct net_device *dev = wdev->netdev; +#endif + hdd_adapter_t *pAdapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_REMAIN_ON_CHANNEL, + pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST)); + ret = wlan_hdd_request_remain_on_channel(wiphy, dev, + chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + channel_type, +#endif + duration, cookie, + REMAIN_ON_CHANNEL_REQUEST); + EXIT(); + return ret; +} + +int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 *cookie ) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + wdev, +#else + dev, +#endif + chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + channel_type, +#endif + duration, cookie); + vos_ssr_unprotect(__func__); + + return ret; +} + + +void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ) +{ + hdd_cfg80211_state_t *cfgState = NULL; + hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL; + VOS_STATUS status; + + if (NULL == pAdapter) + { + hddLog(LOGE, FL("pAdapter is NULL")); + return; + } + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hddLog( LOG1, "Ready on chan ind"); + + pAdapter->startRocTs = vos_timer_get_system_time(); + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if( pRemainChanCtx != NULL ) + { + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_REMAINCHANREADYHANDLER, + pAdapter->sessionId, pRemainChanCtx->duration)); + + // Removing READY_EVENT_PROPOGATE_TIME from current time which gives + // more accurate Remain on Channel start time. + pRemainChanCtx->p2pRemOnChanTimeStamp = + vos_timer_get_system_time() - READY_EVENT_PROPOGATE_TIME; + + //start timer for actual duration + if(VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer)) + { + hddLog( LOGE, "Timer Started before ready event!!!"); + vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer); + } + status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer, + (pRemainChanCtx->duration + COMPLETE_EVENT_PROPOGATE_TIME)); + if (status != VOS_STATUS_SUCCESS) + { + hddLog( LOGE, "%s: Remain on Channel timer start failed", + __func__); + } + + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) + { + cfg80211_ready_on_channel( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + pAdapter->dev->ieee80211_ptr, +#else + pAdapter->dev, +#endif + (uintptr_t)pRemainChanCtx, + &pRemainChanCtx->chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + pRemainChanCtx->chan_type, +#endif + pRemainChanCtx->duration, GFP_KERNEL ); + } + else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request) + { + complete(&pAdapter->offchannel_tx_event); + } + + // Check for cached action frame + if(pRemainChanCtx->action_pkt_buff.frame_length != 0) + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) || defined(WITH_BACKPORTS) + cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, + pRemainChanCtx->action_pkt_buff.freq, 0, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + NL80211_RXMGMT_FLAG_ANSWERED); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) + cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, + pRemainChanCtx->action_pkt_buff.freq, 0, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,pRemainChanCtx->action_pkt_buff.freq, 0, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + GFP_ATOMIC ); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + cfg80211_rx_mgmt( pAdapter->dev, pRemainChanCtx->action_pkt_buff.freq, 0, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + GFP_ATOMIC ); +#else + cfg80211_rx_mgmt( pAdapter->dev, pRemainChanCtx->action_pkt_buff.freq, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + GFP_ATOMIC ); +#endif /* LINUX_VERSION_CODE */ + + vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr); + pRemainChanCtx->action_pkt_buff.frame_length = 0; + pRemainChanCtx->action_pkt_buff.freq = 0; + pRemainChanCtx->action_pkt_buff.frame_ptr = NULL; + } + complete(&pAdapter->rem_on_chan_ready_event); + } + else + { + hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__); + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + return; +} + +int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie ) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct net_device *dev = wdev->netdev; +#endif + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + int status; + unsigned long rc; + hdd_list_node_t *tmp, *q; + hdd_roc_req_t *curr_roc_req; + + ENTER(); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + /* Remove RoC request inside queue */ + spin_lock(&pHddCtx->hdd_roc_req_q.lock); + list_for_each_safe(tmp, q, &pHddCtx->hdd_roc_req_q.anchor) { + curr_roc_req = list_entry(tmp, hdd_roc_req_t, node); + if ((uintptr_t)curr_roc_req->pRemainChanCtx == cookie) { + status = hdd_list_remove_node(&pHddCtx->hdd_roc_req_q, + (hdd_list_node_t*)curr_roc_req); + spin_unlock(&pHddCtx->hdd_roc_req_q.lock); + if (status == VOS_STATUS_SUCCESS) { + vos_mem_free(curr_roc_req->pRemainChanCtx); + vos_mem_free(curr_roc_req); + } + return 0; + } + } + spin_unlock(&pHddCtx->hdd_roc_req_q.lock); + + /* FIXME cancel currently running remain on chan. + * Need to check cookie and cancel accordingly + */ + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if( (cfgState->remain_on_chan_ctx == NULL) || + (cfgState->remain_on_chan_ctx->cookie != cookie) ) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog( LOGE, + "%s: No Remain on channel pending with specified cookie value", + __func__); + return -EINVAL; + } + + if (NULL != cfgState->remain_on_chan_ctx) + { + vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer); + if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog( LOG1, + FL("ROC timer cancellation in progress," + " wait for completion")); + rc = wait_for_completion_timeout( + &pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + if (!rc) { + hddLog( LOGE, + "%s:wait on cancel_rem_on_chan_var timed out", + __func__); + } + return 0; + } + else + pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE; + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + /* wait until remain on channel ready event received + * for already issued remain on channel request */ + rc = wait_for_completion_timeout(&pAdapter->rem_on_chan_ready_event, + msecs_to_jiffies(WAIT_REM_CHAN_READY)); + if (!rc) { + hddLog( LOGE, + "%s: timeout waiting for remain on channel ready indication", + __func__); + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + } + INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); + /* Issue abort remain on chan request to sme. + * The remain on channel callback will make sure the remain_on_chan + * expired event is sent. + */ + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)) { + tANI_U8 sessionId = pAdapter->sessionId; + sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ), + sessionId ); + } else if ((WLAN_HDD_SOFTAP== pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { + WLANSAP_CancelRemainOnChannel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter)); +#else + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); +#endif + + } else { + hddLog(LOGE, FL("Invalid device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return -EIO; + } + rc = wait_for_completion_timeout(&pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + if (!rc) { + hddLog( LOGE, + "%s:wait on cancel_rem_on_chan_var timed out ", __func__); + } + vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.roc); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + EXIT(); + return 0; +} + +int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie ) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + wdev, +#else + dev, +#endif + cookie); + vos_ssr_unprotect(__func__); + + return ret; +} + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) +int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, + bool channel_type_valid, +#endif + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie ) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) +int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie ) +#else +int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, u64 *cookie ) +#endif /* LINUX_VERSION_CODE */ +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct net_device *dev = wdev->netdev; +#endif + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + tANI_U16 extendedWait = 0; + tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); + tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); + tActionFrmType actionFrmType; + bool noack = 0; + int status; + unsigned long rc; + hdd_adapter_t *goAdapter; + uint8_t home_ch = 0; + + ENTER(); + + hddLog(LOG1, FL("wait: %d, offchan: %d"), wait, offchan); + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_ACTION, pAdapter->sessionId, + pAdapter->device_mode )); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hddLog(LOG1, FL("Device_mode %s(%d) type: %d"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, type); + + hddLog(LOG1, FL("category: %d, actionID: %d"), + buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET + + WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET], + buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET + + WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET]); + +#ifdef WLAN_FEATURE_P2P_DEBUG + 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])) + { + actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; + if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA to " + MAC_ADDRESS_STR, actionFrmType, + MAC_ADDR_ARRAY(&buf[WLAN_HDD_80211_FRM_DA_OFFSET])); + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA to " + MAC_ADDRESS_STR, p2p_action_frame_type[actionFrmType], + MAC_ADDR_ARRAY(&buf[WLAN_HDD_80211_FRM_DA_OFFSET])); + if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) && + (globalP2PConnectionStatus == P2P_NOT_ACTIVE) ) + { + globalP2PConnectionStatus = P2P_GO_NEG_PROCESS; + hddLog(LOGE,"[P2P State]Inactive state to " + "GO negotiation progress state"); + } + else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) && + (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) ) + { + globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED; + hddLog(LOGE,"[P2P State]GO nego progress to GO nego" + " completed state"); + } + } + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) || defined(WITH_BACKPORTS) + noack = dont_wait_for_ack; +#endif + + //If the wait is coming as 0 with off channel set + //then set the wait to 200 ms + if (offchan && !wait) + { + wait = ACTION_FRAME_DEFAULT_WAIT; + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + if (cfgState->remain_on_chan_ctx) + { + tANI_U32 current_time = vos_timer_get_system_time(); + int remaining_roc_time = + ((int) cfgState->remain_on_chan_ctx->duration - + (current_time - pAdapter->startRocTs)); + if ( remaining_roc_time > ACTION_FRAME_DEFAULT_WAIT) + wait = remaining_roc_time; + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_PROBE_RSP)) { + /* Drop Probe response recieved from supplicant in sta mode */ + goto err_rem_channel; + } + + //Call sme API to send out a action frame. + // OR can we send it directly through data path?? + // After tx completion send tx status back. + if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) + ) + { + if (type == SIR_MAC_MGMT_FRAME) + { + if (subType == SIR_MAC_MGMT_PROBE_RSP) + { + /* Drop Probe response recieved from supplicant, as for GO and + SAP PE itself sends probe response + */ + goto err_rem_channel; + } + else if ((subType == SIR_MAC_MGMT_DISASSOC) || + (subType == SIR_MAC_MGMT_DEAUTH)) + { + /* During EAP failure or P2P Group Remove supplicant + * is sending del_station command to driver. From + * del_station function, Driver will send deauth frame to + * p2p client. No need to send disassoc frame from here. + * so Drop the frame here and send tx indication back to + * supplicant. + */ + tANI_U8 dstMac[ETH_ALEN] = {0}; + memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Deauth/Disassoc received for STA:" + MAC_ADDRESS_STR, + __func__, + MAC_ADDR_ARRAY(dstMac)); + goto err_rem_channel; + } + } + } + + if( NULL != cfgState->buf ) + { + if ( !noack ) + { + hddLog( LOGE, "(%s):Previous P2P Action frame packet pending", + __func__); + hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter); + } + else + { + hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY", + __func__); + return -EBUSY; + } + } + + if( subType == SIR_MAC_MGMT_ACTION) + { + hddLog( LOG1, "Action frame tx request : %s", + hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET])); + } + + if (pAdapter->device_mode == WLAN_HDD_SOFTAP) { + home_ch = pAdapter->sessionCtx.ap.operatingChannel; + } else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) { + home_ch = pAdapter->sessionCtx.station.conn_info.operationChannel; + } else { + goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO ); + if (goAdapter) + home_ch = goAdapter->sessionCtx.ap.operatingChannel; + } + + if (ieee80211_frequency_to_channel(chan->center_freq) == home_ch) { + /* if adapter is already on requested ch, no need for ROC */ + wait = 0; + hddLog(LOGE, + FL("Adapter already on requested channel. No ROC requested")); + goto send_frame; + } + + if( offchan && wait) + { + int status; + rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX; + // In case of P2P Client mode if we are already + // on the same channel then send the frame directly + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if ((type == SIR_MAC_MGMT_FRAME) && + (subType == SIR_MAC_MGMT_ACTION) && + hdd_p2p_is_action_type_rsp(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET]) && + cfgState->remain_on_chan_ctx && + cfgState->current_freq == chan->center_freq ) + { + if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState( + &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer)) + { + vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer); + status = vos_timer_start(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer, + wait); + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + if(status != VOS_STATUS_SUCCESS) + { + hddLog( LOGE, "%s: Remain on Channel timer start failed", + __func__); + } + goto send_frame; + } else { + + if(pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(VOS_TRACE_LEVEL_INFO, + "action frame tx: waiting for completion of ROC "); + + rc = wait_for_completion_timeout( + &pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + if (!rc) { + hddLog( LOGE, + "%s:wait on cancel_rem_on_chan_var timed out", + __func__); + } + + } else + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + } + } else + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + if((cfgState->remain_on_chan_ctx != NULL) && + (cfgState->current_freq == chan->center_freq) + ) + { + hddLog(LOG1,"action frame: extending the wait time"); + extendedWait = (tANI_U16)wait; + goto send_frame; + } + + INIT_COMPLETION(pAdapter->offchannel_tx_event); + + status = wlan_hdd_request_remain_on_channel(wiphy, dev, + chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + channel_type, +#endif + wait, cookie, + req_type); + if(0 != status) + { + if( (-EBUSY == status) && + (cfgState->current_freq == chan->center_freq) ) + { + goto send_frame; + } + goto err_rem_channel; + } + /* This will extend timer in LIM when sending Any action frame + * It will cover remain on channel timer till next action frame + * in rx direction. + */ + extendedWait = (tANI_U16)wait; + /* Wait for driver to be ready on the requested channel */ + rc = wait_for_completion_timeout( + &pAdapter->offchannel_tx_event, + msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX)); + if(!rc) { + hddLog( LOGE, "wait on offchannel_tx_event timed out"); + goto err_rem_channel; + } + } + else if ( offchan ) + { + /* Check before sending action frame + whether we already remain on channel */ + if(NULL == cfgState->remain_on_chan_ctx) + { + goto err_rem_channel; + } + } + send_frame: + + if(!noack) + { + cfgState->buf = vos_mem_malloc( len ); //buf; + if( cfgState->buf == NULL ) + return -ENOMEM; + + cfgState->len = len; + + vos_mem_copy( cfgState->buf, buf, len); + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + + if( cfgState->remain_on_chan_ctx ) + { + cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie; + *cookie = cfgState->action_cookie; + } + else + { + *cookie = (uintptr_t) cfgState->buf; + cfgState->action_cookie = *cookie; + } + + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + } + + if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) + ) + { + tANI_U8 sessionId = pAdapter->sessionId; + + if ((type == SIR_MAC_MGMT_FRAME) && + (subType == SIR_MAC_MGMT_ACTION) && + (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)) + { + actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; + hddLog(LOG1, "Tx Action Frame %u", actionFrmType); + if (actionFrmType == WLAN_HDD_PROV_DIS_REQ) + { + cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING; + hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING", __func__); + } + else if (actionFrmType == WLAN_HDD_GO_NEG_REQ) + { + cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING; + hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING", __func__); + } + } + + if (eHAL_STATUS_SUCCESS != + sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter), + sessionId, buf, len, extendedWait, noack)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_sendAction returned fail", __func__); + goto err; + } + } + else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) || + ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) + ) + { + if( VOS_STATUS_SUCCESS != +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_SendAction( WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, +#endif + buf, len, 0 ) ) + + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WLANSAP_SendAction returned fail", __func__); + goto err; + } + } + + return 0; +err: + if(!noack) + { + hdd_sendActionCnf( pAdapter, FALSE ); + } + return 0; +err_rem_channel: + *cookie = (uintptr_t)cfgState; + cfg80211_mgmt_tx_status( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + pAdapter->dev->ieee80211_ptr, +#else + pAdapter->dev, +#endif + *cookie, buf, len, FALSE, GFP_KERNEL ); + EXIT(); + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + enum nl80211_channel_type channel_type, + bool channel_type_valid, +#endif + unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie ) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) +int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie ) +#else +int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, u64 *cookie ) +#endif /* LINUX_VERSION_CODE */ +{ + int ret; + + vos_ssr_protect(__func__); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan, + params->wait, params->buf, params->len, + params->no_cck, params->dont_wait_for_ack, + cookie); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + ret = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) && !defined(WITH_BACKPORTS) + channel_type, channel_type_valid, +#endif + wait, buf, len, no_cck, + dont_wait_for_ack, cookie); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) + ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan, + channel_type, channel_type_valid, wait, + buf, len, no_cck, dont_wait_for_ack, cookie); +#else + ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan, + channel_type, channel_type_valid, wait, + buf, len, cookie); +#endif /* LINUX_VERSION_CODE */ + vos_ssr_unprotect(__func__); + + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) +int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + return wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, wdev, cookie); +} +#else +int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, + u64 cookie) +{ + return wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, dev, cookie); +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie); + vos_ssr_unprotect(__func__); + + return ret; +} +#else +int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, + u64 cookie) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter, + hdd_cfg80211_state_t* cfgState, + tANI_BOOLEAN actionSendSuccess ) +{ + struct ieee80211_radiotap_header *rthdr; + unsigned char *pos; + struct sk_buff *skb = cfgState->skb; +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx); +#endif + + /* 2 Byte for TX flags and 1 Byte for Retry count */ + u32 rtHdrLen = sizeof(*rthdr) + 3; + + u8 *data; + + /* We have to return skb with Data starting with MAC header. We have + * copied SKB data starting with MAC header to cfgState->buf. We will pull + * entire skb->len from skb and then we will push cfgState->buf to skb + * */ + if( NULL == skb_pull(skb, skb->len) ) + { + hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len); + kfree_skb(cfgState->skb); + return; + } + + data = skb_push( skb, cfgState->len ); + + if (data == NULL) + { + hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len); + kfree_skb( cfgState->skb ); + return; + } + + memcpy( data, cfgState->buf, cfgState->len ); + + /* send frame to monitor interfaces now */ + if( skb_headroom(skb) < rtHdrLen ) + { + hddLog( LOGE, FL("No headroom for rtap header")); + kfree_skb(cfgState->skb); + return; + } + + rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen ); + + memset( rthdr, 0, rtHdrLen ); + rthdr->it_len = cpu_to_le16( rtHdrLen ); + rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | + (1 << IEEE80211_RADIOTAP_DATA_RETRIES) + ); + + pos = (unsigned char *)( rthdr+1 ); + + // Fill TX flags + *pos = actionSendSuccess; + pos += 2; + + // Fill retry count + *pos = 0; + pos++; + + skb_set_mac_header( skb, 0 ); + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset( skb->cb, 0, sizeof( skb->cb ) ); +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + vos_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, + HDD_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX); +#endif + if (in_interrupt()) + netif_rx( skb ); + else + netif_rx_ni( skb ); + + /* Enable Queues which we have disabled earlier */ + hddLog(LOG1, FL("Enabling queues")); + netif_tx_start_all_queues( pAdapter->dev ); +} + +void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess ) +{ + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + + cfgState->actionFrmState = HDD_IDLE; + + hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess); + if( NULL == cfgState->buf ) + { + return; + } + + /* If skb is NULL it means this packet was received on CFG80211 interface + * else it was received on Monitor interface */ + if( cfgState->skb == NULL ) + { + /* + * buf is the same pointer it passed us to send. Since we are sending + * it through control path, we use different buffers. + * In case of mac80211, they just push it to the skb and pass the same + * data while sending tx ack status. + * */ + cfg80211_mgmt_tx_status( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + pAdapter->dev->ieee80211_ptr, +#else + pAdapter->dev, +#endif + cfgState->action_cookie, + cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL ); + vos_mem_free( cfgState->buf ); + cfgState->buf = NULL; + } + else + { + hdd_adapter_t* pMonAdapter = + hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR ); + if( pMonAdapter == NULL ) + { + hddLog( LOGE, "Not able to get Monitor Adapter"); + cfgState->skb = NULL; + vos_mem_free( cfgState->buf ); + cfgState->buf = NULL; + complete(&pAdapter->tx_action_cnf_event); + return; + } + /* Send TX completion feedback over monitor interface. */ + hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess ); + cfgState->skb = NULL; + vos_mem_free( cfgState->buf ); + cfgState->buf = NULL; + /* Look for the next Mgmt packet to TX */ + hdd_mon_tx_mgmt_pkt(pAdapter); + } + complete(&pAdapter->tx_action_cnf_event); +} + +/** + * hdd_setP2pNoa + * + *FUNCTION: + * This function is called from hdd_hostapd_ioctl function when Driver + * get P2P_SET_NOA command from wpa_supplicant using private ioctl + * + *LOGIC: + * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param dev Pointer to net device structure + * @param command Pointer to command + * + * @return Status + */ + +int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + VOS_STATUS status = VOS_STATUS_SUCCESS; + tP2pPsConfig NoA; + int count, duration, start_time; + char *param; + int ret; + + param = strnchr(command, strlen(command), ' '); + if (param == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: strnchr failed to find delimeter", __func__); + return -EINVAL; + } + param++; + ret = sscanf(param, "%d %d %d", &count, &start_time, &duration); + if (ret != 3) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: P2P_SET GO NoA: fail to read params, ret=%d", + __func__, ret); + return -EINVAL; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: P2P_SET GO NoA: count=%d start_time=%d duration=%d", + __func__, count, start_time, duration); + duration = MS_TO_MUS(duration); + /* PS Selection + * Periodic NoA (2) + * Single NOA (4) + */ + NoA.opp_ps = 0; + NoA.ctWindow = 0; + if (count == 1) + { + NoA.duration = 0; + NoA.single_noa_duration = duration; + NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA; + } + else + { + NoA.duration = duration; + NoA.single_noa_duration = 0; + NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA; + } + NoA.interval = MS_TO_MUS(100); + NoA.count = count; + NoA.sessionid = pAdapter->sessionId; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d " + "interval %d count %d single noa duration %d " + "PsSelection %x", __func__, NoA.opp_ps, + NoA.ctWindow, NoA.duration, NoA.interval, + NoA.count, NoA.single_noa_duration, + NoA.psSelection); + + sme_p2pSetPs(hHal, &NoA); + return status; +} + +/** + * hdd_setP2pOpps + * + *FUNCTION: + * This function is called from hdd_hostapd_ioctl function when Driver + * get P2P_SET_PS command from wpa_supplicant using private ioctl + * + *LOGIC: + * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param dev Pointer to net device structure + * @param command Pointer to command + * + * @return Status + */ + +int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + VOS_STATUS status = VOS_STATUS_SUCCESS; + tP2pPsConfig NoA; + char *param; + int legacy_ps, opp_ps, ctwindow; + int ret; + + param = strnchr(command, strlen(command), ' '); + if (param == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: strnchr failed to find delimiter", __func__); + return -EINVAL; + } + param++; + ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow); + if (ret != 3) { + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: P2P_SET GO PS: fail to read params, ret=%d", + __func__, ret); + return -EINVAL; + } + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d", + __func__, legacy_ps, opp_ps, ctwindow); + + /* PS Selection + * Opportunistic Power Save (1) + */ + + /* From wpa_cli user need to use separate command to set ctWindow and Opps + * When user want to set ctWindow during that time other parameters + * values are coming from wpa_supplicant as -1. + * Example : User want to set ctWindow with 30 then wpa_cli command : + * P2P_SET ctwindow 30 + * Command Received at hdd_hostapd_ioctl is as below: + * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30) + */ + if (ctwindow != -1) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Opportunistic Power Save is %s", + (TRUE == pAdapter->ops) ? "Enable" : "Disable" ); + + if (ctwindow != pAdapter->ctw) + { + pAdapter->ctw = ctwindow; + + if(pAdapter->ops) + { + NoA.opp_ps = pAdapter->ops; + NoA.ctWindow = pAdapter->ctw; + NoA.duration = 0; + NoA.single_noa_duration = 0; + NoA.interval = 0; + NoA.count = 0; + NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC; + NoA.sessionid = pAdapter->sessionId; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d " + "interval %d count %d single noa duration %d " + "PsSelection %x", __func__, NoA.opp_ps, + NoA.ctWindow, NoA.duration, NoA.interval, + NoA.count, NoA.single_noa_duration, + NoA.psSelection); + + sme_p2pSetPs(hHal, &NoA); + } + return 0; + } + } + + if (opp_ps != -1) + { + pAdapter->ops = opp_ps; + + + if ((opp_ps != -1) && (pAdapter->ctw)) + { + NoA.opp_ps = opp_ps; + NoA.ctWindow = pAdapter->ctw; + NoA.duration = 0; + NoA.single_noa_duration = 0; + NoA.interval = 0; + NoA.count = 0; + NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC; + NoA.sessionid = pAdapter->sessionId; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d " + "interval %d count %d single noa duration %d " + "PsSelection %x", __func__, NoA.opp_ps, + NoA.ctWindow, NoA.duration, NoA.interval, + NoA.count, NoA.single_noa_duration, + NoA.psSelection); + + sme_p2pSetPs(hHal, &NoA); + } + } + return status; +} + +int hdd_setP2pPs( struct net_device *dev, void *msgData ) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + VOS_STATUS status = VOS_STATUS_SUCCESS; + tP2pPsConfig NoA; + p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData; + + NoA.opp_ps = pappNoA->opp_ps; + NoA.ctWindow = pappNoA->ctWindow; + NoA.duration = pappNoA->duration; + NoA.interval = pappNoA->interval; + NoA.count = pappNoA->count; + NoA.single_noa_duration = pappNoA->single_noa_duration; + NoA.psSelection = pappNoA->psSelection; + NoA.sessionid = pAdapter->sessionId; + + sme_p2pSetPs(hHal, &NoA); + return status; +} + +static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type ) +{ + tANI_U8 sessionType; + + switch( type ) + { + case NL80211_IFTYPE_AP: + sessionType = WLAN_HDD_SOFTAP; + break; + case NL80211_IFTYPE_P2P_GO: + sessionType = WLAN_HDD_P2P_GO; + break; + case NL80211_IFTYPE_P2P_CLIENT: + sessionType = WLAN_HDD_P2P_CLIENT; + break; + case NL80211_IFTYPE_STATION: + sessionType = WLAN_HDD_INFRA_STATION; + break; + case NL80211_IFTYPE_MONITOR: + sessionType = WLAN_HDD_MONITOR; + break; + default: + sessionType = WLAN_HDD_INFRA_STATION; + break; + } + + return sessionType; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) || defined(WITH_BACKPORTS) +struct wireless_dev* __wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, const char *name, + enum nl80211_iftype type, + u32 *flags, struct vif_params *params ) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +struct wireless_dev* __wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params ) +#else +struct net_device* __wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params ) +#endif +{ + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + hdd_adapter_t* pAdapter = NULL; + hdd_scaninfo_t *scan_info = NULL; + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ERR_PTR(ret); + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return ERR_PTR(-EINVAL); + } + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type)); + /*Allow addition multiple interface for WLAN_HDD_P2P_CLIENT and + WLAN_HDD_SOFTAP session type*/ + if ((hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL) +#ifdef WLAN_FEATURE_MBSSID + && WLAN_HDD_SOFTAP != wlan_hdd_get_session_type(type) +#endif + && WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) + && WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) + ) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. " + "Two interfaces of same type are not supported currently.", + __func__, type); + return ERR_PTR(-EINVAL); + } + + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (pAdapter != NULL) { + scan_info = &pAdapter->scan_info; + if ((scan_info != NULL) && (scan_info->mScanPending)) { + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + hddLog(LOG1, FL("Abort Scan while adding virtual interface")); + } + } + + pAdapter = NULL; + + wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx); + + if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && + ((NL80211_IFTYPE_P2P_GO == type) || + (NL80211_IFTYPE_P2P_CLIENT == type))) + { + /* Generate the P2P Interface Address. this address must be + * different from the P2P Device Address. + */ + v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress; + p2pDeviceAddress.bytes[4] ^= 0x80; + pAdapter = hdd_open_adapter( pHddCtx, + wlan_hdd_get_session_type(type), + name, p2pDeviceAddress.bytes, + VOS_TRUE ); + } + else + { + pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type), + name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE ); + } + + if( NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__); + return ERR_PTR(-ENOSPC); + } + EXIT(); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + return pAdapter->dev->ieee80211_ptr; +#else + return pAdapter->dev; +#endif +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) || defined(WITH_BACKPORTS) +struct wireless_dev* wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, const char *name, + enum nl80211_iftype type, + u32 *flags, struct vif_params *params ) +{ + struct wireless_dev* wdev; + + vos_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); + vos_ssr_unprotect(__func__); + return wdev; +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) +struct wireless_dev* wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params ) +{ + struct wireless_dev* wdev; + + vos_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); + vos_ssr_unprotect(__func__); + return wdev; +} +#else +struct net_device* wlan_hdd_add_virtual_intf( + struct wiphy *wiphy, char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params ) +{ + struct net_device* ndev; + + vos_ssr_protect(__func__); + ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); + vos_ssr_unprotect(__func__); + return ndev; +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) +int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) +#else +int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) +#endif +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + struct net_device *dev = wdev->netdev; +#endif + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int status; + ENTER(); + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, + TRACE_CODE_HDD_DEL_VIRTUAL_INTF, + pAdapter->sessionId, pAdapter->device_mode)); + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pVirtAdapter->device_mode), + pVirtAdapter->device_mode); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + wlan_hdd_release_intf_addr( pHddCtx, + pVirtAdapter->macAddressCurrent.bytes ); + + hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE ); + hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE ); + EXIT(); + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) +int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) +#else +int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) +#endif +{ + int ret; + + vos_ssr_protect(__func__); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS) + ret = __wlan_hdd_del_virtual_intf(wiphy, wdev); +#else + ret = __wlan_hdd_del_virtual_intf(wiphy, dev); +#endif + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * ieee80211_add_rx_radiotap_header - add radiotap header + */ +static int hdd_wlan_add_rx_radiotap_hdr ( + struct sk_buff *skb, int rtap_len, int flag ) +{ + u8 rtap_temp[20] = {0}; + struct ieee80211_radiotap_header *rthdr; + unsigned char *pos; + u16 rx_flags = 0; + + rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]); + + /* radiotap header, set always present flags */ + rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RX_FLAGS)); + rthdr->it_len = cpu_to_le16(rtap_len); + + pos = (unsigned char *) (rthdr + 1); + + /* the order of the following fields is important */ + + /* IEEE80211_RADIOTAP_FLAGS */ + *pos = 0; + pos++; + + /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */ + /* ensure 2 byte alignment for the 2 byte field as required */ + if ((pos - (u8 *)rthdr) & 1) + pos++; + put_unaligned_le16(rx_flags, pos); + pos += 2; + + // actually push the data + memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len); + + return 0; +} + +void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, + tANI_U32 nFrameLength, + tANI_U8* pbFrames, + tANI_U8 frameType ) +{ + //Indicate a Frame over Monitor Intf. + int rxstat; + struct sk_buff *skb = NULL; + int needed_headroom = 0; + int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED | + HDD_RX_FLAG_MMIC_STRIPPED; +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx); +#endif + hddLog( LOG1, FL("Indicate Frame over Monitor Intf")); + + if (NULL == pbFrames) + { + hddLog(LOGE, FL("NULL frame pointer")); + return; + } + + /* room for the radiotap header based on driver features + * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for + * RX flags. + * */ + needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4; + + //alloc skb here + skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC); + if (unlikely(NULL == skb)) + { + hddLog( LOGW, FL("Unable to allocate skb")); + return; + } + skb_reserve(skb, VPKT_SIZE_BUFFER); + if (unlikely(skb_headroom(skb) < nFrameLength)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD [%d]: Insufficient headroom, " + "head[%p], data[%p], req[%d]", + __LINE__, skb->head, skb->data, nFrameLength); + kfree_skb(skb); + return ; + } + // actually push the data + memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength); + /* prepend radiotap information */ + if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) ) + { + hddLog( LOGE, FL("Not Able Add Radio Tap")); + //free skb + kfree_skb(skb); + return ; + } + + skb_reset_mac_header( skb ); + skb->dev = pMonAdapter->dev; + skb->protocol = eth_type_trans( skb, skb->dev ); + skb->ip_summed = CHECKSUM_NONE; +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + vos_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, + HDD_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX); +#endif + rxstat = netif_rx_ni(skb); + if( NET_RX_SUCCESS == rxstat ) + { + hddLog( LOG1, FL("Success")); + } + else + hddLog( LOGE, FL("Failed %d"), rxstat); + + return ; +} + +void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, + tANI_U32 nFrameLength, + tANI_U8* pbFrames, + tANI_U8 frameType, + tANI_U32 rxChan, + tANI_S8 rxRssi ) +{ + tANI_U16 freq; + tANI_U16 extend_time; + tANI_U8 type = 0; + tANI_U8 subType = 0; + tActionFrmType actionFrmType; + hdd_cfg80211_state_t *cfgState = NULL; + VOS_STATUS status; + hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL; + hdd_context_t *pHddCtx; + + hddLog(VOS_TRACE_LEVEL_INFO, FL("Frame Type = %d Frame Length = %d"), + frameType, nFrameLength); + + if (NULL == pAdapter) + { + hddLog(LOGE, FL("pAdapter is NULL")); + return; + } + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 == nFrameLength) + { + hddLog(LOGE, FL("Frame Length is Invalid ZERO")); + return; + } + + if (NULL == pbFrames) + { + hddLog(LOGE, FL("pbFrames is NULL")); + return; + } + + type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]); + subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]); + + /* Get pAdapter from Destination mac address of the frame */ + if ((type == SIR_MAC_MGMT_FRAME) && + (subType != SIR_MAC_MGMT_PROBE_REQ)) + { + pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter), + &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]); + if (NULL == pAdapter) + { + /* Under assumption that we don't receive any action frame + * with BCST as destination we dropping action frame + */ + hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = " + MAC_ADDRESS_STR , + MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET])); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d" + " subType = %d", __func__, frameType, + nFrameLength, subType); + return; + } + } + + + if (NULL == pAdapter->dev) + { + hddLog( LOGE, FL("pAdapter->dev is NULL")); + return; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + hddLog( LOGE, FL("pAdapter has invalid magic")); + return; + } + + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode )) + { + hdd_adapter_t *pMonAdapter = + hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) ); + + if (NULL != pMonAdapter) + { + hddLog( LOG1, FL("Indicate Frame over Monitor Interface")); + hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength, + pbFrames, frameType); + return; + } + } + + //Channel indicated may be wrong. TODO + //Indicate an action frame. + if( rxChan <= MAX_NO_OF_2_4_CHANNELS ) + { + freq = ieee80211_channel_to_frequency( rxChan, + IEEE80211_BAND_2GHZ); + } + else + { + freq = ieee80211_channel_to_frequency( rxChan, + IEEE80211_BAND_5GHZ); + } + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + + if ((type == SIR_MAC_MGMT_FRAME) && + (subType == SIR_MAC_MGMT_ACTION)) + { + if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME) + { + // public action frame + if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) && + vos_mem_compare(&pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+2], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE)) + // P2P action frames + { + u8 *macFrom = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6]; + actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; + hddLog(LOG1, "Rx Action Frame %u", actionFrmType); +#ifdef WLAN_FEATURE_P2P_DEBUG + if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA" + " from " MAC_ADDRESS_STR, actionFrmType, + MAC_ADDR_ARRAY(macFrom)); + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA" + " from " MAC_ADDRESS_STR, + p2p_action_frame_type[actionFrmType], + MAC_ADDR_ARRAY(macFrom)); + if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) && + (globalP2PConnectionStatus == P2P_NOT_ACTIVE) ) + { + globalP2PConnectionStatus = P2P_GO_NEG_PROCESS; + hddLog(LOGE,"[P2P State]Inactive state to " + "GO negotiation progress state"); + } + else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) && + (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) ) + { + globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED; + hddLog(LOGE,"[P2P State]GO negotiation progress to " + "GO negotiation completed state"); + } + else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) && + (globalP2PConnectionStatus == P2P_NOT_ACTIVE) ) + { + globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED; + hddLog(LOGE,"[P2P State]Inactive state to GO negotiation" + " completed state Autonomous GO formation"); + } + } +#endif + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if (pRemainChanCtx != NULL) + { + if(actionFrmType == WLAN_HDD_GO_NEG_REQ || + actionFrmType == WLAN_HDD_GO_NEG_RESP || + actionFrmType == WLAN_HDD_INVITATION_REQ || + actionFrmType == WLAN_HDD_DEV_DIS_REQ || + actionFrmType == WLAN_HDD_PROV_DIS_REQ ) + { + hddLog( LOG1, "Extend RoC timer on reception of Action Frame"); + + if ((actionFrmType == WLAN_HDD_GO_NEG_REQ) + || (actionFrmType == WLAN_HDD_GO_NEG_RESP)) + extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT; + else + extend_time = ACTION_FRAME_DEFAULT_WAIT; + + if(completion_done(&pAdapter->rem_on_chan_ready_event)) + { + if(VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer)) + { + vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer); + status = vos_timer_start( + &pRemainChanCtx->hdd_remain_on_chan_timer, + extend_time); + if (status != VOS_STATUS_SUCCESS) + { + hddLog( LOGE, "%s: Remain on Channel timer start failed", + __func__); + } + } else { + hddLog( LOG1, "%s: Rcvd action frame after timer expired", + __func__); + } + } else { + // Buffer Packet + if(pRemainChanCtx->action_pkt_buff.frame_length == 0) + { + pRemainChanCtx->action_pkt_buff.frame_length = nFrameLength; + pRemainChanCtx->action_pkt_buff.freq = freq; + pRemainChanCtx->action_pkt_buff.frame_ptr + = vos_mem_malloc(nFrameLength); + vos_mem_copy(pRemainChanCtx->action_pkt_buff.frame_ptr, + pbFrames, nFrameLength); + hddLog( LOGE,"%s:" + "Action Pkt Cached successfully !!!", __func__); + } else { + hddLog( LOGE,"%s:" + "Frames are pending. dropping frame !!!", __func__); + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + return; + } + } + } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) && + (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) || + ((actionFrmType == WLAN_HDD_GO_NEG_RESP) && + (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING))) + { + hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ", + __func__); + hdd_sendActionCnf(pAdapter, TRUE); + } + } +#ifdef FEATURE_WLAN_TDLS + else if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP) + { + u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6]; + hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA", + MAC_ADDR_ARRAY(mac),rxRssi); + + wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi); + wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac); + } +#endif + } + if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME) + { + actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1]; + if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE) + { + hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] Action type[%d] <--- OTA", + actionFrmType); + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] %s <--- OTA", + tdls_action_frame_type[actionFrmType]); + } + } + + if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&& + (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) ) + { + sme_UpdateDSCPtoUPMapping(pHddCtx->hHal, + pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId); + } + } + + //Indicate Frame Over Normal Interface + hddLog( LOG1, FL("Indicate Frame over NL80211 Interface")); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) || defined(WITH_BACKPORTS) + cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, 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, + 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, + pbFrames, nFrameLength, + GFP_ATOMIC ); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + cfg80211_rx_mgmt( pAdapter->dev, freq, 0, + pbFrames, nFrameLength, + GFP_ATOMIC ); +#else + cfg80211_rx_mgmt( pAdapter->dev, freq, + pbFrames, nFrameLength, + GFP_ATOMIC ); +#endif /* LINUX_VERSION_CODE */ +} + + diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_scan.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_scan.c new file mode 100644 index 000000000000..83d8871b7a72 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_scan.c @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_scan.c + + \brief WLAN Host Device Driver implementation + + ========================================================================*/ + +/**========================================================================= + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 04/5/09 Shailender Created module. + + ==========================================================================*/ + /* To extract the Scan results */ + +/* Add a stream event */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" +#define WEXT_CSCAN_HEADER_SIZE 12 +#define WEXT_CSCAN_SSID_SECTION 'S' +#define WEXT_CSCAN_CHANNEL_SECTION 'C' +#define WEXT_CSCAN_NPROBE_SECTION 'N' +#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' +#define WEXT_CSCAN_PASV_DWELL_SECTION 'P' +#define WEXT_CSCAN_HOME_DWELL_SECTION 'H' +#define WEXT_CSCAN_TYPE_SECTION 'T' +#define WEXT_CSCAN_PENDING_SECTION 'O' +#define WEXT_CSCAN_TYPE_DEFAULT 0 +#define WEXT_CSCAN_TYPE_PASSIVE 1 +#define WEXT_CSCAN_PASV_DWELL_TIME 130 +#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250 +#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000 +#define WEXT_CSCAN_HOME_DWELL_TIME 130 +#define MAX_RATES 12 + +#define WEXT_CSCAN_SCAN_DONE_WAIT_TIME 2000 + +typedef struct hdd_scan_info{ + struct net_device *dev; + struct iw_request_info *info; + char *start; + char *end; +} hdd_scan_info_t, *hdd_scan_info_tp; + +static v_S31_t hdd_TranslateABGRateToMbpsRate(v_U8_t *pFcRate) +{ + + /** Slightly more sophisticated processing has to take place here. + Basic rates are rounded DOWN. HT rates are rounded UP.*/ + return ( (( ((v_S31_t) *pFcRate) & 0x007f) * 1000000) / 2); +} + + +static eHalStatus hdd_AddIwStreamEvent(int cmd, int length, char* data, hdd_scan_info_t *pscanInfo, char **last_event, char **current_event ) +{ + struct iw_event event; + + *last_event = *current_event; + vos_mem_zero(&event, sizeof (struct iw_event)); + event.cmd = cmd; + event.u.data.flags = 1; + event.u.data.length = length; + *current_event = iwe_stream_add_point (pscanInfo->info,*current_event, pscanInfo->end, &event, data); + + if(*last_event == *current_event) + { + /* no space to add event */ + hddLog( LOGE, "%s: no space left to add event", __func__); + return -E2BIG; /* Error code, may be E2BIG */ + } + + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_GetWPARSNIEs() - + + This function extract the WPA/RSN IE from the Bss descriptor IEs fields + + \param - ieFields - Pointer to the Bss Descriptor IEs. + - ie_length - IE Length. + - last_event -Points to the last event. + - current_event - Points to the + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + + +/* Extract the WPA and/or RSN IEs */ +static eHalStatus hdd_GetWPARSNIEs( v_U8_t *ieFields, v_U16_t ie_length, char **last_event, char **current_event, hdd_scan_info_t *pscanInfo ) +{ + v_U8_t eid, elen, *element; + v_U16_t tie_length=0; + + ENTER(); + + element = ieFields; + tie_length = ie_length; + + while( tie_length > 2 && element != NULL ) + { + eid = element[0]; + elen = element[1]; + + /*If element length is greater than total remaining ie length, + *break the loop*/ + if ((elen+2) > tie_length) + break; + + switch(eid) + { + case DOT11F_EID_WPA: + case DOT11F_EID_RSN: +#ifdef FEATURE_WLAN_WAPI + case DOT11F_EID_WAPI: +#endif + if(hdd_AddIwStreamEvent( IWEVGENIE, elen+2, (char*)element, pscanInfo, last_event, current_event ) < 0 ) + return -E2BIG; + break; + + default: + break; + } + + /* Next element */ + tie_length -= (2 + elen); + element += 2 + elen; + } + + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_IndicateScanResult() - + + This function returns the scan results to the wpa_supplicant + + \param - scanInfo - Pointer to the scan info structure. + - descriptor - Pointer to the Bss Descriptor. + + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +#define MAX_CUSTOM_LEN 64 +static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tSirBssDescription *descriptor = &scan_result->BssDescriptor; + struct iw_event event; + char *current_event = scanInfo->start; + char *end = scanInfo->end; + char *last_event; + char *current_pad; + v_U16_t ie_length = 0; + v_U16_t capabilityInfo; + char *modestr; + int error; + char custom[MAX_CUSTOM_LEN]; + char *p; + + hddLog( LOG1, "hdd_IndicateScanResult " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(descriptor->bssId)); + + error = 0; + last_event = current_event; + vos_mem_zero(&event, sizeof (event)); + + /* BSSID */ + event.cmd = SIOCGIWAP; + event.u.ap_addr.sa_family = ARPHRD_ETHER; + vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId, + sizeof (descriptor->bssId)); + current_event = iwe_stream_add_event(scanInfo->info,current_event, end, + &event, IW_EV_ADDR_LEN); + + if (last_event == current_event) + { + /* no space to add event */ + /* Error code may be E2BIG */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWAP "); + return -E2BIG; + } + + last_event = current_event; + vos_mem_zero(&event, sizeof (struct iw_event)); + + /* Protocol Name */ + event.cmd = SIOCGIWNAME; + + switch (descriptor->nwType) + { + case eSIR_11A_NW_TYPE: + modestr = "a"; + break; + case eSIR_11B_NW_TYPE: + modestr = "b"; + break; + case eSIR_11G_NW_TYPE: + modestr = "g"; + break; + case eSIR_11N_NW_TYPE: + modestr = "n"; + break; + default: + hddLog( LOGW, "%s: Unknown network type [%d]", + __func__, descriptor->nwType); + modestr = "?"; + break; + } + snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr); + current_event = iwe_stream_add_event(scanInfo->info,current_event, end, + &event, IW_EV_CHAR_LEN); + + if (last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWNAME"); + /* Error code, may be E2BIG */ + return -E2BIG; + } + + last_event = current_event; + vos_mem_zero( &event, sizeof (struct iw_event)); + + /*Freq*/ + event.cmd = SIOCGIWFREQ; + + event.u.freq.m = descriptor->channelId; + event.u.freq.e = 0; + event.u.freq.i = 0; + current_event = iwe_stream_add_event(scanInfo->info,current_event, end, + &event, IW_EV_FREQ_LEN); + + if (last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWFREQ"); + return -E2BIG; + } + + last_event = current_event; + vos_mem_zero( &event, sizeof (struct iw_event)); + + /* BSS Mode */ + event.cmd = SIOCGIWMODE; + + capabilityInfo = descriptor->capabilityInfo; + + if (SIR_MAC_GET_ESS(capabilityInfo)) + { + event.u.mode = IW_MODE_MASTER; + } + else if (SIR_MAC_GET_IBSS(capabilityInfo)) + { + event.u.mode = IW_MODE_ADHOC; + } + else + { + /* neither ESS or IBSS */ + event.u.mode = IW_MODE_AUTO; + } + + current_event = iwe_stream_add_event(scanInfo->info,current_event, end, + &event, IW_EV_UINT_LEN); + + if (last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWMODE"); + return -E2BIG; + } + /* To extract SSID */ + ie_length = GET_IE_LEN_IN_BSS( descriptor->length ); + + if (ie_length > 0) + { + /* dot11BeaconIEs is a large struct, so we make it static to + avoid stack overflow. This API is only invoked via ioctl, + so it is serialized by the kernel rtnl_lock and hence does + not need to be reentrant */ + static tDot11fBeaconIEs dot11BeaconIEs; + tDot11fIESSID *pDot11SSID; + tDot11fIESuppRates *pDot11SuppRates; + tDot11fIEExtSuppRates *pDot11ExtSuppRates; + tDot11fIEHTCaps *pDot11IEHTCaps; + int numBasicRates = 0; + int maxNumRates = 0; + + pDot11IEHTCaps = NULL; + + dot11fUnpackBeaconIEs ((tpAniSirGlobal) + hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs); + + pDot11SSID = &dot11BeaconIEs.SSID; + + + if (pDot11SSID->present ) { + last_event = current_event; + vos_mem_zero (&event, sizeof (struct iw_event)); + + event.cmd = SIOCGIWESSID; + event.u.data.flags = 1; + event.u.data.length = scan_result->ssId.length; + current_event = iwe_stream_add_point (scanInfo->info,current_event, end, + &event, (char *)scan_result->ssId.ssId); + + if(last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID"); + return -E2BIG; + } + } + + if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, ¤t_event, scanInfo ) < 0 ) + { + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID"); + return -E2BIG; + } + + last_event = current_event; + current_pad = current_event + IW_EV_LCP_LEN; + vos_mem_zero( &event, sizeof (struct iw_event)); + + /*Rates*/ + event.cmd = SIOCGIWRATE; + + + pDot11SuppRates = &dot11BeaconIEs.SuppRates; + + if (pDot11SuppRates->present ) + { + int i; + + numBasicRates = pDot11SuppRates->num_rates; + for (i=0; inum_rates; i++) + { + if (0 != (pDot11SuppRates->rates[i] & 0x7F)) + { + event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate ( + &pDot11SuppRates->rates[i]); + + current_pad = iwe_stream_add_value (scanInfo->info,current_event, + current_pad, end, &event, IW_EV_PARAM_LEN); + } + } + + } + + pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates; + + if (pDot11ExtSuppRates->present ) + { + int i,no_of_rates; + maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates; + + /* Check to make sure the total number of rates + doesn't exceed IW_MAX_BITRATES */ + + maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES); + + if((maxNumRates - numBasicRates) > MAX_RATES) + { + no_of_rates = MAX_RATES; + hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates "); + } + else + { + no_of_rates = maxNumRates - numBasicRates; + } + for ( i=0; i< no_of_rates ; i++ ) + { + if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F)) + { + event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate ( + &pDot11ExtSuppRates->rates[i]); + + current_pad = iwe_stream_add_value (scanInfo->info,current_event, + current_pad, end, &event, IW_EV_PARAM_LEN); + } + } + } + + + if ((current_pad - current_event) >= IW_EV_LCP_LEN) + { + current_event = current_pad; + } + else + { + if (last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWRATE"); + return -E2BIG; + } + } + + last_event = current_event; + vos_mem_zero (&event, sizeof (struct iw_event)); + + + event.cmd = SIOCGIWENCODE; + + if (SIR_MAC_GET_PRIVACY(capabilityInfo)) + { + event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + } + else + { + event.u.data.flags = IW_ENCODE_DISABLED; + } + event.u.data.length = 0; + + current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid); + + + if(last_event == current_event) + { /* no space to add event + Error code, may be E2BIG */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWENCODE"); + return -E2BIG; + } + } + + last_event = current_event; + vos_mem_zero( &event, sizeof (struct iw_event)); + + /*RSSI*/ + event.cmd = IWEVQUAL; + event.u.qual.qual = descriptor->rssi; + event.u.qual.noise = descriptor->sinr; + + event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0); + + event.u.qual.updated = IW_QUAL_ALL_UPDATED; + + current_event = iwe_stream_add_event(scanInfo->info,current_event, + end, &event, IW_EV_QUAL_LEN); + + if(last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVQUAL"); + return -E2BIG; + } + + + /* AGE */ + event.cmd = IWEVCUSTOM; + p = custom; + p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu", + vos_timer_get_system_ticks() - descriptor->nReceivedTime); + event.u.data.length = p - custom; + current_event = iwe_stream_add_point (scanInfo->info,current_event, end, + &event, custom); + if(last_event == current_event) + { /* no space to add event */ + hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)"); + return -E2BIG; + } + + scanInfo->start = current_event; + + return 0; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_ScanRequestCallback() - + + The sme module calls this callback function once it finish the scan request + and this function notifies the scan complete event to the wpa_supplicant. + + \param - halHandle - Pointer to the Hal Handle. + - pContext - Pointer to the data context. + - sessionId - Session identifier + - scanId - Scan ID. + - status - CSR Status. + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +static eHalStatus hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext, + tANI_U8 sessionId, tANI_U32 scanId, + eCsrScanStatus status) +{ + struct net_device *dev = (struct net_device *) pContext; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; + union iwreq_data wrqu; + int we_event; + char *msg; + + ENTER(); + + hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d," + " returned status = %d", __func__, halHandle, pContext, + (int) scanId, (int) status); + + /* if there is a scan request pending when the wlan driver is unloaded + we may be invoked as SME flushes its pending queue. If that is the + case, the underlying net_device may have already been destroyed, so + do some quick sanity before proceeding */ + if (pAdapter->dev != dev) + { + hddLog(LOGW, "%s: device mismatch %p vs %p", + __func__, pAdapter->dev, dev); + return eHAL_STATUS_SUCCESS; + } + + /* Check the scanId */ + if (pAdapter->scan_info.scanId != scanId) + { + hddLog(LOGW, "%s called with mismatched scanId pHddCtx->scan_info.scanId = %d " + "scanId = %d ", __func__, (int) pAdapter->scan_info.scanId, + (int) scanId); + } + + /* Scan is no longer pending */ + pAdapter->scan_info.mScanPending = VOS_FALSE; + + // notify any applications that may be interested + memset(&wrqu, '\0', sizeof(wrqu)); + we_event = SIOCGIWSCAN; + msg = NULL; + wireless_send_event(dev, we_event, &wrqu, msg); + + EXIT(); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__); + + return eHAL_STATUS_SUCCESS; +} + +/** + * __iw_set_scan() - set scan request + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * This function process the scan request from the wpa_supplicant + * and set the scan request to the SME + * + * Return: 0 on success, error number otherwise + */ +static int __iw_set_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrScanRequest scanRequest; + v_U32_t scanId = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + struct iw_scan_req *scanReq = (struct iw_scan_req *)extra; + hdd_adapter_t *con_sap_adapter; + uint16_t con_dfs_ch; + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + /* Block All Scan during DFS operation and send null scan result */ + con_sap_adapter = hdd_get_con_sap_adapter(pAdapter, true); + if (con_sap_adapter) { + con_dfs_ch = con_sap_adapter->sessionCtx.ap.operatingChannel; + + if (VOS_IS_DFS_CH(con_dfs_ch)) { + hddLog(LOGW, "%s:##In DFS Master mode. Scan aborted", __func__); + return -EOPNOTSUPP; + } + } + + + if(pAdapter->scan_info.mScanPending == TRUE) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__); + return eHAL_STATUS_SUCCESS; + } + + vos_mem_zero( &scanRequest, sizeof(scanRequest)); + + if (NULL != wrqu->data.pointer) + { + /* set scanType, active or passive */ + if ((IW_SCAN_TYPE_ACTIVE == scanReq->scan_type) || + (eSIR_ACTIVE_SCAN == pHddCtx->ioctl_scan_mode)) + { + scanRequest.scanType = eSIR_ACTIVE_SCAN; + } + else + { + scanRequest.scanType = eSIR_PASSIVE_SCAN; + } + + /* set bssid using sockaddr from iw_scan_req */ + vos_mem_copy(scanRequest.bssid, + &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) ); + + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { + + if(scanReq->essid_len && + (scanReq->essid_len <= SIR_MAC_MAX_SSID_LENGTH)) { + scanRequest.SSIDs.numOfSSIDs = 1; + scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if(scanRequest.SSIDs.SSIDList) { + scanRequest.SSIDs.SSIDList->SSID.length = scanReq->essid_len; + vos_mem_copy(scanRequest.SSIDs.SSIDList-> SSID.ssId,scanReq->essid,scanReq->essid_len); + } + else + { + scanRequest.SSIDs.numOfSSIDs = 0; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__); + VOS_ASSERT(0); + } + } + else + { + hddLog(LOGE, FL("Invalid essid length : %d"), scanReq->essid_len); + } + } + + /* set min and max channel time */ + scanRequest.minChnTime = scanReq->min_channel_time; + scanRequest.maxChnTime = scanReq->max_channel_time; + + } + else + { + if (pHddCtx->ioctl_scan_mode == eSIR_ACTIVE_SCAN) { + /* set the scan type to active */ + scanRequest.scanType = eSIR_ACTIVE_SCAN; + } else { + scanRequest.scanType = eSIR_PASSIVE_SCAN; + } + + vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff ); + + /* set min and max channel time to zero */ + scanRequest.minChnTime = 0; + scanRequest.maxChnTime = 0; + } + + /* set BSSType to default type */ + scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + + /*Scan all the channels */ + scanRequest.ChannelInfo.numOfChannels = 0; + + scanRequest.ChannelInfo.ChannelList = NULL; + + /* set requestType to full scan */ + scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + + /* if previous genIE is not NULL, update ScanIE */ + if (0 != pwextBuf->genIE.length) + { + memset( &pAdapter->scan_info.scanAddIE, 0, sizeof(pAdapter->scan_info.scanAddIE) ); + memcpy( pAdapter->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, + pwextBuf->genIE.length ); + pAdapter->scan_info.scanAddIE.length = pwextBuf->genIE.length; + + pwextBuf->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata; + pwextBuf->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length; + + /* clear previous genIE after use it */ + memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) ); + } + + /* push addIEScan in scanRequset if exist */ + if (pAdapter->scan_info.scanAddIE.addIEdata && + pAdapter->scan_info.scanAddIE.length) + { + scanRequest.uIEFieldLen = pAdapter->scan_info.scanAddIE.length; + scanRequest.pIEField = pAdapter->scan_info.scanAddIE.addIEdata; + } + + status = sme_ScanRequest((WLAN_HDD_GET_CTX(pAdapter))->hHal, + pAdapter->sessionId, &scanRequest, &scanId, + &hdd_ScanRequestCallback, dev); + if (!HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest fail %d!!!",__func__, status); + goto error; + } + + pAdapter->scan_info.mScanPending = TRUE; + + pAdapter->scan_info.scanId = scanId; + +error: + if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len)) + vos_mem_free(scanRequest.SSIDs.SSIDList); + + EXIT(); + return status; +} + +/** + * iw_set_scan() - SSR wrapper for __iw_set_scan + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 on success, error number otherwise + */ +int iw_set_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_scan(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_scan() - get scan results + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * This function returns the scan results to the wpa_supplicant + * + * Return: 0 on success, error number otherwise + */ +static int __iw_get_scan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tCsrScanResultInfo *pScanResult; + eHalStatus status = eHAL_STATUS_SUCCESS; + hdd_scan_info_t scanInfo; + tScanResultHandle pResult; + int i = 0; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!", + __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA); + + if (TRUE == pAdapter->scan_info.mScanPending) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__); + return -EAGAIN; + } + + scanInfo.dev = dev; + scanInfo.start = extra; + scanInfo.info = info; + + if (0 == wrqu->data.length) + { + scanInfo.end = extra + IW_SCAN_MAX_DATA; + } + else + { + scanInfo.end = extra + wrqu->data.length; + } + + status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult); + + if (NULL == pResult) + { + // no scan results + hddLog(LOG1,"iw_get_scan: NULL Scan Result "); + return 0; + } + + pScanResult = sme_ScanResultGetFirst(hHal, pResult); + + while (pScanResult) + { + status = hdd_IndicateScanResult(&scanInfo, pScanResult); + if (0 != status) + { + break; + } + i++; + pScanResult = sme_ScanResultGetNext(hHal, pResult); + } + + sme_ScanResultPurge(hHal, pResult); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i); + EXIT(); + return status; +} + +/** + * iw_get_scan() - SSR wrapper function for __iw_get_scan + * @dev: Pointer to the net device. + * @info: Pointer to the iw_request_info. + * @wrqu: Pointer to the iwreq_data. + * @extra: Pointer to the data. + * + * Return: 0 on success, error number otherwise + */ +int iw_get_scan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_scan(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +#if 0 +static eHalStatus hdd_CscanRequestCallback(tHalHandle halHandle, void *pContext, + tANI_U32 scanId, eCsrScanStatus status) +{ + struct net_device *dev = (struct net_device *) pContext; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; + hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + union iwreq_data wrqu; + int we_event; + char *msg; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + ENTER(); + + hddLog(LOG1,"%s called with halHandle = %p, pContext = %p, scanID = %d," + " returned status = %d", __func__, halHandle, pContext, + (int) scanId, (int) status); + + /* Check the scanId */ + if (pwextBuf->scanId != scanId) + { + hddLog(LOGW, "%s called with mismatched scanId pWextState->scanId = %d " + "scanId = %d ", __func__, (int) pwextBuf->scanId, + (int) scanId); + } + + /* Scan is no longer pending */ + pwextBuf->mScanPending = VOS_FALSE; + + // notify any applications that may be interested + memset(&wrqu, '\0', sizeof(wrqu)); + we_event = SIOCGIWSCAN; + msg = NULL; + wireless_send_event(dev, we_event, &wrqu, msg); + + vos_status = vos_event_set(&pwextBuf->vosevent); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos_event_set failed!!")); + return VOS_STATUS_E_FAILURE; + } + + EXIT(); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__); + + return eHAL_STATUS_SUCCESS; +} +#endif + +int iw_set_cscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ; + hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrScanRequest scanRequest; + v_U32_t scanId = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + v_U8_t channelIdx; + + ENTER(); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__); + + + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); + return eHAL_STATUS_SUCCESS; + } + + vos_mem_zero( &scanRequest, sizeof(scanRequest)); + if (NULL != wrqu->data.pointer) + { + char *str_ptr = NULL; + tCsrSSIDInfo *SsidInfo = NULL; + int num_ssid = 0; + int i, j, ssid_start; + hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP; + + str_ptr = extra; + + i = WEXT_CSCAN_HEADER_SIZE; + + if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] ) + { + scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i]; + ++i; + } + pAdapter->scan_info.scan_pending_option = scanPendingOption; + + if(pAdapter->scan_info.mScanPending == TRUE) + { + hddLog(LOG1,"%s: mScanPending is TRUE",__func__); + /* If any scan is pending, just giveup this scan request */ + if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption) + { + pAdapter->scan_info.waitScanResult = FALSE; + return eHAL_STATUS_SUCCESS; + } + /* If any scan pending, wait till finish current scan, + and try this scan request when previous scan finish */ + else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption) + { + pAdapter->scan_info.waitScanResult = TRUE; + vos_event_reset(&pAdapter->scan_info.scan_finished_event); + if(vos_wait_single_event(&pAdapter->scan_info.scan_finished_event, + WEXT_CSCAN_SCAN_DONE_WAIT_TIME)) + { + hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__); + return eHAL_STATUS_SUCCESS; + } + } + /* Piggyback previous scan result */ + else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption) + { + pAdapter->scan_info.waitScanResult = TRUE; + return eHAL_STATUS_SUCCESS; + } + } + pAdapter->scan_info.waitScanResult = FALSE; + + /* Check for scan IE */ + while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] ) + { + /* ssid_len */ + if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION) + { + /* total number of ssid's */ + num_ssid++; + /* increment length filed */ + i += str_ptr[i] + 1; + } + /* i should be saved and it will be pointing to 'C' */ + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid); + if( num_ssid ) + { + /* To be fixed in SME and PE: override the number of ssid with 1, + * as SME and PE does not handle multiple SSID in scan request + * */ + scanRequest.SSIDs.numOfSSIDs = num_ssid; + /* Allocate num_ssid tCsrSSIDInfo structure */ + SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo)); + if(NULL == scanRequest.SSIDs.SSIDList) { + hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer"); + return -ENOMEM; + } + + /* copy all the ssid's and their length */ + ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;/* skipping 'S' */ + for(j = 0; j < num_ssid; j++) { + if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){ + scanRequest.SSIDs.numOfSSIDs -= 1; + } else{ + /* get the ssid length */ + SsidInfo->SSID.length = str_ptr[ssid_start++]; + vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s", j, SsidInfo->SSID.ssId); + } + /* skipping length */ + ssid_start += str_ptr[ssid_start - 1] + 1; + /* Store next ssid info */ + SsidInfo++; + } + } + + /* Check for Channel IE */ + if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i]) + { + if( str_ptr[++i] == 0 ) + { + scanRequest.ChannelInfo.numOfChannels = 0; + scanRequest.ChannelInfo.ChannelList = NULL; + i++; + } + else { + + /* increment the counter */ + scanRequest.ChannelInfo.numOfChannels = str_ptr[i++]; + /* store temp channel list */ + /* SME expects 1 byte channel content */ + scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t)); + if(NULL == scanRequest.ChannelInfo.ChannelList) + { + hddLog(LOGE, "memory alloc failed for channel list creation"); + status = -ENOMEM; + goto exit_point; + } + + for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++) + { + /* SCAN request from upper layer has 2 bytes channel */ + scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i]; + i += sizeof(v_U16_t); + } + } + } + + /* Set default */ + scanRequest.scanType = eSIR_ACTIVE_SCAN; + scanRequest.minChnTime = 0; + scanRequest.maxChnTime = 0; + + /* Now i is pointing to passive dwell dwell time */ + /* 'P',min dwell time, max dwell time */ + /* next two offsets contain min and max channel time */ + if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) ) + { + /* No SSID specified, num_ssid == 0, then start passive scan */ + if (!num_ssid || (eSIR_PASSIVE_SCAN == pAdapter->scan_info.scan_mode)) + { + scanRequest.scanType = eSIR_PASSIVE_SCAN; + scanRequest.minChnTime = (v_U8_t)str_ptr[++i];//scanReq->min_channel_time; + scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];//scanReq->max_channel_time; + i++; + } + else + { + i += 3; + } + } + + /* H indicates active channel time */ + if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) ) + { + if (num_ssid || (eSIR_ACTIVE_SCAN == pAdapter->scan_info.scan_mode)) + { + scanRequest.scanType = eSIR_ACTIVE_SCAN; + scanRequest.minChnTime = str_ptr[++i];//scanReq->min_channel_time; + scanRequest.maxChnTime = str_ptr[++i];//scanReq->max_channel_time; + i++; + } + else + { + i +=3; + } + } + scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + /* set requestType to full scan */ + scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + pAdapter->scan_info.mScanPending = TRUE; + + /* if previous genIE is not NULL, update ScanIE */ + if(0 != pwextBuf->genIE.length) + { + memset( &pAdapter->scan_info.scanAddIE, 0, sizeof(pAdapter->scan_info.scanAddIE) ); + memcpy( pAdapter->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, + pwextBuf->genIE.length ); + pAdapter->scan_info.scanAddIE.length = pwextBuf->genIE.length; + + pwextBuf->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata; + pwextBuf->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length; + + /* clear previous genIE after use it */ + memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) ); + } + + /* push addIEScan in scanRequset if exist */ + if (pAdapter->scan_info.scanAddIE.addIEdata && + pAdapter->scan_info.scanAddIE.length) + { + scanRequest.uIEFieldLen = pAdapter->scan_info.scanAddIE.length; + scanRequest.pIEField = pAdapter->scan_info.scanAddIE.addIEdata; + } + + status = sme_ScanRequest((WLAN_HDD_GET_CTX(pAdapter))->hHal, + pAdapter->sessionId, &scanRequest, &scanId, + &hdd_ScanRequestCallback, dev); + if( !HAL_STATUS_SUCCESS(status) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: SME scan fail status %d !!!",__func__, status); + pAdapter->scan_info.mScanPending = FALSE; + status = -EINVAL; + goto exit_point; + } + + pAdapter->scan_info.scanId = scanId; + + } //end of data->pointer + else { + status = -1; + } + +exit_point: + + /* free ssidlist */ + if (scanRequest.SSIDs.SSIDList) + { + vos_mem_free(scanRequest.SSIDs.SSIDList); + } + /* free the channel list */ + if(scanRequest.ChannelInfo.ChannelList) + { + vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList); + } + + EXIT(); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__); + return status; +} + +/* Abort any MAC scan if in progress */ +void hdd_abort_mac_scan(hdd_context_t* pHddCtx, tANI_U8 sessionId, + eCsrAbortReason reason) +{ + sme_AbortMacScan(pHddCtx->hHal, sessionId, reason); +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c new file mode 100644 index 000000000000..dd56e4d4829c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -0,0 +1,1513 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**=========================================================================== + + \file wlan_hdd_softap_tx_rx.c + + \brief Linux HDD Tx/RX APIs + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef IPA_OFFLOAD +#include +#endif +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Function definitions and documentation + -------------------------------------------------------------------------*/ +#if 0 +static void hdd_softap_dump_sk_buff(struct sk_buff * skb) +{ + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p ", __func__, skb->head); + //VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p ", __func__, skb->tail); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p ", __func__, skb->end); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d ", __func__, skb->len); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d ", __func__, skb->data_len); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len); + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", + skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], + skb->data[5], skb->data[6], skb->data[7]); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12], + skb->data[13], skb->data[14], skb->data[15]); +} +#endif + +/**============================================================================ + @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +static VOS_STATUS hdd_softap_flush_tx_queues( hdd_adapter_t *pAdapter ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + v_SINT_t i = -1; + v_U8_t STAId = 0; + hdd_list_node_t *anchor = NULL; + skb_list_node_t *pktNode = NULL; + struct sk_buff *skb = NULL; + + spin_lock_bh( &pAdapter->staInfo_lock ); + for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) + { + if (FALSE == pAdapter->aStaInfo[STAId].isUsed) + { + continue; + } + + for (i = 0; i < NUM_TX_QUEUES; i ++) + { + spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock); + while (true) + { + status = hdd_list_remove_front ( &pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &anchor); + + if (VOS_STATUS_E_EMPTY != status) + { + //If success then we got a valid packet from some AC + pktNode = list_entry(anchor, skb_list_node_t, anchor); + skb = pktNode->skb; + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + continue; + } + + //current list is empty + break; + } + pAdapter->aStaInfo[STAId].txSuspended[i] = VOS_FALSE; + spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock); + } + pAdapter->aStaInfo[STAId].vosLowResource = VOS_FALSE; + } + + spin_unlock_bh( &pAdapter->staInfo_lock ); + + return status; +} + +#ifdef QCA_LL_TX_FLOW_CT +/**============================================================================ + @brief hdd_softap_tx_resume_timer_expired_handler() - Resume OS TX Q timer + expired handler for SAP and P2P GO interface. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully for SAP and P2P GO interface. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + + if (!pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: INV ARG", __func__); + /* INVALID ARG */ + return; + } + + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(pAdapter->dev); + return; +} + +/**============================================================================ + @brief hdd_softap_tx_resume_cb() - Resume OS TX Q. + Q was stopped due to WLAN TX path low resource condition + + @param adapter_context : [in] pointer to vdev adapter + @param tx_resume : [in] TX Q resume trigger + + @return : NONE + ===========================================================================*/ +void hdd_softap_tx_resume_cb(void *adapter_context, + v_BOOL_t tx_resume) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + + if (!pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: INV ARG", __func__); + /* INVALID ARG */ + return; + } + + /* Resume TX */ + if (VOS_TRUE == tx_resume) + { + if(VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + vos_timer_stop(&pAdapter->tx_flow_control_timer); + } + + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(pAdapter->dev); + pAdapter->hdd_stats.hddTxRxStats.txflow_unpause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = FALSE; + + } +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + else if (VOS_FALSE == tx_resume) /* Pause TX */ + { + hddLog(LOG1, FL("Disabling queues")); + netif_tx_stop_all_queues(pAdapter->dev); + if (VOS_TIMER_STATE_STOPPED == + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + VOS_STATUS status; + status = vos_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + if ( !VOS_IS_STATUS_SUCCESS(status) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to start tx_flow_control_timer", __func__); + } + else + { + pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; + } + } + pAdapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = TRUE; + } +#endif + + return; +} +#endif /* QCA_LL_TX_FLOW_CT */ + +/**============================================================================ + @brief hdd_softap_hard_start_xmit() - Function registered with the Linux OS + for transmitting packets. + + @param skb : [in] pointer to OS packet (sk_buff) + @param dev : [in] pointer to Libra network device + + @return : NETDEV_TX_OK + ===========================================================================*/ +int __hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + WLANTL_ACEnumType ac = WLANTL_AC_BE; + hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev); + hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + v_MACADDR_t *pDestMacAddress; + v_U8_t STAId; +#ifdef QCA_PKT_PROTO_TRACE + hdd_context_t *hddCtxt = (hdd_context_t *)pAdapter->pHddCtx; + v_U8_t proto_type = 0; +#endif /* QCA_PKT_PROTO_TRACE */ + + ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; + /* Prevent this function to be called during SSR since TL context may + not be reinitialized at this time which will lead crash. */ + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: LOGP in Progress. Ignore!!!", __func__); + goto drop_pkt; + } + + /* + * If the device is operating on a DFS Channel + * then check if SAP is in CAC WAIT state and + * drop the packets. In CAC WAIT state device + * is expected not to transmit any frames. + * SAP starts Tx only after the BSS START is + * done. + */ + if (pHddApCtx->dfs_cac_block_tx) + { + goto drop_pkt; + } + + pDestMacAddress = (v_MACADDR_t*)skb->data; + + if (vos_is_macaddr_broadcast( pDestMacAddress ) || + vos_is_macaddr_group(pDestMacAddress)) + { + // The BC/MC station ID is assigned during BSS starting phase. + // SAP will return the station ID used for BC/MC traffic. + STAId = pHddApCtx->uBCStaId; + } + else + { + if (VOS_STATUS_SUCCESS != + hdd_softap_GetStaId(pAdapter, pDestMacAddress, &STAId)) { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Failed to find the station id", __func__); + goto drop_pkt; + } + + if (STAId == HDD_WLAN_INVALID_STA_ID) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Failed to find right station", __func__); + goto drop_pkt; + } + else if (FALSE == pAdapter->aStaInfo[STAId].isUsed ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: STA %d is unregistered", __func__, STAId); + goto drop_pkt; + } + + if ( (WLANTL_STA_CONNECTED != pAdapter->aStaInfo[STAId].tlSTAState) && + (WLANTL_STA_AUTHENTICATED != pAdapter->aStaInfo[STAId].tlSTAState) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Station not connected yet", __func__); + goto drop_pkt; + } + else if(WLANTL_STA_CONNECTED == pAdapter->aStaInfo[STAId].tlSTAState) + { + if(ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: NON-EAPOL packet in non-Authenticated state", __func__); + goto drop_pkt; + } + } + } + +#ifdef QCA_LL_TX_FLOW_CT + if (VOS_FALSE == + WLANTL_GetTxResource((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + pAdapter->sessionId, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_high_watermark_offset)) { + if ((pAdapter->tx_flow_timer_initialized == TRUE) && + (VOS_TIMER_STATE_STOPPED == + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer))) { + hddLog(LOG1, FL("Disabling queues")); + netif_tx_stop_all_queues(dev); + vos_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; + pAdapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = TRUE; + } + } +#endif /* QCA_LL_TX_FLOW_CT */ + + //Get TL AC corresponding to Qdisc queue index/AC. + ac = hdd_QdiscAcToTlAC[skb->queue_mapping]; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac]; + + wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED); + +#ifdef QCA_PKT_PROTO_TRACE + if ((hddCtxt->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_EAPOL) || + (hddCtxt->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_DHCP)) + { + /* Proto Trace enabled */ + proto_type = vos_pkt_get_proto_type(skb, + hddCtxt->cfg_ini->gEnableDebugLog, 0); + if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type) + { + vos_pkt_trace_buf_update("HA:T:EPL"); + } + else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type) + { + vos_pkt_trace_buf_update("HA:T:DHC"); + } + } +#endif /* QCA_PKT_PROTO_TRACE */ + pAdapter->stats.tx_bytes += skb->len; + ++pAdapter->stats.tx_packets; + + if (WLANTL_SendSTA_DataFrame((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + STAId, skb +#ifdef QCA_PKT_PROTO_TRACE + , proto_type +#endif /* QCA_PKT_PROTO_TRACE */ + ) != NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Failed to send packet to txrx for staid:%d", + __func__, STAId); + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac]; + goto drop_pkt; + } + + dev->trans_start = jiffies; + + return NETDEV_TX_OK; + +drop_pkt: + + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + kfree_skb(skb); + + return NETDEV_TX_OK; +} + +int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_softap_hard_start_xmit(skb, dev); + vos_ssr_unprotect(__func__); + return ret; +} + +/** + * __hdd_softap_tx_timeout() - softap tx timeout + * @dev: pointer to net_device + * + * Function called by OS if there is any timeout during transmission. + * Since HDD simply enqueues packet and returns control to OS right away, + * this would never be invoked. + * + * Return: none + */ +static void __hdd_softap_tx_timeout(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Transmission timeout occurred", __func__); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (hdd_ctx->isLogpInProgress) { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: LOGP in Progress. Ignore!!!", __func__); + return; + } + + /* + * Getting here implies we disabled the TX queues for too long. Queues are + * disabled either because of disassociation or low resource scenarios. In + * case of disassociation it is ok to ignore this. But if associated, we have + * do possible recovery here. + */ +} + +/** + * hdd_softap_tx_timeout() - SSR wrapper for __hdd_softap_tx_timeout + * @dev: pointer to net_device + * + * Return: none + */ +void hdd_softap_tx_timeout(struct net_device *dev) +{ + vos_ssr_protect(__func__); + __hdd_softap_tx_timeout(dev); + vos_ssr_unprotect(__func__); +} + +/** + * __hdd_softap_stats() - get softap tx/rx stats + * @dev: pointer to net_device + * + * Function registered with the Linux OS for device TX/RX statistics. + * + * Return: pointer to net_device stats + */ +static struct net_device_stats *__hdd_softap_stats(struct net_device *dev) +{ + hdd_adapter_t *priv = netdev_priv(dev); + return &priv->stats; +} + +/** + * hdd_softap_stats() - SSR wrapper function for __hdd_softap_stats + * @dev: pointer to net_device + * + * Return: pointer to net_device stats + */ +struct net_device_stats* hdd_softap_stats(struct net_device *dev) +{ + struct net_device_stats *priv_stats; + + vos_ssr_protect(__func__); + priv_stats = __hdd_softap_stats(dev); + vos_ssr_unprotect(__func__); + + return priv_stats; +} + +/**============================================================================ + @brief hdd_softap_init_tx_rx() - Init function to initialize Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + v_SINT_t i = -1; + v_SIZE_t size = 0; + + v_U8_t STAId = 0; + + pAdapter->isVosOutOfResource = VOS_FALSE; + pAdapter->isVosLowResource = VOS_FALSE; + + vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats)); + + while (++i != NUM_TX_QUEUES) + hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN); + + /* Initial HDD buffer control / flow control fields*/ + vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE_TX_802_3_DATA, &size); + + pAdapter->aTxQueueLimit[WLANTL_AC_BK] = HDD_SOFTAP_TX_BK_QUEUE_MAX_LEN; + pAdapter->aTxQueueLimit[WLANTL_AC_BE] = HDD_SOFTAP_TX_BE_QUEUE_MAX_LEN; + pAdapter->aTxQueueLimit[WLANTL_AC_VI] = HDD_SOFTAP_TX_VI_QUEUE_MAX_LEN; + pAdapter->aTxQueueLimit[WLANTL_AC_VO] = HDD_SOFTAP_TX_VO_QUEUE_MAX_LEN; + + spin_lock_init( &pAdapter->staInfo_lock ); + + for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) + { + vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t)); + for (i = 0; i < NUM_TX_QUEUES; i ++) + { + hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN); + } + } + + return status; +} + +/**============================================================================ + @brief hdd_softap_deinit_tx_rx() - Deinit function to clean up Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + + status = hdd_softap_flush_tx_queues(pAdapter); + + return status; +} + +/**============================================================================ + @brief hdd_softap_flush_tx_queues_sta() - Utility function to flush the TX queues of a station + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deinit + @return : void + ===========================================================================*/ +static void hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_t STAId ) +{ + v_U8_t i = -1; + + hdd_list_node_t *anchor = NULL; + + skb_list_node_t *pktNode = NULL; + struct sk_buff *skb = NULL; + + if (FALSE == pAdapter->aStaInfo[STAId].isUsed) + return; + + for (i = 0; i < NUM_TX_QUEUES; i ++) + { + spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock); + while (true) + { + if (VOS_STATUS_E_EMPTY != + hdd_list_remove_front(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], + &anchor)) + { + //If success then we got a valid packet from some AC + pktNode = list_entry(anchor, skb_list_node_t, anchor); + skb = pktNode->skb; + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + continue; + } + + //current list is empty + break; + } + spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i].lock); + } + + return; +} + +/**============================================================================ + @brief hdd_softap_init_tx_rx_sta() - Init function to initialize a station in Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deinit + @param pmacAddrSTA : [in] pointer to the MAC address of the station + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA) +{ + v_U8_t i = 0; + spin_lock_bh( &pAdapter->staInfo_lock ); + if (pAdapter->aStaInfo[STAId].isUsed) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Reinit station %d", __func__, STAId ); + spin_unlock_bh( &pAdapter->staInfo_lock ); + return VOS_STATUS_E_FAILURE; + } + + vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t)); + for (i = 0; i < NUM_TX_QUEUES; i ++) + { + hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN); + } + + pAdapter->aStaInfo[STAId].isUsed = TRUE; + pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE; + vos_copy_macaddr( &pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA); + + spin_unlock_bh( &pAdapter->staInfo_lock ); + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief hdd_softap_deinit_tx_rx_sta() - Deinit function to clean up a station in Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @param STAId : [in] Station ID to deinit + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_deinit_tx_rx_sta ( hdd_adapter_t *pAdapter, v_U8_t STAId ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + v_U8_t ac; + /**Track whether OS TX queue has been disabled.*/ + v_BOOL_t txSuspended[NUM_TX_QUEUES]; + v_U8_t tlAC; + hdd_hostapd_state_t *pHostapdState; + v_U8_t i; + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + spin_lock_bh( &pAdapter->staInfo_lock ); + if (FALSE == pAdapter->aStaInfo[STAId].isUsed) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Deinit station not inited %d", __func__, STAId ); + spin_unlock_bh( &pAdapter->staInfo_lock ); + return VOS_STATUS_E_FAILURE; + } + + hdd_softap_flush_tx_queues_sta(pAdapter, STAId); + + pAdapter->aStaInfo[STAId].isUsed = FALSE; + pAdapter->aStaInfo[STAId].isDeauthInProgress = FALSE; + + /* if this STA had any of its WMM TX queues suspended, then the + associated queue on the network interface was disabled. check + to see if that is the case, in which case we need to re-enable + the interface queue. but we only do this if the BSS is running + since, if the BSS is stopped, all of the interfaces have been + stopped and should not be re-enabled */ + + if (BSS_START == pHostapdState->bssState) + { + for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++) + { + tlAC = hdd_QdiscAcToTlAC[ac]; + txSuspended[ac] = pAdapter->aStaInfo[STAId].txSuspended[tlAC]; + } + } + vos_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t)); + + /* re-init spin lock, since netdev can still open adapter until + * driver gets unloaded + */ + for (i = 0; i < NUM_TX_QUEUES; i ++) + { + hdd_list_init(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], + HDD_TX_QUEUE_MAX_LEN); + } + + if (BSS_START == pHostapdState->bssState) + { + for (ac = HDD_LINUX_AC_VO; ac <= HDD_LINUX_AC_BK; ac++) + { + if (txSuspended[ac]) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: TX queue re-enabled", __func__); + netif_wake_subqueue(pAdapter->dev, ac); + } + } + } + + spin_unlock_bh( &pAdapter->staInfo_lock ); + return status; +} + +/**============================================================================ + @brief hdd_softap_tx_complete_cbk() - Callback function invoked by TL + to indicate that a packet has been transmitted across the bus + successfully. OS packet resources can be released after this cbk. + + @param vosContext : [in] pointer to VOS context + @param pVosPacket : [in] pointer to VOS packet (containing skb) + @param vosStatusIn : [in] status of the transmission + + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_tx_complete_cbk( v_VOID_t *vosContext, + vos_pkt_t *pVosPacket, + VOS_STATUS vosStatusIn ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = NULL; + void* pOsPkt = NULL; + + if( ( NULL == vosContext ) || ( NULL == pVosPacket ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + //Return the skb to the OS + status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE ); + if ((!VOS_IS_STATUS_SUCCESS(status)) || (!pOsPkt)) + { + //This is bad but still try to free the VOSS resources if we can + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Failure extracting skb from vos pkt", __func__); + vos_pkt_return_packet( pVosPacket ); + return VOS_STATUS_E_FAILURE; + } + + //Get the Adapter context. + pAdapter = (hdd_adapter_t *)netdev_priv(((struct sk_buff *)pOsPkt)->dev); + if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter context is invalid", __func__); + } + else + { + ++pAdapter->hdd_stats.hddTxRxStats.txCompleted; + } + + kfree_skb((struct sk_buff *)pOsPkt); + + //Return the VOS packet resources. + status = vos_pkt_return_packet( pVosPacket ); + if(!VOS_IS_STATUS_SUCCESS( status )) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Could not return VOS packet to the pool", __func__); + } + + return status; +} + + +/**============================================================================ + @brief hdd_softap_tx_fetch_packet_cbk() - Callback function invoked by TL to + fetch a packet for transmission. + + @param vosContext : [in] pointer to VOS context + @param staId : [in] Station for which TL is requesting a pkt + @param ac : [in] access category requested by TL + @param pVosPacket : [out] pointer to VOS packet packet pointer + @param pPktMetaInfo : [out] pointer to meta info for the pkt + + @return : VOS_STATUS_E_EMPTY if no packets to transmit + : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext, + v_U8_t *pStaId, + WLANTL_ACEnumType ac, + vos_pkt_t **ppVosPacket, + WLANTL_MetaInfoType *pPktMetaInfo ) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; + hdd_adapter_t *pAdapter = NULL; + hdd_list_node_t *anchor = NULL; + skb_list_node_t *pktNode = NULL; + struct sk_buff *skb = NULL; + vos_pkt_t *pVosPacket = NULL; + v_MACADDR_t* pDestMacAddress = NULL; + v_TIME_t timestamp; + v_SIZE_t size = 0; + v_U8_t STAId = WLAN_MAX_STA_COUNT; + hdd_context_t *pHddCtx = NULL; + + //Sanity check on inputs + if ( ( NULL == vosContext ) || + ( NULL == pStaId ) || + ( NULL == ppVosPacket ) || + ( NULL == pPktMetaInfo ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Null Params being passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); + if ( NULL == pHddCtx ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter context is Null", __func__); + return VOS_STATUS_E_FAILURE; + } + + STAId = *pStaId; + if (STAId >= WLAN_MAX_STA_COUNT) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid STAId %d passed by TL", __func__, STAId); + return VOS_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[STAId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + if (FALSE == pAdapter->aStaInfo[STAId].isUsed ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Unregistered STAId %d passed by TL", __func__, STAId); + return VOS_STATUS_E_FAILURE; + } + + *ppVosPacket = NULL; + + //Make sure the AC being asked for is sane + if( ac > WLANTL_MAX_AC || ac < 0) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid AC %d passed by TL", __func__, ac); + return VOS_STATUS_E_FAILURE; + } + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: AC %d passed by TL", __func__, ac); + + //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources + //This simplifies the locking and unlocking of Tx queue + status = vos_pkt_wrap_data_packet( &pVosPacket, + VOS_PKT_TYPE_TX_802_3_DATA, + NULL, //OS Pkt is not being passed + hdd_softap_tx_low_resource_cbk, + pAdapter ); + + if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES) + { + //Remember VOS is in a low resource situation + pAdapter->isVosOutOfResource = VOS_TRUE; + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, + "%s: VOSS in Low Resource scenario", __func__); + //TL needs to handle this case. VOS_STATUS_E_EMPTY is returned when the queue is empty. + return VOS_STATUS_E_FAILURE; + } + + /* Only fetch this station and this AC. Return VOS_STATUS_E_EMPTY if nothing there. Do not get next AC + as the other branch does. + */ + spin_lock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock); + hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &size); + + if (0 == size) + { + spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock); + vos_pkt_return_packet(pVosPacket); + return VOS_STATUS_E_EMPTY; + } + + status = hdd_list_remove_front( &pAdapter->aStaInfo[STAId].wmm_tx_queue[ac], &anchor ); + spin_unlock_bh(&pAdapter->aStaInfo[STAId].wmm_tx_queue[ac].lock); + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: AC %d has packets pending", __func__, ac); + + if(VOS_STATUS_SUCCESS == status) + { + //If success then we got a valid packet from some AC + pktNode = list_entry(anchor, skb_list_node_t, anchor); + skb = pktNode->skb; + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Error in de-queuing skb from Tx queue status = %d", + __func__, status ); + vos_pkt_return_packet(pVosPacket); + return VOS_STATUS_E_FAILURE; + } + + //Attach skb to VOS packet. + status = vos_pkt_set_os_packet( pVosPacket, skb ); + if (status != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Error attaching skb", __func__); + vos_pkt_return_packet(pVosPacket); + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + return VOS_STATUS_E_FAILURE; + } + + //Just being paranoid. To be removed later + if(pVosPacket == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS packet returned by VOSS is NULL", __func__); + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + return VOS_STATUS_E_FAILURE; + } + + //Return VOS packet to TL; + *ppVosPacket = pVosPacket; + + //Fill out the meta information needed by TL + //FIXME This timestamp is really the time stamp of wrap_data_packet + vos_pkt_get_timestamp( pVosPacket, ×tamp ); + pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp; + if ( 1 < size ) + { + pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send + } + else + { + pPktMetaInfo->bMorePackets = 0; + } + + pPktMetaInfo->ucIsEapol = 0; + + if(pAdapter->aStaInfo[STAId].tlSTAState != WLANTL_STA_AUTHENTICATED) + { + if (TRUE == hdd_IsEAPOLPacket( pVosPacket )) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOS packet is EAPOL packet", __func__); + pPktMetaInfo->ucIsEapol = 1; + } + } + /* xg: @@@@: temporarily disable these. will revisit later */ + { + pPktMetaInfo->ucUP = pktNode->userPriority; + pPktMetaInfo->ucTID = pPktMetaInfo->ucUP; + } + + pPktMetaInfo->ucType = 0; //FIXME Don't know what this is + //Extract the destination address from ethernet frame + pDestMacAddress = (v_MACADDR_t*)skb->data; + + // we need 802.3 to 802.11 frame translation + // (note that Bcast/Mcast will be translated in SW, unicast in HW) + pPktMetaInfo->ucDisableFrmXtl = 0; + pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0; + pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0; + + if ( (pAdapter->aStaInfo[STAId].txSuspended[ac]) && + (size <= ((pAdapter->aTxQueueLimit[ac]*3)/4) )) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: TX queue re-enabled", __func__); + pAdapter->aStaInfo[STAId].txSuspended[ac] = VOS_FALSE; + netif_wake_subqueue(pAdapter->dev, skb_get_queue_mapping(skb)); + } + + // We're giving the packet to TL so consider it transmitted from + // a statistics perspective. We account for it here instead of + // when the packet is returned for two reasons. First, TL will + // manipulate the skb to the point where the len field is not + // accurate, leading to inaccurate byte counts if we account for + // it later. Second, TL does not provide any feedback as to + // whether or not the packet was successfully sent over the air, + // so the packet counts will be the same regardless of where we + // account for them + pAdapter->stats.tx_bytes += skb->len; + ++pAdapter->stats.tx_packets; + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: Valid VOS PKT returned to TL", __func__); + + return status; +} + + +/**============================================================================ + @brief hdd_softap_tx_low_resource_cbk() - Callback function invoked in the + case where VOS packets are not available at the time of the call to get + packets. This callback function is invoked by VOS when packets are + available. + + @param pVosPacket : [in] pointer to VOS packet + @param userData : [in] opaque user data that was passed initially + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + =============================================================================*/ +VOS_STATUS hdd_softap_tx_low_resource_cbk( vos_pkt_t *pVosPacket, + v_VOID_t *userData ) +{ + VOS_STATUS status; + v_SINT_t i = 0; + v_SIZE_t size = 0; + hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData; + v_U8_t STAId = WLAN_MAX_STA_COUNT; + + if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("Invalid adapter %p"), pAdapter); + return VOS_STATUS_E_FAILURE; + } + + //Return the packet to VOS. We just needed to know that VOS is out of low resource + //situation. Here we will only signal TL that there is a pending data for a STA. + //VOS packet will be requested (if needed) when TL comes back to fetch data. + vos_pkt_return_packet( pVosPacket ); + + pAdapter->isVosOutOfResource = VOS_FALSE; + + // Indicate to TL that there is pending data if a queue is non empty. + // This Code wasnt included in earlier version which resulted in + // Traffic stalling + for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) + { + if ((pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_AUTHENTICATED) || + (pAdapter->aStaInfo[STAId].tlSTAState == WLANTL_STA_CONNECTED)) + { + for( i=NUM_TX_QUEUES-1; i>=0; --i ) + { + size = 0; + hdd_list_size(&pAdapter->aStaInfo[STAId].wmm_tx_queue[i], &size); + if ( size > 0 ) + { + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + STAId, + (WLANTL_ACEnumType)i ); + if( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Failure in indicating pkt to TL for ac=%d", __func__,i); + } + } + } + } + } + return VOS_STATUS_SUCCESS; +} + + + +/**============================================================================ + @brief hdd_softap_rx_packet_cbk() - Receive callback registered with TL. + TL will call this to notify the HDD when one or more packets were + received for a registered STA. + + @param vosContext : [in] pointer to VOS context + @param rxBuf : [in] pointer to rx adf_nbuf + @param staId : [in] Station Id (Address 1 Index) + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_softap_rx_packet_cbk(v_VOID_t *vosContext, + adf_nbuf_t rxBuf, v_U8_t staId) +{ + hdd_adapter_t *pAdapter = NULL; + int rxstat; + struct sk_buff *skb = NULL; + hdd_context_t *pHddCtx = NULL; +#ifdef QCA_PKT_PROTO_TRACE + v_U8_t proto_type; +#endif /* QCA_PKT_PROTO_TRACE */ + struct sk_buff *skb_next; + unsigned int cpu_index; + + //Sanity check on inputs + if ((NULL == vosContext) || (NULL == rxBuf)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); + if ( NULL == pHddCtx ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__); + return VOS_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[staId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("invalid adapter or adapter has invalid magic")); + return VOS_STATUS_E_FAILURE; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "Magic cookie(%x) for adapter sanity verification is invalid", + pAdapter->magic); + return VOS_STATUS_E_FAILURE; + } + + if (!pAdapter->dev) { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "Invalid DEV(NULL) Drop packets"); + return VOS_STATUS_E_FAILURE; + } + + // walk the chain until all are processed + skb = (struct sk_buff *) rxBuf; + + while (NULL != skb) { + skb_next = skb->next; + skb->dev = pAdapter->dev; + + cpu_index = wlan_hdd_get_cpu(); + + ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; + ++pAdapter->stats.rx_packets; + pAdapter->stats.rx_bytes += skb->len; + + wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED); +#ifdef QCA_PKT_PROTO_TRACE + if ((pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_EAPOL) || + (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_DHCP)) { + proto_type = vos_pkt_get_proto_type(skb, + pHddCtx->cfg_ini->gEnableDebugLog, 0); + if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type) + vos_pkt_trace_buf_update("HA:R:EPL"); + else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type) + vos_pkt_trace_buf_update("HA:R:DHC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + + skb->protocol = eth_type_trans(skb, skb->dev); + + /* + * If this is not a last packet on the chain + * Just put packet into backlog queue, not scheduling RX sirq + */ + if (skb->next) { + rxstat = netif_rx(skb); + } else { +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + vos_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, + HDD_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX); +#endif + /* + * This is the last packet on the chain + * Scheduling rx sirq + */ + rxstat = netif_rx_ni(skb); + } + + if (NET_RX_SUCCESS == rxstat) + ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index]; + else + ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index]; + + skb = skb_next; + } + pAdapter->dev->last_rx = jiffies; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx; + v_U8_t i; + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL", __func__); + return VOS_STATUS_E_INVAL; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pAdapter magic", __func__); + return VOS_STATUS_E_INVAL; + } + + pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx); + //Clear station in TL and then update HDD data structures. This helps + //to block RX frames from other station to this station. + vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "WLANTL_ClearSTAClient() failed to for staID %d. " + "Status= %d [0x%08X]", + staId, vosStatus, vosStatus ); + } + + if (pAdapter->aStaInfo[staId].isUsed) { + spin_lock_bh( &pAdapter->staInfo_lock ); + vos_mem_zero(&pAdapter->aStaInfo[staId], sizeof(hdd_station_info_t)); + + /* re-init spin lock, since netdev can still open adapter until + * driver gets unloaded + */ + for (i = 0; i < NUM_TX_QUEUES; i ++) + { + hdd_list_init(&pAdapter->aStaInfo[staId].wmm_tx_queue[i], + HDD_TX_QUEUE_MAX_LEN); + } + spin_unlock_bh( &pAdapter->staInfo_lock ); + } + pHddCtx->sta_to_adapter[staId] = NULL; + + return( vosStatus ); +} + +VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter, + v_BOOL_t fAuthRequired, + v_BOOL_t fPrivacyBit, + v_U8_t staId, + v_U8_t ucastSig, + v_U8_t bcastSig, + v_MACADDR_t *pPeerMacAddress, + v_BOOL_t fWmmEnabled ) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + WLAN_STADescType staDesc = {0}; + hdd_context_t *pHddCtx = pAdapter->pHddCtx; + hdd_adapter_t *pmonAdapter = NULL; + + //eCsrEncryptionType connectedCipherAlgo; + //v_BOOL_t fConnected; + + /* + * Clean up old entry if it is not cleaned up properly + */ + if ( pAdapter->aStaInfo[staId].isUsed ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "clean up old entry for STA %d", staId); + hdd_softap_DeregisterSTA( pAdapter, staId ); + } + + /* Get the Station ID from the one saved during the association */ + + staDesc.ucSTAId = staId; + + + /*Save the pAdapter Pointer for this staId*/ + pHddCtx->sta_to_adapter[staId] = pAdapter; + + staDesc.wSTAType = WLAN_STA_SOFTAP; + + vos_mem_copy( staDesc.vSTAMACAddress.bytes, pPeerMacAddress->bytes,sizeof(pPeerMacAddress->bytes) ); + vos_mem_copy( staDesc.vBSSIDforIBSS.bytes, &pAdapter->macAddressCurrent,6 ); + vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent ); + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "register station"); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "station mac " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(staDesc.vSTAMACAddress.bytes)); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "BSSIDforIBSS " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(staDesc.vBSSIDforIBSS.bytes)); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "SOFTAP SELFMAC " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(staDesc.vSelfMACAddress.bytes)); + + vosStatus = hdd_softap_init_tx_rx_sta(pAdapter, staId, &staDesc.vSTAMACAddress); + + staDesc.ucQosEnabled = fWmmEnabled; + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "HDD SOFTAP register TL QoS_enabled=%d", + staDesc.ucQosEnabled ); + + staDesc.ucProtectedFrame = (v_U8_t)fPrivacyBit ; + + + // For PRIMA UMA frame translation is not enable yet. + staDesc.ucSwFrameTXXlation = 1; + staDesc.ucSwFrameRXXlation = 1; + staDesc.ucAddRmvLLC = 1; + + // Initialize signatures and state + staDesc.ucUcastSig = ucastSig; + staDesc.ucBcastSig = bcastSig; + staDesc.ucInitState = fAuthRequired ? + WLANTL_STA_CONNECTED : WLANTL_STA_AUTHENTICATED; + + staDesc.ucIsReplayCheckValid = VOS_FALSE; + + // Register the Station with TL... + /* Incase Micro controller data path offload enabled, + * All the traffic routed to WLAN host driver, do not need to + * route IPA. It should be routed kernel network stack */ +#if defined(IPA_OFFLOAD) && !defined(IPA_UC_OFFLOAD) + if (hdd_ipa_is_enabled(pHddCtx)) + vosStatus = WLANTL_RegisterSTAClient( + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + hdd_ipa_process_rxt, + hdd_softap_tx_complete_cbk, + hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 ); + else +#endif + vosStatus = WLANTL_RegisterSTAClient( + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + hdd_softap_rx_packet_cbk, + hdd_softap_tx_complete_cbk, + hdd_softap_tx_fetch_packet_cbk, &staDesc, 0 ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "SOFTAP WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]", + vosStatus, vosStatus ); + return vosStatus; + } + + // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver, + // then go to 'authenticated'. For all other authentication types (those that do + // not require upper layer authentication) we can put TL directly into 'authenticated' + // state. + + //VOS_ASSERT( fConnected ); + pAdapter->aStaInfo[staId].ucSTAId = staId; + pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled; + + if ( !fAuthRequired ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", + pAdapter->aStaInfo[staId].ucSTAId ); + + // Connections that do not need Upper layer auth, transition TL directly + // to 'Authenticated' state. + vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId, + WLANTL_STA_AUTHENTICATED, VOS_FALSE); + + pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_AUTHENTICATED; + pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_TRUE; + } + else + { + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pAdapter->aStaInfo[staId].ucSTAId ); + + vosStatus = WLANTL_ChangeSTAState( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staDesc.ucSTAId, + WLANTL_STA_CONNECTED, VOS_FALSE); + pAdapter->aStaInfo[staId].tlSTAState = WLANTL_STA_CONNECTED; + + pAdapter->sessionCtx.ap.uIsAuthenticated = VOS_FALSE; + + } + pmonAdapter= hdd_get_mon_adapter( pAdapter->pHddCtx); + if(pmonAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO_HIGH, + "Turn on Monitor the carrier"); + netif_carrier_on(pmonAdapter->dev); + //Enable Tx queue + hddLog(LOG1, FL("Enabling queues")); + netif_tx_start_all_queues(pmonAdapter->dev); + } + netif_carrier_on(pAdapter->dev); + //Enable Tx queue + hddLog(LOG1, FL("Enabling queues")); + netif_tx_start_all_queues(pAdapter->dev); + + return( vosStatus ); +} + +VOS_STATUS hdd_softap_Register_BC_STA( hdd_adapter_t *pAdapter, v_BOOL_t fPrivacyBit) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + hdd_ap_ctx_t *pHddApCtx; + + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + + pHddCtx->sta_to_adapter[WLAN_RX_BCMC_STA_ID] = pAdapter; +#ifdef WLAN_FEATURE_MBSSID + pHddCtx->sta_to_adapter[pHddApCtx->uBCStaId] = pAdapter; +#else + pHddCtx->sta_to_adapter[WLAN_RX_SAP_SELF_STA_ID] = pAdapter; +#endif + vosStatus = hdd_softap_RegisterSTA( pAdapter, VOS_FALSE, fPrivacyBit, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId, 0, 1, &broadcastMacAddr,0); + + return vosStatus; +} + +VOS_STATUS hdd_softap_Deregister_BC_STA( hdd_adapter_t *pAdapter) +{ + return hdd_softap_DeregisterSTA( pAdapter, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId); +} + +VOS_STATUS hdd_softap_stop_bss( hdd_adapter_t *pAdapter) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + v_U8_t staId = 0; + hdd_context_t *pHddCtx; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + /*bss deregister is not allowed during wlan driver loading or unloading*/ + if ((pHddCtx->isLoadInProgress) || + (pHddCtx->isUnloadInProgress)) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s:Loading_unloading in Progress. Ignore!!!",__func__); + return VOS_STATUS_E_PERM; + } + + vosStatus = hdd_softap_Deregister_BC_STA( pAdapter); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to deregister BC sta Id %d", __func__, (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->uBCStaId); + } + + for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) + { + if (pAdapter->aStaInfo[staId].isUsed)// This excludes BC sta as it is already deregistered + vosStatus = hdd_softap_DeregisterSTA( pAdapter, staId); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to deregister sta Id %d", __func__, staId); + } + } + return vosStatus; +} + +VOS_STATUS hdd_softap_change_STA_state( hdd_adapter_t *pAdapter, v_MACADDR_t *pDestMacAddress, WLANTL_STAStateType state) +{ + v_U8_t ucSTAId = WLAN_MAX_STA_COUNT; + VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS; + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; + + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: enter", __func__); + + if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &ucSTAId)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to find right station", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (FALSE == vos_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, pDestMacAddress)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Station MAC address does not matching", __func__); + return VOS_STATUS_E_FAILURE; + } + + vosStatus = WLANTL_ChangeSTAState( pVosContext, ucSTAId, state, VOS_FALSE); + VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: change station to state %d succeed", __func__, state); + + if (VOS_STATUS_SUCCESS == vosStatus) + { + pAdapter->aStaInfo[ucSTAId].tlSTAState = WLANTL_STA_AUTHENTICATED; + } + + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s exit", __func__); + + return vosStatus; +} + + +VOS_STATUS hdd_softap_GetStaId(hdd_adapter_t *pAdapter, v_MACADDR_t *pMacAddress, v_U8_t *staId) +{ + v_U8_t i; + + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) + { + if (vos_mem_compare(&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, sizeof(v_MACADDR_t)) && + pAdapter->aStaInfo[i].isUsed) + { + *staId = i; + return VOS_STATUS_SUCCESS; + } + } + + return VOS_STATUS_E_FAILURE; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c new file mode 100644 index 000000000000..f46e26b359ec --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c @@ -0,0 +1,3295 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wlan_hdd_tdls.c + + \brief WLAN Host Device Driver implementation for TDLS + + ========================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlan_hdd_tdls.h" +#include "wlan_hdd_cfg80211.h" +#include "vos_sched.h" + +#ifdef CONFIG_TDLS_IMPLICIT +static void wlan_hdd_tdls_pre_setup(struct work_struct *work); +#endif + +/** + * wlan_hdd_tdls_determine_channel_opclass() - determine channel and opclass + * @hddctx: pointer to hdd context + * @adapter: pointer to adapter + * @curr_peer: pointer to current tdls peer + * @channel: pointer to channel + * @opclass: pointer to opclass + * + * Function determines the channel and operating class + * + * Return: None + */ +static void wlan_hdd_tdls_determine_channel_opclass(hdd_context_t *hddctx, + hdd_adapter_t *adapter, hddTdlsPeer_t *curr_peer, + uint32_t *channel, uint32_t *opclass) +{ + hdd_station_ctx_t *hdd_sta_ctx; + + /* + * If tdls offchannel is not enabled then we provide base channel + * and in that case pass opclass as 0 since opclass is mainly needed + * for offchannel cases. + */ + if (!(hddctx->cfg_ini->fEnableTDLSOffChannel) || + (hddctx->tdls_fw_off_chan_mode != ENABLE_CHANSWITCH)) { + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + *channel = hdd_sta_ctx->conn_info.operationChannel; + *opclass = 0; + } else { + *channel = curr_peer->pref_off_chan_num; + *opclass = curr_peer->op_class_for_pref_off_chan; + } +} + +static u8 wlan_hdd_tdls_hash_key (const u8 *mac) +{ + int i; + u8 key = 0; + + for (i = 0; i < 6; i++) + key ^= mac[i]; + + return key; +} + +/** + * wlan_hdd_tdls_disable_offchan_and_teardown_links - Disable offchannel + * and teardown TDLS links + * @hddCtx : pointer to hdd context + * + * Return: None + */ +void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) +{ + u16 connected_tdls_peers = 0; + u8 staidx; + hddTdlsPeer_t *curr_peer = NULL; + hdd_adapter_t *adapter = NULL; + + if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) { + hddLog(LOG1, FL("TDLS mode is disabled OR not enabled in FW")); + return ; + } + + adapter = hdd_get_adapter(hddctx, WLAN_HDD_INFRA_STATION); + + if (adapter == NULL) { + hddLog(LOGE, FL("Station Adapter Not Found")); + return; + } + + connected_tdls_peers = wlan_hdd_tdlsConnectedPeers(adapter); + + if (!connected_tdls_peers) + return ; + + /* TDLS is not supported in case of concurrency. + * Disable TDLS Offchannel in FW to avoid more + * than two concurrent channels and generate TDLS + * teardown indication to supplicant. + * Below function Finds the first connected peer and + * disables TDLS offchannel for that peer. + * FW enables TDLS offchannel only when there is + * one TDLS peer. When there are more than one TDLS peer, + * there will not be TDLS offchannel in FW. + * So to avoid sending multiple request to FW, for now, + * just invoke offchannel mode functions only once + */ + hdd_set_tdls_offchannel(hddctx, hddctx->cfg_ini->fTDLSPrefOffChanNum); + hdd_set_tdls_secoffchanneloffset(hddctx, + TDLS_SEC_OFFCHAN_OFFSET_40PLUS); + hdd_set_tdls_offchannelmode(adapter, DISABLE_CHANSWITCH); + + for (staidx = 0; staidx < hddctx->max_num_tdls_sta; + staidx++) { + if (!hddctx->tdlsConnInfo[staidx].staId) + continue; + + curr_peer = wlan_hdd_tdls_find_all_peer(hddctx, + hddctx->tdlsConnInfo[staidx].peerMac.bytes); + + if (!curr_peer) + continue; + + hddLog(LOG1, FL("indicate TDLS teardown (staId %d)"), + curr_peer->staId); + + wlan_hdd_tdls_indicate_teardown( + curr_peer->pHddTdlsCtx->pAdapter, + curr_peer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } +} + +/** + * hdd_tdls_notify_mode_change - Notify mode change + * @adapter: pointer to hdd adapter + * @hddCtx : pointer to hdd context + * + * Return: None + */ +void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, hdd_context_t *hddctx) +{ + wlan_hdd_tdls_disable_offchan_and_teardown_links(hddctx); +} + +#ifdef CONFIG_TDLS_IMPLICIT +void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx, + hddTdlsPeer_t *curr_candidate) +{ + if (!pHddTdlsCtx || !curr_candidate) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: either pHddTdlsCtx or curr_candidate is null", + __func__); + return; + } + + if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic) + { + /* When TDLS discovery attempt for a peer reaches to max configured + * threshold then tdls support for that peer would be disabled and + * in that case, ignore discovery trigger from FW for that peer. + */ + if (eTDLS_CAP_NOT_SUPPORTED == curr_candidate->tdls_support) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: tdls_support is marked disabled for peer: " + MAC_ADDRESS_STR ", ignore pre_setup_init_work", + __func__, MAC_ADDR_ARRAY(curr_candidate->peerMac)); + return; + } + + pHddTdlsCtx->curr_candidate = curr_candidate; + pHddTdlsCtx->magic = TDLS_CTX_MAGIC; + + schedule_work(&pHddTdlsCtx->implicit_setup); + } +} +#endif + +/* Caller has to take the lock before calling this function */ +static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each_safe (pos, q, head) { + tmp = list_entry(pos, hddTdlsPeer_t, node); + tmp->discovery_processed = 0; + } + } + + return 0; +} + +static tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + VOS_STATUS status = 0; + tANI_U32 count = 0; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + count = count + pHddTdlsCtx->discovery_sent_cnt; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + return count; +} + +static void wlan_hdd_tdls_check_power_save_prohibited(hdd_adapter_t *pAdapter) +{ + tdlsCtx_t *pHddTdlsCtx = NULL; + hdd_context_t *pHddCtx = NULL; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("invalid pAdapter: %p"), pAdapter); + return; + } + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if ((NULL == pHddTdlsCtx) || (NULL == pHddCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx or pHddTdlsCtx points to NULL")); + return; + } + + if ((0 == pHddCtx->connected_peer_count) && + (0 == wlan_hdd_tdls_discovery_sent_cnt(pHddCtx))) + { + sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), + pAdapter->sessionId, 0); + return; + } + sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), + pAdapter->sessionId, 1); + return; +} + +static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx; + + ENTER(); + + pHddTdlsCtx = (tdlsCtx_t *)userData; + if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx or pAdapter points to NULL")); + return; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pHddTdlsCtx->pAdapter->magic) { + hddLog(LOGE, FL("pAdapter has invalid magic")); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter ); + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return; + + mutex_lock(&pHddCtx->tdls_lock); + + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each_safe (pos, q, head) { + tmp = list_entry(pos, hddTdlsPeer_t, node); + if (eTDLS_LINK_DISCOVERING == tmp->link_status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR " to idle state", __func__, + MAC_ADDR_ARRAY(tmp->peerMac)); + mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(tmp, + eTDLS_LINK_IDLE, + eTDLS_LINK_NOT_SUPPORTED); + mutex_lock(&pHddCtx->tdls_lock); + } + } + } + + pHddTdlsCtx->discovery_sent_cnt = 0; + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); + + mutex_unlock(&pHddCtx->tdls_lock); + + wlan_hdd_tdls_check_bmps(pHddTdlsCtx->pAdapter); + + EXIT(); + return; +} + +static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + + if (NULL == pHddTdlsCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return; + } + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) + { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each_safe (pos, q, head) { + tmp = list_entry(pos, hddTdlsPeer_t, node); + list_del(pos); + vos_mem_free(tmp); + tmp = NULL; + } + } +} + +static void wlan_hdd_tdls_schedule_scan(struct work_struct *work) +{ + tdls_scan_context_t *scan_ctx = + container_of(work, tdls_scan_context_t, tdls_scan_work.work); + + if (NULL == scan_ctx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("scan_ctx is NULL")); + return; + } + + if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic)) + return; + + scan_ctx->attempt++; + + wlan_hdd_cfg80211_scan(scan_ctx->wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + scan_ctx->dev, +#endif + scan_ctx->scan_request); +} + +/* stop all monitoring timers per Adapter */ +static void wlan_hdd_tdls_monitor_timers_stop(tdlsCtx_t *pHddTdlsCtx) +{ + vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); +} + +/* stop all the tdls timers running */ +static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx) +{ + wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx); +} + +int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + tdlsCtx_t *pHddTdlsCtx = NULL; + int i; + v_U8_t staIdx; + tdlsInfo_t *tInfo; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if (NULL == pHddCtx) + return -1; + + mutex_lock(&pHddCtx->tdls_lock); + + /* QCA 2.0 Discrete ANDs feature capability in cfg_ini with that + * received from target, so cfg_ini gives combined intersected result + */ + if ((FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) + ) + { + pHddCtx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED; + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s TDLS not enabled (%d) or FW doesn't support", + __func__, pHddCtx->cfg_ini->fEnableTDLSSupport); + return 0; + } + /* TDLS is supported only in STA / P2P Client modes, + * hence the check for TDLS support in a specific Device mode. + * Do not return a failure rather do not continue further + * with the initialization as tdls_init would be called + * during the open adapter for a p2p interface at which point + * the device mode would be a P2P_DEVICE. The point here is to + * continue initialization for STA / P2P Client modes. + * TDLS exit also check for the device mode for clean up hence + * there is no issue even if success is returned. + */ + if (0 == WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) + { + mutex_unlock(&pHddCtx->tdls_lock); + return 0; + } + /* Check for the valid pHddTdlsCtx. If valid do not further + * allocate the memory, rather continue with the initialization. + * If tdls_initialization would get reinvoked without tdls_exit + * getting invoked (SSR) there is no point to further proceed + * with the memory allocations. + */ + if (NULL == pAdapter->sessionCtx.station.pHddTdlsCtx) + { + pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t)); + + if (NULL == pHddTdlsCtx) { + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__); + return -1; + } + /* initialize TDLS pAdater context */ + vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t)); + + vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_discovery_timeout_peer_cb, + pHddTdlsCtx); + + pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx; + + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) + INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]); + } else { + struct list_head *head, *pos, *q; + hddTdlsPeer_t *tmp = NULL; + + pHddTdlsCtx = pAdapter->sessionCtx.station.pHddTdlsCtx; + + /* stop all timers */ + wlan_hdd_tdls_timers_stop(pHddTdlsCtx); + + /* remove entries from peer list only if peer is not forced */ + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each_safe(pos, q, head) { + tmp = list_entry(pos, hddTdlsPeer_t, node); + if (FALSE == tmp->isForcedPeer) { + list_del(pos); + vos_mem_free(tmp); + tmp = NULL; + } else { + tmp->link_status = eTDLS_LINK_IDLE; + tmp->reason = eTDLS_LINK_UNSPECIFIED; + tmp->staId = 0; + tmp->discovery_attempt = 0; + } + } + } + /* reset tdls peer count to 0 */ + pHddCtx->connected_peer_count = 0; + } + + /* initialize TDLS global context */ + pHddCtx->connected_peer_count = 0; + pHddCtx->tdls_nss_switch_in_progress = false; + pHddCtx->tdls_teardown_peers_cnt = 0; + pHddCtx->tdls_nss_teardown_complete = false; + pHddCtx->tdls_nss_transition_mode = TDLS_NSS_TRANSITION_UNKNOWN; + + sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, 0); + + pHddCtx->tdls_scan_ctxt.magic = 0; + pHddCtx->tdls_scan_ctxt.attempt = 0; + pHddCtx->tdls_scan_ctxt.reject = 0; + pHddCtx->tdls_scan_ctxt.scan_request = NULL; + + if (pHddCtx->cfg_ini->fEnableTDLSSleepSta || + pHddCtx->cfg_ini->fEnableTDLSBufferSta || + pHddCtx->cfg_ini->fEnableTDLSOffChannel) + pHddCtx->max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN; + else + pHddCtx->max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA; + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, FL("max_num_tdls_sta: %d"), + pHddCtx->max_num_tdls_sta); + + for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) + { + pHddCtx->tdlsConnInfo[staIdx].staId = 0; + pHddCtx->tdlsConnInfo[staIdx].sessionId = 255; + vos_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac, + sizeof(v_MACADDR_t)) ; + } + + pHddTdlsCtx->pAdapter = pAdapter; + + pHddTdlsCtx->curr_candidate = NULL; + pHddTdlsCtx->magic = 0; + + /* remember configuration even if it is not used right now. it could be used later */ + pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod; + pHddTdlsCtx->threshold_config.tx_packet_n = pHddCtx->cfg_ini->fTDLSTxPacketThreshold; + pHddTdlsCtx->threshold_config.discovery_period_t = pHddCtx->cfg_ini->fTDLSDiscoveryPeriod; + pHddTdlsCtx->threshold_config.discovery_tries_n = pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt; + pHddTdlsCtx->threshold_config.idle_timeout_t = pHddCtx->cfg_ini->fTDLSIdleTimeout; + pHddTdlsCtx->threshold_config.idle_packet_n = pHddCtx->cfg_ini->fTDLSIdlePacketThreshold; + pHddTdlsCtx->threshold_config.rssi_hysteresis = pHddCtx->cfg_ini->fTDLSRSSIHysteresis; + pHddTdlsCtx->threshold_config.rssi_trigger_threshold = pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold; + pHddTdlsCtx->threshold_config.rssi_teardown_threshold = pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold; + pHddTdlsCtx->threshold_config.rssi_delta = pHddCtx->cfg_ini->fTDLSRSSIDelta; + + if (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) + { + pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; + hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__); + } else if (TRUE == pHddCtx->cfg_ini->fTDLSExternalControl) { + pHddCtx->tdls_mode = eTDLS_SUPPORT_EXTERNAL_CONTROL; + } else { + pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED; + } + +#ifdef CONFIG_TDLS_IMPLICIT +#ifdef CONFIG_CNSS + cnss_init_work(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); +#else +#ifdef WLAN_OPEN_SOURCE + INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); +#endif +#endif +#endif + +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, + wlan_hdd_tdls_schedule_scan); +#else +#ifdef WLAN_OPEN_SOURCE + INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, + wlan_hdd_tdls_schedule_scan); +#endif +#endif + + /* + * Release tdls lock before calling in SME api + * which would try to acquire sme lock. + */ + mutex_unlock(&pHddCtx->tdls_lock); + tInfo = vos_mem_malloc(sizeof(tdlsInfo_t)); + if (NULL == tInfo) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed for tInfo", __func__); + vos_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + vos_mem_free(pHddTdlsCtx); + return -1; + } + + tInfo->vdev_id = pAdapter->sessionId; + tInfo->tdls_state = pHddCtx->tdls_mode; + tInfo->notification_interval_ms = pHddTdlsCtx->threshold_config.tx_period_t; + tInfo->tx_discovery_threshold = pHddTdlsCtx->threshold_config.tx_packet_n; + tInfo->tx_teardown_threshold = pHddTdlsCtx->threshold_config.idle_packet_n; + tInfo->rssi_teardown_threshold = + pHddTdlsCtx->threshold_config.rssi_teardown_threshold; + tInfo->rssi_delta = pHddTdlsCtx->threshold_config.rssi_delta; + tInfo->tdls_options = 0; + if (pHddCtx->cfg_ini->fEnableTDLSOffChannel) { + tInfo->tdls_options |= ENA_TDLS_OFFCHAN; + pHddCtx->tdls_fw_off_chan_mode = ENABLE_CHANSWITCH; + } + if (pHddCtx->cfg_ini->fEnableTDLSBufferSta) + tInfo->tdls_options |= ENA_TDLS_BUFFER_STA; + if (pHddCtx->cfg_ini->fEnableTDLSSleepSta) + tInfo->tdls_options |= ENA_TDLS_SLEEP_STA; + tInfo->peer_traffic_ind_window = + pHddCtx->cfg_ini->fTDLSPuapsdPTIWindow; + tInfo->peer_traffic_response_timeout = + pHddCtx->cfg_ini->fTDLSPuapsdPTRTimeout; + tInfo->puapsd_mask = + pHddCtx->cfg_ini->fTDLSUapsdMask; + tInfo->puapsd_inactivity_time = + pHddCtx->cfg_ini->fTDLSPuapsdInactivityTimer; + tInfo->puapsd_rx_frame_threshold = + pHddCtx->cfg_ini->fTDLSRxFrameThreshold; + tInfo->teardown_notification_ms = + pHddCtx->cfg_ini->fTDLSIdleTimeout; + tInfo->tdls_peer_kickout_threshold = + pHddCtx->cfg_ini->tdls_peer_kickout_threshold; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Setting tdls state and param in fw: " + "vdev_id: %d, " + "tdls_state: %d, " + "notification_interval_ms: %d, " + "tx_discovery_threshold: %d, " + "tx_teardown_threshold: %d, " + "rssi_teardown_threshold: %d, " + "rssi_delta: %d, " + "tdls_options: 0x%x, " + "peer_traffic_ind_window: %d, " + "peer_traffic_response_timeout: %d, " + "puapsd_mask: 0x%x, " + "puapsd_inactivity_time: %d, " + "puapsd_rx_frame_threshold: %d, " + "teardown_notification_ms: %d, " + "tdls_peer_kickout_threshold: %d ", + __func__, + tInfo->vdev_id, + tInfo->tdls_state, + tInfo->notification_interval_ms, + tInfo->tx_discovery_threshold, + tInfo->tx_teardown_threshold, + tInfo->rssi_teardown_threshold, + tInfo->rssi_delta, + tInfo->tdls_options, + tInfo->peer_traffic_ind_window, + tInfo->peer_traffic_response_timeout, + tInfo->puapsd_mask, + tInfo->puapsd_inactivity_time, + tInfo->puapsd_rx_frame_threshold, + tInfo->teardown_notification_ms, + tInfo->tdls_peer_kickout_threshold); + + halStatus = sme_UpdateFwTdlsState(pHddCtx->hHal, tInfo, TRUE); + if (eHAL_STATUS_SUCCESS != halStatus) + { + vos_mem_free(tInfo); + vos_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + vos_mem_free(pHddTdlsCtx); + return -1; + } + + return 0; +} + +static void wlan_hdd_tdls_monitor_timers_destroy(tdlsCtx_t *pHddTdlsCtx) +{ + vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + vos_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); +} + +/* destroy all the tdls timers running */ +static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx) +{ + wlan_hdd_tdls_monitor_timers_destroy(pHddTdlsCtx); +} + +static void wlan_hdd_tdls_free_scan_request(tdls_scan_context_t *tdls_scan_ctx) +{ + if (NULL == tdls_scan_ctx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("tdls_scan_ctx is NULL")); + return; + } + + tdls_scan_ctx->attempt = 0; + tdls_scan_ctx->reject = 0; + tdls_scan_ctx->magic = 0; + tdls_scan_ctx->scan_request = NULL; + return; +} + +void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) +{ + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx; + tdlsInfo_t *tInfo; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + if (!pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("pHddCtx is NULL")); + return; + } + + if (!test_bit(TDLS_INIT_DONE, &pAdapter->event_flags)) { + hddLog(LOGE, FL("TDLS init was not done, exit")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) { + /* TDLS context can be null and might have been freed up during + * cleanup for STA adapter + */ + mutex_unlock(&pHddCtx->tdls_lock); + + hddLog(LOG2, FL("pHddTdlsCtx is NULL, adapter device mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + goto done; + } + + vos_flush_work(&pHddTdlsCtx->implicit_setup); + vos_flush_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work); + + + /* must stop timer here before freeing peer list, because peerIdleTimer is + part of peer list structure. */ + wlan_hdd_tdls_timers_destroy(pHddTdlsCtx); + wlan_hdd_tdls_free_list(pHddTdlsCtx); + + mutex_unlock(&pHddCtx->tdls_lock); + + wlan_hdd_tdls_free_scan_request(&pHddCtx->tdls_scan_ctxt); + + /* No need to post message during driver unload because MC thread is + already shutdown */ + if ( !pHddCtx->isUnloadInProgress) + { + tInfo = vos_mem_malloc(sizeof(tdlsInfo_t)); + if (NULL != tInfo) + { + tInfo->vdev_id = pAdapter->sessionId; + tInfo->tdls_state = eTDLS_SUPPORT_DISABLED; + + mutex_lock(&pHddCtx->tdls_lock); + + tInfo->notification_interval_ms = + pHddTdlsCtx->threshold_config.tx_period_t; + tInfo->tx_discovery_threshold = + pHddTdlsCtx->threshold_config.tx_packet_n; + tInfo->tx_teardown_threshold = + pHddTdlsCtx->threshold_config.idle_packet_n; + tInfo->rssi_teardown_threshold = + pHddTdlsCtx->threshold_config.rssi_teardown_threshold; + tInfo->rssi_delta = pHddTdlsCtx->threshold_config.rssi_delta; + + mutex_unlock(&pHddCtx->tdls_lock); + + tInfo->tdls_options = 0; + if (pHddCtx->cfg_ini->fEnableTDLSOffChannel) + tInfo->tdls_options |= ENA_TDLS_OFFCHAN; + if (pHddCtx->cfg_ini->fEnableTDLSBufferSta) + tInfo->tdls_options |= ENA_TDLS_BUFFER_STA; + if (pHddCtx->cfg_ini->fEnableTDLSSleepSta) + tInfo->tdls_options |= ENA_TDLS_SLEEP_STA; + tInfo->peer_traffic_ind_window = + pHddCtx->cfg_ini->fTDLSPuapsdPTIWindow; + tInfo->peer_traffic_response_timeout = + pHddCtx->cfg_ini->fTDLSPuapsdPTRTimeout; + tInfo->puapsd_mask = + pHddCtx->cfg_ini->fTDLSUapsdMask; + tInfo->puapsd_inactivity_time = + pHddCtx->cfg_ini->fTDLSPuapsdInactivityTimer; + tInfo->puapsd_rx_frame_threshold = + pHddCtx->cfg_ini->fTDLSRxFrameThreshold; + tInfo->teardown_notification_ms = + pHddCtx->cfg_ini->fTDLSIdleTimeout; + tInfo->tdls_peer_kickout_threshold = + pHddCtx->cfg_ini->tdls_peer_kickout_threshold; + + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Setting tdls state and param in fw: " + "vdev_id: %d, " + "tdls_state: %d, " + "notification_interval_ms: %d, " + "tx_discovery_threshold: %d, " + "tx_teardown_threshold: %d, " + "rssi_teardown_threshold: %d, " + "rssi_delta: %d, " + "tdls_options: 0x%x, " + "peer_traffic_ind_window: %d, " + "peer_traffic_response_timeout: %d, " + "puapsd_mask: 0x%x, " + "puapsd_inactivity_time: %d, " + "puapsd_rx_frame_threshold: %d, " + "teardown_notification_ms: %d, " + "tdls_peer_kickout_threshold: %d ", + __func__, + tInfo->vdev_id, + tInfo->tdls_state, + tInfo->notification_interval_ms, + tInfo->tx_discovery_threshold, + tInfo->tx_teardown_threshold, + tInfo->rssi_teardown_threshold, + tInfo->rssi_delta, + tInfo->tdls_options, + tInfo->peer_traffic_ind_window, + tInfo->peer_traffic_response_timeout, + tInfo->puapsd_mask, + tInfo->puapsd_inactivity_time, + tInfo->puapsd_rx_frame_threshold, + tInfo->teardown_notification_ms, + tInfo->tdls_peer_kickout_threshold); + + halStatus = sme_UpdateFwTdlsState(pHddCtx->hHal, tInfo, FALSE); + if (eHAL_STATUS_SUCCESS != halStatus) + { + vos_mem_free(tInfo); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed for tInfo", __func__); + } + } + + mutex_lock(&pHddCtx->tdls_lock); + + pHddTdlsCtx->magic = 0; + pHddTdlsCtx->pAdapter = NULL; + + vos_mem_free(pHddTdlsCtx); + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + pHddTdlsCtx = NULL; + + mutex_unlock(&pHddCtx->tdls_lock); + +done: + clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags); +} + +/* if mac address exist, return pointer + if mac address doesn't exist, create a list and add, return pointer + return NULL if fails to get new mac address +*/ +hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac) +{ + struct list_head *head; + hddTdlsPeer_t *peer; + u8 key; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return NULL; + + /* if already there, just update */ + peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); + if (peer != NULL) + { + return peer; + } + + /* not found, allocate and add the list */ + peer = vos_mem_malloc(sizeof(hddTdlsPeer_t)); + if (NULL == peer) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__); + return NULL; + } + + mutex_lock(&pHddCtx->tdls_lock); + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + + if (NULL == pHddTdlsCtx) { + vos_mem_free(peer); + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(LOG1, FL("pHddTdlsCtx is NULL")); + return NULL; + } + + key = wlan_hdd_tdls_hash_key(mac); + head = &pHddTdlsCtx->peer_list[key]; + + vos_mem_zero(peer, sizeof(hddTdlsPeer_t)); + vos_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac)); + peer->pHddTdlsCtx = pHddTdlsCtx; + peer->pref_off_chan_num = pHddCtx->cfg_ini->fTDLSPrefOffChanNum; + peer->op_class_for_pref_off_chan = + wlan_hdd_find_opclass(pHddCtx->hHal, peer->pref_off_chan_num, + pHddCtx->cfg_ini->fTDLSPrefOffChanBandwidth); + + list_add_tail(&peer->node, head); + mutex_unlock(&pHddCtx->tdls_lock); + return peer; +} + +int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, + const u8* mac, + tTDLSCapType cap) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + curr_peer->tdls_support = cap; + + return 0; +} + +void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, + tTDLSLinkStatus status, + tTDLSLinkReason reason) +{ + tANI_U32 state = 0; + tANI_S32 res = 0; + hdd_context_t *pHddCtx; + + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return; + } + + if (curr_peer->pHddTdlsCtx == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer->pHddTdlsCtx is NULL")); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(curr_peer->pHddTdlsCtx->pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %u", + MAC_ADDR_ARRAY(curr_peer->peerMac), status); + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer->link_status = status; + + /* If TDLS link status is already passed the discovery state + * then clear discovery attempt count + */ + if (status >= eTDLS_LINK_DISCOVERED) + { + curr_peer->discovery_attempt = 0; + } + + mutex_unlock(&pHddCtx->tdls_lock); + + if (curr_peer->isForcedPeer && curr_peer->state_change_notification) + { + uint32_t opclass; + uint32_t channel; + hdd_adapter_t *adapter = curr_peer->pHddTdlsCtx->pAdapter; + + /*save the reason for any further query*/ + curr_peer->reason = reason; + + wlan_hdd_tdls_determine_channel_opclass(pHddCtx, adapter, curr_peer, + &channel, &opclass); + + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); + + (*curr_peer->state_change_notification)(curr_peer->peerMac, opclass, + channel, state, res, + adapter); + + } + return; +} + +void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, + const u8* mac, + tTDLSLinkStatus linkStatus, + tTDLSLinkReason reason) +{ + tANI_U32 state = 0; + tANI_S32 res = 0; + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer->link_status= linkStatus; + + /* If TDLS link status is already passed the discovery state + * then clear discovery attempt count + */ + if (linkStatus >= eTDLS_LINK_DISCOVERED) + { + curr_peer->discovery_attempt = 0; + } + + mutex_unlock(&pHddCtx->tdls_lock); + + if (curr_peer->isForcedPeer && curr_peer->state_change_notification) + { + uint32_t opclass; + uint32_t channel; + hdd_adapter_t *adapter = curr_peer->pHddTdlsCtx->pAdapter; + + /*save the reason for any further query*/ + curr_peer->reason = reason; + + + wlan_hdd_tdls_determine_channel_opclass(pHddCtx, adapter, curr_peer, + &channel, &opclass); + + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); + + (curr_peer->state_change_notification)(mac, opclass, channel, state, + res, adapter); + + } + + return; +} + +int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac) +{ + hddTdlsPeer_t *curr_peer; + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx; + + ENTER(); + + if ( NULL == pHddTdlsCtx ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return -1; + } + + pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return -1; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + + if (NULL == curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + if (pHddTdlsCtx->discovery_sent_cnt) + pHddTdlsCtx->discovery_sent_cnt--; + + mutex_lock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_check_power_save_prohibited(pAdapter); + + mutex_unlock(&pHddCtx->tdls_lock); + if (0 == pHddTdlsCtx->discovery_sent_cnt) + { + vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Discovery(%u) Response from " MAC_ADDRESS_STR " link_status %d", + pHddTdlsCtx->discovery_sent_cnt, MAC_ADDR_ARRAY(curr_peer->peerMac), + curr_peer->link_status); + + if (eTDLS_LINK_DISCOVERING == curr_peer->link_status) + { + /* + * Since we are here, it means Throughput threshold is already met. + * Make sure RSSI threshold is also met before setting up TDLS link + */ + if ((tANI_S32) curr_peer->rssi > (tANI_S32) pHddTdlsCtx->threshold_config.rssi_trigger_threshold) + { + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERED, + eTDLS_LINK_SUCCESS); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Rssi Threshold met: "MAC_ADDRESS_STR" rssi = %d threshold= %d" , + MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi, + pHddTdlsCtx->threshold_config.rssi_trigger_threshold); + cfg80211_tdls_oper_request(pAdapter->dev, curr_peer->peerMac, NL80211_TDLS_SETUP, FALSE, GFP_KERNEL); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ", + MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi, + pHddTdlsCtx->threshold_config.rssi_trigger_threshold); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + + /* if RSSI threshold is not met then allow further discovery + * attempts by decrementing count for the last attempt + */ + if (curr_peer->discovery_attempt) + curr_peer->discovery_attempt--; + } + } + else + { + wlan_hdd_tdls_check_bmps(pAdapter); + } + + curr_peer->tdls_support = eTDLS_CAP_SUPPORTED; + EXIT(); + return 0; +} + +int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, + const u8 *mac, + tCsrStaParams *StaParams, + tANI_BOOLEAN isBufSta, + tANI_BOOLEAN isOffChannelSupported) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + curr_peer->uapsdQueues = StaParams->uapsd_queues; + curr_peer->maxSp = StaParams->max_sp; + curr_peer->isBufSta = isBufSta; + curr_peer->isOffChannelSupported = isOffChannelSupported; + + vos_mem_copy(curr_peer->supported_channels, + StaParams->supported_channels, + StaParams->supported_channels_len); + + curr_peer->supported_channels_len = + StaParams->supported_channels_len; + + vos_mem_copy(curr_peer->supported_oper_classes, + StaParams->supported_oper_classes, + StaParams->supported_oper_classes_len); + + curr_peer->supported_oper_classes_len = + StaParams->supported_oper_classes_len; + return 0; +} + +int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter, + const u8 *mac, + tCsrTdlsLinkEstablishParams* tdlsLinkEstablishParams) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + tdlsLinkEstablishParams->isResponder = curr_peer->is_responder; + tdlsLinkEstablishParams->uapsdQueues = curr_peer->uapsdQueues; + tdlsLinkEstablishParams->maxSp = curr_peer->maxSp; + tdlsLinkEstablishParams->isBufSta = curr_peer->isBufSta; + tdlsLinkEstablishParams->isOffChannelSupported = + curr_peer->isOffChannelSupported; + + vos_mem_copy(tdlsLinkEstablishParams->supportedChannels, + curr_peer->supported_channels, + curr_peer->supported_channels_len); + + tdlsLinkEstablishParams->supportedChannelsLen = + curr_peer->supported_channels_len; + + vos_mem_copy(tdlsLinkEstablishParams->supportedOperClasses, + curr_peer->supported_oper_classes, + curr_peer->supported_oper_classes_len); + + tdlsLinkEstablishParams->supportedOperClassesLen = + curr_peer->supported_oper_classes_len; + return 0; +} + +int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_S8 rxRssi) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + curr_peer->rssi = rxRssi; + + return 0; +} + +int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_U8 responder) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + curr_peer->is_responder = responder; + + return 0; +} + +int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_U8 uSignature) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + curr_peer->signature = uSignature; + + return 0; +} + + +void wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac) +{ + memcpy(mac, skb->data, 6); +} + +void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac) +{ + memcpy(mac, skb->data+6, 6); +} + +int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, const u8 *mac, + u8 tx) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode && + eTDLS_SUPPORT_EXTERNAL_CONTROL != pHddCtx->tdls_mode) + return -1; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOG1, FL("curr_peer is NULL")); + return -1; + } + + if (tx) + curr_peer->tx_pkt++; + else + curr_peer->rx_pkt++; + + return 0; +} + +static int wlan_hdd_tdls_check_config(tdls_config_params_t *config) +{ + if (config->tdls > 2) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 1st argument %d. <0...2>", __func__, config->tdls); + return -1; + } + if (config->tx_period_t < CFG_TDLS_TX_STATS_PERIOD_MIN || + config->tx_period_t > CFG_TDLS_TX_STATS_PERIOD_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 2nd argument %d. <%d...%ld>", __func__, config->tx_period_t, + CFG_TDLS_TX_STATS_PERIOD_MIN, CFG_TDLS_TX_STATS_PERIOD_MAX); + return -1; + } + if (config->tx_packet_n < CFG_TDLS_TX_PACKET_THRESHOLD_MIN || + config->tx_packet_n > CFG_TDLS_TX_PACKET_THRESHOLD_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 3rd argument %d. <%d...%ld>", __func__, + config->tx_packet_n, + CFG_TDLS_TX_PACKET_THRESHOLD_MIN, + CFG_TDLS_TX_PACKET_THRESHOLD_MAX); + return -1; + } + if (config->discovery_period_t < CFG_TDLS_DISCOVERY_PERIOD_MIN || + config->discovery_period_t > CFG_TDLS_DISCOVERY_PERIOD_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 4th argument %d. <%d...%ld>", __func__, + config->discovery_period_t, + CFG_TDLS_DISCOVERY_PERIOD_MIN, + CFG_TDLS_DISCOVERY_PERIOD_MAX); + return -1; + } + if (config->discovery_tries_n < CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN || + config->discovery_tries_n > CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 5th argument %d. <%d...%d>", + __func__, + config->discovery_tries_n, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX); + return -1; + } + if (config->idle_timeout_t < CFG_TDLS_IDLE_TIMEOUT_MIN || + config->idle_timeout_t > CFG_TDLS_IDLE_TIMEOUT_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 6th argument %d. <%d...%d>", __func__, + config->idle_timeout_t, + CFG_TDLS_IDLE_TIMEOUT_MIN, + CFG_TDLS_IDLE_TIMEOUT_MAX); + return -1; + } + if (config->idle_packet_n < CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN || + config->idle_packet_n > CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 7th argument %d. <%d...%d>", __func__, config->idle_packet_n, + CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX); + return -1; + } + if (config->rssi_hysteresis < CFG_TDLS_RSSI_HYSTERESIS_MIN || + config->rssi_hysteresis > CFG_TDLS_RSSI_HYSTERESIS_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 8th argument %d. <%d...%d>", __func__, config->rssi_hysteresis, + CFG_TDLS_RSSI_HYSTERESIS_MIN, CFG_TDLS_RSSI_HYSTERESIS_MAX); + return -1; + } + if (config->rssi_trigger_threshold < CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN || + config->rssi_trigger_threshold > CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 9th argument %d. <%d...%d>", __func__, config->rssi_trigger_threshold, + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX); + return -1; + } + if (config->rssi_teardown_threshold < CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN || + config->rssi_teardown_threshold > CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s invalid 10th argument %d. <%d...%d>", __func__, config->rssi_teardown_threshold, + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX); + return -1; + } + return 0; +} + +/* Caller has to take the lock before calling this function */ +static void wlan_tdd_tdls_reset_tx_rx(tdlsCtx_t *pHddTdlsCtx) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each_safe (pos, q, head) { + tmp = list_entry(pos, hddTdlsPeer_t, node); + tmp->tx_pkt = 0; + tmp->rx_pkt = 0; + } + } + + return; +} + +static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx) +{ + wlan_hdd_tdls_timers_stop(pHddTdlsCtx); +} + +static void wlan_hdd_tdls_implicit_enable(tdlsCtx_t *pHddTdlsCtx) +{ + wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx); + pHddTdlsCtx->discovery_sent_cnt = 0; + wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx); + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); +} + +static void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, + eTDLSSupportMode tdls_mode, + v_BOOL_t bUpdateLast) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + VOS_STATUS status; + hdd_adapter_t *pAdapter; + tdlsCtx_t *pHddTdlsCtx; + + ENTER(); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s mode %d", __func__, (int)tdls_mode); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return; + + mutex_lock(&pHddCtx->tdls_lock); + + if (pHddCtx->tdls_mode == tdls_mode) + { + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s already in mode %d", __func__, (int)tdls_mode); + return; + } + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + if(eTDLS_SUPPORT_ENABLED == tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == tdls_mode) + wlan_hdd_tdls_implicit_enable(pHddTdlsCtx); + else if((eTDLS_SUPPORT_DISABLED == tdls_mode) || + (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode)) + wlan_hdd_tdls_implicit_disable(pHddTdlsCtx); + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + if(bUpdateLast) + { + pHddCtx->tdls_mode_last = tdls_mode; + } + else + { + pHddCtx->tdls_mode_last = pHddCtx->tdls_mode; + } + pHddCtx->tdls_mode = tdls_mode; + + mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); +} + +int wlan_hdd_tdls_set_params(struct net_device *dev, tdls_config_params_t *config) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + eTDLSSupportMode req_tdls_mode; + tdlsInfo_t *tdlsParams; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if (NULL == pHddTdlsCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("TDLS not enabled!")); + return -1; + } + + if (wlan_hdd_tdls_check_config(config) != 0) + { + return -1; + } + + /* config->tdls is mapped to 0->1, 1->2, 2->3 */ + req_tdls_mode = config->tdls + 1; + if (pHddCtx->tdls_mode == req_tdls_mode) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s already in mode %d", __func__, config->tdls); + return -1; + } + + /* copy the configuration only when given tdls mode is implicit trigger enable */ + if (eTDLS_SUPPORT_ENABLED == req_tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == req_tdls_mode) + { + memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t)); + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "iw set tdls params: %d %d %d %d %d %d %d %d %d %d", + config->tdls, + config->tx_period_t, + config->tx_packet_n, + config->discovery_period_t, + config->discovery_tries_n, + config->idle_timeout_t, + config->idle_packet_n, + config->rssi_hysteresis, + config->rssi_trigger_threshold, + config->rssi_teardown_threshold); + + wlan_hdd_tdls_set_mode(pHddCtx, req_tdls_mode, TRUE); + + tdlsParams = vos_mem_malloc(sizeof(tdlsInfo_t)); + if (NULL == tdlsParams) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed for tdlsParams", __func__); + return -1; + } + + tdlsParams->vdev_id = pAdapter->sessionId; + tdlsParams->tdls_state = config->tdls; + tdlsParams->notification_interval_ms = config->tx_period_t; + tdlsParams->tx_discovery_threshold = config->tx_packet_n; + tdlsParams->tx_teardown_threshold = config->idle_packet_n; + tdlsParams->rssi_teardown_threshold = config->rssi_teardown_threshold; + tdlsParams->rssi_delta = config->rssi_delta; + tdlsParams->tdls_options = 0; + if (pHddCtx->cfg_ini->fEnableTDLSOffChannel) + tdlsParams->tdls_options |= ENA_TDLS_OFFCHAN; + if (pHddCtx->cfg_ini->fEnableTDLSBufferSta) + tdlsParams->tdls_options |= ENA_TDLS_BUFFER_STA; + if (pHddCtx->cfg_ini->fEnableTDLSSleepSta) + tdlsParams->tdls_options |= ENA_TDLS_SLEEP_STA; + tdlsParams->peer_traffic_ind_window = + pHddCtx->cfg_ini->fTDLSPuapsdPTIWindow; + tdlsParams->peer_traffic_response_timeout = + pHddCtx->cfg_ini->fTDLSPuapsdPTRTimeout; + tdlsParams->puapsd_mask = + pHddCtx->cfg_ini->fTDLSUapsdMask; + tdlsParams->puapsd_inactivity_time = + pHddCtx->cfg_ini->fTDLSPuapsdInactivityTimer; + tdlsParams->puapsd_rx_frame_threshold = + pHddCtx->cfg_ini->fTDLSRxFrameThreshold; + tdlsParams->teardown_notification_ms = + pHddCtx->cfg_ini->fTDLSIdleTimeout; + tdlsParams->tdls_peer_kickout_threshold = + pHddCtx->cfg_ini->tdls_peer_kickout_threshold; + + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Setting tdls state and param in fw: " + "vdev_id: %d, " + "tdls_state: %d, " + "notification_interval_ms: %d, " + "tx_discovery_threshold: %d, " + "tx_teardown_threshold: %d, " + "rssi_teardown_threshold: %d, " + "rssi_delta: %d, " + "tdls_options: 0x%x, " + "peer_traffic_ind_window: %d, " + "peer_traffic_response_timeout: %d, " + "puapsd_mask: 0x%x, " + "puapsd_inactivity_time: %d, " + "puapsd_rx_frame_threshold: %d, " + "teardown_notification_ms: %d, " + "tdls_peer_kickout_threshold: %d ", + __func__, + tdlsParams->vdev_id, + tdlsParams->tdls_state, + tdlsParams->notification_interval_ms, + tdlsParams->tx_discovery_threshold, + tdlsParams->tx_teardown_threshold, + tdlsParams->rssi_teardown_threshold, + tdlsParams->rssi_delta, + tdlsParams->tdls_options, + tdlsParams->peer_traffic_ind_window, + tdlsParams->peer_traffic_response_timeout, + tdlsParams->puapsd_mask, + tdlsParams->puapsd_inactivity_time, + tdlsParams->puapsd_rx_frame_threshold, + tdlsParams->teardown_notification_ms, + tdlsParams->tdls_peer_kickout_threshold); + + halStatus = sme_UpdateFwTdlsState(pHddCtx->hHal, tdlsParams, TRUE); + if (eHAL_STATUS_SUCCESS != halStatus) + { + vos_mem_free(tdlsParams); + return -1; + } + + return 0; +} + +/** + * wlan_hdd_update_tdls_info - update tdls status info + * @adapter: ptr to device adapter. + * @tdls_prohibited: indicates whether tdls is prohibited. + * @tdls_chan_swit_prohibited: indicates whether tdls channel switch + * is prohibited. + * + * Normally an AP does not influence TDLS connection between STAs + * associated to it. But AP may set bits for TDLS Prohibited or + * TDLS Channel Switch Prohibited in Extended Capability IE in + * Assoc/Re-assoc response to STA. So after STA is connected to + * an AP, call this function to update TDLS status as per those + * bits set in Ext Cap IE in received Assoc/Re-assoc response + * from AP. + * + * Return: None. + */ +void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, + bool tdls_chan_swit_prohibited) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tdlsCtx_t *hdd_tdls_ctx = WLAN_HDD_GET_TDLS_CTX_PTR(adapter); + tdlsInfo_t *tdls_param; + eHalStatus hal_status; + + if (!hdd_tdls_ctx) { + /* may be TDLS is not applicable for this adapter */ + hddLog(LOG1, FL("HDD TDLS context is null")); + return; + } + + /* If TDLS support is disabled then no need to update target */ + if (FALSE == hdd_ctx->cfg_ini->fEnableTDLSSupport) { + hddLog(LOG1, FL("TDLS not enabled")); + return; + } + + /* If AP indicated TDLS Prohibited then disable tdls mode */ + mutex_lock(&hdd_ctx->tdls_lock); + if (tdls_prohibited) { + hdd_ctx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED; + } else { + if (FALSE == hdd_ctx->cfg_ini->fEnableTDLSImplicitTrigger) { + hdd_ctx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; + } else if (TRUE == hdd_ctx->cfg_ini->fTDLSExternalControl) { + hdd_ctx->tdls_mode = eTDLS_SUPPORT_EXTERNAL_CONTROL; + } else { + hdd_ctx->tdls_mode = eTDLS_SUPPORT_ENABLED; + } + } + mutex_unlock(&hdd_ctx->tdls_lock); + + tdls_param = vos_mem_malloc(sizeof(*tdls_param)); + if (!tdls_param) { + hddLog(LOGE, + FL("memory allocation failed for tdlsParams")); + return; + } + + tdls_param->vdev_id = adapter->sessionId; + tdls_param->tdls_state = hdd_ctx->tdls_mode; + tdls_param->notification_interval_ms = + hdd_tdls_ctx->threshold_config.tx_period_t; + tdls_param->tx_discovery_threshold = + hdd_tdls_ctx->threshold_config.tx_packet_n; + tdls_param->tx_teardown_threshold = + hdd_tdls_ctx->threshold_config.idle_packet_n; + tdls_param->rssi_teardown_threshold = + hdd_tdls_ctx->threshold_config.rssi_teardown_threshold; + tdls_param->rssi_delta = hdd_tdls_ctx->threshold_config.rssi_delta; + + tdls_param->tdls_options = 0; + + /* Do not enable TDLS offchannel, if AP prohibited TDLS channel switch */ + if ((hdd_ctx->cfg_ini->fEnableTDLSOffChannel) && + (!tdls_chan_swit_prohibited)) { + tdls_param->tdls_options |= ENA_TDLS_OFFCHAN; + } + + if (hdd_ctx->cfg_ini->fEnableTDLSBufferSta) + tdls_param->tdls_options |= ENA_TDLS_BUFFER_STA; + + if (hdd_ctx->cfg_ini->fEnableTDLSSleepSta) + tdls_param->tdls_options |= ENA_TDLS_SLEEP_STA; + + tdls_param->peer_traffic_ind_window = + hdd_ctx->cfg_ini->fTDLSPuapsdPTIWindow; + tdls_param->peer_traffic_response_timeout = + hdd_ctx->cfg_ini->fTDLSPuapsdPTRTimeout; + tdls_param->puapsd_mask = + hdd_ctx->cfg_ini->fTDLSUapsdMask; + tdls_param->puapsd_inactivity_time = + hdd_ctx->cfg_ini->fTDLSPuapsdInactivityTimer; + tdls_param->puapsd_rx_frame_threshold = + hdd_ctx->cfg_ini->fTDLSRxFrameThreshold; + tdls_param->teardown_notification_ms = + hdd_ctx->cfg_ini->fTDLSIdleTimeout; + tdls_param->tdls_peer_kickout_threshold = + hdd_ctx->cfg_ini->tdls_peer_kickout_threshold; + + + hddLog(LOG1, + FL("Setting tdls state and param in fw: " + "vdev_id: %d, " + "tdls_state: %d, " + "notification_interval_ms: %d, " + "tx_discovery_threshold: %d, " + "tx_teardown_threshold: %d, " + "rssi_teardown_threshold: %d, " + "rssi_delta: %d, " + "tdls_options: 0x%x, " + "peer_traffic_ind_window: %d, " + "peer_traffic_response_timeout: %d, " + "puapsd_mask: 0x%x, " + "puapsd_inactivity_time: %d, " + "puapsd_rx_frame_threshold: %d, " + "teardown_notification_ms: %d, " + "tdls_peer_kickout_threshold: %d "), + tdls_param->vdev_id, + tdls_param->tdls_state, + tdls_param->notification_interval_ms, + tdls_param->tx_discovery_threshold, + tdls_param->tx_teardown_threshold, + tdls_param->rssi_teardown_threshold, + tdls_param->rssi_delta, + tdls_param->tdls_options, + tdls_param->peer_traffic_ind_window, + tdls_param->peer_traffic_response_timeout, + tdls_param->puapsd_mask, + tdls_param->puapsd_inactivity_time, + tdls_param->puapsd_rx_frame_threshold, + tdls_param->teardown_notification_ms, + tdls_param->tdls_peer_kickout_threshold); + + hal_status = sme_UpdateFwTdlsState(hdd_ctx->hHal, tdls_param, TRUE); + if (eHAL_STATUS_SUCCESS != hal_status) { + vos_mem_free(tdls_param); + return; + } + + return; +} + +int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, const u8 *mac, u8 staId) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + curr_peer->staId = staId; + + return 0; +} + +int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint32_t chan, uint32_t max_latency, + uint32_t op_class, uint32_t min_bandwidth) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (!pHddCtx) + return -1; + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE); + if (curr_peer == NULL) + { + mutex_unlock(&pHddCtx->tdls_lock); + return -1; + } + + curr_peer->op_class_for_pref_off_chan = (uint8_t)op_class; + curr_peer->pref_off_chan_num = (uint8_t)chan; + + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +/** + * wlan_hdd_tdls_update_peer_mac() - Update the peer mac information to firmware + * @pAdapter: hdd adapter to interface + * @mac: Mac address of the peer to be added + * @peerState: Current state of the peer + * + * This function updates TDLS peer state to firmware. Firmware will update + * connection table based on new peer state. + * + * Return:success (0) or failure (errno value) + */ +int wlan_hdd_tdls_update_peer_mac(hdd_adapter_t *pAdapter, + const uint8_t *mac, + uint32_t peerState) +{ + tSmeTdlsPeerStateParams sme_tdls_peer_state_params; + eHalStatus hal_status = eHAL_STATUS_FAILURE; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + vos_mem_zero(&sme_tdls_peer_state_params, + sizeof(sme_tdls_peer_state_params)); + sme_tdls_peer_state_params.vdevId = pAdapter->sessionId; + vos_mem_copy(&sme_tdls_peer_state_params.peerMacAddr, + mac, sizeof(sme_tdls_peer_state_params.peerMacAddr)); + sme_tdls_peer_state_params.peerState = peerState; + hal_status = sme_UpdateTdlsPeerState(hdd_ctx->hHal, + &sme_tdls_peer_state_params); + if (eHAL_STATUS_SUCCESS != hal_status) { + hddLog(LOGE, FL("sme_UpdateTdlsPeerState failed for " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(mac)); + return -EPERM; + } + return 0; +} + +int wlan_hdd_tdls_set_force_peer(hdd_adapter_t *pAdapter, const u8 *mac, + tANI_BOOLEAN forcePeer) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (!pHddCtx) + return -1; + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE); + if (curr_peer == NULL) + { + mutex_unlock(&pHddCtx->tdls_lock); + return -1; + } + + curr_peer->isForcedPeer = forcePeer; + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +/* if peerMac is found, then it returns pointer to hddTdlsPeer_t + * otherwise, it returns NULL + */ +hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, + const u8 *mac, + tANI_BOOLEAN mutexLock) +{ + u8 key; + struct list_head *pos; + struct list_head *head; + hddTdlsPeer_t *curr_peer; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return NULL; + + if ( mutexLock ) + { + mutex_lock(&pHddCtx->tdls_lock); + } + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) + { + if ( mutexLock ) + mutex_unlock(&pHddCtx->tdls_lock); + return NULL; + } + + key = wlan_hdd_tdls_hash_key(mac); + + head = &pHddTdlsCtx->peer_list[key]; + + list_for_each(pos, head) { + curr_peer = list_entry (pos, hddTdlsPeer_t, node); + if (!memcmp(mac, curr_peer->peerMac, 6)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "findTdlsPeer: found staId %d", curr_peer->staId); + if ( mutexLock ) + mutex_unlock(&pHddCtx->tdls_lock); + return curr_peer; + } + } + if ( mutexLock ) + mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); + return NULL; +} + +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, + const u8 *mac) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + hddTdlsPeer_t *curr_peer= NULL; + VOS_STATUS status = 0; + + mutex_lock(&pHddCtx->tdls_lock); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE); + if (curr_peer) + { + mutex_unlock(&pHddCtx->tdls_lock); + return curr_peer; + } + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + mutex_unlock(&pHddCtx->tdls_lock); + return curr_peer; +} + + +int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const u8 *mac) +{ + hdd_context_t *pHddCtx; + hddTdlsPeer_t *curr_peer; + + pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -1; + } + + /* + * Reset preferred offchannel and opclass for offchannel as + * per INI configuration only if peer is not forced one. For + * forced peer, offchannel and opclass is set in HAL API at the + * time of enabling TDLS for that specific peer and so do not overwrite + * those set by user space. + */ + if (FALSE == curr_peer->isForcedPeer) { + curr_peer->pref_off_chan_num = pHddCtx->cfg_ini->fTDLSPrefOffChanNum; + curr_peer->op_class_for_pref_off_chan = + wlan_hdd_find_opclass(WLAN_HDD_GET_HAL_CTX(pAdapter), + curr_peer->pref_off_chan_num, + pHddCtx->cfg_ini->fTDLSPrefOffChanBandwidth); + } + + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + curr_peer->staId = 0; + + return 0; +} + +tANI_U16 wlan_hdd_tdlsConnectedPeers(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = NULL; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("invalid pAdapter: %p"), pAdapter); + return 0; + } + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return 0; + + EXIT(); + return pHddCtx->connected_peer_count; +} + +int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) +{ + int i; + int len, init_len; + struct list_head *head; + struct list_head *pos; + hddTdlsPeer_t *curr_peer; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return 0; + + init_len = buflen; + len = scnprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", + "MAC", "Id", "cap", "up", "RSSI"); + buf += len; + buflen -= len; + /* 1234567890123456789012345678901234567 */ + len = scnprintf(buf, buflen, "---------------------------------\n"); + buf += len; + buflen -= len; + + mutex_lock(&pHddCtx->tdls_lock); + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) { + mutex_unlock(&pHddCtx->tdls_lock); + len = scnprintf(buf, buflen, "TDLS not enabled\n"); + return len; + } + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + + list_for_each(pos, head) { + curr_peer= list_entry (pos, hddTdlsPeer_t, node); + + if (buflen < 32+1) + break; + len = scnprintf(buf, buflen, + MAC_ADDRESS_STR"%3d%4s%3s%5d\n", + MAC_ADDR_ARRAY(curr_peer->peerMac), + curr_peer->staId, + (curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N", + TDLS_IS_CONNECTED(curr_peer) ? "Y":"N", + curr_peer->rssi); + buf += len; + buflen -= len; + } + } + mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); + return init_len-buflen; +} + +void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter) +{ + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("pHddCtx or pHddTdlsCtx points to NULL")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s, update %d discover %d", __func__, + pHddTdlsCtx->threshold_config.tx_period_t, + pHddTdlsCtx->threshold_config.discovery_period_t); + + if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode) { + wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx); + pHddTdlsCtx->discovery_sent_cnt = 0; + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); + + } + mutex_unlock(&pHddCtx->tdls_lock); + +} + +void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter) +{ + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx or pHddTdlsCtx points to NULL")); + return; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s", __func__); + + mutex_lock(&pHddCtx->tdls_lock); + + if (NULL == pHddTdlsCtx) + { + mutex_unlock(&pHddCtx->tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return; + } + pHddTdlsCtx->discovery_sent_cnt = 0; + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); + + wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx); + wlan_hdd_tdls_free_list(pHddTdlsCtx); + + pHddTdlsCtx->curr_candidate = NULL; + + mutex_unlock(&pHddCtx->tdls_lock); +} + +void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode) +{ + pAdapter->mgmtTxCompletionStatus = statusCode; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Mgmt TX Completion %d", + __func__, statusCode); + complete(&pAdapter->tdls_mgmt_comp); +} + +void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return; + + mutex_lock(&pHddCtx->tdls_lock); + + pHddCtx->connected_peer_count++; + wlan_hdd_tdls_check_power_save_prohibited(pAdapter); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: %d", + __func__, pHddCtx->connected_peer_count); + + mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); +} + +void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return; + + mutex_lock(&pHddCtx->tdls_lock); + + if (pHddCtx->connected_peer_count) + pHddCtx->connected_peer_count--; + wlan_hdd_tdls_check_power_save_prohibited(pAdapter); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: %d", + __func__, pHddCtx->connected_peer_count); + + mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); +} + +void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter) +{ + tdlsCtx_t *pHddTdlsCtx = NULL; + hdd_context_t *pHddCtx = NULL; + hddTdlsPeer_t *curr_peer; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("invalid pAdapter: %p"), pAdapter); + return; + } + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) + { + //getting over logged, so moving log-level to INFO. + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("pHddCtx or pHddTdlsCtx points to NULL")); + return; + } + + curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0); + if (NULL != curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: tdls in progress. Dont check for BMPS " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY (curr_peer->peerMac)); + return; + } + /* + * If Powersave Offload is enabled + * Fw will take care incase of concurrency + */ + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + { + if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) && + (0 == pHddCtx->connected_peer_count) && + (0 == pHddTdlsCtx->discovery_sent_cnt)) + { + if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: No TDLS peer connected/discovery sent. Enable BMPS", + __func__); + hdd_enable_bmps_imps(pHddCtx); + } + } + else + { + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: TDLS peer connected. Disable BMPS", __func__); + hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); + } + } + } + else + { + if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) && + (0 == pHddCtx->connected_peer_count) && + (0 == pHddTdlsCtx->discovery_sent_cnt)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: No TDLS peer connected/discovery sent. Enable BMPS", + __func__); + sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, FALSE); + sme_PsOffloadEnablePowerSave(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: TDLS peer connected. Disable BMPS", __func__); + sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, TRUE); + sme_PsOffloadDisablePowerSave(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + + } + } + return; +} + +/* return pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL. + * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE + * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if + mac is NULL, this argument is ignored, and check for all the peer list. + */ +static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, + const u8 *mac, + u8 skip_self) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *curr_peer; + struct list_head *pos; + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);; + + if (NULL == pHddTdlsCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return NULL; + } + + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each(pos, head) { + curr_peer = list_entry (pos, hddTdlsPeer_t, node); + if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) { + continue; + } + else + { + if (eTDLS_LINK_CONNECTING == curr_peer->link_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + return curr_peer; + } + } + } + } + return NULL; +} + +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, + const u8 *mac, u8 skip_self) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + hddTdlsPeer_t *curr_peer= NULL; + VOS_STATUS status = 0; + + mutex_lock(&pHddCtx->tdls_lock); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self); + if (curr_peer) + { + mutex_unlock(&pHddCtx->tdls_lock); + return curr_peer; + } + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + mutex_unlock(&pHddCtx->tdls_lock); + return NULL; +} + +static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) +{ + tdlsCtx_t *pHddTdlsCtx = + container_of(work, tdlsCtx_t, implicit_setup); + hdd_context_t *pHddCtx; + hddTdlsPeer_t *curr_peer; + hddTdlsPeer_t *temp_peer; + int status; + tSirMacAddr peer_mac; + + ENTER(); + + if (NULL == pHddTdlsCtx) + return; + + if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: tdls magic number mis-match %u", + __func__, pHddTdlsCtx->magic); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer = pHddTdlsCtx->curr_candidate; + + if (NULL == curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + goto done; + } + + vos_mem_copy(&peer_mac, curr_peer->peerMac, sizeof(peer_mac)); + + mutex_unlock(&pHddCtx->tdls_lock); + + /* + * If Powersave Offload is enabled + * Fw will take care incase of concurrency + */ + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + { + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Disable BMPS", __func__); + hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); + } + } + + temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0); + + if (NULL != temp_peer) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored", + __func__, MAC_ADDR_ARRAY(temp_peer->peerMac)); + goto done; + } + + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_SUCCESS); + + mutex_lock(&pHddCtx->tdls_lock); + + /* Ignore discovery attempt if External Control is enabled, that + * is, peer is forced. In that case, continue discovery attempt + * regardless attempt count + */ + if (FALSE == curr_peer->isForcedPeer) + { + if (curr_peer->discovery_attempt >= + pHddTdlsCtx->threshold_config.discovery_tries_n) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: discovery attempt (%d) reached max (%d) for peer " + MAC_ADDRESS_STR ", ignore discovery trigger from fw", + __func__, curr_peer->discovery_attempt, + pHddTdlsCtx->threshold_config.discovery_tries_n, + MAC_ADDR_ARRAY(curr_peer->peerMac)); + curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED; + /* Since TDLS discovery attempt reached the + * maximum threshold, so we remove the peer + * from the FW connection table. + */ + if (0 != wlan_hdd_tdls_update_peer_mac(pHddTdlsCtx->pAdapter, + curr_peer->peerMac, eSME_TDLS_PEER_REMOVE_MAC_ADDR)) + hddLog(LOGE, FL("TDLS Peer mac update Failed " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(curr_peer->peerMac)); + goto done; + } + } + + mutex_unlock(&pHddCtx->tdls_lock); + + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_SUCCESS); + + status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy, + pHddTdlsCtx->pAdapter->dev, + peer_mac); + + mutex_lock(&pHddCtx->tdls_lock); + + if (NULL == pHddTdlsCtx->curr_candidate) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: current candidate Not valid any more", __func__); + goto done; + } + + curr_peer = pHddTdlsCtx->curr_candidate; + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " discovery could not sent", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) + { + mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + mutex_lock(&pHddCtx->tdls_lock); + } + goto done; + } + + pHddTdlsCtx->discovery_sent_cnt++; + + curr_peer->discovery_attempt++; + + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: discovery count %u timeout %u msec", + __func__, pHddTdlsCtx->discovery_sent_cnt, + pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE); + + wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter, + &pHddTdlsCtx->peerDiscoveryTimeoutTimer, + pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE); + +done: + pHddTdlsCtx->curr_candidate = NULL; + pHddTdlsCtx->magic = 0; + mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); + return; +} + +static void wlan_hdd_tdls_pre_setup(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __wlan_hdd_tdls_pre_setup(work); + vos_ssr_unprotect(__func__); +} + +int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request) +{ + tdls_scan_context_t *scan_ctx; + + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return -1; + + scan_ctx = &pHddCtx->tdls_scan_ctxt; + + scan_ctx->wiphy = wiphy; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + scan_ctx->dev = dev; +#endif + + scan_ctx->scan_request = request; + EXIT(); + return 0; +} + +static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request, + unsigned long delay) +{ + if (TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) + { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, dev, request); +#else + wlan_hdd_tdls_copy_scan_context(pHddCtx, wiphy, request); +#endif + pHddCtx->tdls_scan_ctxt.attempt = 0; + pHddCtx->tdls_scan_ctxt.magic = TDLS_CTX_MAGIC; + } + schedule_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, delay); +} + +/* return negative = caller should stop and return error code immediately + return 0 = caller should stop and return success immediately + return 1 = caller can continue to scan + */ +int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + u16 connectedTdlsPeers; + hddTdlsPeer_t *curr_peer; + unsigned long delay; + int ret; + + ENTER(); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret) + return ret; + + /* if tdls is not enabled, then continue scan */ + if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) + return 1; + + curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0); + if (NULL != curr_peer) + { + if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT) + { + pHddCtx->tdls_scan_ctxt.reject = 0; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle", + __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject); + + wlan_hdd_tdls_set_peer_link_status (curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + return 1; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: tdls in progress. scan rejected %d", + __func__, pHddCtx->tdls_scan_ctxt.reject); + return -EBUSY; + } + + /* tdls teardown is ongoing */ + if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode) + { + connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter); + if (connectedTdlsPeers && (pHddCtx->tdls_scan_ctxt.attempt < TDLS_MAX_SCAN_SCHEDULE)) + { + delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: tdls disabled, but still connected_peers %d attempt %d. schedule scan %lu msec", + __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt, delay); + + wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + dev, +#endif + request, + msecs_to_jiffies(delay)); + /* scan should not continue */ + return 0; + } + /* no connected peer or max retry reached, scan continue */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: tdls disabled. connected_peers %d attempt %d. scan allowed", + __func__, connectedTdlsPeers, pHddCtx->tdls_scan_ctxt.attempt); + return 1; + } + /* while tdls is up, first time scan */ + else if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode) + { + /* Disable implicit trigger logic & tdls operation */ + wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE); + /* indicate the teardown all connected to peer */ + connectedTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter); + if (connectedTdlsPeers) + { + tANI_U8 staIdx; + tANI_U8 num = 0; + tANI_U8 i; + tANI_BOOLEAN allPeersBufStas = 1; + hddTdlsPeer_t *curr_peer; + hddTdlsPeer_t *connectedPeerList[HDD_MAX_NUM_TDLS_STA]; + + /* If TDLSScan is enabled then allow scan and maintain tdls link + * regardless if peer is buffer sta capable or not and if device + * is sleep sta capable or not. If peer is not buffer sta capable, + * then Tx would stop when device initiates scan and there will be + * loss of Rx packets since peer would not know when device moves + * away from the tdls channel. + */ + if (1 == pHddCtx->cfg_ini->enable_tdls_scan) { + hddLog(LOG1, + FL("TDLSScan enabled, keep tdls link and allow scan, connectedTdlsPeers: %d"), + connectedTdlsPeers); + return 1; + } + + for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) + { + if (pHddCtx->tdlsConnInfo[staIdx].staId) + { + curr_peer = wlan_hdd_tdls_find_all_peer(pHddCtx, + pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes); + if (curr_peer) + { + connectedPeerList[num++] = curr_peer; + if (!(curr_peer->isBufSta)) + allPeersBufStas = 0; + } + } + } + + if ((TDLS_MAX_CONNECTED_PEERS_TO_ALLOW_SCAN == + connectedTdlsPeers) && + (pHddCtx->cfg_ini->fEnableTDLSSleepSta) && + (allPeersBufStas)) + { + /* All connected peers bufStas and we can be sleepSta + * so allow scan + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: All peers (num %d) bufSTAs, we can be sleep sta, so allow scan, tdls mode changed to %d", + __func__, connectedTdlsPeers, pHddCtx->tdls_mode); + return 1; + } + else + { + for (i = 0; i < num; i++) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: indicate TDLS teadown (staId %d)", + __func__, connectedPeerList[i]->staId); +#ifdef CONFIG_TDLS_IMPLICIT + wlan_hdd_tdls_indicate_teardown( + connectedPeerList[i]->pHddTdlsCtx->pAdapter, + connectedPeerList[i], + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); +#endif + } + } + /* schedule scan */ + delay = (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION*connectedTdlsPeers); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: tdls enabled (mode %d), connected_peers %d. schedule scan %lu msec", + __func__, pHddCtx->tdls_mode, wlan_hdd_tdlsConnectedPeers(pAdapter), + delay); + + wlan_hdd_tdls_scan_init_work (pHddCtx, wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) + dev, +#endif + request, + msecs_to_jiffies(delay)); + /* scan should not continue */ + return 0; + } + /* no connected peer, scan continue */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: tdls_mode %d, and no tdls connection. scan allowed", + __func__, pHddCtx->tdls_mode); + } + EXIT(); + return 1; +} + +void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return; + + /* free allocated memory at scan time */ + wlan_hdd_tdls_free_scan_request (&pHddCtx->tdls_scan_ctxt); + + /* if tdls was enabled before scan, re-enable tdls mode */ + if(eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode_last || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode_last || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode_last) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("%s: revert tdls mode %d"), __func__, pHddCtx->tdls_mode_last); + + wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, FALSE); + } + wlan_hdd_tdls_check_bmps(pAdapter); + EXIT(); +} + +void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter, + vos_timer_t *timer, + v_U32_t expirationTime) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* Check whether driver load unload is in progress */ + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + hddLog(LOGE, FL("Driver load/unload is in progress.")); + return; + } + + if (hdd_connIsConnected(pHddStaCtx)) { + vos_timer_stop(timer); + vos_timer_start(timer, expirationTime); + } +} + +void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, + hddTdlsPeer_t *curr_peer, + tANI_U16 reason) +{ + if ((NULL == pAdapter || WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) || + (NULL == curr_peer)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("parameters passed are invalid")); + return; + } + + if (eTDLS_LINK_CONNECTED != curr_peer->link_status) + return; + + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_TEARING, + eTDLS_LINK_UNSPECIFIED); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Indicating NL80211_TDLS_TEARDOWN to supplicant, reason %d"), + reason); + cfg80211_tdls_oper_request(pAdapter->dev, + curr_peer->peerMac, + NL80211_TDLS_TEARDOWN, + reason, + GFP_KERNEL); +} + +/*EXT TDLS*/ +int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, + cfg80211_exttdls_callback callback) +{ + hdd_context_t *pHddCtx; + hdd_adapter_t *pAdapter; + + if (!curr_peer) return -1; + + pAdapter = curr_peer->pHddTdlsCtx->pAdapter; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if ((NULL == pHddCtx)) return -1; + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer->state_change_notification = callback; + + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, + tANI_U32 *state, + tANI_S32 *reason) +{ + hdd_context_t *hddctx; + hdd_adapter_t *adapter; + + if (!curr_peer) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return; + } + + adapter = curr_peer->pHddTdlsCtx->pAdapter; + hddctx = WLAN_HDD_GET_CTX(adapter); + + if (0 != (wlan_hdd_validate_context(hddctx))) + return; + + *reason = curr_peer->reason; + + switch(curr_peer->link_status) + { + case eTDLS_LINK_IDLE: + case eTDLS_LINK_DISCOVERED: + *state = QCA_WIFI_HAL_TDLS_ENABLED; + break; + case eTDLS_LINK_DISCOVERING: + case eTDLS_LINK_CONNECTING: + *state = QCA_WIFI_HAL_TDLS_ENABLED; + break; + case eTDLS_LINK_CONNECTED: + if ((hddctx->cfg_ini->fEnableTDLSOffChannel) && + (hddctx->tdls_fw_off_chan_mode == ENABLE_CHANSWITCH)) + *state = QCA_WIFI_HAL_TDLS_ESTABLISHED_OFF_CHANNEL; + else + *state = QCA_WIFI_HAL_TDLS_ESTABLISHED; + break; + case eTDLS_LINK_TEARING: + *state = QCA_WIFI_HAL_TDLS_DROPPED; + break; + } +} + +int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, + const tANI_U8* mac, + uint32_t *opclass, + uint32_t *channel, + tANI_U32 *state, + tANI_S32 *reason) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(hddctx))) + return -EINVAL; + + mutex_lock(&hddctx->tdls_lock); + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE); + if (curr_peer == NULL) { + mutex_unlock(&hddctx->tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + *state = QCA_WIFI_HAL_TDLS_DISABLED; + *reason = eTDLS_LINK_UNSPECIFIED; + return -EINVAL; + } + + if (hddctx->cfg_ini->fTDLSExternalControl && + (FALSE == curr_peer->isForcedPeer)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is not Forced")); + *state = QCA_WIFI_HAL_TDLS_DISABLED; + *reason = eTDLS_LINK_UNSPECIFIED; + } else { + wlan_hdd_tdls_determine_channel_opclass(hddctx, pAdapter, curr_peer, + channel, opclass); + + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason); + } + + mutex_unlock(&hddctx->tdls_lock); + + return 0; +} + +static hddTdlsPeer_t * +wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *pAdapter) +{ + int i; + struct list_head *head; + struct list_head *pos; + hddTdlsPeer_t *curr_peer = NULL; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return NULL; + } + mutex_lock(&pHddCtx->tdls_lock); + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) { + mutex_unlock(&pHddCtx->tdls_lock); + return NULL; + } + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each(pos, head) { + curr_peer = list_entry (pos, hddTdlsPeer_t, node); + if (curr_peer && (curr_peer->link_status == eTDLS_LINK_CONNECTED)) { + mutex_unlock(&pHddCtx->tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL(MAC_ADDRESS_STR "eTDLS_LINK_CONNECTED"), + MAC_ADDR_ARRAY(curr_peer->peerMac)); + return curr_peer; + } + } + } + mutex_unlock(&pHddCtx->tdls_lock); + return NULL; +} + +int hdd_set_tdls_offchannel(hdd_context_t *pHddCtx, int offchannel) +{ + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)) { + if (offchannel < CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN || + offchannel > CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid tdls off channel %u"), + offchannel); + return -EINVAL; + } + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Either TDLS or TDLS Off-channel is not enabled")); + return -ENOTSUPP; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("change tdls off channel from %d to %d"), + pHddCtx->tdls_off_channel, offchannel); + pHddCtx->tdls_off_channel = offchannel; + return 0; +} + +int hdd_set_tdls_secoffchanneloffset(hdd_context_t *pHddCtx, int offchanoffset) +{ + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)) { + pHddCtx->tdls_channel_offset = 0; + switch (offchanoffset) { + case TDLS_SEC_OFFCHAN_OFFSET_0: + pHddCtx->tdls_channel_offset = (1 << BW_20_OFFSET_BIT); + break; + case TDLS_SEC_OFFCHAN_OFFSET_40PLUS: + case TDLS_SEC_OFFCHAN_OFFSET_40MINUS: + pHddCtx->tdls_channel_offset = (1 << BW_40_OFFSET_BIT); + break; + case TDLS_SEC_OFFCHAN_OFFSET_80: + pHddCtx->tdls_channel_offset = (1 << BW_80_OFFSET_BIT); + break; + case TDLS_SEC_OFFCHAN_OFFSET_160: + pHddCtx->tdls_channel_offset = (1 << BW_160_OFFSET_BIT); + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid tdls secondary off channel offset %d"), + offchanoffset); + return -EINVAL; + }/* end switch */ + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Either TDLS or TDLS Off-channel is not enabled")); + return -ENOTSUPP; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("change tdls secondary off channel offset to 0x%x"), + pHddCtx->tdls_channel_offset); + return 0; +} + +int hdd_set_tdls_offchannelmode(hdd_adapter_t *pAdapter, int offchanmode) +{ + hddTdlsPeer_t *connPeer = NULL; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tSmeTdlsChanSwitchParams chanSwitchParams; + eHalStatus status = eHAL_STATUS_FAILURE; + + if (offchanmode < ENABLE_CHANSWITCH || offchanmode > DISABLE_CHANSWITCH) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid tdls off channel mode %d"), + offchanmode); + return -EINVAL; + } + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("tdls off channel mode req in not associated state %d"), + offchanmode); + return -EPERM; + } + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)) { + connPeer = wlan_hdd_tdls_find_first_connected_peer(pAdapter); + if (NULL == connPeer) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + FL("No TDLS Connected Peer")); + return -EPERM; + } + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + FL("TDLS Connection not supported")); + return -ENOTSUPP; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("TDLS Channel Switch in swmode=%d tdls_off_channel %d offchanoffset %d"), + offchanmode, pHddCtx->tdls_off_channel, + pHddCtx->tdls_channel_offset); + + switch (offchanmode) { + case ENABLE_CHANSWITCH: + if (pHddCtx->tdls_off_channel && pHddCtx->tdls_channel_offset) { + chanSwitchParams.tdls_off_channel = pHddCtx->tdls_off_channel; + chanSwitchParams.tdls_off_ch_bw_offset = + pHddCtx->tdls_channel_offset; + chanSwitchParams.opclass = + wlan_hdd_find_opclass(WLAN_HDD_GET_HAL_CTX(pAdapter), + chanSwitchParams.tdls_off_channel, + chanSwitchParams.tdls_off_ch_bw_offset); + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("TDLS off-channel parameters are not set yet!!!")); + return -EINVAL; + } + break; + case DISABLE_CHANSWITCH: + chanSwitchParams.tdls_off_channel = 0; + chanSwitchParams.tdls_off_ch_bw_offset = 0; + chanSwitchParams.opclass = 0; + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Incorrect Parameters mode: %d tdls_off_channel: %d offchanoffset: %d"), + offchanmode, pHddCtx->tdls_off_channel, + pHddCtx->tdls_channel_offset); + return -EINVAL; + }/* end switch */ + + chanSwitchParams.vdev_id = pAdapter->sessionId; + chanSwitchParams.tdls_off_ch_mode = offchanmode; + chanSwitchParams.is_responder = connPeer->is_responder; + vos_mem_copy(&chanSwitchParams.peer_mac_addr, + &connPeer->peerMac, sizeof(tSirMacAddr)); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Peer " MAC_ADDRESS_STR " vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d"), + MAC_ADDR_ARRAY(chanSwitchParams.peer_mac_addr), + chanSwitchParams.vdev_id, + chanSwitchParams.tdls_off_channel, + chanSwitchParams.tdls_off_ch_bw_offset, + chanSwitchParams.tdls_off_ch_mode, + chanSwitchParams.is_responder); + + status = sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter), + &chanSwitchParams); + + if (status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Failed to send channel switch request to sme")); + return -EINVAL; + } + + pHddCtx->tdls_fw_off_chan_mode = offchanmode; + + if (ENABLE_CHANSWITCH == offchanmode) { + connPeer->pref_off_chan_num = chanSwitchParams.tdls_off_channel; + connPeer->op_class_for_pref_off_chan = chanSwitchParams.opclass; + } + + return 0; +} + + +/** + * wlan_hdd_tdls_teardown_links() - teardown tdls links + * @hddCtx : pointer to hdd context + * + * Return: 0 if success else non zero + */ +static int wlan_hdd_tdls_teardown_links(hdd_context_t *hddctx, uint32_t mode) +{ + uint16_t connected_tdls_peers = 0; + uint8_t staidx; + int ret = 0; + hddTdlsPeer_t *curr_peer = NULL; + hdd_adapter_t *adapter = NULL; + + if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) { + hddLog(LOG1, FL("TDLS mode is disabled OR not enabled in FW")); + return 0; + } + + adapter = hdd_get_adapter(hddctx, WLAN_HDD_INFRA_STATION); + + if (adapter == NULL) { + hddLog(LOGE, FL("Station Adapter Not Found")); + return 0; + } + + connected_tdls_peers = wlan_hdd_tdlsConnectedPeers(adapter); + + if (!connected_tdls_peers) + return 0; + + for (staidx = 0; staidx < hddctx->max_num_tdls_sta; + staidx++) { + if (!hddctx->tdlsConnInfo[staidx].staId) + continue; + + curr_peer = wlan_hdd_tdls_find_all_peer(hddctx, + hddctx->tdlsConnInfo[staidx].peerMac.bytes); + + if (!curr_peer) + continue; + + /* Check, is connected peer supports more than one stream */ + if (curr_peer->spatial_streams == TDLS_NSS_1x1_MODE) + continue; + + hddLog(LOG1, FL("indicate TDLS teardown (staId %d)"), + curr_peer->staId); + + wlan_hdd_tdls_indicate_teardown( + curr_peer->pHddTdlsCtx->pAdapter, + curr_peer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + mutex_lock(&hddctx->tdls_lock); + hddctx->tdls_teardown_peers_cnt++; + mutex_unlock(&hddctx->tdls_lock); + } + mutex_lock(&hddctx->tdls_lock); + if (hddctx->tdls_teardown_peers_cnt >= 1) { + hddctx->tdls_nss_switch_in_progress = true; + hddLog(LOG1, FL("TDLS peers to be torn down = %d"), + hddctx->tdls_teardown_peers_cnt); + /* Antenna switch 2x2 to 1x1 */ + if (mode == HDD_ANTENNA_MODE_1X1) { + hddctx->tdls_nss_transition_mode = + TDLS_NSS_TRANSITION_2x2_to_1x1; + ret = -EAGAIN; + } else { + /* Antenna switch 1x1 to 2x2 */ + hddctx->tdls_nss_transition_mode = + TDLS_NSS_TRANSITION_1x1_to_2x2; + ret = 0; + } + hddLog(LOG1, + FL("TDLS teardown for antenna switch operation starts")); + } + mutex_unlock(&hddctx->tdls_lock); + return ret; +} + + +/** + * wlan_hdd_tdls_antenna_switch() - Dynamic TDLS antenna switch 1x1 <-> 2x2 + * antenna mode in standalone station + * @hdd_ctx: Pointer to hdd contex + * @adapter: Pointer to hdd adapter + * + * Return: 0 if success else non zero + */ +int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, uint32_t mode) +{ + hdd_station_ctx_t *sta_ctx = &adapter->sessionCtx.station; + uint8_t tdls_peer_cnt; + uint32_t vdev_nss; + hdd_config_t *cfg_ini = hdd_ctx->cfg_ini; + + /* Check whether TDLS antenna switch is in progress */ + if (hdd_ctx->tdls_nss_switch_in_progress) { + if (hdd_ctx->tdls_nss_teardown_complete == false) { + hddLog(LOGE, FL("TDLS nss switch is in progress")); + return -EAGAIN; + } else { + goto tdls_ant_sw_done; + } + } + + /* Check whether TDLS is connected or not */ + mutex_lock(&hdd_ctx->tdls_lock); + tdls_peer_cnt = hdd_ctx->connected_peer_count; + mutex_unlock(&hdd_ctx->tdls_lock); + if (tdls_peer_cnt <= 0) { + hddLog(LOG1, FL("No TDLS connection established")); + goto tdls_ant_sw_done; + } + + /* Check the supported nss for TDLS */ + if (IS_5G_CH(sta_ctx->conn_info.operationChannel)) + vdev_nss = CFG_TDLS_NSS(cfg_ini->vdev_type_nss_5g); + else + vdev_nss = CFG_TDLS_NSS(cfg_ini->vdev_type_nss_2g); + + if (vdev_nss == HDD_ANTENNA_MODE_1X1) { + hddLog(LOG1, + FL("Supported NSS is 1X1, no need to teardown TDLS links")); + goto tdls_ant_sw_done; + } + + /* teardown all the tdls connections */ + return wlan_hdd_tdls_teardown_links(hdd_ctx, mode); + +tdls_ant_sw_done: + return 0; +} + +/** + * hdd_set_tdls_scan_type - set scan during active tdls session + * @hdd_ctx: ptr to hdd context. + * @val: scan type value: 0 or 1. + * + * Set scan type during tdls session. If set to 1, that means driver + * shall maintain tdls link and allow scan regardless if tdls peer is + * buffer sta capable or not and/or if device is sleep sta capable or + * not. If tdls peer is not buffer sta capable then during scan there + * will be loss of Rx packets and Tx would stop when device moves away + * from tdls channel. If set to 0, then driver shall teardown tdls link + * before initiating scan if peer is not buffer sta capable and device + * is not sleep sta capable. By default, scan type is set to 0. + * + * Return: success (0) or failure (errno value) + */ +int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val) +{ + if ((val != 0) && (val != 1)) { + hddLog(LOGE, FL("Incorrect value of tdls scan type: %d"), + val); + return -EINVAL; + } else { + hdd_ctx->cfg_ini->enable_tdls_scan = val; + return 0; + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_trace.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_trace.c new file mode 100644 index 000000000000..65493b2ea1c2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_trace.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*======================================================================== + \file wlan_hdd_trace.c + + \brief WLAN Host Device Driver trace implementation + + ========================================================================*/ + +#include "vos_trace.h" +#include "vos_types.h" +#include "wlan_hdd_trace.h" +#include "wlan_hdd_main.h" + +static tANI_U8 *hddTraceGetEventString(tANI_U32 code) +{ + switch (code) { + CASE_RETURN_STRING(TRACE_CODE_HDD_OPEN_REQUEST); + CASE_RETURN_STRING(TRACE_CODE_HDD_STOP_REQUEST); + CASE_RETURN_STRING(TRACE_CODE_HDD_TX_TIMEOUT); + CASE_RETURN_STRING(TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_SETROAMDELTA_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_GETROAMDELTA_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_GETBAND_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_GETCOUNTRYREV_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_HOSTAPD_OPEN_REQUEST); + CASE_RETURN_STRING(TRACE_CODE_HDD_HOSTAPD_STOP_REQUEST); + CASE_RETURN_STRING(TRACE_CODE_HDD_HOSTAPD_UNINIT_REQUEST); + CASE_RETURN_STRING(TRACE_CODE_HDD_SOFTAP_TX_TIMEOUT); + CASE_RETURN_STRING(TRACE_CODE_HDD_HOSTAPD_SET_MAC_ADDR); + CASE_RETURN_STRING(TRACE_CODE_HDD_HOSTAPD_P2P_SET_NOA_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_HOSTAPD_P2P_SET_PS_IOCTL); + CASE_RETURN_STRING + (TRACE_CODE_HDD_HOSTAPD_SET_SAP_CHANNEL_LIST_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_ADD_VIRTUAL_INTF); + CASE_RETURN_STRING(TRACE_CODE_HDD_DEL_VIRTUAL_INTF); + CASE_RETURN_STRING(TRACE_CODE_HDD_CHANGE_VIRTUAL_INTF); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_START_AP); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_CHANGE_BEACON); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_STOP_AP); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_CHANGE_BSS); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_ADD_KEY); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_GET_KEY); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_CONNECT); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_DISCONNECT); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_JOIN_IBSS); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_LEAVE_IBSS); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SET_TXPOWER); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_GET_TXPOWER); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SCAN); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SCHED_SCAN_START); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SCHED_SCAN_STOP); + CASE_RETURN_STRING(TRACE_CODE_HDD_REMAIN_ON_CHANNEL); + CASE_RETURN_STRING(TRACE_CODE_HDD_REMAINCHANREADYHANDLER); + CASE_RETURN_STRING + (TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL); + CASE_RETURN_STRING(TRACE_CODE_HDD_ACTION); + CASE_RETURN_STRING(TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_GET_STA); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_DEL_STA); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_ADD_STA); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SET_PMKSA); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_DEL_PMKSA); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_TDLS_MGMT); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_RESUME_WLAN); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_SET_MAC_ACL); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_TESTMODE); + CASE_RETURN_STRING(TRACE_CODE_HDD_CFG80211_DUMP_SURVEY); + CASE_RETURN_STRING(TRACE_CODE_HDD_UNSUPPORTED_IOCTL); + CASE_RETURN_STRING + (TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL); + CASE_RETURN_STRING + (TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL); + CASE_RETURN_STRING(TRACE_CODE_HDD_STORE_JOIN_REQ); + CASE_RETURN_STRING(TRACE_CODE_HDD_CLEAR_JOIN_REQ); + CASE_RETURN_STRING(TRACE_CODE_HDD_ISSUE_JOIN_REQ); + + default: + return ("UNKNOWN"); + break; + } +} + +void hddTraceDump(void *pMac, tpvosTraceRecord pRecord, tANI_U16 recIndex) +{ + if (TRACE_CODE_HDD_RX_SME_MSG == pRecord->code) + hddLog(LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, "RX SME MSG:", + get_eRoamCmdStatus_str(pRecord->data), pRecord->data); + else + hddLog(LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, "HDD Event:", + hddTraceGetEventString(pRecord->code), pRecord->data); +} + +void hddTraceInit() +{ + vosTraceRegister(VOS_MODULE_ID_HDD, (tpvosTraceCb) & hddTraceDump); +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tsf.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tsf.c new file mode 100644 index 000000000000..07c11bebcb29 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tsf.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * wlan_hdd_tsf.c - WLAN Host Device Driver tsf related implementation + */ + +#include "wlan_hdd_main.h" +#include "wma_api.h" + +/** + * hdd_capture_tsf() - capture tsf + * + * @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_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len) +{ + int ret = 0; + hdd_station_ctx_t *hdd_sta_ctx; + + if (adapter == NULL || buf == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid pointer")); + return -EINVAL; + } + if (len != 1) + return -EINVAL; + + /* Reset TSF value for new capture */ + adapter->tsf_high = 0; + adapter->tsf_low = 0; + + 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_ERROR, + 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_ERROR, + FL("Soft AP / P2p GO not beaconing")); + buf[0] = TSF_SAP_NOT_STARTED_NO_TSF; + return ret; + } + if (adapter->tsf_state == TSF_CAP_STATE) { + hddLog(VOS_TRACE_LEVEL_ERROR, + 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; + adapter->tsf_state = TSF_CAP_STATE; + ret = process_wma_set_command((int)adapter->sessionId, + (int)GEN_PARAM_CAPTURE_TSF, + adapter->sessionId, + GEN_CMD); + + if (ret != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail")); + buf[0] = TSF_CAPTURE_FAIL; + adapter->tsf_state = TSF_IDLE; + } + 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; + + 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; + 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("fail to get tsf, sta in disconnected")); + 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_ERROR, + FL("Soft AP / P2p GO not beaconing")); + buf[0] = TSF_SAP_NOT_STARTED_NO_TSF; + return ret; + } + if (adapter->tsf_high == 0 && adapter->tsf_low == 0) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("not getting tsf value")); + buf[0] = TSF_NOT_RETURNED_BY_FW; + } else { + buf[0] = TSF_RETURN; + buf[1] = adapter->tsf_low; + buf[2] = adapter->tsf_high; + adapter->tsf_state = TSF_IDLE; + + ret = process_wma_set_command((int)adapter->sessionId, + (int)GEN_PARAM_RESET_TSF_GPIO, + adapter->sessionId, + GEN_CMD); + + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf get fail ")); + buf[0] = TSF_RESET_GPIO_FAIL; + } + hddLog(VOS_TRACE_LEVEL_INFO, + FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"), + buf[0], buf[1], buf[2]); + } + return ret; +} + +/** + * hdd_get_tsf_cb() - handle tsf callback + * + * @pcb_cxt: pointer to the hdd_contex + * @ptsf: pointer to struct stsf + * + * This function handle the event that reported by firmware at first. + * The event contains the vdev_id, current tsf value of this vdev, + * tsf value is 64bits, discripted in two varaible tsf_low and tsf_high. + * These two values each is uint32. + * + * Return: Describe the execute result of this routine + */ +static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf) +{ + hdd_context_t *hddctx; + hdd_adapter_t *adapter; + int status; + + if (pcb_cxt == NULL || ptsf == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return -EINVAL; + } + + hddctx = (hdd_context_t *)pcb_cxt; + status = wlan_hdd_validate_context(hddctx); + if (0 != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("hdd context is not valid")); + return -EINVAL; + } + + adapter = hdd_get_adapter_by_vdev(hddctx, ptsf->vdev_id); + + 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); + + adapter->tsf_low = ptsf->tsf_low; + adapter->tsf_high = ptsf->tsf_high; + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"), + ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high); + return 0; +} + +/** + * wlan_hdd_tsf_init() - set callback to handle tsf value. + * @hdd_ctx: pointer to the hdd_context_t + * + * This function set the callback to sme module, the callback will be + * called when a tsf event is reported by firmware + * + * Return: nothing + */ +void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx) +{ + sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx); +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c new file mode 100644 index 000000000000..245d9cc83ee5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -0,0 +1,2074 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**=========================================================================== + + \file wlan_hdd_tx_rx.c + + \brief Linux HDD Tx/RX APIs + + ==========================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ + +/* Needs to be removed when completely root-caused */ +#define IPV6_MCAST_WAR 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef IPV6_MCAST_WAR +#include +#endif + +#include +#include +#include +#include +#include "sapApi.h" + +#ifdef FEATURE_WLAN_TDLS +#include "wlan_hdd_tdls.h" +#endif + +#ifdef IPA_OFFLOAD +#include +#endif + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ +const v_U8_t hddWmmAcToHighestUp[] = { + SME_QOS_WMM_UP_RESV, + SME_QOS_WMM_UP_EE, + SME_QOS_WMM_UP_VI, + SME_QOS_WMM_UP_NC +}; + +//Mapping Linux AC interpretation to TL AC. +const v_U8_t hdd_QdiscAcToTlAC[] = { + WLANTL_AC_VO, + WLANTL_AC_VI, + WLANTL_AC_BE, + WLANTL_AC_BK, +}; + +static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter); + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#define HDD_EAPOL_ETHER_TYPE (0x888E) +#define HDD_EAPOL_ETHER_TYPE_OFFSET (12) +#define HDD_EAPOL_PACKET_TYPE_OFFSET (15) +#define HDD_EAPOL_KEY_INFO_OFFSET (19) +#define HDD_EAPOL_DEST_MAC_OFFSET (0) +#define HDD_EAPOL_SRC_MAC_OFFSET (6) +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +/*--------------------------------------------------------------------------- + Function definitions and documentation + -------------------------------------------------------------------------*/ + +#ifdef DATA_PATH_UNIT_TEST +//Utility function to dump an sk_buff +static void dump_sk_buff(struct sk_buff * skb) +{ + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: head = %p", __func__, skb->head); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data = %p", __func__, skb->data); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: tail = %p", __func__, skb->tail); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: end = %p", __func__, skb->end); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: len = %d", __func__, skb->len); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: data_len = %d", __func__, skb->data_len); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: mac_len = %d", __func__, skb->mac_len); + + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], + skb->data[5], skb->data[6], skb->data[7]); + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + skb->data[8], skb->data[9], skb->data[10], skb->data[11], skb->data[12], + skb->data[13], skb->data[14], skb->data[15]); +} + +//Function for Unit Test only +static void transport_thread(hdd_adapter_t *pAdapter) +{ + v_U8_t staId; + WLANTL_ACEnumType ac = WLANTL_AC_BE; + vos_pkt_t *pVosPacket = NULL ; + vos_pkt_t dummyPacket; + WLANTL_MetaInfoType pktMetaInfo; + WLANTL_RxMetaInfoType pktRxMetaInfo; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + VOS_ASSERT(0); + return; + } + status = hdd_tx_fetch_packet_cbk( pAdapter->pvosContext, + &staId, + &ac, + &pVosPacket, + &pktMetaInfo ); + if (status != VOS_STATUS_SUCCESS && status != VOS_STATUS_E_EMPTY) + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test FAIL hdd_tx_fetch_packet_cbk", __func__); + else + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test PASS hdd_tx_fetch_packet_cbk", __func__); + + status = hdd_tx_complete_cbk(pAdapter->pvosContext, &dummyPacket, VOS_STATUS_SUCCESS); + if (status != VOS_STATUS_SUCCESS) + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test FAIL hdd_tx_complete_cbk", __func__); + else + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test PASS hdd_tx_complete_cbk", __func__); + + status = hdd_tx_low_resource_cbk(pVosPacket, pAdapter); + if (status != VOS_STATUS_SUCCESS) + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test FAIL hdd_tx_low_resource_cbk", __func__); + else + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test PASS hdd_tx_low_resource_cbk", __func__); + + status = hdd_rx_packet_cbk( pAdapter->pvosContext, + &dummyPacket, + staId, + &pktRxMetaInfo); + if (status != VOS_STATUS_SUCCESS) + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test FAIL hdd_rx_packet_cbk", __func__); + else + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Test PASS hdd_rx_packet_cbk", __func__); + +} +#endif + +/** + * wlan_hdd_is_eapol() - Function to check if frame is EAPOL or not + * @skb: skb data + * + * This function checks if the frame is an EAPOL frame or not + * + * Return: true (1) if packet is EAPOL + * + */ +static bool wlan_hdd_is_eapol(struct sk_buff *skb) +{ + uint16_t ether_type; + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("skb is NULL")); + return false; + } + + ether_type = (uint16_t)(*(uint16_t *) + (skb->data + HDD_ETHERTYPE_802_1_X_FRAME_OFFSET)); + + if (ether_type == VOS_SWAP_U16(HDD_ETHERTYPE_802_1_X)) { + return true; + } else { + /* No error msg handled since this will happen often */ + return false; + } +} + +/** + * wlan_hdd_is_wai() - Check if frame is EAPOL or WAPI + * @skb: skb data + * + * This function checks if the frame is EAPOL or WAPI. + * single routine call will check for both types, thus avoiding + * data path performance penalty. + * + * Return: true (1) if packet is EAPOL or WAPI + * + */ +static bool wlan_hdd_is_eapol_or_wai(struct sk_buff *skb) +{ + uint16_t ether_type; + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("skb is NULL")); + return false; + } + + ether_type = (uint16_t)(*(uint16_t *) + (skb->data + HDD_ETHERTYPE_802_1_X_FRAME_OFFSET)); + + if (ether_type == VOS_SWAP_U16(HDD_ETHERTYPE_802_1_X) || + ether_type == VOS_SWAP_U16(HDD_ETHERTYPE_WAI)) + return true; + + /* No error msg handled since this will happen often */ + return false; +} + + +/**============================================================================ + @brief hdd_flush_tx_queues() - Utility function to flush the TX queues + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +static VOS_STATUS hdd_flush_tx_queues( hdd_adapter_t *pAdapter ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + v_SINT_t i = -1; + hdd_list_node_t *anchor = NULL; + skb_list_node_t *pktNode = NULL; + struct sk_buff *skb = NULL; + + pAdapter->isVosLowResource = VOS_FALSE; + + while (++i != NUM_TX_QUEUES) + { + //Free up any packets in the Tx queue + spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock); + while (true) + { + status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[i], &anchor ); + if(VOS_STATUS_E_EMPTY != status) + { + pktNode = list_entry(anchor, skb_list_node_t, anchor); + skb = pktNode->skb; + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + continue; + } + break; + } + spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); + /* Back pressure is no longer in effect */ + pAdapter->isTxSuspended[i] = VOS_FALSE; + } + + return status; +} + +/**============================================================================ + @brief hdd_flush_ibss_tx_queues() - Utility function to flush the TX queues + in IBSS mode + + @param pAdapter : [in] pointer to adapter context + : [in] Station Id + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +void hdd_flush_ibss_tx_queues( hdd_adapter_t *pAdapter, v_U8_t STAId) +{ + v_U8_t i; + v_SIZE_t size = 0; + v_U8_t skbStaIdx; + skb_list_node_t *pktNode = NULL; + hdd_list_node_t *tmp = NULL, *next = NULL; + struct netdev_queue *txq; + struct sk_buff *skb = NULL; + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL %u"), STAId); + VOS_ASSERT(0); + return; + } + + for (i = 0; i < NUM_TX_QUEUES; i++) + { + spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock); + + if ( list_empty( &pAdapter->wmm_tx_queue[i].anchor ) ) + { + spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); + continue; + } + + /* Iterate through the queue and identify the data for STAId */ + list_for_each_safe(tmp, next, &pAdapter->wmm_tx_queue[i].anchor) + { + pktNode = list_entry(tmp, skb_list_node_t, anchor); + if (pktNode != NULL) + { + skb = pktNode->skb; + + /* Get the STAId from data */ + skbStaIdx = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1); + if (skbStaIdx == STAId) + { + /* Data for STAId is freed along with the queue node */ + + list_del(tmp); + kfree_skb(skb); + + pAdapter->wmm_tx_queue[i].count--; + } + } + } + + /* Restart the queue only-if suspend and the queue was flushed */ + hdd_list_size( &pAdapter->wmm_tx_queue[i], &size ); + txq = netdev_get_tx_queue(pAdapter->dev, i); + + if (VOS_TRUE == pAdapter->isTxSuspended[i] && + size <= HDD_TX_QUEUE_LOW_WATER_MARK && + netif_tx_queue_stopped(txq) ) + { + hddLog(LOG1, FL("Enabling queue for queue %d"), i); + netif_tx_start_queue(txq); + pAdapter->isTxSuspended[i] = VOS_FALSE; + } + + spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); + } +} + +static struct sk_buff* hdd_mon_tx_fetch_pkt(hdd_adapter_t* pAdapter) +{ + skb_list_node_t *pktNode = NULL; + struct sk_buff *skb = NULL; + v_SIZE_t size = 0; + WLANTL_ACEnumType ac = 0; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + hdd_list_node_t *anchor = NULL; + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + VOS_ASSERT(0); + return NULL; + } + + // do we have any packets pending in this AC? + hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size ); + if( size == 0 ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: NO Packet Pending", __func__); + return NULL; + } + + //Remove the packet from the queue + spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock); + status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor ); + spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock); + + if(VOS_STATUS_SUCCESS == status) + { + //If success then we got a valid packet from some AC + pktNode = list_entry(anchor, skb_list_node_t, anchor); + skb = pktNode->skb; + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to remove Packet from the list", + __func__); + + return NULL; + } + + /* If we are in a back pressure situation see if we can turn the + hose back on */ + if ( (pAdapter->isTxSuspended[ac]) && + (size <= HDD_TX_QUEUE_LOW_WATER_MARK) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, + "%s: TX queue[%d] re-enabled", __func__, ac); + pAdapter->isTxSuspended[ac] = VOS_FALSE; + /* Enable Queues which we have disabled earlier */ + netif_tx_start_all_queues( pAdapter->dev ); + } + + return skb; +} + +static void __hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter) +{ + hdd_cfg80211_state_t *cfgState; + struct sk_buff* skb; + hdd_adapter_t* pMonAdapter = NULL; + struct ieee80211_hdr *hdr; + hdd_context_t *hdd_ctx; + int ret = 0; + struct tagCsrDelStaParams delStaParams; + + ENTER(); + if (pAdapter == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + VOS_ASSERT(0); + return; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return; + + pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR ); + if (pMonAdapter == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: pMonAdapter is NULL", __func__); + return; + } + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + + if( NULL != cfgState->buf ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Already one MGMT packet Tx going on", __func__); + return; + } + + skb = hdd_mon_tx_fetch_pkt(pMonAdapter); + + if (NULL == skb) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: No Packet Pending", __func__); + return; + } + + cfgState->buf = vos_mem_malloc( skb->len ); //buf; + if( cfgState->buf == NULL ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to Allocate memory", __func__); + goto fail; + } + + cfgState->len = skb->len; + + vos_mem_copy( cfgState->buf, skb->data, skb->len); + + cfgState->skb = skb; //buf; + cfgState->action_cookie = (uintptr_t)cfgState->buf; + + hdr = (struct ieee80211_hdr *)skb->data; + if( (hdr->frame_control & HDD_FRAME_TYPE_MASK) + == HDD_FRAME_TYPE_MGMT ) + { + if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK) + == HDD_FRAME_SUBTYPE_DEAUTH ) + { + WLANSAP_PopulateDelStaParams(hdr->addr1, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams); + hdd_softap_sta_deauth (pAdapter, &delStaParams); + goto mgmt_handled; + } + else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK) + == HDD_FRAME_SUBTYPE_DISASSOC ) + { + WLANSAP_PopulateDelStaParams(hdr->addr1, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + (SIR_MAC_MGMT_DISASSOC >> 4), + &delStaParams); + hdd_softap_sta_disassoc( pAdapter, &delStaParams ); + goto mgmt_handled; + } + } + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len); + + if (VOS_STATUS_SUCCESS != +#ifdef WLAN_FEATURE_MBSSID + WLANSAP_SendAction( pAdapter->sessionCtx.ap.sapContext, +#else + WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, +#endif + skb->data, skb->len, 0) ) + + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: WLANSAP_SendAction returned fail", __func__); + hdd_sendActionCnf( pAdapter, FALSE ); + } + EXIT(); + return; + +mgmt_handled: + hdd_sendActionCnf( pAdapter, TRUE ); + EXIT(); + return; +fail: + kfree_skb(pAdapter->skb_to_tx); + pAdapter->skb_to_tx = NULL; + return; +} + +/** + * hdd_mon_tx_mgmt_pkt() - monitor mode tx packet api + * @Adapter: Pointer to adapter + * + * Return: none + */ +void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter) +{ + vos_ssr_protect(__func__); + __hdd_mon_tx_mgmt_pkt(pAdapter); + vos_ssr_unprotect(__func__); +} + + +static void __hdd_mon_tx_work_queue(struct work_struct *work) +{ + hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, monTxWorkQueue); + __hdd_mon_tx_mgmt_pkt(pAdapter); +} + +/** + * hdd_mon_tx_work_queue() - monitor mode tx work handler + * @work: Pointer to work + * + * Return: none + */ +void hdd_mon_tx_work_queue(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __hdd_mon_tx_work_queue(work); + vos_ssr_unprotect(__func__); +} + +int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + v_U16_t rt_hdr_len; + struct ieee80211_hdr *hdr; + hdd_adapter_t *pPgBkAdapter, *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct ieee80211_radiotap_header *rtap_hdr = + (struct ieee80211_radiotap_header *)skb->data; + + /*Supplicant sends the EAPOL packet on monitor interface*/ + pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx; + if(pPgBkAdapter == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "%s: No Adapter to piggy back. Dropping the pkt on monitor inf", + __func__); + goto fail; /* too short to be possibly valid */ + } + + /* Check if total skb length is greater then radio tap + header length of not */ + if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) + goto fail; /* too short to be possibly valid */ + + /* check if radio tap header version is correct or not */ + if (unlikely(rtap_hdr->it_version)) + goto fail; /* only version 0 is supported */ + + /*Strip off the radio tap header*/ + rt_hdr_len = ieee80211_get_radiotap_len(skb->data); + + /* Check if skb length if greater then total radio tap header length ot not*/ + if (unlikely(skb->len < rt_hdr_len)) + goto fail; + + /* Update the trans_start for this netdev */ + dev->trans_start = jiffies; + /* + * fix up the pointers accounting for the radiotap + * header still being in there. + */ + skb_set_mac_header(skb, rt_hdr_len); + skb_set_network_header(skb, rt_hdr_len); + skb_set_transport_header(skb, rt_hdr_len); + + /* Pull rtap header out of the skb */ + skb_pull(skb, rt_hdr_len); + + /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after + * radio tap header and 802.11 header starts + */ + hdr = (struct ieee80211_hdr *)skb->data; + + /* Send data frames through the normal Data path. In this path we will + * convert rcvd 802.11 packet to 802.3 packet */ + if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_DATA) + { + v_U8_t da[6]; + v_U8_t sa[6]; + + memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE); + memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE); + + /* Pull 802.11 MAC header */ + skb_pull(skb, HDD_80211_HEADER_LEN); + + if ( HDD_FRAME_SUBTYPE_QOSDATA == + (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)) + { + skb_pull(skb, HDD_80211_HEADER_QOS_CTL); + } + + /* Pull LLC header */ + skb_pull(skb, HDD_LLC_HDR_LEN); + + /* Create space for Ethernet header */ + skb_push(skb, HDD_MAC_HDR_SIZE*2); + memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE); + memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE); + + /* Only EAPOL Data packets are allowed through monitor interface */ + if (vos_be16_to_cpu( + (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) ) + != HDD_ETHERTYPE_802_1_X) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "%s: Not a Eapol packet. Drop this frame", __func__); + //If not EAPOL frames, drop them. + kfree_skb(skb); + return NETDEV_TX_OK; + } + + skb->protocol = htons(HDD_ETHERTYPE_802_1_X); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + hdd_hostapd_select_queue(pPgBkAdapter->dev, skb, NULL, NULL); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) + hdd_hostapd_select_queue(pPgBkAdapter->dev, skb, NULL); +#else + hdd_hostapd_select_queue(pPgBkAdapter->dev, skb); +#endif + + return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev ); + } + else + { + VOS_STATUS status; + WLANTL_ACEnumType ac = 0; + skb_list_node_t *pktNode = NULL; + v_SIZE_t pktListSize = 0; + + spin_lock(&pAdapter->wmm_tx_queue[ac].lock); + //If we have already reached the max queue size, disable the TX queue + if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size) + { + /* We want to process one packet at a time, so lets disable all TX queues + * and re-enable the queues once we get TX feedback for this packet */ + hddLog(LOG1, FL("Disabling queues")); + netif_tx_stop_all_queues(pAdapter->dev); + pAdapter->isTxSuspended[ac] = VOS_TRUE; + spin_unlock(&pAdapter->wmm_tx_queue[ac].lock); + return NETDEV_TX_BUSY; + } + spin_unlock(&pAdapter->wmm_tx_queue[ac].lock); + + //Use the skb->cb field to hold the list node information + pktNode = (skb_list_node_t *)&skb->cb; + + //Stick the OS packet inside this node. + pktNode->skb = skb; + + INIT_LIST_HEAD(&pktNode->anchor); + + //Insert the OS packet into the appropriate AC queue + spin_lock(&pAdapter->wmm_tx_queue[ac].lock); + status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], + &pktNode->anchor, &pktListSize ); + spin_unlock(&pAdapter->wmm_tx_queue[ac].lock); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s:Insert Tx queue failed. Pkt dropped", __func__); + kfree_skb(skb); + return NETDEV_TX_OK; + } + + if (pktListSize == 1) { + /* + * In this context we cannot acquire any mutex etc. And to transmit + * this packet we need to call SME API. So to take care of this we will + * schedule a work queue + */ + schedule_work(&pPgBkAdapter->monTxWorkQueue); + } + return NETDEV_TX_OK; + } + +fail: + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Packet Rcvd at Monitor interface is not proper," + " Dropping the packet", + __func__); + kfree_skb(skb); + return NETDEV_TX_OK; +} + +#ifdef QCA_LL_TX_FLOW_CT +/**============================================================================ + @brief hdd_tx_resume_timer_expired_handler() - Resume OS TX Q timer expired + handler. + If Blocked OS Q is not resumed during timeout period, to prevent + permanent stall, resume OS Q forcefully. + + @param adapter_context : [in] pointer to vdev adapter + + @return : NONE + ===========================================================================*/ +void hdd_tx_resume_timer_expired_handler(void *adapter_context) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + + if (!pAdapter) + { + /* INVALID ARG */ + return; + } + + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(pAdapter->dev); + pAdapter->hdd_stats.hddTxRxStats.txflow_unpause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = FALSE; + + return; +} + +/**============================================================================ + @brief hdd_tx_resume_cb() - Resume OS TX Q. + Q was stopped due to WLAN TX path low resource condition + + @param adapter_context : [in] pointer to vdev adapter + @param tx_resume : [in] TX Q resume trigger + + @return : NONE + ===========================================================================*/ +void hdd_tx_resume_cb(void *adapter_context, + v_BOOL_t tx_resume) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)adapter_context; + hdd_station_ctx_t *hdd_sta_ctx = NULL; + + if (!pAdapter) + { + /* INVALID ARG */ + return; + } + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* Resume TX */ + if (VOS_TRUE == tx_resume) + { + if (VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + vos_timer_stop(&pAdapter->tx_flow_control_timer); + } + if (adf_os_unlikely(hdd_sta_ctx->hdd_ReassocScenario)) { + hddLog(LOGW, + FL("flow control, tx queues un-pause avoided as we are in REASSOCIATING state")); + return; + } + hddLog(LOG1, FL("Enabling queues")); + netif_tx_wake_all_queues(pAdapter->dev); + pAdapter->hdd_stats.hddTxRxStats.txflow_unpause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = FALSE; + + } +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + else if (VOS_FALSE == tx_resume) /* Pause TX */ + { + hddLog(LOG1, FL("Disabling queues")); + netif_tx_stop_all_queues(pAdapter->dev); + if (VOS_TIMER_STATE_STOPPED == + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer)) + { + VOS_STATUS status; + status = vos_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + if ( !VOS_IS_STATUS_SUCCESS(status) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to start tx_flow_control_timer", __func__); + } + else + { + pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; + } + } + pAdapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = TRUE; + + } +#endif + + return; +} +#endif /* QCA_LL_TX_FLOW_CT */ + +/**============================================================================ + @brief hdd_hard_start_xmit() - Function registered with the Linux OS for + transmitting packets. This version of the function directly passes the packet + to Transport Layer. + + @param skb : [in] pointer to OS packet (sk_buff) + @param dev : [in] pointer to network device + + @return : NET_XMIT_DROP if packets are dropped + : NET_XMIT_SUCCESS if packet is enqueued successfully + ===========================================================================*/ +int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + VOS_STATUS status; + WLANTL_ACEnumType ac; + sme_QosWmmUpType up; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + v_BOOL_t granted; + v_U8_t STAId = WLAN_MAX_STA_COUNT; + hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; +#ifdef QCA_PKT_PROTO_TRACE + hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter); + v_U8_t proto_type = 0; +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef QCA_WIFI_FTM + if (hdd_get_conparam() == VOS_FTM_MODE) { + kfree_skb(skb); + return NETDEV_TX_OK; + } +#endif + + ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; + + if(vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, + "LOPG in progress, dropping the packet\n"); + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + kfree_skb(skb); + return NETDEV_TX_OK; + } + + if (WLAN_HDD_IBSS == pAdapter->device_mode) + { + v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data; + + if ( VOS_STATUS_SUCCESS != + hdd_Ibss_GetStaId(&pAdapter->sessionCtx.station, + pDestMacAddress, &STAId)) + { + STAId = HDD_WLAN_INVALID_STA_ID; + } + + + if ((STAId == HDD_WLAN_INVALID_STA_ID) && + (vos_is_macaddr_broadcast( pDestMacAddress ) || + vos_is_macaddr_group(pDestMacAddress))) + { + STAId = IBSS_BROADCAST_STAID; + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW, + "%s: BC/MC packet", __func__); + } + else if (STAId == HDD_WLAN_INVALID_STA_ID) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Received Unicast frame with invalid staID", __func__); + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + kfree_skb(skb); + return NETDEV_TX_OK; + } + } + else + { + if (WLAN_HDD_OCB != pAdapter->device_mode + && eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + FL("Tx frame in not associated state in %d context"), + pAdapter->device_mode); + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + kfree_skb(skb); + return NETDEV_TX_OK; + } + STAId = pHddStaCtx->conn_info.staId[0]; + } + +#ifdef QCA_LL_TX_FLOW_CT + if (VOS_FALSE == + WLANTL_GetTxResource((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + pAdapter->sessionId, + pAdapter->tx_flow_low_watermark, + pAdapter->tx_flow_high_watermark_offset)) { + hddLog(LOG1, FL("Disabling queues")); + netif_tx_stop_all_queues(dev); + if ((pAdapter->tx_flow_timer_initialized == TRUE) && + (VOS_TIMER_STATE_STOPPED == + vos_timer_getCurrentState(&pAdapter->tx_flow_control_timer))) { + vos_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; + pAdapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++; + pAdapter->hdd_stats.hddTxRxStats.is_txflow_paused = TRUE; + } + } +#endif /* QCA_LL_TX_FLOW_CT */ + + //Get TL AC corresponding to Qdisc queue index/AC. + ac = hdd_QdiscAcToTlAC[skb->queue_mapping]; + + //user priority from IP header, which is already extracted and set from + //select_queue call back function + up = skb->priority; + + ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac]; +#ifdef HDD_WMM_DEBUG + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "%s: Classified as ac %d up %d", __func__, ac, up); +#endif // HDD_WMM_DEBUG + + if (HDD_PSB_CHANGED == pAdapter->psbChanged) + { + /* Function which will determine acquire admittance for a + * WMM AC is required or not based on psb configuration done + * in the framework + */ + hdd_wmm_acquire_access_required(pAdapter, ac); + } + + /* + * Make sure we already have access to this access category + * or it is EAPOL or WAPI frame during initial authentication which + * can have artifically boosted higher qos priority. + */ + + if (((pAdapter->psbChanged & (1 << ac)) && + likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) || + ((pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE) && + wlan_hdd_is_eapol_or_wai(skb))) + { + granted = VOS_TRUE; + } + else + { + status = hdd_wmm_acquire_access( pAdapter, ac, &granted ); + pAdapter->psbChanged |= (1 << ac); + } + + if (!granted) { + bool isDefaultAc = VOS_FALSE; + /* ADDTS request for this AC is sent, for now + * send this packet through next available lower + * Access category until ADDTS negotiation completes. + */ + while (!likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed)) { + switch(ac) { + case WLANTL_AC_VO: + ac = WLANTL_AC_VI; + up = SME_QOS_WMM_UP_VI; + break; + case WLANTL_AC_VI: + ac = WLANTL_AC_BE; + up = SME_QOS_WMM_UP_BE; + break; + case WLANTL_AC_BE: + ac = WLANTL_AC_BK; + up = SME_QOS_WMM_UP_BK; + break; + default: + ac = WLANTL_AC_BK; + up = SME_QOS_WMM_UP_BK; + isDefaultAc = VOS_TRUE; + break; + } + if (isDefaultAc) + break; + } + skb->priority = up; + skb->queue_mapping = hddLinuxUpToAcMap[up]; + } + + wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED); + +#ifdef QCA_PKT_PROTO_TRACE + if ((hddCtxt->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_EAPOL) || + (hddCtxt->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_DHCP)) + { + proto_type = vos_pkt_get_proto_type(skb, + hddCtxt->cfg_ini->gEnableDebugLog, 0); + if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type) + { + vos_pkt_trace_buf_update("ST:T:EPL"); + } + else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type) + { + vos_pkt_trace_buf_update("ST:T:DHC"); + } + } +#endif /* QCA_PKT_PROTO_TRACE */ + + pAdapter->stats.tx_bytes += skb->len; + ++pAdapter->stats.tx_packets; + + /* + * TODO: Should we stop net queues when txrx returns non-NULL?. + */ + if (WLANTL_SendSTA_DataFrame((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + STAId, (adf_nbuf_t) skb +#ifdef QCA_PKT_PROTO_TRACE + , proto_type +#endif /* QCA_PKT_PROTO_TRACE */ + ) != NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, + "%s: Failed to send packet to txrx for staid:%d", + __func__, STAId); + goto drop_pkt; + } + + dev->trans_start = jiffies; + + return NETDEV_TX_OK; + +drop_pkt: + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac]; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_hard_start_xmit(skb, dev); + vos_ssr_unprotect(__func__); + return ret; +} + +/**============================================================================ + @brief hdd_Ibss_GetStaId() - Get the StationID using the Peer Mac address + + @param pHddStaCtx : [in] pointer to HDD Station Context + pMacAddress [in] pointer to Peer Mac address + staID [out] pointer to Station Index + @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE + ===========================================================================*/ + +VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAddress, v_U8_t *staId) +{ + v_U8_t idx; + + for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++) + { + if (vos_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[ idx ], + pMacAddress, sizeof(v_MACADDR_t))) + { + *staId = pHddStaCtx->conn_info.staId[idx]; + return VOS_STATUS_SUCCESS; + } + } + + return VOS_STATUS_E_FAILURE; +} + +/** + * __hdd_tx_timeout() - HDD tx timeout handler + * @dev: pointer to net_device structure + * + * Function called by OS if there is any timeout during transmission. + * Since HDD simply enqueues packet and returns control to OS right away, + * this would never be invoked + * + * Return: none + */ +static void __hdd_tx_timeout(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct netdev_queue *txq; + int i = 0; + + hddLog(LOGE, FL("Transmission timeout occurred jiffies %lu trans_start %lu"), + jiffies, dev->trans_start); + /* + * Getting here implies we disabled the TX queues for too long. Queues are + * disabled either because of disassociation or low resource scenarios. In + * case of disassociation it is ok to ignore this. But if associated, we have + * do possible recovery here. + */ + + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "num_bytes AC0: %d AC1: %d AC2: %d AC3: %d", + pAdapter->wmm_tx_queue[0].count, + pAdapter->wmm_tx_queue[1].count, + pAdapter->wmm_tx_queue[2].count, + pAdapter->wmm_tx_queue[3].count); + + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "tx_suspend AC0: %d AC1: %d AC2: %d AC3: %d", + pAdapter->isTxSuspended[0], + pAdapter->isTxSuspended[1], + pAdapter->isTxSuspended[2], + pAdapter->isTxSuspended[3]); + + for (i = 0; i < NUM_TX_QUEUES; i++) { + txq = netdev_get_tx_queue(dev, i); + hddLog(LOG1, FL("Queue%d status: %d txq->trans_start %lu"), + i, netif_tx_queue_stopped(txq), txq->trans_start); + } + + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "carrier state: %d", netif_carrier_ok(dev)); +} + +/** + * hdd_tx_timeout() - Wrapper function to protect __hdd_tx_timeout from SSR + * @dev: pointer to net_device structure + * + * Function called by OS if there is any timeout during transmission. + * Since HDD simply enqueues packet and returns control to OS right away, + * this would never be invoked + * + * Return: none + */ +void hdd_tx_timeout(struct net_device *dev) +{ + vos_ssr_protect(__func__); + __hdd_tx_timeout(dev); + vos_ssr_unprotect(__func__); +} + +/** + * __hdd_stats() - Function registered with the Linux OS for + * device TX/RX statistics + * @dev: pointer to net_device structure + * + * Return: pointer to net_device_stats structure + */ +static struct net_device_stats *__hdd_stats(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + return &pAdapter->stats; +} + +/** + * hdd_stats() - SSR wrapper for __hdd_stats + * @dev: pointer to net_device structure + * + * Return: pointer to net_device_stats structure + */ +struct net_device_stats* hdd_stats(struct net_device *dev) +{ + struct net_device_stats *dev_stats; + + vos_ssr_protect(__func__); + dev_stats = __hdd_stats(dev); + vos_ssr_unprotect(__func__); + + return dev_stats; +} + +/**============================================================================ + @brief hdd_init_tx_rx() - Init function to initialize Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_init_tx_rx( hdd_adapter_t *pAdapter ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + v_SINT_t i = -1; + + if ( NULL == pAdapter ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + pAdapter->isVosOutOfResource = VOS_FALSE; + pAdapter->isVosLowResource = VOS_FALSE; + + //vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats)); + //Will be zeroed out during alloc + + while (++i != NUM_TX_QUEUES) + { + pAdapter->isTxSuspended[i] = VOS_FALSE; + hdd_list_init( &pAdapter->wmm_tx_queue[i], HDD_TX_QUEUE_MAX_LEN); + } + + return status; +} + + +/**============================================================================ + @brief hdd_deinit_tx_rx() - Deinit function to clean up Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_deinit_tx_rx( hdd_adapter_t *pAdapter ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + v_SINT_t i = -1; + + if ( NULL == pAdapter ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + status = hdd_flush_tx_queues(pAdapter); + if (VOS_STATUS_SUCCESS != status) + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, + FL("failed to flush tx queues")); + + while (++i != NUM_TX_QUEUES) + { + //Free up actual list elements in the Tx queue + hdd_list_destroy( &pAdapter->wmm_tx_queue[i] ); + } + + return status; +} + + +/**============================================================================ + @brief hdd_disconnect_tx_rx() - Disconnect function to clean up Tx/RX + modules in HDD + + @param pAdapter : [in] pointer to adapter context + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_disconnect_tx_rx( hdd_adapter_t *pAdapter ) +{ + return hdd_flush_tx_queues(pAdapter); +} + + +/**============================================================================ + @brief hdd_IsEAPOLPacket() - Checks the packet is EAPOL or not. + + @param pVosPacket : [in] pointer to vos packet + @return : VOS_TRUE if the packet is EAPOL + : VOS_FALSE otherwise + ===========================================================================*/ + +v_BOOL_t hdd_IsEAPOLPacket( vos_pkt_t *pVosPacket ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + v_BOOL_t fEAPOL = VOS_FALSE; + void *pBuffer = NULL; + + + vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET, + &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE ); + if (VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + if (pBuffer && vos_be16_to_cpu( *(unsigned short*)pBuffer) == HDD_ETHERTYPE_802_1_X ) + { + fEAPOL = VOS_TRUE; + } + } + + return fEAPOL; +} + + +#ifdef FEATURE_WLAN_WAPI // Need to update this function +/**============================================================================ + @brief hdd_IsWAIPacket() - Checks the packet is WAI or not. + + @param pVosPacket : [in] pointer to vos packet + @return : VOS_TRUE if the packet is WAI + : VOS_FALSE otherwise + ===========================================================================*/ + +v_BOOL_t hdd_IsWAIPacket( vos_pkt_t *pVosPacket ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + v_BOOL_t fIsWAI = VOS_FALSE; + void *pBuffer = NULL; + + // Need to update this function + vosStatus = vos_pkt_peek_data( pVosPacket, (v_SIZE_t)HDD_ETHERTYPE_802_1_X_FRAME_OFFSET, + &pBuffer, HDD_ETHERTYPE_802_1_X_SIZE ); + + if (VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + if (pBuffer && vos_be16_to_cpu( *((unsigned short*)pBuffer)) == HDD_ETHERTYPE_WAI) + { + fIsWAI = VOS_TRUE; + } + } + + return fIsWAI; +} +#endif /* FEATURE_WLAN_WAPI */ + +/**============================================================================ + @brief hdd_tx_complete_cbk() - Callback function invoked by TL + to indicate that a packet has been transmitted across the SDIO bus + successfully. OS packet resources can be released after this cbk. + + @param vosContext : [in] pointer to VOS context + @param pVosPacket : [in] pointer to VOS packet (containing skb) + @param vosStatusIn : [in] status of the transmission + + @return : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext, + vos_pkt_t *pVosPacket, + VOS_STATUS vosStatusIn ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = NULL; + hdd_context_t *pHddCtx = NULL; + void* pOsPkt = NULL; + + if( ( NULL == vosContext ) || ( NULL == pVosPacket ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + //Return the skb to the OS + status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE ); + if (!VOS_IS_STATUS_SUCCESS( status )) + { + //This is bad but still try to free the VOSS resources if we can + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failure extracting skb from vos pkt", __func__); + vos_pkt_return_packet( pVosPacket ); + return VOS_STATUS_E_FAILURE; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); + //Get the Adapter context. + pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION); + if((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + hddLog(LOG1, FL("Invalid adapter %p"), pAdapter); + else + ++pAdapter->hdd_stats.hddTxRxStats.txCompleted; + + kfree_skb((struct sk_buff *)pOsPkt); + + //Return the VOS packet resources. + status = vos_pkt_return_packet( pVosPacket ); + if (!VOS_IS_STATUS_SUCCESS( status )) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Could not return VOS packet to the pool", __func__); + } + + return status; +} + + +/**============================================================================ + @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to + fetch a packet for transmission. + + @param vosContext : [in] pointer to VOS context + @param staId : [in] Station for which TL is requesting a pkt + @param ac : [in] access category requested by TL + @param pVosPacket : [out] pointer to VOS packet packet pointer + @param pPktMetaInfo : [out] pointer to meta info for the pkt + + @return : VOS_STATUS_E_EMPTY if no packets to transmit + : VOS_STATUS_E_FAILURE if any errors encountered + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext, + v_U8_t *pStaId, + WLANTL_ACEnumType ac, + vos_pkt_t **ppVosPacket, + WLANTL_MetaInfoType *pPktMetaInfo ) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; + hdd_adapter_t *pAdapter = NULL; + hdd_context_t *pHddCtx = NULL; + hdd_list_node_t *anchor = NULL; + skb_list_node_t *pktNode = NULL; + struct sk_buff *skb = NULL; + vos_pkt_t *pVosPacket = NULL; + v_MACADDR_t* pDestMacAddress = NULL; + v_TIME_t timestamp; + WLANTL_ACEnumType newAc; + v_SIZE_t size = 0; + tANI_U8 acAdmitted, i; + + //Sanity check on inputs + if ( ( NULL == vosContext ) || + ( NULL == pStaId ) || + ( NULL == ppVosPacket ) || + ( NULL == pPktMetaInfo ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Null Params being passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); + if(pHddCtx == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter context is Null", __func__); + return VOS_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[*pStaId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("Invalid adapter %p staId %u"), pAdapter, *pStaId); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + *ppVosPacket = NULL; + + //Make sure the AC being asked for is sane + if( ac >= WLANTL_MAX_AC || ac < 0) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid AC %d passed by TL", __func__, ac); + return VOS_STATUS_E_FAILURE; + } + +#ifdef HDD_WMM_DEBUG + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: AC %d passed by TL", __func__, ac); +#endif // HDD_WMM_DEBUG + + // We find an AC with packets + // or we determine we have no more packets to send + // HDD is not allowed to change AC. + + // has this AC been admitted? or + // To allow EAPOL packets when not authenticated + if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) && + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated)) + { +#ifdef HDD_WMM_DEBUG + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "%s: no packets pending", __func__); +#endif // HDD_WMM_DEBUG + return VOS_STATUS_E_FAILURE; + } + + // do we have any packets pending in this AC? + hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size ); + if( size > 0 ) + { + // yes, so process it +#ifdef HDD_WMM_DEBUG + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "%s: AC %d has packets pending", __func__, ac); +#endif // HDD_WMM_DEBUG + } + else + { +#ifdef HDD_WMM_DEBUG + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "%s: no packets pending", __func__); +#endif // HDD_WMM_DEBUG + return VOS_STATUS_E_FAILURE; + } + + //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources + //This simplifies the locking and unlocking of Tx queue + status = vos_pkt_wrap_data_packet( &pVosPacket, + VOS_PKT_TYPE_TX_802_3_DATA, + NULL, //OS Pkt is not being passed + hdd_tx_low_resource_cbk, + pAdapter ); + + if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES) + { + //Remember VOS is in a low resource situation + pAdapter->isVosOutOfResource = VOS_TRUE; + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __func__); + //TL will now think we have no more packets in this AC + return VOS_STATUS_E_FAILURE; + } + + //Remove the packet from the queue + spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock); + status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor ); + spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock); + + if(VOS_STATUS_SUCCESS == status) + { + //If success then we got a valid packet from some AC + pktNode = list_entry(anchor, skb_list_node_t, anchor); + skb = pktNode->skb; + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing " + "skb from Tx queue status = %d", __func__, status ); + vos_pkt_return_packet(pVosPacket); + return VOS_STATUS_E_FAILURE; + } + + //Attach skb to VOS packet. + status = vos_pkt_set_os_packet( pVosPacket, skb ); + if (status != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__); + vos_pkt_return_packet(pVosPacket); + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + return VOS_STATUS_E_FAILURE; + } + + //Just being paranoid. To be removed later + if(pVosPacket == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __func__); + ++pAdapter->stats.tx_dropped; + kfree_skb(skb); + return VOS_STATUS_E_FAILURE; + } + +#ifdef FEATURE_WLAN_TDLS + if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode) { + hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; + u8 mac[6]; + + wlan_hdd_tdls_extract_da(skb, mac); + + if (vos_is_macaddr_group((v_MACADDR_t *)mac)) { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED, + "broadcast packet, not adding to peer list"); + } else if (memcmp(pHddStaCtx->conn_info.bssId, + mac, 6) != 0) { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED, + "extract mac: " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(mac) ); + + wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 1); + } else { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_MED, + "packet da is bssid, not adding to peer list"); + } + } +#endif + + //Return VOS packet to TL; + *ppVosPacket = pVosPacket; + + //Fill out the meta information needed by TL + //FIXME This timestamp is really the time stamp of wrap_data_packet + vos_pkt_get_timestamp( pVosPacket, ×tamp ); + pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp; + + if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE) + pPktMetaInfo->ucIsEapol = 0; + else + pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0; + +#ifdef FEATURE_WLAN_WAPI + // Override usIsEapol value when its zero for WAPI case + pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0; +#endif /* FEATURE_WLAN_WAPI */ + + if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) || + (!pAdapter->hddWmmStatus.wmmQap)) + { + // either we don't want QoS or the AP doesn't support QoS + pPktMetaInfo->ucUP = 0; + pPktMetaInfo->ucTID = 0; + } + else + { + /* 1. Check if ACM is set for this AC + * 2. If set, check if this AC had already admitted + * 3. If not already admitted, downgrade the UP to next best UP */ + if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired || + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid) + { + pPktMetaInfo->ucUP = pktNode->userPriority; + pPktMetaInfo->ucTID = pPktMetaInfo->ucUP; + } + else + { + //Downgrade the UP + acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid; + newAc = WLANTL_AC_BK; + for (i=ac-1; i>0; i--) + { + if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0) + { + newAc = i; + break; + } + } + pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc]; + pPktMetaInfo->ucTID = pPktMetaInfo->ucUP; + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP); + } + } + + pPktMetaInfo->ucType = 0; //FIXME Don't know what this is + pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate + if ( 1 < size ) + { + pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send + } + else + { + pPktMetaInfo->bMorePackets = 0; + } + + //Extract the destination address from ethernet frame + pDestMacAddress = (v_MACADDR_t*)skb->data; + pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0; + pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0; + + + + /* If we are in a back pressure situation see if we can turn the + hose back on */ + if ( (pAdapter->isTxSuspended[ac]) && + (size <= HDD_TX_QUEUE_LOW_WATER_MARK) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "%s: TX queue[%d] re-enabled", __func__, ac); + pAdapter->isTxSuspended[ac] = VOS_FALSE; + netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev, + skb_get_queue_mapping(skb) )); + } + + + // We're giving the packet to TL so consider it transmitted from + // a statistics perspective. We account for it here instead of + // when the packet is returned for two reasons. First, TL will + // manipulate the skb to the point where the len field is not + // accurate, leading to inaccurate byte counts if we account for + // it later. Second, TL does not provide any feedback as to + // whether or not the packet was successfully sent over the air, + // so the packet counts will be the same regardless of where we + // account for them + pAdapter->stats.tx_bytes += skb->len; + ++pAdapter->stats.tx_packets; + + if((pHddCtx->cfg_ini->thermalMitigationEnable) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)) + { + if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Tm Lock fail", __func__); + return VOS_STATUS_E_FAILURE; + } + if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel) + { + if(0 == pHddCtx->tmInfo.txFrameCount) + { + /* Just recovered from sleep timeout */ + pHddCtx->tmInfo.lastOpenTs = timestamp; + } + + if((VOS_FALSE == pHddCtx->tmInfo.qBlocked) && + ((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) && + (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold)) + { + /* During TX open duration, TX frame count is larger than threshold + * Block TX during Sleep time */ + hddLog(LOG1, FL("Disabling queues")); + netif_tx_stop_all_queues(pAdapter->dev); + pHddCtx->tmInfo.qBlocked = VOS_TRUE; + pHddCtx->tmInfo.lastblockTs = timestamp; + if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer)) + { + vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration); + } + } + else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) && + (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold)) + { + /* During TX open duration, TX frame count is less than threshold + * Reset count and timestamp to prepare next cycle */ + pHddCtx->tmInfo.lastOpenTs = timestamp; + pHddCtx->tmInfo.txFrameCount = 0; + } + else + { + /* Do Nothing */ + } + pHddCtx->tmInfo.txFrameCount++; + } + mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); + } + + +#ifdef HDD_WMM_DEBUG + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,"%s: Valid VOS PKT returned to TL", __func__); +#endif // HDD_WMM_DEBUG + + return status; +} + +/**============================================================================ + @brief hdd_tx_low_resource_cbk() - Callback function invoked in the + case where VOS packets are not available at the time of the call to get + packets. This callback function is invoked by VOS when packets are + available. + + @param pVosPacket : [in] pointer to VOS packet + @param userData : [in] opaque user data that was passed initially + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + =============================================================================*/ +VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket, + v_VOID_t *userData ) +{ + VOS_STATUS status; + v_SINT_t i = 0; + v_SIZE_t size = 0; + hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("Invalid adpater %p"), pAdapter); + return VOS_STATUS_E_FAILURE; + } + + //Return the packet to VOS. We just needed to know that VOS is out of low resource + //situation. Here we will only signal TL that there is a pending data for a STA. + //VOS packet will be requested (if needed) when TL comes back to fetch data. + vos_pkt_return_packet( pVosPacket ); + + pAdapter->isVosOutOfResource = VOS_FALSE; + + //Indicate to TL that there is pending data if a queue is non empty + for( i=NUM_TX_QUEUES-1; i>=0; --i ) + { + size = 0; + hdd_list_size( &pAdapter->wmm_tx_queue[i], &size ); + if ( size > 0 ) + { + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0], + (WLANTL_ACEnumType)i ); + if( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failure in indicating pkt to TL for ac=%d", __func__,i); + } + } + } + + return VOS_STATUS_SUCCESS; +} + +#ifdef IPV6_MCAST_WAR +/* + * Return TRUE if the packet is to be dropped + */ +static inline +bool drop_ip6_mcast(struct sk_buff *skb) +{ + struct ethhdr *eth; + + eth = eth_hdr(skb); + if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + if (unlikely(ether_addr_equal(eth->h_source, skb->dev->dev_addr))) +#else + if (unlikely(!compare_ether_addr(eth->h_source, skb->dev->dev_addr))) +#endif + return true; + } + return false; +} +#else +#define drop_ip6_mcast(_a) 0 +#endif + +/**============================================================================ + @brief hdd_rx_packet_cbk() - Receive callback registered with TL. + TL will call this to notify the HDD when one or more packets were + received for a registered STA. + + @param vosContext : [in] pointer to VOS context + @param staId : [in] Station Id + @param rxBuf : [in] pointer to rx adf_nbuf + + @return : VOS_STATUS_E_FAILURE if any errors encountered, + : VOS_STATUS_SUCCESS otherwise + ===========================================================================*/ +VOS_STATUS hdd_rx_packet_cbk(v_VOID_t *vosContext, + adf_nbuf_t rxBuf, v_U8_t staId) +{ + hdd_adapter_t *pAdapter = NULL; + hdd_context_t *pHddCtx = NULL; + int rxstat; + struct sk_buff *skb = NULL; + struct sk_buff *skb_next; + unsigned int cpu_index; +#ifdef QCA_PKT_PROTO_TRACE + v_U8_t proto_type; +#endif /* QCA_PKT_PROTO_TRACE */ + hdd_station_ctx_t *pHddStaCtx = NULL; + + //Sanity check on inputs + if ((NULL == vosContext) || (NULL == rxBuf)) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + 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 VOS_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[staId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("invalid adapter %p for sta Id %d"), pAdapter, staId); + return VOS_STATUS_E_FAILURE; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL, + "Magic cookie(%x) for adapter sanity verification is invalid", + pAdapter->magic); + return VOS_STATUS_E_FAILURE; + } + + cpu_index = wlan_hdd_get_cpu(); + + // walk the chain until all are processed + skb = (struct sk_buff *) rxBuf; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + while (NULL != skb) { + skb_next = skb->next; + + if (((pHddStaCtx->conn_info.proxyARPService) && + cfg80211_is_gratuitous_arp_unsolicited_na(skb)) || + vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index]; + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "%s: Dropping HS 2.0 Gratuitous ARP or Unsolicited NA" + " else dropping as Driver load/unload is in progress", + __func__); + kfree_skb(skb); + + skb = skb_next; + continue; + } + + wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED); + +#ifdef QCA_PKT_PROTO_TRACE + if ((pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_EAPOL) || + (pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_DHCP)) { + proto_type = vos_pkt_get_proto_type(skb, + pHddCtx->cfg_ini->gEnableDebugLog, 0); + if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type) + vos_pkt_trace_buf_update("ST:R:EPL"); + else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type) + vos_pkt_trace_buf_update("ST:R:DHC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + + skb->dev = pAdapter->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + + /* Check & drop mcast packets (for IPV6) as required */ + if (drop_ip6_mcast(skb)) { + hddLog(VOS_TRACE_LEVEL_INFO, "MAC Header:"); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + skb_mac_header(skb), 16); + ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index]; + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO, + "%s: Dropping multicast to self NA", __func__); + kfree_skb(skb); + + skb = skb_next; + continue; + } + + ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; + ++pAdapter->stats.rx_packets; + pAdapter->stats.rx_bytes += skb->len; + + /* + * If this is not a last packet on the chain + * Just put packet into backlog queue, not scheduling RX sirq + */ + if (skb->next) { + rxstat = netif_rx(skb); + } else { +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + vos_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, + HDD_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX); +#endif + /* + * This is the last packet on the chain + * Scheduling rx sirq + */ + rxstat = netif_rx_ni(skb); + } + + if (NET_RX_SUCCESS == rxstat) + ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index]; + else + ++pAdapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index]; + + skb = skb_next; + } + + pAdapter->dev->last_rx = jiffies; + + return VOS_STATUS_SUCCESS; +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + +/** + * wlan_hdd_get_eapol_params() - Function to extract EAPOL params + * @skb: sbb data + * @eapol_params: Pointer to hold the parsed EAPOL params + * @event_type: Event type to indicate Tx/Rx + * + * This function parses the input skb data to get the EAPOL params,if the + * packet is EAPOL and store it in the pointer passed as input + * + * Return: 0 on success and negative value in failure + * + */ +static int wlan_hdd_get_eapol_params(struct sk_buff *skb, + struct vos_event_wlan_eapol *eapol_params, + uint8_t event_type) +{ + bool ret; + uint8_t packet_type=0; + + ret = wlan_hdd_is_eapol(skb); + + if (!ret) + return -1; + + packet_type = (uint8_t)(*(uint8_t *) + (skb->data + HDD_EAPOL_PACKET_TYPE_OFFSET)); + + eapol_params->eapol_packet_type = packet_type; + eapol_params->eapol_key_info = (uint16_t)(*(uint16_t *) + (skb->data + HDD_EAPOL_KEY_INFO_OFFSET)); + eapol_params->event_sub_type = event_type; + eapol_params->eapol_rate = 0;/* As of now, zero */ + + vos_mem_copy(eapol_params->dest_addr, + (skb->data + HDD_EAPOL_DEST_MAC_OFFSET), + sizeof(eapol_params->dest_addr)); + vos_mem_copy(eapol_params->src_addr, + (skb->data + HDD_EAPOL_SRC_MAC_OFFSET), + sizeof(eapol_params->src_addr)); + return 0; +} +/** + * wlan_hdd_event_eapol_log() - Function to log EAPOL events + * @eapol_params: Structure containing EAPOL params + * + * This function logs the parsed EAPOL params + * + * Return: None + * + */ +static void wlan_hdd_event_eapol_log(struct vos_event_wlan_eapol eapol_params) +{ + WLAN_VOS_DIAG_EVENT_DEF(wlan_diag_event, struct vos_event_wlan_eapol); + + wlan_diag_event.event_sub_type = eapol_params.event_sub_type; + wlan_diag_event.eapol_packet_type = eapol_params.eapol_packet_type; + wlan_diag_event.eapol_key_info = eapol_params.eapol_key_info; + wlan_diag_event.eapol_rate = eapol_params.eapol_rate; + vos_mem_copy(wlan_diag_event.dest_addr, + eapol_params.dest_addr, + sizeof (wlan_diag_event.dest_addr)); + vos_mem_copy(wlan_diag_event.src_addr, + eapol_params.src_addr, + sizeof (wlan_diag_event.src_addr)); + + WLAN_VOS_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL); +} + +/** + * wlan_hdd_log_eapol() - Function to check and extract EAPOL params + * @skb: skb data + * @event_type: One of enum wifi_connectivity_events to indicate Tx/Rx + * + * This function parses the input skb data to get the EAPOL params,if the + * packet is EAPOL and store it in the pointer passed as input + * + * Return: None + * + */ +void wlan_hdd_log_eapol(struct sk_buff *skb, + uint8_t event_type) +{ + int ret; + struct vos_event_wlan_eapol eapol_params; + + ret = wlan_hdd_get_eapol_params(skb, &eapol_params, event_type); + if (!ret) { + wlan_hdd_event_eapol_log(eapol_params); + } +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c new file mode 100644 index 000000000000..9b7d3a7d7547 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c @@ -0,0 +1,12526 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** ------------------------------------------------------------------------ * + ------------------------------------------------------------------------ * + + + \file wlan_hdd_wext.c + + \brief Airgo Linux Wireless Extensions Common Control Plane Types and + interfaces. + + $Id: wlan_hdd_wext.c,v 1.34 2007/04/14 01:49:23 jimz Exp jimz $This file defines all of the types that are utilized by the CCP module + of the "Portable" HDD. This file also includes the underlying Linux + Wireless Extensions Data types referred to by CCP. + + ======================================================================== */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ccmApi.h" +#include "sirParams.h" +#include "csrApi.h" +#include "csrInsideApi.h" +#if defined WLAN_FEATURE_VOWIFI +#include "smeRrmInternal.h" +#endif +#include +#include "dot11f.h" +#include +#include +#include +#include "utilsApi.h" +#include "wlan_hdd_p2p.h" +#ifdef FEATURE_WLAN_TDLS +#include "wlan_hdd_tdls.h" +#endif + +#include "ieee80211_common.h" +#include "ol_if_athvar.h" +#include "dbglog_host.h" +#include "wma.h" + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include "wlan_hdd_power.h" +#include "qwlan_version.h" +#include "wlan_hdd_host_offload.h" +#include "wlan_hdd_keep_alive.h" +#ifdef WLAN_FEATURE_PACKET_FILTERING +#include "wlan_hdd_packet_filtering.h" +#endif + +#include +#include +#include "wlan_qct_tl.h" + +#include "wlan_hdd_misc.h" + +#include "wlan_hdd_dev_pwr.h" +#include "qc_sap_ioctl.h" +#include "sme_Api.h" +#include "wlan_qct_wda.h" +#include "vos_trace.h" +#include "wlan_hdd_assoc.h" + +#ifdef QCA_PKT_PROTO_TRACE +#include "vos_packet.h" +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include "wlan_hdd_cfg80211.h" +#endif + +#include "wlan_hdd_ocb.h" +#include "wlan_hdd_tsf.h" + +#define HDD_FINISH_ULA_TIME_OUT 800 +#define HDD_SET_MCBC_FILTERS_TO_FW 1 +#define HDD_DELETE_MCBC_FILTERS_FROM_FW 0 + +extern int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand); +static int ioctl_debug; +module_param(ioctl_debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +/* To Validate Channel against the Frequency and Vice-Versa */ +static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, + {2422, 3}, {2427, 4}, {2432, 5}, {2437, 6}, {2442, 7}, {2447, 8}, + {2452, 9}, {2457, 10}, {2462, 11}, {2467 ,12}, {2472, 13}, + {2484, 14}, {4920, 240}, {4940, 244}, {4960, 248}, {4980, 252}, + {5040, 208}, {5060, 212}, {5080, 216}, {5180, 36}, {5200, 40}, {5220, 44}, + {5240, 48}, {5260, 52}, {5280, 56}, {5300, 60}, {5320, 64}, {5500, 100}, + {5520, 104}, {5540, 108}, {5560, 112}, {5580, 116}, {5600, 120}, + {5620, 124}, {5640, 128}, {5660, 132}, {5680, 136}, {5700, 140}, + {5720, 144}, {5745, 149}, {5765, 153}, {5785, 157}, {5805, 161}, + {5825, 165}, {5852, 170}, {5855, 171}, {5860, 172}, {5865, 173}, + {5870, 174}, {5875, 175}, {5880, 176}, {5885, 177}, {5890, 178}, + {5895, 179}, {5900, 180}, {5905, 181}, {5910, 182}, {5915, 183}, + {5920, 184} }; + +#define FREQ_CHAN_MAP_TABLE_SIZE (sizeof(freq_chan_map)/sizeof(freq_chan_map[0])) + +#define RC_2_RATE_IDX(_rc) ((_rc) & 0x7) +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) + +#define RC_2_RATE_IDX_11AC(_rc) ((_rc) & 0xf) +#define HT_RC_2_STREAMS_11AC(_rc) ((((_rc) & 0x30) >> 4) + 1) + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_INT_GET_NONE (SIOCIWFIRSTPRIV + 0) +#define WE_SET_11D_STATE 1 +#define WE_WOWL 2 +#define WE_SET_POWER 3 +#define WE_SET_MAX_ASSOC 4 +#define WE_SET_SAP_AUTO_CHANNEL_SELECTION 5 +#define WE_SET_DATA_INACTIVITY_TO 6 +#define WE_SET_MAX_TX_POWER 7 +#define WE_SET_HIGHER_DTIM_TRANSITION 8 +#define WE_SET_TM_LEVEL 9 +#define WE_SET_PHYMODE 10 +#define WE_SET_NSS 11 +#define WE_SET_LDPC 12 +#define WE_SET_TX_STBC 13 +#define WE_SET_RX_STBC 14 +#define WE_SET_SHORT_GI 15 +#define WE_SET_RTSCTS 16 +#define WE_SET_CHWIDTH 17 +#define WE_SET_ANI_EN_DIS 18 +#define WE_SET_ANI_POLL_PERIOD 19 +#define WE_SET_ANI_LISTEN_PERIOD 20 +#define WE_SET_ANI_OFDM_LEVEL 21 +#define WE_SET_ANI_CCK_LEVEL 22 +#define WE_SET_DYNAMIC_BW 23 +#define WE_SET_TX_CHAINMASK 24 +#define WE_SET_RX_CHAINMASK 25 +#define WE_SET_11N_RATE 26 +#define WE_SET_AMPDU 27 +#define WE_SET_AMSDU 28 +#define WE_SET_TXPOW_2G 29 +#define WE_SET_TXPOW_5G 30 +/* Private ioctl for firmware debug log */ +#define WE_DBGLOG_LOG_LEVEL 31 +#define WE_DBGLOG_VAP_ENABLE 32 +#define WE_DBGLOG_VAP_DISABLE 33 +#define WE_DBGLOG_MODULE_ENABLE 34 +#define WE_DBGLOG_MODULE_DISABLE 35 +#define WE_DBGLOG_MOD_LOG_LEVEL 36 +#define WE_DBGLOG_TYPE 37 +#define WE_SET_TXRX_FWSTATS 38 +#define WE_SET_VHT_RATE 39 +#define WE_DBGLOG_REPORT_ENABLE 40 +#define WE_TXRX_FWSTATS_RESET 41 +#define WE_SET_MAX_TX_POWER_2_4 42 +#define WE_SET_MAX_TX_POWER_5_0 43 +/* 44 is unused */ +/* Private ioctl for packet power save */ +#define WE_PPS_PAID_MATCH 45 +#define WE_PPS_GID_MATCH 46 +#define WE_PPS_EARLY_TIM_CLEAR 47 +#define WE_PPS_EARLY_DTIM_CLEAR 48 +#define WE_PPS_EOF_PAD_DELIM 49 +#define WE_PPS_MACADDR_MISMATCH 50 +#define WE_PPS_DELIM_CRC_FAIL 51 +#define WE_PPS_GID_NSTS_ZERO 52 +#define WE_PPS_RSSI_CHECK 53 +/* 54 is unused */ +#define WE_SET_HTSMPS 55 +/* Private ioctl for QPower */ +#define WE_SET_QPOWER_MAX_PSPOLL_COUNT 56 +#define WE_SET_QPOWER_MAX_TX_BEFORE_WAKE 57 +#define WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL 58 +#define WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL 59 + +#define WE_SET_BURST_ENABLE 60 +#define WE_SET_BURST_DUR 61 +/* GTX Commands */ +#define WE_SET_GTX_HT_MCS 62 +#define WE_SET_GTX_VHT_MCS 63 +#define WE_SET_GTX_USRCFG 64 +#define WE_SET_GTX_THRE 65 +#define WE_SET_GTX_MARGIN 66 +#define WE_SET_GTX_STEP 67 +#define WE_SET_GTX_MINTPC 68 +#define WE_SET_GTX_BWMASK 69 +/* Private ioctl to configure MCC home channels time quota and latency */ +#define WE_MCC_CONFIG_LATENCY 70 +#define WE_MCC_CONFIG_QUOTA 71 +/* Private IOCTL for debug connection issues */ +#define WE_SET_DEBUG_LOG 72 +#define WE_SET_SCAN_BAND_PREFERENCE 73 +#ifdef WE_SET_TX_POWER +#undef WE_SET_TX_POWER +#endif +#define WE_SET_TX_POWER 74 +/* Private ioctl for earlyrx power save feature */ +#define WE_SET_EARLY_RX_ADJUST_ENABLE 75 +#define WE_SET_EARLY_RX_TGT_BMISS_NUM 76 +#define WE_SET_EARLY_RX_BMISS_SAMPLE_CYCLE 77 +#define WE_SET_EARLY_RX_SLOP_STEP 78 +#define WE_SET_EARLY_RX_INIT_SLOP 79 +#define WE_SET_EARLY_RX_ADJUST_PAUSE 80 +#define WE_SET_MC_RATE 81 +#define WE_SET_EARLY_RX_DRIFT_SAMPLE 82 +/* Private ioctl for packet power save */ +#define WE_PPS_5G_EBT 83 +#define WE_SET_CTS_CBW 84 +#define WE_DUMP_STATS 85 +#define WE_CLEAR_STATS 86 +#define WE_SET_CHANNEL 87 + + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) +#define WE_GET_11D_STATE 1 +#define WE_IBSS_STATUS 2 +#define WE_SET_SAP_CHANNELS 3 +#define WE_GET_WLAN_DBG 4 +#define WE_GET_MAX_ASSOC 6 +/* 7 is unused */ +#define WE_GET_SAP_AUTO_CHANNEL_SELECTION 8 +#define WE_GET_CONCURRENCY_MODE 9 +#define WE_GET_NSS 11 +#define WE_GET_LDPC 12 +#define WE_GET_TX_STBC 13 +#define WE_GET_RX_STBC 14 +#define WE_GET_SHORT_GI 15 +#define WE_GET_RTSCTS 16 +#define WE_GET_CHWIDTH 17 +#define WE_GET_ANI_EN_DIS 18 +#define WE_GET_ANI_POLL_PERIOD 19 +#define WE_GET_ANI_LISTEN_PERIOD 20 +#define WE_GET_ANI_OFDM_LEVEL 21 +#define WE_GET_ANI_CCK_LEVEL 22 +#define WE_GET_DYNAMIC_BW 23 +#define WE_GET_TX_CHAINMASK 24 +#define WE_GET_RX_CHAINMASK 25 +#define WE_GET_11N_RATE 26 +#define WE_GET_AMPDU 27 +#define WE_GET_AMSDU 28 +#define WE_GET_TXPOW_2G 29 +#define WE_GET_TXPOW_5G 30 +/* 31 is unused */ +#define WE_GET_PPS_PAID_MATCH 32 +#define WE_GET_PPS_GID_MATCH 33 +#define WE_GET_PPS_EARLY_TIM_CLEAR 34 +#define WE_GET_PPS_EARLY_DTIM_CLEAR 35 +#define WE_GET_PPS_EOF_PAD_DELIM 36 +#define WE_GET_PPS_MACADDR_MISMATCH 37 +#define WE_GET_PPS_DELIM_CRC_FAIL 38 +#define WE_GET_PPS_GID_NSTS_ZERO 39 +#define WE_GET_PPS_RSSI_CHECK 40 +/* Private ioctl for QPower */ +#define WE_GET_QPOWER_MAX_PSPOLL_COUNT 41 +#define WE_GET_QPOWER_MAX_TX_BEFORE_WAKE 42 +#define WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL 43 +#define WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL 44 +#define WE_GET_BURST_ENABLE 45 +#define WE_GET_BURST_DUR 46 +/* GTX Commands */ +#define WE_GET_GTX_HT_MCS 47 +#define WE_GET_GTX_VHT_MCS 48 +#define WE_GET_GTX_USRCFG 49 +#define WE_GET_GTX_THRE 50 +#define WE_GET_GTX_MARGIN 51 +#define WE_GET_GTX_STEP 52 +#define WE_GET_GTX_MINTPC 53 +#define WE_GET_GTX_BWMASK 54 +#define WE_GET_SCAN_BAND_PREFERENCE 55 +#define WE_GET_TEMPERATURE 56 +#define WE_GET_FW_STATUS 57 +#define WE_CAP_TSF 58 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2) + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_CHAR_GET_NONE (SIOCIWFIRSTPRIV + 3) +#define WE_WOWL_ADD_PTRN 1 +#define WE_WOWL_DEL_PTRN 2 +#if defined WLAN_FEATURE_VOWIFI +#define WE_NEIGHBOR_REPORT_REQUEST 3 +#endif +#define WE_SET_AP_WPS_IE 4 //This is called in station mode to set probe rsp ie. +#define WE_SET_CONFIG 5 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 4) +#define WE_SET_WLAN_DBG 1 +/* 2 is unused */ +#define WE_SET_SAP_CHANNELS 3 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 5) +#define WE_WLAN_VERSION 1 +#define WE_GET_STATS 2 +#define WE_GET_CFG 3 +#define WE_GET_WMM_STATUS 4 +#define WE_GET_CHANNEL_LIST 5 +#ifdef WLAN_FEATURE_11AC +#define WE_GET_RSSI 6 +#endif +#ifdef FEATURE_WLAN_TDLS +#define WE_GET_TDLS_PEERS 8 +#endif +#ifdef WLAN_FEATURE_11W +#define WE_GET_11W_INFO 9 +#endif +#define WE_GET_STATES 10 +#define WE_GET_PHYMODE 12 +#ifdef FEATURE_OEM_DATA_SUPPORT +#define WE_GET_OEM_DATA_CAP 13 +#endif +#define WE_GET_SNR 14 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) +#define WE_ENABLE_DXE_STALL_DETECT 6 +#define WE_DISPLAY_DXE_SNAP_SHOT 7 +#define WE_SET_REASSOC_TRIGGER 8 +#define WE_DISPLAY_DATAPATH_SNAP_SHOT 9 +#define WE_DUMP_AGC_START 11 +#define WE_DUMP_AGC 12 +#define WE_DUMP_CHANINFO_START 13 +#define WE_DUMP_CHANINFO 14 +#define WE_DUMP_WATCHDOG 15 +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +#define WE_DUMP_PCIE_LOG 16 +#endif +#define WE_GET_RECOVERY_STAT 17 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 7) +#define WE_LOG_DUMP_CMD 1 + +#define WE_P2P_NOA_CMD 2 +//IOCTL to configure MCC params +#define WE_MCC_CONFIG_CREDENTIAL 3 +#define WE_MCC_CONFIG_PARAMS 4 + +#ifdef FEATURE_WLAN_TDLS +#define WE_TDLS_CONFIG_PARAMS 5 +#endif + +#define WE_UNIT_TEST_CMD 7 + +#define WE_MTRACE_DUMP_CMD 8 +#define WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD 9 + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +#define WE_LED_FLASHING_PARAM 10 +#endif +#ifdef MEMORY_DEBUG +#define WE_MEM_TRACE_DUMP 11 +#endif +#ifdef FEATURE_WLAN_TDLS +#undef MAX_VAR_ARGS +#define MAX_VAR_ARGS 11 +#else +#define MAX_VAR_ARGS 7 +#endif + +/* Private ioctls (with no sub-ioctls) */ +/* note that they must be odd so that they have "get" semantics */ +#define WLAN_PRIV_ADD_TSPEC (SIOCIWFIRSTPRIV + 9) +#define WLAN_PRIV_DEL_TSPEC (SIOCIWFIRSTPRIV + 11) +#define WLAN_PRIV_GET_TSPEC (SIOCIWFIRSTPRIV + 13) + +/* (SIOCIWFIRSTPRIV + 8) is currently unused */ +/* (SIOCIWFIRSTPRIV + 16) is currently unused */ +/* (SIOCIWFIRSTPRIV + 10) is currently unused */ +/* (SIOCIWFIRSTPRIV + 12) is currently unused */ +/* (SIOCIWFIRSTPRIV + 14) is currently unused */ + +#define WLAN_PRIV_SET_NONE_GET_THREE_INT (SIOCIWFIRSTPRIV + 15) +#define WE_GET_TSF 1 + +/* (SIOCIWFIRSTPRIV + 17) is currently unused */ +/* (SIOCIWFIRSTPRIV + 19) is currently unused */ + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define WLAN_PRIV_SET_FTIES (SIOCIWFIRSTPRIV + 20) +#endif + +/* Private ioctl for setting the host offload feature */ +#define WLAN_PRIV_SET_HOST_OFFLOAD (SIOCIWFIRSTPRIV + 18) + +/* Private ioctl to get the statistics */ +#define WLAN_GET_WLAN_STATISTICS (SIOCIWFIRSTPRIV + 21) + +/* Private ioctl to set the Keep Alive Params */ +#define WLAN_SET_KEEPALIVE_PARAMS (SIOCIWFIRSTPRIV + 22) +#ifdef WLAN_FEATURE_PACKET_FILTERING +/* Private ioctl to set the Packet Filtering Params */ +#define WLAN_SET_PACKET_FILTER_PARAMS (SIOCIWFIRSTPRIV + 23) +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO +/* Private ioctl to get the statistics */ +#define WLAN_SET_PNO (SIOCIWFIRSTPRIV + 24) +#endif + +#define WLAN_SET_BAND_CONFIG (SIOCIWFIRSTPRIV + 25) /*Don't change this number*/ + +#define WLAN_PRIV_SET_MCBC_FILTER (SIOCIWFIRSTPRIV + 26) +#define WLAN_PRIV_CLEAR_MCBC_FILTER (SIOCIWFIRSTPRIV + 27) +/* Private ioctl to trigger reassociation */ + +#define WLAN_SET_POWER_PARAMS (SIOCIWFIRSTPRIV + 29) + +/* 802.11p IOCTL */ +#define WLAN_SET_DOT11P_CHANNEL_SCHED (SIOCIWFIRSTPRIV + 30) + +#define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31) + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28) +#define WE_SET_SMPS_PARAM 1 +#ifdef DEBUG +#define WE_SET_FW_CRASH_INJECT 2 +#endif + +#define WLAN_STATS_INVALID 0 +#define WLAN_STATS_RETRY_CNT 1 +#define WLAN_STATS_MUL_RETRY_CNT 2 +#define WLAN_STATS_TX_FRM_CNT 3 +#define WLAN_STATS_RX_FRM_CNT 4 +#define WLAN_STATS_FRM_DUP_CNT 5 +#define WLAN_STATS_FAIL_CNT 6 +#define WLAN_STATS_RTS_FAIL_CNT 7 +#define WLAN_STATS_ACK_FAIL_CNT 8 +#define WLAN_STATS_RTS_SUC_CNT 9 +#define WLAN_STATS_RX_DISCARD_CNT 10 +#define WLAN_STATS_RX_ERROR_CNT 11 +#define WLAN_STATS_TX_BYTE_CNT 12 + +#define WLAN_STATS_RX_BYTE_CNT 13 +#define WLAN_STATS_RX_RATE 14 +#define WLAN_STATS_TX_RATE 15 + +#define WLAN_STATS_RX_UC_BYTE_CNT 16 +#define WLAN_STATS_RX_MC_BYTE_CNT 17 +#define WLAN_STATS_RX_BC_BYTE_CNT 18 +#define WLAN_STATS_TX_UC_BYTE_CNT 19 +#define WLAN_STATS_TX_MC_BYTE_CNT 20 +#define WLAN_STATS_TX_BC_BYTE_CNT 21 + +#define FILL_TLV(__p, __type, __size, __val, __tlen) do { \ + if ((__tlen + __size + 2) < WE_MAX_STR_LEN) \ + { \ + *__p++ = __type; \ + *__p++ = __size; \ + memcpy(__p, __val, __size); \ + __p += __size; \ + __tlen += __size + 2; \ + } \ + else \ + { \ + hddLog(VOS_TRACE_LEVEL_ERROR, "FILL_TLV Failed!!!"); \ + } \ + } while(0); + +#define VERSION_VALUE_MAX_LEN 32 + +#define TX_PER_TRACKING_DEFAULT_RATIO 5 +#define TX_PER_TRACKING_MAX_RATIO 10 +#define TX_PER_TRACKING_DEFAULT_WATERMARK 5 + +#define WLAN_ADAPTER 0 +#define P2P_ADAPTER 1 + +/*MCC Configuration parameters */ +enum { + MCC_SCHEDULE_TIME_SLICE_CFG_PARAM = 1, + MCC_MAX_NULL_SEND_TIME_CFG_PARAM, + MCC_TX_EARLY_STOP_TIME_CFG_PARAM, + MCC_RX_DRAIN_TIME_CFG_PARAM, + MCC_CHANNEL_SWITCH_TIME_CFG_PARAM, + MCC_MIN_CHANNEL_TIME_CFG_PARAM, + MCC_PARK_BEFORE_TBTT_CFG_PARAM, + MCC_MIN_AFTER_DTIM_CFG_PARAM, + MCC_TOO_CLOSE_MARGIN_CFG_PARAM, +}; + +static const struct qwlan_hw qwlan_hw_list[] = { + { + .id = AR6320_REV1_VERSION, + .subid = 0, + .name = "QCA6174_REV1", + }, + { + .id = AR6320_REV1_1_VERSION, + .subid = 0x1, + .name = "QCA6174_REV1_1", + }, + { + .id = AR6320_REV1_3_VERSION, + .subid = 0x2, + .name = "QCA6174_REV1_3", + }, + { + .id = AR6320_REV2_1_VERSION, + .subid = 0x4, + .name = "QCA6174_REV2_1", + }, + { + .id = AR6320_REV2_1_VERSION, + .subid = 0x5, + .name = "QCA6174_REV2_2", + }, + { + .id = AR6320_REV3_VERSION, + .subid = 0x6, + .name = "QCA6174_REV2.3", + }, + { + .id = AR6320_REV3_VERSION, + .subid = 0x8, + .name = "QCA6174_REV3", + }, + { + .id = AR6320_REV3_VERSION, + .subid = 0x9, + .name = "QCA6174_REV3_1", + }, + { + .id = AR6320_REV3_2_VERSION, + .subid = 0xA, + .name = "QCA6174_REV3_2", + }, + { + .id = AR6320_REV3_VERSION, + .subid = 0x0, + .name = "QCA9377_REV1", + }, + { + .id = QCA9377_REV1_1_VERSION, + .subid = 0x1, + .name = "QCA9377_REV1_1", + } +}; + +int hdd_validate_mcc_config(hdd_adapter_t *pAdapter, v_UINT_t staId, + v_UINT_t arg1, v_UINT_t arg2, v_UINT_t arg3); + +#ifdef WLAN_FEATURE_PACKET_FILTERING +int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, + v_U8_t sessionId); +#endif + +/**--------------------------------------------------------------------------- + + \brief mem_alloc_copy_from_user_helper - + + Helper function to allocate buffer and copy user data. + + \param - wrqu - Pointer to IOCTL Data. + len - size + + \return - On Success pointer to buffer, On failure NULL + + --------------------------------------------------------------------------*/ +void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len) +{ + u8 *ptr = NULL; + + /* in order to protect the code, an extra byte is post appended to the buffer + * and the null termination is added. However, when allocating (len+1) byte + * of memory, we need to make sure that there is no uint overflow when doing + * addition. In theory check len < UINT_MAX protects the uint overflow. For + * wlan private ioctl, the buffer size is much less than UINT_MAX, as a good + * guess, now, it is assumed that the private command buffer size is no + * greater than 4K (4096 bytes). So we use 4096 as the upper boundary for now. + */ + if (len > MAX_USER_COMMAND_SIZE) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid length"); + return NULL; + } + + + ptr = kmalloc(len + 1, GFP_KERNEL); + if (NULL == ptr) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "unable to allocate memory"); + return NULL; + } + + if (copy_from_user(ptr, wrqu_data, len)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + kfree(ptr); + return NULL; + } + ptr[len] = '\0'; + return ptr; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_priv_get_data - + + Helper function to get compatible struct iw_point passed to ioctl + + \param - p_priv_data - pointer to iw_point struct to be filled + wrqu - Pointer to IOCTL Data received from user space + + \return - 0 if p_priv_data successfully filled + error otherwise + + --------------------------------------------------------------------------*/ +int hdd_priv_get_data(struct iw_point *p_priv_data, + union iwreq_data *wrqu) +{ + if ((NULL == p_priv_data) || (NULL == wrqu)) { + return -EINVAL; + } + +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + struct compat_iw_point *p_compat_priv_data; + + /* Compat task: typecast to compat structure and copy the members. */ + p_compat_priv_data = (struct compat_iw_point *) &wrqu->data; + + p_priv_data->pointer = compat_ptr(p_compat_priv_data->pointer); + p_priv_data->length = p_compat_priv_data->length; + p_priv_data->flags = p_compat_priv_data->flags; + } else { +#endif /* #ifdef CONFIG_COMPAT */ + + /* Non compat task: directly copy the structure. */ + memcpy(p_priv_data, &wrqu->data, sizeof(struct iw_point)); + +#ifdef CONFIG_COMPAT + } +#endif /* #ifdef CONFIG_COMPAT */ + + return 0; +} + + +/**--------------------------------------------------------------------------- + + \brief hdd_wlan_get_stats - + + Helper function to get stats + + \param - pAdapter Pointer to the adapter. + wrqu - Pointer to IOCTL REQUEST Data. + extra - Pointer to char + + + \return - none + + --------------------------------------------------------------------------*/ +void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, + char *buffer, v_U16_t buf_len) +{ + hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats; + v_U32_t len; + __u32 total_rxPkt = 0, total_rxDropped = 0; + __u32 total_rxDelv = 0, total_rxRefused = 0; + int i = 0; + + for (; i < NUM_CPUS; i++) { + total_rxPkt += pStats->rxPackets[i]; + total_rxDropped += pStats->rxDropped[i]; + total_rxDelv += pStats->rxDelivered[i]; + total_rxRefused += pStats->rxRefused[i]; + } + + len = snprintf(buffer, buf_len, + "\nTransmit" + "\n called %u, dropped %u," + "\n dropped BK %u, BE %u, VI %u, VO %u" + "\n classified BK %u, BE %u, VI %u, VO %u" + "\n completed %u," + "\n\nReceive Total" + "\n packets %u, dropped %u, delivered %u, refused %u" + "\n", + pStats->txXmitCalled, + pStats->txXmitDropped, + + pStats->txXmitDroppedAC[WLANTL_AC_BK], + pStats->txXmitDroppedAC[WLANTL_AC_BE], + pStats->txXmitDroppedAC[WLANTL_AC_VI], + pStats->txXmitDroppedAC[WLANTL_AC_VO], + + pStats->txXmitClassifiedAC[WLANTL_AC_BK], + pStats->txXmitClassifiedAC[WLANTL_AC_BE], + pStats->txXmitClassifiedAC[WLANTL_AC_VI], + pStats->txXmitClassifiedAC[WLANTL_AC_VO], + + pStats->txCompleted, + total_rxPkt, total_rxDropped, total_rxDelv, total_rxRefused); + + for (i = 0; i < NUM_CPUS; i++) { + len += snprintf(buffer+len, buf_len-len, + "\nReceive CPU: %d" + "\n packets %u, dropped %u, delivered %u, refused %u", + i, pStats->rxPackets[i], pStats->rxDropped[i], + pStats->rxDelivered[i], pStats->rxRefused[i]); + } + len += snprintf(buffer+len, buf_len-len, + "\n" + "\nNetQueue State : %s" + "\n disable %u, enable %u" + "\n\nTX_FLOW" + "\nCurrent status %s" + "\ntx-flow timer start count %u" + "\npause count %u, unpause count %u\n", + (pStats->netq_state_off == TRUE ? "OFF" : "ON"), + pStats->netq_disable_cnt, + pStats->netq_enable_cnt, + (pStats->is_txflow_paused == TRUE ? "PAUSED" : "UNPAUSED"), + pStats->txflow_timer_cnt, + pStats->txflow_pause_cnt, + pStats->txflow_unpause_cnt + ); + + WLANTL_Get_llStats(pAdapter->sessionId, + &buffer[len], (buf_len - len)); + + *length = strlen(buffer) + 1; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_wlan_dump_stats - + + Helper function to dump stats + + \param - pAdapter Pointer to the adapter. + value - value given by user + + \return - none + + --------------------------------------------------------------------------*/ +void hdd_wlan_dump_stats(hdd_adapter_t *pAdapter, int value) +{ + hdd_context_t* hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + switch(value) + { + case WLAN_TXRX_HIST_STATS: + wlan_hdd_display_tx_rx_histogram(hdd_ctx); + break; + default: + WLANTL_display_datapath_stats(hdd_ctx->pvosContext, value); + break; + } +} + +/**--------------------------------------------------------------------------- + + \brief hdd_wlan_get_version() - + + This function use to get Wlan Driver, Firmware, & Hardware Version. + + \param - pAdapter Pointer to the adapter. + wrqu - Pointer to IOCTL REQUEST Data. + extra - Pointer to char + + \return - none + + --------------------------------------------------------------------------*/ +void hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu, + char *extra) +{ + tSirVersionString wcnss_SW_version; + const char *pSWversion; + const char *pHWversion; + v_U32_t MSPId = 0, mSPId = 0, SIId = 0, CRMId = 0; + + hdd_context_t *pHddContext; + int i = 0; + + pHddContext = WLAN_HDD_GET_CTX(pAdapter); + if (!pHddContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Invalid context, HDD context is null", __func__); + goto error; + } + + snprintf(wcnss_SW_version, sizeof(tSirVersionString), "%08x", + pHddContext->target_fw_version); + + pSWversion = wcnss_SW_version; + MSPId = (pHddContext->target_fw_version & 0xf0000000) >> 28; + mSPId = (pHddContext->target_fw_version & 0xf000000) >> 24; + SIId = (pHddContext->target_fw_version & 0xf00000) >> 20; + CRMId = pHddContext->target_fw_version & 0x7fff; + + for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) { + if (pHddContext->target_hw_version == qwlan_hw_list[i].id && + pHddContext->target_hw_revision == qwlan_hw_list[i].subid) { + pHWversion = qwlan_hw_list[i].name; + break; + } + } + + if (i == ARRAY_SIZE(qwlan_hw_list)) + pHWversion = "Unknown"; + pHddContext->target_hw_name = pHWversion; + + if (wrqu) { + wrqu->data.length = scnprintf(extra, WE_MAX_STR_LEN, + "Host SW:%s, FW:%d.%d.%d.%d, HW:%s", + QWLAN_VERSIONSTR, + MSPId, + mSPId, + SIId, + CRMId, + pHWversion); + } else { + pr_info("Host SW:%s, FW:%d.%d.%d.%d, HW:%s\n", + QWLAN_VERSIONSTR, + MSPId, + mSPId, + SIId, + CRMId, + pHWversion); + } +error: + return; +} + +int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U32_t threshold = 0; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + if (NULL == pAdapter) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Adapter is NULL", __func__); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + + if ( eHAL_STATUS_SUCCESS != + ccmCfgGetInt(hHal, WNI_CFG_RTS_THRESHOLD, &threshold) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_RTS_THRESHOLD")); + return -EIO; + } + wrqu->rts.value = threshold; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("Rts-Threshold=%d!!"), wrqu->rts.value); + + EXIT(); + + return 0; +} +int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U32_t threshold = 0, ret; + hdd_context_t *hdd_ctx; + + ENTER(); + + if (NULL == pAdapter) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Adapter is NULL", __func__); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + + if ( ccmCfgGetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, &threshold) + != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_FRAGMENTATION_THRESHOLD")); + return -EIO; + } + wrqu->frag.value = threshold; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("Frag-Threshold=%d!!"), wrqu->frag.value); + + EXIT(); + + return 0; +} + +int hdd_wlan_get_freq(v_U32_t channel, v_U32_t *pfreq) +{ + int i; + if (channel > 0) + { + for (i=0; i < FREQ_CHAN_MAP_TABLE_SIZE; i++) + { + if (channel == freq_chan_map[i].chan) + { + *pfreq = freq_chan_map[i].freq; + return 1; + } + } + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("Invalid channel no=%d!!"), channel); + return -EINVAL; +} + +static v_BOOL_t +hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType) +{ + v_BOOL_t rsnType = VOS_FALSE; + // is the authType supported? + switch (authType) + { + case eCSR_AUTH_TYPE_NONE: //never used + rsnType = eANI_BOOLEAN_FALSE; + break; + // MAC layer authentication types + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + rsnType = eANI_BOOLEAN_FALSE; + break; + case eCSR_AUTH_TYPE_SHARED_KEY: + rsnType = eANI_BOOLEAN_FALSE; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + rsnType = eANI_BOOLEAN_FALSE; + break; + + // Upper layer authentication types + case eCSR_AUTH_TYPE_WPA: + rsnType = eANI_BOOLEAN_TRUE; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + rsnType = eANI_BOOLEAN_TRUE; + break; + case eCSR_AUTH_TYPE_WPA_NONE: + rsnType = eANI_BOOLEAN_TRUE; + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: +#endif + case eCSR_AUTH_TYPE_RSN: + rsnType = eANI_BOOLEAN_TRUE; + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN_PSK: +#endif + case eCSR_AUTH_TYPE_RSN_PSK: +#ifdef WLAN_FEATURE_11W + case eCSR_AUTH_TYPE_RSN_PSK_SHA256: + case eCSR_AUTH_TYPE_RSN_8021X_SHA256: +#endif + rsnType = eANI_BOOLEAN_TRUE; + break; + //case eCSR_AUTH_TYPE_FAILED: + case eCSR_AUTH_TYPE_UNKNOWN: + rsnType = eANI_BOOLEAN_FALSE; + break; + default: + hddLog(LOGE, FL("%s called with unknown authType - default to Open, None"), + __func__); + rsnType = eANI_BOOLEAN_FALSE; + break; + } + hddLog(LOGE, FL("%s called with authType: %d, returned: %d"), + __func__, authType, rsnType); + return rsnType; +} + +static void hdd_GetRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) +{ + struct statsContext *pStatsContext; + hdd_adapter_t *pAdapter; + + if (ioctl_debug) + { + pr_info("%s: rssi [%d] STA [%d] pContext [%p]\n", + __func__, (int)rssi, (int)staId, pContext); + } + + if (NULL == pContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pContext [%p]", + __func__, pContext); + return; + } + + pStatsContext = pContext; + pAdapter = pStatsContext->pAdapter; + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + if ((NULL == pAdapter) || (RSSI_CONTEXT_MAGIC != pStatsContext->magic)) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pStatsContext->magic); + if (ioctl_debug) + { + pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", + __func__, pAdapter, pStatsContext->magic); + } + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pStatsContext->magic = 0; + + /* copy over the rssi */ + pAdapter->rssi = rssi; + + if (pAdapter->rssi > 0) + pAdapter->rssi = 0; + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +static void hdd_GetSnrCB(tANI_S8 snr, tANI_U32 staId, void *pContext) +{ + struct statsContext *pStatsContext; + hdd_adapter_t *pAdapter; + + if (ioctl_debug) + { + pr_info("%s: snr [%d] STA [%d] pContext [%p]\n", + __func__, (int)snr, (int)staId, pContext); + } + + if (NULL == pContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pContext [%p]", + __func__, pContext); + return; + } + + pStatsContext = pContext; + pAdapter = pStatsContext->pAdapter; + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + if ((NULL == pAdapter) || (SNR_CONTEXT_MAGIC != pStatsContext->magic)) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pStatsContext->magic); + if (ioctl_debug) + { + pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", + __func__, pAdapter, pStatsContext->magic); + } + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pStatsContext->magic = 0; + + /* copy over the snr */ + pAdapter->snr = snr; + + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) +{ + struct statsContext context; + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + eHalStatus hstatus; + unsigned long rc; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter", __func__); + return VOS_STATUS_E_FAULT; + } + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__); + /* return a cached value */ + *rssi_value = pAdapter->rssi; + return VOS_STATUS_SUCCESS; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + hddLog(LOG1, "%s: Not associated, rssi on disconnect %d", + __func__, pAdapter->rssi_on_disconnect); + *rssi_value = pAdapter->rssi_on_disconnect; + return VOS_STATUS_SUCCESS; + } + + if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Roaming in progress, return cached RSSI", __func__); + *rssi_value = pAdapter->rssi; + return VOS_STATUS_SUCCESS; + } + + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = RSSI_CONTEXT_MAGIC; + + hstatus = sme_GetRssi(pHddCtx->hHal, hdd_GetRssiCB, + pHddStaCtx->conn_info.staId[ 0 ], + pHddStaCtx->conn_info.bssId, pAdapter->rssi, + &context, pHddCtx->pvosContext); + if (eHAL_STATUS_SUCCESS != hstatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", + __func__); + /* we'll returned a cached value below */ + } + else + { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving RSSI")); + /* we'll now returned a cached value below */ + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + *rssi_value = pAdapter->rssi; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) +{ + struct statsContext context; + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + eHalStatus hstatus; + unsigned long rc; + int valid; + + ENTER(); + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid context, pAdapter", __func__); + return VOS_STATUS_E_FAULT; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + valid = wlan_hdd_validate_context(pHddCtx); + if (0 != valid) + return VOS_STATUS_E_FAULT; + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = SNR_CONTEXT_MAGIC; + + hstatus = sme_GetSnr(pHddCtx->hHal, hdd_GetSnrCB, + pHddStaCtx->conn_info.staId[ 0 ], + pHddStaCtx->conn_info.bssId, + &context); + if (eHAL_STATUS_SUCCESS != hstatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", + __func__); + /* we'll returned a cached value below */ + } + else + { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving SNR")); + /* we'll now returned a cached value below */ + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + *snr = pAdapter->snr; + EXIT(); + return VOS_STATUS_SUCCESS; +} + +void hdd_StatisticsCB( void *pStats, void *pContext ) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext; + hdd_stats_t *pStatsCache = NULL; + hdd_wext_state_t *pWextState; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + tCsrSummaryStatsInfo *pSummaryStats = NULL; + tCsrGlobalClassAStatsInfo *pClassAStats = NULL; + tCsrGlobalClassBStatsInfo *pClassBStats = NULL; + tCsrGlobalClassCStatsInfo *pClassCStats = NULL; + tCsrGlobalClassDStatsInfo *pClassDStats = NULL; + tCsrPerStaStatsInfo *pPerStaStats = NULL; + + if (pAdapter!= NULL) + pStatsCache = &pAdapter->hdd_stats; + + + pSummaryStats = (tCsrSummaryStatsInfo *)pStats; + pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 ); + pClassBStats = (tCsrGlobalClassBStatsInfo *)( pClassAStats + 1 ); + pClassCStats = (tCsrGlobalClassCStatsInfo *)( pClassBStats + 1 ); + pClassDStats = (tCsrGlobalClassDStatsInfo *)( pClassCStats + 1 ); + pPerStaStats = (tCsrPerStaStatsInfo *)( pClassDStats + 1 ); + + if (pStatsCache!=NULL) + { + // and copy the stats into the cache we keep in the adapter instance structure + vos_mem_copy( &pStatsCache->summary_stat, pSummaryStats, sizeof( pStatsCache->summary_stat ) ); + vos_mem_copy( &pStatsCache->ClassA_stat, pClassAStats, sizeof( pStatsCache->ClassA_stat ) ); + vos_mem_copy( &pStatsCache->ClassB_stat, pClassBStats, sizeof( pStatsCache->ClassB_stat ) ); + vos_mem_copy( &pStatsCache->ClassC_stat, pClassCStats, sizeof( pStatsCache->ClassC_stat ) ); + vos_mem_copy( &pStatsCache->ClassD_stat, pClassDStats, sizeof( pStatsCache->ClassD_stat ) ); + vos_mem_copy( &pStatsCache->perStaStats, pPerStaStats, sizeof( pStatsCache->perStaStats ) ); + } + + if (pAdapter) { + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + vos_status = vos_event_set(&pWextState->vosevent); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("vos_event_set failed")); + return; + } + } +} + +void ccmCfgSetCallback(tHalHandle halHandle, tANI_S32 result) +{ + v_CONTEXT_t pVosContext; + hdd_context_t *pHddCtx; + VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx ); +#if 0 + hdd_wext_state_t *pWextState; + v_U32_t roamId; +#endif + + ENTER(); + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS,NULL); + + pHddCtx = (hdd_context_t*) vos_get_context(VOS_MODULE_ID_HDD,pVosContext); + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid pHddCtx", __func__); + return; + } +#if 0 + pWextState = pAdapter->pWextState; +#endif + + if (WNI_CFG_NEED_RESTART == result || WNI_CFG_NEED_RELOAD == result) + { + //TODO Verify is this is really used. If yes need to fix it. + hdd_reconnect_all_adapters( pHddCtx ); +#if 0 + pAdapter->conn_info.connState = eConnectionState_NotConnected; + INIT_COMPLETION(pAdapter->disconnect_comp_var); + vosStatus = sme_RoamDisconnect(halHandle, 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)); + + sme_RoamConnect(halHandle, + pAdapter->sessionId, &(pWextState->roamProfile), + &roamId); +#endif + } + + EXIT(); + +} + +void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) +{ + int i = 0; + hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + /* clear WPA/RSN/WSC IE information in the profile */ + pWextState->roamProfile.nWPAReqIELength = 0; + pWextState->roamProfile.pWPAReqIE = (tANI_U8 *)NULL; + pWextState->roamProfile.nRSNReqIELength = 0; + pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL; + +#ifdef FEATURE_WLAN_WAPI + pWextState->roamProfile.nWAPIReqIELength = 0; + pWextState->roamProfile.pWAPIReqIE = (tANI_U8 *)NULL; +#endif + + pWextState->roamProfile.bWPSAssociation = VOS_FALSE; + pWextState->roamProfile.bOSENAssociation = VOS_FALSE; + pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL; + pWextState->roamProfile.nAddIEScanLength = 0; + pWextState->roamProfile.pAddIEAssoc = (tANI_U8 *)NULL; + pWextState->roamProfile.nAddIEAssocLength = 0; + + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.EncryptionType.encryptionType[0] + = eCSR_ENCRYPT_TYPE_NONE; + + pWextState->roamProfile.mcEncryptionType.numEntries = 1; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] + = eCSR_ENCRYPT_TYPE_NONE; + + pWextState->roamProfile.AuthType.numEntries = 1; + pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; + +#ifdef WLAN_FEATURE_11W + pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE; + pWextState->roamProfile.MFPRequired = 0; + pWextState->roamProfile.MFPCapable = 0; +#endif + + pWextState->authKeyMgmt = 0; + + for (i=0; i < CSR_MAX_NUM_KEY; i++) + { + if (pWextState->roamProfile.Keys.KeyMaterial[i]) + { + pWextState->roamProfile.Keys.KeyLength[i] = 0; + } + } +#ifdef FEATURE_WLAN_WAPI + pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_OPEN; + pAdapter->wapi_info.nWapiMode = 0; +#endif + + vos_mem_zero((void *)(pWextState->req_bssId), VOS_MAC_ADDR_SIZE); + +} + +void wlan_hdd_ula_done_cb(v_VOID_t *callbackContext) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t*)callbackContext; + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pAdapter magic", __func__); + } + else + { + complete(&pAdapter->ula_complete); + } +} + +VOS_STATUS wlan_hdd_check_ula_done(hdd_adapter_t *pAdapter) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + VOS_STATUS vos_status; + unsigned long rc; + + if (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated) + { + INIT_COMPLETION(pAdapter->ula_complete); + + /*To avoid race condition between the set key and the last EAPOL + packet, notify TL to finish upper layer authentication incase if the + last EAPOL packet pending in the TL queue.*/ + vos_status = WLANTL_Finish_ULA(wlan_hdd_ula_done_cb, pAdapter); + + if ( vos_status != VOS_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] WLANTL_Finish_ULA returned ERROR status= %d", + __LINE__, vos_status ); + return vos_status; + + } + + rc = wait_for_completion_timeout(&pAdapter->ula_complete, + msecs_to_jiffies(HDD_FINISH_ULA_TIME_OUT)); + if (rc <= 0) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failure wait on ULA to complete %ld"), rc); + /* we'll still fall through and return success since the + * connection may still get established but is just taking + * too long for us to wait */ + } + } + return VOS_STATUS_SUCCESS; +} + +v_U8_t* wlan_hdd_get_vendor_oui_ie_ptr(v_U8_t *oui, v_U8_t oui_size, v_U8_t *ie, int ie_len) +{ + + int left = ie_len; + v_U8_t *ptr = ie; + v_U8_t elem_id,elem_len; + v_U8_t eid = 0xDD; + + if ( NULL == ie || 0 == ie_len ) + return NULL; + + while(left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), + eid,elem_len,left); + return NULL; + } + if (elem_id == eid) + { + if(memcmp( &ptr[2], oui, oui_size)==0) + return ptr; + } + + left -= elem_len; + ptr += (elem_len + 2); + } + return NULL; +} + +/** + * hdd_get_ldpc() - Get adapter LDPC + * @adapter: adapter being queried + * @value: where to store the value + * + * Return: 0 on success, negative errno on failure + */ +int hdd_get_ldpc(hdd_adapter_t *adapter, int *value) +{ + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + int ret; + + ENTER(); + ret = sme_GetHTConfig(hal, adapter->sessionId, + WNI_CFG_HT_CAP_INFO_ADVANCE_CODING); + if (ret < 0) { + hddLog(LOGE, FL("Failed to get LDPC value")); + } else { + *value = ret; + ret = 0; + } + return ret; +} + +/** + * hdd_set_ldpc() - Set adapter LDPC + * @adapter: adapter being modified + * @value: new LDPC value + * + * Return: 0 on success, negative errno on failure + */ +int hdd_set_ldpc(hdd_adapter_t *adapter, int value) +{ + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + int ret; + + hddLog(LOG1, FL("%d"), value); + if (value) { + /* make sure HT capabilities allow this */ + eHalStatus status; + uint32_t cfg_value; + union { + uint16_t cfg_value16; + tSirMacHTCapabilityInfo ht_cap_info; + } u; + + status = ccmCfgGetInt(hal, WNI_CFG_HT_CAP_INFO, &cfg_value); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("Failed to get HT capability info")); + return -EIO; + } + u.cfg_value16 = cfg_value & 0xFFFF; + if (!u.ht_cap_info.advCodingCap) { + hddLog(LOGE, FL("LDCP not supported")); + return -EINVAL; + } + } + + ret = sme_UpdateHTConfig(hal, adapter->sessionId, + WNI_CFG_HT_CAP_INFO_ADVANCE_CODING, + value); + if (ret) + hddLog(LOGE, FL("Failed to set LDPC value")); + + return ret; +} + +/** + * hdd_get_tx_stbc() - Get adapter TX STBC + * @adapter: adapter being queried + * @value: where to store the value + * + * Return: 0 on success, negative errno on failure + */ +int hdd_get_tx_stbc(hdd_adapter_t *adapter, int *value) +{ + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + int ret; + + ENTER(); + ret = sme_GetHTConfig(hal, adapter->sessionId, + WNI_CFG_HT_CAP_INFO_TX_STBC); + if (ret < 0) { + hddLog(LOGE, FL("Failed to get TX STBC value")); + } else { + *value = ret; + ret = 0; + } + + return ret; +} + +/** + * hdd_set_tx_stbc() - Set adapter TX STBC + * @adapter: adapter being modified + * @value: new TX STBC value + * + * Return: 0 on success, negative errno on failure + */ +int hdd_set_tx_stbc(hdd_adapter_t *adapter, int value) +{ + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + int ret; + + hddLog(LOG1, FL("%d"), value); + if (value) { + /* make sure HT capabilities allow this */ + eHalStatus status; + uint32_t cfg_value; + union { + uint16_t cfg_value16; + tSirMacHTCapabilityInfo ht_cap_info; + } u; + + status = ccmCfgGetInt(hal, WNI_CFG_HT_CAP_INFO, &cfg_value); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("Failed to get HT capability info")); + return -EIO; + } + u.cfg_value16 = cfg_value & 0xFFFF; + if (!u.ht_cap_info.txSTBC) { + hddLog(LOGE, FL("TX STBC not supported")); + return -EINVAL; + } + } + ret = sme_UpdateHTConfig(hal, adapter->sessionId, + WNI_CFG_HT_CAP_INFO_TX_STBC, + value); + if (ret) + hddLog(LOGE, FL("Failed to set TX STBC value")); + + return ret; +} + +/** + * hdd_get_rx_stbc() - Get adapter RX STBC + * @adapter: adapter being queried + * @value: where to store the value + * + * Return: 0 on success, negative errno on failure + */ +int hdd_get_rx_stbc(hdd_adapter_t *adapter, int *value) +{ + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + int ret; + + ENTER(); + ret = sme_GetHTConfig(hal, adapter->sessionId, + WNI_CFG_HT_CAP_INFO_RX_STBC); + if (ret < 0) { + hddLog(LOGE, FL("Failed to get RX STBC value")); + } else { + *value = ret; + ret = 0; + } + + return ret; +} + +/** + * hdd_set_rx_stbc() - Set adapter RX STBC + * @adapter: adapter being modified + * @value: new RX STBC value + * + * Return: 0 on success, negative errno on failure + */ +int hdd_set_rx_stbc(hdd_adapter_t *adapter, int value) +{ + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + int ret; + + hddLog(LOG1, FL("%d"), value); + if (value) { + /* make sure HT capabilities allow this */ + eHalStatus status; + uint32_t cfg_value; + union { + uint16_t cfg_value16; + tSirMacHTCapabilityInfo ht_cap_info; + } u; + + status = ccmCfgGetInt(hal, WNI_CFG_HT_CAP_INFO, &cfg_value); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("Failed to get HT capability info")); + return -EIO; + } + u.cfg_value16 = cfg_value & 0xFFFF; + if (!u.ht_cap_info.rxSTBC) { + hddLog(LOGE, FL("RX STBC not supported")); + return -EINVAL; + } + } + ret = sme_UpdateHTConfig(hal, adapter->sessionId, + WNI_CFG_HT_CAP_INFO_RX_STBC, + value); + if (ret) + hddLog(LOGE, FL("Failed to set RX STBC value")); + + return ret; +} + +/** + * __iw_set_commit() - set commit + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int __iw_set_commit(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* Do nothing for now */ + return 0; +} + +/** + * iw_set_commit() - SSR wrapper function for __iw_set_commit + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +int iw_set_commit(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_commit(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_name() - get name + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int __iw_get_name(struct net_device *dev, + struct iw_request_info *info, + char *wrqu, char *extra) +{ + ENTER(); + strlcpy(wrqu, "Qcom:802.11n", IFNAMSIZ); + EXIT(); + return 0; +} + +/** + * __iw_get_name() - SSR wrapper for __iw_get_name + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_name(struct net_device *dev, + struct iw_request_info *info, + char *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_name(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + + +/** + * __iw_set_mode() - SIOCSIWMODE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tCsrRoamProfile *pRoamProfile; + eCsrRoamBssType LastBSSType; + eMib_dot11DesiredBssType connectedBssType; + hdd_config_t *pConfig; + struct wireless_dev *wdev; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + wdev = dev->ieee80211_ptr; + pRoamProfile = &pWextState->roamProfile; + LastBSSType = pRoamProfile->BSSType; + + hddLog(LOG1, "%s Old Bss type = %d", __func__, LastBSSType); + + switch (wrqu->mode) + { + case IW_MODE_ADHOC: + hddLog(LOG1, "%s Setting AP Mode as IW_MODE_ADHOC", __func__); + pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; + // Set the phymode correctly for IBSS. + pConfig = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + pWextState->roamProfile.phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); + pAdapter->device_mode = WLAN_HDD_IBSS; + wdev->iftype = NL80211_IFTYPE_ADHOC; + break; + case IW_MODE_INFRA: + hddLog(LOG1, "%s Setting AP Mode as IW_MODE_INFRA", __func__); + pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; + wdev->iftype = NL80211_IFTYPE_STATION; + break; + case IW_MODE_AUTO: + hddLog(LOG1, "%s Setting AP Mode as IW_MODE_AUTO", __func__); + pRoamProfile->BSSType = eCSR_BSS_TYPE_ANY; + break; + default: + hddLog(LOGE, "%s Unknown AP Mode value %d ", __func__, wrqu->mode); + return -EOPNOTSUPP; + } + + if ( LastBSSType != pRoamProfile->BSSType ) + { + //the BSS mode changed + // We need to issue disconnect if connected or in IBSS disconnect state + if ( hdd_connGetConnectedBssType( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) || + ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) ) + { + VOS_STATUS vosStatus; + // need to issue a disconnect to CSR. + INIT_COMPLETION(pAdapter->disconnect_comp_var); + vosStatus = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE ); + if(VOS_STATUS_SUCCESS == vosStatus) + { + unsigned long rc; + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed wait on disconnect_comp_var")); + } + } + } + + EXIT(); + return 0; +} + +/** + * iw_set_mode() - SSR wrapper for __iw_set_mode() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_mode(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_mode() - SIOCGIWMODE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int +__iw_get_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + switch (pWextState->roamProfile.BSSType) { + case eCSR_BSS_TYPE_INFRASTRUCTURE: + hddLog(LOG1, FL("returns IW_MODE_INFRA")); + wrqu->mode = IW_MODE_INFRA; + break; + case eCSR_BSS_TYPE_IBSS: + case eCSR_BSS_TYPE_START_IBSS: + hddLog(LOG1, FL("returns IW_MODE_ADHOC")); + wrqu->mode = IW_MODE_ADHOC; + break; + case eCSR_BSS_TYPE_ANY: + default: + hddLog(LOG1, FL("returns IW_MODE_AUTO")); + wrqu->mode = IW_MODE_AUTO; + break; + } + + EXIT(); + return 0; +} + +/** + * iw_get_mode() - SSR wrapper for __iw_get_mode() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_mode(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_freq() - SIOCSIWFREQ ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + v_U32_t numChans = 0; + v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + v_U32_t indx = 0; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamProfile * pRoamProfile; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + pRoamProfile = &pWextState->roamProfile; + + hddLog(LOG1,"setCHANNEL ioctl"); + + /* Link is up then return cant set channel*/ + if(eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState || + eConnectionState_Associated == pHddStaCtx->conn_info.connState) + { + hddLog( LOGE, "IBSS Associated"); + return -EOPNOTSUPP; + } + + /* Settings by Frequency as input */ + if((wrqu->freq.e == 1) && (wrqu->freq.m >= (tANI_U32)2.412e8) && + (wrqu->freq.m <= (tANI_U32)5.825e8)) + { + tANI_U32 freq = wrqu->freq.m / 100000; + + while ((indx < FREQ_CHAN_MAP_TABLE_SIZE) && (freq != freq_chan_map[indx].freq)) + indx++; + if (indx >= FREQ_CHAN_MAP_TABLE_SIZE) + { + return -EINVAL; + } + wrqu->freq.e = 0; + wrqu->freq.m = freq_chan_map[indx].chan; + + } + + if (wrqu->freq.e == 0) + { + if((wrqu->freq.m < WNI_CFG_CURRENT_CHANNEL_STAMIN) || + (wrqu->freq.m > WNI_CFG_CURRENT_CHANNEL_STAMAX)) + { + hddLog(LOG1,"%s: Channel [%d] is outside valid range from %d to %d", + __func__, wrqu->freq.m, WNI_CFG_CURRENT_CHANNEL_STAMIN, + WNI_CFG_CURRENT_CHANNEL_STAMAX); + return -EINVAL; + } + + numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if (ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, + validChan, &numChans) != eHAL_STATUS_SUCCESS){ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_VALID_CHANNEL_LIST")); + return -EIO; + } + + for (indx = 0; indx < numChans; indx++) { + if (wrqu->freq.m == validChan[indx]){ + break; + } + } + } + else{ + + return -EINVAL; + } + + if(indx >= numChans) + { + return -EINVAL; + } + + /* Set the Operational Channel */ + numChans = pRoamProfile->ChannelInfo.numOfChannels = 1; + pHddStaCtx->conn_info.operationChannel = wrqu->freq.m; + pRoamProfile->ChannelInfo.ChannelList = &pHddStaCtx->conn_info.operationChannel; + + hddLog(LOG1,"pRoamProfile->operationChannel = %d", wrqu->freq.m); + + EXIT(); + + return ret; +} + +/** + * iw_set_freq() - SSR wrapper for __iw_set_freq() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_freq(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_freq() - SIOCGIWFREQ ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @fwrq: ioctl frequency data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_freq(struct net_device *dev, struct iw_request_info *info, + struct iw_freq *fwrq, char *extra) +{ + v_U32_t status = FALSE, channel = 0, freq = 0; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal; + hdd_wext_state_t *pWextState; + tCsrRoamProfile * pRoamProfile; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + + pRoamProfile = &pWextState->roamProfile; + + if( pHddStaCtx->conn_info.connState== eConnectionState_Associated ) + { + if (sme_GetOperationChannel(hHal, &channel, pAdapter->sessionId) != eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to get operating channel %u"), pAdapter->sessionId); + return -EIO; + } + else + { + status = hdd_wlan_get_freq(channel, &freq); + if( TRUE == status ) + { + /* Set Exponent parameter as 6 (MHZ) in struct iw_freq + * iwlist & iwconfig command shows frequency into proper + * format (2.412 GHz instead of 246.2 MHz)*/ + fwrq->m = freq; + fwrq->e = MHZ; + } + } + } + else + { + /* Set Exponent parameter as 6 (MHZ) in struct iw_freq + * iwlist & iwconfig command shows frequency into proper + * format (2.412 GHz instead of 246.2 MHz)*/ + fwrq->m = 0; + fwrq->e = MHZ; + } + return 0; +} + +/** + * iw_get_freq() - SSR wrapper for __iw_get_freq() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @fwrq: pointer to frequency data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_freq(struct net_device *dev, struct iw_request_info *info, + struct iw_freq *fwrq, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_freq(dev, info, fwrq, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_tx_power() - SIOCGIWTXPOW ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + wrqu->txpower.value = 0; + return 0; + } + wlan_hdd_get_classAstats(pAdapter); + wrqu->txpower.value = pAdapter->hdd_stats.ClassA_stat.max_pwr; + + return 0; +} + +/** + * iw_get_tx_power() - SSR wrapper for __iw_get_tx_power() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_tx_power(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_tx_power() - SIOCSIWTXPOW ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if ( ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, wrqu->txpower.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_CURRENT_TX_POWER_LEVEL")); + return -EIO; + } + + EXIT(); + + return 0; +} + +/** + * iw_set_tx_power() - SSR wrapper for __iw_set_tx_power() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_tx_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_tx_power(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_bitrate() - SIOCGIWRATE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_bitrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + eHalStatus status = eHAL_STATUS_SUCCESS; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + wrqu->bitrate.value = 0; + } + else { + status = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD, + SME_SUMMARY_STATS | + SME_GLOBAL_CLASSA_STATS | + SME_GLOBAL_CLASSB_STATS | + SME_GLOBAL_CLASSC_STATS | + SME_GLOBAL_CLASSD_STATS | + SME_PER_STA_STATS, + hdd_StatisticsCB, 0, FALSE, + pHddStaCtx->conn_info.staId[0], pAdapter, + pAdapter->sessionId ); + + if(eHAL_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics", + __func__); + return status; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME timeout while retrieving statistics", + __func__); + return VOS_STATUS_E_FAILURE; + } + + wrqu->bitrate.value = pAdapter->hdd_stats.ClassA_stat.tx_rate*500*1000; + } + + EXIT(); + + return vos_status; +} + +/** + * iw_get_bitrate() - SSR wrapper for __iw_get_bitrate() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_bitrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_bitrate(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_bitrate() - SIOCSIWRATE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_bitrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_wext_state_t *pWextState; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; + v_U32_t a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; + v_U32_t b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; + v_U32_t i, rate; + v_U32_t valid_rate = FALSE, active_phy_mode = 0; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + return -ENXIO ; + } + + rate = wrqu->bitrate.value; + + if (rate == -1) + { + rate = WNI_CFG_FIXED_RATE_AUTO; + valid_rate = TRUE; + } + else if (ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS) + { + if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G + || active_phy_mode == WNI_CFG_DOT11_MODE_11B) + { + if ((ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_SUPPORTED_RATES_11A, + supp_rates, &a_len) == eHAL_STATUS_SUCCESS) && + (ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_SUPPORTED_RATES_11B, + supp_rates, &b_len) == eHAL_STATUS_SUCCESS)) + { + for (i = 0; i < (b_len + a_len); ++i) + { + /* supported rates returned is double the actual rate so we divide it by 2 */ + if ((supp_rates[i]&0x7F)/2 == rate) + { + valid_rate = TRUE; + rate = i + WNI_CFG_FIXED_RATE_1MBPS; + break; + } + } + } + } + } + if (valid_rate != TRUE) + { + return -EINVAL; + } + if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_FIXED_RATE, rate, + ccmCfgSetCallback,eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_FIXED_RATE")); + return -EIO; + } + return 0; +} + +/** + * iw_set_bitrate() - SSR wrapper for __iw_set_bitrate() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_bitrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_bitrate(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_genie() - SIOCSIWGENIE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_genie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + u_int8_t *genie = NULL; + u_int8_t *base_genie = NULL; + v_U16_t remLen; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!wrqu->data.length) { + hdd_clearRoamProfileIe(pAdapter); + EXIT(); + return 0; + } + + base_genie = mem_alloc_copy_from_user_helper(wrqu->data.pointer, + wrqu->data.length); + if (NULL == base_genie) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + genie = base_genie; + + remLen = wrqu->data.length; + + hddLog(LOG1,"iw_set_genie ioctl IE[0x%X], LEN[%d]", genie[0], genie[1]); + + /* clear any previous genIE before this call */ + memset( &pWextState->genIE, 0, sizeof(pWextState->genIE) ); + + while (remLen >= 2) + { + v_U16_t eLen = 0; + v_U8_t elementId; + elementId = *genie++; + eLen = *genie++; + remLen -= 2; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]", + __func__, elementId, eLen); + + switch ( elementId ) + { + case IE_EID_VENDOR: + if ((IE_LEN_SIZE+IE_EID_SIZE+IE_VENDOR_OUI_SIZE) > eLen) /* should have at least OUI */ + { + ret = -EINVAL; + goto exit; + } + + if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) + { + v_U16_t curGenIELen = pWextState->genIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS OUI(%02x %02x %02x %02x) IE(len %d)", + __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2); + + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " + "Need bigger buffer space"); + VOS_ASSERT(0); + ret = -EINVAL; + goto exit; + } + // save to Additional IE ; it should be accumulated to handle WPS IE + other IE + memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2); + pWextState->genIE.length += eLen + 2; + } + else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) + { + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2); + if ((eLen + 2) > (sizeof(pWextState->WPARSNIE))) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " + "Need bigger buffer space"); + ret = -EINVAL; + VOS_ASSERT(0); + goto exit; + } + memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); + memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)); + pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE; + pWextState->roamProfile.nWPAReqIELength = eLen + 2; + } + else /* any vendorId except WPA IE should be accumulated to genIE */ + { + v_U16_t curGenIELen = pWextState->genIE.length; + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OUI(%02x %02x %02x %02x) IE(len %d)", + __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2); + + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) ) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " + "Need bigger buffer space"); + VOS_ASSERT(0); + ret = -ENOMEM; + goto exit; + } + // save to Additional IE ; it should be accumulated to handle WPS IE + other IE + memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2); + pWextState->genIE.length += eLen + 2; + } + break; + case DOT11F_EID_RSN: + hddLog (LOG1, "%s Set RSN IE (len %d)",__func__, eLen+2); + if ((eLen + 2) > (sizeof(pWextState->WPARSNIE))) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " + "Need bigger buffer space"); + ret = -EINVAL; + VOS_ASSERT(0); + goto exit; + } + memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); + memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)); + pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE; + pWextState->roamProfile.nRSNReqIELength = eLen + 2; + break; + + default: + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, elementId); + goto exit; + } + genie += eLen; + remLen -= eLen; + } +exit: + EXIT(); + kfree(base_genie); + return ret; +} + +/** + * iw_set_genie() - SSR wrapper for __iw_set_genie() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_genie(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_genie() - SIOCGIWGENIE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_genie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + eHalStatus status; + v_U32_t length = DOT11F_IE_RSN_MAX_LEN; + v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN]; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + hddLog(LOG1,"getGEN_IE ioctl"); + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + if( pHddStaCtx->conn_info.connState == eConnectionState_NotConnected) + { + return -ENXIO; + } + + // Return something ONLY if we are associated with an RSN or WPA network + if ( VOS_TRUE != hdd_IsAuthTypeRSN(WLAN_HDD_GET_HAL_CTX(pAdapter), + pWextState->roamProfile.negotiatedAuthType)) + { + return -ENXIO; + } + + // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.) + status = csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &length, + genIeBytes); + length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN); + if (wrqu->data.length < length) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } + vos_mem_copy( extra, (v_VOID_t*)genIeBytes, length); + wrqu->data.length = length; + + hddLog(LOG1,"%s: RSN IE of %d bytes returned", __func__, wrqu->data.length ); + + EXIT(); + + return 0; +} + +/** + * iw_get_genie() - SSR wrapper for __iw_get_genie() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_genie(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_encode() - SIOCGIWENCODE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @dwrq: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_encode(struct net_device *dev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); + int keyId; + eCsrAuthType authType = eCSR_AUTH_TYPE_NONE; + int i; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + keyId = pRoamProfile->Keys.defaultIndex; + + if(keyId < 0 || keyId >= MAX_WEP_KEYS) + { + hddLog(LOG1,"%s: Invalid keyId : %d", __func__, keyId); + return -EINVAL; + } + + if(pRoamProfile->Keys.KeyLength[keyId] > 0) + { + dwrq->flags |= IW_ENCODE_ENABLED; + dwrq->length = pRoamProfile->Keys.KeyLength[keyId]; + vos_mem_copy(extra,&(pRoamProfile->Keys.KeyMaterial[keyId][0]),pRoamProfile->Keys.KeyLength[keyId]); + + dwrq->flags |= (keyId + 1); + + } + else + { + dwrq->flags |= IW_ENCODE_DISABLED; + } + + for(i=0; i < MAX_WEP_KEYS; i++) + { + if(pRoamProfile->Keys.KeyMaterial[i] == NULL) + { + continue; + } + else + { + break; + } + } + + if(MAX_WEP_KEYS == i) + { + dwrq->flags |= IW_ENCODE_NOKEY; + } + + authType = ((hdd_station_ctx_t*)WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; + + if(eCSR_AUTH_TYPE_OPEN_SYSTEM == authType) + { + dwrq->flags |= IW_ENCODE_OPEN; + } + else + { + dwrq->flags |= IW_ENCODE_RESTRICTED; + } + EXIT(); + return 0; +} + +/** + * iw_get_encode() - SSR wrapper for __iw_get_encode() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @dwrq: pointer to encoding information + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_encode(struct net_device *dev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_encode(dev, info, dwrq, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +#define PAE_ROLE_AUTHENTICATOR 1 // =1 for authenticator, +#define PAE_ROLE_SUPPLICANT 0 // =0 for supplicant + + +/* + * This function sends a single 'key' to LIM at all time. + */ + +/** + * __iw_get_rts_threshold() - SIOCGIWRTS ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + v_U32_t status = 0; + + status = hdd_wlan_get_rts_threshold(pAdapter,wrqu); + + return status; +} + +/** + * iw_get_rts_threshold() - SSR wrapper for __iw_get_rts_threshold() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_rts_threshold(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_rts_threshold() - SIOCSIWRTS ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if ( wrqu->rts.value < WNI_CFG_RTS_THRESHOLD_STAMIN || wrqu->rts.value > WNI_CFG_RTS_THRESHOLD_STAMAX ) + { + return -EINVAL; + } + + if ( ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, wrqu->rts.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_RTS_THRESHOLD")); + return -EIO; + } + + EXIT(); + + return 0; +} + +/** + * iw_set_rts_threshold() - SSR wrapper for __iw_set_rts_threshold() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_rts_threshold(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_frag_threshold() - SIOCGIWFRAG ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + v_U32_t status = 0; + + status = hdd_wlan_get_frag_threshold(pAdapter,wrqu); + + return status; +} + +/** + * iw_get_frag_threshold() - SSR wrapper for __iw_get_frag_threshold() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_frag_threshold(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_frag_threshold() - SIOCSIWFRAG ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + + if ( wrqu->frag.value < WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN || wrqu->frag.value > WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX ) + { + return -EINVAL; + } + + if ( ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, wrqu->frag.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_FRAGMENTATION_THRESHOLD")); + return -EIO; + } + + EXIT(); + + return 0; +} + +/** + * iw_set_frag_threshold() - SSR wrapper for __iw_set_frag_threshold() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_frag_threshold(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_power_mode() - get power mode + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int __iw_get_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + return -EOPNOTSUPP; +} + +/** + * iw_get_power_mode() - SSR wrapper function for __iw_get_power_mode + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +int iw_get_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_power_mode(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_power_mode() - set power mode + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int __iw_set_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + return -EOPNOTSUPP; +} + +/** + * iw_set_power_mode() - SSR wrapper function for __iw_set_power_mode + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +int iw_set_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_power_mode(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_range() - SIOCGIWRANGE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_range(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + struct iw_range *range = (struct iw_range *) extra; + + v_U8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + + v_U32_t num_channels = sizeof(channels); + v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; + v_U32_t a_len; + v_U32_t b_len; + v_U32_t active_phy_mode = 0; + v_U8_t index = 0, i; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + wrqu->data.length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + /*Get the phy mode*/ + if (ccmCfgGetInt(hHal, + WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "active_phy_mode = %d", active_phy_mode); + + if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G) + { + /*Get the supported rates for 11G band*/ + a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; + if (ccmCfgGetStr(hHal, + WNI_CFG_SUPPORTED_RATES_11A, + supp_rates, &a_len) == eHAL_STATUS_SUCCESS) + { + if (a_len > WNI_CFG_SUPPORTED_RATES_11A_LEN) + { + a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; + } + for (i = 0; i < a_len; i++) + { + range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000; + } + range->num_bitrates = a_len; + } + else + { + return -EIO; + } + } + else if (active_phy_mode == WNI_CFG_DOT11_MODE_11B) + { + /*Get the supported rates for 11B band*/ + b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; + if (ccmCfgGetStr(hHal, + WNI_CFG_SUPPORTED_RATES_11B, + supp_rates, &b_len) == eHAL_STATUS_SUCCESS) + { + if (b_len > WNI_CFG_SUPPORTED_RATES_11B_LEN) + { + b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; + } + for (i = 0; i < b_len; i++) + { + range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000; + } + range->num_bitrates = b_len; + } + else + { + return -EIO; + } + } + } + + range->max_rts = WNI_CFG_RTS_THRESHOLD_STAMAX; + range->min_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN; + range->max_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX; + + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = MAX_WEP_KEYS; + + // we support through Wireless Extensions 22 + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 22; + + /*Supported Channels and Frequencies*/ + if (ccmCfgGetStr((hHal), WNI_CFG_VALID_CHANNEL_LIST, channels, &num_channels) != eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_VALID_CHANNEL_LIST")); + return -EIO; + } + if (num_channels > IW_MAX_FREQUENCIES) + { + num_channels = IW_MAX_FREQUENCIES; + } + + range->num_channels = num_channels; + range->num_frequency = num_channels; + + for (index=0; index < num_channels; index++) + { + v_U32_t frq_indx = 0; + + range->freq[index].i = channels[index]; + while (frq_indx < FREQ_CHAN_MAP_TABLE_SIZE) + { + if(channels[index] == freq_chan_map[frq_indx].chan) + { + range->freq[index].m = freq_chan_map[frq_indx].freq * 100000; + range->freq[index].e = 1; + break; + } + frq_indx++; + } + } + + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + + /*Encryption capability*/ + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + + /* Txpower capability */ + range->txpower_capa = IW_TXPOW_MWATT; + + /*Scanning capability*/ + #if WIRELESS_EXT >= 22 + range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_CHANNEL; + #endif + + EXIT(); + return 0; +} + +/** + * iw_get_range() - SSR wrapper for __iw_get_range() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_range(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_range(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* Callback function registered with PMC to know status of PMC request */ +static void iw_power_callback_fn (void *pContext, eHalStatus status) +{ + struct statsContext *pStatsContext; + + if (NULL == pContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pContext [%p]", + __func__, pContext); + return; + } + + pStatsContext = (struct statsContext *)pContext; + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + if (POWER_CONTEXT_MAGIC != pStatsContext->magic) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, magic [%08x]", + __func__, pStatsContext->magic); + + if (ioctl_debug) + { + pr_info("%s: Invalid context, magic [%08x]\n", + __func__, pStatsContext->magic); + } + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pStatsContext->magic = 0; + + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/* Callback function for tx per hit */ +void hdd_tx_per_hit_cb (void *pCallbackContext) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)pCallbackContext; + unsigned char tx_fail[16]; + union iwreq_data wrqu; + + if (NULL == pAdapter || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) + { + hddLog(LOGE, "hdd_tx_per_hit_cb: pAdapter is NULL"); + return; + } + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlcpy(tx_fail, "TX_FAIL", sizeof(tx_fail)); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, tx_fail); +} + +void hdd_GetClassA_statisticsCB(void *pStats, void *pContext) +{ + struct statsContext *pStatsContext; + tCsrGlobalClassAStatsInfo *pClassAStats; + hdd_adapter_t *pAdapter; + + if (ioctl_debug) + { + pr_info("%s: pStats [%p] pContext [%p]\n", + __func__, pStats, pContext); + } + + if ((NULL == pStats) || (NULL == pContext)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pStats [%p] pContext [%p]", + __func__, pStats, pContext); + return; + } + + pClassAStats = pStats; + pStatsContext = pContext; + pAdapter = pStatsContext->pAdapter; + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pStatsContext->magic); + if (ioctl_debug) + { + pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", + __func__, pAdapter, pStatsContext->magic); + } + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pStatsContext->magic = 0; + + /* copy over the stats. do so as a struct copy */ + pAdapter->hdd_stats.ClassA_stat = *pClassAStats; + + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +void hdd_GetLink_SpeedCB(tSirLinkSpeedInfo *pLinkSpeed, void *pContext) +{ + struct linkspeedContext *pLinkSpeedContext; + hdd_adapter_t *pAdapter; + + if ((NULL == pLinkSpeed) || (NULL == pContext)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pLinkSpeed [%p] pContext [%p]", + __func__, pLinkSpeed, pContext); + return; + } + spin_lock(&hdd_context_lock); + pLinkSpeedContext = pContext; + pAdapter = pLinkSpeedContext->pAdapter; + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + + if ((NULL == pAdapter) || (LINK_CONTEXT_MAGIC != pLinkSpeedContext->magic)) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pLinkSpeedContext->magic); + if (ioctl_debug) + { + pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", + __func__, pAdapter, pLinkSpeedContext->magic); + } + return; + } + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pLinkSpeedContext->magic = 0; + + /* copy over the stats. do so as a struct copy */ + pAdapter->ls_stats = *pLinkSpeed; + + /* notify the caller */ + complete(&pLinkSpeedContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + eHalStatus hstatus; + unsigned long rc; + struct statsContext context; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); + return VOS_STATUS_E_FAULT; + } + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__); + return VOS_STATUS_SUCCESS; + } + + /* we are connected + prepare our callback context */ + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = STATS_CONTEXT_MAGIC; + /* query only for Class A statistics (which include link speed) */ + hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), + eCSR_HDD, + SME_GLOBAL_CLASSA_STATS, + hdd_GetClassA_statisticsCB, + 0, // not periodic + FALSE, //non-cached results + pHddStaCtx->conn_info.staId[0], + &context, + pAdapter->sessionId ); + if (eHAL_STATUS_SUCCESS != hstatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve Class A statistics", + __func__); + /* we'll returned a cached value below */ + } + else + { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving Class A statistics")); + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + /* either callback updated pAdapter stats or it has cached data */ + return VOS_STATUS_SUCCESS; +} + +static void hdd_get_station_statisticsCB(void *pStats, void *pContext) +{ + struct statsContext *pStatsContext; + tCsrSummaryStatsInfo *pSummaryStats; + tCsrGlobalClassAStatsInfo *pClassAStats; + hdd_adapter_t *pAdapter; + + if (ioctl_debug) + { + pr_info("%s: pStats [%p] pContext [%p]\n", + __func__, pStats, pContext); + } + + if ((NULL == pStats) || (NULL == pContext)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Bad param, pStats [%p] pContext [%p]", + __func__, pStats, pContext); + return; + } + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + pSummaryStats = (tCsrSummaryStatsInfo *)pStats; + pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 ); + pStatsContext = pContext; + pAdapter = pStatsContext->pAdapter; + if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic)) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter [%p] magic [%08x]", + __func__, pAdapter, pStatsContext->magic); + if (ioctl_debug) + { + pr_info("%s: Invalid context, pAdapter [%p] magic [%08x]\n", + __func__, pAdapter, pStatsContext->magic); + } + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pStatsContext->magic = 0; + + /* copy over the stats. do so as a struct copy */ + pAdapter->hdd_stats.summary_stat = *pSummaryStats; + pAdapter->hdd_stats.ClassA_stat = *pClassAStats; + + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + eHalStatus hstatus; + unsigned long rc; + struct statsContext context; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); + return VOS_STATUS_SUCCESS; + } + + /* we are connected + prepare our callback context */ + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = STATS_CONTEXT_MAGIC; + + /* query only for Summary & Class A statistics */ + hstatus = sme_GetStatistics(WLAN_HDD_GET_HAL_CTX(pAdapter), + eCSR_HDD, + SME_SUMMARY_STATS | + SME_GLOBAL_CLASSA_STATS, + hdd_get_station_statisticsCB, + 0, // not periodic + FALSE, //non-cached results + pHddStaCtx->conn_info.staId[0], + &context, + pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != hstatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics", + __func__); + /* we'll return with cached values */ + } + else + { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving statistics")); + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + /* either callback updated pAdapter stats or it has cached data */ + return VOS_STATUS_SUCCESS; +} + + +/* + * Support for the LINKSPEED private command + * Per the WiFi framework the response must be of the form + * "LinkSpeed xx" + */ +static int iw_get_linkspeed(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + char *pLinkSpeed = (char*)extra; + int len = sizeof(v_U32_t) + 1; + v_U32_t link_speed = 0; + int rc; + int ret_val; + + ENTER(); + ret_val = wlan_hdd_get_link_speed(pAdapter, &link_speed); + if (0 != ret_val) { + return ret_val; + } + + wrqu->data.length = len; + /* return the linkspeed in the format required by the WiFi Framework */ + rc = snprintf(pLinkSpeed, len, "%u", link_speed); + if ((rc < 0) || (rc >= len)) + { + /* encoding or length error? */ + hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed")); + return -EIO; + } + + /* a value is being successfully returned */ + EXIT(); + return rc; +} + +/* + * Helper function to return correct value for WLAN_GET_LINK_SPEED + * + */ +static int __iw_get_linkspeed_priv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int rc, valid; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + valid = wlan_hdd_validate_context(hdd_ctx); + if (0 != valid) + return valid; + + rc = iw_get_linkspeed(dev, info, wrqu, extra); + + if (rc < 0) + return rc; + + /* a value is being successfully returned */ + return 0; +} + +static int iw_get_linkspeed_priv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_linkspeed_priv(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * Support for the RSSI & RSSI-APPROX private commands + * Per the WiFi framework the response must be of the form + * " rssi " + * unless we are not associated, in which case the response is + * "OK" + */ +static int iw_get_rssi(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + char *cmd = extra; + int len = wrqu->data.length; + v_S7_t s7Rssi = 0; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length; + VOS_STATUS vosStatus; + int rc; + + if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || + (0 == ssidlen) || (ssidlen >= len)) + { + /* we are not connected or our SSID is too long + so we cannot report an rssi */ + rc = scnprintf(cmd, len, "OK"); + } + else + { + /* we are connected with a valid SSID + so we can write the SSID into the return buffer + (note that it is not NUL-terminated) */ + memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen ); + + vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi); + + if (VOS_STATUS_SUCCESS == vosStatus) + { + /* append the rssi to the ssid in the format required by + the WiFI Framework */ + rc = scnprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi); + rc += ssidlen; + } + else + { + rc = -1; + } + } + + /* verify that we wrote a valid response */ + if ((rc < 0) || (rc >= len)) + { + // encoding or length error? + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to encode RSSI, got [%s]", + __func__, cmd); + return -EIO; + } + + /* a value is being successfully returned */ + return rc; +} + +VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) +{ + struct statsContext context; + eHalStatus status; + hdd_context_t *pHddCtx; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Adapter NULL"); + return VOS_STATUS_E_FAULT; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "power mode=%d", mode); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (pHddCtx->isLogpInProgress) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:LOGP in Progress. Ignore!!!", __func__); + return VOS_STATUS_E_FAILURE; + } + + init_completion(&context.completion); + + context.pAdapter = pAdapter; + context.magic = POWER_CONTEXT_MAGIC; + + if (DRIVER_POWER_MODE_ACTIVE == mode) + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering " + "Full Power", __func__); + status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), + iw_power_callback_fn, &context, + eSME_FULL_PWR_NEEDED_BY_HDD); + // Enter Full power command received from GUI this means we are disconnected + // Set PMC remainInPowerActiveTillDHCP flag to disable auto BMPS entry by PMC + sme_SetDHCPTillPowerActiveFlag(pHddCtx->hHal, TRUE); + if (eHAL_STATUS_PMC_PENDING == status) + { + unsigned long rc; + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout( + &context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); + + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while requesting full power")); + } + } + } + else if (DRIVER_POWER_MODE_AUTO == mode) + { + if (pHddCtx->cfg_ini->fIsBmpsEnabled) + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering Bmps ", + __func__); + // Enter BMPS command received from GUI this means DHCP is completed + // Clear PMC remainInPowerActiveTillDHCP flag to enable auto BMPS entry + sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter), + FALSE); + status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), + iw_power_callback_fn, &context); + if (eHAL_STATUS_PMC_PENDING == status) + { + unsigned long rc; + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout( + &context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while requesting BMPS")); + } + } + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "BMPS is not " + "enabled in the cfg"); + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wlan_hdd_set_powersave(hdd_adapter_t *pAdapter, int mode) +{ + hdd_context_t *pHddCtx; + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Adapter NULL"); + return VOS_STATUS_E_FAULT; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "power mode=%d", mode); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (DRIVER_POWER_MODE_ACTIVE == mode) + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering " + "Full Power", __func__); + + /* + * Enter Full power command received from GUI + * this means we are disconnected + */ + sme_PsOffloadDisablePowerSave(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + } + else if (DRIVER_POWER_MODE_AUTO == mode) + { + if (pHddCtx->cfg_ini->fIsBmpsEnabled) + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering Bmps ", + __func__); + + /* + * Enter BMPS command received from GUI + * this means DHCP is completed + */ + sme_PsOffloadEnablePowerSave(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "BMPS is not " + "enabled in the cfg"); + } + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wlan_hdd_exit_lowpower(hdd_context_t *pHddCtx, + hdd_adapter_t *pAdapter) +{ + VOS_STATUS vos_Status; + + if ((NULL == pAdapter) || (NULL == pHddCtx)) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid pointer"); + return VOS_STATUS_E_FAULT; + } + + /**Exit from Deep sleep or standby if we get the driver + START cmd from android GUI + */ + if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop) + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit " + "from Stand by",__func__); + vos_Status = hdd_exit_standby(pHddCtx); + } + else if (eHDD_SUSPEND_DEEP_SLEEP == pHddCtx->hdd_ps_state) + { + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit " + "from deep sleep",__func__); + vos_Status = hdd_exit_deep_sleep(pHddCtx, pAdapter); + } + else + { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Not in standby or deep sleep. " + "Ignore start cmd %d", __func__, pHddCtx->hdd_ps_state); + vos_Status = VOS_STATUS_SUCCESS; + } + + return vos_Status; +} + +VOS_STATUS wlan_hdd_enter_lowpower(hdd_context_t *pHddCtx) +{ + VOS_STATUS vos_Status = VOS_STATUS_E_FAILURE; + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "HDD context NULL"); + return VOS_STATUS_E_FAULT; + } + + if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop) + { + //Execute standby procedure. + //Executing standby procedure will cause the STA to + //disassociate first and then the chip will be put into standby. + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering Stand by mode"); + vos_Status = hdd_enter_standby(pHddCtx); + } + else if (WLAN_MAP_DRIVER_STOP_TO_DEEP_SLEEP == + pHddCtx->cfg_ini->nEnableDriverStop) + { + //Execute deep sleep procedure + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering " + "deep sleep mode"); + //Deep sleep not supported + vos_Status = hdd_enter_standby(pHddCtx); + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO_LOW, "%s: Driver stop is not enabled %d", + __func__, pHddCtx->cfg_ini->nEnableDriverStop); + vos_Status = VOS_STATUS_SUCCESS; + } + + return vos_Status; +} + + +void* wlan_hdd_change_country_code_callback(void *pAdapter) +{ + + hdd_adapter_t *call_back_pAdapter = pAdapter; + complete(&call_back_pAdapter->change_country_code); + + return NULL; +} + +/** + * __iw_set_priv() - SIOCSIWPRIV ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_priv(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + char *cmd = NULL; + int cmd_len = wrqu->data.length; + int ret = 0; + int rc = 0; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + cmd = mem_alloc_copy_from_user_helper(wrqu->data.pointer, + wrqu->data.length); + if (NULL == cmd) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + if (ioctl_debug) + { + pr_info("%s: req [%s] len [%d]\n", __func__, cmd, cmd_len); + } + + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: ***Received %s cmd from Wi-Fi GUI***", __func__, cmd); + + if (pHddCtx->isLogpInProgress) { + if (ioctl_debug) + { + pr_info("%s: RESTART in progress\n", __func__); + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!",__func__); + kfree(cmd); + return -EBUSY; + } + + if (strncmp(cmd, "CSCAN", 5) == 0 ) + { + if (eHAL_STATUS_SUCCESS != iw_set_cscan(dev, info, wrqu, cmd)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Error in iw_set_scan!", __func__); + rc = -EINVAL; + } + } + else if( strcasecmp(cmd, "start") == 0 ) { + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Start command"); + /*Exit from Deep sleep or standby if we get the driver START cmd from android GUI*/ + + vos_status = wlan_hdd_exit_lowpower(pHddCtx, pAdapter); + if (vos_status == VOS_STATUS_SUCCESS) + { + union iwreq_data wrqu; + char buf[10]; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlcpy(buf, "START", sizeof(buf)); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: START CMD Status %d", __func__, vos_status); + rc = -EIO; + } + goto done; + } + else if( strcasecmp(cmd, "stop") == 0 ) + { + union iwreq_data wrqu; + char buf[10]; + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Stop command"); + + wlan_hdd_enter_lowpower(pHddCtx); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlcpy(buf, "STOP", sizeof(buf)); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); + goto done; + } + else if (strcasecmp(cmd, "macaddr") == 0) + { + ret = snprintf(cmd, cmd_len, "Macaddr = " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes)); + } + else if (strcasecmp(cmd, "scan-active") == 0) + { + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("making default scan to active")); + pHddCtx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + ret = snprintf(cmd, cmd_len, "OK"); + } + else if (strcasecmp(cmd, "scan-passive") == 0) + { + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("making default scan to active")); + pHddCtx->ioctl_scan_mode = eSIR_PASSIVE_SCAN; + ret = snprintf(cmd, cmd_len, "OK"); + } + else if( strcasecmp(cmd, "scan-mode") == 0 ) + { + ret = snprintf(cmd, cmd_len, "ScanMode = %u", pAdapter->scan_info.scan_mode); + } + else if( strcasecmp(cmd, "linkspeed") == 0 ) + { + ret = iw_get_linkspeed(dev, info, wrqu, cmd); + } + else if( strncasecmp(cmd, "COUNTRY", 7) == 0 ) { + char *country_code; + unsigned long rc; + eHalStatus eHal_status; + + country_code = cmd + 8; + + init_completion(&pAdapter->change_country_code); + + eHal_status = sme_ChangeCountryCode(pHddCtx->hHal, + (void *)(tSmeChangeCountryCallback)wlan_hdd_change_country_code_callback, + country_code, + pAdapter, + pHddCtx->pvosContext, + eSIR_TRUE, + eSIR_TRUE); + + /* Wait for completion */ + rc = wait_for_completion_timeout(&pAdapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timedout while setting country code")); + } + + if (eHAL_STATUS_SUCCESS != eHal_status) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: SME Change Country code fail", __func__); + kfree(cmd); + return -EIO; + } + } + else if( strncasecmp(cmd, "rssi", 4) == 0 ) + { + ret = iw_get_rssi(dev, info, wrqu, cmd); + } + else if( strncasecmp(cmd, "powermode", 9) == 0 ) { + int mode; + char *ptr; + + if (9 < cmd_len) + { + ptr = (char*)(cmd + 9); + + }else{ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "CMD LENGTH %d is not correct",cmd_len); + kfree(cmd); + return -EINVAL; + } + + if (1 != sscanf(ptr,"%d",&mode)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "powermode input %s is not correct",ptr); + kfree(cmd); + return -EIO; + } + + if(!pHddCtx->cfg_ini->enablePowersaveOffload) + wlan_hdd_enter_bmps(pAdapter, mode); + else + wlan_hdd_set_powersave(pAdapter, mode); + } + else if (strncasecmp(cmd, "getpower", 8) == 0 ) { + v_U32_t pmc_state; + v_U16_t value; + + pmc_state = pmcGetPmcState(WLAN_HDD_GET_HAL_CTX(pAdapter)); + if(pmc_state == BMPS) { + value = DRIVER_POWER_MODE_AUTO; + } + else { + value = DRIVER_POWER_MODE_ACTIVE; + } + ret = snprintf(cmd, cmd_len, "powermode = %u", value); + } + else if( strncasecmp(cmd, "btcoexmode", 10) == 0 ) { + hddLog( VOS_TRACE_LEVEL_INFO, "btcoexmode"); + /*TODO: set the btcoexmode*/ + } + else if( strcasecmp(cmd, "btcoexstat") == 0 ) { + + hddLog(VOS_TRACE_LEVEL_INFO, "BtCoex Status"); + /*TODO: Return the btcoex status*/ + } + else if( strcasecmp(cmd, "rxfilter-start") == 0 ) { + + hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Start command"); + + /*TODO: Enable Rx data Filter*/ + } + else if( strcasecmp(cmd, "rxfilter-stop") == 0 ) { + + hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Stop command"); + + /*TODO: Disable Rx data Filter*/ + } + else if( strcasecmp(cmd, "rxfilter-statistics") == 0 ) { + + hddLog( VOS_TRACE_LEVEL_INFO, "Rx Data Filter Statistics command"); + /*TODO: rxfilter-statistics*/ + } + else if( strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { + + hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-add"); + /*TODO: rxfilter-add*/ + } + else if( strncasecmp(cmd, "rxfilter-remove",15) == 0 ) { + + hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-remove"); + /*TODO: rxfilter-remove*/ + } +#ifdef FEATURE_WLAN_SCAN_PNO + else if( strncasecmp(cmd, "pnosetup", 8) == 0 ) { + hddLog( VOS_TRACE_LEVEL_INFO, "pnosetup"); + /*TODO: support pnosetup*/ + } + else if( strncasecmp(cmd, "pnoforce", 8) == 0 ) { + hddLog( VOS_TRACE_LEVEL_INFO, "pnoforce"); + /*TODO: support pnoforce*/ + } + else if( strncasecmp(cmd, "pno",3) == 0 ) { + + hddLog( VOS_TRACE_LEVEL_INFO, "pno"); + ret = iw_set_pno(dev, info, wrqu, cmd, 3); + kfree(cmd); + return ret; + } +#endif /*FEATURE_WLAN_SCAN_PNO*/ + else if( strncasecmp(cmd, "powerparams",11) == 0 ) { + hddLog( VOS_TRACE_LEVEL_INFO, "powerparams"); + vos_status = iw_set_power_params(dev, info, wrqu, cmd, 11); + kfree(cmd); + return (vos_status == VOS_STATUS_SUCCESS) ? 0 : -EINVAL; + } + else if( 0 == strncasecmp(cmd, "CONFIG-TX-TRACKING", 18) ) { + tSirTxPerTrackingParam tTxPerTrackingParam; + char *ptr; + + if (18 < cmd_len) + { + ptr = (char*)(cmd + 18); + }else{ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "CMD LENGTH %d is not correct",cmd_len); + kfree(cmd); + return -EINVAL; + } + + if (4 != sscanf(ptr,"%hhu %hhu %hhu %u", + &(tTxPerTrackingParam.ucTxPerTrackingEnable), + &(tTxPerTrackingParam.ucTxPerTrackingPeriod), + &(tTxPerTrackingParam.ucTxPerTrackingRatio), + &(tTxPerTrackingParam.uTxPerTrackingWatermark))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "CONFIG-TX-TRACKING %s input is not correct",ptr); + kfree(cmd); + return -EIO; + } + + // parameters checking + // period has to be larger than 0 + if (0 == tTxPerTrackingParam.ucTxPerTrackingPeriod) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Period input is not correct"); + kfree(cmd); + return -EIO; + } + + // use default value 5 is the input is not reasonable. in unit of 10% + if ((tTxPerTrackingParam.ucTxPerTrackingRatio > TX_PER_TRACKING_MAX_RATIO) || (0 == tTxPerTrackingParam.ucTxPerTrackingRatio)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Ratio input is not good. use default 5"); + tTxPerTrackingParam.ucTxPerTrackingRatio = TX_PER_TRACKING_DEFAULT_RATIO; + } + + // default is 5 + if (0 == tTxPerTrackingParam.uTxPerTrackingWatermark) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx Packet number input is not good. use default 5"); + tTxPerTrackingParam.uTxPerTrackingWatermark = TX_PER_TRACKING_DEFAULT_WATERMARK; + } + + if (eHAL_STATUS_SUCCESS != + sme_SetTxPerTracking(pHddCtx->hHal, + hdd_tx_per_hit_cb, + (void*)pAdapter, &tTxPerTrackingParam)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Set Tx PER Tracking Failed!"); + rc = -EIO; + } + } + else { + hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", + __func__, cmd); + } +done: + /* many of the commands write information back into the command + string using snprintf(). check the return value here in one + place */ + if ((ret < 0) || (ret >= cmd_len)) + { + /* there was an encoding error or overflow */ + rc = -EINVAL; + } + else if (ret > 0) + { + if (copy_to_user(wrqu->data.pointer, cmd, ret)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + kfree(cmd); + return -EFAULT; + } + wrqu->data.length = ret; + } + + if (ioctl_debug) + { + pr_info("%s: rsp [%s] len [%d] status %d\n", + __func__, cmd, wrqu->data.length, rc); + } + kfree(cmd); + return rc; +} + +/** + * iw_set_priv() - SSR wrapper for __iw_set_priv() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_priv(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_priv(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_nick() - set nick + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int __iw_set_nick(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + return 0; +} + +/** + * iw_set_nick() - SSR wrapper for __iw_set_nick + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_nick(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_nick(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_nick() - get nick + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int __iw_get_nick(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + return 0; +} + +/** + * iw_get_nick() - SSR wrapper for __iw_get_nick + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: extra + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_nick(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_nick(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __get_wireless_stats() - get wireless stats + * @dev: pointer to net_device + * + * Return: %NULL + */ +static struct iw_statistics *__get_wireless_stats(struct net_device *dev) +{ + ENTER(); + return NULL; +} + +/** + * get_wireless_stats() - SSR wrapper for __get_wireless_stats + * @dev: pointer to net_device + * + * Return: pointer to iw_statistics + */ +static struct iw_statistics *get_wireless_stats(struct net_device *dev) +{ + struct iw_statistics *iw_stats; + + ENTER(); + vos_ssr_protect(__func__); + iw_stats = __get_wireless_stats(dev); + vos_ssr_unprotect(__func__); + + return iw_stats; +} + + +/** + * __iw_set_encode() - SIOCSIWENCODE ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_encode(struct net_device *dev,struct iw_request_info *info, + union iwreq_data *wrqu,char *extra) + +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + struct iw_point *encoderq = &(wrqu->encoding); + v_U32_t keyId; + v_U8_t key_length; + eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; + v_BOOL_t fKeyPresent = 0; + int i; + eHalStatus status = eHAL_STATUS_SUCCESS; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + keyId = encoderq->flags & IW_ENCODE_INDEX; + + if(keyId) + { + if(keyId > MAX_WEP_KEYS) + { + return -EINVAL; + } + + fKeyPresent = 1; + keyId--; + } + else + { + fKeyPresent = 0; + } + + + if(wrqu->data.flags & IW_ENCODE_DISABLED) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****iwconfig wlan0 key off*****"); + if(!fKeyPresent) { + + for(i=0;i < CSR_MAX_NUM_KEY; i++) { + + if(pWextState->roamProfile.Keys.KeyMaterial[i]) + pWextState->roamProfile.Keys.KeyLength[i] = 0; + } + } + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + pWextState->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + + pHddStaCtx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE; + pHddStaCtx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE; + + if(eConnectionState_Associated == pHddStaCtx->conn_info.connState) + { + INIT_COMPLETION(pAdapter->disconnect_comp_var); + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED ); + if(eHAL_STATUS_SUCCESS == status) + { + unsigned long rc; + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed wait on disconnect_comp_var")); + } + } + + return status; + + } + + if (wrqu->data.flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "iwconfig wlan0 key on"); + + pHddStaCtx->conn_info.authType = (encoderq->flags & IW_ENCODE_RESTRICTED) ? eCSR_AUTH_TYPE_SHARED_KEY : eCSR_AUTH_TYPE_OPEN_SYSTEM; + + } + + + if(wrqu->data.length > 0) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s : wrqu->data.length : %d",__func__,wrqu->data.length); + + key_length = wrqu->data.length; + + /* IW_ENCODING_TOKEN_MAX is the value that is set for wrqu->data.length by iwconfig.c when 'iwconfig wlan0 key on' is issued.*/ + + if(5 == key_length) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Call with WEP40,key_len=%d",__func__,key_length); + + if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) + { + encryptionType = eCSR_ENCRYPT_TYPE_WEP40; + } + else + { + encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + } + else if(13 == key_length) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s:Call with WEP104,key_len:%d",__func__,key_length); + + if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) + { + encryptionType = eCSR_ENCRYPT_TYPE_WEP104; + } + else + { + encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + } + } + else + { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Invalid WEP key length :%d", + __func__, key_length); + return -EINVAL; + } + + pHddStaCtx->conn_info.ucEncryptionType = encryptionType; + pHddStaCtx->conn_info.mcEncryptionType = encryptionType; + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType; + pWextState->roamProfile.mcEncryptionType.numEntries = 1; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType; + + if((eConnectionState_NotConnected == pHddStaCtx->conn_info.connState) && + ((eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) || + (eCSR_AUTH_TYPE_SHARED_KEY == pHddStaCtx->conn_info.authType))) + { + + vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[keyId][0],extra,key_length); + + pWextState->roamProfile.Keys.KeyLength[keyId] = (v_U8_t)key_length; + pWextState->roamProfile.Keys.defaultIndex = (v_U8_t)keyId; + + return status; + } + } + + return 0; +} + +/** + * iw_set_encode() - SSR wrapper for __iw_set_encode() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_encode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_encode(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_encodeext() - SIOCGIWENCODEEXT ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @dwrq: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); + int keyId; + eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; + eCsrAuthType authType = eCSR_AUTH_TYPE_NONE; + int i, ret; + hdd_context_t *hdd_ctx; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + keyId = pRoamProfile->Keys.defaultIndex; + + if(keyId < 0 || keyId >= MAX_WEP_KEYS) + { + hddLog(LOG1,"%s: Invalid keyId : %d", __func__, keyId); + return -EINVAL; + } + + if(pRoamProfile->Keys.KeyLength[keyId] > 0) + { + dwrq->flags |= IW_ENCODE_ENABLED; + dwrq->length = pRoamProfile->Keys.KeyLength[keyId]; + vos_mem_copy(extra, &(pRoamProfile->Keys.KeyMaterial[keyId][0]), + pRoamProfile->Keys.KeyLength[keyId]); + } + else + { + dwrq->flags |= IW_ENCODE_DISABLED; + } + + for(i=0; i < MAX_WEP_KEYS; i++) + { + if(pRoamProfile->Keys.KeyMaterial[i] == NULL) + { + continue; + } + else + { + break; + } + } + + if(MAX_WEP_KEYS == i) + { + dwrq->flags |= IW_ENCODE_NOKEY; + } + else + { + dwrq->flags |= IW_ENCODE_ENABLED; + } + + encryptionType = pRoamProfile->EncryptionType.encryptionType[0]; + + if(eCSR_ENCRYPT_TYPE_NONE == encryptionType) + { + dwrq->flags |= IW_ENCODE_DISABLED; + } + + authType = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; + + if(IW_AUTH_ALG_OPEN_SYSTEM == authType) + { + dwrq->flags |= IW_ENCODE_OPEN; + } + else + { + dwrq->flags |= IW_ENCODE_RESTRICTED; + } + EXIT(); + return 0; + +} + +/** + * iw_get_encodeext() - SSR wrapper for __iw_get_encodeext() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @dwrq: pointer to encoding information + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_encodeext(dev, info, dwrq, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_encodeext() - SIOCSIWENCODEEXT ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + eHalStatus halStatus= eHAL_STATUS_SUCCESS; + tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; + struct iw_encode_ext *ext = (struct iw_encode_ext*)extra; + v_U8_t groupmacaddr[VOS_MAC_ADDR_SIZE] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int key_index; + struct iw_point *encoding = &wrqu->encoding; + tCsrRoamSetKey setKey; + v_U32_t roamId= 0xFF; + VOS_STATUS vos_status; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + key_index = encoding->flags & IW_ENCODE_INDEX; + + if(key_index > 0) { + + /*Convert from 1-based to 0-based keying*/ + key_index--; + } + if(!ext->key_len) { + + /* Set the encryption type to NONE */ + pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + return ret; + } + + if(eConnectionState_NotConnected == pHddStaCtx->conn_info.connState && + (IW_ENCODE_ALG_WEP == ext->alg)) + { + if(IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) { + + VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("Invalid Configuration:%s"),__func__); + return -EINVAL; + } + else { + /*Static wep, update the roam profile with the keys */ + if(ext->key && (ext->key_len <= eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES) && + key_index < CSR_MAX_NUM_KEY) { + vos_mem_copy(&pRoamProfile->Keys.KeyMaterial[key_index][0],ext->key,ext->key_len); + pRoamProfile->Keys.KeyLength[key_index] = (v_U8_t)ext->key_len; + + if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + pRoamProfile->Keys.defaultIndex = (v_U8_t)key_index; + + } + } + return ret; + } + + vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); + + setKey.keyId = key_index; + setKey.keyLength = ext->key_len; + + if(ext->key_len <= CSR_MAX_KEY_LEN) { + vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len); + } + + if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /*Key direction for group is RX only*/ + setKey.keyDirection = eSIR_RX_ONLY; + vos_mem_copy(setKey.peerMac,groupmacaddr, VOS_MAC_ADDR_SIZE); + } + else { + + setKey.keyDirection = eSIR_TX_RX; + vos_mem_copy(setKey.peerMac,ext->addr.sa_data, VOS_MAC_ADDR_SIZE); + } + + /*For supplicant pae role is zero*/ + setKey.paeRole = 0; + + switch(ext->alg) + { + case IW_ENCODE_ALG_NONE: + setKey.encType = eCSR_ENCRYPT_TYPE_NONE; + break; + + case IW_ENCODE_ALG_WEP: + setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104; + break; + + case IW_ENCODE_ALG_TKIP: + { + v_U8_t *pKey = &setKey.Key[0]; + + setKey.encType = eCSR_ENCRYPT_TYPE_TKIP; + + vos_mem_zero(pKey, CSR_MAX_KEY_LEN); + + /*Supplicant sends the 32bytes key in this order + + |--------------|----------|----------| + | Tk1 |TX-MIC | RX Mic | + |--------------|----------|----------| + <---16bytes---><--8bytes--><--8bytes--> + + */ + /*Sme expects the 32 bytes key to be in the below order + + |--------------|----------|----------| + | Tk1 |RX-MIC | TX Mic | + |--------------|----------|----------| + <---16bytes---><--8bytes--><--8bytes--> + */ + /* Copy the Temporal Key 1 (TK1) */ + vos_mem_copy(pKey,ext->key,16); + + /*Copy the rx mic first*/ + vos_mem_copy(&pKey[16],&ext->key[24],8); + + /*Copy the tx mic */ + vos_mem_copy(&pKey[24],&ext->key[16],8); + + } + break; + + case IW_ENCODE_ALG_CCMP: + setKey.encType = eCSR_ENCRYPT_TYPE_AES; + break; + +#ifdef FEATURE_WLAN_ESE +#define IW_ENCODE_ALG_KRK 6 + case IW_ENCODE_ALG_KRK: + setKey.encType = eCSR_ENCRYPT_TYPE_KRK; + break; +#endif /* FEATURE_WLAN_ESE */ + + default: + setKey.encType = eCSR_ENCRYPT_TYPE_NONE; + break; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d"),__func__,(int)ext->alg,(int)ext->key_len,setKey.encType); + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* The supplicant may attempt to set the PTK once pre-authentication + is done. Save the key in the UMAC and include it in the ADD + BSS request */ + halStatus = sme_FTUpdateKey(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey); + if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } + else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); + return -EINVAL; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + + vos_status = wlan_hdd_check_ula_done(pAdapter); + if ( vos_status != VOS_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d", + __LINE__, vos_status ); + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + + halStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),pAdapter->sessionId, &setKey, &roamId ); + + if ( halStatus != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "[%4d] sme_RoamSetKey returned ERROR status= %d", + __LINE__, halStatus ); + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + + return halStatus; +} + +/** + * iw_set_encodeext() - SSR wrapper for __iw_set_encodeext() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_encodeext(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_retry() - SIOCSIWRETRY ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_retry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if(wrqu->retry.value < WNI_CFG_LONG_RETRY_LIMIT_STAMIN || + wrqu->retry.value > WNI_CFG_LONG_RETRY_LIMIT_STAMAX) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Invalid Retry-Limit=%d!!"),wrqu->retry.value); + + return -EINVAL; + } + + if(wrqu->retry.flags & IW_RETRY_LIMIT) { + + if((wrqu->retry.flags & IW_RETRY_LONG)) + { + if ( ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, wrqu->retry.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_LONG_RETRY_LIMIT")); + return -EIO; + } + } + else if((wrqu->retry.flags & IW_RETRY_SHORT)) + { + if ( ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, wrqu->retry.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_LONG_RETRY_LIMIT")); + return -EIO; + } + } + } + else + { + return -EOPNOTSUPP; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Set Retry-Limit=%d!!"),wrqu->retry.value); + + EXIT(); + + return 0; + +} + +/** + * iw_set_retry() - SSR wrapper for __iw_set_retry() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_retry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_retry(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_retry() - SIOCGIWRETRY ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_get_retry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U32_t retry = 0; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if((wrqu->retry.flags & IW_RETRY_LONG)) + { + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG; + + if ( ccmCfgGetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_LONG_RETRY_LIMIT")); + return -EIO; + } + + wrqu->retry.value = retry; + } + else if ((wrqu->retry.flags & IW_RETRY_SHORT)) + { + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; + + if ( ccmCfgGetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_LONG_RETRY_LIMIT")); + return -EIO; + } + + wrqu->retry.value = retry; + } + else { + return -EOPNOTSUPP; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Retry-Limit=%d!!"),retry); + + EXIT(); + + return 0; +} + +/** + * iw_get_retry() - SSR wrapper for __iw_get_retry() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_get_retry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_retry(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_mlme() - SIOCSIWMLME ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_mlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + eHalStatus status = eHAL_STATUS_SUCCESS; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + //reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED + switch (mlme->cmd) { + case IW_MLME_DISASSOC: + case IW_MLME_DEAUTH: + + if( pHddStaCtx->conn_info.connState == eConnectionState_Associated ) + { + eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED; + + if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE ) + reason = eCSR_DISCONNECT_REASON_MIC_ERROR; + + INIT_COMPLETION(pAdapter->disconnect_comp_var); + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,reason); + + if(eHAL_STATUS_SUCCESS == status) + { + unsigned long rc; + rc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed wait on disconnect_comp_var")); + } + else + hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d", + __func__, (int)mlme->cmd, (int)status ); + + /* Resetting authKeyMgmt */ + (WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->authKeyMgmt = 0; + + hddLog(LOG1, FL("Disabling queues")); + netif_tx_disable(dev); + netif_carrier_off(dev); + pAdapter->hdd_stats.hddTxRxStats.netq_disable_cnt++; + pAdapter->hdd_stats.hddTxRxStats.netq_state_off = TRUE; + + } + else + { + hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state", __func__, (int)mlme->cmd ); + } + break; + default: + hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate", __func__, (int)mlme->cmd ); + return -EINVAL; + }//end of switch + + EXIT(); + + return status; + +} + +/** + * iw_set_mlme() - SSR wrapper for __iw_set_mlme() + * @dev: pointer to net_device + * @info: pointer to iw_request_info + * @wrqu: pointer to iwreq_data + * @extra: pointer to extra ioctl payload + * + * Return: 0 on success, error number otherwise + */ +static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_mlme(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +int process_wma_set_command(int sessid, int paramid, + int sval, int vpdev) +{ + int ret = 0; + vos_msg_t msg = {0}; + + wda_cli_set_cmd_t *iwcmd = (wda_cli_set_cmd_t *)vos_mem_malloc( + sizeof(wda_cli_set_cmd_t)); + if (NULL == iwcmd) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + vos_mem_zero((void *)iwcmd, sizeof(wda_cli_set_cmd_t)); + iwcmd->param_value = sval; + iwcmd->param_vdev_id = sessid; + iwcmd->param_id = paramid; + iwcmd->param_vp_dev = vpdev; + msg.type = WDA_CLI_SET_CMD; + msg.reserved = 0; + msg.bodyptr = (void *)iwcmd; + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, + &msg)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " + "Not able to post wda_cli_set_cmd message to WDA", + __func__); + vos_mem_free(iwcmd); + ret = -EIO; + } + return ret; +} + +int process_wma_set_command_twoargs(int sessid, int paramid, + int sval, int ssecval, int vpdev) +{ + int ret = 0; + vos_msg_t msg = {0}; + wda_cli_set_cmd_t *iwcmd = vos_mem_malloc(sizeof(*iwcmd)); + + if (NULL == iwcmd) { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_mem_alloc failed!", __func__); + ret = -EINVAL; + goto out; + } + + vos_mem_zero(iwcmd, sizeof(*iwcmd)); + iwcmd->param_value = sval; + iwcmd->param_sec_value = ssecval; + iwcmd->param_vdev_id = sessid; + iwcmd->param_id = paramid; + iwcmd->param_vp_dev = vpdev; + msg.type = WDA_CLI_SET_CMD; + msg.reserved = 0; + msg.bodyptr = iwcmd; + + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " + "Not able to post wda_cli_set_cmd message to WDA", __func__); + vos_mem_free(iwcmd); + ret = -EIO; + } + +out: + return ret; +} + +int wlan_hdd_update_phymode(struct net_device *net, tHalHandle hal, + int new_phymode, + hdd_context_t *phddctx) +{ +#ifdef QCA_HT_2040_COEX + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(net); + eHalStatus halStatus = eHAL_STATUS_FAILURE; +#endif + v_BOOL_t band_24 = VOS_FALSE, band_5g = VOS_FALSE; + v_BOOL_t ch_bond24 = VOS_FALSE, ch_bond5g = VOS_FALSE; + tSmeConfigParams smeconfig; + tANI_U32 chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; +#ifdef WLAN_FEATURE_11AC + tANI_U32 vhtchanwidth; +#endif + eCsrPhyMode phymode = -EIO, old_phymode; + eHddDot11Mode hdd_dot11mode = phddctx->cfg_ini->dot11Mode; + eCsrBand curr_band = eCSR_BAND_ALL; + + old_phymode = sme_GetPhyMode(hal); + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + sme_GetCBPhyStateFromCBIniValue( + phddctx->cfg_ini->nChannelBondingMode24GHz)) + ch_bond24 = VOS_TRUE; + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + sme_GetCBPhyStateFromCBIniValue( + phddctx->cfg_ini->nChannelBondingMode5GHz)) + ch_bond5g = VOS_TRUE; + + if (phddctx->cfg_ini->nBandCapability == eCSR_BAND_ALL) { + band_24 = band_5g = VOS_TRUE; + } else if (phddctx->cfg_ini->nBandCapability == eCSR_BAND_24) { + band_24 = VOS_TRUE; + } else if (phddctx->cfg_ini->nBandCapability == eCSR_BAND_5G) { + band_5g = VOS_TRUE; + } + + vhtchanwidth = phddctx->cfg_ini->vhtChannelWidth; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, ("ch_bond24=%d " + "ch_bond5g=%d band_24=%d band_5g=%d VHT_ch_width=%u"), ch_bond24, + ch_bond5g, band_24, band_5g, vhtchanwidth); + + switch (new_phymode) { + case IEEE80211_MODE_AUTO: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_AUTO); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_AUTO) == 0)) { + phymode = eCSR_DOT11_MODE_AUTO; + hdd_dot11mode = eHDD_DOT11_MODE_AUTO; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + curr_band = eCSR_BAND_ALL; + vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11A: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11a); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_5_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11a; + hdd_dot11mode = eHDD_DOT11_MODE_11a; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + curr_band = eCSR_BAND_5G; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11B: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11b); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11b; + hdd_dot11mode = eHDD_DOT11_MODE_11b; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + curr_band = eCSR_BAND_24; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11G: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11g); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11g; + hdd_dot11mode = eHDD_DOT11_MODE_11g; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + curr_band = eCSR_BAND_24; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + /* + * UMAC doesn't have option to set MODE_11NA/MODE_11NG as phymode + * so setting phymode as eCSR_DOT11_MODE_11n and updating the band + * and channel bonding in configuration to reflect MODE_11NA/MODE_11NG + */ + case IEEE80211_MODE_11NA_HT20: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_5_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11n; + hdd_dot11mode = eHDD_DOT11_MODE_11n; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + curr_band = eCSR_BAND_5G; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11NA_HT40: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_5_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11n; + hdd_dot11mode = eHDD_DOT11_MODE_11n; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + curr_band = eCSR_BAND_5G; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11NG_HT20: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11n; + hdd_dot11mode = eHDD_DOT11_MODE_11n; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + curr_band = eCSR_BAND_24; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11NG_HT40: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11n; + hdd_dot11mode = eHDD_DOT11_MODE_11n; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + curr_band = eCSR_BAND_24; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; +#ifdef WLAN_FEATURE_11AC + case IEEE80211_MODE_11AC_VHT20: + case IEEE80211_MODE_11AC_VHT40: + case IEEE80211_MODE_11AC_VHT80: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11ac); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_5_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_11ac; + hdd_dot11mode = eHDD_DOT11_MODE_11ac; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + curr_band = eCSR_BAND_5G; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; +#endif + case IEEE80211_MODE_2G_AUTO: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_AUTO); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_AUTO; + hdd_dot11mode = eHDD_DOT11_MODE_AUTO; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + curr_band = eCSR_BAND_24; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_5G_AUTO: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_AUTO); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_5_GHZ) == 0)) { + phymode = eCSR_DOT11_MODE_AUTO; + hdd_dot11mode = eHDD_DOT11_MODE_AUTO; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ; + curr_band = eCSR_BAND_5G; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11AGN: + sme_SetPhyMode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_setBand(net, WLAN_HDD_UI_BAND_AUTO) == 0)) { + phymode = eCSR_DOT11_MODE_11n; + hdd_dot11mode = eHDD_DOT11_MODE_11n; + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + curr_band = eCSR_BAND_ALL; + } else { + sme_SetPhyMode(hal, old_phymode); + return -EIO; + } + break; + default: + return -EIO; + } + +#ifdef WLAN_FEATURE_11AC + switch (new_phymode) { + case IEEE80211_MODE_11AC_VHT20: + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + vhtchanwidth = eHT_CHANNEL_WIDTH_20MHZ; + break; + case IEEE80211_MODE_11AC_VHT40: + vhtchanwidth = eHT_CHANNEL_WIDTH_40MHZ; + break; + case IEEE80211_MODE_11AC_VHT80: + vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ; + break; + default: + vhtchanwidth = phddctx->cfg_ini->vhtChannelWidth; + break; + } +#endif + + if (phymode != -EIO) { + sme_GetConfigParam(hal, &smeconfig); + + smeconfig.csrConfig.phyMode = phymode; +#ifdef QCA_HT_2040_COEX + if (phymode == eCSR_DOT11_MODE_11n && + chwidth == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) { + smeconfig.csrConfig.obssEnabled = eANI_BOOLEAN_FALSE; + halStatus = sme_SetHT2040Mode(hal, pAdapter->sessionId, + eHT_CHAN_HT20, eANI_BOOLEAN_FALSE); + if (halStatus == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Failed to disable OBSS")); + return -EIO; + } + } else if (phymode == eCSR_DOT11_MODE_11n && + chwidth == WNI_CFG_CHANNEL_BONDING_MODE_ENABLE) { + smeconfig.csrConfig.obssEnabled = eANI_BOOLEAN_TRUE; + halStatus = sme_SetHT2040Mode(hal, pAdapter->sessionId, + eHT_CHAN_HT20, eANI_BOOLEAN_TRUE); + if (halStatus == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Failed to enable OBSS")); + return -EIO; + } + } +#endif + smeconfig.csrConfig.eBand = curr_band; + smeconfig.csrConfig.bandCapability = curr_band; + if (curr_band == eCSR_BAND_24) + smeconfig.csrConfig.Is11hSupportEnabled = 0; + else + smeconfig.csrConfig.Is11hSupportEnabled = + phddctx->cfg_ini->Is11hSupportEnabled; + if (curr_band == eCSR_BAND_24) + smeconfig.csrConfig.channelBondingMode24GHz = chwidth; + else if (curr_band == eCSR_BAND_24) + smeconfig.csrConfig.channelBondingMode5GHz = chwidth; + else { + smeconfig.csrConfig.channelBondingMode24GHz = chwidth; + smeconfig.csrConfig.channelBondingMode5GHz = chwidth; + } + +#ifdef WLAN_FEATURE_11AC + smeconfig.csrConfig.nVhtChannelWidth = vhtchanwidth; +#endif + sme_UpdateConfig(hal, &smeconfig); + phddctx->cfg_ini->dot11Mode = hdd_dot11mode; + phddctx->cfg_ini->nBandCapability = curr_band; + phddctx->cfg_ini->nChannelBondingMode24GHz = + smeconfig.csrConfig.channelBondingMode24GHz; + phddctx->cfg_ini->nChannelBondingMode5GHz = + smeconfig.csrConfig.channelBondingMode5GHz; + phddctx->cfg_ini->vhtChannelWidth = vhtchanwidth; + if (hdd_update_config_dat(phddctx) == VOS_FALSE) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not update config_dat", __func__ ); + return -EIO; + } + + if (phddctx->cfg_ini->nChannelBondingMode5GHz) + phddctx->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.cap |= + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + else + phddctx->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, ("New_Phymode= %d " + "ch_bonding=%d band=%d VHT_ch_width=%u"), + phymode, chwidth, curr_band, vhtchanwidth); + + } + + return 0; +} + +void hdd_GetTemperatureCB(int temperature, void *pContext) +{ + struct statsContext *pTempContext; + hdd_adapter_t *pAdapter; + + ENTER(); + + if (NULL == pContext) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("pContext is NULL")); + return; + } + + pTempContext = pContext; + pAdapter = pTempContext->pAdapter; + + /* there is a race condition that exists between this callback + function and the caller since the caller could time out either + before or while this code is executing. we use a spinlock to + serialize these actions */ + spin_lock(&hdd_context_lock); + + if ((NULL == pAdapter) || + (TEMP_CONTEXT_MAGIC != pTempContext->magic)) + { + /* the caller presumably timed out so there is nothing we can do */ + spin_unlock(&hdd_context_lock); + hddLog(VOS_TRACE_LEVEL_WARN, + FL("Invalid context, pAdapter [%p] magic [%08x]"), + pAdapter, pTempContext->magic); + return; + } + + /* context is valid, update the temperature, ignore it if this was 0 */ + if (temperature != 0) { + pAdapter->temperature = temperature; + } + + /* notify the caller */ + complete(&pTempContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); + + EXIT(); +} + +VOS_STATUS wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu, char *extra) +{ + eHalStatus hstatus; + struct statsContext tempContext; + unsigned long rc; + A_INT32 *pData = (A_INT32 *)extra; + + ENTER(); + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("pAdapter is NULL")); + return VOS_STATUS_E_FAULT; + } + + /* prepare callback context and magic pattern */ + init_completion(&tempContext.completion); + tempContext.pAdapter = pAdapter; + tempContext.magic = TEMP_CONTEXT_MAGIC; + + /* send get temperature request to sme */ + hstatus = sme_GetTemperature( + WLAN_HDD_GET_HAL_CTX(pAdapter), + &tempContext, + hdd_GetTemperatureCB); + + if (eHAL_STATUS_SUCCESS != hstatus) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve temperature")); + } else { + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&tempContext.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while retrieving temperature")); + } + } + + /* either we never sent a request, we sent a request and received a + response or we sent a request and timed out. if we never sent a + request or if we sent a request and got a response, we want to + clear the magic out of paranoia. if we timed out there is a + race condition such that the callback function could be + executing at the same time we are. of primary concern is if the + callback function had already verified the "magic" but had not + yet set the completion variable when a timeout occurred. we + serialize these activities by invalidating the magic while + holding a shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + tempContext.magic = 0; + spin_unlock(&hdd_context_lock); + + /* update temperature */ + *pData = pAdapter->temperature; + + EXIT(); + return VOS_STATUS_SUCCESS; +} + +/* set param sub-ioctls */ +static int __iw_setint_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tSmeConfigParams smeConfig; + int *value = (int *)extra; + int sub_cmd = value[0]; + int set_value = value[1]; + int ret; + int enable_pbm, enable_mp; + eHalStatus status; + +#ifdef CONFIG_HAS_EARLYSUSPEND + v_U8_t nEnableSuspendOld; +#endif + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + INIT_COMPLETION(pWextState->completion_var); + memset(&smeConfig, 0x00, sizeof(smeConfig)); + + + switch(sub_cmd) + { + case WE_SET_11D_STATE: + { + if((ENABLE_11D == set_value) || (DISABLE_11D == set_value)) { + + sme_GetConfigParam(hHal, &smeConfig); + smeConfig.csrConfig.Is11dSupportEnabled = (v_BOOL_t)set_value; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("11D state=%d!!"), + smeConfig.csrConfig.Is11dSupportEnabled); + + sme_UpdateConfig(hHal, &smeConfig); + } + else { + return -EINVAL; + } + break; + } + + case WE_WOWL: + { + switch (set_value) + { + case 0x00: + hdd_exit_wowl(pAdapter); + break; + case 0x01: + case 0x02: + case 0x03: + enable_mp = (set_value & 0x01) ? 1 : 0; + enable_pbm = (set_value & 0x02) ? 1 : 0; + hddLog(LOGE, "magic packet ? = %s pattern byte matching ? = %s", + (enable_mp ? "YES":"NO"), (enable_pbm ? "YES":"NO")); + hdd_enter_wowl(pAdapter, enable_mp, enable_pbm); + break; + default: + hddLog(LOGE, "Invalid arg %d in WE_WOWL IOCTL", set_value); + ret = -EINVAL; + break; + } + + break; + } + case WE_SET_POWER: + { + switch (set_value) + { + case 0: //Full Power + { + struct statsContext context; + eHalStatus status; + + init_completion(&context.completion); + + context.pAdapter = pAdapter; + context.magic = POWER_CONTEXT_MAGIC; + + status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter), + iw_power_callback_fn, &context, + eSME_FULL_PWR_NEEDED_BY_HDD); + if (eHAL_STATUS_PMC_PENDING == status) + { + unsigned long rc; + rc = wait_for_completion_timeout( + &context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); + + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while requesting full power")); + } + } + /* either we have a response or we timed out. if we timed + out there is a race condition such that the callback + function could be executing at the same time we are. of + primary concern is if the callback function had already + verified the "magic" but had not yet set the completion + variable when a timeout occurred. we serialize these + activities by invalidating the magic while holding a + shared spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + hddLog(LOGE, "iwpriv Full Power completed"); + break; + } + case 1: //Enable BMPS + sme_EnablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE); + break; + case 2: //Disable BMPS + sme_DisablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE); + break; + case 3: //Request Bmps + { + struct statsContext context; + eHalStatus status; + + init_completion(&context.completion); + + context.pAdapter = pAdapter; + context.magic = POWER_CONTEXT_MAGIC; + + status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter), + iw_power_callback_fn, &context); + if (eHAL_STATUS_PMC_PENDING == status) + { + unsigned long rc; + rc = wait_for_completion_timeout( + &context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_POWER)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("SME timed out while requesting BMPS")); + } + } + /* either we have a response or we timed out. if we + timed out there is a race condition such that the + callback function could be executing at the same + time we are. of primary concern is if the callback + function had already verified the "magic" but had + not yet set the completion variable when a timeout + occurred. we serialize these activities by + invalidating the magic while holding a shared + spinlock which will cause us to block if the + callback is currently executing */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + + hddLog(LOGE, "iwpriv Request BMPS completed"); + break; + } + case 4: //Enable IMPS + sme_EnablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE); + break; + case 5: //Disable IMPS + sme_DisablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE); + break; + case 6: //Enable Standby + sme_EnablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE); + break; + case 7: //Disable Standby + sme_DisablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE); + break; + case 8: //Request Standby +#ifdef CONFIG_HAS_EARLYSUSPEND +#endif + break; + case 9: //Start Auto Bmps Timer + sme_StartAutoBmpsTimer(hHal); + break; + case 10://Stop Auto BMPS Timer + sme_StopAutoBmpsTimer(hHal); + break; +#ifdef CONFIG_HAS_EARLYSUSPEND + case 11://suspend to standby +#ifdef CONFIG_HAS_EARLYSUSPEND + nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend; + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 1; + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld; +#endif + break; + case 12://suspend to deep sleep +#ifdef CONFIG_HAS_EARLYSUSPEND + nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend; + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 2; + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld; +#endif + break; + case 13://resume from suspend +#ifdef CONFIG_HAS_EARLYSUSPEND +#endif + break; +#endif + case 14://reset wlan (power down/power up) + break; + default: + hddLog(LOGE, "Invalid arg %d in WE_SET_POWER IOCTL", set_value); + ret = -EINVAL; + break; + } + break; + } + + case WE_SET_MAX_ASSOC: + { + if ((WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) || + (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value)) + { + ret = -EINVAL; + } + else if ( ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, + set_value, NULL, eANI_BOOLEAN_FALSE) + != eHAL_STATUS_SUCCESS ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_ASSOC_STA_LIMIT")); + ret = -EIO; + } + break; + } + + case WE_SET_SAP_AUTO_CHANNEL_SELECTION: + if (set_value == 0 || set_value == 1) + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->force_sap_acs = + set_value; + else + ret = -EINVAL; + break; + + case WE_SET_DATA_INACTIVITY_TO: + { + if ((set_value < CFG_DATA_INACTIVITY_TIMEOUT_MIN) || + (set_value > CFG_DATA_INACTIVITY_TIMEOUT_MAX) || + (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal, + WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + set_value, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)) + { + hddLog(LOGE,"Failure: Could not pass on " + "WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT configuration info " + "to CCM"); + ret = -EINVAL; + } + break; + } + case WE_SET_MC_RATE: + { + ret = wlan_hdd_set_mc_rate(pAdapter, set_value); + break; + } + case WE_SET_TX_POWER: + { + tSirMacAddr bssid; + + vos_mem_copy(bssid, pHddStaCtx->conn_info.bssId, VOS_MAC_ADDR_SIZE); + if ( sme_SetTxPower(hHal, pAdapter->sessionId, bssid, + pAdapter->device_mode, set_value) != + eHAL_STATUS_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting tx power failed", + __func__); + return -EIO; + } + break; + } + case WE_SET_MAX_TX_POWER: + { + tSirMacAddr bssid; + tSirMacAddr selfMac; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm", + __func__, set_value); + vos_mem_copy(bssid, pHddStaCtx->conn_info.bssId, + VOS_MAC_ADDR_SIZE); + vos_mem_copy(selfMac, pHddStaCtx->conn_info.bssId, + VOS_MAC_ADDR_SIZE); + + if( sme_SetMaxTxPower(hHal, bssid, selfMac, set_value) != + eHAL_STATUS_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", + __func__); + return -EIO; + } + + break; + } + case WE_SET_MAX_TX_POWER_2_4: + { + 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) != + eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Setting maximum tx power failed for 2.4 GHz band", + __func__); + return -EIO; + } + + break; + } + case WE_SET_MAX_TX_POWER_5_0: + { + 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) != + eHAL_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Setting maximum tx power failed for 5.0 GHz band", + __func__); + return -EIO; + } + + break; + } + case WE_SET_HIGHER_DTIM_TRANSITION: + { + if(!((set_value == eANI_BOOLEAN_FALSE) || + (set_value == eANI_BOOLEAN_TRUE))) + { + hddLog(LOGE, "Dynamic DTIM Incorrect data:%d", set_value); + ret = -EINVAL; + } + else + { + if(pAdapter->higherDtimTransition != set_value) + { + pAdapter->higherDtimTransition = set_value; + hddLog(LOG1, "%s: higherDtimTransition set to :%d", __func__, pAdapter->higherDtimTransition); + } + } + + break; + } + + case WE_SET_TM_LEVEL: + { + hddLog(VOS_TRACE_LEVEL_INFO, "Set Thermal Mitigation Level %d", + set_value); + (void)sme_SetThermalLevel(hHal, set_value); + break; + } + + case WE_SET_PHYMODE: + { + hdd_context_t *phddctx = WLAN_HDD_GET_CTX(pAdapter); + + ret = wlan_hdd_update_phymode(dev, hHal, set_value, phddctx); + break; + } + + case WE_SET_NSS: + { + hddLog(LOG1, "Set NSS = %d", set_value); + if ((set_value > 2) || (set_value <= 0)) { + hddLog(LOGE, "NSS greater than 2 not supported"); + ret = -EINVAL; + } else { + if (VOS_STATUS_SUCCESS != + hdd_update_nss(WLAN_HDD_GET_CTX(pAdapter), set_value)) + ret = -EINVAL; + } + break; + } + + case WE_SET_GTX_HT_MCS: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_HT_MCS %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_HT_MCS, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_VHT_MCS: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_VHT_MCS %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_VHT_MCS, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_USRCFG: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_USR_CFG %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_USR_CFG, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_THRE: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_THRE %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_THRE, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_MARGIN: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_MARGIN %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MARGIN, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_STEP: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_STEP %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_STEP, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_MINTPC: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_MINTPC %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MINTPC, + set_value, GTX_CMD); + break; + } + + case WE_SET_GTX_BWMASK: + { + hddLog(LOG1, "WMI_VDEV_PARAM_GTX_BWMASK %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_BW_MASK, + set_value, GTX_CMD); + break; + } + + case WE_SET_LDPC: + ret = hdd_set_ldpc(pAdapter, set_value); + break; + + case WE_SET_TX_STBC: + ret = hdd_set_tx_stbc(pAdapter, set_value); + break; + + case WE_SET_RX_STBC: + ret = hdd_set_rx_stbc(pAdapter, set_value); + break; + + case WE_SET_SHORT_GI: + { + hddLog(LOG1, "WMI_VDEV_PARAM_SGI val %d", set_value); + ret = sme_UpdateHTConfig(hHal, pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ, + set_value); + if (ret) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to set ShortGI value"); + break; + } + + case WE_SET_RTSCTS: + { + u_int32_t value; + + hddLog(LOG1, "WMI_VDEV_PARAM_ENABLE_RTSCTS val 0x%x", set_value); + + if ((set_value & HDD_RTSCTS_EN_MASK) == HDD_RTSCTS_ENABLE) + value = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->RTSThreshold; + else if (((set_value & HDD_RTSCTS_EN_MASK) == 0) || + ((set_value & HDD_RTSCTS_EN_MASK) == HDD_CTS_ENABLE)) + value = WNI_CFG_RTS_THRESHOLD_STAMAX; + else + return -EIO; + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, + set_value, VDEV_CMD); + if (!ret) { + if (ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, value, + ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != + eHAL_STATUS_SUCCESS) { + hddLog(LOGE, "FAILED TO SET RTSCTS"); + return -EIO; + } + } + + break; + } + + case WE_SET_CHWIDTH: + { + bool chwidth = false; + hdd_context_t *phddctx = WLAN_HDD_GET_CTX(pAdapter); + /*updating channel bonding only on 5Ghz*/ + hddLog(LOG1, "WMI_VDEV_PARAM_CHWIDTH val %d", set_value); + if (set_value > eHT_CHANNEL_WIDTH_80MHZ) { + hddLog(LOGE, "Invalid channel width 0->20 1->40 2->80"); + return -EINVAL; + } + + if ((WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + csrConvertCBIniValueToPhyCBState( + phddctx->cfg_ini->nChannelBondingMode5GHz))) + chwidth = true; + + sme_GetConfigParam(hHal, &smeConfig); + switch (set_value) { + case eHT_CHANNEL_WIDTH_20MHZ: + smeConfig.csrConfig.channelBondingMode5GHz = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + break; + case eHT_CHANNEL_WIDTH_40MHZ: + if (chwidth) + smeConfig.csrConfig.channelBondingMode5GHz = + phddctx->cfg_ini->nChannelBondingMode5GHz; + else + return -EINVAL; + + break; +#ifdef WLAN_FEATURE_11AC + case eHT_CHANNEL_WIDTH_80MHZ: + if (chwidth) + smeConfig.csrConfig.channelBondingMode5GHz = + phddctx->cfg_ini->nChannelBondingMode5GHz; + else + return -EINVAL; + + break; +#endif + + default: + return -EINVAL; + } + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_CHWIDTH, + set_value, VDEV_CMD); + if (!ret) + sme_UpdateConfig(hHal, &smeConfig); + + break; + } + + case WE_SET_ANI_EN_DIS: + { + hddLog(LOG1, "WMI_PDEV_PARAM_ANI_ENABLE val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_ENABLE, + set_value, PDEV_CMD); + break; + } + + case WE_SET_ANI_POLL_PERIOD: + { + hddLog(LOG1, "WMI_PDEV_PARAM_ANI_POLL_PERIOD val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_POLL_PERIOD, + set_value, PDEV_CMD); + break; + } + + case WE_SET_ANI_LISTEN_PERIOD: + { + hddLog(LOG1, "WMI_PDEV_PARAM_ANI_LISTEN_PERIOD val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, + set_value, PDEV_CMD); + break; + } + + case WE_SET_ANI_OFDM_LEVEL: + { + hddLog(LOG1, "WMI_PDEV_PARAM_ANI_OFDM_LEVEL val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_OFDM_LEVEL, + set_value, PDEV_CMD); + break; + } + + case WE_SET_ANI_CCK_LEVEL: + { + hddLog(LOG1, "WMI_PDEV_PARAM_ANI_CCK_LEVEL val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_CCK_LEVEL, + set_value, PDEV_CMD); + break; + } + + case WE_SET_DYNAMIC_BW: + { + hddLog(LOG1, "WMI_PDEV_PARAM_DYNAMIC_BW val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_DYNAMIC_BW, + set_value, PDEV_CMD); + break; + } + + case WE_SET_CTS_CBW: + { + hddLog(LOG1, "WE_SET_CTS_CBW val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_CTS_CBW, + set_value, PDEV_CMD); + break; + } + + case WE_SET_11N_RATE: + { + u_int8_t preamble = 0, nss = 0, rix = 0; + hddLog(LOG1, "WMI_VDEV_PARAM_FIXED_RATE val %d", set_value); + + if (set_value != 0xff) { + rix = RC_2_RATE_IDX(set_value); + if (set_value & 0x80) { + preamble = WMI_RATE_PREAMBLE_HT; + nss = HT_RC_2_STREAMS(set_value) -1; + } else { + nss = 0; + rix = RC_2_RATE_IDX(set_value); + if (set_value & 0x10) { + preamble = WMI_RATE_PREAMBLE_CCK; + /* Enable Short preamble always for CCK except 1mbps */ + if(rix != 0x3) + rix |= 0x4; + } else + preamble = WMI_RATE_PREAMBLE_OFDM; + } + set_value = (preamble << 6) | (nss << 4) | rix; + } + hddLog(LOG1, + "WMI_VDEV_PARAM_FIXED_RATE val %d rix %d preamble %x nss %d", + set_value, rix, preamble, nss); + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case WE_SET_VHT_RATE: + { + u_int8_t preamble = 0, nss = 0, rix = 0; + + if (set_value != 0xff) { + rix = RC_2_RATE_IDX_11AC(set_value); + preamble = WMI_RATE_PREAMBLE_VHT; + nss = HT_RC_2_STREAMS_11AC(set_value) -1; + + set_value = (preamble << 6) | (nss << 4) | rix; + } + hddLog(LOG1, + "WMI_VDEV_PARAM_FIXED_RATE val %d rix %d preamble %x nss %d", + set_value, rix, preamble, nss); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case WE_SET_AMPDU: + { + hddLog(LOG1, "SET AMPDU val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMPDU, + set_value, GEN_CMD); + break; + } + + case WE_SET_AMSDU: + { + hddLog(LOG1, "SET AMSDU val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMSDU, + set_value, GEN_CMD); + if (!ret) { + /* Update the stored ini value */ + pHddCtx->cfg_ini->max_amsdu_num = set_value; + } + break; + } + + case WE_SET_BURST_ENABLE: + { + hddLog(LOG1, "SET Burst enable val %d", set_value); + if ((set_value == 0) || (set_value == 1)) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + set_value, PDEV_CMD); + } + else + ret = -EINVAL; + break; + } + case WE_SET_BURST_DUR: + { + hddLog(LOG1, "SET Burst duration val %d", set_value); + if ((set_value > 0) && (set_value <= 8192)) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_DUR, + set_value, PDEV_CMD); + } + else + ret = -EINVAL; + break; + } + + case WE_SET_TX_CHAINMASK: + { + hddLog(LOG1, "WMI_PDEV_PARAM_TX_CHAIN_MASK val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, + set_value, PDEV_CMD); + break; + } + + case WE_SET_RX_CHAINMASK: + { + hddLog(LOG1, "WMI_PDEV_PARAM_RX_CHAIN_MASK val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, + set_value, PDEV_CMD); + break; + } + + case WE_SET_TXPOW_2G: + { + hddLog(LOG1, "WMI_PDEV_PARAM_TXPOWER_LIMIT2G val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TXPOWER_LIMIT2G, + set_value, PDEV_CMD); + break; + } + + case WE_SET_TXPOW_5G: + { + hddLog(LOG1, "WMI_PDEV_PARAM_TXPOWER_LIMIT5G val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TXPOWER_LIMIT5G, + set_value, PDEV_CMD); + break; + } + + /* Firmware debug log */ + case WE_DBGLOG_LOG_LEVEL: + { + hddLog(LOG1, "WE_DBGLOG_LOG_LEVEL val %d", set_value); + pHddCtx->fw_log_settings.dl_loglevel = set_value; + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_LOG_LEVEL, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_VAP_ENABLE: + { + hddLog(LOG1, "WE_DBGLOG_VAP_ENABLE val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_VAP_ENABLE, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_VAP_DISABLE: + { + hddLog(LOG1, "WE_DBGLOG_VAP_DISABLE val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_VAP_DISABLE, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_MODULE_ENABLE: + { + hddLog(LOG1, "WE_DBGLOG_MODULE_ENABLE val %d", set_value); + pHddCtx->fw_log_settings.enable = set_value; + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_MODULE_ENABLE, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_MODULE_DISABLE: + { + hddLog(LOG1, "WE_DBGLOG_MODULE_DISABLE val %d", set_value); + pHddCtx->fw_log_settings.enable = set_value; + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_MODULE_DISABLE, + set_value, DBG_CMD); + break; + } + case WE_DBGLOG_MOD_LOG_LEVEL: + { + hddLog(LOG1, "WE_DBGLOG_MOD_LOG_LEVEL val %d", set_value); + + if (pHddCtx->fw_log_settings.index >= MAX_MOD_LOGLEVEL) { + pHddCtx->fw_log_settings.index = 0; + } + + pHddCtx->fw_log_settings.dl_mod_loglevel[pHddCtx-> + fw_log_settings.index] = set_value; + pHddCtx->fw_log_settings.index++; + + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_MOD_LOG_LEVEL, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_TYPE: + { + hddLog(LOG1, "WE_DBGLOG_TYPE val %d", set_value); + pHddCtx->fw_log_settings.dl_type = set_value; + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_TYPE, + set_value, DBG_CMD); + break; + } + case WE_DBGLOG_REPORT_ENABLE: + { + hddLog(LOG1, "WE_DBGLOG_REPORT_ENABLE val %d", set_value); + pHddCtx->fw_log_settings.dl_report = set_value; + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_DBGLOG_REPORT_ENABLE, + set_value, DBG_CMD); + break; + } + + case WE_SET_TXRX_FWSTATS: + { + hddLog(LOG1, "WE_SET_TXRX_FWSTATS val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID, + set_value, VDEV_CMD); + break; + } + + case WE_TXRX_FWSTATS_RESET: + { + hddLog(LOG1, "WE_TXRX_FWSTATS_RESET val %d", set_value); + if (set_value != WMA_FW_TXRX_FWSTATS_RESET) { + hddLog(LOGE, "Invalid arg %d in FWSTATS_RESET IOCTL", + set_value); + } + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMA_VDEV_TXRX_FWSTATS_RESET_CMDID, + set_value, VDEV_CMD); + break; + } + + case WE_DUMP_STATS: + { + hddLog(LOG1, "WE_DUMP_STATS val %d", set_value); + hdd_wlan_dump_stats(pAdapter, set_value); + break; + } + + case WE_CLEAR_STATS: + { + hdd_context_t* hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + hddLog(LOG1, "WE_CLEAR_STATS val %d", set_value); + switch (set_value) + { + case WLAN_HDD_STATS: + memset(&pAdapter->stats, 0, sizeof(pAdapter->stats)); + memset(&pAdapter->hdd_stats, 0, sizeof(pAdapter->hdd_stats)); + break; + case WLAN_TXRX_HIST_STATS: + wlan_hdd_clear_tx_rx_histogram(pHddCtx); + break; + default: + WLANTL_clear_datapath_stats(hdd_ctx->pvosContext, set_value); + break; + } + } + + case WE_PPS_PAID_MATCH: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + + hddLog(LOG1, "WMI_VDEV_PPS_PAID_MATCH val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_PAID_MATCH, + set_value, PPS_CMD); + break; + } + + case WE_PPS_GID_MATCH: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_GID_MATCH val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_GID_MATCH, + set_value, PPS_CMD); + break; + } + + case WE_PPS_EARLY_TIM_CLEAR: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, " WMI_VDEV_PPS_EARLY_TIM_CLEAR val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, + set_value, PPS_CMD); + break; + } + + case WE_PPS_EARLY_DTIM_CLEAR: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_EARLY_DTIM_CLEAR val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, + set_value, PPS_CMD); + break; + } + + case WE_PPS_EOF_PAD_DELIM: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_EOF_PAD_DELIM val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EOF_PAD_DELIM, + set_value, PPS_CMD); + break; + } + + case WE_PPS_MACADDR_MISMATCH: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_MACADDR_MISMATCH val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_MACADDR_MISMATCH, + set_value, PPS_CMD); + break; + } + + case WE_PPS_DELIM_CRC_FAIL: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_DELIM_CRC_FAIL val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, + set_value, PPS_CMD); + break; + } + + + case WE_PPS_GID_NSTS_ZERO: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_GID_NSTS_ZERO val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_GID_NSTS_ZERO, + set_value, PPS_CMD); + break; + } + + + case WE_PPS_RSSI_CHECK: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return EINVAL; + hddLog(LOG1, "WMI_VDEV_PPS_RSSI_CHECK val %d ", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_RSSI_CHECK, + set_value, PPS_CMD); + break; + } + + case WE_PPS_5G_EBT: + { + if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION) + return -EINVAL; + + hddLog(LOG1, "WMI_VDEV_PPS_5G_EBT val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_5G_EBT, + set_value, PPS_CMD); + break; + } + + case WE_SET_HTSMPS: + { + hddLog(LOG1, "WE_SET_HTSMPS val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_SMPS_FORCE_MODE_CMDID, + set_value, VDEV_CMD); + break; + } + + + case WE_SET_QPOWER_MAX_PSPOLL_COUNT: + { + hddLog(LOG1, "WE_SET_QPOWER_MAX_PSPOLL_COUNT val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + set_value, QPOWER_CMD); + break; + } + + case WE_SET_QPOWER_MAX_TX_BEFORE_WAKE: + { + hddLog(LOG1, "WE_SET_QPOWER_MAX_TX_BEFORE_WAKE val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE, + set_value, QPOWER_CMD); + break; + } + + case WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + { + hddLog(LOG1, "WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + set_value, QPOWER_CMD); + break; + } + + case WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + { + hddLog(LOG1, "WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL val %d", + set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + set_value, QPOWER_CMD); + break; + } + case WE_SET_SCAN_BAND_PREFERENCE: + { + if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) { + ret = -EINVAL; + break; + } + hddLog(LOG1, "WE_SET_BAND_PREFERRENCE val %d ", set_value); + + if (eCSR_BAND_ALL == set_value || + eCSR_BAND_24 == set_value || eCSR_BAND_5G == set_value) { + sme_GetConfigParam(hHal, &smeConfig); + smeConfig.csrConfig.scanBandPreference = set_value; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "set band scan preference = %d", + smeConfig.csrConfig.scanBandPreference); + + sme_UpdateConfig(hHal, &smeConfig); + } + else { + ret = -EINVAL; + } + break; + + } + + case WE_MCC_CONFIG_LATENCY: + { + tVOS_CONCURRENCY_MODE concurrent_state = 0; + v_U8_t first_adapter_operating_channel = 0; + int ret = 0; /* success */ + + hddLog(LOG1, "iwpriv cmd to set MCC latency with val %dms", + set_value); + /** + * Check if concurrency mode is active. + * Need to modify this code to support MCC modes other than STA/P2P + */ + concurrent_state = hdd_get_concurrency_mode(); + if ((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) || + (concurrent_state == (VOS_STA | VOS_P2P_GO))) + { + hddLog(LOG1, "STA & P2P are both enabled"); + /** + * The channel number and latency are formatted in + * a bit vector then passed on to WMA layer. + +**********************************************+ + |bits 31-16 | bits 15-8 | bits 7-0 | + | Unused | latency - Chan. 1 | channel no. | + +**********************************************+ + */ + /* Get the operating channel of the designated vdev */ + first_adapter_operating_channel = + hdd_get_operating_channel + ( + pAdapter->pHddCtx, + pAdapter->device_mode + ); + /* Move the time latency for the adapter to bits 15-8 */ + set_value = set_value << 8; + /* Store the channel number at bits 7-0 of the bit vector */ + set_value = set_value | first_adapter_operating_channel; + /* Send command to WMA */ + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMA_VDEV_MCC_SET_TIME_LATENCY, + set_value, VDEV_CMD); + } + else + { + hddLog(LOG1, "%s: MCC is not active. Exit w/o setting latency", + __func__); + } + break; + } + + case WE_MCC_CONFIG_QUOTA: + { + + hddLog(LOG1, "iwpriv cmd to set MCC quota with val %dms", + set_value); + ret = hdd_wlan_set_mcc_p2p_quota(pAdapter, set_value); + break; + } + case WE_SET_DEBUG_LOG: + { + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +#ifdef QCA_PKT_PROTO_TRACE + /* Trace buffer dump only */ + if (VOS_PKT_TRAC_DUMP_CMD == set_value) + { + vos_pkt_trace_buf_dump(); + break; + } +#endif /* QCA_PKT_PROTO_TRACE */ + pHddCtx->cfg_ini->gEnableDebugLog = set_value; + sme_UpdateConnectDebug(pHddCtx->hHal, set_value); + break; + } + case WE_SET_EARLY_RX_ADJUST_ENABLE: + { + hddLog(LOG1, "SET early_rx enable val %d", set_value); + if ((set_value == 0) || (set_value == 1)) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_ADJUST_ENABLE, + set_value, VDEV_CMD); + } + else + ret = -EINVAL; + break; + } + case WE_SET_EARLY_RX_TGT_BMISS_NUM: + { + hddLog(LOG1, "SET early_rx bmiss val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_TGT_BMISS_NUM, + set_value, VDEV_CMD); + break; + } + case WE_SET_EARLY_RX_BMISS_SAMPLE_CYCLE: + { + hddLog(LOG1, "SET early_rx bmiss sample cycle %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_BMISS_SAMPLE_CYCLE, + set_value, VDEV_CMD); + break; + } + case WE_SET_EARLY_RX_SLOP_STEP: + { + hddLog(LOG1, "SET early_rx bmiss slop step val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_SLOP_STEP, + set_value, VDEV_CMD); + break; + } + case WE_SET_EARLY_RX_INIT_SLOP: + { + hddLog(LOG1, "SET early_rx init slop step val %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_INIT_SLOP, + set_value, VDEV_CMD); + break; + } + case WE_SET_EARLY_RX_ADJUST_PAUSE: + { + hddLog(LOG1, "SET early_rx adjust pause %d", set_value); + if ((set_value == 0) || (set_value == 1)) { + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_ADJUST_PAUSE, + set_value, VDEV_CMD); + } + else + ret = -EINVAL; + break; + } + case WE_SET_EARLY_RX_DRIFT_SAMPLE: + { + hddLog(LOG1, "SET early_rx drift sample %d", set_value); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_EARLY_RX_DRIFT_SAMPLE, + set_value, VDEV_CMD); + break; + } + case WE_SET_CHANNEL: + { + hddLog(LOG1, "Set Channel %d Session ID %d mode = %d", set_value, + pAdapter->sessionId, pAdapter->device_mode); + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) { + + status = sme_ext_change_channel(pHddCtx->hHal, + set_value, pAdapter->sessionId); + + if (status != eHAL_STATUS_SUCCESS) + ret = -EINVAL; + } else { + ret = -EINVAL; + } + break; + } + default: + { + hddLog(LOGE, "%s: Invalid sub command %d", __func__, sub_cmd); + ret = -EINVAL; + break; + } + } + EXIT(); + return ret; +} + +static int iw_setint_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_setint_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* set param sub-ioctls */ +static int __iw_setchar_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + VOS_STATUS vstatus; + int sub_cmd; + int ret; + char *pBuffer = NULL; + hdd_adapter_t *pAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +#ifdef WLAN_FEATURE_VOWIFI + hdd_config_t *pConfig = pHddCtx->cfg_ini; +#endif /* WLAN_FEATURE_VOWIFI */ + struct iw_point s_priv_data; + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (!capable(CAP_NET_ADMIN)){ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + /* 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"); + hdd_add_wowl_ptrn(pAdapter, pBuffer); + break; + case WE_WOWL_DEL_PTRN: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN"); + hdd_del_wowl_ptrn(pAdapter, pBuffer); + break; +#if defined WLAN_FEATURE_VOWIFI + case WE_NEIGHBOR_REPORT_REQUEST: + { + tRrmNeighborReq neighborReq; + tRrmNeighborRspCallbackInfo callbackInfo; + + if (pConfig->fRrmEnable) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Neighbor Request"); + neighborReq.no_ssid = (s_priv_data.length - 1) ? false : true ; + if( !neighborReq.no_ssid ) + { + neighborReq.ssid.length = (s_priv_data.length - 1) > 32 ? + 32 : (s_priv_data.length - 1); + vos_mem_copy(neighborReq.ssid.ssId, pBuffer, + neighborReq.ssid.length); + } + + callbackInfo.neighborRspCallback = NULL; + callbackInfo.neighborRspCallbackContext = NULL; + callbackInfo.timeout = 5000; //5 seconds + sme_NeighborReportRequest( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &neighborReq, &callbackInfo ); + } + else + { + hddLog(LOGE, "%s: Ignoring neighbor request as RRM is not enabled", __func__); + ret = -EINVAL; + } + } + break; +#endif + case WE_SET_AP_WPS_IE: + hddLog( LOGE, "Received WE_SET_AP_WPS_IE" ); + sme_updateP2pIe(WLAN_HDD_GET_HAL_CTX(pAdapter), pBuffer, + s_priv_data.length); + break; + case WE_SET_CONFIG: + vstatus = hdd_execute_global_config_command(pHddCtx, pBuffer); +#ifdef WLAN_FEATURE_MBSSID + if (vstatus == VOS_STATUS_E_PERM) { + vstatus = hdd_execute_sap_dyn_config_command(pAdapter, pBuffer); + if (vstatus == VOS_STATUS_SUCCESS) + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Stored in Dynamic SAP ini config", __func__); + + } +#endif + if (VOS_STATUS_SUCCESS != vstatus) + { + ret = -EINVAL; + } + break; + default: + { + hddLog(LOGE, "%s: Invalid sub command %d", __func__, sub_cmd); + ret = -EINVAL; + break; + } + } + kfree(pBuffer); + EXIT(); + 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; +} + + +static int iw_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_setchar_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* get param sub-ioctls */ +static int __iw_setnone_getint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + int *value = (int *)extra; + int ret; + hdd_context_t *wmahddCtxt = WLAN_HDD_GET_CTX(pAdapter); + void *wmapvosContext = wmahddCtxt->pvosContext; + tSmeConfigParams smeConfig; + hdd_context_t *hdd_ctx; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (value[0]) + { + case WE_GET_11D_STATE: + { + sme_GetConfigParam(hHal,&smeConfig); + + *value = smeConfig.csrConfig.Is11dSupportEnabled; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("11D state=%d!!"),*value); + + break; + } + + case WE_IBSS_STATUS: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****Return IBSS Status*****"); + break; + + case WE_GET_WLAN_DBG: + { + vos_trace_display(); + *value = 0; + break; + } + case WE_GET_MAX_ASSOC: + { + if (ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value) != eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("failed to get ini parameter, WNI_CFG_ASSOC_STA_LIMIT")); + ret = -EIO; + } + break; + } + case WE_GET_SAP_AUTO_CHANNEL_SELECTION: + *value = (WLAN_HDD_GET_CTX( + pAdapter))->cfg_ini->force_sap_acs; + break; + + case WE_GET_CONCURRENCY_MODE: + { + *value = hdd_get_concurrency_mode ( ); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("concurrency mode=%d"),*value); + break; + } + + case WE_GET_NSS: + { + sme_GetConfigParam(hHal, &smeConfig); + *value = (smeConfig.csrConfig.enable2x2 == 0) ? 1 : 2; + hddLog(LOG1, "GET_NSS: Current NSS:%d", *value); + break; + } + + case WE_GET_GTX_HT_MCS: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_HT_MCS"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_HT_MCS, + GTX_CMD); + break; + } + + case WE_GET_GTX_VHT_MCS: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_VHT_MCS"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_VHT_MCS, + GTX_CMD); + break; + } + + case WE_GET_GTX_USRCFG: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_USR_CFG"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_USR_CFG, + GTX_CMD); + break; + } + + case WE_GET_GTX_THRE: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_THRE"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_THRE, + GTX_CMD); + break; + } + + case WE_GET_GTX_MARGIN: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_MARGIN"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MARGIN, + GTX_CMD); + break; + } + + case WE_GET_GTX_STEP: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_STEP"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_STEP, + GTX_CMD); + break; + } + + case WE_GET_GTX_MINTPC: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_MINTPC"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_MINTPC, + GTX_CMD); + break; + } + + case WE_GET_GTX_BWMASK: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_GTX_BW_MASK"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_GTX_BW_MASK, + GTX_CMD); + break; + } + + case WE_GET_LDPC: + ret = hdd_get_ldpc(pAdapter, value); + break; + + case WE_GET_TX_STBC: + ret = hdd_get_tx_stbc(pAdapter, value); + break; + + case WE_GET_RX_STBC: + ret = hdd_get_rx_stbc(pAdapter, value); + break; + + case WE_GET_SHORT_GI: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_SGI"); + *value = sme_GetHTConfig(hHal, pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ); + break; + } + + case WE_GET_RTSCTS: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_ENABLE_RTSCTS"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_ENABLE_RTSCTS, + VDEV_CMD); + break; + } + + case WE_GET_CHWIDTH: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_CHWIDTH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_CHWIDTH, + VDEV_CMD); + break; + } + + case WE_GET_ANI_EN_DIS: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_ENABLE"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_ENABLE, + PDEV_CMD); + break; + } + + case WE_GET_ANI_POLL_PERIOD: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_POLL_PERIOD"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_POLL_PERIOD, + PDEV_CMD); + break; + } + + case WE_GET_ANI_LISTEN_PERIOD: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_LISTEN_PERIOD"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, + PDEV_CMD); + break; + } + + case WE_GET_ANI_OFDM_LEVEL: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_OFDM_LEVEL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_OFDM_LEVEL, + PDEV_CMD); + break; + } + + case WE_GET_ANI_CCK_LEVEL: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_CCK_LEVEL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_ANI_CCK_LEVEL, + PDEV_CMD); + break; + } + + case WE_GET_DYNAMIC_BW: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_ANI_CCK_LEVEL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_DYNAMIC_BW, + PDEV_CMD); + break; + } + + case WE_GET_11N_RATE: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_FIXED_RATE"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PARAM_FIXED_RATE, + VDEV_CMD); + break; + } + + case WE_GET_AMPDU: + { + hddLog(LOG1, "GET AMPDU"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMPDU, + GEN_CMD); + break; + } + + case WE_GET_AMSDU: + { + hddLog(LOG1, "GET AMSDU"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)GEN_VDEV_PARAM_AMSDU, + GEN_CMD); + break; + } + + case WE_GET_BURST_ENABLE: + { + hddLog(LOG1, "GET Burst enable value"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_ENABLE, + PDEV_CMD); + break; + } + case WE_GET_BURST_DUR: + { + hddLog(LOG1, "GET Burst Duration value"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_BURST_DUR, + PDEV_CMD); + break; + } + + case WE_GET_TX_CHAINMASK: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_TX_CHAIN_MASK"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TX_CHAIN_MASK, + PDEV_CMD); + break; + } + + case WE_GET_RX_CHAINMASK: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_RX_CHAIN_MASK"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_RX_CHAIN_MASK, + PDEV_CMD); + break; + } + + case WE_GET_TXPOW_2G: + { + tANI_U32 txpow2g = 0; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hddLog(LOG1, "GET WMI_PDEV_PARAM_TXPOWER_LIMIT2G"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TXPOWER_LIMIT2G, + PDEV_CMD); + if ( eHAL_STATUS_SUCCESS != ccmCfgGetInt(hHal, + WNI_CFG_CURRENT_TX_POWER_LEVEL, &txpow2g) ) + { + return -EIO; + } + hddLog(LOG1, "2G tx_power %d", txpow2g); + break; + } + + case WE_GET_TXPOW_5G: + { + tANI_U32 txpow5g = 0; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hddLog(LOG1, "GET WMI_PDEV_PARAM_TXPOWER_LIMIT5G"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_PDEV_PARAM_TXPOWER_LIMIT5G, + PDEV_CMD); + if ( eHAL_STATUS_SUCCESS != ccmCfgGetInt(hHal, + WNI_CFG_CURRENT_TX_POWER_LEVEL, &txpow5g) ) + { + return -EIO; + } + hddLog(LOG1, "5G tx_power %d", txpow5g); + break; + } + + case WE_GET_PPS_PAID_MATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_PAID_MATCH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_PAID_MATCH, + PPS_CMD); + break; + } + + case WE_GET_PPS_GID_MATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_GID_MATCH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_GID_MATCH, + PPS_CMD); + break; + } + + case WE_GET_PPS_EARLY_TIM_CLEAR: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_TIM_CLEAR"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EARLY_TIM_CLEAR, + PPS_CMD); + break; + } + + case WE_GET_PPS_EARLY_DTIM_CLEAR: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_EARLY_DTIM_CLEAR"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EARLY_DTIM_CLEAR, + PPS_CMD); + break; + } + + case WE_GET_PPS_EOF_PAD_DELIM: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_EOF_PAD_DELIM"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_EOF_PAD_DELIM, + PPS_CMD); + break; + } + + case WE_GET_PPS_MACADDR_MISMATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_MACADDR_MISMATCH"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_MACADDR_MISMATCH, + PPS_CMD); + break; + } + + case WE_GET_PPS_DELIM_CRC_FAIL: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_DELIM_CRC_FAIL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_DELIM_CRC_FAIL, + PPS_CMD); + break; + } + + case WE_GET_PPS_GID_NSTS_ZERO: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_GID_NSTS_ZERO"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_GID_NSTS_ZERO, + PPS_CMD); + break; + } + + case WE_GET_PPS_RSSI_CHECK: + { + + hddLog(LOG1, "GET WMI_VDEV_PPS_RSSI_CHECK"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_VDEV_PPS_RSSI_CHECK, + PPS_CMD); + break; + } + + case WE_GET_QPOWER_MAX_PSPOLL_COUNT: + { + hddLog(LOG1, "WE_GET_QPOWER_MAX_PSPOLL_COUNT"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + QPOWER_CMD); + break; + } + + case WE_GET_QPOWER_MAX_TX_BEFORE_WAKE: + { + hddLog(LOG1, "WE_GET_QPOWER_MAX_TX_BEFORE_WAKE"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE, + QPOWER_CMD); + break; + } + + case WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + { + hddLog(LOG1, "WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + QPOWER_CMD); + break; + } + + case WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + { + hddLog(LOG1, "WE_GET_QPOWER_MAX_PSPOLL_COUNT"); + *value = wma_cli_get_command(wmapvosContext, + (int)pAdapter->sessionId, + (int)WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + QPOWER_CMD); + break; + } + + case WE_GET_SCAN_BAND_PREFERENCE: + { + sme_GetConfigParam(hHal, &smeConfig); + *value = smeConfig.csrConfig.scanBandPreference; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "scanBandPreference = %d", *value); + break; + } + + case WE_GET_TEMPERATURE: + { + hddLog(VOS_TRACE_LEVEL_INFO, "WE_GET_TEMPERATURE"); + ret = wlan_hdd_get_temperature(pAdapter, wrqu, extra); + break; + } + + case WE_GET_FW_STATUS: + { + hddLog(LOG1, "WE_GET_FW_STATUS"); + *value = wlan_hdd_get_fw_state(pAdapter); + break; + } + case WE_CAP_TSF: + { + ret = hdd_capture_tsf(pAdapter, (uint32_t *)value, 1); + break; + } + default: + { + hddLog(LOGE, "Invalid IOCTL get_value command %d", value[0]); + break; + } + } + EXIT(); + return ret; +} + +static int iw_setnone_getint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_setnone_getint(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* set param sub-ioctls */ +static int __iw_set_three_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + int *value = (int *)extra; + int sub_cmd = value[0]; + int ret; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch(sub_cmd) { + + case WE_SET_WLAN_DBG: + vos_trace_setValue( value[1], value[2], value[3]); + break; + + case WE_SET_SAP_CHANNELS: + /* value[3] the acs band is not required as start and end channels are + * enough but this cmd is maintained under set three ints for historic + * reasons. + */ + if (wlan_hdd_validate_operation_channel(pAdapter, value[1]) != + VOS_STATUS_SUCCESS || + wlan_hdd_validate_operation_channel(pAdapter, value[2]) != + VOS_STATUS_SUCCESS) { + ret = -EINVAL; + } else { + hdd_ctx->cfg_ini->force_sap_acs_st_ch = value[1]; + hdd_ctx->cfg_ini->force_sap_acs_end_ch = value[2]; + } + break; + + default: + hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd ); + break; + + } + EXIT(); + return ret; +} + +int iw_set_three_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_three_ints_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_get_char_setnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int sub_cmd = wrqu->data.flags; + hdd_context_t *hdd_ctx; + int ret; +#ifdef WLAN_FEATURE_11W + hdd_wext_state_t *pWextState; +#endif + +#ifdef WLAN_FEATURE_11W + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); +#endif + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch(sub_cmd) + { + case WE_WLAN_VERSION: + { + hdd_wlan_get_version(pAdapter, wrqu, extra); + break; + } + + case WE_GET_STATS: + { + hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; + } + +/* The case prints the current state of the HDD, SME, CSR, PE, TL + *it can be extended for WDI Global State as well. + *And currently it only checks P2P_CLIENT adapter. + *P2P_DEVICE and P2P_GO have not been added as of now. +*/ + case WE_GET_STATES: + { + int buf = 0, len = 0; + int adapter_num = 0; + int count = 0, check = 1; + + tANI_U16 tlState; + tHalHandle hHal = NULL; + tpAniSirGlobal pMac = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + hdd_adapter_t *useAdapter = NULL; + + /* Print wlan0 or p2p0 states based on the adapter_num + *by using the correct adapter + */ + while ( adapter_num < 2 ) + { + if ( WLAN_ADAPTER == adapter_num ) + { + useAdapter = pAdapter; + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n\n wlan0 States:-"); + len += buf; + } + else if ( P2P_ADAPTER == adapter_num ) + { + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n\n p2p0 States:-"); + len += buf; + + if( !pHddCtx ) + { + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n pHddCtx is NULL"); + len += buf; + break; + } + + /*Printing p2p0 states only in the case when the device is + configured as a p2p_client*/ + useAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT); + if ( !useAdapter ) + { + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n Device not configured as P2P_CLIENT."); + len += buf; + break; + } + } + + hHal = WLAN_HDD_GET_HAL_CTX( useAdapter ); + if (!hHal) { + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n pMac is NULL"); + len += buf; + break; + } + pMac = PMAC_STRUCT( hHal ); + if (!pMac) { + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n pMac is NULL"); + len += buf; + break; + } + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(useAdapter); + + tlState = smeGetTLSTAState(hHal, pHddStaCtx->conn_info.staId[0]); + + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n HDD Conn State - %s " + "\n \n SME State:" + "\n Neighbour Roam State - %s" + "\n CSR State - %s" + "\n CSR Substate - %s" + "\n \n TL STA %d State: %s", + macTraceGetHDDWlanConnState( + pHddStaCtx->conn_info.connState), + macTraceGetNeighbourRoamState( + sme_getNeighborRoamState(hHal, + useAdapter->sessionId)), + macTraceGetcsrRoamState( + sme_getCurrentRoamState(hHal, + useAdapter->sessionId)), + macTraceGetcsrRoamSubState( + sme_getCurrentRoamSubState(hHal, + useAdapter->sessionId)), + pHddStaCtx->conn_info.staId[0], + macTraceGetTLState(tlState) + ); + len += buf; + adapter_num++; + } + + if (hHal) { + /* Printing Lim State starting with global lim states */ + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n \n LIM STATES:-" + "\n Global Sme State - %s "\ + "\n Global mlm State - %s "\ + "\n", + macTraceGetLimSmeState(sme_getLimSmeState(hHal)), + macTraceGetLimMlmState(sme_getLimSmeState(hHal)) + ); + len += buf; + + /* Printing the PE Sme and Mlm states for valid lim sessions */ + while (check < 3 && count < 255) { + if (sme_IsLimSessionValid(hHal, count)) { + buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n Lim Valid Session %d:-" + "\n PE Sme State - %s " + "\n PE Mlm State - %s " + "\n", + check, + macTraceGetLimSmeState(sme_getLimSmeSessionState( + hHal, count)), + macTraceGetLimMlmState(sme_getLimMlmSessionState( + hHal, count)) + ); + + len += buf; + check++; + } + count++; + } + } + + wrqu->data.length = strlen(extra)+1; + break; + } + + case WE_GET_CFG: + { +#ifdef WLAN_FEATURE_MBSSID + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Printing Adapter MBSSID SAP Dyn INI Config", __func__); + hdd_cfg_get_sap_dyn_config(pAdapter, + extra, QCSAP_IOCTL_MAX_STR_LEN); + /* Overwrite extra buffer with global ini config if need to return + * in buf + */ +#endif + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Printing CLD global INI Config", __func__); + hdd_cfg_get_global_config(WLAN_HDD_GET_CTX(pAdapter), extra, + QCSAP_IOCTL_MAX_STR_LEN); + wrqu->data.length = strlen(extra)+1; + break; + } +#ifdef WLAN_FEATURE_11AC + case WE_GET_RSSI: + { + v_S7_t s7Rssi = 0; + wlan_hdd_get_rssi(pAdapter, &s7Rssi); + snprintf(extra, WE_MAX_STR_LEN, "rssi=%d",s7Rssi); + wrqu->data.length = strlen(extra)+1; + break; + } +#endif + + case WE_GET_WMM_STATUS: + { + snprintf(extra, WE_MAX_STR_LEN, + "\nDir: 0=up, 1=down, 3=both\n" + "|------------------------|\n" + "|AC | ACM |Admitted| Dir |\n" + "|------------------------|\n" + "|VO | %d | %3s | %d |\n" + "|VI | %d | %3s | %d |\n" + "|BE | %d | %3s | %d |\n" + "|BK | %d | %3s | %d |\n" + "|------------------------|\n", + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessRequired, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessAllowed?"YES":"NO", + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcTspecInfo.ts_info.direction, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessRequired, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessAllowed?"YES":"NO", + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcTspecInfo.ts_info.direction, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessRequired, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessAllowed?"YES":"NO", + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcTspecInfo.ts_info.direction, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessRequired, + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessAllowed?"YES":"NO", + pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcTspecInfo.ts_info.direction); + + + wrqu->data.length = strlen(extra)+1; + break; + } + case WE_GET_CHANNEL_LIST: + { + VOS_STATUS status; + v_U8_t i, len; + char* buf; + uint8_t ubuf[WNI_CFG_COUNTRY_CODE_LEN]; + uint8_t ubuf_len = WNI_CFG_COUNTRY_CODE_LEN; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + tChannelListInfo channel_list; + + memset(&channel_list, 0, sizeof(channel_list)); + status = iw_softap_get_channel_list(dev, info, wrqu, (char *)&channel_list); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("GetChannelList Failed!!!")); + return -EINVAL; + } + buf = extra; + /** + * Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. Maximum buffer + * needed = 5 * number of channels. Check if sufficient + * buffer is available and then proceed to fill the buffer. + */ + if (WE_MAX_STR_LEN < (5 * WNI_CFG_VALID_CHANNEL_LIST_LEN)) { + hddLog(LOGE, + FL("Insufficient Buffer to populate channel list")); + return -EINVAL; + } + len = scnprintf(buf, WE_MAX_STR_LEN, "%u ", + channel_list.num_channels); + if (eHAL_STATUS_SUCCESS == sme_GetCountryCode(hdd_ctx->hHal, + ubuf, &ubuf_len)) { + /* Printing Country code in getChannelList */ + for (i = 0; i < (ubuf_len - 1); i++) + len += scnprintf(buf + len, WE_MAX_STR_LEN - len, + "%c", ubuf[i]); + } + + for (i = 0; i < channel_list.num_channels; i++) { + len += scnprintf(buf + len, WE_MAX_STR_LEN - len, + " %u", channel_list.channels[i]); + } + wrqu->data.length = strlen(extra) + 1; + + break; + } +#ifdef FEATURE_WLAN_TDLS + case WE_GET_TDLS_PEERS: + { + wrqu->data.length = wlan_hdd_tdls_get_all_peers(pAdapter, extra, WE_MAX_STR_LEN)+1; + break; + } +#endif +#ifdef WLAN_FEATURE_11W + case WE_GET_11W_INFO: + { + hddLog(LOGE, "WE_GET_11W_ENABLED = %d", pWextState->roamProfile.MFPEnabled ); + + snprintf(extra, WE_MAX_STR_LEN, + "\n BSSID %02X:%02X:%02X:%02X:%02X:%02X, Is PMF Assoc? %d" + "\n Number of Unprotected Disassocs %d" + "\n Number of Unprotected Deauths %d", + (*pWextState->roamProfile.BSSIDs.bssid)[0], (*pWextState->roamProfile.BSSIDs.bssid)[1], + (*pWextState->roamProfile.BSSIDs.bssid)[2], (*pWextState->roamProfile.BSSIDs.bssid)[3], + (*pWextState->roamProfile.BSSIDs.bssid)[4], (*pWextState->roamProfile.BSSIDs.bssid)[5], + pWextState->roamProfile.MFPEnabled, pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx, + pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx); + + wrqu->data.length = strlen(extra)+1; + break; + } +#endif + case WE_GET_PHYMODE: + { + v_BOOL_t ch_bond24 = VOS_FALSE, ch_bond5g = VOS_FALSE; + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(pAdapter); + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter); + eCsrPhyMode phymode; + eCsrBand currBand; + tSmeConfigParams smeconfig; + + sme_GetConfigParam(hal, &smeconfig); + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + smeconfig.csrConfig.channelBondingMode24GHz) + ch_bond24 = VOS_TRUE; + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + smeconfig.csrConfig.channelBondingMode5GHz) + ch_bond5g = VOS_TRUE; + + phymode = sme_GetPhyMode(hal); + if ((eHAL_STATUS_SUCCESS != sme_GetFreqBand(hal, &currBand))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Failed to get current band config", + __func__); + return -EIO; + } + + + switch (phymode) { + case eCSR_DOT11_MODE_AUTO: + snprintf(extra, WE_MAX_STR_LEN, "AUTO MODE"); + break; + case eCSR_DOT11_MODE_11n: + case eCSR_DOT11_MODE_11n_ONLY: + if (currBand == eCSR_BAND_24) { + if (ch_bond24) + snprintf(extra, WE_MAX_STR_LEN, "11NGHT40"); + else + snprintf(extra, WE_MAX_STR_LEN, "11NGHT20"); + } + else if(currBand == eCSR_BAND_5G) { + if (ch_bond5g) + snprintf(extra, WE_MAX_STR_LEN, "11NAHT40"); + else + snprintf(extra, WE_MAX_STR_LEN, "11NAHT20"); + } else { + snprintf(extra, WE_MAX_STR_LEN, "11N"); + } + break; + case eCSR_DOT11_MODE_abg: + snprintf(extra, WE_MAX_STR_LEN, "11ABG"); + break; + case eCSR_DOT11_MODE_11a: + snprintf(extra, WE_MAX_STR_LEN, "11A"); + break; + case eCSR_DOT11_MODE_11b: + case eCSR_DOT11_MODE_11b_ONLY: + snprintf(extra, WE_MAX_STR_LEN, "11B"); + break; + case eCSR_DOT11_MODE_11g: + case eCSR_DOT11_MODE_11g_ONLY: + snprintf(extra, WE_MAX_STR_LEN, "11G"); + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: + case eCSR_DOT11_MODE_11ac_ONLY: + if (hddctx->cfg_ini->vhtChannelWidth == + eHT_CHANNEL_WIDTH_20MHZ) + snprintf(extra, WE_MAX_STR_LEN, "11ACVHT20"); + else if (hddctx->cfg_ini->vhtChannelWidth == + eHT_CHANNEL_WIDTH_40MHZ) + snprintf(extra, WE_MAX_STR_LEN, "11ACVHT40"); + else if (hddctx->cfg_ini->vhtChannelWidth == + eHT_CHANNEL_WIDTH_80MHZ) + snprintf(extra, WE_MAX_STR_LEN, "11ACVHT80"); + else if (hddctx->cfg_ini->vhtChannelWidth == + eHT_CHANNEL_WIDTH_160MHZ) + snprintf(extra, WE_MAX_STR_LEN, "11ACVHT160"); + break; +#endif + } + + wrqu->data.length = strlen(extra)+1; + break; + } + +#ifdef FEATURE_OEM_DATA_SUPPORT + case WE_GET_OEM_DATA_CAP: + { + return iw_get_oem_data_cap(dev, info, wrqu, extra); + } +#endif /* FEATURE_OEM_DATA_SUPPORT */ + case WE_GET_SNR: + { + v_S7_t s7snr = 0; + int status = 0; + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + hddLog(LOGE, "%s: getSNR: HDD context is not valid", __func__); + return status; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring || + eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + hddLog(LOGE, "%s: getSNR failed: Enable SNR Monitoring-%d," + " ConnectionState-%d", __func__, + pHddCtx->cfg_ini->fEnableSNRMonitoring, + pHddStaCtx->conn_info.connState); + return -ENONET; + } + + wlan_hdd_get_snr(pAdapter, &s7snr); + snprintf(extra, WE_MAX_STR_LEN, "snr=%d",s7snr); + wrqu->data.length = strlen(extra) + 1; + break; + } + default: + { + hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd ); + break; + } + } + EXIT(); + return 0; +} + +static int iw_get_char_setnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_char_setnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* action sub-ioctls */ +static int __iw_setnone_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int ret; + int sub_cmd; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + +#ifdef CONFIG_COMPAT + /* this ioctl is a special case where a sub-ioctl is used and both + * the number of get and set args is 0. in this specific case the + * logic in iwpriv places the sub_cmd in the data.flags portion of + * the iwreq. unfortunately the location of this field will be + * different between 32-bit and 64-bit user space, and the standard + * compat support in the kernel does not handle this case. so we + * need to explicitly handle it here. */ + if (is_compat_task()) { + struct compat_iw_point *compat_iw_point = + (struct compat_iw_point *) &wrqu->data; + sub_cmd = compat_iw_point->flags; + } else { + sub_cmd = wrqu->data.flags; + } +#else + sub_cmd = wrqu->data.flags; +#endif + + switch (sub_cmd) + { + case WE_GET_RECOVERY_STAT: + { + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter); + sme_getRecoveryStats(hal); + break; + } + + case WE_ENABLE_DXE_STALL_DETECT: + { + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + sme_transportDebug(hHal, VOS_FALSE, VOS_TRUE); + break; + } + case WE_DISPLAY_DXE_SNAP_SHOT: + { + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + sme_transportDebug(hHal, VOS_TRUE, VOS_FALSE); + break; + } + case WE_DISPLAY_DATAPATH_SNAP_SHOT: + { + hddLog(LOGE, "%s: called %d",__func__, sub_cmd); + hdd_wmm_tx_snapshot(pAdapter); + WLANTL_TLDebugMessage(VOS_TRUE); + break; + } + case WE_SET_REASSOC_TRIGGER: + { + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U32_t roamId = 0; + tCsrRoamModifyProfileFields modProfileFields; + hdd_station_ctx_t *pHddStaCtx = + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + /* Reassoc to same AP, only supported for Open Security*/ + if ((pHddStaCtx->conn_info.ucEncryptionType || + pHddStaCtx->conn_info.mcEncryptionType)) { + hddLog(LOGE, + FL("Reassoc to same AP, only supported for Open Security")); + return -ENOTSUPP; + } + sme_GetModifyProfileFields(hHal, pAdapter->sessionId, + &modProfileFields); + sme_RoamReassoc(hHal, pAdapter->sessionId, + NULL, modProfileFields, &roamId, 1); + return 0; + } + + case WE_DUMP_AGC_START: + { + hddLog(LOG1, "WE_DUMP_AGC_START"); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_PARAM_DUMP_AGC_START, + 0, GEN_CMD); + break; + } + case WE_DUMP_AGC: + { + hddLog(LOG1, "WE_DUMP_AGC"); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_PARAM_DUMP_AGC, + 0, GEN_CMD); + break; + } + + case WE_DUMP_CHANINFO_START: + { + hddLog(LOG1, "WE_DUMP_CHANINFO_START"); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_PARAM_DUMP_CHANINFO_START, + 0, GEN_CMD); + break; + } + case WE_DUMP_CHANINFO: + { + hddLog(LOG1, "WE_DUMP_CHANINFO_START"); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_PARAM_DUMP_CHANINFO, + 0, GEN_CMD); + break; + } + case WE_DUMP_WATCHDOG: + { + hddLog(LOG1, "WE_DUMP_WATCHDOG"); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)GEN_PARAM_DUMP_WATCHDOG, + 0, GEN_CMD); + break; + } +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + case WE_DUMP_PCIE_LOG: + { + hddLog(LOGE, "WE_DUMP_PCIE_LOG"); + ret = process_wma_set_command((int) pAdapter->sessionId, + (int) GEN_PARAM_DUMP_PCIE_ACCESS_LOG, + 0, GEN_CMD); + break; + } +#endif + default: + { + hddLog(LOGE, "%s: unknown ioctl %d", __func__, sub_cmd); + break; + } + } + EXIT(); + return ret; +} + +static int iw_setnone_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_setnone_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter) +{ + /* + * Function to display HDD WMM information + * for Tx Queues. + * Prints global as well as per client depending + * whether the clients are registered or not. + */ + int i = 0, j = 0; + for ( i=0; i< NUM_TX_QUEUES; i++) + { + spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock); + hddLog(LOGE, "HDD WMM TxQueue Info For AC: %d Count: %d PrevAdress:%p, NextAddress:%p", + i, pAdapter->wmm_tx_queue[i].count, + pAdapter->wmm_tx_queue[i].anchor.prev, pAdapter->wmm_tx_queue[i].anchor.next); + spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); + } + + for(i =0; iaStaInfo[i].isUsed) + { + hddLog(LOGE, "******STAIndex: %d*********", i); + for ( j=0; j< NUM_TX_QUEUES; j++) + { + spin_lock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); + hddLog(LOGE, "HDD TxQueue Info For AC: %d Count: %d PrevAdress:%p, NextAddress:%p", + j, pAdapter->aStaInfo[i].wmm_tx_queue[j].count, + pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.prev, + pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.next); + spin_unlock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); + } + } + } + +} + +static int __iw_set_var_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + int sub_cmd; + int *apps_args = (int *) extra; + hdd_station_ctx_t *pStaCtx = NULL ; + hdd_ap_ctx_t *pAPCtx = NULL; + int cmd = 0; + int staId = 0; + hdd_context_t *pHddCtx; + int ret, num_args; + + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (extra == NULL) { + hddLog(LOGE, FL("NULL extra buffer pointer")); + return -EINVAL; + } + + sub_cmd = wrqu->data.flags; + num_args = wrqu->data.length; + + hddLog(LOG1, FL("Received length %d"), wrqu->data.length); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if(( sub_cmd == WE_MCC_CONFIG_CREDENTIAL ) || + (sub_cmd == WE_MCC_CONFIG_PARAMS )) + { + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { + pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + staId = pStaCtx->conn_info.staId[0]; + } else if ((pAdapter->device_mode == WLAN_HDD_P2P_GO) || + (pAdapter->device_mode == WLAN_HDD_SOFTAP)) { + pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + staId = pAPCtx->uBCStaId; + } else { + hddLog(LOGE, FL("Device mode %s(%d) not recognised"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return 0; + } + } + + switch (sub_cmd) + { + case WE_LOG_DUMP_CMD: + { + hddLog(LOG1, "%s: LOG_DUMP %d arg1 %d arg2 %d arg3 %d arg4 %d", + __func__, apps_args[0], apps_args[1], apps_args[2], + apps_args[3], apps_args[4]); + + logPrintf(hHal, apps_args[0], apps_args[1], apps_args[2], + apps_args[3], apps_args[4]); + + } + break; + + case WE_P2P_NOA_CMD: + { + p2p_app_setP2pPs_t p2pNoA; + + if (pAdapter->device_mode != WLAN_HDD_P2P_GO) { + hddLog(LOGE, + FL("Setting NoA is not allowed in Device mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return -EINVAL; + } + + p2pNoA.opp_ps = apps_args[0]; + p2pNoA.ctWindow = apps_args[1]; + p2pNoA.duration = apps_args[2]; + p2pNoA.interval = apps_args[3]; + p2pNoA.count = apps_args[4]; + p2pNoA.single_noa_duration = apps_args[5]; + p2pNoA.psSelection = apps_args[6]; + + hddLog(LOG1, "%s: P2P_NOA_ATTR:oppPS %d ctWindow %d duration %d " + "interval %d count %d single noa duration %d PsSelection %x", + __func__, apps_args[0], apps_args[1], apps_args[2], + apps_args[3], apps_args[4], apps_args[5], apps_args[6]); + + hdd_setP2pPs(dev, &p2pNoA); + + } + break; + + case WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD: + { + hddLog(LOG1, "%s: SELECTIVE_MODULE_LOG %d arg1 %d arg2", + __func__, apps_args[0], apps_args[1]); + vosTraceEnable(apps_args[0], apps_args[1]); + } + break; + + case WE_MTRACE_DUMP_CMD: + { + hddLog(LOG1, "%s: MTRACE_DUMP code %d session %d count %d " + "bitmask_of_module %d ", + __func__, apps_args[0], apps_args[1], apps_args[2], + apps_args[3]); + vosTraceDumpAll((void*)hHal , apps_args[0], apps_args[1], + apps_args[2], apps_args[3]); + + } + break; + + case WE_MCC_CONFIG_CREDENTIAL : + { + cmd = 287; //Command should be updated if there is any change + // in the Riva dump command + if((apps_args[0] >= 40 ) && (apps_args[0] <= 160 )) + { + logPrintf(hHal, cmd, staId, apps_args[0], apps_args[1], apps_args[2]); + } + else + { + hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160", __func__); + return 0; + } + } + break; + + case WE_MCC_CONFIG_PARAMS : + { + cmd = 288; //command Should be updated if there is any change + // in the Riva dump command + hdd_validate_mcc_config(pAdapter, staId, apps_args[0], apps_args[1],apps_args[2]); + } + break; + +#ifdef FEATURE_WLAN_TDLS + case WE_TDLS_CONFIG_PARAMS : + { + tdls_config_params_t tdlsParams; + + tdlsParams.tdls = apps_args[0]; + tdlsParams.tx_period_t = apps_args[1]; + tdlsParams.tx_packet_n = apps_args[2]; + tdlsParams.discovery_period_t = apps_args[3]; + tdlsParams.discovery_tries_n = apps_args[4]; + tdlsParams.idle_timeout_t = apps_args[5]; + tdlsParams.idle_packet_n = apps_args[6]; + tdlsParams.rssi_hysteresis = apps_args[7]; + tdlsParams.rssi_trigger_threshold = apps_args[8]; + tdlsParams.rssi_teardown_threshold = apps_args[9]; + tdlsParams.rssi_delta = apps_args[10]; + + wlan_hdd_tdls_set_params(dev, &tdlsParams); + } + break; +#endif + case WE_UNIT_TEST_CMD : + { + t_wma_unit_test_cmd *unitTestArgs; + vos_msg_t msg = {0}; + int i, j; + if ((apps_args[0] < WLAN_MODULE_ID_MIN) || + (apps_args[0] >= WLAN_MODULE_ID_MAX)) { + hddLog(LOGE, FL("Invalid MODULE ID %d"), apps_args[0]); + return -EINVAL; + } + if (apps_args[1] > (WMA_MAX_NUM_ARGS)) { + hddLog(LOGE, FL("Too Many args %d"), apps_args[1]); + return -EINVAL; + } + unitTestArgs = vos_mem_malloc(sizeof(*unitTestArgs)); + if (NULL == unitTestArgs) { + hddLog(LOGE, + FL("vos_mem_alloc failed for unitTestArgs")); + return -ENOMEM; + } + unitTestArgs->vdev_id = (int)pAdapter->sessionId; + unitTestArgs->module_id = apps_args[0]; + unitTestArgs->num_args = apps_args[1]; + for (i = 0, j = 2; i < unitTestArgs->num_args; i++, j++) { + unitTestArgs->args[i] = apps_args[j]; + } + msg.type = SIR_HAL_UNIT_TEST_CMD; + msg.reserved = 0; + msg.bodyptr = unitTestArgs; + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, + &msg)) { + vos_mem_free(unitTestArgs); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Not able to post UNIT_TEST_CMD message to WDA")); + return -EINVAL; + } + } + break; + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + case WE_LED_FLASHING_PARAM: + { + int i; + if (num_args != 5) { + hddLog(LOGE, + FL("gpio_control: 5 parameters are required")); + return -EINVAL; + } + + for (i = 0; i < num_args; i++) { + if (apps_args[i] >= 0x7fffffff) { + hddLog(LOGE, + FL("gpio_control: parameter should be less than 0x7fffffff")); + return -EINVAL; + } + } + sme_SetLedFlashing(WLAN_HDD_GET_HAL_CTX(pAdapter), + 0, apps_args[0], apps_args[1], apps_args[4]); + sme_SetLedFlashing(WLAN_HDD_GET_HAL_CTX(pAdapter), + 1, apps_args[2], apps_args[3], apps_args[4]); + } + break; +#endif + +#ifdef MEMORY_DEBUG + case WE_MEM_TRACE_DUMP: + { + int level = 0; + if (num_args >= 1) { + level = apps_args[0]; + } + vos_mem_trace_dump(level); + } + break; +#endif + default: + { + hddLog(LOGE, FL("Invalid IOCTL command %d"), sub_cmd ); + } + break; + } + EXIT(); + return 0; +} + +/** + * iw_hdd_set_var_ints_getnone() - set var ints getnone callback + * @dev: pointer to net_device structure + * @info: pointer to iw_request_info structure + * @wrqu: pointer to iwreq_data + * @extra; extra + * + * Return: 0 on success, error number otherwise + * + */ +static int iw_hdd_set_var_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + union iwreq_data u_priv_wrqu; + int apps_args[MAX_VAR_ARGS] = {0}; + int ret, num_args; + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + /* Helper function to get iwreq_data with compat handling. */ + if (hdd_priv_get_data(&u_priv_wrqu.data, wrqu)) + return -EINVAL; + + if (NULL == u_priv_wrqu.data.pointer) { + hddLog(LOGE, FL("NULL data pointer")); + return -EINVAL; + } + + num_args = u_priv_wrqu.data.length; + if (num_args > MAX_VAR_ARGS) + num_args = MAX_VAR_ARGS; + + if (copy_from_user(apps_args, u_priv_wrqu.data.pointer, + (sizeof(int)) * num_args)) { + hddLog(LOGE, FL("failed to copy data from user buffer")); + return -EFAULT; + } + + vos_ssr_protect(__func__); + ret = __iw_set_var_ints_getnone(dev, info, &u_priv_wrqu, + (char *)&apps_args); + vos_ssr_unprotect(__func__); + return ret; +} + + +int iw_set_var_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_var_ints_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + return ret; +} + + +static int __iw_add_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra; + int params[HDD_WLAN_WMM_PARAM_COUNT]; + sme_QosWmmTspecInfo tSpec; + v_U32_t handle; + struct iw_point s_priv_data; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* + * Make sure the application is sufficiently privileged + * note that the kernel will do this for "set" ioctls, but since + * this ioctl wants to return status to user space it must be + * defined as a "get" ioctl. + */ + if (!capable(CAP_NET_ADMIN)) + { + return -EPERM; + } + + // we must be associated in order to add a tspec + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + // since we are defined to be a "get" ioctl, and since the number + // of params exceeds the number of params that wireless extensions + // will pass down in the iwreq_data, we must copy the "set" params. + // We must handle the compat for iwreq_data in 32U/64K environment. + + // helper function to get iwreq_data with compat handling. + if (hdd_priv_get_data(&s_priv_data, wrqu)) { + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + // make sure all params are correctly passed to function + if ((NULL == s_priv_data.pointer) || + (HDD_WLAN_WMM_PARAM_COUNT != s_priv_data.length)) { + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + // from user space ourselves + if (copy_from_user(¶ms, s_priv_data.pointer, sizeof(params))) { + // hmmm, can't get them + return -EIO; + } + + // clear the tspec + memset(&tSpec, 0, sizeof(tSpec)); + + // validate the handle + handle = params[HDD_WLAN_WMM_PARAM_HANDLE]; + if (HDD_WMM_HANDLE_IMPLICIT == handle) + { + // that one is reserved + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + // validate the TID + if (params[HDD_WLAN_WMM_PARAM_TID] > 7) + { + // out of range + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + tSpec.ts_info.tid = params[HDD_WLAN_WMM_PARAM_TID]; + + // validate the direction + switch (params[HDD_WLAN_WMM_PARAM_DIRECTION]) + { + case HDD_WLAN_WMM_DIRECTION_UPSTREAM: + tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_UPLINK; + break; + + case HDD_WLAN_WMM_DIRECTION_DOWNSTREAM: + tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_DOWNLINK; + break; + + case HDD_WLAN_WMM_DIRECTION_BIDIRECTIONAL: + tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_BOTH; + break; + + default: + // unknown + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + tSpec.ts_info.psb = params[HDD_WLAN_WMM_PARAM_APSD]; + + // validate the user priority + if (params[HDD_WLAN_WMM_PARAM_USER_PRIORITY] >= SME_QOS_WMM_UP_MAX) + { + // out of range + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + tSpec.ts_info.up = params[HDD_WLAN_WMM_PARAM_USER_PRIORITY]; + if(0 > tSpec.ts_info.up || SME_QOS_WMM_UP_MAX < tSpec.ts_info.up) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"***ts_info.up out of bounds***"); + return 0; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "%s:TS_INFO PSB %d UP %d !!!", __func__, + tSpec.ts_info.psb, tSpec.ts_info.up); + + tSpec.nominal_msdu_size = params[HDD_WLAN_WMM_PARAM_NOMINAL_MSDU_SIZE]; + tSpec.maximum_msdu_size = params[HDD_WLAN_WMM_PARAM_MAXIMUM_MSDU_SIZE]; + tSpec.min_data_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_DATA_RATE]; + tSpec.mean_data_rate = params[HDD_WLAN_WMM_PARAM_MEAN_DATA_RATE]; + tSpec.peak_data_rate = params[HDD_WLAN_WMM_PARAM_PEAK_DATA_RATE]; + tSpec.max_burst_size = params[HDD_WLAN_WMM_PARAM_MAX_BURST_SIZE]; + tSpec.min_phy_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_PHY_RATE]; + tSpec.surplus_bw_allowance = params[HDD_WLAN_WMM_PARAM_SURPLUS_BANDWIDTH_ALLOWANCE]; + tSpec.min_service_interval = params[HDD_WLAN_WMM_PARAM_SERVICE_INTERVAL]; + tSpec.max_service_interval = params[HDD_WLAN_WMM_PARAM_MAX_SERVICE_INTERVAL]; + tSpec.suspension_interval = params[HDD_WLAN_WMM_PARAM_SUSPENSION_INTERVAL]; + tSpec.inactivity_interval = params[HDD_WLAN_WMM_PARAM_INACTIVITY_INTERVAL]; + + tSpec.ts_info.burst_size_defn = params[HDD_WLAN_WMM_PARAM_BURST_SIZE_DEFN]; + + // validate the ts info ack policy + switch (params[HDD_WLAN_WMM_PARAM_ACK_POLICY]) + { + case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK: + tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK; + break; + + case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK: + tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK; + break; + + default: + // unknown + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + *pStatus = hdd_wmm_addts(pAdapter, handle, &tSpec); + EXIT(); + return 0; +} + +static int iw_add_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_add_tspec(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_del_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int *params = (int *)extra; + hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra; + v_U32_t handle; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* + * Make sure the application is sufficiently privileged + * note that the kernel will do this for "set" ioctls, but since + * this ioctl wants to return status to user space it must be + * defined as a "get" ioctl. + */ + if (!capable(CAP_NET_ADMIN)) + { + return -EPERM; + } + + // although we are defined to be a "get" ioctl, the params we require + // will fit in the iwreq_data, therefore unlike iw_add_tspec() there + // is no need to copy the params from user space + + // validate the handle + handle = params[HDD_WLAN_WMM_PARAM_HANDLE]; + if (HDD_WMM_HANDLE_IMPLICIT == handle) + { + // that one is reserved + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + *pStatus = hdd_wmm_delts(pAdapter, handle); + EXIT(); + return 0; +} + +static int iw_del_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_del_tspec(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_get_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int *params = (int *)extra; + hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra; + v_U32_t handle; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + // although we are defined to be a "get" ioctl, the params we require + // will fit in the iwreq_data, therefore unlike iw_add_tspec() there + // is no need to copy the params from user space + + // validate the handle + handle = params[HDD_WLAN_WMM_PARAM_HANDLE]; + if (HDD_WMM_HANDLE_IMPLICIT == handle) + { + // that one is reserved + *pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + return 0; + } + + *pStatus = hdd_wmm_checkts(pAdapter, handle); + EXIT(); + return 0; +} + +static int iw_get_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_tspec(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +// +// +// Each time the supplicant has the auth_request or reassoc request +// IEs ready. This is pushed to the driver. The driver will inturn use +// it to send out the auth req and reassoc req for 11r FT Assoc. +// +static int __iw_set_fties(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!wrqu->data.length) + { + hddLog(LOGE, FL("called with 0 length IEs")); + return -EINVAL; + } + if (wrqu->data.pointer == NULL) + { + hddLog(LOGE, FL("called with NULL IE")); + return -EINVAL; + } + + // Added for debug on reception of Re-assoc Req. + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + hddLog(LOGE, FL("Called with Ie of length = %d when not associated"), + wrqu->data.length); + hddLog(LOGE, FL("Should be Re-assoc Req IEs")); + } + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + hddLog(LOG1, FL("%s called with Ie of length = %d"), __func__, wrqu->data.length); +#endif + + // Pass the received FT IEs to SME + sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, extra, + wrqu->data.length); + EXIT(); + return 0; +} + +static int iw_set_fties(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_fties(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +static int __iw_set_dynamic_mcbc_filter(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpRcvFltMcAddrList pRequest = (tpRcvFltMcAddrList)extra; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tpSirWlanSetRxpFilters wlanRxpFilterParam; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tpSirRcvFltMcAddrList mc_addr_list_ptr; + int idx; + eHalStatus ret_val; + + ENTER(); + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + if ((HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting) || + (HDD_MULTICAST_FILTER_LIST_CLEAR == pRequest->mcastBcastFilterSetting)) + { +#ifdef WLAN_FEATURE_PACKET_FILTERING + + mc_addr_list_ptr = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); + if (NULL == mc_addr_list_ptr) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -ENOMEM; + } + + mc_addr_list_ptr->ulMulticastAddrCnt = pRequest->mcast_addr_cnt; + + if (mc_addr_list_ptr->ulMulticastAddrCnt > HDD_MAX_NUM_MULTICAST_ADDRESS) + mc_addr_list_ptr->ulMulticastAddrCnt = HDD_MAX_NUM_MULTICAST_ADDRESS; + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s MC Addr List Cnt %d", __func__, + mc_addr_list_ptr->ulMulticastAddrCnt); + + for (idx = 0; idx < mc_addr_list_ptr->ulMulticastAddrCnt; idx++) + { + memcpy(&mc_addr_list_ptr->multicastAddr[idx], + pRequest->multicastAddr[idx], HDD_WLAN_MAC_ADDR_LEN); + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s MC Addr for Idx %d ="MAC_ADDRESS_STR, __func__, + idx, MAC_ADDR_ARRAY(mc_addr_list_ptr->multicastAddr[idx])); + } + + if (HDD_MULTICAST_FILTER_LIST_CLEAR == pRequest->mcastBcastFilterSetting) + mc_addr_list_ptr->action = HDD_DELETE_MCBC_FILTERS_FROM_FW; //clear + else + mc_addr_list_ptr->action = HDD_SET_MCBC_FILTERS_TO_FW; //set + + ret_val = sme_8023MulticastList(hHal, pAdapter->sessionId, mc_addr_list_ptr); + vos_mem_free(mc_addr_list_ptr); + if (eHAL_STATUS_SUCCESS != ret_val) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to Set MC Address List", + __func__); + return -EINVAL; + } +#endif //WLAN_FEATURE_PACKET_FILTERING + } + else + { + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Set MC BC Filter Config request: %d suspend %d", + __func__, pRequest->mcastBcastFilterSetting, + pHddCtx->hdd_wlan_suspended); + + pHddCtx->configuredMcastBcastFilter = pRequest->mcastBcastFilterSetting; + + if (pHddCtx->hdd_wlan_suspended) + { + wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pRequest->mcastBcastFilterSetting; + wlanRxpFilterParam->setMcstBcstFilter = TRUE; + + hdd_conf_hostoffload(pAdapter, TRUE); + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + + hddLog(VOS_TRACE_LEVEL_INFO, "%s:MC/BC changed Req %d Set %d En %d", + __func__, + pHddCtx->configuredMcastBcastFilter, + wlanRxpFilterParam->configuredMcstBcstFilterSetting, + wlanRxpFilterParam->setMcstBcstFilter); + + if (eHAL_STATUS_SUCCESS != + sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlanRxpFilterParam)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute set HW MC/BC Filter request", + __func__); + vos_mem_free(wlanRxpFilterParam); + return -EINVAL; + } + + if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) + { + pHddCtx->sus_res_mcastbcast_filter = + pRequest->mcastBcastFilterSetting; + } + } + } + EXIT(); + return 0; +} + +static int iw_set_dynamic_mcbc_filter(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_dynamic_mcbc_filter(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_clear_dynamic_mcbc_filter(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tpSirWlanSetRxpFilters wlanRxpFilterParam; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + //Reset the filter to INI value as we have to clear the dynamic filter + pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; + + //Configure FW with new setting + if (pHddCtx->hdd_wlan_suspended) + { + wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + wlanRxpFilterParam->setMcstBcstFilter = TRUE; + + hdd_conf_hostoffload(pAdapter, TRUE); + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + + if (eHAL_STATUS_SUCCESS != + sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlanRxpFilterParam)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute set HW MC/BC Filter request", + __func__); + vos_mem_free(wlanRxpFilterParam); + return -EINVAL; + } + + if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) + { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->cfg_ini->mcastBcastFilterSetting; + } + } + EXIT(); + return 0; +} + +static int iw_clear_dynamic_mcbc_filter(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_clear_dynamic_mcbc_filter(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_set_host_offload(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpHostOffloadRequest pRequest = (tpHostOffloadRequest) extra; + tSirHostOffloadReq offloadRequest; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP dev is not in CONNECTED state, ignore!!!", __func__); + return -EINVAL; + } + + /* Debug display of request components. */ + switch (pRequest->offloadType) + { + case WLAN_IPV4_ARP_REPLY_OFFLOAD: + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Host offload request: ARP reply", __func__); + switch (pRequest->enableOrDisable) + { + case WLAN_OFFLOAD_DISABLE: + hddLog(VOS_TRACE_LEVEL_WARN, " disable"); + break; + case WLAN_OFFLOAD_ARP_AND_BC_FILTER_ENABLE: + hddLog(VOS_TRACE_LEVEL_WARN, " BC Filtering enable"); + case WLAN_OFFLOAD_ENABLE: + hddLog(VOS_TRACE_LEVEL_WARN, " ARP offload enable"); + hddLog(VOS_TRACE_LEVEL_WARN, " IP address: %d.%d.%d.%d", + pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1], + pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]); + } + break; + + case WLAN_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD: + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Host offload request: neighbor discovery", + __func__); + switch (pRequest->enableOrDisable) + { + case WLAN_OFFLOAD_DISABLE: + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " disable"); + break; + case WLAN_OFFLOAD_ENABLE: + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " enable"); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " IP address: %x:%x:%x:%x:%x:%x:%x:%x", + *(v_U16_t *)(pRequest->params.hostIpv6Addr), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 2), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 4), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 6), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 8), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 10), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 12), + *(v_U16_t *)(pRequest->params.hostIpv6Addr + 14)); + } + } + + /* Execute offload request. The reason that we can copy the request information + from the ioctl structure to the SME structure is that they are laid out + exactly the same. Otherwise, each piece of information would have to be + copied individually. */ + memcpy(&offloadRequest, pRequest, wrqu->data.length); + if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offloadRequest)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute host offload request", + __func__); + return -EINVAL; + } + EXIT(); + return 0; +} + +static int iw_set_host_offload(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_host_offload(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_set_keepalive_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpSirKeepAliveReq pRequest = (tpSirKeepAliveReq) extra; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (wrqu->data.length != sizeof(*pRequest)) { + hddLog(LOGE, FL("Invalid length %d"), wrqu->data.length); + return -EINVAL; + } + + if (pRequest->timePeriod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) { + hddLog(LOGE, FL("Value of timePeriod exceed Max limit %d"), + pRequest->timePeriod); + return -EINVAL; + } + + /* Debug display of request components. */ + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Set Keep Alive Request : TimePeriod %d size %zu", + __func__, pRequest->timePeriod, sizeof(tKeepAliveRequest)); + + switch (pRequest->packetType) + { + case WLAN_KEEP_ALIVE_NULL_PKT: + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Keep Alive Request: Tx NULL", __func__); + break; + + case WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP: + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Keep Alive Request: Tx UnSolicited ARP RSP", + __func__); + + hddLog(VOS_TRACE_LEVEL_WARN, " Host IP address: %d.%d.%d.%d", + pRequest->hostIpv4Addr[0], pRequest->hostIpv4Addr[1], + pRequest->hostIpv4Addr[2], pRequest->hostIpv4Addr[3]); + + hddLog(VOS_TRACE_LEVEL_WARN, " Dest IP address: %d.%d.%d.%d", + pRequest->destIpv4Addr[0], pRequest->destIpv4Addr[1], + pRequest->destIpv4Addr[2], pRequest->destIpv4Addr[3]); + + hddLog(VOS_TRACE_LEVEL_WARN, " Dest MAC address: %d:%d:%d:%d:%d:%d", + pRequest->destMacAddr[0], pRequest->destMacAddr[1], + pRequest->destMacAddr[2], pRequest->destMacAddr[3], + pRequest->destMacAddr[4], pRequest->destMacAddr[5]); + break; + } + + hddLog(LOG1, FL("Keep alive period %d"), pRequest->timePeriod); + + if (eHAL_STATUS_SUCCESS != sme_SetKeepAlive(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, pRequest)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Keep Alive", + __func__); + return -EINVAL; + } + EXIT(); + return 0; +} + +static int iw_set_keepalive_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_keepalive_params(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, + tANI_U8 sessionId) +{ + tSirRcvPktFilterCfgType packetFilterSetReq = {0}; + tSirRcvFltPktClearParam packetFilterClrReq = {0}; + int i=0; + + if (pHddCtx->cfg_ini->disablePacketFilter) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Packet Filtering Disabled. Returning ", + __func__ ); + return 0; + } + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + /* Debug display of request components. */ + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Packet Filter Request : FA %d params %d", + __func__, pRequest->filterAction, pRequest->numParams); + + switch (pRequest->filterAction) + { + case HDD_RCV_FILTER_SET: + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set Packet Filter Request for Id: %d", + __func__, pRequest->filterId); + + packetFilterSetReq.filterId = pRequest->filterId; + if ( pRequest->numParams >= HDD_MAX_CMP_PER_PACKET_FILTER) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Number of Params exceed Max limit %d", + __func__, pRequest->numParams); + return -EINVAL; + } + packetFilterSetReq.numFieldParams = pRequest->numParams; + packetFilterSetReq.coalesceTime = 0; + packetFilterSetReq.filterType = 1; + for (i=0; i < pRequest->numParams; i++) + { + packetFilterSetReq.paramsData[i].protocolLayer = pRequest->paramsData[i].protocolLayer; + packetFilterSetReq.paramsData[i].cmpFlag = pRequest->paramsData[i].cmpFlag; + packetFilterSetReq.paramsData[i].dataOffset = pRequest->paramsData[i].dataOffset; + packetFilterSetReq.paramsData[i].dataLength = pRequest->paramsData[i].dataLength; + packetFilterSetReq.paramsData[i].reserved = 0; + + hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type %d", + pRequest->paramsData[i].protocolLayer, pRequest->paramsData[i].cmpFlag, + packetFilterSetReq.filterType); + + hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d", + pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength); + if ((sizeof(packetFilterSetReq.paramsData[i].compareData)) < + (pRequest->paramsData[i].dataLength)) + return -EINVAL; + + memcpy(&packetFilterSetReq.paramsData[i].compareData, + pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength); + memcpy(&packetFilterSetReq.paramsData[i].dataMask, + pRequest->paramsData[i].dataMask, pRequest->paramsData[i].dataLength); + + hddLog(VOS_TRACE_LEVEL_INFO, "CData %d CData %d CData %d CData %d CData %d CData %d", + pRequest->paramsData[i].compareData[0], pRequest->paramsData[i].compareData[1], + pRequest->paramsData[i].compareData[2], pRequest->paramsData[i].compareData[3], + pRequest->paramsData[i].compareData[4], pRequest->paramsData[i].compareData[5]); + + hddLog(VOS_TRACE_LEVEL_INFO, "MData %d MData %d MData %d MData %d MData %d MData %d", + pRequest->paramsData[i].dataMask[0], pRequest->paramsData[i].dataMask[1], + pRequest->paramsData[i].dataMask[2], pRequest->paramsData[i].dataMask[3], + pRequest->paramsData[i].dataMask[4], pRequest->paramsData[i].dataMask[5]); + } + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Set Filter", + __func__); + return -EINVAL; + } + + break; + + case HDD_RCV_FILTER_CLEAR: + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Clear Packet Filter Request for Id: %d", + __func__, pRequest->filterId); + packetFilterClrReq.filterId = pRequest->filterId; + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, &packetFilterClrReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter", + __func__); + return -EINVAL; + } + break; + + default : + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Packet Filter Request: Invalid %d", + __func__, pRequest->filterAction); + return -EINVAL; + } + return 0; +} + +int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, + tANI_U8 sessionId) +{ + tSirRcvPktFilterCfgType packetFilterSetReq = {0}; + tSirRcvFltPktClearParam packetFilterClrReq = {0}; + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL(" NULL HDD Context Passed")); + return -EINVAL; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + + if (pHddCtx->cfg_ini->disablePacketFilter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Packet Filtering Disabled. Returning ", + __func__ ); + return -EINVAL; + } + + switch (filterType) + { + /* For setting IPV6 MC and UC Filter we need to configure + * 2 filters, one for MC and one for UC. + * The Filter ID shouldn't be swapped, which results in making + * UC Filter ineffective. + * We have hard coded all the values + * + * Reason for a separate UC filter is because, driver need to + * specify the FW that the specific filter is for unicast + * otherwise FW will not pass the unicast frames by default + * through the filter. This is required to avoid any performance + * hits when no unicast filter is set and only MC/BC are set. + * The way driver informs host is by using the MAC protocol + * layer, CMP flag set to MAX, CMP Data set to 1. + */ + + case HDD_FILTER_IPV6_MC_UC: + /* Setting IPV6 MC Filter below + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[0].dataOffset = + WLAN_HDD_80211_FRM_DA_OFFSET; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_MC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Multicast Filter", + __func__); + return -EINVAL; + } + + memset( &packetFilterSetReq, 0, sizeof(tSirRcvPktFilterCfgType)); + + /* + * Setting IPV6 UC Filter below + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_UC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_MAX; + packetFilterSetReq.paramsData[0].dataOffset = 0; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_UC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Unicast Filter", + __func__); + return -EINVAL; + } + + break; + + case HDD_FILTER_IPV6_MC: + /* + * IPV6 UC Filter might be already set, + * clear the UC Filter. As the Filter + * IDs are static, we can directly clear it. + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterClrReq.filterId = HDD_FILTER_ID_IPV6_UC; + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, + &packetFilterClrReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Clear IPv6 Unicast Filter", + __func__); + return -EINVAL; + } + + /* + * Setting IPV6 MC Filter below + */ + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[0].dataOffset = + WLAN_HDD_80211_FRM_DA_OFFSET; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_MC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Multicast Filter", + __func__); + return -EINVAL; + } + break; + + default : + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Packet Filter Request: Invalid", + __func__); + return -EINVAL; + } + return 0; +} + +void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set) +{ + v_U8_t i; + tpSirRcvFltMcAddrList pMulticastAddrs = NULL; + tHalHandle hHal = NULL; + hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD CTX is NULL")); + return; + } + + hHal = pHddCtx->hHal; + + if (NULL == hHal) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HAL Handle is NULL")); + return; + } + + /* Check if INI is enabled or not, other wise just return + */ + if (pHddCtx->cfg_ini->fEnableMCAddrList) + { + pMulticastAddrs = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); + if (NULL == pMulticastAddrs) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Could not allocate Memory")); + return; + } + vos_mem_zero(pMulticastAddrs, sizeof(tSirRcvFltMcAddrList)); + pMulticastAddrs->action = set; + + if (set) + { + /* Following pre-conditions should be satisfied before we + * configure the MC address list. + */ + if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) + && pAdapter->mc_addr_list.mc_cnt + && (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + { + pMulticastAddrs->ulMulticastAddrCnt = + pAdapter->mc_addr_list.mc_cnt; + for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) + { + memcpy(pMulticastAddrs->multicastAddr[i], + pAdapter->mc_addr_list.addr[i], + sizeof(pAdapter->mc_addr_list.addr[i])); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: %s multicast filter: addr =" + MAC_ADDRESS_STR, + __func__, set ? "setting" : "clearing", + MAC_ADDR_ARRAY(pMulticastAddrs->multicastAddr[i])); + } + /* Set multicast filter */ + sme_8023MulticastList(hHal, pAdapter->sessionId, + pMulticastAddrs); + } + } + else + { + /* Need to clear only if it was previously configured + */ + if (pAdapter->mc_addr_list.isFilterApplied) + { + pMulticastAddrs->ulMulticastAddrCnt = + pAdapter->mc_addr_list.mc_cnt; + for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) { + memcpy(pMulticastAddrs->multicastAddr[i], + pAdapter->mc_addr_list.addr[i], + sizeof(pAdapter->mc_addr_list.addr[i])); + } + sme_8023MulticastList(hHal, pAdapter->sessionId, + pMulticastAddrs); + } + + } + /* MAddrCnt is MulticastAddrCnt */ + hddLog(VOS_TRACE_LEVEL_INFO, "smeSessionId:%d; set:%d; MCAdddrCnt :%d", + pAdapter->sessionId, set, pMulticastAddrs->ulMulticastAddrCnt); + + pAdapter->mc_addr_list.isFilterApplied = set ? TRUE : FALSE; + vos_mem_free(pMulticastAddrs); + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("gMCAddrListEnable is not enabled in INI")); + } + return; +} + +static int __iw_set_packet_filter_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpPacketFilterCfg pRequest = NULL; + int ret; + struct iw_point s_priv_data; + hdd_context_t *hdd_ctx; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (hdd_priv_get_data(&s_priv_data, wrqu)) { + return -EINVAL; + } + + if ((NULL == s_priv_data.pointer) || (0 == s_priv_data.length)) { + return -EINVAL; + } + + /* ODD number is used for set, copy data using copy_from_user */ + pRequest = mem_alloc_copy_from_user_helper(s_priv_data.pointer, + s_priv_data.length); + if (NULL == pRequest) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + ret = wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest, + pAdapter->sessionId); + kfree(pRequest); + EXIT(); + return ret; +} + +static int iw_set_packet_filter_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_packet_filter_params(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif + +static int __iw_get_statistics(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + eHalStatus status = eHAL_STATUS_SUCCESS; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + char *p = extra; + int tlen = 0; + int ret; + tCsrSummaryStatsInfo *pStats = &(pAdapter->hdd_stats.summary_stat); + tCsrGlobalClassAStatsInfo *aStats = &(pAdapter->hdd_stats.ClassA_stat); + tCsrGlobalClassDStatsInfo *dStats = &(pAdapter->hdd_stats.ClassD_stat); + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + return ret; + + if (eConnectionState_Associated != (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) { + + wrqu->txpower.value = 0; + } + else { + status = sme_GetStatistics( pHddCtx->hHal, eCSR_HDD, + SME_SUMMARY_STATS | + SME_GLOBAL_CLASSA_STATS | + SME_GLOBAL_CLASSB_STATS | + SME_GLOBAL_CLASSC_STATS | + SME_GLOBAL_CLASSD_STATS | + SME_PER_STA_STATS, + hdd_StatisticsCB, 0, FALSE, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + pAdapter, + pAdapter->sessionId ); + + if (eHAL_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve SME statistics", + __func__); + return -EINVAL; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: SME timeout while retrieving statistics", + __func__); + /*Remove the SME statistics list by passing NULL in callback argument*/ + status = sme_GetStatistics( pHddCtx->hHal, eCSR_HDD, + SME_SUMMARY_STATS | + SME_GLOBAL_CLASSA_STATS | + SME_GLOBAL_CLASSB_STATS | + SME_GLOBAL_CLASSC_STATS | + SME_GLOBAL_CLASSD_STATS | + SME_PER_STA_STATS, + NULL, 0, FALSE, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + pAdapter, + pAdapter->sessionId ); + + return -EINVAL; + } + FILL_TLV(p, (tANI_U8)WLAN_STATS_RETRY_CNT, + (tANI_U8) sizeof (pStats->retry_cnt), + (char*) &(pStats->retry_cnt[0]), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_MUL_RETRY_CNT, + (tANI_U8) sizeof (pStats->multiple_retry_cnt), + (char*) &(pStats->multiple_retry_cnt[0]), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_FRM_CNT, + (tANI_U8) sizeof (pStats->tx_frm_cnt), + (char*) &(pStats->tx_frm_cnt[0]), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_FRM_CNT, + (tANI_U8) sizeof (pStats->rx_frm_cnt), + (char*) &(pStats->rx_frm_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_FRM_DUP_CNT, + (tANI_U8) sizeof (pStats->frm_dup_cnt), + (char*) &(pStats->frm_dup_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_FAIL_CNT, + (tANI_U8) sizeof (pStats->fail_cnt), + (char*) &(pStats->fail_cnt[0]), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_FAIL_CNT, + (tANI_U8) sizeof (pStats->rts_fail_cnt), + (char*) &(pStats->rts_fail_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_ACK_FAIL_CNT, + (tANI_U8) sizeof (pStats->ack_fail_cnt), + (char*) &(pStats->ack_fail_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_SUC_CNT, + (tANI_U8) sizeof (pStats->rts_succ_cnt), + (char*) &(pStats->rts_succ_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_DISCARD_CNT, + (tANI_U8) sizeof (pStats->rx_discard_cnt), + (char*) &(pStats->rx_discard_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_ERROR_CNT, + (tANI_U8) sizeof (pStats->rx_error_cnt), + (char*) &(pStats->rx_error_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BYTE_CNT, + (tANI_U8) sizeof (dStats->tx_uc_byte_cnt[0]), + (char*) &(dStats->tx_uc_byte_cnt[0]), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BYTE_CNT, + (tANI_U8) sizeof (dStats->rx_byte_cnt), + (char*) &(dStats->rx_byte_cnt), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_RATE, + (tANI_U8) sizeof (dStats->rx_rate), + (char*) &(dStats->rx_rate), + tlen); + + /* Transmit rate, in units of 500 kbit/sec */ + FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_RATE, + (tANI_U8) sizeof (aStats->tx_rate), + (char*) &(aStats->tx_rate), + tlen); + + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_UC_BYTE_CNT, + (tANI_U8) sizeof (dStats->rx_uc_byte_cnt[0]), + (char*) &(dStats->rx_uc_byte_cnt[0]), + tlen); + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_MC_BYTE_CNT, + (tANI_U8) sizeof (dStats->rx_mc_byte_cnt), + (char*) &(dStats->rx_mc_byte_cnt), + tlen); + FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BC_BYTE_CNT, + (tANI_U8) sizeof (dStats->rx_bc_byte_cnt), + (char*) &(dStats->rx_bc_byte_cnt), + tlen); + FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_UC_BYTE_CNT, + (tANI_U8) sizeof (dStats->tx_uc_byte_cnt[0]), + (char*) &(dStats->tx_uc_byte_cnt[0]), + tlen); + FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_MC_BYTE_CNT, + (tANI_U8) sizeof (dStats->tx_mc_byte_cnt), + (char*) &(dStats->tx_mc_byte_cnt), + tlen); + FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BC_BYTE_CNT, + (tANI_U8) sizeof (dStats->tx_bc_byte_cnt), + (char*) &(dStats->tx_bc_byte_cnt), + tlen); + + wrqu->data.length = tlen; + + } + + EXIT(); + + return 0; +} + +static int iw_get_statistics(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_get_statistics(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +#ifdef FEATURE_WLAN_SCAN_PNO + +/*Max Len for PNO notification*/ +#define MAX_PNO_NOTIFY_LEN 100 +void found_pref_network_cb (void *callbackContext, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext; + union iwreq_data wrqu; + char buf[MAX_PNO_NOTIFY_LEN+1]; + + hddLog(VOS_TRACE_LEVEL_WARN, "A preferred network was found: %s with rssi: -%d", + pPrefNetworkFoundInd->ssId.ssId, pPrefNetworkFoundInd->rssi); + + // create the event + memset(&wrqu, 0, sizeof(wrqu)); + memset(buf, 0, sizeof(buf)); + + snprintf(buf, MAX_PNO_NOTIFY_LEN, "QCOM: Found preferred network: %s with RSSI of -%u", + pPrefNetworkFoundInd->ssId.ssId, + (unsigned int)pPrefNetworkFoundInd->rssi); + + wrqu.data.pointer = buf; + wrqu.data.length = strlen(buf); + + // send the event + + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); + +} + + +/*string based input*/ +int iw_set_pno(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, int nOffset) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + /* pnoRequest is a large struct, so we make it static to avoid stack + overflow. This API is only invoked via ioctl, so it is + serialized by the kernel rtnl_lock and hence does not need to be + reentrant */ + static tSirPNOScanReq pnoRequest; + char *ptr; + v_U8_t i,j, ucParams, ucMode; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO data len %d data %s", + wrqu->data.length, + extra); + + if (wrqu->data.length <= nOffset ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "PNO input is not correct"); + return -EINVAL; + } + + pnoRequest.enable = 0; + pnoRequest.ucNetworksCount = 0; + /*----------------------------------------------------------------------- + Input is string based and expected to be like this: + + + for each network: + + + + + e.g: + 1 2 4 test 0 0 3 1 6 11 2 40 5 test2 4 4 6 1 2 3 4 5 6 1 0 2 5 2 300 0 + + this translates into: + ----------------------------- + enable PNO + look for 2 networks: + test - with authentication type 0 and encryption type 0, + that can be found on 3 channels: 1 6 and 11 , + SSID bcast type is unknown (directed probe will be sent if AP not found) + and must meet -40dBm RSSI + + test2 - with auth and encryption type 4/4 + that can be found on 6 channels 1, 2, 3, 4, 5 and 6 + bcast type is non-bcast (directed probe will be sent) + and must not meet any RSSI threshold + + scan every 5 seconds 2 times, scan every 300 seconds until stopped + -----------------------------------------------------------------------*/ + ptr = extra + nOffset; + + if (1 != sscanf(ptr,"%hhu%n", &(pnoRequest.enable), &nOffset)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PNO enable input is not valid %s",ptr); + return -EINVAL; + } + + if ( 0 == pnoRequest.enable ) + { + /*Disable PNO*/ + memset(&pnoRequest, 0, sizeof(pnoRequest)); + sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest, + pAdapter->sessionId, + found_pref_network_cb, pAdapter); + return 0; + } + + ptr += nOffset; + + if (1 != sscanf(ptr,"%hhu %n", &(pnoRequest.ucNetworksCount), &nOffset)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PNO count input not valid %s",ptr); + return -EINVAL; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO enable %d networks count %d offset %d", + pnoRequest.enable, + pnoRequest.ucNetworksCount, + nOffset); + + /* Parameters checking: + ucNetworksCount has to be larger than 0*/ + if (( 0 == pnoRequest.ucNetworksCount ) || + ( pnoRequest.ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS )) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Network input is not correct"); + return -EINVAL; + } + + ptr += nOffset; + + for ( i = 0; i < pnoRequest.ucNetworksCount; i++ ) + { + + pnoRequest.aNetworks[i].ssId.length = 0; + + ucParams = sscanf(ptr,"%hhu %n", + &(pnoRequest.aNetworks[i].ssId.length),&nOffset); + + if (1 != ucParams) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PNO ssid length input is not valid %s",ptr); + return -EINVAL; + } + + if (( 0 == pnoRequest.aNetworks[i].ssId.length ) || + ( pnoRequest.aNetworks[i].ssId.length > 32 ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "SSID Len %d is not correct for network %d", + pnoRequest.aNetworks[i].ssId.length, i); + return -EINVAL; + } + + /*Advance to SSID*/ + ptr += nOffset; + + memcpy(pnoRequest.aNetworks[i].ssId.ssId, ptr, + pnoRequest.aNetworks[i].ssId.length); + ptr += pnoRequest.aNetworks[i].ssId.length; + + ucParams = sscanf(ptr,"%u %u %hhu %n", + &(pnoRequest.aNetworks[i].authentication), + &(pnoRequest.aNetworks[i].encryption), + &(pnoRequest.aNetworks[i].ucChannelCount), + &nOffset); + + if ( 3 != ucParams ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "Incorrect cmd %s",ptr); + return -EINVAL; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO len %d ssid 0x%08x%08x%08x%08x%08x%08x%08x%08x" + "auth %d encry %d channel count %d offset %d", + pnoRequest.aNetworks[i].ssId.length, + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[0]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[4]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[8]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[12]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[16]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[20]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[24]), + *((v_U32_t *) &pnoRequest.aNetworks[i].ssId.ssId[28]), + pnoRequest.aNetworks[i].authentication, + pnoRequest.aNetworks[i].encryption, + pnoRequest.aNetworks[i].ucChannelCount, + nOffset ); + + /*Advance to channel list*/ + ptr += nOffset; + + if (SIR_PNO_MAX_NETW_CHANNELS < pnoRequest.aNetworks[i].ucChannelCount) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "Incorrect number of channels"); + return -EINVAL; + } + + if ( 0 != pnoRequest.aNetworks[i].ucChannelCount) + { + for ( j = 0; j < pnoRequest.aNetworks[i].ucChannelCount; j++) + { + if (1 != sscanf(ptr,"%hhu %n", + &(pnoRequest.aNetworks[i].aChannels[j]), + &nOffset)) + { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PNO network channel input is not valid %s",ptr); + return -EINVAL; + } + /*Advance to next channel number*/ + ptr += nOffset; + } + } + + if (1 != sscanf(ptr,"%u %n", + &(pnoRequest.aNetworks[i].bcastNetwType), + &nOffset)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PNO broadcast network type input is not valid %s",ptr); + return -EINVAL; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO bcastNetwType %d offset %d", + pnoRequest.aNetworks[i].bcastNetwType, + nOffset ); + + /*Advance to rssi Threshold*/ + ptr += nOffset; + if (1 != sscanf(ptr,"%d %n", + &(pnoRequest.aNetworks[i].rssiThreshold), + &nOffset)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PNO rssi threshold input is not valid %s",ptr); + return -EINVAL; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO rssi %d offset %d", + pnoRequest.aNetworks[i].rssiThreshold, + nOffset ); + /*Advance to next network*/ + ptr += nOffset; + }/*For ucNetworkCount*/ + + ucParams = sscanf(ptr,"%hhu %n",&(ucMode), &nOffset); + + pnoRequest.modePNO = ucMode; + /*for LA we just expose suspend option*/ + if (( 1 != ucParams )||( ucMode >= SIR_PNO_MODE_MAX )) + { + pnoRequest.modePNO = SIR_PNO_MODE_ON_SUSPEND; + } + + sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest, + pAdapter->sessionId, + found_pref_network_cb, pAdapter); + + return 0; +}/*iw_set_pno*/ + +static int __iw_set_pno_priv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + VOS_STATUS status; + + ENTER(); + + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + status = iw_set_pno(dev,info,wrqu,extra,0); + + EXIT(); + return status; +} + +static int iw_set_pno_priv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_pno_priv(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif /*FEATURE_WLAN_SCAN_PNO*/ + +//Common function to SetBand +int hdd_setBand(struct net_device *dev, u8 ui_band) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + eCsrBand band; + + VOS_STATUS status; + hdd_context_t *pHddCtx; + hdd_adapter_list_node_t *pAdapterNode, *pNext; + eCsrBand currBand = eCSR_BAND_MAX; + eCsrBand connectedBand; + + ENTER(); + + pAdapterNode = NULL; + pNext = NULL; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + switch(ui_band) + { + case WLAN_HDD_UI_BAND_AUTO: + band = eCSR_BAND_ALL; + break; + case WLAN_HDD_UI_BAND_5_GHZ: + band = eCSR_BAND_5G; + break; + case WLAN_HDD_UI_BAND_2_4_GHZ: + band = eCSR_BAND_24; + break; + default: + band = eCSR_BAND_MAX; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change band to %u", + __func__, band); + + if (band == eCSR_BAND_MAX) + { + /* Received change band request with invalid band value */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid band value %u", __func__, ui_band); + return -EINVAL; + } + + if ((band == eCSR_BAND_24 && pHddCtx->cfg_ini->nBandCapability == 2) || + (band == eCSR_BAND_5G && pHddCtx->cfg_ini->nBandCapability == 1)) { + hddLog(LOGP, FL("band value %u violate INI settings %u"), + band, pHddCtx->cfg_ini->nBandCapability); + return -EIO; + } + + if (band == eCSR_BAND_ALL) { + hddLog(LOG1, + FL("Auto band received. Setting band same as ini value %d"), + pHddCtx->cfg_ini->nBandCapability); + band = pHddCtx->cfg_ini->nBandCapability; + } + + if (eHAL_STATUS_SUCCESS != sme_GetFreqBand(hHal, &currBand)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Failed to get current band config", + __func__); + return -EIO; + } + + if (currBand != band) + { + /* Change band request received. + * Abort pending scan requests, flush the existing scan results, + * and change the band capability + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Current band value = %u, new setting %u ", + __func__, currBand, band); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE); + connectedBand = + hdd_connGetConnectedBand(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)); + + /* Handling is done only for STA and P2P */ + if ( band != eCSR_BAND_ALL && + ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) && + (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) && + (connectedBand != band)) + { + eHalStatus status = eHAL_STATUS_SUCCESS; + long lrc; + + /* STA already connected on current band, So issue disconnect + * first, then change the band */ + + hddLog(LOG1, + FL("STA Device mode %s(%d) connected band %u, Changing band to %u, Issuing Disconnect"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, currBand, band); + + INIT_COMPLETION(pAdapter->disconnect_comp_var); + + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + + if ( eHAL_STATUS_SUCCESS != status) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s csrRoamDisconnect failure, returned %d", + __func__, (int)status ); + return -EINVAL; + } + + lrc = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + + if (lrc == 0) { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Timeout while waiting for csrRoamDisconnect", + __func__); + return -ETIMEDOUT ; + } + } + + sme_ScanFlushResult(hHal, pAdapter->sessionId); + + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + if (eHAL_STATUS_SUCCESS != sme_SetFreqBand(hHal, pAdapter->sessionId, + band)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + FL("Failed to set the band value to %u"), band); + return -EINVAL; + } + wlan_hdd_cfg80211_update_band(pHddCtx->wiphy, (eCsrBand)band); + } + EXIT(); + return 0; +} + +int hdd_setBand_helper(struct net_device *dev, const char *command) +{ + u8 band; + int ret; + + /* Convert the band value from ascii to integer */ + command += WLAN_HDD_UI_SET_BAND_VALUE_OFFSET; + ret = kstrtou8(command, 10, &band); + if (ret < 0) { + hddLog(LOGE, FL("kstrtou8 failed")); + return -EINVAL; + } + + return hdd_setBand(dev, band); +} + +static int __iw_set_band_config(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int *value = (int *)extra; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + return hdd_setBand(dev, value[0]); +} + +static int iw_set_band_config(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_band_config(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_set_power_params_priv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + char *ptr; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + /* ODD number is used for set, copy data using copy_from_user */ + ptr = mem_alloc_copy_from_user_helper(wrqu->data.pointer, + wrqu->data.length); + if (NULL == ptr) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + ret = iw_set_power_params(dev, info, wrqu, ptr, 0); + kfree(ptr); + EXIT(); + return ret; +} + +static int iw_set_power_params_priv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_power_params_priv(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + + +/*string based input*/ +VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, int nOffset) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tSirSetPowerParamsReq powerRequest; + char *ptr; + v_U8_t ucType; + v_U32_t uTotalSize, uValue; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Power Params data len %d data %s", + wrqu->data.length, + extra); + + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + + if (wrqu->data.length <= nOffset ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "set power param input is not correct"); + return VOS_STATUS_E_FAILURE; + } + + uTotalSize = wrqu->data.length - nOffset; + + /*----------------------------------------------------------------------- + Input is string based and expected to be like this: + + ... + + e.g: + 1 2 2 3 3 0 4 1 5 1 + + e.g. setting just a few: + 1 2 4 1 + + parameter types: + ----------------------------- + 1 - Ignore DTIM + 2 - Listen Interval + 3 - Broadcast Multicast Filter + 4 - Beacon Early Termination + 5 - Beacon Early Termination Interval + -----------------------------------------------------------------------*/ + powerRequest.uIgnoreDTIM = SIR_NOCHANGE_POWER_VALUE; + powerRequest.uListenInterval = SIR_NOCHANGE_POWER_VALUE; + powerRequest.uBcastMcastFilter = SIR_NOCHANGE_POWER_VALUE; + powerRequest.uEnableBET = SIR_NOCHANGE_POWER_VALUE; + powerRequest.uBETInterval = SIR_NOCHANGE_POWER_VALUE; + + ptr = extra + nOffset; + + while ( uTotalSize ) + { + if (1 != sscanf(ptr,"%hhu %n", &(ucType), &nOffset)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid input parameter type %s",ptr); + return VOS_STATUS_E_FAILURE; + } + + uTotalSize -= nOffset; + + if (!uTotalSize) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid input parameter type : %d with no value at offset %d", + ucType, nOffset); + return VOS_STATUS_E_FAILURE; + } + + ptr += nOffset; + + if (1 != sscanf(ptr,"%u %n", &(uValue), &nOffset)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid input parameter value %s",ptr); + return VOS_STATUS_E_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Power request parameter %d value %d offset %d", + ucType, uValue, nOffset); + + switch (ucType) + { + case eSIR_IGNORE_DTIM: + powerRequest.uIgnoreDTIM = uValue; + break; + case eSIR_LISTEN_INTERVAL: + powerRequest.uListenInterval = uValue; + break; + case eSIR_MCAST_BCAST_FILTER: + powerRequest.uBcastMcastFilter = uValue; + break; + case eSIR_ENABLE_BET: + powerRequest.uEnableBET = uValue; + break; + case eSIR_BET_INTERVAL: + powerRequest.uBETInterval = uValue; + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid input parameter type : %d with value: %d at offset %d", + ucType, uValue, nOffset); + return VOS_STATUS_E_FAILURE; + } + + uTotalSize -= nOffset; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Power request parameter %d Total size", + uTotalSize); + ptr += nOffset; + /* This is added for dynamic Tele LI enable (0xF1) /disable (0xF0)*/ + if(!(uTotalSize - nOffset) && + (powerRequest.uListenInterval != SIR_NOCHANGE_POWER_VALUE)) + { + uTotalSize = 0; + } + + }/*Go for as long as we have a valid string*/ + + /* put the device into full power*/ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); + + /* Apply the power save params*/ + sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); + + /* put the device back to power save*/ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + + return VOS_STATUS_SUCCESS; +}/*iw_set_power_params*/ + +static int __iw_set_two_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int *value = (int *)extra; + int sub_cmd = value[0]; + int ret; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch(sub_cmd) { + case WE_SET_SMPS_PARAM: + hddLog(LOG1, "WE_SET_SMPS_PARAM val %d %d", value[1], value[2]); + ret = process_wma_set_command((int)pAdapter->sessionId, + (int)WMI_STA_SMPS_PARAM_CMDID, + value[1] << WMA_SMPS_PARAM_VALUE_S | value[2], VDEV_CMD); + break; +#ifdef DEBUG + case WE_SET_FW_CRASH_INJECT: + hddLog(LOGE, "WE_SET_FW_CRASH_INJECT: %d %d", value[1], value[2]); + pr_err("SSR is triggered by iwpriv CRASH_INJECT: %d %d\n", + value[1], value[2]); + if (!hdd_ctx->cfg_ini->crash_inject_enabled) { + hddLog(LOGE, "Crash Inject ini disabled, Ignore Crash Inject"); + return 0; + } + ret = process_wma_set_command_twoargs((int) pAdapter->sessionId, + (int) GEN_PARAM_CRASH_INJECT, + value[1], value[2], GEN_CMD); + break; +#endif + default: + hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); + break; + } + + return ret; +} + +static int iw_set_two_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_set_two_ints_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + +// Define the Wireless Extensions to the Linux Network Device structure +// A number of these routines are NULL (meaning they are not implemented.) + +static const iw_handler we_handler[] = +{ + (iw_handler) iw_set_commit, /* SIOCSIWCOMMIT */ + (iw_handler) iw_get_name, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) iw_set_freq, /* SIOCSIWFREQ */ + (iw_handler) iw_get_freq, /* SIOCGIWFREQ */ + (iw_handler) iw_set_mode, /* SIOCSIWMODE */ + (iw_handler) iw_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) iw_get_range, /* SIOCGIWRANGE */ + (iw_handler) iw_set_priv, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) iw_set_ap_address, /* SIOCSIWAP */ + (iw_handler) iw_get_ap_address, /* SIOCGIWAP */ + (iw_handler) iw_set_mlme, /* SIOCSIWMLME */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ + (iw_handler) iw_set_scan, /* SIOCSIWSCAN */ + (iw_handler) iw_get_scan, /* SIOCGIWSCAN */ + (iw_handler) iw_set_essid, /* SIOCSIWESSID */ + (iw_handler) iw_get_essid, /* SIOCGIWESSID */ + (iw_handler) iw_set_nick, /* SIOCSIWNICKN */ + (iw_handler) iw_get_nick, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) iw_set_bitrate, /* SIOCSIWRATE */ + (iw_handler) iw_get_bitrate, /* SIOCGIWRATE */ + (iw_handler) iw_set_rts_threshold,/* SIOCSIWRTS */ + (iw_handler) iw_get_rts_threshold,/* SIOCGIWRTS */ + (iw_handler) iw_set_frag_threshold, /* SIOCSIWFRAG */ + (iw_handler) iw_get_frag_threshold, /* SIOCGIWFRAG */ + (iw_handler) iw_set_tx_power, /* SIOCSIWTXPOW */ + (iw_handler) iw_get_tx_power, /* SIOCGIWTXPOW */ + (iw_handler) iw_set_retry, /* SIOCSIWRETRY */ + (iw_handler) iw_get_retry, /* SIOCGIWRETRY */ + (iw_handler) iw_set_encode, /* SIOCSIWENCODE */ + (iw_handler) iw_get_encode, /* SIOCGIWENCODE */ + (iw_handler) iw_set_power_mode, /* SIOCSIWPOWER */ + (iw_handler) iw_get_power_mode, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) iw_set_genie, /* SIOCSIWGENIE */ + (iw_handler) iw_get_genie, /* SIOCGIWGENIE */ + (iw_handler) iw_set_auth, /* SIOCSIWAUTH */ + (iw_handler) iw_get_auth, /* SIOCGIWAUTH */ + (iw_handler) iw_set_encodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) iw_get_encodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL, /* SIOCSIWPMKSA */ +}; + +static const iw_handler we_private[] = { + + [WLAN_PRIV_SET_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_setint_getnone, //set priv ioctl + [WLAN_PRIV_SET_NONE_GET_INT - SIOCIWFIRSTPRIV] = iw_setnone_getint, //get priv ioctl + [WLAN_PRIV_SET_CHAR_GET_NONE - SIOCIWFIRSTPRIV] = iw_setchar_getnone, //get priv ioctl + [WLAN_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone, + [WLAN_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_get_char_setnone, + [WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, //action priv ioctl + [WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_hdd_set_var_ints_getnone, + [WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] = iw_setnone_get_threeint, + [WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec, + [WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec, + [WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec, + +#ifdef WLAN_FEATURE_VOWIFI_11R + [WLAN_PRIV_SET_FTIES - SIOCIWFIRSTPRIV] = iw_set_fties, +#endif + [WLAN_PRIV_SET_HOST_OFFLOAD - SIOCIWFIRSTPRIV] = iw_set_host_offload, + [WLAN_GET_WLAN_STATISTICS - SIOCIWFIRSTPRIV] = iw_get_statistics, + [WLAN_SET_KEEPALIVE_PARAMS - SIOCIWFIRSTPRIV] = iw_set_keepalive_params +#ifdef WLAN_FEATURE_PACKET_FILTERING + , + [WLAN_SET_PACKET_FILTER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_packet_filter_params +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + , + [WLAN_SET_PNO - SIOCIWFIRSTPRIV] = iw_set_pno_priv +#endif + , + [WLAN_SET_BAND_CONFIG - SIOCIWFIRSTPRIV] = iw_set_band_config, + [WLAN_PRIV_SET_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_set_dynamic_mcbc_filter, + [WLAN_PRIV_CLEAR_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_clear_dynamic_mcbc_filter, + [WLAN_SET_POWER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_power_params_priv, + [WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed_priv, + [WLAN_PRIV_SET_TWO_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_two_ints_getnone, + [WLAN_SET_DOT11P_CHANNEL_SCHED - SIOCIWFIRSTPRIV] = iw_set_dot11p_channel_sched, +}; + +/*Maximum command length can be only 15 */ +static const struct iw_priv_args we_private_args[] = { + + /* handlers for main ioctl */ + { WLAN_PRIV_SET_INT_GET_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "" }, + + /* handlers for sub-ioctl */ + { WE_SET_11D_STATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set11Dstate" }, + + { WE_WOWL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "wowl" }, + + { WE_SET_POWER, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setPower" }, + + { WE_SET_MAX_ASSOC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setMaxAssoc" }, + + { WE_SET_SAP_AUTO_CHANNEL_SELECTION, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setAutoChannel" }, + + { WE_SET_DATA_INACTIVITY_TO, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "inactivityTO" }, + + { WE_SET_MAX_TX_POWER, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setMaxTxPower" }, + + { WE_SET_TX_POWER, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setTxPower" }, + + { WE_SET_MC_RATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setMcRate" }, + + { WE_SET_MAX_TX_POWER_2_4, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setTxMaxPower2G" }, + + { WE_SET_MAX_TX_POWER_5_0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setTxMaxPower5G" }, + + /* SAP has TxMax whereas STA has MaxTx, adding TxMax for STA + * as well to keep same syntax as in SAP. Now onwards, STA + * will support both */ + { WE_SET_MAX_TX_POWER, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setTxMaxPower" }, + + /* set Higher DTIM Transition (DTIM1 to DTIM3) + * 1 = enable and 0 = disable */ + { + WE_SET_HIGHER_DTIM_TRANSITION, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setHDtimTransn" }, + + { WE_SET_TM_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setTmLevel" }, + + { WE_SET_PHYMODE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "setphymode" }, + + { WE_SET_NSS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "nss" }, + + { WE_SET_LDPC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "ldpc" }, + + { WE_SET_TX_STBC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "tx_stbc" }, + + { WE_SET_RX_STBC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "rx_stbc" }, + + { WE_SET_SHORT_GI, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "shortgi" }, + + { WE_SET_RTSCTS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "enablertscts" }, + + { WE_SET_CHWIDTH, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "chwidth" }, + + { WE_SET_ANI_EN_DIS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "anienable" }, + + { WE_SET_ANI_POLL_PERIOD, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "aniplen" }, + + { WE_SET_ANI_LISTEN_PERIOD, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "anilislen" }, + + { WE_SET_ANI_OFDM_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "aniofdmlvl" }, + + { WE_SET_ANI_CCK_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "aniccklvl" }, + + { WE_SET_DYNAMIC_BW, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "cwmenable" }, + + { WE_SET_CTS_CBW, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "cts_cbw" }, + + { WE_SET_GTX_HT_MCS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxHTMcs" }, + + { WE_SET_GTX_VHT_MCS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxVHTMcs" }, + + { WE_SET_GTX_USRCFG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxUsrCfg" }, + + { WE_SET_GTX_THRE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxThre" }, + + { WE_SET_GTX_MARGIN, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxMargin" }, + + { WE_SET_GTX_STEP, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxStep" }, + + { WE_SET_GTX_MINTPC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxMinTpc" }, + + { WE_SET_GTX_BWMASK, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "gtxBWMask" }, + + { WE_SET_TX_CHAINMASK, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "txchainmask" }, + + { WE_SET_RX_CHAINMASK, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "rxchainmask" }, + + { WE_SET_11N_RATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set11NRates" }, + + { WE_SET_VHT_RATE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set11ACRates" }, + + { WE_SET_AMPDU, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "ampdu" }, + + { WE_SET_AMSDU, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "amsdu" }, + + { WE_SET_BURST_ENABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "burst_enable" }, + + { WE_SET_BURST_DUR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "burst_dur" }, + + { WE_SET_TXPOW_2G, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "txpow2g" }, + + { WE_SET_TXPOW_5G, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "txpow5g" }, + + /* Sub-cmds DBGLOG specific commands */ + { WE_DBGLOG_LOG_LEVEL , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_loglevel" }, + + { WE_DBGLOG_VAP_ENABLE , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_vapon" }, + + { WE_DBGLOG_VAP_DISABLE , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_vapoff" }, + + { WE_DBGLOG_MODULE_ENABLE , + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_modon" }, + + { WE_DBGLOG_MODULE_DISABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_modoff" }, + + { WE_DBGLOG_MOD_LOG_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_mod_loglevel" }, + + { WE_DBGLOG_TYPE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_type" }, + { WE_DBGLOG_REPORT_ENABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dl_report" }, + + { WE_SET_TXRX_FWSTATS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "txrx_fw_stats" }, + + { WE_TXRX_FWSTATS_RESET, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "txrx_fw_st_rst" }, + + { WE_PPS_PAID_MATCH, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "paid_match" }, + + + { WE_PPS_GID_MATCH, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "gid_match" }, + + + { WE_PPS_EARLY_TIM_CLEAR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "tim_clear" }, + + + { WE_PPS_EARLY_DTIM_CLEAR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "dtim_clear" }, + + + { WE_PPS_EOF_PAD_DELIM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "eof_delim" }, + + + { WE_PPS_MACADDR_MISMATCH, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "mac_match" }, + + + { WE_PPS_DELIM_CRC_FAIL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "delim_fail" }, + + + { WE_PPS_GID_NSTS_ZERO, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "nsts_zero" }, + + + { WE_PPS_RSSI_CHECK, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "rssi_chk" }, + + { WE_PPS_5G_EBT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "5g_ebt" }, + + { WE_SET_HTSMPS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "htsmps" }, + + + { WE_SET_QPOWER_MAX_PSPOLL_COUNT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qpspollcnt" }, + + { WE_SET_QPOWER_MAX_TX_BEFORE_WAKE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qtxwake" }, + + { WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qwakeintv" }, + + { WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_qnodatapoll" }, + + /* handlers for MCC time quota and latency sub ioctls */ + { WE_MCC_CONFIG_LATENCY, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setMccLatency" }, + + { WE_MCC_CONFIG_QUOTA, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setMccQuota" }, + + { WE_SET_DEBUG_LOG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setDbgLvl" }, + + { WE_SET_SCAN_BAND_PREFERENCE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_scan_pref" }, + /* handlers for early_rx power save */ + { WE_SET_EARLY_RX_ADJUST_ENABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_enable" }, + + { WE_SET_EARLY_RX_TGT_BMISS_NUM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_bmiss_val" }, + + { WE_SET_EARLY_RX_BMISS_SAMPLE_CYCLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_bmiss_smpl" }, + + { WE_SET_EARLY_RX_SLOP_STEP, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_slop_step" }, + + { WE_SET_EARLY_RX_INIT_SLOP, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_init_slop" }, + + { WE_SET_EARLY_RX_ADJUST_PAUSE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_adj_pause" }, + + { WE_SET_EARLY_RX_DRIFT_SAMPLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "erx_dri_sample" }, + + { WLAN_PRIV_SET_NONE_GET_INT, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "" }, + + { WE_DUMP_STATS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "dumpStats" }, + + { WE_CLEAR_STATS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "clearStats" }, + + { WE_SET_CHANNEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setChanChange" }, + + /* handlers for sub-ioctl */ + { WE_GET_11D_STATE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get11Dstate" }, + + { WE_IBSS_STATUS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getAdhocStatus" }, + + { WE_GET_WLAN_DBG, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getwlandbg" }, + + { WE_GET_MAX_ASSOC, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getMaxAssoc" }, + + { WE_GET_SAP_AUTO_CHANNEL_SELECTION, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getAutoChannel" }, + + { WE_GET_CONCURRENCY_MODE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getconcurrency" }, + + { WE_GET_NSS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_nss" }, + + { WE_GET_LDPC, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_ldpc" }, + + { WE_GET_TX_STBC, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_tx_stbc" }, + + { WE_GET_RX_STBC, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_rx_stbc" }, + + { WE_GET_SHORT_GI, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_shortgi" }, + + { WE_GET_RTSCTS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_rtscts" }, + + { WE_GET_CHWIDTH, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_chwidth" }, + + { WE_GET_ANI_EN_DIS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_anienable" }, + + { WE_GET_ANI_POLL_PERIOD, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_aniplen" }, + + { WE_GET_ANI_LISTEN_PERIOD, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_anilislen" }, + + { WE_GET_ANI_OFDM_LEVEL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_aniofdmlvl" }, + + { WE_GET_ANI_CCK_LEVEL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_aniccklvl" }, + + { WE_GET_DYNAMIC_BW, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_cwmenable" }, + + { WE_GET_GTX_HT_MCS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxHTMcs" }, + + { WE_GET_GTX_VHT_MCS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxVHTMcs" }, + + { WE_GET_GTX_USRCFG, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxUsrCfg" }, + + { WE_GET_GTX_THRE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxThre" }, + + { WE_GET_GTX_MARGIN, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxMargin" }, + + { WE_GET_GTX_STEP, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxStep" }, + + { WE_GET_GTX_MINTPC, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxMinTpc" }, + + { WE_GET_GTX_BWMASK, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gtxBWMask" }, + + { WE_GET_TX_CHAINMASK, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_txchainmask" }, + + { WE_GET_RX_CHAINMASK, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_rxchainmask" }, + + { WE_GET_11N_RATE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_11nrate" }, + + { WE_GET_AMPDU, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_ampdu" }, + + { WE_GET_AMSDU, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_amsdu" }, + + { WE_GET_BURST_ENABLE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_burst_en" }, + + { WE_GET_BURST_DUR, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_burst_dur" }, + + { WE_GET_TXPOW_2G, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_txpow2g" }, + + { WE_GET_TXPOW_5G, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_txpow5g" }, + + { WE_GET_PPS_PAID_MATCH, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_paid_match"}, + + + { WE_GET_PPS_GID_MATCH, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_gid_match"}, + + + { WE_GET_PPS_EARLY_TIM_CLEAR, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_tim_clear"}, + + + { WE_GET_PPS_EARLY_DTIM_CLEAR, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_dtim_clear"}, + + + { WE_GET_PPS_EOF_PAD_DELIM, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_eof_delim"}, + + + { WE_GET_PPS_MACADDR_MISMATCH, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_mac_match"}, + + + { WE_GET_PPS_DELIM_CRC_FAIL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_delim_fail"}, + + + { WE_GET_PPS_GID_NSTS_ZERO, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_nsts_zero"}, + + + { WE_GET_PPS_RSSI_CHECK, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_rssi_chk"}, + + { WE_GET_QPOWER_MAX_PSPOLL_COUNT, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qpspollcnt"}, + + { WE_GET_QPOWER_MAX_TX_BEFORE_WAKE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qtxwake"}, + + { WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qwakeintv"}, + + { WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_qnodatapoll"}, + + { WE_GET_SCAN_BAND_PREFERENCE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_scan_pref"}, + + { WE_GET_TEMPERATURE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_temp"}, + + { WE_GET_FW_STATUS, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_fwstate"}, +#ifdef WLAN_FEATURE_TSF + { WE_CAP_TSF, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "cap_tsf"}, +#endif + /* handlers for main ioctl */ + { WLAN_PRIV_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" }, + +#if defined WLAN_FEATURE_VOWIFI + /* handlers for sub-ioctl */ + { WE_NEIGHBOR_REPORT_REQUEST, + IW_PRIV_TYPE_CHAR | 512, + 0, + "neighbor" }, +#endif + { WE_SET_AP_WPS_IE, + IW_PRIV_TYPE_CHAR| 512, + 0, + "set_ap_wps_ie" }, + + { WE_SET_CONFIG, + IW_PRIV_TYPE_CHAR| 512, + 0, + "setConfig" }, + + /* handlers for main ioctl */ + { WLAN_PRIV_SET_THREE_INT_GET_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "" }, + + /* handlers for sub-ioctl */ + { WE_SET_WLAN_DBG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "setwlandbg" }, + + { WE_SET_SAP_CHANNELS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "setsapchannels" }, + + /* 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 + /* handlers for main ioctl */ + { WLAN_PRIV_GET_CHAR_SET_NONE, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "" }, + + /* handlers for sub-ioctl */ + { WE_WLAN_VERSION, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "version" }, + { WE_GET_STATS, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getStats" }, + { WE_GET_STATES, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getHostStates" }, + { WE_GET_CFG, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getConfig" }, +#ifdef WLAN_FEATURE_11AC + { WE_GET_RSSI, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getRSSI" }, +#endif + { WE_GET_WMM_STATUS, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getWmmStatus" }, + { + WE_GET_CHANNEL_LIST, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getChannelList" }, +#ifdef FEATURE_WLAN_TDLS + { + WE_GET_TDLS_PEERS, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getTdlsPeers" }, +#endif +#ifdef WLAN_FEATURE_11W + { + WE_GET_11W_INFO, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getPMFInfo" }, +#endif + { WE_GET_PHYMODE, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getphymode" }, +#ifdef FEATURE_OEM_DATA_SUPPORT + { WE_GET_OEM_DATA_CAP, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getOemDataCap" }, +#endif /* FEATURE_OEM_DATA_SUPPORT */ + { WE_GET_SNR, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getSNR" }, + + /* handlers for main ioctl */ + { WLAN_PRIV_SET_NONE_GET_NONE, + 0, + 0, + "" }, + + /* handlers for sub-ioctl */ + { WE_GET_RECOVERY_STAT, + 0, + 0, + "getRecoverStat" }, + { WE_ENABLE_DXE_STALL_DETECT, + 0, + 0, + "dxeStallDetect" }, + { WE_DISPLAY_DXE_SNAP_SHOT, + 0, + 0, + "dxeSnapshot" }, + { WE_DISPLAY_DATAPATH_SNAP_SHOT, + 0, + 0, + "dataSnapshot"}, + { + WE_SET_REASSOC_TRIGGER, + 0, + 0, + "reassoc" }, + { WE_DUMP_AGC_START, + 0, + 0, + "dump_agc_start" }, + + { WE_DUMP_AGC, + 0, + 0, + "dump_agc" }, + + { WE_DUMP_CHANINFO_START, + 0, + 0, + "dump_chninfo_en" }, + + { WE_DUMP_CHANINFO, + 0, + 0, + "dump_chninfo" }, + + { WE_DUMP_WATCHDOG, + 0, + 0, + "dump_watchdog" }, +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + { WE_DUMP_PCIE_LOG, + 0, + 0, + "dump_pcie_log" }, +#endif + /* handlers for main ioctl */ + { WLAN_PRIV_SET_VAR_INT_GET_NONE, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "" }, + + /* handlers for sub-ioctl */ + { WE_LOG_DUMP_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "dump" }, + + /* handlers for sub-ioctl */ + { WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setdumplog" }, + + { WE_MTRACE_DUMP_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "dumplog" }, + + /* handlers for sub ioctl */ + { + WE_MCC_CONFIG_CREDENTIAL, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setMccCrdnl" }, + + /* handlers for sub ioctl */ + { + WE_MCC_CONFIG_PARAMS, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setMccConfig" }, + +#ifdef FEATURE_WLAN_TDLS + /* handlers for sub ioctl */ + { + WE_TDLS_CONFIG_PARAMS, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setTdlsConfig" }, +#endif + { + WE_UNIT_TEST_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "setUnitTestCmd" }, + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + { WE_LED_FLASHING_PARAM, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "gpio_control" }, +#endif + +#ifdef MEMORY_DEBUG + /* handlers for sub ioctl */ + { WE_MEM_TRACE_DUMP, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "memTraceLog" }, +#endif + + /* handlers for main ioctl */ + { WLAN_PRIV_ADD_TSPEC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | HDD_WLAN_WMM_PARAM_COUNT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "addTspec" }, + + /* handlers for main ioctl */ + { WLAN_PRIV_DEL_TSPEC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "delTspec" }, + + /* handlers for main ioctl */ + { WLAN_PRIV_GET_TSPEC, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getTspec" }, + + /* handlers for main ioctl - host offload */ + { + WLAN_PRIV_SET_HOST_OFFLOAD, + IW_PRIV_TYPE_BYTE | sizeof(tHostOffloadRequest), + 0, + "setHostOffload" }, + + { + WLAN_GET_WLAN_STATISTICS, + 0, + IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN, + "getWlanStats" }, + + { + WLAN_SET_KEEPALIVE_PARAMS, + IW_PRIV_TYPE_BYTE | sizeof(tSirKeepAliveReq) | + IW_PRIV_SIZE_FIXED, + 0, + "setKeepAlive" }, +#ifdef WLAN_FEATURE_PACKET_FILTERING + { + WLAN_SET_PACKET_FILTER_PARAMS, + IW_PRIV_TYPE_BYTE | sizeof(tPacketFilterCfg), + 0, + "setPktFilter" }, +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + { + WLAN_SET_PNO, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + 0, + "setpno" }, +#endif + { + WLAN_SET_BAND_CONFIG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "SETBAND" }, + /* handlers for dynamic MC BC ioctl */ + { + WLAN_PRIV_SET_MCBC_FILTER, + IW_PRIV_TYPE_BYTE | sizeof(tRcvFltMcAddrList), + 0, + "setMCBCFilter" }, + { + WLAN_PRIV_CLEAR_MCBC_FILTER, + 0, + 0, + "clearMCBCFilter" }, + { + WLAN_SET_POWER_PARAMS, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + 0, + "setpowerparams" }, + { + WLAN_GET_LINK_SPEED, + IW_PRIV_TYPE_CHAR | 18, + IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, + + /* handlers for main ioctl */ + { WLAN_PRIV_SET_TWO_INT_GET_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, + "" }, + { WE_SET_SMPS_PARAM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_smps_param" }, + { WLAN_SET_DOT11P_CHANNEL_SCHED, + IW_PRIV_TYPE_BYTE + | sizeof(struct dot11p_channel_sched), + 0, "set_dot11p" }, +#ifdef DEBUG + { WE_SET_FW_CRASH_INJECT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "crash_inject" }, +#endif +}; + + + +const struct iw_handler_def we_handler_def = { + .num_standard = sizeof(we_handler) / sizeof(we_handler[0]), + .num_private = sizeof(we_private) / sizeof(we_private[0]), + .num_private_args = sizeof(we_private_args) / sizeof(we_private_args[0]), + + .standard = (iw_handler *)we_handler, + .private = (iw_handler *)we_private, + .private_args = we_private_args, + .get_wireless_stats = get_wireless_stats, +}; + +int hdd_validate_mcc_config(hdd_adapter_t *pAdapter, v_UINT_t staId, v_UINT_t arg1, v_UINT_t arg2, v_UINT_t arg3) +{ + v_U32_t cmd = 288; //Command to RIVA + hdd_context_t *pHddCtx = NULL; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + /* + *configMccParam : specify the bit which needs to be modified + *allowed to update based on wlan_qcom_cfg.ini + * configuration + * Bit 0 : SCHEDULE_TIME_SLICE MIN : 5 MAX : 20 + * Bit 1 : MAX_NULL_SEND_TIME MIN : 1 MAX : 10 + * Bit 2 : TX_EARLY_STOP_TIME MIN : 1 MAX : 10 + * Bit 3 : RX_DRAIN_TIME MIN : 1 MAX : 10 + * Bit 4 : CHANNEL_SWITCH_TIME MIN : 1 MAX : 20 + * Bit 5 : MIN_CHANNEL_TIME MIN : 5 MAX : 20 + * Bit 6 : PARK_BEFORE_TBTT MIN : 1 MAX : 5 + * Bit 7 : MIN_AFTER_DTIM MIN : 5 MAX : 15 + * Bit 8 : TOO_CLOSE_MARGIN MIN : 1 MAX : 3 + * Bit 9 : Reserved + */ + switch (arg1) + { + //Update MCC SCHEDULE_TIME_SLICE parameter + case MCC_SCHEDULE_TIME_SLICE_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0001) + { + if((arg2 >= 5) && (arg2 <= 20)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC MAX_NULL_SEND_TIME parameter + case MCC_MAX_NULL_SEND_TIME_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0002) + { + if((arg2 >= 1) && (arg2 <= 10)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC TX_EARLY_STOP_TIME parameter + case MCC_TX_EARLY_STOP_TIME_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0004) + { + if((arg2 >= 1) && (arg2 <= 10)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC RX_DRAIN_TIME parameter + case MCC_RX_DRAIN_TIME_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0008) + { + if((arg2 >= 1) && (arg2 <= 10)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC CHANNEL_SWITCH_TIME parameter + case MCC_CHANNEL_SWITCH_TIME_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0010) + { + if((arg2 >= 1) && (arg2 <= 20)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC MIN_CHANNEL_TIME parameter + case MCC_MIN_CHANNEL_TIME_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0020) + { + if((arg2 >= 5) && (arg2 <= 20)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC PARK_BEFORE_TBTT parameter + case MCC_PARK_BEFORE_TBTT_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0040) + { + if((arg2 >= 1) && (arg2 <= 5)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC MIN_AFTER_DTIM parameter + case MCC_MIN_AFTER_DTIM_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0080) + { + if((arg2 >= 5) && (arg2 <= 15)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + //Update MCC TOO_CLOSE_MARGIN parameter + case MCC_TOO_CLOSE_MARGIN_CFG_PARAM : + if( pHddCtx->cfg_ini->configMccParam & 0x0100) + { + if((arg2 >= 1) && (arg2 <= 3)) + { + logPrintf(hHal, cmd, staId, arg1, arg2, arg3); + } + else + { + hddLog(LOGE, "%s : Enter a valid MCC configuration value", __FUNCTION__); + return 0; + } + } + break; + + default : + hddLog(LOGE, FL("Unknown / Not allowed to configure parameter : %d"), arg1); + break; + } + return 0; +} + +int hdd_set_wext(hdd_adapter_t *pAdapter) +{ + hdd_wext_state_t *pwextBuf; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + // Now configure the roaming profile links. To SSID and bssid. + pwextBuf->roamProfile.SSIDs.numOfSSIDs = 0; + pwextBuf->roamProfile.SSIDs.SSIDList = &pHddStaCtx->conn_info.SSID; + + pwextBuf->roamProfile.BSSIDs.numOfBSSIDs = 0; + pwextBuf->roamProfile.BSSIDs.bssid = &pHddStaCtx->conn_info.bssId; + + /*Set the numOfChannels to zero to scan all the channels*/ + pwextBuf->roamProfile.ChannelInfo.numOfChannels = 0; + pwextBuf->roamProfile.ChannelInfo.ChannelList = NULL; + + /* Default is no encryption */ + pwextBuf->roamProfile.EncryptionType.numEntries = 1; + pwextBuf->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + + pwextBuf->roamProfile.mcEncryptionType.numEntries = 1; + pwextBuf->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + + pwextBuf->roamProfile.BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; + + /* Default is no authentication */ + pwextBuf->roamProfile.AuthType.numEntries = 1; + pwextBuf->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + pwextBuf->roamProfile.phyMode = eCSR_DOT11_MODE_AUTO; + pwextBuf->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + + /*Set the default scan mode*/ + pAdapter->scan_info.scan_mode = eSIR_ACTIVE_SCAN; + + hdd_clearRoamProfileIe(pAdapter); + + return VOS_STATUS_SUCCESS; + + } + +int hdd_register_wext(struct net_device *dev) + { + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + VOS_STATUS status; + + ENTER(); + + // Zero the memory. This zeros the profile structure. + memset(pwextBuf, 0,sizeof(hdd_wext_state_t)); + + init_completion(&(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->completion_var); + + + status = hdd_set_wext(pAdapter); + + if(!VOS_IS_STATUS_SUCCESS(status)) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: hdd_set_wext failed!!")); + return eHAL_STATUS_FAILURE; + } + + if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->vosevent))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos event init failed!!")); + return eHAL_STATUS_FAILURE; + } + + if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->scanevent))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD scan event init failed!!")); + return eHAL_STATUS_FAILURE; + } + + // Register as a wireless device + dev->wireless_handlers = (struct iw_handler_def *)&we_handler_def; + + EXIT(); + return 0; +} + +int hdd_UnregisterWext(struct net_device *dev) +{ + hddLog(LOG1, FL("dev(%p)"), dev); + + if (dev != NULL) { + rtnl_lock(); + dev->wireless_handlers = NULL; + rtnl_unlock(); + } + + return 0; +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wmm.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wmm.c new file mode 100644 index 000000000000..2f8cbbbbcd7a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wmm.c @@ -0,0 +1,2745 @@ +/* + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ + @file wlan_hdd_wmm.c + + This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation) + houses all the logic for WMM in HDD. + + On the control path, it has the logic to setup QoS, modify QoS and delete + QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an + explicit application invoked and an internal HDD invoked. The implicit QoS + is for applications that do NOT call the custom QCT WLAN OIDs for QoS but + which DO mark their traffic for prioritization. It also has logic to start, + update and stop the U-APSD trigger frame generation. It also has logic to + read WMM related config parameters from the registry. + + On the data path, it has the logic to figure out the WMM AC of an egress + packet and when to signal TL to serve a particular AC queue. It also has the + logic to retrieve a packet based on WMM priority in response to a fetch from + TL. + + The remaining functions are utility functions for information hiding. +============================================================================*/ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sme_Api.h" + +// change logging behavior based upon debug flag +#ifdef HDD_WMM_DEBUG +#define WMM_TRACE_LEVEL_FATAL VOS_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_ERROR VOS_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_WARN VOS_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_INFO VOS_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_INFO_HIGH VOS_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_INFO_LOW VOS_TRACE_LEVEL_FATAL +#else +#define WMM_TRACE_LEVEL_FATAL VOS_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_ERROR VOS_TRACE_LEVEL_ERROR +#define WMM_TRACE_LEVEL_WARN VOS_TRACE_LEVEL_WARN +#define WMM_TRACE_LEVEL_INFO VOS_TRACE_LEVEL_INFO +#define WMM_TRACE_LEVEL_INFO_HIGH VOS_TRACE_LEVEL_INFO_HIGH +#define WMM_TRACE_LEVEL_INFO_LOW VOS_TRACE_LEVEL_INFO_LOW +#endif + + +#define WLAN_HDD_MAX_DSCP 0x3f + +// DHCP Port number +#define DHCP_SOURCE_PORT 0x4400 +#define DHCP_DESTINATION_PORT 0x4300 + +#define HDD_WMM_UP_TO_AC_MAP_SIZE 8 + +const v_U8_t hddWmmUpToAcMap[] = { + WLANTL_AC_BE, + WLANTL_AC_BK, + WLANTL_AC_BK, + WLANTL_AC_BE, + WLANTL_AC_VI, + WLANTL_AC_VI, + WLANTL_AC_VO, + WLANTL_AC_VO +}; + +//Linux based UP -> AC Mapping +const v_U8_t hddLinuxUpToAcMap[HDD_WMM_UP_TO_AC_MAP_SIZE] = { + HDD_LINUX_AC_BE, + HDD_LINUX_AC_BK, + HDD_LINUX_AC_BK, + HDD_LINUX_AC_BE, + HDD_LINUX_AC_VI, + HDD_LINUX_AC_VI, + HDD_LINUX_AC_VO, + HDD_LINUX_AC_VO +}; + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT +/** + @brief hdd_wmm_enable_tl_uapsd() - function which decides whether and + how to update UAPSD parameters in TL + + @param pQosContext : [in] the pointer the QoS instance control block + + @return + None +*/ +static void hdd_wmm_enable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext) +{ + hdd_adapter_t* pAdapter = pQosContext->pAdapter; + WLANTL_ACEnumType acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + VOS_STATUS status; + v_U32_t service_interval; + v_U32_t suspension_interval; + sme_QosWmmDirType direction; + v_BOOL_t psb; + + + // The TSPEC must be valid + if (pAc->wmmAcTspecValid == VOS_FALSE) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invoked with invalid TSPEC", + __func__); + return; + } + + // determine the service interval + if (pAc->wmmAcTspecInfo.min_service_interval) + { + service_interval = pAc->wmmAcTspecInfo.min_service_interval; + } + else if (pAc->wmmAcTspecInfo.max_service_interval) + { + service_interval = pAc->wmmAcTspecInfo.max_service_interval; + } + else + { + // no service interval is present in the TSPEC + // this is OK, there just won't be U-APSD + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: No service interval supplied", + __func__); + service_interval = 0; + } + + // determine the suspension interval & direction + suspension_interval = pAc->wmmAcTspecInfo.suspension_interval; + direction = pAc->wmmAcTspecInfo.ts_info.direction; + psb = pAc->wmmAcTspecInfo.ts_info.psb; + + // if we have previously enabled U-APSD, have any params changed? + if ((pAc->wmmAcUapsdInfoValid) && + (pAc->wmmAcUapsdServiceInterval == service_interval) && + (pAc->wmmAcUapsdSuspensionInterval == suspension_interval) && + (pAc->wmmAcUapsdDirection == direction) && + (pAc->wmmAcIsUapsdEnabled == psb)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: No change in U-APSD parameters", + __func__); + return; + } + + // are we in the appropriate power save modes? + if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + ePMC_BEACON_MODE_POWER_SAVE)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: BMPS is not enabled", + __func__); + return; + } + + if (!sme_IsPowerSaveEnabled(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + ePMC_UAPSD_MODE_POWER_SAVE)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: U-APSD is not enabled", + __func__); + return; + } + + // everything is in place to notify TL + status = WLANTL_EnableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType, + pAc->wmmAcTspecInfo.ts_info.tid, + pAc->wmmAcTspecInfo.ts_info.up, + service_interval, + suspension_interval, + direction, + psb, + pAdapter->sessionId); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to enable U-APSD for AC=%d", + __func__, acType ); + return; + } + + // stash away the parameters that were used + pAc->wmmAcUapsdInfoValid = VOS_TRUE; + pAc->wmmAcUapsdServiceInterval = service_interval; + pAc->wmmAcUapsdSuspensionInterval = suspension_interval; + pAc->wmmAcUapsdDirection = direction; + pAc->wmmAcIsUapsdEnabled = psb; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Enabled UAPSD in TL srv_int=%d " + "susp_int=%d dir=%d AC=%d", + __func__, + service_interval, + suspension_interval, + direction, + acType); + +} + +/** + @brief hdd_wmm_disable_tl_uapsd() - function which decides whether + to disable UAPSD parameters in TL + + @param pQosContext : [in] the pointer the QoS instance control block + + @return + None +*/ +static void hdd_wmm_disable_tl_uapsd (hdd_wmm_qos_context_t* pQosContext) +{ + hdd_adapter_t* pAdapter = pQosContext->pAdapter; + WLANTL_ACEnumType acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + VOS_STATUS status; + + + // have we previously enabled UAPSD? + if (pAc->wmmAcUapsdInfoValid == VOS_TRUE) + { + status = WLANTL_DisableUAPSDForAC((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType, + pAdapter->sessionId); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to disable U-APSD for AC=%d", + __func__, acType ); + } + else + { + // TL no longer has valid UAPSD info + pAc->wmmAcUapsdInfoValid = VOS_FALSE; + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Disabled UAPSD in TL for AC=%d", + __func__, + acType); + } + } +} + +#endif + +/** + @brief hdd_wmm_free_context() - function which frees a QoS context + + @param pQosContext : [in] the pointer the QoS instance control block + + @return + None +*/ +static void hdd_wmm_free_context (hdd_wmm_qos_context_t* pQosContext) +{ + hdd_adapter_t* pAdapter; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", + __func__, pQosContext); + + if (unlikely((NULL == pQosContext) || + (HDD_WMM_CTX_MAGIC != pQosContext->magic))) + { + // must have been freed in another thread + return; + } + + // get pointer to the adapter context + pAdapter = pQosContext->pAdapter; + + // take the wmmLock since we're manipulating the context list + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + + // make sure nobody thinks this is a valid context + pQosContext->magic = 0; + + // unlink the context + list_del(&pQosContext->node); + + // done manipulating the list + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + + // reclaim memory + kfree(pQosContext); + +} + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT +/** + @brief hdd_wmm_notify_app() - function which notifies an application + changes in state of it flow + + @param pQosContext : [in] the pointer the QoS instance control block + + @return + None +*/ +#define MAX_NOTIFY_LEN 50 +static void hdd_wmm_notify_app (hdd_wmm_qos_context_t* pQosContext) +{ + hdd_adapter_t* pAdapter; + union iwreq_data wrqu; + char buf[MAX_NOTIFY_LEN+1]; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", + __func__, pQosContext); + + if (unlikely((NULL == pQosContext) || + (HDD_WMM_CTX_MAGIC != pQosContext->magic))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invalid QoS Context", + __func__); + return; + } + + + // create the event + memset(&wrqu, 0, sizeof(wrqu)); + memset(buf, 0, sizeof(buf)); + + snprintf(buf, MAX_NOTIFY_LEN, "QCOM: TS change[%u: %u]", + (unsigned int)pQosContext->handle, + (unsigned int)pQosContext->lastStatus); + + wrqu.data.pointer = buf; + wrqu.data.length = strlen(buf); + + // get pointer to the adapter + pAdapter = pQosContext->pAdapter; + + // send the event + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Sending [%s]", __func__, buf); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +} + + + +#ifdef FEATURE_WLAN_ESE +/** + @brief hdd_wmm_inactivity_timer_cb() - timer handler function which is + called for every inactivity interval per AC. This function gets the + current transmitted packets on the given AC, and checks if there where + any TX activity from the previous interval. If there was no traffic + then it would delete the TS that was negotiated on that AC. + + @param pUserData : [in] pointer to pQosContext + + @return : NONE +*/ +void hdd_wmm_inactivity_timer_cb( v_PVOID_t pUserData ) +{ + hdd_wmm_qos_context_t* pQosContext = (hdd_wmm_qos_context_t*)pUserData; + hdd_adapter_t* pAdapter; + hdd_wmm_ac_status_t *pAc; + hdd_wlan_wmm_status_e status; + VOS_STATUS vos_status; + v_U32_t currentTrafficCnt = 0; + WLANTL_ACEnumType acType = pQosContext->acType; + + pAdapter = pQosContext->pAdapter; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("invalid pAdapter: %p"), pAdapter); + return; + } + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + // Get the Tx stats for this AC. + currentTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType]; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("WMM inactivity Timer for AC=%d, currentCnt=%d, prevCnt=%d"), + acType, (int)currentTrafficCnt, (int)pAc->wmmPrevTrafficCnt); + if (pAc->wmmPrevTrafficCnt == currentTrafficCnt) + { + // If there is no traffic activity, delete the TSPEC for this AC + status = hdd_wmm_delts(pAdapter, pQosContext->handle); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("Deleted TS on AC %d, due to inactivity with status = %d!!!"), + acType, status); + } + else + { + pAc->wmmPrevTrafficCnt = currentTrafficCnt; + if (pAc->wmmInactivityTimer.state == VOS_TIMER_STATE_STOPPED) + { + // Restart the timer + vos_status = vos_timer_start(&pAc->wmmInactivityTimer, pAc->wmmInactivityTime); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Restarting inactivity timer failed on AC %d"), acType); + } + } + else + { + VOS_ASSERT(vos_timer_getCurrentState( + &pAc->wmmInactivityTimer) == VOS_TIMER_STATE_STOPPED); + } + } + + return; +} + + +/** + @brief hdd_wmm_enable_inactivity_timer() - function to enable the + traffic inactivity timer for the given AC, if the inactivity_interval + specified in the ADDTS parameters is non-zero + + @param pQosContext : [in] pointer to pQosContext + @param inactivityTime: [in] value of the inactivity interval in millisecs + + @return : VOS_STATUS_E_FAILURE + VOS_STATUS_SUCCESS +*/ +VOS_STATUS hdd_wmm_enable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext, v_U32_t inactivityTime) +{ + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + hdd_adapter_t* pAdapter = pQosContext->pAdapter; + WLANTL_ACEnumType acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc; + + pAdapter = pQosContext->pAdapter; + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + + // If QoS-Tspec is successfully setup and if the inactivity timer is non-zero, + // a traffic inactivity timer needs to be started for the given AC + vos_status = vos_timer_init( + &pAc->wmmInactivityTimer, + VOS_TIMER_TYPE_SW, + hdd_wmm_inactivity_timer_cb, + (v_PVOID_t)pQosContext ); + if ( !VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Initializing inactivity timer failed on AC %d"), acType); + return vos_status; + } + + // Start the inactivity timer + vos_status = vos_timer_start( + &pAc->wmmInactivityTimer, + inactivityTime); + if ( !VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Starting inactivity timer failed on AC %d"), acType); + vos_status = vos_timer_destroy(&pAc->wmmInactivityTimer); + if (VOS_STATUS_SUCCESS != vos_status) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Failed to destroy inactivity timer")); + } + return vos_status; + } + pAc->wmmInactivityTime = inactivityTime; + // Initialize the current tx traffic count on this AC + pAc->wmmPrevTrafficCnt = pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext->acType]; + + pQosContext->is_inactivity_timer_running = true; + + return vos_status; +} + +/** + @brief hdd_wmm_enable_inactivity_timer() - function to disable the + traffic inactivity timer for the given AC. This would be called when + deleting the TS. + + @param pQosContext : [in] pointer to pQosContext + + @return : VOS_STATUS_E_FAILURE + VOS_STATUS_SUCCESS +*/ +VOS_STATUS hdd_wmm_disable_inactivity_timer(hdd_wmm_qos_context_t* pQosContext) +{ + hdd_adapter_t* pAdapter = pQosContext->pAdapter; + WLANTL_ACEnumType acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + + // Clear the timer and the counter + pAc->wmmInactivityTime = 0; + pAc->wmmPrevTrafficCnt = 0; + + if (pQosContext->is_inactivity_timer_running == true) { + pQosContext->is_inactivity_timer_running = false; + vos_status = vos_timer_stop(&pAc->wmmInactivityTimer); + if (VOS_STATUS_SUCCESS != vos_status) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Failed to stop inactivity timer")); + return vos_status; + } + vos_status = vos_timer_destroy(&pAc->wmmInactivityTimer); + if (VOS_STATUS_SUCCESS != vos_status) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Failed to destroy inactivity timer:Timer started")); + } + } + + return vos_status; +} +#endif // FEATURE_WLAN_ESE + +/** + @brief hdd_wmm_sme_callback() - callback registered by HDD with SME for receiving + QoS notifications. Even though this function has a static scope it gets called + externally through some function pointer magic (so there is a need for + rigorous parameter checking) + + @param hHal : [in] the HAL handle + @param HddCtx : [in] the HDD specified handle + @param pCurrentQosInfo : [in] the TSPEC params + @param SmeStatus : [in] the QoS related SME status + + @return + eHAL_STATUS_SUCCESS if all good, eHAL_STATUS_FAILURE otherwise +*/ +static eHalStatus hdd_wmm_sme_callback (tHalHandle hHal, + void * hddCtx, + sme_QosWmmTspecInfo* pCurrentQosInfo, + sme_QosStatusType smeStatus, + v_U32_t qosFlowId) +{ + hdd_wmm_qos_context_t* pQosContext = hddCtx; + hdd_adapter_t* pAdapter; + WLANTL_ACEnumType acType; + hdd_wmm_ac_status_t *pAc; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", + __func__, pQosContext); + + if (unlikely((NULL == pQosContext) || + (HDD_WMM_CTX_MAGIC != pQosContext->magic))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invalid QoS Context", + __func__); + return eHAL_STATUS_FAILURE; + } + + pAdapter = pQosContext->pAdapter; + acType = pQosContext->acType; + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: status %d flowid %d info %p", + __func__, smeStatus, qosFlowId, pCurrentQosInfo); + + switch (smeStatus) + { + + case SME_QOS_STATUS_SETUP_SUCCESS_IND: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Setup is complete", + __func__); + + // there will always be a TSPEC returned with this status, even if + // a TSPEC is not exchanged OTA + if (pCurrentQosInfo) + { + pAc->wmmAcTspecValid = VOS_TRUE; + memcpy(&pAc->wmmAcTspecInfo, + pCurrentQosInfo, + sizeof(pAc->wmmAcTspecInfo)); + } + pAc->wmmAcAccessAllowed = VOS_TRUE; + pAc->wmmAcAccessGranted = VOS_TRUE; + pAc->wmmAcAccessPending = VOS_FALSE; + pAc->wmmAcAccessFailed = VOS_FALSE; + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Implicit Qos, notifying TL for TL AC %d", + __func__, acType); + + // notify TL that packets are pending + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS; + hdd_wmm_notify_app(pQosContext); + } + +#ifdef FEATURE_WLAN_ESE + // Check if the inactivity interval is specified + if (pCurrentQosInfo && pCurrentQosInfo->inactivity_interval) { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Inactivity timer value = %d for AC=%d", + __func__, pCurrentQosInfo->inactivity_interval, acType); + hdd_wmm_enable_inactivity_timer(pQosContext, pCurrentQosInfo->inactivity_interval); + } +#endif // FEATURE_WLAN_ESE + + // notify TL to enable trigger frames if necessary + hdd_wmm_enable_tl_uapsd(pQosContext); + + break; + + case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Setup is complete (U-APSD set previously)", + __func__); + + pAc->wmmAcAccessAllowed = VOS_TRUE; + pAc->wmmAcAccessGranted = VOS_TRUE; + pAc->wmmAcAccessPending = VOS_FALSE; + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Implicit Qos, notifying TL", + __func__); + + // notify TL that packets are pending + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING; + hdd_wmm_notify_app(pQosContext); + } + + break; + + case SME_QOS_STATUS_SETUP_FAILURE_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup failed", + __func__); + // QoS setup failed + + pAc->wmmAcAccessPending = VOS_FALSE; + pAc->wmmAcAccessFailed = VOS_TRUE; + pAc->wmmAcAccessAllowed = VOS_FALSE; + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Implicit Qos, notifying TL", + __func__); + + // this was triggered by implicit QoS so we know packets are pending + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED; + + hdd_wmm_notify_app(pQosContext); + } + + /* + * Setting up QoS Failed, QoS context can be released. + * SME is releasing this flow information and if HDD doesn't release this + * context, next time if application uses the same handle to set-up QoS, + * HDD (as it has QoS context for this handle) will issue Modify QoS + * request to SME but SME will reject as no it has no information + * for this flow. + */ + hdd_wmm_free_context(pQosContext); + break; + + case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup Invalid Params, notify TL", + __func__); + // QoS setup failed + pAc->wmmAcAccessAllowed = VOS_FALSE; + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Implicit Qos, notifying TL", + __func__); + + // we note the failure, but we also mark access as allowed so that + // the packets will flow. Note that the MAC will "do the right thing" + pAc->wmmAcAccessPending = VOS_FALSE; + pAc->wmmAcAccessFailed = VOS_TRUE; + pAc->wmmAcAccessAllowed = VOS_TRUE; + + // this was triggered by implicit QoS so we know packets are pending + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP: + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup failed, not a QoS AP", + __func__); + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Setup pending", + __func__); + // not a callback status -- ignore if we get it + break; + + case SME_QOS_STATUS_SETUP_MODIFIED_IND: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Setup modified", + __func__); + if (pCurrentQosInfo) + { + // update the TSPEC + pAc->wmmAcTspecValid = VOS_TRUE; + memcpy(&pAc->wmmAcTspecInfo, + pCurrentQosInfo, + sizeof(pAc->wmmAcTspecInfo)); + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFIED; + hdd_wmm_notify_app(pQosContext); + } + + // need to tell TL to update its UAPSD handling + hdd_wmm_enable_tl_uapsd(pQosContext); + } + break; + + case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP: + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Implicit Qos, notifying TL", + __func__); + + // this was triggered by implicit QoS so we know packets are pending + pAc->wmmAcAccessPending = VOS_FALSE; + pAc->wmmAcAccessGranted = VOS_TRUE; + pAc->wmmAcAccessAllowed = VOS_TRUE; + + // notify TL that packets are pending + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING: + // nothing to do for now + break; + + case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup successful but U-APSD failed", + __func__); + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Implicit Qos, notifying TL", + __func__); + + // QoS setup was successful but setting U=APSD failed + // Since the OTA part of the request was successful, we don't mark + // this as a failure. + // the packets will flow. Note that the MAC will "do the right thing" + pAc->wmmAcAccessGranted = VOS_TRUE; + pAc->wmmAcAccessAllowed = VOS_TRUE; + pAc->wmmAcAccessFailed = VOS_FALSE; + pAc->wmmAcAccessPending = VOS_FALSE; + + // this was triggered by implicit QoS so we know packets are pending + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_SETUP_UAPSD_SET_FAILED; + hdd_wmm_notify_app(pQosContext); + } + + // Since U-APSD portion failed disabled trigger frame generation + hdd_wmm_disable_tl_uapsd(pQosContext); + + break; + + case SME_QOS_STATUS_RELEASE_SUCCESS_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Release is complete", + __func__); + + if (pCurrentQosInfo) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: flows still active", + __func__); + + // there is still at least one flow active for this AC + // so update the AC state + memcpy(&pAc->wmmAcTspecInfo, + pCurrentQosInfo, + sizeof(pAc->wmmAcTspecInfo)); + + // need to tell TL to update its UAPSD handling + hdd_wmm_enable_tl_uapsd(pQosContext); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: last flow", + __func__); + + // this is the last flow active for this AC so update the AC state + pAc->wmmAcTspecValid = VOS_FALSE; + + // DELTS is successful, do not allow + pAc->wmmAcAccessAllowed = VOS_FALSE; + + // need to tell TL to update its UAPSD handling + hdd_wmm_disable_tl_uapsd(pQosContext); + } + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS; + hdd_wmm_notify_app(pQosContext); + } + + // we are done with this flow + hdd_wmm_free_context(pQosContext); + break; + + case SME_QOS_STATUS_RELEASE_FAILURE_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Release failure", + __func__); + + // we don't need to update our state or TL since nothing has changed + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED; + hdd_wmm_notify_app(pQosContext); + } + + break; + + case SME_QOS_STATUS_RELEASE_QOS_LOST_IND: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: QOS Lost indication received", + __func__); + + // current TSPEC is no longer valid + pAc->wmmAcTspecValid = VOS_FALSE; + // AP has sent DELTS, do not allow + pAc->wmmAcAccessAllowed = VOS_FALSE; + + // need to tell TL to update its UAPSD handling + hdd_wmm_disable_tl_uapsd(pQosContext); + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) + { + // we no longer have implicit access granted + pAc->wmmAcAccessGranted = VOS_FALSE; + pAc->wmmAcAccessFailed = VOS_FALSE; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Explicit Qos, notifying user space", + __func__); + + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_LOST; + hdd_wmm_notify_app(pQosContext); + } + + // we are done with this flow + hdd_wmm_free_context(pQosContext); + break; + + case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Release pending", + __func__); + // not a callback status -- ignore if we get it + break; + + case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Release Invalid Params", + __func__); + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Modification is complete, notify TL", + __func__); + + // there will always be a TSPEC returned with this status, even if + // a TSPEC is not exchanged OTA + if (pCurrentQosInfo) + { + pAc->wmmAcTspecValid = VOS_TRUE; + memcpy(&pAc->wmmAcTspecInfo, + pCurrentQosInfo, + sizeof(pAc->wmmAcTspecInfo)); + } + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS; + hdd_wmm_notify_app(pQosContext); + } + + // notify TL to enable trigger frames if necessary + hdd_wmm_enable_tl_uapsd(pQosContext); + + break; + + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY: + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP: + // the flow modification failed so we'll leave in place + // whatever existed beforehand + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: modification pending", + __func__); + // not a callback status -- ignore if we get it + break; + + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP: + // the flow modification was successful but no QoS changes required + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP: + // invalid params -- notify the application + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM; + hdd_wmm_notify_app(pQosContext); + } + break; + + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING: + // nothing to do for now. when APSD is established we'll have work to do + break; + + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Modify successful but U-APSD failed", + __func__); + + // QoS modification was successful but setting U=APSD failed. + // This will always be an explicit QoS instance, so all we can + // do is notify the application and let it clean up. + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) + { + // this was triggered by an application + pQosContext->lastStatus = HDD_WLAN_WMM_STATUS_MODIFY_UAPSD_SET_FAILED; + hdd_wmm_notify_app(pQosContext); + } + + // Since U-APSD portion failed disabled trigger frame generation + hdd_wmm_disable_tl_uapsd(pQosContext); + + break; + + case SME_QOS_STATUS_HANDING_OFF: + // no roaming so we won't see this + break; + + case SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND: + // need to tell TL to stop trigger frame generation + hdd_wmm_disable_tl_uapsd(pQosContext); + break; + + case SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND: + // need to tell TL to start sending trigger frames again + hdd_wmm_enable_tl_uapsd(pQosContext); + break; + + default: + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", + __func__, smeStatus ); + VOS_ASSERT(0); + } + + // if Tspec only allows downstream traffic then access is not allowed + if (pAc->wmmAcTspecValid && + (pAc->wmmAcTspecInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_DOWNLINK)) { + pAc->wmmAcAccessAllowed = VOS_FALSE; + } + + // if we have valid Tpsec or if ACM bit is not set, allow access + if ((pAc->wmmAcTspecValid && + (pAc->wmmAcTspecInfo.ts_info.direction != SME_QOS_WMM_TS_DIR_DOWNLINK)) || + !pAc->wmmAcAccessRequired) { + pAc->wmmAcAccessAllowed = VOS_TRUE; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: complete, access for TL AC %d is%sallowed", + __func__, + acType, + pAc->wmmAcAccessAllowed ? " " : " not "); + + return eHAL_STATUS_SUCCESS; +} +#endif + +/**======================================================================== + @brief hdd_wmmps_helper() - Function to set uapsd psb dynamically + + @param pAdapter : [in] pointer to adapter structure + + @param ptr : [in] pointer to command buffer + + @return : Zero on success, appropriate error on failure. + =======================================================================*/ +int hdd_wmmps_helper(hdd_adapter_t *pAdapter, tANI_U8 *ptr) +{ + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL", __func__); + return -EINVAL; + } + if (NULL == ptr) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: ptr is NULL", __func__); + return -EINVAL; + } + /* convert ASCII to integer */ + pAdapter->configuredPsb = ptr[9] - '0'; + pAdapter->psbChanged = HDD_PSB_CHANGED; + + return 0; +} + +/** + * __hdd_wmm_do_implicit_qos() - Function which will attempt to setup + * QoS for any AC requiring it. + * @work: [in] pointer to work structure. + * + * Return: none + */ +static void __hdd_wmm_do_implicit_qos(struct work_struct *work) +{ + hdd_wmm_qos_context_t* pQosContext = + container_of(work, hdd_wmm_qos_context_t, wmmAcSetupImplicitQos); + hdd_adapter_t* pAdapter; + WLANTL_ACEnumType acType; + hdd_wmm_ac_status_t *pAc; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + VOS_STATUS status; + sme_QosStatusType smeStatus; +#endif + sme_QosWmmTspecInfo qosInfo; + hdd_context_t *hdd_ctx; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", + __func__, pQosContext); + + if (unlikely(HDD_WMM_CTX_MAGIC != pQosContext->magic)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invalid QoS Context", + __func__); + return; + } + + pAdapter = pQosContext->pAdapter; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return; + } + + acType = pQosContext->acType; + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: pAdapter %p acType %d", + __func__, pAdapter, acType); + + if (!pAc->wmmAcAccessNeeded) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: AC %d doesn't need service", + __func__, acType); + pQosContext->magic = 0; + kfree(pQosContext); + return; + } + + pAc->wmmAcAccessPending = VOS_TRUE; + pAc->wmmAcAccessNeeded = VOS_FALSE; + + memset(&qosInfo, 0, sizeof(qosInfo)); + + qosInfo.ts_info.psb = pAdapter->configuredPsb; + + switch (acType) + { + case WLANTL_AC_VO: + qosInfo.ts_info.up = SME_QOS_WMM_UP_VO; + /* Check if there is any valid configuration from framework */ + if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) + { + qosInfo.ts_info.psb = ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & + SME_QOS_UAPSD_VO) ? 1 : 0; + } + qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVo; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVo; + qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVo; + qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv; + qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVo; + qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVo; + qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv; + break; + case WLANTL_AC_VI: + qosInfo.ts_info.up = SME_QOS_WMM_UP_VI; + /* Check if there is any valid configuration from framework */ + if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) + { + qosInfo.ts_info.psb = ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & + SME_QOS_UAPSD_VI) ? 1 : 0; + } + qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcVi; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcVi; + qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcVi; + qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv; + qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcVi; + qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcVi; + qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv; + break; + default: + case WLANTL_AC_BE: + qosInfo.ts_info.up = SME_QOS_WMM_UP_BE; + /* Check if there is any valid configuration from framework */ + if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) + { + qosInfo.ts_info.psb = ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & + SME_QOS_UAPSD_BE) ? 1 : 0; + } + qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBe; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBe; + qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBe; + qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv; + qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBe; + qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBe; + qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv; + break; + case WLANTL_AC_BK: + qosInfo.ts_info.up = SME_QOS_WMM_UP_BK; + /* Check if there is any valid configuration from framework */ + if (HDD_PSB_CFG_INVALID == pAdapter->configuredPsb) + { + qosInfo.ts_info.psb = ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask & + SME_QOS_UAPSD_BK) ? 1 : 0; + } + qosInfo.ts_info.direction = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraDirAcBk; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMeanDataRateAcBk; + qosInfo.min_phy_rate = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraMinPhyRateAcBk; + qosInfo.min_service_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv; + qosInfo.nominal_msdu_size = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraNomMsduSizeAcBk; + qosInfo.surplus_bw_allowance = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraSbaAcBk; + qosInfo.suspension_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv; + break; + } +#ifdef FEATURE_WLAN_ESE + qosInfo.inactivity_interval = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraInactivityInterval; +#endif + qosInfo.ts_info.burst_size_defn = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->burstSizeDefinition; + + switch ((WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->tsInfoAckPolicy) + { + case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK: + qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK; + break; + + case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK: + qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK; + break; + + default: + // unknown + qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK; + } + + if(qosInfo.ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) + { + if(!sme_QosIsTSInfoAckPolicyValid((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), &qosInfo, pAdapter->sessionId)) + { + qosInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK; + } + } + + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList); + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &qosInfo, + hdd_wmm_sme_callback, + pQosContext, + qosInfo.ts_info.up, + &pQosContext->qosFlowId); + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: sme_QosSetupReq returned %d flowid %d", + __func__, smeStatus, pQosContext->qosFlowId); + + // need to check the return values and act appropriately + switch (smeStatus) + { + case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP: + case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING: + // setup is pending, so no more work to do now. + // all further work will be done in hdd_wmm_sme_callback() + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Setup is pending, no further work", + __func__); + + break; + + + case SME_QOS_STATUS_SETUP_FAILURE_RSP: + // we can't tell the difference between when a request fails because + // AP rejected it versus when SME encountered an internal error + + // in either case SME won't ever reference this context so + // free the record + hdd_wmm_free_context(pQosContext); + + // fall through and start packets flowing + case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP: + // no ACM in effect, no need to setup U-APSD + case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY: + // no ACM in effect, U-APSD is desired but was already setup + + // for these cases everything is already setup so we can + // signal TL that it has work to do + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Setup is complete, notify TL", + __func__); + + pAc->wmmAcAccessAllowed = VOS_TRUE; + pAc->wmmAcAccessGranted = VOS_TRUE; + pAc->wmmAcAccessPending = VOS_FALSE; + + status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + acType ); + + if ( !VOS_IS_STATUS_SUCCESS( status ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Failed to signal TL for AC=%d", + __func__, acType ); + } + + break; + + + default: + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", + __func__, smeStatus ); + VOS_ASSERT(0); + } +#endif + +} + +/** + * hdd_wmm_do_implicit_qos() - SSR wraper function for hdd_wmm_do_implicit_qos + * @work: pointer to work_struct + * + * Return: none + */ +static void hdd_wmm_do_implicit_qos(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __hdd_wmm_do_implicit_qos(work); + vos_ssr_unprotect(__func__); +} + +/**============================================================================ + @brief hdd_wmm_init() - Function which will initialize the WMM configuration + and status to an initial state. The configuration can later be overwritten + via application APIs + + @param pAdapter : [in] pointer to Adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_init ( hdd_adapter_t *pAdapter ) +{ + sme_QosWmmUpType* hddWmmDscpToUpMap = pAdapter->hddWmmDscpToUpMap; + v_U8_t dscp; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + + /* + * DSCP to User Priority Lookup Table + * By default use the 3 Precedence bits of DSCP as the User Priority + */ + for (dscp = 0; dscp <= WLAN_HDD_MAX_DSCP; dscp++) { + hddWmmDscpToUpMap[dscp] = dscp >> 3; + } + + /* Special case for Expedited Forwarding (DSCP 46) */ + hddWmmDscpToUpMap[46] = SME_QOS_WMM_UP_VO; + + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief hdd_wmm_adapter_init() - Function which will initialize the WMM + configuration and status to an initial state. + The configuration can later be overwritten via application APIs + + @param pAdapter : [in] pointer to Adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_adapter_init( hdd_adapter_t *pAdapter ) +{ + hdd_wmm_ac_status_t *pAcStatus; + WLANTL_ACEnumType acType; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + + pAdapter->hddWmmStatus.wmmQap = VOS_FALSE; + INIT_LIST_HEAD(&pAdapter->hddWmmStatus.wmmContextList); + mutex_init(&pAdapter->hddWmmStatus.wmmLock); + + for (acType = 0; acType < WLANTL_MAX_AC; acType++) + { + pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + pAcStatus->wmmAcAccessRequired = VOS_FALSE; + pAcStatus->wmmAcAccessNeeded = VOS_FALSE; + pAcStatus->wmmAcAccessPending = VOS_FALSE; + pAcStatus->wmmAcAccessFailed = VOS_FALSE; + pAcStatus->wmmAcAccessGranted = VOS_FALSE; + pAcStatus->wmmAcAccessAllowed = VOS_FALSE; + pAcStatus->wmmAcTspecValid = VOS_FALSE; + pAcStatus->wmmAcUapsdInfoValid = VOS_FALSE; + } + // Invalid value(0xff) to indicate psb not configured through framework initially. + pAdapter->configuredPsb = HDD_PSB_CFG_INVALID; + + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief hdd_wmm_adapter_clear() - Function which will clear the WMM status + for all the ACs + + @param pAdapter : [in] pointer to Adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_adapter_clear( hdd_adapter_t *pAdapter ) +{ + hdd_wmm_ac_status_t *pAcStatus; + WLANTL_ACEnumType acType; + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + for (acType = 0; acType < WLANTL_MAX_AC; acType++) + { + pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + pAcStatus->wmmAcAccessRequired = VOS_FALSE; + pAcStatus->wmmAcAccessNeeded = VOS_FALSE; + pAcStatus->wmmAcAccessPending = VOS_FALSE; + pAcStatus->wmmAcAccessFailed = VOS_FALSE; + pAcStatus->wmmAcAccessGranted = VOS_FALSE; + pAcStatus->wmmAcAccessAllowed = VOS_FALSE; + pAcStatus->wmmAcTspecValid = VOS_FALSE; + pAcStatus->wmmAcUapsdInfoValid = VOS_FALSE; + } + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief hdd_wmm_close() - Function which will perform any necessary work to + to clean up the WMM functionality prior to the kernel module unload + + @param pAdapter : [in] pointer to adapter context + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + + ===========================================================================*/ +VOS_STATUS hdd_wmm_adapter_close ( hdd_adapter_t* pAdapter ) +{ + hdd_wmm_qos_context_t* pQosContext; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + + // free any context records that we still have linked + while (!list_empty(&pAdapter->hddWmmStatus.wmmContextList)) + { + pQosContext = list_first_entry(&pAdapter->hddWmmStatus.wmmContextList, + hdd_wmm_qos_context_t, node); +#ifdef FEATURE_WLAN_ESE + hdd_wmm_disable_inactivity_timer(pQosContext); +#endif + if (pQosContext->handle == HDD_WMM_HANDLE_IMPLICIT + && pQosContext->magic == HDD_WMM_CTX_MAGIC) + vos_flush_work(&pQosContext->wmmAcSetupImplicitQos); + + hdd_wmm_free_context(pQosContext); + } + + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief is_dhcp_packet() - Function which will check OS packet for + DHCP packet + + @param skb : [in] pointer to OS packet (sk_buff) + @return : VOS_TRUE if the OS packet is DHCP packet + : otherwise VOS_FALSE + ===========================================================================*/ +v_BOOL_t is_dhcp_packet(struct sk_buff *skb) +{ + if (*((u16*)((u8*)skb->data+34)) == DHCP_SOURCE_PORT || + *((u16*)((u8*)skb->data+34)) == DHCP_DESTINATION_PORT) + return VOS_TRUE; + + return VOS_FALSE; +} + +/**============================================================================ + @brief hdd_wmm_classify_pkt() - Function which will classify an OS packet + into a WMM AC based on either 802.1Q or DSCP + + @param pAdapter : [in] pointer to adapter context + @param skb : [in] pointer to OS packet (sk_buff) + @param pAcType : [out] pointer to WMM AC type of OS packet + + @return : None + ===========================================================================*/ +static v_VOID_t +hdd_wmm_classify_pkt(hdd_adapter_t* pAdapter, struct sk_buff *skb, + WLANTL_ACEnumType* pAcType, sme_QosWmmUpType *pUserPri) +{ + unsigned char * pPkt; + union generic_ethhdr *pHdr; + struct iphdr *pIpHdr; + unsigned char tos; + unsigned char dscp; + sme_QosWmmUpType userPri; + WLANTL_ACEnumType acType; + + // this code is executed for every packet therefore + // all debug code is kept conditional + +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); +#endif // HDD_WMM_DEBUG + + pPkt = skb->data; + pHdr = (union generic_ethhdr *)pPkt; + +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: proto/length is 0x%04x", + __func__, pHdr->eth_II.h_proto); +#endif // HDD_WMM_DEBUG + + if (HDD_WMM_CLASSIFICATION_DSCP == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis) + { + if (pHdr->eth_II.h_proto == htons(ETH_P_IP)) + { + // case 1: Ethernet II IP packet + pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_II)]; + tos = pIpHdr->tos; +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Ethernet II IP Packet, tos is %d", + __func__, tos); +#endif // HDD_WMM_DEBUG + + } + else if ((ntohs(pHdr->eth_II.h_proto) < WLAN_MIN_PROTO) && + (pHdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) && + (pHdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) && + (pHdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) && + (pHdr->eth_8023.h_proto == htons(ETH_P_IP))) + { + // case 2: 802.3 LLC/SNAP IP packet + pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023)]; + tos = pIpHdr->tos; +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: 802.3 LLC/SNAP IP Packet, tos is %d", + __func__, tos); +#endif // HDD_WMM_DEBUG + } + else if (pHdr->eth_II.h_proto == htons(ETH_P_8021Q)) + { + // VLAN tagged + + if (pHdr->eth_IIv.h_vlan_encapsulated_proto == htons(ETH_P_IP)) + { + // case 3: Ethernet II vlan-tagged IP packet + pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_IIv)]; + tos = pIpHdr->tos; +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Ethernet II VLAN tagged IP Packet, tos is %d", + __func__, tos); +#endif // HDD_WMM_DEBUG + } + else if ((ntohs(pHdr->eth_IIv.h_vlan_encapsulated_proto) < WLAN_MIN_PROTO) && + (pHdr->eth_8023v.h_snap.dsap == WLAN_SNAP_DSAP) && + (pHdr->eth_8023v.h_snap.ssap == WLAN_SNAP_SSAP) && + (pHdr->eth_8023v.h_snap.ctrl == WLAN_SNAP_CTRL) && + (pHdr->eth_8023v.h_proto == htons(ETH_P_IP))) + { + // case 4: 802.3 LLC/SNAP vlan-tagged IP packet + pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023v)]; + tos = pIpHdr->tos; +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d", + __func__, tos); +#endif // HDD_WMM_DEBUG + } + else + { + // default +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, + "%s: VLAN tagged Unhandled Protocol, using default tos", + __func__); +#endif // HDD_WMM_DEBUG + tos = 0; + } + } + else + { + // default +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, + "%s: Unhandled Protocol, using default tos", + __func__); +#endif // HDD_WMM_DEBUG + //Give the highest priority to 802.1x packet + if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X)) + tos = 0xC0; + else + tos = 0; + } + + dscp = (tos>>2) & 0x3f; + userPri = pAdapter->hddWmmDscpToUpMap[dscp]; + +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: tos is %d, dscp is %d, up is %d", + __func__, tos, dscp, userPri); +#endif // HDD_WMM_DEBUG + + } + else if (HDD_WMM_CLASSIFICATION_802_1Q == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->PktClassificationBasis) + { + if (pHdr->eth_IIv.h_vlan_proto == htons(ETH_P_8021Q)) + { + // VLAN tagged + userPri = (ntohs(pHdr->eth_IIv.h_vlan_TCI)>>13) & 0x7; +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Tagged frame, UP is %d", + __func__, userPri); +#endif // HDD_WMM_DEBUG + } + else + { + // not VLAN tagged, use default +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, + "%s: Untagged frame, using default UP", + __func__); +#endif // HDD_WMM_DEBUG + //Give the highest priority to 802.1x packet + if (pHdr->eth_II.h_proto == htons(HDD_ETHERTYPE_802_1_X)) + userPri = SME_QOS_WMM_UP_VO; + else + userPri = SME_QOS_WMM_UP_BE; + } + } + else + { + // default +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Unknown classification scheme, using default UP", + __func__); +#endif // HDD_WMM_DEBUG + userPri = SME_QOS_WMM_UP_BE; + } + + acType = hddWmmUpToAcMap[userPri]; + +#ifdef HDD_WMM_DEBUG + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: UP is %d, AC is %d", + __func__, userPri, acType); +#endif // HDD_WMM_DEBUG + + *pUserPri = userPri; + *pAcType = acType; + + return; +} + +/**============================================================================ + @brief hdd_hostapd_select_quueue() - Function which will classify the packet + according to Linux qdisc expectation. + + + @param dev : [in] pointer to net_device structure + @param skb : [in] pointer to os packet + + @return : Qdisc queue index + ===========================================================================*/ +v_U16_t hdd_hostapd_select_queue(struct net_device * dev, struct sk_buff *skb +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) + , void *accel_priv +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + , select_queue_fallback_t fallback +#endif +) +{ + WLANTL_ACEnumType ac; + sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; + v_USHORT_t queueIndex; + hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int status = 0; + status = wlan_hdd_validate_context(pHddCtx); + + if (status != 0) + { + skb->priority = SME_QOS_WMM_UP_BE; + return HDD_LINUX_AC_BE; + } + + if (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->cfg_ini->WmmMode) { + /* Get the user priority from IP header & corresponding AC */ + hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up); + } + + skb->priority = up; + queueIndex = hddLinuxUpToAcMap[skb->priority]; + + return queueIndex; +} + +/**============================================================================ + @brief hdd_wmm_select_quueue() - Function which will classify the packet + according to Linux qdisc expectation. + + + @param dev : [in] pointer to net_device structure + @param skb : [in] pointer to os packet + + @return : Qdisc queue index + ===========================================================================*/ +v_U16_t hdd_wmm_select_queue(struct net_device * dev, struct sk_buff *skb) +{ + WLANTL_ACEnumType ac; + sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; + v_USHORT_t queueIndex; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int status = 0; + + status = wlan_hdd_validate_context(pHddCtx); + if (status != 0) { + skb->priority = SME_QOS_WMM_UP_BE; + return HDD_LINUX_AC_BE; + } + /* + * If we don't want QoS or the AP doesn't support Qos + * All traffic will get equal opportunity to transmit data frames. + */ + + if( hdd_wmm_is_active(pAdapter) ) { + /* Get the user priority from IP header & corresponding AC */ + hdd_wmm_classify_pkt (pAdapter, skb, &ac, &up); + } + + skb->priority = up; + queueIndex = hddLinuxUpToAcMap[skb->priority]; + + return queueIndex; +} + +/**========================================================================== + @brief hdd_wmm_acquire_access_required() - Function which will determine + acquire admittance for a WMM AC is required or not based on psb configuration + done in framework + + @param pAdapter : [in] pointer to adapter structure + + @param acType : [in] WMM AC type of OS packet + + @return : void + ===========================================================================*/ +void hdd_wmm_acquire_access_required(hdd_adapter_t *pAdapter, + WLANTL_ACEnumType acType) +{ +/* Each bit in the LSB nibble indicates 1 AC. + * Clearing the particular bit in LSB nibble to indicate + * access required + */ + switch(acType) + { + case WLANTL_AC_BK: + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_BK_CHANGED_MASK; /* clear first bit */ + break; + case WLANTL_AC_BE: + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_BE_CHANGED_MASK; /* clear second bit */ + break; + case WLANTL_AC_VI: + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_VI_CHANGED_MASK; /* clear third bit */ + break; + case WLANTL_AC_VO: + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_VO_CHANGED_MASK; /* clear fourth bit */ + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invalid AC Type", __func__); + break; + } +} + +/**============================================================================ + @brief hdd_wmm_acquire_access() - Function which will attempt to acquire + admittance for a WMM AC + + @param pAdapter : [in] pointer to adapter context + @param acType : [in] WMM AC type of OS packet + @param pGranted : [out] pointer to boolean flag when indicates if access + has been granted or not + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_acquire_access( hdd_adapter_t* pAdapter, + WLANTL_ACEnumType acType, + v_BOOL_t * pGranted ) +{ + hdd_wmm_qos_context_t *pQosContext; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered for AC %d", __func__, acType); + + if (!hdd_wmm_is_active(pAdapter) || + !(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->bImplicitQosEnabled || + !pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessRequired) + { + // either we don't want QoS or the AP doesn't support QoS + // or we don't want to do implicit QoS + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: QoS not configured on both ends ", __func__); + + *pGranted = pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed; + + return VOS_STATUS_SUCCESS; + } + + // do we already have an implicit QoS request pending for this AC? + if ((pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded) || + (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessPending)) + { + // request already pending so we need to wait for that response + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Implicit QoS for TL AC %d already scheduled", + __func__, acType); + + *pGranted = VOS_FALSE; + return VOS_STATUS_SUCCESS; + } + + // did we already fail to establish implicit QoS for this AC? + // (if so, access should have been granted when the failure was handled) + if (pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessFailed) + { + // request previously failed + // allow access, but we'll be downgraded + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Implicit QoS for TL AC %d previously failed", + __func__, acType); + + if (!pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessRequired) + { + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE; + *pGranted = VOS_TRUE; + } + else + { + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_FALSE; + *pGranted = VOS_FALSE; + } + + return VOS_STATUS_SUCCESS; + } + + // we need to establish implicit QoS + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Need to schedule implicit QoS for TL AC %d, pAdapter is %p", + __func__, acType, pAdapter); + + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessNeeded = VOS_TRUE; + + pQosContext = kmalloc(sizeof(*pQosContext), GFP_ATOMIC); + if (NULL == pQosContext) + { + // no memory for QoS context. Nothing we can do but let data flow + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Unable to allocate context", __func__); + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_TRUE; + *pGranted = VOS_TRUE; + return VOS_STATUS_SUCCESS; + } + + pQosContext->acType = acType; + pQosContext->pAdapter = pAdapter; + pQosContext->qosFlowId = 0; + pQosContext->handle = HDD_WMM_HANDLE_IMPLICIT; + pQosContext->magic = HDD_WMM_CTX_MAGIC; + pQosContext->is_inactivity_timer_running = false; + +#ifdef CONFIG_CNSS + cnss_init_work(&pQosContext->wmmAcSetupImplicitQos, + hdd_wmm_do_implicit_qos); +#else +#ifdef WLAN_OPEN_SOURCE + INIT_WORK(&pQosContext->wmmAcSetupImplicitQos, + hdd_wmm_do_implicit_qos); +#endif +#endif + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Scheduling work for AC %d, context %p", + __func__, acType, pQosContext); + + schedule_work(&pQosContext->wmmAcSetupImplicitQos); + + // caller will need to wait until the work takes place and + // TSPEC negotiation completes + *pGranted = VOS_FALSE; + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief hdd_wmm_assoc() - Function which will handle the housekeeping + required by WMM when association takes place + + @param pAdapter : [in] pointer to adapter context + @param pRoamInfo: [in] pointer to roam information + @param eBssType : [in] type of BSS + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_assoc( hdd_adapter_t* pAdapter, + tCsrRoamInfo *pRoamInfo, + eCsrRoamBssType eBssType ) +{ + tANI_U8 uapsdMask; + VOS_STATUS status; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + // when we associate we need to notify TL if it needs to enable + // UAPSD for any access categories + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + + if (pRoamInfo->fReassocReq) + { + // when we reassociate we should continue to use whatever + // parameters were previously established. if we are + // reassociating due to a U-APSD change for a particular + // Access Category, then the change will be communicated + // to HDD via the QoS callback associated with the given + // flow, and U-APSD parameters will be updated there + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Reassoc so no work, Exiting", __func__); + + return VOS_STATUS_SUCCESS; + } + + // get the negotiated UAPSD Mask + uapsdMask = pRoamInfo->u.pConnectedProfile->modifyProfileFields.uapsd_mask; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: U-APSD mask is 0x%02x", __func__, (int) uapsdMask); + + if (uapsdMask & HDD_AC_VO) + { + status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + WLANTL_AC_VO, + 7, + 7, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSuspIntv, + WLANTL_BI_DIR, + 1, + pAdapter->sessionId); + + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status )); + } + + if (uapsdMask & HDD_AC_VI) + { + status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + WLANTL_AC_VI, + 5, + 5, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSuspIntv, + WLANTL_BI_DIR, + 1, + pAdapter->sessionId); + + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status )); + } + + if (uapsdMask & HDD_AC_BK) + { + status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + WLANTL_AC_BK, + 2, + 2, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSuspIntv, + WLANTL_BI_DIR, + 1, + pAdapter->sessionId); + + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status )); + } + + if (uapsdMask & HDD_AC_BE) + { + status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + WLANTL_AC_BE, + 3, + 3, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv, + (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSuspIntv, + WLANTL_BI_DIR, + 1, + pAdapter->sessionId); + + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status )); + } + + status = sme_UpdateDSCPtoUPMapping(pHddCtx->hHal, + pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId); + + if (!VOS_IS_STATUS_SUCCESS( status )) + { + hdd_wmm_init( pAdapter ); + } + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Exiting", __func__); + + return VOS_STATUS_SUCCESS; +} + + + +static const v_U8_t acmMaskBit[WLANTL_MAX_AC] = + { + 0x4, /* WLANTL_AC_BK */ + 0x8, /* WLANTL_AC_BE */ + 0x2, /* WLANTL_AC_VI */ + 0x1 /* WLANTL_AC_VO */ + }; + +/**============================================================================ + @brief hdd_wmm_connect() - Function which will handle the housekeeping + required by WMM when a connection is established + + @param pAdapter : [in] pointer to adapter context + @param pRoamInfo: [in] pointer to roam information + @param eBssType : [in] type of BSS + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_connect( hdd_adapter_t* pAdapter, + tCsrRoamInfo *pRoamInfo, + eCsrRoamBssType eBssType ) +{ + int ac; + v_BOOL_t qap; + v_BOOL_t qosConnection; + v_U8_t acmMask; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + + if ((eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType) && + pRoamInfo && + pRoamInfo->u.pConnectedProfile) { + qap = pRoamInfo->u.pConnectedProfile->qap; + qosConnection = pRoamInfo->u.pConnectedProfile->qosConnection; + acmMask = pRoamInfo->u.pConnectedProfile->acm_mask; + } else { + /* TODO: if a non-qos IBSS peer joins the group make qap and qosConnection + false. */ + qap = VOS_TRUE; + qosConnection = VOS_TRUE; + acmMask = 0x0; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: qap is %d, qosConnection is %d, acmMask is 0x%x", + __func__, qap, qosConnection, acmMask); + + pAdapter->hddWmmStatus.wmmQap = qap; + pAdapter->hddWmmStatus.wmmQosConnection = qosConnection; + + for (ac = 0; ac < WLANTL_MAX_AC; ac++) + { + if (qap && + qosConnection && + (acmMask & acmMaskBit[ac])) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: ac %d on", + __func__, ac); + + // admission is required + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_TRUE; + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_FALSE; + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessGranted = VOS_FALSE; + //after reassoc if we have valid tspec, allow access + if (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid && + (pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecInfo.ts_info.direction != + SME_QOS_WMM_TS_DIR_DOWNLINK)) { + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_TRUE; + + /* + * Making TSPEC invalid here so downgrading can happen while + * roaming. It is expected this will be SET in hdd_wmm_sme_callback, + * once sme is done with the AddTspec. + * Here we avoid 11r and ccx based association because Tspec will + * be part of assoc/reassoc request. + */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL( "fReassocReq = %d" +#if defined (FEATURE_WLAN_ESE) + "isESEAssoc = %d" +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) + "is11rAssoc = %d" +#endif + ), + pRoamInfo->fReassocReq +#if defined (FEATURE_WLAN_ESE) + ,pRoamInfo->isESEAssoc +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) + ,pRoamInfo->is11rAssoc +#endif + ); + if ( !pRoamInfo->fReassocReq +#if defined (WLAN_FEATURE_VOWIFI_11R) + && + !pRoamInfo->is11rAssoc +#endif +#if defined (FEATURE_WLAN_ESE) + && + !pRoamInfo->isESEAssoc +#endif + ) + { + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid = + VOS_FALSE; + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = + VOS_FALSE; + } + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: ac %d off", + __func__, ac); + // admission is not required so access is allowed + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired = VOS_FALSE; + pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed = VOS_TRUE; + } + + } + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Exiting", __func__); + + return VOS_STATUS_SUCCESS; +} + +/**============================================================================ + @brief hdd_wmm_get_uapsd_mask() - Function which will calculate the + initial value of the UAPSD mask based upon the device configuration + + @param pAdapter : [in] pointer to adapter context + @param pUapsdMask: [in] pointer to where the UAPSD Mask is to be stored + + @return : VOS_STATUS_SUCCESS if successful + : other values if failure + ===========================================================================*/ +VOS_STATUS hdd_wmm_get_uapsd_mask( hdd_adapter_t* pAdapter, + tANI_U8 *pUapsdMask ) +{ + tANI_U8 uapsdMask; + + if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode) + { + // no QOS then no UAPSD + uapsdMask = 0; + } + else + { + // start with the default mask + uapsdMask = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask; + + // disable UAPSD for any ACs with a 0 Service Interval + if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdVoSrvIntv == 0 ) + { + uapsdMask &= ~HDD_AC_VO; + } + + if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdViSrvIntv == 0 ) + { + uapsdMask &= ~HDD_AC_VI; + } + + if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBkSrvIntv == 0 ) + { + uapsdMask &= ~HDD_AC_BK; + } + + if( (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->InfraUapsdBeSrvIntv == 0 ) + { + uapsdMask &= ~HDD_AC_BE; + } + } + + // return calculated mask + *pUapsdMask = uapsdMask; + return VOS_STATUS_SUCCESS; +} + + +/**============================================================================ + @brief hdd_wmm_is_active() - Function which will determine if WMM is + active on the current connection + + @param pAdapter : [in] pointer to adapter context + + @return : VOS_TRUE if WMM is enabled + : VOS_FALSE if WMM is not enabled + ===========================================================================*/ +v_BOOL_t hdd_wmm_is_active( hdd_adapter_t* pAdapter ) +{ + if ((!pAdapter->hddWmmStatus.wmmQosConnection) || + (!pAdapter->hddWmmStatus.wmmQap)) + { + return VOS_FALSE; + } + else + { + return VOS_TRUE; + } +} + +/**============================================================================ + @brief hdd_wmm_addts() - Function which will add a traffic spec at the + request of an application + + @param pAdapter : [in] pointer to adapter context + @param handle : [in] handle to uniquely identify a TS + @param pTspec : [in] pointer to the traffic spec + + @return : HDD_WLAN_WMM_STATUS_* + ===========================================================================*/ +hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter, + v_U32_t handle, + sme_QosWmmTspecInfo* pTspec ) +{ + hdd_wmm_qos_context_t *pQosContext; + hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosStatusType smeStatus; +#endif + v_BOOL_t found = VOS_FALSE; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered with handle 0x%x", __func__, handle); + + // see if a context already exists with the given handle + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + list_for_each_entry(pQosContext, + &pAdapter->hddWmmStatus.wmmContextList, + node) + { + if (pQosContext->handle == handle) + { + found = VOS_TRUE; + break; + } + } + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + if (found) + { + // record with that handle already exists + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Record already exists with handle 0x%x", + __func__, handle); + + /* Application is trying to modify some of the Tspec params. Allow it */ + smeStatus = sme_QosModifyReq(WLAN_HDD_GET_HAL_CTX(pAdapter), + pTspec, + pQosContext->qosFlowId); + + // need to check the return value and act appropriately + switch (smeStatus) + { + case SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP: + status = HDD_WLAN_WMM_STATUS_MODIFY_PENDING; + break; + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP: + status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_NO_UAPSD; + break; + case SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY: + status = HDD_WLAN_WMM_STATUS_MODIFY_SUCCESS_NO_ACM_UAPSD_EXISTING; + break; + case SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP: + status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED_BAD_PARAM; + break; + case SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP: + status = HDD_WLAN_WMM_STATUS_MODIFY_FAILED; + break; + case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP: + status = HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM; + break; + default: + // we didn't get back one of the SME_QOS_STATUS_MODIFY_* status codes + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus ); + VOS_ASSERT(0); + return HDD_WLAN_WMM_STATUS_MODIFY_FAILED; + } + + /* we were successful, save the status */ + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + if (pQosContext->magic == HDD_WMM_CTX_MAGIC) + pQosContext->lastStatus = status; + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + + return status; + } + + pQosContext = kmalloc(sizeof(*pQosContext), GFP_KERNEL); + if (NULL == pQosContext) + { + // no memory for QoS context. Nothing we can do + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Unable to allocate QoS context", __func__); + return HDD_WLAN_WMM_STATUS_INTERNAL_FAILURE; + } + + // we assume the tspec has already been validated by the caller + + pQosContext->handle = handle; + if (pTspec->ts_info.up < HDD_WMM_UP_TO_AC_MAP_SIZE) + pQosContext->acType = hddWmmUpToAcMap[pTspec->ts_info.up]; + else { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: ts_info.up (%d) larger than max value (%d), use default acType (%d)", + __func__, pTspec->ts_info.up, + HDD_WMM_UP_TO_AC_MAP_SIZE - 1, hddWmmUpToAcMap[0]); + pQosContext->acType = hddWmmUpToAcMap[0]; + } + pQosContext->pAdapter = pAdapter; + pQosContext->qosFlowId = 0; + pQosContext->magic = HDD_WMM_CTX_MAGIC; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Setting up QoS, context %p", + __func__, pQosContext); + + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + list_add(&pQosContext->node, &pAdapter->hddWmmStatus.wmmContextList); + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + smeStatus = sme_QosSetupReq(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + pTspec, + hdd_wmm_sme_callback, + pQosContext, + pTspec->ts_info.up, + &pQosContext->qosFlowId); + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: sme_QosSetupReq returned %d flowid %d", + __func__, smeStatus, pQosContext->qosFlowId); + + // need to check the return value and act appropriately + switch (smeStatus) + { + case SME_QOS_STATUS_SETUP_REQ_PENDING_RSP: + status = HDD_WLAN_WMM_STATUS_SETUP_PENDING; + break; + case SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP: + status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_NO_UAPSD; + break; + case SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY: + status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS_NO_ACM_UAPSD_EXISTING; + break; + case SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING: + status = HDD_WLAN_WMM_STATUS_SETUP_PENDING; + break; + case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP: + hdd_wmm_free_context(pQosContext); + return HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM; + case SME_QOS_STATUS_SETUP_FAILURE_RSP: + /* + * We can't tell the difference between when a request fails because + * AP rejected it versus when SME encountered an internal error + */ + hdd_wmm_free_context(pQosContext); + return HDD_WLAN_WMM_STATUS_SETUP_FAILED; + case SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP: + hdd_wmm_free_context(pQosContext); + return HDD_WLAN_WMM_STATUS_SETUP_FAILED_NO_WMM; + default: + // we didn't get back one of the SME_QOS_STATUS_SETUP_* status codes + hdd_wmm_free_context(pQosContext); + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus ); + VOS_ASSERT(0); + return HDD_WLAN_WMM_STATUS_SETUP_FAILED; + } +#endif + + /* we were successful, save the status */ + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + if (pQosContext->magic == HDD_WMM_CTX_MAGIC) + pQosContext->lastStatus = status; + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + + return status; +} + +/**============================================================================ + @brief hdd_wmm_delts() - Function which will delete a traffic spec at the + request of an application + + @param pAdapter : [in] pointer to adapter context + @param handle : [in] handle to uniquely identify a TS + + @return : HDD_WLAN_WMM_STATUS_* + ===========================================================================*/ +hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter, + v_U32_t handle ) +{ + hdd_wmm_qos_context_t *pQosContext; + v_BOOL_t found = VOS_FALSE; + WLANTL_ACEnumType acType = 0; + v_U32_t qosFlowId = 0; + hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_SETUP_SUCCESS ; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosStatusType smeStatus; +#endif + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered with handle 0x%x", __func__, handle); + + // locate the context with the given handle + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + list_for_each_entry(pQosContext, + &pAdapter->hddWmmStatus.wmmContextList, + node) + { + if (pQosContext->handle == handle) + { + found = VOS_TRUE; + acType = pQosContext->acType; + qosFlowId = pQosContext->qosFlowId; + break; + } + } + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + + if (VOS_FALSE == found) + { + // we didn't find the handle + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: handle 0x%x not found", __func__, handle); + return HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM; + } + + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: found handle 0x%x, flow %d, AC %d, context %p", + __func__, handle, qosFlowId, acType, pQosContext); + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + smeStatus = sme_QosReleaseReq( WLAN_HDD_GET_HAL_CTX(pAdapter), qosFlowId ); + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: SME flow %d released, SME status %d", + __func__, qosFlowId, smeStatus); + + switch(smeStatus) + { + case SME_QOS_STATUS_RELEASE_SUCCESS_RSP: + // this flow is the only one on that AC, so go ahead and update + // our TSPEC state for the AC + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcTspecValid = VOS_FALSE; + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = VOS_FALSE; + + // need to tell TL to stop trigger timer, etc + hdd_wmm_disable_tl_uapsd(pQosContext); + +#ifdef FEATURE_WLAN_ESE + // disable the inactivity timer + hdd_wmm_disable_inactivity_timer(pQosContext); +#endif + // we are done with this context + hdd_wmm_free_context(pQosContext); + + // SME must not fire any more callbacks for this flow since the context + // is no longer valid + + return HDD_WLAN_WMM_STATUS_RELEASE_SUCCESS; + + case SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP: + // do nothing as we will get a response from SME + status = HDD_WLAN_WMM_STATUS_RELEASE_PENDING; + break; + + case SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP: + // nothing we can do with the existing flow except leave it + status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED_BAD_PARAM; + break; + + case SME_QOS_STATUS_RELEASE_FAILURE_RSP: + // nothing we can do with the existing flow except leave it + status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED; + + default: + // we didn't get back one of the SME_QOS_STATUS_RELEASE_* status codes + VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus ); + VOS_ASSERT(0); + status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED; + } + +#endif + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + if (pQosContext->magic == HDD_WMM_CTX_MAGIC) + pQosContext->lastStatus = status; + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + + return status; +} + +/**============================================================================ + @brief hdd_wmm_checkts() - Function which will return the status of a traffic + spec at the request of an application + + @param pAdapter : [in] pointer to adapter context + @param handle : [in] handle to uniquely identify a TS + + @return : HDD_WLAN_WMM_STATUS_* + ===========================================================================*/ +hdd_wlan_wmm_status_e hdd_wmm_checkts( hdd_adapter_t* pAdapter, + v_U32_t handle ) +{ + hdd_wmm_qos_context_t *pQosContext; + hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_LOST; + + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered with handle 0x%x", __func__, handle); + + // locate the context with the given handle + mutex_lock(&pAdapter->hddWmmStatus.wmmLock); + list_for_each_entry(pQosContext, + &pAdapter->hddWmmStatus.wmmContextList, + node) + { + if (pQosContext->handle == handle) + { + VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: found handle 0x%x, context %p", + __func__, handle, pQosContext); + + status = pQosContext->lastStatus; + break; + } + } + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + return status; +} diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wowl.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wowl.c new file mode 100644 index 000000000000..0b33988b00b0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wowl.c @@ -0,0 +1,615 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ + * @file wlan_hdd_wowl.c + * + * + * ==========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + +#include +#include + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define WOWL_INTER_PTRN_TOKENIZER ';' +#define WOWL_INTRA_PTRN_TOKENIZER ':' + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +static char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED]; //Patterns 0-15 +static v_BOOL_t g_hdd_wowl_ptrns_debugfs[WOWL_MAX_PTRNS_ALLOWED] = {0}; +static v_U8_t g_hdd_wowl_ptrns_count = 0; + +int hdd_parse_hex(unsigned char c) +{ + if (c >= '0' && c <= '9') + return c-'0'; + if (c >= 'a' && c <= 'f') + return c-'a'+10; + if (c >= 'A' && c <= 'F') + return c-'A'+10; + + return 0; +} + +static inline int find_ptrn_len(const char* ptrn) +{ + int len = 0; + while (*ptrn != '\0' && *ptrn != WOWL_INTER_PTRN_TOKENIZER) + { + len++; ptrn++; + } + return len; +} + +static void hdd_wowl_callback( void *pContext, eHalStatus halStatus ) +{ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Return code = (%d)", __func__, halStatus ); +} + +#ifdef WLAN_WAKEUP_EVENTS +static void hdd_wowl_wakeIndication_callback( void *pContext, + tpSirWakeReasonInd pWakeReasonInd ) +{ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Wake Reason %d", + __func__, pWakeReasonInd->ulReason ); + hdd_exit_wowl((hdd_adapter_t *)pContext); +} +#endif + +static void dump_hdd_wowl_ptrn(tSirWowlAddBcastPtrn *ptrn) +{ + int i; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatetrnId = 0x%x", __func__, + ptrn->ucPatternId); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatternByteOffset = 0x%x", __func__, + ptrn->ucPatternByteOffset); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatternSize = 0x%x", __func__, + ptrn->ucPatternSize); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ucPatternMaskSize = 0x%x", __func__, + ptrn->ucPatternMaskSize); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Pattern: ", __func__); + for(i = 0; i < ptrn->ucPatternSize; i++) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO," %02X", ptrn->ucPattern[i]); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: PatternMask: ", __func__); + for(i = 0; iucPatternMaskSize; i++) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%02X", ptrn->ucPatternMask[i]); +} + + +/**============================================================================ + @brief hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be + used when PBM filtering is enabled + + @param ptrn : [in] pointer to the pattern string to be added + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) +{ + tSirWowlAddBcastPtrn localPattern; + int i, first_empty_slot, len, offset; + eHalStatus halStatus; + const char *temp; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U8_t sessionId = pAdapter->sessionId; + hdd_context_t *pHddCtx = pAdapter->pHddCtx; + + len = find_ptrn_len(ptrn); + + /* There has to have atleast 1 byte for each field (pattern size, mask size, + * pattern, mask) e.g. PP:QQ:RR:SS ==> 11 chars */ + while ( len >= 11 ) + { + // Detect duplicate pattern + for (i=0; icfg_ini->maxWoWFilters; i++) + { + if(g_hdd_wowl_ptrns[i] == NULL) continue; + + if(!memcmp(ptrn, g_hdd_wowl_ptrns[i], len)) + { + // Pattern Already configured, skip to next pattern + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Trying to add duplicate WoWL pattern. Skip it!"); + ptrn += len; + goto next_ptrn; + } + } + + first_empty_slot = -1; + + // Find an empty slot to store the pattern + for (i=0; icfg_ini->maxWoWFilters; i++) + { + if(g_hdd_wowl_ptrns[i] == NULL) { + first_empty_slot = i; + break; + } + } + + // Maximum number of patterns have been configured already + if(first_empty_slot == -1) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot add anymore patterns. No free slot!", __func__); + return VOS_FALSE; + } + + //Validate the pattern + if(ptrn[2] != WOWL_INTRA_PTRN_TOKENIZER || + ptrn[5] != WOWL_INTRA_PTRN_TOKENIZER) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Malformed pattern string. Skip!", __func__); + ptrn += len; + goto next_ptrn; + } + + // Extract the pattern size + localPattern.ucPatternSize = + ( hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); + + // Extract the pattern mask size + localPattern.ucPatternMaskSize = + ( hdd_parse_hex( ptrn[3] ) * 0x10 ) + hdd_parse_hex( ptrn[4] ); + + if(localPattern.ucPatternSize > SIR_WOWL_BCAST_PATTERN_MAX_SIZE || + localPattern.ucPatternMaskSize > WOWL_PTRN_MASK_MAX_SIZE) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid length specified. Skip!", __func__); + ptrn += len; + goto next_ptrn; + } + + //compute the offset of tokenizer after the pattern + offset = 5 + 2*localPattern.ucPatternSize + 1; + if(offset >= len || ptrn[offset] != WOWL_INTRA_PTRN_TOKENIZER) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Malformed pattern string..skip!", __func__); + ptrn += len; + goto next_ptrn; + } + + /* Compute the end of pattern string */ + offset = offset + 2*localPattern.ucPatternMaskSize; + if(offset+1 != len) //offset begins with 0 + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Malformed pattern string...skip!", __func__); + ptrn += len; + goto next_ptrn; + } + + temp = ptrn; + + // Now advance to where pattern begins + ptrn += 6; + + // Extract the pattern + for(i=0; i < localPattern.ucPatternSize; i++) + { + localPattern.ucPattern[i] = + (hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); + ptrn += 2; //skip to next byte + } + + ptrn++; /* Skip over the ':' separator after the pattern */ + + // Extract the pattern Mask + for(i=0; i < localPattern.ucPatternMaskSize; i++) + { + localPattern.ucPatternMask[i] = + (hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); + ptrn += 2; //skip to next byte + } + + //All is good. Store the pattern locally + g_hdd_wowl_ptrns[first_empty_slot] = (char*) kmalloc(len+1, GFP_KERNEL); + if(g_hdd_wowl_ptrns[first_empty_slot] == NULL) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kmalloc failure", __func__); + return VOS_FALSE; + } + + memcpy(g_hdd_wowl_ptrns[first_empty_slot], temp, len); + g_hdd_wowl_ptrns[first_empty_slot][len] = '\0'; + localPattern.ucPatternId = first_empty_slot; + localPattern.ucPatternByteOffset = 0; + localPattern.sessionId = sessionId; + + // Register the pattern downstream + halStatus = sme_WowlAddBcastPattern( hHal, &localPattern, sessionId ); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + // Add failed, so invalidate the local storage + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "sme_WowlAddBcastPattern failed with error code (%d)", halStatus ); + kfree(g_hdd_wowl_ptrns[first_empty_slot]); + g_hdd_wowl_ptrns[first_empty_slot] = NULL; + } + + dump_hdd_wowl_ptrn(&localPattern); + + next_ptrn: + if (*ptrn == WOWL_INTER_PTRN_TOKENIZER) + { + ptrn += 1; // move past the tokenizer + len = find_ptrn_len(ptrn); + continue; + } + else + break; + } + + return VOS_TRUE; +} + +/**============================================================================ + @brief hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern + + @param ptrn : [in] pointer to the pattern string to be removed + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_del_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) +{ + tSirWowlDelBcastPtrn delPattern; + unsigned char id; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_BOOL_t patternFound = VOS_FALSE; + eHalStatus halStatus; + v_U8_t sessionId = pAdapter->sessionId; + hdd_context_t *pHddCtx = pAdapter->pHddCtx; + + // Detect pattern + for (id=0; idcfg_ini->maxWoWFilters && g_hdd_wowl_ptrns[id] != NULL; id++) + { + if(!strcmp(ptrn, g_hdd_wowl_ptrns[id])) + { + patternFound = VOS_TRUE; + break; + } + } + + // If pattern present, remove it from downstream + if(patternFound) + { + delPattern.ucPatternId = id; + halStatus = sme_WowlDelBcastPattern( hHal, &delPattern, sessionId ); + if ( HAL_STATUS_SUCCESS( halStatus ) ) + { + // Remove from local storage as well + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Deleted pattern with id %d [%s]", id, g_hdd_wowl_ptrns[id]); + + kfree(g_hdd_wowl_ptrns[id]); + g_hdd_wowl_ptrns[id] = NULL; + return VOS_TRUE; + } + } + return VOS_FALSE; +} + +/**============================================================================ + @brief hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern + sent from debugfs interface + + @param pAdapter : [in] pointer to the adapter + pattern_idx : [in] index of the pattern to be added + pattern_offset : [in] offset of the pattern in the frame payload + pattern_buf : [in] pointer to the pattern hex string to be added + pattern_mask : [in] pointer to the pattern mask hex string + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx, + v_U8_t pattern_offset, char *pattern_buf, + char *pattern_mask) +{ + tSirWowlAddBcastPtrn localPattern; + eHalStatus halStatus; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + v_U8_t sessionId = pAdapter->sessionId; + v_U16_t pattern_len, mask_len, i; + + if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WoW pattern index %d is out of range (0 ~ %d).", + __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1); + + return VOS_FALSE; + } + + pattern_len = strlen(pattern_buf); + + /* Since the pattern is a hex string, 2 characters represent 1 byte. */ + if (pattern_len % 2) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Malformed WoW pattern!", __func__); + + return VOS_FALSE; + } + else + pattern_len >>= 1; + + if (!pattern_len || pattern_len > WOWL_PTRN_MAX_SIZE) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WoW pattern length %d is out of range (1 ~ %d).", + __func__, pattern_len, WOWL_PTRN_MAX_SIZE); + + return VOS_FALSE; + } + + localPattern.ucPatternId = pattern_idx; + localPattern.ucPatternByteOffset = pattern_offset; + localPattern.ucPatternSize = pattern_len; + localPattern.sessionId = sessionId; + + if (localPattern.ucPatternSize > SIR_WOWL_BCAST_PATTERN_MAX_SIZE) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WoW pattern size (%d) greater than max (%d)", + __func__, localPattern.ucPatternSize, + SIR_WOWL_BCAST_PATTERN_MAX_SIZE); + return VOS_FALSE; + } + /* Extract the pattern */ + for (i = 0; i < localPattern.ucPatternSize; i++) + { + localPattern.ucPattern[i] = + (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]); + + /* Skip to next byte */ + pattern_buf += 2; + } + + /* Get pattern mask size by pattern length */ + localPattern.ucPatternMaskSize = pattern_len >> 3; + if (pattern_len % 8) + localPattern.ucPatternMaskSize += 1; + + mask_len = strlen(pattern_mask); + if ((mask_len % 2) || (localPattern.ucPatternMaskSize != (mask_len >> 1))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Malformed WoW pattern mask!", __func__); + + return VOS_FALSE; + } + if (localPattern.ucPatternMaskSize > WOWL_PTRN_MASK_MAX_SIZE) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WoW pattern mask size (%d) greater than max (%d)", + __func__, localPattern.ucPatternMaskSize, WOWL_PTRN_MASK_MAX_SIZE); + return VOS_FALSE; + } + /* Extract the pattern mask */ + for (i = 0; i < localPattern.ucPatternMaskSize; i++) + { + localPattern.ucPatternMask[i] = + (hdd_parse_hex(pattern_mask[0]) << 4) + hdd_parse_hex(pattern_mask[1]); + + /* Skip to next byte */ + pattern_mask += 2; + } + + /* Register the pattern downstream */ + halStatus = sme_WowlAddBcastPattern(hHal, &localPattern, sessionId); + + if (!HAL_STATUS_SUCCESS(halStatus)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_WowlAddBcastPattern failed with error code (%d).", + __func__, halStatus); + + return VOS_FALSE; + } + + /* All is good. */ + if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) + { + g_hdd_wowl_ptrns_debugfs[pattern_idx] = 1; + g_hdd_wowl_ptrns_count++; + } + + dump_hdd_wowl_ptrn(&localPattern); + + return VOS_TRUE; +} + +/**============================================================================ + @brief hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern + sent from debugfs interface + + @param pAdapter : [in] pointer to the adapter + pattern_idx : [in] index of the pattern to be removed + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, v_U8_t pattern_idx) +{ + tSirWowlDelBcastPtrn delPattern; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + eHalStatus halStatus; + v_U8_t sessionId = pAdapter->sessionId; + + if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WoW pattern index %d is not in the range (0 ~ %d).", + __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1); + + return VOS_FALSE; + } + + if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: WoW pattern %d is not in the table.", + __func__, pattern_idx); + + return VOS_FALSE; + } + + delPattern.ucPatternId = pattern_idx; + halStatus = sme_WowlDelBcastPattern(hHal, &delPattern, sessionId); + + if (!HAL_STATUS_SUCCESS(halStatus)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_WowlDelBcastPattern failed with error code (%d).", + __func__, halStatus); + + return VOS_FALSE; + } + + g_hdd_wowl_ptrns_debugfs[pattern_idx] = 0; + g_hdd_wowl_ptrns_count--; + + return VOS_TRUE; +} + +/**============================================================================ + @brief hdd_enter_wowl() - Function which will enable WoWL. Atleast one + of MP and PBM must be enabled + + @param enable_mp : [in] Whether to enable magic packet WoWL mode + @param enable_pbm : [in] Whether to enable pattern byte matching WoWL mode + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_enter_wowl (hdd_adapter_t *pAdapter, v_BOOL_t enable_mp, v_BOOL_t enable_pbm) +{ + tSirSmeWowlEnterParams wowParams; + eHalStatus halStatus; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + + vos_mem_zero( &wowParams, sizeof( tSirSmeWowlEnterParams)); + + wowParams.ucPatternFilteringEnable = enable_pbm; + wowParams.ucMagicPktEnable = enable_mp; + wowParams.sessionId = pAdapter->sessionId; + if(enable_mp) + { + vos_copy_macaddr( (v_MACADDR_t *)&(wowParams.magicPtrn), + &(pAdapter->macAddressCurrent) ); + } + +#ifdef WLAN_WAKEUP_EVENTS + wowParams.ucWoWEAPIDRequestEnable = VOS_TRUE; + wowParams.ucWoWEAPOL4WayEnable = VOS_TRUE; + wowParams.ucWowNetScanOffloadMatch = VOS_TRUE; + wowParams.ucWowGTKRekeyError = VOS_TRUE; + wowParams.ucWoWBSSConnLoss = VOS_TRUE; +#endif // WLAN_WAKEUP_EVENTS + + + // Request to put Libra into WoWL + halStatus = sme_EnterWowl( hHal, hdd_wowl_callback, + pAdapter, +#ifdef WLAN_WAKEUP_EVENTS + hdd_wowl_wakeIndication_callback, + pAdapter, +#endif // WLAN_WAKEUP_EVENTS + &wowParams, pAdapter->sessionId); + + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + if ( eHAL_STATUS_PMC_PENDING != halStatus ) + { + // We failed to enter WoWL + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "sme_EnterWowl failed with error code (%d)", halStatus ); + return VOS_FALSE; + } + } + return VOS_TRUE; +} + +/**============================================================================ + @brief hdd_exit_wowl() - Function which will disable WoWL + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_exit_wowl (hdd_adapter_t*pAdapter) +{ + tSirSmeWowlExitParams wowParams; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + eHalStatus halStatus; + + wowParams.sessionId = pAdapter->sessionId; + + halStatus = sme_ExitWowl( hHal, &wowParams); + if ( !HAL_STATUS_SUCCESS( halStatus ) ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "sme_ExitWowl failed with error code (%d)", halStatus ); + return VOS_FALSE; + } + + return VOS_TRUE; +} + +/**============================================================================ + @brief hdd_init_wowl() - Init function which will initialize the WoWL module + and perform any required initial configuration + + @return : FALSE if any errors encountered + : TRUE otherwise + ===========================================================================*/ +v_BOOL_t hdd_init_wowl (hdd_adapter_t*pAdapter) +{ + hdd_context_t *pHddCtx = NULL; + pHddCtx = pAdapter->pHddCtx; + + memset(g_hdd_wowl_ptrns, 0, sizeof(g_hdd_wowl_ptrns)); + + //Add any statically configured patterns + hdd_add_wowl_ptrn(pAdapter, pHddCtx->cfg_ini->wowlPattern); + + return VOS_TRUE; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h new file mode 100644 index 000000000000..22c95bbd8f19 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h @@ -0,0 +1,1276 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * aniGlobal.h: MAC Modules Adapter Definitions. + * Author: V. K. Kandarpa + * Date: 10/25/2002 + * + * History:- + * Date: 04/08/2008 Modified by: Santosh Mandiganal + * Modification Information: Added the logDump.h header file and defined the + * dumpTablecurrentId, dumpTableEntry. + * -------------------------------------------------------------------------- + * + */ + +#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" +#include "sysDef.h" +#include "dphGlobal.h" +#include "limGlobal.h" +#include "pmmGlobal.h" +#include "schGlobal.h" +#include "sysGlobal.h" +#include "cfgGlobal.h" +#include "utilsGlobal.h" +#include "sirApi.h" + + +#include "wlan_qct_hal.h" + +#include "pmc.h" + +#include "csrApi.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "sme_FTApi.h" +#endif +#include "csrSupport.h" +#include "smeInternal.h" +#include "sapApi.h" +#include "ccmApi.h" +#include "btcApi.h" +#include "csrInternal.h" + +#ifdef FEATURE_OEM_DATA_SUPPORT +#include "oemDataInternal.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI +#include "smeRrmInternal.h" +#include "rrmGlobal.h" +#endif +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseApi.h" +#include "eseGlobal.h" +#endif +#include "p2p_Api.h" + +#if defined WLAN_FEATURE_VOWIFI_11R +#include +#endif + + +// New HAL API interface defs. +#include "logDump.h" + +//Check if this definition can actually move here from halInternal.h even for Volans. In that case +//this featurization can be removed. +#define PMAC_STRUCT( _hHal ) ( (tpAniSirGlobal)_hHal ) + +#define ANI_DRIVER_TYPE(pMac) (((tpAniSirGlobal)(pMac))->gDriverType) + +#define IS_MIRACAST_SESSION_PRESENT(pMac) (((tpAniSirGlobal)(pMac))->fMiracastSessionPresent ? 1 : 0) +// ------------------------------------------------------------------- +// Bss Qos Caps bit map definition +#define LIM_BSS_CAPS_OFFSET_HCF 0 +#define LIM_BSS_CAPS_OFFSET_WME 1 +#define LIM_BSS_CAPS_OFFSET_WSM 2 + +#define LIM_BSS_CAPS_HCF (1 << LIM_BSS_CAPS_OFFSET_HCF) +#define LIM_BSS_CAPS_WME (1 << LIM_BSS_CAPS_OFFSET_WME) +#define LIM_BSS_CAPS_WSM (1 << LIM_BSS_CAPS_OFFSET_WSM) + +// cap should be one of HCF/WME/WSM +#define LIM_BSS_CAPS_GET(cap, val) (((val) & (LIM_BSS_CAPS_ ## cap)) >> LIM_BSS_CAPS_OFFSET_ ## cap) +#define LIM_BSS_CAPS_SET(cap, val) ((val) |= (LIM_BSS_CAPS_ ## cap )) +#define LIM_BSS_CAPS_CLR(cap, val) ((val) &= (~ (LIM_BSS_CAPS_ ## cap))) + +// 40 beacons per heart beat interval is the default + 1 to count the rest +#define MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL 41 + +/* max number of legacy bssid we can store during scan on one channel */ +#define MAX_NUM_LEGACY_BSSID_PER_CHANNEL 10 + +#define P2P_WILDCARD_SSID "DIRECT-" //TODO Put it in proper place; +#define P2P_WILDCARD_SSID_LEN 7 + +#ifdef WLAN_FEATURE_CONCURRENT_P2P +#define MAX_NO_OF_P2P_SESSIONS 5 +#endif //WLAN_FEATURE_CONCURRENT_P2P + +#define SPACE_ASCII_VALUE 32 + +#define WLAN_HOST_SEQ_NUM_MIN 2048 +#define WLAN_HOST_SEQ_NUM_MAX 4095 +#define LOW_SEQ_NUM_MASK 0x000F +#define HIGH_SEQ_NUM_MASK 0x0FF0 +#define HIGH_SEQ_NUM_OFFSET 4 + +/* + * NSS cfg bit definition. + * STA BIT[0:1] + * SAP BIT[2:3] + * P2P_GO BIT[4:5] + * P2P_CLIENT BIT[6:7] + * IBSS BIT[8:9] + * TDLS BIT[10:11] + * P2P_DEVICE BIT[12:13] + * OCB BIT[14:15] + */ + +#define CFG_STA_NSS(_x) ((((_x) >> 0) & 0x3) ? (((_x) >> 0) & 0x3) : 1) +#define CFG_SAP_NSS(_x) ((((_x) >> 2) & 0x3) ? (((_x) >> 2) & 0x3) : 1) +#define CFG_P2P_GO_NSS(_x) ((((_x) >> 4) & 0x3) ? (((_x) >> 4) & 0x3) : 1) +#define CFG_P2P_CLI_NSS(_x) ((((_x) >> 6) & 0x3) ? (((_x) >> 6) & 0x3) : 1) +#define CFG_IBSS_NSS(_x) ((((_x) >> 8) & 0x3) ? (((_x) >> 8) & 0x3) : 1) +#define CFG_TDLS_NSS(_x) ((((_x) >> 10) & 0x3) ? (((_x) >> 10) & 0x3) : 1) +#define CFG_P2P_DEV_NSS(_x) ((((_x) >> 12) & 0x3) ? (((_x) >> 12) & 0x3) : 1) +#define CFG_OCB_NSS(_x) ((((_x) >> 14) & 0x3) ? (((_x) >> 14) & 0x3) : 1) + +/** + * enum log_event_type - Type of event initiating bug report + * @WLAN_LOG_TYPE_NON_FATAL: Non fatal event + * @WLAN_LOG_TYPE_FATAL: Fatal event + * + * Enum indicating the type of event that is initiating the bug report + */ +enum log_event_type { + WLAN_LOG_TYPE_NON_FATAL, + WLAN_LOG_TYPE_FATAL, +}; + +/** + * enum log_event_indicator - Module triggering bug report + * @WLAN_LOG_INDICATOR_UNUSED: Unused + * @WLAN_LOG_INDICATOR_FRAMEWORK: Framework triggers bug report + * @WLAN_LOG_INDICATOR_HOST_DRIVER: Host driver triggers bug report + * @WLAN_LOG_INDICATOR_FIRMWARE: FW initiates bug report + * + * Enum indicating the module that triggered the bug report + */ +enum log_event_indicator { + WLAN_LOG_INDICATOR_UNUSED, + WLAN_LOG_INDICATOR_FRAMEWORK, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_INDICATOR_FIRMWARE, +}; + +/** + * enum log_event_host_reason_code - Reason code for bug report + * @WLAN_LOG_REASON_CODE_UNUSED: Unused + * @WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL: Command response status from FW + * is error + * @WLAN_LOG_REASON_ROAM_FAIL: Driver initiated roam has failed + * @WLAN_LOG_REASON_THREAD_STUCK: Monitor Health of host threads and report + * fatal event if some thread is stuck + * @WLAN_LOG_REASON_DATA_STALL: Unable to send/receive data due to low resource + * scenario for a prolonged period + * @WLAN_LOG_REASON_SME_COMMAND_STUCK: SME command is stuck in SME active queue + * @WLAN_LOG_REASON_ZERO_SCAN_RESULTS: Full scan resulted in zero scan results + * @WLAN_LOG_REASON_QUEUE_FULL: Defer queue becomes full for a prolonged period + * @WLAN_LOG_REASON_POWER_COLLAPSE_FAIL: Unable to allow apps power collapse + * for a prolonged period + * @WLAN_LOG_REASON_SSR_FAIL: Unable to gracefully complete SSR + * @WLAN_LOG_REASON_DISCONNECT_FAIL: Disconnect from Supplicant is not + * successful + * @WLAN_LOG_REASON_CLEAN_UP_FAIL: Clean up of TDLS or Pre-Auth Sessions + * not successful + * @WLAN_LOG_REASON_MALLOC_FAIL: Memory allocation Fails + * @WLAN_LOG_REASON_VOS_MSG_UNDER_RUN: VOS Core runs out of message wrapper + * @WLAN_LOG_REASON_MSG_POST_FAIL: Unable to post msg + * + * This enum contains the different reason codes for bug report + */ +enum log_event_host_reason_code { + WLAN_LOG_REASON_CODE_UNUSED, + WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL, + WLAN_LOG_REASON_ROAM_FAIL, + WLAN_LOG_REASON_THREAD_STUCK, + WLAN_LOG_REASON_DATA_STALL, + WLAN_LOG_REASON_SME_COMMAND_STUCK, + WLAN_LOG_REASON_ZERO_SCAN_RESULTS, + WLAN_LOG_REASON_QUEUE_FULL, + WLAN_LOG_REASON_POWER_COLLAPSE_FAIL, + WLAN_LOG_REASON_SSR_FAIL, + WLAN_LOG_REASON_DISCONNECT_FAIL, + WLAN_LOG_REASON_CLEAN_UP_FAIL, + WLAN_LOG_REASON_MALLOC_FAIL, + WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, + WLAN_LOG_REASON_MSG_POST_FAIL, +}; + +/** + * enum userspace_log_level - Log level at userspace + * @LOG_LEVEL_NO_COLLECTION: verbose_level 0 corresponds to no collection + * @LOG_LEVEL_NORMAL_COLLECT: verbose_level 1 correspond to normal log level, + * with minimal user impact. this is the default value + * @LOG_LEVEL_ISSUE_REPRO: verbose_level 2 are enabled when user is lazily + * trying to reproduce a problem, wifi performances and power can be impacted + * but device should not otherwise be significantly impacted + * @LOG_LEVEL_ACTIVE: verbose_level 3+ are used when trying to + * actively debug a problem + * + * Various log levels defined in the userspace for logging applications + */ +enum userspace_log_level { + LOG_LEVEL_NO_COLLECTION, + LOG_LEVEL_NORMAL_COLLECT, + LOG_LEVEL_ISSUE_REPRO, + LOG_LEVEL_ACTIVE, +}; + +/** + * enum wifi_driver_log_level - Log level defined in the driver for logging + * @WLAN_LOG_LEVEL_OFF: No logging + * @WLAN_LOG_LEVEL_NORMAL: Default logging + * @WLAN_LOG_LEVEL_REPRO: Normal debug level + * @WLAN_LOG_LEVEL_ACTIVE: Active debug level + * + * Log levels defined for logging by the wifi driver + */ +enum wifi_driver_log_level { + WLAN_LOG_LEVEL_OFF, + WLAN_LOG_LEVEL_NORMAL, + WLAN_LOG_LEVEL_REPRO, + WLAN_LOG_LEVEL_ACTIVE, +}; + +/** + * enum wifi_logging_ring_id - Ring id of logging entities + * @RING_ID_WAKELOCK: Power events ring id + * @RING_ID_CONNECTIVITY: Connectivity event ring id + * @RING_ID_PER_PACKET_STATS: Per packet statistic ring id + * @RIND_ID_DRIVER_DEBUG: Driver debug messages ring id + * @RING_ID_FIRMWARE_DEBUG: Firmware debug messages ring id + * + * This enum has the ring id values of logging rings + */ +enum wifi_logging_ring_id { + RING_ID_WAKELOCK, + RING_ID_CONNECTIVITY, + RING_ID_PER_PACKET_STATS, + RIND_ID_DRIVER_DEBUG, + RING_ID_FIRMWARE_DEBUG, +}; + +// ------------------------------------------------------------------- +// Change channel generic scheme +typedef void (*CHANGE_CHANNEL_CALLBACK)(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, + tpPESession psessionEntry); + +/// LIM global definitions +typedef struct sAniSirLimIbss +{ + void *pHdr; + void *pBeacon; +} tAniSirLimIbss; + +typedef struct sDialogueToken +{ + //bytes 0-3 + tANI_U16 assocId; + tANI_U8 token; + tANI_U8 rsvd1; + //Bytes 4-7 + tANI_U16 tid; + tANI_U8 rsvd2[2]; + + struct sDialogueToken* next; +}tDialogueToken, *tpDialogueToken; + +typedef struct sLimTimers +{ + //TIMERS IN LIM ARE NOT SUPPOSED TO BE ZEROED OUT DURING RESET. + //DURING limInitialize DONOT ZERO THEM OUT. + +//STA SPECIFIC TIMERS + // Periodic background scan timer + TX_TIMER gLimBackgroundScanTimer; + + TX_TIMER gLimPreAuthClnupTimer; + + // Association related timers + TX_TIMER gLimAssocFailureTimer; + TX_TIMER gLimReassocFailureTimer; + + + /// Heartbeat timer on STA + TX_TIMER gLimHeartBeatTimer; + + /// Wait for Probe after Heartbeat failure timer on STA + TX_TIMER gLimProbeAfterHBTimer; + + + // Authentication related timers + TX_TIMER gLimAuthFailureTimer; + + // Join Failure timeout on STA + TX_TIMER gLimJoinFailureTimer; + + // Keepalive timer + TX_TIMER gLimKeepaliveTimer; + + // Scan related timers + TX_TIMER gLimMinChannelTimer; + TX_TIMER gLimMaxChannelTimer; + TX_TIMER gLimPeriodicProbeReqTimer; + + // CNF_WAIT timer + TX_TIMER *gpLimCnfWaitTimer; + + // Send Disassociate frame threshold parameters + TX_TIMER gLimSendDisassocFrameThresholdTimer; + + TX_TIMER gLimAddtsRspTimer; // max wait for a response + + // Update OLBC Cache Timer + TX_TIMER gLimUpdateOlbcCacheTimer; + + TX_TIMER gLimChannelSwitchTimer; + // This TIMER is started on the STA, as indicated by the + // AP in its Quiet BSS IE, for the specified interval + TX_TIMER gLimQuietTimer; + // This TIMER is started on the AP, prior to the AP going + // into LEARN mode + // This TIMER is started on the STA, for the specified + // quiet duration + TX_TIMER gLimQuietBssTimer; + +#ifdef WLAN_FEATURE_VOWIFI_11R + TX_TIMER gLimFTPreAuthRspTimer; +#endif + +#ifdef FEATURE_WLAN_ESE + TX_TIMER gLimEseTsmTimer; +#endif + TX_TIMER gLimRemainOnChannelTimer; + + TX_TIMER gLimPeriodicJoinProbeReqTimer; + TX_TIMER gLimDisassocAckTimer; + TX_TIMER gLimDeauthAckTimer; + TX_TIMER g_lim_periodic_auth_retry_timer; + // This timer is started when single shot NOA insert msg is sent to FW for scan in P2P GO mode + TX_TIMER gLimP2pSingleShotNoaInsertTimer; + /* This timer is used to convert active channel to + * passive channel when there is no beacon + * for a period of time on a particular DFS channel + */ + TX_TIMER gLimActiveToPassiveChannelTimer; + +//********************TIMER SECTION ENDS************************************************** +// ALL THE FIELDS BELOW THIS CAN BE ZEROED OUT in limInitialize +//**************************************************************************************** + +}tLimTimers; + +typedef struct { + void *pMlmDisassocReq; + void *pMlmDeauthReq; +}tLimDisassocDeauthCnfReq; + +typedef struct sAniSirLim +{ + ////////////////////////////////////// TIMER RELATED START /////////////////////////////////////////// + + tLimTimers limTimers; + /// Flag to track if LIM timers are created or not + tANI_U32 gLimTimersCreated; + + + ////////////////////////////////////// TIMER RELATED END /////////////////////////////////////////// + + ////////////////////////////////////// SCAN/LEARN RELATED START /////////////////////////////////////////// + /** + * This flag when set, will use scan mode instead of + * Learn mode on BP/AP. By default this flag is set + * to true until HIF getting stuck in 0x800 state is + * debugged. + */ + tANI_U32 gLimUseScanModeForLearnMode; + + /** + * This is useful for modules other than LIM + * to see if system is in scan/learn mode or not + */ + tANI_U32 gLimSystemInScanLearnMode; + + // Scan related globals on STA + tANI_U8 gLimReturnAfterFirstMatch; + tANI_U8 gLim24Band11dScanDone; + tANI_U8 gLim50Band11dScanDone; + tANI_U8 gLimReturnUniqueResults; + + // Background Scan related globals on STA + tANI_U32 gLimNumOfBackgroundScanSuccess; + tANI_U32 gLimNumOfConsecutiveBkgndScanFailure; + tANI_U32 gLimNumOfForcedBkgndScan; + tANI_U8 gLimBackgroundScanDisable; //based on BG timer + tANI_U8 gLimForceBackgroundScanDisable; //debug control flag + tANI_U8 gLimBackgroundScanTerminate; //controlled by SME + tANI_U8 gLimReportBackgroundScanResults;//controlled by SME + + /// Place holder for current channel ID + /// being scanned + tANI_U32 gLimCurrentScanChannelId; + + // Hold onto SCAN criteria + /* The below is used in P2P GO case when we need to defer processing SME Req + * to LIM and insert NOA first and process SME req once SNOA is started + */ + tANI_U16 gDeferMsgTypeForNOA; + tANI_U32 *gpDefdSmeMsgForNOA; + + tLimMlmScanReq *gpLimMlmScanReq; + + /// This indicates total length of 'matched' scan results + tANI_U16 gLimMlmScanResultLength; + + /// This indicates total length of 'cached' scan results + tANI_U16 gLimSmeScanResultLength; + + /** + * Hash table definition for storing SCAN results + * This is the placed holder for 'cached' scan results + */ + tLimScanResultNode + *gLimCachedScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS]; + + /// This indicates total length of 'matched' scan results + tANI_U16 gLimMlmLfrScanResultLength; + + /// This indicates total length of 'cached' scan results + tANI_U16 gLimSmeLfrScanResultLength; + + /** + * Hash table definition for storing LFR SCAN results + * This is the placed holder for roaming candidates as forwarded + * by FW + */ + tLimScanResultNode + *gLimCachedLfrScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS]; + + /// Place holder for current channel ID + /// being scanned during background scanning + tANI_U32 gLimBackgroundScanChannelId; + /* Flag to indicate that background scan timer has been started */ + tANI_U8 gLimBackgroundScanStarted; + + /* Used to store the list of legacy bss sta detected during scan on one channel */ + tANI_U16 gLimRestoreCBNumScanInterval; + tANI_U16 gLimRestoreCBCount; + tSirMacAddr gLimLegacyBssidList[MAX_NUM_LEGACY_BSSID_PER_CHANNEL]; + + /* + * If this flag is 1, + * then, LIM will "try and trigger" a background + * scan whenever it receives a Quiet BSS IE + * + * If this flag is 0, + * then, LIM will simply shut-off Tx/Rx whenever it + * receives a Quiet BSS IE. + * This is the default behaviour when a Quiet BSS IE + * is received and 11H is enabled + */ + tANI_U32 gLimTriggerBackgroundScanDuringQuietBss; + + + // This variable store the total duration to do scan + tANI_U32 gTotalScanDuration; + tANI_U32 p2pRemOnChanTimeStamp; + + // abort scan is used to abort an on-going scan + tANI_U8 abortScan; + tLimScanChnInfo scanChnInfo; + + ////////////////////////////////////// SCAN/LEARN RELATED START /////////////////////////////////////////// + tSirMacAddr gSelfMacAddr; //added for BT-AMP Support + + ////////////////////////////////////////// BSS RELATED END /////////////////////////////////////////// + // Place holder for StartBssReq message + // received by SME state machine + + tANI_U8 gLimCurrentBssUapsd; + + /* This is used for testing sta legacy bss detect feature */ + tANI_U8 gLimForceNoPropIE; + + // + // Store the BSS Index returned by HAL during + // WDA_ADD_BSS_RSP here. + // + // For now: + // This will be used during WDA_SET_BSSKEY_REQ in + // order to set the GTK + // Later: + // There could be other interfaces needing this info + // + + // + // Due to the asynchronous nature of the interface + // between PE <-> HAL, some transient information + // like this needs to be cached. + // This is cached upon receipt of eWNI_SME_SETCONTEXT_REQ. + // This is released while posting LIM_MLM_SETKEYS_CNF + // + void* gpLimMlmSetKeysReq; + void* gpLimMlmRemoveKeyReq; + + ////////////////////////////////////////// BSS RELATED END /////////////////////////////////////////// + + ////////////////////////////////////////// IBSS RELATED START /////////////////////////////////////////// + //This indicates whether this STA coalesced and adapter to peer's capabilities or not. + tANI_U8 gLimIbssCoalescingHappened; + + /// Definition for storing IBSS peers BSS description + tLimIbssPeerNode *gLimIbssPeerList; + tANI_U32 gLimNumIbssPeers; + tANI_U32 gLimIbssRetryCnt; + + // ibss info - params for which ibss to join while coalescing + tAniSirLimIbss ibssInfo; + + ////////////////////////////////////////// IBSS RELATED END /////////////////////////////////////////// + + ////////////////////////////////////////// STATS/COUNTER RELATED START /////////////////////////////////////////// + + tANI_U16 maxStation; + tANI_U16 maxBssId; + + tANI_U32 gLimNumBeaconsRcvd; + tANI_U32 gLimNumBeaconsIgnored; + + tANI_U32 gLimNumDeferredMsgs; + + /// Variable to keep track of number of currently associated STAs + tANI_U16 gLimNumOfAniSTAs; // count of ANI peers + tANI_U16 gLimAssocStaLimit; + + // Heart-Beat interval value + tANI_U32 gLimHeartBeatCount; + tSirMacAddr gLimHeartBeatApMac[2]; + tANI_U8 gLimHeartBeatApMacIndex; + + // Statistics to keep track of no. beacons rcvd in heart beat interval + tANI_U16 gLimHeartBeatBeaconStats[MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL]; + +#ifdef WLAN_DEBUG + // Debug counters + tANI_U32 numTot, numBbt, numProtErr, numLearn, numLearnIgnore; + tANI_U32 numSme, numMAC[4][16]; + + // Debug counter to track number of Assoc Req frame drops + // when received in pStaDs->mlmState other than LINK_ESTABLISED + tANI_U32 gLimNumAssocReqDropInvldState; + // counters to track rejection of Assoc Req due to Admission Control + tANI_U32 gLimNumAssocReqDropACRejectTS; + tANI_U32 gLimNumAssocReqDropACRejectSta; + // Debug counter to track number of Reassoc Req frame drops + // when received in pStaDs->mlmState other than LINK_ESTABLISED + tANI_U32 gLimNumReassocReqDropInvldState; + // Debug counter to track number of Hash Miss event that + // will not cause a sending of de-auth/de-associate frame + tANI_U32 gLimNumHashMissIgnored; + + // Debug counter to track number of Beacon frames + // received in unexpected state + tANI_U32 gLimUnexpBcnCnt; + + // Debug counter to track number of Beacon frames + // received in wt-join-state that do have SSID mismatch + tANI_U32 gLimBcnSSIDMismatchCnt; + + // Debug counter to track number of Link establishments on STA/BP + tANI_U32 gLimNumLinkEsts; + + // Debug counter to track number of Rx cleanup + tANI_U32 gLimNumRxCleanup; + + // Debug counter to track different parse problem + tANI_U32 gLim11bStaAssocRejectCount; + +#endif + + //Time stamp of the last beacon received from the BSS to which STA is connected. + tANI_U64 gLastBeaconTimeStamp; + //RX Beacon count for the current BSS to which STA is connected. + tANI_U32 gCurrentBssBeaconCnt; + tANI_U8 gLastBeaconDtimCount; + tANI_U8 gLastBeaconDtimPeriod; + + + ////////////////////////////////////////// STATS/COUNTER RELATED END /////////////////////////////////////////// + + + ////////////////////////////////////////// STATES RELATED START /////////////////////////////////////////// + // Counts Heartbeat failures + tANI_U8 gLimHBfailureCntInLinkEstState; + tANI_U8 gLimProbeFailureAfterHBfailedCnt; + tANI_U8 gLimHBfailureCntInOtherStates; + + /** + * This variable indicates whether LIM module need to + * send response to host. Used to identify whether a request + * is generated internally within LIM module or by host + */ + tANI_U8 gLimRspReqd; + + /// Previous SME State + tLimSmeStates gLimPrevSmeState; + + /// MLM State visible across all Sirius modules + tLimMlmStates gLimMlmState; + + /// Previous MLM State + tLimMlmStates gLimPrevMlmState; + + // LIM to HAL SCAN Management Message Interface states + tLimLimHalScanState gLimHalScanState; +//WLAN_SUSPEND_LINK Related + SUSPEND_RESUME_LINK_CALLBACK gpLimSuspendCallback; + tANI_U32 *gpLimSuspendData; + SUSPEND_RESUME_LINK_CALLBACK gpLimResumeCallback; + tANI_U32 *gpLimResumeData; +//end WLAN_SUSPEND_LINK Related + tANI_U8 fScanDisabled; + //Can be set to invalid channel. If it is invalid, HAL + //should move to previous valid channel or stay in the + //current channel. CB state goes along with channel to resume to + tANI_U16 gResumeChannel; + ePhyChanBondState gResumePhyCbState; + + // Change channel generic scheme + CHANGE_CHANNEL_CALLBACK gpchangeChannelCallback; + tANI_U32 *gpchangeChannelData; + + /// SME State visible across all Sirius modules + tLimSmeStates gLimSmeState; + /// This indicates whether we're an AP, STA in BSS/IBSS + tLimSystemRole gLimSystemRole; + + // Number of STAs that do not support short preamble + tLimNoShortParams gLimNoShortParams; + + // Number of STAs that do not support short slot time + tLimNoShortSlotParams gLimNoShortSlotParams; + + + // OLBC parameters + tLimProtStaParams gLimOverlap11gParams; + + tLimProtStaParams gLimOverlap11aParams; + tLimProtStaParams gLimOverlapHt20Params; + tLimProtStaParams gLimOverlapNonGfParams; + + // + // ---------------- DPH ----------------------- + // these used to live in DPH but are now moved here (where they belong) + tANI_U32 gLimPhyMode; + tANI_U32 propRateAdjustPeriod; + tANI_U32 scanStartTime; // used to measure scan time + + tANI_U8 gLimMyMacAddr[6]; + tANI_U8 ackPolicy; + + tANI_U8 gLimQosEnabled:1; //11E + tANI_U8 gLimWmeEnabled:1; //WME + tANI_U8 gLimWsmEnabled:1; //WSM + tANI_U8 gLimHcfEnabled:1; + tANI_U8 gLim11dEnabled:1; + tANI_U8 gLimProbeRespDisableFlag:1; // control over probe response + // ---------------- DPH ----------------------- + + ////////////////////////////////////////// STATES RELATED END /////////////////////////////////////////// + + ////////////////////////////////////////// MISC RELATED START /////////////////////////////////////////// + + /* Deferred Queue Parameters */ + tLimDeferredMsgQParams gLimDeferredMsgQ; + +#ifdef SAP_AUTH_OFFLOAD + /* SAP deferred msg queue */ + struct slim_deferred_sap_queue glim_sap_deferred_msgq; +#endif + + // addts request if any - only one can be outstanding at any time + tSirAddtsReq gLimAddtsReq; + tANI_U8 gLimAddtsSent; + tANI_U8 gLimAddtsRspTimerCount; + + //protection related config cache + tCfgProtection cfgProtection; + + tANI_U8 gLimProtectionControl; + /* RF band to determine 2.4/5 GHz */ + + // alternate radio info used by STA + tSirAlternateRadioInfo gLimAlternateRadio; + + //This flag will remain to be set except while LIM is waiting for specific response messages + //from HAL. e.g when LIM issues ADD_STA req it will clear this flag and when it will receive + //the response the flag will be set. + tANI_U8 gLimProcessDefdMsgs; + + // UAPSD flag used on AP + tANI_U8 gUapsdEnable; + + /* Used on STA, this is a static UAPSD mask setting + * derived from SME_JOIN_REQ and SME_REASSOC_REQ. If a + * particular AC bit is set, it means the AC is both + * trigger enabled and delivery enabled. + */ + tANI_U8 gUapsdPerAcBitmask; + + /* Used on STA, this is a dynamic UPASD mask setting + * derived from AddTS Rsp and DelTS frame. If a + * particular AC bit is set, it means AC is trigger + * enabled. + */ + tANI_U8 gUapsdPerAcTriggerEnableMask; + + /* Used on STA, dynamic UPASD mask setting + * derived from AddTS Rsp and DelTs frame. If + * a particular AC bit is set, it means AC is + * delivery enabled. + */ + tANI_U8 gUapsdPerAcDeliveryEnableMask; + + /* Used on STA for AC downgrade. This is a dynamic mask + * setting which keep tracks of ACs being admitted. + * If bit is set to 0: That particular AC is not admitted + * If bit is set to 1: That particular AC is admitted + */ + tANI_U8 gAcAdmitMask[SIR_MAC_DIRECTION_DIRECT]; + + //dialogue token List head/tail for Action frames request sent. + tpDialogueToken pDialogueTokenHead; + tpDialogueToken pDialogueTokenTail; + + tLimTspecInfo tspecInfo[LIM_NUM_TSPEC_MAX]; + + // admission control policy information + tLimAdmitPolicyInfo admitPolicyInfo; + vos_lock_t lkPeGlobalLock; + tANI_U8 disableLDPCWithTxbfAP; +#ifdef FEATURE_WLAN_TDLS + tANI_U8 gLimTDLSBufStaEnabled; + tANI_U8 gLimTDLSUapsdMask; + tANI_U8 gLimTDLSOffChannelEnabled; + // TDLS WMM Mode + tANI_U8 gLimTDLSWmmMode; +#endif + ////////////////////////////////////////// MISC RELATED END /////////////////////////////////////////// + + ////////////////////////////////////////// ASSOC RELATED START /////////////////////////////////////////// + // Place holder for JoinReq message + // received by SME state machine + // tpSirSmeJoinReq gpLimJoinReq; + + // Place holder for ReassocReq message + // received by SME state machine + //tpSirSmeReassocReq gpLimReassocReq; sep23 review + + // Current Authentication type used at STA + //tAniAuthType gLimCurrentAuthType; + + // Place holder for current authentication request + // being handled + tLimMlmAuthReq *gpLimMlmAuthReq; + + // Reason code to determine the channel change context while sending + // WDA_CHNL_SWITCH_REQ message to HAL + tANI_U32 channelChangeReasonCode; + + /// MAC level Pre-authentication related globals + tSirMacChanNum gLimPreAuthChannelNumber; + tAniAuthType gLimPreAuthType; + tSirMacAddr gLimPreAuthPeerAddr; + tANI_U32 gLimNumPreAuthContexts; + tLimPreAuthTable gLimPreAuthTimerTable; + + // Placed holder to deauth reason + tANI_U16 gLimDeauthReasonCode; + + // Place holder for Pre-authentication node list + struct tLimPreAuthNode * pLimPreAuthList; + + // Send Disassociate frame threshold parameters + tANI_U16 gLimDisassocFrameThreshold; + tANI_U16 gLimDisassocFrameCredit; + + // Assoc or ReAssoc Response Data/Frame + void *gLimAssocResponseData; + + //One cache for each overlap and associated case. + tCacheParams protStaOverlapCache[LIM_PROT_STA_OVERLAP_CACHE_SIZE]; + tCacheParams protStaCache[LIM_PROT_STA_CACHE_SIZE]; + + ////////////////////////////////////////// ASSOC RELATED END /////////////////////////////////////////// + + //////////////////////////////// HT RELATED ////////////////////////////////////////// + // + // The following global LIM variables maintain/manage + // the runtime configurations related to 802.11n + + // 802.11n Station detected HT capability in Beacon Frame + tANI_U8 htCapabilityPresentInBeacon; + + // 802.11 HT capability: Enabled or Disabled + tANI_U8 htCapability; + + + tANI_U8 gHTGreenfield; + + tANI_U8 gHTShortGI40Mhz; + tANI_U8 gHTShortGI20Mhz; + + //Set to 0 for 3839 octets + //Set to 1 for 7935 octets + tANI_U8 gHTMaxAmsduLength; + + + // DSSS/CCK at 40 MHz: Enabled 1 or Disabled + tANI_U8 gHTDsssCckRate40MHzSupport; + + // PSMP Support: Enabled 1 or Disabled 0 + tANI_U8 gHTPSMPSupport; + + // L-SIG TXOP Protection used only if peer support available + tANI_U8 gHTLsigTXOPProtection; + + // MIMO Power Save + tSirMacHTMIMOPowerSaveState gHTMIMOPSState; + + // Scan In Power Save + tANI_U8 gScanInPowersave; + + // + // A-MPDU Density + // 000 - No restriction + // 001 - 1/8 usec + // 010 - 1/4 usec + // 011 - 1/2 usec + // 100 - 1 usec + // 101 - 2 usec + // 110 - 4 usec + // 111 - 8 usec + // + tANI_U8 gHTAMpduDensity; + + tANI_BOOLEAN gMaxAmsduSizeEnabled; + // Maximum Tx/Rx A-MPDU factor + tANI_U8 gHTMaxRxAMpduFactor; + + // + // Scheduled PSMP related - Service Interval Granularity + // 000 - 5 ms + // 001 - 10 ms + // 010 - 15 ms + // 011 - 20 ms + // 100 - 25 ms + // 101 - 30 ms + // 110 - 35 ms + // 111 - 40 ms + // + tANI_U8 gHTServiceIntervalGranularity; + + // Indicates whether an AP wants to associate PSMP enabled Stations + tANI_U8 gHTControlledAccessOnly; + + // RIFS Mode. Set if no APSD legacy devices associated + tANI_U8 gHTRifsMode; + // OBss Mode . set when we have Non HT STA is associated or with in overlap bss + tANI_U8 gHTObssMode; + + // Identifies the current Operating Mode + tSirMacHTOperatingMode gHTOperMode; + + // Indicates if PCO is activated in the BSS + tANI_U8 gHTPCOActive; + + // + // If PCO is active, indicates which PCO phase to use + // 0 - switch to 20 MHz phase + // 1 - switch to 40 MHz phase + // + tANI_U8 gHTPCOPhase; + + // + // Used only in beacons. For PR, this is set to 0 + // 0 - Primary beacon + // 1 - Secondary beacon + // + tANI_U8 gHTSecondaryBeacon; + + // + // Dual CTS Protection + // 0 - Use RTS/CTS + // 1 - Dual CTS Protection is used + // + tANI_U8 gHTDualCTSProtection; + + /* + * Identifies a single STBC MCS that shall be used for + * STBC control frames and STBC beacons + */ + tANI_U8 gHTSTBCBasicMCS; + + tANI_U8 gHTNonGFDevicesPresent; + + tANI_U8 gAddBA_Declined; // Flag to Decline the BAR if the particular bit (0-7) is being set + + //////////////////////////////// HT RELATED ////////////////////////////////////////// + +#ifdef FEATURE_WLAN_TDLS + tANI_U8 gLimAddStaTdls ; + tANI_U8 gLimTdlsLinkMode ; + //////////////////////////////// TDLS RELATED ////////////////////////////////////////// +#endif + + // wsc info required to form the wsc IE + tLimWscIeInfo wscIeInfo; + tpPESession gpSession ; //Pointer to session table + /* + * sessionID and transactionID from SME is stored here for those messages, for which + * there is no session context in PE, e.g. Scan related messages. + **/ + tANI_U8 gSmeSessionId; + tANI_U16 gTransactionId; + +#ifdef FEATURE_OEM_DATA_SUPPORT +tLimMlmOemDataReq *gpLimMlmOemDataReq; +tLimMlmOemDataRsp *gpLimMlmOemDataRsp; +#endif + + tSirRemainOnChnReq *gpLimRemainOnChanReq; //hold remain on chan request in this buf + vos_list_t gLimMgmtFrameRegistratinQueue; + tANI_U32 mgmtFrameSessionId; + tSirBackgroundScanMode gLimBackgroundScanMode; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tpPESession pSessionEntry; + tANI_U8 reAssocRetryAttempt; +#endif + tLimDisassocDeauthCnfReq limDisassocDeauthCnfReq; + tANI_U8 deferredMsgCnt; + tSirDFSChannelList dfschannelList; + tANI_U8 deauthMsgCnt; + tANI_U8 gLimIbssStaLimit; + + /* Number of channel switch IEs sent so far */ + tANI_U8 gLimDfsChanSwTxCount; + tANI_U8 gLimDfsTargetChanNum; + tANI_U8 fOffloadScanPending; /*Flag to track offload scan */ + tANI_U8 fOffloadScanP2PSearch; /*Flag to track the p2p search */ + tANI_U8 fOffloadScanP2PListen; /*Flag to track the p2p listen */ + tANI_U8 probeCounter; + tANI_U8 maxProbe; + uint8_t retry_packet_cnt; +} tAniSirLim, *tpAniSirLim; + +typedef struct sLimMgmtFrameRegistration +{ + vos_list_node_t node; // MUST be first element + tANI_U16 frameType; + tANI_U16 matchLen; + tANI_U16 sessionId; + tANI_U8 matchData[1]; +} tLimMgmtFrameRegistration, *tpLimMgmtFrameRegistration; + +#if defined WLAN_FEATURE_VOWIFI +typedef struct sRrmContext +{ + tRrmSMEContext rrmSmeContext; + tRrmPEContext rrmPEContext; +}tRrmContext, *tpRrmContext; +#endif + +//Check if this definition can actually move here even for Volans. In that case +//this featurization can be removed. +/** ------------------------------------------------------------------------- * + + \typedef tDriverType + + \brief Indicate the driver type to the mac, and based on this do + appropriate initialization. + + -------------------------------------------------------------------------- */ + +typedef enum +{ + eDRIVER_TYPE_PRODUCTION = 0, + eDRIVER_TYPE_MFG = 1, + eDRIVER_TYPE_DVT = 2 +} tDriverType; + +/** ------------------------------------------------------------------------- * + + \typedef tMacOpenParameters + + \brief Parameters needed for Enumeration of all status codes returned by the higher level + interface functions. + + -------------------------------------------------------------------------- */ + +typedef struct sMacOpenParameters +{ + tANI_U16 maxStation; + tANI_U16 maxBssId; + tANI_U32 frameTransRequired; + tANI_U8 powersaveOffloadEnabled; + /* Powersave Parameters */ + tANI_U8 staMaxLIModDtim; + tANI_U8 staModDtim; + tANI_U8 staDynamicDtim; + tDriverType driverType; + tANI_U8 maxWoWFilters; + tANI_U8 wowEnable; +/* Here olIniInfo is used to store ini + * status of arp offload, ns offload + * and others. Currently 1st bit is used + * for arp off load and 2nd bit for ns + * offload currently, rest bits are unused + */ + tANI_U8 olIniInfo; + v_BOOL_t ssdp; + bool enable_bcst_ptrn; + /* + * DFS Phyerror Filtering offload status from ini + * 0 indicates offload disabled + * 1 indicates offload enabled + */ + tANI_U8 dfsPhyerrFilterOffload; +/* pass intra-bss-fwd info to txrx module */ + tANI_U8 apDisableIntraBssFwd; + + /* max offload peer */ + tANI_U8 apMaxOffloadPeers; + + /* max offload reorder buffs */ + tANI_U8 apMaxOffloadReorderBuffs; + +#ifdef FEATURE_WLAN_RA_FILTERING + tANI_U16 RArateLimitInterval; + v_BOOL_t IsRArateLimitEnabled; +#endif + /* is RX re-ordering offloaded to the fw */ + tANI_U8 reorderOffload; + + /* dfs radar pri multiplier */ + tANI_S32 dfsRadarPriMultiplier; + +#ifdef IPA_UC_OFFLOAD + /* IPA Micro controller data path offload enable flag */ + tANI_U8 ucOffloadEnabled; + /* IPA Micro controller data path offload TX buffer count */ + tANI_U32 ucTxBufCount; + /* IPA Micro controller data path offload TX buffer size */ + tANI_U32 ucTxBufSize; + /* IPA Micro controller data path offload RX indication ring count */ + tANI_U32 ucRxIndRingCount; + /* IPA Micro controller data path offload TX partition base */ + tANI_U32 ucTxPartitionBase; +#endif /* IPA_UC_OFFLOAD */ + + bool tx_chain_mask_cck; + uint16_t self_gen_frm_pwr; +#ifdef WLAN_FEATURE_LPSS + bool is_lpass_enabled; +#endif +#ifdef WLAN_FEATURE_NAN + bool is_nan_enabled; +#endif + uint16_t max_mgmt_tx_fail_count; + bool force_target_assert_enabled; +} tMacOpenParameters; + +typedef struct sHalMacStartParameters +{ + /* Parameters for the Firmware */ + tDriverType driverType; + +} tHalMacStartParameters; + +/** + * struct vdev_type_nss - vdev type nss structure + * + * @sta: STA Nss value. + * @sap: SAP Nss value. + * @p2p_go: P2P GO Nss value. + * @p2p_cli: P2P CLI Nss value. + * @p2p_dev: P2P device Nss value. + * @ibss: IBSS Nss value. + * @tdls: TDLS Nss value. + * @ocb: OCB Nss value. + * + * Holds the Nss values of different vdev types. + */ +struct vdev_type_nss { + uint8_t sta; + uint8_t sap; + uint8_t p2p_go; + uint8_t p2p_cli; + uint8_t p2p_dev; + uint8_t ibss; + uint8_t tdls; + uint8_t ocb; +}; + +typedef enum +{ + LIM_AUTH_ACK_NOT_RCD, + LIM_AUTH_ACK_RCD_SUCCESS, + LIM_AUTH_ACK_RCD_FAILURE, +} t_auth_ack_status; + +// ------------------------------------------------------------------- +/// MAC Sirius parameter structure +typedef struct sAniSirGlobal +{ + tDriverType gDriverType; + + tSirMbMsg* pResetMsg; + tAniSirCfg cfg; + tAniSirLim lim; + tAniSirPmm pmm; + tAniSirSch sch; + tAniSirSys sys; + tAniSirUtils utils; + + /* PAL/HDD handle */ + tHddHandle hHdd; + + + tSmeStruct sme; + tSapStruct sap; + tCsrScanStruct scan; + tCsrRoamStruct roam; + +#ifdef FEATURE_OEM_DATA_SUPPORT + tOemDataStruct oemData; +#endif + tPmcInfo pmc; + tSmeBtcInfo btc; + + tCcm ccm; + +#if defined WLAN_FEATURE_VOWIFI + tRrmContext rrm; +#endif +#ifdef WLAN_FEATURE_CONCURRENT_P2P + tp2pContext p2pContext[MAX_NO_OF_P2P_SESSIONS]; +#else + tp2pContext p2pContext; +#endif + + tANI_U32 gCurrentLogSize; + tANI_U32 menuCurrent; + /* logDump specific */ + tANI_U32 dumpTablecurrentId; + /* Instead of static allocation I will dynamically allocate memory + for dumpTableEntry thinking of using linked list */ + tDumpModuleEntry *dumpTableEntry[MAX_DUMP_TABLE_ENTRY]; +#ifdef FEATURE_WLAN_TDLS + v_BOOL_t isTdlsPowerSaveProhibited; +#endif + tANI_U8 fScanOffload; + tANI_U8 isCoalesingInIBSSAllowed; + tANI_U8 psOffloadEnabled; + + /* Power Save offload Info */ + tPmcOffloadInfo pmcOffloadInfo; + + /* P2P Listen Offload */ + tANI_U8 fP2pListenOffload; + + /* PNO offload */ + v_BOOL_t pnoOffload; + + csrReadyToSuspendCallback readyToSuspendCallback; + void *readyToSuspendContext; + tANI_U8 lteCoexAntShare; + tANI_U8 beacon_offload; + tANI_U32 fEnableDebugLog; + tANI_U16 mgmtSeqNum; + v_BOOL_t enable5gEBT; + /* Miracast session 0-Disabled, 1-Source, 2-sink*/ + tANI_U8 fMiracastSessionPresent; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + csrReadyToExtWoWCallback readyToExtWoWCallback; + void *readyToExtWoWContext; +#endif + +#ifdef SAP_AUTH_OFFLOAD + bool sap_auth_offload; + uint32_t sap_auth_offload_sec_type; +#endif /* SAP_AUTH_OFFLOAD */ + + /* 802.11p enable */ + bool enable_dot11p; + uint32_t f_sta_miracast_mcc_rest_time_val; + uint8_t f_prefer_non_dfs_on_radar; + uint32_t fine_time_meas_cap; + /* per band chain mask support */ + bool per_band_chainmask_supp; + struct vdev_type_nss vdev_type_nss_2g; + struct vdev_type_nss vdev_type_nss_5g; + uint8_t user_configured_nss; + t_auth_ack_status auth_ack_status; + bool first_scan_done; + int8_t first_scan_bucket_threshold; +} tAniSirGlobal; + +typedef enum +{ + eHIDDEN_SSID_NOT_IN_USE, + eHIDDEN_SSID_ZERO_LEN, + eHIDDEN_SSID_ZERO_CONTENTS +} tHiddenssId; + +#ifdef FEATURE_WLAN_TDLS + +#define RFC1042_HDR_LENGTH (6) +#define GET_BE16(x) ((tANI_U16) (((x)[0] << 8) | (x)[1])) +#define ETH_TYPE_89_0d (0x890d) +#define ETH_TYPE_LEN (2) +#define PAYLOAD_TYPE_TDLS_SIZE (1) +#define PAYLOAD_TYPE_TDLS (2) + +#endif + +#endif /* _ANIGLOBAL_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniSystemDefs.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniSystemDefs.h new file mode 100644 index 000000000000..2e666359fbb0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniSystemDefs.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file aniSystemDefs.h contains definitions used by + * various ANI entities + * Author: Chandra Modumudi + * Date: 09/18/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __ANI_SYSTEM_DEFS_H +#define __ANI_SYSTEM_DEFS_H + +#include "sirTypes.h" +#include "sirMacProtDef.h" + +#define ANI_OUI 0x000AF5 + +/// Max WDS info length. +#define ANI_WDS_INFO_MAX_LENGTH 64 + +//This is to force compiler to use the maximum of an int for enum +#define SIR_MAX_ENUM_SIZE 0x7FFFFFFF + +/* Max key size including the WAPI and TKIP */ +#define WLAN_MAX_KEY_RSC_LEN 16 +#define WLAN_WAPI_KEY_RSC_LEN 16 + + + +#ifndef FALSE +#undef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#undef TRUE +#define TRUE 1 +#endif + +typedef enum eAniBool +{ + eSIR_FALSE, + eSIR_TRUE, + eSIR_DONOT_USE_BOOL = SIR_MAX_ENUM_SIZE +} tAniBool; + +/// Authentication type enum used with peer +typedef enum eAniAuthType +{ + eSIR_OPEN_SYSTEM, + eSIR_SHARED_KEY, +#if defined WLAN_FEATURE_VOWIFI_11R + eSIR_FT_AUTH, +#endif +#if defined FEATURE_WLAN_ESE + eSIR_LEAP_AUTH = 0x80, +#endif + eSIR_AUTO_SWITCH, + eSIR_DONOT_USE_AUTH_TYPE = SIR_MAX_ENUM_SIZE +} tAniAuthType; + +/// Encryption type enum used with peer +typedef enum eAniEdType +{ + eSIR_ED_NONE, + eSIR_ED_WEP40, + eSIR_ED_WEP104, + eSIR_ED_TKIP, + eSIR_ED_CCMP, +#if defined(FEATURE_WLAN_WAPI) + eSIR_ED_WPI, +#endif + /*DPU HW treats encryption mode 4 plus RMF bit set in TX BD as BIP. + Thus while setting BIP encryption mode in corresponding DPU Desc + eSIR_ED_AES_128_CMAC should be set to eSIR_ED_CCMP*/ + eSIR_ED_AES_128_CMAC, + eSIR_ED_NOT_IMPLEMENTED = SIR_MAX_ENUM_SIZE +} tAniEdType; + + +typedef enum eAniWepType +{ + eSIR_WEP_STATIC, + eSIR_WEP_DYNAMIC, +} tAniWepType; + +/// Enum to specify whether key is used +/// for TX only, RX only or both +typedef enum eAniKeyDirection +{ + eSIR_TX_ONLY, + eSIR_RX_ONLY, + eSIR_TX_RX, + eSIR_TX_DEFAULT, + eSIR_DONOT_USE_KEY_DIRECTION = SIR_MAX_ENUM_SIZE +} tAniKeyDirection; + +typedef struct sAniSSID +{ + tANI_U8 length; + tANI_U8 ssId[SIR_MAC_MAX_SSID_LENGTH]; +} tAniSSID, *tpAniSSID; + +typedef struct sAniApName +{ + tANI_U8 length; + tANI_U8 name[SIR_MAC_MAX_SSID_LENGTH]; +} tAniApName, *tpAniApName; + +/// RSN IE information +typedef struct sSirRSNie +{ + tANI_U16 length; + tANI_U8 rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2]; +} tSirRSNie, *tpSirRSNie; + +/// WAPI IE information +typedef struct sSirWAPIie +{ + tANI_U16 length; + tANI_U8 wapiIEdata[SIR_MAC_MAX_IE_LENGTH+2]; +} tSirWAPIie, *tpSirWAPIie; + +/// Additional IE information : +/// This can include WSC IE, P2P IE, and/or FTIE from upper layer. +/// MAC layer transparently convey these IE info between peer STA and upper layer, +/// but never requires to parse it. +typedef struct sSirAddie +{ + tANI_U16 length; + tANI_U8 addIEdata[SIR_MAC_MAX_ADD_IE_LENGTH + 2]; +} tSirAddie, *tpSirAddie; + +#ifdef FEATURE_WLAN_ESE + +// The CCKM IE needs to be in the +// Join and Reassoc Req. +typedef struct sSirCCKMie +{ + tANI_U16 length; + tANI_U8 cckmIEdata[SIR_MAC_MAX_IE_LENGTH+2]; +} tSirCCKMie, *tpSirCCKMie; + +#endif + +/// Definition for Encryption Keys +typedef struct sSirKeys +{ + tANI_U8 keyId; + tANI_U8 unicast; // 0 for multicast + tAniKeyDirection keyDirection; + tANI_U8 keyRsc[WLAN_MAX_KEY_RSC_LEN]; // Usage is unknown + tANI_U8 paeRole; // =1 for authenticator, + // =0 for supplicant + tANI_U16 keyLength; + tANI_U8 key[SIR_MAC_MAX_KEY_LENGTH]; +} tSirKeys, *tpSirKeys; + +/// Definition for Keying material +typedef struct sSirKeyMaterial +{ + tANI_U16 length; // This is the length of all + // data that follows + tAniEdType edType; // Encryption/Decryption type + tANI_U8 numKeys; + tSirKeys key[1]; +} tSirKeyMaterial, *tpSirKeyMaterial; + +#define SIR_CIPHER_SEQ_CTR_SIZE 6 +/// Definition for MIC failure indication +typedef struct sSirMicFailureInfo +{ + tSirMacAddr srcMacAddr; //address used to compute MIC + tSirMacAddr taMacAddr; //transmitter address + tSirMacAddr dstMacAddr; + tAniBool multicast; + tANI_U8 IV1; // first byte of IV + tANI_U8 keyId; // second byte of IV + tANI_U8 TSC[SIR_CIPHER_SEQ_CTR_SIZE]; // sequence number + tSirMacAddr rxMacAddr; // receive address + +} tSirMicFailureInfo, *tpSirMicFailureInfo; + +typedef __ani_attr_pre_packed struct sTrafStrmMetrics +{ + tANI_U16 UplinkPktQueueDly; + tANI_U16 UplinkPktQueueDlyHist[4]; + tANI_U32 UplinkPktTxDly; + tANI_U16 UplinkPktLoss; + tANI_U16 UplinkPktCount; + tANI_U8 RoamingCount; + tANI_U16 RoamingDly; +} __ani_attr_packed tTrafStrmMetrics, *tpTrafStrmMetrics; + + +typedef __ani_attr_pre_packed struct sBcnReportFields +{ + tANI_U8 ChanNum; + tANI_U8 Spare; + tANI_U16 MeasDuration; + tANI_U8 PhyType; + tANI_U8 RecvSigPower; + tSirMacAddr Bssid; + tANI_U32 ParentTsf; + tANI_U32 TargetTsf[2]; + tANI_U16 BcnInterval; + tANI_U16 CapabilityInfo; +} __ani_attr_packed tBcnReportFields, *tpBcnReportFields; + + +#endif /* __ANI_SYSTEM_DEFS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/logDump.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/logDump.h new file mode 100644 index 000000000000..734df7aa8bf0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/logDump.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/*============================================================================ +logDump.h + +Provides api's for dump commands. + +Author: Santosh Mandiganal +Date: 04/06/2008 +============================================================================*/ + + +#ifndef __LOGDUMP_H__ +#define __LOGDUMP_H__ + +#define MAX_DUMP_CMD 999 +#define MAX_DUMP_TABLE_ENTRY 10 + +typedef char * (*tpFunc)(tpAniSirGlobal, tANI_U32, tANI_U32, tANI_U32, tANI_U32, char *); + +typedef struct sDumpFuncEntry { + tANI_U32 id; + char *description; + tpFunc func; +} tDumpFuncEntry; + +typedef struct sDumpModuleEntry { + tANI_U32 mindumpid; + tANI_U32 maxdumpid; + tANI_U32 nItems; + tDumpFuncEntry *dumpTable; +} tDumpModuleEntry; + +typedef struct sRegList { + tANI_U32 addr; + char *name; +} tLogdRegList; + +int log_sprintf(tpAniSirGlobal pMac, char *pBuf, char *fmt, ... ); + +char * +dump_log_level_set( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p); + +char * +dump_cfg_set( tpAniSirGlobal pMac, tANI_U32 arg1, + tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p); + +char * +dump_cfg_get( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, + tANI_U32 arg3, tANI_U32 arg4, char *p); + +char * +dump_cfg_group_get( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, + tANI_U32 arg3, tANI_U32 arg4, char *p); + +void logDumpRegisterTable( tpAniSirGlobal pMac, tDumpFuncEntry *pEntry, + tANI_U32 nItems ); + + +void logDumpInit(tpAniSirGlobal pMac); + +#endif /* __LOGDUMP_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/macInitApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/macInitApi.h new file mode 100644 index 000000000000..401027c8a2d3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/macInitApi.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * macInitApi.c - Header file for mac level init functions + * Author: Dinesh Upadhyay + * Date: 04/23/2007 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------------- + * + */ +#ifndef __MAC_INIT_API_H +#define __MAC_INIT_API_H + +#include "aniGlobal.h" + +tSirRetStatus macStart(tHalHandle hHal, void* pHalMacStartParams); +tSirRetStatus macStop(tHalHandle hHal, tHalStopType stopType); +tSirRetStatus macOpen(tHalHandle * pHalHandle, tHddHandle hHdd, tMacOpenParameters * pMacOpenParms); +tSirRetStatus macClose(tHalHandle hHal); + +tSirRetStatus macPreStart(tHalHandle hHal); + +#endif //__MAC_INIT_API_H diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/macTrace.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/macTrace.h new file mode 100644 index 000000000000..0377885b94b2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/macTrace.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + + +* \file macTrace.h + +* \brief definition for trace related APIs + + \author Sunit Bhatia + + ========================================================================*/ + + + +#ifndef __MAC_TRACE_H +#define __MAC_TRACE_H + +#include "aniGlobal.h" + + +#ifdef TRACE_RECORD + +#define MAC_TRACE_GET_MODULE_ID(data) ((data >> 8) & 0xff) +#define MAC_TRACE_GET_MSG_ID(data) (data & 0xffff) + + +#define eLOG_NODROP_MISSED_BEACON_SCENARIO 0 +#define eLOG_PROC_DEAUTH_FRAME_SCENARIO 1 + + +void macTraceReset(tpAniSirGlobal pMac); +void macTrace(tpAniSirGlobal pMac, tANI_U8 code, tANI_U16 session, + tANI_U32 data); +void macTraceNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 code, + tANI_U16 session, tANI_U32 data); +tANI_U8* macTraceGetCfgMsgString( tANI_U16 cfgMsg ); +tANI_U8* macTraceGetLimMsgString( tANI_U16 limMsg ); +tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ); +tANI_U8* macTraceGetSmeMsgString( tANI_U16 smeMsg ); +tANI_U8* macTraceGetModuleString( tANI_U8 moduleId); +tANI_U8* macTraceGetInfoLogString( tANI_U16 infoLog ); +eHalStatus pe_AcquireGlobalLock( tAniSirLim *psPe); +eHalStatus pe_ReleaseGlobalLock( tAniSirLim *psPe); + +tANI_U8* macTraceGetHDDWlanConnState(tANI_U16 connState); + +#ifdef WLAN_FEATURE_P2P_DEBUG +tANI_U8* macTraceGetP2PConnState(tANI_U16 connState); +#endif + +tANI_U8* macTraceGetNeighbourRoamState(tANI_U16 neighbourRoamState); +tANI_U8* macTraceGetcsrRoamState(tANI_U16 csrRoamState); +tANI_U8* macTraceGetcsrRoamSubState(tANI_U16 csrRoamSubState); +tANI_U8* macTraceGetLimSmeState(tANI_U16 limState); +tANI_U8* macTraceGetLimMlmState(tANI_U16 mlmState); +tANI_U8* macTraceGetTLState(tANI_U16 tlState); + +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h new file mode 100644 index 000000000000..c92227a1ed7d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef QWLAN_VERSION_H +#define QWLAN_VERSION_H +/*=========================================================================== + +FILE: + qwlan_version.h + +BRIEF DESCRIPTION: + WLAN Host Version file. + Build number automatically updated by build scripts. + +===========================================================================*/ + +#define QWLAN_VERSION_MAJOR 4 +#define QWLAN_VERSION_MINOR 4 +#define QWLAN_VERSION_PATCH 31 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 52 + +#define QWLAN_VERSIONSTR "4.4.31.52" + + +#define AR6320_REV1_VERSION 0x5000000 +#define AR6320_REV1_1_VERSION 0x5000001 +#define AR6320_REV1_3_VERSION 0x5000003 +#define AR6320_REV2_1_VERSION 0x5010000 +#define AR6320_REV3_VERSION 0x5020000 +#define QCA9377_REV1_1_VERSION 0x5020001 +#define AR6320_REV3_2_VERSION 0x5030000 + +struct qwlan_hw { + u32 id; + u32 subid; + const char *name; +}; + + +#endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h new file mode 100644 index 000000000000..c786b8aa1893 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h @@ -0,0 +1,6514 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file sirApi.h contains definitions exported by + * Sirius software. + * Author: Chandra Modumudi + * Date: 04/16/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __SIR_API_H +#define __SIR_API_H + +#include "sirTypes.h" +#include "sirMacProtDef.h" +#include "aniSystemDefs.h" +#include "sirParams.h" + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseGlobal.h" +#endif + +/// Start of Sirius software/Host driver message types +#define SIR_HAL_HOST_MSG_START 0x1000 + +/// Max supported channel list +#define SIR_MAX_SUPPORTED_CHANNEL_LIST 96 + +#define SIR_MDIE_SIZE 3 + +// Increase dwell time for P2P search in ms +#define P2P_SEARCH_DWELL_TIME_INCREASE 20 +#define P2P_SOCIAL_CHANNELS 3 + +/* Max number of channels are 165, but to access 165th element of array, + *array of 166 is required. + */ +#define SIR_MAX_24G_5G_CHANNEL_RANGE 166 +#define SIR_BCN_REPORT_MAX_BSS_DESC 4 + +#define SIR_NUM_11B_RATES 4 //1,2,5.5,11 +#define SIR_NUM_11A_RATES 8 //6,9,12,18,24,36,48,54 + +#define SIR_PM_SLEEP_MODE 0 +#define SIR_PM_ACTIVE_MODE 1 + +//hidden SSID options +#define SIR_SCAN_NO_HIDDEN_SSID 0 +#define SIR_SCAN_HIDDEN_SSID_PE_DECISION 1 + +#define SIR_MAC_ADDR_LEN 6 +#define SIR_IPV4_ADDR_LEN 4 + +typedef tANI_U8 tSirIpv4Addr[SIR_IPV4_ADDR_LEN]; + +#define SIR_VERSION_STRING_LEN 64 +typedef tANI_U8 tSirVersionString[SIR_VERSION_STRING_LEN]; + +/* Periodic Tx pattern offload feature */ +#define PERIODIC_TX_PTRN_MAX_SIZE 1536 +#define MAXNUM_PERIODIC_TX_PTRNS 6 + +#define WIFI_SCANNING_MAC_OUI_LENGTH 3 + +#define MAX_LEN_UDP_RESP_OFFLOAD 128 + +#ifdef FEATURE_WLAN_EXTSCAN + +#define WLAN_EXTSCAN_MAX_CHANNELS 36 +#define WLAN_EXTSCAN_MAX_BUCKETS 16 +#define WLAN_EXTSCAN_MAX_HOTLIST_APS 128 +#define WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS 64 +#define WLAN_EXTSCAN_MAX_HOTLIST_SSIDS 8 + +typedef enum +{ + eSIR_EXTSCAN_INVALID, + eSIR_EXTSCAN_START_RSP, + eSIR_EXTSCAN_STOP_RSP, + eSIR_EXTSCAN_CACHED_RESULTS_RSP, + eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP, + eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP, + eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP, + eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP, + + eSIR_EXTSCAN_GET_CAPABILITIES_IND, + eSIR_EXTSCAN_HOTLIST_MATCH_IND, + eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND, + eSIR_EXTSCAN_CACHED_RESULTS_IND, + eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND, + eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, + eSIR_EXTSCAN_FULL_SCAN_RESULT_IND, + eSIR_EPNO_NETWORK_FOUND_IND, + eSIR_PASSPOINT_NETWORK_FOUND_IND, + eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP, + eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP, + eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND, + + /* Keep this last */ + eSIR_EXTSCAN_CALLBACK_TYPE_MAX, +} tSirExtScanCallbackType; + + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#define SIR_KRK_KEY_LEN 16 +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_BTK_KEY_LEN 32 +#define SIR_KCK_KEY_LEN 16 +#define SIR_KEK_KEY_LEN 16 +#define SIR_REPLAY_CTR_LEN 8 + +#define SIR_UAPSD_BITOFFSET_ACVO 0 +#define SIR_UAPSD_BITOFFSET_ACVI 1 +#define SIR_UAPSD_BITOFFSET_ACBK 2 +#define SIR_UAPSD_BITOFFSET_ACBE 3 + +#define SIR_UAPSD_FLAG_ACVO (1 << SIR_UAPSD_BITOFFSET_ACVO) +#define SIR_UAPSD_FLAG_ACVI (1 << SIR_UAPSD_BITOFFSET_ACVI) +#define SIR_UAPSD_FLAG_ACBK (1 << SIR_UAPSD_BITOFFSET_ACBK) +#define SIR_UAPSD_FLAG_ACBE (1 << SIR_UAPSD_BITOFFSET_ACBE) +#define SIR_UAPSD_GET(ac, mask) (((mask) & (SIR_UAPSD_FLAG_ ## ac)) >> SIR_UAPSD_BITOFFSET_ ## ac) +#endif +enum eSirHostMsgTypes +{ + SIR_HAL_APP_SETUP_NTF = SIR_HAL_HOST_MSG_START, + SIR_HAL_INITIAL_CAL_FAILED_NTF, + SIR_HAL_NIC_OPER_NTF, + SIR_HAL_INIT_START_REQ, + SIR_HAL_SHUTDOWN_REQ, + SIR_HAL_SHUTDOWN_CNF, + SIR_HAL_RESET_REQ, + SIR_HAL_RADIO_ON_OFF_IND, + SIR_HAL_RESET_CNF, + SIR_WRITE_TO_TD, + SIR_HAL_HDD_ADDBA_REQ, // MAC -> HDD + SIR_HAL_HDD_ADDBA_RSP, // HDD -> HAL + SIR_HAL_DELETEBA_IND, // MAC -> HDD + SIR_HAL_BA_FAIL_IND, // HDD -> MAC + SIR_TL_HAL_FLUSH_AC_REQ, + SIR_HAL_TL_FLUSH_AC_RSP +}; + + + +/** + * Module ID definitions. + */ +enum { + SIR_BOOT_MODULE_ID = 1, + SIR_HAL_MODULE_ID = 0x10, + SIR_CFG_MODULE_ID = 0x12, + SIR_LIM_MODULE_ID, + SIR_ARQ_MODULE_ID, + SIR_SCH_MODULE_ID, + SIR_PMM_MODULE_ID, + SIR_MNT_MODULE_ID, + SIR_DBG_MODULE_ID, + SIR_DPH_MODULE_ID, + SIR_SYS_MODULE_ID, + SIR_SMS_MODULE_ID, + + SIR_PHY_MODULE_ID = 0x20, + + + // Add any modules above this line + SIR_DVT_MODULE_ID +}; + +#define SIR_WDA_MODULE_ID SIR_HAL_MODULE_ID + +/** + * First and last module definition for logging utility + * + * NOTE: The following definitions need to be updated if + * the above list is changed. + */ +#define SIR_FIRST_MODULE_ID SIR_HAL_MODULE_ID +#define SIR_LAST_MODULE_ID SIR_DVT_MODULE_ID + + +// Type declarations used by Firmware and Host software + +// Scan type enum used in scan request +typedef enum eSirScanType +{ + eSIR_PASSIVE_SCAN, + eSIR_ACTIVE_SCAN, + eSIR_BEACON_TABLE, +} tSirScanType; + +/// Result codes Firmware return to Host SW +typedef enum eSirResultCodes +{ + eSIR_SME_SUCCESS, + + eSIR_EOF_SOF_EXCEPTION, + eSIR_BMU_EXCEPTION, + eSIR_LOW_PDU_EXCEPTION, + eSIR_USER_TRIG_RESET, + eSIR_LOGP_EXCEPTION, + eSIR_CP_EXCEPTION, + eSIR_STOP_BSS, + eSIR_AHB_HANG_EXCEPTION, + eSIR_DPU_EXCEPTION, + eSIR_RPE_EXCEPTION, + eSIR_TPE_EXCEPTION, + eSIR_DXE_EXCEPTION, + eSIR_RXP_EXCEPTION, + eSIR_MCPU_EXCEPTION, + eSIR_MCU_EXCEPTION, + eSIR_MTU_EXCEPTION, + eSIR_MIF_EXCEPTION, + eSIR_FW_EXCEPTION, + eSIR_PS_MUTEX_READ_EXCEPTION, + eSIR_PHY_HANG_EXCEPTION, + eSIR_MAILBOX_SANITY_CHK_FAILED, + eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF, // Only where this switch is present + eSIR_CFB_FLAG_STUCK_EXCEPTION, + + eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS=30, + + eSIR_SME_INVALID_PARAMETERS=500, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, + eSIR_SME_RESOURCES_UNAVAILABLE, + eSIR_SME_SCAN_FAILED, // Unable to find a BssDescription + // matching requested scan criteria + eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED, + eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE, + eSIR_SME_REFUSED, + eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA, + eSIR_SME_JOIN_TIMEOUT_RESULT_CODE, + eSIR_SME_AUTH_TIMEOUT_RESULT_CODE, + eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE, + eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE, + eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED, + eSIR_SME_AUTH_REFUSED, + eSIR_SME_INVALID_WEP_DEFAULT_KEY, + eSIR_SME_NO_KEY_MAPPING_KEY_FOR_PEER, + eSIR_SME_ASSOC_REFUSED, + eSIR_SME_REASSOC_REFUSED, + + /* Received Deauth while joining or pre-authenticating */ + eSIR_SME_DEAUTH_WHILE_JOIN, + + eSIR_SME_DISASSOC_WHILE_JOIN, //Received Disassociation while joining. + eSIR_SME_DEAUTH_WHILE_REASSOC, //Received Deauth while ReAssociate. + eSIR_SME_DISASSOC_WHILE_REASSOC, //Received Disassociation while ReAssociate + eSIR_SME_STA_NOT_AUTHENTICATED, + eSIR_SME_STA_NOT_ASSOCIATED, + eSIR_SME_STA_DISASSOCIATED, + eSIR_SME_ALREADY_JOINED_A_BSS, + eSIR_ULA_COMPLETED, + eSIR_ULA_FAILURE, + eSIR_SME_LINK_ESTABLISHED, + eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS, + eSIR_SME_UNABLE_TO_PERFORM_DFS, + eSIR_SME_DFS_FAILED, + eSIR_SME_TRANSFER_STA, // To be used when STA need to be LB'ed + eSIR_SME_INVALID_LINK_TEST_PARAMETERS,// Given in LINK_TEST_START_RSP + eSIR_SME_LINK_TEST_MAX_EXCEEDED, // Given in LINK_TEST_START_RSP + eSIR_SME_UNSUPPORTED_RATE, // Given in LINK_TEST_RSP if peer does + // support requested rate in + // LINK_TEST_REQ + eSIR_SME_LINK_TEST_TIMEOUT, // Given in LINK_TEST_IND if peer does + // not respond before next test packet + // is sent + eSIR_SME_LINK_TEST_COMPLETE, // Given in LINK_TEST_IND at the end + // of link test + eSIR_SME_LINK_TEST_INVALID_STATE, // Given in LINK_TEST_START_RSP + eSIR_SME_LINK_TEST_TERMINATE, // Given in LINK_TEST_START_RSP + eSIR_SME_LINK_TEST_INVALID_ADDRESS, // Given in LINK_TEST_STOP_RSP + eSIR_SME_SETCONTEXT_FAILED, // Given in SME_SETCONTEXT_REQ when + // unable to plumb down keys + eSIR_SME_BSS_RESTART, // Given in SME_STOP_BSS_REQ + + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW, // Given in SME_SCAN_RSP message + // that more SME_SCAN_RSP + // messages are following. + // SME_SCAN_RSP message with + // eSIR_SME_SUCCESS status + // code is the last one. + eSIR_SME_INVALID_ASSOC_RSP_RXED, // Sent in SME_JOIN/REASSOC_RSP + // messages upon receiving + // invalid Re/Assoc Rsp frame. + eSIR_SME_MIC_COUNTER_MEASURES, // STOP BSS triggered by MIC failures: MAC software to disassoc all stations + // with MIC_FAILURE reason code and perform the stop bss operation + eSIR_SME_ADDTS_RSP_TIMEOUT, // didn't get response from peer within + // timeout interval + eSIR_SME_ADDTS_RSP_FAILED, // didn't get success response from HAL + eSIR_SME_RECEIVED, + // TBA - TSPEC related Result Codes + + eSIR_SME_CHANNEL_SWITCH_FAIL, // failed to send out Channel Switch Action Frame + eSIR_SME_INVALID_STA_ROLE, + eSIR_SME_INVALID_STATE, + eSIR_SME_CHANNEL_SWITCH_DISABLED, // either 11h is disabled or channelSwitch is currently active + eSIR_SME_HAL_SCAN_INIT_FAILED, // SIR_HAL_SIR_HAL_INIT_SCAN_RSP returned failed status + eSIR_SME_HAL_SCAN_START_FAILED, // SIR_HAL_START_SCAN_RSP returned failed status + eSIR_SME_HAL_SCAN_END_FAILED, // SIR_HAL_END_SCAN_RSP returned failed status + eSIR_SME_HAL_SCAN_FINISH_FAILED, // SIR_HAL_FINISH_SCAN_RSP returned failed status + eSIR_SME_HAL_SEND_MESSAGE_FAIL, // Failed to send a message to HAL +#ifdef FEATURE_OEM_DATA_SUPPORT + eSIR_SME_HAL_OEM_DATA_REQ_START_FAILED, +#endif + eSIR_SME_STOP_BSS_FAILURE, // Failed to stop the bss + eSIR_SME_STA_ASSOCIATED, + eSIR_SME_INVALID_PMM_STATE, + eSIR_SME_CANNOT_ENTER_IMPS, + eSIR_SME_IMPS_REQ_FAILED, + eSIR_SME_BMPS_REQ_FAILED, + eSIR_SME_BMPS_REQ_REJECT, + eSIR_SME_UAPSD_REQ_FAILED, + eSIR_SME_WOWL_ENTER_REQ_FAILED, + eSIR_SME_WOWL_EXIT_REQ_FAILED, +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) + eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE, + eSIR_SME_FT_REASSOC_FAILURE, +#endif + eSIR_SME_SEND_ACTION_FAIL, +#ifdef WLAN_FEATURE_PACKET_FILTERING + eSIR_SME_PC_FILTER_MATCH_COUNT_REQ_FAILED, +#endif // WLAN_FEATURE_PACKET_FILTERING + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + eSIR_SME_GTK_OFFLOAD_GETINFO_REQ_FAILED, +#endif // WLAN_FEATURE_GTK_OFFLOAD + eSIR_SME_DEAUTH_STATUS, + eSIR_SME_SAP_AUTH_OFFLOAD_PEER_UPDATE_STATUS, + eSIR_DONOT_USE_RESULT_CODE = SIR_MAX_ENUM_SIZE +} tSirResultCodes; + +#define RMENABLEDCAP_MAX_LEN 5 + +struct rrm_config_param +{ + uint8_t rrm_enabled; + uint8_t max_randn_interval; + uint8_t rm_capability[RMENABLEDCAP_MAX_LEN]; +}; + +/* each station added has a rate mode which specifies the sta attributes */ +typedef enum eStaRateMode { + eSTA_11b, + eSTA_11bg, + eSTA_11a, + eSTA_11n, +#ifdef WLAN_FEATURE_11AC + eSTA_11ac, +#endif + eSTA_INVALID_RATE_MODE +} tStaRateMode, *tpStaRateMode; + +//although in tSirSupportedRates each IE is 16bit but PE only passes IEs in 8 bits with MSB=1 for basic rates. +//change the mask for bit0-7 only so HAL gets correct basic rates for setting response rates. +#define IERATE_BASICRATE_MASK 0x80 +#define IERATE_RATE_MASK 0x7f +#define IERATE_IS_BASICRATE(x) ((x) & IERATE_BASICRATE_MASK) + +const char * lim_BssTypetoString(const v_U8_t bssType); +const char * lim_ScanTypetoString(const v_U8_t scanType); +const char * lim_BackgroundScanModetoString(const v_U8_t mode); + +typedef struct sSirSupportedRates { + /* + * For Self STA Entry: this represents Self Mode. + * For Peer Stations, this represents the mode of the peer. + * On Station: + * --this mode is updated when PE adds the Self Entry. + * -- OR when PE sends 'ADD_BSS' message and station context in BSS is used to indicate the mode of the AP. + * ON AP: + * -- this mode is updated when PE sends 'ADD_BSS' and Sta entry for that BSS is used + * to indicate the self mode of the AP. + * -- OR when a station is associated, PE sends 'ADD_STA' message with this mode updated. + */ + + tStaRateMode opRateMode; + // 11b, 11a and aniLegacyRates are IE rates which gives rate in unit of 500Kbps + tANI_U16 llbRates[SIR_NUM_11B_RATES]; + tANI_U16 llaRates[SIR_NUM_11A_RATES]; + + /* + * 0-76 bits used, remaining reserved + * bits 0-15 and 32 should be set. + */ + tANI_U8 supportedMCSSet[SIR_MAC_MAX_SUPPORTED_MCS_SET]; + + /* + * RX Highest Supported Data Rate defines the highest data + * rate that the STA is able to receive, in unites of 1Mbps. + * This value is derived from "Supported MCS Set field" inside + * the HT capability element. + */ + tANI_U16 rxHighestDataRate; + +#ifdef WLAN_FEATURE_11AC + /*Indicates the Maximum MCS that can be received for each number + of spacial streams */ + tANI_U16 vhtRxMCSMap; + /*Indicate the highest VHT data rate that the STA is able to receive*/ + tANI_U16 vhtRxHighestDataRate; + /*Indicates the Maximum MCS that can be transmitted for each number + of spacial streams */ + tANI_U16 vhtTxMCSMap; + /*Indicate the highest VHT data rate that the STA is able to transmit*/ + tANI_U16 vhtTxHighestDataRate; +#endif +} tSirSupportedRates, *tpSirSupportedRates; + + +typedef enum eSirRFBand +{ + SIR_BAND_UNKNOWN, + SIR_BAND_2_4_GHZ, + SIR_BAND_5_GHZ, +} tSirRFBand; + + +/* +* Specifies which beacons are to be indicated up to the host driver when +* Station is in power save mode. +*/ +typedef enum eBeaconForwarding +{ + ePM_BEACON_FWD_NTH, + ePM_BEACON_FWD_TIM, + ePM_BEACON_FWD_DTIM, + ePM_BEACON_FWD_NONE +} tBeaconForwarding; + + +typedef struct sSirRemainOnChnReq +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; + tSirMacAddr selfMacAddr; + tANI_U8 chnNum; + tANI_U8 phyMode; + tANI_U32 duration; + tANI_U8 isProbeRequestAllowed; + tANI_U8 probeRspIe[1]; +}tSirRemainOnChnReq, *tpSirRemainOnChnReq; + +typedef struct sSirRegisterMgmtFrame +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; + tANI_BOOLEAN registerFrame; + tANI_U16 frameType; + tANI_U16 matchLen; + tANI_U8 matchData[1]; +}tSirRegisterMgmtFrame, *tpSirRegisterMgmtFrame; + +/// Generic type for sending a response message +/// with result code to host software +typedef struct sSirSmeRsp +{ + tANI_U16 messageType; // eWNI_SME_*_RSP + tANI_U16 length; + tANI_U8 sessionId; // To support BT-AMP + tANI_U16 transactionId; // To support BT-AMP + tSirResultCodes statusCode; +} tSirSmeRsp, *tpSirSmeRsp; + +/// Definition for kick starting Firmware on STA +typedef struct sSirSmeStartReq +{ + tANI_U16 messageType; // eWNI_SME_START_REQ + tANI_U16 length; + tANI_U8 sessionId; //Added for BT-AMP Support + tANI_U16 transcationId; //Added for BT-AMP Support + tSirMacAddr bssId; //Added For BT-AMP Support + tANI_U32 sendNewBssInd; +} tSirSmeStartReq, *tpSirSmeStartReq; + +/// Definition for indicating all modules ready on STA +typedef struct sSirSmeReadyReq +{ + tANI_U16 messageType; // eWNI_SME_SYS_READY_IND + tANI_U16 length; + tANI_U16 transactionId; +} tSirSmeReadyReq, *tpSirSmeReadyReq; + +/// Definition for response message to previously issued start request +typedef struct sSirSmeStartRsp +{ + tANI_U16 messageType; // eWNI_SME_START_RSP + tANI_U16 length; + tSirResultCodes statusCode; + tANI_U16 transactionId; +} tSirSmeStartRsp, *tpSirSmeStartRsp; + + +/// Definition for Load structure +typedef struct sSirLoad +{ + tANI_U16 numStas; + tANI_U16 channelUtilization; +} tSirLoad, *tpSirLoad; + +/// BSS type enum used in while scanning/joining etc +typedef enum eSirBssType +{ + eSIR_INFRASTRUCTURE_MODE, + eSIR_INFRA_AP_MODE, //Added for softAP support + eSIR_IBSS_MODE, + eSIR_BTAMP_STA_MODE, //Added for BT-AMP support + eSIR_BTAMP_AP_MODE, //Added for BT-AMP support + eSIR_AUTO_MODE, + eSIR_DONOT_USE_BSS_TYPE = SIR_MAX_ENUM_SIZE +} tSirBssType; + +/// Power Capability info used in 11H +typedef struct sSirMacPowerCapInfo +{ + tANI_U8 minTxPower; + tANI_U8 maxTxPower; +} tSirMacPowerCapInfo, *tpSirMacPowerCapInfo; + +/// Supported Channel info used in 11H +typedef struct sSirSupChnl +{ + tANI_U8 numChnl; + tANI_U8 channelList[SIR_MAX_SUPPORTED_CHANNEL_LIST]; +} tSirSupChnl, *tpSirSupChnl; + +typedef enum eSirNwType +{ + eSIR_11A_NW_TYPE, + eSIR_11B_NW_TYPE, + eSIR_11G_NW_TYPE, + eSIR_11N_NW_TYPE, +#ifdef WLAN_FEATURE_11AC + eSIR_11AC_NW_TYPE, +#endif + eSIR_DONOT_USE_NW_TYPE = SIR_MAX_ENUM_SIZE +} tSirNwType; + +/// Definition for new iBss peer info +typedef struct sSirNewIbssPeerInfo +{ + tSirMacAddr peerAddr; + tANI_U16 aid; +} tSirNewIbssPeerInfo, *tpSirNewIbssPeerInfo; + +/// Definition for Alternate BSS info +typedef struct sSirAlternateRadioInfo +{ + tSirMacAddr bssId; + tANI_U8 channelId; +} tSirAlternateRadioInfo, *tpSirAlternateRadioInfo; + +/// Definition for Alternate BSS list +typedef struct sSirAlternateRadioList +{ + tANI_U8 numBss; + tSirAlternateRadioInfo alternateRadio[1]; +} tSirAlternateRadioList, *tpSirAlternateRadioList; + +//HT configuration values +typedef __ani_attr_pre_packed struct sSirHtConfig +{ + //Enable/Disable receiving LDPC coded packets + tANI_U32 ht_rx_ldpc:1; + //Enable/Disable TX STBC + tANI_U32 ht_tx_stbc:1; + //Enable/Disable RX STBC + tANI_U32 ht_rx_stbc:2; + //Enable/Disable SGI + tANI_U32 ht_sgi:1; + tANI_U32 unused:27; +} __ani_attr_packed tSirHTConfig, *tpSirHTConfig; + +typedef __ani_attr_pre_packed struct sSirAddIeParams{ + tANI_U16 probeRespDataLen; + tANI_U8 *probeRespData_buff; + tANI_U16 assocRespDataLen; + tANI_U8 *assocRespData_buff; + tANI_U16 probeRespBCNDataLen; + tANI_U8 *probeRespBCNData_buff; +} tSirAddIeParams, *tpSirAddIeParams; + +/// Definition for kick starting BSS +/// ---> MAC +/** + * Usage of ssId, numSSID & ssIdList: + * --------------------------------- + * 1. ssId.length of zero indicates that Broadcast/Suppress SSID + * feature is enabled. + * 2. If ssId.length is zero, MAC SW will advertise NULL SSID + * and interpret the SSID list from numSSID & ssIdList. + * 3. If ssId.length is non-zero, MAC SW will advertise the SSID + * specified in the ssId field and it is expected that + * application will set numSSID to one (only one SSID present + * in the list) and SSID in the list is same as ssId field. + * 4. Application will always set numSSID >= 1. + */ +//*****NOTE: Please make sure all codes are updated if inserting field into this structure..********** +typedef struct sSirSmeStartBssReq +{ + tANI_U16 messageType; // eWNI_SME_START_BSS_REQ + tANI_U16 length; + tANI_U8 sessionId; //Added for BT-AMP Support + tANI_U16 transactionId; //Added for BT-AMP Support + tSirMacAddr bssId; //Added for BT-AMP Support + tSirMacAddr selfMacAddr; //Added for BT-AMP Support + tANI_U16 beaconInterval; //Added for BT-AMP Support + tANI_U8 dot11mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tANI_U8 cc_switch_mode; +#endif + tSirBssType bssType; + tSirMacSSid ssId; + tANI_U8 channelId; + ePhyChanBondState cbMode; + tANI_U8 vht_channel_width; + + tANI_U8 privacy; + tANI_U8 apUapsdEnable; + tANI_U8 ssidHidden; + tANI_BOOLEAN fwdWPSPBCProbeReq; + tANI_BOOLEAN protEnabled; + tANI_BOOLEAN obssProtEnabled; + tANI_U16 ht_capab; + tAniAuthType authType; + tANI_U32 dtimPeriod; + tANI_U8 wps_state; + + /* Coalescing on/off knob */ + tANI_U8 isCoalesingInIBSSAllowed; + tVOS_CON_MODE bssPersona; + + tANI_U8 txLdpcIniFeatureEnabled; + + tSirRSNie rsnIE; // RSN IE to be sent in + // Beacon and Probe + // Response frames + tSirNwType nwType; // Indicates 11a/b/g + tSirMacRateSet operationalRateSet;// Has 11a or 11b rates + tSirMacRateSet extendedRateSet; // Has 11g rates + tSirHTConfig htConfig; + +#ifdef WLAN_FEATURE_11W + tANI_BOOLEAN pmfCapable; + tANI_BOOLEAN pmfRequired; +#endif + + tSirAddIeParams addIeParams; + + tANI_BOOLEAN obssEnabled; + uint8_t sap_dot11mc; + +} tSirSmeStartBssReq, *tpSirSmeStartBssReq; + +#define GET_IE_LEN_IN_BSS(lenInBss) ( lenInBss + sizeof(lenInBss) - \ + ((uintptr_t)OFFSET_OF( tSirBssDescription, ieFields))) + +#define WSCIE_PROBE_RSP_LEN (317 + 2) + +typedef struct sSirBssDescription +{ + //offset of the ieFields from bssId. + tANI_U16 length; + tSirMacAddr bssId; + v_TIME_t scanSysTimeMsec; + tANI_U32 timeStamp[2]; + tANI_U16 beaconInterval; + tANI_U16 capabilityInfo; + tSirNwType nwType; // Indicates 11a/b/g + tANI_S8 rssi; + tANI_S8 rssi_raw; + tANI_S8 sinr; + //channelId what peer sent in beacon/probersp. + tANI_U8 channelId; + //channelId on which we are parked at. + //used only in scan case. + tANI_U8 channelIdSelf; + tANI_U8 sSirBssDescriptionRsvd[3]; + tANI_TIMESTAMP nReceivedTime; //base on a tick count. It is a time stamp, not a relative time. +#if defined WLAN_FEATURE_VOWIFI + tANI_U32 parentTSF; + tANI_U32 startTSF[2]; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_U8 mdiePresent; + tANI_U8 mdie[SIR_MDIE_SIZE]; // MDIE for 11r, picked from the beacons +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U16 QBSSLoad_present; + tANI_U16 QBSSLoad_avail; + tANI_U32 reservedPadding5; // To achieve 8-byte alignment with ESE enabled +#endif + // Please keep the structure 4 bytes aligned above the ieFields + + tANI_U8 fProbeRsp; //whether it is from a probe rsp + tANI_U8 reservedPadding1; + tANI_U8 reservedPadding2; + tANI_U8 reservedPadding3; + tANI_U32 WscIeLen; + tANI_U8 WscIeProbeRsp[WSCIE_PROBE_RSP_LEN]; + tANI_U8 reservedPadding4; + tANI_U32 tsf_delta; + + tANI_U32 ieFields[1]; +} tSirBssDescription, *tpSirBssDescription; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +typedef struct sSirSmeHTProfile +{ + tANI_U8 dot11mode; + tANI_U8 htCapability; + tANI_U8 htSupportedChannelWidthSet; + tANI_U8 htRecommendedTxWidthSet; + ePhyChanBondState htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtCapability; + tANI_U8 vhtTxChannelWidthSet; + tANI_U8 apCenterChan; + tANI_U8 apChanWidth; +#endif +} tSirSmeHTProfile; +#endif +/// Definition for response message to previously +/// issued start BSS request +/// MAC ---> +typedef struct sSirSmeStartBssRsp +{ + tANI_U16 messageType; // eWNI_SME_START_BSS_RSP + tANI_U16 length; + tANI_U8 sessionId; + tANI_U16 transactionId;//transaction ID for cmd + tSirResultCodes statusCode; + tSirBssType bssType;//Add new type for WDS mode + tANI_U16 beaconInterval;//Beacon Interval for both type + tANI_U32 staId; /* Station ID for Self */ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile HTProfile; +#endif + tSirBssDescription bssDescription;//Peer BSS description +} tSirSmeStartBssRsp, *tpSirSmeStartBssRsp; + + +typedef struct sSirChannelList +{ + tANI_U8 numChannels; + tANI_U8 channelNumber[SIR_ESE_MAX_MEAS_IE_REQS]; +} tSirChannelList, *tpSirChannelList; + +typedef struct sSirDFSChannelList +{ + tANI_U32 timeStamp[SIR_MAX_24G_5G_CHANNEL_RANGE]; + +} tSirDFSChannelList, *tpSirDFSChannelList; + +#ifdef FEATURE_WLAN_ESE +typedef struct sTspecInfo { + tANI_U8 valid; + tSirMacTspecIE tspec; +} tTspecInfo; + +#define SIR_ESE_MAX_TSPEC_IES 4 +typedef struct sESETspecTspecInfo { + tANI_U8 numTspecs; + tTspecInfo tspec[SIR_ESE_MAX_TSPEC_IES]; +} tESETspecInfo; +#endif + + +/// Definition for Radar Info +typedef struct sSirRadarInfo +{ + tANI_U8 channelNumber; + tANI_U16 radarPulseWidth; // in usecond + tANI_U16 numRadarPulse; +} tSirRadarInfo, *tpSirRadarInfo; + +#define SIR_RADAR_INFO_SIZE (sizeof(tANI_U8) + 2 *sizeof(tANI_U16)) + +/// Two Background Scan mode +typedef enum eSirBackgroundScanMode +{ + eSIR_AGGRESSIVE_BACKGROUND_SCAN = 0, + eSIR_NORMAL_BACKGROUND_SCAN = 1, + eSIR_ROAMING_SCAN = 2, +} tSirBackgroundScanMode; + +/// Two types of traffic check +typedef enum eSirLinkTrafficCheck +{ + eSIR_DONT_CHECK_LINK_TRAFFIC_BEFORE_SCAN = 0, + eSIR_CHECK_LINK_TRAFFIC_BEFORE_SCAN = 1, + eSIR_CHECK_ROAMING_SCAN = 2, +} tSirLinkTrafficCheck; + +#define SIR_BG_SCAN_RETURN_CACHED_RESULTS 0x0 +#define SIR_BG_SCAN_PURGE_RESUTLS 0x80 +#define SIR_BG_SCAN_RETURN_FRESH_RESULTS 0x01 +#define SIR_SCAN_MAX_NUM_SSID 0x0A +#define SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS 0x02 +#define SIR_BG_SCAN_PURGE_LFR_RESULTS 0x40 + +/// Definition for scan request +typedef struct sSirSmeScanReq +{ + tANI_U16 messageType; // eWNI_SME_SCAN_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssId; + tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; + tSirMacAddr selfMacAddr; //Added For BT-AMP Support + tSirBssType bssType; + tANI_U8 dot11mode; + tSirScanType scanType; + /** + * minChannelTime. Not used if scanType is passive. + * 0x0 - Dont Use min channel timer. Only max channel timeout will used. + * 11k measurements set this to zero to user only single duration for scan. + * - Timeout value used for min channel timeout. + */ + tANI_U32 minChannelTime; + /** + * maxChannelTime. + * 0x0 - Invalid. In case of active scan. + * In case of passive scan, MAX( maxChannelTime, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME) is used. + * + */ + tANI_U32 maxChannelTime; + /** + * returnAfterFirstMatch can take following values: + * 0x00 - Return SCAN_RSP message after complete channel scan + * 0x01 - Return SCAN_RSP message after collecting BSS description + * that matches scan criteria. + * 0xC0 - Return after collecting first 11d IE from 2.4 GHz & + * 5 GHz band channels + * 0x80 - Return after collecting first 11d IE from 5 GHz band + * channels + * 0x40 - Return after collecting first 11d IE from 2.4 GHz + * band channels + * + * Values of 0xC0, 0x80 & 0x40 are to be used by + * Roaming/application when 11d is enabled. + */ + tANI_U32 minChannelTimeBtc; //in units of milliseconds + tANI_U32 maxChannelTimeBtc; //in units of milliseconds + tANI_U32 restTime; //in units of milliseconds, ignored when not connected + /*in units of milliseconds, ignored when not connected*/ + uint32_t min_rest_time; + /*in units of milliseconds, ignored when not connected*/ + uint32_t idle_time; + + tANI_U8 returnAfterFirstMatch; + + /** + * returnUniqueResults can take following values: + * 0 - Collect & report all received BSS descriptions from same BSS. + * 1 - Collect & report unique BSS description from same BSS. + */ + tANI_U8 returnUniqueResults; + + /** + * returnFreshResults can take following values: + * 0x00 - Return background scan results. + * 0x80 - Return & purge background scan results + * 0x01 - Trigger fresh scan instead of returning background scan + * results. + * 0x81 - Trigger fresh scan instead of returning background scan + * results and purge background scan results. + */ + tANI_U8 returnFreshResults; + + /* backgroundScanMode can take following values: + * 0x0 - aggressive scan + * 0x1 - normal scan where HAL will check for link traffic + * prior to proceeding with the scan + */ + tSirBackgroundScanMode backgroundScanMode; + + tANI_U8 hiddenSsid; + + /* Number of SSIDs to scan */ + tANI_U8 numSsid; + + //channelList has to be the last member of this structure. Check tSirChannelList for the reason. + /* This MUST be the last field of the structure */ + + + tANI_BOOLEAN p2pSearch; + tANI_U16 uIEFieldLen; + tANI_U16 uIEFieldOffset; + + //channelList MUST be the last field of this structure + tSirChannelList channelList; + /*----------------------------- + tSirSmeScanReq.... + ----------------------------- + uIEFiledLen + ----------------------------- + uIEFiledOffset ----+ + ----------------------------- | + channelList.numChannels | + ----------------------------- | + ... variable size up to | + channelNumber[numChannels-1] | + This can be zero, if | + numChannel is zero. | + ----------------------------- <--+ + ... variable size uIEFiled + up to uIEFieldLen (can be 0) + -----------------------------*/ +} tSirSmeScanReq, *tpSirSmeScanReq; + +typedef struct sSirSmeScanAbortReq +{ + tANI_U16 type; + tANI_U16 msgLen; + tANI_U8 sessionId; +} tSirSmeScanAbortReq, *tpSirSmeScanAbortReq; + +typedef struct sSirSmeScanChanReq +{ + tANI_U16 type; + tANI_U16 msgLen; + tANI_U8 sessionId; + tANI_U16 transcationId; +} tSirSmeGetScanChanReq, *tpSirSmeGetScanChanReq; + +#ifdef FEATURE_OEM_DATA_SUPPORT + +#ifndef OEM_DATA_REQ_SIZE +#define OEM_DATA_REQ_SIZE 280 +#endif +#ifndef OEM_DATA_RSP_SIZE +#define OEM_DATA_RSP_SIZE 1724 +#endif + +typedef struct sSirOemDataReq +{ + tANI_U16 messageType; //eWNI_SME_OEM_DATA_REQ + tANI_U16 messageLen; + tSirMacAddr selfMacAddr; + tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; +} tSirOemDataReq, *tpSirOemDataReq; + +typedef struct sSirOemDataRsp +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 oemDataRsp[OEM_DATA_RSP_SIZE]; +} tSirOemDataRsp, *tpSirOemDataRsp; + +#endif //FEATURE_OEM_DATA_SUPPORT + +/// Definition for response message to previously issued scan request +typedef struct sSirSmeScanRsp +{ + tANI_U16 messageType; // eWNI_SME_SCAN_RSP + tANI_U16 length; + tANI_U8 sessionId; + tSirResultCodes statusCode; + tANI_U16 transcationId; + tSirBssDescription bssDescription[1]; +} tSirSmeScanRsp, *tpSirSmeScanRsp; + +/// Sme Req message to set the Background Scan mode +typedef struct sSirSmeBackgroundScanModeReq +{ + tANI_U16 messageType; // eWNI_SME_BACKGROUND_SCAN_MODE_REQ + tANI_U16 length; + tSirBackgroundScanMode mode; +} tSirSmeBackgroundScanModeReq, *tpSirSmeBackgroundScanModeReq; + +/* Background Scan Statistics */ +typedef struct sSirBackgroundScanInfo { + tANI_U32 numOfScanSuccess; + tANI_U32 numOfScanFailure; + tANI_U32 reserved; +} tSirBackgroundScanInfo, *tpSirBackgroundScanInfo; + +#define SIR_BACKGROUND_SCAN_INFO_SIZE (3 * sizeof(tANI_U32)) + +/* Definition for Join/Reassoc info */ +typedef struct sJoinReassocInfo +{ + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; +} tJoinReassocInfo, *tpJoinReassocInfo; + +/// Definition for join request +/// ---> MAC +/// WARNING! If you add a field in JOIN REQ. +/// Make sure to add it in REASSOC REQ +/// The Serdes function is the same and its +/// shared with REASSOC. So if we add a field +// here and dont add it in REASSOC REQ. It will BREAK!!! REASSOC. +typedef struct sSirSmeJoinReq +{ + tANI_U16 messageType; // eWNI_SME_JOIN_REQ + tANI_U16 length; + tANI_U8 sessionId; + tANI_U16 transactionId; + tSirMacSSid ssId; + tSirMacAddr selfMacAddr; // self Mac address + tSirBssType bsstype; // add new type for BT -AMP STA and AP Modules + tANI_U8 dot11mode; // to support BT-AMP +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tANI_U8 cc_switch_mode; +#endif + tVOS_CON_MODE staPersona; //Persona + ePhyChanBondState cbMode; // Pass CB mode value in Join. + + /*This contains the UAPSD Flag for all 4 AC + * B0: AC_VO UAPSD FLAG + * B1: AC_VI UAPSD FLAG + * B2: AC_BK UAPSD FLAG + * B3: AC_BE UASPD FLAG + */ + tANI_U8 uapsdPerAcBitmask; + + tSirMacRateSet operationalRateSet;// Has 11a or 11b rates + tSirMacRateSet extendedRateSet; // Has 11g rates + tSirRSNie rsnIE; // RSN IE to be sent in + // (Re) Association Request +#ifdef FEATURE_WLAN_ESE + tSirCCKMie cckmIE; // CCMK IE to be included as handler for join and reassoc is + // the same. The join will never carry cckm, but will be set to + // 0. +#endif + + tSirAddie addIEScan; // Additional IE to be sent in + // (unicast) Probe Request at the time of join + + tSirAddie addIEAssoc; // Additional IE to be sent in + // (Re) Association Request + + tAniEdType UCEncryptionType; + + tAniEdType MCEncryptionType; + +#ifdef WLAN_FEATURE_11W + tAniEdType MgmtEncryptionType; +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + tAniBool is11Rconnection; +#endif +#ifdef FEATURE_WLAN_ESE + tAniBool isESEFeatureIniEnabled; + tAniBool isESEconnection; + tESETspecInfo eseTspecInfo; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + tAniBool isFastTransitionEnabled; +#endif +#ifdef FEATURE_WLAN_LFR + tAniBool isFastRoamIniFeatureEnabled; +#endif + + tANI_U8 txLdpcIniFeatureEnabled; + tSirHTConfig htConfig; +#ifdef WLAN_FEATURE_11AC + tANI_U8 txBFIniFeatureEnabled; + tANI_U8 txBFCsnValue; + tANI_U8 txMuBformee; + tANI_U8 enableVhtpAid; + tANI_U8 enableVhtGid; +#endif + tANI_U8 enableAmpduPs; + tANI_U8 enableHtSmps; + tANI_U8 htSmps; + + tANI_U8 max_amsdu_num; + tAniBool isWMEenabled; + tAniBool isQosEnabled; + tAniBool isOSENConnection; + struct rrm_config_param rrm_config; + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; + tSirBssDescription bssDescription; + +} tSirSmeJoinReq, *tpSirSmeJoinReq; + +/* Definition for response message to previously issued join request */ +typedef struct sSirSmeJoinRsp +{ + tANI_U16 messageType; // eWNI_SME_JOIN_RSP + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirResultCodes statusCode; + tAniAuthType authType; + tANI_U32 vht_channel_width; + tANI_U16 protStatusCode; //It holds reasonCode when join fails due to deauth/disassoc frame. + //Otherwise it holds status code. + tANI_U16 aid; + tANI_U32 beaconLength; + tANI_U32 assocReqLength; + tANI_U32 assocRspLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_U32 parsedRicRspLen; +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U32 tspecIeLen; +#endif + tANI_U32 staId;//Station ID for peer + + /*The DPU signatures will be sent eventually to TL to help it determine the + association to which a packet belongs to*/ + /*Unicast DPU signature*/ + tANI_U8 ucastSig; + + /*Broadcast DPU signature*/ + tANI_U8 bcastSig; + + /* Timing and fine Timing measurement capability clubbed together */ + tANI_U8 timingMeasCap; + +#ifdef FEATURE_WLAN_TDLS + /* TDLS prohibited and TDLS channel switch prohibited are set as + * per ExtCap IE in received assoc/re-assoc response from AP + */ + bool tdls_prohibited; + bool tdls_chan_swit_prohibited; +#endif + + uint8_t nss; + uint32_t max_rate_flags; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile HTProfile; +#endif + + bool supported_nss_1x1; + /* Add new members before 'frames' to avoid memory corruption of 'frames' */ + tANI_U8 frames[ 1 ]; +} tSirSmeJoinRsp, *tpSirSmeJoinRsp; + +/// Definition for Authentication indication from peer +typedef struct sSirSmeAuthInd +{ + tANI_U16 messageType; // eWNI_SME_AUTH_IND + tANI_U16 length; + tANI_U8 sessionId; + tSirMacAddr bssId; // Self BSSID + tSirMacAddr peerMacAddr; + tAniAuthType authType; +} tSirSmeAuthInd, *tpSirSmeAuthInd; + +/// probereq from peer, when wsc is enabled +typedef struct sSirSmeProbereq +{ + tANI_U16 messageType; // eWNI_SME_PROBE_REQ + tANI_U16 length; + tANI_U8 sessionId; + tSirMacAddr peerMacAddr; + tANI_U16 devicePasswdId; +} tSirSmeProbeReq, *tpSirSmeProbeReq; + +typedef struct sSirSmeChanInfo +{ + /* channel id */ + tANI_U8 chan_id; + /* primary 20 MHz channel frequency in mhz */ + tANI_U32 mhz; + /* Center frequency 1 in MHz */ + tANI_U32 band_center_freq1; + /* Center frequency 2 in MHz - valid only for 11acvht 80plus80 mode */ + tANI_U32 band_center_freq2; + /* channel info described below */ + tANI_U32 info; + /* contains min power, max power, reg power and reg class id */ + tANI_U32 reg_info_1; + /* contains antennamax */ + tANI_U32 reg_info_2; + /* number of spatial streams */ + uint8_t nss; + /* rate flags */ + uint32_t rate_flags; +} tSirSmeChanInfo, *tpSirSmeChanInfo; +/// Definition for Association indication from peer +/// MAC ---> +typedef struct sSirSmeAssocInd +{ + tANI_U16 messageType; // eWNI_SME_ASSOC_IND + tANI_U16 length; + tANI_U8 sessionId; + tSirMacAddr peerMacAddr; + tANI_U16 aid; + tSirMacAddr bssId; // Self BSSID + tANI_U16 staId; // Station ID for peer + tANI_U8 uniSig; // DPU signature for unicast packets + tANI_U8 bcastSig; // DPU signature for broadcast packets + tAniAuthType authType; + tAniSSID ssId; // SSID used by STA to associate + tSirWAPIie wapiIE;//WAPI IE received from peer + tSirRSNie rsnIE;// RSN IE received from peer + tSirAddie addIE;// Additional IE received from peer, which possibly include WSC IE and/or P2P IE + + // powerCap & supportedChannels are present only when + // spectrumMgtIndicator flag is set + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; + tAniBool wmmEnabledSta; /* if present - STA is WMM enabled */ + tAniBool reassocReq; + // Required for indicating the frames to upper layer + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; + + /* Timing and fine Timing measurement capability clubbed together */ + tANI_U8 timingMeasCap; + tSirSmeChanInfo chan_info; +} tSirSmeAssocInd, *tpSirSmeAssocInd; + + +/// Definition for Association confirm +/// ---> MAC +typedef struct sSirSmeAssocCnf +{ + tANI_U16 messageType; // eWNI_SME_ASSOC_CNF + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr bssId; // Self BSSID + tSirMacAddr peerMacAddr; + tANI_U16 aid; + tSirMacAddr alternateBssId; + tANI_U8 alternateChannelId; +} tSirSmeAssocCnf, *tpSirSmeAssocCnf; + +/// Definition for Reassociation indication from peer +typedef struct sSirSmeReassocInd +{ + tANI_U16 messageType; // eWNI_SME_REASSOC_IND + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tSirMacAddr peerMacAddr; + tSirMacAddr oldMacAddr; + tANI_U16 aid; + tSirMacAddr bssId; // Self BSSID + tANI_U16 staId; // Station ID for peer + tAniAuthType authType; + tAniSSID ssId; // SSID used by STA to reassociate + tSirRSNie rsnIE; // RSN IE received from peer + + tSirAddie addIE; // Additional IE received from peer + + // powerCap & supportedChannels are present only when + // spectrumMgtIndicator flag is set + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; + // Required for indicating the frames to upper layer + // TODO: use the appropriate names to distinguish between the other similar names used above for station mode of operation + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; +} tSirSmeReassocInd, *tpSirSmeReassocInd; + +/// Definition for Reassociation confirm +/// ---> MAC +typedef struct sSirSmeReassocCnf +{ + tANI_U16 messageType; // eWNI_SME_REASSOC_CNF + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr bssId; // Self BSSID + tSirMacAddr peerMacAddr; + tANI_U16 aid; + tSirMacAddr alternateBssId; + tANI_U8 alternateChannelId; +} tSirSmeReassocCnf, *tpSirSmeReassocCnf; + + +/// Enum definition for Wireless medium status change codes +typedef enum eSirSmeStatusChangeCode +{ + eSIR_SME_DEAUTH_FROM_PEER, + eSIR_SME_DISASSOC_FROM_PEER, + eSIR_SME_LOST_LINK_WITH_PEER, + eSIR_SME_CHANNEL_SWITCH, + eSIR_SME_JOINED_NEW_BSS, + eSIR_SME_LEAVING_BSS, + eSIR_SME_IBSS_ACTIVE, + eSIR_SME_IBSS_INACTIVE, + eSIR_SME_IBSS_PEER_DEPARTED, + eSIR_SME_RADAR_DETECTED, + eSIR_SME_IBSS_NEW_PEER, + eSIR_SME_AP_CAPS_CHANGED, + eSIR_SME_BACKGROUND_SCAN_FAIL, + eSIR_SME_CB_LEGACY_BSS_FOUND_BY_AP, + eSIR_SME_CB_LEGACY_BSS_FOUND_BY_STA +} tSirSmeStatusChangeCode; + +typedef struct sSirSmeNewBssInfo +{ + tSirMacAddr bssId; + tANI_U8 channelNumber; + tANI_U8 reserved; + tSirMacSSid ssId; +} tSirSmeNewBssInfo, *tpSirSmeNewBssInfo; + +typedef struct sSirSmeApNewCaps +{ + tANI_U16 capabilityInfo; + tSirMacAddr bssId; + tANI_U8 channelId; + tANI_U8 reserved[3]; + tSirMacSSid ssId; +} tSirSmeApNewCaps, *tpSirSmeApNewCaps; + +/** + * Table below indicates what information is passed for each of + * the Wireless Media status change notifications: + * + * Status Change code Status change info + * ---------------------------------------------------------------------- + * eSIR_SME_DEAUTH_FROM_PEER Reason code received in DEAUTH frame + * eSIR_SME_DISASSOC_FROM_PEER Reason code received in DISASSOC frame + * eSIR_SME_LOST_LINK_WITH_PEER None + * eSIR_SME_CHANNEL_SWITCH New channel number + * eSIR_SME_JOINED_NEW_BSS BSSID, SSID and channel number + * eSIR_SME_LEAVING_BSS None + * eSIR_SME_IBSS_ACTIVE Indicates that another STA joined + * IBSS apart from this STA that + * started IBSS + * eSIR_SME_IBSS_INACTIVE Indicates that only this STA is left + * in IBSS + * eSIR_SME_RADAR_DETECTED Indicates that radar is detected + * eSIR_SME_IBSS_NEW_PEER Indicates that a new peer is detected + * eSIR_SME_AP_CAPS_CHANGED Indicates that capabilities of the AP + * that STA is currently associated with + * have changed. + * eSIR_SME_BACKGROUND_SCAN_FAIL Indicates background scan failure + */ + +/// Definition for Wireless medium status change notification +typedef struct sSirSmeWmStatusChangeNtf +{ + tANI_U16 messageType; // eWNI_SME_WM_STATUS_CHANGE_NTF + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tSirSmeStatusChangeCode statusChangeCode; + tSirMacAddr bssId; // Self BSSID + union + { + tANI_U16 deAuthReasonCode; // eSIR_SME_DEAUTH_FROM_PEER + tANI_U16 disassocReasonCode; // eSIR_SME_DISASSOC_FROM_PEER + // none for eSIR_SME_LOST_LINK_WITH_PEER + tANI_U8 newChannelId; // eSIR_SME_CHANNEL_SWITCH + tSirSmeNewBssInfo newBssInfo; // eSIR_SME_JOINED_NEW_BSS + // none for eSIR_SME_LEAVING_BSS + // none for eSIR_SME_IBSS_ACTIVE + // none for eSIR_SME_IBSS_INACTIVE + tSirNewIbssPeerInfo newIbssPeerInfo; // eSIR_SME_IBSS_NEW_PEER + tSirSmeApNewCaps apNewCaps; // eSIR_SME_AP_CAPS_CHANGED + tSirBackgroundScanInfo bkgndScanInfo; // eSIR_SME_BACKGROUND_SCAN_FAIL + } statusChangeInfo; +} tSirSmeWmStatusChangeNtf, *tpSirSmeWmStatusChangeNtf; + +/// Definition for Disassociation request +typedef +__ani_attr_pre_packed +struct sSirSmeDisassocReq +{ + tANI_U16 messageType; // eWNI_SME_DISASSOC_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssId; // Peer BSSID + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; + tANI_U8 doNotSendOverTheAir; //This flag tells LIM whether to send the disassoc OTA or not + //This will be set in while handing off from one AP to other +} +__ani_attr_packed +tSirSmeDisassocReq, *tpSirSmeDisassocReq; + +/// Definition for Tkip countermeasures request +typedef __ani_attr_pre_packed struct sSirSmeTkipCntrMeasReq +{ + tANI_U16 messageType; // eWNI_SME_DISASSOC_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssId; // Peer BSSID + tANI_BOOLEAN bEnable; // Start/stop countermeasures +} __ani_attr_packed tSirSmeTkipCntrMeasReq, *tpSirSmeTkipCntrMeasReq; + +typedef struct sAni64BitCounters +{ + tANI_U32 Hi; + tANI_U32 Lo; +}tAni64BitCounters, *tpAni64BitCounters; + +typedef struct sAniSecurityStat +{ + tAni64BitCounters txBlks; + tAni64BitCounters rxBlks; + tAni64BitCounters formatErrorCnt; + tAni64BitCounters decryptErr; + tAni64BitCounters protExclCnt; + tAni64BitCounters unDecryptableCnt; + tAni64BitCounters decryptOkCnt; + +}tAniSecurityStat, *tpAniSecurityStat; + +typedef struct sAniTxRxCounters +{ + tANI_U32 txFrames; // Incremented for every packet tx + tANI_U32 rxFrames; + tANI_U32 nRcvBytes; + tANI_U32 nXmitBytes; +}tAniTxRxCounters, *tpAniTxRxCounters; + +typedef struct sAniTxRxStats +{ + tAni64BitCounters txFrames; + tAni64BitCounters rxFrames; + tAni64BitCounters nRcvBytes; + tAni64BitCounters nXmitBytes; + +}tAniTxRxStats,*tpAniTxRxStats; + +typedef struct sAniSecStats +{ + tAniSecurityStat aes; + tAni64BitCounters aesReplays; + tAniSecurityStat tkip; + tAni64BitCounters tkipReplays; + tAni64BitCounters tkipMicError; + + tAniSecurityStat wep; +#if defined(FEATURE_WLAN_WAPI) && !defined(LIBRA_WAPI_SUPPORT) + tAniSecurityStat wpi; + tAni64BitCounters wpiReplays; + tAni64BitCounters wpiMicError; +#endif +}tAniSecStats, *tpAniSecStats; + +#define SIR_MAX_RX_CHAINS 3 + +typedef struct sAniStaStatStruct +{ + /* following statistic elements till expandPktRxCntLo are not filled with valid data. + * These are kept as it is, since WSM is using this structure. + * These elements can be removed whenever WSM is updated. + * Phystats is used to hold phystats from BD. + */ + tANI_U32 sentAesBlksUcastHi; + tANI_U32 sentAesBlksUcastLo; + tANI_U32 recvAesBlksUcastHi; + tANI_U32 recvAesBlksUcastLo; + tANI_U32 aesFormatErrorUcastCnts; + tANI_U32 aesReplaysUcast; + tANI_U32 aesDecryptErrUcast; + tANI_U32 singleRetryPkts; + tANI_U32 failedTxPkts; + tANI_U32 ackTimeouts; + tANI_U32 multiRetryPkts; + tANI_U32 fragTxCntsHi; + tANI_U32 fragTxCntsLo; + tANI_U32 transmittedPktsHi; + tANI_U32 transmittedPktsLo; + tANI_U32 phyStatHi; //These are used to fill in the phystats. + tANI_U32 phyStatLo; //This is only for private use. + + tANI_U32 uplinkRssi; + tANI_U32 uplinkSinr; + tANI_U32 uplinkRate; + tANI_U32 downlinkRssi; + tANI_U32 downlinkSinr; + tANI_U32 downlinkRate; + tANI_U32 nRcvBytes; + tANI_U32 nXmitBytes; + + /* Following elements are valid and filled in correctly. They have valid values. + */ + + //Unicast frames and bytes. + tAniTxRxStats ucStats; + + //Broadcast frames and bytes. + tAniTxRxStats bcStats; + + //Multicast frames and bytes. + tAniTxRxStats mcStats; + + tANI_U32 currentTxRate; + tANI_U32 currentRxRate; //Rate in 100Kbps + + tANI_U32 maxTxRate; + tANI_U32 maxRxRate; + + tANI_S8 rssi[SIR_MAX_RX_CHAINS]; + + + tAniSecStats securityStats; + + tANI_U8 currentRxRateIdx; //This the softmac rate Index. + tANI_U8 currentTxRateIdx; + +} tAniStaStatStruct, *tpAniStaStatStruct; + +//Statistics that are not maintained per stations. +typedef struct sAniGlobalStatStruct +{ + tAni64BitCounters txError; + tAni64BitCounters rxError; + tAni64BitCounters rxDropNoBuffer; + tAni64BitCounters rxDropDup; + tAni64BitCounters rxCRCError; + + tAni64BitCounters singleRetryPkts; + tAni64BitCounters failedTxPkts; + tAni64BitCounters ackTimeouts; + tAni64BitCounters multiRetryPkts; + tAni64BitCounters fragTxCnts; + tAni64BitCounters fragRxCnts; + + tAni64BitCounters txRTSSuccess; + tAni64BitCounters txCTSSuccess; + tAni64BitCounters rxRTSSuccess; + tAni64BitCounters rxCTSSuccess; + + tAniSecStats securityStats; + + tAniTxRxStats mcStats; + tAniTxRxStats bcStats; + +}tAniGlobalStatStruct,*tpAniGlobalStatStruct; + +typedef enum sPacketType +{ + ePACKET_TYPE_UNKNOWN, + ePACKET_TYPE_11A, + ePACKET_TYPE_11G, + ePACKET_TYPE_11B, + ePACKET_TYPE_11N + +}tPacketType, *tpPacketType; + +typedef struct sAniStatSummaryStruct +{ + tAniTxRxStats uc; //Unicast counters. + tAniTxRxStats bc; //Broadcast counters. + tAniTxRxStats mc; //Multicast counters. + tAni64BitCounters txError; + tAni64BitCounters rxError; + tANI_S8 rssi[SIR_MAX_RX_CHAINS]; //For each chain. + tANI_U32 rxRate; // Rx rate of the last received packet. + tANI_U32 txRate; + tANI_U16 rxMCSId; //MCS index is valid only when packet type is ePACKET_TYPE_11N + tANI_U16 txMCSId; + tPacketType rxPacketType; + tPacketType txPacketType; + tSirMacAddr macAddr; //Mac Address of the station from which above RSSI and rate is from. +}tAniStatSummaryStruct,*tpAniStatSummaryStruct; + +//structure for stats that may be reset, like the ones in sta descriptor +//The stats are saved into here before reset. It should be tANI_U32 aligned. +typedef struct _sPermStaStats +{ + tANI_U32 aesFormatErrorUcastCnts; + tANI_U32 aesReplaysUcast; + tANI_U32 aesDecryptErrUcast; + tANI_U32 singleRetryPkts; + tANI_U32 failedTxPkts; + tANI_U32 ackTimeouts; + tANI_U32 multiRetryPkts; + tANI_U32 fragTxCntsHi; + tANI_U32 fragTxCntsLo; + tANI_U32 transmittedPktsHi; + tANI_U32 transmittedPktsLo; +}tPermanentStaStats; + + +/// Definition for Disassociation response +typedef struct sSirSmeDisassocRsp +{ + tANI_U16 messageType; // eWNI_SME_DISASSOC_RSP + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; + tAniStaStatStruct perStaStats; // STA stats + tANI_U16 staId; +} +__ani_attr_packed + tSirSmeDisassocRsp, *tpSirSmeDisassocRsp; + +/// Definition for Disassociation indication from peer +typedef struct sSirSmeDisassocInd +{ + tANI_U16 messageType; // eWNI_SME_DISASSOC_IND + tANI_U16 length; + tANI_U8 sessionId; // Session Identifier + tANI_U16 transactionId; // Transaction Identifier with PE + tSirResultCodes statusCode; + tSirMacAddr bssId; + tSirMacAddr peerMacAddr; + tAniStaStatStruct perStaStats; // STA stats + tANI_U16 staId; + tANI_U32 reasonCode; +} tSirSmeDisassocInd, *tpSirSmeDisassocInd; + +/// Definition for Disassociation confirm +/// MAC ---> +typedef struct sSirSmeDisassocCnf +{ + tANI_U16 messageType; // eWNI_SME_DISASSOC_CNF + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr bssId; + tSirMacAddr peerMacAddr; +} tSirSmeDisassocCnf, *tpSirSmeDisassocCnf; + +/* Definition for Deauthentication request */ +typedef struct sSirSmeDeauthReq +{ + tANI_U16 messageType; // eWNI_SME_DEAUTH_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssId; // AP BSSID + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; +} tSirSmeDeauthReq, *tpSirSmeDeauthReq; + +/* Definition for Deauthentication response */ +typedef struct sSirSmeDeauthRsp +{ + tANI_U16 messageType; // eWNI_SME_DEAUTH_RSP + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirSmeDeauthRsp, *tpSirSmeDeauthRsp; + +/* Definition for Deauthentication indication from peer */ +typedef struct sSirSmeDeauthInd +{ + tANI_U16 messageType; // eWNI_SME_DEAUTH_IND + tANI_U16 length; + tANI_U8 sessionId; //Added for BT-AMP + tANI_U16 transactionId; //Added for BT-AMP + tSirResultCodes statusCode; + tSirMacAddr bssId;// AP BSSID + tSirMacAddr peerMacAddr; + + tANI_U16 staId; + tANI_U32 reasonCode; + tANI_S8 rssi; +} tSirSmeDeauthInd, *tpSirSmeDeauthInd; + +/// Definition for Deauthentication confirm +/// MAC ---> +typedef struct sSirSmeDeauthCnf +{ + tANI_U16 messageType; // eWNI_SME_DEAUTH_CNF + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr bssId; // AP BSSID + tSirMacAddr peerMacAddr; +} tSirSmeDeauthCnf, *tpSirSmeDeauthCnf; + +/// Definition for stop BSS request message +typedef struct sSirSmeStopBssReq +{ + tANI_U16 messageType; // eWNI_SME_STOP_BSS_REQ + tANI_U16 length; + tANI_U8 sessionId; //Session ID + tANI_U16 transactionId; //tranSaction ID for cmd + tSirResultCodes reasonCode; + tSirMacAddr bssId; //Self BSSID +} tSirSmeStopBssReq, *tpSirSmeStopBssReq; + +/// Definition for stop BSS response message +typedef struct sSirSmeStopBssRsp +{ + tANI_U16 messageType; // eWNI_SME_STOP_BSS_RSP + tANI_U16 length; + tSirResultCodes statusCode; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd +} tSirSmeStopBssRsp, *tpSirSmeStopBssRsp; + + + +/// Definition for Channel Switch indication for station +/// MAC ---> +typedef struct sSirSmeSwitchChannelInd +{ + tANI_U16 messageType; // eWNI_SME_SWITCH_CHL_REQ + tANI_U16 length; + tANI_U8 sessionId; + tANI_U16 newChannelId; + tSirMacAddr bssId; // BSSID +} tSirSmeSwitchChannelInd, *tpSirSmeSwitchChannelInd; + +/// Definition for ULA complete indication message +typedef struct sirUlaCompleteInd +{ + tANI_U16 messageType; // eWNI_ULA_COMPLETE_IND + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirUlaCompleteInd, *tpSirUlaCompleteInd; + +/// Definition for ULA complete confirmation message +typedef struct sirUlaCompleteCnf +{ + tANI_U16 messageType; // eWNI_ULA_COMPLETE_CNF + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirUlaCompleteCnf, *tpSirUlaCompleteCnf; + +/* + * Definition for Neighbor BSS indication + * MAC ---> + * MAC reports this each time a new I/BSS is detected + */ +typedef struct sSirSmeNeighborBssInd +{ + tANI_U16 messageType; // eWNI_SME_NEIGHBOR_BSS_IND + tANI_U16 length; + tANI_U8 sessionId; + tSirBssDescription bssDescription[1]; +} tSirSmeNeighborBssInd, *tpSirSmeNeighborBssInd; + +/* + * Definition for MIC failure indication + * MAC ---> + * MAC reports this each time a MIC failure occurs on Rx TKIP packet + */ +typedef struct sSirSmeMicFailureInd +{ + tANI_U16 messageType; // eWNI_SME_MIC_FAILURE_IND + tANI_U16 length; + tANI_U8 sessionId; + tSirMacAddr bssId; // BSSID + tSirMicFailureInfo info; +} tSirSmeMicFailureInd, *tpSirSmeMicFailureInd; + +typedef struct sSirSmeMissedBeaconInd +{ + tANI_U16 messageType; // eWNI_SME_MISSED_BEACON_IND + tANI_U16 length; + tANI_U8 bssIdx; +} tSirSmeMissedBeaconInd, *tpSirSmeMissedBeaconInd; + +/// Definition for Set Context request +/// ---> MAC +typedef struct sSirSmeSetContextReq +{ + tANI_U16 messageType; // eWNI_SME_SET_CONTEXT_REQ + tANI_U16 length; + tANI_U8 sessionId; //Session ID + tANI_U16 transactionId; //Transaction ID for cmd + tSirMacAddr peerMacAddr; + tSirMacAddr bssId; // BSSID + tSirKeyMaterial keyMaterial; +} tSirSmeSetContextReq, *tpSirSmeSetContextReq; + +/// Definition for Set Context response +/// MAC ---> +typedef struct sSirSmeSetContextRsp +{ + tANI_U16 messageType; // eWNI_SME_SET_CONTEXT_RSP + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirSmeSetContextRsp, *tpSirSmeSetContextRsp; + +/// Definition for Remove Key Context request +/// ---> MAC +typedef struct sSirSmeRemoveKeyReq +{ + tANI_U16 messageType; // eWNI_SME_REMOVE_KEY_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssId; // BSSID + tSirMacAddr peerMacAddr; + tANI_U8 edType; + tANI_U8 wepType; + tANI_U8 keyId; + tANI_BOOLEAN unicast; +} tSirSmeRemoveKeyReq, *tpSirSmeRemoveKeyReq; + +/// Definition for Remove Key Context response +/// MAC ---> +typedef struct sSirSmeRemoveKeyRsp +{ + tANI_U16 messageType; // eWNI_SME_REMOVE_KEY_RSP + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirSmeRemoveKeyRsp, *tpSirSmeRemoveKeyRsp; + +/// Definition for Set Power request +/// ---> MAC +typedef struct sSirSmeSetPowerReq +{ + tANI_U16 messageType; // eWNI_SME_SET_POWER_REQ + tANI_U16 length; + tANI_U16 transactionId; // Transaction ID for cmd + tANI_S8 powerLevel; +} tSirSmeSetPowerReq, *tpSirSmeSetPowerReq; + +/// Definition for Set Power response +/// MAC ---> +typedef struct sSirSmeSetPowerRsp +{ + tANI_U16 messageType; // eWNI_SME_SET_POWER_RSP + tANI_U16 length; + tSirResultCodes statusCode; + tANI_U16 transactionId; // Transaction ID for cmd +} tSirSmeSetPowerRsp, *tpSirSmeSetPowerRsp; + + +/// Definition for Link Test Start response +/// MAC ---> +typedef struct sSirSmeLinkTestStartRsp +{ + tANI_U16 messageType; // eWNI_SME_LINK_TEST_START_RSP + tANI_U16 length; + tSirMacAddr peerMacAddr; + tSirResultCodes statusCode; +} tSirSmeLinkTestStartRsp, *tpSirSmeLinkTestStartRsp; + +/// Definition for Link Test Stop response +/// WSM ---> MAC +typedef struct sSirSmeLinkTestStopRsp +{ + tANI_U16 messageType; // eWNI_SME_LINK_TEST_STOP_RSP + tANI_U16 length; + tSirMacAddr peerMacAddr; + tSirResultCodes statusCode; +} tSirSmeLinkTestStopRsp, *tpSirSmeLinkTestStopRsp; + +/// Definition for kick starting DFS measurements +typedef struct sSirSmeDFSreq +{ + tANI_U16 messageType; // eWNI_SME_DFS_REQ + tANI_U16 length; + tANI_U16 transactionId; // Transaction ID for cmd +} tSirSmeDFSrequest, *tpSirSmeDFSrequest; + +/// Definition for response message to previously +/// issued DFS request +typedef struct sSirSmeDFSrsp +{ + tANI_U16 messageType; // eWNI_SME_DFS_RSP + tANI_U16 length; + tSirResultCodes statusCode; + tANI_U16 transactionId; // Transaction ID for cmd + tANI_U32 dfsReport[1]; +} tSirSmeDFSrsp, *tpSirSmeDFSrsp; + +/// Statistic definitions +//============================================================= +// Per STA statistic structure; This same struct will be used for Aggregate +// STA stats as well. + +// Clear radio stats and clear per sta stats +typedef enum +{ + eANI_CLEAR_ALL_STATS, // Clears all stats + eANI_CLEAR_RX_STATS, // Clears RX statistics of the radio interface + eANI_CLEAR_TX_STATS, // Clears TX statistics of the radio interface + eANI_CLEAR_RADIO_STATS, // Clears all the radio stats + eANI_CLEAR_PER_STA_STATS, // Clears Per STA stats + eANI_CLEAR_AGGR_PER_STA_STATS, // Clears aggregate stats + + // Used to distinguish between per sta to security stats. + // Used only by AP, FW just returns the same parameter as it received. + eANI_LINK_STATS, // Get Per STA stats + eANI_SECURITY_STATS, // Get Per STA security stats + + eANI_CLEAR_STAT_TYPES_END +} tAniStatSubTypes; + +typedef struct sAniTxCtrs +{ + // add the rate counters here + tANI_U32 tx1Mbps; + tANI_U32 tx2Mbps; + tANI_U32 tx5_5Mbps; + tANI_U32 tx6Mbps; + tANI_U32 tx9Mbps; + tANI_U32 tx11Mbps; + tANI_U32 tx12Mbps; + tANI_U32 tx18Mbps; + tANI_U32 tx24Mbps; + tANI_U32 tx36Mbps; + tANI_U32 tx48Mbps; + tANI_U32 tx54Mbps; + tANI_U32 tx72Mbps; + tANI_U32 tx96Mbps; + tANI_U32 tx108Mbps; + + // tx path radio counts + tANI_U32 txFragHi; + tANI_U32 txFragLo; + tANI_U32 txFrameHi; + tANI_U32 txFrameLo; + tANI_U32 txMulticastFrameHi; + tANI_U32 txMulticastFrameLo; + tANI_U32 txFailedHi; + tANI_U32 txFailedLo; + tANI_U32 multipleRetryHi; + tANI_U32 multipleRetryLo; + tANI_U32 singleRetryHi; + tANI_U32 singleRetryLo; + tANI_U32 ackFailureHi; + tANI_U32 ackFailureLo; + tANI_U32 xmitBeacons; +} tAniTxCtrs, *tpAniTxCtrs; + +typedef struct sAniRxCtrs +{ + // receive frame rate counters + tANI_U32 rx1Mbps; + tANI_U32 rx2Mbps; + tANI_U32 rx5_5Mbps; + tANI_U32 rx6Mbps; + tANI_U32 rx9Mbps; + tANI_U32 rx11Mbps; + tANI_U32 rx12Mbps; + tANI_U32 rx18Mbps; + tANI_U32 rx24Mbps; + tANI_U32 rx36Mbps; + tANI_U32 rx48Mbps; + tANI_U32 rx54Mbps; + tANI_U32 rx72Mbps; + tANI_U32 rx96Mbps; + tANI_U32 rx108Mbps; + + // receive size counters; 'Lte' = Less than or equal to + tANI_U32 rxLte64; + tANI_U32 rxLte128Gt64; + tANI_U32 rxLte256Gt128; + tANI_U32 rxLte512Gt256; + tANI_U32 rxLte1kGt512; + tANI_U32 rxLte1518Gt1k; + tANI_U32 rxLte2kGt1518; + tANI_U32 rxLte4kGt2k; + + // rx radio stats + tANI_U32 rxFrag; + tANI_U32 rxFrame; + tANI_U32 fcsError; + tANI_U32 rxMulticast; + tANI_U32 duplicate; + tANI_U32 rtsSuccess; + tANI_U32 rtsFailed; + tANI_U32 wepUndecryptables; + tANI_U32 drops; + tANI_U32 aesFormatErrorUcastCnts; + tANI_U32 aesReplaysUcast; + tANI_U32 aesDecryptErrUcast; +} tAniRxCtrs, *tpAniRxCtrs; + +// Radio stats +typedef struct sAniRadioStats +{ + tAniTxCtrs tx; + tAniRxCtrs rx; +} tAniRadioStats, *tpAniRadioStats; + +// Get Radio Stats request structure +// This structure shall be used for both Radio stats and Aggregate stats +// A valid request must contain entire structure with/without valid fields. +// Based on the request type, the valid fields will be checked. +typedef struct sAniGetStatsReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 sessionId; //Session ID + tANI_U16 transactionId; + tSirMacAddr bssId; //BSSID + // only used for clear stats and per sta stats clear + tAniStatSubTypes stat; // Clears the stats of the described types. + tANI_U32 staId; // Per STA stats request must contain valid + // values + tANI_U8 macAddr[6]; +} tAniGetStatsReq, *tpAniGetStatsReq; + +// Get Radio Stats response struct +typedef struct sAniGetRadioStatsRsp +{ + tANI_U16 type; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U32 rc; + tANI_U16 transactionId; + tAniRadioStats radio; +} tAniGetRadioStatsRsp, *tpAniGetRadioStatsRsp; + +// Per Sta stats response struct +typedef struct sAniGetPerStaStatsRsp +{ + tANI_U16 type; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U32 rc; + tANI_U16 transactionId; + tAniStatSubTypes stat; // Sub type needed by AP. Returns the same value + tAniStaStatStruct sta; + tANI_U32 staId; + tANI_U8 macAddr[6]; +} tAniGetPerStaStatsRsp, *tpAniGetPerStaStatsRsp; + +// Get Aggregate stats +typedef struct sAniGetAggrStaStatsRsp +{ + tANI_U16 type; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U32 rc; + tANI_U16 transactionId; + tAniStaStatStruct sta; +} tAniGetAggrStaStatsRsp, *tpAniGetAggrStaStatsRsp; + +// Clear stats request and response structure. 'rc' field is unused in +// request and this field is used in response field. +typedef struct sAniClearStatsRsp +{ + tANI_U16 type; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U32 rc; // return code - will be filled by FW on + // response. + // Same transaction ID will be returned by the FW + tANI_U16 transactionId; + tAniStatSubTypes stat; // Clears the stats of the described types. + tANI_U32 staId; // Applicable only to PER STA stats clearing + tANI_U8 macAddr[6]; // Applicable only to PER STA stats clearing +} tAniClearStatsRsp, *tpAniClearStatsRsp; + +typedef struct sAniGetGlobalStatsRsp +{ + tANI_U16 type; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U32 rc; + tANI_U16 transactionId; + tAniGlobalStatStruct global; +} tAniGetGlobalStatsRsp, *tpAniGetGlobalStatsRsp; + +typedef struct sAniGetStatSummaryRsp +{ + tANI_U16 type; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request --Why? + tANI_U32 rc; + tANI_U16 transactionId; + tAniStatSummaryStruct stat; +} tAniGetStatSummaryRsp, *tpAniGetStatSummaryRsp; + +//*************************************************************** + + +/*******************PE Statistics*************************/ +typedef enum +{ + PE_SUMMARY_STATS_INFO = 0x00000001, + PE_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, + PE_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, + PE_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, + PE_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, + PE_PER_STA_STATS_INFO = 0x00000020 +}ePEStatsMask; + +/* + * tpAniGetPEStatsReq is tied to + * for SME ==> PE eWNI_SME_GET_STATISTICS_REQ msgId and + * for PE ==> HAL SIR_HAL_GET_STATISTICS_REQ msgId + */ +typedef struct sAniGetPEStatsReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U32 staId; // Per STA stats request must contain valid + tANI_U32 statsMask; // categories of stats requested. look at ePEStatsMask + tANI_U8 sessionId; +} tAniGetPEStatsReq, *tpAniGetPEStatsReq; + +/* + * tpAniGetPEStatsRsp is tied to + * for PE ==> SME eWNI_SME_GET_STATISTICS_RSP msgId and + * for HAL ==> PE SIR_HAL_GET_STATISTICS_RSP msgId + */ +typedef struct sAniGetPEStatsRsp +{ + // Common for all types are responses + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request, includes the pStatsBuf length too + tANI_U8 sessionId; + tANI_U32 rc; //success/failure + tANI_U32 staId; // Per STA stats request must contain valid + tANI_U32 statsMask; // categories of stats requested. look at ePEStatsMask +/********************************************************************************************** + //void *pStatsBuf; + The Stats buffer starts here and can be an aggregate of more than one statistics + structure depending on statsMask.The void pointer "pStatsBuf" is commented out + intentionally and the src code that uses this structure should take that into account. +**********************************************************************************************/ +} tAniGetPEStatsRsp, *tpAniGetPEStatsRsp; + +typedef struct sAniGetRssiReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 sessionId; + tANI_U8 staId; + tANI_S8 lastRSSI; // in case of error, return last RSSI + void *rssiCallback; + void *pDevContext; //device context + void *pVosContext; //voss context + +} tAniGetRssiReq, *tpAniGetRssiReq; + +typedef struct sAniGetSnrReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 sessionId; + tANI_U8 staId; + void *snrCallback; + void *pDevContext; //device context + tANI_S8 snr; +} tAniGetSnrReq, *tpAniGetSnrReq; + +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) +typedef struct sSirTsmIE +{ + tANI_U8 tsid; + tANI_U8 state; + tANI_U16 msmt_interval; +} tSirTsmIE, *tpSirTsmIE; +typedef struct sSirSmeTsmIEInd +{ + tSirTsmIE tsmIe; + tANI_U8 sessionId; +} tSirSmeTsmIEInd, *tpSirSmeTsmIEInd; +typedef struct sAniTrafStrmMetrics +{ + tANI_U16 UplinkPktQueueDly; + tANI_U16 UplinkPktQueueDlyHist[4]; + tANI_U32 UplinkPktTxDly; + tANI_U16 UplinkPktLoss; + tANI_U16 UplinkPktCount; + tANI_U8 RoamingCount; + tANI_U16 RoamingDly; +} tAniTrafStrmMetrics, *tpAniTrafStrmMetrics; +typedef struct sAniGetTsmStatsReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 staId; + tANI_U8 tid; // traffic id + tSirMacAddr bssId; + void *tsmStatsCallback; + void *pDevContext; //device context + void *pVosContext; //voss context +} tAniGetTsmStatsReq, *tpAniGetTsmStatsReq; +typedef struct sAniGetTsmStatsRsp +{ + // Common for all types are responses + tANI_U16 msgType; /* + * message type is same as + * the request type + */ + tANI_U16 msgLen; /* + * length of the entire request, + * includes the pStatsBuf length too + */ + tANI_U8 sessionId; + tANI_U32 rc; /* success/failure */ + tANI_U32 staId; /* + * Per STA stats request must + * contain valid + */ + tAniTrafStrmMetrics tsmMetrics; + void *tsmStatsReq; /* tsm stats request backup */ +} tAniGetTsmStatsRsp, *tpAniGetTsmStatsRsp; + +typedef struct sSirEseBcnReportBssInfo +{ + tBcnReportFields bcnReportFields; + tANI_U8 ieLen; + tANI_U8 *pBuf; +} tSirEseBcnReportBssInfo, *tpSirEseBcnReportBssInfo; + +typedef struct sSirEseBcnReportRsp +{ + tANI_U16 measurementToken; + tANI_U8 flag; /* Flag to report measurement done and more data */ + tANI_U8 numBss; + tSirEseBcnReportBssInfo bcnRepBssInfo[SIR_BCN_REPORT_MAX_BSS_DESC]; +} tSirEseBcnReportRsp, *tpSirEseBcnReportRsp; + +#endif /* FEATURE_WLAN_ESE || FEATURE_WLAN_ESE_UPLOAD */ + +/* Change country code request MSG structure */ +typedef struct sAniChangeCountryCodeReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN]; //3 char country code + tAniBool countryFromUserSpace; + tAniBool sendRegHint; //TRUE if we want to send hint to NL80211 + void *changeCCCallback; + void *pDevContext; //device context + void *pVosContext; //voss context + +} tAniChangeCountryCodeReq, *tpAniChangeCountryCodeReq; + +/* generic country code change request MSG structure */ +typedef struct sAniGenericChangeCountryCodeReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN]; //3 char country code + tANI_U16 domain_index; +} tAniGenericChangeCountryCodeReq, *tpAniGenericChangeCountryCodeReq; + +typedef struct sAniDHCPStopInd +{ + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 device_mode; // Mode of the device(ex:STA, AP) + tSirMacAddr adapterMacAddr; // MAC address of the adapter + tSirMacAddr peerMacAddr; // MAC address of the connected peer + +} tAniDHCPInd, *tpAniDHCPInd; + +typedef struct sAniSummaryStatsInfo +{ + tANI_U32 retry_cnt[4]; //Total number of packets(per AC) that were successfully transmitted with retries + tANI_U32 multiple_retry_cnt[4];//The number of MSDU packets and MMPDU frames per AC that the 802.11 + // station successfully transmitted after more than one retransmission attempt + + tANI_U32 tx_frm_cnt[4]; //Total number of packets(per AC) that were successfully transmitted + //(with and without retries, including multi-cast, broadcast) + //tANI_U32 tx_fail_cnt; + //tANI_U32 num_rx_frm_crc_err; //Total number of received frames with CRC Error + //tANI_U32 num_rx_frm_crc_ok; //Total number of successfully received frames with out CRC Error + tANI_U32 rx_frm_cnt; //Total number of packets that were successfully received + //(after appropriate filter rules including multi-cast, broadcast) + tANI_U32 frm_dup_cnt; //Total number of duplicate frames received successfully + tANI_U32 fail_cnt[4]; //Total number packets(per AC) failed to transmit + tANI_U32 rts_fail_cnt; //Total number of RTS/CTS sequence failures for transmission of a packet + tANI_U32 ack_fail_cnt; //Total number packets failed transmit because of no ACK from the remote entity + tANI_U32 rts_succ_cnt; //Total number of RTS/CTS sequence success for transmission of a packet + tANI_U32 rx_discard_cnt; //The sum of the receive error count and dropped-receive-buffer error count. + //HAL will provide this as a sum of (FCS error) + (Fail get BD/PDU in HW) + tANI_U32 rx_error_cnt; //The receive error count. HAL will provide the RxP FCS error global counter. + tANI_U32 tx_byte_cnt; //The sum of the transmit-directed byte count, transmit-multicast byte count + //and transmit-broadcast byte count. HAL will sum TPE UC/MC/BCAST global counters + //to provide this. +}tAniSummaryStatsInfo, *tpAniSummaryStatsInfo; + +typedef enum eTxRateInfo +{ + eHAL_TX_RATE_LEGACY = 0x1, /* Legacy rates */ + eHAL_TX_RATE_HT20 = 0x2, /* HT20 rates */ + eHAL_TX_RATE_HT40 = 0x4, /* HT40 rates */ + eHAL_TX_RATE_SGI = 0x8, /* Rate with Short guard interval */ + eHAL_TX_RATE_LGI = 0x10, /* Rate with Long guard interval */ + eHAL_TX_RATE_VHT20 = 0x20, /* VHT 20 rates */ + eHAL_TX_RATE_VHT40 = 0x40, /* VHT 40 rates */ + eHAL_TX_RATE_VHT80 = 0x80 /* VHT 80 rates */ +} tTxrateinfoflags; + +typedef struct sAniGlobalClassAStatsInfo +{ + tANI_U32 rx_frag_cnt; //The number of MPDU frames received by the 802.11 station for MSDU packets + //or MMPDU frames + tANI_U32 promiscuous_rx_frag_cnt; //The number of MPDU frames received by the 802.11 station for MSDU packets + //or MMPDU frames when a promiscuous packet filter was enabled + tANI_U32 rx_input_sensitivity; //The receiver input sensitivity referenced to a FER of 8% at an MPDU length + //of 1024 bytes at the antenna connector. Each element of the array shall correspond + //to a supported rate and the order shall be the same as the supporteRates parameter. + + /* The maximum transmit power in dBm up-to one decimal + for eg: if it is 10.5dBm, the value would be 105 */ + tANI_U32 max_pwr; + + tANI_U32 sync_fail_cnt; //Number of times the receiver failed to synchronize with the incoming signal + //after detecting the sync in the preamble of the transmitted PLCP protocol data unit. + tANI_U32 tx_rate; //Legacy transmit rate, in units of + //500 kbit/sec, for the most + //recently transmitted frame + tANI_U32 mcs_index; //mcs index for HT20 and HT40 rates + tANI_U32 tx_rate_flags; //to differentiate between HT20 and + //HT40 rates; short and long guard interval + +}tAniGlobalClassAStatsInfo, *tpAniGlobalClassAStatsInfo; + + +typedef struct sAniGlobalSecurityStats +{ + tANI_U32 rx_wep_unencrypted_frm_cnt; //The number of unencrypted received MPDU frames that the MAC layer discarded when + //the IEEE 802.11 dot11ExcludeUnencrypted management information base (MIB) object + //is enabled + tANI_U32 rx_mic_fail_cnt; //The number of received MSDU packets that that the 802.11 station discarded + //because of MIC failures + tANI_U32 tkip_icv_err; //The number of encrypted MPDU frames that the 802.11 station failed to decrypt + //because of a TKIP ICV error + tANI_U32 aes_ccmp_format_err; //The number of received MPDU frames that the 802.11 discarded because of an + //invalid AES-CCMP format + tANI_U32 aes_ccmp_replay_cnt; //The number of received MPDU frames that the 802.11 station discarded because of + //the AES-CCMP replay protection procedure + tANI_U32 aes_ccmp_decrpt_err; //The number of received MPDU frames that the 802.11 station discarded because of + //errors detected by the AES-CCMP decryption algorithm + tANI_U32 wep_undecryptable_cnt; //The number of encrypted MPDU frames received for which a WEP decryption key was + //not available on the 802.11 station + tANI_U32 wep_icv_err; //The number of encrypted MPDU frames that the 802.11 station failed to decrypt + //because of a WEP ICV error + tANI_U32 rx_decrypt_succ_cnt; //The number of received encrypted packets that the 802.11 station successfully + //decrypted + tANI_U32 rx_decrypt_fail_cnt; //The number of encrypted packets that the 802.11 station failed to decrypt + +}tAniGlobalSecurityStats, *tpAniGlobalSecurityStats; + +typedef struct sAniGlobalClassBStatsInfo +{ + tAniGlobalSecurityStats ucStats; + tAniGlobalSecurityStats mcbcStats; +}tAniGlobalClassBStatsInfo, *tpAniGlobalClassBStatsInfo; + +typedef struct sAniGlobalClassCStatsInfo +{ + tANI_U32 rx_amsdu_cnt; //This counter shall be incremented for a received A-MSDU frame with the stations + //MAC address in the address 1 field or an A-MSDU frame with a group address in the + //address 1 field + tANI_U32 rx_ampdu_cnt; //This counter shall be incremented when the MAC receives an AMPDU from the PHY + tANI_U32 tx_20_frm_cnt; //This counter shall be incremented when a Frame is transmitted only on the + //primary channel + tANI_U32 rx_20_frm_cnt; //This counter shall be incremented when a Frame is received only on the primary channel + tANI_U32 rx_mpdu_in_ampdu_cnt; //This counter shall be incremented by the number of MPDUs received in the A-MPDU + //when an A-MPDU is received + tANI_U32 ampdu_delimiter_crc_err;//This counter shall be incremented when an MPDU delimiter has a CRC error when this + //is the first CRC error in the received AMPDU or when the previous delimiter has been + //decoded correctly + +}tAniGlobalClassCStatsInfo, *tpAniGlobalClassCStatsInfo; + +typedef struct sAniPerStaStatsInfo +{ + tANI_U32 tx_frag_cnt[4]; //The number of MPDU frames that the 802.11 station transmitted and acknowledged + //through a received 802.11 ACK frame + tANI_U32 tx_ampdu_cnt; //This counter shall be incremented when an A-MPDU is transmitted + tANI_U32 tx_mpdu_in_ampdu_cnt; //This counter shall increment by the number of MPDUs in the AMPDU when an A-MPDU + //is transmitted + +}tAniPerStaStatsInfo, *tpAniPerStaStatsInfo; + +/**********************PE Statistics end*************************/ + + + +typedef struct sSirRSSIThresholds +{ +#ifdef ANI_BIG_BYTE_ENDIAN + tANI_S8 ucRssiThreshold1 : 8; + tANI_S8 ucRssiThreshold2 : 8; + tANI_S8 ucRssiThreshold3 : 8; + tANI_U8 bRssiThres1PosNotify : 1; + tANI_U8 bRssiThres1NegNotify : 1; + tANI_U8 bRssiThres2PosNotify : 1; + tANI_U8 bRssiThres2NegNotify : 1; + tANI_U8 bRssiThres3PosNotify : 1; + tANI_U8 bRssiThres3NegNotify : 1; + tANI_U8 bReserved10 : 2; +#else + tANI_U8 bReserved10 : 2; + tANI_U8 bRssiThres3NegNotify : 1; + tANI_U8 bRssiThres3PosNotify : 1; + tANI_U8 bRssiThres2NegNotify : 1; + tANI_U8 bRssiThres2PosNotify : 1; + tANI_U8 bRssiThres1NegNotify : 1; + tANI_U8 bRssiThres1PosNotify : 1; + tANI_S8 ucRssiThreshold3 : 8; + tANI_S8 ucRssiThreshold2 : 8; + tANI_S8 ucRssiThreshold1 : 8; +#endif + +}tSirRSSIThresholds, *tpSirRSSIThresholds; + +typedef struct sSirRSSINotification +{ +#ifdef ANI_BIG_BYTE_ENDIAN + tANI_U32 bRssiThres1PosCross : 1; + tANI_U32 bRssiThres1NegCross : 1; + tANI_U32 bRssiThres2PosCross : 1; + tANI_U32 bRssiThres2NegCross : 1; + tANI_U32 bRssiThres3PosCross : 1; + tANI_U32 bRssiThres3NegCross : 1; + v_S7_t avgRssi : 8; + tANI_U32 bReserved : 18; +#else + tANI_U32 bReserved : 18; + v_S7_t avgRssi : 8; + tANI_U32 bRssiThres3NegCross : 1; + tANI_U32 bRssiThres3PosCross : 1; + tANI_U32 bRssiThres2NegCross : 1; + tANI_U32 bRssiThres2PosCross : 1; + tANI_U32 bRssiThres1NegCross : 1; + tANI_U32 bRssiThres1PosCross : 1; +#endif + +}tSirRSSINotification, *tpSirRSSINotification; + + +typedef struct sSirP2PNoaStart +{ + tANI_U32 status; + tANI_U32 bssIdx; +} tSirP2PNoaStart, *tpSirP2PNoaStart; + +typedef struct sSirTdlsInd +{ + tANI_U16 status; + tANI_U16 assocId; + tANI_U16 staIdx; + tANI_U16 reasonCode; +} tSirTdlsInd, *tpSirTdlsInd; + +typedef struct sSirP2PNoaAttr +{ +#ifdef ANI_BIG_BYTE_ENDIAN + tANI_U32 index :8; + tANI_U32 oppPsFlag :1; + tANI_U32 ctWin :7; + tANI_U32 rsvd1: 16; +#else + tANI_U32 rsvd1: 16; + tANI_U32 ctWin :7; + tANI_U32 oppPsFlag :1; + tANI_U32 index :8; +#endif + +#ifdef ANI_BIG_BYTE_ENDIAN + tANI_U32 uNoa1IntervalCnt:8; + tANI_U32 rsvd2:24; +#else + tANI_U32 rsvd2:24; + tANI_U32 uNoa1IntervalCnt:8; +#endif + tANI_U32 uNoa1Duration; + tANI_U32 uNoa1Interval; + tANI_U32 uNoa1StartTime; + +#ifdef ANI_BIG_BYTE_ENDIAN + tANI_U32 uNoa2IntervalCnt:8; + tANI_U32 rsvd3:24; +#else + tANI_U32 rsvd3:24; + tANI_U32 uNoa2IntervalCnt:8; +#endif + tANI_U32 uNoa2Duration; + tANI_U32 uNoa2Interval; + tANI_U32 uNoa2StartTime; +} tSirP2PNoaAttr, *tpSirP2PNoaAttr; + +typedef __ani_attr_pre_packed struct sSirTclasInfo +{ + tSirMacTclasIE tclas; + tANI_U8 version; // applies only for classifier type ip + __ani_attr_pre_packed union { + tSirMacTclasParamEthernet eth; + tSirMacTclasParamIPv4 ipv4; + tSirMacTclasParamIPv6 ipv6; + tSirMacTclasParam8021dq t8021dq; + }__ani_attr_packed tclasParams; +} __ani_attr_packed tSirTclasInfo; + +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) +#define TSRS_11AG_RATE_6MBPS 0xC +#define TSRS_11B_RATE_5_5MBPS 0xB +typedef struct sSirMacESETSRSIE +{ + tANI_U8 tsid; + tANI_U8 rates[8]; +} tSirMacESETSRSIE; +typedef struct sSirMacESETSMIE +{ + tANI_U8 tsid; + tANI_U8 state; + tANI_U16 msmt_interval; +} tSirMacESETSMIE; +typedef struct sTSMStats +{ + tANI_U8 tid; + tSirMacAddr bssId; + tTrafStrmMetrics tsmMetrics; +} tTSMStats, *tpTSMStats; +typedef struct sEseTSMContext +{ + tANI_U8 tid; + tSirMacESETSMIE tsmInfo; + tTrafStrmMetrics tsmMetrics; +} tEseTSMContext, *tpEseTSMContext; +typedef struct sEsePEContext +{ +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + tEseMeasReq curMeasReq; +#endif + tEseTSMContext tsm; +} tEsePEContext, *tpEsePEContext; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +typedef struct sSirAddtsReqInfo +{ + tANI_U8 dialogToken; + tSirMacTspecIE tspec; + + tANI_U8 numTclas; // number of Tclas elements + tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM]; + tANI_U8 tclasProc; +#if defined(FEATURE_WLAN_ESE) + tSirMacESETSRSIE tsrsIE; + tANI_U8 tsrsPresent:1; +#endif + tANI_U8 wmeTspecPresent:1; + tANI_U8 wsmTspecPresent:1; + tANI_U8 lleTspecPresent:1; + tANI_U8 tclasProcPresent:1; +} tSirAddtsReqInfo, *tpSirAddtsReqInfo; + +typedef struct sSirAddtsRspInfo +{ + tANI_U8 dialogToken; + tSirMacStatusCodes status; + tSirMacTsDelayIE delay; + + tSirMacTspecIE tspec; + tANI_U8 numTclas; // number of Tclas elements + tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM]; + tANI_U8 tclasProc; + tSirMacScheduleIE schedule; +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) + tSirMacESETSMIE tsmIE; + tANI_U8 tsmPresent:1; +#endif + tANI_U8 wmeTspecPresent:1; + tANI_U8 wsmTspecPresent:1; + tANI_U8 lleTspecPresent:1; + tANI_U8 tclasProcPresent:1; + tANI_U8 schedulePresent:1; +} tSirAddtsRspInfo, *tpSirAddtsRspInfo; + +typedef struct sSirDeltsReqInfo +{ + tSirMacTSInfo tsinfo; + tSirMacTspecIE tspec; + tANI_U8 wmeTspecPresent:1; + tANI_U8 wsmTspecPresent:1; + tANI_U8 lleTspecPresent:1; +} tSirDeltsReqInfo, *tpSirDeltsReqInfo; + +/// Add a tspec as defined +typedef struct sSirAddtsReq +{ + tANI_U16 messageType; // eWNI_SME_ADDTS_REQ + tANI_U16 length; + tANI_U8 sessionId; //Session ID + tANI_U16 transactionId; + tSirMacAddr bssId; //BSSID + tANI_U32 timeout; // in ms + tANI_U8 rspReqd; + tSirAddtsReqInfo req; +} tSirAddtsReq, *tpSirAddtsReq; + +typedef struct sSirAddtsRsp +{ + tANI_U16 messageType; // eWNI_SME_ADDTS_RSP + tANI_U16 length; + tANI_U8 sessionId; // sme sessionId Added for BT-AMP support + tANI_U16 transactionId; //sme transaction Id Added for BT-AMP Support + tANI_U32 rc; // return code + tSirAddtsRspInfo rsp; +} tSirAddtsRsp, *tpSirAddtsRsp; + +typedef struct sSirDeltsReq +{ + tANI_U16 messageType; // eWNI_SME_DELTS_REQ + tANI_U16 length; + tANI_U8 sessionId;//Session ID + tANI_U16 transactionId; + tSirMacAddr bssId; //BSSID + tANI_U16 aid; // use 0 if macAddr is being specified + tANI_U8 macAddr[6]; // only on AP to specify the STA + tANI_U8 rspReqd; + tSirDeltsReqInfo req; +} tSirDeltsReq, *tpSirDeltsReq; + +typedef struct sSirDeltsRsp +{ + tANI_U16 messageType; // eWNI_SME_DELTS_RSP + tANI_U16 length; + tANI_U8 sessionId; // sme sessionId Added for BT-AMP support + tANI_U16 transactionId; //sme transaction Id Added for BT-AMP Support + tANI_U32 rc; + tANI_U16 aid; // use 0 if macAddr is being specified + tANI_U8 macAddr[6]; // only on AP to specify the STA + tSirDeltsReqInfo rsp; +} tSirDeltsRsp, *tpSirDeltsRsp; + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +typedef struct sSirPlmReq +{ + tANI_U16 diag_token; // Dialog token + tANI_U16 meas_token; // measurement token + tANI_U16 numBursts; // total number of bursts + tANI_U16 burstInt; // burst interval in seconds + tANI_U16 measDuration; // in TU's,STA goes off-ch + /* no of times the STA should cycle through PLM ch list */ + tANI_U8 burstLen; + tPowerdBm desiredTxPwr; // desired tx power + tSirMacAddr macAddr; // MC dest addr + /* no of channels */ + tANI_U8 plmNumCh; + /* channel numbers */ + tANI_U8 plmChList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_U8 sessionId; + eAniBoolean enable; +} tSirPlmReq, *tpSirPlmReq; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + +#define SIR_QOS_NUM_AC_MAX 4 + +typedef struct sSirAggrQosReqInfo +{ + tANI_U16 tspecIdx; + tSirAddtsReqInfo aggrAddTsInfo[SIR_QOS_NUM_AC_MAX]; +}tSirAggrQosReqInfo, *tpSirAggrQosReqInfo; + +typedef struct sSirAggrQosReq +{ + tANI_U16 messageType; // eWNI_SME_ADDTS_REQ + tANI_U16 length; + tANI_U8 sessionId; //Session ID + tANI_U16 transactionId; + tSirMacAddr bssId; //BSSID + tANI_U32 timeout; // in ms + tANI_U8 rspReqd; + tSirAggrQosReqInfo aggrInfo; +}tSirAggrQosReq, *tpSirAggrQosReq; + +typedef struct sSirAggrQosRspInfo +{ + tANI_U16 tspecIdx; + tSirAddtsRspInfo aggrRsp[SIR_QOS_NUM_AC_MAX]; +} tSirAggrQosRspInfo, *tpSirAggrQosRspInfo; + +typedef struct sSirAggrQosRsp +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; + tSirAggrQosRspInfo aggrInfo; +} tSirAggrQosRsp, *tpSirAggrQosRsp; + +#endif/*WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE*/ + +typedef struct sSirSetTxPowerReq +{ + tANI_U16 messageType; + tANI_U16 length; + tSirMacAddr bssId; + tANI_U8 mwPower; + tANI_U8 bssIdx; +} tSirSetTxPowerReq, *tpSirSetTxPowerReq; + +typedef struct sSirSetTxPowerRsp +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U32 status; +} tSirSetTxPowerRsp, *tpSirSetTxPowerRsp; + +typedef struct sSirGetTxPowerReq +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U16 staid; +} tSirGetTxPowerReq, *tpSirGetTxPowerReq; + +typedef struct sSirGetTxPowerRsp +{ + tANI_U16 messageType; + tANI_U16 length; // length of the entire request + tANI_U32 power; // units of milliwatts + tANI_U32 status; +} tSirGetTxPowerRsp, *tpSirGetTxPowerRsp; + + +typedef tANI_U32 tSirMacNoise[3]; + +typedef struct sSirGetNoiseRsp +{ + tANI_U16 messageType; + tANI_U16 length; + tSirMacNoise noise; +} tSirGetNoiseRsp, *tpSirGetNoiseRsp; + +typedef struct sSirQosMapSet +{ + tANI_U8 present; + tANI_U8 num_dscp_exceptions; + tANI_U8 dscp_exceptions[21][2]; + tANI_U8 dscp_range[8][2]; +} tSirQosMapSet, *tpSirQosMapSet; + +// +// PMC --> PE --> HAL +// Power save configuration parameters +// +typedef struct sSirPowerSaveCfg +{ + tANI_U16 listenInterval; + + /* Number of consecutive missed beacons before + * hardware generates an interrupt to wake up + * the host. In units of listen interval. + */ + tANI_U32 HeartBeatCount; + + /* specifies which beacons are to be forwarded + * to host when beacon filtering is enabled. + * In units of listen interval. + */ + tANI_U32 nthBeaconFilter; + + /* Maximum number of PS-Poll send before + * firmware sends data null with PM set to 0. + */ + tANI_U32 maxPsPoll; + + /* If the average RSSI value falls below the + * minRssiThreshold, then FW will send an + * interrupt to wake up the host. + */ + tANI_U32 minRssiThreshold; + + /* Number of beacons for which firmware will + * collect the RSSI values and compute the average. + */ + tANI_U8 numBeaconPerRssiAverage; + + /* FW collects the RSSI stats for this period + * in BMPS mode. + */ + tANI_U8 rssiFilterPeriod; + + // Enabling/disabling broadcast frame filter feature + tANI_U8 broadcastFrameFilter; + + // Enabling/disabling the ignore DTIM feature + tANI_U8 ignoreDtim; + + /* The following configuration parameters are kept + * in order to be backward compatible for Gen5. + * These will NOT be used for Gen6 Libra chip + */ + tBeaconForwarding beaconFwd; + tANI_U16 nthBeaconFwd; + tANI_U8 fEnablePwrSaveImmediately; + tANI_U8 fPSPoll; + + // Enabling/disabling Beacon Early Termination feature + tANI_U8 fEnableBeaconEarlyTermination; + tANI_U8 bcnEarlyTermWakeInterval; + +}tSirPowerSaveCfg, *tpSirPowerSaveCfg; + +/* Reason code for requesting Full Power. This reason code is used by + any module requesting full power from PMC and also by PE when it + sends the eWNI_PMC_EXIT_BMPS_IND to PMC*/ +typedef enum eRequestFullPowerReason +{ + eSME_MISSED_BEACON_IND_RCVD, /* PE received a MAX_MISSED_BEACON_IND */ + eSME_BMPS_STATUS_IND_RCVD, /* PE received a SIR_HAL_BMPS_STATUS_IND */ + eSME_BMPS_MODE_DISABLED, /* BMPS mode was disabled by HDD in SME */ + eSME_LINK_DISCONNECTED_BY_HDD, /* Link has been disconnected requested by HDD */ + + /* Disconnect due to link lost or requested by peer */ + eSME_LINK_DISCONNECTED_BY_OTHER, + + eSME_FULL_PWR_NEEDED_BY_HDD, /* HDD request full power for some reason */ + eSME_FULL_PWR_NEEDED_BY_BAP, /* BAP request full power for BT_AMP */ + eSME_FULL_PWR_NEEDED_BY_CSR, /* CSR requests full power */ + eSME_FULL_PWR_NEEDED_BY_QOS, /* QOS requests full power */ + eSME_FULL_PWR_NEEDED_BY_CHANNEL_SWITCH, /* channel switch request full power*/ +#ifdef FEATURE_WLAN_TDLS + eSME_FULL_PWR_NEEDED_BY_TDLS_PEER_SETUP, /* TDLS peer setup*/ +#endif + eSME_REASON_OTHER /* No specific reason. General reason code */ +} tRequestFullPowerReason, tExitBmpsReason; + + + +/* This is sent along with eWNI_PMC_EXIT_BMPS_REQ message */ +typedef struct sExitBmpsInfo +{ + tExitBmpsReason exitBmpsReason; /*Reason for exiting BMPS */ +}tExitBmpsInfo, *tpExitBmpsInfo; + + +// MAC SW --> SME +// Message indicating to SME to exit BMPS sleep mode +typedef struct sSirSmeExitBmpsInd +{ + tANI_U16 mesgType; /* eWNI_PMC_EXIT_BMPS_IND */ + tANI_U16 mesgLen; + tSirResultCodes statusCode; + tExitBmpsReason exitBmpsReason; /*Reason for exiting BMPS */ + tANI_U32 smeSessionId; +} tSirSmeExitBmpsInd, *tpSirSmeExitBmpsInd; + +// MAC SW --> SME +// Message indicating to SME for channel switch +typedef struct sSirSmePreSwitchChannelInd +{ + tANI_U16 mesgType; /* eWNI_SME_PRE_SWITCH_CHL_IND */ + tANI_U16 mesgLen; + tANI_U8 sessionId; +} tSirSmePreSwitchChannelInd, *tpSirSmePreSwitchChannelInd; + + +// +// HDD -> LIM +// tSirMsgQ.type = eWNI_SME_DEL_BA_PEER_IND +// tSirMsgQ.reserved = 0 +// tSirMsgQ.body = instance of tDelBAParams +// +typedef struct sSmeDelBAPeerInd +{ + // Message Type + tANI_U16 mesgType; + + tSirMacAddr bssId;//BSSID + + // Message Length + tANI_U16 mesgLen; + + // Station Index + tANI_U16 staIdx; + + // TID for which the BA session is being deleted + tANI_U8 baTID; + + // DELBA direction + // eBA_INITIATOR - Originator + // eBA_RECEIPIENT - Recipient + tANI_U8 baDirection; +} tSmeDelBAPeerInd, *tpSmeDelBAPeerInd; + +typedef struct sSmeIbssPeerInd +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_U8 sessionId; + + tSirMacAddr peerAddr; + tANI_U16 staId; + + /*The DPU signatures will be sent eventually to TL to help it determine the + association to which a packet belongs to*/ + /*Unicast DPU signature*/ + tANI_U8 ucastSig; + + /*Broadcast DPU signature*/ + tANI_U8 bcastSig; + + //Beacon will be appended for new Peer indication. +}tSmeIbssPeerInd, *tpSmeIbssPeerInd; + +typedef struct sSirIbssPeerInactivityInd +{ + tANI_U8 bssIdx; + tANI_U8 staIdx; + tSirMacAddr peerAddr; +}tSirIbssPeerInactivityInd, *tpSirIbssPeerInactivityInd; + + +typedef struct sLimScanChn +{ + tANI_U16 numTimeScan; //how many time this channel is scan + tANI_U8 channelId; +}tLimScanChn; + +typedef struct sSmeGetScanChnRsp +{ + // Message Type + tANI_U16 mesgType; + // Message Length + tANI_U16 mesgLen; + tANI_U8 sessionId; + tANI_U8 numChn; + tLimScanChn scanChn[1]; +} tSmeGetScanChnRsp, *tpSmeGetScanChnRsp; + +typedef struct sLimScanChnInfo +{ + tANI_U8 numChnInfo; //number of channels in scanChn + tLimScanChn scanChn[SIR_MAX_SUPPORTED_CHANNEL_LIST]; +}tLimScanChnInfo; + +typedef struct sSirSmeGetAssocSTAsReq +{ + tANI_U16 messageType; // eWNI_SME_GET_ASSOC_STAS_REQ + tANI_U16 length; + tSirMacAddr bssId; // BSSID + tANI_U16 modId; + void *pUsrContext; + void *pSapEventCallback; + void *pAssocStasArray;// Pointer to allocated memory passed in WLANSAP_GetAssocStations API +} tSirSmeGetAssocSTAsReq, *tpSirSmeGetAssocSTAsReq; + +typedef struct sSmeMaxAssocInd +{ + tANI_U16 mesgType; // eWNI_SME_MAX_ASSOC_EXCEEDED + tANI_U16 mesgLen; + tANI_U8 sessionId; + tSirMacAddr peerMac; // the new peer that got rejected due to softap max assoc limit reached +} tSmeMaxAssocInd, *tpSmeMaxAssocInd; + +typedef struct sSmeCsaOffloadInd +{ + tANI_U16 mesgType; // eWNI_SME_CSA_OFFLOAD_EVENT + tANI_U16 mesgLen; + tSirMacAddr bssId; // BSSID +} tSmeCsaOffloadInd, *tpSmeCsaOffloadInd; + +/// WOW related structures +// SME -> PE <-> HAL +#define SIR_WOWL_BCAST_PATTERN_MAX_SIZE 146 +#define SIR_WOWL_BCAST_MAX_NUM_PATTERNS 19 +// SME -> PE -> HAL - This is to add WOWL BCAST wake-up pattern. +// SME/HDD maintains the list of the BCAST wake-up patterns. +// This is a pass through message for PE +typedef struct sSirWowlAddBcastPtrn +{ + tANI_U8 ucPatternId; // Pattern ID + // Pattern byte offset from beginning of the 802.11 packet to start of the + // wake-up pattern + tANI_U8 ucPatternByteOffset; + tANI_U8 ucPatternSize; // Non-Zero Pattern size + tANI_U8 ucPattern[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; // Pattern + tANI_U8 ucPatternMaskSize; // Non-zero pattern mask size + tANI_U8 ucPatternMask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; // Pattern mask + // Extra pattern data beyond 128 bytes + tANI_U8 ucPatternExt[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; // Extra Pattern + tANI_U8 ucPatternMaskExt[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; // Extra Pattern mask + tSirMacAddr bssId; // BSSID + tANI_U8 sessionId; +} tSirWowlAddBcastPtrn, *tpSirWowlAddBcastPtrn; + + +// SME -> PE -> HAL - This is to delete WOWL BCAST wake-up pattern. +// SME/HDD maintains the list of the BCAST wake-up patterns. +// This is a pass through message for PE +typedef struct sSirWowlDelBcastPtrn +{ + /* Pattern ID of the wakeup pattern to be deleted */ + tANI_U8 ucPatternId; + tSirMacAddr bssId; // BSSID +}tSirWowlDelBcastPtrn, *tpSirWowlDelBcastPtrn; + + +// SME->PE: Enter WOWLAN parameters +typedef struct sSirSmeWowlEnterParams +{ + tANI_U8 sessionId; + + /* Enables/disables magic packet filtering */ + tANI_U8 ucMagicPktEnable; + + /* Magic pattern */ + tSirMacAddr magicPtrn; + + /* Enables/disables packet pattern filtering */ + tANI_U8 ucPatternFilteringEnable; + +#ifdef WLAN_WAKEUP_EVENTS + /* This configuration directs the WoW packet filtering to look for EAP-ID + * requests embedded in EAPOL frames and use this as a wake source. + */ + tANI_U8 ucWoWEAPIDRequestEnable; + + /* This configuration directs the WoW packet filtering to look for EAPOL-4WAY + * requests and use this as a wake source. + */ + tANI_U8 ucWoWEAPOL4WayEnable; + + /* This configuration allows a host wakeup on an network scan offload match. + */ + tANI_U8 ucWowNetScanOffloadMatch; + + /* This configuration allows a host wakeup on any GTK re-keying error. + */ + tANI_U8 ucWowGTKRekeyError; + + /* This configuration allows a host wakeup on BSS connection loss. + */ + tANI_U8 ucWoWBSSConnLoss; +#endif // WLAN_WAKEUP_EVENTS + + tSirMacAddr bssId; +} tSirSmeWowlEnterParams, *tpSirSmeWowlEnterParams; + + +// PE<->HAL: Enter WOWLAN parameters +typedef struct sSirHalWowlEnterParams +{ + tANI_U8 sessionId; + + /* Enables/disables magic packet filtering */ + tANI_U8 ucMagicPktEnable; + + /* Magic pattern */ + tSirMacAddr magicPtrn; + + /* Enables/disables packet pattern filtering in firmware. + Enabling this flag enables broadcast pattern matching + in Firmware. If unicast pattern matching is also desired, + ucUcastPatternFilteringEnable flag must be set tot true + as well + */ + tANI_U8 ucPatternFilteringEnable; + + /* Enables/disables unicast packet pattern filtering. + This flag specifies whether we want to do pattern match + on unicast packets as well and not just broadcast packets. + This flag has no effect if the ucPatternFilteringEnable + (main controlling flag) is set to false + */ + tANI_U8 ucUcastPatternFilteringEnable; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it receives the + * Channel Switch Action Frame. + */ + tANI_U8 ucWowChnlSwitchRcv; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it receives the + * Deauthentication Frame. + */ + tANI_U8 ucWowDeauthRcv; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it receives the + * Disassociation Frame. + */ + tANI_U8 ucWowDisassocRcv; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it has missed + * consecutive beacons. This is a hardware register + * configuration (NOT a firmware configuration). + */ + tANI_U8 ucWowMaxMissedBeacons; + + /* This configuration is valid only when magicPktEnable=1. + * This is a timeout value in units of microsec. It requests + * hardware to unconditionally wake up after it has stayed + * in WoWLAN mode for some time. Set 0 to disable this feature. + */ + tANI_U8 ucWowMaxSleepUsec; + +#ifdef WLAN_WAKEUP_EVENTS + /* This configuration directs the WoW packet filtering to look for EAP-ID + * requests embedded in EAPOL frames and use this as a wake source. + */ + tANI_U8 ucWoWEAPIDRequestEnable; + + /* This configuration directs the WoW packet filtering to look for EAPOL-4WAY + * requests and use this as a wake source. + */ + tANI_U8 ucWoWEAPOL4WayEnable; + + /* This configuration allows a host wakeup on an network scan offload match. + */ + tANI_U8 ucWowNetScanOffloadMatch; + + /* This configuration allows a host wakeup on any GTK rekeying error. + */ + tANI_U8 ucWowGTKRekeyError; + + /* This configuration allows a host wakeup on BSS connection loss. + */ + tANI_U8 ucWoWBSSConnLoss; +#endif // WLAN_WAKEUP_EVENTS + + /* Status code to be filled by HAL when it sends + * SIR_HAL_WOWL_ENTER_RSP to PE. + */ + eHalStatus status; + + /*BSSID to find the current session + */ + tANI_U8 bssIdx; +} tSirHalWowlEnterParams, *tpSirHalWowlEnterParams; + +// SME->PE: Exit WOWLAN parameters +typedef struct sSirSmeWowlExitParams +{ + tANI_U8 sessionId; + +} tSirSmeWowlExitParams, *tpSirSmeWowlExitParams; + +// PE<->HAL: Exit WOWLAN parameters +typedef struct sSirHalWowlExitParams +{ + tANI_U8 sessionId; + + /* Status code to be filled by HAL when it sends + * SIR_HAL_WOWL_EXIT_RSP to PE. + */ + eHalStatus status; + + /*BSSIDX to find the current session + */ + tANI_U8 bssIdx; +} tSirHalWowlExitParams, *tpSirHalWowlExitParams; + + +#define SIR_MAX_NAME_SIZE 64 +#define SIR_MAX_TEXT_SIZE 32 + +typedef struct sSirName { + v_U8_t num_name; + v_U8_t name[SIR_MAX_NAME_SIZE]; +} tSirName; + +typedef struct sSirText { + v_U8_t num_text; + v_U8_t text[SIR_MAX_TEXT_SIZE]; +} tSirText; + + +#define SIR_WPS_PROBRSP_VER_PRESENT 0x00000001 +#define SIR_WPS_PROBRSP_STATE_PRESENT 0x00000002 +#define SIR_WPS_PROBRSP_APSETUPLOCK_PRESENT 0x00000004 +#define SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT 0x00000008 +#define SIR_WPS_PROBRSP_DEVICEPASSWORDID_PRESENT 0x00000010 +#define SIR_WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT 0x00000020 +#define SIR_WPS_PROBRSP_RESPONSETYPE_PRESENT 0x00000040 +#define SIR_WPS_PROBRSP_UUIDE_PRESENT 0x00000080 +#define SIR_WPS_PROBRSP_MANUFACTURE_PRESENT 0x00000100 +#define SIR_WPS_PROBRSP_MODELNAME_PRESENT 0x00000200 +#define SIR_WPS_PROBRSP_MODELNUMBER_PRESENT 0x00000400 +#define SIR_WPS_PROBRSP_SERIALNUMBER_PRESENT 0x00000800 +#define SIR_WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT 0x00001000 +#define SIR_WPS_PROBRSP_DEVICENAME_PRESENT 0x00002000 +#define SIR_WPS_PROBRSP_CONFIGMETHODS_PRESENT 0x00004000 +#define SIR_WPS_PROBRSP_RF_BANDS_PRESENT 0x00008000 + + +typedef struct sSirWPSProbeRspIE { + v_U32_t FieldPresent; + v_U32_t Version; // Version. 0x10 = version 1.0, 0x11 = etc. + v_U32_t wpsState; // 1 = unconfigured, 2 = configured. + v_BOOL_t APSetupLocked; // Must be included if value is TRUE + v_BOOL_t SelectedRegistra; //BOOL: indicates if the user has recently activated a Registrar to add an Enrollee. + v_U16_t DevicePasswordID; // Device Password ID + v_U16_t SelectedRegistraCfgMethod; // Selected Registrar config method + v_U8_t ResponseType; // Response type + v_U8_t UUID_E[16]; // Unique identifier of the AP. + tSirName Manufacture; + tSirText ModelName; + tSirText ModelNumber; + tSirText SerialNumber; + v_U32_t PrimaryDeviceCategory ; // Device Category ID: 1Computer, 2Input Device, ... + v_U8_t PrimaryDeviceOUI[4] ; // Vendor specific OUI for Device Sub Category + v_U32_t DeviceSubCategory ; // Device Sub Category ID: 1-PC, 2-Server if Device Category ID is computer + tSirText DeviceName; + v_U16_t ConfigMethod; /* Configuration method */ + v_U8_t RFBand; // RF bands available on the AP +} tSirWPSProbeRspIE; + +#define SIR_WPS_BEACON_VER_PRESENT 0x00000001 +#define SIR_WPS_BEACON_STATE_PRESENT 0x00000002 +#define SIR_WPS_BEACON_APSETUPLOCK_PRESENT 0x00000004 +#define SIR_WPS_BEACON_SELECTEDREGISTRA_PRESENT 0x00000008 +#define SIR_WPS_BEACON_DEVICEPASSWORDID_PRESENT 0x00000010 +#define SIR_WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT 0x00000020 +#define SIR_WPS_BEACON_UUIDE_PRESENT 0x00000080 +#define SIR_WPS_BEACON_RF_BANDS_PRESENT 0x00000100 +#define SIR_WPS_UUID_LEN 16 + +typedef struct sSirWPSBeaconIE { + v_U32_t FieldPresent; + v_U32_t Version; // Version. 0x10 = version 1.0, 0x11 = etc. + v_U32_t wpsState; // 1 = unconfigured, 2 = configured. + v_BOOL_t APSetupLocked; // Must be included if value is TRUE + v_BOOL_t SelectedRegistra; //BOOL: indicates if the user has recently activated a Registrar to add an Enrollee. + v_U16_t DevicePasswordID; // Device Password ID + v_U16_t SelectedRegistraCfgMethod; // Selected Registrar config method + v_U8_t UUID_E[SIR_WPS_UUID_LEN]; /* Unique identifier of the AP */ + v_U8_t RFBand; // RF bands available on the AP +} tSirWPSBeaconIE; + +#define SIR_WPS_ASSOCRSP_VER_PRESENT 0x00000001 +#define SIR_WPS_ASSOCRSP_RESPONSETYPE_PRESENT 0x00000002 + +typedef struct sSirWPSAssocRspIE { + v_U32_t FieldPresent; + v_U32_t Version; + v_U8_t ResposeType; +} tSirWPSAssocRspIE; + +typedef struct sSirAPWPSIEs { + tSirWPSProbeRspIE SirWPSProbeRspIE; /* WPS Set Probe Response IE */ + tSirWPSBeaconIE SirWPSBeaconIE; /*WPS Set Beacon IE*/ + tSirWPSAssocRspIE SirWPSAssocRspIE; /*WPS Set Assoc Response IE*/ +} tSirAPWPSIEs, *tpSiriAPWPSIEs; + +typedef struct sSirUpdateAPWPSIEsReq +{ + tANI_U16 messageType; // eWNI_SME_UPDATE_APWPSIE_REQ + tANI_U16 length; + tANI_U16 transactionId; //Transaction ID for cmd + tSirMacAddr bssId; // BSSID + tANI_U8 sessionId; //Session ID + tSirAPWPSIEs APWPSIEs; +} tSirUpdateAPWPSIEsReq, *tpSirUpdateAPWPSIEsReq; + +typedef struct sSirUpdateParams +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U8 ssidHidden; // Hide SSID +} tSirUpdateParams, *tpSirUpdateParams; + +//Beacon Interval +typedef struct sSirChangeBIParams +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U16 beaconInterval; // Beacon Interval + tSirMacAddr bssId; + tANI_U8 sessionId; // Session ID +} tSirChangeBIParams, *tpSirChangeBIParams; + +#ifdef QCA_HT_2040_COEX +typedef struct sSirSetHT2040Mode +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 cbMode; + tANI_BOOLEAN obssEnabled; + tSirMacAddr bssId; + tANI_U8 sessionId; // Session ID +} tSirSetHT2040Mode, *tpSirSetHT2040Mode; +#endif + +#define SIR_WPS_PBC_WALK_TIME 120 // 120 Second + +typedef struct sSirWPSPBCSession { + struct sSirWPSPBCSession *next; + tSirMacAddr addr; + tANI_U8 uuid_e[SIR_WPS_UUID_LEN]; + tANI_TIMESTAMP timestamp; +} tSirWPSPBCSession; + +typedef struct sSirSmeGetWPSPBCSessionsReq +{ + tANI_U16 messageType; // eWNI_SME_GET_WPSPBC_SESSION_REQ + tANI_U16 length; + void *pUsrContext; + void *pSapEventCallback; + tSirMacAddr bssId; // BSSID + tSirMacAddr pRemoveMac; // MAC Address of STA in WPS Session to be removed +} tSirSmeGetWPSPBCSessionsReq, *tpSirSmeGetWPSPBCSessionsReq; + +typedef struct sSirWPSPBCProbeReq +{ + tSirMacAddr peerMacAddr; + tANI_U16 probeReqIELen; + tANI_U8 probeReqIE[512]; +} tSirWPSPBCProbeReq, *tpSirWPSPBCProbeReq; + +// probereq from peer, when wsc is enabled +typedef struct sSirSmeProbeReqInd +{ + tANI_U16 messageType; // eWNI_SME_WPS_PBC_PROBE_REQ_IND + tANI_U16 length; + tANI_U8 sessionId; + tSirMacAddr bssId; + tSirWPSPBCProbeReq WPSPBCProbeReq; +} tSirSmeProbeReqInd, *tpSirSmeProbeReqInd; + +typedef struct sSirUpdateAPWPARSNIEsReq +{ + tANI_U16 messageType; // eWNI_SME_SET_APWPARSNIEs_REQ + tANI_U16 length; + tANI_U16 transactionId; //Transaction ID for cmd + tSirMacAddr bssId; // BSSID + tANI_U8 sessionId; //Session ID + tSirRSNie APWPARSNIEs; +} tSirUpdateAPWPARSNIEsReq, *tpSirUpdateAPWPARSNIEsReq; + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define SIR_ROAM_MAX_CHANNELS 80 +#define SIR_ROAM_SCAN_MAX_PB_REQ_SIZE 450 +#define CHANNEL_LIST_STATIC 1 /* Occupied channel list remains static */ +#define CHANNEL_LIST_DYNAMIC_INIT 2 /* Occupied channel list can be learnt after init */ +#define CHANNEL_LIST_DYNAMIC_FLUSH 3 /* Occupied channel list can be learnt after flush */ +#define CHANNEL_LIST_DYNAMIC_UPDATE 4 /* Occupied channel list can be learnt after update */ +#define SIR_ROAM_SCAN_24G_DEFAULT_CH 1 +#define SIR_ROAM_SCAN_5G_DEFAULT_CH 36 +#define SIR_ROAM_SCAN_RESERVED_BYTES 61 +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_ROAM_SCAN_PSK_SIZE 32 +#define SIR_ROAM_R0KH_ID_MAX_LEN 48 +#endif +// SME -> HAL - This is the host offload request. +#define SIR_IPV4_ARP_REPLY_OFFLOAD 0 +#define SIR_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 +#define SIR_IPV6_NS_OFFLOAD 2 +#define SIR_OFFLOAD_DISABLE 0 +#define SIR_OFFLOAD_ENABLE 1 +#define SIR_OFFLOAD_BCAST_FILTER_ENABLE 0x2 +#define SIR_OFFLOAD_MCAST_FILTER_ENABLE 0x4 +#define SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE (SIR_OFFLOAD_ENABLE|SIR_OFFLOAD_BCAST_FILTER_ENABLE) +#define SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE (SIR_OFFLOAD_ENABLE|SIR_OFFLOAD_MCAST_FILTER_ENABLE) + +#ifdef WLAN_NS_OFFLOAD +typedef struct sSirNsOffloadReq +{ + tANI_U8 srcIPv6Addr[16]; + tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; + tANI_U8 targetIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; + tANI_U8 selfMacAddr[6]; + tANI_U8 srcIPv6AddrValid; + tANI_U8 targetIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; + tANI_U8 slotIdx; +} tSirNsOffloadReq, *tpSirNsOffloadReq; +#endif //WLAN_NS_OFFLOAD + +typedef struct sSirHostOffloadReq +{ + tANI_U8 offloadType; + tANI_U8 enableOrDisable; + uint32_t num_ns_offload_count; + union + { + tANI_U8 hostIpv4Addr [4]; + tANI_U8 hostIpv6Addr [16]; + } params; +#ifdef WLAN_NS_OFFLOAD + tSirNsOffloadReq nsOffloadInfo; +#endif //WLAN_NS_OFFLOAD + tSirMacAddr bssId; +} tSirHostOffloadReq, *tpSirHostOffloadReq; + +/* Packet Types. */ +#define SIR_KEEP_ALIVE_NULL_PKT 1 +#define SIR_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 + +/* Keep Alive request. */ +typedef struct sSirKeepAliveReq +{ + v_U8_t packetType; + v_U32_t timePeriod; + tSirIpv4Addr hostIpv4Addr; + tSirIpv4Addr destIpv4Addr; + tSirMacAddr destMacAddr; + tSirMacAddr bssId; + tANI_U8 sessionId; +} tSirKeepAliveReq, *tpSirKeepAliveReq; + +typedef struct sSirSmeAddStaSelfReq +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; + tANI_U32 type; + tANI_U32 subType; + tANI_U8 sessionId; + tANI_U16 pkt_err_disconn_th; + uint8_t nss_2g; + uint8_t nss_5g; +}tSirSmeAddStaSelfReq, *tpSirSmeAddStaSelfReq; + +typedef struct sSirSmeDelStaSelfReq +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tSirMacAddr selfMacAddr; + tANI_U8 sessionId; +}tSirSmeDelStaSelfReq, *tpSirSmeDelStaSelfReq; + +typedef struct sSirSmeAddStaSelfRsp +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_U16 status; + tSirMacAddr selfMacAddr; +}tSirSmeAddStaSelfRsp, *tpSirSmeAddStaSelfRsp; + +typedef struct sSirSmeDelStaSelfRsp +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_U16 status; + tSirMacAddr selfMacAddr; +}tSirSmeDelStaSelfRsp, *tpSirSmeDelStaSelfRsp; + +/* Coex Indication defines - + should match WLAN_COEX_IND_DATA_SIZE + should match WLAN_COEX_IND_TYPE_DISABLE_HB_MONITOR + should match WLAN_COEX_IND_TYPE_ENABLE_HB_MONITOR */ +#define SIR_COEX_IND_DATA_SIZE (4) +#define SIR_COEX_IND_TYPE_DISABLE_HB_MONITOR (0) +#define SIR_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) +#define SIR_COEX_IND_TYPE_SCAN_COMPROMISED (2) +#define SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED (3) +#define SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4 (4) +#define SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4 (5) + +typedef struct sSirSmeCoexInd +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_U32 coexIndType; + tANI_U32 coexIndData[SIR_COEX_IND_DATA_SIZE]; +}tSirSmeCoexInd, *tpSirSmeCoexInd; + +typedef struct sSirSmeMgmtFrameInd +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_U32 rxChan; + tANI_U8 sessionId; + tANI_U8 frameType; + tANI_S8 rxRssi; + tANI_U8 frameBuf[1]; //variable +}tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd; + +#ifdef WLAN_FEATURE_11W +typedef struct sSirSmeUnprotMgmtFrameInd +{ + tANI_U8 sessionId; + tANI_U8 frameType; + tANI_U8 frameLen; + tANI_U8 frameBuf[1]; //variable +}tSirSmeUnprotMgmtFrameInd, *tpSirSmeUnprotMgmtFrameInd; +#endif + +#define SIR_IS_FULL_POWER_REASON_DISCONNECTED(eReason) \ + ( ( eSME_LINK_DISCONNECTED_BY_HDD == (eReason) ) || \ + ( eSME_LINK_DISCONNECTED_BY_OTHER == (eReason) ) || \ + (eSME_FULL_PWR_NEEDED_BY_CHANNEL_SWITCH == (eReason))) +#define SIR_IS_FULL_POWER_NEEDED_BY_HDD(eReason) \ + ( ( eSME_LINK_DISCONNECTED_BY_HDD == (eReason) ) || ( eSME_FULL_PWR_NEEDED_BY_HDD == (eReason) ) ) + +/* P2P Power Save Related */ +typedef struct sSirNoAParam +{ + tANI_U8 ctWindow:7; + tANI_U8 OppPS:1; + tANI_U8 count; + tANI_U32 duration; + tANI_U32 interval; + tANI_U32 singleNoADuration; + tANI_U8 psSelection; +}tSirNoAParam, *tpSirNoAParam; + +typedef struct sSirWlanSuspendParam +{ + tANI_U8 configuredMcstBcstFilterSetting; + tANI_U8 sessionId; + tANI_U8 connectedState; +}tSirWlanSuspendParam,*tpSirWlanSuspendParam; + +typedef struct sSirWlanResumeParam +{ + tANI_U8 configuredMcstBcstFilterSetting; +}tSirWlanResumeParam,*tpSirWlanResumeParam; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + +typedef enum ext_wow_type +{ + EXT_WOW_TYPE_APP_TYPE1, /* wow type: only enable wakeup for app type1 */ + EXT_WOW_TYPE_APP_TYPE2, /* wow type: only enable wakeup for app type2 */ + EXT_WOW_TYPE_APP_TYPE1_2, /* wow type: enable wakeup for app type1&2 */ + +}EXT_WOW_TYPE; + +typedef struct +{ + tANI_U8 vdev_id; + EXT_WOW_TYPE type; + tANI_U32 wakeup_pin_num; +} tSirExtWoWParams, *tpSirExtWoWParams; + +typedef struct +{ + tANI_U8 vdev_id; + tSirMacAddr wakee_mac_addr; + tANI_U8 identification_id[8]; + tANI_U8 password[16]; + tANI_U32 id_length; + tANI_U32 pass_length; +} tSirAppType1Params, *tpSirAppType1Params; + +typedef struct +{ + tANI_U8 vdev_id; + + tANI_U8 rc4_key[16]; + tANI_U32 rc4_key_len; + + /** ip header parameter */ + tANI_U32 ip_id; /* NC id */ + tANI_U32 ip_device_ip; /* NC IP address */ + tANI_U32 ip_server_ip; /* Push server IP address */ + + /** tcp header parameter */ + tANI_U16 tcp_src_port; /* NC TCP port */ + tANI_U16 tcp_dst_port; /* Push server TCP port */ + tANI_U32 tcp_seq; + tANI_U32 tcp_ack_seq; + + tANI_U32 keepalive_init; /* Initial ping interval */ + tANI_U32 keepalive_min; /* Minimum ping interval */ + tANI_U32 keepalive_max; /* Maximum ping interval */ + tANI_U32 keepalive_inc; /* Increment of ping interval */ + + tSirMacAddr gateway_mac; + tANI_U32 tcp_tx_timeout_val; + tANI_U32 tcp_rx_timeout_val; +} tSirAppType2Params, *tpSirAppType2Params; +#endif + +typedef struct sSirWlanSetRxpFilters +{ + tANI_U8 configuredMcstBcstFilterSetting; + tANI_U8 setMcstBcstFilter; +}tSirWlanSetRxpFilters,*tpSirWlanSetRxpFilters; + +#ifdef FEATURE_WLAN_SCAN_PNO +// +// PNO Messages +// + +// Set PNO +#define SIR_PNO_MAX_NETW_CHANNELS 26 +#define SIR_PNO_MAX_NETW_CHANNELS_EX 60 +#define SIR_PNO_MAX_SUPP_NETWORKS 16 + +/*size based of dot11 declaration without extra IEs as we will not carry those for PNO*/ +#define SIR_PNO_MAX_PB_REQ_SIZE 450 + +#define SIR_PNO_24G_DEFAULT_CH 1 +#define SIR_PNO_5G_DEFAULT_CH 36 + +typedef enum +{ + SIR_PNO_MODE_IMMEDIATE, + SIR_PNO_MODE_ON_SUSPEND, + SIR_PNO_MODE_ON_RESUME, + SIR_PNO_MODE_MAX +} eSirPNOMode; + +typedef struct +{ + tSirMacSSid ssId; + tANI_U32 authentication; + tANI_U32 encryption; + tANI_U32 bcastNetwType; + tANI_U8 ucChannelCount; + tANI_U8 aChannels[SIR_PNO_MAX_NETW_CHANNELS_EX]; + tANI_S32 rssiThreshold; +} tSirNetworkType; + +/** + * struct sSirPNOScanReq - PNO Scan request structure + * @enable: flag to enable or disable + * @modePNO: PNO Mode + * @ucNetworksCount: Number of networks + * @do_passive_scan: Flag to request passive scan to fw + * @aNetworks: Preferred network list + * @sessionId: Session identifier + * @fast_scan_period: Fast Scan period + * @slow_scan_period: Slow scan period + * @fast_scan_max_cycles: Fast scan max cycles + * @active_min_time: Min value of dwell time for active scan + * @active_max_time: Max value of dwell time for active scan + * @passive_min_time: Min value of dwell time for passive scan + * @passive_max_time: Max value of dwell time for passive scan + * @us24GProbeTemplateLen: 2.4G probe template length + * @p24GProbeTemplate: 2.4G probe template + * @us5GProbeTemplateLen: 5G probe template length + * @p5GProbeTemplate: 5G probe template + */ +typedef struct sSirPNOScanReq { + uint8_t enable; + eSirPNOMode modePNO; + bool do_passive_scan; + uint8_t ucNetworksCount; + tSirNetworkType aNetworks[SIR_PNO_MAX_SUPP_NETWORKS]; + uint8_t sessionId; + uint32_t fast_scan_period; + uint32_t slow_scan_period; + uint8_t fast_scan_max_cycles; + + uint32_t active_min_time; + uint32_t active_max_time; + uint32_t passive_min_time; + uint32_t passive_max_time; + + uint16_t us24GProbeTemplateLen; + uint8_t p24GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE]; + uint16_t us5GProbeTemplateLen; + uint8_t p5GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE]; +} tSirPNOScanReq, *tpSirPNOScanReq; + +typedef struct sSirSetRSSIFilterReq +{ + tANI_U8 rssiThreshold; +} tSirSetRSSIFilterReq, *tpSirSetRSSIFilterReq; + + +// Update Scan Params +typedef struct { + tANI_U8 b11dEnabled; + tANI_U8 b11dResolved; + tANI_U8 ucChannelCount; + tANI_U8 aChannels[SIR_PNO_MAX_NETW_CHANNELS_EX]; + tANI_U16 usPassiveMinChTime; + tANI_U16 usPassiveMaxChTime; + tANI_U16 usActiveMinChTime; + tANI_U16 usActiveMaxChTime; + tANI_U8 ucCBState; +} tSirUpdateScanParams, * tpSirUpdateScanParams; + +// Preferred Network Found Indication +typedef struct +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + /* Network that was found with the highest RSSI*/ + tSirMacSSid ssId; + /* Indicates the RSSI */ + tANI_U8 rssi; + /* Length of the beacon or probe response + * corresponding to the candidate found by PNO */ + tANI_U32 frameLength; + tANI_U8 sessionId; + /* Index to memory location where the contents of + * beacon or probe response frame will be copied */ + tANI_U8 data[1]; +} tSirPrefNetworkFoundInd, *tpSirPrefNetworkFoundInd; +#endif //FEATURE_WLAN_SCAN_PNO + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +typedef struct { + tANI_U8 acvo_uapsd: 1; + tANI_U8 acvi_uapsd: 1; + tANI_U8 acbk_uapsd: 1; + tANI_U8 acbe_uapsd: 1; + tANI_U8 reserved: 4; +} tSirAcUapsd, *tpSirAcUapsd; +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +typedef struct +{ + tSirMacSSid ssId; + tANI_U8 currAPbssid[VOS_MAC_ADDR_SIZE]; + tANI_U32 authentication; + tANI_U8 encryption; + tANI_U8 mcencryption; + tANI_U8 ChannelCount; + tANI_U8 ChannelCache[SIR_ROAM_MAX_CHANNELS]; +#ifdef WLAN_FEATURE_11W + tANI_BOOLEAN MFPEnabled; +#endif + +} tSirRoamNetworkType; + +typedef struct SirMobilityDomainInfo +{ + tANI_U8 mdiePresent; + tANI_U16 mobilityDomain; +} tSirMobilityDomainInfo; + +typedef enum { + SIR_ROAMING_DFS_CHANNEL_DISABLED = 0, + SIR_ROAMING_DFS_CHANNEL_ENABLED_NORMAL = 1, + SIR_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE = 2 +} eSirDFSRoamScanMode; +#define MAX_SSID_ALLOWED_LIST 4 +#define MAX_BSSID_AVOID_LIST 16 +#define MAX_BSSID_FAVORED 16 +struct roam_ext_params { + uint8_t num_bssid_avoid_list; + uint8_t num_ssid_allowed_list; + uint8_t num_bssid_favored; + tSirMacSSid ssid_allowed_list[MAX_SSID_ALLOWED_LIST]; + tSirMacAddr bssid_avoid_list[MAX_BSSID_AVOID_LIST]; + tSirMacAddr bssid_favored[MAX_BSSID_FAVORED]; + uint8_t bssid_favored_factor[MAX_BSSID_FAVORED]; + int raise_rssi_thresh_5g; + int drop_rssi_thresh_5g; + uint8_t raise_rssi_type_5g; + uint8_t raise_factor_5g; + uint8_t drop_rssi_type_5g; + uint8_t drop_factor_5g; + int max_raise_rssi_5g; + int max_drop_rssi_5g; + int alert_rssi_threshold; + int rssi_diff; + int good_rssi_roam; + bool is_5g_pref_enabled; +}; + +typedef struct sSirRoamOffloadScanReq +{ + eAniBoolean RoamScanOffloadEnabled; + eAniBoolean MAWCEnabled; + tANI_S8 LookupThreshold; + tANI_U8 delay_before_vdev_stop; + tANI_U8 OpportunisticScanThresholdDiff; + tANI_U8 RoamRescanRssiDiff; + tANI_U8 RoamRssiDiff; + tANI_U8 ChannelCacheType; + tANI_U8 Command; + tANI_U8 reason; + tANI_U16 NeighborScanTimerPeriod; + tANI_U16 NeighborRoamScanRefreshPeriod; + tANI_U16 NeighborScanChannelMinTime; + tANI_U16 NeighborScanChannelMaxTime; + tANI_U16 EmptyRefreshScanPeriod; + tANI_U8 ValidChannelCount; + tANI_U8 ValidChannelList[SIR_ROAM_MAX_CHANNELS]; + eAniBoolean IsESEAssoc; + tANI_U16 us24GProbeTemplateLen; + tANI_U8 p24GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; + tANI_U16 us5GProbeTemplateLen; + tANI_U8 p5GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; + tANI_U8 ReservedBytes[SIR_ROAM_SCAN_RESERVED_BYTES]; + /*ReservedBytes is to add any further params in future + without changing the interface params on Host + and firmware.The firmware right now checks + if the size of this structure matches and then + proceeds with the processing of the command. + So, in future, if there is any need to add + more params, pick the memory from reserved + bytes and keep deducting the reserved bytes + by the amount of bytes picked.*/ + tANI_U8 nProbes; + tANI_U16 HomeAwayTime; + tSirRoamNetworkType ConnectedNetwork; + tSirMobilityDomainInfo MDID; + tANI_U8 sessionId; + tANI_U8 RoamBmissFirstBcnt; + tANI_U8 RoamBmissFinalBcnt; + tANI_U8 RoamBeaconRssiWeight; + eSirDFSRoamScanMode allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U8 RoamOffloadEnabled; + tANI_U8 PSK_PMK[SIR_ROAM_SCAN_PSK_SIZE]; + tANI_U32 pmk_len; + tANI_U8 Prefer5GHz; + tANI_U8 RoamRssiCatGap; + tANI_U8 Select5GHzMargin; + tANI_U8 KRK[SIR_KRK_KEY_LEN]; + tANI_U8 BTK[SIR_BTK_KEY_LEN]; + tANI_U32 ReassocFailureTimeout; + tSirAcUapsd AcUapsd; + tANI_U8 R0KH_ID[SIR_ROAM_R0KH_ID_MAX_LEN]; + tANI_U32 R0KH_ID_Length; + tANI_U8 RoamKeyMgmtOffloadEnabled; +#endif + struct roam_ext_params roam_params; + uint32_t hi_rssi_scan_max_count; + uint32_t hi_rssi_scan_rssi_delta; + uint32_t hi_rssi_scan_delay; + int32_t hi_rssi_scan_rssi_ub; + uint8_t middle_of_roaming; + +} tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; + +typedef struct sSirRoamOffloadScanRsp +{ + tANI_U8 sessionId; + tANI_U32 reason; +} tSirRoamOffloadScanRsp, *tpSirRoamOffloadScanRsp; + +struct sir_sme_roam_restart_req +{ + tANI_U16 message_type; + tANI_U16 length; + tANI_U8 sme_session_id; + tANI_U8 command; + tANI_U8 reason; +}; +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +#define SIR_NOCHANGE_POWER_VALUE 0xFFFFFFFF + +//Power Parameters Type +typedef enum +{ + eSIR_IGNORE_DTIM = 1, + eSIR_LISTEN_INTERVAL = 2, + eSIR_MCAST_BCAST_FILTER = 3, + eSIR_ENABLE_BET = 4, + eSIR_BET_INTERVAL = 5 +}tPowerParamType; + +//Power Parameters Value s +typedef struct +{ + /* Ignore DTIM */ + tANI_U32 uIgnoreDTIM; + + /* DTIM Period */ + tANI_U32 uDTIMPeriod; + + /* Listen Interval */ + tANI_U32 uListenInterval; + + /* Broadcast Multicast Filter */ + tANI_U32 uBcastMcastFilter; + + /* Beacon Early Termination */ + tANI_U32 uEnableBET; + + /* Beacon Early Termination Interval */ + tANI_U32 uBETInterval; + + /* MAX LI for modulated DTIM */ + tANI_U32 uMaxLIModulatedDTIM; + +}tSirSetPowerParamsReq, *tpSirSetPowerParamsReq; + +typedef struct sSirTxPerTrackingParam +{ + tANI_U8 ucTxPerTrackingEnable; /* 0: disable, 1:enable */ + tANI_U8 ucTxPerTrackingPeriod; /* Check period, unit is sec. Once tx_stat_chk enable, firmware will check PER in this period periodically */ + tANI_U8 ucTxPerTrackingRatio; /* (Fail TX packet)/(Total TX packet) ratio, the unit is 10%. for example, 5 means 50% TX failed rate, default is 5. If current TX packet failed rate bigger than this ratio then firmware send WLC_E_TX_STAT_ERROR event to driver */ + tANI_U32 uTxPerTrackingWatermark; /* A watermark of check number, once the tx packet exceed this number, we do the check, default is 5 */ +}tSirTxPerTrackingParam, *tpSirTxPerTrackingParam; + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/*--------------------------------------------------------------------------- + Packet Filtering Parameters +---------------------------------------------------------------------------*/ +#define SIR_IPV4_ADDR_LEN 4 +#define SIR_MAC_ADDR_LEN 6 +#define SIR_MAX_FILTER_TEST_DATA_LEN 8 +#define SIR_MAX_NUM_MULTICAST_ADDRESS 240 +#define SIR_MAX_NUM_FILTERS 20 +#define SIR_MAX_NUM_TESTS_PER_FILTER 10 + +// +// Receive Filter Parameters +// +typedef enum +{ + SIR_RCV_FILTER_TYPE_INVALID, + SIR_RCV_FILTER_TYPE_FILTER_PKT, + SIR_RCV_FILTER_TYPE_BUFFER_PKT, + SIR_RCV_FILTER_TYPE_MAX_ENUM_SIZE +}eSirReceivePacketFilterType; + +typedef enum +{ + SIR_FILTER_HDR_TYPE_INVALID, + SIR_FILTER_HDR_TYPE_MAC, + SIR_FILTER_HDR_TYPE_ARP, + SIR_FILTER_HDR_TYPE_IPV4, + SIR_FILTER_HDR_TYPE_IPV6, + SIR_FILTER_HDR_TYPE_UDP, + SIR_FILTER_HDR_TYPE_MAX +}eSirRcvPktFltProtocolType; + +typedef enum +{ + SIR_FILTER_CMP_TYPE_INVALID, + SIR_FILTER_CMP_TYPE_EQUAL, + SIR_FILTER_CMP_TYPE_MASK_EQUAL, + SIR_FILTER_CMP_TYPE_NOT_EQUAL, + SIR_FILTER_CMP_TYPE_MASK_NOT_EQUAL, + SIR_FILTER_CMP_TYPE_MAX +}eSirRcvPktFltCmpFlagType; + +typedef struct sSirRcvPktFilterFieldParams +{ + eSirRcvPktFltProtocolType protocolLayer; + eSirRcvPktFltCmpFlagType cmpFlag; + /* Length of the data to compare */ + tANI_U16 dataLength; + /* from start of the respective frame header */ + tANI_U8 dataOffset; + /* Reserved field */ + tANI_U8 reserved; + /* Data to compare */ + tANI_U8 compareData[SIR_MAX_FILTER_TEST_DATA_LEN]; + /* Mask to be applied on the received packet data before compare */ + tANI_U8 dataMask[SIR_MAX_FILTER_TEST_DATA_LEN]; +}tSirRcvPktFilterFieldParams, *tpSirRcvPktFilterFieldParams; + +typedef struct sSirRcvPktFilterCfg +{ + tANI_U8 filterId; + eSirReceivePacketFilterType filterType; + tANI_U32 numFieldParams; + tANI_U32 coalesceTime; + tSirMacAddr selfMacAddr; + tSirMacAddr bssId; //Bssid of the connected AP + tSirRcvPktFilterFieldParams paramsData[SIR_MAX_NUM_TESTS_PER_FILTER]; +}tSirRcvPktFilterCfgType, *tpSirRcvPktFilterCfgType; + +// +// Filter Packet Match Count Parameters +// +typedef struct sSirRcvFltPktMatchCnt +{ + tANI_U8 filterId; + tANI_U32 matchCnt; +} tSirRcvFltPktMatchCnt, tpSirRcvFltPktMatchCnt; + +typedef struct sSirRcvFltPktMatchRsp +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + + /* Success or Failure */ + tANI_U32 status; + tSirRcvFltPktMatchCnt filterMatchCnt[SIR_MAX_NUM_FILTERS]; + tSirMacAddr bssId; +} tSirRcvFltPktMatchRsp, *tpSirRcvFltPktMatchRsp; + +// +// Receive Filter Clear Parameters +// +typedef struct sSirRcvFltPktClearParam +{ + tANI_U32 status; /* only valid for response message */ + tANI_U8 filterId; + tSirMacAddr selfMacAddr; + tSirMacAddr bssId; +}tSirRcvFltPktClearParam, *tpSirRcvFltPktClearParam; + +// +// Multicast Address List Parameters +// +typedef struct sSirRcvFltMcAddrList +{ + tANI_U32 ulMulticastAddrCnt; + tSirMacAddr multicastAddr[SIR_MAX_NUM_MULTICAST_ADDRESS]; + tSirMacAddr selfMacAddr; + tSirMacAddr bssId; + tANI_U8 action; +} tSirRcvFltMcAddrList, *tpSirRcvFltMcAddrList; +#endif // WLAN_FEATURE_PACKET_FILTERING + +// +// Generic version information +// +typedef struct +{ + tANI_U8 revision; + tANI_U8 version; + tANI_U8 minor; + tANI_U8 major; +} tSirVersionType; + +typedef struct sAniBtAmpLogLinkReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 sessionId; //sme Session Id + void *btampHandle; //AMP context + +} tAniBtAmpLogLinkReq, *tpAniBtAmpLogLinkReq; + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/*--------------------------------------------------------------------------- +* WDA_GTK_OFFLOAD_REQ +*--------------------------------------------------------------------------*/ +typedef struct +{ + tANI_U32 ulFlags; /* optional flags */ + tANI_U8 aKCK[16]; /* Key confirmation key */ + tANI_U8 aKEK[16]; /* key encryption key */ + tANI_U64 ullKeyReplayCounter; /* replay counter */ + tSirMacAddr bssId; +} tSirGtkOffloadParams, *tpSirGtkOffloadParams; + +/** + * struct sir_wifi_start_log - Structure to store the params sent to start/ + * stop logging + * @name: Attribute which indicates the type of logging like per packet + * statistics, connectivity etc. + * @verbose_level: Verbose level which can be 0,1,2,3 + * @flag: Flag field for future use + */ +struct sir_wifi_start_log { + uint32_t ring_id; + uint32_t verbose_level; + uint32_t flag; +}; + +/*--------------------------------------------------------------------------- +* WDA_GTK_OFFLOAD_GETINFO_REQ +*--------------------------------------------------------------------------*/ +typedef struct +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + + tANI_U32 ulStatus; /* success or failure */ + tANI_U64 ullKeyReplayCounter; /* current replay counter value */ + tANI_U32 ulTotalRekeyCount; /* total rekey attempts */ + tANI_U32 ulGTKRekeyCount; /* successful GTK rekeys */ + tANI_U32 ulIGTKRekeyCount; /* successful iGTK rekeys */ + tSirMacAddr bssId; +} tSirGtkOffloadGetInfoRspParams, *tpSirGtkOffloadGetInfoRspParams; +#endif // WLAN_FEATURE_GTK_OFFLOAD + +#ifdef WLAN_WAKEUP_EVENTS +/*--------------------------------------------------------------------------- + tSirWakeReasonInd +---------------------------------------------------------------------------*/ +typedef struct +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_U32 ulReason; /* see tWakeReasonType */ + tANI_U32 ulReasonArg; /* argument specific to the reason type */ + tANI_U32 ulStoredDataLen; /* length of optional data stored in this message, in case + HAL truncates the data (i.e. data packets) this length + will be less than the actual length */ + tANI_U32 ulActualDataLen; /* actual length of data */ + tANI_U8 aDataStart[1]; /* variable length start of data (length == storedDataLen) + see specific wake type */ +} tSirWakeReasonInd, *tpSirWakeReasonInd; +#endif // WLAN_WAKEUP_EVENTS + +/*--------------------------------------------------------------------------- + sAniSetTmLevelReq +---------------------------------------------------------------------------*/ +typedef struct sAniSetTmLevelReq +{ + tANI_U16 tmMode; + tANI_U16 newTmLevel; +} tAniSetTmLevelReq, *tpAniSetTmLevelReq; + +#ifdef FEATURE_WLAN_TDLS +/* TDLS Request struct SME-->PE */ +typedef struct sSirTdlsSendMgmtReq +{ + tANI_U16 messageType; // eWNI_SME_TDLS_DISCOVERY_START_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tANI_U8 reqType; + tANI_U8 dialog; + tANI_U16 statusCode; + tANI_U8 responder; + tANI_U32 peerCapability; + tSirMacAddr bssid; // For multi-session, for PE to locate peSession ID + tSirMacAddr peerMac; + + /* Variable length. Dont add any field after this. */ + tANI_U8 addIe[1]; +} tSirTdlsSendMgmtReq, *tpSirSmeTdlsSendMgmtReq ; + +typedef enum TdlsAddOper +{ + TDLS_OPER_NONE, + TDLS_OPER_ADD, + TDLS_OPER_UPDATE +} eTdlsAddOper; + +/* TDLS Request struct SME-->PE */ +typedef struct sSirTdlsAddStaReq +{ + tANI_U16 messageType; // eWNI_SME_TDLS_DISCOVERY_START_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssid; // For multi-session, for PE to locate peSession ID + eTdlsAddOper tdlsAddOper; + tSirMacAddr peerMac; + tANI_U16 capability; + tANI_U8 extn_capability[SIR_MAC_MAX_EXTN_CAP]; + tANI_U8 supported_rates_length; + tANI_U8 supported_rates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; + tSirHTCap htCap; + tANI_U8 vhtcap_present; + tSirVHTCap vhtCap; + tANI_U8 uapsd_queues; + tANI_U8 max_sp; +} tSirTdlsAddStaReq, *tpSirSmeTdlsAddStaReq ; + +/* TDLS Response struct PE-->SME */ +typedef struct sSirTdlsAddStaRsp +{ + tANI_U16 messageType; + tANI_U16 length; + tSirResultCodes statusCode; + tSirMacAddr peerMac; + tANI_U8 sessionId; // Session ID + tANI_U16 staId ; + tANI_U16 staType ; + tANI_U8 ucastSig; + tANI_U8 bcastSig; + eTdlsAddOper tdlsAddOper; +} tSirTdlsAddStaRsp ; + +/* TDLS Request struct SME-->PE */ +typedef struct +{ + tANI_U16 messageType; // eWNI_SME_TDLS_LINK_ESTABLISH_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tANI_U8 uapsdQueues; // Peer's uapsd Queues Information + tANI_U8 maxSp; // Peer's Supported Maximum Service Period + tANI_U8 isBufSta; // Does Peer Support as Buffer Station. + tANI_U8 isOffChannelSupported; // Does Peer Support as TDLS Off Channel. + tANI_U8 isResponder; // Is Peer a responder. + tSirMacAddr bssid; // For multi-session, for PE to locate peSession ID + tSirMacAddr peerMac; + tANI_U8 supportedChannelsLen; + tANI_U8 supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; + tANI_U8 supportedOperClassesLen; + tANI_U8 supportedOperClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +}tSirTdlsLinkEstablishReq, *tpSirTdlsLinkEstablishReq; + +/* TDLS Request struct SME-->PE */ +typedef struct +{ + tANI_U16 messageType; // eWNI_SME_TDLS_LINK_ESTABLISH_RSP + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirResultCodes statusCode; + tSirMacAddr peerMac; +}tSirTdlsLinkEstablishReqRsp, *tpSirTdlsLinkEstablishReqRsp; + +/* TDLS Request struct SME-->PE */ +typedef struct sSirTdlsDelStaReq +{ + tANI_U16 messageType; // eWNI_SME_TDLS_DISCOVERY_START_REQ + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 transactionId; // Transaction ID for cmd + tSirMacAddr bssid; // For multi-session, for PE to locate peSession ID + tSirMacAddr peerMac; +} tSirTdlsDelStaReq, *tpSirSmeTdlsDelStaReq ; +/* TDLS Response struct PE-->SME */ +typedef struct sSirTdlsDelStaRsp +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tSirResultCodes statusCode; + tSirMacAddr peerMac; + tANI_U16 staId; +} tSirTdlsDelStaRsp, *tpSirTdlsDelStaRsp; +/* TDLS Delete Indication struct PE-->SME */ +typedef struct sSirTdlsDelStaInd +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tSirMacAddr peerMac; + tANI_U16 staId; + tANI_U16 reasonCode; +} tSirTdlsDelStaInd, *tpSirTdlsDelStaInd; +typedef struct sSirTdlsDelAllPeerInd +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; // Session ID +} tSirTdlsDelAllPeerInd, *tpSirTdlsDelAllPeerInd; +#ifdef FEATURE_WLAN_TDLS_DISAPPEAR_AP +typedef struct sSirTdlsDisappearAPInd +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U16 staId; + tSirMacAddr staAddr; +} tSirTdlsDisappearAPInd, *tpSirTdlsDisappearAPInd; +#endif +typedef struct sSirMgmtTxCompletionInd +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 sessionId; // Session ID + tANI_U32 txCompleteStatus; +} tSirMgmtTxCompletionInd, *tpSirMgmtTxCompletionInd; + +typedef struct sSirTdlsEventNotify +{ + tANI_U8 sessionId; + tSirMacAddr peerMac; + tANI_U16 messageType; + tANI_U32 peer_reason; +} tSirTdlsEventNotify; +#endif /* FEATURE_WLAN_TDLS */ + + +typedef struct sSirActiveModeSetBcnFilterReq +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U8 seesionId; +} tSirSetActiveModeSetBncFilterReq, *tpSirSetActiveModeSetBncFilterReq; + +//Reset AP Caps Changed +typedef struct sSirResetAPCapsChange +{ + tANI_U16 messageType; + tANI_U16 length; + tSirMacAddr bssId; +} tSirResetAPCapsChange, *tpSirResetAPCapsChange; + +/// Definition for Candidate found indication from FW +typedef struct sSirSmeCandidateFoundInd +{ + tANI_U16 messageType; // eWNI_SME_CANDIDATE_FOUND_IND + tANI_U16 length; + tANI_U8 sessionId; // Session Identifier +} tSirSmeCandidateFoundInd, *tpSirSmeCandidateFoundInd; + +#ifdef WLAN_FEATURE_11W +typedef struct sSirWlanExcludeUnencryptParam +{ + tANI_BOOLEAN excludeUnencrypt; + tSirMacAddr bssId; +}tSirWlanExcludeUnencryptParam,*tpSirWlanExcludeUnencryptParam; +#endif + +typedef enum { + P2P_SCAN_TYPE_SEARCH = 1, /* P2P Search */ + P2P_SCAN_TYPE_LISTEN /* P2P Listen */ +}tSirP2pScanType; + +typedef struct sAniHandoffReq +{ + // Common for all types are requests + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 sessionId; + tANI_U8 bssid[VOS_MAC_ADDR_SIZE]; + tANI_U8 channel; + tANI_U8 handoff_src; +} tAniHandoffReq, *tpAniHandoffReq; + +typedef struct sSirScanOffloadReq { + tANI_U8 sessionId; + tSirMacAddr bssId; + tANI_U8 numSsid; + tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; + tANI_U8 hiddenSsid; + tSirMacAddr selfMacAddr; + tSirBssType bssType; + tANI_U8 dot11mode; + tSirScanType scanType; + tANI_U32 minChannelTime; + tANI_U32 maxChannelTime; + /*in units of milliseconds, ignored when not connected*/ + uint32_t restTime; + /*in units of milliseconds, ignored when not connected*/ + uint32_t min_rest_time; + /*in units of milliseconds, ignored when not connected*/ + uint32_t idle_time; + tSirP2pScanType p2pScanType; + tANI_U16 uIEFieldLen; + tANI_U16 uIEFieldOffset; + tSirChannelList channelList; + /*----------------------------- + sSirScanOffloadReq.... + ----------------------------- + uIEFieldLen + ----------------------------- + uIEFieldOffset ----+ + ----------------------------- | + channelList.numChannels | + ----------------------------- | + ... variable size up to | + channelNumber[numChannels-1] | + This can be zero, if | + numChannel is zero. | + ----------------------------- <--+ + ... variable size uIEField + up to uIEFieldLen (can be 0) + -----------------------------*/ +} tSirScanOffloadReq, *tpSirScanOffloadReq; + +typedef enum sSirScanEventType { + SCAN_EVENT_STARTED=0x1, /* Scan command accepted by FW */ + SCAN_EVENT_COMPLETED=0x2, /* Scan has been completed by FW */ + SCAN_EVENT_BSS_CHANNEL=0x4, /* FW is going to move to HOME channel */ + SCAN_EVENT_FOREIGN_CHANNEL = 0x8,/* FW is going to move to FORIEGN channel */ + SCAN_EVENT_DEQUEUED=0x10, /* scan request got dequeued */ + SCAN_EVENT_PREEMPTED=0x20, /* preempted by other high priority scan */ + SCAN_EVENT_START_FAILED=0x40, /* scan start failed */ + SCAN_EVENT_RESTARTED=0x80, /*scan restarted*/ + SCAN_EVENT_MAX=0x8000 +} tSirScanEventType; + +typedef struct sSirScanOffloadEvent{ + tSirScanEventType event; + tSirResultCodes reasonCode; + tANI_U32 chanFreq; + tANI_U32 requestor; + tANI_U32 scanId; + tSirP2pScanType p2pScanType; + tANI_U8 sessionId; +} tSirScanOffloadEvent, *tpSirScanOffloadEvent; + +typedef struct sSirUpdateChanParam +{ + tANI_U8 chanId; + tANI_U8 pwr; + tANI_BOOLEAN dfsSet; + bool half_rate; + bool quarter_rate; +} tSirUpdateChanParam, *tpSirUpdateChanParam; + +typedef struct sSirUpdateChan +{ + tANI_U8 numChan; + uint8_t ht_en; + uint8_t vht_en; + uint8_t vht_24_en; + tSirUpdateChanParam chanParam[1]; +} tSirUpdateChanList, *tpSirUpdateChanList; + +typedef enum eSirAddonPsReq +{ + eSIR_ADDON_NOTHING, + eSIR_ADDON_ENABLE_UAPSD, + eSIR_ADDON_DISABLE_UAPSD +}tSirAddonPsReq; + +/* Powersave Offload data */ +typedef struct sSirPsReqData +{ + /* BSSID */ + tSirMacAddr bssId; + + /* Additional Info */ + tSirAddonPsReq addOnReq; +} tSirPsReqData,*tpSirPsReqData; + +#ifdef FEATURE_WLAN_LPHB +#define SIR_LPHB_FILTER_LEN 64 + +typedef enum +{ + LPHB_SET_EN_PARAMS_INDID, + LPHB_SET_TCP_PARAMS_INDID, + LPHB_SET_TCP_PKT_FILTER_INDID, + LPHB_SET_UDP_PARAMS_INDID, + LPHB_SET_UDP_PKT_FILTER_INDID, + LPHB_SET_NETWORK_INFO_INDID, +} LPHBIndType; + +typedef struct sSirLPHBEnableStruct +{ + v_U8_t enable; + v_U8_t item; + v_U8_t session; +} tSirLPHBEnableStruct; + +typedef struct sSirLPHBTcpParamStruct +{ + v_U32_t srv_ip; + v_U32_t dev_ip; + v_U16_t src_port; + v_U16_t dst_port; + v_U16_t timeout; + v_U8_t session; + tSirMacAddr gateway_mac; + uint16 timePeriodSec; // in seconds + uint32 tcpSn; +} tSirLPHBTcpParamStruct; + +typedef struct sSirLPHBTcpFilterStruct +{ + v_U16_t length; + v_U8_t offset; + v_U8_t session; + v_U8_t filter[SIR_LPHB_FILTER_LEN]; +} tSirLPHBTcpFilterStruct; + +typedef struct sSirLPHBUdpParamStruct +{ + v_U32_t srv_ip; + v_U32_t dev_ip; + v_U16_t src_port; + v_U16_t dst_port; + v_U16_t interval; + v_U16_t timeout; + v_U8_t session; + tSirMacAddr gateway_mac; +} tSirLPHBUdpParamStruct; + +typedef struct sSirLPHBUdpFilterStruct +{ + v_U16_t length; + v_U8_t offset; + v_U8_t session; + v_U8_t filter[SIR_LPHB_FILTER_LEN]; +} tSirLPHBUdpFilterStruct; + +typedef struct sSirLPHBReq +{ + v_U16_t cmd; + v_U16_t dummy; + union + { + tSirLPHBEnableStruct lphbEnableReq; + tSirLPHBTcpParamStruct lphbTcpParamReq; + tSirLPHBTcpFilterStruct lphbTcpFilterReq; + tSirLPHBUdpParamStruct lphbUdpParamReq; + tSirLPHBUdpFilterStruct lphbUdpFilterReq; + } params; +} tSirLPHBReq; + +typedef struct sSirLPHBInd +{ + v_U8_t sessionIdx; + v_U8_t protocolType; /*TCP or UDP*/ + v_U8_t eventReason; +} tSirLPHBInd; +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_CH_AVOID +typedef struct sSirChAvoidUpdateReq +{ + tANI_U32 reserved_param; +} tSirChAvoidUpdateReq; +#endif /* FEATURE_WLAN_CH_AVOID */ + +typedef struct sSirLinkSpeedInfo +{ + /* MAC Address for the peer */ + tSirMacAddr peer_macaddr; + tANI_U32 estLinkSpeed; //Linkspeed from firmware +} tSirLinkSpeedInfo, *tpSirLinkSpeedInfo; + + +/* + * struct sir_rssi_req - rssi request struct + * @peer_macaddr: MAC address + * @sessionId: vdev id + * + * rssi request message's struct + */ +struct sir_rssi_req { + v_MACADDR_t peer_macaddr; + uint8_t sessionId; +}; + + +/* + * struct sir_rssi_info - rssi information struct + * @peer_macaddr: MAC address + * @rssi: rssi + * + * a station's rssi information + */ +struct sir_rssi_info { + tSirMacAddr peer_macaddr; + int8_t rssi; +}; + +/* + * struct sir_rssi_info - all peers rssi information struct + * @count: peer's number + * @info: rssi information + * + * all station's rssi information + */ +struct sir_rssi_resp { + uint8_t count; + struct sir_rssi_info info[0]; +}; + + +typedef struct sSirAddPeriodicTxPtrn +{ + /* MAC Address for the adapter */ + tSirMacAddr macAddress; + tANI_U8 ucPtrnId; // Pattern ID + tANI_U16 ucPtrnSize; // Pattern size + tANI_U32 usPtrnIntervalMs; // In msec + tANI_U8 ucPattern[PERIODIC_TX_PTRN_MAX_SIZE]; // Pattern buffer +} tSirAddPeriodicTxPtrn, *tpSirAddPeriodicTxPtrn; + +typedef struct sSirDelPeriodicTxPtrn +{ + /* MAC Address for the adapter */ + tSirMacAddr macAddress; + /* Bitmap of pattern IDs that need to be deleted */ + tANI_U32 ucPatternIdBitmap; + tANI_U8 ucPtrnId; // Pattern ID +} tSirDelPeriodicTxPtrn, *tpSirDelPeriodicTxPtrn; + + +typedef struct +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_BOOLEAN suspended; +} tSirReadyToSuspendInd, *tpSirReadyToSuspendInd; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +typedef struct +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tANI_BOOLEAN status; +} tSirReadyToExtWoWInd, *tpSirReadyToExtWoWInd; +#endif +typedef struct sSirRateUpdateInd +{ + tANI_U8 nss; /* 0: 1x1, 1: 2x2 */ + tSirMacAddr bssid; + tVOS_CON_MODE dev_mode; + tANI_S32 bcastDataRate; /* bcast rate unit Mbpsx10, -1 : not used */ + /* 0 implies RA, positive value implies fixed rate, -1 implies ignore this + * param. + */ + tANI_S32 ucastDataRate; + + /* TX flag to differentiate between HT20, HT40 etc */ + tTxrateinfoflags ucastDataRateTxFlag; + + /* + * 0 implies MCAST RA, positive value implies fixed rate, + * -1 implies ignore this param + */ + tANI_S32 reliableMcastDataRate;//unit Mbpsx10 + + /* TX flag to differentiate between HT20, HT40 etc */ + tTxrateinfoflags reliableMcastDataRateTxFlag; + + /* + * MCAST(or BCAST) fixed data rate in 2.4 GHz, unit Mbpsx10, + * 0 implies ignore + */ + tANI_U32 mcastDataRate24GHz; + + /* TX flag to differentiate between HT20, HT40 etc */ + tTxrateinfoflags mcastDataRate24GHzTxFlag; + + /* + * MCAST(or BCAST) fixed data rate in 5 GHz, + * unit Mbpsx10, 0 implies ignore + */ + tANI_U32 mcastDataRate5GHz; + + /* TX flag to differentiate between HT20, HT40 etc */ + tTxrateinfoflags mcastDataRate5GHzTxFlag; + +} tSirRateUpdateInd, *tpSirRateUpdateInd; + +#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC) +#define SIR_CH_AVOID_MAX_RANGE 4 + +typedef struct sSirChAvoidFreqType +{ + tANI_U32 start_freq; + tANI_U32 end_freq; +} tSirChAvoidFreqType; + +typedef struct sSirChAvoidIndType +{ + tANI_U32 avoid_range_count; + tSirChAvoidFreqType avoid_freq_range[SIR_CH_AVOID_MAX_RANGE]; +} tSirChAvoidIndType; +#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */ + +#define SIR_DFS_MAX_20M_SUB_CH 8 + +typedef struct sSirSmeDfsChannelList +{ + tANI_U32 nchannels; + /*Channel number including bonded channels on which the RADAR is present */ + tANI_U8 channels[SIR_DFS_MAX_20M_SUB_CH]; +}tSirSmeDfsChannelList, *tpSirSmeDfsChannelList; + +typedef struct sSirSmeDfsEventInd +{ + tANI_U32 sessionId; + tSirSmeDfsChannelList chan_list; + tANI_U32 dfs_radar_status; + int use_nol; +}tSirSmeDfsEventInd, *tpSirSmeDfsEventInd; + +typedef struct sSirChanChangeRequest +{ + tANI_U16 messageType; + tANI_U16 messageLen; + tANI_U8 targetChannel; + tANI_U8 cbMode; + tANI_U8 vht_channel_width; + tANI_U8 bssid[VOS_MAC_ADDR_SIZE]; + tANI_U32 dot11mode; + tSirMacRateSet operational_rateset; + tSirMacRateSet extended_rateset; +}tSirChanChangeRequest, *tpSirChanChangeRequest; + +typedef struct sSirChanChangeResponse +{ + tANI_U8 sessionId; + tANI_U8 newChannelNumber; + tANI_U8 channelChangeStatus; + ePhyChanBondState secondaryChannelOffset; +}tSirChanChangeResponse, *tpSirChanChangeResponse; + +typedef struct sSirStartBeaconIndication +{ + tANI_U16 messageType; + tANI_U16 messageLen; + tANI_U8 beaconStartStatus; + tANI_U8 bssid[VOS_MAC_ADDR_SIZE]; +}tSirStartBeaconIndication, *tpSirStartBeaconIndication; + +/* additional IE type */ +typedef enum tUpdateIEsType +{ + eUPDATE_IE_NONE, + eUPDATE_IE_PROBE_BCN, + eUPDATE_IE_PROBE_RESP, + eUPDATE_IE_ASSOC_RESP, + + /* Add type above this line*/ + /* this is used to reset all buffer */ + eUPDATE_IE_ALL, + eUPDATE_IE_MAX +} eUpdateIEsType; + + +/* Modify particular IE in addition IE for probe resp Bcn */ +typedef struct sSirModifyIE +{ + tSirMacAddr bssid; + tANI_U16 smeSessionId; + boolean notify; + tANI_U8 ieID; + tANI_U8 ieIDLen; /*ie length as per spec*/ + tANI_U16 ieBufferlength; + tANI_U8 *pIEBuffer; + +}tSirModifyIE, *tpSirModifyIE; + + +/* Message format for Update IE message sent to PE */ +typedef struct sSirModifyIEsInd +{ + tANI_U16 msgType; + tANI_U16 msgLen; + tSirModifyIE modifyIE; + eUpdateIEsType updateType; +}tSirModifyIEsInd, *tpSirModifyIEsInd; + + +/* Message format for Update IE message sent to PE */ +typedef struct sSirUpdateIE +{ + tSirMacAddr bssid; + tANI_U16 smeSessionId; + boolean append; + boolean notify; + tANI_U16 ieBufferlength; + tANI_U8 *pAdditionIEBuffer; +}tSirUpdateIE, *tpSirUpdateIE; + + +/* Message format for Update IE message sent to PE */ +typedef struct sSirUpdateIEsInd +{ + tANI_U16 msgType; + tANI_U16 msgLen; + tSirUpdateIE updateIE; + eUpdateIEsType updateType; +}tSirUpdateIEsInd, *tpSirUpdateIEsInd; + +/* Message format for requesting channel switch announcement to lower layers */ +typedef struct sSirDfsCsaIeRequest +{ + tANI_U16 msgType; + tANI_U16 msgLen; + tANI_U8 targetChannel; + tANI_U8 csaIeRequired; + tANI_U8 bssid[VOS_MAC_ADDR_SIZE]; + u_int8_t ch_bandwidth; +}tSirDfsCsaIeRequest, *tpSirDfsCsaIeRequest; + +/* Indication from lower layer indicating the completion of first beacon send + * after the beacon template update + */ +typedef struct sSirFirstBeaconTxCompleteInd +{ + tANI_U16 messageType; // eWNI_SME_MISSED_BEACON_IND + tANI_U16 length; + tANI_U8 bssIdx; +}tSirFirstBeaconTxCompleteInd, *tpSirFirstBeaconTxCompleteInd; + +typedef struct sSirSmeCSAIeTxCompleteRsp +{ + tANI_U8 sessionId; + tANI_U8 chanSwIeTxStatus; +}tSirSmeCSAIeTxCompleteRsp, *tpSirSmeCSAIeTxCompleteRsp; + +/* Thermal Mitigation*/ + +typedef struct{ + u_int16_t minTempThreshold; + u_int16_t maxTempThreshold; +} t_thermal_level_info, *tp_thermal_level_info; + +typedef enum +{ + WLAN_WMA_THERMAL_LEVEL_0, + WLAN_WMA_THERMAL_LEVEL_1, + WLAN_WMA_THERMAL_LEVEL_2, + WLAN_WMA_THERMAL_LEVEL_3, + WLAN_WMA_MAX_THERMAL_LEVELS +} t_thermal_level; + +typedef struct{ + /* Array of thermal levels */ + t_thermal_level_info thermalLevels[WLAN_WMA_MAX_THERMAL_LEVELS]; + u_int8_t thermalCurrLevel; + u_int8_t thermalMgmtEnabled; + u_int32_t throttlePeriod; +} t_thermal_mgmt, *tp_thermal_mgmt; + +typedef struct sSirTxPowerLimit +{ + /* Thermal limits for 2g and 5g */ + u_int32_t txPower2g; + u_int32_t txPower5g; +} tSirTxPowerLimit; + + +enum bad_peer_thresh_levels{ + WLAN_WMA_IEEE80211_B_LEVEL = 0, + WLAN_WMA_IEEE80211_AG_LEVEL, + WLAN_WMA_IEEE80211_N_LEVEL, + WLAN_WMA_IEEE80211_AC_LEVEL, + WLAN_WMA_IEEE80211_AX_LEVEL, + WLAN_WMA_IEEE80211_MAX_LEVEL, +}; + +#define NUM_OF_RATE_THRESH_MAX (4) +struct t_bad_peer_info{ + uint32_t cond; + uint32_t delta; + uint32_t percentage; + uint32_t thresh[NUM_OF_RATE_THRESH_MAX]; + uint32_t txlimit; +}; + +struct t_bad_peer_txtcl_config{ + /* Array of thermal levels */ + struct t_bad_peer_info threshold[WLAN_WMA_IEEE80211_MAX_LEVEL]; + uint32_t enable; + uint32_t period; + uint32_t txq_limit; + uint32_t tgt_backoff; + uint32_t tgt_report_prd; +}; + + +// Notify MODEM power state to FW +typedef struct +{ + tANI_U32 param; +} tSirModemPowerStateInd, *tpSirModemPowerStateInd; + +#ifdef WLAN_FEATURE_STATS_EXT +typedef struct +{ + tANI_U32 vdev_id; + tANI_U32 event_data_len; + u_int8_t event_data[]; +} tSirStatsExtEvent, *tpSirStatsExtEvent; +#endif + +#ifdef WLAN_FEATURE_NAN +typedef struct +{ + tANI_U32 event_data_len; + tANI_U8 event_data[]; +} tSirNanEvent, *tpSirNanEvent; +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +typedef struct sSirSmeRoamOffloadSynchInd +{ + tANI_U16 messageType; /*eWNI_SME_ROAM_OFFLOAD_SYNCH_IND*/ + tANI_U16 length; + tANI_U16 beaconProbeRespOffset; + tANI_U16 beaconProbeRespLength; + tANI_U16 reassocRespOffset; + tANI_U16 reassocRespLength; + tANI_U8 isBeacon; + tANI_U8 roamedVdevId; + tSirMacAddr bssId; + tANI_S8 txMgmtPower; + tANI_U32 authStatus; + tANI_U8 rssi; + tANI_U8 roamReason; + tANI_U32 chan_freq; + tANI_U8 kck[SIR_KCK_KEY_LEN]; + tANI_U8 kek[SIR_KEK_KEY_LEN]; + tANI_U8 replay_ctr[SIR_REPLAY_CTR_LEN]; + tpSirBssDescription pbssDescription; +} tSirRoamOffloadSynchInd, *tpSirRoamOffloadSynchInd; + +typedef struct sSirSmeRoamOffloadSynchCnf +{ + tANI_U8 sessionId; +} tSirSmeRoamOffloadSynchCnf, *tpSirSmeRoamOffloadSynchCnf; + +typedef struct sSirSmeHOFailureInd +{ + tANI_U8 sessionId; +} tSirSmeHOFailureInd, *tpSirSmeHOFailureInd; + +typedef struct sSirRoamOffloadSynchFail +{ + tANI_U8 sessionId; +} tSirRoamOffloadSynchFail, *tpSirRoamOffloadSynchFail; +#endif + +#ifdef FEATURE_WLAN_EXTSCAN + +/** + * typedef enum wifi_scan_flags - wifi scan flags + * @WIFI_SCAN_FLAG_INTERRUPTED: Indicates that scan results are not complete + * because probes were not sent on some channels + */ +typedef enum { + WIFI_SCAN_FLAG_INTERRUPTED = 1, +} wifi_scan_flags; + +typedef enum +{ + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_A_DFS_ONLY = 4, /* 5 GHz DFS only */ + /* 5 is reserved */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ + + /* Keep it last */ + WIFI_BAND_MAX +} tWifiBand; + +/* wifi scan related events */ +typedef enum +{ + WIFI_SCAN_BUFFER_FULL, + WIFI_SCAN_COMPLETE, +} tWifiScanEventType; + +/** + * enum extscan_configuration_flags - extscan config flags + * @EXTSCAN_LP_EXTENDED_BATCHING: extended batching + */ +enum extscan_configuration_flags { + EXTSCAN_LP_EXTENDED_BATCHING = 0x00000001, +}; + +typedef struct +{ + tSirMacAddr bssid; + + /* Low threshold */ + tANI_S32 low; + + /* High threshold */ + tANI_S32 high; + +} tSirAPThresholdParam, *tpSirAPThresholdParam; + +typedef struct +{ + tANI_U32 requestId; + tANI_U8 sessionId; +} tSirGetExtScanCapabilitiesReqParams, *tpSirGetExtScanCapabilitiesReqParams; + +/** + * struct ext_scan_capabilities_response - extscan capabilities response data + * from target + * @requestId: request identifier + * @status: status + * @max_scan_cache_size: total space allocated for scan (in bytes) + * @max_scan_buckets: maximum number of channel buckets + * @max_ap_cache_per_scan: maximum number of APs that can be stored per scan + * @max_rssi_sample_size: number of RSSI samples used for averaging RSSI + * @ax_scan_reporting_threshold: max possible report_threshold + * @max_hotlist_bssids: maximum number of entries for hotlist APs + * @max_significant_wifi_change_aps: maximum number of entries for + * significant wifi change APs + * @max_bssid_history_entries: number of BSSID/RSSI entries that device can hold + * @max_hotlist_ssids: maximum number of entries for hotlist SSIDs + * @max_number_epno_networks: max number of epno entries + * @max_number_epno_networks_by_ssid: max number of epno entries + * if ssid is specified, that is, epno entries for + * which an exact match is required, + * or entries corresponding to hidden ssids + * @max_number_of_white_listed_ssid: max number of white listed SSIDs + */ +struct ext_scan_capabilities_response +{ + uint32_t requestId; + uint32_t status; + + uint32_t max_scan_cache_size; + uint32_t max_scan_buckets; + uint32_t max_ap_cache_per_scan; + uint32_t max_rssi_sample_size; + uint32_t max_scan_reporting_threshold; + + uint32_t max_hotlist_bssids; + uint32_t max_significant_wifi_change_aps; + + uint32_t max_bssid_history_entries; + uint32_t max_hotlist_ssids; + uint32_t max_number_epno_networks; + uint32_t max_number_epno_networks_by_ssid; + uint32_t max_number_of_white_listed_ssid; +}; + + +typedef struct +{ + tANI_U32 requestId; + tANI_U8 sessionId; + + /* + * 1 - return cached results and flush it + * 0 - return cached results and do not flush + */ + tANI_BOOLEAN flush; +} tSirExtScanGetCachedResultsReqParams, *tpSirExtScanGetCachedResultsReqParams; + +typedef struct +{ + tANI_U32 requestId; + tANI_U32 status; +} tSirExtScanGetCachedResultsRspParams, *tpSirExtScanGetCachedResultsRspParams; + +typedef struct +{ + /* Time of discovery (in micro second) */ + tANI_U64 ts; + + /* Null terminated SSID */ + tANI_U8 ssid[SIR_MAC_MAX_SSID_LENGTH+1]; + + tSirMacAddr bssid; + + /* Frequency in MHz */ + tANI_U32 channel; + + /* RSSI in dBm */ + tANI_S32 rssi; + + /* RTT in nanoseconds */ + tANI_U32 rtt; + + /* Standard deviation in rtt */ + tANI_U32 rtt_sd; + + /* Period advertised in the beacon */ + tANI_U16 beaconPeriod; + + /* Capabilities advertised in the beacon */ + tANI_U16 capability; + + tANI_U16 ieLength; + + tANI_U8 ieData[]; +} tSirWifiScanResult, *tpSirWifiScanResult; + +/** + * struct extscan_hotlist_match - extscan hotlist match + * @requestId: request identifier + * @numOfAps: number of bssids retrieved by the scan + * @moreData: 0 - for last fragment + * 1 - still more fragment(s) coming + * @ap: wifi scan result + */ +struct extscan_hotlist_match +{ + uint32_t requestId; + bool moreData; + bool ap_found; + uint32_t numOfAps; + tSirWifiScanResult ap[]; +}; + +/** + * struct extscan_cached_scan_result - extscan cached scan result + * @scan_id: a unique identifier for the scan unit + * @flags: a bitmask with additional information about scan + * @num_results: number of bssids retrieved by the scan + * @ap: wifi scan bssid results info + */ +struct extscan_cached_scan_result +{ + uint32_t scan_id; + uint32_t flags; + uint32_t num_results; + tSirWifiScanResult *ap; +}; + +/** + * struct tSirWifiScanResultEvent - wifi scan result event + * @requestId: request identifier + * @ap_found: flag to indicate ap found or not + * true: AP was found + * false: AP was lost + * @numOfAps: number of aps + * @moreData: more data + * @ap: bssid information + * + */ +typedef struct +{ + uint32_t requestId; + bool ap_found; + uint32_t numOfAps; + bool moreData; + tSirWifiScanResult ap[]; +} tSirWifiScanResultEvent, *tpSirWifiScanResultEvent; + +/** + * struct extscan_cached_scan_results - extscan cached scan results + * @request_id: request identifier + * @more_data: 0 - for last fragment + * 1 - still more fragment(s) coming + * @num_scan_ids: number of scan ids + * @result: wifi scan result + */ +struct extscan_cached_scan_results +{ + uint32_t request_id; + bool more_data; + uint32_t num_scan_ids; + struct extscan_cached_scan_result *result; +}; + + +/** + * struct tSirWifiFullScanResultEvent - extscan full scan event + * @request_id: request identifier + * @moreData: 0 - for last fragment + * 1 - still more fragment(s) coming + * @ap: bssid info + * + * Reported when each probe response is received, if reportEvents + * enabled in tSirWifiScanCmdReqParams + */ +typedef struct +{ + uint32_t requestId; + bool moreData; + tSirWifiScanResult ap; +} tSirWifiFullScanResultEvent, *tpSirWifiFullScanResultEvent; + +/** + * struct pno_match_found - epno match found + * @request_id: request identifier + * @moreData: 0 - for last fragment + * 1 - still more fragment(s) coming + * @num_results: number of bssids, driver sends this event to upper layer + * for every beacon, hence %num_results is always set to 1. + * @ap: bssid info + * + * Reported when each beacon probe response is received with + * epno match found tag. + */ +struct pno_match_found +{ + uint32_t request_id; + bool more_data; + uint32_t num_results; + tSirWifiScanResult ap[]; +}; + + +typedef struct +{ + /* Frequency in MHz*/ + tANI_U32 channel; + + tANI_U32 dwellTimeMs; + + /* 0 => active + 1 => passive scan; ignored for DFS */ + tANI_BOOLEAN passive; + + tANI_U8 chnlClass; +} tSirWifiScanChannelSpec, *tpSirWifiScanChannelSpec; + +/** + * struct tSirWifiScanBucketSpec - wifi scan bucket spec + * @bucket: bucket identifier + * @band: wifi band + * @period: Desired period, in millisecond; if this is too + * low, the firmware should choose to generate results as fast as + * it can instead of failing the command byte + * for exponential backoff bucket this is the min_period + * @reportEvents: 0 => normal reporting (reporting rssi history + * only, when rssi history buffer is % full) + * 1 => same as 0 + report a scan completion event after scanning + * this bucket + * 2 => same as 1 + forward scan results + * (beacons/probe responses + IEs) in real time to HAL + * @max_period: if max_period is non zero or different than period, + * then this bucket is an exponential backoff bucket and + * the scan period will grow exponentially as per formula: + * actual_period(N) = period ^ (N/(step_count+1)) to a + * maximum period of max_period + * @exponent: for exponential back off bucket: multiplier: + * new_period = old_period * exponent + * @step_count: for exponential back off bucket, number of scans performed + * at a given period and until the exponent is applied + * @numChannels: channels to scan; these may include DFS channels + * Note that a given channel may appear in multiple buckets + * @min_dwell_time_active: per bucket minimum active dwell time + * @max_dwell_time_active: per bucket maximum active dwell time + * @min_dwell_time_passive: per bucket minimum passive dwell time + * @max_dwell_time_passive: per bucket maximum passive dwell time + * @channels: Channel list + */ +typedef struct +{ + uint8_t bucket; + tWifiBand band; + uint32_t period; + uint32_t reportEvents; + uint32_t max_period; + uint32_t exponent; + uint32_t step_count; + uint32_t numChannels; + + uint32_t min_dwell_time_active; + uint32_t max_dwell_time_active; + uint32_t min_dwell_time_passive; + uint32_t max_dwell_time_passive; + tSirWifiScanChannelSpec channels[WLAN_EXTSCAN_MAX_CHANNELS]; +} tSirWifiScanBucketSpec, *tpSirWifiScanBucketSpec; + +/** + * struct tSirWifiScanCmdReqParams - extscan request parameters + * @basePeriod: base period + * @maxAPperScan: Max number of APs to report per scan + * @report_threshold_percent: threshold at which framework should be informed + * @report_threshold_num_scans: number of scans after which wake up the host + * @requestId: Request id + * @sessionId: Session id + * @numBuckets: number of buckets to scan + * @min_dwell_time_active: per bucket minimum active dwell time + * @max_dwell_time_active: per bucket maximum active dwell time + * @min_dwell_time_passive: per bucket minimum passive dwell time + * @max_dwell_time_passive: per bucket maximum passive dwell time + * @configuration_flags: configuration flags + * @buckets: bucket list + */ +typedef struct +{ + tANI_U32 basePeriod; + tANI_U32 maxAPperScan; + uint32_t report_threshold_percent; + uint32_t report_threshold_num_scans; + + tANI_U32 requestId; + tANI_U8 sessionId; + tANI_U32 numBuckets; + + uint32_t min_dwell_time_active; + uint32_t max_dwell_time_active; + uint32_t min_dwell_time_passive; + uint32_t max_dwell_time_passive; + uint32_t configuration_flags; + tSirWifiScanBucketSpec buckets[WLAN_EXTSCAN_MAX_BUCKETS]; +} tSirWifiScanCmdReqParams, *tpSirWifiScanCmdReqParams; + +/** + * struct sir_extscan_generic_response - + * Generic ExtScan Response structure + * @request_id: ID of the request + * @status: operation status returned by firmware + */ +struct sir_extscan_generic_response { + uint32_t request_id; + int32_t status; +}; + +typedef struct +{ + tANI_U32 requestId; + tANI_U8 sessionId; +} tSirExtScanStopReqParams, *tpSirExtScanStopReqParams; + +/** + * struct tSirExtScanSetBssidHotListReqParams - set hotlist request + * @requestId: request identifier + * @sessionId: session identifier + * @lost_ap_sample_size: number of samples to confirm AP loss + * @numAp: Number of hotlist APs + * @ap: hotlist APs + */ +typedef struct +{ + uint32_t requestId; + uint8_t sessionId; + uint32_t lost_ap_sample_size; + uint32_t numAp; + tSirAPThresholdParam ap[WLAN_EXTSCAN_MAX_HOTLIST_APS]; +} tSirExtScanSetBssidHotListReqParams, *tpSirExtScanSetBssidHotListReqParams; + +typedef struct +{ + tANI_U32 requestId; + tANI_U8 sessionId; +} tSirExtScanResetBssidHotlistReqParams, + *tpSirExtScanResetBssidHotlistReqParams; + +/** + * struct sir_ssid_hotlist_param - param for SSID Hotlist + * @ssid: SSID which is being hotlisted + * @band: Band in which the given SSID should be scanned + * @rssi_low: Low bound on RSSI + * @rssi_high: High bound on RSSI + */ +struct sir_ssid_hotlist_param { + tSirMacSSid ssid; + uint8_t band; + int32_t rssi_low; + int32_t rssi_high; +}; + +/** + * struct sir_set_ssid_hotlist_request - set SSID hotlist request struct + * @request_id: ID of the request + * @session_id: ID of the session + * @lost_ssid_sample_size: Number of consecutive scans in which the SSID + * must not be seen in order to consider the SSID "lost" + * @ssid_count: Number of valid entries in the @ssids array + * @ssids: Array that defines the SSIDs that are in the hotlist + */ +struct sir_set_ssid_hotlist_request { + uint32_t request_id; + uint8_t session_id; + uint32_t lost_ssid_sample_size; + uint32_t ssid_count; + struct sir_ssid_hotlist_param ssids[WLAN_EXTSCAN_MAX_HOTLIST_SSIDS]; +}; + +typedef struct +{ + tANI_U32 requestId; + tANI_U8 sessionId; + + /* Number of samples for averaging RSSI */ + tANI_U32 rssiSampleSize; + + /* Number of missed samples to confirm AP loss */ + tANI_U32 lostApSampleSize; + + /* Number of APs breaching threshold required for firmware + * to generate event + */ + tANI_U32 minBreaching; + + tANI_U32 numAp; + tSirAPThresholdParam ap[WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS]; +} tSirExtScanSetSigChangeReqParams, + *tpSirExtScanSetSigChangeReqParams; + +typedef struct +{ + tSirMacAddr bssid; + tANI_U32 channel; + tANI_U32 numOfRssi; + + /* Rssi history in db */ + tANI_S32 rssi[]; +} tSirWifiSignificantChange, *tpSirWifiSignificantChange; + +typedef struct +{ + tANI_U32 requestId; + + tANI_BOOLEAN moreData; + tANI_U32 numResults; + tSirWifiSignificantChange ap[]; +} tSirWifiSignificantChangeEvent, *tpSirWifiSignificantChangeEvent; + +typedef struct +{ + tANI_U32 requestId; + tANI_U8 sessionId; +} tSirExtScanResetSignificantChangeReqParams, + *tpSirExtScanResetSignificantChangeReqParams; + +typedef struct +{ + tANI_U32 requestId; + tANI_U32 numResultsAvailable; +} tSirExtScanResultsAvailableIndParams, + *tpSirExtScanResultsAvailableIndParams; + +typedef struct +{ + tANI_U32 requestId; + tANI_U32 status; + tANI_U8 scanEventType; +} tSirExtScanOnScanEventIndParams, + *tpSirExtScanOnScanEventIndParams; + +/** + * struct wifi_epno_network - enhanced pno network block + * @ssid: ssid + * @rssi_threshold: threshold for considering this SSID as found, required + * granularity for this threshold is 4dBm to 8dBm + * @flags: WIFI_PNO_FLAG_XXX + * @auth_bit_field: auth bit field for matching WPA IE + */ +struct wifi_epno_network +{ + tSirMacSSid ssid; + int8_t rssi_threshold; + uint8_t flags; + uint8_t auth_bit_field; +}; + +/** + * struct wifi_epno_params - enhanced pno network params + * @num_networks: number of ssids + * @networks: PNO networks + */ +struct wifi_epno_params +{ + uint32_t request_id; + uint32_t session_id; + uint32_t num_networks; + struct wifi_epno_network networks[]; +}; + +#define SIR_PASSPOINT_REALM_LEN 256 +#define SIR_PASSPOINT_ROAMING_CONSORTIUM_ID_NUM 16 +#define SIR_PASSPOINT_PLMN_LEN 3 +/** + * struct wifi_passpoint_network - passpoint network block + * @id: identifier of this network block + * @realm: null terminated UTF8 encoded realm, 0 if unspecified + * @roaming_consortium_ids: roaming consortium ids to match, 0s if unspecified + * @plmn: mcc/mnc combination as per rules, 0s if unspecified + */ +struct wifi_passpoint_network +{ + uint32_t id; + uint8_t realm[SIR_PASSPOINT_REALM_LEN]; + int64_t roaming_consortium_ids[SIR_PASSPOINT_ROAMING_CONSORTIUM_ID_NUM]; + uint8_t plmn[SIR_PASSPOINT_PLMN_LEN]; +}; + +/** + * struct wifi_passpoint_req - passpoint request + * @request_id: request identifier + * @num_networks: number of networks + * @networks: passpoint networks + */ +struct wifi_passpoint_req +{ + uint32_t request_id; + uint32_t session_id; + uint32_t num_networks; + struct wifi_passpoint_network networks[]; +}; + +/** + * struct wifi_passpoint_match - wifi passpoint network match + * @id: network block identifier for the matched network + * @anqp_len: length of ANQP blob + * @ap: scan result, with channel and beacon information + * @anqp: ANQP data, in the information_element format + */ +struct wifi_passpoint_match +{ + uint32_t request_id; + uint32_t id; + uint32_t anqp_len; + tSirWifiScanResult ap; + uint8_t anqp[]; +}; + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +typedef struct +{ + tANI_U32 timer_val; +} tSirAutoShutdownCmdParams; + +typedef struct +{ + tANI_U32 shutdown_reason; +} tSirAutoShutdownEvtParams; +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +typedef struct +{ + tANI_U32 reqId; + tANI_U8 staId; + tANI_U32 mpduSizeThreshold; + tANI_U32 aggressiveStatisticsGathering; +} tSirLLStatsSetReq, *tpSirLLStatsSetReq; + +typedef struct +{ + tANI_U32 reqId; + tANI_U8 staId; + tANI_U32 paramIdMask; +} tSirLLStatsGetReq, *tpSirLLStatsGetReq; + +typedef struct +{ + tANI_U32 reqId; + tANI_U8 staId; + tANI_U32 statsClearReqMask; + tANI_U8 stopReq; +} tSirLLStatsClearReq, *tpSirLLStatsClearReq; + +typedef struct +{ + tANI_U8 oui[WIFI_SCANNING_MAC_OUI_LENGTH]; +} tSirScanMacOui, *tpSirScanMacOui; + +enum { + SIR_AP_RX_DATA_OFFLOAD = 0x00, + SIR_STA_RX_DATA_OFFLOAD = 0x01, +}; + +struct sir_ipa_offload_enable_disable +{ + uint32_t offload_type; + uint32_t vdev_id; + uint32_t enable; +}; + +/** + * struct sir_set_ht_vht_cfg - ht, vht IE config + * + * @msg_type: message type + * @len: message length + * @pdev_id: pdev id + * @nss: Nss value + * @dot11mode: Dot11 mode. + * + * Message wrapper structure for set HT/VHT IE req. + */ +struct sir_set_ht_vht_cfg { + uint16_t msg_type; + uint16_t len; + uint32_t pdev_id; + uint32_t nss; + uint32_t dot11mode; +}; + +/*--------------------------------------------------------------------------- + WLAN_HAL_LL_NOTIFY_STATS +---------------------------------------------------------------------------*/ + + +/******************************LINK LAYER Statistics**********************/ + +typedef int tSirWifiRadio; +typedef int tSirWifiChannel; +typedef int tSirwifiTxRate; + +/* channel operating width */ +typedef enum +{ + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, +} tSirWifiChannelWidth; + +typedef enum +{ + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, /* if done by firmware/driver */ + WIFI_EAPOL_COMPLETED = 5, /* if done by firmware/driver */ +} tSirWifiConnectionState; + +typedef enum +{ + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +} tSirWifiRoamState; + +typedef enum +{ + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + } tSirWifiInterfaceMode; + +/* set for QOS association */ +#define WIFI_CAPABILITY_QOS 0x00000001 +/* set for protected association (802.11 beacon frame control protected bit set) */ +#define WIFI_CAPABILITY_PROTECTED 0x00000002 +/* set if 802.11 Extended Capabilities element interworking bit is set */ +#define WIFI_CAPABILITY_INTERWORKING 0x00000004 +/* set for HS20 association */ +#define WIFI_CAPABILITY_HS20 0x00000008 +/* set is 802.11 Extended Capabilities element UTF-8 SSID bit is set */ +#define WIFI_CAPABILITY_SSID_UTF8 0x00000010 +/* set is 802.11 Country Element is present */ +#define WIFI_CAPABILITY_COUNTRY 0x00000020 + +typedef struct +{ + /* tSirWifiInterfaceMode */ + /* interface mode */ + tANI_U8 mode; + /* interface mac address (self) */ + tSirMacAddr macAddr; + /* tSirWifiConnectionState */ + /* connection state (valid for STA, CLI only) */ + tANI_U8 state; + /* tSirWifiRoamState */ + /* roaming state */ + tANI_U32 roaming; + /* WIFI_CAPABILITY_XXX (self) */ + tANI_U32 capabilities; + /* null terminated SSID */ + tANI_U8 ssid[33]; + /* bssid */ + tSirMacAddr bssid; + /* country string advertised by AP */ + tANI_U8 apCountryStr[WNI_CFG_COUNTRY_CODE_LEN]; + /* country string for this association */ + tANI_U8 countryStr[WNI_CFG_COUNTRY_CODE_LEN]; +} tSirWifiInterfaceInfo, *tpSirWifiInterfaceInfo; + +/* channel information */ +typedef struct +{ + /* channel width (20, 40, 80, 80+80, 160) */ + tSirWifiChannelWidth width; + /* primary 20 MHz channel */ + tSirWifiChannel centerFreq; + /* center frequency (MHz) first segment */ + tSirWifiChannel centerFreq0; + /* center frequency (MHz) second segment */ + tSirWifiChannel centerFreq1; +} tSirWifiChannelInfo, *tpSirWifiChannelInfo; + +/* wifi rate info */ +typedef struct +{ + /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ + tANI_U32 preamble :3; + /* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ + tANI_U32 nss :2; + /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */ + tANI_U32 bw :3; + /* OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps */ + /* HT/VHT it would be mcs index */ + tANI_U32 rateMcsIdx :8; + /* reserved */ + tANI_U32 reserved :16; + /* units of 100 Kbps */ + tANI_U32 bitrate; +} tSirWifiRate, *tpSirWifiRate; + +/* channel statistics */ +typedef struct +{ + /* channel */ + tSirWifiChannelInfo channel; + /* msecs the radio is awake (32 bits number accruing over time) */ + tANI_U32 onTime; + /* msecs the CCA register is busy (32 bits number accruing over time) */ + tANI_U32 ccaBusyTime; +} tSirWifiChannelStats, *tpSirWifiChannelStats; + +/* radio statistics */ +typedef struct +{ + /* wifi radio (if multiple radio supported) */ + tSirWifiRadio radio; + /* msecs the radio is awake (32 bits number accruing over time) */ + tANI_U32 onTime; + /* msecs the radio is transmitting + * (32 bits number accruing over time) + */ + tANI_U32 txTime; + /* msecs the radio is in active receive + *(32 bits number accruing over time) + */ + tANI_U32 rxTime; + /* msecs the radio is awake due to all scan + * (32 bits number accruing over time) + */ + tANI_U32 onTimeScan; + /* msecs the radio is awake due to NAN + * (32 bits number accruing over time) + */ + tANI_U32 onTimeNbd; + /* msecs the radio is awake due to Gscan + * (32 bits number accruing over time) + */ + tANI_U32 onTimeGscan; + /* msecs the radio is awake due to roam?scan + * (32 bits number accruing over time) + */ + tANI_U32 onTimeRoamScan; + /* msecs the radio is awake due to PNO scan + * (32 bits number accruing over time) + */ + tANI_U32 onTimePnoScan; + /* msecs the radio is awake due to HS2.0 scans and GAS exchange + * (32 bits number accruing over time) + */ + tANI_U32 onTimeHs20; + /* number of channels */ + tANI_U32 numChannels; + /* channel statistics tSirWifiChannelStats */ + tSirWifiChannelStats channels[0]; +} tSirWifiRadioStat, *tpSirWifiRadioStat; + +/* per rate statistics */ +typedef struct +{ + /* rate information */ + tSirWifiRate rate; + /* number of successfully transmitted data pkts (ACK rcvd) */ + tANI_U32 txMpdu; + /* number of received data pkts */ + tANI_U32 rxMpdu; + /* number of data packet losses (no ACK) */ + tANI_U32 mpduLost; + /* total number of data pkt retries * */ + tANI_U32 retries; + /* number of short data pkt retries */ + tANI_U32 retriesShort; + /* number of long data pkt retries */ + tANI_U32 retriesLong; +} tSirWifiRateStat, *tpSirWifiRateStat; + +/* access categories */ +typedef enum +{ + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +} tSirWifiTrafficAc; + +/* wifi peer type */ +typedef enum +{ + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +} tSirWifiPeerType; + +/* per peer statistics */ +typedef struct +{ + /* peer type (AP, TDLS, GO etc.) */ + tSirWifiPeerType type; + /* mac address */ + tSirMacAddr peerMacAddress; + /* peer WIFI_CAPABILITY_XXX */ + tANI_U32 capabilities; + /* number of rates */ + tANI_U32 numRate; + /* per rate statistics, number of entries = num_rate */ + tSirWifiRateStat rateStats[0]; +} tSirWifiPeerInfo, *tpSirWifiPeerInfo; + +/* per access category statistics */ +typedef struct +{ + /* tSirWifiTrafficAc */ + /* access category (VI, VO, BE, BK) */ + tANI_U32 ac; + /* number of successfully transmitted unicast data pkts (ACK rcvd) */ + tANI_U32 txMpdu; + /* number of received unicast mpdus */ + tANI_U32 rxMpdu; + /* Number of successfully transmitted multicast data packets */ + /* STA case: implies ACK received from AP for the unicast */ + /* packet in which mcast pkt was sent */ + tANI_U32 txMcast; + /* number of received multicast data packets */ + tANI_U32 rxMcast; + /* number of received unicast a-mpdus */ + tANI_U32 rxAmpdu; + /* number of transmitted unicast a-mpdus */ + tANI_U32 txAmpdu; + /* number of data pkt losses (no ACK) */ + tANI_U32 mpduLost; + /* total number of data pkt retries */ + tANI_U32 retries; + /* number of short data pkt retries */ + tANI_U32 retriesShort; + /* number of long data pkt retries */ + tANI_U32 retriesLong; + /* data pkt min contention time (usecs) */ + tANI_U32 contentionTimeMin; + /* data pkt max contention time (usecs) */ + tANI_U32 contentionTimeMax; + /* data pkt avg contention time (usecs) */ + tANI_U32 contentionTimeAvg; + /* num of data pkts used for contention statistics */ + tANI_U32 contentionNumSamples; +} tSirWifiWmmAcStat, *tpSirWifiWmmAcStat; + +/* Interface statistics - corresponding to 2nd most + * LSB in wifi statistics bitmap for getting statistics + */ +typedef struct +{ + /* current state of the interface */ + tSirWifiInterfaceInfo info; + /* access point beacon received count from connected AP */ + tANI_U32 beaconRx; + /* access point mgmt frames received count from */ + /* connected AP (including Beacon) */ + tANI_U32 mgmtRx; + /* action frames received count */ + tANI_U32 mgmtActionRx; + /* action frames transmit count */ + tANI_U32 mgmtActionTx; + /* access Point Beacon and Management frames RSSI (averaged) */ + tANI_U32 rssiMgmt; + /* access Point Data Frames RSSI (averaged) from connected AP */ + tANI_U32 rssiData; + /* access Point ACK RSSI (averaged) from connected AP */ + tANI_U32 rssiAck; + /** number of peers */ + tANI_U32 num_peers; + /** Indicates how many peer_stats events will be sent depending on the num_peers. */ + tANI_U32 num_peer_events; + /** number of ac */ + tANI_U32 num_ac; + /** Roaming Stat */ + tANI_U32 roam_state; + /** Average Beacon spread offset is the averaged time delay between TBTT and beacon TSF */ + /** Upper 32 bits of averaged 64 bit beacon spread offset */ + tANI_U32 avg_bcn_spread_offset_high; + /** Lower 32 bits of averaged 64 bit beacon spread offset */ + tANI_U32 avg_bcn_spread_offset_low; + /** Takes value of 1 if AP leaks packets after sending an ACK for PM=1 otherwise 0 */ + tANI_U32 is_leaky_ap; + /** Average number of frames received from AP after receiving the ACK for a frame with PM=1 */ + tANI_U32 avg_rx_frms_leaked; + /** Rx leak watch window currently in force to minimize data loss because of leaky AP. Rx leak window is the + time driver waits before shutting down the radio or switching the channel and after receiving an ACK for + a data frame with PM bit set) */ + tANI_U32 rx_leak_window; + /* per ac data packet statistics */ + tSirWifiWmmAcStat AccessclassStats[WIFI_AC_MAX]; +} tSirWifiIfaceStat, *tpSirWifiIfaceStat; + +/* Peer statistics - corresponding to 3rd most LSB in + * wifi statistics bitmap for getting statistics + */ +typedef struct +{ + /* number of peers */ + tANI_U32 numPeers; + /* per peer statistics */ + tSirWifiPeerInfo peerInfo[0]; +} tSirWifiPeerStat, *tpSirWifiPeerStat; + +/* wifi statistics bitmap for getting statistics */ +#define WMI_LINK_STATS_RADIO 0x00000001 +#define WMI_LINK_STATS_IFACE 0x00000002 +#define WMI_LINK_STATS_ALL_PEER 0x00000004 +#define WMI_LINK_STATS_PER_PEER 0x00000008 + +/* wifi statistics bitmap for clearing statistics */ +/* all radio statistics */ +#define WIFI_STATS_RADIO 0x00000001 +/* cca_busy_time (within radio statistics) */ +#define WIFI_STATS_RADIO_CCA 0x00000002 +/* all channel statistics (within radio statistics) */ +#define WIFI_STATS_RADIO_CHANNELS 0x00000004 +/* all scan statistics (within radio statistics) */ +#define WIFI_STATS_RADIO_SCAN 0x00000008 +/* all interface statistics */ +#define WIFI_STATS_IFACE 0x00000010 +/* all tx rate statistics (within interface statistics) */ +#define WIFI_STATS_IFACE_TXRATE 0x00000020 +/* all ac statistics (within interface statistics) */ +#define WIFI_STATS_IFACE_AC 0x00000040 +/* all contention (min, max, avg) statistics (within ac statistics) */ +#define WIFI_STATS_IFACE_CONTENTION 0x00000080 + +typedef struct +{ + tANI_U32 paramId; + tANI_U8 ifaceId; + tANI_U32 rspId; + tANI_U32 moreResultToFollow; + union + { + tANI_U32 num_peers; + tANI_U32 num_radio; + }; + + tANI_U32 peer_event_number ; + /* Variable length field - Do not add anything after this */ + tANI_U8 results[0]; +} tSirLLStatsResults, *tpSirLLStatsResults; + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +typedef struct sAniGetLinkStatus +{ + tANI_U16 msgType; /* message type is same as the request type */ + tANI_U16 msgLen; /* length of the entire request */ + tANI_U8 linkStatus; + tANI_U8 sessionId; +} tAniGetLinkStatus, *tpAniGetLinkStatus; + +#ifdef DHCP_SERVER_OFFLOAD +typedef struct +{ + tANI_U32 vdev_id; + tANI_U32 dhcpSrvOffloadEnabled; + tANI_U32 dhcpClientNum; + tANI_U32 dhcpSrvIP; + tANI_U32 dhcp_client_start_ip; +} tSirDhcpSrvOffloadInfo, *tpSirDhcpSrvOffloadInfo; +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +typedef struct +{ + tANI_U32 reqId; + tANI_U32 pattern_id; /* pattern identifier. 0: disconnected 1: connected*/ + tANI_U32 led_x0; /* led flashing parameter0 */ + tANI_U32 led_x1; /* led flashing parameter1 */ + tANI_U32 gpio_num; /* GPIO number */ +} tSirLedFlashingReq, *tpSirLedFlashingReq; +#endif + +#ifdef MDNS_OFFLOAD +#define MAX_MDNS_FQDN_LEN 64 +#define MAX_MDNS_RESP_LEN 512 + +typedef struct +{ + tANI_U32 vdev_id; + tANI_U32 mDNSOffloadEnabled; +} tSirMDNSOffloadInfo, *tpSirMDNSOffloadInfo; + +typedef struct +{ + tANI_U32 vdev_id; + tANI_U32 fqdn_type; + tANI_U32 fqdn_len; + tANI_U8 fqdn_data[MAX_MDNS_FQDN_LEN]; +} tSirMDNSFqdnInfo, *tpSirMDNSFqdnInfo; + +typedef struct +{ + tANI_U32 vdev_id; + tANI_U32 resourceRecord_count; + tANI_U32 resp_len; + tANI_U8 resp_data[MAX_MDNS_RESP_LEN]; +} tSirMDNSResponseInfo, *tpSirMDNSResponseInfo; +#endif /* MDNS_OFFLOAD */ + +/** + * struct sir_lost_link_info - lost link information structure. + * + * @vdev_id: vdev_id from WMA. some modules call sessionId. + * @rssi: rssi at disconnection time. + * + * driver uses this structure to communicate information collected at + * disconnection time. + */ +struct sir_lost_link_info +{ + uint32_t vdev_id; + int8_t rssi; +}; + +/* find the size of given member within a structure */ +#ifndef member_size +#define member_size(type, member) (sizeof(((type *)0)->member)) +#endif + +#define RTT_INVALID 0x00 +#define RTT_TIMING_MEAS_CAPABILITY 0x01 +#define RTT_FINE_TIME_MEAS_INITIATOR_CAPABILITY 0x02 +#define RTT_FINE_TIME_MEAS_RESPONDER_CAPABILITY 0x03 + +/** + * enum fine_time_meas_mask - bit mask to identify device's + * fine timing measurement capability + * @FINE_TIME_MEAS_STA_INITIATOR - STA role, Initiator capability is supported + * @FINE_TIME_MEAS_STA_RESPONDER - STA role, Responder capability is supported + * @FINE_TIME_MEAS_P2PCLI_INITIATOR - P2P-CLI supports initiator capability + * @FINE_TIME_MEAS_P2PCLI_RESPONDER - P2P-CLI supports responder capability + * @FINE_TIME_MEAS_P2PGO_INITIATOR - P2P-GO supports initiator capability + * @FINE_TIME_MEAS_P2PGO_RESPONDER - P2P-GO supports responder capability + * @FINE_TIME_MEAS_SAP_INITIATOR - SAP role, Initiator capability is supported + * @FINE_TIME_MEAS_SAP_RESPONDER - SAP role, Responder capability is supported + */ +enum fine_time_meas_mask { + FINE_TIME_MEAS_STA_INITIATOR = (1 << (0)), + FINE_TIME_MEAS_STA_RESPONDER = (1 << (1)), + FINE_TIME_MEAS_P2PCLI_INITIATOR = (1 << (2)), + FINE_TIME_MEAS_P2PCLI_RESPONDER = (1 << (3)), + FINE_TIME_MEAS_P2PGO_INITIATOR = (1 << (4)), + FINE_TIME_MEAS_P2PGO_RESPONDER = (1 << (5)), + FINE_TIME_MEAS_SAP_INITIATOR = (1 << (6)), + FINE_TIME_MEAS_SAP_RESPONDER = (1 << (7)), +}; + +/* number of neighbor reports that we can handle in Neighbor Report Response */ +#define MAX_SUPPORTED_NEIGHBOR_RPT 15 + +#ifdef SAP_AUTH_OFFLOAD +/* 80211 Pre-Share Key length */ +#define SIR_PSK_MAX_LEN 64 + +/* Definition for Software AP Auth Offload Security Type */ +enum tSirSecurityType +{ + eSIR_OFFLOAD_NONE, + eSIR_OFFLOAD_WPA2PSK_CCMP, +}; + +/* Structure for Software AP Auth Offload feature */ +struct tSirSapOffloadInfo +{ + uint32_t vdev_id; + bool sap_auth_offload_enable; + uint32_t sap_auth_offload_sec_type; + uint32_t key_len; + uint8_t key[SIR_PSK_MAX_LEN]; +}; +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * struct sblock_info - the basic block info structure + * + * @vdev_id: vdev id + * @reconnect_cnt: allowed connection fail count in duration + * @con_fail_duration: duration in which connection failure will be recorded + * @block_duration: duration in whcih client will be rejected to connect + * + * driver use this structure to configure fw client connect block info + */ +struct sblock_info { + uint32_t vdev_id; + uint32_t reconnect_cnt; + uint32_t con_fail_duration; + uint32_t block_duration; +}; + +/** + * struct stsf - the basic stsf structure + * + * @vdev_id: vdev id + * @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 vdev_id; + uint32_t tsf_low; + uint32_t tsf_high; +}; + +/** + * OCB structures + */ + +#define NUM_AC (4) +#define OCB_CHANNEL_MAX (5) + +typedef struct sir_qos_params { + uint8_t aifsn; + uint8_t cwmin; + uint8_t cwmax; +} sir_qos_params_t; + +/** + * struct sir_ocb_set_config_response + * @status: response status + */ +struct sir_ocb_set_config_response { + uint8_t status; +}; + +/** Callback for the dcc_stats_event */ +typedef void (*dcc_stats_event_callback_t)(void *hdd_ctx, uint32_t vdev_id, + uint32_t num_channels, uint32_t stats_per_channel_array_len, + const void *stats_per_channel_array); + +/** + * struct sir_ocb_config_channel + * @chan_freq: frequency of the channel + * @bandwidth: bandwidth of the channel, either 10 or 20 MHz + * @mac_address: MAC address assigned to this channel + * @qos_params: QoS parameters + * @max_pwr: maximum transmit power of the channel (dBm) + * @min_pwr: minimum transmit power of the channel (dBm) + * @reg_pwr: maximum transmit power specified by the regulatory domain (dBm) + * @antenna_max: maximum antenna gain specified by the regulatory domain (dB) + */ +struct sir_ocb_config_channel { + uint32_t chan_freq; + uint32_t bandwidth; + tSirMacAddr mac_address; + sir_qos_params_t qos_params[MAX_NUM_AC]; + uint32_t max_pwr; + uint32_t min_pwr; + uint8_t reg_pwr; + uint8_t antenna_max; + uint16_t flags; +}; + +/** + * OCB_CHANNEL_FLAG_NO_RX_HDR - Don't add the RX stats header to packets + * received on this channel. + */ +#define OCB_CHANNEL_FLAG_DISABLE_RX_STATS_HDR (1 << 0) + +/** + * struct sir_ocb_config_sched + * @chan_freq: frequency of the channel + * @total_duration: duration of the schedule + * @guard_interval: guard interval on the start of the schedule + */ +struct sir_ocb_config_sched { + uint32_t chan_freq; + uint32_t total_duration; + uint32_t guard_interval; +}; + +/** + * struct sir_ocb_config + * @session_id: session id + * @channel_count: number of channels + * @schedule_size: size of the channel schedule + * @flags: reserved + * @channels: array of OCB channels + * @schedule: array of OCB schedule elements + * @dcc_ndl_chan_list_len: size of the ndl_chan array + * @dcc_ndl_chan_list: array of dcc channel info + * @dcc_ndl_active_state_list_len: size of the active state array + * @dcc_ndl_active_state_list: array of active states + * @adapter: the OCB adapter + * @dcc_stats_callback: callback for the response event + */ +struct sir_ocb_config { + uint8_t session_id; + uint32_t channel_count; + uint32_t schedule_size; + uint32_t flags; + struct sir_ocb_config_channel *channels; + struct sir_ocb_config_sched *schedule; + uint32_t dcc_ndl_chan_list_len; + void *dcc_ndl_chan_list; + uint32_t dcc_ndl_active_state_list_len; + void *dcc_ndl_active_state_list; +}; + +/* The size of the utc time in bytes. */ +#define SIZE_UTC_TIME (10) +/* The size of the utc time error in bytes. */ +#define SIZE_UTC_TIME_ERROR (5) + +/** + * struct sir_ocb_utc + * @vdev_id: session id + * @utc_time: number of nanoseconds from Jan 1st 1958 + * @time_error: the error in the UTC time. All 1's for unknown + */ +struct sir_ocb_utc { + uint32_t vdev_id; + uint8_t utc_time[SIZE_UTC_TIME]; + uint8_t time_error[SIZE_UTC_TIME_ERROR]; +}; + +/** + * struct sir_ocb_timing_advert + * @vdev_id: session id + * @chan_freq: frequency on which to advertise + * @repeat_rate: the number of times it will send TA in 5 seconds + * @timestamp_offset: offset of the timestamp field in the TA frame + * @time_value_offset: offset of the time_value field in the TA frame + * @template_length: size in bytes of the TA frame + * @template_value: the TA frame + */ +struct sir_ocb_timing_advert { + uint32_t vdev_id; + uint32_t chan_freq; + uint32_t repeat_rate; + uint32_t timestamp_offset; + uint32_t time_value_offset; + uint32_t template_length; + uint8_t *template_value; +}; + +/** + * struct sir_ocb_get_tsf_timer_response + * @vdev_id: session id + * @timer_high: higher 32-bits of the timer + * @timer_low: lower 32-bits of the timer + */ +struct sir_ocb_get_tsf_timer_response { + uint32_t vdev_id; + uint32_t timer_high; + uint32_t timer_low; +}; + +/** + * struct sir_ocb_get_tsf_timer + * @vdev_id: session id + */ +struct sir_ocb_get_tsf_timer { + uint32_t vdev_id; +}; + +/** + * struct sir_dcc_get_stats_response + * @vdev_id: session id + * @num_channels: number of dcc channels + * @channel_stats_array_len: size in bytes of the stats array + * @channel_stats_array: the stats array + */ +struct sir_dcc_get_stats_response { + uint32_t vdev_id; + uint32_t num_channels; + uint32_t channel_stats_array_len; + void *channel_stats_array; +}; + +/** + * struct sir_dcc_get_stats + * @vdev_id: session id + * @channel_count: number of dcc channels + * @request_array_len: size in bytes of the request array + * @request_array: the request array + */ +struct sir_dcc_get_stats { + uint32_t vdev_id; + uint32_t channel_count; + uint32_t request_array_len; + void *request_array; +}; + +/** + * struct sir_dcc_clear_stats + * @vdev_id: session id + * @dcc_stats_bitmap: bitmap of clear option + */ +struct sir_dcc_clear_stats { + uint32_t vdev_id; + uint32_t dcc_stats_bitmap; +}; + +/** + * struct sir_dcc_update_ndl_response + * @vdev_id: session id + * @status: response status + */ +struct sir_dcc_update_ndl_response { + uint32_t vdev_id; + uint32_t status; +}; + +/** + * struct sir_dcc_update_ndl + * @vdev_id: session id + * @channel_count: number of channels to be updated + * @dcc_ndl_chan_list_len: size in bytes of the ndl_chan array + * @dcc_ndl_chan_list: the ndl_chan array + * @dcc_ndl_active_state_list_len: size in bytes of the active_state array + * @dcc_ndl_active_state_list: the active state array + */ +struct sir_dcc_update_ndl { + uint32_t vdev_id; + uint32_t channel_count; + uint32_t dcc_ndl_chan_list_len; + void *dcc_ndl_chan_list; + uint32_t dcc_ndl_active_state_list_len; + void *dcc_ndl_active_state_list; +}; + +/** + * struct sir_stats_avg_factor + * @vdev_id: session id + * @stats_avg_factor: average factor + */ +struct sir_stats_avg_factor { + uint8_t vdev_id; + uint16_t stats_avg_factor; +}; + +/** + * struct sir_guard_time_request + * @vdev_id: session id + * @guard_time: guard time + */ +struct sir_guard_time_request { + uint8_t vdev_id; + uint32_t guard_time; +}; + +/* Max number of rates allowed in Supported Rates IE */ +#define MAX_NUM_SUPPORTED_RATES (8) + +#define MAX_NUM_FW_SEGMENTS 4 + +/** + * struct fw_dump_seg_req - individual segment details + * @seg_id - segment id. + * @seg_start_addr_lo - lower address of the segment. + * @seg_start_addr_hi - higher address of the segment. + * @seg_length - length of the segment. + * @dst_addr_lo - lower address of the destination buffer. + * @dst_addr_hi - higher address of the destination buffer. + * + * This structure carries the information to firmware about the + * individual segments. This structure is part of firmware memory + * dump request. + */ +struct fw_dump_seg_req +{ + uint8_t seg_id; + uint32_t seg_start_addr_lo; + uint32_t seg_start_addr_hi; + uint32_t seg_length; + uint32_t dst_addr_lo; + uint32_t dst_addr_hi; +}; + +/** + * struct fw_dump_req - firmware memory dump request details. + * @request_id - request id. + * @num_seg - requested number of segments. + * @fw_dump_seg_req - individual segment information. + * + * This structure carries information about the firmware + * memory dump request. + */ +struct fw_dump_req +{ + uint32_t request_id; + uint32_t num_seg; + struct fw_dump_seg_req segment[MAX_NUM_FW_SEGMENTS]; +}; + +/** + * struct fw_dump_rsp - firmware dump response details. + * @request_id - request id. + * @dump_complete - copy completion status. + * + * This structure is used to store the firmware dump copy complete + * response from the firmware. + */ +struct fw_dump_rsp +{ + uint32_t request_id; + uint32_t dump_complete; +}; + +/** + * struct vdev_ie_info - IE info + * @vdev_i - vdev for which the IE is being sent + * @ie_id - ID of the IE + * @length - length of the IE data + * @data - IE data + * + * This structure is used to store the IE information. + */ +struct vdev_ie_info +{ + uint32_t vdev_id; + uint32_t ie_id; + uint32_t length; + uint8_t *data; +}; + +/* + * struct rssi_monitor_req - rssi monitoring + * @request_id: request id + * @session_id: session id + * @min_rssi: minimum rssi + * @max_rssi: maximum rssi + * @control: flag to indicate start or stop + */ +struct rssi_monitor_req { + uint32_t request_id; + uint32_t session_id; + int8_t min_rssi; + int8_t max_rssi; + bool control; +}; + +/** + * struct rssi_breach_event - rssi breached event structure + * @request_id: request id + * @session_id: session id + * @curr_rssi: current rssi + * @curr_bssid: current bssid + */ +struct rssi_breach_event { + uint32_t request_id; + uint32_t session_id; + int8_t curr_rssi; + v_MACADDR_t curr_bssid; +}; + +/** + * struct sir_sme_ext_change_chan_req - channel change request + * @message_type: message id + * @length: msg length + * @new_channel: new channel + * @session_id: session id + */ +struct sir_sme_ext_cng_chan_req +{ + uint16_t message_type; /* eWNI_SME_EXT_CHANGE_CHANNEL */ + uint16_t length; + uint32_t new_channel; + uint8_t session_id; +}; + +/** + * struct sir_sme_ext_change_chan_ind. + * @session_id: session id + * @new_channel: new channel to change + */ +struct sir_sme_ext_cng_chan_ind +{ + uint8_t session_id; + uint8_t new_channel; +}; + +/** + * enum powersave_qpower_mode: QPOWER modes + * @QPOWER_DISABLED: Qpower is disabled + * @QPOWER_ENABLED: Qpower is enabled + * @QPOWER_DUTY_CYCLING: Qpower is enabled with duty cycling + */ +enum powersave_qpower_mode { + QPOWER_DISABLED = 0, + QPOWER_ENABLED = 1, + QPOWER_DUTY_CYCLING = 2 +}; + +/** + * enum powersave_qpower_mode: powersave_mode + * @PS_NOT_SUPPORTED: Power save is not supported + * @PS_LEGACY_NODEEPSLEEP: Legacy power save enabled and deep sleep disabled + * @PS_QPOWER_NODEEPSLEEP: QPOWER enabled and deep sleep disabled + * @PS_LEGACY_DEEPSLEEP: Legacy power save enabled and deep sleep enabled + * @PS_QPOWER_DEEPSLEEP: QPOWER enabled and deep sleep enabled + * @PS_DUTY_CYCLING_QPOWER: QPOWER enabled in duty cycling mode + */ +enum powersave_mode { + PS_NOT_SUPPORTED = 0, + PS_LEGACY_NODEEPSLEEP = 1, + PS_QPOWER_NODEEPSLEEP = 2, + PS_LEGACY_DEEPSLEEP = 3, + PS_QPOWER_DEEPSLEEP = 4, + PS_DUTY_CYCLING_QPOWER = 5 +}; + + +/* + * struct udp_resp_offload - the basic info structure + * + * @vdev_id: vdev id + * @dest_port: specific UDP dest port + * @udp_payload_filter: specific UDP payload filter + * @udp_response_payload: response UDP oayload + * + * driver use this structure to configure fw specific + * udp offload filter and response udp info + */ +struct udp_resp_offload { + uint32_t vdev_id; + uint32_t enable; + uint32_t dest_port; + char udp_payload_filter[MAX_LEN_UDP_RESP_OFFLOAD]; + char udp_response_payload[MAX_LEN_UDP_RESP_OFFLOAD]; + +}; + +/** + * struct smps_force_mode_event - smps force mode event param + * @message_type: Type of message + * @length: length + * @vdev_id: vdev id + * @status: status of the SMPS force mode command + * + */ +struct sir_smps_force_mode_event { + uint16_t message_type; + uint16_t length; + uint8_t vdev_id; + uint8_t status; +}; +#endif /* __SIR_API_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacPropExts.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacPropExts.h new file mode 100644 index 000000000000..ed4809f691d8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacPropExts.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file sirMacPropExts.h contains the MAC protocol + * extensions to support ANI feature set. + * Author: Chandra Modumudi + * Date: 11/27/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __MAC_PROP_EXTS_H +#define __MAC_PROP_EXTS_H + +#include "sirTypes.h" +#include "sirApi.h" +#include "aniSystemDefs.h" + +/// EID (Element ID) definitions + +#define PROP_CAPABILITY_GET(bitname, value) \ + (((value) >> SIR_MAC_PROP_CAPABILITY_ ## bitname) & 1) + +#define IS_DOT11_MODE_HT(dot11Mode) \ + (((dot11Mode == WNI_CFG_DOT11_MODE_11N) || \ + (dot11Mode == WNI_CFG_DOT11_MODE_11N_ONLY) || \ + (dot11Mode == WNI_CFG_DOT11_MODE_11AC) || \ + (dot11Mode == WNI_CFG_DOT11_MODE_11AC_ONLY) || \ + (dot11Mode == WNI_CFG_DOT11_MODE_ALL)) ? TRUE: FALSE) + +#ifdef WLAN_FEATURE_11AC +#define IS_DOT11_MODE_VHT(dot11Mode) \ + (((dot11Mode == WNI_CFG_DOT11_MODE_11AC) || \ + (dot11Mode == WNI_CFG_DOT11_MODE_11AC_ONLY) || \ + (dot11Mode == WNI_CFG_DOT11_MODE_ALL)) ? TRUE: FALSE) +#endif + +#define IS_DOT11_MODE_11B(dot11Mode) \ + ((dot11Mode == WNI_CFG_DOT11_MODE_11B) ? TRUE : FALSE) + +#define IS_BSS_VHT_CAPABLE(vhtCaps) \ + ((vhtCaps).present && \ + ((vhtCaps).rxMCSMap != 0xFFFF) && \ + ((vhtCaps).txMCSMap != 0xFFFF)) + +#define WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ 0 +#define WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ 1 +#define WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ 2 +#define WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ 3 + + +/// Proprietary IE definition +typedef struct sSirMacPropIE +{ + tANI_U8 elementID; // SIR_MAC_ANI_PROP_IE_EID + tANI_U8 length; + tANI_U8 oui[3]; // ANI_OUI for Airgo products + tANI_U8 info[1]; +} tSirMacPropIE, *tpSirMacPropIE; + + +typedef struct sSirMacPropRateSet +{ + tANI_U8 numPropRates; + tANI_U8 propRate[8]; +} tSirMacPropRateSet, *tpSirMacPropRateSet; + + +#define SIR_PROP_VERSION_STR_MAX 20 +typedef struct sSirMacPropVersion +{ + tANI_U32 chip_rev; // board, chipset info + tANI_U8 card_type; // Type of Card + tANI_U8 build_version[SIR_PROP_VERSION_STR_MAX]; //build version string +} tSirMacPropVersion, *tpSirMacPropVersion; + + +/* Default value for gLimRestoreCBNumScanInterval */ +#define LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT 2 + +// generic proprietary IE structure definition +typedef struct sSirPropIEStruct +{ + tANI_U8 propRatesPresent:1; + tANI_U8 apNamePresent:1; + tANI_U8 loadBalanceInfoPresent:1; + tANI_U8 versionPresent:1; + tANI_U8 edcaParamPresent:1; + tANI_U8 capabilityPresent:1; + tANI_U8 propChannelSwitchPresent:1; + tANI_U8 triggerStaScanPresent:1; + tANI_U8 rsvd:8; + + + tSirMacPropRateSet propRates; + tAniApName apName; // used in beacon/probe only + tSirAlternateRadioInfo alternateRadio; // used in assoc response only + tANI_U16 capability; // capability bit map + tSirMacPropVersion version; + tSirMacEdcaParamSetIE edca; + tANI_U8 triggerStaScanEnable; + + +} tSirPropIEStruct, *tpSirPropIEStruct; + + + +#endif /* __MAC_PROP_EXTS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h new file mode 100644 index 000000000000..9a01efdc2db3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h @@ -0,0 +1,2326 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file sirMacProtDef.h contains the MAC/PHY protocol + * definitions used across various projects. + * Author: Chandra Modumudi + * Date: 02/27/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __MAC_PROT_DEFS_H +#define __MAC_PROT_DEFS_H + +#include "palTypes.h" +#include "sirTypes.h" +#include "wniCfgSta.h" + + +///Capability information related +#define CAPABILITY_INFO_DELAYED_BA_BIT 14 +#define CAPABILITY_INFO_IMMEDIATE_BA_BIT 15 + +/// 11h MAC defaults +#define SIR_11A_CHANNEL_BEGIN 34 +#define SIR_11A_CHANNEL_END 165 +#define SIR_11B_CHANNEL_BEGIN 1 +#define SIR_11B_CHANNEL_END 14 +#define SIR_11A_FREQUENCY_OFFSET 4 +#define SIR_11B_FREQUENCY_OFFSET 1 +#define SIR_11P_CHANNEL_BEGIN 170 +#define SIR_11P_CHANNEL_END 184 + +/// Current version of 802.11 +#define SIR_MAC_PROTOCOL_VERSION 0 + +// Frame Type definitions + +#define SIR_MAC_MGMT_FRAME 0x0 +#define SIR_MAC_CTRL_FRAME 0x1 +#define SIR_MAC_DATA_FRAME 0x2 + +#define SIR_MAC_FRAME_TYPE_START 0x0 +#define SIR_MAC_FRAME_TYPE_END 0x3 + +// Control frame subtype definitions + +#define SIR_MAC_CTRL_RR 4 +#define SIR_MAC_CTRL_BAR 8 +#define SIR_MAC_CTRL_BA 9 +#define SIR_MAC_CTRL_PS_POLL 10 +#define SIR_MAC_CTRL_RTS 11 +#define SIR_MAC_CTRL_CTS 12 +#define SIR_MAC_CTRL_ACK 13 +#define SIR_MAC_CTRL_CF_END 14 +#define SIR_MAC_CTRL_CF_END_ACK 15 + +#define SIR_MAC_MAX_DURATION_MICRO_SECONDS 32767 + +// Data frame subtype definitions +#define SIR_MAC_DATA_DATA 0 +#define SIR_MAC_DATA_DATA_ACK 1 +#define SIR_MAC_DATA_DATA_POLL 2 +#define SIR_MAC_DATA_DATA_ACK_POLL 3 +#define SIR_MAC_DATA_NULL 4 +#define SIR_MAC_DATA_NULL_ACK 5 +#define SIR_MAC_DATA_NULL_POLL 6 +#define SIR_MAC_DATA_NULL_ACK_POLL 7 +#define SIR_MAC_DATA_QOS_DATA 8 +#define SIR_MAC_DATA_QOS_DATA_ACK 9 +#define SIR_MAC_DATA_QOS_DATA_POLL 10 +#define SIR_MAC_DATA_QOS_DATA_ACK_POLL 11 +#define SIR_MAC_DATA_QOS_NULL 12 +#define SIR_MAC_DATA_QOS_NULL_ACK 13 +#define SIR_MAC_DATA_QOS_NULL_POLL 14 +#define SIR_MAC_DATA_QOS_NULL_ACK_POLL 15 + +#define SIR_MAC_FRAME_SUBTYPE_START 0 +#define SIR_MAC_FRAME_SUBTYPE_END 16 + +#define SIR_MAC_DATA_QOS_MASK 8 +#define SIR_MAC_DATA_NULL_MASK 4 +#define SIR_MAC_DATA_POLL_MASK 2 +#define SIR_MAC_DATA_ACK_MASK 1 + +// Management frame subtype definitions + +#define SIR_MAC_MGMT_ASSOC_REQ 0x0 +#define SIR_MAC_MGMT_ASSOC_RSP 0x1 +#define SIR_MAC_MGMT_REASSOC_REQ 0x2 +#define SIR_MAC_MGMT_REASSOC_RSP 0x3 +#define SIR_MAC_MGMT_PROBE_REQ 0x4 +#define SIR_MAC_MGMT_PROBE_RSP 0x5 +#define SIR_MAC_MGMT_TIME_ADVERT 0x6 +#define SIR_MAC_MGMT_BEACON 0x8 +#define SIR_MAC_MGMT_ATIM 0x9 +#define SIR_MAC_MGMT_DISASSOC 0xA +#define SIR_MAC_MGMT_AUTH 0xB +#define SIR_MAC_MGMT_DEAUTH 0xC +#define SIR_MAC_MGMT_ACTION 0xD +#define SIR_MAC_MGMT_RESERVED15 0xF + +// Action frame categories + +#define SIR_MAC_ACTION_SPECTRUM_MGMT 0 +#define SIR_MAC_ACTION_QOS_MGMT 1 +#define SIR_MAC_ACTION_DLP 2 +#define SIR_MAC_ACTION_BLKACK 3 +#define SIR_MAC_ACTION_PUBLIC_USAGE 4 +#define SIR_MAC_ACTION_RRM 5 +#define SIR_MAC_ACTION_FAST_BSS_TRNST 6 +#define SIR_MAC_ACTION_HT 7 +#define SIR_MAC_ACTION_SA_QUERY 8 +#define SIR_MAC_ACTION_PROT_DUAL_PUB 9 +#define SIR_MAC_ACTION_WNM 10 +#define SIR_MAC_ACTION_UNPROT_WNM 11 +#define SIR_MAC_ACTION_TDLS 12 +#define SIR_MAC_ACITON_MESH 13 +#define SIR_MAC_ACTION_MHF 14 +#define SIR_MAC_SELF_PROTECTED 15 +#define SIR_MAC_ACTION_WME 17 +#define SIR_MAC_ACTION_FST 18 +#define SIR_MAC_ACTION_VHT 21 + +// QoS management action codes + +#define SIR_MAC_QOS_ADD_TS_REQ 0 +#define SIR_MAC_QOS_ADD_TS_RSP 1 +#define SIR_MAC_QOS_DEL_TS_REQ 2 +#define SIR_MAC_QOS_SCHEDULE 3 +#define SIR_MAC_QOS_MAP_CONFIGURE 4 +// and these are proprietary +#define SIR_MAC_QOS_DEF_BA_REQ 4 +#define SIR_MAC_QOS_DEF_BA_RSP 5 +#define SIR_MAC_QOS_DEL_BA_REQ 6 +#define SIR_MAC_QOS_DEL_BA_RSP 7 + +#define SIR_MAC_ACTION_CHANNEL_SWITCH_ID 4 + + + +//RRM related. +//Refer IEEE Std 802.11k-2008, Section 7.3.2.21, table 7.29 +#if defined WLAN_FEATURE_VOWIFI + +#define SIR_MAC_RRM_CHANNEL_LOAD_TYPE 3 +#define SIR_MAC_RRM_NOISE_HISTOGRAM_BEACON 4 +#define SIR_MAC_RRM_BEACON_TYPE 5 +#define SIR_MAC_RRM_FRAME_TYPE 6 +#define SIR_MAC_RRM_STA_STATISTICS_TYPE 7 +#define SIR_MAC_RRM_LCI_TYPE 8 +#define SIR_MAC_RRM_TSM_TYPE 9 +#define SIR_MAC_RRM_LOCATION_CIVIC_TYPE 11 +#define SIR_MAC_RRM_FINE_TIME_MEAS_TYPE 16 + +//RRM action codes +#define SIR_MAC_RRM_RADIO_MEASURE_REQ 0 +#define SIR_MAC_RRM_RADIO_MEASURE_RPT 1 +#define SIR_MAC_RRM_LINK_MEASUREMENT_REQ 2 +#define SIR_MAC_RRM_LINK_MEASUREMENT_RPT 3 +#define SIR_MAC_RRM_NEIGHBOR_REQ 4 +#define SIR_MAC_RRM_NEIGHBOR_RPT 5 + +#endif + +//VHT Action Field +#ifdef WLAN_FEATURE_11AC +#define SIR_MAC_VHT_GID_NOTIFICATION 1 +#define SIR_MAC_VHT_OPMODE_NOTIFICATION 2 +#endif + +// HT Action Field Codes +#define SIR_MAC_SM_POWER_SAVE 1 + +// DLP action frame types +#define SIR_MAC_DLP_REQ 0 +#define SIR_MAC_DLP_RSP 1 +#define SIR_MAC_DLP_TEARDOWN 2 + +// block acknowledgement action frame types +#define SIR_MAC_BLKACK_ADD_REQ 0 +#define SIR_MAC_BLKACK_ADD_RSP 1 +#define SIR_MAC_BLKACK_DEL 2 +#define SIR_MAC_ACTION_VENDOR_SPECIFIC 9 +#define SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY 0x7F +#define SIR_MAC_ACTION_P2P_SUBTYPE_PRESENCE_RSP 2 + +// Public Action for 20/40 BSS Coexistence +#define SIR_MAC_ACTION_2040_BSS_COEXISTENCE 0 +#define SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID 4 + + +#ifdef WLAN_FEATURE_11W +//11w SA query request/response action frame category code +#define SIR_MAC_SA_QUERY_REQ 0 +#define SIR_MAC_SA_QUERY_RSP 1 +#endif + +#ifdef FEATURE_WLAN_TDLS +#define SIR_MAC_TDLS_SETUP_REQ 0 +#define SIR_MAC_TDLS_SETUP_RSP 1 +#define SIR_MAC_TDLS_SETUP_CNF 2 +#define SIR_MAC_TDLS_TEARDOWN 3 +#define SIR_MAC_TDLS_PEER_TRAFFIC_IND 4 +#define SIR_MAC_TDLS_CH_SWITCH_REQ 5 +#define SIR_MAC_TDLS_CH_SWITCH_RSP 6 +#define SIR_MAC_TDLS_PEER_TRAFFIC_RSP 9 +#define SIR_MAC_TDLS_DIS_REQ 10 +#define SIR_MAC_TDLS_DIS_RSP 14 +#endif + +/* WNM Action field values; IEEE Std 802.11-2012, 8.5.14.1, Table 8-250 */ +#define SIR_MAC_WNM_BSS_TM_QUERY 6 +#define SIR_MAC_WNM_BSS_TM_REQUEST 7 +#define SIR_MAC_WNM_BSS_TM_RESPONSE 8 +#define SIR_MAC_WNM_NOTIF_REQUEST 26 +#define SIR_MAC_WNM_NOTIF_RESPONSE 27 + +#define SIR_MAC_MAX_RANDOM_LENGTH 2306 + +//----------------------------------------------------------------------------- +// EID (Element ID) definitions +// and their min/max lengths +//----------------------------------------------------------------------------- + +#define SIR_MAC_SSID_EID 0 +#define SIR_MAC_SSID_EID_MIN 0 +#define SIR_MAC_SSID_EID_MAX 32 +#define SIR_MAC_RATESET_EID 1 +#define SIR_MAC_RATESET_EID_MIN 1 +#define SIR_MAC_RATESET_EID_MAX 12 +#define SIR_MAC_FH_PARAM_SET_EID 2 +#define SIR_MAC_FH_PARAM_SET_EID_MIN 5 +#define SIR_MAC_FH_PARAM_SET_EID_MAX 5 +#define SIR_MAC_DS_PARAM_SET_EID 3 +#define SIR_MAC_DS_PARAM_SET_EID_MIN 1 +#define SIR_MAC_DS_PARAM_SET_EID_MAX 1 +#define SIR_MAC_CF_PARAM_SET_EID 4 +#define SIR_MAC_CF_PARAM_SET_EID_MIN 6 +#define SIR_MAC_CF_PARAM_SET_EID_MAX 6 +#define SIR_MAC_TIM_EID 5 +#define SIR_MAC_TIM_EID_MIN 3 +#define SIR_MAC_TIM_EID_MAX 254 +#define SIR_MAC_IBSS_PARAM_SET_EID 6 +#define SIR_MAC_IBSS_PARAM_SET_EID_MIN 2 +#define SIR_MAC_IBSS_PARAM_SET_EID_MAX 2 +#define SIR_MAC_COUNTRY_EID 7 +#define SIR_MAC_COUNTRY_EID_MIN 6 +#define SIR_MAC_COUNTRY_EID_MAX 254 +#define SIR_MAC_FH_PARAMS_EID 8 +#define SIR_MAC_FH_PARAMS_EID_MIN 4 +#define SIR_MAC_FH_PARAMS_EID_MAX 4 +#define SIR_MAC_FH_PATTERN_EID 9 +#define SIR_MAC_FH_PATTERN_EID_MIN 4 +#define SIR_MAC_FH_PATTERN_EID_MAX 254 +#define SIR_MAC_REQUEST_EID 10 +#define SIR_MAC_REQUEST_EID_MIN 1 +#define SIR_MAC_REQUEST_EID_MAX 255 +#define SIR_MAC_QBSS_LOAD_EID 11 +#define SIR_MAC_QBSS_LOAD_EID_MIN 5 +#define SIR_MAC_QBSS_LOAD_EID_MAX 5 +#define SIR_MAC_EDCA_PARAM_SET_EID 12 // EDCA parameter set +#define SIR_MAC_EDCA_PARAM_SET_EID_MIN 18 +#define SIR_MAC_EDCA_PARAM_SET_EID_MAX 20 +#define SIR_MAC_TSPEC_EID 13 +#define SIR_MAC_TSPEC_EID_MIN 55 +#define SIR_MAC_TSPEC_EID_MAX 55 +#define SIR_MAC_TCLAS_EID 14 +#define SIR_MAC_TCLAS_EID_MIN 4 +#define SIR_MAC_TCLAS_EID_MAX 255 +#define SIR_MAC_QOS_SCHEDULE_EID 15 +#define SIR_MAC_QOS_SCHEDULE_EID_MIN 14 +#define SIR_MAC_QOS_SCHEDULE_EID_MAX 14 +#define SIR_MAC_CHALLENGE_TEXT_EID 16 +#define SIR_MAC_CHALLENGE_TEXT_EID_MIN 1 +#define SIR_MAC_CHALLENGE_TEXT_EID_MAX 253 +// reserved 17-31 +#define SIR_MAC_PWR_CONSTRAINT_EID 32 +#define SIR_MAC_PWR_CONSTRAINT_EID_MIN 1 +#define SIR_MAC_PWR_CONSTRAINT_EID_MAX 1 +#define SIR_MAC_PWR_CAPABILITY_EID 33 +#define SIR_MAC_PWR_CAPABILITY_EID_MIN 2 +#define SIR_MAC_PWR_CAPABILITY_EID_MAX 2 +#define SIR_MAC_TPC_REQ_EID 34 +#define SIR_MAC_TPC_REQ_EID_MIN 0 +#define SIR_MAC_TPC_REQ_EID_MAX 255 +// SIR_MAC_EXTENDED_CAP_EID 35 +#define SIR_MAC_TPC_RPT_EID 35 +#define SIR_MAC_TPC_RPT_EID_MIN 2 +#define SIR_MAC_TPC_RPT_EID_MAX 2 +#define SIR_MAC_SPRTD_CHNLS_EID 36 +#define SIR_MAC_SPRTD_CHNLS_EID_MIN 2 +#define SIR_MAC_SPRTD_CHNLS_EID_MAX 254 +#define SIR_MAC_CHNL_SWITCH_ANN_EID 37 +#define SIR_MAC_CHNL_SWITCH_ANN_EID_MIN 3 +#define SIR_MAC_CHNL_SWITCH_ANN_EID_MAX 3 +#define SIR_MAC_MEAS_REQ_EID 38 +#define SIR_MAC_MEAS_REQ_EID_MIN 3 +#define SIR_MAC_MEAS_REQ_EID_MAX 255 +#define SIR_MAC_MEAS_RPT_EID 39 +#define SIR_MAC_MEAS_RPT_EID_MIN 3 +#define SIR_MAC_MEAS_RPT_EID_MAX 255 +#define SIR_MAC_QUIET_EID 40 +#define SIR_MAC_QUIET_EID_MIN 6 +#define SIR_MAC_QUIET_EID_MAX 6 +#define SIR_MAC_IBSS_DFS_EID 41 +#define SIR_MAC_IBSS_DFS_EID_MIN 7 +#define SIR_MAC_IBSS_DFS_EID_MAX 255 +#define SIR_MAC_ERP_INFO_EID 42 +#define SIR_MAC_ERP_INFO_EID_MIN 0 +#define SIR_MAC_ERP_INFO_EID_MAX 255 +#define SIR_MAC_TS_DELAY_EID 43 +#define SIR_MAC_TS_DELAY_EID_MIN 4 +#define SIR_MAC_TS_DELAY_EID_MAX 4 +#define SIR_MAC_TCLAS_PROC_EID 44 +#define SIR_MAC_TCLAS_PROC_EID_MIN 1 +#define SIR_MAC_TCLAS_PROC_EID_MAX 1 +#define SIR_MAC_QOS_CAPABILITY_EID 46 +#define SIR_MAC_QOS_CAPABILITY_EID_MIN 1 +#define SIR_MAC_QOS_CAPABILITY_EID_MAX 1 +#define SIR_MAC_RSN_EID 48 +#define SIR_MAC_RSN_EID_MIN 4 +#define SIR_MAC_RSN_EID_MAX 254 + +//using reserved EID for Qos Action IE for now, +//need to check 11e spec for the actual EID +#define SIR_MAC_QOS_ACTION_EID 49 +#define SIR_MAC_QOS_ACTION_EID_MIN 4 +#define SIR_MAC_QOS_ACTION_EID_MAX 255 +#define SIR_MAC_EXTENDED_RATE_EID 50 +#define SIR_MAC_EXTENDED_RATE_EID_MIN 0 +#define SIR_MAC_EXTENDED_RATE_EID_MAX 255 +#define SIR_MAC_OPERATING_CLASS_EID 59 +#define SIR_MAC_OPERATING_CLASS_EID_MIN 2 +#define SIR_MAC_OPERATING_CLASS_EID_MAX 253 +#define SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID 60 +#define SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID_MIN 0 +#define SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID_MAX 255 + + +// reserved 51-69 +#define SIR_MAC_RM_ENABLED_CAPABILITY_EID 70 +#define SIR_MAC_RM_ENABLED_CAPABILITY_EID_MIN 5 +#define SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX 5 +// reserved 71-220 +#define SIR_MAC_WPA_EID 221 +#define SIR_MAC_WPA_EID_MIN 0 +#define SIR_MAC_WPA_EID_MAX 255 + +#define SIR_MAC_EID_VENDOR 221 + +#define SIR_MAC_WAPI_EID 68 + +// reserved 222-254 +#define SIR_MAC_HT_CAPABILITIES_EID 45 +#define SIR_MAC_HT_CAPABILITIES_EID_MIN 0 +#define SIR_MAC_HT_CAPABILITIES_EID_MAX 255 +#define SIR_MAC_HT_INFO_EID 61 +#define SIR_MAC_HT_INFO_EID_MIN 0 +#define SIR_MAC_HT_INFO_EID_MAX 255 + +#ifdef WLAN_FEATURE_11AC +#define SIR_MAC_VHT_CAPABILITIES_EID 191 +#define SIR_MAC_VHT_OPERATION_EID 192 +#define SIR_MAC_VHT_EXT_BSS_LOAD_EID 193 +#define SIR_MAC_VHT_OPMODE_EID 199 +#endif +#define SIR_MAC_MAX_SUPPORTED_MCS_SET 16 + +#define VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390 +#define VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390 +#define VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780 +#define VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780 + +#define VHT_MCS_1x1 0xFFFC +#define VHT_MCS_2x2 0xFFF3 + +#define NSS_1x1_MODE 1 +#define NSS_2x2_MODE 2 + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define SIR_MAC_QCOM_VENDOR_EID 200 +#define SIR_MAC_QCOM_VENDOR_OUI "\x00\xA0\xC6" +#define SIR_MAC_QCOM_VENDOR_SIZE 3 +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/// Workaround IE to change beacon length when it is 4*n+1 +#define SIR_MAC_ANI_WORKAROUND_EID 255 +#define SIR_MAC_ANI_WORKAROUND_EID_MIN 0 +#define SIR_MAC_ANI_WORKAROUND_EID_MAX 255 + +#define SIR_MAC_MAX_ADD_IE_LENGTH 500 +/// Maximum length of each IE +#define SIR_MAC_MAX_IE_LENGTH 255 + +/// Maximum length of each IE +#define SIR_MAC_RSN_IE_MAX_LENGTH 255 +#define SIR_MAC_WPA_IE_MAX_LENGTH 255 +/// Minimum length of each IE +#define SIR_MAC_RSN_IE_MIN_LENGTH 2 +#define SIR_MAC_WPA_IE_MIN_LENGTH 6 + +#ifdef FEATURE_WLAN_ESE +#define ESE_VERSION_4 4 +#define ESE_VERSION_SUPPORTED ESE_VERSION_4 + +// When station sends Radio Management Cap. +// State should be normal=1 +// Mbssid Mask should be 0 +#define RM_STATE_NORMAL 1 +#endif + +#define SIR_MAC_OUI_VERSION_1 1 + +// OUI and type definition for WPA IE in network byte order +#define SIR_MAC_WPA_OUI 0x01F25000 +#define SIR_MAC_WME_OUI 0x02F25000 +#define SIR_MAC_WSM_OUI SIR_MAC_WME_OUI +#define SIR_MAC_WSC_OUI "\x00\x50\xf2\x04" +#define SIR_MAC_WSC_OUI_SIZE 4 +#define SIR_MAC_P2P_OUI "\x50\x6f\x9a\x09" +#define SIR_MAC_P2P_OUI_SIZE 4 +#define SIR_P2P_NOA_ATTR 12 +#define SIR_MAX_NOA_ATTR_LEN 31 +#define SIR_MAX_NOA_DESCR 2 +#define SIR_P2P_IE_HEADER_LEN 6 + +#define SIR_MAC_CISCO_OUI "\x00\x40\x96" +#define SIR_MAC_CISCO_OUI_SIZE 3 + +// min size of wme oui header: oui(3) + type + subtype + version +#define SIR_MAC_OUI_WME_HDR_MIN 6 + +// OUI subtype and their lengths +#define SIR_MAC_OUI_SUBTYPE_WME_INFO 0 +#define SIR_MAC_OUI_WME_INFO_MIN 7 +#define SIR_MAC_OUI_WME_INFO_MAX 7 + +#define SIR_MAC_OUI_SUBTYPE_WME_PARAM 1 +#define SIR_MAC_OUI_WME_PARAM_MIN 24 +#define SIR_MAC_OUI_WME_PARAM_MAX 24 + +#define SIR_MAC_OUI_SUBTYPE_WME_TSPEC 2 +#define SIR_MAC_OUI_WME_TSPEC_MIN 61 +#define SIR_MAC_OUI_WME_TSPEC_MAX 61 + +#define SIR_MAC_OUI_SUBTYPE_WSM_TSPEC 2 // same as WME TSPEC +#define SIR_MAC_OUI_WSM_TSPEC_MIN 61 +#define SIR_MAC_OUI_WSM_TSPEC_MAX 61 + +// reserved subtypes 3-4 +// WSM capability +#define SIR_MAC_OUI_SUBTYPE_WSM_CAPABLE 5 +#define SIR_MAC_OUI_WSM_CAPABLE_MIN 7 +#define SIR_MAC_OUI_WSM_CAPABLE_MAX 7 +// WSM classifier +#define SIR_MAC_OUI_SUBTYPE_WSM_TCLAS 6 +#define SIR_MAC_OUI_WSM_TCLAS_MIN 10 +#define SIR_MAC_OUI_WSM_TCLAS_MAX 255 +// classifier processing element +#define SIR_MAC_OUI_SUBTYPE_WSM_TCLASPROC 7 +#define SIR_MAC_OUI_WSM_TCLASPROC_MIN 7 +#define SIR_MAC_OUI_WSM_TCLASPROC_MAX 7 +// tspec delay element +#define SIR_MAC_OUI_SUBTYPE_WSM_TSDELAY 8 +#define SIR_MAC_OUI_WSM_TSDELAY_MIN 10 +#define SIR_MAC_OUI_WSM_TSDELAY_MAX 10 +// schedule element +#define SIR_MAC_OUI_SUBTYPE_WSM_SCHEDULE 9 +#define SIR_MAC_OUI_WSM_SCHEDULE_MIN 20 +#define SIR_MAC_OUI_WSM_SCHEDULE_MAX 20 + +#ifdef WLAN_NS_OFFLOAD +#define SIR_MAC_NS_OFFLOAD_SIZE 1 //support only one IPv6 offload +/* Number of target IP V6 addresses for NS offload */ +#define SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA 16 +#define SIR_MAC_IPV6_ADDR_LEN 16 +#define SIR_IPV6_ADDR_VALID 1 +#endif //WLAN_NS_OFFLOAD +#define SIR_MAC_ARP_OFFLOAD_SIZE 1 + +// total length of an Info element including T/L fields +#define EID_LEN(eid) (2 + (eid)) + +// support for radar Detect, Channel Switch +#define CHANNEL_SWITCH_MAX_FRAME_SIZE 256 + + +// Length of Channel Switch related message +#define SIR_SME_CHANNEL_SWITCH_SIZE (sizeof(tANI_U8) + 2 *sizeof(tANI_U16) + sizeof(tANI_U32) + sizeof(ePhyChanBondState)) +#define SIR_CHANNEL_SWITCH_IE_SIZE EID_LEN(SIR_MAC_CHNL_SWITCH_ANN_EID_MIN) + +//Measurement Request/Report messages +#define SIR_MEAS_REQ_FIELD_SIZE 11 +#define SIR_MEAS_REQ_IE_SIZE (5 + SIR_MEAS_REQ_FIELD_SIZE) +#define SIR_MEAS_REQ_ACTION_FRAME_SIZE (3 + SIR_MEAS_REQ_IE_SIZE) +#define SIR_MEAS_MAX_FRAME_SIZE 256 +#define SIR_MEAS_REPORT_MIN_FRAME_SIZE (3 + EID_LEN(SIR_MAC_MEAS_RPT_EID_MIN)) + +#define SIR_MAC_SET_MEAS_REQ_ENABLE(x) (((tANI_U8) x) | 2) +#define SIR_MAC_SET_MEAS_REQ_REQUEST(x) (((tANI_U8) x) | 4) +#define SIR_MAC_SET_MEAS_REQ_REPORT(x) (((tANI_U8) x) | 8) + +#define SIR_MAC_SET_MEAS_REPORT_LATE(x) (((tANI_U8) x) | 1) +#define SIR_MAC_SET_MEAS_REPORT_INCAPABLE(x) (((tANI_U8) x) | 2) +#define SIR_MAC_SET_MEAS_REPORT_REFUSE(x) (((tANI_U8) x) | 4) + +// Length of TPC Request Action Frame +#define SIR_TPC_REQ_ACTION_FRAME_SIZE (3 + EID_LEN(SIR_MAC_TPC_REQ_EID_MIN)) +#define SIR_TPC_REPORT_ACTION_FRAME_SIZE (3 + EID_LEN(SIR_MAC_TPC_RPT_EID_MIN)) +#define SIR_TPC_MAX_FRAME_SIZE 256 +//----------------------------------------------------------------------------- + +// OFFSET definitions for fixed fields in Management frames + +// Beacon/Probe Response offsets +#define SIR_MAC_TS_OFFSET 0 +#define SIR_MAC_BEACON_INT_OFFSET 8 // Beacon Interval offset +#define SIR_MAC_B_PR_CAPAB_OFFSET 10 +#define SIR_MAC_B_PR_SSID_OFFSET 12 + +// Association/Reassociation offsets +#define SIR_MAC_ASSOC_CAPAB_OFFSET 0 +#define SIR_MAC_LISTEN_INT_OFFSET 2 // Listen Interval offset +#define SIR_MAC_ASSOC_SSID_OFFSET 4 +#define SIR_MAC_CURRENT_AP_OFFSET 4 +#define SIR_MAC_REASSOC_SSID_OFFSET 10 +#define SIR_MAC_ASSOC_STATUS_CODE_OFFSET 2 +#define SIR_MAC_ASSOC_AID_OFFSET 4 +#define SIR_MAC_ASSOC_RSP_RATE_OFFSET 6 + +// Disassociation/Deauthentication offsets +#define SIR_MAC_REASON_CODE_OFFSET 0 + +// Probe Request offset +#define SIR_MAC_PROBE_REQ_SSID_OFFSET 0 + +// Authentication offsets +#define SIR_MAC_AUTH_ALGO_OFFSET 0 +#define SIR_MAC_AUTH_XACT_SEQNUM_OFFSET 2 +#define SIR_MAC_AUTH_STATUS_CODE_OFFSET 4 +#define SIR_MAC_AUTH_CHALLENGE_OFFSET 6 + +/// Transaction sequence number definitions (used in Authentication frames) +#define SIR_MAC_AUTH_FRAME_1 1 +#define SIR_MAC_AUTH_FRAME_2 2 +#define SIR_MAC_AUTH_FRAME_3 3 +#define SIR_MAC_AUTH_FRAME_4 4 + +/// Protocol defined MAX definitions +#define SIR_MAC_ADDR_LENGTH 6 +#define SIR_MAC_MAX_SSID_LENGTH 32 +#define SIR_MAC_MAX_NUMBER_OF_RATES 12 +#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 128 +#define SIR_MAC_WEP_IV_LENGTH 4 +#define SIR_MAC_WEP_ICV_LENGTH 4 + +/// MAX key length when ULA is used +#define SIR_MAC_MAX_KEY_LENGTH 32 + +/// Macro definitions for get/set on FC fields +#define SIR_MAC_GET_PROT_VERSION(x) ((((tANI_U16) x) & 0x0300) >> 8) +#define SIR_MAC_GET_FRAME_TYPE(x) ((((tANI_U16) x) & 0x0C00) >> 8) +#define SIR_MAC_GET_FRAME_SUB_TYPE(x) ((((tANI_U16) x) & 0xF000) >> 12) +#define SIR_MAC_GET_WEP_BIT_IN_FC(x) (((tANI_U16) x) & 0x0040) +#define SIR_MAC_SET_PROT_VERSION(x) ((tANI_U16) x) +#define SIR_MAC_SET_FRAME_TYPE(x) (((tANI_U16) x) << 2) +#define SIR_MAC_SET_FRAME_SUB_TYPE(x) (((tANI_U16) x) << 4) +#define SIR_MAC_SET_WEP_BIT_IN_FC(x) (((tANI_U16) x) << 14) + +/// Macro definitions for get/set on capabilityInfo bits +#define SIR_MAC_GET_ESS(x) (((tANI_U16) x) & 0x0001) +#define SIR_MAC_GET_IBSS(x) ((((tANI_U16) x) & 0x0002) >> 1) +#define SIR_MAC_GET_CF_POLLABLE(x) ((((tANI_U16) x) & 0x0004) >> 2) +#define SIR_MAC_GET_CF_POLL_REQ(x) ((((tANI_U16) x) & 0x0008) >> 3) +#define SIR_MAC_GET_PRIVACY(x) ((((tANI_U16) x) & 0x0010) >> 4) +#define SIR_MAC_GET_SHORT_PREAMBLE(x) ((((tANI_U16) x) & 0x0020) >> 5) +#define SIR_MAC_GET_SPECTRUM_MGMT(x) ((((tANI_U16) x) & 0x0100) >> 8) +#define SIR_MAC_GET_QOS(x) ((((tANI_U16) x) & 0x0200) >> 9) +#define SIR_MAC_GET_SHORT_SLOT_TIME(x) ((((tANI_U16) x) & 0x0400) >> 10) +#define SIR_MAC_GET_APSD(x) ((((tANI_U16) x) & 0x0800) >> 11) +#if defined WLAN_FEATURE_VOWIFI +#define SIR_MAC_GET_RRM(x) ((((tANI_U16) x) & 0x1000) >> 12) +#endif +#define SIR_MAC_GET_BLOCK_ACK(x) ((((tANI_U16) x) & 0xc000) >> CAPABILITY_INFO_DELAYED_BA_BIT) +#define SIR_MAC_SET_ESS(x) (((tANI_U16) x) | 0x0001) +#define SIR_MAC_SET_IBSS(x) (((tANI_U16) x) | 0x0002) +#define SIR_MAC_SET_CF_POLLABLE(x) (((tANI_U16) x) | 0x0004) +#define SIR_MAC_SET_CF_POLL_REQ(x) (((tANI_U16) x) | 0x0008) +#define SIR_MAC_SET_PRIVACY(x) (((tANI_U16) x) | 0x0010) +#define SIR_MAC_SET_SHORT_PREAMBLE(x) (((tANI_U16) x) | 0x0020) +#define SIR_MAC_SET_SPECTRUM_MGMT(x) (((tANI_U16) x) | 0x0100) +#define SIR_MAC_SET_QOS(x) (((tANI_U16) x) | 0x0200) +#define SIR_MAC_SET_SHORT_SLOT_TIME(x) (((tANI_U16) x) | 0x0400) +#define SIR_MAC_SET_APSD(x) (((tANI_U16) x) | 0x0800) +#if defined WLAN_FEATURE_VOWIFI +#define SIR_MAC_SET_RRM(x) (((tANI_U16) x) | 0x1000) +#endif +#define SIR_MAC_SET_GROUP_ACK(x) (((tANI_U16) x) | 0x4000) + +#ifdef WLAN_FEATURE_11AC +#define SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(x) ((((tANI_U32) x) & 0x03800000) >> 23) +#endif + +// bitname must be one of the above, eg ESS, CF_POLLABLE, etc. +#define SIR_MAC_CLEAR_CAPABILITY(u16value, bitname) \ + ((u16value) &= (~(SIR_MAC_SET_##bitname(0)))) + +#define IS_WES_MODE_ENABLED(x) \ + ((x)->roam.configParam.isWESModeEnabled) + +#define BA_RECIPIENT 1 +#define BA_INITIATOR 2 +#define BA_BOTH_DIRECTIONS 3 + +/// Status Code (present in Management response frames) enum + +typedef enum eSirMacStatusCodes +{ + eSIR_MAC_SUCCESS_STATUS = 0, //Reserved + eSIR_MAC_UNSPEC_FAILURE_STATUS = 1, //Unspecified reason + // 802.11 reserved 2-9 + /* + WMM status codes(standard 1.1 table 9) + Table 9 ADDTS Response Status Codes + Value Operation + 0 Admission accepted + 1 Invalid parameters + 2 Reserved + 3 Refused + 4-255 Reserved + */ + eSIR_MAC_WME_INVALID_PARAMS_STATUS = 1, // ?? + eSIR_MAC_WME_REFUSED_STATUS = 3, // ?? + eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS = 10, //Cannot support all requested capabilities in the Capability Information field + eSIR_MAC_INABLITY_TO_CONFIRM_ASSOC_STATUS = 11, //Reassociation denied due to inability to confirm that association exists + eSIR_MAC_OUTSIDE_SCOPE_OF_SPEC_STATUS = 12, //Association denied due to reason outside the scope of this standard + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS = 13, //Responding station does not support the specified authentication algorithm + eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS = 14, //Received an Authentication frame with authentication transaction sequence number + //out of expected sequence + eSIR_MAC_CHALLENGE_FAILURE_STATUS = 15, //Authentication rejected because of challenge failure + eSIR_MAC_AUTH_RSP_TIMEOUT_STATUS = 16, //Authentication rejected due to timeout waiting for next frame in sequence + eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS = 17, //Association denied because AP is unable to handle additional associated stations + eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS = 18, //Association denied due to requesting station not supporting all of the data rates in the + //BSSBasicRateSet parameter + eSIR_MAC_SHORT_PREAMBLE_NOT_SUPPORTED_STATUS = 19, //Association denied due to requesting station not supporting the short preamble + //option + eSIR_MAC_PBCC_NOT_SUPPORTED_STATUS = 20, //Association denied due to requesting station not supporting the PBCC modulation + //option + eSIR_MAC_CHANNEL_AGILITY_NOT_SUPPORTED_STATUS = 21, //Association denied due to requesting station not supporting the Channel Agility + //option + eSIR_MAC_SPECTRUM_MGMT_REQD_STATUS = 22, //Association request rejected because Spectrum Management capability is required + eSIR_MAC_PWR_CAPABILITY_BAD_STATUS = 23, //Association request rejected because the information in the Power Capability + //element is unacceptable + eSIR_MAC_SPRTD_CHANNELS_BAD_STATUS = 24, //Association request rejected because the information in the Supported Channels + //element is unacceptable + eSIR_MAC_SHORT_SLOT_NOT_SUPORTED_STATUS = 25, //Association denied due to requesting station not supporting the Short Slot Time + //option + eSIR_MAC_DSSS_OFDM_NOT_SUPPORTED_STATUS = 26, //Association denied due to requesting station not supporting the DSSS-OFDM option + // reserved 27-29 + eSIR_MAC_TRY_AGAIN_LATER = 30, //Association request rejected temporarily, try again later + // reserved 31 + eSIR_MAC_QOS_UNSPECIFIED_FAILURE_STATUS = 32, //Unspecified, QoS-related failure + eSIR_MAC_QAP_NO_BANDWIDTH_STATUS = 33, //Association denied because QoS AP has insufficient bandwidth to handle another + //QoS STA + eSIR_MAC_XS_FRAME_LOSS_STATUS = 34, //Association denied due to excessive frame loss rates and/or poor conditions on cur- + //rent operating channel + eSIR_MAC_STA_QOS_NOT_SUPPORTED_STATUS = 35, //Association (with QoS BSS) denied because the requesting STA does not support the + //QoS facility + eSIR_MAC_STA_BLK_ACK_NOT_SUPPORTED_STATUS = 36, //Reserved + eSIR_MAC_REQ_DECLINED_STATUS = 37, //The request has been declined + eSIR_MAC_INVALID_PARAM_STATUS = 38, //The request has not been successful as one or more parameters have invalid values + eSIR_MAC_TS_NOT_HONOURED_STATUS = 39, //The TS has not been created because the request cannot be honored; however, a suggested + //TSPEC is provided so that the initiating STA may attempt to set another TS + //with the suggested changes to the TSPEC + eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS = 40, //Invalid information element, i.e., an information element defined in this standard for + //which the content does not meet the specifications in Clause 7 + eSIR_MAC_INVALID_GROUP_CIPHER_STATUS = 41, //Invalid group cipher + eSIR_MAC_INVALID_PAIRWISE_CIPHER_STATUS = 42, //Invalid pairwise cipher + eSIR_MAC_INVALID_AKMP_STATUS = 43, //Invalid AKMP + eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS = 44, //Unsupported RSN information element version + eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS = 45, //Invalid RSN information element capabilities + eSIR_MAC_CIPHER_SUITE_REJECTED_STATUS = 46, //Cipher suite rejected because of security policy + + /* + * The TS has not been created; however, the HC may be capable of creating + * a TS, in response to a request, after the time indicated in the TS Delay + * element + */ + eSIR_MAC_TS_NOT_CREATED_STATUS = 47, + + eSIR_MAC_DL_NOT_ALLOWED_STATUS = 48, //Direct link is not allowed in the BSS by policy + eSIR_MAC_DEST_STA_NOT_KNOWN_STATUS = 49, //The Destination STA is not present within this BSS + eSIR_MAC_DEST_STA_NOT_QSTA_STATUS = 50, //The Destination STA is not a QoS STA + eSIR_MAC_INVALID_LISTEN_INTERVAL_STATUS = 51, //Association denied because the ListenInterval is too large + + eSIR_MAC_DSSS_CCK_RATE_MUST_SUPPORT_STATUS = 52, //FIXME: + eSIR_MAC_DSSS_CCK_RATE_NOT_SUPPORT_STATUS = 53, + eSIR_MAC_PSMP_CONTROLLED_ACCESS_ONLY_STATUS = 54, +#ifdef FEATURE_WLAN_ESE + eSIR_MAC_ESE_UNSPECIFIED_QOS_FAILURE_STATUS = 200, //ESE-Unspecified, QoS related failure in (Re)Assoc response frames + eSIR_MAC_ESE_TSPEC_REQ_REFUSED_STATUS = 201, //ESE-TSPEC request refused due to AP's policy configuration in AddTs Rsp, (Re)Assoc Rsp. + eSIR_MAC_ESE_ASSOC_DENIED_INSUFF_BW_STATUS = 202, //ESE-Assoc denied due to insufficient bandwidth to handle new TS in (Re)Assoc Rsp. + eSIR_MAC_ESE_INVALID_PARAMETERS_STATUS = 203, //ESE-Invalid parameters. (Re)Assoc request had one or more TSPEC parameters with + //invalid values. +#endif + +} tSirMacStatusCodes; + +/** + * Reason Code (present in Deauthentication/Disassociation + * Management frames) enum + */ +typedef enum eSirMacReasonCodes +{ + eSIR_MAC_UNSPEC_FAILURE_REASON = 1, //Unspecified reason + eSIR_MAC_PREV_AUTH_NOT_VALID_REASON = 2, //Previous authentication no longer valid + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON = 3, //Deauthenticated because sending station is leaving (or has left) IBSS or ESS + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON = 4, //Disassociated due to inactivity + eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON = 5, //Disassociated because AP is unable to handle all currently associated stations + + /* Class 2 frame received from non-authenticated station */ + eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON = 6, + + /* Class 3 frame received from non-associated station */ + eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON = 7, + + eSIR_MAC_DISASSOC_LEAVING_BSS_REASON = 8, //Disassociated because sending station is leaving (or has left) BSS + eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON = 9, //Station requesting (re)association is not authenticated with responding station + eSIR_MAC_PWR_CAPABILITY_BAD_REASON = 10, //Disassociated because the information in the Power Capability element is unacceptable + eSIR_MAC_SPRTD_CHANNELS_BAD_REASON = 11, //Disassociated because the information in the Supported Channels element is unacceptable + // reserved 12 + eSIR_MAC_INVALID_IE_REASON = 13, //Invalid information element, i.e., an information element defined in this standard for + //which the content does not meet the specifications in Clause 7 + eSIR_MAC_MIC_FAILURE_REASON = 14, //Message integrity code (MIC) failure + eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON = 15, //4-Way Handshake timeout + eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON = 16, //Group Key Handshake timeout + eSIR_MAC_RSN_IE_MISMATCH_REASON = 17, //Information element in 4-Way Handshake different from (Re)Association Request/Probe + //Response/Beacon frame + eSIR_MAC_INVALID_MC_CIPHER_REASON = 18, //Invalid group cipher + eSIR_MAC_INVALID_UC_CIPHER_REASON = 19, //Invalid pairwise cipher + eSIR_MAC_INVALID_AKMP_REASON = 20, //Invalid AKMP + eSIR_MAC_UNSUPPORTED_RSN_IE_VER_REASON = 21, //Unsupported RSN information element version + eSIR_MAC_INVALID_RSN_CAPABILITIES_REASON = 22, //Invalid RSN information element capabilities + eSIR_MAC_1X_AUTH_FAILURE_REASON = 23, //IEEE 802.1X authentication failed + eSIR_MAC_CIPHER_SUITE_REJECTED_REASON = 24, //Cipher suite rejected because of the security policy +#ifdef FEATURE_WLAN_TDLS + /* TDLS direct link tear down due to TDLS peer STA unreachable + via the TDLS direct link */ + eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE = 25, + + /* TDLS direct link tear down for unspecified reason */ + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON = 26, +#endif + // reserved 27 - 30 +#ifdef WLAN_FEATURE_11W + eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION = 31, //Robust management frames policy violation +#endif + eSIR_MAC_QOS_UNSPECIFIED_REASON = 32, //Disassociated for unspecified, QoS-related reason + eSIR_MAC_QAP_NO_BANDWIDTH_REASON = 33, //Disassociated because QoS AP lacks sufficient bandwidth for this QoS STA + eSIR_MAC_XS_UNACKED_FRAMES_REASON = 34, //Disassociated because excessive number of frames need to be acknowledged, but are not + //acknowledged due to AP transmissions and/or poor channel conditions + eSIR_MAC_BAD_TXOP_USE_REASON = 35, //Disassociated because STA is transmitting outside the limits of its TXOPs + eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON = 36, //Requested from peer STA as the STA is leaving the BSS (or resetting) + eSIR_MAC_PEER_REJECT_MECHANISIM_REASON = 37, //Requested from peer STA as it does not want to use the mechanism + eSIR_MAC_MECHANISM_NOT_SETUP_REASON = 38, //Requested from peer STA as the STA received frames using the mechanism for which a + //setup is required + eSIR_MAC_PEER_TIMEDOUT_REASON = 39, //Requested from peer STA due to timeout + eSIR_MAC_CIPHER_NOT_SUPPORTED_REASON = 45, //Peer STA does not support the requested cipher suite + eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON = 46, //FT reason + //reserved 47 - 65535. + eSIR_BEACON_MISSED = 65534, //We invented this to tell beacon missed case +} tSirMacReasonCodes; + + +// BA Initiator v/s Recipient +typedef enum eBADirection +{ + eBA_RECIPIENT, + eBA_INITIATOR +} tBADirection; + +// A-MPDU/BA Enable/Disable in Tx/Rx direction +typedef enum eBAEnable +{ + eBA_DISABLE, + eBA_ENABLE +} tBAEnable; + +// A-MPDU/BA Policy +typedef enum eBAPolicy +{ + eBA_UNCOMPRESSED, + eBA_COMPRESSED +} tBAPolicy; + +// A-MPDU/BA Policy +typedef enum eBAPolicyType +{ + eBA_POLICY_DELAYED, + eBA_POLICY_IMMEDIATE +} tBAPolicyType; + +/// Frame control field format (2 bytes) +typedef __ani_attr_pre_packed struct sSirMacFrameCtl +{ + +#ifndef ANI_LITTLE_BIT_ENDIAN + + tANI_U8 subType :4; + tANI_U8 type :2; + tANI_U8 protVer :2; + + tANI_U8 order :1; + tANI_U8 wep :1; + tANI_U8 moreData :1; + tANI_U8 powerMgmt :1; + tANI_U8 retry :1; + tANI_U8 moreFrag :1; + tANI_U8 fromDS :1; + tANI_U8 toDS :1; + +#else + + tANI_U8 protVer :2; + tANI_U8 type :2; + tANI_U8 subType :4; + + tANI_U8 toDS :1; + tANI_U8 fromDS :1; + tANI_U8 moreFrag :1; + tANI_U8 retry :1; + tANI_U8 powerMgmt :1; + tANI_U8 moreData :1; + tANI_U8 wep :1; + tANI_U8 order :1; + +#endif + +} __ani_attr_packed tSirMacFrameCtl, *tpSirMacFrameCtl; + +/// Sequence control field +typedef __ani_attr_pre_packed struct sSirMacSeqCtl +{ + +#ifndef ANI_LITTLE_BIT_ENDIAN + + tANI_U8 seqNumLo : 4; + tANI_U8 fragNum : 4; + + tANI_U8 seqNumHi : 8; + +#else + + tANI_U8 fragNum : 4; + tANI_U8 seqNumLo : 4; + tANI_U8 seqNumHi : 8; + +#endif +} __ani_attr_packed tSirMacSeqCtl, *tpSirMacSeqCtl; + +/// QoS control field +typedef __ani_attr_pre_packed struct sSirMacQosCtl +{ + +#ifndef ANI_LITTLE_BIT_ENDIAN + + tANI_U8 rsvd : 1; + tANI_U8 ackPolicy : 2; + tANI_U8 esop_txopUnit : 1; + tANI_U8 tid : 4; + + tANI_U8 txop : 8; + +#else + + tANI_U8 tid : 4; + tANI_U8 esop_txopUnit : 1; + tANI_U8 ackPolicy : 2; + tANI_U8 rsvd : 1; + + tANI_U8 txop : 8; + +#endif +} __ani_attr_packed tSirMacQosCtl, *tpSirMacQosCtl; + +/// Length (in bytes) of MAC header in 3 address format +#define SIR_MAC_HDR_LEN_3A 24 + +/// 3 address MAC data header format (24/26 bytes) +typedef __ani_attr_pre_packed struct sSirMacDot3Hdr +{ + tANI_U8 da[6]; + tANI_U8 sa[6]; + tANI_U16 length; +} __ani_attr_packed tSirMacDot3Hdr, *tpSirMacDot3Hdr; + + +/// 3 address MAC data header format (24/26 bytes) +typedef __ani_attr_pre_packed struct sSirMacDataHdr3a +{ + tSirMacFrameCtl fc; + tANI_U8 durationLo; + tANI_U8 durationHi; + tANI_U8 addr1[6]; + tANI_U8 addr2[6]; + tANI_U8 addr3[6]; + tSirMacSeqCtl seqControl; + tSirMacQosCtl qosControl; +} __ani_attr_packed tSirMacDataHdr3a, *tpSirMacDataHdr3a; + +/// Management header format +typedef __ani_attr_pre_packed struct sSirMacMgmtHdr +{ + tSirMacFrameCtl fc; + tANI_U8 durationLo; + tANI_U8 durationHi; + tANI_U8 da[6]; + tANI_U8 sa[6]; + tANI_U8 bssId[6]; + tSirMacSeqCtl seqControl; +} __ani_attr_packed tSirMacMgmtHdr, *tpSirMacMgmtHdr; + +/// ERP information field +typedef __ani_attr_pre_packed struct sSirMacErpInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 reserved:5; + tANI_U8 barkerPreambleMode:1; + tANI_U8 useProtection:1; + tANI_U8 nonErpPresent:1; +#else + tANI_U8 nonErpPresent:1; + tANI_U8 useProtection:1; + tANI_U8 barkerPreambleMode:1; + tANI_U8 reserved:5; +#endif +} __ani_attr_packed tSirMacErpInfo, *tpSirMacErpInfo; + +/// Capability information field +typedef __ani_attr_pre_packed struct sSirMacCapabilityInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 immediateBA:1; + tANI_U16 delayedBA:1; + tANI_U16 dsssOfdm:1; + tANI_U16 rrm:1; + tANI_U16 apsd:1; + tANI_U16 shortSlotTime:1; + tANI_U16 qos:1; + tANI_U16 spectrumMgt:1; + tANI_U16 channelAgility:1; + tANI_U16 pbcc:1; + tANI_U16 shortPreamble:1; + tANI_U16 privacy:1; + tANI_U16 cfPollReq:1; + tANI_U16 cfPollable:1; + tANI_U16 ibss:1; + tANI_U16 ess:1; +#else + tANI_U16 ess:1; + tANI_U16 ibss:1; + tANI_U16 cfPollable:1; + tANI_U16 cfPollReq:1; + tANI_U16 privacy:1; + tANI_U16 shortPreamble:1; + tANI_U16 pbcc:1; + tANI_U16 channelAgility:1; + tANI_U16 spectrumMgt:1; + tANI_U16 qos:1; + tANI_U16 shortSlotTime:1; + tANI_U16 apsd:1; + tANI_U16 rrm:1; + tANI_U16 dsssOfdm:1; + tANI_U16 delayedBA:1; + tANI_U16 immediateBA:1; +#endif +} __ani_attr_packed tSirMacCapabilityInfo, *tpSirMacCapabilityInfo; + +typedef __ani_attr_pre_packed struct sSirMacCfParamSet +{ + tANI_U8 cfpCount; + tANI_U8 cfpPeriod; + tANI_U16 cfpMaxDuration; + tANI_U16 cfpDurRemaining; +} __ani_attr_packed tSirMacCfParamSet; + +typedef __ani_attr_pre_packed struct sSirMacTim +{ + tANI_U8 dtimCount; + tANI_U8 dtimPeriod; + tANI_U8 bitmapControl; + tANI_U8 bitmapLength; + tANI_U8 bitmap[251]; +} __ani_attr_packed tSirMacTim; + +//12 Bytes long because this structure can be used to represent rate +//and extended rate set IEs +//The parser assume this to be at least 12 +typedef __ani_attr_pre_packed struct sSirMacRateSet +{ + tANI_U8 numRates; + tANI_U8 rate[SIR_MAC_RATESET_EID_MAX]; +} __ani_attr_packed tSirMacRateSet; + + +typedef __ani_attr_pre_packed struct sSirMacSSid +{ + tANI_U8 length; + tANI_U8 ssId[SIR_MAC_MAX_SSID_LENGTH]; +} __ani_attr_packed tSirMacSSid; + +typedef __ani_attr_pre_packed struct sSirMacWpaInfo +{ + tANI_U8 length; + tANI_U8 info[SIR_MAC_MAX_IE_LENGTH]; +} __ani_attr_packed tSirMacWpaInfo, *tpSirMacWpaInfo, + tSirMacRsnInfo, *tpSirMacRsnInfo; + +typedef __ani_attr_pre_packed struct sSirMacWapiInfo +{ + tANI_U8 length; + tANI_U8 info[SIR_MAC_MAX_IE_LENGTH]; +} __ani_attr_packed tSirMacWapiInfo, *tpSirMacWapiInfo, + tSirMacWapiInfo, *tpSirMacWapiInfo; + +typedef __ani_attr_pre_packed struct sSirMacFHParamSet +{ + tANI_U16 dwellTime; + tANI_U8 hopSet; + tANI_U8 hopPattern; + tANI_U8 hopIndex; +} tSirMacFHParamSet, *tpSirMacFHParamSet; + +typedef __ani_attr_pre_packed struct sSirMacIBSSParams +{ + tANI_U16 atim; +} tSirMacIBSSParams, *tpSirMacIBSSParams; + +typedef __ani_attr_pre_packed struct sSirMacRRMEnabledCap +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 reserved: 6; + tANI_U8 AntennaInformation: 1; + tANI_U8 BSSAvailAdmission: 1; + tANI_U8 BssAvgAccessDelay: 1; + tANI_U8 RSNIMeasurement: 1; + tANI_U8 RCPIMeasurement: 1; + tANI_U8 NeighborTSFOffset: 1; + tANI_U8 MeasurementPilotEnabled: 1; + tANI_U8 MeasurementPilot: 3; + tANI_U8 nonOperatinChanMax: 3; + tANI_U8 operatingChanMax: 3; + tANI_U8 RRMMIBEnabled: 1; + tANI_U8 APChanReport: 1; + tANI_U8 triggeredTCM: 1; + tANI_U8 TCMCapability: 1; + tANI_U8 LCIAzimuth: 1; + tANI_U8 LCIMeasurement: 1; + tANI_U8 statistics: 1; + tANI_U8 NoiseHistogram: 1; + tANI_U8 ChannelLoad: 1; + tANI_U8 FrameMeasurement: 1; + tANI_U8 BeaconRepCond: 1; + tANI_U8 BeaconTable: 1; + tANI_U8 BeaconActive: 1; + tANI_U8 BeaconPassive: 1; + tANI_U8 repeated: 1; + tANI_U8 parallel: 1; + tANI_U8 NeighborRpt: 1; + tANI_U8 LinkMeasurement: 1; + tANI_U8 present; +#else + tANI_U8 present; + tANI_U8 LinkMeasurement: 1; + tANI_U8 NeighborRpt: 1; + tANI_U8 parallel: 1; + tANI_U8 repeated: 1; + tANI_U8 BeaconPassive: 1; + tANI_U8 BeaconActive: 1; + tANI_U8 BeaconTable: 1; + tANI_U8 BeaconRepCond: 1; + tANI_U8 FrameMeasurement: 1; + tANI_U8 ChannelLoad: 1; + tANI_U8 NoiseHistogram: 1; + tANI_U8 statistics: 1; + tANI_U8 LCIMeasurement: 1; + tANI_U8 LCIAzimuth: 1; + tANI_U8 TCMCapability: 1; + tANI_U8 triggeredTCM: 1; + tANI_U8 APChanReport: 1; + tANI_U8 RRMMIBEnabled: 1; + tANI_U8 operatingChanMax: 3; + tANI_U8 nonOperatinChanMax: 3; + tANI_U8 MeasurementPilot: 3; + tANI_U8 MeasurementPilotEnabled: 1; + tANI_U8 NeighborTSFOffset: 1; + tANI_U8 RCPIMeasurement: 1; + tANI_U8 RSNIMeasurement: 1; + tANI_U8 BssAvgAccessDelay: 1; + tANI_U8 BSSAvailAdmission: 1; + tANI_U8 AntennaInformation: 1; + tANI_U8 reserved: 6; +#endif +} tSirMacRRMEnabledCap, *tpSirMacRRMEnabledCap; + + +/* ---------------- + * EDCA Profiles + * --------------- + */ + +#define EDCA_AC_BE 0 +#define EDCA_AC_BK 1 +#define EDCA_AC_VI 2 +#define EDCA_AC_VO 3 +#define AC_MGMT_LO 4 +#define AC_MGMT_HI 5 +#define MAX_NUM_AC 4 + +// access categories +#define SIR_MAC_EDCAACI_BESTEFFORT (EDCA_AC_BE) +#define SIR_MAC_EDCAACI_BACKGROUND (EDCA_AC_BK) +#define SIR_MAC_EDCAACI_VIDEO (EDCA_AC_VI) +#define SIR_MAC_EDCAACI_VOICE (EDCA_AC_VO) + +// access category record +typedef __ani_attr_pre_packed struct sSirMacAciAifsn +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 rsvd : 1; + tANI_U8 aci : 2; + tANI_U8 acm : 1; + tANI_U8 aifsn : 4; +#else + tANI_U8 aifsn : 4; + tANI_U8 acm : 1; + tANI_U8 aci : 2; + tANI_U8 rsvd : 1; +#endif +} __ani_attr_packed tSirMacAciAifsn; + +// contention window size +typedef __ani_attr_pre_packed struct sSirMacCW +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 max : 4; + tANI_U8 min : 4; +#else + tANI_U8 min : 4; + tANI_U8 max : 4; +#endif +} __ani_attr_packed tSirMacCW; + +typedef __ani_attr_pre_packed struct sSirMacEdcaParamRecord +{ + tSirMacAciAifsn aci; + tSirMacCW cw; + tANI_U16 txoplimit; +} __ani_attr_packed tSirMacEdcaParamRecord; + +typedef __ani_attr_pre_packed struct sSirMacQosInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 uapsd : 1; + tANI_U8 txopreq : 1; + tANI_U8 qreq : 1; + tANI_U8 qack : 1; + tANI_U8 count : 4; +#else + tANI_U8 count : 4; + tANI_U8 qack : 1; + tANI_U8 qreq : 1; + tANI_U8 txopreq : 1; + tANI_U8 uapsd : 1; +#endif +} __ani_attr_packed tSirMacQosInfo; + + +typedef __ani_attr_pre_packed struct sSirMacQosInfoStation +{ +#ifdef ANI_LITTLE_BIT_ENDIAN + tANI_U8 acvo_uapsd:1; + tANI_U8 acvi_uapsd:1; + tANI_U8 acbk_uapsd:1; + tANI_U8 acbe_uapsd:1; + tANI_U8 qack:1; + tANI_U8 maxSpLen:2; + tANI_U8 moreDataAck:1; +#else + tANI_U8 moreDataAck:1; + tANI_U8 maxSpLen:2; + tANI_U8 qack:1; + tANI_U8 acbe_uapsd:1; + tANI_U8 acbk_uapsd:1; + tANI_U8 acvi_uapsd:1; + tANI_U8 acvo_uapsd:1; +#endif +} __ani_attr_packed tSirMacQosInfoStation, *tpSirMacQosInfoStation; + + + +typedef __ani_attr_pre_packed struct sSirMacEdcaParamSetIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacQosInfo qosInfo; + tANI_U8 rsvd; + tSirMacEdcaParamRecord acbe; // best effort + tSirMacEdcaParamRecord acbk; // background + tSirMacEdcaParamRecord acvi; // video + tSirMacEdcaParamRecord acvo; // voice +} __ani_attr_packed tSirMacEdcaParamSetIE; + +typedef __ani_attr_pre_packed struct sSirMacQoSParams +{ + tANI_U8 count; + tANI_U16 limit; + tANI_U8 CWmin[8]; + tANI_U8 AIFS[8]; +} __ani_attr_packed tSirMacQoSParams; + +// ts info direction field can take any of these values +#define SIR_MAC_DIRECTION_UPLINK 0 +#define SIR_MAC_DIRECTION_DNLINK 1 +#define SIR_MAC_DIRECTION_DIRECT 2 +#define SIR_MAC_DIRECTION_BIDIR 3 + +// access policy +// reserved 0 +#define SIR_MAC_ACCESSPOLICY_EDCA 1 +#define SIR_MAC_ACCESSPOLICY_HCCA 2 +#define SIR_MAC_ACCESSPOLICY_BOTH 3 + +typedef __ani_attr_pre_packed struct sSirMacTSInfoTfc +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 burstSizeDefn : 1; + tANI_U8 reserved :7; +#else + tANI_U8 reserved :7; + tANI_U8 burstSizeDefn : 1; +#endif + +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 ackPolicy : 2; + tANI_U16 userPrio : 3; + tANI_U16 psb : 1; + tANI_U16 aggregation : 1; + tANI_U16 accessPolicy : 2; + tANI_U16 direction : 2; + tANI_U16 tsid : 4; + tANI_U16 trafficType : 1; +#else + tANI_U16 trafficType : 1; + tANI_U16 tsid : 4; + tANI_U16 direction : 2; + tANI_U16 accessPolicy : 2; + tANI_U16 aggregation : 1; + tANI_U16 psb : 1; + tANI_U16 userPrio : 3; + tANI_U16 ackPolicy : 2; +#endif +} __ani_attr_packed tSirMacTSInfoTfc; + +typedef __ani_attr_pre_packed struct sSirMacTSInfoSch +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 rsvd : 7; + tANI_U8 schedule : 1; +#else + tANI_U8 schedule : 1; + tANI_U8 rsvd : 7; +#endif +} __ani_attr_packed tSirMacTSInfoSch; + +typedef __ani_attr_pre_packed struct sSirMacTSInfo +{ + tSirMacTSInfoTfc traffic; + tSirMacTSInfoSch schedule; +} __ani_attr_packed tSirMacTSInfo; + +typedef __ani_attr_pre_packed struct sSirMacTspecIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacTSInfo tsinfo; + tANI_U16 nomMsduSz; + tANI_U16 maxMsduSz; + tANI_U32 minSvcInterval; + tANI_U32 maxSvcInterval; + tANI_U32 inactInterval; + tANI_U32 suspendInterval; + tANI_U32 svcStartTime; + tANI_U32 minDataRate; + tANI_U32 meanDataRate; + tANI_U32 peakDataRate; + tANI_U32 maxBurstSz; + tANI_U32 delayBound; + tANI_U32 minPhyRate; + tANI_U16 surplusBw; + tANI_U16 mediumTime; +} +__ani_attr_packed tSirMacTspecIE; + +// frame classifier types +#define SIR_MAC_TCLASTYPE_ETHERNET 0 +#define SIR_MAC_TCLASTYPE_TCPUDPIP 1 +#define SIR_MAC_TCLASTYPE_8021DQ 2 +// reserved 3-255 + +typedef __ani_attr_pre_packed struct sSirMacTclasParamEthernet +{ + tANI_U8 srcAddr[6]; + tANI_U8 dstAddr[6]; + tANI_U16 type; +}__ani_attr_packed tSirMacTclasParamEthernet; + +typedef __ani_attr_pre_packed struct sSirMacTclasParamIPv4 +{ + tANI_U8 version; + tANI_U8 srcIpAddr[4]; + tANI_U8 dstIpAddr[4]; + tANI_U16 srcPort; + tANI_U16 dstPort; + tANI_U8 dscp; + tANI_U8 protocol; + tANI_U8 rsvd; +} __ani_attr_packed tSirMacTclasParamIPv4; + +#define SIR_MAC_TCLAS_IPV4 4 +#define SIR_MAC_TCLAS_IPV6 6 + +typedef __ani_attr_pre_packed struct sSirMacTclasParamIPv6 +{ + tANI_U8 version; + tANI_U8 srcIpAddr[16]; + tANI_U8 dstIpAddr[16]; + tANI_U16 srcPort; + tANI_U16 dstPort; + tANI_U8 flowLabel[3]; +} __ani_attr_packed tSirMacTclasParamIPv6; + +typedef __ani_attr_pre_packed struct sSirMacTclasParam8021dq +{ + tANI_U16 tag; +} __ani_attr_packed tSirMacTclasParam8021dq; + +typedef __ani_attr_pre_packed struct sSirMacTclasIE +{ + tANI_U8 type; + tANI_U8 length; + tANI_U8 userPrio; + tANI_U8 classifierType; + tANI_U8 classifierMask; +} __ani_attr_packed tSirMacTclasIE; + +typedef __ani_attr_pre_packed struct sSirMacTsDelayIE +{ + tANI_U8 type; + tANI_U8 length; + tANI_U32 delay; +} __ani_attr_packed tSirMacTsDelayIE; + +typedef __ani_attr_pre_packed struct sSirMacScheduleInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 rsvd : 9; + tANI_U16 direction : 2; + tANI_U16 tsid : 4; + tANI_U16 aggregation : 1; +#else + tANI_U16 aggregation : 1; + tANI_U16 tsid : 4; + tANI_U16 direction : 2; + tANI_U16 rsvd : 9; +#endif +} __ani_attr_packed tSirMacScheduleInfo; + +typedef __ani_attr_pre_packed struct sSirMacScheduleIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacScheduleInfo info; + tANI_U32 svcStartTime; + tANI_U32 svcInterval; + tANI_U16 maxSvcDuration; + tANI_U16 specInterval; +} __ani_attr_packed tSirMacScheduleIE; + +typedef __ani_attr_pre_packed struct sSirMacQosCapabilityIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacQosInfo qosInfo; +} __ani_attr_packed tSirMacQosCapabilityIE; + +typedef __ani_attr_pre_packed struct sSirMacQosCapabilityStaIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacQosInfoStation qosInfo; +} __ani_attr_packed tSirMacQosCapabilityStaIE; + + +typedef tANI_U32 tSirMacTimeStamp[2]; + +typedef tANI_U16 tSirMacBeaconInterval; + +typedef tANI_U16 tSirMacListenInterval; + +typedef tANI_U8 tSirMacChanNum; + +typedef tANI_U8 tSirMacAddr[6]; + + +// IE definitions +typedef __ani_attr_pre_packed struct sSirMacSSidIE +{ + tANI_U8 type; + tSirMacSSid ssId; +} __ani_attr_packed tSirMacSSidIE; + +typedef __ani_attr_pre_packed struct sSirMacRateSetIE +{ + tANI_U8 type; + tSirMacRateSet supportedRateSet; +} __ani_attr_packed tSirMacRateSetIE; + +typedef __ani_attr_pre_packed struct sSirMacDsParamSetIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacChanNum channelNumber; +} __ani_attr_packed tSirMacDsParamSetIE; + +typedef __ani_attr_pre_packed struct sSirMacCfParamSetIE +{ + tANI_U8 type; + tANI_U8 length; + tSirMacCfParamSet cfParams; +} __ani_attr_packed tSirMacCfParamSetIE; + +typedef __ani_attr_pre_packed struct sSirMacChanInfo +{ + tSirMacChanNum firstChanNum; + tANI_U8 numChannels; + tANI_S8 maxTxPower; +} __ani_attr_packed tSirMacChanInfo; + +typedef __ani_attr_pre_packed struct sSirMacNonErpPresentIE +{ + tANI_U8 type; + tANI_U8 length; + tANI_U8 erp; +} __ani_attr_packed tSirMacNonErpPresentIE; + +typedef struct sSirMacPowerCapabilityIE +{ + tANI_U8 type; + tANI_U8 length; + tANI_U8 minTxPower; + tANI_U8 maxTxPower; +} tSirMacPowerCapabilityIE; + +typedef struct sSirMacSupportedChannelIE +{ + tANI_U8 type; + tANI_U8 length; + tANI_U8 supportedChannels[96]; +} tSirMacSupportedChannelIE; + +typedef struct sSirMacMeasReqField +{ + tANI_U8 channelNumber; + tANI_U8 measStartTime[8]; + tANI_U16 measDuration; +} tSirMacMeasReqField, *tpSirMacMeasReqField; + +typedef struct sSirMacMeasReqIE +{ + tANI_U8 type; + tANI_U8 length; + tANI_U8 measToken; + tANI_U8 measReqMode; + tANI_U8 measType; + tSirMacMeasReqField measReqField; +} tSirMacMeasReqIE, *tpSirMacMeasReqIE; + +#define SIR_MAC_MAX_SUPP_RATES 32 + +#define SIR_MAC_MAX_SUPP_CHANNELS 100 +#define SIR_MAC_MAX_SUPP_OPER_CLASSES 32 +#define SIR_MAC_MAX_EXTN_CAP 8 + +// VHT Capabilities Info +typedef __ani_attr_pre_packed struct sSirMacVHTCapabilityInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U32 reserved1: 2; + tANI_U32 txAntPattern: 1; + tANI_U32 rxAntPattern: 1; + tANI_U32 vhtLinkAdaptCap: 2; + tANI_U32 maxAMPDULenExp: 3; + tANI_U32 htcVHTCap: 1; + tANI_U32 vhtTXOPPS: 1; + tANI_U32 muBeamformeeCap: 1; + tANI_U32 muBeamformerCap: 1; + tANI_U32 numSoundingDim: 3; + tANI_U32 csnofBeamformerAntSup: 3; + tANI_U32 suBeamformeeCap: 1; + tANI_U32 suBeamFormerCap: 1; + tANI_U32 rxSTBC: 3; + tANI_U32 txSTBC: 1; + tANI_U32 shortGI160and80plus80MHz: 1; + tANI_U32 shortGI80MHz: 1; + tANI_U32 ldpcCodingCap: 1; + tANI_U32 supportedChannelWidthSet: 2; + tANI_U32 maxMPDULen: 2; +#else + tANI_U32 maxMPDULen: 2; + tANI_U32 supportedChannelWidthSet: 2; + tANI_U32 ldpcCodingCap: 1; + tANI_U32 shortGI80MHz: 1; + tANI_U32 shortGI160and80plus80MHz: 1; + tANI_U32 txSTBC: 1; + tANI_U32 rxSTBC: 3; + tANI_U32 suBeamFormerCap: 1; + tANI_U32 suBeamformeeCap: 1; + tANI_U32 csnofBeamformerAntSup: 3; + tANI_U32 numSoundingDim: 3; + tANI_U32 muBeamformerCap: 1; + tANI_U32 muBeamformeeCap: 1; + tANI_U32 vhtTXOPPS: 1; + tANI_U32 htcVHTCap: 1; + tANI_U32 maxAMPDULenExp: 3; + tANI_U32 vhtLinkAdaptCap: 2; + tANI_U32 rxAntPattern: 1; + tANI_U32 txAntPattern: 1; + tANI_U32 reserved1: 2; +#endif +} __ani_attr_packed tSirMacVHTCapabilityInfo; + +typedef __ani_attr_pre_packed struct sSirMacVHTTxSupDataRateInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 reserved: 3; + tANI_U16 txSupDataRate: 13; +#else + tANI_U16 txSupDataRate: 13; + tANI_U16 reserved: 3; +#endif +}__ani_attr_packed tSirMacVHTTxSupDataRateInfo; + +typedef __ani_attr_pre_packed struct sSirMacVHTRxSupDataRateInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 reserved: 3; + tANI_U16 rxSupDataRate: 13; +#else + tANI_U16 rxSupDataRate: 13; + tANI_U16 reserved: 3; +#endif +}__ani_attr_packed tSirMacVHTRxSupDataRateInfo; + +/** + * struct sSirVhtMcsInfo - VHT MCS information + * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams + * @rx_highest: Indicates highest long GI VHT PPDU data rate + * STA can receive. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams + * @tx_highest: Indicates highest long GI VHT PPDU data rate + * STA can transmit. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest TX data rate supported. + */ +typedef struct sSirVhtMcsInfo { + tANI_U16 rxMcsMap; + tANI_U16 rxHighest; + tANI_U16 txMcsMap; + tANI_U16 txHighest; +}tSirVhtMcsInfo; + +/** + * struct sSirVHtCap - VHT capabilities + * + * This structure is the "VHT capabilities element" as + * described in 802.11ac D3.0 8.4.2.160 + * @vht_cap_info: VHT capability info + * @supp_mcs: VHT MCS supported rates + */ +typedef struct sSirVHtCap { + tANI_U32 vhtCapInfo; + tSirVhtMcsInfo suppMcs; +}tSirVHTCap; + +/** + * struct sSirHtCap - HT capabilities + * + * This structure refers to "HT capabilities element" as + * described in 802.11n draft section 7.3.2.52 + */ + + +typedef struct sSirHtCap { + tANI_U16 capInfo; + tANI_U8 ampduParamsInfo; + tANI_U8 suppMcsSet[16]; + tANI_U16 extendedHtCapInfo; + tANI_U32 txBFCapInfo; + tANI_U8 antennaSelectionInfo; +}tSirHTCap; + +// HT Cap and HT IE Size defines +#define HT_CAPABILITY_IE_SIZE 28 +#define HT_INFO_IE_SIZE 24 + +// +// Determines the current operating mode of the 802.11n STA +// +typedef enum eSirMacHTOperatingMode +{ + eSIR_HT_OP_MODE_PURE, // No Protection + eSIR_HT_OP_MODE_OVERLAP_LEGACY, // Overlap Legacy device present, protection is optional + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT, // No legacy device, but 20 MHz HT present + eSIR_HT_OP_MODE_MIXED /* Protection is required */ +} tSirMacHTOperatingMode; + + +// Spatial Multiplexing(SM) Power Save mode +typedef enum eSirMacHTMIMOPowerSaveState +{ + eSIR_HT_MIMO_PS_STATIC = 0, // Static SM Power Save mode + eSIR_HT_MIMO_PS_DYNAMIC = 1, // Dynamic SM Power Save mode + eSIR_HT_MIMO_PS_NA = 2, // reserved + eSIR_HT_MIMO_PS_NO_LIMIT = 3 // SM Power Save disabled +} tSirMacHTMIMOPowerSaveState; + + +typedef enum eSirMacHTChannelWidth +{ + eHT_CHANNEL_WIDTH_20MHZ = 0, + eHT_CHANNEL_WIDTH_40MHZ = 1, +#ifdef WLAN_FEATURE_11AC + eHT_CHANNEL_WIDTH_80MHZ = 2, + eHT_CHANNEL_WIDTH_160MHZ = 3, +#endif + eHT_MAX_CHANNEL_WIDTH +} tSirMacHTChannelWidth; + +typedef enum eSirMacHTChannelType +{ + eHT_CHAN_NO_HT = 0, + eHT_CHAN_HT20 = 1, + eHT_CHAN_HT40MINUS = 2, + eHT_CHAN_HT40PLUS = 3 +} tSirMacHTChannelType; + +//Packet struct for HT capability +typedef __ani_attr_pre_packed struct sHtCaps { + tANI_U16 advCodingCap: 1; + tANI_U16 supportedChannelWidthSet: 1; + tANI_U16 mimoPowerSave: 2; + tANI_U16 greenField: 1; + tANI_U16 shortGI20MHz: 1; + tANI_U16 shortGI40MHz: 1; + tANI_U16 txSTBC: 1; + tANI_U16 rxSTBC: 2; + tANI_U16 delayedBA: 1; + tANI_U16 maximalAMSDUsize: 1; + tANI_U16 dsssCckMode40MHz: 1; + tANI_U16 psmp: 1; + tANI_U16 stbcControlFrame: 1; + tANI_U16 lsigTXOPProtection: 1; + tANI_U8 maxRxAMPDUFactor: 2; + tANI_U8 mpduDensity: 3; + tANI_U8 reserved1: 3; + tANI_U8 supportedMCSSet[16]; + tANI_U16 pco: 1; + tANI_U16 transitionTime: 2; + tANI_U16 reserved2: 5; + tANI_U16 mcsFeedback: 2; + tANI_U16 reserved3: 6; + tANI_U32 txBF: 1; + tANI_U32 rxStaggeredSounding: 1; + tANI_U32 txStaggeredSounding: 1; + tANI_U32 rxZLF: 1; + tANI_U32 txZLF: 1; + tANI_U32 implicitTxBF: 1; + tANI_U32 calibration: 2; + tANI_U32 explicitCSITxBF: 1; + tANI_U32 explicitUncompressedSteeringMatrix: 1; + tANI_U32 explicitBFCSIFeedback: 3; + tANI_U32 explicitUncompressedSteeringMatrixFeedback: 3; + tANI_U32 explicitCompressedSteeringMatrixFeedback: 3; + tANI_U32 csiNumBFAntennae: 2; + tANI_U32 uncompressedSteeringMatrixBFAntennae: 2; + tANI_U32 compressedSteeringMatrixBFAntennae: 2; + tANI_U32 reserved4: 7; + tANI_U8 antennaSelection: 1; + tANI_U8 explicitCSIFeedbackTx: 1; + tANI_U8 antennaIndicesFeedbackTx: 1; + tANI_U8 explicitCSIFeedback: 1; + tANI_U8 antennaIndicesFeedback: 1; + tANI_U8 rxAS: 1; + tANI_U8 txSoundingPPDUs: 1; + tANI_U8 reserved5: 1; + +} __ani_attr_packed tHtCaps; + +/* During 11h channel switch, the AP can indicate if the + * STA needs to stop the transmission or continue until the + * channel-switch. + * eSIR_CHANSW_MODE_NORMAL - STA can continue transmission + * eSIR_CHANSW_MODE_SILENT - STA should stop transmission + */ +typedef enum eSirMacChanSwMode +{ + eSIR_CHANSW_MODE_NORMAL = 0, + eSIR_CHANSW_MODE_SILENT = 1 +} tSirMacChanSwitchMode; + + +typedef __ani_attr_pre_packed struct _BarControl { + +#ifndef ANI_BIG_BYTE_ENDIAN + + tANI_U16 barAckPolicy:1; + tANI_U16 multiTID:1; + tANI_U16 bitMap:1; + tANI_U16 rsvd:9; + tANI_U16 numTID:4; + +#else + tANI_U16 numTID:4; + tANI_U16 rsvd:9; + tANI_U16 bitMap:1; + tANI_U16 multiTID:1; + tANI_U16 barAckPolicy:1; + +#endif + +}__ani_attr_packed barCtrlType; + +typedef __ani_attr_pre_packed struct _BARFrmStruct { + tSirMacFrameCtl fc; + tANI_U16 duration; + tSirMacAddr rxAddr; + tSirMacAddr txAddr; + barCtrlType barControl; + tSirMacSeqCtl ssnCtrl; +}__ani_attr_packed BARFrmType; + + +// Supported MCS set +#define SIZE_OF_SUPPORTED_MCS_SET 16 +#define SIZE_OF_BASIC_MCS_SET 16 +#define VALID_MCS_SIZE 77 //0-76 +#define MCS_RX_HIGHEST_SUPPORTED_RATE_BYTE_OFFSET 10 +// This is not clear, Count 8 based from NV supported MCS count +#define VALID_MAX_MCS_INDEX 8 + +// +// The following enums will be used to get the "current" HT Capabilities of +// the local STA in a generic fashion. In other words, the following enums +// identify the HT capabilities that can be queried or set. +// +typedef enum eHTCapability +{ + eHT_LSIG_TXOP_PROTECTION, + eHT_STBC_CONTROL_FRAME, + eHT_PSMP, + eHT_DSSS_CCK_MODE_40MHZ, + eHT_MAX_AMSDU_LENGTH, + eHT_MAX_AMSDU_NUM, + eHT_DELAYED_BA, + eHT_RX_STBC, + eHT_TX_STBC, + eHT_SHORT_GI_40MHZ, + eHT_SHORT_GI_20MHZ, + eHT_GREENFIELD, + eHT_MIMO_POWER_SAVE, + eHT_SUPPORTED_CHANNEL_WIDTH_SET, + eHT_ADVANCED_CODING, + eHT_MAX_RX_AMPDU_FACTOR, + eHT_MPDU_DENSITY, + eHT_PCO, + eHT_TRANSITION_TIME, + eHT_MCS_FEEDBACK, + eHT_TX_BEAMFORMING, + eHT_ANTENNA_SELECTION, + // The following come under Additional HT Capabilities + eHT_SI_GRANULARITY, + eHT_CONTROLLED_ACCESS, + eHT_RIFS_MODE, + eHT_RECOMMENDED_TX_WIDTH_SET, + eHT_EXTENSION_CHANNEL_OFFSET, + eHT_OP_MODE, + eHT_BASIC_STBC_MCS, + eHT_DUAL_CTS_PROTECTION, + eHT_LSIG_TXOP_PROTECTION_FULL_SUPPORT, + eHT_PCO_ACTIVE, + eHT_PCO_PHASE +} tHTCapability; + +// HT Capabilities Info +typedef __ani_attr_pre_packed struct sSirMacHTCapabilityInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 lsigTXOPProtection:1; // Dynamic state + tANI_U16 stbcControlFrame:1; // Static via CFG + tANI_U16 psmp:1; // Static via CFG + tANI_U16 dsssCckMode40MHz:1; // Static via CFG + tANI_U16 maximalAMSDUsize:1; // Static via CFG + tANI_U16 delayedBA:1; // Static via CFG + tANI_U16 rxSTBC:2; // Static via CFG + tANI_U16 txSTBC:1; // Static via CFG + tANI_U16 shortGI40MHz:1; // Static via CFG + tANI_U16 shortGI20MHz:1; // Static via CFG + tANI_U16 greenField:1; // Static via CFG + tANI_U16 mimoPowerSave:2; // Dynamic state + tANI_U16 supportedChannelWidthSet:1; // Static via CFG + tANI_U16 advCodingCap:1; // Static via CFG +#else + tANI_U16 advCodingCap:1; + tANI_U16 supportedChannelWidthSet:1; + tANI_U16 mimoPowerSave:2; + tANI_U16 greenField:1; + tANI_U16 shortGI20MHz:1; + tANI_U16 shortGI40MHz:1; + tANI_U16 txSTBC:1; + tANI_U16 rxSTBC:2; + tANI_U16 delayedBA:1; + tANI_U16 maximalAMSDUsize:1; + tANI_U16 dsssCckMode40MHz:1; + tANI_U16 psmp:1; + tANI_U16 stbcControlFrame:1; + tANI_U16 lsigTXOPProtection:1; +#endif +} __ani_attr_packed tSirMacHTCapabilityInfo; + +// HT Parameters Info +typedef __ani_attr_pre_packed struct sSirMacHTParametersInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 reserved:3; + tANI_U8 mpduDensity:3; // Dynamic state + tANI_U8 maxRxAMPDUFactor:2; // Dynamic state +#else + tANI_U8 maxRxAMPDUFactor:2; + tANI_U8 mpduDensity:3; + tANI_U8 reserved:3; +#endif +} __ani_attr_packed tSirMacHTParametersInfo; + +// Extended HT Capabilities Info +typedef __ani_attr_pre_packed struct sSirMacExtendedHTCapabilityInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 reserved2:6; + tANI_U16 mcsFeedback:2; // Static via CFG + tANI_U16 reserved1:5; + tANI_U16 transitionTime:2; // Static via CFG + tANI_U16 pco:1; // Static via CFG +#else + tANI_U16 pco:1; + tANI_U16 transitionTime:2; + tANI_U16 reserved1:5; + tANI_U16 mcsFeedback:2; + tANI_U16 reserved2:6; +#endif +} __ani_attr_packed tSirMacExtendedHTCapabilityInfo; + +//IEEE 802.11n/D7.0 - 7.3.2.57.4 +//Part of the "supported MCS set field" +typedef __ani_attr_pre_packed struct sSirMacRxHighestSupportRate +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 reserved : 6; + tANI_U16 rate : 10; +#else + tANI_U16 rate : 10; + tANI_U16 reserved : 6; +#endif +} __ani_attr_packed tSirMacRxHighestSupportRate, *tpSirMacRxHighestSupportRate; + + +// Transmit Beam Forming Capabilities Info +typedef __ani_attr_pre_packed struct sSirMacTxBFCapabilityInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U32 reserved:7; + tANI_U32 compressedSteeringMatrixBFAntennae:2; // Static via CFG + tANI_U32 uncompressedSteeringMatrixBFAntennae:2; // Static via CFG + tANI_U32 csiNumBFAntennae:2; // Static via CFG + tANI_U32 explicitCompressedSteeringMatrixFeedback:3; // Static via CFG + tANI_U32 explicitUncompressedSteeringMatrixFeedback:3; // Static via CFG + tANI_U32 explicitBFCSIFeedback:3; // Static via CFG + tANI_U32 explicitUncompressedSteeringMatrix:1; // Static via CFG + tANI_U32 explicitCSITxBF:1; // Static via CFG + tANI_U32 calibration:2; // Static via CFG + tANI_U32 implicitTxBF:1; // Static via CFG + tANI_U32 txZLF:1; // Static via CFG + tANI_U32 rxZLF:1; // Static via CFG + tANI_U32 txStaggeredSounding:1; // Static via CFG + tANI_U32 rxStaggeredSounding:1; // Static via CFG + tANI_U32 txBF:1; // Static via CFG +#else + tANI_U32 txBF:1; + tANI_U32 rxStaggeredSounding:1; + tANI_U32 txStaggeredSounding:1; + tANI_U32 rxZLF:1; + tANI_U32 txZLF:1; + tANI_U32 implicitTxBF:1; + tANI_U32 calibration:2; + tANI_U32 explicitCSITxBF:1; + tANI_U32 explicitUncompressedSteeringMatrix:1; + tANI_U32 explicitBFCSIFeedback:3; + tANI_U32 explicitUncompressedSteeringMatrixFeedback:3; + tANI_U32 explicitCompressedSteeringMatrixFeedback:3; + tANI_U32 csiNumBFAntennae:2; + tANI_U32 uncompressedSteeringMatrixBFAntennae:2; + tANI_U32 compressedSteeringMatrixBFAntennae:2; + tANI_U32 reserved:7; +#endif +} __ani_attr_packed tSirMacTxBFCapabilityInfo; + +// Antenna Selection Capability Info +typedef __ani_attr_pre_packed struct sSirMacASCapabilityInfo +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 reserved2:1; + tANI_U8 txSoundingPPDUs:1; // Static via CFG + tANI_U8 rxAS:1; // Static via CFG + tANI_U8 antennaIndicesFeedback:1; // Static via CFG + tANI_U8 explicitCSIFeedback:1; // Static via CFG + tANI_U8 antennaIndicesFeedbackTx:1; // Static via CFG + tANI_U8 explicitCSIFeedbackTx:1; // Static via CFG + tANI_U8 antennaSelection:1; // Static via CFG +#else + tANI_U8 antennaSelection:1; + tANI_U8 explicitCSIFeedbackTx:1; + tANI_U8 antennaIndicesFeedbackTx:1; + tANI_U8 explicitCSIFeedback:1; + tANI_U8 antennaIndicesFeedback:1; + tANI_U8 rxAS:1; + tANI_U8 txSoundingPPDUs:1; + tANI_U8 reserved2:1; +#endif +} __ani_attr_packed tSirMacASCapabilityInfo; + +// Additional HT IE Field1 +typedef __ani_attr_pre_packed struct sSirMacHTInfoField1 +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U8 serviceIntervalGranularity:3; // Dynamic state + tANI_U8 controlledAccessOnly:1; // Static via CFG + tANI_U8 rifsMode:1; // Dynamic state + tANI_U8 recommendedTxWidthSet:1; // Dynamic state + tANI_U8 secondaryChannelOffset:2; // Dynamic state +#else + tANI_U8 secondaryChannelOffset:2; + tANI_U8 recommendedTxWidthSet:1; + tANI_U8 rifsMode:1; + tANI_U8 controlledAccessOnly:1; + tANI_U8 serviceIntervalGranularity:3; +#endif +} __ani_attr_packed tSirMacHTInfoField1; + +// Additional HT IE Field2 +typedef __ani_attr_pre_packed struct sSirMacHTInfoField2 +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 reserved:11; + tANI_U16 obssNonHTStaPresent:1; /*added for Obss */ + tANI_U16 transmitBurstLimit: 1; + tANI_U16 nonGFDevicesPresent:1; + tANI_U16 opMode:2; // Dynamic state +#else + tANI_U16 opMode:2; + tANI_U16 nonGFDevicesPresent:1; + tANI_U16 transmitBurstLimit: 1; + tANI_U16 obssNonHTStaPresent:1; /*added for Obss */ + tANI_U16 reserved:11; +#endif +} __ani_attr_packed tSirMacHTInfoField2; + +// Additional HT IE Field3 +typedef __ani_attr_pre_packed struct sSirMacHTInfoField3 +{ +#ifndef ANI_LITTLE_BIT_ENDIAN + tANI_U16 reserved:4; + tANI_U16 pcoPhase:1; // Dynamic state + tANI_U16 pcoActive:1; // Dynamic state + tANI_U16 lsigTXOPProtectionFullSupport:1; // Dynamic state + tANI_U16 secondaryBeacon:1; // Dynamic state + tANI_U16 dualCTSProtection:1; // Dynamic state + tANI_U16 basicSTBCMCS:7; // Dynamic state +#else + tANI_U16 basicSTBCMCS:7; + tANI_U16 dualCTSProtection:1; + tANI_U16 secondaryBeacon:1; + tANI_U16 lsigTXOPProtectionFullSupport:1; + tANI_U16 pcoActive:1; + tANI_U16 pcoPhase:1; + tANI_U16 reserved:4; +#endif +} __ani_attr_packed tSirMacHTInfoField3; + +typedef __ani_attr_pre_packed struct sSirMacProbeReqFrame +{ + tSirMacSSidIE ssIdIE; + tSirMacRateSetIE rateSetIE; + tSirMacRateSetIE extendedRateSetIE; +} __ani_attr_packed tSirMacProbeReqFrame, *tpSirMacProbeReqFrame; + +typedef __ani_attr_pre_packed struct sSirMacProbeRspFrame +{ + tSirMacTimeStamp ts; + tSirMacBeaconInterval beaconInterval; + tSirMacCapabilityInfo capabilityInfo; + tSirMacSSidIE ssIdIE; + tSirMacRateSetIE rateSetIE; + tSirMacRateSetIE extendedRateSetIE; + tSirMacNonErpPresentIE nonErpPresent; + tSirMacDsParamSetIE dsParamsIE; + tSirMacCfParamSetIE cfParamsIE; +} __ani_attr_packed tSirMacProbeRspFrame, *tpSirMacProbeRspFrame; + +typedef __ani_attr_pre_packed struct sSirMacAuthFrameBody +{ + tANI_U16 authAlgoNumber; + tANI_U16 authTransactionSeqNumber; + tANI_U16 authStatusCode; + tANI_U8 type; // = SIR_MAC_CHALLENGE_TEXT_EID + tANI_U8 length; // = SIR_MAC_AUTH_CHALLENGE_LENGTH + tANI_U8 challengeText[SIR_MAC_AUTH_CHALLENGE_LENGTH]; +} __ani_attr_packed tSirMacAuthFrameBody, *tpSirMacAuthFrameBody; + +typedef __ani_attr_pre_packed struct sSirMacAuthenticationFrame +{ + tSirMacAuthFrameBody authFrameBody; +} __ani_attr_packed tSirMacAuthFrame, *tpSirMacAuthFrame; + +typedef __ani_attr_pre_packed struct sSirMacAssocReqFrame +{ + tSirMacCapabilityInfo capabilityInfo; + tANI_U16 listenInterval; + tSirMacSSidIE ssIdIE; + tSirMacRateSetIE rateSetIE; + tSirMacRateSetIE extendedRateSetIE; +} __ani_attr_packed tSirMacAssocReqFrame, *tpSirMacAssocReqFrame; + +typedef __ani_attr_pre_packed struct sSirMacAssocRspFrame +{ + tSirMacCapabilityInfo capabilityInfo; + tANI_U16 statusCode; + tANI_U16 aid; + tSirMacRateSetIE supportedRates; + tSirMacRateSetIE extendedRateSetIE; +} __ani_attr_packed tSirMacAssocRspFrame, *tpSirMacAssocRspFrame; + +typedef __ani_attr_pre_packed struct sSirMacDisassocFrame +{ + tANI_U16 reasonCode; +} __ani_attr_packed tSirMacDisassocFrame, *tpSirMacDisassocFrame; + +typedef __ani_attr_pre_packed struct sDSirMacDeauthFrame +{ + tANI_U16 reasonCode; +} __ani_attr_packed tSirMacDeauthFrame, *tpSirMacDeauthFrame; + +/// Common header for all action frames +typedef __ani_attr_pre_packed struct sSirMacActionFrameHdr +{ + tANI_U8 category; + tANI_U8 actionID; +} __ani_attr_packed tSirMacActionFrameHdr, *tpSirMacActionFrameHdr; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +typedef __ani_attr_pre_packed struct sSirMacVendorSpecificFrameHdr +{ + tANI_U8 category; + tANI_U8 Oui[4]; +} __ani_attr_packed tSirMacVendorSpecificFrameHdr, *tpSirMacVendorSpecificFrameHdr; +#endif + +typedef __ani_attr_pre_packed struct sSirMacVendorSpecificPublicActionFrameHdr +{ + tANI_U8 category; + tANI_U8 actionID; + tANI_U8 Oui[4]; + tANI_U8 OuiSubType; + tANI_U8 dialogToken; +} __ani_attr_packed tSirMacVendorSpecificPublicActionFrameHdr, *tpSirMacVendorSpecificPublicActionFrameHdr; + +typedef __ani_attr_pre_packed struct sSirMacP2PActionFrameHdr +{ + tANI_U8 category; + tANI_U8 Oui[4]; + tANI_U8 OuiSubType; + tANI_U8 dialogToken; +} __ani_attr_packed tSirMacP2PActionFrameHdr, *tpSirMacP2PActionFrameHdr; + + + +typedef struct sSirMacMeasActionFrameHdr +{ + tANI_U8 category; + tANI_U8 actionID; + tANI_U8 dialogToken; +} tSirMacMeasActionFrameHdr, *tpSirMacMeasActionFrameHdr; + + + +#if defined WLAN_FEATURE_VOWIFI + +typedef struct sSirMacNeighborReportReq +{ + tANI_U8 dialogToken; + tANI_U8 ssid_present; + tSirMacSSid ssid; +} tSirMacNeighborReportReq, *tpSirMacNeighborReportReq; + +typedef struct sSirMacLinkReport +{ + tANI_U8 dialogToken; + tANI_U8 txPower; + tANI_U8 rxAntenna; + tANI_U8 txAntenna; + tANI_U8 rcpi; + tANI_U8 rsni; +} tSirMacLinkReport, *tpSirMacLinkReport; + +#define BEACON_REPORT_MAX_IES 224 //Refer IEEE 802.11k-2008, Table 7-31d +typedef struct sSirMacBeaconReport +{ + tANI_U8 regClass; + tANI_U8 channel; + tANI_U8 measStartTime[8]; + tANI_U8 measDuration; + tANI_U8 phyType; + tANI_U8 bcnProbeRsp; + tANI_U8 rsni; + tANI_U8 rcpi; + tSirMacAddr bssid; + tANI_U8 antennaId; + tANI_U32 parentTSF; + tANI_U8 numIes; + tANI_U8 Ies[BEACON_REPORT_MAX_IES]; + +} tSirMacBeaconReport, *tpSirMacBeaconReport; + +#define RADIO_REPORTS_MAX_IN_A_FRAME 4 +typedef struct sSirMacRadioMeasureReport +{ + tANI_U8 token; + tANI_U8 refused; + tANI_U8 incapable; + tANI_U8 type; + union + { + tSirMacBeaconReport beaconReport; + }report; + +}tSirMacRadioMeasureReport, *tpSirMacRadioMeasureReport; + +#endif + +// QOS action frame definitions + +// max number of possible tclas elements in any frame +#define SIR_MAC_TCLASIE_MAXNUM 2 + +// 11b rate encoding in MAC format + +#define SIR_MAC_RATE_1 0x02 +#define SIR_MAC_RATE_2 0x04 +#define SIR_MAC_RATE_5_5 0x0B +#define SIR_MAC_RATE_11 0x16 + +// 11a/g rate encoding in MAC format + +#define SIR_MAC_RATE_6 0x0C +#define SIR_MAC_RATE_9 0x12 +#define SIR_MAC_RATE_12 0x18 +#define SIR_MAC_RATE_18 0x24 +#define SIR_MAC_RATE_24 0x30 +#define SIR_MAC_RATE_36 0x48 +#define SIR_MAC_RATE_48 0x60 +#define SIR_MAC_RATE_54 0x6C + +// ANI legacy supported rates +#define SIR_MAC_RATE_72 0x01 +#define SIR_MAC_RATE_96 0x03 +#define SIR_MAC_RATE_108 0x05 + +// ANI enhanced rates +#define SIR_MAC_RATE_42 1000 +#define SIR_MAC_RATE_84 1001 +#define SIR_MAC_RATE_126 1002 +#define SIR_MAC_RATE_144 1003 +#define SIR_MAC_RATE_168 1004 +#define SIR_MAC_RATE_192 1005 +#define SIR_MAC_RATE_216 1006 +#define SIR_MAC_RATE_240 1007 + +#define SIR_MAC_RATE_1_BITMAP (1<<0) +#define SIR_MAC_RATE_2_BITMAP (1<<1) +#define SIR_MAC_RATE_5_5_BITMAP (1<<2) +#define SIR_MAC_RATE_11_BITMAP (1<<3) +#define SIR_MAC_RATE_6_BITMAP (1<<4) +#define SIR_MAC_RATE_9_BITMAP (1<<5) +#define SIR_MAC_RATE_12_BITMAP (1<<6) +#define SIR_MAC_RATE_18_BITMAP (1<<7) +#define SIR_MAC_RATE_24_BITMAP (1<<8) +#define SIR_MAC_RATE_36_BITMAP (1<<9) +#define SIR_MAC_RATE_48_BITMAP (1<<10) +#define SIR_MAC_RATE_54_BITMAP (1<<11) + + +#define sirIsArate(x) ((((tANI_U8)x)==SIR_MAC_RATE_6) || \ + (((tANI_U8)x)==SIR_MAC_RATE_9) || \ + (((tANI_U8)x)==SIR_MAC_RATE_12)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_18)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_24)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_36)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_48)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_54)) + +#define sirIsBrate(x) ((((tANI_U8)x)==SIR_MAC_RATE_1) || \ + (((tANI_U8)x)==SIR_MAC_RATE_2) || \ + (((tANI_U8)x)==SIR_MAC_RATE_5_5)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_11)) + +#define sirIsGrate(x) ((((tANI_U8)x)==SIR_MAC_RATE_1) || \ + (((tANI_U8)x)==SIR_MAC_RATE_2) || \ + (((tANI_U8)x)==SIR_MAC_RATE_5_5)|| \ + (((tANI_U8)x)==SIR_MAC_RATE_11) || \ + (((tANI_U8)x)==SIR_MAC_RATE_6) || \ + (((tANI_U8)x)==SIR_MAC_RATE_9) || \ + (((tANI_U8)x)==SIR_MAC_RATE_12) || \ + (((tANI_U8)x)==SIR_MAC_RATE_18) || \ + (((tANI_U8)x)==SIR_MAC_RATE_24) || \ + (((tANI_U8)x)==SIR_MAC_RATE_36) || \ + (((tANI_U8)x)==SIR_MAC_RATE_48) || \ + (((tANI_U8)x)==SIR_MAC_RATE_54)) + +#define SIR_MAC_MIN_IE_LEN 2 // Minimum IE length for IE validation + +#define SIR_MAC_TI_TYPE_REASSOC_DEADLINE 1 +#define SIR_MAC_TI_TYPE_KEY_LIFETIME 2 +#define SIR_MAC_TI_TYPE_ASSOC_COMEBACK 3 + +#define SIR_MAC_VHT_CAP_MAX_MPDU_LEN 0 +#define SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET 2 +#define SIR_MAC_VHT_CAP_LDPC_CODING_CAP 4 +#define SIR_MAC_VHT_CAP_SHORTGI_80MHZ 5 +#define SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ 6 +#define SIR_MAC_VHT_CAP_TXSTBC 7 +#define SIR_MAC_VHT_CAP_RXSTBC 8 +#define SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP 11 +#define SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP 12 +#define SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP 13 +#define SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM 16 +#define SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP 19 +#define SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP 20 +#define SIR_MAC_VHT_CAP_TXOPPS 21 +#define SIR_MAC_VHT_CAP_HTC_CAP 22 +#define SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO 23 +#define SIR_MAC_VHT_CAP_LINK_ADAPT_CAP 26 +#define SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN 28 +#define SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN 29 +#define SIR_MAC_VHT_CAP_RESERVED2 30 + +#define SIR_MAC_HT_CAP_ADVCODING_S 0 +#define SIR_MAC_HT_CAP_CHWIDTH40_S 1 +#define SIR_MAC_HT_CAP_SMPOWERSAVE_DYNAMIC_S 2 +#define SIR_MAC_HT_CAP_SM_RESERVED_S 3 +#define SIR_MAC_HT_CAP_GREENFIELD_S 4 +#define SIR_MAC_HT_CAP_SHORTGI20MHZ_S 5 +#define SIR_MAC_HT_CAP_SHORTGI40MHZ_S 6 +#define SIR_MAC_HT_CAP_TXSTBC_S 7 +#define SIR_MAC_HT_CAP_RXSTBC_S 8 +#define SIR_MAC_HT_CAP_DELAYEDBLKACK_S 10 +#define SIR_MAC_HT_CAP_MAXAMSDUSIZE_S 11 +#define SIR_MAC_HT_CAP_DSSSCCK40_S 12 +#define SIR_MAC_HT_CAP_PSMP_S 13 +#define SIR_MAC_HT_CAP_INTOLERANT40_S 14 +#define SIR_MAC_HT_CAP_LSIGTXOPPROT_S 15 + +#define SIR_MAC_TXSTBC 1 +#define SIR_MAC_RXSTBC 1 + +#endif /* __MAC_PROT_DEFS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirTypes.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirTypes.h new file mode 100644 index 000000000000..4c4f177600a7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirTypes.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file sirTypes.h contains the common types + * + * Author: V. K. Kandarpa + * Date: 04/12/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __SIR_TYPES_H +#define __SIR_TYPES_H + +#include "halTypes.h" + +#define FIRST_SCAN_ID 1 +/* ********************************************** * + * * + * SIRIUS ERROR Codes / Return Codes * + * * + * ********************************************** */ + +/// Return status type +typedef enum eSirRetStatus +{ + eSIR_SUCCESS, + eSIR_FAILURE, + + /// System Errors + eSIR_SYS_ERROR_BASE=0x100, + eSIR_SYS_TX_THREAD_CREATE_FAILED, + eSIR_SYS_TX_THREAD_RESUME_FAILED, + eSIR_SYS_TX_MSG_Q_CREATE_FAILED, + eSIR_SYS_TX_Q_SEND_FAILED, + eSIR_SYS_TX_Q_RECV_FAILED, + eSIR_SYS_TX_TIMER_ACTIVATE_FAILED, + eSIR_SYS_TX_TIMER_CHANGE_FAILED, + eSIR_SYS_TX_TIMER_CREATE_FAILED, + eSIR_MEM_ALLOC_FAILED, + eSIR_PCI_ERROR, + + // Driver Return Codes + eSIR_HAL_ERROR_BASE=0x1000, + eSIR_HAL_STAID_INVALID, // 1 + eSIR_HAL_TCDESC_INVALID, // 2 + eSIR_HAL_TX_WQ_NOT_VALID, // 3 + eSIR_HAL_PREV_BMU_CMD_INCOMPLETE, // 4 + eSIR_HAL_EEPROM_CRC_FAILED, // 5 + eSIR_HAL_PCI_REVID_INVALID, // 6 + eSIR_HAL_STA_TC_ID_INVALID, // 7 + eSIR_HAL_TXWQ_EMPTY, // 8 + eSIR_HAL_ROUT_TBL_TYPE_STYPE_INVALID, // 9 + eSIR_HAL_TFP_ENABLE_FAILED, // a + eSIR_HAL_TFP_ABORT_CMD_FAILED, // b + eSIR_HAL_TFP_TEMPL_BCNLEN_INVALID, // c + eSIR_HAL_TFP_TEMPL_SCHLEN_INVALID, // d + eSIR_HAL_TFP_TEMPL_CFENDLEN_INVALID, // e + eSIR_HAL_TFP_TEMPL_RRLEN_INVALID, // f + eSIR_HAL_TFP_TEMPL_PSPOLLLEN_INVALID, // 10 + eSIR_HAL_TFP_TEMPL_CTSLEN_INVALID, // 11 + eSIR_HAL_TFP_TEMPL_CFPOLLLEN_INVALID, // 12 + eSIR_HAL_TFP_TEMPL_BACKLEN_INVALID, // 13 + eSIR_HAL_INPUT_INVALID, // 14 + eSIR_HAL_GET_PDU_FAILED, // 15 + eSIR_HAL_ADD_STA_ACK_POLICY_INVALID, // 16 + eSIR_HAL_STA_EXISTS, // 17 + eSIR_HAL_STA_DOES_NOT_EXIST, // 18 + eSIR_HAL_MASTER_WQ_ID_INVALID, // 19 + eSIR_HAL_WQ_NOT_EMPTY, // 1a + eSIR_HAL_WQ_EMPTY, // 1b + eSIR_HAL_PDUCNT_AND_NEXTPTR_MISMATCH, // 1c + eSIR_HAL_ERR_NUM_BYTES_TO_BE_SET_TOO_BIG, // 1d + eSIR_HAL_GET_PKT_LENGTH_INVALID, // 1e + eSIR_HAL_AS_CNT_INVALID, // 1f + eSIR_HAL_RFP_AGE_CMD_SEQFAIL, // 20 + eSIR_HAL_RFP_AGE_CMD_AGE_CMD_TCFAIL, // 21 + eSIR_HAL_RFP_AGE_CMD_PASS, // 22 + eSIR_HAL_RFP_AGE_CMD_TIMEDOUT, // 23 + eSIR_HAL_RHP_HASH_CMD_TIMEOUT, // 24 + eSIR_HAL_RHP_ROUTING_TBL_SET_FAILED, // 25 + eSIR_HAL_RHP_ROUTING_TBL_GET_FAILED, // 26 + + eSIR_HAL_CAL_STATUS_CHK_FAILED, + + eSIR_HAL_SYS_ARM_DBG_MODE_SET_FAILED, + eSIR_HAL_TFP_BCN_SENT, + eSIR_HAL_TFP_BCN_NOT_SENT, + eSIR_HAL_TFP_BKOF_ID_INVALID, + eSIR_HAL_TFP_CFB_ENABLE_INPUT_INVALID, + eSIR_HAL_TFP_EDCF_TXOP_INVALID, + eSIR_HAL_TFP_TEMPL_LEN_INVALID, + eSIR_HAL_KEY_ID_INVALID, + eSIR_HAL_KEY_LEN_INVALID, + eSIR_HAL_CHID_INVALID, + eSIR_HAL_HIF_BURST_READ_FAILED, + eSIR_HAL_HIF_BURST_WRITE_FAILED, + eSIR_HAL_HIF_BURST_LEN_REQ_INVALID, + eSIR_HAL_HIF_TX_NO_FRAG_DESC, + + eSIR_HAL_INVALID_PRODUCT_ID, // 44 + + eSIR_HAL_INVALID_CAPABILITY, // 48 + eSIR_HAL_CB_NOT_ENABLED, // 49 + eSIR_HAL_MAC_RATE_INVALID, // 4a + eSIR_HAL_RHP_HANG, // 4b + eSIR_HAL_UNSUPPORTED, // 4c + eSIR_HAL_TSPEC_INVALID, // 4d + + // NIM Return Codes + eSIR_NIM_ERROR_BASE=0x2000, + eSIR_NIM_ERR_INVALID_EVENT, + + + // MMH Return Codes + eSIR_NIM_MMH_ERROR_BASE=0x2100, + eSIR_NIM_MMH_ERR_INV_EVENT, + eSIR_NIM_MMH_ERR_MSG_LEN, + eSIR_NIM_MMH_ERR_IN_Q_TYPE, + + // MNT Return Codes + eSIR_NIM_MNT_ERROR_BASE=0x2140, + + // WDT Errors + eSIR_NIM_WDT_ERROR_BASE=0x2180, + + // LIM Return Codes + eSIR_LIM_ERROR_BASE=0x2200, + eSIR_LIM_IGNORE_BEACON, + eSIR_LIM_INVALID_STA, + eSIR_LIM_MAX_STA_REACHED_ERROR, + + // SCH Return Codes + eSIR_SCH_ERROR_BASE=0x2300, + + // PMM Return Codes + eSIR_PMM_ERROR_BASE=0x2400, + eSIR_PMM_INVALID_MODE, + eSIR_PMM_INVALID_STATE, + eSIR_PMM_INVALID_ROLE, + eSIR_PMM_STA_NOT_ASSOCIATED, + eSIR_PMM_HEART_BEAT_TMOUT, + eSIR_PMM_NTH_BEACON_DELIVERY, + + // ARQ Return Codes + eSIR_ARQ_ERROR_BASE=0x2500, + + // CFG Return Codes + eSIR_CFG_ERROR_BASE=2600, + eSIR_CFG_INVALID_ID, + eSIR_CFG_INVALID_LEN, + + // parser Return Codes + eSIR_PRS_ERROR_BASE=0x2700, + eSIR_IGNORE_IE, + + // Put all your return codes above this line + eSIR_ERROR_LAST + +} tSirRetStatus; + +# endif // __SIR_TYPES_H diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h new file mode 100644 index 000000000000..e027c116705a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h @@ -0,0 +1,729 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file wniApi.h contains message definitions exported by + * Sirius software modules. + * NOTE: See projects/sirius/include/sirApi.h for structure + * definitions of the host/FW messages. + * + * Author: Chandra Modumudi + * Date: 04/11/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __WNI_API_H +#define __WNI_API_H + +// DPH return error codes +#define ANI_DPH_SUCCESS 0 + +#define ANI_DPH_RX_STA_INVALID 1 + +#define ANI_DPH_DO_TKIP 2 + +#define ANI_DPH_PORT_BLOCKED 3 +#define ANI_DPH_TX_PUSH_ERROR 10 +#define ANI_DPH_TX_MAC_HDR_ERROR 11 +#define ANI_DPH_TX_INVALID_PAYLOAD 12 +#define ANI_DPH_TX_STA_INVALID 13 +#define ANI_DPH_TX_HASH_MISS 14 +#define ANI_DPH_TX_UNINITIALIZED 15 +#define ANI_DPH_TX_RADIO_IN_DIAG_MODE 16 +#define ANI_DPH_WMM_DROP 17 +#define ANI_DPH_APSD_DROP 18 +#define ANI_DPH_UNKNOWN_STA 19 + +/// HDD type for special handling of BDs in the TX pkts +/// Used in the structure ani_mod_info_t->bd_spl_proc_type +#define ANI_HDD_NO_SPL_PROC 0 +#define ANI_HDD_DUMMY_PKT_SPL_PROC 1 +#define ANI_HDD_PRE_DUMMY_PKT_SPL_PROC 2 +#define ANI_HDD_WNS_L2_UPDATE_SPL_PROC 3 +#define ANI_HDD_DUMMY_DATA 4 + +/// Message offset for the cmd to enqueue a dummy pkt to HDD TD ring +#define ANI_DUMMY_PKT_MSG_TYPE_OFFSET 0 +#define ANI_DUMMY_PKT_MSG_LEN_OFFSET 2 +#define ANI_DUMMY_PKT_MAC_ADDR_OFFSET 4 +#define ANI_DUMMY_PKT_STA_ID_OFFSET 10 +#define ANI_DUMMY_PKT_RT_FL_OFFSET 12 +#define ANI_DUMMY_PKT_MSG_LEN 16 +#define ANI_DUMMY_DATA_PAYLOAD_OFFSET 10 + + +/// Start of Sirius/Host message types +#define WNI_HOST_MSG_START 0x1500 + +enum eWniMsgTypes +{ + /// CFG message types + eWNI_CFG_MSG_TYPES_BEGIN=WNI_HOST_MSG_START, + eWNI_CFG_MSG_TYPES_END=eWNI_CFG_MSG_TYPES_BEGIN+0xFF, + + /// SME message types + eWNI_SME_MSG_TYPES_BEGIN=eWNI_CFG_MSG_TYPES_END, + eWNI_SME_START_REQ, + eWNI_SME_START_RSP, + eWNI_SME_SYS_READY_IND, + eWNI_SME_SCAN_REQ, + eWNI_SME_SCAN_ABORT_IND, + eWNI_SME_SCAN_RSP, +#ifdef FEATURE_OEM_DATA_SUPPORT + eWNI_SME_OEM_DATA_REQ, + eWNI_SME_OEM_DATA_RSP, +#endif + eWNI_SME_JOIN_REQ, + eWNI_SME_JOIN_RSP, + eWNI_SME_SETCONTEXT_REQ, + eWNI_SME_SETCONTEXT_RSP, + eWNI_SME_REASSOC_REQ, + eWNI_SME_REASSOC_RSP, + eWNI_SME_DISASSOC_REQ, + eWNI_SME_DISASSOC_RSP, + eWNI_SME_DISASSOC_IND, + eWNI_SME_DISASSOC_CNF, + eWNI_SME_DEAUTH_REQ, + eWNI_SME_DEAUTH_RSP, + eWNI_SME_DEAUTH_IND, + eWNI_SME_WM_STATUS_CHANGE_NTF, + eWNI_SME_IBSS_NEW_PEER_IND, + eWNI_SME_IBSS_PEER_DEPARTED_IND, + eWNI_SME_START_BSS_REQ, + eWNI_SME_START_BSS_RSP, + eWNI_SME_AUTH_IND, + eWNI_SME_ASSOC_IND, + eWNI_SME_ASSOC_CNF, + eWNI_SME_REASSOC_IND, + eWNI_SME_REASSOC_CNF, + eWNI_SME_SWITCH_CHL_REQ, + eWNI_SME_SWITCH_CHL_RSP, + eWNI_SME_STOP_BSS_REQ, + eWNI_SME_STOP_BSS_RSP, + eWNI_SME_DEL_BA_PEER_IND, + eWNI_SME_DEFINE_QOS_REQ, + eWNI_SME_DEFINE_QOS_RSP, + eWNI_SME_DELETE_QOS_REQ, + eWNI_SME_DELETE_QOS_RSP, + eWNI_SME_LINK_TEST_START_REQ, + eWNI_SME_LINK_TEST_START_RSP, + eWNI_SME_LINK_TEST_STOP_REQ, + eWNI_SME_LINK_TEST_STOP_RSP, + eWNI_SME_LINK_TEST_REPORT_IND, + eWNI_SME_NEIGHBOR_BSS_IND, + eWNI_SME_MEASUREMENT_REQ, + eWNI_SME_MEASUREMENT_RSP, + eWNI_SME_MEASUREMENT_IND, + eWNI_SME_SET_WDS_INFO_REQ, + eWNI_SME_SET_WDS_INFO_RSP, + eWNI_SME_WDS_INFO_IND, + eWNI_SME_SET_POWER_REQ, + eWNI_SME_SET_POWER_RSP, + eWNI_SME_CLIENT_SIDE_LOAD_BALANCE_REQ, + eWNI_SME_CLIENT_SIDE_LOAD_BALANCE_RSP, + eWNI_SME_SELECT_CHANNEL_REQ, + eWNI_SME_SELECT_CHANNEL_RSP, + eWNI_SME_SET_PROPRIETARY_IE_REQ, + eWNI_SME_SET_PROPRIETARY_IE_RSP, // #endif + eWNI_SME_DISCARD_SKB_NTF, /* Used to clean up SKBs by HDD */ + eWNI_SME_DEAUTH_CNF, + eWNI_SME_MIC_FAILURE_IND, + eWNI_SME_ADDTS_REQ, + eWNI_SME_ADDTS_RSP, + eWNI_SME_ADDTS_CNF, + eWNI_SME_ADDTS_IND, + eWNI_SME_DELTS_REQ, + eWNI_SME_DELTS_RSP, + eWNI_SME_DELTS_IND, + eWNI_SME_SET_BACKGROUND_SCAN_MODE_REQ, + eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ, + eWNI_SME_SWITCH_CHL_CB_PRIMARY_RSP, + eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ, + eWNI_SME_SWITCH_CHL_CB_SECONDARY_RSP, + eWNI_SME_PROBE_REQ, + eWNI_SME_STA_STAT_REQ, + eWNI_SME_STA_STAT_RSP, + eWNI_SME_AGGR_STAT_REQ, + eWNI_SME_AGGR_STAT_RSP, + eWNI_SME_GLOBAL_STAT_REQ, + eWNI_SME_GLOBAL_STAT_RSP, + eWNI_SME_STAT_SUMM_REQ, + eWNI_SME_STAT_SUMM_RSP, + eWNI_SME_REMOVEKEY_REQ, + eWNI_SME_REMOVEKEY_RSP, + eWNI_SME_GET_SCANNED_CHANNEL_REQ, + eWNI_SME_GET_SCANNED_CHANNEL_RSP, + eWNI_SME_SET_TX_POWER_REQ, + eWNI_SME_SET_TX_POWER_RSP, + eWNI_SME_GET_TX_POWER_REQ, + eWNI_SME_GET_TX_POWER_RSP, + eWNI_SME_GET_NOISE_REQ, + eWNI_SME_GET_NOISE_RSP, + eWNI_SME_LOW_RSSI_IND, + eWNI_SME_GET_STATISTICS_REQ, + eWNI_SME_GET_STATISTICS_RSP, + eWNI_SME_GET_RSSI_REQ, + eWNI_SME_GET_ASSOC_STAS_REQ, + eWNI_SME_TKIP_CNTR_MEAS_REQ, + eWNI_SME_UPDATE_APWPSIE_REQ, + eWNI_SME_GET_WPSPBC_SESSION_REQ, + eWNI_SME_WPS_PBC_PROBE_REQ_IND, + eWNI_SME_SET_APWPARSNIEs_REQ, + eWNI_SME_UPPER_LAYER_ASSOC_CNF, + eWNI_SME_HIDE_SSID_REQ, + eWNI_SME_CHNG_MCC_BEACON_INTERVAL, + eWNI_SME_REMAIN_ON_CHANNEL_REQ, + eWNI_SME_REMAIN_ON_CHN_IND, + eWNI_SME_REMAIN_ON_CHN_RSP, + eWNI_SME_MGMT_FRM_IND, + eWNI_SME_REMAIN_ON_CHN_RDY_IND, + eWNI_SME_SEND_ACTION_FRAME_IND, + eWNI_SME_ACTION_FRAME_SEND_CNF, + eWNI_SME_ABORT_REMAIN_ON_CHAN_IND, + eWNI_SME_UPDATE_NOA, + eWNI_SME_CLEAR_DFS_CHANNEL_LIST, + eWNI_SME_CLEAR_LIM_SCAN_CACHE, + eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER, + eWNI_SME_GET_SNR_REQ, + //General Power Save Messages + eWNI_PMC_MSG_TYPES_BEGIN, + eWNI_PMC_PWR_SAVE_CFG, + + //BMPS Messages + eWNI_PMC_ENTER_BMPS_REQ, + eWNI_PMC_ENTER_BMPS_RSP, + eWNI_PMC_EXIT_BMPS_REQ, + eWNI_PMC_EXIT_BMPS_RSP, + eWNI_PMC_EXIT_BMPS_IND, + + //IMPS Messages. + eWNI_PMC_ENTER_IMPS_REQ, + eWNI_PMC_ENTER_IMPS_RSP, + eWNI_PMC_EXIT_IMPS_REQ, + eWNI_PMC_EXIT_IMPS_RSP, + + //UAPSD Messages + eWNI_PMC_ENTER_UAPSD_REQ, + eWNI_PMC_ENTER_UAPSD_RSP, + eWNI_PMC_EXIT_UAPSD_REQ, + eWNI_PMC_EXIT_UAPSD_RSP, + + //WOWL Messages + eWNI_PMC_SMPS_STATE_IND, + + //WoWLAN Messages + eWNI_PMC_WOWL_ADD_BCAST_PTRN, + eWNI_PMC_WOWL_DEL_BCAST_PTRN, + eWNI_PMC_ENTER_WOWL_REQ, + eWNI_PMC_ENTER_WOWL_RSP, + eWNI_PMC_EXIT_WOWL_REQ, + eWNI_PMC_EXIT_WOWL_RSP, + +#ifdef WLAN_FEATURE_PACKET_FILTERING + eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP, +#endif // WLAN_FEATURE_PACKET_FILTERING + +#if defined WLAN_FEATURE_VOWIFI + eWNI_SME_RRM_MSG_TYPE_BEGIN, + + eWNI_SME_NEIGHBOR_REPORT_REQ_IND, + eWNI_SME_NEIGHBOR_REPORT_IND, + eWNI_SME_BEACON_REPORT_REQ_IND, + eWNI_SME_BEACON_REPORT_RESP_XMIT_IND, + +#endif + eWNI_SME_ADD_STA_SELF_REQ, + eWNI_SME_ADD_STA_SELF_RSP, + eWNI_SME_DEL_STA_SELF_REQ, + eWNI_SME_DEL_STA_SELF_RSP, + +#if defined WLAN_FEATURE_VOWIFI_11R + eWNI_SME_FT_PRE_AUTH_REQ, + eWNI_SME_FT_PRE_AUTH_RSP, + eWNI_SME_FT_UPDATE_KEY, + eWNI_SME_FT_AGGR_QOS_REQ, + eWNI_SME_FT_AGGR_QOS_RSP, +#endif + +#if defined FEATURE_WLAN_ESE + eWNI_SME_ESE_ADJACENT_AP_REPORT, +#endif + + eWNI_SME_REGISTER_MGMT_FRAME_REQ, + + eWNI_SME_COEX_IND, + +#ifdef FEATURE_WLAN_SCAN_PNO + eWNI_SME_PREF_NETWORK_FOUND_IND, +#endif // FEATURE_WLAN_SCAN_PNO + + eWNI_SME_TX_PER_HIT_IND, + + eWNI_SME_CHANGE_COUNTRY_CODE, + eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE, + eWNI_SME_PRE_SWITCH_CHL_IND, + eWNI_SME_POST_SWITCH_CHL_IND, + + eWNI_SME_MAX_ASSOC_EXCEEDED, + + /* To serialize the create/accept LL req from HCI */ + eWNI_SME_BTAMP_LOG_LINK_IND, + +#ifdef WLAN_WAKEUP_EVENTS + eWNI_SME_WAKE_REASON_IND, +#endif // WLAN_WAKEUP_EVENTS + eWNI_SME_EXCLUDE_UNENCRYPTED, + eWNI_SME_RSSI_IND, //RSSI indication from TL to be serialized on MC thread +#ifdef FEATURE_WLAN_TDLS + eWNI_SME_TDLS_SEND_MGMT_REQ, + eWNI_SME_TDLS_SEND_MGMT_RSP, + eWNI_SME_TDLS_ADD_STA_REQ, + eWNI_SME_TDLS_ADD_STA_RSP, + eWNI_SME_TDLS_DEL_STA_REQ, + eWNI_SME_TDLS_DEL_STA_RSP, + eWNI_SME_TDLS_DEL_STA_IND, + eWNI_SME_TDLS_DEL_ALL_PEER_IND, + eWNI_SME_MGMT_FRM_TX_COMPLETION_IND, + eWNI_SME_TDLS_LINK_ESTABLISH_REQ, + eWNI_SME_TDLS_LINK_ESTABLISH_RSP, + eWNI_SME_TDLS_SHOULD_DISCOVER, + eWNI_SME_TDLS_SHOULD_TEARDOWN, + eWNI_SME_TDLS_PEER_DISCONNECTED, +#endif + /* + * NOTE: If you are planning to add more messages, please make sure that + * SIR_LIM_ITC_MSG_TYPES_BEGIN is moved appropriately. It is set as + * SIR_LIM_MSG_TYPES_BEGIN+0xB0 = 12B0 (which means max of 176 messages and + * eWNI_SME_TDLS_DEL_STA_RSP = 175. + * Should fix above issue to enable TDLS_INTERNAL + */ + eWNI_SME_SET_BCN_FILTER_REQ, + eWNI_SME_RESET_AP_CAPS_CHANGED, +#ifdef WLAN_FEATURE_11W + eWNI_SME_UNPROT_MGMT_FRM_IND, +#endif +#ifdef WLAN_FEATURE_GTK_OFFLOAD + eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP, +#endif // WLAN_FEATURE_GTK_OFFLOAD + eWNI_SME_CANDIDATE_FOUND_IND, /*ROAM candidate indication from FW*/ + eWNI_SME_HANDOFF_REQ,/*upper layer requested handoff to driver in STA mode*/ + eWNI_SME_ROAM_SCAN_OFFLOAD_RSP,/*Fwd the LFR scan offload rsp from FW to SME*/ +#ifdef FEATURE_WLAN_LPHB + eWNI_SME_LPHB_IND, +#endif /* FEATURE_WLAN_LPHB */ + + eWNI_SME_GET_TSM_STATS_REQ, + eWNI_SME_GET_TSM_STATS_RSP, + eWNI_SME_TSM_IE_IND, + + eWNI_SME_READY_TO_SUSPEND_IND, +#ifdef FEATURE_WLAN_CH_AVOID + eWNI_SME_CH_AVOID_IND, +#endif /* FEATURE_WLAN_CH_AVOID */ + /* DFS EVENTS */ + eWNI_SME_DFS_RADAR_FOUND, //RADAR found indication from DFS + eWNI_SME_CHANNEL_CHANGE_REQ,//Channel Change Request from SAP + eWNI_SME_CHANNEL_CHANGE_RSP,// Channel Change Response from WMA + eWNI_SME_START_BEACON_REQ,//Start Beacon Transmission. + eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ, //Transmit CSA IE in beacons + eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND, //To indicate completion of CSA IE + //update in beacons/probe rsp + eWNI_SME_STATS_EXT_EVENT, + eWNI_SME_LINK_SPEED_IND, /* Indicate link speed response from WMA */ + eWNI_SME_CSA_OFFLOAD_EVENT, + eWNI_SME_UPDATE_ADDITIONAL_IES, // indicates Additional IE from hdd to PE + eWNI_SME_MODIFY_ADDITIONAL_IES, /* To indicate IE modify from hdd to PE */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + eWNI_SME_AUTO_SHUTDOWN_IND, +#endif +#ifdef QCA_HT_2040_COEX + eWNI_SME_SET_HT_2040_MODE, +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + eWNI_SME_ROAM_OFFLOAD_SYNCH_IND, /* Roam Synch Indication from WMA to SME*/ + eWNI_SME_HO_FAIL_IND, /* Hand Off Failure Ind from WMA to SME */ +#endif +#ifdef WLAN_FEATURE_NAN + eWNI_SME_NAN_EVENT, +#endif + eWNI_SME_LINK_STATUS_IND, +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + eWNI_SME_READY_TO_EXTWOW_IND, +#endif + eWNI_SME_MSG_GET_TEMPERATURE_IND, + eWNI_SME_SNR_IND, +#ifdef FEATURE_WLAN_EXTSCAN + eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND, + eWNI_SME_EPNO_NETWORK_FOUND_IND, +#endif + eWNI_SME_FW_STATUS_IND, + eWNI_SME_SET_THERMAL_LEVEL_IND, + + eWNI_SME_OCB_SET_CONFIG_RSP, + eWNI_SME_OCB_GET_TSF_TIMER_RSP, + eWNI_SME_DCC_GET_STATS_RSP, + eWNI_SME_DCC_UPDATE_NDL_RSP, + eWNI_SME_DCC_STATS_EVENT, + + eWNI_SME_TSF_EVENT, + eWNI_SME_FW_DUMP_IND, + eWNI_SME_PDEV_SET_HT_VHT_IE, + eWNI_SME_EXT_CHANGE_CHANNEL, + eWNI_SME_EXT_CHANGE_CHANNEL_IND, + eWNI_SME_LOST_LINK_INFO_IND, + eWNI_SME_GET_RSSI_IND, + eWNI_SME_ROAM_RESTART_REQ, + eWNI_SME_SMPS_FORCE_MODE_IND, + eWNI_SME_MSG_TYPES_END +}; + +typedef enum { + eWNI_TDLS_TEARDOWN_REASON_TX, + eWNI_TDLS_TEARDOWN_REASON_RSSI, + eWNI_TDLS_TEARDOWN_REASON_SCAN, + eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE, + eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT, + eWNI_TDLS_TEARDOWN_REASON_BAD_PTR, + eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE, +} eWniTdlsTeardownReason; + +#define WNI_CFG_MSG_TYPES_BEGIN 0x1200 + +/*---------------------------------------------------------------------*/ +/* CFG Module Definitions */ +/*---------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------*/ +/* CFG message definitions */ +/*---------------------------------------------------------------------*/ +#define WNI_CFG_MSG_HDR_MASK 0xffff0000 +#define WNI_CFG_MSG_LEN_MASK 0x0000ffff +#define WNI_CFG_MB_HDR_LEN 4 +#define WNI_CFG_MAX_PARAM_NUM 32 + + +/*---------------------------------------------------------------------*/ +/* CFG to HDD message types */ +/*---------------------------------------------------------------------*/ +#define WNI_CFG_PARAM_UPDATE_IND (WNI_CFG_MSG_TYPES_BEGIN | 0x00) +#define WNI_CFG_DNLD_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x01) +#define WNI_CFG_DNLD_CNF (WNI_CFG_MSG_TYPES_BEGIN | 0x02) +#define WNI_CFG_GET_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x03) +#define WNI_CFG_SET_CNF (WNI_CFG_MSG_TYPES_BEGIN | 0x04) +#define WNI_CFG_GET_ATTRIB_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x05) +#define WNI_CFG_ADD_GRP_ADDR_CNF (WNI_CFG_MSG_TYPES_BEGIN | 0x06) +#define WNI_CFG_DEL_GRP_ADDR_CNF (WNI_CFG_MSG_TYPES_BEGIN | 0x07) + +#define ANI_CFG_GET_RADIO_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x08) +#define ANI_CFG_GET_PER_STA_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x09) +#define ANI_CFG_GET_AGG_STA_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x0a) +#define ANI_CFG_CLEAR_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x0b) + + +/*---------------------------------------------------------------------*/ +/* CFG to HDD message parameter indices */ + +/* The followings are word indices starting from the message body */ + +/* WNI_CFG_xxxx_xxxx_xxxx: index of parameter */ +/* */ +/* WNI_CFG_xxxx_xxxx_NUM: number of parameters in message */ +/* */ +/* WNI_CFG_xxxx_xxxx_LEN: byte length of message including */ +/* MB header */ +/* */ +/* WNI_CFG_xxxx_xxxx_PARTIAL_LEN: byte length of message including */ +/* parameters and MB header but */ +/* excluding variable data length */ +/*---------------------------------------------------------------------*/ + +// Parameter update indication +#define WNI_CFG_PARAM_UPDATE_IND_PID 0 + +#define WNI_CFG_PARAM_UPDATE_IND_NUM 1 +#define WNI_CFG_PARAM_UPDATE_IND_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_PARAM_UPDATE_IND_NUM << 2)) + +// Configuration download request +#define WNI_CFG_DNLD_REQ_NUM 0 +#define WNI_CFG_DNLD_REQ_LEN WNI_CFG_MB_HDR_LEN + +// Configuration download confirm +#define WNI_CFG_DNLD_CNF_RES 0 + +#define WNI_CFG_DNLD_CNF_NUM 1 +#define WNI_CFG_DNLD_CNF_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_DNLD_CNF_NUM << 2)) +// Get response +#define WNI_CFG_GET_RSP_RES 0 +#define WNI_CFG_GET_RSP_PID 1 +#define WNI_CFG_GET_RSP_PLEN 2 + +#define WNI_CFG_GET_RSP_NUM 3 +#define WNI_CFG_GET_RSP_PARTIAL_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_RSP_NUM << 2)) +// Set confirm +#define WNI_CFG_SET_CNF_RES 0 +#define WNI_CFG_SET_CNF_PID 1 + +#define WNI_CFG_SET_CNF_NUM 2 +#define WNI_CFG_SET_CNF_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_SET_CNF_NUM << 2)) +// Get attribute response +#define WNI_CFG_GET_ATTRIB_RSP_RES 0 +#define WNI_CFG_GET_ATTRIB_RSP_PID 1 +#define WNI_CFG_GET_ATTRIB_RSP_TYPE 2 +#define WNI_CFG_GET_ATTRIB_RSP_PLEN 3 +#define WNI_CFG_GET_ATTRIB_RSP_RW 4 + +#define WNI_CFG_GET_ATTRIB_RSP_NUM 5 +#define WNI_CFG_GET_ATTRIB_RSP_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_ATTRIB_RSP_NUM << 2)) + +// Add group address confirm +#define WNI_CFG_ADD_GRP_ADDR_CNF_RES 0 + +#define WNI_CFG_ADD_GRP_ADDR_CNF_NUM 1 +#define WNI_CFG_ADD_GRP_ADDR_CNF_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_ADD_GRP_ADDR_CNF_NUM << 2)) + +// Delete group address confirm +#define WNI_CFG_DEL_GRP_ADDR_CNF_RES 0 + +#define WNI_CFG_DEL_GRP_ADDR_CNF_NUM 1 +#define WNI_CFG_DEL_GRP_ADDR_CNF_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_DEL_GRP_ADDR_CNF_NUM <<2)) + + +#define IS_CFG_MSG(msg) ((msg & 0xff00) == WNI_CFG_MSG_TYPES_BEGIN) + +// Clear stats types. +#define ANI_CLEAR_ALL_STATS 0 +#define ANI_CLEAR_RX_STATS 1 +#define ANI_CLEAR_TX_STATS 2 +#define ANI_CLEAR_PER_STA_STATS 3 +#define ANI_CLEAR_AGGR_PER_STA_STATS 4 +#define ANI_CLEAR_STAT_TYPES_END 5 + +/*---------------------------------------------------------------------*/ +/* HDD to CFG message types */ +/*---------------------------------------------------------------------*/ +#define WNI_CFG_DNLD_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x80) +#define WNI_CFG_GET_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x81) +#define WNI_CFG_SET_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x82) +#define WNI_CFG_SET_REQ_NO_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x83) //No RSP for this set + +// Shall be removed after stats integration + + +/*---------------------------------------------------------------------*/ +/* HDD to CFG message parameter indices */ +/* */ +/* The followings are word indices starting from the message body */ +/* */ +/* WNI_CFG_xxxx_xxxx_xxxx: index of parameter */ +/* */ +/* WNI_CFG_xxxx_xxxx_NUM: number of parameters in message */ +/* */ +/* WNI_CFG_xxxx_xxxx_LEN: byte length of message including */ +/* MB header */ +/* */ +/* WNI_CFG_xxxx_xxxx_PARTIAL_LEN: byte length of message including */ +/* parameters and MB header but */ +/* excluding variable data length */ +/*---------------------------------------------------------------------*/ + +// Download response +#define WNI_CFG_DNLD_RSP_BIN_LEN 0 + +#define WNI_CFG_DNLD_RSP_NUM 1 +#define WNI_CFG_DNLD_RSP_PARTIAL_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_DNLD_RSP_NUM << 2)) + +// Set parameter request +#define WNI_CFG_SET_REQ_PID 0 +#define WNI_CFG_SET_REQ_PLEN 1 + +/* +// Get attribute request +//#define WNI_CFG_GET_ATTRIB_REQ_PID 0 + +//#define WNI_CFG_GET_ATTRIB_REQ_NUM 1 +//#define WNI_CFG_GET_ATTRIB_REQ_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_ATTRIB_REQ_NUM << 2)) +// Add group address request +#define WNI_CFG_ADD_GRP_ADDR_REQ_MAC_ADDR 0 + +#define WNI_CFG_ADD_GRP_ADDR_REQ_NUM 1 +#define WNI_CFG_ADD_GRP_ADDR_REQ_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_ADD_GRP_ADDR_REQ_NUM << 2)) +// Delete group address request +#define WNI_CFG_DEL_GRP_ADDR_REQ_MAC_ADDR 0 + +#define WNI_CFG_DEL_GRP_ADDR_REQ_NUM 1 +#define WNI_CFG_DEL_GRP_ADDR_REQ_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_DEL_GRP_ADDR_REQ_NUM << 2)) +*/ + + +/*---------------------------------------------------------------------*/ +/* CFG return values */ +/*---------------------------------------------------------------------*/ +#define WNI_CFG_SUCCESS 1 +#define WNI_CFG_NOT_READY 2 +#define WNI_CFG_INVALID_PID 3 +#define WNI_CFG_INVALID_LEN 4 +#define WNI_CFG_RO_PARAM 5 +#define WNI_CFG_WO_PARAM 6 +#define WNI_CFG_INVALID_STAID 7 +#define WNI_CFG_OTHER_ERROR 8 +#define WNI_CFG_NEED_RESTART 9 +#define WNI_CFG_NEED_RELOAD 10 + + +/*---------------------------------------------------------------------*/ +/* CFG definitions */ +/*---------------------------------------------------------------------*/ + +// Shall be removed after integration of stats. +// Get statistic response +#define WNI_CFG_GET_STAT_RSP_RES 0 +#define WNI_CFG_GET_STAT_RSP_PARAMID 1 +#define WNI_CFG_GET_STAT_RSP_VALUE 2 + +#define WNI_CFG_GET_STAT_RSP_NUM 3 +#define WNI_CFG_GET_STAT_RSP_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_STAT_RSP_NUM <<2)) +// Get per station statistic response +#define WNI_CFG_GET_PER_STA_STAT_RSP_RES 0 +#define WNI_CFG_GET_PER_STA_STAT_RSP_STAID 1 +#define WNI_CFG_GET_PER_STA_STAT_RSP_FIRST_PARAM 2 + +// Per STA statistic structure +typedef struct sAniCfgPerStaStatStruct +{ + unsigned long sentAesBlksUcastHi; + unsigned long sentAesBlksUcastLo; + + unsigned long recvAesBlksUcastHi; + unsigned long recvAesBlksUcastLo; + + unsigned long aesFormatErrorUcastCnts; + + unsigned long aesReplaysUcast; + + unsigned long aesDecryptErrUcast; + + unsigned long singleRetryPkts; + + unsigned long failedTxPkts; + + unsigned long ackTimeouts; + + unsigned long multiRetryPkts; + + unsigned long fragTxCntsHi; + unsigned long fragTxCntsLo; + + unsigned long transmittedPktsHi; + unsigned long transmittedPktsLo; + + unsigned long phyStatHi; + unsigned long phyStatLo; +} tCfgPerStaStatStruct, *tpAniCfgPerStaStatStruct; + +#define WNI_CFG_GET_PER_STA_STAT_RSP_NUM 23 +#define WNI_CFG_GET_PER_STA_STAT_RSP_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_PER_STA_STAT_RSP_NUM << 2)) + + +// Shall be removed after integrating stats. +#define WNI_CFG_GET_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x08) +#define WNI_CFG_GET_PER_STA_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x09) +#define WNI_CFG_GET_AGG_STA_STAT_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x0a) +#define WNI_CFG_GET_TX_RATE_CTR_RSP (WNI_CFG_MSG_TYPES_BEGIN | 0x0b) + +#define WNI_CFG_GET_AGG_STA_STAT_RSP_NUM 21 +#define WNI_CFG_GET_AGG_STA_STAT_RSP_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_AGG_STA_STAT_RSP_NUM << 2)) +#define WNI_CFG_GET_AGG_STA_STAT_RSP_RES 0 + + // Get TX rate based stats +#define WNI_CFG_GET_TX_RATE_CTR_RSP_RES 0 + +typedef struct sAniCfgTxRateCtrs +{ +// add the rate counters here + unsigned long TxFrames_1Mbps; + unsigned long TxFrames_2Mbps; + unsigned long TxFrames_5_5Mbps; + unsigned long TxFrames_6Mbps; + unsigned long TxFrames_9Mbps; + unsigned long TxFrames_11Mbps; + unsigned long TxFrames_12Mbps; + unsigned long TxFrames_18Mbps; + unsigned long TxFrames_24Mbps; + unsigned long TxFrames_36Mbps; + unsigned long TxFrames_48Mbps; + unsigned long TxFrames_54Mbps; + unsigned long TxFrames_72Mbps; + unsigned long TxFrames_96Mbps; + unsigned long TxFrames_108Mbps; + +} tAniCfgTxRateCtrs, *tpAniCfgTxRateCtrs; + + +#define WNI_CFG_GET_STAT_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x86) +#define WNI_CFG_GET_PER_STA_STAT_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x87) +#define WNI_CFG_GET_AGG_STA_STAT_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x88) +#define WNI_CFG_GET_TX_RATE_CTR_REQ (WNI_CFG_MSG_TYPES_BEGIN | 0x89) + +// Get statistic request +#define WNI_CFG_GET_STAT_REQ_PARAMID 0 + +#define WNI_CFG_GET_STAT_REQ_NUM 1 +#define WNI_CFG_GET_STAT_REQ_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_STAT_REQ_NUM << 2)) + + // Get per station statistic request +#define WNI_CFG_GET_PER_STA_STAT_REQ_STAID 0 + +#define WNI_CFG_GET_PER_STA_STAT_REQ_NUM 1 +#define WNI_CFG_GET_PER_STA_STAT_REQ_LEN (WNI_CFG_MB_HDR_LEN + \ + (WNI_CFG_GET_PER_STA_STAT_REQ_NUM << 2)) + + + + +#define DYNAMIC_CFG_TYPE_SELECTED_REGISTRAR (0) +#define DYNAMIC_CFG_TYPE_WPS_STATE (1) + +#endif /* __WNI_API_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h new file mode 100644 index 000000000000..268d7496066a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h @@ -0,0 +1,2522 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * DO NOT EDIT - This file is generated automatically + */ + +/* + * IMPORTANT: This file is for system that supports both STA and AP mode. + */ + + +#ifndef __WNICFGAP_H +#define __WNICFGAP_H + +/* + * Configuration Parameter ID for STA and AP + */ + +#define WNI_CFG_STA_ID 0 +#define WNI_CFG_CF_POLLABLE 1 +#define WNI_CFG_CFP_PERIOD 2 +#define WNI_CFG_CFP_MAX_DURATION 3 +#define WNI_CFG_SSID 4 +#define WNI_CFG_BEACON_INTERVAL 5 +#define WNI_CFG_DTIM_PERIOD 6 +#define WNI_CFG_WEP_KEY_LENGTH 7 +#define WNI_CFG_WEP_DEFAULT_KEY_TABLE 8 +#define WNI_CFG_WEP_DEFAULT_KEY_TABLE_ROW 4 +#define WNI_CFG_WEP_DEFAULT_KEY_TABLE_COL 1 +#define WNI_CFG_WEP_DEFAULT_KEY_1 8 +#define WNI_CFG_WEP_DEFAULT_KEY_2 9 +#define WNI_CFG_WEP_DEFAULT_KEY_3 10 +#define WNI_CFG_WEP_DEFAULT_KEY_4 11 +#define WNI_CFG_WEP_DEFAULT_KEYID 12 +#define WNI_CFG_EXCLUDE_UNENCRYPTED 13 +#define WNI_CFG_RTS_THRESHOLD 14 +#define WNI_CFG_SHORT_RETRY_LIMIT 15 +#define WNI_CFG_LONG_RETRY_LIMIT 16 +#define WNI_CFG_FRAGMENTATION_THRESHOLD 17 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME 18 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME 19 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME 20 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME 21 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT 22 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT 23 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT 24 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT 25 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT 26 +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS 27 +#define WNI_CFG_PS_ENABLE_BCN_FILTER 28 +#define WNI_CFG_PS_ENABLE_HEART_BEAT 29 +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR 30 +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT 31 +#define WNI_CFG_RF_SETTLING_TIME_CLK 32 +#define WNI_CFG_SUPPORTED_RATES_11B 33 +#define WNI_CFG_SUPPORTED_RATES_11A 34 +#define WNI_CFG_PHY_MODE 35 +#define WNI_CFG_DOT11_MODE 36 +#define WNI_CFG_OPERATIONAL_RATE_SET 37 +#define WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET 38 +#define WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET 39 +#define WNI_CFG_LISTEN_INTERVAL 40 +#define WNI_CFG_VALID_CHANNEL_LIST 41 +#define WNI_CFG_CURRENT_CHANNEL 42 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ 43 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ 44 +#define WNI_CFG_RATE_ADAPTATION_TYPE 45 +#define WNI_CFG_FIXED_RATE 46 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ 47 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ 48 +#define WNI_CFG_RETRYRATE_POLICY 49 +#define WNI_CFG_RETRYRATE_SECONDARY 50 +#define WNI_CFG_RETRYRATE_TERTIARY 51 +#define WNI_CFG_APSD_ENABLED 52 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE 53 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE 54 +#define WNI_CFG_AUTHENTICATION_TYPE 55 +#define WNI_CFG_CF_POLL_REQUEST 56 +#define WNI_CFG_PRIVACY_ENABLED 57 +#define WNI_CFG_SHORT_PREAMBLE 58 +#define WNI_CFG_SHORT_SLOT_TIME 59 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY 60 +#define WNI_CFG_QOS_ENABLED 61 +#define WNI_CFG_HCF_ENABLED 62 +#define WNI_CFG_RSN_ENABLED 63 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD 64 +#define WNI_CFG_MAX_NUM_PRE_AUTH 65 +#define WNI_CFG_PREAUTH_CLNUP_TIMEOUT 66 +#define WNI_CFG_RELEASE_AID_TIMEOUT 67 +#define WNI_CFG_HEART_BEAT_THRESHOLD 68 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT 69 +#define WNI_CFG_MANUFACTURER_OUI 70 +#define WNI_CFG_MANUFACTURER_NAME 71 +#define WNI_CFG_MODEL_NUMBER 72 +#define WNI_CFG_MODEL_NAME 73 +#define WNI_CFG_MANUFACTURER_PRODUCT_NAME 74 +#define WNI_CFG_MANUFACTURER_PRODUCT_VERSION 75 +#define WNI_CFG_11D_ENABLED 76 +#define WNI_CFG_MAX_TX_POWER_2_4 77 +#define WNI_CFG_MAX_TX_POWER_5 78 +#define WNI_CFG_NETWORK_DENSITY 79 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM 80 +#define WNI_CFG_CURRENT_TX_ANTENNA 81 +#define WNI_CFG_CURRENT_RX_ANTENNA 82 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL 83 +#define WNI_CFG_NEW_BSS_FOUND_IND 84 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED 85 +#define WNI_CFG_AP_NODE_NAME 86 +#define WNI_CFG_COUNTRY_CODE 87 +#define WNI_CFG_11H_ENABLED 88 +#define WNI_CFG_WT_CNF_TIMEOUT 89 +#define WNI_CFG_KEEPALIVE_TIMEOUT 90 +#define WNI_CFG_PROXIMITY 91 +#define WNI_CFG_LOG_LEVEL 92 +#define WNI_CFG_OLBC_DETECT_TIMEOUT 93 +#define WNI_CFG_PROTECTION_ENABLED 94 +#define WNI_CFG_11G_PROTECTION_ALWAYS 95 +#define WNI_CFG_FORCE_POLICY_PROTECTION 96 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED 97 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED 98 +#define WNI_CFG_11G_ONLY_POLICY 99 +#define WNI_CFG_PACKET_CLASSIFICATION 100 +#define WNI_CFG_WME_ENABLED 101 +#define WNI_CFG_ADDTS_RSP_TIMEOUT 102 +#define WNI_CFG_MAX_SP_LENGTH 103 +#define WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD 104 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS 105 +#define WNI_CFG_WSM_ENABLED 106 +#define WNI_CFG_EDCA_PROFILE 107 +#define WNI_CFG_EDCA_ANI_ACBK_LOCAL 108 +#define WNI_CFG_EDCA_ANI_ACBE_LOCAL 109 +#define WNI_CFG_EDCA_ANI_ACVI_LOCAL 110 +#define WNI_CFG_EDCA_ANI_ACVO_LOCAL 111 +#define WNI_CFG_EDCA_ANI_ACBK 112 +#define WNI_CFG_EDCA_ANI_ACBE 113 +#define WNI_CFG_EDCA_ANI_ACVI 114 +#define WNI_CFG_EDCA_ANI_ACVO 115 +#define WNI_CFG_EDCA_WME_ACBK_LOCAL 116 +#define WNI_CFG_EDCA_WME_ACBE_LOCAL 117 +#define WNI_CFG_EDCA_WME_ACVI_LOCAL 118 +#define WNI_CFG_EDCA_WME_ACVO_LOCAL 119 +#define WNI_CFG_EDCA_WME_ACBK 120 +#define WNI_CFG_EDCA_WME_ACBE 121 +#define WNI_CFG_EDCA_WME_ACVI 122 +#define WNI_CFG_EDCA_WME_ACVO 123 +#define WNI_CFG_RDET_FLAG 124 +#define WNI_CFG_RADAR_CHANNEL_LIST 125 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT 126 +#define WNI_CFG_ADMIT_POLICY 127 +#define WNI_CFG_ADMIT_BWFACTOR 128 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE 129 +#define WNI_CFG_CHANNEL_BONDING_MODE 130 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE 131 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO 132 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE 133 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO 134 +#define WNI_CFG_TRIG_STA_BK_SCAN 135 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING 136 +#define WNI_CFG_SCAN_CONTROL_LIST 137 +#define WNI_CFG_MIMO_ENABLED 138 +#define WNI_CFG_BLOCK_ACK_ENABLED 139 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT 140 +#define WNI_CFG_HT_RX_STBC 141 +#define WNI_CFG_HT_CAP_INFO 142 +#define WNI_CFG_HT_AMPDU_PARAMS 143 +#define WNI_CFG_SUPPORTED_MCS_SET 144 +#define WNI_CFG_EXT_HT_CAP_INFO 145 +#define WNI_CFG_TX_BF_CAP 146 +#define WNI_CFG_AS_CAP 147 +#define WNI_CFG_HT_INFO_FIELD1 148 +#define WNI_CFG_HT_INFO_FIELD2 149 +#define WNI_CFG_HT_INFO_FIELD3 150 +#define WNI_CFG_BASIC_MCS_SET 151 +#define WNI_CFG_CURRENT_MCS_SET 152 +#define WNI_CFG_GREENFIELD_CAPABILITY 153 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH 154 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET 155 +#define WNI_CFG_VHT_LDPC_CODING_CAP 156 +#define WNI_CFG_VHT_SHORT_GI_80MHZ 157 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ 158 +#define WNI_CFG_VHT_TXSTBC 159 +#define WNI_CFG_VHT_RXSTBC 160 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP 161 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP 162 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED 163 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS 164 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP 165 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP 166 +#define WNI_CFG_VHT_TXOP_PS 167 +#define WNI_CFG_VHT_HTC_VHTC_CAP 168 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT 169 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP 170 +#define WNI_CFG_VHT_RX_ANT_PATTERN 171 +#define WNI_CFG_VHT_TX_ANT_PATTERN 172 +#define WNI_CFG_VHT_RX_MCS_MAP 173 +#define WNI_CFG_VHT_TX_MCS_MAP 174 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE 175 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE 176 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1 177 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2 178 +#define WNI_CFG_VHT_BASIC_MCS_SET 179 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT 180 +#define WNI_CFG_VHT_SS_UNDER_UTIL 181 +#define WNI_CFG_VHT_40MHZ_UTILIZATION 182 +#define WNI_CFG_VHT_80MHZ_UTILIZATION 183 +#define WNI_CFG_VHT_160MHZ_UTILIZATION 184 +#define WNI_CFG_MAX_AMSDU_LENGTH 185 +#define WNI_CFG_MPDU_DENSITY 186 +#define WNI_CFG_NUM_BUFF_ADVERT 187 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR 188 +#define WNI_CFG_SHORT_GI_20MHZ 189 +#define WNI_CFG_SHORT_GI_40MHZ 190 +#define WNI_CFG_RIFS_ENABLED 191 +#define WNI_CFG_MAX_PS_POLL 192 +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE 193 +#define WNI_CFG_RSSI_FILTER_PERIOD 194 +#define WNI_CFG_MIN_RSSI_THRESHOLD 195 +#define WNI_CFG_NTH_BEACON_FILTER 196 +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE 197 +#define WNI_CFG_SCAN_IN_POWERSAVE 198 +#define WNI_CFG_IGNORE_DTIM 199 +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE 200 +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE 201 +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE 202 +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE 203 +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON 204 +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD 205 +#define WNI_CFG_BA_TIMEOUT 206 +#define WNI_CFG_BA_THRESHOLD_HIGH 207 +#define WNI_CFG_MAX_BA_BUFFERS 208 +#define WNI_CFG_MAX_BA_SESSIONS 209 +#define WNI_CFG_BA_AUTO_SETUP 210 +#define WNI_CFG_ADDBA_REQ_DECLINE 211 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC 212 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST 213 +#define WNI_CFG_MAX_MEDIUM_TIME 214 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU 215 +#define WNI_CFG_IBSS_AUTO_BSSID 216 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 217 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 218 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 219 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 220 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 221 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 222 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 223 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 224 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 225 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 226 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 227 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 228 +#define WNI_CFG_WPS_ENABLE 229 +#define WNI_CFG_WPS_STATE 230 +#define WNI_CFG_WPS_PROBE_REQ_FLAG 231 +#define WNI_CFG_WPS_VERSION 232 +#define WNI_CFG_WPS_REQUEST_TYPE 233 +#define WNI_CFG_WPS_CFG_METHOD 234 +#define WNI_CFG_WPS_UUID 235 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 236 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 237 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 238 +#define WNI_CFG_WPS_ASSOCIATION_STATE 239 +#define WNI_CFG_WPS_CONFIGURATION_ERROR 240 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 241 +#define WNI_CFG_WPS_ASSOC_METHOD 242 +#define WNI_CFG_LOW_GAIN_OVERRIDE 243 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 244 +#define WNI_CFG_RPE_POLLING_THRESHOLD 245 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 246 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 247 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 248 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 249 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 250 +#define WNI_CFG_SINGLE_TID_RC 251 +#define WNI_CFG_TX_PWR_CTRL_ENABLE 252 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 253 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 254 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 255 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 256 +#define WNI_CFG_TELE_BCN_WAKEUP_EN 257 +#define WNI_CFG_TELE_BCN_TRANS_LI 258 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 259 +#define WNI_CFG_TELE_BCN_MAX_LI 260 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 261 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 262 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 263 +#define WNI_CFG_ASSOC_STA_LIMIT 264 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 265 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 266 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 267 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 268 +#define WNI_CFG_ENABLE_CLOSE_LOOP 269 +#define WNI_CFG_ENABLE_LTE_COEX 270 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 271 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 272 +#define WNI_CFG_ENABLE_MC_ADDR_LIST 273 +#define WNI_CFG_ENABLE_UC_FILTER 274 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 275 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 276 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 277 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 278 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK 279 +#define WNI_CFG_TDLS_BUF_STA_ENABLED 280 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME 281 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD 282 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES 283 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL 284 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN 285 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR 286 +#define WNI_CFG_ANTENNA_DIVESITY 287 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT 288 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY 289 +#define WNI_CFG_CURRENT_RSSI 290 +#define WNI_CFG_RTT3_ENABLE 291 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL 292 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED 293 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE 294 +#define WNI_CFG_DFS_MASTER_ENABLED 295 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ 296 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED 297 + +/* + * String parameter lengths + */ + +#define WNI_CFG_STA_ID_LEN 6 +#define WNI_CFG_SSID_LEN 32 +#define WNI_CFG_WEP_DEFAULT_KEY_1_LEN 13 +#define WNI_CFG_WEP_DEFAULT_KEY_2_LEN 13 +#define WNI_CFG_WEP_DEFAULT_KEY_3_LEN 13 +#define WNI_CFG_WEP_DEFAULT_KEY_4_LEN 13 +#define WNI_CFG_SUPPORTED_RATES_11B_LEN 4 +#define WNI_CFG_SUPPORTED_RATES_11A_LEN 8 +#define WNI_CFG_OPERATIONAL_RATE_SET_LEN 12 +#define WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN 8 +#define WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET_LEN 4 +#define WNI_CFG_VALID_CHANNEL_LIST_LEN 100 +#define WNI_CFG_MANUFACTURER_OUI_LEN 3 +#define WNI_CFG_MANUFACTURER_NAME_LEN 64 +#define WNI_CFG_MODEL_NUMBER_LEN 32 +#define WNI_CFG_MODEL_NAME_LEN 32 +#define WNI_CFG_MANUFACTURER_PRODUCT_NAME_LEN 32 +#define WNI_CFG_MANUFACTURER_PRODUCT_VERSION_LEN 32 +#define WNI_CFG_MAX_TX_POWER_2_4_LEN 128 +#define WNI_CFG_MAX_TX_POWER_5_LEN 128 +#define WNI_CFG_AP_NODE_NAME_LEN 32 +#define WNI_CFG_COUNTRY_CODE_LEN 3 +#define WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACBE_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVI_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVO_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACBK_LEN 20 +#define WNI_CFG_EDCA_ANI_ACBE_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVI_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVO_LEN 20 +#define WNI_CFG_EDCA_WME_ACBK_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACBE_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACVI_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACVO_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACBK_LEN 20 +#define WNI_CFG_EDCA_WME_ACBE_LEN 20 +#define WNI_CFG_EDCA_WME_ACVI_LEN 20 +#define WNI_CFG_EDCA_WME_ACVO_LEN 20 +#define WNI_CFG_RADAR_CHANNEL_LIST_LEN 20 +#define WNI_CFG_SCAN_CONTROL_LIST_LEN 128 +#define WNI_CFG_SUPPORTED_MCS_SET_LEN 16 +#define WNI_CFG_BASIC_MCS_SET_LEN 16 +#define WNI_CFG_CURRENT_MCS_SET_LEN 16 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN 100 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA_LEN 255 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN 255 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2_LEN 255 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3_LEN 255 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN 255 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA_LEN 255 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN 255 +#define WNI_CFG_WPS_UUID_LEN 16 + +/* + * Integer parameter min/max/default values + */ + +#define WNI_CFG_CF_POLLABLE_APMIN 0 +#define WNI_CFG_CF_POLLABLE_APMAX 1 +#define WNI_CFG_CF_POLLABLE_APDEF 0 + +#define WNI_CFG_CFP_PERIOD_STAMIN 0 +#define WNI_CFG_CFP_PERIOD_STAMAX 255 +#define WNI_CFG_CFP_PERIOD_STADEF 1 + +#define WNI_CFG_CFP_PERIOD_APMIN 0 +#define WNI_CFG_CFP_PERIOD_APMAX 255 +#define WNI_CFG_CFP_PERIOD_APDEF 1 + +#define WNI_CFG_CFP_MAX_DURATION_STAMIN 0 +#define WNI_CFG_CFP_MAX_DURATION_STAMAX 65535 +#define WNI_CFG_CFP_MAX_DURATION_STADEF 30000 + +#define WNI_CFG_CFP_MAX_DURATION_APMIN 0 +#define WNI_CFG_CFP_MAX_DURATION_APMAX 65535 +#define WNI_CFG_CFP_MAX_DURATION_APDEF 30000 + +#define WNI_CFG_BEACON_INTERVAL_STAMIN 0 +#define WNI_CFG_BEACON_INTERVAL_STAMAX 65535 +#define WNI_CFG_BEACON_INTERVAL_STADEF 100 + +#define WNI_CFG_BEACON_INTERVAL_APMIN 0 +#define WNI_CFG_BEACON_INTERVAL_APMAX 65535 +#define WNI_CFG_BEACON_INTERVAL_APDEF 100 + +#define WNI_CFG_DTIM_PERIOD_STAMIN 0 +#define WNI_CFG_DTIM_PERIOD_STAMAX 65535 +#define WNI_CFG_DTIM_PERIOD_STADEF 1 + +#define WNI_CFG_DTIM_PERIOD_APMIN 0 +#define WNI_CFG_DTIM_PERIOD_APMAX 65535 +#define WNI_CFG_DTIM_PERIOD_APDEF 1 + +#define WNI_CFG_WEP_KEY_LENGTH_STAMIN 5 +#define WNI_CFG_WEP_KEY_LENGTH_STAMAX 13 +#define WNI_CFG_WEP_KEY_LENGTH_STADEF 5 + +#define WNI_CFG_WEP_KEY_LENGTH_APMIN 5 +#define WNI_CFG_WEP_KEY_LENGTH_APMAX 13 +#define WNI_CFG_WEP_KEY_LENGTH_APDEF 5 + +#define WNI_CFG_WEP_KEY_LENGTH_5 5 +#define WNI_CFG_WEP_KEY_LENGTH_13 13 + +#define WNI_CFG_WEP_DEFAULT_KEYID_STAMIN 0 +#define WNI_CFG_WEP_DEFAULT_KEYID_STAMAX 3 +#define WNI_CFG_WEP_DEFAULT_KEYID_STADEF 0 + +#define WNI_CFG_WEP_DEFAULT_KEYID_APMIN 0 +#define WNI_CFG_WEP_DEFAULT_KEYID_APMAX 3 +#define WNI_CFG_WEP_DEFAULT_KEYID_APDEF 0 + +#define WNI_CFG_WEP_DEFAULT_KEYID_0 0 +#define WNI_CFG_WEP_DEFAULT_KEYID_1 1 +#define WNI_CFG_WEP_DEFAULT_KEYID_2 2 +#define WNI_CFG_WEP_DEFAULT_KEYID_3 3 + +#define WNI_CFG_EXCLUDE_UNENCRYPTED_STAMIN 0 +#define WNI_CFG_EXCLUDE_UNENCRYPTED_STAMAX 1 +#define WNI_CFG_EXCLUDE_UNENCRYPTED_STADEF 0 + +#define WNI_CFG_EXCLUDE_UNENCRYPTED_APMIN 0 +#define WNI_CFG_EXCLUDE_UNENCRYPTED_APMAX 1 +#define WNI_CFG_EXCLUDE_UNENCRYPTED_APDEF 0 + +#define WNI_CFG_RTS_THRESHOLD_STAMIN 0 +#define WNI_CFG_RTS_THRESHOLD_STAMAX 1048576 +#define WNI_CFG_RTS_THRESHOLD_STADEF 2347 + +#define WNI_CFG_RTS_THRESHOLD_APMIN 0 +#define WNI_CFG_RTS_THRESHOLD_APMAX 1048576 +#define WNI_CFG_RTS_THRESHOLD_APDEF 2347 + +#define WNI_CFG_SHORT_RETRY_LIMIT_STAMIN 0 +#define WNI_CFG_SHORT_RETRY_LIMIT_STAMAX 255 +#define WNI_CFG_SHORT_RETRY_LIMIT_STADEF 6 + +#define WNI_CFG_SHORT_RETRY_LIMIT_APMIN 0 +#define WNI_CFG_SHORT_RETRY_LIMIT_APMAX 255 +#define WNI_CFG_SHORT_RETRY_LIMIT_APDEF 6 + +#define WNI_CFG_LONG_RETRY_LIMIT_STAMIN 0 +#define WNI_CFG_LONG_RETRY_LIMIT_STAMAX 255 +#define WNI_CFG_LONG_RETRY_LIMIT_STADEF 6 + +#define WNI_CFG_LONG_RETRY_LIMIT_APMIN 0 +#define WNI_CFG_LONG_RETRY_LIMIT_APMAX 255 +#define WNI_CFG_LONG_RETRY_LIMIT_APDEF 6 + +#define WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN 256 +#define WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX 8000 +#define WNI_CFG_FRAGMENTATION_THRESHOLD_STADEF 8000 + +#define WNI_CFG_FRAGMENTATION_THRESHOLD_APMIN 256 +#define WNI_CFG_FRAGMENTATION_THRESHOLD_APMAX 8000 +#define WNI_CFG_FRAGMENTATION_THRESHOLD_APDEF 8000 + +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STADEF 20 + +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_APMIN 0 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_APMAX 65535 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_APDEF 20 + +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STADEF 40 + +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_APMIN 0 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_APMAX 65535 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_APDEF 40 + +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STADEF 60 + +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_APMIN 0 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_APMAX 65535 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_APDEF 60 + +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STADEF 110 + +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_APMIN 0 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_APMAX 65535 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_APDEF 110 + +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF 3000 + +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_APMIN 0 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_APMAX 65535 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_APDEF 3000 + +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STADEF 1000 + +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_APMIN 0 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_APMAX 65535 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_APDEF 1000 + +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STAMIN 0 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STADEF 1000 + +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_APMIN 0 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_APMAX 65535 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_APDEF 1000 + +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STADEF 2000 + +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_APMIN 0 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_APMAX 65535 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_APDEF 3000 + +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STADEF 1000 + +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_APMIN 0 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_APMAX 65535 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_APDEF 3000 + +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STAMIN 0 +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STAMAX 65535 +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STADEF 1000 + +#define WNI_CFG_PS_ENABLE_BCN_FILTER_STAMIN 0 +#define WNI_CFG_PS_ENABLE_BCN_FILTER_STAMAX 1 +#define WNI_CFG_PS_ENABLE_BCN_FILTER_STADEF 1 + +#define WNI_CFG_PS_ENABLE_HEART_BEAT_STAMIN 0 +#define WNI_CFG_PS_ENABLE_HEART_BEAT_STAMAX 1 +#define WNI_CFG_PS_ENABLE_HEART_BEAT_STADEF 1 + +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR_STAMIN 0 +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR_STAMAX 1 +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR_STADEF 0 + +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STAMIN 1 +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STAMAX 255 +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STADEF 20 + +#define WNI_CFG_RF_SETTLING_TIME_CLK_STAMIN 0 +#define WNI_CFG_RF_SETTLING_TIME_CLK_STAMAX 60000 +#define WNI_CFG_RF_SETTLING_TIME_CLK_STADEF 1500 + +#define WNI_CFG_PHY_MODE_STAMIN 0 +#define WNI_CFG_PHY_MODE_STAMAX 3 +#define WNI_CFG_PHY_MODE_STADEF 0 + +#define WNI_CFG_PHY_MODE_APMIN 0 +#define WNI_CFG_PHY_MODE_APMAX 3 +#define WNI_CFG_PHY_MODE_APDEF 0 + +#define WNI_CFG_PHY_MODE_11A 0 +#define WNI_CFG_PHY_MODE_11B 1 +#define WNI_CFG_PHY_MODE_11G 2 +#define WNI_CFG_PHY_MODE_NONE 3 + +#define WNI_CFG_DOT11_MODE_STAMIN 0 +#define WNI_CFG_DOT11_MODE_STAMAX 11 +#define WNI_CFG_DOT11_MODE_STADEF 0 + +#define WNI_CFG_DOT11_MODE_APMIN 0 +#define WNI_CFG_DOT11_MODE_APMAX 11 +#define WNI_CFG_DOT11_MODE_APDEF 0 + +#define WNI_CFG_DOT11_MODE_ALL 0 +#define WNI_CFG_DOT11_MODE_11A 1 +#define WNI_CFG_DOT11_MODE_11B 2 +#define WNI_CFG_DOT11_MODE_11G 3 +#define WNI_CFG_DOT11_MODE_11N 4 +#define WNI_CFG_DOT11_MODE_11G_ONLY 5 +#define WNI_CFG_DOT11_MODE_11N_ONLY 6 +#define WNI_CFG_DOT11_MODE_11AC 7 +#define WNI_CFG_DOT11_MODE_11AC_ONLY 8 + +#define WNI_CFG_LISTEN_INTERVAL_STAMIN 0 +#define WNI_CFG_LISTEN_INTERVAL_STAMAX 65535 +#define WNI_CFG_LISTEN_INTERVAL_STADEF 1 + +#define WNI_CFG_LISTEN_INTERVAL_APMIN 0 +#define WNI_CFG_LISTEN_INTERVAL_APMAX 65535 +#define WNI_CFG_LISTEN_INTERVAL_APDEF 1 + +#define WNI_CFG_CURRENT_CHANNEL_STAMIN 0 +#define WNI_CFG_CURRENT_CHANNEL_STAMAX 165 +#define WNI_CFG_CURRENT_CHANNEL_STADEF 1 + +#define WNI_CFG_CURRENT_CHANNEL_APMIN 0 +#define WNI_CFG_CURRENT_CHANNEL_APMAX 165 +#define WNI_CFG_CURRENT_CHANNEL_APDEF 1 + +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STAMIN 0 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STAMAX 11 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STADEF 5 + +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_APMIN 0 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_APMAX 11 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_APDEF 5 + +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STAMIN 0 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STAMAX 31 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STADEF 1 + +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_APMIN 0 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_APMAX 31 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_APDEF 1 + +#define WNI_CFG_RATE_ADAPTATION_TYPE_STAMIN 0 +#define WNI_CFG_RATE_ADAPTATION_TYPE_STAMAX 2 +#define WNI_CFG_RATE_ADAPTATION_TYPE_STADEF 1 + +#define WNI_CFG_RATE_ADAPTATION_TYPE_APMIN 0 +#define WNI_CFG_RATE_ADAPTATION_TYPE_APMAX 2 +#define WNI_CFG_RATE_ADAPTATION_TYPE_APDEF 1 + +#define WNI_CFG_RATE_ADAPTATION_TYPE_FIXED 0 +#define WNI_CFG_RATE_ADAPTATION_TYPE_AUTO 1 +#define WNI_CFG_RATE_ADAPTATION_TYPE_SNR_BASED 2 + +#define WNI_CFG_FIXED_RATE_STAMIN 0 +#define WNI_CFG_FIXED_RATE_STAMAX 44 +#define WNI_CFG_FIXED_RATE_STADEF 0 + +#define WNI_CFG_FIXED_RATE_APMIN 0 +#define WNI_CFG_FIXED_RATE_APMAX 44 +#define WNI_CFG_FIXED_RATE_APDEF 0 + +#define WNI_CFG_FIXED_RATE_AUTO 0 +#define WNI_CFG_FIXED_RATE_1MBPS 1 +#define WNI_CFG_FIXED_RATE_2MBPS 2 +#define WNI_CFG_FIXED_RATE_5_5MBPS 3 +#define WNI_CFG_FIXED_RATE_11MBPS 4 +#define WNI_CFG_FIXED_RATE_6MBPS 5 +#define WNI_CFG_FIXED_RATE_9MBPS 6 +#define WNI_CFG_FIXED_RATE_12MBPS 7 +#define WNI_CFG_FIXED_RATE_18MBPS 8 +#define WNI_CFG_FIXED_RATE_24MBPS 9 +#define WNI_CFG_FIXED_RATE_36MBPS 10 +#define WNI_CFG_FIXED_RATE_48MBPS 11 +#define WNI_CFG_FIXED_RATE_54MBPS 12 +#define WNI_CFG_FIXED_RATE_6_5MBPS_MCS0_20MHZ_SIMO 13 +#define WNI_CFG_FIXED_RATE_13MBPS_MCS1_20MHZ_SIMO 14 +#define WNI_CFG_FIXED_RATE_19_5MBPS_MCS2_20MHZ_SIMO 15 +#define WNI_CFG_FIXED_RATE_26MBPS_MCS3_20MHZ_SIMO 16 +#define WNI_CFG_FIXED_RATE_39MBPS_MCS4_20MHZ_SIMO 17 +#define WNI_CFG_FIXED_RATE_52MBPS_MCS5_20MHZ_SIMO 18 +#define WNI_CFG_FIXED_RATE_58_5MBPS_MCS6_20MHZ_SIMO 19 +#define WNI_CFG_FIXED_RATE_65MBPS_MCS7_20MHZ_SIMO 20 +#define WNI_CFG_FIXED_RATE_7_2MBPS_MCS0_20MHZ_SIMO_SGI 21 +#define WNI_CFG_FIXED_RATE_14_4MBPS_MCS1_20MHZ_SIMO_SGI 22 +#define WNI_CFG_FIXED_RATE_21_7MBPS_MCS2_20MHZ_SIMO_SGI 23 +#define WNI_CFG_FIXED_RATE_28_9MBPS_MCS3_20MHZ_SIMO_SGI 24 +#define WNI_CFG_FIXED_RATE_43_3MBPS_MCS4_20MHZ_SIMO_SGI 25 +#define WNI_CFG_FIXED_RATE_57_8MBPS_MCS5_20MHZ_SIMO_SGI 26 +#define WNI_CFG_FIXED_RATE_65MBPS_MCS6_20MHZ_SIMO_SGI 27 +#define WNI_CFG_FIXED_RATE_72_2MBPS_MCS7_20MHZ_SIMO_SGI 28 +#define WNI_CFG_FIXED_RATE_0_25MBPS_SLR_20MHZ_SIMO 29 +#define WNI_CFG_FIXED_RATE_0_5MBPS_SLR_20MHZ_SIMO 30 +#define WNI_CFG_FIXED_RATE_68_25MBPS_QC_PROP_20MHZ_SIMO 31 +#define WNI_CFG_FIXED_RATE_54MBPS_MCS3_40MHZ_SIMO 32 +#define WNI_CFG_FIXED_RATE_81MBPS_MCS4_40MHZ_SIMO 33 +#define WNI_CFG_FIXED_RATE_108MBPS_MCS5_40MHZ_SIMO 34 +#define WNI_CFG_FIXED_RATE_121_5MBPS_MCS6_40MHZ_SIMO 35 +#define WNI_CFG_FIXED_RATE_135MBPS_MCS7_40MHZ_SIMO 36 +#define WNI_CFG_FIXED_RATE_15MBPS_MCS0_40MHZ_SIMO_SGI 37 +#define WNI_CFG_FIXED_RATE_30MBPS_MCS1_40MHZ_SIMO_SGI 38 +#define WNI_CFG_FIXED_RATE_45MBPS_MCS2_40MHZ_SIMO_SGI 39 +#define WNI_CFG_FIXED_RATE_60MBPS_MCS3_40MHZ_SIMO_SGI 40 +#define WNI_CFG_FIXED_RATE_90MBPS_MCS4_40MHZ_SIMO_SGI 41 +#define WNI_CFG_FIXED_RATE_120MBPS_MCS5_40MHZ_SIMO_SGI 42 +#define WNI_CFG_FIXED_RATE_135MBPS_MCS6_40MHZ_SIMO_SGI 43 +#define WNI_CFG_FIXED_RATE_150MBPS_MCS7_40MHZ_SIMO_SGI 44 + +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STAMIN 0 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STAMAX 31 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STADEF 1 + +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_APMIN 0 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_APMAX 31 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_APDEF 1 + +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STAMIN 0 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STAMAX 31 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STADEF 5 + +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_APMIN 0 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_APMAX 31 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_APDEF 5 + +#define WNI_CFG_RETRYRATE_POLICY_STAMIN 0 +#define WNI_CFG_RETRYRATE_POLICY_STAMAX 255 +#define WNI_CFG_RETRYRATE_POLICY_STADEF 4 + +#define WNI_CFG_RETRYRATE_POLICY_APMIN 0 +#define WNI_CFG_RETRYRATE_POLICY_APMAX 255 +#define WNI_CFG_RETRYRATE_POLICY_APDEF 4 + +#define WNI_CFG_RETRYRATE_POLICY_MIN_SUPPORTED 0 +#define WNI_CFG_RETRYRATE_POLICY_PRIMARY 1 +#define WNI_CFG_RETRYRATE_POLICY_RESERVED 2 +#define WNI_CFG_RETRYRATE_POLICY_CLOSEST 3 +#define WNI_CFG_RETRYRATE_POLICY_AUTOSELECT 4 +#define WNI_CFG_RETRYRATE_POLICY_MAX 5 + +#define WNI_CFG_RETRYRATE_SECONDARY_STAMIN 0 +#define WNI_CFG_RETRYRATE_SECONDARY_STAMAX 255 +#define WNI_CFG_RETRYRATE_SECONDARY_STADEF 0 + +#define WNI_CFG_RETRYRATE_SECONDARY_APMIN 0 +#define WNI_CFG_RETRYRATE_SECONDARY_APMAX 255 +#define WNI_CFG_RETRYRATE_SECONDARY_APDEF 0 + +#define WNI_CFG_RETRYRATE_TERTIARY_STAMIN 0 +#define WNI_CFG_RETRYRATE_TERTIARY_STAMAX 255 +#define WNI_CFG_RETRYRATE_TERTIARY_STADEF 0 + +#define WNI_CFG_RETRYRATE_TERTIARY_APMIN 0 +#define WNI_CFG_RETRYRATE_TERTIARY_APMAX 255 +#define WNI_CFG_RETRYRATE_TERTIARY_APDEF 0 + +#define WNI_CFG_APSD_ENABLED_STAMIN 0 +#define WNI_CFG_APSD_ENABLED_STAMAX 1 +#define WNI_CFG_APSD_ENABLED_STADEF 0 + +#define WNI_CFG_APSD_ENABLED_APMIN 0 +#define WNI_CFG_APSD_ENABLED_APMAX 1 +#define WNI_CFG_APSD_ENABLED_APDEF 0 + +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_STAMIN 0 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_STAMAX 1 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_STADEF 1 + +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_APMIN 0 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_APMAX 1 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_APDEF 1 + +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STAMIN 0 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STAMAX 1 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STADEF 1 + +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_APMIN 0 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_APMAX 1 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_APDEF 1 + +#define WNI_CFG_AUTHENTICATION_TYPE_STAMIN 0 +#define WNI_CFG_AUTHENTICATION_TYPE_STAMAX 65535 +#define WNI_CFG_AUTHENTICATION_TYPE_STADEF 0 + +#define WNI_CFG_AUTHENTICATION_TYPE_APMIN 0 +#define WNI_CFG_AUTHENTICATION_TYPE_APMAX 65535 +#define WNI_CFG_AUTHENTICATION_TYPE_APDEF 0 + +#define WNI_CFG_CF_POLL_REQUEST_APMIN 0 +#define WNI_CFG_CF_POLL_REQUEST_APMAX 1 +#define WNI_CFG_CF_POLL_REQUEST_APDEF 0 + +#define WNI_CFG_PRIVACY_ENABLED_STAMIN 0 +#define WNI_CFG_PRIVACY_ENABLED_STAMAX 1 +#define WNI_CFG_PRIVACY_ENABLED_STADEF 0 + +#define WNI_CFG_PRIVACY_ENABLED_APMIN 0 +#define WNI_CFG_PRIVACY_ENABLED_APMAX 1 +#define WNI_CFG_PRIVACY_ENABLED_APDEF 0 + +#define WNI_CFG_SHORT_PREAMBLE_STAMIN 0 +#define WNI_CFG_SHORT_PREAMBLE_STAMAX 1 +#define WNI_CFG_SHORT_PREAMBLE_STADEF 1 + +#define WNI_CFG_SHORT_PREAMBLE_APMIN 0 +#define WNI_CFG_SHORT_PREAMBLE_APMAX 1 +#define WNI_CFG_SHORT_PREAMBLE_APDEF 1 + +#define WNI_CFG_SHORT_SLOT_TIME_STAMIN 0 +#define WNI_CFG_SHORT_SLOT_TIME_STAMAX 1 +#define WNI_CFG_SHORT_SLOT_TIME_STADEF 1 + +#define WNI_CFG_SHORT_SLOT_TIME_APMIN 0 +#define WNI_CFG_SHORT_SLOT_TIME_APMAX 1 +#define WNI_CFG_SHORT_SLOT_TIME_APDEF 0 + +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STAMIN 0 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STAMAX 1 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STADEF 0 + +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_APMIN 0 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_APMAX 1 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_APDEF 0 + +#define WNI_CFG_QOS_ENABLED_STAMIN 0 +#define WNI_CFG_QOS_ENABLED_STAMAX 1 +#define WNI_CFG_QOS_ENABLED_STADEF 0 + +#define WNI_CFG_QOS_ENABLED_APMIN 0 +#define WNI_CFG_QOS_ENABLED_APMAX 1 +#define WNI_CFG_QOS_ENABLED_APDEF 0 + +#define WNI_CFG_HCF_ENABLED_STAMIN 0 +#define WNI_CFG_HCF_ENABLED_STAMAX 1 +#define WNI_CFG_HCF_ENABLED_STADEF 0 + +#define WNI_CFG_HCF_ENABLED_APMIN 0 +#define WNI_CFG_HCF_ENABLED_APMAX 1 +#define WNI_CFG_HCF_ENABLED_APDEF 0 + +#define WNI_CFG_RSN_ENABLED_STAMIN 0 +#define WNI_CFG_RSN_ENABLED_STAMAX 1 +#define WNI_CFG_RSN_ENABLED_STADEF 0 + +#define WNI_CFG_RSN_ENABLED_APMIN 0 +#define WNI_CFG_RSN_ENABLED_APMAX 1 +#define WNI_CFG_RSN_ENABLED_APDEF 0 + +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_STAMIN 0 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_STAMAX 180000 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_STADEF 5000 + +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_APMIN 0 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_APMAX 18000 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_APDEF 5000 + +#define WNI_CFG_MAX_NUM_PRE_AUTH_STAMIN 0 +#define WNI_CFG_MAX_NUM_PRE_AUTH_STAMAX 256 +#define WNI_CFG_MAX_NUM_PRE_AUTH_STADEF 64 + +#define WNI_CFG_MAX_NUM_PRE_AUTH_APMIN 0 +#define WNI_CFG_MAX_NUM_PRE_AUTH_APMAX 256 +#define WNI_CFG_MAX_NUM_PRE_AUTH_APDEF 64 + +#define WNI_CFG_PREAUTH_CLNUP_TIMEOUT_APMIN 0 +#define WNI_CFG_PREAUTH_CLNUP_TIMEOUT_APMAX 120000 +#define WNI_CFG_PREAUTH_CLNUP_TIMEOUT_APDEF 30000 + +#define WNI_CFG_RELEASE_AID_TIMEOUT_APMIN 0 +#define WNI_CFG_RELEASE_AID_TIMEOUT_APMAX 100000 +#define WNI_CFG_RELEASE_AID_TIMEOUT_APDEF 1000 + +#define WNI_CFG_HEART_BEAT_THRESHOLD_STAMIN 0 +#define WNI_CFG_HEART_BEAT_THRESHOLD_STAMAX 65535 +#define WNI_CFG_HEART_BEAT_THRESHOLD_STADEF 40 + +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMIN 10 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMAX 10000 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STADEF 40 + +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_APMIN 10 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_APMAX 10000 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_APDEF 40 + +#define WNI_CFG_11D_ENABLED_STAMIN 0 +#define WNI_CFG_11D_ENABLED_STAMAX 1 +#define WNI_CFG_11D_ENABLED_STADEF 1 + +#define WNI_CFG_11D_ENABLED_APMIN 0 +#define WNI_CFG_11D_ENABLED_APMAX 1 +#define WNI_CFG_11D_ENABLED_APDEF 0 + +#define WNI_CFG_NETWORK_DENSITY_STAMIN 0 +#define WNI_CFG_NETWORK_DENSITY_STAMAX 3 +#define WNI_CFG_NETWORK_DENSITY_STADEF 3 + +#define WNI_CFG_NETWORK_DENSITY_APMIN 0 +#define WNI_CFG_NETWORK_DENSITY_APMAX 3 +#define WNI_CFG_NETWORK_DENSITY_APDEF 0 + +#define WNI_CFG_NETWORK_DENSITY_LOW 0 +#define WNI_CFG_NETWORK_DENSITY_MEDIUM 1 +#define WNI_CFG_NETWORK_DENSITY_HIGH 2 +#define WNI_CFG_NETWORK_DENSITY_ADAPTIVE 3 + +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STAMIN 1 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STAMAX 2 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STADEF 2 + +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_APMIN 1 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_APMAX 2 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_APDEF 2 + +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_CARRIER 1 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_CORRELATION 2 + +#define WNI_CFG_CURRENT_TX_ANTENNA_STAMIN 1 +#define WNI_CFG_CURRENT_TX_ANTENNA_STAMAX 1 +#define WNI_CFG_CURRENT_TX_ANTENNA_STADEF 1 + +#define WNI_CFG_CURRENT_TX_ANTENNA_APMIN 1 +#define WNI_CFG_CURRENT_TX_ANTENNA_APMAX 2 +#define WNI_CFG_CURRENT_TX_ANTENNA_APDEF 2 + +#define WNI_CFG_CURRENT_RX_ANTENNA_STAMIN 1 +#define WNI_CFG_CURRENT_RX_ANTENNA_STAMAX 2 +#define WNI_CFG_CURRENT_RX_ANTENNA_STADEF 2 + +#define WNI_CFG_CURRENT_RX_ANTENNA_APMIN 1 +#define WNI_CFG_CURRENT_RX_ANTENNA_APMAX 3 +#define WNI_CFG_CURRENT_RX_ANTENNA_APDEF 3 + +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMIN 0 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX 128 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_STADEF 27 + +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_APMIN 0 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_APMAX 128 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_APDEF 27 + +#define WNI_CFG_NEW_BSS_FOUND_IND_STAMIN 0 +#define WNI_CFG_NEW_BSS_FOUND_IND_STAMAX 1 +#define WNI_CFG_NEW_BSS_FOUND_IND_STADEF 0 + +#define WNI_CFG_NEW_BSS_FOUND_IND_APMIN 0 +#define WNI_CFG_NEW_BSS_FOUND_IND_APMAX 1 +#define WNI_CFG_NEW_BSS_FOUND_IND_APDEF 0 + +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_STAMIN 0 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_STAMAX 1 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_STADEF 0 + +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_APMIN 0 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_APMAX 1 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_APDEF 0 + +#define WNI_CFG_11H_ENABLED_STAMIN 0 +#define WNI_CFG_11H_ENABLED_STAMAX 1 +#define WNI_CFG_11H_ENABLED_STADEF 1 + +#define WNI_CFG_11H_ENABLED_APMIN 0 +#define WNI_CFG_11H_ENABLED_APMAX 1 +#define WNI_CFG_11H_ENABLED_APDEF 1 + +#define WNI_CFG_WT_CNF_TIMEOUT_STAMIN 10 +#define WNI_CFG_WT_CNF_TIMEOUT_STAMAX 3000 +#define WNI_CFG_WT_CNF_TIMEOUT_STADEF 1000 + +#define WNI_CFG_WT_CNF_TIMEOUT_APMIN 10 +#define WNI_CFG_WT_CNF_TIMEOUT_APMAX 3000 +#define WNI_CFG_WT_CNF_TIMEOUT_APDEF 1000 + +#define WNI_CFG_KEEPALIVE_TIMEOUT_STAMIN 0 +#define WNI_CFG_KEEPALIVE_TIMEOUT_STAMAX 3600000 +#define WNI_CFG_KEEPALIVE_TIMEOUT_STADEF 0 + +#define WNI_CFG_KEEPALIVE_TIMEOUT_APMIN 0 +#define WNI_CFG_KEEPALIVE_TIMEOUT_APMAX 3600000 +#define WNI_CFG_KEEPALIVE_TIMEOUT_APDEF 3000 + +#define WNI_CFG_PROXIMITY_STAMIN 0 +#define WNI_CFG_PROXIMITY_STAMAX 1 +#define WNI_CFG_PROXIMITY_STADEF 0 + +#define WNI_CFG_PROXIMITY_APMIN 0 +#define WNI_CFG_PROXIMITY_APMAX 1 +#define WNI_CFG_PROXIMITY_APDEF 0 + +#define WNI_CFG_PROXIMITY_OFF 0 +#define WNI_CFG_PROXIMITY_ON 1 + +#define WNI_CFG_LOG_LEVEL_STAMIN 0 +#define WNI_CFG_LOG_LEVEL_STAMAX 7 +#define WNI_CFG_LOG_LEVEL_STADEF 4 + +#define WNI_CFG_LOG_LEVEL_APMIN 0 +#define WNI_CFG_LOG_LEVEL_APMAX 7 +#define WNI_CFG_LOG_LEVEL_APDEF 4 + +#define WNI_CFG_OLBC_DETECT_TIMEOUT_STAMIN 1000 +#define WNI_CFG_OLBC_DETECT_TIMEOUT_STAMAX 30000 +#define WNI_CFG_OLBC_DETECT_TIMEOUT_STADEF 10000 + +#define WNI_CFG_OLBC_DETECT_TIMEOUT_APMIN 1000 +#define WNI_CFG_OLBC_DETECT_TIMEOUT_APMAX 30000 +#define WNI_CFG_OLBC_DETECT_TIMEOUT_APDEF 10000 + +#define WNI_CFG_PROTECTION_ENABLED_STAMIN 0 +#define WNI_CFG_PROTECTION_ENABLED_STAMAX 65535 +#define WNI_CFG_PROTECTION_ENABLED_STADEF 65535 + +#define WNI_CFG_PROTECTION_ENABLED_APMIN 0 +#define WNI_CFG_PROTECTION_ENABLED_APMAX 65535 +#define WNI_CFG_PROTECTION_ENABLED_APDEF 65535 + +#define WNI_CFG_PROTECTION_ENABLED_FROM_llA 0 +#define WNI_CFG_PROTECTION_ENABLED_FROM_llB 1 +#define WNI_CFG_PROTECTION_ENABLED_FROM_llG 2 +#define WNI_CFG_PROTECTION_ENABLED_HT_20 3 +#define WNI_CFG_PROTECTION_ENABLED_NON_GF 4 +#define WNI_CFG_PROTECTION_ENABLED_LSIG_TXOP 5 +#define WNI_CFG_PROTECTION_ENABLED_RIFS 6 +#define WNI_CFG_PROTECTION_ENABLED_OBSS 7 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_FROM_llA 8 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_FROM_llB 9 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_FROM_llG 10 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_HT20 11 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_NON_GF 12 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_LSIG_TXOP 13 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_RIFS 14 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_OBSS 15 + +#define WNI_CFG_11G_PROTECTION_ALWAYS_STAMIN 0 +#define WNI_CFG_11G_PROTECTION_ALWAYS_STAMAX 1 +#define WNI_CFG_11G_PROTECTION_ALWAYS_STADEF 0 + +#define WNI_CFG_11G_PROTECTION_ALWAYS_APMIN 0 +#define WNI_CFG_11G_PROTECTION_ALWAYS_APMAX 1 +#define WNI_CFG_11G_PROTECTION_ALWAYS_APDEF 0 + +#define WNI_CFG_FORCE_POLICY_PROTECTION_STAMIN 0 +#define WNI_CFG_FORCE_POLICY_PROTECTION_STAMAX 5 +#define WNI_CFG_FORCE_POLICY_PROTECTION_STADEF 5 + +#define WNI_CFG_FORCE_POLICY_PROTECTION_APMIN 0 +#define WNI_CFG_FORCE_POLICY_PROTECTION_APMAX 5 +#define WNI_CFG_FORCE_POLICY_PROTECTION_APDEF 5 + +#define WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE 0 +#define WNI_CFG_FORCE_POLICY_PROTECTION_CTS 1 +#define WNI_CFG_FORCE_POLICY_PROTECTION_RTS 2 +#define WNI_CFG_FORCE_POLICY_PROTECTION_DUAL_CTS 3 +#define WNI_CFG_FORCE_POLICY_PROTECTION_RTS_ALWAYS 4 +#define WNI_CFG_FORCE_POLICY_PROTECTION_AUTO 5 + +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STAMIN 0 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STAMAX 1 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STADEF 0 + +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_APMIN 0 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_APMAX 1 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_APDEF 0 + +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STAMIN 0 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STAMAX 1 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STADEF 1 + +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_APMIN 0 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_APMAX 1 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_APDEF 1 + +#define WNI_CFG_11G_ONLY_POLICY_STAMIN 0 +#define WNI_CFG_11G_ONLY_POLICY_STAMAX 1 +#define WNI_CFG_11G_ONLY_POLICY_STADEF 0 + +#define WNI_CFG_11G_ONLY_POLICY_APMIN 0 +#define WNI_CFG_11G_ONLY_POLICY_APMAX 1 +#define WNI_CFG_11G_ONLY_POLICY_APDEF 0 + +#define WNI_CFG_PACKET_CLASSIFICATION_STAMIN 0 +#define WNI_CFG_PACKET_CLASSIFICATION_STAMAX 3 +#define WNI_CFG_PACKET_CLASSIFICATION_STADEF 0 + +#define WNI_CFG_PACKET_CLASSIFICATION_APMIN 0 +#define WNI_CFG_PACKET_CLASSIFICATION_APMAX 3 +#define WNI_CFG_PACKET_CLASSIFICATION_APDEF 0 + +#define WNI_CFG_PACKET_CLASSIFICATION_DISABLED 0 +#define WNI_CFG_PACKET_CLASSIFICATION_DSCP 1 +#define WNI_CFG_PACKET_CLASSIFICATION_8021P 2 +#define WNI_CFG_PACKET_CLASSIFICATION_ALL 3 + +#define WNI_CFG_WME_ENABLED_STAMIN 0 +#define WNI_CFG_WME_ENABLED_STAMAX 1 +#define WNI_CFG_WME_ENABLED_STADEF 1 + +#define WNI_CFG_WME_ENABLED_APMIN 0 +#define WNI_CFG_WME_ENABLED_APMAX 1 +#define WNI_CFG_WME_ENABLED_APDEF 1 + +#define WNI_CFG_ADDTS_RSP_TIMEOUT_STAMIN 0 +#define WNI_CFG_ADDTS_RSP_TIMEOUT_STAMAX 65535 +#define WNI_CFG_ADDTS_RSP_TIMEOUT_STADEF 1000 + +#define WNI_CFG_ADDTS_RSP_TIMEOUT_APMIN 0 +#define WNI_CFG_ADDTS_RSP_TIMEOUT_APMAX 65535 +#define WNI_CFG_ADDTS_RSP_TIMEOUT_APDEF 1000 + +#define WNI_CFG_MAX_SP_LENGTH_STAMIN 0 +#define WNI_CFG_MAX_SP_LENGTH_STAMAX 3 +#define WNI_CFG_MAX_SP_LENGTH_STADEF 0 + +#define WNI_CFG_MAX_SP_LENGTH_APMIN 0 +#define WNI_CFG_MAX_SP_LENGTH_APMAX 3 +#define WNI_CFG_MAX_SP_LENGTH_APDEF 0 + +#define WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD_APMIN 0 +#define WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD_APMAX 32 +#define WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD_APDEF 0 + +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STAMIN 0 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STAMAX 1 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STADEF 0 + +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_APMIN 0 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_APMAX 1 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_APDEF 0 + +#define WNI_CFG_WSM_ENABLED_STAMIN 0 +#define WNI_CFG_WSM_ENABLED_STAMAX 1 +#define WNI_CFG_WSM_ENABLED_STADEF 0 + +#define WNI_CFG_WSM_ENABLED_APMIN 0 +#define WNI_CFG_WSM_ENABLED_APMAX 1 +#define WNI_CFG_WSM_ENABLED_APDEF 0 + +#define WNI_CFG_EDCA_PROFILE_STAMIN 0 +#define WNI_CFG_EDCA_PROFILE_STAMAX 255 +#define WNI_CFG_EDCA_PROFILE_STADEF 1 + +#define WNI_CFG_EDCA_PROFILE_APMIN 0 +#define WNI_CFG_EDCA_PROFILE_APMAX 255 +#define WNI_CFG_EDCA_PROFILE_APDEF 1 + +#define WNI_CFG_EDCA_PROFILE_ANI 0 +#define WNI_CFG_EDCA_PROFILE_WMM 1 +#define WNI_CFG_EDCA_PROFILE_TIT_DEMO 2 +#define WNI_CFG_EDCA_PROFILE_MAX 3 +#define WNI_CFG_EDCA_PROFILE_ACM_IDX 0 +#define WNI_CFG_EDCA_PROFILE_AIFSN_IDX 1 +#define WNI_CFG_EDCA_PROFILE_CWMINA_IDX 2 +#define WNI_CFG_EDCA_PROFILE_CWMAXA_IDX 4 +#define WNI_CFG_EDCA_PROFILE_TXOPA_IDX 6 +#define WNI_CFG_EDCA_PROFILE_CWMINB_IDX 7 +#define WNI_CFG_EDCA_PROFILE_CWMAXB_IDX 9 +#define WNI_CFG_EDCA_PROFILE_TXOPB_IDX 11 +#define WNI_CFG_EDCA_PROFILE_CWMING_IDX 12 +#define WNI_CFG_EDCA_PROFILE_CWMAXG_IDX 14 +#define WNI_CFG_EDCA_PROFILE_TXOPG_IDX 16 + +#define WNI_CFG_RDET_FLAG_STAMIN 0 +#define WNI_CFG_RDET_FLAG_STAMAX 1 +#define WNI_CFG_RDET_FLAG_STADEF 0 + +#define WNI_CFG_RDET_FLAG_APMIN 0 +#define WNI_CFG_RDET_FLAG_APMAX 1 +#define WNI_CFG_RDET_FLAG_APDEF 0 + +#define WNI_CFG_RDET_FLAG_ENABLE 1 +#define WNI_CFG_RDET_FLAG_DISABLE 0 + +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_STAMIN 0 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_STAMAX 255 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_STADEF 0 + +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_APMIN 0 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_APMAX 255 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_APDEF 0 + +#define WNI_CFG_ADMIT_POLICY_STAMIN 0 +#define WNI_CFG_ADMIT_POLICY_STAMAX 2 +#define WNI_CFG_ADMIT_POLICY_STADEF 0 + +#define WNI_CFG_ADMIT_POLICY_APMIN 0 +#define WNI_CFG_ADMIT_POLICY_APMAX 2 +#define WNI_CFG_ADMIT_POLICY_APDEF 0 + +#define WNI_CFG_ADMIT_POLICY_ADMIT_ALL 0 +#define WNI_CFG_ADMIT_POLICY_REJECT_ALL 1 +#define WNI_CFG_ADMIT_POLICY_BW_FACTOR 2 + +#define WNI_CFG_ADMIT_BWFACTOR_STAMIN 0 +#define WNI_CFG_ADMIT_BWFACTOR_STAMAX 100 +#define WNI_CFG_ADMIT_BWFACTOR_STADEF 20 + +#define WNI_CFG_ADMIT_BWFACTOR_APMIN 0 +#define WNI_CFG_ADMIT_BWFACTOR_APMAX 100 +#define WNI_CFG_ADMIT_BWFACTOR_APDEF 20 + +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STAMIN 0 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STAMAX 256 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STADEF 60 + +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_APMIN 0 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_APMAX 256 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_APDEF 60 + +#define WNI_CFG_CHANNEL_BONDING_MODE_STAMIN 0 +#define WNI_CFG_CHANNEL_BONDING_MODE_STAMAX 10 +#define WNI_CFG_CHANNEL_BONDING_MODE_STADEF 0 + +#define WNI_CFG_CHANNEL_BONDING_MODE_APMIN 0 +#define WNI_CFG_CHANNEL_BONDING_MODE_APMAX 10 +#define WNI_CFG_CHANNEL_BONDING_MODE_APDEF 0 + +#define WNI_CFG_CHANNEL_BONDING_MODE_DISABLE 0 +#define WNI_CFG_CHANNEL_BONDING_MODE_ENABLE 1 +#define WNI_CFG_CHANNEL_BONDING_MODE_IF_NO_LEGACY_BSS 2 +#define WNI_CFG_CHANNEL_BONDING_MODE_IF_NO_LEGACY_ALL 3 +#define WNI_CFG_CHANNEL_BONDING_MODE_INTELLIGENT 4 + +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STAMIN 0 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STAMAX 10 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STADEF 0 + +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_APMIN 0 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_APMAX 10 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_APDEF 0 + +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_NONE 0 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_LOWER 1 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_HIGHER 2 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_LOW_40MHZ_CENTERED 3 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_CENTERED_40MHZ_CENTERED 4 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_HIGH_40MHZ_CENTERED 5 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_LOW_40MHZ_LOW 6 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_HIGH_40MHZ_LOW 7 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_LOW_40MHZ_HIGH 8 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_HIGH_40MHZ_HIGH 9 + +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STAMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STAMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STADEF 2 + +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_APMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_APMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_APDEF 2 + +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_STAMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_STAMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_STADEF 4 + +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_APMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_APMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_APDEF 4 + +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_STAMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_STAMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_STADEF 6 + +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_APMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_APMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_APDEF 6 + +#define WNI_CFG_TRIG_STA_BK_SCAN_STAMIN 0 +#define WNI_CFG_TRIG_STA_BK_SCAN_STAMAX 1 +#define WNI_CFG_TRIG_STA_BK_SCAN_STADEF 0 + +#define WNI_CFG_TRIG_STA_BK_SCAN_APMIN 0 +#define WNI_CFG_TRIG_STA_BK_SCAN_APMAX 1 +#define WNI_CFG_TRIG_STA_BK_SCAN_APDEF 1 + +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STAMIN 0 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STAMAX 255 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STADEF 255 + +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_APMIN 0 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_APMAX 255 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_APDEF 1 + +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_UNUSED 255 + +#define WNI_CFG_MIMO_ENABLED_STAMIN 0 +#define WNI_CFG_MIMO_ENABLED_STAMAX 1 +#define WNI_CFG_MIMO_ENABLED_STADEF 1 + +#define WNI_CFG_MIMO_ENABLED_APMIN 0 +#define WNI_CFG_MIMO_ENABLED_APMAX 1 +#define WNI_CFG_MIMO_ENABLED_APDEF 1 + +#define WNI_CFG_MIMO_ENABLED_ENABLE 1 +#define WNI_CFG_MIMO_ENABLED_DISABLE 0 + +#define WNI_CFG_BLOCK_ACK_ENABLED_STAMIN 0 +#define WNI_CFG_BLOCK_ACK_ENABLED_STAMAX 3 +#define WNI_CFG_BLOCK_ACK_ENABLED_STADEF 0 + +#define WNI_CFG_BLOCK_ACK_ENABLED_APMIN 0 +#define WNI_CFG_BLOCK_ACK_ENABLED_APMAX 3 +#define WNI_CFG_BLOCK_ACK_ENABLED_APDEF 0 + +#define WNI_CFG_BLOCK_ACK_ENABLED_DELAYED 0 +#define WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE 1 + +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STAMIN 0 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STAMAX 65535 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STADEF 1000 + +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_APMIN 0 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_APMAX 65535 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_APDEF 1000 + +#define WNI_CFG_HT_RX_STBC_STAMIN 0 +#define WNI_CFG_HT_RX_STBC_STAMAX 3 +#define WNI_CFG_HT_RX_STBC_STADEF 1 + +#define WNI_CFG_HT_RX_STBC_APMIN 0 +#define WNI_CFG_HT_RX_STBC_APMAX 3 +#define WNI_CFG_HT_RX_STBC_APDEF 1 + +#define WNI_CFG_HT_CAP_INFO_STAMIN 0 +#define WNI_CFG_HT_CAP_INFO_STAMAX 65535 +#define WNI_CFG_HT_CAP_INFO_STADEF 364 + +#define WNI_CFG_HT_CAP_INFO_APMIN 0 +#define WNI_CFG_HT_CAP_INFO_APMAX 65535 +#define WNI_CFG_HT_CAP_INFO_APDEF 4206 + +#define WNI_CFG_HT_CAP_INFO_ADVANCE_CODING 0 +#define WNI_CFG_HT_CAP_INFO_SUPPORTED_CHAN_WIDTH_SET 1 +#define WNI_CFG_HT_CAP_INFO_SM_POWER_SAVE 2 +#define WNI_CFG_HT_CAP_INFO_GREEN_FIELD 4 +#define WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ 5 +#define WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ 6 +#define WNI_CFG_HT_CAP_INFO_TX_STBC 7 +#define WNI_CFG_HT_CAP_INFO_RX_STBC 8 +#define WNI_CFG_HT_CAP_INFO_DELAYED_BA 10 +#define WNI_CFG_HT_CAP_INFO_MAX_AMSDU_SIZE 11 +#define WNI_CFG_HT_CAP_INFO_DSSS_CCK_MODE_40MHZ 12 +#define WNI_CFG_HT_CAP_INFO_PSMP 13 +#define WNI_CFG_HT_CAP_INFO_STBC_CONTROL_FRAME 14 +#define WNI_CFG_HT_CAP_INFO_LSIG_TXOP_PROTECTION 15 + +#define WNI_CFG_HT_AMPDU_PARAMS_STAMIN 0 +#define WNI_CFG_HT_AMPDU_PARAMS_STAMAX 255 +#define WNI_CFG_HT_AMPDU_PARAMS_STADEF 0 + +#define WNI_CFG_HT_AMPDU_PARAMS_APMIN 0 +#define WNI_CFG_HT_AMPDU_PARAMS_APMAX 255 +#define WNI_CFG_HT_AMPDU_PARAMS_APDEF 2 + +#define WNI_CFG_HT_AMPDU_PARAMS_MAX_RX_AMPDU_FACTOR 0 +#define WNI_CFG_HT_AMPDU_PARAMS_MPDU_DENSITY 2 +#define WNI_CFG_HT_AMPDU_PARAMS_RESERVED 5 + +#define WNI_CFG_EXT_HT_CAP_INFO_STAMIN 0 +#define WNI_CFG_EXT_HT_CAP_INFO_STAMAX 65535 +#define WNI_CFG_EXT_HT_CAP_INFO_STADEF 1024 + +#define WNI_CFG_EXT_HT_CAP_INFO_APMIN 0 +#define WNI_CFG_EXT_HT_CAP_INFO_APMAX 65535 +#define WNI_CFG_EXT_HT_CAP_INFO_APDEF 1024 + +#define WNI_CFG_EXT_HT_CAP_INFO_PCO 0 +#define WNI_CFG_EXT_HT_CAP_INFO_TRANSITION_TIME 1 +#define WNI_CFG_EXT_HT_CAP_INFO_RESERVED1 3 +#define WNI_CFG_EXT_HT_CAP_INFO_MCS_FEEDBACK 8 +#define WNI_CFG_EXT_HT_CAP_INFO_HTC_SUPPORT 10 +#define WNI_CFG_EXT_HT_CAP_INFO_RD_RESPONDER 11 +#define WNI_CFG_EXT_HT_CAP_INFO_RESERVED2 12 + +#define WNI_CFG_TX_BF_CAP_STAMIN 0 +#define WNI_CFG_TX_BF_CAP_STAMAX 4294967295 +#define WNI_CFG_TX_BF_CAP_STADEF 0 + +#define WNI_CFG_TX_BF_CAP_APMIN 0 +#define WNI_CFG_TX_BF_CAP_APMAX 4294967295 +#define WNI_CFG_TX_BF_CAP_APDEF 0 + +#define WNI_CFG_AS_CAP_STAMIN 0 +#define WNI_CFG_AS_CAP_STAMAX 255 +#define WNI_CFG_AS_CAP_STADEF 0 + +#define WNI_CFG_AS_CAP_APMIN 0 +#define WNI_CFG_AS_CAP_APMAX 255 +#define WNI_CFG_AS_CAP_APDEF 0 + +#define WNI_CFG_AS_CAP_ANTENNA_SELECTION 0 +#define WNI_CFG_AS_CAP_EXPLICIT_CSI_FEEDBACK_TX 1 +#define WNI_CFG_AS_CAP_ANTENNA_INDICES_FEEDBACK_TX 2 +#define WNI_CFG_AS_CAP_EXPLICIT_CSI_FEEDBACK 3 +#define WNI_CFG_AS_CAP_ANTENNA_INDICES_FEEDBACK 4 +#define WNI_CFG_AS_CAP_RX_AS 5 +#define WNI_CFG_AS_CAP_TX_SOUNDING_PPDUS 6 +#define WNI_CFG_AS_CAP_RESERVED 7 + +#define WNI_CFG_HT_INFO_FIELD1_STAMIN 0 +#define WNI_CFG_HT_INFO_FIELD1_STAMAX 255 +#define WNI_CFG_HT_INFO_FIELD1_STADEF 15 + +#define WNI_CFG_HT_INFO_FIELD1_APMIN 0 +#define WNI_CFG_HT_INFO_FIELD1_APMAX 255 +#define WNI_CFG_HT_INFO_FIELD1_APDEF 15 + +#define WNI_CFG_HT_INFO_FIELD1_SECONDARY_CHANNEL_OFFSET 0 +#define WNI_CFG_HT_INFO_FIELD1_RECOMMENDED_CHANNEL_WIDTH 2 +#define WNI_CFG_HT_INFO_FIELD1_RIFS_MODE 3 +#define WNI_CFG_HT_INFO_FIELD1_PSMP_ACCESS_ONLY 4 +#define WNI_CFG_HT_INFO_FIELD1_SERVICE_INTERVAL_GRANULARITY 5 + +#define WNI_CFG_HT_INFO_FIELD2_STAMIN 0 +#define WNI_CFG_HT_INFO_FIELD2_STAMAX 65535 +#define WNI_CFG_HT_INFO_FIELD2_STADEF 0 + +#define WNI_CFG_HT_INFO_FIELD2_APMIN 0 +#define WNI_CFG_HT_INFO_FIELD2_APMAX 65535 +#define WNI_CFG_HT_INFO_FIELD2_APDEF 0 + +#define WNI_CFG_HT_INFO_FIELD2_OP_MODE 0 +#define WNI_CFG_HT_INFO_FIELD2_NON_GF_DEVICES_PRESENT 2 +#define WNI_CFG_HT_INFO_FIELD2_RESERVED 3 + +#define WNI_CFG_HT_INFO_FIELD3_STAMIN 0 +#define WNI_CFG_HT_INFO_FIELD3_STAMAX 65535 +#define WNI_CFG_HT_INFO_FIELD3_STADEF 0 + +#define WNI_CFG_HT_INFO_FIELD3_APMIN 0 +#define WNI_CFG_HT_INFO_FIELD3_APMAX 65535 +#define WNI_CFG_HT_INFO_FIELD3_APDEF 0 + +#define WNI_CFG_HT_INFO_FIELD3_BASIC_STBC_MCS 0 +#define WNI_CFG_HT_INFO_FIELD3_DUAL_STBC_PROTECTION 7 +#define WNI_CFG_HT_INFO_FIELD3_SECONDARY_BEACON 8 +#define WNI_CFG_HT_INFO_FIELD3_LSIG_TXOP_PROTECTION_FULL_SUPPORT 9 +#define WNI_CFG_HT_INFO_FIELD3_PCO_ACTIVE 10 +#define WNI_CFG_HT_INFO_FIELD3_PCO_PHASE 11 +#define WNI_CFG_HT_INFO_FIELD3_RESERVED 12 + +#define WNI_CFG_GREENFIELD_CAPABILITY_STAMIN 0 +#define WNI_CFG_GREENFIELD_CAPABILITY_STAMAX 1 +#define WNI_CFG_GREENFIELD_CAPABILITY_STADEF 0 + +#define WNI_CFG_GREENFIELD_CAPABILITY_APMIN 0 +#define WNI_CFG_GREENFIELD_CAPABILITY_APMAX 1 +#define WNI_CFG_GREENFIELD_CAPABILITY_APDEF 0 + +#define WNI_CFG_GREENFIELD_CAPABILITY_ENABLE 1 +#define WNI_CFG_GREENFIELD_CAPABILITY_DISABLE 0 + +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_STAMIN 0 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_STAMAX 2 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_STADEF 0 + +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_APMIN 0 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_APMAX 2 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_APDEF 0 + +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STAMIN 0 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STAMAX 0 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STADEF 0 + +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_APMIN 0 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_APMAX 0 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_APDEF 0 + +#define WNI_CFG_VHT_LDPC_CODING_CAP_STAMIN 0 +#define WNI_CFG_VHT_LDPC_CODING_CAP_STAMAX 1 +#define WNI_CFG_VHT_LDPC_CODING_CAP_STADEF 0 + +#define WNI_CFG_VHT_LDPC_CODING_CAP_APMIN 0 +#define WNI_CFG_VHT_LDPC_CODING_CAP_APMAX 1 +#define WNI_CFG_VHT_LDPC_CODING_CAP_APDEF 0 + +#define WNI_CFG_VHT_SHORT_GI_80MHZ_STAMIN 0 +#define WNI_CFG_VHT_SHORT_GI_80MHZ_STAMAX 1 +#define WNI_CFG_VHT_SHORT_GI_80MHZ_STADEF 1 + +#define WNI_CFG_VHT_SHORT_GI_80MHZ_APMIN 0 +#define WNI_CFG_VHT_SHORT_GI_80MHZ_APMAX 1 +#define WNI_CFG_VHT_SHORT_GI_80MHZ_APDEF 1 + +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STAMIN 0 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STAMAX 1 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STADEF 0 + +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_APMIN 0 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_APMAX 1 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_APDEF 0 + +#define WNI_CFG_VHT_TXSTBC_STAMIN 0 +#define WNI_CFG_VHT_TXSTBC_STAMAX 1 +#define WNI_CFG_VHT_TXSTBC_STADEF 0 + +#define WNI_CFG_VHT_TXSTBC_APMIN 0 +#define WNI_CFG_VHT_TXSTBC_APMAX 1 +#define WNI_CFG_VHT_TXSTBC_APDEF 0 + +#define WNI_CFG_VHT_RXSTBC_STAMIN 0 +#define WNI_CFG_VHT_RXSTBC_STAMAX 1 +#define WNI_CFG_VHT_RXSTBC_STADEF 1 + +#define WNI_CFG_VHT_RXSTBC_APMIN 0 +#define WNI_CFG_VHT_RXSTBC_APMAX 1 +#define WNI_CFG_VHT_RXSTBC_APDEF 1 + +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_STAMIN 0 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_STAMAX 1 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_STADEF 0 + +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_APMIN 0 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_APMAX 1 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_APDEF 0 + +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMIN 0 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMAX 1 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STADEF 1 + +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_APMIN 0 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_APMAX 1 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_APDEF 1 + +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMIN 0 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMAX 4 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STADEF 0 + +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_APMIN 0 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_APMAX 4 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_APDEF 0 + +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STAMIN 0 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STAMAX 3 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STADEF 0 + +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_APMIN 0 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_APMAX 3 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_APDEF 0 + +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_STAMIN 0 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_STAMAX 1 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_STADEF 0 + +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_APMIN 0 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_APMAX 1 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_APDEF 0 + +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STAMIN 0 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STAMAX 1 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STADEF 0 + +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_APMIN 0 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_APMAX 1 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_APDEF 0 + +#define WNI_CFG_VHT_TXOP_PS_STAMIN 0 +#define WNI_CFG_VHT_TXOP_PS_STAMAX 1 +#define WNI_CFG_VHT_TXOP_PS_STADEF 0 + +#define WNI_CFG_VHT_TXOP_PS_APMIN 0 +#define WNI_CFG_VHT_TXOP_PS_APMAX 1 +#define WNI_CFG_VHT_TXOP_PS_APDEF 0 + +#define WNI_CFG_VHT_HTC_VHTC_CAP_STAMIN 0 +#define WNI_CFG_VHT_HTC_VHTC_CAP_STAMAX 1 +#define WNI_CFG_VHT_HTC_VHTC_CAP_STADEF 0 + +#define WNI_CFG_VHT_HTC_VHTC_CAP_APMIN 0 +#define WNI_CFG_VHT_HTC_VHTC_CAP_APMAX 1 +#define WNI_CFG_VHT_HTC_VHTC_CAP_APDEF 0 + +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STAMIN 0 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STAMAX 7 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STADEF 3 + +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_APMIN 0 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_APMAX 7 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_APDEF 3 + +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_STAMIN 0 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_STAMAX 3 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_STADEF 0 + +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_APMIN 0 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_APMAX 3 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_APDEF 0 + +#define WNI_CFG_VHT_RX_ANT_PATTERN_STAMIN 0 +#define WNI_CFG_VHT_RX_ANT_PATTERN_STAMAX 1 +#define WNI_CFG_VHT_RX_ANT_PATTERN_STADEF 1 + +#define WNI_CFG_VHT_RX_ANT_PATTERN_APMIN 0 +#define WNI_CFG_VHT_RX_ANT_PATTERN_APMAX 1 +#define WNI_CFG_VHT_RX_ANT_PATTERN_APDEF 1 + +#define WNI_CFG_VHT_TX_ANT_PATTERN_STAMIN 0 +#define WNI_CFG_VHT_TX_ANT_PATTERN_STAMAX 1 +#define WNI_CFG_VHT_TX_ANT_PATTERN_STADEF 1 + +#define WNI_CFG_VHT_TX_ANT_PATTERN_APMIN 0 +#define WNI_CFG_VHT_TX_ANT_PATTERN_APMAX 1 +#define WNI_CFG_VHT_TX_ANT_PATTERN_APDEF 1 + +#define WNI_CFG_VHT_RX_MCS_MAP_STAMIN 0 +#define WNI_CFG_VHT_RX_MCS_MAP_STAMAX 65535 +#define WNI_CFG_VHT_RX_MCS_MAP_STADEF 65534 + +#define WNI_CFG_VHT_RX_MCS_MAP_APMIN 0 +#define WNI_CFG_VHT_RX_MCS_MAP_APMAX 65535 +#define WNI_CFG_VHT_RX_MCS_MAP_APDEF 65534 + +#define WNI_CFG_VHT_TX_MCS_MAP_STAMIN 0 +#define WNI_CFG_VHT_TX_MCS_MAP_STAMAX 65535 +#define WNI_CFG_VHT_TX_MCS_MAP_STADEF 65534 + +#define WNI_CFG_VHT_TX_MCS_MAP_APMIN 0 +#define WNI_CFG_VHT_TX_MCS_MAP_APMAX 65535 +#define WNI_CFG_VHT_TX_MCS_MAP_APDEF 65534 + +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STAMIN 0 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STAMAX 780 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STADEF 780 + +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_APMIN 0 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_APMAX 780 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_APDEF 780 + +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STAMIN 0 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STAMAX 780 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STADEF 780 + +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_APMIN 0 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_APMAX 780 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_APDEF 780 + +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STAMIN 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STAMAX 256 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STADEF 0 + +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_APMIN 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_APMAX 256 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_APDEF 0 + +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STAMIN 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STAMAX 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STADEF 0 + +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_APMIN 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_APMAX 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_APDEF 0 + +#define WNI_CFG_VHT_BASIC_MCS_SET_STAMIN 0 +#define WNI_CFG_VHT_BASIC_MCS_SET_STAMAX 65535 +#define WNI_CFG_VHT_BASIC_MCS_SET_STADEF 65534 + +#define WNI_CFG_VHT_BASIC_MCS_SET_APMIN 0 +#define WNI_CFG_VHT_BASIC_MCS_SET_APMAX 65535 +#define WNI_CFG_VHT_BASIC_MCS_SET_APDEF 65534 + +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STAMIN 0 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STAMAX 4 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STADEF 0 + +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_APMIN 0 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_APMAX 4 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_APDEF 0 + +#define WNI_CFG_VHT_SS_UNDER_UTIL_STAMIN 0 +#define WNI_CFG_VHT_SS_UNDER_UTIL_STAMAX 0 +#define WNI_CFG_VHT_SS_UNDER_UTIL_STADEF 0 + +#define WNI_CFG_VHT_SS_UNDER_UTIL_APMIN 0 +#define WNI_CFG_VHT_SS_UNDER_UTIL_APMAX 0 +#define WNI_CFG_VHT_SS_UNDER_UTIL_APDEF 0 + +#define WNI_CFG_VHT_40MHZ_UTILIZATION_STAMIN 0 +#define WNI_CFG_VHT_40MHZ_UTILIZATION_STAMAX 0 +#define WNI_CFG_VHT_40MHZ_UTILIZATION_STADEF 0 + +#define WNI_CFG_VHT_40MHZ_UTILIZATION_APMIN 0 +#define WNI_CFG_VHT_40MHZ_UTILIZATION_APMAX 0 +#define WNI_CFG_VHT_40MHZ_UTILIZATION_APDEF 0 + +#define WNI_CFG_VHT_80MHZ_UTILIZATION_STAMIN 0 +#define WNI_CFG_VHT_80MHZ_UTILIZATION_STAMAX 0 +#define WNI_CFG_VHT_80MHZ_UTILIZATION_STADEF 0 + +#define WNI_CFG_VHT_80MHZ_UTILIZATION_APMIN 0 +#define WNI_CFG_VHT_80MHZ_UTILIZATION_APMAX 0 +#define WNI_CFG_VHT_80MHZ_UTILIZATION_APDEF 0 + +#define WNI_CFG_VHT_160MHZ_UTILIZATION_STAMIN 0 +#define WNI_CFG_VHT_160MHZ_UTILIZATION_STAMAX 0 +#define WNI_CFG_VHT_160MHZ_UTILIZATION_STADEF 0 + +#define WNI_CFG_VHT_160MHZ_UTILIZATION_APMIN 0 +#define WNI_CFG_VHT_160MHZ_UTILIZATION_APMAX 0 +#define WNI_CFG_VHT_160MHZ_UTILIZATION_APDEF 0 + +#define WNI_CFG_MAX_AMSDU_LENGTH_STAMIN 0 +#define WNI_CFG_MAX_AMSDU_LENGTH_STAMAX 1 +#define WNI_CFG_MAX_AMSDU_LENGTH_STADEF 0 + +#define WNI_CFG_MAX_AMSDU_LENGTH_APMIN 0 +#define WNI_CFG_MAX_AMSDU_LENGTH_APMAX 1 +#define WNI_CFG_MAX_AMSDU_LENGTH_APDEF 0 + +#define WNI_CFG_MAX_AMSDU_LENGTH_SHORT_3839_BYTES 0 +#define WNI_CFG_MAX_AMSDU_LENGTH_LONG_7935__BYTES 1 + +#define WNI_CFG_MPDU_DENSITY_STAMIN 0 +#define WNI_CFG_MPDU_DENSITY_STAMAX 7 +#define WNI_CFG_MPDU_DENSITY_STADEF 7 + +#define WNI_CFG_MPDU_DENSITY_APMIN 0 +#define WNI_CFG_MPDU_DENSITY_APMAX 7 +#define WNI_CFG_MPDU_DENSITY_APDEF 7 + +#define WNI_CFG_NUM_BUFF_ADVERT_STAMIN 0 +#define WNI_CFG_NUM_BUFF_ADVERT_STAMAX 128 +#define WNI_CFG_NUM_BUFF_ADVERT_STADEF 64 + +#define WNI_CFG_NUM_BUFF_ADVERT_APMIN 0 +#define WNI_CFG_NUM_BUFF_ADVERT_APMAX 128 +#define WNI_CFG_NUM_BUFF_ADVERT_APDEF 64 + +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMIN 0 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMAX 3 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_STADEF 3 + +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_APMIN 0 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_APMAX 3 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_APDEF 3 + +#define WNI_CFG_SHORT_GI_20MHZ_STAMIN 0 +#define WNI_CFG_SHORT_GI_20MHZ_STAMAX 1 +#define WNI_CFG_SHORT_GI_20MHZ_STADEF 1 + +#define WNI_CFG_SHORT_GI_20MHZ_APMIN 0 +#define WNI_CFG_SHORT_GI_20MHZ_APMAX 1 +#define WNI_CFG_SHORT_GI_20MHZ_APDEF 1 + +#define WNI_CFG_SHORT_GI_20MHZ_ENABLE 1 +#define WNI_CFG_SHORT_GI_20MHZ_DISABLE 0 + +#define WNI_CFG_SHORT_GI_40MHZ_STAMIN 0 +#define WNI_CFG_SHORT_GI_40MHZ_STAMAX 1 +#define WNI_CFG_SHORT_GI_40MHZ_STADEF 0 + +#define WNI_CFG_SHORT_GI_40MHZ_APMIN 0 +#define WNI_CFG_SHORT_GI_40MHZ_APMAX 1 +#define WNI_CFG_SHORT_GI_40MHZ_APDEF 1 + +#define WNI_CFG_SHORT_GI_40MHZ_ENABLE 1 +#define WNI_CFG_SHORT_GI_40MHZ_DISABLE 0 + +#define WNI_CFG_RIFS_ENABLED_STAMIN 0 +#define WNI_CFG_RIFS_ENABLED_STAMAX 1 +#define WNI_CFG_RIFS_ENABLED_STADEF 1 + +#define WNI_CFG_RIFS_ENABLED_APMIN 0 +#define WNI_CFG_RIFS_ENABLED_APMAX 1 +#define WNI_CFG_RIFS_ENABLED_APDEF 1 + +#define WNI_CFG_RIFS_ENABLED_ENABLE 1 +#define WNI_CFG_RIFS_ENABLED_DISABLE 0 + +#define WNI_CFG_MAX_PS_POLL_STAMIN 0 +#define WNI_CFG_MAX_PS_POLL_STAMAX 255 +#define WNI_CFG_MAX_PS_POLL_STADEF 0 + +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMIN 1 +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX 20 +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STADEF 20 + +#define WNI_CFG_RSSI_FILTER_PERIOD_STAMIN 0 +#define WNI_CFG_RSSI_FILTER_PERIOD_STAMAX 255 +#define WNI_CFG_RSSI_FILTER_PERIOD_STADEF 5 + +#define WNI_CFG_MIN_RSSI_THRESHOLD_STAMIN 0 +#define WNI_CFG_MIN_RSSI_THRESHOLD_STAMAX 10 +#define WNI_CFG_MIN_RSSI_THRESHOLD_STADEF 10 + +#define WNI_CFG_NTH_BEACON_FILTER_STAMIN 0 +#define WNI_CFG_NTH_BEACON_FILTER_STAMAX 255 +#define WNI_CFG_NTH_BEACON_FILTER_STADEF 10 + +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STAMIN 0 +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STAMAX 1 +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STADEF 0 + +#define WNI_CFG_SCAN_IN_POWERSAVE_STAMIN 0 +#define WNI_CFG_SCAN_IN_POWERSAVE_STAMAX 1 +#define WNI_CFG_SCAN_IN_POWERSAVE_STADEF 1 + +#define WNI_CFG_SCAN_IN_POWERSAVE_APMIN 0 +#define WNI_CFG_SCAN_IN_POWERSAVE_APMAX 1 +#define WNI_CFG_SCAN_IN_POWERSAVE_APDEF 1 + +#define WNI_CFG_IGNORE_DTIM_STAMIN 0 +#define WNI_CFG_IGNORE_DTIM_STAMAX 1 +#define WNI_CFG_IGNORE_DTIM_STADEF 0 + +#define WNI_CFG_IGNORE_DTIM_APMIN 0 +#define WNI_CFG_IGNORE_DTIM_APMAX 1 +#define WNI_CFG_IGNORE_DTIM_APDEF 0 + +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STAMIN 0 +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STAMAX 65535 +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STADEF 40 + +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STAMIN 0 +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STAMAX 65535 +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STADEF 65535 + +#define WNI_CFG_BA_TIMEOUT_STAMIN 0 +#define WNI_CFG_BA_TIMEOUT_STAMAX 65535 +#define WNI_CFG_BA_TIMEOUT_STADEF 0 + +#define WNI_CFG_BA_TIMEOUT_APMIN 0 +#define WNI_CFG_BA_TIMEOUT_APMAX 65535 +#define WNI_CFG_BA_TIMEOUT_APDEF 0 + +#define WNI_CFG_BA_THRESHOLD_HIGH_STAMIN 0 +#define WNI_CFG_BA_THRESHOLD_HIGH_STAMAX 65535 +#define WNI_CFG_BA_THRESHOLD_HIGH_STADEF 128 + +#define WNI_CFG_BA_THRESHOLD_HIGH_APMIN 0 +#define WNI_CFG_BA_THRESHOLD_HIGH_APMAX 65535 +#define WNI_CFG_BA_THRESHOLD_HIGH_APDEF 128 + +#define WNI_CFG_MAX_BA_BUFFERS_STAMIN 0 +#define WNI_CFG_MAX_BA_BUFFERS_STAMAX 2560 +#define WNI_CFG_MAX_BA_BUFFERS_STADEF 2560 + +#define WNI_CFG_MAX_BA_BUFFERS_APMIN 0 +#define WNI_CFG_MAX_BA_BUFFERS_APMAX 2560 +#define WNI_CFG_MAX_BA_BUFFERS_APDEF 2560 + +#define WNI_CFG_MAX_BA_SESSIONS_STAMIN 0 +#define WNI_CFG_MAX_BA_SESSIONS_STAMAX 64 +#define WNI_CFG_MAX_BA_SESSIONS_STADEF 40 + +#define WNI_CFG_MAX_BA_SESSIONS_APMIN 0 +#define WNI_CFG_MAX_BA_SESSIONS_APMAX 64 +#define WNI_CFG_MAX_BA_SESSIONS_APDEF 40 + +#define WNI_CFG_BA_AUTO_SETUP_STAMIN 0 +#define WNI_CFG_BA_AUTO_SETUP_STAMAX 1 +#define WNI_CFG_BA_AUTO_SETUP_STADEF 1 + +#define WNI_CFG_BA_AUTO_SETUP_APMIN 0 +#define WNI_CFG_BA_AUTO_SETUP_APMAX 1 +#define WNI_CFG_BA_AUTO_SETUP_APDEF 1 + +#define WNI_CFG_BA_AUTO_SETUP_ENABLE 1 +#define WNI_CFG_BA_AUTO_SETUP_DISABLE 0 + +#define WNI_CFG_ADDBA_REQ_DECLINE_STAMIN 0 +#define WNI_CFG_ADDBA_REQ_DECLINE_STAMAX 255 +#define WNI_CFG_ADDBA_REQ_DECLINE_STADEF 0 + +#define WNI_CFG_ADDBA_REQ_DECLINE_APMIN 0 +#define WNI_CFG_ADDBA_REQ_DECLINE_APMAX 255 +#define WNI_CFG_ADDBA_REQ_DECLINE_APDEF 0 + +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF 0 + +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APDEF 0 + +#define WNI_CFG_MAX_MEDIUM_TIME_STAMIN 0 +#define WNI_CFG_MAX_MEDIUM_TIME_STAMAX 65535 +#define WNI_CFG_MAX_MEDIUM_TIME_STADEF 2048 + +#define WNI_CFG_MAX_MEDIUM_TIME_APMIN 0 +#define WNI_CFG_MAX_MEDIUM_TIME_APMAX 65535 +#define WNI_CFG_MAX_MEDIUM_TIME_APDEF 2048 + +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_STAMIN 0 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_STAMAX 65535 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_STADEF 64 + +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_APMIN 0 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_APMAX 65535 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_APDEF 64 + +#define WNI_CFG_IBSS_AUTO_BSSID_STAMIN 0 +#define WNI_CFG_IBSS_AUTO_BSSID_STAMAX 1 +#define WNI_CFG_IBSS_AUTO_BSSID_STADEF 1 + +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_APMIN 0 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_APMAX 1 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_APDEF 0 + +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_APMIN 0 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_APMAX 1 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_APDEF 0 + +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_APMIN 0 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_APMAX 1 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_APDEF 0 + +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_APMIN 0 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_APMAX 1 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_APDEF 0 + +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_APMIN 0 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_APMAX 1 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_APDEF 0 + +#define WNI_CFG_WPS_ENABLE_STAMIN 0 +#define WNI_CFG_WPS_ENABLE_STAMAX 255 +#define WNI_CFG_WPS_ENABLE_STADEF 0 + +#define WNI_CFG_WPS_ENABLE_APMIN 0 +#define WNI_CFG_WPS_ENABLE_APMAX 255 +#define WNI_CFG_WPS_ENABLE_APDEF 0 + +#define WNI_CFG_WPS_ENABLE_AP 1 +#define WNI_CFG_WPS_ENABLE_STA 2 + +#define WNI_CFG_WPS_STATE_STAMIN 0 +#define WNI_CFG_WPS_STATE_STAMAX 255 +#define WNI_CFG_WPS_STATE_STADEF 1 + +#define WNI_CFG_WPS_STATE_APMIN 0 +#define WNI_CFG_WPS_STATE_APMAX 255 +#define WNI_CFG_WPS_STATE_APDEF 1 + +#define WNI_CFG_WPS_PROBE_REQ_FLAG_STAMIN 0 +#define WNI_CFG_WPS_PROBE_REQ_FLAG_STAMAX 1 +#define WNI_CFG_WPS_PROBE_REQ_FLAG_STADEF 0 + +#define WNI_CFG_WPS_PROBE_REQ_FLAG_APMIN 0 +#define WNI_CFG_WPS_PROBE_REQ_FLAG_APMAX 1 +#define WNI_CFG_WPS_PROBE_REQ_FLAG_APDEF 0 + +#define WNI_CFG_WPS_VERSION_STAMIN 0 +#define WNI_CFG_WPS_VERSION_STAMAX 255 +#define WNI_CFG_WPS_VERSION_STADEF 16 + +#define WNI_CFG_WPS_VERSION_APMIN 0 +#define WNI_CFG_WPS_VERSION_APMAX 255 +#define WNI_CFG_WPS_VERSION_APDEF 16 + +#define WNI_CFG_WPS_REQUEST_TYPE_STAMIN 0 +#define WNI_CFG_WPS_REQUEST_TYPE_STAMAX 255 +#define WNI_CFG_WPS_REQUEST_TYPE_STADEF 0 + +#define WNI_CFG_WPS_REQUEST_TYPE_APMIN 0 +#define WNI_CFG_WPS_REQUEST_TYPE_APMAX 255 +#define WNI_CFG_WPS_REQUEST_TYPE_APDEF 3 + +#define WNI_CFG_WPS_CFG_METHOD_STAMIN 0 +#define WNI_CFG_WPS_CFG_METHOD_STAMAX 4294967295 +#define WNI_CFG_WPS_CFG_METHOD_STADEF 8 + +#define WNI_CFG_WPS_CFG_METHOD_APMIN 0 +#define WNI_CFG_WPS_CFG_METHOD_APMAX 4294967295 +#define WNI_CFG_WPS_CFG_METHOD_APDEF 25952654 + +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STAMIN 0 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STAMAX 65535 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STADEF 1 + +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_APMIN 0 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_APMAX 65535 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_APDEF 6 + +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_STAMIN 0 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_STAMAX 4294967295 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_STADEF 5304836 + +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_APMIN 0 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_APMAX 4294967295 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_APDEF 5304836 + +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STAMIN 0 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STAMAX 65535 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STADEF 1 + +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_APMIN 0 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_APMAX 65535 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_APDEF 1 + +#define WNI_CFG_WPS_ASSOCIATION_STATE_STAMIN 0 +#define WNI_CFG_WPS_ASSOCIATION_STATE_STAMAX 65535 +#define WNI_CFG_WPS_ASSOCIATION_STATE_STADEF 0 + +#define WNI_CFG_WPS_ASSOCIATION_STATE_APMIN 0 +#define WNI_CFG_WPS_ASSOCIATION_STATE_APMAX 65535 +#define WNI_CFG_WPS_ASSOCIATION_STATE_APDEF 0 + +#define WNI_CFG_WPS_CONFIGURATION_ERROR_STAMIN 0 +#define WNI_CFG_WPS_CONFIGURATION_ERROR_STAMAX 65535 +#define WNI_CFG_WPS_CONFIGURATION_ERROR_STADEF 0 + +#define WNI_CFG_WPS_CONFIGURATION_ERROR_APMIN 0 +#define WNI_CFG_WPS_CONFIGURATION_ERROR_APMAX 65535 +#define WNI_CFG_WPS_CONFIGURATION_ERROR_APDEF 0 + +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_STAMIN 0 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_STAMAX 4294967295 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_STADEF 0 + +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_APMIN 0 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_APMAX 4294967295 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_APDEF 0 + +#define WNI_CFG_WPS_ASSOC_METHOD_STAMIN 0 +#define WNI_CFG_WPS_ASSOC_METHOD_STAMAX 65535 +#define WNI_CFG_WPS_ASSOC_METHOD_STADEF 0 + +#define WNI_CFG_WPS_ASSOC_METHOD_APMIN 0 +#define WNI_CFG_WPS_ASSOC_METHOD_APMAX 65535 +#define WNI_CFG_WPS_ASSOC_METHOD_APDEF 0 + +#define WNI_CFG_LOW_GAIN_OVERRIDE_STAMIN 0 +#define WNI_CFG_LOW_GAIN_OVERRIDE_STAMAX 1 +#define WNI_CFG_LOW_GAIN_OVERRIDE_STADEF 0 + +#define WNI_CFG_LOW_GAIN_OVERRIDE_APMIN 0 +#define WNI_CFG_LOW_GAIN_OVERRIDE_APMAX 1 +#define WNI_CFG_LOW_GAIN_OVERRIDE_APDEF 0 + +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STAMIN 0 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STAMAX 128 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STADEF 128 + +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_APMIN 0 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_APMAX 128 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_APDEF 128 + +#define WNI_CFG_RPE_POLLING_THRESHOLD_STAMIN 0 +#define WNI_CFG_RPE_POLLING_THRESHOLD_STAMAX 65535 +#define WNI_CFG_RPE_POLLING_THRESHOLD_STADEF 10 + +#define WNI_CFG_RPE_POLLING_THRESHOLD_APMIN 0 +#define WNI_CFG_RPE_POLLING_THRESHOLD_APMAX 65535 +#define WNI_CFG_RPE_POLLING_THRESHOLD_APDEF 10 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_APMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_APMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_APDEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_APMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_APMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_APDEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_APMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_APMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_APDEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_APMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_APMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_APDEF 30 + +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STAMIN 0 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STAMAX 2 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STADEF 1 + +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_APMIN 0 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_APMAX 2 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_APDEF 1 + +#define WNI_CFG_SINGLE_TID_RC_STAMIN 0 +#define WNI_CFG_SINGLE_TID_RC_STAMAX 1 +#define WNI_CFG_SINGLE_TID_RC_STADEF 1 + +#define WNI_CFG_SINGLE_TID_RC_APMIN 0 +#define WNI_CFG_SINGLE_TID_RC_APMAX 1 +#define WNI_CFG_SINGLE_TID_RC_APDEF 1 + +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STAMIN 0 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STAMAX 1 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STADEF 1 + +#define WNI_CFG_TX_PWR_CTRL_ENABLE_APMIN 0 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_APMAX 1 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_APDEF 1 + +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMIN 0 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMAX 3 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STADEF 0 + +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_APMIN 0 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_APMAX 3 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_APDEF 0 + +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMIN 0 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMAX 255 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STADEF 0 + +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_APMIN 0 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_APMAX 255 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_APDEF 0 + +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMIN 0 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMAX 255 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STADEF 0 + +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_APMIN 0 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_APMAX 255 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_APDEF 0 + +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMIN 0 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMAX 80 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STADEF 0 + +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STAMIN 0 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STAMAX 1 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STADEF 0 + +#define WNI_CFG_TELE_BCN_WAKEUP_EN_APMIN 0 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_APMAX 1 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_APDEF 0 + +#define WNI_CFG_TELE_BCN_TRANS_LI_STAMIN 0 +#define WNI_CFG_TELE_BCN_TRANS_LI_STAMAX 7 +#define WNI_CFG_TELE_BCN_TRANS_LI_STADEF 3 + +#define WNI_CFG_TELE_BCN_TRANS_LI_APMIN 0 +#define WNI_CFG_TELE_BCN_TRANS_LI_APMAX 7 +#define WNI_CFG_TELE_BCN_TRANS_LI_APDEF 3 + +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMIN 5 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMAX 255 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STADEF 10 + +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_APMIN 5 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_APMAX 255 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_APDEF 10 + +#define WNI_CFG_TELE_BCN_MAX_LI_STAMIN 0 +#define WNI_CFG_TELE_BCN_MAX_LI_STAMAX 7 +#define WNI_CFG_TELE_BCN_MAX_LI_STADEF 5 + +#define WNI_CFG_TELE_BCN_MAX_LI_APMIN 0 +#define WNI_CFG_TELE_BCN_MAX_LI_APMAX 7 +#define WNI_CFG_TELE_BCN_MAX_LI_APDEF 5 + +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMIN 5 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMAX 255 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STADEF 15 + +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_APMIN 5 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_APMAX 255 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_APDEF 15 + +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMIN 0 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMAX 255 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STADEF 7 + +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_APMIN 0 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_APMAX 255 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_APDEF 7 + +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMIN 0 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX 1000 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STADEF 0 + +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_APMIN 0 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_APMAX 1000 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_APDEF 0 + +#define WNI_CFG_ASSOC_STA_LIMIT_STAMIN 1 +#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX 32 +#define WNI_CFG_ASSOC_STA_LIMIT_STADEF 10 + +#define WNI_CFG_ASSOC_STA_LIMIT_APMIN 1 +#define WNI_CFG_ASSOC_STA_LIMIT_APMAX 32 +#define WNI_CFG_ASSOC_STA_LIMIT_APDEF 10 + +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STADEF 1 + +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_APMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_APMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_APDEF 1 + +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STADEF 11 + +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_APMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_APMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_APDEF 11 + +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMIN 0 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMAX 5 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STADEF 0 + +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_APMIN 0 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_APMAX 5 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_APDEF 0 + +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMIN 0 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMAX 65535 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STADEF 5 + +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_APMIN 0 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_APMAX 65535 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_APDEF 5 + +#define WNI_CFG_ENABLE_CLOSE_LOOP_STAMIN 0 +#define WNI_CFG_ENABLE_CLOSE_LOOP_STAMAX 1 +#define WNI_CFG_ENABLE_CLOSE_LOOP_STADEF 0 + +#define WNI_CFG_ENABLE_CLOSE_LOOP_APMIN 0 +#define WNI_CFG_ENABLE_CLOSE_LOOP_APMAX 1 +#define WNI_CFG_ENABLE_CLOSE_LOOP_APDEF 0 + +#define WNI_CFG_ENABLE_LTE_COEX_STAMIN 0 +#define WNI_CFG_ENABLE_LTE_COEX_STAMAX 1 +#define WNI_CFG_ENABLE_LTE_COEX_STADEF 0 + +#define WNI_CFG_ENABLE_LTE_COEX_APMIN 0 +#define WNI_CFG_ENABLE_LTE_COEX_APMAX 1 +#define WNI_CFG_ENABLE_LTE_COEX_APDEF 0 + +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMIN 1 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STADEF 20 + +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_APMIN 1 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_APMAX 65535 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_APDEF 20 + +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMIN 1 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STADEF 20 + +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_APMIN 1 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_APMAX 65535 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_APDEF 20 + +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STAMIN 0 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STAMAX 1 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STADEF 0 + +#define WNI_CFG_ENABLE_MC_ADDR_LIST_APMIN 0 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_APMAX 1 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_APDEF 0 + +#define WNI_CFG_ENABLE_UC_FILTER_STAMIN 0 +#define WNI_CFG_ENABLE_UC_FILTER_STAMAX 1 +#define WNI_CFG_ENABLE_UC_FILTER_STADEF 0 + +#define WNI_CFG_ENABLE_UC_FILTER_APMIN 0 +#define WNI_CFG_ENABLE_UC_FILTER_APMAX 1 +#define WNI_CFG_ENABLE_UC_FILTER_APDEF 0 + +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMIN 0 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMAX 1 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STADEF 0 + +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_APMIN 0 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_APMAX 1 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_APDEF 0 + +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMIN 0 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX 1 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STADEF 0 + +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_APMIN 0 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_APMAX 1 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_APDEF 0 + +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMIN 0 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMAX 1 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STADEF 0 + +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_APMIN 0 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_APMAX 1 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_APDEF 0 + +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMIN 1 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMAX 255 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STADEF 3 + +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APMIN 1 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APMAX 255 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APDEF 3 + +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMIN 0 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMAX 15 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STADEF 0 + +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_APMIN 0 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_APMAX 15 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_APDEF 0 + +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STADEF 0 + +#define WNI_CFG_TDLS_BUF_STA_ENABLED_APMIN 0 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_APMAX 1 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_APDEF 0 + +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMIN 0 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMAX 10 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STADEF 0 + +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_APMIN 0 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_APMAX 10 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_APDEF 0 + +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMIN 10 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMAX 20 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STADEF 10 + +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_APMIN 10 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_APMAX 20 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_APDEF 10 + +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMIN 0 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMAX 20 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STADEF 5 + +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_APMIN 0 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_APMAX 20 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_APDEF 5 + +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN 10 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMAX 2000 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF 200 + +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_APMIN 10 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_APMAX 2000 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_APDEF 200 + +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMIN 0 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMAX 1 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STADEF 1 + +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMIN 0 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMAX 9 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STADEF 0 + +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_APMIN 0 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_APMAX 9 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_APDEF 0 + +#define WNI_CFG_ANTENNA_DIVESITY_STAMIN 0 +#define WNI_CFG_ANTENNA_DIVESITY_STAMAX 3 +#define WNI_CFG_ANTENNA_DIVESITY_STADEF 0 + +#define WNI_CFG_ANTENNA_DIVESITY_APMIN 0 +#define WNI_CFG_ANTENNA_DIVESITY_APMAX 3 +#define WNI_CFG_ANTENNA_DIVESITY_APDEF 0 + +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMIN 3 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMAX 50 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STADEF 10 + +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_APMIN 3 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_APMAX 50 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_APDEF 10 + +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN 100 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX 1000 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF 300 + +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_APMIN 100 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_APMAX 1000 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_APDEF 300 + +#define WNI_CFG_CURRENT_RSSI_STAMIN 0 +#define WNI_CFG_CURRENT_RSSI_STAMAX 127 +#define WNI_CFG_CURRENT_RSSI_STADEF 0 + +#define WNI_CFG_CURRENT_RSSI_APMIN 0 +#define WNI_CFG_CURRENT_RSSI_APMAX 127 +#define WNI_CFG_CURRENT_RSSI_APDEF 0 + +#define WNI_CFG_RTT3_ENABLE_STAMIN 0 +#define WNI_CFG_RTT3_ENABLE_STAMAX 1 +#define WNI_CFG_RTT3_ENABLE_STADEF 1 + +#define WNI_CFG_RTT3_ENABLE_APMIN 0 +#define WNI_CFG_RTT3_ENABLE_APMAX 1 +#define WNI_CFG_RTT3_ENABLE_APDEF 1 + +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMIN 0 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMAX 1 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STADEF 0 + +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_APMIN 0 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_APMAX 1 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_APDEF 0 + +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STADEF 0 + +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_APMIN 0 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_APMAX 1 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_APDEF 0 + +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMIN 0 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMAX 100 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STADEF 0 + +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_APMIN 0 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_APMAX 100 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_APDEF 0 + +#define WNI_CFG_DFS_MASTER_ENABLED_STAMIN 0 +#define WNI_CFG_DFS_MASTER_ENABLED_STAMAX 1 +#define WNI_CFG_DFS_MASTER_ENABLED_STADEF 0 + +#define WNI_CFG_DFS_MASTER_ENABLED_APMIN 0 +#define WNI_CFG_DFS_MASTER_ENABLED_APMAX 1 +#define WNI_CFG_DFS_MASTER_ENABLED_APDEF 0 + +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMIN 0 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMAX 1 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STADEF 0 + +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_APMIN 0 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_APMAX 1 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_APDEF 0 + +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF 0 + +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_APMIN 0 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_APMAX 1 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_APDEF 0 + +#define CFG_PARAM_MAX_NUM 298 +#define CFG_AP_IBUF_MAX_SIZE 246 +#define CFG_AP_SBUF_MAX_SIZE 3233 +#define CFG_STA_IBUF_MAX_SIZE 241 +#define CFG_STA_SBUF_MAX_SIZE 3199 +#define CFG_SEM_MAX_NUM 19 + +#define CFG_STA_MAGIC_DWORD 0xbeefbeef + +#define CFG_AP_MAGIC_DWORD 0xdeaddead + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h new file mode 100644 index 000000000000..d0ff9c25de60 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h @@ -0,0 +1,1615 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * DO NOT EDIT - This file is generated automatically + */ + +/* + * IMPORTANT: This file is for system that supports STA mode ONLY. + */ + + +#ifndef __WNICFGSTA_H +#define __WNICFGSTA_H + +/* + * Configuration Parameter ID for STA + */ + +#define WNI_CFG_STA_ID 0 +#define WNI_CFG_CFP_PERIOD 2 +#define WNI_CFG_CFP_MAX_DURATION 3 +#define WNI_CFG_SSID 4 +#define WNI_CFG_BEACON_INTERVAL 5 +#define WNI_CFG_DTIM_PERIOD 6 +#define WNI_CFG_WEP_KEY_LENGTH 7 +#define WNI_CFG_WEP_DEFAULT_KEY_TABLE 8 +#define WNI_CFG_WEP_DEFAULT_KEY_TABLE_ROW 4 +#define WNI_CFG_WEP_DEFAULT_KEY_TABLE_COL 1 +#define WNI_CFG_WEP_DEFAULT_KEY_1 8 +#define WNI_CFG_WEP_DEFAULT_KEY_2 9 +#define WNI_CFG_WEP_DEFAULT_KEY_3 10 +#define WNI_CFG_WEP_DEFAULT_KEY_4 11 +#define WNI_CFG_WEP_DEFAULT_KEYID 12 +#define WNI_CFG_EXCLUDE_UNENCRYPTED 13 +#define WNI_CFG_RTS_THRESHOLD 14 +#define WNI_CFG_SHORT_RETRY_LIMIT 15 +#define WNI_CFG_LONG_RETRY_LIMIT 16 +#define WNI_CFG_FRAGMENTATION_THRESHOLD 17 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME 18 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME 19 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME 20 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME 21 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT 22 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT 23 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT 24 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT 25 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT 26 +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS 27 +#define WNI_CFG_PS_ENABLE_BCN_FILTER 28 +#define WNI_CFG_PS_ENABLE_HEART_BEAT 29 +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR 30 +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT 31 +#define WNI_CFG_RF_SETTLING_TIME_CLK 32 +#define WNI_CFG_SUPPORTED_RATES_11B 33 +#define WNI_CFG_SUPPORTED_RATES_11A 34 +#define WNI_CFG_PHY_MODE 35 +#define WNI_CFG_DOT11_MODE 36 +#define WNI_CFG_OPERATIONAL_RATE_SET 37 +#define WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET 38 +#define WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET 39 +#define WNI_CFG_LISTEN_INTERVAL 40 +#define WNI_CFG_VALID_CHANNEL_LIST 41 +#define WNI_CFG_CURRENT_CHANNEL 42 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ 43 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ 44 +#define WNI_CFG_RATE_ADAPTATION_TYPE 45 +#define WNI_CFG_FIXED_RATE 46 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ 47 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ 48 +#define WNI_CFG_RETRYRATE_POLICY 49 +#define WNI_CFG_RETRYRATE_SECONDARY 50 +#define WNI_CFG_RETRYRATE_TERTIARY 51 +#define WNI_CFG_APSD_ENABLED 52 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE 53 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE 54 +#define WNI_CFG_AUTHENTICATION_TYPE 55 +#define WNI_CFG_PRIVACY_ENABLED 57 +#define WNI_CFG_SHORT_PREAMBLE 58 +#define WNI_CFG_SHORT_SLOT_TIME 59 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY 60 +#define WNI_CFG_QOS_ENABLED 61 +#define WNI_CFG_HCF_ENABLED 62 +#define WNI_CFG_RSN_ENABLED 63 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD 64 +#define WNI_CFG_MAX_NUM_PRE_AUTH 65 +#define WNI_CFG_HEART_BEAT_THRESHOLD 68 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT 69 +#define WNI_CFG_MANUFACTURER_OUI 70 +#define WNI_CFG_MANUFACTURER_NAME 71 +#define WNI_CFG_MODEL_NUMBER 72 +#define WNI_CFG_MODEL_NAME 73 +#define WNI_CFG_MANUFACTURER_PRODUCT_NAME 74 +#define WNI_CFG_MANUFACTURER_PRODUCT_VERSION 75 +#define WNI_CFG_11D_ENABLED 76 +#define WNI_CFG_MAX_TX_POWER_2_4 77 +#define WNI_CFG_MAX_TX_POWER_5 78 +#define WNI_CFG_NETWORK_DENSITY 79 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM 80 +#define WNI_CFG_CURRENT_TX_ANTENNA 81 +#define WNI_CFG_CURRENT_RX_ANTENNA 82 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL 83 +#define WNI_CFG_NEW_BSS_FOUND_IND 84 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED 85 +#define WNI_CFG_COUNTRY_CODE 87 +#define WNI_CFG_11H_ENABLED 88 +#define WNI_CFG_WT_CNF_TIMEOUT 89 +#define WNI_CFG_KEEPALIVE_TIMEOUT 90 +#define WNI_CFG_PROXIMITY 91 +#define WNI_CFG_LOG_LEVEL 92 +#define WNI_CFG_OLBC_DETECT_TIMEOUT 93 +#define WNI_CFG_PROTECTION_ENABLED 94 +#define WNI_CFG_11G_PROTECTION_ALWAYS 95 +#define WNI_CFG_FORCE_POLICY_PROTECTION 96 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED 97 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED 98 +#define WNI_CFG_11G_ONLY_POLICY 99 +#define WNI_CFG_PACKET_CLASSIFICATION 100 +#define WNI_CFG_WME_ENABLED 101 +#define WNI_CFG_ADDTS_RSP_TIMEOUT 102 +#define WNI_CFG_MAX_SP_LENGTH 103 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS 105 +#define WNI_CFG_WSM_ENABLED 106 +#define WNI_CFG_EDCA_PROFILE 107 +#define WNI_CFG_EDCA_ANI_ACBK_LOCAL 108 +#define WNI_CFG_EDCA_ANI_ACBE_LOCAL 109 +#define WNI_CFG_EDCA_ANI_ACVI_LOCAL 110 +#define WNI_CFG_EDCA_ANI_ACVO_LOCAL 111 +#define WNI_CFG_EDCA_ANI_ACBK 112 +#define WNI_CFG_EDCA_ANI_ACBE 113 +#define WNI_CFG_EDCA_ANI_ACVI 114 +#define WNI_CFG_EDCA_ANI_ACVO 115 +#define WNI_CFG_EDCA_WME_ACBK_LOCAL 116 +#define WNI_CFG_EDCA_WME_ACBE_LOCAL 117 +#define WNI_CFG_EDCA_WME_ACVI_LOCAL 118 +#define WNI_CFG_EDCA_WME_ACVO_LOCAL 119 +#define WNI_CFG_EDCA_WME_ACBK 120 +#define WNI_CFG_EDCA_WME_ACBE 121 +#define WNI_CFG_EDCA_WME_ACVI 122 +#define WNI_CFG_EDCA_WME_ACVO 123 +#define WNI_CFG_RDET_FLAG 124 +#define WNI_CFG_RADAR_CHANNEL_LIST 125 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT 126 +#define WNI_CFG_ADMIT_POLICY 127 +#define WNI_CFG_ADMIT_BWFACTOR 128 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE 129 +#define WNI_CFG_CHANNEL_BONDING_MODE 130 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE 131 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO 132 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE 133 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO 134 +#define WNI_CFG_TRIG_STA_BK_SCAN 135 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING 136 +#define WNI_CFG_SCAN_CONTROL_LIST 137 +#define WNI_CFG_MIMO_ENABLED 138 +#define WNI_CFG_BLOCK_ACK_ENABLED 139 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT 140 +#define WNI_CFG_HT_RX_STBC 141 +#define WNI_CFG_HT_CAP_INFO 142 +#define WNI_CFG_HT_AMPDU_PARAMS 143 +#define WNI_CFG_SUPPORTED_MCS_SET 144 +#define WNI_CFG_EXT_HT_CAP_INFO 145 +#define WNI_CFG_TX_BF_CAP 146 +#define WNI_CFG_AS_CAP 147 +#define WNI_CFG_HT_INFO_FIELD1 148 +#define WNI_CFG_HT_INFO_FIELD2 149 +#define WNI_CFG_HT_INFO_FIELD3 150 +#define WNI_CFG_BASIC_MCS_SET 151 +#define WNI_CFG_CURRENT_MCS_SET 152 +#define WNI_CFG_GREENFIELD_CAPABILITY 153 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH 154 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET 155 +#define WNI_CFG_VHT_LDPC_CODING_CAP 156 +#define WNI_CFG_VHT_SHORT_GI_80MHZ 157 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ 158 +#define WNI_CFG_VHT_TXSTBC 159 +#define WNI_CFG_VHT_RXSTBC 160 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP 161 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP 162 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED 163 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS 164 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP 165 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP 166 +#define WNI_CFG_VHT_TXOP_PS 167 +#define WNI_CFG_VHT_HTC_VHTC_CAP 168 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT 169 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP 170 +#define WNI_CFG_VHT_RX_ANT_PATTERN 171 +#define WNI_CFG_VHT_TX_ANT_PATTERN 172 +#define WNI_CFG_VHT_RX_MCS_MAP 173 +#define WNI_CFG_VHT_TX_MCS_MAP 174 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE 175 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE 176 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1 177 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2 178 +#define WNI_CFG_VHT_BASIC_MCS_SET 179 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT 180 +#define WNI_CFG_VHT_SS_UNDER_UTIL 181 +#define WNI_CFG_VHT_40MHZ_UTILIZATION 182 +#define WNI_CFG_VHT_80MHZ_UTILIZATION 183 +#define WNI_CFG_VHT_160MHZ_UTILIZATION 184 +#define WNI_CFG_MAX_AMSDU_LENGTH 185 +#define WNI_CFG_MPDU_DENSITY 186 +#define WNI_CFG_NUM_BUFF_ADVERT 187 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR 188 +#define WNI_CFG_SHORT_GI_20MHZ 189 +#define WNI_CFG_SHORT_GI_40MHZ 190 +#define WNI_CFG_RIFS_ENABLED 191 +#define WNI_CFG_MAX_PS_POLL 192 +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE 193 +#define WNI_CFG_RSSI_FILTER_PERIOD 194 +#define WNI_CFG_MIN_RSSI_THRESHOLD 195 +#define WNI_CFG_NTH_BEACON_FILTER 196 +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE 197 +#define WNI_CFG_SCAN_IN_POWERSAVE 198 +#define WNI_CFG_IGNORE_DTIM 199 +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE 200 +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE 201 +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE 202 +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE 203 +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON 204 +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD 205 +#define WNI_CFG_BA_TIMEOUT 206 +#define WNI_CFG_BA_THRESHOLD_HIGH 207 +#define WNI_CFG_MAX_BA_BUFFERS 208 +#define WNI_CFG_MAX_BA_SESSIONS 209 +#define WNI_CFG_BA_AUTO_SETUP 210 +#define WNI_CFG_ADDBA_REQ_DECLINE 211 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC 212 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST 213 +#define WNI_CFG_MAX_MEDIUM_TIME 214 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU 215 +#define WNI_CFG_IBSS_AUTO_BSSID 216 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 217 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 218 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 219 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 220 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 221 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 222 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 223 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 224 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 225 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 226 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 227 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 228 +#define WNI_CFG_WPS_ENABLE 229 +#define WNI_CFG_WPS_STATE 230 +#define WNI_CFG_WPS_PROBE_REQ_FLAG 231 +#define WNI_CFG_WPS_VERSION 232 +#define WNI_CFG_WPS_REQUEST_TYPE 233 +#define WNI_CFG_WPS_CFG_METHOD 234 +#define WNI_CFG_WPS_UUID 235 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 236 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 237 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 238 +#define WNI_CFG_WPS_ASSOCIATION_STATE 239 +#define WNI_CFG_WPS_CONFIGURATION_ERROR 240 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 241 +#define WNI_CFG_WPS_ASSOC_METHOD 242 +#define WNI_CFG_LOW_GAIN_OVERRIDE 243 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 244 +#define WNI_CFG_RPE_POLLING_THRESHOLD 245 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 246 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 247 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 248 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 249 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 250 +#define WNI_CFG_SINGLE_TID_RC 251 +#define WNI_CFG_TX_PWR_CTRL_ENABLE 252 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 253 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 254 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 255 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 256 +#define WNI_CFG_TELE_BCN_WAKEUP_EN 257 +#define WNI_CFG_TELE_BCN_TRANS_LI 258 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 259 +#define WNI_CFG_TELE_BCN_MAX_LI 260 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 261 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 262 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 263 +#define WNI_CFG_ASSOC_STA_LIMIT 264 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 265 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 266 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 267 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 268 +#define WNI_CFG_ENABLE_CLOSE_LOOP 269 +#define WNI_CFG_ENABLE_LTE_COEX 270 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 271 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 272 +#define WNI_CFG_ENABLE_MC_ADDR_LIST 273 +#define WNI_CFG_ENABLE_UC_FILTER 274 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 275 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 276 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 277 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 278 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK 279 +#define WNI_CFG_TDLS_BUF_STA_ENABLED 280 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME 281 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD 282 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES 283 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL 284 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN 285 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR 286 +#define WNI_CFG_ANTENNA_DIVESITY 287 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT 288 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY 289 +#define WNI_CFG_CURRENT_RSSI 290 +#define WNI_CFG_RTT3_ENABLE 291 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL 292 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED 293 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE 294 +#define WNI_CFG_DFS_MASTER_ENABLED 295 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ 296 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED 297 + +/* + * String parameter lengths + */ + +#define WNI_CFG_STA_ID_LEN 6 +#define WNI_CFG_SSID_LEN 32 +#define WNI_CFG_WEP_DEFAULT_KEY_1_LEN 13 +#define WNI_CFG_WEP_DEFAULT_KEY_2_LEN 13 +#define WNI_CFG_WEP_DEFAULT_KEY_3_LEN 13 +#define WNI_CFG_WEP_DEFAULT_KEY_4_LEN 13 +#define WNI_CFG_SUPPORTED_RATES_11B_LEN 4 +#define WNI_CFG_SUPPORTED_RATES_11A_LEN 8 +#define WNI_CFG_OPERATIONAL_RATE_SET_LEN 12 +#define WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN 8 +#define WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET_LEN 4 +#define WNI_CFG_VALID_CHANNEL_LIST_LEN 100 +#define WNI_CFG_MANUFACTURER_OUI_LEN 3 +#define WNI_CFG_MANUFACTURER_NAME_LEN 64 +#define WNI_CFG_MODEL_NUMBER_LEN 32 +#define WNI_CFG_MODEL_NAME_LEN 32 +#define WNI_CFG_MANUFACTURER_PRODUCT_NAME_LEN 32 +#define WNI_CFG_MANUFACTURER_PRODUCT_VERSION_LEN 32 +#define WNI_CFG_MAX_TX_POWER_2_4_LEN 128 +#define WNI_CFG_MAX_TX_POWER_5_LEN 128 +#define WNI_CFG_COUNTRY_CODE_LEN 3 +#define WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACBE_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVI_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVO_LOCAL_LEN 20 +#define WNI_CFG_EDCA_ANI_ACBK_LEN 20 +#define WNI_CFG_EDCA_ANI_ACBE_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVI_LEN 20 +#define WNI_CFG_EDCA_ANI_ACVO_LEN 20 +#define WNI_CFG_EDCA_WME_ACBK_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACBE_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACVI_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACVO_LOCAL_LEN 20 +#define WNI_CFG_EDCA_WME_ACBK_LEN 20 +#define WNI_CFG_EDCA_WME_ACBE_LEN 20 +#define WNI_CFG_EDCA_WME_ACVI_LEN 20 +#define WNI_CFG_EDCA_WME_ACVO_LEN 20 +#define WNI_CFG_RADAR_CHANNEL_LIST_LEN 20 +#define WNI_CFG_SCAN_CONTROL_LIST_LEN 128 +#define WNI_CFG_SUPPORTED_MCS_SET_LEN 16 +#define WNI_CFG_BASIC_MCS_SET_LEN 16 +#define WNI_CFG_CURRENT_MCS_SET_LEN 16 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN 100 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA_LEN 255 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN 255 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2_LEN 255 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3_LEN 255 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN 255 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA_LEN 255 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN 255 +#define WNI_CFG_WPS_UUID_LEN 16 + +/* + * Integer parameter min/max/default values + */ + +#define WNI_CFG_CFP_PERIOD_STAMIN 0 +#define WNI_CFG_CFP_PERIOD_STAMAX 255 +#define WNI_CFG_CFP_PERIOD_STADEF 1 + +#define WNI_CFG_CFP_MAX_DURATION_STAMIN 0 +#define WNI_CFG_CFP_MAX_DURATION_STAMAX 65535 +#define WNI_CFG_CFP_MAX_DURATION_STADEF 30000 + +#define WNI_CFG_BEACON_INTERVAL_STAMIN 0 +#define WNI_CFG_BEACON_INTERVAL_STAMAX 65535 +#define WNI_CFG_BEACON_INTERVAL_STADEF 100 + +#define WNI_CFG_DTIM_PERIOD_STAMIN 0 +#define WNI_CFG_DTIM_PERIOD_STAMAX 65535 +#define WNI_CFG_DTIM_PERIOD_STADEF 1 + +#define WNI_CFG_WEP_KEY_LENGTH_STAMIN 5 +#define WNI_CFG_WEP_KEY_LENGTH_STAMAX 13 +#define WNI_CFG_WEP_KEY_LENGTH_STADEF 5 + +#define WNI_CFG_WEP_KEY_LENGTH_5 5 +#define WNI_CFG_WEP_KEY_LENGTH_13 13 + +#define WNI_CFG_WEP_DEFAULT_KEYID_STAMIN 0 +#define WNI_CFG_WEP_DEFAULT_KEYID_STAMAX 3 +#define WNI_CFG_WEP_DEFAULT_KEYID_STADEF 0 + +#define WNI_CFG_WEP_DEFAULT_KEYID_0 0 +#define WNI_CFG_WEP_DEFAULT_KEYID_1 1 +#define WNI_CFG_WEP_DEFAULT_KEYID_2 2 +#define WNI_CFG_WEP_DEFAULT_KEYID_3 3 + +#define WNI_CFG_EXCLUDE_UNENCRYPTED_STAMIN 0 +#define WNI_CFG_EXCLUDE_UNENCRYPTED_STAMAX 1 +#define WNI_CFG_EXCLUDE_UNENCRYPTED_STADEF 0 + +#define WNI_CFG_RTS_THRESHOLD_STAMIN 0 +#define WNI_CFG_RTS_THRESHOLD_STAMAX 1048576 +#define WNI_CFG_RTS_THRESHOLD_STADEF 2347 + +#define WNI_CFG_SHORT_RETRY_LIMIT_STAMIN 0 +#define WNI_CFG_SHORT_RETRY_LIMIT_STAMAX 255 +#define WNI_CFG_SHORT_RETRY_LIMIT_STADEF 6 + +#define WNI_CFG_LONG_RETRY_LIMIT_STAMIN 0 +#define WNI_CFG_LONG_RETRY_LIMIT_STAMAX 255 +#define WNI_CFG_LONG_RETRY_LIMIT_STADEF 6 + +#define WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN 256 +#define WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX 8000 +#define WNI_CFG_FRAGMENTATION_THRESHOLD_STADEF 8000 + +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STADEF 20 + +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STADEF 40 + +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STADEF 60 + +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STAMIN 0 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STAMAX 65535 +#define WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STADEF 110 + +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF 3000 + +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STADEF 1000 + +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STAMIN 0 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STADEF 1000 + +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STADEF 2000 + +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STAMIN 0 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STADEF 1000 + +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STAMIN 0 +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STAMAX 65535 +#define WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STADEF 1000 + +#define WNI_CFG_PS_ENABLE_BCN_FILTER_STAMIN 0 +#define WNI_CFG_PS_ENABLE_BCN_FILTER_STAMAX 1 +#define WNI_CFG_PS_ENABLE_BCN_FILTER_STADEF 1 + +#define WNI_CFG_PS_ENABLE_HEART_BEAT_STAMIN 0 +#define WNI_CFG_PS_ENABLE_HEART_BEAT_STAMAX 1 +#define WNI_CFG_PS_ENABLE_HEART_BEAT_STADEF 1 + +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR_STAMIN 0 +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR_STAMAX 1 +#define WNI_CFG_PS_ENABLE_RSSI_MONITOR_STADEF 0 + +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STAMIN 1 +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STAMAX 255 +#define WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STADEF 20 + +#define WNI_CFG_RF_SETTLING_TIME_CLK_STAMIN 0 +#define WNI_CFG_RF_SETTLING_TIME_CLK_STAMAX 60000 +#define WNI_CFG_RF_SETTLING_TIME_CLK_STADEF 1500 + +#define WNI_CFG_PHY_MODE_STAMIN 0 +#define WNI_CFG_PHY_MODE_STAMAX 3 +#define WNI_CFG_PHY_MODE_STADEF 0 + +#define WNI_CFG_PHY_MODE_11A 0 +#define WNI_CFG_PHY_MODE_11B 1 +#define WNI_CFG_PHY_MODE_11G 2 +#define WNI_CFG_PHY_MODE_NONE 3 + +#define WNI_CFG_DOT11_MODE_STAMIN 0 +#define WNI_CFG_DOT11_MODE_STAMAX 11 +#define WNI_CFG_DOT11_MODE_STADEF 0 + +#define WNI_CFG_DOT11_MODE_ALL 0 +#define WNI_CFG_DOT11_MODE_11A 1 +#define WNI_CFG_DOT11_MODE_11B 2 +#define WNI_CFG_DOT11_MODE_11G 3 +#define WNI_CFG_DOT11_MODE_11N 4 +#define WNI_CFG_DOT11_MODE_11G_ONLY 5 +#define WNI_CFG_DOT11_MODE_11N_ONLY 6 +#define WNI_CFG_DOT11_MODE_11AC 7 +#define WNI_CFG_DOT11_MODE_11AC_ONLY 8 + +#define WNI_CFG_LISTEN_INTERVAL_STAMIN 0 +#define WNI_CFG_LISTEN_INTERVAL_STAMAX 65535 +#define WNI_CFG_LISTEN_INTERVAL_STADEF 1 + +#define WNI_CFG_CURRENT_CHANNEL_STAMIN 0 +#define WNI_CFG_CURRENT_CHANNEL_STAMAX 165 +#define WNI_CFG_CURRENT_CHANNEL_STADEF 1 + +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STAMIN 0 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STAMAX 11 +#define WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STADEF 5 + +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STAMIN 0 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STAMAX 31 +#define WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STADEF 1 + +#define WNI_CFG_RATE_ADAPTATION_TYPE_STAMIN 0 +#define WNI_CFG_RATE_ADAPTATION_TYPE_STAMAX 2 +#define WNI_CFG_RATE_ADAPTATION_TYPE_STADEF 1 + +#define WNI_CFG_RATE_ADAPTATION_TYPE_FIXED 0 +#define WNI_CFG_RATE_ADAPTATION_TYPE_AUTO 1 +#define WNI_CFG_RATE_ADAPTATION_TYPE_SNR_BASED 2 + +#define WNI_CFG_FIXED_RATE_STAMIN 0 +#define WNI_CFG_FIXED_RATE_STAMAX 44 +#define WNI_CFG_FIXED_RATE_STADEF 0 + +#define WNI_CFG_FIXED_RATE_AUTO 0 +#define WNI_CFG_FIXED_RATE_1MBPS 1 +#define WNI_CFG_FIXED_RATE_2MBPS 2 +#define WNI_CFG_FIXED_RATE_5_5MBPS 3 +#define WNI_CFG_FIXED_RATE_11MBPS 4 +#define WNI_CFG_FIXED_RATE_6MBPS 5 +#define WNI_CFG_FIXED_RATE_9MBPS 6 +#define WNI_CFG_FIXED_RATE_12MBPS 7 +#define WNI_CFG_FIXED_RATE_18MBPS 8 +#define WNI_CFG_FIXED_RATE_24MBPS 9 +#define WNI_CFG_FIXED_RATE_36MBPS 10 +#define WNI_CFG_FIXED_RATE_48MBPS 11 +#define WNI_CFG_FIXED_RATE_54MBPS 12 +#define WNI_CFG_FIXED_RATE_6_5MBPS_MCS0_20MHZ_SIMO 13 +#define WNI_CFG_FIXED_RATE_13MBPS_MCS1_20MHZ_SIMO 14 +#define WNI_CFG_FIXED_RATE_19_5MBPS_MCS2_20MHZ_SIMO 15 +#define WNI_CFG_FIXED_RATE_26MBPS_MCS3_20MHZ_SIMO 16 +#define WNI_CFG_FIXED_RATE_39MBPS_MCS4_20MHZ_SIMO 17 +#define WNI_CFG_FIXED_RATE_52MBPS_MCS5_20MHZ_SIMO 18 +#define WNI_CFG_FIXED_RATE_58_5MBPS_MCS6_20MHZ_SIMO 19 +#define WNI_CFG_FIXED_RATE_65MBPS_MCS7_20MHZ_SIMO 20 +#define WNI_CFG_FIXED_RATE_7_2MBPS_MCS0_20MHZ_SIMO_SGI 21 +#define WNI_CFG_FIXED_RATE_14_4MBPS_MCS1_20MHZ_SIMO_SGI 22 +#define WNI_CFG_FIXED_RATE_21_7MBPS_MCS2_20MHZ_SIMO_SGI 23 +#define WNI_CFG_FIXED_RATE_28_9MBPS_MCS3_20MHZ_SIMO_SGI 24 +#define WNI_CFG_FIXED_RATE_43_3MBPS_MCS4_20MHZ_SIMO_SGI 25 +#define WNI_CFG_FIXED_RATE_57_8MBPS_MCS5_20MHZ_SIMO_SGI 26 +#define WNI_CFG_FIXED_RATE_65MBPS_MCS6_20MHZ_SIMO_SGI 27 +#define WNI_CFG_FIXED_RATE_72_2MBPS_MCS7_20MHZ_SIMO_SGI 28 +#define WNI_CFG_FIXED_RATE_0_25MBPS_SLR_20MHZ_SIMO 29 +#define WNI_CFG_FIXED_RATE_0_5MBPS_SLR_20MHZ_SIMO 30 +#define WNI_CFG_FIXED_RATE_68_25MBPS_QC_PROP_20MHZ_SIMO 31 +#define WNI_CFG_FIXED_RATE_54MBPS_MCS3_40MHZ_SIMO 32 +#define WNI_CFG_FIXED_RATE_81MBPS_MCS4_40MHZ_SIMO 33 +#define WNI_CFG_FIXED_RATE_108MBPS_MCS5_40MHZ_SIMO 34 +#define WNI_CFG_FIXED_RATE_121_5MBPS_MCS6_40MHZ_SIMO 35 +#define WNI_CFG_FIXED_RATE_135MBPS_MCS7_40MHZ_SIMO 36 +#define WNI_CFG_FIXED_RATE_15MBPS_MCS0_40MHZ_SIMO_SGI 37 +#define WNI_CFG_FIXED_RATE_30MBPS_MCS1_40MHZ_SIMO_SGI 38 +#define WNI_CFG_FIXED_RATE_45MBPS_MCS2_40MHZ_SIMO_SGI 39 +#define WNI_CFG_FIXED_RATE_60MBPS_MCS3_40MHZ_SIMO_SGI 40 +#define WNI_CFG_FIXED_RATE_90MBPS_MCS4_40MHZ_SIMO_SGI 41 +#define WNI_CFG_FIXED_RATE_120MBPS_MCS5_40MHZ_SIMO_SGI 42 +#define WNI_CFG_FIXED_RATE_135MBPS_MCS6_40MHZ_SIMO_SGI 43 +#define WNI_CFG_FIXED_RATE_150MBPS_MCS7_40MHZ_SIMO_SGI 44 + +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STAMIN 0 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STAMAX 31 +#define WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STADEF 1 + +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STAMIN 0 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STAMAX 31 +#define WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STADEF 5 + +#define WNI_CFG_RETRYRATE_POLICY_STAMIN 0 +#define WNI_CFG_RETRYRATE_POLICY_STAMAX 255 +#define WNI_CFG_RETRYRATE_POLICY_STADEF 4 + +#define WNI_CFG_RETRYRATE_POLICY_MIN_SUPPORTED 0 +#define WNI_CFG_RETRYRATE_POLICY_PRIMARY 1 +#define WNI_CFG_RETRYRATE_POLICY_RESERVED 2 +#define WNI_CFG_RETRYRATE_POLICY_CLOSEST 3 +#define WNI_CFG_RETRYRATE_POLICY_AUTOSELECT 4 +#define WNI_CFG_RETRYRATE_POLICY_MAX 5 + +#define WNI_CFG_RETRYRATE_SECONDARY_STAMIN 0 +#define WNI_CFG_RETRYRATE_SECONDARY_STAMAX 255 +#define WNI_CFG_RETRYRATE_SECONDARY_STADEF 0 + +#define WNI_CFG_RETRYRATE_TERTIARY_STAMIN 0 +#define WNI_CFG_RETRYRATE_TERTIARY_STAMAX 255 +#define WNI_CFG_RETRYRATE_TERTIARY_STADEF 0 + +#define WNI_CFG_APSD_ENABLED_STAMIN 0 +#define WNI_CFG_APSD_ENABLED_STAMAX 1 +#define WNI_CFG_APSD_ENABLED_STADEF 0 + +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_STAMIN 0 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_STAMAX 1 +#define WNI_CFG_SHARED_KEY_AUTH_ENABLE_STADEF 1 + +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STAMIN 0 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STAMAX 1 +#define WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STADEF 1 + +#define WNI_CFG_AUTHENTICATION_TYPE_STAMIN 0 +#define WNI_CFG_AUTHENTICATION_TYPE_STAMAX 65535 +#define WNI_CFG_AUTHENTICATION_TYPE_STADEF 0 + +#define WNI_CFG_PRIVACY_ENABLED_STAMIN 0 +#define WNI_CFG_PRIVACY_ENABLED_STAMAX 1 +#define WNI_CFG_PRIVACY_ENABLED_STADEF 0 + +#define WNI_CFG_SHORT_PREAMBLE_STAMIN 0 +#define WNI_CFG_SHORT_PREAMBLE_STAMAX 1 +#define WNI_CFG_SHORT_PREAMBLE_STADEF 1 + +#define WNI_CFG_SHORT_SLOT_TIME_STAMIN 0 +#define WNI_CFG_SHORT_SLOT_TIME_STAMAX 1 +#define WNI_CFG_SHORT_SLOT_TIME_STADEF 1 + +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STAMIN 0 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STAMAX 1 +#define WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STADEF 0 + +#define WNI_CFG_QOS_ENABLED_STAMIN 0 +#define WNI_CFG_QOS_ENABLED_STAMAX 1 +#define WNI_CFG_QOS_ENABLED_STADEF 0 + +#define WNI_CFG_HCF_ENABLED_STAMIN 0 +#define WNI_CFG_HCF_ENABLED_STAMAX 1 +#define WNI_CFG_HCF_ENABLED_STADEF 0 + +#define WNI_CFG_RSN_ENABLED_STAMIN 0 +#define WNI_CFG_RSN_ENABLED_STAMAX 1 +#define WNI_CFG_RSN_ENABLED_STADEF 0 + +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_STAMIN 0 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_STAMAX 180000 +#define WNI_CFG_BACKGROUND_SCAN_PERIOD_STADEF 5000 + +#define WNI_CFG_MAX_NUM_PRE_AUTH_STAMIN 0 +#define WNI_CFG_MAX_NUM_PRE_AUTH_STAMAX 256 +#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_STADEF 40 + +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMIN 10 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMAX 10000 +#define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STADEF 40 + +#define WNI_CFG_11D_ENABLED_STAMIN 0 +#define WNI_CFG_11D_ENABLED_STAMAX 1 +#define WNI_CFG_11D_ENABLED_STADEF 1 + +#define WNI_CFG_NETWORK_DENSITY_STAMIN 0 +#define WNI_CFG_NETWORK_DENSITY_STAMAX 3 +#define WNI_CFG_NETWORK_DENSITY_STADEF 3 + +#define WNI_CFG_NETWORK_DENSITY_LOW 0 +#define WNI_CFG_NETWORK_DENSITY_MEDIUM 1 +#define WNI_CFG_NETWORK_DENSITY_HIGH 2 +#define WNI_CFG_NETWORK_DENSITY_ADAPTIVE 3 + +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STAMIN 1 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STAMAX 2 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STADEF 2 + +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_CARRIER 1 +#define WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_CORRELATION 2 + +#define WNI_CFG_CURRENT_TX_ANTENNA_STAMIN 1 +#define WNI_CFG_CURRENT_TX_ANTENNA_STAMAX 1 +#define WNI_CFG_CURRENT_TX_ANTENNA_STADEF 1 + +#define WNI_CFG_CURRENT_RX_ANTENNA_STAMIN 1 +#define WNI_CFG_CURRENT_RX_ANTENNA_STAMAX 2 +#define WNI_CFG_CURRENT_RX_ANTENNA_STADEF 2 + +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMIN 0 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX 128 +#define WNI_CFG_CURRENT_TX_POWER_LEVEL_STADEF 27 + +#define WNI_CFG_NEW_BSS_FOUND_IND_STAMIN 0 +#define WNI_CFG_NEW_BSS_FOUND_IND_STAMAX 1 +#define WNI_CFG_NEW_BSS_FOUND_IND_STADEF 0 + +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_STAMIN 0 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_STAMAX 1 +#define WNI_CFG_PROPRIETARY_RATES_ENABLED_STADEF 0 + +#define WNI_CFG_11H_ENABLED_STAMIN 0 +#define WNI_CFG_11H_ENABLED_STAMAX 1 +#define WNI_CFG_11H_ENABLED_STADEF 1 + +#define WNI_CFG_WT_CNF_TIMEOUT_STAMIN 10 +#define WNI_CFG_WT_CNF_TIMEOUT_STAMAX 3000 +#define WNI_CFG_WT_CNF_TIMEOUT_STADEF 1000 + +#define WNI_CFG_KEEPALIVE_TIMEOUT_STAMIN 0 +#define WNI_CFG_KEEPALIVE_TIMEOUT_STAMAX 3600000 +#define WNI_CFG_KEEPALIVE_TIMEOUT_STADEF 0 + +#define WNI_CFG_PROXIMITY_STAMIN 0 +#define WNI_CFG_PROXIMITY_STAMAX 1 +#define WNI_CFG_PROXIMITY_STADEF 0 + +#define WNI_CFG_PROXIMITY_OFF 0 +#define WNI_CFG_PROXIMITY_ON 1 + +#define WNI_CFG_LOG_LEVEL_STAMIN 0 +#define WNI_CFG_LOG_LEVEL_STAMAX 7 +#define WNI_CFG_LOG_LEVEL_STADEF 4 + +#define WNI_CFG_OLBC_DETECT_TIMEOUT_STAMIN 1000 +#define WNI_CFG_OLBC_DETECT_TIMEOUT_STAMAX 30000 +#define WNI_CFG_OLBC_DETECT_TIMEOUT_STADEF 10000 + +#define WNI_CFG_PROTECTION_ENABLED_STAMIN 0 +#define WNI_CFG_PROTECTION_ENABLED_STAMAX 65535 +#define WNI_CFG_PROTECTION_ENABLED_STADEF 65535 + +#define WNI_CFG_PROTECTION_ENABLED_FROM_llA 0 +#define WNI_CFG_PROTECTION_ENABLED_FROM_llB 1 +#define WNI_CFG_PROTECTION_ENABLED_FROM_llG 2 +#define WNI_CFG_PROTECTION_ENABLED_HT_20 3 +#define WNI_CFG_PROTECTION_ENABLED_NON_GF 4 +#define WNI_CFG_PROTECTION_ENABLED_LSIG_TXOP 5 +#define WNI_CFG_PROTECTION_ENABLED_RIFS 6 +#define WNI_CFG_PROTECTION_ENABLED_OBSS 7 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_FROM_llA 8 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_FROM_llB 9 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_FROM_llG 10 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_HT20 11 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_NON_GF 12 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_LSIG_TXOP 13 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_RIFS 14 +#define WNI_CFG_PROTECTION_ENABLED_OLBC_OBSS 15 + +#define WNI_CFG_11G_PROTECTION_ALWAYS_STAMIN 0 +#define WNI_CFG_11G_PROTECTION_ALWAYS_STAMAX 1 +#define WNI_CFG_11G_PROTECTION_ALWAYS_STADEF 0 + +#define WNI_CFG_FORCE_POLICY_PROTECTION_STAMIN 0 +#define WNI_CFG_FORCE_POLICY_PROTECTION_STAMAX 5 +#define WNI_CFG_FORCE_POLICY_PROTECTION_STADEF 5 + +#define WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE 0 +#define WNI_CFG_FORCE_POLICY_PROTECTION_CTS 1 +#define WNI_CFG_FORCE_POLICY_PROTECTION_RTS 2 +#define WNI_CFG_FORCE_POLICY_PROTECTION_DUAL_CTS 3 +#define WNI_CFG_FORCE_POLICY_PROTECTION_RTS_ALWAYS 4 +#define WNI_CFG_FORCE_POLICY_PROTECTION_AUTO 5 + +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STAMIN 0 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STAMAX 1 +#define WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STADEF 0 + +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STAMIN 0 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STAMAX 1 +#define WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STADEF 1 + +#define WNI_CFG_11G_ONLY_POLICY_STAMIN 0 +#define WNI_CFG_11G_ONLY_POLICY_STAMAX 1 +#define WNI_CFG_11G_ONLY_POLICY_STADEF 0 + +#define WNI_CFG_PACKET_CLASSIFICATION_STAMIN 0 +#define WNI_CFG_PACKET_CLASSIFICATION_STAMAX 3 +#define WNI_CFG_PACKET_CLASSIFICATION_STADEF 0 + +#define WNI_CFG_PACKET_CLASSIFICATION_DISABLED 0 +#define WNI_CFG_PACKET_CLASSIFICATION_DSCP 1 +#define WNI_CFG_PACKET_CLASSIFICATION_8021P 2 +#define WNI_CFG_PACKET_CLASSIFICATION_ALL 3 + +#define WNI_CFG_WME_ENABLED_STAMIN 0 +#define WNI_CFG_WME_ENABLED_STAMAX 1 +#define WNI_CFG_WME_ENABLED_STADEF 1 + +#define WNI_CFG_ADDTS_RSP_TIMEOUT_STAMIN 0 +#define WNI_CFG_ADDTS_RSP_TIMEOUT_STAMAX 65535 +#define WNI_CFG_ADDTS_RSP_TIMEOUT_STADEF 1000 + +#define WNI_CFG_MAX_SP_LENGTH_STAMIN 0 +#define WNI_CFG_MAX_SP_LENGTH_STAMAX 3 +#define WNI_CFG_MAX_SP_LENGTH_STADEF 0 + +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STAMIN 0 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STAMAX 1 +#define WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STADEF 0 + +#define WNI_CFG_WSM_ENABLED_STAMIN 0 +#define WNI_CFG_WSM_ENABLED_STAMAX 1 +#define WNI_CFG_WSM_ENABLED_STADEF 0 + +#define WNI_CFG_EDCA_PROFILE_STAMIN 0 +#define WNI_CFG_EDCA_PROFILE_STAMAX 255 +#define WNI_CFG_EDCA_PROFILE_STADEF 1 + +#define WNI_CFG_EDCA_PROFILE_ANI 0 +#define WNI_CFG_EDCA_PROFILE_WMM 1 +#define WNI_CFG_EDCA_PROFILE_TIT_DEMO 2 +#define WNI_CFG_EDCA_PROFILE_MAX 3 +#define WNI_CFG_EDCA_PROFILE_ACM_IDX 0 +#define WNI_CFG_EDCA_PROFILE_AIFSN_IDX 1 +#define WNI_CFG_EDCA_PROFILE_CWMINA_IDX 2 +#define WNI_CFG_EDCA_PROFILE_CWMAXA_IDX 4 +#define WNI_CFG_EDCA_PROFILE_TXOPA_IDX 6 +#define WNI_CFG_EDCA_PROFILE_CWMINB_IDX 7 +#define WNI_CFG_EDCA_PROFILE_CWMAXB_IDX 9 +#define WNI_CFG_EDCA_PROFILE_TXOPB_IDX 11 +#define WNI_CFG_EDCA_PROFILE_CWMING_IDX 12 +#define WNI_CFG_EDCA_PROFILE_CWMAXG_IDX 14 +#define WNI_CFG_EDCA_PROFILE_TXOPG_IDX 16 + +#define WNI_CFG_RDET_FLAG_STAMIN 0 +#define WNI_CFG_RDET_FLAG_STAMAX 1 +#define WNI_CFG_RDET_FLAG_STADEF 0 + +#define WNI_CFG_RDET_FLAG_ENABLE 1 +#define WNI_CFG_RDET_FLAG_DISABLE 0 + +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_STAMIN 0 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_STAMAX 255 +#define WNI_CFG_LOCAL_POWER_CONSTRAINT_STADEF 0 + +#define WNI_CFG_ADMIT_POLICY_STAMIN 0 +#define WNI_CFG_ADMIT_POLICY_STAMAX 2 +#define WNI_CFG_ADMIT_POLICY_STADEF 0 + +#define WNI_CFG_ADMIT_POLICY_ADMIT_ALL 0 +#define WNI_CFG_ADMIT_POLICY_REJECT_ALL 1 +#define WNI_CFG_ADMIT_POLICY_BW_FACTOR 2 + +#define WNI_CFG_ADMIT_BWFACTOR_STAMIN 0 +#define WNI_CFG_ADMIT_BWFACTOR_STAMAX 100 +#define WNI_CFG_ADMIT_BWFACTOR_STADEF 20 + +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STAMIN 0 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STAMAX 256 +#define WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STADEF 60 + +#define WNI_CFG_CHANNEL_BONDING_MODE_STAMIN 0 +#define WNI_CFG_CHANNEL_BONDING_MODE_STAMAX 10 +#define WNI_CFG_CHANNEL_BONDING_MODE_STADEF 0 + +#define WNI_CFG_CHANNEL_BONDING_MODE_DISABLE 0 +#define WNI_CFG_CHANNEL_BONDING_MODE_ENABLE 1 +#define WNI_CFG_CHANNEL_BONDING_MODE_IF_NO_LEGACY_BSS 2 +#define WNI_CFG_CHANNEL_BONDING_MODE_IF_NO_LEGACY_ALL 3 +#define WNI_CFG_CHANNEL_BONDING_MODE_INTELLIGENT 4 + +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STAMIN 0 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STAMAX 10 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STADEF 0 + +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_NONE 0 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_LOWER 1 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_HIGHER 2 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_LOW_40MHZ_CENTERED 3 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_CENTERED_40MHZ_CENTERED 4 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_HIGH_40MHZ_CENTERED 5 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_LOW_40MHZ_LOW 6 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_HIGH_40MHZ_LOW 7 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_LOW_40MHZ_HIGH 8 +#define WNI_CFG_CB_SECONDARY_CHANNEL_STATE_11AC_20MHZ_HIGH_40MHZ_HIGH 9 + +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STAMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STAMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STADEF 2 + +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_STAMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_STAMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_ONE_STADEF 4 + +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_STAMIN 0 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_STAMAX 255 +#define WNI_CFG_DYNAMIC_THRESHOLD_TWO_STADEF 6 + +#define WNI_CFG_TRIG_STA_BK_SCAN_STAMIN 0 +#define WNI_CFG_TRIG_STA_BK_SCAN_STAMAX 1 +#define WNI_CFG_TRIG_STA_BK_SCAN_STADEF 0 + +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STAMIN 0 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STAMAX 255 +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STADEF 255 + +#define WNI_CFG_DYNAMIC_PROFILE_SWITCHING_UNUSED 255 + +#define WNI_CFG_MIMO_ENABLED_STAMIN 0 +#define WNI_CFG_MIMO_ENABLED_STAMAX 1 +#define WNI_CFG_MIMO_ENABLED_STADEF 1 + +#define WNI_CFG_MIMO_ENABLED_ENABLE 1 +#define WNI_CFG_MIMO_ENABLED_DISABLE 0 + +#define WNI_CFG_BLOCK_ACK_ENABLED_STAMIN 0 +#define WNI_CFG_BLOCK_ACK_ENABLED_STAMAX 3 +#define WNI_CFG_BLOCK_ACK_ENABLED_STADEF 0 + +#define WNI_CFG_BLOCK_ACK_ENABLED_DELAYED 0 +#define WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE 1 + +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STAMIN 0 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STAMAX 65535 +#define WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STADEF 1000 + +#define WNI_CFG_HT_RX_STBC_STAMIN 0 +#define WNI_CFG_HT_RX_STBC_STAMAX 3 +#define WNI_CFG_HT_RX_STBC_STADEF 1 + +#define WNI_CFG_HT_CAP_INFO_STAMIN 0 +#define WNI_CFG_HT_CAP_INFO_STAMAX 65535 +#define WNI_CFG_HT_CAP_INFO_STADEF 364 + +#define WNI_CFG_HT_CAP_INFO_ADVANCE_CODING 0 +#define WNI_CFG_HT_CAP_INFO_SUPPORTED_CHAN_WIDTH_SET 1 +#define WNI_CFG_HT_CAP_INFO_SM_POWER_SAVE 2 +#define WNI_CFG_HT_CAP_INFO_GREEN_FIELD 4 +#define WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ 5 +#define WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ 6 +#define WNI_CFG_HT_CAP_INFO_TX_STBC 7 +#define WNI_CFG_HT_CAP_INFO_RX_STBC 8 +#define WNI_CFG_HT_CAP_INFO_DELAYED_BA 10 +#define WNI_CFG_HT_CAP_INFO_MAX_AMSDU_SIZE 11 +#define WNI_CFG_HT_CAP_INFO_DSSS_CCK_MODE_40MHZ 12 +#define WNI_CFG_HT_CAP_INFO_PSMP 13 +#define WNI_CFG_HT_CAP_INFO_STBC_CONTROL_FRAME 14 +#define WNI_CFG_HT_CAP_INFO_LSIG_TXOP_PROTECTION 15 + +#define WNI_CFG_HT_AMPDU_PARAMS_STAMIN 0 +#define WNI_CFG_HT_AMPDU_PARAMS_STAMAX 255 +#define WNI_CFG_HT_AMPDU_PARAMS_STADEF 0 + +#define WNI_CFG_HT_AMPDU_PARAMS_MAX_RX_AMPDU_FACTOR 0 +#define WNI_CFG_HT_AMPDU_PARAMS_MPDU_DENSITY 2 +#define WNI_CFG_HT_AMPDU_PARAMS_RESERVED 5 + +#define WNI_CFG_EXT_HT_CAP_INFO_STAMIN 0 +#define WNI_CFG_EXT_HT_CAP_INFO_STAMAX 65535 +#define WNI_CFG_EXT_HT_CAP_INFO_STADEF 1024 + +#define WNI_CFG_EXT_HT_CAP_INFO_PCO 0 +#define WNI_CFG_EXT_HT_CAP_INFO_TRANSITION_TIME 1 +#define WNI_CFG_EXT_HT_CAP_INFO_RESERVED1 3 +#define WNI_CFG_EXT_HT_CAP_INFO_MCS_FEEDBACK 8 +#define WNI_CFG_EXT_HT_CAP_INFO_HTC_SUPPORT 10 +#define WNI_CFG_EXT_HT_CAP_INFO_RD_RESPONDER 11 +#define WNI_CFG_EXT_HT_CAP_INFO_RESERVED2 12 + +#define WNI_CFG_TX_BF_CAP_STAMIN 0 +#define WNI_CFG_TX_BF_CAP_STAMAX 4294967295 +#define WNI_CFG_TX_BF_CAP_STADEF 0 + +#define WNI_CFG_AS_CAP_STAMIN 0 +#define WNI_CFG_AS_CAP_STAMAX 255 +#define WNI_CFG_AS_CAP_STADEF 0 + +#define WNI_CFG_AS_CAP_ANTENNA_SELECTION 0 +#define WNI_CFG_AS_CAP_EXPLICIT_CSI_FEEDBACK_TX 1 +#define WNI_CFG_AS_CAP_ANTENNA_INDICES_FEEDBACK_TX 2 +#define WNI_CFG_AS_CAP_EXPLICIT_CSI_FEEDBACK 3 +#define WNI_CFG_AS_CAP_ANTENNA_INDICES_FEEDBACK 4 +#define WNI_CFG_AS_CAP_RX_AS 5 +#define WNI_CFG_AS_CAP_TX_SOUNDING_PPDUS 6 +#define WNI_CFG_AS_CAP_RESERVED 7 + +#define WNI_CFG_HT_INFO_FIELD1_STAMIN 0 +#define WNI_CFG_HT_INFO_FIELD1_STAMAX 255 +#define WNI_CFG_HT_INFO_FIELD1_STADEF 15 + +#define WNI_CFG_HT_INFO_FIELD1_SECONDARY_CHANNEL_OFFSET 0 +#define WNI_CFG_HT_INFO_FIELD1_RECOMMENDED_CHANNEL_WIDTH 2 +#define WNI_CFG_HT_INFO_FIELD1_RIFS_MODE 3 +#define WNI_CFG_HT_INFO_FIELD1_PSMP_ACCESS_ONLY 4 +#define WNI_CFG_HT_INFO_FIELD1_SERVICE_INTERVAL_GRANULARITY 5 + +#define WNI_CFG_HT_INFO_FIELD2_STAMIN 0 +#define WNI_CFG_HT_INFO_FIELD2_STAMAX 65535 +#define WNI_CFG_HT_INFO_FIELD2_STADEF 0 + +#define WNI_CFG_HT_INFO_FIELD2_OP_MODE 0 +#define WNI_CFG_HT_INFO_FIELD2_NON_GF_DEVICES_PRESENT 2 +#define WNI_CFG_HT_INFO_FIELD2_RESERVED 3 + +#define WNI_CFG_HT_INFO_FIELD3_STAMIN 0 +#define WNI_CFG_HT_INFO_FIELD3_STAMAX 65535 +#define WNI_CFG_HT_INFO_FIELD3_STADEF 0 + +#define WNI_CFG_HT_INFO_FIELD3_BASIC_STBC_MCS 0 +#define WNI_CFG_HT_INFO_FIELD3_DUAL_STBC_PROTECTION 7 +#define WNI_CFG_HT_INFO_FIELD3_SECONDARY_BEACON 8 +#define WNI_CFG_HT_INFO_FIELD3_LSIG_TXOP_PROTECTION_FULL_SUPPORT 9 +#define WNI_CFG_HT_INFO_FIELD3_PCO_ACTIVE 10 +#define WNI_CFG_HT_INFO_FIELD3_PCO_PHASE 11 +#define WNI_CFG_HT_INFO_FIELD3_RESERVED 12 + +#define WNI_CFG_GREENFIELD_CAPABILITY_STAMIN 0 +#define WNI_CFG_GREENFIELD_CAPABILITY_STAMAX 1 +#define WNI_CFG_GREENFIELD_CAPABILITY_STADEF 0 + +#define WNI_CFG_GREENFIELD_CAPABILITY_ENABLE 1 +#define WNI_CFG_GREENFIELD_CAPABILITY_DISABLE 0 + +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_STAMIN 0 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_STAMAX 2 +#define WNI_CFG_VHT_MAX_MPDU_LENGTH_STADEF 0 + +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STAMIN 0 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STAMAX 0 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STADEF 0 + +#define WNI_CFG_VHT_LDPC_CODING_CAP_STAMIN 0 +#define WNI_CFG_VHT_LDPC_CODING_CAP_STAMAX 1 +#define WNI_CFG_VHT_LDPC_CODING_CAP_STADEF 0 + +#define WNI_CFG_VHT_SHORT_GI_80MHZ_STAMIN 0 +#define WNI_CFG_VHT_SHORT_GI_80MHZ_STAMAX 1 +#define WNI_CFG_VHT_SHORT_GI_80MHZ_STADEF 1 + +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STAMIN 0 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STAMAX 1 +#define WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STADEF 0 + +#define WNI_CFG_VHT_TXSTBC_STAMIN 0 +#define WNI_CFG_VHT_TXSTBC_STAMAX 1 +#define WNI_CFG_VHT_TXSTBC_STADEF 0 + +#define WNI_CFG_VHT_RXSTBC_STAMIN 0 +#define WNI_CFG_VHT_RXSTBC_STAMAX 1 +#define WNI_CFG_VHT_RXSTBC_STADEF 1 + +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_STAMIN 0 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_STAMAX 1 +#define WNI_CFG_VHT_SU_BEAMFORMER_CAP_STADEF 0 + +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMIN 0 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMAX 1 +#define WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STADEF 1 + +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMIN 0 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMAX 4 +#define WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STADEF 0 + +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STAMIN 0 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STAMAX 3 +#define WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STADEF 0 + +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_STAMIN 0 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_STAMAX 1 +#define WNI_CFG_VHT_MU_BEAMFORMER_CAP_STADEF 0 + +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STAMIN 0 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STAMAX 1 +#define WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STADEF 0 + +#define WNI_CFG_VHT_TXOP_PS_STAMIN 0 +#define WNI_CFG_VHT_TXOP_PS_STAMAX 1 +#define WNI_CFG_VHT_TXOP_PS_STADEF 0 + +#define WNI_CFG_VHT_HTC_VHTC_CAP_STAMIN 0 +#define WNI_CFG_VHT_HTC_VHTC_CAP_STAMAX 1 +#define WNI_CFG_VHT_HTC_VHTC_CAP_STADEF 0 + +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STAMIN 0 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STAMAX 7 +#define WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STADEF 3 + +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_STAMIN 0 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_STAMAX 3 +#define WNI_CFG_VHT_LINK_ADAPTATION_CAP_STADEF 0 + +#define WNI_CFG_VHT_RX_ANT_PATTERN_STAMIN 0 +#define WNI_CFG_VHT_RX_ANT_PATTERN_STAMAX 1 +#define WNI_CFG_VHT_RX_ANT_PATTERN_STADEF 1 + +#define WNI_CFG_VHT_TX_ANT_PATTERN_STAMIN 0 +#define WNI_CFG_VHT_TX_ANT_PATTERN_STAMAX 1 +#define WNI_CFG_VHT_TX_ANT_PATTERN_STADEF 1 + +#define WNI_CFG_VHT_RX_MCS_MAP_STAMIN 0 +#define WNI_CFG_VHT_RX_MCS_MAP_STAMAX 65535 +#define WNI_CFG_VHT_RX_MCS_MAP_STADEF 65534 + +#define WNI_CFG_VHT_TX_MCS_MAP_STAMIN 0 +#define WNI_CFG_VHT_TX_MCS_MAP_STAMAX 65535 +#define WNI_CFG_VHT_TX_MCS_MAP_STADEF 65534 + +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STAMIN 0 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STAMAX 780 +#define WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STADEF 780 + +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STAMIN 0 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STAMAX 780 +#define WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STADEF 780 + +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STAMIN 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STAMAX 256 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STADEF 0 + +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STAMIN 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STAMAX 0 +#define WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STADEF 0 + +#define WNI_CFG_VHT_BASIC_MCS_SET_STAMIN 0 +#define WNI_CFG_VHT_BASIC_MCS_SET_STAMAX 65535 +#define WNI_CFG_VHT_BASIC_MCS_SET_STADEF 65534 + +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STAMIN 0 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STAMAX 4 +#define WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STADEF 0 + +#define WNI_CFG_VHT_SS_UNDER_UTIL_STAMIN 0 +#define WNI_CFG_VHT_SS_UNDER_UTIL_STAMAX 0 +#define WNI_CFG_VHT_SS_UNDER_UTIL_STADEF 0 + +#define WNI_CFG_VHT_40MHZ_UTILIZATION_STAMIN 0 +#define WNI_CFG_VHT_40MHZ_UTILIZATION_STAMAX 0 +#define WNI_CFG_VHT_40MHZ_UTILIZATION_STADEF 0 + +#define WNI_CFG_VHT_80MHZ_UTILIZATION_STAMIN 0 +#define WNI_CFG_VHT_80MHZ_UTILIZATION_STAMAX 0 +#define WNI_CFG_VHT_80MHZ_UTILIZATION_STADEF 0 + +#define WNI_CFG_VHT_160MHZ_UTILIZATION_STAMIN 0 +#define WNI_CFG_VHT_160MHZ_UTILIZATION_STAMAX 0 +#define WNI_CFG_VHT_160MHZ_UTILIZATION_STADEF 0 + +#define WNI_CFG_MAX_AMSDU_LENGTH_STAMIN 0 +#define WNI_CFG_MAX_AMSDU_LENGTH_STAMAX 1 +#define WNI_CFG_MAX_AMSDU_LENGTH_STADEF 0 + +#define WNI_CFG_MAX_AMSDU_LENGTH_SHORT_3839_BYTES 0 +#define WNI_CFG_MAX_AMSDU_LENGTH_LONG_7935__BYTES 1 + +#define WNI_CFG_MPDU_DENSITY_STAMIN 0 +#define WNI_CFG_MPDU_DENSITY_STAMAX 7 +#define WNI_CFG_MPDU_DENSITY_STADEF 7 + +#define WNI_CFG_NUM_BUFF_ADVERT_STAMIN 0 +#define WNI_CFG_NUM_BUFF_ADVERT_STAMAX 128 +#define WNI_CFG_NUM_BUFF_ADVERT_STADEF 64 + +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMIN 0 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMAX 3 +#define WNI_CFG_MAX_RX_AMPDU_FACTOR_STADEF 3 + +#define WNI_CFG_SHORT_GI_20MHZ_STAMIN 0 +#define WNI_CFG_SHORT_GI_20MHZ_STAMAX 1 +#define WNI_CFG_SHORT_GI_20MHZ_STADEF 1 + +#define WNI_CFG_SHORT_GI_20MHZ_ENABLE 1 +#define WNI_CFG_SHORT_GI_20MHZ_DISABLE 0 + +#define WNI_CFG_SHORT_GI_40MHZ_STAMIN 0 +#define WNI_CFG_SHORT_GI_40MHZ_STAMAX 1 +#define WNI_CFG_SHORT_GI_40MHZ_STADEF 0 + +#define WNI_CFG_SHORT_GI_40MHZ_ENABLE 1 +#define WNI_CFG_SHORT_GI_40MHZ_DISABLE 0 + +#define WNI_CFG_RIFS_ENABLED_STAMIN 0 +#define WNI_CFG_RIFS_ENABLED_STAMAX 1 +#define WNI_CFG_RIFS_ENABLED_STADEF 1 + +#define WNI_CFG_RIFS_ENABLED_ENABLE 1 +#define WNI_CFG_RIFS_ENABLED_DISABLE 0 + +#define WNI_CFG_MAX_PS_POLL_STAMIN 0 +#define WNI_CFG_MAX_PS_POLL_STAMAX 255 +#define WNI_CFG_MAX_PS_POLL_STADEF 0 + +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMIN 1 +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX 20 +#define WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STADEF 20 + +#define WNI_CFG_RSSI_FILTER_PERIOD_STAMIN 0 +#define WNI_CFG_RSSI_FILTER_PERIOD_STAMAX 255 +#define WNI_CFG_RSSI_FILTER_PERIOD_STADEF 5 + +#define WNI_CFG_MIN_RSSI_THRESHOLD_STAMIN 0 +#define WNI_CFG_MIN_RSSI_THRESHOLD_STAMAX 10 +#define WNI_CFG_MIN_RSSI_THRESHOLD_STADEF 10 + +#define WNI_CFG_NTH_BEACON_FILTER_STAMIN 0 +#define WNI_CFG_NTH_BEACON_FILTER_STAMAX 255 +#define WNI_CFG_NTH_BEACON_FILTER_STADEF 10 + +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STAMIN 0 +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STAMAX 1 +#define WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STADEF 0 + +#define WNI_CFG_SCAN_IN_POWERSAVE_STAMIN 0 +#define WNI_CFG_SCAN_IN_POWERSAVE_STAMAX 1 +#define WNI_CFG_SCAN_IN_POWERSAVE_STADEF 1 + +#define WNI_CFG_IGNORE_DTIM_STAMIN 0 +#define WNI_CFG_IGNORE_DTIM_STAMAX 1 +#define WNI_CFG_IGNORE_DTIM_STADEF 0 + +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_DEAUTH_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE_STAMIN 0 +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE_STAMAX 1 +#define WNI_CFG_WOWLAN_DISASSOC_ENABLE_STADEF 1 + +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STAMIN 0 +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STAMAX 65535 +#define WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STADEF 40 + +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STAMIN 0 +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STAMAX 65535 +#define WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STADEF 65535 + +#define WNI_CFG_BA_TIMEOUT_STAMIN 0 +#define WNI_CFG_BA_TIMEOUT_STAMAX 65535 +#define WNI_CFG_BA_TIMEOUT_STADEF 0 + +#define WNI_CFG_BA_THRESHOLD_HIGH_STAMIN 0 +#define WNI_CFG_BA_THRESHOLD_HIGH_STAMAX 65535 +#define WNI_CFG_BA_THRESHOLD_HIGH_STADEF 128 + +#define WNI_CFG_MAX_BA_BUFFERS_STAMIN 0 +#define WNI_CFG_MAX_BA_BUFFERS_STAMAX 2560 +#define WNI_CFG_MAX_BA_BUFFERS_STADEF 2560 + +#define WNI_CFG_MAX_BA_SESSIONS_STAMIN 0 +#define WNI_CFG_MAX_BA_SESSIONS_STAMAX 64 +#define WNI_CFG_MAX_BA_SESSIONS_STADEF 40 + +#define WNI_CFG_BA_AUTO_SETUP_STAMIN 0 +#define WNI_CFG_BA_AUTO_SETUP_STAMAX 1 +#define WNI_CFG_BA_AUTO_SETUP_STADEF 1 + +#define WNI_CFG_BA_AUTO_SETUP_ENABLE 1 +#define WNI_CFG_BA_AUTO_SETUP_DISABLE 0 + +#define WNI_CFG_ADDBA_REQ_DECLINE_STAMIN 0 +#define WNI_CFG_ADDBA_REQ_DECLINE_STAMAX 255 +#define WNI_CFG_ADDBA_REQ_DECLINE_STADEF 0 + +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF 0 + +#define WNI_CFG_MAX_MEDIUM_TIME_STAMIN 0 +#define WNI_CFG_MAX_MEDIUM_TIME_STAMAX 65535 +#define WNI_CFG_MAX_MEDIUM_TIME_STADEF 2048 + +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_STAMIN 0 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_STAMAX 65535 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU_STADEF 64 + +#define WNI_CFG_IBSS_AUTO_BSSID_STAMIN 0 +#define WNI_CFG_IBSS_AUTO_BSSID_STAMAX 1 +#define WNI_CFG_IBSS_AUTO_BSSID_STADEF 1 + +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STADEF 0 + +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STAMIN 0 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STAMAX 1 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STADEF 0 + +#define WNI_CFG_WPS_ENABLE_STAMIN 0 +#define WNI_CFG_WPS_ENABLE_STAMAX 255 +#define WNI_CFG_WPS_ENABLE_STADEF 0 + +#define WNI_CFG_WPS_ENABLE_AP 1 +#define WNI_CFG_WPS_ENABLE_STA 2 + +#define WNI_CFG_WPS_STATE_STAMIN 0 +#define WNI_CFG_WPS_STATE_STAMAX 255 +#define WNI_CFG_WPS_STATE_STADEF 1 + +#define WNI_CFG_WPS_PROBE_REQ_FLAG_STAMIN 0 +#define WNI_CFG_WPS_PROBE_REQ_FLAG_STAMAX 1 +#define WNI_CFG_WPS_PROBE_REQ_FLAG_STADEF 0 + +#define WNI_CFG_WPS_VERSION_STAMIN 0 +#define WNI_CFG_WPS_VERSION_STAMAX 255 +#define WNI_CFG_WPS_VERSION_STADEF 16 + +#define WNI_CFG_WPS_REQUEST_TYPE_STAMIN 0 +#define WNI_CFG_WPS_REQUEST_TYPE_STAMAX 255 +#define WNI_CFG_WPS_REQUEST_TYPE_STADEF 0 + +#define WNI_CFG_WPS_CFG_METHOD_STAMIN 0 +#define WNI_CFG_WPS_CFG_METHOD_STAMAX 4294967295 +#define WNI_CFG_WPS_CFG_METHOD_STADEF 8 + +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STAMIN 0 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STAMAX 65535 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STADEF 1 + +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_STAMIN 0 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_STAMAX 4294967295 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI_STADEF 5304836 + +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STAMIN 0 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STAMAX 65535 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STADEF 1 + +#define WNI_CFG_WPS_ASSOCIATION_STATE_STAMIN 0 +#define WNI_CFG_WPS_ASSOCIATION_STATE_STAMAX 65535 +#define WNI_CFG_WPS_ASSOCIATION_STATE_STADEF 0 + +#define WNI_CFG_WPS_CONFIGURATION_ERROR_STAMIN 0 +#define WNI_CFG_WPS_CONFIGURATION_ERROR_STAMAX 65535 +#define WNI_CFG_WPS_CONFIGURATION_ERROR_STADEF 0 + +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_STAMIN 0 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_STAMAX 4294967295 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID_STADEF 0 + +#define WNI_CFG_WPS_ASSOC_METHOD_STAMIN 0 +#define WNI_CFG_WPS_ASSOC_METHOD_STAMAX 65535 +#define WNI_CFG_WPS_ASSOC_METHOD_STADEF 0 + +#define WNI_CFG_LOW_GAIN_OVERRIDE_STAMIN 0 +#define WNI_CFG_LOW_GAIN_OVERRIDE_STAMAX 1 +#define WNI_CFG_LOW_GAIN_OVERRIDE_STADEF 0 + +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STAMIN 0 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STAMAX 128 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STADEF 128 + +#define WNI_CFG_RPE_POLLING_THRESHOLD_STAMIN 0 +#define WNI_CFG_RPE_POLLING_THRESHOLD_STAMAX 65535 +#define WNI_CFG_RPE_POLLING_THRESHOLD_STADEF 10 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STADEF 30 + +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STAMIN 0 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STAMAX 65535 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STADEF 30 + +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STAMIN 0 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STAMAX 2 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STADEF 1 + +#define WNI_CFG_SINGLE_TID_RC_STAMIN 0 +#define WNI_CFG_SINGLE_TID_RC_STAMAX 1 +#define WNI_CFG_SINGLE_TID_RC_STADEF 1 + +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STAMIN 0 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STAMAX 1 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STADEF 1 + +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMIN 0 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMAX 3 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STADEF 0 + +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMIN 0 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMAX 255 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STADEF 0 + +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMIN 0 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMAX 255 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STADEF 0 + +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMIN 0 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMAX 80 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STADEF 0 + +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STAMIN 0 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STAMAX 1 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STADEF 0 + +#define WNI_CFG_TELE_BCN_TRANS_LI_STAMIN 0 +#define WNI_CFG_TELE_BCN_TRANS_LI_STAMAX 7 +#define WNI_CFG_TELE_BCN_TRANS_LI_STADEF 3 + +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMIN 5 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMAX 255 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STADEF 10 + +#define WNI_CFG_TELE_BCN_MAX_LI_STAMIN 0 +#define WNI_CFG_TELE_BCN_MAX_LI_STAMAX 7 +#define WNI_CFG_TELE_BCN_MAX_LI_STADEF 5 + +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMIN 5 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMAX 255 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STADEF 15 + +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMIN 0 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMAX 255 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STADEF 7 + +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMIN 0 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX 1000 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STADEF 0 + +#define WNI_CFG_ASSOC_STA_LIMIT_STAMIN 1 +#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX 32 +#define WNI_CFG_ASSOC_STA_LIMIT_STADEF 10 + +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STADEF 1 + +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STADEF 11 + +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMIN 0 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMAX 5 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STADEF 0 + +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMIN 0 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMAX 65535 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STADEF 5 + +#define WNI_CFG_ENABLE_CLOSE_LOOP_STAMIN 0 +#define WNI_CFG_ENABLE_CLOSE_LOOP_STAMAX 1 +#define WNI_CFG_ENABLE_CLOSE_LOOP_STADEF 0 + +#define WNI_CFG_ENABLE_LTE_COEX_STAMIN 0 +#define WNI_CFG_ENABLE_LTE_COEX_STAMAX 1 +#define WNI_CFG_ENABLE_LTE_COEX_STADEF 0 + +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMIN 1 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STADEF 20 + +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMIN 1 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STADEF 20 + +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STAMIN 0 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STAMAX 1 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STADEF 0 + +#define WNI_CFG_ENABLE_UC_FILTER_STAMIN 0 +#define WNI_CFG_ENABLE_UC_FILTER_STAMAX 1 +#define WNI_CFG_ENABLE_UC_FILTER_STADEF 0 + +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMIN 0 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMAX 1 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STADEF 0 + +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMIN 0 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX 1 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STADEF 0 + +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMIN 0 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMAX 1 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STADEF 0 + +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMIN 1 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMAX 255 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STADEF 3 + +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMIN 0 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMAX 15 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STADEF 0 + +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STADEF 0 + +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMIN 0 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMAX 10 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STADEF 0 + +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMIN 10 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMAX 20 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STADEF 10 + +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMIN 0 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMAX 20 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STADEF 5 + +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN 10 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMAX 2000 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF 200 + +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMIN 0 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMAX 1 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STADEF 1 + +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMIN 0 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMAX 9 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STADEF 0 + +#define WNI_CFG_ANTENNA_DIVESITY_STAMIN 0 +#define WNI_CFG_ANTENNA_DIVESITY_STAMAX 3 +#define WNI_CFG_ANTENNA_DIVESITY_STADEF 0 + +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMIN 3 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMAX 50 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STADEF 10 + +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN 100 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX 1000 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF 300 + +#define WNI_CFG_CURRENT_RSSI_STAMIN 0 +#define WNI_CFG_CURRENT_RSSI_STAMAX 127 +#define WNI_CFG_CURRENT_RSSI_STADEF 0 + +#define WNI_CFG_RTT3_ENABLE_STAMIN 0 +#define WNI_CFG_RTT3_ENABLE_STAMAX 1 +#define WNI_CFG_RTT3_ENABLE_STADEF 1 + +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMIN 0 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMAX 1 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STADEF 0 + +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STADEF 0 + +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMIN 0 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMAX 100 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STADEF 0 + +#define WNI_CFG_DFS_MASTER_ENABLED_STAMIN 0 +#define WNI_CFG_DFS_MASTER_ENABLED_STAMAX 1 +#define WNI_CFG_DFS_MASTER_ENABLED_STADEF 0 + +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMIN 0 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMAX 1 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STADEF 0 + +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF 0 + +#define CFG_PARAM_MAX_NUM 298 +#define CFG_STA_IBUF_MAX_SIZE 241 +#define CFG_STA_SBUF_MAX_SIZE 3199 +#define CFG_SEM_MAX_NUM 19 + +#define CFG_STA_MAGIC_DWORD 0xbeefbeef + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c new file mode 100644 index 000000000000..993974753b81 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c @@ -0,0 +1,1142 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file contains the source code for CFG API functions. + * + * Author: Kevin Nguyen + * Date: 04/09/02 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + */ + +#include "palTypes.h" +#include "cfgPriv.h" +#include "cfgDebug.h" +#include "wlan_qct_wda.h" + +//--------------------------------------------------------------------- +// Static Variables +//---------------------------------------------------------------------- +static tCfgCtl __gCfgEntry[CFG_PARAM_MAX_NUM] ; +static tANI_U32 __gCfgIBufMin[CFG_STA_IBUF_MAX_SIZE] ; +static tANI_U32 __gCfgIBufMax[CFG_STA_IBUF_MAX_SIZE] ; +static tANI_U32 __gCfgIBuf[CFG_STA_IBUF_MAX_SIZE] ; +static tANI_U8 __gCfgSBuf[CFG_STA_SBUF_MAX_SIZE] ; +static tANI_U8 __gSBuffer[CFG_MAX_STR_LEN] ; + +static void Notify(tpAniSirGlobal, tANI_U16, tANI_U32); + + +// --------------------------------------------------------------------- +tANI_U32 cfgNeedRestart(tpAniSirGlobal pMac, tANI_U16 cfgId) +{ + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } + return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RESTART) ; +} + +// --------------------------------------------------------------------- +tANI_U32 cfgNeedReload(tpAniSirGlobal pMac, tANI_U16 cfgId) +{ + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } + return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RELOAD) ; +} + +// --------------------------------------------------------------------- +/** + * wlan_cfgInit() + * + * FUNCTION: + * CFG initialization function. + * + * LOGIC: + * Please see Configuration & Statistic Collection Micro-Architecture + * specification for the pseudo code. + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * This function must be called during system initialization. + * + * @param None + * @return None. + */ + +void +wlan_cfgInit(tpAniSirGlobal pMac) +{ + // Set status to not-ready + pMac->cfg.gCfgStatus = CFG_INCOMPLETE; + + // Send CFG_DNLD_REQ to host + PELOGW(cfgLog(pMac, LOGW, FL("Sending CFG_DNLD_REQ"));) + cfgSendHostMsg(pMac, WNI_CFG_DNLD_REQ, WNI_CFG_DNLD_REQ_LEN, + WNI_CFG_DNLD_REQ_NUM, 0, 0, 0); + +} /*** end wlan_cfgInit() ***/ + +void cfg_get_str_index(tpAniSirGlobal mac_ctx, uint16_t cfg_id) +{ + uint16_t i = 0; + + for (i = 0; i < CFG_MAX_STATIC_STRING; i++) { + if (cfg_id == cfg_static_string[i].cfg_id) + break; + } + + if (i == CFG_MAX_STATIC_STRING) { + PELOGE(cfgLog(mac_ctx, LOGE, + FL("Entry not found for cfg id :%d"), cfg_id);) + cfg_static[cfg_id].p_str_data = NULL; + return; + } + + cfg_static[cfg_id].p_str_data = &cfg_static_string[i]; +} + + +//--------------------------------------------------------------------- +tSirRetStatus cfgInit(tpAniSirGlobal pMac) +{ + uint16_t i = 0; + pMac->cfg.gCfgIBufMin = __gCfgIBufMin; + pMac->cfg.gCfgIBufMax = __gCfgIBufMax; + pMac->cfg.gCfgIBuf = __gCfgIBuf; + pMac->cfg.gCfgSBuf = __gCfgSBuf; + pMac->cfg.gSBuffer = __gSBuffer; + pMac->cfg.gCfgEntry = __gCfgEntry; + + for (i = 0; i < CFG_PARAM_MAX_NUM; i++) { + if (!(cfg_static[i].control & CFG_CTL_INT)) + cfg_get_str_index(pMac, i); + else + cfg_static[i].p_str_data = NULL; + } + + return (eSIR_SUCCESS); +} + +//---------------------------------------------------------------------- +void cfgDeInit(tpAniSirGlobal pMac) +{ + pMac->cfg.gCfgIBufMin = NULL; + pMac->cfg.gCfgIBufMax = NULL; + pMac->cfg.gCfgIBuf = NULL; + pMac->cfg.gCfgSBuf = NULL; + pMac->cfg.gSBuffer = NULL; + pMac->cfg.gCfgEntry = NULL; +} + +// --------------------------------------------------------------------- +/** + * cfgSetInt() + * + * FUNCTION: + * This function is called to update an integer parameter. + * + * LOGIC: + * + * ASSUMPTIONS: + * - Range checking is performed by the calling function. In case this + * function call is being triggered by a request from host, then host + * is responsible for performing range checking before sending the + * request. + * + * - Host RW permission checking should already be done prior to calling + * this function by the message processing function. + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param value: 32-bit unsigned value + * + * @return eSIR_SUCCESS : request completed successfully \n + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID \n + */ + +tSirRetStatus +cfgSetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 value) +{ + tANI_U32 index; + tANI_U32 control, mask; + tSirRetStatus retVal; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + return eSIR_CFG_INVALID_ID; + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + index = control & CFG_BUF_INDX_MASK; + retVal = eSIR_SUCCESS; + + if (index >= CFG_STA_IBUF_MAX_SIZE) + { + PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else if ((pMac->cfg.gCfgIBufMin[index] > value) || + (pMac->cfg.gCfgIBufMax[index] < value)) + { + PELOGE(cfgLog(pMac, LOGE, FL("Value %d out of range [%d,%d] cfg id %d"), + value, pMac->cfg.gCfgIBufMin[index], + pMac->cfg.gCfgIBufMax[index], cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else + { + // Write integer value + pMac->cfg.gCfgIBuf[index] = value; + + // Update hardware if necessary + mask = control & CFG_CTL_NTF_MASK; + if ((mask & CFG_CTL_NTF_HW) != 0) + PELOGE(cfgLog(pMac, LOGE, FL("CFG Notify HW not supported!!!"));) + + // Notify other modules if necessary + if ((mask & CFG_CTL_NTF_MASK) != 0) + Notify(pMac, cfgId, mask); + + } + + return (retVal); + +} /*** end cfgSetInt ***/ + +// --------------------------------------------------------------------- +/** + * cfgCheckValid() + * + * FUNCTION: + * This function is called to check if a parameter is valid + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + */ + +tSirRetStatus +cfgCheckValid(tpAniSirGlobal pMac, tANI_U16 cfgId) +{ + tANI_U32 control; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOG3(cfgLog(pMac, LOG3, FL("Invalid cfg id %d"), cfgId);) + return(eSIR_CFG_INVALID_ID); + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOG3(cfgLog(pMac, LOG3, FL("Not valid cfg id %d"), cfgId);) + return(eSIR_CFG_INVALID_ID); + } + else + return(eSIR_SUCCESS); + +} /*** end cfgCheckValid() ***/ + +// --------------------------------------------------------------------- +/** + * wlan_cfgGetInt() + * + * FUNCTION: + * This function is called to read an integer parameter. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param pVal: address where parameter value will be written + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + */ + +tSirRetStatus +wlan_cfgGetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pValue) +{ + tANI_U32 index; + tANI_U32 control; + tSirRetStatus retVal; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + index = control & CFG_BUF_INDX_MASK; + retVal = eSIR_SUCCESS; + + if (index >= CFG_STA_IBUF_MAX_SIZE) + { + PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else { + // Get integer value + if (index < CFG_STA_IBUF_MAX_SIZE) + *pValue = pMac->cfg.gCfgIBuf[index]; + } + + return (retVal); + +} /*** end wlan_cfgGetInt() ***/ + +// --------------------------------------------------------------------- +/** + * cfgSetStr() + * + * FUNCTION: + * This function is called to set a string parameter. + * + * LOGIC: + * This function invokes the cfgSetStrNotify function passing the notify + * boolean value set to TRUE. This basically means that HAL needs to be + * notified. This is true in the case of non-integrated SOC's or Libra/Volans. + * In the case of Prima the cfgSetStrNotify is invoked with the boolean value + * set to FALSE. + * + * ASSUMPTIONS: + * - always Notify has to be called + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param pStr: address of string data + * @param len: string length + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + * @return eSIR_CFG_INVALID_LEN: invalid parameter length + * + */ + +tSirRetStatus cfgSetStr(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pStr, + tANI_U32 length) +{ + return cfgSetStrNotify( pMac, cfgId, pStr, length, TRUE ); +} + +// --------------------------------------------------------------------- +/** + * cfgSetStrNotify() + * + * FUNCTION: + * This function is called to set a string parameter. + * + * LOGIC: + * + * ASSUMPTIONS: + * - No length checking will be performed. Should be done by calling + * module. + * - Host RW permission should be checked prior to calling this + * function. + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param pStr: address of string data + * @param len: string length + * @param notifyMod. Notify respective Module + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + * @return eSIR_CFG_INVALID_LEN: invalid parameter length + * + */ + +tSirRetStatus +cfgSetStrNotify(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pStr, + tANI_U32 length, int notifyMod) +{ + tANI_U8 *pDst, *pDstEnd; + tANI_U32 index, paramLen, control, mask; + tSirRetStatus retVal; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + return eSIR_CFG_INVALID_ID; + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + index = control & CFG_BUF_INDX_MASK; + retVal = eSIR_SUCCESS; + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else if (index >= CFG_STA_SBUF_MAX_SIZE) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid Sbuf index %d (max size %d)"), + index, CFG_STA_SBUF_MAX_SIZE);) + retVal = eSIR_CFG_INVALID_ID; + } + else + { + pDst = &pMac->cfg.gCfgSBuf[index]; + paramLen = *pDst++; + if (length > paramLen) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid length %d (>%d) cfg id %d"), + length, paramLen, cfgId);) + retVal = eSIR_CFG_INVALID_LEN; + } + else + { + *pDst++ = (tANI_U8)length; + pDstEnd = pDst + length; + while (pDst < pDstEnd) + { + *pDst++ = *pStr++; + } + + if(notifyMod) + { + // Update hardware if necessary + mask = control & CFG_CTL_NTF_MASK; + if ((mask & CFG_CTL_NTF_HW) != 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("CFG Notify HW not supported!!!"));) + } + + // Notify other modules if necessary + if ( (mask & CFG_CTL_NTF_MASK) != 0) + { + Notify(pMac, cfgId, mask); + } + } + } + + } + + return (retVal); + +} /*** end cfgSetStrNotify() ***/ + +// --------------------------------------------------------------------- +/** + * wlan_cfgGetStr() + * + * FUNCTION: + * This function is called to get a string parameter. + * + * LOGIC: + * + * ASSUMPTIONS: + * - Host RW permission should be checked prior to calling this + * function. + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param pBuf: address of string buffer + * @param pLen: address of max buffer length + * actual length will be returned at this address + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + * @return eSIR_CFG_INVALID_LEN: invalid parameter length + * + */ + +tSirRetStatus +wlan_cfgGetStr(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pBuf, tANI_U32 *pLength) +{ + tANI_U8 *pSrc, *pSrcEnd; + tANI_U32 index, control; + tSirRetStatus retVal; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + index = control & CFG_BUF_INDX_MASK; + retVal = eSIR_SUCCESS; + + if (index >= CFG_STA_SBUF_MAX_SIZE) + { + PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else + { + // Get string + pSrc = &pMac->cfg.gCfgSBuf[index]; + pSrc++; // skip over max length + if (*pLength < *pSrc) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid length %d (<%d) cfg id %d"), + *pLength, *pSrc, cfgId);) + retVal = eSIR_CFG_INVALID_LEN; + } + else + { + *pLength = *pSrc++; // save parameter length + pSrcEnd = pSrc + *pLength; + while (pSrc < pSrcEnd) + *pBuf++ = *pSrc++; + } + } + + return (retVal); + +} /*** end wlan_cfgGetStr() ***/ + +// --------------------------------------------------------------------- +/** + * wlan_cfgGetStrMaxLen() + * + * FUNCTION: + * This function is called to get a string maximum length. + * + * LOGIC: + * + * ASSUMPTIONS: + * - Host RW permission should be checked prior to calling this + * function. + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param pLen: maximum length will be returned at this address + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + * + */ + +tSirRetStatus +wlan_cfgGetStrMaxLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) +{ + tANI_U32 index, control; + tSirRetStatus retVal; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + index = control & CFG_BUF_INDX_MASK; + retVal = eSIR_SUCCESS; + + if (index >= CFG_STA_SBUF_MAX_SIZE) + { + PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else + { + *pLength = pMac->cfg.gCfgSBuf[index]; + } + + return (retVal); + +} /*** end wlan_cfgGetStrMaxLen() ***/ + +// --------------------------------------------------------------------- +/** + * wlan_cfgGetStrLen() + * + * FUNCTION: + * This function is called to get a string length. + * + * LOGIC: + * + * ASSUMPTIONS: + * - Host RW permission should be checked prior to calling this + * function. + * + * NOTE: + * + * @param cfgId: 16-bit CFG parameter ID + * @param pLen: current length will be returned at this address + * + * @return eSIR_SUCCESS: request completed successfully + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + * + */ + +tSirRetStatus +wlan_cfgGetStrLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) +{ + tANI_U32 index, control; + tSirRetStatus retVal; + + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + + control = pMac->cfg.gCfgEntry[cfgId].control; + index = control & CFG_BUF_INDX_MASK; + retVal = eSIR_SUCCESS; + + if (index >= CFG_STA_SBUF_MAX_SIZE-1) + { + PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) + retVal = eSIR_CFG_INVALID_ID; + return retVal; + } + + // Check if parameter is valid + if ((control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) + retVal = eSIR_CFG_INVALID_ID; + } + else + { + *pLength = pMac->cfg.gCfgSBuf[index+1]; + } + + return (retVal); + +} /*** end wlan_cfgGetStrLen() ***/ + + + +/*------------------------------------------------------------- +\fn cfgGetDot11dTransmitPower +\brief This function returns the regulatory max transmit power +\param pMac +\return tPowerdBm - Power +\-------------------------------------------------------------*/ +static tPowerdBm +cfgGetDot11dTransmitPower(tpAniSirGlobal pMac, tANI_U16 cfgId, + tANI_U32 cfgLength, tANI_U8 channel) +{ + tANI_U8 *pCountryInfo = NULL; + tANI_U8 count = 0; + tPowerdBm maxTxPwr = WDA_MAX_TXPOWER_INVALID; + + /* At least one element is present */ + if(cfgLength < sizeof(tSirMacChanInfo)) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid CFGLENGTH %d while getting 11d txpower"), cfgLength);) + goto error; + } + + pCountryInfo = vos_mem_malloc(cfgLength); + if ( NULL == pCountryInfo ) + { + cfgLog(pMac, LOGP, FL(" failed to allocate memory")); + goto error; + } + /* The CSR will always update this CFG. The contents will be from country IE if regulatory domain + * is enabled on AP else will contain EEPROM contents + */ + if (wlan_cfgGetStr(pMac, cfgId, pCountryInfo, &cfgLength) != eSIR_SUCCESS) + { + vos_mem_free(pCountryInfo); + pCountryInfo = NULL; + + cfgLog(pMac, LOGP, FL("Failed to retrieve 11d configuration parameters while retrieving 11d tuples")); + goto error; + } + /* Identify the channel and max txpower */ + while(count <= (cfgLength - (sizeof(tSirMacChanInfo)))) + { + tANI_U8 firstChannel, maxChannels; + + firstChannel = pCountryInfo[count++]; + maxChannels = pCountryInfo[count++]; + maxTxPwr = pCountryInfo[count++]; + + if((channel >= firstChannel) && + (channel < (firstChannel + maxChannels))) + { + break; + } + } + +error: + if (NULL != pCountryInfo) + vos_mem_free(pCountryInfo); + + return maxTxPwr; +} + + +/**---------------------------------------------------------------------- +\fn cfgGetRegulatoryMaxTransmitPower + +\brief Gets regulatory tx power on the current channel. + +\param pMac +\param channel +\param rfBand + -----------------------------------------------------------------------*/ +tPowerdBm cfgGetRegulatoryMaxTransmitPower(tpAniSirGlobal pMac, tANI_U8 channel) +{ + tANI_U32 cfgLength = 0; + tANI_U16 cfgId = 0; + tPowerdBm maxTxPwr; + eRfBandMode rfBand = eRF_BAND_UNKNOWN; + + if ((channel >= SIR_11A_CHANNEL_BEGIN) && + (channel <= SIR_11A_CHANNEL_END)) + rfBand = eRF_BAND_5_GHZ; + else + rfBand = eRF_BAND_2_4_GHZ; + + + /* Get the max transmit power for current channel for the current regulatory domain */ + switch (rfBand) + { + case eRF_BAND_2_4_GHZ: + cfgId = WNI_CFG_MAX_TX_POWER_2_4; + cfgLength = WNI_CFG_MAX_TX_POWER_2_4_LEN; + PELOG2(cfgLog(pMac, LOG2, FL("HAL: Reading CFG for 2.4 GHz channels to get regulatory max tx power"));) + break; + + case eRF_BAND_5_GHZ: + cfgId = WNI_CFG_MAX_TX_POWER_5; + cfgLength = WNI_CFG_MAX_TX_POWER_5_LEN; + PELOG2(cfgLog(pMac, LOG2, FL("HAL: Reading CFG for 5.0 GHz channels to get regulatory max tx power"));) + break; + + case eRF_BAND_UNKNOWN: + default: + PELOG2(cfgLog(pMac, LOG2, FL("HAL: Invalid current working band for the device"));) + return WDA_MAX_TXPOWER_INVALID; //Its return, not break. + } + + maxTxPwr = cfgGetDot11dTransmitPower(pMac, cfgId, cfgLength, channel); + + return (maxTxPwr); +} + +// --------------------------------------------------------------------- +/** + * cfgGetCapabilityInfo + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +tSirRetStatus +cfgGetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 *pCap,tpPESession sessionEntry) +{ + tANI_U32 val = 0; + tpSirMacCapabilityInfo pCapInfo; + + *pCap = 0; + pCapInfo = (tpSirMacCapabilityInfo) pCap; + + if (LIM_IS_IBSS_ROLE(sessionEntry)) + pCapInfo->ibss = 1; // IBSS bit + else if (LIM_IS_AP_ROLE(sessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(sessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(sessionEntry) || + LIM_IS_STA_ROLE(sessionEntry)) + pCapInfo->ess = 1; // ESS bit + else if (LIM_IS_P2P_DEVICE_ROLE(sessionEntry)) { + pCapInfo->ess = 0; + pCapInfo->ibss = 0; + } + else + cfgLog(pMac, LOGP, FL("can't get capability, role is UNKNOWN!!")); + + + if (LIM_IS_AP_ROLE(sessionEntry)) { + val = sessionEntry->privacy; +#ifdef SAP_AUTH_OFFLOAD + /* Support software AP Authentication Offload feature, + * If Auth offload security Type is not disabled + * We need to enable privacy bit in beacon + */ + if (pMac->sap_auth_offload && pMac->sap_auth_offload_sec_type) { + val = 1; + } +#endif + } else { + // PRIVACY bit + if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_PRIVACY_ENABLED failed")); + return eSIR_FAILURE; + } + } + if (val) + pCapInfo->privacy = 1; + + // Short preamble bit + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_SHORT_PREAMBLE failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->shortPreamble = 1; + + + // PBCC bit + pCapInfo->pbcc = 0; + + // Channel agility bit + pCapInfo->channelAgility = 0; + //If STA/AP operating in 11B mode, don't set rest of the capability info bits. + if(sessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) + return eSIR_SUCCESS; + + // Short slot time bit + if (LIM_IS_AP_ROLE(sessionEntry)) { + pCapInfo->shortSlotTime = sessionEntry->shortSlotTimeSupported; + } else { + if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val) + != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, + FL("cfg get WNI_CFG_11G_SHORT_SLOT_TIME failed")); + return eSIR_FAILURE; + } + /* When in STA mode, we need to check if short slot is enabled as well as check if the current operating + * mode is short slot time and then decide whether to enable short slot or not. It is safe to check both + * cfg values to determine short slot value in this funcn since this funcn is always used after assoc when + * these cfg values are already set based on peer's capability. Even in case of IBSS, its value is set to + * correct value either in delBSS as part of deleting the previous IBSS or in start BSS as part of coalescing + */ + if (val) + { + pCapInfo->shortSlotTime = sessionEntry->shortSlotTimeSupported; + } + } + + // Spectrum Management bit + if (!LIM_IS_IBSS_ROLE(sessionEntry) && sessionEntry->lim11hEnable) { + if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_11H_ENABLED failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->spectrumMgt = 1; + } + + // QoS bit + if (wlan_cfgGetInt(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_QOS_ENABLED failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->qos = 1; + + // APSD bit + if (wlan_cfgGetInt(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_APSD_ENABLED failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->apsd = 1; + +#if defined WLAN_FEATURE_VOWIFI + pCapInfo->rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; +#if defined WLAN_VOWIFI_DEBUG + cfgLog( pMac, LOGE, "RRM = %d", pCapInfo->rrm); +#endif +#endif + + //DSSS-OFDM + //FIXME : no config defined yet. + + // Block ack bit + if (wlan_cfgGetInt(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != eSIR_SUCCESS) + { + cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_BLOCK_ACK_ENABLED failed")); + return eSIR_FAILURE; + } + pCapInfo->delayedBA = (tANI_U16)((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); + pCapInfo->immediateBA = (tANI_U16)((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); + + return eSIR_SUCCESS; +} + +// -------------------------------------------------------------------- +/** + * cfgSetCapabilityInfo + * + * FUNCTION: + * This function is called on BP based on the capabilities + * received in SME_JOIN/REASSOC_REQ message. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: 1. ESS/IBSS capabilities are based on system role. + * 2. Since PBCC, Channel agility and Extended capabilities + * are not supported, they're not set at CFG + * + * @param pMac Pointer to global MAC structure + * @param caps 16-bit Capability Info field + * @return None + */ + +void +cfgSetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 caps) +{ +} + + +// --------------------------------------------------------------------- +/** + * cfgCleanup() + * + * FUNCTION: + * CFG clean up function. + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * This function must be called during system shut down. + * + * @param None + * + * @return None. + * + */ + +void +cfgCleanup(tpAniSirGlobal pMac) +{ + // Set status to not-ready + pMac->cfg.gCfgStatus = CFG_INCOMPLETE; + +} /*** end CfgCleanup() ***/ + +// --------------------------------------------------------------------- +/** + * Notify() + * + * FUNCTION: + * This function is called to notify other modules of parameter update. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param cfgId: configuration parameter ID + * @param mask: notification mask + * + * @return None. + * + */ + +static void +Notify(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 ntfMask) +{ + + tSirMsgQ mmhMsg; + + mmhMsg.type = SIR_CFG_PARAM_UPDATE_IND; + mmhMsg.bodyval = (tANI_U32)cfgId; + mmhMsg.bodyptr = NULL; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + + if ((ntfMask & CFG_CTL_NTF_SCH) != 0) + schPostMessage(pMac, &mmhMsg); + + if ((ntfMask & CFG_CTL_NTF_LIM) != 0) + limPostMsgApi(pMac, &mmhMsg); + + if ((ntfMask & CFG_CTL_NTF_HAL) != 0) + wdaPostCtrlMsg(pMac, &mmhMsg); + + // Notify ARQ + +} /*** end Notify() ***/ + +/** + * cfg_get_vendor_ie_ptr_from_oui() - returns IE pointer in IE buffer given its + * OUI and OUI size + * @mac_ctx: mac context. + * @oui: OUI string. + * @oui_size: length of OUI string + * One can provide multiple line descriptions + * for arguments. + * @ie: ie buffer + * @ie_len: length of ie buffer + * + * This function parses the IE buffer and finds the given OUI and returns its + * pointer + * + * Return: pointer of given OUI IE else NULL + */ +uint8_t* cfg_get_vendor_ie_ptr_from_oui(tpAniSirGlobal mac_ctx, + uint8_t *oui, + uint8_t oui_size, + uint8_t *ie, + uint16_t ie_len) +{ + int32_t left = ie_len; + uint8_t *ptr = ie; + uint8_t elem_id, elem_len; + + while(left >= 2) { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) { + cfgLog(mac_ctx, LOGE, + FL("Invalid IEs eid = %d elem_len=%d left=%d"), + elem_id, elem_len, left); + return NULL; + } + if (SIR_MAC_EID_VENDOR == elem_id) { + if(memcmp(&ptr[2], oui, oui_size)==0) + return ptr; + } + + left -= elem_len; + ptr += (elem_len + 2); + } + return NULL; +} +// --------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.c new file mode 100644 index 000000000000..7778a54d460a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file cfgDebug.c + + \brief implementation for log Debug related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +#include "cfgDebug.h" + +void cfgLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) +{ +#ifdef WLAN_DEBUG + // Verify against current log level + if (loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_CFG_MODULE_ID )]) + return; + else + { + va_list marker; + + va_start( marker, pString ); /* Initialize variable arguments. */ + + logDebug(pMac, SIR_CFG_MODULE_ID, loglevel, pString, marker); + + va_end( marker ); /* Reset variable arguments. */ + } +#endif +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.h new file mode 100644 index 000000000000..26c44e9a6a6d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDebug.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Kevin Nguyen + * Date: 04/09/02 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + */ + +#ifndef __CFG_DEBUG_H__ +#define __CFG_DEBUG_H__ + +#include "sirDebug.h" +#include "utilsApi.h" +#include "limTrace.h" + +#if !defined(__printf) +#define __printf(a,b) +#endif + +void __printf(3,4) cfgLog(tpAniSirGlobal pMac, tANI_U32 loglevel, + const char *pString, ...); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDef.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDef.h new file mode 100644 index 000000000000..0be77c6e9f63 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgDef.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This is the private header file for CFG module. + * + * Author: Kevin Nguyen + * Date: 03/20/02 + * History:- + * 03/20/02 Created. + * -------------------------------------------------------------------- + * + */ + +#ifndef __CFGDEF_H +#define __CFGDEF_H + +/* + * CFG Control Flag definitions + */ +#define CFG_CTL_VALID 0x00010000 +#define CFG_CTL_RE 0x00020000 +#define CFG_CTL_WE 0x00040000 +#define CFG_CTL_INT 0x00080000 +#define CFG_CTL_SAVE 0x00100000 +#define CFG_CTL_RESTART 0x00200000 +#define CFG_CTL_RELOAD 0x00400000 +#define CFG_CTL_NTF_PHY 0x00800000 +#define CFG_CTL_NTF_MAC 0x01000000 +#define CFG_CTL_NTF_LOG 0x02000000 +#define CFG_CTL_NTF_HAL 0x04000000 +#define CFG_CTL_NTF_DPH 0x08000000 +#define CFG_CTL_NTF_ARQ 0x10000000 +#define CFG_CTL_NTF_SCH 0x20000000 +#define CFG_CTL_NTF_LIM 0x40000000 +#define CFG_CTL_NTF_HDD 0x80000000 +#define CFG_CTL_NTF_MASK 0xFFE00000 + +#define CFG_CTL_NTF_TFP CFG_CTL_NTF_MAC +#define CFG_CTL_NTF_RHP CFG_CTL_NTF_MAC +#define CFG_CTL_NTF_RFP CFG_CTL_NTF_MAC +#define CFG_CTL_NTF_SP CFG_CTL_NTF_MAC +#define CFG_CTL_NTF_HW (CFG_CTL_NTF_MAC | CFG_CTL_NTF_PHY) + +#define CFG_BUF_INDX_MASK 0x00000fff +#define CFG_SEM_INDX_MASK 0x0000f000 +#define CFG_SEM_INDX_SHIFT 12 + + +#endif /* __CFGDEF_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgParamName.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgParamName.c new file mode 100644 index 000000000000..fc2ebae7634d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgParamName.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * DO NOT EDIT - This file is generated automatically + */ + +/* + * IMPORTANT: This file is for system that supports STA mode ONLY. + */ +#include "cfgPriv.h" + +unsigned char *gCfgParamName[] = { + (unsigned char *)"STA_ID", + (unsigned char *)"CF_POLLABLE", + (unsigned char *)"CFP_PERIOD", + (unsigned char *)"CFP_MAX_DURATION", + (unsigned char *)"SSID", + (unsigned char *)"BEACON_INTERVAL", + (unsigned char *)"DTIM_PERIOD", + (unsigned char *)"WEP_KEY_LENGTH", + (unsigned char *)"WEP_DEFAULT_KEY_1", + (unsigned char *)"WEP_DEFAULT_KEY_2", + (unsigned char *)"WEP_DEFAULT_KEY_3", + (unsigned char *)"WEP_DEFAULT_KEY_4", + (unsigned char *)"WEP_DEFAULT_KEYID", + (unsigned char *)"EXCLUDE_UNENCRYPTED", + (unsigned char *)"RTS_THRESHOLD", + (unsigned char *)"SHORT_RETRY_LIMIT", + (unsigned char *)"LONG_RETRY_LIMIT", + (unsigned char *)"FRAGMENTATION_THRESHOLD", + (unsigned char *)"ACTIVE_MINIMUM_CHANNEL_TIME", + (unsigned char *)"ACTIVE_MAXIMUM_CHANNEL_TIME", + (unsigned char *)"PASSIVE_MINIMUM_CHANNEL_TIME", + (unsigned char *)"PASSIVE_MAXIMUM_CHANNEL_TIME", + (unsigned char *)"JOIN_FAILURE_TIMEOUT", + (unsigned char *)"AUTHENTICATE_FAILURE_TIMEOUT", + (unsigned char *)"AUTHENTICATE_RSP_TIMEOUT", + (unsigned char *)"ASSOCIATION_FAILURE_TIMEOUT", + (unsigned char *)"REASSOCIATION_FAILURE_TIMEOUT", + (unsigned char *)"RA_PERIODICITY_TIMEOUT_IN_PS", + (unsigned char *)"PS_ENABLE_BCN_FILTER", + (unsigned char *)"PS_ENABLE_HEART_BEAT", + (unsigned char *)"PS_ENABLE_RSSI_MONITOR", + (unsigned char *)"PS_DATA_INACTIVITY_TIMEOUT", + (unsigned char *)"RF_SETTLING_TIME_CLK", + (unsigned char *)"SUPPORTED_RATES_11B", + (unsigned char *)"SUPPORTED_RATES_11A", + (unsigned char *)"PHY_MODE", + (unsigned char *)"DOT11_MODE", + (unsigned char *)"OPERATIONAL_RATE_SET", + (unsigned char *)"EXTENDED_OPERATIONAL_RATE_SET", + (unsigned char *)"PROPRIETARY_OPERATIONAL_RATE_SET", + (unsigned char *)"LISTEN_INTERVAL", + (unsigned char *)"VALID_CHANNEL_LIST", + (unsigned char *)"CURRENT_CHANNEL", + (unsigned char *)"DEFAULT_RATE_INDEX_5GHZ", + (unsigned char *)"DEFAULT_RATE_INDEX_24GHZ", + (unsigned char *)"RATE_ADAPTATION_TYPE", + (unsigned char *)"FIXED_RATE", + (unsigned char *)"FIXED_RATE_MULTICAST_24GHZ", + (unsigned char *)"FIXED_RATE_MULTICAST_5GHZ", + (unsigned char *)"RETRYRATE_POLICY", + (unsigned char *)"RETRYRATE_SECONDARY", + (unsigned char *)"RETRYRATE_TERTIARY", + (unsigned char *)"APSD_ENABLED", + (unsigned char *)"SHARED_KEY_AUTH_ENABLE", + (unsigned char *)"OPEN_SYSTEM_AUTH_ENABLE", + (unsigned char *)"AUTHENTICATION_TYPE", + (unsigned char *)"CF_POLL_REQUEST", + (unsigned char *)"PRIVACY_ENABLED", + (unsigned char *)"SHORT_PREAMBLE", + (unsigned char *)"SHORT_SLOT_TIME", + (unsigned char *)"ACCEPT_SHORT_SLOT_ASSOC_ONLY", + (unsigned char *)"QOS_ENABLED", + (unsigned char *)"HCF_ENABLED", + (unsigned char *)"RSN_ENABLED", + (unsigned char *)"BACKGROUND_SCAN_PERIOD", + (unsigned char *)"MAX_NUM_PRE_AUTH", + (unsigned char *)"PREAUTH_CLNUP_TIMEOUT", + (unsigned char *)"RELEASE_AID_TIMEOUT", + (unsigned char *)"HEART_BEAT_THRESHOLD", + (unsigned char *)"PROBE_AFTER_HB_FAIL_TIMEOUT", + (unsigned char *)"MANUFACTURER_OUI", + (unsigned char *)"MANUFACTURER_NAME", + (unsigned char *)"MODEL_NUMBER", + (unsigned char *)"MODEL_NAME", + (unsigned char *)"MANUFACTURER_PRODUCT_NAME", + (unsigned char *)"MANUFACTURER_PRODUCT_VERSION", + (unsigned char *)"11D_ENABLED", + (unsigned char *)"MAX_TX_POWER_2_4", + (unsigned char *)"MAX_TX_POWER_5", + (unsigned char *)"NETWORK_DENSITY", + (unsigned char *)"ADAPTIVE_THRESHOLD_ALGORITHM", + (unsigned char *)"CURRENT_TX_ANTENNA", + (unsigned char *)"CURRENT_RX_ANTENNA", + (unsigned char *)"CURRENT_TX_POWER_LEVEL", + (unsigned char *)"NEW_BSS_FOUND_IND", + (unsigned char *)"PROPRIETARY_RATES_ENABLED", + (unsigned char *)"AP_NODE_NAME", + (unsigned char *)"COUNTRY_CODE", + (unsigned char *)"11H_ENABLED", + (unsigned char *)"WT_CNF_TIMEOUT", + (unsigned char *)"KEEPALIVE_TIMEOUT", + (unsigned char *)"PROXIMITY", + (unsigned char *)"LOG_LEVEL", + (unsigned char *)"OLBC_DETECT_TIMEOUT", + (unsigned char *)"PROTECTION_ENABLED", + (unsigned char *)"11G_PROTECTION_ALWAYS", + (unsigned char *)"FORCE_POLICY_PROTECTION", + (unsigned char *)"11G_SHORT_PREAMBLE_ENABLED", + (unsigned char *)"11G_SHORT_SLOT_TIME_ENABLED", + (unsigned char *)"11G_ONLY_POLICY", + (unsigned char *)"PACKET_CLASSIFICATION", + (unsigned char *)"WME_ENABLED", + (unsigned char *)"ADDTS_RSP_TIMEOUT", + (unsigned char *)"MAX_SP_LENGTH", + (unsigned char *)"KEEP_ALIVE_STA_LIMIT_THRESHOLD", + (unsigned char *)"SEND_SINGLE_SSID_ALWAYS", + (unsigned char *)"WSM_ENABLED", + (unsigned char *)"EDCA_PROFILE", + (unsigned char *)"EDCA_ANI_ACBK_LOCAL", + (unsigned char *)"EDCA_ANI_ACBE_LOCAL", + (unsigned char *)"EDCA_ANI_ACVI_LOCAL", + (unsigned char *)"EDCA_ANI_ACVO_LOCAL", + (unsigned char *)"EDCA_ANI_ACBK", + (unsigned char *)"EDCA_ANI_ACBE", + (unsigned char *)"EDCA_ANI_ACVI", + (unsigned char *)"EDCA_ANI_ACVO", + (unsigned char *)"EDCA_WME_ACBK_LOCAL", + (unsigned char *)"EDCA_WME_ACBE_LOCAL", + (unsigned char *)"EDCA_WME_ACVI_LOCAL", + (unsigned char *)"EDCA_WME_ACVO_LOCAL", + (unsigned char *)"EDCA_WME_ACBK", + (unsigned char *)"EDCA_WME_ACBE", + (unsigned char *)"EDCA_WME_ACVI", + (unsigned char *)"EDCA_WME_ACVO", + (unsigned char *)"RDET_FLAG", + (unsigned char *)"RADAR_CHANNEL_LIST", + (unsigned char *)"LOCAL_POWER_CONSTRAINT", + (unsigned char *)"ADMIT_POLICY", + (unsigned char *)"ADMIT_BWFACTOR", + (unsigned char *)"MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE", + (unsigned char *)"CHANNEL_BONDING_MODE", + (unsigned char *)"CB_SECONDARY_CHANNEL_STATE", + (unsigned char *)"DYNAMIC_THRESHOLD_ZERO", + (unsigned char *)"DYNAMIC_THRESHOLD_ONE", + (unsigned char *)"DYNAMIC_THRESHOLD_TWO", + (unsigned char *)"TRIG_STA_BK_SCAN", + (unsigned char *)"DYNAMIC_PROFILE_SWITCHING", + (unsigned char *)"SCAN_CONTROL_LIST", + (unsigned char *)"MIMO_ENABLED", + (unsigned char *)"BLOCK_ACK_ENABLED", + (unsigned char *)"BA_ACTIVITY_CHECK_TIMEOUT", + (unsigned char *)"HT_RX_STBC", + (unsigned char *)"HT_CAP_INFO", + (unsigned char *)"HT_AMPDU_PARAMS", + (unsigned char *)"SUPPORTED_MCS_SET", + (unsigned char *)"EXT_HT_CAP_INFO", + (unsigned char *)"TX_BF_CAP", + (unsigned char *)"AS_CAP", + (unsigned char *)"HT_INFO_FIELD1", + (unsigned char *)"HT_INFO_FIELD2", + (unsigned char *)"HT_INFO_FIELD3", + (unsigned char *)"BASIC_MCS_SET", + (unsigned char *)"CURRENT_MCS_SET", + (unsigned char *)"GREENFIELD_CAPABILITY", + (unsigned char *)"VHT_MAX_MPDU_LENGTH", + (unsigned char *)"VHT_SUPPORTED_CHAN_WIDTH_SET", + (unsigned char *)"VHT_LDPC_CODING_CAP", + (unsigned char *)"VHT_SHORT_GI_80MHZ", + (unsigned char *)"VHT_SHORT_GI_160_AND_80_PLUS_80MHZ", + (unsigned char *)"VHT_TXSTBC", + (unsigned char *)"VHT_RXSTBC", + (unsigned char *)"VHT_SU_BEAMFORMER_CAP", + (unsigned char *)"VHT_SU_BEAMFORMEE_CAP", + (unsigned char *)"VHT_CSN_BEAMFORMEE_ANT_SUPPORTED", + (unsigned char *)"VHT_NUM_SOUNDING_DIMENSIONS", + (unsigned char *)"VHT_MU_BEAMFORMER_CAP", + (unsigned char *)"VHT_MU_BEAMFORMEE_CAP", + (unsigned char *)"VHT_TXOP_PS", + (unsigned char *)"VHT_HTC_VHTC_CAP", + (unsigned char *)"VHT_AMPDU_LEN_EXPONENT", + (unsigned char *)"VHT_LINK_ADAPTATION_CAP", + (unsigned char *)"VHT_RX_ANT_PATTERN", + (unsigned char *)"VHT_TX_ANT_PATTERN", + (unsigned char *)"VHT_RX_MCS_MAP", + (unsigned char *)"VHT_TX_MCS_MAP", + (unsigned char *)"VHT_RX_HIGHEST_SUPPORTED_DATA_RATE", + (unsigned char *)"VHT_TX_HIGHEST_SUPPORTED_DATA_RATE", + (unsigned char *)"VHT_CHANNEL_CENTER_FREQ_SEGMENT1", + (unsigned char *)"VHT_CHANNEL_CENTER_FREQ_SEGMENT2", + (unsigned char *)"VHT_BASIC_MCS_SET", + (unsigned char *)"VHT_MU_MIMO_CAP_STA_COUNT", + (unsigned char *)"VHT_SS_UNDER_UTIL", + (unsigned char *)"VHT_40MHZ_UTILIZATION", + (unsigned char *)"VHT_80MHZ_UTILIZATION", + (unsigned char *)"VHT_160MHZ_UTILIZATION", + (unsigned char *)"MAX_AMSDU_LENGTH", + (unsigned char *)"MPDU_DENSITY", + (unsigned char *)"NUM_BUFF_ADVERT", + (unsigned char *)"MAX_RX_AMPDU_FACTOR", + (unsigned char *)"SHORT_GI_20MHZ", + (unsigned char *)"SHORT_GI_40MHZ", + (unsigned char *)"RIFS_ENABLED", + (unsigned char *)"MAX_PS_POLL", + (unsigned char *)"NUM_BEACON_PER_RSSI_AVERAGE", + (unsigned char *)"RSSI_FILTER_PERIOD", + (unsigned char *)"MIN_RSSI_THRESHOLD", + (unsigned char *)"NTH_BEACON_FILTER", + (unsigned char *)"BROADCAST_FRAME_FILTER_ENABLE", + (unsigned char *)"SCAN_IN_POWERSAVE", + (unsigned char *)"IGNORE_DTIM", + (unsigned char *)"WOWLAN_UCAST_PATTERN_FILTER_ENABLE", + (unsigned char *)"WOWLAN_CHANNEL_SWITCH_ENABLE", + (unsigned char *)"WOWLAN_DEAUTH_ENABLE", + (unsigned char *)"WOWLAN_DISASSOC_ENABLE", + (unsigned char *)"WOWLAN_MAX_MISSED_BEACON", + (unsigned char *)"WOWLAN_MAX_SLEEP_PERIOD", + (unsigned char *)"BA_TIMEOUT", + (unsigned char *)"BA_THRESHOLD_HIGH", + (unsigned char *)"MAX_BA_BUFFERS", + (unsigned char *)"MAX_BA_SESSIONS", + (unsigned char *)"BA_AUTO_SETUP", + (unsigned char *)"ADDBA_REQ_DECLINE", + (unsigned char *)"DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC", + (unsigned char *)"BG_SCAN_CHANNEL_LIST", + (unsigned char *)"MAX_MEDIUM_TIME", + (unsigned char *)"MAX_MPDUS_IN_AMPDU", + (unsigned char *)"IBSS_AUTO_BSSID", + (unsigned char *)"PROBE_REQ_ADDNIE_FLAG", + (unsigned char *)"PROBE_REQ_ADDNIE_DATA", + (unsigned char *)"PROBE_RSP_ADDNIE_FLAG", + (unsigned char *)"PROBE_RSP_ADDNIE_DATA1", + (unsigned char *)"PROBE_RSP_ADDNIE_DATA2", + (unsigned char *)"PROBE_RSP_ADDNIE_DATA3", + (unsigned char *)"ASSOC_RSP_ADDNIE_FLAG", + (unsigned char *)"ASSOC_RSP_ADDNIE_DATA", + (unsigned char *)"PROBE_REQ_ADDNP2PIE_FLAG", + (unsigned char *)"PROBE_REQ_ADDNP2PIE_DATA", + (unsigned char *)"PROBE_RSP_BCN_ADDNIE_FLAG", + (unsigned char *)"PROBE_RSP_BCN_ADDNIE_DATA", + (unsigned char *)"WPS_ENABLE", + (unsigned char *)"WPS_STATE", + (unsigned char *)"WPS_PROBE_REQ_FLAG", + (unsigned char *)"WPS_VERSION", + (unsigned char *)"WPS_REQUEST_TYPE", + (unsigned char *)"WPS_CFG_METHOD", + (unsigned char *)"WPS_UUID", + (unsigned char *)"WPS_PRIMARY_DEVICE_CATEGORY", + (unsigned char *)"WPS_PIMARY_DEVICE_OUI", + (unsigned char *)"WPS_DEVICE_SUB_CATEGORY", + (unsigned char *)"WPS_ASSOCIATION_STATE", + (unsigned char *)"WPS_CONFIGURATION_ERROR", + (unsigned char *)"WPS_DEVICE_PASSWORD_ID", + (unsigned char *)"WPS_ASSOC_METHOD", + (unsigned char *)"LOW_GAIN_OVERRIDE", + (unsigned char *)"ENABLE_PHY_AGC_LISTEN_MODE", + (unsigned char *)"RPE_POLLING_THRESHOLD", + (unsigned char *)"RPE_AGING_THRESHOLD_FOR_AC0_REG", + (unsigned char *)"RPE_AGING_THRESHOLD_FOR_AC1_REG", + (unsigned char *)"RPE_AGING_THRESHOLD_FOR_AC2_REG", + (unsigned char *)"RPE_AGING_THRESHOLD_FOR_AC3_REG", + (unsigned char *)"NO_OF_ONCHIP_REORDER_SESSIONS", + (unsigned char *)"SINGLE_TID_RC", + (unsigned char *)"TX_PWR_CTRL_ENABLE", + (unsigned char *)"MCAST_BCAST_FILTER_SETTING", + (unsigned char *)"BTC_DHCP_BT_SLOTS_TO_BLOCK", + (unsigned char *)"DYNAMIC_PS_POLL_VALUE", + (unsigned char *)"PS_NULLDATA_AP_RESP_TIMEOUT", + (unsigned char *)"TELE_BCN_WAKEUP_EN", + (unsigned char *)"TELE_BCN_TRANS_LI", + (unsigned char *)"TELE_BCN_TRANS_LI_IDLE_BCNS", + (unsigned char *)"TELE_BCN_MAX_LI", + (unsigned char *)"TELE_BCN_MAX_LI_IDLE_BCNS", + (unsigned char *)"BTC_A2DP_DHCP_BT_SUB_INTERVALS", + (unsigned char *)"INFRA_STA_KEEP_ALIVE_PERIOD", + (unsigned char *)"ASSOC_STA_LIMIT", + (unsigned char *)"SAP_CHANNEL_SELECT_START_CHANNEL", + (unsigned char *)"SAP_CHANNEL_SELECT_END_CHANNEL", + (unsigned char *)"SAP_CHANNEL_SELECT_OPERATING_BAND", + (unsigned char *)"AP_DATA_AVAIL_POLL_PERIOD", + (unsigned char *)"ENABLE_CLOSE_LOOP", + (unsigned char *)"ENABLE_LTE_COEX", + (unsigned char *)"AP_KEEP_ALIVE_TIMEOUT", + (unsigned char *)"GO_KEEP_ALIVE_TIMEOUT", + (unsigned char *)"ENABLE_MC_ADDR_LIST", + (unsigned char *)"ENABLE_UC_FILTER", + (unsigned char *)"ENABLE_LPWR_IMG_TRANSITION", + (unsigned char *)"ENABLE_MCC_ADAPTIVE_SCHED", + (unsigned char *)"DISABLE_LDPC_WITH_TXBF_AP", + (unsigned char *)"AP_LINK_MONITOR_TIMEOUT", + (unsigned char *)"TDLS_QOS_WMM_UAPSD_MASK", + (unsigned char *)"TDLS_BUF_STA_ENABLED", + (unsigned char *)"TDLS_PUAPSD_INACT_TIME", + (unsigned char *)"TDLS_RX_FRAME_THRESHOLD", + (unsigned char *)"PMF_SA_QUERY_MAX_RETRIES", + (unsigned char *)"PMF_SA_QUERY_RETRY_INTERVAL", + (unsigned char *)"ENABLE_ADAPT_RX_DRAIN", + (unsigned char *)"FLEX_CONNECT_POWER_FACTOR", + (unsigned char *)"ANTENNA_DIVESITY", + (unsigned char *)"GO_LINK_MONITOR_TIMEOUT", + (unsigned char *)"RMC_ACTION_PERIOD_FREQUENCY", + (unsigned char *)"CURRENT_RSSI", + (unsigned char *)"RTT3_ENABLE", + (unsigned char *)"DEBUG_P2P_REMAIN_ON_CHANNEL", + (unsigned char *)"TDLS_OFF_CHANNEL_ENABLED", + (unsigned char *)"IBSS_ATIM_WIN_SIZE", + (unsigned char *)"DFS_MASTER_ENABLED", + (unsigned char *)"VHT_ENABLE_TXBF_20MHZ", + (unsigned char *)"TDLS_WMM_MODE_ENABLED", +}; + diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgPriv.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgPriv.h new file mode 100644 index 000000000000..7ab0fec80068 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgPriv.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This is the private header file for CFG module. + * + * Author: Kevin Nguyen + * Date: 03/20/02 + * History:- + * 03/20/02 Created. + * -------------------------------------------------------------------- + * + */ + +#ifndef __CFGPRIV_H +#define __CFGPRIV_H + +#include +#include +#include +#include +#include +#include +#include +#include "cfgDef.h" + + #include + +/*--------------------------------------------------------------------*/ +/* CFG miscellaneous definition */ +/*--------------------------------------------------------------------*/ + +// Function index bit mask +#define CFG_FUNC_INDX_MASK 0x7f +#define CFG_GET_FUNC_INDX(val) (val & CFG_FUNC_INDX_MASK) + +// Macro to convert return code to debug string index +#define CFG_GET_DBG_INDX(val) (val - eCFG_SUCCESS - 1) + + +/*--------------------------------------------------------------------*/ +/* Binary header structure */ +/*--------------------------------------------------------------------*/ +typedef struct sCfgBinHdr +{ + tANI_U32 hdrInfo; + tANI_U32 controlSize; + tANI_U32 iBufSize; + tANI_U32 sBufSize; +} tCfgBinHdr, *tpCfgBinHdr; + + +#define CFG_STAT_CNT_LO_MASK 0x0000ffff +#define CFG_STAT_CNT_HI_MASK 0xffff0000 +#define CFG_STAT_CNT_HI_INCR 0x00010000 + +/*--------------------------------------------------------------------*/ +/* CFG function prototypes */ +/*--------------------------------------------------------------------*/ + +extern void cfgSendHostMsg(tpAniSirGlobal, tANI_U16, tANI_U32, tANI_U32, tANI_U32*, tANI_U32, tANI_U32*); + +extern struct cfgstatic_string cfg_static_string[CFG_MAX_STATIC_STRING]; + +extern struct cgstatic cfg_static[CFG_PARAM_MAX_NUM]; + +#endif /* __CFGPRIV_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c new file mode 100644 index 000000000000..4b53a83ec3e4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c @@ -0,0 +1,2979 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file contains CFG functions for processing host messages. + * + * Author: Kevin Nguyen + * Date: 04/09/02 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + */ +#include "palTypes.h" +#include "aniGlobal.h" +#include "cfgPriv.h" +#include "cfgDebug.h" +#include "wlan_qct_wda.h" + +struct cgstatic cfg_static[CFG_PARAM_MAX_NUM] = { + {WNI_CFG_STA_ID, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RELOAD | + CFG_CTL_NTF_HAL, + 0, 255, 1}, + + {WNI_CFG_CF_POLLABLE, + CFG_CTL_RE | CFG_CTL_INT | CFG_CTL_RESTART, + 0, 255, 1}, + + {WNI_CFG_CFP_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_INT, + WNI_CFG_CFP_PERIOD_STAMIN, + WNI_CFG_CFP_PERIOD_STAMAX, + WNI_CFG_CFP_PERIOD_STADEF}, + + {WNI_CFG_CFP_MAX_DURATION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_INT, + WNI_CFG_CFP_MAX_DURATION_STAMIN, + WNI_CFG_CFP_MAX_DURATION_STAMAX, + WNI_CFG_CFP_MAX_DURATION_STADEF}, + + {WNI_CFG_SSID, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 255, 6}, + + {WNI_CFG_BEACON_INTERVAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_SCH, + WNI_CFG_BEACON_INTERVAL_STAMIN, + WNI_CFG_BEACON_INTERVAL_STAMAX, + WNI_CFG_BEACON_INTERVAL_STADEF}, + + {WNI_CFG_DTIM_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_INT, + WNI_CFG_DTIM_PERIOD_STAMIN, + WNI_CFG_DTIM_PERIOD_STAMAX, + WNI_CFG_DTIM_PERIOD_STADEF}, + + {WNI_CFG_WEP_KEY_LENGTH, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_WEP_KEY_LENGTH_STAMIN, + WNI_CFG_WEP_KEY_LENGTH_STAMAX, + WNI_CFG_WEP_KEY_LENGTH_STADEF}, + + {WNI_CFG_WEP_DEFAULT_KEY_1, + CFG_CTL_VALID | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 65535, 0}, + + {WNI_CFG_WEP_DEFAULT_KEY_2, + CFG_CTL_VALID | CFG_CTL_WE | CFG_CTL_RESTART, + 1, 1, 1}, + + {WNI_CFG_WEP_DEFAULT_KEY_3, + CFG_CTL_VALID | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 5, 5}, + + {WNI_CFG_WEP_DEFAULT_KEY_4, + CFG_CTL_VALID | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 1, 0}, + + {WNI_CFG_WEP_DEFAULT_KEYID, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WEP_DEFAULT_KEYID_STAMIN, + WNI_CFG_WEP_DEFAULT_KEYID_STAMAX, + WNI_CFG_WEP_DEFAULT_KEYID_STADEF}, + + {WNI_CFG_EXCLUDE_UNENCRYPTED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_EXCLUDE_UNENCRYPTED_STAMIN, + WNI_CFG_EXCLUDE_UNENCRYPTED_STAMAX, + WNI_CFG_EXCLUDE_UNENCRYPTED_STADEF}, + + {WNI_CFG_RTS_THRESHOLD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RTS_THRESHOLD_STAMIN, + WNI_CFG_RTS_THRESHOLD_STAMAX, + WNI_CFG_RTS_THRESHOLD_STADEF}, + + {WNI_CFG_SHORT_RETRY_LIMIT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_SHORT_RETRY_LIMIT_STAMIN, + WNI_CFG_SHORT_RETRY_LIMIT_STAMAX, + WNI_CFG_SHORT_RETRY_LIMIT_STADEF}, + + {WNI_CFG_LONG_RETRY_LIMIT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_LONG_RETRY_LIMIT_STAMIN, + WNI_CFG_LONG_RETRY_LIMIT_STAMAX, + WNI_CFG_LONG_RETRY_LIMIT_STADEF}, + + {WNI_CFG_FRAGMENTATION_THRESHOLD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN, + WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX, + WNI_CFG_FRAGMENTATION_THRESHOLD_STADEF}, + + {WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STAMIN, + WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STAMAX, + WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME_STADEF}, + + {WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STAMIN, + WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STAMAX, + WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME_STADEF}, + + {WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STAMIN, + WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STAMAX, + WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME_STADEF}, + + {WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STAMIN, + WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STAMAX, + WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME_STADEF}, + + {WNI_CFG_JOIN_FAILURE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_JOIN_FAILURE_TIMEOUT_STAMIN, + WNI_CFG_JOIN_FAILURE_TIMEOUT_STAMAX, + WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF}, + + {WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STAMIN, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STAMAX, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STADEF}, + + {WNI_CFG_AUTHENTICATE_RSP_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STAMIN, + WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STAMAX, + WNI_CFG_AUTHENTICATE_RSP_TIMEOUT_STADEF}, + + {WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STAMIN, + WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STAMAX, + WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT_STADEF}, + + {WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STAMIN, + WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STAMAX, + WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT_STADEF}, + + {WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STAMIN, + WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STAMAX, + WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS_STADEF}, + + {WNI_CFG_PS_ENABLE_BCN_FILTER, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PS_ENABLE_BCN_FILTER_STAMIN, + WNI_CFG_PS_ENABLE_BCN_FILTER_STAMAX, + WNI_CFG_PS_ENABLE_BCN_FILTER_STADEF}, + + {WNI_CFG_PS_ENABLE_HEART_BEAT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PS_ENABLE_HEART_BEAT_STAMIN, + WNI_CFG_PS_ENABLE_HEART_BEAT_STAMAX, + WNI_CFG_PS_ENABLE_HEART_BEAT_STADEF}, + + {WNI_CFG_PS_ENABLE_RSSI_MONITOR, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PS_ENABLE_RSSI_MONITOR_STAMIN, + WNI_CFG_PS_ENABLE_RSSI_MONITOR_STAMAX, + WNI_CFG_PS_ENABLE_RSSI_MONITOR_STADEF}, + + {WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STAMIN, + WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STAMAX, + WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT_STADEF}, + + {WNI_CFG_RF_SETTLING_TIME_CLK, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RF_SETTLING_TIME_CLK_STAMIN, + WNI_CFG_RF_SETTLING_TIME_CLK_STAMAX, + WNI_CFG_RF_SETTLING_TIME_CLK_STADEF}, + + {WNI_CFG_SUPPORTED_RATES_11B, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 3, 1}, + + {WNI_CFG_SUPPORTED_RATES_11A, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 255, 15}, + + {WNI_CFG_PHY_MODE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_PHY_MODE_STAMIN, + WNI_CFG_PHY_MODE_STAMAX, + WNI_CFG_PHY_MODE_STADEF}, + + {WNI_CFG_DOT11_MODE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_DOT11_MODE_STAMIN, + WNI_CFG_DOT11_MODE_STAMAX, + WNI_CFG_DOT11_MODE_STADEF}, + + {WNI_CFG_OPERATIONAL_RATE_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 1, 1}, + + {WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 65535, 65534}, + + {WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_LISTEN_INTERVAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_LISTEN_INTERVAL_STAMIN, + WNI_CFG_LISTEN_INTERVAL_STAMAX, + WNI_CFG_LISTEN_INTERVAL_STADEF}, + + {WNI_CFG_VALID_CHANNEL_LIST, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + 0, 1, 1}, + + {WNI_CFG_CURRENT_CHANNEL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_INT, + WNI_CFG_CURRENT_CHANNEL_STAMIN, + WNI_CFG_CURRENT_CHANNEL_STAMAX, + WNI_CFG_CURRENT_CHANNEL_STADEF}, + + {WNI_CFG_DEFAULT_RATE_INDEX_5GHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STAMIN, + WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STAMAX, + WNI_CFG_DEFAULT_RATE_INDEX_5GHZ_STADEF}, + + {WNI_CFG_DEFAULT_RATE_INDEX_24GHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STAMIN, + WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STAMAX, + WNI_CFG_DEFAULT_RATE_INDEX_24GHZ_STADEF}, + + {WNI_CFG_RATE_ADAPTATION_TYPE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_SCH, + WNI_CFG_RATE_ADAPTATION_TYPE_STAMIN, + WNI_CFG_RATE_ADAPTATION_TYPE_STAMAX, + WNI_CFG_RATE_ADAPTATION_TYPE_STADEF}, + + {WNI_CFG_FIXED_RATE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_FIXED_RATE_STAMIN, + WNI_CFG_FIXED_RATE_STAMAX, + WNI_CFG_FIXED_RATE_STADEF}, + + {WNI_CFG_FIXED_RATE_MULTICAST_24GHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STAMIN, + WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STAMAX, + WNI_CFG_FIXED_RATE_MULTICAST_24GHZ_STADEF}, + + {WNI_CFG_FIXED_RATE_MULTICAST_5GHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STAMIN, + WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STAMAX, + WNI_CFG_FIXED_RATE_MULTICAST_5GHZ_STADEF}, + + {WNI_CFG_RETRYRATE_POLICY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RETRYRATE_POLICY_STAMIN, + WNI_CFG_RETRYRATE_POLICY_STAMAX, + WNI_CFG_RETRYRATE_POLICY_STADEF}, + + {WNI_CFG_RETRYRATE_SECONDARY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RETRYRATE_SECONDARY_STAMIN, + WNI_CFG_RETRYRATE_SECONDARY_STAMAX, + WNI_CFG_RETRYRATE_SECONDARY_STADEF}, + + {WNI_CFG_RETRYRATE_TERTIARY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RETRYRATE_TERTIARY_STAMIN, + WNI_CFG_RETRYRATE_TERTIARY_STAMAX, + WNI_CFG_RETRYRATE_TERTIARY_STADEF}, + + {WNI_CFG_APSD_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_APSD_ENABLED_STAMIN, + WNI_CFG_APSD_ENABLED_STAMAX, + WNI_CFG_APSD_ENABLED_STADEF}, + + {WNI_CFG_SHARED_KEY_AUTH_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SHARED_KEY_AUTH_ENABLE_STAMIN, + WNI_CFG_SHARED_KEY_AUTH_ENABLE_STAMAX, + WNI_CFG_SHARED_KEY_AUTH_ENABLE_STADEF}, + + {WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STAMIN, + WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STAMAX, + WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE_STADEF}, + + {WNI_CFG_AUTHENTICATION_TYPE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_AUTHENTICATION_TYPE_STAMIN, + WNI_CFG_AUTHENTICATION_TYPE_STAMAX, + WNI_CFG_AUTHENTICATION_TYPE_STADEF}, + + {WNI_CFG_CF_POLL_REQUEST, + CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART, + 0, 255, 1}, + + {WNI_CFG_PRIVACY_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_PRIVACY_ENABLED_STAMIN, + WNI_CFG_PRIVACY_ENABLED_STAMAX, + WNI_CFG_PRIVACY_ENABLED_STADEF}, + + {WNI_CFG_SHORT_PREAMBLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_SHORT_PREAMBLE_STAMIN, + WNI_CFG_SHORT_PREAMBLE_STAMAX, + WNI_CFG_SHORT_PREAMBLE_STADEF}, + + {WNI_CFG_SHORT_SLOT_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SHORT_SLOT_TIME_STAMIN, + WNI_CFG_SHORT_SLOT_TIME_STAMAX, + WNI_CFG_SHORT_SLOT_TIME_STADEF}, + + {WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STAMIN, + WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STAMAX, + WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY_STADEF}, + + {WNI_CFG_QOS_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_QOS_ENABLED_STAMIN, + WNI_CFG_QOS_ENABLED_STAMAX, + WNI_CFG_QOS_ENABLED_STADEF}, + + {WNI_CFG_HCF_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_HCF_ENABLED_STAMIN, + WNI_CFG_HCF_ENABLED_STAMAX, + WNI_CFG_HCF_ENABLED_STADEF}, + + {WNI_CFG_RSN_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_RSN_ENABLED_STAMIN, + WNI_CFG_RSN_ENABLED_STAMAX, + WNI_CFG_RSN_ENABLED_STADEF}, + + {WNI_CFG_BACKGROUND_SCAN_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_BACKGROUND_SCAN_PERIOD_STAMIN, + WNI_CFG_BACKGROUND_SCAN_PERIOD_STAMAX, + WNI_CFG_BACKGROUND_SCAN_PERIOD_STADEF}, + + {WNI_CFG_MAX_NUM_PRE_AUTH, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_MAX_NUM_PRE_AUTH_STAMIN, + WNI_CFG_MAX_NUM_PRE_AUTH_STAMAX, + WNI_CFG_MAX_NUM_PRE_AUTH_STADEF}, + + {WNI_CFG_PREAUTH_CLNUP_TIMEOUT, + CFG_CTL_INT, + 0, 255, 1}, + + {WNI_CFG_RELEASE_AID_TIMEOUT, + CFG_CTL_INT, + 0, 255, 1}, + + {WNI_CFG_HEART_BEAT_THRESHOLD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_HEART_BEAT_THRESHOLD_STAMIN, + WNI_CFG_HEART_BEAT_THRESHOLD_STAMAX, + WNI_CFG_HEART_BEAT_THRESHOLD_STADEF}, + + {WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMIN, + WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMAX, + WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STADEF}, + + {WNI_CFG_MANUFACTURER_OUI, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 0, 0}, + + {WNI_CFG_MANUFACTURER_NAME, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 0, 0}, + + {WNI_CFG_MODEL_NUMBER, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 0, 0}, + + {WNI_CFG_MODEL_NAME, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 0, 0}, + + {WNI_CFG_MANUFACTURER_PRODUCT_NAME, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 0, 0}, + + {WNI_CFG_MANUFACTURER_PRODUCT_VERSION, + CFG_CTL_VALID | CFG_CTL_RE, + 0, 0, 0}, + + {WNI_CFG_11D_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_11D_ENABLED_STAMIN, + WNI_CFG_11D_ENABLED_STAMAX, + WNI_CFG_11D_ENABLED_STADEF}, + + {WNI_CFG_MAX_TX_POWER_2_4, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_MAX_TX_POWER_5, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_NETWORK_DENSITY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_NETWORK_DENSITY_STAMIN, + WNI_CFG_NETWORK_DENSITY_STAMAX, + WNI_CFG_NETWORK_DENSITY_STADEF}, + + {WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STAMIN, + WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STAMAX, + WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM_STADEF}, + + {WNI_CFG_CURRENT_TX_ANTENNA, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_CURRENT_TX_ANTENNA_STAMIN, + WNI_CFG_CURRENT_TX_ANTENNA_STAMAX, + WNI_CFG_CURRENT_TX_ANTENNA_STADEF}, + + {WNI_CFG_CURRENT_RX_ANTENNA, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_CURRENT_RX_ANTENNA_STAMIN, + WNI_CFG_CURRENT_RX_ANTENNA_STAMAX, + WNI_CFG_CURRENT_RX_ANTENNA_STADEF}, + + {WNI_CFG_CURRENT_TX_POWER_LEVEL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMIN, + WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX, + WNI_CFG_CURRENT_TX_POWER_LEVEL_STADEF}, + + {WNI_CFG_NEW_BSS_FOUND_IND, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_NEW_BSS_FOUND_IND_STAMIN, + WNI_CFG_NEW_BSS_FOUND_IND_STAMAX, + WNI_CFG_NEW_BSS_FOUND_IND_STADEF}, + + {WNI_CFG_PROPRIETARY_RATES_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_PROPRIETARY_RATES_ENABLED_STAMIN, + WNI_CFG_PROPRIETARY_RATES_ENABLED_STAMAX, + WNI_CFG_PROPRIETARY_RATES_ENABLED_STADEF}, + + {WNI_CFG_AP_NODE_NAME, + CFG_CTL_RE, + 0, 255, 1}, + + {WNI_CFG_COUNTRY_CODE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_11H_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_11H_ENABLED_STAMIN, + WNI_CFG_11H_ENABLED_STAMAX, + WNI_CFG_11H_ENABLED_STADEF}, + + {WNI_CFG_WT_CNF_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WT_CNF_TIMEOUT_STAMIN, + WNI_CFG_WT_CNF_TIMEOUT_STAMAX, + WNI_CFG_WT_CNF_TIMEOUT_STADEF}, + + {WNI_CFG_KEEPALIVE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_KEEPALIVE_TIMEOUT_STAMIN, + WNI_CFG_KEEPALIVE_TIMEOUT_STAMAX, + WNI_CFG_KEEPALIVE_TIMEOUT_STADEF}, + + {WNI_CFG_PROXIMITY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PROXIMITY_STAMIN, + WNI_CFG_PROXIMITY_STAMAX, + WNI_CFG_PROXIMITY_STADEF}, + + {WNI_CFG_LOG_LEVEL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_LOG_LEVEL_STAMIN, + WNI_CFG_LOG_LEVEL_STAMAX, + WNI_CFG_LOG_LEVEL_STADEF}, + + {WNI_CFG_OLBC_DETECT_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_OLBC_DETECT_TIMEOUT_STAMIN, + WNI_CFG_OLBC_DETECT_TIMEOUT_STAMAX, + WNI_CFG_OLBC_DETECT_TIMEOUT_STADEF}, + + {WNI_CFG_PROTECTION_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_PROTECTION_ENABLED_STAMIN, + WNI_CFG_PROTECTION_ENABLED_STAMAX, + WNI_CFG_PROTECTION_ENABLED_STADEF}, + + {WNI_CFG_11G_PROTECTION_ALWAYS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_11G_PROTECTION_ALWAYS_STAMIN, + WNI_CFG_11G_PROTECTION_ALWAYS_STAMAX, + WNI_CFG_11G_PROTECTION_ALWAYS_STADEF}, + + {WNI_CFG_FORCE_POLICY_PROTECTION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_HAL, + WNI_CFG_FORCE_POLICY_PROTECTION_STAMIN, + WNI_CFG_FORCE_POLICY_PROTECTION_STAMAX, + WNI_CFG_FORCE_POLICY_PROTECTION_STADEF}, + + {WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STAMIN, + WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STAMAX, + WNI_CFG_11G_SHORT_PREAMBLE_ENABLED_STADEF}, + + {WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STAMIN, + WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STAMAX, + WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED_STADEF}, + + {WNI_CFG_11G_ONLY_POLICY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_11G_ONLY_POLICY_STAMIN, + WNI_CFG_11G_ONLY_POLICY_STAMAX, + WNI_CFG_11G_ONLY_POLICY_STADEF}, + + {WNI_CFG_PACKET_CLASSIFICATION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PACKET_CLASSIFICATION_STAMIN, + WNI_CFG_PACKET_CLASSIFICATION_STAMAX, + WNI_CFG_PACKET_CLASSIFICATION_STADEF}, + + {WNI_CFG_WME_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_WME_ENABLED_STAMIN, + WNI_CFG_WME_ENABLED_STAMAX, + WNI_CFG_WME_ENABLED_STADEF}, + + {WNI_CFG_ADDTS_RSP_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ADDTS_RSP_TIMEOUT_STAMIN, + WNI_CFG_ADDTS_RSP_TIMEOUT_STAMAX, + WNI_CFG_ADDTS_RSP_TIMEOUT_STADEF}, + + {WNI_CFG_MAX_SP_LENGTH, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_MAX_SP_LENGTH_STAMIN, + WNI_CFG_MAX_SP_LENGTH_STAMAX, + WNI_CFG_MAX_SP_LENGTH_STADEF}, + + {WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD, + CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + 0, 255, 1}, + + {WNI_CFG_SEND_SINGLE_SSID_ALWAYS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STAMIN, + WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STAMAX, + WNI_CFG_SEND_SINGLE_SSID_ALWAYS_STADEF}, + + {WNI_CFG_WSM_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WSM_ENABLED_STAMIN, + WNI_CFG_WSM_ENABLED_STAMAX, + WNI_CFG_WSM_ENABLED_STADEF}, + + {WNI_CFG_EDCA_PROFILE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_SCH, + WNI_CFG_EDCA_PROFILE_STAMIN, + WNI_CFG_EDCA_PROFILE_STAMAX, + WNI_CFG_EDCA_PROFILE_STADEF}, + + {WNI_CFG_EDCA_ANI_ACBK_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACBE_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACVI_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACVO_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACBK, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACBE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACVI, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_ANI_ACVO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACBK_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACBE_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACVI_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACVO_LOCAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACBK, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACBE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACVI, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_EDCA_WME_ACVO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_RDET_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_RDET_FLAG_STAMIN, + WNI_CFG_RDET_FLAG_STAMAX, + WNI_CFG_RDET_FLAG_STADEF}, + + {WNI_CFG_RADAR_CHANNEL_LIST, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART, + 0, 0, 0}, + + {WNI_CFG_LOCAL_POWER_CONSTRAINT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_LOCAL_POWER_CONSTRAINT_STAMIN, + WNI_CFG_LOCAL_POWER_CONSTRAINT_STAMAX, + WNI_CFG_LOCAL_POWER_CONSTRAINT_STADEF}, + + {WNI_CFG_ADMIT_POLICY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_ADMIT_POLICY_STAMIN, + WNI_CFG_ADMIT_POLICY_STAMAX, + WNI_CFG_ADMIT_POLICY_STADEF}, + + {WNI_CFG_ADMIT_BWFACTOR, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_ADMIT_BWFACTOR_STAMIN, + WNI_CFG_ADMIT_BWFACTOR_STAMAX, + WNI_CFG_ADMIT_BWFACTOR_STADEF}, + + {WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STAMIN, + WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STAMAX, + WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE_STADEF}, + + {WNI_CFG_CHANNEL_BONDING_MODE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_CHANNEL_BONDING_MODE_STAMIN, + WNI_CFG_CHANNEL_BONDING_MODE_STAMAX, + WNI_CFG_CHANNEL_BONDING_MODE_STADEF}, + + {WNI_CFG_CB_SECONDARY_CHANNEL_STATE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STAMIN, + WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STAMAX, + WNI_CFG_CB_SECONDARY_CHANNEL_STATE_STADEF}, + + {WNI_CFG_DYNAMIC_THRESHOLD_ZERO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STAMIN, + WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STAMAX, + WNI_CFG_DYNAMIC_THRESHOLD_ZERO_STADEF}, + + {WNI_CFG_DYNAMIC_THRESHOLD_ONE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_DYNAMIC_THRESHOLD_ONE_STAMIN, + WNI_CFG_DYNAMIC_THRESHOLD_ONE_STAMAX, + WNI_CFG_DYNAMIC_THRESHOLD_ONE_STADEF}, + + {WNI_CFG_DYNAMIC_THRESHOLD_TWO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_DYNAMIC_THRESHOLD_TWO_STAMIN, + WNI_CFG_DYNAMIC_THRESHOLD_TWO_STAMAX, + WNI_CFG_DYNAMIC_THRESHOLD_TWO_STADEF}, + + {WNI_CFG_TRIG_STA_BK_SCAN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TRIG_STA_BK_SCAN_STAMIN, + WNI_CFG_TRIG_STA_BK_SCAN_STAMAX, + WNI_CFG_TRIG_STA_BK_SCAN_STADEF}, + + {WNI_CFG_DYNAMIC_PROFILE_SWITCHING, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STAMIN, + WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STAMAX, + WNI_CFG_DYNAMIC_PROFILE_SWITCHING_STADEF}, + + {WNI_CFG_SCAN_CONTROL_LIST, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_MIMO_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RELOAD, + WNI_CFG_MIMO_ENABLED_STAMIN, + WNI_CFG_MIMO_ENABLED_STAMAX, + WNI_CFG_MIMO_ENABLED_STADEF}, + + {WNI_CFG_BLOCK_ACK_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_BLOCK_ACK_ENABLED_STAMIN, + WNI_CFG_BLOCK_ACK_ENABLED_STAMAX, + WNI_CFG_BLOCK_ACK_ENABLED_STADEF}, + + {WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STAMIN, + WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STAMAX, + WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT_STADEF}, + + {WNI_CFG_HT_RX_STBC, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_HT_RX_STBC_STAMIN, + WNI_CFG_HT_RX_STBC_STAMAX, + WNI_CFG_HT_RX_STBC_STADEF}, + + {WNI_CFG_HT_CAP_INFO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_HT_CAP_INFO_STAMIN, + WNI_CFG_HT_CAP_INFO_STAMAX, + WNI_CFG_HT_CAP_INFO_STADEF}, + + {WNI_CFG_HT_AMPDU_PARAMS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_HT_AMPDU_PARAMS_STAMIN, + WNI_CFG_HT_AMPDU_PARAMS_STAMAX, + WNI_CFG_HT_AMPDU_PARAMS_STADEF}, + + {WNI_CFG_SUPPORTED_MCS_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_SAVE | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_EXT_HT_CAP_INFO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_SAVE | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_EXT_HT_CAP_INFO_STAMIN, + WNI_CFG_EXT_HT_CAP_INFO_STAMAX, + WNI_CFG_EXT_HT_CAP_INFO_STADEF}, + + {WNI_CFG_TX_BF_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_TX_BF_CAP_STAMIN, + 4294967295u, + WNI_CFG_TX_BF_CAP_STADEF}, + + {WNI_CFG_AS_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_SAVE | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_AS_CAP_STAMIN, + WNI_CFG_AS_CAP_STAMAX, + WNI_CFG_AS_CAP_STADEF}, + + {WNI_CFG_HT_INFO_FIELD1, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_HT_INFO_FIELD1_STAMIN, + WNI_CFG_HT_INFO_FIELD1_STAMAX, + WNI_CFG_HT_INFO_FIELD1_STADEF}, + + {WNI_CFG_HT_INFO_FIELD2, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_SAVE | + CFG_CTL_NTF_LIM, + WNI_CFG_HT_INFO_FIELD2_STAMIN, + WNI_CFG_HT_INFO_FIELD2_STAMAX, + WNI_CFG_HT_INFO_FIELD2_STADEF}, + + {WNI_CFG_HT_INFO_FIELD3, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_SAVE | + CFG_CTL_NTF_LIM, + WNI_CFG_HT_INFO_FIELD3_STAMIN, + WNI_CFG_HT_INFO_FIELD3_STAMAX, + WNI_CFG_HT_INFO_FIELD3_STADEF}, + + {WNI_CFG_BASIC_MCS_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_SAVE | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_CURRENT_MCS_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_SAVE | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_GREENFIELD_CAPABILITY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_RESTART | + CFG_CTL_NTF_LIM, + WNI_CFG_GREENFIELD_CAPABILITY_STAMIN, + WNI_CFG_GREENFIELD_CAPABILITY_STAMAX, + WNI_CFG_GREENFIELD_CAPABILITY_STADEF}, + + {WNI_CFG_VHT_MAX_MPDU_LENGTH, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_MAX_MPDU_LENGTH_STAMIN, + WNI_CFG_VHT_MAX_MPDU_LENGTH_STAMAX, + WNI_CFG_VHT_MAX_MPDU_LENGTH_STADEF}, + + {WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STAMIN, + WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STAMAX, + WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STADEF}, + + {WNI_CFG_VHT_LDPC_CODING_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_LDPC_CODING_CAP_STAMIN, + WNI_CFG_VHT_LDPC_CODING_CAP_STAMAX, + WNI_CFG_VHT_LDPC_CODING_CAP_STADEF}, + + {WNI_CFG_VHT_SHORT_GI_80MHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_SHORT_GI_80MHZ_STAMIN, + WNI_CFG_VHT_SHORT_GI_80MHZ_STAMAX, + WNI_CFG_VHT_SHORT_GI_80MHZ_STADEF}, + + {WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STAMIN, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STAMAX, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ_STADEF}, + + {WNI_CFG_VHT_TXSTBC, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_TXSTBC_STAMIN, + WNI_CFG_VHT_TXSTBC_STAMAX, + WNI_CFG_VHT_TXSTBC_STADEF}, + + {WNI_CFG_VHT_RXSTBC, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_RXSTBC_STAMIN, + WNI_CFG_VHT_RXSTBC_STAMAX, + WNI_CFG_VHT_RXSTBC_STADEF}, + + {WNI_CFG_VHT_SU_BEAMFORMER_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_SU_BEAMFORMER_CAP_STAMIN, + WNI_CFG_VHT_SU_BEAMFORMER_CAP_STAMAX, + WNI_CFG_VHT_SU_BEAMFORMER_CAP_STADEF}, + + {WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMIN, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STAMAX, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP_STADEF}, + + {WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMIN, + WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STAMAX, + WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_STADEF}, + + {WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STAMIN, + WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STAMAX, + WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS_STADEF}, + + {WNI_CFG_VHT_MU_BEAMFORMER_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_MU_BEAMFORMER_CAP_STAMIN, + WNI_CFG_VHT_MU_BEAMFORMER_CAP_STAMAX, + WNI_CFG_VHT_MU_BEAMFORMER_CAP_STADEF}, + + {WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STAMIN, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STAMAX, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP_STADEF}, + + {WNI_CFG_VHT_TXOP_PS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_TXOP_PS_STAMIN, + WNI_CFG_VHT_TXOP_PS_STAMAX, + WNI_CFG_VHT_TXOP_PS_STADEF}, + + {WNI_CFG_VHT_HTC_VHTC_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_HTC_VHTC_CAP_STAMIN, + WNI_CFG_VHT_HTC_VHTC_CAP_STAMAX, + WNI_CFG_VHT_HTC_VHTC_CAP_STADEF}, + + {WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STAMIN, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STAMAX, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT_STADEF}, + + {WNI_CFG_VHT_LINK_ADAPTATION_CAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_LINK_ADAPTATION_CAP_STAMIN, + WNI_CFG_VHT_LINK_ADAPTATION_CAP_STAMAX, + WNI_CFG_VHT_LINK_ADAPTATION_CAP_STADEF}, + + {WNI_CFG_VHT_RX_ANT_PATTERN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_RX_ANT_PATTERN_STAMIN, + WNI_CFG_VHT_RX_ANT_PATTERN_STAMAX, + WNI_CFG_VHT_RX_ANT_PATTERN_STADEF}, + + {WNI_CFG_VHT_TX_ANT_PATTERN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_TX_ANT_PATTERN_STAMIN, + WNI_CFG_VHT_TX_ANT_PATTERN_STAMAX, + WNI_CFG_VHT_TX_ANT_PATTERN_STADEF}, + + {WNI_CFG_VHT_RX_MCS_MAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_RX_MCS_MAP_STAMIN, + WNI_CFG_VHT_RX_MCS_MAP_STAMAX, + WNI_CFG_VHT_RX_MCS_MAP_STADEF}, + + {WNI_CFG_VHT_TX_MCS_MAP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_TX_MCS_MAP_STAMIN, + WNI_CFG_VHT_TX_MCS_MAP_STAMAX, + WNI_CFG_VHT_TX_MCS_MAP_STADEF}, + + {WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STAMIN, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STAMAX, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_STADEF}, + + {WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STAMIN, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STAMAX, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_STADEF}, + + {WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STAMIN, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STAMAX, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1_STADEF}, + + {WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STAMIN, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STAMAX, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2_STADEF}, + + {WNI_CFG_VHT_BASIC_MCS_SET, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_BASIC_MCS_SET_STAMIN, + WNI_CFG_VHT_BASIC_MCS_SET_STAMAX, + WNI_CFG_VHT_BASIC_MCS_SET_STADEF}, + + {WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STAMIN, + WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STAMAX, + WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT_STADEF}, + + {WNI_CFG_VHT_SS_UNDER_UTIL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_SS_UNDER_UTIL_STAMIN, + WNI_CFG_VHT_SS_UNDER_UTIL_STAMAX, + WNI_CFG_VHT_SS_UNDER_UTIL_STADEF}, + + {WNI_CFG_VHT_40MHZ_UTILIZATION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_40MHZ_UTILIZATION_STAMIN, + WNI_CFG_VHT_40MHZ_UTILIZATION_STAMAX, + WNI_CFG_VHT_40MHZ_UTILIZATION_STADEF}, + + {WNI_CFG_VHT_80MHZ_UTILIZATION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_80MHZ_UTILIZATION_STAMIN, + WNI_CFG_VHT_80MHZ_UTILIZATION_STAMAX, + WNI_CFG_VHT_80MHZ_UTILIZATION_STADEF}, + + {WNI_CFG_VHT_160MHZ_UTILIZATION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_VHT_80MHZ_UTILIZATION_STADEF, + WNI_CFG_VHT_160MHZ_UTILIZATION_STAMAX, + WNI_CFG_VHT_160MHZ_UTILIZATION_STADEF}, + + {WNI_CFG_MAX_AMSDU_LENGTH, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_MAX_AMSDU_LENGTH_STAMIN, + WNI_CFG_MAX_AMSDU_LENGTH_STAMAX, + WNI_CFG_MAX_AMSDU_LENGTH_STADEF}, + + {WNI_CFG_MPDU_DENSITY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_MPDU_DENSITY_STAMIN, + WNI_CFG_MPDU_DENSITY_STAMAX, + WNI_CFG_MPDU_DENSITY_STADEF}, + + {WNI_CFG_NUM_BUFF_ADVERT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_NUM_BUFF_ADVERT_STAMIN, + WNI_CFG_NUM_BUFF_ADVERT_STAMAX, + WNI_CFG_NUM_BUFF_ADVERT_STADEF}, + + {WNI_CFG_MAX_RX_AMPDU_FACTOR, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMIN, + WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMAX, + WNI_CFG_MAX_RX_AMPDU_FACTOR_STAMAX}, + + {WNI_CFG_SHORT_GI_20MHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_SHORT_GI_20MHZ_STAMIN, + WNI_CFG_SHORT_GI_20MHZ_STAMAX, + WNI_CFG_SHORT_GI_20MHZ_STADEF}, + + {WNI_CFG_SHORT_GI_40MHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_SHORT_GI_40MHZ_STAMIN, + WNI_CFG_SHORT_GI_40MHZ_STAMAX, + WNI_CFG_SHORT_GI_40MHZ_STADEF}, + + {WNI_CFG_RIFS_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_RIFS_ENABLED_STAMIN, + WNI_CFG_RIFS_ENABLED_STAMAX, + WNI_CFG_RIFS_ENABLED_STADEF}, + + {WNI_CFG_MAX_PS_POLL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_MAX_PS_POLL_STAMIN, + WNI_CFG_MAX_PS_POLL_STAMAX, + WNI_CFG_MAX_PS_POLL_STADEF}, + + {WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMIN, + WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX, + WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STADEF}, + + {WNI_CFG_RSSI_FILTER_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_RSSI_FILTER_PERIOD_STAMIN, + WNI_CFG_RSSI_FILTER_PERIOD_STAMAX, + WNI_CFG_RSSI_FILTER_PERIOD_STADEF}, + + {WNI_CFG_MIN_RSSI_THRESHOLD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_MIN_RSSI_THRESHOLD_STAMIN, + WNI_CFG_MIN_RSSI_THRESHOLD_STAMAX, + WNI_CFG_MIN_RSSI_THRESHOLD_STADEF}, + + {WNI_CFG_NTH_BEACON_FILTER, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_NTH_BEACON_FILTER_STAMIN, + WNI_CFG_NTH_BEACON_FILTER_STAMAX, + WNI_CFG_NTH_BEACON_FILTER_STADEF}, + + {WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STAMIN, + WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STAMAX, + WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE_STADEF}, + + {WNI_CFG_SCAN_IN_POWERSAVE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_SCAN_IN_POWERSAVE_STAMIN, + WNI_CFG_SCAN_IN_POWERSAVE_STAMAX, + WNI_CFG_SCAN_IN_POWERSAVE_STADEF}, + + {WNI_CFG_IGNORE_DTIM, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_IGNORE_DTIM_STAMIN, + WNI_CFG_IGNORE_DTIM_STAMAX, + WNI_CFG_IGNORE_DTIM_STADEF}, + + {WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STAMIN, + WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STAMAX, + WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE_STADEF}, + + {WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STAMIN, + WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STAMAX, + WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE_STADEF}, + + {WNI_CFG_WOWLAN_DEAUTH_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WOWLAN_DEAUTH_ENABLE_STAMIN, + WNI_CFG_WOWLAN_DEAUTH_ENABLE_STAMAX, + WNI_CFG_WOWLAN_DEAUTH_ENABLE_STADEF}, + + {WNI_CFG_WOWLAN_DISASSOC_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WOWLAN_DISASSOC_ENABLE_STAMIN, + WNI_CFG_WOWLAN_DISASSOC_ENABLE_STAMAX, + WNI_CFG_WOWLAN_DISASSOC_ENABLE_STADEF}, + + {WNI_CFG_WOWLAN_MAX_MISSED_BEACON, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STAMIN, + WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STAMAX, + WNI_CFG_WOWLAN_MAX_MISSED_BEACON_STADEF}, + + {WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STAMIN, + WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STAMAX, + WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD_STADEF}, + + {WNI_CFG_BA_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_HAL, + WNI_CFG_BA_TIMEOUT_STAMIN, + WNI_CFG_BA_TIMEOUT_STAMAX, + WNI_CFG_BA_TIMEOUT_STADEF}, + + {WNI_CFG_BA_THRESHOLD_HIGH, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_HAL, + WNI_CFG_BA_THRESHOLD_HIGH_STAMIN, + WNI_CFG_BA_THRESHOLD_HIGH_STAMAX, + WNI_CFG_BA_THRESHOLD_HIGH_STADEF}, + + {WNI_CFG_MAX_BA_BUFFERS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_HAL, + WNI_CFG_MAX_BA_BUFFERS_STAMIN, + WNI_CFG_MAX_BA_BUFFERS_STAMAX, + WNI_CFG_MAX_BA_BUFFERS_STADEF}, + + {WNI_CFG_MAX_BA_SESSIONS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_HAL, + WNI_CFG_MAX_BA_SESSIONS_STAMIN, + WNI_CFG_MAX_BA_SESSIONS_STAMAX, + WNI_CFG_MAX_BA_SESSIONS_STADEF}, + + {WNI_CFG_BA_AUTO_SETUP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_HAL, + WNI_CFG_BA_AUTO_SETUP_STAMIN, + WNI_CFG_BA_AUTO_SETUP_STAMAX, + WNI_CFG_BA_AUTO_SETUP_STADEF}, + + {WNI_CFG_ADDBA_REQ_DECLINE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART | CFG_CTL_NTF_LIM, + WNI_CFG_ADDBA_REQ_DECLINE_STAMIN, + WNI_CFG_ADDBA_REQ_DECLINE_STAMAX, + WNI_CFG_ADDBA_REQ_DECLINE_STADEF}, + + {WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN, + WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX, + WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF}, + + {WNI_CFG_BG_SCAN_CHANNEL_LIST, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_MAX_MEDIUM_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_MAX_MEDIUM_TIME_STAMIN, + WNI_CFG_MAX_MEDIUM_TIME_STAMAX, + WNI_CFG_MAX_MEDIUM_TIME_STADEF}, + + {WNI_CFG_MAX_MPDUS_IN_AMPDU, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_MAX_MPDUS_IN_AMPDU_STAMIN, + WNI_CFG_MAX_MPDUS_IN_AMPDU_STAMAX, + WNI_CFG_MAX_MPDUS_IN_AMPDU_STADEF}, + + {WNI_CFG_IBSS_AUTO_BSSID, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_IBSS_AUTO_BSSID_STAMIN, + WNI_CFG_IBSS_AUTO_BSSID_STAMAX, + WNI_CFG_IBSS_AUTO_BSSID_STADEF}, + + {WNI_CFG_PROBE_REQ_ADDNIE_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STAMIN, + WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STAMAX, + WNI_CFG_PROBE_REQ_ADDNIE_FLAG_STADEF}, + + {WNI_CFG_PROBE_REQ_ADDNIE_DATA, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_PROBE_RSP_ADDNIE_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STAMIN, + WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STAMAX, + WNI_CFG_PROBE_RSP_ADDNIE_FLAG_STADEF}, + + {WNI_CFG_PROBE_RSP_ADDNIE_DATA1, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_PROBE_RSP_ADDNIE_DATA2, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_PROBE_RSP_ADDNIE_DATA3, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STAMIN, + WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STAMAX, + WNI_CFG_ASSOC_RSP_ADDNIE_FLAG_STADEF}, + + {WNI_CFG_ASSOC_RSP_ADDNIE_DATA, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STAMIN, + WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STAMAX, + WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG_STADEF}, + + {WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, + 0, 0, 0}, + + {WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STAMIN, + WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STAMAX, + WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG_STADEF}, + + {WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_WPS_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_ENABLE_STAMIN, + WNI_CFG_WPS_ENABLE_STAMAX, + WNI_CFG_WPS_ENABLE_STADEF}, + + {WNI_CFG_WPS_STATE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_STATE_STAMIN, + WNI_CFG_WPS_STATE_STAMAX, + WNI_CFG_WPS_STATE_STADEF}, + + {WNI_CFG_WPS_PROBE_REQ_FLAG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_PROBE_REQ_FLAG_STAMIN, + WNI_CFG_WPS_PROBE_REQ_FLAG_STAMAX, + WNI_CFG_WPS_PROBE_REQ_FLAG_STADEF}, + + {WNI_CFG_WPS_VERSION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_VERSION_STAMIN, + WNI_CFG_WPS_VERSION_STAMAX, + WNI_CFG_WPS_VERSION_STADEF}, + + {WNI_CFG_WPS_REQUEST_TYPE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_REQUEST_TYPE_STAMIN, + WNI_CFG_WPS_REQUEST_TYPE_STAMAX, + WNI_CFG_WPS_REQUEST_TYPE_STADEF}, + + {WNI_CFG_WPS_CFG_METHOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_CFG_METHOD_STAMIN, + 4294967295u, + WNI_CFG_WPS_CFG_METHOD_STADEF}, + + {WNI_CFG_WPS_UUID, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_NTF_LIM, + 0, 0, 0}, + + {WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STAMIN, + WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STAMAX, + WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY_STADEF}, + + {WNI_CFG_WPS_PIMARY_DEVICE_OUI, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_PIMARY_DEVICE_OUI_STAMIN, + 4294967295u, + WNI_CFG_WPS_PIMARY_DEVICE_OUI_STADEF}, + + {WNI_CFG_WPS_DEVICE_SUB_CATEGORY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STAMIN, + WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STAMAX, + WNI_CFG_WPS_DEVICE_SUB_CATEGORY_STADEF}, + + {WNI_CFG_WPS_ASSOCIATION_STATE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_ASSOCIATION_STATE_STAMIN, + WNI_CFG_WPS_ASSOCIATION_STATE_STAMAX, + WNI_CFG_WPS_ASSOCIATION_STATE_STADEF}, + + {WNI_CFG_WPS_CONFIGURATION_ERROR, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_CONFIGURATION_ERROR_STAMIN, + WNI_CFG_WPS_CONFIGURATION_ERROR_STAMAX, + WNI_CFG_WPS_CONFIGURATION_ERROR_STADEF}, + + {WNI_CFG_WPS_DEVICE_PASSWORD_ID, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_DEVICE_PASSWORD_ID_STAMIN, + 4294967295u, + WNI_CFG_WPS_DEVICE_PASSWORD_ID_STADEF}, + + {WNI_CFG_WPS_ASSOC_METHOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_WPS_ASSOC_METHOD_STAMIN, + WNI_CFG_WPS_ASSOC_METHOD_STAMAX, + WNI_CFG_WPS_ASSOC_METHOD_STADEF}, + + {WNI_CFG_LOW_GAIN_OVERRIDE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_LOW_GAIN_OVERRIDE_STAMIN, + WNI_CFG_LOW_GAIN_OVERRIDE_STAMAX, + WNI_CFG_LOW_GAIN_OVERRIDE_STADEF}, + + {WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STAMIN, + WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STAMAX, + WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE_STADEF}, + + {WNI_CFG_RPE_POLLING_THRESHOLD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RPE_POLLING_THRESHOLD_STAMIN, + WNI_CFG_RPE_POLLING_THRESHOLD_STAMAX, + WNI_CFG_RPE_POLLING_THRESHOLD_STADEF}, + + {WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STAMIN, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STAMAX, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG_STADEF}, + + {WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STAMIN, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STAMAX, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG_STADEF}, + + {WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STAMIN, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STAMAX, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG_STADEF}, + + {WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STAMIN, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STAMAX, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG_STADEF}, + + {WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STAMIN, + WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STAMAX, + WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS_STADEF}, + + {WNI_CFG_SINGLE_TID_RC, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SINGLE_TID_RC_STAMIN, + WNI_CFG_SINGLE_TID_RC_STAMAX, + WNI_CFG_SINGLE_TID_RC_STADEF}, + + {WNI_CFG_TX_PWR_CTRL_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_TX_PWR_CTRL_ENABLE_STAMIN, + WNI_CFG_TX_PWR_CTRL_ENABLE_STAMAX, + WNI_CFG_TX_PWR_CTRL_ENABLE_STADEF}, + + {WNI_CFG_MCAST_BCAST_FILTER_SETTING, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMIN, + WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMAX, + WNI_CFG_MCAST_BCAST_FILTER_SETTING_STADEF}, + + {WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMIN, + WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMAX, + WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STADEF}, + + {WNI_CFG_DYNAMIC_PS_POLL_VALUE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMIN, + WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMAX, + WNI_CFG_DYNAMIC_PS_POLL_VALUE_STADEF}, + + {WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMIN, + WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMAX, + WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STADEF}, + + {WNI_CFG_TELE_BCN_WAKEUP_EN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_TELE_BCN_WAKEUP_EN_STAMIN, + WNI_CFG_TELE_BCN_WAKEUP_EN_STAMAX, + WNI_CFG_TELE_BCN_WAKEUP_EN_STADEF}, + + {WNI_CFG_TELE_BCN_TRANS_LI, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_TELE_BCN_TRANS_LI_STAMIN, + WNI_CFG_TELE_BCN_TRANS_LI_STAMAX, + WNI_CFG_TELE_BCN_TRANS_LI_STADEF}, + + {WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMIN, + WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMAX, + WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STADEF}, + + {WNI_CFG_TELE_BCN_MAX_LI, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_TELE_BCN_MAX_LI_STAMIN, + WNI_CFG_TELE_BCN_MAX_LI_STAMAX, + WNI_CFG_TELE_BCN_MAX_LI_STADEF}, + + {WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMIN, + WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMAX, + WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STADEF}, + + {WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMIN, + WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMAX, + WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STADEF}, + + {WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMIN, + WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX, + WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STADEF}, + + {WNI_CFG_ASSOC_STA_LIMIT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_ASSOC_STA_LIMIT_STAMIN, + WNI_CFG_ASSOC_STA_LIMIT_STAMAX, + WNI_CFG_ASSOC_STA_LIMIT_STADEF}, + + {WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMIN, + WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMAX, + WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STADEF}, + + {WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMIN, + WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMAX, + WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STADEF}, + + {WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMIN, + WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMAX, + WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STADEF}, + + {WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMIN, + WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMAX, + WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STADEF}, + + {WNI_CFG_ENABLE_CLOSE_LOOP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ENABLE_CLOSE_LOOP_STAMIN, + WNI_CFG_ENABLE_CLOSE_LOOP_STAMAX, + WNI_CFG_ENABLE_CLOSE_LOOP_STADEF}, + + {WNI_CFG_ENABLE_LTE_COEX, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ENABLE_LTE_COEX_STAMIN, + WNI_CFG_ENABLE_LTE_COEX_STAMAX, + WNI_CFG_ENABLE_LTE_COEX_STADEF}, + + {WNI_CFG_AP_KEEP_ALIVE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMIN, + WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMAX, + WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STADEF}, + + {WNI_CFG_GO_KEEP_ALIVE_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMIN, + WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMAX, + WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STADEF}, + + {WNI_CFG_ENABLE_MC_ADDR_LIST, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_ENABLE_MC_ADDR_LIST_STAMIN, + WNI_CFG_ENABLE_MC_ADDR_LIST_STAMAX, + WNI_CFG_ENABLE_MC_ADDR_LIST_STADEF}, + + {WNI_CFG_ENABLE_UC_FILTER, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_ENABLE_UC_FILTER_STAMIN, + WNI_CFG_ENABLE_UC_FILTER_STAMAX, + WNI_CFG_ENABLE_UC_FILTER_STADEF}, + + {WNI_CFG_ENABLE_LPWR_IMG_TRANSITION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMIN, + WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMAX, + WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STADEF}, + + {WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMIN, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STADEF}, + + {WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMIN, + WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMAX, + WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STADEF}, + + {WNI_CFG_AP_LINK_MONITOR_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMIN, + WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMAX, + WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STADEF}, + + {WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMIN, + WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMAX, + WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STADEF}, + + {WNI_CFG_TDLS_BUF_STA_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TDLS_BUF_STA_ENABLED_STAMIN, + WNI_CFG_TDLS_BUF_STA_ENABLED_STAMAX, + WNI_CFG_TDLS_BUF_STA_ENABLED_STADEF}, + + {WNI_CFG_TDLS_PUAPSD_INACT_TIME, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMIN, + WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMAX, + WNI_CFG_TDLS_PUAPSD_INACT_TIME_STADEF}, + + {WNI_CFG_TDLS_RX_FRAME_THRESHOLD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMIN, + WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMAX, + WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STADEF}, + + {WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMIN, + WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMAX, + WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STADEF}, + + {WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_RESTART, + WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN, + WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMAX, + WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF}, + + {WNI_CFG_ENABLE_ADAPT_RX_DRAIN, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMIN, + WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMAX, + WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STADEF}, + + {WNI_CFG_FLEX_CONNECT_POWER_FACTOR, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMIN, + WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMAX, + WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STADEF}, + + {WNI_CFG_ANTENNA_DIVESITY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_ANTENNA_DIVESITY_STAMIN, + WNI_CFG_ANTENNA_DIVESITY_STAMAX, + WNI_CFG_ANTENNA_DIVESITY_STADEF}, + + {WNI_CFG_GO_LINK_MONITOR_TIMEOUT, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMIN, + WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMAX, + WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STADEF}, + + {WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_HAL, + WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN, + WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX, + WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF}, + + {WNI_CFG_CURRENT_RSSI, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_CURRENT_RSSI_STAMIN, + WNI_CFG_CURRENT_RSSI_STAMAX, + WNI_CFG_CURRENT_RSSI_STADEF}, + + {WNI_CFG_RTT3_ENABLE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_RTT3_ENABLE_STAMIN, + WNI_CFG_RTT3_ENABLE_STAMAX, + WNI_CFG_RTT3_ENABLE_STADEF}, + + {WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMIN, + WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMAX, + WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STADEF}, + + {WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMIN, + WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMAX, + WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STADEF}, + + {WNI_CFG_IBSS_ATIM_WIN_SIZE, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMIN, + WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMAX, + WNI_CFG_IBSS_ATIM_WIN_SIZE_STADEF}, + + {WNI_CFG_DFS_MASTER_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_DFS_MASTER_ENABLED_STAMIN, + WNI_CFG_DFS_MASTER_ENABLED_STAMAX, + WNI_CFG_DFS_MASTER_ENABLED_STADEF}, + + {WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMIN, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMAX, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STADEF}, + + {WNI_CFG_TDLS_WMM_MODE_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | + CFG_CTL_NTF_LIM, + WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMIN, + WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX, + WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF} +}; + +struct cfgstatic_string cfg_static_string[CFG_MAX_STATIC_STRING] = { + {WNI_CFG_STA_ID, + WNI_CFG_STA_ID_LEN, + 6, + {0x22, 0x22, 0x44, 0x44, 0x33, 0x33}}, + + {WNI_CFG_SSID, + WNI_CFG_SSID_LEN, + 10, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, + + {WNI_CFG_WEP_DEFAULT_KEY_1, + WNI_CFG_WEP_DEFAULT_KEY_1_LEN, + 0, + {0}}, + + {WNI_CFG_WEP_DEFAULT_KEY_2, + WNI_CFG_WEP_DEFAULT_KEY_2_LEN, + 0, + {0}}, + + {WNI_CFG_WEP_DEFAULT_KEY_3, + WNI_CFG_WEP_DEFAULT_KEY_3_LEN, + 0, + {0}}, + + {WNI_CFG_WEP_DEFAULT_KEY_4, + WNI_CFG_WEP_DEFAULT_KEY_4_LEN, + 0, + {0}}, + + {WNI_CFG_SUPPORTED_RATES_11B, + WNI_CFG_SUPPORTED_RATES_11B_LEN, + 4, + {2, 4, 11, 22}}, + + {WNI_CFG_SUPPORTED_RATES_11A, + WNI_CFG_SUPPORTED_RATES_11A_LEN, + 8, + {12, 18, 24, 36, 48, 72, 96, 108}}, + + {WNI_CFG_OPERATIONAL_RATE_SET, + WNI_CFG_OPERATIONAL_RATE_SET_LEN, + 0, + {0}}, + + {WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN, + 0, + {0}}, + + {WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET, + WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET_LEN, + 4, + {1, 3, 5, 7}}, + + {WNI_CFG_VALID_CHANNEL_LIST, + WNI_CFG_VALID_CHANNEL_LIST_LEN, + 55, + {36, 40, 44, 48, 52, 56, 60, 64, 1, 6, 11, 34, 38, 42, 46, 2, 3, 4, 5, + 7, 8, 9, 10, 12, 13, 14, 100, 104, 108, 112, 116, 120, 124, 128, 132, + 136, 140, 149, 151, 153, 155, 157, 159, 161, 50, 54, 58, 62, 240, 242, + 244, 246, 248, 250, 252}}, + + {WNI_CFG_MANUFACTURER_OUI, + WNI_CFG_MANUFACTURER_OUI_LEN, + 3, + {0x0, 0xa, 0xf5}}, + + {WNI_CFG_MANUFACTURER_NAME, + WNI_CFG_MANUFACTURER_NAME_LEN, + 8, + {0x51, 0x75, 0x61, 0x6c, 0x63, 0x6f, 0x6d, 0x6d}}, + + {WNI_CFG_MODEL_NUMBER, + WNI_CFG_MODEL_NUMBER_LEN, + 6, + {0x4d, 0x4e, 0x31, 0x32, 0x33, 0x34}}, + + {WNI_CFG_MODEL_NAME, + WNI_CFG_MODEL_NAME_LEN, + 7, + {0x57, 0x46, 0x52, 0x34, 0x30, 0x33, 0x31}}, + + {WNI_CFG_MANUFACTURER_PRODUCT_NAME, + WNI_CFG_MANUFACTURER_PRODUCT_NAME_LEN, + 6, + {0x31, 0x31, 0x6e, 0x2d, 0x41, 0x50}}, + + {WNI_CFG_MANUFACTURER_PRODUCT_VERSION, + WNI_CFG_MANUFACTURER_PRODUCT_VERSION_LEN, + 6, + {0x53, 0x4e, 0x31, 0x32, 0x33, 0x34}}, + + {WNI_CFG_MAX_TX_POWER_2_4, + WNI_CFG_MAX_TX_POWER_2_4_LEN, + 3, + {0x1, 0xe, 0x14}}, + + {WNI_CFG_MAX_TX_POWER_5, + WNI_CFG_MAX_TX_POWER_5_LEN, + 3, + {0x24, 0x7e, 0x14}}, + + {WNI_CFG_AP_NODE_NAME, + WNI_CFG_AP_NODE_NAME_LEN, + 0, + {0}}, + + {WNI_CFG_COUNTRY_CODE, + WNI_CFG_COUNTRY_CODE_LEN, + 0, + {0}}, + + {WNI_CFG_EDCA_ANI_ACBK_LOCAL, + WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN, + 17, + {0x0, 0x7, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, 0x1f, 0x3, 0xff, 0x0, 0x0, + 0xf, 0x3, 0xff, 0x0}}, + + {WNI_CFG_EDCA_ANI_ACBE_LOCAL, + WNI_CFG_EDCA_ANI_ACBE_LOCAL_LEN, + 17, + {0x0, 0x2, 0x0, 0xf, 0x3, 0xff, 0x64, 0x0, 0x1f, 0x3, 0xff, 0x64, 0x0, + 0xf, 0x3, 0xff, 0x64}}, + + {WNI_CFG_EDCA_ANI_ACVI_LOCAL, + WNI_CFG_EDCA_ANI_ACVI_LOCAL_LEN, + 17, + {0x0, 0x2, 0x0, 0x7, 0x0, 0xf, 0xc8, 0x0, 0xf, 0x0, 0x1f, 0xbc, 0x0, + 0x7, 0x0, 0xf, 0xc8}}, + + {WNI_CFG_EDCA_ANI_ACVO_LOCAL, + WNI_CFG_EDCA_ANI_ACVO_LOCAL_LEN, + 17, + {0x0, 0x2, 0x0, 0x3, 0x0, 0x7, 0x64, 0x0, 0x7, 0x0, 0xf, 0x66, 0x0, + 0x3, 0x0, 0x7, 0x64}}, + + {WNI_CFG_EDCA_ANI_ACBK, + WNI_CFG_EDCA_ANI_ACBK_LEN, + 17, + {0x0, 0x7, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, 0x1f, 0x3, 0xff, 0x0, 0x0, + 0xf, 0x3, 0xff, 0x0}}, + + {WNI_CFG_EDCA_ANI_ACBE, + WNI_CFG_EDCA_ANI_ACBE_LEN, + 17, + {0x0, 0x2, 0x0, 0xf, 0x3, 0xff, 0x64, 0x0, 0x1f, 0x3, 0xff, 0x64, + 0x0, 0xf, 0x3, 0xff, 0x64}}, + + {WNI_CFG_EDCA_ANI_ACVI, + WNI_CFG_EDCA_ANI_ACVI_LEN, + 17, + {0x0, 0x2, 0x0, 0x7, 0x0, 0xf, 0xc8, 0x0, 0xf, 0x0, 0x1f, 0xbc, 0x0, + 0x7, 0x0, 0xf, 0xc8}}, + + {WNI_CFG_EDCA_ANI_ACVO, + WNI_CFG_EDCA_ANI_ACVO_LEN, + 17, + {0x0, 0x2, 0x0, 0x3, 0x0, 0x7, 0x64, 0x0, 0x7, 0x0, 0xf, 0x66, 0x0, + 0x3, 0x0, 0x7, 0x64}}, + + {WNI_CFG_EDCA_WME_ACBK_LOCAL, + WNI_CFG_EDCA_WME_ACBK_LOCAL_LEN, + 17, + {0x0, 0x7, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, 0x1f, 0x3, 0xff, 0x0, 0x0, + 0xf, 0x3, 0xff, 0x0}}, + + {WNI_CFG_EDCA_WME_ACBE_LOCAL, + WNI_CFG_EDCA_WME_ACBE_LOCAL_LEN, + 17, + {0x0, 0x3, 0x0, 0xf, 0x0, 0x3f, 0x0, 0x0, 0x1f, 0x3, 0xff,0x0, 0x0, + 0xf, 0x0, 0x3f, 0x0}}, + + {WNI_CFG_EDCA_WME_ACVI_LOCAL, + WNI_CFG_EDCA_WME_ACVI_LOCAL_LEN, + 17, + {0x0, 0x1, 0x0, 0x7, 0x0, 0xf, 0x5e, 0x0, 0x7, 0x0, 0xf, 0xbc, 0x0, + 0x7, 0x0, 0xf, 0x5e}}, + + {WNI_CFG_EDCA_WME_ACVO_LOCAL, + WNI_CFG_EDCA_WME_ACVO_LOCAL_LEN, + 17, + {0x0, 0x1, 0x0, 0x3, 0x0, 0x7, 0x2f, 0x0, 0x3, 0x0, 0x7, 0x66, 0x0, + 0x3, 0x0, 0x7, 0x2f}}, + + {WNI_CFG_EDCA_WME_ACBK, + WNI_CFG_EDCA_WME_ACBK_LEN, + 17, + {0x0, 0x7, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, + 0xf, 0x3, 0xff, 0x0}}, + + {WNI_CFG_EDCA_WME_ACBE, + WNI_CFG_EDCA_WME_ACBE_LEN, + 17, + {0x0, 0x3, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, 0xf, 0x3, 0xff, 0x0, 0x0, + 0xf, 0x3, 0xff, 0x0}}, + + {WNI_CFG_EDCA_WME_ACVI, + WNI_CFG_EDCA_WME_ACVI_LEN, + 17, + {0x0, 0x2, 0x0, 0x7, 0x0, 0xf, 0x5e, 0x0, 0x7, 0x0, 0xf, 0xbc, 0x0, + 0x7, 0x0, 0xf, 0x5e}}, + + {WNI_CFG_EDCA_WME_ACVO, + WNI_CFG_EDCA_WME_ACVO_LEN, + 17, + {0x0, 0x2, 0x0, 0x3, 0x0, 0x7, 0x2f, 0x0, 0x3, 0x0, 0x7, 0x66, 0x0, + 0x3, 0x0, 0x7, 0x2f}}, + + {WNI_CFG_RADAR_CHANNEL_LIST, + WNI_CFG_RADAR_CHANNEL_LIST_LEN, + 15, + {0x34, 0x38, 0x3c, 0x40, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, + 0x80, 0x84, 0x88, 0x8c}}, + + {WNI_CFG_SCAN_CONTROL_LIST, + WNI_CFG_SCAN_CONTROL_LIST_LEN, + 114, + {0x1, 0x1, 0x2, 0x1, 0x3, 0x1, 0x4, 0x1, 0x5, 0x1, 0x6, 0x1, 0x7, + 0x1, 0x8, 0x1, 0x9,0x1, 0xa, 0x1, 0xb, 0x1, 0xc, 0x1, 0xd, 0x1, + 0xe, 0x1, 0x22, 0x1, 0x24, 0x1, 0x26, 0x1, 0x28,0x1, 0x2a, 0x1, + 0x2c, 0x1, 0x2e, 0x1, 0x30, 0x1, 0x32, 0x1, 0x34, 0x0, 0x36, 0x0, + 0x38, 0x0,0x3a, 0x0, 0x3c, 0x0, 0x3e, 0x0, 0x40, 0x0, 0x64, 0x0, + 0x68, 0x0, 0x6c, 0x0, 0x70, 0x0, 0x74,0x0, 0x78, 0x0, 0x7c, 0x0, + 0x80, 0x0, 0x84, 0x0, 0x88, 0x0, 0x8c, 0x0, 0x90, 0x0, 0x95, 0x1, + 0x97, 0x1, 0x99, 0x1, 0x9b, 0x1, 0x9d, 0x1, 0x9f, 0x1, 0xa1, 0x1, + 0xa5, 0x1, 0xf0, 0x1, 0xf2, 0x1, 0xf4, 0x1, 0xf6, 0x1, 0xf8, 0x1, + 0xfa, 0x1, 0xfc, 0x1}}, + + {WNI_CFG_SUPPORTED_MCS_SET, + WNI_CFG_SUPPORTED_MCS_SET_LEN, + 16, + {0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0}}, + + {WNI_CFG_BASIC_MCS_SET, + WNI_CFG_BASIC_MCS_SET_LEN, + 16, + {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0}}, + + {WNI_CFG_CURRENT_MCS_SET, + WNI_CFG_CURRENT_MCS_SET_LEN, + 16, + {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0}}, + + {WNI_CFG_BG_SCAN_CHANNEL_LIST, + WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN, + 55, + {0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,0x40, 0x1, 0x6, 0xb, 0x22, + 0x26, 0x2a, 0x2e, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8, 0x9, 0xa, 0xc, 0xd, + 0xe, 0x64, 0x68, 0x6c, 0x70, 0x74,0x78, 0x7c, 0x80, 0x84, 0x88, 0x8c, + 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9f, 0xa1, 0x32, 0x36,0x3a, 0x3e, 0xf0, + 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc}}, + + {WNI_CFG_PROBE_REQ_ADDNIE_DATA, + WNI_CFG_PROBE_REQ_ADDNIE_DATA_LEN, + 0, + {0}}, + + {WNI_CFG_PROBE_RSP_ADDNIE_DATA1, + WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN, + 0, + {0}}, + + {WNI_CFG_PROBE_RSP_ADDNIE_DATA2, + WNI_CFG_PROBE_RSP_ADDNIE_DATA2_LEN, + 0, + {0}}, + + {WNI_CFG_PROBE_RSP_ADDNIE_DATA3, + WNI_CFG_PROBE_RSP_ADDNIE_DATA3_LEN, + 0, + {0}}, + + {WNI_CFG_ASSOC_RSP_ADDNIE_DATA, + WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN, + 0, + {0}}, + + {WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA, + WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA_LEN, + 0, + {0}}, + + {WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, + WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN, + 0, + {0}}, + + {WNI_CFG_WPS_UUID, + WNI_CFG_WPS_UUID_LEN, + 6, + {0xa, 0xb, 0xc, 0xd, 0xe, 0xf}} +}; + +/*--------------------------------------------------------------------*/ +/* Static function prototypes */ +/*--------------------------------------------------------------------*/ +static void ProcDnldRsp (tpAniSirGlobal, tANI_U16, tANI_U32*); +static void ProcGetReq (tpAniSirGlobal, tANI_U16, tANI_U32*); +static void ProcSetReq (tpAniSirGlobal, tANI_U16, tANI_U32*); +static void ProcSetReqNoRsp (tpAniSirGlobal, tANI_U16, tANI_U32*); + +static tANI_U8 CheckParam(tpAniSirGlobal, tANI_U16, tANI_U32, tANI_U32, tANI_U32*); +static void GetStrValue(tANI_U8*, tANI_U8*, tANI_U32); + + +/*--------------------------------------------------------------------*/ +/* Module global variables */ +/*--------------------------------------------------------------------*/ + +// CFG function table +void (*gCfgFunc[])(tpAniSirGlobal, tANI_U16, tANI_U32*) = +{ ProcDnldRsp, + ProcGetReq, + ProcSetReq, + ProcSetReqNoRsp +}; + +/**--------------------------------------------------------------------- + * cfgProcessMbMsg() + * + *FUNCTION: + * CFG mailbox message processing function. + * + *LOGIC: + * + *ASSUMPTIONS: + * None. + * + *NOTE: + * + * @param pMsg Message pointer + * + * @return None. + * + */ +void +cfgProcessMbMsg(tpAniSirGlobal pMac, tSirMbMsg *pMsg) +{ + tANI_U16 index; + tANI_U16 len; + tANI_U32 *pParam; + + // Use type[7:0] as index to function table + index = CFG_GET_FUNC_INDX(pMsg->type); + + if (index >= (sizeof(gCfgFunc) / sizeof(gCfgFunc[0]))) + { + vos_mem_free(pMsg); + return; + } + len = pMsg->msgLen - WNI_CFG_MB_HDR_LEN; + pParam = ((tANI_U32*)pMsg) + 1; + + // Call processing function + gCfgFunc[index](pMac, len, pParam); + + // Free up buffer + vos_mem_free(pMsg); + +} /*** end cfgProcessMbMsg() ***/ + +/**--------------------------------------------------------------------- + * ProcDnldRsp() + * + * FUNCTION: + * This function processes CFG_DNLD_RSP message from host. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param length: message length + * @param pParam: parameter list pointer + * + * @return None + * + */ +static void +ProcDnldRsp(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam) +{ + tANI_S32 i; + + tANI_U32 expLen, retVal, bufStart, bufEnd; + tANI_U32 *pSrc, *pDst, *pDstEnd; + tANI_U32 strSize, j; + tANI_U8 pStr[CFG_MAX_STR_LEN]; + tpCfgBinHdr pHdr; + tANI_U32 logLevel; + tSirMsgQ mmhMsg; + tANI_U32 param_list[WNI_CFG_DNLD_CNF_NUM]; + + // First Dword must contain the AP or STA magic dword + PELOGW(cfgLog(pMac, LOGW, FL("CFG size %d bytes MAGIC dword is 0x%x"), + length, sirReadU32N((tANI_U8*)pParam) );) + + // if the string is not correct, return failure + if (*pParam == CFG_STA_MAGIC_DWORD) {} + + + + + else + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid magic dword 0x%x"),sirReadU32N((tANI_U8*)pParam) );) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + + pParam++; + length -= 4; + + // Verify message length + { + pMac->cfg.gCfgMaxIBufSize = CFG_STA_IBUF_MAX_SIZE; + pMac->cfg.gCfgMaxSBufSize = CFG_STA_SBUF_MAX_SIZE; + } + + // Parse the Cfg header + pHdr = (tpCfgBinHdr) pParam; + pParam += (sizeof(tCfgBinHdr) >> 2); + PELOGW(cfgLog(pMac, LOGW, FL("CFG hdr totParams %d intParams %d strBufSize %d/%d"), + pHdr->controlSize, pHdr->iBufSize, pHdr->sBufSize, pMac->cfg.gCfgMaxSBufSize);) + + expLen = ((CFG_PARAM_MAX_NUM + 3 * pMac->cfg.gCfgMaxIBufSize) << 2) + + pHdr->sBufSize + sizeof(tCfgBinHdr); + + if (length != expLen) + { + PELOGE(cfgLog(pMac, LOGE, FL(" DNLD_RSP invalid length %d (exp %d)"), + length, expLen);) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + + + if (pHdr->controlSize != CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL(" Total parameter count mismatch"));) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + + if (pHdr->iBufSize != pMac->cfg.gCfgMaxIBufSize) + { + PELOGE(cfgLog(pMac, LOGE, FL(" Integer parameter count mismatch"));) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + + // Copy control array + pDst = (tANI_U32*)pMac->cfg.gCfgEntry; + pDstEnd = pDst + CFG_PARAM_MAX_NUM; + pSrc = pParam; + while (pDst < pDstEnd) + { + *pDst++ = *pSrc++; + } + // Copy default values + pDst = pMac->cfg.gCfgIBuf; + pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize; + while (pDst < pDstEnd) + { + *pDst++ = *pSrc++; + } + + // Copy min values + pDst = pMac->cfg.gCfgIBufMin; + pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize; + while (pDst < pDstEnd) + { + *pDst++ = *pSrc++; + } + + // Copy max values + pDst = pMac->cfg.gCfgIBufMax; + pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize; + while (pDst < pDstEnd) + { + *pDst++ = *pSrc++; + } + + for (i=0; icfg.gCfgMaxIBufSize; i++) + if (pMac->cfg.gCfgIBuf[i] < pMac->cfg.gCfgIBufMin[i] || + pMac->cfg.gCfgIBuf[i] > pMac->cfg.gCfgIBufMax[i]) + { + PELOGE(cfgLog(pMac, LOGE, FL("cfg id %d Invalid def value %d " + "min %d max %d"), + i, pMac->cfg.gCfgIBuf[i], pMac->cfg.gCfgIBufMin[i], + pMac->cfg.gCfgIBufMax[i]);) + } + + // Calculate max string buffer lengths for all string parameters + bufEnd = pMac->cfg.gCfgMaxSBufSize; + for (i = CFG_PARAM_MAX_NUM - 1; i >= 0; i--) + { + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_INT) != 0) + continue; + + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0) + continue; + + bufStart = pMac->cfg.gCfgEntry[i].control & CFG_BUF_INDX_MASK; + pMac->cfg.gCfgSBuf[bufStart] = (tANI_U8)(bufEnd - bufStart - 2); + + PELOG1(cfgLog(pMac, LOG1, FL("id %d max %d bufStart %d bufEnd %d"), + i, pMac->cfg.gCfgSBuf[bufStart], bufStart, bufEnd);) + + bufEnd = bufStart; + } + + // Initialize string defaults + strSize = pHdr->sBufSize; + while (strSize) + { + tANI_U32 paramId, paramLen, paramLenCeil4; + + if (strSize < 4) + { + PELOGE(cfgLog(pMac, LOGE, FL("Error parsing str defaults, rem %d bytes"), strSize);) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + paramId = *pSrc >> 16; + paramLen = *pSrc & 0xff; + pSrc++; + strSize -= 4; + + paramLenCeil4 = ((paramLen + 3) >> 2); + if (strSize < paramLenCeil4 << 2) + { + PELOGE(cfgLog(pMac, LOGE, FL("Error parsing str defaults, rem %d bytes"), strSize);) + PELOGE(cfgLog(pMac, LOGE, FL("param id %d len %d bytes"), paramId, paramLen);) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + for (j=0; j < paramLenCeil4; j++) + { + pStr[4*j] = (tANI_U8) (*pSrc >> 24) & 0xff; + pStr[4*j+1] = (tANI_U8) (*pSrc >> 16) & 0xff; + pStr[4*j+2] = (tANI_U8) (*pSrc >> 8) & 0xff; + pStr[4*j+3] = (tANI_U8) (*pSrc) & 0xff; + + pSrc++; + strSize -= 4; + } + + PELOG1(cfgLog(pMac, LOG1, FL("set str id %d len %d"), paramId, paramLen);) + + if (cfgSetStr(pMac, (tANI_U16) paramId, pStr, paramLen) != eSIR_SUCCESS) + { + PELOGE(cfgLog(pMac, LOGE, FL("Error setting str default param %d len %d"), paramId, paramLen);) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + } + + // Set the default log level based on config + wlan_cfgGetInt(pMac, WNI_CFG_LOG_LEVEL, &logLevel); + for (i = 0; i < LOG_ENTRY_NUM; i++) + pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = logLevel; + + // Set status to READY + pMac->cfg.gCfgStatus = CFG_SUCCESS; + retVal = WNI_CFG_SUCCESS; + PELOG1(cfgLog(pMac, LOG1, " Completed successfully");) + + end: + + if ( retVal != WNI_CFG_SUCCESS ) + pMac->cfg.gCfgStatus = CFG_FAILURE; + + // Send response message to host + param_list[WNI_CFG_DNLD_CNF_RES] = retVal; + cfgSendHostMsg(pMac, WNI_CFG_DNLD_CNF, WNI_CFG_DNLD_CNF_LEN, + WNI_CFG_DNLD_CNF_NUM, param_list, 0, 0); + + // Notify WDA that the config has downloaded + mmhMsg.type = SIR_CFG_DOWNLOAD_COMPLETE_IND; + mmhMsg.bodyptr = NULL; + mmhMsg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + if (wdaPostCtrlMsg(pMac, &mmhMsg) != eSIR_SUCCESS) + { + PELOGE(cfgLog(pMac, LOGE, FL("WDAPostMsgApi failed!"));) + } + +} /*** end procDnldRsp() ***/ + + +/**--------------------------------------------------------------------- + * ProcGetReq() + * + * FUNCTION: + * This function processes CFG_GET_REQ message from host. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * For every parameter ID specified on the list, CFG will send a separate + * CFG_GET_RSP back to host. + * + * @param length: message length + * @param pParam: parameter list pointer + * + * @return None + * + */ +static void +ProcGetReq(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam) +{ + tANI_U16 cfgId, i; + tANI_U32 value, valueLen, result; + tANI_U32 *pValue; + tANI_U32 param_list[WNI_CFG_GET_RSP_NUM]; + + PELOG1(cfgLog(pMac, LOG1, FL("Rcvd cfg get request %d bytes"), length);) + for (i=0; icfg.gCfgStatus) + { + cfgId = (tANI_U16)sirReadU32N((tANI_U8*)pParam); + PELOGE(cfgLog(pMac, LOGE, FL("CFG not ready, param %d"), cfgId);) + param_list[WNI_CFG_GET_RSP_RES] = WNI_CFG_NOT_READY; + param_list[WNI_CFG_GET_RSP_PID] = cfgId; + param_list[WNI_CFG_GET_RSP_PLEN] = 0; + cfgSendHostMsg(pMac, WNI_CFG_GET_RSP, WNI_CFG_GET_RSP_PARTIAL_LEN, + WNI_CFG_GET_RSP_NUM, param_list, 0, 0); + } + else + { + // Process all parameter ID's on the list + while (length >= sizeof(tANI_U32)) + { + cfgId = (tANI_U16)*pParam++; + pValue = 0; + valueLen = 0; + + PELOG1(cfgLog(pMac, LOG1, FL("Cfg get param %d"), cfgId);) + + // Check for valid parameter ID, etc... + if (CheckParam(pMac, cfgId, CFG_CTL_RE, WNI_CFG_WO_PARAM, &result)) + { + if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_INT) != 0) + { + // Get integer parameter + result = (wlan_cfgGetInt(pMac, cfgId, &value) == eSIR_SUCCESS ? + WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR); + pValue = &value; + valueLen = sizeof(tANI_U32); + } + else + { + // Get string parameter + valueLen = sizeof(pMac->cfg.gSBuffer); + result = (wlan_cfgGetStr(pMac, cfgId, pMac->cfg.gSBuffer, &valueLen) + == eSIR_SUCCESS ? + WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR); + pValue = (tANI_U32*)pMac->cfg.gSBuffer; + } + } + else + { + PELOGE(cfgLog(pMac, LOGE, FL("Check param failed, param %d"), cfgId);) + result = WNI_CFG_INVALID_LEN; + } + + // Send response message to host + param_list[WNI_CFG_GET_RSP_RES] = result; + param_list[WNI_CFG_GET_RSP_PID] = cfgId; + param_list[WNI_CFG_GET_RSP_PLEN] = valueLen; + + // We need to round up buffer length to word-increment + valueLen = (((valueLen + 3) >> 2) << 2); + cfgSendHostMsg(pMac, WNI_CFG_GET_RSP, + WNI_CFG_GET_RSP_PARTIAL_LEN + valueLen, + WNI_CFG_GET_RSP_NUM, param_list, valueLen, pValue); + + // Decrement length + length -= sizeof(tANI_U32); + } + } + +} /*** end procGetReq() ***/ + + + +/**--------------------------------------------------------------------- + * ProcSetReqInternal() + * + * FUNCTION: + * This function processes CFG_SET_REQ message from host. + * + * LOGIC: + * + * ASSUMPTIONS: + * - The message content is coded in TLV format. + * - For string parameter, the length field is byte accurate. However, + * the next TLV set will begin on the next word boundary. + * + * NOTE: + * - For every parameter ID specified on the list, CFG will send a separate + * CFG_SET_RSP back to host. + * + * @param length: message length + * @param pParam: parameter list pointer + * @param fRsp: whether to send response to host. TRUE means sending. + * @return None + * + */ +static void +ProcSetReqInternal(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam, tANI_BOOLEAN fRsp) +{ + tANI_U16 cfgId, valueLen, valueLenRoundedUp4; + tANI_U32 value, result; + tANI_U32 param_list[WNI_CFG_SET_CNF_NUM]; + + PELOG1(cfgLog(pMac, LOGl, FL("Rcvd cfg set request %d bytes"), length);) + + if (!pMac->cfg.gCfgStatus) + { + cfgId = (tANI_U16)sirReadU32N((tANI_U8*)pParam); + PELOG1(cfgLog(pMac, LOGW, FL("CFG not ready, param %d"), cfgId);) + if( fRsp ) + { + param_list[WNI_CFG_SET_CNF_RES] = WNI_CFG_NOT_READY; + param_list[WNI_CFG_SET_CNF_PID] = cfgId; + cfgSendHostMsg(pMac, WNI_CFG_SET_CNF, WNI_CFG_SET_CNF_LEN, + WNI_CFG_SET_CNF_NUM, param_list, 0, 0); + } + } + else + { + // Process all TLVs in buffer + while (length >= (sizeof(tANI_U32) * 2)) + { + cfgId = (tANI_U16) *pParam++; + valueLen = (tANI_U16) *pParam++; + length -= (sizeof(tANI_U32) * 2); + // value length rounded up to a 4 byte multiple + valueLenRoundedUp4 = (((valueLen + 3) >> 2) << 2); + + // Check for valid request before proceeding + if (CheckParam(pMac, cfgId, CFG_CTL_WE, WNI_CFG_RO_PARAM, &result)) + { + PELOG1(cfgLog(pMac, LOGW, (char *) gCfgParamName[cfgId]);) + // Process integer parameter + if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_INT) != 0) + { + // Set VALUE + if (valueLen != sizeof(tANI_U32)) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid value length %d in set param %d (tot %d)"), + valueLen, cfgId, length);) + result = WNI_CFG_INVALID_LEN; + } + else + { + value = *pParam; + PELOG1(cfgLog(pMac, LOGW, FL("Cfg set int %d len %d(%d) val %d"), + cfgId, valueLen, valueLenRoundedUp4, value);) + result = (cfgSetInt(pMac, cfgId, value) == eSIR_SUCCESS ? + WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR); + if (result == WNI_CFG_SUCCESS) + { + if (cfgNeedRestart(pMac, cfgId)) + { + result = WNI_CFG_NEED_RESTART ; + } + else + if (cfgNeedReload(pMac, cfgId)) + { + result = WNI_CFG_NEED_RELOAD ; + } + } + } + } + // Process string parameter + else + { + if (valueLenRoundedUp4 > length) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid string length %d" + "in set param %d (tot %d)"), valueLen, + cfgId, length);) + result = WNI_CFG_INVALID_LEN; + } + else + { + GetStrValue((tANI_U8*)pParam, pMac->cfg.gSBuffer, valueLen); + PELOG1(cfgLog(pMac, LOGW, FL("Cfg set str %d len %d(%d) bytes"), + cfgId, valueLen, valueLenRoundedUp4);) + result = (cfgSetStr(pMac, cfgId, pMac->cfg.gSBuffer, valueLen) == eSIR_SUCCESS ? + WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR); + if (result == WNI_CFG_SUCCESS) + { + if (cfgNeedRestart(pMac, cfgId)) + { + result = WNI_CFG_NEED_RESTART ; + } + else + if (cfgNeedReload(pMac, cfgId)) + { + result = WNI_CFG_NEED_RELOAD ; + } + } + } + } + } + else + { + PELOGE(cfgLog(pMac, LOGE, FL("Check param failed, param %d"), cfgId);) + result = WNI_CFG_INVALID_LEN; + } + + if( fRsp ) + { + /* Send confirm message to host */ + param_list[WNI_CFG_SET_CNF_RES] = result; + param_list[WNI_CFG_SET_CNF_PID] = cfgId; + cfgSendHostMsg(pMac, WNI_CFG_SET_CNF, WNI_CFG_SET_CNF_LEN, + WNI_CFG_SET_CNF_NUM, param_list, 0, 0); + } + else + { + PELOGW(cfgLog( pMac, LOG2, " CFGID %d no rsp", cfgId);) + } + + if (valueLenRoundedUp4 > length) + length = 0; + else + { + length -= valueLenRoundedUp4; + pParam += (valueLenRoundedUp4 >> 2); + } + } + } +} + + + +static void +ProcSetReq(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam) +{ + ProcSetReqInternal( pMac, length, pParam, eANI_BOOLEAN_TRUE ); +} + +static void +ProcSetReqNoRsp(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam) +{ + ProcSetReqInternal( pMac, length, pParam, eANI_BOOLEAN_FALSE ); +} + + + +/**--------------------------------------------------------------------- + * CheckParam() + * + * FUNCTION: + * This function is called to perform various check on a parameter. + * + * LOGIC: + * - If cfgId is out of bound or parameter is not valid, result + * WNI_CFG_INVALID_PID is returned at address specified in pResult. + * + * - If specified 'flag' is not set in the parameter control entry, + * 'failedResult' is returned at address specified in pResult. + * + * ASSUMPTIONS: + * Since this function is used internally, 'pResult' is always valid. + * + * NOTE: + * + * @param None + * + * @return true: Parameter is valid and matches checked condition \n + * @return false: Parameter either is not valid or does not match + * checked condition. + * + */ +static tANI_U8 +CheckParam(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 flag, tANI_U32 failedResult, tANI_U32 *pResult) +{ + // Check if parameter ID is out of bound + if (cfgId >= CFG_PARAM_MAX_NUM) + { + PELOGE(cfgLog(pMac, LOGE, FL("Invalid param id %d"), cfgId);) + *pResult = WNI_CFG_INVALID_PID; + } + else + { + // Check if parameter is valid + if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_VALID) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Param id %d not valid"), cfgId);) + *pResult = WNI_CFG_INVALID_PID; + } + else + { + // Check control field against flag + if ((pMac->cfg.gCfgEntry[cfgId].control & flag) == 0) + { + PELOGE(cfgLog(pMac, LOGE, FL("Param id %d wrong permissions %x"), + cfgId, pMac->cfg.gCfgEntry[cfgId].control);) + *pResult = failedResult; + } + else + return(true); + } + } + return(false); + +} /*** cfgParamCheck() ***/ + + +/**--------------------------------------------------------------------- + * GetStrValue() + * + * FUNCTION: + * This function copies a string value from the specified buffer. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pBuf: input data buffer + * @param pValue: address where data is returned + * @param length: number of bytes to copy + * + * @return None + * + */ +static void +GetStrValue(tANI_U8 *pBuf, tANI_U8 *pValue, tANI_U32 length) +{ + tANI_U8 *pEnd; + + pEnd = pValue + length; + while (pValue < pEnd) + *pValue++ = *pBuf++; +} /*** end GetStrValue() ***/ + + +/**--------------------------------------------------------------------- + * processCfgDownloadReq() + * + * FUNCTION: This function reads the cfg_static array and + * populates the cfg data structure. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac: Pointer to Mac Structure + * + * @return None + * + */ + +void +processCfgDownloadReq(tpAniSirGlobal pMac) +{ + int32_t i; + uint32_t index; + uint8_t *dst_ptr, *src_ptr; + uint8_t len; + struct cfgstatic_string *str_cfg; + uint32_t buf_start, buf_end, log_level, ret_val; + uint32_t icount = 0; + uint32_t scount = 0; + + for (i = 0; i < CFG_PARAM_MAX_NUM ; i++) { + if ((cfg_static[i].control & CFG_CTL_VALID) != 0) { + if (!(cfg_static[i].control & CFG_CTL_INT)) { + str_cfg = (struct cfgstatic_string *)cfg_static[i].p_str_data; + if (str_cfg == NULL) { + PELOGE(cfgLog(pMac, LOGE, + FL("str_cfg is NULL for ConfigID : %d"), + i);) + continue; + } + index = scount & CFG_BUF_INDX_MASK; + scount += str_cfg->max_len + 1 + 1; + } else { + index = icount & CFG_BUF_INDX_MASK; + icount++; + } + } else { + index = 0; + } + + pMac->cfg.gCfgEntry[i].control = cfg_static[i].control | index; + } + + /*Fill the SBUF wih maxLength*/ + buf_end = pMac->cfg.gCfgMaxSBufSize; + + for (i = CFG_PARAM_MAX_NUM - 1; i >= 0; i--) + { + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_INT) != 0) + continue; + + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0) + continue; + + buf_start = pMac->cfg.gCfgEntry[i].control & CFG_BUF_INDX_MASK; + pMac->cfg.gCfgSBuf[buf_start] = (tANI_U8)(buf_end - buf_start - 2); + + PELOG1(cfgLog(pMac, LOG1, FL("id %d max %d buf_start %d buf_end %d"), + i, pMac->cfg.gCfgSBuf[buf_start], buf_start, buf_end);) + + buf_end = buf_start; + } + + for (i = 0; i < CFG_PARAM_MAX_NUM ; i++) { + index = pMac->cfg.gCfgEntry[i].control & CFG_BUF_INDX_MASK; + + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_INT) != 0) { + pMac->cfg.gCfgIBufMin[index] = cfg_static[i].cfg_imin; + pMac->cfg.gCfgIBufMax[index] = cfg_static[i].cfg_imax; + pMac->cfg.gCfgIBuf[index] = cfg_static[i].cfg_ival; + } else { + uint8_t max_saved_len; + + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0) + continue; + + if (index >= CFG_STA_SBUF_MAX_SIZE) + continue; + + dst_ptr = &pMac->cfg.gCfgSBuf[index]; + str_cfg = (struct cfgstatic_string *)cfg_static[i].p_str_data; + src_ptr = str_cfg->data; + + if ((dst_ptr == NULL) || (str_cfg == NULL) || (src_ptr == NULL)) + continue; + + max_saved_len = *dst_ptr; + len = str_cfg->length; + if (len > max_saved_len) + continue; + + *dst_ptr++ = str_cfg->max_len; + *dst_ptr++ = len; + while (len) { + *dst_ptr++ = *src_ptr++; + len--; + } + } + } + + // Set the default log level based on config + wlan_cfgGetInt(pMac, WNI_CFG_LOG_LEVEL, &log_level); + for (i = 0; i < LOG_ENTRY_NUM; i++) + pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = log_level; + + // Set status to READY + pMac->cfg.gCfgStatus = CFG_SUCCESS; + ret_val = WNI_CFG_SUCCESS; + PELOG1(cfgLog(pMac, LOG1, " Completed successfully");) +} /*** end ProcessDownloadReq() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgSendMsg.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgSendMsg.c new file mode 100644 index 000000000000..9540d20a71f2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgSendMsg.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file contains the source code for composing and sending messages + * to host. + * + * Author: Kevin Nguyen + * Date: 04/09/02 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + */ +#include "palTypes.h" +#include "cfgPriv.h" +#include "limTrace.h" +#include "cfgDebug.h" + +extern void SysProcessMmhMsg(tpAniSirGlobal pMac, tSirMsgQ* pMsg); + +/*--------------------------------------------------------------------*/ +/* ATTENTION: The functions contained in this module are to be used */ +/* by CFG module ONLY. */ +/*--------------------------------------------------------------------*/ + + +/**--------------------------------------------------------------------- + * cfgSendHostMsg() + * + * FUNCTION: + * Send CNF/RSP to host. + * + * LOGIC: + * Please see Configuration & Statistic Collection Micro-Architecture + * specification for details. + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param msgType: message type + * @param msgLen: message length + * @param paramNum: number of parameters + * @param pParamList: pointer to parameter list + * @param dataLen: data length + * @param pData: pointer to additional data + * + * @return None. + * + */ +void +cfgSendHostMsg(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 msgLen, tANI_U32 paramNum, tANI_U32 *pParamList, + tANI_U32 dataLen, tANI_U32 *pData) +{ + tANI_U32 *pMsg, *pEnd; + tSirMsgQ mmhMsg; + + // sanity + if ((paramNum > 0) && (NULL == pParamList)) + { + PELOGE(cfgLog(pMac, LOGE, + FL("pParamList NULL when paramNum greater than 0!"));) + return; + } + if ((dataLen > 0) && (NULL == pData)) + { + PELOGE(cfgLog(pMac, LOGE, + FL("pData NULL when dataLen greater than 0!"));) + return; + } + + // Allocate message buffer + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + { + PELOGE(cfgLog(pMac, LOGE, + FL("Memory allocation failure!"));) + return; + } + + // Fill in message details + mmhMsg.type = msgType; + mmhMsg.bodyptr = pMsg; + mmhMsg.bodyval = 0; + ((tSirMbMsg*)pMsg)->type = msgType; + ((tSirMbMsg*)pMsg)->msgLen = (tANI_U16)msgLen; + + switch (msgType) + { + case WNI_CFG_GET_RSP: + case WNI_CFG_PARAM_UPDATE_IND: + case WNI_CFG_DNLD_REQ: + case WNI_CFG_DNLD_CNF: + case WNI_CFG_SET_CNF: + // Fill in parameters + pMsg++; + if (NULL != pParamList) + { + pEnd = pMsg + paramNum; + while (pMsg < pEnd) + { + *pMsg++ = *pParamList++; + } + } + // Copy data if there is any + if (NULL != pData) + { + pEnd = pMsg + (dataLen >> 2); + while (pMsg < pEnd) + { + *pMsg++ = *pData++; + } + } + break; + + default: + PELOGE(cfgLog(pMac, LOGE, + FL("Unknown msg %d!"), (int) msgType);) + vos_mem_free( pMsg); + return; + } + + // Ship it + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + SysProcessMmhMsg(pMac, &mmhMsg); + +} /*** end cfgSendHostMsg() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/cfg.txt b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/cfg.txt new file mode 100644 index 000000000000..9171aac41fd8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/cfg.txt @@ -0,0 +1,4416 @@ +* Copyright (c) 2014 The Linux Foundation. All rights reserved. +* +* Previously licensed under the ISC license by Qualcomm Atheros, Inc. +* +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. + +* This file was originally distributed by Qualcomm Atheros, Inc. +* under proprietary terms before Copyright ownership was assigned +* to the Linux Foundation. + +* +* This is the data definition file for the CFG module. +* Author: Kevin Nguyen +* Date: 03/18/02 +* History:- +* 03/18/02 Created. +* 08/10/05 ww: add maoe channels to have a complete channel listing: (see WNI_CFG_VALID_CHANNEL_LIST) +* 08/10/05 ww: WNI_CFG_SCAN_CONTROL_LIST has a new contents +* -------------------------------------------------------------------- + +********************************************************************** +* +* This file contains the descriptions of all configuration parameters +* for both STA and AP. +* +* OUTPUT: +* ------- +* The output files are: +* wniCfgSta.h - C header file for STA mode only +* wniCfgAp.h - C header file for both STA and AP +* wniCfgSta.bin - Control and default values for STA system +* wniCfgAp.bin - Control and default values for AP system +* +* PARAMETER DESCRIPTION: +* ---------------------- +* For each parameter, the description must be on separate lines and +* exactly as specified below. [] are comments and should not be included. +* +* [Common info] parameter_name type maxLen semIndx +* [STA flags] valid RW P/NP RESTART/RELOAD +* [STA_NTF] notification_mask +* [STA values] min max value [for integer] +* length byte1 byte2 ... [for string] +* [AP flags] valid RW/RO/WO P/NP RESTART/RELOAD +* [AP_NTF] notification_mask +* [AP values] min max value [for integer] +* length byte1 byte2 ... [for string] +* +* parameter_name: +* This will be used as the base name for C macro definition. +* Therefore, C syntax rule must be observed. +* +* type: +* Specifies parameter type +* S - variable-length string +* I - integer +* +* maxLen: +* Specifies maximum parameter length in bytes. +* +* semIndx: +* Specifies semaphore index to use for locking this parameter. +* More than one parameters (those belonging to the same group) +* can share the same semaphore index. +* +* valid: +* Specifies if this parameter will be valid in current mode. +* V - Valid +* NV - Not valid +* +* RW: +* Specifies Read/Write mode. +* RO - Read only +* RW - Read/Write +* WO - Write only +* XX - Not accessible from host +* +* P: +* Specifies persistent memory option +* P - Save to persistent memory +* NP - No save +* +* RELOAD: +* Specifies whether setting this requires reloading the MAC module +* This attribute can be changed only when SME is in OFFLINE or SUSPEND(OFFLINE) state +* +* RESTART: +* Specifies whether setting this requires (re)assoc at STA and restart at AP +* This attribute can be changed only when SME is in OFFLINE, SUSPEND(OFFLINE), +* IDLE or SUSPEND(IDLE) states +* +* STA_notification: +* Lists modules to be notified in STA mode. Valid modules are: +* HDD, LIM, SCH, ARQ, DPH, NIM, SP, RFP, RHP, TFP. More than one +* modules can be listed on the same line using space or tab as the +* separator. If no notification is required, 'NONE' must be specified. +* +* AP_notification: +* Lists module to be notified in AP mode. Valid modules are: +* HDD, LIM, SCH, ARQ, DPH, NIM, SP, RFP, RHP, TFP. More than one +* modules can be listed on the same line using space or tab as the +* separator. If no notification is required, 'NONE' must be specified. +* +* STA/AP integer values: +* min: +* Specifies minimum value for an integer parameter. This field is +* ignored if the parameter type is string. However, this field must +* not be omitted. +* +* max: +* Specifies maximum value for an integer parameter. This field is +* ignored if the parameter type is string. However, this field must +* not be omitted. +* +* default: +* Specifies default value for an integer parameter. This field is +* ignored if the parameter type is string. However, this field must +* not be omitted. +* +* STA/AP string values: +* len: +* The actual length of the string +* +* bytei: +* byte i of the string where i varies from 1 to len +* +* TABLE GENERATION: +* ----------------- +* Table can be generated using keywords '#TABLE' and '#END' as below: +* +* #TABLE table_name number_of_row +* WNI_CFG_xxxx +* ....... +* ....... +* #END +* +* The CFG utility will generate the following output: +* WNI_CFG_table_xxx_ID xxx +* WNI_CFG_table_xxx_ROW number_of_rows +* WNI_CFG_table_xxx_COL number_of_columns +* +* These will be followed by the parameter definition for each entry in +* the table. Table is organized in column-major order. +* +* #ENTRY_VALUES 1 +* 0 4 1 +* 0 0 0 +* #ENTRY_VALUES 2 +* 0 4 2 +* 0 0 0 +* #ENTRY_VALUES 3 +* 0 4 3 +* 0 0 0 +* #ENTRY_VALUES 4 +* 0 4 4 +* 0 0 0 +* +* +* ENUMERATION +* ----------- +* Enumerations can be define using keyword '#ENUM' +* +* #ENUM xxx val +* +* The cfg utility will generate the following output in the header file +* #define paramname_xxx val +* + + +* +* Station ID (changing requires restart) +* + +WNI_CFG_STA_ID S 6 1 +V RW NP RELOAD +HAL +6 0x22 0x22 0x44 0x44 0x33 0x33 +V RW NP RELOAD +HAL +6 0x22 0x22 0x11 0x11 0x33 0x33 + +* +* CF Pollable +* + +WNI_CFG_CF_POLLABLE I 4 1 +NV RO NP RESTART +NONE +0 0 0 +V RO NP RESTART +NONE +0 1 0 + +* +* CFP Period +* + +WNI_CFG_CFP_PERIOD I 4 1 +V RO NP +NONE +0 255 1 +V RW NP +SCH +0 255 1 + +* +* CFP Max Duration +* + +WNI_CFG_CFP_MAX_DURATION I 4 1 +V RO NP +NONE +0 65535 30000 +V RW NP +HAL +0 65535 30000 + +* +* SSID (changing requires restart) +* + +WNI_CFG_SSID S 32 1 +V RW NP RESTART +NONE +10 1 2 3 4 5 6 7 8 9 0 +V RW NP RESTART +NONE +10 1 2 3 4 5 6 7 8 9 0 + +* +* Beacon Period +* Can't be changed on STA in infrastructure, ignore notification at SCH +* + +WNI_CFG_BEACON_INTERVAL I 4 2 +V RW NP +SCH +0 65535 100 +V RW NP +SCH +0 65535 100 + +* +* DTIM Period +* + +WNI_CFG_DTIM_PERIOD I 4 2 +V RO NP +NONE +0 65535 1 +V RW NP +SCH +0 65535 1 + + +* +* WEP Key Length (5 or 13 bytes) +* + +WNI_CFG_WEP_KEY_LENGTH I 4 5 +V RW NP RESTART +NONE +5 13 5 +V RW NP RESTART +NONE +5 13 5 + +#ENUM 5 5 +#ENUM 13 13 + +* +* Default Key Table +* + +#TABLE WNI_CFG_WEP_DEFAULT_KEY_TABLE 4 + +WNI_CFG_WEP_DEFAULT_KEY S 13 4 +V WO NP RESTART +NONE +0 +V WO NP RESTART +NONE +0 + +#END + +* +* WEP Default Key id +* + +WNI_CFG_WEP_DEFAULT_KEYID I 4 5 +V RW NP +LIM +0 3 0 +V RW NP +LIM +0 3 0 + +#ENUM 0 0 +#ENUM 1 1 +#ENUM 2 2 +#ENUM 3 3 + +* +* Exclude unencrypted frames (WEP) +* + +WNI_CFG_EXCLUDE_UNENCRYPTED I 4 5 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* RTS Threshold +* + +WNI_CFG_RTS_THRESHOLD I 4 6 +V RW NP +HAL +0 1048576 2347 +V RW NP +HAL +0 1048576 2347 + +* +* Short Retry Limit +* + +WNI_CFG_SHORT_RETRY_LIMIT I 4 6 +V RW NP +HAL +0 255 6 +V RW NP +HAL +0 255 6 + +* +* Long Retry Limit +* + +WNI_CFG_LONG_RETRY_LIMIT I 4 6 +V RW NP +HAL +0 255 6 +V RW NP +HAL +0 255 6 + + +* +* Fragmentation Threshold +* + +WNI_CFG_FRAGMENTATION_THRESHOLD I 4 6 +V RW NP +HAL +256 8000 8000 +V RW NP +HAL +256 8000 8000 + + +* +* Minimum Channel Time (TU) +* + +WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME I 4 9 +V RW NP +NONE +0 65535 20 +V RW NP +NONE +0 65535 20 + +* +* Maximum Channel Time (TU) +* + +WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME I 4 9 +V RW NP +NONE +0 65535 40 +V RW NP +NONE +0 65535 40 +* +* Minimum Channel Time (TU) +* + +WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME I 4 9 +V RW NP +NONE +0 65535 60 +V RW NP +NONE +0 65535 60 + +* +* Maximum Channel Time (TU) +* + +WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME I 4 9 +V RW NP +NONE +0 65535 110 +V RW NP +NONE +0 65535 110 + +* +* Join Failure Timeout (TU) +* + +WNI_CFG_JOIN_FAILURE_TIMEOUT I 4 7 +V RW NP +NONE +0 65535 3000 +V RW NP +NONE +0 65535 3000 + +* +* Authenticate Failure Timeout (TU) +* + +WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT I 4 7 +V RW NP +NONE +0 65535 1000 +V RW NP +NONE +0 65535 1000 + +* +* Authenticate Response Timeout (TU) +* + +WNI_CFG_AUTHENTICATE_RSP_TIMEOUT I 4 7 +V RW NP +NONE +0 65535 1000 +V RW NP +NONE +0 65535 1000 + +* +* Assocation Failure Timeout (TU) +* + +WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT I 4 8 +V RW NP +LIM +0 65535 2000 +V RW NP +LIM +0 65535 3000 + +* +* Reassociation Failure Timeout (TU) +* + +WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT I 4 7 +V RW NP +NONE +0 65535 1000 +V RW NP +NONE +0 65535 3000 + + +* +* RA periodicity Timeout (TU) +* + +WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS I 4 7 +V RW NP +HAL +0 65535 1000 +NV RW NP +NONE +0 0 0 + +* +* Beacon Filter Enable/Disable (TU) +* + +WNI_CFG_PS_ENABLE_BCN_FILTER I 4 7 +V RW NP +HAL +0 1 1 +NV RW NP +NONE +0 1 1 + +* +* Heart Beat Enable/Disable (TU) +* + +WNI_CFG_PS_ENABLE_HEART_BEAT I 4 7 +V RW NP +HAL +0 1 1 +NV RW NP +NONE +0 1 1 + +* +* RSSI Monitor Enable/Disable (TU) +* + +WNI_CFG_PS_ENABLE_RSSI_MONITOR I 4 7 +V RW NP +HAL +0 1 0 +NV RW NP +NONE +0 1 0 + + +* +* PS Data InActivity Timeout (TU) +* + +WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT I 4 7 +V RW NP +HAL +1 255 20 +NV RW NP +NONE +1 255 20 + + +* +* RF Settling Time Clk (In US) +* + +WNI_CFG_RF_SETTLING_TIME_CLK I 4 7 +V RW NP +HAL +0 60000 1500 +NV RW NP +NONE +0 60000 1500 + +* +* Supported Rate Set for 11b +* + +WNI_CFG_SUPPORTED_RATES_11B S 4 2 +V RO NP +NONE +4 2 4 11 22 +V RO NP +NONE +4 2 4 11 22 + +* +* Supported Rate Set for 11a +* + +WNI_CFG_SUPPORTED_RATES_11A S 8 7 +V RO NP +NONE +8 12 18 24 36 48 72 96 108 +V RO NP +NONE +8 12 18 24 36 48 72 96 108 + + +* +* PHY Mode +* + +WNI_CFG_PHY_MODE I 4 9 +V RW NP RESTART +NONE +0 3 0 +V RW NP RESTART +NONE +0 3 0 + +#ENUM 11A 0 +#ENUM 11B 1 +#ENUM 11G 2 +#ENUM NONE 3 + + +* +*The Dot11 mode can change dynamically on STA +* +WNI_CFG_DOT11_MODE I 4 9 +V RW NP RESTART +LIM +0 11 0 +V RW NP RESTART +LIM +0 11 0 + +#ENUM ALL 0 +#ENUM 11A 1 +#ENUM 11B 2 +#ENUM 11G 3 +#ENUM 11N 4 +#ENUM 11G_ONLY 5 +#ENUM 11N_ONLY 6 +#ENUM 11AC 7 +#ENUM 11AC_ONLY 8 + + + + + + +* +* Operational Rate Set (goes in beacon, probe rsp and assoc req) +* + +WNI_CFG_OPERATIONAL_RATE_SET S 12 2 +V RW NP RESTART +NONE +0 +V RW NP RESTART +NONE +4 0x82 0x84 11 22 +* 8 0x8c 18 24 36 48 72 96 108 + +* +* Extended Operational Rate Set (goes in beacon, assoc req) +* required for 11g +* + +WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET S 8 7 +V RW NP RESTART +NONE +0 +V RW NP RESTART +NONE +0 + +* +* Proprietary Operational Rate Set +* + +WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET S 4 7 +V RW NP RESTART +NONE +4 1 3 5 7 +V RW NP RESTART +NONE +4 1 3 5 7 + +* +* BSSID +* In IBSS, this can be changed for coalescing, should SME go into IDLE state? +* + +* +* Listen Interval +* + +WNI_CFG_LISTEN_INTERVAL I 4 7 +V RW NP RESTART +NONE +0 65535 1 +V RO NP +NONE +0 65535 1 + +* +* Valid Channel List +* + +WNI_CFG_VALID_CHANNEL_LIST S 100 8 +V RW NP RESTART +LIM +55 36 40 44 48 52 56 60 64 1 6 11 34 38 42 46 2 3 4 5 7 8 9 10 12 13 14 100 104 108 112 116 120 124 128 132 136 140 149 151 153 155 157 159 161 50 54 58 62 240 242 244 246 248 250 252 +V RW NP RESTART +LIM +55 36 40 44 48 52 56 60 64 1 6 11 34 38 42 46 2 3 4 5 7 8 9 10 12 13 14 100 104 108 112 116 120 124 128 132 136 140 149 151 153 155 157 159 161 50 54 58 62 240 242 244 246 248 250 252 + +* +* Current Channel +* + +WNI_CFG_CURRENT_CHANNEL I 4 9 +V RO NP +NONE +0 165 1 +V RO NP +NONE +0 165 1 + + +* +* For 11a or pure 11g, use 6Mbps(rateindex 11) +* as the default beaconRateIndex and +* nonBeaconRateIndex. +* +WNI_CFG_DEFAULT_RATE_INDEX_5GHZ I 4 9 +V RW NP +NONE +0 11 5 +V RW NP +NONE +0 11 5 + +* +* For 11b/g, use 1Mbps +* as the default beaconRateIndex and +* nonBeaconRateIndex. +* +WNI_CFG_DEFAULT_RATE_INDEX_24GHZ I 4 9 +V RW NP +NONE +0 31 1 +V RW NP +NONE +0 31 1 + + +* ********************************************************* +* +* Rate adaptation type +* + +WNI_CFG_RATE_ADAPTATION_TYPE I 4 0 +V RW NP +SCH +0 2 1 +V RW NP +SCH +0 2 1 + +#ENUM FIXED 0 +#ENUM AUTO 1 +#ENUM SNR_BASED 2 + +* +* Rate adaptation fixed rate +* Used to determine the rate for all peer stations +* +* + +WNI_CFG_FIXED_RATE I 4 0 +V RW NP +HAL +0 44 0 +V RW NP +HAL +0 44 0 + +#ENUM AUTO 0 + +#ENUM 1MBPS 1 +#ENUM 2MBPS 2 +#ENUM 5_5MBPS 3 +#ENUM 11MBPS 4 + +#ENUM 6MBPS 5 +#ENUM 9MBPS 6 +#ENUM 12MBPS 7 +#ENUM 18MBPS 8 +#ENUM 24MBPS 9 +#ENUM 36MBPS 10 +#ENUM 48MBPS 11 +#ENUM 54MBPS 12 + +#ENUM 6_5MBPS_MCS0_20MHZ_SIMO 13 +#ENUM 13MBPS_MCS1_20MHZ_SIMO 14 +#ENUM 19_5MBPS_MCS2_20MHZ_SIMO 15 +#ENUM 26MBPS_MCS3_20MHZ_SIMO 16 +#ENUM 39MBPS_MCS4_20MHZ_SIMO 17 +#ENUM 52MBPS_MCS5_20MHZ_SIMO 18 +#ENUM 58_5MBPS_MCS6_20MHZ_SIMO 19 +#ENUM 65MBPS_MCS7_20MHZ_SIMO 20 + +#ENUM 7_2MBPS_MCS0_20MHZ_SIMO_SGI 21 +#ENUM 14_4MBPS_MCS1_20MHZ_SIMO_SGI 22 +#ENUM 21_7MBPS_MCS2_20MHZ_SIMO_SGI 23 +#ENUM 28_9MBPS_MCS3_20MHZ_SIMO_SGI 24 +#ENUM 43_3MBPS_MCS4_20MHZ_SIMO_SGI 25 +#ENUM 57_8MBPS_MCS5_20MHZ_SIMO_SGI 26 +#ENUM 65MBPS_MCS6_20MHZ_SIMO_SGI 27 +#ENUM 72_2MBPS_MCS7_20MHZ_SIMO_SGI 28 + +#ENUM 0_25MBPS_SLR_20MHZ_SIMO 29 +#ENUM 0_5MBPS_SLR_20MHZ_SIMO 30 + +#ENUM 68_25MBPS_QC_PROP_20MHZ_SIMO 31 +#ENUM 54MBPS_MCS3_40MHZ_SIMO 32 +#ENUM 81MBPS_MCS4_40MHZ_SIMO 33 +#ENUM 108MBPS_MCS5_40MHZ_SIMO 34 +#ENUM 121_5MBPS_MCS6_40MHZ_SIMO 35 +#ENUM 135MBPS_MCS7_40MHZ_SIMO 36 +#ENUM 15MBPS_MCS0_40MHZ_SIMO_SGI 37 +#ENUM 30MBPS_MCS1_40MHZ_SIMO_SGI 38 +#ENUM 45MBPS_MCS2_40MHZ_SIMO_SGI 39 +#ENUM 60MBPS_MCS3_40MHZ_SIMO_SGI 40 +#ENUM 90MBPS_MCS4_40MHZ_SIMO_SGI 41 +#ENUM 120MBPS_MCS5_40MHZ_SIMO_SGI 42 +#ENUM 135MBPS_MCS6_40MHZ_SIMO_SGI 43 +#ENUM 150MBPS_MCS7_40MHZ_SIMO_SGI 44 + +* ********************************************************* +* +* Broadcast/mutlicast rates for 2.4GHZ +* uses the same rate indices definition as WNI_CFG_FIXED_RATE +* default value corresponds to 1M + +WNI_CFG_FIXED_RATE_MULTICAST_24GHZ I 4 8 +V RW NP +HAL +0 31 1 +V RW NP +HAL +0 31 1 + +* ********************************************************* +* +* Broadcast/mutlicast rates for 5 GHZ +* uses the same rate indices definition as WNI_CFG_FIXED_RATE +* default value corresponds to 6M + +WNI_CFG_FIXED_RATE_MULTICAST_5GHZ I 4 8 +V RW NP +HAL +0 31 5 +V RW NP +HAL +0 31 5 + +* +* retry rate selection policy +* 0 => use the minimum supported rate +* 1 => use the same rate as the chosen primary rate +* 2 => use the rate specified in RETRYRATE_SECONDARY +* 3 => use the rate closest to the primary +* 4 => autoselect the retry rate based on RA algorithm +* + +WNI_CFG_RETRYRATE_POLICY I 4 0 +V RW NP +HAL +0 255 4 +V RW NP +HAL +0 255 4 + +#ENUM MIN_SUPPORTED 0 +#ENUM PRIMARY 1 +#ENUM RESERVED 2 +#ENUM CLOSEST 3 +#ENUM AUTOSELECT 4 +#ENUM MAX 5 + +* +* the following two CFG's are +* used only if the retryrate policy == 2 +* These should be set to one of the values used +* for configuring fixed rates (see enumerated rates) +* + +WNI_CFG_RETRYRATE_SECONDARY I 4 0 +V RW NP +HAL +0 255 0 +V RW NP +HAL +0 255 0 + +WNI_CFG_RETRYRATE_TERTIARY I 4 0 +V RW NP +HAL +0 255 0 +V RW NP +HAL +0 255 0 + +* ********************************************************* +* +* Automatic Power Save Delivery capability +* + +WNI_CFG_APSD_ENABLED I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* Shared key authentication supported +* + +WNI_CFG_SHARED_KEY_AUTH_ENABLE I 4 8 +V RW NP +NONE +0 1 1 +V RW NP +NONE +0 1 1 + +* +* Open system authentication supported +* + +WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE I 4 8 +V RW NP +NONE +0 1 1 +V RW NP +NONE +0 1 1 + +* +* Authentication Type (change requires restart) +* + +WNI_CFG_AUTHENTICATION_TYPE I 4 8 +V RW NP RESTART +NONE +0 65535 0 +V RW NP RESTART +NONE +0 65535 0 + +* +* CF Poll Request (change requires restart) +* + +WNI_CFG_CF_POLL_REQUEST I 4 8 +NV RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +* +* Privacy Enabled (change requires restart) +* + +WNI_CFG_PRIVACY_ENABLED I 4 8 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +* +* Short Preamble (change requires restart) +* + +WNI_CFG_SHORT_PREAMBLE I 4 8 +V RW NP RESTART +NONE +0 1 1 +V RW NP RESTART +NONE +0 1 1 + +* +* Short Slot time +* This is the operational state of the BSS + +WNI_CFG_SHORT_SLOT_TIME I 4 8 +V RW NP +NONE +0 1 1 +V RW NP +NONE +0 1 0 + + +* +* ACCEPT Short Slot Association only +* +* 1: If AP supports shortSlot, then AP will accept +* association only from stations that supports +* supports short slot +* 0: AP supports shortSlot, but AP will accept association +* from stations regardless of whether station supports +* short slot or long slot +* +WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY I 4 9 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + + +* +* QOS Enabled (change requires restart) +* + +WNI_CFG_QOS_ENABLED I 4 8 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +* +* HCF Enabled (change requires restart) +* + +WNI_CFG_HCF_ENABLED I 4 8 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +* +* RSN (11i/WPA) Enabled +* + +WNI_CFG_RSN_ENABLED I 4 8 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +* +* Background scanning periodicity (kilo usec) +* + +WNI_CFG_BACKGROUND_SCAN_PERIOD I 4 8 +V RW NP +LIM +0 180000 5000 +V RW NP +LIM +0 18000 5000 + +* +* Max number of Preauthentication +* + +WNI_CFG_MAX_NUM_PRE_AUTH I 4 8 +V RW NP RESTART +NONE +0 256 64 +V RW NP RESTART +NONE +0 256 64 + +* +* Preauthentication Cleanup Timeout (kilo usec) +* + +WNI_CFG_PREAUTH_CLNUP_TIMEOUT I 4 8 +NV XX NP +NONE +0 0 0 +V RW NP +LIM +0 120000 30000 + +* +* Release AID Timeout +* + +WNI_CFG_RELEASE_AID_TIMEOUT I 4 8 +NV XX NP +NONE +0 0 0 +V RW NP +LIM +0 100000 1000 +* +* Heartbeat Threshold +* + +WNI_CFG_HEART_BEAT_THRESHOLD I 4 8 +V RW NP +LIM +0 65535 40 +NV RW NP +NONE +0 65535 40 + +* +* Probe response wait time out after heartbeat failure +* + +WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT I 4 8 +V RW NP +NONE +10 10000 40 +V RW NP +NONE +10 10000 40 + +* +* Manufacturer OUI (from eeprom) +* + +WNI_CFG_MANUFACTURER_OUI S 3 8 +V RO NP +NONE +3 0x0 0xa 0xf5 +V RO NP +NONE +3 0x0 0xa 0xf5 + +* +* Manufacture Name (from eeprom) +* + +WNI_CFG_MANUFACTURER_NAME S 64 8 +V RO NP +NONE +8 0x51 0x75 0x61 0x6c 0x63 0x6f 0x6D 0x6D +V RO NP +NONE +8 0x51 0x75 0x61 0x6c 0x63 0x6f 0x6D 0x6D + +* +* Model Number (from eeprom) +* + +WNI_CFG_MODEL_NUMBER S 32 8 +V RO NP +NONE +6 0x4d 0x4e 0x31 0x32 0x33 0x34 +V RO NP +NONE +6 0x4d 0x4e 0x31 0x32 0x33 0x34 + + + +* +* Model Name (from eeprom) +* WFR4031 +* + +WNI_CFG_MODEL_NAME S 32 8 +V RO NP +NONE +7 0x57 0x46 0x52 0x34 0x30 0x33 0x31 +V RO NP +NONE +7 0x57 0x46 0x52 0x34 0x30 0x33 0x31 + + + + +* +* Manufacture Product Name (from eeprom) +* + +WNI_CFG_MANUFACTURER_PRODUCT_NAME S 32 8 +V RO NP +NONE +6 0x31 0x31 0x6e 0x2D 0x41 0x50 +V RO NP +NONE +6 0x31 0x31 0x6e 0x2D 0x41 0x50 + + +* +* Manufacture Product Version (from eeprom) +* + +WNI_CFG_MANUFACTURER_PRODUCT_VERSION S 32 8 +V RO NP +NONE +6 0x53 0x4e 0x31 0x32 0x33 0x34 +V RO NP +NONE +6 0x53 0x4e 0x31 0x32 0x33 0x34 + +* +* Multi Domain Capability (11d) Enable +* + +WNI_CFG_11D_ENABLED I 4 9 +V RW NP RESTART +NONE +0 1 1 +V RW NP RESTART +NONE +0 1 0 + +* +* per channel Max power transmit (in dBm) +* this parameter correspond to the MAX_COUNTRY_EID +* table of (Channel Number/num channel/max tx power) +* +* There is one table for 5GHz channels and one table for 2.4GHz channels +* + +WNI_CFG_MAX_TX_POWER_2_4 S 128 8 +V RW NP +NONE +3 1 14 20 +V RW NP +NONE +3 1 14 20 + +WNI_CFG_MAX_TX_POWER_5 S 128 8 +V RW NP +NONE +3 36 126 20 +V RW NP +NONE +3 36 126 20 + +* +* Cell size configurations. These are canned configurations for a specified +* cell size. +* +WNI_CFG_NETWORK_DENSITY I 4 9 +V RW NP +HAL +0 3 3 +V RW NP +HAL +0 3 0 + +#ENUM LOW 0 +#ENUM MEDIUM 1 +#ENUM HIGH 2 +#ENUM ADAPTIVE 3 + + +* +* Adaptive Threshold Algorithm +* +WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM I 4 9 +V RW NP +HAL +1 2 2 +V RW NP +HAL +1 2 2 + +#ENUM CARRIER 1 +#ENUM CORRELATION 2 + + + +* +* Current TX Antenna +* + +WNI_CFG_CURRENT_TX_ANTENNA I 4 9 +V RW NP +HAL +1 1 1 +V RW NP +HAL +1 2 2 + +* +* Current RX Antenna +* + +WNI_CFG_CURRENT_RX_ANTENNA I 4 9 +V RW NP +HAL +1 2 2 +V RW NP +HAL +1 3 3 + +* +* Current TX Power Level +* + +WNI_CFG_CURRENT_TX_POWER_LEVEL I 4 9 +V RW NP +NONE +0 128 27 +V RW NP +NONE +0 128 27 + + +* +* Parameter to indicate or not new BSS found +* + +WNI_CFG_NEW_BSS_FOUND_IND I 4 9 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + + +* +* Qualcomm Prop Rates are disabled by default +* +WNI_CFG_PROPRIETARY_RATES_ENABLED I 4 12 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + + +* +* AP node Name +* + +WNI_CFG_AP_NODE_NAME S 32 8 +NV RO NP +NONE +0 +V RW NP RESTART +NONE +0 + +* +* Country code (from EEPROM) +* + +WNI_CFG_COUNTRY_CODE S 3 8 +V RW NP +NONE +0 +V RW NP +NONE +3 0x11 0x22 0x33 + +* +* Spectrum Management (11h) enable/disable +* + +WNI_CFG_11H_ENABLED I 4 12 +V RW NP RESTART +NONE +0 1 1 +V RW NP RESTART +NONE +0 1 1 + +* +* Wait for CNF Timeout. CNF include (RE)ASSOC, DISASSOC, AUTH, DEAUTH, +* DUMMY packet +* + +WNI_CFG_WT_CNF_TIMEOUT I 4 12 +V RW NP +NONE +10 3000 1000 +V RW NP +NONE +10 3000 1000 + +* +* Keepalive Timeout. A Null data frame is sent out every timeout. +* Applicable to both AP and STA +* + +WNI_CFG_KEEPALIVE_TIMEOUT I 4 12 +V RW NP +NONE +0 3600000 0 +V RW NP +NONE +0 3600000 3000 + +* +* Proximity, set it for very short distances +* Proxmity setting is applied via halPhySetNwDensity() +* +* close proximity off = densityOn is true. network density config applies. +* close proximity on = densityOn is false. Don't care about network density config. +* + +WNI_CFG_PROXIMITY I 4 12 +V RW NP +HAL +0 1 0 +V RW NP +HAL +0 1 0 + +#ENUM OFF 0 +#ENUM ON 1 + +* +* Default LOG level +* + +WNI_CFG_LOG_LEVEL I 4 12 +V RW NP +NONE +0 7 4 +V RW NP +NONE +0 7 4 + +* +* OLBC detection timeout +* + +WNI_CFG_OLBC_DETECT_TIMEOUT I 4 12 +V RW NP +NONE +1000 30000 10000 +V RW NP +NONE +1000 30000 10000 + +********************************** +* Protection Enable +* +*LOWER byte for associated stations +*UPPER byte for overlapping stations. +*11g ==> protection from 11g +*11b ==> protection from 11b +*each byte will have the following info +*bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 +*reserved reserved RIFS Lsig n-GF ht20 11g 11b +********************************** +WNI_CFG_PROTECTION_ENABLED I 4 9 +V RW NP RESTART +LIM +0 0xffff 0xffff +V RW NP RESTART +LIM +0 0xffff 0xffff + +#ENUM FROM_llA 0 +#ENUM FROM_llB 1 +#ENUM FROM_llG 2 +#ENUM HT_20 3 +#ENUM NON_GF 4 +#ENUM LSIG_TXOP 5 +#ENUM RIFS 6 +#ENUM OBSS 7 +#ENUM OLBC_FROM_llA 8 +#ENUM OLBC_FROM_llB 9 +#ENUM OLBC_FROM_llG 10 +#ENUM OLBC_HT20 11 +#ENUM OLBC_NON_GF 12 +#ENUM OLBC_LSIG_TXOP 13 +#ENUM OLBC_RIFS 14 +#ENUM OLBC_OBSS 15 + + +* **************************************** +* +* 11G Protection Enable Always +* Valid only if protection is enabled +* forces uses of protection regardless of legacy stations +* + +WNI_CFG_11G_PROTECTION_ALWAYS I 4 9 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +********************************************* +* Force protection +* 0 : disable protection +* 1 : CTS +* 2 : RTS by threshold (threshold nonzero) +* 3 : dual CTS (not supported right now) +* 4 : RTS (threshold 0) +* 5 : auto + +WNI_CFG_FORCE_POLICY_PROTECTION I 4 9 +V RW NP RESTART +HAL +0 5 5 +V RW NP RESTART +HAL +0 5 5 + +#ENUM DISABLE 0 +#ENUM CTS 1 +#ENUM RTS 2 +#ENUM DUAL_CTS 3 +#ENUM RTS_ALWAYS 4 +#ENUM AUTO 5 + + + + + + +******************************************** +* 11G Short Preamble Enable +* + +WNI_CFG_11G_SHORT_PREAMBLE_ENABLED I 4 9 +V RW NP RESTART +NONE +0 1 0 +V RW NP RESTART +NONE +0 1 0 + +* +* 11G Short Slot Time Enable (change requires restart) +* This is the admin state of short slot support. + +WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED I 4 9 +V RW NP RESTART +NONE +0 1 1 +V RW NP RESTART +NONE +0 1 1 + +* +* Parameter to allow 11g only STAs while operating in 11g mode +* + +WNI_CFG_11G_ONLY_POLICY I 4 12 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* Packet Classification +* This flag is a bitmask used to indicate which +* frame classifier to be enabled: +* b0: DSCP +* b1: 802.1P +* + +WNI_CFG_PACKET_CLASSIFICATION I 4 12 +V RW NP +HAL +0 3 0 +V RW NP +HAL +0 3 0 + +#ENUM DISABLED 0 +#ENUM DSCP 1 +#ENUM 8021P 2 +#ENUM ALL 3 + +* +* WME Enabled (change requires restart) +* + +WNI_CFG_WME_ENABLED I 4 8 +V RW NP RESTART +NONE +0 1 1 +V RW NP RESTART +NONE +0 1 1 + +* +* ADDTS response timeout (in ms) +* + +WNI_CFG_ADDTS_RSP_TIMEOUT I 4 8 +V RW NP +NONE +0 65535 1000 +V RW NP +NONE +0 65535 1000 + + + * Max SP Length indicates the max number of + * total buffered MSDUs and MMPDUs the WMM AP + * may deliver to WMM STA during any service period + * triggered by WMM STA. + * 1) If AP sends WMM IE with the UAPSD bit 0, max_sp_length=0 + * 2) If WMM STA's all 4 UAPSD flag are set to 0, max_sp_length=0 + * 3) If AP sends WMM IE with UAPSD=1, and at least one of stations + * UAPSD flag is set to 1, then max_sp_length can be set to: + * [b5:b6]=0x00: WMM AP may deliver all buffered frames + * [b5:b6]=0x10: WMM AP may deliver max 2 buffered frames + * [b5:b6]=0x01: WMM AP may deliver max 4 buffered frames + * [b5:b6]=0x11: WMM AP may deliver max 6 buffered frames + +WNI_CFG_MAX_SP_LENGTH I 4 8 +V RW NP +NONE +0 3 0 +V RW NP +NONE +0 3 0 + + +* +* KEEP ALIVE STA Limit Threshold , used in AP to delete the STA +* from Station Table which didn't respond to Probe Response Messages +* + +WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD I 4 8 +NV RW NP +NONE +0 32 0 +V RW NP +NONE +0 32 0 + +* +* Parameter that specifies whether to send SSID +* in Probe Response when SSID is suppressed +* + +WNI_CFG_SEND_SINGLE_SSID_ALWAYS I 4 12 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* WSM Enabled (change requires restart) +* Takes effect only if WME is also enabled +* + +WNI_CFG_WSM_ENABLED I 4 8 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* **************************************** +* +* Background Channel List +* Contains pairs of {channelNumber, scanType} +* where scanType = 0 indicates active scan and +* = 1 indicates passive scan +* +* +*WNI_CFG_BACKGROUND_SCAN_LIST S 128 8 +*V RW NP RESTART +*LIM +*60 36 0 40 0 44 0 48 0 52 0 56 0 60 0 64 0 1 0 6 0 11 0 34 0 38 0 42 0 46 0 2 0 3 0 4 0 5 0 7 0 8 0 9 0 10 0 12 0 13 0 14 0 149 0 153 0 157 0 161 0 +*V RW NP RESTART +*LIM +*60 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 34 0 36 0 38 0 40 0 42 0 44 0 46 0 48 0 52 0 56 0 60 0 64 0 149 0 153 0 157 0 161 0 +* + +* **************************************** +* EDCA paramters are contained in profiles - each profile contains +* the parameters [ACM, AIFSN, CWmin, CWmax, TxOp] for four +* access categories (i.e., four sets). Two such sets of four parameters +* make a single profile: One set is used locally by the AP, the other set +* is broadcast for use by stations. +* +* Cwmin and Cwmax are two bytes each, MSB first. So Cwmin of [3 255] is +* equivalent to 0x3ff, i.e. 3*256+255=1023 +* +* The profile to use is selected based on the valus of the profile select param +* See ENUMs below for definitions of profile values +* + +WNI_CFG_EDCA_PROFILE I 4 8 +V RW NP +SCH +0 255 1 +V RW NP +SCH +0 255 1 + +#ENUM ANI 0 +#ENUM WMM 1 +#ENUM TIT_DEMO 2 +#ENUM MAX 3 + +#ENUM ACM_IDX 0 +#ENUM AIFSN_IDX 1 +#ENUM CWMINA_IDX 2 +#ENUM CWMAXA_IDX 4 +#ENUM TXOPA_IDX 6 +#ENUM CWMINB_IDX 7 +#ENUM CWMAXB_IDX 9 +#ENUM TXOPB_IDX 11 +#ENUM CWMING_IDX 12 +#ENUM CWMAXG_IDX 14 +#ENUM TXOPG_IDX 16 + + +* **************************************** +* Profile 0 (Airgo) parameters - AC_BK Local +* ACM, AIFSN, [CWminH, CWminL, CWmaxH, CWmaxL, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACBK_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 31 3 255 0 0 15 3 255 0 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 31 3 255 0 0 15 3 255 0 + +* +* Profile 0 (Airgo) parameters AC_BE Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACBE_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 2 0 15 3 255 100 0 31 3 255 100 0 15 3 255 100 +V RW NP RESTART +NONE +17 0 2 0 15 3 255 100 0 31 3 255 100 0 15 3 255 100 + +* +* Profile 0 (Airgo) parameters AC_VI Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACVI_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 2 0 7 0 15 200 0 15 0 31 188 0 7 0 15 200 +V RW NP RESTART +NONE +17 0 2 0 7 0 15 200 0 15 0 31 188 0 7 0 15 200 + +* +* Profile 0 (Airgo) parameters AC_VO Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACVO_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 2 0 3 0 7 100 0 7 0 15 102 0 3 0 7 100 +V RW NP RESTART +NONE +17 0 2 0 3 0 7 100 0 7 0 15 102 0 3 0 7 100 + +* +* Profile 0 (Airgo) parameters - AC_BK Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACBK S 20 8 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 31 3 255 0 0 15 3 255 0 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 31 3 255 0 0 15 3 255 0 + +* +* Profile 0 (Airgo) parameters AC_BE Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACBE S 20 8 +V RW NP RESTART +NONE +17 0 2 0 15 3 255 100 0 31 3 255 100 0 15 3 255 100 +V RW NP RESTART +NONE +17 0 2 0 15 3 255 100 0 31 3 255 100 0 15 3 255 100 + +* +* Profile 0 (Airgo) parameters AC_VI Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACVI S 20 8 +V RW NP RESTART +NONE +17 0 2 0 7 0 15 200 0 15 0 31 188 0 7 0 15 200 +V RW NP RESTART +NONE +17 0 2 0 7 0 15 200 0 15 0 31 188 0 7 0 15 200 + +* +* Profile 0 (Airgo) parameters AC_VO Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_ANI_ACVO S 20 8 +V RW NP RESTART +NONE +17 0 2 0 3 0 7 100 0 7 0 15 102 0 3 0 7 100 +V RW NP RESTART +NONE +17 0 2 0 3 0 7 100 0 7 0 15 102 0 3 0 7 100 + + +* **************************************** +* Profile 1 (WME) parameters - AC_BK Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACBK_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 31 3 255 0 0 15 3 255 0 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 15 3 255 0 0 15 3 255 0 + + +* +* Profile 1 (WME) parameters AC_BE Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACBE_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 3 0 15 0 63 0 0 31 3 255 0 0 15 0 63 0 +V RW NP RESTART +NONE +17 0 3 0 15 0 63 0 0 15 0 63 0 0 15 0 63 0 + +* +* Profile 1 (WME) parameters AC_VI Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACVI_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 1 0 7 0 15 94 0 7 0 15 188 0 7 0 15 94 +V RW NP RESTART +NONE +17 0 1 0 7 0 15 94 0 7 0 15 188 0 7 0 15 94 + +* +* Profile 1 (WME) parameters AC_VO Local +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACVO_LOCAL S 20 8 +V RW NP RESTART +NONE +17 0 1 0 3 0 7 47 0 3 0 7 102 0 3 0 7 47 +V RW NP RESTART +NONE +17 0 1 0 3 0 7 47 0 3 0 7 102 0 3 0 7 47 + +* +* Profile 1 (WME) parameters - AC_BK Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACBK S 20 8 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 15 3 255 0 0 15 3 255 0 +V RW NP RESTART +NONE +17 0 7 0 15 3 255 0 0 15 3 255 0 0 15 3 255 0 + +* +* Profile 1 (WME) parameters AC_BE Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACBE S 20 8 +V RW NP RESTART +NONE +17 0 3 0 15 3 255 0 0 15 3 255 0 0 15 3 255 0 +V RW NP RESTART +NONE +17 0 3 0 15 3 255 0 0 15 3 255 0 0 15 3 255 0 + +* +* Profile 1 (WME) parameters AC_VI Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACVI S 20 8 +V RW NP RESTART +NONE +17 0 2 0 7 0 15 94 0 7 0 15 188 0 7 0 15 94 +V RW NP RESTART +NONE +17 0 2 0 7 0 15 94 0 7 0 15 188 0 7 0 15 94 + +* +* Profile 1 (WME) parameters AC_VO Broadcast +* ACM, AIFSN, [CWmin, CWmax, TxOp]-11A/11B/11G +* + +WNI_CFG_EDCA_WME_ACVO S 20 8 +V RW NP RESTART +NONE +17 0 2 0 3 0 7 47 0 3 0 7 102 0 3 0 7 47 +V RW NP RESTART +NONE +17 0 2 0 3 0 7 47 0 3 0 7 102 0 3 0 7 47 + +* +* Radar detector flag enable/disable +* + +WNI_CFG_RDET_FLAG I 4 9 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + +WNI_CFG_RADAR_CHANNEL_LIST S 20 8 +V RW NP RESTART +NONE +15 52 56 60 64 100 104 108 112 116 120 124 128 132 136 140 +V RW NP RESTART +NONE +15 52 56 60 64 100 104 108 112 116 120 124 128 132 136 140 + +* +* Local Power Constraint (dBm) +* + +WNI_CFG_LOCAL_POWER_CONSTRAINT I 4 12 +V RW NP RESTART +NONE +0 255 0 +V RW NP RESTART +NONE +0 255 0 + +* ********************************************************* +* +* Admission Control Policy +* used for admitting tspec's when either edca or hcca are in use +* + +WNI_CFG_ADMIT_POLICY I 4 8 +V RW NP RESTART +NONE +0 2 0 +V RW NP +SCH +0 2 0 + +#ENUM ADMIT_ALL 0 +#ENUM REJECT_ALL 1 +#ENUM BW_FACTOR 2 + +* +* Oversubscription factor for admission control +* valid only when admit policy is set to BW_FACTOR +* units are in terms of 1/10th of available bandwidth +* + +WNI_CFG_ADMIT_BWFACTOR I 4 8 +V RW NP RESTART +NONE +0 100 20 +V RW NP +SCH +0 100 20 + +* ********************************************************* +* +* Number of "consecutive" Background Scan Failure needed +* before LIM is forced to perform 1 aggressive background scan +* +WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE I 4 8 +V RW NP RESTART +NONE +0 256 60 +V RW NP RESTART +NONE +0 256 60 + + +************************************* +* Feature: Channel Bonding +************************************* +* +* Global flag to enable/disable Channel Bonding +* 0 - Disable: Force disable channel bonding for all TC-ids +* 1 - Enable: Force enable channel bonding for all TC-ids +* 2 - no legacy bss: Enable channel bonding if no legacy BSS are present +* 3 - no legacy all: Enable channel bonding if no legacy BSS or devices are present +* 4 - intelligent: Enable channel bonding depending on load level on secondary channel +* +WNI_CFG_CHANNEL_BONDING_MODE I 4 12 +V RW NP RESTART +LIM +0 10 0 +V RW NP RESTART +LIM +0 10 0 + +#ENUM DISABLE 0 +#ENUM ENABLE 1 +#ENUM IF_NO_LEGACY_BSS 2 +#ENUM IF_NO_LEGACY_ALL 3 +#ENUM INTELLIGENT 4 + + +* +* When the channel is 40MHz wide, this CFG indicates +* if the secondary channel is located above (at +* a higher frequency), or located below (at a +* lower frequency). +* +* 0 - There is no secondary channel. The channel is 20Mhz +* 1 - LOWER: Secondary channel 40MHZ is located below the primary channel +* 2 - CENTERED:Secondary channel and primary located at centered +* 3 - HIGHER: Secondary channel 40 MHZ is located above the primary channel +* 4 - 80MHZ_LOW_CENTERED : 20/40MHZ offset LOW 40/80MHZ offset CENTERED +* 5 - 80MHZ_CENTERED_CENTERED : 20/40MHZ offset CENTERED 40/80MHZ offset CENTERED +* 6 - 80MHZ_HIGH_CENTERED : 20/40MHZ offset HIGH 40/80MHZ offset CENTERED +* 7 - 80MHZ_LOW_LOW: 20/40MHZ offset LOW 40/80MHZ offset LOW +* 8 - 80MHZ_HIGH_LOW: 20/40MHZ offset HIGH 40/80MHZ offset LOW +* 9 - 80MHZ_LOW_HIGH: 20/40MHZ offset LOW 40/80MHZ offset HIGH +* 10 - 80MHZ_HIGH_HIGH: 20/40MHZ offset HIGH 40/80MHZ offset HIGH +* +WNI_CFG_CB_SECONDARY_CHANNEL_STATE I 4 12 +V RW NP +NONE +0 10 0 +V RW NP +NONE +0 10 0 + +#ENUM NONE 0 +#ENUM LOWER 1 +#ENUM HIGHER 2 +#ENUM 11AC_20MHZ_LOW_40MHZ_CENTERED 3 +#ENUM 11AC_20MHZ_CENTERED_40MHZ_CENTERED 4 +#ENUM 11AC_20MHZ_HIGH_40MHZ_CENTERED 5 +#ENUM 11AC_20MHZ_LOW_40MHZ_LOW 6 +#ENUM 11AC_20MHZ_HIGH_40MHZ_LOW 7 +#ENUM 11AC_20MHZ_LOW_40MHZ_HIGH 8 +#ENUM 11AC_20MHZ_HIGH_40MHZ_HIGH 9 + +************************************* +* Feature: Dynamic Retry Rates +************************************* +* +* When the short/long retry count reach the +* adaptive_retry_threshold(0), then the retry0 +* template shall be used +* +WNI_CFG_DYNAMIC_THRESHOLD_ZERO I 4 12 +V RW NP +HAL +0 255 2 +V RW NP +HAL +0 255 2 + +* +* When the short/long retry count reach the +* adaptive_retry_threshold(1), then the retry1 +* template shall be used +* +WNI_CFG_DYNAMIC_THRESHOLD_ONE I 4 12 +V RW NP +HAL +0 255 4 +V RW NP +HAL +0 255 4 + +* +* When the short/long retry count reach the +* adaptive_retry_threshold(2), then the retry2 +* template shall be used +* +WNI_CFG_DYNAMIC_THRESHOLD_TWO I 4 12 +V RW NP +HAL +0 255 6 +V RW NP +HAL +0 255 6 + + +* +* Trigger Station Background Scan Flag +* +WNI_CFG_TRIG_STA_BK_SCAN I 4 12 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 1 + +* ********************************************************* +* control of dynamic EDCA parameter profile switching +* +* OOB, we would like to support WMM standard edca profile +* However, when Airgo STA's join the BSS, we would like +* to switch the profile to Airgo high-performance edca parameters +* +* This cfg supports that behaviour. It is used only if 11e qos +* has been enabled and is ignored otherwise. +* +* When set to any value (other than unused), it determines the +* edca profile to switch to when an Airgo STA joins the BSS. +* +* By default, we choose to switch to Airgo profile. +* +* NOTE: This parameter applies only to an AP +* + +WNI_CFG_DYNAMIC_PROFILE_SWITCHING I 4 8 +V RW NP RESTART +NONE +0 255 255 +V RW NP RESTART +NONE +0 255 1 + +#ENUM UNUSED 255 + +* ********************************************************* +* +* Scan control list +* Contains pairs of {channelNumber, activeScanAllowedFlag} +* where scanType = 1 indicates active scan is allowed, and +* = 0 indicates passive scan is used +* If a channel is not on this list, active scan is NOT allowed. So it is +* sufficient to inlude only those channels where active scan is allowed +* on this list. +* +* The list determines only whether active scan is allowed or not; it does not +* determine which type of scan is actually performed. +* + +WNI_CFG_SCAN_CONTROL_LIST S 128 8 +V RW NP RESTART +LIM +112 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 1 11 1 12 1 13 1 14 1 34 1 36 1 38 1 40 1 42 1 44 1 46 1 48 1 50 1 52 0 54 0 56 0 58 0 60 0 62 0 64 0 100 0 104 0 108 0 112 0 116 0 120 0 124 0 128 0 132 0 136 0 140 0 149 1 151 1 153 1 155 1 157 1 159 1 161 1 165 1 240 1 242 1 244 1 246 1 248 1 250 1 252 1 +V RW NP RESTART +LIM +112 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 1 11 1 12 1 13 1 14 1 34 1 36 1 38 1 40 1 42 1 44 1 46 1 48 1 50 1 52 0 54 0 56 0 58 0 60 0 62 0 64 0 100 0 104 0 108 0 112 0 116 0 120 0 124 0 128 0 132 0 136 0 140 0 149 1 151 1 153 1 155 1 157 1 159 1 161 1 165 1 240 1 242 1 244 1 246 1 248 1 250 1 252 1 + + +* **************************************** +* +* MIMO rates enabled (for rate adaptation, to start) +* + +WNI_CFG_MIMO_ENABLED I 4 9 +V RW NP RELOAD +NONE +0 1 1 +V RW NP RELOAD +NIM +0 1 1 + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + + + +* +* BLOCK ACK Enabled (change requires restart) +* change default to ON +* bit 0 ==> delayed BA +* bit 1 ==> immediate BA +WNI_CFG_BLOCK_ACK_ENABLED I 4 8 +V RW NP RESTART +LIM +0 3 0 +V RW NP RESTART +LIM +0 3 0 + +#ENUM DELAYED 0 +#ENUM IMMEDIATE 1 + + +* +*BA Activity check global timer +* +WNI_CFG_BA_ACTIVITY_CHECK_TIMEOUT I 4 7 +V RW NP +HAL +0 65535 1000 +V RW NP +HAL +0 65535 1000 + + +* +* Rx STBC support +* +WNI_CFG_HT_RX_STBC I 4 7 +V RW NP RESTART +LIM +0 3 1 +V RW NP RESTART +LIM +0 3 1 + + +* +* 1. HT capabilities Info: 2 bytes size +* +* Supported channel Width is set to 1 (40 Mhz) +* SM Power Save is disabled. +* GreenField support is enabled. +* Short GI for 20 and 40Mhz is enabled. +* Max AMSDU Size is set to 0(3839 Octets) +* DSSS-CCK Mode is enabled. +* LSIG TXOP Protection is disabled +* Rest of the features are not supported at this moment. +* +* fedc ba98 7654 3210 +* 0000 0001 0010 0000 +* +WNI_CFG_HT_CAP_INFO I 4 10 +V RW NP RESTART +LIM +0 0xffff 0x016c +V RW NP RESTART +LIM +0 0xffff 0x106e + +#ENUM ADVANCE_CODING 0 +#ENUM SUPPORTED_CHAN_WIDTH_SET 1 +#ENUM SM_POWER_SAVE 2 +#ENUM GREEN_FIELD 4 +#ENUM SHORT_GI_20MHZ 5 +#ENUM SHORT_GI_40MHZ 6 +#ENUM TX_STBC 7 +#ENUM RX_STBC 8 +#ENUM DELAYED_BA 10 +#ENUM MAX_AMSDU_SIZE 11 +#ENUM DSSS_CCK_MODE_40MHZ 12 +#ENUM PSMP 13 +#ENUM STBC_CONTROL_FRAME 14 +#ENUM LSIG_TXOP_PROTECTION 15 + +* +* 2. HT Parameters Info: 1 byte size +* +* Max AMPDU Rx Factor is defined using bit #0 and #1 +* MPDU Density is defined using bit #2 thru #4. +* The default values are, +* 7654 3210 +* 0000 0010 --> 2 for RX AMPDU Factor, 0 for MPDU density +* +WNI_CFG_HT_AMPDU_PARAMS I 4 7 +V RW NP RESTART +LIM +0 0xff 0x00 +V RW NP RESTART +LIM +0 0xff 0x02 + +#ENUM MAX_RX_AMPDU_FACTOR 0 +#ENUM MPDU_DENSITY 2 +#ENUM RESERVED 5 + +* +* 3. Supported MCS Set: 16 bytes size +* +* MCS #0-15 and #32 is supported. +* +WNI_CFG_SUPPORTED_MCS_SET S 16 7 +V RW P RESTART +LIM +16 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +V RW P RESTART +LIM +16 255 255 0 0 1 0 0 0 0 0 0 0 0 0 0 0 + +* +* 4. Extended HT Capabilities Info: 2 bytes size +* +* Only HTC Support is enabled, rest all features are not +* supported at this moment. +* +* fedc ba98 7654 3210 +* 0000 0100 0000 0000 +* +WNI_CFG_EXT_HT_CAP_INFO I 4 10 +V RW P RESTART +LIM +0 0xffff 0x0400 +V RW P RESTART +LIM +0 0xffff 0x0400 + +#ENUM PCO 0 +#ENUM TRANSITION_TIME 1 +#ENUM RESERVED1 3 +#ENUM MCS_FEEDBACK 8 +#ENUM HTC_SUPPORT 10 +#ENUM RD_RESPONDER 11 +#ENUM RESERVED2 12 + + +* +* 5. Transmit Beam Forming Capabiliries Info: 4 bytes size +* +WNI_CFG_TX_BF_CAP I 4 7 +V RO NP RESTART +LIM +0 0xffffffff 0x00000000 +V RO NP RESTART +LIM +0 0xffffffff 0x00000000 + +* +* 6. Antenna Selection Capabilities: 1 byte size +* +WNI_CFG_AS_CAP I 4 7 +V RW P RESTART +LIM +0 0xff 0x00 +V RW P RESTART +LIM +0 0xff 0x00 + +#ENUM ANTENNA_SELECTION 0 +#ENUM EXPLICIT_CSI_FEEDBACK_TX 1 +#ENUM ANTENNA_INDICES_FEEDBACK_TX 2 +#ENUM EXPLICIT_CSI_FEEDBACK 3 +#ENUM ANTENNA_INDICES_FEEDBACK 4 +#ENUM RX_AS 5 +#ENUM TX_SOUNDING_PPDUS 6 +#ENUM RESERVED 7 + +************************************************** +* Beacon HT (High Through) Info IE +*************************************************** +* +* 3. HT Info Field1: 1 byte size. +* +* Secondary Channel Offset is set to 3 (Down) by default and will +* be updated dynamically by DFS algorithm. +* Channel Width is set to 1 (40 Mhz) +* RIFS Mode is enabled +* Rest of the features are not supported at this moment. +* +* 7654 3210 +* 0000 1111 +* +WNI_CFG_HT_INFO_FIELD1 I 4 10 +V RW NP RESTART +LIM +0 0xff 0x0f +V RW NP RESTART +LIM +0 0xff 0x0f + +#ENUM SECONDARY_CHANNEL_OFFSET 0 +#ENUM RECOMMENDED_CHANNEL_WIDTH 2 +#ENUM RIFS_MODE 3 +#ENUM PSMP_ACCESS_ONLY 4 +#ENUM SERVICE_INTERVAL_GRANULARITY 5 + +* +* 4. HT Info Field2: 2 bytes +* +* Operation mode is set to 0(Pure, GF) to begin with and +* will be updated dynamically. +* 'NonGF Devices present is also set to zero and +* will be updated dynamically. +* +* fedc ba98 7654 3210 +* 0000 0000 0000 0000 +* +WNI_CFG_HT_INFO_FIELD2 I 4 10 +V RW P +LIM +0 0xffff 0x00 +V RW P +LIM +0 0xffff 0x00 + +#ENUM OP_MODE 0 +#ENUM NON_GF_DEVICES_PRESENT 2 +#ENUM RESERVED 3 + +* +* 5. HT Info Field3: 2 bytes +* +* fedc ba98 7654 3210 +* 0000 0000 0000 0000 +* +* LSIG TXOP Full Protection will be zero to begin with and +* updated dynamically. +* Everything else is not supported at this moment. +* +WNI_CFG_HT_INFO_FIELD3 I 4 10 +V RW P +LIM +0 0xffff 0x0000 +V RW P +LIM +0 0xffff 0x0000 + +#ENUM BASIC_STBC_MCS 0 +#ENUM DUAL_STBC_PROTECTION 7 +#ENUM SECONDARY_BEACON 8 +#ENUM LSIG_TXOP_PROTECTION_FULL_SUPPORT 9 +#ENUM PCO_ACTIVE 10 +#ENUM PCO_PHASE 11 +#ENUM RESERVED 12 + +* +* 6. Basic MCS Set: 16 bytes size +* +* For now set this to zero and don't put any restrictions. +* +WNI_CFG_BASIC_MCS_SET S 16 7 +V RW P RESTART +LIM +16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +V RW P RESTART +LIM +16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +* +* 7. Current supported MCS Set: 16 bytes size +* +* For now set this to zero and don't put any restrictions. +* +WNI_CFG_CURRENT_MCS_SET S 16 7 +V RW P RESTART +LIM +16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +V RW P RESTART +LIM +16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + +* +* Greenfield Capability +* By default Greenfield is enabled +* +WNI_CFG_GREENFIELD_CAPABILITY I 4 7 +V RW NP RESTART +LIM +0 1 0 +V RW NP RESTART +LIM +0 1 0 + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + +* +* Maximum AMPDU Length +* By default set to zero for 3895 octets +* +WNI_CFG_VHT_MAX_MPDU_LENGTH I 4 19 +V RW NP +LIM +0 2 0 +V RW NP +LIM +0 2 0 + +* +* Supported Channel Width Set +* By default set to zero for +* STAs does not support either 160 or 80+80MHz +* +WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET I 4 19 +V RW NP +LIM +0 0 0 +V RW NP +LIM +0 0 0 + +* +* LDPC Coding Capability +* Riva/Pronto supports, default set to 1 +* +WNI_CFG_VHT_LDPC_CODING_CAP I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* Short GI for 80MHz +* Riva/Pronto supports, default set to 1 +* +WNI_CFG_VHT_SHORT_GI_80MHZ I 4 19 +V RW NP +LIM +0 1 1 +V RW NP +LIM +0 1 1 + +* +* Short GI for 160MHz and 80+80MHz +* Riva/Pronto does not supports, default set to 0 +* +WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* Support for Transmission of 2x1 STBC +* Riva/Pronto does not supports, default set to 0 +* +WNI_CFG_VHT_TXSTBC I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* Support for Reception of PPDUs using STBC +* Riva/Pronto supports, default set to 1 +* +WNI_CFG_VHT_RXSTBC I 4 19 +V RW NP +LIM +0 1 1 +V RW NP +LIM +0 1 1 + +* +* Support for Operating as SU Beamformer +* Riva/Pronto does not supports, default set to 0 +* +WNI_CFG_VHT_SU_BEAMFORMER_CAP I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* Support for Operating as SU Beamformee +* Riva does not support, But Pronto supports, default set to 0 +* +WNI_CFG_VHT_SU_BEAMFORMEE_CAP I 4 19 +V RW NP +LIM +0 1 1 +V RW NP +LIM +0 1 1 + +* +* Compressed Steering Number of Beamformer Antennas Supported +* Riva does not support,Pronto supports, default set to 0 +* +WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED I 4 19 +V RW NP +LIM +0 4 0 +V RW NP +LIM +0 4 0 + +* +* Number of Sounding Dimensions indicates Number +* of antennas used by the beamformer when sending beamformed transmissions +* Riva/Pronto does not support beamformer, default set to 0 +* +WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS I 4 19 +V RW NP +LIM +0 3 0 +V RW NP +LIM +0 3 0 + +* +* MU Beamformer Capable +* Riva/Pronto does not support, default set to 0 +* +WNI_CFG_VHT_MU_BEAMFORMER_CAP I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* MU Beamformee Capable +* Riva does not support but pronto supports, default set to 0 +* +WNI_CFG_VHT_MU_BEAMFORMEE_CAP I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* VHT TXOP PS +* Riva does not support but pronto supports, default set to 0 +* +WNI_CFG_VHT_TXOP_PS I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* +HTC-VHT Capable +* Riva does not support but pronto supports, default set to 0 +* +WNI_CFG_VHT_HTC_VHTC_CAP I 4 19 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* Maximum AMPDU Length exponent range 0-7 +* 2^(13+Max AMPDU Length)-1, default set to 0 +* +WNI_CFG_VHT_AMPDU_LEN_EXPONENT I 4 19 +V RW NP +LIM +0 7 3 +V RW NP +LIM +0 7 3 + +* +* VHT Link Adaptation Capable +* Riva does not support but pronto supports, default set to 0 +* +WNI_CFG_VHT_LINK_ADAPTATION_CAP I 4 19 +V RW NP +LIM +0 3 0 +V RW NP +LIM +0 3 0 + +* +* VHT Rx Antenna Pattern Consistency +* +WNI_CFG_VHT_RX_ANT_PATTERN I 4 19 +V RW NP +LIM +0 1 1 +V RW NP +LIM +0 1 1 + +* +* VHT Tx Antenna Pattern Consistency +* +WNI_CFG_VHT_TX_ANT_PATTERN I 4 19 +V RW NP +LIM +0 1 1 +V RW NP +LIM +0 1 1 + +* +* RxMCS Map is 16 bits, The 2bit Max MCS for n SS field. +* Indicates the maximum MCS that can be received for each +* number of spacial streams. Riva supports MCS 0-9 +* +WNI_CFG_VHT_RX_MCS_MAP I 4 19 +V RW NP +LIM +0 0xFFFF 0xFFFE +V RW NP +LIM +0 0xFFFF 0xFFFE + +* TxMCS Map is 16 bits, The 2bit Max MCS for n SS field. +* Indicates the maximum MCS that can be transmitted for each +* number of spacial streams. +* +WNI_CFG_VHT_TX_MCS_MAP I 4 19 +V RW NP +LIM +0 0xFFFF 0xFFFE +V RW NP +LIM +0 0xFFFF 0xFFFE + +* +* Rx Highest supported data rate. +* +WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE I 4 19 +V RW NP +LIM +0 780 780 +V RW NP +LIM +0 780 780 + +* +* Tx Highest supported data rate. +* +WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE I 4 19 +V RW NP +LIM +0 780 780 +V RW NP +LIM +0 780 780 + +* +* Channel center freq Seg1 +* +WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1 I 4 19 +V RW NP +LIM +0 256 0 +V RW NP +LIM +0 256 0 + +* +* Channel center freq Seg2 for 80+80 Mhz +* +WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2 I 4 19 +V RW NP +LIM +0 0 0 +V RW NP +LIM +0 0 0 + +* +* Basic MCS Set +* +WNI_CFG_VHT_BASIC_MCS_SET I 4 19 +V RW NP +LIM +0 0xFFFF 0xFFFE +V RW NP +LIM +0 0xFFFF 0xFFFE + +* +* MU-MIMO Capable STA Count +* +WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT I 4 19 +V RW NP +LIM +0 4 0 +V RW NP +LIM +0 4 0 + +* +* Spatial Stream Under-Utilization +* +WNI_CFG_VHT_SS_UNDER_UTIL I 4 19 +V RW NP +LIM +0 0 0 +V RW NP +LIM +0 0 0 + +* +* Forty MHZ Utilization +* +WNI_CFG_VHT_40MHZ_UTILIZATION I 4 19 +V RW NP +LIM +0 0 0 +V RW NP +LIM +0 0 0 + +* +* Eighty MHz Utilization +* +WNI_CFG_VHT_80MHZ_UTILIZATION I 4 19 +V RW NP +LIM +0 0 0 +V RW NP +LIM +0 0 0 + +* +* Hundred Sixty MHz Utilization +* +WNI_CFG_VHT_160MHZ_UTILIZATION I 4 19 +V RW NP +LIM +0 0 0 +V RW NP +LIM +0 0 0 + +* +* Maximum AMSDU length +* User can set it to either 3839 or 7935 bytes. +* +WNI_CFG_MAX_AMSDU_LENGTH I 4 7 +V RW NP RESTART +LIM +0 1 0 +V RW NP RESTART +LIM +0 1 0 + +#ENUM SHORT_3839_BYTES 0 +#ENUM LONG_7935__BYTES 1 + + +* +* Minimum MPDU Start Spacing +* Determines the minimum time between the start of adjacent MPDUs within an AMPDU. +* Set to 0 for no restriction +* Set to 1 for 1/4 s +* Set to 2 for 1/2 s +* Set to 3 for 1 s +* Set to 4 for 2 s +* Set to 5 for 4 s +* Set to 6 for 8 s +* Set to 7 for 16 s +* default is set to 0 +WNI_CFG_MPDU_DENSITY I 4 7 +V RW NP RESTART +LIM +0 7 0 +V RW NP RESTART +LIM +0 7 0 + +* +* NUM BUFFERS ADVERTISED +* Defines number of buffers advertised in ADDBA +* +WNI_CFG_NUM_BUFF_ADVERT I 4 7 +V RW NP +LIM +0 128 64 +V RW NP +LIM +0 128 64 + +* +* Maximum Rx AMPDU Factor +* Indicates the maximum length of A-MPDU +* that the STA can receive. +* The Maximum Rx A-MPDU defined by this field is equal to (2 ^ (13 + MAX RX AMPDU FActor))-1 octets. +* Maximum Rx A-MPDU Factor is an integer in the range 0 to 3. +* default is set to 2 for 32K max RX side. +* +WNI_CFG_MAX_RX_AMPDU_FACTOR I 4 7 +V RW NP RESTART +LIM +0 3 3 +V RW NP RESTART +LIM +0 3 3 + + +* +* Short GI support for the reception of 20Mhz packets +* By default it is enabled +* +WNI_CFG_SHORT_GI_20MHZ I 4 7 +V RW NP RESTART +LIM +0 1 1 +V RW NP RESTART +LIM +0 1 1 + + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + + +* +* Short GI support for the reception of 40Mhz packets +* By default it is enabled +* +WNI_CFG_SHORT_GI_40MHZ I 4 7 +V RW NP RESTART +LIM +0 1 0 +V RW NP RESTART +LIM +0 1 1 + + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + + +* +* RIFS support on TX Side +* on RX side it is always supported, it is mandatory +* +WNI_CFG_RIFS_ENABLED I 4 7 +V RW NP RESTART +NONE +0 1 1 +V RW NP RESTART +NONE +0 1 1 + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + + +* ********************************************************* +* +* Power Save Configuration +* +WNI_CFG_MAX_PS_POLL I 4 5 +V RW NP +LIM +0 255 0 +NV RW NP +LIM +0 255 0 + + +WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE I 4 5 +V RW NP +LIM +1 20 20 +NV RW NP +LIM +1 20 20 + + +* +* Period for which Firmware will collect the +* RSSI stats. Its in units of beacon interval. +* Rssi Filter period should always be >= +* the num_beacon_per_rssi_average. +* +WNI_CFG_RSSI_FILTER_PERIOD I 4 5 +V RW NP +LIM +0 255 5 +NV RW NP +LIM +0 255 5 + + +WNI_CFG_MIN_RSSI_THRESHOLD I 4 5 +V RW NP +LIM +0 10 10 +NV RW NP +LIM +0 10 10 + + +WNI_CFG_NTH_BEACON_FILTER I 4 5 +V RW NP +LIM +0 255 10 +NV RW NP +LIM +0 255 10 + + +WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE I 4 5 +V RW NP +LIM +0 1 0 +NV RW NP +LIM +0 1 0 + + +WNI_CFG_SCAN_IN_POWERSAVE I 4 5 +V RW NP +LIM +0 1 1 +V RW NP +LIM +0 1 1 + + +* +* Ignore DTIM support - If disabled(value=0), HAL will +* try to align the Listen Interval to the DTIM +* period and the following rules will be applied: +* 1) If LI=DTIM, then set LI=DTIM +* 2) If LIDTIM, then set LI=DTIM +* +WNI_CFG_IGNORE_DTIM I 4 5 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* ********************************************************* +* +* WoWLAN Configuration The following configurations +* are valid only when magicPktEnable = 1. +* +WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE I 4 5 +V RW NP +NONE +0 1 1 +NV RW NP +NONE +0 1 0 + + +WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE I 4 5 +V RW NP +NONE +0 1 1 +NV RW NP +NONE +0 1 0 + + +WNI_CFG_WOWLAN_DEAUTH_ENABLE I 4 5 +V RW NP +NONE +0 1 1 +NV RW NP +NONE +0 1 0 + + +WNI_CFG_WOWLAN_DISASSOC_ENABLE I 4 5 +V RW NP +NONE +0 1 1 +NV RW NP +NONE +0 1 0 + + +WNI_CFG_WOWLAN_MAX_MISSED_BEACON I 4 5 +V RW NP +NONE +0 65535 40 +NV RW NP +NONE +0 65535 40 + +* +* Timeout value in units of us. It requests +* hardware to unconditionally wake up after +* it has stayed in WoWLAN mode for some time. +* +WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD I 4 5 +V RW NP +NONE +0 65535 65535 +NV RW NP +NONE +0 65535 65535 + + +* +* BA timeout in TUs, set to 1 minute = approx 58593 TUs +* 16 bit wide +* +WNI_CFG_BA_TIMEOUT I 4 7 +V RW NP RESTART +HAL +0 0xffff 0 +V RW NP +HAL +0 0xffff 0 + + +* +* This threshold is registered with a traffic monitoring interface (probably HAL), +* on a per-STA, per-TID basis. Once this threshold has been reached, +* HAL will indicate to PE that the threshold has been reached for that TID. +* PE is then free to negotiate a BA session for that peer +* defaults to 128 +* 16 bit wide +* +WNI_CFG_BA_THRESHOLD_HIGH I 4 7 +V RW NP RESTART +HAL +0 0xffff 0x80 +V RW NP +HAL +0 0xffff 0x80 + + +* +* MAX BA Buffers to be allocated. +* This count is system wide. +* 16 bit wide +* +WNI_CFG_MAX_BA_BUFFERS I 4 7 +V RW NP RESTART +HAL +0 2560 2560 +V RW NP +HAL +0 2560 2560 + + +* +* MAX BA Sessions. +* This count is system wide. +* 16 bit wide +* +WNI_CFG_MAX_BA_SESSIONS I 4 7 +V RW NP RESTART +HAL +0 64 40 +V RW NP +HAL +0 64 40 + + +* +* BA setup based on Traffic +* +WNI_CFG_BA_AUTO_SETUP I 4 7 +V RW NP RESTART +HAL +0 1 1 +V RW NP RESTART +HAL +0 1 1 + +#ENUM ENABLE 1 +#ENUM DISABLE 0 + +* +* Decline an ADDBA Request +* +WNI_CFG_ADDBA_REQ_DECLINE I 4 7 +V RW NP RESTART +LIM +0 0xff 0 +V RW NP RESTART +LIM +0 0xff 0 + +* +* Delete all Rx BA sessions in 2.4 GHz +* when BTC requests to disable agg. +* +WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + + +* +* Valid Channel List +* + +WNI_CFG_BG_SCAN_CHANNEL_LIST S 100 8 +V RW NP +LIM +55 36 40 44 48 52 56 60 64 1 6 11 34 38 42 46 2 3 4 5 7 8 9 10 12 13 14 100 104 108 112 116 120 124 128 132 136 140 149 151 153 155 157 159 161 50 54 58 62 240 242 244 246 248 250 252 +V RW NP +LIM +55 36 40 44 48 52 56 60 64 1 6 11 34 38 42 46 2 3 4 5 7 8 9 10 12 13 14 100 104 108 112 116 120 124 128 132 136 140 149 151 153 155 157 159 161 50 54 58 62 240 242 244 246 248 250 252 + + +* +* AMPDU default TX medium Time (in us) +* +WNI_CFG_MAX_MEDIUM_TIME I 4 8 +V RW NP +HAL +0 65535 2048 +V RW NP +HAL +0 65535 2048 + + +* +* Maximum number of MPDUs in single A-MPDU. +* +WNI_CFG_MAX_MPDUS_IN_AMPDU I 4 8 +V RW NP +HAL +0 65535 64 +V RW NP +HAL +0 65535 64 + + +* +* Auto BSSID - When set, BSSID is generated automatically in IBSS, else BSSID in cfg will be used. +* + +WNI_CFG_IBSS_AUTO_BSSID I 4 0 +V RW NP +NONE +0 1 1 +NV RW NP +NONE +0 1 1 + +* +* Include Additional IEs in probe request. +* +WNI_CFG_PROBE_REQ_ADDNIE_FLAG I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* Include Additional IE in probe request. +* +WNI_CFG_PROBE_REQ_ADDNIE_DATA S 255 0 +V RW NP +NONE +0 0 +V RW NP +NONE +0 0 + +* +* Include Additional IEs in probe response. +* +WNI_CFG_PROBE_RSP_ADDNIE_FLAG I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* Include Additional IE in probe response. +* +WNI_CFG_PROBE_RSP_ADDNIE_DATA1 S 255 0 +V RW NP +NONE +0 0 +V RW NP +NONE +0 0 + +* +* Include Additional IE in probe response. +* +WNI_CFG_PROBE_RSP_ADDNIE_DATA2 S 255 0 +V RW NP +NONE +0 0 +V RW NP +NONE +0 0 + +* +* Include Additional IE in probe response. +* +WNI_CFG_PROBE_RSP_ADDNIE_DATA3 S 255 0 +V RW NP +NONE +0 0 +V RW NP +NONE +0 0 + +* +* Include Additional IEs in assoc response. +* +WNI_CFG_ASSOC_RSP_ADDNIE_FLAG I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* Include Additional IE in assoc response. +* +WNI_CFG_ASSOC_RSP_ADDNIE_DATA S 255 0 +V RW NP +NONE +0 0 +V RW NP +NONE +0 0 + +* +* Include Additional P2P IEs in probe request. +* +WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* Include Additional P2P IE in probe request. +* +WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA S 255 0 +V RW NP +NONE +0 0 +V RW NP +NONE +0 0 + + +* +* Include Additional IEs in probe response/beacon. +* +WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG I 4 0 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + + +* +* Include Additional IEs in probe response/beacon. +* +WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA S 255 0 +V RW NP +LIM +0 0 +V RW NP +LIM +0 0 + + +* +* wpsApEnable and wpsStaEnable is specified in here +* wpsApEnable is bit #0 and wpsStaEnable is bit #1 +* +WNI_CFG_WPS_ENABLE I 4 7 +V RW NP +LIM +0 0xff 0 +V RW NP +LIM +0 0xff 0 + +#ENUM AP 1 +#ENUM STA 2 + +WNI_CFG_WPS_STATE I 4 7 +V RW NP +LIM +0 0xff 1 +V RW NP +LIM +0 0xff 1 + +* +* TRUE => include this information in Probe Requests, FALSE => omit it +* + +WNI_CFG_WPS_PROBE_REQ_FLAG I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +* +* Wi-Fi Protected Setup Version +* +* This one-byte field is broken into a four-bit major +* part using the top MSBs and four-bit minor part +* using the LSBs. As an example, version 3.2 would be 0x32. +* + +WNI_CFG_WPS_VERSION I 4 7 +V RW NP +LIM +0 0xff 0x10 +V RW NP +LIM +0 0xff 0x10 + +* +* Wi-Fi Protected Setup Request type +* 0x00: Enrollee, Info only +* 0x01: Enrollee, open 802.1X +* 0x02: Registrar +* 0x03: WLAN Manager Registrar + +WNI_CFG_WPS_REQUEST_TYPE I 4 7 +V RW NP +LIM +0 0xff 0x00 +V RW NP +LIM +0 0xff 0x03 + +* Configuration Method(s) +* +* The Config Methods Data component lists the configuration methods +* the Enrollee or Registrar supports. The list is a bitwise OR of +* values from the table below. In addition to Config Methods, APs and +* STAs that support the UPnP Management Interface must support the +* Permitted Config Methods attribute, which is used to control the +* Config Methods that are enabled on that AP. +* +* Value Hardware Interface +* 0x0001 USBA (Flash Drive) +* 0x0002 Ethernet +* 0x0004 Label +* 0x0008 Display +* 0x0010 External NFC Token +* 0x0020 Integrated NFC Token +* 0x0040 NFC Interface +* 0x0080 PushButton +* 0x0100 Keypad +* +* The bottom 16 bits contain the configuration method(s) when acting +* as an Enrollee, and the top 16 when acting as a Registrar. +* +* QNE-TODO: Merge this with the inappropriately named +* 'WNI_CFG_WSC_AP_CFG_METHOD'-- this one can serve both puposes. +* + +WNI_CFG_WPS_CFG_METHOD I 4 7 +V RW NP +LIM +0 0xFFFFFFFF 0x00000008 +V RW NP +LIM +0 0xFFFFFFFF 0x018c018e + +* UUID +* The universally unique identifier (UUID) element is a unique +* GUID generated by the Enrollee or Registrar. It uniquely identifies +* an operational device and should survive reboots and resets. The +* UUID is provided in binary format. If the device also supports UPnP, +* then the UUID corresponds to the UPnP UUID. +* +* QNE-TODO: Re-name their cfg from 'WNI_CFG_UUID' + +WNI_CFG_WPS_UUID S 16 8 +V RW NP +LIM +6 0xa 0xb 0xc 0xd 0xe 0xf +V RW NP +LIM +6 0xa 0xb 0xc 0xd 0xe 0xf + +************************************************************************ +* The following cfgs contains the primary type of the device. Its format +* follows: +* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | Attribute ID | Length | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | Category ID | OUI (1-2) | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | OUI (3-4) | Sub Category ID | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* +* Vendor-specific sub-categories are designated by setting the OUI to the +* value associated with that vendor. Note that a four-byte subdivided OUI +* is used. For the predefined values, the Wi-Fi Alliance OUI of 00 50 F2 04 +* is used. The predefined values for Category ID and Sub Category ID are +* provided in the next table. There is no way to indicate a vendor-specific +* main device category. The OUI applies only to the interpretation of the +* Sub Category. If a vendor does not use sub categories for their OUI, the +* three-byte OUI occupies the first three bytes of the OUI field and the +* fourth byte is set to zero. +* +* Category ID Value Sub Category ID Value +* Computer 1 PC 1 +* Server 2 +* Media Center 3 +* Input Device 2 +* Printers, Scanners, Printer 1 +* Faxes and Copiers 3 Scanner 2 +* Camera 4 Digital Still Camera 1 +* Storage 5 NAS 1 +* Network AP 1 +* Infrastructure 6 Router 2 +* Switch 3 +* Displays 7 Television 1 +* Electronic Picture Frame 2 +* Projector 3 +* Multimedia Devices 8 DAR 1 +* PVR 2 +* MCX 3 +* Gaming Devices 9 Xbox 1 +* Xbox360 2 +* Playstation 3 +* Telephone 10 Windows Mobile 1 +* +************************************************************************ + +* QNE-TODO: Rename their cfg from 'WNI_CFG_PRIM_DEVICE_CATEGORY' +WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY I 4 7 +V RW NP +LIM +0 0xffff 1 +V RW NP +LIM +0 0xffff 6 + +* QNE-TODO: Rename their cfg from 'WNI_CFG_PRIM_DEVICE_OUI' +WNI_CFG_WPS_PIMARY_DEVICE_OUI I 4 7 +V RW NP +LIM +0 0xffffffff 0x0050f204 +V RW NP +LIM +0 0xffffffff 0x0050f204 + +* QNE-TODO: Rename their cfg from 'WNI_CFG_PRIM_DEVICE_SUB_CATEGORY' +WNI_CFG_WPS_DEVICE_SUB_CATEGORY I 4 7 +V RW NP +LIM +0 0xffff 1 +V RW NP +LIM +0 0xffff 1 + +* Association State +* + +* The Association State component shows the configuration and previous +* association state of the wireless station when sending a Discovery +* request. +* +* Association State Description +* 0 Not Associated +* 1 Connection Success +* 2 Configuration Failure +* 3 Association Failure +* 4 IP Failure + +WNI_CFG_WPS_ASSOCIATION_STATE I 4 7 +V RW NP +LIM +0 0xffff 0 +V RW NP +LIM +0 0xffff 0 + +* Configuration Error +* +* The Configuration Error component shows the result of the device +* attempting to configure itself and to associate with the WLAN. +* +* Configuration Error Description +* 0 No Error +* 1 OOB Interface Read Error +* 2 Decryption CRC Failure +* 3 2.4 channel not supported +* 4 5.0 channel not supported +* 5 Signal too weak +* 6 Network auth failure +* 7 Network association failure +* 8 No DHCP response +* 9 Failed DHCP config +* 10 IP address conflict +* 11 Couldnt connect to Registrar +* 12 Multiple PBC sessions detected +* 13 Rogue activity suspected +* 14 Device busy +* 15 Setup locked +* 16 Message Timeout +* 17 Registration Session Timeout +* 18 Device Password Auth Failure +* +* The Device busy error is returned if the sending device is unable to +* respond to the request due to some internal conflict or resource +* contention issue. For example, if a device is only capable of +* performing a single instance of the Registration Protocol at a time, +* it may return this error in response to attempts to start another +* instance in the middle of an active session. + +WNI_CFG_WPS_CONFIGURATION_ERROR I 4 7 +V RW NP +LIM +0 0xffff 0 +V RW NP +LIM +0 0xffff 0 + +* Device Password ID +* + +* This attribute is used to identify a device password. There are six +* predefined values and ten reserved values. If the Device Password ID is +* Default, the Enrollee should use its PIN password (from the label or +* display). This password may correspond to the label, display, or a +* user-defined password that has been configured to replace the original +* device password. +* +* User-specified indicates that the user has overridden the password with a +* manually selected value. Machine-specified indicates that the original +* PIN password has been overridden by a strong, machinegenerated device +* password value. The Rekey value indicates that the device's 256-bit +* rekeying password will be used. The PushButton value indicates that the +* PIN is the all-zero value reserved for the PushButton Configuration +* method. +* +* The Registrar-specified value indicates a PIN that has been obtained from +* the Registrar (via a display or other out-of-band method). This value may +* be further augmented with the optional 'Identity' attribute in M1. This +* augmentation is useful when multiple predefined UserID/PIN pairs have been +* established by a Registrar such as an authenticator used for Hotspot +* access. If the Device Password ID in M1 is not one of the predefined or +* reserved values, it corresponds to a password given to the Registrar as an +* OOB Device Password. +* +* Value Description +* 0x0000 Default (PIN) +* 0x0001 User-specified +* 0x0002 Machine-specified +* 0x0003 Rekey +* 0x0004 PushButton +* 0x0005 Registrar-specified +* 0x0006 - 0x000F Reserved' +* + +WNI_CFG_WPS_DEVICE_PASSWORD_ID I 4 7 +V RW NP +LIM +0 0xffffffff 0 +V RW NP +LIM +0 0xffffffff 0 + +* +* WPS Association +* +* Wi-Fi Protected Setup requires a prospective enrollee to associate to +* an AP in the network in which the STA would like to enroll. Once +* associated, the enrollment takes place over an EAPOL conversation +* (there's actually a new EAP method: EAP-WSC). The STA would +* presumably send an EAPOL-Start over his new link, to which the AP +* would respond with an EAP Identity Request. When the STA sends back +* "WSC-Enrollee-1" as his EAP Identity, the AP knows that he's got a WPS +* supplicant on his hands, and proceeds to talk EAP-WSC. +* +* Toward the end of the specification's development, a problem came up. +* Microsoft's EAP supplicant on XP SP1 & SP2 will send an EAPOL-Start, +* no matter what. Even if the AP is beaconing WPA-PSK, say, the MS +* supplicant will send an EAPOL-Start. If it receives an EAP Identity +* Request in return, it decides that the AP is really using 802.1x +* authentication, and proceeds on that assumption. +* +* Now, imagine an AP that is configured for WPA-PSK, and is WPS-capable. +* It receives an association request from some STA, and then sees an +* EAPOL-Start from the newly joined STA. It naturally sends back an EAP +* Identity Request to see if the new STA wants to talk EAP-WSC. On +* Windows XP SP1 & SP2, the supplicant will take that to mean that this +* AP is using 802.1x authentication, and will never let the user provide +* the PSK. Consequently, WZC will never be able to associate with this +* AP. +* +* Naturally, Microsoft's solution was to have the world change to +* accommodate them. After a lot of back & forth, the WFA decided on the +* following change to the WPS spec: when associating for purposes of WPS +* enrollment, "A client that intends to use the EAP-WSC method with a +* WSC enabled AP may include a WSC IE in its 802.11 (re)association +* request. If a WSC IE is present in the (re)association request, the AP +* shall engage in EAP-WSC with the station and must not attempt other +* security handshake. If the client does not include a WSC IE in its +* 802.11 (re)association request, it must send its 802.11 Authentication +* frame with Authentication set to open and an 802.11 Association +* Request frame without an RSN IE or SSN IE, regardless of the network +* type that is hosted by the AP. On successful association, the client +* will then send an EAPOL-Start to the AP and wait for +* EAP-Request/Identity. When the client receives an EAP Request/ +* Identity, it will respond with EAP-Response/Identity and the +* appropriate WSC string to indicate if it is an Enrollee or Registrar. +* ' +* +* This configuration variable contains a bitvector: +* +* 0x0001 Incldue the WPS Information Element in Assoc Request frames +* 0x0002 Elide the the WPA and RSN Information Elements from the +* Assoc Request frame +* + +WNI_CFG_WPS_ASSOC_METHOD I 4 7 +V RW NP +LIM +0 0xffff 0 +V RW NP +LIM +0 0xffff 0 + +* +* Low gain override +* + +WNI_CFG_LOW_GAIN_OVERRIDE I 4 9 +V RW NP +HAL +0 1 0 +V RW NP +HAL +0 1 0 + +* +* Listen Mode Enable/Disable +* + +WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE I 4 7 +V RW NP +HAL +0 128 128 +V RW NP +HAL +0 128 128 + +* +* On chip reodering polling threshold +* + +WNI_CFG_RPE_POLLING_THRESHOLD I 4 2 +V RW NP +HAL +0 65535 10 +V RW NP +HAL +0 65535 10 + +* +* On chip reodering aging threshold for AC0 +* + +WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG I 4 2 +V RW NP +HAL +0 65535 30 +V RW NP +HAL +0 65535 30 + +* +* On chip reodering aging threshold for AC1 +* + +WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG I 4 2 +V RW NP +HAL +0 65535 30 +V RW NP +HAL +0 65535 30 + +* +* On chip reodering aging threshold for AC2 +* + +WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG I 4 2 +V RW NP +HAL +0 65535 30 +V RW NP +HAL +0 65535 30 + +* +* On chip reodering aging threshold for AC3 +* + +WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG I 4 2 +V RW NP +HAL +0 65535 30 +V RW NP +HAL +0 65535 30 + +* +* Number of On-Chip reorder sessions +* + +WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS I 4 2 +V RW NP +HAL +0 2 1 +V RW NP +HAL +0 2 1 + + +* +* Single RC for all TID +* + +WNI_CFG_SINGLE_TID_RC I 4 7 +V RW NP +NONE +0 1 1 +V RW NP +NONE +0 1 1 + +* +* TX power control feature +* + +WNI_CFG_TX_PWR_CTRL_ENABLE I 4 8 +V RW NP +NONE +0 1 1 +V RW NP +NONE +0 1 1 + +* +* MCAST BCAST filter Setting +* 0: No filter, 1: Block Mcast, 2: Block Bcast, 3: Block Mcast and Bcast +* + +WNI_CFG_MCAST_BCAST_FILTER_SETTING I 4 7 +V RW NP +HAL +0 3 0 +V RW NP +HAL +0 3 0 + +* +* BTC DHCP No of Bt slots to block +* +WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK I 4 7 +V RW NP +HAL +0 0xFF 0 +V RW NP +HAL +0 0xFF 0 + +* +* Config parameter to Enable/Disable Dynamic PS-Poll mechanism +* 0: Disable, x: FW will send x number of NULL frames before switching to PS-Poll mexhanism +* +WNI_CFG_DYNAMIC_PS_POLL_VALUE I 4 7 +V RW NP +HAL +0 0xFF 0 +V RW NP +HAL +0 0xFF 0 + +* +* PS Data InActivity Timeout (TU) +* + +WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT I 4 7 +V RW NP +HAL +0 80 0 +NV RW NP +NONE +0 80 0 + +* +* Config parameter to Enable/Disable Telescopic Bcn Wakeups +* 0: Disable, 1: Enable +* + +WNI_CFG_TELE_BCN_WAKEUP_EN I 4 7 +V RW NP +HAL +0 1 0 +V RW NP +HAL +0 1 0 + + +* +* Config parameter for Transient LI +* 0: Disable, x: Transient LI +* + +WNI_CFG_TELE_BCN_TRANS_LI I 4 7 +V RW NP +HAL +0 7 3 +V RW NP +HAL +0 7 3 + +* +* Config parameter for Idle bcns for Transient LI +* x: Num Idle bcns before switch to trans LI +* + +WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS I 4 7 +V RW NP +HAL +5 255 10 +V RW NP +HAL +5 255 10 + +* +* Config parameter for Max LI +* 0: Disable, x: Max LI +* + +WNI_CFG_TELE_BCN_MAX_LI I 4 7 +V RW NP +HAL +0 7 5 +V RW NP +HAL +0 7 5 + +* +* Config parameter for Idle bcns for max LI +* x: Num Idle bcns before switch to max LI +* + +WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS I 4 7 +V RW NP +HAL +5 255 15 +V RW NP +HAL +5 255 15 + +* +* BTC DHCP No of Bt sub interval during DHCP +* +WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS I 4 7 +V RW NP +HAL +0 0xFF 7 +V RW NP +HAL +0 0xFF 7 + +* +* Infra STA mode Keep alive period (in secs) for +* sending keep alive (Qos)Null frames to the AP. +* 0 = disabled. Recommended values is 30 secs +* +WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD I 4 7 +V RW NP +HAL +0 1000 0 +V RW NP +HAL +0 1000 0 + +* Limit on number of associated stations +* (applies to peer stations in IBSS, SoftAP, BT-AMP AP, & P2P-GO modes) +* + +WNI_CFG_ASSOC_STA_LIMIT I 4 8 +V RW NP +LIM +1 32 10 +V RW NP +LIM +1 32 10 + +* +* SAP channel select start channel number +* +WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL I 4 7 +V RW NP +NONE +1 0xFC 1 +V RW NP +NONE +1 0xFC 1 + +* +* SAP channel select end channel number +* +WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL I 4 7 +V RW NP +NONE +1 0xFC 11 +V RW NP +NONE +1 0xFC 11 + +* +* SAP channel select operating band +* 0- 2.4GHZ / 1- Low 5GHZ /2-MID /3-HIGH/4-Japan4.9GHZ +* +WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND I 4 7 +V RW NP +NONE +0 0x5 0 +V RW NP +NONE +0 0x5 0 + +* +* Softap data available poll period (in milliseconds) for +* queueing (Qos)Null frames to the station if there +* is no data available and PS-Poll/Trigger frame is pending. +* 0 = disabled. Recommended values is 5ms +* +WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD I 4 8 +V RW NP +NONE +0 65535 5 +V RW NP +NONE +0 65535 5 + +* +* Close loop power control will be enabled if value is set to 1 +* +* +* +WNI_CFG_ENABLE_CLOSE_LOOP I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* LTE Coexistence will be enabled if value is set to 1 +* +* +* +WNI_CFG_ENABLE_LTE_COEX I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* AP Keep Alive Timeout (TU) +* +WNI_CFG_AP_KEEP_ALIVE_TIMEOUT I 4 7 +V RW NP +HAL +1 65535 20 +V RW NP +HAL +1 65535 20 + +* +* GO Keep Alive Timeout (TU) +* +WNI_CFG_GO_KEEP_ALIVE_TIMEOUT I 4 7 +V RW NP +HAL +1 65535 20 +V RW NP +HAL +1 65535 20 + +* +* MC Addr List power control will be enabled if value is set to 1 +* +* +* +WNI_CFG_ENABLE_MC_ADDR_LIST I 4 0 +V RW NP +HAL +0 1 0 +V RW NP +HAL +0 1 0 + +* +* UC Filter will be enabled if value is set to 1 +* +* +* +WNI_CFG_ENABLE_UC_FILTER I 4 0 +V RW NP +HAL +0 1 0 +V RW NP +HAL +0 1 0 + +* +* Low Power Image Transition will be enabled if value is set to 1 +* +* +* +WNI_CFG_ENABLE_LPWR_IMG_TRANSITION I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* MCC Adaptive Scheduler will be enabled if value is set to 1 +* +* +* +WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 +* +*Disable LDPC in STA mode when AP is TXBF capable +* +* +* +WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP I 4 0 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* AP Link Monitor Timeout (TU) +* +WNI_CFG_AP_LINK_MONITOR_TIMEOUT I 4 7 +V RW NP +HAL +1 255 3 +V RW NP +HAL +1 255 3 + +* +*TDLS Station's UAPSD MASK Configuration +* +* +* +WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK I 4 7 +V RW NP +LIM +0 15 0 +V RW NP +LIM +0 15 0 +* +*TDLS Stations Buffer STA Capability +* +* +* +WNI_CFG_TDLS_BUF_STA_ENABLED I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 +*TDLS Stations PUAPSD Inactivity Timer +* +* +* +WNI_CFG_TDLS_PUAPSD_INACT_TIME I 4 7 +V RW NP +LIM +0 10 0 +V RW NP +LIM +0 10 0 +*TDLS Stations PUAPSD RX Frame Threshold +* +* +* +WNI_CFG_TDLS_RX_FRAME_THRESHOLD I 4 7 +V RW NP +LIM +10 20 10 +V RW NP +LIM +10 20 10 + +* +* PMF SA Query Maximum Retries +* + +WNI_CFG_PMF_SA_QUERY_MAX_RETRIES I 4 1 +V RW NP RESTART +NONE +0 20 5 +V RW NP RESTART +NONE +0 20 5 + +* +* PMF SA Query Retry Interval (in TUs) +* + +WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL I 4 1 +V RW NP RESTART +NONE +10 2000 200 +V RW NP RESTART +NONE +10 2000 200 + + +* +*MCC ENABLE/DISABLE ADAPTIVE RX Drain feature +* +* +* +WNI_CFG_ENABLE_ADAPT_RX_DRAIN I 4 7 +V RW NP +HAL +0 1 1 +NV RW NP +HAL +0 1 1 + +* +* FlexConnect Power Factor +* Default is set to 0 (disable) +* +* +WNI_CFG_FLEX_CONNECT_POWER_FACTOR I 4 0 +V RW NP +NONE +0 9 0 +V RW NP +NONE +0 9 0 + +* +* Antenna Diversity +* +* 0 = disabled +* 1 = Ant 1 +* 2 = Ant 2 +* 3 = Adaptive +* +WNI_CFG_ANTENNA_DIVESITY I 4 7 +V RW NP +HAL +0 3 0 +V RW NP +HAL +0 3 0 + +* GO Link Monitor Timeout (TU) +* +WNI_CFG_GO_LINK_MONITOR_TIMEOUT I 4 7 +V RW NP +HAL +3 50 10 +V RW NP +HAL +3 50 10 +* +* + +* RMC action period frequency (milli seconds) +* +WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY I 4 7 +V RW NP +HAL +100 1000 300 +V RW NP +HAL +100 1000 300 +* +* + +* Current RSSI value (of connected AP) +* +WNI_CFG_CURRENT_RSSI I 4 7 +V RW NP +NONE +0 127 0 +V RW NP +NONE +0 127 0 + +* RTT3 Bit Value +* +WNI_CFG_RTT3_ENABLE I 1 1 +V RW NP +NONE +0 1 1 +V RW NP +NONE +0 1 1 + +* Debug p2p remain on channel +* +WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL I 4 7 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* TDLS Off Channel Implementation +* +WNI_CFG_TDLS_OFF_CHANNEL_ENABLED I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + +WNI_CFG_IBSS_ATIM_WIN_SIZE I 4 7 +V RW NP +NONE +0 100 0 +V RW NP +NONE +0 100 0 + +* +* DFS Master capability (11h) enable/disable +* + +WNI_CFG_DFS_MASTER_ENABLED I 4 7 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +WNI_CFG_VHT_ENABLE_TXBF_20MHZ I 4 7 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +*TDLS WMM Mode +* +* +WNI_CFG_TDLS_WMM_MODE_ENABLED I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/dot11f.frms b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/dot11f.frms new file mode 100644 index 000000000000..06d6a8a5af85 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgUtil/dot11f.frms @@ -0,0 +1,4017 @@ +/* + * Copyright (c) 2006-2007, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * \file dot11f.frms + * + * \brief Primary 'frames' file for the MAC parser + * + * + * This file defines several 802.11 frames (along with their associated + * constituents) in a little language called "frames". When run through the + * 'framesc' program, it will generate C code for working with these frames: + * C structs representing the 802.11 frame together with functions for + * packing & unpacking them. + * + * For more information on the "frames" language, run 'framesc --help'... + * + * + */ + + +// Tell framesc what types to use for... +%8-bit-type tANI_U8 // 8, +%16-bit-type tANI_U16 // 16, +%32-bit-type tANI_U32 // & 32-bit unsigned integral types. These can also + // be specified on the command line. + +// Define some mnemonic constants; these are just for our use with the frames +// files we're compiling. IOW, they won't result in any C code being +// emitted. + +const EID_SSID = 0; +const EID_SUPP_RATES = 1; +const EID_FH_PARAM_SET = 2; +const EID_DS_PARAM_SET = 3; +const EID_CF_PARAM_SET = 4; +const EID_TIM = 5; +const EID_IBSS_PARAM_SET = 6; +const EID_COUNTRY = 7; +const EID_FH_PATTERN = 8; +const EID_FH_PATT_TABLE = 9; +const EID_REQUEST = 10; +const EID_QBSS_LOAD = 11; +const EID_EDCA_PARAM_SET = 12; +const EID_TSPEC = 13; +const EID_TCLAS = 14; +const EID_SCHEDULE = 15; +const EID_CHALLENGE_TEXT = 16; +const EID_POWER_CONSTRAINTS = 32; +const EID_POWER_CAPABILITY = 33; +const EID_TPC_REQUEST = 34; +const EID_TPC_REPORT = 35; +const EID_SUPPORTED_CHANNELS = 36; +const EID_CHANNEL_SWITCH_ANN = 37; +const EID_MEAS_REQUEST = 38; +const EID_MEAS_REPORT = 39; +const EID_QUIET = 40; +const EID_ERP_INFO = 42; +const EID_TS_DELAY = 43; +const EID_TCLASS_PROC = 44; +const EID_HT_CAPABILITIES = 45; +const EID_QOS_CAPABILITY = 46; +const EID_RSN = 48; +const EID_EXT_SUPP_RATES = 50; +const EID_AP_CHAN_REPORT = 51; +const EID_NEIGHBOR_REPORT = 52; +const EID_RCPI = 53; +const EID_FT_MOBILITY_DOMAIN = 54; +const EID_FT_INFO = 55; +const EID_TIMEOUT_INTERVAL = 56; +const EID_FT_RIC_DATA = 57; +const EID_SUPPORTED_OPER_CLASSES = 59; +const EID_EXT_CHAN_SWITCH = 60; +const EID_HT_INFO = 61; +const EID_SEC_CHAN_OFFSET = 62; +const EID_RSNI = 65; +const EID_RRM_MEAS_PILOT_TX_INFO = 66; +const EID_WAPI = 68; +const EID_TIME_ADVERTISEMENT = 69; +const EID_RRM_ENABLED_CAPS = 70; +const EID_MULTIPLE_BSSID = 71; +const EID_20_40_BSS_COEXISTENCE = 72; +const EID_20_40_BSS_INTOLERANT_REPORT= 73; +const EID_OBSS_SCAN_PARAMETERS = 74; +const EID_FT_RIC_DESCRIPTOR = 75; +const EID_LINK_IDENTIFIER = 101; +const EID_PTI_CONTROL = 105; +const EID_PU_BUFFER_STATUS = 106; +const EID_QOS_MAP_SET = 110; +const EID_ESE_SPECIFIC = 150; +const EID_ESE_CCKM_SPECIFIC = 156; +const EID_VHT_CAPABILITIES = 191; +const EID_VHT_OPERATION_ELEMENT = 192; +const EID_VHT_EXT_BSS_LOAD = 193; +const EID_AID = 197; +const EID_EXT_CAP = 127; +const EID_OPERATING_MODE = 199; +const EID_WIDER_BW_CHANNEL_SWITCH_ANN= 194; +const EID_CHANNEL_SWITCH_WRAPPER = 196; +const EID_VENDOR_SPECIFIC = 221; + +const SIR_MAC_PROP_EXT_RATES_TYPE = 0; +const SIR_MAC_PROP_AP_NAME_TYPE = 1; +const SIR_MAC_PROP_HCF_TYPE = 2; +const SIR_MAC_PROP_WDS_TYPE = 3; +const SIR_MAC_PROP_BP_IND_TYPE = 4; +const SIR_MAC_PROP_NEIGHBOR_BSS_TYPE = 5; +const SIR_MAC_PROP_LOAD_INFO_TYPE = 6; +const SIR_MAC_PROP_ASSOC_TYPE = 7; +const SIR_MAC_PROP_LOAD_BALANCE_TYPE = 8; +const SIR_MAC_PROP_LL_ATTR_TYPE = 9; +const SIR_MAC_PROP_CAPABILITY = 10; +const SIR_MAC_PROP_VERSION = 11; +const SIR_MAC_PROP_EDCAPARAMS = 12; +const SIR_MAC_PROP_CHANNEL_SWITCH = 15; +const SIR_MAC_PROP_QUIET_BSS = 16; +const SIR_MAC_PROP_TRIG_STA_BK_SCAN = 17; + +const ANI_WDS_INFO_MAX_LENGTH = 64; +const SIR_MAC_MAX_NUMBER_OF_RATES = 12; +const HT_MAX_SUPPORTED_MCS_SET = 16; +const MAX_SUPPORTED_NEIGHBOR_RPT = 15; + +///////////////////////////////////////////////////////////////////////////// +// Wi-Fi Protected Setup TLV Identifiers // +// WSC Version 2.0.0 Table 28 // +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// Wi-Fi Simple Configuration TLV Identifiers // +// WFA Vendor Extension Subelements // +///////////////////////////////////////////////////////////////////////////// +const TLV_VERSION2 = 0; +const TLV_AUTHORIZED_MAC = 1; +const TLV_NETWORK_KEY_SHAREABLE = 2; +const TLV_REQUEST_TO_ENROLL = 3; +const TLV_SETTINGS_DELAY_TIME = 4; + +const TLV_VERSION = 0x104A; +const TLV_WI_FI_SIMPLE_CONFIG_STATE = 0x1044; +const TLV_AP_SETUP_LOCKED = 0x1057; +const TLV_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053; +const TLV_DEVICE_PASSWORD_ID = 0x1012; +const TLV_UUID_E = 0x1047; +const TLV_UUID_R = 0x1048; +const TLV_RF_BANDS = 0x103C; +const TLV_REQUEST_TYPE = 0x103A; +const TLV_RESPONSE_TYPE = 0x103B; +const TLV_CONFIG_METHODS = 0x1008; +const TLV_PRIMARY_DEVICE_TYPE = 0x1054; +const TLV_ASSOCIATION_STATE = 0x1002; +const TLV_CONFIGURATION_ERROR = 0x1009; +const TLV_MANUFACTURER = 0x1021; +const TLV_MODEL_NAME = 0x1023; +const TLV_MODEL_NUMBER = 0x1024; +const TLV_SERIAL_NUMBER = 0x1042; +const TLV_DEVICE_NAME = 0x1011; +const TLV_SELECTED_REGISTRAR = 0x1041; +const TLV_VENDOR_EXTENSION = 0x1049; +const TLV_REQUESTED_DEVICE_TYPE = 0x106A; + +///////////////////////////////////////////////////////////////////////////// +// Wi-Fi Direct/P2P TLV Identifiers // +///////////////////////////////////////////////////////////////////////////// +const TLV_P2P_STATUS = 0; +const TLV_MINOR_REASON_CODE = 1; +const TLV_P2P_CAPABILITY = 2; +const TLV_P2P_DEVICE_ID = 3; +const TLV_P2P_GROUP_OWNER_INTENT = 4; +const TLV_CONFIGURATION_TIMEOUT = 5; +const TLV_LISTEN_CHANNEL = 6; +const TLV_P2P_GROUP_BSSID = 7; +const TLV_EXTENDED_LISTEN_TIMING = 8; +const TLV_INTENDED_P2P_INTERFACE_ADDRESS = 9; +const TLV_P2P_MANAGEABILITY = 10; +const TLV_CHANNEL_LIST = 11; +const TLV_NOTICE_OF_ABSENCE = 12; +const TLV_P2P_DEVICE_INFO = 13; +const TLV_P2P_GROUP_INFO = 14; +const TLV_P2P_GROUP_ID = 15; +const TLV_P2P_INTERFACE = 16; +const TLV_OPERATING_CHANNEL = 17; +const TLV_INVITATION_FLAGS = 18; +const TLV_P2P_VENDOR_SPECIFIC = 221; + +///////////////////////////////////////////////////////////////////////////// +// Fixed Fields + +FF AuthAlgo (2) // C.f. Sec. 7.3.1.1 +{ + algo, 2; +} + +FF AuthSeqNo (2) // 7.3.1.2 +{ + no, 2; +} + +FF BeaconInterval (2) // 7.3.1.3 +{ + interval, 2; +} + +FF Capabilities (2) // 7.3.1.4 +{ + { + ess: 1; + ibss: 1; + cfPollable: 1; + cfPollReq: 1; + privacy: 1; + shortPreamble: 1; + pbcc: 1; + channelAgility: 1; + spectrumMgt: 1; + qos: 1; + shortSlotTime: 1; + apsd: 1; + rrm: 1; + dsssOfdm: 1; + delayedBA: 1; + immediateBA: 1; + } +} + +FF CurrentAPAddress(6) // 7.3.1.5 +{ + mac[6]; +} + +FF ListenInterval (2) // 7.3.1.6 +{ + interval, 2; +} + +FF Reason (2) // 7.3.1.7 +{ + code, 2; +} + +FF AID (2) // 7.3.1.8 +{ + associd, 2; +} + +FF Status (2) // 7.3.1.9 +{ + status, 2; +} + +FF TimeStamp (8) // 7.3.1.10 +{ + timestamp, 8; +} + +FF Category (1) // 7.3.1.11 +{ + category, 1; +} + +FF Action (1) // 7.3.1.11 +{ + action, 1; +} + +FF TransactionId (2) // 7.3.1.11 +{ + transId[2]; +} + +FF DialogToken (1) // 7.3.1.12 +{ + token, 1; +} + +FF StatusCode (1) // WMM Spec 2.2.10 +{ + statusCode, 1; +} + +FF OperatingMode (1) +{ + { + //Operating Mode field + chanWidth: 2; + reserved: 2; + rxNSS: 3; + rxNSSType: 1; + } +} +FF AddBAParameterSet (2) // 7.3.1.14 +{ + { + amsduSupported: 1; + policy: 1; + tid: 4; + bufferSize: 10; + } +} + +FF BATimeout (2) // 7.3.1.15 +{ + timeout, 2; +} + +FF BAStartingSequenceControl (2) // 7.2.1.7 +{ + { + fragNumber: 4; + ssn: 12; + } +} + +FF DelBAParameterSet (2) // 7.3.1.16 +{ + { + reserved: 11; + initiator: 1; + tid: 4; + } +} + +FF SMPowerModeSet (1) //7.3.1.25 +{ + { + PowerSave_En: 1; + Mode: 1; + reserved: 6; + } +} + +FF TSInfo (3) // 7.3.2.30 +{ + { + traffic_type: 1; + tsid: 4; + direction: 2; + access_policy: 2; + aggregation: 1; + psb: 1; + user_priority: 3; + tsinfo_ack_pol: 2; + schedule: 1; + unused: 15; + } +} + +FF NumOfRepetitions (2) +{ + repetitions, 2; +} + +FF TxPower (1) +{ + txPower, 1; +} + +FF MaxTxPower (1) +{ + maxTxPower, 1; +} +FF TPCEleID (1) +{ + TPCId, 1; +} +FF TPCEleLen (1) +{ + TPCLen, 1; +} +FF LinkMargin (1) +{ + linkMargin, 1; +} +FF RxAntennaId (1) +{ + antennaId, 1; +} +FF TxAntennaId (1) +{ + antennaId, 1; +} +FF RCPI (1) +{ + rcpi, 1; +} +FF RSNI (1) +{ + rsni, 1; +} + +FF P2POUI (4) +{ + oui, 4; +} + +FF P2POUISubType (1) +{ + ouiSubtype, 1; +} + +FF VhtMembershipStatusArray(8) // 8.4.1.51 +{ + membershipStatusArray[8]; +} + +FF VhtUserPositionArray(16) // 8.4.1.52 +{ + userPositionArray[16]; +} + +FF ext_chan_switch_ann_action(4) +{ + { + switch_mode: 8; + op_class: 8; + new_channel: 8; + switch_count: 8; + } +} +///////////////////////////////////////////////////////////////////////////// +// TLVs // +///////////////////////////////////////////////////////////////////////////// + +/** + * \brief Version + * + * WPS 1.0h + * Version specifies the Easy Setup version. The one-byte field is broken + * into a four-bit major part using the top MSBs and four-bit minor part + * using the LSBs. As an example, version 3.2 would be 0x32. + * + * WSC 2.0.0 + * Deprecated Version mechanism. This attribute is always set to value 0x10 + * (version 1.0) for backwards compatibility. Version 1.0h of the specification + * did not fully describe the version negotiation mechanism and version 2.0 + * introduced a new subelement (Version2) for indicating the version number + * to avoid potential interoperability issues with deployed 1.0h-based devices. + * + */ + +TLV Version( TLV_VERSION ) ( 2 : 2 ) MSB +{ + { + minor: 4; + major: 4; + } +} + +/// Wi-Fi Protected Setup State +TLV WPSState( TLV_WI_FI_SIMPLE_CONFIG_STATE ) ( 2 : 2 ) MSB +{ + state, 1; +} + +/** + * \brief AP Setup Locked + * + * + * This variable indicates that the AP has entered a state in which it will + * refuse to allow an external Registrar to attempt to run the Registration + * Protocol using the AP?s PIN (with the AP acting as Enrollee). The AP + * should enter this state if it believes a brute force attack is underway + * against the AP?s PIN. + * + * When the AP is in this state, it MUST continue to allow other Enrollees to + * connect and run the Registration Protocol with any external Registrars or + * the AP's built-in Registrar (if any). It is only the use of the AP' PIN + * for adding external Registrars that is disabled in this state. + * + * The AP Setup Locked state can be reset to FALSE through an authenticated + * call to SetAPSettings. APs may provide other implementation-specific + * methods of resetting the AP Setup Locked state as well. + * + * + */ + +TLV APSetupLocked( TLV_AP_SETUP_LOCKED ) ( 2 : 2 ) MSB +{ + fLocked, 1; +} + +/** + * \brief Selected Registrar Config Methods + * + * + * This attribute has the same values that Config Methods have. It is used in + * Probe Response messages to convey the Config Methods of the selected + * Registrar. + * + * + */ + +TLV SelectedRegistrarConfigMethods ( TLV_SELECTED_REGISTRAR_CONFIG_METHODS ) ( 2 : 2 ) MSB +{ + methods, 2; +} + +/** + * \brief UUID-E + * + * + * The universally unique identifier (UUID) element is a unique GUID + * generated by the Enrollee. It uniquely identifies an operational device + * and should survive reboots and resets. The UUID is provided in binary + * format. If the device also supports UPnP, then the UUID corresponds to the + * UPnP UUID. + * + * + */ + +TLV UUID_E ( TLV_UUID_E ) ( 2 : 2 ) MSB +{ + uuid[ 16 ]; +} + +/** + * \brief UUID-R + * + * + * The universally unique identifier (UUID) element is a unique GUID + * generated by the Registrar. It uniquely identifies an operational device + * and should survive reboots and resets. The UUID is provided in binary + * format. If the device also supports UPnP, then the UUID corresponds to the + * UPnP UUID. + * + * + */ + +TLV UUID_R ( TLV_UUID_R ) ( 2 : 2 ) MSB +{ + uuid[ 16 ]; +} + +/** + * \brief RF Bands + * + * + \code + + 0x01 2.4GHz + 0x02 5.0GHz + + \endcode + * + * + */ + +TLV RFBands ( TLV_RF_BANDS ) ( 2 : 2 ) MSB +{ + bands, 1; +} + + +/** + * \brief Selected Registrar + * + * + * This field indicates that a Registrar has been selected by a user and that + * an Enrollee should proceed with setting up an 802.1X uncontrolled data + * port with the Registrar. + * + * + */ + +TLV SelectedRegistrar ( TLV_SELECTED_REGISTRAR ) ( 2 : 2 ) MSB +{ + selected, 1; +} + +/** + * \brief Config Methods + * + * + * The Config Methods Data component lists the configuration methods the + * Enrollee or Registrar supports. The list is a bitwise OR of values from + * the table below. In addition to Config Methods, APs and STAs that support + * the UPnP Management Interface must support the Permitted Config Methods + * attribute, which is used to control the Config Methods that are enabled on + * that AP. + * + \code + + Value Hardware Interface + 0x0001 USBA (Flash Drive) + 0x0002 Ethernet + 0x0004 Label + 0x0008 Display + 0x0010 External NFC Token + 0x0020 Integrated NFC Token + 0x0040 NFC Interface + 0x0080 PushButton + 0x0100 Keypad + + \endcode + * + * + */ + +TLV ConfigMethods ( TLV_CONFIG_METHODS ) ( 2 : 2 ) MSB +{ + methods, 2; +} + +/** + * \brief Association State + * + * + * The Association State component shows the configuration and previous + * association state of the wireless station when sending a Discovery + * request. + * + \code + + Association State Description + 0 Not Associated + 1 Connection Success + 2 Configuration Failure + 3 Association Failure + 4 IP Failure + + \endcode + * + * + */ + +TLV AssociationState ( TLV_ASSOCIATION_STATE ) ( 2 : 2 ) MSB +{ + state, 2; +} + +/** + * \brief Configuration Error + * + * + * The Configuration Error component shows the result of the device + * attempting to configure itself and to associate with the WLAN. + * + \code + + Configuration Error Description + 0 No Error + 1 OOB Interface Read Error + 2 Decryption CRC Failure + 3 2.4 channel not supported + 4 5.0 channel not supported + 5 Signal too weak + 6 Network auth failure + 7 Network association failure + 8 No DHCP response + 9 Failed DHCP config + 10 IP address conflict + 11 Couldn't connect to Registrar + 12 Multiple PBC sessions detected + 13 Rogue activity suspected + 14 Device busy + 15 Setup locked + 16 Message Timeout + 17 Registration Session Timeout + 18 Device Password Auth Failure + + \endcode + * + * The Device busy error is returned if the sending device is unable to + * respond to the request due to some internal conflict or resource + * contention issue. For example, if a device is only capable of performing a + * single instance of the Registration Protocol at a time, it may return this + * error in response to attempts to start another instance in the middle of + * an active session. + * + * + */ + +TLV ConfigurationError ( TLV_CONFIGURATION_ERROR ) ( 2 : 2 ) MSB +{ + error, 2; +} + +TLV Manufacturer ( TLV_MANUFACTURER ) ( 2 : 2 ) MSB +{ + name[ 0..64 ]; +} + +TLV ModelName ( TLV_MODEL_NAME ) ( 2 : 2 ) MSB +{ + text[ 0..32 ]; +} + +TLV ModelNumber ( TLV_MODEL_NUMBER ) ( 2 : 2 ) MSB +{ + text[ 0..32 ]; +} + +TLV SerialNumber ( TLV_SERIAL_NUMBER ) ( 2 : 2 ) MSB +{ + text[ 0..32 ]; +} + +TLV DeviceName ( TLV_DEVICE_NAME ) ( 2 : 2 ) MSB +{ + text[ 0..32 ]; +} + +/** + * \brief Device Password ID + * + * + * This attribute is used to identify a device password. There are six + * predefined values and ten reserved values. If the Device Password ID is + * Default, the Enrollee should use its PIN password (from the label or + * display). This password may correspond to the label, display, or a + * user-defined password that has been configured to replace the original + * device password. + * + * User-specified indicates that the user has overridden the password with a + * manually selected value. Machine-specified indicates that the original + * PIN password has been overridden by a strong, machinegenerated device + * password value. The Rekey value indicates that the device's 256-bit + * rekeying password will be used. The PushButton value indicates that the + * PIN is the all-zero value reserved for the PushButton Configuration + * method. + * + * The Registrar-specified value indicates a PIN that has been obtained from + * the Registrar (via a display or other out-of-band method). This value may + * be further augmented with the optional 'Identity' attribute in M1. This + * augmentation is useful when multiple predefined UserID/PIN pairs have been + * established by a Registrar such as an authenticator used for Hotspot + * access. If the Device Password ID in M1 is not one of the predefined or + * reserved values, it corresponds to a password given to the Registrar as an + * OOB Device Password. + * + \code + + Value Description + + 0x0000 Default (PIN) + 0x0001 User-specified + 0x0002 Machine-specified + 0x0003 Rekey + 0x0004 PushButton + 0x0005 Registrar-specified + 0x0006 - 0x000F Reserved + + \endcode + * + * + */ + +TLV DevicePasswordID ( TLV_DEVICE_PASSWORD_ID ) ( 2 : 2 ) MSB +{ + id, 2; +} + + +/** + * \brief Primary Device Type + * + * + * This attribute contains the primary type of the device. Its format + * follows: + * + \code + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Attribute ID | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Category ID | OUI (1-2) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | OUI (3-4) | Sub Category ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endcode + * + * Vendor-specific sub-categories are designated by setting the OUI to the + * value associated with that vendor. Note that a four-byte subdivided OUI + * is used. For the predefined values, the Wi-Fi Alliance OUI of 00 50 F2 04 + * is used. The predefined values for Category ID and Sub Category ID are + * provided in the next table. There is no way to indicate a vendor-specific + * main device category. The OUI applies only to the interpretation of the + * Sub Category. If a vendor does not use sub categories for their OUI, the + * three-byte OUI occupies the first three bytes of the OUI field and the + * fourth byte is set to zero. + * + * + \code + + Category ID Value Sub Category ID Value + Computer 1 PC 1 + Server 2 + Media Center 3 + Input Device 2 + Printers, Scanners, Printer 1 + Faxes and Copiers 3 Scanner 2 + Camera 4 Digital Still Camera 1 + Storage 5 NAS 1 + Network AP 1 + Infrastructure 6 Router 2 + Switch 3 + Displays 7 Television 1 + Electronic Picture Frame 2 + Projector 3 + Multimedia Devices 8 DAR 1 + PVR 2 + MCX 3 + Gaming Devices 9 Xbox 1 + Xbox360 2 + Playstation 3 + Telephone 10 Windows Mobile 1 + + \endcode + * + * + */ + +TLV PrimaryDeviceType ( TLV_PRIMARY_DEVICE_TYPE ) ( 2 : 2 ) MSB +{ + primary_category, 2; + oui[ 4 ]; + sub_category, 2; +} + + +/** + * \brief Request Type + * + * + * The Request Type component specifies the mode in which the device will + * operate in for this setup exchange. If the device is an Enrollee, it may + * send only discovery messages or it may also request that the Registrar + * proceed with opening a data connection. This protocol allows Enrollees to + * more efficiently discover devices on the network. + + * If the device indicates that it intends to engage setup either as a + * Registrar or an Enrollee, the Access Point continues to indicate that it + * will operate as an AP in the response. The Request Type attribute is + * carried throughout the 802.1X data channel setup process in the Wi-Fi + * Protected Setup IE. There are two sub-types of Registrars: WLAN Manager + * Registrar indicates that this Registrar intends to manage the AP or STA + * settings using UPnP. It will derive a UPnP AP or STA Management key. The + * ordinary Registrar type indicates that this Registrar does not intend to + * subsequently manage the Enrollee's settings. APs must not derive AP + * Management Keys for an ordinary Registrar. If a Registrar does not intend + * to be a WLAN Manager Registrar, it should set the Request Type to + * Registrar. Doing so avoids needlessly consuming resources on the AP. + + \code + + Request Type Value Description + 0x00 Enrollee, Info only + 0x01 Enrollee, open 802.1X + 0x02 Registrar + 0x03 WLAN Manager Registrar + + \endcode + * + * + */ + +TLV RequestType ( TLV_REQUEST_TYPE ) ( 2 : 2 ) MSB +{ + reqType, 1; +} + +/** + * \brief Response Type + * + * + * The Response Type component specifies the operational mode of the + * device for this setup exchange. The Response Type IE is carried + * throughout the 802.1X data channel setup process. + + \code + + Response Type Value Description + 0x00 Enrollee, Info only + 0x01 Enrollee, open 802.1X + 0x02 Registrar + 0x03 AP + +\endcode + * + * + */ + +TLV ResponseType ( TLV_RESPONSE_TYPE ) ( 2 : 2 ) MSB +{ + resType, 1; +} + + +/////////////////////////////////////////////////////////////////////////// +// WiFi Direct/P2P TLVs // +/////////////////////////////////////////////////////////////////////////// + +/** + * \brief P2P Status Attribute + */ + +TLV P2PStatus ( TLV_P2P_STATUS ) ( 1 : 2 ) LSB +{ + status, 1; +} + + +/** + * \brief Minor Reason Code Attribute + */ + +TLV MinorReasonCode ( TLV_MINOR_REASON_CODE ) ( 1 : 2 ) LSB +{ + minorReasonCode, 1; +} + + +/** + * \brief P2P Capability Attribute + */ + +TLV P2PCapability ( TLV_P2P_CAPABILITY ) ( 1 : 2 ) LSB +{ + deviceCapability, 1; + groupCapability, 1; +} + + +/** + * \brief P2P Device Id Attribute + */ + +TLV P2PDeviceId ( TLV_P2P_DEVICE_ID ) ( 1 : 2 ) LSB +{ + P2PDeviceAddress[6]; +} + + +/** + * \brief Group Owner Intent Attribute + */ + +TLV GOIntent ( TLV_P2P_GROUP_OWNER_INTENT ) ( 1 : 2 ) LSB +{ + GOIntent, 1; +} + + +/** + * \brief Configuration Timeout Attribute + */ + +TLV ConfigurationTimeout ( TLV_CONFIGURATION_TIMEOUT ) ( 1 : 2 ) LSB +{ + GOConfigTimeout, 1; + CLConfigTimeout, 1; +} + + +/** + * \brief Listen Channel Attribute + */ + +TLV ListenChannel ( TLV_LISTEN_CHANNEL ) ( 1 : 2 ) LSB +{ + countryString[3]; + regulatoryClass, 1; + channel, 1; +} + + +/** + * \brief P2P Group BSSID Attribute + */ + +TLV P2PGroupBssid ( TLV_P2P_GROUP_BSSID ) ( 1 : 2 ) LSB +{ + P2PGroupBssid[6]; +} + + +/** + * \brief Extended Listen Attribute + */ + +TLV ExtendedListenTiming ( TLV_EXTENDED_LISTEN_TIMING ) ( 1 : 2 ) LSB +{ + availibilityPeriod, 2; + availibilityInterval, 2; +} + + +/** + * \brief Intended P2P Interface Address Attribute + */ + +TLV IntendedP2PInterfaceAddress ( TLV_INTENDED_P2P_INTERFACE_ADDRESS ) ( 1 : 2 ) LSB +{ + P2PInterfaceAddress[6]; +} + + +/** + * \brief P2P Manageability Attribute + */ + +TLV P2PManageability ( TLV_P2P_MANAGEABILITY ) ( 1 : 2 ) LSB +{ + manageability, 1; +} + + +/** + * \brief ChannelList Attribute + */ + +TLV ChannelList ( TLV_CHANNEL_LIST ) ( 1 : 2 ) LSB +{ + countryString[3]; + channelList[0..251]; +} + + +/** + * \brief Notice of Absence + */ + +TLV NoticeOfAbsence ( TLV_NOTICE_OF_ABSENCE ) ( 1 : 2 ) LSB +{ + index, 1; + CTSWindowOppPS, 1; + NoADesc[0..36]; +} + +/** + * \brief P2P Device Info Attribute + */ + +TLV P2PDeviceInfo ( TLV_P2P_DEVICE_INFO ) ( 1 : 2 ) LSB +{ + P2PDeviceAddress[6]; + configMethod, 2 , FLIPBYTEORDER; + primaryDeviceType[8]; + MANDATORYTLV DeviceName; +} + + +/** + * \brief P2P Group Info Attribute + */ + +TLV P2PGroupInfo ( TLV_P2P_GROUP_INFO ) ( 1 : 2 ) LSB +{ + P2PClientInfoDesc[0..1024]; +} + + +/** + * \brief P2P Group Id Attribute + */ + +TLV P2PGroupId ( TLV_P2P_GROUP_ID ) ( 1 : 2 ) LSB +{ + deviceAddress[6]; + ssid[0..32]; +} + + +/** + * \brief P2P Interface Attribute + */ + +TLV P2PInterface ( TLV_P2P_INTERFACE ) ( 1 : 2 ) LSB +{ + P2PDeviceAddress[6]; +} + + +/** + * \brief Operating Channel Attribute + */ + +TLV OperatingChannel ( TLV_OPERATING_CHANNEL ) ( 1 : 2 ) LSB +{ + countryString[3]; + regulatoryClass, 1; + channel, 1; +} + + +/** + * \brief Invitation Flags Attribute + */ + +TLV InvitationFlags ( TLV_INVITATION_FLAGS ) ( 1 : 2 ) LSB +{ + invitationFlags, 1; +} + +/** + * \brief Vendor Extension + * + * This variable permits vendor extensions in the Wi-Fi Simple + * Configuration TLV framework. The Vendor Extension figure + * illustrates the implementation of vendor extensions. Vendor + * ID is the SMI network management private enterprise code + * + * +-----------+----------------------+ + * | Vendor ID | Vendor Data | + * +-----------+----------------------+ + * |<--- 3 --->|<----- 1 - 1021 ----->| + * + */ + +TLV VendorExtension ( TLV_VENDOR_EXTENSION ) ( 2 : 2 ) MSB +{ + /* + * vendorId is the SMI network management private enterprise code. + * WFA Vendor ID 0x00372A + * + */ + vendorId[ 3 ]; + + /** + * \breif Version2 + * + * The Version2 field specifies the version Wi-Fi Simple + * Configuration implemented by the device sending this attribute. + * The one-byte field is broken into a four-bit major part using + * the top MSBs and four-bit minor part using the LSBs. As an example, + * version 3.2 would be 0x32. This subelement was added in the + * specification version 2.0 and if the subelement is not included + * in a message, the transmitter of the message is assumed to + * use version 1.0. + * + */ + OPTIONALTLV TLV Version2 ( TLV_VERSION2 ) ( 1 : 1 ) MSB + { + { + minor: 4; + major: 4; + } + } + /** + * \brief AuthorizedMACs + * + * This subelement contains a list of Enrollee MAC addresses (each + * being six bytes in length) that have been registered to start WSC. + * The AP includes this field in Beacon and Probe Response frames so + * Enrollees can tell if they have been registered to start WSC. There + * may be multiple Enrollees active on the network, but not all of them have + * been registered to start WSC. This element allows an Enrollee to detect + * if they should start WSC with the AP. The AuthorizedMACs field augments + * the use of the Selected Registrar. + * + */ + OPTIONALTLV TLV AuthorizedMACs ( TLV_AUTHORIZED_MAC ) ( 1 : 1 ) MSB + { + mac[6]; + } + + /** + * \brief Request to Enroll + * + * This optional subelement in the WSC IE in Probe Request or M1 indicates + * the desire to enroll in the network by setting its value to TRUE. If the + * Registrar gets this subelement it can use this as a trigger that a device + * wants to enroll (maybe an indication can be shown to the user). The device + * must set it to FALSE after the registration protocol completion. + * + */ + OPTIONALTLV TLV RequestToEnroll( TLV_REQUEST_TO_ENROLL ) ( 1 : 1 ) MSB + { + req, 1; + } +} + +/** + * \brief Requested Device Type + * + * This attribute contains the requested device type of a Wi-Fi + * Direct device. + * + * This attribute allows a device to specify the Primary Device Type + * or the Secondary Device Type of other devices it is interested in. + * Only a device that receives a Probe Request containing a WSC IE with + * this attribute and with a Primary Device Type or Secondary Device Type + * that matches the Requested Device Type will respond with a Probe Response. + * + * Its format and contents is identical to the 'Primary Device Type'. + * + * Both the Category ID and Sub Category ID can be used as a filter. If only + * looking for devices with a certain Category ID, the OUI and Sub Category ID + * fields will have to be set to zero. + * + */ +TLV RequestDeviceType ( TLV_REQUESTED_DEVICE_TYPE ) ( 2 : 2 ) MSB +{ + primary_category, 2; + oui[ 4 ]; + sub_category, 2; +} + +///////////////////////////////////////////////////////////////////////////// +// Information Elements + +IE SSID (EID_SSID) // C.f. Sec. 7.3.2.1 +{ + ssid[0..32]; +} + +IE SuppRates (EID_SUPP_RATES) // 7.3.2.2 +{ + rates[0..SIR_MAC_MAX_NUMBER_OF_RATES]; +} + +IE FHParamSet (EID_FH_PARAM_SET) // 7.3.2.3 +{ + dwell_time, 2; + hop_set, 1; + hop_pattern, 1; + hop_index, 1; +} + +IE DSParams (EID_DS_PARAM_SET) // 7.3.2.4 +{ + curr_channel, 1; +} + +IE CFParams (EID_CF_PARAM_SET) // 7.3.2.5 +{ + cfp_count, 1; + cfp_period, 1; + cfp_maxduration, 2; + cfp_durremaining, 2; +} + +IE TIM (EID_TIM) // 7.3.2.6 +{ + dtim_count, 1; + dtim_period, 1; + bmpctl, 1; + vbmp[1..251]; +} + +IE IBSSParams (EID_IBSS_PARAM_SET) // 7.3.2.7 +{ + atim, 2; +} + +IE ChallengeText (EID_CHALLENGE_TEXT) // 7.3.2.8 +{ + text[1..253]; +} + +IE RequestedInfo (EID_REQUEST) // 7.3.2.12 +{ + requested_eids[0..255]; +} + +IE Country (EID_COUNTRY) // 7.3.2.9 +{ + country[3]; + OPTIONAL triplets[3][0..84]; +} + +IE FHParams (EID_FH_PATTERN) // 7.3.2.10 +{ + radix, 1; + nchannels, 1; +} + +IE FHPattTable (EID_FH_PATT_TABLE) // 7.3.2.11 +{ + flag, 1; + nsets, 1; + modulus, 1; + offset, 1; + randtable[0..251]; +} + +IE ERPInfo (EID_ERP_INFO) // 7.3.2.13 +{ + { + non_erp_present : 1; + use_prot: 1; + barker_preamble: 1; + unused: 5; + } +} + +IE ExtSuppRates (EID_EXT_SUPP_RATES) // 7.3.2.14 +{ + rates[1..SIR_MAC_MAX_NUMBER_OF_RATES]; +} + +IE PowerConstraints (EID_POWER_CONSTRAINTS) // 7.3.2.15 +{ + localPowerConstraints, 1; +} + +IE PowerCaps (EID_POWER_CAPABILITY) // 7.3.2.16 +{ + minTxPower, 1; + maxTxPower, 1; +} + +IE TPCRequest (EID_TPC_REQUEST) // 7.3.2.17 +{ } + +IE TPCReport (EID_TPC_REPORT) // 7.3.2.18 +{ + tx_power, 1; + link_margin, 1; +} + +IE SuppChannels (EID_SUPPORTED_CHANNELS) // 7.2.3.19 +{ + bands[2][1..48]; +} + +IE SuppOperatingClasses (EID_SUPPORTED_OPER_CLASSES) +{ + classes[1..32]; +} + +IE ChanSwitchAnn (EID_CHANNEL_SWITCH_ANN) // 7.3.2.20 +{ + switchMode, 1; + newChannel, 1; + switchCount, 1; +} + +IE ext_chan_switch_ann (EID_EXT_CHAN_SWITCH) // 8.4.2.55 +{ + switch_mode, 1; + new_reg_class, 1; + new_channel, 1; + switch_count, 1; +} + +IE sec_chan_offset_ele (EID_SEC_CHAN_OFFSET) // 7.3.2.20a +{ + secondaryChannelOffset, 1; +} + +IE Quiet (EID_QUIET) // 7.3.2.23 +{ + count, 1; + period, 1; + duration, 2; + offset, 2; +} + +IE RSN (EID_RSN) // 7.3.2.25 +{ + // The version is 2 octets, and we only support version 1. + version, 2 MUSTBE 1; + // The next four octets will be the Group Cipher Suite + gp_cipher_suite[4]; + // The IE *may* stop here; if there's any more, we should see two more + // octets giving the number of Pairwise Cipher Suites + OPTIONAL pwise_cipher_suite_count, 2; + // I don't see anything in the Standard limiting the number of Pairwise + // Cypher Suites, other than the maximum length of an IE, which limits us + // to 61. However, that seems needlessly wasteful of space. + pwise_cipher_suites[4][0..4] COUNTIS pwise_cipher_suite_count; + // Optional count of AKM suite selectors + OPTIONAL akm_suite_count, 2; + // Again, I see nothing in the Standard explicitly limiting the number of + // AKM suite selectors other than the maximum size of an IE. + akm_suites[4][0..4] COUNTIS akm_suite_count; + OPTIONAL RSN_Cap[2]; + // Finally, the IE may contain zero or more PMKIDs: + OPTIONAL pmkid_count, 2; + pmkid[16][0..4] COUNTIS pmkid_count; + OPTIONAL gp_mgmt_cipher_suite[4]; +} + +IE RSNOpaque (EID_RSN) // 7.3.2.25 +{ + data[ 6..253 ]; +} + +IE WAPI (EID_WAPI) // 7.3.2.25 +{ + // The version is 2 octets, and we only support version 1. + version, 2 MUSTBE 1; + // count of AKM suite selectors + akm_suite_count, 2; + // Again, I see nothing in the Standard explicitly limiting the number of + // AKM suite selectors other than the maximum size of an IE. + akm_suites[4][0..4] COUNTIS akm_suite_count; + // we should see two more + // octets giving the number of Unicast Cipher Suites + unicast_cipher_suite_count, 2; + // I don't see anything in the Standard limiting the number of Pairwise + // Cypher Suites, other than the maximum length of an IE, which limits us + // to 61. However, that seems needlessly wasteful of space. + unicast_cipher_suites[4][0..4] COUNTIS unicast_cipher_suite_count; + // The next four octets will be the Multicast Cipher Suite + multicast_cipher_suite[4]; + // WAPI capabilities + { + preauth: 1; + reserved: 15; + } + // Finally, the IE may contain zero or more BKIDs: + OPTIONAL bkid_count, 2; + bkid[16][0..4] COUNTIS bkid_count; +} + +IE WAPIOpaque (EID_WAPI) // 7.3.2.25 +{ + data[ 6..253 ]; +} + +IE QBSSLoad (EID_QBSS_LOAD) // 7.3.2.28 +{ + stacount, 2; + chautil, 1; + avail, 2; +} + +IE EDCAParamSet (EID_EDCA_PARAM_SET) // 7.3.2.29 +{ + qos, 1; // ToDo: This is a bitfield whose format + // depends on whether this is from an AP + // or a STA, information which I'm not + // sure we have at parse time... + reserved, 1; + { + acbe_aifsn: 4; + acbe_acm: 1; + acbe_aci: 2; + unused1: 1; + } + { + acbe_acwmin: 4; + acbe_acwmax: 4; + } + acbe_txoplimit, 2; + { + acbk_aifsn: 4; + acbk_acm: 1; + acbk_aci: 2; + unused2: 1; + } + { + acbk_acwmin: 4; + acbk_acwmax: 4; + } + acbk_txoplimit, 2; + { + acvi_aifsn: 4; + acvi_acm: 1; + acvi_aci: 2; + unused3: 1; + } + { + acvi_acwmin: 4; + acvi_acwmax: 4; + } + acvi_txoplimit, 2; + { + acvo_aifsn: 4; + acvo_acm: 1; + acvo_aci: 2; + unused4: 1; + } + { + acvo_acwmin: 4; + acvo_acwmax: 4; + } + acvo_txoplimit, 2; +} + +IE TSPEC (EID_TSPEC) // 7.3.2.30 +{ + + // TS Info + { + traffic_type: 1; + tsid: 4; + direction: 2; + access_policy: 2; + aggregation: 1; + psb: 1; + user_priority: 3; + tsinfo_ack_pol: 2; + } + { + schedule: 1; + unused: 7; + } + + // Nominal MSDU Size + { + size: 15; + fixed: 1; + } + + max_msdu_size, 2; + min_service_int, 4; + max_service_int, 4; + inactivity_int, 4; + suspension_int, 4; + service_start_time, 4; + min_data_rate, 4; + mean_data_rate, 4; + peak_data_rate, 4; + burst_size, 4; + delay_bound, 4; + min_phy_rate, 4; + surplus_bw_allowance, 2; + medium_time, 2; + +} // End IE TSPEC. + +IE TCLAS (EID_TCLAS) // 7.3.2.31 +{ + user_priority, 1; + classifier_type, 1; + classifier_mask, 1; + UNION info (DISCRIMINATOR classifier_type) + { + EthParams (classifier_type IS 0) + { + source[6]; + dest[6]; + type, 2; + } + IpParams (classifier_type IS 1) + { + version, 1; + UNION params (DISCRIMINATOR version) + { + IpV4Params (version IS 4) + { + source[4]; + dest[4]; + src_port, 2; + dest_port, 2; + DSCP, 1; + proto, 1; + reserved, 1; + } + IpV6Params (version IS 6) + { + source[16]; + dest[16]; + src_port, 2; + dest_port, 2; + flow_label[3]; + } + }; + } + Params8021dq (classifier_type IS 2) + { + tag_type, 2; + } + }; +} // End IE TCLASS + +const EID_RRM_BEACON_REPORTING = 1; +const EID_RRM_BCN_REPORTING_DETAIL = 2; + +IE BeaconReporting (EID_RRM_BEACON_REPORTING) +{ + reportingCondition, 1; + threshold, 1; +} + +IE BcnReportingDetail (EID_RRM_BCN_REPORTING_DETAIL) +{ + reportingDetail, 1; +} + +IE APChannelReport (EID_AP_CHAN_REPORT) +{ + regulatoryClass, 1; + channelList[0..50]; +} + +IE MeasurementRequest (EID_MEAS_REQUEST) // 7.3.2.21 +{ + measurement_token, 1; + + // Measurement Request Mode + { + parallel: 1; + enable: 1; + request: 1; + report: 1; + durationMandatory: 1; + unused: 3; + } + + measurement_type, 1; + UNION measurement_request (DISCRIMINATOR measurement_type) + { + Basic (measurement_type IS 0) + { + channel_no, 1; + meas_start_time[8]; + meas_duration, 2; + } + CCA (measurement_type IS 1) + { + channel_no, 1; + meas_start_time[8]; + meas_duration, 2; + } + RPIHistogram (measurement_type IS 2) + { + channel_no, 1; + meas_start_time[8]; + meas_duration, 2; + } + Beacon (measurement_type IS 5) + { + regClass, 1; + channel, 1; + randomization, 2; + meas_duration, 2; + meas_mode, 1; + BSSID[6]; + OPTIE SSID; + OPTIE BeaconReporting; + OPTIE BcnReportingDetail; + OPTIE RequestedInfo; + OPTIE APChannelReport[0..2]; + //OPTIONAL vendor_specific[1..239]; + } + + }; +} + +const EID_BCN_REPORT_FRAME_BODY = 1; +IE BeaconReportFrmBody (EID_BCN_REPORT_FRAME_BODY) +{ + reportedFields[0..224]; +} + +IE MeasurementReport (EID_MEAS_REPORT) // 7.3.2.22 +{ + token, 1; + // Measurement Report Mode + { + late: 1; + incapable: 1; + refused: 1; + unused: 5; + } + type, 1; + OPTIONAL UNION report (DISCRIMINATOR type) + { + Basic (type IS 0) // 7.3.2.22.1 + { + channel, 1; + meas_start_time, 8; + meas_duration, 2; + // Map + { + bss: 1; + ofdm_preamble: 1; + unid_signal: 1; + rader: 1; + unmeasured: 1; + unused: 3; + } + } + CCA (type IS 1) + { + channel, 1; + meas_start_time, 8; + meas_duration, 2; + cca_busy_fraction, 1; + } + RPIHistogram (type IS 2) + { + channel, 1; + meas_start_time, 8; + meas_duration, 2; + rpi0_density, 1; + rpi1_density, 1; + rpi2_density, 1; + rpi3_density, 1; + rpi4_density, 1; + rpi5_density, 1; + rpi6_density, 1; + rpi7_density, 1; + } + Beacon (type IS 5) + { + regClass, 1; + channel, 1; + meas_start_time, 8; + meas_duration, 2; + // reported_frame_info, + { + condensed_PHY: 7; + reported_frame_type: 1; + } + RCPI, 1; + RSNI, 1; + BSSID[6]; + antenna_id, 1; + parent_TSF, 4; + OPTIE BeaconReportFrmBody; + //IE vendor_specific + } + }; +} + +IE TSDelay (EID_TS_DELAY) // 7.3.2.32 +{ + delay, 4; +} + +IE TCLASSPROC (EID_TCLASS_PROC) // 7.3.2.33 +{ + processing, 1; +} + +IE Schedule (EID_SCHEDULE) // 7.3.2.34 +{ + { + aggregation: 1; + tsid: 4; + direction: 2; + reserved: 9; + } + service_start_time, 4; + service_interval, 4; + max_service_dur, 2; + spec_interval, 2; +} + +IE QOSCapsAp (EID_QOS_CAPABILITY) // 7.3.2.35 +{ + { + count: 4; + qack: 1; + qreq: 1; + txopreq: 1; + reserved: 1; + } +} + +IE QOSCapsStation (EID_QOS_CAPABILITY) // 7.3.2.35 +{ + { + acvo_uapsd: 1; + acvi_uapsd: 1; + acbk_uapsd: 1; + acbe_uapsd: 1; + qack: 1; + max_sp_length: 2; + more_data_ack: 1; + } +} + +IE LinkIdentifier (EID_LINK_IDENTIFIER) // 7.3.2.62 +{ + bssid[6]; + InitStaAddr[6]; + RespStaAddr[6]; +} + +IE WPA (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x01) +{ + // This IE's first two octets should be interpreted as a version number; + // we only support version 1. + version, 2 MUSTBE 1; + // A four-octet Multicast Cipher may or may not appear next (hence the + // OPTIONAL keyword) + OPTIONAL multicast_cipher[4]; + // Optional Unicast Cipher count + OPTIONAL unicast_cipher_count, 2; + // Next comes an array of four-octet Cipher Suite selectors; the COUNTIS + // clause indicates that the actual number of selectors seen is in the + // member 'unicast_cipher_count'. + unicast_ciphers[4][0..4] COUNTIS unicast_cipher_count; + // (Optional) Authentication suites: + OPTIONAL auth_suite_count, 2; + auth_suites[4][0..4] COUNTIS auth_suite_count; + // This field is declared optional as per bugs 15234, 14755, & 14991. + OPTIONAL caps, 2; +} + +IE WPAOpaque (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x01) +{ + data[ 2..249 ]; +} + +IE WMMInfoStation (EID_VENDOR_SPECIFIC) OUI(0x00, 0x50, 0xF2, 0x02, 0x00) +{ + // This IE contains the QoS Info field when sent from WMM Station + version, 1; + { + acvo_uapsd: 1; + acvi_uapsd: 1; + acbk_uapsd: 1; + acbe_uapsd: 1; + reserved1: 1; + max_sp_length: 2; + reserved2: 1; + } +} + +IE WMMInfoAp (EID_VENDOR_SPECIFIC) OUI(0x00, 0x50, 0xF2, 0x02, 0x00) +{ + // This IE contains the QoS Info field when sent from WMM AP + version, 1; + { + param_set_count: 4; + reserved: 3; + uapsd: 1; + } +} + + +IE WMMParams (EID_VENDOR_SPECIFIC) OUI(0x00, 0x50, 0xF2, 0x02, 0x01) +{ + version, 1 MUSTBE 1; + qosInfo, 1; // ToDo: This is actually a + // bitfield, but it's format + // varies depending on whether + // the sender is a STA or AP... + reserved2, 1; + { + acbe_aifsn: 4; + acbe_acm: 1; + acbe_aci: 2; + unused1: 1; + } + { + acbe_acwmin: 4; + acbe_acwmax: 4; + } + acbe_txoplimit, 2; + { + acbk_aifsn: 4; + acbk_acm: 1; + acbk_aci: 2; + unused2: 1; + } + { + acbk_acwmin: 4; + acbk_acwmax: 4; + } + acbk_txoplimit, 2; + { + acvi_aifsn: 4; + acvi_acm: 1; + acvi_aci: 2; + unused3: 1; + } + { + acvi_acwmin: 4; + acvi_acwmax: 4; + } + acvi_txoplimit, 2; + { + acvo_aifsn: 4; + acvo_acm: 1; + acvo_aci: 2; + unused4: 1; + } + { + acvo_acwmin: 4; + acvo_acwmax: 4; + } + acvo_txoplimit, 2; +} + +IE WMMTSPEC (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xf2, 0x02, 0x02) +{ + version, 1 MUSTBE 1; + + // TS Info + { + traffic_type: 1; + tsid: 4; + direction: 2; + access_policy: 2; + aggregation: 1; + psb: 1; + user_priority: 3; + tsinfo_ack_pol: 2; + } + { + tsinfo_rsvd: 7; + burst_size_defn: 1; + } + + // Nominal MSDU Size + { + size: 15; + fixed: 1; + } + + max_msdu_size, 2; + min_service_int, 4; + max_service_int, 4; + inactivity_int, 4; + suspension_int, 4; + service_start_time, 4; + min_data_rate, 4; + mean_data_rate, 4; + peak_data_rate, 4; + burst_size, 4; + delay_bound, 4; + min_phy_rate, 4; + surplus_bw_allowance, 2; + medium_time, 2; + +} // End IE WMMTSpec. + +IE WMMCaps (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x02, 0x05) +{ + version, 1 MUSTBE 1; + { + reserved: 4; + qack: 1; + queue_request: 1; + txop_request: 1; + more_ack: 1; + } +} + +IE WMMTCLAS (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x02, 0x06) +{ + version, 1 MUSTBE 1; + + user_priority, 1; + classifier_type, 1; + classifier_mask, 1; + UNION info (DISCRIMINATOR classifier_type) + { + EthParams (classifier_type IS 0) + { + source[6]; + dest[6]; + type, 2; + } + IpParams (classifier_type IS 1) + { + version, 1; + UNION params (DISCRIMINATOR version) + { + IpV4Params (version IS 4) + { + source[4]; + dest[4]; + src_port, 2; + dest_port, 2; + DSCP, 1; + proto, 1; + reserved, 1; + } + IpV6Params (version IS 6) + { + source[16]; + dest[16]; + src_port, 2; + dest_port, 2; + flow_label[3]; + } + }; + } + Params8021dq (classifier_type IS 2) + { + tag_type, 2; + } + }; + +} + +IE WMMTCLASPROC (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x02, 0x07) +{ + version, 1 MUSTBE 1; + processing, 1; +} + +IE WMMTSDelay (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x02, 0x08) +{ + version, 1 MUSTBE 1; + delay, 4; +} + +IE WMMSchedule (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x02, 0x09) +{ + version, 1 MUSTBE 1; + + { + aggregation: 1; + tsid: 4; + direction: 2; + reserved: 9; + } + + service_start_time, 4; + service_interval, 4; + max_service_dur, 2; + spec_interval, 2; +} + +IE ESERadMgmtCap (EID_VENDOR_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x01) +{ + + mgmt_state, 1; + + { + mbssid_mask: 3; + reserved: 5; + } + +} + +IE Vendor1IE (EID_VENDOR_SPECIFIC) OUI (0x00, 0x10, 0x18) +{ +} + +IE Vendor2IE (EID_VENDOR_SPECIFIC) OUI (0x00, 0x90, 0x4C) +{ +} + +IE Vendor3IE (EID_VENDOR_SPECIFIC) OUI (0x00, 0x16, 0x32) +{ +} + +IE QComVendorIE (EID_VENDOR_SPECIFIC) OUI (0x00, 0xA0, 0xC6) +{ + type, 1; + channel, 1; +} + +IE ESETrafStrmMet (EID_VENDOR_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x07) +{ + tsid, 1; + state, 1; + msmt_interval, 2; +} + +IE ESETrafStrmRateSet (EID_VENDOR_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x08) +{ + tsid, 1; + tsrates[0..8]; +} + +IE ESEVersion (EID_VENDOR_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x03) +{ + version, 1; +} + +IE ESETxmitPower (EID_ESE_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x00) +{ + power_limit, 1; + reserved, 1; +} + +IE ESECckmOpaque (EID_ESE_CCKM_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x00) +{ + data[ 6..20 ]; +} + +IE RRMEnabledCap (EID_RRM_ENABLED_CAPS) +{ + //Capability bitmap + { + LinkMeasurement: 1; + NeighborRpt: 1; + parallel: 1; + repeated: 1; + BeaconPassive: 1; + BeaconActive: 1; + BeaconTable: 1; + BeaconRepCond: 1; + } + { + FrameMeasurement: 1; + ChannelLoad: 1; + NoiseHistogram: 1; + statistics: 1; + LCIMeasurement: 1; + LCIAzimuth: 1; + TCMCapability: 1; + triggeredTCM: 1; + } + { + APChanReport: 1; + RRMMIBEnabled: 1; + operatingChanMax: 3; + nonOperatinChanMax: 3; + } + { + MeasurementPilot: 3; + MeasurementPilotEnabled: 1; + NeighborTSFOffset: 1; + RCPIMeasurement: 1; + RSNIMeasurement: 1; + BssAvgAccessDelay: 1; + } + { + BSSAvailAdmission: 1; + AntennaInformation: 1; + fine_time_meas_rpt: 1; + lci_capability: 1; + reserved: 4; + } +} + +IE MeasurementPilot (EID_RRM_MEAS_PILOT_TX_INFO) +{ + measurementPilot, 1; + vendorSpecific[0..255]; //Should be an IE. But currently only one level of nesting allowed. Can ignore for now. +} + +IE MultiBssid (EID_MULTIPLE_BSSID) +{ + maxBSSIDIndicator, 1; + vendorSpecific[0..255]; +} + +IE OBSSScanParameters (EID_OBSS_SCAN_PARAMETERS) +{ + obssScanPassiveDwell, 2; + obssScanActiveDwell, 2; + bssChannelWidthTriggerScanInterval, 2; + obssScanPassiveTotalPerChannel, 2; + obssScanActiveTotalPerChannel, 2; + bssWidthChannelTransitionDelayFactor, 2; + obssScanActivityThreshold, 2; +} + +IE HT2040BSSCoexistence (EID_20_40_BSS_COEXISTENCE) +{ + // 20/40 BSS Coexistence Information + { + infoRequest: 1; + fortyMHzIntolerant: 1; + twentyMHzBssWidthReq: 1; + obssScanExemptionReq: 1; + obssScanExemptionGrant: 1; + unused: 3; + } +} + +IE HT2040BSSIntolerantReport (EID_20_40_BSS_INTOLERANT_REPORT) +{ + operatingClass, 1; + channelList[0..50]; +} + +const EID_RRM_NBR_RPT_TSF = 1; +const EID_RRM_NBR_CD_COUNTRY = 2; +const EID_RRM_NBR_MSMT_PILOT_TX_INFO = 66; + +IE NeighborReport (EID_NEIGHBOR_REPORT) +{ + bssid[6]; + //Bssid Info + { + APReachability: 2; + Security: 1; + KeyScope: 1; + //Capabilities + SpecMgmtCap: 1; + QosCap: 1; + apsd: 1; + rrm: 1; + } + //Capabilities contd. + { + DelayedBA: 1; + ImmBA: 1; + //Capabilities end. + MobilityDomain: 1; + reserved: 5; + } + + reserved1, 2; //part of BSSID Info. + + regulatoryClass, 1; + channel, 1; + PhyType, 1; + OPTIE IE TSFInfo (EID_RRM_NBR_RPT_TSF) + { + TsfOffset, 2; + BeaconIntvl, 2; + } + OPTIE IE CondensedCountryStr (EID_RRM_NBR_CD_COUNTRY) + { + countryStr[2]; + } + OPTIE IE MeasurementPilot; // (EID_RRM_NBR_MSMT_PILOT_TX_INFO) +// { +// measurementPilot, 1; +// vendorSpecific[0..255]; //Should be an IE. But currently only one level of nesting allowed. Can ignore for now. +// } + OPTIE IE RRMEnabledCap; + OPTIE IE MultiBssid; + //Ignoring vendor specific. +} + +IE RCPIIE (EID_RCPI) +{ + rcpi, 1; +} + +IE RSNIIE (EID_RSNI) +{ + rsni, 1; +} + +IE WFATPC (EID_VENDOR_SPECIFIC) OUI (0x00, 0x50, 0xF2, 0x08, 0x00) +{ + txPower, 1; + linkMargin, 1; +} + +IE MobilityDomain (EID_FT_MOBILITY_DOMAIN) +{ + MDID, 2; + //FT Capability and policy + { + overDSCap: 1; + resourceReqCap: 1; + reserved: 6; + } +} +const SUB_EID_FT_R1KH_ID = 1; +const SUB_EID_FT_GTK = 2; +const SUB_EID_FT_R0KH_ID = 3; +const SUB_EID_FT_IGTK = 4; +IE FTInfo (EID_FT_INFO) +{ + // MicControl, 2; + { + reserved: 8; + IECount: 8; + } + MIC[16]; + Anonce[32]; + Snonce[32]; + + OPTIE IE R1KH_ID (SUB_EID_FT_R1KH_ID) + { + PMK_R1_ID[6]; + } + + OPTIE IE GTK (SUB_EID_FT_GTK) + { + //Key Info + { + keyId: 2; + reserved: 14; + } + keyLength, 1; + RSC[8]; + key[5..32]; + } + + OPTIE IE R0KH_ID (SUB_EID_FT_R0KH_ID) + { + PMK_R0_ID[1..48]; + } + + OPTIE IE IGTK (SUB_EID_FT_IGTK) + { + //Key Info + keyID[2]; + IPN[6]; + keyLength, 1; + key[24]; + } +} + +IE TimeoutInterval (EID_TIMEOUT_INTERVAL) +{ + timeoutType, 1; + timeoutValue, 4; +} + +//TODO: need to define this properly. +IE RICData (EID_FT_RIC_DATA) +{ + Identifier, 1; + resourceDescCount, 1; + statusCode, 2; +} + +IE RICDescriptor (EID_FT_RIC_DESCRIPTOR) +{ + resourceType, 1; + variableData[0..255]; //Block ack param set...TODO: +} + +IE WscIEOpaque (EID_VENDOR_SPECIFIC) OUI ( 0x00, 0x50, 0xF2, 0x04 ) +{ + data[ 2..249 ]; +} + +IE P2PIEOpaque (EID_VENDOR_SPECIFIC) OUI ( 0x50, 0x6F, 0x9A, 0x09 ) +{ + data[ 2..249 ]; +} + +IE WFDIEOpaque (EID_VENDOR_SPECIFIC) OUI ( 0x50, 0x6F, 0x9A, 0x0A ) +{ + data[ 2..249 ]; +} + +IE PTIControl (EID_PTI_CONTROL) // 7.3.2.65 +{ + tid, 1; + sequence_control, 2; +} + +IE PUBufferStatus (EID_PU_BUFFER_STATUS) // 7.3.2.66 +{ + { + ac_bk_traffic_aval: 1; + ac_be_traffic_aval: 1; + ac_vi_traffic_aval: 1; + ac_vo_traffic_aval: 1; + reserved: 4; + } +} + + + +IE VHTCaps (EID_VHT_CAPABILITIES) +{ + //VHT Capability Info + { + maxMPDULen: 2; + supportedChannelWidthSet: 2; + ldpcCodingCap: 1; + shortGI80MHz: 1; + shortGI160and80plus80MHz: 1; + txSTBC: 1; + rxSTBC: 3; + suBeamFormerCap: 1; + suBeamformeeCap: 1; + csnofBeamformerAntSup: 3; + numSoundingDim: 3; + muBeamformerCap: 1; + muBeamformeeCap: 1; + vhtTXOPPS: 1; + htcVHTCap: 1; + maxAMPDULenExp: 3; + vhtLinkAdaptCap: 2; + rxAntPattern: 1; + txAntPattern: 1; + reserved1: 2; + } + rxMCSMap, 2; + { + rxHighSupDataRate: 13; + reserved2: 3; + } + txMCSMap, 2; + { + txSupDataRate: 13; + reserved3: 3; + } +} + +IE VHTOperation (EID_VHT_OPERATION_ELEMENT) +{ + chanWidth, 1; + chanCenterFreqSeg1, 1; + chanCenterFreqSeg2, 1; + basicMCSSet, 2; +} + +IE VHTExtBssLoad (EID_VHT_EXT_BSS_LOAD) +{ + muMIMOCapStaCount, 1; + ssUnderUtil, 1; + FortyMHzUtil, 1; + EightyMHzUtil, 1; + OneSixtyMHzUtil, 1; +} + +IE AID (EID_AID) +{ + assocId, 2; +} + +IE WiderBWChanSwitchAnn (EID_WIDER_BW_CHANNEL_SWITCH_ANN) +{ + newChanWidth, 1; + newCenterChanFreq0, 1; + newCenterChanFreq1, 1; +} + +IE ChannelSwitchWrapper (EID_CHANNEL_SWITCH_WRAPPER) +{ + OPTIE IE WiderBWChanSwitchAnn; +} +IE ExtCap (EID_EXT_CAP) +{ + bytes[8..9]; +} + +IE HTCaps (EID_HT_CAPABILITIES) +{ + // HT Capability Info + { + advCodingCap: 1; + supportedChannelWidthSet: 1; + mimoPowerSave: 2; + greenField: 1; + shortGI20MHz: 1; + shortGI40MHz: 1; + txSTBC: 1; + rxSTBC: 2; + delayedBA: 1; + maximalAMSDUsize: 1; + dsssCckMode40MHz: 1; + psmp: 1; + stbcControlFrame: 1; + lsigTXOPProtection: 1; + } + // HT Parameters Info; + { + maxRxAMPDUFactor: 2; + mpduDensity: 3; + reserved1: 3; + } + + supportedMCSSet[ HT_MAX_SUPPORTED_MCS_SET ]; + + // Extended HT Capability Info + { + pco: 1; + transitionTime: 2; + reserved2: 5; + mcsFeedback: 2; + reserved3: 6; + } + // TXBF Capability Info + { + txBF: 1; + rxStaggeredSounding: 1; + txStaggeredSounding: 1; + rxZLF: 1; + txZLF: 1; + implicitTxBF: 1; + calibration: 2; + explicitCSITxBF: 1; + explicitUncompressedSteeringMatrix: 1; + explicitBFCSIFeedback: 3; + explicitUncompressedSteeringMatrixFeedback: 3; + explicitCompressedSteeringMatrixFeedback: 3; + csiNumBFAntennae: 2; + uncompressedSteeringMatrixBFAntennae: 2; + compressedSteeringMatrixBFAntennae: 2; + reserved4: 7; + } + // AS Capability Info + { + antennaSelection: 1; + explicitCSIFeedbackTx: 1; + antennaIndicesFeedbackTx: 1; + explicitCSIFeedback: 1; + antennaIndicesFeedback: 1; + rxAS: 1; + txSoundingPPDUs: 1; + reserved5: 1; + } + //TODO: take it out when generic fix to remove extra bytes in IE is available. + //This is required to interop with Dlink AP which is sending 2 bytes extra in HTInfo IE. + rsvd[0..32]; + +} // End IE HTCaps. + +IE HTInfo (EID_HT_INFO) +{ + primaryChannel, 1; + + // ahtInfoField1 + { + secondaryChannelOffset: 2; + recommendedTxWidthSet: 1; + rifsMode: 1; + controlledAccessOnly: 1; + serviceIntervalGranularity: 3; + } + + // ahtInfoField2 + + + // ahtInfoField2 + { + opMode: 2; + nonGFDevicesPresent: 1; + transmitBurstLimit: 1; + obssNonHTStaPresent:1; + reserved: 11; + } + + + // ahtInfoField3 + { + basicSTBCMCS: 7; + dualCTSProtection: 1; + secondaryBeacon: 1; + lsigTXOPProtectionFullSupport: 1; + pcoActive: 1; + pcoPhase: 1; + reserved2: 4; + } + + basicMCSSet[ HT_MAX_SUPPORTED_MCS_SET ]; + + //TODO: take it out when generic fix to remove extra bytes in IE is available. + //This is required to interop with Dlink AP which is sending 2 bytes extra in HTInfo IE. + rsvd[0..32]; + +} // End IE HTInfo. + + +IE OperatingMode (EID_OPERATING_MODE) +{ + { //Operating Mode field + chanWidth: 2; + reserved: 2; + rxNSS: 3; + rxNSSType: 1; + } +} + +IE QosMapSet (EID_QOS_MAP_SET) +{ + dscp_exceptions[0..60]; +} + +CONTAINERIE RICDataDesc +{ + MANDIE RICData; + OPTIE RICDescriptor; + OPTIE TSPEC; + OPTIE TCLAS[0..2]; + OPTIE TCLASSPROC; + OPTIE TSDelay; + OPTIE Schedule; + OPTIE WMMTSPEC; + OPTIE WMMTCLAS[0..2]; + OPTIE WMMTCLASPROC; + OPTIE WMMTSDelay; + OPTIE WMMSchedule; +} + +IE TimeAdvertisement (EID_TIME_ADVERTISEMENT) // 8.4.2.63 +{ + timing_capabilities, 1; + time_value[10]; + time_error[5]; +} + +///////////////////////////////////////////////////////////////////////////// +// MULTIIEs // +///////////////////////////////////////////////////////////////////////////// + +MULTIIE WSC ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // Must be 0x10 + OPTIONALTLV WPSState; + OPTIONALTLV APSetupLocked; + OPTIONALTLV SelectedRegistrarConfigMethods; + OPTIONALTLV UUID_E; + OPTIONALTLV UUID_R; + OPTIONALTLV RFBands; + OPTIONALTLV SelectedRegistrar; + OPTIONALTLV ConfigMethods; + OPTIONALTLV AssociationState; + OPTIONALTLV ConfigurationError; + OPTIONALTLV Manufacturer; + OPTIONALTLV ModelName; + OPTIONALTLV ModelNumber; + OPTIONALTLV SerialNumber; + OPTIONALTLV DeviceName; + OPTIONALTLV DevicePasswordID; + OPTIONALTLV PrimaryDeviceType; + OPTIONALTLV RequestType; + OPTIONALTLV ResponseType; + OPTIONALTLV VendorExtension; + OPTIONALTLV RequestDeviceType; +} + +MULTIIE WscBeacon ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + MANDATORYTLV WPSState; // 1 = unconfigured, 2 = + // configured + OPTIONALTLV APSetupLocked; // Must be included if value + // is TRUE + OPTIONALTLV SelectedRegistrar; // BOOL: indicates if the + // user has recently + // activated a Registrar to + // add an Enrollee. + OPTIONALTLV DevicePasswordID; // Device Password ID + // indicates the method or + // identifies the specific + // password that the + // selected Registrar + // intends to use. + OPTIONALTLV SelectedRegistrarConfigMethods; // This attribute contains + // the config methods active + // on the selected + // Registrar. + OPTIONALTLV UUID_E; // The AP's UUID is provided + // only when the AP is a + // dual-band AP in push + // button mode and + // indicating push button + // mode on both radios + OPTIONALTLV RFBands; // Indicates all RF bands + // available on the AP. A + // dual-band AP must provide + // this attribute. + // WSC 2.0 + OPTIONALTLV VendorExtension; // Version2 and AuthorizedMACs + +} // End Multi-IE WscBeacon. + +MULTIIE WscAssocReq ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + MANDATORYTLV RequestType; // + // + // WSC 2.0 + OPTIONALTLV VendorExtension; // Version2 + +} // End Multi-IE WscAssocReq. + + +MULTIIE WscAssocRes ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + MANDATORYTLV ResponseType; // + // + // WSC 2.0 + OPTIONALTLV VendorExtension; // Version2 + +} // End Multi-IE WscAssocRes. + +MULTIIE WscReassocRes ( 221 ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + MANDATORYTLV ResponseType; // + // + // WSC 2.0 + OPTIONALTLV VendorExtension; // Version2 + +} // End Multi-IE WscReassocRes + +MULTIIE WscProbeReq ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + MANDATORYTLV RequestType; // + // + MANDATORYTLV ConfigMethods; // Configuration methods the + // Enrollee or Registrar + // supports + MANDATORYTLV UUID_E; // unique GUID generated by + // the Enrollee. + MANDATORYTLV PrimaryDeviceType; + MANDATORYTLV RFBands; // Specific RF bands used + // for this message + MANDATORYTLV AssociationState; // Configuration and previous + // association state + MANDATORYTLV ConfigurationError; + MANDATORYTLV DevicePasswordID; + + // WSC 2.0 + OPTIONALTLV Manufacturer; // Must be included in ver 2.0 + // or higher. + OPTIONALTLV ModelName; // Must be included in ver 2.0 + // or higher. + OPTIONALTLV ModelNumber; // Must be included in ver 2.0 + // or higher. + OPTIONALTLV DeviceName; // Must be included in ver 2.0 + // or higher. + OPTIONALTLV VendorExtension; // Version2 and RequestToEntroll + + OPTIONALTLV RequestDeviceType; // When a device receives a Probe + // Request containing this type, + // It will only reponse if Primary + // or Secondary Device Type matches. + +} // End Multi-IE WscProbeReq. + +MULTIIE WscProbeRes ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + MANDATORYTLV WPSState; // 1 = unconfigured, 2 = + // configured + OPTIONALTLV APSetupLocked; // Must be included if value + // is TRUE + OPTIONALTLV SelectedRegistrar; // BOOL: indicates if the + // user has recently + // activated a Registrar to + // add an Enrollee. + OPTIONALTLV DevicePasswordID; // Device Password ID + // indicates the method or + // identifies the specific + // password that the + // selected Registrar + // intends to use. + OPTIONALTLV SelectedRegistrarConfigMethods; // This attribute contains + // the config methods active + // on the selected + // Registrar. + MANDATORYTLV ResponseType; + MANDATORYTLV UUID_E; // unique identifier of AP + MANDATORYTLV Manufacturer; + MANDATORYTLV ModelName; + MANDATORYTLV ModelNumber; + MANDATORYTLV SerialNumber; + MANDATORYTLV PrimaryDeviceType; + MANDATORYTLV DeviceName; // User-friendly description + // of device + MANDATORYTLV ConfigMethods; // Config Methods corresponds + // to the methods the AP + // supports as an Enrollee + // for adding external + // Registrars. + OPTIONALTLV RFBands; // Indicates all RF bands + // available on the AP. A + // dual-band AP must provide + // this attribute. + // WSC 2.0 + OPTIONALTLV VendorExtension; // Version2 and AuthorizedMACs + +} // WscProbeRes. + +// This MULTIIE combines the fields from the WSC IEs as they appear in +// Beacons *and* in Probe Responses, with the difference that they're all +// optional. In our device drivers, we combine Probe Responses and Beacons +// into one list, and parse their IEs later (c.f. frame BeaconIEs). Because +// the WSC IE differs in those two frames, we'd often see warning messages +// about either unexpected fields showing up (if we thought we were parsing a +// Beacon, and we in fact had data from a Probe Response) or mandatory fields +// missing (if we thought we were parsing a Probe Response, and in fact had +// data from a Beacon). + +// I created this MULTIIE to stuff into the BeaconIEs frames to avoid this. +// It's intended to be used on unpack only, and to do so in a very forgiving +// way. + +MULTIIE WscBeaconProbeRes ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + OPTIONALTLV Version; // 0x10 = version 1.0, 0x11 + // = version 1.1, etc. + OPTIONALTLV WPSState; // 1 = unconfigured, 2 = + // configured + OPTIONALTLV APSetupLocked; // Must be included if value + // is TRUE + OPTIONALTLV SelectedRegistrar; // BOOL: indicates if the + // user has recently + // activated a Registrar to + // add an Enrollee. + OPTIONALTLV DevicePasswordID; // Device Password ID + // indicates the method or + // identifies the specific + // password that the + // selected Registrar + // intends to use. + OPTIONALTLV SelectedRegistrarConfigMethods; // This attribute contains + // the config methods active + // on the selected + // Registrar. + OPTIONALTLV ResponseType; + OPTIONALTLV UUID_E; // unique identifier of AP + OPTIONALTLV Manufacturer; + OPTIONALTLV ModelName; + OPTIONALTLV ModelNumber; + OPTIONALTLV SerialNumber; + OPTIONALTLV PrimaryDeviceType; + OPTIONALTLV DeviceName; // User-friendly description + // of device + OPTIONALTLV ConfigMethods; // Config Methods corresponds + // to the methods the AP + // supports as an Enrollee + // for adding external + // Registrars. + OPTIONALTLV RFBands; // Indicates all RF bands + // available on the AP. A + // dual-band AP must provide + // this attribute. + // WSC 2.0 + OPTIONALTLV VendorExtension; // Version2 and AuthorizedMACs + +} // WscProbeRes. +///////////////////////////////////////////////////////////////////////////// +// MULTIIEs // +///////////////////////////////////////////////////////////////////////////// + +MULTIIE P2PBeacon ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PCapability; // Contains P2P Device + // and P2P Group Capability + MANDATORYTLV P2PDeviceId; // Contains P2P Device + // Address + OPTIONALTLV NoticeOfAbsence; // Indicates Notice of + // Absence schedule and + // CT Window + +} // End P2PBeacon + + +MULTIIE P2PAssocReq ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PCapability; // Contains P2P Device + // and P2P Group Capability + OPTIONALTLV ExtendedListenTiming; + MANDATORYTLV P2PDeviceInfo; + +} // End P2PAssocReq + + +MULTIIE P2PAssocRes ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PStatus; + OPTIONALTLV ExtendedListenTiming; + +} // End P2PAssocRes + + +MULTIIE P2PProbeReq ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PCapability; + OPTIONALTLV P2PDeviceId; + MANDATORYTLV ListenChannel; + OPTIONALTLV ExtendedListenTiming; + OPTIONALTLV OperatingChannel; +} // End P2PProbeReq + + +MULTIIE P2PProbeRes ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PCapability; + OPTIONALTLV ExtendedListenTiming; + OPTIONALTLV NoticeOfAbsence; + MANDATORYTLV P2PDeviceInfo; + OPTIONALTLV P2PGroupInfo; + +} // End P2PProbeRes + + +MULTIIE P2PBeaconProbeRes ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + OPTIONALTLV P2PCapability; + OPTIONALTLV P2PDeviceId; + OPTIONALTLV ExtendedListenTiming; + OPTIONALTLV NoticeOfAbsence; + OPTIONALTLV P2PDeviceInfo; + OPTIONALTLV P2PGroupInfo; + +} // End P2PBeaconProbeRes + + +MULTIIE P2PGONegReq ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PCapability; + MANDATORYTLV GOIntent; + MANDATORYTLV ConfigurationTimeout; + MANDATORYTLV ListenChannel; + OPTIONALTLV ExtendedListenTiming; + MANDATORYTLV IntendedP2PInterfaceAddress; + MANDATORYTLV ChannelList; + MANDATORYTLV P2PDeviceInfo; + MANDATORYTLV OperatingChannel; + +} // End P2PGONegReq + + +MULTIIE P2PGONegRes ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PStatus; + MANDATORYTLV P2PCapability; + MANDATORYTLV GOIntent; + MANDATORYTLV ConfigurationTimeout; + MANDATORYTLV OperatingChannel; + MANDATORYTLV IntendedP2PInterfaceAddress; + MANDATORYTLV ChannelList; + MANDATORYTLV P2PDeviceInfo; + OPTIONALTLV P2PGroupId; + +} // End P2PGONegRes + + +MULTIIE P2PGONegCnf ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PStatus; + MANDATORYTLV P2PCapability; + MANDATORYTLV OperatingChannel; + MANDATORYTLV ChannelList; + OPTIONALTLV P2PGroupId; + +} // End P2PGONegCnf + + +MULTIIE P2PGONegWPS ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV Version; + MANDATORYTLV DevicePasswordID; + +} // End P2PGONegWPS + + +MULTIIE P2PDeAuth ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV MinorReasonCode; +} + + +MULTIIE P2PDisAssoc ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV MinorReasonCode; +} + + +MULTIIE P2PInvitationReq ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV ConfigurationTimeout; + MANDATORYTLV InvitationFlags; + MANDATORYTLV OperatingChannel; + MANDATORYTLV P2PGroupBssid; + MANDATORYTLV ChannelList; + MANDATORYTLV P2PGroupId; + MANDATORYTLV P2PDeviceInfo; +} + + +MULTIIE P2PInvitationRes ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PStatus; + MANDATORYTLV ConfigurationTimeout; + MANDATORYTLV OperatingChannel; + MANDATORYTLV P2PGroupBssid; + MANDATORYTLV ChannelList; +} + + +MULTIIE P2PDeviceDiscoverabilityReq ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PDeviceId; + MANDATORYTLV P2PGroupId; +} + + +MULTIIE P2PDeviceDiscoverabilityRes ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PStatus; +} + + +MULTIIE P2PProvisionDiscoveryReq ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PCapability; + MANDATORYTLV P2PDeviceInfo; + MANDATORYTLV P2PGroupId; +} + +MULTIIE P2PWSCProvisionDiscoveryRes ( EID_VENDOR_SPECIFIC ) OUI( 0x00, 0x50, 0xF2, 0x04 ) +{ + MANDATORYTLV ConfigMethods; +} + + +MULTIIE P2PNoticeOfAbsence ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV NoticeOfAbsence; +} + + +MULTIIE P2PPresenceResponse ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV P2PStatus; + MANDATORYTLV NoticeOfAbsence; +} + + +///////////////////////////////////////////////////////////////////////////// +// Frames + +FRAME Beacon // C.f. Sec. 7.2.3.1 +{ + FF TimeStamp; + FF BeaconInterval; + FF Capabilities; + MANDIE SSID; + MANDIE SuppRates; + OPTIE FHParamSet; + OPTIE DSParams; + OPTIE CFParams; + OPTIE IBSSParams; + OPTIE TIM; + OPTIE Country; + OPTIE FHParams; + OPTIE FHPattTable; + OPTIE PowerConstraints; + OPTIE ChanSwitchAnn; + OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; + OPTIE Quiet; + OPTIE TPCReport; + OPTIE ERPInfo; + OPTIE ExtSuppRates; + OPTIE RSN; + OPTIE QBSSLoad; + OPTIE EDCAParamSet; + OPTIE QOSCapsAp; + OPTIE APChannelReport; + OPTIE RRMEnabledCap; + OPTIE MobilityDomain; + OPTIE WPA; + OPTIE HTCaps; + OPTIE HTInfo; + OPTIE sec_chan_offset_ele; + OPTIE WMMInfoAp; + OPTIE WMMParams; + OPTIE WMMCaps; + OPTIE WAPI; + OPTIE ESERadMgmtCap; + OPTIE ESETrafStrmMet; + OPTIE ESETxmitPower; + + OPTIE WscBeacon; + OPTIE P2PBeacon; + OPTIE VHTCaps; + OPTIE VHTOperation; + OPTIE VHTExtBssLoad; + OPTIE ExtCap; + OPTIE OperatingMode; + OPTIE WiderBWChanSwitchAnn; + OPTIE OBSSScanParameters; + OPTIE Vendor1IE; + OPTIE Vendor2IE; + OPTIE Vendor3IE; + OPTIE ChannelSwitchWrapper; + OPTIE QComVendorIE; + OPTIE ESEVersion; +} // End frame Beacon. + +// Ok, here's the story on Beacon1 & Beacon2. We presumably beacon a lot +// more than we change configuration. So it makes sense to keep the beacon +// we plan to send next in serialized format. We do this in struct schMisc. +// Whenever our config changes in a way that would affect our beacons, we +// just update our internal datastructures & re-generate the serialized +// beacon. + +// The problem is that there are *some* fields that need to be updated at +// send time, specifically the CF Param Set & the TIM. So, what we do is +// this: whenever our config changes, call schSetFixedBeaconFields. There, +// we serialize the following Beacon fields into gSchBeaconFrameBegin (after +// the power template & MAC header): TimeStamp, BeaconInterval, Capabilities, +// SSID, SuppRates, DSParams, & IBSSParams. It sets gSchBeaconOffsetBegin to +// the length of this buffer (incl. power template & MAC header). + +// Next, it serializes the following fields into gSchBeaconFrameEnd: Country, +// EDCAParamSet, PowerConstraints, TPCReport, ChannelSwitchAnn, Quiet, +// ERPInfo, HTCaps, HTInfo, ExtSuppRates, WPA, RSN, WMMInfo, +// WMMParams, WMMCaps. +// The length of *this* buffer is kept in gSchBeaconOffsetEnd. + +// Then, in 'schBeaconInterruptHandler', we write CFParams & TIM at the end +// of gSchBeaconFrameBegin, keeping track of the (new) size of this buffer in +// the local 'beaconSize'. + +// After that, we call 'specialBeaconProcessing'. Note that this may +// actually call schSetFixedBeaconFields repeatedly! The comments say they +// try to avoid this, but... + +// Finally, we call writeBeaconToTFP, where the first thing we do is copy the +// gSchBeaconFrameEnd buffer after the end of gSchBeaconFrameBegin. + +FRAME Beacon1 +{ + FF TimeStamp; + FF BeaconInterval; + FF Capabilities; + MANDIE SSID; + MANDIE SuppRates; + OPTIE DSParams; + OPTIE IBSSParams; +} + +FRAME Beacon2 +{ + OPTIE Country; + OPTIE PowerConstraints; + OPTIE ChanSwitchAnn; + OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; + OPTIE Quiet; + OPTIE TPCReport; + OPTIE ERPInfo; + OPTIE ExtSuppRates; + OPTIE RSNOpaque; + OPTIE EDCAParamSet; + OPTIE APChannelReport; + OPTIE RRMEnabledCap; + OPTIE MobilityDomain; + OPTIE WPA; + OPTIE HTCaps; + OPTIE HTInfo; + OPTIE sec_chan_offset_ele; + OPTIE WMMInfoAp; + OPTIE WMMParams; + OPTIE WMMCaps; + OPTIE WscBeacon; + OPTIE WAPI; + OPTIE ESERadMgmtCap; + OPTIE ESETrafStrmMet; + OPTIE ESETxmitPower; + OPTIE P2PBeacon; + OPTIE VHTCaps; + OPTIE VHTOperation; + OPTIE VHTExtBssLoad; + OPTIE ExtCap; + OPTIE OperatingMode; + OPTIE WiderBWChanSwitchAnn; + OPTIE OBSSScanParameters; + OPTIE Vendor1IE; + OPTIE Vendor2IE; + OPTIE Vendor3IE; + OPTIE ChannelSwitchWrapper; + OPTIE QComVendorIE; + OPTIE ESEVersion; +} + +// This frame is just Beacon with its Fixed Fields stripped out. It's handy +// for use with struct 'tSirBssDescription', which has members corresponding +// to some fixed fields, but keeps its IEs in un-parsed format. + +// Note that it also includes the IE 'WscBeaconProbeRes'. + +FRAME BeaconIEs +{ + + MANDIE SSID; + MANDIE SuppRates; + OPTIE FHParamSet; + OPTIE DSParams; + OPTIE CFParams; + OPTIE IBSSParams; + OPTIE TIM; + OPTIE Country; + OPTIE FHParams; + OPTIE FHPattTable; + OPTIE PowerConstraints; + OPTIE ChanSwitchAnn; + OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; + OPTIE Quiet; + OPTIE TPCReport; + OPTIE ERPInfo; + OPTIE ExtSuppRates; + OPTIE RSN; + OPTIE QBSSLoad; + OPTIE EDCAParamSet; + OPTIE QOSCapsAp; + OPTIE APChannelReport; + OPTIE RRMEnabledCap; + OPTIE MobilityDomain; + OPTIE WPA; + OPTIE HTCaps; + OPTIE HTInfo; + OPTIE sec_chan_offset_ele; + OPTIE WMMInfoAp; + OPTIE WMMParams; + OPTIE WMMCaps; + OPTIE WAPI; + OPTIE ESEVersion; + OPTIE ESERadMgmtCap; + OPTIE ESETrafStrmMet; + OPTIE ESETxmitPower; + + OPTIE WscBeaconProbeRes; + OPTIE P2PBeaconProbeRes; + OPTIE VHTCaps; + OPTIE VHTOperation; + OPTIE VHTExtBssLoad; + OPTIE ExtCap; + OPTIE OperatingMode; + OPTIE WiderBWChanSwitchAnn; + OPTIE OBSSScanParameters; + OPTIE Vendor1IE; + OPTIE Vendor2IE; + OPTIE Vendor3IE; + OPTIE ChannelSwitchWrapper; + OPTIE QComVendorIE; + +} // End frame BeaconIEs. + +FRAME Disassociation // 7.3.3.3 +{ + FF Reason; + OPTIE P2PDisAssoc; +} + +FRAME AssocRequest // 7.2.3.4 +{ + FF Capabilities; + FF ListenInterval; + MANDIE SSID; + MANDIE SuppRates; + OPTIE ExtSuppRates; + OPTIE PowerCaps; + OPTIE SuppChannels; + OPTIE RSNOpaque; + OPTIE QOSCapsStation; + OPTIE RRMEnabledCap; + OPTIE MobilityDomain; + OPTIE WPAOpaque; + OPTIE HTCaps; + OPTIE WMMCaps; + OPTIE WMMInfoStation; + OPTIE WscIEOpaque; + OPTIE WAPIOpaque; + OPTIE WAPI; + OPTIE ESERadMgmtCap; + OPTIE ESEVersion; + OPTIE P2PIEOpaque; + OPTIE WFDIEOpaque; + OPTIE VHTCaps; + OPTIE ExtCap; + OPTIE OperatingMode; + OPTIE QosMapSet; +} // End frame AssocRequest. + +FRAME AssocResponse // 7.2.3.5 +{ + FF Capabilities; + FF Status; + FF AID; + MANDIE SuppRates; + OPTIE ExtSuppRates; + OPTIE EDCAParamSet; + OPTIE RCPIIE; + OPTIE RSNIIE; + OPTIE RRMEnabledCap; + OPTIE MobilityDomain; + OPTIE FTInfo; + OPTIE RICDataDesc[2]; + OPTIE WPA; + OPTIE TimeoutInterval; + OPTIE HTCaps; + OPTIE HTInfo; + OPTIE WMMParams; + OPTIE WMMCaps; + OPTIE ESERadMgmtCap; + OPTIE ESETrafStrmMet; + OPTIE ESETxmitPower; + OPTIE WMMTSPEC[0..4]; + OPTIE WscAssocRes; + OPTIE P2PAssocRes; + OPTIE VHTCaps; + OPTIE VHTOperation; + OPTIE ExtCap; + OPTIE OBSSScanParameters; + OPTIE QosMapSet; +} // End frame AssocResponse. + +FRAME ReAssocRequest // 7.2.3.6 +{ + FF Capabilities; + FF ListenInterval; + FF CurrentAPAddress; + MANDIE SSID; + MANDIE SuppRates; + OPTIE ExtSuppRates; + OPTIE PowerCaps; + OPTIE SuppChannels; + OPTIE RSNOpaque; + OPTIE QOSCapsStation; + OPTIE RRMEnabledCap; + OPTIE MobilityDomain; + OPTIE FTInfo; + OPTIE RICDataDesc[2]; + OPTIE WPAOpaque; + OPTIE HTCaps; + OPTIE WMMCaps; + OPTIE WMMInfoStation; + OPTIE WscIEOpaque; + OPTIE WAPIOpaque; + OPTIE WAPI; + OPTIE ESERadMgmtCap; + OPTIE ESEVersion; + OPTIE ESECckmOpaque; + OPTIE WMMTSPEC[0..4]; + OPTIE ESETrafStrmRateSet; + OPTIE P2PIEOpaque; + OPTIE WFDIEOpaque; + OPTIE VHTCaps; + OPTIE ExtCap; + OPTIE OperatingMode; + OPTIE QosMapSet; +} // End frame ReAssocRequest. + +FRAME ReAssocResponse // 7.2.3.7 +{ + FF Capabilities; + FF Status; + FF AID; + MANDIE SuppRates; + OPTIE ExtSuppRates; + OPTIE EDCAParamSet; + OPTIE RCPIIE; + OPTIE RSNIIE; + OPTIE RRMEnabledCap; + OPTIE RSNOpaque; + OPTIE MobilityDomain; + OPTIE FTInfo; + OPTIE RICDataDesc[2]; + OPTIE WPA; + OPTIE TimeoutInterval; + OPTIE HTCaps; + OPTIE HTInfo; + OPTIE WMMParams; + OPTIE ESERadMgmtCap; + OPTIE ESETrafStrmMet; + OPTIE ESETxmitPower; + OPTIE WMMTSPEC[0..4]; + OPTIE ESETrafStrmRateSet; + OPTIE WscReassocRes; + OPTIE P2PAssocRes; + OPTIE VHTCaps; + OPTIE VHTOperation; + OPTIE ExtCap; + OPTIE OBSSScanParameters; + OPTIE QosMapSet; +} // End frame ReAssocResponse. + +FRAME ProbeRequest // 7.2.3.8 +{ + MANDIE SSID; + MANDIE SuppRates; + OPTIE RequestedInfo; + OPTIE ExtSuppRates; + OPTIE DSParams; + OPTIE HTCaps; + OPTIE WscProbeReq; + OPTIE WFATPC; + OPTIE P2PProbeReq; + OPTIE VHTCaps; + OPTIE ExtCap; +} // End frame ProbeRequest. + +FRAME ProbeResponse // 7.2.3.9 +{ + FF TimeStamp; + FF BeaconInterval; + FF Capabilities; + MANDIE SSID; + MANDIE SuppRates; + OPTIE FHParamSet; + OPTIE DSParams; + OPTIE CFParams; + OPTIE IBSSParams; + OPTIE Country; + OPTIE FHParams; + OPTIE FHPattTable; + OPTIE PowerConstraints; + OPTIE ChanSwitchAnn; + OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; + OPTIE Quiet; + OPTIE TPCReport; + OPTIE ERPInfo; + OPTIE ExtSuppRates; + OPTIE RSNOpaque; + OPTIE QBSSLoad; + OPTIE EDCAParamSet; + OPTIE RRMEnabledCap; + OPTIE APChannelReport; + OPTIE MobilityDomain; + OPTIE WPA; + OPTIE HTCaps; + OPTIE HTInfo; + OPTIE sec_chan_offset_ele; + OPTIE WMMInfoAp; + OPTIE WMMParams; + OPTIE WMMCaps; + OPTIE WAPI; + OPTIE ESERadMgmtCap; + OPTIE ESETrafStrmMet; + OPTIE ESETxmitPower; + + OPTIE WscProbeRes; + OPTIE P2PProbeRes; + + OPTIE VHTCaps; + OPTIE VHTOperation; + OPTIE VHTExtBssLoad; + OPTIE ExtCap; + OPTIE OBSSScanParameters; + OPTIE Vendor1IE; + OPTIE Vendor2IE; + OPTIE Vendor3IE; + OPTIE ChannelSwitchWrapper; + OPTIE QComVendorIE; + OPTIE ESEVersion; +} // End frame ProbeResponse. + +FRAME Authentication // 7.2.3.10 +{ + FF AuthAlgo; + FF AuthSeqNo; + FF Status; + OPTIE ChallengeText; + OPTIE RSNOpaque; + OPTIE MobilityDomain; + OPTIE FTInfo; + OPTIE TimeoutInterval; + OPTIE RICDataDesc[2]; +} // End frame Auth. + +FRAME DeAuth // 7.2.3.11 +{ + FF Reason; + OPTIE P2PDeAuth; +} + +FRAME AddTSRequest // 7.4.2.1 +{ + + FF Category; + FF Action; + FF DialogToken; + MANDIE TSPEC; + OPTIE TCLAS[0..2]; + OPTIE TCLASSPROC; + + // These IEs aren't in the spec, but our extant code *will* parse them if + // they're present. I included them to preserve that capability + + OPTIE WMMTSPEC; + OPTIE WMMTCLAS[0..2]; + OPTIE WMMTCLASPROC; + OPTIE ESETrafStrmRateSet; + +} // End frame AddTSRequest. + +FRAME WMMAddTSRequest +{ + FF Category; + FF Action; + FF DialogToken; + FF StatusCode; + MANDIE WMMTSPEC; + OPTIE ESETrafStrmRateSet; +} // End Frame WMMAddTSRequest + +FRAME AddTSResponse // 7.4.2.2 +{ + + FF Category; + FF Action; + FF DialogToken; + FF Status; + MANDIE TSDelay; + MANDIE TSPEC; + OPTIE TCLAS[0..2]; + OPTIE TCLASSPROC; + OPTIE Schedule; + + // These IEs aren't in the spec, but our extant code *will* parse them if + // they're present. I included them to preserve that capability + OPTIE WMMTSDelay; + OPTIE WMMSchedule; + OPTIE WMMTSPEC; + OPTIE WMMTCLAS[0..2]; + OPTIE WMMTCLASPROC; + OPTIE ESETrafStrmMet; + +} // End frame AddTSResponse. + +FRAME WMMAddTSResponse +{ + + FF Category; + FF Action; + FF DialogToken; + FF StatusCode; + OPTIE WMMTSPEC; + OPTIE ESETrafStrmMet; + +} // End frame WMMAddTSResponse. + +FRAME DelTS // 7.4.2.3 +{ + FF Category; + FF Action; + FF TSInfo; + FF Reason; +} + +FRAME WMMDelTS +{ + FF Category; + FF Action; + FF DialogToken; + FF StatusCode; + MANDIE WMMTSPEC; +} + +FRAME TPCRequest +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE TPCRequest; +} + +FRAME TPCReport +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE TPCReport; +} + +FRAME ChannelSwitch +{ + FF Category; + FF Action; + MANDIE ChanSwitchAnn; + OPTIE sec_chan_offset_ele; + OPTIE WiderBWChanSwitchAnn; +} + +FRAME MeasurementRequest +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE MeasurementRequest[1..4]; +} + +FRAME MeasurementReport +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE MeasurementReport; +} + +FRAME AddBAReq +{ + FF Category; + FF Action; + FF DialogToken; + FF AddBAParameterSet; + FF BATimeout; + FF BAStartingSequenceControl; +} + +FRAME AddBARsp +{ + FF Category; + FF Action; + FF DialogToken; + FF Status; + FF AddBAParameterSet; + FF BATimeout; +} + +FRAME DelBAInd +{ + FF Category; + FF Action; + FF DelBAParameterSet; + FF Reason; +} + +FRAME SMPowerSave +{ + FF Category; + FF Action; + FF SMPowerModeSet; +} + +FRAME RadioMeasurementRequest +{ + FF Category; + FF Action; + FF DialogToken; + FF NumOfRepetitions; + //Measurement Request IE. + MANDIE MeasurementRequest[1..2]; +} + +FRAME RadioMeasurementReport +{ + FF Category; + FF Action; + FF DialogToken; + //Measurement Report elements. + MANDIE MeasurementReport[1..4]; +} + +FRAME LinkMeasurementRequest +{ + FF Category; + FF Action; + FF DialogToken; + FF TxPower; + FF MaxTxPower; + //Optional Sub Ies +} + +FRAME LinkMeasurementReport +{ + FF Category; + FF Action; + FF DialogToken; + FF TPCEleID; + FF TPCEleLen; + FF TxPower; + FF LinkMargin; + FF RxAntennaId; + FF TxAntennaId; + FF RCPI; + FF RSNI; + //Optional Vendor specific IEs ... ignoring +} + +FRAME NeighborReportRequest +{ + FF Category; + FF Action; + FF DialogToken; + OPTIE SSID; + //Optional vendor specific IE...ignoring. +} + +FRAME NeighborReportResponse +{ + FF Category; + FF Action; + FF DialogToken; + OPTIE NeighborReport[1..MAX_SUPPORTED_NEIGHBOR_RPT]; +} + +FRAME GONegReq +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PGONegWPS; + MANDIE P2PGONegReq; +} + +FRAME GONegRes +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PGONegWPS; + MANDIE P2PGONegRes; +} + + +FRAME GONegCnf +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PGONegCnf; +} + + +FRAME InvitationReq +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PInvitationReq; +} + + +FRAME InvitationRes +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PInvitationRes; +} + + +FRAME DeviceDiscoverabilityReq +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PDeviceDiscoverabilityReq; +} + + +FRAME DeviceDiscoverabilityRes +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PDeviceDiscoverabilityRes; +} + + + +FRAME ProvisionDiscoveryReq +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PProvisionDiscoveryReq; +} + + +FRAME ProvisionDiscoveryRes +{ + FF Category; + FF Action; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PWSCProvisionDiscoveryRes; +} + + +FRAME NoticeOfAbs +{ + FF Category; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PNoticeOfAbsence; +} + + +FRAME PresenceReq +{ + FF Category; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PNoticeOfAbsence; +} + + +FRAME PresenceRes +{ + FF Category; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; + MANDIE P2PPresenceResponse; +} + + +FRAME GODiscoverabilityReq +{ + FF Category; + FF P2POUI; + FF P2POUISubType; + FF DialogToken; +} + +FRAME OperatingMode +{ + FF Category; + FF Action; + //Operating Mode field + FF OperatingMode; +} + +FRAME TDLSDisReq +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE LinkIdentifier; +} + +FRAME TDLSDisRsp +{ + FF Category; + FF Action; + FF DialogToken; + FF Capabilities; + MANDIE SuppRates; + OPTIE ExtSuppRates; + OPTIE SuppChannels; + OPTIE SuppOperatingClasses; + OPTIE RSN; + OPTIE ExtCap; + OPTIE FTInfo; + OPTIE TimeoutInterval; + OPTIE RICData; + OPTIE HTCaps; + OPTIE HT2040BSSCoexistence; + MANDIE LinkIdentifier; + OPTIE VHTCaps; +} + +FRAME TDLSSetupReq +{ + FF Category; + FF Action; + FF DialogToken; + FF Capabilities; + MANDIE SuppRates; + OPTIE Country; + OPTIE ExtSuppRates; + OPTIE SuppChannels; + OPTIE RSN; + OPTIE ExtCap; + OPTIE SuppOperatingClasses; + OPTIE QOSCapsStation; + OPTIE FTInfo; + OPTIE TimeoutInterval; + OPTIE RICData; + OPTIE HTCaps; + OPTIE HT2040BSSCoexistence; + MANDIE LinkIdentifier; + OPTIE WMMInfoStation; + OPTIE AID; + OPTIE VHTCaps; +} + +FRAME TDLSSetupRsp +{ + FF Category; + FF Action; + FF Status; + FF DialogToken; + FF Capabilities ; + OPTIE SuppRates; + OPTIE Country; + OPTIE ExtSuppRates; + OPTIE SuppChannels; + OPTIE RSN; + OPTIE ExtCap; + OPTIE SuppOperatingClasses; + OPTIE QOSCapsStation; + OPTIE FTInfo; + OPTIE TimeoutInterval; + OPTIE RICData; + OPTIE HTCaps; + OPTIE HT2040BSSCoexistence; + OPTIE LinkIdentifier; + OPTIE WMMInfoStation; + OPTIE AID; + OPTIE VHTCaps; + OPTIE OperatingMode; +} + +FRAME TDLSSetupCnf +{ + FF Category; + FF Action; + FF Status; + FF DialogToken; + OPTIE RSN; + OPTIE EDCAParamSet; + OPTIE FTInfo; + OPTIE TimeoutInterval; + OPTIE HTInfo; + OPTIE LinkIdentifier; + OPTIE WMMParams; + OPTIE VHTOperation; + OPTIE OperatingMode; +} +FRAME TDLSTeardown +{ + FF Category; + FF Action; + FF Reason; + OPTIE FTInfo; + MANDIE LinkIdentifier; +} + +FRAME TDLSPeerTrafficInd +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE LinkIdentifier; + OPTIE PTIControl; + MANDIE PUBufferStatus; +} + +FRAME TDLSPeerTrafficRsp +{ + FF Category; + FF Action; + FF DialogToken; + MANDIE LinkIdentifier; +} + +FRAME SaQueryReq +{ + FF Category; + FF Action; + FF TransactionId; +} + +FRAME SaQueryRsp +{ + FF Category; + FF Action; + FF TransactionId; +} + +FRAME QosMapConfigure +{ + FF Category; + FF Action; + MANDIE QosMapSet; +} + +FRAME VHTGidManagementActionFrame +{ + FF Category; + FF Action; + FF VhtMembershipStatusArray; + FF VhtUserPositionArray; +} + +FRAME HT2040BSSCoexistenceManagementActionFrame +{ + FF Category; + FF Action; + MANDIE HT2040BSSCoexistence; + MANDIE HT2040BSSIntolerantReport; +} + +FRAME TimingAdvertisementFrame // 8.3.3.15 +{ + FF TimeStamp; + FF Capabilities; + OPTIE Country; + OPTIE PowerConstraints; + OPTIE TimeAdvertisement; + OPTIE ExtCap; + OPTIE Vendor1IE; + OPTIE Vendor2IE; + OPTIE Vendor3IE; +} + +FRAME ext_channel_switch_action_frame +{ + FF Category; + FF Action; + FF ext_chan_switch_ann_action; +} + +// Local Variables: +// mode: c++ +// fill-column: 77 +// comment-column: 42 +// indent-tabs-mode: nil +// show-trailing-whitespace: t +// End: + +// parser.frms ends here. diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/polFile.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/polFile.h new file mode 100644 index 000000000000..485196845916 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/polFile.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//================================================================== +// +// File: polFile.h +// +// Description: Structures that define the firmware file format. +// +// Author: Larry Cawley +// +//// +// Change History: +// 04/09/2002 - LAC - Initial version. +// +//=================================================================== +#if !defined( __polFile_h__ ) +#define __polFile_h__ + + + + +// File format +// +// byte 0 1 2 3 +// +// +---------+---------+--------+-------+ <----+ +// | Major | Minor | | | | +// | Version | Version | Suffix | Build | FileVersion | +// +---------+---------+--------+-------+ | +// | Major | Minor | | | | +// | Version | Version | Suffix | Build | HwCapabilities | tPolFileHeader +// +---------+---------+--------+-------+ | +// | | | +// | FileLength | FileLength | +// +------------------------------------+ | +// | | | +// | Number of Directory Entries | NumDirectoryEntries | +// +------------------------------------+ <----+ +// | | | +// | Directory Entry 1 Type | DirEntryType | +// +------------------------------------+ | +// | | | tPolFileDirEntry 1 +// | Directory Entry 1 File Offset | DirEntryFileOffset | +// +------------------------------------+ | +// | | | +// | Directory Entry 1 Length | DirEntryLength | +// +------------------------------------+ <----+ +// | . . . | . . . +// +------------------------------------+ <----+ +// | | | +// | Directory Entry n Type | | +// +------------------------------------+ | +// | | | tpolFileDirEntry n +// | Directory Entry n File Offset | | +// +------------------------------------+ | +// | | | +// | Directory Entry n Length | | +// +------------------------------------+ <----+ +// | | +// | | +// | File data described by | +// | directory entry 1 | +// | | +// | | +// +------------------------------------+ +// | . . . | +// +------------------------------------+ +// | | +// | | +// | File data described by | +// | directory entry n | +// | | +// | | +// +---------+---------+----------------+ +// | | +// | File Checksum | +// +---------+---------+ +// +// +// +// + + +#pragma pack( push ) +#pragma pack( 1 ) + +typedef struct sPolFileVersion { + + unsigned char MajorVersion; + unsigned char MinorVersion; + unsigned char Suffix; + unsigned char Build; + +} tPolFileVersion; + + +typedef struct sPolFileHeader { + + tPolFileVersion FileVersion; + tPolFileVersion HWCapabilities; + unsigned int FileLength; + unsigned int NumDirectoryEntries; + +} tPolFileHeader; + + +typedef enum ePolFileDirTypes { + + ePOL_DIR_TYPE_BOOTLOADER = 0, + ePOL_DIR_TYPE_STA_FIRMWARE, + ePOL_DIR_TYPE_AP_FIRMWARE, + ePOL_DIR_TYPE_DIAG_FIRMWARE, + ePOL_DIR_TYPE_STA_CONFIG, + ePOL_DIR_TYPE_AP_CONFIG + +} tPolFileDirTypes; + + +typedef struct sPolFileDirEntry { + + unsigned int DirEntryType; + unsigned int DirEntryFileOffset; + unsigned int DirEntryLength; + +} tPolFileDirEntry; + + +#pragma pack( pop ) + + +__inline unsigned short polFileChkSum( unsigned short *FileData, unsigned long NumWords ) +{ + unsigned long Sum; + + for ( Sum = 0; NumWords > 0; NumWords-- ) { + + Sum += *FileData++; + } + + Sum = (Sum >> 16) + (Sum & 0xffff); // add carry + Sum += (Sum >> 16); // maybe last unsigned short + + return( (unsigned short)( ~Sum ) ); +} + + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.c new file mode 100644 index 000000000000..76c2e491096f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file dphHashTable.cc implements the member functions of + * DPH hash table class. + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "cfgApi.h" +#include "schApi.h" +#include "dphGlobal.h" +#include "limDebug.h" + + +#include "halMsgApi.h" + +// --------------------------------------------------------------------- +/** + * dphHashTableClass() + * + * FUNCTION: + * Constructor function + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void dphHashTableClassInit(tpAniSirGlobal pMac, dphHashTableClass* pDphHashTable) +{ + tANI_U16 i; + + for (i=0; isize; i++) + { + pDphHashTable->pHashTable[i] = 0; + } + + for (i=0; isize; i++) + { + pDphHashTable->pDphNodeArray[i].valid = 0; + pDphHashTable->pDphNodeArray[i].added = 0; + pDphHashTable->pDphNodeArray[i].assocId = i; + } + +} + +// --------------------------------------------------------------------- +/** + * hashFunction + * + * FUNCTION: + * Hashing function + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param staAddr MAC address of the station + * @return None + */ + +tANI_U16 hashFunction(tpAniSirGlobal pMac, tANI_U8 staAddr[], tANI_U16 numSta) +{ + int i; + tANI_U16 sum = 0; + + for (i=0; i<6; i++) + sum += staAddr[i]; + + return (sum % numSta); +} + +// --------------------------------------------------------------------- +/** + * dphLookupHashEntry + * + * FUNCTION: + * Look up an entry in hash table + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param staAddr MAC address of the station + * @param pStaId pointer to the Station ID assigned to the station + * @return pointer to STA hash entry if lookup was a success \n + * NULL if lookup was a failure + */ + +tpDphHashNode dphLookupHashEntry(tpAniSirGlobal pMac, tANI_U8 staAddr[], tANI_U16 *pAssocId, + dphHashTableClass* pDphHashTable) +{ + tpDphHashNode ptr = NULL; + tANI_U16 index = hashFunction(pMac, staAddr, pDphHashTable->size); + + for (ptr = pDphHashTable->pHashTable[index]; ptr; ptr = ptr->next) + { + if (dphCompareMacAddr(staAddr, ptr->staAddr)) + { + *pAssocId = ptr->assocId; + break; + } + } + return ptr; +} + +// --------------------------------------------------------------------- +/** + * dphGetHashEntry + * + * FUNCTION: + * Get a pointer to the hash node + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param staId Station ID + * @return pointer to STA hash entry if lookup was a success \n + * NULL if lookup was a failure + */ + +tpDphHashNode dphGetHashEntry(tpAniSirGlobal pMac, tANI_U16 peerIdx, dphHashTableClass* pDphHashTable) +{ + if (peerIdx < pDphHashTable->size) + { + if (pDphHashTable->pDphNodeArray[peerIdx].added) + return &pDphHashTable->pDphNodeArray[peerIdx]; + else + return NULL; + } + else + return NULL; + +} + +static inline tpDphHashNode getNode(tpAniSirGlobal pMac, tANI_U8 assocId, dphHashTableClass* pDphHashTable) +{ + return &pDphHashTable->pDphNodeArray[assocId]; +} + + + + +// --------------------------------------------------------------------- +/** + * dphLookupAssocId + * + * FUNCTION: + * This function looks up assocID given the station Id. It traverses the complete table to do this. + * Need to find an efficient way to do this. + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac pointer to global Mac structure. + * @param staIdx station ID + * @param *assocId pointer to associd to be returned by this function. + * @return pointer to the dph node. + */ +tpDphHashNode dphLookupAssocId(tpAniSirGlobal pMac, tANI_U16 staIdx, tANI_U16* assocId, dphHashTableClass* pDphHashTable) +{ + tANI_U8 i; + + for(i=0; isize; i++) + { + if( (pDphHashTable->pDphNodeArray[i].added) && + (pDphHashTable->pDphNodeArray[i].staIndex == staIdx)) + { + *assocId = i; + break; + } + + } + if(i==pDphHashTable->size) + return NULL; + return &pDphHashTable->pDphNodeArray[i]; + +} + + + + +/** ------------------------------------------------------------- +\fn dphInitStaState +\brief Initialize STA state. this function saves the staId from the current entry in the DPH table with given assocId +\ if validStaIdx flag is set. Otherwise it sets the staId to invalid. +\param tpAniSirGlobal pMac +\param tSirMacAddr staAddr +\param tANI_U16 assocId +\param tANI_U8 validStaIdx - true ==> the staId in the DPH entry with given assocId is valid and restore it back. +\ false ==> set the staId to invalid. +\return tpDphHashNode - DPH hash node if found. + -------------------------------------------------------------*/ + +tpDphHashNode dphInitStaState(tpAniSirGlobal pMac, tSirMacAddr staAddr, + tANI_U16 assocId, tANI_U8 validStaIdx, dphHashTableClass* pDphHashTable) +{ + tANI_U32 val; + + tpDphHashNode pStaDs; + tANI_U16 staIdx = HAL_STA_INVALID_IDX; + + if (assocId >= pDphHashTable->size) + { + PELOGE(limLog(pMac, LOGE, FL("Invalid Assoc Id %d"), assocId);) + return NULL; + } + + pStaDs = getNode(pMac, (tANI_U8) assocId, pDphHashTable); + staIdx = pStaDs->staIndex; + + PELOG1(limLog(pMac, LOG1, FL("Assoc Id %d, Addr %08X"), assocId, pStaDs);) + + // Clear the STA node except for the next pointer (last 4 bytes) + vos_mem_set( (tANI_U8 *) pStaDs, sizeof(tDphHashNode) - sizeof(tpDphHashNode), 0); + + // Initialize the assocId + pStaDs->assocId = assocId; + if(true == validStaIdx) + pStaDs->staIndex = staIdx; + else + pStaDs->staIndex = HAL_STA_INVALID_IDX; + + // Initialize STA mac address + vos_mem_copy( pStaDs->staAddr, staAddr, sizeof(tSirMacAddr)); + + // Initialize fragmentation threshold + if (wlan_cfgGetInt(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("could not retrieve fragmentation threshold")); + else + pStaDs->fragSize = (tANI_U16) val; + + pStaDs->added = 1; + pStaDs->encPolicy = HAL_ENC_POLICY_NULL; + + pStaDs->isDisassocDeauthInProgress = 0; +#ifdef WLAN_FEATURE_11W + pStaDs->last_assoc_received_time = 0; +#endif + pStaDs->valid = 1; + return pStaDs; +} + +// --------------------------------------------------------------------- +/** + * dphAddHashEntry + * + * FUNCTION: + * Add entry to hash table + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param staAddr MAC address of the station + * @param staId Station ID assigned to the station + * @return Pointer to STA hash entry + */ + +tpDphHashNode dphAddHashEntry(tpAniSirGlobal pMac, tSirMacAddr staAddr, tANI_U16 assocId, dphHashTableClass* pDphHashTable) +{ + tpDphHashNode ptr, node; + tANI_U16 index = hashFunction(pMac, staAddr, pDphHashTable->size); + + PELOG1(limLog(pMac, LOG1, FL("assocId %d index %d STA addr"), + assocId, index); + dphPrintMacAddr(pMac, staAddr, LOG1);) + + if (assocId >= pDphHashTable->size) + { + PELOGE(limLog(pMac, LOGE, FL("invalid STA id %d"), assocId);) + return NULL; + } + + if (pDphHashTable->pDphNodeArray[assocId].added) + { + PELOGE(limLog(pMac, LOGE, FL("already added STA %d"), assocId);) + return NULL; + } + + for (ptr = pDphHashTable->pHashTable[index]; ptr; ptr = ptr->next) + { + if (ptr == ptr->next) + { + PELOGE(limLog(pMac, LOGE, FL("Infinite Loop"));) + return NULL; + } + + if (dphCompareMacAddr(staAddr, ptr->staAddr) || ptr->assocId== assocId) + break; + } + + if (ptr) + { + // Duplicate entry + limLog(pMac, LOGE, FL("assocId %d hashIndex %d entry exists"), + assocId, index); + return NULL; + } + else + { + if (dphInitStaState(pMac, staAddr, assocId, false, pDphHashTable) == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("could not Init STAid=%d"), assocId);) + return NULL; + } + + // Add the node to the link list + pDphHashTable->pDphNodeArray[assocId].next = pDphHashTable->pHashTable[index]; + pDphHashTable->pHashTable[index] = &pDphHashTable->pDphNodeArray[assocId]; + + node = pDphHashTable->pHashTable[index]; + return node; + } +} + +// --------------------------------------------------------------------- +/** + * dphDeleteHashEntry + * + * FUNCTION: + * Delete entry from hash table + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param staAddr MAC address of the station + * @param staId Station ID assigned to the station + * @return eSIR_SUCCESS if successful,\n + * eSIR_FAILURE otherwise + */ + +tSirRetStatus dphDeleteHashEntry(tpAniSirGlobal pMac, tSirMacAddr staAddr, tANI_U16 assocId, dphHashTableClass* pDphHashTable) +{ + tpDphHashNode ptr, prev; + tANI_U16 index = hashFunction(pMac, staAddr, pDphHashTable->size); + + + PELOG1(limLog(pMac, LOG1, FL("assocId %d index %d STA addr"), + assocId, index); + dphPrintMacAddr(pMac, staAddr, LOG1);) + + if (assocId >= pDphHashTable->size) + { + PELOGE(limLog(pMac, LOGE, FL("invalid STA id %d"), assocId);) + return eSIR_FAILURE; + } + + if (pDphHashTable->pDphNodeArray[assocId].added == 0) + { + PELOGE(limLog(pMac, LOGE, FL("STA %d never added"), assocId);) + return eSIR_FAILURE; + } + + + for (prev = 0, ptr = pDphHashTable->pHashTable[index]; + ptr; + prev = ptr, ptr = ptr->next) + { + if (dphCompareMacAddr(staAddr, ptr->staAddr)) + break; + if (prev == ptr) + { + PELOGE(limLog(pMac, LOGE, FL("Infinite Loop"));) + return eSIR_FAILURE; + } + } + + if (ptr) + { + /// Delete the entry after invalidating it + ptr->valid = 0; + memset(ptr->staAddr, 0, sizeof(ptr->staAddr)); + if (prev == 0) + pDphHashTable->pHashTable[index] = ptr->next; + else + prev->next = ptr->next; + ptr->added = 0; + ptr->isDisassocDeauthInProgress = 0; +#ifdef WLAN_FEATURE_11W + ptr->last_assoc_received_time = 0; +#endif + ptr->next = 0; + } + else + { + /// Entry not present + PELOGE(limLog(pMac, LOGE, FL("Entry not present STA addr")); + dphPrintMacAddr(pMac, staAddr, LOGE);) + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +// --------------------------------------------------------------------- +/** + * dphPrintMacAddr + * + * FUNCTION: + * Print a MAC address + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param addr MAC address + * @return None + */ + +void +dphPrintMacAddr(tpAniSirGlobal pMac, tANI_U8 addr[], tANI_U32 level) +{ + limLog(pMac, (tANI_U16) level, FL("MAC ADDR = %d:%d:%d:%d:%d:%d"), + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +} +// --------------------------------------------------------------------- + + +#ifdef SAP_AUTH_OFFLOAD +/** + * dph_entry_exist() - judge if entry exist + * + * @pmac: pointer to mac + * @staaddr: new sta mac address + * @associd : new sta assoc id + * @dphtable: pointer to hash table + * + * This function is used to judge whether entry exist (mac addr or assoc id). + * + * Return: if exist (mac addr or assoc id), return true. + */ + +bool dph_entry_exist(tpAniSirGlobal pmac, tSirMacAddr staaddr, + tANI_U16 associd, dphHashTableClass* dphtable) +{ + tpDphHashNode ptr; + tANI_U16 index = hashFunction(pmac, staaddr, dphtable->size); + tANI_U16 exist_aid = 0; + limLog(pmac, LOG1, FL("assocId %d index %d"), + associd, index); + + dphPrintMacAddr(pmac, staaddr, LOG1); + + if (associd >= dphtable->size) { + limLog(pmac, LOG1, FL("invalid STA id %d"), associd); + return false; + } + + if (dphtable->pDphNodeArray[associd].added) { + limLog(pmac, LOG1, FL("aid same")); + return true; + } + + ptr = dphLookupHashEntry(pmac, staaddr, &exist_aid, dphtable); + if (ptr) { + limLog(pmac, LOG1, FL("Mac same")); + return true; + } + return false; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.h new file mode 100644 index 000000000000..5925befa74e9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/dph/dphHashTable.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file dphHashTable.h contains the definition of the scheduler class. + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __DPH_HASH_TABLE_H__ +#define __DPH_HASH_TABLE_H__ + +#include "aniGlobal.h" +/// Compare MAC addresses, return true if same +static inline tANI_U8 +dphCompareMacAddr(tANI_U8 addr1[], tANI_U8 addr2[]) +{ + return((addr1[0] == addr2[0]) && + (addr1[1] == addr2[1]) && + (addr1[2] == addr2[2]) && + (addr1[3] == addr2[3]) && + (addr1[4] == addr2[4]) && + (addr1[5] == addr2[5])); +} + +/// Hash table class +typedef struct +{ + + /// The hash table itself + tpDphHashNode *pHashTable; + + /// The state array + tDphHashNode *pDphNodeArray; + tANI_U16 size; +} dphHashTableClass; + +/// The hash table object +extern dphHashTableClass dphHashTable; + +/* Print MAC address */ +extern void dphPrintMacAddr(struct sAniSirGlobal *pMac, tANI_U8 addr[], tANI_U32); + +tpDphHashNode dphLookupHashEntry(tpAniSirGlobal pMac, tANI_U8 staAddr[], tANI_U16 *pStaId, dphHashTableClass* pDphHashTable); +tpDphHashNode dphLookupAssocId(tpAniSirGlobal pMac, tANI_U16 staIdx, tANI_U16* assocId, dphHashTableClass* pDphHashTable); + + +/// Get a pointer to the hash node +extern tpDphHashNode dphGetHashEntry(tpAniSirGlobal pMac, tANI_U16 staId, dphHashTableClass* pDphHashTable); + +/// Add an entry to the hash table +extern tpDphHashNode dphAddHashEntry(tpAniSirGlobal pMac, tSirMacAddr staAddr, tANI_U16 staId, dphHashTableClass* pDphHashTable); + +/// Delete an entry from the hash table +extern tSirRetStatus dphDeleteHashEntry(tpAniSirGlobal pMac, tSirMacAddr staAddr, tANI_U16 staId, dphHashTableClass* pDphHashTable); + +void dphHashTableClassInit(tpAniSirGlobal pMac, dphHashTableClass* pDphHashTable); + +#ifdef SAP_AUTH_OFFLOAD +extern bool dph_entry_exist(tpAniSirGlobal pmac, tSirMacAddr staaddr, + tANI_U16 staid, dphHashTableClass* dphtable); + +#endif + +/// Initialize STA state +extern tpDphHashNode dphInitStaState(tpAniSirGlobal pMac, tSirMacAddr staAddr, + tANI_U16 staId, tANI_U8 validStaIdx, dphHashTableClass* pDphHashTable); + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgApi.h new file mode 100644 index 000000000000..4241748bf193 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgApi.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2011-2012,2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Kevin Nguyen + * Date: 04/09/02 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + * + */ + +#ifndef __CFGAPI_H +#define __CFGAPI_H + +#include +#include +#include +#include +#include + + +/*---------------------------------------------------------------------*/ +/* CFG definitions */ +/*---------------------------------------------------------------------*/ + +// CFG status +typedef enum eCfgStatusTypes { + CFG_INCOMPLETE, + CFG_SUCCESS, + CFG_FAILURE +} tCfgStatusTypes; + +// WEP key mapping table row structure +typedef struct +{ + tANI_U8 keyMappingAddr[SIR_MAC_ADDR_LENGTH]; + tANI_U32 wepOn; + tANI_U8 key[SIR_MAC_KEY_LENGTH]; + tANI_U32 status; +} tCfgWepKeyEntry; + + +/*---------------------------------------------------------------------*/ +/* CFG function prototypes */ +/*---------------------------------------------------------------------*/ + +tANI_U32 cfgNeedRestart(tpAniSirGlobal pMac, tANI_U16 cfgId) ; +tANI_U32 cfgNeedReload(tpAniSirGlobal pMac, tANI_U16 cfgId) ; + +/// CFG initialization function +void wlan_cfgInit(tpAniSirGlobal); + +/// Process host message +void cfgProcessMbMsg(tpAniSirGlobal, tSirMbMsg*); + +/// Set integer parameter value +tSirRetStatus cfgSetInt(tpAniSirGlobal, tANI_U16, tANI_U32); + +/// Check if the parameter is valid +tSirRetStatus cfgCheckValid(tpAniSirGlobal, tANI_U16); + +/// Get integer parameter value +tSirRetStatus wlan_cfgGetInt(tpAniSirGlobal, tANI_U16, tANI_U32*); + +/// Set string parameter value +tSirRetStatus cfgSetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32); + +tSirRetStatus cfgSetStrNotify(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32, int); + +//Cfg Download function for Prima or Integrated solutions. +void processCfgDownloadReq(tpAniSirGlobal); + +/// Get string parameter value +tSirRetStatus wlan_cfgGetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32*); + +/// Get string parameter maximum length +tSirRetStatus wlan_cfgGetStrMaxLen(tpAniSirGlobal, tANI_U16, tANI_U32*); + +/// Get string parameter maximum length +tSirRetStatus wlan_cfgGetStrLen(tpAniSirGlobal, tANI_U16, tANI_U32*); + +/// Get the regulatory tx power on given channel +tPowerdBm cfgGetRegulatoryMaxTransmitPower(tpAniSirGlobal pMac, tANI_U8 channel); + +/// Dump CFG data to memory +void cfgDump(tANI_U32*); + +/// Save parameters with P flag set +void cfgSave(void); + +/// Get capability info +extern tSirRetStatus cfgGetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 *pCap,tpPESession psessionEntry); + +/// Set capability info +extern void cfgSetCapabilityInfo(tpAniSirGlobal, tANI_U16); + +/* Clean up CFG module */ +void cfgCleanup(tpAniSirGlobal pMac); + +extern tANI_U8 *gCfgParamName[]; + +uint8_t* cfg_get_vendor_ie_ptr_from_oui(tpAniSirGlobal mac_ctx, + uint8_t *oui, + uint8_t oui_size, + uint8_t *ie, + uint16_t ie_len); + +#endif /* __CFGAPI_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgGlobal.h new file mode 100644 index 000000000000..893ebae20e48 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/cfgGlobal.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011-2013, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Sandesh Goel + * Date: 02/09/03 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + * + */ + +#ifndef __CFGGLOBAL_H +#define __CFGGLOBAL_H + +#include "sirCommon.h" +#include "sirTypes.h" +#include "wniCfgSta.h" +#include "wniCfgAp.h" + +#define CFG_MAX_NUM_STA SIR_MAX_NUM_STA_IN_IBSS + +#define CFG_MAX_STATIC_STRING 70 +#define CFG_MAX_STR_LEN 256 // as the number of channels grows, 128 is not big enough + +/*--------------------------------------------------------------------*/ +/* Configuration Control Structure */ +/*--------------------------------------------------------------------*/ +typedef struct +{ + tANI_U32 control; +} tCfgCtl; + +struct cfgstatic_string { + uint16_t cfg_id; + uint8_t max_len; + uint8_t length; + uint8_t data[255]; +}; + +struct cgstatic { + uint16_t cfg_id; + uint32_t control; + uint32_t cfg_imin; + uint32_t cfg_imax; + uint32_t cfg_ival; + void *p_str_data; +}; + +typedef struct sAniSirCfg +{ + // CFG module status + tANI_U8 gCfgStatus; + + tCfgCtl *gCfgEntry; + tANI_U32 *gCfgIBufMin; + tANI_U32 *gCfgIBufMax; + tANI_U32 *gCfgIBuf; + tANI_U8 *gCfgSBuf; + + tANI_U16 gCfgMaxIBufSize; + tANI_U16 gCfgMaxSBufSize; + + // Static buffer for string parameter (must be word-aligned) + tANI_U8 *gSBuffer; + + // Message parameter list buffer (enough for largest possible response) +} tAniSirCfg, *tpAniSirCfg; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h new file mode 100644 index 000000000000..111c093c606f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dot11f.h @@ -0,0 +1,7583 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef DOT11F_H +#define DOT11F_H +/** + * \file dot11f.h + * + * \brief Structures, function prototypes & definitions + * for working with 802.11 Frames + * + * + * + * + * This file was automatically generated by 'framesc' + * Tue Sep 29 17:32:33 2015 from the following file(s): + * + * dot11f.frms + * + * PLEASE DON'T EDIT THIS FILE BY HAND! + * + * Instead, please update the input files & re-run + * 'framesc' For more information on 'framesc' & the + * frames language, run 'framesc --help'. + * + * + */ + +typedef tANI_U32 tDOT11F_U64[2]; + +#if defined ( _MSC_VER ) +# pragma warning (disable: 4214) /* nonstandard extension used */ +#endif /* Microsoft C/C++ bit field types other than int */ + +/* + * Frames Return Codes: + * + * Success is indicated by a return value of zero. Failure is indicated + * by the presence of the high bit. Warnings encountered in the course + * of a successful parse are indicated by various bits in the lower 31 + * being turned on. + * + * For instance, a return value of 0x0000000a would indicate that the + * parse succeeded, but that a mandatory IE wasn't present, and some IE + * was found to be corrupt. + * + * + */ + +#define DOT11F_PARSE_SUCCESS ( 0x00000000 ) +#define DOT11F_UNKNOWN_IES ( 0x00000001 ) +#define DOT11F_MANDATORY_IE_MISSING ( 0x00000002 ) +#define DOT11F_INCOMPLETE_IE ( 0x00000004 ) +#define DOT11F_SKIPPED_BAD_IE ( 0x00000008 ) +#define DOT11F_LAST_IE_TOO_LONG ( 0x00000010 ) +#define DOT11F_DUPLICATE_IE ( 0x00000020 ) +#define DOT11F_BAD_FIXED_VALUE ( 0x00000040 ) +#define DOT11F_INCOMPLETE_TLV ( 0x00000080 ) +#define DOT11F_INVALID_TLV_LENGTH ( 0x00000100 ) +#define DOT11F_SKIPPED_BAD_TLV ( 0x00000200 ) +#define DOT11F_UNKNOWN_TLVS ( 0x00000400 ) +#define DOT11F_LAST_TLV_TOO_LONG ( 0x00000800 ) +#define DOT11F_INTERNAL_ERROR ( 0x10000001 ) +#define DOT11F_MISSING_FIXED_FIELD ( 0x10000002 ) +#define DOT11F_BAD_INPUT_BUFFER ( 0x10000003 ) +#define DOT11F_BAD_OUTPUT_BUFFER ( 0x10000004 ) +#define DOT11F_BUFFER_OVERFLOW ( 0x10000005 ) +#define DOT11F_MANDATORY_TLV_MISSING ( 0x00001000 ) +#define DOT11F_FAILED(code) ( (code) & 0x10000000 ) +#define DOT11F_WARNED(code) ( ( ( 0 == (code) ) & 0x10000000 ) && code) +#define DOT11F_SUCCEEDED(code) ( (code) == 0 ) + +/********************************************************************* + * Fixed Fields * + ********************************************************************/ + +typedef struct sDot11fFfAID { + tANI_U16 associd; +} tDot11fFfAID; + +#define DOT11F_FF_AID_LEN ( 2 ) + +void dot11fUnpackFfAID(tpAniSirGlobal, tANI_U8*, tDot11fFfAID*); + +void dot11fPackFfAID(tpAniSirGlobal, tDot11fFfAID*, tANI_U8*); + +typedef struct sDot11fFfAction { + tANI_U8 action; +} tDot11fFfAction; + +#define DOT11F_FF_ACTION_LEN ( 1 ) + +void dot11fUnpackFfAction(tpAniSirGlobal, tANI_U8*, tDot11fFfAction*); + +void dot11fPackFfAction(tpAniSirGlobal, tDot11fFfAction*, tANI_U8*); + +typedef struct sDot11fFfAddBAParameterSet { + tANI_U16 amsduSupported: 1; + tANI_U16 policy: 1; + tANI_U16 tid: 4; + tANI_U16 bufferSize: 10; +} tDot11fFfAddBAParameterSet; + +#define DOT11F_FF_ADDBAPARAMETERSET_LEN ( 2 ) + +void dot11fUnpackFfAddBAParameterSet(tpAniSirGlobal, tANI_U8*, tDot11fFfAddBAParameterSet*); + +void dot11fPackFfAddBAParameterSet(tpAniSirGlobal, tDot11fFfAddBAParameterSet*, tANI_U8*); + +#define ADDBAPARAMETERSET_AMSDUSUPPORTED_OFFSET 0 +#define ADDBAPARAMETERSET_AMSDUSUPPORTED_WIDTH 1 +#define ADDBAPARAMETERSET_POLICY_OFFSET 1 +#define ADDBAPARAMETERSET_POLICY_WIDTH 1 +#define ADDBAPARAMETERSET_TID_OFFSET 2 +#define ADDBAPARAMETERSET_TID_WIDTH 4 +#define ADDBAPARAMETERSET_BUFFERSIZE_OFFSET 6 +#define ADDBAPARAMETERSET_BUFFERSIZE_WIDTH 10 + +typedef struct sDot11fFfAuthAlgo { + tANI_U16 algo; +} tDot11fFfAuthAlgo; + +#define DOT11F_FF_AUTHALGO_LEN ( 2 ) + +void dot11fUnpackFfAuthAlgo(tpAniSirGlobal, tANI_U8*, tDot11fFfAuthAlgo*); + +void dot11fPackFfAuthAlgo(tpAniSirGlobal, tDot11fFfAuthAlgo*, tANI_U8*); + +typedef struct sDot11fFfAuthSeqNo { + tANI_U16 no; +} tDot11fFfAuthSeqNo; + +#define DOT11F_FF_AUTHSEQNO_LEN ( 2 ) + +void dot11fUnpackFfAuthSeqNo(tpAniSirGlobal, tANI_U8*, tDot11fFfAuthSeqNo*); + +void dot11fPackFfAuthSeqNo(tpAniSirGlobal, tDot11fFfAuthSeqNo*, tANI_U8*); + +typedef struct sDot11fFfBAStartingSequenceControl { + tANI_U16 fragNumber: 4; + tANI_U16 ssn: 12; +} tDot11fFfBAStartingSequenceControl; + +#define DOT11F_FF_BASTARTINGSEQUENCECONTROL_LEN ( 2 ) + +void dot11fUnpackFfBAStartingSequenceControl(tpAniSirGlobal, tANI_U8*, tDot11fFfBAStartingSequenceControl*); + +void dot11fPackFfBAStartingSequenceControl(tpAniSirGlobal, tDot11fFfBAStartingSequenceControl*, tANI_U8*); + +#define BASTARTINGSEQUENCECONTROL_FRAGNUMBER_OFFSET 0 +#define BASTARTINGSEQUENCECONTROL_FRAGNUMBER_WIDTH 4 +#define BASTARTINGSEQUENCECONTROL_SSN_OFFSET 4 +#define BASTARTINGSEQUENCECONTROL_SSN_WIDTH 12 + +typedef struct sDot11fFfBATimeout { + tANI_U16 timeout; +} tDot11fFfBATimeout; + +#define DOT11F_FF_BATIMEOUT_LEN ( 2 ) + +void dot11fUnpackFfBATimeout(tpAniSirGlobal, tANI_U8*, tDot11fFfBATimeout*); + +void dot11fPackFfBATimeout(tpAniSirGlobal, tDot11fFfBATimeout*, tANI_U8*); + +typedef struct sDot11fFfBeaconInterval { + tANI_U16 interval; +} tDot11fFfBeaconInterval; + +#define DOT11F_FF_BEACONINTERVAL_LEN ( 2 ) + +void dot11fUnpackFfBeaconInterval(tpAniSirGlobal, tANI_U8*, tDot11fFfBeaconInterval*); + +void dot11fPackFfBeaconInterval(tpAniSirGlobal, tDot11fFfBeaconInterval*, tANI_U8*); + +typedef struct sDot11fFfCapabilities { + tANI_U16 ess: 1; + tANI_U16 ibss: 1; + tANI_U16 cfPollable: 1; + tANI_U16 cfPollReq: 1; + tANI_U16 privacy: 1; + tANI_U16 shortPreamble: 1; + tANI_U16 pbcc: 1; + tANI_U16 channelAgility: 1; + tANI_U16 spectrumMgt: 1; + tANI_U16 qos: 1; + tANI_U16 shortSlotTime: 1; + tANI_U16 apsd: 1; + tANI_U16 rrm: 1; + tANI_U16 dsssOfdm: 1; + tANI_U16 delayedBA: 1; + tANI_U16 immediateBA: 1; +} tDot11fFfCapabilities; + +#define DOT11F_FF_CAPABILITIES_LEN ( 2 ) + +void dot11fUnpackFfCapabilities(tpAniSirGlobal, tANI_U8*, tDot11fFfCapabilities*); + +void dot11fPackFfCapabilities(tpAniSirGlobal, tDot11fFfCapabilities*, tANI_U8*); + +#define CAPABILITIES_ESS_OFFSET 0 +#define CAPABILITIES_ESS_WIDTH 1 +#define CAPABILITIES_IBSS_OFFSET 1 +#define CAPABILITIES_IBSS_WIDTH 1 +#define CAPABILITIES_CFPOLLABLE_OFFSET 2 +#define CAPABILITIES_CFPOLLABLE_WIDTH 1 +#define CAPABILITIES_CFPOLLREQ_OFFSET 3 +#define CAPABILITIES_CFPOLLREQ_WIDTH 1 +#define CAPABILITIES_PRIVACY_OFFSET 4 +#define CAPABILITIES_PRIVACY_WIDTH 1 +#define CAPABILITIES_SHORTPREAMBLE_OFFSET 5 +#define CAPABILITIES_SHORTPREAMBLE_WIDTH 1 +#define CAPABILITIES_PBCC_OFFSET 6 +#define CAPABILITIES_PBCC_WIDTH 1 +#define CAPABILITIES_CHANNELAGILITY_OFFSET 7 +#define CAPABILITIES_CHANNELAGILITY_WIDTH 1 +#define CAPABILITIES_SPECTRUMMGT_OFFSET 8 +#define CAPABILITIES_SPECTRUMMGT_WIDTH 1 +#define CAPABILITIES_QOS_OFFSET 9 +#define CAPABILITIES_QOS_WIDTH 1 +#define CAPABILITIES_SHORTSLOTTIME_OFFSET 10 +#define CAPABILITIES_SHORTSLOTTIME_WIDTH 1 +#define CAPABILITIES_APSD_OFFSET 11 +#define CAPABILITIES_APSD_WIDTH 1 +#define CAPABILITIES_RRM_OFFSET 12 +#define CAPABILITIES_RRM_WIDTH 1 +#define CAPABILITIES_DSSSOFDM_OFFSET 13 +#define CAPABILITIES_DSSSOFDM_WIDTH 1 +#define CAPABILITIES_DELAYEDBA_OFFSET 14 +#define CAPABILITIES_DELAYEDBA_WIDTH 1 +#define CAPABILITIES_IMMEDIATEBA_OFFSET 15 +#define CAPABILITIES_IMMEDIATEBA_WIDTH 1 + +typedef struct sDot11fFfCategory { + tANI_U8 category; +} tDot11fFfCategory; + +#define DOT11F_FF_CATEGORY_LEN ( 1 ) + +void dot11fUnpackFfCategory(tpAniSirGlobal, tANI_U8*, tDot11fFfCategory*); + +void dot11fPackFfCategory(tpAniSirGlobal, tDot11fFfCategory*, tANI_U8*); + +typedef struct sDot11fFfCurrentAPAddress { + tANI_U8 mac[6]; +} tDot11fFfCurrentAPAddress; + +#define DOT11F_FF_CURRENTAPADDRESS_LEN ( 6 ) + +void dot11fUnpackFfCurrentAPAddress(tpAniSirGlobal, tANI_U8*, tDot11fFfCurrentAPAddress*); + +void dot11fPackFfCurrentAPAddress(tpAniSirGlobal, tDot11fFfCurrentAPAddress*, tANI_U8*); + +typedef struct sDot11fFfDelBAParameterSet { + tANI_U16 reserved: 11; + tANI_U16 initiator: 1; + tANI_U16 tid: 4; +} tDot11fFfDelBAParameterSet; + +#define DOT11F_FF_DELBAPARAMETERSET_LEN ( 2 ) + +void dot11fUnpackFfDelBAParameterSet(tpAniSirGlobal, tANI_U8*, tDot11fFfDelBAParameterSet*); + +void dot11fPackFfDelBAParameterSet(tpAniSirGlobal, tDot11fFfDelBAParameterSet*, tANI_U8*); + +#define DELBAPARAMETERSET_RESERVED_OFFSET 0 +#define DELBAPARAMETERSET_RESERVED_WIDTH 11 +#define DELBAPARAMETERSET_INITIATOR_OFFSET 11 +#define DELBAPARAMETERSET_INITIATOR_WIDTH 1 +#define DELBAPARAMETERSET_TID_OFFSET 12 +#define DELBAPARAMETERSET_TID_WIDTH 4 + +typedef struct sDot11fFfDialogToken { + tANI_U8 token; +} tDot11fFfDialogToken; + +#define DOT11F_FF_DIALOGTOKEN_LEN ( 1 ) + +void dot11fUnpackFfDialogToken(tpAniSirGlobal, tANI_U8*, tDot11fFfDialogToken*); + +void dot11fPackFfDialogToken(tpAniSirGlobal, tDot11fFfDialogToken*, tANI_U8*); + +typedef struct sDot11fFfLinkMargin { + tANI_U8 linkMargin; +} tDot11fFfLinkMargin; + +#define DOT11F_FF_LINKMARGIN_LEN ( 1 ) + +void dot11fUnpackFfLinkMargin(tpAniSirGlobal, tANI_U8*, tDot11fFfLinkMargin*); + +void dot11fPackFfLinkMargin(tpAniSirGlobal, tDot11fFfLinkMargin*, tANI_U8*); + +typedef struct sDot11fFfListenInterval { + tANI_U16 interval; +} tDot11fFfListenInterval; + +#define DOT11F_FF_LISTENINTERVAL_LEN ( 2 ) + +void dot11fUnpackFfListenInterval(tpAniSirGlobal, tANI_U8*, tDot11fFfListenInterval*); + +void dot11fPackFfListenInterval(tpAniSirGlobal, tDot11fFfListenInterval*, tANI_U8*); + +typedef struct sDot11fFfMaxTxPower { + tANI_U8 maxTxPower; +} tDot11fFfMaxTxPower; + +#define DOT11F_FF_MAXTXPOWER_LEN ( 1 ) + +void dot11fUnpackFfMaxTxPower(tpAniSirGlobal, tANI_U8*, tDot11fFfMaxTxPower*); + +void dot11fPackFfMaxTxPower(tpAniSirGlobal, tDot11fFfMaxTxPower*, tANI_U8*); + +typedef struct sDot11fFfNumOfRepetitions { + tANI_U16 repetitions; +} tDot11fFfNumOfRepetitions; + +#define DOT11F_FF_NUMOFREPETITIONS_LEN ( 2 ) + +void dot11fUnpackFfNumOfRepetitions(tpAniSirGlobal, tANI_U8*, tDot11fFfNumOfRepetitions*); + +void dot11fPackFfNumOfRepetitions(tpAniSirGlobal, tDot11fFfNumOfRepetitions*, tANI_U8*); + +typedef struct sDot11fFfOperatingMode { + tANI_U8 chanWidth: 2; + tANI_U8 reserved: 2; + tANI_U8 rxNSS: 3; + tANI_U8 rxNSSType: 1; +} tDot11fFfOperatingMode; + +#define DOT11F_FF_OPERATINGMODE_LEN ( 1 ) + +void dot11fUnpackFfOperatingMode(tpAniSirGlobal, tANI_U8*, tDot11fFfOperatingMode*); + +void dot11fPackFfOperatingMode(tpAniSirGlobal, tDot11fFfOperatingMode*, tANI_U8*); + +#define OPERATINGMODE_CHANWIDTH_OFFSET 0 +#define OPERATINGMODE_CHANWIDTH_WIDTH 2 +#define OPERATINGMODE_RESERVED_OFFSET 2 +#define OPERATINGMODE_RESERVED_WIDTH 2 +#define OPERATINGMODE_RXNSS_OFFSET 4 +#define OPERATINGMODE_RXNSS_WIDTH 3 +#define OPERATINGMODE_RXNSSTYPE_OFFSET 7 +#define OPERATINGMODE_RXNSSTYPE_WIDTH 1 + +typedef struct sDot11fFfP2POUI { + tANI_U32 oui; +} tDot11fFfP2POUI; + +#define DOT11F_FF_P2POUI_LEN ( 4 ) + +void dot11fUnpackFfP2POUI(tpAniSirGlobal, tANI_U8*, tDot11fFfP2POUI*); + +void dot11fPackFfP2POUI(tpAniSirGlobal, tDot11fFfP2POUI*, tANI_U8*); + +typedef struct sDot11fFfP2POUISubType { + tANI_U8 ouiSubtype; +} tDot11fFfP2POUISubType; + +#define DOT11F_FF_P2POUISUBTYPE_LEN ( 1 ) + +void dot11fUnpackFfP2POUISubType(tpAniSirGlobal, tANI_U8*, tDot11fFfP2POUISubType*); + +void dot11fPackFfP2POUISubType(tpAniSirGlobal, tDot11fFfP2POUISubType*, tANI_U8*); + +typedef struct sDot11fFfRCPI { + tANI_U8 rcpi; +} tDot11fFfRCPI; + +#define DOT11F_FF_RCPI_LEN ( 1 ) + +void dot11fUnpackFfRCPI(tpAniSirGlobal, tANI_U8*, tDot11fFfRCPI*); + +void dot11fPackFfRCPI(tpAniSirGlobal, tDot11fFfRCPI*, tANI_U8*); + +typedef struct sDot11fFfRSNI { + tANI_U8 rsni; +} tDot11fFfRSNI; + +#define DOT11F_FF_RSNI_LEN ( 1 ) + +void dot11fUnpackFfRSNI(tpAniSirGlobal, tANI_U8*, tDot11fFfRSNI*); + +void dot11fPackFfRSNI(tpAniSirGlobal, tDot11fFfRSNI*, tANI_U8*); + +typedef struct sDot11fFfReason { + tANI_U16 code; +} tDot11fFfReason; + +#define DOT11F_FF_REASON_LEN ( 2 ) + +void dot11fUnpackFfReason(tpAniSirGlobal, tANI_U8*, tDot11fFfReason*); + +void dot11fPackFfReason(tpAniSirGlobal, tDot11fFfReason*, tANI_U8*); + +typedef struct sDot11fFfRxAntennaId { + tANI_U8 antennaId; +} tDot11fFfRxAntennaId; + +#define DOT11F_FF_RXANTENNAID_LEN ( 1 ) + +void dot11fUnpackFfRxAntennaId(tpAniSirGlobal, tANI_U8*, tDot11fFfRxAntennaId*); + +void dot11fPackFfRxAntennaId(tpAniSirGlobal, tDot11fFfRxAntennaId*, tANI_U8*); + +typedef struct sDot11fFfSMPowerModeSet { + tANI_U8 PowerSave_En: 1; + tANI_U8 Mode: 1; + tANI_U8 reserved: 6; +} tDot11fFfSMPowerModeSet; + +#define DOT11F_FF_SMPOWERMODESET_LEN ( 1 ) + +void dot11fUnpackFfSMPowerModeSet(tpAniSirGlobal, tANI_U8*, tDot11fFfSMPowerModeSet*); + +void dot11fPackFfSMPowerModeSet(tpAniSirGlobal, tDot11fFfSMPowerModeSet*, tANI_U8*); + +#define SMPOWERMODESET_POWERSAVE_EN_OFFSET 0 +#define SMPOWERMODESET_POWERSAVE_EN_WIDTH 1 +#define SMPOWERMODESET_MODE_OFFSET 1 +#define SMPOWERMODESET_MODE_WIDTH 1 +#define SMPOWERMODESET_RESERVED_OFFSET 2 +#define SMPOWERMODESET_RESERVED_WIDTH 6 + +typedef struct sDot11fFfStatus { + tANI_U16 status; +} tDot11fFfStatus; + +#define DOT11F_FF_STATUS_LEN ( 2 ) + +void dot11fUnpackFfStatus(tpAniSirGlobal, tANI_U8*, tDot11fFfStatus*); + +void dot11fPackFfStatus(tpAniSirGlobal, tDot11fFfStatus*, tANI_U8*); + +typedef struct sDot11fFfStatusCode { + tANI_U8 statusCode; +} tDot11fFfStatusCode; + +#define DOT11F_FF_STATUSCODE_LEN ( 1 ) + +void dot11fUnpackFfStatusCode(tpAniSirGlobal, tANI_U8*, tDot11fFfStatusCode*); + +void dot11fPackFfStatusCode(tpAniSirGlobal, tDot11fFfStatusCode*, tANI_U8*); + +typedef struct sDot11fFfTPCEleID { + tANI_U8 TPCId; +} tDot11fFfTPCEleID; + +#define DOT11F_FF_TPCELEID_LEN ( 1 ) + +void dot11fUnpackFfTPCEleID(tpAniSirGlobal, tANI_U8*, tDot11fFfTPCEleID*); + +void dot11fPackFfTPCEleID(tpAniSirGlobal, tDot11fFfTPCEleID*, tANI_U8*); + +typedef struct sDot11fFfTPCEleLen { + tANI_U8 TPCLen; +} tDot11fFfTPCEleLen; + +#define DOT11F_FF_TPCELELEN_LEN ( 1 ) + +void dot11fUnpackFfTPCEleLen(tpAniSirGlobal, tANI_U8*, tDot11fFfTPCEleLen*); + +void dot11fPackFfTPCEleLen(tpAniSirGlobal, tDot11fFfTPCEleLen*, tANI_U8*); + +typedef struct sDot11fFfTSInfo { + tANI_U32 traffic_type: 1; + tANI_U32 tsid: 4; + tANI_U32 direction: 2; + tANI_U32 access_policy: 2; + tANI_U32 aggregation: 1; + tANI_U32 psb: 1; + tANI_U32 user_priority: 3; + tANI_U32 tsinfo_ack_pol: 2; + tANI_U32 schedule: 1; + tANI_U32 unused: 15; +} tDot11fFfTSInfo; + +#define DOT11F_FF_TSINFO_LEN ( 3 ) + +void dot11fUnpackFfTSInfo(tpAniSirGlobal, tANI_U8*, tDot11fFfTSInfo*); + +void dot11fPackFfTSInfo(tpAniSirGlobal, tDot11fFfTSInfo*, tANI_U8*); + +#define TSINFO_TRAFFIC_TYPE_OFFSET 0 +#define TSINFO_TRAFFIC_TYPE_WIDTH 1 +#define TSINFO_TSID_OFFSET 1 +#define TSINFO_TSID_WIDTH 4 +#define TSINFO_DIRECTION_OFFSET 5 +#define TSINFO_DIRECTION_WIDTH 2 +#define TSINFO_ACCESS_POLICY_OFFSET 7 +#define TSINFO_ACCESS_POLICY_WIDTH 2 +#define TSINFO_AGGREGATION_OFFSET 9 +#define TSINFO_AGGREGATION_WIDTH 1 +#define TSINFO_PSB_OFFSET 10 +#define TSINFO_PSB_WIDTH 1 +#define TSINFO_USER_PRIORITY_OFFSET 11 +#define TSINFO_USER_PRIORITY_WIDTH 3 +#define TSINFO_TSINFO_ACK_POL_OFFSET 14 +#define TSINFO_TSINFO_ACK_POL_WIDTH 2 +#define TSINFO_SCHEDULE_OFFSET 16 +#define TSINFO_SCHEDULE_WIDTH 1 +#define TSINFO_UNUSED_OFFSET 17 +#define TSINFO_UNUSED_WIDTH 15 + +typedef struct sDot11fFfTimeStamp { + tDOT11F_U64 timestamp; +} tDot11fFfTimeStamp; + +#define DOT11F_FF_TIMESTAMP_LEN ( 8 ) + +void dot11fUnpackFfTimeStamp(tpAniSirGlobal, tANI_U8*, tDot11fFfTimeStamp*); + +void dot11fPackFfTimeStamp(tpAniSirGlobal, tDot11fFfTimeStamp*, tANI_U8*); + +typedef struct sDot11fFfTransactionId { + tANI_U8 transId[2]; +} tDot11fFfTransactionId; + +#define DOT11F_FF_TRANSACTIONID_LEN ( 2 ) + +void dot11fUnpackFfTransactionId(tpAniSirGlobal, tANI_U8*, tDot11fFfTransactionId*); + +void dot11fPackFfTransactionId(tpAniSirGlobal, tDot11fFfTransactionId*, tANI_U8*); + +typedef struct sDot11fFfTxAntennaId { + tANI_U8 antennaId; +} tDot11fFfTxAntennaId; + +#define DOT11F_FF_TXANTENNAID_LEN ( 1 ) + +void dot11fUnpackFfTxAntennaId(tpAniSirGlobal, tANI_U8*, tDot11fFfTxAntennaId*); + +void dot11fPackFfTxAntennaId(tpAniSirGlobal, tDot11fFfTxAntennaId*, tANI_U8*); + +typedef struct sDot11fFfTxPower { + tANI_U8 txPower; +} tDot11fFfTxPower; + +#define DOT11F_FF_TXPOWER_LEN ( 1 ) + +void dot11fUnpackFfTxPower(tpAniSirGlobal, tANI_U8*, tDot11fFfTxPower*); + +void dot11fPackFfTxPower(tpAniSirGlobal, tDot11fFfTxPower*, tANI_U8*); + +typedef struct sDot11fFfVhtMembershipStatusArray { + tANI_U8 membershipStatusArray[8]; +} tDot11fFfVhtMembershipStatusArray; + +#define DOT11F_FF_VHTMEMBERSHIPSTATUSARRAY_LEN ( 8 ) + +void dot11fUnpackFfVhtMembershipStatusArray(tpAniSirGlobal, tANI_U8*, tDot11fFfVhtMembershipStatusArray*); + +void dot11fPackFfVhtMembershipStatusArray(tpAniSirGlobal, tDot11fFfVhtMembershipStatusArray*, tANI_U8*); + +typedef struct sDot11fFfVhtUserPositionArray { + tANI_U8 userPositionArray[16]; +} tDot11fFfVhtUserPositionArray; + +#define DOT11F_FF_VHTUSERPOSITIONARRAY_LEN ( 16 ) + +void dot11fUnpackFfVhtUserPositionArray(tpAniSirGlobal, tANI_U8*, tDot11fFfVhtUserPositionArray*); + +void dot11fPackFfVhtUserPositionArray(tpAniSirGlobal, tDot11fFfVhtUserPositionArray*, tANI_U8*); + +typedef struct sDot11fFfext_chan_switch_ann_action { + tANI_U32 switch_mode: 8; + tANI_U32 op_class: 8; + tANI_U32 new_channel: 8; + tANI_U32 switch_count: 8; +} tDot11fFfext_chan_switch_ann_action; + +#define DOT11F_FF_EXT_CHAN_SWITCH_ANN_ACTION_LEN ( 4 ) + +void dot11fUnpackFfext_chan_switch_ann_action(tpAniSirGlobal, tANI_U8*, tDot11fFfext_chan_switch_ann_action*); + +void dot11fPackFfext_chan_switch_ann_action(tpAniSirGlobal, tDot11fFfext_chan_switch_ann_action*, tANI_U8*); + +#define EXT_CHAN_SWITCH_ANN_ACTION_SWITCH_MODE_OFFSET 0 +#define EXT_CHAN_SWITCH_ANN_ACTION_SWITCH_MODE_WIDTH 8 +#define EXT_CHAN_SWITCH_ANN_ACTION_OP_CLASS_OFFSET 8 +#define EXT_CHAN_SWITCH_ANN_ACTION_OP_CLASS_WIDTH 8 +#define EXT_CHAN_SWITCH_ANN_ACTION_NEW_CHANNEL_OFFSET 16 +#define EXT_CHAN_SWITCH_ANN_ACTION_NEW_CHANNEL_WIDTH 8 +#define EXT_CHAN_SWITCH_ANN_ACTION_SWITCH_COUNT_OFFSET 24 +#define EXT_CHAN_SWITCH_ANN_ACTION_SWITCH_COUNT_WIDTH 8 + +/********************************************************************* + * TLVs * + ********************************************************************/ + +// ID 1 (0x0001) +typedef struct sDot11fTLVAuthorizedMACs { + tANI_U8 present; + tANI_U8 mac[6]; +} tDot11fTLVAuthorizedMACs; + +#define DOT11F_TLV_AUTHORIZEDMACS ( 1 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_AUTHORIZEDMACS_MIN_LEN ( 6 ) + +#define DOT11F_TLV_AUTHORIZEDMACS_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvAuthorizedMACs(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVAuthorizedMACs*); + +tANI_U32 dot11fPackTlvAuthorizedMACs(tpAniSirGlobal, tDot11fTLVAuthorizedMACs*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvAuthorizedMACs(tpAniSirGlobal, tDot11fTLVAuthorizedMACs*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 3 (0x0003) +typedef struct sDot11fTLVRequestToEnroll { + tANI_U8 present; + tANI_U8 req; +} tDot11fTLVRequestToEnroll; + +#define DOT11F_TLV_REQUESTTOENROLL ( 3 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_REQUESTTOENROLL_MIN_LEN ( 1 ) + +#define DOT11F_TLV_REQUESTTOENROLL_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvRequestToEnroll(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVRequestToEnroll*); + +tANI_U32 dot11fPackTlvRequestToEnroll(tpAniSirGlobal, tDot11fTLVRequestToEnroll*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvRequestToEnroll(tpAniSirGlobal, tDot11fTLVRequestToEnroll*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 0 (0x0000) +typedef struct sDot11fTLVVersion2 { + tANI_U8 present; + tANI_U8 minor: 4; + tANI_U8 major: 4; +} tDot11fTLVVersion2; + +#define DOT11F_TLV_VERSION2 ( 0 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_VERSION2_MIN_LEN ( 1 ) + +#define DOT11F_TLV_VERSION2_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvVersion2(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVVersion2*); + +tANI_U32 dot11fPackTlvVersion2(tpAniSirGlobal, tDot11fTLVVersion2*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvVersion2(tpAniSirGlobal, tDot11fTLVVersion2*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4183 (0x1057) +typedef struct sDot11fTLVAPSetupLocked { + tANI_U8 present; + tANI_U8 fLocked; +} tDot11fTLVAPSetupLocked; + +#define DOT11F_TLV_APSETUPLOCKED ( 4183 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_APSETUPLOCKED_MIN_LEN ( 3 ) + +#define DOT11F_TLV_APSETUPLOCKED_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvAPSetupLocked(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVAPSetupLocked*); + +tANI_U32 dot11fPackTlvAPSetupLocked(tpAniSirGlobal, tDot11fTLVAPSetupLocked*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvAPSetupLocked(tpAniSirGlobal, tDot11fTLVAPSetupLocked*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4098 (0x1002) +typedef struct sDot11fTLVAssociationState { + tANI_U8 present; + tANI_U16 state; +} tDot11fTLVAssociationState; + +#define DOT11F_TLV_ASSOCIATIONSTATE ( 4098 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_ASSOCIATIONSTATE_MIN_LEN ( 4 ) + +#define DOT11F_TLV_ASSOCIATIONSTATE_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvAssociationState(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVAssociationState*); + +tANI_U32 dot11fPackTlvAssociationState(tpAniSirGlobal, tDot11fTLVAssociationState*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvAssociationState(tpAniSirGlobal, tDot11fTLVAssociationState*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 11 (0x000b) +typedef struct sDot11fTLVChannelList { + tANI_U8 present; + tANI_U8 countryString[3]; + tANI_U8 num_channelList; + tANI_U8 channelList[251]; +} tDot11fTLVChannelList; + +#define DOT11F_TLV_CHANNELLIST ( 11 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_CHANNELLIST_MIN_LEN ( 4 ) + +#define DOT11F_TLV_CHANNELLIST_MAX_LEN ( 255 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvChannelList(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVChannelList*); + +tANI_U32 dot11fPackTlvChannelList(tpAniSirGlobal, tDot11fTLVChannelList*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvChannelList(tpAniSirGlobal, tDot11fTLVChannelList*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4104 (0x1008) +typedef struct sDot11fTLVConfigMethods { + tANI_U8 present; + tANI_U16 methods; +} tDot11fTLVConfigMethods; + +#define DOT11F_TLV_CONFIGMETHODS ( 4104 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_CONFIGMETHODS_MIN_LEN ( 4 ) + +#define DOT11F_TLV_CONFIGMETHODS_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvConfigMethods(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVConfigMethods*); + +tANI_U32 dot11fPackTlvConfigMethods(tpAniSirGlobal, tDot11fTLVConfigMethods*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvConfigMethods(tpAniSirGlobal, tDot11fTLVConfigMethods*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4105 (0x1009) +typedef struct sDot11fTLVConfigurationError { + tANI_U8 present; + tANI_U16 error; +} tDot11fTLVConfigurationError; + +#define DOT11F_TLV_CONFIGURATIONERROR ( 4105 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_CONFIGURATIONERROR_MIN_LEN ( 4 ) + +#define DOT11F_TLV_CONFIGURATIONERROR_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvConfigurationError(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVConfigurationError*); + +tANI_U32 dot11fPackTlvConfigurationError(tpAniSirGlobal, tDot11fTLVConfigurationError*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvConfigurationError(tpAniSirGlobal, tDot11fTLVConfigurationError*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 5 (0x0005) +typedef struct sDot11fTLVConfigurationTimeout { + tANI_U8 present; + tANI_U8 GOConfigTimeout; + tANI_U8 CLConfigTimeout; +} tDot11fTLVConfigurationTimeout; + +#define DOT11F_TLV_CONFIGURATIONTIMEOUT ( 5 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_CONFIGURATIONTIMEOUT_MIN_LEN ( 3 ) + +#define DOT11F_TLV_CONFIGURATIONTIMEOUT_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvConfigurationTimeout(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVConfigurationTimeout*); + +tANI_U32 dot11fPackTlvConfigurationTimeout(tpAniSirGlobal, tDot11fTLVConfigurationTimeout*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvConfigurationTimeout(tpAniSirGlobal, tDot11fTLVConfigurationTimeout*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4113 (0x1011) +typedef struct sDot11fTLVDeviceName { + tANI_U8 present; + tANI_U8 num_text; + tANI_U8 text[32]; +} tDot11fTLVDeviceName; + +#define DOT11F_TLV_DEVICENAME ( 4113 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_DEVICENAME_MIN_LEN ( 2 ) + +#define DOT11F_TLV_DEVICENAME_MAX_LEN ( 34 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvDeviceName(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVDeviceName*); + +tANI_U32 dot11fPackTlvDeviceName(tpAniSirGlobal, tDot11fTLVDeviceName*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvDeviceName(tpAniSirGlobal, tDot11fTLVDeviceName*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4114 (0x1012) +typedef struct sDot11fTLVDevicePasswordID { + tANI_U8 present; + tANI_U16 id; +} tDot11fTLVDevicePasswordID; + +#define DOT11F_TLV_DEVICEPASSWORDID ( 4114 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_DEVICEPASSWORDID_MIN_LEN ( 4 ) + +#define DOT11F_TLV_DEVICEPASSWORDID_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvDevicePasswordID(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVDevicePasswordID*); + +tANI_U32 dot11fPackTlvDevicePasswordID(tpAniSirGlobal, tDot11fTLVDevicePasswordID*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvDevicePasswordID(tpAniSirGlobal, tDot11fTLVDevicePasswordID*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 8 (0x0008) +typedef struct sDot11fTLVExtendedListenTiming { + tANI_U8 present; + tANI_U16 availibilityPeriod; + tANI_U16 availibilityInterval; +} tDot11fTLVExtendedListenTiming; + +#define DOT11F_TLV_EXTENDEDLISTENTIMING ( 8 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_EXTENDEDLISTENTIMING_MIN_LEN ( 5 ) + +#define DOT11F_TLV_EXTENDEDLISTENTIMING_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvExtendedListenTiming(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVExtendedListenTiming*); + +tANI_U32 dot11fPackTlvExtendedListenTiming(tpAniSirGlobal, tDot11fTLVExtendedListenTiming*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvExtendedListenTiming(tpAniSirGlobal, tDot11fTLVExtendedListenTiming*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4 (0x0004) +typedef struct sDot11fTLVGOIntent { + tANI_U8 present; + tANI_U8 GOIntent; +} tDot11fTLVGOIntent; + +#define DOT11F_TLV_GOINTENT ( 4 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_GOINTENT_MIN_LEN ( 2 ) + +#define DOT11F_TLV_GOINTENT_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvGOIntent(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVGOIntent*); + +tANI_U32 dot11fPackTlvGOIntent(tpAniSirGlobal, tDot11fTLVGOIntent*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvGOIntent(tpAniSirGlobal, tDot11fTLVGOIntent*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 9 (0x0009) +typedef struct sDot11fTLVIntendedP2PInterfaceAddress { + tANI_U8 present; + tANI_U8 P2PInterfaceAddress[6]; +} tDot11fTLVIntendedP2PInterfaceAddress; + +#define DOT11F_TLV_INTENDEDP2PINTERFACEADDRESS ( 9 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_INTENDEDP2PINTERFACEADDRESS_MIN_LEN ( 7 ) + +#define DOT11F_TLV_INTENDEDP2PINTERFACEADDRESS_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvIntendedP2PInterfaceAddress(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVIntendedP2PInterfaceAddress*); + +tANI_U32 dot11fPackTlvIntendedP2PInterfaceAddress(tpAniSirGlobal, tDot11fTLVIntendedP2PInterfaceAddress*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvIntendedP2PInterfaceAddress(tpAniSirGlobal, tDot11fTLVIntendedP2PInterfaceAddress*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 18 (0x0012) +typedef struct sDot11fTLVInvitationFlags { + tANI_U8 present; + tANI_U8 invitationFlags; +} tDot11fTLVInvitationFlags; + +#define DOT11F_TLV_INVITATIONFLAGS ( 18 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_INVITATIONFLAGS_MIN_LEN ( 2 ) + +#define DOT11F_TLV_INVITATIONFLAGS_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvInvitationFlags(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVInvitationFlags*); + +tANI_U32 dot11fPackTlvInvitationFlags(tpAniSirGlobal, tDot11fTLVInvitationFlags*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvInvitationFlags(tpAniSirGlobal, tDot11fTLVInvitationFlags*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 6 (0x0006) +typedef struct sDot11fTLVListenChannel { + tANI_U8 present; + tANI_U8 countryString[3]; + tANI_U8 regulatoryClass; + tANI_U8 channel; +} tDot11fTLVListenChannel; + +#define DOT11F_TLV_LISTENCHANNEL ( 6 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_LISTENCHANNEL_MIN_LEN ( 6 ) + +#define DOT11F_TLV_LISTENCHANNEL_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvListenChannel(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVListenChannel*); + +tANI_U32 dot11fPackTlvListenChannel(tpAniSirGlobal, tDot11fTLVListenChannel*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvListenChannel(tpAniSirGlobal, tDot11fTLVListenChannel*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4129 (0x1021) +typedef struct sDot11fTLVManufacturer { + tANI_U8 present; + tANI_U8 num_name; + tANI_U8 name[64]; +} tDot11fTLVManufacturer; + +#define DOT11F_TLV_MANUFACTURER ( 4129 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_MANUFACTURER_MIN_LEN ( 2 ) + +#define DOT11F_TLV_MANUFACTURER_MAX_LEN ( 66 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvManufacturer(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVManufacturer*); + +tANI_U32 dot11fPackTlvManufacturer(tpAniSirGlobal, tDot11fTLVManufacturer*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvManufacturer(tpAniSirGlobal, tDot11fTLVManufacturer*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 1 (0x0001) +typedef struct sDot11fTLVMinorReasonCode { + tANI_U8 present; + tANI_U8 minorReasonCode; +} tDot11fTLVMinorReasonCode; + +#define DOT11F_TLV_MINORREASONCODE ( 1 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_MINORREASONCODE_MIN_LEN ( 2 ) + +#define DOT11F_TLV_MINORREASONCODE_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvMinorReasonCode(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVMinorReasonCode*); + +tANI_U32 dot11fPackTlvMinorReasonCode(tpAniSirGlobal, tDot11fTLVMinorReasonCode*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvMinorReasonCode(tpAniSirGlobal, tDot11fTLVMinorReasonCode*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4131 (0x1023) +typedef struct sDot11fTLVModelName { + tANI_U8 present; + tANI_U8 num_text; + tANI_U8 text[32]; +} tDot11fTLVModelName; + +#define DOT11F_TLV_MODELNAME ( 4131 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_MODELNAME_MIN_LEN ( 2 ) + +#define DOT11F_TLV_MODELNAME_MAX_LEN ( 34 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvModelName(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVModelName*); + +tANI_U32 dot11fPackTlvModelName(tpAniSirGlobal, tDot11fTLVModelName*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvModelName(tpAniSirGlobal, tDot11fTLVModelName*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4132 (0x1024) +typedef struct sDot11fTLVModelNumber { + tANI_U8 present; + tANI_U8 num_text; + tANI_U8 text[32]; +} tDot11fTLVModelNumber; + +#define DOT11F_TLV_MODELNUMBER ( 4132 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_MODELNUMBER_MIN_LEN ( 2 ) + +#define DOT11F_TLV_MODELNUMBER_MAX_LEN ( 34 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvModelNumber(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVModelNumber*); + +tANI_U32 dot11fPackTlvModelNumber(tpAniSirGlobal, tDot11fTLVModelNumber*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvModelNumber(tpAniSirGlobal, tDot11fTLVModelNumber*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 12 (0x000c) +typedef struct sDot11fTLVNoticeOfAbsence { + tANI_U8 present; + tANI_U8 index; + tANI_U8 CTSWindowOppPS; + tANI_U8 num_NoADesc; + tANI_U8 NoADesc[36]; +} tDot11fTLVNoticeOfAbsence; + +#define DOT11F_TLV_NOTICEOFABSENCE ( 12 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_NOTICEOFABSENCE_MIN_LEN ( 3 ) + +#define DOT11F_TLV_NOTICEOFABSENCE_MAX_LEN ( 39 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvNoticeOfAbsence(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVNoticeOfAbsence*); + +tANI_U32 dot11fPackTlvNoticeOfAbsence(tpAniSirGlobal, tDot11fTLVNoticeOfAbsence*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvNoticeOfAbsence(tpAniSirGlobal, tDot11fTLVNoticeOfAbsence*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 17 (0x0011) +typedef struct sDot11fTLVOperatingChannel { + tANI_U8 present; + tANI_U8 countryString[3]; + tANI_U8 regulatoryClass; + tANI_U8 channel; +} tDot11fTLVOperatingChannel; + +#define DOT11F_TLV_OPERATINGCHANNEL ( 17 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_OPERATINGCHANNEL_MIN_LEN ( 6 ) + +#define DOT11F_TLV_OPERATINGCHANNEL_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvOperatingChannel(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVOperatingChannel*); + +tANI_U32 dot11fPackTlvOperatingChannel(tpAniSirGlobal, tDot11fTLVOperatingChannel*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvOperatingChannel(tpAniSirGlobal, tDot11fTLVOperatingChannel*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 2 (0x0002) +typedef struct sDot11fTLVP2PCapability { + tANI_U8 present; + tANI_U8 deviceCapability; + tANI_U8 groupCapability; +} tDot11fTLVP2PCapability; + +#define DOT11F_TLV_P2PCAPABILITY ( 2 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PCAPABILITY_MIN_LEN ( 3 ) + +#define DOT11F_TLV_P2PCAPABILITY_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PCapability(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PCapability*); + +tANI_U32 dot11fPackTlvP2PCapability(tpAniSirGlobal, tDot11fTLVP2PCapability*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PCapability(tpAniSirGlobal, tDot11fTLVP2PCapability*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 3 (0x0003) +typedef struct sDot11fTLVP2PDeviceId { + tANI_U8 present; + tANI_U8 P2PDeviceAddress[6]; +} tDot11fTLVP2PDeviceId; + +#define DOT11F_TLV_P2PDEVICEID ( 3 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PDEVICEID_MIN_LEN ( 7 ) + +#define DOT11F_TLV_P2PDEVICEID_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PDeviceId(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PDeviceId*); + +tANI_U32 dot11fPackTlvP2PDeviceId(tpAniSirGlobal, tDot11fTLVP2PDeviceId*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PDeviceId(tpAniSirGlobal, tDot11fTLVP2PDeviceId*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 13 (0x000d) +typedef struct sDot11fTLVP2PDeviceInfo { + tANI_U8 present; + tANI_U8 P2PDeviceAddress[6]; + tANI_U16 configMethod; + tANI_U8 primaryDeviceType[8]; + tDot11fTLVDeviceName DeviceName; +} tDot11fTLVP2PDeviceInfo; + +#define DOT11F_TLV_P2PDEVICEINFO ( 13 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PDEVICEINFO_MIN_LEN ( 17 ) + +#define DOT11F_TLV_P2PDEVICEINFO_MAX_LEN ( 53 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PDeviceInfo(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PDeviceInfo*); + +tANI_U32 dot11fPackTlvP2PDeviceInfo(tpAniSirGlobal, tDot11fTLVP2PDeviceInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PDeviceInfo(tpAniSirGlobal, tDot11fTLVP2PDeviceInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 7 (0x0007) +typedef struct sDot11fTLVP2PGroupBssid { + tANI_U8 present; + tANI_U8 P2PGroupBssid[6]; +} tDot11fTLVP2PGroupBssid; + +#define DOT11F_TLV_P2PGROUPBSSID ( 7 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PGROUPBSSID_MIN_LEN ( 7 ) + +#define DOT11F_TLV_P2PGROUPBSSID_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PGroupBssid(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PGroupBssid*); + +tANI_U32 dot11fPackTlvP2PGroupBssid(tpAniSirGlobal, tDot11fTLVP2PGroupBssid*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PGroupBssid(tpAniSirGlobal, tDot11fTLVP2PGroupBssid*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 15 (0x000f) +typedef struct sDot11fTLVP2PGroupId { + tANI_U8 present; + tANI_U8 deviceAddress[6]; + tANI_U8 num_ssid; + tANI_U8 ssid[32]; +} tDot11fTLVP2PGroupId; + +#define DOT11F_TLV_P2PGROUPID ( 15 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PGROUPID_MIN_LEN ( 7 ) + +#define DOT11F_TLV_P2PGROUPID_MAX_LEN ( 39 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PGroupId(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PGroupId*); + +tANI_U32 dot11fPackTlvP2PGroupId(tpAniSirGlobal, tDot11fTLVP2PGroupId*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PGroupId(tpAniSirGlobal, tDot11fTLVP2PGroupId*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 14 (0x000e) +typedef struct sDot11fTLVP2PGroupInfo { + tANI_U8 present; + tANI_U8 num_P2PClientInfoDesc; + tANI_U8 P2PClientInfoDesc[1024]; +} tDot11fTLVP2PGroupInfo; + +#define DOT11F_TLV_P2PGROUPINFO ( 14 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PGROUPINFO_MIN_LEN ( 1 ) + +#define DOT11F_TLV_P2PGROUPINFO_MAX_LEN ( 1025 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PGroupInfo(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PGroupInfo*); + +tANI_U32 dot11fPackTlvP2PGroupInfo(tpAniSirGlobal, tDot11fTLVP2PGroupInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PGroupInfo(tpAniSirGlobal, tDot11fTLVP2PGroupInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 0 (0x0000) +typedef struct sDot11fTLVP2PStatus { + tANI_U8 present; + tANI_U8 status; +} tDot11fTLVP2PStatus; + +#define DOT11F_TLV_P2PSTATUS ( 0 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PSTATUS_MIN_LEN ( 2 ) + +#define DOT11F_TLV_P2PSTATUS_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PStatus(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PStatus*); + +tANI_U32 dot11fPackTlvP2PStatus(tpAniSirGlobal, tDot11fTLVP2PStatus*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PStatus(tpAniSirGlobal, tDot11fTLVP2PStatus*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4180 (0x1054) +typedef struct sDot11fTLVPrimaryDeviceType { + tANI_U8 present; + tANI_U16 primary_category; + tANI_U8 oui[4]; + tANI_U16 sub_category; +} tDot11fTLVPrimaryDeviceType; + +#define DOT11F_TLV_PRIMARYDEVICETYPE ( 4180 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_PRIMARYDEVICETYPE_MIN_LEN ( 10 ) + +#define DOT11F_TLV_PRIMARYDEVICETYPE_MAX_LEN ( 10 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvPrimaryDeviceType(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVPrimaryDeviceType*); + +tANI_U32 dot11fPackTlvPrimaryDeviceType(tpAniSirGlobal, tDot11fTLVPrimaryDeviceType*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvPrimaryDeviceType(tpAniSirGlobal, tDot11fTLVPrimaryDeviceType*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4156 (0x103c) +typedef struct sDot11fTLVRFBands { + tANI_U8 present; + tANI_U8 bands; +} tDot11fTLVRFBands; + +#define DOT11F_TLV_RFBANDS ( 4156 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_RFBANDS_MIN_LEN ( 3 ) + +#define DOT11F_TLV_RFBANDS_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvRFBands(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVRFBands*); + +tANI_U32 dot11fPackTlvRFBands(tpAniSirGlobal, tDot11fTLVRFBands*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvRFBands(tpAniSirGlobal, tDot11fTLVRFBands*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4202 (0x106a) +typedef struct sDot11fTLVRequestDeviceType { + tANI_U8 present; + tANI_U16 primary_category; + tANI_U8 oui[4]; + tANI_U16 sub_category; +} tDot11fTLVRequestDeviceType; + +#define DOT11F_TLV_REQUESTDEVICETYPE ( 4202 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_REQUESTDEVICETYPE_MIN_LEN ( 10 ) + +#define DOT11F_TLV_REQUESTDEVICETYPE_MAX_LEN ( 10 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvRequestDeviceType(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVRequestDeviceType*); + +tANI_U32 dot11fPackTlvRequestDeviceType(tpAniSirGlobal, tDot11fTLVRequestDeviceType*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvRequestDeviceType(tpAniSirGlobal, tDot11fTLVRequestDeviceType*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4154 (0x103a) +typedef struct sDot11fTLVRequestType { + tANI_U8 present; + tANI_U8 reqType; +} tDot11fTLVRequestType; + +#define DOT11F_TLV_REQUESTTYPE ( 4154 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_REQUESTTYPE_MIN_LEN ( 3 ) + +#define DOT11F_TLV_REQUESTTYPE_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvRequestType(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVRequestType*); + +tANI_U32 dot11fPackTlvRequestType(tpAniSirGlobal, tDot11fTLVRequestType*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvRequestType(tpAniSirGlobal, tDot11fTLVRequestType*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4155 (0x103b) +typedef struct sDot11fTLVResponseType { + tANI_U8 present; + tANI_U8 resType; +} tDot11fTLVResponseType; + +#define DOT11F_TLV_RESPONSETYPE ( 4155 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_RESPONSETYPE_MIN_LEN ( 3 ) + +#define DOT11F_TLV_RESPONSETYPE_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvResponseType(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVResponseType*); + +tANI_U32 dot11fPackTlvResponseType(tpAniSirGlobal, tDot11fTLVResponseType*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvResponseType(tpAniSirGlobal, tDot11fTLVResponseType*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4161 (0x1041) +typedef struct sDot11fTLVSelectedRegistrar { + tANI_U8 present; + tANI_U8 selected; +} tDot11fTLVSelectedRegistrar; + +#define DOT11F_TLV_SELECTEDREGISTRAR ( 4161 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_SELECTEDREGISTRAR_MIN_LEN ( 3 ) + +#define DOT11F_TLV_SELECTEDREGISTRAR_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvSelectedRegistrar(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVSelectedRegistrar*); + +tANI_U32 dot11fPackTlvSelectedRegistrar(tpAniSirGlobal, tDot11fTLVSelectedRegistrar*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvSelectedRegistrar(tpAniSirGlobal, tDot11fTLVSelectedRegistrar*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4179 (0x1053) +typedef struct sDot11fTLVSelectedRegistrarConfigMethods { + tANI_U8 present; + tANI_U16 methods; +} tDot11fTLVSelectedRegistrarConfigMethods; + +#define DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS ( 4179 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS_MIN_LEN ( 4 ) + +#define DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvSelectedRegistrarConfigMethods(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVSelectedRegistrarConfigMethods*); + +tANI_U32 dot11fPackTlvSelectedRegistrarConfigMethods(tpAniSirGlobal, tDot11fTLVSelectedRegistrarConfigMethods*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvSelectedRegistrarConfigMethods(tpAniSirGlobal, tDot11fTLVSelectedRegistrarConfigMethods*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4162 (0x1042) +typedef struct sDot11fTLVSerialNumber { + tANI_U8 present; + tANI_U8 num_text; + tANI_U8 text[32]; +} tDot11fTLVSerialNumber; + +#define DOT11F_TLV_SERIALNUMBER ( 4162 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_SERIALNUMBER_MIN_LEN ( 2 ) + +#define DOT11F_TLV_SERIALNUMBER_MAX_LEN ( 34 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvSerialNumber(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVSerialNumber*); + +tANI_U32 dot11fPackTlvSerialNumber(tpAniSirGlobal, tDot11fTLVSerialNumber*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvSerialNumber(tpAniSirGlobal, tDot11fTLVSerialNumber*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4167 (0x1047) +typedef struct sDot11fTLVUUID_E { + tANI_U8 present; + tANI_U8 uuid[16]; +} tDot11fTLVUUID_E; + +#define DOT11F_TLV_UUID_E ( 4167 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_UUID_E_MIN_LEN ( 18 ) + +#define DOT11F_TLV_UUID_E_MAX_LEN ( 18 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvUUID_E(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVUUID_E*); + +tANI_U32 dot11fPackTlvUUID_E(tpAniSirGlobal, tDot11fTLVUUID_E*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvUUID_E(tpAniSirGlobal, tDot11fTLVUUID_E*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4168 (0x1048) +typedef struct sDot11fTLVUUID_R { + tANI_U8 present; + tANI_U8 uuid[16]; +} tDot11fTLVUUID_R; + +#define DOT11F_TLV_UUID_R ( 4168 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_UUID_R_MIN_LEN ( 18 ) + +#define DOT11F_TLV_UUID_R_MAX_LEN ( 18 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvUUID_R(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVUUID_R*); + +tANI_U32 dot11fPackTlvUUID_R(tpAniSirGlobal, tDot11fTLVUUID_R*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvUUID_R(tpAniSirGlobal, tDot11fTLVUUID_R*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4169 (0x1049) +typedef struct sDot11fTLVVendorExtension { + tANI_U8 present; + tANI_U8 vendorId[3]; + tDot11fTLVVersion2 Version2; + tDot11fTLVAuthorizedMACs AuthorizedMACs; + tDot11fTLVRequestToEnroll RequestToEnroll; +} tDot11fTLVVendorExtension; + +#define DOT11F_TLV_VENDOREXTENSION ( 4169 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_VENDOREXTENSION_MIN_LEN ( 5 ) + +#define DOT11F_TLV_VENDOREXTENSION_MAX_LEN ( 19 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvVendorExtension(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVVendorExtension*); + +tANI_U32 dot11fPackTlvVendorExtension(tpAniSirGlobal, tDot11fTLVVendorExtension*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvVendorExtension(tpAniSirGlobal, tDot11fTLVVendorExtension*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4170 (0x104a) +typedef struct sDot11fTLVVersion { + tANI_U8 present; + tANI_U8 minor: 4; + tANI_U8 major: 4; +} tDot11fTLVVersion; + +#define DOT11F_TLV_VERSION ( 4170 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_VERSION_MIN_LEN ( 3 ) + +#define DOT11F_TLV_VERSION_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvVersion(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVVersion*); + +tANI_U32 dot11fPackTlvVersion(tpAniSirGlobal, tDot11fTLVVersion*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvVersion(tpAniSirGlobal, tDot11fTLVVersion*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 4164 (0x1044) +typedef struct sDot11fTLVWPSState { + tANI_U8 present; + tANI_U8 state; +} tDot11fTLVWPSState; + +#define DOT11F_TLV_WPSSTATE ( 4164 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_WPSSTATE_MIN_LEN ( 3 ) + +#define DOT11F_TLV_WPSSTATE_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvWPSState(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVWPSState*); + +tANI_U32 dot11fPackTlvWPSState(tpAniSirGlobal, tDot11fTLVWPSState*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvWPSState(tpAniSirGlobal, tDot11fTLVWPSState*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 16 (0x0010) +typedef struct sDot11fTLVP2PInterface { + tANI_U8 present; + tANI_U8 P2PDeviceAddress[6]; +} tDot11fTLVP2PInterface; + +#define DOT11F_TLV_P2PINTERFACE ( 16 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PINTERFACE_MIN_LEN ( 7 ) + +#define DOT11F_TLV_P2PINTERFACE_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PInterface(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PInterface*); + +tANI_U32 dot11fPackTlvP2PInterface(tpAniSirGlobal, tDot11fTLVP2PInterface*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PInterface(tpAniSirGlobal, tDot11fTLVP2PInterface*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// ID 10 (0x000a) +typedef struct sDot11fTLVP2PManageability { + tANI_U8 present; + tANI_U8 manageability; +} tDot11fTLVP2PManageability; + +#define DOT11F_TLV_P2PMANAGEABILITY ( 10 ) + +// N.B. These #defines do *not* include the ID & length +#define DOT11F_TLV_P2PMANAGEABILITY_MIN_LEN ( 2 ) + +#define DOT11F_TLV_P2PMANAGEABILITY_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackTlvP2PManageability(tpAniSirGlobal, tANI_U8*,tANI_U16, tDot11fTLVP2PManageability*); + +tANI_U32 dot11fPackTlvP2PManageability(tpAniSirGlobal, tDot11fTLVP2PManageability*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedTlvP2PManageability(tpAniSirGlobal, tDot11fTLVP2PManageability*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +/********************************************************************* + * Information Elements * + ********************************************************************/ + +// EID 2 (0x02) +typedef struct sDot11fIECondensedCountryStr { + tANI_U8 present; + tANI_U8 countryStr[2]; +} tDot11fIECondensedCountryStr; + +#define DOT11F_EID_CONDENSEDCOUNTRYSTR ( 2 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_CONDENSEDCOUNTRYSTR_MIN_LEN ( 2 ) + +#define DOT11F_IE_CONDENSEDCOUNTRYSTR_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeCondensedCountryStr(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIECondensedCountryStr*); + +tANI_U32 dot11fPackIeCondensedCountryStr(tpAniSirGlobal, tDot11fIECondensedCountryStr*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIECondensedCountryStr(tpAniSirGlobal, tDot11fIECondensedCountryStr*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 2 (0x02) +typedef struct sDot11fIEGTK { + tANI_U8 present; + tANI_U16 keyId: 2; + tANI_U16 reserved: 14; + tANI_U8 keyLength; + tANI_U8 RSC[8]; + tANI_U8 num_key; + tANI_U8 key[32]; +} tDot11fIEGTK; + +#define DOT11F_EID_GTK ( 2 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_GTK_MIN_LEN ( 16 ) + +#define DOT11F_IE_GTK_MAX_LEN ( 43 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeGTK(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEGTK*); + +tANI_U32 dot11fPackIeGTK(tpAniSirGlobal, tDot11fIEGTK*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEGTK(tpAniSirGlobal, tDot11fIEGTK*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 4 (0x04) +typedef struct sDot11fIEIGTK { + tANI_U8 present; + tANI_U8 keyID[2]; + tANI_U8 IPN[6]; + tANI_U8 keyLength; + tANI_U8 key[24]; +} tDot11fIEIGTK; + +#define DOT11F_EID_IGTK ( 4 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_IGTK_MIN_LEN ( 33 ) + +#define DOT11F_IE_IGTK_MAX_LEN ( 33 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeIGTK(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEIGTK*); + +tANI_U32 dot11fPackIeIGTK(tpAniSirGlobal, tDot11fIEIGTK*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEIGTK(tpAniSirGlobal, tDot11fIEIGTK*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 3 (0x03) +typedef struct sDot11fIER0KH_ID { + tANI_U8 present; + tANI_U8 num_PMK_R0_ID; + tANI_U8 PMK_R0_ID[48]; +} tDot11fIER0KH_ID; + +#define DOT11F_EID_R0KH_ID ( 3 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_R0KH_ID_MIN_LEN ( 1 ) + +#define DOT11F_IE_R0KH_ID_MAX_LEN ( 48 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeR0KH_ID(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIER0KH_ID*); + +tANI_U32 dot11fPackIeR0KH_ID(tpAniSirGlobal, tDot11fIER0KH_ID*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIER0KH_ID(tpAniSirGlobal, tDot11fIER0KH_ID*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 1 (0x01) +typedef struct sDot11fIER1KH_ID { + tANI_U8 present; + tANI_U8 PMK_R1_ID[6]; +} tDot11fIER1KH_ID; + +#define DOT11F_EID_R1KH_ID ( 1 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_R1KH_ID_MIN_LEN ( 6 ) + +#define DOT11F_IE_R1KH_ID_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeR1KH_ID(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIER1KH_ID*); + +tANI_U32 dot11fPackIeR1KH_ID(tpAniSirGlobal, tDot11fIER1KH_ID*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIER1KH_ID(tpAniSirGlobal, tDot11fIER1KH_ID*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 1 (0x01) +typedef struct sDot11fIETSFInfo { + tANI_U8 present; + tANI_U16 TsfOffset; + tANI_U16 BeaconIntvl; +} tDot11fIETSFInfo; + +#define DOT11F_EID_TSFINFO ( 1 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TSFINFO_MIN_LEN ( 4 ) + +#define DOT11F_IE_TSFINFO_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTSFInfo(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETSFInfo*); + +tANI_U32 dot11fPackIeTSFInfo(tpAniSirGlobal, tDot11fIETSFInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETSFInfo(tpAniSirGlobal, tDot11fIETSFInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 51 (0x33) +typedef struct sDot11fIEAPChannelReport { + tANI_U8 present; + tANI_U8 regulatoryClass; + tANI_U8 num_channelList; + tANI_U8 channelList[50]; +} tDot11fIEAPChannelReport; + +#define DOT11F_EID_APCHANNELREPORT ( 51 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_APCHANNELREPORT_MIN_LEN ( 1 ) + +#define DOT11F_IE_APCHANNELREPORT_MAX_LEN ( 51 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeAPChannelReport(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEAPChannelReport*); + +tANI_U32 dot11fPackIeAPChannelReport(tpAniSirGlobal, tDot11fIEAPChannelReport*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEAPChannelReport(tpAniSirGlobal, tDot11fIEAPChannelReport*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 2 (0x02) +typedef struct sDot11fIEBcnReportingDetail { + tANI_U8 present; + tANI_U8 reportingDetail; +} tDot11fIEBcnReportingDetail; + +#define DOT11F_EID_BCNREPORTINGDETAIL ( 2 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_BCNREPORTINGDETAIL_MIN_LEN ( 1 ) + +#define DOT11F_IE_BCNREPORTINGDETAIL_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeBcnReportingDetail(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEBcnReportingDetail*); + +tANI_U32 dot11fPackIeBcnReportingDetail(tpAniSirGlobal, tDot11fIEBcnReportingDetail*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEBcnReportingDetail(tpAniSirGlobal, tDot11fIEBcnReportingDetail*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 1 (0x01) +typedef struct sDot11fIEBeaconReportFrmBody { + tANI_U8 present; + tANI_U8 num_reportedFields; + tANI_U8 reportedFields[224]; +} tDot11fIEBeaconReportFrmBody; + +#define DOT11F_EID_BEACONREPORTFRMBODY ( 1 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_BEACONREPORTFRMBODY_MIN_LEN ( 0 ) + +#define DOT11F_IE_BEACONREPORTFRMBODY_MAX_LEN ( 224 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeBeaconReportFrmBody(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEBeaconReportFrmBody*); + +tANI_U32 dot11fPackIeBeaconReportFrmBody(tpAniSirGlobal, tDot11fIEBeaconReportFrmBody*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEBeaconReportFrmBody(tpAniSirGlobal, tDot11fIEBeaconReportFrmBody*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 1 (0x01) +typedef struct sDot11fIEBeaconReporting { + tANI_U8 present; + tANI_U8 reportingCondition; + tANI_U8 threshold; +} tDot11fIEBeaconReporting; + +#define DOT11F_EID_BEACONREPORTING ( 1 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_BEACONREPORTING_MIN_LEN ( 2 ) + +#define DOT11F_IE_BEACONREPORTING_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeBeaconReporting(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEBeaconReporting*); + +tANI_U32 dot11fPackIeBeaconReporting(tpAniSirGlobal, tDot11fIEBeaconReporting*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEBeaconReporting(tpAniSirGlobal, tDot11fIEBeaconReporting*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 66 (0x42) +typedef struct sDot11fIEMeasurementPilot { + tANI_U8 present; + tANI_U8 measurementPilot; + tANI_U8 num_vendorSpecific; + tANI_U8 vendorSpecific[255]; +} tDot11fIEMeasurementPilot; + +#define DOT11F_EID_MEASUREMENTPILOT ( 66 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_MEASUREMENTPILOT_MIN_LEN ( 1 ) + +#define DOT11F_IE_MEASUREMENTPILOT_MAX_LEN ( 256 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeMeasurementPilot(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEMeasurementPilot*); + +tANI_U32 dot11fPackIeMeasurementPilot(tpAniSirGlobal, tDot11fIEMeasurementPilot*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEMeasurementPilot(tpAniSirGlobal, tDot11fIEMeasurementPilot*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 71 (0x47) +typedef struct sDot11fIEMultiBssid { + tANI_U8 present; + tANI_U8 maxBSSIDIndicator; + tANI_U8 num_vendorSpecific; + tANI_U8 vendorSpecific[255]; +} tDot11fIEMultiBssid; + +#define DOT11F_EID_MULTIBSSID ( 71 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_MULTIBSSID_MIN_LEN ( 1 ) + +#define DOT11F_IE_MULTIBSSID_MAX_LEN ( 256 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeMultiBssid(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEMultiBssid*); + +tANI_U32 dot11fPackIeMultiBssid(tpAniSirGlobal, tDot11fIEMultiBssid*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEMultiBssid(tpAniSirGlobal, tDot11fIEMultiBssid*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 57 (0x39) +typedef struct sDot11fIERICData { + tANI_U8 present; + tANI_U8 Identifier; + tANI_U8 resourceDescCount; + tANI_U16 statusCode; +} tDot11fIERICData; + +#define DOT11F_EID_RICDATA ( 57 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RICDATA_MIN_LEN ( 4 ) + +#define DOT11F_IE_RICDATA_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRICData(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERICData*); + +tANI_U32 dot11fPackIeRICData(tpAniSirGlobal, tDot11fIERICData*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERICData(tpAniSirGlobal, tDot11fIERICData*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 75 (0x4b) +typedef struct sDot11fIERICDescriptor { + tANI_U8 present; + tANI_U8 resourceType; + tANI_U8 num_variableData; + tANI_U8 variableData[255]; +} tDot11fIERICDescriptor; + +#define DOT11F_EID_RICDESCRIPTOR ( 75 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RICDESCRIPTOR_MIN_LEN ( 1 ) + +#define DOT11F_IE_RICDESCRIPTOR_MAX_LEN ( 256 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRICDescriptor(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERICDescriptor*); + +tANI_U32 dot11fPackIeRICDescriptor(tpAniSirGlobal, tDot11fIERICDescriptor*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERICDescriptor(tpAniSirGlobal, tDot11fIERICDescriptor*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 70 (0x46) +typedef struct sDot11fIERRMEnabledCap { + tANI_U8 present; + tANI_U8 LinkMeasurement: 1; + tANI_U8 NeighborRpt: 1; + tANI_U8 parallel: 1; + tANI_U8 repeated: 1; + tANI_U8 BeaconPassive: 1; + tANI_U8 BeaconActive: 1; + tANI_U8 BeaconTable: 1; + tANI_U8 BeaconRepCond: 1; + tANI_U8 FrameMeasurement: 1; + tANI_U8 ChannelLoad: 1; + tANI_U8 NoiseHistogram: 1; + tANI_U8 statistics: 1; + tANI_U8 LCIMeasurement: 1; + tANI_U8 LCIAzimuth: 1; + tANI_U8 TCMCapability: 1; + tANI_U8 triggeredTCM: 1; + tANI_U8 APChanReport: 1; + tANI_U8 RRMMIBEnabled: 1; + tANI_U8 operatingChanMax: 3; + tANI_U8 nonOperatinChanMax: 3; + tANI_U8 MeasurementPilot: 3; + tANI_U8 MeasurementPilotEnabled: 1; + tANI_U8 NeighborTSFOffset: 1; + tANI_U8 RCPIMeasurement: 1; + tANI_U8 RSNIMeasurement: 1; + tANI_U8 BssAvgAccessDelay: 1; + tANI_U8 BSSAvailAdmission: 1; + tANI_U8 AntennaInformation: 1; + tANI_U8 fine_time_meas_rpt: 1; + tANI_U8 lci_capability: 1; + tANI_U8 reserved: 4; +} tDot11fIERRMEnabledCap; + +#define DOT11F_EID_RRMENABLEDCAP ( 70 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RRMENABLEDCAP_MIN_LEN ( 5 ) + +#define DOT11F_IE_RRMENABLEDCAP_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRRMEnabledCap(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERRMEnabledCap*); + +tANI_U32 dot11fPackIeRRMEnabledCap(tpAniSirGlobal, tDot11fIERRMEnabledCap*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERRMEnabledCap(tpAniSirGlobal, tDot11fIERRMEnabledCap*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 10 (0x0a) +typedef struct sDot11fIERequestedInfo { + tANI_U8 present; + tANI_U8 num_requested_eids; + tANI_U8 requested_eids[255]; +} tDot11fIERequestedInfo; + +#define DOT11F_EID_REQUESTEDINFO ( 10 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_REQUESTEDINFO_MIN_LEN ( 0 ) + +#define DOT11F_IE_REQUESTEDINFO_MAX_LEN ( 255 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRequestedInfo(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERequestedInfo*); + +tANI_U32 dot11fPackIeRequestedInfo(tpAniSirGlobal, tDot11fIERequestedInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERequestedInfo(tpAniSirGlobal, tDot11fIERequestedInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 0 (0x00) +typedef struct sDot11fIESSID { + tANI_U8 present; + tANI_U8 num_ssid; + tANI_U8 ssid[32]; +} tDot11fIESSID; + +#define DOT11F_EID_SSID ( 0 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_SSID_MIN_LEN ( 0 ) + +#define DOT11F_IE_SSID_MAX_LEN ( 32 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeSSID(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIESSID*); + +tANI_U32 dot11fPackIeSSID(tpAniSirGlobal, tDot11fIESSID*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIESSID(tpAniSirGlobal, tDot11fIESSID*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 15 (0x0f) +typedef struct sDot11fIESchedule { + tANI_U8 present; + tANI_U16 aggregation: 1; + tANI_U16 tsid: 4; + tANI_U16 direction: 2; + tANI_U16 reserved: 9; + tANI_U32 service_start_time; + tANI_U32 service_interval; + tANI_U16 max_service_dur; + tANI_U16 spec_interval; +} tDot11fIESchedule; + +#define DOT11F_EID_SCHEDULE ( 15 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_SCHEDULE_MIN_LEN ( 14 ) + +#define DOT11F_IE_SCHEDULE_MAX_LEN ( 14 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeSchedule(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIESchedule*); + +tANI_U32 dot11fPackIeSchedule(tpAniSirGlobal, tDot11fIESchedule*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIESchedule(tpAniSirGlobal, tDot11fIESchedule*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 14 (0x0e) +typedef struct sDot11fIETCLAS { + tANI_U8 present; + tANI_U8 user_priority; + tANI_U8 classifier_type; + tANI_U8 classifier_mask; + union + { + struct + { + tANI_U8 source[6]; + tANI_U8 dest[6]; + tANI_U16 type; + } EthParams; /* classifier_type = 0 */ + struct + { + tANI_U8 version; + union + { + struct + { + tANI_U8 source[4]; + tANI_U8 dest[4]; + tANI_U16 src_port; + tANI_U16 dest_port; + tANI_U8 DSCP; + tANI_U8 proto; + tANI_U8 reserved; + } IpV4Params; /* version = 4 */ + struct + { + tANI_U8 source[16]; + tANI_U8 dest[16]; + tANI_U16 src_port; + tANI_U16 dest_port; + tANI_U8 flow_label[3]; + } IpV6Params; /* version = 6 */ + } params; + } IpParams; /* classifier_type = 1 */ + struct + { + tANI_U16 tag_type; + } Params8021dq; /* classifier_type = 2 */ + } info; +} tDot11fIETCLAS; + +#define DOT11F_EID_TCLAS ( 14 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TCLAS_MIN_LEN ( 5 ) + +#define DOT11F_IE_TCLAS_MAX_LEN ( 43 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTCLAS(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETCLAS*); + +tANI_U32 dot11fPackIeTCLAS(tpAniSirGlobal, tDot11fIETCLAS*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETCLAS(tpAniSirGlobal, tDot11fIETCLAS*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 44 (0x2c) +typedef struct sDot11fIETCLASSPROC { + tANI_U8 present; + tANI_U8 processing; +} tDot11fIETCLASSPROC; + +#define DOT11F_EID_TCLASSPROC ( 44 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TCLASSPROC_MIN_LEN ( 1 ) + +#define DOT11F_IE_TCLASSPROC_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTCLASSPROC(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETCLASSPROC*); + +tANI_U32 dot11fPackIeTCLASSPROC(tpAniSirGlobal, tDot11fIETCLASSPROC*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETCLASSPROC(tpAniSirGlobal, tDot11fIETCLASSPROC*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 43 (0x2b) +typedef struct sDot11fIETSDelay { + tANI_U8 present; + tANI_U32 delay; +} tDot11fIETSDelay; + +#define DOT11F_EID_TSDELAY ( 43 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TSDELAY_MIN_LEN ( 4 ) + +#define DOT11F_IE_TSDELAY_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTSDelay(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETSDelay*); + +tANI_U32 dot11fPackIeTSDelay(tpAniSirGlobal, tDot11fIETSDelay*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETSDelay(tpAniSirGlobal, tDot11fIETSDelay*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 13 (0x0d) +typedef struct sDot11fIETSPEC { + tANI_U8 present; + tANI_U16 traffic_type: 1; + tANI_U16 tsid: 4; + tANI_U16 direction: 2; + tANI_U16 access_policy: 2; + tANI_U16 aggregation: 1; + tANI_U16 psb: 1; + tANI_U16 user_priority: 3; + tANI_U16 tsinfo_ack_pol: 2; + tANI_U8 schedule: 1; + tANI_U8 unused: 7; + tANI_U16 size: 15; + tANI_U16 fixed: 1; + tANI_U16 max_msdu_size; + tANI_U32 min_service_int; + tANI_U32 max_service_int; + tANI_U32 inactivity_int; + tANI_U32 suspension_int; + tANI_U32 service_start_time; + tANI_U32 min_data_rate; + tANI_U32 mean_data_rate; + tANI_U32 peak_data_rate; + tANI_U32 burst_size; + tANI_U32 delay_bound; + tANI_U32 min_phy_rate; + tANI_U16 surplus_bw_allowance; + tANI_U16 medium_time; +} tDot11fIETSPEC; + +#define DOT11F_EID_TSPEC ( 13 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TSPEC_MIN_LEN ( 55 ) + +#define DOT11F_IE_TSPEC_MAX_LEN ( 55 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTSPEC(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETSPEC*); + +tANI_U32 dot11fPackIeTSPEC(tpAniSirGlobal, tDot11fIETSPEC*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETSPEC(tpAniSirGlobal, tDot11fIETSPEC*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x09} +typedef struct sDot11fIEWMMSchedule { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U16 aggregation: 1; + tANI_U16 tsid: 4; + tANI_U16 direction: 2; + tANI_U16 reserved: 9; + tANI_U32 service_start_time; + tANI_U32 service_interval; + tANI_U16 max_service_dur; + tANI_U16 spec_interval; +} tDot11fIEWMMSchedule; + +#define DOT11F_EID_WMMSCHEDULE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMSCHEDULE_MIN_LEN ( 20 ) + +#define DOT11F_IE_WMMSCHEDULE_MAX_LEN ( 20 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMSchedule(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMSchedule*); + +tANI_U32 dot11fPackIeWMMSchedule(tpAniSirGlobal, tDot11fIEWMMSchedule*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMSchedule(tpAniSirGlobal, tDot11fIEWMMSchedule*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x06} +typedef struct sDot11fIEWMMTCLAS { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U8 user_priority; + tANI_U8 classifier_type; + tANI_U8 classifier_mask; + union + { + struct + { + tANI_U8 source[6]; + tANI_U8 dest[6]; + tANI_U16 type; + } EthParams; /* classifier_type = 0 */ + struct + { + tANI_U8 version; + union + { + struct + { + tANI_U8 source[4]; + tANI_U8 dest[4]; + tANI_U16 src_port; + tANI_U16 dest_port; + tANI_U8 DSCP; + tANI_U8 proto; + tANI_U8 reserved; + } IpV4Params; /* version = 4 */ + struct + { + tANI_U8 source[16]; + tANI_U8 dest[16]; + tANI_U16 src_port; + tANI_U16 dest_port; + tANI_U8 flow_label[3]; + } IpV6Params; /* version = 6 */ + } params; + } IpParams; /* classifier_type = 1 */ + struct + { + tANI_U16 tag_type; + } Params8021dq; /* classifier_type = 2 */ + } info; +} tDot11fIEWMMTCLAS; + +#define DOT11F_EID_WMMTCLAS ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMTCLAS_MIN_LEN ( 11 ) + +#define DOT11F_IE_WMMTCLAS_MAX_LEN ( 49 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMTCLAS(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMTCLAS*); + +tANI_U32 dot11fPackIeWMMTCLAS(tpAniSirGlobal, tDot11fIEWMMTCLAS*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMTCLAS(tpAniSirGlobal, tDot11fIEWMMTCLAS*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x07} +typedef struct sDot11fIEWMMTCLASPROC { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U8 processing; +} tDot11fIEWMMTCLASPROC; + +#define DOT11F_EID_WMMTCLASPROC ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMTCLASPROC_MIN_LEN ( 7 ) + +#define DOT11F_IE_WMMTCLASPROC_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMTCLASPROC(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMTCLASPROC*); + +tANI_U32 dot11fPackIeWMMTCLASPROC(tpAniSirGlobal, tDot11fIEWMMTCLASPROC*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMTCLASPROC(tpAniSirGlobal, tDot11fIEWMMTCLASPROC*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x08} +typedef struct sDot11fIEWMMTSDelay { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U32 delay; +} tDot11fIEWMMTSDelay; + +#define DOT11F_EID_WMMTSDELAY ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMTSDELAY_MIN_LEN ( 10 ) + +#define DOT11F_IE_WMMTSDELAY_MAX_LEN ( 10 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMTSDelay(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMTSDelay*); + +tANI_U32 dot11fPackIeWMMTSDelay(tpAniSirGlobal, tDot11fIEWMMTSDelay*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMTSDelay(tpAniSirGlobal, tDot11fIEWMMTSDelay*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x02} +typedef struct sDot11fIEWMMTSPEC { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U16 traffic_type: 1; + tANI_U16 tsid: 4; + tANI_U16 direction: 2; + tANI_U16 access_policy: 2; + tANI_U16 aggregation: 1; + tANI_U16 psb: 1; + tANI_U16 user_priority: 3; + tANI_U16 tsinfo_ack_pol: 2; + tANI_U8 tsinfo_rsvd: 7; + tANI_U8 burst_size_defn: 1; + tANI_U16 size: 15; + tANI_U16 fixed: 1; + tANI_U16 max_msdu_size; + tANI_U32 min_service_int; + tANI_U32 max_service_int; + tANI_U32 inactivity_int; + tANI_U32 suspension_int; + tANI_U32 service_start_time; + tANI_U32 min_data_rate; + tANI_U32 mean_data_rate; + tANI_U32 peak_data_rate; + tANI_U32 burst_size; + tANI_U32 delay_bound; + tANI_U32 min_phy_rate; + tANI_U16 surplus_bw_allowance; + tANI_U16 medium_time; +} tDot11fIEWMMTSPEC; + +#define DOT11F_EID_WMMTSPEC ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMTSPEC_MIN_LEN ( 61 ) + +#define DOT11F_IE_WMMTSPEC_MAX_LEN ( 61 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMTSPEC(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMTSPEC*); + +tANI_U32 dot11fPackIeWMMTSPEC(tpAniSirGlobal, tDot11fIEWMMTSPEC*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMTSPEC(tpAniSirGlobal, tDot11fIEWMMTSPEC*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 194 (0xc2) +typedef struct sDot11fIEWiderBWChanSwitchAnn { + tANI_U8 present; + tANI_U8 newChanWidth; + tANI_U8 newCenterChanFreq0; + tANI_U8 newCenterChanFreq1; +} tDot11fIEWiderBWChanSwitchAnn; + +#define DOT11F_EID_WIDERBWCHANSWITCHANN ( 194 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WIDERBWCHANSWITCHANN_MIN_LEN ( 3 ) + +#define DOT11F_IE_WIDERBWCHANSWITCHANN_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWiderBWChanSwitchAnn(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWiderBWChanSwitchAnn*); + +tANI_U32 dot11fPackIeWiderBWChanSwitchAnn(tpAniSirGlobal, tDot11fIEWiderBWChanSwitchAnn*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWiderBWChanSwitchAnn(tpAniSirGlobal, tDot11fIEWiderBWChanSwitchAnn*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 197 (0xc5) +typedef struct sDot11fIEAID { + tANI_U8 present; + tANI_U16 assocId; +} tDot11fIEAID; + +#define DOT11F_EID_AID ( 197 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_AID_MIN_LEN ( 2 ) + +#define DOT11F_IE_AID_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeAID(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEAID*); + +tANI_U32 dot11fPackIeAID(tpAniSirGlobal, tDot11fIEAID*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEAID(tpAniSirGlobal, tDot11fIEAID*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 4 (0x04) +typedef struct sDot11fIECFParams { + tANI_U8 present; + tANI_U8 cfp_count; + tANI_U8 cfp_period; + tANI_U16 cfp_maxduration; + tANI_U16 cfp_durremaining; +} tDot11fIECFParams; + +#define DOT11F_EID_CFPARAMS ( 4 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_CFPARAMS_MIN_LEN ( 6 ) + +#define DOT11F_IE_CFPARAMS_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeCFParams(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIECFParams*); + +tANI_U32 dot11fPackIeCFParams(tpAniSirGlobal, tDot11fIECFParams*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIECFParams(tpAniSirGlobal, tDot11fIECFParams*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 16 (0x10) +typedef struct sDot11fIEChallengeText { + tANI_U8 present; + tANI_U8 num_text; + tANI_U8 text[253]; +} tDot11fIEChallengeText; + +#define DOT11F_EID_CHALLENGETEXT ( 16 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_CHALLENGETEXT_MIN_LEN ( 1 ) + +#define DOT11F_IE_CHALLENGETEXT_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeChallengeText(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEChallengeText*); + +tANI_U32 dot11fPackIeChallengeText(tpAniSirGlobal, tDot11fIEChallengeText*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEChallengeText(tpAniSirGlobal, tDot11fIEChallengeText*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 37 (0x25) +typedef struct sDot11fIEChanSwitchAnn { + tANI_U8 present; + tANI_U8 switchMode; + tANI_U8 newChannel; + tANI_U8 switchCount; +} tDot11fIEChanSwitchAnn; + +#define DOT11F_EID_CHANSWITCHANN ( 37 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_CHANSWITCHANN_MIN_LEN ( 3 ) + +#define DOT11F_IE_CHANSWITCHANN_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeChanSwitchAnn(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEChanSwitchAnn*); + +tANI_U32 dot11fPackIeChanSwitchAnn(tpAniSirGlobal, tDot11fIEChanSwitchAnn*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEChanSwitchAnn(tpAniSirGlobal, tDot11fIEChanSwitchAnn*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 196 (0xc4) +typedef struct sDot11fIEChannelSwitchWrapper { + tANI_U8 present; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; +} tDot11fIEChannelSwitchWrapper; + +#define DOT11F_EID_CHANNELSWITCHWRAPPER ( 196 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_CHANNELSWITCHWRAPPER_MIN_LEN ( 0 ) + +#define DOT11F_IE_CHANNELSWITCHWRAPPER_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeChannelSwitchWrapper(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEChannelSwitchWrapper*); + +tANI_U32 dot11fPackIeChannelSwitchWrapper(tpAniSirGlobal, tDot11fIEChannelSwitchWrapper*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEChannelSwitchWrapper(tpAniSirGlobal, tDot11fIEChannelSwitchWrapper*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 7 (0x07) +typedef struct sDot11fIECountry { + tANI_U8 present; + tANI_U8 country[3]; + tANI_U8 num_triplets; + tANI_U8 triplets[84][3]; +} tDot11fIECountry; + +#define DOT11F_EID_COUNTRY ( 7 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_COUNTRY_MIN_LEN ( 3 ) + +#define DOT11F_IE_COUNTRY_MAX_LEN ( 255 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIECountry*); + +tANI_U32 dot11fPackIeCountry(tpAniSirGlobal, tDot11fIECountry*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIECountry(tpAniSirGlobal, tDot11fIECountry*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 3 (0x03) +typedef struct sDot11fIEDSParams { + tANI_U8 present; + tANI_U8 curr_channel; +} tDot11fIEDSParams; + +#define DOT11F_EID_DSPARAMS ( 3 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_DSPARAMS_MIN_LEN ( 1 ) + +#define DOT11F_IE_DSPARAMS_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeDSParams(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEDSParams*); + +tANI_U32 dot11fPackIeDSParams(tpAniSirGlobal, tDot11fIEDSParams*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEDSParams(tpAniSirGlobal, tDot11fIEDSParams*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 12 (0x0c) +typedef struct sDot11fIEEDCAParamSet { + tANI_U8 present; + tANI_U8 qos; + tANI_U8 reserved; + tANI_U8 acbe_aifsn: 4; + tANI_U8 acbe_acm: 1; + tANI_U8 acbe_aci: 2; + tANI_U8 unused1: 1; + tANI_U8 acbe_acwmin: 4; + tANI_U8 acbe_acwmax: 4; + tANI_U16 acbe_txoplimit; + tANI_U8 acbk_aifsn: 4; + tANI_U8 acbk_acm: 1; + tANI_U8 acbk_aci: 2; + tANI_U8 unused2: 1; + tANI_U8 acbk_acwmin: 4; + tANI_U8 acbk_acwmax: 4; + tANI_U16 acbk_txoplimit; + tANI_U8 acvi_aifsn: 4; + tANI_U8 acvi_acm: 1; + tANI_U8 acvi_aci: 2; + tANI_U8 unused3: 1; + tANI_U8 acvi_acwmin: 4; + tANI_U8 acvi_acwmax: 4; + tANI_U16 acvi_txoplimit; + tANI_U8 acvo_aifsn: 4; + tANI_U8 acvo_acm: 1; + tANI_U8 acvo_aci: 2; + tANI_U8 unused4: 1; + tANI_U8 acvo_acwmin: 4; + tANI_U8 acvo_acwmax: 4; + tANI_U16 acvo_txoplimit; +} tDot11fIEEDCAParamSet; + +#define DOT11F_EID_EDCAPARAMSET ( 12 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_EDCAPARAMSET_MIN_LEN ( 18 ) + +#define DOT11F_IE_EDCAPARAMSET_MAX_LEN ( 18 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeEDCAParamSet(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEEDCAParamSet*); + +tANI_U32 dot11fPackIeEDCAParamSet(tpAniSirGlobal, tDot11fIEEDCAParamSet*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEEDCAParamSet(tpAniSirGlobal, tDot11fIEEDCAParamSet*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 42 (0x2a) +typedef struct sDot11fIEERPInfo { + tANI_U8 present; + tANI_U8 non_erp_present: 1; + tANI_U8 use_prot: 1; + tANI_U8 barker_preamble: 1; + tANI_U8 unused: 5; +} tDot11fIEERPInfo; + +#define DOT11F_EID_ERPINFO ( 42 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ERPINFO_MIN_LEN ( 1 ) + +#define DOT11F_IE_ERPINFO_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeERPInfo(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEERPInfo*); + +tANI_U32 dot11fPackIeERPInfo(tpAniSirGlobal, tDot11fIEERPInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEERPInfo(tpAniSirGlobal, tDot11fIEERPInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 156 (0x9c) {OUI 0x00, 0x40, 0x96, 0x00} +typedef struct sDot11fIEESECckmOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[20]; +} tDot11fIEESECckmOpaque; + +#define DOT11F_EID_ESECCKMOPAQUE ( 156 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ESECCKMOPAQUE_MIN_LEN ( 10 ) + +#define DOT11F_IE_ESECCKMOPAQUE_MAX_LEN ( 24 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeESECckmOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEESECckmOpaque*); + +tANI_U32 dot11fPackIeESECckmOpaque(tpAniSirGlobal, tDot11fIEESECckmOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEESECckmOpaque(tpAniSirGlobal, tDot11fIEESECckmOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x01} +typedef struct sDot11fIEESERadMgmtCap { + tANI_U8 present; + tANI_U8 mgmt_state; + tANI_U8 mbssid_mask: 3; + tANI_U8 reserved: 5; +} tDot11fIEESERadMgmtCap; + +#define DOT11F_EID_ESERADMGMTCAP ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ESERADMGMTCAP_MIN_LEN ( 6 ) + +#define DOT11F_IE_ESERADMGMTCAP_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeESERadMgmtCap(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEESERadMgmtCap*); + +tANI_U32 dot11fPackIeESERadMgmtCap(tpAniSirGlobal, tDot11fIEESERadMgmtCap*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEESERadMgmtCap(tpAniSirGlobal, tDot11fIEESERadMgmtCap*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x07} +typedef struct sDot11fIEESETrafStrmMet { + tANI_U8 present; + tANI_U8 tsid; + tANI_U8 state; + tANI_U16 msmt_interval; +} tDot11fIEESETrafStrmMet; + +#define DOT11F_EID_ESETRAFSTRMMET ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ESETRAFSTRMMET_MIN_LEN ( 8 ) + +#define DOT11F_IE_ESETRAFSTRMMET_MAX_LEN ( 8 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeESETrafStrmMet(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEESETrafStrmMet*); + +tANI_U32 dot11fPackIeESETrafStrmMet(tpAniSirGlobal, tDot11fIEESETrafStrmMet*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEESETrafStrmMet(tpAniSirGlobal, tDot11fIEESETrafStrmMet*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x08} +typedef struct sDot11fIEESETrafStrmRateSet { + tANI_U8 present; + tANI_U8 tsid; + tANI_U8 num_tsrates; + tANI_U8 tsrates[8]; +} tDot11fIEESETrafStrmRateSet; + +#define DOT11F_EID_ESETRAFSTRMRATESET ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ESETRAFSTRMRATESET_MIN_LEN ( 5 ) + +#define DOT11F_IE_ESETRAFSTRMRATESET_MAX_LEN ( 13 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeESETrafStrmRateSet(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEESETrafStrmRateSet*); + +tANI_U32 dot11fPackIeESETrafStrmRateSet(tpAniSirGlobal, tDot11fIEESETrafStrmRateSet*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEESETrafStrmRateSet(tpAniSirGlobal, tDot11fIEESETrafStrmRateSet*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 150 (0x96) {OUI 0x00, 0x40, 0x96, 0x00} +typedef struct sDot11fIEESETxmitPower { + tANI_U8 present; + tANI_U8 power_limit; + tANI_U8 reserved; +} tDot11fIEESETxmitPower; + +#define DOT11F_EID_ESETXMITPOWER ( 150 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ESETXMITPOWER_MIN_LEN ( 6 ) + +#define DOT11F_IE_ESETXMITPOWER_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeESETxmitPower(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEESETxmitPower*); + +tANI_U32 dot11fPackIeESETxmitPower(tpAniSirGlobal, tDot11fIEESETxmitPower*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEESETxmitPower(tpAniSirGlobal, tDot11fIEESETxmitPower*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x03} +typedef struct sDot11fIEESEVersion { + tANI_U8 present; + tANI_U8 version; +} tDot11fIEESEVersion; + +#define DOT11F_EID_ESEVERSION ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_ESEVERSION_MIN_LEN ( 5 ) + +#define DOT11F_IE_ESEVERSION_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeESEVersion(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEESEVersion*); + +tANI_U32 dot11fPackIeESEVersion(tpAniSirGlobal, tDot11fIEESEVersion*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEESEVersion(tpAniSirGlobal, tDot11fIEESEVersion*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 127 (0x7f) +typedef struct sDot11fIEExtCap { + tANI_U8 present; + tANI_U8 num_bytes; + tANI_U8 bytes[9]; +} tDot11fIEExtCap; + +#define DOT11F_EID_EXTCAP ( 127 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_EXTCAP_MIN_LEN ( 8 ) + +#define DOT11F_IE_EXTCAP_MAX_LEN ( 9 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeExtCap(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEExtCap*); + +tANI_U32 dot11fPackIeExtCap(tpAniSirGlobal, tDot11fIEExtCap*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEExtCap(tpAniSirGlobal, tDot11fIEExtCap*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 50 (0x32) +typedef struct sDot11fIEExtSuppRates { + tANI_U8 present; + tANI_U8 num_rates; + tANI_U8 rates[12]; +} tDot11fIEExtSuppRates; + +#define DOT11F_EID_EXTSUPPRATES ( 50 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_EXTSUPPRATES_MIN_LEN ( 1 ) + +#define DOT11F_IE_EXTSUPPRATES_MAX_LEN ( 12 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeExtSuppRates(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEExtSuppRates*); + +tANI_U32 dot11fPackIeExtSuppRates(tpAniSirGlobal, tDot11fIEExtSuppRates*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEExtSuppRates(tpAniSirGlobal, tDot11fIEExtSuppRates*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 2 (0x02) +typedef struct sDot11fIEFHParamSet { + tANI_U8 present; + tANI_U16 dwell_time; + tANI_U8 hop_set; + tANI_U8 hop_pattern; + tANI_U8 hop_index; +} tDot11fIEFHParamSet; + +#define DOT11F_EID_FHPARAMSET ( 2 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_FHPARAMSET_MIN_LEN ( 5 ) + +#define DOT11F_IE_FHPARAMSET_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeFHParamSet(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEFHParamSet*); + +tANI_U32 dot11fPackIeFHParamSet(tpAniSirGlobal, tDot11fIEFHParamSet*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEFHParamSet(tpAniSirGlobal, tDot11fIEFHParamSet*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 8 (0x08) +typedef struct sDot11fIEFHParams { + tANI_U8 present; + tANI_U8 radix; + tANI_U8 nchannels; +} tDot11fIEFHParams; + +#define DOT11F_EID_FHPARAMS ( 8 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_FHPARAMS_MIN_LEN ( 2 ) + +#define DOT11F_IE_FHPARAMS_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeFHParams(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEFHParams*); + +tANI_U32 dot11fPackIeFHParams(tpAniSirGlobal, tDot11fIEFHParams*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEFHParams(tpAniSirGlobal, tDot11fIEFHParams*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 9 (0x09) +typedef struct sDot11fIEFHPattTable { + tANI_U8 present; + tANI_U8 flag; + tANI_U8 nsets; + tANI_U8 modulus; + tANI_U8 offset; + tANI_U8 num_randtable; + tANI_U8 randtable[251]; +} tDot11fIEFHPattTable; + +#define DOT11F_EID_FHPATTTABLE ( 9 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_FHPATTTABLE_MIN_LEN ( 4 ) + +#define DOT11F_IE_FHPATTTABLE_MAX_LEN ( 255 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEFHPattTable*); + +tANI_U32 dot11fPackIeFHPattTable(tpAniSirGlobal, tDot11fIEFHPattTable*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEFHPattTable(tpAniSirGlobal, tDot11fIEFHPattTable*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 55 (0x37) +typedef struct sDot11fIEFTInfo { + tANI_U8 present; + tANI_U16 reserved: 8; + tANI_U16 IECount: 8; + tANI_U8 MIC[16]; + tANI_U8 Anonce[32]; + tANI_U8 Snonce[32]; + tDot11fIER1KH_ID R1KH_ID; + tDot11fIEGTK GTK; + tDot11fIER0KH_ID R0KH_ID; + tDot11fIEIGTK IGTK; +} tDot11fIEFTInfo; + +#define DOT11F_EID_FTINFO ( 55 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_FTINFO_MIN_LEN ( 82 ) + +#define DOT11F_IE_FTINFO_MAX_LEN ( 220 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeFTInfo(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEFTInfo*); + +tANI_U32 dot11fPackIeFTInfo(tpAniSirGlobal, tDot11fIEFTInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEFTInfo(tpAniSirGlobal, tDot11fIEFTInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 72 (0x48) +typedef struct sDot11fIEHT2040BSSCoexistence { + tANI_U8 present; + tANI_U8 infoRequest: 1; + tANI_U8 fortyMHzIntolerant: 1; + tANI_U8 twentyMHzBssWidthReq: 1; + tANI_U8 obssScanExemptionReq: 1; + tANI_U8 obssScanExemptionGrant: 1; + tANI_U8 unused: 3; +} tDot11fIEHT2040BSSCoexistence; + +#define DOT11F_EID_HT2040BSSCOEXISTENCE ( 72 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_HT2040BSSCOEXISTENCE_MIN_LEN ( 1 ) + +#define DOT11F_IE_HT2040BSSCOEXISTENCE_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeHT2040BSSCoexistence(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEHT2040BSSCoexistence*); + +tANI_U32 dot11fPackIeHT2040BSSCoexistence(tpAniSirGlobal, tDot11fIEHT2040BSSCoexistence*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEHT2040BSSCoexistence(tpAniSirGlobal, tDot11fIEHT2040BSSCoexistence*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 73 (0x49) +typedef struct sDot11fIEHT2040BSSIntolerantReport { + tANI_U8 present; + tANI_U8 operatingClass; + tANI_U8 num_channelList; + tANI_U8 channelList[50]; +} tDot11fIEHT2040BSSIntolerantReport; + +#define DOT11F_EID_HT2040BSSINTOLERANTREPORT ( 73 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_HT2040BSSINTOLERANTREPORT_MIN_LEN ( 1 ) + +#define DOT11F_IE_HT2040BSSINTOLERANTREPORT_MAX_LEN ( 51 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeHT2040BSSIntolerantReport(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEHT2040BSSIntolerantReport*); + +tANI_U32 dot11fPackIeHT2040BSSIntolerantReport(tpAniSirGlobal, tDot11fIEHT2040BSSIntolerantReport*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEHT2040BSSIntolerantReport(tpAniSirGlobal, tDot11fIEHT2040BSSIntolerantReport*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 45 (0x2d) +typedef struct sDot11fIEHTCaps { + tANI_U8 present; + tANI_U16 advCodingCap: 1; + tANI_U16 supportedChannelWidthSet: 1; + tANI_U16 mimoPowerSave: 2; + tANI_U16 greenField: 1; + tANI_U16 shortGI20MHz: 1; + tANI_U16 shortGI40MHz: 1; + tANI_U16 txSTBC: 1; + tANI_U16 rxSTBC: 2; + tANI_U16 delayedBA: 1; + tANI_U16 maximalAMSDUsize: 1; + tANI_U16 dsssCckMode40MHz: 1; + tANI_U16 psmp: 1; + tANI_U16 stbcControlFrame: 1; + tANI_U16 lsigTXOPProtection: 1; + tANI_U8 maxRxAMPDUFactor: 2; + tANI_U8 mpduDensity: 3; + tANI_U8 reserved1: 3; + tANI_U8 supportedMCSSet[16]; + tANI_U16 pco: 1; + tANI_U16 transitionTime: 2; + tANI_U16 reserved2: 5; + tANI_U16 mcsFeedback: 2; + tANI_U16 reserved3: 6; + tANI_U32 txBF: 1; + tANI_U32 rxStaggeredSounding: 1; + tANI_U32 txStaggeredSounding: 1; + tANI_U32 rxZLF: 1; + tANI_U32 txZLF: 1; + tANI_U32 implicitTxBF: 1; + tANI_U32 calibration: 2; + tANI_U32 explicitCSITxBF: 1; + tANI_U32 explicitUncompressedSteeringMatrix: 1; + tANI_U32 explicitBFCSIFeedback: 3; + tANI_U32 explicitUncompressedSteeringMatrixFeedback: 3; + tANI_U32 explicitCompressedSteeringMatrixFeedback: 3; + tANI_U32 csiNumBFAntennae: 2; + tANI_U32 uncompressedSteeringMatrixBFAntennae: 2; + tANI_U32 compressedSteeringMatrixBFAntennae: 2; + tANI_U32 reserved4: 7; + tANI_U8 antennaSelection: 1; + tANI_U8 explicitCSIFeedbackTx: 1; + tANI_U8 antennaIndicesFeedbackTx: 1; + tANI_U8 explicitCSIFeedback: 1; + tANI_U8 antennaIndicesFeedback: 1; + tANI_U8 rxAS: 1; + tANI_U8 txSoundingPPDUs: 1; + tANI_U8 reserved5: 1; + tANI_U8 num_rsvd; + tANI_U8 rsvd[32]; +} tDot11fIEHTCaps; + +#define DOT11F_EID_HTCAPS ( 45 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_HTCAPS_MIN_LEN ( 26 ) + +#define DOT11F_IE_HTCAPS_MAX_LEN ( 58 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeHTCaps(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEHTCaps*); + +tANI_U32 dot11fPackIeHTCaps(tpAniSirGlobal, tDot11fIEHTCaps*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEHTCaps(tpAniSirGlobal, tDot11fIEHTCaps*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 61 (0x3d) +typedef struct sDot11fIEHTInfo { + tANI_U8 present; + tANI_U8 primaryChannel; + tANI_U8 secondaryChannelOffset: 2; + tANI_U8 recommendedTxWidthSet: 1; + tANI_U8 rifsMode: 1; + tANI_U8 controlledAccessOnly: 1; + tANI_U8 serviceIntervalGranularity: 3; + tANI_U16 opMode: 2; + tANI_U16 nonGFDevicesPresent: 1; + tANI_U16 transmitBurstLimit: 1; + tANI_U16 obssNonHTStaPresent: 1; + tANI_U16 reserved: 11; + tANI_U16 basicSTBCMCS: 7; + tANI_U16 dualCTSProtection: 1; + tANI_U16 secondaryBeacon: 1; + tANI_U16 lsigTXOPProtectionFullSupport: 1; + tANI_U16 pcoActive: 1; + tANI_U16 pcoPhase: 1; + tANI_U16 reserved2: 4; + tANI_U8 basicMCSSet[16]; + tANI_U8 num_rsvd; + tANI_U8 rsvd[32]; +} tDot11fIEHTInfo; + +#define DOT11F_EID_HTINFO ( 61 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_HTINFO_MIN_LEN ( 22 ) + +#define DOT11F_IE_HTINFO_MAX_LEN ( 54 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeHTInfo(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEHTInfo*); + +tANI_U32 dot11fPackIeHTInfo(tpAniSirGlobal, tDot11fIEHTInfo*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEHTInfo(tpAniSirGlobal, tDot11fIEHTInfo*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 6 (0x06) +typedef struct sDot11fIEIBSSParams { + tANI_U8 present; + tANI_U16 atim; +} tDot11fIEIBSSParams; + +#define DOT11F_EID_IBSSPARAMS ( 6 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_IBSSPARAMS_MIN_LEN ( 2 ) + +#define DOT11F_IE_IBSSPARAMS_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeIBSSParams(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEIBSSParams*); + +tANI_U32 dot11fPackIeIBSSParams(tpAniSirGlobal, tDot11fIEIBSSParams*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEIBSSParams(tpAniSirGlobal, tDot11fIEIBSSParams*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 101 (0x65) +typedef struct sDot11fIELinkIdentifier { + tANI_U8 present; + tANI_U8 bssid[6]; + tANI_U8 InitStaAddr[6]; + tANI_U8 RespStaAddr[6]; +} tDot11fIELinkIdentifier; + +#define DOT11F_EID_LINKIDENTIFIER ( 101 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_LINKIDENTIFIER_MIN_LEN ( 18 ) + +#define DOT11F_IE_LINKIDENTIFIER_MAX_LEN ( 18 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeLinkIdentifier(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIELinkIdentifier*); + +tANI_U32 dot11fPackIeLinkIdentifier(tpAniSirGlobal, tDot11fIELinkIdentifier*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIELinkIdentifier(tpAniSirGlobal, tDot11fIELinkIdentifier*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 39 (0x27) +typedef struct sDot11fIEMeasurementReport { + tANI_U8 present; + tANI_U8 token; + tANI_U8 late: 1; + tANI_U8 incapable: 1; + tANI_U8 refused: 1; + tANI_U8 unused: 5; + tANI_U8 type; + union + { + struct + { + tANI_U8 channel; + tDOT11F_U64 meas_start_time; + tANI_U16 meas_duration; + tANI_U8 bss: 1; + tANI_U8 ofdm_preamble: 1; + tANI_U8 unid_signal: 1; + tANI_U8 rader: 1; + tANI_U8 unmeasured: 1; + tANI_U8 unused: 3; + } Basic; /* type = 0 */ + struct + { + tANI_U8 channel; + tDOT11F_U64 meas_start_time; + tANI_U16 meas_duration; + tANI_U8 cca_busy_fraction; + } CCA; /* type = 1 */ + struct + { + tANI_U8 channel; + tDOT11F_U64 meas_start_time; + tANI_U16 meas_duration; + tANI_U8 rpi0_density; + tANI_U8 rpi1_density; + tANI_U8 rpi2_density; + tANI_U8 rpi3_density; + tANI_U8 rpi4_density; + tANI_U8 rpi5_density; + tANI_U8 rpi6_density; + tANI_U8 rpi7_density; + } RPIHistogram; /* type = 2 */ + struct + { + tANI_U8 regClass; + tANI_U8 channel; + tDOT11F_U64 meas_start_time; + tANI_U16 meas_duration; + tANI_U8 condensed_PHY: 7; + tANI_U8 reported_frame_type: 1; + tANI_U8 RCPI; + tANI_U8 RSNI; + tANI_U8 BSSID[6]; + tANI_U8 antenna_id; + tANI_U32 parent_TSF; + tDot11fIEBeaconReportFrmBody BeaconReportFrmBody; + } Beacon; /* type = 5 */ + } report; +} tDot11fIEMeasurementReport; + +#define DOT11F_EID_MEASUREMENTREPORT ( 39 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_MEASUREMENTREPORT_MIN_LEN ( 3 ) + +#define DOT11F_IE_MEASUREMENTREPORT_MAX_LEN ( 29 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeMeasurementReport(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEMeasurementReport*); + +tANI_U32 dot11fPackIeMeasurementReport(tpAniSirGlobal, tDot11fIEMeasurementReport*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEMeasurementReport(tpAniSirGlobal, tDot11fIEMeasurementReport*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 38 (0x26) +typedef struct sDot11fIEMeasurementRequest { + tANI_U8 present; + tANI_U8 measurement_token; + tANI_U8 parallel: 1; + tANI_U8 enable: 1; + tANI_U8 request: 1; + tANI_U8 report: 1; + tANI_U8 durationMandatory: 1; + tANI_U8 unused: 3; + tANI_U8 measurement_type; + union + { + struct + { + tANI_U8 channel_no; + tANI_U8 meas_start_time[8]; + tANI_U16 meas_duration; + } Basic; /* measurement_type = 0 */ + struct + { + tANI_U8 channel_no; + tANI_U8 meas_start_time[8]; + tANI_U16 meas_duration; + } CCA; /* measurement_type = 1 */ + struct + { + tANI_U8 channel_no; + tANI_U8 meas_start_time[8]; + tANI_U16 meas_duration; + } RPIHistogram; /* measurement_type = 2 */ + struct + { + tANI_U8 regClass; + tANI_U8 channel; + tANI_U16 randomization; + tANI_U16 meas_duration; + tANI_U8 meas_mode; + tANI_U8 BSSID[6]; + tDot11fIESSID SSID; + tDot11fIEBeaconReporting BeaconReporting; + tDot11fIEBcnReportingDetail BcnReportingDetail; + tDot11fIERequestedInfo RequestedInfo; + tANI_U16 num_APChannelReport; + tDot11fIEAPChannelReport APChannelReport[2]; + } Beacon; /* measurement_type = 5 */ + } measurement_request; +} tDot11fIEMeasurementRequest; + +#define DOT11F_EID_MEASUREMENTREQUEST ( 38 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_MEASUREMENTREQUEST_MIN_LEN ( 14 ) + +#define DOT11F_IE_MEASUREMENTREQUEST_MAX_LEN ( 16 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeMeasurementRequest(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEMeasurementRequest*); + +tANI_U32 dot11fPackIeMeasurementRequest(tpAniSirGlobal, tDot11fIEMeasurementRequest*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEMeasurementRequest(tpAniSirGlobal, tDot11fIEMeasurementRequest*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 54 (0x36) +typedef struct sDot11fIEMobilityDomain { + tANI_U8 present; + tANI_U16 MDID; + tANI_U8 overDSCap: 1; + tANI_U8 resourceReqCap: 1; + tANI_U8 reserved: 6; +} tDot11fIEMobilityDomain; + +#define DOT11F_EID_MOBILITYDOMAIN ( 54 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_MOBILITYDOMAIN_MIN_LEN ( 3 ) + +#define DOT11F_IE_MOBILITYDOMAIN_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeMobilityDomain(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEMobilityDomain*); + +tANI_U32 dot11fPackIeMobilityDomain(tpAniSirGlobal, tDot11fIEMobilityDomain*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEMobilityDomain(tpAniSirGlobal, tDot11fIEMobilityDomain*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 52 (0x34) +typedef struct sDot11fIENeighborReport { + tANI_U8 present; + tANI_U8 bssid[6]; + tANI_U8 APReachability: 2; + tANI_U8 Security: 1; + tANI_U8 KeyScope: 1; + tANI_U8 SpecMgmtCap: 1; + tANI_U8 QosCap: 1; + tANI_U8 apsd: 1; + tANI_U8 rrm: 1; + tANI_U8 DelayedBA: 1; + tANI_U8 ImmBA: 1; + tANI_U8 MobilityDomain: 1; + tANI_U8 reserved: 5; + tANI_U16 reserved1; + tANI_U8 regulatoryClass; + tANI_U8 channel; + tANI_U8 PhyType; + tDot11fIETSFInfo TSFInfo; + tDot11fIECondensedCountryStr CondensedCountryStr; + tDot11fIEMeasurementPilot MeasurementPilot; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMultiBssid MultiBssid; +} tDot11fIENeighborReport; + +#define DOT11F_EID_NEIGHBORREPORT ( 52 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_NEIGHBORREPORT_MIN_LEN ( 13 ) + +#define DOT11F_IE_NEIGHBORREPORT_MAX_LEN ( 546 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeNeighborReport(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIENeighborReport*); + +tANI_U32 dot11fPackIeNeighborReport(tpAniSirGlobal, tDot11fIENeighborReport*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIENeighborReport(tpAniSirGlobal, tDot11fIENeighborReport*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 74 (0x4a) +typedef struct sDot11fIEOBSSScanParameters { + tANI_U8 present; + tANI_U16 obssScanPassiveDwell; + tANI_U16 obssScanActiveDwell; + tANI_U16 bssChannelWidthTriggerScanInterval; + tANI_U16 obssScanPassiveTotalPerChannel; + tANI_U16 obssScanActiveTotalPerChannel; + tANI_U16 bssWidthChannelTransitionDelayFactor; + tANI_U16 obssScanActivityThreshold; +} tDot11fIEOBSSScanParameters; + +#define DOT11F_EID_OBSSSCANPARAMETERS ( 74 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_OBSSSCANPARAMETERS_MIN_LEN ( 14 ) + +#define DOT11F_IE_OBSSSCANPARAMETERS_MAX_LEN ( 14 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeOBSSScanParameters(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEOBSSScanParameters*); + +tANI_U32 dot11fPackIeOBSSScanParameters(tpAniSirGlobal, tDot11fIEOBSSScanParameters*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEOBSSScanParameters(tpAniSirGlobal, tDot11fIEOBSSScanParameters*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 199 (0xc7) +typedef struct sDot11fIEOperatingMode { + tANI_U8 present; + tANI_U8 chanWidth: 2; + tANI_U8 reserved: 2; + tANI_U8 rxNSS: 3; + tANI_U8 rxNSSType: 1; +} tDot11fIEOperatingMode; + +#define DOT11F_EID_OPERATINGMODE ( 199 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_OPERATINGMODE_MIN_LEN ( 1 ) + +#define DOT11F_IE_OPERATINGMODE_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeOperatingMode(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEOperatingMode*); + +tANI_U32 dot11fPackIeOperatingMode(tpAniSirGlobal, tDot11fIEOperatingMode*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEOperatingMode(tpAniSirGlobal, tDot11fIEOperatingMode*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PAssocReq { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVExtendedListenTiming ExtendedListenTiming; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; +} tDot11fIEP2PAssocReq; + +#define DOT11F_EID_P2PASSOCREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PASSOCREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PASSOCREQ_MAX_LEN ( 71 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PAssocReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PAssocReq*); + +tANI_U32 dot11fPackIeP2PAssocReq(tpAniSirGlobal, tDot11fIEP2PAssocReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PAssocReq(tpAniSirGlobal, tDot11fIEP2PAssocReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PAssocRes { + tANI_U8 present; + tDot11fTLVP2PStatus P2PStatus; + tDot11fTLVExtendedListenTiming ExtendedListenTiming; +} tDot11fIEP2PAssocRes; + +#define DOT11F_EID_P2PASSOCRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PASSOCRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PASSOCRES_MAX_LEN ( 15 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PAssocRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PAssocRes*); + +tANI_U32 dot11fPackIeP2PAssocRes(tpAniSirGlobal, tDot11fIEP2PAssocRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PAssocRes(tpAniSirGlobal, tDot11fIEP2PAssocRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PBeacon { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVP2PDeviceId P2PDeviceId; + tDot11fTLVNoticeOfAbsence NoticeOfAbsence; +} tDot11fIEP2PBeacon; + +#define DOT11F_EID_P2PBEACON ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PBEACON_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PBEACON_MAX_LEN ( 59 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PBeacon(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PBeacon*); + +tANI_U32 dot11fPackIeP2PBeacon(tpAniSirGlobal, tDot11fIEP2PBeacon*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PBeacon(tpAniSirGlobal, tDot11fIEP2PBeacon*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PBeaconProbeRes { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVP2PDeviceId P2PDeviceId; + tDot11fTLVExtendedListenTiming ExtendedListenTiming; + tDot11fTLVNoticeOfAbsence NoticeOfAbsence; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; + tDot11fTLVP2PGroupInfo P2PGroupInfo; +} tDot11fIEP2PBeaconProbeRes; + +#define DOT11F_EID_P2PBEACONPROBERES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PBEACONPROBERES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PBEACONPROBERES_MAX_LEN ( 1148 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PBeaconProbeRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PBeaconProbeRes*); + +tANI_U32 dot11fPackIeP2PBeaconProbeRes(tpAniSirGlobal, tDot11fIEP2PBeaconProbeRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PBeaconProbeRes(tpAniSirGlobal, tDot11fIEP2PBeaconProbeRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PDeAuth { + tANI_U8 present; + tDot11fTLVMinorReasonCode MinorReasonCode; +} tDot11fIEP2PDeAuth; + +#define DOT11F_EID_P2PDEAUTH ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PDEAUTH_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PDEAUTH_MAX_LEN ( 8 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PDeAuth(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PDeAuth*); + +tANI_U32 dot11fPackIeP2PDeAuth(tpAniSirGlobal, tDot11fIEP2PDeAuth*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PDeAuth(tpAniSirGlobal, tDot11fIEP2PDeAuth*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PDeviceDiscoverabilityReq { + tANI_U8 present; + tDot11fTLVP2PDeviceId P2PDeviceId; + tDot11fTLVP2PGroupId P2PGroupId; +} tDot11fIEP2PDeviceDiscoverabilityReq; + +#define DOT11F_EID_P2PDEVICEDISCOVERABILITYREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PDEVICEDISCOVERABILITYREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PDEVICEDISCOVERABILITYREQ_MAX_LEN ( 54 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PDeviceDiscoverabilityReq*); + +tANI_U32 dot11fPackIeP2PDeviceDiscoverabilityReq(tpAniSirGlobal, tDot11fIEP2PDeviceDiscoverabilityReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PDeviceDiscoverabilityReq(tpAniSirGlobal, tDot11fIEP2PDeviceDiscoverabilityReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PDeviceDiscoverabilityRes { + tANI_U8 present; + tDot11fTLVP2PStatus P2PStatus; +} tDot11fIEP2PDeviceDiscoverabilityRes; + +#define DOT11F_EID_P2PDEVICEDISCOVERABILITYRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PDEVICEDISCOVERABILITYRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PDEVICEDISCOVERABILITYRES_MAX_LEN ( 8 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PDeviceDiscoverabilityRes*); + +tANI_U32 dot11fPackIeP2PDeviceDiscoverabilityRes(tpAniSirGlobal, tDot11fIEP2PDeviceDiscoverabilityRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PDeviceDiscoverabilityRes(tpAniSirGlobal, tDot11fIEP2PDeviceDiscoverabilityRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PDisAssoc { + tANI_U8 present; + tDot11fTLVMinorReasonCode MinorReasonCode; +} tDot11fIEP2PDisAssoc; + +#define DOT11F_EID_P2PDISASSOC ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PDISASSOC_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PDISASSOC_MAX_LEN ( 8 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PDisAssoc(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PDisAssoc*); + +tANI_U32 dot11fPackIeP2PDisAssoc(tpAniSirGlobal, tDot11fIEP2PDisAssoc*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PDisAssoc(tpAniSirGlobal, tDot11fIEP2PDisAssoc*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PGONegCnf { + tANI_U8 present; + tDot11fTLVP2PStatus P2PStatus; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVOperatingChannel OperatingChannel; + tDot11fTLVChannelList ChannelList; + tDot11fTLVP2PGroupId P2PGroupId; +} tDot11fIEP2PGONegCnf; + +#define DOT11F_EID_P2PGONEGCNF ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PGONEGCNF_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PGONEGCNF_MAX_LEN ( 319 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PGONegCnf(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PGONegCnf*); + +tANI_U32 dot11fPackIeP2PGONegCnf(tpAniSirGlobal, tDot11fIEP2PGONegCnf*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PGONegCnf(tpAniSirGlobal, tDot11fIEP2PGONegCnf*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PGONegReq { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVGOIntent GOIntent; + tDot11fTLVConfigurationTimeout ConfigurationTimeout; + tDot11fTLVListenChannel ListenChannel; + tDot11fTLVExtendedListenTiming ExtendedListenTiming; + tDot11fTLVIntendedP2PInterfaceAddress IntendedP2PInterfaceAddress; + tDot11fTLVChannelList ChannelList; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; + tDot11fTLVOperatingChannel OperatingChannel; +} tDot11fIEP2PGONegReq; + +#define DOT11F_EID_P2PGONEGREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PGONEGREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PGONEGREQ_MAX_LEN ( 362 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PGONegReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PGONegReq*); + +tANI_U32 dot11fPackIeP2PGONegReq(tpAniSirGlobal, tDot11fIEP2PGONegReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PGONegReq(tpAniSirGlobal, tDot11fIEP2PGONegReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PGONegRes { + tANI_U8 present; + tDot11fTLVP2PStatus P2PStatus; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVGOIntent GOIntent; + tDot11fTLVConfigurationTimeout ConfigurationTimeout; + tDot11fTLVOperatingChannel OperatingChannel; + tDot11fTLVIntendedP2PInterfaceAddress IntendedP2PInterfaceAddress; + tDot11fTLVChannelList ChannelList; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; + tDot11fTLVP2PGroupId P2PGroupId; +} tDot11fIEP2PGONegRes; + +#define DOT11F_EID_P2PGONEGRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PGONEGRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PGONEGRES_MAX_LEN ( 392 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PGONegRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PGONegRes*); + +tANI_U32 dot11fPackIeP2PGONegRes(tpAniSirGlobal, tDot11fIEP2PGONegRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PGONegRes(tpAniSirGlobal, tDot11fIEP2PGONegRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEP2PGONegWPS { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVDevicePasswordID DevicePasswordID; +} tDot11fIEP2PGONegWPS; + +#define DOT11F_EID_P2PGONEGWPS ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PGONEGWPS_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PGONEGWPS_MAX_LEN ( 15 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PGONegWPS(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PGONegWPS*); + +tANI_U32 dot11fPackIeP2PGONegWPS(tpAniSirGlobal, tDot11fIEP2PGONegWPS*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PGONegWPS(tpAniSirGlobal, tDot11fIEP2PGONegWPS*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} +typedef struct sDot11fIEP2PIEOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[249]; +} tDot11fIEP2PIEOpaque; + +#define DOT11F_EID_P2PIEOPAQUE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PIEOPAQUE_MIN_LEN ( 6 ) + +#define DOT11F_IE_P2PIEOPAQUE_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PIEOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PIEOpaque*); + +tANI_U32 dot11fPackIeP2PIEOpaque(tpAniSirGlobal, tDot11fIEP2PIEOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PIEOpaque(tpAniSirGlobal, tDot11fIEP2PIEOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PInvitationReq { + tANI_U8 present; + tDot11fTLVConfigurationTimeout ConfigurationTimeout; + tDot11fTLVInvitationFlags InvitationFlags; + tDot11fTLVOperatingChannel OperatingChannel; + tDot11fTLVP2PGroupBssid P2PGroupBssid; + tDot11fTLVChannelList ChannelList; + tDot11fTLVP2PGroupId P2PGroupId; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; +} tDot11fIEP2PInvitationReq; + +#define DOT11F_EID_P2PINVITATIONREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PINVITATIONREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PINVITATIONREQ_MAX_LEN ( 383 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PInvitationReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PInvitationReq*); + +tANI_U32 dot11fPackIeP2PInvitationReq(tpAniSirGlobal, tDot11fIEP2PInvitationReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PInvitationReq(tpAniSirGlobal, tDot11fIEP2PInvitationReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PInvitationRes { + tANI_U8 present; + tDot11fTLVP2PStatus P2PStatus; + tDot11fTLVConfigurationTimeout ConfigurationTimeout; + tDot11fTLVOperatingChannel OperatingChannel; + tDot11fTLVP2PGroupBssid P2PGroupBssid; + tDot11fTLVChannelList ChannelList; +} tDot11fIEP2PInvitationRes; + +#define DOT11F_EID_P2PINVITATIONRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PINVITATIONRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PINVITATIONRES_MAX_LEN ( 287 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PInvitationRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PInvitationRes*); + +tANI_U32 dot11fPackIeP2PInvitationRes(tpAniSirGlobal, tDot11fIEP2PInvitationRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PInvitationRes(tpAniSirGlobal, tDot11fIEP2PInvitationRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PNoticeOfAbsence { + tANI_U8 present; + tDot11fTLVNoticeOfAbsence NoticeOfAbsence; +} tDot11fIEP2PNoticeOfAbsence; + +#define DOT11F_EID_P2PNOTICEOFABSENCE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PNOTICEOFABSENCE_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PNOTICEOFABSENCE_MAX_LEN ( 45 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PNoticeOfAbsence(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PNoticeOfAbsence*); + +tANI_U32 dot11fPackIeP2PNoticeOfAbsence(tpAniSirGlobal, tDot11fIEP2PNoticeOfAbsence*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PNoticeOfAbsence(tpAniSirGlobal, tDot11fIEP2PNoticeOfAbsence*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PPresenceResponse { + tANI_U8 present; + tDot11fTLVP2PStatus P2PStatus; + tDot11fTLVNoticeOfAbsence NoticeOfAbsence; +} tDot11fIEP2PPresenceResponse; + +#define DOT11F_EID_P2PPRESENCERESPONSE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PPRESENCERESPONSE_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PPRESENCERESPONSE_MAX_LEN ( 49 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PPresenceResponse(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PPresenceResponse*); + +tANI_U32 dot11fPackIeP2PPresenceResponse(tpAniSirGlobal, tDot11fIEP2PPresenceResponse*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PPresenceResponse(tpAniSirGlobal, tDot11fIEP2PPresenceResponse*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PProbeReq { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVP2PDeviceId P2PDeviceId; + tDot11fTLVListenChannel ListenChannel; + tDot11fTLVExtendedListenTiming ExtendedListenTiming; + tDot11fTLVOperatingChannel OperatingChannel; +} tDot11fIEP2PProbeReq; + +#define DOT11F_EID_P2PPROBEREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PPROBEREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PPROBEREQ_MAX_LEN ( 41 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PProbeReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PProbeReq*); + +tANI_U32 dot11fPackIeP2PProbeReq(tpAniSirGlobal, tDot11fIEP2PProbeReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PProbeReq(tpAniSirGlobal, tDot11fIEP2PProbeReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PProbeRes { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVExtendedListenTiming ExtendedListenTiming; + tDot11fTLVNoticeOfAbsence NoticeOfAbsence; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; + tDot11fTLVP2PGroupInfo P2PGroupInfo; +} tDot11fIEP2PProbeRes; + +#define DOT11F_EID_P2PPROBERES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PPROBERES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PPROBERES_MAX_LEN ( 1139 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PProbeRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PProbeRes*); + +tANI_U32 dot11fPackIeP2PProbeRes(tpAniSirGlobal, tDot11fIEP2PProbeRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PProbeRes(tpAniSirGlobal, tDot11fIEP2PProbeRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) +typedef struct sDot11fIEP2PProvisionDiscoveryReq { + tANI_U8 present; + tDot11fTLVP2PCapability P2PCapability; + tDot11fTLVP2PDeviceInfo P2PDeviceInfo; + tDot11fTLVP2PGroupId P2PGroupId; +} tDot11fIEP2PProvisionDiscoveryReq; + +#define DOT11F_EID_P2PPROVISIONDISCOVERYREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PPROVISIONDISCOVERYREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PPROVISIONDISCOVERYREQ_MAX_LEN ( 105 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PProvisionDiscoveryReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PProvisionDiscoveryReq*); + +tANI_U32 dot11fPackIeP2PProvisionDiscoveryReq(tpAniSirGlobal, tDot11fIEP2PProvisionDiscoveryReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PProvisionDiscoveryReq(tpAniSirGlobal, tDot11fIEP2PProvisionDiscoveryReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEP2PWSCProvisionDiscoveryRes { + tANI_U8 present; + tDot11fTLVConfigMethods ConfigMethods; +} tDot11fIEP2PWSCProvisionDiscoveryRes; + +#define DOT11F_EID_P2PWSCPROVISIONDISCOVERYRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_P2PWSCPROVISIONDISCOVERYRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_P2PWSCPROVISIONDISCOVERYRES_MAX_LEN ( 10 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeP2PWSCProvisionDiscoveryRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEP2PWSCProvisionDiscoveryRes*); + +tANI_U32 dot11fPackIeP2PWSCProvisionDiscoveryRes(tpAniSirGlobal, tDot11fIEP2PWSCProvisionDiscoveryRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEP2PWSCProvisionDiscoveryRes(tpAniSirGlobal, tDot11fIEP2PWSCProvisionDiscoveryRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 105 (0x69) +typedef struct sDot11fIEPTIControl { + tANI_U8 present; + tANI_U8 tid; + tANI_U16 sequence_control; +} tDot11fIEPTIControl; + +#define DOT11F_EID_PTICONTROL ( 105 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_PTICONTROL_MIN_LEN ( 3 ) + +#define DOT11F_IE_PTICONTROL_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIePTIControl(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEPTIControl*); + +tANI_U32 dot11fPackIePTIControl(tpAniSirGlobal, tDot11fIEPTIControl*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEPTIControl(tpAniSirGlobal, tDot11fIEPTIControl*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 106 (0x6a) +typedef struct sDot11fIEPUBufferStatus { + tANI_U8 present; + tANI_U8 ac_bk_traffic_aval: 1; + tANI_U8 ac_be_traffic_aval: 1; + tANI_U8 ac_vi_traffic_aval: 1; + tANI_U8 ac_vo_traffic_aval: 1; + tANI_U8 reserved: 4; +} tDot11fIEPUBufferStatus; + +#define DOT11F_EID_PUBUFFERSTATUS ( 106 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_PUBUFFERSTATUS_MIN_LEN ( 1 ) + +#define DOT11F_IE_PUBUFFERSTATUS_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIePUBufferStatus(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEPUBufferStatus*); + +tANI_U32 dot11fPackIePUBufferStatus(tpAniSirGlobal, tDot11fIEPUBufferStatus*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEPUBufferStatus(tpAniSirGlobal, tDot11fIEPUBufferStatus*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 33 (0x21) +typedef struct sDot11fIEPowerCaps { + tANI_U8 present; + tANI_U8 minTxPower; + tANI_U8 maxTxPower; +} tDot11fIEPowerCaps; + +#define DOT11F_EID_POWERCAPS ( 33 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_POWERCAPS_MIN_LEN ( 2 ) + +#define DOT11F_IE_POWERCAPS_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIePowerCaps(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEPowerCaps*); + +tANI_U32 dot11fPackIePowerCaps(tpAniSirGlobal, tDot11fIEPowerCaps*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEPowerCaps(tpAniSirGlobal, tDot11fIEPowerCaps*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 32 (0x20) +typedef struct sDot11fIEPowerConstraints { + tANI_U8 present; + tANI_U8 localPowerConstraints; +} tDot11fIEPowerConstraints; + +#define DOT11F_EID_POWERCONSTRAINTS ( 32 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_POWERCONSTRAINTS_MIN_LEN ( 1 ) + +#define DOT11F_IE_POWERCONSTRAINTS_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIePowerConstraints(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEPowerConstraints*); + +tANI_U32 dot11fPackIePowerConstraints(tpAniSirGlobal, tDot11fIEPowerConstraints*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEPowerConstraints(tpAniSirGlobal, tDot11fIEPowerConstraints*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 11 (0x0b) +typedef struct sDot11fIEQBSSLoad { + tANI_U8 present; + tANI_U16 stacount; + tANI_U8 chautil; + tANI_U16 avail; +} tDot11fIEQBSSLoad; + +#define DOT11F_EID_QBSSLOAD ( 11 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_QBSSLOAD_MIN_LEN ( 5 ) + +#define DOT11F_IE_QBSSLOAD_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeQBSSLoad(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEQBSSLoad*); + +tANI_U32 dot11fPackIeQBSSLoad(tpAniSirGlobal, tDot11fIEQBSSLoad*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEQBSSLoad(tpAniSirGlobal, tDot11fIEQBSSLoad*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0xa0, 0xc6} +typedef struct sDot11fIEQComVendorIE { + tANI_U8 present; + tANI_U8 type; + tANI_U8 channel; +} tDot11fIEQComVendorIE; + +#define DOT11F_EID_QCOMVENDORIE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_QCOMVENDORIE_MIN_LEN ( 5 ) + +#define DOT11F_IE_QCOMVENDORIE_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeQComVendorIE(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEQComVendorIE*); + +tANI_U32 dot11fPackIeQComVendorIE(tpAniSirGlobal, tDot11fIEQComVendorIE*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEQComVendorIE(tpAniSirGlobal, tDot11fIEQComVendorIE*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 46 (0x2e) +typedef struct sDot11fIEQOSCapsAp { + tANI_U8 present; + tANI_U8 count: 4; + tANI_U8 qack: 1; + tANI_U8 qreq: 1; + tANI_U8 txopreq: 1; + tANI_U8 reserved: 1; +} tDot11fIEQOSCapsAp; + +#define DOT11F_EID_QOSCAPSAP ( 46 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_QOSCAPSAP_MIN_LEN ( 1 ) + +#define DOT11F_IE_QOSCAPSAP_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeQOSCapsAp(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEQOSCapsAp*); + +tANI_U32 dot11fPackIeQOSCapsAp(tpAniSirGlobal, tDot11fIEQOSCapsAp*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEQOSCapsAp(tpAniSirGlobal, tDot11fIEQOSCapsAp*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 46 (0x2e) +typedef struct sDot11fIEQOSCapsStation { + tANI_U8 present; + tANI_U8 acvo_uapsd: 1; + tANI_U8 acvi_uapsd: 1; + tANI_U8 acbk_uapsd: 1; + tANI_U8 acbe_uapsd: 1; + tANI_U8 qack: 1; + tANI_U8 max_sp_length: 2; + tANI_U8 more_data_ack: 1; +} tDot11fIEQOSCapsStation; + +#define DOT11F_EID_QOSCAPSSTATION ( 46 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_QOSCAPSSTATION_MIN_LEN ( 1 ) + +#define DOT11F_IE_QOSCAPSSTATION_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeQOSCapsStation(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEQOSCapsStation*); + +tANI_U32 dot11fPackIeQOSCapsStation(tpAniSirGlobal, tDot11fIEQOSCapsStation*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEQOSCapsStation(tpAniSirGlobal, tDot11fIEQOSCapsStation*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 110 (0x6e) +typedef struct sDot11fIEQosMapSet { + tANI_U8 present; + tANI_U8 num_dscp_exceptions; + tANI_U8 dscp_exceptions[60]; +} tDot11fIEQosMapSet; + +#define DOT11F_EID_QOSMAPSET ( 110 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_QOSMAPSET_MIN_LEN ( 0 ) + +#define DOT11F_IE_QOSMAPSET_MAX_LEN ( 60 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeQosMapSet(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEQosMapSet*); + +tANI_U32 dot11fPackIeQosMapSet(tpAniSirGlobal, tDot11fIEQosMapSet*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEQosMapSet(tpAniSirGlobal, tDot11fIEQosMapSet*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 40 (0x28) +typedef struct sDot11fIEQuiet { + tANI_U8 present; + tANI_U8 count; + tANI_U8 period; + tANI_U16 duration; + tANI_U16 offset; +} tDot11fIEQuiet; + +#define DOT11F_EID_QUIET ( 40 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_QUIET_MIN_LEN ( 6 ) + +#define DOT11F_IE_QUIET_MAX_LEN ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeQuiet(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEQuiet*); + +tANI_U32 dot11fPackIeQuiet(tpAniSirGlobal, tDot11fIEQuiet*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEQuiet(tpAniSirGlobal, tDot11fIEQuiet*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 53 (0x35) +typedef struct sDot11fIERCPIIE { + tANI_U8 present; + tANI_U8 rcpi; +} tDot11fIERCPIIE; + +#define DOT11F_EID_RCPIIE ( 53 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RCPIIE_MIN_LEN ( 1 ) + +#define DOT11F_IE_RCPIIE_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRCPIIE(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERCPIIE*); + +tANI_U32 dot11fPackIeRCPIIE(tpAniSirGlobal, tDot11fIERCPIIE*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERCPIIE(tpAniSirGlobal, tDot11fIERCPIIE*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 57 (0x39) +typedef struct sDot11fIERICDataDesc { + tANI_U8 present; + tDot11fIERICData RICData; + tDot11fIERICDescriptor RICDescriptor; + tDot11fIETSPEC TSPEC; + tANI_U16 num_TCLAS; + tDot11fIETCLAS TCLAS[2]; + tDot11fIETCLASSPROC TCLASSPROC; + tDot11fIETSDelay TSDelay; + tDot11fIESchedule Schedule; + tDot11fIEWMMTSPEC WMMTSPEC; + tANI_U16 num_WMMTCLAS; + tDot11fIEWMMTCLAS WMMTCLAS[2]; + tDot11fIEWMMTCLASPROC WMMTCLASPROC; + tDot11fIEWMMTSDelay WMMTSDelay; + tDot11fIEWMMSchedule WMMSchedule; +} tDot11fIERICDataDesc; + +#define DOT11F_EID_RICDATADESC ( 57 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RICDATADESC_MIN_LEN ( 0 ) + +#define DOT11F_IE_RICDATADESC_MAX_LEN ( 548 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRICDataDesc(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERICDataDesc*); + +tANI_U32 dot11fPackIeRICDataDesc(tpAniSirGlobal, tDot11fIERICDataDesc*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERICDataDesc(tpAniSirGlobal, tDot11fIERICDataDesc*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 48 (0x30) +typedef struct sDot11fIERSN { + tANI_U8 present; + tANI_U16 version /* Must be 1! */; + tANI_U8 gp_cipher_suite[4]; + tANI_U16 pwise_cipher_suite_count; + tANI_U8 pwise_cipher_suites[4][4]; + tANI_U16 akm_suite_count; + tANI_U8 akm_suites[4][4]; + tANI_U8 RSN_Cap[2]; + tANI_U16 pmkid_count; + tANI_U8 pmkid[4][16]; + tANI_U8 gp_mgmt_cipher_suite[4]; +} tDot11fIERSN; + +#define DOT11F_EID_RSN ( 48 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RSN_MIN_LEN ( 6 ) + +#define DOT11F_IE_RSN_MAX_LEN ( 114 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRSN(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERSN*); + +tANI_U32 dot11fPackIeRSN(tpAniSirGlobal, tDot11fIERSN*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERSN(tpAniSirGlobal, tDot11fIERSN*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 65 (0x41) +typedef struct sDot11fIERSNIIE { + tANI_U8 present; + tANI_U8 rsni; +} tDot11fIERSNIIE; + +#define DOT11F_EID_RSNIIE ( 65 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RSNIIE_MIN_LEN ( 1 ) + +#define DOT11F_IE_RSNIIE_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRSNIIE(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERSNIIE*); + +tANI_U32 dot11fPackIeRSNIIE(tpAniSirGlobal, tDot11fIERSNIIE*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERSNIIE(tpAniSirGlobal, tDot11fIERSNIIE*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 48 (0x30) +typedef struct sDot11fIERSNOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[253]; +} tDot11fIERSNOpaque; + +#define DOT11F_EID_RSNOPAQUE ( 48 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_RSNOPAQUE_MIN_LEN ( 6 ) + +#define DOT11F_IE_RSNOPAQUE_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeRSNOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIERSNOpaque*); + +tANI_U32 dot11fPackIeRSNOpaque(tpAniSirGlobal, tDot11fIERSNOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIERSNOpaque(tpAniSirGlobal, tDot11fIERSNOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 36 (0x24) +typedef struct sDot11fIESuppChannels { + tANI_U8 present; + tANI_U8 num_bands; + tANI_U8 bands[48][2]; +} tDot11fIESuppChannels; + +#define DOT11F_EID_SUPPCHANNELS ( 36 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_SUPPCHANNELS_MIN_LEN ( 2 ) + +#define DOT11F_IE_SUPPCHANNELS_MAX_LEN ( 96 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIESuppChannels*); + +tANI_U32 dot11fPackIeSuppChannels(tpAniSirGlobal, tDot11fIESuppChannels*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIESuppChannels(tpAniSirGlobal, tDot11fIESuppChannels*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 59 (0x3b) +typedef struct sDot11fIESuppOperatingClasses { + tANI_U8 present; + tANI_U8 num_classes; + tANI_U8 classes[32]; +} tDot11fIESuppOperatingClasses; + +#define DOT11F_EID_SUPPOPERATINGCLASSES ( 59 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_SUPPOPERATINGCLASSES_MIN_LEN ( 1 ) + +#define DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN ( 32 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeSuppOperatingClasses(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIESuppOperatingClasses*); + +tANI_U32 dot11fPackIeSuppOperatingClasses(tpAniSirGlobal, tDot11fIESuppOperatingClasses*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIESuppOperatingClasses(tpAniSirGlobal, tDot11fIESuppOperatingClasses*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 1 (0x01) +typedef struct sDot11fIESuppRates { + tANI_U8 present; + tANI_U8 num_rates; + tANI_U8 rates[12]; +} tDot11fIESuppRates; + +#define DOT11F_EID_SUPPRATES ( 1 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_SUPPRATES_MIN_LEN ( 0 ) + +#define DOT11F_IE_SUPPRATES_MAX_LEN ( 12 ) + +#define DOT11F_IS_BG_RATE(_x) (((_x) == 02) || \ + ((_x) == 04) || \ + ((_x) == 11) || \ + ((_x) == 22) || \ + ((_x) == 12) || \ + ((_x) == 18) || \ + ((_x) == 24) || \ + ((_x) == 36) || \ + ((_x) == 48) || \ + ((_x) == 72) || \ + ((_x) == 96) || \ + ((_x) == 108)) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeSuppRates(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIESuppRates*); + +tANI_U32 dot11fPackIeSuppRates(tpAniSirGlobal, tDot11fIESuppRates*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIESuppRates(tpAniSirGlobal, tDot11fIESuppRates*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 5 (0x05) +typedef struct sDot11fIETIM { + tANI_U8 present; + tANI_U8 dtim_count; + tANI_U8 dtim_period; + tANI_U8 bmpctl; + tANI_U8 num_vbmp; + tANI_U8 vbmp[251]; +} tDot11fIETIM; + +#define DOT11F_EID_TIM ( 5 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TIM_MIN_LEN ( 4 ) + +#define DOT11F_IE_TIM_MAX_LEN ( 254 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTIM(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETIM*); + +tANI_U32 dot11fPackIeTIM(tpAniSirGlobal, tDot11fIETIM*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETIM(tpAniSirGlobal, tDot11fIETIM*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 35 (0x23) +typedef struct sDot11fIETPCReport { + tANI_U8 present; + tANI_U8 tx_power; + tANI_U8 link_margin; +} tDot11fIETPCReport; + +#define DOT11F_EID_TPCREPORT ( 35 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TPCREPORT_MIN_LEN ( 2 ) + +#define DOT11F_IE_TPCREPORT_MAX_LEN ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTPCReport(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETPCReport*); + +tANI_U32 dot11fPackIeTPCReport(tpAniSirGlobal, tDot11fIETPCReport*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETPCReport(tpAniSirGlobal, tDot11fIETPCReport*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 34 (0x22) +typedef struct sDot11fIETPCRequest { + tANI_U8 present; +} tDot11fIETPCRequest; + +#define DOT11F_EID_TPCREQUEST ( 34 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TPCREQUEST_MIN_LEN ( 0 ) + +#define DOT11F_IE_TPCREQUEST_MAX_LEN ( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTPCRequest(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETPCRequest*); + +tANI_U32 dot11fPackIeTPCRequest(tpAniSirGlobal, tDot11fIETPCRequest*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETPCRequest(tpAniSirGlobal, tDot11fIETPCRequest*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 69 (0x45) +typedef struct sDot11fIETimeAdvertisement { + tANI_U8 present; + tANI_U8 timing_capabilities; + tANI_U8 time_value[10]; + tANI_U8 time_error[5]; +} tDot11fIETimeAdvertisement; + +#define DOT11F_EID_TIMEADVERTISEMENT ( 69 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TIMEADVERTISEMENT_MIN_LEN ( 16 ) + +#define DOT11F_IE_TIMEADVERTISEMENT_MAX_LEN ( 16 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTimeAdvertisement(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETimeAdvertisement*); + +tANI_U32 dot11fPackIeTimeAdvertisement(tpAniSirGlobal, tDot11fIETimeAdvertisement*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETimeAdvertisement(tpAniSirGlobal, tDot11fIETimeAdvertisement*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 56 (0x38) +typedef struct sDot11fIETimeoutInterval { + tANI_U8 present; + tANI_U8 timeoutType; + tANI_U32 timeoutValue; +} tDot11fIETimeoutInterval; + +#define DOT11F_EID_TIMEOUTINTERVAL ( 56 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_TIMEOUTINTERVAL_MIN_LEN ( 5 ) + +#define DOT11F_IE_TIMEOUTINTERVAL_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeTimeoutInterval(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIETimeoutInterval*); + +tANI_U32 dot11fPackIeTimeoutInterval(tpAniSirGlobal, tDot11fIETimeoutInterval*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIETimeoutInterval(tpAniSirGlobal, tDot11fIETimeoutInterval*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 191 (0xbf) +typedef struct sDot11fIEVHTCaps { + tANI_U8 present; + tANI_U32 maxMPDULen: 2; + tANI_U32 supportedChannelWidthSet: 2; + tANI_U32 ldpcCodingCap: 1; + tANI_U32 shortGI80MHz: 1; + tANI_U32 shortGI160and80plus80MHz: 1; + tANI_U32 txSTBC: 1; + tANI_U32 rxSTBC: 3; + tANI_U32 suBeamFormerCap: 1; + tANI_U32 suBeamformeeCap: 1; + tANI_U32 csnofBeamformerAntSup: 3; + tANI_U32 numSoundingDim: 3; + tANI_U32 muBeamformerCap: 1; + tANI_U32 muBeamformeeCap: 1; + tANI_U32 vhtTXOPPS: 1; + tANI_U32 htcVHTCap: 1; + tANI_U32 maxAMPDULenExp: 3; + tANI_U32 vhtLinkAdaptCap: 2; + tANI_U32 rxAntPattern: 1; + tANI_U32 txAntPattern: 1; + tANI_U32 reserved1: 2; + tANI_U16 rxMCSMap; + tANI_U16 rxHighSupDataRate: 13; + tANI_U16 reserved2: 3; + tANI_U16 txMCSMap; + tANI_U16 txSupDataRate: 13; + tANI_U16 reserved3: 3; +} tDot11fIEVHTCaps; + +#define DOT11F_EID_VHTCAPS ( 191 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_VHTCAPS_MIN_LEN ( 12 ) + +#define DOT11F_IE_VHTCAPS_MAX_LEN ( 12 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeVHTCaps(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEVHTCaps*); + +tANI_U32 dot11fPackIeVHTCaps(tpAniSirGlobal, tDot11fIEVHTCaps*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEVHTCaps(tpAniSirGlobal, tDot11fIEVHTCaps*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 193 (0xc1) +typedef struct sDot11fIEVHTExtBssLoad { + tANI_U8 present; + tANI_U8 muMIMOCapStaCount; + tANI_U8 ssUnderUtil; + tANI_U8 FortyMHzUtil; + tANI_U8 EightyMHzUtil; + tANI_U8 OneSixtyMHzUtil; +} tDot11fIEVHTExtBssLoad; + +#define DOT11F_EID_VHTEXTBSSLOAD ( 193 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_VHTEXTBSSLOAD_MIN_LEN ( 5 ) + +#define DOT11F_IE_VHTEXTBSSLOAD_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeVHTExtBssLoad(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEVHTExtBssLoad*); + +tANI_U32 dot11fPackIeVHTExtBssLoad(tpAniSirGlobal, tDot11fIEVHTExtBssLoad*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEVHTExtBssLoad(tpAniSirGlobal, tDot11fIEVHTExtBssLoad*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 192 (0xc0) +typedef struct sDot11fIEVHTOperation { + tANI_U8 present; + tANI_U8 chanWidth; + tANI_U8 chanCenterFreqSeg1; + tANI_U8 chanCenterFreqSeg2; + tANI_U16 basicMCSSet; +} tDot11fIEVHTOperation; + +#define DOT11F_EID_VHTOPERATION ( 192 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_VHTOPERATION_MIN_LEN ( 5 ) + +#define DOT11F_IE_VHTOPERATION_MAX_LEN ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeVHTOperation(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEVHTOperation*); + +tANI_U32 dot11fPackIeVHTOperation(tpAniSirGlobal, tDot11fIEVHTOperation*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEVHTOperation(tpAniSirGlobal, tDot11fIEVHTOperation*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x10, 0x18} +typedef struct sDot11fIEVendor1IE { + tANI_U8 present; +} tDot11fIEVendor1IE; + +#define DOT11F_EID_VENDOR1IE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_VENDOR1IE_MIN_LEN ( 3 ) + +#define DOT11F_IE_VENDOR1IE_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeVendor1IE(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEVendor1IE*); + +tANI_U32 dot11fPackIeVendor1IE(tpAniSirGlobal, tDot11fIEVendor1IE*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEVendor1IE(tpAniSirGlobal, tDot11fIEVendor1IE*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x90, 0x4c} +typedef struct sDot11fIEVendor2IE { + tANI_U8 present; +} tDot11fIEVendor2IE; + +#define DOT11F_EID_VENDOR2IE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_VENDOR2IE_MIN_LEN ( 3 ) + +#define DOT11F_IE_VENDOR2IE_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeVendor2IE(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEVendor2IE*); + +tANI_U32 dot11fPackIeVendor2IE(tpAniSirGlobal, tDot11fIEVendor2IE*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEVendor2IE(tpAniSirGlobal, tDot11fIEVendor2IE*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x16, 0x32} +typedef struct sDot11fIEVendor3IE { + tANI_U8 present; +} tDot11fIEVendor3IE; + +#define DOT11F_EID_VENDOR3IE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_VENDOR3IE_MIN_LEN ( 3 ) + +#define DOT11F_IE_VENDOR3IE_MAX_LEN ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeVendor3IE(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEVendor3IE*); + +tANI_U32 dot11fPackIeVendor3IE(tpAniSirGlobal, tDot11fIEVendor3IE*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEVendor3IE(tpAniSirGlobal, tDot11fIEVendor3IE*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 68 (0x44) +typedef struct sDot11fIEWAPI { + tANI_U8 present; + tANI_U16 version /* Must be 1! */; + tANI_U16 akm_suite_count; + tANI_U8 akm_suites[4][4]; + tANI_U16 unicast_cipher_suite_count; + tANI_U8 unicast_cipher_suites[4][4]; + tANI_U8 multicast_cipher_suite[4]; + tANI_U16 preauth: 1; + tANI_U16 reserved: 15; + tANI_U16 bkid_count; + tANI_U8 bkid[4][16]; +} tDot11fIEWAPI; + +#define DOT11F_EID_WAPI ( 68 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WAPI_MIN_LEN ( 12 ) + +#define DOT11F_IE_WAPI_MAX_LEN ( 110 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWAPI(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWAPI*); + +tANI_U32 dot11fPackIeWAPI(tpAniSirGlobal, tDot11fIEWAPI*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWAPI(tpAniSirGlobal, tDot11fIEWAPI*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 68 (0x44) +typedef struct sDot11fIEWAPIOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[253]; +} tDot11fIEWAPIOpaque; + +#define DOT11F_EID_WAPIOPAQUE ( 68 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WAPIOPAQUE_MIN_LEN ( 6 ) + +#define DOT11F_IE_WAPIOPAQUE_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWAPIOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWAPIOpaque*); + +tANI_U32 dot11fPackIeWAPIOpaque(tpAniSirGlobal, tDot11fIEWAPIOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWAPIOpaque(tpAniSirGlobal, tDot11fIEWAPIOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x08, 0x00} +typedef struct sDot11fIEWFATPC { + tANI_U8 present; + tANI_U8 txPower; + tANI_U8 linkMargin; +} tDot11fIEWFATPC; + +#define DOT11F_EID_WFATPC ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WFATPC_MIN_LEN ( 7 ) + +#define DOT11F_IE_WFATPC_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWFATPC(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWFATPC*); + +tANI_U32 dot11fPackIeWFATPC(tpAniSirGlobal, tDot11fIEWFATPC*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWFATPC(tpAniSirGlobal, tDot11fIEWFATPC*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x0a} +typedef struct sDot11fIEWFDIEOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[249]; +} tDot11fIEWFDIEOpaque; + +#define DOT11F_EID_WFDIEOPAQUE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WFDIEOPAQUE_MIN_LEN ( 6 ) + +#define DOT11F_IE_WFDIEOPAQUE_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWFDIEOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWFDIEOpaque*); + +tANI_U32 dot11fPackIeWFDIEOpaque(tpAniSirGlobal, tDot11fIEWFDIEOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWFDIEOpaque(tpAniSirGlobal, tDot11fIEWFDIEOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x05} +typedef struct sDot11fIEWMMCaps { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U8 reserved: 4; + tANI_U8 qack: 1; + tANI_U8 queue_request: 1; + tANI_U8 txop_request: 1; + tANI_U8 more_ack: 1; +} tDot11fIEWMMCaps; + +#define DOT11F_EID_WMMCAPS ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMCAPS_MIN_LEN ( 7 ) + +#define DOT11F_IE_WMMCAPS_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMCaps(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMCaps*); + +tANI_U32 dot11fPackIeWMMCaps(tpAniSirGlobal, tDot11fIEWMMCaps*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMCaps(tpAniSirGlobal, tDot11fIEWMMCaps*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x00} +typedef struct sDot11fIEWMMInfoAp { + tANI_U8 present; + tANI_U8 version; + tANI_U8 param_set_count: 4; + tANI_U8 reserved: 3; + tANI_U8 uapsd: 1; +} tDot11fIEWMMInfoAp; + +#define DOT11F_EID_WMMINFOAP ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMINFOAP_MIN_LEN ( 7 ) + +#define DOT11F_IE_WMMINFOAP_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMInfoAp(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMInfoAp*); + +tANI_U32 dot11fPackIeWMMInfoAp(tpAniSirGlobal, tDot11fIEWMMInfoAp*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMInfoAp(tpAniSirGlobal, tDot11fIEWMMInfoAp*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x00} +typedef struct sDot11fIEWMMInfoStation { + tANI_U8 present; + tANI_U8 version; + tANI_U8 acvo_uapsd: 1; + tANI_U8 acvi_uapsd: 1; + tANI_U8 acbk_uapsd: 1; + tANI_U8 acbe_uapsd: 1; + tANI_U8 reserved1: 1; + tANI_U8 max_sp_length: 2; + tANI_U8 reserved2: 1; +} tDot11fIEWMMInfoStation; + +#define DOT11F_EID_WMMINFOSTATION ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMINFOSTATION_MIN_LEN ( 7 ) + +#define DOT11F_IE_WMMINFOSTATION_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMInfoStation(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMInfoStation*); + +tANI_U32 dot11fPackIeWMMInfoStation(tpAniSirGlobal, tDot11fIEWMMInfoStation*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMInfoStation(tpAniSirGlobal, tDot11fIEWMMInfoStation*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x01} +typedef struct sDot11fIEWMMParams { + tANI_U8 present; + tANI_U8 version /* Must be 1! */; + tANI_U8 qosInfo; + tANI_U8 reserved2; + tANI_U8 acbe_aifsn: 4; + tANI_U8 acbe_acm: 1; + tANI_U8 acbe_aci: 2; + tANI_U8 unused1: 1; + tANI_U8 acbe_acwmin: 4; + tANI_U8 acbe_acwmax: 4; + tANI_U16 acbe_txoplimit; + tANI_U8 acbk_aifsn: 4; + tANI_U8 acbk_acm: 1; + tANI_U8 acbk_aci: 2; + tANI_U8 unused2: 1; + tANI_U8 acbk_acwmin: 4; + tANI_U8 acbk_acwmax: 4; + tANI_U16 acbk_txoplimit; + tANI_U8 acvi_aifsn: 4; + tANI_U8 acvi_acm: 1; + tANI_U8 acvi_aci: 2; + tANI_U8 unused3: 1; + tANI_U8 acvi_acwmin: 4; + tANI_U8 acvi_acwmax: 4; + tANI_U16 acvi_txoplimit; + tANI_U8 acvo_aifsn: 4; + tANI_U8 acvo_acm: 1; + tANI_U8 acvo_aci: 2; + tANI_U8 unused4: 1; + tANI_U8 acvo_acwmin: 4; + tANI_U8 acvo_acwmax: 4; + tANI_U16 acvo_txoplimit; +} tDot11fIEWMMParams; + +#define DOT11F_EID_WMMPARAMS ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WMMPARAMS_MIN_LEN ( 24 ) + +#define DOT11F_IE_WMMPARAMS_MAX_LEN ( 24 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWMMParams(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWMMParams*); + +tANI_U32 dot11fPackIeWMMParams(tpAniSirGlobal, tDot11fIEWMMParams*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWMMParams(tpAniSirGlobal, tDot11fIEWMMParams*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x01} +typedef struct sDot11fIEWPA { + tANI_U8 present; + tANI_U16 version /* Must be 1! */; + tANI_U8 multicast_cipher_present; //field added to fix the bug in dot11fPackIEWPA + tANI_U8 multicast_cipher[4]; + tANI_U16 unicast_cipher_count; + tANI_U8 unicast_ciphers[4][4]; + tANI_U16 auth_suite_count; + tANI_U8 auth_suites[4][4]; + tANI_U16 caps; +} tDot11fIEWPA; + +#define DOT11F_EID_WPA ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WPA_MIN_LEN ( 6 ) + +#define DOT11F_IE_WPA_MAX_LEN ( 48 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWPA(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWPA*); + +tANI_U32 dot11fPackIeWPA(tpAniSirGlobal, tDot11fIEWPA*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWPA(tpAniSirGlobal, tDot11fIEWPA*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x01} +typedef struct sDot11fIEWPAOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[249]; +} tDot11fIEWPAOpaque; + +#define DOT11F_EID_WPAOPAQUE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WPAOPAQUE_MIN_LEN ( 6 ) + +#define DOT11F_IE_WPAOPAQUE_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWPAOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWPAOpaque*); + +tANI_U32 dot11fPackIeWPAOpaque(tpAniSirGlobal, tDot11fIEWPAOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWPAOpaque(tpAniSirGlobal, tDot11fIEWPAOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWSC { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVWPSState WPSState; + tDot11fTLVAPSetupLocked APSetupLocked; + tDot11fTLVSelectedRegistrarConfigMethods SelectedRegistrarConfigMethods; + tDot11fTLVUUID_E UUID_E; + tDot11fTLVUUID_R UUID_R; + tDot11fTLVRFBands RFBands; + tDot11fTLVSelectedRegistrar SelectedRegistrar; + tDot11fTLVConfigMethods ConfigMethods; + tDot11fTLVAssociationState AssociationState; + tDot11fTLVConfigurationError ConfigurationError; + tDot11fTLVManufacturer Manufacturer; + tDot11fTLVModelName ModelName; + tDot11fTLVModelNumber ModelNumber; + tDot11fTLVSerialNumber SerialNumber; + tDot11fTLVDeviceName DeviceName; + tDot11fTLVDevicePasswordID DevicePasswordID; + tDot11fTLVPrimaryDeviceType PrimaryDeviceType; + tDot11fTLVRequestType RequestType; + tDot11fTLVResponseType ResponseType; + tDot11fTLVVendorExtension VendorExtension; + tDot11fTLVRequestDeviceType RequestDeviceType; +} tDot11fIEWSC; + +#define DOT11F_EID_WSC ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSC_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSC_MAX_LEN ( 366 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWSC(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWSC*); + +tANI_U32 dot11fPackIeWSC(tpAniSirGlobal, tDot11fIEWSC*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWSC(tpAniSirGlobal, tDot11fIEWSC*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscAssocReq { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVRequestType RequestType; + tDot11fTLVVendorExtension VendorExtension; +} tDot11fIEWscAssocReq; + +#define DOT11F_EID_WSCASSOCREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCASSOCREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCASSOCREQ_MAX_LEN ( 35 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscAssocReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscAssocReq*); + +tANI_U32 dot11fPackIeWscAssocReq(tpAniSirGlobal, tDot11fIEWscAssocReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscAssocReq(tpAniSirGlobal, tDot11fIEWscAssocReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscAssocRes { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVResponseType ResponseType; + tDot11fTLVVendorExtension VendorExtension; +} tDot11fIEWscAssocRes; + +#define DOT11F_EID_WSCASSOCRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCASSOCRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCASSOCRES_MAX_LEN ( 35 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscAssocRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscAssocRes*); + +tANI_U32 dot11fPackIeWscAssocRes(tpAniSirGlobal, tDot11fIEWscAssocRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscAssocRes(tpAniSirGlobal, tDot11fIEWscAssocRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscBeacon { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVWPSState WPSState; + tDot11fTLVAPSetupLocked APSetupLocked; + tDot11fTLVSelectedRegistrar SelectedRegistrar; + tDot11fTLVDevicePasswordID DevicePasswordID; + tDot11fTLVSelectedRegistrarConfigMethods SelectedRegistrarConfigMethods; + tDot11fTLVUUID_E UUID_E; + tDot11fTLVRFBands RFBands; + tDot11fTLVVendorExtension VendorExtension; +} tDot11fIEWscBeacon; + +#define DOT11F_EID_WSCBEACON ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCBEACON_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCBEACON_MAX_LEN ( 82 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscBeacon(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscBeacon*); + +tANI_U32 dot11fPackIeWscBeacon(tpAniSirGlobal, tDot11fIEWscBeacon*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscBeacon(tpAniSirGlobal, tDot11fIEWscBeacon*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscBeaconProbeRes { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVWPSState WPSState; + tDot11fTLVAPSetupLocked APSetupLocked; + tDot11fTLVSelectedRegistrar SelectedRegistrar; + tDot11fTLVDevicePasswordID DevicePasswordID; + tDot11fTLVSelectedRegistrarConfigMethods SelectedRegistrarConfigMethods; + tDot11fTLVResponseType ResponseType; + tDot11fTLVUUID_E UUID_E; + tDot11fTLVManufacturer Manufacturer; + tDot11fTLVModelName ModelName; + tDot11fTLVModelNumber ModelNumber; + tDot11fTLVSerialNumber SerialNumber; + tDot11fTLVPrimaryDeviceType PrimaryDeviceType; + tDot11fTLVDeviceName DeviceName; + tDot11fTLVConfigMethods ConfigMethods; + tDot11fTLVRFBands RFBands; + tDot11fTLVVendorExtension VendorExtension; +} tDot11fIEWscBeaconProbeRes; + +#define DOT11F_EID_WSCBEACONPROBERES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCBEACONPROBERES_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCBEACONPROBERES_MAX_LEN ( 317 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscBeaconProbeRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscBeaconProbeRes*); + +tANI_U32 dot11fPackIeWscBeaconProbeRes(tpAniSirGlobal, tDot11fIEWscBeaconProbeRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscBeaconProbeRes(tpAniSirGlobal, tDot11fIEWscBeaconProbeRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} +typedef struct sDot11fIEWscIEOpaque { + tANI_U8 present; + tANI_U8 num_data; + tANI_U8 data[249]; +} tDot11fIEWscIEOpaque; + +#define DOT11F_EID_WSCIEOPAQUE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCIEOPAQUE_MIN_LEN ( 6 ) + +#define DOT11F_IE_WSCIEOPAQUE_MAX_LEN ( 253 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscIEOpaque(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscIEOpaque*); + +tANI_U32 dot11fPackIeWscIEOpaque(tpAniSirGlobal, tDot11fIEWscIEOpaque*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscIEOpaque(tpAniSirGlobal, tDot11fIEWscIEOpaque*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscProbeReq { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVRequestType RequestType; + tDot11fTLVConfigMethods ConfigMethods; + tDot11fTLVUUID_E UUID_E; + tDot11fTLVPrimaryDeviceType PrimaryDeviceType; + tDot11fTLVRFBands RFBands; + tDot11fTLVAssociationState AssociationState; + tDot11fTLVConfigurationError ConfigurationError; + tDot11fTLVDevicePasswordID DevicePasswordID; + tDot11fTLVManufacturer Manufacturer; + tDot11fTLVModelName ModelName; + tDot11fTLVModelNumber ModelNumber; + tDot11fTLVDeviceName DeviceName; + tDot11fTLVVendorExtension VendorExtension; + tDot11fTLVRequestDeviceType RequestDeviceType; +} tDot11fIEWscProbeReq; + +#define DOT11F_EID_WSCPROBEREQ ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCPROBEREQ_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCPROBEREQ_MAX_LEN ( 284 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscProbeReq(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscProbeReq*); + +tANI_U32 dot11fPackIeWscProbeReq(tpAniSirGlobal, tDot11fIEWscProbeReq*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscProbeReq(tpAniSirGlobal, tDot11fIEWscProbeReq*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscProbeRes { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVWPSState WPSState; + tDot11fTLVAPSetupLocked APSetupLocked; + tDot11fTLVSelectedRegistrar SelectedRegistrar; + tDot11fTLVDevicePasswordID DevicePasswordID; + tDot11fTLVSelectedRegistrarConfigMethods SelectedRegistrarConfigMethods; + tDot11fTLVResponseType ResponseType; + tDot11fTLVUUID_E UUID_E; + tDot11fTLVManufacturer Manufacturer; + tDot11fTLVModelName ModelName; + tDot11fTLVModelNumber ModelNumber; + tDot11fTLVSerialNumber SerialNumber; + tDot11fTLVPrimaryDeviceType PrimaryDeviceType; + tDot11fTLVDeviceName DeviceName; + tDot11fTLVConfigMethods ConfigMethods; + tDot11fTLVRFBands RFBands; + tDot11fTLVVendorExtension VendorExtension; +} tDot11fIEWscProbeRes; + +#define DOT11F_EID_WSCPROBERES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCPROBERES_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCPROBERES_MAX_LEN ( 317 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscProbeRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscProbeRes*); + +tANI_U32 dot11fPackIeWscProbeRes(tpAniSirGlobal, tDot11fIEWscProbeRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscProbeRes(tpAniSirGlobal, tDot11fIEWscProbeRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) +typedef struct sDot11fIEWscReassocRes { + tANI_U8 present; + tDot11fTLVVersion Version; + tDot11fTLVResponseType ResponseType; + tDot11fTLVVendorExtension VendorExtension; +} tDot11fIEWscReassocRes; + +#define DOT11F_EID_WSCREASSOCRES ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_WSCREASSOCRES_MIN_LEN ( 4 ) + +#define DOT11F_IE_WSCREASSOCRES_MAX_LEN ( 35 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeWscReassocRes(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEWscReassocRes*); + +tANI_U32 dot11fPackIeWscReassocRes(tpAniSirGlobal, tDot11fIEWscReassocRes*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEWscReassocRes(tpAniSirGlobal, tDot11fIEWscReassocRes*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 60 (0x3c) +typedef struct sDot11fIEext_chan_switch_ann { + tANI_U8 present; + tANI_U8 switch_mode; + tANI_U8 new_reg_class; + tANI_U8 new_channel; + tANI_U8 switch_count; +} tDot11fIEext_chan_switch_ann; + +#define DOT11F_EID_EXT_CHAN_SWITCH_ANN ( 60 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_EXT_CHAN_SWITCH_ANN_MIN_LEN ( 4 ) + +#define DOT11F_IE_EXT_CHAN_SWITCH_ANN_MAX_LEN ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeext_chan_switch_ann(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEext_chan_switch_ann*); + +tANI_U32 dot11fPackIeext_chan_switch_ann(tpAniSirGlobal, tDot11fIEext_chan_switch_ann*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEext_chan_switch_ann(tpAniSirGlobal, tDot11fIEext_chan_switch_ann*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 62 (0x3e) +typedef struct sDot11fIEsec_chan_offset_ele { + tANI_U8 present; + tANI_U8 secondaryChannelOffset; +} tDot11fIEsec_chan_offset_ele; + +#define DOT11F_EID_SEC_CHAN_OFFSET_ELE ( 62 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_SEC_CHAN_OFFSET_ELE_MIN_LEN ( 1 ) + +#define DOT11F_IE_SEC_CHAN_OFFSET_ELE_MAX_LEN ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIesec_chan_offset_ele(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEsec_chan_offset_ele*); + +tANI_U32 dot11fPackIesec_chan_offset_ele(tpAniSirGlobal, tDot11fIEsec_chan_offset_ele*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEsec_chan_offset_ele(tpAniSirGlobal, tDot11fIEsec_chan_offset_ele*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +/************************************************************************ + * Frames + **********************************************************************/ + +typedef struct sDot11fAddBAReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfAddBAParameterSet AddBAParameterSet; + tDot11fFfBATimeout BATimeout; + tDot11fFfBAStartingSequenceControl BAStartingSequenceControl; +} tDot11fAddBAReq; + +#define DOT11F_ADDBAREQ ( 1 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAddBAReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddBAReq *pFrm); +tANI_U32 dot11fPackAddBAReq(tpAniSirGlobal pCtx, tDot11fAddBAReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAddBAReqSize(tpAniSirGlobal pCtx, tDot11fAddBAReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAddBARsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfStatus Status; + tDot11fFfAddBAParameterSet AddBAParameterSet; + tDot11fFfBATimeout BATimeout; +} tDot11fAddBARsp; + +#define DOT11F_ADDBARSP ( 2 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAddBARsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddBARsp *pFrm); +tANI_U32 dot11fPackAddBARsp(tpAniSirGlobal pCtx, tDot11fAddBARsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAddBARspSize(tpAniSirGlobal pCtx, tDot11fAddBARsp *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAddTSRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIETSPEC TSPEC; + tANI_U16 num_TCLAS; + tDot11fIETCLAS TCLAS[2]; + tDot11fIETCLASSPROC TCLASSPROC; + tDot11fIEWMMTSPEC WMMTSPEC; + tANI_U16 num_WMMTCLAS; + tDot11fIEWMMTCLAS WMMTCLAS[2]; + tDot11fIEWMMTCLASPROC WMMTCLASPROC; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; +} tDot11fAddTSRequest; + +#define DOT11F_ADDTSREQUEST ( 3 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAddTSRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddTSRequest *pFrm); +tANI_U32 dot11fPackAddTSRequest(tpAniSirGlobal pCtx, tDot11fAddTSRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAddTSRequestSize(tpAniSirGlobal pCtx, tDot11fAddTSRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAddTSResponse{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfStatus Status; + tDot11fIETSDelay TSDelay; + tDot11fIETSPEC TSPEC; + tANI_U16 num_TCLAS; + tDot11fIETCLAS TCLAS[2]; + tDot11fIETCLASSPROC TCLASSPROC; + tDot11fIESchedule Schedule; + tDot11fIEWMMTSDelay WMMTSDelay; + tDot11fIEWMMSchedule WMMSchedule; + tDot11fIEWMMTSPEC WMMTSPEC; + tANI_U16 num_WMMTCLAS; + tDot11fIEWMMTCLAS WMMTCLAS[2]; + tDot11fIEWMMTCLASPROC WMMTCLASPROC; + tDot11fIEESETrafStrmMet ESETrafStrmMet; +} tDot11fAddTSResponse; + +#define DOT11F_ADDTSRESPONSE ( 4 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAddTSResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddTSResponse *pFrm); +tANI_U32 dot11fPackAddTSResponse(tpAniSirGlobal pCtx, tDot11fAddTSResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAddTSResponseSize(tpAniSirGlobal pCtx, tDot11fAddTSResponse *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAssocRequest{ + tDot11fFfCapabilities Capabilities; + tDot11fFfListenInterval ListenInterval; + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIEPowerCaps PowerCaps; + tDot11fIESuppChannels SuppChannels; + tDot11fIERSNOpaque RSNOpaque; + tDot11fIEQOSCapsStation QOSCapsStation; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEWPAOpaque WPAOpaque; + tDot11fIEHTCaps HTCaps; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEWMMInfoStation WMMInfoStation; + tDot11fIEWscIEOpaque WscIEOpaque; + tDot11fIEWAPIOpaque WAPIOpaque; + tDot11fIEWAPI WAPI; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESEVersion ESEVersion; + tDot11fIEP2PIEOpaque P2PIEOpaque; + tDot11fIEWFDIEOpaque WFDIEOpaque; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEExtCap ExtCap; + tDot11fIEOperatingMode OperatingMode; + tDot11fIEQosMapSet QosMapSet; +} tDot11fAssocRequest; + +#define DOT11F_ASSOCREQUEST ( 5 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAssocRequest *pFrm); +tANI_U32 dot11fPackAssocRequest(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAssocRequestSize(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAssocResponse{ + tDot11fFfCapabilities Capabilities; + tDot11fFfStatus Status; + tDot11fFfAID AID; + tDot11fIESuppRates SuppRates; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIERCPIIE RCPIIE; + tDot11fIERSNIIE RSNIIE; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEFTInfo FTInfo; + tANI_U16 num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; + tDot11fIEWPA WPA; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEWMMParams WMMParams; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + tANI_U16 num_WMMTSPEC; + tDot11fIEWMMTSPEC WMMTSPEC[4]; + tDot11fIEWscAssocRes WscAssocRes; + tDot11fIEP2PAssocRes P2PAssocRes; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEExtCap ExtCap; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEQosMapSet QosMapSet; +} tDot11fAssocResponse; + +#define DOT11F_ASSOCRESPONSE ( 6 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAssocResponse *pFrm); +tANI_U32 dot11fPackAssocResponse(tpAniSirGlobal pCtx, tDot11fAssocResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAssocResponseSize(tpAniSirGlobal pCtx, tDot11fAssocResponse *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAuthentication{ + tDot11fFfAuthAlgo AuthAlgo; + tDot11fFfAuthSeqNo AuthSeqNo; + tDot11fFfStatus Status; + tDot11fIEChallengeText ChallengeText; + tDot11fIERSNOpaque RSNOpaque; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEFTInfo FTInfo; + tDot11fIETimeoutInterval TimeoutInterval; + tANI_U16 num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; +} tDot11fAuthentication; + +#define DOT11F_AUTHENTICATION ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackAuthentication(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAuthentication *pFrm); +tANI_U32 dot11fPackAuthentication(tpAniSirGlobal pCtx, tDot11fAuthentication *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedAuthenticationSize(tpAniSirGlobal pCtx, tDot11fAuthentication *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fBeacon{ + tDot11fFfTimeStamp TimeStamp; + tDot11fFfBeaconInterval BeaconInterval; + tDot11fFfCapabilities Capabilities; + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIEFHParamSet FHParamSet; + tDot11fIEDSParams DSParams; + tDot11fIECFParams CFParams; + tDot11fIEIBSSParams IBSSParams; + tDot11fIETIM TIM; + tDot11fIECountry Country; + tDot11fIEFHParams FHParams; + tDot11fIEFHPattTable FHPattTable; + tDot11fIEPowerConstraints PowerConstraints; + tDot11fIEChanSwitchAnn ChanSwitchAnn; + tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIEQuiet Quiet; + tDot11fIETPCReport TPCReport; + tDot11fIEERPInfo ERPInfo; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIERSN RSN; + tDot11fIEQBSSLoad QBSSLoad; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIEQOSCapsAp QOSCapsAp; + tDot11fIEAPChannelReport APChannelReport; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEWPA WPA; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEsec_chan_offset_ele sec_chan_offset_ele; + tDot11fIEWMMInfoAp WMMInfoAp; + tDot11fIEWMMParams WMMParams; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEWAPI WAPI; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + tDot11fIEWscBeacon WscBeacon; + tDot11fIEP2PBeacon P2PBeacon; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEExtCap ExtCap; + tDot11fIEOperatingMode OperatingMode; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEVendor1IE Vendor1IE; + tDot11fIEVendor2IE Vendor2IE; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; + tDot11fIEESEVersion ESEVersion; +} tDot11fBeacon; + +#define DOT11F_BEACON ( 8 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeacon *pFrm); +tANI_U32 dot11fPackBeacon(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedBeaconSize(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fBeacon1{ + tDot11fFfTimeStamp TimeStamp; + tDot11fFfBeaconInterval BeaconInterval; + tDot11fFfCapabilities Capabilities; + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIEDSParams DSParams; + tDot11fIEIBSSParams IBSSParams; +} tDot11fBeacon1; + +#define DOT11F_BEACON1 ( 9 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackBeacon1(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeacon1 *pFrm); +tANI_U32 dot11fPackBeacon1(tpAniSirGlobal pCtx, tDot11fBeacon1 *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedBeacon1Size(tpAniSirGlobal pCtx, tDot11fBeacon1 *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fBeacon2{ + tDot11fIECountry Country; + tDot11fIEPowerConstraints PowerConstraints; + tDot11fIEChanSwitchAnn ChanSwitchAnn; + tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIEQuiet Quiet; + tDot11fIETPCReport TPCReport; + tDot11fIEERPInfo ERPInfo; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIERSNOpaque RSNOpaque; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIEAPChannelReport APChannelReport; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEWPA WPA; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEsec_chan_offset_ele sec_chan_offset_ele; + tDot11fIEWMMInfoAp WMMInfoAp; + tDot11fIEWMMParams WMMParams; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEWscBeacon WscBeacon; + tDot11fIEWAPI WAPI; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + tDot11fIEP2PBeacon P2PBeacon; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEExtCap ExtCap; + tDot11fIEOperatingMode OperatingMode; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEVendor1IE Vendor1IE; + tDot11fIEVendor2IE Vendor2IE; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; + tDot11fIEESEVersion ESEVersion; +} tDot11fBeacon2; + +#define DOT11F_BEACON2 ( 10 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackBeacon2(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeacon2 *pFrm); +tANI_U32 dot11fPackBeacon2(tpAniSirGlobal pCtx, tDot11fBeacon2 *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedBeacon2Size(tpAniSirGlobal pCtx, tDot11fBeacon2 *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fBeaconIEs{ + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIEFHParamSet FHParamSet; + tDot11fIEDSParams DSParams; + tDot11fIECFParams CFParams; + tDot11fIEIBSSParams IBSSParams; + tDot11fIETIM TIM; + tDot11fIECountry Country; + tDot11fIEFHParams FHParams; + tDot11fIEFHPattTable FHPattTable; + tDot11fIEPowerConstraints PowerConstraints; + tDot11fIEChanSwitchAnn ChanSwitchAnn; + tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIEQuiet Quiet; + tDot11fIETPCReport TPCReport; + tDot11fIEERPInfo ERPInfo; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIERSN RSN; + tDot11fIEQBSSLoad QBSSLoad; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIEQOSCapsAp QOSCapsAp; + tDot11fIEAPChannelReport APChannelReport; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEWPA WPA; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEsec_chan_offset_ele sec_chan_offset_ele; + tDot11fIEWMMInfoAp WMMInfoAp; + tDot11fIEWMMParams WMMParams; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEWAPI WAPI; + tDot11fIEESEVersion ESEVersion; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + tDot11fIEWscBeaconProbeRes WscBeaconProbeRes; + tDot11fIEP2PBeaconProbeRes P2PBeaconProbeRes; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEExtCap ExtCap; + tDot11fIEOperatingMode OperatingMode; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEVendor1IE Vendor1IE; + tDot11fIEVendor2IE Vendor2IE; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; +} tDot11fBeaconIEs; + +#define DOT11F_BEACONIES ( 11 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackBeaconIEs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeaconIEs *pFrm); +tANI_U32 dot11fPackBeaconIEs(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedBeaconIEsSize(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fChannelSwitch{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fIEChanSwitchAnn ChanSwitchAnn; + tDot11fIEsec_chan_offset_ele sec_chan_offset_ele; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; +} tDot11fChannelSwitch; + +#define DOT11F_CHANNELSWITCH ( 12 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackChannelSwitch(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fChannelSwitch *pFrm); +tANI_U32 dot11fPackChannelSwitch(tpAniSirGlobal pCtx, tDot11fChannelSwitch *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedChannelSwitchSize(tpAniSirGlobal pCtx, tDot11fChannelSwitch *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDeAuth{ + tDot11fFfReason Reason; + tDot11fIEP2PDeAuth P2PDeAuth; +} tDot11fDeAuth; + +#define DOT11F_DEAUTH ( 13 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackDeAuth(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDeAuth *pFrm); +tANI_U32 dot11fPackDeAuth(tpAniSirGlobal pCtx, tDot11fDeAuth *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedDeAuthSize(tpAniSirGlobal pCtx, tDot11fDeAuth *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDelBAInd{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDelBAParameterSet DelBAParameterSet; + tDot11fFfReason Reason; +} tDot11fDelBAInd; + +#define DOT11F_DELBAIND ( 14 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackDelBAInd(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDelBAInd *pFrm); +tANI_U32 dot11fPackDelBAInd(tpAniSirGlobal pCtx, tDot11fDelBAInd *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedDelBAIndSize(tpAniSirGlobal pCtx, tDot11fDelBAInd *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDelTS{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfTSInfo TSInfo; + tDot11fFfReason Reason; +} tDot11fDelTS; + +#define DOT11F_DELTS ( 15 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackDelTS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDelTS *pFrm); +tANI_U32 dot11fPackDelTS(tpAniSirGlobal pCtx, tDot11fDelTS *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedDelTSSize(tpAniSirGlobal pCtx, tDot11fDelTS *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDeviceDiscoverabilityReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PDeviceDiscoverabilityReq P2PDeviceDiscoverabilityReq; +} tDot11fDeviceDiscoverabilityReq; + +#define DOT11F_DEVICEDISCOVERABILITYREQ ( 16 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDeviceDiscoverabilityReq *pFrm); +tANI_U32 dot11fPackDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedDeviceDiscoverabilityReqSize(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDeviceDiscoverabilityRes{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PDeviceDiscoverabilityRes P2PDeviceDiscoverabilityRes; +} tDot11fDeviceDiscoverabilityRes; + +#define DOT11F_DEVICEDISCOVERABILITYRES ( 17 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDeviceDiscoverabilityRes *pFrm); +tANI_U32 dot11fPackDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedDeviceDiscoverabilityResSize(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityRes *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDisassociation{ + tDot11fFfReason Reason; + tDot11fIEP2PDisAssoc P2PDisAssoc; +} tDot11fDisassociation; + +#define DOT11F_DISASSOCIATION ( 18 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackDisassociation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDisassociation *pFrm); +tANI_U32 dot11fPackDisassociation(tpAniSirGlobal pCtx, tDot11fDisassociation *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedDisassociationSize(tpAniSirGlobal pCtx, tDot11fDisassociation *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fGODiscoverabilityReq{ + tDot11fFfCategory Category; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; +} tDot11fGODiscoverabilityReq; + +#define DOT11F_GODISCOVERABILITYREQ ( 19 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackGODiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGODiscoverabilityReq *pFrm); +tANI_U32 dot11fPackGODiscoverabilityReq(tpAniSirGlobal pCtx, tDot11fGODiscoverabilityReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedGODiscoverabilityReqSize(tpAniSirGlobal pCtx, tDot11fGODiscoverabilityReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fGONegCnf{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PGONegCnf P2PGONegCnf; +} tDot11fGONegCnf; + +#define DOT11F_GONEGCNF ( 20 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackGONegCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGONegCnf *pFrm); +tANI_U32 dot11fPackGONegCnf(tpAniSirGlobal pCtx, tDot11fGONegCnf *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedGONegCnfSize(tpAniSirGlobal pCtx, tDot11fGONegCnf *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fGONegReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PGONegWPS P2PGONegWPS; + tDot11fIEP2PGONegReq P2PGONegReq; +} tDot11fGONegReq; + +#define DOT11F_GONEGREQ ( 21 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackGONegReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGONegReq *pFrm); +tANI_U32 dot11fPackGONegReq(tpAniSirGlobal pCtx, tDot11fGONegReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedGONegReqSize(tpAniSirGlobal pCtx, tDot11fGONegReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fGONegRes{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PGONegWPS P2PGONegWPS; + tDot11fIEP2PGONegRes P2PGONegRes; +} tDot11fGONegRes; + +#define DOT11F_GONEGRES ( 22 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackGONegRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGONegRes *pFrm); +tANI_U32 dot11fPackGONegRes(tpAniSirGlobal pCtx, tDot11fGONegRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedGONegResSize(tpAniSirGlobal pCtx, tDot11fGONegRes *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fHT2040BSSCoexistenceManagementActionFrame{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fIEHT2040BSSCoexistence HT2040BSSCoexistence; + tDot11fIEHT2040BSSIntolerantReport HT2040BSSIntolerantReport; +} tDot11fHT2040BSSCoexistenceManagementActionFrame; + +#define DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME ( 23 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackHT2040BSSCoexistenceManagementActionFrame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm); +tANI_U32 dot11fPackHT2040BSSCoexistenceManagementActionFrame(tpAniSirGlobal pCtx, tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedHT2040BSSCoexistenceManagementActionFrameSize(tpAniSirGlobal pCtx, tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fInvitationReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PInvitationReq P2PInvitationReq; +} tDot11fInvitationReq; + +#define DOT11F_INVITATIONREQ ( 24 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackInvitationReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fInvitationReq *pFrm); +tANI_U32 dot11fPackInvitationReq(tpAniSirGlobal pCtx, tDot11fInvitationReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedInvitationReqSize(tpAniSirGlobal pCtx, tDot11fInvitationReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fInvitationRes{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PInvitationRes P2PInvitationRes; +} tDot11fInvitationRes; + +#define DOT11F_INVITATIONRES ( 25 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackInvitationRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fInvitationRes *pFrm); +tANI_U32 dot11fPackInvitationRes(tpAniSirGlobal pCtx, tDot11fInvitationRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedInvitationResSize(tpAniSirGlobal pCtx, tDot11fInvitationRes *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fLinkMeasurementReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfTPCEleID TPCEleID; + tDot11fFfTPCEleLen TPCEleLen; + tDot11fFfTxPower TxPower; + tDot11fFfLinkMargin LinkMargin; + tDot11fFfRxAntennaId RxAntennaId; + tDot11fFfTxAntennaId TxAntennaId; + tDot11fFfRCPI RCPI; + tDot11fFfRSNI RSNI; +} tDot11fLinkMeasurementReport; + +#define DOT11F_LINKMEASUREMENTREPORT ( 26 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackLinkMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fLinkMeasurementReport *pFrm); +tANI_U32 dot11fPackLinkMeasurementReport(tpAniSirGlobal pCtx, tDot11fLinkMeasurementReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedLinkMeasurementReportSize(tpAniSirGlobal pCtx, tDot11fLinkMeasurementReport *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fLinkMeasurementRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfTxPower TxPower; + tDot11fFfMaxTxPower MaxTxPower; +} tDot11fLinkMeasurementRequest; + +#define DOT11F_LINKMEASUREMENTREQUEST ( 27 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackLinkMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fLinkMeasurementRequest *pFrm); +tANI_U32 dot11fPackLinkMeasurementRequest(tpAniSirGlobal pCtx, tDot11fLinkMeasurementRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedLinkMeasurementRequestSize(tpAniSirGlobal pCtx, tDot11fLinkMeasurementRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fMeasurementReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIEMeasurementReport MeasurementReport; +} tDot11fMeasurementReport; + +#define DOT11F_MEASUREMENTREPORT ( 28 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fMeasurementReport *pFrm); +tANI_U32 dot11fPackMeasurementReport(tpAniSirGlobal pCtx, tDot11fMeasurementReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedMeasurementReportSize(tpAniSirGlobal pCtx, tDot11fMeasurementReport *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fMeasurementRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tANI_U16 num_MeasurementRequest; + tDot11fIEMeasurementRequest MeasurementRequest[4]; +} tDot11fMeasurementRequest; + +#define DOT11F_MEASUREMENTREQUEST ( 29 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fMeasurementRequest *pFrm); +tANI_U32 dot11fPackMeasurementRequest(tpAniSirGlobal pCtx, tDot11fMeasurementRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedMeasurementRequestSize(tpAniSirGlobal pCtx, tDot11fMeasurementRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fNeighborReportRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIESSID SSID; +} tDot11fNeighborReportRequest; + +#define DOT11F_NEIGHBORREPORTREQUEST ( 30 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackNeighborReportRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fNeighborReportRequest *pFrm); +tANI_U32 dot11fPackNeighborReportRequest(tpAniSirGlobal pCtx, tDot11fNeighborReportRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedNeighborReportRequestSize(tpAniSirGlobal pCtx, tDot11fNeighborReportRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fNeighborReportResponse{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tANI_U16 num_NeighborReport; + tDot11fIENeighborReport NeighborReport[15]; +} tDot11fNeighborReportResponse; + +#define DOT11F_NEIGHBORREPORTRESPONSE ( 31 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackNeighborReportResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fNeighborReportResponse *pFrm); +tANI_U32 dot11fPackNeighborReportResponse(tpAniSirGlobal pCtx, tDot11fNeighborReportResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedNeighborReportResponseSize(tpAniSirGlobal pCtx, tDot11fNeighborReportResponse *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fNoticeOfAbs{ + tDot11fFfCategory Category; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PNoticeOfAbsence P2PNoticeOfAbsence; +} tDot11fNoticeOfAbs; + +#define DOT11F_NOTICEOFABS ( 32 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackNoticeOfAbs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fNoticeOfAbs *pFrm); +tANI_U32 dot11fPackNoticeOfAbs(tpAniSirGlobal pCtx, tDot11fNoticeOfAbs *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedNoticeOfAbsSize(tpAniSirGlobal pCtx, tDot11fNoticeOfAbs *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fOperatingMode{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfOperatingMode OperatingMode; +} tDot11fOperatingMode; + +#define DOT11F_OPERATINGMODE ( 33 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fOperatingMode *pFrm); +tANI_U32 dot11fPackOperatingMode(tpAniSirGlobal pCtx, tDot11fOperatingMode *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedOperatingModeSize(tpAniSirGlobal pCtx, tDot11fOperatingMode *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fPresenceReq{ + tDot11fFfCategory Category; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PNoticeOfAbsence P2PNoticeOfAbsence; +} tDot11fPresenceReq; + +#define DOT11F_PRESENCEREQ ( 34 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackPresenceReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fPresenceReq *pFrm); +tANI_U32 dot11fPackPresenceReq(tpAniSirGlobal pCtx, tDot11fPresenceReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedPresenceReqSize(tpAniSirGlobal pCtx, tDot11fPresenceReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fPresenceRes{ + tDot11fFfCategory Category; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PPresenceResponse P2PPresenceResponse; +} tDot11fPresenceRes; + +#define DOT11F_PRESENCERES ( 35 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackPresenceRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fPresenceRes *pFrm); +tANI_U32 dot11fPackPresenceRes(tpAniSirGlobal pCtx, tDot11fPresenceRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedPresenceResSize(tpAniSirGlobal pCtx, tDot11fPresenceRes *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fProbeRequest{ + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIERequestedInfo RequestedInfo; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIEDSParams DSParams; + tDot11fIEHTCaps HTCaps; + tDot11fIEWscProbeReq WscProbeReq; + tDot11fIEWFATPC WFATPC; + tDot11fIEP2PProbeReq P2PProbeReq; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEExtCap ExtCap; +} tDot11fProbeRequest; + +#define DOT11F_PROBEREQUEST ( 36 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackProbeRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProbeRequest *pFrm); +tANI_U32 dot11fPackProbeRequest(tpAniSirGlobal pCtx, tDot11fProbeRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedProbeRequestSize(tpAniSirGlobal pCtx, tDot11fProbeRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fProbeResponse{ + tDot11fFfTimeStamp TimeStamp; + tDot11fFfBeaconInterval BeaconInterval; + tDot11fFfCapabilities Capabilities; + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIEFHParamSet FHParamSet; + tDot11fIEDSParams DSParams; + tDot11fIECFParams CFParams; + tDot11fIEIBSSParams IBSSParams; + tDot11fIECountry Country; + tDot11fIEFHParams FHParams; + tDot11fIEFHPattTable FHPattTable; + tDot11fIEPowerConstraints PowerConstraints; + tDot11fIEChanSwitchAnn ChanSwitchAnn; + tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIEQuiet Quiet; + tDot11fIETPCReport TPCReport; + tDot11fIEERPInfo ERPInfo; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIERSNOpaque RSNOpaque; + tDot11fIEQBSSLoad QBSSLoad; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEAPChannelReport APChannelReport; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEWPA WPA; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEsec_chan_offset_ele sec_chan_offset_ele; + tDot11fIEWMMInfoAp WMMInfoAp; + tDot11fIEWMMParams WMMParams; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEWAPI WAPI; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + tDot11fIEWscProbeRes WscProbeRes; + tDot11fIEP2PProbeRes P2PProbeRes; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEExtCap ExtCap; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEVendor1IE Vendor1IE; + tDot11fIEVendor2IE Vendor2IE; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; + tDot11fIEESEVersion ESEVersion; +} tDot11fProbeResponse; + +#define DOT11F_PROBERESPONSE ( 37 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackProbeResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProbeResponse *pFrm); +tANI_U32 dot11fPackProbeResponse(tpAniSirGlobal pCtx, tDot11fProbeResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedProbeResponseSize(tpAniSirGlobal pCtx, tDot11fProbeResponse *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fProvisionDiscoveryReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PProvisionDiscoveryReq P2PProvisionDiscoveryReq; +} tDot11fProvisionDiscoveryReq; + +#define DOT11F_PROVISIONDISCOVERYREQ ( 38 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackProvisionDiscoveryReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProvisionDiscoveryReq *pFrm); +tANI_U32 dot11fPackProvisionDiscoveryReq(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedProvisionDiscoveryReqSize(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fProvisionDiscoveryRes{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfP2POUI P2POUI; + tDot11fFfP2POUISubType P2POUISubType; + tDot11fFfDialogToken DialogToken; + tDot11fIEP2PWSCProvisionDiscoveryRes P2PWSCProvisionDiscoveryRes; +} tDot11fProvisionDiscoveryRes; + +#define DOT11F_PROVISIONDISCOVERYRES ( 39 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackProvisionDiscoveryRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProvisionDiscoveryRes *pFrm); +tANI_U32 dot11fPackProvisionDiscoveryRes(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedProvisionDiscoveryResSize(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryRes *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fQosMapConfigure{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fIEQosMapSet QosMapSet; +} tDot11fQosMapConfigure; + +#define DOT11F_QOSMAPCONFIGURE ( 40 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackQosMapConfigure(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fQosMapConfigure *pFrm); +tANI_U32 dot11fPackQosMapConfigure(tpAniSirGlobal pCtx, tDot11fQosMapConfigure *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedQosMapConfigureSize(tpAniSirGlobal pCtx, tDot11fQosMapConfigure *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fRadioMeasurementReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tANI_U16 num_MeasurementReport; + tDot11fIEMeasurementReport MeasurementReport[4]; +} tDot11fRadioMeasurementReport; + +#define DOT11F_RADIOMEASUREMENTREPORT ( 41 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackRadioMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fRadioMeasurementReport *pFrm); +tANI_U32 dot11fPackRadioMeasurementReport(tpAniSirGlobal pCtx, tDot11fRadioMeasurementReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedRadioMeasurementReportSize(tpAniSirGlobal pCtx, tDot11fRadioMeasurementReport *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fRadioMeasurementRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfNumOfRepetitions NumOfRepetitions; + tANI_U16 num_MeasurementRequest; + tDot11fIEMeasurementRequest MeasurementRequest[2]; +} tDot11fRadioMeasurementRequest; + +#define DOT11F_RADIOMEASUREMENTREQUEST ( 42 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackRadioMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fRadioMeasurementRequest *pFrm); +tANI_U32 dot11fPackRadioMeasurementRequest(tpAniSirGlobal pCtx, tDot11fRadioMeasurementRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedRadioMeasurementRequestSize(tpAniSirGlobal pCtx, tDot11fRadioMeasurementRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fReAssocRequest{ + tDot11fFfCapabilities Capabilities; + tDot11fFfListenInterval ListenInterval; + tDot11fFfCurrentAPAddress CurrentAPAddress; + tDot11fIESSID SSID; + tDot11fIESuppRates SuppRates; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIEPowerCaps PowerCaps; + tDot11fIESuppChannels SuppChannels; + tDot11fIERSNOpaque RSNOpaque; + tDot11fIEQOSCapsStation QOSCapsStation; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEFTInfo FTInfo; + tANI_U16 num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; + tDot11fIEWPAOpaque WPAOpaque; + tDot11fIEHTCaps HTCaps; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEWMMInfoStation WMMInfoStation; + tDot11fIEWscIEOpaque WscIEOpaque; + tDot11fIEWAPIOpaque WAPIOpaque; + tDot11fIEWAPI WAPI; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESEVersion ESEVersion; + tDot11fIEESECckmOpaque ESECckmOpaque; + tANI_U16 num_WMMTSPEC; + tDot11fIEWMMTSPEC WMMTSPEC[4]; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; + tDot11fIEP2PIEOpaque P2PIEOpaque; + tDot11fIEWFDIEOpaque WFDIEOpaque; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEExtCap ExtCap; + tDot11fIEOperatingMode OperatingMode; + tDot11fIEQosMapSet QosMapSet; +} tDot11fReAssocRequest; + +#define DOT11F_REASSOCREQUEST ( 43 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fReAssocRequest *pFrm); +tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedReAssocRequestSize(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fReAssocResponse{ + tDot11fFfCapabilities Capabilities; + tDot11fFfStatus Status; + tDot11fFfAID AID; + tDot11fIESuppRates SuppRates; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIERCPIIE RCPIIE; + tDot11fIERSNIIE RSNIIE; + tDot11fIERRMEnabledCap RRMEnabledCap; + tDot11fIERSNOpaque RSNOpaque; + tDot11fIEMobilityDomain MobilityDomain; + tDot11fIEFTInfo FTInfo; + tANI_U16 num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; + tDot11fIEWPA WPA; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEWMMParams WMMParams; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + tANI_U16 num_WMMTSPEC; + tDot11fIEWMMTSPEC WMMTSPEC[4]; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; + tDot11fIEWscReassocRes WscReassocRes; + tDot11fIEP2PAssocRes P2PAssocRes; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEExtCap ExtCap; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEQosMapSet QosMapSet; +} tDot11fReAssocResponse; + +#define DOT11F_REASSOCRESPONSE ( 44 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackReAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fReAssocResponse *pFrm); +tANI_U32 dot11fPackReAssocResponse(tpAniSirGlobal pCtx, tDot11fReAssocResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedReAssocResponseSize(tpAniSirGlobal pCtx, tDot11fReAssocResponse *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fSMPowerSave{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfSMPowerModeSet SMPowerModeSet; +} tDot11fSMPowerSave; + +#define DOT11F_SMPOWERSAVE ( 45 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackSMPowerSave(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSMPowerSave *pFrm); +tANI_U32 dot11fPackSMPowerSave(tpAniSirGlobal pCtx, tDot11fSMPowerSave *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedSMPowerSaveSize(tpAniSirGlobal pCtx, tDot11fSMPowerSave *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fSaQueryReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfTransactionId TransactionId; +} tDot11fSaQueryReq; + +#define DOT11F_SAQUERYREQ ( 46 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackSaQueryReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryReq *pFrm); +tANI_U32 dot11fPackSaQueryReq(tpAniSirGlobal pCtx, tDot11fSaQueryReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedSaQueryReqSize(tpAniSirGlobal pCtx, tDot11fSaQueryReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fSaQueryRsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfTransactionId TransactionId; +} tDot11fSaQueryRsp; + +#define DOT11F_SAQUERYRSP ( 47 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackSaQueryRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryRsp *pFrm); +tANI_U32 dot11fPackSaQueryRsp(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedSaQueryRspSize(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSDisReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIELinkIdentifier LinkIdentifier; +} tDot11fTDLSDisReq; + +#define DOT11F_TDLSDISREQ ( 48 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSDisReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSDisReq *pFrm); +tANI_U32 dot11fPackTDLSDisReq(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSDisReqSize(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSDisRsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfCapabilities Capabilities; + tDot11fIESuppRates SuppRates; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIESuppChannels SuppChannels; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIERSN RSN; + tDot11fIEExtCap ExtCap; + tDot11fIEFTInfo FTInfo; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIERICData RICData; + tDot11fIEHTCaps HTCaps; + tDot11fIEHT2040BSSCoexistence HT2040BSSCoexistence; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEVHTCaps VHTCaps; +} tDot11fTDLSDisRsp; + +#define DOT11F_TDLSDISRSP ( 49 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSDisRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSDisRsp *pFrm); +tANI_U32 dot11fPackTDLSDisRsp(tpAniSirGlobal pCtx, tDot11fTDLSDisRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSDisRspSize(tpAniSirGlobal pCtx, tDot11fTDLSDisRsp *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSPeerTrafficInd{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEPTIControl PTIControl; + tDot11fIEPUBufferStatus PUBufferStatus; +} tDot11fTDLSPeerTrafficInd; + +#define DOT11F_TDLSPEERTRAFFICIND ( 50 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSPeerTrafficInd(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSPeerTrafficInd *pFrm); +tANI_U32 dot11fPackTDLSPeerTrafficInd(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficInd *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSPeerTrafficIndSize(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficInd *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSPeerTrafficRsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIELinkIdentifier LinkIdentifier; +} tDot11fTDLSPeerTrafficRsp; + +#define DOT11F_TDLSPEERTRAFFICRSP ( 51 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSPeerTrafficRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSPeerTrafficRsp *pFrm); +tANI_U32 dot11fPackTDLSPeerTrafficRsp(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSPeerTrafficRspSize(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficRsp *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSSetupCnf{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfStatus Status; + tDot11fFfDialogToken DialogToken; + tDot11fIERSN RSN; + tDot11fIEEDCAParamSet EDCAParamSet; + tDot11fIEFTInfo FTInfo; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIEHTInfo HTInfo; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEWMMParams WMMParams; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEOperatingMode OperatingMode; +} tDot11fTDLSSetupCnf; + +#define DOT11F_TDLSSETUPCNF ( 52 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupCnf *pFrm); +tANI_U32 dot11fPackTDLSSetupCnf(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSSetupCnfSize(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSSetupReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfCapabilities Capabilities; + tDot11fIESuppRates SuppRates; + tDot11fIECountry Country; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIESuppChannels SuppChannels; + tDot11fIERSN RSN; + tDot11fIEExtCap ExtCap; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIEQOSCapsStation QOSCapsStation; + tDot11fIEFTInfo FTInfo; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIERICData RICData; + tDot11fIEHTCaps HTCaps; + tDot11fIEHT2040BSSCoexistence HT2040BSSCoexistence; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEWMMInfoStation WMMInfoStation; + tDot11fIEAID AID; + tDot11fIEVHTCaps VHTCaps; +} tDot11fTDLSSetupReq; + +#define DOT11F_TDLSSETUPREQ ( 53 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupReq *pFrm); +tANI_U32 dot11fPackTDLSSetupReq(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSSetupReqSize(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSSetupRsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfStatus Status; + tDot11fFfDialogToken DialogToken; + tDot11fFfCapabilities Capabilities; + tDot11fIESuppRates SuppRates; + tDot11fIECountry Country; + tDot11fIEExtSuppRates ExtSuppRates; + tDot11fIESuppChannels SuppChannels; + tDot11fIERSN RSN; + tDot11fIEExtCap ExtCap; + tDot11fIESuppOperatingClasses SuppOperatingClasses; + tDot11fIEQOSCapsStation QOSCapsStation; + tDot11fIEFTInfo FTInfo; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIERICData RICData; + tDot11fIEHTCaps HTCaps; + tDot11fIEHT2040BSSCoexistence HT2040BSSCoexistence; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEWMMInfoStation WMMInfoStation; + tDot11fIEAID AID; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEOperatingMode OperatingMode; +} tDot11fTDLSSetupRsp; + +#define DOT11F_TDLSSETUPRSP ( 54 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupRsp *pFrm); +tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSSetupRspSize(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSTeardown{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfReason Reason; + tDot11fIEFTInfo FTInfo; + tDot11fIELinkIdentifier LinkIdentifier; +} tDot11fTDLSTeardown; + +#define DOT11F_TDLSTEARDOWN ( 55 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTDLSTeardown(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSTeardown *pFrm); +tANI_U32 dot11fPackTDLSTeardown(tpAniSirGlobal pCtx, tDot11fTDLSTeardown *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTDLSTeardownSize(tpAniSirGlobal pCtx, tDot11fTDLSTeardown *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTPCReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIETPCReport TPCReport; +} tDot11fTPCReport; + +#define DOT11F_TPCREPORT ( 56 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTPCReport *pFrm); +tANI_U32 dot11fPackTPCReport(tpAniSirGlobal pCtx, tDot11fTPCReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTPCReportSize(tpAniSirGlobal pCtx, tDot11fTPCReport *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTPCRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIETPCRequest TPCRequest; +} tDot11fTPCRequest; + +#define DOT11F_TPCREQUEST ( 57 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTPCRequest *pFrm); +tANI_U32 dot11fPackTPCRequest(tpAniSirGlobal pCtx, tDot11fTPCRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTPCRequestSize(tpAniSirGlobal pCtx, tDot11fTPCRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTimingAdvertisementFrame{ + tDot11fFfTimeStamp TimeStamp; + tDot11fFfCapabilities Capabilities; + tDot11fIECountry Country; + tDot11fIEPowerConstraints PowerConstraints; + tDot11fIETimeAdvertisement TimeAdvertisement; + tDot11fIEExtCap ExtCap; + tDot11fIEVendor1IE Vendor1IE; + tDot11fIEVendor2IE Vendor2IE; + tDot11fIEVendor3IE Vendor3IE; +} tDot11fTimingAdvertisementFrame; + +#define DOT11F_TIMINGADVERTISEMENTFRAME ( 58 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackTimingAdvertisementFrame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTimingAdvertisementFrame *pFrm); +tANI_U32 dot11fPackTimingAdvertisementFrame(tpAniSirGlobal pCtx, tDot11fTimingAdvertisementFrame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedTimingAdvertisementFrameSize(tpAniSirGlobal pCtx, tDot11fTimingAdvertisementFrame *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fVHTGidManagementActionFrame{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfVhtMembershipStatusArray VhtMembershipStatusArray; + tDot11fFfVhtUserPositionArray VhtUserPositionArray; +} tDot11fVHTGidManagementActionFrame; + +#define DOT11F_VHTGIDMANAGEMENTACTIONFRAME ( 59 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackVHTGidManagementActionFrame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fVHTGidManagementActionFrame *pFrm); +tANI_U32 dot11fPackVHTGidManagementActionFrame(tpAniSirGlobal pCtx, tDot11fVHTGidManagementActionFrame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedVHTGidManagementActionFrameSize(tpAniSirGlobal pCtx, tDot11fVHTGidManagementActionFrame *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fWMMAddTSRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfStatusCode StatusCode; + tDot11fIEWMMTSPEC WMMTSPEC; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; +} tDot11fWMMAddTSRequest; + +#define DOT11F_WMMADDTSREQUEST ( 60 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackWMMAddTSRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fWMMAddTSRequest *pFrm); +tANI_U32 dot11fPackWMMAddTSRequest(tpAniSirGlobal pCtx, tDot11fWMMAddTSRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedWMMAddTSRequestSize(tpAniSirGlobal pCtx, tDot11fWMMAddTSRequest *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fWMMAddTSResponse{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfStatusCode StatusCode; + tDot11fIEWMMTSPEC WMMTSPEC; + tDot11fIEESETrafStrmMet ESETrafStrmMet; +} tDot11fWMMAddTSResponse; + +#define DOT11F_WMMADDTSRESPONSE ( 61 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackWMMAddTSResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fWMMAddTSResponse *pFrm); +tANI_U32 dot11fPackWMMAddTSResponse(tpAniSirGlobal pCtx, tDot11fWMMAddTSResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedWMMAddTSResponseSize(tpAniSirGlobal pCtx, tDot11fWMMAddTSResponse *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fWMMDelTS{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfStatusCode StatusCode; + tDot11fIEWMMTSPEC WMMTSPEC; +} tDot11fWMMDelTS; + +#define DOT11F_WMMDELTS ( 62 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackWMMDelTS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fWMMDelTS *pFrm); +tANI_U32 dot11fPackWMMDelTS(tpAniSirGlobal pCtx, tDot11fWMMDelTS *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedWMMDelTSSize(tpAniSirGlobal pCtx, tDot11fWMMDelTS *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fext_channel_switch_action_frame{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfext_chan_switch_ann_action ext_chan_switch_ann_action; +} tDot11fext_channel_switch_action_frame; + +#define DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME ( 63 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +tANI_U32 dot11fUnpackext_channel_switch_action_frame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fext_channel_switch_action_frame *pFrm); +tANI_U32 dot11fPackext_channel_switch_action_frame(tpAniSirGlobal pCtx, tDot11fext_channel_switch_action_frame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); +tANI_U32 dot11fGetPackedext_channel_switch_action_frameSize(tpAniSirGlobal pCtx, tDot11fext_channel_switch_action_frame *pFrm, tANI_U32 *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +#endif /* DOT11F_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dphGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dphGlobal.h new file mode 100644 index 000000000000..2d3517605be8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/dphGlobal.h @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + + * Author: Sandesh Goel + + * Date: 02/25/02 + + * History:- + + * Date Modified by Modification Information + + * -------------------------------------------------------------------- + + * + + */ + + +#ifndef __DPH_GLOBAL_H__ + +#define __DPH_GLOBAL_H__ + + +#include "limGlobal.h" + +#include "sirMacProtDef.h" + +#include "sirMacPropExts.h" + +#include "sirApi.h" + + +/// Following determines whether statistics are maintained or not + +#define DPH_STATS + +/// STAID for Management frames + +#define DPH_USE_MGMT_STAID -1 + + +// Keep Alive frames + +#define DPH_NON_KEEPALIVE_FRAME 0 + +#define DPH_KEEPALIVE_FRAME 1 + +//DPH Hash Index for BSS(STA's Peer) on station. + +#define DPH_STA_HASH_INDEX_PEER 1 + + +#ifdef WLAN_FEATURE_11W +//DPH PMF SA Query state for station + +#define DPH_SA_QUERY_NOT_IN_PROGRESS 1 + +#define DPH_SA_QUERY_IN_PROGRESS 2 + +#define DPH_SA_QUERY_TIMED_OUT 3 +#endif + + +typedef struct sDphRateBasedCtr + +{ + + tANI_U32 hi; + + tANI_U32 lo; + +} tDphRateBasedCtr; + + +typedef struct sDphPhyRates + +{ + + tANI_U8 dataRateX2; + + tANI_U8 ackRateX2; + + tANI_U8 rtsRateX2; + +} tDphPhyRates; + + +typedef struct sDphIFSValues + +{ + + tANI_U8 sifs; + + tANI_U8 pifs; + + tANI_U8 difs; + + tANI_U8 preamble; + +} tDphIFSValues; + + +typedef struct sDphQosParams + +{ + + tANI_U8 addtsPresent; + + tSirAddtsReqInfo addts; + + tSirMacQosCapabilityStaIE capability; + +} tDphQosParams; + + +/// Queue attribute structure + +typedef struct sDphQueueAttr + +{ + + tANI_U16 valid : 1; + + tANI_U16 seqNum : 12; + + tANI_U16 ackPolicy : 2; + + tANI_U16 rsvd : 1; + +} tDphQueueAttr, *tpDphQueueAttr; + + + +typedef struct sCfgTrafficClass { + + //Use Block ACK on this STA/TID + + // Fields used to store the default TC parameters for this TSPEC. + + // They will be used when the TSPEC is deleted. + + tANI_U8 fDisableTx:1; + + tANI_U8 fDisableRx:1; + + tANI_U8 fUseBATx:1; + + tANI_U8 fUseBARx:1; + + + // 1: expect to see frames with compressed BA coming from this peer MAC + + tANI_U8 fRxCompBA:1; + + tANI_U8 fTxCompBA:1; + + + // immediate ACK or delayed ACK for frames from this peer MAC + + tANI_U8 fRxBApolicy:1; + + + // immediate ACK or delayed ACK for frames to this peer MAC + + tANI_U8 fTxBApolicy:1; + + + //Initiator or recipient + + tANI_U8 role; + + + //Max # of MSDU received from this STA, negotiated at ADDBA + + // used for maintaining block ack state info + + tANI_U16 rxBufSize; + + + //Max # of MSDU send to this STA, negotiated at ADDBA + + tANI_U16 txBufSize; + + + //BA timeout negotiated at ADDBA. Unit: TU + + tANI_U16 tuTxBAWaitTimeout; //Time for Tx to wait for BA. 0 means no timeout + + + tANI_U16 tuRxBAWaitTimeout; //Time for Rx to wait for explicit/implicit BAR. 0 means no timeout + + +} tCfgTrafficClass; + + + +/// STA state node + +typedef struct sDphHashNode + +{ + + + //BYTE 0 + + // HASH ENTRY FIELDS NOT NEEDED IN HAL. + + /// This STA valid or not + + tANI_U8 valid : 1; + + tANI_U8 encPolicy : 3; + + tANI_U8 defaultKey : 1; + + tANI_U8 defaultKeyId : 2; + + tANI_U8 qosMode : 1; + + + //BYTE 1 + + tANI_U8 erpEnabled : 1; + + tANI_U8 added : 1; // This has been added to the dph hash table + + tANI_U8 linkTestOn : 1; + + tANI_U8 shortPreambleEnabled : 1; + + tANI_U8 shortSlotTimeEnabled : 1; + + tANI_U8 stopTx:1; + + tANI_U8 wmeEnabled: 1; // set if both ap and sta are wme capable + + tANI_U8 lleEnabled: 1; // set if both ap and sta are 11e capable + + + //BYTE 2 + + tANI_U8 wsmEnabled: 1; // set if both ap and sta are wsm capable + + tANI_U8 versionPresent:1; // station gave version info + + tANI_U8 burstEnableForce:1; // allow bursting regardless of qosMode + + tANI_U8 staAuthenticated:1; + + tANI_U8 fAniCount:1; + + tANI_U8 rmfEnabled:1; + + + /// Fragmentation size + + tANI_U16 fragSize; + + + /// LIM state + + tLimMlmStaContext mlmStaContext; + + + /// Number of Tim to wait if the STA doesn't respond / fetch data + + tANI_U8 timWaitCount; + + + /* Number of Successful MPDU's being sent */ + tANI_U32 curTxMpduCnt; + + + /// number of consecutive TIMs sent without response + + tANI_U8 numTimSent; + + + // qos parameter info + + tDphQosParams qos; + + + // station version info - valid only if versionPresent is set + + tSirMacPropVersion version; + +#ifdef PLM_WDS + + tANI_U8 wdsIndex; + + tANI_U8 wdsPeerBeaconSeen; + +#endif + + + tANI_U16 baPolicyFlag; //BA Policy for each TID. + + + /* + * All the legacy supported rates. + */ + + tSirSupportedRates supportedRates; + + + tANI_U8 htGreenfield:1; + + tANI_U8 htShortGI40Mhz:1; + + tANI_U8 htShortGI20Mhz:1; + + // DSSS/CCK at 40 MHz: Enabled 1 or Disabled + + tANI_U8 htDsssCckRate40MHzSupport:1; + + // L-SIG TXOP Protection used only if peer support available + + tANI_U8 htLsigTXOPProtection:1; + + // A-MPDU Density + + // 000 - No restriction + + // 001 - 1/8 usec + + // 010 - 1/4 usec + + // 011 - 1/2 usec + + // 100 - 1 usec + + // 101 - 2 usec + + // 110 - 4 usec + + // 111 - 8 usec + + // + + tANI_U8 htAMpduDensity:3; + + + + + //Set to 0 for 3839 octets + + //Set to 1 for 7935 octets + + tANI_U8 htMaxAmsduLength; + + + + + // MIMO Power Save + + tSirMacHTMIMOPowerSaveState htMIMOPSState; + + + // + + + // Maximum Rx A-MPDU factor + + tANI_U8 htMaxRxAMpduFactor:3; + + // + + // Recommended Tx Width Set + + // 0 - use 20 MHz channel (control channel) + + // 1 - use 40 Mhz channel + + // + + tANI_U8 htSupportedChannelWidthSet:1; + tANI_U8 htSecondaryChannelOffset:2; + tANI_U8 rsvd1:2; + + + /////////////////////////////////////////////////////////////////////// + + // DPH HASH ENTRY FIELDS NEEDED IN HAL ONLY + + /////////////////////////////////////////////////////////////////////// + + tANI_U8 dpuSig:4; /* DPU signature */ + + tANI_U8 staSig:4; // STA signature + + tANI_U8 staType; + + + tANI_U16 bssId; // BSSID + + tANI_U16 assocId; // Association ID + + + + + //This is the real sta index generated by HAL + + tANI_U16 staIndex; + + tANI_U8 staAddr[6]; + + /*The DPU signatures will be sent eventually to TL to help it determine the + + association to which a packet belongs to*/ + + /*Unicast DPU signature*/ + + tANI_U8 ucUcastSig; + + + /*Broadcast DPU signature*/ + + tANI_U8 ucBcastSig; + + + // + + // PE needs this info on a per-STA, per-TID basis + + // At any point in time, when this data is sampled, + + // it gives a measure of: + + // a) All the active bA sessions + + // b) And the BA configuration itself + + // + + tCfgTrafficClass tcCfg[STACFG_MAX_TC]; + + + //BA state bitmap 2 bits per tid + + // BA state for tid i = (baState >> tid*2) & 0x3 + + tANI_U32 baState; + +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtSupportedChannelWidthSet; + tANI_U8 vhtSupportedRxNss; + tANI_U8 vhtBeamFormerCapable; +#endif + +#ifdef WLAN_FEATURE_11W + tANI_U8 pmfSaQueryState; + tANI_U8 pmfSaQueryRetryCount; + tANI_U16 pmfSaQueryCurrentTransId; + tANI_U16 pmfSaQueryStartTransId; + TX_TIMER pmfSaQueryTimer; + v_TIME_t last_unprot_deauth_disassoc; + tANI_U8 proct_deauh_disassoc_cnt; + v_TIME_t last_assoc_received_time; +#endif + + tANI_U8 htLdpcCapable; + tANI_U8 vhtLdpcCapable; + +#ifdef FEATURE_WLAN_TDLS + tANI_U16 ht_caps; + tANI_U32 vht_caps; +#endif + + /* Timing and fine Timing measurement capability clubbed together */ + tANI_U8 timingMeasCap; + /* key installed for this STA or not in the firmware */ + tANI_U8 isKeyInstalled; + + uint8_t nss; + + /* When a station with already an existing dph entry tries to + + * associate again, the old dph entry will be zeroed out except + + * for the next pointer. The next pointer must be defined at the + + * end of the structure. + + */ + + tANI_U8 isDisassocDeauthInProgress; + struct sDphHashNode *next; + tANI_S8 del_sta_ctx_rssi; +} tDphHashNode, *tpDphHashNode; + + +#include "dphHashTable.h" + + +// ------------------------------------------------------------------- + + +typedef struct sAniSirDph + +{ + + /// The hash table object + + dphHashTableClass dphHashTable; + +} tAniSirDph, *tpAniSirDph; + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h new file mode 100644 index 000000000000..dd75d5e7b123 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h @@ -0,0 +1,1008 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file parserApi.h contains the definitions used + * for parsing received 802.11 frames + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __PARSE_H__ +#define __PARSE_H__ + +#include +#include "sirMacPropExts.h" +#include "dot11f.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" + +#define COUNTRY_STRING_LENGTH ( 3 ) +#define COUNTRY_INFO_MAX_CHANNEL ( 84 ) +#define MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE (COUNTRY_STRING_LENGTH * COUNTRY_INFO_MAX_CHANNEL) +#define HIGHEST_24GHZ_CHANNEL_NUM ( 14 ) + +#define IS_24G_CH(__chNum) ((__chNum > 0) && (__chNum < 15)) +#define IS_5G_CH(__chNum) ((__chNum >= 36) && (__chNum <= 165)) +#define IS_2X2_CHAIN(__chain) ((__chain & 0x3) == 0x3) +#define DISABLE_NSS2_MCS 0xC + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define QCOM_VENDOR_IE_MCC_AVOID_CH 0x01 + +struct sAvoidChannelIE { + /* following must be 0xDD (221) */ + uint8_t tag_number; + uint8_t length; + /* following must be 00-A0-C6 */ + uint8_t oui[3]; + /* following must be 0x01 */ + uint8_t type; + uint8_t channel; +}; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#define SIZE_OF_FIXED_PARAM ( 12 ) +#define SIZE_OF_TAG_PARAM_NUM ( 1 ) +#define SIZE_OF_TAG_PARAM_LEN ( 1 ) +#define RSNIEID ( 0x30 ) +#define RSNIE_CAPABILITY_LEN ( 2 ) +#define DEFAULT_RSNIE_CAP_VAL ( 0x00 ) + +typedef struct sSirCountryInformation +{ + tANI_U8 countryString[COUNTRY_STRING_LENGTH]; + tANI_U8 numIntervals; //number of channel intervals + struct channelPowerLim + { + tANI_U8 channelNumber; + tANI_U8 numChannel; + tANI_U8 maxTransmitPower; + } channelTransmitPower[COUNTRY_INFO_MAX_CHANNEL]; +} tSirCountryInformation,*tpSirCountryInformation; + + +/* Structure common to Beacons & Probe Responses */ +typedef struct sSirProbeRespBeacon +{ + tSirMacTimeStamp timeStamp; + tANI_U16 beaconInterval; + tSirMacCapabilityInfo capabilityInfo; + + tSirMacSSid ssId; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tSirMacChanNum channelNumber; + tSirMacCfParamSet cfParamSet; + tSirMacTim tim; + tSirMacEdcaParamSetIE edcaParams; + tSirMacQosCapabilityIE qosCapability; + + tSirCountryInformation countryInfoParam; + tSirMacWpaInfo wpa; + tSirMacRsnInfo rsn; + + tSirMacErpInfo erpIEInfo; + + tSirPropIEStruct propIEinfo; + tDot11fIEPowerConstraints localPowerConstraint; + tDot11fIETPCReport tpcReport; + tDot11fIEChanSwitchAnn channelSwitchIE; + tDot11fIEsec_chan_offset_ele sec_chan_offset; + tDot11fIEext_chan_switch_ann ext_chan_switch; + tDot11fIESuppOperatingClasses supp_operating_classes; + tSirMacAddr bssid; + tDot11fIEQuiet quietIE; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEP2PProbeRes P2PProbeRes; +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_U8 mdie[SIR_MDIE_SIZE]; +#endif +#ifdef FEATURE_WLAN_ESE + tDot11fIEESETxmitPower eseTxPwr; + tDot11fIEQBSSLoad QBSSLoad; +#endif + tANI_U8 ssidPresent; + tANI_U8 suppRatesPresent; + tANI_U8 extendedRatesPresent; + tANI_U8 cfPresent; + tANI_U8 dsParamsPresent; + tANI_U8 timPresent; + + tANI_U8 edcaPresent; + tANI_U8 qosCapabilityPresent; + tANI_U8 wmeEdcaPresent; + tANI_U8 wmeInfoPresent; + tANI_U8 wsmCapablePresent; + + tANI_U8 countryInfoPresent; + tANI_U8 wpaPresent; + tANI_U8 rsnPresent; + tANI_U8 erpPresent; + tANI_U8 channelSwitchPresent; + uint8_t sec_chan_offset_present; + uint8_t ext_chan_switch_present; + uint8_t supp_operating_class_present; + tANI_U8 quietIEPresent; + tANI_U8 tpcReportPresent; + tANI_U8 powerConstraintPresent; + +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_U8 mdiePresent; +#endif + +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEOperatingMode OperatingMode; + tANI_U8 WiderBWChanSwitchAnnPresent; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; +#endif + tANI_U8 Vendor1IEPresent; + tANI_U8 Vendor2IEPresent; + tANI_U8 Vendor3IEPresent; + tDot11fIEIBSSParams IBSSParams; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tDot11fIEQComVendorIE AvoidChannelIE; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ +#ifdef FEATURE_WLAN_ESE + uint8_t is_ese_ver_ie_present; +#endif +} tSirProbeRespBeacon, *tpSirProbeRespBeacon; + +// probe Request structure +typedef struct sSirProbeReq +{ + tSirMacSSid ssId; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tDot11fIEWscProbeReq probeReqWscIeInfo; + tDot11fIEHTCaps HTCaps; + tANI_U8 ssidPresent; + tANI_U8 suppRatesPresent; + tANI_U8 extendedRatesPresent; + tANI_U8 wscIePresent; + tANI_U8 p2pIePresent; +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; +#endif + + +} tSirProbeReq, *tpSirProbeReq; + +/// Association Request structure (one day to be replaced by +/// tDot11fAssocRequest) +typedef struct sSirAssocReq +{ + + tSirMacCapabilityInfo capabilityInfo; + tANI_U16 listenInterval; + tSirMacAddr currentApAddr; /* only in reassoc frames */ + tSirMacSSid ssId; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + + tSirAddtsReqInfo addtsReq; + tSirMacQosCapabilityStaIE qosCapability; + + tSirMacWapiInfo wapi; + tSirMacWpaInfo wpa; + tSirMacRsnInfo rsn; + tSirAddie addIE; + + tSirPropIEStruct propIEinfo; + tSirMacPowerCapabilityIE powerCapability; + tSirMacSupportedChannelIE supportedChannels; + tDot11fIEHTCaps HTCaps; + tDot11fIEWMMInfoStation WMMInfoStation; + /// This is set if the frame is a reassoc request: + tANI_U8 reassocRequest; + tANI_U8 ssidPresent; + tANI_U8 suppRatesPresent; + tANI_U8 extendedRatesPresent; + + tANI_U8 wmeInfoPresent; + tANI_U8 qosCapabilityPresent; + tANI_U8 addtsPresent; + tANI_U8 wsmCapablePresent; + + tANI_U8 wapiPresent; + tANI_U8 wpaPresent; + tANI_U8 rsnPresent; + tANI_U8 addIEPresent; + + tANI_U8 powerCapabilityPresent; + tANI_U8 supportedChannelsPresent; + /* keeping copy of association request received, this is + required for indicating the frame to upper layers */ + tANI_U32 assocReqFrameLength; + tANI_U8* assocReqFrame; +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + tDot11fIEOperatingMode operMode; +#endif + tDot11fIEExtCap ExtCap; +} tSirAssocReq, *tpSirAssocReq; + + +/// Association Response structure (one day to be replaced by +/// tDot11fAssocRequest) +typedef struct sSirAssocRsp +{ + + tSirMacCapabilityInfo capabilityInfo; + tANI_U16 aid; + tANI_U16 statusCode; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tSirPropIEStruct propIEinfo; + tSirMacEdcaParamSetIE edca; + tSirAddtsRspInfo addtsRsp; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; +#if defined WLAN_FEATURE_VOWIFI_11R + tDot11fIEFTInfo FTInfo; + tANI_U8 mdie[SIR_MDIE_SIZE]; + tANI_U8 num_RICData; + tDot11fIERICDataDesc RICData[2]; +#endif + +#ifdef FEATURE_WLAN_ESE + tANI_U8 num_tspecs; + tDot11fIEWMMTSPEC TSPECInfo[SIR_ESE_MAX_TSPEC_IES]; + tSirMacESETSMIE tsmIE; +#endif + + tANI_U8 suppRatesPresent; + tANI_U8 extendedRatesPresent; + + tANI_U8 edcaPresent; + tANI_U8 wmeEdcaPresent; + tANI_U8 addtsPresent; + tANI_U8 wsmCapablePresent; +#if defined WLAN_FEATURE_VOWIFI_11R + tANI_U8 ftinfoPresent; + tANI_U8 mdiePresent; + tANI_U8 ricPresent; +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U8 tspecPresent; + tANI_U8 tsmPresent; +#endif +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; +#endif + tDot11fIEExtCap ExtCap; + tSirQosMapSet QosMapSet; +#ifdef WLAN_FEATURE_11W + tDot11fIETimeoutInterval TimeoutInterval; +#endif +} tSirAssocRsp, *tpSirAssocRsp; + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +// Structure to hold ESE Beacon report mandatory IEs +typedef struct sSirEseBcnReportMandatoryIe +{ + tSirMacSSid ssId; + tSirMacRateSet supportedRates; + tSirMacFHParamSet fhParamSet; + tSirMacDsParamSetIE dsParamSet; + tSirMacCfParamSet cfParamSet; + tSirMacIBSSParams ibssParamSet; + tSirMacTim tim; + tSirMacRRMEnabledCap rmEnabledCapabilities; + + tANI_U8 ssidPresent; + tANI_U8 suppRatesPresent; + tANI_U8 fhParamPresent; + tANI_U8 dsParamsPresent; + tANI_U8 cfPresent; + tANI_U8 ibssParamPresent; + tANI_U8 timPresent; + tANI_U8 rrmPresent; +} tSirEseBcnReportMandatoryIe, *tpSirEseBcnReportMandatoryIe; +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +struct s_ext_cap { + uint8_t bssCoexistMgmtSupport: 1; + uint8_t reserved1: 1; + uint8_t extChanSwitch: 1; + uint8_t reserved2: 1; + uint8_t psmpCap: 1; + uint8_t reserved3: 1; + uint8_t spsmpCap: 1; + uint8_t event: 1; + uint8_t diagnostics: 1; + uint8_t multiDiagnostics: 1; + uint8_t locTracking: 1; + uint8_t FMS: 1; + uint8_t proxyARPService: 1; + uint8_t coLocIntfReporting: 1; + uint8_t civicLoc: 1; + uint8_t geospatialLoc: 1; + uint8_t TFS: 1; + uint8_t wnmSleepMode: 1; + uint8_t timBroadcast: 1; + uint8_t bssTransition: 1; + uint8_t qosTrafficCap: 1; + uint8_t acStaCnt: 1; + uint8_t multiBSSID: 1; + uint8_t timingMeas: 1; + uint8_t chanUsage: 1; + uint8_t ssidList: 1; + uint8_t DMS: 1; + uint8_t UTCTSFOffset: 1; + uint8_t TDLSPeerUAPSDBufferSTA: 1; + uint8_t TDLSPeerPSMSupp: 1; + uint8_t TDLSChannelSwitching: 1; + uint8_t interworkingService: 1; + uint8_t qosMap: 1; + uint8_t EBR: 1; + uint8_t sspnInterface: 1; + uint8_t reserved4: 1; + uint8_t msgCFCap: 1; + uint8_t TDLSSupport: 1; + uint8_t TDLSProhibited: 1; + uint8_t TDLSChanSwitProhibited: 1; + uint8_t rejectUnadmittedTraffic: 1; + uint8_t serviceIntervalGranularity: 3; + uint8_t identifierLoc: 1; + uint8_t uapsdCoexistence: 1; + uint8_t wnmNotification: 1; + uint8_t QABcapbility: 1; + uint8_t UTF8SSID: 1; + uint8_t QMFActivated: 1; + uint8_t QMFreconAct: 1; + uint8_t RobustAVStreaming: 1; + uint8_t AdvancedGCR: 1; + uint8_t MeshGCR: 1; + uint8_t SCS: 1; + uint8_t QLoadReport: 1; + uint8_t AlternateEDCA: 1; + uint8_t UnprotTXOPneg: 1; + uint8_t ProtTXOPneg: 1; + uint8_t reserved6: 1; + uint8_t ProtQLoadReport: 1; + uint8_t TDLSWiderBW: 1; + uint8_t operModeNotification: 1; + uint8_t maxNumOfMSDU_bit1: 1; + uint8_t maxNumOfMSDU_bit2: 1; + uint8_t ChanSchMgmt: 1; + uint8_t GeoDBInbandEnSignal: 1; + uint8_t NwChanControl: 1; + uint8_t WhiteSpaceMap: 1; + uint8_t ChanAvailQuery: 1; + uint8_t fine_time_meas_responder: 1; + uint8_t fine_time_meas_initiator: 1; +}; + +tANI_U8 +sirIsPropCapabilityEnabled(struct sAniSirGlobal *pMac, tANI_U32 bitnum); + +void dot11fLog(tpAniSirGlobal pMac, int nSev, const char *lpszFormat, ...); + +#define CFG_GET_INT(nStatus, pMac, nItem, cfg ) do { \ + (nStatus) = wlan_cfgGetInt( (pMac), (nItem), & (cfg) ); \ + if ( eSIR_SUCCESS != (nStatus) ) \ + { \ + dot11fLog( (pMac), LOGP, FL("Failed to retrieve " \ + #nItem " from CFG (%d)."), \ + (nStatus) ); \ + return nStatus; \ + } \ + } while (0) + +#define CFG_GET_INT_NO_STATUS(nStatus, pMac, nItem, cfg ) do { \ + (nStatus) = wlan_cfgGetInt( (pMac), (nItem), & (cfg) ); \ + if ( eSIR_SUCCESS != (nStatus) ) \ + { \ + dot11fLog( (pMac), LOGP, FL("Failed to retrieve " \ + #nItem " from CFG (%d)."), \ + (nStatus) ); \ + return; \ + } \ + } while (0) + +#define CFG_GET_STR(nStatus, pMac, nItem, cfg, nCfg, nMaxCfg) do { \ + (nCfg) = (nMaxCfg); \ + (nStatus) = wlan_cfgGetStr( (pMac), (nItem), (cfg), & (nCfg) ); \ + if ( eSIR_SUCCESS != (nStatus) ) \ + { \ + dot11fLog( (pMac), LOGP, FL("Failed to retrieve " \ + #nItem " from CFG (%d)."), \ + (nStatus) ); \ + return nStatus; \ + } \ + } while (0) + +#define CFG_GET_STR_NO_STATUS(nStatus, pMac, nItem, cfg, nCfg, \ + nMaxCfg) do { \ + (nCfg) = (nMaxCfg); \ + (nStatus) = wlan_cfgGetStr( (pMac), (nItem), (cfg), & (nCfg) ); \ + if ( eSIR_SUCCESS != (nStatus) ) \ + { \ + dot11fLog( (pMac), LOGP, FL("Failed to retrieve " \ + #nItem " from CFG (%d)."), \ + (nStatus) ); \ + return; \ + } \ + } while (0) + +void swapBitField16(tANI_U16 in, tANI_U16 *out); + +// Currently implemented as "shims" between callers & the new framesc- +// generated code: + +tSirRetStatus +sirConvertProbeReqFrame2Struct(struct sAniSirGlobal *pMac, + tANI_U8 *frame, + tANI_U32 len, + tpSirProbeReq probe); + +tSirRetStatus +sirConvertProbeFrame2Struct(struct sAniSirGlobal *pMac, tANI_U8 *frame, + tANI_U32 len, + tpSirProbeRespBeacon probe); + +tSirRetStatus +sirConvertAssocReqFrame2Struct(struct sAniSirGlobal *pMac, + tANI_U8 * frame, + tANI_U32 len, + tpSirAssocReq assoc); + +tSirRetStatus +sirConvertAssocRespFrame2Struct(struct sAniSirGlobal *pMac, + tANI_U8 * frame, + tANI_U32 len, + tpSirAssocRsp assoc); + +tSirRetStatus +sirConvertReassocReqFrame2Struct(struct sAniSirGlobal *pMac, + tANI_U8 * frame, + tANI_U32 len, + tpSirAssocReq assoc); + +tSirRetStatus +sirParseBeaconIE(struct sAniSirGlobal *pMac, + tpSirProbeRespBeacon pBeaconStruct, + tANI_U8 *pPayload, + tANI_U32 payloadLength); + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +tSirRetStatus +sirFillBeaconMandatoryIEforEseBcnReport(tpAniSirGlobal pMac, + tANI_U8 *pPayload, + const tANI_U32 payloadLength, + tANI_U8 **outIeBuf, + tANI_U32 *pOutIeLen); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +tSirRetStatus +sirConvertBeaconFrame2Struct(struct sAniSirGlobal *pMac, + tANI_U8 *pBeaconFrame, + tpSirProbeRespBeacon pBeaconStruct); + +tSirRetStatus +sirConvertAuthFrame2Struct(struct sAniSirGlobal *pMac, + tANI_U8 * frame, + tANI_U32 len, + tpSirMacAuthFrameBody auth); + +tSirRetStatus +sirConvertAddtsReq2Struct(struct sAniSirGlobal *pMac, + tANI_U8 *frame, + tANI_U32 len, + tSirAddtsReqInfo *addTs); + +tSirRetStatus +sirConvertAddtsRsp2Struct(struct sAniSirGlobal *pMac, + tANI_U8 *frame, + tANI_U32 len, + tSirAddtsRspInfo *addts); + +tSirRetStatus +sirConvertDeltsReq2Struct(struct sAniSirGlobal *pMac, + tANI_U8 *frame, + tANI_U32 len, + tSirDeltsReqInfo *delTs); +tSirRetStatus +sirConvertQosMapConfigureFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tSirQosMapSet *pQosMapSet); + +/** + * \brief Populated a tDot11fFfCapabilities + * + * \sa PopulatedDot11fCapabilities2 + * + * + * \param pMac Pointer to the global MAC data structure + * + * \param pDot11f Address of a tDot11fFfCapabilities to be filled in + * + * + * \note If SIR_MAC_PROP_CAPABILITY_11EQOS is enabled, we'll clear the QOS + * bit in pDot11f + * + * + */ + +tSirRetStatus +PopulateDot11fCapabilities(tpAniSirGlobal pMac, + tDot11fFfCapabilities *pDot11f, + tpPESession psessionEntry); + +/** + * \brief Populated a tDot11fFfCapabilities + * + * \sa PopulatedDot11fCapabilities2 + * + * + * \param pMac Pointer to the global MAC data structure + * + * \param pDot11f Address of a tDot11fFfCapabilities to be filled in + * + * \param pSta Pointer to a tDphHashNode representing a peer + * + * + * \note If SIR_MAC_PROP_CAPABILITY_11EQOS is enabled on our peer, we'll + * clear the QOS bit in pDot11f + * + * + */ + +struct sDphHashNode; + +tSirRetStatus +PopulateDot11fCapabilities2(tpAniSirGlobal pMac, + tDot11fFfCapabilities *pDot11f, + struct sDphHashNode *pSta, + tpPESession psessionEntry); + +/// Populate a tDot11fIEChanSwitchAnn +void +PopulateDot11fChanSwitchAnn(tpAniSirGlobal pMac, + tDot11fIEChanSwitchAnn *pDot11f, + tpPESession psessionEntry); + +/** + * populate_dot_11_f_ext_chann_switch_ann() - Function to populate ECS + * @mac_ptr: Pointer to PMAC structure + * @dot_11_ptr: ECS element + * @session_entry: PE session entry + * + * This function is used to populate the extended channel switch element + * + * Return: None + * + */ +void +populate_dot_11_f_ext_chann_switch_ann(tpAniSirGlobal mac_ptr, + tDot11fIEext_chan_switch_ann *dot_11_ptr, + tpPESession session_entry); + +/// Populate a tDot11fIEChannelSwitchWrapper +void +PopulateDot11fChanSwitchWrapper(tpAniSirGlobal pMac, + tDot11fIEChannelSwitchWrapper *pDot11f, + tpPESession psessionEntry); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/* Populate a tDot11fIEQComVendorIE */ +void +populate_dot11f_avoid_channel_ie(tpAniSirGlobal mac_ctx, + tDot11fIEQComVendorIE *dot11f, + tpPESession session_entry); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/// Populate a tDot11fIECountry +tSirRetStatus +PopulateDot11fCountry(tpAniSirGlobal pMac, + tDot11fIECountry *pDot11f, tpPESession psessionEntry); + +/// Populated a PopulateDot11fDSParams +tSirRetStatus +PopulateDot11fDSParams(tpAniSirGlobal pMac, + tDot11fIEDSParams *pDot11f, tANI_U8 channel, + tpPESession psessionEntry); + + +/// Populated a tDot11fIEEDCAParamSet +void +PopulateDot11fEDCAParamSet(tpAniSirGlobal pMac, + tDot11fIEEDCAParamSet *pDot11f, + tpPESession psessionEntry); + +tSirRetStatus +PopulateDot11fERPInfo(tpAniSirGlobal pMac, + tDot11fIEERPInfo *pDot11f, tpPESession psessionEntry); + +tSirRetStatus +PopulateDot11fExtSuppRates(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, tDot11fIEExtSuppRates *pDot11f, + tpPESession psessionEntry); + +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus +PopulateDot11fBeaconReport(tpAniSirGlobal pMac, + tDot11fIEMeasurementReport *pDot11f, + tSirMacBeaconReport *pBeaconReport ); +#endif + +/** + * \brief Populate a tDot11fIEExtSuppRates + * + * + * \param pMac Pointer to the global MAC data structure + * + * \param nChannelNum Channel on which the enclosing frame will be going out + * + * \param pDot11f Address of a tDot11fIEExtSuppRates struct to be filled in. + * + * + * This method is a NOP if the channel is greater than 14. + * + * + */ + +tSirRetStatus +PopulateDot11fExtSuppRates1(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tDot11fIEExtSuppRates *pDot11f); + +tSirRetStatus +PopulateDot11fHTCaps(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEHTCaps *pDot11f); + +tSirRetStatus +PopulateDot11fHTInfo(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pDot11f, + tpPESession psessionEntry); + +void PopulateDot11fIBSSParams(tpAniSirGlobal pMac, + tDot11fIEIBSSParams *pDot11f, tpPESession psessionEntry); + + +/// Populate a tDot11fIEPowerCaps +void +PopulateDot11fPowerCaps(tpAniSirGlobal pMac, + tDot11fIEPowerCaps *pCaps, + tANI_U8 nAssocType,tpPESession psessionEntry); + +/// Populate a tDot11fIEPowerConstraints +tSirRetStatus +PopulateDot11fPowerConstraints(tpAniSirGlobal pMac, + tDot11fIEPowerConstraints *pDot11f); + +void +PopulateDot11fQOSCapsAp(tpAniSirGlobal pMac, + tDot11fIEQOSCapsAp *pDot11f, tpPESession psessionEntry); + +void +PopulateDot11fQOSCapsStation(tpAniSirGlobal pMac, + tDot11fIEQOSCapsStation *pDot11f); + +tSirRetStatus +PopulateDot11fRSN(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIERSN *pDot11f); + +tSirRetStatus +PopulateDot11fRSNOpaque( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIERSNOpaque *pDot11f ); + +#if defined(FEATURE_WLAN_WAPI) + +tSirRetStatus +PopulateDot11fWAPI(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWAPI *pDot11f); + +tSirRetStatus PopulateDot11fWAPIOpaque( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWAPIOpaque *pDot11f ); + +#endif //defined(FEATURE_WLAN_WAPI) + +/// Populate a tDot11fIESSID given a tSirMacSSid +void +PopulateDot11fSSID(tpAniSirGlobal pMac, + tSirMacSSid *pInternal, + tDot11fIESSID *pDot11f); + +/// Populate a tDot11fIESSID from CFG +tSirRetStatus +PopulateDot11fSSID2(tpAniSirGlobal pMac, + tDot11fIESSID *pDot11f); + + +/** + * \brief Populate a tDot11fIESchedule + * + * \sa PopulateDot11fWMMSchedule + * + * + * \param pSchedule Address of a tSirMacScheduleIE struct + * + * \param pDot11f Address of a tDot11fIESchedule to be filled in + * + * + */ + +void +PopulateDot11fSchedule(tSirMacScheduleIE *pSchedule, + tDot11fIESchedule *pDot11f); + +void +PopulateDot11fSuppChannels(tpAniSirGlobal pMac, + tDot11fIESuppChannels *pDot11f, + tANI_U8 nAssocType,tpPESession psessionEntry); + +/** + * \brief Populated a tDot11fIESuppRates + * + * + * \param pMac Pointer to the global MAC data structure + * + * \param nChannelNum Channel the enclosing frame will be going out on; see + * below + * + * \param pDot11f Address of a tDot11fIESuppRates struct to be filled in. + * + * + * If nChannelNum is greater than 13, the supported rates will be + * WNI_CFG_SUPPORTED_RATES_11B. If it is less than or equal to 13, the + * supported rates will be WNI_CFG_SUPPORTED_RATES_11A. If nChannelNum is + * set to the sentinel value POPULATE_DOT11F_RATES_OPERATIONAL, the struct + * will be populated with WNI_CFG_OPERATIONAL_RATE_SET. + * + * + */ + +#define POPULATE_DOT11F_RATES_OPERATIONAL ( 0xff ) + +tSirRetStatus +PopulateDot11fSuppRates(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tDot11fIESuppRates *pDot11f,tpPESession); + +tSirRetStatus +populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, + tDot11fIESuppRates *p_supp_rates, + tDot11fIEExtSuppRates *p_ext_supp_rates); + +tSirRetStatus PopulateDot11fTPCReport(tpAniSirGlobal pMac, + tDot11fIETPCReport *pDot11f, + tpPESession psessionEntry); + +/// Populate a tDot11FfTSInfo +void PopulateDot11fTSInfo(tSirMacTSInfo *pInfo, + tDot11fFfTSInfo *pDot11f); + + +void PopulateDot11fWMM(tpAniSirGlobal pMac, + tDot11fIEWMMInfoAp *pInfo, + tDot11fIEWMMParams *pParams, + tDot11fIEWMMCaps *pCaps, + tpPESession psessionEntry); + +void PopulateDot11fWMMCaps(tDot11fIEWMMCaps *pCaps); + +#if defined(FEATURE_WLAN_ESE) +// Fill the ESE version IE +void PopulateDot11fESEVersion(tDot11fIEESEVersion *pESEVersion); +// Fill the Radio Management Capability +void PopulateDot11fESERadMgmtCap(tDot11fIEESERadMgmtCap *pESERadMgmtCap); +// Fill the CCKM IE +tSirRetStatus PopulateDot11fESECckmOpaque( tpAniSirGlobal pMac, + tpSirCCKMie pCCKMie, + tDot11fIEESECckmOpaque *pDot11f ); + +void PopulateDot11TSRSIE(tpAniSirGlobal pMac, + tSirMacESETSRSIE *pOld, + tDot11fIEESETrafStrmRateSet *pDot11f, + tANI_U8 rate_length); +void PopulateDot11fReAssocTspec(tpAniSirGlobal pMac, tDot11fReAssocRequest *pReassoc, tpPESession psessionEntry); +#endif + +void PopulateDot11fWMMInfoAp(tpAniSirGlobal pMac, + tDot11fIEWMMInfoAp *pInfo, + tpPESession psessionEntry); + +void PopulateDot11fWMMInfoStation(tpAniSirGlobal pMac, + tDot11fIEWMMInfoStation *pInfo); + +void PopulateDot11fWMMInfoStationPerSession(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEWMMInfoStation *pInfo); + +void PopulateDot11fWMMParams(tpAniSirGlobal pMac, + tDot11fIEWMMParams *pParams, + tpPESession psessionEntry); + +/** + * \brief Populate a tDot11fIEWMMSchedule + * + * \sa PopulatedDot11fSchedule + * + * + * \param pSchedule Address of a tSirMacScheduleIE struct + * + * \param pDot11f Address of a tDot11fIEWMMSchedule to be filled in + * + * + */ + +void +PopulateDot11fWMMSchedule(tSirMacScheduleIE *pSchedule, + tDot11fIEWMMSchedule *pDot11f); + +tSirRetStatus +PopulateDot11fWPA(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWPA *pDot11f); + +tSirRetStatus +PopulateDot11fWPAOpaque( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWPAOpaque *pDot11f ); + +void +PopulateDot11fTSPEC(tSirMacTspecIE *pOld, + tDot11fIETSPEC *pDot11f); + +void +PopulateDot11fWMMTSPEC(tSirMacTspecIE *pOld, + tDot11fIEWMMTSPEC *pDot11f); + +tSirRetStatus +PopulateDot11fTCLAS(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, + tDot11fIETCLAS *pDot11f); + +tSirRetStatus +PopulateDot11fWMMTCLAS(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, + tDot11fIEWMMTCLAS *pDot11f); + + +tSirRetStatus PopulateDot11fWsc(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f); + +tSirRetStatus PopulateDot11fWscRegistrarInfo(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f); + +tSirRetStatus DePopulateDot11fWscRegistrarInfo(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f); + +tSirRetStatus PopulateDot11fProbeResWPSIEs(tpAniSirGlobal pMac, tDot11fIEWscProbeRes *pDot11f, tpPESession psessionEntry); +tSirRetStatus PopulateDot11fAssocResWPSIEs(tpAniSirGlobal pMac, tDot11fIEWscAssocRes *pDot11f, tpPESession psessionEntry); +tSirRetStatus PopulateDot11fBeaconWPSIEs(tpAniSirGlobal pMac, tDot11fIEWscBeacon *pDot11f, tpPESession psessionEntry); + +tSirRetStatus PopulateDot11fWscInProbeRes(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f); + +tSirRetStatus PopulateDot11fWscRegistrarInfoInProbeRes(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f); + +tSirRetStatus DePopulateDot11fWscRegistrarInfoInProbeRes(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f); + + +tSirRetStatus PopulateDot11fAssocResWscIE(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq); + +tSirRetStatus PopulateDot11AssocResP2PIE(tpAniSirGlobal pMac, + tDot11fIEP2PAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq); + +tSirRetStatus PopulateDot11fWscInAssocRes(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f); + + +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus PopulateDot11fWFATPC( tpAniSirGlobal pMac, + tDot11fIEWFATPC *pDot11f, tANI_U8 txPower, tANI_U8 linkMargin ); + +tSirRetStatus PopulateDot11fRRMIe( tpAniSirGlobal pMac, + tDot11fIERRMEnabledCap *pDot11f, + tpPESession psessionEntry ); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +void PopulateMDIE( tpAniSirGlobal pMac, + tDot11fIEMobilityDomain *pDot11f, tANI_U8 mdie[] ); +void PopulateFTInfo( tpAniSirGlobal pMac, + tDot11fIEFTInfo *pDot11f ); +#endif + +void PopulateDot11fAssocRspRates ( tpAniSirGlobal pMac, tDot11fIESuppRates *pSupp, + tDot11fIEExtSuppRates *pExt, tANI_U16 *_11bRates, tANI_U16 *_11aRates ); + +int FindIELocation( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tANI_U8 EID); +#endif + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +PopulateDot11fVHTCaps(tpAniSirGlobal pMac, tpPESession psessionEntry, + tDot11fIEVHTCaps *pDot11f); + +tSirRetStatus +PopulateDot11fVHTOperation(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEVHTOperation *pDot11f); + +tSirRetStatus +PopulateDot11fVHTExtBssLoad(tpAniSirGlobal pMac, tDot11fIEVHTExtBssLoad *pDot11f); + +tSirRetStatus +PopulateDot11fExtCap(tpAniSirGlobal pMac, tANI_BOOLEAN isVHTEnabled, + tDot11fIEExtCap * pDot11f, tpPESession psessionEntry); + +tSirRetStatus +PopulateDot11fOperatingMode(tpAniSirGlobal pMac, tDot11fIEOperatingMode *pDot11f, tpPESession psessionEntry ); + +void +PopulateDot11fWiderBWChanSwitchAnn(tpAniSirGlobal pMac, + tDot11fIEWiderBWChanSwitchAnn *pDot11f, + tpPESession psessionEntry); +#endif + +void PopulateDot11fTimeoutInterval( tpAniSirGlobal pMac, + tDot11fIETimeoutInterval *pDot11f, + tANI_U8 type, tANI_U32 value ); +void populate_dot11_supp_operating_classes(tpAniSirGlobal mac_ptr, + tDot11fIESuppOperatingClasses *dot_11_ptr, + tpPESession session_entry); +#ifdef SAP_AUTH_OFFLOAD +void +sap_auth_offload_update_rsn_ie(tpAniSirGlobal pmac, + tDot11fIERSNOpaque *pdot11f); +#endif /* SAP_AUTH_OFFLOAD */ + +tSirRetStatus PopulateDot11fTimingAdvertFrame(tpAniSirGlobal pMac, + tDot11fTimingAdvertisementFrame *frame); + +tSirRetStatus sirvalidateandrectifyies(tpAniSirGlobal pMac, + tANI_U8 *pMgmtFrame, + tANI_U32 nFrameBytes, + tANI_U32 *nMissingRsnBytes); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirCommon.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirCommon.h new file mode 100644 index 000000000000..3e54eb334d2d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirCommon.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file sirCommon.h contains the common definitions used by all + * Firmware modules. + * + * Author: V. K. Kandarpa + * Date: 04/12/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __SIRCOMMON_H +#define __SIRCOMMON_H + +#include "sirApi.h" +#include "sirParams.h" +#include "VossWrapper.h" + +/* ********************************************* * + * * + * SIRIUS SYSTEM EXTERNAL GLOBALS * + * * + * ********************************************* */ + + +// All the following are resource definitions + +#endif /* __SIRCOMMON_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirDebug.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirDebug.h new file mode 100644 index 000000000000..9407ee1f483f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirDebug.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __POL_DEBUG_H__ +#define __POL_DEBUG_H__ + +#define LOGOFF 0 +#define LOGP 1 +#define LOGE 2 +#define LOGW 3 +#define LOG1 4 +#define LOG2 5 +#define LOG3 6 +#define LOG4 7 + +#ifdef WLAN_MDM_CODE_REDUCTION_OPT +#ifdef PE_DEBUG_LOGE +#define PELOGE(p) { p } +#else +#define PELOGE(p) { } +#endif + +#ifdef PE_DEBUG_LOGW +#define PELOGW(p) { p } +#else +#define PELOGW(p) { } +#endif + +#define PELOG1(p) { } +#define PELOG2(p) { } +#define PELOG3(p) { } +#define PELOG4(p) { } + + +#else /* WLAN_MDM_CODE_REDUCTION_OPT */ + +#ifdef PE_DEBUG_LOGE +#define PELOGE(p) { p } +#else +#define PELOGE(p) { } +#endif + +#ifdef PE_DEBUG_LOGW +#define PELOGW(p) { p } +#else +#define PELOGW(p) { } +#endif + +#ifdef PE_DEBUG_LOG1 +#define PELOG1(p) { p } +#else +#define PELOG1(p) { } +#endif + +#ifdef PE_DEBUG_LOG2 +#define PELOG2(p) { p } +#else +#define PELOG2(p) { } +#endif + +#ifdef PE_DEBUG_LOG3 +#define PELOG3(p) { p } +#else +#define PELOG3(p) { } +#endif + +#ifdef PE_DEBUG_LOG4 +#define PELOG4(p) { p } +#else +#define PELOG4(p) { } +#endif + +#endif /* WLAN_MDM_CODE_REDUCTION_OPT */ + +#define FL(x) "%s: %d: "\ + x, __func__, __LINE__ + +#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h new file mode 100644 index 000000000000..63d1f5b5d339 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h @@ -0,0 +1,902 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file sirParams.h contains the common parameter definitions, which + * are not dependent on threadX API. These can be used by all Firmware + * modules. + * + * Author: Sandesh Goel + * Date: 04/13/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __SIRPARAMS_H +#define __SIRPARAMS_H + +# include "sirTypes.h" + +/* defines for WPS config states */ +#define SAP_WPS_DISABLED 0 +#define SAP_WPS_ENABLED_UNCONFIGURED 1 +#define SAP_WPS_ENABLED_CONFIGURED 2 + +// Firmware wide constants + +#define SIR_MAX_PACKET_SIZE 512 +#define SIR_MAX_NUM_CHANNELS 64 +#define SIR_MAX_NUM_STA_IN_IBSS 16 +#define SIR_ESE_MAX_MEAS_IE_REQS 8 + +typedef enum +{ + PHY_SINGLE_CHANNEL_CENTERED = 0, // 20MHz IF bandwidth centered on IF carrier + PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1, // 40MHz IF bandwidth with lower 20MHz supporting the primary channel + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3, // 40MHz IF bandwidth with higher 20MHz supporting the primary channel +#ifdef WLAN_FEATURE_11AC + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED = 4, //20/40MHZ offset LOW 40/80MHZ offset CENTERED + PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED = 5, //20/40MHZ offset CENTERED 40/80MHZ offset CENTERED + PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED = 6, //20/40MHZ offset HIGH 40/80MHZ offset CENTERED + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW = 7,//20/40MHZ offset LOW 40/80MHZ offset LOW + PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW = 8, //20/40MHZ offset HIGH 40/80MHZ offset LOW + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH = 9, //20/40MHZ offset LOW 40/80MHZ offset HIGH + PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH = 10,//20/40MHZ offset-HIGH 40/80MHZ offset HIGH +#endif + PHY_CHANNEL_BONDING_STATE_MAX = 11 +}ePhyChanBondState; + +#define MAX_BONDED_CHANNELS 4 + +#define SIR_MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define SIR_MAX(a,b) (((a) > (b)) ? (a) : (b)) + +typedef enum { + MCC = 0, + P2P = 1, + DOT11AC = 2, + SLM_SESSIONIZATION = 3, + DOT11AC_OPMODE = 4, + SAP32STA = 5, + TDLS = 6, + P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, + WLANACTIVE_OFFLOAD = 8, +#ifdef FEATURE_WLAN_EXTSCAN + EXTENDED_SCAN = 9, +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + PNO = 10, +#endif +#ifdef WLAN_FEATURE_NAN + NAN = 11, +#endif + RTT = 12, + WOW = 22, +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WLAN_ROAM_SCAN_OFFLOAD = 23, +#endif + IBSS_HEARTBEAT_OFFLOAD = 26, + WLAN_PERIODIC_TX_PTRN = 28, +#ifdef FEATURE_WLAN_TDLS + ADVANCE_TDLS = 29, + TDLS_OFF_CHANNEL = 30, +#endif + + //MAX_FEATURE_SUPPORTED = 128 +} placeHolderInCapBitmap; + +typedef enum eSriLinkState { + eSIR_LINK_IDLE_STATE = 0, + eSIR_LINK_PREASSOC_STATE = 1, + eSIR_LINK_POSTASSOC_STATE = 2, + eSIR_LINK_AP_STATE = 3, + eSIR_LINK_IBSS_STATE = 4, + // BT-AMP Case + eSIR_LINK_BTAMP_PREASSOC_STATE = 5, + eSIR_LINK_BTAMP_POSTASSOC_STATE = 6, + eSIR_LINK_BTAMP_AP_STATE = 7, + eSIR_LINK_BTAMP_STA_STATE = 8, + + // Reserved for HAL internal use + eSIR_LINK_LEARN_STATE = 9, + eSIR_LINK_SCAN_STATE = 10, + eSIR_LINK_FINISH_SCAN_STATE = 11, + eSIR_LINK_INIT_CAL_STATE = 12, + eSIR_LINK_FINISH_CAL_STATE = 13, + eSIR_LINK_LISTEN_STATE = 14, + eSIR_LINK_SEND_ACTION_STATE = 15, + eSIR_LINK_DOWN_STATE = 16, +} tSirLinkState; + + +/// Message queue structure used across Sirius project. +/// NOTE: this structure should be multiples of a word size (4bytes) +/// as this is used in tx_queue where it expects to be multiples of 4 bytes. +typedef struct sSirMsgQ +{ + tANI_U16 type; + /* + * This field can be used as sequence number/dialog token for matching + * requests and responses. + */ + tANI_U16 reserved; + /** + * Based on the type either a bodyptr pointer into + * memory or bodyval as a 32 bit data is used. + * bodyptr: is always a free able pointer, one should always + * make sure that bodyptr is always free able. + * + * Messages should use either bodyptr or bodyval; not both !!!. + */ + void *bodyptr; + tANI_U32 bodyval; + + /* + * Some messages provide a callback function. The function signature + * must be agreed upon between the two entities exchanging the message + */ + void *callback; + +} tSirMsgQ, *tpSirMsgQ; + +/// Mailbox Message Structure Define +typedef struct sSirMbMsg +{ + tANI_U16 type; + + /** + * This length includes 4 bytes of header, that is, + * 2 bytes type + 2 bytes msgLen + n*4 bytes of data. + * This field is byte length. + */ + tANI_U16 msgLen; + + /** + * This is the first data word in the mailbox message. + * It is followed by n words of data. + * NOTE: data[1] is not a place holder to store data + * instead to dereference the message body. + */ + tANI_U32 data[1]; +} tSirMbMsg, *tpSirMbMsg; + +/// Mailbox Message Structure for P2P +typedef struct sSirMbMsgP2p +{ + tANI_U16 type; + + /** + * This length includes 4 bytes of header, that is, + * 2 bytes type + 2 bytes msgLen + n*4 bytes of data. + * This field is byte length. + */ + tANI_U16 msgLen; + + tANI_U8 sessionId; + tANI_U8 noack; + tANI_U16 wait; + + /** + * This is the first data word in the mailbox message. + * It is followed by n words of data. + * NOTE: data[1] is not a place holder to store data + * instead to dereference the message body. + */ + tANI_U32 data[1]; +} tSirMbMsgP2p, *tpSirMbMsgP2p; + + +/* ******************************************* * + * * + * SIRIUS MESSAGE TYPES * + * * + * ******************************************* */ + + +/* + * The following message types have bounds defined for each module for + * inter thread/module communications. + * Each module will get 256 message types in total. + * Note that message type definitions for mailbox messages for + * communication with Host are in wniApi.h file. + * + * Any addition/deletion to this message list should also be + * reflected in the halUtil_getMsgString() routine. + */ + +// HAL message types +#define SIR_HAL_MSG_TYPES_BEGIN (SIR_HAL_MODULE_ID << 8) +#define SIR_HAL_ITC_MSG_TYPES_BEGIN (SIR_HAL_MSG_TYPES_BEGIN+0x20) +#define SIR_HAL_RADAR_DETECTED_IND SIR_HAL_ITC_MSG_TYPES_BEGIN +#define SIR_HAL_WDT_KAM_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 1) +#define SIR_HAL_TIMER_TEMP_MEAS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 2) +#define SIR_HAL_TIMER_PERIODIC_STATS_COLLECT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 3) +#define SIR_HAL_CAL_REQ_NTF (SIR_HAL_ITC_MSG_TYPES_BEGIN + 4) +#define SIR_HAL_MNT_OPEN_TPC_TEMP_MEAS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 5) +#define SIR_HAL_CCA_MONITOR_INTERVAL_TO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 6) +#define SIR_HAL_CCA_MONITOR_DURATION_TO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 7) +#define SIR_HAL_CCA_MONITOR_START (SIR_HAL_ITC_MSG_TYPES_BEGIN + 8) +#define SIR_HAL_CCA_MONITOR_STOP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 9) +#define SIR_HAL_CCA_CHANGE_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 10) +#define SIR_HAL_TIMER_WRAP_AROUND_STATS_COLLECT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 11) + +#define SIR_HAL_GET_FW_STATUS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 12) +#define SIR_HAL_ADD_STA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 13) +#define SIR_HAL_ADD_STA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 14) +#define SIR_HAL_DELETE_STA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 15) +#define SIR_HAL_DELETE_STA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 16) +#define SIR_HAL_ADD_BSS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 17) +#define SIR_HAL_ADD_BSS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 18) +#define SIR_HAL_DELETE_BSS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 19) +#define SIR_HAL_DELETE_BSS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 20) +#define SIR_HAL_INIT_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 21) +#define SIR_HAL_INIT_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 22) +#define SIR_HAL_START_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 23) +#define SIR_HAL_START_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 24) +#define SIR_HAL_END_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 25) +#define SIR_HAL_END_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 26) +#define SIR_HAL_FINISH_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 27) +#define SIR_HAL_FINISH_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 28) +#define SIR_HAL_SEND_BEACON_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 29) +#define SIR_HAL_SEND_BEACON_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 30) + +#define SIR_HAL_INIT_CFG_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 31) +#define SIR_HAL_INIT_CFG_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 32) + +#define SIR_HAL_INIT_WM_CFG_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 33) +#define SIR_HAL_INIT_WM_CFG_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 34) + +#define SIR_HAL_SET_BSSKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 35) +#define SIR_HAL_SET_BSSKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 36) +#define SIR_HAL_SET_STAKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 37) +#define SIR_HAL_SET_STAKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 38) +#define SIR_HAL_DPU_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 39) +#define SIR_HAL_DPU_STATS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 40) +#define SIR_HAL_GET_DPUINFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 41) +#define SIR_HAL_GET_DPUINFO_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 42) + +#define SIR_HAL_UPDATE_EDCA_PROFILE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 43) + +#define SIR_HAL_UPDATE_STARATEINFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 45) +#define SIR_HAL_UPDATE_STARATEINFO_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 46) + +#define SIR_HAL_UPDATE_BEACON_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 47) +#define SIR_HAL_UPDATE_CF_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 48) +#define SIR_HAL_CHNL_SWITCH_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 49) +#define SIR_HAL_ADD_TS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 50) +#define SIR_HAL_DEL_TS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 51) +#define SIR_HAL_SOFTMAC_TXSTAT_REPORT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 52) + +#define SIR_HAL_MBOX_SENDMSG_COMPLETE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 61) +#define SIR_HAL_EXIT_BMPS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 53) +#define SIR_HAL_EXIT_BMPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 54) +#define SIR_HAL_EXIT_BMPS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 55) +#define SIR_HAL_ENTER_BMPS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 56) +#define SIR_HAL_ENTER_BMPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 57) +#define SIR_HAL_BMPS_STATUS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 58) +#define SIR_HAL_MISSED_BEACON_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 59) + +#define SIR_HAL_SWITCH_CHANNEL_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 60) +#define SIR_HAL_PWR_SAVE_CFG (SIR_HAL_ITC_MSG_TYPES_BEGIN + 62) + +#define SIR_HAL_REGISTER_PE_CALLBACK (SIR_HAL_ITC_MSG_TYPES_BEGIN + 63) +#define SIR_HAL_SOFTMAC_MEM_READREQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 64) +#define SIR_HAL_SOFTMAC_MEM_WRITEREQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 65) + +#define SIR_HAL_SOFTMAC_MEM_READRESPONSE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 66) +#define SIR_HAL_SOFTMAC_BULKREGWRITE_CONFIRM (SIR_HAL_ITC_MSG_TYPES_BEGIN + 67) +#define SIR_HAL_SOFTMAC_BULKREGREAD_RESPONSE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 68) +#define SIR_HAL_SOFTMAC_HOSTMESG_MSGPROCESSRESULT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 69) + +#define SIR_HAL_ADDBA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 70) +#define SIR_HAL_ADDBA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 71) +#define SIR_HAL_DELBA_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 72) +#define SIR_HAL_DEL_BA_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 73) + +//message from sme to initiate delete block ack session. +#define SIR_HAL_DELBA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 74) +#define SIR_HAL_IBSS_STA_ADD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 75) +#define SIR_HAL_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 76) +#define SIR_HAL_SET_LINK_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 77) +#define SIR_HAL_ENTER_IMPS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 78) +#define SIR_HAL_ENTER_IMPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 79) +#define SIR_HAL_EXIT_IMPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 80) +#define SIR_HAL_EXIT_IMPS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 81) +#define SIR_HAL_SOFTMAC_HOSTMESG_PS_STATUS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 82) +#define SIR_HAL_POSTPONE_ENTER_IMPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 83) +#define SIR_HAL_STA_STAT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 84) +#define SIR_HAL_GLOBAL_STAT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 85) +#define SIR_HAL_AGGR_STAT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 86) +#define SIR_HAL_STA_STAT_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 87) +#define SIR_HAL_GLOBAL_STAT_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 88) +#define SIR_HAL_AGGR_STAT_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 89) +#define SIR_HAL_STAT_SUMM_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 90) +#define SIR_HAL_STAT_SUMM_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 92) +#define SIR_HAL_REMOVE_BSSKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 93) +#define SIR_HAL_REMOVE_BSSKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 94) +#define SIR_HAL_REMOVE_STAKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 95) +#define SIR_HAL_REMOVE_STAKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 96) +#define SIR_HAL_SET_STA_BCASTKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 97) +#define SIR_HAL_SET_STA_BCASTKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 98) +#define SIR_HAL_REMOVE_STA_BCASTKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 99) +#define SIR_HAL_REMOVE_STA_BCASTKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 100) +#define SIR_HAL_ADD_TS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 101) +#define SIR_HAL_DPU_MIC_ERROR (SIR_HAL_ITC_MSG_TYPES_BEGIN + 102) +#define SIR_HAL_TIMER_BA_ACTIVITY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 103) +#define SIR_HAL_TIMER_CHIP_MONITOR_TIMEOUT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 104) +#define SIR_HAL_TIMER_TRAFFIC_ACTIVITY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 105) +#define SIR_HAL_TIMER_ADC_RSSI_STATS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 106) +#define SIR_HAL_MIC_FAILURE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 107) +#define SIR_HAL_UPDATE_UAPSD_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 108) +#define SIR_HAL_SET_MIMOPS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 109) +#define SIR_HAL_SET_MIMOPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 110) +#define SIR_HAL_SYS_READY_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 111) +#define SIR_HAL_SET_TX_POWER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 112) +#define SIR_HAL_SET_TX_POWER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 113) +#define SIR_HAL_GET_TX_POWER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 114) +#define SIR_HAL_GET_TX_POWER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 115) +#define SIR_HAL_GET_NOISE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 116) +#define SIR_HAL_GET_NOISE_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 117) + +/* Messages to support transmit_halt and transmit_resume */ +#define SIR_HAL_TRANSMISSION_CONTROL_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 118) +/* Indication from LIM to HAL to Initialize radar interrupt */ +#define SIR_HAL_INIT_RADAR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 119) + +#define SIR_HAL_BEACON_PRE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 120) +#define SIR_HAL_ENTER_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 121) +#define SIR_HAL_ENTER_UAPSD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 122) +#define SIR_HAL_EXIT_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 123) +#define SIR_HAL_EXIT_UAPSD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 124) +#define SIR_HAL_LOW_RSSI_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 125) +#define SIR_HAL_BEACON_FILTER_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 126) +/// PE <-> HAL WOWL messages +#define SIR_HAL_WOWL_ADD_BCAST_PTRN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 127) +#define SIR_HAL_WOWL_DEL_BCAST_PTRN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 128) +#define SIR_HAL_WOWL_ENTER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 129) +#define SIR_HAL_WOWL_ENTER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 130) +#define SIR_HAL_WOWL_EXIT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 131) +#define SIR_HAL_WOWL_EXIT_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 132) +#define SIR_HAL_TX_COMPLETE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 133) +#define SIR_HAL_TIMER_RA_COLLECT_AND_ADAPT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 134) +/// PE <-> HAL statistics messages +#define SIR_HAL_GET_STATISTICS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 135) +#define SIR_HAL_GET_STATISTICS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 136) +#define SIR_HAL_SET_KEY_DONE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 137) + +/// PE <-> HAL BTC messages +#define SIR_HAL_BTC_SET_CFG (SIR_HAL_ITC_MSG_TYPES_BEGIN + 138) +#define SIR_HAL_SIGNAL_BT_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 139) +#define SIR_HAL_HANDLE_FW_MBOX_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 140) +#define SIR_HAL_SEND_PROBE_RSP_TMPL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 141) + +/* PE <-> HAL addr2 mismatch message */ +#define SIR_LIM_ADDR2_MISS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 142) +#ifdef FEATURE_OEM_DATA_SUPPORT +/* PE <-> HAL OEM_DATA RELATED MESSAGES */ +#define SIR_HAL_START_OEM_DATA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 143) +#define SIR_HAL_START_OEM_DATA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 144) +#define SIR_HAL_FINISH_OEM_DATA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 145) +#endif + +#define SIR_HAL_SET_MAX_TX_POWER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 146) +#define SIR_HAL_SET_MAX_TX_POWER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 147) + +#define SIR_HAL_SEND_MSG_COMPLETE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 148) + +/// PE <-> HAL Host Offload message +#define SIR_HAL_SET_HOST_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 149) + +#define SIR_HAL_ADD_STA_SELF_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 150) +#define SIR_HAL_ADD_STA_SELF_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 151) +#define SIR_HAL_DEL_STA_SELF_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 152) +#define SIR_HAL_DEL_STA_SELF_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 153) + +#define SIR_HAL_CFG_RXP_FILTER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 155) +#define SIR_HAL_CFG_RXP_FILTER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 156) + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define SIR_HAL_AGGR_ADD_TS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 157) +#define SIR_HAL_AGGR_ADD_TS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 158) +#define SIR_HAL_AGGR_QOS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 159) +#define SIR_HAL_AGGR_QOS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 160) +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* P2P <-> HAL P2P msg */ +#define SIR_HAL_SET_P2P_GO_NOA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 161) +#define SIR_HAL_P2P_NOA_ATTR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 162) +#define SIR_HAL_P2P_NOA_START_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 163) + +#define SIR_HAL_SET_LINK_STATE_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 165) + + +#define SIR_HAL_WLAN_SUSPEND_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 166) +#define SIR_HAL_WLAN_RESUME_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 167) + +/// PE <-> HAL Keep Alive message +#define SIR_HAL_SET_KEEP_ALIVE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 168) + +#ifdef WLAN_NS_OFFLOAD +#define SIR_HAL_SET_NS_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 169) +#endif //WLAN_NS_OFFLOAD + +#ifdef FEATURE_WLAN_SCAN_PNO +#define SIR_HAL_SET_PNO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 170) +#define SIR_HAL_SET_PNO_CHANGED_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 171) +#define SIR_HAL_UPDATE_SCAN_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 172) +#endif // FEATURE_WLAN_SCAN_PNO + + +#define SIR_HAL_SET_TX_PER_TRACKING_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 174) + +#ifdef WLAN_FEATURE_PACKET_FILTERING +#define SIR_HAL_8023_MULTICAST_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 175) +#define SIR_HAL_RECEIVE_FILTER_SET_FILTER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 176) +#define SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 177) +#define SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 178) +#define SIR_HAL_RECEIVE_FILTER_CLEAR_FILTER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 179) +#endif // WLAN_FEATURE_PACKET_FILTERING + +#define SIR_HAL_SET_POWER_PARAMS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 180) + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define SIR_HAL_GTK_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 181) +#define SIR_HAL_GTK_OFFLOAD_GETINFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 182) +#define SIR_HAL_GTK_OFFLOAD_GETINFO_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 183) +#endif //WLAN_FEATURE_GTK_OFFLOAD + +#ifdef FEATURE_WLAN_ESE +#define SIR_HAL_TSM_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 184) +#define SIR_HAL_TSM_STATS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 185) +#endif + + +#ifdef WLAN_WAKEUP_EVENTS +#define SIR_HAL_WAKE_REASON_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 186) +#endif //WLAN_WAKEUP_EVENTS + +#define SIR_HAL_SET_TM_LEVEL_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 187) + +#ifdef WLAN_FEATURE_11AC +#define SIR_HAL_UPDATE_OP_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 188) +#endif + +#ifdef FEATURE_WLAN_TDLS +/// PE <-> HAL TDLS messages +#define SIR_HAL_TDLS_LINK_ESTABLISH (SIR_HAL_ITC_MSG_TYPES_BEGIN + 189) +#define SIR_HAL_TDLS_LINK_TEARDOWN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 190) +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define SIR_HAL_ROAM_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 191) +#define SIR_HAL_ROAM_SCAN_OFFLOAD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 192) +#endif + +#define SIR_HAL_TRAFFIC_STATS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 195) + +#ifdef WLAN_FEATURE_11W +#define SIR_HAL_EXCLUDE_UNENCRYPTED_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 196) +#endif +#ifdef FEATURE_WLAN_TDLS +/// PE <-> HAL TDLS messages +#define SIR_HAL_TDLS_LINK_ESTABLISH_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 197) +#define SIR_HAL_TDLS_LINK_ESTABLISH_REQ_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 198) +#define SIR_HAL_TDLS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 199) +#endif + +#define SIR_HAL_UPDATE_CHAN_LIST_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 200) +#define SIR_HAL_STOP_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 201) +#define SIR_HAL_STOP_SCAN_OFFLOAD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 202) +#define SIR_HAL_RX_SCAN_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 203) +#define SIR_HAL_DHCP_START_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 204) +#define SIR_HAL_DHCP_STOP_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 205) +#define SIR_HAL_IBSS_PEER_INACTIVITY_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 206) + +#define SIR_HAL_LPHB_CONF_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 207) +#define SIR_HAL_LPHB_WAIT_EXPIRE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 208) + +#define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209) +#define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 210) + +#define SIR_HAL_RATE_UPDATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 217) + +#define SIR_HAL_FLUSH_LOG_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 218) + +#define SIR_HAL_GET_RSSI (SIR_HAL_ITC_MSG_TYPES_BEGIN + 219) + +#define SIR_HAL_SMPS_FORCE_MODE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 220) + +/* 221 unused */ + +#define SIR_HAL_START_ROAM_CANDIDATE_LOOKUP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 222) + +#define SIR_HAL_CLI_SET_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 223) +#define SIR_HAL_CLI_GET_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 224) +#ifndef REMOVE_PKT_LOG +#define SIR_HAL_PKTLOG_ENABLE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 225) +#endif +#ifdef FEATURE_WLAN_SCAN_PNO +#define SIR_HAL_SME_SCAN_CACHE_UPDATED (SIR_HAL_ITC_MSG_TYPES_BEGIN + 226) +#endif +#define SIR_HAL_START_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 227) +#define SIR_HAL_START_SCAN_OFFLOAD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 228) +#define SIR_HAL_UPDATE_CHAN_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 229) +#define SIR_CSA_OFFLOAD_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 231) + +#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 232) +#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 233) + +#ifdef WLAN_FEATURE_11AC +#define SIR_HAL_UPDATE_MEMBERSHIP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 235) +#define SIR_HAL_UPDATE_USERPOS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 236) +#endif + +#ifdef FEATURE_WLAN_TDLS +#define SIR_HAL_UPDATE_FW_TDLS_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237) +#define SIR_HAL_UPDATE_TDLS_PEER_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238) +#define SIR_HAL_TDLS_SHOULD_DISCOVER (SIR_HAL_ITC_MSG_TYPES_BEGIN + 239) +#define SIR_HAL_TDLS_SHOULD_TEARDOWN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 240) +#define SIR_HAL_TDLS_PEER_DISCONNECTED (SIR_HAL_ITC_MSG_TYPES_BEGIN + 241) +#endif + +/* Handling of beacon tx indication from FW */ +#define SIR_HAL_BEACON_TX_SUCCESS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 242) +#define SIR_HAL_DFS_RADAR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 243) + +#define SIR_HAL_INIT_THERMAL_INFO_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 248) +#define SIR_HAL_SET_THERMAL_LEVEL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 249) + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define SIR_HAL_SET_PLM_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 250) +#endif + +#define SIR_HAL_SET_TX_POWER_LIMIT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 251) +#define SIR_HAL_SET_SAP_INTRABSS_DIS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 252) +#define SIR_HAL_FW_STATS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 253) + +#define SIR_HAL_MODEM_POWER_STATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 254) + +#define SIR_HAL_DISASSOC_TX_COMP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 255) +#define SIR_HAL_DEAUTH_TX_COMP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 256) + +#ifdef WLAN_FEATURE_11AC +#define SIR_HAL_UPDATE_RX_NSS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 257) +#endif + +#define SIR_HAL_VDEV_STOP_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 258) + +#ifdef WLAN_FEATURE_STATS_EXT +#define SIR_HAL_STATS_EXT_REQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 259) +#define SIR_HAL_STATS_EXT_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 260) +#endif /* WLAN_FEATURE_STATS_EXT */ + +#define SIR_HAL_HIDE_SSID_VDEV_RESTART (SIR_HAL_ITC_MSG_TYPES_BEGIN + 261) + +#define SIR_HAL_VDEV_START_RSP_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 262) +#define SIR_HAL_GET_LINK_SPEED (SIR_HAL_ITC_MSG_TYPES_BEGIN + 263) + +#define SIR_HAL_ROAM_PREAUTH_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 264) + +#define SIR_HAL_TBTT_UPDATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 265) + +#ifdef FEATURE_WLAN_EXTSCAN +#define SIR_HAL_EXTSCAN_GET_CAPABILITIES_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 266) +#define SIR_HAL_EXTSCAN_START_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 267) +#define SIR_HAL_EXTSCAN_STOP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 268) +#define SIR_HAL_EXTSCAN_SET_BSS_HOTLIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 269) +#define SIR_HAL_EXTSCAN_RESET_BSS_HOTLIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 270) +#define SIR_HAL_EXTSCAN_SET_SIGNF_CHANGE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 271) +#define SIR_HAL_EXTSCAN_RESET_SIGNF_CHANGE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 272) +#define SIR_HAL_EXTSCAN_GET_CACHED_RESULTS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 273) +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef FEATURE_WLAN_CH_AVOID +#define SIR_HAL_CH_AVOID_UPDATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 274) +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +#define SIR_HAL_LL_STATS_CLEAR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 275) +#define SIR_HAL_LL_STATS_SET_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 276) +#define SIR_HAL_LL_STATS_GET_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 277) +#define SIR_HAL_LL_STATS_RESULTS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 278) +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_HAL_ROAM_OFFLOAD_SYNCH_CNF (SIR_HAL_ITC_MSG_TYPES_BEGIN + 279) +#endif +#ifdef WLAN_FEATURE_NAN +#define SIR_HAL_NAN_REQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 280) +#endif /* WLAN_FEATURE_NAN */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +#define SIR_HAL_SET_AUTO_SHUTDOWN_TIMER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 281) +#endif + +#define SIR_HAL_SET_BASE_MACADDR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 282) + +#define SIR_HAL_UNIT_TEST_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 283) + +#define SIR_HAL_LINK_STATUS_GET_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 285) +#define SIR_HAL_GET_LINK_STATUS_RSP_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 286) + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define SIR_HAL_CONFIG_EXT_WOW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 287) +#define SIR_HAL_CONFIG_APP_TYPE1_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 288) +#define SIR_HAL_CONFIG_APP_TYPE2_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 289) +#endif + +#define SIR_HAL_GET_TEMPERATURE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 290) +#define SIR_HAL_SET_SCAN_MAC_OUI_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 291) + +#ifdef DHCP_SERVER_OFFLOAD +#define SIR_HAL_SET_DHCP_SERVER_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 292) +#endif /* DHCP_SERVER_OFFLOAD */ +#define SIR_HAL_LED_FLASHING_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 293) + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_HAL_ROAM_OFFLOAD_SYNCH_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 294) +#endif + +#ifdef FEATURE_WLAN_TDLS +#define SIR_HAL_TDLS_SET_OFFCHAN_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 295) +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_HAL_ROAM_OFFLOAD_SYNCH_FAIL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 296) +#define SIR_HAL_ROAM_INVOKE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 297) +#endif +#define SIR_HAL_IPA_OFFLOAD_ENABLE_DISABLE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 298) + +#ifdef MDNS_OFFLOAD +#define SIR_HAL_SET_MDNS_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 299) +#define SIR_HAL_SET_MDNS_FQDN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 300) +#define SIR_HAL_SET_MDNS_RESPONSE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 301) +#define SIR_HAL_GET_MDNS_STATUS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 302) +#endif /* MDNS_OFFLOAD */ + +#ifdef SAP_AUTH_OFFLOAD +#define SIR_HAL_SET_SAP_AUTH_OFL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303) +#define SIR_HAL_SAP_OFL_ADD_STA (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304) +#define SIR_HAL_SAP_OFL_DEL_STA (SIR_HAL_ITC_MSG_TYPES_BEGIN + 305) +#define SIR_HAL_SET_CLIENT_BLOCK_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 306) +#endif + +#ifdef WLAN_FEATURE_APFIND +#define SIR_HAL_APFIND_SET_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 307) +#endif /* WLAN_FEATURE_APFIND */ + +#ifdef FEATURE_RUNTIME_PM +#define SIR_HAL_RUNTIME_PM_SUSPEND_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 308) +#define SIR_HAL_RUNTIME_PM_RESUME_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 309) +#endif + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define SIR_HAL_UPDATE_Q2Q_IE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 310) +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#define SIR_HAL_SET_MAS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 311) +#define SIR_HAL_SET_MIRACAST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 312) + +#define SIR_HAL_SET_EPNO_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313) +#define SIR_HAL_CONFIG_STATS_FACTOR (SIR_HAL_ITC_MSG_TYPES_BEGIN + 314) +#define SIR_HAL_CONFIG_GUARD_TIME (SIR_HAL_ITC_MSG_TYPES_BEGIN + 315) +#define SIR_HAL_SET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 316) +#define SIR_HAL_RESET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 317) +#define SIR_HAL_EXTSCAN_SET_SSID_HOTLIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 318) + +#define SIR_HAL_OCB_SET_CONFIG_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 319) +#define SIR_HAL_OCB_SET_UTC_TIME_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 320) +#define SIR_HAL_OCB_START_TIMING_ADVERT_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 321) +#define SIR_HAL_OCB_STOP_TIMING_ADVERT_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 322) +#define SIR_HAL_OCB_GET_TSF_TIMER_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 323) +#define SIR_HAL_DCC_GET_STATS_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 324) +#define SIR_HAL_DCC_CLEAR_STATS_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 325) +#define SIR_HAL_DCC_UPDATE_NDL_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 326) +#define SIR_HAL_FW_MEM_DUMP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 327) +#define SIR_HAL_START_STOP_LOGGING (SIR_HAL_ITC_MSG_TYPES_BEGIN + 328) +#define SIR_HAL_EXTSCAN_STATUS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 329) + +#define SIR_HAL_TSF_GPIO_PIN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 330) +#define SIR_HAL_SET_IE_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 331) + +#define SIR_HAL_BAD_PEER_TX_CTL_INI_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 332) +#define SIR_HAL_SET_RSSI_MONITOR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 333) +#define SIR_HAL_SET_PDEV_IE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 334) +#define SIR_HAL_EXTSCAN_OPERATION_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 335) + + +#define SIR_HAL_SET_UDP_RESP_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 336) + +#define SIR_HAL_UPDATE_WEP_DEFAULT_KEY (SIR_HAL_ITC_MSG_TYPES_BEGIN + 337) + +#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) + +// CFG message types +#define SIR_CFG_MSG_TYPES_BEGIN (SIR_CFG_MODULE_ID << 8) +#define SIR_CFG_ITC_MSG_TYPES_BEGIN (SIR_CFG_MSG_TYPES_BEGIN+0xB0) +#define SIR_CFG_PARAM_UPDATE_IND (SIR_CFG_ITC_MSG_TYPES_BEGIN) +#define SIR_CFG_DOWNLOAD_COMPLETE_IND (SIR_CFG_ITC_MSG_TYPES_BEGIN + 1) +#define SIR_CFG_MSG_TYPES_END (SIR_CFG_MSG_TYPES_BEGIN+0xFF) + +// LIM message types +#define SIR_LIM_MSG_TYPES_BEGIN (SIR_LIM_MODULE_ID << 8) +#define SIR_LIM_ITC_MSG_TYPES_BEGIN (SIR_LIM_MSG_TYPES_BEGIN+0xB0) + +// Messages to/from HAL +// Removed as part of moving HAL down to FW + +// Message from ISR upon TFP retry interrupt +#define SIR_LIM_RETRY_INTERRUPT_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 3) +// Message from BB Transport +#define SIR_BB_XPORT_MGMT_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 4) +// UNUSED SIR_LIM_ITC_MSG_TYPES_BEGIN + 6 +// Message from ISR upon SP's Invalid session key interrupt +#define SIR_LIM_INV_KEY_INTERRUPT_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 7) +// Message from ISR upon SP's Invalid key ID interrupt +#define SIR_LIM_KEY_ID_INTERRUPT_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 8) +// Message from ISR upon SP's Replay threshold reached interrupt +#define SIR_LIM_REPLAY_THRES_INTERRUPT_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 9) +// Message from HDD after the TD dummy packet is cleaned up +#define SIR_LIM_TD_DUMMY_CALLBACK_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xA) +// Message from SCH when the STA is ready to be deleted +#define SIR_LIM_SCH_CLEAN_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xB) +// Message from ISR upon Radar Detection +#define SIR_LIM_RADAR_DETECT_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xC) + +///////////////////////////////////// +// message id Available +//////////////////////////////////// + + +// Message from Hal to send out a DEL-TS indication +#define SIR_LIM_DEL_TS_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xE) +//Message from HAL to send BA global timer timeout +#define SIR_LIM_ADD_BA_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xF) +//Indication from HAL to delete all the BA sessions when the BA activity check timer is disabled +#define SIR_LIM_DEL_BA_ALL_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0x10) +//Indication from HAL to delete Station context +#define SIR_LIM_DELETE_STA_CONTEXT_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0x11) +//Indication from HAL to delete BA +#define SIR_LIM_DEL_BA_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0x12) +#define SIR_LIM_UPDATE_BEACON (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0x13) + + +/* LIM Time out messages */ +#define SIR_LIM_TIMEOUT_MSG_START ((SIR_LIM_MODULE_ID << 8) + 0xD0) +#define SIR_LIM_MIN_CHANNEL_TIMEOUT SIR_LIM_TIMEOUT_MSG_START +#define SIR_LIM_MAX_CHANNEL_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 1) +#define SIR_LIM_JOIN_FAIL_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 2) +#define SIR_LIM_AUTH_FAIL_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 3) +#define SIR_LIM_AUTH_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 4) +#define SIR_LIM_ASSOC_FAIL_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 5) +#define SIR_LIM_REASSOC_FAIL_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 6) +#define SIR_LIM_HEART_BEAT_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 7) +// currently unused SIR_LIM_TIMEOUT_MSG_START + 0x8 +// Link Monitoring Messages +#define SIR_LIM_CHANNEL_SCAN_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0xA) +#define SIR_LIM_PROBE_HB_FAILURE_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0xB) +#define SIR_LIM_ADDTS_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0xC) +#define SIR_LIM_LINK_TEST_DURATION_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x13) +#define SIR_LIM_HASH_MISS_THRES_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x16) +#define SIR_LIM_CNF_WAIT_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x17) +#define SIR_LIM_KEEPALIVE_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x18) +#define SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x19) +#define SIR_LIM_CHANNEL_SWITCH_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1A) +#define SIR_LIM_QUIET_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1B) +#define SIR_LIM_QUIET_BSS_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1C) + +#define SIR_LIM_WPS_OVERLAP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1D) +#ifdef WLAN_FEATURE_VOWIFI_11R +#define SIR_LIM_FT_PREAUTH_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1E) +#endif +#define SIR_LIM_REMAIN_CHN_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1F) +#define SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x20) + +#define SIR_LIM_BEACON_GEN_IND (SIR_LIM_TIMEOUT_MSG_START + 0x23) +#define SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x24) +#ifdef FEATURE_WLAN_ESE +#define SIR_LIM_ESE_TSM_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x25) +#endif + +#define SIR_LIM_DISASSOC_ACK_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x26) +#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) + +#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) + +#define SIR_LIM_MSG_TYPES_END (SIR_LIM_MSG_TYPES_BEGIN+0xFF) + +// SCH message types +#define SIR_SCH_MSG_TYPES_BEGIN (SIR_SCH_MODULE_ID << 8) +#define SIR_SCH_CHANNEL_SWITCH_REQUEST (SIR_SCH_MSG_TYPES_BEGIN) +#define SIR_SCH_START_SCAN_REQ (SIR_SCH_MSG_TYPES_BEGIN + 1) +#define SIR_SCH_START_SCAN_RSP (SIR_SCH_MSG_TYPES_BEGIN + 2) +#define SIR_SCH_END_SCAN_NTF (SIR_SCH_MSG_TYPES_BEGIN + 3) +#define SIR_SCH_MSG_TYPES_END (SIR_SCH_MSG_TYPES_BEGIN+0xFF) + +// PMM message types +#define SIR_PMM_MSG_TYPES_BEGIN (SIR_PMM_MODULE_ID << 8) +#define SIR_PMM_CHANGE_PM_MODE (SIR_PMM_MSG_TYPES_BEGIN) +#define SIR_PMM_CHANGE_IMPS_MODE (SIR_PMM_MSG_TYPES_BEGIN + 1) //for Idle mode power save +#define SIR_PMM_MSG_TYPES_END (SIR_PMM_MSG_TYPES_BEGIN+0xFF) + +// MNT message types +#define SIR_MNT_MSG_TYPES_BEGIN (SIR_MNT_MODULE_ID << 8) +#define SIR_MNT_RELEASE_BD (SIR_MNT_MSG_TYPES_BEGIN + 0) +#define SIR_MNT_MSG_TYPES_END (SIR_MNT_MSG_TYPES_BEGIN + 0xFF) + +// DVT message types +#define SIR_DVT_MSG_TYPES_BEGIN (SIR_DVT_MODULE_ID << 8) +#define SIR_DVT_ITC_MSG_TYPES_BEGIN (SIR_DVT_MSG_TYPES_BEGIN+0x0F) +#define SIR_DVT_MSG_TYPES_END (SIR_DVT_ITC_MSG_TYPES_BEGIN+0xFFF) + +//PTT message types +#define SIR_PTT_MSG_TYPES_BEGIN 0x3000 +#define SIR_PTT_MSG_TYPES_END 0x3300 + + +/* ****************************************** * + * * + * EVENT TYPE Definitions * + * * + * ****************************************** */ + +// MMH Events that are used in other modules to post events to MMH +# define SIR_HAL_MMH_TXMB_READY_EVT 0x00000002 +# define SIR_HAL_MMH_RXMB_DONE_EVT 0x00000004 +# define SIR_HAL_MMH_MSGQ_NE_EVT 0x00000008 + +# define SIR_HSTEMUL_TXMB_DONE_EVT 0x00000100 +# define SIR_HSTEMUL_RXMB_READY_EVT 0x00000200 +# define SIR_HSTEMUL_MSGQ_NE_EVT 0x00000400 + +# define SIR_TST_XMIT_MSG_QS_EMPTY_EVT 0x00000080 + +//added for OBSS + +//Param Change Bitmap sent to HAL +#define PARAM_BCN_INTERVAL_CHANGED (1 << 0) +#define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) +#define PARAM_SHORT_SLOT_TIME_CHANGED (1 << 2) +#define PARAM_llACOEXIST_CHANGED (1 << 3) +#define PARAM_llBCOEXIST_CHANGED (1 << 4) +#define PARAM_llGCOEXIST_CHANGED (1 << 5) +#define PARAM_HT20MHZCOEXIST_CHANGED (1<<6) +#define PARAM_NON_GF_DEVICES_PRESENT_CHANGED (1<<7) +#define PARAM_RIFS_MODE_CHANGED (1<<8) +#define PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED (1<<9) +#define PARAM_OBSS_MODE_CHANGED (1<<10) +#define PARAM_BEACON_UPDATE_MASK (PARAM_BCN_INTERVAL_CHANGED|PARAM_SHORT_PREAMBLE_CHANGED|PARAM_SHORT_SLOT_TIME_CHANGED|PARAM_llACOEXIST_CHANGED |PARAM_llBCOEXIST_CHANGED|\ + PARAM_llGCOEXIST_CHANGED|PARAM_HT20MHZCOEXIST_CHANGED|PARAM_NON_GF_DEVICES_PRESENT_CHANGED|PARAM_RIFS_MODE_CHANGED|PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED| PARAM_OBSS_MODE_CHANGED) + + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sysGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sysGlobal.h new file mode 100644 index 000000000000..375df2221f98 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sysGlobal.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef __SYS_GLOBAL_H__ +#define __SYS_GLOBAL_H__ + +typedef struct sAniSirSys +{ + tANI_U32 abort; /* system is aborting and will be unloaded, only MMH thread is running */ + + tANI_U32 gSysFrameCount[4][16]; + tANI_U32 gSysBbtReceived; + tANI_U32 gSysBbtPostedToLim; + tANI_U32 gSysBbtPostedToSch; + tANI_U32 gSysBbtPostedToPmm; + tANI_U32 gSysBbtPostedToHal; + tANI_U32 gSysBbtDropped; + tANI_U32 gSysBbtNonLearnFrameInv; + tANI_U32 gSysBbtLearnFrameInv; + tANI_U32 gSysBbtCrcFail; + tANI_U32 gSysBbtDuplicates; + tANI_U32 gSysReleaseCount; + tANI_U32 probeError, probeBadSsid, probeIgnore, probeRespond; + + tANI_U32 gSysEnableLearnMode; + tANI_U32 gSysEnableScanMode; + tANI_U32 gSysEnableLinkMonitorMode; +} tAniSirSys, *tpAniSirSys; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsApi.h new file mode 100644 index 000000000000..e130f969b104 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsApi.h @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * + * Author: Kevin Nguyen + * Date: 02/27/02 + * History:- + * 02/12/02 Created. + * -------------------------------------------------------------------- + * + */ + +#ifndef __UTILSAPI_H +#define __UTILSAPI_H + +#include +#include +#include "aniGlobal.h" +#include "utilsGlobal.h" +#include "VossWrapper.h" + +#define LOG_INDEX_FOR_MODULE( modId ) ( ( modId ) - LOG_FIRST_MODULE_ID ) +#define GET_MIN_VALUE(__val1, __val2) ((__val1 < __val2) ? __val1 : __val2) + +// The caller must check loglevel. This API assumes loglevel is good +extern void logDebug(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 debugLevel, const char *pStr, va_list marker); + +extern void logDbg(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 debugLevel, const char *pStr,...); + +extern tANI_U32 gPktAllocCnt, gPktFreeCnt; + +extern VOS_TRACE_LEVEL getVosDebugLevel(tANI_U32 debugLevel); + +/// Debug dumps +extern void logPrintf(tpAniSirGlobal, tANI_U32, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4); + +/// RTAI dump +extern int logRtaiDump(tpAniSirGlobal, tANI_U32, tANI_U32, tANI_U32, tANI_U32, tANI_U32, tANI_U8 *); + +/// Log initialization +extern tSirRetStatus logInit (tpAniSirGlobal); + +extern void +logDeinit(tpAniSirGlobal ); + +extern tSirRetStatus cfgInit(tpAniSirGlobal); +extern void cfgDeInit(tpAniSirGlobal); + +// ------------------------------------------------------------------- +/** + * sirDumpBuf() + * + * FUNCTION: + * This function is called to dump a buffer with a certain level + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param pBuf: buffer pointer + * @return None. + */ + +void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size); + + +// -------------------------------------------------------------------- +/** + * sirSwapU16() + * + * FUNCTION: + * This function is called to swap two U8s of an tANI_U16 value + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val tANI_U16 value to be tANI_U8 swapped + * @return Swapped tANI_U16 value + */ + +static inline tANI_U16 +sirSwapU16(tANI_U16 val) +{ + return(((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8)); +}/*** end sirSwapU16() ***/ + +// -------------------------------------------------------------------- +/** + * sirSwapU16ifNeeded() + * + * FUNCTION: + * This function is called to swap two U8s of an tANI_U16 value depending + * on endianness of the target processor/compiler the software is + * running on + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val tANI_U16 value to be tANI_U8 swapped + * @return Swapped tANI_U16 value + */ + +static inline tANI_U16 +sirSwapU16ifNeeded(tANI_U16 val) +{ +#ifndef ANI_LITTLE_BYTE_ENDIAN + return sirSwapU16(val); +#else + return val; +#endif +}/*** end sirSwapU16ifNeeded() ***/ + +// -------------------------------------------------------------------- +/** + * sirSwapU32() + * + * FUNCTION: + * This function is called to swap four U8s of an tANI_U32 value + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val tANI_U32 value to be tANI_U8 swapped + * @return Swapped tANI_U32 value + */ + +static inline tANI_U32 +sirSwapU32(tANI_U32 val) +{ + return((val << 24) | + (val >> 24) | + ((val & 0x0000FF00) << 8) | + ((val & 0x00FF0000) >> 8)); +}/*** end sirSwapU32() ***/ + +// -------------------------------------------------------------------- +/** + * sirSwapU32ifNeeded() + * + * FUNCTION: + * This function is called to swap U8s of an tANI_U32 value depending + * on endianness of the target processor/compiler the software is + * running on + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val tANI_U32 value to be tANI_U8 swapped + * @return Swapped tANI_U32 value + */ + +static inline tANI_U32 +sirSwapU32ifNeeded(tANI_U32 val) +{ +#ifndef ANI_LITTLE_BYTE_ENDIAN + return sirSwapU32(val); +#else + return val; +#endif +}/*** end sirSwapU32ifNeeded() ***/ + + + + +// ------------------------------------------------------------------- +/** + * sirSwapU32Buf + * + * FUNCTION: + * It swaps N dwords into the same buffer + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of tANI_U32 array + * @return void + * + */ + +static inline void +sirSwapU32Buf(tANI_U32 *ptr, tANI_U32 nWords) +{ + tANI_U32 i; + + for (i=0; i < nWords; i++) + ptr[i] = sirSwapU32(ptr[i]); +} + +// -------------------------------------------------------------------- +/** + * sirSwapU32BufIfNeeded() + * + * FUNCTION: + * This function is called to swap U8s of U32s in the buffer depending + * on endianness of the target processor/compiler the software is + * running on + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param pBuf Buffer that will get swapped + * @param nWords Number DWORDS will be swapped + * @return void + */ + +static inline void +sirSwapU32BufIfNeeded(tANI_U32* pBuf, tANI_U32 nWords) +{ +#ifdef ANI_LITTLE_BYTE_ENDIAN + sirSwapU32Buf(pBuf, nWords); +#endif +}/*** end sirSwapU32ifNeeded() ***/ + + +// -------------------------------------------------------------------- +/** + * sirSwapBDIfNeeded + * + * FUNCTION: + * Byte swap all the dwords in the BD, except the PHY/MAC headers + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param pBd BD that will get swapped + * @return void + */ + +static inline void +sirSwapBDIfNeeded(tANI_U32 *pBd) +{ + sirSwapU32BufIfNeeded(pBd, 6); + sirSwapU32BufIfNeeded(pBd+18, 14); +} + + +// ------------------------------------------------------------------- +/** + * sirStoreU16N + * + * FUNCTION: + * It stores a 16 bit number into the byte array in network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of destination byte array + * @param val value to store + * @return None + */ + +static inline void +sirStoreU16N(tANI_U8 *ptr, tANI_U16 val) +{ + *ptr++ = (val >> 8) & 0xff; + *ptr = val & 0xff; +} + +// ------------------------------------------------------------------- +/** + * sirStoreU32N + * + * FUNCTION: + * It stores a 32 bit number into the byte array in network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of destination byte array + * @param val value to store + * @return None + */ + +static inline void +sirStoreU32N(tANI_U8 *ptr, tANI_U32 val) +{ + *ptr++ = (tANI_U8) (val >> 24) & 0xff; + *ptr++ = (tANI_U8) (val >> 16) & 0xff; + *ptr++ = (tANI_U8) (val >> 8) & 0xff; + *ptr = (tANI_U8) (val) & 0xff; +} + +// ------------------------------------------------------------------- +/** + * sirStoreU16 + * + * FUNCTION: + * It stores a 16 bit number into the byte array in NON-network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of destination byte array + * @param val value to store + * @return None + */ + +static inline void +sirStoreU16(tANI_U8 *ptr, tANI_U16 val) +{ + *ptr++ = val & 0xff; + *ptr = (val >> 8) & 0xff; +} + +// ------------------------------------------------------------------- +/** + * sirStoreU32 + * + * FUNCTION: + * It stores a 32 bit number into the byte array in NON-network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of destination byte array + * @param val value to store + * @return None + */ + +static inline void +sirStoreU32(tANI_U8 *ptr, tANI_U32 val) +{ + *ptr++ = (tANI_U8) val & 0xff; + *ptr++ = (tANI_U8) (val >> 8) & 0xff; + *ptr++ = (tANI_U8) (val >> 16) & 0xff; + *ptr = (tANI_U8) (val >> 24) & 0xff; +} + +// ------------------------------------------------------------------- +/** + * sirStoreU32BufN + * + * FUNCTION: + * It stores a 32 bit number into the byte array in network byte order + * i.e. the least significant byte first. It performs the above operation + * on entire buffer and writes to the dst buffer + * + * LOGIC: + * + * ASSUMPTIONS: + * Assumes that the pSrc buffer is of all tANI_U32 data type fields. + * + * NOTE: + * Must be used if all the fields in the buffer must be of tANI_U32 types. + * + * @param pDst address of destination byte array + * @param pSrc address of the source DWORD array + * @param length number of DWORDs + * @return None + */ + +static inline void +sirStoreBufN(tANI_U8* pDst, tANI_U32* pSrc, tANI_U32 length) +{ + while (length) + { + sirStoreU32N(pDst, *pSrc); + pDst += 4; + pSrc++; + length--; + } +} + +// ------------------------------------------------------------------- +/** + * sirReadU16N + * + * FUNCTION: + * It reads a 16 bit number from the byte array in network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of byte array + * @return 16 bit value + */ + +static inline tANI_U16 +sirReadU16N(tANI_U8 *ptr) +{ + return(((*ptr) << 8) | + (*(ptr+1))); +} +/** + * sirSwapU32Buf + * + * FUNCTION: + * It swaps N dwords into the same buffer + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of tANI_U32 array + * @return void + * + */ + +static inline void +sirSwapNStore(tANI_U32 *src, tANI_U32 *dst, tANI_U32 nWords) +{ + tANI_U32 i; + + for (i=0; i < nWords; i++) + dst[i] = sirSwapU32(src[i]); +} + +// ------------------------------------------------------------------- +/** + * sirReadU32N + * + * FUNCTION: + * It reads a 32 bit number from the byte array in network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of byte array + * @return 32 bit value + */ + +static inline tANI_U32 +sirReadU32N(tANI_U8 *ptr) +{ + return((*(ptr) << 24) | + (*(ptr+1) << 16) | + (*(ptr+2) << 8) | + (*(ptr+3))); +} + +// ------------------------------------------------------------------- +/** + * sirReadU16 + * + * FUNCTION: + * It reads a 16 bit number from the byte array in NON-network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of byte array + * @return 16 bit value + */ + +static inline tANI_U16 +sirReadU16(tANI_U8 *ptr) +{ + return((*ptr) | + (*(ptr+1) << 8)); +} + +// ------------------------------------------------------------------- +/** + * sirReadU32 + * + * FUNCTION: + * It reads a 32 bit number from the byte array in NON-network byte order + * i.e. the least significant byte first + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of byte array + * @return 32 bit value + */ + +static inline tANI_U32 +sirReadU32(tANI_U8 *ptr) +{ + return((*(ptr)) | + (*(ptr+1) << 8) | + (*(ptr+2) << 16) | + (*(ptr+3) << 24)); +} + +// ------------------------------------------------------------------- + + +/// Copy a MAC address from 'from' to 'to' +static inline void +sirCopyMacAddr(tANI_U8 to[], tANI_U8 from[]) +{ +#if defined( _X86_ ) + tANI_U32 align = (0x3 & ((tANI_U32) to | (tANI_U32) from )); + if( align ==0){ + *((tANI_U16 *) &(to[4])) = *((tANI_U16 *) &(from[4])); + *((tANI_U32 *) to) = *((tANI_U32 *) from); + }else if (align == 2){ + *((tANI_U16 *) &to[4]) = *((tANI_U16 *) &from[4]); + *((tANI_U16 *) &to[2]) = *((tANI_U16 *) &from[2]); + *((tANI_U16 *) &to[0]) = *((tANI_U16 *) &from[0]); + }else{ + to[5] = from[5]; + to[4] = from[4]; + to[3] = from[3]; + to[2] = from[2]; + to[1] = from[1]; + to[0] = from[0]; + } +#else + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; +#endif +} + +static inline tANI_U8 +sirCompareMacAddr(tANI_U8 addr1[], tANI_U8 addr2[]) +{ +#if defined( _X86_ ) + tANI_U32 align = (0x3 & ((tANI_U32) addr1 | (tANI_U32) addr2 )); + + if( align ==0){ + return ((*((tANI_U16 *) &(addr1[4])) == *((tANI_U16 *) &(addr2[4])))&& + (*((tANI_U32 *) addr1) == *((tANI_U32 *) addr2))); + }else if(align == 2){ + return ((*((tANI_U16 *) &addr1[4]) == *((tANI_U16 *) &addr2[4])) && + (*((tANI_U16 *) &addr1[2]) == *((tANI_U16 *) &addr2[2])) && + (*((tANI_U16 *) &addr1[0]) == *((tANI_U16 *) &addr2[0]))); + }else{ + return ( (addr1[5]==addr2[5])&& + (addr1[4]==addr2[4])&& + (addr1[3]==addr2[3])&& + (addr1[2]==addr2[2])&& + (addr1[1]==addr2[1])&& + (addr1[0]==addr2[0])); + } +#else + return ( (addr1[0]==addr2[0])&& + (addr1[1]==addr2[1])&& + (addr1[2]==addr2[2])&& + (addr1[3]==addr2[3])&& + (addr1[4]==addr2[4])&& + (addr1[5]==addr2[5])); +#endif +} + + +/* +* converts tANI_U16 CW value to 4 bit value to be inserted in IE +*/ +static inline tANI_U8 convertCW(tANI_U16 cw) +{ + tANI_U8 val = 0; + while (cw > 0) + { + val++; + cw >>= 1; + } + if (val > 15) + return 0xF; + return val; +} + +/* The user priority to AC mapping is such: + * UP(1, 2) ---> AC_BK(1) + * UP(0, 3) ---> AC_BE(0) + * UP(4, 5) ---> AC_VI(2) + * UP(6, 7) ---> AC_VO(3) + */ +#define WLAN_UP_TO_AC_MAP 0x33220110 +#define upToAc(up) ((WLAN_UP_TO_AC_MAP >> ((up) << 2)) & 0x03) + + +// ------------------------------------------------------------------- + +/// Parse the next IE in a message +extern tSirRetStatus sirParseNextIE(tpAniSirGlobal, tANI_U8 *pPayload, + tANI_U16 payloadLength, tANI_S16 lastType, + tANI_U8 *pType, tANI_U8 *pLength); + +/// Check if the given channel is 11b channel +#define SIR_IS_CHANNEL_11B(chId) (chId <= 14) + +// ------------------------------------------------------------------- +/** + * halRoundS32 + * + * FUNCTION: + * Performs integer rounding like returns 12346 for 123456 or -12346 for -123456 + * Note that a decimal place is lost. + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param tANI_S32 input + * @return rounded number + */ +static inline tANI_S32 +halRoundS32(tANI_S32 p) +{ + tANI_S32 k, i, j; + + i = p/10; + j = p%10; + if (p > 0) + k = i + (j > 4 ? 1 : 0); + else if (p < 0) + k = i + (j < -5 ? -1 : 0); + else + k = p; + + return(k); +} + +/* New functions for endianness conversion */ +#ifdef ANI_LITTLE_BYTE_ENDIAN +#define ani_cpu_to_be16(x) sirSwapU16((x)) +#define ani_cpu_to_le16(x) (x) +#define ani_cpu_to_be32(x) sirSwapU32((x)) +#define ani_cpu_to_le32(x) (x) +#else // ANI_LITTLE_BYTE_ENDIAN +#define ani_cpu_to_be16(x) (x) +#define ani_cpu_to_le16(x) sirSwapU16((x)) +#define ani_cpu_to_be32(x) (x) +#define ani_cpu_to_le32(x) sirSwapU32((x)) +#endif // ANI_LITTLE_BYTE_ENDIAN + +#define ani_le16_to_cpu(x) ani_cpu_to_le16(x) +#define ani_le32_to_cpu(x) ani_cpu_to_le32(x) +#define ani_be16_to_cpu(x) ani_cpu_to_be16(x) +#define ani_be32_to_cpu(x) ani_cpu_to_be32(x) + +void ConverttoBigEndian(void *ptr, tANI_U16 size); +void CreateScanCtsFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, tSirMacAddr selfMac); +void CreateScanDataNullFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, + tANI_U8 pwrMgmt, tSirMacAddr bssid, + tSirMacAddr selfMacAddr); +void CreateInitScanRawFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, tBssSystemRole role); +void CreateFinishScanRawFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, tBssSystemRole role); + +#endif /* __UTILSAPI_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsGlobal.h new file mode 100644 index 000000000000..e700ff92819d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/utilsGlobal.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __UTILS_GLOBAL_H__ +#define __UTILS_GLOBAL_H__ + +#include "sirParams.h" + +/* + * Current debug and event log level + */ +#define LOG_FIRST_MODULE_ID SIR_FIRST_MODULE_ID +#define LOG_LAST_MODULE_ID SIR_LAST_MODULE_ID +#define LOG_ENTRY_NUM (LOG_LAST_MODULE_ID - LOG_FIRST_MODULE_ID + 1) + +typedef struct sAniSirUtils +{ + tANI_U32 gLogEvtLevel[LOG_ENTRY_NUM]; + tANI_U32 gLogDbgLevel[LOG_ENTRY_NUM]; + +} tAniSirUtils, *tpAniSirUtils; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limAdmitControl.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limAdmitControl.h new file mode 100644 index 000000000000..e1cecd63d900 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limAdmitControl.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Dinesh Upadhyay + * Date: 10/24/06 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __LIM_ADMIT_CONTROL_H__ +#define __LIM_ADMIT_CONTROL_H__ + +#include "sirCommon.h" +#include "sirMacProtDef.h" + +#include "aniGlobal.h" + +tSirRetStatus +limTspecFindByAssocId(tpAniSirGlobal, tANI_U16, tSirMacTspecIE*, tpLimTspecInfo, tpLimTspecInfo *); + +// Add TSPEC in lim local table +tSirRetStatus limTspecAdd( + tpAniSirGlobal pMac, + tANI_U8 *pAddr, + tANI_U16 assocId, + tSirMacTspecIE *pTspec, + tANI_U32 interval, + tpLimTspecInfo *ppInfo); + + +// admit control interface +extern tSirRetStatus +limAdmitControlAddTS( + tpAniSirGlobal pMac, + tANI_U8 *pAddr, + tSirAddtsReqInfo *addts, + tSirMacQosCapabilityStaIE *qos, + tANI_U16 assocId, + tANI_U8 alloc, + tSirMacScheduleIE *pSch, + tANI_U8 *pTspecIdx ,//index to the lim tspec table. + tpPESession psessionEntry + ); + +static inline tSirRetStatus +limAdmitControlAddSta( + tpAniSirGlobal pMac, + tANI_U8 *staAddr, + tANI_U8 alloc) +{ return eSIR_SUCCESS;} + +extern tSirRetStatus +limAdmitControlDeleteSta( + tpAniSirGlobal pMac, + tANI_U16 assocId); + +extern tSirRetStatus +limAdmitControlDeleteTS( + tpAniSirGlobal pMac, + tANI_U16 assocId, + tSirMacTSInfo *tsinfo, + tANI_U8 *tsStatus, + tANI_U8 *tspecIdx); + +extern tSirRetStatus +limUpdateAdmitPolicy( + tpAniSirGlobal pMac); + +tSirRetStatus limAdmitControlInit(tpAniSirGlobal pMac); +#ifdef FEATURE_WLAN_ESE +tSirRetStatus limSendHalMsgAddTs(tpAniSirGlobal pMac, + tANI_U16 staIdx, + tANI_U8 tspecIdx, + tSirMacTspecIE tspecIE, + tANI_U8 sessionId, + tANI_U16 tsm_interval); +#else +tSirRetStatus limSendHalMsgAddTs(tpAniSirGlobal pMac, + tANI_U16 staIdx, + tANI_U8 tspecIdx, + tSirMacTspecIE tspecIE, + tANI_U8 sessionId); +#endif + +tSirRetStatus limSendHalMsgDelTs(tpAniSirGlobal pMac, + tANI_U16 staIdx, + tANI_U8 tspecIdx, + tSirDeltsReqInfo delts, + tANI_U8 sessionId, + tANI_U8 *bssId); +void limProcessHalAddTsRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h new file mode 100644 index 000000000000..45a6e1cb3e39 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limApi.h contains the definitions exported by + * LIM module. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __LIM_API_H +#define __LIM_API_H +#include "wniApi.h" +#include "sirApi.h" +#include "aniGlobal.h" +#include "sirMacProtDef.h" +#include "sirCommon.h" +#include "sirDebug.h" +#include "schGlobal.h" +#include "utilsApi.h" +#include "limGlobal.h" +#include "halMsgApi.h" +#include "wlan_qct_wda.h" + +/* Macro to count heartbeat */ +#define limResetHBPktCount(psessionEntry) (psessionEntry->LimRxedBeaconCntDuringHB = 0) + +/* Useful macros for fetching various states in pMac->lim */ +/* gLimSystemRole */ +#define GET_LIM_SYSTEM_ROLE(psessionEntry) (psessionEntry->limSystemRole) +#define LIM_IS_UNKNOWN_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_UNKNOWN_ROLE) +#define LIM_IS_AP_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_AP_ROLE) +#define LIM_IS_BT_AMP_AP_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_BT_AMP_AP_ROLE) +#define LIM_IS_BT_AMP_STA_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_BT_AMP_STA_ROLE) +#define LIM_IS_STA_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_STA_ROLE) +#define LIM_IS_IBSS_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_STA_IN_IBSS_ROLE) +#define LIM_IS_P2P_DEVICE_ROLE(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_P2P_DEVICE_ROLE) +#define LIM_IS_P2P_DEVICE_GO(psessionEntry) \ + (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_P2P_DEVICE_GO) +/* gLimSmeState */ +#define GET_LIM_SME_STATE(pMac) (pMac->lim.gLimSmeState) +#define SET_LIM_SME_STATE(pMac, state) (pMac->lim.gLimSmeState = state) +/* gLimMlmState */ +#define GET_LIM_MLM_STATE(pMac) (pMac->lim.gLimMlmState) +#define SET_LIM_MLM_STATE(pMac, state) (pMac->lim.gLimMlmState = state) +/*tpdphHashNode mlmStaContext*/ +#define GET_LIM_STA_CONTEXT_MLM_STATE(pStaDs) (pStaDs->mlmStaContext.mlmState) +#define SET_LIM_STA_CONTEXT_MLM_STATE(pStaDs, state) (pStaDs->mlmStaContext.mlmState = state) +/* gLimQuietState */ +#define GET_LIM_QUIET_STATE(pMac) (pMac->lim.gLimSpecMgmt.quietState) +#define SET_LIM_QUIET_STATE(pMac, state) (pMac->lim.gLimSpecMgmt.quietState = state) +#define LIM_IS_CONNECTION_ACTIVE(psessionEntry) (psessionEntry->LimRxedBeaconCntDuringHB) +/*pMac->lim.gLimProcessDefdMsgs*/ +#define GET_LIM_PROCESS_DEFD_MESGS(pMac) (pMac->lim.gLimProcessDefdMsgs) +#define SET_LIM_PROCESS_DEFD_MESGS(pMac, val) (pMac->lim.gLimProcessDefdMsgs = val) +// LIM exported function templates +#define LIM_IS_RADAR_DETECTED(pMac) (pMac->lim.gLimSpecMgmt.fRadarDetCurOperChan) +#define LIM_SET_RADAR_DETECTED(pMac, val) (pMac->lim.gLimSpecMgmt.fRadarDetCurOperChan = val) +#define LIM_MIN_BCN_PR_LENGTH 12 +#define LIM_BCN_PR_CAPABILITY_OFFSET 10 +typedef enum eMgmtFrmDropReason +{ + eMGMT_DROP_NO_DROP, + eMGMT_DROP_NOT_LAST_IBSS_BCN, + eMGMT_DROP_INFRA_BCN_IN_IBSS, + eMGMT_DROP_SCAN_MODE_FRAME, + eMGMT_DROP_NON_SCAN_MODE_FRAME, + eMGMT_DROP_INVALID_SIZE, + eMGMT_DROP_SPURIOUS_FRAME, +}tMgmtFrmDropReason; + + +/** + * Function to initialize LIM state machines. + * This called upon LIM thread creation. + */ +extern tSirRetStatus limInitialize(tpAniSirGlobal); +tSirRetStatus peOpen(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam); +tSirRetStatus peClose(tpAniSirGlobal pMac); +tSirRetStatus limStart(tpAniSirGlobal pMac); +tSirRetStatus peStart(tpAniSirGlobal pMac); +void peStop(tpAniSirGlobal pMac); +tSirRetStatus pePostMsgApi(tpAniSirGlobal pMac, tSirMsgQ* pMsg); +tSirRetStatus peProcessMsg(tpAniSirGlobal pMac, tSirMsgQ* limMsg); +void limDumpInit(tpAniSirGlobal pMac); +/** + * Function to clean up LIM state. + * This called upon reset/persona change etc + */ +extern void limCleanup(tpAniSirGlobal); +/// Function to post messages to LIM thread +extern tANI_U32 limPostMsgApi(tpAniSirGlobal, tSirMsgQ *); +/** + * Function to process messages posted to LIM thread + * and dispatch to various sub modules within LIM module. + */ +extern void limMessageProcessor(tpAniSirGlobal, tpSirMsgQ); +extern void limProcessMessages(tpAniSirGlobal, tpSirMsgQ); // DT test alt deferred 2 +/** + * Function to check the LIM state if system is in Scan/Learn state. + */ +extern tANI_U8 limIsSystemInScanState(tpAniSirGlobal); +/** + * Function to handle IBSS coalescing. + * Beacon Processing module to call this. + */ +extern tSirRetStatus limHandleIBSScoalescing(tpAniSirGlobal, + tpSchBeaconStruct, + tANI_U8 *,tpPESession); +/// Function used by other Sirius modules to read global SME state + static inline tLimSmeStates +limGetSmeState(tpAniSirGlobal pMac) { return pMac->lim.gLimSmeState; } +extern void limReceivedHBHandler(tpAniSirGlobal, tANI_U8, tpPESession); +extern void limCheckAndQuietBSS(tpAniSirGlobal); +/// Function that triggers STA context deletion +extern void limTriggerSTAdeletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry); + +#ifdef FEATURE_WLAN_TDLS +// Function that sends TDLS Del Sta indication to SME +extern void limSendSmeTDLSDelStaInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry, tANI_U16 reasonCode); +#endif + +/// Function that checks for change in AP's capabilties on STA +extern void limDetectChangeInApCapabilities(tpAniSirGlobal, + tpSirProbeRespBeacon,tpPESession); +tSirRetStatus limUpdateShortSlot(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeacon, + tpUpdateBeaconParams pBeaconParams,tpPESession); + +/// creates an addts request action frame and sends it out to staid +extern void limSendAddtsReq (tpAniSirGlobal pMac, tANI_U16 staid, tANI_U8 tsid, tANI_U8 userPrio, tANI_U8 wme); +/// creates a delts request action frame and sends it out to staid +extern void limSendDeltsReq (tpAniSirGlobal pMac, tANI_U16 staid, tANI_U8 tsid, tANI_U8 userPrio, tANI_U8 wme); +#ifdef WLAN_FEATURE_11AC +extern ePhyChanBondState limGet11ACPhyCBState(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 htSecondaryChannelOffset, tANI_U8 CenterChan,tpPESession ); +#endif +tANI_U8 limIsSystemInActiveState(tpAniSirGlobal pMac); + +void limHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void limPsOffloadHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void +limSendHeartBeatTimeoutInd(tpAniSirGlobal pMac, tpPESession psessionEntry); +tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U32 subType); +bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info); +#ifdef WLAN_FEATURE_11W +bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info); +#endif +void limMicFailureInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void limRoamOffloadSynchInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +#endif +void lim_update_lost_link_info(tpAniSirGlobal mac, tpPESession session, + int8_t rssi); +/* ----------------------------------------------------------------------- */ +// These used to be in DPH +extern void limGetMyMacAddr(tpAniSirGlobal pMac, tANI_U8 *mac); +#define limGetQosMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limQosEnabled) +#define limGetWmeMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWmeEnabled) +#define limGetWsmMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWsmEnabled) +#define limGet11dMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->lim11dEnabled) +#define limGetAckPolicy(pMac, pVal) (*(pVal) = pMac->lim.ackPolicy) +/* ----------------------------------------------------------------------- */ +static inline void limGetPhyMode(tpAniSirGlobal pMac, tANI_U32 *phyMode, tpPESession psessionEntry) +{ + *phyMode = psessionEntry ? psessionEntry->gLimPhyMode : pMac->lim.gLimPhyMode; +} + +/* ----------------------------------------------------------------------- */ +static inline void limGetRfBand(tpAniSirGlobal pMac, tSirRFBand *band, tpPESession psessionEntry) +{ + *band = psessionEntry ? psessionEntry->limRFBand : SIR_BAND_UNKNOWN; +} + +/*-------------------------------------------------------------------------- + + \brief peProcessMessages() - Message Processor for PE + + Voss calls this function to dispatch the message to PE + + \param pMac - Pointer to Global MAC structure + \param pMsg - Pointer to the message structure + + \return tANI_U32 - TX_SUCCESS for success. + + --------------------------------------------------------------------------*/ +tSirRetStatus peProcessMessages(tpAniSirGlobal pMac, tSirMsgQ* pMsg); +/** ------------------------------------------------------------- +\fn peFreeMsg +\brief Called by VOS scheduler (function vos_sched_flush_mc_mqs) +\ to free a given PE message on the TX and MC thread. +\ This happens when there are messages pending in the PE +\ queue when system is being stopped and reset. +\param tpAniSirGlobal pMac +\param tSirMsgQ pMsg +\return none +-----------------------------------------------------------------*/ +v_VOID_t peFreeMsg( tpAniSirGlobal pMac, tSirMsgQ* pMsg); + +/*-------------------------------------------------------------------------- + + \brief limRemainOnChnRsp() - API for sending remain on channel response. + + LIM calls this api to send the remain on channel response to SME. + + \param pMac - Pointer to Global MAC structure + \param status - status of the response + \param data - pointer to msg + + \return void + + --------------------------------------------------------------------------*/ +void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); + +/*-------------------------------------------------------------------------- + + \brief limProcessAbortScanInd() - function for sending abort scan indication. + + LIM calls this function for sending abort scan indication. + + \param pMac - Pointer to Global MAC structure + + \return void + + --------------------------------------------------------------------------*/ +void limProcessAbortScanInd(tpAniSirGlobal pMac, tANI_U8 sessionId); + +void lim_smps_force_mode_ind(tpAniSirGlobal mac_ctx, tpSirMsgQ msg); + +/************************************************************/ +#endif /* __LIM_API_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFT.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFT.h new file mode 100644 index 000000000000..1f81bf8d293f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFT.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if defined WLAN_FEATURE_VOWIFI_11R +/**========================================================================= + + Macros and Function prototypes FT and 802.11R purposes + + ========================================================================*/ + +#ifndef __LIMFT_H__ +#define __LIMFT_H__ + + +#include +#include +#include +#include +#include + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +void limFTOpen(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limFTCleanup(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limFTCleanupPreAuthInfo(tpAniSirGlobal pMac, tpPESession psessionEntry); +int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void limPerformFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, + tpPESession psessionEntry); +void limPerformPostFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, + tpPESession psessionEntry); +void limFTResumeLinkCb(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); +void limPostFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status, + tANI_U8 *auth_rsp, tANI_U16 auth_rsp_length, + tpPESession psessionEntry); +void limHandleFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status, + tANI_U8 *auth_rsp, tANI_U16 auth_rsp_len, + tpPESession psessionEntry); +void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, + tpPESession psessionEntry); +void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac); +void limFillFTSession(tpAniSirGlobal pMac, tpSirBssDescription pbssDescription, + tpPESession pftSessionEntry, tpPESession psessionEntry); +tSirRetStatus limFTPrepareAddBssReq(tpAniSirGlobal pMac, tANI_U8 updateEntry, + tpPESession pftSessionEntry, + tpSirBssDescription bssDescription); +tANI_BOOLEAN limProcessFTUpdateKey(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf ); +tSirRetStatus limProcessFTAggrQosReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf ); +void limProcessFTAggrQoSRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void limFTCleanupAllFTSessions(tpAniSirGlobal pMac); + +#endif /* __LIMFT_H__ */ + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFTDefs.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFTDefs.h new file mode 100644 index 000000000000..9d3ba2a9dad8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limFTDefs.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if defined WLAN_FEATURE_VOWIFI_11R +/**========================================================================= + + Macros and Function prototypes FT and 802.11R purposes + + ========================================================================*/ + +#ifndef __LIMFTDEFS_H__ +#define __LIMFTDEFS_H__ + + +#include +#include "halMsgApi.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define SIR_MDIE_SIZE 3 // MD ID(2 bytes), Capability(1 byte) +#define MAX_FTIE_SIZE 384 // Max size limited to 384, on acct. of IW custom events + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------- + FT Pre Auth Req SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthReq +{ + tANI_U16 messageType; // eWNI_SME_FT_PRE_AUTH_REQ + tANI_U16 length; + tANI_BOOLEAN bPreAuthRspProcessed; /* Track if response is processed for this request + We expect only one response per request. */ + tANI_U8 preAuthchannelNum; + tSirMacAddr currbssId; // BSSID currently associated to suspend the link + tSirMacAddr preAuthbssId; // BSSID to preauth to + tANI_U16 ft_ies_length; + tANI_U8 ft_ies[MAX_FTIE_SIZE]; + tpSirBssDescription pbssDescription; +} tSirFTPreAuthReq, *tpSirFTPreAuthReq; + +/*------------------------------------------------------------------------- + FT Pre Auth Rsp PE<->SME + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthRsp +{ + tANI_U16 messageType; // eWNI_SME_FT_PRE_AUTH_RSP + tANI_U16 length; + tANI_U8 smeSessionId; + tSirMacAddr preAuthbssId; // BSSID to preauth to + tSirRetStatus status; + tANI_U16 ft_ies_length; + tANI_U8 ft_ies[MAX_FTIE_SIZE]; + tANI_U16 ric_ies_length; + tANI_U8 ric_ies[MAX_FTIE_SIZE]; +} tSirFTPreAuthRsp, *tpSirFTPreAuthRsp; + +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTUpdateKeyInfo +{ + tANI_U16 messageType; + tANI_U16 length; + tANI_U32 smeSessionId; + tSirMacAddr bssId; + tSirKeyMaterial keyMaterial; +} tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo; + +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthKeyInfo +{ + tANI_U8 extSetStaKeyParamValid; //Ext Bss Config Msg if set + tLimMlmSetKeysReq extSetStaKeyParam; //SetStaKeyParams for ext bss msg +} tSirFTPreAuthKeyInfo, *tpSirFTPreAuthKeyInfo; + +/*------------------------------------------------------------------------- + Global FT Information + ------------------------------------------------------------------------*/ +typedef struct sFTPEContext +{ + tpSirFTPreAuthReq pFTPreAuthReq; /* Saved FT Pre Auth Req */ + tSirRetStatus ftPreAuthStatus; + tANI_U16 saved_auth_rsp_length; + tANI_U8 saved_auth_rsp[MAX_FTIE_SIZE]; + tSirFTPreAuthKeyInfo PreAuthKeyInfo; + /* Items created for the new FT, session */ + void *pAddBssReq; /* Save add bss req */ + void *pAddStaReq; /*Save add sta req */ + tANI_U32 peSessionId; + tANI_U32 smeSessionId; + + /* This flag is required to indicate on which session the preauth + * has taken place, since the auth reponse for preauth will come + * for a new BSSID for which there is no session yet. This flag + * will be used to extract the session from the session preauth + * has been initiated + */ + tANI_BOOLEAN ftPreAuthSession; +} tftPEContext, *tpftPEContext; + +#endif /* __LIMFTDEFS_H__ */ + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h new file mode 100644 index 000000000000..94807df42c70 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h @@ -0,0 +1,723 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limGlobal.h contains the definitions exported by + * LIM module. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __LIM_GLOBAL_H +#define __LIM_GLOBAL_H + +#include "wniApi.h" +#include "sirApi.h" +#include "sirMacProtDef.h" +#include "sirMacPropExts.h" +#include "sirCommon.h" +#include "sirDebug.h" +#include "wniCfgSta.h" +#include "csrApi.h" +#include "sapApi.h" +#include "dot11f.h" +#include "sys/queue.h" + +/// Maximum number of scan hash table entries +#define LIM_MAX_NUM_OF_SCAN_RESULTS 256 + +// Sending Disassociate frames threshold +#define LIM_SEND_DISASSOC_FRAME_THRESHOLD 2 +#define LIM_HASH_MISS_TIMER_MS 10000 + +// Deferred Message Queue Length +#define MAX_DEFERRED_QUEUE_LEN 80 + +// Maximum number of PS - TIM's to be sent with out wakeup from STA +#define LIM_TIM_WAIT_COUNT_FACTOR 5 + +/** Use this count if (LIM_TIM_WAIT_FACTOR * ListenInterval) is less than LIM_MIN_TIM_WAIT_CNT*/ +#define LIM_MIN_TIM_WAIT_COUNT 50 + +#define GET_TIM_WAIT_COUNT(LIntrvl) ((LIntrvl * LIM_TIM_WAIT_COUNT_FACTOR) > LIM_MIN_TIM_WAIT_COUNT ? \ + (LIntrvl * LIM_TIM_WAIT_COUNT_FACTOR) : LIM_MIN_TIM_WAIT_COUNT) +#define IS_5G_BAND(__rfBand) ((__rfBand & 0x3) == 0x2) +#define IS_24G_BAND(__rfBand) ((__rfBand & 0x3) == 0x1) + +#define LIM_MAX_CSA_IE_UPDATES ( 5 ) + +// enums exported by LIM are as follows + +/// System role definition +typedef enum eLimSystemRole +{ + eLIM_UNKNOWN_ROLE, + eLIM_AP_ROLE, + eLIM_STA_IN_IBSS_ROLE, + eLIM_STA_ROLE, + eLIM_BT_AMP_STA_ROLE, + eLIM_BT_AMP_AP_ROLE, + eLIM_P2P_DEVICE_ROLE, + eLIM_P2P_DEVICE_GO, + eLIM_P2P_DEVICE_CLIENT +} tLimSystemRole; + +/** + * SME state definition accessible across all Sirius modules. + * AP only states are LIM_SME_CHANNEL_SCAN_STATE & + * LIM_SME_NORMAL_CHANNEL_SCAN_STATE. + * Note that these states may also be present in STA + * side too when DFS support is present for a STA in IBSS mode. + */ +typedef enum eLimSmeStates +{ + eLIM_SME_OFFLINE_STATE, + eLIM_SME_IDLE_STATE, + eLIM_SME_SUSPEND_STATE, + eLIM_SME_WT_SCAN_STATE, + eLIM_SME_WT_JOIN_STATE, + eLIM_SME_WT_AUTH_STATE, + eLIM_SME_WT_ASSOC_STATE, + eLIM_SME_WT_REASSOC_STATE, + eLIM_SME_WT_REASSOC_LINK_FAIL_STATE, + eLIM_SME_JOIN_FAILURE_STATE, + eLIM_SME_ASSOCIATED_STATE, + eLIM_SME_REASSOCIATED_STATE, + eLIM_SME_LINK_EST_STATE, + eLIM_SME_LINK_EST_WT_SCAN_STATE, + eLIM_SME_WT_PRE_AUTH_STATE, + eLIM_SME_WT_DISASSOC_STATE, + eLIM_SME_WT_DEAUTH_STATE, + eLIM_SME_WT_START_BSS_STATE, + eLIM_SME_WT_STOP_BSS_STATE, + eLIM_SME_NORMAL_STATE, + eLIM_SME_CHANNEL_SCAN_STATE, + eLIM_SME_NORMAL_CHANNEL_SCAN_STATE +} tLimSmeStates; + +/** + * MLM state definition. + * While these states are present on AP too when it is + * STA mode, per-STA MLM state exclusive to AP is: + * eLIM_MLM_WT_AUTH_FRAME3. + */ +typedef enum eLimMlmStates +{ + eLIM_MLM_OFFLINE_STATE, + eLIM_MLM_IDLE_STATE, + eLIM_MLM_WT_PROBE_RESP_STATE, + eLIM_MLM_PASSIVE_SCAN_STATE, + eLIM_MLM_WT_JOIN_BEACON_STATE, + eLIM_MLM_JOINED_STATE, + eLIM_MLM_BSS_STARTED_STATE, + eLIM_MLM_WT_AUTH_FRAME2_STATE, + eLIM_MLM_WT_AUTH_FRAME3_STATE, + eLIM_MLM_WT_AUTH_FRAME4_STATE, + eLIM_MLM_AUTH_RSP_TIMEOUT_STATE, + eLIM_MLM_AUTHENTICATED_STATE, + eLIM_MLM_WT_ASSOC_RSP_STATE, + eLIM_MLM_WT_REASSOC_RSP_STATE, + eLIM_MLM_ASSOCIATED_STATE, + eLIM_MLM_REASSOCIATED_STATE, + eLIM_MLM_LINK_ESTABLISHED_STATE, + eLIM_MLM_WT_ASSOC_CNF_STATE, + eLIM_MLM_LEARN_STATE, + eLIM_MLM_WT_ADD_BSS_RSP_STATE, + eLIM_MLM_WT_DEL_BSS_RSP_STATE, + eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE, + eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE, + eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE, + eLIM_MLM_WT_ADD_STA_RSP_STATE, + eLIM_MLM_WT_DEL_STA_RSP_STATE, + //MLM goes to this state when LIM initiates DELETE_STA as processing of Assoc req because + //the entry already exists. LIM comes out of this state when DELETE_STA response from + //HAL is received. LIM needs to maintain this state so that ADD_STA can be issued while + //processing DELETE_STA response from HAL. + eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE, + eLIM_MLM_WT_SET_BSS_KEY_STATE, + eLIM_MLM_WT_SET_STA_KEY_STATE, + eLIM_MLM_WT_SET_STA_BCASTKEY_STATE, + eLIM_MLM_WT_ADDBA_RSP_STATE, + eLIM_MLM_WT_REMOVE_BSS_KEY_STATE, + eLIM_MLM_WT_REMOVE_STA_KEY_STATE, + eLIM_MLM_WT_SET_MIMOPS_STATE, +#if defined WLAN_FEATURE_VOWIFI_11R + eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE, + eLIM_MLM_WT_FT_REASSOC_RSP_STATE, +#endif + eLIM_MLM_P2P_LISTEN_STATE, +} tLimMlmStates; + +// 11h channel quiet states +/* This enum indicates in which state the device is in + * when it receives quiet element in beacon or probe-response. + * The default quiet state of the device is always INIT + * eLIM_QUIET_BEGIN - When Quiet period is started + * eLIM_QUIET_CHANGED - When Quiet period is updated + * eLIM_QUIET_RUNNING - Between two successive Quiet updates + * eLIM_QUIET_END - When quiet period ends + */ +typedef enum eLimQuietStates +{ + eLIM_QUIET_INIT, + eLIM_QUIET_BEGIN, + eLIM_QUIET_CHANGED, + eLIM_QUIET_RUNNING, + eLIM_QUIET_END +} tLimQuietStates; + +// 11h channel switch states +/* This enum indicates in which state the channel-swith + * is presently operating. + * eLIM_11H_CHANSW_INIT - Default state + * eLIM_11H_CHANSW_RUNNING - When channel switch is running + * eLIM_11H_CHANSW_END - After channel switch is complete + */ +typedef enum eLimDot11hChanSwStates +{ + eLIM_11H_CHANSW_INIT, + eLIM_11H_CHANSW_RUNNING, + eLIM_11H_CHANSW_END +} tLimDot11hChanSwStates; + + +//WLAN_SUSPEND_LINK Related +typedef void (*SUSPEND_RESUME_LINK_CALLBACK)(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); + +// LIM to HAL SCAN Management Message Interface states +typedef enum eLimHalScanState +{ + eLIM_HAL_IDLE_SCAN_STATE, + eLIM_HAL_INIT_SCAN_WAIT_STATE, + eLIM_HAL_START_SCAN_WAIT_STATE, + eLIM_HAL_END_SCAN_WAIT_STATE, + eLIM_HAL_FINISH_SCAN_WAIT_STATE, + eLIM_HAL_INIT_LEARN_WAIT_STATE, + eLIM_HAL_START_LEARN_WAIT_STATE, + eLIM_HAL_END_LEARN_WAIT_STATE, + eLIM_HAL_FINISH_LEARN_WAIT_STATE, + eLIM_HAL_SCANNING_STATE, +//WLAN_SUSPEND_LINK Related + eLIM_HAL_SUSPEND_LINK_WAIT_STATE, + eLIM_HAL_SUSPEND_LINK_STATE, + eLIM_HAL_RESUME_LINK_WAIT_STATE, +//end WLAN_SUSPEND_LINK Related +} tLimLimHalScanState; + +// LIM states related to A-MPDU/BA +// This is used for maintaining the state between PE and HAL only. +typedef enum eLimBAState +{ + eLIM_BA_STATE_IDLE, // we are not waiting for anything from HAL. + eLIM_BA_STATE_WT_ADD_RSP, //We are waiting for Add rsponse from HAL. + eLIM_BA_STATE_WT_DEL_RSP // We are waiting for Del response from HAL. +} tLimBAState; + + + + + +// MLM Req/Cnf structure definitions +typedef struct sLimMlmAuthReq +{ + tSirMacAddr peerMacAddr; + tAniAuthType authType; + tANI_U32 authFailureTimeout; + tANI_U8 sessionId; +} tLimMlmAuthReq, *tpLimMlmAuthReq; + +typedef struct sLimMlmJoinReq +{ + tANI_U32 joinFailureTimeout; + tSirMacRateSet operationalRateSet; + tANI_U8 sessionId; + tSirBssDescription bssDescription; +} tLimMlmJoinReq, *tpLimMlmJoinReq; + +typedef struct sLimMlmScanReq +{ + tSirBssType bssType; + tSirMacAddr bssId; + tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; + tSirScanType scanType; + tANI_U32 minChannelTime; + tANI_U32 maxChannelTime; + tANI_U32 minChannelTimeBtc; + tANI_U32 maxChannelTimeBtc; + tSirBackgroundScanMode backgroundScanMode; + tANI_U32 dot11mode; + /* Number of SSIDs to scan(send Probe request) */ + tANI_U8 numSsid; + + tANI_BOOLEAN p2pSearch; + tANI_U16 uIEFieldLen; + tANI_U16 uIEFieldOffset; + + tANI_U8 sessionId; + //channelList MUST be the last field of this structure + tSirChannelList channelList; + /*----------------------------- + tLimMlmScanReq.... + ----------------------------- + uIEFiledLen + ----------------------------- + uIEFiledOffset ----+ + ----------------------------- | + channelList.numChannels | + ----------------------------- | + ... variable size up to | + channelNumber[numChannels-1] | + This can be zero, if | + numChannel is zero. | + ----------------------------- <--+ + ... variable size uIEFiled + up to uIEFieldLen (can be 0) + -----------------------------*/ +} tLimMlmScanReq, *tpLimMlmScanReq; + +typedef struct tLimScanResultNode tLimScanResultNode; +struct tLimScanResultNode +{ + tLimScanResultNode *next; + tSirBssDescription bssDescription; +}; + +#ifdef FEATURE_OEM_DATA_SUPPORT + +#ifndef OEM_DATA_REQ_SIZE +#define OEM_DATA_REQ_SIZE 280 +#endif +#ifndef OEM_DATA_RSP_SIZE +#define OEM_DATA_RSP_SIZE 1724 +#endif + +// OEM Data related structure definitions +typedef struct sLimMlmOemDataReq +{ + tSirMacAddr selfMacAddr; + tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; +} tLimMlmOemDataReq, *tpLimMlmOemDataReq; + +typedef struct sLimMlmOemDataRsp +{ + tANI_U8 oemDataRsp[OEM_DATA_RSP_SIZE]; +} tLimMlmOemDataRsp, *tpLimMlmOemDataRsp; +#endif + +// Pre-authentication structure definition +typedef struct tLimPreAuthNode +{ + struct tLimPreAuthNode *next; + tSirMacAddr peerMacAddr; + tAniAuthType authType; + tLimMlmStates mlmState; + tANI_U8 authNodeIdx; + tANI_U8 challengeText[SIR_MAC_AUTH_CHALLENGE_LENGTH]; + tANI_U8 fTimerStarted:1; + tANI_U8 fSeen:1; + tANI_U8 fFree:1; + tANI_U8 rsvd:5; + TX_TIMER timer; + tANI_U16 seqNum; + v_TIME_t timestamp; +}tLimPreAuthNode, *tpLimPreAuthNode; + +// Pre-authentication table definition +typedef struct tLimPreAuthTable +{ + tANI_U32 numEntry; + tLimPreAuthNode **pTable; +}tLimPreAuthTable, *tpLimPreAuthTable; + +/// Per STA context structure definition +typedef struct sLimMlmStaContext +{ + tLimMlmStates mlmState; + tAniAuthType authType; + tANI_U16 listenInterval; + tSirMacCapabilityInfo capabilityInfo; + tSirMacPropRateSet propRateSet; + tSirMacReasonCodes disassocReason; + tANI_U16 cleanupTrigger; + + tSirResultCodes resultCode; + tANI_U16 protStatusCode; + + tANI_U8 subType:1; // Indicates ASSOC (0) or REASSOC (1) + tANI_U8 updateContext:1; + tANI_U8 schClean:1; + // 802.11n HT Capability in Station: Enabled 1 or DIsabled 0 + tANI_U8 htCapability:1; +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtCapability:1; +#endif +} tLimMlmStaContext, *tpLimMlmStaContext; + +// Structure definition to hold deferred messages queue parameters +typedef struct sLimDeferredMsgQParams +{ + tSirMsgQ deferredQueue[MAX_DEFERRED_QUEUE_LEN]; + tANI_U16 size; + tANI_U16 read; + tANI_U16 write; +} tLimDeferredMsgQParams, *tpLimDeferredMsgQParams; + +#ifdef SAP_AUTH_OFFLOAD +/** + * slim_deferred_sap_msg - member of sap deferred queue + * + * list_elem: tq element + * deferredmsg: deferred msg + */ +struct slim_deferred_sap_msg +{ + TAILQ_ENTRY(slim_deferred_sap_msg) list_elem; + tSirMsgQ deferredmsg; +}; + +/** + * slim_deferred_sap_queue - sap msg deferred queue + * + * head: head of tq + */ +struct slim_deferred_sap_queue +{ + TAILQ_HEAD(t_slim_deferred_sap_msg_head, slim_deferred_sap_msg) tq_head; +}; +#endif +typedef struct sCfgProtection +{ + tANI_U32 overlapFromlla:1; + tANI_U32 overlapFromllb:1; + tANI_U32 overlapFromllg:1; + tANI_U32 overlapHt20:1; + tANI_U32 overlapNonGf:1; + tANI_U32 overlapLsigTxop:1; + tANI_U32 overlapRifs:1; + tANI_U32 overlapOBSS:1; /* added for obss */ + tANI_U32 fromlla:1; + tANI_U32 fromllb:1; + tANI_U32 fromllg:1; + tANI_U32 ht20:1; + tANI_U32 nonGf:1; + tANI_U32 lsigTxop:1; + tANI_U32 rifs:1; + tANI_U32 obss:1; /* added for Obss */ +}tCfgProtection, *tpCfgProtection; + +typedef enum eLimProtStaCacheType +{ + eLIM_PROT_STA_CACHE_TYPE_INVALID, + eLIM_PROT_STA_CACHE_TYPE_llB, + eLIM_PROT_STA_CACHE_TYPE_llG, + eLIM_PROT_STA_CACHE_TYPE_HT20 +}tLimProtStaCacheType; + +typedef struct sCacheParams +{ + tANI_U8 active; + tSirMacAddr addr; + tLimProtStaCacheType protStaCacheType; + +} tCacheParams, *tpCacheParams; + +#define LIM_PROT_STA_OVERLAP_CACHE_SIZE HAL_NUM_ASSOC_STA +#define LIM_PROT_STA_CACHE_SIZE HAL_NUM_ASSOC_STA + +typedef struct sLimProtStaParams +{ + tANI_U8 numSta; + tANI_U8 protectionEnabled; +} tLimProtStaParams, *tpLimProtStaParams; + + +typedef struct sLimNoShortParams +{ + tANI_U8 numNonShortPreambleSta; + tCacheParams staNoShortCache[LIM_PROT_STA_CACHE_SIZE]; +} tLimNoShortParams, *tpLimNoShortParams; + +typedef struct sLimNoShortSlotParams +{ + tANI_U8 numNonShortSlotSta; + tCacheParams staNoShortSlotCache[LIM_PROT_STA_CACHE_SIZE]; +} tLimNoShortSlotParams, *tpLimNoShortSlotParams; + + +typedef struct tLimIbssPeerNode tLimIbssPeerNode; +struct tLimIbssPeerNode +{ + tLimIbssPeerNode *next; + tSirMacAddr peerMacAddr; + tANI_U8 extendedRatesPresent:1; + tANI_U8 edcaPresent:1; + tANI_U8 wmeEdcaPresent:1; + tANI_U8 wmeInfoPresent:1; + tANI_U8 htCapable:1; + tANI_U8 vhtCapable:1; + tANI_U8 rsvd:2; + tANI_U8 htSecondaryChannelOffset; + tSirMacCapabilityInfo capabilityInfo; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tANI_U8 supportedMCSSet[SIZE_OF_SUPPORTED_MCS_SET]; + tSirMacEdcaParamSetIE edcaParams; + tANI_U8 erpIePresent; + + //HT Capabilities of IBSS Peer + tANI_U8 htGreenfield; + tANI_U8 htShortGI40Mhz; + tANI_U8 htShortGI20Mhz; + + // DSSS/CCK at 40 MHz: Enabled 1 or Disabled + tANI_U8 htDsssCckRate40MHzSupport; + + // MIMO Power Save + tSirMacHTMIMOPowerSaveState htMIMOPSState; + + // + // A-MPDU Density + // 000 - No restriction + // 001 - 1/8 usec + // 010 - 1/4 usec + // 011 - 1/2 usec + // 100 - 1 usec + // 101 - 2 usec + // 110 - 4 usec + // 111 - 8 usec + // + tANI_U8 htAMpduDensity; + + // Maximum Rx A-MPDU factor + tANI_U8 htMaxRxAMpduFactor; + + //Set to 0 for 3839 octets + //Set to 1 for 7935 octets + tANI_U8 htMaxAmsduLength; + + // + // Recommended Tx Width Set + // 0 - use 20 MHz channel (control channel) + // 1 - use 40 Mhz channel + // + tANI_U8 htSupportedChannelWidthSet; + + tANI_U8 htLdpcCapable; + + tANI_U8 beaconHBCount; + tANI_U8 heartbeatFailure; + + tANI_U8 *beacon; //Hold beacon to be sent to HDD/CSR + tANI_U16 beaconLen; + +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + tANI_U8 vhtSupportedChannelWidthSet; + tANI_U8 vhtBeamFormerCapable; +#endif + /* + * Peer Atim Info + */ + tANI_U8 atimIePresent; + tANI_U32 peerAtimWindowLength; +}; + +// Enums used for channel switching. +typedef enum eLimChannelSwitchState +{ + eLIM_CHANNEL_SWITCH_IDLE, + eLIM_CHANNEL_SWITCH_PRIMARY_ONLY, + eLIM_CHANNEL_SWITCH_SECONDARY_ONLY, + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY +} tLimChannelSwitchState; + + +// Channel Switch Info +typedef struct sLimChannelSwitchInfo +{ + tLimChannelSwitchState state; + tANI_U8 primaryChannel; + ePhyChanBondState secondarySubBand; + tANI_S8 switchCount; + tANI_U32 switchTimeoutValue; + tANI_U8 switchMode; +} tLimChannelSwitchInfo, *tpLimChannelSwitchInfo; + +#ifdef WLAN_FEATURE_11AC +typedef struct sLimOperatingModeInfo +{ + tANI_U8 present; + tANI_U8 chanWidth: 2; + tANI_U8 reserved: 2; + tANI_U8 rxNSS: 3; + tANI_U8 rxNSSType: 1; +}tLimOperatingModeInfo, *tpLimOperatingModeInfo; +#endif + +typedef struct sLimWiderBWChannelSwitch +{ + tANI_U8 newChanWidth; + tANI_U8 newCenterChanFreq0; + tANI_U8 newCenterChanFreq1; +}tLimWiderBWChannelSwitchInfo, *tpLimWiderBWChannelSwitchInfo; + +// Enums used when stopping the Tx. +typedef enum eLimQuietTxMode +{ + eLIM_TX_ALL = 0, /* Stops/resumes the transmission of all stations, Uses the global flag. */ + eLIM_TX_STA, /* Stops/resumes the transmission of specific stations identified by staId. */ + eLIM_TX_BSS, /* Stops/resumes the transmission of all the packets in BSS */ + eLIM_TX_BSS_BUT_BEACON /* Stops/resumes the transmission of all packets except beacons in BSS + * This is used when radar is detected in the current operating channel. + * Beacon has to be sent to notify the stations associated about the + * scheduled channel switch */ +} tLimQuietTxMode; + +typedef enum eLimControlTx +{ + eLIM_RESUME_TX = 0, + eLIM_STOP_TX +} tLimControlTx; + + +// -------------------------------------------------------------------- + +typedef __ani_attr_pre_packed struct sLimTspecInfo +{ + tANI_U8 inuse; // 0==free, else used + tANI_U8 idx; // index in list + tANI_U8 staAddr[6]; + tANI_U16 assocId; + tSirMacTspecIE tspec; + tANI_U8 numTclas; // number of Tclas elements + tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM]; + tANI_U8 tclasProc; + tANI_U8 tclasProcPresent:1; //tclassProc is valid only if this is set to 1. +} __ani_attr_packed tLimTspecInfo, *tpLimTspecInfo; + +typedef struct sLimAdmitPolicyInfo +{ + tANI_U8 type; // admit control policy type + tANI_U8 bw_factor; // oversubscription factor : 0 means nothing is allowed + // valid only when 'type' is set BW_FACTOR +} tLimAdmitPolicyInfo, *tpLimAdmitPolicyInfo; + + +typedef enum eLimWscEnrollState +{ + eLIM_WSC_ENROLL_NOOP, + eLIM_WSC_ENROLL_BEGIN, + eLIM_WSC_ENROLL_IN_PROGRESS, + eLIM_WSC_ENROLL_END + +} tLimWscEnrollState; + +#define WSC_PASSWD_ID_PUSH_BUTTON (0x0004) + +typedef struct sLimWscIeInfo +{ + tANI_BOOLEAN apSetupLocked; + tANI_BOOLEAN selectedRegistrar; + tANI_U16 selectedRegistrarConfigMethods; + tLimWscEnrollState wscEnrollmentState; + tLimWscEnrollState probeRespWscEnrollmentState; + tANI_U8 reqType; + tANI_U8 respType; +} tLimWscIeInfo, *tpLimWscIeInfo; + +// maximum number of tspec's supported +#define LIM_NUM_TSPEC_MAX 15 + + +//structure to hold all 11h specific data +typedef struct sLimSpecMgmtInfo +{ + tLimQuietStates quietState; + tANI_U32 quietCount; + tANI_U32 quietDuration; /* This is in units of system TICKS */ + tANI_U32 quietDuration_TU; /* This is in units of TU, for over the air transmission */ + tANI_U32 quietTimeoutValue; /* After this timeout, actual quiet starts */ + tANI_BOOLEAN fQuietEnabled; /* Used on AP, if quiet is enabled during learning */ + + tLimDot11hChanSwStates dot11hChanSwState; + + tANI_BOOLEAN fRadarDetCurOperChan; /* Radar detected in cur oper chan on AP */ + tANI_BOOLEAN fRadarIntrConfigured; /* Whether radar interrupt has been configured */ +}tLimSpecMgmtInfo, *tpLimSpecMgmtInfo; + + +#ifdef FEATURE_WLAN_TDLS +/* + * Peer info needed for TDLS setup.. + */ +typedef struct tLimTDLSPeerSta +{ + struct tLimTDLSPeerSta *next; + tANI_U8 dialog ; + tSirMacAddr peerMac; + tSirMacCapabilityInfo capabilityInfo; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tSirMacQosCapabilityStaIE qosCaps; + tSirMacEdcaParamSetIE edcaParams; + tANI_U8 mcsSet[SIZE_OF_SUPPORTED_MCS_SET]; + tANI_U8 tdls_bIsResponder ; + /* HT Capabilties */ + tDot11fIEHTCaps tdlsPeerHTCaps ; + tDot11fIEExtCap tdlsPeerExtCaps; + tANI_U8 tdls_flags ; + tANI_U8 tdls_link_state ; + tANI_U8 tdls_prev_link_state ; + tANI_U8 tdls_sessionId; + tANI_U8 ExtRatesPresent ; + TX_TIMER gLimTdlsLinkSetupRspTimeoutTimer ; + TX_TIMER gLimTdlsLinkSetupCnfTimeoutTimer ; +}tLimTdlsLinkSetupPeer, *tpLimTdlsLinkSetupPeer ; + +typedef struct tLimTdlsLinkSetupInfo +{ + tLimTdlsLinkSetupPeer *tdlsLinkSetupList ; + tANI_U8 num_tdls_peers ; + tANI_U8 tdls_flags ; + tANI_U8 tdls_state ; + tANI_U8 tdls_prev_state ; +}tLimTdlsLinkSetupInfo, *tpLimTdlsLinkSetupInfo ; + +typedef enum tdlsLinkMode +{ + TDLS_LINK_MODE_BG, + TDLS_LINK_MODE_N, + TDLS_LINK_MODE_AC, + TDLS_LINK_MODE_NONE +} eLimTdlsLinkMode ; +#endif /* FEATURE_WLAN_TDLS */ + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h new file mode 100644 index 000000000000..c4bf4058daaf --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __LIM_SESSION_H ) +#define __LIM_SESSION_H + +/**========================================================================= + + \file limSession.h + + \brief prototype for lim Session related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +/* Powersave Offload Implementation */ +typedef enum ePowersaveState +{ + PMM_FULL_POWER, + PMM_POWER_SAVE +}tPowersaveState; + +/* Master Structure: This will be part of PE Session Entry */ +typedef struct sPowersaveoffloadInfo +{ + tPowersaveState psstate; + tANI_U8 bcnmiss; +}tPowersaveoffloadInfo, tpPowersaveoffloadInfo; + +#ifdef WLAN_FEATURE_11W +/* + * This struct is needed for handling of ASSOC RSP with TRY AGAIN LATER + * It stores the context and state machine setting for MLM so that it can + * go back send ASSOC REQ frame again after the timer has expired. + */ +typedef struct tagComebackTimerInfo +{ + tpAniSirGlobal pMac; + tANI_U8 sessionID; + tLimMlmStates limPrevMlmState; /* Previous MLM State */ + tLimSmeStates limMlmState; /* MLM State */ +} tComebackTimerInfo; +#endif /* WLAN_FEATURE_11W */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + + + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define NUM_WEP_KEYS 4 + +// Maximum allowable size of a beacon frame +#define SCH_MAX_BEACON_SIZE 512 + +#define SCH_MAX_PROBE_RESP_SIZE 512 + +#define SCH_PROTECTION_RESET_TIME 4000 +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +typedef struct +{ + tSirMacBeaconInterval beaconInterval; + tANI_U8 fShortPreamble; + tANI_U8 llaCoexist; + tANI_U8 llbCoexist; + tANI_U8 llgCoexist; + tANI_U8 ht20Coexist; + tANI_U8 llnNonGFCoexist; + tANI_U8 fRIFSMode; + tANI_U8 fLsigTXOPProtectionFullSupport; + tANI_U8 gHTObssMode; +}tBeaconParams, *tpBeaconParams; + +typedef struct sPESession // Added to Support BT-AMP +{ + /* To check session table is in use or free*/ + tANI_U8 available; + tANI_U16 peSessionId; + tANI_U8 smeSessionId; + tANI_U16 transactionId; + + //In AP role: BSSID and selfMacAddr will be the same. + //In STA role: they will be different + tSirMacAddr bssId; + tSirMacAddr selfMacAddr; + tSirMacSSid ssId; + tANI_U8 bssIdx; + tANI_U8 valid; + tLimMlmStates limMlmState; //MLM State + tLimMlmStates limPrevMlmState; //Previous MLM State + tLimSmeStates limSmeState; //SME State + tLimSmeStates limPrevSmeState; //Previous SME State + tLimSystemRole limSystemRole; + tSirBssType bssType; + tANI_U8 operMode; // AP - 0; STA - 1 ; + tSirNwType nwType; + tpSirSmeStartBssReq pLimStartBssReq; //handle to smestart bss req + tpSirSmeJoinReq pLimJoinReq; // handle to sme join req + tpSirSmeJoinReq pLimReAssocReq; //handle to sme reassoc req + tpLimMlmJoinReq pLimMlmJoinReq; //handle to MLM join Req +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + void *pLimMlmReassocRetryReq; //keep reasoc req for retry +#endif + void *pLimMlmReassocReq; //handle to MLM reassoc Req + tANI_U16 channelChangeReasonCode; + tANI_U8 dot11mode; + tANI_U8 htCapability; + /* Supported Channel Width Set: 0-20MHz 1 - 40MHz */ + tANI_U8 htSupportedChannelWidthSet; + /* Recommended Tx Width Set + * 0 - use 20 MHz channel (control channel) + * 1 - use channel width enabled under Supported Channel Width Set + */ + tANI_U8 htRecommendedTxWidthSet; + /* Identifies the 40 MHz extension channel */ + ePhyChanBondState htSecondaryChannelOffset; + tSirRFBand limRFBand; + tANI_U8 limIbssActive; //TO SUPPORT CONCURRENCY + + /* These global varibales moved to session Table to support BT-AMP : Oct 9th review */ + tAniAuthType limCurrentAuthType; + tANI_U16 limCurrentBssCaps; + tANI_U8 limCurrentBssQosCaps; + tANI_U16 limCurrentBssPropCap; + tANI_U8 limSentCapsChangeNtf; + tANI_U16 limAID; + + /* Parameters For Reassociation */ + tSirMacAddr limReAssocbssId; + tSirMacChanNum limReassocChannelId; + /* CB paramaters required/duplicated for Reassoc since re-assoc mantains its own params in lim */ + tANI_U8 reAssocHtSupportedChannelWidthSet; + tANI_U8 reAssocHtRecommendedTxWidthSet; + ePhyChanBondState reAssocHtSecondaryChannelOffset; + tSirMacSSid limReassocSSID; + tANI_U16 limReassocBssCaps; + tANI_U8 limReassocBssQosCaps; + tANI_U16 limReassocBssPropCap; + + // Assoc or ReAssoc Response Data/Frame + void *limAssocResponseData; + + /** BSS Table parameters **/ + + /* + * staId: Start BSS: this is the Sta Id for the BSS. + * Join: this is the selfStaId + * In both cases above, the peer STA ID wll be stored in dph hash table. + */ + tANI_U16 staId; + tANI_U16 statypeForBss; //to know session is for PEER or SELF + tANI_U8 shortSlotTimeSupported; + tANI_U8 dtimPeriod; + tSirMacRateSet rateSet; + tSirMacRateSet extRateSet; + tSirMacHTOperatingMode htOperMode; + tANI_U8 currentOperChannel; + tANI_U8 currentReqChannel; + tANI_U8 LimRxedBeaconCntDuringHB; + + //Time stamp of the last beacon received from the BSS to which STA is connected. + tANI_U64 lastBeaconTimeStamp; + //RX Beacon count for the current BSS to which STA is connected. + tANI_U32 currentBssBeaconCnt; + tANI_U8 lastBeaconDtimCount; + tANI_U8 lastBeaconDtimPeriod; + + tANI_U32 bcnLen; + tANI_U8 *beacon; //Used to store last beacon / probe response before assoc. + + tANI_U32 assocReqLen; + tANI_U8 *assocReq; //Used to store association request frame sent out while associating. + + tANI_U32 assocRspLen; + tANI_U8 *assocRsp; //Used to store association response received while associating + tAniSirDph dph; + void * *parsedAssocReq; //Used to store parsed assoc req from various requesting station +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_U32 RICDataLen; //Used to store the Ric data received in the assoc response + tANI_U8 *ricData; +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U32 tspecLen; //Used to store the TSPEC IEs received in the assoc response + tANI_U8 *tspecIes; +#endif + tANI_U32 encryptType; + + tANI_BOOLEAN bTkipCntrMeasActive; // Used to keep record of TKIP counter measures start/stop + + tANI_U8 gLimProtectionControl; //used for 11n protection + + tANI_U8 gHTNonGFDevicesPresent; + + //protection related config cache + tCfgProtection cfgProtection; + + // Number of legacy STAs associated + tLimProtStaParams gLim11bParams; + + // Number of 11A STAs associated + tLimProtStaParams gLim11aParams; + + // Number of non-ht non-legacy STAs associated + tLimProtStaParams gLim11gParams; + + //Number of nonGf STA associated + tLimProtStaParams gLimNonGfParams; + + //Number of HT 20 STAs associated + tLimProtStaParams gLimHt20Params; + + //Number of Lsig Txop not supported STAs associated + tLimProtStaParams gLimLsigTxopParams; + + // Number of STAs that do not support short preamble + tLimNoShortParams gLimNoShortParams; + + // Number of STAs that do not support short slot time + tLimNoShortSlotParams gLimNoShortSlotParams; + + + // OLBC parameters + tLimProtStaParams gLimOlbcParams; + + // OLBC parameters + tLimProtStaParams gLimOverlap11gParams; + + tLimProtStaParams gLimOverlap11aParams; + tLimProtStaParams gLimOverlapHt20Params; + tLimProtStaParams gLimOverlapNonGfParams; + + //cache for each overlap + tCacheParams protStaCache[LIM_PROT_STA_CACHE_SIZE]; + + tANI_U8 privacy; + tAniAuthType authType; + tSirKeyMaterial WEPKeyMaterial[NUM_WEP_KEYS]; + + tDot11fIERSN gStartBssRSNIe; + tDot11fIEWPA gStartBssWPAIe; + tSirAPWPSIEs APWPSIEs; + tANI_U8 apUapsdEnable; + tSirWPSPBCSession *pAPWPSPBCSession; + tANI_U32 DefProbeRspIeBitmap[8]; + tANI_U32 proxyProbeRspEn; + tDot11fProbeResponse probeRespFrame; + tANI_U8 ssidHidden; + tANI_BOOLEAN fwdWPSPBCProbeReq; + tANI_U8 wps_state; + + tANI_U8 limQosEnabled:1; //11E + tANI_U8 limWmeEnabled:1; //WME + tANI_U8 limWsmEnabled:1; //WSM + tANI_U8 limHcfEnabled:1; + tANI_U8 lim11dEnabled:1; +#ifdef WLAN_FEATURE_11W + tANI_U8 limRmfEnabled:1; //11W +#endif + tANI_U32 lim11hEnable; + + tPowerdBm maxTxPower; //MIN (Regulatory and local power constraint) + tVOS_CON_MODE pePersona; +#if defined WLAN_FEATURE_VOWIFI + tPowerdBm txMgmtPower; +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + tAniBool is11Rconnection; +#endif + +#ifdef FEATURE_WLAN_ESE + tAniBool isESEconnection; + tEsePEContext eseContext; +#endif +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + tAniBool isFastTransitionEnabled; +#endif +#ifdef FEATURE_WLAN_LFR + tAniBool isFastRoamIniFeatureEnabled; +#endif + tSirNoAParam p2pNoA; + tSirP2PNoaAttr p2pGoPsUpdate; + tANI_U32 defaultAuthFailureTimeout; + tSirP2PNoaStart p2pGoPsNoaStartInd; + + /* EDCA QoS parameters + * gLimEdcaParams - These EDCA parameters are used locally on AP or STA. + * If STA, then these are values taken from the Assoc Rsp when associating, + * or Beacons/Probe Response after association. If AP, then these are + * values originally set locally on AP. + * + * gLimEdcaParamsBC - These EDCA parameters are use by AP to broadcast + * to other STATIONs in the BSS. + * + * gLimEdcaParamsActive: These EDCA parameters are what's actively being + * used on station. Specific AC values may be downgraded depending on + * admission control for that particular AC. + */ + tSirMacEdcaParamRecord gLimEdcaParams[MAX_NUM_AC]; //used locally + tSirMacEdcaParamRecord gLimEdcaParamsBC[MAX_NUM_AC]; //used for broadcast + tSirMacEdcaParamRecord gLimEdcaParamsActive[MAX_NUM_AC]; + + tANI_U8 gLimEdcaParamSetCount; + + tBeaconParams beaconParams; +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtCapability; + tANI_U8 vhtTxChannelWidthSet; + tLimOperatingModeInfo gLimOperatingMode; + tANI_U8 vhtCapabilityPresentInBeacon; + tANI_U8 apCenterChan; + tANI_U8 apChanWidth; + tANI_U8 txBFIniFeatureEnabled; + tANI_U8 txMuBformee; + tANI_U8 enableVhtpAid; + tANI_U8 enableVhtGid; +#endif + tLimWiderBWChannelSwitchInfo gLimWiderBWChannelSwitch; + tANI_U8 enableAmpduPs; + tANI_U8 enableHtSmps; + tANI_U8 htSmpsvalue; + tANI_U8 spectrumMgtEnabled; + /* *********************11H related*****************************/ + tLimSpecMgmtInfo gLimSpecMgmt; + // CB Primary/Secondary Channel Switch Info + tLimChannelSwitchInfo gLimChannelSwitch; + /* *********************End 11H related*****************************/ + + /*Flag to Track Status/Indicate HBFailure on this session */ + tANI_BOOLEAN LimHBFailureStatus; + tANI_U32 gLimPhyMode; + tANI_U8 amsduSupportedInBA; + tANI_U8 txLdpcIniFeatureEnabled; + /** + * Following is the place holder for free peer index pool. + * A non-zero value indicates that peer index is available + * for assignment. + */ + tANI_U8 *gpLimPeerIdxpool; + tANI_U8 freePeerIdxHead; + tANI_U8 freePeerIdxTail; + tANI_U16 gLimNumOfCurrentSTAs; +#ifdef FEATURE_WLAN_TDLS + tANI_U32 peerAIDBitmap[2]; + bool tdls_prohibited; + bool tdls_chan_swit_prohibited; +#endif + tANI_BOOLEAN fWaitForProbeRsp; + tANI_BOOLEAN fIgnoreCapsChange; + tANI_BOOLEAN fDeauthReceived; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + tANI_S8 rssi; +#endif + tANI_U8 max_amsdu_num; + tANI_U8 isCoalesingInIBSSAllowed; + + tSirHTConfig htConfig; + + /* + * Place holder for StartBssReq message + * received by SME state machine + */ + tANI_U8 gLimCurrentBssUapsd; + + /* Used on STA, this is a static UAPSD mask setting + * derived from SME_JOIN_REQ and SME_REASSOC_REQ. If a + * particular AC bit is set, it means the AC is both + * trigger enabled and delivery enabled. + */ + tANI_U8 gUapsdPerAcBitmask; + + /* Used on STA, this is a dynamic UPASD mask setting + * derived from AddTS Rsp and DelTS frame. If a + * particular AC bit is set, it means AC is trigger + * enabled. + */ + tANI_U8 gUapsdPerAcTriggerEnableMask; + + /* Used on STA, dynamic UPASD mask setting + * derived from AddTS Rsp and DelTs frame. If + * a particular AC bit is set, it means AC is + * delivery enabled. + */ + tANI_U8 gUapsdPerAcDeliveryEnableMask; + + /* Flag to skip CSA IE processing when CSA + * offload is enabled. + */ + tANI_U8 csaOffloadEnable; + + /* Used on STA for AC downgrade. This is a dynamic mask + * setting which keep tracks of ACs being admitted. + * If bit is set to 0: That partiular AC is not admitted + * If bit is set to 1: That particular AC is admitted + */ + tANI_U8 gAcAdmitMask[SIR_MAC_DIRECTION_DIRECT]; + + /* Power Save Off load Parameters */ + tPowersaveoffloadInfo pmmOffloadInfo; + + /* SMPS mode */ + tANI_U8 smpsMode; + + tANI_U8 chainMask; + + /* Flag to indicate Chan Sw announcement is required */ + tANI_U8 dfsIncludeChanSwIe; + + /* Flag to indicate Chan Wrapper Element is required */ + tANI_U8 dfsIncludeChanWrapperIe; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tANI_U8 cc_switch_mode; +#endif + + tANI_BOOLEAN isCiscoVendorAP; + + tSirAddIeParams addIeParams; + + tANI_U8 *pSchProbeRspTemplate; + // Beginning portion of the beacon frame to be written to TFP + tANI_U8 *pSchBeaconFrameBegin; + // Trailing portion of the beacon frame to be written to TFP + tANI_U8 *pSchBeaconFrameEnd; + // Size of the beginning portion + tANI_U16 schBeaconOffsetBegin; + // Size of the trailing portion + tANI_U16 schBeaconOffsetEnd; + tANI_BOOLEAN isOSENConnection; + /* DSCP to UP mapping for HS 2.0 */ + tSirQosMapSet QosMapSet; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_BOOLEAN bRoamSynchInProgress; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + /* Fast Transition (FT) */ + tftPEContext ftPEContext; +#endif + tANI_BOOLEAN isNonRoamReassoc; +#ifdef WLAN_FEATURE_11W + vos_timer_t pmfComebackTimer; + tComebackTimerInfo pmfComebackTimerInfo; +#endif /* WLAN_FEATURE_11W */ + tANI_U8 isKeyInstalled; + /* timer for reseting protection fileds at regular intervals */ + vos_timer_t protection_fields_reset_timer; + void *mac_ctx; + /* + * variable to store state of various protection struct like + * gLimOlbcParams, gLimOverlap11gParams, gLimOverlapHt20Params etc + */ + tANI_U16 old_protection_state; + tSirMacAddr prev_ap_bssid; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* tells if Q2Q IE, from another MDM device in AP MCC mode was recvd */ + bool sap_advertise_avoid_ch_ie; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + uint8_t sap_dot11mc; +#ifdef FEATURE_WLAN_ESE + uint8_t is_ese_version_ie_present; +#endif + /* flag to indicate country code in beacon */ + tANI_U8 countryInfoPresent; + uint8_t vdev_nss; + bool roaming_in_progress; + /* Supported NSS is intersection of self and peer NSS */ + bool supported_nss_1x1; + bool add_bss_failed; +} tPESession, *tpPESession; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + + \brief peCreateSession() - creates a new PE session given the BSSID + + This function returns the session context and the session ID if the + session corresponding to the passed BSSID is found in the PE session + table. + + \param pMac - pointer to global adapter context + \param bssid - BSSID of the new session + \param sessionId - session ID is returned here, if session is + created. + \param bssType - bss type of new session to do conditional + memory allocation. + \return tpPESession - pointer to the session context or NULL if + session can not be created. + + \sa + + --------------------------------------------------------------------------*/ +tpPESession peCreateSession(tpAniSirGlobal pMac, + tANI_U8 *bssid, + tANI_U8* sessionId, + tANI_U16 numSta, + tSirBssType bssType); + +/*-------------------------------------------------------------------------- + \brief peFindSessionByBssid() - looks up the PE session given the BSSID. + + This function returns the session context and the session ID if the session + corresponding to the given BSSID is found in the PE session table. + + \param pMac - pointer to global adapter context + \param bssid - BSSID of the session + \param sessionId -session ID is returned here, if session is found. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ +tpPESession peFindSessionByBssid(tpAniSirGlobal pMac, tANI_U8* bssid, tANI_U8* sessionId); + + + +/*-------------------------------------------------------------------------- + \brief peFindSessionByBssIdx() - looks up the PE session given the bssIdx. + + This function returns the session context if the session + corresponding to the given bssIdx is found in the PE session table. + \param pMac - pointer to global adapter context + \param bssIdx - bss index of the session + \return tpPESession - pointer to the session context or NULL if session is not found. + \sa + --------------------------------------------------------------------------*/ +tpPESession peFindSessionByBssIdx(tpAniSirGlobal pMac, tANI_U8 bssIdx); + + + + +/*-------------------------------------------------------------------------- + \brief peFindSessionByPeerSta() - looks up the PE session given the Peer Station Address. + + This function returns the session context and the session ID if the session + corresponding to the given destination address is found in the PE session table. + + \param pMac - pointer to global adapter context + \param sa - Peer STA Address of the session + \param sessionId -session ID is returned here, if session is found. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ +tpPESession peFindSessionByPeerSta(tpAniSirGlobal pMac, tANI_U8* sa, tANI_U8* sessionId); + +/*-------------------------------------------------------------------------- + \brief peFindSessionBySessionId() - looks up the PE session given the session ID. + + This function returns the session context if the session + corresponding to the given session ID is found in the PE session table. + + \param pMac - pointer to global adapter context + \param sessionId -session ID for which session context needs to be looked up. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ + tpPESession peFindSessionBySessionId(tpAniSirGlobal pMac , tANI_U8 sessionId); + +/*-------------------------------------------------------------------------- + \brief peFindSessionByBssid() - looks up the PE session given staid. + + This function returns the session context and the session ID if the session + corresponding to the given StaId is found in the PE session table. + + \param pMac - pointer to global adapter context + \param staid - StaId of the session + \param sessionId - session ID is returned here, if session is found. + + \return tpPESession - pointer to the session context or NULL if session is not found. + +--------------------------------------------------------------------------*/ + tpPESession peFindSessionByStaId(tpAniSirGlobal pMac, tANI_U8 staid, tANI_U8* sessionId); + + + + + +/*-------------------------------------------------------------------------- + \brief peDeleteSession() - deletes the PE session given the session ID. + + + \param pMac - pointer to global adapter context + \param sessionId -session ID of the session which needs to be deleted. + + \sa + --------------------------------------------------------------------------*/ +void peDeleteSession(tpAniSirGlobal pMac, tpPESession psessionEntry); + +/** + * pe_find_session_by_sme_session_id() - looks up the PE session for given sme + * session id + * @mac_ctx: pointer to global adapter context + * @sme_session_id: sme session id + * + * looks up the PE session for given sme session id + * + * Return: pe session entry for given sme session if found else NULL + */ +tpPESession pe_find_session_by_sme_session_id(tpAniSirGlobal mac_ctx, + uint8_t sme_session_id); + +int pe_get_active_session_count(tpAniSirGlobal mac_ctx); +#endif //#if !defined( __LIM_SESSION_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limTrace.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limTrace.h new file mode 100644 index 000000000000..66772e1af72f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limTrace.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + +* \file limTrace.h + +* \brief definition for trace related APIs + +* \author Sunit Bhatia + + ========================================================================*/ + + + +#ifndef __LIM_TRACE_H +#define __LIM_TRACE_H + +#include "limGlobal.h" +#include "macTrace.h" +#include "vos_trace.h" +#ifdef LIM_TRACE_RECORD + + + +#define LIM_TRACE_GET_SSN(data) (((data) >> 16) & 0xff) +#define LIM_TRACE_GET_SUBTYPE(data) (data & 0xff) +#define LIM_TRACE_GET_DEFERRED(data) (data & 0x80000000) +#define LIM_TRACE_GET_DEFRD_OR_DROPPED(data) (data & 0xc0000000) + +#define LIM_MSG_PROCESSED 0 +#define LIM_MSG_DEFERRED 1 +#define LIM_MSG_DROPPED 2 + +#define LIM_TRACE_MAKE_RXMGMT(type, ssn) \ + ((ssn << 16) | (type) ) +#define LIM_TRACE_MAKE_RXMSG(msg, action) \ + ((msg) | (action << 30) ) + + + + +enum { + TRACE_CODE_MLM_STATE, + TRACE_CODE_SME_STATE, + TRACE_CODE_TX_MGMT, + TRACE_CODE_RX_MGMT, + TRACE_CODE_RX_MGMT_TSF, + TRACE_CODE_TX_COMPLETE, + TRACE_CODE_TX_SME_MSG, + TRACE_CODE_RX_SME_MSG, + TRACE_CODE_TX_WDA_MSG, + TRACE_CODE_RX_WDA_MSG, + TRACE_CODE_TX_LIM_MSG, + TRACE_CODE_RX_LIM_MSG, + TRACE_CODE_TX_CFG_MSG, + TRACE_CODE_RX_CFG_MSG, + TRACE_CODE_RX_MGMT_DROP, + + TRACE_CODE_TIMER_ACTIVATE, + TRACE_CODE_TIMER_DEACTIVATE, + TRACE_CODE_INFO_LOG +}; + + + + + + +void limTraceInit(tpAniSirGlobal pMac); +void limTraceReset(tpAniSirGlobal pMac); +void limTraceUpdateMgmtStat(tpAniSirGlobal pMac, tANI_U8 subtype); +void limTraceDumpMgmtStat(tpAniSirGlobal pMac, tANI_U8 subtype); +tANI_U8* limTraceGetMlmStateString( tANI_U32 mlmState ); +tANI_U8* limTraceGetSmeStateString( tANI_U32 smeState ); +void limTraceDump(tpAniSirGlobal pMac, tpvosTraceRecord pRecord, tANI_U16 recIndex); +void macTraceMsgTx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data); +void macTraceMsgRx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data); + +void macTraceMsgRxNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 session, tANI_U32 data); +void macTraceMsgTxNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 session, tANI_U32 data); +#endif //endof LIM_TRACE_RECORD MACRO + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmApi.h new file mode 100644 index 000000000000..60f3541e7cf2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmApi.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __PMM_API_H__ +#define __PMM_API_H__ + +#include "sirCommon.h" +#include "schApi.h" +#include "halMsgApi.h" + + +/// Initialize PMM +extern tSirRetStatus pmmInitialize(tpAniSirGlobal pMac); + +/// Post a message to PMM module +extern tSirRetStatus pmmPostMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg); + +/// Reset PMM beacon mode power save statistics +extern void pmmResetStats(void *pvMac); + +/// Process the next PM message +extern void pmmProcessMessage(tpAniSirGlobal, tpSirMsgQ); + +extern void pmmProcessPSPoll(tpAniSirGlobal, tANI_U8 *); +extern void pmmUpdatePSPollState(tpAniSirGlobal); +extern void pmmProcessRxActivity(tpAniSirGlobal, tANI_U16, tANI_U8); + +extern void pmmGenerateTIM(tpAniSirGlobal, tANI_U8 **, tANI_U16 *, tANI_U8); + + +void pmmUpdateTIM(tpAniSirGlobal pMac, tpBeaconGenParams pBeaconGenParams); + +/// Update the PM mode +extern void pmmUpdatePMMode(tpAniSirGlobal pMac, tANI_U16 staId, tANI_U8 pmMode); + +/// Update Power Mode +extern void pmmUpdatePollablePMMode(tpAniSirGlobal, tANI_U16, tANI_U8, tANI_U16); +extern void pmmUpdateNonPollablePMMode(tpAniSirGlobal, tANI_U16, tANI_U8, tANI_U16); + +/** Monitor the STA in PS*/ +void pmmHandleTimBasedDisassociation(tpAniSirGlobal pMac, tpPESession psessionEntry); + +//go into sleep state +void pmmInitBmpsPwrSave(tpAniSirGlobal pMac); +tSirRetStatus pmmSendInitPowerSaveMsg(tpAniSirGlobal pMac,tpPESession); +void pmmInitBmpsResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirRetStatus pmmSendChangePowerSaveMsg(tpAniSirGlobal pMac); +tSirRetStatus pmmSendSleepIndicationToHal(tpAniSirGlobal pMac); + +//go into wakeup state +void pmmExitBmpsRequestHandler(tpAniSirGlobal pMac, tpExitBmpsInfo pExitBmpsInfo); +void pmmExitBmpsResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) ; +void pmmMissedBeaconHandler(tpAniSirGlobal pMac); + +//handlling all UAPSD messages +void pmmEnterUapsdRequestHandler (tpAniSirGlobal pMac); +void pmmEnterUapsdResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void pmmExitUapsdRequestHandler (tpAniSirGlobal pMac); +void pmmExitUapsdResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirRetStatus pmmUapsdSendChangePwrSaveMsg (tpAniSirGlobal pMac, tANI_U8 mode); + +// handling of all idle mode power save messages +void pmmEnterImpsRequestHandler(tpAniSirGlobal pMac); +void pmmEnterImpsResponseHandler(tpAniSirGlobal pMac, eHalStatus rspStatus); +void pmmExitImpsRequestHandler(tpAniSirGlobal pMac); +void pmmExitImpsResponseHandler(tpAniSirGlobal pMac, eHalStatus rspStatus); + +// handling WOWLAN messages +void pmmSendWowlAddBcastPtrn(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void pmmSendWowlDelBcastPtrn(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void pmmEnterWowlRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +tSirRetStatus pmmSendWowlEnterRequest(tpAniSirGlobal pMac, tpSirHalWowlEnterParams pHalWowlParams); +void pmmEnterWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirRetStatus pmmSendExitWowlReq(tpAniSirGlobal pMac, tpSirHalWowlExitParams pHalWowlParams); +void pmmExitWowlanRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void pmmExitWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); + +// update idle mode statistics +void pmmImpsUpdatePwrSaveStats(tpAniSirGlobal pMac); +void pmmImpsUpdateWakeupStats(tpAniSirGlobal pMac); +tSirRetStatus pmmImpsSendChangePwrSaveMsg(tpAniSirGlobal pMac, tANI_U8 mode); +void pmmImpsUpdateSleepErrStats(tpAniSirGlobal pMac, tSirRetStatus retStatus); +void pmmImpsUpdateWakeupErrStats(tpAniSirGlobal pMac, tSirRetStatus retStatus); +void pmmImpsUpdateErrStateStats(tpAniSirGlobal pMac); +void pmmImpsUpdatePktDropStats(tpAniSirGlobal pMac); + +void pmmBmpsUpdatePktDropStats(tpAniSirGlobal pMac); +void pmmBmpsUpdateHalReqFailureCnt(tpAniSirGlobal pMac); +void pmmBmpsUpdateInitFailureCnt(tpAniSirGlobal pMac); +void pmmBmpsUpdateInvalidStateCnt(tpAniSirGlobal pMac); +void pmmBmpsUpdatePktDropStats(tpAniSirGlobal pMac); +void pmmBmpsUpdateReqInInvalidRoleCnt(tpAniSirGlobal pMac); +void pmmBmpsUpdateSleepReqFailureCnt(tpAniSirGlobal pMac); +void pmmBmpsUpdateWakeupIndCnt(tpAniSirGlobal pMac); +void pmmBmpsUpdateWakeupReqFailureCnt(tpAniSirGlobal pMac); +void pmmResetPmmState(tpAniSirGlobal pMac); +void pmmSendMessageToLim(tpAniSirGlobal pMac, tANI_U32 msgId); + +//Power Save CFG +tSirRetStatus pmmSendPowerSaveCfg(tpAniSirGlobal pMac, tpSirPowerSaveCfg pUpdatedPwrSaveCfg); + +//Handle Low RSSI Indication +void pmmLowRssiHandler(tpAniSirGlobal pMac); + +#ifdef WLAN_FEATURE_PACKET_FILTERING +void pmmFilterMatchCountResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +#endif // WLAN_FEATURE_PACKET_FILTERING + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void pmmGTKOffloadGetInfoResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +#endif // WLAN_FEATURE_GTK_OFFLOAD + +eHalStatus pmmPsOffloadOpen(tpAniSirGlobal pMac,tpPESession psessionEntry); +eHalStatus pmmPsOffloadClose(tpAniSirGlobal pMac, + tpPESession psessionEntry); +tANI_U8 pmmPsOffloadIsActive(tpAniSirGlobal pMac, + tpPESession psessionEntry); +void pmmOffloadProcessMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmGlobal.h new file mode 100644 index 000000000000..e24252071a68 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/pmmGlobal.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __PMM_GLOBAL_H__ +#define __PMM_GLOBAL_H__ + +#include "sirApi.h" + +typedef enum ePmmState +{ + ePMM_STATE_INVALID, + ePMM_STATE_READY, + //BMPS + ePMM_STATE_BMPS_WT_INIT_RSP, + ePMM_STATE_BMPS_WT_SLEEP_RSP, + ePMM_STATE_BMPS_SLEEP, + ePMM_STATE_BMPS_WT_WAKEUP_RSP, + ePMM_STATE_BMPS_WAKEUP, + //IMPS + ePMM_STATE_IMPS_WT_SLEEP_RSP, + ePMM_STATE_IMPS_SLEEP, + ePMM_STATE_IMPS_WT_WAKEUP_RSP, + ePMM_STATE_IMPS_WAKEUP, + //UAPSD + ePMM_STATE_UAPSD_WT_SLEEP_RSP, + ePMM_STATE_UAPSD_SLEEP, + ePMM_STATE_UAPSD_WT_WAKEUP_RSP, + + //WOWLAN + ePMM_STATE_WOWLAN, + + ePMM_STATE_ERROR, + ePMM_STATE_LAST, +}tPmmState; + +typedef struct sPmmStaInfo +{ + tANI_U16 assocId; + tANI_U32 staTxAckCnt; +}tPmmStaInfo, *tpPmmStaInfo; + +typedef struct sPmmTim +{ + tANI_U8 *pTim; /** Tim Bit Array*/ + tANI_U8 minAssocId; + tANI_U8 maxAssocId; + tANI_U8 dtimCount; + /** Remaining Members are needed for LinkMonitaring of the STA in PS*/ + tANI_U8 numStaWithData; /** Number of stations in power save, who have data pending*/ + tpPmmStaInfo pStaInfo; /** Points to 1st Instant of the Array of MaxSTA StaInfo */ +} tPmmTim, *tpPmmTim; + +typedef struct sAniSirPmm +{ + tANI_U64 BmpsmaxSleepTime; + tANI_U64 BmpsavgSleepTime; + tANI_U64 BmpsminSleepTime; + tANI_U64 BmpscntSleep; + + tANI_U64 BmpsmaxTimeAwake; + tANI_U64 BmpsavgTimeAwake; + tANI_U64 BmpsminTimeAwake; + tANI_U64 BmpscntAwake; + + tANI_U64 BmpsWakeupTimeStamp; + tANI_U64 BmpsSleepTimeStamp; + + // debug statistics + tANI_U64 BmpsPktDrpInSleepMode; + tANI_U64 BmpsInitFailCnt; + tANI_U64 BmpsSleeReqFailCnt; + tANI_U64 BmpsWakeupReqFailCnt; + tANI_U64 BmpsInvStateCnt; + tANI_U64 BmpsWakeupIndCnt; + tANI_U64 BmpsHalReqFailCnt; + tANI_U64 BmpsReqInInvalidRoleCnt; + + /* Add wakeup and sleep time stamps here */ + tANI_U64 ImpsWakeupTimeStamp; + tANI_U64 ImpsSleepTimeStamp; + + tANI_U64 ImpsMaxTimeAwake; + tANI_U64 ImpsMinTimeAwake; + tANI_U64 ImpsAvgTimeAwake; + tANI_U64 ImpsCntAwake; + + tANI_U64 ImpsCntSleep; + tANI_U64 ImpsMaxSleepTime; + tANI_U64 ImpsMinSleepTime; + tANI_U64 ImpsAvgSleepTime; + + tANI_U64 ImpsSleepErrCnt; + tANI_U64 ImpsWakeupErrCnt; + tANI_U64 ImpsLastErr; + + tANI_U64 ImpsInvalidStateCnt; + tANI_U64 ImpsPktDrpInSleepMode; + + + /// Next STA to be serviced in PS state + tANI_U16 gPmmNextSta; + + /// Next CF-pollable STA to be serviced in PS state + tANI_U16 gPmmNextCFPSta; + + /// Number of STAs in PS state + tANI_U16 gPmmNumSta; + + tANI_U8 gPmmPsPollUpdate:1; // set when any sta state is update due to PS-Poll + tANI_U8 rsvd: 7; + + /// STA Power management state array + /** + * An entry in this array records the power save state for an STA + * It also points to the next closest STA in power save state. + */ + + tANI_U32 gPmmBeaconInterval; //pmm keeps its won copy of beacon interval, default to 100ms + tSirPowerSaveCfg gPmmCfg; //pmm keeps a copy of Power Save config parameters sent to softmac. + /// Current PM state of the station + tPmmState gPmmState; + /// Flag to track if we are in a missed beacon scenario + tANI_U8 inMissedBeaconScenario; + + tPmmTim gPmmTim; + + + //Reason for which PMC is sending an EXIT_BMPS_REQ to PE + tExitBmpsReason gPmmExitBmpsReasonCode; + tANI_U8 sessionId; //This sessio Id is added to know the bsstype , infra/btamp .......in power save mode + +} tAniSirPmm, *tpAniSirPmm; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmApi.h new file mode 100644 index 000000000000..7b5fc2ce3403 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmApi.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011-2012, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/**========================================================================= + + \file rrmApi.h + + \brief RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +#ifndef __RRM_API_H__ +#define __RRM_API_H__ + +#ifdef WLAN_FEATURE_VOWIFI +#define RRM_MIN_TX_PWR_CAP 13 +#define RRM_MAX_TX_PWR_CAP 19 + +#define RRM_BCN_RPT_NO_BSS_INFO 0 +#define RRM_BCN_RPT_MIN_RPT 1 + +tANI_U8 rrmGetMinOfMaxTxPower(tpAniSirGlobal pMac, tPowerdBm regMax, tPowerdBm apTxPower); + +extern tSirRetStatus rrmInitialize(tpAniSirGlobal pMac); + +extern tSirRetStatus rrmCleanup(tpAniSirGlobal pMac); + + +extern tSirRetStatus rrmProcessLinkMeasurementRequest( tpAniSirGlobal pMac, + tANI_U8 *pRxPacketInfo, + tDot11fLinkMeasurementRequest *pLinkReq, + tpPESession pSessionEntry ); + +extern tSirRetStatus rrmProcessRadioMeasurementRequest( tpAniSirGlobal pMac, + tSirMacAddr peer, + tDot11fRadioMeasurementRequest *pRRMReq, + tpPESession pSessionEntry ); + +extern tSirRetStatus rrmProcessNeighborReportResponse( tpAniSirGlobal pMac, + tDot11fNeighborReportResponse *pNeighborRep, + tpPESession pSessionEntry ); + +extern void rrmProcessMessage(tpAniSirGlobal pMac, + tpSirMsgQ pMsg); + +extern tSirRetStatus rrmSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, + tPowerdBm txPower, + tpPESession pSessionEntry ); + +extern tPowerdBm rrmGetMgmtTxPower ( tpAniSirGlobal pMac, + tpPESession pSessionEntry ); + +extern void rrmCacheMgmtTxPower ( tpAniSirGlobal pMac, + tPowerdBm txPower, + tpPESession pSessionEntry ); + +extern tpRRMCaps rrmGetCapabilities ( tpAniSirGlobal pMac, + tpPESession pSessionEntry ); + +extern void rrmGetStartTSF ( tpAniSirGlobal pMac, + tANI_U32 *pStartTSF ); + +extern void rrmUpdateStartTSF ( tpAniSirGlobal pMac, + tANI_U32 startTSF[2] ); + +extern tSirRetStatus rrmSetMaxTxPowerRsp ( tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ ); + +extern tSirRetStatus +rrmProcessNeighborReportReq( tpAniSirGlobal pMac, + tpSirNeighborReportReqInd pNeighborReq ); +extern tSirRetStatus +rrmProcessBeaconReportXmit( tpAniSirGlobal pMac, + tpSirBeaconReportXmitInd pBcnReport); + +extern void lim_update_rrm_capability(tpAniSirGlobal mac_ctx, + tpSirSmeJoinReq join_req); +#else +void lim_update_rrm_capability(tpAniSirGlobal pMac, + tpSirSmeJoinReq join_req) +{ +} +#endif +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmGlobal.h new file mode 100644 index 000000000000..c23f1e00a89e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/rrmGlobal.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2011-2012, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __RRMGLOBAL_H ) +#define __RRMGLOBAL_H + +/**========================================================================= + + \file rrmGlobal.h + + \brief Definitions for SME APIs + + ========================================================================*/ + +typedef enum eRrmRetStatus +{ + eRRM_SUCCESS, + eRRM_INCAPABLE, + eRRM_REFUSED, + eRRM_FAILURE +} tRrmRetStatus; + +typedef enum eRrmMsgReqSource +{ + eRRM_MSG_SOURCE_LEGACY_ESE = 1, /* legacy ese */ + eRRM_MSG_SOURCE_11K = 2, /* 11k */ + eRRM_MSG_SOURCE_ESE_UPLOAD = 3, /* ese upload approach */ +} tRrmMsgReqSource; + +typedef struct sSirChannelInfo +{ + tANI_U8 regulatoryClass; + tANI_U8 channelNum; +} tSirChannelInfo, * tpSirChannelInfo; + +typedef struct sSirBeaconReportReqInd +{ + tANI_U16 messageType; // eWNI_SME_BEACON_REPORT_REQ_IND + tANI_U16 length; + tSirMacAddr bssId; + tANI_U16 measurementDuration[SIR_ESE_MAX_MEAS_IE_REQS]; //ms + tANI_U16 randomizationInterval; //ms + tSirChannelInfo channelInfo; + tSirMacAddr macaddrBssid; //0: wildcard + tANI_U8 fMeasurementtype[SIR_ESE_MAX_MEAS_IE_REQS]; //0:Passive, 1: Active, 2: table mode + tAniSSID ssId; //May be wilcard. + tANI_U16 uDialogToken; + tSirChannelList channelList; //From AP channel report. + tRrmMsgReqSource msgSource; +} tSirBeaconReportReqInd, * tpSirBeaconReportReqInd; + + +typedef struct sSirBeaconReportXmitInd +{ + tANI_U16 messageType; // eWNI_SME_BEACON_REPORT_RESP_XMIT_IND + tANI_U16 length; + tSirMacAddr bssId; + tANI_U16 uDialogToken; + tANI_U8 fMeasureDone; + tANI_U16 duration; + tANI_U8 regClass; + tANI_U8 numBssDesc; + tpSirBssDescription pBssDescription[SIR_BCN_REPORT_MAX_BSS_DESC]; +} tSirBeaconReportXmitInd, * tpSirBeaconReportXmitInd; + +typedef struct sSirNeighborReportReqInd +{ + tANI_U16 messageType; // eWNI_SME_NEIGHBOR_REPORT_REQ_IND + tANI_U16 length; + tSirMacAddr bssId; //For the session. + tANI_U16 noSSID; //TRUE - dont include SSID in the request. + //FALSE include the SSID. It may be null (wildcard) + tSirMacSSid ucSSID; +} tSirNeighborReportReqInd, * tpSirNeighborReportReqInd; + + +typedef struct sSirNeighborBssDescription +{ + tANI_U16 length; + tSirMacAddr bssId; + tANI_U8 regClass; + tANI_U8 channel; + tANI_U8 phyType; + union sSirNeighborBssidInfo { + struct _rrmInfo { + tANI_U32 fApPreauthReachable:2; //see IEEE 802.11k Table 7-43a + tANI_U32 fSameSecurityMode:1; + tANI_U32 fSameAuthenticator:1; + tANI_U32 fCapSpectrumMeasurement:1; //see IEEE 802.11k Table 7-95d + tANI_U32 fCapQos:1; + tANI_U32 fCapApsd:1; + tANI_U32 fCapRadioMeasurement:1; + tANI_U32 fCapDelayedBlockAck:1; + tANI_U32 fCapImmediateBlockAck:1; + tANI_U32 fMobilityDomain:1; + tANI_U32 reserved:21; + } rrmInfo; + struct _eseInfo { + tANI_U32 channelBand:8; + tANI_U32 minRecvSigPower:8; + tANI_U32 apTxPower:8; + tANI_U32 roamHysteresis:8; + tANI_U32 adaptScanThres:8; + + tANI_U32 transitionTime:8; + tANI_U32 tsfOffset:16; + + tANI_U32 beaconInterval:16; + tANI_U32 reserved: 16; + } eseInfo; + } bssidInfo; + + //Optional sub IEs....ignoring for now. +}tSirNeighborBssDescription, *tpSirNeighborBssDescripton; + +typedef struct sSirNeighborReportInd +{ + tANI_U16 messageType; // eWNI_SME_NEIGHBOR_REPORT_IND + tANI_U16 length; + tANI_U8 sessionId; + tANI_U16 numNeighborReports; + tSirMacAddr bssId; //For the session. + tSirNeighborBssDescription sNeighborBssDescription[1]; +} tSirNeighborReportInd, * tpSirNeighborReportInd; + +typedef struct sRRMBeaconReportRequestedIes +{ + tANI_U8 num; + tANI_U8 *pElementIds; +}tRRMBeaconReportRequestedIes, *tpRRMBeaconReportRequestedIes; + +//Reporting detail defines. +//Reference - IEEE Std 802.11k-2008 section 7.3.2.21.6 Table 7-29h +#define BEACON_REPORTING_DETAIL_NO_FF_IE 0 +#define BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE 1 +#define BEACON_REPORTING_DETAIL_ALL_FF_IE 2 + + +typedef struct sRRMReq +{ + tANI_U8 dialog_token; //In action frame; + tANI_U8 token; //Within individual request; + tANI_U8 type; + union { + struct { + tANI_U8 reportingDetail; + tRRMBeaconReportRequestedIes reqIes; + }Beacon; + }request; + tANI_U8 sendEmptyBcnRpt; +}tRRMReq, *tpRRMReq; + +typedef struct sRRMCaps +{ + tANI_U8 LinkMeasurement: 1; + tANI_U8 NeighborRpt: 1; + tANI_U8 parallel: 1; + tANI_U8 repeated: 1; + tANI_U8 BeaconPassive: 1; + tANI_U8 BeaconActive: 1; + tANI_U8 BeaconTable: 1; + tANI_U8 BeaconRepCond: 1; + tANI_U8 FrameMeasurement: 1; + tANI_U8 ChannelLoad: 1; + tANI_U8 NoiseHistogram: 1; + tANI_U8 statistics: 1; + tANI_U8 LCIMeasurement: 1; + tANI_U8 LCIAzimuth: 1; + tANI_U8 TCMCapability: 1; + tANI_U8 triggeredTCM: 1; + tANI_U8 APChanReport: 1; + tANI_U8 RRMMIBEnabled: 1; + tANI_U8 operatingChanMax: 3; + tANI_U8 nonOperatingChanMax: 3; + tANI_U8 MeasurementPilot: 3; + tANI_U8 MeasurementPilotEnabled: 1; + tANI_U8 NeighborTSFOffset: 1; + tANI_U8 RCPIMeasurement: 1; + tANI_U8 RSNIMeasurement: 1; + tANI_U8 BssAvgAccessDelay: 1; + tANI_U8 BSSAvailAdmission: 1; + tANI_U8 AntennaInformation: 1; + tANI_U8 fine_time_meas_rpt: 1; + tANI_U8 lci_capability: 1; + tANI_U8 reserved: 4; +}tRRMCaps, *tpRRMCaps; + +typedef struct sRrmPEContext +{ + tANI_U8 rrmEnable; + tANI_U32 startTSF[2]; //Used during scan/measurement to store the start TSF. this is not used directly in beacon reports. + //This value is stored into bssdescription and beacon report gets it from bss decsription. + tRRMCaps rrmEnabledCaps; + tPowerdBm txMgmtPower; + tANI_U8 DialogToken; //Dialog token for the request initiated from station. + tpRRMReq pCurrentReq; +}tRrmPEContext, *tpRrmPEContext; + +// 2008 11k spec reference: 18.4.8.5 RCPI Measurement +#define RCPI_LOW_RSSI_VALUE (-110) +#define RCPI_MAX_VALUE (220) +#define CALCULATE_RCPI(rssi) (((rssi) + 110) * 2) + +/* Bit mask are defined as per Draft P802.11REVmc_D4.2 */ + +/** + * enum mask_rm_capability_byte1 - mask for supported capability + * @RM_CAP_LINK_MEASUREMENT: Link Measurement capability + * @RM_CAP_NEIGHBOR_REPORT: Neighbor report capability + * @RM_CAP_PARALLEL_MEASUREMENT: Parallel Measurement capability + * @RM_CAP_REPEATED_MEASUREMENT: Repeated Measurement capability + * @RM_CAP_BCN_PASSIVE_MEASUREMENT: Beacon passive measurement capability + * @RM_CAP_BCN_ACTIVE_MEASUREMENT: Beacon active measurement capability + * @RM_CAP_BCN_TABLE_MEASUREMENT: Beacon table measurement capability + * @RM_CAP_BCN_MEAS_REPORTING_COND: Beacon measurement reporting conditions + */ +enum mask_rm_capability_byte1 { + RM_CAP_LINK_MEASUREMENT = (1 << (0)), + RM_CAP_NEIGHBOR_REPORT = (1 << (1)), + RM_CAP_PARALLEL_MEASUREMENT = (1 << (2)), + RM_CAP_REPEATED_MEASUREMENT = (1 << (3)), + RM_CAP_BCN_PASSIVE_MEASUREMENT = (1 << (4)), + RM_CAP_BCN_ACTIVE_MEASUREMENT = (1 << (5)), + RM_CAP_BCN_TABLE_MEASUREMENT = (1 << (6)), + RM_CAP_BCN_MEAS_REPORTING_COND = (1 << (7)), +}; + +/** + * enum mask_rm_capability_byte2 - mask for supported capability + * @RM_CAP_FRAME_MEASUREMENT: Frame Measurement capability + * @RM_CAP_CHAN_LOAD_MEASUREMENT: Channel load measurement capability + * @RM_CAP_NOISE_HIST_MEASUREMENT: Noise Histogram Measurement capability + * @RM_CAP_STATISTICS_MEASUREMENT: Statistics Measurement capability + * @RM_CAP_LCI_MEASUREMENT: LCI measurement capability + * @RM_CAP_LCI_AZIMUTH: LCI Azimuth capability + * @RM_CAP_TX_CATEGORY_MEASUREMENT: Transmit category measurement capability + * @RM_CAP_TRIG_TX_CATEGORY_MEASUREMENT: + * Triggered Transmit category measurement capability + */ +enum mask_rm_capability_byte2 { + RM_CAP_FRAME_MEASUREMENT = (1 << (0)), + RM_CAP_CHAN_LOAD_MEASUREMENT = (1 << (1)), + RM_CAP_NOISE_HIST_MEASUREMENT = (1 << (2)), + RM_CAP_STATISTICS_MEASUREMENT = (1 << (3)), + RM_CAP_LCI_MEASUREMENT = (1 << (4)), + RM_CAP_LCI_AZIMUTH = (1 << (5)), + RM_CAP_TX_CATEGORY_MEASUREMENT = (1 << (6)), + RM_CAP_TRIG_TX_CATEGORY_MEASUREMENT = (1 << (7)), +}; + +/** + * enum mask_rm_capability_byte3 - mask for supported capability + * @RM_CAP_AP_CHAN_REPORT: AP channel report capability + * @RM_CAP_RM_MIB: RM MIB capability + * @RM_CAP_OPER_CHAN_MAX_DURATION_1: OPER_CHAN_MAX_DURATION bit1 + * @RM_CAP_OPER_CHAN_MAX_DURATION_2: OPER_CHAN_MAX_DURATION bit2 + * @RM_CAP_OPER_CHAN_MAX_DURATION_3: OPER_CHAN_MAX_DURATION bit3 + * @RM_CAP_NONOPER_CHAN_MAX_DURATION_1: NONOPER_CHAN_MAX bit1 + * @RM_CAP_NONOPER_CHAN_MAX_DURATION_2: NONOPER_CHAN_MAX bit2 + * @RM_CAP_NONOPER_CHAN_MAX_DURATION_3: NONOPER_CHAN_MAX bit3 + * @RM_CAP_OPER_CHAN_MAX_DURATION: Operating Channel Max Measurement Duration + * @RM_CAP_NONOPER_CHAN_MAX_DURATION: + * Nonoperating Channel Max Measurement Duration + */ + +enum mask_rm_capability_byte3 { + RM_CAP_AP_CHAN_REPORT = (1 << (0)), + RM_CAP_RM_MIB = (1 << (1)), + RM_CAP_OPER_CHAN_MAX_DURATION_1 = (1 << (2)), + RM_CAP_OPER_CHAN_MAX_DURATION_2 = (1 << (3)), + RM_CAP_OPER_CHAN_MAX_DURATION_3 = (1 << (4)), + RM_CAP_NONOPER_CHAN_MAX_DURATION_1 = (1 << (5)), + RM_CAP_NONOPER_CHAN_MAX_DURATION_2 = (1 << (6)), + RM_CAP_NONOPER_CHAN_MAX_DURATION_3 = (1 << (7)), + RM_CAP_OPER_CHAN_MAX_DURATION = (RM_CAP_OPER_CHAN_MAX_DURATION_1 || + RM_CAP_OPER_CHAN_MAX_DURATION_2 || + RM_CAP_OPER_CHAN_MAX_DURATION_3), + RM_CAP_NONOPER_CHAN_MAX_DURATION = + (RM_CAP_NONOPER_CHAN_MAX_DURATION_1 || + RM_CAP_NONOPER_CHAN_MAX_DURATION_2 || + RM_CAP_NONOPER_CHAN_MAX_DURATION_3), +}; + +/** + * enum mask_rm_capability_byte4 - mask for supported capability + * @RM_CAP_MEASUREMENT_PILOT_1: MEASUREMENT_PILOT bit1 + * @RM_CAP_MEASUREMENT_PILOT_2: MEASUREMENT_PILOT bit2 + * @RM_CAP_MEASUREMENT_PILOT_3: MEASUREMENT_PILOT bit3 + * @RM_CAP_MEAS_PILOT_TX_INFO: Measurement Pilot Transmission Capability + * @RM_CAP_NEIGHBOR_RPT_TSF_OFFSET: Neighbor Report TSF Offset Capability + * @RM_CAP_RCPI_MEASUREMENT: RCPI Measurement Capability + * @RM_CAP_RSNI_MEASUREMENT: RSNI Measurement Capability + * @RM_CAP_BSS_AVG_ACCESS_DELAY: BSS Average Access Delay Capability + * @RM_CAP_MEASUREMENT_PILOT: Measurement pilot capability + */ + +enum mask_rm_capability_byte4 { + RM_CAP_MEASUREMENT_PILOT_1 = (1 << (0)), + RM_CAP_MEASUREMENT_PILOT_2 = (1 << (1)), + RM_CAP_MEASUREMENT_PILOT_3 = (1 << (2)), + RM_CAP_MEAS_PILOT_TX_INFO = (1 << (3)), + RM_CAP_NEIGHBOR_RPT_TSF_OFFSET = (1 << (4)), + RM_CAP_RCPI_MEASUREMENT1 = (1 << (5)), + RM_CAP_RSNI_MEASUREMENT = (1 << (6)), + RM_CAP_BSS_AVG_ACCESS_DELAY = (1 << (7)), + RM_CAP_MEASUREMENT_PILOT = (RM_CAP_MEASUREMENT_PILOT_1 || + RM_CAP_MEASUREMENT_PILOT_2 || + RM_CAP_MEASUREMENT_PILOT_3), +}; + +/** + * enum mask_rm_capability_byte5 - mask for supported capability + * @RM_CAP_BSS_AVAIL_ADMISSION: BSS Available Admission Capacity Capability + * @RM_CAP_ANTENNA: Antenna Capability + * @RM_CAP_FTM_RANGE_REPORT: FTM Range Report Capability + * @RM_CAP_CIVIC_LOC_MEASUREMENT: Civic Location Measurement capability + * + * 4 bits are reserved + */ +enum mask_rm_capability_byte5 { + RM_CAP_BSS_AVAIL_ADMISSION = (1 << (0)), + RM_CAP_ANTENNA = (1 << (1)), + RM_CAP_FTM_RANGE_REPORT = (1 << (2)), + RM_CAP_CIVIC_LOC_MEASUREMENT = (1 << (3)), +}; + +#endif //#if defined __RRMGLOBAL_H diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schApi.h new file mode 100644 index 000000000000..130f165ba25d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schApi.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __SCH_API_H__ +#define __SCH_API_H__ + +#include "sirCommon.h" +#include "sirMacProtDef.h" + +#include "aniGlobal.h" + +/// Send start scan response message +extern void schSendStartScanRsp(tpAniSirGlobal pMac); + +// update only the broadcast qos params +extern void schQosUpdateBroadcast(tpAniSirGlobal pMac, tpPESession psessionEntry); + +// fill in the default local edca parameter into gLimEdcaParams[] +extern void schSetDefaultEdcaParams(tpAniSirGlobal pMac, tpPESession psessionE); + +// update only local qos params +extern void schQosUpdateLocal(tpAniSirGlobal pMac, tpPESession psessionEntry); + +// update the edca profile parameters +extern void schEdcaProfileUpdate(tpAniSirGlobal pMac, tpPESession psessionEntry); + +/// Set the fixed fields in a beacon frame +extern tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEntry); + +/// Initializations +extern void schInitialize(tpAniSirGlobal pMac); + +/// Initialize globals +extern void schInitGlobals(tpAniSirGlobal pMac); + +/// Initialize CF Poll template +extern void schInitializeCfPollTemplate(tpAniSirGlobal pMac); + +/// Initialize CF End template +extern void schInitializeCfEndTemplate(tpAniSirGlobal pMac); + +/// Process the scheduler messages +extern void schProcessMessage(tpAniSirGlobal pMac,tpSirMsgQ pSchMsg); + +/// The beacon Indication handler function +extern void schProcessPreBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg); + +/// Post a message to the scheduler message queue +extern tSirRetStatus schPostMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg); + + +extern void schBeaconProcess(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry); +extern tSirRetStatus schBeaconEdcaProcess(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry); + + +#define SCH_RR_TIMEOUT (SCH_RR_TIMEOUT_MS / SYS_TICK_DUR_MS) + +void schSetBeaconInterval(tpAniSirGlobal pMac,tpPESession psessionEntry); + +tSirRetStatus schSendBeaconReq( tpAniSirGlobal, tANI_U8 *, tANI_U16, tpPESession psessionEntry ); + +tSirRetStatus limUpdateProbeRspTemplateIeBitmapBeacon1(tpAniSirGlobal, + tDot11fBeacon1*, tpPESession psessionEntry); +void limUpdateProbeRspTemplateIeBitmapBeacon2(tpAniSirGlobal,tDot11fBeacon2*,tANI_U32*,tDot11fProbeResponse*); +void SetProbeRspIeBitmap(tANI_U32*,tANI_U32); +tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal,tpPESession, + tANI_U32*); + +int schGenTimingAdvertFrame(tpAniSirGlobal pMac, tSirMacAddr self_addr, + uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schGlobal.h new file mode 100644 index 000000000000..2b04ba2e4a6c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/schGlobal.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __SCH_GLOBAL_H__ +#define __SCH_GLOBAL_H__ + +#include "sirMacPropExts.h" +#include "limGlobal.h" + +#include "parserApi.h" + +#ifdef WLAN_SOFTAP_VSTA_FEATURE +#define TIM_IE_SIZE 0xB +#else +#define TIM_IE_SIZE 0x7 +#endif + +// ----------------------- Beacon processing ------------------------ + +/// Beacon structure +#define tSchBeaconStruct tSirProbeRespBeacon +#define tpSchBeaconStruct struct sSirProbeRespBeacon * + +// ------------------------------------------------------------------- + +//****************** MISC defs ********************************* + +struct schMisc { + tANI_U16 gSchBeaconInterval; + + /// Current CFP count + tANI_U8 gSchCFPCount; + + /// CFP Duration remaining + tANI_U8 gSchCFPDurRemaining; + + /// CFP Maximum Duration + tANI_U8 gSchCFPMaxDuration; + + /// Current DTIM count + tANI_U8 gSchDTIMCount; + + /// Whether we have initiated a CFP or not + tANI_U8 gSchCFPInitiated; + + /// Whether we have initiated a CFB or not + tANI_U8 gSchCFBInitiated; + + /// CFP is enabled and AP is configured as HCF + tANI_U8 gSchCFPEnabled; + + /// CFB is enabled and AP is configured as HCF + tANI_U8 gSchCFBEnabled; + + // --------- STA ONLY state ----------- + + /// Indicates whether RR timer is running or not + tANI_U8 rrTimer[8]; + + /// Indicates the remaining RR timeout value if the RR timer is running + tANI_U16 rrTimeout[8]; + + /// Number of RRs transmitted + tANI_U16 numRR[8]; + tANI_U16 numRRtimeouts[8]; + + /// flag to indicate that beacon template has been updated + tANI_U8 fBeaconChanged; + + tANI_U16 p2pIeOffset; + +}; + +//****************** MISC defs ********************************* + +typedef struct schStaWaitList +{ + tANI_U16 staId; + tANI_U16 count; +} tStaWaitList, *tpStaWaitList; + + +/// Global SCH structure +typedef struct sAniSirSch +{ + /// The scheduler object + struct schMisc schObject; + + // schQoSClass unsolicited; + + /// Whether HCF is enabled or not + tANI_U8 gSchHcfEnabled; + + /// Whether scan is requested by LIM or not + tANI_U8 gSchScanRequested; + + /// Whether scan request is received by SCH or not + tANI_U8 gSchScanReqRcvd; + + + /// Debug flag to disable beacon generation + tANI_U32 gSchGenBeacon; + +#define SCH_MAX_ARR 100 + tANI_U32 gSchBeaconsWritten; + tANI_U32 gSchBeaconsSent; + tANI_U32 gSchBBXportRcvCnt; + tANI_U32 gSchRRRcvCnt, qosNullCnt; + tANI_U32 gSchBcnRcvCnt; + tANI_U32 gSchUnknownRcvCnt; + + tANI_U32 gSchBcnParseErrorCnt; + tANI_U32 gSchBcnIgnored; + + tANI_U32 numPoll, numData, numCorrupt; + tANI_U32 numBogusInt, numTxAct0; + +#define SCH_MAX_NUM_SCH 21 + tANI_U32 lastBeaconLength; + tANI_U16 rrTimeout; + tANI_U32 pollPeriod; + tANI_U32 keepAlive; + tANI_U32 multipleSched; + tANI_U32 pollFeedbackHist[8]; + tANI_U32 dataFeedbackHist[8]; + tANI_U32 maxPollTimeouts; + tANI_U32 checkCfbFlagStuck; + + /// Sta Wait list + tpStaWaitList pStaWaitList; + + /// Pointer to next available entry in sta wait list + tANI_U16 staWaitListIn; + /// Pointer to first waiting sta in sta wait list + tANI_U16 staWaitListOut; + /// Total number of waiting STAs in sta wait list + tANI_U16 staWaitListCount; + /// Total number of schedules to be waited + tANI_U16 staWaitListTotalWait; + + /// Number of entries in DPH activity queue that were ignored + tANI_U32 ignoreDph; + +} tAniSirSch, *tpAniSirSch; + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/wmmApsd.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/wmmApsd.h new file mode 100644 index 000000000000..fc112290d7a0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/wmmApsd.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WMMAPSD_H__ +#define __WMMAPSD_H__ + +#include "aniGlobal.h" + +// UAPSD Flag for each AC (WMM spec 2.2.1) +#define LIM_UAPSD_BITOFFSET_ACVO 0 +#define LIM_UAPSD_BITOFFSET_ACVI 1 +#define LIM_UAPSD_BITOFFSET_ACBK 2 +#define LIM_UAPSD_BITOFFSET_ACBE 3 + +#define LIM_UAPSD_FLAG_ACVO (1 << LIM_UAPSD_BITOFFSET_ACVO) +#define LIM_UAPSD_FLAG_ACVI (1 << LIM_UAPSD_BITOFFSET_ACVI) +#define LIM_UAPSD_FLAG_ACBK (1 << LIM_UAPSD_BITOFFSET_ACBK) +#define LIM_UAPSD_FLAG_ACBE (1 << LIM_UAPSD_BITOFFSET_ACBE) + +#define LIM_UAPSD_GET(ac, mask) (((mask) & (LIM_UAPSD_FLAG_ ## ac)) >> LIM_UAPSD_BITOFFSET_ ## ac) + +// Definition for setting/clearing Uapsd Mask +#define SET_UAPSD_MASK 1 +#define CLEAR_UAPSD_MASK 0 + +#endif /* __WMMAPSD_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAIDmgmt.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAIDmgmt.c new file mode 100644 index 000000000000..26d27159ca96 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAIDmgmt.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limAIDmgmt.cc contains the functions related to + * AID pool management like initialization, assignment etc. + * Author: Chandra Modumudi + * Date: 03/20/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "palTypes.h" +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "cfgApi.h" +#include "sirParams.h" +#include "limUtils.h" +#include "limTimerUtils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "limSessionUtils.h" + +#define LIM_START_PEER_IDX 1 + +/** + * limInitPeerIdxpool() + * + *FUNCTION: + * This function is called while starting a BSS at AP + * to initialize AID pool. This may also be called while + * starting/joining an IBSS if 'Association' is allowed + * in IBSS. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limInitPeerIdxpool(tpAniSirGlobal pMac,tpPESession pSessionEntry) +{ + tANI_U8 i; + tANI_U8 maxAssocSta = pMac->lim.gLimAssocStaLimit; + + pSessionEntry->gpLimPeerIdxpool[0]=0; + +#ifdef FEATURE_WLAN_TDLS + //In station role, DPH_STA_HASH_INDEX_PEER (index 1) is reserved for peer + //station index corresponding to AP. Avoid choosing that index and get index + //starting from (DPH_STA_HASH_INDEX_PEER + 1) (index 2) for TDLS stations; + if (LIM_IS_STA_ROLE(pSessionEntry)) { + pSessionEntry->freePeerIdxHead = DPH_STA_HASH_INDEX_PEER + 1; + } + else +#endif +#ifdef QCA_IBSS_SUPPORT + if (LIM_IS_IBSS_ROLE(pSessionEntry)) { + pSessionEntry->freePeerIdxHead=LIM_START_PEER_IDX; + maxAssocSta = pMac->lim.gLimIbssStaLimit; + } + else +#endif + { + pSessionEntry->freePeerIdxHead=LIM_START_PEER_IDX; + } + + for (i=pSessionEntry->freePeerIdxHead;igpLimPeerIdxpool[i] = i+1; + } + pSessionEntry->gpLimPeerIdxpool[i] = 0; + + pSessionEntry->freePeerIdxTail=i; + +} + + +/** + * limAssignPeerIdx() + * + *FUNCTION: + * This function is called to get a peer station index. This index is + * used during Association/Reassociation + * frame handling to assign association ID (aid) to a STA. + * In case of TDLS, this is used to assign a index into the Dph hash entry. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return peerIdx - assigned peer Station IDx for STA + */ + +tANI_U16 +limAssignPeerIdx(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + tANI_U16 peerId; + + // make sure we haven't exceeded the configurable limit on associations + // This count is global to ensure that it doesnt exceed the hardware limits. + if (peGetCurrentSTAsCount(pMac) >= pMac->lim.gLimAssocStaLimit) + { + // too many associations already active + return 0; + } + + /* return head of free list */ + + if (pSessionEntry->freePeerIdxHead) + { + peerId=pSessionEntry->freePeerIdxHead; + pSessionEntry->freePeerIdxHead = pSessionEntry->gpLimPeerIdxpool[pSessionEntry->freePeerIdxHead]; + if (pSessionEntry->freePeerIdxHead==0) + pSessionEntry->freePeerIdxTail=0; + pSessionEntry->gLimNumOfCurrentSTAs++; + return peerId; + } + + return 0; /* no more free peer index */ +} + + +/** + * limReleasePeerIdx() + * + *FUNCTION: + * This function is called when a STA context is removed + * at AP (or at a STA in IBSS mode or TDLS) to return peer Index + * to free pool. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param peerIdx - peer station index that need to return to free pool + * + * @return None + */ + +void +limReleasePeerIdx(tpAniSirGlobal pMac, tANI_U16 peerIdx, tpPESession pSessionEntry) +{ + pSessionEntry->gLimNumOfCurrentSTAs--; + + /* insert at tail of free list */ + if (pSessionEntry->freePeerIdxTail) + { + pSessionEntry->gpLimPeerIdxpool[pSessionEntry->freePeerIdxTail]=(tANI_U8)peerIdx; + pSessionEntry->freePeerIdxTail=(tANI_U8)peerIdx; + } + else + { + pSessionEntry->freePeerIdxTail=pSessionEntry->freePeerIdxHead=(tANI_U8)peerIdx; + } + pSessionEntry->gpLimPeerIdxpool[(tANI_U8)peerIdx]=0; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAdmitControl.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAdmitControl.c new file mode 100644 index 000000000000..696f3e3daa7f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAdmitControl.c @@ -0,0 +1,1140 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file contains TSPEC and STA admit control related functions + * NOTE: applies only to AP builds + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "limDebug.h" +#include "sysDef.h" +#include "limApi.h" +#include "cfgApi.h" // wlan_cfgGetInt() +#include "limTrace.h" +#include "limSendSmeRspMessages.h" +#include "limTypes.h" + + +#define ADMIT_CONTROL_LOGLEVEL LOG1 +#define ADMIT_CONTROL_POLICY_LOGLEVEL LOG1 + +/* total available bandwidth in bps in each phy mode + * these should be defined in hal or dph - replace these later + */ +#define LIM_TOTAL_BW_11A 54000000 +#define LIM_MIN_BW_11A 6000000 +#define LIM_TOTAL_BW_11B 11000000 +#define LIM_MIN_BW_11B 1000000 +#define LIM_TOTAL_BW_11G LIM_TOTAL_BW_11A +#define LIM_MIN_BW_11G LIM_MIN_BW_11B + +// conversion factors +#define LIM_CONVERT_SIZE_BITS(numBytes) ((numBytes) * 8) +#define LIM_CONVERT_RATE_MBPS(rate) ((rate)/1000000) + + +//------------------------------------------------------------------------------ +// local protos + +static tSirRetStatus +limCalculateSvcInt(tpAniSirGlobal, tSirMacTspecIE *, tANI_U32 *); +static tSirRetStatus +limValidateTspecEdca(tpAniSirGlobal, tSirMacTspecIE *, tpPESession); +static tSirRetStatus +limValidateTspec(tpAniSirGlobal, tSirMacTspecIE *, tpPESession); +static void +limComputeMeanBwUsed(tpAniSirGlobal, tANI_U32 *, tANI_U32, tpLimTspecInfo, tpPESession); +static void +limGetAvailableBw(tpAniSirGlobal, tANI_U32 *, tANI_U32 *, tANI_U32, tANI_U32); +static tSirRetStatus +limAdmitPolicyOversubscription(tpAniSirGlobal, tSirMacTspecIE *, tpLimAdmitPolicyInfo, tpLimTspecInfo, tpPESession); +static tSirRetStatus +limTspecFindByStaAddr(tpAniSirGlobal, tANI_U8 *, tSirMacTspecIE*, tpLimTspecInfo, tpLimTspecInfo *); +static tSirRetStatus +limValidateAccessPolicy(tpAniSirGlobal, tANI_U8, tANI_U16, tpPESession); + + +/** ------------------------------------------------------------- +\fn limCalculateSvcInt +\brief TSPEC validation and servcie interval determination +\param tpAniSirGlobal pMac +\param tSirMacTspecIE *pTspec +\param tANI_U32 *pSvcInt +\return eSirRetStatus - status of the comparison + -------------------------------------------------------------*/ + +static tSirRetStatus +limCalculateSvcInt( + tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, + tANI_U32 *pSvcInt) +{ + tANI_U32 msduSz, dataRate; + *pSvcInt = 0; + + // if a service interval is already specified, we are done + if ((pTspec->minSvcInterval != 0) || (pTspec->maxSvcInterval != 0)) + { + *pSvcInt = (pTspec->maxSvcInterval != 0) + ? pTspec->maxSvcInterval : pTspec->minSvcInterval; + return eSIR_SUCCESS; + } + + /* Masking off the fixed bits according to definition of MSDU size + * in IEEE 802.11-2007 spec (section 7.3.2.30). Nominal MSDU size + * is defined as: Bit[0:14]=Size, Bit[15]=Fixed + */ + if (pTspec->nomMsduSz != 0) + msduSz = (pTspec->nomMsduSz & 0x7fff); + else if (pTspec->maxMsduSz != 0) + msduSz = pTspec->maxMsduSz; + else + { + PELOGE(limLog(pMac, LOGE, FL("MsduSize not specified"));) + return eSIR_FAILURE; + } + + /* need to calculate a reasonable service interval + * this is simply the msduSz/meanDataRate + */ + if (pTspec->meanDataRate != 0) dataRate = pTspec->meanDataRate; + else if (pTspec->peakDataRate != 0) dataRate = pTspec->peakDataRate; + else if (pTspec->minDataRate != 0) dataRate = pTspec->minDataRate; + else + { + PELOGE(limLog(pMac, LOGE, FL("DataRate not specified"));) + return eSIR_FAILURE; + } + + *pSvcInt = LIM_CONVERT_SIZE_BITS(msduSz) / LIM_CONVERT_RATE_MBPS(dataRate); + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- +\fn limValidateTspecEdca +\brief validate the parameters in the edca tspec + mandatory fields are derived from 11e Annex I (Table I.1) +\param tpAniSirGlobal pMac +\param tSirMacTspecIE *pTspec +\return eSirRetStatus - status + -------------------------------------------------------------*/ +static tSirRetStatus +limValidateTspecEdca( + tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, + tpPESession psessionEntry) +{ + tANI_U32 maxPhyRate, minPhyRate; + tANI_U32 phyMode; + tSirRetStatus retval = eSIR_SUCCESS; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + limGetAvailableBw(pMac, &maxPhyRate, &minPhyRate, phyMode, + 1 /* bandwidth mult factor */); + // mandatory fields are derived from 11e Annex I (Table I.1) + if ((pTspec->nomMsduSz == 0) || + (pTspec->meanDataRate == 0) || + (pTspec->surplusBw == 0) || + (pTspec->minPhyRate == 0) || + (pTspec->minPhyRate > maxPhyRate)) + { + limLog(pMac, LOGW, FL("Invalid EDCA Tspec: NomMsdu %d, meanDataRate %d, surplusBw %d, minPhyRate %d"), + pTspec->nomMsduSz, pTspec->meanDataRate, pTspec->surplusBw, pTspec->minPhyRate); + retval = eSIR_FAILURE; + } + + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("return status %d"), retval); + return retval; +} + +/** ------------------------------------------------------------- +\fn limValidateTspec +\brief validate the offered tspec +\param tpAniSirGlobal pMac +\param tSirMacTspecIE *pTspec +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +static tSirRetStatus +limValidateTspec( + tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, + tpPESession psessionEntry) +{ + tSirRetStatus retval = eSIR_SUCCESS; + switch (pTspec->tsinfo.traffic.accessPolicy) + { + case SIR_MAC_ACCESSPOLICY_EDCA: + if ((retval = limValidateTspecEdca(pMac, pTspec, psessionEntry)) != eSIR_SUCCESS) + PELOGW(limLog(pMac, LOGW, FL("EDCA tspec invalid"));) + break; + + case SIR_MAC_ACCESSPOLICY_HCCA: + case SIR_MAC_ACCESSPOLICY_BOTH: + // TBD: should we support hybrid tspec as well?? for now, just fall through + default: + limLog(pMac, LOGW, FL("AccessType %d not supported"), + pTspec->tsinfo.traffic.accessPolicy); + retval = eSIR_FAILURE; + break; + } + return retval; +} + +//----------------------------------------------------------------------------- +// Admit Control Policy + + +/** ------------------------------------------------------------- +\fn limComputeMeanBwUsed +\brief determime the used/allocated bandwidth +\param tpAniSirGlobal pMac +\param tANI_U32 *pBw +\param tANI_U32 phyMode +\param tpLimTspecInfo pTspecInfo +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +static void +limComputeMeanBwUsed( + tpAniSirGlobal pMac, + tANI_U32 *pBw, + tANI_U32 phyMode, + tpLimTspecInfo pTspecInfo, + tpPESession psessionEntry) +{ + tANI_U32 ctspec; + *pBw = 0; + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) + { + if (pTspecInfo->inuse) + { + tpDphHashNode pSta = dphGetHashEntry(pMac, pTspecInfo->assocId, &psessionEntry->dph.dphHashTable); + if (pSta == NULL) + { + // maybe we should delete the tspec?? + limLog(pMac, LOGE, FL("Tspec %d (assocId %d): dphNode not found"), + ctspec, pTspecInfo->assocId); + continue; + } + *pBw += pTspecInfo->tspec.meanDataRate; + } + } +} + +/** ------------------------------------------------------------- +\fn limGetAvailableBw +\brief based on the phy mode and the bw_factor, determine the total bandwidth that + can be supported +\param tpAniSirGlobal pMac +\param tANI_U32 *pMaxBw +\param tANI_U32 *pMinBw +\param tANI_U32 phyMode +\param tANI_U32 bw_factor +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +static void +limGetAvailableBw( + tpAniSirGlobal pMac, + tANI_U32 *pMaxBw, + tANI_U32 *pMinBw, + tANI_U32 phyMode, + tANI_U32 bw_factor) +{ + switch (phyMode) + { + case WNI_CFG_PHY_MODE_11B: + *pMaxBw = LIM_TOTAL_BW_11B; + *pMinBw = LIM_MIN_BW_11B; + break; + + case WNI_CFG_PHY_MODE_11A: + *pMaxBw = LIM_TOTAL_BW_11A; + *pMinBw = LIM_MIN_BW_11A; + break; + + case WNI_CFG_PHY_MODE_11G: + case WNI_CFG_PHY_MODE_NONE: + default: + *pMaxBw = LIM_TOTAL_BW_11G; + *pMinBw = LIM_MIN_BW_11G; + break; + } + *pMaxBw *= bw_factor; +} + +/** ------------------------------------------------------------- +\fn limAdmitPolicyOversubscription +\brief simple admission control policy based on oversubscription + if the total bandwidth of all admitted tspec's exceeds (factor * phy-bw) then + reject the tspec, else admit it. The phy-bw is the peak available bw in the + current phy mode. The 'factor' is the configured oversubscription factor. +\param tpAniSirGlobal pMac +\param tSirMacTspecIE *pTspec +\param tpLimAdmitPolicyInfo pAdmitPolicy +\param tpLimTspecInfo pTspecInfo +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +/* + * simple admission control policy based on oversubscription + * if the total bandwidth of all admitted tspec's exceeds (factor * phy-bw) then + * reject the tspec, else admit it. The phy-bw is the peak available bw in the + * current phy mode. The 'factor' is the configured oversubscription factor. + */ +static tSirRetStatus +limAdmitPolicyOversubscription( + tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, + tpLimAdmitPolicyInfo pAdmitPolicy, + tpLimTspecInfo pTspecInfo, + tpPESession psessionEntry) +{ + tANI_U32 totalbw, minbw, usedbw; + tANI_U32 phyMode; + + // determine total bandwidth used so far + limGetPhyMode(pMac, &phyMode, psessionEntry); + + limComputeMeanBwUsed(pMac, &usedbw, phyMode, pTspecInfo, psessionEntry); + + // determine how much bandwidth is available based on the current phy mode + limGetAvailableBw(pMac, &totalbw, &minbw, phyMode, pAdmitPolicy->bw_factor); + + if (usedbw > totalbw) // this can't possibly happen + return eSIR_FAILURE; + + if ((totalbw - usedbw) < pTspec->meanDataRate) + { + limLog(pMac, ADMIT_CONTROL_POLICY_LOGLEVEL, + FL("Total BW %d, Used %d, Tspec request %d not possible"), + totalbw, usedbw, pTspec->meanDataRate); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limAdmitPolicy +\brief determine the current admit control policy and apply it for the offered tspec +\param tpAniSirGlobal pMac +\param tSirMacTspecIE *pTspec +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus limAdmitPolicy( + tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, + tpPESession psessionEntry) +{ + tSirRetStatus retval = eSIR_FAILURE; + tpLimAdmitPolicyInfo pAdmitPolicy = &pMac->lim.admitPolicyInfo; + + switch (pAdmitPolicy->type) + { + case WNI_CFG_ADMIT_POLICY_ADMIT_ALL: + retval = eSIR_SUCCESS; + break; + + case WNI_CFG_ADMIT_POLICY_BW_FACTOR: + retval = limAdmitPolicyOversubscription(pMac, pTspec, + &pMac->lim.admitPolicyInfo, &pMac->lim.tspecInfo[0], psessionEntry); + if (retval != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("rejected by BWFactor policy"));) + break; + + case WNI_CFG_ADMIT_POLICY_REJECT_ALL: + retval = eSIR_FAILURE; + break; + + default: + retval = eSIR_SUCCESS; + limLog(pMac, LOGE, FL("Admit Policy %d unknown, admitting all traffic"), + pAdmitPolicy->type); + break; + } + return retval; +} + +/** ------------------------------------------------------------- +\fn limTspecDelete +\brief delete the specified tspec +\param tpAniSirGlobal pMac +\param tpLimTspecInfo pInfo +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +//----------------------------------------------------------------------------- +// delete the specified tspec +void limTspecDelete(tpAniSirGlobal pMac, tpLimTspecInfo pInfo) +{ + if (pInfo == NULL) + return; + //pierre + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("tspec entry = %d"), pInfo->idx); + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("delete tspec %p"), pInfo); + pInfo->inuse = 0; + + return; +} + +/** ------------------------------------------------------------- +\fn limTspecFindByStaAddr +\brief Send halMsg_AddTs to HAL +\param tpAniSirGlobal pMac +\param \param tANI_U8 *pAddr +\param tSirMacTspecIE *pTspecIE +\param tpLimTspecInfo pTspecList +\param tpLimTspecInfo *ppInfo +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +// find the specified tspec in the list +static tSirRetStatus +limTspecFindByStaAddr( + tpAniSirGlobal pMac, + tANI_U8 *pAddr, + tSirMacTspecIE *pTspecIE, + tpLimTspecInfo pTspecList, + tpLimTspecInfo *ppInfo) +{ + int ctspec; + + *ppInfo = NULL; + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) + { + if ((pTspecList->inuse) + && (vos_mem_compare(pAddr, pTspecList->staAddr, sizeof(pTspecList->staAddr))) + && (vos_mem_compare((tANI_U8 *) pTspecIE, (tANI_U8 *) &pTspecList->tspec, + sizeof(tSirMacTspecIE)))) + { + *ppInfo = pTspecList; + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- +\fn limTspecFindByAssocId +\brief find tspec with matchin staid and Tspec +\param tpAniSirGlobal pMac +\param tANI_U32 staid +\param tSirMacTspecIE *pTspecIE +\param tpLimTspecInfo pTspecList +\param tpLimTspecInfo *ppInfo +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +limTspecFindByAssocId( + tpAniSirGlobal pMac, + tANI_U16 assocId, + tSirMacTspecIE *pTspecIE, + tpLimTspecInfo pTspecList, + tpLimTspecInfo *ppInfo) +{ + int ctspec; + + *ppInfo = NULL; + + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Trying to find tspec entry for assocId = %d"), assocId); + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("pTsInfo->traffic.direction = %d, pTsInfo->traffic.tsid = %d"), + pTspecIE->tsinfo.traffic.direction, pTspecIE->tsinfo.traffic.tsid); + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) + { + if ((pTspecList->inuse) + && (assocId == pTspecList->assocId) + && (vos_mem_compare((tANI_U8 *)pTspecIE, (tANI_U8 *)&pTspecList->tspec, + sizeof(tSirMacTspecIE)))) + { + *ppInfo = pTspecList; + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- +\fn limFindTspec +\brief finding a TSPEC entry with assocId, tsinfo.direction and tsinfo.tsid +\param tANI_U16 assocId +\param tpAniSirGlobal pMac +\param tSirMacTSInfo *pTsInfo +\param tpLimTspecInfo pTspecList +\param tpLimTspecInfo *ppInfo +\return eSirRetStatus - status of the comparison + -------------------------------------------------------------*/ + +tSirRetStatus +limFindTspec( + tpAniSirGlobal pMac, + tANI_U16 assocId, + tSirMacTSInfo *pTsInfo, + tpLimTspecInfo pTspecList, + tpLimTspecInfo *ppInfo) +{ + int ctspec; + + *ppInfo = NULL; + + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Trying to find tspec entry for assocId = %d"), assocId); + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("pTsInfo->traffic.direction = %d, pTsInfo->traffic.tsid = %d"), + pTsInfo->traffic.direction, pTsInfo->traffic.tsid); + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) + { + if ((pTspecList->inuse) + && (assocId == pTspecList->assocId) + && (pTsInfo->traffic.direction == pTspecList->tspec.tsinfo.traffic.direction) + && (pTsInfo->traffic.tsid == pTspecList->tspec.tsinfo.traffic.tsid)) + { + *ppInfo = pTspecList; + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- +\fn limTspecAdd +\brief add or update the specified tspec to the tspec list +\param tpAniSirGlobal pMac +\param tANI_U8 *pAddr +\param tANI_U16 assocId +\param tSirMacTspecIE *pTspec +\param tANI_U32 interval +\param tpLimTspecInfo *ppInfo + +\return eSirRetStatus - status of the comparison + -------------------------------------------------------------*/ + +tSirRetStatus limTspecAdd( + tpAniSirGlobal pMac, + tANI_U8 *pAddr, + tANI_U16 assocId, + tSirMacTspecIE *pTspec, + tANI_U32 interval, + tpLimTspecInfo *ppInfo) +{ + tpLimTspecInfo pTspecList = &pMac->lim.tspecInfo[0]; + *ppInfo = NULL; + + // validate the assocId + if (assocId >= pMac->lim.maxStation) + { + PELOGE(limLog(pMac, LOGE, FL("Invalid assocId 0x%x"), assocId);) + return eSIR_FAILURE; + } + + //decide whether to add/update + { + *ppInfo = NULL; + + if(eSIR_SUCCESS == limFindTspec(pMac, assocId, &pTspec->tsinfo, pTspecList, ppInfo)) + { + //update this entry. + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("updating TSPEC table entry = %d"), + (*ppInfo)->idx); + } + else + { + /* We didn't find one to update. So find a free slot in the + * LIM TSPEC list and add this new entry + */ + tANI_U8 ctspec = 0; + for (ctspec = 0 , pTspecList = &pMac->lim.tspecInfo[0]; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) + { + if (! pTspecList->inuse) + { + limLog(pMac, LOG1, FL("Found free slot in TSPEC list. Add to TSPEC table entry %d"), ctspec); + break; + } + } + + if (ctspec >= LIM_NUM_TSPEC_MAX) + return eSIR_FAILURE; + + //Record the new index entry + pTspecList->idx = ctspec; + } + } + + // update the tspec info + pTspecList->tspec = *pTspec; + pTspecList->assocId = assocId; + vos_mem_copy(pTspecList->staAddr, pAddr, sizeof(pTspecList->staAddr)); + + // for edca tspec's, we are all done + if (pTspec->tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) + { + pTspecList->inuse = 1; + *ppInfo = pTspecList; + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("added entry for EDCA AccessPolicy")); + return eSIR_SUCCESS; + } + + /* + * for hcca tspec's, must set the parameterized bit in the queues + * the 'ts' bit in the queue data structure indicates that the queue is + * parameterized (hcca). When the schedule is written this bit is used + * in the tsid field (bit 3) and the other three bits (0-2) are simply + * filled in as the user priority (or qid). This applies only to uplink + * polls where the qos control field must contain the tsid specified in the + * tspec. + */ + pTspecList->inuse = 1; + *ppInfo = pTspecList; + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("added entry for HCCA AccessPolicy")); + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limValidateAccessPolicy +\brief Validates Access policy +\param tpAniSirGlobal pMac +\param tANI_U8 accessPolicy +\param tANI_U16 assocId +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +static tSirRetStatus +limValidateAccessPolicy( + tpAniSirGlobal pMac, + tANI_U8 accessPolicy, + tANI_U16 assocId, + tpPESession psessionEntry) +{ + tSirRetStatus retval = eSIR_FAILURE; + tpDphHashNode pSta = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); + + if ((pSta == NULL) || (! pSta->valid)) + { + PELOGE(limLog(pMac, LOGE, FL("invalid station address passed"));) + return eSIR_FAILURE; + } + + switch (accessPolicy) + { + case SIR_MAC_ACCESSPOLICY_EDCA: + if (pSta->wmeEnabled || pSta->lleEnabled) + retval = eSIR_SUCCESS; + break; + + case SIR_MAC_ACCESSPOLICY_HCCA: + case SIR_MAC_ACCESSPOLICY_BOTH: + default: + PELOGE(limLog(pMac, LOGE, FL("Invalid accessPolicy %d"), accessPolicy);) + break; + } + + if (retval != eSIR_SUCCESS) + limLog(pMac, LOGW, FL("failed (accPol %d, staId %d, lle %d, wme %d, wsm %d)"), + accessPolicy, pSta->staIndex, pSta->lleEnabled, pSta->wmeEnabled, pSta->wsmEnabled); + + return retval; +} + +/** ------------------------------------------------------------- +\fn limAdmitControlAddTS +\brief Determine if STA with the specified TSPEC can be admitted. If it can, + a schedule element is provided +\param tpAniSirGlobal pMac +\param tANI_U8 *pAddr, +\param tSirAddtsReqInfo *pAddts, +\param tSirMacQosCapabilityIE *pQos, +\param tANI_U16 assocId, // assocId, valid only if alloc==true +\param tANI_U8 alloc, // true=>allocate bw for this tspec, + // else determine only if space is available +\param tSirMacScheduleIE *pSch, +\param tANI_U8 *pTspecIdx //index to the lim tspec table. +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus limAdmitControlAddTS( + tpAniSirGlobal pMac, + tANI_U8 *pAddr, + tSirAddtsReqInfo *pAddts, + tSirMacQosCapabilityStaIE *pQos, + tANI_U16 assocId, // assocId, valid only if alloc==true + tANI_U8 alloc, // true=>allocate bw for this tspec, + // else determine only if space is available + tSirMacScheduleIE *pSch, + tANI_U8 *pTspecIdx, //index to the lim tspec table. + tpPESession psessionEntry + ) +{ + tpLimTspecInfo pTspecInfo; + tSirRetStatus retval; + tANI_U32 svcInterval; + (void) pQos; + + // TBD: modify tspec as needed + // EDCA: need to fill in the medium time and the minimum phy rate + // to be consistent with the desired traffic parameters. + + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("tsid %d, directn %d, start %d, intvl %d, accPolicy %d, up %d"), + pAddts->tspec.tsinfo.traffic.tsid, pAddts->tspec.tsinfo.traffic.direction, + pAddts->tspec.svcStartTime, pAddts->tspec.minSvcInterval, + pAddts->tspec.tsinfo.traffic.accessPolicy, pAddts->tspec.tsinfo.traffic.userPrio); + + // check for duplicate tspec + retval = (alloc) + ? limTspecFindByAssocId(pMac, assocId, &pAddts->tspec, &pMac->lim.tspecInfo[0], &pTspecInfo) + : limTspecFindByStaAddr(pMac, pAddr, &pAddts->tspec, &pMac->lim.tspecInfo[0], &pTspecInfo); + + if (retval == eSIR_SUCCESS) + { + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("duplicate tspec (index %d)!"), pTspecInfo->idx); + return eSIR_FAILURE; + } + + // check that the tspec's are well formed and acceptable + if (limValidateTspec(pMac, &pAddts->tspec, psessionEntry) != eSIR_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("tspec validation failed"));) + return eSIR_FAILURE; + } + + // determine a service interval for the tspec + if (limCalculateSvcInt(pMac, &pAddts->tspec, &svcInterval) != eSIR_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("SvcInt calculate failed"));) + return eSIR_FAILURE; + } + + // determine if the tspec can be admitted or not based on current policy + if (limAdmitPolicy(pMac, &pAddts->tspec, psessionEntry) != eSIR_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("tspec rejected by admit control policy"));) + return eSIR_FAILURE; + } + + // fill in a schedule if requested + if (pSch != NULL) + { + vos_mem_set((tANI_U8 *) pSch, sizeof(*pSch), 0); + pSch->svcStartTime = pAddts->tspec.svcStartTime; + pSch->svcInterval = svcInterval; + pSch->maxSvcDuration = (tANI_U16) pSch->svcInterval; // use SP = SI + pSch->specInterval = 0x1000; // fixed for now: TBD + + pSch->info.direction = pAddts->tspec.tsinfo.traffic.direction; + pSch->info.tsid = pAddts->tspec.tsinfo.traffic.tsid; + pSch->info.aggregation = 0; // no support for aggregation for now: TBD + } + + // if no allocation is requested, done + if (! alloc) + return eSIR_SUCCESS; + + // check that we are in the proper mode to deal with the tspec type + if (limValidateAccessPolicy(pMac, (tANI_U8) pAddts->tspec.tsinfo.traffic.accessPolicy, assocId, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGW, FL("AccessPolicy %d is not valid in current mode"), + pAddts->tspec.tsinfo.traffic.accessPolicy); + return eSIR_FAILURE; + } + + // add tspec to list + if (limTspecAdd(pMac, pAddr, assocId, &pAddts->tspec, svcInterval, &pTspecInfo) + != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("no space in tspec list"));) + return eSIR_FAILURE; + } + + //passing lim tspec table index to the caller + *pTspecIdx = pTspecInfo->idx; + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limAdmitControlDeleteTS +\brief Delete the specified Tspec for the specified STA +\param tpAniSirGlobal pMac +\param tANI_U16 assocId +\param tSirMacTSInfo *pTsInfo +\param tANI_U8 *pTsStatus +\param tANI_U8 *ptspecIdx +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +limAdmitControlDeleteTS( + tpAniSirGlobal pMac, + tANI_U16 assocId, + tSirMacTSInfo *pTsInfo, + tANI_U8 *pTsStatus, + tANI_U8 *ptspecIdx) +{ + tpLimTspecInfo pTspecInfo = NULL; + + if (pTsStatus != NULL) + *pTsStatus = 0; + + if (limFindTspec(pMac, assocId, pTsInfo, &pMac->lim.tspecInfo[0], &pTspecInfo) == eSIR_SUCCESS) + { + if(pTspecInfo != NULL) + { + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Tspec entry %d found"), pTspecInfo->idx); + + *ptspecIdx = pTspecInfo->idx; + limTspecDelete(pMac, pTspecInfo); + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- +\fn limAdmitControlDeleteSta +\brief Delete all TSPEC for the specified STA +\param tpAniSirGlobal pMac +\param tANI_U16 assocId +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +limAdmitControlDeleteSta( + tpAniSirGlobal pMac, + tANI_U16 assocId) +{ + tpLimTspecInfo pTspecInfo = &pMac->lim.tspecInfo[0]; + int ctspec; + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) + { + if (assocId == pTspecInfo->assocId) + { + limTspecDelete(pMac, pTspecInfo); + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Deleting TSPEC %d for assocId %d"), + ctspec, assocId); + } + } + limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("assocId %d done"), assocId); + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limAdmitControlInit +\brief init tspec table +\param tpAniSirGlobal pMac +\return eSirRetStatus - status + -------------------------------------------------------------*/ +tSirRetStatus limAdmitControlInit(tpAniSirGlobal pMac) +{ + vos_mem_set(pMac->lim.tspecInfo, LIM_NUM_TSPEC_MAX * sizeof(tLimTspecInfo), 0); + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limUpdateAdmitPolicy +\brief Set the admit control policy based on CFG parameters +\param tpAniSirGlobal pMac +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus limUpdateAdmitPolicy(tpAniSirGlobal pMac) +{ + tANI_U32 val; + if (wlan_cfgGetInt(pMac, WNI_CFG_ADMIT_POLICY, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Unable to get CFG_ADMIT_POLICY")); + return eSIR_FAILURE; + } + pMac->lim.admitPolicyInfo.type = (tANI_U8) val; + if (wlan_cfgGetInt(pMac, WNI_CFG_ADMIT_BWFACTOR, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Unable to get CFG_ADMIT_BWFACTOR")); + return eSIR_FAILURE; + } + pMac->lim.admitPolicyInfo.bw_factor = (tANI_U8) val; + + PELOG1(limLog(pMac, LOG1, FL("LIM: AdmitPolicy %d, bw_factor %d"), + pMac->lim.admitPolicyInfo.type, pMac->lim.admitPolicyInfo.bw_factor);) + + return eSIR_SUCCESS; +} + + +/** ------------------------------------------------------------- +\fn limSendHalMsgAddTs +\brief Send halMsg_AddTs to HAL +\param tpAniSirGlobal pMac +\param tANI_U16 staIdx +\param tANI_U8 tspecIdx +\param tSirMacTspecIE tspecIE +\param tSirTclasInfo *tclasInfo +\param tANI_U8 tclasProc +\param tANI_U16 tsm_interval +\return eSirRetStatus - status + -------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_ESE +tSirRetStatus +limSendHalMsgAddTs( + tpAniSirGlobal pMac, + tANI_U16 staIdx, + tANI_U8 tspecIdx, + tSirMacTspecIE tspecIE, + tANI_U8 sessionId, + tANI_U16 tsm_interval) +#else +tSirRetStatus +limSendHalMsgAddTs( + tpAniSirGlobal pMac, + tANI_U16 staIdx, + tANI_U8 tspecIdx, + tSirMacTspecIE tspecIE, + tANI_U8 sessionId) +#endif +{ + tSirMsgQ msg; + tpAddTsParams pAddTsParam; + tpPESession psessionEntry = peFindSessionBySessionId(pMac, sessionId); + + if (psessionEntry == NULL) { + limLog( pMac, LOGP, + FL("Unable to get Session for session Id %d"), sessionId); + return eSIR_FAILURE; + } + + pAddTsParam = vos_mem_malloc(sizeof(tAddTsParams)); + if (NULL == pAddTsParam) + { + PELOGW(limLog(pMac, LOGW, FL("AllocateMemory() failed"));) + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_set((tANI_U8 *)pAddTsParam, sizeof(tAddTsParams), 0); + pAddTsParam->staIdx = staIdx; + pAddTsParam->tspecIdx = tspecIdx; + vos_mem_copy(&pAddTsParam->tspec, &tspecIE, sizeof(tSirMacTspecIE)); + pAddTsParam->sessionId = sessionId; + pAddTsParam->sme_session_id = psessionEntry->smeSessionId; + +#ifdef FEATURE_WLAN_ESE + pAddTsParam->tsm_interval = tsm_interval; +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadEnabled && + psessionEntry->is11Rconnection) + pAddTsParam->setRICparams = 1; +#endif + + msg.type = WDA_ADD_TS_REQ; + msg.bodyptr = pAddTsParam; + msg.bodyval = 0; + + /* We need to defer any incoming messages until we get a + * WDA_ADD_TS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, sessionId, msg.type)); + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed"));) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pAddTsParam); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limSendHalMsgDelTs +\brief Send halMsg_AddTs to HAL +\param tpAniSirGlobal pMac +\param tANI_U16 staIdx +\param tANI_U8 tspecIdx +\param tSirAddtsReqInfo addts +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +limSendHalMsgDelTs( + tpAniSirGlobal pMac, + tANI_U16 staIdx, + tANI_U8 tspecIdx, + tSirDeltsReqInfo delts, + tANI_U8 sessionId, + tANI_U8 *bssId) +{ + tSirMsgQ msg; + tpDelTsParams pDelTsParam; + tpPESession psessionEntry = NULL; + + pDelTsParam = vos_mem_malloc(sizeof(tDelTsParams)); + if (NULL == pDelTsParam) + { + limLog(pMac, LOGP, FL("AllocateMemory() failed")); + return eSIR_MEM_ALLOC_FAILED; + } + + msg.type = WDA_DEL_TS_REQ; + msg.bodyptr = pDelTsParam; + msg.bodyval = 0; + vos_mem_set((tANI_U8 *)pDelTsParam, sizeof(tDelTsParams), 0); + + //filling message parameters. + pDelTsParam->staIdx = staIdx; + pDelTsParam->tspecIdx = tspecIdx; + vos_mem_copy(&pDelTsParam->bssId, bssId, sizeof(tSirMacAddr)); + + psessionEntry = peFindSessionBySessionId(pMac, sessionId); + if(psessionEntry == NULL) + { + PELOGE(limLog(pMac, LOGE, + FL("Session does Not exist with given sessionId :%d "), + sessionId);) + goto err; + } + pDelTsParam->sessionId = psessionEntry->smeSessionId; + pDelTsParam->userPrio = delts.wmeTspecPresent? + delts.tspec.tsinfo.traffic.userPrio: delts.tsinfo.traffic.userPrio; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadEnabled && + psessionEntry->is11Rconnection) { + vos_mem_copy(&pDelTsParam->delTsInfo, &delts, sizeof(tSirDeltsReqInfo)); + pDelTsParam->setRICparams = 1; + } +#endif + + PELOGW(limLog(pMac, LOGW, FL("calling wdaPostCtrlMsg()"));) + MTRACE(macTraceMsgTx(pMac, sessionId, msg.type)); + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed"));) + goto err; + } + return eSIR_SUCCESS; + +err: + vos_mem_free(pDelTsParam); + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- +\fn limProcessHalAddTsRsp +\brief This function process the WDA_ADD_TS_RSP from HAL. +\ If response is successful, then send back SME_ADDTS_RSP. +\ Otherwise, send DELTS action frame to peer and then +\ then send back SME_ADDTS_RSP. +\ +\param tpAniSirGlobal pMac +\param tpSirMsgQ limMsg +-------------------------------------------------------------*/ +void limProcessHalAddTsRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpAddTsParams pAddTsRspMsg = NULL; + tpDphHashNode pSta = NULL; + tANI_U16 assocId =0; + tSirMacAddr peerMacAddr; + tANI_U8 rspReqd = 1; + tpPESession psessionEntry = NULL; + + + /* Need to process all the deferred messages enqueued + * since sending the WDA_ADD_TS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if (NULL == limMsg->bodyptr) + { + limLog(pMac, LOGP, FL("Received WDA_ADD_TS_RSP with NULL ")); + goto end; + } + + pAddTsRspMsg = (tpAddTsParams) (limMsg->bodyptr); + + // 090803: Use peFindSessionBySessionId() to obtain the PE session context + // from the sessionId in the Rsp Msg from HAL + psessionEntry = peFindSessionBySessionId(pMac, pAddTsRspMsg->sessionId); + + if(psessionEntry == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId :%d "), pAddTsRspMsg->sessionId);) + limSendSmeAddtsRsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED, psessionEntry, pAddTsRspMsg->tspec, + pMac->lim.gLimAddtsReq.sessionId, pMac->lim.gLimAddtsReq.transactionId); + goto end; + } + + if(pAddTsRspMsg->status == eHAL_STATUS_SUCCESS) + { + PELOG1(limLog(pMac, LOG1, FL("Received successful ADDTS response from HAL "));) + // Use the smesessionId and smetransactionId from the PE session context + limSendSmeAddtsRsp(pMac, rspReqd, eSIR_SME_SUCCESS, psessionEntry, pAddTsRspMsg->tspec, + psessionEntry->smeSessionId, psessionEntry->transactionId); + goto end; + } + else + { + PELOG1(limLog(pMac, LOG1, FL("Received failure ADDTS response from HAL "));) + + // Send DELTS action frame to AP + // 090803: Get peer MAC addr from session + sirCopyMacAddr(peerMacAddr,psessionEntry->bssId); + + // 090803: Add the SME Session ID + limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, &pAddTsRspMsg->tspec.tsinfo, &pAddTsRspMsg->tspec, + psessionEntry); + + // Delete TSPEC + // 090803: Pull the hash table from the session + pSta = dphLookupAssocId(pMac, pAddTsRspMsg->staIdx, &assocId, + &psessionEntry->dph.dphHashTable); + if (pSta != NULL) + limAdmitControlDeleteTS(pMac, assocId, &pAddTsRspMsg->tspec.tsinfo, NULL, (tANI_U8 *)&pAddTsRspMsg->tspecIdx); + + // Send SME_ADDTS_RSP + // 090803: Use the smesessionId and smetransactionId from the PE session context + limSendSmeAddtsRsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED, psessionEntry, pAddTsRspMsg->tspec, + psessionEntry->smeSessionId, psessionEntry->transactionId); + goto end; + } + +end: + if (pAddTsRspMsg != NULL) + vos_mem_free(pAddTsRspMsg); + return; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c new file mode 100644 index 000000000000..2827fc77b26d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c @@ -0,0 +1,2679 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file limApi.cc contains the functions that are + * exported by LIM to other modules. + * + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "wniCfgSta.h" +#include "wniApi.h" +#include "sirCommon.h" +#include "sirDebug.h" +#include "cfgApi.h" + +#include "schApi.h" +#include "utilsApi.h" +#include "limApi.h" +#include "limGlobal.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limPropExtsUtils.h" +#include "limSerDesUtils.h" +#include "limIbssPeerMgmt.h" +#include "limAdmitControl.h" +#include "pmmApi.h" +#include "logDump.h" +#include "limSendSmeRspMessages.h" +#include "wmmApsd.h" +#include "limTrace.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "wlan_qct_wda.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif + +#include +#include "vos_types.h" +#include "vos_packet.h" +#include "vos_utils.h" +#include "wlan_qct_tl.h" +#include "sysStartup.h" + + +static void __limInitScanVars(tpAniSirGlobal pMac) +{ + pMac->lim.gLimUseScanModeForLearnMode = 1; + + pMac->lim.gLimSystemInScanLearnMode = 0; + + // Scan related globals on STA + pMac->lim.gLimReturnAfterFirstMatch = 0; + pMac->lim.gLim24Band11dScanDone = 0; + pMac->lim.gLim50Band11dScanDone = 0; + pMac->lim.gLimReturnUniqueResults = 0; + + // Background Scan related globals on STA + pMac->lim.gLimNumOfBackgroundScanSuccess = 0; + pMac->lim.gLimNumOfConsecutiveBkgndScanFailure = 0; + pMac->lim.gLimNumOfForcedBkgndScan = 0; + pMac->lim.gLimBackgroundScanDisable = false; //based on BG timer + pMac->lim.gLimForceBackgroundScanDisable = false; //debug control flag + pMac->lim.gLimBackgroundScanTerminate = TRUE; //controlled by SME + pMac->lim.gLimReportBackgroundScanResults = FALSE; //controlled by SME + + pMac->lim.gLimCurrentScanChannelId = 0; + pMac->lim.gpLimMlmScanReq = NULL; + pMac->lim.gDeferMsgTypeForNOA = 0; + pMac->lim.gpDefdSmeMsgForNOA = NULL; + pMac->lim.gLimMlmScanResultLength = 0; + pMac->lim.gLimSmeScanResultLength = 0; + + vos_mem_set(pMac->lim.gLimCachedScanHashTable, + sizeof(pMac->lim.gLimCachedScanHashTable), 0); + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + + pMac->lim.gLimMlmLfrScanResultLength = 0; + pMac->lim.gLimSmeLfrScanResultLength = 0; + + vos_mem_set(pMac->lim.gLimCachedLfrScanHashTable, + sizeof(pMac->lim.gLimCachedLfrScanHashTable), 0); +#endif + pMac->lim.gLimBackgroundScanChannelId = 0; + pMac->lim.gLimBackgroundScanStarted = 0; + pMac->lim.gLimRestoreCBNumScanInterval = LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT; + pMac->lim.gLimRestoreCBCount = 0; + vos_mem_set(pMac->lim.gLimLegacyBssidList, + sizeof(pMac->lim.gLimLegacyBssidList), 0); + + /* Fill in default values */ + pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = 0; + + // abort scan is used to abort an on-going scan + pMac->lim.abortScan = 0; + vos_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0); + vos_mem_set(&pMac->lim.dfschannelList, sizeof(tSirDFSChannelList), 0); + +//WLAN_SUSPEND_LINK Related + pMac->lim.gpLimSuspendCallback = NULL; + pMac->lim.gpLimResumeCallback = NULL; +//end WLAN_SUSPEND_LINK Related +} + + +static void __limInitBssVars(tpAniSirGlobal pMac) +{ + vos_mem_set((void*)pMac->lim.gpSession, + sizeof(*pMac->lim.gpSession)*pMac->lim.maxBssId, 0); + + /* This is for testing purposes only, be default should always be off */ + pMac->lim.gLimForceNoPropIE = 0; + pMac->lim.gpLimMlmSetKeysReq = NULL; + pMac->lim.gpLimMlmRemoveKeyReq = NULL; +} + + +static void __limInitStatsVars(tpAniSirGlobal pMac) +{ + pMac->lim.gLimNumBeaconsRcvd = 0; + pMac->lim.gLimNumBeaconsIgnored = 0; + + pMac->lim.gLimNumDeferredMsgs = 0; + + /// Variable to keep track of number of currently associated STAs + pMac->lim.gLimNumOfAniSTAs = 0; // count of ANI peers + + // Heart-Beat interval value + pMac->lim.gLimHeartBeatCount = 0; + + vos_mem_zero(pMac->lim.gLimHeartBeatApMac[0], + sizeof(tSirMacAddr)); + vos_mem_zero(pMac->lim.gLimHeartBeatApMac[1], + sizeof(tSirMacAddr)); + pMac->lim.gLimHeartBeatApMacIndex = 0; + + // Statistics to keep track of no. beacons rcvd in heart beat interval + vos_mem_set(pMac->lim.gLimHeartBeatBeaconStats, + sizeof(pMac->lim.gLimHeartBeatBeaconStats), 0); + +#ifdef WLAN_DEBUG + // Debug counters + pMac->lim.numTot = 0; + pMac->lim.numBbt = 0; + pMac->lim.numProtErr = 0; + pMac->lim.numLearn = 0; + pMac->lim.numLearnIgnore = 0; + pMac->lim.numSme = 0; + vos_mem_set(pMac->lim.numMAC, sizeof(pMac->lim.numMAC), 0); + pMac->lim.gLimNumAssocReqDropInvldState = 0; + pMac->lim.gLimNumAssocReqDropACRejectTS = 0; + pMac->lim.gLimNumAssocReqDropACRejectSta = 0; + pMac->lim.gLimNumReassocReqDropInvldState = 0; + pMac->lim.gLimNumHashMissIgnored = 0; + pMac->lim.gLimUnexpBcnCnt = 0; + pMac->lim.gLimBcnSSIDMismatchCnt = 0; + pMac->lim.gLimNumLinkEsts = 0; + pMac->lim.gLimNumRxCleanup = 0; + pMac->lim.gLim11bStaAssocRejectCount = 0; +#endif +} + +static void __limInitStates(tpAniSirGlobal pMac) +{ + // Counts Heartbeat failures + pMac->lim.gLimHBfailureCntInLinkEstState = 0; + pMac->lim.gLimProbeFailureAfterHBfailedCnt = 0; + pMac->lim.gLimHBfailureCntInOtherStates = 0; + pMac->lim.gLimRspReqd = 0; + pMac->lim.gLimPrevSmeState = eLIM_SME_OFFLINE_STATE; + + /// MLM State visible across all Sirius modules + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, eLIM_MLM_IDLE_STATE)); + pMac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE; + + /// Previous MLM State + pMac->lim.gLimPrevMlmState = eLIM_MLM_OFFLINE_STATE; + + // LIM to HAL SCAN Management Message Interface states + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + + /** + * Initialize state to eLIM_SME_OFFLINE_STATE + */ + pMac->lim.gLimSmeState = eLIM_SME_OFFLINE_STATE; + + /** + * By default assume 'unknown' role. This will be updated + * when SME_START_BSS_REQ is received. + */ + + vos_mem_set(&pMac->lim.gLimOverlap11gParams, sizeof(tLimProtStaParams), 0); + vos_mem_set(&pMac->lim.gLimOverlap11aParams, sizeof(tLimProtStaParams), 0); + vos_mem_set(&pMac->lim.gLimOverlapHt20Params, sizeof(tLimProtStaParams), 0); + vos_mem_set(&pMac->lim.gLimOverlapNonGfParams, sizeof(tLimProtStaParams), 0); + vos_mem_set(&pMac->lim.gLimNoShortParams, sizeof(tLimNoShortParams), 0); + vos_mem_set(&pMac->lim.gLimNoShortSlotParams, sizeof(tLimNoShortSlotParams), 0); + + pMac->lim.gLimPhyMode = 0; + pMac->lim.scanStartTime = 0; // used to measure scan time + + vos_mem_set(pMac->lim.gLimMyMacAddr, sizeof(pMac->lim.gLimMyMacAddr), 0); + pMac->lim.ackPolicy = 0; + + pMac->lim.gLimProbeRespDisableFlag = 0; // control over probe response +} + +static void __limInitVars(tpAniSirGlobal pMac) +{ + // Place holder for Measurement Req/Rsp/Ind related info + + // Deferred Queue Paramters + vos_mem_set(&pMac->lim.gLimDeferredMsgQ, sizeof(tSirAddtsReq), 0); + + // addts request if any - only one can be outstanding at any time + vos_mem_set(&pMac->lim.gLimAddtsReq, sizeof(tSirAddtsReq) , 0); + pMac->lim.gLimAddtsSent = 0; + pMac->lim.gLimAddtsRspTimerCount = 0; + + //protection related config cache + vos_mem_set(&pMac->lim.cfgProtection, sizeof(tCfgProtection), 0); + pMac->lim.gLimProtectionControl = 0; + vos_mem_set(&pMac->lim.gLimAlternateRadio, sizeof(tSirAlternateRadioInfo), 0); + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + // WMM Related Flag + pMac->lim.gUapsdEnable = 0; + pMac->lim.gUapsdPerAcBitmask = 0; + pMac->lim.gUapsdPerAcTriggerEnableMask = 0; + pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; + + // QoS-AC Downgrade: Initially, no AC is admitted + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] = 0; + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] = 0; + + //dialogue token List head/tail for Action frames request sent. + pMac->lim.pDialogueTokenHead = NULL; + pMac->lim.pDialogueTokenTail = NULL; + + vos_mem_set(&pMac->lim.tspecInfo, + sizeof(tLimTspecInfo) * LIM_NUM_TSPEC_MAX, 0); + + // admission control policy information + vos_mem_set(&pMac->lim.admitPolicyInfo, sizeof(tLimAdmitPolicyInfo), 0); + + pMac->lim.gLastBeaconDtimCount = 0; + pMac->lim.gLastBeaconDtimPeriod = 0; + + //Scan in Power Save Flag + pMac->lim.gScanInPowersave = 0; + pMac->lim.probeCounter = 0; + pMac->lim.maxProbe = 0; + +#ifdef SAP_AUTH_OFFLOAD + /* Init SAP deffered Q Head */ + lim_init_sap_deferred_msg_queue(pMac); +#endif +} + +static void __limInitAssocVars(tpAniSirGlobal pMac) +{ + tANI_U32 val; + if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) + { + limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); + } + pMac->lim.gLimAssocStaLimit = val; + pMac->lim.gLimIbssStaLimit = val; + // Place holder for current authentication request + // being handled + pMac->lim.gpLimMlmAuthReq = NULL; + + /// MAC level Pre-authentication related globals + pMac->lim.gLimPreAuthChannelNumber = 0; + pMac->lim.gLimPreAuthType = eSIR_OPEN_SYSTEM; + vos_mem_set(&pMac->lim.gLimPreAuthPeerAddr, sizeof(tSirMacAddr), 0); + pMac->lim.gLimNumPreAuthContexts = 0; + vos_mem_set(&pMac->lim.gLimPreAuthTimerTable, sizeof(tLimPreAuthTable), 0); + + // Placed holder to deauth reason + pMac->lim.gLimDeauthReasonCode = 0; + + // Place holder for Pre-authentication node list + pMac->lim.pLimPreAuthList = NULL; + + // Send Disassociate frame threshold parameters + pMac->lim.gLimDisassocFrameThreshold = LIM_SEND_DISASSOC_FRAME_THRESHOLD; + pMac->lim.gLimDisassocFrameCredit = 0; + + //One cache for each overlap and associated case. + vos_mem_set(pMac->lim.protStaOverlapCache, + sizeof(tCacheParams) * LIM_PROT_STA_OVERLAP_CACHE_SIZE, 0); + vos_mem_set(pMac->lim.protStaCache, + sizeof(tCacheParams) * LIM_PROT_STA_CACHE_SIZE, 0); + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pMac->lim.pSessionEntry = NULL; + pMac->lim.reAssocRetryAttempt = 0; +#endif + +} + +static void __limInitHTVars(tpAniSirGlobal pMac) +{ + pMac->lim.htCapabilityPresentInBeacon = 0; + pMac->lim.gHTGreenfield = 0; + pMac->lim.gHTShortGI40Mhz = 0; + pMac->lim.gHTShortGI20Mhz = 0; + pMac->lim.gHTMaxAmsduLength = 0; + pMac->lim.gHTDsssCckRate40MHzSupport = 0; + pMac->lim.gHTPSMPSupport = 0; + pMac->lim.gHTLsigTXOPProtection = 0; + pMac->lim.gHTMIMOPSState = eSIR_HT_MIMO_PS_STATIC; + pMac->lim.gHTAMpduDensity = 0; + + pMac->lim.gMaxAmsduSizeEnabled = false; + pMac->lim.gHTMaxRxAMpduFactor = 0; + pMac->lim.gHTServiceIntervalGranularity = 0; + pMac->lim.gHTControlledAccessOnly = 0; + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + pMac->lim.gHTPCOActive = 0; + + pMac->lim.gHTPCOPhase = 0; + pMac->lim.gHTSecondaryBeacon = 0; + pMac->lim.gHTDualCTSProtection = 0; + pMac->lim.gHTSTBCBasicMCS = 0; + pMac->lim.gAddBA_Declined = 0; // Flag to Decline the BAR if the particular bit (0-7) is being set +} + +static tSirRetStatus __limInitConfig( tpAniSirGlobal pMac ) +{ + tANI_U32 val1, val2, val3; + tANI_U16 val16; + tANI_U8 val8; + tSirMacHTCapabilityInfo *pHTCapabilityInfo; + tSirMacHTInfoField1 *pHTInfoField1; + tpSirPowerSaveCfg pPowerSaveConfig; + tSirMacHTParametersInfo *pAmpduParamInfo; + + /* Read all the CFGs here that were updated before peStart is called */ + /* All these CFG READS/WRITES are only allowed in init, at start when there is no session + * and they will be used throughout when there is no session + */ + + if(wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) + return eSIR_FAILURE; + } + + if(wlan_cfgGetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Channel Bonding CFG"));) + return eSIR_FAILURE; + } + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + + pHTCapabilityInfo->supportedChannelWidthSet = val2 ? + WNI_CFG_CHANNEL_BONDING_MODE_ENABLE : WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) + != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + return eSIR_FAILURE; + } + + if(wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD1, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT INFO Field1 CFG"));) + return eSIR_FAILURE; + } + + val8 = ( tANI_U8 ) val1; + pHTInfoField1 = ( tSirMacHTInfoField1* ) &val8; + pHTInfoField1->recommendedTxWidthSet = + (tANI_U8)pHTCapabilityInfo->supportedChannelWidthSet; + if(cfgSetInt(pMac, WNI_CFG_HT_INFO_FIELD1, *(tANI_U8*)pHTInfoField1) + != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not update HT Info Field"));) + return eSIR_FAILURE; + } + + /* WNI_CFG_HEART_BEAT_THRESHOLD */ + + if( wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != + eSIR_SUCCESS ) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG"));) + return eSIR_FAILURE; + } + if(!val1) + { + limDeactivateAndChangeTimer(pMac, eLIM_HEART_BEAT_TIMER); + pMac->sys.gSysEnableLinkMonitorMode = 0; + } + else + { + //No need to activate the timer during init time. + pMac->sys.gSysEnableLinkMonitorMode = 1; + } + + /* WNI_CFG_SHORT_GI_20MHZ */ + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) + return eSIR_FAILURE; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG"));) + return eSIR_FAILURE; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val3) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG"));) + return eSIR_FAILURE; + } + + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + pHTCapabilityInfo->shortGI20MHz = (tANI_U16)val2; + pHTCapabilityInfo->shortGI40MHz = (tANI_U16)val3; + + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != + eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + return eSIR_FAILURE; + } + + /* WNI_CFG_MAX_RX_AMPDU_FACTOR */ + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) + return eSIR_FAILURE; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG"));) + } + if (wlan_cfgGetInt(pMac, WNI_CFG_MPDU_DENSITY, &val3) != eSIR_SUCCESS) { + limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG")); + return eSIR_FAILURE; + } + + val16 = ( tANI_U16 ) val1; + pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; + pAmpduParamInfo->maxRxAMPDUFactor = (tANI_U8)val2; + pAmpduParamInfo->mpduDensity = (uint8_t)val3; + + if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("cfg get short preamble failed")); + return eSIR_FAILURE; + } + + /* WNI_CFG_SHORT_PREAMBLE - this one is not updated in + limHandleCFGparamUpdate do we want to update this? */ + if(wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val1) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("cfg get short preamble failed")); + return eSIR_FAILURE; + } + + /* WNI_CFG_MAX_PS_POLL */ + + if (!pMac->psOffloadEnabled) + { + /* Allocate and fill in power save configuration. */ + pPowerSaveConfig = vos_mem_malloc(sizeof(tSirPowerSaveCfg)); + if (NULL == pPowerSaveConfig) + { + PELOGE(limLog(pMac, LOGE, + FL("LIM: Cannot allocate memory for power save configuration"));) + return eSIR_FAILURE; + } + + /* This context should be valid if power-save configuration message has + * been already dispatched during initialization process. Re-using the + * present configuration mask + */ + vos_mem_copy(pPowerSaveConfig, (tANI_U8 *)&pMac->pmm.gPmmCfg, + sizeof(tSirPowerSaveCfg)); + + /* Note: it is okay to do this since DAL/HAL is alrady started */ + if ( (pmmSendPowerSaveCfg(pMac, pPowerSaveConfig)) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, + FL("LIM: pmmSendPowerSaveCfg() failed "));) + return eSIR_FAILURE; + } + } + + /* WNI_CFG_BG_SCAN_CHANNEL_LIST_CHANNEL_LIST */ + + PELOG1(limLog(pMac, LOG1, + FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel"));) + pMac->lim.gLimBackgroundScanChannelId = 0; + + /* WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA - not needed */ + + /* This was initially done after resume notification from HAL. Now, DAL is + started before PE so this can be done here */ + handleHTCapabilityandHTInfo(pMac, NULL); + if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, + (tANI_U32 *) &pMac->lim.disableLDPCWithTxbfAP)) + { + limLog(pMac, LOGP, FL("cfg get disableLDPCWithTxbfAP failed")); + return eSIR_FAILURE; + } +#ifdef FEATURE_WLAN_TDLS + if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_BUF_STA_ENABLED, + (tANI_U32 *) &pMac->lim.gLimTDLSBufStaEnabled)) + { + limLog(pMac, LOGP, FL("cfg get LimTDLSBufStaEnabled failed")); + return eSIR_FAILURE; + } + if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, + (tANI_U32 *) &pMac->lim.gLimTDLSUapsdMask)) + { + limLog(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed")); + return eSIR_FAILURE; + } + if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, + (tANI_U32 *) &pMac->lim.gLimTDLSOffChannelEnabled)) + { + limLog(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed")); + return eSIR_FAILURE; + } + + if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_WMM_MODE_ENABLED, + (tANI_U32 *) &pMac->lim.gLimTDLSWmmMode)) + { + limLog(pMac, LOGP, FL("cfg get LimTDLSWmmMode failed")); + return eSIR_FAILURE; + } +#endif + return eSIR_SUCCESS; +} + +/* + limStart + This function is to replace the __limProcessSmeStartReq since there is no + eWNI_SME_START_REQ post to PE. +*/ +tSirRetStatus limStart(tpAniSirGlobal pMac) +{ + tSirResultCodes retCode = eSIR_SUCCESS; + + PELOG1(limLog(pMac, LOG1, FL(" enter"));) + + if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) + { + pMac->lim.gLimSmeState = eLIM_SME_IDLE_STATE; + + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, NO_SESSION, pMac->lim.gLimSmeState)); + + // By default do not return after first scan match + pMac->lim.gLimReturnAfterFirstMatch = 0; + + // Initialize MLM state machine + if (eSIR_SUCCESS != limInitMlm(pMac)) { + limLog(pMac, LOGE, FL("Init MLM failed.")); + return eSIR_FAILURE; + } + + // By default return unique scan results + pMac->lim.gLimReturnUniqueResults = true; + pMac->lim.gLimSmeScanResultLength = 0; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->lim.gLimSmeLfrScanResultLength = 0; +#endif + } + else + { + /** + * Should not have received eWNI_SME_START_REQ in states + * other than OFFLINE. Return response to host and + * log error + */ + limLog(pMac, LOGE, FL("Invalid SME state %X"),pMac->lim.gLimSmeState ); + retCode = eSIR_FAILURE; + } + + return retCode; +} + +/** + * limInitialize() + * + *FUNCTION: + * This function is called from LIM thread entry function. + * LIM related global data structures are initialized in this function. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to global MAC structure + * @return None + */ + +tSirRetStatus +limInitialize(tpAniSirGlobal pMac) +{ + tSirRetStatus status = eSIR_SUCCESS; + + __limInitAssocVars(pMac); + __limInitVars(pMac); + __limInitStates(pMac); + __limInitStatsVars(pMac); + __limInitBssVars(pMac); + __limInitScanVars(pMac); + __limInitHTVars(pMac); + + status = limStart(pMac); + if(eSIR_SUCCESS != status) + { + return status; + } + + // Initializations for maintaining peers in IBSS + limIbssInit(pMac); + + if(!pMac->psOffloadEnabled) + pmmInitialize(pMac); + +#if defined WLAN_FEATURE_VOWIFI + rrmInitialize(pMac); +#endif + + vos_list_init(&pMac->lim.gLimMgmtFrameRegistratinQueue); + + //Initialize the configurations needed by PE + if( eSIR_FAILURE == __limInitConfig(pMac)) + { + //We need to undo everything in limStart + limCleanupMlm(pMac); + return eSIR_FAILURE; + } + + //initialize the TSPEC admission control table. + //Note that this was initially done after resume notification from HAL. + //Now, DAL is started before PE so this can be done here + limAdmitControlInit(pMac); + limRegisterHalIndCallBack(pMac); + + return status; + +} /*** end limInitialize() ***/ + + + +/** + * limCleanup() + * + *FUNCTION: + * This function is called upon reset or persona change + * to cleanup LIM state + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limCleanup(tpAniSirGlobal pMac) +{ +//Before destroying the list making sure all the nodes have been deleted. +//Which should be the normal case, but a memory leak has been reported. + uint8_t i; + + tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL; + + while(vos_list_remove_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, + (vos_list_node_t**)&pLimMgmtRegistration) == VOS_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("Fixing leak! Deallocating pLimMgmtRegistration node")); + + vos_mem_free(pLimMgmtRegistration); + } + + vos_list_destroy(&pMac->lim.gLimMgmtFrameRegistratinQueue); + + limCleanupMlm(pMac); + limCleanupLmm(pMac); + + // free up preAuth table + if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL) + { + for (i = 0; i < pMac->lim.gLimPreAuthTimerTable.numEntry; i++) + vos_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable[i]); + vos_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable); + pMac->lim.gLimPreAuthTimerTable.pTable = NULL; + pMac->lim.gLimPreAuthTimerTable.numEntry = 0; + } + + if(NULL != pMac->lim.pDialogueTokenHead) + { + limDeleteDialogueTokenList(pMac); + } + + if(NULL != pMac->lim.pDialogueTokenTail) + { + vos_mem_free(pMac->lim.pDialogueTokenTail); + pMac->lim.pDialogueTokenTail = NULL; + } + + if (pMac->lim.gpLimMlmSetKeysReq != NULL) + { + vos_mem_free(pMac->lim.gpLimMlmSetKeysReq); + pMac->lim.gpLimMlmSetKeysReq = NULL; + } + + if (pMac->lim.gpLimMlmAuthReq != NULL) + { + vos_mem_free(pMac->lim.gpLimMlmAuthReq); + pMac->lim.gpLimMlmAuthReq = NULL; + } + + if (pMac->lim.gpLimMlmRemoveKeyReq != NULL) + { + vos_mem_free(pMac->lim.gpLimMlmRemoveKeyReq); + pMac->lim.gpLimMlmRemoveKeyReq = NULL; + } + + if (pMac->lim.gpDefdSmeMsgForNOA != NULL) + { + vos_mem_free(pMac->lim.gpDefdSmeMsgForNOA); + pMac->lim.gpDefdSmeMsgForNOA = NULL; + } + + if (pMac->lim.gpLimMlmScanReq != NULL) + { + vos_mem_free(pMac->lim.gpLimMlmScanReq); + pMac->lim.gpLimMlmScanReq = NULL; + } + + // Now, finally reset the deferred message queue pointers + limResetDeferredMsgQ(pMac); + +#if defined WLAN_FEATURE_VOWIFI + rrmCleanup(pMac); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + limFTCleanupAllFTSessions(pMac); +#endif + +#ifdef SAP_AUTH_OFFLOAD + lim_cleanup_sap_deferred_msg_queue(pMac); +#endif + +} /*** end limCleanup() ***/ + + +#ifdef WLAN_FEATURE_11W +/** + * lim_is_assoc_req_for_drop()- function to decides to drop assoc\reassoc + * frames. + * @mac: pointer to global mac structure + * @rx_pkt_info: rx packet meta information + * + * This function is called before enqueuing the frame to PE queue to + * drop flooded assoc/reassoc frames getting into PE Queue. + * + * Return: true for dropping the frame otherwise false + */ + +bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info) +{ + uint8_t session_id; + uint16_t aid; + tpPESession session_entry; + tpSirMacMgmtHdr mac_hdr; + tpDphHashNode sta_ds; + + mac_hdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info); + session_entry = peFindSessionByBssid(mac, mac_hdr->bssId, &session_id); + if (!session_entry) { + PELOG1(limLog(pMac, LOG1, + FL("session does not exist for given STA [%pM]"), + mac_hdr->sa);); + return false; + } + + sta_ds = dphLookupHashEntry(mac, mac_hdr->sa, &aid, + &session_entry->dph.dphHashTable); + if (!sta_ds) { + PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL"));); + return false; + } + + if (!sta_ds->rmfEnabled) + return false; + + if (sta_ds->pmfSaQueryState == DPH_SA_QUERY_IN_PROGRESS) + return true; + + if (sta_ds->last_assoc_received_time && + ((vos_timer_get_system_time() - + sta_ds->last_assoc_received_time) < 1000)) + return true; + + sta_ds->last_assoc_received_time = vos_timer_get_system_time(); + return false; +} +#endif +/** + * lim_is_deauth_diassoc_for_drop()- function to decides to drop deauth\diassoc + * frames. + * @mac: pointer to global mac structure + * @rx_pkt_info: rx packet meta information + * + * This function is called before enqueuing the frame to PE queue to + * drop flooded deauth/diassoc frames getting into PE Queue. + * + * Return: true for dropping the frame otherwise false + */ + +bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info) +{ + uint8_t session_id; + uint16_t aid; + tpPESession session_entry; + tpSirMacMgmtHdr mac_hdr; + tpDphHashNode sta_ds; + + mac_hdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info); + session_entry = peFindSessionByBssid(mac, mac_hdr->bssId, &session_id); + if (!session_entry) { + PELOG1(limLog(mac, LOG1, + FL("session does not exist for given STA [%pM]"), + mac_hdr->sa);); + return true; + } + + sta_ds = dphLookupHashEntry(mac, mac_hdr->sa, &aid, + &session_entry->dph.dphHashTable); + if (!sta_ds) { + PELOG1(limLog(mac, LOG1,FL("pStaDs is NULL"));); + return true; + } + +#ifdef WLAN_FEATURE_11W + if (session_entry->limRmfEnabled) { + if ((WDA_GET_RX_DPU_FEEDBACK(rx_pkt_info) & + DPU_FEEDBACK_UNPROTECTED_ERROR)) { + /* It may be possible that deauth/diassoc frames from a + * spoofy AP is received. So if all further + * deauth/diassoc frmaes are dropped, then it may + * result in lossing deauth/diassoc frames from genuine + * AP. So process all deauth/diassoc frames with + * a time difference of 1 sec. + */ + if ((vos_timer_get_system_time() - + sta_ds->last_unprot_deauth_disassoc) < 1000) + return true; + + sta_ds->last_unprot_deauth_disassoc = + vos_timer_get_system_time(); + } else { + /* PMF enabed, Management frames are protected */ + if (sta_ds->proct_deauh_disassoc_cnt) + return true; + else + sta_ds->proct_deauh_disassoc_cnt++; + } + } + else +#endif + /* PMF disabled */ + { + if (sta_ds->isDisassocDeauthInProgress) + return true; + else + sta_ds->isDisassocDeauthInProgress++; + } + + return false; +} + +/** ------------------------------------------------------------- +\fn peOpen +\brief will be called in Open sequence from macOpen +\param tpAniSirGlobal pMac +\param tHalOpenParameters *pHalOpenParam +\return tSirRetStatus + -------------------------------------------------------------*/ + +tSirRetStatus peOpen(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam) +{ + tSirRetStatus status = eSIR_SUCCESS; + + if (eDRIVER_TYPE_MFG == pMacOpenParam->driverType) + return eSIR_SUCCESS; + + pMac->lim.maxBssId = pMacOpenParam->maxBssId; + pMac->lim.maxStation = pMacOpenParam->maxStation; + + if ((pMac->lim.maxBssId == 0) || (pMac->lim.maxStation == 0)) { + PELOGE(limLog(pMac, LOGE, + FL("max number of Bssid or Stations cannot be zero!"));) + return eSIR_FAILURE; + } + + pMac->lim.limTimers.gpLimCnfWaitTimer = vos_mem_malloc(sizeof(TX_TIMER) * + (pMac->lim.maxStation + 1)); + if (NULL == pMac->lim.limTimers.gpLimCnfWaitTimer) { + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) + return eSIR_FAILURE; + } + + pMac->lim.gpSession = vos_mem_malloc(sizeof(tPESession)* + pMac->lim.maxBssId); + if (NULL == pMac->lim.gpSession) { + limLog(pMac, LOGE, FL("memory allocate failed!")); + status = eSIR_FAILURE; + goto pe_open_psession_fail; + } + + vos_mem_set(pMac->lim.gpSession, sizeof(tPESession) * + pMac->lim.maxBssId, 0); + + pMac->pmm.gPmmTim.pTim = vos_mem_malloc(sizeof(tANI_U8) * + pMac->lim.maxStation); + if (NULL == pMac->pmm.gPmmTim.pTim) { + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed for pTim!"));) + status = eSIR_FAILURE; + goto pe_open_ptim_fail; + } + vos_mem_set(pMac->pmm.gPmmTim.pTim, sizeof(tANI_U8) * + pMac->lim.maxStation, 0); + + pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.deferredMsgCnt = 0; + + if (!VOS_IS_STATUS_SUCCESS(vos_lock_init(&pMac->lim.lkPeGlobalLock))) { + PELOGE(limLog(pMac, LOGE, FL("pe lock init failed!"));) + status = eSIR_FAILURE; + goto pe_open_lock_fail; + } + pMac->lim.deauthMsgCnt = 0; + pMac->lim.retry_packet_cnt = 0; + pMac->lim.gLimIbssRetryCnt = 0; + + /* + * peOpen is successful by now, so it is right time to initialize + * MTRACE for PE module. if LIM_TRACE_RECORD is not defined in build file + * then nothing will be logged for PE module. + */ +#ifdef LIM_TRACE_RECORD + MTRACE(limTraceInit(pMac)); +#endif + return status; /* status here will be eSIR_SUCCESS */ + +pe_open_lock_fail: + vos_mem_free(pMac->pmm.gPmmTim.pTim); + pMac->pmm.gPmmTim.pTim = NULL; +pe_open_ptim_fail: + vos_mem_free(pMac->lim.gpSession); + pMac->lim.gpSession = NULL; +pe_open_psession_fail: + vos_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer); + pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; + + return status; +} + +/** ------------------------------------------------------------- +\fn peClose +\brief will be called in close sequence from macClose +\param tpAniSirGlobal pMac +\return tSirRetStatus + -------------------------------------------------------------*/ + +tSirRetStatus peClose(tpAniSirGlobal pMac) +{ + tANI_U8 i; + + if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) + return eSIR_SUCCESS; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + peDeleteSession(pMac,&pMac->lim.gpSession[i]); + } + } + vos_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer); + pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; + + if (pMac->lim.gpLimMlmOemDataReq) { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq); + pMac->lim.gpLimMlmOemDataReq = NULL; + } + + vos_mem_free(pMac->lim.gpSession); + pMac->lim.gpSession = NULL; + vos_mem_free(pMac->pmm.gPmmTim.pTim); + pMac->pmm.gPmmTim.pTim = NULL; + if( !VOS_IS_STATUS_SUCCESS( vos_lock_destroy( &pMac->lim.lkPeGlobalLock ) ) ) + { + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn peStart +\brief will be called in start sequence from macStart +\param tpAniSirGlobal pMac +\return none + -------------------------------------------------------------*/ + +tSirRetStatus peStart(tpAniSirGlobal pMac) +{ + tSirRetStatus status = eSIR_SUCCESS; + + status = limInitialize(pMac); +#if defined(ANI_LOGDUMP) + limDumpInit(pMac); +#endif //#if defined(ANI_LOGDUMP) + + return status; +} + +/** ------------------------------------------------------------- +\fn peStop +\brief will be called in stop sequence from macStop +\param tpAniSirGlobal pMac +\return none + -------------------------------------------------------------*/ + +void peStop(tpAniSirGlobal pMac) +{ + limCleanup(pMac); + SET_LIM_MLM_STATE(pMac, eLIM_MLM_OFFLINE_STATE); + return; +} + +/** ------------------------------------------------------------- +\fn peFreeMsg +\brief Called by VOS scheduler (function vos_sched_flush_mc_mqs) +\ to free a given PE message on the TX and MC thread. +\ This happens when there are messages pending in the PE +\ queue when system is being stopped and reset. +\param tpAniSirGlobal pMac +\param tSirMsgQ pMsg +\return none +-----------------------------------------------------------------*/ +v_VOID_t peFreeMsg( tpAniSirGlobal pMac, tSirMsgQ* pMsg) +{ + if (pMsg != NULL) + { + if (NULL != pMsg->bodyptr) + { + if (SIR_BB_XPORT_MGMT_MSG == pMsg->type) + { + vos_pkt_return_packet((vos_pkt_t *)pMsg->bodyptr); + } + else + { + vos_mem_free((v_VOID_t*)pMsg->bodyptr); + } + } + pMsg->bodyptr = 0; + pMsg->bodyval = 0; + pMsg->type = 0; + } + return; +} + + +/** + * The function checks if a particular timer should be allowed + * into LIM while device is sleeping + */ +tANI_U8 limIsTimerAllowedInPowerSaveState(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + tANI_U8 retStatus = TRUE; + + if(!limIsSystemInActiveState(pMac)) + { + switch(pMsg->type) + { + /* Don't allow following timer messages if in sleep */ + case SIR_LIM_MIN_CHANNEL_TIMEOUT: + case SIR_LIM_MAX_CHANNEL_TIMEOUT: + case SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT: + retStatus = FALSE; + break; + /* May allow following timer messages in sleep mode */ + case SIR_LIM_HASH_MISS_THRES_TIMEOUT: + + /* Safe to allow as of today, this triggers background scan + * which will not be started if the device is in power-save mode + * might need to block in the future if we decide to implement + * spectrum management + */ + case SIR_LIM_QUIET_TIMEOUT: + + /* Safe to allow as of today, this triggers background scan + * which will not be started if the device is in power-save mode + * might need to block in the future if we decide to implement + * spectrum management + */ + case SIR_LIM_QUIET_BSS_TIMEOUT: + + /* Safe to allow this timermessage, triggers background scan + * which is blocked in sleep mode + */ + case SIR_LIM_CHANNEL_SCAN_TIMEOUT: + + /* Safe to allow this timer, since, while in IMPS this timer will not + * be started. In case of BMPS sleep, SoftMAC handles the heart-beat + * when heart-beat control is handled back to PE, device would have + * already woken-up due to EXIT_BMPS_IND mesage from SoftMAC + */ + case SIR_LIM_HEART_BEAT_TIMEOUT: + case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT: + + /* Safe to allow, PE is not handling this message as of now. May need + * to block it, basically, free the buffer and restart the timer + */ + case SIR_LIM_REASSOC_FAIL_TIMEOUT: + case SIR_LIM_JOIN_FAIL_TIMEOUT: + case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT: + case SIR_LIM_ASSOC_FAIL_TIMEOUT: + case SIR_LIM_AUTH_FAIL_TIMEOUT: + case SIR_LIM_ADDTS_RSP_TIMEOUT: + case SIR_LIM_AUTH_RETRY_TIMEOUT: + retStatus = TRUE; + break; + + /* by default allow rest of messages */ + default: + retStatus = TRUE; + break; + + + } + } + + return retStatus; + +} + + + +/** + * limPostMsgApi() + * + *FUNCTION: + * This function is called from other thread while posting a + * message to LIM message Queue gSirLimMsgQ. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pMsg - Pointer to the message structure + * @return None + */ + +tANI_U32 +limPostMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + return vos_mq_post_message(VOS_MQ_ID_PE, (vos_msg_t *) pMsg); + + +} /*** end limPostMsgApi() ***/ + + +/*-------------------------------------------------------------------------- + + \brief pePostMsgApi() - A wrapper function to post message to Voss msg queues + + This function can be called by legacy code to post message to voss queues OR + legacy code may keep on invoking 'limPostMsgApi' to post the message to voss queue + for dispatching it later. + + \param pMac - Pointer to Global MAC structure + \param pMsg - Pointer to the message structure + + \return tANI_U32 - TX_SUCCESS for success. + + --------------------------------------------------------------------------*/ + +tSirRetStatus pePostMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + return (tSirRetStatus)limPostMsgApi(pMac, pMsg); +} + +/*-------------------------------------------------------------------------- + + \brief peProcessMessages() - Message Processor for PE + + Voss calls this function to dispatch the message to PE + + \param pMac - Pointer to Global MAC structure + \param pMsg - Pointer to the message structure + + \return tANI_U32 - TX_SUCCESS for success. + + --------------------------------------------------------------------------*/ + +tSirRetStatus peProcessMessages(tpAniSirGlobal pMac, tSirMsgQ* pMsg) +{ + if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) { + return eSIR_SUCCESS; + } + /** + * If the Message to be handled is for CFG Module call the CFG Msg Handler + * and for all the other cases post it to LIM + */ + if ( SIR_CFG_PARAM_UPDATE_IND != pMsg->type && IS_CFG_MSG(pMsg->type)) + cfgProcessMbMsg(pMac, (tSirMbMsg*)pMsg->bodyptr); + else + limMessageProcessor(pMac, pMsg); + return eSIR_SUCCESS; +} + + + +// --------------------------------------------------------------------------- +/** + * peHandleMgmtFrame + * + * FUNCTION: + * Process the Management frames from TL + * + * LOGIC: + * + * ASSUMPTIONS: TL sends the packet along with the VOS GlobalContext + * + * NOTE: + * + * @param pvosGCtx Global Vos Context + * @param vossBuff Packet + * @return None + */ + +VOS_STATUS peHandleMgmtFrame( v_PVOID_t pvosGCtx, v_PVOID_t vosBuff) +{ + tpAniSirGlobal pMac; + tpSirMacMgmtHdr mHdr; + tSirMsgQ msg; + vos_pkt_t *pVosPkt; + VOS_STATUS vosStatus; + v_U8_t *pRxPacketInfo; + + pVosPkt = (vos_pkt_t *)vosBuff; + if (NULL == pVosPkt) + { + return VOS_STATUS_E_FAILURE; + } + + pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, pvosGCtx); + if (NULL == pMac) + { + // cannot log a failure without a valid pMac + vos_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + return VOS_STATUS_E_FAILURE; + } + + vosStatus = WDA_DS_PeekRxPacketInfo( pVosPkt, (void *)&pRxPacketInfo, VOS_FALSE ); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + vos_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + return VOS_STATUS_E_FAILURE; + } + + + // + // The MPDU header is now present at a certain "offset" in + // the BD and is specified in the BD itself + // + + mHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + if(mHdr->fc.type == SIR_MAC_MGMT_FRAME) { + PELOG1(limLog( pMac, LOG1, + FL("RxBd=%p mHdr=%p Type: %d Subtype: %d Sizes:FC%d Mgmt%d"), + pRxPacketInfo, mHdr, mHdr->fc.type, mHdr->fc.subType, + sizeof(tSirMacFrameCtl), sizeof(tSirMacMgmtHdr));) + + limLog(pMac, LOG1, FL("mpdu_len:%d hdr_len:%d data_len:%d"), + WDA_GET_RX_MPDU_LEN(pRxPacketInfo), + WDA_GET_RX_MPDU_HEADER_LEN(pRxPacketInfo), + WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)); + + MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT, + WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo), + LIM_TRACE_MAKE_RXMGMT(mHdr->fc.subType, + (tANI_U16) (((tANI_U16)(mHdr->seqControl.seqNumHi << 4)) + | mHdr->seqControl.seqNumLo)));) + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + limLog(pMac, LOG1, FL("roamCandidateInd %d"), + WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)); + + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + limLog(pMac, LOG1, FL("offloadScanLearn %d"), + WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)); +#endif + } + + + // Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG + msg.type = SIR_BB_XPORT_MGMT_MSG; + msg.bodyptr = vosBuff; + msg.bodyval = 0; + + if( eSIR_SUCCESS != sysBbtProcessMessageCore( pMac, + &msg, + mHdr->fc.type, + mHdr->fc.subType )) + { + vos_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + limLog( pMac, LOGW, + FL ( "sysBbtProcessMessageCore failed to process SIR_BB_XPORT_MGMT_MSG" )); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +/** + * peRegisterTLHandle + * + * FUNCTION: + * Registers the Handler which, process the Management frames from TL + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @return None + */ + +void peRegisterTLHandle(tpAniSirGlobal pMac) +{ + v_PVOID_t pvosGCTx; + VOS_STATUS retStatus; + + pvosGCTx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); + + retStatus = WLANTL_RegisterMgmtFrmClient(pvosGCTx, peHandleMgmtFrame); + + if (retStatus != VOS_STATUS_SUCCESS) + limLog( pMac, LOGP, FL("Registering the PE Handle with TL has failed bailing out...")); + +} + + +/** + * limIsSystemInScanState() + * + *FUNCTION: + * This function is called by various MAC software modules to + * determine if System is in Scan/Learn state + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return true - System is in Scan/Learn state + * false - System is NOT in Scan/Learn state + */ + +tANI_U8 +limIsSystemInScanState(tpAniSirGlobal pMac) +{ + switch (pMac->lim.gLimSmeState) + { + case eLIM_SME_CHANNEL_SCAN_STATE: + case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE: + case eLIM_SME_LINK_EST_WT_SCAN_STATE: + case eLIM_SME_WT_SCAN_STATE: + // System is in Learn mode + return true; + + default: + // System is NOT in Learn mode + return false; + } +} /*** end limIsSystemInScanState() ***/ + + + +/** + * limIsSystemInActiveState() + * + *FUNCTION: + * This function is called by various MAC software modules to + * determine if System is in Active/Wakeup state + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return true - System is in Active state + * false - System is not in Active state + */ + +tANI_U8 limIsSystemInActiveState(tpAniSirGlobal pMac) +{ + switch (pMac->pmm.gPmmState) + { + case ePMM_STATE_BMPS_WAKEUP: + case ePMM_STATE_IMPS_WAKEUP: + case ePMM_STATE_READY: + // System is in Active mode + return true; + default: + return false; + // System is NOT in Active mode + } +} + + + + + +/** +*\brief limReceivedHBHandler() +* +* This function is called by schBeaconProcess() upon +* receiving a Beacon on STA. This also gets called upon +* receiving Probe Response after heat beat failure is +* detected. +* +* param pMac - global mac structure +* param channel - channel number indicated in Beacon, Probe Response +* return - none +*/ + + +void +limReceivedHBHandler(tpAniSirGlobal pMac, tANI_U8 channelId, tpPESession psessionEntry) +{ + if((channelId == 0 ) || (channelId == psessionEntry->currentOperChannel) ) + psessionEntry->LimRxedBeaconCntDuringHB++; + + if(pMac->psOffloadEnabled) + psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; + else + pMac->pmm.inMissedBeaconScenario = FALSE; +} /*** end limReceivedHBHandler() ***/ + + + +/** ------------------------------------------------------------- +\fn limUpdateOverlapStaParam +\brief Updates overlap cache and param data structure +\param tpAniSirGlobal pMac +\param tSirMacAddr bssId +\param tpLimProtStaParams pStaParams +\return None + -------------------------------------------------------------*/ +void +limUpdateOverlapStaParam(tpAniSirGlobal pMac, tSirMacAddr bssId, tpLimProtStaParams pStaParams) +{ + int i; + if (!pStaParams->numSta) + { + vos_mem_copy(pMac->lim.protStaOverlapCache[0].addr, + bssId, + sizeof(tSirMacAddr)); + pMac->lim.protStaOverlapCache[0].active = true; + + pStaParams->numSta = 1; + + return; + } + + for (i=0; ilim.protStaOverlapCache[i].active) + { + if (vos_mem_compare( pMac->lim.protStaOverlapCache[i].addr, + bssId, + sizeof(tSirMacAddr))) { + return; } + } + else + break; + } + + if (i == LIM_PROT_STA_OVERLAP_CACHE_SIZE) + { + PELOG1(limLog(pMac, LOGW, FL("Overlap cache is full"));) + } + else + { + vos_mem_copy(pMac->lim.protStaOverlapCache[i].addr, + bssId, + sizeof(tSirMacAddr)); + pMac->lim.protStaOverlapCache[i].active = true; + + pStaParams->numSta++; + } +} + + +/** + * limIbssEncTypeMatched + * + *FUNCTION: + * This function compares the encryption type of the peer with self + * while operating in IBSS mode and detects mismatch. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pBeacon - Parsed Beacon Frame structure + * @param pSession - Pointer to the PE session + * + * @return eSIR_TRUE if encryption type is matched; eSIR_FALSE otherwise + */ +static tAniBool limIbssEncTypeMatched(tpSchBeaconStruct pBeacon, + tpPESession pSession) +{ + if (!pBeacon || !pSession) + return eSIR_FALSE; + + /* Open case */ + if (pBeacon->capabilityInfo.privacy == 0 + && pSession->encryptType == eSIR_ED_NONE) + return eSIR_TRUE; + + /* WEP case */ + if (pBeacon->capabilityInfo.privacy == 1 && pBeacon->wpaPresent == 0 + && pBeacon->rsnPresent == 0 + && (pSession->encryptType == eSIR_ED_WEP40 + || pSession->encryptType == eSIR_ED_WEP104)) + return eSIR_TRUE; + + /* WPA-None case */ + if (pBeacon->capabilityInfo.privacy == 1 && pBeacon->wpaPresent == 1 + && pBeacon->rsnPresent == 0 + && ((pSession->encryptType == eSIR_ED_CCMP) || + (pSession->encryptType == eSIR_ED_TKIP))) + return eSIR_TRUE; + + return eSIR_FALSE; +} + + +/** + * limHandleIBSScoalescing() + * + *FUNCTION: + * This function is called upon receiving Beacon/Probe Response + * while operating in IBSS mode. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pBeacon - Parsed Beacon Frame structure + * @param pRxPacketInfo - Pointer to RX packet info structure + * + * @return Status whether to process or ignore received Beacon Frame + */ + +tSirRetStatus +limHandleIBSScoalescing( + tpAniSirGlobal pMac, + tpSchBeaconStruct pBeacon, + tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tSirRetStatus retCode; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + /* Ignore the beacon when any of the conditions below is met: + 1. The beacon claims no IBSS network + 2. SSID in the beacon does not match SSID of self station + 3. Operational channel in the beacon does not match self station + 4. Encyption type in the beacon does not match with self station + */ + if ( (!pBeacon->capabilityInfo.ibss) || + (limCmpSSid(pMac, &pBeacon->ssId,psessionEntry) != true) || + (psessionEntry->currentOperChannel != pBeacon->channelNumber) ) + retCode = eSIR_LIM_IGNORE_BEACON; + else if (limIbssEncTypeMatched(pBeacon, psessionEntry) != eSIR_TRUE) + { + PELOG3(limLog(pMac, LOG3, + FL("peer privacy %d peer wpa %d peer rsn %d self encType %d"), + pBeacon->capabilityInfo.privacy, + pBeacon->wpaPresent, + pBeacon->rsnPresent, + psessionEntry->encryptType);) + retCode = eSIR_LIM_IGNORE_BEACON; + } + else + { + tANI_U32 ieLen; + tANI_U16 tsfLater; + tANI_U8 *pIEs; + ieLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + tsfLater = WDA_GET_RX_TSF_LATER(pRxPacketInfo); + pIEs = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + PELOG3(limLog(pMac, LOG3, FL("BEFORE Coalescing tsfLater val :%d"), tsfLater);) + retCode = limIbssCoalesce(pMac, pHdr, pBeacon, pIEs, ieLen, tsfLater,psessionEntry); + } + return retCode; +} /*** end limHandleIBSScoalescing() ***/ + +/** + * lim_enc_type_matched() - matches security type of incoming beracon with + * current + * @mac_ctx Pointer to Global MAC structure + * @bcn Pointer to parsed Beacon structure + * @session PE session entry + * + * This function matches security type of incoming beracon with current + * + * @return true if matched, false otherwise + */ +static bool +lim_enc_type_matched(tpAniSirGlobal mac_ctx, + tpSchBeaconStruct bcn, + tpPESession session) +{ + if (!bcn || !session) + return false; + + limLog(mac_ctx, LOG1, + FL("Beacon/Probe:: Privacy :%d WPA Present:%d RSN Present: %d"), + bcn->capabilityInfo.privacy, bcn->wpaPresent, + bcn->rsnPresent); + limLog(mac_ctx, LOG1, + FL("session:: Privacy :%d EncyptionType: %d"), + SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps), + session->encryptType); + + /* This is handled by sending probe req due to IOT issues so return TRUE */ + if ((bcn->capabilityInfo.privacy) != + SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps)) { + limLog(mac_ctx, LOGW, FL("Privacy bit miss match\n")); + return true; + } + + /* Open */ + if ((bcn->capabilityInfo.privacy == 0) + && (session->encryptType == eSIR_ED_NONE)) + return true; + + /* WEP */ + if ((bcn->capabilityInfo.privacy == 1) + && (bcn->wpaPresent == 0) + && (bcn->rsnPresent == 0) + && ((session->encryptType == eSIR_ED_WEP40) + || (session->encryptType == eSIR_ED_WEP104) +#ifdef FEATURE_WLAN_WAPI + || (session->encryptType == eSIR_ED_WPI) +#endif + )) + return true; + + /* WPA OR RSN*/ + if ((bcn->capabilityInfo.privacy == 1) + && ((bcn->wpaPresent == 1) || (bcn->rsnPresent == 1)) + && ((session->encryptType == eSIR_ED_TKIP) + || (session->encryptType == eSIR_ED_CCMP) + || (session->encryptType == eSIR_ED_AES_128_CMAC))) + return true; + + return false; +} + +/** + * limDetectChangeInApCapabilities() + * + *FUNCTION: + * This function is called while SCH is processing + * received Beacon from AP on STA to detect any + * change in AP's capabilities. If there any change + * is detected, Roaming is informed of such change + * so that it can trigger reassociation. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * Notification is enabled for STA product only since + * it is not a requirement on BP side. + * + * @param pMac Pointer to Global MAC structure + * @param pBeacon Pointer to parsed Beacon structure + * @return None + */ + +void +limDetectChangeInApCapabilities(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeacon, + tpPESession psessionEntry) +{ + tANI_U8 len; + tSirSmeApNewCaps apNewCaps; + tANI_U8 newChannel; + bool security_caps_matched = true; + tSirRetStatus status = eSIR_SUCCESS; + apNewCaps.capabilityInfo = limGetU16((tANI_U8 *) &pBeacon->capabilityInfo); + newChannel = (tANI_U8) pBeacon->channelNumber; + + security_caps_matched = lim_enc_type_matched(pMac, pBeacon, psessionEntry); + if ( ( false == psessionEntry->limSentCapsChangeNtf ) && + ( ( ( !limIsNullSsid(&pBeacon->ssId) ) && + ( false == limCmpSSid(pMac, &pBeacon->ssId, psessionEntry) ) ) || + ( (SIR_MAC_GET_ESS(apNewCaps.capabilityInfo) != + SIR_MAC_GET_ESS(psessionEntry->limCurrentBssCaps) ) || + ( SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) != + SIR_MAC_GET_PRIVACY(psessionEntry->limCurrentBssCaps) ) || + ( SIR_MAC_GET_SHORT_PREAMBLE(apNewCaps.capabilityInfo) != + SIR_MAC_GET_SHORT_PREAMBLE(psessionEntry->limCurrentBssCaps) ) || + ( SIR_MAC_GET_QOS(apNewCaps.capabilityInfo) != + SIR_MAC_GET_QOS(psessionEntry->limCurrentBssCaps) ) || + ( (newChannel != psessionEntry->currentOperChannel) && + (newChannel != 0) ) || + (eSIR_FALSE == security_caps_matched) + ) ) ) + { + if (false == psessionEntry->fWaitForProbeRsp) + { + /* If Beacon capabilities is not matching with the current capability, + * then send unicast probe request to AP and take decision after + * receiving probe response */ + if ( true == psessionEntry->fIgnoreCapsChange ) + { + limLog(pMac, LOGW, FL("Ignoring the Capability change as it is false alarm")); + return; + } + psessionEntry->fWaitForProbeRsp = true; + limLog(pMac, LOGW, FL("AP capabilities are not matching," + "sending directed probe request.. ")); + status = limSendProbeReqMgmtFrame(pMac, &psessionEntry->ssId, psessionEntry->bssId, + psessionEntry->currentOperChannel,psessionEntry->selfMacAddr, + psessionEntry->dot11mode, 0, NULL); + + if ( eSIR_SUCCESS != status ) + { + limLog(pMac, LOGE, FL("send ProbeReq failed")); + psessionEntry->fWaitForProbeRsp = false; + } + return; + } + /** + * BSS capabilities have changed. + * Inform Roaming. + */ + len = sizeof(tSirMacCapabilityInfo) + + sizeof(tSirMacAddr) + sizeof(tANI_U8) + + 3 * sizeof(tANI_U8) + // reserved fields + pBeacon->ssId.length + 1; + + vos_mem_copy(apNewCaps.bssId, + psessionEntry->bssId, + sizeof(tSirMacAddr)); + if (newChannel != psessionEntry->currentOperChannel) + { + PELOGE(limLog(pMac, LOGE, FL("Channel Change from %d --> %d - " + "Ignoring beacon!"), + psessionEntry->currentOperChannel, newChannel);) + return; + } + + /** + * When Cisco 1262 Enterprise APs are configured with WPA2-PSK with + * AES+TKIP Pairwise ciphers and WEP-40 Group cipher, they do not set + * the privacy bit in Beacons (wpa/rsnie is still present in beacons), + * the privacy bit is set in Probe and association responses. + * Due to this anomaly, we detect a change in + * AP capabilities when we receive a beacon after association and + * disconnect from the AP. The following check makes sure that we can + * connect to such APs + */ + else if ((SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) == 0) && + (pBeacon->rsnPresent || pBeacon->wpaPresent)) + { + PELOGE(limLog(pMac, LOGE, FL("BSS Caps (Privacy) bit 0 in beacon," + " but WPA or RSN IE present, Ignore Beacon!"));) + return; + } + else + apNewCaps.channelId = psessionEntry->currentOperChannel; + vos_mem_copy((tANI_U8 *) &apNewCaps.ssId, + (tANI_U8 *) &pBeacon->ssId, + pBeacon->ssId.length + 1); + + psessionEntry->fIgnoreCapsChange = false; + psessionEntry->fWaitForProbeRsp = false; + psessionEntry->limSentCapsChangeNtf = true; + limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_AP_CAPS_CHANGED, + (tANI_U32 *) &apNewCaps, + len, psessionEntry->smeSessionId); + } + else if ( true == psessionEntry->fWaitForProbeRsp ) + { + /* Only for probe response frames and matching capabilities the control + * will come here. If beacon is with broadcast ssid then fWaitForProbeRsp + * will be false, the control will not come here*/ + + limLog(pMac, LOG1, FL("capabilities in probe response are" + "matching with the current setting," + "Ignoring subsequent capability" + "mismatch")); + psessionEntry->fIgnoreCapsChange = true; + psessionEntry->fWaitForProbeRsp = false; + } + +} /*** limDetectChangeInApCapabilities() ***/ + + + + +// --------------------------------------------------------------------- +/** + * limUpdateShortSlot + * + * FUNCTION: + * Enable/Disable short slot + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param enable Flag to enable/disable short slot + * @return None + */ + +tSirRetStatus limUpdateShortSlot(tpAniSirGlobal pMac, tpSirProbeRespBeacon pBeacon, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + + tSirSmeApNewCaps apNewCaps; + tANI_U32 nShortSlot; + tANI_U32 val = 0; + tANI_U32 phyMode; + + // Check Admin mode first. If it is disabled just return + if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("cfg get WNI_CFG_11G_SHORT_SLOT_TIME failed")); + return eSIR_FAILURE; + } + if (val == false) + return eSIR_SUCCESS; + + // Check for 11a mode or 11b mode. In both cases return since slot time is constant and cannot/should not change in beacon + limGetPhyMode(pMac, &phyMode, psessionEntry); + if ((phyMode == WNI_CFG_PHY_MODE_11A) || (phyMode == WNI_CFG_PHY_MODE_11B)) + return eSIR_SUCCESS; + + apNewCaps.capabilityInfo = limGetU16((tANI_U8 *) &pBeacon->capabilityInfo); + + // Earlier implementation: determine the appropriate short slot mode based on AP advertised modes + // when erp is present, apply short slot always unless, prot=on && shortSlot=off + // if no erp present, use short slot based on current ap caps + + // Issue with earlier implementation : Cisco 1231 BG has shortSlot = 0, erpIEPresent and useProtection = 0 (Case4); + + //Resolution : always use the shortSlot setting the capability info to decide slot time. + // The difference between the earlier implementation and the new one is only Case4. + /* + ERP IE Present | useProtection | shortSlot = QC STA Short Slot + Case1 1 1 1 1 //AP should not advertise this combination. + Case2 1 1 0 0 + Case3 1 0 1 1 + Case4 1 0 0 0 + Case5 0 1 1 1 + Case6 0 1 0 0 + Case7 0 0 1 1 + Case8 0 0 0 0 + */ + nShortSlot = SIR_MAC_GET_SHORT_SLOT_TIME(apNewCaps.capabilityInfo); + + if (nShortSlot != psessionEntry->shortSlotTimeSupported) + { + // Short slot time capability of AP has changed. Adopt to it. + PELOG1(limLog(pMac, LOG1, FL("Shortslot capability of AP changed: %d"), nShortSlot);) + ((tpSirMacCapabilityInfo)&psessionEntry->limCurrentBssCaps)->shortSlotTime = (tANI_U16)nShortSlot; + psessionEntry->shortSlotTimeSupported = nShortSlot; + pBeaconParams->fShortSlotTime = (tANI_U8) nShortSlot; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; + } + return eSIR_SUCCESS; +} + +/** ----------------------------------------------------------------- + \brief limHandleMissedBeaconInd() - handles missed beacon indication + + This function process the SIR_HAL_MISSED_BEACON_IND message from HAL, + and invokes limSendExitBmpsInd( ) to send an eWNI_PMC_EXIT_BMPS_IND + to SME with reason code 'eSME_MISSED_BEACON_IND_RCVD'. + + \param pMac - global mac structure + \return - none + \sa + ----------------------------------------------------------------- */ +void limHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + tpSirSmeMissedBeaconInd pSirMissedBeaconInd = + (tpSirSmeMissedBeaconInd)pMsg->bodyptr; + tpPESession psessionEntry = peFindSessionByBssIdx(pMac,pSirMissedBeaconInd->bssIdx); + if (psessionEntry == NULL) + { + limLog(pMac, LOGE, + FL("session does not exist for given BSSIdx:%d"), + pSirMissedBeaconInd->bssIdx); + return; + } +#endif + if ( (pMac->pmm.gPmmState == ePMM_STATE_BMPS_SLEEP) || + (pMac->pmm.gPmmState == ePMM_STATE_UAPSD_SLEEP)|| + (pMac->pmm.gPmmState == ePMM_STATE_WOWLAN) ) + { + pMac->pmm.inMissedBeaconScenario = TRUE; + PELOGE(limLog(pMac, LOGE, + FL("Sending EXIT_BMPS_IND to SME due to Missed beacon from FW"));) + limSendExitBmpsInd(pMac, eSME_MISSED_BEACON_IND_RCVD, psessionEntry); + } +/* ACTIVE_MODE_HB_OFFLOAD */ +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + else if(((pMac->pmm.gPmmState == ePMM_STATE_READY) || + (pMac->pmm.gPmmState == ePMM_STATE_BMPS_WAKEUP)) && + (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + pMac->pmm.inMissedBeaconScenario = TRUE; + PELOGE(limLog(pMac, LOGE, FL("Received Heart Beat Failure"));) + limMissedBeaconInActiveMode(pMac, psessionEntry); + } +#endif + else + { + limLog(pMac, LOGE, + FL("Received SIR_HAL_MISSED_BEACON_IND while in incorrect state: %d"), + pMac->pmm.gPmmState); + } + return; +} + +/** + * lim_smps_force_mode_ind() - Process smps force mode event + * @mac_ctx: Global MAC pointer + * @data: message containing the parameters of the event + * + * Process the smps force mode event and post message to SME to + * invoke the HDD callback + * + * Return: None + */ +void lim_smps_force_mode_ind(tpAniSirGlobal mac_ctx, tpSirMsgQ data) +{ + tSirMsgQ msg; + tpPESession psession_entry; + struct sir_smps_force_mode_event *smps_ind, *param; + + smps_ind = data->bodyptr; + psession_entry = pe_find_session_by_sme_session_id(mac_ctx, + smps_ind->vdev_id); + if (psession_entry == NULL) { + limLog(mac_ctx, LOGE, + FL("session does not exist for given BSSIdx: %d"), + smps_ind->vdev_id); + return; + } + + param = vos_mem_malloc(sizeof(*param)); + if (NULL == param) { + limLog(mac_ctx, LOGE, FL("Failed to allocate memory")); + return; + } + *param = *smps_ind; + + msg.type = eWNI_SME_SMPS_FORCE_MODE_IND; + msg.bodyptr = param; + msg.bodyval = 0; + limLog(mac_ctx, LOGE, + FL("send eWNI_SME_SMPS_FORCE_MODE_IND to SME")); + + limSysProcessMmhMsgApi(mac_ctx, &msg, ePROT); + return; +} + +void +limSendHeartBeatTimeoutInd(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tANI_U32 statusCode; + tSirMsgQ msg; + + /* Prepare and post message to LIM Message Queue */ + msg.type = (tANI_U16) SIR_LIM_HEART_BEAT_TIMEOUT; + msg.bodyptr = psessionEntry; + msg.bodyval = 0; + limLog(pMac, LOGE, + FL("Heartbeat failure from Fw")); + + statusCode = limPostMsgApi(pMac, &msg); + + if(statusCode != eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("posting message %X to LIM failed, reason=%d"), + msg.type, statusCode); + } +} + +/** ----------------------------------------------------------------- + \brief limPsOffloadHandleMissedBeaconInd() - handles missed beacon indication + + This function process the SIR_HAL_MISSED_BEACON_IND message from HAL, + and invokes limSendExitBmpsInd( ) to send an eWNI_PMC_EXIT_BMPS_IND + to SME with reason code 'eSME_MISSED_BEACON_IND_RCVD'. + + \param pMac - global mac structure + \return - none + \sa + ----------------------------------------------------------------- */ +void limPsOffloadHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirSmeMissedBeaconInd pSirMissedBeaconInd = + (tpSirSmeMissedBeaconInd)pMsg->bodyptr; + tpPESession psessionEntry = + peFindSessionByBssIdx(pMac,pSirMissedBeaconInd->bssIdx); + + if(!psessionEntry) + { + limLog(pMac, LOGE, + FL("session does not exist for given BSSId")); + return; + } + + /* Set Beacon Miss in Powersave Offload */ + psessionEntry->pmmOffloadInfo.bcnmiss = TRUE; + + /* + * If the session is in power save state then + * first need to come out of power save before + * triggering ap probing + */ + if(psessionEntry->pmmOffloadInfo.psstate == PMM_POWER_SAVE) + { + PELOGE(limLog(pMac, LOGE, + FL("Received Heart Beat Failure in Power Save State"));) + + /* Send Request for Full Power to SME */ + limSendExitBmpsInd(pMac, eSME_MISSED_BEACON_IND_RCVD, psessionEntry); + } + else + { + PELOGE(limLog(pMac, LOGE, + FL("Received Heart Beat Failure in active state"));) + /* Incase of Active state do AP probing immediately */ + limSendHeartBeatTimeoutInd(pMac, psessionEntry); + } + return; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus limRoamFillBssDescr(tpAniSirGlobal pMac, + tSirRoamOffloadSynchInd *pRoamOffloadSynchInd) +{ + v_U32_t uLen = 0; + tpSirProbeRespBeacon pParsedFrame; + tpSirMacMgmtHdr macHeader; + tANI_U8 *pBeaconProbeResp; + tSirBssDescription *pBssDescr = NULL; + + pBeaconProbeResp = (tANI_U8 *)pRoamOffloadSynchInd + + pRoamOffloadSynchInd->beaconProbeRespOffset; + macHeader = (tpSirMacMgmtHdr)pBeaconProbeResp; + pParsedFrame = + (tpSirProbeRespBeacon) vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (NULL == pParsedFrame) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "%s: fail to allocate memory for frame",__func__); + return eHAL_STATUS_RESOURCES; + } + + if ( pRoamOffloadSynchInd->beaconProbeRespLength <= SIR_MAC_HDR_LEN_3A ) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "%s: Very few bytes in synchInd beacon / probe resp frame! length=%d", + __func__, pRoamOffloadSynchInd->beaconProbeRespLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,"LFR3: Beacon/Prb Rsp:"); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + pBeaconProbeResp, pRoamOffloadSynchInd->beaconProbeRespLength); + if (pRoamOffloadSynchInd->isBeacon) { + if (sirParseBeaconIE(pMac, pParsedFrame, + &pBeaconProbeResp[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET], + pRoamOffloadSynchInd->beaconProbeRespLength - + SIR_MAC_HDR_LEN_3A) != eSIR_SUCCESS || !pParsedFrame->ssidPresent) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "Parse error Beacon, length=%d", + pRoamOffloadSynchInd->beaconProbeRespLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + } + else { + if (sirConvertProbeFrame2Struct(pMac, + &pBeaconProbeResp[SIR_MAC_HDR_LEN_3A], + pRoamOffloadSynchInd->beaconProbeRespLength - SIR_MAC_HDR_LEN_3A, + pParsedFrame) != eSIR_SUCCESS || + !pParsedFrame->ssidPresent) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "Parse error ProbeResponse, length=%d", + pRoamOffloadSynchInd->beaconProbeRespLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + } + /* 24 byte MAC header and 12 byte to ssid IE */ + if (pRoamOffloadSynchInd->beaconProbeRespLength > + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) { + uLen = pRoamOffloadSynchInd->beaconProbeRespLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + } + pRoamOffloadSynchInd->pbssDescription = + vos_mem_malloc(sizeof (tSirBssDescription) + uLen); /*De-allocated in + csrProcessRoamOffloadSynchInd*/ + pBssDescr = pRoamOffloadSynchInd->pbssDescription; + if (NULL == pBssDescr) + { + PELOGE(limLog( pMac, LOGE, "LFR3:Failed to allocate memory");) + VOS_ASSERT(pBssDescr != NULL); + return eHAL_STATUS_RESOURCES; + } + vos_mem_zero(pBssDescr, sizeof(tSirBssDescription)); + + /** + * Length of BSS desription is without length of + * length itself and length of pointer + * that holds ieFields + * + * tSirBssDescription + * +--------+---------------------------------+---------------+ + * | length | other fields | pointer to IEs| + * +--------+---------------------------------+---------------+ + * ^ + * ieFields + */ + pBssDescr->length = (tANI_U16)(offsetof(tSirBssDescription, ieFields[0]) - + sizeof(pBssDescr->length) + uLen); + + if (pParsedFrame->dsParamsPresent) + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + else if (pParsedFrame->HTInfo.present) + { + pBssDescr->channelId = pParsedFrame->HTInfo.primaryChannel; + } + else + { + /*If DS Params or HTIE is not present in the probe resp or beacon, + * then use the channel frequency provided by firmware to fill the + * channel in the BSS descriptor.*/ + pBssDescr->channelId = vos_freq_to_chan(pRoamOffloadSynchInd->chan_freq); + } + pBssDescr->channelIdSelf = pBssDescr->channelId; + + if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) + { + int i; + /* 11b or 11g packet + * 11g if extended Rate IE is present or + * if there is an A rate in suppRate IE */ + for (i = 0; i < pParsedFrame->supportedRates.numRates; i++) { + if (sirIsArate(pParsedFrame->supportedRates.rate[i] & 0x7f)) { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (pParsedFrame->extendedRatesPresent) { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + } + } else { + /* 11a packet */ + pBssDescr->nwType = eSIR_11A_NW_TYPE; + } + + pBssDescr->sinr = 0; + pBssDescr->beaconInterval = pParsedFrame->beaconInterval; + pBssDescr->timeStamp[0] = pParsedFrame->timeStamp[0]; + pBssDescr->timeStamp[1] = pParsedFrame->timeStamp[1]; + vos_mem_copy(&pBssDescr->capabilityInfo, + &pBeaconProbeResp[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2); + vos_mem_copy((tANI_U8 *) &pBssDescr->bssId, + (tANI_U8 *) macHeader->bssId, + sizeof(tSirMacAddr)); + pBssDescr->nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + if(pParsedFrame->mdiePresent) { + pBssDescr->mdiePresent = pParsedFrame->mdiePresent; + vos_mem_copy((tANI_U8 *)pBssDescr->mdie, (tANI_U8 *)pParsedFrame->mdie, + SIR_MDIE_SIZE); + } + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:%s:BssDescr Info:", __func__); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + pBssDescr->bssId, sizeof(tSirMacAddr)); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "chan=%d, rssi=%d",pBssDescr->channelId,pBssDescr->rssi); + if (uLen) + { + vos_mem_copy(&pBssDescr->ieFields, + pBeaconProbeResp + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET), + uLen); + } + vos_mem_free(pParsedFrame); + return eHAL_STATUS_SUCCESS; +} + +/** ----------------------------------------------------------------- + * brief limRoamOffloadSynchInd() - Handles Roam Synch Indication + * param pMac - global mac structure + * return - none + ----------------------------------------------------------------- */ +void limRoamOffloadSynchInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpPESession psessionEntry; + tpPESession pftSessionEntry; + tANI_U8 sessionId; + tSirMsgQ mmhMsg; + tSirBssDescription *pbssDescription = NULL; + tpSirRoamOffloadSynchInd pRoamOffloadSynchInd = + (tpSirRoamOffloadSynchInd)pMsg->bodyptr; + + if (!pRoamOffloadSynchInd) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "LFR3:%s:pRoamOffloadSynchInd is NULL", __func__); + return; + } + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "LFR3: Received WDA_ROAM_OFFLOAD_SYNCH_IND"); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:%s:authStatus=%d, vdevId=%d", __func__, + pRoamOffloadSynchInd->authStatus, + pRoamOffloadSynchInd->roamedVdevId); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + pRoamOffloadSynchInd->bssId,6); + psessionEntry = peFindSessionByBssIdx(pMac, + pRoamOffloadSynchInd->roamedVdevId); + if (psessionEntry == NULL) { + PELOGE(limLog( pMac, LOGE, + "%s: LFR3:Unable to find session", __func__);) + return; + } + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) + return; + } + if (!HAL_STATUS_SUCCESS(limRoamFillBssDescr(pMac, + pRoamOffloadSynchInd))) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "LFR3:%s:Failed to fill Bss Descr", __func__); + return; + } + pbssDescription = pRoamOffloadSynchInd->pbssDescription; + if((pftSessionEntry = peCreateSession(pMac, pbssDescription->bssId, + &sessionId, pMac->lim.maxStation, + eSIR_INFRASTRUCTURE_MODE)) == NULL) { + limLog(pMac, LOGE, FL("LFR3: Session Can not be created for new AP" + "during Roam Offload Synch")); + limPrintMacAddr( pMac, pbssDescription->bssId, LOGE ); + return; + } + pftSessionEntry->peSessionId = sessionId; + sirCopyMacAddr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr); + sirCopyMacAddr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId); + pftSessionEntry->bssType = eSIR_INFRASTRUCTURE_MODE; + /*Set bRoamSynchInProgress here since this session is + * specific to roam synch indication. This flag will + * later be used to differentiate LFR3 with LFR2 in LIM + */ + pftSessionEntry->bRoamSynchInProgress = VOS_TRUE; + + if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) + pftSessionEntry->limSystemRole = eLIM_STA_ROLE; + else { + limLog(pMac, LOGE, FL("LFR3:Invalid bss type")); + return; + } + pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:%s:created session (%p) with id = %d", + __func__, pftSessionEntry, pftSessionEntry->peSessionId); + /* Update the ReAssoc BSSID of the current session */ + sirCopyMacAddr(psessionEntry->limReAssocbssId, pbssDescription->bssId); + limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOG2); + + /* Prepare the session right now with as much as possible */ + limFillFTSession(pMac, pbssDescription, pftSessionEntry, psessionEntry); + limFTPrepareAddBssReq( pMac, FALSE, pftSessionEntry, pbssDescription ); + mmhMsg.type = + pRoamOffloadSynchInd->messageType;/* eWNI_SME_ROAM_OFFLOAD_SYNCH_IND */ + mmhMsg.bodyptr = pRoamOffloadSynchInd; + mmhMsg.bodyval = 0; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:%s:sending eWNI_SME_ROAM_OFFLOAD_SYNCH_IND", __func__); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + +#endif +/** ----------------------------------------------------------------- + \brief limMicFailureInd() - handles mic failure indication + + This function process the SIR_HAL_MIC_FAILURE_IND message from HAL, + + \param pMac - global mac structure + \return - none + \sa + ----------------------------------------------------------------- */ +void limMicFailureInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirSmeMicFailureInd pSirSmeMicFailureInd; + tpSirSmeMicFailureInd pSirMicFailureInd = (tpSirSmeMicFailureInd)pMsg->bodyptr; + tSirMsgQ mmhMsg; + tpPESession psessionEntry ; + tANI_U8 sessionId; + + if((psessionEntry = peFindSessionByBssid(pMac,pSirMicFailureInd->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE, + FL("session does not exist for given BSSId")); + return; + } + + pSirSmeMicFailureInd = vos_mem_malloc(sizeof(tSirSmeMicFailureInd)); + if (NULL == pSirSmeMicFailureInd) + { + // Log error + limLog(pMac, LOGP, + FL("memory allocate failed for eWNI_SME_MIC_FAILURE_IND")); + return; + } + + pSirSmeMicFailureInd->messageType = eWNI_SME_MIC_FAILURE_IND; + pSirSmeMicFailureInd->length = sizeof(pSirSmeMicFailureInd); + pSirSmeMicFailureInd->sessionId = psessionEntry->smeSessionId; + + vos_mem_copy(pSirSmeMicFailureInd->bssId, + pSirMicFailureInd->bssId, + sizeof(tSirMacAddr)); + + vos_mem_copy(pSirSmeMicFailureInd->info.srcMacAddr, + pSirMicFailureInd->info.srcMacAddr, + sizeof(tSirMacAddr)); + + vos_mem_copy(pSirSmeMicFailureInd->info.taMacAddr, + pSirMicFailureInd->info.taMacAddr, + sizeof(tSirMacAddr)); + + vos_mem_copy(pSirSmeMicFailureInd->info.dstMacAddr, + pSirMicFailureInd->info.dstMacAddr, + sizeof(tSirMacAddr)); + + vos_mem_copy(pSirSmeMicFailureInd->info.rxMacAddr, + pSirMicFailureInd->info.rxMacAddr, + sizeof(tSirMacAddr)); + + pSirSmeMicFailureInd->info.multicast = + pSirMicFailureInd->info.multicast; + + pSirSmeMicFailureInd->info.keyId= + pSirMicFailureInd->info.keyId; + + pSirSmeMicFailureInd->info.IV1= + pSirMicFailureInd->info.IV1; + + vos_mem_copy(pSirSmeMicFailureInd->info.TSC, + pSirMicFailureInd->info.TSC,SIR_CIPHER_SEQ_CTR_SIZE); + + mmhMsg.type = eWNI_SME_MIC_FAILURE_IND; + mmhMsg.bodyptr = pSirSmeMicFailureInd; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, sessionId, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} + +tANI_U8 limIsBeaconMissScenario(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) +{ + if(pMac->psOffloadEnabled) + { + tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + tANI_U8 sessionId; + tpPESession psessionEntry = + peFindSessionByBssid(pMac,pHdr->bssId,&sessionId); + + if(psessionEntry && psessionEntry->pmmOffloadInfo.bcnmiss) + return true; + } + else if(pMac->pmm.inMissedBeaconScenario) + { + return true; + } + return false; +} + +/** ----------------------------------------------------------------- + \brief limIsPktCandidateForDrop() - decides whether to drop the frame or not + + This function is called before enqueuing the frame to PE queue for further processing. + This prevents unnecessary frames getting into PE Queue and drops them right away. + Frames will be droped in the following scenarios: + + - In Scan State, drop the frames which are not marked as scan frames + - In non-Scan state, drop the frames which are marked as scan frames. + - Drop INFRA Beacons and Probe Responses in IBSS Mode + - Drop the Probe Request in IBSS mode, if STA did not send out the last beacon + + \param pMac - global mac structure + \return - none + \sa + ----------------------------------------------------------------- */ + +tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U32 subType) +{ + tANI_U32 framelen; + tANI_U8 *pBody; + tSirMacCapabilityInfo capabilityInfo; + tpSirMacMgmtHdr pHdr=NULL; + tpPESession psessionEntry=NULL; + tANI_U8 sessionId; + + /* + * + * In scan mode, drop only Beacon/Probe Response which are NOT marked as scan-frames. + * In non-scan mode, drop only Beacon/Probe Response which are marked as scan frames. + * Allow other mgmt frames, they must be from our own AP, as we don't allow + * other than beacons or probe responses in scan state. + */ + if( (subType == SIR_MAC_MGMT_BEACON) || + (subType == SIR_MAC_MGMT_PROBE_RSP)) + { + if(limIsBeaconMissScenario(pMac, pRxPacketInfo)) + { + MTRACE(macTrace(pMac, TRACE_CODE_INFO_LOG, 0, eLOG_NODROP_MISSED_BEACON_SCENARIO)); + return eMGMT_DROP_NO_DROP; + } + if (limIsSystemInScanState(pMac)) + { + return eMGMT_DROP_NO_DROP; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + else if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + { + return eMGMT_DROP_NO_DROP; + } +#endif + else if (WDA_IS_RX_IN_SCAN(pRxPacketInfo)) + { + return eMGMT_DROP_SCAN_MODE_FRAME; + } + } + + framelen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if ((subType == SIR_MAC_MGMT_DEAUTH || + subType == SIR_MAC_MGMT_DISASSOC) && + lim_is_deauth_diassoc_for_drop(pMac, pRxPacketInfo)) + return eMGMT_DROP_SPURIOUS_FRAME; + +#ifdef WLAN_FEATURE_11W + if ((subType == SIR_MAC_MGMT_ASSOC_REQ || + subType == SIR_MAC_MGMT_REASSOC_REQ) && + lim_is_assoc_req_for_drop(pMac, pRxPacketInfo)) + return eMGMT_DROP_SPURIOUS_FRAME; +#endif + //Drop INFRA Beacons and Probe Responses in IBSS Mode + if( (subType == SIR_MAC_MGMT_BEACON) || + (subType == SIR_MAC_MGMT_PROBE_RSP)) + { + //drop the frame if length is less than 12 + if(framelen < LIM_MIN_BCN_PR_LENGTH) + return eMGMT_DROP_INVALID_SIZE; + + *((tANI_U16*) &capabilityInfo) = sirReadU16(pBody+ LIM_BCN_PR_CAPABILITY_OFFSET); + + /* Note sure if this is sufficient, basically this condition allows all probe responses and + * beacons from an infrastructure network + */ + if(!capabilityInfo.ibss) + return eMGMT_DROP_NO_DROP; + + //This can be enhanced to even check the SSID before deciding to enque the frame. + if(capabilityInfo.ess) + return eMGMT_DROP_INFRA_BCN_IN_IBSS; + } + else if( (subType == SIR_MAC_MGMT_PROBE_REQ) && + (!WDA_GET_RX_BEACON_SENT(pRxPacketInfo))) + { + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + psessionEntry = peFindSessionByBssid(pMac, pHdr->bssId, &sessionId); + if ((psessionEntry && !LIM_IS_IBSS_ROLE(psessionEntry)) || + (!psessionEntry)) + return eMGMT_DROP_NO_DROP; + + //Drop the Probe Request in IBSS mode, if STA did not send out the last beacon + //In IBSS, the node which sends out the beacon, is supposed to respond to ProbeReq + return eMGMT_DROP_NOT_LAST_IBSS_BCN; + } + + return eMGMT_DROP_NO_DROP; +} + +/** + * lim_update_lost_link_info() - update lost link information to SME + * @mac: global MAC handle + * @session: PE session + * @rssi: rssi value from the received frame + * + * Return: none + */ +void lim_update_lost_link_info(tpAniSirGlobal mac, tpPESession session, + int8_t rssi) +{ + struct sir_lost_link_info *lost_link_info; + tSirMsgQ mmh_msg; + if ((NULL == mac) || (NULL == session)) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "%s: parameter NULL", __func__); + return; + } + if (!LIM_IS_STA_ROLE(session)) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "%s: not STA mode, do nothing", __func__); + return; + } + + lost_link_info = vos_mem_malloc(sizeof(*lost_link_info)); + if (NULL == lost_link_info) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "%s: lost_link_info allocation failure", __func__); + return; + } + + lost_link_info->vdev_id = session->smeSessionId; + lost_link_info->rssi = rssi; + mmh_msg.type = eWNI_SME_LOST_LINK_INFO_IND; + mmh_msg.bodyptr = lost_link_info; + mmh_msg.bodyval = 0; + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "%s: post eWNI_SME_LOST_LINK_INFO_IND, bss_idx %d, rssi %d", + __func__, lost_link_info->vdev_id, lost_link_info->rssi); + + limSysProcessMmhMsgApi(mac, &mmh_msg, ePROT); +} + +eHalStatus pe_AcquireGlobalLock( tAniSirLim *psPe) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + + if(psPe) + { + if( VOS_IS_STATUS_SUCCESS( vos_lock_acquire( &psPe->lkPeGlobalLock) ) ) + { + status = eHAL_STATUS_SUCCESS; + } + } + return (status); +} +eHalStatus pe_ReleaseGlobalLock( tAniSirLim *psPe) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + if(psPe) + { + if( VOS_IS_STATUS_SUCCESS( vos_lock_release( &psPe->lkPeGlobalLock) ) ) + { + status = eHAL_STATUS_SUCCESS; + } + } + return (status); +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c new file mode 100644 index 000000000000..7606aad9fa98 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c @@ -0,0 +1,5001 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limAssocUtils.cc contains the utility functions + * LIM uses while processing (Re) Association messages. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * 05/26/10 js WPA handling in (Re)Assoc frames + * + */ + +#include "palTypes.h" +#include "aniGlobal.h" +#include "wniApi.h" +#include "sirCommon.h" + +#include "wniCfgSta.h" +#include "pmmApi.h" +#include "cfgApi.h" + +#include "schApi.h" +#include "utilsApi.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limStaHashApi.h" +#include "limAdmitControl.h" +#include "limSendMessages.h" +#include "limIbssPeerMgmt.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" + +#include "vos_types.h" +#include "wlan_qct_wda.h" + +/* + * fill up the rate info properly based on what is actually supported by the peer + * TBD TBD TBD + */ +void +limFillSupportedRatesInfo( + tpAniSirGlobal pMac, + tpDphHashNode pSta, + tpSirSupportedRates pRates, + tpPESession psessionEntry) +{ + //pSta will be NULL for self entry, so get the opRateMode based on the self mode. + //For the peer entry get it from the peer Capabilities present in hash table + if(pSta == NULL) + pRates->opRateMode = limGetStaRateMode((tANI_U8)psessionEntry->dot11mode); + else + pRates->opRateMode = limGetStaPeerType(pMac, pSta, psessionEntry); + +} + + +/** + * limCmpSSid() + * + *FUNCTION: + * This function is called in various places within LIM code + * to determine whether received SSid is same as SSID in use. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param *prxSSid - pointer to SSID structure + * + * @return status - true for SSID match else false. + */ + +tANI_U8 +limCmpSSid(tpAniSirGlobal pMac, tSirMacSSid *prxSSid,tpPESession psessionEntry) +{ + + if (vos_mem_compare((tANI_U8* ) prxSSid, (tANI_U8 *) &psessionEntry->ssId, + (tANI_U8) (psessionEntry->ssId.length + 1))) + return true; + else + return false; + +} /****** end limCmpSSid() ******/ + + + +/** + * limCompareCapabilities() + * + *FUNCTION: + * This function is called during Association/Reassociation + * frame handling to determine whether received capabilities + * match with local capabilities or not. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pAssocReq - Pointer to received Assoc Req frame + * @param pLocalCapabs - Pointer to local capabilities + * + * @return status - true for Capabilitity match else false. + */ + +tANI_U8 +limCompareCapabilities(tpAniSirGlobal pMac, + tSirAssocReq *pAssocReq, + tSirMacCapabilityInfo *pLocalCapabs,tpPESession psessionEntry) +{ + tANI_U32 val; + + if ((LIM_IS_AP_ROLE(psessionEntry)|| + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (pAssocReq->capabilityInfo.ibss)) { + // Requesting STA asserting IBSS capability. + limLog(pMac, LOG1,FL("Requesting STA asserting IBSS capability")); + return false; + } + + // Compare CF capabilities + if (pAssocReq->capabilityInfo.cfPollable || + pAssocReq->capabilityInfo.cfPollReq) + { + // AP does not support PCF functionality + limLog(pMac, LOG1,FL(" AP does not support PCF functionality")); + return false; + } + + // Compare short preamble capability + if (pAssocReq->capabilityInfo.shortPreamble && + (pAssocReq->capabilityInfo.shortPreamble != + pLocalCapabs->shortPreamble)) + { + // Allowing a STA requesting short preamble while + // AP does not support it + } + + + limLog(pMac, LOG1, "QoS in AssocReq: %d, local capabs qos: %d", + pAssocReq->capabilityInfo.qos, + pLocalCapabs->qos); + + // Compare QoS capability + if (pAssocReq->capabilityInfo.qos && + (pAssocReq->capabilityInfo.qos != pLocalCapabs->qos)) + { + /*Temporary hack for UPF to skip 11e capability check in order to interop with + CSR - proper fix needs to be put in place*/ + if ( 0 != vos_get_skip_11e_check()) + { + limLog(pMac, LOG1, + FL("Received unmatched QOS but cfg to suppress - continuing")); + } + else + { + // AP does not support QoS capability + limLog(pMac, LOG1, FL("AP does not support QoS capability")); + return false; + } + } + + + /* + * If AP supports shortSlot and if apple user has + * enforced association only from shortSlot station, + * then AP must reject any station that does not support + * shortSlot + */ + if ((LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (pLocalCapabs->shortSlotTime == 1)) { + if (wlan_cfgGetInt(pMac, WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("error getting WNI_CFG_FORCE_SHORT_SLOT_ASSOC_ONLY ")); + return false; + } + if(val) + { + if (pAssocReq->capabilityInfo.shortSlotTime != pLocalCapabs->shortSlotTime) + { + limLog(pMac, LOGE, + FL("AP rejects association as station doesnt support shortslot time")); + return false; + } + return false; + } + } + + return true; +} /****** end limCompareCapabilities() ******/ + + +/** + * limCheckRxBasicRates() + * + *FUNCTION: + * This function is called during Association/Reassociation + * frame handling to determine whether received rates in + * Assoc/Reassoc request frames include all BSS basic rates + * or not. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param rxRateSet - pointer to SSID structure + * + * @return status - true if ALL BSS basic rates are present in the + * received rateset else false. + */ + +tANI_U8 +limCheckRxBasicRates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet,tpPESession psessionEntry) +{ + tSirMacRateSet *pRateSet, basicRate; + tANI_U8 i, j, k, match; + + pRateSet = vos_mem_malloc(sizeof(tSirMacRateSet)); + if (NULL == pRateSet) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for RATESET")); + + return false; + } + + /* Copy operational rate set from session Entry */ + vos_mem_copy(pRateSet->rate, (psessionEntry->rateSet.rate), + psessionEntry->rateSet.numRates); + + pRateSet->numRates = psessionEntry->rateSet.numRates; + + // Extract BSS basic rateset from operational rateset + for (i = 0, j = 0; ((i < pRateSet->numRates) && (i < SIR_MAC_RATESET_EID_MAX)) ; i++) + { + if ((pRateSet->rate[i] & 0x80) == 0x80) + { + // msb is set, so this is a basic rate + basicRate.rate[j++] = pRateSet->rate[i]; + } + } + + /* + * For each BSS basic rate, find if it is present in the + * received rateset. + */ + for (k = 0; k < j; k++) + { + match = 0; + for (i = 0; ((i < rxRateSet.numRates) && (i < SIR_MAC_RATESET_EID_MAX)); i++) + { + if ((rxRateSet.rate[i] | 0x80) == basicRate.rate[k]) + match = 1; + } + + if (!match) + { + // Free up memory allocated for rateset + vos_mem_free((tANI_U8 *)pRateSet); + + return false; + } + } + + // Free up memory allocated for rateset + vos_mem_free((tANI_U8 *)pRateSet); + + return true; +} /****** end limCheckRxBasicRates() ******/ + + + +/** + * limCheckMCSSet() + * + *FUNCTION: + * This function is called during Association/Reassociation + * frame handling to determine whether received MCS rates in + * Assoc/Reassoc request frames includes all Basic MCS Rate Set or not. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param supportedMCSSet - pointer to Supported MCS Rate Set + * + * @return status - true if ALL MCS Basic Rate Set rates are present in the + * received rateset else false. + */ + +tANI_U8 +limCheckMCSSet(tpAniSirGlobal pMac, tANI_U8* supportedMCSSet) +{ + tANI_U8 basicMCSSet[SIZE_OF_BASIC_MCS_SET] = {0}; + tANI_U32 cfgLen = 0; + tANI_U8 i; + tANI_U8 validBytes; + tANI_U8 lastByteMCSMask = 0x1f; + + + cfgLen = WNI_CFG_BASIC_MCS_SET_LEN; + if (wlan_cfgGetStr(pMac, WNI_CFG_BASIC_MCS_SET, + (tANI_U8 *) basicMCSSet, + (tANI_U32 *) &cfgLen) != eSIR_SUCCESS) + { + /// Could not get Basic MCS rateset from CFG. Log error. + limLog(pMac, LOGP, FL("could not retrieve Basic MCS rateset")); + return false; + } + + validBytes = VALID_MCS_SIZE/8; + + //check if all the Basic MCS Bits are set in supported MCS bitmap + for (i=0; igStartBssRSNIe; + + // Check groupwise cipher suite + for (i = 0; i < sizeof(rxRSNIe.gp_cipher_suite); i++) + { + if (pRSNIe->gp_cipher_suite[i] != rxRSNIe.gp_cipher_suite[i]) + { + limLog(pMac, LOG3, FL("Invalid groupwise cipher suite")); + return eSIR_MAC_INVALID_GROUP_CIPHER_STATUS; + } + } + + /* + * For each Pairwise cipher suite check whether we support + * received pairwise + */ + match = 0; + for (i = 0; i < rxRSNIe.pwise_cipher_suite_count; i++) + { + for(j = 0; j < pRSNIe->pwise_cipher_suite_count; j++) + { + if (vos_mem_compare(&rxRSNIe.pwise_cipher_suites[i], + &pRSNIe->pwise_cipher_suites[j], + sizeof(pRSNIe->pwise_cipher_suites[j]))) + { + match = 1; + break; + } + } + + if ((staIsHT) +#ifdef ANI_LITTLE_BYTE_ENDIAN + &&( (rxRSNIe.pwise_cipher_suites[i][3] & SECURITY_SUITE_TYPE_MASK) == SECURITY_SUITE_TYPE_CCMP)) +#else + &&( (rxRSNIe.pwise_cipher_suites[i][0] & SECURITY_SUITE_TYPE_MASK) == SECURITY_SUITE_TYPE_CCMP)) +#endif + { + onlyNonHtCipher=0; + } + + } + + if ((!match) || ((staIsHT) && onlyNonHtCipher)) + { + limLog(pMac, LOG1, FL("Invalid pairwise cipher suite")); + return eSIR_MAC_INVALID_PAIRWISE_CIPHER_STATUS; + } + /* Check RSN capabilities + * Bit 0 of First Byte - PreAuthentication Capability + */ + if(((rxRSNIe.RSN_Cap[0] >> 0) & 0x1) == true) //this is supported by AP only + { + limLog(pMac, LOG1, FL("Invalid RSN information element capabilities")); + return eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS; + } + + *pmfConnection = eANI_BOOLEAN_FALSE; + +#ifdef WLAN_FEATURE_11W + weArePMFCapable = pSessionEntry->pLimStartBssReq->pmfCapable; + weRequirePMF = pSessionEntry->pLimStartBssReq->pmfRequired; + theyArePMFCapable = (rxRSNIe.RSN_Cap[0] >> 7) & 0x1; + theyRequirePMF = (rxRSNIe.RSN_Cap[0] >> 6) & 0x1; + + if ((theyRequirePMF && theyArePMFCapable && !weArePMFCapable) || + (weRequirePMF && !theyArePMFCapable)) + { + limLog(pMac, LOG1, FL("Association fail, robust management frames " + "policy violation theyRequirePMF =%d theyArePMFCapable %d " + "weArePMFCapable %d weRequirePMF %d theyArePMFCapable %d"), + theyRequirePMF,theyArePMFCapable,weArePMFCapable,weRequirePMF, + theyArePMFCapable); + return eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION; + } + + if(theyArePMFCapable && weArePMFCapable) + *pmfConnection = eANI_BOOLEAN_TRUE; + + limLog(pMac, LOG1, FL("weAreCapable %d, weRequire %d, theyAreCapable %d, " + "theyRequire %d, PMFconnection %d"), + weArePMFCapable, weRequirePMF, theyArePMFCapable, theyRequirePMF, *pmfConnection); +#endif + + return eSIR_SUCCESS; +} /****** end limCheckRxRSNIeMatch() ******/ + +/** + * limCheckRxWPAIeMatch() + * + *FUNCTION: + * This function is called during Association/Reassociation + * frame handling to determine whether received RSN in + * Assoc/Reassoc request frames include supported cipher suites or not. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param rxWPAIe - Received WPA IE in (Re)Assco req + * + * @return status - true if ALL BSS basic rates are present in the + * received rateset else false. + */ + +tANI_U8 +limCheckRxWPAIeMatch(tpAniSirGlobal pMac, tDot11fIEWPA rxWPAIe,tpPESession pSessionEntry, tANI_U8 staIsHT) +{ + tDot11fIEWPA *pWPAIe; + tANI_U8 i, j, match, onlyNonHtCipher = 1; + + // WPA IE should be received from PE + pWPAIe = &pSessionEntry->gStartBssWPAIe; + + // Check groupwise cipher suite + for (i = 0; i < 4; i++) + { + if (pWPAIe->multicast_cipher[i] != rxWPAIe.multicast_cipher[i]) + { + limLog(pMac, LOG1, FL("Invalid groupwise cipher suite")); + return eSIR_MAC_INVALID_GROUP_CIPHER_STATUS; + } + } + + /* + * For each Pairwise cipher suite check whether we support + * received pairwise + */ + match = 0; + for (i = 0; i < rxWPAIe.unicast_cipher_count; i++) + { + for(j = 0; j < pWPAIe->unicast_cipher_count; j++) + { + if (vos_mem_compare(rxWPAIe.unicast_ciphers[i], + pWPAIe->unicast_ciphers[j], + 4)) + { + match = 1; + break; + } + } + + if ((staIsHT) +#ifdef ANI_LITTLE_BYTE_ENDIAN + &&( (rxWPAIe.unicast_ciphers[i][3] & SECURITY_SUITE_TYPE_MASK) == SECURITY_SUITE_TYPE_CCMP)) +#else + &&( (rxWPAIe.unicast_ciphers[i][0] & SECURITY_SUITE_TYPE_MASK) == SECURITY_SUITE_TYPE_CCMP)) +#endif + { + onlyNonHtCipher=0; + } + + } + + if ((!match) || ((staIsHT) && onlyNonHtCipher)) + { + limLog(pMac, LOG1, FL("Invalid pairwise cipher suite")); + return eSIR_MAC_CIPHER_SUITE_REJECTED_STATUS; + } + + return eSIR_SUCCESS; +} /****** end limCheckRxWPAIeMatch() ******/ + + +/** + * limCleanupRxPath() + * + *FUNCTION: + * This function is called to cleanup STA state at SP & RFP. + * + *LOGIC: + * To circumvent RFP's handling of dummy packet when it does not + * have an incomplete packet for the STA to be deleted, a packet + * with 'more framgents' bit set will be queued to RFP's WQ before + * queuing 'dummy packet'. + * A 'dummy' BD is pushed into RFP's WQ with type=00, subtype=1010 + * (Disassociation frame) and routing flags in BD set to eCPU's + * Low Priority WQ. + * RFP cleans up its local context for the STA id mentioned in the + * BD and then pushes BD to eCPU's low priority WQ. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pStaDs Pointer to the per STA data structure + * initialized by LIM and maintained at DPH + * + * @return None + */ + +tSirRetStatus +limCleanupRxPath(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + + + limLog( pMac, LOG1, FL("Cleanup Rx Path for AID : %d" + "psessionEntry->limSmeState : %d, mlmState : %d"), + pStaDs->assocId, psessionEntry->limSmeState, + pStaDs->mlmStaContext.mlmState); + + limAbortBackgroundScan( pMac ); + psessionEntry->isCiscoVendorAP = FALSE; + + if (pMac->lim.gLimAddtsSent) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_ADDTS_RSP_TIMER)); + tx_timer_deactivate(&pMac->lim.limTimers.gLimAddtsRspTimer); + } + + if (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_ASSOC_CNF_STATE) + { + limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, + pStaDs->assocId); + + if (!pStaDs->mlmStaContext.updateContext) + { + /** + * There is no context to delete. + * Release our assigned AID back to the free pool + */ + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry); + } + limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId,psessionEntry); + + return retCode; + } + } + + //delete all tspecs associated with this sta. + limAdmitControlDeleteSta(pMac, pStaDs->assocId); + + + /** + * Make STA hash entry invalid at eCPU so that DPH + * does not process any more data packets and + * releases those BDs + */ + pStaDs->valid = 0; + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_WT_DEL_STA_RSP_STATE)); + psessionEntry->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + /* Deactivating probe after heart beat timer */ + limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_JOIN_FAIL_TIMER); + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + limDeactivateAndChangeTimer(pMac, eLIM_KEEPALIVE_TIMER); + pMac->lim.gLastBeaconDtimCount = 0; + pMac->lim.gLastBeaconDtimPeriod = 0; + +#ifdef FEATURE_WLAN_ESE +#ifdef FEATURE_WLAN_ESE_UPLOAD + limSendSmeTsmIEInd(pMac, psessionEntry, 0, 0, 0); +#else + limDeactivateAndChangeTimer(pMac,eLIM_TSM_TIMER); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + + /** + * Update the status for PMM module + */ + pmmResetPmmState(pMac); + } +#ifdef WLAN_DEBUG + // increment a debug count + pMac->lim.gLimNumRxCleanup++; +#endif + /* Do DEL BSS or DEL STA only if ADD BSS was success */ + if (!psessionEntry->add_bss_failed) { + if (psessionEntry->limSmeState == eLIM_SME_JOIN_FAILURE_STATE) { + retCode = limDelBss( pMac, pStaDs, + psessionEntry->bssIdx, psessionEntry); + } else + retCode = limDelSta( pMac, pStaDs, true, psessionEntry); + } + + return retCode; + +} /*** end limCleanupRxPath() ***/ + + +/** + * limSendDelStaCnf() + * + *FUNCTION: + * This function is called to send appropriate CNF message to SME + * + *LOGIC: + * + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param tpAniSirGlobal pMac, + * @param tSirMacAddr staDsAddr, + * @param tANI_U16 staDsAssocId, + * @param tLimMlmStaContext mlmStaContext, + * @param tSirResultCodes statusCode + * + * @return None + */ + +void +limSendDelStaCnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, + tANI_U16 staDsAssocId, tLimMlmStaContext mlmStaContext, tSirResultCodes statusCode,tpPESession psessionEntry) +{ + + tLimMlmDisassocCnf mlmDisassocCnf; + tLimMlmDeauthCnf mlmDeauthCnf; + tLimMlmPurgeStaInd mlmPurgeStaInd; + + limLog(pMac, LOG1, FL("Sessionid: %d staDsAssocId: %d Trigger: %d " + "statusCode: %d staDsAddr: "MAC_ADDRESS_STR),psessionEntry->peSessionId, + staDsAssocId, mlmStaContext.cleanupTrigger, statusCode, + MAC_ADDR_ARRAY(staDsAddr)); + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + // Set BSSID at CFG to null + tSirMacAddr nullAddr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + sirCopyMacAddr(nullAddr,psessionEntry->bssId); + + // Free up buffer allocated for JoinReq held by + // MLM state machine + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + psessionEntry->limAID = 0; + + } else if ( + (mlmStaContext.cleanupTrigger == eLIM_LINK_MONITORING_DISASSOC) || + (mlmStaContext.cleanupTrigger == eLIM_LINK_MONITORING_DEAUTH)) { + /* only for non-STA cases PE/SME is serialized */ + return; + } + + if ((mlmStaContext.cleanupTrigger == + eLIM_HOST_DISASSOC) || + (mlmStaContext.cleanupTrigger == + eLIM_PROMISCUOUS_MODE_DISASSOC) || + (mlmStaContext.cleanupTrigger == + eLIM_LINK_MONITORING_DISASSOC)) + { + /** + * Host or LMM driven Disassociation. + * Issue Disassoc Confirm to SME. + */ + limLog( pMac, LOGW, FL("Lim Posting DISASSOC_CNF to Sme. Trigger: %d"), + mlmStaContext.cleanupTrigger); + + + vos_mem_copy((tANI_U8 *) &mlmDisassocCnf.peerMacAddr, + (tANI_U8 *) staDsAddr, + sizeof(tSirMacAddr)); + mlmDisassocCnf.resultCode = statusCode; + mlmDisassocCnf.disassocTrigger = + mlmStaContext.cleanupTrigger; + /* Update PE session Id*/ + mlmDisassocCnf.sessionId = psessionEntry->peSessionId; + + limPostSmeMessage(pMac, + LIM_MLM_DISASSOC_CNF, + (tANI_U32 *) &mlmDisassocCnf); + } + else if ((mlmStaContext.cleanupTrigger == eLIM_HOST_DEAUTH) || + (mlmStaContext.cleanupTrigger == eLIM_LINK_MONITORING_DEAUTH)) + { + /** + * Host or LMM driven Deauthentication. + * Issue Deauth Confirm to SME. + */ + limLog( pMac, LOGW, FL("Lim Posting DEAUTH_CNF to Sme. Trigger: %d"), + mlmStaContext.cleanupTrigger); + vos_mem_copy((tANI_U8 *) &mlmDeauthCnf.peerMacAddr, + (tANI_U8 *) staDsAddr, + sizeof(tSirMacAddr)); + mlmDeauthCnf.resultCode = statusCode; + mlmDeauthCnf.deauthTrigger = + mlmStaContext.cleanupTrigger; + /* PE session Id */ + mlmDeauthCnf.sessionId = psessionEntry->peSessionId; + + limPostSmeMessage(pMac, + LIM_MLM_DEAUTH_CNF, + (tANI_U32 *) &mlmDeauthCnf); + } + else if ((mlmStaContext.cleanupTrigger == + eLIM_PEER_ENTITY_DISASSOC) || + (mlmStaContext.cleanupTrigger == + eLIM_PEER_ENTITY_DEAUTH)) + { + /** + * Received Disassociation/Deauthentication from peer. + * Issue Purge Ind to SME. + */ + limLog( pMac, LOGW, FL("Lim Posting PURGE_STA_IND to Sme. Trigger: %d"), + mlmStaContext.cleanupTrigger) ; + vos_mem_copy((tANI_U8 *) &mlmPurgeStaInd.peerMacAddr, + (tANI_U8 *) staDsAddr, + sizeof(tSirMacAddr)); + mlmPurgeStaInd.reasonCode = (tANI_U8) mlmStaContext.disassocReason; + mlmPurgeStaInd.aid = staDsAssocId; + mlmPurgeStaInd.purgeTrigger = mlmStaContext.cleanupTrigger; + mlmPurgeStaInd.sessionId = psessionEntry->peSessionId; + + limPostSmeMessage(pMac, + LIM_MLM_PURGE_STA_IND, + (tANI_U32 *) &mlmPurgeStaInd); + } + else if(mlmStaContext.cleanupTrigger == eLIM_JOIN_FAILURE) + { + //PE setup the peer entry in HW upfront, right after join is completed. + //If there is a failure during rest of the assoc sequence, this context needs to be cleaned up. + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + tLimSmeStates tempLimSmeState = eLIM_SME_IDLE_STATE; + + smesessionId = psessionEntry->smeSessionId; + smetransactionId = psessionEntry->transactionId; + tempLimSmeState = psessionEntry->limSmeState; + + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + //if it is a reassoc failure to join new AP + //eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA result code is used + //during assoc and reassoc, so sme state req to distinguish them + if((mlmStaContext.resultCode == eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE) || + (mlmStaContext.resultCode == eSIR_SME_FT_REASSOC_FAILURE) || + (mlmStaContext.resultCode == eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE) || + (mlmStaContext.resultCode == eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA && + tempLimSmeState == eLIM_SME_WT_REASSOC_STATE) + ) + { + limLog( pMac, LOG1, FL("Lim Posting eWNI_SME_REASSOC_RSP to SME" + "resultCode: %d, statusCode: %d," + "sessionId: %d"), + mlmStaContext.resultCode, + mlmStaContext.protStatusCode, + psessionEntry->peSessionId); + if(mlmStaContext.resultCode != eSIR_SME_SUCCESS ) + { + peDeleteSession(pMac, psessionEntry); + psessionEntry = NULL; + } + + limSendSmeJoinReassocRsp(pMac, eWNI_SME_REASSOC_RSP, + mlmStaContext.resultCode, mlmStaContext.protStatusCode, psessionEntry, + smesessionId, smetransactionId); + } + else + { + vos_mem_free(psessionEntry->pLimJoinReq); + psessionEntry->pLimJoinReq = NULL; + + limLog( pMac, LOG1, FL("Lim Posting eWNI_SME_JOIN_RSP to SME." + "resultCode: %d,statusCode: %d," + "sessionId: %d"), + mlmStaContext.resultCode, + mlmStaContext.protStatusCode, + psessionEntry->peSessionId); + + if(mlmStaContext.resultCode != eSIR_SME_SUCCESS) + { + peDeleteSession(pMac,psessionEntry); + psessionEntry = NULL; + } + + limSendSmeJoinReassocRsp(pMac, eWNI_SME_JOIN_RSP, + mlmStaContext.resultCode, + mlmStaContext.protStatusCode, + psessionEntry, smesessionId, + smetransactionId); + } + + } + + if ((NULL != psessionEntry) && (!LIM_IS_AP_ROLE(psessionEntry))) { + peDeleteSession(pMac, psessionEntry); + psessionEntry = NULL; + } +} + +/** + * limRejectAssociation() + * + *FUNCTION: + * This function is called whenever Re/Association Request need + * to be rejected due to failure in assigning an AID or failure + * in adding STA context reject by applications. + * + *LOGIC: + * Resources allocated if any are freedup and (Re) Association + * Response frame is sent to requesting STA. Pre-Auth context + * will be added for this STA if it does not exist already + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param *pBd - A pointer to Buffer descriptor + associated PDUs + * @param subType - Indicates whether it is Association Request (=0) or + * Reassociation Request (=1) frame + * @param addPreAuthContext - Indicates whether pre-auth context + * to be added for this STA + * @param authType - Indicates auth type to be added + * @param staId - Indicates staId of the STA being rejected + * association + * @param deleteSta - Indicates whether to delete STA context + * @param rCode - Indicates what reasonCode to be sent in + * Re/Assoc response to STA + * + * @return None + */ + +void +limRejectAssociation(tpAniSirGlobal pMac, tSirMacAddr peerAddr, tANI_U8 subType, + tANI_U8 addPreAuthContext, tAniAuthType authType, + tANI_U16 staId, tANI_U8 deleteSta, tSirResultCodes rCode, tpPESession psessionEntry ) +{ + tpDphHashNode pStaDs; + + limLog(pMac, LOG1, FL("Sessionid: %d authType: %d subType: %d " + "addPreAuthContext: %d staId: %d deleteSta: %d rCode : %d " + "peerAddr: "MAC_ADDRESS_STR),psessionEntry->peSessionId, + authType, subType, addPreAuthContext, staId, deleteSta, rCode, + MAC_ADDR_ARRAY(peerAddr)); + + if (addPreAuthContext) + { + // Create entry for this STA in pre-auth list + struct tLimPreAuthNode *pAuthNode; + + pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); + + if (pAuthNode) + { + vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, + peerAddr, + sizeof(tSirMacAddr)); + pAuthNode->fTimerStarted = 0; + pAuthNode->mlmState = eLIM_MLM_AUTHENTICATED_STATE; + pAuthNode->authType = (tAniAuthType) authType; + pAuthNode->timestamp = vos_timer_get_system_ticks(); + limAddPreAuthNode(pMac, pAuthNode); + } + } + + if (deleteSta == true) + { + pStaDs = dphGetHashEntry(pMac, staId, &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) + { + limLog(pMac, LOGW, + FL("No STA context, yet rejecting Association")); + + return; + } + + /** + * 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); + + if ( psessionEntry->parsedAssocReq[pStaDs->assocId] != NULL) + { + // Assoction confirmation is complete, free the copy of association request frame + if ( ((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame) + { + vos_mem_free(((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame); + ((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame = NULL; + } + vos_mem_free(psessionEntry->parsedAssocReq[pStaDs->assocId]); + psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL; + } + } + else + { + limSendAssocRspMgmtFrame(pMac, + eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS, + 1, + peerAddr, + subType, 0,psessionEntry); + // Log error + limLog(pMac, LOGW, + FL("received Re/Assoc req when max associated STAs reached from ")); + limPrintMacAddr(pMac, peerAddr, LOGW); + limSendSmeMaxAssocExceededNtf(pMac, peerAddr, psessionEntry->smeSessionId); + } +} /*** end limRejectAssociation() ***/ + + +/** ------------------------------------------------------------- +\fn limDecideApProtectionOnHt20Delete +\brief protection related function while HT20 station is getting deleted. +\param tpAniSirGlobal pMac +\param tpDphHashNode pStaDs +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +static void +limDecideApProtectionOnHt20Delete(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + tANI_U32 i = 0; + PELOG1( limLog(pMac, LOG1, FL("(%d) A HT 20 STA is disassociated. Addr is "), + psessionEntry->gLimHt20Params.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLimHt20Params.numSta > 0) + { + for (i=0; iprotStaCache[i].active) + { + if (vos_mem_compare(psessionEntry->protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLimHt20Params.numSta--; + psessionEntry->protStaCache[i].active = false; + break; + } + } + } + } + + if (psessionEntry->gLimHt20Params.numSta == 0) + { + // disable protection + limLog(pMac, LOG1, FL("No 11B STA exists, PESessionID %d"), + psessionEntry->peSessionId); + limEnableHT20Protection(pMac, false, false, pBeaconParams,psessionEntry); + } +} +/** ------------------------------------------------------------- +\fn limDecideApProtectionOnDelete +\brief Decides about protection related settings when a station is getting deleted. +\param tpAniSirGlobal pMac +\param tpDphHashNode pStaDs +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +void +limDecideApProtectionOnDelete(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + tANI_U32 phyMode; + tHalBitVal erpEnabled = eHAL_CLEAR; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + tANI_U32 i; + + if(NULL == pStaDs) + return; + + limGetRfBand(pMac, &rfBand, psessionEntry); + if(SIR_BAND_5_GHZ == rfBand) + { + //we are HT. if we are 11A, then protection is not required. + if(true == psessionEntry->htCapability) + { + //we are HT and 11A station is leaving. + //protection consideration required. + //HT station leaving ==> this case is commonly handled between both the bands below. + if((psessionEntry->beaconParams.llaCoexist) && + (false == pStaDs->mlmStaContext.htCapability)) + { + PELOG1(limLog(pMac, LOG1, FL("(%d) A 11A STA is disassociated. Addr is "), + psessionEntry->gLim11aParams.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLim11aParams.numSta > 0) + { + for (i=0; iprotStaCache[i].active) + { + if (vos_mem_compare( psessionEntry->protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLim11aParams.numSta--; + break; + } + } + } + } + + if(psessionEntry->gLim11aParams.numSta == 0) + { + // disable protection + limEnable11aProtection(pMac, false, false, pBeaconParams,psessionEntry); + } + } + } + } + else if(SIR_BAND_2_4_GHZ == rfBand) + { + limGetPhyMode(pMac, &phyMode, psessionEntry); + + erpEnabled = pStaDs->erpEnabled; + //we are HT or 11G and 11B station is getting deleted. + if (((phyMode == WNI_CFG_PHY_MODE_11G) || + psessionEntry->htCapability) && + (erpEnabled == eHAL_CLEAR)) + { + PELOG1(limLog(pMac, LOG1, FL("(%d) A legacy STA is disassociated. Addr is "), + psessionEntry->gLim11bParams.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLim11bParams.numSta > 0) + { + for (i=0; iprotStaCache[i].active) + { + if (vos_mem_compare( psessionEntry->protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLim11bParams.numSta--; + psessionEntry->protStaCache[i].active = false; + break; + } + } + } + } + + if (psessionEntry->gLim11bParams.numSta == 0) + { + // disable protection + limEnable11gProtection(pMac, false, false, pBeaconParams,psessionEntry); + } + } + //(non-11B station is leaving) or (we are not 11G or HT AP) + else if(psessionEntry->htCapability) + { //we are HT AP and non-11B station is leaving. + + //11g station is leaving + if(!pStaDs->mlmStaContext.htCapability) + { + PELOG1(limLog(pMac, LOG1, FL("(%d) A 11g STA is disassociated. Addr is "), + psessionEntry->gLim11bParams.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLim11gParams.numSta > 0) + { + for (i=0; iprotStaCache[i].active) + { + if (vos_mem_compare( psessionEntry->protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLim11gParams.numSta--; + psessionEntry->protStaCache[i].active = false; + break; + } + } + } + } + + if (psessionEntry->gLim11gParams.numSta == 0) + { + // disable protection + limEnableHtProtectionFrom11g(pMac, false, false, pBeaconParams,psessionEntry); + } + } + } + } + + //LSIG TXOP not supporting staiton leaving. applies to 2.4 as well as 5 GHZ. + if((true == psessionEntry->htCapability) && + (true == pStaDs->mlmStaContext.htCapability)) + { + //HT non-GF leaving + if(!pStaDs->htGreenfield) + { + PELOG1(limLog(pMac, LOG1, FL("(%d) A non-GF STA is disassociated. Addr is "), + psessionEntry->gLimNonGfParams.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLimNonGfParams.numSta > 0) + { + for (i=0; iprotStaCache[i].active) + { + if (vos_mem_compare( psessionEntry->protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLimNonGfParams.numSta--; + break; + } + } + } + } + + if (psessionEntry->gLimNonGfParams.numSta == 0) + { + // disable protection + limEnableHTNonGfProtection(pMac, false, false, pBeaconParams,psessionEntry); + } + } + //HT 20Mhz station leaving. + if(psessionEntry->beaconParams.ht20Coexist && + (eHT_CHANNEL_WIDTH_20MHZ == pStaDs->htSupportedChannelWidthSet)) + { + limDecideApProtectionOnHt20Delete(pMac, pStaDs, pBeaconParams,psessionEntry); + } + + if(false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport && + (false == pStaDs->htLsigTXOPProtection)) + { + PELOG1( limLog(pMac, LOG1, FL("(%d) A HT LSIG not supporting STA is disassociated. Addr is "), + psessionEntry->gLimLsigTxopParams.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLimLsigTxopParams.numSta > 0) + { + for (i=0; iprotStaCache[i].active) + { + if (vos_mem_compare( psessionEntry->protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLimLsigTxopParams.numSta--; + break; + } + } + } + } + + if (psessionEntry->gLimLsigTxopParams.numSta == 0) + { + // disable protection + limEnableHTLsigTxopProtection(pMac, true, false, pBeaconParams,psessionEntry); + } + } + } +} + + + +/** ------------------------------------------------------------- +\fn limDecideShortPreamble +\brief Decides about any short preamble reated change because of new station joining. +\param tpAniSirGlobal pMac +\param tpDphHashNode pStaDs +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +void limDecideShortPreamble(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry ) +{ + tANI_U32 i; + + if (pStaDs->shortPreambleEnabled == eHAL_CLEAR) + { + PELOG1(limLog(pMac, LOG1, FL("(%d) A non-short preamble STA is disassociated. Addr is "), + psessionEntry->gLimNoShortParams.numNonShortPreambleSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + if (psessionEntry->gLimNoShortParams.numNonShortPreambleSta > 0) + { + for (i=0; igLimNoShortParams.staNoShortCache[i].active) + { + if (vos_mem_compare( psessionEntry->gLimNoShortParams.staNoShortCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLimNoShortParams.numNonShortPreambleSta--; + psessionEntry->gLimNoShortParams.staNoShortCache[i].active = false; + break; + } + } + } + } + + if (psessionEntry->gLimNoShortParams.numNonShortPreambleSta == 0) + { + // enable short preamble + //reset the cache + vos_mem_set((tANI_U8 *)&psessionEntry->gLimNoShortParams, + sizeof(tLimNoShortParams), 0); + if (limEnableShortPreamble(pMac, true, pBeaconParams, psessionEntry) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Cannot enable short preamble"));) + } + } +} + +/** ------------------------------------------------------------- +\fn limDecideShortSlot +\brief Decides about any short slot time related change because of station leaving the BSS. +\param tpAniSirGlobal pMac +\param tpDphHashNode pStaDs +\return None + -------------------------------------------------------------*/ + +void +limDecideShortSlot(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + tANI_U32 i, val; + if (pStaDs->shortSlotTimeEnabled == eHAL_CLEAR) + { + PELOG1(limLog(pMac, LOG1, FL("(%d) A non-short slottime STA is disassociated. Addr is "), + pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + + if (LIM_IS_AP_ROLE(psessionEntry) && + psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta > 0) { + for (i=0; igLimNoShortSlotParams.staNoShortSlotCache[i].active) + { + if (vos_mem_compare(psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta--; + psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active = false; + break; + } + } + } + } else { + if (pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta> 0) + { + for (i=0; ilim.gLimNoShortSlotParams.staNoShortSlotCache[i].active) + { + if (vos_mem_compare(pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta--; + pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active = false; + break; + } + } + } + } + } + + wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val); + + if (LIM_IS_AP_ROLE(psessionEntry) && + (val && psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta == 0)) { + // enable short slot time + //reset the cache + vos_mem_set((tANI_U8 *)&psessionEntry->gLimNoShortSlotParams, + sizeof(tLimNoShortSlotParams), 0); + // in case of AP set SHORT_SLOT_TIME to enable + pBeaconParams->fShortSlotTime = true; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; + psessionEntry->shortSlotTimeSupported = true; + } else { + if (val && pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta == 0) { + // enable short slot time + //reset the cache + vos_mem_set((tANI_U8 *)&pMac->lim.gLimNoShortSlotParams, + sizeof(tLimNoShortSlotParams), 0); + // in case of AP set SHORT_SLOT_TIME to enable + if (LIM_IS_AP_ROLE(psessionEntry)) { + pBeaconParams->fShortSlotTime = true; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; + psessionEntry->shortSlotTimeSupported = true; + } + } + } + } +} + +void +limPostReassocFailure(tpAniSirGlobal pMac, + tSirResultCodes resultCode, + tANI_U16 protStatusCode,tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; + + psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_LINK_ESTABLISHED_STATE)); + + // 'Change' timer for future activations + limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_FAIL_TIMER); + + mlmReassocCnf.resultCode = resultCode; + mlmReassocCnf.protStatusCode = protStatusCode; + /* Update PE session Id */ + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage(pMac, + LIM_MLM_REASSOC_CNF, + (tANI_U32 *) &mlmReassocCnf); +} /*** end limPostReassocFailure() ***/ + +/** + * limRestorePreReassocState() + * + *FUNCTION: + * This function is called on STA role whenever Reasociation + * Response with a reject code is received from AP. + * + *LOGIC: + * Reassociation failure timer is stopped, Old (or current) AP's + * context is restored at software + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param resultCode - Result code that specifies why Reassociation + * attemp failed + * + * @return None + */ + +void +limRestorePreReassocState(tpAniSirGlobal pMac, + tSirResultCodes resultCode, + tANI_U16 protStatusCode,tpPESession psessionEntry) +{ + tANI_U8 chanNum, secChanOffset; + tLimMlmReassocCnf mlmReassocCnf; + + limLog(pMac, LOG1, FL("sessionid: %d protStatusCode: %d resultCode: %d"), + psessionEntry->smeSessionId, protStatusCode, resultCode); + + psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_LINK_ESTABLISHED_STATE)); + + // 'Change' timer for future activations + limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_FAIL_TIMER); + + /* To support BT-AMP */ + chanNum = psessionEntry->currentOperChannel; + secChanOffset = psessionEntry->htSecondaryChannelOffset; + + limSetChannel(pMac, chanNum, secChanOffset, psessionEntry->maxTxPower, psessionEntry->peSessionId); + + /** @ToDo : Need to Integrate the STOP the DataTransfer to the AP from 11H code */ + + mlmReassocCnf.resultCode = resultCode; + mlmReassocCnf.protStatusCode = protStatusCode; + /* Update PE session Id */ + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage(pMac, + LIM_MLM_REASSOC_CNF, + (tANI_U32 *) &mlmReassocCnf); +} /*** end limRestorePreReassocState() ***/ + + + +/** + * limIsReassocInProgress() + * + *FUNCTION: + * This function is called to see if STA is in wt-reassoc-rsp state. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * + * @return eANI_BOOLEAN_TRUE When STA is waiting for Reassoc response from AP \n + * else eANI_BOOLEAN_FALSE + */ + +eAniBoolean +limIsReassocInProgress(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + if (psessionEntry == NULL) + { + return eANI_BOOLEAN_FALSE; + } + if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + ((psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) || + (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_LINK_FAIL_STATE))) + return eANI_BOOLEAN_TRUE; + + return eANI_BOOLEAN_FALSE; +} /*** end limIsReassocInProgress() ***/ + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus limPopulateVhtMcsSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tDot11fIEVHTCaps *pPeerVHTCaps, + tpPESession psessionEntry, + uint8_t nss) +{ + tANI_U32 val; + tANI_U32 selfStaDot11Mode=0; + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfStaDot11Mode); + + if (IS_DOT11_MODE_VHT(selfStaDot11Mode)) + { + if ( wlan_cfgGetInt( pMac,WNI_CFG_VHT_RX_MCS_MAP,&val) != + eSIR_SUCCESS ) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve VHT RX MCS MAP"));) + goto error; + } + pRates->vhtRxMCSMap = (tANI_U16)val; + + if ( wlan_cfgGetInt( pMac,WNI_CFG_VHT_TX_MCS_MAP,&val ) != + eSIR_SUCCESS ) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve VHT TX MCS MAP"));) + goto error; + } + pRates->vhtTxMCSMap = (tANI_U16)val; + + if ( wlan_cfgGetInt( pMac,WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,&val ) != + eSIR_SUCCESS ) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve VHT RX Supported data rate MAP"));) + goto error; + } + pRates->vhtRxHighestDataRate = (tANI_U16)val; + + if ( wlan_cfgGetInt( pMac,WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,&val ) != + eSIR_SUCCESS ) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve VHT RX Supported data rate MAP"));) + goto error; + } + pRates->vhtTxHighestDataRate = (tANI_U16)val; + + if (NSS_1x1_MODE == nss) { + pRates->vhtRxMCSMap |= VHT_MCS_1x1; + pRates->vhtTxMCSMap |= VHT_MCS_1x1; + pRates->vhtTxHighestDataRate = + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + pRates->vhtRxHighestDataRate = + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } + + if( pPeerVHTCaps != NULL) + { + tANI_U16 mcsMapMask = MCSMAPMASK1x1; + tANI_U16 mcsMapMask2x2 = 0; + pRates->vhtTxHighestDataRate = SIR_MIN(pRates->vhtTxHighestDataRate, pPeerVHTCaps->txSupDataRate); + pRates->vhtRxHighestDataRate = SIR_MIN(pRates->vhtRxHighestDataRate, pPeerVHTCaps->rxHighSupDataRate); + + if (!pMac->per_band_chainmask_supp) { + if (pMac->roam.configParam.enable2x2) { + if (psessionEntry) { + if ((pMac->lteCoexAntShare) && (IS_24G_CH( + psessionEntry->currentOperChannel))) { + if (IS_2X2_CHAIN(psessionEntry->chainMask)) + mcsMapMask2x2 = MCSMAPMASK2x2; + else + limLog(pMac, LOGE,FL( + "2x2 not enabled %d"), + psessionEntry->chainMask); + } else { + mcsMapMask2x2 = MCSMAPMASK2x2; + } + } else { + mcsMapMask2x2 = MCSMAPMASK2x2; + } + } + } else { + if (psessionEntry && (psessionEntry->vdev_nss == NSS_2x2_MODE)) + mcsMapMask2x2 = MCSMAPMASK2x2; + } + + if ((pPeerVHTCaps->txMCSMap & mcsMapMask) < (pRates->vhtRxMCSMap & mcsMapMask)) { + pRates->vhtRxMCSMap &= ~(mcsMapMask); + pRates->vhtRxMCSMap |= (pPeerVHTCaps->txMCSMap & mcsMapMask); + } + if ((pPeerVHTCaps->rxMCSMap & mcsMapMask) < (pRates->vhtTxMCSMap & mcsMapMask)) { + pRates->vhtTxMCSMap &= ~(mcsMapMask); + pRates->vhtTxMCSMap |= (pPeerVHTCaps->rxMCSMap & mcsMapMask); + } + + if (mcsMapMask2x2) { + + tANI_U16 peerMcsMap, selfMcsMap; + + peerMcsMap = pPeerVHTCaps->txMCSMap & mcsMapMask2x2; + selfMcsMap = pRates->vhtRxMCSMap & mcsMapMask2x2; + + if ((selfMcsMap != mcsMapMask2x2) && + ((peerMcsMap == mcsMapMask2x2) || + (peerMcsMap < selfMcsMap))) { + pRates->vhtRxMCSMap &= ~mcsMapMask2x2; + pRates->vhtRxMCSMap |= peerMcsMap; + } + + peerMcsMap = (pPeerVHTCaps->rxMCSMap & mcsMapMask2x2); + selfMcsMap = (pRates->vhtTxMCSMap & mcsMapMask2x2); + + if ((selfMcsMap != mcsMapMask2x2) && + ((peerMcsMap == mcsMapMask2x2) || + (peerMcsMap < selfMcsMap))) { + pRates->vhtTxMCSMap &= ~mcsMapMask2x2; + pRates->vhtTxMCSMap |= peerMcsMap; + } + } + + limLog(pMac, LOG1, FL( + "enable2x2 %d nss %d vhtRxMCSMap %x vhtTxMCSMap %x\n"), + pMac->roam.configParam.enable2x2, nss, + pRates->vhtRxMCSMap, pRates->vhtTxMCSMap); + + if (psessionEntry) { + psessionEntry->supported_nss_1x1 = + ((pRates->vhtTxMCSMap & VHT_MCS_1x1) == + VHT_MCS_1x1) ? true : false; + limLog(pMac, LOG1, FL("VHT supported nss 1x1 : %d "), + psessionEntry->supported_nss_1x1); + } + } + } + return eSIR_SUCCESS; +error: + + return eSIR_FAILURE; + +} +#endif + +/** + * limPopulateOwnRateSet + * + * FUNCTION: + * This function is called by limProcessAssocRsp() or + * limAddStaInIBSS() + * - It creates a combined rate set of 12 rates max which + * comprises the basic and extended rates read from CFG + * - It sorts the combined rate Set and copy it in the + * rate array of the pSTA descriptor + * - It sets the erpEnabled bit of the STA descriptor + * + * NOTE: + * ERP bit is set iff the dph PHY mode is 11G and there is at least + * an A rate in the supported or extended rate sets + * + * @param pMac - Pointer to Global MAC structure + * @param basicOnly - When passed value is true, only basic + * rates are copied to DPH node else + * all supported rates are copied + * @return eSIR_SUCCESS or eSIR_FAILURE + * + */ +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +limPopulateOwnRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps) +#else +tSirRetStatus +limPopulateOwnRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry) +#endif + +{ + tSirMacRateSet tempRateSet; + tSirMacRateSet tempRateSet2; + tANI_U32 i,j,val,min,isArate; + tANI_U32 phyMode = 0; + tANI_U32 selfStaDot11Mode=0; + + isArate = 0; + + wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); + limGetPhyMode(pMac, &phyMode, psessionEntry); + + /* Include 11b rates only when the device configured in + auto, 11a/b/g or 11b_only */ + if ( (selfStaDot11Mode == WNI_CFG_DOT11_MODE_ALL) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11A) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11AC) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11N) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11G) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11B) ) + { + val = WNI_CFG_SUPPORTED_RATES_11B_LEN; + wlan_cfgGetStr( pMac, WNI_CFG_SUPPORTED_RATES_11B, + (tANI_U8 *)&tempRateSet.rate, &val ); + tempRateSet.numRates = (tANI_U8) val; + } + else + tempRateSet.numRates = 0; + + /* Include 11a rates when the device configured in non-11b mode */ + if (!IS_DOT11_MODE_11B(selfStaDot11Mode)) + { + val = WNI_CFG_SUPPORTED_RATES_11A_LEN; + wlan_cfgGetStr( pMac, WNI_CFG_SUPPORTED_RATES_11A, + (tANI_U8 *)&tempRateSet2.rate, &val ); + tempRateSet2.numRates = (tANI_U8) val; + } + else + tempRateSet2.numRates = 0; + + if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) + { + //we are in big trouble + limLog(pMac, LOGP, FL("more than 12 rates in CFG")); + //panic + goto error; + } + + //copy all rates in tempRateSet, there are 12 rates max + for (i = 0;i < tempRateSet2.numRates; i++) + tempRateSet.rate[i + tempRateSet.numRates] = tempRateSet2.rate[i]; + tempRateSet.numRates += tempRateSet2.numRates; + + /** + * Sort rates in tempRateSet (they are likely to be already sorted) + * put the result in pSupportedRates + */ + { + tANI_U8 aRateIndex = 0; + tANI_U8 bRateIndex = 0; + + vos_mem_set((tANI_U8 *) pRates, sizeof(tSirSupportedRates), 0); + for(i = 0;i < tempRateSet.numRates; i++) + { + min = 0; + val = 0xff; + isArate = 0; + for(j = 0; (j < tempRateSet.numRates) && (j < SIR_MAC_RATESET_EID_MAX); j++) + { + if ((tANI_U32) (tempRateSet.rate[j] & 0x7f) < val) + { + val = tempRateSet.rate[j] & 0x7f; + min = j; + } + } + + if (sirIsArate(tempRateSet.rate[min] & 0x7f)) + isArate = 1; + + /* + * HAL needs to know whether the rate is basic rate or not, as it needs to + * update the response rate table accordingly. e.g. if one of the 11a rates is + * basic rate, then that rate can be used for sending control frames. + * HAL updates the response rate table whenever basic rate set is changed. + */ + if (basicOnly) + { + if (tempRateSet.rate[min] & 0x80) + { + if (isArate) + pRates->llaRates[aRateIndex++] = tempRateSet.rate[min]; + else + pRates->llbRates[bRateIndex++] = tempRateSet.rate[min]; + } + } + else + { + if (isArate) + pRates->llaRates[aRateIndex++] = tempRateSet.rate[min]; + else + pRates->llbRates[bRateIndex++] = tempRateSet.rate[min]; + } + tempRateSet.rate[min] = 0xff; + } + + } + + if (IS_DOT11_MODE_HT(selfStaDot11Mode)) + { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET, + pRates->supportedMCSSet, + &val) != eSIR_SUCCESS) + { + /// Could not get rateset from CFG. Log error. + PELOGE(limLog(pMac, LOGE, FL("could not retrieve supportedMCSSet"));) + goto error; + } + + if (psessionEntry->vdev_nss == NSS_1x1_MODE) + pRates->supportedMCSSet[1] = 0; + + //if supported MCS Set of the peer is passed in, then do the intersection + //else use the MCS set from local CFG. + + if(pSupportedMCSSet != NULL) + { + for(i=0; isupportedMCSSet[i] &= pSupportedMCSSet[i]; + + } + + PELOG2(limLog(pMac, LOG2, FL("MCS Rate Set Bitmap: "));) + for(i=0; isupportedMCSSet[i]);) + } + +#ifdef WLAN_FEATURE_11AC + limPopulateVhtMcsSet(pMac, pRates , pVHTCaps, psessionEntry, + psessionEntry->vdev_nss); +#endif + + return eSIR_SUCCESS; + + error: + + return eSIR_FAILURE; +} /*** limPopulateOwnRateSet() ***/ + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +limPopulatePeerRateSet(tpAniSirGlobal pMac, + + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps) +#else +tSirRetStatus +limPopulatePeerRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry) +#endif +{ + tSirMacRateSet tempRateSet; + tSirMacRateSet tempRateSet2; + tANI_U32 i,j,val,min,isArate; + isArate = 0; + + /* copy operational rate set from psessionEntry */ + if ( psessionEntry->rateSet.numRates <= SIR_MAC_RATESET_EID_MAX ) + { + vos_mem_copy((tANI_U8 *)tempRateSet.rate, + (tANI_U8*)(psessionEntry->rateSet.rate), + psessionEntry->rateSet.numRates); + tempRateSet.numRates = psessionEntry->rateSet.numRates; + } + else + { + limLog(pMac, LOGE, FL("more than SIR_MAC_RATESET_EID_MAX rates\n")); + goto error; + } + if ((psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11G) || + (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11A) || + (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11AC) || + (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11N)) + { + + if (psessionEntry->extRateSet.numRates <= SIR_MAC_RATESET_EID_MAX) + { + vos_mem_copy((tANI_U8 *)tempRateSet2.rate, + (tANI_U8*)(psessionEntry->extRateSet.rate), + psessionEntry->extRateSet.numRates); + tempRateSet2.numRates = psessionEntry->extRateSet.numRates; + } + else { + limLog(pMac, LOGE, FL("psessionEntry->extRateSet.numRates more than SIR_MAC_RATESET_EID_MAX rates\n")); + goto error; + } + } + else + tempRateSet2.numRates = 0; + if ((tempRateSet.numRates + tempRateSet2.numRates) > SIR_MAC_RATESET_EID_MAX) + { + //we are in big trouble + limLog(pMac, LOGP, FL("more than 12 rates in CFG")); + goto error; + } + + + //copy all rates in tempRateSet, there are 12 rates max + for (i = 0;i < tempRateSet2.numRates; i++) + tempRateSet.rate[i + tempRateSet.numRates] = tempRateSet2.rate[i]; + tempRateSet.numRates += tempRateSet2.numRates; + /** + * Sort rates in tempRateSet (they are likely to be already sorted) + * put the result in pSupportedRates + */ + { + tANI_U8 aRateIndex = 0; + tANI_U8 bRateIndex = 0; + vos_mem_set((tANI_U8 *) pRates, sizeof(tSirSupportedRates), 0); + for(i = 0;i < tempRateSet.numRates; i++) + { + min = 0; + val = 0xff; + isArate = 0; + for(j = 0; (j < tempRateSet.numRates) && (j < SIR_MAC_RATESET_EID_MAX); j++) + { + if ((tANI_U32) (tempRateSet.rate[j] & 0x7f) < val) + { + val = tempRateSet.rate[j] & 0x7f; + min = j; + } + } + if (sirIsArate(tempRateSet.rate[min] & 0x7f)) + isArate = 1; + /* + * HAL needs to know whether the rate is basic rate or not, as it needs to + * update the response rate table accordingly. e.g. if one of the 11a rates is + * basic rate, then that rate can be used for sending control frames. + * HAL updates the response rate table whenever basic rate set is changed. + */ + if (basicOnly) + { + if (tempRateSet.rate[min] & 0x80) + { + if (isArate) + pRates->llaRates[aRateIndex++] = tempRateSet.rate[min]; + else + pRates->llbRates[bRateIndex++] = tempRateSet.rate[min]; + } + } + else + { + if (isArate) + pRates->llaRates[aRateIndex++] = tempRateSet.rate[min]; + else + pRates->llbRates[bRateIndex++] = tempRateSet.rate[min]; + } + tempRateSet.rate[min] = 0xff; + } + } + + + if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)) + { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET, + pRates->supportedMCSSet, + &val) != eSIR_SUCCESS) + { + /// Could not get rateset from CFG. Log error. + PELOGE(limLog(pMac, LOGE, FL("could not retrieve supportedMCSSet"));) + goto error; + } + if (psessionEntry->vdev_nss == NSS_1x1_MODE) + pRates->supportedMCSSet[1] = 0; + + //if supported MCS Set of the peer is passed in, then do the intersection + //else use the MCS set from local CFG. + if(pSupportedMCSSet != NULL) + { + for(i=0; isupportedMCSSet[i] &= pSupportedMCSSet[i]; + } + + PELOG2(limLog(pMac, LOG2, FL("MCS Rate Set Bitmap: "));) + for(i=0; isupportedMCSSet[i]);) + + psessionEntry->supported_nss_1x1 = + ((pRates->supportedMCSSet[1] != 0) ? false : true); + PELOG1(limLog(pMac, LOG1, FL("HT supported nss 1x1 : %d "), + psessionEntry->supported_nss_1x1);) + + } +#ifdef WLAN_FEATURE_11AC + limPopulateVhtMcsSet(pMac, pRates , pVHTCaps, psessionEntry, + psessionEntry->vdev_nss); +#endif + return eSIR_SUCCESS; + error: + return eSIR_FAILURE; +} /*** limPopulatePeerRateSet() ***/ + +/** + * limPopulateMatchingRateSet + * FUNCTION: + * This is called at the time of Association Request + * processing on AP and while adding peer's context + * in IBSS role to process the CFG rate sets and + * the rate sets received in the Assoc request on AP + * or Beacon/Probe Response from peer in IBSS. + * + * LOGIC: + * 1. It makes the intersection between our own rate Sat + * and extemcded rate set and the ones received in the + * association request. + * 2. It creates a combined rate set of 12 rates max which + * comprised the basic and extended rates + * 3. It sorts the combined rate Set and copy it in the + * rate array of the pSTA descriptor + * + * ASSUMPTION: + * The parser has already ensured unicity of the rates in the + * association request structure + * + * @param: pMac - Pointer to Global MAC structure + * pStaDs - Pointer to DPH node + * pOperRateSet - Pointer to peer's supported rateset + * pExtRateSet - Pointer to peer's extended rateset + * + * @return: eSIR_SUCCESS or eSIR_FAILURE + */ +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +limPopulateMatchingRateSet(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tSirMacRateSet *pOperRateSet, + tSirMacRateSet *pExtRateSet, + tANI_U8* pSupportedMCSSet, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps) + +#else +tSirRetStatus +limPopulateMatchingRateSet(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tSirMacRateSet *pOperRateSet, + tSirMacRateSet *pExtRateSet, + tANI_U8* pSupportedMCSSet, + tpPESession psessionEntry) +#endif +{ + tSirMacRateSet tempRateSet; + tSirMacRateSet tempRateSet2; + tANI_U32 i,j,val,min,isArate; + tANI_U32 phyMode; + tANI_U8 mcsSet[SIZE_OF_SUPPORTED_MCS_SET]; + + isArate=0; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + /* copy operational rate set from psessionEntry */ + vos_mem_copy((tempRateSet.rate), (psessionEntry->rateSet.rate), + psessionEntry->rateSet.numRates); + tempRateSet.numRates = (tANI_U8) psessionEntry->rateSet.numRates; + + if (phyMode == WNI_CFG_PHY_MODE_11G) + { + vos_mem_copy((tempRateSet2.rate), (psessionEntry->extRateSet.rate), + psessionEntry->extRateSet.numRates); + tempRateSet2.numRates = (tANI_U8) psessionEntry->extRateSet.numRates; + } + else + tempRateSet2.numRates = 0; + + if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) + { + PELOGE(limLog(pMac, LOGE, FL("more than 12 rates in CFG"));) + goto error; + } + + /** + * Handling of the rate set IEs is the following: + * - keep only rates that we support and that the station supports + * - sort and the rates into the pSta->rate array + */ + + // Copy all rates in tempRateSet, there are 12 rates max + for(i = 0; i < tempRateSet2.numRates; i++) + tempRateSet.rate[i + tempRateSet.numRates] = + tempRateSet2.rate[i]; + + tempRateSet.numRates += tempRateSet2.numRates; + + /** + * Sort rates in tempRateSet (they are likely to be already sorted) + * put the result in tempRateSet2 + */ + tempRateSet2.numRates = 0; + + for(i = 0;i < tempRateSet.numRates; i++) + { + min = 0; + val = 0xff; + + for(j = 0;j < tempRateSet.numRates; j++) + if ((tANI_U32) (tempRateSet.rate[j] & 0x7f) < val) + { + val = tempRateSet.rate[j] & 0x7f; + min = j; + } + + tempRateSet2.rate[tempRateSet2.numRates++] = + tempRateSet.rate[min]; + tempRateSet.rate[min] = 0xff; + } + + + /** + * Copy received rates in tempRateSet, the parser has ensured + * unicity of the rates so there cannot be more than 12 + */ + for(i = 0; (i < pOperRateSet->numRates && i < SIR_MAC_RATESET_EID_MAX) ; i++) + { + tempRateSet.rate[i] = pOperRateSet->rate[i]; + } + + tempRateSet.numRates = pOperRateSet->numRates; + + if (pExtRateSet->numRates) + { + if((tempRateSet.numRates + pExtRateSet->numRates) > 12 ) + { + limLog( pMac, LOG2, + "Sum of SUPPORTED and EXTENDED Rate Set (%1d) exceeds 12!", + tempRateSet.numRates + pExtRateSet->numRates ); + + if( tempRateSet.numRates < 12 ) + { + int found = 0; + int tail = tempRateSet.numRates; + + for( i = 0; (i < pExtRateSet->numRates && i < SIR_MAC_RATESET_EID_MAX); i++ ) + { + found = 0; + for( j = 0; j < (tANI_U32) tail; j++ ) + { + if((tempRateSet.rate[j] & 0x7F) == + (pExtRateSet->rate[i] & 0x7F)) + { + found = 1; + break; + } + } + + if( !found ) + { + tempRateSet.rate[tempRateSet.numRates++] = + pExtRateSet->rate[i]; + + if( tempRateSet.numRates >= 12 ) + break; + } + } + } + else + limLog( pMac, LOG2, + "Relying only on the SUPPORTED Rate Set IE..." ); + } + else + { + for(j = 0; ((j < pExtRateSet->numRates) && (j < SIR_MAC_RATESET_EID_MAX) && ((i+j) < SIR_MAC_RATESET_EID_MAX)); j++) + tempRateSet.rate[i+j] = pExtRateSet->rate[j]; + + tempRateSet.numRates += pExtRateSet->numRates; + } + } + + { + tpSirSupportedRates rates = &pStaDs->supportedRates; + tANI_U8 aRateIndex = 0; + tANI_U8 bRateIndex = 0; + vos_mem_set((tANI_U8 *) rates, sizeof(tSirSupportedRates), 0); + for(i = 0;(i < tempRateSet2.numRates && i < SIR_MAC_RATESET_EID_MAX ); i++) + { + for(j = 0;(j < tempRateSet.numRates && j < SIR_MAC_RATESET_EID_MAX); j++) + { + if ((tempRateSet2.rate[i] & 0x7F) == + (tempRateSet.rate[j] & 0x7F)) + { + if (sirIsArate(tempRateSet2.rate[i] & 0x7f)) + { + isArate=1; + if (aRateIndex < SIR_NUM_11A_RATES) + rates->llaRates[aRateIndex++] = tempRateSet2.rate[i]; + } + else + { + if (bRateIndex < SIR_NUM_11B_RATES) + rates->llbRates[bRateIndex++] = tempRateSet2.rate[i]; + } + break; + } + } + } + } + + + //compute the matching MCS rate set, if peer is 11n capable and self mode is 11n +#ifdef FEATURE_WLAN_TDLS + if(pStaDs->mlmStaContext.htCapability) +#else + if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) && + (pStaDs->mlmStaContext.htCapability)) +#endif + { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET, + mcsSet, + &val) != eSIR_SUCCESS) + { + /// Could not get rateset from CFG. Log error. + limLog(pMac, LOGP, FL("could not retrieve supportedMCSSet")); + goto error; + } + if (psessionEntry->vdev_nss == NSS_1x1_MODE) + mcsSet[1] = 0; + + for(i=0; isupportedRates.supportedMCSSet[i] = mcsSet[i] & pSupportedMCSSet[i]; + + PELOG2(limLog(pMac, LOG2, FL("limPopulateMatchingRateSet: MCS Rate Set Bitmap from CFG and DPH : "));) + for(i=0; isupportedRates.supportedMCSSet[i]);) + } + } + +#ifdef WLAN_FEATURE_11AC + limPopulateVhtMcsSet(pMac, &pStaDs->supportedRates, pVHTCaps, + psessionEntry, psessionEntry->vdev_nss); +#endif + /** + * Set the erpEnabled bit iff the phy is in G mode and at least + * one A rate is supported + */ + if ((phyMode == WNI_CFG_PHY_MODE_11G) && isArate) + pStaDs->erpEnabled = eHAL_SET; + + + + return eSIR_SUCCESS; + + error: + + return eSIR_FAILURE; +} /*** limPopulateMatchingRateSet() ***/ + + + +/** + * limAddSta() + * + *FUNCTION: + * This function is called to add an STA context at hardware + * whenever a STA is (Re) Associated. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to the STA datastructure created by + * LIM and maintained by DPH + * @return retCode - Indicates success or failure return code + */ + +tSirRetStatus +limAddSta( + tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tANI_U8 updateEntry, tpPESession psessionEntry) +{ + tpAddStaParams pAddStaParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMacAddr staMac, *pStaAddr; + tANI_U8 i, nwType11b = 0; + tpSirAssocReq pAssocReq; + tLimIbssPeerNode *pPeerNode; /* for IBSS mode */ + tDot11fIEVHTCaps vht_caps; /* for IBSS mode */ + tANI_U8 *p2pIe = NULL; + + sirCopyMacAddr(staMac,psessionEntry->selfMacAddr); + + limLog(pMac, LOG1, FL("sessionid: %d updateEntry = %d limsystemrole = %d "), + psessionEntry->smeSessionId, updateEntry, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + pAddStaParams = vos_mem_malloc(sizeof(tAddStaParams)); + if (NULL == pAddStaParams) + { + limLog( pMac, LOGP, FL( "Unable to allocate memory during ADD_STA" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set((tANI_U8 *) pAddStaParams, sizeof(tAddStaParams), 0); + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) + pStaAddr = &pStaDs->staAddr; +#ifdef FEATURE_WLAN_TDLS + /* SystemRole shouldn't be matter if staType is TDLS peer */ + else if(STA_ENTRY_TDLS_PEER == pStaDs->staType) + { + pStaAddr = &pStaDs->staAddr ; + } +#endif + else + pStaAddr = &staMac; + + limLog(pMac, LOG1, FL(MAC_ADDRESS_STR": Subtype(Assoc/Reassoc): %d "), + MAC_ADDR_ARRAY(*pStaAddr), pStaDs->mlmStaContext.subType); + + vos_mem_copy((tANI_U8 *) pAddStaParams->staMac, + (tANI_U8 *) *pStaAddr, sizeof(tSirMacAddr)); + vos_mem_copy((tANI_U8 *) pAddStaParams->bssId, + psessionEntry->bssId, sizeof(tSirMacAddr)); + vos_mem_copy(&pAddStaParams->capab_info, + &pStaDs->mlmStaContext.capabilityInfo, + sizeof(pAddStaParams->capab_info)); + + limFillSupportedRatesInfo(pMac, pStaDs, &pStaDs->supportedRates,psessionEntry); + + //Copy legacy rates + vos_mem_copy ((tANI_U8*)&pAddStaParams->supportedRates, + (tANI_U8*)&pStaDs->supportedRates, sizeof(tSirSupportedRates)); + + pAddStaParams->assocId = pStaDs->assocId; + + pAddStaParams->wmmEnabled = pStaDs->qosMode; + pAddStaParams->listenInterval = pStaDs->mlmStaContext.listenInterval; + pAddStaParams->shortPreambleSupported = pStaDs->shortPreambleEnabled; + if (LIM_IS_AP_ROLE(psessionEntry) && + (pStaDs->mlmStaContext.subType == LIM_REASSOC)) { + /* TBD - need to remove this REASSOC check after fixing rmmod issue */ + pAddStaParams->updateSta = pStaDs->mlmStaContext.updateContext; + } + pStaDs->valid = 0; + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + + limLog(pMac, LOG2, FL(" Assoc ID: %d wmmEnabled = %d listenInterval = %d" + " shortPreambleSupported: %d "), pAddStaParams->assocId, + pAddStaParams->wmmEnabled, pAddStaParams->listenInterval, + pAddStaParams->shortPreambleSupported); + // This will indicate HAL to "allocate" a new STA index +#ifdef FEATURE_WLAN_TDLS + /* As there is corner case in-between add_sta and change_sta,if del_sta for other staIdx happened, + * firmware return wrong staIdx (recently removed staIdx). Until we get a confirmation from the + * firmware team it is now return correct staIdx for same sta_mac_addr for update case, we want + * to get around it by passing valid staIdx given by add_sta time. + */ + if((STA_ENTRY_TDLS_PEER == pStaDs->staType) && + (true == updateEntry)) + pAddStaParams->staIdx = pStaDs->staIndex; + else +#endif + pAddStaParams->staIdx = HAL_STA_INVALID_IDX; + pAddStaParams->staType = pStaDs->staType; + + pAddStaParams->updateSta = updateEntry; + + pAddStaParams->status = eHAL_STATUS_SUCCESS; + pAddStaParams->respReqd = 1; + //Update HT Capability + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_IBSS_ROLE(psessionEntry)) { + pAddStaParams->htCapable = pStaDs->mlmStaContext.htCapability; +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = pStaDs->mlmStaContext.vhtCapability; +#endif + } +#ifdef FEATURE_WLAN_TDLS + /* SystemRole shouldn't be matter if staType is TDLS peer */ + else if(STA_ENTRY_TDLS_PEER == pStaDs->staType) + { + pAddStaParams->htCapable = pStaDs->mlmStaContext.htCapability; +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = pStaDs->mlmStaContext.vhtCapability; +#endif + } +#endif + else + { + pAddStaParams->htCapable = psessionEntry->htCapability; +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = psessionEntry->vhtCapability; +#endif + + } +#ifdef WLAN_FEATURE_11AC + limLog(pMac, LOG2, FL("vhtCapable: %d "),pAddStaParams->vhtCapable); +#endif + limLog(pMac, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "), + pAddStaParams->staIdx,pAddStaParams->updateSta, + pAddStaParams->htCapable); + + pAddStaParams->greenFieldCapable = pStaDs->htGreenfield; + pAddStaParams->maxAmpduDensity= pStaDs->htAMpduDensity; + pAddStaParams->maxAmpduSize = pStaDs->htMaxRxAMpduFactor; + pAddStaParams->fDsssCckMode40Mhz = pStaDs->htDsssCckRate40MHzSupport; + pAddStaParams->fShortGI20Mhz = pStaDs->htShortGI20Mhz; + pAddStaParams->fShortGI40Mhz = pStaDs->htShortGI40Mhz; + pAddStaParams->lsigTxopProtection = pStaDs->htLsigTXOPProtection; + pAddStaParams->maxAmsduSize = pStaDs->htMaxAmsduLength; + pAddStaParams->txChannelWidthSet = pStaDs->htSupportedChannelWidthSet; + pAddStaParams->mimoPS = pStaDs->htMIMOPSState; + + limLog(pMac, LOG2, FL(" greenFieldCapable: %d maxAmpduDensity = %d " + "maxAmpduDensity = %d"), pAddStaParams->greenFieldCapable, + pAddStaParams->maxAmpduDensity, pAddStaParams->maxAmpduSize); + + limLog(pMac, LOG2, FL("fDsssCckMode40Mhz: %d fShortGI20Mhz: %d " + "fShortGI40Mhz: %d"), pAddStaParams->fDsssCckMode40Mhz, + pAddStaParams->fShortGI20Mhz, pAddStaParams->fShortGI40Mhz); + + limLog(pMac, LOG2, FL("lsigTxopProtection: %d maxAmsduSize: %d " + "txChannelWidthSet: %d mimoPS: %d "), pAddStaParams->lsigTxopProtection, + pAddStaParams->maxAmsduSize,pAddStaParams->txChannelWidthSet, + pAddStaParams->mimoPS); + +#ifdef WLAN_FEATURE_11AC + if(pAddStaParams->vhtCapable) + { + pAddStaParams->vhtTxChannelWidthSet = pStaDs->vhtSupportedChannelWidthSet; + pAddStaParams->vhtSupportedRxNss = pStaDs->vhtSupportedRxNss; + pAddStaParams->vhtTxBFCapable = +#ifdef FEATURE_WLAN_TDLS + (( STA_ENTRY_PEER == pStaDs->staType ) || (STA_ENTRY_TDLS_PEER == pStaDs->staType)) ? + pStaDs->vhtBeamFormerCapable : psessionEntry->txBFIniFeatureEnabled ; +#else + ( STA_ENTRY_PEER == pStaDs->staType ) ? pStaDs->vhtBeamFormerCapable : + psessionEntry->txBFIniFeatureEnabled ; +#endif + limLog(pMac, LOG2, FL("vhtTxChannelWidthSet: %d vhtTxBFCapable: %d"), + pAddStaParams->vhtTxChannelWidthSet,pAddStaParams->vhtTxBFCapable); + } +#endif + +#ifdef FEATURE_WLAN_TDLS + if((STA_ENTRY_PEER == pStaDs->staType) || + (STA_ENTRY_TDLS_PEER == pStaDs->staType)) +#else + if (STA_ENTRY_PEER == pStaDs->staType) +#endif + { + /* peer STA get the LDPC capability from pStaDs, which populated from + * HT/VHT capability*/ + if(pAddStaParams->vhtTxBFCapable && pMac->lim.disableLDPCWithTxbfAP) + { + pAddStaParams->htLdpcCapable = 0; + pAddStaParams->vhtLdpcCapable = 0; + } + else + { + if (psessionEntry->txLdpcIniFeatureEnabled & 0x1) + pAddStaParams->htLdpcCapable = pStaDs->htLdpcCapable; + else + pAddStaParams->htLdpcCapable = 0; + if (psessionEntry->txLdpcIniFeatureEnabled & 0x2) + pAddStaParams->vhtLdpcCapable = pStaDs->vhtLdpcCapable; + else + pAddStaParams->vhtLdpcCapable = 0; + } + } + else if( STA_ENTRY_SELF == pStaDs->staType) + { + /* For Self STA get the LDPC capability from config.ini*/ + pAddStaParams->htLdpcCapable = + (psessionEntry->txLdpcIniFeatureEnabled & 0x01); + pAddStaParams->vhtLdpcCapable = + ((psessionEntry->txLdpcIniFeatureEnabled >> 1)& 0x01); + } + + /* Update PE session ID*/ + pAddStaParams->sessionId = psessionEntry->peSessionId; + + /* Update SME session ID */ + pAddStaParams->smesessionId = psessionEntry->smeSessionId; + + pAddStaParams->maxTxPower = psessionEntry->maxTxPower; + + if (psessionEntry->parsedAssocReq != NULL) + { + // Get a copy of the already parsed Assoc Request + pAssocReq = (tpSirAssocReq) psessionEntry->parsedAssocReq[pStaDs->assocId]; + if ( pAssocReq && pAssocReq->addIEPresent && pAssocReq->addIE.length ) { + p2pIe = limGetP2pIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length); + } + pAddStaParams->p2pCapableSta = (p2pIe != NULL); + if ( pAssocReq && pAddStaParams->htCapable ) { + vos_mem_copy(&pAddStaParams->ht_caps, ((tANI_U8 *) &pAssocReq->HTCaps) + 1, + sizeof(pAddStaParams->ht_caps)); + } + if ( pAssocReq && pAddStaParams->vhtCapable) { + pAddStaParams->vht_caps = + ((pAssocReq->VHTCaps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | + (pAssocReq->VHTCaps.supportedChannelWidthSet << + SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | + (pAssocReq->VHTCaps.ldpcCodingCap << + SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | + (pAssocReq->VHTCaps.shortGI80MHz << + SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | + (pAssocReq->VHTCaps.shortGI160and80plus80MHz << + SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | + (pAssocReq->VHTCaps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) | + (pAssocReq->VHTCaps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) | + (pAssocReq->VHTCaps.suBeamFormerCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | + (pAssocReq->VHTCaps.suBeamformeeCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | + (pAssocReq->VHTCaps.csnofBeamformerAntSup << + SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | + (pAssocReq->VHTCaps.numSoundingDim << + SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | + (pAssocReq->VHTCaps.muBeamformerCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP)| + (pAssocReq->VHTCaps.muBeamformeeCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | + (pAssocReq->VHTCaps.vhtTXOPPS << SIR_MAC_VHT_CAP_TXOPPS) | + (pAssocReq->VHTCaps.htcVHTCap << SIR_MAC_VHT_CAP_HTC_CAP) | + (pAssocReq->VHTCaps.maxAMPDULenExp << + SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | + (pAssocReq->VHTCaps.vhtLinkAdaptCap << + SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | + (pAssocReq->VHTCaps.rxAntPattern << + SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | + (pAssocReq->VHTCaps.txAntPattern << + SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | + (pAssocReq->VHTCaps.reserved1 << SIR_MAC_VHT_CAP_RESERVED2)); + } + } else if (LIM_IS_IBSS_ROLE(psessionEntry)) { + /* in IBSS mode, use peer node as the source of ht_caps and vht_caps */ + pPeerNode = limIbssPeerFind(pMac, *pStaAddr); + if (!pPeerNode) { + limLog( pMac, LOGP, FL("Can't find IBSS peer node for ADD_STA")); + return eSIR_HAL_STA_DOES_NOT_EXIST; + } + + if (pPeerNode->atimIePresent) + { + pAddStaParams->atimIePresent = pPeerNode->atimIePresent; + pAddStaParams->peerAtimWindowLength = + pPeerNode->peerAtimWindowLength; + } + + pAddStaParams->ht_caps = + ( pPeerNode->htSupportedChannelWidthSet << + SIR_MAC_HT_CAP_CHWIDTH40_S ) | + ( pPeerNode->htGreenfield << + SIR_MAC_HT_CAP_GREENFIELD_S ) | + ( pPeerNode->htShortGI20Mhz << + SIR_MAC_HT_CAP_SHORTGI20MHZ_S ) | + ( pPeerNode->htShortGI40Mhz << + SIR_MAC_HT_CAP_SHORTGI40MHZ_S ) | + ( SIR_MAC_TXSTBC << + SIR_MAC_HT_CAP_TXSTBC_S ) | + ( SIR_MAC_RXSTBC << + SIR_MAC_HT_CAP_RXSTBC_S ) | + ( pPeerNode->htMaxAmsduLength << + SIR_MAC_HT_CAP_MAXAMSDUSIZE_S ) | + ( pPeerNode->htDsssCckRate40MHzSupport << + SIR_MAC_HT_CAP_DSSSCCK40_S ); + + vht_caps = pPeerNode->VHTCaps; + pAddStaParams->vht_caps = + ((vht_caps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | + (vht_caps.supportedChannelWidthSet << + SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | + (vht_caps.ldpcCodingCap << + SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | + (vht_caps.shortGI80MHz << + SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | + (vht_caps.shortGI160and80plus80MHz << + SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | + (vht_caps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) | + (vht_caps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) | + (vht_caps.suBeamFormerCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | + (vht_caps.suBeamformeeCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | + (vht_caps.csnofBeamformerAntSup << + SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | + (vht_caps.numSoundingDim << + SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | + (vht_caps.muBeamformerCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP)| + (vht_caps.muBeamformeeCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | + (vht_caps.vhtTXOPPS << SIR_MAC_VHT_CAP_TXOPPS) | + (vht_caps.htcVHTCap << SIR_MAC_VHT_CAP_HTC_CAP) | + (vht_caps.maxAMPDULenExp << + SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | + (vht_caps.vhtLinkAdaptCap << + SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | + (vht_caps.rxAntPattern << + SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | + (vht_caps.txAntPattern << + SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | + (vht_caps.reserved1 << SIR_MAC_VHT_CAP_RESERVED2)); + } + +#ifdef FEATURE_WLAN_TDLS + if (STA_ENTRY_TDLS_PEER == pStaDs->staType) + { + pAddStaParams->ht_caps = pStaDs->ht_caps; + pAddStaParams->vht_caps = pStaDs->vht_caps; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "%s: Sta type is TDLS_PEER, ht_caps: 0x%x, vht_caps: 0x%x", + __func__, pAddStaParams->ht_caps, pAddStaParams->vht_caps); + } +#endif + + //Disable BA. It will be set as part of ADDBA negotiation. + for( i = 0; i < STACFG_MAX_TC; i++ ) + { + pAddStaParams->staTCParams[i].txUseBA = eBA_DISABLE; + pAddStaParams->staTCParams[i].rxUseBA = eBA_DISABLE; + } + +#ifdef FEATURE_WLAN_TDLS + if(pStaDs->wmeEnabled && + (LIM_IS_AP_ROLE(psessionEntry) || + (STA_ENTRY_TDLS_PEER == pStaDs->staType))) +#else + if (pStaDs->wmeEnabled && LIM_IS_AP_ROLE(psessionEntry)) +#endif + { + pAddStaParams->uAPSD = 0; + /* update UAPSD and send it to LIM to add STA */ + // bitmap MSB <- LSB MSB 4 bits are for + // trigger enabled AC setting and LSB 4 bits + // are for delivery enabled AC setting + // 7 6 5 4 3 2 1 0 + // BE BK VI VO BE BK VI VO + pAddStaParams->uAPSD |= pStaDs->qos.capability.qosInfo.acvo_uapsd; + pAddStaParams->uAPSD |= (pStaDs->qos.capability.qosInfo.acvi_uapsd << 1); + pAddStaParams->uAPSD |= (pStaDs->qos.capability.qosInfo.acbk_uapsd << 2); + pAddStaParams->uAPSD |= (pStaDs->qos.capability.qosInfo.acbe_uapsd << 3); + //making delivery enabled and trigger enabled setting the same. + pAddStaParams->uAPSD |= pAddStaParams->uAPSD << 4; + + pAddStaParams->maxSPLen = pStaDs->qos.capability.qosInfo.maxSpLen; + limLog( pMac, LOG1, FL("uAPSD = 0x%x, maxSpLen = %d"), + pAddStaParams->uAPSD, pAddStaParams->maxSPLen); + } + +#ifdef WLAN_FEATURE_11W + pAddStaParams->rmfEnabled = pStaDs->rmfEnabled; + limLog( pMac, LOG1, FL( "PMF enabled %d"), pAddStaParams->rmfEnabled); +#endif + + limLog(pMac, LOG2, FL("htLdpcCapable: %d vhtLdpcCapable: %d " + "p2pCapableSta: %d"), pAddStaParams->htLdpcCapable, + pAddStaParams->vhtLdpcCapable, pAddStaParams->p2pCapableSta); + + if (!pAddStaParams->htLdpcCapable) + pAddStaParams->ht_caps &= ~(1 << SIR_MAC_HT_CAP_ADVCODING_S); + + if (!pAddStaParams->vhtLdpcCapable) + pAddStaParams->vht_caps &= ~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP); + //we need to defer the message until we get the response back from HAL. + if (pAddStaParams->respReqd) + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + for (i = 0; i < SIR_NUM_11A_RATES; i++) + { + if (sirIsArate(pStaDs->supportedRates.llaRates[i] & 0x7F)) + { + nwType11b = 0; + break; + } + else + { + nwType11b = 1; + } + } + if (nwType11b) + { + pAddStaParams->nwType = eSIR_11B_NW_TYPE; + } + else + { + pAddStaParams->nwType = psessionEntry->nwType; + } + + msgQ.type = WDA_ADD_STA_REQ; + + msgQ.reserved = 0; + msgQ.bodyptr = pAddStaParams; + msgQ.bodyval = 0; + + limLog(pMac, LOG1, FL("Sending WDA_ADD_STA_REQ for assocId %d"), + pStaDs->assocId); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if( eSIR_SUCCESS != retCode) + { + if (pAddStaParams->respReqd) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + limLog( pMac, LOGE, FL("ADD_STA_REQ for aId %d failed (reason %X)"), + pStaDs->assocId, retCode ); + vos_mem_free(pAddStaParams); + } + + return retCode; +} + + +/** + * limDelSta() + * + *FUNCTION: + * This function is called to delete an STA context at hardware + * whenever a STA is disassociated + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to the STA datastructure created by + * LIM and maintained by DPH + * @param fRespReqd - flag to indicate whether the delete is synchronous (true) + * or not (false) + * @return retCode - Indicates success or failure return code + */ + +tSirRetStatus +limDelSta( + tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tANI_BOOLEAN fRespReqd, + tpPESession psessionEntry) +{ + tpDeleteStaParams pDelStaParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + pDelStaParams = vos_mem_malloc(sizeof( tDeleteStaParams )); + if (NULL == pDelStaParams) + { + limLog( pMac, LOGP, FL( "Unable to allocate memory during ADD_STA" )); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_set((tANI_U8 *) pDelStaParams, sizeof(tDeleteStaParams), 0); + + // + // DPH contains the STA index only for "peer" STA entries. + // LIM global contains "self" STA index + // Thus, + // if( STA role ) + // get STA index from LIM global + // else + // get STA index from DPH + // + +#ifdef FEATURE_WLAN_TDLS + if ((LIM_IS_STA_ROLE(psessionEntry) && + (pStaDs->staType != STA_ENTRY_TDLS_PEER)) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) +#else + if (LIM_IS_STA_ROLE(psessionEntry) || LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) +#endif + pDelStaParams->staIdx= psessionEntry->staId; + + else + pDelStaParams->staIdx= pStaDs->staIndex; + + pDelStaParams->assocId = pStaDs->assocId; + pStaDs->valid = 0; + + if (! fRespReqd) + pDelStaParams->respReqd = 0; + else + { + //when limDelSta is called from processSmeAssocCnf then mlmState is already set properly. + if(eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != GET_LIM_STA_CONTEXT_MLM_STATE(pStaDs)) + { + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_WT_DEL_STA_RSP_STATE)); + SET_LIM_STA_CONTEXT_MLM_STATE(pStaDs, eLIM_MLM_WT_DEL_STA_RSP_STATE); + } + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_WT_DEL_STA_RSP_STATE)); + + psessionEntry->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + + } + pDelStaParams->respReqd = 1; + //we need to defer the message until we get the response back from HAL. + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + } + + /* Update PE session ID*/ + pDelStaParams->sessionId = psessionEntry->peSessionId; + pDelStaParams->smesessionId = psessionEntry->smeSessionId; + + pDelStaParams->staType = pStaDs->staType; + vos_mem_copy((tANI_U8 *)pDelStaParams->staMac, + (tANI_U8 *)pStaDs->staAddr, sizeof(tSirMacAddr)); + + pDelStaParams->status = eHAL_STATUS_SUCCESS; + msgQ.type = WDA_DELETE_STA_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pDelStaParams; + msgQ.bodyval = 0; + + limLog( pMac, LOG1, FL( "Sessionid %d :Sending SIR_HAL_DELETE_STA_REQ " + "for STAID: %X and AssocID: %d MAC : "MAC_ADDRESS_STR ), + pDelStaParams->sessionId, + pDelStaParams->staIdx, pDelStaParams->assocId, + MAC_ADDR_ARRAY(pStaDs->staAddr)); + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if( eSIR_SUCCESS != retCode) + { + if(fRespReqd) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + limLog( pMac, LOGE, FL("Posting DELETE_STA_REQ to HAL failed, reason=%X"), + retCode ); + vos_mem_free(pDelStaParams); + } + + return retCode; +} + +#if defined WLAN_FEATURE_VOWIFI_11R +/*------------------------------------------------------------------------ + * limAddFTStaSelf() + * + * FUNCTION: + * + * This function is called to add a STA once we have connected with a new + * AP, that we have performed an FT to. + * + * The Add STA Response is created and now after the ADD Bss Is Successful + * we add the self sta. We update with the association id from the reassoc + * response from the AP. + *------------------------------------------------------------------------ + */ +tSirRetStatus limAddFTStaSelf(tpAniSirGlobal pMac, tANI_U16 assocId, tpPESession psessionEntry) +{ + tpAddStaParams pAddStaParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pAddStaParams = psessionEntry->ftPEContext.pAddStaReq; + pAddStaParams->assocId = assocId; + pAddStaParams->smesessionId = psessionEntry->smeSessionId; + + msgQ.type = WDA_ADD_STA_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pAddStaParams; + msgQ.bodyval = 0; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "%s: Sending WDA_ADD_STA_REQ (aid %d)", + __func__, pAddStaParams->assocId); +#endif + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + eLIM_MLM_WT_ADD_STA_RSP_STATE)); + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + if (eSIR_SUCCESS != (retCode = wdaPostCtrlMsg(pMac, &msgQ))) { + limLog(pMac, LOGE, + FL("Posting WDA_ADD_STA_REQ to HAL failed, reason=%X"), retCode); + vos_mem_free(pAddStaParams); + } + psessionEntry->ftPEContext.pAddStaReq = NULL; + return retCode; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/** + * limAddStaSelf() + * + *FUNCTION: + * This function is called to add an STA context at hardware + * whenever a STA is (Re) Associated. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to the STA datastructure created by + * LIM and maintained by DPH + * @return retCode - Indicates success or failure return code + */ + +tSirRetStatus +limAddStaSelf(tpAniSirGlobal pMac,tANI_U16 staIdx, tANI_U8 updateSta, tpPESession psessionEntry) +{ + tpAddStaParams pAddStaParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMacAddr staMac; + tANI_U32 listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF; + tANI_U32 shortGi20MhzSupport; + tANI_U32 shortGi40MhzSupport; + tANI_U32 ampduLenExponent = 0; + tANI_U32 val; + /*This self Sta dot 11 mode comes from the cfg and the expectation here is + * that cfg carries the systemwide capability that device under + * consideration can support. This capability gets plumbed into the cfg + * cache at system initialization time via the .dat and .ini file override + * mechanisms and will not change. If it does change, it is the + * responsibility of SME to evict the selfSta and reissue a new AddStaSelf + * command.*/ + tANI_U32 selfStaDot11Mode=0, selfTxWidth=0; + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfStaDot11Mode); + limLog( pMac, LOG1, FL("cfgDot11Mode %d"),(int)selfStaDot11Mode); + wlan_cfgGetInt(pMac,WNI_CFG_HT_CAP_INFO_SUPPORTED_CHAN_WIDTH_SET,&selfTxWidth); + limLog( pMac, LOG1, FL("SGI 20 %d"),(int)selfTxWidth); + limLog( pMac, LOG1, FL("Roam Channel Bonding Mode %d"),(int)pMac->roam.configParam.uCfgDot11Mode); + + sirCopyMacAddr(staMac,psessionEntry->selfMacAddr); + limLog(pMac, LOG1, FL(MAC_ADDRESS_STR": "),MAC_ADDR_ARRAY(staMac)); + pAddStaParams = vos_mem_malloc(sizeof(tAddStaParams)); + if (NULL == pAddStaParams) + { + limLog( pMac, LOGP, FL( "Unable to allocate memory during ADD_STA" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set((tANI_U8 *) pAddStaParams, sizeof(tAddStaParams), 0); + + /// Add STA context at MAC HW (BMU, RHP & TFP) + vos_mem_copy((tANI_U8 *) pAddStaParams->staMac, + (tANI_U8 *) staMac, sizeof(tSirMacAddr)); + + vos_mem_copy((tANI_U8 *) pAddStaParams->bssId, + psessionEntry->bssId, sizeof(tSirMacAddr)); + + pAddStaParams->assocId = psessionEntry->limAID; + pAddStaParams->staType = STA_ENTRY_SELF; + pAddStaParams->status = eHAL_STATUS_SUCCESS; + pAddStaParams->respReqd = 1; + + /* Update PE session ID */ + pAddStaParams->sessionId = psessionEntry->peSessionId; + + /* Update SME session ID */ + pAddStaParams->smesessionId = psessionEntry->smeSessionId; + + pAddStaParams->maxTxPower = psessionEntry->maxTxPower; + + // This will indicate HAL to "allocate" a new STA index + pAddStaParams->staIdx = staIdx; + pAddStaParams->updateSta = updateSta; + + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != + eSIR_SUCCESS) { + limLog(pMac, LOGP, FL("Couldn't get SHORT_PREAMBLE, set default")); + pAddStaParams->shortPreambleSupported = 1; + } + pAddStaParams->shortPreambleSupported = val; + +#ifdef WLAN_FEATURE_11AC + limPopulateOwnRateSet(pMac, &pAddStaParams->supportedRates, NULL, false,psessionEntry,NULL); +#else + limPopulateOwnRateSet(pMac, &pAddStaParams->supportedRates, NULL, false,psessionEntry); +#endif + if ( IS_DOT11_MODE_HT(selfStaDot11Mode) ) + { + pAddStaParams->htCapable = TRUE ; + { + pAddStaParams->greenFieldCapable = limGetHTCapability( pMac, eHT_GREENFIELD, psessionEntry); + pAddStaParams->txChannelWidthSet = + pMac->roam.configParam.channelBondingMode5GHz; + pAddStaParams->mimoPS = limGetHTCapability( pMac, eHT_MIMO_POWER_SAVE, psessionEntry ); + pAddStaParams->rifsMode = limGetHTCapability( pMac, eHT_RIFS_MODE, psessionEntry ); + pAddStaParams->lsigTxopProtection = limGetHTCapability( pMac, eHT_LSIG_TXOP_PROTECTION, psessionEntry ); + pAddStaParams->delBASupport = limGetHTCapability( pMac, eHT_DELAYED_BA, psessionEntry ); + pAddStaParams->maxAmpduDensity = limGetHTCapability( pMac, eHT_MPDU_DENSITY, psessionEntry ); + pAddStaParams->maxAmpduSize = limGetHTCapability(pMac, eHT_MAX_RX_AMPDU_FACTOR, psessionEntry); + pAddStaParams->maxAmsduSize = limGetHTCapability( pMac, eHT_MAX_AMSDU_LENGTH, psessionEntry ); + pAddStaParams->max_amsdu_num = limGetHTCapability(pMac, + eHT_MAX_AMSDU_NUM, + psessionEntry); + pAddStaParams->fDsssCckMode40Mhz = limGetHTCapability( pMac, eHT_DSSS_CCK_MODE_40MHZ, psessionEntry); + /* + * We will read the gShortGI20Mhz from ini file, and if it is set + * to 1 then we will tell Peer that we support 40Mhz short GI + */ + if (HAL_STATUS_SUCCESS(ccmCfgGetInt + (pMac, WNI_CFG_SHORT_GI_20MHZ, + &shortGi20MhzSupport))) + { + if (VOS_TRUE == shortGi20MhzSupport) + { + pAddStaParams->fShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STAMAX; + } + else + { + pAddStaParams->fShortGI20Mhz = VOS_FALSE; + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz" + "CFG,setting value to default"));) + pAddStaParams->fShortGI20Mhz = WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + /* + * We will read the gShortGI40Mhz from ini file, and if it is set + * to 1 then we will tell Peer that we support 40Mhz short GI + */ + if (HAL_STATUS_SUCCESS(ccmCfgGetInt + (pMac, WNI_CFG_SHORT_GI_40MHZ, + &shortGi40MhzSupport))) + { + if (VOS_TRUE == shortGi40MhzSupport) + { + pAddStaParams->fShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STAMAX; + } + else + { + pAddStaParams->fShortGI40Mhz = VOS_FALSE; + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz" + "CFG,setting value to default"));) + pAddStaParams->fShortGI40Mhz = WNI_CFG_SHORT_GI_40MHZ_STADEF; + } + limLog(pMac, LOG2, FL(" greenFieldCapable: %d maxAmpduDensity = %d " + "maxAmpduSize = %d"), pAddStaParams->greenFieldCapable, + pAddStaParams->maxAmpduDensity, pAddStaParams->maxAmpduSize); + + limLog(pMac, LOG2, FL("fDsssCckMode40Mhz: %d fShortGI20Mhz: %d " + "fShortGI40Mhz: %d lsigTxopProtection: %d"), + pAddStaParams->fDsssCckMode40Mhz, pAddStaParams->fShortGI20Mhz, + pAddStaParams->fShortGI40Mhz, pAddStaParams->lsigTxopProtection); + + limLog(pMac, LOG2, FL(" maxAmsduSize: %d txChannelWidthSet: %d " + "mimoPS: %d rifsMode %d delBASupport %d"), + pAddStaParams->maxAmsduSize, + pAddStaParams->txChannelWidthSet, pAddStaParams->mimoPS, + pAddStaParams->rifsMode, pAddStaParams->delBASupport ); + } + } +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = IS_DOT11_MODE_VHT(selfStaDot11Mode); + if (pAddStaParams->vhtCapable){ + pAddStaParams->vhtTxChannelWidthSet = psessionEntry->vhtTxChannelWidthSet; + limLog( pMac, LOG1, FL("VHT WIDTH SET %d"),pAddStaParams->vhtTxChannelWidthSet); + } + pAddStaParams->vhtTxBFCapable = psessionEntry->txBFIniFeatureEnabled; + limLog(pMac, LOG2, FL("vhtCapable: %d vhtTxBFCapable %d "), + pAddStaParams->vhtCapable, pAddStaParams->vhtTxBFCapable); + + // In 11ac mode, the hardware is capable of supporting 128K AMPDU size + if ( IS_DOT11_MODE_VHT(selfStaDot11Mode) ) + { + if(wlan_cfgGetInt(pMac, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, &duLenExponent) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_VHT_AMPDU_LEN_EXPONENT")); + } + pAddStaParams->maxAmpduSize = (tANI_U8)ampduLenExponent; + } + pAddStaParams->vhtTxMUBformeeCapable = psessionEntry->txMuBformee; + pAddStaParams->enableVhtpAid = psessionEntry->enableVhtpAid; +#endif + pAddStaParams->enableAmpduPs = psessionEntry->enableAmpduPs; + pAddStaParams->enableHtSmps = (psessionEntry->enableHtSmps && + (!psessionEntry->supported_nss_1x1)); + pAddStaParams->htSmpsconfig = psessionEntry->htSmpsvalue; + + /* For Self STA get the LDPC capability from session i.e config.ini*/ + pAddStaParams->htLdpcCapable = + (psessionEntry->txLdpcIniFeatureEnabled & 0x01); + pAddStaParams->vhtLdpcCapable = + ((psessionEntry->txLdpcIniFeatureEnabled >> 1)& 0x01); + + if(wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); + pAddStaParams->listenInterval = (tANI_U16)listenInterval; + + if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona) + { + pAddStaParams->p2pCapableSta = 1; + } + + pAddStaParams->supportedRates.opRateMode = + limGetStaRateMode((tANI_U8)selfStaDot11Mode); + + limLog(pMac, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "), + pAddStaParams->staIdx,pAddStaParams->updateSta, + pAddStaParams->htCapable); + + limLog(pMac, LOG2, FL("htLdpcCapable: %d vhtLdpcCapable: %d " + "p2pCapableSta: %d"), + pAddStaParams->htLdpcCapable,pAddStaParams->vhtLdpcCapable, + pAddStaParams->p2pCapableSta); + /* As part of HS2.0 certification need to send reassoc + * to the same AP to which STA connected .in this case + * we are not sending delsta but sending only addsta + * which is causing target asssert. to fix this + * set pAddStaParams->nonRoamReassoc = 1 and using this + * skip sending the addsta to firmware + */ + if (psessionEntry->isNonRoamReassoc) { + pAddStaParams->nonRoamReassoc = 1; + psessionEntry->isNonRoamReassoc = 0; + } + limLog(pMac, LOG2, FL("sessionid: %d Assoc ID: %d listenInterval = %d " + "shortPreambleSupported: %d"), psessionEntry->smeSessionId, + pAddStaParams->assocId, pAddStaParams->listenInterval, + pAddStaParams->shortPreambleSupported); + + msgQ.type = WDA_ADD_STA_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pAddStaParams; + msgQ.bodyval = 0; + + limLog(pMac, LOG1, FL(MAC_ADDRESS_STR":Sessionid %d : " + "Sending WDA_ADD_STA_REQ. (aid %d)"), + MAC_ADDR_ARRAY(pAddStaParams->staMac), + pAddStaParams->sessionId, + pAddStaParams->assocId); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + if (eSIR_SUCCESS != (retCode = wdaPostCtrlMsg(pMac, &msgQ))) { + limLog(pMac, LOGE, + FL("Posting WDA_ADD_STA_REQ to HAL failed, reason=%X"), retCode); + vos_mem_free(pAddStaParams); + } + return retCode; +} + + +/** + * limTeardownInfraBSS() + * + *FUNCTION: + * This function is called by various LIM functions to teardown + * an established Infrastructure BSS + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limTeardownInfraBss(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + /** + * Send Broadcast Disassociate frame with + * 'leaving BSS' reason. + */ + limSendDisassocMgmtFrame(pMac, + eSIR_MAC_DISASSOC_LEAVING_BSS_REASON, + bcAddr,psessionEntry, FALSE); +} /*** end limTeardownInfraBss() ***/ + + +/** + * limHandleCnfWaitTimeout() + * + *FUNCTION: + * This function is called by limProcessMessageQueue to handle + * various confirmation failure cases. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to a sta descriptor + * @return None + */ + +void limHandleCnfWaitTimeout(tpAniSirGlobal pMac, tANI_U16 staId) +{ + tpDphHashNode pStaDs; + tpPESession psessionEntry = NULL; + + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gpLimCnfWaitTimer[staId].sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + pStaDs = dphGetHashEntry(pMac, staId, &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) + { + PELOGW(limLog(pMac, LOGW, FL("No STA context in SIR_LIM_CNF_WAIT_TIMEOUT."));) + return; + } + + switch (pStaDs->mlmStaContext.mlmState) { + case eLIM_MLM_WT_ASSOC_CNF_STATE: + PELOGW(limLog(pMac, LOGW, FL("Did not receive Assoc Cnf in eLIM_MLM_WT_ASSOC_CNF_STATE sta Assoc id %d"), pStaDs->assocId);) + limPrintMacAddr(pMac, pStaDs->staAddr, LOGW); + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + limRejectAssociation( + pMac, + pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, + pStaDs->mlmStaContext.authType, + pStaDs->assocId, + true, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + } + break; + + default: + limLog(pMac, LOGW, FL("Received CNF_WAIT_TIMEOUT in state %d"), + pStaDs->mlmStaContext.mlmState); + } +} + +/** + * limDeleteDphHashEntry() + * + *FUNCTION: + * This function is called whenever we need to delete + * the dph hash entry + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tANI_U16 staId + * @return None + */ + +void +limDeleteDphHashEntry(tpAniSirGlobal pMac, tSirMacAddr staAddr, tANI_U16 staId,tpPESession psessionEntry) +{ + tANI_U16 aid; + tpDphHashNode pStaDs; + tUpdateBeaconParams beaconParams; + + vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); + beaconParams.paramChangeBitmap = 0; + limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, staId); + if (NULL == psessionEntry) + { + PELOGE(limLog(pMac, LOGE, FL("NULL psessionEntry"));) + return; + } + beaconParams.bssIdx = psessionEntry->bssIdx; + pStaDs = dphLookupHashEntry(pMac, staAddr, &aid, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + PELOGW(limLog(pMac, LOGW, FL("Deleting DPH Hash entry for STAID: %X"), staId);) + // update the station count and perform associated actions + // do this before deleting the dph hash entry + limUtilCountStaDel(pMac, pStaDs, psessionEntry); + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) { + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(psessionEntry->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE){ + limDecideApProtectionOnDelete(pMac, pStaDs, &beaconParams,psessionEntry); + } + } + + if (LIM_IS_IBSS_ROLE(psessionEntry)) + limIbssDecideProtectionOnDelete(pMac, pStaDs, &beaconParams, psessionEntry); + + limDecideShortPreamble(pMac, pStaDs, &beaconParams, psessionEntry); + limDecideShortSlot(pMac, pStaDs, &beaconParams, psessionEntry); + + //Send message to HAL about beacon parameter change. + PELOGW(limLog(pMac, LOGW, FL("param bitmap = %d "), beaconParams.paramChangeBitmap);) + if((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) + { + schSetFixedBeaconFields(pMac,psessionEntry); + limSendBeaconParams(pMac, &beaconParams, psessionEntry ); + } + +#ifdef WLAN_FEATURE_11W + tx_timer_delete(&pStaDs->pmfSaQueryTimer); +#endif + } + if (dphDeleteHashEntry(pMac, staAddr, staId, &psessionEntry->dph.dphHashTable) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("error deleting hash entry")); +#ifdef SAP_AUTH_OFFLOAD + lim_pop_sap_deferred_msg(pMac, psessionEntry); +#endif + } +} + + + +/** + * limCheckAndAnnounceJoinSuccess() + * + *FUNCTION: + * This function is called upon receiving Beacon/Probe Response + * frame in WT_JOIN_BEACON_STATE to check if the received + * Beacon/Probe Response is from the BSS that we're attempting + * to join. + * + *LOGIC: + * If the Beacon/Probe Response is indeed from the BSS we're + * attempting to join, join success is sent to SME. + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pBPR Pointer to received Beacon/Probe Response + * @param pHdr Pointer to received Beacon/Probe Response + * MAC header + * @return None + */ + +void +limCheckAndAnnounceJoinSuccess(tpAniSirGlobal pMac, + tSirProbeRespBeacon *pBPR, + tpSirMacMgmtHdr pHdr,tpPESession psessionEntry) +{ + tSirMacSSid currentSSID; + tLimMlmJoinCnf mlmJoinCnf; + tANI_U32 val = 0; + tANI_U32 *noa1DurationFromBcn = NULL; + tANI_U32 *noa2DurationFromBcn = NULL; + tANI_U32 noa; + tANI_U32 TotalNum_NoADesc = 0; + + vos_mem_copy(currentSSID.ssId, + psessionEntry->ssId.ssId, + psessionEntry->ssId.length); + + currentSSID.length = (tANI_U8)psessionEntry->ssId.length ; + + if ( + /* Check for SSID only in probe response. Beacons may not carry + SSID information in hidden SSID case */ + ( (SIR_MAC_MGMT_FRAME == pHdr->fc.type) && + (SIR_MAC_MGMT_PROBE_RSP == pHdr->fc.subType) ) && + currentSSID.length && + (!vos_mem_compare((tANI_U8 *) &pBPR->ssId, + (tANI_U8 *) ¤tSSID, + (tANI_U8) (1 + currentSSID.length)) )) + { + /** + * Received SSID does not match with the one we've. + * Ignore received Beacon frame + */ + PELOG1(limLog(pMac, LOG1, FL("SSID received in Beacon does not match"));) +#ifdef WLAN_DEBUG + pMac->lim.gLimBcnSSIDMismatchCnt++; +#endif + return; + } + + if (LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || + LIM_IS_STA_ROLE(psessionEntry)) { + limLog(pMac, LOG1, FL("Received Beacon/PR with matching BSSID" + MAC_ADDRESS_STR "PESessionID %d"), + MAC_ADDR_ARRAY(psessionEntry->bssId), + psessionEntry->peSessionId ); + + // Deactivate Join Failure timer + limDeactivateAndChangeTimer(pMac, eLIM_JOIN_FAIL_TIMER); + // Deactivate Periodic Join timer + limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + + if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona && + pBPR->P2PProbeRes.NoticeOfAbsence.present) + { + + noa1DurationFromBcn = (tANI_U32*)(pBPR->P2PProbeRes.NoticeOfAbsence.NoADesc + 1); + + if(pBPR->P2PProbeRes.NoticeOfAbsence.num_NoADesc) + TotalNum_NoADesc = pBPR->P2PProbeRes.NoticeOfAbsence.num_NoADesc/SIZE_OF_NOA_DESCRIPTOR; + + noa = *noa1DurationFromBcn; + + if(TotalNum_NoADesc > 1) + { + noa2DurationFromBcn = (tANI_U32*)(pBPR->P2PProbeRes.NoticeOfAbsence.NoADesc + SIZE_OF_NOA_DESCRIPTOR + 1); + noa += *noa2DurationFromBcn; + } + + /*If MAX Noa exceeds 3 secs we will consider only 3 secs to + * avoid arbitary values in noa duration field + */ + noa = noa > MAX_NOA_PERIOD_IN_MICROSECS ? MAX_NOA_PERIOD_IN_MICROSECS : noa; + noa = noa/1000; //Convert to ms + + if( wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,&val) == eSIR_SUCCESS ) + { + psessionEntry->defaultAuthFailureTimeout = val; + ccmCfgSetInt(pMac,WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT ,val + noa, NULL, eANI_BOOLEAN_FALSE); + } + } + else + { + psessionEntry->defaultAuthFailureTimeout = 0; + } + + // Update Beacon Interval at CFG database + + if ( pBPR->HTCaps.present ) + limUpdateStaRunTimeHTCapability( pMac, &pBPR->HTCaps ); + if ( pBPR->HTInfo.present ) + limUpdateStaRunTimeHTInfo( pMac, &pBPR->HTInfo, psessionEntry); + psessionEntry->limMlmState = eLIM_MLM_JOINED_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_JOINED_STATE)); + + + /* + * update the capability info based on recently + * received beacon/probe response frame + */ + psessionEntry->limCurrentBssCaps = + limGetU16((tANI_U8 *)&pBPR->capabilityInfo); + + /** + * Announce join success by sending + * Join confirm to SME. + */ + mlmJoinCnf.resultCode = eSIR_SME_SUCCESS; + mlmJoinCnf.protStatusCode = eSIR_MAC_SUCCESS_STATUS; + /* Update PE sessionId*/ + mlmJoinCnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage(pMac, LIM_MLM_JOIN_CNF, (tANI_U32 *) &mlmJoinCnf); + } // if ((pMac->lim.gLimSystemRole == IBSS.... +} + +/** + * limExtractApCapabilities() + * + *FUNCTION: + * This function is called to extract all of the AP's capabilities + * from the IEs received from it in Beacon/Probe Response frames + * + *LOGIC: + * This routine mimics the limExtractApCapability() API. The difference here + * is that this API returns the entire tSirProbeRespBeacon info as is. It is + * left to the caller of this API to use this info as required + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pIE Pointer to starting IE in Beacon/Probe Response + * @param ieLen Length of all IEs combined + * @param beaconStruct A pointer to tSirProbeRespBeacon that needs to be + * populated + * @return status A status reporting eSIR_SUCCESS or eSIR_FAILURE + */ +tSirRetStatus limExtractApCapabilities( tpAniSirGlobal pMac, + tANI_U8 *pIE, + tANI_U16 ieLen, + tpSirProbeRespBeacon beaconStruct ) +{ + vos_mem_set((tANI_U8 *) beaconStruct, sizeof( tSirProbeRespBeacon ), 0); + + PELOG3(limLog( pMac, LOG3, + FL( "In limExtractApCapabilities: The IE's being received are:" )); + sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG3, pIE, ieLen );) + + // Parse the Beacon IE's, Don't try to parse if we dont have anything in IE + if (ieLen > 0) { + if( eSIR_SUCCESS != sirParseBeaconIE( pMac, beaconStruct, pIE, (tANI_U32)ieLen )) + { + limLog( pMac, LOGE, FL("APCapExtract: Beacon parsing error!")); + return eSIR_FAILURE; + } + } + + return eSIR_SUCCESS; +} + + +/** + * limDelBss() + * + *FUNCTION: + * This function is called to delete BSS context at hardware + * whenever a STA is disassociated + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to the STA datastructure created by + * LIM and maintained by DPH + * @return retCode - Indicates success or failure return code + */ + +tSirRetStatus +limDelBss(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tANI_U16 bssIdx,tpPESession psessionEntry) +{ + tpDeleteBssParams pDelBssParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + pDelBssParams = vos_mem_malloc(sizeof(tDeleteBssParams)); + if (NULL == pDelBssParams) + { + limLog( pMac, LOGP, FL( "Unable to allocate memory during ADD_BSS" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set((tANI_U8 *) pDelBssParams, sizeof(tDeleteBssParams), 0); + + + pDelBssParams->sessionId = psessionEntry->peSessionId; //update PE session Id + + //DPH was storing the AssocID in staID field, + //staID is actually assigned by HAL when AddSTA message is sent. + if (pStaDs != NULL) + { + pDelBssParams->bssIdx= pStaDs->bssId; + pStaDs->valid = 0; + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE; + } + else + pDelBssParams->bssIdx = bssIdx; + psessionEntry->limMlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_WT_DEL_BSS_RSP_STATE)); + + if((psessionEntry->peSessionId == pMac->lim.limTimers.gLimJoinFailureTimer.sessionId) && + (VOS_TRUE == tx_timer_running(&pMac->lim.limTimers.gLimJoinFailureTimer))) + { + limDeactivateAndChangeTimer(pMac, eLIM_JOIN_FAIL_TIMER); + } + + pDelBssParams->status= eHAL_STATUS_SUCCESS; + pDelBssParams->respReqd = 1; + vos_mem_copy(pDelBssParams->bssid, psessionEntry->bssId, sizeof(tSirMacAddr)); + pDelBssParams->smesessionId = psessionEntry->smeSessionId; + PELOGW(limLog( pMac, LOGW, FL("Sessionid %d : Sending HAL_DELETE_BSS_REQ " + "for bss idx: %X BSSID:"MAC_ADDRESS_STR), pDelBssParams->sessionId, + pDelBssParams->bssIdx, + MAC_ADDR_ARRAY(psessionEntry->bssId));) + + //we need to defer the message until we get the response back from HAL. + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.type = WDA_DELETE_BSS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pDelBssParams; + msgQ.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + limLog( pMac, LOGE, FL("Posting DELETE_BSS_REQ to HAL failed, reason=%X"), retCode ); + vos_mem_free(pDelBssParams); + } + + return retCode; +} + + + +/** + * limSendAddBss() + * + *FUNCTION: + * + *LOGIC: + * 1) LIM receives eWNI_SME_JOIN_REQ + * 2) For a valid eWNI_SME_JOIN_REQ, LIM sends + * SIR_HAL_ADD_BSS_REQ to HAL + * + *ASSUMPTIONS: + * JOIN REQ parameters are saved in pMac->lim.gLimMlmJoinReq + * ADD BSS parameters can be obtained from two sources: + * 1) pMac->lim.gLimMlmJoinReq + * 2) beaconStruct, passed as paramter + * So, if a reqd parameter is found in bssDescriptions + * then it is given preference over beaconStruct + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * pAssocRsp contains the structured assoc/reassoc Response got from AP + * beaconstruct Has the ProbeRsp/Beacon structured details + * bssDescription bssDescription passed to PE from the SME + * @return None + */ + +tSirRetStatus limStaSendAddBss( tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, + tpSchBeaconStruct pBeaconStruct, tpSirBssDescription bssDescription, tANI_U8 updateEntry, + tpPESession psessionEntry) + +{ + tSirMsgQ msgQ; + tpAddBssParams pAddBssParams = NULL; + tANI_U32 retCode; + tANI_U8 i; + tpDphHashNode pStaDs = NULL; + tANI_U8 chanWidthSupp = 0; + tANI_U32 shortGi20MhzSupport; + tANI_U32 shortGi40MhzSupport; + tANI_U32 enableTxBF20MHz; + // Package SIR_HAL_ADD_BSS_REQ message parameters + pAddBssParams = vos_mem_malloc(sizeof( tAddBssParams )); + if (NULL == pAddBssParams) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during ADD_BSS" )); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + else + vos_mem_set((tANI_U8 *) pAddBssParams, sizeof( tAddBssParams ), 0); + + vos_mem_copy(pAddBssParams->bssId,bssDescription->bssId, + sizeof(tSirMacAddr)); + // Fill in tAddBssParams selfMacAddr + vos_mem_copy(pAddBssParams->selfMacAddr, + psessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); + + limLog(pMac, LOG1, FL("sessionid: %d updateEntry = %d limsystemrole = %d "), + psessionEntry->smeSessionId, updateEntry, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + limLog(pMac, LOG1, FL("BSSID: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pAddBssParams->bssId)); + + if(psessionEntry->bssType == eSIR_BTAMP_AP_MODE) + { + pAddBssParams->bssType = eSIR_BTAMP_AP_MODE; + } + else + { + pAddBssParams->bssType = eSIR_INFRASTRUCTURE_MODE; + } + + pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA; + + /* Update PE session ID */ + pAddBssParams->sessionId = psessionEntry->peSessionId; + + pAddBssParams->beaconInterval = bssDescription->beaconInterval; + + pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod; + pAddBssParams->updateBss = updateEntry; + + + pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount; + pAddBssParams->cfParamSet.cfpPeriod = pBeaconStruct->cfParamSet.cfpPeriod; + pAddBssParams->cfParamSet.cfpMaxDuration = pBeaconStruct->cfParamSet.cfpMaxDuration; + pAddBssParams->cfParamSet.cfpDurRemaining = pBeaconStruct->cfParamSet.cfpDurRemaining; + + pAddBssParams->rateSet.numRates = pAssocRsp->supportedRates.numRates; + vos_mem_copy(pAddBssParams->rateSet.rate, + pAssocRsp->supportedRates.rate, pAssocRsp->supportedRates.numRates); + + if (IS_DOT11_MODE_11B(psessionEntry->dot11mode) && + bssDescription->nwType != eSIR_11B_NW_TYPE) { + pAddBssParams->nwType = eSIR_11B_NW_TYPE; + } else { + pAddBssParams->nwType = bssDescription->nwType; + } + + pAddBssParams->shortSlotTimeSupported = (tANI_U8)pAssocRsp->capabilityInfo.shortSlotTime; + pAddBssParams->llaCoexist = (tANI_U8) psessionEntry->beaconParams.llaCoexist; + pAddBssParams->llbCoexist = (tANI_U8) psessionEntry->beaconParams.llbCoexist; + pAddBssParams->llgCoexist = (tANI_U8) psessionEntry->beaconParams.llgCoexist; + pAddBssParams->ht20Coexist = (tANI_U8) psessionEntry->beaconParams.ht20Coexist; + + limLog(pMac, LOG2, FL(" BSS Type %d Beacon Interval: %d dtimPeriod: %d " + "cfpCount: %d"),pAddBssParams->bssType, pAddBssParams->beaconInterval, + pAddBssParams->dtimPeriod, pAddBssParams->cfParamSet.cfpCount); + + limLog(pMac, LOG2, FL(" cfpPeriod: %d cfpMaxDuration: %d cfpDurRemaining:" + " %d numRates: %d "),pAddBssParams->cfParamSet.cfpPeriod, + pAddBssParams->cfParamSet.cfpMaxDuration, + pAddBssParams->cfParamSet.cfpDurRemaining, + pAddBssParams->rateSet.numRates); + + limLog(pMac, LOG2, FL("nwType:%d shortSlotTimeSupported: %d" + "llaCoexist: %d llbCoexist: %d llgCoexist: %d ht20Coexist: %d"), + pAddBssParams->nwType, pAddBssParams->shortSlotTimeSupported, + pAddBssParams->llaCoexist, pAddBssParams->llbCoexist, + pAddBssParams->llgCoexist, pAddBssParams->ht20Coexist); + + pAddBssParams->dot11_mode = psessionEntry->dot11mode; + limLog(pMac, LOG2, FL("dot11_mode:%d"), pAddBssParams->dot11_mode); + + // Use the advertised capabilities from the received beacon/PR + + + if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) && ( pAssocRsp->HTCaps.present )) + { + pAddBssParams->htCapable = pAssocRsp->HTCaps.present; + limLog(pMac, LOG2, FL("htCapable: %d"),pAddBssParams->htCapable); + if ( pBeaconStruct->HTInfo.present ) + { + pAddBssParams->htOperMode = (tSirMacHTOperatingMode)pAssocRsp->HTInfo.opMode; + pAddBssParams->dualCTSProtection = ( tANI_U8 ) pAssocRsp->HTInfo.dualCTSProtection; + chanWidthSupp = limGetHTCapability( pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry); + if( (pAssocRsp->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp) ) + { + pAddBssParams->txChannelWidthSet = ( tANI_U8 )pAssocRsp->HTInfo.recommendedTxWidthSet; + pAddBssParams->currentExtChannel = pAssocRsp->HTInfo.secondaryChannelOffset; + } + else + { + pAddBssParams->txChannelWidthSet = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + pAddBssParams->currentExtChannel = PHY_SINGLE_CHANNEL_CENTERED; + } + pAddBssParams->llnNonGFCoexist = (tANI_U8)pAssocRsp->HTInfo.nonGFDevicesPresent; + pAddBssParams->fLsigTXOPProtectionFullSupport = (tANI_U8)pAssocRsp->HTInfo.lsigTXOPProtectionFullSupport; + pAddBssParams->fRIFSMode = pAssocRsp->HTInfo.rifsMode; + + limLog(pMac, LOG2, FL("htOperMode: %d dualCTSProtection: %d " + "txChannelWidthSet: %d currentExtChannel: %d "), + pAddBssParams->htOperMode, pAddBssParams->dualCTSProtection, + pAddBssParams->txChannelWidthSet,pAddBssParams->currentExtChannel); + + limLog(pMac, LOG2, FL("llnNonGFCoexist: %d " + "fLsigTXOPProtectionFullSupport: %d fRIFSMode %d"), + pAddBssParams->llnNonGFCoexist, + pAddBssParams->fLsigTXOPProtectionFullSupport, + pAddBssParams->fRIFSMode); + } + } + + pAddBssParams->currentOperChannel = bssDescription->channelId; + limLog(pMac, LOG2, FL("currentOperChannel %d"), + pAddBssParams->currentOperChannel); +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && ( pAssocRsp->VHTCaps.present )) + { + pAddBssParams->vhtCapable = pAssocRsp->VHTCaps.present; + pAddBssParams->vhtTxChannelWidthSet = pAssocRsp->VHTOperation.chanWidth; + pAddBssParams->currentExtChannel = limGet11ACPhyCBState ( pMac, + pAddBssParams->currentOperChannel, + pAddBssParams->currentExtChannel, + psessionEntry->apCenterChan, + psessionEntry); + + pAddBssParams->staContext.vht_caps = + ((pAssocRsp->VHTCaps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | + (pAssocRsp->VHTCaps.supportedChannelWidthSet << + SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | + (pAssocRsp->VHTCaps.ldpcCodingCap << + SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | + (pAssocRsp->VHTCaps.shortGI80MHz << + SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | + (pAssocRsp->VHTCaps.shortGI160and80plus80MHz << + SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | + (pAssocRsp->VHTCaps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) | + (pAssocRsp->VHTCaps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) | + (pAssocRsp->VHTCaps.suBeamFormerCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | + (pAssocRsp->VHTCaps.suBeamformeeCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | + (pAssocRsp->VHTCaps.csnofBeamformerAntSup << + SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | + (pAssocRsp->VHTCaps.numSoundingDim << + SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | + (pAssocRsp->VHTCaps.muBeamformerCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP)| + (pAssocRsp->VHTCaps.muBeamformeeCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | + (pAssocRsp->VHTCaps.vhtTXOPPS << SIR_MAC_VHT_CAP_TXOPPS) | + (pAssocRsp->VHTCaps.htcVHTCap << SIR_MAC_VHT_CAP_HTC_CAP) | + (pAssocRsp->VHTCaps.maxAMPDULenExp << + SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | + (pAssocRsp->VHTCaps.vhtLinkAdaptCap << + SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | + (pAssocRsp->VHTCaps.rxAntPattern << + SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | + (pAssocRsp->VHTCaps.txAntPattern << + SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | + (pAssocRsp->VHTCaps.reserved1 << SIR_MAC_VHT_CAP_RESERVED2)); + + pAddBssParams->staContext.maxAmpduSize = + SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( + pAddBssParams->staContext.vht_caps); + } + else + { + pAddBssParams->vhtCapable = 0; + } + limLog(pMac, LOG2, FL("vhtCapable %d vhtTxChannelWidthSet %d " + "currentExtChannel %d"),pAddBssParams->vhtCapable, + pAddBssParams->vhtTxChannelWidthSet, + pAddBssParams->currentExtChannel); +#endif + + + // Populate the STA-related parameters here + // Note that the STA here refers to the AP + { + /* staType = PEER*/ + pAddBssParams->staContext.staType = STA_ENTRY_OTHER; // Identifying AP as an STA + + vos_mem_copy(pAddBssParams->staContext.bssId, + bssDescription->bssId, + sizeof( tSirMacAddr)); + pAddBssParams->staContext.listenInterval = bssDescription->beaconInterval; + + /* Fill Assoc id from the dph table */ + pStaDs = dphLookupHashEntry(pMac, pAddBssParams->staContext.bssId, + &pAddBssParams->staContext.assocId, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Couldn't get assoc id for " + "MAC ADDR: " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pAddBssParams->staContext.staMac));) + return eSIR_FAILURE; + } + + if(!pMac->psOffloadEnabled) + { + pAddBssParams->staContext.uAPSD = 0; + } + else + { + pAddBssParams->staContext.uAPSD = + psessionEntry->gUapsdPerAcBitmask; + } + + pAddBssParams->staContext.maxSPLen = 0; + pAddBssParams->staContext.shortPreambleSupported = + psessionEntry->beaconParams.fShortPreamble; + pAddBssParams->staContext.updateSta = updateEntry; + + limLog(pMac, LOG2, FL("StaContext: "MAC_ADDRESS_STR + " shortPreambleSupported: %d"), + MAC_ADDR_ARRAY(pAddBssParams->staContext.staMac), + pAddBssParams->staContext.shortPreambleSupported); + + if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) && pBeaconStruct->HTCaps.present) + { + pAddBssParams->staContext.us32MaxAmpduDuration = 0; + pAddBssParams->staContext.htCapable = 1; + pAddBssParams->staContext.greenFieldCapable = ( tANI_U8 )pAssocRsp->HTCaps.greenField; + pAddBssParams->staContext.lsigTxopProtection = ( tANI_U8 )pAssocRsp->HTCaps.lsigTXOPProtection; + limLog(pMac, LOG2,FL("StaContext htCapable: %d greenFieldCapable: %d " + "lsigTxopProtection: %d"), pAddBssParams->staContext.htCapable, + pAddBssParams->staContext.greenFieldCapable, + pAddBssParams->staContext.lsigTxopProtection); +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) + { + pAddBssParams->staContext.vhtCapable = 1; + pAddBssParams->staContext.vhtSupportedRxNss = pStaDs->vhtSupportedRxNss; + if ((pAssocRsp->VHTCaps.suBeamFormerCap || + pAssocRsp->VHTCaps.muBeamformerCap) && + psessionEntry->txBFIniFeatureEnabled) + { + pAddBssParams->staContext.vhtTxBFCapable = 1; + } + + if (pAssocRsp->VHTCaps.muBeamformerCap && + psessionEntry->txMuBformee ) + { + pAddBssParams->staContext.vhtTxMUBformeeCapable = 1; + } + } +#endif + if( (pAssocRsp->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp) ) + { + pAddBssParams->staContext.txChannelWidthSet = ( tANI_U8 )pAssocRsp->HTInfo.recommendedTxWidthSet; +#ifdef WLAN_FEATURE_11AC + if (pAddBssParams->staContext.vhtCapable) + { + pAddBssParams->staContext.vhtTxChannelWidthSet = pAssocRsp->VHTOperation.chanWidth; //pMac->lim.apChanWidth; + } + limLog(pMac, LOG2,FL("StaContext vhtCapable %d " + "vhtTxChannelWidthSet: %d vhtTxBFCapable: %d"), + pAddBssParams->staContext.vhtCapable, + pAddBssParams->staContext.vhtTxChannelWidthSet, + pAddBssParams->staContext.vhtTxBFCapable); +#endif + } + else + { + pAddBssParams->staContext.txChannelWidthSet = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + &enableTxBF20MHz))) { + if (VOS_FALSE == enableTxBF20MHz) { + pAddBssParams->staContext.vhtTxBFCapable = 0; + } + } + } + pAddBssParams->staContext.mimoPS = (tSirMacHTMIMOPowerSaveState)pAssocRsp->HTCaps.mimoPowerSave; + pAddBssParams->staContext.delBASupport = ( tANI_U8 )pAssocRsp->HTCaps.delayedBA; + pAddBssParams->staContext.maxAmsduSize = ( tANI_U8 )pAssocRsp->HTCaps.maximalAMSDUsize; + pAddBssParams->staContext.maxAmpduDensity = pAssocRsp->HTCaps.mpduDensity; + pAddBssParams->staContext.fDsssCckMode40Mhz = (tANI_U8)pAssocRsp->HTCaps.dsssCckMode40MHz; + /* + * We will check gShortGI20Mhz and gShortGI40Mhz from ini file. + * if they are set then we will use what ever Assoc response coming + * from AP supports. If these values are set as 0 in ini file then + * we will hardcode this values to 0. + */ + if (HAL_STATUS_SUCCESS(ccmCfgGetInt + (pMac, WNI_CFG_SHORT_GI_20MHZ, + &shortGi20MhzSupport))) + { + if (VOS_TRUE == shortGi20MhzSupport) + { + pAddBssParams->staContext.fShortGI20Mhz = + (tANI_U8)pAssocRsp->HTCaps.shortGI20MHz; + } + else + { + pAddBssParams->staContext.fShortGI20Mhz = VOS_FALSE; + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz" + "CFG,setting value to default"));) + pAddBssParams->staContext.fShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + if (HAL_STATUS_SUCCESS(ccmCfgGetInt + (pMac, WNI_CFG_SHORT_GI_40MHZ, + &shortGi40MhzSupport))) + { + if (VOS_TRUE == shortGi40MhzSupport) + { + pAddBssParams->staContext.fShortGI40Mhz = + (tANI_U8)pAssocRsp->HTCaps.shortGI40MHz; + } + else + { + pAddBssParams->staContext.fShortGI40Mhz = VOS_FALSE; + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz" + "CFG,setting value to default"));) + pAddBssParams->staContext.fShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STADEF; + } + +#ifdef WLAN_FEATURE_11AC + if (!pAddBssParams->staContext.vhtCapable) + // Use max ampd factor advertised in HTCAP for non-vht connection +#endif + { + pAddBssParams->staContext.maxAmpduSize = pAssocRsp->HTCaps.maxRxAMPDUFactor; + } + else if (pAddBssParams->staContext.maxAmpduSize < pAssocRsp->HTCaps.maxRxAMPDUFactor) + { + pAddBssParams->staContext.maxAmpduSize = pAssocRsp->HTCaps.maxRxAMPDUFactor; + } + if( pAddBssParams->staContext.vhtTxBFCapable && pMac->lim.disableLDPCWithTxbfAP ) + { + pAddBssParams->staContext.htLdpcCapable = 0; + pAddBssParams->staContext.vhtLdpcCapable = 0; + } + else + { + if (psessionEntry->txLdpcIniFeatureEnabled & 0x1) + pAddBssParams->staContext.htLdpcCapable = + (tANI_U8)pAssocRsp->HTCaps.advCodingCap; + else + pAddBssParams->staContext.htLdpcCapable = 0; + if (psessionEntry->txLdpcIniFeatureEnabled & 0x2) + pAddBssParams->staContext.vhtLdpcCapable = + (tANI_U8)pAssocRsp->VHTCaps.ldpcCodingCap; + else + pAddBssParams->staContext.vhtLdpcCapable = 0; + } + + if( pBeaconStruct->HTInfo.present ) + pAddBssParams->staContext.rifsMode = pAssocRsp->HTInfo.rifsMode; + + limLog(pMac, LOG2, FL("StaContext txChannelWidthSet: %d mimoPS: %d" + " delBASupport: %d maxAmsduSize: %d"), + pAddBssParams->staContext.txChannelWidthSet, + pAddBssParams->staContext.mimoPS, + pAddBssParams->staContext.delBASupport, + pAddBssParams->staContext.maxAmsduSize); + + limLog(pMac, LOG2, FL("maxAmpduDensity: %d fDsssCckMode40Mhz: %d " + "fShortGI20Mhz: %d "),pAddBssParams->staContext.maxAmpduDensity, + pAddBssParams->staContext.fDsssCckMode40Mhz, + pAddBssParams->staContext.fShortGI20Mhz); + + limLog(pMac, LOG2, FL("fShortGI40Mh: %d maxAmpduSize: %d " + "htLdpcCapable: %d vhtLdpcCapable: %d"), + pAddBssParams->staContext.fShortGI40Mhz, + pAddBssParams->staContext.maxAmpduSize, + pAddBssParams->staContext.htLdpcCapable, + pAddBssParams->staContext.vhtLdpcCapable); + } + pAddBssParams->staContext.smesessionId = psessionEntry->smeSessionId; + pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent; + pAddBssParams->staContext.wpa_rsn |= (pBeaconStruct->wpaPresent << 1); + /* For OSEN Connection AP does not advertise RSN or WPA IE + * so from the IEs we get from supplicant we get this info + * so for FW to transmit EAPOL message 4 we shall set + * wpa_rsn + */ + if ((!pAddBssParams->staContext.wpa_rsn) && (psessionEntry->isOSENConnection)) + pAddBssParams->staContext.wpa_rsn = 1; + vos_mem_copy(&pAddBssParams->staContext.capab_info, + &pAssocRsp->capabilityInfo, + sizeof(pAddBssParams->staContext.capab_info)); + vos_mem_copy(&pAddBssParams->staContext.ht_caps, + (tANI_U8 *)&pAssocRsp->HTCaps + sizeof(tANI_U8), + sizeof(pAddBssParams->staContext.ht_caps)); + + //If WMM IE or 802.11E IE is present then enable WMM + if ((psessionEntry->limWmeEnabled && pAssocRsp->wmeEdcaPresent) || + (psessionEntry->limQosEnabled && pAssocRsp->edcaPresent)) + pAddBssParams->staContext.wmmEnabled = 1; + else + pAddBssParams->staContext.wmmEnabled = 0; + + //Update the rates + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + limFillSupportedRatesInfo(pMac, pStaDs, &pStaDs->supportedRates,psessionEntry); + vos_mem_copy((tANI_U8*)&pAddBssParams->staContext.supportedRates, + (tANI_U8*)&pStaDs->supportedRates, + sizeof(tSirSupportedRates)); + } + else + PELOGE(limLog(pMac, LOGE, FL("could not Update the supported rates."));) + + } + + //Disable BA. It will be set as part of ADDBA negotiation. + for( i = 0; i < STACFG_MAX_TC; i++ ) + { + pAddBssParams->staContext.staTCParams[i].txUseBA = eBA_DISABLE; + pAddBssParams->staContext.staTCParams[i].rxUseBA = eBA_DISABLE; + pAddBssParams->staContext.staTCParams[i].txBApolicy = eBA_POLICY_IMMEDIATE; + pAddBssParams->staContext.staTCParams[i].rxBApolicy = eBA_POLICY_IMMEDIATE; + } + + pAddBssParams->staContext.encryptType = psessionEntry->encryptType; + +#if defined WLAN_FEATURE_VOWIFI + pAddBssParams->maxTxPower = psessionEntry->maxTxPower; + limLog(pMac, LOG2,FL("maxTxPower: %d"), + pAddBssParams->maxTxPower); +#endif + // FIXME_GEN4 - Any other value that can be used for initialization? + pAddBssParams->status = eHAL_STATUS_SUCCESS; + pAddBssParams->respReqd = true; + + pAddBssParams->halPersona = (tANI_U8)psessionEntry->pePersona; //update persona + + if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona) + { + pAddBssParams->staContext.p2pCapableSta = 1; + } + + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; + +#if defined WLAN_FEATURE_VOWIFI_11R + pAddBssParams->extSetStaKeyParamValid = 0; + limLog(pMac, LOG2,FL("extSetStaKeyParamValid: %d"), + pAddBssParams->extSetStaKeyParamValid); +#endif + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled) + { + pAddBssParams->rmfEnabled = 1; + pAddBssParams->staContext.rmfEnabled = 1; + } +#endif + + // Set a new state for MLME + if( eLIM_MLM_WT_ASSOC_RSP_STATE == psessionEntry->limMlmState ) + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE; + else + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + if (!pAddBssParams->staContext.htLdpcCapable) + pAddBssParams->staContext.ht_caps &= + ~(1 << SIR_MAC_HT_CAP_ADVCODING_S); + if (!pAddBssParams->staContext.vhtLdpcCapable) + pAddBssParams->staContext.vht_caps &= + ~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP); + + limLog(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d " + "p2pCapableSta: %d"),pAddBssParams->staContext.wmmEnabled, + pAddBssParams->staContext.encryptType, + pAddBssParams->staContext.p2pCapableSta); + + limLog(pMac, LOG2, FL("bSpectrumMgtEnabled: %d halPersona: %d setting " + "LimMlm state to %d"), pAddBssParams->bSpectrumMgtEnabled, + pAddBssParams->halPersona, psessionEntry->limMlmState); + if (psessionEntry->isNonRoamReassoc) { + pAddBssParams->nonRoamReassoc = 1; + } + //we need to defer the message until we get the response back from HAL. + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.type = WDA_ADD_BSS_REQ; + /** @ToDo : Update the Global counter to keeptrack of the PE <--> HAL messages*/ + msgQ.reserved = 0; + msgQ.bodyptr = pAddBssParams; + msgQ.bodyval = 0; + + limLog(pMac, LOG1, FL("SessionId:%d Sending WDA_ADD_BSS_REQ"), + psessionEntry->peSessionId); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if( eSIR_SUCCESS != retCode) + { + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pAddBssParams); + limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), + retCode ); + goto returnFailure; + + } + else + return retCode; + + returnFailure: + // Clean-up will be done by the caller... + return retCode; +} + + + + +tSirRetStatus limStaSendAddBssPreAssoc( tpAniSirGlobal pMac, tANI_U8 updateEntry, tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpAddBssParams pAddBssParams = NULL; + tANI_U32 retCode; + tANI_U8 i; + tSchBeaconStruct *pBeaconStruct; + tANI_U8 chanWidthSupp = 0; + tANI_U32 shortGi20MhzSupport; + tANI_U32 shortGi40MhzSupport; + tpSirBssDescription bssDescription = &psessionEntry->pLimJoinReq->bssDescription; + + pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) + { + limLog(pMac, LOGE, FL("Unable to allocate memory during ADD_BSS") ); + return eSIR_MEM_ALLOC_FAILED; + } + + + // Package SIR_HAL_ADD_BSS_REQ message parameters + pAddBssParams = vos_mem_malloc(sizeof(tAddBssParams)); + if (NULL == pAddBssParams) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during ADD_BSS" )); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + vos_mem_set((tANI_U8 *) pAddBssParams, sizeof( tAddBssParams ), 0); + + + limExtractApCapabilities( pMac, + (tANI_U8 *) bssDescription->ieFields, + limGetIElenFromBssDescription( bssDescription ), + pBeaconStruct ); + + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, psessionEntry); + vos_mem_copy(pAddBssParams->bssId, bssDescription->bssId, + sizeof(tSirMacAddr)); + + // Fill in tAddBssParams selfMacAddr + vos_mem_copy(pAddBssParams->selfMacAddr, + psessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); + limLog(pMac, LOG1, FL("sessionid: %d updateEntry = %d limsystemrole = %d"), + psessionEntry->smeSessionId, updateEntry, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + limLog(pMac, LOG1, FL("BSSID: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pAddBssParams->bssId)); + /* Incorrect BSS Type which caused UMA Descriptor to be overwritten on + * top of an already established Infra link. This lead to issues in + * concurrent data transfer. + */ + + pAddBssParams->bssType = psessionEntry->bssType;//eSIR_INFRASTRUCTURE_MODE; + pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA; + + pAddBssParams->beaconInterval = bssDescription->beaconInterval; + + pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod; + pAddBssParams->updateBss = updateEntry; + + + pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount; + pAddBssParams->cfParamSet.cfpPeriod = pBeaconStruct->cfParamSet.cfpPeriod; + pAddBssParams->cfParamSet.cfpMaxDuration = pBeaconStruct->cfParamSet.cfpMaxDuration; + pAddBssParams->cfParamSet.cfpDurRemaining = pBeaconStruct->cfParamSet.cfpDurRemaining; + + + pAddBssParams->rateSet.numRates = pBeaconStruct->supportedRates.numRates; + vos_mem_copy(pAddBssParams->rateSet.rate, + pBeaconStruct->supportedRates.rate, pBeaconStruct->supportedRates.numRates); + + pAddBssParams->nwType = bssDescription->nwType; + + pAddBssParams->shortSlotTimeSupported = (tANI_U8)pBeaconStruct->capabilityInfo.shortSlotTime; + pAddBssParams->llaCoexist = (tANI_U8) psessionEntry->beaconParams.llaCoexist; + pAddBssParams->llbCoexist = (tANI_U8) psessionEntry->beaconParams.llbCoexist; + pAddBssParams->llgCoexist = (tANI_U8) psessionEntry->beaconParams.llgCoexist; + pAddBssParams->ht20Coexist = (tANI_U8) psessionEntry->beaconParams.ht20Coexist; + + limLog(pMac, LOG2, FL(" BSS Type %d Beacon Interval: %d dtimPeriod: %d " + "cfpCount: %d"),pAddBssParams->bssType, pAddBssParams->beaconInterval, + pAddBssParams->dtimPeriod, pAddBssParams->cfParamSet.cfpCount); + + limLog(pMac, LOG2, FL(" cfpPeriod: %d cfpMaxDuration: %d cfpDurRemaining:" + " %d numRates: %d "),pAddBssParams->cfParamSet.cfpPeriod, + pAddBssParams->cfParamSet.cfpMaxDuration, + pAddBssParams->cfParamSet.cfpDurRemaining, + pAddBssParams->rateSet.numRates); + + limLog(pMac, LOG2, FL("nwType:%d shortSlotTimeSupported: %d" + "llaCoexist: %d llbCoexist: %d llgCoexist: %d ht20Coexist: %d"), + pAddBssParams->nwType, pAddBssParams->shortSlotTimeSupported, + pAddBssParams->llaCoexist, pAddBssParams->llbCoexist, + pAddBssParams->llgCoexist, pAddBssParams->ht20Coexist); + // Use the advertised capabilities from the received beacon/PR + if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) && ( pBeaconStruct->HTCaps.present )) + { + pAddBssParams->htCapable = pBeaconStruct->HTCaps.present; + limLog(pMac, LOG2, FL("htCapable: %d"),pAddBssParams->htCapable); + if ( pBeaconStruct->HTInfo.present ) + { + pAddBssParams->htOperMode = (tSirMacHTOperatingMode)pBeaconStruct->HTInfo.opMode; + pAddBssParams->dualCTSProtection = ( tANI_U8 ) pBeaconStruct->HTInfo.dualCTSProtection; + + chanWidthSupp = limGetHTCapability( pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry); + if( (pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp) ) + { + pAddBssParams->txChannelWidthSet = ( tANI_U8 ) pBeaconStruct->HTInfo.recommendedTxWidthSet; + pAddBssParams->currentExtChannel = pBeaconStruct->HTInfo.secondaryChannelOffset; + } + else + { + pAddBssParams->txChannelWidthSet = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + pAddBssParams->currentExtChannel = PHY_SINGLE_CHANNEL_CENTERED; + } + pAddBssParams->llnNonGFCoexist = (tANI_U8)pBeaconStruct->HTInfo.nonGFDevicesPresent; + pAddBssParams->fLsigTXOPProtectionFullSupport = (tANI_U8)pBeaconStruct->HTInfo.lsigTXOPProtectionFullSupport; + pAddBssParams->fRIFSMode = pBeaconStruct->HTInfo.rifsMode; + + limLog(pMac, LOG2, FL("htOperMode: %d dualCTSProtection: %d " + "txChannelWidthSet: %d currentExtChannel: %d "), + pAddBssParams->htOperMode, pAddBssParams->dualCTSProtection, + pAddBssParams->txChannelWidthSet,pAddBssParams->currentExtChannel); + + limLog(pMac, LOG2, FL("llnNonGFCoexist: %d " + "fLsigTXOPProtectionFullSupport: %d fRIFSMode %d"), + pAddBssParams->llnNonGFCoexist, + pAddBssParams->fLsigTXOPProtectionFullSupport, + pAddBssParams->fRIFSMode); + } + } + + pAddBssParams->currentOperChannel = bssDescription->channelId; + limLog(pMac, LOG2, FL("currentOperChannel %d"), + pAddBssParams->currentOperChannel); +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) + { + pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present; + /* + * in limExtractApCapability function intersection of FW advertised + * channel width and AP advertised channel width has been taken into + * account for calculating psessionEntry->apChanWidth + */ + pAddBssParams->vhtTxChannelWidthSet = psessionEntry->apChanWidth; + pAddBssParams->currentExtChannel = limGet11ACPhyCBState (pMac, + pAddBssParams->currentOperChannel, + pAddBssParams->currentExtChannel, + psessionEntry->apCenterChan, + psessionEntry); + pAddBssParams->staContext.maxAmpduSize = + SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( + pAddBssParams->staContext.vht_caps); + } + else + { + pAddBssParams->vhtCapable = 0; + } + limLog(pMac, LOG2, FL("vhtCapable %d vhtTxChannelWidthSet %d " + "currentExtChannel %d"),pAddBssParams->vhtCapable, + pAddBssParams->vhtTxChannelWidthSet, + pAddBssParams->currentExtChannel); +#endif + + // Populate the STA-related parameters here + // Note that the STA here refers to the AP + { + pAddBssParams->staContext.staType = STA_ENTRY_OTHER; // Identifying AP as an STA + + vos_mem_copy(pAddBssParams->staContext.bssId, + bssDescription->bssId, + sizeof(tSirMacAddr)); + pAddBssParams->staContext.listenInterval = bssDescription->beaconInterval; + + pAddBssParams->staContext.assocId = 0; // Is SMAC OK with this? + pAddBssParams->staContext.uAPSD = 0; + pAddBssParams->staContext.maxSPLen = 0; + pAddBssParams->staContext.shortPreambleSupported = (tANI_U8)pBeaconStruct->capabilityInfo.shortPreamble; + pAddBssParams->staContext.updateSta = updateEntry; + + limLog(pMac, LOG2, FL("StaContext: "MAC_ADDRESS_STR + " shortPreambleSupported: %d"), + MAC_ADDR_ARRAY(pAddBssParams->staContext.staMac), + pAddBssParams->staContext.shortPreambleSupported); + + pAddBssParams->dot11_mode = psessionEntry->dot11mode; + limLog(pMac, LOG2, FL("dot11_mode:%d"), pAddBssParams->dot11_mode); + + if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) && ( pBeaconStruct->HTCaps.present )) + { + pAddBssParams->staContext.us32MaxAmpduDuration = 0; + pAddBssParams->staContext.htCapable = 1; + pAddBssParams->staContext.greenFieldCapable = ( tANI_U8 ) pBeaconStruct->HTCaps.greenField; + pAddBssParams->staContext.lsigTxopProtection = ( tANI_U8 ) pBeaconStruct->HTCaps.lsigTXOPProtection; + limLog(pMac, LOG2, FL("StaContext htCapable: %d " + "greenFieldCapable: %d lsigTxopProtection: %d"), + pAddBssParams->staContext.htCapable, + pAddBssParams->staContext.greenFieldCapable, + pAddBssParams->staContext.lsigTxopProtection); +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) + { + pAddBssParams->staContext.vhtCapable = 1; + if ((pBeaconStruct->VHTCaps.suBeamFormerCap || + pBeaconStruct->VHTCaps.muBeamformerCap) && + psessionEntry->txBFIniFeatureEnabled ) + { + pAddBssParams->staContext.vhtTxBFCapable = 1; + } + + if ( pBeaconStruct->VHTCaps.muBeamformerCap && + psessionEntry->txMuBformee ) + { + pAddBssParams->staContext.vhtTxMUBformeeCapable = 1; + } + } +#endif + if( (pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp) ) + { + pAddBssParams->staContext.txChannelWidthSet = ( tANI_U8 )pBeaconStruct->HTInfo.recommendedTxWidthSet; +#ifdef WLAN_FEATURE_11AC + if (pAddBssParams->staContext.vhtCapable) + { + /* + * in limExtractApCapability function intersection of FW + * advertised channel width and AP advertised channel width + * has been taken into account for calculating + * psessionEntry->apChanWidth + */ + pAddBssParams->staContext.vhtTxChannelWidthSet = + psessionEntry->apChanWidth; + } + limLog(pMac, LOG2,FL("StaContext vhtCapable %d " + "vhtTxChannelWidthSet: %d vhtTxBFCapable: %d"), + pAddBssParams->staContext.vhtCapable, + pAddBssParams->staContext.vhtTxChannelWidthSet, + pAddBssParams->staContext.vhtTxBFCapable); +#endif + } + else + { + pAddBssParams->staContext.txChannelWidthSet = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + } + pAddBssParams->staContext.mimoPS = (tSirMacHTMIMOPowerSaveState)pBeaconStruct->HTCaps.mimoPowerSave; + pAddBssParams->staContext.delBASupport = ( tANI_U8 ) pBeaconStruct->HTCaps.delayedBA; + pAddBssParams->staContext.maxAmsduSize = ( tANI_U8 ) pBeaconStruct->HTCaps.maximalAMSDUsize; + pAddBssParams->staContext.maxAmpduDensity = pBeaconStruct->HTCaps.mpduDensity; + pAddBssParams->staContext.fDsssCckMode40Mhz = (tANI_U8)pBeaconStruct->HTCaps.dsssCckMode40MHz; + /* + * We will check gShortGI20Mhz and gShortGI40Mhz from ini file. + * if they are set then we will use what ever Beacon coming from AP + * supports. If these values are set as 0 in ini file then + * we will hardcode this values to 0. + */ + if (HAL_STATUS_SUCCESS(ccmCfgGetInt + (pMac, WNI_CFG_SHORT_GI_20MHZ, + &shortGi20MhzSupport))) + { + if (VOS_TRUE == shortGi20MhzSupport) + { + pAddBssParams->staContext.fShortGI20Mhz = + (tANI_U8)pBeaconStruct->HTCaps.shortGI20MHz; + } + else + { + pAddBssParams->staContext.fShortGI20Mhz = VOS_FALSE; + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz" + "CFG,setting value to default"));) + pAddBssParams->staContext.fShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + if (HAL_STATUS_SUCCESS(ccmCfgGetInt + (pMac, WNI_CFG_SHORT_GI_40MHZ, + &shortGi40MhzSupport))) + { + if (VOS_TRUE == shortGi40MhzSupport) + { + pAddBssParams->staContext.fShortGI40Mhz = + (tANI_U8)pBeaconStruct->HTCaps.shortGI40MHz; + } + else + { + pAddBssParams->staContext.fShortGI40Mhz = VOS_FALSE; + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz" + "CFG,setting value to default"));) + pAddBssParams->staContext.fShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STADEF; + } + + pAddBssParams->staContext.maxAmpduSize= pBeaconStruct->HTCaps.maxRxAMPDUFactor; + if( pAddBssParams->staContext.vhtTxBFCapable && pMac->lim.disableLDPCWithTxbfAP ) + { + pAddBssParams->staContext.htLdpcCapable = 0; + pAddBssParams->staContext.vhtLdpcCapable = 0; + } + else + { + if (psessionEntry->txLdpcIniFeatureEnabled & 0x1) + pAddBssParams->staContext.htLdpcCapable = + (tANI_U8)pBeaconStruct->HTCaps.advCodingCap; + else + pAddBssParams->staContext.htLdpcCapable = 0; + if (psessionEntry->txLdpcIniFeatureEnabled & 0x2) + pAddBssParams->staContext.vhtLdpcCapable = + (tANI_U8)pBeaconStruct->VHTCaps.ldpcCodingCap; + else + pAddBssParams->staContext.vhtLdpcCapable = 0; + } + + if( pBeaconStruct->HTInfo.present ) + pAddBssParams->staContext.rifsMode = pBeaconStruct->HTInfo.rifsMode; + limLog(pMac, LOG2, FL("StaContext txChannelWidthSet: %d mimoPS: %d" + " delBASupport: %d maxAmsduSize: %d"), + pAddBssParams->staContext.txChannelWidthSet, + pAddBssParams->staContext.mimoPS, + pAddBssParams->staContext.delBASupport, + pAddBssParams->staContext.maxAmsduSize); + + limLog(pMac, LOG2, FL("maxAmpduDensity: %d fDsssCckMode40Mhz: %d " + "fShortGI20Mhz: %d "),pAddBssParams->staContext.maxAmpduDensity, + pAddBssParams->staContext.fDsssCckMode40Mhz, + pAddBssParams->staContext.fShortGI20Mhz); + + limLog(pMac, LOG2, FL("fShortGI40Mh: %d maxAmpduSize: %d " + "htLdpcCapable: %d vhtLdpcCapable: %d"), + pAddBssParams->staContext.fShortGI40Mhz, + pAddBssParams->staContext.maxAmpduSize, + pAddBssParams->staContext.htLdpcCapable, + pAddBssParams->staContext.vhtLdpcCapable); + } + + //If WMM IE or 802.11E IE is not present and AP is HT AP then enable WMM + if ((psessionEntry->limWmeEnabled && (pBeaconStruct->wmeEdcaPresent || pAddBssParams->staContext.htCapable)) || + (psessionEntry->limQosEnabled && (pBeaconStruct->edcaPresent || pAddBssParams->staContext.htCapable))) + pAddBssParams->staContext.wmmEnabled = 1; + else + pAddBssParams->staContext.wmmEnabled = 0; + + //Update the rates +#ifdef WLAN_FEATURE_11AC + limPopulatePeerRateSet(pMac, &pAddBssParams->staContext.supportedRates, + pBeaconStruct->HTCaps.supportedMCSSet, false,psessionEntry, + &pBeaconStruct->VHTCaps); +#else + limPopulatePeerRateSet(pMac, &pAddBssParams->staContext.supportedRates, + pBeaconStruct->HTCaps.supportedMCSSet, false,psessionEntry); +#endif + limFillSupportedRatesInfo(pMac, NULL, &pAddBssParams->staContext.supportedRates,psessionEntry); + + } + + + //Disable BA. It will be set as part of ADDBA negotiation. + for( i = 0; i < STACFG_MAX_TC; i++ ) + { + pAddBssParams->staContext.staTCParams[i].txUseBA = eBA_DISABLE; + pAddBssParams->staContext.staTCParams[i].rxUseBA = eBA_DISABLE; + pAddBssParams->staContext.staTCParams[i].txBApolicy = eBA_POLICY_IMMEDIATE; + pAddBssParams->staContext.staTCParams[i].rxBApolicy = eBA_POLICY_IMMEDIATE; + } + + pAddBssParams->staContext.encryptType = psessionEntry->encryptType; + +#if defined WLAN_FEATURE_VOWIFI + pAddBssParams->maxTxPower = psessionEntry->maxTxPower; + limLog(pMac, LOG2,FL("maxTxPower: %d"), + pAddBssParams->maxTxPower); +#endif + + pAddBssParams->status = eHAL_STATUS_SUCCESS; + pAddBssParams->respReqd = true; + + pAddBssParams->staContext.smesessionId = psessionEntry->smeSessionId; + pAddBssParams->staContext.sessionId = psessionEntry->peSessionId; + pAddBssParams->sessionId = psessionEntry->peSessionId; + + pAddBssParams->halPersona = (tANI_U8)psessionEntry->pePersona; //update persona + + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; + +#if defined WLAN_FEATURE_VOWIFI_11R + pAddBssParams->extSetStaKeyParamValid = 0; + limLog(pMac, LOG2,FL("extSetStaKeyParamValid: %d"), + pAddBssParams->extSetStaKeyParamValid); +#endif + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled) + { + pAddBssParams->rmfEnabled = 1; + pAddBssParams->staContext.rmfEnabled = 1; + } +#endif + + // Set a new state for MLME + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; + + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + limLog(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d " + "p2pCapableSta: %d"),pAddBssParams->staContext.wmmEnabled, + pAddBssParams->staContext.encryptType, + pAddBssParams->staContext.p2pCapableSta); + + limLog(pMac, LOG2, FL("bSpectrumMgtEnabled: %d halPersona: %d setting " + "LimMlm state to %d"), pAddBssParams->bSpectrumMgtEnabled, + pAddBssParams->halPersona, psessionEntry->limMlmState); + + //we need to defer the message until we get the response back from HAL. + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.type = WDA_ADD_BSS_REQ; + /** @ToDo : Update the Global counter to keeptrack of the PE <--> HAL messages*/ + msgQ.reserved = 0; + msgQ.bodyptr = pAddBssParams; + msgQ.bodyval = 0; + + limLog(pMac, LOG1, FL("SessionId:%d Sending WDA_ADD_BSS_REQ"), + psessionEntry->peSessionId); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if( eSIR_SUCCESS != retCode) + { + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pAddBssParams); + limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), + retCode ); + goto returnFailure; + + } + else + { + vos_mem_free(pBeaconStruct); + return retCode; + } + + returnFailure: + // Clean-up will be done by the caller... + vos_mem_free(pBeaconStruct); + return retCode; +} + + + + + + +/** ------------------------------------------------------------- +\fn limPrepareAndSendDelStaCnf +\brief deletes DPH entry + changes the MLM mode for station. + calls limSendDelStaCnf +\param tpAniSirGlobal pMac +\param tpDphHashNode pStaDs +\return none + -------------------------------------------------------------*/ + + +void +limPrepareAndSendDelStaCnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tSirResultCodes statusCode,tpPESession psessionEntry) +{ + tANI_U16 staDsAssocId = 0; + tSirMacAddr staDsAddr; + tLimMlmStaContext mlmStaContext; + + if(pStaDs == NULL) + { + PELOGW(limLog(pMac, LOGW, FL("pStaDs is NULL"));) + return; + } + staDsAssocId = pStaDs->assocId; + vos_mem_copy((tANI_U8 *)staDsAddr, + pStaDs->staAddr, + sizeof(tSirMacAddr)); + + mlmStaContext = pStaDs->mlmStaContext; + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry); + } + limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, psessionEntry); + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, psessionEntry->limMlmState)); + } + limSendDelStaCnf(pMac, staDsAddr, staDsAssocId, mlmStaContext, statusCode,psessionEntry); +} + +/** ------------------------------------------------------------- +\fn limGetStaRateMode +\brief Gets the Station Rate Mode. +\param tANI_U8 dot11Mode +\return none + -------------------------------------------------------------*/ +tStaRateMode limGetStaRateMode(tANI_U8 dot11Mode) +{ + switch(dot11Mode) + { + case WNI_CFG_DOT11_MODE_11A: + return eSTA_11a; + case WNI_CFG_DOT11_MODE_11B: + return eSTA_11b; + case WNI_CFG_DOT11_MODE_11G: + return eSTA_11bg; + case WNI_CFG_DOT11_MODE_11N: + return eSTA_11n; +#ifdef WLAN_FEATURE_11AC + case WNI_CFG_DOT11_MODE_11AC: + return eSTA_11ac; +#endif + case WNI_CFG_DOT11_MODE_ALL: + default: + return eSTA_11n; + + } +} + +/** ------------------------------------------------------------- +\fn limInitPreAuthTimerTable +\brief Initialize the Pre Auth Tanle and creates the timer for + each node for the timeout value got from cfg. +\param tpAniSirGlobal pMac +\param tpLimPreAuthTable pPreAuthTimerTable +\return none + -------------------------------------------------------------*/ +void limInitPreAuthTimerTable(tpAniSirGlobal pMac, tpLimPreAuthTable pPreAuthTimerTable) +{ + tANI_U32 cfgValue; + tANI_U32 authNodeIdx; + tLimPreAuthNode **pAuthNode = pPreAuthTimerTable->pTable; + + // Get AUTH_RSP Timers value + + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_RSP_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /* + ** Could not get AUTH_RSP timeout value + ** from CFG. Log error. + **/ + limLog(pMac, LOGP, + FL("could not retrieve AUTH_RSP timeout value")); + return; + } + + cfgValue = SYS_MS_TO_TICKS(cfgValue); + for(authNodeIdx=0; authNodeIdxnumEntry; authNodeIdx++) + { + if (tx_timer_create(&(pAuthNode[authNodeIdx]->timer), + "AUTH RESPONSE TIMEOUT", + limAuthResponseTimerHandler, + authNodeIdx, + cfgValue, + 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + // Cannot create timer. Log error. + limLog(pMac, LOGP, FL("Cannot create Auth Rsp timer of Index :%d."), authNodeIdx); + return; + } + pAuthNode[authNodeIdx]->authNodeIdx = (tANI_U8)authNodeIdx; + pAuthNode[authNodeIdx]->fFree = 1; + } +} + +/** ------------------------------------------------------------- +\fn limAcquireFreePreAuthNode +\brief Retrives a free Pre Auth node from Pre Auth Table. +\param tpAniSirGlobal pMac +\param tpLimPreAuthTable pPreAuthTimerTable +\return none + -------------------------------------------------------------*/ +tLimPreAuthNode * limAcquireFreePreAuthNode(tpAniSirGlobal pMac, tpLimPreAuthTable pPreAuthTimerTable) +{ + tANI_U32 i; + tLimPreAuthNode **pTempNode = pPreAuthTimerTable->pTable; + for (i=0; i < pPreAuthTimerTable->numEntry; i++) { + if (pTempNode[i]->fFree == 1) { + pTempNode[i]->fFree = 0; + return pTempNode[i]; + } + } + + return NULL; +} + +/** ------------------------------------------------------------- +\fn limGetPreAuthNodeFromIndex +\brief Depending on the Index this retrives the pre auth node. +\param tpAniSirGlobal pMac +\param tpLimPreAuthTable pAuthTable +\param tANI_U32 authNodeIdx +\return none + -------------------------------------------------------------*/ +tLimPreAuthNode * limGetPreAuthNodeFromIndex(tpAniSirGlobal pMac, + tpLimPreAuthTable pAuthTable, tANI_U32 authNodeIdx) +{ + if ((authNodeIdx >= pAuthTable->numEntry) || (pAuthTable->pTable == NULL)) + { + limLog(pMac, LOGE, FL("Invalid Auth Timer Index : %d NumEntry : %d"), + authNodeIdx, pAuthTable->numEntry); + return NULL; + } + + return pAuthTable->pTable[authNodeIdx]; +} + +/* Util API to check if the channels supported by STA is within range */ +tSirRetStatus limIsDot11hSupportedChannelsValid(tpAniSirGlobal pMac, tSirAssocReq *assoc) +{ + /* + * Allow all the stations to join with us. + * 802.11h-2003 11.6.1 => An AP may use the supported channels list for associated STAs + * as an input into an algorithm used to select a new channel for the BSS. + * The specification of the algorithm is beyond the scope of this amendment. + */ + + return (eSIR_SUCCESS); +} + +/* Util API to check if the txpower supported by STA is within range */ +tSirRetStatus limIsDot11hPowerCapabilitiesInRange(tpAniSirGlobal pMac, tSirAssocReq *assoc,tpPESession psessionEntry) +{ + tPowerdBm localMaxTxPower; + tANI_U32 localPwrConstraint; + + localMaxTxPower = cfgGetRegulatoryMaxTransmitPower(pMac, psessionEntry->currentOperChannel); + + if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { + limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" )); + return eSIR_FAILURE; + } + localMaxTxPower -= (tPowerdBm)localPwrConstraint; + + /** + * The min Tx Power of the associating station should not be greater than (regulatory + * max tx power - local power constraint configured on AP). + */ + if(assoc->powerCapability.minTxPower > localMaxTxPower) + { + limLog(pMac, LOGW, FL("minTxPower (STA) = %d, localMaxTxPower (AP) = %d"), + assoc->powerCapability.minTxPower, localMaxTxPower); + return (eSIR_FAILURE); + } + + return (eSIR_SUCCESS); +} + +/** ------------------------------------------------------------- +\fn limFillRxHighestSupportedRate +\brief Fills in the Rx Highest Supported Data Rate field from +\ the 'supported MCS set' field in HT capability element. +\param tpAniSirGlobal pMac +\param tpSirSupportedRates pRates +\param tANI_U8* pSupportedMCSSet +\return none + -------------------------------------------------------------*/ +void limFillRxHighestSupportedRate(tpAniSirGlobal pMac, tANI_U16 *rxHighestRate, tANI_U8* pSupportedMCSSet) +{ + tSirMacRxHighestSupportRate *pRxHighestRate; + tANI_U8 *pBuf; + tANI_U16 rate=0; + + pBuf = pSupportedMCSSet + MCS_RX_HIGHEST_SUPPORTED_RATE_BYTE_OFFSET; + rate = limGetU16(pBuf); + + pRxHighestRate = (tSirMacRxHighestSupportRate *) &rate; + *rxHighestRate = pRxHighestRate->rate; + + return; +} + +#ifdef WLAN_FEATURE_11W +/** ------------------------------------------------------------- +\fn limSendSmeUnprotectedMgmtFrameInd +\brief Forwards the unprotected management frame to SME. +\param tpAniSirGlobal pMac +\param frameType - 802.11 frame type +\param frame - frame buffer +\param sessionId - id for the current session +\param psessionEntry - PE session context +\return none + -------------------------------------------------------------*/ +void limSendSmeUnprotectedMgmtFrameInd( + tpAniSirGlobal pMac, tANI_U8 frameType, + tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, + tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirSmeUnprotMgmtFrameInd * pSirSmeMgmtFrame = NULL; + tANI_U16 length; + + length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen; + + pSirSmeMgmtFrame = vos_mem_malloc(length); + if (NULL == pSirSmeMgmtFrame) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for tSirSmeUnprotectedMgmtFrameInd")); + return; + } + vos_mem_set((void*)pSirSmeMgmtFrame, length, 0); + + pSirSmeMgmtFrame->sessionId = sessionId; + pSirSmeMgmtFrame->frameType = frameType; + + vos_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); + pSirSmeMgmtFrame->frameLen = frameLen; + + mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND; + mmhMsg.bodyptr = pSirSmeMgmtFrame; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** ------------------------------------------------------------- +\fn limSendSmeTsmIEInd +\brief Forwards the TSM IE information to SME. +\param tpAniSirGlobal pMac +\param psessionEntry - PE session context +\param tid - traffic id +\param state - tsm state (enabled/disabled) +\param measurementInterval - measurement interval +\return none + -------------------------------------------------------------*/ +void limSendSmeTsmIEInd(tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U8 tid, tANI_U8 state, tANI_U16 measInterval) +{ + tSirMsgQ mmhMsg; + tpSirSmeTsmIEInd pSirSmeTsmIeInd = NULL; + + if (!pMac || !psessionEntry) + { + return; + } + pSirSmeTsmIeInd = vos_mem_malloc(sizeof(tSirSmeTsmIEInd)); + if (NULL == pSirSmeTsmIeInd) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for tSirSmeTsmIEInd")); + return; + } + vos_mem_set((void*)pSirSmeTsmIeInd, sizeof(tSirSmeTsmIEInd), 0); + + pSirSmeTsmIeInd->sessionId = psessionEntry->smeSessionId; + pSirSmeTsmIeInd->tsmIe.tsid = tid; + pSirSmeTsmIeInd->tsmIe.state= state; + pSirSmeTsmIeInd->tsmIe.msmt_interval= measInterval; + + mmhMsg.type = eWNI_SME_TSM_IE_IND; + mmhMsg.bodyptr = pSirSmeTsmIeInd; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.h new file mode 100644 index 000000000000..2d5b2709fbfc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limAssocUtils.h contains the utility definitions + * LIM uses while processing Re/Association messages. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * 05/26/10 js WPA handling in (Re)Assoc frames + * + */ +#ifndef __LIM_ASSOC_UTILS_H +#define __LIM_ASSOC_UTILS_H + +#include "sirApi.h" +#include "sirDebug.h" +#include "cfgApi.h" + +#include "limTypes.h" + + +tANI_U8 limCmpSSid(tpAniSirGlobal, tSirMacSSid *,tpPESession); +tANI_U8 limCompareCapabilities(tpAniSirGlobal, + tSirAssocReq *, + tSirMacCapabilityInfo *,tpPESession); +tANI_U8 limCheckRxBasicRates(tpAniSirGlobal, tSirMacRateSet,tpPESession); +tANI_U8 limCheckRxRSNIeMatch(tpAniSirGlobal, tDot11fIERSN, tpPESession, tANI_U8, tANI_BOOLEAN *); +tANI_U8 limCheckRxWPAIeMatch(tpAniSirGlobal, tDot11fIEWPA, tpPESession, tANI_U8); +tANI_U8 limCheckMCSSet(tpAniSirGlobal pMac, tANI_U8* supportedMCSSet); +void limPostDummyToTmRing(tpAniSirGlobal, tpDphHashNode); +void limPostPacketToTdRing(tpAniSirGlobal, + tpDphHashNode, + tANI_U8); +tSirRetStatus limCleanupRxPath(tpAniSirGlobal, tpDphHashNode,tpPESession); +void limRejectAssociation(tpAniSirGlobal , tSirMacAddr, tANI_U8, + tANI_U8 , tAniAuthType, + tANI_U16, tANI_U8, tSirResultCodes, tpPESession); + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus limPopulatePeerRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps); +#else +tSirRetStatus limPopulatePeerRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry); +#endif + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus limPopulateOwnRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps); + +#else +tSirRetStatus limPopulateOwnRateSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tANI_U8* pSupportedMCSSet, + tANI_U8 basicOnly, + tpPESession psessionEntry); +#endif + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +limPopulateMatchingRateSet(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tSirMacRateSet *pOperRateSet, + tSirMacRateSet *pExtRateSet, + tANI_U8* pSupportedMCSSet, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps); +#else +tSirRetStatus limPopulateMatchingRateSet(tpAniSirGlobal, + tpDphHashNode, + tSirMacRateSet *, + tSirMacRateSet *, + tANI_U8* pSupportedMCSSet, + tpPESession); + + +#endif + +#ifdef WLAN_FEATURE_11AC +#define MCSMAPMASK1x1 0x3 +#define MCSMAPMASK2x2 0xC +#endif + +tSirRetStatus limAddSta(tpAniSirGlobal, tpDphHashNode, tANI_U8, tpPESession); +tSirRetStatus limDelBss(tpAniSirGlobal, tpDphHashNode, tANI_U16, tpPESession); +tSirRetStatus limDelSta(tpAniSirGlobal, tpDphHashNode, tANI_BOOLEAN, tpPESession); +#ifdef WLAN_FEATURE_VOWIFI_11R +tSirRetStatus limAddFTStaSelf(tpAniSirGlobal pMac, tANI_U16 assocId, + tpPESession psessionEntry); +#endif /* WLAN_FEATURE_VOWIFI_11R */ +tSirRetStatus limAddStaSelf(tpAniSirGlobal, tANI_U16, tANI_U8, tpPESession); +tStaRateMode limGetStaRateMode(tANI_U8 dot11Mode); + + +void limTeardownInfraBss(tpAniSirGlobal,tpPESession); +void limRestorePreReassocState(tpAniSirGlobal, + tSirResultCodes, + tANI_U16,tpPESession); +void limPostReassocFailure(tpAniSirGlobal, + tSirResultCodes, + tANI_U16,tpPESession); +eAniBoolean limIsReassocInProgress(tpAniSirGlobal,tpPESession); +void +limSendDelStaCnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, + tANI_U16 staDsAssocId, tLimMlmStaContext mlmStaContext, tSirResultCodes statusCode,tpPESession psessionEntry); + +void limHandleCnfWaitTimeout(tpAniSirGlobal pMac, tANI_U16 staId); +void limDeleteDphHashEntry(tpAniSirGlobal, tSirMacAddr, tANI_U16,tpPESession); +void limCheckAndAnnounceJoinSuccess(tpAniSirGlobal, + tSirProbeRespBeacon *, + tpSirMacMgmtHdr,tpPESession); +void limUpdateReAssocGlobals(tpAniSirGlobal pMac, + tpSirAssocRsp pAssocRsp,tpPESession psessionEntry); + +void limUpdateAssocStaDatas(tpAniSirGlobal pMac, + tpDphHashNode pStaDs,tpSirAssocRsp pAssocRsp,tpPESession psessionEntry); +void +limFillSupportedRatesInfo( + tpAniSirGlobal pMac, + tpDphHashNode pSta, + tpSirSupportedRates pRates, + tpPESession psessionEntry); + +tSirRetStatus limStaSendAddBss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, + tpSchBeaconStruct pBeaconStruct, tpSirBssDescription bssDescription, tANI_U8 updateEntry, tpPESession psessionEntry); +tSirRetStatus limStaSendAddBssPreAssoc( tpAniSirGlobal pMac, tANI_U8 updateEntry, tpPESession psessionEntry); + +void limPrepareAndSendDelStaCnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tSirResultCodes statusCode,tpPESession); +tSirRetStatus limExtractApCapabilities(tpAniSirGlobal pMac, tANI_U8 * pIE, tANI_U16 ieLen, tpSirProbeRespBeacon beaconStruct); +void limInitPreAuthTimerTable(tpAniSirGlobal pMac, tpLimPreAuthTable pPreAuthTimerTable); +tpLimPreAuthNode limAcquireFreePreAuthNode(tpAniSirGlobal pMac, tpLimPreAuthTable pPreAuthTimerTable); +tpLimPreAuthNode limGetPreAuthNodeFromIndex(tpAniSirGlobal pMac, tpLimPreAuthTable pAuthTable, tANI_U32 authNodeIdx); + +/* Util API to check if the channels supported by STA is within range */ +tSirRetStatus limIsDot11hSupportedChannelsValid(tpAniSirGlobal pMac, tSirAssocReq *assoc); + +/* Util API to check if the txpower supported by STA is within range */ +tSirRetStatus limIsDot11hPowerCapabilitiesInRange(tpAniSirGlobal pMac, tSirAssocReq *assoc,tpPESession); + +/* API to re-add the same BSS during re-association */ +void limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry); + +/* API to fill in RX Highest Supported data Rate */ +void limFillRxHighestSupportedRate(tpAniSirGlobal pMac, tANI_U16 *rxHighestRate, tANI_U8* pSupportedMCSSet); +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +void limSendRetryReassocReqFrame(tpAniSirGlobal pMac, tLimMlmReassocReq *pMlmReassocReq, tpPESession psessionEntry); +#endif +#ifdef WLAN_FEATURE_11W +void limSendSmeUnprotectedMgmtFrameInd(tpAniSirGlobal pMac, tANI_U8 frameType, + tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, tpPESession psessionEntry); +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +void limSendSmeTsmIEInd( tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U8 tid, tANI_U8 state, tANI_U16 measInterval); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +#endif /* __LIM_ASSOC_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.c new file mode 100644 index 000000000000..9df867428c96 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file limDebug.c + + \brief implementation for log Debug related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +#include "limDebug.h" + +void limLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) +{ +#ifdef WLAN_DEBUG + // Verify against current log level + if ( loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_LIM_MODULE_ID )] ) + return; + else + { + va_list marker; + + va_start( marker, pString ); /* Initialize variable arguments. */ + + logDebug(pMac, SIR_LIM_MODULE_ID, loglevel, pString, marker); + + va_end( marker ); /* Reset variable arguments. */ + } +#endif +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.h new file mode 100644 index 000000000000..371ff401ce04 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limDebug.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limDebug.h contains log function called by LIM module. + * + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __LIM_DEBUG_H__ +#define __LIM_DEBUG_H__ + +#include "utilsApi.h" +#include "sirDebug.h" + +#if !defined(__printf) +#define __printf(a,b) +#endif + +void __printf(3,4) limLog(tpAniSirGlobal pMac, tANI_U32 loglevel, + const char *pString, ...); + +/* define this to show more message in the LIM during TDLS development */ +#define LIM_DEBUG_TDLS + +#ifdef LIM_DEBUG_TDLS +#define LIM_LOG_TDLS(x0) x0 +#else +#define LIM_LOG_TDLS(x0) +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c new file mode 100644 index 000000000000..9e5df46402eb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c @@ -0,0 +1,2027 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef WLAN_FEATURE_VOWIFI_11R +/**========================================================================= + + \brief implementation for PE 11r VoWiFi FT Protocol + + ========================================================================*/ + +/* $Header$ */ + + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wmmApsd.h" + +extern void limSendSetStaKeyReq( tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + tANI_U16 staIdx, + tANI_U8 defWEPIdx, + tpPESession sessionEntry, + tANI_BOOLEAN sendRsp); + +/*-------------------------------------------------------------------------- + Initialize the FT variables. + ------------------------------------------------------------------------*/ +void limFTOpen(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (psessionEntry) + vos_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0); +} + +/*-------------------------------------------------------------------------- + Clean up FT variables. + ------------------------------------------------------------------------*/ +void limFTCleanupPreAuthInfo(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tpPESession pReAssocSessionEntry = NULL; + tANI_U8 sessionId = 0; + if (!psessionEntry) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, "%s: psessionEntry is NULL", __func__);) +#endif + return; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + pReAssocSessionEntry = + peFindSessionByBssid(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + &sessionId); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog( pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + psessionEntry->ftPEContext.pFTPreAuthReq);) +#endif + if (psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + vos_mem_free( + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddBssReq) { + vos_mem_free(psessionEntry->ftPEContext.pAddBssReq); + psessionEntry->ftPEContext.pAddBssReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddStaReq) { + vos_mem_free(psessionEntry->ftPEContext.pAddStaReq); + psessionEntry->ftPEContext.pAddStaReq = NULL; + } + + /* The session is being deleted, cleanup the contents */ + vos_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0); + + /* Delete the session created while handling pre-auth response */ + if (pReAssocSessionEntry) { + /* If we have successful pre-auth response, then we would have + * created a session on which reassoc request will be sent + */ + if (pReAssocSessionEntry->valid && + pReAssocSessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) { + limLog( pMac, LOG1, FL("Deleting Preauth Session %d"), + pReAssocSessionEntry->peSessionId); + peDeleteSession(pMac, pReAssocSessionEntry); + } + } +} + +void limFTCleanupAllFTSessions(tpAniSirGlobal pMac) +{ + /* Wrapper function to cleanup all FT sessions */ + int i; + + for (i = 0; i < pMac->lim.maxBssId; i++) { + if (VOS_TRUE == pMac->lim.gpSession[i].valid) { + /* The session is valid, may have FT data */ + limFTCleanup(pMac, &pMac->lim.gpSession[i]); + } + } +} + +void limFTCleanup(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (NULL == psessionEntry) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is NULL"));) +#endif + return; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog( pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + psessionEntry->ftPEContext.pFTPreAuthReq);) +#endif + if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + vos_mem_free( + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddBssReq) { + vos_mem_free(psessionEntry->ftPEContext.pAddBssReq); + psessionEntry->ftPEContext.pAddBssReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddStaReq) { + vos_mem_free(psessionEntry->ftPEContext.pAddStaReq); + psessionEntry->ftPEContext.pAddStaReq = NULL; + } + + /* The session is being deleted, cleanup the contents */ + vos_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0); +} + +/*------------------------------------------------------------------ + * + * This is the handler after suspending the link. + * We suspend the link and then now proceed to switch channel. + * + *------------------------------------------------------------------*/ +void static +limFTPreAuthSuspendLinkHandler(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data) +{ + tpPESession psessionEntry = (tpPESession)data; + + /* The link is suspended of not */ + if (NULL == psessionEntry || + NULL == psessionEntry->ftPEContext.pFTPreAuthReq || + status != eHAL_STATUS_SUCCESS) { + PELOGE(limLog( pMac, LOGE, + FL("preAuth error, status = %d"), status);) + limPostFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); + return; + } + + /* Suspended, now move to a different channel. + * Perform some sanity check before proceeding + */ + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + limChangeChannelWithCallback(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum, + limPerformFTPreAuth, NULL, psessionEntry); + return; + } +} + + +/*-------------------------------------------------------------------------- + In this function, we process the FT Pre Auth Req. + We receive Pre-Auth + Suspend link + Register a call back + In the call back, we will need to accept frames from the new bssid + Send out the auth req to new AP. + Start timer and when the timer is done or if we receive the Auth response + We change channel + Resume link + ------------------------------------------------------------------------*/ +int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + int bufConsumed = FALSE; + tpPESession psessionEntry; + tANI_U8 sessionId; + tpSirFTPreAuthReq ftPreAuthReq = + (tSirFTPreAuthReq *)pMsg->bodyptr; + + if (NULL == ftPreAuthReq) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("tSirFTPreAuthReq is NULL"));) +#endif + return bufConsumed; + } + + /* Get the current session entry */ + psessionEntry = + peFindSessionByBssid(pMac, ftPreAuthReq->currbssId, &sessionId); + if (psessionEntry == NULL) { + PELOGE(limLog( pMac, LOGE, + FL("Unable to find session for the following bssid"));) + limPrintMacAddr( pMac, ftPreAuthReq->currbssId, LOGE ); + + /* Post the FT Pre Auth Response to SME */ + limPostFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); + /* return FALSE, since the Pre-Auth Req will be freed in + * limPostFTPreAuthRsp on failure + */ + return bufConsumed; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + bufConsumed = TRUE; + return bufConsumed; + } + + /* Can set it only after sending auth */ + psessionEntry->ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + psessionEntry->ftPEContext.ftPreAuthSession = VOS_TRUE; + + /* Indicate that this is the session on which preauth is being done */ + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + if (psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) + { + vos_mem_free( + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + } + + /* We need information from the Pre-Auth Req. Lets save that */ + psessionEntry->ftPEContext.pFTPreAuthReq = ftPreAuthReq; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOG1, FL("PRE Auth ft_ies_length=%02x%02x%02x"), + psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[0], + psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[1], + psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[2]);) +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, + psessionEntry, 0, 0); +#endif + + /* Dont need to suspend if APs are in same channel */ + if (psessionEntry->currentOperChannel != + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + /* Need to suspend link only if the channels are different */ + PELOG2(limLog(pMac, LOG2, FL("Performing pre-auth on different" + " channel (session %p)"), psessionEntry);) + limSuspendLink(pMac, eSIR_CHECK_ROAMING_SCAN, + limFTPreAuthSuspendLinkHandler, + (tANI_U32 *)psessionEntry); + } else { + PELOG2(limLog(pMac, LOG2, FL("Performing pre-auth on same" + " channel (session %p)"), psessionEntry);) + /* We are in the same channel. Perform pre-auth */ + limPerformFTPreAuth(pMac, eHAL_STATUS_SUCCESS, NULL, psessionEntry); + } + + return bufConsumed; +} + +/*------------------------------------------------------------------ + * Send the Auth1 + * Receive back Auth2 + *------------------------------------------------------------------*/ +void limPerformFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry) +{ + tSirMacAuthFrameBody authFrame; + + if (NULL == psessionEntry) { + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is NULL"));) + return; + } + + if (psessionEntry->is11Rconnection && + psessionEntry->ftPEContext.pFTPreAuthReq) { + /* Only 11r assoc has FT IEs */ + if (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies == NULL) { + PELOGE(limLog( pMac, LOGE, + "%s: FTIEs for Auth Req Seq 1 is absent", + __func__);) + goto preauth_fail; + } + } + + if (status != eHAL_STATUS_SUCCESS) { + PELOGE(limLog( pMac, LOGE, + "%s: Change channel not successful for FT pre-auth", + __func__);) + goto preauth_fail; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG2(limLog(pMac,LOG2,"Entered wait auth2 state for FT" + " (old session %p)", psessionEntry);) +#endif + + if (psessionEntry->is11Rconnection) { + /* Now we are on the right channel and need to send out Auth1 and + * receive Auth2 + */ + authFrame.authAlgoNumber = eSIR_FT_AUTH; + } +#if defined FEATURE_WLAN_ESE || defined FEATURE_WLAN_LFR + else { + /* Will need to make isESEconnection a enum may be for further + * improvements to this to match this algorithm number + */ + authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM; + } +#endif + authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; + authFrame.authStatusCode = 0; + + /* Start timer here to come back to operating channel */ + pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId = + psessionEntry->peSessionId; + if(TX_SUCCESS != + tx_timer_activate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOGE, FL("FT Auth Rsp Timer Start Failed"));) +#endif + goto preauth_fail; + } + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, + eLIM_FT_PREAUTH_RSP_TIMER)); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog( pMac, LOG1, FL("FT Auth Rsp Timer Started"));) +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, + pMac->lim.pSessionEntry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + + limSendAuthMgmtFrame(pMac, &authFrame, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + LIM_NO_WEP_IN_FC, psessionEntry, eSIR_FALSE); + return; + +preauth_fail: + limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); + return; +} + +/*------------------------------------------------------------------ + * + * Create the new Add Bss Req to the new AP. + * This will be used when we are ready to FT to the new AP. + * The newly created ft Session entry is passed to this function + * + *------------------------------------------------------------------*/ +tSirRetStatus limFTPrepareAddBssReq( tpAniSirGlobal pMac, + tANI_U8 updateEntry, tpPESession pftSessionEntry, + tpSirBssDescription bssDescription ) +{ + tpAddBssParams pAddBssParams = NULL; + tANI_U8 i; + tANI_U8 chanWidthSupp = 0; + tSchBeaconStruct *pBeaconStruct; + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(pftSessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return eSIR_FAILURE; + } + + pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) { + limLog(pMac, LOGE, + FL("Unable to allocate memory for creating ADD_BSS") ); + return eSIR_MEM_ALLOC_FAILED; + } + + // Package SIR_HAL_ADD_BSS_REQ message parameters + pAddBssParams = vos_mem_malloc(sizeof( tAddBssParams )); + if (NULL == pAddBssParams) { + vos_mem_free(pBeaconStruct); + limLog( pMac, LOGP, + FL( "Unable to allocate memory for creating ADD_BSS" )); + return (eSIR_MEM_ALLOC_FAILED); + } + + vos_mem_set((tANI_U8 *) pAddBssParams, sizeof( tAddBssParams ), 0); + + limExtractApCapabilities( pMac, + (tANI_U8 *) bssDescription->ieFields, + limGetIElenFromBssDescription( bssDescription ), pBeaconStruct ); + + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, pftSessionEntry); + + vos_mem_copy(pAddBssParams->bssId, bssDescription->bssId, + sizeof(tSirMacAddr)); + + // Fill in tAddBssParams selfMacAddr + vos_mem_copy(pAddBssParams->selfMacAddr, pftSessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); + + pAddBssParams->bssType = pftSessionEntry->bssType; + pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA; + + pAddBssParams->beaconInterval = bssDescription->beaconInterval; + + pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod; + pAddBssParams->updateBss = updateEntry; + + pAddBssParams->reassocReq = true; + + pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount; + pAddBssParams->cfParamSet.cfpPeriod = pBeaconStruct->cfParamSet.cfpPeriod; + pAddBssParams->cfParamSet.cfpMaxDuration = + pBeaconStruct->cfParamSet.cfpMaxDuration; + pAddBssParams->cfParamSet.cfpDurRemaining = + pBeaconStruct->cfParamSet.cfpDurRemaining; + + + pAddBssParams->rateSet.numRates = pBeaconStruct->supportedRates.numRates; + vos_mem_copy(pAddBssParams->rateSet.rate, + pBeaconStruct->supportedRates.rate, + pBeaconStruct->supportedRates.numRates); + + pAddBssParams->nwType = bssDescription->nwType; + + pAddBssParams->shortSlotTimeSupported = + (tANI_U8)pBeaconStruct->capabilityInfo.shortSlotTime; + pAddBssParams->llaCoexist = + (tANI_U8) pftSessionEntry->beaconParams.llaCoexist; + pAddBssParams->llbCoexist = + (tANI_U8) pftSessionEntry->beaconParams.llbCoexist; + pAddBssParams->llgCoexist = + (tANI_U8) pftSessionEntry->beaconParams.llgCoexist; + pAddBssParams->ht20Coexist = + (tANI_U8) pftSessionEntry->beaconParams.ht20Coexist; +#ifdef WLAN_FEATURE_11W + pAddBssParams->rmfEnabled = pftSessionEntry->limRmfEnabled; +#endif + + // Use the advertised capabilities from the received beacon/PR + if (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) && + ( pBeaconStruct->HTCaps.present )) + { + pAddBssParams->htCapable = pBeaconStruct->HTCaps.present; + vos_mem_copy(&pAddBssParams->staContext.capab_info, + &pBeaconStruct->capabilityInfo, + sizeof(pAddBssParams->staContext.capab_info)); + vos_mem_copy(&pAddBssParams->staContext.ht_caps, + (tANI_U8 *)&pBeaconStruct->HTCaps + sizeof(tANI_U8), + sizeof(pAddBssParams->staContext.ht_caps)); + + if ( pBeaconStruct->HTInfo.present ) + { + pAddBssParams->htOperMode = + (tSirMacHTOperatingMode)pBeaconStruct->HTInfo.opMode; + pAddBssParams->dualCTSProtection = + ( tANI_U8 ) pBeaconStruct->HTInfo.dualCTSProtection; + + chanWidthSupp = limGetHTCapability( pMac, + eHT_SUPPORTED_CHANNEL_WIDTH_SET, + pftSessionEntry); + if( (pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp) ) + { + pAddBssParams->txChannelWidthSet = + ( tANI_U8 ) pBeaconStruct->HTInfo.recommendedTxWidthSet; + pAddBssParams->currentExtChannel = + pBeaconStruct->HTInfo.secondaryChannelOffset; + } + else + { + pAddBssParams->txChannelWidthSet = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + pAddBssParams->currentExtChannel = PHY_SINGLE_CHANNEL_CENTERED; + } + pAddBssParams->llnNonGFCoexist = + (tANI_U8)pBeaconStruct->HTInfo.nonGFDevicesPresent; + pAddBssParams->fLsigTXOPProtectionFullSupport = + (tANI_U8)pBeaconStruct->HTInfo.lsigTXOPProtectionFullSupport; + pAddBssParams->fRIFSMode = pBeaconStruct->HTInfo.rifsMode; + } + } + + pAddBssParams->currentOperChannel = bssDescription->channelId; + pftSessionEntry->htSecondaryChannelOffset = + pAddBssParams->currentExtChannel; + +#ifdef WLAN_FEATURE_11AC + if (pftSessionEntry->vhtCapability && + pftSessionEntry->vhtCapabilityPresentInBeacon) + { + pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present; + pAddBssParams->vhtTxChannelWidthSet = + pBeaconStruct->VHTOperation.chanWidth; + pAddBssParams->currentExtChannel = + limGet11ACPhyCBState(pMac, + pAddBssParams->currentOperChannel, + pAddBssParams->currentExtChannel, + pftSessionEntry->apCenterChan, + pftSessionEntry); + pAddBssParams->staContext.vht_caps = + ((pBeaconStruct->VHTCaps.maxMPDULen << + SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | + (pBeaconStruct->VHTCaps.supportedChannelWidthSet << + SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | + (pBeaconStruct->VHTCaps.ldpcCodingCap << + SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | + (pBeaconStruct->VHTCaps.shortGI80MHz << + SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | + (pBeaconStruct->VHTCaps.shortGI160and80plus80MHz << + SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | + (pBeaconStruct->VHTCaps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) | + (pBeaconStruct->VHTCaps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) | + (pBeaconStruct->VHTCaps.suBeamFormerCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | + (pBeaconStruct->VHTCaps.suBeamformeeCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | + (pBeaconStruct->VHTCaps.csnofBeamformerAntSup << + SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | + (pBeaconStruct->VHTCaps.numSoundingDim << + SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | + (pBeaconStruct->VHTCaps.muBeamformerCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP)| + (pBeaconStruct->VHTCaps.muBeamformeeCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | + (pBeaconStruct->VHTCaps.vhtTXOPPS << SIR_MAC_VHT_CAP_TXOPPS) | + (pBeaconStruct->VHTCaps.htcVHTCap << SIR_MAC_VHT_CAP_HTC_CAP) | + (pBeaconStruct->VHTCaps.maxAMPDULenExp << + SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | + (pBeaconStruct->VHTCaps.vhtLinkAdaptCap << + SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | + (pBeaconStruct->VHTCaps.rxAntPattern << + SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | + (pBeaconStruct->VHTCaps.txAntPattern << + SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | + (pBeaconStruct->VHTCaps.reserved1 << SIR_MAC_VHT_CAP_RESERVED2)); + } + else + { + pAddBssParams->vhtCapable = 0; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog( pMac, LOG1, FL( "SIR_HAL_ADD_BSS_REQ with channel = %d..." ), + pAddBssParams->currentOperChannel); +#endif + + // Populate the STA-related parameters here + // Note that the STA here refers to the AP + { + pAddBssParams->staContext.staType = STA_ENTRY_OTHER; + + vos_mem_copy(pAddBssParams->staContext.bssId, + bssDescription->bssId, + sizeof(tSirMacAddr)); + pAddBssParams->staContext.listenInterval = + bssDescription->beaconInterval; + + pAddBssParams->staContext.assocId = 0; + pAddBssParams->staContext.uAPSD = 0; + pAddBssParams->staContext.maxSPLen = 0; + pAddBssParams->staContext.shortPreambleSupported = + (tANI_U8)pBeaconStruct->capabilityInfo.shortPreamble; + pAddBssParams->staContext.updateSta = updateEntry; + pAddBssParams->staContext.encryptType = pftSessionEntry->encryptType; +#ifdef WLAN_FEATURE_11W + pAddBssParams->staContext.rmfEnabled = pftSessionEntry->limRmfEnabled; +#endif + + if (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) && + ( pBeaconStruct->HTCaps.present )) { + pAddBssParams->staContext.us32MaxAmpduDuration = 0; + pAddBssParams->staContext.htCapable = 1; + pAddBssParams->staContext.greenFieldCapable = + ( tANI_U8 ) pBeaconStruct->HTCaps.greenField; + pAddBssParams->staContext.lsigTxopProtection = + ( tANI_U8 ) pBeaconStruct->HTCaps.lsigTXOPProtection; + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) { + pAddBssParams->staContext.txChannelWidthSet = + ( tANI_U8 )pBeaconStruct->HTInfo.recommendedTxWidthSet; + } + else { + pAddBssParams->staContext.txChannelWidthSet = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + } +#ifdef WLAN_FEATURE_11AC + if (pftSessionEntry->vhtCapability && + IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) + { + pAddBssParams->staContext.vhtCapable = 1; + if ((pBeaconStruct->VHTCaps.suBeamFormerCap || + pBeaconStruct->VHTCaps.muBeamformerCap) && + pftSessionEntry->txBFIniFeatureEnabled) + { + pAddBssParams->staContext.vhtTxBFCapable = 1; + } + } +#endif + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) + { + pAddBssParams->staContext.txChannelWidthSet = + (tANI_U8)pBeaconStruct->HTInfo.recommendedTxWidthSet; +#ifdef WLAN_FEATURE_11AC + if (pAddBssParams->staContext.vhtCapable) + { + pAddBssParams->staContext.vhtTxChannelWidthSet = + pBeaconStruct->VHTOperation.chanWidth; + } +#endif + } + else + { + pAddBssParams->staContext.txChannelWidthSet = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + } + pAddBssParams->staContext.mimoPS = + (tSirMacHTMIMOPowerSaveState)pBeaconStruct->HTCaps.mimoPowerSave; + pAddBssParams->staContext.delBASupport = + ( tANI_U8 ) pBeaconStruct->HTCaps.delayedBA; + pAddBssParams->staContext.maxAmsduSize = + ( tANI_U8 ) pBeaconStruct->HTCaps.maximalAMSDUsize; + pAddBssParams->staContext.maxAmpduDensity = + pBeaconStruct->HTCaps.mpduDensity; + pAddBssParams->staContext.fDsssCckMode40Mhz = + (tANI_U8)pBeaconStruct->HTCaps.dsssCckMode40MHz; + pAddBssParams->staContext.fShortGI20Mhz = + (tANI_U8)pBeaconStruct->HTCaps.shortGI20MHz; + pAddBssParams->staContext.fShortGI40Mhz = + (tANI_U8)pBeaconStruct->HTCaps.shortGI40MHz; + pAddBssParams->staContext.maxAmpduSize = + pBeaconStruct->HTCaps.maxRxAMPDUFactor; + + if( pBeaconStruct->HTInfo.present ) + pAddBssParams->staContext.rifsMode = + pBeaconStruct->HTInfo.rifsMode; + } + + if ((pftSessionEntry->limWmeEnabled && pBeaconStruct->wmeEdcaPresent) || + (pftSessionEntry->limQosEnabled && pBeaconStruct->edcaPresent)) + pAddBssParams->staContext.wmmEnabled = 1; + else + pAddBssParams->staContext.wmmEnabled = 0; + + pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent; + /* For OSEN Connection AP does not advertise RSN or WPA IE + * so from the IEs we get from supplicant we get this info + * so for FW to transmit EAPOL message 4 we shall set + * wpa_rsn + */ + pAddBssParams->staContext.wpa_rsn |= (pBeaconStruct->wpaPresent << 1); + if ((!pAddBssParams->staContext.wpa_rsn) && + (pftSessionEntry->isOSENConnection)) + pAddBssParams->staContext.wpa_rsn = 1; + //Update the rates +#ifdef WLAN_FEATURE_11AC + limPopulatePeerRateSet(pMac, &pAddBssParams->staContext.supportedRates, + pBeaconStruct->HTCaps.supportedMCSSet, + false,pftSessionEntry,&pBeaconStruct->VHTCaps); +#else + limPopulatePeerRateSet(pMac, &pAddBssParams->staContext.supportedRates, + beaconStruct.HTCaps.supportedMCSSet, false,pftSessionEntry); +#endif + if (pftSessionEntry->htCapability) + { + pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11n; + if (pftSessionEntry->vhtCapability) + pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11ac; + } + else + { + if (pftSessionEntry->limRFBand == SIR_BAND_5_GHZ) + { + pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11a; + } + else + { + pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11bg; + } + } + } + + //Disable BA. It will be set as part of ADDBA negotiation. + for( i = 0; i < STACFG_MAX_TC; i++ ) + { + pAddBssParams->staContext.staTCParams[i].txUseBA = eBA_DISABLE; + pAddBssParams->staContext.staTCParams[i].rxUseBA = eBA_DISABLE; + pAddBssParams->staContext.staTCParams[i].txBApolicy = + eBA_POLICY_IMMEDIATE; + pAddBssParams->staContext.staTCParams[i].rxBApolicy = + eBA_POLICY_IMMEDIATE; + } + +#if defined WLAN_FEATURE_VOWIFI + pAddBssParams->maxTxPower = pftSessionEntry->maxTxPower; +#endif + +#ifdef WLAN_FEATURE_11W + if (pftSessionEntry->limRmfEnabled) + { + pAddBssParams->rmfEnabled = 1; + pAddBssParams->staContext.rmfEnabled = 1; + } +#endif + + pAddBssParams->status = eHAL_STATUS_SUCCESS; + pAddBssParams->respReqd = true; + + pAddBssParams->staContext.sessionId = pftSessionEntry->peSessionId; + pAddBssParams->staContext.smesessionId = pftSessionEntry->smeSessionId; + pAddBssParams->sessionId = pftSessionEntry->peSessionId; + + // Set a new state for MLME + + pftSessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, pftSessionEntry->peSessionId, + eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE)); + pAddBssParams->halPersona=(tANI_U8)pftSessionEntry->pePersona; + + pftSessionEntry->ftPEContext.pAddBssReq = pAddBssParams; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog( pMac, LOG1, FL( "Saving SIR_HAL_ADD_BSS_REQ for pre-auth ap..." )); +#endif + + vos_mem_free(pBeaconStruct); + return 0; +} + + +/*------------------------------------------------------------------ + * + * Setup the new session for the pre-auth AP. + * Return the newly created session entry. + * + *------------------------------------------------------------------*/ +void limFillFTSession(tpAniSirGlobal pMac, + tpSirBssDescription pbssDescription, + tpPESession pftSessionEntry, + tpPESession psessionEntry) +{ + tANI_U8 currentBssUapsd; + tPowerdBm localPowerConstraint; + tPowerdBm regMax; + tSchBeaconStruct *pBeaconStruct; + tANI_U32 selfDot11Mode; + ePhyChanBondState cbEnabledMode; + + pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(pMac, LOGE, + FL("Unable to allocate memory for creating limFillFTSession") ); +#endif + return; + } + + /* Retrieve the session that has already been created and update the entry */ +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + limPrintMacAddr(pMac, pbssDescription->bssId, LOG1); +#endif + pftSessionEntry->limWmeEnabled = psessionEntry->limWmeEnabled; + pftSessionEntry->limQosEnabled = psessionEntry->limQosEnabled; + pftSessionEntry->limWsmEnabled = psessionEntry->limWsmEnabled; + pftSessionEntry->lim11hEnable = psessionEntry->lim11hEnable; + pftSessionEntry->isOSENConnection = psessionEntry->isOSENConnection; + + // Fields to be filled later + pftSessionEntry->pLimJoinReq = NULL; + pftSessionEntry->smeSessionId = psessionEntry->smeSessionId; + pftSessionEntry->transactionId = 0; + + limExtractApCapabilities( pMac, + (tANI_U8 *) pbssDescription->ieFields, + limGetIElenFromBssDescription( pbssDescription ), + pBeaconStruct ); + + pftSessionEntry->rateSet.numRates = pBeaconStruct->supportedRates.numRates; + vos_mem_copy(pftSessionEntry->rateSet.rate, + pBeaconStruct->supportedRates.rate, pBeaconStruct->supportedRates.numRates); + + pftSessionEntry->extRateSet.numRates = pBeaconStruct->extendedRates.numRates; + vos_mem_copy(pftSessionEntry->extRateSet.rate, + pBeaconStruct->extendedRates.rate, pftSessionEntry->extRateSet.numRates); + + pftSessionEntry->ssId.length = pBeaconStruct->ssId.length; + 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->vhtCapability = + (IS_DOT11_MODE_VHT(pftSessionEntry->dot11mode) + && IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)); + pftSessionEntry->htCapability = (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) + && pBeaconStruct->HTCaps.present); +#ifdef WLAN_FEATURE_11AC + if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) && pBeaconStruct->VHTOperation.present) + { + pftSessionEntry->vhtCapabilityPresentInBeacon = 1; + pftSessionEntry->apCenterChan = + pBeaconStruct->VHTOperation.chanCenterFreqSeg1; + pftSessionEntry->apChanWidth = pBeaconStruct->VHTOperation.chanWidth; + } + else + { + pftSessionEntry->vhtCapabilityPresentInBeacon = 0; + } +#endif + sirCopyMacAddr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr); + sirCopyMacAddr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId); + sirCopyMacAddr(pftSessionEntry->prev_ap_bssid, psessionEntry->bssId); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + limPrintMacAddr(pMac, pftSessionEntry->limReAssocbssId, LOG1); +#endif + + /* Store beaconInterval */ + pftSessionEntry->beaconParams.beaconInterval = + pbssDescription->beaconInterval; + pftSessionEntry->bssType = psessionEntry->bssType; + + pftSessionEntry->statypeForBss = STA_ENTRY_PEER; + pftSessionEntry->nwType = pbssDescription->nwType; + + /* Copy The channel Id to the session Table */ + pftSessionEntry->limReassocChannelId = pbssDescription->channelId; + pftSessionEntry->currentOperChannel = pbssDescription->channelId; + + if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) + { + pftSessionEntry->limSystemRole = eLIM_STA_ROLE; + } + else if(pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) + { + pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; + } + else + { + /* Throw an error and return and make sure to delete the session.*/ + limLog(pMac, LOGE, FL("Invalid bss type")); + } + + pftSessionEntry->limCurrentBssCaps = pbssDescription->capabilityInfo; + pftSessionEntry->limReassocBssCaps = pbssDescription->capabilityInfo; + if( pMac->roam.configParam.shortSlotTime && + SIR_MAC_GET_SHORT_SLOT_TIME(pftSessionEntry->limReassocBssCaps)) + { + pftSessionEntry->shortSlotTimeSupported = TRUE; + } + + regMax = cfgGetRegulatoryMaxTransmitPower(pMac, + pftSessionEntry->currentOperChannel ); + localPowerConstraint = regMax; + limExtractApCapability( pMac, (tANI_U8 *) pbssDescription->ieFields, + limGetIElenFromBssDescription(pbssDescription), + &pftSessionEntry->limCurrentBssQosCaps, + &pftSessionEntry->limCurrentBssPropCap, + ¤tBssUapsd , &localPowerConstraint, psessionEntry); + + pftSessionEntry->limReassocBssQosCaps = + pftSessionEntry->limCurrentBssQosCaps; + pftSessionEntry->limReassocBssPropCap = + pftSessionEntry->limCurrentBssPropCap; + +#ifdef WLAN_FEATURE_VOWIFI_11R + pftSessionEntry->is11Rconnection = psessionEntry->is11Rconnection; +#endif +#ifdef FEATURE_WLAN_ESE + pftSessionEntry->isESEconnection = psessionEntry->isESEconnection; + pftSessionEntry->is_ese_version_ie_present = + pBeaconStruct->is_ese_ver_ie_present; +#endif +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + pftSessionEntry->isFastTransitionEnabled = + psessionEntry->isFastTransitionEnabled; +#endif + +#ifdef FEATURE_WLAN_LFR + pftSessionEntry->isFastRoamIniFeatureEnabled = + psessionEntry->isFastRoamIniFeatureEnabled; +#endif + +#ifdef FEATURE_WLAN_ESE + pftSessionEntry->maxTxPower = + limGetMaxTxPower(regMax, localPowerConstraint, + pMac->roam.configParam.nTxPowerCap); +#else + pftSessionEntry->maxTxPower = VOS_MIN( regMax , (localPowerConstraint) ); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(pMac, LOG1, + FL("Reg max = %d, local power = %d, ini tx power = %d, max tx = %d"), + regMax, localPowerConstraint, pMac->roam.configParam.nTxPowerCap, + pftSessionEntry->maxTxPower); +#endif + + pftSessionEntry->limRFBand = + limGetRFBand(pftSessionEntry->currentOperChannel); + + pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, pftSessionEntry->peSessionId, + pftSessionEntry->limSmeState)); + + pftSessionEntry->encryptType = psessionEntry->encryptType; +#ifdef WLAN_FEATURE_11W + pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled; +#endif + + if (pftSessionEntry->limRFBand == SIR_BAND_2_4_GHZ) + { + cbEnabledMode = pMac->roam.configParam.channelBondingMode24GHz; + } + else + { + cbEnabledMode = pMac->roam.configParam.channelBondingMode5GHz; + } + pftSessionEntry->htSupportedChannelWidthSet = + (pBeaconStruct->HTInfo.present)? + (cbEnabledMode && pBeaconStruct->HTInfo.recommendedTxWidthSet):0; + pftSessionEntry->htRecommendedTxWidthSet = + pftSessionEntry->htSupportedChannelWidthSet; + + pftSessionEntry->enableHtSmps = psessionEntry->enableHtSmps; + pftSessionEntry->smpsMode = psessionEntry->smpsMode; + limLog(pMac, LOG1, FL("FT session enable smps: %d mode: %d"), + pftSessionEntry->enableHtSmps, pftSessionEntry->smpsMode); + + vos_mem_free(pBeaconStruct); +} + +/*------------------------------------------------------------------ + * + * Setup the session and the add bss req for the pre-auth AP. + * + *------------------------------------------------------------------*/ +tSirRetStatus limFTSetupAuthSession(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tpPESession pftSessionEntry = NULL; + tANI_U8 sessionId = 0; + + pftSessionEntry = + peFindSessionByBssid(pMac, psessionEntry->limReAssocbssId, &sessionId); + if (pftSessionEntry == NULL) { + PELOGE(limLog(pMac, LOGE, + FL("Unable to find session for the following bssid"));) + limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE); + return eSIR_FAILURE; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return eSIR_FAILURE; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq && + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + limFillFTSession(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription, + pftSessionEntry, + psessionEntry); + + limFTPrepareAddBssReq( pMac, FALSE, pftSessionEntry, + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription ); + } + + return eSIR_SUCCESS; +} + +/*------------------------------------------------------------------ + * Resume Link Call Back + *------------------------------------------------------------------*/ +void limFTProcessPreAuthResult(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data) +{ + tpPESession psessionEntry = (tpPESession)data; + + if (NULL == psessionEntry || + NULL == psessionEntry->ftPEContext.pFTPreAuthReq) + return; + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { + psessionEntry->ftPEContext.ftPreAuthStatus = + limFTSetupAuthSession(pMac, psessionEntry); + } + + // Post the FT Pre Auth Response to SME + limPostFTPreAuthRsp(pMac, psessionEntry->ftPEContext.ftPreAuthStatus, + psessionEntry->ftPEContext.saved_auth_rsp, + psessionEntry->ftPEContext.saved_auth_rsp_length, psessionEntry); +} + +/*------------------------------------------------------------------ + * Resume Link Call Back + *------------------------------------------------------------------*/ +void limPerformPostFTPreAuthAndChannelChange(tpAniSirGlobal pMac, + eHalStatus status, + tANI_U32 *data, + tpPESession psessionEntry) +{ + /* Set the resume channel to Any valid channel (invalid) + * This will instruct HAL to set it to any previous valid channel. + */ + peSetResumeChannel(pMac, 0, 0); + limResumeLink(pMac, limFTProcessPreAuthResult, (tANI_U32 *)psessionEntry); +} + +/*------------------------------------------------------------------ + * + * Will post pre auth response to SME. + * + *------------------------------------------------------------------*/ +void limPostFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status, + tANI_U8 *auth_rsp, tANI_U16 auth_rsp_length, + tpPESession psessionEntry) +{ + tpSirFTPreAuthRsp pFTPreAuthRsp; + tSirMsgQ mmhMsg; + tANI_U16 rspLen = sizeof(tSirFTPreAuthRsp); + + pFTPreAuthRsp = (tpSirFTPreAuthRsp)vos_mem_malloc(rspLen); + if (NULL == pFTPreAuthRsp) { + PELOGE(limLog( pMac, LOGE, "Failed to allocate memory");) + VOS_ASSERT(pFTPreAuthRsp != NULL); + return; + } + vos_mem_zero( pFTPreAuthRsp, rspLen); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOG1, FL("Auth Rsp = %p"), pFTPreAuthRsp);) +#endif + + if (psessionEntry) { + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + vos_mem_free(pFTPreAuthRsp); + return; + } + pFTPreAuthRsp->smeSessionId = psessionEntry->smeSessionId; + + /* The bssid of the AP we are sending Auth1 to. */ + if (psessionEntry->ftPEContext.pFTPreAuthReq) + sirCopyMacAddr(pFTPreAuthRsp->preAuthbssId, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId); + } + + pFTPreAuthRsp->messageType = eWNI_SME_FT_PRE_AUTH_RSP; + pFTPreAuthRsp->length = (tANI_U16) rspLen; + pFTPreAuthRsp->status = status; + + /* Attach the auth response now back to SME */ + pFTPreAuthRsp->ft_ies_length = 0; + if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { + /* Only 11r assoc has FT IEs */ + vos_mem_copy(pFTPreAuthRsp->ft_ies, auth_rsp, auth_rsp_length); + pFTPreAuthRsp->ft_ies_length = auth_rsp_length; + } + + if (status != eSIR_SUCCESS) { + /* Ensure that on Pre-Auth failure the cached Pre-Auth Req and + * other allocated memory is freed up before returning. + */ + limLog(pMac, LOG1, "Pre-Auth Failed, Cleanup!"); + limFTCleanup(pMac, psessionEntry); + } + + mmhMsg.type = pFTPreAuthRsp->messageType; + mmhMsg.bodyptr = pFTPreAuthRsp; + mmhMsg.bodyval = 0; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOG1, + "Posted Auth Rsp to SME with status of 0x%x", status);) +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + if (status == eSIR_SUCCESS) + limDiagEventReport(pMac, WLAN_PE_DIAG_PREAUTH_DONE, psessionEntry, + status, 0); +#endif + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + +/*------------------------------------------------------------------ + * + * Send the FT Pre Auth Response to SME whenever we have a status + * ready to be sent to SME + * + * SME will be the one to send it up to the supplicant to receive + * FTIEs which will be required for Reassoc Req. + * + *------------------------------------------------------------------*/ +void limHandleFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status, + tANI_U8 *auth_rsp, tANI_U16 auth_rsp_length, + tpPESession psessionEntry) +{ + tpPESession pftSessionEntry = NULL; + tANI_U8 sessionId = 0; + tpSirBssDescription pbssDescription = NULL; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, + psessionEntry, (tANI_U16)status, 0); +#endif + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + /* Save the status of pre-auth */ + psessionEntry->ftPEContext.ftPreAuthStatus = status; + + /* Save the auth rsp, so we can send it to + * SME once we resume link + */ + psessionEntry->ftPEContext.saved_auth_rsp_length = 0; + if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { + vos_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp, + auth_rsp, auth_rsp_length); + psessionEntry->ftPEContext.saved_auth_rsp_length = + auth_rsp_length; + } + + if (!psessionEntry->ftPEContext.pFTPreAuthReq || + !psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + limLog(pMac, LOGE, + FL("pFTPreAuthReq or pbssDescription is NULL")); + return; + } + + /* Create FT session for the re-association at this point */ + if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { + pbssDescription = + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription; + limPrintMacAddr(pMac, pbssDescription->bssId, LOG1); + if((pftSessionEntry = + peCreateSession(pMac, pbssDescription->bssId, + &sessionId, pMac->lim.maxStation, + psessionEntry->bssType)) == NULL) { + limLog(pMac, LOGE, + FL("Session Can not be created for pre-auth 11R AP")); + status = eSIR_FAILURE; + psessionEntry->ftPEContext.ftPreAuthStatus = status; + goto send_rsp; + } + + pftSessionEntry->peSessionId = sessionId; + pftSessionEntry->smeSessionId = psessionEntry->smeSessionId; + sirCopyMacAddr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr); + sirCopyMacAddr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId); + pftSessionEntry->bssType = psessionEntry->bssType; + + if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) { + pftSessionEntry->limSystemRole = eLIM_STA_ROLE; + } + else if(pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) { + pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; + } + else { + limLog(pMac, LOGE, FL("Invalid bss type")); + } + pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; + vos_mem_copy(&(pftSessionEntry->htConfig), &(psessionEntry->htConfig), + sizeof(psessionEntry->htConfig)); + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + + PELOGE(limLog(pMac, LOG1, "%s:created session (%p) with id = %d", + __func__, pftSessionEntry, pftSessionEntry->peSessionId);) + + /* Update the ReAssoc BSSID of the current session */ + sirCopyMacAddr(psessionEntry->limReAssocbssId, pbssDescription->bssId); + limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOG1); + } + +send_rsp: + if (psessionEntry->currentOperChannel != + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + /* Need to move to the original AP channel */ + limChangeChannelWithCallback(pMac, psessionEntry->currentOperChannel, + limPerformPostFTPreAuthAndChannelChange, + NULL, psessionEntry); + } + else { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOG1, + "Pre auth on same channel as connected AP channel %d", + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum);) +#endif + limFTProcessPreAuthResult(pMac, status, (tANI_U32 *)psessionEntry); + } +} + +/** + * lim_ft_reassoc_set_link_state_callback()- registered callback to perform post + * peer creation operations + * + * @mac: pointer to global mac structure + * @callback_arg: registered callback argument + * @status: peer creation status + * + * this is registered callback function during ft reassoc scenario to perform + * post peer creation operation based on the peer creation status + * + * Return: none + */ +void lim_ft_reassoc_set_link_state_callback(tpAniSirGlobal mac, + void *callback_arg, bool status) +{ + tpPESession session_entry; + tSirMsgQ msg_q; + tLimMlmReassocReq *mlm_reassoc_req = (tLimMlmReassocReq *) callback_arg; + tSirRetStatus ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + tLimMlmReassocCnf mlm_reassoc_cnf = {0}; + session_entry = peFindSessionBySessionId(mac, + mlm_reassoc_req->sessionId); + if (!status || !session_entry) { + limLog(mac, LOGE, FL("Failed: session:%p for session id:%d status:%d"), + session_entry, mlm_reassoc_req->sessionId, status); + goto failure; + } + + /* + * we need to defer the message until we get the + * response back from HAL + */ + SET_LIM_PROCESS_DEFD_MESGS(mac, false); + + msg_q.type = SIR_HAL_ADD_BSS_REQ; + msg_q.reserved = 0; + msg_q.bodyptr = session_entry->ftPEContext.pAddBssReq; + msg_q.bodyval = 0; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(mac, LOG1, FL("Sending SIR_HAL_ADD_BSS_REQ...")); +#endif + MTRACE(macTraceMsgTx(mac, session_entry->peSessionId, msg_q.type)); + ret_code = wdaPostCtrlMsg(mac, &msg_q); + if(eSIR_SUCCESS != ret_code) { + vos_mem_free(session_entry->ftPEContext.pAddBssReq); + limLog(mac, LOGE, FL("Post ADD_BSS_REQ failed reason=%X"), + ret_code); + session_entry->ftPEContext.pAddBssReq = NULL; + goto failure; + } + + session_entry->pLimMlmReassocReq = mlm_reassoc_req; + session_entry->ftPEContext.pAddBssReq = NULL; + return; + +failure: + vos_mem_free(mlm_reassoc_req); + mlm_reassoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; + mlm_reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE session Id*/ + if (session_entry) + mlm_reassoc_cnf.sessionId = session_entry->peSessionId; + limPostSmeMessage(mac, LIM_MLM_REASSOC_CNF, + (tANI_U32 *) &mlm_reassoc_cnf); +} + +/*------------------------------------------------------------------ + * + * This function handles the 11R Reassoc Req from SME + * + *------------------------------------------------------------------*/ +void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, + tpPESession psessionEntry) +{ + tANI_U8 smeSessionId = 0; + tANI_U16 transactionId = 0; + tANI_U8 chanNum = 0; + tLimMlmReassocReq *pMlmReassocReq; + tANI_U16 caps; + tANI_U32 val; + tANI_U32 teleBcnEn = 0; + tLimMlmReassocCnf mlm_reassoc_cnf = {0}; + + chanNum = psessionEntry->currentOperChannel; + limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); + psessionEntry->smeSessionId = smeSessionId; + psessionEntry->transactionId = transactionId; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOCIATING, psessionEntry, 0, 0); +#endif + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + if (NULL == psessionEntry->ftPEContext.pAddBssReq) { + limLog(pMac, LOGE, FL("pAddBssReq is NULL")); + goto end; + } + pMlmReassocReq = vos_mem_malloc(sizeof(tLimMlmReassocReq)); + if (NULL == pMlmReassocReq) { + limLog(pMac, LOGE, + FL("call to AllocateMemory failed for mlmReassocReq")); + goto end; + } + + vos_mem_copy(pMlmReassocReq->peerMacAddr, + psessionEntry->bssId, + sizeof(tSirMacAddr)); + + if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + (tANI_U32 *) &pMlmReassocReq->reassocFailureTimeout) + != eSIR_SUCCESS) { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGE, + FL("could not retrieve ReassocFailureTimeout value")); + vos_mem_free(pMlmReassocReq); + goto end; + } + + if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) { + /** + * Could not get Capabilities value + * from CFG. Log error. + */ + limLog(pMac, LOGE, FL("could not retrieve Capabilities value")); + vos_mem_free(pMlmReassocReq); + goto end; + } + pMlmReassocReq->capabilityInfo = caps; + + /* Update PE sessionId*/ + pMlmReassocReq->sessionId = psessionEntry->peSessionId; + + /* If telescopic beaconing is enabled, set listen interval + to WNI_CFG_TELE_BCN_MAX_LI + */ + if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != + eSIR_SUCCESS) { + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + vos_mem_free(pMlmReassocReq); + goto end; + } + + if (teleBcnEn) { + if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != eSIR_SUCCESS) + { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + limLog(pMac, LOGE, FL("could not retrieve ListenInterval")); + vos_mem_free(pMlmReassocReq); + goto end; + } + } + else { + if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + limLog(pMac, LOGE, FL("could not retrieve ListenInterval")); + vos_mem_free(pMlmReassocReq); + goto end; + } + } + + pMlmReassocReq->listenInterval = (tANI_U16) val; + if (limSetLinkState(pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, + lim_ft_reassoc_set_link_state_callback, + pMlmReassocReq) != eSIR_SUCCESS) { + vos_mem_free(pMlmReassocReq); + goto end; + } + return; + +end: + mlm_reassoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; + mlm_reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE session Id*/ + mlm_reassoc_cnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, + (tANI_U32 *) &mlm_reassoc_cnf); +} + +/*------------------------------------------------------------------ + * + * This function is called if preauth response is not received from the AP + * within this timeout while FT in progress + * + *------------------------------------------------------------------*/ +void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry; + + /* We have failed pre auth. We need to resume link and get back on + * home channel + */ + limLog(pMac, LOGE, FL("FT Pre-Auth Time Out!!!!")); + + if ((psessionEntry = + peFindSessionBySessionId(pMac, + pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId)) == NULL) { + limLog(pMac, LOGE, FL("Session Does not exist for given sessionID")); + return; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + /* Reset the flag to indicate preauth request session */ + psessionEntry->ftPEContext.ftPreAuthSession = VOS_FALSE; + + if (NULL == + psessionEntry->ftPEContext.pFTPreAuthReq) { + limLog(pMac,LOGE,FL("pFTPreAuthReq is NULL")); + return; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq == NULL) { + limLog(pMac, LOGE, FL("Auth Rsp might already be posted to SME and " + "ftcleanup done! sessionId:%d"), + pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); + return; + } + + /* To handle the race condition where we recieve preauth rsp after + * timer has expired. + */ + if (eANI_BOOLEAN_TRUE == + psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) { + limLog(pMac,LOGE,FL("Auth rsp already posted to SME" + " (session %p)"), psessionEntry); + 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(pMac,LOG1,FL("Auth rsp not yet posted to SME" + " (session %p)"), psessionEntry); + psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = + eANI_BOOLEAN_TRUE; + } + + /* Attempted at Pre-Auth and failed. If we are off channel. We need + * to get back to home channel + */ + limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); +} + + +/*------------------------------------------------------------------ + * + * This function is called to process the update key request from SME + * + *------------------------------------------------------------------*/ +tANI_BOOLEAN limProcessFTUpdateKey(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf ) +{ + tAddBssParams *pAddBssParams; + tSirFTUpdateKeyInfo *pKeyInfo; + tANI_U32 val = 0; + tpPESession psessionEntry; + tANI_U8 sessionId; + + /* Sanity Check */ + if( pMac == NULL || pMsgBuf == NULL ) + { + return VOS_FALSE; + } + + pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf; + + psessionEntry = + peFindSessionByBssid(pMac, pKeyInfo->bssId, &sessionId); + if (NULL == psessionEntry) + { + PELOGE(limLog( pMac, LOGE, + "%s: Unable to find session for the following bssid", + __func__);) + limPrintMacAddr( pMac, pKeyInfo->bssId, LOGE ); + return VOS_FALSE; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return VOS_FALSE; + } + + if (NULL == psessionEntry->ftPEContext.pAddBssReq) + { + // AddBss Req is NULL, save the keys to configure them later. + tpLimMlmSetKeysReq pMlmSetKeysReq = + &psessionEntry->ftPEContext.PreAuthKeyInfo.extSetStaKeyParam; + + vos_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq)); + vos_mem_copy(pMlmSetKeysReq->peerMacAddr, pKeyInfo->bssId, + sizeof(tSirMacAddr)); + pMlmSetKeysReq->sessionId = psessionEntry->peSessionId; + pMlmSetKeysReq->smesessionId = psessionEntry->smeSessionId; + pMlmSetKeysReq->edType = pKeyInfo->keyMaterial.edType; + pMlmSetKeysReq->numKeys = pKeyInfo->keyMaterial.numKeys; + vos_mem_copy((tANI_U8 *) &pMlmSetKeysReq->key, + (tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof(tSirKeys)); + + psessionEntry->ftPEContext.PreAuthKeyInfo.extSetStaKeyParamValid = TRUE; + + limLog( pMac, LOGE, FL( "pAddBssReq is NULL" )); + + if (psessionEntry->ftPEContext.pAddStaReq == NULL) + { + limLog( pMac, LOGE, FL( "pAddStaReq is NULL" )); + limSendSetStaKeyReq(pMac, pMlmSetKeysReq, 0, 0, psessionEntry, + FALSE); + psessionEntry->ftPEContext.PreAuthKeyInfo.extSetStaKeyParamValid = + FALSE; + } + } + else + { + pAddBssParams = psessionEntry->ftPEContext.pAddBssReq; + + /* Store the key information in the ADD BSS parameters */ + pAddBssParams->extSetStaKeyParamValid = 1; + pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType; + vos_mem_copy((tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key, + (tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof(tSirKeys)); + if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) + { + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); + } + + pAddBssParams->extSetStaKeyParam.singleTidRc = val; + PELOG1(limLog(pMac, LOG1, FL("Key valid %d"), + pAddBssParams->extSetStaKeyParamValid, + pAddBssParams->extSetStaKeyParam.key[0].keyLength);) + + pAddBssParams->extSetStaKeyParam.staIdx = 0; + + PELOG1(limLog(pMac, LOG1, + FL("BSSID = "MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pKeyInfo->bssId));) + + sirCopyMacAddr(pAddBssParams->extSetStaKeyParam.peerMacAddr, + pKeyInfo->bssId); + + pAddBssParams->extSetStaKeyParam.sendRsp = FALSE; + + if(pAddBssParams->extSetStaKeyParam.key[0].keyLength == 16) + { + PELOG1(limLog(pMac, LOG1, + FL("BSS key = %02X-%02X-%02X-%02X-%02X-%02X-%02X- " + "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"), + pAddBssParams->extSetStaKeyParam.key[0].key[0], + pAddBssParams->extSetStaKeyParam.key[0].key[1], + pAddBssParams->extSetStaKeyParam.key[0].key[2], + pAddBssParams->extSetStaKeyParam.key[0].key[3], + pAddBssParams->extSetStaKeyParam.key[0].key[4], + pAddBssParams->extSetStaKeyParam.key[0].key[5], + pAddBssParams->extSetStaKeyParam.key[0].key[6], + pAddBssParams->extSetStaKeyParam.key[0].key[7], + pAddBssParams->extSetStaKeyParam.key[0].key[8], + pAddBssParams->extSetStaKeyParam.key[0].key[9], + pAddBssParams->extSetStaKeyParam.key[0].key[10], + pAddBssParams->extSetStaKeyParam.key[0].key[11], + pAddBssParams->extSetStaKeyParam.key[0].key[12], + pAddBssParams->extSetStaKeyParam.key[0].key[13], + pAddBssParams->extSetStaKeyParam.key[0].key[14], + pAddBssParams->extSetStaKeyParam.key[0].key[15]);) + } + } + return TRUE; +} + +void +limFTSendAggrQosRsp(tpAniSirGlobal pMac, tANI_U8 rspReqd, + tpAggrAddTsParams aggrQosRsp, tANI_U8 smesessionId) +{ + tpSirAggrQosRsp rsp; + int i = 0; + + if (! rspReqd) + { + return; + } + + rsp = vos_mem_malloc(sizeof(tSirAggrQosRsp)); + if (NULL == rsp) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for tSirAggrQosRsp")); + return; + } + + vos_mem_set((tANI_U8 *) rsp, sizeof(*rsp), 0); + rsp->messageType = eWNI_SME_FT_AGGR_QOS_RSP; + rsp->sessionId = smesessionId; + rsp->length = sizeof(*rsp); + rsp->aggrInfo.tspecIdx = aggrQosRsp->tspecIdx; + + for( i = 0; i < SIR_QOS_NUM_AC_MAX; i++ ) + { + if( (1 << i) & aggrQosRsp->tspecIdx ) + { + rsp->aggrInfo.aggrRsp[i].status = aggrQosRsp->status[i]; + rsp->aggrInfo.aggrRsp[i].tspec = aggrQosRsp->tspec[i]; + } + } + + limSendSmeAggrQosRsp(pMac, rsp, smesessionId); + return; +} + +void limProcessFTAggrQoSRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpAggrAddTsParams pAggrQosRspMsg = NULL; + tAddTsParams addTsParam = {0}; + tpDphHashNode pSta = NULL; + tANI_U16 assocId =0; + tSirMacAddr peerMacAddr; + tANI_U8 rspReqd = 1; + tpPESession psessionEntry = NULL; + int i = 0; + + PELOG1(limLog(pMac, LOG1, FL(" Received AGGR_QOS_RSP from HAL"));) + + /* Need to process all the deferred messages enqueued since sending the + SIR_HAL_AGGR_ADD_TS_REQ */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + pAggrQosRspMsg = (tpAggrAddTsParams) (limMsg->bodyptr); + if (NULL == pAggrQosRspMsg) + { + PELOGE(limLog(pMac, LOGE, FL("NULL pAggrQosRspMsg"));) + return; + } + + psessionEntry = peFindSessionBySessionId(pMac, pAggrQosRspMsg->sessionId); + if (NULL == psessionEntry) + { + PELOGE(limLog(pMac, LOGE, + FL("Cant find session entry for %s"), __func__);) + if( pAggrQosRspMsg != NULL ) + { + vos_mem_free(pAggrQosRspMsg); + } + return; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + return; + } + + for( i = 0; i < HAL_QOS_NUM_AC_MAX; i++ ) + { + if((((1 << i) & pAggrQosRspMsg->tspecIdx)) && + (pAggrQosRspMsg->status[i] != eHAL_STATUS_SUCCESS)) + { + /* send DELTS to the station */ + sirCopyMacAddr(peerMacAddr,psessionEntry->bssId); + + addTsParam.staIdx = pAggrQosRspMsg->staIdx; + addTsParam.sessionId = pAggrQosRspMsg->sessionId; + addTsParam.tspec = pAggrQosRspMsg->tspec[i]; + addTsParam.tspecIdx = pAggrQosRspMsg->tspecIdx; + + limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, + &addTsParam.tspec.tsinfo, + &addTsParam.tspec, psessionEntry); + + pSta = dphLookupAssocId(pMac, addTsParam.staIdx, &assocId, + &psessionEntry->dph.dphHashTable); + if (pSta != NULL) + { + limAdmitControlDeleteTS(pMac, assocId, &addTsParam.tspec.tsinfo, + NULL, (tANI_U8 *)&addTsParam.tspecIdx); + } + } + } + + /* Send the Aggr QoS response to SME */ + limFTSendAggrQosRsp(pMac, rspReqd, pAggrQosRspMsg, + psessionEntry->smeSessionId); + if( pAggrQosRspMsg != NULL ) + { + vos_mem_free(pAggrQosRspMsg); + } + return; +} + +tSirRetStatus +limProcessFTAggrQosReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf ) +{ + tSirMsgQ msg; + tSirAggrQosReq * aggrQosReq = (tSirAggrQosReq *)pMsgBuf; + tpAggrAddTsParams pAggrAddTsParam; + tpPESession psessionEntry = NULL; + tpLimTspecInfo tspecInfo; + tANI_U8 ac; + tpDphHashNode pSta; + tANI_U16 aid; + tANI_U8 sessionId; + int i; + + pAggrAddTsParam = vos_mem_malloc(sizeof(tAggrAddTsParams)); + if (NULL == pAggrAddTsParam) + { + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory() failed"));) + return eSIR_MEM_ALLOC_FAILED; + } + + psessionEntry = peFindSessionByBssid(pMac, aggrQosReq->bssId, &sessionId); + + if (psessionEntry == NULL) { + PELOGE(limLog(pMac, LOGE, FL("psession Entry Null for sessionId = %d"), + aggrQosReq->sessionId);) + vos_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) +#endif + vos_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + + pSta = dphLookupHashEntry(pMac, aggrQosReq->bssId, &aid, + &psessionEntry->dph.dphHashTable); + if (pSta == NULL) + { + PELOGE(limLog(pMac, LOGE, + FL("Station context not found - ignoring AddTsRsp"));) + vos_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + + vos_mem_set((tANI_U8 *)pAggrAddTsParam, + sizeof(tAggrAddTsParams), 0); + pAggrAddTsParam->staIdx = psessionEntry->staId; + // Fill in the sessionId specific to PE + pAggrAddTsParam->sessionId = sessionId; + pAggrAddTsParam->tspecIdx = aggrQosReq->aggrInfo.tspecIdx; + + for( i = 0; i < HAL_QOS_NUM_AC_MAX; i++ ) + { + if (aggrQosReq->aggrInfo.tspecIdx & (1<aggrInfo.aggrAddTsInfo[i].tspec; + /* Since AddTS response was successful, check for the PSB flag + * and directional flag inside the TS Info field. + * An AC is trigger enabled AC if the PSB subfield is set to 1 + * in the uplink direction. + * An AC is delivery enabled AC if the PSB subfield is set to 1 + * in the downlink direction. + * An AC is trigger and delivery enabled AC if the PSB subfield + * is set to 1 in the bi-direction field. + */ + if(!pMac->psOffloadEnabled) + { + if (pTspec->tsinfo.traffic.psb == 1) + { + limSetTspecUapsdMask(pMac, &pTspec->tsinfo, SET_UAPSD_MASK); + } + else + { + limSetTspecUapsdMask(pMac, &pTspec->tsinfo, + CLEAR_UAPSD_MASK); + } + /* + * ADDTS success, so AC is now admitted. + * We shall now use the default + * EDCA parameters as advertised by AP and + * send the updated EDCA params + * to HAL. + */ + ac = upToAc(pTspec->tsinfo.traffic.userPrio); + if(pTspec->tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + } + else if(pTspec->tsinfo.traffic.direction == + SIR_MAC_DIRECTION_DNLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } + else if(pTspec->tsinfo.traffic.direction == + SIR_MAC_DIRECTION_BIDIR) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } + } + else + { + if (pTspec->tsinfo.traffic.psb == 1) + { + limSetTspecUapsdMaskPerSession(pMac, psessionEntry, + &pTspec->tsinfo, + SET_UAPSD_MASK); + } + else + { + limSetTspecUapsdMaskPerSession(pMac, psessionEntry, + &pTspec->tsinfo, + CLEAR_UAPSD_MASK); + } + /* + * ADDTS success, so AC is now admitted. + * We shall now use the default + * EDCA parameters as advertised by AP and + * send the updated EDCA params + * to HAL. + */ + ac = upToAc(pTspec->tsinfo.traffic.userPrio); + if(pTspec->tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + } + else if(pTspec->tsinfo.traffic.direction == + SIR_MAC_DIRECTION_DNLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } + else if(pTspec->tsinfo.traffic.direction == + SIR_MAC_DIRECTION_BIDIR) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } + } + + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, + psessionEntry); + + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pSta->bssId); + + if(eSIR_SUCCESS != limTspecAdd(pMac, pSta->staAddr, pSta->assocId, + pTspec, 0, &tspecInfo)) + { + PELOGE(limLog(pMac, LOGE, + FL("Adding entry in lim Tspec Table failed "));) + pMac->lim.gLimAddtsSent = false; + vos_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + + pAggrAddTsParam->tspec[i] = + aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec; + } + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (!pMac->roam.configParam.isRoamOffloadEnabled || + (pMac->roam.configParam.isRoamOffloadEnabled && + !psessionEntry->is11Rconnection)) +#endif + { + msg.type = WDA_AGGR_QOS_REQ; + msg.bodyptr = pAggrAddTsParam; + msg.bodyval = 0; + + /* We need to defer any incoming messages until we get a + * WDA_AGGR_QOS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msg.type)); + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed"));) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + else + { + /* Implies it is a LFR3.0 based 11r connection + * so donot send add ts request to fimware since it + * already has the RIC IEs */ + + /* Send the Aggr QoS response to SME */ + limFTSendAggrQosRsp(pMac, true, pAggrAddTsParam, + psessionEntry->smeSessionId); + if( pAggrAddTsParam != NULL ) + { + vos_mem_free(pAggrAddTsParam); + } + } +#endif + + return eSIR_SUCCESS; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c new file mode 100644 index 000000000000..839783c90027 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c @@ -0,0 +1,1810 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file limIbssPeerMgmt.cc contains the utility functions + * LIM uses to maintain peers in IBSS. + * Author: Chandra Modumudi + * Date: 03/12/04 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#include "palTypes.h" +#include "aniGlobal.h" +#include "sirCommon.h" +#include "wniCfgSta.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limStaHashApi.h" +#include "schApi.h" // schSetFixedBeaconFields for IBSS coalesce +#include "limSecurityUtils.h" +#include "limSendMessages.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "limIbssPeerMgmt.h" + + +/** + * ibss_peer_find + * + *FUNCTION: + * This function is called while adding a context at + * DPH for a peer in IBSS. + * If peer is found in the list, capabilities from the + * returned BSS description are used at DPH node. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param macAddr - MAC address of the peer + * + * @return Pointer to peer node if found, else NULL + */ + +static tLimIbssPeerNode * +ibss_peer_find( + tpAniSirGlobal pMac, + tSirMacAddr macAddr) +{ + tLimIbssPeerNode *pTempNode = pMac->lim.gLimIbssPeerList; + + while (pTempNode != NULL) + { + if (vos_mem_compare((tANI_U8 *) macAddr, + (tANI_U8 *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr))) + break; + pTempNode = pTempNode->next; + } + return pTempNode; +} /*** end ibss_peer_find() ***/ + +/** + * ibss_peer_add + * + *FUNCTION: + * This is called on a STA in IBSS upon receiving Beacon/ + * Probe Response from a peer. + * + *LOGIC: + * Node is always added to the front of the list + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pPeerNode - Pointer to peer node to be added to the list. + * + * @return None + */ + +static tSirRetStatus +ibss_peer_add(tpAniSirGlobal pMac, tLimIbssPeerNode *pPeerNode) +{ +#ifdef ANI_SIR_IBSS_PEER_CACHING + tANI_U32 numIbssPeers = (2 * pMac->lim.maxStation); + + if (pMac->lim.gLimNumIbssPeers >= numIbssPeers) + { + /** + * Reached max number of peers to be maintained. + * Delete last entry & add new entry at the beginning. + */ + tLimIbssPeerNode *pTemp, *pPrev; + pTemp = pPrev = pMac->lim.gLimIbssPeerList; + while (pTemp->next != NULL) + { + pPrev = pTemp; + pTemp = pTemp->next; + } + if(pTemp->beacon) + { + vos_mem_free(pTemp->beacon); + } + + vos_mem_free(pTemp); + pPrev->next = NULL; + } + else +#endif + pMac->lim.gLimNumIbssPeers++; + + pPeerNode->next = pMac->lim.gLimIbssPeerList; + pMac->lim.gLimIbssPeerList = pPeerNode; + + return eSIR_SUCCESS; + +} /*** end limAddIbssPeerToList() ***/ + +/** + * ibss_peer_collect + * + *FUNCTION: + * This is called to collect IBSS peer information + * from received Beacon/Probe Response frame from it. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pBeacon - Parsed Beacon Frame structure + * @param pBD - Pointer to received BD + * @param pPeer - Pointer to IBSS peer node + * + * @return None + */ + +static void +ibss_peer_collect( + tpAniSirGlobal pMac, + tpSchBeaconStruct pBeacon, + tpSirMacMgmtHdr pHdr, + tLimIbssPeerNode *pPeer, + tpPESession psessionEntry) +{ + vos_mem_copy(pPeer->peerMacAddr, pHdr->sa, sizeof(tSirMacAddr)); + + pPeer->capabilityInfo = pBeacon->capabilityInfo; + pPeer->extendedRatesPresent = pBeacon->extendedRatesPresent; + pPeer->edcaPresent = pBeacon->edcaPresent; + pPeer->wmeEdcaPresent = pBeacon->wmeEdcaPresent; + pPeer->wmeInfoPresent = pBeacon->wmeInfoPresent; + + if (pBeacon->IBSSParams.present) + { + pPeer->atimIePresent = pBeacon->IBSSParams.present; + pPeer->peerAtimWindowLength = pBeacon->IBSSParams.atim; + } + + if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) && + (pBeacon->HTCaps.present)) + { + pPeer->htCapable = pBeacon->HTCaps.present; + vos_mem_copy((tANI_U8 *)pPeer->supportedMCSSet, + (tANI_U8 *)pBeacon->HTCaps.supportedMCSSet, + sizeof(pPeer->supportedMCSSet)); + pPeer->htGreenfield = (tANI_U8)pBeacon->HTCaps.greenField; + pPeer->htSupportedChannelWidthSet = ( tANI_U8 ) pBeacon->HTCaps.supportedChannelWidthSet; + pPeer->htMIMOPSState = (tSirMacHTMIMOPowerSaveState)pBeacon->HTCaps.mimoPowerSave; + pPeer->htMaxAmsduLength = ( tANI_U8 ) pBeacon->HTCaps.maximalAMSDUsize; + pPeer->htAMpduDensity = pBeacon->HTCaps.mpduDensity; + pPeer->htDsssCckRate40MHzSupport = (tANI_U8)pBeacon->HTCaps.dsssCckMode40MHz; + pPeer->htShortGI20Mhz = (tANI_U8)pBeacon->HTCaps.shortGI20MHz; + pPeer->htShortGI40Mhz = (tANI_U8)pBeacon->HTCaps.shortGI40MHz; + pPeer->htMaxRxAMpduFactor = pBeacon->HTCaps.maxRxAMPDUFactor; + pPeer->htSecondaryChannelOffset = pBeacon->HTInfo.secondaryChannelOffset; + pPeer->htLdpcCapable = (tANI_U8)pBeacon->HTCaps.advCodingCap; + } + + /* Collect peer VHT capabilities based on the received beacon from the peer */ +#ifdef WLAN_FEATURE_11AC + if ( pBeacon->VHTCaps.present ) + { + pPeer->vhtSupportedChannelWidthSet = pBeacon->VHTOperation.chanWidth; + pPeer->vhtCapable = pBeacon->VHTCaps.present; + + // Collect VHT capabilities from beacon + vos_mem_copy((tANI_U8 *) &pPeer->VHTCaps, + (tANI_U8 *) &pBeacon->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } +#endif + pPeer->erpIePresent = pBeacon->erpPresent; + + vos_mem_copy((tANI_U8 *) &pPeer->supportedRates, + (tANI_U8 *) &pBeacon->supportedRates, + pBeacon->supportedRates.numRates + 1); + if (pPeer->extendedRatesPresent) + vos_mem_copy((tANI_U8 *) &pPeer->extendedRates, + (tANI_U8 *) &pBeacon->extendedRates, + pBeacon->extendedRates.numRates + 1); + else + pPeer->extendedRates.numRates = 0; + + pPeer->next = NULL; +} /*** end ibss_peer_collect() ***/ + +// handle change in peer qos/wme capabilities +static void +ibss_sta_caps_update( + tpAniSirGlobal pMac, + tLimIbssPeerNode *pPeerNode, + tpPESession psessionEntry) +{ + tANI_U16 peerIdx; + tpDphHashNode pStaDs; + + pPeerNode->beaconHBCount++; //Update beacon count. + + // if the peer node exists, update its qos capabilities + if ((pStaDs = dphLookupHashEntry(pMac, pPeerNode->peerMacAddr, &peerIdx, &psessionEntry->dph.dphHashTable)) == NULL) + return; + + + //Update HT Capabilities + if(IS_DOT11_MODE_HT(psessionEntry->dot11mode)) + { + pStaDs->mlmStaContext.htCapability = pPeerNode->htCapable; + if (pPeerNode->htCapable) + { + pStaDs->htGreenfield = pPeerNode->htGreenfield; + pStaDs->htSupportedChannelWidthSet = + pPeerNode->htSupportedChannelWidthSet; + pStaDs->htSecondaryChannelOffset = + pPeerNode->htSecondaryChannelOffset; + pStaDs->htMIMOPSState = pPeerNode->htMIMOPSState; + pStaDs->htMaxAmsduLength = pPeerNode->htMaxAmsduLength; + pStaDs->htAMpduDensity = pPeerNode->htAMpduDensity; + pStaDs->htDsssCckRate40MHzSupport = pPeerNode->htDsssCckRate40MHzSupport; + pStaDs->htShortGI20Mhz = pPeerNode->htShortGI20Mhz; + pStaDs->htShortGI40Mhz = pPeerNode->htShortGI40Mhz; + pStaDs->htMaxRxAMpduFactor = pPeerNode->htMaxRxAMpduFactor; + // In the future, may need to check for "delayedBA" + // For now, it is IMMEDIATE BA only on ALL TID's + pStaDs->baPolicyFlag = 0xFF; + pStaDs->htLdpcCapable = pPeerNode->htLdpcCapable; + } + } +#ifdef WLAN_FEATURE_11AC + if ( IS_DOT11_MODE_VHT(psessionEntry->dot11mode) ) + { + pStaDs->mlmStaContext.vhtCapability = pPeerNode->vhtCapable; + if ( pPeerNode->vhtCapable ) + { + pStaDs->vhtSupportedChannelWidthSet = pPeerNode->vhtSupportedChannelWidthSet; + + // If in 11AC mode and if session requires 11AC mode, consider peer's + // max AMPDU length factor + pStaDs->htMaxRxAMpduFactor = pPeerNode->VHTCaps.maxAMPDULenExp; + pStaDs->vhtLdpcCapable = (tANI_U8)pPeerNode->VHTCaps.ldpcCodingCap; + } + } +#endif + + // peer is 11e capable but is not 11e enabled yet + // some STA's when joining Airgo IBSS, assert qos capability even when + // they don't suport qos. however, they do not include the edca parameter + // set. so let's check for edcaParam in addition to the qos capability + if (pPeerNode->capabilityInfo.qos && (psessionEntry->limQosEnabled) && pPeerNode->edcaPresent) + { + pStaDs->qosMode = 1; + pStaDs->wmeEnabled = 0; + if (! pStaDs->lleEnabled) + { + pStaDs->lleEnabled = 1; + //dphSetACM(pMac, pStaDs); + } + return; + } + // peer is not 11e capable now but was 11e enabled earlier + else if (pStaDs->lleEnabled) + { + pStaDs->qosMode = 0; + pStaDs->lleEnabled = 0; + } + + // peer is wme capable but is not wme enabled yet + if (pPeerNode->wmeInfoPresent && psessionEntry->limWmeEnabled) + { + pStaDs->qosMode = 1; + pStaDs->lleEnabled = 0; + if (! pStaDs->wmeEnabled) + { + pStaDs->wmeEnabled = 1; + } + return; + } + /* When the peer device supports EDCA parameters, then we were not + considering. Added this code when we saw that one of the Peer Device + was advertising WMM param where we were not honouring that. CR# 210756 + */ + if (pPeerNode->wmeEdcaPresent && psessionEntry->limWmeEnabled) { + pStaDs->qosMode = 1; + pStaDs->lleEnabled = 0; + if (! pStaDs->wmeEnabled) { + pStaDs->wmeEnabled = 1; + } + return; + } + + // peer is not wme capable now but was wme enabled earlier + else if (pStaDs->wmeEnabled) + { + pStaDs->qosMode = 0; + pStaDs->wmeEnabled = 0; + } + +} + +static void +ibss_sta_rates_update( + tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tLimIbssPeerNode *pPeer, + tpPESession psessionEntry) +{ +#ifdef WLAN_FEATURE_11AC + limPopulateMatchingRateSet(pMac, pStaDs, &pPeer->supportedRates, + &pPeer->extendedRates, pPeer->supportedMCSSet, + psessionEntry, &pPeer->VHTCaps); +#else + // Populate supported rateset + limPopulateMatchingRateSet(pMac, pStaDs, &pPeer->supportedRates, + &pPeer->extendedRates, pPeer->supportedMCSSet, + psessionEntry); +#endif + + pStaDs->mlmStaContext.capabilityInfo = pPeer->capabilityInfo; +} /*** end ibss_sta_info_update() ***/ + +/** + * ibss_sta_info_update + * + *FUNCTION: + * This is called to program SW context for peer in IBSS. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to DPH node + * @param pPeer - Pointer to IBSS peer node + * + * @return None + */ + +static void +ibss_sta_info_update( + tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tLimIbssPeerNode *pPeer, + tpPESession psessionEntry) +{ + pStaDs->staType = STA_ENTRY_PEER; + ibss_sta_caps_update(pMac, pPeer,psessionEntry); + ibss_sta_rates_update(pMac, pStaDs, pPeer,psessionEntry); +} /*** end ibss_sta_info_update() ***/ + +static void +ibss_coalesce_free( + tpAniSirGlobal pMac) +{ + if (pMac->lim.ibssInfo.pHdr != NULL) + vos_mem_free(pMac->lim.ibssInfo.pHdr); + if (pMac->lim.ibssInfo.pBeacon != NULL) + vos_mem_free(pMac->lim.ibssInfo.pBeacon); + + pMac->lim.ibssInfo.pHdr = NULL; + pMac->lim.ibssInfo.pBeacon = NULL; +} + +/* + * save the beacon params for use when adding the bss + */ +static void +ibss_coalesce_save( + tpAniSirGlobal pMac, + tpSirMacMgmtHdr pHdr, + tpSchBeaconStruct pBeacon) +{ + // get rid of any saved info + ibss_coalesce_free(pMac); + + pMac->lim.ibssInfo.pHdr = vos_mem_malloc(sizeof(*pHdr)); + if (NULL == pMac->lim.ibssInfo.pHdr) + { + PELOGE(limLog(pMac, LOGE, FL("ibbs-save: Failed malloc pHdr"));) + return; + } + pMac->lim.ibssInfo.pBeacon = vos_mem_malloc(sizeof(*pBeacon)); + if (NULL == pMac->lim.ibssInfo.pBeacon) + { + PELOGE(limLog(pMac, LOGE, FL("ibbs-save: Failed malloc pBeacon"));) + ibss_coalesce_free(pMac); + return; + } + + vos_mem_copy(pMac->lim.ibssInfo.pHdr, pHdr, sizeof(*pHdr)); + vos_mem_copy(pMac->lim.ibssInfo.pBeacon, pBeacon, sizeof(*pBeacon)); +} + +/* + * tries to add a new entry to dph hash node + * if necessary, an existing entry is eliminated + */ +static tSirRetStatus +ibss_dph_entry_add( + tpAniSirGlobal pMac, + tSirMacAddr peerAddr, + tpDphHashNode *ppSta, + tpPESession psessionEntry) +{ + tANI_U16 peerIdx; + tpDphHashNode pStaDs; + + *ppSta = NULL; + + pStaDs = dphLookupHashEntry(pMac, peerAddr, &peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + /* Trying to add context for already existing STA in IBSS */ + PELOGE(limLog(pMac, LOGE, FL("STA exists already "));) + limPrintMacAddr(pMac, peerAddr, LOGE); + return eSIR_FAILURE; + } + + /** + * Assign an AID, delete context existing with that + * AID and then add an entry to hash table maintained + * by DPH module. + */ + peerIdx = limAssignPeerIdx(pMac, psessionEntry); + + pStaDs = dphGetHashEntry(pMac, peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs) + { + (void) limDelSta(pMac, pStaDs, false /*asynchronous*/,psessionEntry); + limDeleteDphHashEntry(pMac, pStaDs->staAddr, peerIdx,psessionEntry); + } + + pStaDs = dphAddHashEntry(pMac, peerAddr, peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + // Could not add hash table entry + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for peerIdx/aid=%d MACaddr:"), peerIdx);) + limPrintMacAddr(pMac, peerAddr, LOGE); + return eSIR_FAILURE; + } + + *ppSta = pStaDs; + return eSIR_SUCCESS; +} + +// send a status change notification +static void +ibss_status_chg_notify( + tpAniSirGlobal pMac, + tSirMacAddr peerAddr, + tANI_U16 staIndex, + tANI_U8 ucastSig, + tANI_U8 bcastSig, + tANI_U16 status, + tANI_U8 sessionId) +{ + + tLimIbssPeerNode *peerNode; + tANI_U8 *beacon = NULL; + tANI_U16 bcnLen = 0; + + + peerNode = ibss_peer_find(pMac,peerAddr); + if(peerNode != NULL) + { + if(peerNode->beacon == NULL) peerNode->beaconLen = 0; + beacon = peerNode->beacon; + bcnLen = peerNode->beaconLen; + peerNode->beacon = NULL; + peerNode->beaconLen = 0; + } + + limSendSmeIBSSPeerInd(pMac,peerAddr, staIndex, ucastSig, bcastSig, + beacon, bcnLen, status, sessionId); + + if(beacon != NULL) + { + vos_mem_free(beacon); + } +} + + +static void +ibss_bss_add( + tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tLimMlmStartReq mlmStartReq; + tANI_U32 cfg; + tpSirMacMgmtHdr pHdr = (tpSirMacMgmtHdr) pMac->lim.ibssInfo.pHdr; + tpSchBeaconStruct pBeacon = (tpSchBeaconStruct) pMac->lim.ibssInfo.pBeacon; + tANI_U8 numExtRates = 0; + + if ((pHdr == NULL) || (pBeacon == NULL)) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to add BSS (no cached BSS info)"));) + return; + } + + vos_mem_copy(psessionEntry->bssId, pHdr->bssId, + sizeof(tSirMacAddr)); + + sirCopyMacAddr(pHdr->bssId,psessionEntry->bssId); + + /* Copy beacon interval from sessionTable */ + cfg = psessionEntry->beaconParams.beaconInterval; + if (cfg != pBeacon->beaconInterval) + psessionEntry->beaconParams.beaconInterval = pBeacon->beaconInterval; + + /* This function ibss_bss_add (and hence the below code) is only called during ibss coalescing. We need to + * adapt to peer's capability with respect to short slot time. Changes have been made to limApplyConfiguration() + * so that the IBSS doesnt blindly start with short slot = 1. If IBSS start is part of coalescing then it will adapt + * to peer's short slot using code below. + */ + /* If cfg is already set to current peer's capability then no need to set it again */ + if (psessionEntry->shortSlotTimeSupported != pBeacon->capabilityInfo.shortSlotTime) + { + psessionEntry->shortSlotTimeSupported = pBeacon->capabilityInfo.shortSlotTime; + } + vos_mem_copy((tANI_U8 *) &psessionEntry->pLimStartBssReq->operationalRateSet, + (tANI_U8 *) &pBeacon->supportedRates, + pBeacon->supportedRates.numRates); + + /** + * WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET CFG needs to be reset, when + * there is no extended rate IE present in beacon. This is especially important when + * supportedRateSet IE contains all the extended rates as well and STA decides to coalesce. + * In this IBSS coalescing scenario LIM will tear down the BSS and Add a new one. So LIM needs to + * reset this CFG, just in case CSR originally had set this CFG when IBSS was started from the local profile. + * If IBSS was started by CSR from the BssDescription, then it would reset this CFG before StartBss is issued. + * The idea is that the count of OpRateSet and ExtendedOpRateSet rates should not be more than 12. + */ + + if(pBeacon->extendedRatesPresent) + numExtRates = pBeacon->extendedRates.numRates; + if (cfgSetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + (tANI_U8 *) &pBeacon->extendedRates.rate, numExtRates) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not update ExtendedOperRateset at CFG")); + return; + } + + + /* + * Each IBSS node will advertise its own HT Capabilities instead of adapting to the Peer's capabilities + * If we don't do this then IBSS may not go back to full capabilities when the STA with lower capabilities + * leaves the IBSS. e.g. when non-CB STA joins an IBSS and then leaves, the IBSS will be stuck at non-CB mode + * even though all the nodes are capable of doing CB. + * so it is decided to leave the self HT capabilties intact. This may change if some issues are found in interop. + */ + vos_mem_set((void *) &mlmStartReq, sizeof(mlmStartReq), 0); + + vos_mem_copy(mlmStartReq.bssId, pHdr->bssId, sizeof(tSirMacAddr)); + mlmStartReq.rateSet.numRates = psessionEntry->pLimStartBssReq->operationalRateSet.numRates; + vos_mem_copy(&mlmStartReq.rateSet.rate[0], + &psessionEntry->pLimStartBssReq->operationalRateSet.rate[0], + mlmStartReq.rateSet.numRates); + mlmStartReq.bssType = eSIR_IBSS_MODE; + mlmStartReq.beaconPeriod = pBeacon->beaconInterval; + mlmStartReq.nwType = psessionEntry->pLimStartBssReq->nwType; //psessionEntry->nwType is also OK???? + mlmStartReq.htCapable = psessionEntry->htCapability; + mlmStartReq.htOperMode = pMac->lim.gHTOperMode; + mlmStartReq.dualCTSProtection = pMac->lim.gHTDualCTSProtection; + mlmStartReq.txChannelWidthSet = psessionEntry->htRecommendedTxWidthSet; + + /* reading the channel num from session Table */ + mlmStartReq.channelNumber = psessionEntry->currentOperChannel; + + mlmStartReq.cbMode = psessionEntry->pLimStartBssReq->cbMode; + + // Copy the SSID for RxP filtering based on SSID. + vos_mem_copy((tANI_U8 *) &mlmStartReq.ssId, + (tANI_U8 *) &psessionEntry->pLimStartBssReq->ssId, + psessionEntry->pLimStartBssReq->ssId.length + 1); + + PELOG1(limLog(pMac, LOG1, FL("invoking ADD_BSS as part of coalescing!"));) + if (limMlmAddBss(pMac, &mlmStartReq,psessionEntry) != eSIR_SME_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("AddBss failure"));) + return; + } + + // Update fields in Beacon + if (schSetFixedBeaconFields(pMac,psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("*** Unable to set fixed Beacon fields ***"));) + return; + } + +} + + + +/* delete the current BSS */ +static void +ibss_bss_delete( + tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tSirRetStatus status; + PELOGW(limLog(pMac, LOGW, FL("Initiating IBSS Delete BSS"));) + if (psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) + { + limLog(pMac, LOGW, FL("Incorrect LIM MLM state for delBss (%d)"), + psessionEntry->limMlmState); + return; + } + status = limDelBss(pMac, NULL, psessionEntry->bssIdx, psessionEntry); + if (status != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d"), psessionEntry->bssIdx);) +} + +/** + * limIbssInit + * + *FUNCTION: + * This function is called while starting an IBSS + * to initialize list used to maintain IBSS peers. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limIbssInit( + tpAniSirGlobal pMac) +{ + pMac->lim.gLimIbssCoalescingHappened = 0; + pMac->lim.gLimIbssPeerList = NULL; + pMac->lim.gLimNumIbssPeers = 0; + + // ibss info - params for which ibss to join while coalescing + vos_mem_set(&pMac->lim.ibssInfo, sizeof(tAniSirLimIbss), 0); +} /*** end limIbssInit() ***/ + +/** + * limIbssDeleteAllPeers + * + *FUNCTION: + * This function is called to delete all peers. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void limIbssDeleteAllPeers( tpAniSirGlobal pMac ,tpPESession psessionEntry) +{ + tLimIbssPeerNode *pCurrNode, *pTempNode; + tpDphHashNode pStaDs; + tANI_U16 peerIdx; + + pCurrNode = pTempNode = pMac->lim.gLimIbssPeerList; + + while (pCurrNode != NULL) + { + if (!pMac->lim.gLimNumIbssPeers) + { + limLog(pMac, LOGP, + FL("Number of peers in the list is zero and node present")); + return; + } + /* Delete the dph entry for the station + * Since it is called to remove all peers, just delete from dph, + * no need to do any beacon related params i.e., dont call limDeleteDphHashEntry + */ + pStaDs = dphLookupHashEntry(pMac, pCurrNode->peerMacAddr, &peerIdx, &psessionEntry->dph.dphHashTable); + if( pStaDs ) + { + + ibss_status_chg_notify( pMac, pCurrNode->peerMacAddr, pStaDs->staIndex, + pStaDs->ucUcastSig, pStaDs->ucBcastSig, + eWNI_SME_IBSS_PEER_DEPARTED_IND, psessionEntry->smeSessionId ); + limReleasePeerIdx(pMac, peerIdx, psessionEntry); + dphDeleteHashEntry(pMac, pStaDs->staAddr, peerIdx, &psessionEntry->dph.dphHashTable); + } + + pTempNode = pCurrNode->next; + + /* TODO :Sessionize this code */ + /* Fix CR 227642: PeerList should point to the next node since the current node is being + * freed in the next line. In ibss_peerfind in ibss_status_chg_notify above, we use this + * peer list to find the next peer. So this list needs to be updated with the no of peers left + * after each iteration in this while loop since one by one peers are deleted (freed) in this + * loop causing the lim.gLimIbssPeerList to point to some freed memory. + */ + pMac->lim.gLimIbssPeerList = pTempNode; + + if(pCurrNode->beacon) + { + vos_mem_free(pCurrNode->beacon); + } + vos_mem_free(pCurrNode); + if (pMac->lim.gLimNumIbssPeers > 0) // be paranoid + pMac->lim.gLimNumIbssPeers--; + pCurrNode = pTempNode; + } + + if (pMac->lim.gLimNumIbssPeers) + limLog(pMac, LOGP, FL("Number of peers[%d] in the list is non-zero"), + pMac->lim.gLimNumIbssPeers); + + pMac->lim.gLimNumIbssPeers = 0; + pMac->lim.gLimIbssPeerList = NULL; + +} +/** + * limIbssDelete + * + *FUNCTION: + * This function is called while tearing down an IBSS. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limIbssDelete( + tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + limIbssDeleteAllPeers(pMac,psessionEntry); + + ibss_coalesce_free(pMac); +} /*** end limIbssDelete() ***/ + +/** ------------------------------------------------------------- +\fn limIbssSetProtection +\brief Decides all the protection related information. +\ +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +static void +limIbssSetProtection(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + + if(!pMac->lim.cfgProtection.fromllb) + { + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) + return; + } + + if (enable) + { + psessionEntry->gLim11bParams.protectionEnabled = true; + if(false == psessionEntry->beaconParams.llbCoexist/*pMac->lim.llbCoexist*/) + { + PELOGE(limLog(pMac, LOGE, FL("=> IBSS: Enable Protection "));) + pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + } + else if (true == psessionEntry->beaconParams.llbCoexist/*pMac->lim.llbCoexist*/) + { + psessionEntry->gLim11bParams.protectionEnabled = false; + PELOGE(limLog(pMac, LOGE, FL("===> IBSS: Disable protection "));) + pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + return; +} + + +/** ------------------------------------------------------------- +\fn limIbssUpdateProtectionParams +\brief Decides all the protection related information. +\ +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +static void +limIbssUpdateProtectionParams(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, tLimProtStaCacheType protStaCacheType, + tpPESession psessionEntry) +{ + tANI_U32 i; + + PELOG1(limLog(pMac,LOG1, FL("A STA is associated:")); + limLog(pMac,LOG1, FL("Addr : ")); + limPrintMacAddr(pMac, peerMacAddr, LOG1);) + + for (i=0; ilim.protStaCache[i].active) + { + PELOG1(limLog(pMac, LOG1, FL("Addr: "));) + PELOG1(limPrintMacAddr(pMac, pMac->lim.protStaCache[i].addr, LOG1);) + + if (vos_mem_compare(pMac->lim.protStaCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) + { + PELOG1(limLog(pMac, LOG1, FL("matching cache entry at %d already active."), i);) + return; + } + } + } + + for (i=0; ilim.protStaCache[i].active) + break; + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) + { + PELOGE(limLog(pMac, LOGE, FL("No space in ProtStaCache"));) + return; + } + + vos_mem_copy(pMac->lim.protStaCache[i].addr, + peerMacAddr, + sizeof(tSirMacAddr)); + + pMac->lim.protStaCache[i].protStaCacheType = protStaCacheType; + pMac->lim.protStaCache[i].active = true; + if(eLIM_PROT_STA_CACHE_TYPE_llB == protStaCacheType) + { + psessionEntry->gLim11bParams.numSta++; + } + else if(eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) + { + psessionEntry->gLim11gParams.numSta++; + } +} + + +/** ------------------------------------------------------------- +\fn limIbssDecideProtection +\brief Decides all the protection related information. +\ +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +static void +limIbssDecideProtection(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + tANI_U32 phyMode; + tLimProtStaCacheType protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_INVALID; + + pBeaconParams->paramChangeBitmap = 0; + + if(NULL == pStaDs) + { + PELOGE(limLog(pMac, LOGE, FL("pStaDs is NULL"));) + return; + } + + limGetRfBand(pMac, &rfBand, psessionEntry); + if(SIR_BAND_2_4_GHZ== rfBand) + { + limGetPhyMode(pMac, &phyMode, psessionEntry); + + //We are 11G or 11n. Check if we need protection from 11b Stations. + if ((phyMode == WNI_CFG_PHY_MODE_11G) || (psessionEntry->htCapability)) + { + /* As we found in the past, it is possible that a 11n STA sends + * Beacon with HT IE but not ERP IE. So the absense of ERP IE + * in the Beacon is not enough to conclude that STA is 11b. + */ + if ((pStaDs->erpEnabled == eHAL_CLEAR) && + (!pStaDs->mlmStaContext.htCapability)) + { + protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; + PELOGE(limLog(pMac, LOGE, FL("Enable protection from 11B"));) + limIbssSetProtection(pMac, true, pBeaconParams,psessionEntry); + } + } + } + limIbssUpdateProtectionParams(pMac, pStaDs->staAddr, protStaCacheType, psessionEntry); + return; +} + +/** + * limIbssPeerFind() + * + *FUNCTION: + * This function is called while adding a context at + * DPH for a peer in IBSS. + * If peer is found in the list, capabilities from the + * returned BSS description are used at DPH node. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param macAddr - MAC address of the peer + * + * @return Pointer to peer node if found, else NULL + */ +tLimIbssPeerNode* limIbssPeerFind(tpAniSirGlobal pMac, tSirMacAddr macAddr) +{ + return ibss_peer_find(pMac, macAddr); +} + +/** + * limIbssStaAdd() + * + *FUNCTION: + * This function is called to add an STA context in IBSS role + * whenever a data frame is received from/for a STA that failed + * hash lookup at DPH. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param peerAdddr MAC address of the peer being added + * @return retCode Indicates success or failure return code + * @return + */ + +tSirRetStatus +limIbssStaAdd( + tpAniSirGlobal pMac, + void *pBody, + tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tpDphHashNode pStaDs; + tLimIbssPeerNode *pPeerNode; + tLimMlmStates prevState; + tSirMacAddr *pPeerAddr = (tSirMacAddr *) pBody; + tUpdateBeaconParams beaconParams; + + vos_mem_set((tANI_U8 *) &beaconParams, sizeof(tUpdateBeaconParams), 0); + + if (pBody == 0) + { + PELOGE(limLog(pMac, LOGE, FL("Invalid IBSS AddSta"));) + return eSIR_FAILURE; + } + + PELOGE(limLog(pMac, LOGE, FL("Rx Add-Ibss-Sta for MAC:"));) + limPrintMacAddr(pMac, *pPeerAddr, LOGE); + + pPeerNode = ibss_peer_find(pMac, *pPeerAddr); + if (NULL != pPeerNode) + { + retCode = ibss_dph_entry_add(pMac, *pPeerAddr, &pStaDs, psessionEntry); + if (eSIR_SUCCESS == retCode) + { + prevState = pStaDs->mlmStaContext.mlmState; + pStaDs->erpEnabled = pPeerNode->erpIePresent; + + ibss_sta_info_update(pMac, pStaDs, pPeerNode, psessionEntry); + PELOGW(limLog(pMac, LOGW, FL("initiating ADD STA for the IBSS peer."));) + retCode = limAddSta(pMac, pStaDs, false, psessionEntry); + if (retCode != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("ibss-sta-add failed (reason %x)"), + retCode);) + limPrintMacAddr(pMac, *pPeerAddr, LOGE); + pStaDs->mlmStaContext.mlmState = prevState; + dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, + &psessionEntry->dph.dphHashTable); + } + else + { + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limIbssDecideProtection(pMac, pStaDs, &beaconParams , psessionEntry); + + if(beaconParams.paramChangeBitmap) + { + PELOGE(limLog(pMac, LOGE, FL("---> Update Beacon Params "));) + schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; + limSendBeaconParams(pMac, &beaconParams, psessionEntry ); + } + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("hashTblAdd failed (reason %x)"), retCode);) + limPrintMacAddr(pMac, *pPeerAddr, LOGE); + } + } + else + { + retCode = eSIR_FAILURE; + } + + return retCode; +} + +/* handle the response from HAL for an ADD STA request */ +tSirRetStatus +limIbssAddStaRsp( + tpAniSirGlobal pMac, + void *msg,tpPESession psessionEntry) +{ + tpDphHashNode pStaDs; + tANI_U16 peerIdx; + tpAddStaParams pAddStaParams = (tpAddStaParams) msg; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + if (pAddStaParams == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: ADD_STA_RSP with no body!"));) + return eSIR_FAILURE; + } + + pStaDs = dphLookupHashEntry(pMac, pAddStaParams->staMac, &peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: ADD_STA_RSP for unknown MAC addr "));) + limPrintMacAddr(pMac, pAddStaParams->staMac, LOGE); + vos_mem_free(pAddStaParams); + return eSIR_FAILURE; + } + + if (pAddStaParams->status != eHAL_STATUS_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: ADD_STA_RSP error (%x) "), pAddStaParams->status);) + limPrintMacAddr(pMac, pAddStaParams->staMac, LOGE); + vos_mem_free(pAddStaParams); + return eSIR_FAILURE; + } + + pStaDs->bssId = pAddStaParams->bssIdx; + pStaDs->staIndex = pAddStaParams->staIdx; + pStaDs->ucUcastSig = pAddStaParams->ucUcastSig; + pStaDs->ucBcastSig = pAddStaParams->ucBcastSig; + pStaDs->valid = 1; + pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + + PELOGW(limLog(pMac, LOGW, FL("IBSS: sending IBSS_NEW_PEER msg to SME!"));) + + ibss_status_chg_notify(pMac, pAddStaParams->staMac, pStaDs->staIndex, + pStaDs->ucUcastSig, pStaDs->ucBcastSig, + eWNI_SME_IBSS_NEW_PEER_IND, + psessionEntry->smeSessionId); + + vos_mem_free(pAddStaParams); + + return eSIR_SUCCESS; +} + + + +void limIbssDelBssRspWhenCoalescing(tpAniSirGlobal pMac, void *msg,tpPESession psessionEntry) +{ + tpDeleteBssParams pDelBss = (tpDeleteBssParams) msg; + + PELOGW(limLog(pMac, LOGW, FL("IBSS: DEL_BSS_RSP Rcvd during coalescing!"));) + + if (pDelBss == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: DEL_BSS_RSP(coalesce) with no body!"));) + goto end; + } + + if (pDelBss->status != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGE, FL("IBSS: DEL_BSS_RSP(coalesce) error (%x) Bss %d "), + pDelBss->status, pDelBss->bssIdx); + goto end; + } + //Delete peer entries. + limIbssDeleteAllPeers(pMac,psessionEntry); + + /* add the new bss */ + ibss_bss_add(pMac,psessionEntry); + + end: + if(pDelBss != NULL) + vos_mem_free(pDelBss); +} + + + +void limIbssAddBssRspWhenCoalescing(tpAniSirGlobal pMac, void *msg, tpPESession pSessionEntry) +{ + tANI_U8 infoLen; + tSirSmeNewBssInfo newBssInfo; + + tpAddBssParams pAddBss = (tpAddBssParams) msg; + + tpSirMacMgmtHdr pHdr = (tpSirMacMgmtHdr) pMac->lim.ibssInfo.pHdr; + tpSchBeaconStruct pBeacon = (tpSchBeaconStruct) pMac->lim.ibssInfo.pBeacon; + + if ((pHdr == NULL) || (pBeacon == NULL)) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to handle AddBssRspWhenCoalescing (no cached BSS info)"));) + goto end; + } + + // Inform Host of IBSS coalescing + infoLen = sizeof(tSirMacAddr) + sizeof(tSirMacChanNum) + + sizeof(tANI_U8) + pBeacon->ssId.length + 1; + + vos_mem_set((void *) &newBssInfo, sizeof(newBssInfo), 0); + vos_mem_copy(newBssInfo.bssId, pHdr->bssId, sizeof(tSirMacAddr)); + newBssInfo.channelNumber = (tSirMacChanNum) pAddBss->currentOperChannel; + vos_mem_copy((tANI_U8 *) &newBssInfo.ssId, + (tANI_U8 *) &pBeacon->ssId, pBeacon->ssId.length + 1); + + PELOGW(limLog(pMac, LOGW, FL("Sending JOINED_NEW_BSS notification to SME."));) + + limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_JOINED_NEW_BSS, + (tANI_U32 *) &newBssInfo, + infoLen,pSessionEntry->smeSessionId); + { + //Configure beacon and send beacons to HAL + limSendBeaconInd(pMac, pSessionEntry); + } + + end: + ibss_coalesce_free(pMac); +} + + + +void +limIbssDelBssRsp( + tpAniSirGlobal pMac, + void *msg,tpPESession psessionEntry) +{ + tSirResultCodes rc = eSIR_SME_SUCCESS; + tpDeleteBssParams pDelBss = (tpDeleteBssParams) msg; + tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + if (pDelBss == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: DEL_BSS_RSP with no body!"));) + rc = eSIR_SME_REFUSED; + goto end; + } + + if((psessionEntry = peFindSessionBySessionId(pMac,pDelBss->sessionId))==NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + goto end; + } + + + /* + * If delBss was issued as part of IBSS Coalescing, gLimIbssCoalescingHappened flag will be true. + * BSS has to be added again in this scenario, so this case needs to be handled separately. + * If delBss was issued as a result of trigger from SME_STOP_BSS Request, then limSme state changes to + * 'IDLE' and gLimIbssCoalescingHappened flag will be false. In this case STOP BSS RSP has to be sent to SME. + */ + if(true == pMac->lim.gLimIbssCoalescingHappened) + { + + limIbssDelBssRspWhenCoalescing(pMac,msg,psessionEntry); + return; + } + + + + if (pDelBss->status != eHAL_STATUS_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: DEL_BSS_RSP error (%x) Bss %d "), + pDelBss->status, pDelBss->bssIdx);) + rc = eSIR_SME_STOP_BSS_FAILURE; + goto end; + } + + + + if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("IBSS: DEL_BSS_RSP setLinkState failed"));) + rc = eSIR_SME_REFUSED; + goto end; + } + + limIbssDelete(pMac,psessionEntry); + + dphHashTableClassInit(pMac, &psessionEntry->dph.dphHashTable); + limDeletePreAuthList(pMac); + + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + psessionEntry->limSystemRole = eLIM_STA_ROLE; + + /* Change the short slot operating mode to Default (which is 1 for now) so that when IBSS starts next time with Libra + * as originator, it picks up the default. This enables us to remove hard coding of short slot = 1 from limApplyConfiguration + */ + psessionEntry->shortSlotTimeSupported = WNI_CFG_SHORT_SLOT_TIME_STADEF; + + end: + if(pDelBss != NULL) + vos_mem_free(pDelBss); + /* Delete PE session once BSS is deleted */ + if (NULL != psessionEntry) { + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, rc,psessionEntry->smeSessionId,psessionEntry->transactionId); + peDeleteSession(pMac, psessionEntry); + psessionEntry = NULL; + } +} + +static void +__limIbssSearchAndDeletePeer(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacAddr macAddr) +{ + tLimIbssPeerNode *pTempNode, *pPrevNode; + tLimIbssPeerNode *pTempNextNode = NULL; + tpDphHashNode pStaDs=NULL; + tANI_U16 peerIdx=0; + tANI_U16 staIndex=0; + tANI_U8 ucUcastSig; + tANI_U8 ucBcastSig; + + pPrevNode = pTempNode = pMac->lim.gLimIbssPeerList; + + limLog(pMac, LOG1, FL(" PEER ADDR :" MAC_ADDRESS_STR ),MAC_ADDR_ARRAY(macAddr)); + + /** Compare Peer */ + while (NULL != pTempNode) + { + pTempNextNode = pTempNode->next; + + /* Delete the STA with MAC address */ + if (vos_mem_compare( (tANI_U8 *) macAddr, + (tANI_U8 *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr)) ) + { + pStaDs = dphLookupHashEntry(pMac, macAddr, + &peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs) + { + staIndex = pStaDs->staIndex; + ucUcastSig = pStaDs->ucUcastSig; + ucBcastSig = pStaDs->ucBcastSig; + + (void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry); + limDeleteDphHashEntry(pMac, pStaDs->staAddr, peerIdx, psessionEntry); + limReleasePeerIdx(pMac, peerIdx, psessionEntry); + + /* Send indication to upper layers */ + ibss_status_chg_notify(pMac, macAddr, staIndex, + ucUcastSig, ucBcastSig, + eWNI_SME_IBSS_PEER_DEPARTED_IND, + psessionEntry->smeSessionId ); + if (pTempNode == pMac->lim.gLimIbssPeerList) + { + pMac->lim.gLimIbssPeerList = pTempNode->next; + pPrevNode = pMac->lim.gLimIbssPeerList; + } + else + pPrevNode->next = pTempNode->next; + + vos_mem_free(pTempNode); + pMac->lim.gLimNumIbssPeers--; + + pTempNode = pTempNextNode; + break; + } + } + pPrevNode = pTempNode; + pTempNode = pTempNextNode; + } + /* + * if it is the last peer walking out, we better + * we set IBSS state to inactive. + */ + if (0 == pMac->lim.gLimNumIbssPeers) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "Last STA from IBSS walked out"); + psessionEntry->limIbssActive = false; + } +} + +/** + * limIbssCoalesce() + * + *FUNCTION: + * This function is called upon receiving Beacon/Probe Response + * while operating in IBSS mode. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pBeacon - Parsed Beacon Frame structure + * @param pBD - Pointer to received BD + * + * @return Status whether to process or ignore received Beacon Frame + */ + +tSirRetStatus +limIbssCoalesce( + tpAniSirGlobal pMac, + tpSirMacMgmtHdr pHdr, + tpSchBeaconStruct pBeacon, + tANI_U8 *pIEs, + tANI_U32 ieLen, + tANI_U16 fTsfLater, + tpPESession psessionEntry) +{ + tANI_U16 peerIdx; + tSirMacAddr currentBssId; + tLimIbssPeerNode *pPeerNode; + tpDphHashNode pStaDs; + tUpdateBeaconParams beaconParams; + + vos_mem_set((tANI_U8 *)&beaconParams, sizeof(tUpdateBeaconParams), 0); + + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + limLog(pMac, LOG1, FL("Current BSSID :" MAC_ADDRESS_STR " Received BSSID :" MAC_ADDRESS_STR ), + MAC_ADDR_ARRAY(currentBssId), MAC_ADDR_ARRAY(pHdr->bssId)); + + /* Check for IBSS Coalescing only if Beacon is from different BSS */ + if ( !vos_mem_compare(currentBssId, pHdr->bssId, sizeof( tSirMacAddr )) + && psessionEntry->isCoalesingInIBSSAllowed) + { + /* + * If STA entry is already available in the LIM hash table, then it is + * possible that the peer may have left and rejoined within the heartbeat + * timeout. In the offloaded case with 32 peers, the HB timeout is whopping + * 128 seconds. In that case, the FW will not let any frames come in until + * atleast the last sequence number is received before the peer is left + * Hence, if the coalescing peer is already there in the peer list and if + * the BSSID matches then, invoke delSta() to cleanup the entries. We will + * let the peer coalesce when we receive next beacon from the peer + */ + pPeerNode = ibss_peer_find(pMac, pHdr->sa); + if (NULL != pPeerNode) + { + __limIbssSearchAndDeletePeer (pMac, psessionEntry, pHdr->sa); + PELOGW(limLog(pMac, LOGW, + FL("** Peer attempting to reconnect before HB timeout, deleted **"));) + return eSIR_LIM_IGNORE_BEACON; + } + + if (! fTsfLater) // No Coalescing happened. + { + PELOGW(limLog(pMac, LOGW, FL("No Coalescing happened"));) + return eSIR_LIM_IGNORE_BEACON; + } + /* + * IBSS Coalescing happened. + * save the received beacon, and delete the current BSS. The rest of the + * processing will be done in the delBss response processing + */ + pMac->lim.gLimIbssCoalescingHappened = true; + PELOGW(limLog(pMac, LOGW, FL("IBSS Coalescing happened"));) + ibss_coalesce_save(pMac, pHdr, pBeacon); + limLog(pMac, LOGW, FL("Delete BSSID :" MAC_ADDRESS_STR ), + MAC_ADDR_ARRAY(currentBssId)); + ibss_bss_delete(pMac,psessionEntry); + return eSIR_SUCCESS; + } + else + { + if (!vos_mem_compare(currentBssId, pHdr->bssId, sizeof( tSirMacAddr ))) + return eSIR_LIM_IGNORE_BEACON; + } + + + // STA in IBSS mode and SSID matches with ours + pPeerNode = ibss_peer_find(pMac, pHdr->sa); + if (pPeerNode == NULL) + { + /* Peer not in the list - Collect BSS description & add to the list */ + tANI_U32 frameLen; + tSirRetStatus retCode; + + /* + * Limit the Max number of IBSS Peers allowed as the max + * number of STA's allowed + * pMac->lim.gLimNumIbssPeers will be increamented after exiting + * this function. so we will add additional 1 to compare against + * pMac->lim.gLimIbssStaLimit + */ + if ((pMac->lim.gLimNumIbssPeers+1) >= pMac->lim.gLimIbssStaLimit) + { + /*Print every 100th time */ + if (pMac->lim.gLimIbssRetryCnt % 100 == 0) + { + PELOGE(limLog(pMac, LOG1, FL("**** MAX STA LIMIT HAS REACHED ****"));) + } + pMac->lim.gLimIbssRetryCnt++; + return eSIR_LIM_MAX_STA_REACHED_ERROR; + } + PELOGW(limLog(pMac, LOGW, FL("IBSS Peer node does not exist, adding it***"));) + frameLen = sizeof(tLimIbssPeerNode) + ieLen - sizeof(tANI_U32); + + pPeerNode = vos_mem_malloc((tANI_U16)frameLen); + if (NULL == pPeerNode) + { + limLog(pMac, LOGP, FL("alloc fail (%d bytes) storing IBSS peer info"), + frameLen); + return eSIR_MEM_ALLOC_FAILED; + } + + /* Initialize all peer node properties to 0 */ + vos_mem_zero(pPeerNode, frameLen); + + pPeerNode->beacon = NULL; + pPeerNode->beaconLen = 0; + + ibss_peer_collect(pMac, pBeacon, pHdr, pPeerNode,psessionEntry); + pPeerNode->beacon = vos_mem_malloc(ieLen); + if (NULL == pPeerNode->beacon) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store beacon"));) + } + else + { + vos_mem_copy(pPeerNode->beacon, pIEs, ieLen); + pPeerNode->beaconLen = (tANI_U16)ieLen; + } + ibss_peer_add(pMac, pPeerNode); + + pStaDs = dphLookupHashEntry(pMac, pPeerNode->peerMacAddr, &peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + /// DPH node already exists for the peer + PELOGW(limLog(pMac, LOGW, FL("DPH Node present for just learned peer"));) + PELOG1(limPrintMacAddr(pMac, pPeerNode->peerMacAddr, LOG1);) + ibss_sta_info_update(pMac, pStaDs, pPeerNode,psessionEntry); + return eSIR_SUCCESS; + } + retCode = limIbssStaAdd(pMac, pPeerNode->peerMacAddr,psessionEntry); + if (retCode != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("lim-ibss-sta-add failed (reason %x)"), retCode);) + limPrintMacAddr(pMac, pPeerNode->peerMacAddr, LOGE); + return retCode; + } + + // Decide protection mode + pStaDs = dphLookupHashEntry(pMac, pPeerNode->peerMacAddr, &peerIdx, &psessionEntry->dph.dphHashTable); + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limIbssDecideProtection(pMac, pStaDs, &beaconParams, psessionEntry); + + if(beaconParams.paramChangeBitmap) + { + PELOGE(limLog(pMac, LOGE, FL("beaconParams.paramChangeBitmap=1 ---> Update Beacon Params "));) + schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; + limSendBeaconParams(pMac, &beaconParams, psessionEntry ); + } + } + else + ibss_sta_caps_update(pMac, pPeerNode,psessionEntry); + + if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) + return eSIR_SUCCESS; + + // Received Beacon from same IBSS we're + // currently part of. Inform Roaming algorithm + // if not already that IBSS is active. + if (psessionEntry->limIbssActive == false) + { + limResetHBPktCount(psessionEntry); + PELOGW(limLog(pMac, LOGW, FL("Partner joined our IBSS, Sending IBSS_ACTIVE Notification to SME"));) + psessionEntry->limIbssActive = true; + limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_IBSS_ACTIVE, NULL, 0, psessionEntry->smeSessionId); + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); + if (limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); + } + + return eSIR_SUCCESS; +} /*** end limHandleIBSScoalescing() ***/ + + +void limIbssHeartBeatHandle(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tLimIbssPeerNode *pTempNode, *pPrevNode; + tLimIbssPeerNode *pTempNextNode = NULL; + tANI_U16 peerIdx=0; + tpDphHashNode pStaDs=0; + tANI_U32 threshold=0; + tANI_U16 staIndex=0; + tANI_U8 ucUcastSig=0; + tANI_U8 ucBcastSig=0; + + /** MLM BSS is started and if PE in scanmode then MLM state will be waiting for probe resp. + * If Heart beat timeout triggers during this corner case then we need to reactivate HeartBeat timer + */ + if(psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) { + /****** + * Note: Use this code once you have converted all + * limReactivateHeartBeatTimer() calls to + * limReactivateTimer() calls. + * + ******/ + limReactivateHeartBeatTimer(pMac, psessionEntry); + return; + } + /** If LinkMonitor is Disabled */ + if(!pMac->sys.gSysEnableLinkMonitorMode) + return; + + pPrevNode = pTempNode = pMac->lim.gLimIbssPeerList; + threshold = (pMac->lim.gLimNumIbssPeers / 4 ) + 1; + + /** Monitor the HeartBeat with the Individual PEERS in the IBSS */ + while (pTempNode != NULL) + { + pTempNextNode = pTempNode->next; + if(pTempNode->beaconHBCount) //There was a beacon for this peer during heart beat. + { + pTempNode->beaconHBCount = 0; + pTempNode->heartbeatFailure = 0; + } + else //There wasnt any beacon received during heartbeat timer. + { + pTempNode->heartbeatFailure++; + PELOGE(limLog(pMac, LOGE, FL("Heartbeat fail = %d thres = %d"), pTempNode->heartbeatFailure, pMac->lim.gLimNumIbssPeers);) + if(pTempNode->heartbeatFailure >= threshold ) + { + //Remove this entry from the list. + pStaDs = dphLookupHashEntry(pMac, pTempNode->peerMacAddr, &peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs) + { + staIndex = pStaDs->staIndex; + ucUcastSig = pStaDs->ucUcastSig; + ucBcastSig = pStaDs->ucBcastSig; + + (void) limDelSta(pMac, pStaDs, false /*asynchronous*/,psessionEntry); + limDeleteDphHashEntry(pMac, pStaDs->staAddr, peerIdx,psessionEntry); + limReleasePeerIdx(pMac, peerIdx, psessionEntry); + //Send indication. + ibss_status_chg_notify( pMac, pTempNode->peerMacAddr, staIndex, + ucUcastSig, ucBcastSig, + eWNI_SME_IBSS_PEER_DEPARTED_IND, + psessionEntry->smeSessionId ); + } + if(pTempNode == pMac->lim.gLimIbssPeerList) + { + pMac->lim.gLimIbssPeerList = pTempNode->next; + pPrevNode = pMac->lim.gLimIbssPeerList; + } + else + pPrevNode->next = pTempNode->next; + + vos_mem_free(pTempNode); + pMac->lim.gLimNumIbssPeers--; + + pTempNode = pTempNextNode; //Since we deleted current node, prevNode remains same. + continue; + } + } + + pPrevNode = pTempNode; + pTempNode = pTempNextNode; + } + + /** General IBSS Activity Monitor, check if in IBSS Mode we are received any Beacons */ + if(pMac->lim.gLimNumIbssPeers) + { + if(psessionEntry->LimRxedBeaconCntDuringHB < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL) + pMac->lim.gLimHeartBeatBeaconStats[psessionEntry->LimRxedBeaconCntDuringHB]++; + else + pMac->lim.gLimHeartBeatBeaconStats[0]++; + + limReactivateHeartBeatTimer(pMac, psessionEntry); + + // Reset number of beacons received + limResetHBPktCount(psessionEntry); + return; + } + else + { + + PELOGW(limLog(pMac, LOGW, FL("Heartbeat Failure"));) + pMac->lim.gLimHBfailureCntInLinkEstState++; + + if (psessionEntry->limIbssActive == true) + { + // We don't receive Beacon frames from any + // other STA in IBSS. Announce IBSS inactive + // to Roaming algorithm + PELOGW(limLog(pMac, LOGW, FL("Alone in IBSS"));) + psessionEntry->limIbssActive = false; + + limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_IBSS_INACTIVE, + NULL, 0, psessionEntry->smeSessionId); + } + } +} + + +/** ------------------------------------------------------------- +\fn limIbssDecideProtectionOnDelete +\brief Decides all the protection related information. +\ +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +void +limIbssDecideProtectionOnDelete(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + tANI_U32 phyMode; + tHalBitVal erpEnabled = eHAL_CLEAR; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + tANI_U32 i; + + if(NULL == pStaDs) + return; + + limGetRfBand(pMac, &rfBand, psessionEntry); + if(SIR_BAND_2_4_GHZ == rfBand) + { + limGetPhyMode(pMac, &phyMode, psessionEntry); + erpEnabled = pStaDs->erpEnabled; + //we are HT or 11G and 11B station is getting deleted. + if ( ((phyMode == WNI_CFG_PHY_MODE_11G) || psessionEntry->htCapability) + && (erpEnabled == eHAL_CLEAR)) + { + PELOGE(limLog(pMac, LOGE, FL("(%d) A legacy STA is disassociated. Addr is "), + psessionEntry->gLim11bParams.numSta); + limPrintMacAddr(pMac, pStaDs->staAddr, LOGE);) + if (psessionEntry->gLim11bParams.numSta > 0) + { + for (i=0; ilim.protStaCache[i].active) + { + if (vos_mem_compare(pMac->lim.protStaCache[i].addr, + pStaDs->staAddr, sizeof(tSirMacAddr))) + { + psessionEntry->gLim11bParams.numSta--; + pMac->lim.protStaCache[i].active = false; + break; + } + } + } + } + + if (psessionEntry->gLim11bParams.numSta == 0) + { + PELOGE(limLog(pMac, LOGE, FL("No more 11B STA exists. Disable protection. "));) + limIbssSetProtection(pMac, false, pBeaconParams,psessionEntry); + } + } + } +} + +/** ----------------------------------------------------------------- +\fn __limIbssPeerInactivityHandler +\brief Internal function. Deletes FW indicated peer which is inactive +\ +\param tpAniSirGlobal pMac +\param tpPESession psessionEntry +\param tpSirIbssPeerInactivityInd peerInactivityInd +\return None + -----------------------------------------------------------------*/ +static void +__limIbssPeerInactivityHandler(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSirIbssPeerInactivityInd peerInactivityInd) +{ + if(psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) + { + limReactivateHeartBeatTimer(pMac, psessionEntry); + return; + } + + /* delete the peer for which heartbeat is observed */ + __limIbssSearchAndDeletePeer (pMac, psessionEntry, peerInactivityInd->peerAddr); + +} + +/** ------------------------------------------------------------- +\fn limProcessIbssPeerInactivity +\brief Peer inactivity message handler +\ +\param tpAniSirGlobal pMac +\param void* buf +\return None + -------------------------------------------------------------*/ +void +limProcessIbssPeerInactivity(tpAniSirGlobal pMac, void *buf) +{ + /* + * --------------- HEARTBEAT OFFLOAD CASE ------------------ + * This message handler is executed when the firmware identifies + * inactivity from one or more peer devices. We will come here + * for every inactive peer device + */ + tANI_U8 i; + + tSirIbssPeerInactivityInd *peerInactivityInd = + (tSirIbssPeerInactivityInd *) buf; + + /* + * If IBSS is not started or heartbeat offload is not enabled + * we should not handle this request + */ + if (eLIM_STA_IN_IBSS_ROLE != pMac->lim.gLimSystemRole && + !IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE) + { + return; + } + + /** If LinkMonitor is Disabled */ + if (!pMac->sys.gSysEnableLinkMonitorMode) + { + return; + } + + for (i = 0; i < pMac->lim.maxBssId; i++) + { + if (VOS_TRUE == pMac->lim.gpSession[i].valid && + eSIR_IBSS_MODE == pMac->lim.gpSession[i].bssType) + { + __limIbssPeerInactivityHandler(pMac, + &pMac->lim.gpSession[i], + peerInactivityInd); + break; + } + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h new file mode 100644 index 000000000000..4b075a2758ba --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limIbssPeerMgmt.h contains prototypes for + * the utility functions LIM uses to maintain peers in IBSS. + * Author: Chandra Modumudi + * Date: 03/12/04 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "sirCommon.h" +#include "limUtils.h" + +#define IBSS_STATIONS_USED_DURING_INIT 4 //(broadcast + self + p2p + softap) + +void limIbssInit(tpAniSirGlobal); +void limIbssDelete(tpAniSirGlobal,tpPESession psessionEntry); +tSirRetStatus limIbssCoalesce(tpAniSirGlobal, tpSirMacMgmtHdr, tpSchBeaconStruct, tANI_U8*,tANI_U32, tANI_U16,tpPESession); +tSirRetStatus limIbssStaAdd(tpAniSirGlobal, void *,tpPESession); +tSirRetStatus limIbssAddStaRsp( tpAniSirGlobal, void *,tpPESession); +tLimIbssPeerNode* limIbssPeerFind(tpAniSirGlobal pMac, tSirMacAddr macAddr); +void limIbssDelBssRsp( tpAniSirGlobal, void *,tpPESession); +void limIbssDelBssRspWhenCoalescing(tpAniSirGlobal, void *,tpPESession); +void limIbssAddBssRspWhenCoalescing(tpAniSirGlobal pMac, void * msg, tpPESession pSessionEntry); +void limIbssDecideProtectionOnDelete(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams,tpPESession pSessionEntry); +void limIbssHeartBeatHandle(tpAniSirGlobal pMac,tpPESession psessionEntry); +void limProcessIbssPeerInactivity(tpAniSirGlobal pMac, void *buf); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c new file mode 100644 index 000000000000..2c1581767ce9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limLinkMonitoringAlgo.cc contains the code for + * Link monitoring algorithm on AP and heart beat failure + * handling on STA. + * Author: Chandra Modumudi + * Date: 03/01/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "aniGlobal.h" +#include "wniCfgSta.h" +#include "cfgApi.h" + + +#include "schApi.h" +#include "pmmApi.h" +#include "utilsApi.h" +#include "limAssocUtils.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limPropExtsUtils.h" + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT +#include "vos_diag_core_log.h" +#endif //FEATURE_WLAN_DIAG_SUPPORT +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "limSerDesUtils.h" + + +/** + * limSendKeepAliveToPeer() + * + *FUNCTION: + * This function is called to send Keep alive message to peer + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limSendKeepAliveToPeer(tpAniSirGlobal pMac) +{ + +} /*** limSendKeepAliveToPeer() ***/ + + +/** --------------------------------------------------------- +\fn limDeleteStaContext +\brief This function handles the message from HAL: +\ WDA_DELETE_STA_CONTEXT_IND. This function +\ validates that the given station id exist, and if so, +\ deletes the station by calling limTriggerSTAdeletion. +\param tpAniSirGlobal pMac +\param tpSirMsgQ limMsg +\return none + -----------------------------------------------------------*/ +void +limDeleteStaContext(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpDeleteStaContext pMsg = (tpDeleteStaContext)limMsg->bodyptr; + tpDphHashNode pStaDs; + tpPESession psessionEntry ; + + if(NULL == pMsg) + { + PELOGE(limLog(pMac, LOGE,FL("Invalid body pointer in message"));) + return; + } + psessionEntry = pe_find_session_by_sme_session_id(pMac, pMsg->vdev_id); + if(NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("session not found for given sme session")); + vos_mem_free(pMsg); + return; + } + + switch(pMsg->reasonCode) + { + case HAL_DEL_STA_REASON_CODE_KEEP_ALIVE: + pStaDs = dphLookupAssocId(pMac, pMsg->staId, &pMsg->assocId, + &psessionEntry->dph.dphHashTable); + + if (!pStaDs) { + PELOGE(limLog(pMac, LOGE, + FL("Skip STA deletion (invalid STA) limSystemRole=%d"), + GET_LIM_SYSTEM_ROLE(psessionEntry));) + vos_mem_free(pMsg); + return; + } + + /* + * check and see if same staId. This is to avoid the scenario + * where we're trying to delete a staId we just added. + */ + if (pStaDs->staIndex != pMsg->staId) { + PELOGE(limLog(pMac, LOGE, + FL("staid mismatch: %d vs %d "), pStaDs->staIndex, pMsg->staId);) + vos_mem_free(pMsg); + return; + } + + /* + * Check if Deauth/Disassoc is triggered from Host. + * If mlmState is in some transient state then + * don't trigger STA deletion to avoid the race + * condition. + */ + if ((pStaDs && + ((pStaDs->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_WT_ASSOC_CNF_STATE) && + (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_ASSOCIATED_STATE)))) { + PELOGE(limLog(pMac, LOGE, + FL("received Del STA context in some transit state(staId: %d, assocId: %d)"), + pMsg->staId, pMsg->assocId);) + vos_mem_free(pMsg); + return; + } + + if (LIM_IS_STA_ROLE(psessionEntry) && !pMsg->is_tdls) { + /* + * If roaming is in progress, then ignore the STA kick out + * and let the connection happen. The roaming_in_progress + * flag is set whenever a candidate found indication is + * received. It is enabled on the PE session for which + * the indication is received. There is really no need to + * re-set the flag, since the PE session on which it was + * set will be deleted, even if roaming is success or failure. + * When roaming is a success, the PE session for AP1 is + * deleted. When we get a candidate indication, it would be + * on the PE session of the AP1. AP2 to which we are about to + * roam will have a new PE session ID.If roaming fails for + * any reason, then it will anyways delete the PE session of + * of the AP1. + */ + if (psessionEntry->roaming_in_progress || + limIsReassocInProgress(pMac, psessionEntry)) { + limLog(pMac, LOGE, + FL("roam_progress=%d, reassoc=%d. Not disconnecting"), + psessionEntry->roaming_in_progress, + limIsReassocInProgress(pMac, psessionEntry)); + vos_mem_free(pMsg); + return; + } + pStaDs = dphGetHashEntry(pMac, + DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) { + limLog(pMac, LOGE, FL("Dph entry not found.")); + vos_mem_free(pMsg); + return; + } + pStaDs->del_sta_ctx_rssi = pMsg->rssi; + limSendDeauthMgmtFrame(pMac, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + pMsg->addr2, psessionEntry, FALSE); + limTearDownLinkWithAp(pMac, psessionEntry->peSessionId, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON); + /* only break for STA role (non TDLS) */ + break; + } + + limLog(pMac, LOGE, FL("Deleting sta: staId %d, reasonCode %d"), + pMsg->staId, pMsg->reasonCode); + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + vos_mem_free(pMsg); + return; + } + if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry)) { + PELOG1(limLog(pMac, LOG1, FL("SAP:lim Delete Station Context (staId: %d, assocId: %d) "), + pMsg->staId, pMsg->assocId);) + limSendDisassocMgmtFrame(pMac, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + pStaDs->staAddr, psessionEntry, FALSE); + limTriggerSTAdeletion(pMac, pStaDs, psessionEntry); + } +#ifdef FEATURE_WLAN_TDLS + else + { + if (LIM_IS_STA_ROLE(psessionEntry) && + STA_ENTRY_TDLS_PEER == pStaDs->staType) { + //TeardownLink with PEER + //Reason code HAL_DEL_STA_REASON_CODE_KEEP_ALIVE means + //eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE + limSendSmeTDLSDelStaInd(pMac, pStaDs, psessionEntry, + eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE); + } + } +#endif + break; + + case HAL_DEL_STA_REASON_CODE_UNKNOWN_A2: + PELOGE(limLog(pMac, LOGE, FL(" Deleting Unknown station "));) + limPrintMacAddr(pMac, pMsg->addr2, LOGE); + limSendDeauthMgmtFrame( pMac, eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON, pMsg->addr2, psessionEntry, FALSE); + break; + + default: + PELOGE(limLog(pMac, LOGE, FL(" Unknown reason code "));) + break; + + } + vos_mem_free(pMsg); + return; +} + + +/** + * limTriggerSTAdeletion() + * + *FUNCTION: + * This function is called to trigger STA context deletion + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param pMac - Pointer to global MAC structure + * @param pStaDs - Pointer to internal STA Datastructure + * @return None + */ +void +limTriggerSTAdeletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry) +{ + tLimMlmDisassocInd mlmDisassocInd; + + if (!pStaDs) + { + PELOGW(limLog(pMac, LOGW, FL("Skip STA deletion (invalid STA)"));) + return; + } + + if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || + (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { + /* Already in the process of deleting context for the peer */ + PELOGE(limLog(pMac, LOGE, + FL("Deletion is in progress for peer:%p"), pStaDs->staAddr);) + return; + } + + pStaDs->mlmStaContext.disassocReason = + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + pStaDs->mlmStaContext.cleanupTrigger = eLIM_LINK_MONITORING_DISASSOC; + vos_mem_copy(&mlmDisassocInd.peerMacAddr, pStaDs->staAddr, + sizeof(tSirMacAddr)); + mlmDisassocInd.reasonCode = eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + mlmDisassocInd.disassocTrigger = eLIM_LINK_MONITORING_DISASSOC; + + /* Update PE session Id */ + mlmDisassocInd.sessionId = psessionEntry->peSessionId; + limPostSmeMessage(pMac, LIM_MLM_DISASSOC_IND, + (tANI_U32 *) &mlmDisassocInd); + // Issue Disassoc Indication to SME. + limSendSmeDisassocInd(pMac, pStaDs, psessionEntry); +} /*** end limTriggerSTAdeletion() ***/ + + + +/** + * limTearDownLinkWithAp() + * + *FUNCTION: + * This function is called when heartbeat (beacon reception) + * fails on STA + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limTearDownLinkWithAp(tpAniSirGlobal pMac, tANI_U8 sessionId, tSirMacReasonCodes reasonCode) +{ + tpDphHashNode pStaDs = NULL; + + //tear down the following sessionEntry + tpPESession psessionEntry; + + if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + /** + * Heart beat failed for upto threshold value + * and AP did not respond for Probe request. + * Trigger link tear down. + */ + if(pMac->psOffloadEnabled) + psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; + else + pMac->pmm.inMissedBeaconScenario = FALSE; + + limLog(pMac, LOGW, + FL("No ProbeRsp from AP after HB failure. Tearing down link")); + + // Deactivate heartbeat timer + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + + // Announce loss of link to Roaming algorithm + // and cleanup by sending SME_DISASSOC_REQ to SME + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + + + if (pStaDs != NULL) + { + tLimMlmDeauthInd mlmDeauthInd; + +#ifdef FEATURE_WLAN_TDLS + /* Delete all TDLS peers connected before leaving BSS*/ + limDeleteTDLSPeers(pMac, psessionEntry); +#endif + + pStaDs->mlmStaContext.disassocReason = reasonCode; + pStaDs->mlmStaContext.cleanupTrigger = eLIM_LINK_MONITORING_DEAUTH; + + /// Issue Deauth Indication to SME. + vos_mem_copy((tANI_U8 *) &mlmDeauthInd.peerMacAddr, + pStaDs->staAddr, + sizeof(tSirMacAddr)); + + /* + * if sendDeauthBeforeCon is enabled and reasoncode is + * Beacon Missed Store the MAC of AP in the flip flop + * buffer. This MAC will be used to send Deauth before + * connection, if we connect to same AP after HB failure. + */ + if (pMac->roam.configParam.sendDeauthBeforeCon && + eSIR_BEACON_MISSED == reasonCode) + { + int apCount = pMac->lim.gLimHeartBeatApMacIndex; + + if (pMac->lim.gLimHeartBeatApMacIndex) + pMac->lim.gLimHeartBeatApMacIndex = 0; + else + pMac->lim.gLimHeartBeatApMacIndex = 1; + + limLog(pMac, LOGE, FL("HB Failure on MAC " + MAC_ADDRESS_STR" Store it on Index %d"), + MAC_ADDR_ARRAY(pStaDs->staAddr),apCount); + + sirCopyMacAddr(pMac->lim.gLimHeartBeatApMac[apCount], + pStaDs->staAddr); + } + + mlmDeauthInd.reasonCode = (tANI_U8) pStaDs->mlmStaContext.disassocReason; + mlmDeauthInd.deauthTrigger = pStaDs->mlmStaContext.cleanupTrigger; + + limPostSmeMessage(pMac, LIM_MLM_DEAUTH_IND, (tANI_U32 *) &mlmDeauthInd); + + limSendSmeDeauthInd(pMac, pStaDs, psessionEntry); + limReInitScanResults(pMac); + } +} /*** limTearDownLinkWithAp() ***/ + + + + +/** + * limHandleHeartBeatFailure() + * + *FUNCTION: + * This function is called when heartbeat (beacon reception) + * fails on STA + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void limHandleHeartBeatFailure(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + vos_log_beacon_update_pkt_type *log_ptr = NULL; +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /* If gLimHeartBeatTimer fires between the interval of sending WDA_ENTER_BMPS_REQUEST + * to the HAL and receiving WDA_ENTER_BMPS_RSP from the HAL, then LIM (PE) tries to Process the + * SIR_LIM_HEAR_BEAT_TIMEOUT message but The PE state is ePMM_STATE_BMPS_SLEEP so PE dont + * want to handle heartbeat timeout in the BMPS, because Firmware handles it in BMPS. + * So just return from heartbeatfailure handler + */ + if(!pMac->psOffloadEnabled) + { + if(!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE && (!limIsSystemInActiveState(pMac))) + return; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_beacon_update_pkt_type, LOG_WLAN_BEACON_UPDATE_C); + if(log_ptr) + log_ptr->bcn_rx_cnt = psessionEntry->LimRxedBeaconCntDuringHB; + WLAN_VOS_DIAG_LOG_REPORT(log_ptr); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /* Ensure HB Status for the session has been reseted */ + psessionEntry->LimHBFailureStatus = eANI_BOOLEAN_FALSE; + + if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) + { + if (!pMac->sys.gSysEnableLinkMonitorMode) + return; + + /** + * Beacon frame not received within heartbeat timeout. + */ + PELOGW(limLog(pMac, LOGW, FL("Heartbeat Failure"));) + pMac->lim.gLimHBfailureCntInLinkEstState++; + + /** + * Check if connected on the DFS channel, if not connected on + * DFS channel then only send the probe request otherwise tear down the link + */ + if(!limIsconnectedOnDFSChannel(psessionEntry->currentOperChannel)) + { + /*** Detected continuous Beacon Misses ***/ + psessionEntry->LimHBFailureStatus= eANI_BOOLEAN_TRUE; + + /*Reset the HB packet count before sending probe*/ + limResetHBPktCount(psessionEntry); + /** + * Send Probe Request frame to AP to see if + * it is still around. Wait until certain + * timeout for Probe Response from AP. + */ + PELOGW(limLog(pMac, LOGW, FL("Heart Beat missed from AP. Sending Probe Req"));) + /* for searching AP, we don't include any additional IE */ + limSendProbeReqMgmtFrame(pMac, &psessionEntry->ssId, psessionEntry->bssId, + psessionEntry->currentOperChannel,psessionEntry->selfMacAddr, + psessionEntry->dot11mode, 0, NULL); + } + else + { + PELOGW(limLog(pMac, LOGW, + FL("Heart Beat missed from AP on DFS chanel moving to passive"));) + if (psessionEntry->currentOperChannel < SIR_MAX_24G_5G_CHANNEL_RANGE){ + limCovertChannelScanType(pMac, psessionEntry->currentOperChannel, false); + pMac->lim.dfschannelList.timeStamp[psessionEntry->currentOperChannel] = 0; + } + /* Connected on DFS channel so should not send the probe request + * tear down the link directly */ + limTearDownLinkWithAp(pMac, psessionEntry->peSessionId, + eSIR_BEACON_MISSED); + } + } + else + { + /** + * Heartbeat timer may have timed out + * while we're doing background scanning/learning + * or in states other than link-established state. + * Log error. + */ + PELOG1(limLog(pMac, LOG1, FL("received heartbeat timeout in state %X"), + psessionEntry->limMlmState);) + limPrintMlmState(pMac, LOG1, psessionEntry->limMlmState); + pMac->lim.gLimHBfailureCntInOtherStates++; + limReactivateHeartBeatTimer(pMac, psessionEntry); + } +} /*** limHandleHeartBeatFailure() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLogDump.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLogDump.c new file mode 100644 index 000000000000..eefedfcf3b89 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLogDump.c @@ -0,0 +1,2193 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ +limLogDump.c + +Implements the dump commands specific to the lim module. + ============================================================================*/ + +#include "vos_types.h" +#include "limApi.h" + +#if defined(ANI_LOGDUMP) + + +#include "limUtils.h" +#include "limSecurityUtils.h" +#include "schApi.h" +#include "limSerDesUtils.h" +#include "limAssocUtils.h" +#include "limSendMessages.h" +#include "logDump.h" +#include "limTrace.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif +#if defined WLAN_FEATURE_VOWIFI_11R +#include +#endif +#include "smeInside.h" +#include "wlan_qct_wda.h" + +void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA); +#ifdef WLANTL_DEBUG +extern void WLANTLPrintPktsRcvdPerRssi(v_PVOID_t pAdapter, v_U8_t staId, v_BOOL_t flush); +extern void WLANTLPrintPktsRcvdPerRateIdx(v_PVOID_t pAdapter, v_U8_t staId, v_BOOL_t flush); +#endif + +static char *getRole( tLimSystemRole role ) +{ + switch (role) + { + case eLIM_UNKNOWN_ROLE: + return "eLIM_UNKNOWN_ROLE"; + case eLIM_AP_ROLE: + return "eLIM_AP_ROLE"; + case eLIM_STA_IN_IBSS_ROLE: + return "eLIM_STA_IN_IBSS_ROLE"; + case eLIM_STA_ROLE: + return "eLIM_STA_ROLE"; + case eLIM_BT_AMP_STA_ROLE: + return "eLIM_BT_AMP_STA_ROLE"; + case eLIM_BT_AMP_AP_ROLE: + return "eLIM_BT_AMP_AP_ROLE"; + default: + return "UNKNOWN"; + } +} + +/******************************************* + * FUNCTION: triggerBeaconGen() + * + * This logdump sends SIR_SCH_BEACON_GEN_IND to SCH. + * SCH then proceeds to generate a beacon template + * and copy it to the Host/SoftMAC shared memory + * + * TODO - This routine can safely be deleted once + * beacon generation is working + ******************************************/ +char *triggerBeaconGen( tpAniSirGlobal pMac, char *p ) +{ + tSirMsgQ mesg = { (tANI_U16) SIR_LIM_BEACON_GEN_IND, (tANI_U16) 0, (tANI_U32) 0 }; + + pMac->lim.gLimSmeState = eLIM_SME_NORMAL_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, NO_SESSION, pMac->lim.gLimSmeState)); + pMac->lim.gLimSystemRole = eLIM_AP_ROLE; + + p += log_sprintf( pMac, p, + "Posted SIR_LIM_BEACON_GEN_IND with result = %s\n", + (eSIR_SUCCESS == limPostMsgApi( pMac, &mesg ))? + "Success": "Failure" ); + + return p; +} + + +/******************************************* + * FUNCTION: testLimSendProbeRsp() + * + * This logdump sends SIR_MAC_MGMT_PROBE_RSP + * + * TODO - This routine can safely be deleted once + * the MGMT frame transmission is working + ******************************************/ +char *testLimSendProbeRsp( tpAniSirGlobal pMac, char *p ) +{ + tSirMacAddr peerMacAddr = { 0, 1, 2, 3, 4, 5 }; + tAniSSID ssId; + tANI_U32 len = SIR_MAC_MAX_SSID_LENGTH; + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + + if( eSIR_SUCCESS != wlan_cfgGetStr( pMac, + WNI_CFG_SSID, + (tANI_U8 *) &ssId.ssId, + (tANI_U32 *) &len )) + { + // Could not get SSID from CFG. Log error. + p += log_sprintf( pMac, p, "Unable to retrieve SSID\n" ); + return p; + } + else + ssId.length = (tANI_U8) len; + + p += log_sprintf( pMac, p, "Calling limSendProbeRspMgmtFrame...\n" ); + limSendProbeRspMgmtFrame( pMac, peerMacAddr, &ssId, -1, 1, psessionEntry , 0); + + return p; +} + + +static char *sendSmeScanReq(tpAniSirGlobal pMac, char *p) +{ + tSirMsgQ msg; + tSirSmeScanReq scanReq, *pScanReq; + + p += log_sprintf( pMac,p, "sendSmeScanReq: Preparing eWNI_SME_SCAN_REQ message\n"); + + pScanReq = (tSirSmeScanReq *) &scanReq; + + pScanReq = vos_mem_malloc(sizeof(tSirSmeScanReq)); + if (NULL == pScanReq) + { + p += log_sprintf( pMac,p,"sendSmeScanReq: AllocateMemory() failed \n"); + return p; + } + + pScanReq->messageType = eWNI_SME_SCAN_REQ; + pScanReq->minChannelTime = 30; + pScanReq->maxChannelTime = 130; + pScanReq->bssType = eSIR_INFRASTRUCTURE_MODE; + limGetMyMacAddr(pMac, pScanReq->bssId); + pScanReq->numSsid = 1; + vos_mem_copy((void *) &pScanReq->ssId[0].ssId, (void *)"Ivan", 4); + pScanReq->ssId[0].length = 4; + pScanReq->scanType = eSIR_ACTIVE_SCAN; + pScanReq->returnAfterFirstMatch = 0; + pScanReq->returnUniqueResults = 0; + /* Original code: + * pScanReq->returnFreshResults = SIR_BG_SCAN_PURGE_RESUTLS|SIR_BG_SCAN_RETURN_FRESH_RESULTS; + * + * Do not purge while starting a scan. Rome firmware sends results of + * roaming scan as normal entries. They land up in this scan cache. + * We should not lose those entries. + * This cached should be purged after filling in a query. + */ + pScanReq->returnFreshResults = SIR_BG_SCAN_RETURN_FRESH_RESULTS; + pScanReq->channelList.numChannels = 1; + pScanReq->channelList.channelNumber[0] = 6; + pScanReq->uIEFieldLen = 0; + pScanReq->uIEFieldOffset = sizeof(tSirSmeScanReq); + pScanReq->sessionId = 0; + + msg.type = eWNI_SME_SCAN_REQ; + msg.bodyptr = pScanReq; + msg.bodyval = 0; + p += log_sprintf( pMac,p, "sendSmeScanReq: limPostMsgApi(eWNI_SME_SCAN_REQ) \n"); + limPostMsgApi(pMac, &msg); + + return p; +} + +static char *sendSmeDisAssocReq(tpAniSirGlobal pMac, char *p,tANI_U32 arg1 ,tANI_U32 arg2) +{ + + tpDphHashNode pStaDs; + tSirMsgQ msg; + tSirSmeDisassocReq *pDisAssocReq; + tpPESession psessionEntry; + + //arg1 - assocId + //arg2 - sessionId + if( arg1 < 1 ) + { + p += log_sprintf( pMac,p,"Invalid session OR Assoc ID \n"); + return p; + } + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg2) )== NULL) + { + p += log_sprintf( pMac,p,"Session does not exist for given session Id \n"); + return p; + } + + pStaDs = dphGetHashEntry(pMac, (tANI_U16)arg1, &psessionEntry->dph.dphHashTable); + + if(NULL == pStaDs) + { + p += log_sprintf( pMac,p, "Could not find station with assocId = %d\n", arg1); + return p; + } + + pDisAssocReq = vos_mem_malloc(sizeof(tSirSmeDisassocReq)); + if (NULL == pDisAssocReq) + { + p += log_sprintf( pMac,p,"sendSmeDisAssocReq: AllocateMemory() failed \n"); + return p; + } + + if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->statypeForBss == STA_ENTRY_PEER)) { + sirCopyMacAddr(pDisAssocReq->bssId,psessionEntry->bssId); + sirCopyMacAddr(pDisAssocReq->peerMacAddr,psessionEntry->bssId); + } + if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + (LIM_IS_AP_ROLE(psessionEntry))) { + sirCopyMacAddr(pDisAssocReq->peerMacAddr,pStaDs->staAddr); + sirCopyMacAddr(pDisAssocReq->bssId,psessionEntry->bssId); + } + + pDisAssocReq->messageType = eWNI_SME_DISASSOC_REQ; + + pDisAssocReq->length = sizeof(tSirSmeDisassocReq); + + pDisAssocReq->reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; + + pDisAssocReq->sessionId = 0; + + pDisAssocReq->transactionId = 0; + + msg.type = eWNI_SME_DISASSOC_REQ; + msg.bodyptr = pDisAssocReq; + msg.bodyval = 0; + + p += log_sprintf( pMac,p, "sendSmeDisAssocReq: limPostMsgApi(eWNI_SME_DISASSOC_REQ) \n"); + limPostMsgApi(pMac, &msg); + + return p; +} + + +static char *sendSmeStartBssReq(tpAniSirGlobal pMac, char *p,tANI_U32 arg1) +{ + tSirMsgQ msg; + tSirSmeStartBssReq *pStartBssReq; + unsigned char *pBuf; + ePhyChanBondState cbMode; + tSirNwType nwType; + + p += log_sprintf( pMac,p, "sendSmeStartBssReq: Preparing eWNI_SME_START_BSS_REQ message\n"); + + if(arg1 > 2) + { + p += log_sprintf( pMac,p,"Invalid Argument1 \n"); + return p; + } + + pStartBssReq = vos_mem_malloc(sizeof(tSirSmeStartBssReq)); + if (NULL == pStartBssReq) + { + p += log_sprintf( pMac,p,"sendSmeStartBssReq: AllocateMemory() failed \n"); + return p; + } + + pStartBssReq->messageType = eWNI_SME_START_BSS_REQ; + pStartBssReq->length = 29; // 0x1d + + if(arg1 == 0) //BTAMP STATION + { + pStartBssReq->bssType = eSIR_BTAMP_STA_MODE; + + pStartBssReq->ssId.length = 5; + vos_mem_copy((void *) &pStartBssReq->ssId.ssId, (void *)"BTSTA", 5); + } + else if(arg1 == 1) //BTAMP AP + { + pStartBssReq->bssType = eSIR_BTAMP_AP_MODE; + pStartBssReq->ssId.length = 4; + vos_mem_copy((void *) &pStartBssReq->ssId.ssId, (void *)"BTAP", 4); + } + else //IBSS + { + pStartBssReq->bssType = eSIR_IBSS_MODE; + pStartBssReq->ssId.length = 4; + vos_mem_copy((void *) &pStartBssReq->ssId.ssId, (void *)"Ibss", 4); + } + + // Filling in channel ID 6 + pBuf = &(pStartBssReq->ssId.ssId[pStartBssReq->ssId.length]); + *pBuf = 6; + pBuf++; + + // Filling in CB mode + cbMode = PHY_SINGLE_CHANNEL_CENTERED; + vos_mem_copy(pBuf, (tANI_U8 *)&cbMode, sizeof(ePhyChanBondState)); + pBuf += sizeof(ePhyChanBondState); + + // Filling in RSN IE Length to zero + vos_mem_set(pBuf, sizeof(tANI_U16), 0); //tSirRSNie->length + pBuf += sizeof(tANI_U16); + + // Filling in NW Type + nwType = eSIR_11G_NW_TYPE; + vos_mem_copy(pBuf, (tANI_U8 *)&nwType, sizeof(tSirNwType)); + pBuf += sizeof(tSirNwType); + + /* ---- To be filled by LIM later ---- + pStartBssReq->operationalRateSet + pStartBssReq->extendedRateSet + pStartBssReq->dot11mode + pStartBssReq->bssId + pStartBssReq->selfMacAddr + pStartBssReq->beaconInterval + pStartBssReq->sessionId = 0; + pStartBssReq->transactionId = 0; + * ------------------------------------ */ + + msg.type = eWNI_SME_START_BSS_REQ; + msg.bodyptr = pStartBssReq; + msg.bodyval = 0; + p += log_sprintf( pMac,p, "sendSmeStartBssReq: limPostMsgApi(eWNI_SME_START_BSS_REQ) \n"); + limPostMsgApi(pMac, &msg); + + return p; +} + +static char *sendSmeStopBssReq(tpAniSirGlobal pMac, char *p, tANI_U32 sessionId) +{ + tSirMsgQ msg; + tSirSmeStopBssReq stopBssReq, *pStopBssReq; + tANI_U16 msgLen = 0; + tpPESession psessionEntry; + + psessionEntry = peFindSessionBySessionId(pMac, (tANI_U8)sessionId); + if ( psessionEntry == NULL ) + { + limLog(pMac, LOGP, FL("Session entry does not exist for given sessionID \n")); + return p; + } + + p += log_sprintf( pMac,p, "sendSmeStopBssReq: Preparing eWNI_SME_STOP_BSS_REQ message\n"); + pStopBssReq = (tSirSmeStopBssReq *) &stopBssReq; + + pStopBssReq = vos_mem_malloc(sizeof(tSirSmeStopBssReq)); + if (NULL == pStopBssReq) + { + p += log_sprintf( pMac,p,"sendSmeStopBssReq: AllocateMemory() failed \n"); + return p; + } + + pStopBssReq->messageType = eWNI_SME_STOP_BSS_REQ; + msgLen += sizeof(tANI_U32); // msgType + length + + pStopBssReq->reasonCode = eSIR_SME_SUCCESS; + msgLen += sizeof(tSirResultCodes); + + vos_mem_copy((void *) &pStopBssReq->bssId, (void *)psessionEntry->bssId, 6); + msgLen += sizeof(tSirMacAddr); + + pStopBssReq->sessionId = (tANI_U8)sessionId; + msgLen += sizeof(tANI_U8); + + pStopBssReq->transactionId = 0; + msgLen += sizeof(tANI_U16); + + pStopBssReq->length = msgLen; + + msg.type = eWNI_SME_STOP_BSS_REQ; + msg.bodyptr = pStopBssReq; + msg.bodyval = 0; + p += log_sprintf( pMac,p, "sendSmeStopBssReq: limPostMsgApi(eWNI_SME_STOP_BSS_REQ) \n"); + limPostMsgApi(pMac, &msg); + + return p; +} + +static char *sendSmeJoinReq(tpAniSirGlobal pMac, char *p) +{ + tSirMsgQ msg; + tSirSmeJoinReq *pJoinReq; + unsigned char *pBuf; + tANI_U16 msgLen = 307; + + tANI_U8 msgDump[307] = { + 0x06, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, + 0xDE, 0xAD, 0xBA, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x21, 0x04, 0x02, 0x00, 0x00, + 0x00, 0x01, 0x1E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0xA8, 0x85, 0x4F, 0x7A, 0x00, 0x06, 0x41, + 0x6E, 0x69, 0x4E, 0x65, 0x74, 0x01, 0x04, 0x82, 0x84, 0x8B, + 0x96, 0x03, 0x01, 0x06, 0x07, 0x06, 0x55, 0x53, 0x49, 0x01, + 0x0E, 0x1E, 0x2A, 0x01, 0x00, 0x32, 0x08, 0x0C, 0x12, 0x18, + 0x24, 0x30, 0x48, 0x60, 0x6C, 0x2D, 0x1A, 0xEE, 0x11, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3D, 0x16, 0x06, 0x07, 0x11, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x18, 0x00, + 0x50, 0xF2, 0x02, 0x01, 0x01, 0x01, 0x00, 0x03, 0xA4, 0x00, + 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, + 0x32, 0x2F, 0x00, 0xDD, 0x14, 0x00, 0x0A, 0xF5, 0x00, 0x03, + 0x01, 0x03, 0x05, 0x0A, 0x02, 0x80, 0xC0, 0x12, 0x06, 0xFF, + 0xFF, 0xFF, 0xFF, 0xB6, 0x0D, 0xDD, 0x6E, 0x00, 0x50, 0xF2, + 0x04, 0x10, 0x4A, 0x00, 0x01, 0x10, 0x10, 0x44, 0x00, 0x01, + 0x01, 0x10, 0x3B, 0x00, 0x01, 0x03, 0x10, 0x47, 0x00, 0x10, + 0xDB, 0xC6, 0x77, 0x28, 0xB9, 0xF3, 0xD8, 0x58, 0x86, 0xFF, + 0xFC, 0x6B, 0xB6, 0xB9, 0x27, 0x79, 0x10, 0x21, 0x00, 0x08, + 0x51, 0x75, 0x61, 0x6C, 0x63, 0x6F, 0x6D, 0x6D, 0x10, 0x23, + 0x00, 0x07, 0x57, 0x46, 0x52, 0x34, 0x30, 0x33, 0x31, 0x10, + 0x24, 0x00, 0x06, 0x4D, 0x4E, 0x31, 0x32, 0x33, 0x34, 0x10, + 0x42, 0x00, 0x06, 0x53, 0x4E, 0x31, 0x32, 0x33, 0x34, 0x10, + 0x54, 0x00, 0x08, 0x00, 0x06, 0x00, 0x50, 0xF2, 0x04, 0x00, + 0x01, 0x10, 0x11, 0x00, 0x06, 0x31, 0x31, 0x6E, 0x2D, 0x41, + 0x50, 0x10, 0x08, 0x00, 0x02, 0x01, 0x8E + }; + + pJoinReq = vos_mem_malloc(msgLen); + if (NULL == pJoinReq) + { + p += log_sprintf( pMac,p,"sendSmeJoinReq: AllocateMemory() failed \n"); + return p; + } + + pBuf = (unsigned char *)pJoinReq; + vos_mem_copy(pBuf, (tANI_U8 *)msgDump, msgLen); + + msg.type = eWNI_SME_JOIN_REQ; + msg.bodyptr = pJoinReq; + msg.bodyval = 0; + limPostMsgApi(pMac, &msg); + + return p; +} + + +static char *printSessionInfo(tpAniSirGlobal pMac, char *p) +{ + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + tANI_U8 i; + + p += log_sprintf( pMac, p, "Dump PE Session \n"); + + for(i=0; i < pMac->lim.maxBssId; i++) + { + if( pMac->lim.gpSession[i].valid ) + { + psessionEntry = &pMac->lim.gpSession[i]; + p += log_sprintf( pMac,p, "*****************************************\n"); + p += log_sprintf( pMac,p, " PE Session [%d] \n", i); + p += log_sprintf( pMac,p, "available: %d \n", psessionEntry->available); + p += log_sprintf( pMac,p, "peSessionId: %d, smeSessionId: %d, transactionId: %d \n", + psessionEntry->peSessionId, psessionEntry->smeSessionId, psessionEntry->smeSessionId); + p += log_sprintf( pMac,p, "bssId: %02X:%02X:%02X:%02X:%02X:%02X \n", + psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], + psessionEntry->bssId[3], psessionEntry->bssId[4], psessionEntry->bssId[5]); + p += log_sprintf( pMac,p, "selfMacAddr: %02X:%02X:%02X:%02X:%02X:%02X \n", + psessionEntry->selfMacAddr[0], psessionEntry->selfMacAddr[1], psessionEntry->selfMacAddr[2], + psessionEntry->selfMacAddr[3], psessionEntry->selfMacAddr[4], psessionEntry->selfMacAddr[5]); + p += log_sprintf( pMac,p, "bssIdx: %d \n", psessionEntry->bssIdx); + p += log_sprintf( pMac,p, "valid: %d \n", psessionEntry->valid); + p += log_sprintf( pMac,p, "limMlmState: (%d) %s ", psessionEntry->limMlmState, limMlmStateStr(psessionEntry->limMlmState) ); + p += log_sprintf( pMac,p, "limPrevMlmState: (%d) %s ", psessionEntry->limPrevMlmState, limMlmStateStr(psessionEntry->limMlmState) ); + p += log_sprintf( pMac,p, "limSystemRole: (%d) %s \n", GET_LIM_SYSTEM_ROLE(psessionEntry), getRole(psessionEntry->limSystemRole) ); + p += log_sprintf( pMac,p, "bssType: (%d) %s \n", psessionEntry->bssType, limBssTypeStr(psessionEntry->bssType)); + p += log_sprintf( pMac,p, "operMode: %d \n", psessionEntry->operMode); + p += log_sprintf( pMac,p, "dot11mode: %d \n", psessionEntry->dot11mode); + p += log_sprintf( pMac,p, "htCapability: %d \n", psessionEntry->htCapability); + p += log_sprintf( pMac,p, "limRFBand: %d \n", psessionEntry->limRFBand); + p += log_sprintf( pMac,p, "limIbssActive: %d \n", psessionEntry->limIbssActive); + p += log_sprintf( pMac,p, "limCurrentAuthType: %d \n", psessionEntry->limCurrentAuthType); + p += log_sprintf( pMac,p, "limCurrentBssCaps: %d \n", psessionEntry->limCurrentBssCaps); + p += log_sprintf( pMac,p, "limCurrentBssQosCaps: %d \n", psessionEntry->limCurrentBssQosCaps); + p += log_sprintf( pMac,p, "limCurrentBssPropCap: %d \n", psessionEntry->limCurrentBssPropCap); + p += log_sprintf( pMac,p, "limSentCapsChangeNtf: %d \n", psessionEntry->limSentCapsChangeNtf); + p += log_sprintf( pMac,p, "LimAID: %d \n", psessionEntry->limAID); + p += log_sprintf( pMac,p, "ReassocbssId: %02X:%02X:%02X:%02X:%02X:%02X \n", + psessionEntry->limReAssocbssId[0], psessionEntry->limReAssocbssId[1], psessionEntry->limReAssocbssId[2], + psessionEntry->limReAssocbssId[3], psessionEntry->limReAssocbssId[4], psessionEntry->limReAssocbssId[5]); + p += log_sprintf( pMac,p, "limReassocChannelId: %d \n", psessionEntry->limReassocChannelId); + p += log_sprintf( pMac,p, "limReassocBssCaps: %d \n", psessionEntry->limReassocBssCaps); + p += log_sprintf( pMac,p, "limReassocBssQosCaps: %d \n", psessionEntry->limReassocBssQosCaps); + p += log_sprintf( pMac,p, "limReassocBssPropCap: %d \n", psessionEntry->limReassocBssPropCap); + p += log_sprintf( pMac,p, "********************************************\n"); + } + } + return p; +} + +void +limSetEdcaBcastACMFlag(tpAniSirGlobal pMac, tANI_U32 ac, tANI_U32 acmFlag) +{ + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + psessionEntry->gLimEdcaParamsBC[ac].aci.acm = (tANI_U8)acmFlag; + psessionEntry->gLimEdcaParamSetCount++; + schSetFixedBeaconFields(pMac,psessionEntry); +} + +static char * +limDumpEdcaParams(tpAniSirGlobal pMac, char *p) +{ + tANI_U8 i = 0; + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + p += log_sprintf( pMac,p, "EDCA parameter set count = %d\n", psessionEntry->gLimEdcaParamSetCount); + p += log_sprintf( pMac,p, "Broadcast parameters\n"); + p += log_sprintf( pMac,p, "AC\tACI\tACM\tAIFSN\tCWMax\tCWMin\tTxopLimit\t\n"); + for(i = 0; i < MAX_NUM_AC; i++) + { + //right now I am just interested in ACM bit. this can be extended for all other EDCA paramters. + p += log_sprintf( pMac,p, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", i, + psessionEntry->gLimEdcaParamsBC[i].aci.aci, psessionEntry->gLimEdcaParamsBC[i].aci.acm, + psessionEntry->gLimEdcaParamsBC[i].aci.aifsn, psessionEntry->gLimEdcaParamsBC[i].cw.max, + psessionEntry->gLimEdcaParamsBC[i].cw.min, psessionEntry->gLimEdcaParamsBC[i].txoplimit); + } + + p += log_sprintf( pMac,p, "\nLocal parameters\n"); + p += log_sprintf( pMac,p, "AC\tACI\tACM\tAIFSN\tCWMax\tCWMin\tTxopLimit\t\n"); + for(i = 0; i < MAX_NUM_AC; i++) + { + //right now I am just interested in ACM bit. this can be extended for all other EDCA paramters. + p += log_sprintf( pMac,p, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", i, + psessionEntry->gLimEdcaParams[i].aci.aci, psessionEntry->gLimEdcaParams[i].aci.acm, + psessionEntry->gLimEdcaParams[i].aci.aifsn, psessionEntry->gLimEdcaParams[i].cw.max, + psessionEntry->gLimEdcaParams[i].cw.min, psessionEntry->gLimEdcaParams[i].txoplimit); + } + + return p; +} + + +static char* limDumpTspecEntry(tpAniSirGlobal pMac, char *p, tANI_U32 tspecEntryNo) +{ + tpLimTspecInfo pTspecList; + if(tspecEntryNo >= LIM_NUM_TSPEC_MAX) + { + p += log_sprintf( pMac,p, "Tspec Entry no. %d is out of allowed range(0 .. %d)\n", + tspecEntryNo, (LIM_NUM_TSPEC_MAX - 1)); + return p; + } + pTspecList = &pMac->lim.tspecInfo[tspecEntryNo]; + if (pTspecList->inuse) + p += log_sprintf( pMac,p, "Entry %d is VALID\n", tspecEntryNo); + else + { + p += log_sprintf( pMac,p, "Entry %d is UNUSED\n", tspecEntryNo); + return p; + } + p += log_sprintf( pMac,p, "\tSta %0x:%0x:%0x:%0x:%0x:%0x, AID %d, Index %d\n", + pTspecList->staAddr[0], pTspecList->staAddr[1], + pTspecList->staAddr[2], pTspecList->staAddr[3], + pTspecList->staAddr[4], pTspecList->staAddr[5], + pTspecList->assocId, pTspecList->idx); + p += log_sprintf( pMac,p, "\tType %d, Length %d, ackPolicy %d, userPrio %d, accessPolicy = %d, Dir %d, tsid %d\n", + pTspecList->tspec.type, pTspecList->tspec.length, + pTspecList->tspec.tsinfo.traffic.ackPolicy, pTspecList->tspec.tsinfo.traffic.userPrio, + pTspecList->tspec.tsinfo.traffic.accessPolicy, pTspecList->tspec.tsinfo.traffic.direction, + pTspecList->tspec.tsinfo.traffic.tsid); + p += log_sprintf( pMac,p, "\tPsb %d, Agg %d, TrafficType %d, schedule %d; msduSz: nom %d, max %d\n", + pTspecList->tspec.tsinfo.traffic.psb, pTspecList->tspec.tsinfo.traffic.aggregation, + pTspecList->tspec.tsinfo.traffic.trafficType, pTspecList->tspec.tsinfo.schedule.schedule, + pTspecList->tspec.nomMsduSz, pTspecList->tspec.maxMsduSz); + p += log_sprintf( pMac,p, "\tSvcInt: Min %d, Max %d; dataRate: Min %d, mean %d, peak %d\n", + pTspecList->tspec.minSvcInterval, pTspecList->tspec.maxSvcInterval, + pTspecList->tspec.minDataRate, pTspecList->tspec.meanDataRate, + pTspecList->tspec.peakDataRate); + p += log_sprintf( pMac,p, "\tmaxBurstSz %d, delayBound %d, minPhyRate %d, surplusBw %d, mediumTime %d\n", + pTspecList->tspec.maxBurstSz, pTspecList->tspec.delayBound, + pTspecList->tspec.minPhyRate, pTspecList->tspec.surplusBw, + pTspecList->tspec.mediumTime); + + return p; +} + +static char* dumpTspecTableSummary(tpAniSirGlobal pMac, tpLimTspecInfo pTspecList, char *p, int ctspec) +{ + p += log_sprintf( pMac, p, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + ctspec, pTspecList->idx, pTspecList->assocId, + pTspecList->tspec.tsinfo.traffic.ackPolicy, pTspecList->tspec.tsinfo.traffic.userPrio, + pTspecList->tspec.tsinfo.traffic.psb, pTspecList->tspec.tsinfo.traffic.aggregation, + pTspecList->tspec.tsinfo.traffic.accessPolicy, pTspecList->tspec.tsinfo.traffic.direction, + pTspecList->tspec.tsinfo.traffic.tsid, pTspecList->tspec.tsinfo.traffic.trafficType); + + return p; +} + + +static char* limDumpDphTableSummary(tpAniSirGlobal pMac,char *p) +{ + tANI_U8 i, j; + p += log_sprintf( pMac,p, "DPH Table dump\n"); + + for(j=0; j < pMac->lim.maxBssId; j++) + { + /* Find first free room in session table */ + if(pMac->lim.gpSession[j].valid) + { + p += log_sprintf( pMac,p, "aid staId bssid encPol qosMode wme 11e wsm staaddr\n"); + for(i = 0; i < pMac->lim.gpSession[j].dph.dphHashTable.size; i++) + { + if (pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].added) + { + p += log_sprintf( pMac,p, "%d %d %d %d %d %d %d %d %x:%x:%x:%x:%x:%x\n", + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].assocId, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staIndex, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].bssId, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].encPolicy, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].qosMode, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].wmeEnabled, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].lleEnabled, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].wsmEnabled, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAuthenticated, + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAddr[0], + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAddr[1], + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAddr[2], + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAddr[3], + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAddr[4], + pMac->lim.gpSession[j].dph.dphHashTable.pDphNodeArray[i].staAddr[5]); + } + } + } + } + return p; +} + +// add the specified tspec to the tspec list +static char* limDumpTsecTable( tpAniSirGlobal pMac, char* p) +{ + int ctspec; + tpLimTspecInfo pTspecList = &pMac->lim.tspecInfo[0]; + + p += log_sprintf( pMac,p, "=======LIM TSPEC TABLE DUMP\n"); + p += log_sprintf( pMac,p, "Num\tIdx\tAID\tAckPol\tUP\tPSB\tAgg\tAccessPol\tDir\tTSID\ttraffic\n"); + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) + { + if (pTspecList->inuse) + p = dumpTspecTableSummary(pMac, pTspecList, p, ctspec); + } + return p; +} + +static char * +dump_lim_tspec_table( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = limDumpTsecTable(pMac, p); + return p; +} + +static char * +dump_lim_tspec_entry( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + p = limDumpTspecEntry(pMac, p, arg1); + return p; +} + +static char * +dump_lim_dph_table_summary( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + p = limDumpDphTableSummary(pMac, p); + return p; +} + + +static char * +dump_lim_link_monitor_stats( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tANI_U32 ind, val; + + (void) arg2; (void) arg3; (void) arg4; + p += log_sprintf( pMac,p, "\n ----- LIM Heart Beat Stats ----- \n"); + p += log_sprintf( pMac,p, "No. of HeartBeat Failures in LinkEst State = %d\n", + pMac->lim.gLimHBfailureCntInLinkEstState); + p += log_sprintf( pMac,p, "No. of Probe Failures after HB failed = %d\n", + pMac->lim.gLimProbeFailureAfterHBfailedCnt); + p += log_sprintf( pMac,p, "No. of HeartBeat Failures in Other States = %d\n", + pMac->lim.gLimHBfailureCntInOtherStates); + + if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val) == eSIR_SUCCESS) + p += log_sprintf( pMac,p, "Cfg HeartBeat Threshold = %d\n", val); + + p += log_sprintf( pMac,p, "# Beacons Rcvd in HB interval # of times\n"); + + for (ind = 1; ind < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL; ind++) + { + p += log_sprintf( pMac,p, "\t\t\t\t\t\t\t\t%2d\t\t\t\t\t\t\t\t\t\t\t%8d\n", ind, + pMac->lim.gLimHeartBeatBeaconStats[ind]); + } + p += log_sprintf( pMac,p, "\t\t\t\t\t\t\t\t%2d>\t\t\t\t\t\t\t\t\t\t%8d\n", + MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL-1, + pMac->lim.gLimHeartBeatBeaconStats[0]); + + if (arg1 != 0) + { + for (ind = 0; ind < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL; ind++) + pMac->lim.gLimHeartBeatBeaconStats[ind] = 0; + + pMac->lim.gLimHBfailureCntInLinkEstState = 0; + pMac->lim.gLimProbeFailureAfterHBfailedCnt = 0; + pMac->lim.gLimHBfailureCntInOtherStates = 0; + + p += log_sprintf( pMac,p, "\nReset HeartBeat Statistics\n"); + } + return p; +} + +static char * +dump_lim_edca_params( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = limDumpEdcaParams(pMac, p); + return p; +} + +static char * +dump_lim_acm_set( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg3; (void) arg4; + limSetEdcaBcastACMFlag(pMac, arg1 /*ac(0..3)*/, arg2 /*(acmFlag = 1 to set ACM*/); + return p; +} + +static char * +dump_lim_bgscan_toggle( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + pMac->lim.gLimForceBackgroundScanDisable = (arg1 == 0) ? 1 : 0; + p += log_sprintf( pMac,p, "Bgnd scan is now %s\n", + (pMac->lim.gLimForceBackgroundScanDisable) ? "Disabled" : "On"); + return p; +} + +static char * +dump_lim_linkmonitor_toggle( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + pMac->sys.gSysEnableLinkMonitorMode = (arg1 == 0) ? 0 : 1; + p += log_sprintf( pMac,p, "LinkMonitor mode enable = %s\n", + (pMac->sys.gSysEnableLinkMonitorMode) ? "On" : "Off"); + return p; +} + +static char * +dump_lim_proberesp_toggle( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + pMac->lim.gLimProbeRespDisableFlag = (arg1 == 0) ? 0 : 1; + p += log_sprintf( pMac,p, "ProbeResponse mode disable = %s\n", + (pMac->lim.gLimProbeRespDisableFlag) ? "On" : "Off"); + return p; +} + +static char * +dump_lim_del_sta( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + + tpDphHashNode pStaDs; + tLimMlmDisassocInd mlmDisassocInd; + tpPESession psessionEntry; + tANI_U8 reasonCode = eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg2) )== NULL) + { + p += log_sprintf( pMac,p,"Session does not exist for given session Id \n"); + return p; + } + + pStaDs = dphGetHashEntry(pMac, (tANI_U16)arg1, &psessionEntry->dph.dphHashTable); + + if(NULL == pStaDs) + { + p += log_sprintf( pMac,p, "Could not find station with assocId = %d\n", arg1); + return p; + } + + if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) + { + p += log_sprintf( pMac,p, "received Disassoc frame from peer that is in state %X \n", pStaDs->mlmStaContext.mlmState); + return p; + } + + pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC; + pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode; + + // Issue Disassoc Indication to SME. + vos_mem_copy((tANI_U8 *) &mlmDisassocInd.peerMacAddr, + (tANI_U8 *) pStaDs->staAddr, sizeof(tSirMacAddr)); + mlmDisassocInd.reasonCode = reasonCode; + mlmDisassocInd.disassocTrigger = eLIM_PEER_ENTITY_DISASSOC; + + mlmDisassocInd.sessionId = psessionEntry->peSessionId; + + limPostSmeMessage(pMac, LIM_MLM_DISASSOC_IND, (tANI_U32 *) &mlmDisassocInd); + // Receive path cleanup + limCleanupRxPath(pMac, pStaDs,psessionEntry); + return p; +} + + + + +static char * +set_lim_prot_cfg( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + +/********************************** +* Protection Enable +* +*LOWER byte for associated stations +*UPPER byte for overlapping stations. +*11g ==> protection from 11g +*11b ==> protection from 11b +*each byte will have the following info +*bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 +*reserved reserved RIFS Lsig n-GF ht20 11g 11b +********************************** +WNI_CFG_PROTECTION_ENABLED I 4 9 +V RW NP RESTART +LIM +0 0xff 0xff +V RW NP RESTART +LIM +0 0xffff 0xffff + +#ENUM FROM_llB 0 +#ENUM FROM_llG 1 +#ENUM HT_20 2 +#ENUM NON_GF 3 +#ENUM LSIG_TXOP 4 +#ENUM RIFS 5 +#ENUM OLBC_FROM_llB 8 +#ENUM OLBC_FROM_llG 9 +#ENUM OLBC_HT20 10 +#ENUM OLBC_NON_GF 11 +#ENUM OLBC_LSIG_TXOP 12 +#ENUM OLBC_RIFS 13 +******************************************/ + if(1 == arg1) + dump_cfg_set(pMac, WNI_CFG_PROTECTION_ENABLED, 0xff, arg3, arg4, p); + else if(2 == arg1) + dump_cfg_set(pMac, WNI_CFG_PROTECTION_ENABLED, arg2 & 0xff, arg3, arg4, p); + else + { + p += log_sprintf( pMac,p, "To set protection config:\n"); + p += log_sprintf( pMac,p, "arg1: operation type(1 -> set to Default 0xff, 2-> set to a arg2, else print help)\n"); + } + return p; +} + + +static char * +dump_lim_set_protection_control( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + dump_cfg_set(pMac, WNI_CFG_FORCE_POLICY_PROTECTION, arg1, arg2, arg3, p); + limSetCfgProtection(pMac, NULL); + return p; +} + + +static char * +dump_lim_send_SM_Power_Mode( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirMsgQ msg; + tpSirMbMsg pMBMsg; + tSirMacHTMIMOPowerSaveState state; + + p += log_sprintf( pMac,p, "%s: Verifying the Arguments\n", __func__); + if ((arg1 > 3) || (arg1 == 2)) + { + p += log_sprintf( pMac,p, "Invalid Argument , enter one of the valid states\n"); + return p; + } + + state = (tSirMacHTMIMOPowerSaveState) arg1; + + pMBMsg = vos_mem_malloc(WNI_CFG_MB_HDR_LEN + sizeof(tSirMacHTMIMOPowerSaveState)); + if (NULL == pMBMsg) + { + p += log_sprintf( pMac,p, "pMBMsg is NULL\n"); + return p; + } + pMBMsg->type = eWNI_PMC_SMPS_STATE_IND; + pMBMsg->msgLen = (tANI_U16)(WNI_CFG_MB_HDR_LEN + sizeof(tSirMacHTMIMOPowerSaveState)); + vos_mem_copy(pMBMsg->data, &state, sizeof(tSirMacHTMIMOPowerSaveState)); + + msg.type = eWNI_PMC_SMPS_STATE_IND; + msg.bodyptr = pMBMsg; + msg.bodyval = 0; + + if (limPostMsgApi(pMac, &msg) != TX_SUCCESS) + { + p += log_sprintf( pMac,p, "Updating the SMPower Request has failed \n"); + vos_mem_free(pMBMsg); + } + else + { + p += log_sprintf( pMac,p, "Updating the SMPower Request is Done \n"); + } + + return p; +} + + + + +static char * +dump_lim_addba_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirRetStatus status; + tpDphHashNode pSta; + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + + (void) arg4; + + // Get DPH Sta entry for this ASSOC ID + pSta = dphGetHashEntry( pMac, (tANI_U16) arg1, &psessionEntry->dph.dphHashTable); + if( NULL == pSta ) + { + p += log_sprintf( pMac, p, + "\n%s: Could not find entry in DPH table for assocId = %d\n", + __func__, + arg1 ); + } + else + { + status = limPostMlmAddBAReq( pMac, pSta, (tANI_U8) arg2, (tANI_U16) arg3,psessionEntry); + p += log_sprintf( pMac, p, + "\n%s: Attempted to send an ADDBA Req to STA Index %d, for TID %d. Send Status = %s\n", + __func__, + pSta->staIndex, + arg2, + limResultCodeStr( status )); + } + + return p; +} + +static char * +dump_lim_delba_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ +tSirRetStatus status; +tpDphHashNode pSta; + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + // Get DPH Sta entry for this ASSOC ID + pSta = dphGetHashEntry( pMac, (tANI_U16) arg1, &psessionEntry->dph.dphHashTable ); + if( NULL == pSta ) + { + p += log_sprintf( pMac, p, + "\n%s: Could not find entry in DPH table for assocId = %d\n", + __func__, + arg1 ); + } + else + { + status = limPostMlmDelBAReq( pMac, pSta, (tANI_U8) arg2, (tANI_U8) arg3, (tANI_U16) arg4 ,psessionEntry); + p += log_sprintf( pMac, p, + "\n%s: Attempted to send a DELBA Ind to STA Index %d, " + "as the BA \"%s\" for TID %d, with Reason code %d. " + "Send Status = %s\n", + __func__, + pSta->staIndex, + (arg2 == 1)? "Initiator": "Recipient", + arg3, // TID + arg4, // Reason Code + limResultCodeStr( status )); + } + + return p; +} + +static char * +dump_lim_ba_timeout( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + +/* FIXME: NO HAL IN UMAC for PRIMA */ + + p += log_sprintf( pMac, p, + "\n%s: Attempted to trigger a BA Timeout Ind to STA Index %d, for TID %d, Direction %d\n", + __func__, + arg1, // STA index + arg2, // TID + arg3 ); // BA Direction + + return p; +} + +static char * +dump_lim_list_active_ba( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ +tANI_U32 i; +tpDphHashNode pSta; + + +tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + (void) arg2; (void) arg3; (void) arg4; + + // Get DPH Sta entry for this ASSOC ID + pSta = dphGetHashEntry( pMac, (tANI_U16) arg1, &psessionEntry->dph.dphHashTable); + if( NULL == pSta ) + { + p += log_sprintf( pMac, p, + "\n%s: Could not find entry in DPH table for assocId = %d\n", + __func__, + arg1 ); + } + else + { + p += log_sprintf( pMac, p, + "\nList of Active BA sessions for STA Index %d with Assoc ID %d\n", + pSta->staIndex, + arg1 ); + + p += log_sprintf( pMac, p, "TID\tRxBA\tTxBA\tRxBufferSize\tTxBufferSize\tRxBATimeout\tTxBATimeout\n"); + for( i = 0; i < STACFG_MAX_TC; i ++ ) + p += log_sprintf( pMac, p, + "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + i, // TID + pSta->tcCfg[i].fUseBARx, + pSta->tcCfg[i].fUseBATx, + pSta->tcCfg[i].rxBufSize, + pSta->tcCfg[i].txBufSize, + pSta->tcCfg[i].tuRxBAWaitTimeout, + pSta->tcCfg[i].tuTxBAWaitTimeout ); + } + + return p; +} + + +static char * +dump_lim_AddBA_DeclineStat( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + + int Tid, Enable=(arg1 & 0x1); + tANI_U8 val; + + if (arg1 > 1) { + log_sprintf( pMac,p, "%s:Invalid Value is entered for Enable/Disable \n", __func__ ); + arg1 &= 1; + } + + val = pMac->lim.gAddBA_Declined; + + if (arg2 > 7) { + log_sprintf( pMac,p, "%s:Invalid Value is entered for Tid \n", __func__ ); + Tid = arg2 & 0x7; + } else + Tid = arg2; + + + if ( Enable) + val |= Enable << Tid; + else + val &= ~(0x1 << Tid); + + if (cfgSetInt(pMac, (tANI_U16)WNI_CFG_ADDBA_REQ_DECLINE, (tANI_U32) val) != eSIR_SUCCESS) + log_sprintf( pMac,p, "%s:Config Set for ADDBA REQ Decline has failed \n", __func__ ); + + log_sprintf( pMac,p, "%s:Decline value %d is being set for TID %d ,\n \tAddBA_Decline Cfg value is %d \n", __func__ , arg1, Tid, (int) val); + + return p; +} +static char * +dump_lim_set_dot11_mode( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + + tpPESession psessionEntry =&pMac->lim.gpSession[0]; + dump_cfg_set(pMac, WNI_CFG_DOT11_MODE, arg1, arg2, arg3, p); + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) + schSetFixedBeaconFields(pMac,psessionEntry); + p += log_sprintf( pMac,p, "The Dot11 Mode is set to %d", (tANI_U8)psessionEntry->dot11mode); + return p; +} + + +static char* dump_lim_update_cb_Mode(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tANI_U32 localPwrConstraint; + tpPESession psessionEntry = peFindSessionBySessionId(pMac, arg1); + + if (psessionEntry == NULL) + { + p += log_sprintf( pMac, p, "Invalid sessionId: %d \n ", arg1); + return p; + } + + if ( !psessionEntry->htCapability ) + { + p += log_sprintf( pMac,p, "Error: Dot11 mode is non-HT, can not change the CB mode.\n"); + return p; + } + + psessionEntry->htSupportedChannelWidthSet = arg2?1:0; + psessionEntry->htRecommendedTxWidthSet = psessionEntry->htSupportedChannelWidthSet; + psessionEntry->htSecondaryChannelOffset = arg2; + + if(eSIR_SUCCESS != cfgSetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, + arg2 ? WNI_CFG_CHANNEL_BONDING_MODE_ENABLE : WNI_CFG_CHANNEL_BONDING_MODE_DISABLE)) + p += log_sprintf(pMac,p, "cfgSetInt failed for WNI_CFG_CHANNEL_BONDING_MODE\n"); + + wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint); + + limSendSwitchChnlParams(pMac, psessionEntry->currentOperChannel, + psessionEntry->htSecondaryChannelOffset, + (tPowerdBm) localPwrConstraint, + psessionEntry->peSessionId, VOS_FALSE); + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) + schSetFixedBeaconFields(pMac,psessionEntry); + + return p; +} + +static char* dump_lim_abort_scan(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + //csrScanAbortMacScan(pMac); + return p; + +} + +static char* dump_lim_start_stop_bg_scan(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + + if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); + } + + if(arg1 == 1) + { + if (tx_timer_activate( + &pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) + { + pMac->lim.gLimBackgroundScanTerminate = TRUE; + } + else + { + pMac->lim.gLimBackgroundScanTerminate = FALSE; + pMac->lim.gLimBackgroundScanDisable = false; + pMac->lim.gLimForceBackgroundScanDisable = false; + } + } + else + { + pMac->lim.gLimBackgroundScanTerminate = TRUE; + pMac->lim.gLimBackgroundScanChannelId = 0; + pMac->lim.gLimBackgroundScanDisable = true; + pMac->lim.gLimForceBackgroundScanDisable = true; + } + return p; + +} + +static char* +dump_lim_get_pe_statistics(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tpAniGetPEStatsReq pReq; + tANI_U32 statsMask; + + (void) arg2; (void) arg3; (void) arg4; + + + switch(arg1) + { + case 1: + statsMask = PE_SUMMARY_STATS_INFO; + break; + case 2: + statsMask = PE_GLOBAL_CLASS_A_STATS_INFO; + break; + case 3: + statsMask = PE_GLOBAL_CLASS_B_STATS_INFO; + break; + case 4: + statsMask = PE_GLOBAL_CLASS_C_STATS_INFO; + break; + case 5: + statsMask = PE_PER_STA_STATS_INFO; + break; + default: + return p; + } + + pReq = vos_mem_malloc(sizeof(tAniGetPEStatsReq)); + if (NULL == pReq) + { + p += log_sprintf( pMac,p, "Error: Unable to allocate memory.\n"); + return p; + } + + vos_mem_set(pReq, sizeof(*pReq), 0); + + pReq->msgType = eWNI_SME_GET_STATISTICS_REQ; + pReq->statsMask = statsMask; + pReq->staId = (tANI_U16)arg2; + + pMac->lim.gLimRspReqd = eANI_BOOLEAN_TRUE; + limPostSmeMessage(pMac, eWNI_SME_GET_STATISTICS_REQ, (tANI_U32 *) pReq); + + return p; + +} + +extern char* setLOGLevel( tpAniSirGlobal pMac, char *p, tANI_U32 module, tANI_U32 level ); +static char * +dump_lim_set_log_level( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + p = setLOGLevel(pMac, p, arg1, arg2); + return p; +} + +static char * +dump_lim_update_log_level( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + vos_trace_setLevel( arg1, arg2 ); + return p; +} + +static char * +dump_lim_scan_req_send( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = sendSmeScanReq(pMac, p); + return p; +} + +static char * +dump_lim_send_start_bss_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = sendSmeStartBssReq(pMac, p,arg1); + return p; +} + +static char * +dump_lim_send_join_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = sendSmeJoinReq(pMac, p); + return p; +} + +static char * +dump_lim_send_disassoc_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + + p = sendSmeDisAssocReq(pMac, p, arg1 ,arg2); + return p; +} + +static char * +dump_lim_stop_bss_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + p = sendSmeStopBssReq(pMac, p, arg1); + return p; +} + + +static char * +dump_lim_session_print( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = printSessionInfo(pMac, p); + return p; +} + +static char * +dump_lim_sme_reassoc_req( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tANI_U32 sessionId = arg1; + tCsrRoamModifyProfileFields modifyProfileFields; + tANI_U32 roamId; + + (void) arg2; (void) arg3; (void) arg4; + + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + if(HAL_STATUS_SUCCESS(sme_AcquireGlobalLock( &pMac->sme ))) + { + csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields); + csrReassoc( pMac, sessionId, &modifyProfileFields, &roamId, 0); + sme_ReleaseGlobalLock( &pMac->sme ); + } + } + else + { + p += log_sprintf( pMac,p, "Invalid session = %d\n", sessionId); + } + + return p; +} + +static char * +dump_lim_dot11h_stats( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + return p; +} + +static char * +dump_lim_enable_measurement( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + + if (arg1) + { + pMac->sys.gSysEnableLearnMode = eANI_BOOLEAN_TRUE; + p += log_sprintf(pMac, p, "Measurement enabled\n"); + } + else + { + pMac->sys.gSysEnableLearnMode = eANI_BOOLEAN_FALSE; + p += log_sprintf(pMac, p, "Measurement disabled\n"); + } + + return p; +} + +static char * +dump_lim_enable_quietIE( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + + return p; +} + +static char * +dump_lim_disable_enable_scan( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + + if (arg1) + { + pMac->lim.fScanDisabled = 1; + p += log_sprintf(pMac, p, "Scan disabled\n"); + } + else + { + pMac->lim.fScanDisabled = 0; + p += log_sprintf(pMac, p, "scan enabled\n"); + } + + return p; +} + +static char *finishScan(tpAniSirGlobal pMac, char *p) +{ + tSirMsgQ msg; + + p += log_sprintf( pMac,p, "logDump finishScan \n"); + + msg.type = SIR_LIM_MIN_CHANNEL_TIMEOUT; + msg.bodyval = 0; + msg.bodyptr = NULL; + + limPostMsgApi(pMac, &msg); + return p; +} + +static char * +dump_lim_info( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + return p; +} + +static char * +dump_lim_finishscan_send( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = finishScan(pMac, p); + return p; +} + +static char * +dump_lim_prb_rsp_send( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = testLimSendProbeRsp( pMac, p ); + return p; +} + +static char * +dump_sch_beacon_trigger( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = triggerBeaconGen(pMac, p); + return p; +} + +static char* dump_lim_set_scan_in_powersave( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + p += log_sprintf( pMac,p, "logDump set scan in powersave to %d \n", arg1); + dump_cfg_set(pMac, WNI_CFG_SCAN_IN_POWERSAVE, arg1, arg2, arg3, p); + return p; +} + +#if defined WLAN_FEATURE_VOWIFI +static char * +dump_lim_send_rrm_action( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tpPESession psessionEntry; + tSirMacRadioMeasureReport *pRRMReport = + vos_mem_malloc(4*sizeof(tSirMacRadioMeasureReport)); + tANI_U8 num = (tANI_U8)(arg4 > 4 ? 4 : arg4); + tANI_U8 i; + + if (!pRRMReport) + { + p += log_sprintf(pMac, p, + "Unable to allocate memory to process command\n"); + goto done; + } + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg2) )== NULL) + { + p += log_sprintf( pMac,p,"Session does not exist for given session Id \n"); + goto done; + } + switch (arg3) + { + case 0: + /* send two reports with incapable bit set */ + pRRMReport[0].type = 6; + pRRMReport[1].type = 7; + limSendRadioMeasureReportActionFrame( pMac, 1, 2, &pRRMReport[0], psessionEntry->bssId, psessionEntry ); + break; + case 1: + for ( i = 0 ; i < num ; i++ ) + { + pRRMReport[i].type = 5; + if ( i == 3 ) + pRRMReport[i].refused = 1; + else + pRRMReport[i].refused = 0; + + pRRMReport[i].report.beaconReport.regClass = 32; + pRRMReport[i].report.beaconReport.channel = i; + pRRMReport[i].report.beaconReport.measDuration = 23; + pRRMReport[i].report.beaconReport.phyType = i << 4; //some value. + pRRMReport[i].report.beaconReport.bcnProbeRsp = 1; + pRRMReport[i].report.beaconReport.rsni = 10; + pRRMReport[i].report.beaconReport.rcpi = 40; + + pRRMReport[i].report.beaconReport.bssid[0] = 0x00; + pRRMReport[i].report.beaconReport.bssid[1] = 0xAA; + pRRMReport[i].report.beaconReport.bssid[2] = 0xBB; + pRRMReport[i].report.beaconReport.bssid[3] = 0xCC; + pRRMReport[i].report.beaconReport.bssid[4] = 0x00; + pRRMReport[i].report.beaconReport.bssid[5] = 0x01 << i; + + + pRRMReport[i].report.beaconReport.antennaId = 10; + pRRMReport[i].report.beaconReport.parentTSF = 0x1234; + + pRRMReport[i].report.beaconReport.numIes = i * 10; + { + tANI_U8 j; + for( j = 0; j < pRRMReport[i].report.beaconReport.numIes ; j++ ) + { + pRRMReport[i].report.beaconReport.Ies[j] = j + i; //Junk values. + } + } + + } + limSendRadioMeasureReportActionFrame( pMac, 1, num, &pRRMReport[0], psessionEntry->bssId, psessionEntry ); + break; + case 2: + //send Neighbor request. + { + tSirMacNeighborReportReq neighbor; + neighbor.dialogToken = 2; + neighbor.ssid_present = (tANI_U8) arg4; + neighbor.ssid.length = 5; + vos_mem_copy(neighbor.ssid.ssId, "abcde", 5); + + limSendNeighborReportRequestFrame( pMac, &neighbor, psessionEntry->bssId, psessionEntry ); + + } + + break; + case 3: + //send Link measure report. + { + tSirMacLinkReport link; + link.dialogToken = 4; + link.txPower = 34; + link.rxAntenna = 2; + link.txAntenna = 1; + link.rcpi = 9; + link.rsni = 3; + limSendLinkReportActionFrame( pMac, &link, psessionEntry->bssId, psessionEntry ); + } + break; + default: + break; + } + +done: + vos_mem_free(pRRMReport); + return p; +} + +static char * +dump_lim_unpack_rrm_action( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tpPESession psessionEntry; + tANI_U32 status; + + tANI_U8 size[] = { + 0x2C, + 0x2F, + 0x25, + 0x2C, + 0x1C, + 0x05 + }; + + tANI_U8 pBody[][100] = { + { + /*Beacon Request 0*/ + 0x05, 0x00, 0x01, 0x00, 0x00, + //Measurement request IE + 0x26, 0x25, 0x01, 0x00, + //Beacon request type + 0x05, + //Beacon request starts here + 0x0C, 0x01, 0x30, 0x00, 0x14, 0x00, 0x01, + //BSSID + 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0xFF, + //SSID + 0x00, 0x05, 0x57, 0x69, 0x46, 0x69, 0x31, + //Reporting Condition + 0x01, 0x02, 0x00, 0x00, + //Reporting Detail + 0x02, 0x01, 0x1, + //Request IE + 0x0A, 0x05, 0x00, 0x30, 0x46, 0x36, 0xDD + }, + { + /*Beacon Request 1*/ + 0x05, 0x00, 0x01, 0x00, 0x00, + //Measurement request IE + 0x26, 0x28, 0x01, 0x00, + //Beacon request type + 0x05, + //Beacon request starts here + 0x0C, 0xFF, 0x30, 0x00, 0x14, 0x00, 0x01, + //BSSID + 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0xFF, + //SSID +/* 0x00, 0x08, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, */ + //Reporting Condition + 0x01, 0x02, 0x00, 0x00, + //Reporting Detail + 0x02, 0x01, 0x1, + //Request IE + 0x0A, 0x05, 0x00, 0x30, 0x46, 0x36, 0xDD, + //AP channel report + 0x33, 0x03, 0x0C, 0x01, 0x06, + 0x33, 0x03, 0x0C, 0x24, 0x30, + }, + { + /*Beacon Request 2*/ + 0x05, 0x00, 0x01, 0x00, 0x00, + //Measurement request IE + 0x26, 0x1E, 0x01, 0x00, + //Beacon request type + 0x05, + //Beacon request starts here + 0x0C, 0x00, 0x30, 0x00, 0x14, 0x00, 0x02, + //BSSID + 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0xFF, + //SSID + 0x00, 0x05, 0x57, 0x69, 0x46, 0x69, 0x31, + //0x00, 0x08, 0x41, 0x53, 0x54, 0x2D, 0x57, 0x41, 0x50, 0x49, + //Reporting Condition + 0x01, 0x02, 0x00, 0x00, + //Reporting Detail + 0x02, 0x01, 0x0 + //Request IE + }, + { + /*Beacon Request 3*/ + 0x05, 0x00, 0x01, 0x00, 0x00, + //Measurement request IE + 0x26, 0x25, 0x01, 0x00, + //Beacon request type + 0x05, + //Beacon request starts here + 0x0C, 0x01, 0x30, 0x00, 0x69, 0x00, 0x00, + //BSSID + 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0xFF, + //SSID + 0x00, 0x05, 0x57, 0x69, 0x46, 0x69, 0x31, + //Reporting Condition + 0x01, 0x02, 0x00, 0x00, + //Reporting Detail + 0x02, 0x01, 0x1, + //Request IE + 0x0A, 0x05, 0x00, 0x30, 0x46, 0x36, 0xDD + }, + { + /*Neighbor report*/ + 0x05, 0x05, 0x01, + //Measurement request IE + 0x34, 0x17, + //BSSID + 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0xFF, + //BSSID INFOo + 0xED, 0x01, 0x00, 0x00, + //Reg class, channel, Phy type + 0x20, 0x01, 0x02, + //TSF Info + 0x01, 0x04, 0x02, 0x00, 0x60, 0x00, + //Condensed country + 0x02, 0x02, 0x62, 0x63 + }, + { + /* Link measurement request */ + 0x05, 0x02, 0x00, + //Txpower used + 0x00, + //Max Tx Power + 0x00 + } + }; + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg1) )== NULL) + { + p += log_sprintf( pMac,p,"Session does not exist for given session Id \n"); + return p; + } + switch (arg2) + { + case 0: + case 1: + case 2: + case 3: + { + tDot11fRadioMeasurementRequest *frm = + vos_mem_malloc(sizeof(tDot11fRadioMeasurementRequest)); + if (!frm) + { + p += log_sprintf(pMac, p, + "Unable to allocate memory to process command\n"); + break; + } + if( (status = dot11fUnpackRadioMeasurementRequest( pMac, &pBody[arg2][0], size[arg2], frm )) != 0 ) + p += log_sprintf( pMac, p, "failed to unpack.....status = %x\n", status); + else + rrmProcessRadioMeasurementRequest( pMac, psessionEntry->bssId, frm, psessionEntry ); + vos_mem_free(frm); + } + break; + case 4: + { + tDot11fNeighborReportResponse *frm = + vos_mem_malloc(sizeof(tDot11fNeighborReportResponse)); + if (!frm) + { + p += log_sprintf(pMac, p, + "Unable to allocate memory to process command\n"); + break; + } + pBody[arg2][2] = (tANI_U8)arg3; //Dialog Token + if( (status = dot11fUnpackNeighborReportResponse( pMac, &pBody[arg2][0], size[arg2], frm )) != 0 ) + p += log_sprintf( pMac, p, "failed to unpack.....status = %x\n", status); + else + rrmProcessNeighborReportResponse( pMac, frm, psessionEntry ); + vos_mem_free(frm); + } + break; + case 5: + { +// FIXME. + } + break; + case 6: + { + tPowerdBm localConstraint = (tPowerdBm) arg3; + tPowerdBm maxTxPower = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); + maxTxPower = VOS_MIN( maxTxPower, maxTxPower-localConstraint ); + if( maxTxPower != psessionEntry->maxTxPower ) + { + rrmSendSetMaxTxPowerReq( pMac, maxTxPower, psessionEntry ); + psessionEntry->maxTxPower = maxTxPower; + } + } + break; + default: + p += log_sprintf( pMac, p, "Invalid option" ); + break; + } + return p; +} +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +/* This command is used to trigger FT Preauthentication with the AP with BSSID below */ +static char * +dump_lim_ft_event( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + static tANI_U8 macAddr[6] = {0x00, 0xde, 0xad, 0xaf, 0xaf, 0x04}; + tpPESession psessionEntry; + tSirMsgQ msg; + tpSirFTPreAuthReq pftPreAuthReq; + tANI_U16 auth_req_len = 0; + tCsrRoamConnectedProfile Profile; + tANI_U32 smeSessionId = arg2; + + if (!CSR_IS_SESSION_VALID( pMac, smeSessionId )) + { + p += log_sprintf( pMac, p, "smeSessionId is not valid\n"); + return p; + } + + csrRoamCopyConnectProfile(pMac, arg2, &Profile); + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg2) )== NULL) + { + p += log_sprintf( pMac, + p,"Session does not exist usage: 363 <0> sessionid channel \n"); + return p; + } + + switch (arg1) + { + case 0: + // Send Pre-auth event + { + /*----------------*/ + p += log_sprintf( pMac,p, "Preparing Pre Auth Req message\n"); + auth_req_len = sizeof(tSirFTPreAuthReq); + + pftPreAuthReq = vos_mem_malloc(auth_req_len); + if (NULL == pftPreAuthReq) + { + p += log_sprintf( pMac, p, + "Pre auth dump: AllocateMemory() failed \n"); + return p; + } + pftPreAuthReq->pbssDescription = + vos_mem_malloc(sizeof(Profile.pBssDesc->length)+ + Profile.pBssDesc->length); + + pftPreAuthReq->messageType = eWNI_SME_FT_PRE_AUTH_REQ; + pftPreAuthReq->length = + auth_req_len + sizeof(Profile.pBssDesc->length) + + Profile.pBssDesc->length; + pftPreAuthReq->preAuthchannelNum = 6; + + vos_mem_copy((void *) &pftPreAuthReq->currbssId, + (void *)psessionEntry->bssId, 6); + vos_mem_copy((void *) &pftPreAuthReq->preAuthbssId, + (void *)macAddr, 6); + pftPreAuthReq->ft_ies_length = + (tANI_U16)pMac->roam.roamSession[smeSessionId].ftSmeContext.auth_ft_ies_length; + + // Also setup the mac address in sme context. + vos_mem_copy( + pMac->roam.roamSession[smeSessionId].ftSmeContext.preAuthbssId, + macAddr, 6); + + vos_mem_copy(pftPreAuthReq->ft_ies, + pMac->roam.roamSession[smeSessionId].ftSmeContext.auth_ft_ies, + pMac->roam.roamSession[smeSessionId].ftSmeContext.auth_ft_ies_length); + + vos_mem_copy(Profile.pBssDesc->bssId, macAddr, 6); + + p += log_sprintf( pMac, p, + "\n ----- LIM Debug Information ----- \n"); + p += log_sprintf( pMac, p, "%s: length = %d\n", __func__, + (int)pMac->roam.roamSession[smeSessionId].ftSmeContext.auth_ft_ies_length); + p += log_sprintf( pMac, p, "%s: length = %02x\n", __func__, + (int)pMac->roam.roamSession[smeSessionId].ftSmeContext.auth_ft_ies[0]); + p += log_sprintf( pMac, p, "%s: Auth Req %02x %02x %02x\n", + __func__, pftPreAuthReq->ft_ies[0], + pftPreAuthReq->ft_ies[1], pftPreAuthReq->ft_ies[2]); + + p += log_sprintf( pMac, p, "%s: Session %02x %02x %02x\n", __func__, + psessionEntry->bssId[0], + psessionEntry->bssId[1], psessionEntry->bssId[2]); + p += log_sprintf( pMac, p, "%s: Session %02x %02x %02x %p\n", + __func__, + pftPreAuthReq->currbssId[0], + pftPreAuthReq->currbssId[1], + pftPreAuthReq->currbssId[2], pftPreAuthReq); + + Profile.pBssDesc->channelId = (tANI_U8)arg3; + vos_mem_copy((void *)pftPreAuthReq->pbssDescription, + (void *)Profile.pBssDesc, + Profile.pBssDesc->length); + + msg.type = eWNI_SME_FT_PRE_AUTH_REQ; + msg.bodyptr = pftPreAuthReq; + msg.bodyval = 0; + + p += log_sprintf(pMac, p, + "limPostMsgApi(eWNI_SME_FT_PRE_AUTH_REQ) \n"); + limPostMsgApi(pMac, &msg); + } + break; + + default: + break; + } + return p; +} +#endif +static char * +dump_lim_channel_switch_announcement( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tpPESession psessionEntry; + tANI_U8 nMode = arg2; + tANI_U8 nNewChannel = arg3; + tANI_U8 nCount = arg4; + tANI_U8 peer[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg1) )== NULL) + { + p += log_sprintf( pMac, + p,"Session does not exist usage: 363 <0> sessionid channel \n"); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN,"Session Not found!!!!"); + return p; + } + + limSendChannelSwitchMgmtFrame( pMac, peer, nMode, nNewChannel, nCount, psessionEntry ); + + psessionEntry->gLimChannelSwitch.switchCount = nCount; + psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_RUNNING; + psessionEntry->gLimChannelSwitch.switchMode = nMode; + psessionEntry->gLimChannelSwitch.primaryChannel = nNewChannel; + + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + + return p; +} + +#ifdef WLAN_FEATURE_11AC +static char * +dump_lim_vht_opmode_notification(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tANI_U8 peer[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + tANI_U8 nMode = arg2; + tpPESession psessionEntry; + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg1) )== NULL) + { + p += log_sprintf( pMac, + p,"Session does not exist usage: 366 <0> sessionid channel \n"); + return p; + } + + limSendVHTOpmodeNotificationFrame(pMac, peer, nMode,psessionEntry); + + psessionEntry->gLimOperatingMode.present = 1; + psessionEntry->gLimOperatingMode.chanWidth = nMode; + psessionEntry->gLimOperatingMode.rxNSS = 0; + psessionEntry->gLimOperatingMode.rxNSSType = 0; + + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + + return p; +} + +static char * +dump_lim_vht_channel_switch_notification(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tpPESession psessionEntry; + tANI_U8 nChanWidth = arg2; + tANI_U8 nNewChannel = arg3; + tANI_U8 ncbMode = arg4; + tANI_U8 peer[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg1) )== NULL) + { + p += log_sprintf( pMac, + p,"Session does not exist usage: 367 <0> sessionid channel \n"); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN,"Session Not found!!!!"); + return p; + } + + limSendVHTChannelSwitchMgmtFrame( pMac, peer, nChanWidth, nNewChannel, (ncbMode+1), psessionEntry ); + + psessionEntry->gLimChannelSwitch.switchCount = 0; + psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_RUNNING; + psessionEntry->gLimChannelSwitch.switchMode = 1; + psessionEntry->gLimChannelSwitch.primaryChannel = nNewChannel; + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = nChanWidth; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = limGetCenterChannel(pMac,nNewChannel,(ncbMode+1),nChanWidth); + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = 0; + + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + + return p; +} + +#endif +static char * +dump_lim_cancel_channel_switch_announcement( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tpPESession psessionEntry; + + if((psessionEntry = peFindSessionBySessionId(pMac,(tANI_U8)arg1) )== NULL) + { + p += log_sprintf( pMac, + p,"Session does not exist usage: 363 <0> sessionid channel \n"); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN,"Session Not found!!!!"); + return p; + } + psessionEntry->gLimChannelSwitch.switchCount = 0; + psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_INIT; + psessionEntry->gLimChannelSwitch.switchMode = 0; + psessionEntry->gLimChannelSwitch.primaryChannel = 0; + + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + + return p; +} + + +static char * +dump_lim_mcc_policy_maker(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_FATAL, "dump_lim_mcc_policy_maker arg = %d",arg1); + + if(arg1 == 0) //Disable feature completely + { + WDA_TrafficStatsTimerActivate(FALSE); + if (ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, FALSE, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + limLog( pMac, LOGE, FL("Could not get WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED")); + } + } + else if(arg1 == 1) //Enable feature + { + if (ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + limLog( pMac, LOGE, FL("Could not set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED")); + } + } + else if(arg1 == 2) //Enable feature and activate periodic timer + { + if (ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + limLog( pMac, LOGE, FL("Could not set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED")); + } + WDA_TrafficStatsTimerActivate(TRUE); + } + else if(arg1 == 3) //Enable only stats collection - Used for unit testing + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_FATAL, + FL("Obsolete command %d"), arg1); + } + else if(arg1 == 4) //Send current stats snapshot to Riva -- Used for unit testing + { + v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tWDA_CbContext *pWDA = vos_get_context(VOS_MODULE_ID_WDA, pVosContext); + ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE, NULL, eANI_BOOLEAN_FALSE); + if(pWDA != NULL) + { + WDA_TimerTrafficStatsInd(pWDA); + } + WDA_TrafficStatsTimerActivate(FALSE); + ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, FALSE,NULL, eANI_BOOLEAN_FALSE); + } + else if (arg1 == 5) //Change the periodicity of TX stats timer + { + v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tWDA_CbContext *pWDA = vos_get_context(VOS_MODULE_ID_WDA, pVosContext); + if (pWDA != NULL && tx_timer_change(&pWDA->wdaTimers.trafficStatsTimer, arg2/10, arg2/10) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("Disable timer before changing timeout value")); + } + } + return p; +} + +#ifdef WLANTL_DEBUG +/* API to print number of pkts received based on rate index */ +/* arg1 = station Id */ +/* arg2 = BOOLEAN value to either or not flush the counters */ +static char * +dump_lim_get_pkts_rcvd_per_rate_idx( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + /* if anything other than 1, then we need not flush the counters */ + if( arg2 != 1) + arg2 = FALSE; + + WLANTLPrintPktsRcvdPerRateIdx(pMac->roam.gVosContext, (tANI_U8)arg1, (v_BOOL_t)arg2); + return p; +} + +/* API to print number of pkts received based on rssi */ +/* arg1 = station Id */ +/* arg2 = BOOLEAN value to either or not flush the counters */ +static char * +dump_lim_get_pkts_rcvd_per_rssi_values( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + /* if anything other than 1, then we need not flush the counters */ + if( arg2 != 1) + arg2 = FALSE; + + WLANTLPrintPktsRcvdPerRssi(pMac->roam.gVosContext, (tANI_U8)arg1, (v_BOOL_t)arg2); + return p; +} +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +static char * +dump_send_plm_start(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, + tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + + eHalStatus status = eHAL_STATUS_SUCCESS; + tpSirPlmReq pPlmRequest = NULL; + + pPlmRequest = vos_mem_malloc(sizeof(tSirPlmReq)); + if (NULL == pPlmRequest){ + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,"dump allocating PLM struct failed"); + return p; + } + + pPlmRequest->diag_token = 0x5; + pPlmRequest->meas_token = 0x4; + pPlmRequest->numBursts = 2; + pPlmRequest->burstInt = 10; + pPlmRequest->measDuration = 20; + pPlmRequest->burstLen = 1; + pPlmRequest->desiredTxPwr = 12; + pPlmRequest->macAddr[0] = 0xff; + pPlmRequest->macAddr[1] = 0xff; + pPlmRequest->macAddr[2] = 0xff; + pPlmRequest->macAddr[3] = 0xff; + pPlmRequest->macAddr[4] = 0xff; + pPlmRequest->macAddr[5] = 0xff; + pPlmRequest->plmNumCh = 0; + pPlmRequest->sessionId = 0; + pPlmRequest->enable = 1; + + status = sme_SetPlmRequest((tHalHandle)pMac, pPlmRequest); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,"dump sending PLM command failed"); + vos_mem_free(pPlmRequest); + pPlmRequest = NULL; + return p; + } + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG,"dump sending PLM command is SUCCESS"); + return p; +} +#endif + +static char * +dump_set_max_probe_req(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, + tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + if ((arg1 <= 0) || (arg1 > 4)){ + limLog(pMac, LOGE, + FL("invalid number. valid range 1 - 4 \n")); + return p; + } + pMac->lim.maxProbe = arg1; + return p; +} + +static tDumpFuncEntry limMenuDumpTable[] = { + {0, "PE (300-499)", NULL}, + {300, "LIM: Dump state(s)/statistics ", dump_lim_info}, + {301, "PE.LIM: dump TSPEC Table", dump_lim_tspec_table}, + {302, "PE.LIM: dump specified TSPEC entry (id)", dump_lim_tspec_entry}, + {303, "PE.LIM: dump EDCA params", dump_lim_edca_params}, + {304, "PE.LIM: dump DPH table summary", dump_lim_dph_table_summary}, + {305, "PE.LIM: dump link monitor stats", dump_lim_link_monitor_stats}, + {306, "PE.LIM:dump Set the BAR Decline stat(arg1= 1/0 (enable/disable) arg2 =TID", dump_lim_AddBA_DeclineStat}, + {307, "PE: LIM: dump CSR Send ReAssocReq", dump_lim_sme_reassoc_req}, + {308, "PE:LIM: dump all 11H related data", dump_lim_dot11h_stats}, + {309, "PE:LIM: dump to enable Measurement on AP", dump_lim_enable_measurement}, + {310, "PE:LIM: dump to enable QuietIE on AP", dump_lim_enable_quietIE}, + {311, "PE:LIM: disable/enable scan 1(disable)", dump_lim_disable_enable_scan}, + {320, "PE.LIM: send sme scan request", dump_lim_scan_req_send}, + + + /* This dump command is more of generic dump cmd and hence it should + * be moved to logDump.c + */ + {321, "PE:LIM: Set Log Level ", dump_lim_update_log_level}, + {331, "PE.LIM: Send finish scan to LIM", dump_lim_finishscan_send}, + {332, "PE.LIM: force probe rsp send from LIM", dump_lim_prb_rsp_send}, + {333, "PE.SCH: Trigger to generate a beacon", dump_sch_beacon_trigger}, + {335, "PE.LIM: set ACM flag (0..3)", dump_lim_acm_set}, + {336, "PE.LIM: Send an ADDBA Req to peer MAC arg1=aid,arg2=tid, arg3=ssn", dump_lim_addba_req}, + {337, "PE.LIM: Send a DELBA Ind to peer MAC arg1=aid,arg2=recipient(0)/initiator(1),arg3=tid,arg4=reasonCode", dump_lim_delba_req}, + {338, "PE.LIM: Trigger a BA timeout for STA index", dump_lim_ba_timeout}, + {339, "PE.LIM: List active BA session(s) for AssocID", dump_lim_list_active_ba}, + {340, "PE.LIM: Set background scan flag (0-disable, 1-enable)",dump_lim_bgscan_toggle}, + {341, "PE.LIM: Set link monitoring mode", dump_lim_linkmonitor_toggle}, + {343, "PE.LIM: DelSta ", dump_lim_del_sta}, + {344, "PE.LIM: Set probe respond flag", dump_lim_proberesp_toggle}, + {345, "PE.LIM: set protection config bitmap", set_lim_prot_cfg}, + {346, "PE:LIM: Set the Dot11 Mode", dump_lim_set_dot11_mode}, + {347, "PE:Enable or Disable Protection", dump_lim_set_protection_control}, + {348, "PE:LIM: Send SM Power Mode Action frame", dump_lim_send_SM_Power_Mode}, + {349, "PE: LIM: Change CB Mode ",dump_lim_update_cb_Mode}, + {350, "PE: LIM: abort scan", dump_lim_abort_scan}, + {351, "PE: LIM: Start stop BG scan", dump_lim_start_stop_bg_scan}, + {352, "PE: LIM: PE statistics ", dump_lim_get_pe_statistics}, + {353, "PE: LIM: Set MAC log level ", dump_lim_set_log_level}, + {354, "PE: LIM: Set Scan in Power Save <0-disable, 1-enable>", dump_lim_set_scan_in_powersave}, + {355, "PE.LIM: send sme start BSS request", dump_lim_send_start_bss_req}, + {356, "PE.LIM: dump pesession info ", dump_lim_session_print}, + {357, "PE.LIM: send DisAssocRequest", dump_lim_send_disassoc_req}, + {358, "PE.LIM: send sme stop bss request ", dump_lim_stop_bss_req}, + {359, "PE.LIM: send sme join request", dump_lim_send_join_req}, +#if defined WLAN_FEATURE_VOWIFI + {360, "PE.LIM: send an RRM action frame", dump_lim_send_rrm_action}, + {361, "PE.LIM: unpack an RRM action frame", dump_lim_unpack_rrm_action}, +#endif +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + {363, "PE.LIM: trigger pre auth/reassoc event", dump_lim_ft_event}, +#endif + {364, "PE.LIM: Send a channel switch announcement", dump_lim_channel_switch_announcement}, + {365, "PE.LIM: Cancel channel switch announcement", dump_lim_cancel_channel_switch_announcement}, +#ifdef WLAN_FEATURE_11AC + {366, "PE.LIM: Send a VHT OPMode Action Frame", dump_lim_vht_opmode_notification}, + {367, "PE.LIM: Send a VHT Channel Switch Announcement", dump_lim_vht_channel_switch_notification}, + {368, "PE.LIM: MCC Policy Maker", dump_lim_mcc_policy_maker}, +#endif +#ifdef WLANTL_DEBUG + {369, "PE.LIM: pkts/rateIdx: iwpriv wlan0 dump 369 ", dump_lim_get_pkts_rcvd_per_rate_idx}, + {370, "PE.LIM: pkts/rssi: : iwpriv wlan0 dump 370 ", dump_lim_get_pkts_rcvd_per_rssi_values}, +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + {372, "PE.LIM: send PLM start command Usage: iwpriv wlan0 372", dump_send_plm_start }, +#endif + {376, "PE.LIM: max number of probe per scan", dump_set_max_probe_req }, +}; + + + +void limDumpInit(tpAniSirGlobal pMac) +{ + logDumpRegisterTable( pMac, &limMenuDumpTable[0], + sizeof(limMenuDumpTable)/sizeof(limMenuDumpTable[0]) ); +} + + +#endif //#if defined(ANI_LOGDUMP) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c new file mode 100644 index 000000000000..3938a819fd55 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c @@ -0,0 +1,1173 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + L I M _ P 2 P . C + + OVERVIEW: + + This software unit holds the implementation of the WLAN Protocol Engine for + P2P. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header$$DateTime$$Author$ + + + when who what, where, why +---------- --- -------------------------------------------------------- +2011-05-02 djindal Corrected file indentation and changed remain on channel + handling for concurrency. +===========================================================================*/ + + +#include "limUtils.h" +#include "limSessionUtils.h" +#include "wlan_qct_wda.h" + +#define PROBE_RSP_IE_OFFSET 36 +#define BSSID_OFFSET 16 +#define ADDR2_OFFSET 10 +#define ACTION_OFFSET 24 + +/* A DFS channel can be ACTIVE for max 9000 msec, from the last + received Beacon/Prpbe Resp. */ +#define MAX_TIME_TO_BE_ACTIVE_CHANNEL 9000 + + + +void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data); +void limRemainOnChnlSetLinkStat(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry); +void limExitRemainOnChannel(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry); +extern tSirRetStatus limSetLinkState( + tpAniSirGlobal pMac, tSirLinkState state, + tSirMacAddr bssId, tSirMacAddr selfMacAddr, + tpSetLinkStateCallback callback, void *callbackArg); + +static tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession); +eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess); +/*------------------------------------------------------------------ + * + * Below function is callback function, it is called when + * WDA_SET_LINK_STATE_RSP is received from WDI. callback function for + * P2P of limSetLinkState + * + *------------------------------------------------------------------*/ +void limSetLinkStateP2PCallback(tpAniSirGlobal pMac, void *callbackArg, + bool status) +{ + //Send Ready on channel indication to SME + if(pMac->lim.gpLimRemainOnChanReq) + { + limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RDY_IND, eHAL_STATUS_SUCCESS, + pMac->lim.gpLimRemainOnChanReq->sessionId, 0); + } + else + { + //This is possible in case remain on channel is aborted + limLog( pMac, LOGE, FL(" NULL pointer of gpLimRemainOnChanReq") ); + } +} + +/*------------------------------------------------------------------ + * + * Below function is called if pMac->fP2pListenOffload enabled and hdd + * requests a remain on channel. + * + *------------------------------------------------------------------*/ +static eHalStatus limSendHalReqRemainOnChanOffload(tpAniSirGlobal pMac, + tSirRemainOnChnReq *pRemOnChnReq) +{ + tSirScanOffloadReq *pScanOffloadReq; + tSirMsgQ msg; + tSirRetStatus rc = eSIR_SUCCESS; + tANI_U8 bssid[SIR_MAC_ADDR_LENGTH] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + pScanOffloadReq = vos_mem_malloc(sizeof(tSirScanOffloadReq)); + if (NULL == pScanOffloadReq) + { + limLog(pMac, LOGE, + FL("Memory allocation failed for pScanOffloadReq")); + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(pScanOffloadReq, sizeof(tSirScanOffloadReq)); + + msg.type = WDA_START_SCAN_OFFLOAD_REQ; + msg.bodyptr = pScanOffloadReq; + msg.bodyval = 0; + + vos_mem_copy((tANI_U8 *) pScanOffloadReq->selfMacAddr, + (tANI_U8 *) pRemOnChnReq->selfMacAddr, + sizeof(tSirMacAddr)); + + vos_mem_copy((tANI_U8 *) pScanOffloadReq->bssId, + (tANI_U8 *) bssid, + sizeof(tSirMacAddr)); + pScanOffloadReq->scanType = eSIR_PASSIVE_SCAN; + pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_LISTEN; + pScanOffloadReq->minChannelTime = pRemOnChnReq->duration; + pScanOffloadReq->maxChannelTime = pRemOnChnReq->duration; + pScanOffloadReq->sessionId = pRemOnChnReq->sessionId; + pScanOffloadReq->channelList.numChannels = 1; + pScanOffloadReq->channelList.channelNumber[0] = pRemOnChnReq->chnNum; + + limLog(pMac, LOG1, + FL("Req-rem-on-channel: duration %u, session %hu, chan %hu"), + pRemOnChnReq->duration, pRemOnChnReq->sessionId, + pRemOnChnReq->chnNum); + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("wdaPostCtrlMsg() return failure %u"), + rc); + vos_mem_free(pScanOffloadReq); + return eHAL_STATUS_FAILURE; + } + + pMac->lim.fOffloadScanPending = 1; + pMac->lim.fOffloadScanP2PListen = 1; + + return eHAL_STATUS_SUCCESS; +} + +/*------------------------------------------------------------------ + * + * Remain on channel req handler. Initiate the INIT_SCAN, CHN_CHANGE + * and SET_LINK Request from SME, chnNum and duration to remain on channel. + * + *------------------------------------------------------------------*/ +int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + + /* CONC_OPER_AND_LISTEN_CHNL_SAME_OPTIMIZE - Currently removed the special optimization when a concurrent session + * exists with operating channel same as P2P listen channel since it was causing issues in P2P search. The reason was + * STA-AP link entering BMPS when returning to home channel causing P2P search to miss Probe Reqs and hence not + * respond with Probe Rsp causing peer device to NOT find us. + * If we need this optimization, we need to find a way to keep the STA-AP link awake (no BMPS) on home channel when in listen state + */ + + tSirRemainOnChnReq *MsgBuff = (tSirRemainOnChnReq *)pMsg; + pMac->lim.gpLimRemainOnChanReq = MsgBuff; + + if (pMac->fP2pListenOffload) + { + eHalStatus status; + + status = limSendHalReqRemainOnChanOffload(pMac, MsgBuff); + if (status != eHAL_STATUS_SUCCESS) + { + /* Post the meessage to Sme */ + limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, status, + MsgBuff->sessionId, 0); + vos_mem_free(pMac->lim.gpLimRemainOnChanReq); + pMac->lim.gpLimRemainOnChanReq = NULL; + } + return FALSE; + } + + pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState; + pMac->lim.gLimMlmState = eLIM_MLM_P2P_LISTEN_STATE; + + pMac->lim.gTotalScanDuration = MsgBuff->duration; + + /* 1st we need to suspend link with callback to initiate change channel */ + limSuspendLink(pMac, eSIR_CHECK_LINK_TRAFFIC_BEFORE_SCAN, + limRemainOnChnlSuspendLinkHdlr, NULL); + return FALSE; + +} + + +tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession) +{ + tSirRetStatus nSirStatus = eSIR_FAILURE; + tpPESession psessionEntry; + tANI_U8 sessionId; + tANI_U32 val; + + if(pMac->lim.gpLimRemainOnChanReq && ppP2pSession) + { + if((psessionEntry = peCreateSession(pMac, + pMac->lim.gpLimRemainOnChanReq->selfMacAddr, + &sessionId, 1, eSIR_INFRA_AP_MODE)) == NULL) + { + limLog(pMac, LOGE, FL("Session Can not be created ")); + /* send remain on chn failure */ + return nSirStatus; + } + /* Store PE sessionId in session Table */ + psessionEntry->peSessionId = sessionId; + psessionEntry->smeSessionId = pMac->lim.gpLimRemainOnChanReq->sessionId; + + psessionEntry->limSystemRole = eLIM_P2P_DEVICE_ROLE; + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A, + psessionEntry->rateSet.rate, val , SIR_MAC_MAX_NUMBER_OF_RATES ); + psessionEntry->rateSet.numRates = val; + + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + psessionEntry->extRateSet.rate, val, + WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN ); + psessionEntry->extRateSet.numRates = val; + + sirCopyMacAddr(psessionEntry->selfMacAddr, + pMac->lim.gpLimRemainOnChanReq->selfMacAddr); + + psessionEntry->currentOperChannel = pMac->lim.gpLimRemainOnChanReq->chnNum; + nSirStatus = eSIR_SUCCESS; + *ppP2pSession = psessionEntry; + } + + return nSirStatus; +} + + +/*------------------------------------------------------------------ + * + * limSuspenLink callback, on success link suspend, trigger change chn + * + * + *------------------------------------------------------------------*/ + +tSirRetStatus limRemainOnChnlChangeChnReq(tpAniSirGlobal pMac, + eHalStatus status, tANI_U32 *data) +{ + tpPESession psessionEntry; + tANI_U8 sessionId = 0; + tSirRetStatus nSirStatus = eSIR_FAILURE; + + if( NULL == pMac->lim.gpLimRemainOnChanReq ) + { + //RemainOnChannel may have aborted + PELOGE(limLog( pMac, LOGE, FL(" gpLimRemainOnChanReq is NULL") );) + return nSirStatus; + } + + /* The link is not suspended */ + if (status != eHAL_STATUS_SUCCESS) + { + PELOGE(limLog( pMac, LOGE, FL(" Suspend link Failure ") );) + goto error; + } + + + if((psessionEntry = peFindSessionByBssid( + pMac,pMac->lim.gpLimRemainOnChanReq->selfMacAddr, &sessionId)) != NULL) + { + goto change_channel; + } + else /* Session Entry does not exist for given BSSId */ + { + /* Try to Create a new session */ + if(eSIR_SUCCESS != limCreateSessionForRemainOnChn(pMac, &psessionEntry)) + { + limLog(pMac, LOGE, FL("Session Can not be created ")); + /* send remain on chn failure */ + goto error; + } + } + +change_channel: + /* change channel to the requested by RemainOn Chn*/ + limChangeChannelWithCallback(pMac, + pMac->lim.gpLimRemainOnChanReq->chnNum, + limRemainOnChnlSetLinkStat, NULL, psessionEntry); + return eSIR_SUCCESS; + +error: + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + return eSIR_FAILURE; +} + +void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data) +{ + limRemainOnChnlChangeChnReq(pMac, status, data); + return; +} + +/*------------------------------------------------------------------ + * + * Set the LINK state to LISTEN to allow only PROBE_REQ and Action frames + * + *------------------------------------------------------------------*/ +void limRemainOnChnlSetLinkStat(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry) +{ + tANI_U32 val; + tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq; + tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + if (status != eHAL_STATUS_SUCCESS) + { + limLog( pMac, LOGE, FL("Change channel not successful")); + goto error1; + } + + // Start timer here to come back to operating channel. + pMac->lim.limTimers.gLimRemainOnChannelTimer.sessionId = + psessionEntry->peSessionId; + pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time(); + pMac->lim.gTotalScanDuration = MsgRemainonChannel->duration; + + /* get the duration from the request */ + val = SYS_MS_TO_TICKS(MsgRemainonChannel->duration); + + limLog( pMac, LOG2, "Start listen duration = %d", val); + if (tx_timer_change(&pMac->lim.limTimers.gLimRemainOnChannelTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Remain on channel Timer. Log error. + */ + limLog(pMac, LOGP, + FL("Unable to change remain on channel Timer val")); + goto error; + } + + if(TX_SUCCESS != + tx_timer_activate(&pMac->lim.limTimers.gLimRemainOnChannelTimer)) + { + limLog( pMac, LOGE, + "%s: remain on channel Timer Start Failed", __func__); + goto error; + } + + if ((limSetLinkState(pMac, MsgRemainonChannel->isProbeRequestAllowed? + eSIR_LINK_LISTEN_STATE:eSIR_LINK_SEND_ACTION_STATE,nullBssid, + pMac->lim.gSelfMacAddr, limSetLinkStateP2PCallback, + NULL)) != eSIR_SUCCESS) + { + limLog( pMac, LOGE, "Unable to change link state"); + goto error; + } + + return; +error: + limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER); +error1: + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + return; +} + +/*------------------------------------------------------------------ + * + * lim Insert NOA timer timeout callback - when timer fires, deactivate it and send + * scan rsp to csr/hdd + * + *------------------------------------------------------------------*/ +void limProcessInsertSingleShotNOATimeout(tpAniSirGlobal pMac) +{ + /* timeout means start NOA did not arrive; we need to deactivate and change the timer for + * future activations + */ + limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); + + /* Even if insert NOA timedout, go ahead and process/send stored SME request */ + limProcessRegdDefdSmeReqAfterNOAStart(pMac); + + return; +} + +/*----------------------------------------------------------------- + * lim Insert Timer callback function to check active DFS channels + * and convert them to passive channels if there was no + * beacon/proberesp for MAX_TIME_TO_BE_ACTIVE_CHANNEL time + *------------------------------------------------------------------*/ +void limConvertActiveChannelToPassiveChannel(tpAniSirGlobal pMac ) +{ + tANI_U32 currentTime; + tANI_U32 lastTime = 0; + tANI_U32 timeDiff; + tANI_U8 i; + currentTime = vos_timer_get_system_time(); + for (i = 1; i < SIR_MAX_24G_5G_CHANNEL_RANGE ; i++) + { + if ((pMac->lim.dfschannelList.timeStamp[i]) != 0) + { + lastTime = pMac->lim.dfschannelList.timeStamp[i]; + if (currentTime >= lastTime) + { + timeDiff = (currentTime - lastTime); + } + else + { + timeDiff = (0xFFFFFFFF - lastTime) + currentTime; + } + + if (timeDiff >= MAX_TIME_TO_BE_ACTIVE_CHANNEL) + { + limCovertChannelScanType( pMac, i,FALSE); + pMac->lim.dfschannelList.timeStamp[i] = 0; + } + } + } + /* lastTime is zero if there is no DFS active channels in the list. + * If this is non zero then we have active DFS channels so restart the timer. + */ + if (lastTime != 0) + { + if (tx_timer_activate( + &pMac->lim.limTimers.gLimActiveToPassiveChannelTimer) + != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("Could not activate Active to Passive Channel timer")); + } + } + + return; + +} + +/*------------------------------------------------------------------ + * + * limchannelchange callback, on success channel change, set the + * link_state to LISTEN + * + *------------------------------------------------------------------*/ + +void limProcessRemainOnChnTimeout(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry; + tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + //Timer might get extended while Sending Action Frame + //In that case don't process Channel Timeout + if (tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer)) + { + limLog( pMac, LOGE, + "still timer is running already and not processing limProcessRemainOnChnTimeout"); + return; + } + + limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER); + + if (NULL == pMac->lim.gpLimRemainOnChanReq) + { + limLog( pMac, LOGE, "No Remain on channel pending"); + return; + } + + /* get the previous valid LINK state */ + if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid, + pMac->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS) + { + limLog( pMac, LOGE, "Unable to change link state"); + return; + } + + if (pMac->lim.gLimMlmState != eLIM_MLM_P2P_LISTEN_STATE ) + { + limRemainOnChnRsp(pMac,eHAL_STATUS_SUCCESS, NULL); + } + else + { + /* get the session */ + if((psessionEntry = peFindSessionBySessionId(pMac, + pMac->lim.limTimers.gLimRemainOnChannelTimer.sessionId))== NULL) + { + limLog(pMac, LOGE, + FL("Session Does not exist for given sessionID")); + goto error; + } + + limExitRemainOnChannel(pMac, eHAL_STATUS_SUCCESS, NULL, psessionEntry); + return; +error: + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + } + return; +} + + +/*------------------------------------------------------------------ + * + * limchannelchange callback, on success channel change, set the link_state + * to LISTEN + * + *------------------------------------------------------------------*/ + +void limExitRemainOnChannel(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry) +{ + + if (status != eHAL_STATUS_SUCCESS) + { + PELOGE(limLog( pMac, LOGE, "Remain on Channel Failed");) + goto error; + } + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limResumeLink(pMac, limRemainOnChnRsp, NULL); + return; +error: + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + return; +} + +/*------------------------------------------------------------------ + * + * Send remain on channel respone: Success/ Failure + * + *------------------------------------------------------------------*/ +void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data) +{ + tpPESession psessionEntry; + tANI_U8 sessionId; + tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq; + tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + if ( NULL == MsgRemainonChannel ) + { + PELOGE(limLog( pMac, LOGP, + "%s: No Pointer for Remain on Channel Req", __func__);) + return; + } + + /* Incase of the Remain on Channel Failure Case + Clean up Everything */ + if(eHAL_STATUS_FAILURE == status) + { + //Deactivate Remain on Channel Timer + limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER); + + //Set the Link State to Idle + /* get the previous valid LINK state */ + if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid, + pMac->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS) + { + limLog( pMac, LOGE, "Unable to change link state"); + } + + pMac->lim.gLimSystemInScanLearnMode = 0; + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + } + + /* delete the session */ + if((psessionEntry = peFindSessionByBssid(pMac, + MsgRemainonChannel->selfMacAddr,&sessionId)) != NULL) + { + if (LIM_IS_P2P_DEVICE_ROLE(psessionEntry)) { + peDeleteSession( pMac, psessionEntry); + } + } + + /* Post the meessage to Sme */ + limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, status, + MsgRemainonChannel->sessionId, 0); + + vos_mem_free(pMac->lim.gpLimRemainOnChanReq); + pMac->lim.gpLimRemainOnChanReq = NULL; + + pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; + + /* If remain on channel timer expired and action frame is pending then + * indicaiton confirmation with status failure */ + if (pMac->lim.mgmtFrameSessionId != 0xff) + { + limP2PActionCnf(pMac, 0); + } + + return; +} + +/*------------------------------------------------------------------ + * + * Indicate the Mgmt Frame received to SME to HDD callback + * handle Probe_req/Action frame currently + * + *------------------------------------------------------------------*/ +void limSendSmeMgmtFrameInd( + tpAniSirGlobal pMac, tANI_U8 frameType, + tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, + tANI_U32 rxChannel, tpPESession psessionEntry, + tANI_S8 rxRssi) +{ + tSirMsgQ mmhMsg; + tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL; + tANI_U16 length; + + length = sizeof(tSirSmeMgmtFrameInd) + frameLen; + + pSirSmeMgmtFrame = vos_mem_malloc(length); + if (NULL == pSirSmeMgmtFrame) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for eWNI_SME_LISTEN_RSP")); + return; + } + vos_mem_set((void*)pSirSmeMgmtFrame, length, 0); + + pSirSmeMgmtFrame->mesgType = eWNI_SME_MGMT_FRM_IND; + pSirSmeMgmtFrame->mesgLen = length; + pSirSmeMgmtFrame->sessionId = sessionId; + pSirSmeMgmtFrame->frameType = frameType; + pSirSmeMgmtFrame->rxRssi = rxRssi; + + if (pMac->fP2pListenOffload) + goto send_frame; + + /* + * Work around to address LIM sending wrong channel to HDD for p2p action + * frames(In case of auto GO) recieved on 5GHz channel. + * As RXP has only 4bits to store the channel, we need some mechanism to + * to distinguish between 2.4Ghz/5GHz channel. if gLimRemainOnChannelTImer + * is not running and if we get a frame then pass the Go session + * operating channel to HDD. Some vendors create separate p2p interface + * after group formation. In that case LIM session entry will be NULL for + * p2p device address. So search for p2p go session and pass it's + * operating channel. + * Need to revisit this path in case of GO+CLIENT concurrency. + */ + if( VOS_FALSE == + tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer) ) + { + tpPESession pTempSessionEntry = psessionEntry; + if( ( (NULL != pTempSessionEntry) || + (pTempSessionEntry = limIsApSessionActive(pMac)) ) && + (SIR_BAND_5_GHZ == limGetRFBand(pTempSessionEntry->currentOperChannel)) ) + { + rxChannel = pTempSessionEntry->currentOperChannel; + } + } + + if(VOS_TRUE == tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer) && + ( (psessionEntry != NULL) && (psessionEntry->pePersona != VOS_P2P_GO_MODE)) && + (frameType == SIR_MAC_MGMT_ACTION)) + { + unsigned int chanWaitTime, vStatus ; + + limLog( pMac, LOG1, FL("Rx: Extend the gLimRemainOnChannelTimer = %d "), + pMac->lim.gTotalScanDuration); + + pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time(); + + chanWaitTime = SYS_MS_TO_TICKS(pMac->lim.gTotalScanDuration); + vStatus = tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer); + + if (VOS_STATUS_SUCCESS != vStatus) + { + limLog( pMac, LOGE, FL("Rx: Extend the gLimRemainOnChannelTimer")); + } + + if (tx_timer_change(&pMac->lim.limTimers.gLimRemainOnChannelTimer, chanWaitTime, 0) != TX_SUCCESS) + { + limLog( pMac, LOGE, FL("Unable to change the gLimRemainOnChannelTimer")); + } + + if (tx_timer_activate(&pMac->lim.limTimers.gLimRemainOnChannelTimer) != 0) + { + limLog( pMac, LOGE, FL("Unable to active the gLimRemainOnChannelTimer")); + } + } + else + { + if(frameType == SIR_MAC_MGMT_ACTION) + limLog( pMac, LOGE, FL("Rx: NO REMAIN ON CHANNEL and recd action frame ")); + } + +send_frame: + pSirSmeMgmtFrame->rxChan = rxChannel; + + vos_mem_zero(pSirSmeMgmtFrame->frameBuf,frameLen); + vos_mem_copy(pSirSmeMgmtFrame->frameBuf,frame,frameLen); + + mmhMsg.type = eWNI_SME_MGMT_FRM_IND; + mmhMsg.bodyptr = pSirSmeMgmtFrame; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} /*** end limSendSmeListenRsp() ***/ + + +eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess) +{ + if (pMac->lim.mgmtFrameSessionId != 0xff) + { + /* The session entry might be invalid(0xff) action confirmation received after + * remain on channel timer expired */ + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + (txCompleteSuccess ? eSIR_SME_SUCCESS : eSIR_SME_SEND_ACTION_FAIL), + pMac->lim.mgmtFrameSessionId, 0); + pMac->lim.mgmtFrameSessionId = 0xff; + } + + return eHAL_STATUS_SUCCESS; +} + + +void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tSirMbMsgP2p *pMbMsg = (tSirMbMsgP2p *)pMsg->bodyptr; + tANI_U32 nBytes; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tpSirMacFrameCtl pFc = (tpSirMacFrameCtl ) pMbMsg->data; + tANI_U8 noaLen = 0; + tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + (2*SIR_P2P_IE_HEADER_LEN)]; + tANI_U8 origLen = 0; + tANI_U8 sessionId = 0; + v_U8_t *pP2PIe = NULL; + tpPESession psessionEntry = NULL; + v_U8_t *pPresenceRspNoaAttr = NULL; + v_U8_t *pNewP2PIe = NULL; + v_U16_t remainLen = 0; + tANI_U8 smeSessionId = 0; +#ifdef WLAN_FEATURE_11W + tpSirMacMgmtHdr pMacHdr; + tpSirMacActionFrameHdr pActionHdr; +#endif + + nBytes = pMbMsg->msgLen - sizeof(tSirMbMsg); + + limLog( pMac, LOG1, FL("sending pFc->type=%d pFc->subType=%d"), + pFc->type, pFc->subType); + if (pMac->fP2pListenOffload) + { + if ((!pMac->lim.gpLimRemainOnChanReq) && (0 != pMbMsg->wait)) + { + limLog(pMac, LOGE, + FL("Remain on channel is not running")); + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + return; + } + smeSessionId = pMbMsg->sessionId; + goto send_action_frame; + } + + psessionEntry = peFindSessionByBssid(pMac, + (tANI_U8*)pMbMsg->data + BSSID_OFFSET, &sessionId); + + /* Check for session corresponding to ADDR2 As Supplicant is filling + ADDR2 with BSSID */ + if( NULL == psessionEntry ) + { + psessionEntry = peFindSessionByBssid(pMac, + (tANI_U8*)pMbMsg->data + ADDR2_OFFSET, &sessionId); + } + + if( NULL == psessionEntry ) + { + tANI_U8 isSessionActive = 0; + tANI_U8 i; + + /* If we are not able to find psessionEntry entry, then try to find + active session, if found any active sessions then send the + action frame, If no active sessions found then drop the frame */ + for (i =0; i < pMac->lim.maxBssId;i++) + { + psessionEntry = peFindSessionBySessionId(pMac,i); + if ( NULL != psessionEntry) + { + isSessionActive = 1; + break; + } + } + if( !isSessionActive ) + { + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + return; + } + } + + smeSessionId = psessionEntry->smeSessionId; + +send_action_frame: + if ((SIR_MAC_MGMT_FRAME == pFc->type)&& + ((SIR_MAC_MGMT_PROBE_RSP == pFc->subType)|| + (SIR_MAC_MGMT_ACTION == pFc->subType))) + { + //if this is a probe RSP being sent from wpa_supplicant + if (SIR_MAC_MGMT_PROBE_RSP == pFc->subType) + { + //get proper offset for Probe RSP + pP2PIe = limGetP2pIEPtr(pMac, + (tANI_U8*)pMbMsg->data + PROBE_RSP_IE_OFFSET, + nBytes - PROBE_RSP_IE_OFFSET); + while ((NULL != pP2PIe) && (SIR_MAC_MAX_IE_LENGTH == pP2PIe[1])) + { + remainLen = nBytes - (pP2PIe - (tANI_U8*)pMbMsg->data); + if (remainLen > 2) + { + pNewP2PIe = limGetP2pIEPtr(pMac, + pP2PIe+SIR_MAC_MAX_IE_LENGTH + 2, remainLen); + } + if (pNewP2PIe) + { + pP2PIe = pNewP2PIe; + pNewP2PIe = NULL; + } + else + { + break; + } + } //end of while + } + else + { + if (SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY == + *((v_U8_t *)pMbMsg->data+ACTION_OFFSET)) + { + tpSirMacP2PActionFrameHdr pActionHdr = + (tpSirMacP2PActionFrameHdr)((v_U8_t *)pMbMsg->data + + ACTION_OFFSET); + if (vos_mem_compare( pActionHdr->Oui, + SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE ) && + (SIR_MAC_ACTION_P2P_SUBTYPE_PRESENCE_RSP == + pActionHdr->OuiSubType)) + { //In case of Presence RSP response + pP2PIe = limGetP2pIEPtr(pMac, + (v_U8_t *)pMbMsg->data + ACTION_OFFSET + + sizeof(tSirMacP2PActionFrameHdr), + (nBytes - ACTION_OFFSET - + sizeof(tSirMacP2PActionFrameHdr))); + if( NULL != pP2PIe ) + { + //extract the presence of NoA attribute inside P2P IE + pPresenceRspNoaAttr = + limGetIEPtr(pMac,pP2PIe + SIR_P2P_IE_HEADER_LEN, + pP2PIe[1], SIR_P2P_NOA_ATTR,TWO_BYTE); + } + } + } + } + + if (pP2PIe != NULL) + { + //get NoA attribute stream P2P IE + noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry); + //need to append NoA attribute in P2P IE + if (noaLen > 0) + { + origLen = pP2PIe[1]; + //if Presence Rsp has NoAttr + if (pPresenceRspNoaAttr) + { + v_U16_t noaAttrLen = pPresenceRspNoaAttr[1] | + (pPresenceRspNoaAttr[2]<<8); + /*One byte for attribute, 2bytes for length*/ + origLen -= (noaAttrLen + 1 + 2); + //remove those bytes to copy + nBytes -= (noaAttrLen + 1 + 2); + //remove NoA from original Len + pP2PIe[1] = origLen; + } + if ((pP2PIe[1] + (tANI_U16)noaLen)> SIR_MAC_MAX_IE_LENGTH) + { + //Form the new NoA Byte array in multiple P2P IEs + noaLen = limGetNoaAttrStreamInMultP2pIes(pMac, noaStream, + noaLen,((pP2PIe[1] + (tANI_U16)noaLen)- + SIR_MAC_MAX_IE_LENGTH)); + pP2PIe[1] = SIR_MAC_MAX_IE_LENGTH; + } + else + { + pP2PIe[1] += noaLen; //increment the length of P2P IE + } + nBytes += noaLen; + limLog( pMac, LOGE, + FL("noaLen=%d origLen=%d pP2PIe=%p" + " nBytes=%d nBytesToCopy=%zu "), + noaLen,origLen,pP2PIe,nBytes, + ((pP2PIe + origLen + 2) - (v_U8_t *)pMbMsg->data)); + } + } + + if (SIR_MAC_MGMT_PROBE_RSP == pFc->subType) + { + lim_set_ht_caps(pMac, psessionEntry, + (tANI_U8*)pMbMsg->data + PROBE_RSP_IE_OFFSET, + nBytes - PROBE_RSP_IE_OFFSET); + } + + if (pMac->fP2pListenOffload) + goto send_frame1; + + /* The minimum wait for any action frame should be atleast 100 ms. + * If supplicant sends action frame at the end of already running remain on channel time + * Then there is a chance to miss the response of the frame. So increase the remain on channel + * time for all action frame to make sure that we receive the response frame */ + if ((SIR_MAC_MGMT_ACTION == pFc->subType) && + (0 != pMbMsg->wait)) + { + if (tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer)) + { + tANI_U32 val = 0; + tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer); + /* get the duration from the request */ + pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time(); + pMac->lim.gTotalScanDuration = pMbMsg->wait; + + val = SYS_MS_TO_TICKS(pMbMsg->wait); + + limLog(pMac, LOG1, + FL("Tx: Extending the gLimRemainOnChannelTimer")); + if (tx_timer_change( + &pMac->lim.limTimers.gLimRemainOnChannelTimer, val, 0) + != TX_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to change remain on channel Timer val")); + return; + } + else if(TX_SUCCESS != tx_timer_activate( + &pMac->lim.limTimers.gLimRemainOnChannelTimer)) + { + limLog(pMac, LOGP, + FL("Unable to activate remain on channel Timer")); + limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER); + return; + } + } + else + { + limLog(pMac, LOGE, + FL("Failed to Send Action frame")); + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + return; + } + } + } + +send_frame1: + // Ok-- try to allocate some memory: + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + (tANI_U16)nBytes, ( void** ) &pFrame, (void**) &pPacket); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to allocate %d bytes for a Probe" + " Request."), nBytes ); + return; + } + + // Paranoia: + vos_mem_set(pFrame, nBytes, 0); + + /* Add sequence number to action frames */ + /* Frames are handed over in .11 format by supplicant already */ + limPopulateP2pMacHeader(pMac, (tANI_U8*)pMbMsg->data); + + if ((noaLen > 0) && (noaLen<(SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN))) + { + // Add 2 bytes for length and Arribute field + v_U32_t nBytesToCopy = ((pP2PIe + origLen + 2 ) - + (v_U8_t *)pMbMsg->data); + vos_mem_copy(pFrame, pMbMsg->data, nBytesToCopy); + vos_mem_copy((pFrame + nBytesToCopy), noaStream, noaLen); + vos_mem_copy((pFrame + nBytesToCopy + noaLen), + pMbMsg->data + nBytesToCopy, nBytes - nBytesToCopy - noaLen); + + } + else + { + vos_mem_copy(pFrame, pMbMsg->data, nBytes); + } + +#ifdef WLAN_FEATURE_11W + pActionHdr = (tpSirMacActionFrameHdr) (pFrame + sizeof(tSirMacMgmtHdr)); + + /* + * Setting Protected bit for SA_QUERY Action Frame + * This has to be based on the current Connection with the station + * limSetProtectedBit API will set the protected bit if connection if PMF + */ + + if ((SIR_MAC_MGMT_ACTION == pFc->subType) && + (SIR_MAC_ACTION_SA_QUERY == pActionHdr->category)) + { + pMacHdr = (tpSirMacMgmtHdr ) pFrame; + psessionEntry = peFindSessionByBssid(pMac, + (tANI_U8*)pMbMsg->data + BSSID_OFFSET, &sessionId); + + /* Check for session corresponding to ADDR2 ss supplicant is filling + ADDR2 with BSSID */ + if(NULL == psessionEntry) + { + psessionEntry = peFindSessionByBssid(pMac, + (tANI_U8*)pMbMsg->data + ADDR2_OFFSET, &sessionId); + } + + if(NULL != psessionEntry) + { + limSetProtectedBit(pMac, psessionEntry, pMacHdr->da, pMacHdr); + } + else + { + limLog(pMac, LOGE, + FL("Dropping SA Query frame - Unable to find PE Session")); + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; + } + + /* + * If wep bit is not set in MAC header then we are trying to + * send SA Query via non PMF connection. Drop the packet. + */ + + if(0 == pMacHdr->fc.wep) + { + limLog(pMac, LOGE, + FL("Dropping SA Query frame due to non PMF connection")); + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; + } + } +#endif + + /* Use BD rate 2 for all P2P related frames. As these frames need to go + * at OFDM rates. And BD rate2 we configured at 6Mbps. + */ + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + + if ( (SIR_MAC_MGMT_PROBE_RSP == pFc->subType) || + (pMbMsg->noack) + ) + { + halstatus = halTxFrame( pMac, pPacket, (tANI_U16)nBytes, + HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, + 7, limTxComplete, pFrame, + txFlag, smeSessionId ); + + if (!pMbMsg->noack) + { + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + halstatus, pMbMsg->sessionId, 0); + } + pMac->lim.mgmtFrameSessionId = 0xff; + } + else + { + pMac->lim.mgmtFrameSessionId = pMbMsg->sessionId; + halstatus = halTxFrameWithTxComplete( pMac, pPacket, (tANI_U16)nBytes, + HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, + 7, limTxComplete, pFrame, + limP2PActionCnf, txFlag, smeSessionId, false ); + + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("could not send action frame!" )); + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, halstatus, + pMbMsg->sessionId, 0); + pMac->lim.mgmtFrameSessionId = 0xff; + } + else + { + pMac->lim.mgmtFrameSessionId = pMbMsg->sessionId; + limLog( pMac, LOG2, FL("lim.actionFrameSessionId = %u" ), + pMac->lim.mgmtFrameSessionId); + + } + } + + return; +} + + +void limAbortRemainOnChan(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + if (pMac->fP2pListenOffload) + { + limProcessAbortScanInd(pMac, sessionId); + return; + } + + if(VOS_TRUE == tx_timer_running( + &pMac->lim.limTimers.gLimRemainOnChannelTimer)) + { + //TODO check for state and take appropriate actions + limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER); + limProcessRemainOnChnTimeout(pMac); + } + return; +} + +/* Power Save Related Functions */ +tSirRetStatus __limProcessSmeNoAUpdate(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpP2pPsConfig pNoA; + tpP2pPsParams pMsgNoA; + tSirMsgQ msg; + + pNoA = (tpP2pPsConfig) pMsgBuf; + + pMsgNoA = vos_mem_malloc(sizeof( tP2pPsConfig )); + if (NULL == pMsgNoA) + { + limLog( pMac, LOGE, + FL( "Unable to allocate memory during NoA Update" )); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_set((tANI_U8 *)pMsgNoA, sizeof(tP2pPsConfig), 0); + pMsgNoA->opp_ps = pNoA->opp_ps; + pMsgNoA->ctWindow = pNoA->ctWindow; + pMsgNoA->duration = pNoA->duration; + pMsgNoA->interval = pNoA->interval; + pMsgNoA->count = pNoA->count; + pMsgNoA->single_noa_duration = pNoA->single_noa_duration; + pMsgNoA->psSelection = pNoA->psSelection; + pMsgNoA->sessionId = pNoA->sessionid; + + msg.type = WDA_SET_P2P_GO_NOA_REQ; + msg.reserved = 0; + msg.bodyptr = pMsgNoA; + msg.bodyval = 0; + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGE, FL("halPostMsgApi failed")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} /*** end __limProcessSmeGoNegReq() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c new file mode 100644 index 000000000000..5122856c4342 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c @@ -0,0 +1,2625 @@ +/* + * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file limProcessActionFrame.cc contains the code + * for processing Action Frame. + * Author: Michael Lui + * Date: 05/23/03 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "wniApi.h" +#include "sirApi.h" +#include "aniGlobal.h" +#include "wniCfgSta.h" +#include "schApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limSendSmeRspMessages.h" +#include "parserApi.h" +#include "limAdmitControl.h" +#include "wmmApsd.h" +#include "limSendMessages.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif +#include "limSessionUtils.h" + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseApi.h" +#endif +#include "wlan_qct_wda.h" + +#include "pmmApi.h" +#include "wma.h" + +#define BA_DEFAULT_TX_BUFFER_SIZE 64 + +typedef enum +{ + LIM_ADDBA_RSP = 0, + LIM_ADDBA_REQ = 1 +}tLimAddBaValidationReqType; + +/* Note: The test passes if the STAUT stops sending any frames, and no further + frames are transmitted on this channel by the station when the AP has sent + the last 6 beacons, with the channel switch information elements as seen + with the sniffer.*/ +#define SIR_CHANSW_TX_STOP_MAX_COUNT 6 +/**----------------------------------------------------------------- +\fn limStopTxAndSwitchChannel +\brief Stops the transmission if channel switch mode is silent and + starts the channel switch timer. + +\param pMac +\return NONE +-----------------------------------------------------------------*/ +void limStopTxAndSwitchChannel(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tANI_U8 isFullPowerRequested = 0; + tpPESession psessionEntry; + tANI_U8 isSessionPowerActive = false; + + psessionEntry = peFindSessionBySessionId( pMac , sessionId ); + + if( NULL == psessionEntry ) + { + limLog(pMac, LOGE, FL("Session %d not active"), sessionId); + return; + } + + /* + * Sme Session is passed in limSendSmePreChannelSwitchInd + * so that it can be passed till sme to request full power for + * particular session + */ + if(pMac->psOffloadEnabled) + { + isSessionPowerActive = pmmPsOffloadIsActive(pMac, psessionEntry); + } + else + { + isSessionPowerActive = limIsSystemInActiveState(pMac); + } + + PELOG1(limLog(pMac, LOG1, FL("Channel switch Mode == %d"), + psessionEntry->gLimChannelSwitch.switchMode);) + + if (psessionEntry->gLimChannelSwitch.switchMode == eSIR_CHANSW_MODE_SILENT || + psessionEntry->gLimChannelSwitch.switchCount <= SIR_CHANSW_TX_STOP_MAX_COUNT) + { + /* Freeze the transmission */ + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_STOP_TX); + + /*Request for Full power only if the device is in powersave*/ + if(!isSessionPowerActive) + { + /* Request Full Power */ + limSendSmePreChannelSwitchInd(pMac, psessionEntry); + isFullPowerRequested = 1; + } + } + else + { + /* Resume the transmission */ + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + } + + pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId = sessionId; + /* change the channel immediatly only if the channel switch count is 0 and the + * device is not in powersave + * If the device is in powersave channel switch should happen only after the + * device comes out of the powersave */ + if (psessionEntry->gLimChannelSwitch.switchCount == 0) + { + if(isSessionPowerActive) + { + limProcessChannelSwitchTimeout(pMac); + } + else if(!isFullPowerRequested) + { + /* + * If the Full power is already not requested + * Request Full Power so the channel switch happens + * after device comes to full power + */ + limSendSmePreChannelSwitchInd(pMac, psessionEntry); + } + return; + } + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, eLIM_CHANNEL_SWITCH_TIMER)); + + + if (tx_timer_activate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("tx_timer_activate failed")); + } + return; +} + +/**------------------------------------------------------------ +\fn limStartChannelSwitch +\brief Switches the channel if switch count == 0, otherwise + starts the timer for channel switch and stops BG scan + and heartbeat timer tempororily. + +\param pMac +\param psessionEntry +\return NONE +------------------------------------------------------------*/ +tSirRetStatus limStartChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + PELOG1(limLog(pMac, LOG1, FL("Starting the channel switch"));) + + /*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) && + psessionEntry->gLimSpecMgmt.dot11hChanSwState != eLIM_11H_CHANSW_RUNNING) || + psessionEntry->csaOffloadEnable) + { + limLog(pMac, LOGW, FL("Ignoring channel switch on session %d"), psessionEntry->peSessionId); + return eSIR_SUCCESS; + } + + /* Deactivate and change reconfigure the timeout value */ + //limDeactivateAndChangeTimer(pMac, eLIM_CHANNEL_SWITCH_TIMER); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("tx_timer_deactivate failed!")); + return eSIR_FAILURE; + } + + if (tx_timer_change(&pMac->lim.limTimers.gLimChannelSwitchTimer, + psessionEntry->gLimChannelSwitch.switchTimeoutValue, + 0) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("tx_timer_change failed ")); + return eSIR_FAILURE; + } + + /* Follow the channel switch, forget about the previous quiet. */ + //If quiet is running, chance is there to resume tx on its timeout. + //so stop timer for a safer side. + if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("tx_timer_deactivate failed")); + return eSIR_FAILURE; + } + } + else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("tx_timer_deactivate failed")); + return eSIR_FAILURE; + } + } + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + + /* Prepare for 11h channel switch */ + limPrepareFor11hChannelSwitch(pMac, psessionEntry); + + /** Dont add any more statements here as we posted finish scan request + * to HAL, wait till we get the response + */ + return eSIR_SUCCESS; +} + + +/** + * __limProcessChannelSwitchActionFrame + * + *FUNCTION: + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to packet info structure + * @return None + */ + +static void + +__limProcessChannelSwitchActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + + tpSirMacMgmtHdr pHdr; + tANI_U8 *pBody; + tDot11fChannelSwitch *pChannelSwitchFrame; + tANI_U16 beaconPeriod; + tANI_U32 val; + tANI_U32 frameLen; + tANI_U32 nStatus; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + PELOG3(limLog(pMac, LOG3, FL("Received Channel switch action frame"));) + if (!psessionEntry->lim11hEnable) + return; + + pChannelSwitchFrame = vos_mem_malloc(sizeof(*pChannelSwitchFrame)); + if (NULL == pChannelSwitchFrame) + { + limLog(pMac, LOGE, + FL("AllocateMemory failed")); + return; + } + + /* Unpack channel switch frame */ + nStatus = dot11fUnpackChannelSwitch(pMac, pBody, frameLen, pChannelSwitchFrame); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to unpack and parse an 11h-CHANSW Request (0x%08x, %d bytes):"), + nStatus, + frameLen); + vos_mem_free(pChannelSwitchFrame); + return; + } + else if(DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while unpacking an 11h-CHANSW Request (0x%08x, %d bytes):"), + nStatus, + frameLen); + } + + if (vos_mem_compare((tANI_U8 *) &psessionEntry->bssId, + (tANI_U8 *) &pHdr->sa, + sizeof(tSirMacAddr))) + { + /* copy the beacon interval from psessionEntry*/ + val = psessionEntry->beaconParams.beaconInterval; + + beaconPeriod = (tANI_U16) val; + + psessionEntry->gLimChannelSwitch.primaryChannel = pChannelSwitchFrame->ChanSwitchAnn.newChannel; + psessionEntry->gLimChannelSwitch.switchCount = pChannelSwitchFrame->ChanSwitchAnn.switchCount; + psessionEntry->gLimChannelSwitch.switchTimeoutValue = SYS_MS_TO_TICKS(beaconPeriod) * + psessionEntry->gLimChannelSwitch.switchCount; + psessionEntry->gLimChannelSwitch.switchMode = pChannelSwitchFrame->ChanSwitchAnn.switchMode; +#ifdef WLAN_FEATURE_11AC + if ( pChannelSwitchFrame->WiderBWChanSwitchAnn.present && psessionEntry->vhtCapability) + { + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = pChannelSwitchFrame->WiderBWChanSwitchAnn.newChanWidth; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = pChannelSwitchFrame->WiderBWChanSwitchAnn.newCenterChanFreq0; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = pChannelSwitchFrame->WiderBWChanSwitchAnn.newCenterChanFreq1; + } +#endif + + PELOG3(limLog(pMac, LOG3, FL("Rcv Chnl Swtch Frame: Timeout in %d ticks"), + psessionEntry->gLimChannelSwitch.switchTimeoutValue);) + + /* Only primary channel switch element is present */ + psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + psessionEntry->gLimChannelSwitch.secondarySubBand = PHY_SINGLE_CHANNEL_CENTERED; + + if (psessionEntry->htSupportedChannelWidthSet) { + if ((pChannelSwitchFrame->sec_chan_offset_ele. + secondaryChannelOffset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) || + (pChannelSwitchFrame->sec_chan_offset_ele. + secondaryChannelOffset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)) { + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + psessionEntry->gLimChannelSwitch.secondarySubBand = + pChannelSwitchFrame->sec_chan_offset_ele.secondaryChannelOffset; + } +#ifdef WLAN_FEATURE_11AC + if(psessionEntry->vhtCapability && + pChannelSwitchFrame->WiderBWChanSwitchAnn.present) { + if (pChannelSwitchFrame->WiderBWChanSwitchAnn.newChanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + if (pChannelSwitchFrame->sec_chan_offset_ele.present && + ((pChannelSwitchFrame->sec_chan_offset_ele. + secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) || + (pChannelSwitchFrame->sec_chan_offset_ele. + secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY))) { + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + psessionEntry->gLimChannelSwitch.secondarySubBand = + limGet11ACPhyCBState(pMac, + psessionEntry->gLimChannelSwitch.primaryChannel, + pChannelSwitchFrame->sec_chan_offset_ele. + secondaryChannelOffset, + pChannelSwitchFrame->WiderBWChanSwitchAnn. + newCenterChanFreq0, + psessionEntry); + } + } + } +#endif + } + + } + else + { + PELOG1(limLog(pMac, LOG1, FL("LIM: Received action frame not from our BSS, dropping..."));) + } + + if (eSIR_SUCCESS != limStartChannelSwitch(pMac, psessionEntry)) + { + PELOG1(limLog(pMac, LOG1, FL("Could not start channel switch"));) + } + + vos_mem_free(pChannelSwitchFrame); + return; +} /*** end limProcessChannelSwitchActionFrame() ***/ + +/** + * lim_process_ext_channel_switch_action_frame()- Process ECSA Action + * Frames. + * @mac_ctx: pointer to global mac structure + * @rx_packet_info: rx packet meta information + * @session_entry: Session entry. + * + * This function is called when ECSA action frame is received. + * + * Return: void + */ +static void +lim_process_ext_channel_switch_action_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_packet_info, tpPESession session_entry) +{ + + tpSirMacMgmtHdr hdr; + uint8_t *body; + tDot11fext_channel_switch_action_frame *ext_channel_switch_frame; + uint32_t frame_len; + uint32_t status; + uint8_t target_channel; + + hdr = WDA_GET_RX_MAC_HEADER(rx_packet_info); + body = WDA_GET_RX_MPDU_DATA(rx_packet_info); + frame_len = WDA_GET_RX_PAYLOAD_LEN(rx_packet_info); + + limLog(mac_ctx, LOG1, FL("Received EXT Channel switch action frame")); + + ext_channel_switch_frame = + vos_mem_malloc(sizeof(*ext_channel_switch_frame)); + if (NULL == ext_channel_switch_frame) { + limLog(mac_ctx, LOGE, FL("AllocateMemory failed")); + return; + } + + /* Unpack channel switch frame */ + status = dot11fUnpackext_channel_switch_action_frame(mac_ctx, + body, frame_len, ext_channel_switch_frame); + + if (DOT11F_FAILED(status)) { + + limLog( mac_ctx, LOGE, + FL( "Failed to parse CHANSW action frame (0x%08x, len %d):"), + status, frame_len); + vos_mem_free(ext_channel_switch_frame); + return; + } else if (DOT11F_WARNED(status)) { + + limLog( mac_ctx, LOGW, + FL( "There were warnings while unpacking CHANSW Request (0x%08x, %d bytes):"), + status, frame_len); + } + + target_channel = + ext_channel_switch_frame->ext_chan_switch_ann_action.new_channel; + + /* Free ext_channel_switch_frame here as its no longer needed */ + vos_mem_free(ext_channel_switch_frame); + /* + * Now, validate if channel change is required for the passed + * channel and if is valid in the current regulatory domain, + * and no concurrent session is running. + */ + if (!((session_entry->currentOperChannel != target_channel) && + ((vos_nv_getChannelEnabledState(target_channel) + == NV_CHANNEL_ENABLE) || + (vos_nv_getChannelEnabledState(target_channel) == NV_CHANNEL_DFS && + !vos_concurrent_open_sessions_running())))) { + limLog(mac_ctx, LOGE, FL(" Channel %d is not valid"), + target_channel); + return; + } + + if (eLIM_AP_ROLE == session_entry->limSystemRole) { + + struct sir_sme_ext_cng_chan_ind *ext_cng_chan_ind; + tSirMsgQ mmh_msg; + + ext_cng_chan_ind = vos_mem_malloc(sizeof(*ext_cng_chan_ind)); + if (NULL == ext_cng_chan_ind) { + limLog(mac_ctx, LOGP, + FL("AllocateMemory failed for ext_cng_chan_ind")); + return; + } + + vos_mem_zero(ext_cng_chan_ind, + sizeof(*ext_cng_chan_ind)); + ext_cng_chan_ind->session_id= + session_entry->smeSessionId; + + /* No need to extract op mode as BW will be decided in + * in SAP FSM depending on previous BW. + */ + ext_cng_chan_ind->new_channel = target_channel; + + mmh_msg.type = eWNI_SME_EXT_CHANGE_CHANNEL_IND; + mmh_msg.bodyptr = ext_cng_chan_ind; + mmh_msg.bodyval = 0; + limSysProcessMmhMsgApi(mac_ctx, &mmh_msg, ePROT); + } + return; +} /*** end lim_process_ext_channel_switch_action_frame() ***/ + + +#ifdef WLAN_FEATURE_11AC +static void +__limProcessOperatingModeActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + + tpSirMacMgmtHdr pHdr; + tANI_U8 *pBody; + tDot11fOperatingMode *pOperatingModeframe; + tANI_U32 frameLen; + tANI_U32 nStatus; + tpDphHashNode pSta; + tANI_U16 aid; + tANI_U8 operMode; + tANI_U8 cbMode; + tANI_U8 ch_bw = 0; + tANI_U8 skip_opmode_update = false; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + limLog(pMac, LOG1, FL("Received Operating Mode action frame")); + + if (RF_CHAN_14 >= psessionEntry->currentOperChannel) + cbMode = pMac->roam.configParam.channelBondingMode24GHz; + else + cbMode = pMac->roam.configParam.channelBondingMode5GHz; + + /* Do not update the channel bonding mode if channel bonding + * mode is disabled in INI. + */ + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cbMode) { + limLog(pMac, LOGW, FL("channel bonding disabled")); + return; + } + + pOperatingModeframe = vos_mem_malloc(sizeof(*pOperatingModeframe)); + if (NULL == pOperatingModeframe) + { + limLog(pMac, LOGE, + FL("AllocateMemory failed")); + return; + } + + /* Unpack channel switch frame */ + nStatus = dot11fUnpackOperatingMode(pMac, pBody, frameLen, pOperatingModeframe); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to unpack and parse an 11h-CHANSW Request (0x%08x, %d bytes):"), + nStatus, + frameLen); + vos_mem_free(pOperatingModeframe); + return; + } + else if(DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while unpacking an 11h-CHANSW Request (0x%08x, %d bytes):"), + nStatus, + frameLen); + } + pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + + operMode = pSta->vhtSupportedChannelWidthSet ? eHT_CHANNEL_WIDTH_80MHZ : pSta->htSupportedChannelWidthSet ? eHT_CHANNEL_WIDTH_40MHZ: eHT_CHANNEL_WIDTH_20MHZ; + + if ((operMode == eHT_CHANNEL_WIDTH_80MHZ) && + (pOperatingModeframe->OperatingMode.chanWidth > + eHT_CHANNEL_WIDTH_80MHZ)) + skip_opmode_update = true; + + if (!skip_opmode_update && + (operMode != pOperatingModeframe->OperatingMode.chanWidth)) + { + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + limLog(pMac, LOGE, + FL(" received Chanwidth %d, staIdx = %d"), + (pOperatingModeframe->OperatingMode.chanWidth ), + pSta->staIndex); + + limLog(pMac, LOGE, + FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), + pHdr->sa[0], + pHdr->sa[1], + pHdr->sa[2], + pHdr->sa[3], + pHdr->sa[4], + pHdr->sa[5]); + + if ((pOperatingModeframe->OperatingMode.chanWidth > + eHT_CHANNEL_WIDTH_80MHZ) && + (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { + pSta->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + ch_bw = eHT_CHANNEL_WIDTH_160MHZ; + } else if(pOperatingModeframe->OperatingMode.chanWidth >= + eHT_CHANNEL_WIDTH_80MHZ) { + pSta->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + ch_bw = eHT_CHANNEL_WIDTH_80MHZ; + } else if(pOperatingModeframe->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_40MHZ) { + pSta->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + ch_bw = eHT_CHANNEL_WIDTH_40MHZ; + } else if(pOperatingModeframe->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_20MHZ) { + pSta->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ; + ch_bw = eHT_CHANNEL_WIDTH_20MHZ; + } + limCheckVHTOpModeChange(pMac, psessionEntry, + ch_bw, + pSta->staIndex, pHdr->sa); + } + + if (pSta->vhtSupportedRxNss != (pOperatingModeframe->OperatingMode.rxNSS + 1)) { + pSta->vhtSupportedRxNss = pOperatingModeframe->OperatingMode.rxNSS + 1; + limSetNssChange( pMac, psessionEntry, pSta->vhtSupportedRxNss, + pSta->staIndex, pHdr->sa); + } + + vos_mem_free(pOperatingModeframe); + return; +} + +static void +__limProcessGidManagementActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + + tpSirMacMgmtHdr pHdr; + tANI_U8 *pBody; + tDot11fVHTGidManagementActionFrame *pGidManagementframe; + tANI_U32 frameLen; + tANI_U32 nStatus; + tpDphHashNode pSta; + tANI_U16 aid; + tANI_U32 membership = 0; + tANI_U32 userPosition = 0; + tANI_U32 *pMemLower; + tANI_U32 *pMemUpper; + tANI_U32 *pMemCur; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + PELOG3(limLog(pMac, LOG3, FL("Received GID Management action frame"));) + pGidManagementframe = vos_mem_malloc(sizeof(*pGidManagementframe)); + if (NULL == pGidManagementframe) + { + limLog(pMac, LOGE, + FL("AllocateMemory failed")); + return; + } + + /* Unpack Gid Mangement Action frame */ + nStatus = dot11fUnpackVHTGidManagementActionFrame(pMac, pBody, frameLen, pGidManagementframe); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to unpack and parse an GidManagement Action frame (0x%08x, %d bytes):"), + nStatus, + frameLen); + vos_mem_free(pGidManagementframe); + return; + } + else if(DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while unpacking an GidManagement Action frame (0x%08x, %d bytes):"), + nStatus, + frameLen); + } + pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + + { + limLog(pMac, LOGE, + FL(" received Gid Management Action Frame , staIdx = %d"), + pSta->staIndex); + + limLog(pMac, LOGE, + FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), + pHdr->sa[0], + pHdr->sa[1], + pHdr->sa[2], + pHdr->sa[3], + pHdr->sa[4], + pHdr->sa[5]); + + pMemLower = (tANI_U32 *)pGidManagementframe->VhtMembershipStatusArray.membershipStatusArray; + pMemUpper = (tANI_U32 *)&pGidManagementframe->VhtMembershipStatusArray.membershipStatusArray[4]; + + if (*pMemLower && *pMemUpper) + { + limLog(pMac, LOGE, + FL(" received frame with multiple group ID set, staIdx = %d"), + pSta->staIndex); + goto out; + } + if (*pMemLower) + { + pMemCur = pMemLower; + } + else if (*pMemUpper) + { + pMemCur = pMemUpper; + membership += sizeof(tANI_U32); + } + else + { + limLog(pMac, LOGE, + FL(" received Gid Management Frame with no group ID set, staIdx = %d"), + pSta->staIndex); + goto out; + } + while (!(*pMemCur & 1)) + { + *pMemCur >>= 1; + ++membership; + } + if (*pMemCur) + { + limLog(pMac, LOGE, + FL(" received frame with multiple group ID set, staIdx = %d"), + pSta->staIndex); + goto out; + } + + /*Just read the last two bits */ + userPosition = pGidManagementframe->VhtUserPositionArray.userPositionArray[membership] + & 0x3; + + limCheckMembershipUserPosition( pMac, psessionEntry, membership, + userPosition, pSta->staIndex); + } +out: + vos_mem_free(pGidManagementframe); + return; +} + +#endif + +static void +__limProcessAddTsReq(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ +} + + +static void +__limProcessAddTsRsp(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tSirAddtsRspInfo addts; + tSirRetStatus retval; + tpSirMacMgmtHdr pHdr; + tpDphHashNode pSta; + tANI_U16 aid; + tANI_U32 frameLen; + tANI_U8 *pBody; + tpLimTspecInfo tspecInfo; + tANI_U8 ac; + tpDphHashNode pStaDs = NULL; + tANI_U8 rspReqd = 1; + tANI_U32 cfgLen; + tSirMacAddr peerMacAddr; + + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + + PELOGW(limLog(pMac, LOGW, "Recv AddTs Response");) + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + PELOGW(limLog(pMac, LOGW, FL("AddTsRsp recvd at AP: ignoring"));) + return; + } + + pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + if (pSta == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Station context not found - ignoring AddTsRsp"));) + return; + } + + retval = sirConvertAddtsRsp2Struct(pMac, pBody, frameLen, &addts); + if (retval != eSIR_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("AddTsRsp parsing failed (error %d)"), retval);) + return; + } + + // don't have to check for qos/wme capabilities since we wouldn't have this + // flag set otherwise + if (! pMac->lim.gLimAddtsSent) + { + // we never sent an addts request! + PELOGW(limLog(pMac, LOGW, "Recvd AddTsRsp but no request was ever sent - ignoring");) + return; + } + + if (pMac->lim.gLimAddtsReq.req.dialogToken != addts.dialogToken) + { + limLog(pMac, LOGW, "AddTsRsp: token mismatch (got %d, exp %d) - ignoring", + addts.dialogToken, pMac->lim.gLimAddtsReq.req.dialogToken); + return; + } + + /* + * for successful addts reponse, try to add the classifier. + * if this fails for any reason, we should send a delts request to the ap + * for now, its ok not to send a delts since we are going to add support for + * multiple tclas soon and until then we won't send any addts requests with + * multiple tclas elements anyway. + * In case of addClassifier failure, we just let the addts timer run out + */ + if (((addts.tspec.tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) || + (addts.tspec.tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_BOTH)) && + (addts.status == eSIR_MAC_SUCCESS_STATUS)) + { + // add the classifier - this should always succeed + if (addts.numTclas > 1) // currently no support for multiple tclas elements + { + limLog(pMac, LOGE, FL("Sta %d: Too many Tclas (%d), only 1 supported"), + aid, addts.numTclas); + return; + } + else if (addts.numTclas == 1) + { + limLog(pMac, LOGW, "AddTs Response from STA %d: tsid %d, UP %d, OK!", aid, + addts.tspec.tsinfo.traffic.tsid, addts.tspec.tsinfo.traffic.userPrio); + } + } + limLog(pMac, LOGW, "Recv AddTsRsp: tsid %d, UP %d, status %d ", + addts.tspec.tsinfo.traffic.tsid, addts.tspec.tsinfo.traffic.userPrio, + addts.status); + + // deactivate the response timer + limDeactivateAndChangeTimer(pMac, eLIM_ADDTS_RSP_TIMER); + + if (addts.status != eSIR_MAC_SUCCESS_STATUS) + { + limLog(pMac, LOGW, "Recv AddTsRsp: tsid %d, UP %d, status %d ", + addts.tspec.tsinfo.traffic.tsid, addts.tspec.tsinfo.traffic.userPrio, + addts.status); + limSendSmeAddtsRsp(pMac, true, addts.status, psessionEntry, addts.tspec, + psessionEntry->smeSessionId, psessionEntry->transactionId); + + // clear the addts flag + pMac->lim.gLimAddtsSent = false; + + return; + } +#ifdef FEATURE_WLAN_ESE + if (addts.tsmPresent) { + limLog(pMac, LOGW, "TSM IE Present"); + psessionEntry->eseContext.tsm.tid = addts.tspec.tsinfo.traffic.userPrio; + vos_mem_copy(&psessionEntry->eseContext.tsm.tsmInfo, + &addts.tsmIE,sizeof(tSirMacESETSMIE)); +#ifdef FEATURE_WLAN_ESE_UPLOAD + limSendSmeTsmIEInd(pMac, psessionEntry, addts.tsmIE.tsid, + addts.tsmIE.state, addts.tsmIE.msmt_interval); +#else + limActivateTSMStatsTimer(pMac, psessionEntry); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + } +#endif + /* Since AddTS response was successful, check for the PSB flag + * and directional flag inside the TS Info field. + * An AC is trigger enabled AC if the PSB subfield is set to 1 + * in the uplink direction. + * An AC is delivery enabled AC if the PSB subfield is set to 1 + * in the downlink direction. + * An AC is trigger and delivery enabled AC if the PSB subfield + * is set to 1 in the bi-direction field. + */ + if(!pMac->psOffloadEnabled) + { + if (addts.tspec.tsinfo.traffic.psb == 1) + limSetTspecUapsdMask(pMac, &addts.tspec.tsinfo, SET_UAPSD_MASK); + else + limSetTspecUapsdMask(pMac, &addts.tspec.tsinfo, CLEAR_UAPSD_MASK); + + + /* + * ADDTS success, so AC is now admitted. We shall now use the default + * EDCA parameters as advertised by AP and send the updated EDCA params + * to HAL. + */ + ac = upToAc(addts.tspec.tsinfo.traffic.userPrio); + if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= (1 << ac); + } + else if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_DNLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= (1 << ac); + } + else if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_BIDIR) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= (1 << ac); + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= (1 << ac); + } + } + else + { + if (addts.tspec.tsinfo.traffic.psb == 1) + limSetTspecUapsdMaskPerSession(pMac, psessionEntry, + &addts.tspec.tsinfo, SET_UAPSD_MASK); + else + limSetTspecUapsdMaskPerSession(pMac, psessionEntry, + &addts.tspec.tsinfo, CLEAR_UAPSD_MASK); + + /* + * ADDTS success, so AC is now admitted. We shall now use the default + * EDCA parameters as advertised by AP and send the updated EDCA params + * to HAL. + */ + ac = upToAc(addts.tspec.tsinfo.traffic.userPrio); + if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= (1 << ac); + } + else if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_DNLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= (1 << ac); + } + else if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_BIDIR) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= (1 << ac); + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= (1 << ac); + } + } + + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); + else + limLog(pMac, LOGE, FL("Self entry missing in Hash Table ")); + + + sirCopyMacAddr(peerMacAddr,psessionEntry->bssId); + + //if schedule is not present then add TSPEC with svcInterval as 0. + if(!addts.schedulePresent) + addts.schedule.svcInterval = 0; + if(eSIR_SUCCESS != limTspecAdd(pMac, pSta->staAddr, pSta->assocId, &addts.tspec, addts.schedule.svcInterval, &tspecInfo)) + { + PELOGE(limLog(pMac, LOGE, FL("Adding entry in lim Tspec Table failed "));) + limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, &addts.tspec.tsinfo, &addts.tspec, + psessionEntry); + pMac->lim.gLimAddtsSent = false; + return; //Error handling. send the response with error status. need to send DelTS to tear down the TSPEC status. + } + if((addts.tspec.tsinfo.traffic.accessPolicy != SIR_MAC_ACCESSPOLICY_EDCA) || + ((upToAc(addts.tspec.tsinfo.traffic.userPrio) < MAX_NUM_AC))) + { +#ifdef FEATURE_WLAN_ESE + retval = limSendHalMsgAddTs(pMac, + pSta->staIndex, + tspecInfo->idx, + addts.tspec, + psessionEntry->peSessionId, + addts.tsmIE.msmt_interval); +#else + retval = limSendHalMsgAddTs(pMac, + pSta->staIndex, + tspecInfo->idx, + addts.tspec, + psessionEntry->peSessionId); +#endif + if(eSIR_SUCCESS != retval) + { + limAdmitControlDeleteTS(pMac, pSta->assocId, &addts.tspec.tsinfo, NULL, &tspecInfo->idx); + + // Send DELTS action frame to AP + cfgLen = sizeof(tSirMacAddr); + limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, &addts.tspec.tsinfo, &addts.tspec, + psessionEntry); + limSendSmeAddtsRsp(pMac, true, retval, psessionEntry, addts.tspec, + psessionEntry->smeSessionId, psessionEntry->transactionId); + pMac->lim.gLimAddtsSent = false; + return; + } + PELOGW(limLog(pMac, LOGW, FL("AddTsRsp received successfully(UP %d, TSID %d)"), + addts.tspec.tsinfo.traffic.userPrio, addts.tspec.tsinfo.traffic.tsid);) + } + else + { + PELOGW(limLog(pMac, LOGW, FL("AddTsRsp received successfully(UP %d, TSID %d)"), + addts.tspec.tsinfo.traffic.userPrio, addts.tspec.tsinfo.traffic.tsid);) + PELOGW(limLog(pMac, LOGW, FL("no ACM: Bypass sending WDA_ADD_TS_REQ to HAL "));) + // Use the smesessionId and smetransactionId from the PE session context + limSendSmeAddtsRsp(pMac, true, eSIR_SME_SUCCESS, psessionEntry, addts.tspec, + psessionEntry->smeSessionId, psessionEntry->transactionId); + } + + // clear the addts flag + pMac->lim.gLimAddtsSent = false; + return; +} + + +static void +__limProcessDelTsReq(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tSirRetStatus retval; + tSirDeltsReqInfo delts; + tpSirMacMgmtHdr pHdr; + tpDphHashNode pSta; + tANI_U32 frameLen; + tANI_U16 aid; + tANI_U8 *pBody; + tANI_U8 tsStatus; + tSirMacTSInfo *tsinfo; + tANI_U8 tspecIdx; + tANI_U8 ac; + tpDphHashNode pStaDs = NULL; + + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + if (pSta == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Station context not found - ignoring DelTs"));) + return; + } + + // parse the delts request + retval = sirConvertDeltsReq2Struct(pMac, pBody, frameLen, &delts); + if (retval != eSIR_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("DelTs parsing failed (error %d)"), retval);) + return; + } + + if (delts.wmeTspecPresent) + { + if ((!psessionEntry->limWmeEnabled) || (! pSta->wmeEnabled)) + { + PELOGW(limLog(pMac, LOGW, FL("Ignoring delts request: wme not enabled/capable"));) + return; + } + PELOG2(limLog(pMac, LOG2, FL("WME Delts received"));) + } + else if ((psessionEntry->limQosEnabled) && pSta->lleEnabled) + { + PELOG2(limLog(pMac, LOG2, FL("11e QoS Delts received"));) + } + else if ((psessionEntry->limWsmEnabled) && pSta->wsmEnabled) + { + PELOG2(limLog(pMac, LOG2, FL("WSM Delts received"));) + } + else + { + PELOGW(limLog(pMac, LOGW, FL("Ignoring delts request: qos not enabled/capable"));) + return; + } + + tsinfo = delts.wmeTspecPresent ? &delts.tspec.tsinfo : &delts.tsinfo; + + // if no Admit Control, ignore the request + if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA)) + { + + if (upToAc(tsinfo->traffic.userPrio) >= MAX_NUM_AC) + { + limLog(pMac, LOGW, FL("DelTs with UP %d has no AC - ignoring request"), + tsinfo->traffic.userPrio); + return; + } + } + + if (!LIM_IS_AP_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) + limSendSmeDeltsInd(pMac, &delts, aid,psessionEntry); + + // try to delete the TS + if (eSIR_SUCCESS != limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx)) + { + PELOGW(limLog(pMac, LOGW, FL("Unable to Delete TS"));) + return; + } + + else if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) || + (tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_BOTH)) + { + //Edca only for now. + } + else + { + //send message to HAL to delete TS + if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac, + pSta->staIndex, + tspecIdx, + delts, + psessionEntry->peSessionId, + psessionEntry->bssId)) + { + limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"), + tsinfo->traffic.userPrio); + return; + } + } + + /* We successfully deleted the TSPEC. Update the dynamic UAPSD Mask. + * The AC for this TSPEC is no longer trigger enabled if this Tspec + * was set-up in uplink direction only. + * The AC for this TSPEC is no longer delivery enabled if this Tspec + * was set-up in downlink direction only. + * The AC for this TSPEC is no longer triiger enabled and delivery + * enabled if this Tspec was a bidirectional TSPEC. + */ + if(!pMac->psOffloadEnabled) + { + limSetTspecUapsdMask(pMac, tsinfo, CLEAR_UAPSD_MASK); + + + /* We're deleting the TSPEC. + * The AC for this TSPEC is no longer admitted in uplink/downlink direction + * if this TSPEC was set-up in uplink/downlink direction only. + * The AC for this TSPEC is no longer admitted in both uplink and downlink + * directions if this TSPEC was a bi-directional TSPEC. + * If ACM is set for this AC and this AC is admitted only in downlink + * direction, PE needs to downgrade the EDCA parameter + * (for the AC for which TS is being deleted) to the + * next best AC for which ACM is not enabled, and send the + * updated values to HAL. + */ + ac = upToAc(tsinfo->traffic.userPrio); + + if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + } + else if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + else if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + } + else + { + limSetTspecUapsdMaskPerSession(pMac, psessionEntry, + tsinfo, CLEAR_UAPSD_MASK); + + + /* We're deleting the TSPEC. + * The AC for this TSPEC is no longer admitted in uplink/downlink direction + * if this TSPEC was set-up in uplink/downlink direction only. + * The AC for this TSPEC is no longer admitted in both uplink and downlink + * directions if this TSPEC was a bi-directional TSPEC. + * If ACM is set for this AC and this AC is admitted only in downlink + * direction, PE needs to downgrade the EDCA parameter + * (for the AC for which TS is being deleted) to the + * next best AC for which ACM is not enabled, and send the + * updated values to HAL. + */ + ac = upToAc(tsinfo->traffic.userPrio); + + if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + } + else if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + else if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + } + + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); + else + limLog(pMac, LOGE, FL("Self entry missing in Hash Table ")); + + PELOG1(limLog(pMac, LOG1, FL("DeleteTS succeeded"));) + +#ifdef FEATURE_WLAN_ESE +#ifdef FEATURE_WLAN_ESE_UPLOAD + limSendSmeTsmIEInd(pMac, psessionEntry, 0, 0, 0); +#else + limDeactivateAndChangeTimer(pMac,eLIM_TSM_TIMER); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + +} + +static void +__limProcessQosMapConfigureFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 *pBody; + tSirRetStatus retval; + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + retval = sirConvertQosMapConfigureFrame2Struct(pMac, pBody, frameLen, + &psessionEntry->QosMapSet); + if (retval != eSIR_SUCCESS) + { + PELOGW(limLog(pMac, LOGE, + FL("QosMapConfigure frame parsing failed (error %d)"), retval);) + return; + } + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, (tANI_U8*)pHdr, + frameLen + sizeof(tSirMacMgmtHdr), 0, + WDA_GET_RX_CH( pRxPacketInfo ), + psessionEntry, 0); +} + + + +/** + * \brief Validate an ADDBA Req from peer with respect + * to our own BA configuration + * + * \sa __limValidateAddBAParameterSet + * + * \param pMac The global tpAniSirGlobal object + * + * \param baParameterSet The ADDBA Parameter Set. + * + * \param pDelBAFlag this parameter is NULL except for call from processAddBAReq + * delBAFlag is set when entry already exists. + * + * \param reqType ADDBA Req v/s ADDBA Rsp + * 1 - ADDBA Req + * 0 - ADDBA Rsp + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ + +static tSirMacStatusCodes +__limValidateAddBAParameterSet( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tDot11fFfAddBAParameterSet baParameterSet, + tANI_U8 dialogueToken, + tLimAddBaValidationReqType reqType , + tANI_U8* pDelBAFlag /*this parameter is NULL except for call from processAddBAReq*/) +{ + if(baParameterSet.tid >= STACFG_MAX_TC) + { + return eSIR_MAC_WME_INVALID_PARAMS_STATUS; + } + + //check if there is already a BA session setup with this STA/TID while processing AddBaReq + if((true == pSta->tcCfg[baParameterSet.tid].fUseBARx) && + (LIM_ADDBA_REQ == reqType)) + { + //There is already BA session setup for STA/TID. + limLog(pMac, LOGE, + FL("AddBAReq rcvd when there is already a session for this StaId = %d, tid = %d"), + pSta->staIndex, baParameterSet.tid); + limPrintMacAddr( pMac, pSta->staAddr, LOGW ); + + if(pDelBAFlag) + *pDelBAFlag = true; + } + return eSIR_MAC_SUCCESS_STATUS; +} + +/** + * \brief Validate a DELBA Ind from peer with respect + * to our own BA configuration + * + * \sa __limValidateDelBAParameterSet + * + * \param pMac The global tpAniSirGlobal object + * + * \param baParameterSet The DELBA Parameter Set. + * + * \param pSta Runtime, STA-related configuration cached + * in the HashNode object + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +static tSirMacStatusCodes +__limValidateDelBAParameterSet( tpAniSirGlobal pMac, + tDot11fFfDelBAParameterSet baParameterSet, + tpDphHashNode pSta ) +{ +tSirMacStatusCodes statusCode = eSIR_MAC_STA_BLK_ACK_NOT_SUPPORTED_STATUS; + + // Validate if a BA is active for the requested TID + if( pSta->tcCfg[baParameterSet.tid].fUseBATx || + pSta->tcCfg[baParameterSet.tid].fUseBARx ) + { + statusCode = eSIR_MAC_SUCCESS_STATUS; + + limLog( pMac, LOGW, + FL("Valid DELBA Ind received. Time to send WDA_DELBA_IND to HAL...")); + } + else + limLog( pMac, LOGW, + FL("Received an INVALID DELBA Ind for TID %d..."), + baParameterSet.tid ); + + return statusCode; +} + +/** + * \brief Process an ADDBA REQ + * + * \sa limProcessAddBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pRxPacketInfo Handle to the Rx packet info from HDD + * + * \return none + * + */ +static void +__limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tDot11fAddBAReq frmAddBAReq; + tpSirMacMgmtHdr pHdr; + tpDphHashNode pSta; + tSirMacStatusCodes status = eSIR_MAC_SUCCESS_STATUS; + tANI_U16 aid; + tANI_U32 frameLen, nStatus,val; + tANI_U8 *pBody; + tANI_U8 delBAFlag =0; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + val = 0; + + // Unpack the received frame + nStatus = dot11fUnpackAddBAReq( pMac, pBody, frameLen, &frmAddBAReq ); + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL("Failed to unpack and parse an ADDBA Request (0x%08x, %d bytes):"), + nStatus, + frameLen ); + + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + + // Without an unpacked request we cannot respond, so silently ignore the request + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, + FL( "There were warnings while unpacking an ADDBA Request (0x%08x, %d bytes):"), + nStatus, + frameLen ); + + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + psessionEntry->amsduSupportedInBA = frmAddBAReq.AddBAParameterSet.amsduSupported; + + pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable ); + if( pSta == NULL ) + { + limLog( pMac, LOGE, + FL( "STA context not found - ignoring ADDBA from " )); + limPrintMacAddr( pMac, pHdr->sa, LOGE ); + + // FIXME - Should we do this? + status = eSIR_MAC_INABLITY_TO_CONFIRM_ASSOC_STATUS; + goto returnAfterError; + } + + limLog( pMac, LOG1, FL( "ADDBA Req from STA "MAC_ADDRESS_STR " with AID %d" + " tid = %d policy = %d buffsize = %d" + " amsduSupported = %d"), MAC_ADDR_ARRAY(pHdr->sa), + aid, frmAddBAReq.AddBAParameterSet.tid, + frmAddBAReq.AddBAParameterSet.policy, + frmAddBAReq.AddBAParameterSet.bufferSize, + frmAddBAReq.AddBAParameterSet.amsduSupported); + +#ifdef WLAN_SOFTAP_VSTA_FEATURE + // we can only do BA on "hard" STAs + if (!(IS_HWSTA_IDX(pSta->staIndex))) + { + status = eSIR_MAC_REQ_DECLINED_STATUS; + goto returnAfterError; + } +#endif //WLAN_SOFTAP_VSTA_FEATURE + + if (wlan_cfgGetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, &val) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("Unable to get WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + val = 0; + } + if ((SIR_BAND_2_4_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) && + val) + { + limLog( pMac, LOGW, + FL( "BTC disabled aggregation - ignoring ADDBA from " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + + status = eSIR_MAC_REQ_DECLINED_STATUS; + goto returnAfterError; + } + + // Now, validate the ADDBA Req + if( eSIR_MAC_SUCCESS_STATUS != + (status = __limValidateAddBAParameterSet( pMac, pSta, + frmAddBAReq.AddBAParameterSet, + 0, //dialogue token is don't care in request validation. + LIM_ADDBA_REQ, &delBAFlag))) + goto returnAfterError; + + //BA already set, so we need to delete it before adding new one. + if(delBAFlag) + { + if( eSIR_SUCCESS != limPostMsgDelBAInd( pMac, + pSta, + (tANI_U8)frmAddBAReq.AddBAParameterSet.tid, + eBA_RECIPIENT,psessionEntry)) + { + status = eSIR_MAC_UNSPEC_FAILURE_STATUS; + goto returnAfterError; + } + } + + // Check if the ADD BA Declined configuration is Disabled + if ((pMac->lim.gAddBA_Declined & ( 1 << frmAddBAReq.AddBAParameterSet.tid ) )) { + limLog( pMac, LOGE, FL( "Declined the ADDBA Req for the TID %d " ), + frmAddBAReq.AddBAParameterSet.tid); + status = eSIR_MAC_REQ_DECLINED_STATUS; + goto returnAfterError; + } + + // + // Post WDA_ADDBA_REQ to HAL. + // If HAL/HDD decide to allow this ADDBA Req session, + // then this BA session is termed active + // + + // Change the Block Ack state of this STA to wait for + // ADDBA Rsp from HAL + LIM_SET_STA_BA_STATE(pSta, frmAddBAReq.AddBAParameterSet.tid, eLIM_BA_STATE_WT_ADD_RSP); + + if (wlan_cfgGetInt(pMac, WNI_CFG_NUM_BUFF_ADVERT , &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Unable to get WNI_CFG_NUM_BUFF_ADVERT")); + return ; + } + + + if (frmAddBAReq.AddBAParameterSet.bufferSize) + { + frmAddBAReq.AddBAParameterSet.bufferSize = + VOS_MIN(val, frmAddBAReq.AddBAParameterSet.bufferSize); + } + else + { + frmAddBAReq.AddBAParameterSet.bufferSize = val; + } + limLog( pMac, LOG1, FL( "ADDBAREQ NUMBUFF %d" ), + frmAddBAReq.AddBAParameterSet.bufferSize); + + if( eSIR_SUCCESS != limPostMsgAddBAReq( pMac, + pSta, + (tANI_U8) frmAddBAReq.DialogToken.token, + (tANI_U8) frmAddBAReq.AddBAParameterSet.tid, + (tANI_U8) frmAddBAReq.AddBAParameterSet.policy, + frmAddBAReq.AddBAParameterSet.bufferSize, + frmAddBAReq.BATimeout.timeout, + (tANI_U16) frmAddBAReq.BAStartingSequenceControl.ssn, + eBA_RECIPIENT,psessionEntry)) + status = eSIR_MAC_UNSPEC_FAILURE_STATUS; + else + return; + +returnAfterError: + + // + // Package LIM_MLM_ADDBA_RSP to MLME, with proper + // status code. MLME will then send an ADDBA RSP + // over the air to the peer MAC entity + // + if( eSIR_SUCCESS != limPostMlmAddBARsp( pMac, + pHdr->sa, + status, + frmAddBAReq.DialogToken.token, + (tANI_U8) frmAddBAReq.AddBAParameterSet.tid, + (tANI_U8) frmAddBAReq.AddBAParameterSet.policy, + frmAddBAReq.AddBAParameterSet.bufferSize, + frmAddBAReq.BATimeout.timeout,psessionEntry)) + { + limLog( pMac, LOGW, + FL( "Failed to post LIM_MLM_ADDBA_RSP to " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + } + +} + +/** + * \brief Process an ADDBA RSP + * + * \sa limProcessAddBARsp + * + * \param pMac The global tpAniSirGlobal object + * + * \param pRxPacketInfo Handle to the packet info structure from HDD + * + * \return none + * + */ +static void +__limProcessAddBARsp( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ +tDot11fAddBARsp frmAddBARsp; +tpSirMacMgmtHdr pHdr; +tpDphHashNode pSta; +tSirMacReasonCodes reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; +tANI_U16 aid; +tANI_U32 frameLen, nStatus; +tANI_U8 *pBody; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + + pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable ); + if( pSta == NULL ) + { + limLog( pMac, LOGE, + FL( "STA context not found - ignoring ADDBA from " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + return; + } + +#ifdef WLAN_SOFTAP_VSTA_FEATURE + // We can only do BA on "hard" STAs. We should not have issued an ADDBA + // Request, so we should never be processing a ADDBA Response + if (!(IS_HWSTA_IDX(pSta->staIndex))) + { + return; + } +#endif //WLAN_SOFTAP_VSTA_FEATURE + + // Unpack the received frame + nStatus = dot11fUnpackAddBARsp( pMac, pBody, frameLen, &frmAddBARsp ); + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to unpack and parse an ADDBA Response (0x%08x, %d bytes):"), + nStatus, + frameLen ); + + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + goto returnAfterError; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, + FL( "There were warnings while unpacking an ADDBA Response (0x%08x, %d bytes):"), + nStatus, + frameLen ); + + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + limLog( pMac, LOG1, FL( "ADDBA Rsp from STA "MAC_ADDRESS_STR " with AID %d " + "tid = %d policy = %d buffsize = %d " + "amsduSupported = %d status = %d"), + MAC_ADDR_ARRAY(pHdr->sa), aid, + frmAddBARsp.AddBAParameterSet.tid, + frmAddBARsp.AddBAParameterSet.policy, + frmAddBARsp.AddBAParameterSet.bufferSize, + frmAddBARsp.AddBAParameterSet.amsduSupported, + frmAddBARsp.Status.status); + + //if there is no matchin dialougue token then ignore the response. + + if(eSIR_SUCCESS != limSearchAndDeleteDialogueToken(pMac, frmAddBARsp.DialogToken.token, + pSta->assocId, frmAddBARsp.AddBAParameterSet.tid)) + { + PELOGW(limLog(pMac, LOGE, FL("dialogueToken in received addBARsp did not match with outstanding requests"));) + return; + } + + // Check first if the peer accepted the ADDBA Req + if( eSIR_MAC_SUCCESS_STATUS == frmAddBARsp.Status.status ) + { + //if peer responded with buffer size 0 then we should pick the default. + if(0 == frmAddBARsp.AddBAParameterSet.bufferSize) + frmAddBARsp.AddBAParameterSet.bufferSize = BA_DEFAULT_TX_BUFFER_SIZE; + + // Now, validate the ADDBA Rsp + if( eSIR_MAC_SUCCESS_STATUS != + __limValidateAddBAParameterSet( pMac, pSta, + frmAddBARsp.AddBAParameterSet, + (tANI_U8)frmAddBARsp.DialogToken.token, + LIM_ADDBA_RSP, NULL)) + goto returnAfterError; + } + else + goto returnAfterError; + + // Change STA state to wait for ADDBA Rsp from HAL + LIM_SET_STA_BA_STATE(pSta, frmAddBARsp.AddBAParameterSet.tid, eLIM_BA_STATE_WT_ADD_RSP); + + // + // Post WDA_ADDBA_REQ to HAL. + // If HAL/HDD decide to allow this ADDBA Rsp session, + // then this BA session is termed active + // + + if( eSIR_SUCCESS != limPostMsgAddBAReq( pMac, + pSta, + (tANI_U8) frmAddBARsp.DialogToken.token, + (tANI_U8) frmAddBARsp.AddBAParameterSet.tid, + (tANI_U8) frmAddBARsp.AddBAParameterSet.policy, + frmAddBARsp.AddBAParameterSet.bufferSize, + frmAddBARsp.BATimeout.timeout, + 0, + eBA_INITIATOR,psessionEntry)) + reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; + else + return; + +returnAfterError: + + // TODO: Do we need to signal an error status to SME, + // if status != eSIR_MAC_SUCCESS_STATUS + + // Restore STA "BA" State + LIM_SET_STA_BA_STATE(pSta, frmAddBARsp.AddBAParameterSet.tid, eLIM_BA_STATE_IDLE); + // + // Need to send a DELBA IND to peer, who + // would have setup a BA session with this STA + // + if( eSIR_MAC_SUCCESS_STATUS == frmAddBARsp.Status.status ) + { + // + // Package LIM_MLM_DELBA_REQ to MLME, with proper + // status code. MLME will then send a DELBA IND + // over the air to the peer MAC entity + // + if( eSIR_SUCCESS != limPostMlmDelBAReq( pMac, + pSta, + eBA_INITIATOR, + (tANI_U8) frmAddBARsp.AddBAParameterSet.tid, + reasonCode, psessionEntry)) + { + limLog( pMac, LOGW, + FL( "Failed to post LIM_MLM_DELBA_REQ to " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + } + } +} + +/** + * \brief Process a DELBA Indication + * + * \sa limProcessDelBAInd + * + * \param pMac The global tpAniSirGlobal object + * + * \param pRxPacketInfo Handle to the Rx packet info from HDD + * + * \return none + * + */ +static void +__limProcessDelBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ +tDot11fDelBAInd frmDelBAInd; +tpSirMacMgmtHdr pHdr; +tpDphHashNode pSta; +tANI_U16 aid; +tANI_U32 frameLen, nStatus; +tANI_U8 *pBody; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + + pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable ); + if( pSta == NULL ) + { + limLog( pMac, LOGE, FL( "STA context not found - ignoring DELBA from ")); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + return; + } + + limLog( pMac, LOG1, FL( "DELBA Ind from STA with AID %d" ), aid ); + + // Unpack the received frame + nStatus = dot11fUnpackDelBAInd( pMac, pBody, frameLen, &frmDelBAInd ); + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to unpack and parse a DELBA Indication (0x%08x, %d bytes):"), + nStatus, + frameLen ); + + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, + FL( "There were warnings while unpacking a DELBA Indication (0x%08x, %d bytes):"), + nStatus, + frameLen ); + + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + limLog( pMac, LOGW, + FL( "Received DELBA for TID %d, Reason code %d" ), + frmDelBAInd.DelBAParameterSet.tid, + frmDelBAInd.Reason.code ); + + // Now, validate the DELBA Ind + if( eSIR_MAC_SUCCESS_STATUS != __limValidateDelBAParameterSet( pMac, + frmDelBAInd.DelBAParameterSet, + pSta )) + return; + + // + // Post WDA_DELBA_IND to HAL and delete the + // existing BA session + // + // NOTE - IEEE 802.11-REVma-D8.0, Section 7.3.1.16 + // is kind of confusing... + // + if( eSIR_SUCCESS != limPostMsgDelBAInd( pMac, + pSta, + (tANI_U8) frmDelBAInd.DelBAParameterSet.tid, + (eBA_RECIPIENT == frmDelBAInd.DelBAParameterSet.initiator)? + eBA_INITIATOR: eBA_RECIPIENT,psessionEntry)) + limLog( pMac, LOGE, FL( "Posting WDA_DELBA_IND to HAL failed ")); + + return; + +} + +static void +__limProcessSMPowerSaveUpdate(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry) +{ + + tpSirMacMgmtHdr pHdr; + tDot11fSMPowerSave frmSMPower; + tSirMacHTMIMOPowerSaveState state; + tpDphHashNode pSta; + tANI_U16 aid; + tANI_U32 frameLen, nStatus; + tANI_U8 *pBody; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + + pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable ); + if( pSta == NULL ) { + limLog( pMac, LOGE,FL( "STA context not found - ignoring UpdateSM PSave Mode from " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + return; + } + + /**Unpack the received frame */ + nStatus = dot11fUnpackSMPowerSave( pMac, pBody, frameLen, &frmSMPower); + + if( DOT11F_FAILED( nStatus )) { + limLog( pMac, LOGE, FL( "Failed to unpack and parse a Update SM Power (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + return; + }else if ( DOT11F_WARNED( nStatus ) ) { + limLog(pMac, LOGW, FL( "There were warnings while unpacking a SMPower Save update (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + limLog(pMac, LOGW, FL("Received SM Power save Mode update Frame with PS_Enable:%d" + "PS Mode: %d"), frmSMPower.SMPowerModeSet.PowerSave_En, + frmSMPower.SMPowerModeSet.Mode); + + /** Update in the DPH Table about the Update in the SM Power Save mode*/ + if (frmSMPower.SMPowerModeSet.PowerSave_En && frmSMPower.SMPowerModeSet.Mode) + state = eSIR_HT_MIMO_PS_DYNAMIC; + else if ((frmSMPower.SMPowerModeSet.PowerSave_En) && (frmSMPower.SMPowerModeSet.Mode ==0)) + state = eSIR_HT_MIMO_PS_STATIC; + else if ((frmSMPower.SMPowerModeSet.PowerSave_En == 0) && (frmSMPower.SMPowerModeSet.Mode == 0)) + state = eSIR_HT_MIMO_PS_NO_LIMIT; + else { + PELOGW(limLog(pMac, LOGW, FL("Received SM Power save Mode update Frame with invalid mode"));) + return; + } + + if (state == pSta->htMIMOPSState) { + PELOGE(limLog(pMac, LOGE, FL("The PEER is already set in the same mode"));) + return; + } + + /** Update in the HAL Station Table for the Update of the Protection Mode */ + pSta->htMIMOPSState = state; + limPostSMStateUpdate(pMac,pSta->staIndex, pSta->htMIMOPSState, + pSta->staAddr, psessionEntry->smeSessionId); +} + +#if defined WLAN_FEATURE_VOWIFI + +static void +__limProcessRadioMeasureRequest( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry ) +{ + tpSirMacMgmtHdr pHdr; + tDot11fRadioMeasurementRequest frm; + tANI_U32 frameLen, nStatus; + tANI_U8 *pBody; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + + if( psessionEntry == NULL ) + { + return; + } + + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, (tANI_U8*)pHdr, + frameLen + sizeof(tSirMacMgmtHdr), 0, WDA_GET_RX_CH(pRxPacketInfo), + psessionEntry, 0); + + /**Unpack the received frame */ + nStatus = dot11fUnpackRadioMeasurementRequest( pMac, pBody, frameLen, &frm ); + + if( DOT11F_FAILED( nStatus )) { + limLog( pMac, LOGE, FL( "Failed to unpack and parse a Radio Measure request (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + return; + }else if ( DOT11F_WARNED( nStatus ) ) { + limLog(pMac, LOGW, FL( "There were warnings while unpacking a Radio Measure request (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + // Call rrm function to handle the request. + + rrmProcessRadioMeasurementRequest( pMac, pHdr->sa, &frm, psessionEntry ); +} + +static void +__limProcessLinkMeasurementReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry ) +{ + tpSirMacMgmtHdr pHdr; + tDot11fLinkMeasurementRequest frm; + tANI_U32 frameLen, nStatus; + tANI_U8 *pBody; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + + if( psessionEntry == NULL ) + { + return; + } + + /**Unpack the received frame */ + nStatus = dot11fUnpackLinkMeasurementRequest( pMac, pBody, frameLen, &frm ); + + if( DOT11F_FAILED( nStatus )) { + limLog( pMac, LOGE, FL( "Failed to unpack and parse a Link Measure request (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + return; + }else if ( DOT11F_WARNED( nStatus ) ) { + limLog(pMac, LOGW, FL( "There were warnings while unpacking a Link Measure request (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + // Call rrm function to handle the request. + + rrmProcessLinkMeasurementRequest( pMac, pRxPacketInfo, &frm, psessionEntry ); + +} + +static void +__limProcessNeighborReport( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry ) +{ + tpSirMacMgmtHdr pHdr; + tDot11fNeighborReportResponse *pFrm; + tANI_U32 frameLen, nStatus; + tANI_U8 *pBody; + + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); + frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + + pFrm = vos_mem_malloc(sizeof(tDot11fNeighborReportResponse)); + if (NULL == pFrm) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in __limProcessNeighborReport") ); + return; + } + + if(psessionEntry == NULL) + { + vos_mem_free(pFrm); + return; + } + + /**Unpack the received frame */ + nStatus = dot11fUnpackNeighborReportResponse( pMac, pBody, frameLen,pFrm ); + + if( DOT11F_FAILED( nStatus )) { + limLog( pMac, LOGE, FL( "Failed to unpack and parse a Neighbor report response (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + vos_mem_free(pFrm); + return; + }else if ( DOT11F_WARNED( nStatus ) ) { + limLog(pMac, LOGW, FL( "There were warnings while unpacking a Neighbor report response (0x%08x, %d bytes):"), + nStatus, frameLen ); + PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) + } + + //Call rrm function to handle the request. + rrmProcessNeighborReportResponse( pMac, pFrm, psessionEntry ); + + vos_mem_free(pFrm); +} + +#endif + +#ifdef WLAN_FEATURE_11W +/** + * limProcessSAQueryRequestActionFrame + * + *FUNCTION: + * This function is called by limProcessActionFrame() upon + * SA query request Action frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - Handle to the Rx packet info + * @param psessionEntry - PE session entry + * + * @return None + */ +static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tANI_U8 *pBody; + tANI_U8 transId[2]; + + /* Prima --- Below Macro not available in prima + pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd); + pBody = SIR_MAC_BD_TO_MPDUDATA(pBd); */ + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + /* If this is an unprotected SA Query Request, then ignore it. */ + if (pHdr->fc.wep == 0) + return; + + /*Extract 11w trsansId from SA query request action frame + In SA query response action frame we will send same transId + In SA query request action frame: + Category : 1 byte + Action : 1 byte + Transaction ID : 2 bytes */ + vos_mem_copy(&transId[0], &pBody[2], 2); + + //Send 11w SA query response action frame + if (limSendSaQueryResponseFrame(pMac, + transId, + pHdr->sa,psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("fail to send SA query response action frame."));) + return; + } +} + +/** + * __limProcessSAQueryResponseActionFrame + * + *FUNCTION: + * This function is called by limProcessActionFrame() upon + * SA query response Action frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - Handle to the Rx packet info + * @param psessionEntry - PE session entry + * @return None + */ +static void __limProcessSAQueryResponseActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 *pBody; + tpDphHashNode pSta; + tANI_U16 aid; + tANI_U16 transId; + tANI_U8 retryNum; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + ("SA Query Response received...")) ; + + /* When a station, supplicant handles SA Query Response. + * Forward to SME to HDD to wpa_supplicant. + */ + if (LIM_IS_STA_ROLE(psessionEntry)) { + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, (tANI_U8*)pHdr, + frameLen + sizeof(tSirMacMgmtHdr), 0, + WDA_GET_RX_CH( pRxPacketInfo ), + psessionEntry, 0); + return; + } + + /* If this is an unprotected SA Query Response, then ignore it. */ + if (pHdr->fc.wep == 0) + return; + + pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + if (NULL == pSta) + return; + + limLog(pMac, LOG1, + FL("SA Query Response source addr - %0x:%0x:%0x:%0x:%0x:%0x"), + pHdr->sa[0], pHdr->sa[1], pHdr->sa[2], pHdr->sa[3], + pHdr->sa[4], pHdr->sa[5]); + limLog(pMac, LOG1, + FL("SA Query state for station - %d"), pSta->pmfSaQueryState); + + if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState) + return; + + /* Extract 11w trsansId from SA query reponse action frame + In SA query response action frame: + Category : 1 byte + Action : 1 byte + Transaction ID : 2 bytes */ + vos_mem_copy(&transId, &pBody[2], 2); + + /* If SA Query is in progress with the station and the station + responds then the association request that triggered the SA + query is from a rogue station, just go back to initial state. */ + for (retryNum = 0; retryNum <= pSta->pmfSaQueryRetryCount; retryNum++) + if (transId == pSta->pmfSaQueryStartTransId + retryNum) + { + limLog(pMac, LOG1, + FL("Found matching SA Query Request - transaction ID %d"), transId); + tx_timer_deactivate(&pSta->pmfSaQueryTimer); + pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; + break; + } +} +#endif + +#ifdef WLAN_FEATURE_11W +/** + * limDropUnprotectedActionFrame + * + *FUNCTION: + * This function checks if an Action frame should be dropped since it is + * a Robust Managment Frame, it is unprotected, and it is received on a + * connection where PMF is enabled. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Global MAC structure + * @param psessionEntry - PE session entry + * @param pHdr - Frame header + * @param category - Action frame category + * @return TRUE if frame should be dropped + */ + +static tANI_BOOLEAN +limDropUnprotectedActionFrame (tpAniSirGlobal pMac, tpPESession psessionEntry, + tpSirMacMgmtHdr pHdr, tANI_U8 category) +{ + tANI_U16 aid; + tpDphHashNode pStaDs; + tANI_BOOLEAN rmfConnection = eANI_BOOLEAN_FALSE; + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + if (pStaDs->rmfEnabled) + rmfConnection = eANI_BOOLEAN_TRUE; + } else if (psessionEntry->limRmfEnabled) + rmfConnection = eANI_BOOLEAN_TRUE; + + if (rmfConnection && (pHdr->fc.wep == 0)) + { + PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " + "since RMF is enabled."), category);) + return eANI_BOOLEAN_TRUE; + } + else + return eANI_BOOLEAN_FALSE; +} +#endif + +/** + * limProcessActionFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Action frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to packet info structure + * @return None + */ + +void +limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + tpSirMacActionFrameHdr pActionHdr = (tpSirMacActionFrameHdr) pBody; +#ifdef WLAN_FEATURE_11W + tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); +#endif + tANI_U32 frameLen; + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + switch (pActionHdr->category) + { + case SIR_MAC_ACTION_QOS_MGMT: +#ifdef WLAN_FEATURE_11W + if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) + break; +#endif + if ( (psessionEntry->limQosEnabled) || + (pActionHdr->actionID == SIR_MAC_QOS_MAP_CONFIGURE) ) + { + switch (pActionHdr->actionID) + { + case SIR_MAC_QOS_ADD_TS_REQ: + __limProcessAddTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_QOS_ADD_TS_RSP: + __limProcessAddTsRsp(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_QOS_DEL_TS_REQ: + __limProcessDelTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_QOS_MAP_CONFIGURE: + __limProcessQosMapConfigureFrame(pMac, + (tANI_U8 *) pRxPacketInfo, psessionEntry); + break; + default: + PELOGE(limLog(pMac, LOGE, FL("Qos action %d not handled"), pActionHdr->actionID);) + break; + } + break ; + } + + break; + + case SIR_MAC_ACTION_SPECTRUM_MGMT: +#ifdef WLAN_FEATURE_11W + if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) + break; +#endif + switch (pActionHdr->actionID) + { + case SIR_MAC_ACTION_CHANNEL_SWITCH_ID: + if (LIM_IS_STA_ROLE(psessionEntry)) { + __limProcessChannelSwitchActionFrame(pMac, + pRxPacketInfo, + psessionEntry); + } + break; + default: + PELOGE(limLog(pMac, LOGE, FL("Spectrum mgmt action id %d not handled"), pActionHdr->actionID);) + break; + } + break; + + case SIR_MAC_ACTION_WME: + if (! psessionEntry->limWmeEnabled) + { + limLog(pMac, LOGW, FL("WME mode disabled - dropping action frame %d"), + pActionHdr->actionID); + break; + } + switch(pActionHdr->actionID) + { + case SIR_MAC_QOS_ADD_TS_REQ: + __limProcessAddTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_QOS_ADD_TS_RSP: + __limProcessAddTsRsp(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_QOS_DEL_TS_REQ: + __limProcessDelTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_QOS_MAP_CONFIGURE: + __limProcessQosMapConfigureFrame(pMac, + (tANI_U8 *) pRxPacketInfo, psessionEntry); + break; + + default: + PELOGE(limLog(pMac, LOGE, FL("WME action %d not handled"), pActionHdr->actionID);) + break; + } + break; + + case SIR_MAC_ACTION_BLKACK: + // Determine the "type" of BA Action Frame +#ifdef WLAN_FEATURE_11W + if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) + break; +#endif + switch(pActionHdr->actionID) + { + case SIR_MAC_BLKACK_ADD_REQ: + __limProcessAddBAReq( pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_BLKACK_ADD_RSP: + __limProcessAddBARsp( pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_BLKACK_DEL: + __limProcessDelBAReq( pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + + default: + break; + } + + break; + case SIR_MAC_ACTION_HT: + /** Type of HT Action to be performed*/ + switch(pActionHdr->actionID) { + case SIR_MAC_SM_POWER_SAVE: + if (LIM_IS_AP_ROLE(psessionEntry)) + __limProcessSMPowerSaveUpdate(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry); + break; + default: + PELOGE(limLog(pMac, LOGE, FL("Action ID %d not handled in HT Action category"), pActionHdr->actionID);) + break; + } + break; + + case SIR_MAC_ACTION_WNM: + { +#ifdef WLAN_FEATURE_11W + if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) + { + PELOGE(limLog(pMac, LOGE, FL + ("Dropping unprotected Action category %d frame since RMF is enabled."), + pActionHdr->category);) + break; + } +#endif + PELOGE(limLog(pMac, LOG1, FL("WNM Action category %d action %d."), + pActionHdr->category, pActionHdr->actionID);) + switch (pActionHdr->actionID) + { + case SIR_MAC_WNM_BSS_TM_QUERY: + case SIR_MAC_WNM_BSS_TM_REQUEST: + case SIR_MAC_WNM_BSS_TM_RESPONSE: + case SIR_MAC_WNM_NOTIF_REQUEST: + case SIR_MAC_WNM_NOTIF_RESPONSE: + { + tpSirMacMgmtHdr pHdr; + tANI_S8 rssi = WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + /* Forward to the SME to HDD to wpa_supplicant */ + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, (tANI_U8*)pHdr, + frameLen + sizeof(tSirMacMgmtHdr), + psessionEntry->smeSessionId, + WDA_GET_RX_CH( pRxPacketInfo ), + psessionEntry, rssi); + break; + } + default: + PELOGE(limLog(pMac, LOGE, + FL("Action ID %d not handled in WNM Action category"), + pActionHdr->actionID);) + break; + } + break; + } +#if defined WLAN_FEATURE_VOWIFI + case SIR_MAC_ACTION_RRM: +#ifdef WLAN_FEATURE_11W + if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) + break; +#endif + if( pMac->rrm.rrmPEContext.rrmEnable ) + { + switch(pActionHdr->actionID) { + case SIR_MAC_RRM_RADIO_MEASURE_REQ: + __limProcessRadioMeasureRequest( pMac, (tANI_U8 *) pRxPacketInfo, psessionEntry ); + break; + case SIR_MAC_RRM_LINK_MEASUREMENT_REQ: + __limProcessLinkMeasurementReq( pMac, (tANI_U8 *) pRxPacketInfo, psessionEntry ); + break; + case SIR_MAC_RRM_NEIGHBOR_RPT: + __limProcessNeighborReport( pMac, (tANI_U8*) pRxPacketInfo, psessionEntry ); + break; + default: + PELOGE( limLog( pMac, LOGE, FL("Action ID %d not handled in RRM"), pActionHdr->actionID);) + break; + + } + } + else + { + // Else we will just ignore the RRM messages. + PELOGE( limLog( pMac, LOGE, FL("RRM Action frame ignored as RRM is disabled in cfg"));) + } + break; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY: + { + tpSirMacVendorSpecificFrameHdr pVendorSpecific = (tpSirMacVendorSpecificFrameHdr) pActionHdr; + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 Oui[] = { 0x00, 0x00, 0xf0 }; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + //Check if it is a vendor specific action frame. + if (LIM_IS_STA_ROLE(psessionEntry) && + (VOS_TRUE == vos_mem_compare(psessionEntry->selfMacAddr, + &pHdr->da[0], sizeof(tSirMacAddr))) && + IS_WES_MODE_ENABLED(pMac) && + vos_mem_compare(pVendorSpecific->Oui, Oui, 3)) { + PELOGE( limLog( pMac, LOGW, FL("Received Vendor specific action frame, OUI %x %x %x"), + pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], pVendorSpecific->Oui[2]);) + /* Forward to the SME to HDD to wpa_supplicant */ + // type is ACTION + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), + psessionEntry->smeSessionId, + WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); + } + else { + limLog( pMac, LOGE, FL("Dropping the vendor specific action frame because of( " + "WES Mode not enabled (WESMODE = %d) or OUI mismatch (%02x %02x %02x) or " + "not received with SelfSta Mac address) system role = %d"), + IS_WES_MODE_ENABLED(pMac), + pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], + pVendorSpecific->Oui[2], + GET_LIM_SYSTEM_ROLE(psessionEntry)); + } + } + break; +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || + FEATURE_WLAN_LFR */ + case SIR_MAC_ACTION_PUBLIC_USAGE: + switch(pActionHdr->actionID) { + case SIR_MAC_ACTION_VENDOR_SPECIFIC: + { + tpSirMacVendorSpecificPublicActionFrameHdr pPubAction = (tpSirMacVendorSpecificPublicActionFrameHdr) pActionHdr; + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 }; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + //Check if it is a P2P public action frame. + if (vos_mem_compare(pPubAction->Oui, P2POui, 4)) + { + /* Forward to the SME to HDD to wpa_supplicant */ + // type is ACTION + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), + psessionEntry->smeSessionId, + WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); + } + else + { + limLog( pMac, LOGE, FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"), + pPubAction->Oui[0], pPubAction->Oui[1], pPubAction->Oui[2], pPubAction->Oui[3] ); + } + } + break; + + case SIR_MAC_ACTION_2040_BSS_COEXISTENCE: + { + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), + psessionEntry->smeSessionId, + WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); + } + break; +#ifdef FEATURE_WLAN_TDLS + case SIR_MAC_TDLS_DIS_RSP: + { + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_S8 rssi; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + rssi = WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + ("Public Action TDLS Discovery RSP ..")) ; + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), + psessionEntry->smeSessionId, + WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, rssi); + } + break; +#endif + + case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID: + lim_process_ext_channel_switch_action_frame(pMac, + pRxPacketInfo, psessionEntry); + break; + default: + PELOGE(limLog(pMac, LOGE, FL("Unhandled public action frame -- %x "), pActionHdr->actionID);) + break; + } + break; + +#ifdef WLAN_FEATURE_11W + case SIR_MAC_ACTION_SA_QUERY: + { + PELOGE(limLog(pMac, LOG1, FL("SA Query Action category %d action %d."), pActionHdr->category, pActionHdr->actionID);) + if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) + break; + switch (pActionHdr->actionID) + { + case SIR_MAC_SA_QUERY_REQ: + /**11w SA query request action frame received**/ + /* Respond directly to the incoming request in LIM */ + __limProcessSAQueryRequestActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); + break; + case SIR_MAC_SA_QUERY_RSP: + /**11w SA query response action frame received**/ + /* Handle based on the current SA Query state */ + __limProcessSAQueryResponseActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); + break; + default: + break; + } + break; + } +#endif +#ifdef WLAN_FEATURE_11AC + case SIR_MAC_ACTION_VHT: + { + if (psessionEntry->vhtCapability) + { + switch (pActionHdr->actionID) + { + case SIR_MAC_VHT_OPMODE_NOTIFICATION: + __limProcessOperatingModeActionFrame(pMac,pRxPacketInfo,psessionEntry); + break; + case SIR_MAC_VHT_GID_NOTIFICATION: + /* Only if ini supports it */ + if (psessionEntry->enableVhtGid) + __limProcessGidManagementActionFrame(pMac,pRxPacketInfo,psessionEntry); + break; + default: + break; + } + } + break; + } +#endif + case SIR_MAC_ACTION_FST: + { + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + limLog(pMac, LOG1, FL("Received FST MGMT action frame")); + /* Forward to the SME to HDD */ + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, (tANI_U8*)pHdr, + frameLen + sizeof(tSirMacMgmtHdr), + psessionEntry->smeSessionId, + WDA_GET_RX_CH(pRxPacketInfo), + psessionEntry, 0); + break; + } + default: + PELOGE(limLog(pMac, LOGE, FL("Action category %d not handled"), pActionHdr->category);) + break; + } +} + +/** + * limProcessActionFrameNoSession + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Action frame reception and no session. + * Currently only public action frames can be received from + * a non-associated station. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pBd - A pointer to Buffer descriptor + associated PDUs + * @return None + */ + +void +limProcessActionFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd) +{ + tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pBd); + tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr = (tpSirMacVendorSpecificPublicActionFrameHdr) pBody; + + limLog( pMac, LOG1, "Received a Action frame -- no session"); + + switch ( pActionHdr->category ) + { + case SIR_MAC_ACTION_PUBLIC_USAGE: + switch(pActionHdr->actionID) { + case SIR_MAC_ACTION_VENDOR_SPECIFIC: + { + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 }; + + pHdr = WDA_GET_RX_MAC_HEADER(pBd); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd); + + //Check if it is a P2P public action frame. + if (vos_mem_compare(pActionHdr->Oui, P2POui, 4)) + { + /* Forward to the SME to HDD to wpa_supplicant */ + // type is ACTION + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), 0, + WDA_GET_RX_CH( pBd ), NULL, 0); + } + else + { + limLog( pMac, LOGE, FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"), + pActionHdr->Oui[0], pActionHdr->Oui[1], pActionHdr->Oui[2], pActionHdr->Oui[3] ); + } + } + break; + default: + PELOGE(limLog(pMac, LOGE, FL("Unhandled public action frame -- %x "), pActionHdr->actionID);) + break; + } + break; + default: + PELOGE(limLog(pMac, LOG1, FL("Unhandled action frame without session -- %x "), pActionHdr->category);) + break; + + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c new file mode 100644 index 000000000000..4e7fbe234181 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c @@ -0,0 +1,1949 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limProcessAssocReqFrame.cc contains the code + * for processing Re/Association Request Frame. + * Author: Chandra Modumudi + * Date: 03/18/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * 05/26/10 js WPA handling in (Re)Assoc frames + * + */ +#include "palTypes.h" +#include "aniGlobal.h" +#include "wniCfgSta.h" +#include "sirApi.h" +#include "cfgApi.h" + +#include "schApi.h" +#include "pmmApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limStaHashApi.h" +#include "limAdmitControl.h" +#include "palApi.h" +#include "limSessionUtils.h" +#ifdef WLAN_FEATURE_11W +#include "wniCfgAp.h" +#endif + + +#include "vos_types.h" +#include "vos_utils.h" +/** + * limConvertSupportedChannels + * + *FUNCTION: + * This function is called by limProcessAssocReqFrame() to + * parse the channel support IE in the Assoc/Reassoc Request + * frame, and send relevant information in the SME_ASSOC_IND + * + *NOTE: + * + * @param pMac - A pointer to Global MAC structure + * @param pMlmAssocInd - A pointer to SME ASSOC/REASSOC IND + * @param assocReq - A pointer to ASSOC/REASSOC Request frame + * + * @return None + */ +static void +limConvertSupportedChannels(tpAniSirGlobal pMac, + tpLimMlmAssocInd pMlmAssocInd, + tSirAssocReq *assocReq) +{ + + tANI_U16 i, j, index=0; + tANI_U8 firstChannelNumber; + tANI_U8 numberOfChannel; + tANI_U8 nextChannelNumber; + + if(assocReq->supportedChannels.length >= SIR_MAX_SUPPORTED_CHANNEL_LIST) + { + limLog(pMac, LOG1, FL("Number of supported channels:%d is more than " + "MAX"), assocReq->supportedChannels.length); + pMlmAssocInd->supportedChannels.numChnl = 0; + return; + } + + for(i=0; i < (assocReq->supportedChannels.length); i++) + { + // Get First Channel Number + firstChannelNumber = assocReq->supportedChannels.supportedChannels[i]; + pMlmAssocInd->supportedChannels.channelList[index] = firstChannelNumber; + i++; + index++; + if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) + { + pMlmAssocInd->supportedChannels.numChnl = 0; + return; + } + // Get Number of Channels in a Subband + numberOfChannel = assocReq->supportedChannels.supportedChannels[i]; + PELOG2(limLog(pMac, LOG2, FL("Rcv AssocReq: chnl=%d, numOfChnl=%d "), + firstChannelNumber, numberOfChannel);) + + if (numberOfChannel > 1) + { + nextChannelNumber = firstChannelNumber; + if(SIR_BAND_5_GHZ == limGetRFBand(firstChannelNumber)) + { + for (j=1; j < numberOfChannel; j++) + { + nextChannelNumber += SIR_11A_FREQUENCY_OFFSET; + pMlmAssocInd->supportedChannels.channelList[index] = nextChannelNumber; + index++; + if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) + { + pMlmAssocInd->supportedChannels.numChnl = 0; + return; + } + } + } + else if(SIR_BAND_2_4_GHZ == limGetRFBand(firstChannelNumber)) + { + for (j=1; j < numberOfChannel; j++) + { + nextChannelNumber += SIR_11B_FREQUENCY_OFFSET; + pMlmAssocInd->supportedChannels.channelList[index] = nextChannelNumber; + index++; + if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) + { + pMlmAssocInd->supportedChannels.numChnl = 0; + return; + } + } + } + } + } + + pMlmAssocInd->supportedChannels.numChnl = (tANI_U8) index; + PELOG2(limLog(pMac, LOG2, + FL("Send AssocInd to WSM: spectrum ON, minPwr %d, maxPwr %d, " + "numChnl %d"), + pMlmAssocInd->powerCap.minTxPower, + pMlmAssocInd->powerCap.maxTxPower, + pMlmAssocInd->supportedChannels.numChnl);) +} + +/**--------------------------------------------------------------- +\fn lim_check_sta_in_pe_entries +\brief This function is called by limProcessAssocReqFrame() +\ to check if STA entry already exists in any of the +\ PE entries of the AP. If it exists, deauth will be +\ sent on that session and the STA deletion will +\ happen. After this, the ASSOC request will be +\ processed +\ +\param pMac - A pointer to Global MAC structure +\param pHdr - A pointer to the MAC header +\return None +------------------------------------------------------------------*/ +void lim_check_sta_in_pe_entries(tpAniSirGlobal pMac, tpSirMacMgmtHdr pHdr) +{ + tANI_U8 i; + tANI_U16 assocId = 0; + tpDphHashNode pStaDs = NULL; + tpPESession psessionEntry=NULL; + + for(i = 0; i < pMac->lim.maxBssId; i++) + { + if ((&pMac->lim.gpSession[i] != NULL) && + (pMac->lim.gpSession[i].valid) && + (pMac->lim.gpSession[i].pePersona == VOS_STA_SAP_MODE)) { + + psessionEntry = &pMac->lim.gpSession[i]; + + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &assocId, + &psessionEntry->dph.dphHashTable); + if (pStaDs +#ifdef WLAN_FEATURE_11W + && !pStaDs->rmfEnabled +#endif + ) { + limLog(pMac, LOGE, + FL("Sending Deauth and Deleting existing STA entry: " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(psessionEntry->selfMacAddr)); + limSendDeauthMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON, + (tANI_U8 *) pHdr->sa, psessionEntry, FALSE); + limTriggerSTAdeletion(pMac, pStaDs, psessionEntry); + break; + } + } + } +} + +/**--------------------------------------------------------------- +\fn limProcessAssocReqFrame +\brief This function is called by limProcessMessageQueue() +\ upon Re/Association Request frame reception in +\ BTAMP AP or Soft AP role. +\ +\param pMac +\param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs +\param subType - Indicates whether it is Association Request(=0) +\ or Reassociation Request(=1) frame +\return None +------------------------------------------------------------------*/ +void +limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, + tANI_U8 subType, tpPESession psessionEntry) +{ + tANI_U8 updateContext; + tANI_U8 *pBody; + tANI_U16 peerIdx, temp; + tANI_U32 val; + tANI_S32 framelen; + tSirRetStatus status; + tpSirMacMgmtHdr pHdr; + struct tLimPreAuthNode *pStaPreAuthContext; + tAniAuthType authType; + tSirMacCapabilityInfo localCapabilities; + tpDphHashNode pStaDs = NULL; + tpSirAssocReq pAssocReq, pTempAssocReq; + tLimMlmStates mlmPrevState; + tDot11fIERSN Dot11fIERSN; + tDot11fIEWPA Dot11fIEWPA; + tANI_U32 phyMode; + tHalBitVal qosMode; + tHalBitVal wsmMode, wmeMode; + tANI_U8 *wpsIe = NULL; + tANI_U8 *ht_cap_ie = NULL; + tSirMacRateSet basicRates; + tANI_U8 i = 0, j = 0; + tANI_BOOLEAN pmfConnection = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_11W + tPmfSaQueryTimerId timerId; + tANI_U32 retryInterval; +#endif + tANI_U16 assocId = 0; + bool assoc_req_copied = false; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + limGetQosMode(psessionEntry, &qosMode); + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + framelen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + limLog(pMac, LOG1, FL("Received %s Req Frame on sessionid: %d systemrole %d" + " limMlmState %d from: "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), + psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->sa)); + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + limLog(pMac, LOGE, FL("received unexpected ASSOC REQ on sessionid: %d " + "sys subType=%d for role=%d from: "MAC_ADDRESS_STR), + psessionEntry->peSessionId, + subType, GET_LIM_SYSTEM_ROLE(psessionEntry), MAC_ADDR_ARRAY(pHdr->sa)); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, + WDA_GET_RX_MPDU_DATA(pRxPacketInfo), framelen); + return; + } + + /* + * If a STA is already present in DPH and it + * is initiating a Assoc re-transmit, do not + * process it. This can happen when first Assoc Req frame + * is received but ACK lost at STA side. The ACK for this + * dropped Assoc Req frame should be sent by HW. Host simply + * does not process it once the entry for the STA is already + * present in DPH. + */ + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &assocId, + &psessionEntry->dph.dphHashTable); + + if (NULL != pStaDs) + { + if (pHdr->fc.retry > 0) { + /* Ignore the Retry */ + limLog(pMac, LOGE, + FL("STA is initiating Assoc Req after ACK lost. " + "So, do not Process sessionid: %d sys subType=%d " + "for role=%d from: "MAC_ADDRESS_STR), + psessionEntry->peSessionId, subType, + psessionEntry->limSystemRole, + MAC_ADDR_ARRAY(pHdr->sa)); + return; + } else if (!pStaDs->rmfEnabled) { + /* Do this only for non PMF case. + * + * STA might have missed the assoc response, + * so it is sending assoc request frame again. + */ + limSendAssocRspMgmtFrame(pMac, eSIR_SUCCESS, + pStaDs->assocId, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, pStaDs, + psessionEntry); + limLog(pMac, LOGE, + FL("DUT already received an assoc request frame " + "and STA is sending another assoc req.So, do not " + "Process sessionid: %d sys subType=%d for role=%d " + "from: "MAC_ADDRESS_STR), + psessionEntry->peSessionId, subType, + psessionEntry->limSystemRole, + MAC_ADDR_ARRAY(pHdr->sa)); + return; + } + } + + lim_check_sta_in_pe_entries(pMac, pHdr); + + // Get pointer to Re/Association Request frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (limIsGroupAddr(pHdr->sa)) + { + // Received Re/Assoc Req frame from a BC/MC address + // Log error and ignore it + limLog(pMac, LOGE, FL("Received %s Req on sessionid: %d frame from a " + "BC/MC address"MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + psessionEntry->peSessionId, + MAC_ADDR_ARRAY(pHdr->sa)); + return; + } + + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, (tANI_U8 *) pBody, framelen); + + if (vos_mem_compare((tANI_U8* ) pHdr->sa, (tANI_U8 *) pHdr->da, + (tANI_U8) (sizeof(tSirMacAddr)))) + { + limLog(pMac, LOGE, FL("Rejected Assoc Req frame Since same mac as" + " SAP/GO")); + limSendAssocRspMgmtFrame(pMac, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + return ; + } + + // If TKIP counter measures active send Assoc Rsp frame to station with eSIR_MAC_MIC_FAILURE_REASON + if ((psessionEntry->bTkipCntrMeasActive) && LIM_IS_AP_ROLE(psessionEntry)) { + limLog(pMac, LOGE, FL("TKIP counter measure is active")); + limSendAssocRspMgmtFrame(pMac, + eSIR_MAC_MIC_FAILURE_REASON, + 1, + pHdr->sa, + subType, 0, psessionEntry); + return; + } + + // Allocate memory for the Assoc Request frame + pAssocReq = vos_mem_malloc(sizeof(*pAssocReq)); + if (NULL == pAssocReq) + { + limLog(pMac, LOGP, FL("Allocate Memory failed in AssocReq")); + return; + } + vos_mem_set((void *)pAssocReq , sizeof(*pAssocReq), 0); + + // Parse Assoc Request frame + if (subType == LIM_ASSOC) + status = sirConvertAssocReqFrame2Struct(pMac, pBody, framelen, pAssocReq); + else + status = sirConvertReassocReqFrame2Struct(pMac, pBody, framelen, pAssocReq); + + if (status != eSIR_SUCCESS) + { + limLog(pMac, LOGE, 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); + goto error; + } + + pAssocReq->assocReqFrame = vos_mem_malloc(framelen); + if ( NULL == pAssocReq->assocReqFrame ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory for the assoc req, " + "length=%d from "),framelen); + goto error; + } + + vos_mem_copy((tANI_U8 *) pAssocReq->assocReqFrame, + (tANI_U8 *) pBody, framelen); + pAssocReq->assocReqFrameLength = framelen; + + if (cfgGetCapabilityInfo(pMac, &temp,psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not retrieve Capabilities")); + goto error; + } + limCopyU16((tANI_U8 *) &localCapabilities, temp); + + if (limCompareCapabilities(pMac, + pAssocReq, + &localCapabilities,psessionEntry) == false) + { + limLog(pMac, LOGE, FL("local caps mismatch received caps")); + limLog(pMac, LOGE, FL("Received %s Req with unsupported " + "capabilities from"MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + /** + * Capabilities of requesting STA does not match with + * local capabilities. Respond with 'unsupported capabilities' + * status code. + */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + } + + updateContext = false; + + if (limCmpSSid(pMac, &pAssocReq->ssId, psessionEntry) == false) + { + limLog(pMac, LOGE, FL("Received %s Req with unmatched ssid ( Received" + " SSID: %.*s current SSID: %.*s ) from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", pAssocReq->ssId.length, + pAssocReq->ssId.ssId, psessionEntry->ssId.length, + psessionEntry->ssId.ssId, MAC_ADDR_ARRAY(pHdr->sa)); + + /** + * Received Re/Association Request with either + * Broadcast SSID OR with SSID that does not + * match with local one. + * Respond with unspecified status code. + */ + limSendAssocRspMgmtFrame(pMac, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + } + + /*************************************************************** + ** Verify if the requested rates are available in supported rate + ** set or Extended rate set. Some APs are adding basic rates in + ** Extended rateset IE + ***************************************************************/ + basicRates.numRates = 0; + + for(i = 0; i < pAssocReq->supportedRates.numRates && (i < SIR_MAC_RATESET_EID_MAX); i++) + { + basicRates.rate[i] = pAssocReq->supportedRates.rate[i]; + basicRates.numRates++; + } + + for(j = 0; (j < pAssocReq->extendedRates.numRates) && (i < SIR_MAC_RATESET_EID_MAX); i++,j++) + { + basicRates.rate[i] = pAssocReq->extendedRates.rate[j]; + basicRates.numRates++; + } + if (limCheckRxBasicRates(pMac, basicRates, psessionEntry) == false) + { + limLog(pMac, LOGE, FL("Received %s Req with unsupported " + "rates from"MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + /** + * Requesting STA does not support ALL BSS basic + * rates. Respond with 'basic rates not supported' + * status code. + */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + } + + + if (LIM_IS_AP_ROLE(psessionEntry) && + (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11G_ONLY) && + (pAssocReq->HTCaps.present)) { + 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 ); + goto error; + + }//end if phyMode == 11G_only + + if (LIM_IS_AP_ROLE(psessionEntry) && + (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11N_ONLY) && + (!pAssocReq->HTCaps.present)) { + 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 ); + goto error; + }//end if PhyMode == 11N_only + + if (LIM_IS_AP_ROLE(psessionEntry) && + (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11AC_ONLY) && + (!pAssocReq->VHTCaps.present)) { + limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, + 1, pHdr->sa, subType, 0, psessionEntry ); + limLog(pMac, LOGE, FL("SOFTAP was in 11AC only mode, reject")); + goto error; + }//end if PhyMode == 11AC_only + + /* Spectrum Management (11h) specific checks */ + if (localCapabilities.spectrumMgt) + { + tSirRetStatus status = eSIR_SUCCESS; + + /* If station is 11h capable, then it SHOULD send all mandatory + * IEs in assoc request frame. Let us verify that + */ + if (pAssocReq->capabilityInfo.spectrumMgt) + { + if (!((pAssocReq->powerCapabilityPresent) && (pAssocReq->supportedChannelsPresent))) + { + /* One or more required information elements are missing, log the peers error */ + if (!pAssocReq->powerCapabilityPresent) + { + limLog(pMac, LOG1, FL("LIM Info: Missing Power capability " + "IE in %s Req from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + } + if (!pAssocReq->supportedChannelsPresent) + { + limLog(pMac, LOGW, FL("LIM Info: Missing Supported channel " + "IE in %s Req from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + + } + } + else + { + /* Assoc request has mandatory fields */ + status = limIsDot11hPowerCapabilitiesInRange(pMac, pAssocReq, psessionEntry); + if (eSIR_SUCCESS != status) + { + limLog(pMac, LOGW, FL("LIM Info: MinTxPower(STA) > " + "MaxTxPower(AP) in %s Req from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + + } + status = limIsDot11hSupportedChannelsValid(pMac, pAssocReq); + if (eSIR_SUCCESS != status) + { + limLog(pMac, LOGW, FL("LIM Info: wrong supported " + "channels (STA) in %s Req from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + + } + /* IEs are valid, use them if needed */ + } + } //if(assoc.capabilityInfo.spectrumMgt) + else + { + /* As per the capabiities, the spectrum management is not enabled on the station + * The AP may allow the associations to happen even if spectrum management is not + * allowed, if the transmit power of station is below the regulatory maximum + */ + + /* TODO: presently, this is not handled. In the current implemetation, the AP would + * allow the station to associate even if it doesn't support spectrum management. + */ + } + }// end of spectrum management related processing + + if ( (pAssocReq->HTCaps.present) && (limCheckMCSSet(pMac, pAssocReq->HTCaps.supportedMCSSet) == false)) + { + limLog(pMac, LOGE, FL("received %s req with unsupported" + "MCS Rate Set from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + MAC_ADDR_ARRAY(pHdr->sa)); + + /** + * Requesting STA does not support ALL BSS MCS basic Rate set rates. + * Spec does not define any status code for this scenario. + */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_OUTSIDE_SCOPE_OF_SPEC_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + } + + if (phyMode == WNI_CFG_PHY_MODE_11G) + { + + if (wlan_cfgGetInt(pMac, WNI_CFG_11G_ONLY_POLICY, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not retrieve 11g-only flag")); + goto error; + } + + if (!pAssocReq->extendedRatesPresent && val) + { + /** + * Received Re/Association Request from + * 11b STA when 11g only policy option + * is set. + * Reject with unspecified status code. + */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + limLog(pMac, LOGE, FL("Rejecting Re/Assoc req from 11b STA: ")); + limPrintMacAddr(pMac, pHdr->sa, LOGW); + +#ifdef WLAN_DEBUG + pMac->lim.gLim11bStaAssocRejectCount++; +#endif + goto error; + } + } + + + // Check for 802.11n HT caps compatibility; are HT Capabilities + // turned on in lim? + if ( psessionEntry->htCapability ) + { + // There are; are they turned on in the STA? + if ( pAssocReq->HTCaps.present ) + { + // The station *does* support 802.11n HT capability... + + limLog( pMac, LOG1, FL( "AdvCodingCap:%d ChaWidthSet:%d " + "PowerSave:%d greenField:%d " + "shortGI20:%d shortGI40:%d" + "txSTBC:%d rxSTBC:%d delayBA:%d" + "maxAMSDUsize:%d DSSS/CCK:%d " + "PSMP:%d stbcCntl:%d lsigTXProt:%d"), + pAssocReq->HTCaps.advCodingCap, + pAssocReq->HTCaps.supportedChannelWidthSet, + pAssocReq->HTCaps.mimoPowerSave, + pAssocReq->HTCaps.greenField, + pAssocReq->HTCaps.shortGI20MHz, + pAssocReq->HTCaps.shortGI40MHz, + pAssocReq->HTCaps.txSTBC, + pAssocReq->HTCaps.rxSTBC, + pAssocReq->HTCaps.delayedBA, + pAssocReq->HTCaps.maximalAMSDUsize, + pAssocReq->HTCaps.dsssCckMode40MHz, + pAssocReq->HTCaps.psmp, + pAssocReq->HTCaps.stbcControlFrame, + pAssocReq->HTCaps.lsigTXOPProtection ); + + // Make sure the STA's caps are compatible with our own: + //11.15.2 Support of DSSS/CCK in 40 MHz + //the AP shall refuse association requests from an HT STA that has the DSSS/CCK + //Mode in 40 MHz subfield set to 1; + } + } // End if on HT caps turned on in lim. + + /* Clear the buffers so that frame parser knows that there isn't a previously decoded IE in these buffers */ + vos_mem_set((tANI_U8*)&Dot11fIERSN, sizeof( Dot11fIERSN ), 0); + vos_mem_set((tANI_U8*)&Dot11fIEWPA, sizeof( Dot11fIEWPA ), 0); + + /* if additional IE is present, check if it has WscIE */ + if( pAssocReq->addIEPresent && pAssocReq->addIE.length ) + wpsIe = limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length); + else + { + limLog(pMac, LOG1, FL("Assoc req addIEPresent = %d " + "addIE length = %d"), pAssocReq->addIEPresent, + pAssocReq->addIE.length); + } + /* when wpsIe is present, RSN/WPA IE is ignored */ + if( wpsIe == NULL ) + { + /** check whether as RSN IE is present */ + if (LIM_IS_AP_ROLE(psessionEntry) && + psessionEntry->pLimStartBssReq->privacy && + psessionEntry->pLimStartBssReq->rsnIE.length) { + limLog(pMac, LOG1, + FL("RSN enabled auth, Re/Assoc req from STA: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa)); + if(pAssocReq->rsnPresent) + { + if(pAssocReq->rsn.length) + { + // Unpack the RSN IE + dot11fUnpackIeRSN(pMac, + &pAssocReq->rsn.info[0], + pAssocReq->rsn.length, + &Dot11fIERSN); + + /* Check RSN version is supported or not */ + if(SIR_MAC_OUI_VERSION_1 == Dot11fIERSN.version) + { + /* check the groupwise and pairwise cipher suites */ + if(eSIR_SUCCESS != (status = limCheckRxRSNIeMatch(pMac, Dot11fIERSN, psessionEntry, + pAssocReq->HTCaps.present, &pmfConnection))) + { + limLog(pMac, LOGE, FL("RSN Mismatch." + "Rejecting Re/Assoc req from" + "STA: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa)); + + /* some IE is not properly sent */ + /* received Association req frame with RSN IE but length is 0 */ + limSendAssocRspMgmtFrame( + pMac, + status, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + + } + } + else + { + limLog(pMac, LOGE, FL("RSN length not correct." + "Rejecting Re/Assoc req from " + "STA: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa)); + + /* received Association req frame with RSN IE version wrong */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + goto error; + + } + } + else + { + limLog(pMac, LOGW, FL("Rejecting Re/Assoc req from STA:" + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); + /* received Association req frame with RSN IE but length is 0 */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + + } + } /* end - if(pAssocReq->rsnPresent) */ + if((!pAssocReq->rsnPresent) && pAssocReq->wpaPresent) + { + // Unpack the WPA IE + if(pAssocReq->wpa.length) + { + dot11fUnpackIeWPA(pMac, + &pAssocReq->wpa.info[4], //OUI is not taken care + pAssocReq->wpa.length, + &Dot11fIEWPA); + /* check the groupwise and pairwise cipher suites */ + if(eSIR_SUCCESS != (status = limCheckRxWPAIeMatch(pMac, Dot11fIEWPA, psessionEntry, pAssocReq->HTCaps.present))) + { + limLog(pMac, LOGW, FL("WPA IE mismatch." + "Rejecting Re/Assoc req from " + "STA: "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); + /* received Association req frame with WPA IE but mismatch */ + limSendAssocRspMgmtFrame( + pMac, + status, + 1, + pHdr->sa, + subType, 0,psessionEntry); + goto error; + + } + } + else + { + limLog(pMac, LOGW, FL("WPA len incorrect." + "Rejecting Re/Assoc req from STA: " + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); + /* received Association req frame with invalid WPA IE */ + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, + 1, + pHdr->sa, + subType, 0,psessionEntry); + + goto error; + }/* end - if(pAssocReq->wpa.length) */ + } /* end - if(pAssocReq->wpaPresent) */ + } /* end of if(psessionEntry->pLimStartBssReq->privacy + && psessionEntry->pLimStartBssReq->rsnIE->length) */ + + } /* end of if( ! pAssocReq->wscInfo.present ) */ + else + { + limLog(pMac, LOG1, FL("Assoc req WSE IE is present")); + } + + /** + * Extract 'associated' context for STA, if any. + * This is maintained by DPH and created by LIM. + */ + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &peerIdx, &psessionEntry->dph.dphHashTable); + + /// Extract pre-auth context for the STA, if any. + pStaPreAuthContext = limSearchPreAuthList(pMac, pHdr->sa); + + if (pStaDs == NULL) + { + /// Requesting STA is not currently associated + if (peGetCurrentSTAsCount(pMac) == pMac->lim.gLimAssocStaLimit) + { + /** + * Maximum number of STAs that AP can handle reached. + * Send Association response to peer MAC entity + */ + limLog(pMac, LOGE, FL("Max Sta count reached : %d"), + pMac->lim.maxStation); + limRejectAssociation(pMac, pHdr->sa, + subType, false, + (tAniAuthType) 0, 0, + false, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + goto error; + } + + /// Check if STA is pre-authenticated. + if ((pStaPreAuthContext == NULL) || + (pStaPreAuthContext && + (pStaPreAuthContext->mlmState != + eLIM_MLM_AUTHENTICATED_STATE))) + { + /** + * STA is not pre-authenticated yet requesting + * Re/Association before Authentication. + * OR STA is in the process of getting authenticated + * and sent Re/Association request. + * Send Deauthentication frame with 'prior + * authentication required' reason code. + */ + limSendDeauthMgmtFrame( + pMac, + eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON, //=9 + pHdr->sa, psessionEntry, FALSE); + + limLog(pMac, LOGE, FL("received %s req on sessionid: %d from STA " + "that does not have pre-auth context"MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", + psessionEntry->peSessionId, + MAC_ADDR_ARRAY(pHdr->sa)); + goto error; + } + + /// Delete 'pre-auth' context of STA + authType = pStaPreAuthContext->authType; + limDeletePreAuthNode(pMac, pHdr->sa); + + // All is well. Assign AID (after else part) + + } // if (pStaDs == NULL) + else + { + // STA context does exist for this STA + + if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) + { + /** + * Requesting STA is in some 'transient' state? + * Ignore the Re/Assoc Req frame by incrementing + * debug counter & logging error. + */ + if (subType == LIM_ASSOC) + { + +#ifdef WLAN_DEBUG + pMac->lim.gLimNumAssocReqDropInvldState++; +#endif + limLog(pMac, LOGE, FL("received Assoc req in state " + "%X from "), pStaDs->mlmStaContext.mlmState); + } + else + { +#ifdef WLAN_DEBUG + pMac->lim.gLimNumReassocReqDropInvldState++; +#endif + limLog(pMac, LOGE, FL("received ReAssoc req in state %X" + " from "), pStaDs->mlmStaContext.mlmState); + } + limPrintMacAddr(pMac, pHdr->sa, LOG1); + limPrintMlmState(pMac, LOG1, (tLimMlmStates) pStaDs->mlmStaContext.mlmState); + + goto error; + } // if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) + + /* STA sent association Request frame while already in + * 'associated' state */ + +#ifdef WLAN_FEATURE_11W + limLog(pMac, LOG1, FL("Re/Assoc request from station that is already associated")); + limLog(pMac, LOG1, FL("PMF enabled %d, SA Query state %d"), pStaDs->rmfEnabled, + pStaDs->pmfSaQueryState); + if (pStaDs->rmfEnabled) + { + switch (pStaDs->pmfSaQueryState) + { + + // start SA Query procedure, respond to Association Request + // with try again later + case DPH_SA_QUERY_NOT_IN_PROGRESS: + /* + * We should reset the retry counter before we start + * the SA query procedure, otherwise in next set of SA query + * procedure we will end up using the stale value. + */ + pStaDs->pmfSaQueryRetryCount = 0; + limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1, + pHdr->sa, subType, pStaDs, psessionEntry); + limSendSaQueryRequestFrame( + pMac, (tANI_U8 *)&(pStaDs->pmfSaQueryCurrentTransId), + pHdr->sa, psessionEntry); + pStaDs->pmfSaQueryStartTransId = pStaDs->pmfSaQueryCurrentTransId; + pStaDs->pmfSaQueryCurrentTransId++; + + // start timer for SA Query retry + if (tx_timer_activate(&pStaDs->pmfSaQueryTimer) != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("PMF SA Query timer activation failed!")); + goto error; + } + + pStaDs->pmfSaQueryState = DPH_SA_QUERY_IN_PROGRESS; + goto error; + + // SA Query procedure still going, respond to Association + // Request with try again later + case DPH_SA_QUERY_IN_PROGRESS: + limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1, + pHdr->sa, subType, 0, psessionEntry); + goto error; + + // SA Query procedure timed out, accept Association Request + // normally + case DPH_SA_QUERY_TIMED_OUT: + pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; + break; + } + } +#endif + + /* no change in the capability so drop the frame */ + if ((VOS_TRUE == vos_mem_compare(&pStaDs->mlmStaContext.capabilityInfo, + &pAssocReq->capabilityInfo, + sizeof(tSirMacCapabilityInfo)))&& + (subType == LIM_ASSOC)) + { + limLog(pMac, LOGE, FL(" Received Assoc req in state %X STAid=%d"), + pStaDs->mlmStaContext.mlmState,peerIdx); + goto error; + } + else + { + /** + * STA sent Re/association Request frame while already in + * 'associated' state. Update STA capabilities and + * send Association response frame with same AID + */ + limLog(pMac, LOG1, FL("Received Assoc req from STA already connected" + " UpdateConext")); + pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo; + if (pStaPreAuthContext && + (pStaPreAuthContext->mlmState == + eLIM_MLM_AUTHENTICATED_STATE)) + { + /// STA has triggered pre-auth again + authType = pStaPreAuthContext->authType; + limDeletePreAuthNode(pMac, pHdr->sa); + } + else + authType = pStaDs->mlmStaContext.authType; + + updateContext = true; + if (dphInitStaState(pMac, pHdr->sa, peerIdx, true, &psessionEntry->dph.dphHashTable) + == NULL) + { + limLog(pMac, LOGE, FL("could not Init STAid=%d"), peerIdx); + goto error; + } + } + goto sendIndToSme; + } // end if (lookup for STA in perStaDs fails) + + + + // check if sta is allowed per QoS AC rules + limGetWmeMode(psessionEntry, &wmeMode); + if ((qosMode == eHAL_SET) || (wmeMode == eHAL_SET)) + { + // for a qsta, check if the requested Traffic spec + // is admissible + // for a non-qsta check if the sta can be admitted + if (pAssocReq->addtsPresent) + { + tANI_U8 tspecIdx = 0; //index in the sch tspec table. + if (limAdmitControlAddTS(pMac, pHdr->sa, &(pAssocReq->addtsReq), + &(pAssocReq->qosCapability), 0, false, NULL, &tspecIdx, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("AdmitControl: TSPEC rejected")); + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_QAP_NO_BANDWIDTH_REASON, + 1, + pHdr->sa, + subType, 0,psessionEntry); +#ifdef WLAN_DEBUG + pMac->lim.gLimNumAssocReqDropACRejectTS++; +#endif + goto error; + } + } + else if (limAdmitControlAddSta(pMac, pHdr->sa, false) + != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("AdmitControl: Sta rejected")); + limSendAssocRspMgmtFrame( + pMac, + eSIR_MAC_QAP_NO_BANDWIDTH_REASON, + 1, + pHdr->sa, + subType, 0,psessionEntry); +#ifdef WLAN_DEBUG + pMac->lim.gLimNumAssocReqDropACRejectSta++; +#endif + goto error; + } + + // else all ok + limLog(pMac, LOG1, FL("AdmitControl: Sta OK!")); + } + + /** + * STA is Associated ! + */ + limLog(pMac, LOGE, FL("Received %s Req successful from "MAC_ADDRESS_STR), + (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", MAC_ADDR_ARRAY(pHdr->sa)); + + /** + * AID for this association will be same as the peer Index used in DPH table. + * Assign unused/least recently used peer Index from perStaDs. + * NOTE: limAssignPeerIdx() assigns AID values ranging + * between 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT) + */ + + peerIdx = limAssignPeerIdx(pMac, psessionEntry); + + if (!peerIdx) + { + // Could not assign AID + // Reject association + limLog(pMac, LOGE, FL("PeerIdx not avaialble. Reject associaton")); + limRejectAssociation(pMac, pHdr->sa, + subType, true, authType, + peerIdx, false, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + goto error; + } + + /** + * Add an entry to hash table maintained by DPH module + */ + + pStaDs = dphAddHashEntry(pMac, pHdr->sa, peerIdx, &psessionEntry->dph.dphHashTable); + + if (pStaDs == 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), + peerIdx,MAC_ADDR_ARRAY(pHdr->sa)); + + // Release AID + limReleasePeerIdx(pMac, peerIdx, psessionEntry); + + limRejectAssociation(pMac, pHdr->sa, + subType, true, authType, peerIdx, false, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + goto error; + } + + +sendIndToSme: + /* + * check here if the parsedAssocReq already + * pointing to the AssocReq and free it before + * assigning this new pAssocReq + */ + if (psessionEntry->parsedAssocReq != NULL) + { + pTempAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId]; + if (pTempAssocReq != NULL) + { + if (pTempAssocReq->assocReqFrame) + { + vos_mem_free(pTempAssocReq->assocReqFrame); + pTempAssocReq->assocReqFrame = NULL; + pTempAssocReq->assocReqFrameLength = 0; + } + vos_mem_free(pTempAssocReq); + pTempAssocReq = NULL; + } + + psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq; + assoc_req_copied = true; + } + + + pStaDs->mlmStaContext.htCapability = pAssocReq->HTCaps.present; +#ifdef WLAN_FEATURE_11AC + pStaDs->mlmStaContext.vhtCapability = pAssocReq->VHTCaps.present; +#endif + pStaDs->qos.addtsPresent = (pAssocReq->addtsPresent==0) ? false : true; + pStaDs->qos.addts = pAssocReq->addtsReq; + pStaDs->qos.capability = pAssocReq->qosCapability; + pStaDs->versionPresent = 0; + /* short slot and short preamble should be updated before doing limaddsta */ + pStaDs->shortPreambleEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortPreamble; + pStaDs->shortSlotTimeEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortSlotTime; + + pStaDs->valid = 0; + pStaDs->mlmStaContext.authType = authType; + pStaDs->staType = STA_ENTRY_PEER; + + //TODO: If listen interval is more than certain limit, reject the association. + //Need to check customer requirements and then implement. + pStaDs->mlmStaContext.listenInterval = pAssocReq->listenInterval; + pStaDs->mlmStaContext.capabilityInfo = pAssocReq->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*/ + pStaDs->timWaitCount = (tANI_U8)GET_TIM_WAIT_COUNT(pAssocReq->listenInterval); + + /** Initialise the Current successful MPDU's tranfered to this STA count as 0 */ + pStaDs->curTxMpduCnt = 0; + + if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) && + pAssocReq->HTCaps.present && pAssocReq->wmeInfoPresent) + { + pStaDs->htGreenfield = (tANI_U8)pAssocReq->HTCaps.greenField; + pStaDs->htAMpduDensity = pAssocReq->HTCaps.mpduDensity; + pStaDs->htDsssCckRate40MHzSupport = (tANI_U8)pAssocReq->HTCaps.dsssCckMode40MHz; + pStaDs->htLsigTXOPProtection = (tANI_U8)pAssocReq->HTCaps.lsigTXOPProtection; + pStaDs->htMaxAmsduLength = (tANI_U8)pAssocReq->HTCaps.maximalAMSDUsize; + pStaDs->htMaxRxAMpduFactor = pAssocReq->HTCaps.maxRxAMPDUFactor; + pStaDs->htMIMOPSState = pAssocReq->HTCaps.mimoPowerSave; + + /* pAssocReq will be copied to psessionEntry->parsedAssocReq later */ + ht_cap_ie = ((tANI_U8 *) &pAssocReq->HTCaps) + 1; + + /* check whether AP is enabled with shortGI */ + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val) != + eSIR_SUCCESS) { + PELOGE(limLog(pMac, LOGE, + FL("could not retrieve shortGI 20Mhz CFG"));) + goto error; + } + if (val) { + pStaDs->htShortGI20Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI20MHz; + } else { + /* Unset htShortGI20Mhz in ht_caps*/ + *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI20MHZ_S); + pStaDs->htShortGI20Mhz = 0; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val) != + eSIR_SUCCESS) { + PELOGE(limLog(pMac, LOGE, + FL("could not retrieve shortGI 40Mhz CFG"));) + goto error; + } + if (val) { + pStaDs->htShortGI40Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI40MHz; + } else { + /* Unset htShortGI40Mhz in ht_caps */ + *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI40MHZ_S); + pStaDs->htShortGI40Mhz = 0; + } + + pStaDs->htSupportedChannelWidthSet = (tANI_U8)pAssocReq->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 + */ + pStaDs->htSecondaryChannelOffset = (pStaDs->htSupportedChannelWidthSet)?psessionEntry->htSecondaryChannelOffset:0; +#ifdef WLAN_FEATURE_11AC + if(pAssocReq->operMode.present) + { + pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pAssocReq->operMode.chanWidth == eHT_CHANNEL_WIDTH_80MHZ) ? WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ : WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ); + pStaDs->htSupportedChannelWidthSet = (tANI_U8)(pAssocReq->operMode.chanWidth ? eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ); + } + else if (pAssocReq->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. + pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pStaDs->htSupportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) ? + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ : + psessionEntry->vhtTxChannelWidthSet ); + pStaDs->htMaxRxAMpduFactor = pAssocReq->VHTCaps.maxAMPDULenExp; + } + + // Lesser among the AP and STA bandwidth of operation. + pStaDs->htSupportedChannelWidthSet = + (pStaDs->htSupportedChannelWidthSet < psessionEntry->htSupportedChannelWidthSet) ? + pStaDs->htSupportedChannelWidthSet : psessionEntry->htSupportedChannelWidthSet ; + +#endif + pStaDs->baPolicyFlag = 0xFF; + pStaDs->htLdpcCapable = (tANI_U8)pAssocReq->HTCaps.advCodingCap; + } + + if(pAssocReq->VHTCaps.present && pAssocReq->wmeInfoPresent) + { + pStaDs->vhtLdpcCapable = (tANI_U8)pAssocReq->VHTCaps.ldpcCodingCap; + } + + if (!pAssocReq->wmeInfoPresent) { + pStaDs->mlmStaContext.htCapability = 0; +#ifdef WLAN_FEATURE_11AC + pStaDs->mlmStaContext.vhtCapability = 0; +#endif + } +#ifdef WLAN_FEATURE_11AC +if (limPopulateMatchingRateSet(pMac, + pStaDs, + &(pAssocReq->supportedRates), + &(pAssocReq->extendedRates), + pAssocReq->HTCaps.supportedMCSSet, + psessionEntry, &pAssocReq->VHTCaps) + != eSIR_SUCCESS) +#else + + if (limPopulateMatchingRateSet(pMac, + pStaDs, + &(pAssocReq->supportedRates), + &(pAssocReq->extendedRates), + pAssocReq->HTCaps.supportedMCSSet, + psessionEntry) != eSIR_SUCCESS) +#endif + { + // Could not update hash table entry at DPH with rateset + limLog(pMac, LOGE, + FL("could not update hash entry at DPH for aid=%d, MacAddr: " + MAC_ADDRESS_STR), + peerIdx, MAC_ADDR_ARRAY(pHdr->sa)); + + // Release AID + limReleasePeerIdx(pMac, peerIdx, psessionEntry); + + + limRejectAssociation(pMac, pHdr->sa, + subType, true, authType, peerIdx, true, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + if(psessionEntry->parsedAssocReq) + pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId]; + goto error; + } + +#ifdef WLAN_FEATURE_11AC + if(pAssocReq->operMode.present) + { + pStaDs->vhtSupportedRxNss = pAssocReq->operMode.rxNSS + 1; + } + else + { + pStaDs->vhtSupportedRxNss = ((pStaDs->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2) + == MCSMAPMASK2x2) ? 1 : 2; + } +#endif + + /// Add STA context at MAC HW (BMU, RHP & TFP) + + pStaDs->qosMode = eANI_BOOLEAN_FALSE; + pStaDs->lleEnabled = eANI_BOOLEAN_FALSE; + if (pAssocReq->capabilityInfo.qos && (qosMode == eHAL_SET)) + { + pStaDs->lleEnabled = eANI_BOOLEAN_TRUE; + pStaDs->qosMode = eANI_BOOLEAN_TRUE; + } + + pStaDs->wmeEnabled = eANI_BOOLEAN_FALSE; + pStaDs->wsmEnabled = eANI_BOOLEAN_FALSE; + limGetWmeMode(psessionEntry, &wmeMode); + if ((! pStaDs->lleEnabled) && pAssocReq->wmeInfoPresent && (wmeMode == eHAL_SET)) + { + pStaDs->wmeEnabled = eANI_BOOLEAN_TRUE; + pStaDs->qosMode = eANI_BOOLEAN_TRUE; + limGetWsmMode(psessionEntry, &wsmMode); + /* WMM_APSD - WMM_SA related processing should be separate; WMM_SA and WMM_APSD + can coexist */ + if( pAssocReq->WMMInfoStation.present) + { + /* check whether AP supports or not */ + if (LIM_IS_AP_ROLE(psessionEntry) + && (psessionEntry->apUapsdEnable == 0) && (pAssocReq->WMMInfoStation.acbe_uapsd + || pAssocReq->WMMInfoStation.acbk_uapsd + || pAssocReq->WMMInfoStation.acvo_uapsd + || pAssocReq->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 */ + pStaDs->qos.capability.qosInfo.acbe_uapsd = 0; + pStaDs->qos.capability.qosInfo.acbk_uapsd = 0; + pStaDs->qos.capability.qosInfo.acvo_uapsd = 0; + pStaDs->qos.capability.qosInfo.acvi_uapsd = 0; + pStaDs->qos.capability.qosInfo.maxSpLen = 0; + + } + else + { + /* update UAPSD and send it to LIM to add STA */ + pStaDs->qos.capability.qosInfo.acbe_uapsd = pAssocReq->WMMInfoStation.acbe_uapsd; + pStaDs->qos.capability.qosInfo.acbk_uapsd = pAssocReq->WMMInfoStation.acbk_uapsd; + pStaDs->qos.capability.qosInfo.acvo_uapsd = pAssocReq->WMMInfoStation.acvo_uapsd; + pStaDs->qos.capability.qosInfo.acvi_uapsd = pAssocReq->WMMInfoStation.acvi_uapsd; + pStaDs->qos.capability.qosInfo.maxSpLen = pAssocReq->WMMInfoStation.max_sp_length; + } + } + if (pAssocReq->wsmCapablePresent && (wsmMode == eHAL_SET)) + pStaDs->wsmEnabled = eANI_BOOLEAN_TRUE; + + } + + // Re/Assoc Response frame to requesting STA + pStaDs->mlmStaContext.subType = subType; + +#ifdef WLAN_FEATURE_11W + pStaDs->rmfEnabled = (pmfConnection) ? 1 : 0; + pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; + timerId.fields.sessionId = psessionEntry->peSessionId; + timerId.fields.peerIdx = peerIdx; + if (wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + &retryInterval) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("Could not retrieve PMF SA Query retry interval value")); + limRejectAssociation(pMac, pHdr->sa, + subType, true, authType, + peerIdx, false, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + goto error; + } + if (WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_APMIN > retryInterval) + { + retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_APDEF; + } + if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer", + limPmfSaQueryTimerHandler, timerId.value, + SYS_MS_TO_TICKS((retryInterval * 1024) / 1000), + 0, TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("could not create PMF SA Query timer")); + limRejectAssociation(pMac, pHdr->sa, + subType, true, authType, + peerIdx, false, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + goto error; + } +#endif + + if (pAssocReq->ExtCap.present) + { + lim_set_stads_rtt_cap(pStaDs, + (struct s_ext_cap *) pAssocReq->ExtCap.bytes); + } + else + { + pStaDs->timingMeasCap = 0; + PELOG1(limLog(pMac, LOG1, FL("ExtCap not present"));) + } + + // BTAMP: Storing the parsed assoc request in the psessionEntry array + if(psessionEntry->parsedAssocReq) + psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq; + assoc_req_copied = true; + + /* BTAMP: If STA context already exist (ie. updateContext = 1) + * for this STA, then we should delete the old one, and add + * the new STA. This is taken care of in the limDelSta() routine. + * + * Prior to BTAMP, we were setting this flag so that when + * PE receives SME_ASSOC_CNF, and if this flag is set, then + * PE shall delete the old station and then add. But now in + * BTAMP, we're directly adding station before waiting for + * SME_ASSOC_CNF, so we can do this now. + */ + if (!updateContext) + { + pStaDs->mlmStaContext.updateContext = 0; + + // BTAMP: Add STA context at HW - issue WDA_ADD_STA_REQ to HAL + if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("could not Add STA with assocId=%d"), + pStaDs->assocId); + limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, + true, pStaDs->mlmStaContext.authType, pStaDs->assocId, true, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + if(psessionEntry->parsedAssocReq) + pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId]; + goto error; + } + } + else + { + pStaDs->mlmStaContext.updateContext = 1; + + mlmPrevState = pStaDs->mlmStaContext.mlmState; + + /* As per the HAL/FW needs the reassoc req need not be calling limDelSta */ + if(subType != LIM_REASSOC) + { + //we need to set the mlmState here in order differentiate in limDelSta. + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE; + if(limDelSta(pMac, pStaDs, true, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("could not DEL STA with assocId=%d staId %d"), + pStaDs->assocId, pStaDs->staIndex); + limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + //Restoring the state back. + pStaDs->mlmStaContext.mlmState = mlmPrevState; + if(psessionEntry->parsedAssocReq) + pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId]; + goto error; + } + } + else + { + /* mlmState is changed in limAddSta context */ + /* use the same AID, already allocated */ + if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS) + { + limLog( pMac, LOGE, FL( "Could not AddSta with assocId= %d staId %d"), + pStaDs->assocId, pStaDs->staIndex); + limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_WME_REFUSED_STATUS, psessionEntry); + + //Restoring the state back. + pStaDs->mlmStaContext.mlmState = mlmPrevState; + if(psessionEntry->parsedAssocReq) + pAssocReq = + psessionEntry->parsedAssocReq[pStaDs->assocId]; + goto error; + } + + } + + } + + /* AddSta is sucess here */ + if (LIM_IS_AP_ROLE(psessionEntry) && + IS_DOT11_MODE_HT(psessionEntry->dot11mode) && + pAssocReq->HTCaps.present && pAssocReq->wmeInfoPresent) { + /** Update in the HAL Station Table for the Update of the Protection Mode */ + limPostSMStateUpdate(pMac,pStaDs->staIndex, + pStaDs->htMIMOPSState, + pStaDs->staAddr, psessionEntry->smeSessionId); + } + + return; + +error: + if (pAssocReq != NULL) { + if (pAssocReq->assocReqFrame) { + vos_mem_free(pAssocReq->assocReqFrame); + pAssocReq->assocReqFrame = NULL; + pAssocReq->assocReqFrameLength = 0; + } + vos_mem_free(pAssocReq); + if (assoc_req_copied) /* to avoid double free */ + if(psessionEntry->parsedAssocReq) + psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL; + } + + /* If it is not duplicate Assoc request then only free the memory */ + if ((pStaDs != NULL) && + (pStaDs->mlmStaContext.mlmState != eLIM_MLM_WT_ADD_STA_RSP_STATE)) { + if (psessionEntry->parsedAssocReq != NULL) { + pTempAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId]; + if (pTempAssocReq != NULL) { + if (pTempAssocReq->assocReqFrame) { + vos_mem_free(pTempAssocReq->assocReqFrame); + pTempAssocReq->assocReqFrame = NULL; + pTempAssocReq->assocReqFrameLength = 0; + } + vos_mem_free(pTempAssocReq); + psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL; + } + } + } + + return; + +} /*** end limProcessAssocReqFrame() ***/ + + + +/**--------------------------------------------------------------- +\fn limSendMlmAssocInd +\brief This function sends either LIM_MLM_ASSOC_IND +\ or LIM_MLM_REASSOC_IND to SME. +\ +\param pMac +\param *pStaDs - Station DPH hash entry +\param psessionEntry - PE session entry +\return None + + * ?????? How do I get + * - subtype =====> psessionEntry->parsedAssocReq.reassocRequest + * - aid =====> pStaDs->assocId + * - pHdr->sa =====> pStaDs->staAddr + * - authType + * - pHdr->seqControl =====> no longer needed + * - pStaDs +------------------------------------------------------------------*/ +void limSendMlmAssocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry) +{ + tpLimMlmAssocInd pMlmAssocInd = NULL; + tpLimMlmReassocInd pMlmReassocInd; + tpSirAssocReq pAssocReq; + tANI_U16 temp; + tANI_U32 phyMode; + tANI_U8 subType; + tANI_U8 *wpsIe = NULL; + tANI_U32 tmp; + tANI_U16 i, j=0; + + // Get a copy of the already parsed Assoc Request + pAssocReq = (tpSirAssocReq) psessionEntry->parsedAssocReq[pStaDs->assocId]; + + // Get the phyMode + limGetPhyMode(pMac, &phyMode, psessionEntry); + // Extract pre-auth context for the peer BTAMP-STA, if any. + + // Determiine if its Assoc or ReAssoc Request + if (pAssocReq->reassocRequest == 1) + subType = LIM_REASSOC; + else + subType = LIM_ASSOC; + + limLog(pMac, LOG1, FL("Sessionid %d ssid %s subtype %d Associd %d staAddr " + MAC_ADDRESS_STR), psessionEntry->peSessionId, pAssocReq->ssId.ssId, + subType,pStaDs->assocId,MAC_ADDR_ARRAY(pStaDs->staAddr)); + + if (subType == LIM_ASSOC || subType == LIM_REASSOC) + { + temp = sizeof(tLimMlmAssocInd); + + pMlmAssocInd = vos_mem_malloc(temp); + if (NULL == pMlmAssocInd) + { + limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry); + limLog(pMac, LOGP, FL("AllocateMemory failed for pMlmAssocInd")); + return; + } + vos_mem_set(pMlmAssocInd, temp ,0); + + vos_mem_copy((tANI_U8 *)pMlmAssocInd->peerMacAddr, + (tANI_U8 *)pStaDs->staAddr, sizeof(tSirMacAddr)); + + pMlmAssocInd->aid = pStaDs->assocId; + vos_mem_copy((tANI_U8 *)&pMlmAssocInd->ssId, + (tANI_U8 *)&(pAssocReq->ssId), pAssocReq->ssId.length + 1); + pMlmAssocInd->sessionId = psessionEntry->peSessionId; + pMlmAssocInd->authType = pStaDs->mlmStaContext.authType; + + pMlmAssocInd->capabilityInfo = pAssocReq->capabilityInfo; + + // Fill in RSN IE information + pMlmAssocInd->rsnIE.length = 0; + // if WPS IE is present, ignore RSN IE + if (pAssocReq->addIEPresent && pAssocReq->addIE.length ) { + wpsIe = limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length); + } + if (pAssocReq->rsnPresent && (NULL == wpsIe)) + { + limLog(pMac, LOG2, FL("Assoc Req RSN IE len = %d"), + pAssocReq->rsn.length); + pMlmAssocInd->rsnIE.length = 2 + pAssocReq->rsn.length; + pMlmAssocInd->rsnIE.rsnIEdata[0] = SIR_MAC_RSN_EID; + pMlmAssocInd->rsnIE.rsnIEdata[1] = pAssocReq->rsn.length; + vos_mem_copy(&pMlmAssocInd->rsnIE.rsnIEdata[2], + pAssocReq->rsn.info, + pAssocReq->rsn.length); + } + + // Fill in 802.11h related info + if (pAssocReq->powerCapabilityPresent && pAssocReq->supportedChannelsPresent) + { + pMlmAssocInd->spectrumMgtIndicator = eSIR_TRUE; + pMlmAssocInd->powerCap.minTxPower = pAssocReq->powerCapability.minTxPower; + pMlmAssocInd->powerCap.maxTxPower = pAssocReq->powerCapability.maxTxPower; + limConvertSupportedChannels(pMac, pMlmAssocInd, pAssocReq); + } + else + pMlmAssocInd->spectrumMgtIndicator = eSIR_FALSE; + + + /* This check is to avoid extra Sec IEs present incase of WPS */ + if (pAssocReq->wpaPresent && (NULL == wpsIe)) + { + if((pMlmAssocInd->rsnIE.length + pAssocReq->wpa.length) >= SIR_MAC_MAX_IE_LENGTH) + { + PELOGE(limLog(pMac, LOGE, FL("rsnIEdata index out of bounds %d"), + pMlmAssocInd->rsnIE.length);) + vos_mem_free(pMlmAssocInd); + return; + } + pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length] = SIR_MAC_WPA_EID; + pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length + 1] = pAssocReq->wpa.length; + vos_mem_copy(&pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length + 2], + pAssocReq->wpa.info, + pAssocReq->wpa.length); + pMlmAssocInd->rsnIE.length += 2 + pAssocReq->wpa.length; + } + +#ifdef FEATURE_WLAN_WAPI + /* This check is to avoid extra Sec IEs present incase of WPS */ + if (pAssocReq->wapiPresent && (NULL == wpsIe)) + { + limLog(pMac, LOG2, FL("Received WAPI IE length in Assoc Req is %d"), + pAssocReq->wapi.length); + pMlmAssocInd->wapiIE.wapiIEdata[0] = SIR_MAC_WAPI_EID; + pMlmAssocInd->wapiIE.wapiIEdata[1] = pAssocReq->wapi.length; + vos_mem_copy(&pMlmAssocInd->wapiIE.wapiIEdata[2], + pAssocReq->wapi.info, + pAssocReq->wapi.length); + pMlmAssocInd->wapiIE.length = 2 + pAssocReq->wapi.length; + } +#endif + + pMlmAssocInd->addIE.length = 0; + if (pAssocReq->addIEPresent) + { + vos_mem_copy(&pMlmAssocInd->addIE.addIEdata, + pAssocReq->addIE.addIEdata, + pAssocReq->addIE.length); + + pMlmAssocInd->addIE.length = pAssocReq->addIE.length; + } + + /* Add HT Capabilities into addIE for OBSS processing in hostapd */ + if (pAssocReq->HTCaps.present) + { + if (pMlmAssocInd->addIE.length + DOT11F_IE_HTCAPS_MIN_LEN + 2 < + SIR_MAC_MAX_IE_LENGTH) + { + pMlmAssocInd->addIE.addIEdata[pMlmAssocInd->addIE.length] = + SIR_MAC_HT_CAPABILITIES_EID; + pMlmAssocInd->addIE.addIEdata[pMlmAssocInd->addIE.length + 1] = + DOT11F_IE_HTCAPS_MIN_LEN; + vos_mem_copy( + &pMlmAssocInd->addIE.addIEdata[pMlmAssocInd->addIE.length + 2], + ((tANI_U8*)&pAssocReq->HTCaps)+1, + DOT11F_IE_HTCAPS_MIN_LEN); + pMlmAssocInd->addIE.length += 2 + DOT11F_IE_HTCAPS_MIN_LEN; + } + else + limLog(pMac, LOGP, FL("Cannot add HT capabilities IE to addIE")); + } + + if (pAssocReq->wmeInfoPresent) + { + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WME_ENABLED, &tmp) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("wlan_cfgGetInt failed for id %d"), + WNI_CFG_WME_ENABLED ); + + /* check whether AP is enabled with WMM */ + if(tmp) + { + pMlmAssocInd->WmmStaInfoPresent = 1; + } + else + { + pMlmAssocInd->WmmStaInfoPresent= 0; + } + /* Note: we are not rejecting association here because IOT will fail */ + + } + + // Required for indicating the frames to upper layer + pMlmAssocInd->assocReqLength = pAssocReq->assocReqFrameLength; + pMlmAssocInd->assocReqPtr = pAssocReq->assocReqFrame; + + pMlmAssocInd->beaconPtr = psessionEntry->beacon; + pMlmAssocInd->beaconLength = psessionEntry->bcnLen; + + pMlmAssocInd->chan_info.chan_id = psessionEntry->currentOperChannel; + + pMlmAssocInd->chan_info.mhz = vos_chan_to_freq( + psessionEntry->currentOperChannel); + + pMlmAssocInd->chan_info.band_center_freq1 = vos_chan_to_freq( + psessionEntry->currentOperChannel); + + pMlmAssocInd->chan_info.band_center_freq2 = 0; + + pMlmAssocInd->chan_info.reg_info_1 = (psessionEntry->maxTxPower << 16); + pMlmAssocInd->chan_info.reg_info_2 = (psessionEntry->maxTxPower << 8); + + if (psessionEntry->limRFBand == SIR_BAND_2_4_GHZ) { + if (psessionEntry->vhtCapability && pAssocReq->VHTCaps.present) { + pMlmAssocInd->chan_info.info = MODE_11AC_VHT20_2G; + } else if (psessionEntry->htCapability && + pAssocReq->HTCaps.present) { + pMlmAssocInd->chan_info.info = MODE_11NG_HT20; + } else { + pMlmAssocInd->chan_info.info = MODE_11G; + } + } else { + if (psessionEntry->vhtCapability && pAssocReq->VHTCaps.present) { + if ((psessionEntry->vhtTxChannelWidthSet == + eHT_CHANNEL_WIDTH_80MHZ) && + pAssocReq->HTCaps.supportedChannelWidthSet) { + pMlmAssocInd->chan_info.band_center_freq1 = + vos_chan_to_freq(psessionEntry->apCenterChan); + pMlmAssocInd->chan_info.info = MODE_11AC_VHT80; + } else if ((psessionEntry->vhtTxChannelWidthSet == + eHT_CHANNEL_WIDTH_40MHZ) && + pAssocReq->HTCaps.supportedChannelWidthSet) { + pMlmAssocInd->chan_info.info = MODE_11AC_VHT40; + if (psessionEntry->htSecondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + pMlmAssocInd->chan_info.band_center_freq1 += 10; + } else { + pMlmAssocInd->chan_info.band_center_freq1 -= 10; + } + } else + pMlmAssocInd->chan_info.info = MODE_11AC_VHT20; + } else if (psessionEntry->htCapability && + pAssocReq->HTCaps.present) { + if ((psessionEntry->vhtTxChannelWidthSet == + eHT_CHANNEL_WIDTH_40MHZ) && + pAssocReq->HTCaps.supportedChannelWidthSet) { + pMlmAssocInd->chan_info.info = MODE_11NA_HT40; + if (psessionEntry->htSecondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + pMlmAssocInd->chan_info.band_center_freq1 += 10; + } else { + pMlmAssocInd->chan_info.band_center_freq1 -= 10; + } + } else + pMlmAssocInd->chan_info.info = MODE_11NA_HT20; + } else + pMlmAssocInd->chan_info.info = MODE_11A; + } + pMlmAssocInd->chan_info.nss = pStaDs->nss; + pMlmAssocInd->chan_info.rate_flags = + lim_get_max_rate_flags(pMac, pStaDs); + + limPostSmeMessage(pMac, LIM_MLM_ASSOC_IND, (tANI_U32 *) pMlmAssocInd); + vos_mem_free(pMlmAssocInd); + } + else + { + // If its of Reassociation Request, then post LIM_MLM_REASSOC_IND + temp = sizeof(tLimMlmReassocInd); + + pMlmReassocInd = vos_mem_malloc(temp); + if (NULL == pMlmReassocInd) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for " + "pMlmReassocInd")); + limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry); + return; + } + vos_mem_set(pMlmReassocInd, temp, 0); + + vos_mem_copy((tANI_U8 *) pMlmReassocInd->peerMacAddr, + (tANI_U8 *)pStaDs->staAddr, sizeof(tSirMacAddr)); + vos_mem_copy((tANI_U8 *) pMlmReassocInd->currentApAddr, + (tANI_U8 *)&(pAssocReq->currentApAddr), sizeof(tSirMacAddr)); + pMlmReassocInd->aid = pStaDs->assocId; + pMlmReassocInd->authType = pStaDs->mlmStaContext.authType; + vos_mem_copy((tANI_U8 *)&pMlmReassocInd->ssId, + (tANI_U8 *)&(pAssocReq->ssId), pAssocReq->ssId.length + 1); + + pMlmReassocInd->capabilityInfo = pAssocReq->capabilityInfo; + pMlmReassocInd->rsnIE.length = 0; + + if (pAssocReq->addIEPresent && pAssocReq->addIE.length ) + wpsIe = limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length); + + if (pAssocReq->rsnPresent && (NULL == wpsIe)) + { + limLog(pMac, LOG2, FL("Assoc Req: RSN IE length = %d"), + pAssocReq->rsn.length); + pMlmReassocInd->rsnIE.length = 2 + pAssocReq->rsn.length; + pMlmReassocInd->rsnIE.rsnIEdata[0] = SIR_MAC_RSN_EID; + pMlmReassocInd->rsnIE.rsnIEdata[1] = pAssocReq->rsn.length; + vos_mem_copy(&pMlmReassocInd->rsnIE.rsnIEdata[2], + pAssocReq->rsn.info, pAssocReq->rsn.length); + } + + // 802.11h support + if (pAssocReq->powerCapabilityPresent && pAssocReq->supportedChannelsPresent) + { + pMlmReassocInd->spectrumMgtIndicator = eSIR_TRUE; + pMlmReassocInd->powerCap.minTxPower = pAssocReq->powerCapability.minTxPower; + pMlmReassocInd->powerCap.maxTxPower = pAssocReq->powerCapability.maxTxPower; + pMlmReassocInd->supportedChannels.numChnl = (tANI_U8)(pAssocReq->supportedChannels.length / 2); + + limLog(pMac, LOG1, + FL("Sending Reassoc Ind: spectrum ON, minPwr %d, " + "maxPwr %d, numChnl %d"), + pMlmReassocInd->powerCap.minTxPower, + pMlmReassocInd->powerCap.maxTxPower, + pMlmReassocInd->supportedChannels.numChnl); + + for(i=0; i < pMlmReassocInd->supportedChannels.numChnl; i++) + { + pMlmReassocInd->supportedChannels.channelList[i] = pAssocReq->supportedChannels.supportedChannels[j]; + limLog(pMac, LOG1, FL("Sending ReassocInd: chn[%d] = %d "), + i, pMlmReassocInd->supportedChannels.channelList[i]); + j+=2; + } + } + else + pMlmReassocInd->spectrumMgtIndicator = eSIR_FALSE; + + + /* This check is to avoid extra Sec IEs present incase of WPS */ + if (pAssocReq->wpaPresent && (NULL == wpsIe)) + { + limLog(pMac, LOG2, FL("Received WPA IE length in Assoc Req is %d"), + pAssocReq->wpa.length); + pMlmReassocInd->rsnIE.rsnIEdata[pMlmReassocInd->rsnIE.length] = SIR_MAC_WPA_EID; + pMlmReassocInd->rsnIE.rsnIEdata[pMlmReassocInd->rsnIE.length + 1] = pAssocReq->wpa.length; + vos_mem_copy(&pMlmReassocInd->rsnIE.rsnIEdata[pMlmReassocInd->rsnIE.length + 2], + pAssocReq->wpa.info, + pAssocReq->wpa.length); + pMlmReassocInd->rsnIE.length += 2 + pAssocReq->wpa.length; + } + +#ifdef FEATURE_WLAN_WAPI + /* This check is to avoid extra Sec IEs present incase of WPS */ + if (pAssocReq->wapiPresent && (NULL == wpsIe)) + { + limLog(pMac, LOG2, FL("Received WAPI IE length in Assoc Req is %d"), + pAssocReq->wapi.length); + pMlmReassocInd->wapiIE.wapiIEdata[0] = SIR_MAC_WAPI_EID; + pMlmReassocInd->wapiIE.wapiIEdata[1] = pAssocReq->wapi.length; + vos_mem_copy(&pMlmReassocInd->wapiIE.wapiIEdata[2], + pAssocReq->wapi.info, + pAssocReq->wapi.length); + pMlmReassocInd->wapiIE.length = 2 + pAssocReq->wapi.length; + } +#endif + + pMlmReassocInd->addIE.length = 0; + if (pAssocReq->addIEPresent) + { + vos_mem_copy(&pMlmReassocInd->addIE.addIEdata, + pAssocReq->addIE.addIEdata, + pAssocReq->addIE.length); + + pMlmReassocInd->addIE.length = pAssocReq->addIE.length; + } + + if(pAssocReq->wmeInfoPresent) + { + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WME_ENABLED, &tmp) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("wlan_cfgGetInt failed for id %d"), + WNI_CFG_WME_ENABLED ); + + /* check whether AP is enabled with WMM */ + if(tmp) + { + pMlmReassocInd->WmmStaInfoPresent = 1; + } + else + { + pMlmReassocInd->WmmStaInfoPresent = 0; + } + /* Note: we are not rejecting Re-association here because IOT will fail */ + + } + + // Required for indicating the frames to upper layer + pMlmReassocInd->assocReqLength = pAssocReq->assocReqFrameLength; + pMlmReassocInd->assocReqPtr = pAssocReq->assocReqFrame; + + pMlmReassocInd->beaconPtr = psessionEntry->beacon; + pMlmReassocInd->beaconLength = psessionEntry->bcnLen; + + limPostSmeMessage(pMac, LIM_MLM_REASSOC_IND, (tANI_U32 *) pMlmReassocInd); + vos_mem_free(pMlmReassocInd); + } + + return; + +} /*** end limSendMlmAssocInd() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c new file mode 100644 index 000000000000..12324b1166de --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limProcessAssocRspFrame.cc contains the code + * for processing Re/Association Response Frame. + * Author: Chandra Modumudi + * Date: 03/18/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wniApi.h" +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "cfgApi.h" + +#include "utilsApi.h" +#include "pmmApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limStaHashApi.h" +#include "limSendMessages.h" + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseApi.h" +#endif + +extern tSirRetStatus schBeaconEdcaProcess(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry); + + +/** + * @function : limUpdateAssocStaDatas + * + * @brief : This function is called to Update the Station Descriptor (dph) Details from + * Association / ReAssociation Response Frame + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Station Descriptor in DPH + * @param pAssocRsp - Pointer to Association Response Structure + * + * @return None + */ +void limUpdateAssocStaDatas(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpSirAssocRsp pAssocRsp,tpPESession psessionEntry) +{ + tANI_U32 phyMode; + tANI_BOOLEAN qosMode; + tANI_U16 rxHighestRate = 0; + uint32_t shortgi_20mhz_support; + uint32_t shortgi_40mhz_support; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + pStaDs->staType= STA_ENTRY_SELF; + + limGetQosMode(psessionEntry, &qosMode); + + pStaDs->mlmStaContext.authType = psessionEntry->limCurrentAuthType; + + // Add capabilities information, rates and AID + pStaDs->mlmStaContext.capabilityInfo = pAssocRsp->capabilityInfo; + pStaDs->shortPreambleEnabled= (tANI_U8)pAssocRsp->capabilityInfo.shortPreamble; + + //Update HT Capabilites only when the self mode supports HT + if(IS_DOT11_MODE_HT(psessionEntry->dot11mode)) { + pStaDs->mlmStaContext.htCapability = pAssocRsp->HTCaps.present; + + if ( pAssocRsp->HTCaps.present ) { + pStaDs->htGreenfield = ( tANI_U8 ) pAssocRsp->HTCaps.greenField; + if (psessionEntry->htSupportedChannelWidthSet) { + pStaDs->htSupportedChannelWidthSet = + (tANI_U8)(pAssocRsp->HTCaps.supportedChannelWidthSet ? + pAssocRsp->HTInfo.recommendedTxWidthSet : + pAssocRsp->HTCaps.supportedChannelWidthSet); + } + else + pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ; + + pStaDs->htLsigTXOPProtection = ( tANI_U8 ) pAssocRsp->HTCaps.lsigTXOPProtection; + pStaDs->htMIMOPSState = (tSirMacHTMIMOPowerSaveState)pAssocRsp->HTCaps.mimoPowerSave; + pStaDs->htMaxAmsduLength = ( tANI_U8 ) pAssocRsp->HTCaps.maximalAMSDUsize; + pStaDs->htAMpduDensity = pAssocRsp->HTCaps.mpduDensity; + pStaDs->htDsssCckRate40MHzSupport = (tANI_U8)pAssocRsp->HTCaps.dsssCckMode40MHz; + pStaDs->htMaxRxAMpduFactor = pAssocRsp->HTCaps.maxRxAMPDUFactor; + limFillRxHighestSupportedRate(pMac, &rxHighestRate, pAssocRsp->HTCaps.supportedMCSSet); + pStaDs->supportedRates.rxHighestDataRate = rxHighestRate; + /* This is for AP as peer STA and we are INFRA STA. We will put APs offset in dph node which is peer STA */ + pStaDs->htSecondaryChannelOffset = (tANI_U8)pAssocRsp->HTInfo.secondaryChannelOffset; + + //FIXME_AMPDU + // In the future, may need to check for "assoc.HTCaps.delayedBA" + // For now, it is IMMEDIATE BA only on ALL TID's + pStaDs->baPolicyFlag = 0xFF; + + /* + * Check if we have support for gShortGI20Mhz and + * gShortGI40Mhz from ini file. + */ + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, + WNI_CFG_SHORT_GI_20MHZ, + &shortgi_20mhz_support))) { + if (VOS_TRUE == shortgi_20mhz_support) + pStaDs->htShortGI20Mhz = + (tANI_U8)pAssocRsp->HTCaps.shortGI20MHz; + else + pStaDs->htShortGI20Mhz = VOS_FALSE; + } else { + limLog(pMac, LOGE, + FL("could not retrieve shortGI 20Mhz CFG, setting value to default")); + pStaDs->htShortGI20Mhz = WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, + WNI_CFG_SHORT_GI_40MHZ, + &shortgi_40mhz_support))) { + if (VOS_TRUE == shortgi_40mhz_support) + pStaDs->htShortGI40Mhz = + (tANI_U8)pAssocRsp->HTCaps.shortGI40MHz; + else + pStaDs->htShortGI40Mhz = VOS_FALSE; + } else { + limLog(pMac, LOGE, + FL("could not retrieve shortGI 40Mhz CFG,setting value to default")); + pStaDs->htShortGI40Mhz = WNI_CFG_SHORT_GI_40MHZ_STADEF; + } + } + } + +#ifdef WLAN_FEATURE_11AC + if(IS_DOT11_MODE_VHT(psessionEntry->dot11mode)) + { + pStaDs->mlmStaContext.vhtCapability = pAssocRsp->VHTCaps.present; + if (pAssocRsp->VHTCaps.present && + psessionEntry->htSupportedChannelWidthSet) + pStaDs->vhtSupportedChannelWidthSet = + pAssocRsp->VHTOperation.chanWidth; + } + + // If 11ac is supported and if the peer is sending VHT capabilities, + // then htMaxRxAMpduFactor should be overloaded with VHT maxAMPDULenExp + if (pAssocRsp->VHTCaps.present) + { + pStaDs->htMaxRxAMpduFactor = pAssocRsp->VHTCaps.maxAMPDULenExp; + } + + if (limPopulatePeerRateSet(pMac, &pStaDs->supportedRates, + pAssocRsp->HTCaps.supportedMCSSet, + false,psessionEntry , &pAssocRsp->VHTCaps) != eSIR_SUCCESS) +#else + if (limPopulatePeerRateSet(pMac, &pStaDs->supportedRates, pAssocRsp->HTCaps.supportedMCSSet, false,psessionEntry) != eSIR_SUCCESS) +#endif + { + limLog(pMac, LOGP, FL("could not get rateset and extended rate set")); + return; + } + +#ifdef WLAN_FEATURE_11AC + pStaDs->vhtSupportedRxNss = ((pStaDs->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2) + == MCSMAPMASK2x2) ? 1 : 2; +#endif + //If one of the rates is 11g rates, set the ERP mode. + if ((phyMode == WNI_CFG_PHY_MODE_11G) && sirIsArate(pStaDs->supportedRates.llaRates[0] & 0x7f)) + pStaDs->erpEnabled = eHAL_SET; + + + pStaDs->qosMode = 0; + pStaDs->lleEnabled = 0; + + // update TSID to UP mapping + if (qosMode) { + if (pAssocRsp->edcaPresent) { + tSirRetStatus status; + status = schBeaconEdcaProcess(pMac,&pAssocRsp->edca, psessionEntry); + PELOG2(limLog(pMac, LOG2, "Edca set update based on AssocRsp: status %d", + status);) + if (status != eSIR_SUCCESS) { + PELOGE(limLog(pMac, LOGE, FL("Edca error in AssocResp "));) + } else { // update default tidmap based on ACM + pStaDs->qosMode = 1; + pStaDs->lleEnabled = 1; + } + } + } + + pStaDs->wmeEnabled = 0; + pStaDs->wsmEnabled = 0; + if (psessionEntry->limWmeEnabled && pAssocRsp->wmeEdcaPresent) + { + tSirRetStatus status; + status = schBeaconEdcaProcess(pMac,&pAssocRsp->edca, psessionEntry); + PELOGW(limLog(pMac, LOGW, "WME Edca set update based on AssocRsp: status %d", status);) + + if (status != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("WME Edca error in AssocResp - ignoring"));) + else { // update default tidmap based on HashACM + pStaDs->qosMode = 1; + pStaDs->wmeEnabled = 1; + } + } + else { + /* We received assoc rsp from a legacy AP. So fill in the default + * local EDCA params. This is needed (refer to bug #14989) as we'll + * be passing the gLimEdcaParams to HAL in limProcessStaMlmAddBssRsp(). + */ + schSetDefaultEdcaParams(pMac, psessionEntry); + } + + if(qosMode && (!pStaDs->qosMode) && pStaDs->mlmStaContext.htCapability) + { + // Enable QOS for all HT AP's even though WMM or 802.11E IE is not present + pStaDs->qosMode = 1; + pStaDs->wmeEnabled = 1; + } + +#ifdef WLAN_FEATURE_11W + if(psessionEntry->limRmfEnabled) + { + pStaDs->rmfEnabled = 1; + } +#endif +} + +/** + * @function : limUpdateReAssocGlobals + * + * @brief : This function is called to Update the Globals (LIM) during ReAssoc. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pAssocRsp - Pointer to Association Response Structure + * + * @return None + */ + +void limUpdateReAssocGlobals(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp,tpPESession psessionEntry) +{ + /** + * Update the status for PMM module + */ + pmmResetPmmState(pMac); + + // Update the current Bss Information + vos_mem_copy(psessionEntry->bssId, + psessionEntry->limReAssocbssId, sizeof(tSirMacAddr)); + psessionEntry->currentOperChannel = psessionEntry->limReassocChannelId; + psessionEntry->htSecondaryChannelOffset = psessionEntry->reAssocHtSupportedChannelWidthSet; + psessionEntry->htRecommendedTxWidthSet = psessionEntry->reAssocHtRecommendedTxWidthSet; + psessionEntry->htSecondaryChannelOffset = psessionEntry->reAssocHtSecondaryChannelOffset; + psessionEntry->limCurrentBssCaps = psessionEntry->limReassocBssCaps; + psessionEntry->limCurrentBssQosCaps = psessionEntry->limReassocBssQosCaps; + psessionEntry->limCurrentBssPropCap = psessionEntry->limReassocBssPropCap; + + vos_mem_copy((tANI_U8 *) &psessionEntry->ssId, + (tANI_U8 *) &psessionEntry->limReassocSSID, + psessionEntry->limReassocSSID.length+1); + + // Store assigned AID for TIM processing + psessionEntry->limAID = pAssocRsp->aid & 0x3FFF; + /** Set the State Back to ReAssoc Rsp*/ + psessionEntry->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + +} + +/** + * @function : limProcessAssocRspFrame + * + * @brief : This function is called by limProcessMessageQueue() upon + * Re/Association Response frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to Rx packet info structure + * @param subType - Indicates whether it is Association Response (=0) or + * Reassociation Response (=1) frame + * + * @return None + */ + +void +limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 subType,tpPESession psessionEntry) +{ + tANI_U8 *pBody; + tANI_U16 caps; + tANI_U32 frameLen; + tSirMacAddr currentBssId; + tpSirMacMgmtHdr pHdr = NULL; + tSirMacCapabilityInfo localCapabilities; + tpDphHashNode pStaDs; + tpSirAssocRsp pAssocRsp; + tLimMlmAssocCnf mlmAssocCnf; + tSchBeaconStruct *pBeaconStruct; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U8 smeSessionId = 0; +#endif + + //Initialize status code to success. +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) + pHdr = (tpSirMacMgmtHdr)pMac->roam.pReassocResp; + else +#endif + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + smeSessionId = psessionEntry->smeSessionId; +#endif + + mlmAssocCnf.resultCode = eSIR_SME_SUCCESS; + /* Update PE session Id*/ + mlmAssocCnf.sessionId = psessionEntry->peSessionId; + if (pHdr == NULL) { + limLog(pMac, LOGE, + FL("LFR3: Reassoc response packet header is NULL")); + return; + } else if ( pHdr->sa == NULL) { + limLog(pMac, LOGE, + FL("LFR3: Reassoc response packet source address is NULL")); + return; + } + + limLog(pMac, LOG1, + FL("received Re/Assoc(%d) resp on sessionid: %d with systemrole: %d " + "and mlmstate: %d RSSI %d from "MAC_ADDRESS_STR),subType, + psessionEntry->peSessionId, + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo)), + MAC_ADDR_ARRAY(pHdr->sa)); + + pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) + { + limLog(pMac, LOGE, FL("Unable to allocate memory") ); + return; + } + + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + // Should not have received Re/Association Response + // frame on AP. Log error + limLog(pMac, LOGE, + FL("Should not recieved Re/Assoc Response in role %d"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + vos_mem_free(pBeaconStruct); + return; + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) + { + pHdr = (tpSirMacMgmtHdr)pMac->roam.pReassocResp; + frameLen = pMac->roam.reassocRespLen - SIR_MAC_HDR_LEN_3A; + } + else + { +#endif + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } +#endif + if (((subType == LIM_ASSOC) && + (psessionEntry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) || + ((subType == LIM_REASSOC) && + ((psessionEntry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + && (psessionEntry->limMlmState != eLIM_MLM_WT_FT_REASSOC_RSP_STATE) +#endif + ))) + { + /// Received unexpected Re/Association Response frame + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog(pMac, LOG1, FL("Recieved Re/Assoc rsp in unexpected " + "state %d on session=%d"), + psessionEntry->limMlmState, psessionEntry->peSessionId);) +#endif + // Log error + if (!pHdr->fc.retry) { + if (!(pMac->lim.retry_packet_cnt & 0xf)) { + limLog(pMac, LOGE, + FL("received Re/Assoc rsp frame is not a retry frame")); + limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); + } else { + pMac->lim.retry_packet_cnt++; + } + } + vos_mem_free(pBeaconStruct); + return; + } + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + if (subType == LIM_ASSOC) + { + if (!vos_mem_compare(pHdr->sa, currentBssId, sizeof(tSirMacAddr))) + { + /** + * Received Association Response frame from an entity + * other than one to which request was initiated. + * Ignore this and wait until Association Failure Timeout. + */ + + // Log error + PELOGW(limLog(pMac, LOGW, + FL("received AssocRsp frame from unexpected peer "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) + vos_mem_free(pBeaconStruct); + return; + } + } + else + { + if (!vos_mem_compare(pHdr->sa, psessionEntry->limReAssocbssId, sizeof(tSirMacAddr))) + { + /** + * Received Reassociation Response frame from an entity + * other than one to which request was initiated. + * Ignore this and wait until Reassociation Failure Timeout. + */ + + // Log error + PELOGW(limLog(pMac, LOGW, + FL("received ReassocRsp frame from unexpected peer "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) + vos_mem_free(pBeaconStruct); + + return; + } + } + + pAssocRsp = vos_mem_malloc(sizeof(*pAssocRsp)); + if (NULL == pAssocRsp) + { + limLog(pMac, LOGP, FL("Allocate Memory failed in AssocRsp")); + vos_mem_free(pBeaconStruct); + + return; + } + + // Get pointer to Re/Association Response frame body +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) + pBody = pMac->roam.pReassocResp + SIR_MAC_HDR_LEN_3A; + else +#endif + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + // parse Re/Association Response frame. + if (sirConvertAssocRespFrame2Struct( + pMac, pBody, frameLen, pAssocRsp) == eSIR_FAILURE) + { + vos_mem_free(pAssocRsp); + PELOGE(limLog(pMac, LOGE, FL("Parse error Assoc resp subtype %d," + "length=%d"), frameLen,subType);) + vos_mem_free(pBeaconStruct); + + return; + } + + if(!pAssocRsp->suppRatesPresent) + { + PELOGE(limLog(pMac, LOGE, FL("assoc response does not have supported rate set"));) + vos_mem_copy(&pAssocRsp->supportedRates, + &psessionEntry->rateSet, sizeof(tSirMacRateSet)); + } + + mlmAssocCnf.protStatusCode = pAssocRsp->statusCode; + + if( psessionEntry->assocRsp != NULL ) + { + limLog(pMac, LOGW, FL("psessionEntry->assocRsp is not NULL freeing it " + "and setting NULL")); + vos_mem_free(psessionEntry->assocRsp); + 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; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (psessionEntry->ricData != NULL) + { + vos_mem_free(psessionEntry->ricData); + psessionEntry->ricData = NULL; + } + if(pAssocRsp->ricPresent) { + psessionEntry->RICDataLen = + pAssocRsp->num_RICData * sizeof(tDot11fIERICDataDesc); + if (psessionEntry->RICDataLen) { + psessionEntry->ricData = vos_mem_malloc(psessionEntry->RICDataLen); + if (NULL == psessionEntry->ricData) { + limLog(pMac, LOGE, FL("Unable to alloc mem for RIC data")); + psessionEntry->RICDataLen = 0; + } else { + vos_mem_copy(psessionEntry->ricData, + &pAssocRsp->RICData[0], psessionEntry->RICDataLen); + } + } else { + limLog(pMac, LOGE, FL("RIC Data not present")); + } + } else { + limLog(pMac, LOG1, FL("RIC is not present")); + psessionEntry->RICDataLen = 0; + psessionEntry->ricData = NULL; + } +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pAssocRsp->FTInfo.R0KH_ID.present) + { + pMac->roam.roamSession[smeSessionId].ftSmeContext.r0kh_id_len = + pAssocRsp->FTInfo.R0KH_ID.num_PMK_R0_ID; + vos_mem_copy(pMac->roam.roamSession[smeSessionId].ftSmeContext.r0kh_id, + pAssocRsp->FTInfo.R0KH_ID.PMK_R0_ID, + pMac->roam.roamSession[smeSessionId].ftSmeContext.r0kh_id_len); + } + else + { + pMac->roam.roamSession[smeSessionId].ftSmeContext.r0kh_id_len = 0; + vos_mem_zero(pMac->roam.roamSession[smeSessionId].ftSmeContext.r0kh_id, + SIR_ROAM_R0KH_ID_MAX_LEN); + } +#endif + +#ifdef FEATURE_WLAN_ESE + if (psessionEntry->tspecIes != NULL) + { + vos_mem_free(psessionEntry->tspecIes); + psessionEntry->tspecIes = NULL; + } + if(pAssocRsp->tspecPresent) { + limLog(pMac, LOG1, FL("Tspec EID present in assoc rsp")); + psessionEntry->tspecLen = pAssocRsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC); + if (psessionEntry->tspecLen) { + psessionEntry->tspecIes = vos_mem_malloc(psessionEntry->tspecLen); + if (NULL == psessionEntry->tspecIes) { + limLog(pMac, LOGE, FL("Unable to alloc mem for TSPEC")); + psessionEntry->tspecLen = 0; + } else { + vos_mem_copy(psessionEntry->tspecIes, + &pAssocRsp->TSPECInfo[0], psessionEntry->tspecLen); + } + } else { + limLog(pMac, LOGE, FL("TSPEC has Zero length")); + } + } else { + psessionEntry->tspecLen = 0; + psessionEntry->tspecIes = NULL; + limLog(pMac, LOG1, FL("Tspec EID *NOT* present in assoc rsp")); + } +#endif + + if (pAssocRsp->capabilityInfo.ibss) + { + /** + * Received Re/Association Response from peer + * with IBSS capability set. + * Ignore the frame and wait until Re/assoc + * failure timeout. + */ + + // Log error + limLog(pMac, LOGE, + FL("received Re/AssocRsp frame with IBSS capability")); + vos_mem_free(pAssocRsp); + vos_mem_free(pBeaconStruct); + + return; + } + + if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) + { + /** + * Could not get Capabilities value + * from CFG. Log error. + */ + vos_mem_free(pAssocRsp); + vos_mem_free(pBeaconStruct); + + limLog(pMac, LOGP, FL("could not retrieve Capabilities value")); + return; + } + limCopyU16((tANI_U8 *) &localCapabilities, caps); + + if (subType == LIM_ASSOC) // Stop Association failure timer + limDeactivateAndChangeTimer(pMac, eLIM_ASSOC_FAIL_TIMER); + else // Stop Reassociation failure timer + { +#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)) + { + vos_mem_free(pMac->lim.pSessionEntry->pLimMlmReassocRetryReq); + pMac->lim.pSessionEntry->pLimMlmReassocRetryReq = NULL; + } +#endif + limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_FAIL_TIMER); + } + + if (pAssocRsp->statusCode != eSIR_MAC_SUCCESS_STATUS +#ifdef WLAN_FEATURE_11W + && (!psessionEntry->limRmfEnabled || + pAssocRsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER) +#endif /* WLAN_FEATURE_11W */ + ) + { + // Re/Association response was received + // either with failure code. + // Log error. + PELOGE(limLog(pMac, LOGE, FL("received Re/AssocRsp frame failure code %d"), pAssocRsp->statusCode);) + // Need to update 'association failure' error counter + // along with STATUS CODE + + // Return Assoc confirm to SME with received failure code + mlmAssocCnf.resultCode = eSIR_SME_ASSOC_REFUSED; + + // Delete Pre-auth context for the associated BSS + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); + + goto assocReject; + } + else if ((pAssocRsp->aid & 0x3FFF) > 2007) + { + // Re/Association response was received + // with invalid AID value + // Log error + PELOGW(limLog(pMac, LOGE, FL("received Re/AssocRsp frame with" + "invalid aid %X"), pAssocRsp->aid);) + mlmAssocCnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + // Send advisory Disassociation frame to AP + limSendDisassocMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON, + pHdr->sa, psessionEntry, FALSE); + + goto assocReject; + } + // Association Response received with success code + /* + * Set the link state to POSTASSOC now that we have received + * assoc/reassoc response + * NOTE: for BTAMP case, it is being handled in limProcessMlmAssocReq + */ + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled && + pAssocRsp->statusCode == eSIR_MAC_TRY_AGAIN_LATER) { + /* fetch timer value from IE */ + if (pAssocRsp->TimeoutInterval.present && + (pAssocRsp->TimeoutInterval.timeoutType == + SIR_MAC_TI_TYPE_ASSOC_COMEBACK) ) { + tANI_U16 timeout_value = pAssocRsp->TimeoutInterval.timeoutValue; + if (timeout_value < 10) { + /* + * if this value is less than 10 then our timer will fail to + * start and due to this we will never re-attempt. Better + * modify the timer value here. + */ + timeout_value = 10; + } + PELOGE(limLog(pMac, LOG1, + FL("ASSOC response with eSIR_MAC_TRY_AGAIN_LATER recvd. " + "Starting timer to wait timeout=%d."), + timeout_value);) + + /* start timer with callback */ + if (VOS_STATUS_SUCCESS != + vos_timer_start(&psessionEntry->pmfComebackTimer, + timeout_value)) { + PELOGE(limLog(pMac, LOGE, + FL("Failed to start comeback timer."));) + } + } else { + PELOGE(limLog(pMac, LOG1, + FL("ASSOC response with eSIR_MAC_TRY_AGAIN_LATER recvd." + "But try again time interval IE is wrong."));) + } + /* callback will send Assoc again */ + /* DO NOT send ASSOC CNF to MLM state machine */ + vos_mem_free(pBeaconStruct); + vos_mem_free(pAssocRsp); + return; + } +#endif /* WLAN_FEATURE_11W */ + + if (!((psessionEntry->bssType == eSIR_BTAMP_STA_MODE) || + ((psessionEntry->bssType == eSIR_BTAMP_AP_MODE) && + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)))) { + 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) + { + // Log success + PELOG1(limLog(pMac, LOG1, FL("Successfully Reassociated with BSS"));) +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT, + psessionEntry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif +#ifdef FEATURE_WLAN_ESE + { + tANI_U8 cnt = 0; + if (pAssocRsp->tsmPresent) + { + limLog(pMac, LOGW, "TSM IE Present in Reassoc Rsp"); + // Start the TSM timer only if the TSPEC Ie is present in the reassoc rsp + if (pAssocRsp->tspecPresent) { + // Find the TSPEC IE with VO user priority + for (cnt=0; cntnum_tspecs; cnt++) { + if ( upToAc(pAssocRsp->TSPECInfo[cnt].user_priority) == EDCA_AC_VO) { + psessionEntry->eseContext.tsm.tid = pAssocRsp->TSPECInfo[cnt].user_priority; + vos_mem_copy(&psessionEntry->eseContext.tsm.tsmInfo, + &pAssocRsp->tsmIE, sizeof(tSirMacESETSMIE)); +#ifdef FEATURE_WLAN_ESE_UPLOAD + limSendSmeTsmIEInd(pMac, + psessionEntry, + pAssocRsp->tsmIE.tsid, + pAssocRsp->tsmIE.state, + pAssocRsp->tsmIE.msmt_interval); +#else + limActivateTSMStatsTimer(pMac, psessionEntry); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + if(psessionEntry->eseContext.tsm.tsmInfo.state) { + psessionEntry->eseContext.tsm.tsmMetrics.RoamingCount++; + } + break; + } + } + } else { + limLog(pMac, LOGE, "TSM present but TSPEC IE not present in Reassoc Rsp"); + } + } + } +#endif + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + psessionEntry->limAssocResponseData = (void *) pAssocRsp; /** Store the ReAssocRsp Frame in DphTable to be used + during processing DelSta nd DelBss to send AddBss again*/ + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + + if(!pStaDs) + { + PELOGE(limLog(pMac, LOGE, FL("could not get hash entry at DPH for"));) + limPrintMacAddr(pMac, pHdr->sa, LOGE); + mlmAssocCnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + // Send advisory Disassociation frame to AP + limSendDisassocMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON, + pHdr->sa, psessionEntry, FALSE); + + goto assocReject; + } + +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE) + { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOG1, FL("Sending self sta"));) +#endif + pmmResetPmmState(pMac); + + limUpdateAssocStaDatas(pMac, pStaDs, pAssocRsp,psessionEntry); + + // Store assigned AID for TIM processing + psessionEntry->limAID = pAssocRsp->aid & 0x3FFF; + + // Downgrade the EDCA parameters if needed + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + + // Send the active EDCA parameters to HAL +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (!psessionEntry->bRoamSynchInProgress) + { +#endif + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } +#endif + limAddFTStaSelf(pMac, (pAssocRsp->aid & 0x3FFF), psessionEntry); + vos_mem_free(pBeaconStruct); + + return; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + /* If we're re-associating to the same BSS, we don't want to invoke delete + * STA, delete BSS, as that would remove the already established TSPEC. + * Just go ahead and re-add the BSS, STA with new capability information. + * However, if we're re-associating to a different BSS, then follow thru + * with del STA, del BSS, add BSS, add STA. + */ + if (sirCompareMacAddr( psessionEntry->bssId, psessionEntry->limReAssocbssId)) + limHandleAddBssInReAssocContext(pMac, pStaDs, psessionEntry); + else + { + if(!pMac->psOffloadEnabled) + { + /* + * reset the uapsd mask settings + * since we're re-associating to new AP + */ + pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; + pMac->lim.gUapsdPerAcTriggerEnableMask = 0; + } + else + { + /* + * reset the uapsd mask settings since + * we're re-associating to new AP + */ + psessionEntry->gUapsdPerAcDeliveryEnableMask = 0; + psessionEntry->gUapsdPerAcTriggerEnableMask = 0; + } + + if (limCleanupRxPath(pMac, pStaDs,psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Could not cleanup the rx path"));) + goto assocReject; + } + } + vos_mem_free(pBeaconStruct); + + return; + } + + // Log success + PELOG1(limLog(pMac, LOG1, FL("Successfully Associated with BSS "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) +#ifdef FEATURE_WLAN_ESE + if(psessionEntry->eseContext.tsm.tsmInfo.state) + { + psessionEntry->eseContext.tsm.tsmMetrics.RoamingCount = 0; + } +#endif + /** + * Update the status for PMM module + */ + pmmResetPmmState(pMac); + + // Store assigned AID for TIM processing + psessionEntry->limAID = pAssocRsp->aid & 0x3FFF; + + + //STA entry was created during pre-assoc state. + if ((pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) + { + // Could not add hash table entry + PELOGE(limLog(pMac, LOGE, FL("could not get hash entry at DPH for "));) + limPrintMacAddr(pMac, pHdr->sa, LOGE); + + mlmAssocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmAssocCnf.protStatusCode = eSIR_SME_SUCCESS; + + + limPostSmeMessage(pMac, LIM_MLM_ASSOC_CNF, + (tANI_U32 *) &mlmAssocCnf); + vos_mem_free(pAssocRsp); + vos_mem_free(pBeaconStruct); + + return; + } + + // Delete Pre-auth context for the associated BSS + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); + + limUpdateAssocStaDatas(pMac, pStaDs, pAssocRsp,psessionEntry); + // Extract the AP capabilities from the beacon that was received earlier + // TODO - Watch out for an error response! + limExtractApCapabilities( pMac, + (tANI_U8 *) psessionEntry->pLimJoinReq->bssDescription.ieFields, + limGetIElenFromBssDescription( &psessionEntry->pLimJoinReq->bssDescription ), + pBeaconStruct ); + + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, psessionEntry); + + if(pBeaconStruct->erpPresent) { + if (pBeaconStruct->erpIEInfo.barkerPreambleMode) + psessionEntry->beaconParams.fShortPreamble = false; + else + psessionEntry->beaconParams.fShortPreamble = true; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_CONNECTED, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + if( pAssocRsp->QosMapSet.present ) + { + vos_mem_copy(&psessionEntry->QosMapSet, + &pAssocRsp->QosMapSet, + sizeof(tSirQosMapSet)); + } + else + { + vos_mem_zero(&psessionEntry->QosMapSet, sizeof(tSirQosMapSet)); + } + + if (pAssocRsp->ExtCap.present) + { + struct s_ext_cap *ext_cap = (struct s_ext_cap *) + pAssocRsp->ExtCap.bytes; + + lim_set_stads_rtt_cap(pStaDs, ext_cap); +#ifdef FEATURE_WLAN_TDLS + psessionEntry->tdls_prohibited = + ext_cap->TDLSProhibited; + psessionEntry->tdls_chan_swit_prohibited = + ext_cap->TDLSChanSwitProhibited; + + PELOG1(limLog(pMac, LOG1, + FL("ExtCap: tdls_prohibited: %d, tdls_chan_swit_prohibited: %d"), + ext_cap->TDLSProhibited, + ext_cap->TDLSChanSwitProhibited);) +#endif + } + else + { + pStaDs->timingMeasCap = 0; +#ifdef FEATURE_WLAN_TDLS + psessionEntry->tdls_prohibited = false; + psessionEntry->tdls_chan_swit_prohibited = false; +#endif + PELOG1(limLog(pMac, LOG1, FL("ExtCap not present"));) + } + + //Update the BSS Entry, this entry was added during preassoc. + if( eSIR_SUCCESS == limStaSendAddBss( pMac, pAssocRsp, pBeaconStruct, + &psessionEntry->pLimJoinReq->bssDescription, true, psessionEntry)) + { + vos_mem_free(pAssocRsp); + vos_mem_free(pBeaconStruct); + return; + } + else + { + PELOGE(limLog(pMac, LOGE, FL("could not update the bss entry"));) + mlmAssocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + } + + + +assocReject: + if ((subType == LIM_ASSOC) +#ifdef WLAN_FEATURE_VOWIFI_11R + || ((subType == LIM_REASSOC) && (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE)) +#endif + ) { + PELOGE(limLog(pMac, LOGE, FL("Assoc Rejected by the peer. " + "mlmestate: %d sessionid %d Reason: %d MACADDR:" + MAC_ADDRESS_STR), psessionEntry->limMlmState, + psessionEntry->peSessionId, mlmAssocCnf.resultCode, + MAC_ADDR_ARRAY(pHdr->sa));) + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + if (subType == LIM_ASSOC) + { + limPostSmeMessage(pMac, LIM_MLM_ASSOC_CNF, (tANI_U32 *) &mlmAssocCnf); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + else + { + mlmAssocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmAssocCnf); + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + } else { + limRestorePreReassocState( pMac, + eSIR_SME_REASSOC_REFUSED, mlmAssocCnf.protStatusCode,psessionEntry); + } + + /* CR: vos packet memory is leaked when assoc rsp timeouted/failed. */ + /* notify TL that association is failed so that TL can flush the cached frame */ + PELOG1(limLog(pMac, LOG1, FL("notify TL that association is failed"));) + WLANTL_AssocFailed (psessionEntry->staId); + + vos_mem_free(pBeaconStruct); + vos_mem_free(pAssocRsp); + return; +} /*** end limProcessAssocRspFrame() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c new file mode 100644 index 000000000000..7c91ee381d16 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c @@ -0,0 +1,1929 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limProcessAuthFrame.cc contains the code + * for processing received Authentication Frame. + * Author: Chandra Modumudi + * Date: 03/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * 05/12/2010 js To support Shared key authentication at AP side + * + */ + +#include "wniApi.h" +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "cfgApi.h" + +#include "utilsApi.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFT.h" +#endif +#include "vos_utils.h" + + +/** + * isAuthValid + * + *FUNCTION: + * This function is called by limProcessAuthFrame() upon Authentication + * frame reception. + * + *LOGIC: + * This function is used to test validity of auth frame: + * - AUTH1 and AUTH3 must be received in AP mode + * - AUTH2 and AUTH4 must be received in STA mode + * - AUTH3 and AUTH4 must have challenge text IE, that is,'type' field has been set to + * SIR_MAC_CHALLENGE_TEXT_EID by parser + * - + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param *auth - Pointer to extracted auth frame body + * + * @return 0 or 1 (Valid) + */ + + +static inline unsigned int +isAuthValid(tpAniSirGlobal pMac, tpSirMacAuthFrameBody auth, + tpPESession sessionEntry) +{ + unsigned int valid = 1; + + if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_1) || + (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_3)) && + (LIM_IS_STA_ROLE(sessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(sessionEntry))) + valid = 0; + + if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_2) || + (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4)) && + (LIM_IS_AP_ROLE(sessionEntry) || LIM_IS_BT_AMP_AP_ROLE(sessionEntry))) + valid = 0; + + if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_3) || + (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4)) && + (auth->type != SIR_MAC_CHALLENGE_TEXT_EID) && + (auth->authAlgoNumber != eSIR_SHARED_KEY)) + valid = 0; + + return valid; +} + + +/** + * limProcessAuthFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon Authentication + * frame reception. + * + *LOGIC: + * This function processes received Authentication frame and responds + * with either next Authentication frame in sequence to peer MAC entity + * or LIM_MLM_AUTH_IND on AP or LIM_MLM_AUTH_CNF on STA. + * + *ASSUMPTIONS: + * + *NOTE: + * 1. Authentication failures are reported to SME with same status code + * received from the peer MAC entity. + * 2. Authentication frame2/4 received with alogirthm number other than + * one requested in frame1/3 are logged with an error and auth confirm + * will be sent to SME only after auth failure timeout. + * 3. Inconsistency in the spec: + * On receiving Auth frame2, specs says that if WEP key mapping key + * or default key is NULL, Auth frame3 with a status code 15 (challenge + * failure to be returned to peer entity. However, section 7.2.3.10, + * table 14 says that status code field is 'reserved' for frame3 ! + * In the current implementation, Auth frame3 is returned with status + * code 15 overriding section 7.2.3.10. + * 4. If number pre-authentications reach configrable max limit, + * Authentication frame with 'unspecified failure' status code is + * returned to requesting entity. + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to Rx packet info structure + * @return None + */ + +void +limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +{ + tANI_U8 *pBody, keyId, cfgPrivacyOptImp, + defaultKey[SIR_MAC_KEY_LENGTH], + encrAuthFrame[LIM_ENCR_AUTH_BODY_LEN], + plainBody[256]; + tANI_U16 frameLen; + tANI_U32 maxNumPreAuth, val; + tSirMacAuthFrameBody *pRxAuthFrameBody, rxAuthFrame, authFrame; + tpSirMacMgmtHdr pHdr; + tCfgWepKeyEntry *pKeyMapEntry = NULL; + struct tLimPreAuthNode *pAuthNode; + tLimMlmAuthInd mlmAuthInd; + tANI_U8 decryptResult; + tANI_U8 *pChallenge; + tANI_U32 key_length=8; + tANI_U8 challengeTextArray[SIR_MAC_AUTH_CHALLENGE_LENGTH]; + tpDphHashNode pStaDs = NULL; + tANI_U16 assocId = 0; + tANI_U16 currSeqNum = 0; + + // Get pointer to Authentication frame header and body + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + + if (!frameLen) + { + // Log error + limLog(pMac, LOGE, + FL("received Authentication frame with no body from ")); + limPrintMacAddr(pMac, pHdr->sa, LOGE); + + return; + } + + if (limIsGroupAddr(pHdr->sa)) + { + // Received Auth frame from a BC/MC address + // Log error and ignore it + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame from a BC/MC address - "));) + PELOGE( limPrintMacAddr(pMac, pHdr->sa, LOGE);) + + return; + } + currSeqNum = (pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo); + limLog(pMac, LOG1, + FL("Sessionid: %d System role : %d limMlmState: %d :Auth " + "Frame Received: BSSID: "MAC_ADDRESS_STR " (RSSI %d)"), + psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), + psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo))); + + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + //Restore default failure timeout + if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona && psessionEntry->defaultAuthFailureTimeout) + { + limLog(pMac, LOG1, FL("Restore default failure timeout")); + ccmCfgSetInt(pMac,WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT , + psessionEntry->defaultAuthFailureTimeout, NULL, eANI_BOOLEAN_FALSE); + } + + /// Determine if WEP bit is set in the FC or received MAC header + if (pHdr->fc.wep) + { + /** + * WEP bit is set in FC of MAC header. + */ + + // If TKIP counter measures enabled issue Deauth frame to station + if ((psessionEntry->bTkipCntrMeasActive) && + LIM_IS_AP_ROLE(psessionEntry)) { + PELOGE( limLog(pMac, LOGE, + FL("Tkip counter measures Enabled, sending Deauth frame to")); ) + limPrintMacAddr(pMac, pHdr->sa, LOGE); + + limSendDeauthMgmtFrame( pMac, eSIR_MAC_MIC_FAILURE_REASON, + pHdr->sa, psessionEntry, FALSE ); + return; + } + + // Extract key ID from IV (most 2 bits of 4th byte of IV) + + keyId = (*(pBody + 3)) >> 6; + + /** + * On STA in infrastructure BSS, Authentication frames received + * with WEP bit set in the FC must be rejected with challenge + * failure status code (wierd thing in the spec - this should have + * been rejected with unspecified failure or unexpected assertion + * of wep bit (this status code does not exist though) or + * Out-of-sequence-Authentication-Frame status code. + */ + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = eSIR_MAC_CHALLENGE_FAILURE_STATUS; + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame with wep bit set on role=%d" + MAC_ADDRESS_STR), GET_LIM_SYSTEM_ROLE(psessionEntry), + MAC_ADDR_ARRAY(pHdr->sa));) + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + + if (frameLen < LIM_ENCR_AUTH_BODY_LEN) + { + // Log error + limLog(pMac, LOGE, + FL("Not enough size [%d] to decrypt received Auth frame"), + frameLen); + limPrintMacAddr(pMac, pHdr->sa, LOGE); + + return; + } + if (LIM_IS_AP_ROLE(psessionEntry)) { + val = psessionEntry->privacy; + } + else + // Accept Authentication frame only if Privacy is implemented + if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &val) != eSIR_SUCCESS) + { + /** + * Could not get Privacy option + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve Privacy option")); + } + + cfgPrivacyOptImp = (tANI_U8)val; + if (cfgPrivacyOptImp) + { + /** + * Privacy option is implemented. + * Check if the received frame is Authentication + * frame3 and there is a context for requesting STA. + * If not, reject with unspecified failure status code + */ + pAuthNode = limSearchPreAuthList(pMac, pHdr->sa); + + if (pAuthNode == NULL) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame from peer that has no preauth context with WEP bit set " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * No 'pre-auth' context exists for this STA that sent + * an Authentication frame with FC bit set. + * Send Auth frame4 with 'out of sequence' status code. + */ + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + else + { + /// Change the auth-response timeout + limDeactivateAndChangePerStaIdTimer(pMac, + eLIM_AUTH_RSP_TIMER, + pAuthNode->authNodeIdx); + + /// 'Pre-auth' status exists for STA + if ((pAuthNode->mlmState != + eLIM_MLM_WT_AUTH_FRAME3_STATE) && + (pAuthNode->mlmState != + eLIM_MLM_AUTH_RSP_TIMEOUT_STATE)) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame from peer that is in state %d " + MAC_ADDRESS_STR), + pAuthNode->mlmState, MAC_ADDR_ARRAY(pHdr->sa));) + /** + * Should not have received Authentication frame + * with WEP bit set in FC in other states. + * Reject by sending Authenticaton frame with + * out of sequence Auth frame status code. + */ + + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + } + + /** + * Check if there exists a key mappping key + * for the STA that sent Authentication frame + */ + pKeyMapEntry = limLookUpKeyMappings(pHdr->sa); + + if (pKeyMapEntry) + { + if (!pKeyMapEntry->wepOn) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame3 from peer that has NULL key map entry " + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));) + /** + * Key Mapping entry has null key. + * Send Authentication frame + * with challenge failure status code + */ + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } // if (!pKeyMapEntry->wepOn) + else + { + decryptResult = limDecryptAuthFrame(pMac, pKeyMapEntry->key, + pBody, + plainBody, + key_length, + (tANI_U16) (frameLen-SIR_MAC_WEP_IV_LENGTH)); + if (decryptResult == LIM_DECRYPT_ICV_FAIL) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame from peer that failed decryption, Addr " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + + limDeletePreAuthNode(pMac, + pHdr->sa); + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + + return; + } + + if ((sirConvertAuthFrame2Struct(pMac, plainBody, frameLen-8, + &rxAuthFrame)!=eSIR_SUCCESS ) || + ( !isAuthValid(pMac, &rxAuthFrame,psessionEntry))) + { + PELOGE(limLog(pMac, LOGE, FL( + "failed to convert Auth Frame to structure or Auth is not valid "));) + return; + } + } // end if (pKeyMapEntry->key == NULL) + } // if keyMappings has entry + else + { + + val = SIR_MAC_KEY_LENGTH; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + tpSirKeys pKey; + pKey = &psessionEntry->WEPKeyMaterial[keyId].key[0]; + vos_mem_copy(defaultKey, pKey->key, pKey->keyLength); + val = pKey->keyLength; + } else if (wlan_cfgGetStr(pMac, + (tANI_U16) (WNI_CFG_WEP_DEFAULT_KEY_1 + keyId), + defaultKey, &val) != eSIR_SUCCESS) { + /// Could not get Default key from CFG. + //Log error. + limLog(pMac, LOGP, + FL("could not retrieve Default key")); + + /** + * Send Authentication frame + * with challenge failure status code + */ + + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + return; + } + + key_length=val; + + decryptResult = limDecryptAuthFrame(pMac, defaultKey, + pBody, + plainBody, + key_length, + (tANI_U16) (frameLen-SIR_MAC_WEP_IV_LENGTH)); + if (decryptResult == LIM_DECRYPT_ICV_FAIL) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame from peer that failed decryption: " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + /// ICV failure + limDeletePreAuthNode(pMac, + pHdr->sa); + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + if ( ( sirConvertAuthFrame2Struct(pMac, plainBody, frameLen-8, + &rxAuthFrame)!=eSIR_SUCCESS ) || + ( !isAuthValid(pMac, &rxAuthFrame, psessionEntry) ) ) + { + limLog(pMac, LOGE, + FL("failed to convert Auth Frame to structure or Auth is not valid ")); + return; + } + } // End of check for Key Mapping/Default key presence + } + else + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame3 from peer that while privacy option is turned OFF " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + /** + * Privacy option is not implemented. + * So reject Authentication frame received with + * WEP bit set by sending Authentication frame + * with 'challenge failure' status code. This is + * another strange thing in the spec. Status code + * should have been 'unsupported algorithm' status code. + */ + + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } // else if (wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED)) + } // if (fc.wep) + else + { + if ( ( sirConvertAuthFrame2Struct(pMac, pBody, + frameLen, &rxAuthFrame)!=eSIR_SUCCESS ) || + ( !isAuthValid(pMac, &rxAuthFrame,psessionEntry) ) ) + { + PELOGE(limLog(pMac, LOGE, + FL("failed to convert Auth Frame to structure or Auth is not valid "));) + return; + } + } + + + pRxAuthFrameBody = &rxAuthFrame; + + PELOGW(limLog(pMac, LOGW, + FL("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"), + (tANI_U32) pRxAuthFrameBody->authAlgoNumber, + (tANI_U32) pRxAuthFrameBody->authTransactionSeqNumber, + (tANI_U32) pRxAuthFrameBody->authStatusCode,(tANI_U32)pMac->lim.gLimNumPreAuthContexts);) + + switch (pRxAuthFrameBody->authTransactionSeqNumber) + { + case SIR_MAC_AUTH_FRAME_1: + // AuthFrame 1 + + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, + &assocId, &psessionEntry->dph.dphHashTable); + if (pStaDs) + { + tLimMlmDisassocReq *pMlmDisassocReq = NULL; + tLimMlmDeauthReq *pMlmDeauthReq = NULL; + tAniBool isConnected = eSIR_TRUE; + + pMlmDisassocReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + if (pMlmDisassocReq && + (vos_mem_compare((tANI_U8 *) pHdr->sa, + (tANI_U8 *) &pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)))) + { + PELOGE(limLog(pMac, LOGE, FL("TODO:Ack for disassoc " + "frame is pending Issue delsta for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDisassocReq->peerMacAddr));) + limProcessDisassocAckTimeout(pMac); + isConnected = eSIR_FALSE; + } + pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (pMlmDeauthReq && + (vos_mem_compare((tANI_U8 *) pHdr->sa, + (tANI_U8 *) &pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)))) + { + PELOGE(limLog(pMac, LOGE, FL("TODO:Ack for deauth frame " + "is pending Issue delsta for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr));) + limProcessDeauthAckTimeout(pMac); + isConnected = eSIR_FALSE; + } + + /* pStaDS != NULL and isConnected = 1 means the STA is already + * connected, But SAP received the Auth from that station. + * For non PMF connection send Deauth frame as STA will retry + * to connect back. + * + * For PMF connection the AP should not tear down or otherwise + * modify the state of the existing association until the + * SA-Query procedure determines that the original SA is + * invalid. + */ + if (isConnected +#ifdef WLAN_FEATURE_11W + && !pStaDs->rmfEnabled +#endif + ) + { + limLog(pMac, LOGE, + FL("STA is already connected but received auth frame" + "Send the Deauth and lim Delete Station Context" + "(staId: %d, assocId: %d) "), + pStaDs->staIndex, assocId); + limSendDeauthMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON, + (tANI_U8 *) pHdr->sa, psessionEntry, FALSE); + limTriggerSTAdeletion(pMac, pStaDs, psessionEntry); + return; + } + } + + /// Check if there exists pre-auth context for this STA + pAuthNode = limSearchPreAuthList(pMac, pHdr->sa); + if (pAuthNode) + { + /// Pre-auth context exists for the STA + if (pHdr->fc.retry == 0 || pAuthNode->seqNum != currSeqNum) + { + /** + * STA is initiating brand-new Authentication + * sequence after local Auth Response timeout. + * Or STA retrying to transmit First Auth frame due to packet drop OTA + * Delete Pre-auth node and fall through. + */ + if(pAuthNode->fTimerStarted) + { + limDeactivateAndChangePerStaIdTimer(pMac, + eLIM_AUTH_RSP_TIMER, + pAuthNode->authNodeIdx); + } + PELOGE(limLog(pMac, LOGE, FL("STA is initiating brand-new Authentication ..."));) + limDeletePreAuthNode(pMac, + pHdr->sa); + /** + * SAP Mode:Disassociate the station and + * delete its entry if we have its entry + * already and received "auth" from the + * same station. + */ + + for (assocId = 0; assocId < psessionEntry->dph.dphHashTable.size; assocId++)// Softap dphHashTable.size = 8 + { + pStaDs = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); + + if (NULL == pStaDs) + continue; + + if (pStaDs->valid) + { + if (vos_mem_compare((tANI_U8 *) &pStaDs->staAddr, + (tANI_U8 *) &(pHdr->sa), (tANI_U8) (sizeof(tSirMacAddr))) ) + break; + } + + pStaDs = NULL; + } + + if (NULL != pStaDs +#ifdef WLAN_FEATURE_11W + && !pStaDs->rmfEnabled +#endif + ) + { + PELOGE(limLog(pMac, LOGE, + FL("lim Delete Station Context (staId: %d, assocId: %d) "), + pStaDs->staIndex, assocId);) + limSendDeauthMgmtFrame(pMac, + eSIR_MAC_UNSPEC_FAILURE_REASON, (tANI_U8 *) pAuthNode->peerMacAddr, psessionEntry, FALSE); + limTriggerSTAdeletion(pMac, pStaDs, psessionEntry); + return; + } + } + else + { + /* + * This can happen when first authentication frame is received + * but ACK lost at STA side, in this case 2nd auth frame is already + * in transmission queue + * */ + PELOGE(limLog(pMac, LOGE, FL("STA is initiating Authentication after ACK lost..."));) + return; + } + } + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_NUM_PRE_AUTH, + (tANI_U32 *) &maxNumPreAuth) != eSIR_SUCCESS) + { + /** + * Could not get MaxNumPreAuth + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve MaxNumPreAuth")); + } + if (pMac->lim.gLimNumPreAuthContexts == maxNumPreAuth && + !limDeleteOpenAuthPreAuthNode(pMac)) + { + PELOGE(limLog(pMac, LOGE, FL("Max number of preauth context reached"));) + /** + * Maximum number of pre-auth contexts + * reached. Send Authentication frame + * with unspecified failure + */ + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + return; + } + /// No Pre-auth context exists for the STA. + if (limIsAuthAlgoSupported( + pMac, + (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber, psessionEntry)) + { + switch (pRxAuthFrameBody->authAlgoNumber) + { + case eSIR_OPEN_SYSTEM: + PELOGW(limLog(pMac, LOGW, FL("=======> eSIR_OPEN_SYSTEM ..."));) + /// Create entry for this STA in pre-auth list + pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); + if (pAuthNode == NULL) + { + // Log error + limLog(pMac, LOGW, + FL("Max pre-auth nodes reached ")); + limPrintMacAddr(pMac, pHdr->sa, LOGW); + + return; + } + + PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %x peer "), pAuthNode); + limPrintMacAddr(pMac, pHdr->sa, LOG1);) + + vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, + pHdr->sa, + sizeof(tSirMacAddr)); + + pAuthNode->mlmState = + eLIM_MLM_AUTHENTICATED_STATE; + pAuthNode->authType = (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber; + pAuthNode->fSeen = 0; + pAuthNode->fTimerStarted = 0; + pAuthNode->seqNum = ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = vos_timer_get_system_ticks(); + limAddPreAuthNode(pMac, pAuthNode); + + /** + * Send Authenticaton frame with Success + * status code. + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = eSIR_MAC_SUCCESS_STATUS; + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + /// Send Auth indication to SME + + vos_mem_copy((tANI_U8 *) mlmAuthInd.peerMacAddr, + (tANI_U8 *) pHdr->sa, + sizeof(tSirMacAddr)); + mlmAuthInd.authType = (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber; + mlmAuthInd.sessionId = psessionEntry->smeSessionId; + + limPostSmeMessage(pMac, + LIM_MLM_AUTH_IND, + (tANI_U32 *) &mlmAuthInd); + break; + + case eSIR_SHARED_KEY: + PELOGW(limLog(pMac, LOGW, FL("=======> eSIR_SHARED_KEY ..."));) + if (LIM_IS_AP_ROLE(psessionEntry)) { + val = psessionEntry->privacy; + } else if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &val) != eSIR_SUCCESS) { + /** + * Could not get Privacy option + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Privacy option")); + } + cfgPrivacyOptImp = (tANI_U8)val; + if (!cfgPrivacyOptImp) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame for unsupported auth algorithm %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * Authenticator does not have WEP + * implemented. + * Reject by sending Authentication frame + * with Auth algorithm not supported status + * code. + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + else + { + // Create entry for this STA + //in pre-auth list + pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); + if (pAuthNode == NULL) + { + // Log error + limLog(pMac, LOGW, + FL("Max pre-auth nodes reached ")); + limPrintMacAddr(pMac, pHdr->sa, LOGW); + + return; + } + + vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, + pHdr->sa, + sizeof(tSirMacAddr)); + + pAuthNode->mlmState = + eLIM_MLM_WT_AUTH_FRAME3_STATE; + pAuthNode->authType = + (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber; + pAuthNode->fSeen = 0; + pAuthNode->fTimerStarted = 0; + pAuthNode->seqNum = + ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = vos_timer_get_system_ticks(); + limAddPreAuthNode(pMac, pAuthNode); + + PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %x id %d peer "), + pAuthNode, pAuthNode->authNodeIdx);) + PELOG1(limPrintMacAddr(pMac, pHdr->sa, LOG1);) + + /// Create and activate Auth Response timer + if (tx_timer_change_context(&pAuthNode->timer, pAuthNode->authNodeIdx) != TX_SUCCESS) + { + /// Could not start Auth response timer. + // Log error + limLog(pMac, LOGP, + FL("Unable to chg context auth response timer for peer ")); + limPrintMacAddr(pMac, pHdr->sa, LOGP); + + /** + * Send Authenticaton frame with + * unspecified failure status code. + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + limDeletePreAuthNode(pMac, pHdr->sa); + return; + } + + limActivateAuthRspTimer(pMac, pAuthNode); + + pAuthNode->fTimerStarted = 1; + + // get random bytes and use as + // challenge text. If it fails we already have random stack bytes. + if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( 0, (tANI_U8 *)challengeTextArray, SIR_MAC_AUTH_CHALLENGE_LENGTH ) ) ) + { + limLog(pMac, LOGE,FL("Challenge text preparation failed in limProcessAuthFrame")); + } + + pChallenge = pAuthNode->challengeText; + + vos_mem_copy(pChallenge, + (tANI_U8 *) challengeTextArray, + sizeof(challengeTextArray)); + + /** + * Sending Authenticaton frame with challenge. + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_SUCCESS_STATUS; + authFrame.type = SIR_MAC_CHALLENGE_TEXT_EID; + authFrame.length = SIR_MAC_AUTH_CHALLENGE_LENGTH; + vos_mem_copy(authFrame.challengeText, + pAuthNode->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH); + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + } // if (wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED)) + + break; + + default: + // Log error + PELOGE( limLog(pMac, LOGE, + FL("received Auth frame for unsupported auth algorithm %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * Responding party does not support the + * authentication algorithm requested by + * sending party. + * Reject by sending Authentication frame + * with auth algorithm not supported status code + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } // end switch(pRxAuthFrameBody->authAlgoNumber) + } // if (limIsAuthAlgoSupported(pRxAuthFrameBody->authAlgoNumber)) + else + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame for unsupported auth algorithm %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * Responding party does not support the + * authentication algorithm requested by sending party. + * Reject Authentication with StatusCode=13. + */ + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } //end if (limIsAuthAlgoSupported(pRxAuthFrameBody->authAlgoNumber)) + break; + + case SIR_MAC_AUTH_FRAME_2: + // AuthFrame 2 + + if (psessionEntry->limMlmState != eLIM_MLM_WT_AUTH_FRAME2_STATE) + { +#ifdef WLAN_FEATURE_VOWIFI_11R + /** + * Check if a Reassociation is in progress and this is a + * Pre-Auth frame + */ + if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) && + (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) && + (psessionEntry->ftPEContext.pFTPreAuthReq != NULL) && + (vos_mem_compare( + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + pHdr->sa, sizeof(tSirMacAddr)))) + { + // Update the FTIEs in the saved auth response + PELOGW(limLog(pMac, LOGW, FL("received another PreAuth frame2" + " from peer " MAC_ADDRESS_STR" in Smestate %d"), + MAC_ADDR_ARRAY(pHdr->sa), psessionEntry->limSmeState);) + + psessionEntry->ftPEContext.saved_auth_rsp_length = 0; + if ((pBody != NULL) && (frameLen < MAX_FTIE_SIZE)) + { + vos_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp, + pBody, frameLen); + psessionEntry->ftPEContext.saved_auth_rsp_length = frameLen; + } + } + else +#endif + { + /** + * Received Authentication frame2 in an unexpected state. + * Log error and ignore the frame. + */ + + // Log error + PELOG1(limLog(pMac, LOG1, + FL("received Auth frame2 from peer in state %d, addr "), + psessionEntry->limMlmState);) + PELOG1(limPrintMacAddr(pMac, pHdr->sa, LOG1);) + } + + return; + + } + + if ( !vos_mem_compare((tANI_U8 *) pHdr->sa, + (tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)) ) + { + /** + * Received Authentication frame from an entity + * other than one request was initiated. + * Wait until Authentication Failure Timeout. + */ + + // Log error + PELOGW(limLog(pMac, LOGW, + FL("received Auth frame2 from unexpected peer " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } + + if (pRxAuthFrameBody->authStatusCode == + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS) + { + /** + * Interoperability workaround: Linksys WAP4400N is returning + * wrong authType in OpenAuth response in case of + * SharedKey AP configuration. Pretend we don't see that, + * so upper layer can fallback to SharedKey authType, + * and successfully connect to the AP. + */ + if (pRxAuthFrameBody->authAlgoNumber != + pMac->lim.gpLimMlmAuthReq->authType) + { + pRxAuthFrameBody->authAlgoNumber = + pMac->lim.gpLimMlmAuthReq->authType; + } + } + + if (pRxAuthFrameBody->authAlgoNumber != + pMac->lim.gpLimMlmAuthReq->authType) + { + /** + * Received Authentication frame with an auth + * algorithm other than one requested. + * Wait until Authentication Failure Timeout. + */ + + // Log error + PELOGW(limLog(pMac, LOGW, + FL("received Auth frame2 for unexpected auth algo number %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } + + if (pRxAuthFrameBody->authStatusCode == + eSIR_MAC_SUCCESS_STATUS) + { + if (pRxAuthFrameBody->authAlgoNumber == + eSIR_OPEN_SYSTEM) + { + psessionEntry->limCurrentAuthType = eSIR_OPEN_SYSTEM; + + pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); + + if (pAuthNode == NULL) + { + // Log error + limLog(pMac, LOGW, + FL("Max pre-auth nodes reached ")); + limPrintMacAddr(pMac, pHdr->sa, LOGW); + + return; + } + + PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %x peer "), pAuthNode);) + PELOG1(limPrintMacAddr(pMac, pHdr->sa, LOG1);) + + vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, + pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)); + pAuthNode->fTimerStarted = 0; + pAuthNode->seqNum = ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->authType = pMac->lim.gpLimMlmAuthReq->authType; + pAuthNode->timestamp = vos_timer_get_system_ticks(); + limAddPreAuthNode(pMac, pAuthNode); + + limRestoreFromAuthState(pMac, eSIR_SME_SUCCESS, + pRxAuthFrameBody->authStatusCode,psessionEntry); + } // if (pRxAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) + else + { + // Shared key authentication + + if (LIM_IS_AP_ROLE(psessionEntry)) { + val = psessionEntry->privacy; + } else if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &val) != eSIR_SUCCESS) { + /** + * Could not get Privacy option + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Privacy option")); + } + cfgPrivacyOptImp = (tANI_U8)val; + if (!cfgPrivacyOptImp) + { + /** + * Requesting STA does not have WEP implemented. + * Reject with unsupported authentication algorithm + * Status code and wait until auth failure timeout + */ + + // Log error + PELOGE( limLog(pMac, LOGE, + FL("received Auth frame from peer for unsupported auth algo %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + else + { + + if (pRxAuthFrameBody->type != + SIR_MAC_CHALLENGE_TEXT_EID) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame with invalid challenge text IE"));) + + return; + } + + /** + * Check if there exists a key mappping key + * for the STA that sent Authentication frame + */ + pKeyMapEntry = limLookUpKeyMappings( + pHdr->sa); + + if (pKeyMapEntry) + { + if (pKeyMapEntry->key == NULL) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame from peer when key mapping key is NULL" + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * Key Mapping entry has null key. + * Send Auth frame with + * challenge failure status code + */ + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + limRestoreFromAuthState(pMac, eSIR_SME_NO_KEY_MAPPING_KEY_FOR_PEER, + eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + + return; + } // if (pKeyMapEntry->key == NULL) + else + { + ((tpSirMacAuthFrameBody) plainBody)->authAlgoNumber = + sirSwapU16ifNeeded(pRxAuthFrameBody->authAlgoNumber); + ((tpSirMacAuthFrameBody) plainBody)->authTransactionSeqNumber = + 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; + vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText, + pRxAuthFrameBody->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH); + + limEncryptAuthFrame(pMac, 0, + pKeyMapEntry->key, + plainBody, + encrAuthFrame,key_length); + + psessionEntry->limMlmState = eLIM_MLM_WT_AUTH_FRAME4_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + limSendAuthMgmtFrame(pMac, + (tpSirMacAuthFrameBody) encrAuthFrame, + pHdr->sa, + LIM_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + break; + } // end if (pKeyMapEntry->key == NULL) + } // if (pKeyMapEntry) + else + { + if (wlan_cfgGetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, + &val) != eSIR_SUCCESS) + { + /** + * Could not get Default keyId + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Default keyId")); + } + keyId = (tANI_U8)val; + + val = SIR_MAC_KEY_LENGTH; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + tpSirKeys pKey; + pKey = &psessionEntry->WEPKeyMaterial[keyId].key[0]; + vos_mem_copy(defaultKey, pKey->key, pKey->keyLength); + } else if (wlan_cfgGetStr(pMac, + (tANI_U16) (WNI_CFG_WEP_DEFAULT_KEY_1 + keyId), + defaultKey, &val) != eSIR_SUCCESS) { + /// Could not get Default key from CFG. + //Log error. + limLog(pMac, LOGP, + FL("could not retrieve Default key")); + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + 1; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + limRestoreFromAuthState(pMac, eSIR_SME_INVALID_WEP_DEFAULT_KEY, + eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + + break; + } + key_length=val; + ((tpSirMacAuthFrameBody) plainBody)->authAlgoNumber = + sirSwapU16ifNeeded(pRxAuthFrameBody->authAlgoNumber); + ((tpSirMacAuthFrameBody) plainBody)->authTransactionSeqNumber = + 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; + vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText, + pRxAuthFrameBody->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH); + + limEncryptAuthFrame(pMac, keyId, + defaultKey, + plainBody, + encrAuthFrame,key_length); + + psessionEntry->limMlmState = + eLIM_MLM_WT_AUTH_FRAME4_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + limSendAuthMgmtFrame(pMac, + (tpSirMacAuthFrameBody) encrAuthFrame, + pHdr->sa, + LIM_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + break; + } // end if (pKeyMapEntry) + } // end if (!wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED)) + } // end if (pRxAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) + } // if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) + else + { + /** + * Authentication failure. + * Return Auth confirm with received failure code to SME + */ + + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame from peer with failure code %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authStatusCode, + MAC_ADDR_ARRAY(pHdr->sa));) + + limRestoreFromAuthState(pMac, eSIR_SME_AUTH_REFUSED, + pRxAuthFrameBody->authStatusCode,psessionEntry); + } // end if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) + + break; + + case SIR_MAC_AUTH_FRAME_3: + // AuthFrame 3 + + if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame3 from peer with auth algo number %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * Received Authentication frame3 with algorithm other than + * Shared Key authentication type. Reject with Auth frame4 + * with 'out of sequence' status code. + */ + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_IBSS_ROLE(psessionEntry)) { + /** + * Check if wep bit was set in FC. If not set, + * reject with Authentication frame4 with + * 'challenge failure' status code. + */ + if (!pHdr->fc.wep) + { + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame3 from peer with no WEP bit set "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) + + /// WEP bit is not set in FC of Auth Frame3 + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + + pAuthNode = limSearchPreAuthList(pMac, + pHdr->sa); + if (pAuthNode == NULL) + { + // Log error + PELOGE(limLog(pMac, LOGW, + FL("received AuthFrame3 from peer that has no preauth context " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + /** + * No 'pre-auth' context exists for + * this STA that sent an Authentication + * frame3. + * Send Auth frame4 with 'out of sequence' + * status code. + */ + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + + if (pAuthNode->mlmState == eLIM_MLM_AUTH_RSP_TIMEOUT_STATE) + { + // Log error + limLog(pMac, LOGW, + FL("auth response timer timedout for peer " + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); + + /** + * Received Auth Frame3 after Auth Response timeout. + * Reject by sending Auth Frame4 with + * Auth respone timeout Status Code. + */ + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_AUTH_RSP_TIMEOUT_STATUS; + + limSendAuthMgmtFrame( + pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + /// Delete pre-auth context of STA + limDeletePreAuthNode(pMac, + pHdr->sa); + + return; + } // end switch (pAuthNode->mlmState) + + if (pRxAuthFrameBody->authStatusCode != eSIR_MAC_SUCCESS_STATUS) + { + /** + * Received Authenetication Frame 3 with status code + * other than success. Wait until Auth response timeout + * to delete STA context. + */ + + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame3 from peer with status code %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authStatusCode, + MAC_ADDR_ARRAY(pHdr->sa));) + + return; + } + + /** + * Check if received challenge text is same as one sent in + * Authentication frame3 + */ + + if (vos_mem_compare(pRxAuthFrameBody->challengeText, + pAuthNode->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH)) + { + /// Challenge match. STA is autheticated ! + + /// Delete Authentication response timer if running + limDeactivateAndChangePerStaIdTimer(pMac, + eLIM_AUTH_RSP_TIMER, + pAuthNode->authNodeIdx); + + pAuthNode->fTimerStarted = 0; + pAuthNode->mlmState = eLIM_MLM_AUTHENTICATED_STATE; + + /** + * Send Authentication Frame4 with 'success' Status Code. + */ + authFrame.authAlgoNumber = eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = eSIR_MAC_SUCCESS_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + + /// Send Auth indication to SME + vos_mem_copy((tANI_U8 *) mlmAuthInd.peerMacAddr, + (tANI_U8 *) pHdr->sa, + sizeof(tSirMacAddr)); + mlmAuthInd.authType = (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber; + mlmAuthInd.sessionId = psessionEntry->smeSessionId; + + limPostSmeMessage(pMac, + LIM_MLM_AUTH_IND, + (tANI_U32 *) &mlmAuthInd); + + break; + } + else + { + // Log error + PELOGE( limLog(pMac, LOGW, + FL("Challenge failure for peer "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) + /** + * Challenge Failure. + * Send Authentication frame4 with 'challenge failure' + * status code and wait until Auth response timeout to + * delete STA context. + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + limSendAuthMgmtFrame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry, + eSIR_FALSE); + return; + } + } // if (pMac->lim.gLimSystemRole == eLIM_AP_ROLE || ... + + break; + + case SIR_MAC_AUTH_FRAME_4: + // AuthFrame 4 + if (psessionEntry->limMlmState != eLIM_MLM_WT_AUTH_FRAME4_STATE) + { + /** + * Received Authentication frame4 in an unexpected state. + * Log error and ignore the frame. + */ + + // Log error + PELOG1(limLog(pMac, LOG1, + FL("received unexpected Auth frame4 from peer in state %d, addr " + MAC_ADDRESS_STR), psessionEntry->limMlmState, + MAC_ADDR_ARRAY(pHdr->sa));) + + return; + } + + if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY) + { + /** + * Received Authentication frame4 with algorithm other than + * Shared Key authentication type. + * Wait until Auth failure timeout to report authentication + * failure to SME. + */ + + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame4 from peer with invalid auth algo %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + return; + } + + if ( !vos_mem_compare((tANI_U8 *) pHdr->sa, + (tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)) ) + { + /** + * Received Authentication frame from an entity + * other than one to which request was initiated. + * Wait until Authentication Failure Timeout. + */ + + // Log error + PELOGE(limLog(pMac, LOGW, + FL("received Auth frame4 from unexpected peer " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } + + if (pRxAuthFrameBody->authAlgoNumber != + pMac->lim.gpLimMlmAuthReq->authType) + { + /** + * Received Authentication frame with an auth algorithm + * other than one requested. + * Wait until Authentication Failure Timeout. + */ + + PELOGE(limLog(pMac, LOGE, + FL("received Authentication frame from peer with invalid auth seq number %d " + MAC_ADDRESS_STR), pRxAuthFrameBody->authTransactionSeqNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } + + if (pRxAuthFrameBody->authStatusCode == + eSIR_MAC_SUCCESS_STATUS) + { + /** + * Authentication Success ! + * Inform SME of same. + */ + psessionEntry->limCurrentAuthType = eSIR_SHARED_KEY; + + pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); + if (pAuthNode == NULL) + { + // Log error + limLog(pMac, LOGW, + FL("Max pre-auth nodes reached ")); + limPrintMacAddr(pMac, pHdr->sa, LOGW); + + return; + } + PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %x peer "), pAuthNode); + limPrintMacAddr(pMac, pHdr->sa, LOG1);) + + vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, + pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)); + pAuthNode->fTimerStarted = 0; + pAuthNode->authType = pMac->lim.gpLimMlmAuthReq->authType; + pAuthNode->seqNum = ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = vos_timer_get_system_ticks(); + limAddPreAuthNode(pMac, pAuthNode); + + limRestoreFromAuthState(pMac, eSIR_SME_SUCCESS, + pRxAuthFrameBody->authStatusCode,psessionEntry); + + } // if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) + else + { + /** + * Authentication failure. + * Return Auth confirm with received failure code to SME + */ + + // Log error + PELOGE(limLog(pMac, LOGE, FL("Authentication failure from peer " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) + + limRestoreFromAuthState(pMac, eSIR_SME_AUTH_REFUSED, + pRxAuthFrameBody->authStatusCode,psessionEntry); + } // end if (pRxAuthFrameBody->Status == 0) + + break; + + default: + /// Invalid Authentication Frame received. Ignore it. + + // Log error + PELOGE(limLog(pMac, LOGE, + FL("received Auth frame from peer with invalid auth seq " + "number %d " MAC_ADDRESS_STR), + pRxAuthFrameBody->authTransactionSeqNumber, + MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } // end switch (pRxAuthFrameBody->authTransactionSeqNumber) +} /*** end limProcessAuthFrame() ***/ + + + + + +#ifdef WLAN_FEATURE_VOWIFI_11R + +/*---------------------------------------------------------------------- + * + * Pass the received Auth frame. This is possibly the pre-auth from the + * neighbor AP, in the same mobility domain. + * This will be used in case of 11r FT. + * + * !!!! This is going to be renoved for the next checkin. We will be creating + * the session before sending out the Auth. Thus when auth response + * is received we will have a session in progress. !!!!! + *---------------------------------------------------------------------- + */ +tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd, void *body) +{ + tpSirMacMgmtHdr pHdr; + tpPESession psessionEntry = NULL; + tANI_U8 *pBody; + tANI_U16 frameLen; + tSirMacAuthFrameBody rxAuthFrame; + tSirMacAuthFrameBody *pRxAuthFrameBody = NULL; + tSirRetStatus ret_status = eSIR_FAILURE; + int i; + + pHdr = WDA_GET_RX_MAC_HEADER(pBd); + pBody = WDA_GET_RX_MPDU_DATA(pBd); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd); + + limLog(pMac, LOG1, + FL("Auth Frame Received: BSSID "MAC_ADDRESS_STR" (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED(pBd))); + + /* Auth frame has come on a new BSS, however, we need to find the session + * from where the auth-req was sent to the new AP + */ + for (i = 0; i < pMac->lim.maxBssId; i++) { + /* Find first free room in session table */ + if (pMac->lim.gpSession[i].valid == TRUE && + pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession == VOS_TRUE) { + /* Found the session */ + psessionEntry = &pMac->lim.gpSession[i]; + pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession = VOS_FALSE; + } + } + + if (psessionEntry == NULL) + { + limLog(pMac, LOGE, + FL("Error: Unable to find session id while in pre-auth phase for FT")); + return eSIR_FAILURE; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq == NULL) + { + limLog(pMac, LOGE, FL("Error: No FT")); + // No FT in progress. + return eSIR_FAILURE; + } + + if (frameLen == 0) + { + limLog(pMac, LOGE, FL("Error: Frame len = 0")); + return eSIR_FAILURE; + } +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limPrintMacAddr(pMac, pHdr->bssId, LOG2); + limPrintMacAddr(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, LOG2); + limLog(pMac,LOG2,FL("seqControl 0x%X"), + ((pHdr->seqControl.seqNumHi << 8) | + (pHdr->seqControl.seqNumLo << 4) | + (pHdr->seqControl.fragNum))); +#endif + + // Check that its the same bssId we have for preAuth + if (!vos_mem_compare(psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + pHdr->bssId, sizeof( tSirMacAddr ))) + { + limLog(pMac, LOGE, FL("Error: Same bssid as preauth BSSID")); + // In this case SME if indeed has triggered a + // pre auth it will time out. + return eSIR_FAILURE; + } + + if (eANI_BOOLEAN_TRUE == + psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) + { + /* + * This is likely a duplicate for the same pre-auth request. + * PE/LIM already posted a response to SME. Hence, drop it. + * TBD: + * 1) How did we even receive multiple auth responses? + * 2) Do we need to delete pre-auth session? Suppose we + * previously received an auth resp with failure which + * would not have created the session and forwarded to SME. + * And, we subsequently received an auth resp with success + * which would have created the session. This will now be + * dropped without being forwarded to SME! However, it is + * very unlikely to receive auth responses from the same + * AP with different reason codes. + * NOTE: return eSIR_SUCCESS so that the packet is dropped + * as this was indeed a response from the BSSID we tried to + * pre-auth. + */ + PELOGE(limLog(pMac,LOG1,"Auth rsp already posted to SME" + " (session %p, FT session %p)", psessionEntry, + psessionEntry);); + return eSIR_SUCCESS; + } + else + { + PELOGE(limLog(pMac,LOGW,"Auth rsp not yet posted to SME" + " (session %p, FT session %p)", psessionEntry, + psessionEntry);); + psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = + eANI_BOOLEAN_TRUE; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(pMac, LOG1, FL("Pre-Auth response received from neighbor")); + limLog(pMac, LOG1, FL("Pre-Auth done state")); +#endif + // Stopping timer now, that we have our unicast from the AP + // of our choice. + limDeactivateAndChangeTimer(pMac, eLIM_FT_PREAUTH_RSP_TIMER); + + + // Save off the auth resp. + if ((sirConvertAuthFrame2Struct(pMac, pBody, frameLen, &rxAuthFrame) != eSIR_SUCCESS)) + { + limLog(pMac, LOGE, FL("failed to convert Auth frame to struct")); + limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); + return eSIR_FAILURE; + } + pRxAuthFrameBody = &rxAuthFrame; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOG1, + FL("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"), + (tANI_U32) pRxAuthFrameBody->authAlgoNumber, + (tANI_U32) pRxAuthFrameBody->authTransactionSeqNumber, + (tANI_U32) pRxAuthFrameBody->authStatusCode,(tANI_U32)pMac->lim.gLimNumPreAuthContexts);) +#endif + + switch (pRxAuthFrameBody->authTransactionSeqNumber) + { + case SIR_MAC_AUTH_FRAME_2: + if (pRxAuthFrameBody->authStatusCode != eSIR_MAC_SUCCESS_STATUS) + { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOGE, "Auth status code received is %d", + (tANI_U32) pRxAuthFrameBody->authStatusCode);); +#endif + if (eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS == pRxAuthFrameBody->authStatusCode) + ret_status = eSIR_LIM_MAX_STA_REACHED_ERROR; + } + else + { + ret_status = eSIR_SUCCESS; + } + break; + + default: +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog( pMac, LOGE, "Seq. no incorrect expected 2 received %d", + (tANI_U32) pRxAuthFrameBody->authTransactionSeqNumber);) +#endif + break; + } + + // Send the Auth response to SME + limHandleFTPreAuthRsp(pMac, ret_status, pBody, frameLen, psessionEntry); + + return ret_status; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c new file mode 100644 index 000000000000..bdc4ddf51a85 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limProcessBeaconFrame.cc contains the code + * for processing Received Beacon Frame. + * Author: Chandra Modumudi + * Date: 03/01/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "cfgApi.h" +#include "schApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limPropExtsUtils.h" +#include "limSerDesUtils.h" + +/** + * limProcessBeaconFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon Beacon + * frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * 1. Beacons received in 'normal' state in IBSS are handled by + * Beacon Processing module. + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to RX packet info structure + * @return None + */ + +void +limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tSchBeaconStruct *pBeacon; + + pMac->lim.gLimNumBeaconsRcvd++; + + /* here is it required to increment session specific heartBeat beacon counter */ + + + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + + PELOG2(limLog(pMac, LOG2, FL("Received Beacon frame with length=%d from "), + WDA_GET_RX_MPDU_LEN(pRxPacketInfo)); + limPrintMacAddr(pMac, pHdr->sa, LOG2);) + + if (!pMac->fScanOffload) + { + if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) + return; + } + + /** + * Expect Beacon only when + * 1. STA is in Scan mode waiting for Beacon/Probe response or + * 2. STA is waiting for Beacon/Probe Respose Frame + * to announce join success. + * 3. STA/AP is in Learn mode + */ + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) || + (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) + || pMac->fScanOffload + ) + { + pBeacon = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if ( NULL == pBeacon ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limProcessBeaconFrame") ); + return; + } + + // Parse received Beacon + if (sirConvertBeaconFrame2Struct(pMac, (tANI_U8 *) pRxPacketInfo, + pBeacon) != eSIR_SUCCESS) + { + // Received wrongly formatted/invalid Beacon. + // Ignore it and move on. + limLog(pMac, LOGW, + FL("Received invalid Beacon in state %X"), + psessionEntry->limMlmState); + limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); + vos_mem_free(pBeacon); + return; + } + + /*during scanning, when any session is active, and beacon/Pr belongs to + one of the session, fill up the following, TBD - HB couter */ + if ((!psessionEntry->lastBeaconDtimPeriod) && + (sirCompareMacAddr( psessionEntry->bssId, pBeacon->bssid))) + { + vos_mem_copy(( tANI_U8* )&psessionEntry->lastBeaconTimeStamp, + ( tANI_U8* )pBeacon->timeStamp, sizeof(tANI_U64) ); + psessionEntry->lastBeaconDtimCount = pBeacon->tim.dtimCount; + psessionEntry->lastBeaconDtimPeriod= pBeacon->tim.dtimPeriod; + psessionEntry->currentBssBeaconCnt++; + } + + MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_TSF, 0, pBeacon->timeStamp[0]);) + MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_TSF, 0, pBeacon->timeStamp[1]);) + + if (pMac->fScanOffload) + { + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + + } + + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) + { + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + ((pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) ? + eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE), + eANI_BOOLEAN_FALSE); + /* Calling dfsChannelList which will convert DFS channel + * to Active channel for x secs if this channel is DFS channel */ + limSetDFSChannelList(pMac, pBeacon->channelNumber, + &pMac->lim.dfschannelList); + } + else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) + { + } + else if (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) + { + if( psessionEntry->beacon != NULL ) + { + vos_mem_free(psessionEntry->beacon); + psessionEntry->beacon = NULL; + } + psessionEntry->bcnLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + psessionEntry->beacon = vos_mem_malloc(psessionEntry->bcnLen); + if ( NULL == psessionEntry->beacon ) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store beacon"));) + } + else + { + //Store the Beacon/ProbeRsp. This is sent to csr/hdd in join cnf response. + vos_mem_copy(psessionEntry->beacon, WDA_GET_RX_MPDU_DATA(pRxPacketInfo), + psessionEntry->bcnLen); + + } + + // STA in WT_JOIN_BEACON_STATE (IBSS) + limCheckAndAnnounceJoinSuccess(pMac, pBeacon, pHdr,psessionEntry); + } // if (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) + vos_mem_free(pBeacon); + } // if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || ... + else + { + // Ignore Beacon frame in all other states + if (psessionEntry->limMlmState == eLIM_MLM_JOINED_STATE || + psessionEntry->limMlmState == eLIM_MLM_BSS_STARTED_STATE || + psessionEntry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE || + psessionEntry->limMlmState == eLIM_MLM_WT_AUTH_FRAME3_STATE || + psessionEntry->limMlmState == eLIM_MLM_WT_AUTH_FRAME4_STATE || + psessionEntry->limMlmState == eLIM_MLM_AUTH_RSP_TIMEOUT_STATE || + psessionEntry->limMlmState == eLIM_MLM_AUTHENTICATED_STATE || + psessionEntry->limMlmState == eLIM_MLM_WT_ASSOC_RSP_STATE || + psessionEntry->limMlmState == eLIM_MLM_WT_REASSOC_RSP_STATE || + psessionEntry->limMlmState == eLIM_MLM_ASSOCIATED_STATE || + psessionEntry->limMlmState == eLIM_MLM_REASSOCIATED_STATE || + psessionEntry->limMlmState == eLIM_MLM_WT_ASSOC_CNF_STATE || + limIsReassocInProgress(pMac,psessionEntry)) { + // nothing unexpected about beacon in these states + pMac->lim.gLimNumBeaconsIgnored++; + } + else + { + PELOG1(limLog(pMac, LOG1, FL("Received Beacon in unexpected state %d"), + psessionEntry->limMlmState); + limPrintMlmState(pMac, LOG1, psessionEntry->limMlmState);) +#ifdef WLAN_DEBUG + pMac->lim.gLimUnexpBcnCnt++; +#endif + } + } + + return; +} /*** end limProcessBeaconFrame() ***/ + + +/**--------------------------------------------------------------- +\fn limProcessBeaconFrameNoSession +\brief This function is called by limProcessMessageQueue() +\ upon Beacon reception. +\ +\param pMac +\param *pRxPacketInfo - A pointer to Rx packet info structure +\return None +------------------------------------------------------------------*/ +void +limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) +{ + tpSirMacMgmtHdr pHdr; + tSchBeaconStruct *pBeacon; + + pMac->lim.gLimNumBeaconsRcvd++; + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + limLog(pMac, LOG2, FL("Received Beacon frame with length=%d from "), + WDA_GET_RX_MPDU_LEN(pRxPacketInfo)); + limPrintMacAddr(pMac, pHdr->sa, LOG2); + + if (!pMac->fScanOffload) + { + if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) + return; + } + + /** + * No session has been established. Expect Beacon only when + * 1. STA is in Scan mode waiting for Beacon/Probe response or + * 2. STA/AP is in Learn mode + */ + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE)) + { + pBeacon = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if ( NULL == pBeacon ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limProcessBeaconFrameNoSession") ); + return; + } + + if (sirConvertBeaconFrame2Struct(pMac, (tANI_U8 *) pRxPacketInfo, pBeacon) != eSIR_SUCCESS) + { + // Received wrongly formatted/invalid Beacon. Ignore and move on. + limLog(pMac, LOGW, FL("Received invalid Beacon in global MLM state %X"), pMac->lim.gLimMlmState); + limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); + vos_mem_free(pBeacon); + return; + } + + if ( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) ) + { + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE); + /* Calling dfsChannelList which will convert DFS channel + * to Active channel for x secs if this channel is DFS channel */ + limSetDFSChannelList(pMac, pBeacon->channelNumber, + &pMac->lim.dfschannelList); + } + else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) + { + } // end of eLIM_MLM_LEARN_STATE) + vos_mem_free(pBeacon); + } // end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) + else + { + limLog(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %s (%d)"), + limMlmStateStr(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState); + limPrintMlmState(pMac, LOG1, pMac->lim.gLimMlmState); +#ifdef WLAN_DEBUG + pMac->lim.gLimUnexpBcnCnt++; +#endif + } + + return; +} /*** end limProcessBeaconFrameNoSession() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c new file mode 100644 index 000000000000..c32c436de555 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c @@ -0,0 +1,726 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limProcessCfgUpdates.cc contains the utility functions + * to handle various CFG parameter update events + * Author: Chandra Modumudi + * Date: 01/20/03 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "aniGlobal.h" + +#include "wniCfgSta.h" +#include "sirMacProtDef.h" +#include "cfgApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limPropExtsUtils.h" +#include "schApi.h" +#include "pmmApi.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif + +static void limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry); + +/** ------------------------------------------------------------- +\fn limSetCfgProtection +\brief sets lim global cfg cache from the config. +\param tpAniSirGlobal pMac +\return None + -------------------------------------------------------------*/ +void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) +{ + tANI_U32 val = 0; + + if ((pesessionEntry != NULL) && LIM_IS_AP_ROLE(pesessionEntry)) { + if (pesessionEntry->gLimProtectionControl == WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE ) + vos_mem_set((void *)&pesessionEntry->cfgProtection, sizeof(tCfgProtection), 0); + else{ + limLog(pMac, LOG1, FL(" frm11a = %d, from11b = %d, frm11g = %d, " + "ht20 = %d, nongf = %d, lsigTxop = %d, " + "rifs = %d, obss = %d"), + pesessionEntry->cfgProtection.fromlla, + pesessionEntry->cfgProtection.fromllb, + pesessionEntry->cfgProtection.fromllg, + pesessionEntry->cfgProtection.ht20, + pesessionEntry->cfgProtection.nonGf, + pesessionEntry->cfgProtection.lsigTxop, + pesessionEntry->cfgProtection.rifs, + pesessionEntry->cfgProtection.obss); + } + } + else{ + if (wlan_cfgGetInt(pMac, WNI_CFG_FORCE_POLICY_PROTECTION, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed")); + return; + } + else + pMac->lim.gLimProtectionControl = (tANI_U8)val; + + if (wlan_cfgGetInt(pMac, WNI_CFG_PROTECTION_ENABLED, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("reading protection cfg failed")); + return; + } + + if (pMac->lim.gLimProtectionControl == WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + vos_mem_set((void *)&pMac->lim.cfgProtection, sizeof(tCfgProtection), 0); + else + { + pMac->lim.cfgProtection.fromlla = (val >> WNI_CFG_PROTECTION_ENABLED_FROM_llA) & 1; + pMac->lim.cfgProtection.fromllb = (val >> WNI_CFG_PROTECTION_ENABLED_FROM_llB) & 1; + pMac->lim.cfgProtection.fromllg = (val >> WNI_CFG_PROTECTION_ENABLED_FROM_llG) & 1; + pMac->lim.cfgProtection.ht20 = (val >> WNI_CFG_PROTECTION_ENABLED_HT_20) & 1; + pMac->lim.cfgProtection.nonGf = (val >> WNI_CFG_PROTECTION_ENABLED_NON_GF) & 1; + pMac->lim.cfgProtection.lsigTxop = (val >> WNI_CFG_PROTECTION_ENABLED_LSIG_TXOP) & 1; + pMac->lim.cfgProtection.rifs = (val >> WNI_CFG_PROTECTION_ENABLED_RIFS) & 1; + pMac->lim.cfgProtection.obss= (val >> WNI_CFG_PROTECTION_ENABLED_OBSS) & 1; + + } + } +} + + + +/** + * limUpdateTriggerStaBkScanFlag + * + * FUNCTION: + * This function updates the lim global gLimTriggerBackgroundScanDuringQuietBss + * based on cfg configuration. Usually triggered after a cfgSetInt call. + * + * PARAMS: + * pMac - Pointer to Global MAC structure + * + */ +static tSirRetStatus limUpdateTriggerStaBkScanFlag(tpAniSirGlobal pMac) +{ + tANI_U32 val; + tANI_U8 flag; + + if(wlan_cfgGetInt(pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val) != eSIR_SUCCESS) + { + PELOG1(limLog(pMac, LOG1, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN from cfg"));) + return eSIR_FAILURE; + } + + flag = (val) ? 1 : 0; + if(flag != pMac->lim.gLimTriggerBackgroundScanDuringQuietBss) + { + /* Update global flag */ + pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = flag; + /*Update beacon prop IE also if we're an AP */ + + //call a wrapper and if the session role is other than the sta call this function schsetfixedbeacon fields function + limUpdateBeacon(pMac); + + } + + return eSIR_FAILURE; +} +/** + * limHandleParamUpdate() + * + *FUNCTION: + * This function is use to post a message whenever need indicate + * there is update of config parameter. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param cfgId - ID of CFG parameter that got updated + * @return None + */ +void +limHandleParamUpdate(tpAniSirGlobal pMac, eUpdateIEsType cfgId) +{ + tSirMsgQ msg = {0}; + tANI_U32 status; + + PELOG3(limLog(pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId);) + switch (cfgId) + { + case eUPDATE_IE_PROBE_BCN: + { + msg.type = SIR_LIM_UPDATE_BEACON; + status = limPostMsgApi(pMac, &msg); + + if (status != TX_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Failed limPostMsgApi %u"), status);) + break; + } + default: + break; + } +} + +/** + * limHandleCFGparamUpdate() + * + *FUNCTION: + * This function is called by limProcessMessages() to + * whenever SIR_CFG_PARAM_UPDATE_IND message is posted + * to LIM (due to a set operation on a CFG parameter). + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param cfgId - ID of CFG parameter that got updated + * @return None + */ + +void +limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) +{ + tANI_U32 val1, val2; + tANI_U16 val16; + tSirMacHTCapabilityInfo *pHTCapabilityInfo; + tSirMacHTParametersInfo *pAmpduParamInfo; + + PELOG3(limLog(pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId);) + switch (cfgId) + { + case WNI_CFG_WEP_DEFAULT_KEYID: + break; + + case WNI_CFG_EXCLUDE_UNENCRYPTED: + if (wlan_cfgGetInt(pMac, WNI_CFG_EXCLUDE_UNENCRYPTED, + &val1) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to retrieve excludeUnencr from CFG")); + } + limLog(pMac, LOGE, + FL("Unsupported CFG: WNI_CFG_EXCLUDE_UNENCRYPTED")); + + break; + + case WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT: + if (pMac->lim.gLimMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) + { + // 'Change' timer for future activations + limDeactivateAndChangeTimer(pMac, + eLIM_ASSOC_FAIL_TIMER); + } + + break; + + case WNI_CFG_BACKGROUND_SCAN_PERIOD: + + + limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); + + if (wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, &val1) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); + break; + } + if (val1 == 0) + break; + + + + if ( (pMac->lim.gLimSystemRole == eLIM_STA_ROLE) || + ( (pMac->lim.gLimSystemRole == eLIM_STA_IN_IBSS_ROLE) && + (pMac->lim.gLimSmeState == eLIM_SME_NORMAL_STATE))) + { + // Reactivate Background scan timer + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_BACKGROUND_SCAN_TIMER)); + if (tx_timer_activate( + &pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) + { + /// Could not activate background scan timer. + // Log error + limLog(pMac, LOGP, + FL("could not activate background scan timer")); + pMac->lim.gLimBackgroundScanStarted = FALSE; + pMac->lim.gLimBackgroundScanTerminate = TRUE; + } + else + { + pMac->lim.gLimBackgroundScanStarted = TRUE; + pMac->lim.gLimBackgroundScanTerminate = FALSE; + } + + PELOG3(limLog(pMac, LOG3, + FL("Updated Background scan period"));) + } + + break; + + case WNI_CFG_BG_SCAN_CHANNEL_LIST: + PELOG1(limLog(pMac, LOG1, + FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel"));) + pMac->lim.gLimBackgroundScanChannelId = 0; + + break; + + case WNI_CFG_TRIG_STA_BK_SCAN: + if(limUpdateTriggerStaBkScanFlag(pMac) != eSIR_SUCCESS) + { + PELOG2(limLog(pMac, LOG2, + FL("Updating lim trigger sta bk scan global flag failed!"));) + } + break; + + case WNI_CFG_PROTECTION_ENABLED: + limSetCfgProtection(pMac, NULL); + break; + case WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG: + { + tSirMsgQ msg = {0}; + tANI_U32 status; + + msg.type = SIR_LIM_UPDATE_BEACON; + + status = limPostMsgApi(pMac, &msg); + + if (status != TX_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Failed limPostMsgApi %u"), status);) + break; + } + case WNI_CFG_GREENFIELD_CAPABILITY: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG"));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_GREENFIELD_CAPABILITY, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve GreenField CFG"));) + break; + } + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + pHTCapabilityInfo->greenField = (tANI_U16)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + break; + + case WNI_CFG_HT_RX_STBC: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_CAP_INFO "));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_RX_STBC, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_RX_STBC"));) + break; + } + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + pHTCapabilityInfo->rxSTBC = (tANI_U16)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + break; + + case WNI_CFG_MAX_AMSDU_LENGTH: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG"));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_AMSDU_LENGTH, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max AMSDU Length CFG"));) + break; + } + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + pHTCapabilityInfo->maximalAMSDUsize = (tANI_U16)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + break; + + case WNI_CFG_SHORT_GI_20MHZ: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG"));) + break; + } + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + pHTCapabilityInfo->shortGI20MHz = (tANI_U16)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + break; + case WNI_CFG_SHORT_GI_40MHZ: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG"));) + break; + } + val16 = ( tANI_U16 ) val1; + pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; + pHTCapabilityInfo->shortGI40MHz = (tANI_U16)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) + break; + case WNI_CFG_MPDU_DENSITY: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_MPDU_DENSITY, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG"));) + break; + } + val16 = ( tANI_U16 ) val1; + pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; + pAmpduParamInfo->mpduDensity = (tANI_U8)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));) + + break; + case WNI_CFG_MAX_RX_AMPDU_FACTOR: + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG"));) + break; + } + val16 = ( tANI_U16 ) val1; + pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; + pAmpduParamInfo->maxRxAMPDUFactor = (tANI_U8)val2; + if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));) + break; + + case WNI_CFG_HEART_BEAT_THRESHOLD: + if(pMac->psOffloadEnabled) + { + break; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG"));) + break; + } + if(!val1) + { + limDeactivateAndChangeTimer(pMac, eLIM_HEART_BEAT_TIMER); + pMac->sys.gSysEnableLinkMonitorMode = 0; + } + else + { + tANI_U16 sessionId; + pMac->sys.gSysEnableLinkMonitorMode = 1; + for(sessionId = 0; sessionId < pMac->lim.maxBssId; sessionId++) + { + if( (pMac->lim.gpSession[sessionId].valid )&& + (eLIM_MLM_LINK_ESTABLISHED_STATE == pMac->lim.gpSession[sessionId].limMlmState) && + ( pMac->pmm.gPmmState != ePMM_STATE_BMPS_SLEEP) && + (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + PELOG2(limLog(pMac, LOG2, "HB link monitoring reactivated" + " for session=%d", sessionId);) + PELOGW(limLog(pMac, LOGW, "Before reactivating HB timer; parameters are" + " session=%d limMlmState=%d pmmState=%d", sessionId, + pMac->lim.gpSession[sessionId].limMlmState, + pMac->pmm.gPmmState);) + limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[sessionId]); + } + else if ( pMac->lim.gpSession[sessionId].valid ) + { + PELOGW(limLog(pMac, LOGW, "HB link monitoring not reactivated-" + "session=%d, limMlmState=%d, gPmmState=%d", + sessionId, pMac->lim.gpSession[sessionId].limMlmState, + pMac->pmm.gPmmState);) + } + } + } + case WNI_CFG_MAX_PS_POLL: + case WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE: + case WNI_CFG_MIN_RSSI_THRESHOLD: + case WNI_CFG_NTH_BEACON_FILTER: + case WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE: + if(!pMac->psOffloadEnabled) + { + tpSirPowerSaveCfg pPowerSaveConfig; + + /* Allocate and fill in power save configuration. */ + pPowerSaveConfig = vos_mem_malloc(sizeof(tSirPowerSaveCfg)); + if ( NULL == pPowerSaveConfig ) + { + PELOGE(limLog(pMac, LOGE, FL("LIM: Cannot allocate memory for power save configuration"));) + break; + } + + /* This context should be valid if power-save configuration message has been already dispathed + * during initialization process. Re-using the present configuration mask + */ + vos_mem_copy(pPowerSaveConfig, (tANI_U8 *)&pMac->pmm.gPmmCfg, sizeof(tSirPowerSaveCfg)); + + if ( (pmmSendPowerSaveCfg(pMac, pPowerSaveConfig)) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("LIM: pmmSendPowerSaveCfg() failed "));) + } + } + break; + + + case WNI_CFG_DOT11_MODE: + if (wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &val1) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Dot11 Mode CFG"));) + break; + } + break; + case WNI_CFG_ADDBA_REQ_DECLINE: + if(wlan_cfgGetInt(pMac, WNI_CFG_ADDBA_REQ_DECLINE, &val1) != eSIR_SUCCESS) { + limLog( pMac, LOGE, FL( "Unable to get ADDBA_REQ_DECLINE cfg" )); + break; + } + pMac->lim.gAddBA_Declined = (tANI_U8)val1; + break; + + case WNI_CFG_SCAN_IN_POWERSAVE: + if(wlan_cfgGetInt(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val1) != eSIR_SUCCESS) { + limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_SCAN_IN_POWERSAVE " )); + break; + } + pMac->lim.gScanInPowersave = (tANI_U8)val1; + break; + + + case WNI_CFG_ASSOC_STA_LIMIT: + if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val1) != eSIR_SUCCESS) { + limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_ASSOC_STA_LIMIT" )); + break; + } + pMac->lim.gLimAssocStaLimit = (tANI_U16)val1; + break; + + case WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC: + if (wlan_cfgGetInt + (pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, &val1) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL( "Unable to get WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + break; + } + if (val1) + { + limLog(pMac, LOGW, + FL("BTC requested to disable all RX BA sessions")); + limDelPerBssBASessionsBtc(pMac); + } + else + { + limLog(pMac, LOGW, + FL("Resetting the WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + } + break; + + default: + break; + } +} /*** end limHandleCFGparamUpdate() ***/ + + + +/** + * limApplyConfiguration() + * + *FUNCTION: + * This function is called to apply the configured parameters + * before joining or reassociating with a BSS or starting a BSS. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tANI_U32 val=0, phyMode; + + PELOG2(limLog(pMac, LOG2, FL("Applying config"));) + + psessionEntry->limSentCapsChangeNtf = false; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + limUpdateConfig(pMac,psessionEntry); + + limGetShortSlotFromPhyMode(pMac, psessionEntry, phyMode, + &psessionEntry->shortSlotTimeSupported); + + limSetCfgProtection(pMac, psessionEntry); + + + /* Added for BT - AMP Support */ + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)|| + LIM_IS_IBSS_ROLE(psessionEntry)|| + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + /* This check is required to ensure the beacon generation is not done + as a part of join request for a BT-AMP station */ + + if(psessionEntry->statypeForBss == STA_ENTRY_SELF) + { + PELOG1(limLog(pMac, LOG1, FL("Initializing BT-AMP beacon generation"));) + schSetBeaconInterval(pMac,psessionEntry); + schSetFixedBeaconFields(pMac,psessionEntry); + } + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE")); + return; + } + + PELOG1(limLog(pMac, LOG1, FL("pMac->lim.gScanInPowersave = %hu"), + pMac->lim.gScanInPowersave);) + pMac->lim.gScanInPowersave = (tANI_U8) val; + +} /*** end limApplyConfiguration() ***/ + + +/** + * limUpdateConfig + * + * FUNCTION: + * Update the local state from CFG database + * (This used to be dphUpdateConfig) + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +static void +limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tANI_U32 val; + + sirCopyMacAddr(pMac->lim.gLimMyMacAddr,psessionEntry->selfMacAddr); + + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("cfg get short preamble failed")); + psessionEntry->beaconParams.fShortPreamble = (val) ? 1 : 0; + + /* In STA case this parameter is filled during the join request */ + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) { + if (wlan_cfgGetInt(pMac, WNI_CFG_WME_ENABLED, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("cfg get wme enabled failed")); + psessionEntry->limWmeEnabled = (val) ? 1 : 0; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_WSM_ENABLED, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("cfg get wsm enabled failed")); + psessionEntry->limWsmEnabled = (val) ? 1 : 0; + + if ((! psessionEntry->limWmeEnabled) && (psessionEntry->limWsmEnabled)) + { + PELOGE(limLog(pMac, LOGE, FL("Can't enable WSM without WME"));) + psessionEntry->limWsmEnabled = 0; + } + /* In STA , this parameter is filled during the join request */ + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) { + if (wlan_cfgGetInt(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("cfg get qos enabled failed")); + psessionEntry->limQosEnabled = (val) ? 1 : 0; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_HCF_ENABLED, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("cfg get hcf enabled failed")); + psessionEntry->limHcfEnabled = (val) ? 1 : 0; + + // Update the ADD BA Declined configuration + if(wlan_cfgGetInt(pMac, WNI_CFG_ADDBA_REQ_DECLINE, &val) != eSIR_SUCCESS) + limLog( pMac, LOGP, FL( "Unable to get ADDBA_REQ_DECLINE cfg" )); + pMac->lim.gAddBA_Declined = (val) ? 0xff : 0x0; + + // AP: WSM should enable HCF as well, for STA enable WSM only after + // association response is received + if (psessionEntry->limWsmEnabled && LIM_IS_AP_ROLE(psessionEntry)) + psessionEntry->limHcfEnabled = 1; + + if (wlan_cfgGetInt(pMac, WNI_CFG_11D_ENABLED, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("cfg get 11d enabled failed")); + psessionEntry->lim11dEnabled = (val) ? 1 : 0; + + if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) { + limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); + } + pMac->lim.gLimAssocStaLimit = (tANI_U16)val; + + PELOG1(limLog(pMac, LOG1, FL("Updated Lim shadow state based on CFG"));) +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c new file mode 100644 index 000000000000..4cd0b527e96c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limProcessDeauthFrame.cc contains the code + * for processing Deauthentication Frame. + * Author: Chandra Modumudi + * Date: 03/24/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "aniGlobal.h" + +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "schApi.h" +#include "limSendMessages.h" + + + +/** + * limProcessDeauthFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Deauthentication frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs + * @return None + */ + +void +limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +{ + tANI_U8 *pBody; + tANI_U16 aid, reasonCode; + tpSirMacMgmtHdr pHdr; + tLimMlmAssocCnf mlmAssocCnf; + tLimMlmDeauthInd mlmDeauthInd; + tpDphHashNode pStaDs; + tpPESession pRoamSessionEntry=NULL; + tANI_U8 roamSessionId; +#ifdef WLAN_FEATURE_11W + tANI_U32 frameLen; +#endif + int8_t frame_rssi; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frame_rssi = (int8_t)WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + + if (LIM_IS_STA_ROLE(psessionEntry) && + ((eLIM_SME_WT_DISASSOC_STATE == psessionEntry->limSmeState) || + (eLIM_SME_WT_DEAUTH_STATE == psessionEntry->limSmeState))) + { + /*Every 15th deauth frame will be logged in kmsg*/ + if(!(pMac->lim.deauthMsgCnt & 0xF)) + { + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame in DEAUTH_WT_STATE" + "(already processing previously received DEAUTH frame).." + "Dropping this.. Deauth Failed %d"),++pMac->lim.deauthMsgCnt);) + } + else + { + pMac->lim.deauthMsgCnt++; + } + return; + } + + if (limIsGroupAddr(pHdr->sa)) + { + // Received Deauth frame from a BC/MC address + // Log error and ignore it + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame from a BC/MC address"));) + + return; + } + + if (limIsGroupAddr(pHdr->da) && !limIsAddrBC(pHdr->da)) + { + // Received Deauth frame for a MC address + // Log error and ignore it + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame for a MC address"));) + + return; + } + + if (!lim_validate_received_frame_a1_addr(pMac, pHdr->da, psessionEntry)) { + limLog(pMac, LOGE, + FL("rx frame doesn't have valid a1 address, dropping it")); + return; + } + +#ifdef WLAN_FEATURE_11W + /* PMF: If this session is a PMF session, then ensure that this frame was protected */ + if(psessionEntry->limRmfEnabled && (WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & DPU_FEEDBACK_UNPROTECTED_ERROR)) + { + PELOGE(limLog(pMac, LOGE, FL("received an unprotected deauth from AP"));) + // If the frame received is unprotected, forward it to the supplicant to initiate + // an SA query + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + //send the unprotected frame indication to SME + limSendSmeUnprotectedMgmtFrameInd( pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), + psessionEntry->smeSessionId, psessionEntry); + return; + } +#endif + + // Get reasonCode from Deauthentication frame body + reasonCode = sirReadU16(pBody); + + PELOGE(limLog(pMac, LOGE, + FL("Received Deauth frame for Addr: "MAC_ADDRESS_STR" (mlm state=%s " + "sme state=%d systemrole=%d RSSI=%d) with reason code %d [%s] from " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->da), + limMlmStateStr(psessionEntry->limMlmState), + psessionEntry->limSmeState, + GET_LIM_SYSTEM_ROLE(psessionEntry), frame_rssi, + reasonCode, limDot11ReasonStr(reasonCode), + MAC_ADDR_ARRAY(pHdr->sa));) + + if (limCheckDisassocDeauthAckPending(pMac, (tANI_U8*)pHdr->sa)) + { + PELOGE(limLog(pMac, LOGE, + FL("Ignore the Deauth received, while waiting for ack of " + "disassoc/deauth"));) + limCleanUpDisassocDeauthReq(pMac,(tANI_U8*)pHdr->sa, 1); + return; + } + + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + switch (reasonCode) + { + case eSIR_MAC_UNSPEC_FAILURE_REASON: + case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON: + // Valid reasonCode in received Deauthentication frame + break; + + default: + // Invalid reasonCode in received Deauthentication frame + // Log error and ignore the frame + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame with invalid reasonCode %d from " + MAC_ADDRESS_STR), reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } + } + else if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + switch (reasonCode) + { + case eSIR_MAC_UNSPEC_FAILURE_REASON: + case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON: + case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON: + case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON: + case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON: + case eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON: + // Valid reasonCode in received Deauth frame + break; + + default: + // Invalid reasonCode in received Deauth frame + // Log error and ignore the frame + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame with invalid reasonCode %d from " + MAC_ADDRESS_STR), reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) + + break; + } + } + else + { + // Received Deauth frame in either IBSS + // or un-known role. Log and ignore it + limLog(pMac, LOGE, + FL("received Deauth frame with reasonCode %d in role %d from " + MAC_ADDRESS_STR),reasonCode, GET_LIM_SYSTEM_ROLE(psessionEntry), + MAC_ADDR_ARRAY(pHdr->sa)); + + return; + } + + /** If we are in the middle of ReAssoc, a few things could happen: + * - STA is reassociating to current AP, and receives deauth from: + * a) current AP + * b) other AP + * - STA is reassociating to a new AP, and receives deauth from: + * c) current AP + * d) reassoc AP + * e) other AP + * + * The logic is: + * 1) If rcv deauth from an AP other than the one we're trying to + * reassociate with, then drop the deauth frame (case b, c, e) + * 2) If rcv deauth from the "new" reassoc AP (case d), then restore + * context with previous AP and send SME_REASSOC_RSP failure. + * 3) If rcv deauth from the reassoc AP, which is also the same + * AP we're currently associated with (case a), then proceed + * with normal deauth processing. + */ + if ( psessionEntry->limReAssocbssId!=NULL ) + { + pRoamSessionEntry = peFindSessionByBssid(pMac, psessionEntry->limReAssocbssId, &roamSessionId); + } + 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 " + "AP while ReAssoc. Ignore "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));) + PELOGE(limLog(pMac, LOGE, FL(" limReAssocbssId : "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(psessionEntry->limReAssocbssId));) + return; + } + + /** Received deauth from the new AP to which we tried to ReAssociate. + * Drop ReAssoc and Restore the Previous context( current connected AP). + */ + if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) { + PELOGE(limLog(pMac, LOGE, FL("received DeAuth from the New AP to " + "which ReAssoc is sent "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));) + PELOGE(limLog(pMac, LOGE, FL(" psessionEntry->bssId: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(psessionEntry->bssId));) + limRestorePreReassocState(pMac, + eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry); + return; + } + } + + + /* If received DeAuth from AP other than the one we're trying to join with + * nor associated with, then ignore deauth and delete Pre-auth entry. + */ + if (!LIM_IS_AP_ROLE(psessionEntry)) { + if (!IS_CURRENT_BSSID(pMac, pHdr->bssId, psessionEntry)) + { + PELOGE(limLog(pMac, LOGE, FL("received DeAuth from an AP other " + "than we're trying to join. Ignore. "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa));) + if (limSearchPreAuthList(pMac, pHdr->sa)) + { + PELOG1(limLog(pMac, LOG1, FL("Preauth entry exist. " + "Deleting... "));) + limDeletePreAuthNode(pMac, pHdr->sa); + } + return; + } + } + + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + + // Check for pre-assoc states + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + switch (psessionEntry->limMlmState) + { + case eLIM_MLM_WT_AUTH_FRAME2_STATE: + /** + * AP sent Deauth frame while waiting + * for Auth frame2. Report Auth failure + * to SME. + */ + + // Log error + PELOG1(limLog(pMac, LOG1, + FL("received Deauth frame state %X with failure " + "code %d from "MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa));) + + limRestoreFromAuthState(pMac, eSIR_SME_DEAUTH_WHILE_JOIN, + reasonCode,psessionEntry); + + return; + + case eLIM_MLM_AUTHENTICATED_STATE: + limLog(pMac, LOG1, + FL("received Deauth frame state %X with " + "reasonCode=%d from "MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + /// Issue Deauth Indication to SME. + vos_mem_copy((tANI_U8 *) &mlmDeauthInd.peerMacAddr, + pHdr->sa, + sizeof(tSirMacAddr)); + mlmDeauthInd.reasonCode = reasonCode; + + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + + limPostSmeMessage(pMac, + LIM_MLM_DEAUTH_IND, + (tANI_U32 *) &mlmDeauthInd); + return; + + case eLIM_MLM_WT_ASSOC_RSP_STATE: + /** + * AP may have 'aged-out' our Pre-auth + * context. Delete local pre-auth context + * if any and issue ASSOC_CNF to SME. + */ + limLog(pMac, LOG1, + FL("received Deauth frame state %X with " + "reasonCode=%d from "MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); + + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + mlmAssocCnf.resultCode = eSIR_SME_DEAUTH_WHILE_JOIN; + mlmAssocCnf.protStatusCode = reasonCode; + + /* PE session Id*/ + mlmAssocCnf.sessionId = psessionEntry->peSessionId; + + psessionEntry->limMlmState = + psessionEntry->limPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + // Deactive Association response timeout + limDeactivateAndChangeTimer( + pMac, + eLIM_ASSOC_FAIL_TIMER); + + limPostSmeMessage( + pMac, + LIM_MLM_ASSOC_CNF, + (tANI_U32 *) &mlmAssocCnf); + + return; + + case eLIM_MLM_WT_ADD_STA_RSP_STATE: + psessionEntry->fDeauthReceived = true; + PELOGW(limLog(pMac, LOGW, + FL("Received Deauth frame in state %X with Reason " + "Code %d from Peer"MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa));) + return ; + + case eLIM_MLM_IDLE_STATE: + case eLIM_MLM_LINK_ESTABLISHED_STATE: +#ifdef FEATURE_WLAN_TDLS + if ((NULL != pStaDs) && (STA_ENTRY_TDLS_PEER == pStaDs->staType)) + { + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame in state %X with " + "reason code %d from Tdls peer" + MAC_ADDRESS_STR), + psessionEntry->limMlmState,reasonCode, + MAC_ADDR_ARRAY(pHdr->sa));) + limSendSmeTDLSDelStaInd(pMac, pStaDs, psessionEntry, + reasonCode); + return; + } + else + { + /* Delete all the TDLS peers only if Deauth + * is received from the AP + */ + if (IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry)) + limDeleteTDLSPeers(pMac, psessionEntry); +#endif + /** + * This could be Deauthentication frame from + * a BSS with which pre-authentication was + * performed. Delete Pre-auth entry if found. + */ + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); +#ifdef FEATURE_WLAN_TDLS + } +#endif + break; + + case eLIM_MLM_WT_REASSOC_RSP_STATE: + limLog(pMac, LOGE, + FL("received Deauth frame state %X with " + "reasonCode=%d from "MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + break; + + case eLIM_MLM_WT_FT_REASSOC_RSP_STATE: + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame in FT state %X with " + "reasonCode=%d from "MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa));) + break; + + default: + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame in state %X with " + "reasonCode=%d from "MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa));) + return; + } + break; + + case eLIM_STA_IN_IBSS_ROLE: + break; + + case eLIM_AP_ROLE: + break; + + default: // eLIM_AP_ROLE or eLIM_BT_AMP_AP_ROLE + + + return; + } // end switch (pMac->lim.gLimSystemRole) + + + + /** + * Extract 'associated' context for STA, if any. + * This is maintained by DPH and created by LIM. + */ + if (NULL == pStaDs) + { + limLog(pMac, LOGE, FL("pStaDs is NULL")); + return; + } + + if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || + (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { + /** + * Already in the process of deleting context for the peer + * and received Deauthentication frame. Log and Ignore. + */ + PELOGE(limLog(pMac, LOGE, + FL("received Deauth frame from peer that is in state %X, addr " + MAC_ADDRESS_STR", isDisassocDeauthInProgress : %d\n"), + pStaDs->mlmStaContext.mlmState,MAC_ADDR_ARRAY(pHdr->sa), + pStaDs->isDisassocDeauthInProgress);) + return; + } + pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes)reasonCode; + pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH; + + /// Issue Deauth Indication to SME. + vos_mem_copy((tANI_U8 *) &mlmDeauthInd.peerMacAddr, + pStaDs->staAddr, + sizeof(tSirMacAddr)); + mlmDeauthInd.reasonCode = (tANI_U8) pStaDs->mlmStaContext.disassocReason; + mlmDeauthInd.deauthTrigger = eLIM_PEER_ENTITY_DEAUTH; + + + /* + * If we're in the middle of ReAssoc and received deauth from + * the ReAssoc AP, then notify SME by sending REASSOC_RSP with + * failure result code. SME will post the disconnect to the + * supplicant and the latter would start a fresh assoc. + */ + if (limIsReassocInProgress(pMac,psessionEntry)) { + /** + * AP may have 'aged-out' our Pre-auth + * context. Delete local pre-auth context + * if any and issue REASSOC_CNF to SME. + */ + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); + + if (psessionEntry->limAssocResponseData) { + vos_mem_free(psessionEntry->limAssocResponseData); + psessionEntry->limAssocResponseData = NULL; + } + + PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. " + "Issue REASSOC_CNF. "));) + /* + * TODO: Instead of overloading eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE + * it would have been good to define/use a different failure type. + * Using eSIR_SME_FT_REASSOC_FAILURE does not seem to clean-up + * properly and we end up seeing "transmit queue timeout". + */ + limPostReassocFailure(pMac, eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE, + eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + return; + } + /* reset the deauthMsgCnt here since we are able to Process + * the deauth frame and sending up the indication as well */ + if(pMac->lim.deauthMsgCnt != 0) + { + pMac->lim.deauthMsgCnt = 0; + } + if (LIM_IS_STA_ROLE(psessionEntry)) + WDA_TxAbort(psessionEntry->smeSessionId); + + lim_update_lost_link_info(pMac, psessionEntry, frame_rssi); + + /// Deauthentication from peer MAC entity + limPostSmeMessage(pMac, LIM_MLM_DEAUTH_IND, (tANI_U32 *) &mlmDeauthInd); + + // send eWNI_SME_DEAUTH_IND to SME + limSendSmeDeauthInd(pMac, pStaDs, psessionEntry); + return; + +} /*** end limProcessDeauthFrame() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c new file mode 100644 index 000000000000..4e89e3de5ce7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limProcessDisassocFrame.cc contains the code + * for processing Disassocation Frame. + * Author: Chandra Modumudi + * Date: 03/24/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "wniApi.h" +#include "sirApi.h" +#include "aniGlobal.h" +#include "wniCfgSta.h" + +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limSendMessages.h" +#include "schApi.h" + + +/** + * limProcessDisassocFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Disassociation frame reception. + * + *LOGIC: + * + *ASSUMPTIONS: + * DPH drops packets for STA with 'valid' bit in pStaDs set to '0'. + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param *pRxPacketInfo - A pointer to Rx packet info structure + * @return None + */ +void +limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +{ + tANI_U8 *pBody; + tANI_U16 aid, reasonCode; + tpSirMacMgmtHdr pHdr; + tpDphHashNode pStaDs; + tLimMlmDisassocInd mlmDisassocInd; +#ifdef WLAN_FEATURE_11W + tANI_U32 frameLen; +#endif + int8_t frame_rssi; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + frame_rssi = (int8_t)WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + + if (limIsGroupAddr(pHdr->sa)) + { + // Received Disassoc frame from a BC/MC address + // Log error and ignore it + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame from a BC/MC address"));) + + return; + } + + if (limIsGroupAddr(pHdr->da) && !limIsAddrBC(pHdr->da)) + { + // Received Disassoc frame for a MC address + // Log error and ignore it + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame for a MC address"));) + + return; + } + if (!lim_validate_received_frame_a1_addr(pMac, pHdr->da, psessionEntry)) { + limLog(pMac, LOGE, + FL("rx frame doesn't have valid a1 address, dropping it")); + return; + } + + if (LIM_IS_STA_ROLE(psessionEntry) && + (eLIM_SME_WT_DISASSOC_STATE == psessionEntry->limSmeState)) { + if (pHdr->fc.retry > 0) { + /* + * This can happen when first disassoc frame is received + * but ACK from this STA is lost, in this case 2nd disassoc frame is + * already in transmission queue + */ + PELOGE(limLog(pMac, LOGE, + FL("AP is sending disassoc after ACK lost..."));) + return; + } + + } + + +#ifdef WLAN_FEATURE_11W + /* PMF: If this session is a PMF session, then ensure that this frame was protected */ + if(psessionEntry->limRmfEnabled && (WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & DPU_FEEDBACK_UNPROTECTED_ERROR)) + { + PELOGE(limLog(pMac, LOGE, FL("received an unprotected disassoc from AP"));) + // If the frame received is unprotected, forward it to the supplicant to initiate + // an SA query + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + //send the unprotected frame indication to SME + limSendSmeUnprotectedMgmtFrameInd( pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), + psessionEntry->smeSessionId, psessionEntry); + return; + } +#endif + + // Get reasonCode from Disassociation frame body + reasonCode = sirReadU16(pBody); + + PELOGE(limLog(pMac, LOGE, + FL("Received Disassoc frame for Addr: "MAC_ADDRESS_STR"(mlm state=%s " + "sme state=%d RSSI=%d),with reason code %d [%s] from "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->da), + limMlmStateStr(psessionEntry->limMlmState), psessionEntry->limSmeState, + frame_rssi, + reasonCode, limDot11ReasonStr(reasonCode), + MAC_ADDR_ARRAY(pHdr->sa));) + + /** + * Extract 'associated' context for STA, if any. + * This is maintained by DPH and created by LIM. + */ + pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) + { + /** + * Disassociating STA is not associated. + * Log error. + */ + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame from STA that does not have context " + "reasonCode=%d, addr "MAC_ADDRESS_STR), + reasonCode,MAC_ADDR_ARRAY(pHdr->sa));) + + return; + } + + if (limCheckDisassocDeauthAckPending(pMac, (tANI_U8*)pHdr->sa)) + { + PELOGE(limLog(pMac, LOGE, + FL("Ignore the DisAssoc received, while waiting " + "for ack of disassoc/deauth"));) + limCleanUpDisassocDeauthReq(pMac,(tANI_U8*)pHdr->sa, 1); + return; + } + + /** If we are in the Wait for ReAssoc Rsp state */ + if (limIsReassocInProgress(pMac,psessionEntry)) { + /** If we had received the DisAssoc from, + * a. the Current AP during ReAssociate to different AP in same ESS + * b. Unknown AP + * drop/ignore the DisAssoc received + */ + if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) { + PELOGE(limLog(pMac, LOGE, FL("Ignore the DisAssoc received, while " + "Processing ReAssoc with different/unknown AP"));) + return; + } + /** If the Disassoc is received from the new AP to which we tried to ReAssociate + * Drop ReAssoc and Restore the Previous context( current connected AP). + */ + if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) { + PELOGW(limLog(pMac, LOGW, FL("received Disassoc from the New AP to which ReAssoc is sent "));) + limRestorePreReassocState(pMac, + eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry); + return; + } + } + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + switch (reasonCode) + { + case eSIR_MAC_UNSPEC_FAILURE_REASON: + case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON: + case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON: + case eSIR_MAC_MIC_FAILURE_REASON: + case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON: + case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON: + case eSIR_MAC_RSN_IE_MISMATCH_REASON: + case eSIR_MAC_1X_AUTH_FAILURE_REASON: + // Valid reasonCode in received Disassociation frame + break; + + default: + // Invalid reasonCode in received Disassociation frame + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame with invalid reasonCode " + "%d from "MAC_ADDRESS_STR), + reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) + break; + } + } else if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + ((psessionEntry->limSmeState != eLIM_SME_WT_JOIN_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_AUTH_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE))) { + switch (reasonCode) + { + case eSIR_MAC_UNSPEC_FAILURE_REASON: + case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON: + case eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON: + case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON: + case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON: + case eSIR_MAC_MIC_FAILURE_REASON: + case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON: + case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON: + case eSIR_MAC_RSN_IE_MISMATCH_REASON: + case eSIR_MAC_1X_AUTH_FAILURE_REASON: + case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON: + // Valid reasonCode in received Disassociation frame + break; + + case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON: + case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON: + // Valid reasonCode in received Disassociation frame + // as long as we're not about to channel switch + if(psessionEntry->gLimChannelSwitch.state != eLIM_CHANNEL_SWITCH_IDLE) + { + limLog(pMac, LOGE, + FL("Ignoring disassoc frame due to upcoming " + "channel switch, from "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); + return; + } + break; + + default: + // Invalid reasonCode in received Disassociation frame + // Log error and ignore the frame + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame with invalid reasonCode " + "%d from "MAC_ADDRESS_STR), reasonCode, + MAC_ADDR_ARRAY(pHdr->sa));) + return; + } + } + else + { + // Received Disassociation frame in either IBSS + // or un-known role. Log and ignore it + limLog(pMac, LOGE, + FL("received Disassoc frame with invalid reasonCode %d in role " + "%d in sme state %d from "MAC_ADDRESS_STR), reasonCode, + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limSmeState, + MAC_ADDR_ARRAY(pHdr->sa)); + + return; + } + + if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || + (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { + /** + * Already in the process of deleting context for the peer + * and received Disassociation frame. Log and Ignore. + */ + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame in state %d from "MAC_ADDRESS_STR + ",isDisassocDeauthInProgress : %d\n"), + pStaDs->mlmStaContext.mlmState, MAC_ADDR_ARRAY(pHdr->sa), + pStaDs->isDisassocDeauthInProgress);) + + return; + } + + if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) + { + /** + * Requesting STA is in some 'transient' state? + * Log error. + */ + if (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_ASSOC_CNF_STATE) + pStaDs->mlmStaContext.updateContext = 1; + + PELOGE(limLog(pMac, LOGE, + FL("received Disassoc frame from peer that is in state %X, addr " + MAC_ADDRESS_STR), + pStaDs->mlmStaContext.mlmState, MAC_ADDR_ARRAY(pHdr->sa));) + + } // if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) + + pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC; + pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode; + + // Issue Disassoc Indication to SME. + vos_mem_copy((tANI_U8 *) &mlmDisassocInd.peerMacAddr, + (tANI_U8 *) pStaDs->staAddr, + sizeof(tSirMacAddr)); + mlmDisassocInd.reasonCode = + (tANI_U8) pStaDs->mlmStaContext.disassocReason; + mlmDisassocInd.disassocTrigger = eLIM_PEER_ENTITY_DISASSOC; + + /* Update PE session Id */ + mlmDisassocInd.sessionId = psessionEntry->peSessionId; + + if (limIsReassocInProgress(pMac,psessionEntry)) { + + /* If we're in the middle of ReAssoc and received disassoc from + * the ReAssoc AP, then notify SME by sending REASSOC_RSP with + * failure result code. By design, SME will then issue "Disassoc" + * and cleanup will happen at that time. + */ + PELOGE(limLog(pMac, LOGE, FL("received Disassoc from AP while waiting " + "for Reassoc Rsp"));) + + if (psessionEntry->limAssocResponseData) { + vos_mem_free(psessionEntry->limAssocResponseData); + psessionEntry->limAssocResponseData = NULL; + } + + limRestorePreReassocState(pMac,eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry); + return; + } + + lim_update_lost_link_info(pMac, psessionEntry, frame_rssi); + limPostSmeMessage(pMac, LIM_MLM_DISASSOC_IND, + (tANI_U32 *) &mlmDisassocInd); + + + // send eWNI_SME_DISASSOC_IND to SME + limSendSmeDisassocInd(pMac, pStaDs,psessionEntry); + + return; +} /*** end limProcessDisassocFrame() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c new file mode 100644 index 000000000000..bc7b78d4b452 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -0,0 +1,2410 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file lim ProcessMessageQueue.cc contains the code + * for processing LIM message Queue. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "wniApi.h" +#include "wlan_qct_wda.h" + +#include "wniCfgSta.h" +#include "cfgApi.h" +#include "sirCommon.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limPropExtsUtils.h" + +#include "limAdmitControl.h" +#include "pmmApi.h" +#include "limIbssPeerMgmt.h" +#include "schApi.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "limSendMessages.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseApi.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +#include "limFT.h" +#endif + +#include "vos_types.h" +#include "vos_packet.h" +#include "vos_memory.h" + +void limLogSessionStates(tpAniSirGlobal pMac); + +/** ------------------------------------------------------------- +\fn defMsgDecision +\brief The function decides whether to defer a message or not in limProcessMessage function +\param tpAniSirGlobal pMac +\param tSirMsgQ limMsg +\param tSirMacTspecIE *ppInfo +\return none + -------------------------------------------------------------*/ + +tANI_U8 static +defMsgDecision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + + +/* this function should not changed */ + if(pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) + { + // Defer processsing this message + if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), + limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) + limLogSessionStates(pMac); + limHandleDeferMsgError(pMac, limMsg); + } + return true; + } + + //When defer is requested then defer all the messages except HAL responses. + if((!limIsSystemInScanState(pMac)) && (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) && + !pMac->lim.gLimSystemInScanLearnMode) + { + if((limMsg->type != WDA_ADD_BSS_RSP) && + (limMsg->type != WDA_DELETE_BSS_RSP) && + (limMsg->type != WDA_ADD_STA_RSP) && + (limMsg->type != WDA_ADD_STA_SELF_RSP) && + (limMsg->type != WDA_DEL_STA_SELF_RSP) && + (limMsg->type != WDA_DELETE_STA_RSP)&& + (limMsg->type != WDA_SET_BSSKEY_RSP)&& + (limMsg->type != WDA_SET_STAKEY_RSP)&& + (limMsg->type != WDA_SET_STA_BCASTKEY_RSP) && + (limMsg->type != eWNI_SME_START_REQ) && + (limMsg->type != WDA_AGGR_QOS_RSP) && + (limMsg->type != WDA_REMOVE_BSSKEY_RSP) && + (limMsg->type != WDA_REMOVE_STAKEY_RSP) && + (limMsg->type != WDA_SET_MIMOPS_RSP)&& + (limMsg->type != WDA_ADDBA_RSP) && + (limMsg->type != WDA_ENTER_BMPS_RSP) && + (limMsg->type != WDA_EXIT_BMPS_RSP) && + (limMsg->type != WDA_ENTER_IMPS_RSP) && + (limMsg->type != WDA_EXIT_IMPS_RSP) && + (limMsg->type != WDA_ENTER_UAPSD_RSP) && + (limMsg->type != WDA_EXIT_UAPSD_RSP) && + (limMsg->type != WDA_WOWL_ENTER_RSP) && + (limMsg->type != WDA_WOWL_EXIT_RSP) && + (limMsg->type != WDA_SWITCH_CHANNEL_RSP) && + (limMsg->type != WDA_P2P_NOA_ATTR_IND) && + (limMsg->type != WDA_P2P_NOA_START_IND) && +#ifdef FEATURE_OEM_DATA_SUPPORT + (limMsg->type != WDA_START_OEM_DATA_RSP) && +#endif + (limMsg->type != WDA_ADD_TS_RSP) && + /* Allow processing of RX frames while awaiting reception of + ADD TS response over the air. This logic particularly handles the + case when host sends ADD BA request to FW after ADD TS request + is sent over the air and ADD TS response received over the air */ + !(limMsg->type == SIR_BB_XPORT_MGMT_MSG && pMac->lim.gLimAddtsSent)) { + PELOG1(limLog(pMac, LOG1, FL("Defer the current message type %d , gLimProcessDefdMsgs is false and system is not in scan/learn mode"), + limMsg->type);) + + // Defer processsing this message + if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), + limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) + limLogSessionStates(pMac); + limHandleDeferMsgError(pMac, limMsg); + + } + return true; + } + } + return false; +} + +#ifdef FEATURE_WLAN_EXTSCAN +static void +__lim_pno_match_fwd_bcn_probepsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, + tSirProbeRespBeacon *frame, uint32_t ie_len, + uint32_t msg_type) +{ + struct pno_match_found *result; + uint8_t *body; + tSirMsgQ mmh_msg; + tpSirMacMgmtHdr hdr; + uint32_t num_results = 1, len, i; + + /* Upon receiving every matched beacon, bss info is forwarded to the + * the upper layer, hence num_results is set to 1 */ + len = sizeof(*result) + (num_results * sizeof(tSirWifiScanResult)) + + ie_len; + + result = vos_mem_malloc(len); + if (NULL == result) { + limLog(pmac, LOGE, FL("Memory allocation failed")); + return; + } + hdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info); + body = WDA_GET_RX_MPDU_DATA(rx_pkt_info); + vos_mem_zero(result, sizeof(*result) + ie_len); + + /* Received frame does not have request id, hence set 0 */ + result->request_id = 0; + result->more_data = 0; + result->num_results = num_results; + + for (i = 0; i < result->num_results; i++) { + result->ap[i].ts = vos_timer_get_system_time(); + result->ap[i].beaconPeriod = frame->beaconInterval; + result->ap[i].capability = + limGetU16((uint8_t *)&frame->capabilityInfo); + result->ap[i].channel = WDA_GET_RX_CH(rx_pkt_info); + result->ap[i].rssi = WDA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); + result->ap[i].rtt = 0; + result->ap[i].rtt_sd = 0; + result->ap[i].ieLength = ie_len; + vos_mem_copy((uint8_t *) &result->ap[i].ssid[0], + (uint8_t *) frame->ssId.ssId, frame->ssId.length); + result->ap[i].ssid[frame->ssId.length] = '\0'; + vos_mem_copy((uint8_t *) &result->ap[i].bssid, + (uint8_t *) hdr->bssId, + sizeof(tSirMacAddr)); + /* Copy IE fields */ + vos_mem_copy((uint8_t *) &result->ap[i].ieData, + body + SIR_MAC_B_PR_SSID_OFFSET, ie_len); + } + + mmh_msg.type = msg_type; + mmh_msg.bodyptr = result; + mmh_msg.bodyval = 0; + limSysProcessMmhMsgApi(pmac, &mmh_msg, ePROT); +} + +static void +__limExtScanForwardBcnProbeRsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, + tSirProbeRespBeacon *frame, uint32_t ie_len, + uint32_t msg_type) +{ + tpSirWifiFullScanResultEvent result; + uint8_t *body; + tSirMsgQ mmh_msg; + tpSirMacMgmtHdr hdr; + + result = vos_mem_malloc(sizeof(*result) + ie_len); + if (NULL == result) { + limLog(pmac, LOGE, FL("Memory allocation failed")); + return; + } + hdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info); + body = WDA_GET_RX_MPDU_DATA(rx_pkt_info); + vos_mem_zero(result, sizeof(*result) + ie_len); + + /* Received frame does not have request id, hence set 0 */ + result->requestId = 0; + + result->moreData = 0; + result->ap.ts = vos_timer_get_system_time(); + result->ap.beaconPeriod = frame->beaconInterval; + result->ap.capability = limGetU16((uint8_t *)&frame->capabilityInfo); + result->ap.channel = WDA_GET_RX_CH(rx_pkt_info); + result->ap.rssi = WDA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); + result->ap.rtt = 0; + result->ap.rtt_sd = 0; + result->ap.ieLength = ie_len; + + vos_mem_copy((uint8_t *) &result->ap.ssid[0], + (uint8_t *) frame->ssId.ssId, frame->ssId.length); + result->ap.ssid[frame->ssId.length] = '\0'; + vos_mem_copy((uint8_t *) &result->ap.bssid, (uint8_t *) hdr->bssId, + sizeof(tSirMacAddr)); + /* Copy IE fields */ + vos_mem_copy((uint8_t *) &result->ap.ieData, + body + SIR_MAC_B_PR_SSID_OFFSET, ie_len); + + mmh_msg.type = msg_type; + mmh_msg.bodyptr = result; + mmh_msg.bodyval = 0; + limSysProcessMmhMsgApi(pmac, &mmh_msg, ePROT); +} + +static void +__limProcessExtScanBeaconProbeRsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, + uint8_t sub_type) +{ + tSirProbeRespBeacon *frame; + uint8_t *body; + uint32_t frm_len; + tSirRetStatus status; + + frm_len = WDA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + if (frm_len <= SIR_MAC_B_PR_SSID_OFFSET) { + limLog(pmac, LOGP, + FL("RX packet has invalid length %d"), frm_len); + return; + } + + frame = vos_mem_malloc(sizeof(*frame)); + if (NULL == frame) { + limLog(pmac, LOGE, FL("Memory allocation failed")); + return; + } + + if (sub_type == SIR_MAC_MGMT_BEACON) { + limLog(pmac, LOG2, FL("Beacon due to ExtScan/epno")); + status = sirConvertBeaconFrame2Struct(pmac, + (uint8_t *)rx_pkt_info, + frame); + } else if (sub_type == SIR_MAC_MGMT_PROBE_RSP) { + limLog(pmac, LOG2, FL("Probe Rsp due to ExtScan/epno")); + body = WDA_GET_RX_MPDU_DATA(rx_pkt_info); + status = sirConvertProbeFrame2Struct(pmac, body, + frm_len, frame); + } else { + vos_mem_free(frame); + return; + } + + if (status != eSIR_SUCCESS) { + limLog(pmac, LOGE, FL("Frame parsing failed")); + vos_mem_free(frame); + return; + } + + if (WMA_IS_EXTSCAN_SCAN_SRC(rx_pkt_info)) + __limExtScanForwardBcnProbeRsp(pmac, rx_pkt_info, frame, + (frm_len - SIR_MAC_B_PR_SSID_OFFSET), + eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND); + + if (WMA_IS_EPNO_SCAN_SRC(rx_pkt_info)) + __lim_pno_match_fwd_bcn_probepsp(pmac, rx_pkt_info, frame, + (frm_len - SIR_MAC_B_PR_SSID_OFFSET), + eWNI_SME_EPNO_NETWORK_FOUND_IND); + + vos_mem_free(frame); +} +#endif + + +/* +* Beacon Handling Cases: +* during scanning, when no session is active: +* handled by limHandleFramesInScanState before __limHandleBeacon call is invoked. +* during scanning, when any session is active, but beacon/Pr does not belong to that session, psessionEntry will be null. +* handled by limHandleFramesInScanState before __limHandleBeacon call is invoked. +* during scanning, when any session is active, and beacon/Pr belongs to one of the session, psessionEntry will not be null. +* handled by limHandleFramesInScanState before __limHandleBeacon call is invoked. +* Not scanning, no session: +* there should not be any beacon coming, if coming, should be dropped. +* Not Scanning, +*/ +static void +__limHandleBeacon(tpAniSirGlobal pMac, tpSirMsgQ pMsg, tpPESession psessionEntry) +{ + /* checking for global SME state...*/ + tANI_U8 *pRxPacketInfo; + limGetBDfromRxPacket(pMac, pMsg->bodyptr, (tANI_U32 **)&pRxPacketInfo); + + //This function should not be called if beacon is received in scan state. + //So not doing any checks for the global state. + + if(psessionEntry == NULL) + { + schBeaconProcess(pMac, pRxPacketInfo, NULL); + } + else if( (psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE) || + (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE)) + { + schBeaconProcess(pMac, pRxPacketInfo, psessionEntry); + } + else + limProcessBeaconFrame(pMac, pRxPacketInfo, psessionEntry); + + return; +} + + +//Fucntion prototype +void limProcessNormalHddMsg(tpAniSirGlobal pMac, tSirMsgQ *pLimMsg, tANI_U8 fRspReqd); + +/** + * limDeferMsg() + * + *FUNCTION: + * This function is called to defer the messages received + * during Learn mode + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pMsg of type tSirMsgQ - Pointer to the message structure + * @return None + */ + +tANI_U32 +limDeferMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + tANI_U32 retCode = TX_SUCCESS; + + retCode = limWriteDeferredMsgQ(pMac, pMsg); + + if (retCode == TX_SUCCESS) + { + limLog(pMac, LOG1, + FL("Deferred message(0x%X) limSmeState %d (prev sme state %d)" + " sysRole %d mlm state %d (prev mlm state %d)"), + pMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, + pMac->lim.gLimPrevMlmState); + MTRACE(macTraceMsgRx(pMac, NO_SESSION, LIM_TRACE_MAKE_RXMSG(pMsg->type, LIM_MSG_DEFERRED));) + } + else + { + limLog(pMac, LOG1, FL("Dropped lim message (0x%X)"), pMsg->type); + MTRACE(macTraceMsgRx(pMac, NO_SESSION, LIM_TRACE_MAKE_RXMSG(pMsg->type, LIM_MSG_DROPPED));) + } + + return retCode; +} /*** end limDeferMsg() ***/ + + + +/** + * limHandleFramesInScanState() + * + *FUNCTION: + * This function is called to process 802.11 frames + * received by LIM in scan state. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param limMsg - Received message + * @param pRxPacketInfo - Pointer to Rx packet info structure + * @param deferMsg - Indicates whether the frame shall be deferred + * @return None + */ + +static void +limHandleFramesInScanState(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pRxPacketInfo, tANI_U8 *deferMsg, tpPESession psessionEntry) +{ + tSirMacFrameCtl fc; + tpSirMacMgmtHdr pHdr; + + *deferMsg = false; + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + fc = pHdr->fc; + limLog( pMac, LOG2, FL("ProtVersion %d, Type %d, Subtype %d"), + fc.protVer, fc.type, fc.subType ); + + // defer all message in scan state except for Beacons and Probe Response + if ((fc.type == SIR_MAC_MGMT_FRAME) && (fc.subType == SIR_MAC_MGMT_BEACON)) + { + if (psessionEntry == NULL) + limProcessBeaconFrameNoSession(pMac, pRxPacketInfo); + else + limProcessBeaconFrame(pMac, pRxPacketInfo,psessionEntry); + } + else if ((fc.type == SIR_MAC_MGMT_FRAME) && (fc.subType == SIR_MAC_MGMT_PROBE_RSP)) + { + if (psessionEntry == NULL) + limProcessProbeRspFrameNoSession(pMac, pRxPacketInfo); + else + limProcessProbeRspFrame(pMac, pRxPacketInfo,psessionEntry); + } + else if ((fc.type == SIR_MAC_MGMT_FRAME) && (fc.subType == SIR_MAC_MGMT_PROBE_REQ)) + { + limProcessProbeReqFrame_multiple_BSS(pMac, pRxPacketInfo, psessionEntry); + } + else if ((fc.type == SIR_MAC_MGMT_FRAME) && (fc.subType == SIR_MAC_MGMT_ACTION)) + { + limProcessActionFrameNoSession( pMac, pRxPacketInfo); + } + else + { + *deferMsg = true; + return; + } + + limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr); + return; + +} /*** end limHandleFramesInScanState() ***/ + +/** ------------------------------------------------------------ +\brief This function handles Unknown Unicast (A2 Index) +\ packets. +\param tpAniSirGlobal pMac Global Mac data structure +\param void *pRxPacketInfo Pointer to Buffer Descriptor +\return none +\ +\ -------------------------------------------------------------- */ +static void limHandleUnknownA2IndexFrames(tpAniSirGlobal pMac, void *pRxPacketInfo,tpPESession psessionEntry) +{ + /* addr2 mismatch interrupt occurred this means previous + disassociation was not successful + In Volans pRxPacketInfo only contains pointer 48-bit address2 field */ + /*Send disassociation message again*/ + //Dinesh need one more arguement. + //limSendDisassocMgmtFrame(pMac, eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON,(tANI_U8 *) pRxPacketInfo); + //TODO: verify this + //This could be a public action frame. + if (LIM_IS_P2P_DEVICE_ROLE(psessionEntry)) + limProcessActionFrameNoSession(pMac, (tANI_U8 *) pRxPacketInfo); + +#ifdef FEATURE_WLAN_TDLS + { + tpSirMacDataHdr3a pMacHdr; + pMacHdr = WDA_GET_RX_MPDUHEADER3A(pRxPacketInfo); + + if (limIsGroupAddr(pMacHdr->addr2)) + { + PELOG2(limLog(pMac, LOG2, FL("Ignoring A2 Invalid Packet received for MC/BC:")); + limPrintMacAddr(pMac, pMacHdr->addr2, LOG2);) + + return; + } + /* TDLS_hklee: move down here to reject Addr2 == Group (first checking above) + and also checking if SystemRole == STA */ + if (LIM_IS_STA_ROLE(psessionEntry)) + { + /* ADD handling of Public Action Frame */ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + ("limHandleUnknownA2IndexFrames: type=0x%x, subtype=0x%x"), + pMacHdr->fc.type, pMacHdr->fc.subType)); + switch (pMacHdr->fc.type) + { + case SIR_MAC_MGMT_FRAME: + { + switch (pMacHdr->fc.subType) + { + case SIR_MAC_MGMT_ACTION: + { + limProcessActionFrame(pMac, pRxPacketInfo, psessionEntry) ; + break ; + } + default: + { + break ; + } + } + } + default: + { + break ; + } + } + } + } +#endif + + + return; +} + +/** + * limCheckMgmtRegisteredFrames() + * + *FUNCTION: + * This function is called to process to check if received frame match with + * any of the registered frame from HDD. If yes pass this frame to SME. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pBd Pointer to the received Buffer Descriptor+payload + * @param *psessionEntry Pointer to session on which packet is received + * @return None + */ +static tANI_BOOLEAN +limCheckMgmtRegisteredFrames(tpAniSirGlobal pMac, tANI_U8 *pBd, + tpPESession psessionEntry) +{ + tSirMacFrameCtl fc; + tpSirMacMgmtHdr pHdr; + tANI_U8 *pBody; + tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL, pNext = NULL; + tANI_U16 frameType; + tANI_U16 framelen; + tANI_U8 type,subType; + tANI_BOOLEAN match = VOS_FALSE; + VOS_STATUS vosStatus; + + pHdr = WDA_GET_RX_MAC_HEADER(pBd); + fc = pHdr->fc; + frameType = (fc.type << 2 ) | (fc.subType << 4); + pBody = WDA_GET_RX_MPDU_DATA(pBd); + framelen = WDA_GET_RX_PAYLOAD_LEN(pBd); + + vos_list_peek_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, + (vos_list_node_t**)&pLimMgmtRegistration); + + while(pLimMgmtRegistration != NULL) + { + type = (pLimMgmtRegistration->frameType >> 2) & 0x03; + subType = (pLimMgmtRegistration->frameType >> 4) & 0x0f; + if ( (type == SIR_MAC_MGMT_FRAME) && (fc.type == SIR_MAC_MGMT_FRAME) + && (subType == SIR_MAC_MGMT_RESERVED15) ) + { + limLog( pMac, LOG3, + FL("rcvd frame match with SIR_MAC_MGMT_RESERVED15")); + match = VOS_TRUE; + break; + } + + if (pLimMgmtRegistration->frameType == frameType) + { + if (pLimMgmtRegistration->matchLen > 0) + { + if (pLimMgmtRegistration->matchLen <= framelen) + { + if (vos_mem_compare(pLimMgmtRegistration->matchData, + pBody, pLimMgmtRegistration->matchLen)) + { + /* found match! */ + match = VOS_TRUE; + break; + } + } + } + else + { + /* found match! */ + match = VOS_TRUE; + break; + } + } + + vosStatus = + vos_list_peek_next ( &pMac->lim.gLimMgmtFrameRegistratinQueue, + (vos_list_node_t*) pLimMgmtRegistration, + (vos_list_node_t**) &pNext ); + pLimMgmtRegistration = pNext; + pNext = NULL; + } + + if (match) + { + limLog( pMac, LOG1, + FL("rcvd frame match with registered frame params")); + + /* Indicate this to SME */ + limSendSmeMgmtFrameInd( pMac, pHdr->fc.subType, (tANI_U8*)pHdr, + WDA_GET_RX_PAYLOAD_LEN(pBd) + sizeof(tSirMacMgmtHdr), + pLimMgmtRegistration->sessionId, + WDA_GET_RX_CH(pBd), psessionEntry, 0); + + if ( (type == SIR_MAC_MGMT_FRAME) && (fc.type == SIR_MAC_MGMT_FRAME) + && (subType == SIR_MAC_MGMT_RESERVED15) ) + { + // These packets needs to be processed by PE/SME as well as HDD. + // If it returns TRUE here, the packet is forwarded to HDD only. + match = VOS_FALSE; + } + } + + return match; +} /*** end limCheckMgmtRegisteredFrames() ***/ + + +/** + * limHandle80211Frames() + * + *FUNCTION: + * This function is called to process 802.11 frames + * received by LIM. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pMsg of type tSirMsgQ - Pointer to the message structure + * @return None + */ + +static void +limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) +{ + tANI_U8 *pRxPacketInfo = NULL; + tSirMacFrameCtl fc; + tpSirMacMgmtHdr pHdr=NULL; + tpPESession psessionEntry=NULL; + tANI_U8 sessionId; + tAniBool isFrmFt = FALSE; + tANI_U16 fcOffset = WLANHAL_RX_BD_HEADER_SIZE; + + *pDeferMsg= false; + limGetBDfromRxPacket(pMac, limMsg->bodyptr, (tANI_U32 **)&pRxPacketInfo); + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + isFrmFt = WDA_GET_RX_FT_DONE(pRxPacketInfo); + fcOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(pRxPacketInfo); + fc = pHdr->fc; + +#ifdef WLAN_DUMP_MGMTFRAMES + limLog( pMac, LOGE, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), + fc.protVer, fc.type, fc.subType, + WDA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, pHdr, + WDA_GET_RX_MPDU_HEADER_LEN(pRxPacketInfo)); +#endif + if (pMac->fEnableDebugLog & 0x1) { + if ((fc.type == SIR_MAC_MGMT_FRAME) && + (fc.subType != SIR_MAC_MGMT_PROBE_REQ) && + (fc.subType != SIR_MAC_MGMT_PROBE_RSP) && + (fc.subType != SIR_MAC_MGMT_BEACON)) + { + limLog(pMac, LOGE, FL("RX MGMT - Type %hu, SubType %hu"), + fc.type, fc.subType); + } + } +#ifdef FEATURE_WLAN_EXTSCAN + if (WMA_IS_EXTSCAN_SCAN_SRC(pRxPacketInfo) || + WMA_IS_EPNO_SCAN_SRC(pRxPacketInfo)) { + if (fc.subType == SIR_MAC_MGMT_BEACON || + fc.subType == SIR_MAC_MGMT_PROBE_RSP) { + __limProcessExtScanBeaconProbeRsp(pMac, pRxPacketInfo, fc.subType); + } else { + limLog(pMac, LOGE, FL("Wrong frameType %d, Subtype %d for %d"), + fc.type, fc.subType, WMA_GET_SCAN_SRC(pRxPacketInfo)); + } + goto end; + } +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if ( WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + { + limLog(pMac, LOG2, FL("Notify SME with candidate ind")); + limSendSmeCandidateFoundInd(pMac, WDA_GET_SESSIONID(pRxPacketInfo)); + goto end; + } + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + if (fc.subType == SIR_MAC_MGMT_BEACON) + { + limLog( pMac, LOG2, FL("Save this beacon in LFR cache")); + __limHandleBeacon(pMac, limMsg, NULL); + } + else if (fc.subType == SIR_MAC_MGMT_PROBE_RSP) + { + limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache")); + limProcessProbeRspFrameNoSession(pMac, pRxPacketInfo); + } + else + { + limLog( pMac, LOGE, FL("Wrong frame Type %d, Subtype %d for LFR"), + fc.type, fc.subType); + } + goto end; + } +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + if (fc.type == SIR_MAC_DATA_FRAME && isFrmFt) + { + limLog(pMac, LOGE, + FL("Need to port handling of IAPP frames to QCACLD for ESE")); + } else +#endif + /* Added For BT-AMP Support */ + if((psessionEntry = peFindSessionByBssid(pMac,pHdr->bssId,&sessionId))== NULL) + { +#ifdef WLAN_FEATURE_VOWIFI_11R + if (fc.subType == SIR_MAC_MGMT_AUTH) + { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog( pMac, LOG1, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), + fc.protVer, fc.type, fc.subType, WDA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); + limPrintMacAddr(pMac, pHdr->bssId, LOG1); +#endif + if (limProcessAuthFrameNoSession(pMac, pRxPacketInfo, limMsg->bodyptr) == eSIR_SUCCESS) + { + goto end; + } + } +#endif + if((fc.subType != SIR_MAC_MGMT_PROBE_RSP )&& + (fc.subType != SIR_MAC_MGMT_BEACON)&& + (fc.subType != SIR_MAC_MGMT_PROBE_REQ) + && (fc.subType != SIR_MAC_MGMT_ACTION ) //Public action frame can be received from non-associated stations. + ) + { + + if((psessionEntry = peFindSessionByPeerSta(pMac,pHdr->sa,&sessionId))== NULL) + { + limLog(pMac, LOG1, FL("session does not exist for given bssId")); + goto end; + } + else + limLog(pMac,LOG1,"SessionId:%d Session Exist for given Bssid", + psessionEntry->peSessionId); + } + // For p2p resp frames search for valid session with DA as + // BSSID will be SA and session will be present with DA only + if(fc.subType == SIR_MAC_MGMT_ACTION ) + { + psessionEntry = peFindSessionByBssid(pMac,pHdr->da,&sessionId); + } + } + + + /* Check if frame is registered by HDD */ + if(limCheckMgmtRegisteredFrames(pMac, pRxPacketInfo, psessionEntry)) + { + limLog( pMac, LOG1, FL("Received frame is passed to SME")); + goto end; + } + + + + if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) + { // Received Frame with non-zero Protocol Version + limLog(pMac, LOGE, FL("Unexpected frame with protVersion %d received"), + fc.protVer); +#ifdef WLAN_DEBUG + pMac->lim.numProtErr++; +#endif + goto end; + } + + if (!pMac->fScanOffload) + { + if (limIsSystemInScanState(pMac)) + { + limHandleFramesInScanState(pMac, limMsg, pRxPacketInfo, pDeferMsg, psessionEntry); + return; + } + } + +/* Chance of crashing : to be done BT-AMP ........happens when broadcast probe req is received */ + +#ifdef WLAN_DEBUG + pMac->lim.numMAC[fc.type][fc.subType]++; +#endif + + switch (fc.type) + { + case SIR_MAC_MGMT_FRAME: + { + // Received Management frame + switch (fc.subType) + { + case SIR_MAC_MGMT_ASSOC_REQ: + // Make sure the role supports Association + if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry)) + limProcessAssocReqFrame(pMac, pRxPacketInfo, LIM_ASSOC, psessionEntry); + else { + // Unwanted messages - Log error + limLog(pMac, LOGE, FL("unexpected message received %X"),limMsg->type); + } + break; + + case SIR_MAC_MGMT_ASSOC_RSP: + limProcessAssocRspFrame(pMac, pRxPacketInfo, LIM_ASSOC,psessionEntry); + break; + + case SIR_MAC_MGMT_REASSOC_REQ: + // Make sure the role supports Reassociation + if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry)) { + limProcessAssocReqFrame(pMac, pRxPacketInfo, LIM_REASSOC, psessionEntry); + } else { + // Unwanted messages - Log error + limLog(pMac, LOGE, FL("unexpected message received %X"),limMsg->type); + } + break; + + case SIR_MAC_MGMT_REASSOC_RSP: + limProcessAssocRspFrame(pMac, pRxPacketInfo, LIM_REASSOC,psessionEntry); + break; + + case SIR_MAC_MGMT_PROBE_REQ: + limProcessProbeReqFrame_multiple_BSS(pMac, pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_MGMT_PROBE_RSP: + if(psessionEntry == NULL) + limProcessProbeRspFrameNoSession(pMac, pRxPacketInfo); + else + limProcessProbeRspFrame(pMac, pRxPacketInfo, psessionEntry); + break; + + case SIR_MAC_MGMT_BEACON: + __limHandleBeacon(pMac, limMsg,psessionEntry); + break; + + case SIR_MAC_MGMT_DISASSOC: + limProcessDisassocFrame(pMac, pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_MGMT_AUTH: + limProcessAuthFrame(pMac, pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_MGMT_DEAUTH: + limProcessDeauthFrame(pMac, pRxPacketInfo,psessionEntry); + break; + + case SIR_MAC_MGMT_ACTION: + if(psessionEntry == NULL) + limProcessActionFrameNoSession(pMac, pRxPacketInfo); + else + { + if (WDA_GET_RX_UNKNOWN_UCAST(pRxPacketInfo)) + limHandleUnknownA2IndexFrames(pMac, pRxPacketInfo,psessionEntry); + else + limProcessActionFrame(pMac, pRxPacketInfo,psessionEntry); + } + break; + default: + // Received Management frame of 'reserved' subtype + break; + } // switch (fc.subType) + + } + break; + case SIR_MAC_DATA_FRAME: + { +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + /* We accept data frame (IAPP frame) only if Session is + * present and ese connection is established on that + * session + */ + if (psessionEntry && psessionEntry->isESEconnection) { + limProcessIappFrame(pMac, pRxPacketInfo, psessionEntry); + } +#endif + } + break; + default: + // Received frame of type 'reserved' + break; + + } // switch (fc.type) + +end: + limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr) ; + return; +} /*** end limHandle80211Frames() ***/ + +/** + * limSendStopScanOffloadReq() + * + *FUNCTION: + * This function will be called to abort the ongoing offloaded scan + * request. + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return eHAL_STATUS_SUCCESS or eHAL_STATUS_FAILURE + */ +eHalStatus limSendStopScanOffloadReq(tpAniSirGlobal pMac, tANI_U8 SessionId) +{ + tSirMsgQ msg; + tSirRetStatus rc = eSIR_SUCCESS; + tAbortScanParams *pAbortScanParams; + + pAbortScanParams = vos_mem_malloc(sizeof(tAbortScanParams)); + if (NULL == pAbortScanParams) + { + limLog(pMac, LOGP, FL("Memory allocation failed for AbortScanParams")); + return eHAL_STATUS_FAILURE; + } + + pAbortScanParams->SessionId = SessionId; + msg.type = WDA_STOP_SCAN_OFFLOAD_REQ; + msg.bodyptr = pAbortScanParams; + msg.bodyval = 0; + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("wdaPostCtrlMsg() return failure")); + vos_mem_free(pAbortScanParams); + return eHAL_STATUS_FAILURE; + } + + limLog(pMac, LOG1, FL("Abort ongoing offload scan.")); + return eHAL_STATUS_SUCCESS; + +} + +/** + * limProcessAbortScanInd() + * + *FUNCTION: + * This function is called from HDD to abort the scan which is presently being run + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +void +limProcessAbortScanInd(tpAniSirGlobal pMac, tANI_U8 SessionId) +{ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_SCAN_ABORT_IND_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /* Deactivate the gLimBackgroundScanTimer as part of the abort scan. + * SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD indication + * to start the background scan again + */ + PELOG2(limLog(pMac, LOG2, FL("Processing AbortScan Ind"));) + + limAbortBackgroundScan(pMac); + + if (pMac->fScanOffload) + { + /* send stop scan cmd to fw if scan offload is enabled. */ + limSendStopScanOffloadReq(pMac, SessionId); + } + else + { + /* Abort the scan if its running, else just return */ + if(limIsSystemInScanState(pMac)) + { + if( (eLIM_HAL_INIT_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState ) || + (eLIM_HAL_START_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState ) || + (eLIM_HAL_END_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState ) || + (eLIM_HAL_FINISH_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState) ) + { + //Simply signal we need to abort + limLog( pMac, LOGW, FL(" waiting for HAL, simply signal abort gLimHalScanState = %d"), pMac->lim.gLimHalScanState ); + pMac->lim.abortScan = 1; + } + else + { + //Force abort + limLog( pMac, LOGW, FL(" Force aborting scan") ); + pMac->lim.abortScan = 0; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + } + } + } + return; +} + +/** + * limMessageProcessor + * + *FUNCTION: + * Wrapper function for limProcessMessages when handling messages received by LIM. + * Could either defer messages or process them. + * @param pMac Pointer to Global MAC structure + * @param limMsg Received LIM message + * @return None + */ + +void limMessageProcessor(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + if (eLIM_MLM_OFFLINE_STATE == pMac->lim.gLimMlmState) + { + peFreeMsg(pMac, limMsg); + return; + } + + if (!defMsgDecision(pMac, limMsg)) + { + limProcessMessages(pMac, limMsg); + // process deferred message queue if allowed + { + if ( (! (pMac->lim.gLimAddtsSent)) + && + (! (limIsSystemInScanState(pMac))) + ) + { + if (true == GET_LIM_PROCESS_DEFD_MESGS(pMac)) + limProcessDeferredMessageQueue(pMac); + } + } + } +} + +#ifdef FEATURE_OEM_DATA_SUPPORT + +void limOemDataRspHandleResumeLinkRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32* mlmOemDataRsp) +{ + if(status != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGE, FL("OEM Data Rsp failed to get the response for resume link")); + } + + if(NULL != pMac->lim.gpLimMlmOemDataReq) + { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq); + pMac->lim.gpLimMlmOemDataReq = NULL; + } + + //"Failure" status doesn't mean that Oem Data Rsp did not happen + //and hence we need to respond to upper layers. Only Resume link is failed, but + //we got the oem data response already. + //Post the meessage to MLM + limPostSmeMessage(pMac, LIM_MLM_OEM_DATA_CNF, (tANI_U32*)(mlmOemDataRsp)); + + return; +} + +void limProcessOemDataRsp(tpAniSirGlobal pMac, tANI_U32* body) +{ + tpLimMlmOemDataRsp mlmOemDataRsp = NULL; + + //Process all the messages for the lim queue + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + mlmOemDataRsp = (tpLimMlmOemDataRsp) body; + + PELOG1(limLog(pMac, LOG1, FL("%s: sending oem data response msg to sme"), + __func__);) + limPostSmeMessage(pMac, LIM_MLM_OEM_DATA_CNF, (tANI_U32*)(mlmOemDataRsp)); + + return; +} + +#endif + +/** + * limProcessMessages + * + *FUNCTION: + * This function is called by limProcessMessageQueue function. This + * function processes messages received by LIM. + * + *LOGIC: + * Depending on the message type, corresponding function will be + * called, for example limProcessSmeMessages() will be called to + * process SME messages received from HDD/Upper layer software module. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param limMsg Received LIM message + * @return None + */ + +void +limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + uint8_t vdev_id = 0; + uint8_t i; + tpPESession session_entry = NULL; + tUpdateBeaconParams beacon_params; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + tANI_U8 deferMsg = false; + tLinkStateParams *linkStateParams; +#if defined WLAN_FEATURE_VOWIFI_11R + tpPESession pSession; +#endif + if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) { + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + if (limMsg == NULL) + { + limLog(pMac, LOGE, FL("Message pointer is Null")); + VOS_ASSERT(0); + return; + } +#ifdef WLAN_DEBUG + pMac->lim.numTot++; +#endif + + MTRACE(macTraceMsgRx(pMac, NO_SESSION, LIM_TRACE_MAKE_RXMSG(limMsg->type, LIM_MSG_PROCESSED));) + + switch (limMsg->type) + { + + case SIR_LIM_UPDATE_BEACON: + limUpdateBeacon(pMac); + break; + + case SIR_CFG_PARAM_UPDATE_IND: + /// CFG parameter updated + if (limIsSystemInScanState(pMac)) + { + // System is in DFS (Learn) mode + // Defer processsing this message + if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) + { + if(!(pMac->lim.deferredMsgCnt & 0xF)) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), + limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) + } + limLogSessionStates(pMac); + } + } + else + { + limHandleCFGparamUpdate(pMac, limMsg->bodyval); + } + + break; + + case WDA_INIT_SCAN_RSP: + limProcessInitScanRsp(pMac, limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case WDA_START_SCAN_RSP: + limProcessStartScanRsp(pMac, limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case WDA_END_SCAN_RSP: + limProcessEndScanRsp(pMac, limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case WDA_FINISH_SCAN_RSP: + limProcessFinishScanRsp(pMac, limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case WDA_START_OEM_DATA_RSP: + limProcessOemDataRsp(pMac, limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; +#endif + + case WDA_SWITCH_CHANNEL_RSP: + limProcessSwitchChannelRsp(pMac, limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + +#ifdef ANI_SIR_IBSS_PEER_CACHING + case WDA_IBSS_STA_ADD: + limIbssStaAdd(pMac, limMsg->bodyptr); + break; +#endif + case SIR_BB_XPORT_MGMT_MSG: + // These messages are from Peer MAC entity. +#ifdef WLAN_DEBUG + pMac->lim.numBbt++; +#endif + + { + v_U16_t pktLen = 0; + vos_pkt_t *pVosPkt; + VOS_STATUS vosStatus; + tSirMsgQ limMsgNew; + + /* The original limMsg which we were deferring have the + * bodyPointer point to 'BD' instead of 'Vos pkt'. If we don't make a copy + * of limMsg, then vos_pkt_peek_data will overwrite the limMsg->bodyPointer. + * and next time when we try to process the msg, we will try to use 'BD' as + * 'Vos Pkt' which will cause a crash + */ + if (limMsg->bodyptr == NULL) + { + limLog(pMac, LOGE, FL("Message bodyptr is Null")); + VOS_ASSERT(0); + break; + } + vos_mem_copy((tANI_U8*)&limMsgNew, (tANI_U8*)limMsg, + sizeof(tSirMsgQ)); + pVosPkt = (vos_pkt_t *)limMsgNew.bodyptr; + vos_pkt_get_packet_length(pVosPkt, &pktLen); + + vosStatus = WDA_DS_PeekRxPacketInfo( pVosPkt, (v_PVOID_t *)&limMsgNew.bodyptr, VOS_FALSE ); + + if( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + vos_pkt_return_packet(pVosPkt); + break; + + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (WDA_GET_ROAMCANDIDATEIND(limMsgNew.bodyptr)) + limLog(pMac, LOG1, FL("roamCandidateInd %d"), + WDA_GET_ROAMCANDIDATEIND(limMsgNew.bodyptr)); + + if (WDA_GET_OFFLOADSCANLEARN(limMsgNew.bodyptr)) + limLog(pMac, LOG1, FL("offloadScanLearn %d"), + WDA_GET_OFFLOADSCANLEARN(limMsgNew.bodyptr)); +#endif + + limHandle80211Frames(pMac, &limMsgNew, &deferMsg); + + if ( deferMsg == true ) + { + PELOG1(limLog(pMac, LOG1, FL("Defer message type=%X "), limMsg->type);) + if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), + limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) + limLogSessionStates(pMac); + vos_pkt_return_packet(pVosPkt); + } + } + else + { + /* PE is not deferring this 802.11 frame so we need to call vos_pkt_return. + * Asumption here is when Rx mgmt frame processing is done, + * voss packet could be freed here. + */ + vos_pkt_return_packet(pVosPkt); + } + } + break; + + case eWNI_SME_SCAN_REQ: + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + case eWNI_SME_DISASSOC_REQ: + case eWNI_SME_DEAUTH_REQ: + case eWNI_SME_GET_SCANNED_CHANNEL_REQ: +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: +#endif +#ifdef FEATURE_WLAN_TDLS + case eWNI_SME_TDLS_SEND_MGMT_REQ: + case eWNI_SME_TDLS_ADD_STA_REQ: + case eWNI_SME_TDLS_DEL_STA_REQ: + case eWNI_SME_TDLS_LINK_ESTABLISH_REQ: +#endif + case eWNI_SME_RESET_AP_CAPS_CHANGED: + // These messages are from HDD + limProcessNormalHddMsg(pMac, limMsg, true); //need to response to hdd + break; + + case eWNI_SME_SCAN_ABORT_IND: + { + tSirMbMsg *pMsg = limMsg->bodyptr; + tANI_U8 sessionId; + if (pMsg) + { + sessionId = (tANI_U8) pMsg->data[0]; + limProcessAbortScanInd(pMac, sessionId); + vos_mem_free((v_VOID_t *)limMsg->bodyptr); + limMsg->bodyptr = NULL; + } + } + break; + case eWNI_SME_PDEV_SET_HT_VHT_IE: + case eWNI_SME_START_REQ: + case eWNI_SME_SYS_READY_IND: + case eWNI_SME_JOIN_REQ: + case eWNI_SME_REASSOC_REQ: + case eWNI_SME_START_BSS_REQ: + case eWNI_SME_STOP_BSS_REQ: + case eWNI_SME_SWITCH_CHL_REQ: + case eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ: + case eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ: + case eWNI_SME_SETCONTEXT_REQ: + case eWNI_SME_REMOVEKEY_REQ: + case eWNI_SME_DISASSOC_CNF: + case eWNI_SME_DEAUTH_CNF: + case eWNI_SME_ASSOC_CNF: + case eWNI_SME_REASSOC_CNF: + case eWNI_SME_ADDTS_REQ: + case eWNI_SME_DELTS_REQ: + case eWNI_SME_DEL_BA_PEER_IND: + case eWNI_SME_SET_TX_POWER_REQ: + case eWNI_SME_GET_TX_POWER_REQ: + case eWNI_SME_GET_NOISE_REQ: + case eWNI_SME_GET_ASSOC_STAS_REQ: + case eWNI_SME_TKIP_CNTR_MEAS_REQ: + case eWNI_SME_UPDATE_APWPSIE_REQ: + case eWNI_SME_HIDE_SSID_REQ: + case eWNI_SME_GET_WPSPBC_SESSION_REQ: + case eWNI_SME_SET_APWPARSNIEs_REQ: + case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: +#if defined WLAN_FEATURE_VOWIFI + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: +#endif +#if defined FEATURE_WLAN_ESE + case eWNI_SME_ESE_ADJACENT_AP_REPORT: +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_UPDATE_KEY: + case eWNI_SME_FT_PRE_AUTH_REQ: + case eWNI_SME_FT_AGGR_QOS_REQ: +#endif + case eWNI_SME_ADD_STA_SELF_REQ: + case eWNI_SME_DEL_STA_SELF_REQ: + case eWNI_SME_REGISTER_MGMT_FRAME_REQ: + case eWNI_SME_UPDATE_NOA: + case eWNI_SME_CLEAR_DFS_CHANNEL_LIST: + case eWNI_SME_CLEAR_LIM_SCAN_CACHE: + case eWNI_SME_STA_STAT_REQ: + case eWNI_SME_AGGR_STAT_REQ: + case eWNI_SME_GLOBAL_STAT_REQ: + case eWNI_SME_STAT_SUMM_REQ: + case eWNI_SME_GET_STATISTICS_REQ: +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_GET_TSM_STATS_REQ: +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_EXT_CHANGE_CHANNEL: + case eWNI_SME_ROAM_RESTART_REQ: + // These messages are from HDD + limProcessNormalHddMsg(pMac, limMsg, false); //no need to response to hdd + break; + + //Power Save Messages From HDD + case eWNI_PMC_PWR_SAVE_CFG: + case eWNI_PMC_ENTER_BMPS_REQ: + case eWNI_PMC_EXIT_BMPS_REQ: + case eWNI_PMC_ENTER_IMPS_REQ: + case eWNI_PMC_EXIT_IMPS_REQ: + case eWNI_PMC_ENTER_UAPSD_REQ: + case eWNI_PMC_EXIT_UAPSD_REQ: + case eWNI_PMC_ENTER_WOWL_REQ: + case eWNI_PMC_EXIT_WOWL_REQ: + case eWNI_PMC_WOWL_ADD_BCAST_PTRN: + case eWNI_PMC_WOWL_DEL_BCAST_PTRN: + if(!pMac->psOffloadEnabled) + pmmProcessMessage(pMac, limMsg); + else + pmmOffloadProcessMessage(pMac, limMsg); + break; + + case eWNI_PMC_SMPS_STATE_IND : + { + if(limMsg->bodyptr){ + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + } + } + break; + case eWNI_SME_SEND_ACTION_FRAME_IND: + limSendP2PActionFrame(pMac, limMsg); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + case eWNI_SME_ABORT_REMAIN_ON_CHAN_IND: + { + tSirMbMsgP2p *pMbMsg = (tSirMbMsgP2p *)limMsg->bodyptr; + limAbortRemainOnChan(pMac, pMbMsg->sessionId); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + } + + case SIR_HAL_P2P_NOA_START_IND: + { + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + tANI_U8 i; + tANI_U8 p2pGOExists = 0; + + limLog(pMac, LOG1, "LIM received NOA start %x", limMsg->type); + + /* Since insert NOA is done and NOA start msg received, we should deactivate the Insert NOA timer */ + limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); + + for(i=0; i < pMac->lim.maxBssId; i++) + { + psessionEntry = &pMac->lim.gpSession[i]; + if ( (psessionEntry != NULL) && (psessionEntry->valid) && + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { //Save P2P NOA start attributes for P2P Go persona + p2pGOExists = 1; + vos_mem_copy(&psessionEntry->p2pGoPsNoaStartInd, limMsg->bodyptr, + sizeof(tSirP2PNoaStart)); + if (psessionEntry->p2pGoPsNoaStartInd.status != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGW, FL("GO NOA start failure status %d reported by FW." + " - still go ahead with deferred sme req. This is just info"), + psessionEntry->p2pGoPsNoaStartInd.status); + } + break; + } + } + + if (p2pGOExists == 0) + { + limLog(pMac, LOGW, FL("By the time, we received NOA start, GO is already removed." + " - still go ahead with deferred sme req. This is just info")); + } + + /* We received the NOA start indication. Now we can send down the SME request which requires off-channel operation */ + limProcessRegdDefdSmeReqAfterNOAStart(pMac); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + } + break; +#ifdef FEATURE_WLAN_TDLS + case SIR_HAL_TDLS_IND: + { + tSirTdlsInd *pTdlsInd = (tpSirTdlsInd)limMsg->bodyptr ; + tpDphHashNode pStaDs = NULL ; + tpPESession psessionEntry = NULL; + tANI_U8 sessionId; + if((psessionEntry = peFindSessionByStaId(pMac,pTdlsInd->staIdx,&sessionId))== NULL) + { + limLog(pMac, LOG1, FL("session does not exist for given bssId")); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + if ((pStaDs = dphGetHashEntry(pMac, pTdlsInd->assocId, &psessionEntry->dph.dphHashTable)) == NULL) + { + limLog(pMac, LOG1, FL("pStaDs Does not exist for given staId")); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + + if ((STA_ENTRY_TDLS_PEER == pStaDs->staType)) + { + limLog(pMac, LOGE, + FL("received TDLS Indication from the Firmware with Reason Code %d "), + pTdlsInd->reasonCode); + limSendSmeTDLSDelStaInd(pMac, pStaDs, psessionEntry, + pTdlsInd->reasonCode); + } + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + } + break; +#endif + case SIR_HAL_P2P_NOA_ATTR_IND: + { + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + tANI_U8 i; + + limLog(pMac, LOG1, FL("Received message Noa_ATTR %x"), limMsg->type); + for(i=0; i < pMac->lim.maxBssId; i++) + { + psessionEntry = &pMac->lim.gpSession[i]; + if ( (psessionEntry != NULL) && (psessionEntry->valid) && + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { //Save P2P attributes for P2P Go persona + + vos_mem_copy(&psessionEntry->p2pGoPsUpdate, limMsg->bodyptr, + sizeof(tSirP2PNoaAttr)); + + limLog(pMac, LOG2, FL(" &psessionEntry->bssId " + MAC_ADDRESS_STR " ctWin=%d oppPsFlag=%d"), + MAC_ADDR_ARRAY(psessionEntry->bssId), + psessionEntry->p2pGoPsUpdate.ctWin, + psessionEntry->p2pGoPsUpdate.oppPsFlag); + + limLog(pMac, LOG2, FL(" uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d"), + psessionEntry->p2pGoPsUpdate.uNoa1IntervalCnt, + psessionEntry->p2pGoPsUpdate.uNoa1Duration, + psessionEntry->p2pGoPsUpdate.uNoa1Interval, + psessionEntry->p2pGoPsUpdate.uNoa1StartTime); + + + break; + } + } + + } + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + + break; + + + /* eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER Message comes after the + * device comes out of full power for the full power request sent + * because of channel switch with switch count as 0, so call the same + * function used in timeout case(i.e SIR_LIM_CHANNEL_SWITCH_TIMEOUT) + * for switching the channel*/ + case eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER: + if ( !tx_timer_running(&pMac->lim.limTimers.gLimChannelSwitchTimer) ) + { + limProcessChannelSwitchTimeout(pMac); + } + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + //Power Save Related Messages From HAL + case WDA_ENTER_BMPS_RSP: + case WDA_EXIT_BMPS_RSP: + case WDA_EXIT_BMPS_IND: + case WDA_ENTER_IMPS_RSP: + case WDA_EXIT_IMPS_RSP: + case WDA_ENTER_UAPSD_RSP: + case WDA_EXIT_UAPSD_RSP: + case WDA_WOWL_ENTER_RSP: + case WDA_WOWL_EXIT_RSP: + if(!pMac->psOffloadEnabled) + pmmProcessMessage(pMac, limMsg); + else + pmmOffloadProcessMessage(pMac, limMsg); + break; + + case WDA_MISSED_BEACON_IND: + if(pMac->psOffloadEnabled) + limPsOffloadHandleMissedBeaconInd(pMac, limMsg); + else + limHandleMissedBeaconInd(pMac, limMsg); + + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + case WDA_SMPS_FORCE_MODE_IND: + lim_smps_force_mode_ind(pMac, limMsg); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + case WDA_MIC_FAILURE_IND: + limMicFailureInd(pMac, limMsg); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WDA_ROAM_OFFLOAD_SYNCH_IND: + limRoamOffloadSynchInd(pMac, limMsg); + /* bodyPtr is freed after handling + * eWNI_SME_ROAM_OFFLOAD_SYNCH_IND in sme_ProcessMsg */ + break; +#endif + + + + case SIR_LIM_ADDTS_RSP_TIMEOUT: + limProcessSmeReqMessages(pMac,limMsg); + break; +#ifdef FEATURE_WLAN_ESE + case SIR_LIM_ESE_TSM_TIMEOUT: +#ifndef FEATURE_WLAN_ESE_UPLOAD + limProcessTsmTimeoutHandler(pMac,limMsg); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + break; + case WDA_TSM_STATS_RSP: +#ifdef FEATURE_WLAN_ESE_UPLOAD + limSendSmePEEseTsmRsp(pMac, (tAniGetTsmStatsRsp *)limMsg->bodyptr); +#else + limProcessHalEseTsmRsp(pMac, limMsg); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + break; +#endif + case WDA_ADD_TS_RSP: + limProcessHalAddTsRsp(pMac, limMsg); + break; + + case SIR_LIM_DEL_TS_IND: + limProcessDelTsInd(pMac, limMsg); + break; + case SIR_LIM_ADD_BA_IND: + limProcessAddBaInd(pMac, limMsg); + break; + case SIR_LIM_DEL_BA_ALL_IND: + limDelAllBASessions(pMac); + break; + case SIR_LIM_DEL_BA_IND: + limProcessMlmHalBADeleteInd( pMac, limMsg ); + break; + + case SIR_LIM_BEACON_GEN_IND: { + + if( pMac->lim.gLimSystemRole != eLIM_AP_ROLE ) + schProcessPreBeaconInd(pMac, limMsg); + + } + break; + + case SIR_LIM_DELETE_STA_CONTEXT_IND: + limDeleteStaContext(pMac, limMsg); + break; + + case SIR_LIM_MIN_CHANNEL_TIMEOUT: + case SIR_LIM_MAX_CHANNEL_TIMEOUT: + case SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT: + case SIR_LIM_JOIN_FAIL_TIMEOUT: + case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT: + case SIR_LIM_AUTH_FAIL_TIMEOUT: + case SIR_LIM_AUTH_RSP_TIMEOUT: + case SIR_LIM_ASSOC_FAIL_TIMEOUT: + case SIR_LIM_REASSOC_FAIL_TIMEOUT: +#ifdef WLAN_FEATURE_VOWIFI_11R + case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: +#endif + case SIR_LIM_REMAIN_CHN_TIMEOUT: + case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT: + case SIR_LIM_DISASSOC_ACK_TIMEOUT: + case SIR_LIM_DEAUTH_ACK_TIMEOUT: + case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE: + case SIR_LIM_AUTH_RETRY_TIMEOUT: + // These timeout messages are handled by MLM sub module + + limProcessMlmReqMessages(pMac, + limMsg); + + break; + + case SIR_LIM_HEART_BEAT_TIMEOUT: + /** check if heart beat failed, even if one Beacon + * is rcvd within the Heart Beat interval continue + * normal processing + */ + + if(pMac->psOffloadEnabled) + { + /* Powersave Offload Case */ + /* TODO: Handle in Scan Case */ + /* TODO: handle in TDLS Case */ + if(NULL == limMsg->bodyptr) + { + limLog(pMac, LOGE, + FL("Cannot Process HearBeat Timeout - bodyptr is Null")); + } + else + { + tpPESession psessionEntry = (tpPESession)limMsg->bodyptr; + limLog(pMac, LOGE, + FL("Processing SIR_LIM_HEART_BEAT_TIMEOUT for Session %d"), + ((tpPESession)limMsg->bodyptr)->peSessionId); + limResetHBPktCount(psessionEntry); + limHandleHeartBeatTimeoutForSession(pMac, psessionEntry); + } + break; + } + if (limIsSystemInScanState(pMac)) + { + // System is in DFS (Learn) mode + // Defer processsing this message + if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), + limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) + limLogSessionStates(pMac); + } + } + else + { + if (NULL == limMsg->bodyptr) + { + limHandleHeartBeatTimeout(pMac); + } + else + { + limHandleHeartBeatTimeoutForSession(pMac, (tpPESession)limMsg->bodyptr); + } + } + break; + + case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT: + limHandleHeartBeatFailureTimeout(pMac); + break; + + case SIR_LIM_CHANNEL_SCAN_TIMEOUT: + /** + * Background scan timeout occurred on STA. + * This is handled by LMM sub module. + */ + limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); + + //We will do background scan even in bcnps mode + //if (pMac->sys.gSysEnableScanMode) + pMac->lim.gLimReportBackgroundScanResults = FALSE; + limTriggerBackgroundScan(pMac); + break; + + + case SIR_LIM_HASH_MISS_THRES_TIMEOUT: + + /* + ** clear the credit to the send disassociate frame bucket + **/ + + pMac->lim.gLimDisassocFrameCredit = 0; + break; + + case SIR_LIM_CNF_WAIT_TIMEOUT: + + /* + ** Does not receive CNF or dummy packet + **/ + limHandleCnfWaitTimeout(pMac, (tANI_U16) limMsg->bodyval); + + break; + + case SIR_LIM_KEEPALIVE_TIMEOUT: + limSendKeepAliveToPeer(pMac); + + break; + + case SIR_LIM_RETRY_INTERRUPT_MSG: + // Message from ISR upon TFP's max retry limit interrupt + + break; + + case SIR_LIM_INV_KEY_INTERRUPT_MSG: + // Message from ISR upon SP's Invalid session key interrupt + + break; + + case SIR_LIM_KEY_ID_INTERRUPT_MSG: + // Message from ISR upon SP's Invalid key ID interrupt + + break; + + case SIR_LIM_REPLAY_THRES_INTERRUPT_MSG: + // Message from ISR upon SP's Replay threshold interrupt + + break; + + case SIR_LIM_CHANNEL_SWITCH_TIMEOUT: + limProcessChannelSwitchTimeout(pMac); + break; + + case SIR_LIM_QUIET_TIMEOUT: + limProcessQuietTimeout(pMac); + break; + + case SIR_LIM_QUIET_BSS_TIMEOUT: + limProcessQuietBssTimeout(pMac); + break; + + case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: + limHandleUpdateOlbcCache(pMac); + break; + + +#ifdef FEATURE_WLAN_TDLS + case SIR_HAL_TDLS_SHOULD_DISCOVER: + case SIR_HAL_TDLS_SHOULD_TEARDOWN: + case SIR_HAL_TDLS_PEER_DISCONNECTED: + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + ("%s received tdls event: 0x%x"), + __func__, limMsg->type); + limSendSmeTdlsEventNotify(pMac, limMsg->type, + (void *)limMsg->bodyptr); + break; +#endif + + case WDA_ADD_BSS_RSP: + limProcessMlmAddBssRsp( pMac, limMsg ); + break; + + case WDA_ADD_STA_RSP: + + //call a wrapper by paasing bodyptr, their get sessionID and and call proper function from there. + limProcessAddStaRsp(pMac,limMsg); + break; + + case WDA_DELETE_STA_RSP: + limProcessMlmDelStaRsp(pMac, limMsg); + break; + + case WDA_ADD_STA_SELF_RSP: + limProcessAddStaSelfRsp(pMac, limMsg); + break; + case WDA_DEL_STA_SELF_RSP: + limProcessDelStaSelfRsp(pMac, limMsg); + break; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + case WDA_UPDATE_Q2Q_IE_IND: + /* + * this device is operating AP in MCC mode, update Q2Q IE in + * beacon template + */ + vos_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); + beacon_params.paramChangeBitmap = 0; + for ( i = 0; i < pMac->lim.maxBssId; i++) { + vdev_id = ((tANI_U8*)limMsg->bodyptr)[i]; + session_entry = pe_find_session_by_sme_session_id(pMac, + vdev_id); + if(session_entry == NULL) + continue; + session_entry->sap_advertise_avoid_ch_ie = + (tANI_U8)limMsg->bodyval; + + /* + * if message comes for DFS channel, no need to update as: + * 1) We wont have MCC with DFS channels. so no need to add + * Q2Q IE + * 2) We cannot end up in DFS channel SCC by channel switch + * from non DFS MCC scenario, so no need to remove Q2Q IE + * 3) There is however a case where device start MCC and then + * user modifies hostapd.conf and does SAP restart, in such + * a case, beacon params will be reset and thus will not + * contain Q2Q IE, by default. + */ + if (vos_nv_getChannelEnabledState( + session_entry->currentOperChannel) != NV_CHANNEL_DFS) { + beacon_params.bssIdx = session_entry->bssIdx; + beacon_params.beaconInterval = + session_entry->beaconParams.beaconInterval; + beacon_params.paramChangeBitmap |= + PARAM_BCN_INTERVAL_CHANGED; + schSetFixedBeaconFields(pMac, session_entry); + limSendBeaconParams(pMac, &beacon_params, session_entry); + } + } + vos_mem_free(limMsg->bodyptr); + break; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + case WDA_DELETE_BSS_RSP: + limHandleDeleteBssRsp(pMac,limMsg); //wrapper routine to handle delete bss response + break; + + case WDA_CSA_OFFLOAD_EVENT: + limHandleCSAoffloadMsg(pMac, limMsg); + break; + + case WDA_SET_BSSKEY_RSP: + case WDA_SET_STA_BCASTKEY_RSP: + limProcessMlmSetBssKeyRsp( pMac, limMsg ); + break; + case WDA_SET_STAKEY_RSP: + limProcessMlmSetStaKeyRsp( pMac, limMsg ); + break; + case WDA_REMOVE_BSSKEY_RSP: + case WDA_REMOVE_STAKEY_RSP: + limProcessMlmRemoveKeyRsp( pMac, limMsg ); + break; + case WDA_ADDBA_RSP: + limProcessMlmHalAddBARsp( pMac, limMsg ); + break; + + case WDA_STA_STAT_RSP: + case WDA_AGGR_STAT_RSP: + case WDA_GLOBAL_STAT_RSP: + case WDA_STAT_SUMM_RSP: + limSendSmeStatsRsp ( pMac, limMsg->type, (void *)limMsg->bodyptr); + break; + + case WDA_GET_STATISTICS_RSP: + limSendSmePEStatisticsRsp ( pMac, limMsg->type, (void *)limMsg->bodyptr); + break; + + case WDA_SET_MIMOPS_RSP: + case WDA_SET_TX_POWER_RSP: + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case WDA_SET_MAX_TX_POWER_RSP: +#if defined WLAN_FEATURE_VOWIFI + rrmSetMaxTxPowerRsp( pMac, limMsg ); +#endif + if(limMsg->bodyptr != NULL) + { + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + } + break; + + case SIR_LIM_ADDR2_MISS_IND: + { + limLog(pMac, LOGE, + FL("Addr2 mismatch interrupt received %X"), + limMsg->type); + /*a message from HAL indicating addr2 mismatch interrupt occurred + limMsg->bodyptr contains only pointer to 48-bit addr2 field*/ + + vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); + limMsg->bodyptr = NULL; + break; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + case WDA_AGGR_QOS_RSP: + limProcessFTAggrQoSRsp( pMac, limMsg ); + break; +#endif + + case WDA_SET_LINK_STATE_RSP: + linkStateParams = (tLinkStateParams *)limMsg->bodyptr; +#if defined WLAN_FEATURE_VOWIFI_11R + pSession = linkStateParams->session; + if(linkStateParams->ft +#if defined WLAN_FEATURE_ROAM_OFFLOAD + && !pSession->bRoamSynchInProgress +#endif + ) + { + limSendReassocReqWithFTIEsMgmtFrame(pMac, + pSession->pLimMlmReassocReq, + pSession); + } +#endif + if( linkStateParams->callback ) + { + linkStateParams->callback(pMac, linkStateParams->callbackArg, + linkStateParams->status); + } + vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); + limMsg->bodyptr = NULL; + break; + +#ifdef WLAN_FEATURE_PACKET_FILTERING + case WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP: + pmmProcessMessage(pMac, limMsg); + break; +#endif // WLAN_FEATURE_PACKET_FILTERING + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + case WDA_GTK_OFFLOAD_GETINFO_RSP: + pmmProcessMessage(pMac, limMsg); + break; +#endif // WLAN_FEATURE_GTK_OFFLOAD + case eWNI_SME_SET_BCN_FILTER_REQ: + { +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + tpPESession psessionEntry; + tANI_U8 sessionId = (tANI_U8)limMsg->bodyval ; + psessionEntry = &pMac->lim.gpSession[sessionId]; + if(psessionEntry != NULL && IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + // sending beacon filtering information down to HAL + if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); + } + } + vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); + limMsg->bodyptr = NULL; +#endif + } + break; +#ifdef FEATURE_WLAN_TDLS + case WDA_SET_TDLS_LINK_ESTABLISH_REQ_RSP: + { + tpPESession psessionEntry; + tANI_U8 sessionId; + tTdlsLinkEstablishParams *pTdlsLinkEstablishParams; + pTdlsLinkEstablishParams = (tTdlsLinkEstablishParams*) limMsg->bodyptr; + + if((psessionEntry = peFindSessionByStaId(pMac, + pTdlsLinkEstablishParams->staIdx, + &sessionId))== NULL) + { + limLog(pMac, LOGE, FL("session %u does not exist"), sessionId); + /* Still send the eWNI_SME_TDLS_LINK_ESTABLISH_RSP message to + * SME with session id as zero and status as FAILURE so, + * that message queued in SME queue can be freed to prevent + * the SME cmd buffer leak */ + limSendSmeTdlsLinkEstablishReqRsp(pMac, + 0, + NULL, + NULL, + eSIR_FAILURE); + } + else + { + limSendSmeTdlsLinkEstablishReqRsp(pMac, + psessionEntry->smeSessionId, + NULL, + NULL, + pTdlsLinkEstablishParams->status) ; + } + vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); + limMsg->bodyptr = NULL; + break; + } +#endif + + case WDA_RX_SCAN_EVENT: + limProcessRxScanEvent(pMac, limMsg->bodyptr); + break; + + case WDA_IBSS_PEER_INACTIVITY_IND: + { + limProcessIbssPeerInactivity(pMac, limMsg->bodyptr); + vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); + limMsg->bodyptr = NULL; + break; + } + + case WDA_DFS_RADAR_IND: + limSendSmeDfsEventNotify(pMac, limMsg->type, + (void *)limMsg->bodyptr); + /* limmsg->bodyptr will be freed up by SME/CSR */ + break; + + case WDA_DFS_BEACON_TX_SUCCESS_IND: + limProcessBeaconTxSuccessInd(pMac, limMsg->type, + (void *)limMsg->bodyptr); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case WDA_DISASSOC_TX_COMP: + limDisassocTxCompleteCnf(pMac , limMsg->bodyval); + break; + + case WDA_DEAUTH_TX_COMP: + limDeauthTxCompleteCnf(pMac, limMsg->bodyval); + break; + + case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_CHANNEL_CHANGE_REQ: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_START_BEACON_REQ: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_UPDATE_ADDITIONAL_IES: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_MODIFY_ADDITIONAL_IES: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + +#ifdef QCA_HT_2040_COEX + case eWNI_SME_SET_HT_2040_MODE: + limProcessSmeReqMessages(pMac, limMsg); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; +#endif + +#ifdef SAP_AUTH_OFFLOAD + case WDA_SAP_OFL_ADD_STA: + lim_sap_offload_add_sta(pMac, limMsg); + break; + case WDA_SAP_OFL_DEL_STA: + lim_sap_offload_del_sta(pMac, limMsg); + break; +#endif /* SAP_AUTH_OFFLOAD */ + default: + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + // Unwanted messages + // Log error + limLog(pMac, LOGE, + FL("Discarding unexpected message received %X"), + limMsg->type); + break; + + } // switch (limMsg->type) + + PELOG2(limLog(pMac, LOG2, FL("Done Processing msgType = %d, mlm state = %s"), + limMsg->type, + limMlmStateStr(pMac->lim.gLimMlmState));) + +} /*** end limProcessMessages() ***/ + + + +/** + * limProcessDeferredMessageQueue + * + *FUNCTION: + * This function is called by LIM while exiting from Learn + * mode. This function fetches messages posted to the LIM + * deferred message queue limDeferredMsgQ. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limProcessDeferredMessageQueue(tpAniSirGlobal pMac) +{ + tSirMsgQ limMsg = { 0, 0, 0 }; + + tSirMsgQ *readMsg; + tANI_U16 size; + + /* + ** check any deferred messages need to be processed + **/ + size = pMac->lim.gLimDeferredMsgQ.size; + if (size > 0) + { + while ((readMsg = limReadDeferredMsgQ(pMac)) != NULL) + { + vos_mem_copy((tANI_U8*) &limMsg, + (tANI_U8*) readMsg, sizeof(tSirMsgQ)); + size--; + limProcessMessages(pMac, &limMsg); + + if((limIsSystemInScanState(pMac)) || (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) || + (pMac->lim.gLimSystemInScanLearnMode) || + pMac->lim.gLimAddtsSent) + break; + } + } +} /*** end limProcessDeferredMessageQueue() ***/ + + +/* + * limProcessNormalHddMsg + * Function: this function checks the current lim state and decide whether the message passed shall be deffered. + * @param pMac - Pointer to Global MAC structure + * pLimMsg -- the message need to be processed + * fRspReqd -- whether return result to hdd + * @return None + */ +void limProcessNormalHddMsg(tpAniSirGlobal pMac, tSirMsgQ *pLimMsg, tANI_U8 fRspReqd) +{ + tANI_BOOLEAN fDeferMsg = eANI_BOOLEAN_TRUE; + + /* Added For BT-AMP Support */ + if ((pMac->lim.gLimSystemRole == eLIM_AP_ROLE) ||(pMac->lim.gLimSystemRole == eLIM_BT_AMP_AP_ROLE ) + ||(pMac->lim.gLimSystemRole == eLIM_BT_AMP_STA_ROLE) + ||(pMac->lim.gLimSystemRole == eLIM_UNKNOWN_ROLE)) + { + /** This check is required only for the AP and in 2 cases. + * 1. If we are in learn mode and we receive any of these messages, + * you have to come out of scan and process the message, hence dont + * defer the message here. In handler, these message could be defered + * till we actually come out of scan mode. + * 2. If radar is detected, you might have to defer all of these + * messages except Stop BSS request/ Switch channel request. This + * decision is also made inside its handler. + * + * Please be careful while using the flag fDeferMsg. Possibly you + * might end up in an infinite loop. + **/ + if (((pLimMsg->type == eWNI_SME_START_BSS_REQ) || + (pLimMsg->type == eWNI_SME_STOP_BSS_REQ) || + (pLimMsg->type == eWNI_SME_SWITCH_CHL_REQ) || + (pLimMsg->type == eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ) || + (pLimMsg->type == eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ))) + { + fDeferMsg = eANI_BOOLEAN_FALSE; + } + } + + /* limInsystemInscanState() refers the psessionEntry, how to get session Entry????*/ + if (((pMac->lim.gLimAddtsSent) || (limIsSystemInScanState(pMac))) && + fDeferMsg) { + // System is in DFS (Learn) mode or awaiting addts response + // or if radar is detected, Defer processsing this message + if (limDeferMsg(pMac, pLimMsg) != TX_SUCCESS) + { +#ifdef WLAN_DEBUG + pMac->lim.numSme++; +#endif + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), + pLimMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, + pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) + limLogSessionStates(pMac); + // Release body + vos_mem_free(pLimMsg->bodyptr); + pLimMsg->bodyptr = NULL; + } + } + else + { + if(fRspReqd) + { + // These messages are from HDD + // Since these requests may also be generated + // internally within LIM module, need to + // distinquish and send response to host + pMac->lim.gLimRspReqd = eANI_BOOLEAN_TRUE; + } +#ifdef WLAN_DEBUG + pMac->lim.numSme++; +#endif + if(limProcessSmeReqMessages(pMac, pLimMsg)) + { + // Release body + // limProcessSmeReqMessage consumed the buffer. We can free it. + vos_mem_free(pLimMsg->bodyptr); + pLimMsg->bodyptr = NULL; + } + } +} + +void +handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntry) +{ + tSirMacHTCapabilityInfo macHTCapabilityInfo; + tSirMacHTParametersInfo macHTParametersInfo; + tSirMacHTInfoField1 macHTInfoField1; + tSirMacHTInfoField2 macHTInfoField2; + tSirMacHTInfoField3 macHTInfoField3; + tANI_U32 cfgValue; + tANI_U8 *ptr; + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &cfgValue) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_CAP_INFO value")); + return ; + } + ptr = (tANI_U8 *) &macHTCapabilityInfo; + *((tANI_U16 *)ptr) = (tANI_U16) (cfgValue & 0xffff); + pMac->lim.gHTLsigTXOPProtection = (tANI_U8)macHTCapabilityInfo.lsigTXOPProtection; + pMac->lim.gHTMIMOPSState = (tSirMacHTMIMOPowerSaveState) macHTCapabilityInfo.mimoPowerSave; + pMac->lim.gHTGreenfield = (tANI_U8)macHTCapabilityInfo.greenField; + pMac->lim.gHTMaxAmsduLength = (tANI_U8)macHTCapabilityInfo.maximalAMSDUsize; + pMac->lim.gHTShortGI20Mhz = (tANI_U8)macHTCapabilityInfo.shortGI20MHz; + pMac->lim.gHTShortGI40Mhz = (tANI_U8)macHTCapabilityInfo.shortGI40MHz; + pMac->lim.gHTPSMPSupport = (tANI_U8)macHTCapabilityInfo.psmp; + pMac->lim.gHTDsssCckRate40MHzSupport = (tANI_U8)macHTCapabilityInfo.dsssCckMode40MHz; + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &cfgValue) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_PARAM_INFO value")); + return ; + } + ptr = (tANI_U8 *) &macHTParametersInfo; + *ptr = (tANI_U8) (cfgValue & 0xff); + pMac->lim.gHTAMpduDensity = (tANI_U8)macHTParametersInfo.mpduDensity; + pMac->lim.gHTMaxRxAMpduFactor = (tANI_U8)macHTParametersInfo.maxRxAMPDUFactor; + + // Get HT IE Info + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD1, &cfgValue) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value")); + return ; + } + ptr = (tANI_U8 *) &macHTInfoField1; + *((tANI_U8 *)ptr) = (tANI_U8) (cfgValue & 0xff); + pMac->lim.gHTServiceIntervalGranularity = (tANI_U8)macHTInfoField1.serviceIntervalGranularity; + pMac->lim.gHTControlledAccessOnly = (tANI_U8)macHTInfoField1.controlledAccessOnly; + pMac->lim.gHTRifsMode = (tANI_U8)macHTInfoField1.rifsMode; + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD2, &cfgValue) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value")); + return ; + } + ptr = (tANI_U8 *) &macHTInfoField2; + *((tANI_U16 *)ptr) = (tANI_U16) (cfgValue & 0xffff); + pMac->lim.gHTOperMode = (tSirMacHTOperatingMode) macHTInfoField2.opMode; + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD3, &cfgValue) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value")); + return ; + } + ptr = (tANI_U8 *) &macHTInfoField3; + *((tANI_U16 *)ptr) = (tANI_U16) (cfgValue & 0xffff); + pMac->lim.gHTPCOActive = (tANI_U8)macHTInfoField3.pcoActive; + pMac->lim.gHTPCOPhase = (tANI_U8)macHTInfoField3.pcoPhase; + pMac->lim.gHTSecondaryBeacon = (tANI_U8)macHTInfoField3.secondaryBeacon; + pMac->lim.gHTDualCTSProtection = (tANI_U8)macHTInfoField3.dualCTSProtection; + pMac->lim.gHTSTBCBasicMCS = (tANI_U8)macHTInfoField3.basicSTBCMCS; + + /* The lim globals for channelwidth and secondary chnl have been removed and should not be used during no session; + * instead direct cfg is read and used when no session for transmission of mgmt frames (same as old); + * For now, we might come here during init and join with sessionEntry = NULL; in that case just fill the globals which exist + * Sessionized entries values will be filled in join or add bss req. The ones which are missed in join are filled below + */ + if (psessionEntry != NULL) + { + psessionEntry->htCapability = IS_DOT11_MODE_HT(psessionEntry->dot11mode); + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = (tANI_U8)macHTInfoField3.lsigTXOPProtectionFullSupport; + } +} + +void limLogSessionStates(tpAniSirGlobal pMac) +{ +#ifdef WLAN_DEBUG + int i; + + for(i = 0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid) + { + PELOG1(limLog(pMac, LOG1, FL("Session[%d] sysRole(%d) limSmeState %d (prev sme state %d) mlm state %d (prev mlm state %d)"), + i, pMac->lim.gpSession[i].limSystemRole, pMac->lim.gpSession[i].limSmeState, + pMac->lim.gpSession[i].limPrevSmeState, pMac->lim.gpSession[i].limMlmState, + pMac->lim.gpSession[i].limPrevMlmState);) + } + } +#endif //ifdef WLAN_DEBUG +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c new file mode 100644 index 000000000000..ae1c6e580db2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -0,0 +1,4896 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limProcessMlmMessages.cc contains the code + * for processing MLM request messages. + * Author: Chandra Modumudi + * Date: 02/12/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "sirApi.h" +#include "sirParams.h" +#include "cfgApi.h" + +#include "schApi.h" +#include "utilsApi.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limPropExtsUtils.h" +#include "limSecurityUtils.h" +#include "limSendMessages.h" +#include "pmmApi.h" +#include "limSendMessages.h" +#include "limSessionUtils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM +#include "vos_diag_core_log.h" +#endif + + +// MLM REQ processing function templates +static void limProcessMlmStartReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmScanReq(tpAniSirGlobal, tANI_U32 *); +#ifdef FEATURE_OEM_DATA_SUPPORT +static void limProcessMlmOemDataReq(tpAniSirGlobal, tANI_U32 *); +#endif +static void limProcessMlmJoinReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmAuthReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmAssocReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmReassocReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmDisassocReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmDeauthReq(tpAniSirGlobal, tANI_U32 *); +static void limProcessMlmSetKeysReq(tpAniSirGlobal, tANI_U32 *); + +static void limProcessMlmAddBAReq( tpAniSirGlobal, tANI_U32 * ); +static void limProcessMlmAddBARsp( tpAniSirGlobal, tANI_U32 * ); +static void limProcessMlmDelBAReq( tpAniSirGlobal, tANI_U32 * ); + +// MLM Timeout event handler templates +static void limProcessMinChannelTimeout(tpAniSirGlobal); +static void limProcessMaxChannelTimeout(tpAniSirGlobal); +static void limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac); +static void limProcessJoinFailureTimeout(tpAniSirGlobal); +static void limProcessAuthFailureTimeout(tpAniSirGlobal); +static void limProcessAuthRspTimeout(tpAniSirGlobal, tANI_U32); +static void limProcessAssocFailureTimeout(tpAniSirGlobal, tANI_U32); +static void limProcessPeriodicJoinProbeReqTimer(tpAniSirGlobal); +static void lim_process_auth_retry_timer(tpAniSirGlobal); + + +static void limProcessMlmRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 * pMsgBuf); +void +limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tPowerdBm maxTxPower, tANI_U8 peSessionId); +#define IS_MLM_SCAN_REQ_BACKGROUND_SCAN_AGGRESSIVE(pMac) (pMac->lim.gpLimMlmScanReq->backgroundScanMode == eSIR_AGGRESSIVE_BACKGROUND_SCAN) +#define IS_MLM_SCAN_REQ_BACKGROUND_SCAN_NORMAL(pMac) (pMac->lim.gpLimMlmScanReq->backgroundScanMode == eSIR_NORMAL_BACKGROUND_SCAN) + +/** + * limProcessMlmReqMessages() + * + *FUNCTION: + * This function is called by limPostMlmMessage(). This + * function handles MLM primitives invoked by SME. + * + *LOGIC: + * Depending on the message type, corresponding function will be + * called. + * + *ASSUMPTIONS: + * 1. Upon receiving Beacon in WT_JOIN_STATE, MLM module invokes + * APIs exposed by Beacon Processing module for setting parameters + * at MAC hardware. + * 2. If attempt to Reassociate with an AP fails, link with current + * AP is restored back. + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the MLM primitive message type + * @param *pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ + +void +limProcessMlmReqMessages(tpAniSirGlobal pMac, tpSirMsgQ Msg) +{ + MTRACE(macTraceMsgRx(pMac, NO_SESSION, Msg->type)); + switch (Msg->type) + { + case LIM_MLM_START_REQ: limProcessMlmStartReq(pMac, Msg->bodyptr); break; + case LIM_MLM_SCAN_REQ: limProcessMlmScanReq(pMac, Msg->bodyptr); break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case LIM_MLM_OEM_DATA_REQ: limProcessMlmOemDataReq(pMac, Msg->bodyptr); break; +#endif + case LIM_MLM_JOIN_REQ: limProcessMlmJoinReq(pMac, Msg->bodyptr); break; + case LIM_MLM_AUTH_REQ: limProcessMlmAuthReq(pMac, Msg->bodyptr); break; + case LIM_MLM_ASSOC_REQ: limProcessMlmAssocReq(pMac, Msg->bodyptr); break; + case LIM_MLM_REASSOC_REQ: limProcessMlmReassocReq(pMac, Msg->bodyptr); break; + case LIM_MLM_DISASSOC_REQ: limProcessMlmDisassocReq(pMac, Msg->bodyptr); break; + case LIM_MLM_DEAUTH_REQ: limProcessMlmDeauthReq(pMac, Msg->bodyptr); break; + case LIM_MLM_SETKEYS_REQ: limProcessMlmSetKeysReq(pMac, Msg->bodyptr); break; + case LIM_MLM_REMOVEKEY_REQ: limProcessMlmRemoveKeyReq(pMac, Msg->bodyptr); break; + case SIR_LIM_MIN_CHANNEL_TIMEOUT: limProcessMinChannelTimeout(pMac); break; + case SIR_LIM_MAX_CHANNEL_TIMEOUT: limProcessMaxChannelTimeout(pMac); break; + case SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT: + limProcessPeriodicProbeReqTimer(pMac); break; + case SIR_LIM_JOIN_FAIL_TIMEOUT: limProcessJoinFailureTimeout(pMac); break; + case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT: + limProcessPeriodicJoinProbeReqTimer(pMac); break; + case SIR_LIM_AUTH_FAIL_TIMEOUT: limProcessAuthFailureTimeout(pMac); break; + case SIR_LIM_AUTH_RSP_TIMEOUT: limProcessAuthRspTimeout(pMac, Msg->bodyval); break; + case SIR_LIM_ASSOC_FAIL_TIMEOUT: limProcessAssocFailureTimeout(pMac, Msg->bodyval); break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: limProcessFTPreauthRspTimeout(pMac); break; +#endif + case SIR_LIM_REMAIN_CHN_TIMEOUT: limProcessRemainOnChnTimeout(pMac); break; + case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT: + limProcessInsertSingleShotNOATimeout(pMac); break; + case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE: + limConvertActiveChannelToPassiveChannel(pMac); break; + case SIR_LIM_AUTH_RETRY_TIMEOUT: + lim_process_auth_retry_timer(pMac); + break; + case SIR_LIM_DISASSOC_ACK_TIMEOUT: limProcessDisassocAckTimeout(pMac); break; + case SIR_LIM_DEAUTH_ACK_TIMEOUT: limProcessDeauthAckTimeout(pMac); break; + case LIM_MLM_ADDBA_REQ: limProcessMlmAddBAReq( pMac, Msg->bodyptr ); break; + case LIM_MLM_ADDBA_RSP: limProcessMlmAddBARsp( pMac, Msg->bodyptr ); break; + case LIM_MLM_DELBA_REQ: limProcessMlmDelBAReq( pMac, Msg->bodyptr ); break; + case LIM_MLM_TSPEC_REQ: + default: + break; + } // switch (msgType) +} /*** end limProcessMlmReqMessages() ***/ + + +/** + * limSetScanMode() + * + *FUNCTION: + * This function is called to setup system into Scan mode + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limSetScanMode(tpAniSirGlobal pMac) +{ + tSirLinkTrafficCheck checkTraffic; + + /// Set current scan channel id to the first in the channel list + pMac->lim.gLimCurrentScanChannelId = 0; + + if ( IS_MLM_SCAN_REQ_BACKGROUND_SCAN_AGGRESSIVE(pMac) ) + { + checkTraffic = eSIR_DONT_CHECK_LINK_TRAFFIC_BEFORE_SCAN; + } + else if (IS_MLM_SCAN_REQ_BACKGROUND_SCAN_NORMAL(pMac)) + { + checkTraffic = eSIR_CHECK_LINK_TRAFFIC_BEFORE_SCAN; + } + else + checkTraffic = eSIR_CHECK_ROAMING_SCAN; + + PELOG1(limLog(pMac, LOG1, FL("Calling limSendHalInitScanReq"));) + limSendHalInitScanReq(pMac, eLIM_HAL_INIT_SCAN_WAIT_STATE, checkTraffic); + + return ; +} /*** end limSetScanMode() ***/ + +//WLAN_SUSPEND_LINK Related + +/* limIsLinkSuspended() + * + *FUNCTION: + * This function returns is link is suspended or not. + * + *LOGIC: + * Since Suspend link uses init scan, it just returns + * gLimSystemInScanLearnMode flag. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ +tANI_U8 +limIsLinkSuspended(tpAniSirGlobal pMac) +{ + return pMac->lim.gLimSystemInScanLearnMode; +} +/** + * limSuspendLink() + * + *FUNCTION: + * This function is called to suspend traffic. Internally this function uses WDA_INIT_SCAN_REQ. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param trafficCheck - Takes value from enum tSirLinkTrafficCheck. + * @param callback - Callback function to be called after suspending the link. + * @param data - Pointer to any buffer that will be passed to callback. + * @return None + */ +void +limSuspendLink(tpAniSirGlobal pMac, tSirLinkTrafficCheck trafficCheck, SUSPEND_RESUME_LINK_CALLBACK callback, tANI_U32 *data) +{ + if( NULL == callback ) + { + limLog( pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ ); + return; + } + + if( pMac->lim.gpLimSuspendCallback || + pMac->lim.gLimSystemInScanLearnMode ) + { + limLog( pMac, LOGE, FL("Something is wrong, SuspendLinkCbk:%p " + "IsSystemInScanLearnMode:%d"), pMac->lim.gpLimSuspendCallback, + pMac->lim.gLimSystemInScanLearnMode ); + callback( pMac, eHAL_STATUS_FAILURE, data ); + return; + } + + pMac->lim.gLimSystemInScanLearnMode = 1; + pMac->lim.gpLimSuspendCallback = callback; + pMac->lim.gpLimSuspendData = data; + limSendHalInitScanReq(pMac, eLIM_HAL_SUSPEND_LINK_WAIT_STATE, trafficCheck ); + + WDA_TrafficStatsTimerActivate(FALSE); +} + +/** + * limResumeLink() + * + *FUNCTION: + * This function is called to Resume traffic after a suspend. Internally this function uses WDA_FINISH_SCAN_REQ. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param callback - Callback function to be called after Resuming the link. + * @param data - Pointer to any buffer that will be passed to callback. + * @return None + */ +void +limResumeLink(tpAniSirGlobal pMac, SUSPEND_RESUME_LINK_CALLBACK callback, tANI_U32 *data) +{ + if( NULL == callback ) + { + limLog( pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ ); + return; + } + + if( pMac->lim.gpLimResumeCallback ) + { + limLog( pMac, LOGE, "%s:%d: gLimResumeLink callback is not NULL...something is wrong", __func__, __LINE__ ); + callback( pMac, eHAL_STATUS_FAILURE, data ); + return; + } + + pMac->lim.gpLimResumeCallback = callback; + pMac->lim.gpLimResumeData = data; + + /* eLIM_HAL_IDLE_SCAN_STATE state indicate limSendHalInitScanReq failed. + * In case limSendHalInitScanReq is success, Scanstate would be + * eLIM_HAL_SUSPEND_LINK_STATE + */ + if( eLIM_HAL_IDLE_SCAN_STATE != pMac->lim.gLimHalScanState ) + { + limSendHalFinishScanReq(pMac, eLIM_HAL_RESUME_LINK_WAIT_STATE ); + } + else + { + limLog(pMac, LOGW, FL("Init Scan failed, we will not call finish scan." + " calling the callback with failure status")); + pMac->lim.gpLimResumeCallback( pMac, eSIR_FAILURE, pMac->lim.gpLimResumeData); + pMac->lim.gpLimResumeCallback = NULL; + pMac->lim.gpLimResumeData = NULL; + pMac->lim.gLimSystemInScanLearnMode = 0; + } + + if(limIsInMCC(pMac)) + { + WDA_TrafficStatsTimerActivate(TRUE); + } +} +//end WLAN_SUSPEND_LINK Related + + +/** + * + * limChangeChannelWithCallback() + * + * FUNCTION: + * This function is called to change channel and perform off channel operation + * if required. The caller registers a callback to be called at the end of the + * channel change. + * + */ +void +limChangeChannelWithCallback(tpAniSirGlobal pMac, tANI_U8 newChannel, + CHANGE_CHANNEL_CALLBACK callback, + tANI_U32 *cbdata, tpPESession psessionEntry) +{ + // Sanity checks for the current and new channel +#if defined WLAN_VOWIFI_DEBUG + PELOGE(limLog( pMac, LOGE, "Switching channel to %d", newChannel);) +#endif + psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; + + pMac->lim.gpchangeChannelCallback = callback; + pMac->lim.gpchangeChannelData = cbdata; + + limSendSwitchChnlParams(pMac, newChannel, + PHY_SINGLE_CHANNEL_CENTERED, + psessionEntry->maxTxPower, psessionEntry->peSessionId, VOS_FALSE); + + return; +} + + +/** + * limContinuePostChannelScan() + * + *FUNCTION: + * This function is called to scan the current channel. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * + * @return None + */ + +void limContinuePostChannelScan(tpAniSirGlobal pMac) +{ + tANI_U8 channelNum; + tANI_U8 handleError = 0; + tANI_U8 i = 0; + tSirRetStatus status = eSIR_SUCCESS; + + if( pMac->lim.abortScan || (NULL == pMac->lim.gpLimMlmScanReq ) || + (pMac->lim.gLimCurrentScanChannelId > + (tANI_U32)(pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1))) + { + pMac->lim.abortScan = 0; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + return; + } + + channelNum = limGetCurrentScanChannel(pMac); + if ((pMac->lim.gpLimMlmScanReq->scanType == eSIR_ACTIVE_SCAN) && + (limActiveScanAllowed(pMac, channelNum))) + { + TX_TIMER *periodicScanTimer; + PELOG2(limLog(pMac, LOG2, FL("ACTIVE Scan chan %d, sending probe"), channelNum);) + + pMac->lim.probeCounter++; + do + { + /* Prepare and send Probe Request frame for all the SSIDs present in the saved MLM + */ + + PELOGE(limLog(pMac, LOG1, FL("sending ProbeReq number %d, for SSID %s on channel: %d"), + i, pMac->lim.gpLimMlmScanReq->ssId[i].ssId, channelNum);) + // include additional IE if there is + status = limSendProbeReqMgmtFrame( pMac, &pMac->lim.gpLimMlmScanReq->ssId[i], + pMac->lim.gpLimMlmScanReq->bssId, channelNum, pMac->lim.gSelfMacAddr, + pMac->lim.gpLimMlmScanReq->dot11mode, + pMac->lim.gpLimMlmScanReq->uIEFieldLen, + (tANI_U8 *)(pMac->lim.gpLimMlmScanReq)+pMac->lim.gpLimMlmScanReq->uIEFieldOffset); + + if ( status != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID %s on channel: %d"), + pMac->lim.gpLimMlmScanReq->ssId[i].ssId, channelNum);) + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limSendHalEndScanReq(pMac, channelNum, eLIM_HAL_END_SCAN_WAIT_STATE); + return; + } + i++; + } while (i < pMac->lim.gpLimMlmScanReq->numSsid); + + { +#if defined WLAN_FEATURE_VOWIFI + //If minChannelTime is set to zero, SME is requesting scan to not use min channel timer. + //This is used in 11k to request for beacon measurement request with a fixed duration in + //max channel time. + if( pMac->lim.gpLimMlmScanReq->minChannelTime != 0 ) + { +#endif + /// TXP has sent Probe Request + /// Activate minChannelTimer + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + + + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_MIN_CHANNEL_TIMER)); + + if (tx_timer_activate(&pMac->lim.limTimers.gLimMinChannelTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not start min channel timer")); + return; + } + + // Initialize max timer too + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); +#if defined WLAN_FEATURE_VOWIFI + } + else + { +#if defined WLAN_VOWIFI_DEBUG + PELOGE(limLog( pMac, LOGE, "Min channel time == 0, Use only max chan timer" );) +#endif + //No Need to start Min channel timer. Start Max Channel timer. + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, pMac->lim.limTimers.gLimMaxChannelTimer.sessionId, eLIM_MAX_CHANNEL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) + == TX_TIMER_ERROR) + { + /// Could not activate max channel timer. + // Log error + limLog(pMac,LOGP, FL("could not start max channel timer")); + return; + } + + } +#endif + } + /* Start peridic timer which will trigger probe req based on min/max + channel timer */ + periodicScanTimer = &pMac->lim.limTimers.gLimPeriodicProbeReqTimer; + if (tx_timer_activate(periodicScanTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not start periodic probe req " + "timer")); + return; + } + periodicScanTimer->sessionId = channelNum; + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, periodicScanTimer->sessionId, eLIM_PERIODIC_PROBE_REQ_TIMER)); + } + else + { + tANI_U32 val; + PELOG2(limLog(pMac, LOG2, FL("START PASSIVE Scan chan %d"), channelNum);) + + /// Passive Scanning. Activate maxChannelTimer + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_MAX_CHANNEL_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimMaxChannelTimer) + != TX_SUCCESS) + { + // Could not deactivate max channel timer. + // Log error + limLog(pMac, LOGP, FL("Unable to deactivate max channel timer")); + return; + } + else + { + if (wlan_cfgGetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + &val) != eSIR_SUCCESS) + { + /** + * Could not get max channel value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); + return; + } + else + { + tANI_U32 val1 = 0; + + val = SYS_MS_TO_TICKS(val); + //Pick the longer stay time + val = (val > val1) ? val : val1; + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_MAX_CHANNEL_TIMER)); + if (tx_timer_change(&pMac->lim.limTimers.gLimMaxChannelTimer, + val, 0) != TX_SUCCESS) + { + // Could not change max channel timer. + // Log error + limLog(pMac, LOGP, FL("Unable to change max channel timer")); + return; + } + else if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not start max channel timer")); + return; + } + + } + } + // Wait for Beacons to arrive + } // if (pMac->lim.gLimMlmScanReq->scanType == eSIR_ACTIVE_SCAN) + + if( handleError ) + { + // + // FIXME - With this, LIM/SoftMAC will try and recover + // state, but eWNI_SME_SCAN_CNF maybe reporting an + // incorrect status back to the SME. Some of the possible + // errors are: + // eSIR_SME_HAL_SCAN_INIT_FAILED + // eSIR_SME_RESOURCES_UNAVAILABLE + // + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq( pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE ); + } + else + { + limAddScanChannelInfo(pMac, channelNum); + } + + return; +} + + + + + +/* limCovertChannelScanType() + * + *FUNCTION: + * This function is called to get the list, change the channel type and set again. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: If a channel is ACTIVE, this function will make it as PASSIVE + * If a channel is PASSIVE, this fucntion will make it as ACTIVE + * NA + * + * @param pMac - Pointer to Global MAC structure + * channelNum - Channel which need to be convert + PassiveToActive - Boolean flag to convert channel + * + * @return None + */ + + +void limCovertChannelScanType(tpAniSirGlobal pMac,tANI_U8 channelNum, tANI_BOOLEAN passiveToActive) +{ + + tANI_U32 i; + tANI_U8 channelPair[WNI_CFG_SCAN_CONTROL_LIST_LEN]; + tANI_U32 len = WNI_CFG_SCAN_CONTROL_LIST_LEN; + if (wlan_cfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len) + != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list"));) + return ; + } + if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) + { + limLog(pMac, LOGE, FL("Invalid scan control list length:%d"), len); + return ; + } + for (i=0; (i+1) < len; i+=2) + { + if (channelPair[i] == channelNum) + { + if ((eSIR_PASSIVE_SCAN == channelPair[i+1]) && TRUE == passiveToActive) + { + PELOG1(limLog(pMac, LOG1, FL("Channel %d changed from Passive to Active"), + channelNum);) + channelPair[i+1] = eSIR_ACTIVE_SCAN; + break ; + } + if ((eSIR_ACTIVE_SCAN == channelPair[i+1]) && FALSE == passiveToActive) + { + PELOG1(limLog(pMac, LOG1, FL("Channel %d changed from Active to Passive"), + channelNum);) + channelPair[i+1] = eSIR_PASSIVE_SCAN; + break ; + } + } + } + + cfgSetStrNotify(pMac, WNI_CFG_SCAN_CONTROL_LIST, (tANI_U8 *)channelPair, len, FALSE); + return ; +} + + + + +/* limSetDFSChannelList() + * + *FUNCTION: + * This function is called to convert DFS channel list to active channel list when any + * beacon is present on that channel. This function store time for passive channels + * which help to know that for how much time channel has been passive. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: If a channel is ACTIVE, it won't store any time + * If a channel is PAssive, it will store time as timestamp + * NA + * + * @param pMac - Pointer to Global MAC structure + * dfsChannelList - DFS channel list. + * @return None + */ + +void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannelList *dfsChannelList) +{ + + tANI_BOOLEAN passiveToActive = TRUE; + if ((1 <= channelNum) && (165 >= channelNum)) + { + if (eANI_BOOLEAN_TRUE == limIsconnectedOnDFSChannel(channelNum)) + { + if (dfsChannelList->timeStamp[channelNum] == 0) + { + //Received first beacon; Convert DFS channel to Active channel. + PELOG1(limLog(pMac, LOG1, FL("Received first beacon on DFS channel: %d"), channelNum);) + limCovertChannelScanType(pMac,channelNum, passiveToActive); + } + dfsChannelList->timeStamp[channelNum] = vos_timer_get_system_time(); + } + else + { + return; + } + if (!tx_timer_running(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)) + { + tx_timer_activate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + } + } + else + { + PELOGE(limLog(pMac, LOGE, FL("Invalid Channel: %d"), channelNum);) + return; + } + + return; +} + + + + +/* +* Creates a Raw frame to be sent before every Scan, if required. +* If only infra link is active (mlmState = Link Estb), then send Data Null +* If only BT-AMP-AP link is active(mlmState = BSS_STARTED), then send CTS2Self frame. +* If only BT-AMP-STA link is active(mlmState = BSS_STARTED or Link Est) then send CTS2Self +* If Only IBSS link is active, then send CTS2Self +* for concurrent scenario: Infra+BT or Infra+IBSS, always send CTS2Self, no need to send Data Null +* +*/ +static void __limCreateInitScanRawFrame(tpAniSirGlobal pMac, + tpInitScanParams pInitScanParam) +{ + tANI_U8 i; + pInitScanParam->scanEntry.activeBSScnt = 0; + + /* Don't send CTS to self as we have issue with BTQM queues where BTQM can + * not handle transmition of CTS2self frames. Sending CTS 2 self at this + * juncture also doesn't serve much purpose as probe request frames go out + * immediately, No need to notify BSS in IBSS case. + * */ + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + if(pMac->lim.gpSession[i].limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) + { + if ((pMac->lim.gpSession[i].limSystemRole != eLIM_BT_AMP_STA_ROLE) && + (pInitScanParam->scanEntry.activeBSScnt < HAL_NUM_BSSID)) + { + pInitScanParam->scanEntry.bssIdx[pInitScanParam->scanEntry.activeBSScnt] + = pMac->lim.gpSession[i].bssIdx; + pInitScanParam->scanEntry.activeBSScnt++; + + } + } + else if( (eLIM_AP_ROLE == pMac->lim.gpSession[i].limSystemRole ) + && ( VOS_P2P_GO_MODE == pMac->lim.gpSession[i].pePersona ) + ) + { + pInitScanParam->useNoA = TRUE; + } + } + } + if (pInitScanParam->scanEntry.activeBSScnt) + { + pInitScanParam->notifyBss = TRUE; + pInitScanParam->frameType = SIR_MAC_DATA_FRAME; + pInitScanParam->frameLength = 0; + } +} + +/* +* Creates a Raw frame to be sent during finish scan, if required. +* Send data null frame, only when there is just one session active and that session is +* in 'link Estb' state. +* if more than one session is active, don't send any frame. +* for concurrent scenario: Infra+BT or Infra+IBSS, no need to send Data Null +* +*/ +static void __limCreateFinishScanRawFrame(tpAniSirGlobal pMac, + tpFinishScanParams pFinishScanParam) +{ + tANI_U8 i; + pFinishScanParam->scanEntry.activeBSScnt = 0; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + if(pMac->lim.gpSession[i].limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) + { + //BT-STA can either be in LINK-ESTB state or BSS_STARTED State + //for BT, need to send CTS2Self + if ((pMac->lim.gpSession[i].limSystemRole != eLIM_BT_AMP_STA_ROLE) && + (pFinishScanParam->scanEntry.activeBSScnt < HAL_NUM_BSSID)) + { + pFinishScanParam->scanEntry.bssIdx[pFinishScanParam->scanEntry.activeBSScnt] + = pMac->lim.gpSession[i].bssIdx; + pFinishScanParam->scanEntry.activeBSScnt++; + } + } + } + } + + if (pFinishScanParam->scanEntry.activeBSScnt) + { + pFinishScanParam->notifyBss = TRUE; + pFinishScanParam->frameType = SIR_MAC_DATA_FRAME; + pFinishScanParam->frameLength = 0; + } +} + +void +limSendHalInitScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState, tSirLinkTrafficCheck trafficCheck) +{ + + + tSirMsgQ msg; + tpInitScanParams pInitScanParam; + tSirRetStatus rc = eSIR_SUCCESS; + + pInitScanParam = vos_mem_malloc(sizeof(*pInitScanParam)); + if ( NULL == pInitScanParam ) + { + PELOGW(limLog(pMac, LOGW, FL("AllocateMemory() failed"));) + goto error; + } + + /*Initialize the pInitScanParam with 0*/ + vos_mem_set((tANI_U8 *)pInitScanParam, sizeof(*pInitScanParam), 0); + + msg.type = WDA_INIT_SCAN_REQ; + msg.bodyptr = pInitScanParam; + msg.bodyval = 0; + + vos_mem_set((tANI_U8 *)&pInitScanParam->macMgmtHdr, sizeof(tSirMacMgmtHdr), 0); + if (nextState == eLIM_HAL_INIT_LEARN_WAIT_STATE) + { + pInitScanParam->notifyBss = TRUE; + pInitScanParam->notifyHost = FALSE; + if (eSIR_CHECK_ROAMING_SCAN == trafficCheck) + { + pInitScanParam->scanMode = eHAL_SYS_MODE_ROAM_SCAN; + } + else + { + pInitScanParam->scanMode = eHAL_SYS_MODE_LEARN; + } + + pInitScanParam->frameType = SIR_MAC_CTRL_CTS; + __limCreateInitScanRawFrame(pMac, pInitScanParam); + pInitScanParam->checkLinkTraffic = trafficCheck; + } + else + { + if(nextState == eLIM_HAL_SUSPEND_LINK_WAIT_STATE) + { + if (eSIR_CHECK_ROAMING_SCAN == trafficCheck) + { + pInitScanParam->scanMode = eHAL_SYS_MODE_ROAM_SUSPEND_LINK; + } + else + { + pInitScanParam->scanMode = eHAL_SYS_MODE_SUSPEND_LINK; + } + + } + else + { + if (eSIR_CHECK_ROAMING_SCAN == trafficCheck) + { + pInitScanParam->scanMode = eHAL_SYS_MODE_ROAM_SCAN; + } + else + { + pInitScanParam->scanMode = eHAL_SYS_MODE_SCAN; + } + } + __limCreateInitScanRawFrame(pMac, pInitScanParam); + if (pInitScanParam->useNoA) + { + pInitScanParam->scanDuration = pMac->lim.gTotalScanDuration; + } + /* Inform HAL whether it should check for traffic on the link + * prior to performing a background scan + */ + pInitScanParam->checkLinkTraffic = trafficCheck; + } + + pMac->lim.gLimHalScanState = nextState; + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc == eSIR_SUCCESS) { + PELOG3(limLog(pMac, LOG3, FL("wdaPostCtrlMsg() return eSIR_SUCCESS pMac=%x nextState=%d"), + pMac, pMac->lim.gLimHalScanState);) + return; + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pInitScanParam); + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) + +error: + switch(nextState) + { + case eLIM_HAL_START_SCAN_WAIT_STATE: + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); + break; + + + //WLAN_SUSPEND_LINK Related + case eLIM_HAL_SUSPEND_LINK_WAIT_STATE: + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + if( pMac->lim.gpLimSuspendCallback ) + { + pMac->lim.gpLimSuspendCallback( pMac, rc, pMac->lim.gpLimSuspendData ); + pMac->lim.gpLimSuspendCallback = NULL; + pMac->lim.gpLimSuspendData = NULL; + } + pMac->lim.gLimSystemInScanLearnMode = 0; + break; + //end WLAN_SUSPEND_LINK Related + default: + break; + } + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + + return ; +} + +void +limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanState nextState) +{ + tSirMsgQ msg; + tpStartScanParams pStartScanParam; + tSirRetStatus rc = eSIR_SUCCESS; + + /** + * The Start scan request to be sent only if Start Scan is not already requested + */ + if(pMac->lim.gLimHalScanState != eLIM_HAL_START_SCAN_WAIT_STATE) + { + + pStartScanParam = vos_mem_malloc(sizeof(*pStartScanParam)); + if ( NULL == pStartScanParam ) + { + PELOGW(limLog(pMac, LOGW, FL("AllocateMemory() failed"));) + goto error; + } + + msg.type = WDA_START_SCAN_REQ; + msg.bodyptr = pStartScanParam; + msg.bodyval = 0; + pStartScanParam->status = eHAL_STATUS_SUCCESS; + pStartScanParam->scanChannel = (tANI_U8)channelNum; + + pMac->lim.gLimHalScanState = nextState; + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + limLog(pMac, LOG1, FL("Channel %d"), channelNum); + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc == eSIR_SUCCESS) { + return; + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pStartScanParam); + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) + +error: + switch(nextState) + { + case eLIM_HAL_START_SCAN_WAIT_STATE: + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); + break; + + + default: + break; + } + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + + } + else + { + PELOGW(limLog(pMac, LOGW, FL("Invalid state for START_SCAN_REQ message=%d"), pMac->lim.gLimHalScanState);) + } + + return; +} + +void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanState nextState) +{ + tSirMsgQ msg; + tpEndScanParams pEndScanParam; + tSirRetStatus rc = eSIR_SUCCESS; + + /** + * The End scan request to be sent only if End Scan is not already requested or + * Start scan is not already requestd. + * after finish scan rsp from firmware host is sending endscan request so adding + * check for IDLE SCAN STATE also added to avoid this issue + */ + if((pMac->lim.gLimHalScanState != eLIM_HAL_END_SCAN_WAIT_STATE) && + (pMac->lim.gLimHalScanState != eLIM_HAL_IDLE_SCAN_STATE) && + (pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) && + (pMac->lim.gLimHalScanState != eLIM_HAL_FINISH_SCAN_WAIT_STATE) && + (pMac->lim.gLimHalScanState != eLIM_HAL_START_SCAN_WAIT_STATE)) + { + pEndScanParam = vos_mem_malloc(sizeof(*pEndScanParam)); + if ( NULL == pEndScanParam ) + { + PELOGW(limLog(pMac, LOGW, FL("AllocateMemory() failed"));) + goto error; + } + + msg.type = WDA_END_SCAN_REQ; + msg.bodyptr = pEndScanParam; + msg.bodyval = 0; + pEndScanParam->status = eHAL_STATUS_SUCCESS; + pEndScanParam->scanChannel = (tANI_U8)channelNum; + + pMac->lim.gLimHalScanState = nextState; + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc == eSIR_SUCCESS) { + return; + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pEndScanParam); + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) + + error: + switch(nextState) + { + case eLIM_HAL_END_SCAN_WAIT_STATE: + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_END_FAILED); + break; + + + default: + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg Rcvd invalid nextState %d"), nextState);) + break; + } + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) + } + else + { + PELOGW(limLog(pMac, LOGW, FL("Invalid state for END_SCAN_REQ message=%d"), pMac->lim.gLimHalScanState);) + } + + + return; +} + +/** + * limSendHalFinishScanReq() + * + *FUNCTION: + * This function is called to finish scan/learn request.. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param nextState - this parameters determines whether this call is for scan or learn + * + * @return None + */ +void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) +{ + + tSirMsgQ msg; + tpFinishScanParams pFinishScanParam; + tSirRetStatus rc = eSIR_SUCCESS; + + if(pMac->lim.gLimHalScanState == nextState) + { + /* + * PE may receive multiple probe responses, while waiting for HAL to send 'FINISH_SCAN_RSP' message + * PE was sending multiple finish scan req messages to HAL + * this check will avoid that. + * If PE is already waiting for the 'finish_scan_rsp' message from HAL, it will ignore this request. + */ + PELOGW(limLog(pMac, LOGW, FL("Next Scan State is same as the current state: %d "), nextState);) + return; + } + + pFinishScanParam = vos_mem_malloc(sizeof(*pFinishScanParam)); + if ( NULL == pFinishScanParam ) + { + PELOGW(limLog(pMac, LOGW, FL("AllocateMemory() failed"));) + goto error; + } + + msg.type = WDA_FINISH_SCAN_REQ; + msg.bodyptr = pFinishScanParam; + msg.bodyval = 0; + + peGetResumeChannel(pMac, &pFinishScanParam->currentOperChannel, &pFinishScanParam->cbState); + + vos_mem_set((tANI_U8 *)&pFinishScanParam->macMgmtHdr, sizeof(tSirMacMgmtHdr), 0); + + if (nextState == eLIM_HAL_FINISH_LEARN_WAIT_STATE) + { + //AP - No pkt need to be transmitted + pFinishScanParam->scanMode = eHAL_SYS_MODE_LEARN; + pFinishScanParam->notifyBss = FALSE; + pFinishScanParam->notifyHost = FALSE; + pFinishScanParam->frameType = 0; + + pFinishScanParam->frameLength = 0; + pMac->lim.gLimHalScanState = nextState; + } + else + { + /* If STA is associated with an AP (ie. STA is in + * LINK_ESTABLISHED state), then STA need to inform + * the AP via either DATA-NULL + */ + if (nextState == eLIM_HAL_RESUME_LINK_WAIT_STATE) + { + pFinishScanParam->scanMode = eHAL_SYS_MODE_SUSPEND_LINK; + } + else + { + pFinishScanParam->scanMode = eHAL_SYS_MODE_SCAN; + } + pFinishScanParam->notifyHost = FALSE; + __limCreateFinishScanRawFrame(pMac, pFinishScanParam); + //WLAN_SUSPEND_LINK Related + pMac->lim.gLimHalScanState = nextState; + //end WLAN_SUSPEND_LINK Related + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc == eSIR_SUCCESS) { + return; + } + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pFinishScanParam); + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) + + error: + if(nextState == eLIM_HAL_FINISH_SCAN_WAIT_STATE) + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_FINISH_FAILED); + //WLAN_SUSPEND_LINK Related + else if ( nextState == eLIM_HAL_RESUME_LINK_WAIT_STATE ) + { + if( pMac->lim.gpLimResumeCallback ) + { + pMac->lim.gpLimResumeCallback( pMac, rc, pMac->lim.gpLimResumeData ); + pMac->lim.gpLimResumeCallback = NULL; + pMac->lim.gpLimResumeData = NULL; + pMac->lim.gLimSystemInScanLearnMode = 0; + } + } + //end WLAN_SUSPEND_LINK Related + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + return; +} + +/** + * limContinueChannelScan() + * + *FUNCTION: + * This function is called by limPerformChannelScan(). + * This function is called to continue channel scanning when + * Beacon/Probe Response frame are received. + * + *LOGIC: + * Scan criteria stored in pMac->lim.gLimMlmScanReq is used + * to perform channel scan. In this function MLM sub module + * makes channel switch, sends PROBE REQUEST frame in case of + * ACTIVE SCANNING, starts min/max channel timers, programs + * NAV to probeDelay timer and waits for Beacon/Probe Response. + * Once all required channels are scanned, LIM_MLM_SCAN_CNF + * primitive is used to send Scan results to SME sub module. + * + *ASSUMPTIONS: + * 1. In case of Active scanning, start MAX channel time iff + * MIN channel timer expired and activity is observed on + * the channel. + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @return None + */ +void +limContinueChannelScan(tpAniSirGlobal pMac) +{ + tANI_U8 channelNum; + + if (pMac->lim.gLimCurrentScanChannelId > + (tANI_U32) (pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1) + || pMac->lim.abortScan) + { + pMac->lim.abortScan = 0; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + + /// Done scanning all required channels + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + return; + } + + /// Atleast one more channel is to be scanned + + if ((pMac->lim.gLimReturnAfterFirstMatch & 0x40) || + (pMac->lim.gLimReturnAfterFirstMatch & 0x80)) + { + while (pMac->lim.gLimCurrentScanChannelId <= + (tANI_U32) (pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1)) + { + if (((limGetCurrentScanChannel(pMac) <= 14) && + pMac->lim.gLim24Band11dScanDone) || + ((limGetCurrentScanChannel(pMac) > 14) && + pMac->lim.gLim50Band11dScanDone)) + { + limLog(pMac, LOGW, FL("skipping chan %d"), + limGetCurrentScanChannel(pMac)); + pMac->lim.gLimCurrentScanChannelId++; + } + else + break; + } + + if (pMac->lim.gLimCurrentScanChannelId > + (tANI_U32) (pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1)) + { + pMac->lim.abortScan = 0; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + /// Done scanning all required channels + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + return; + } + } + + channelNum = limGetCurrentScanChannel(pMac); + PELOG2(limLog(pMac, LOG2, FL("Current Channel to be scanned is %d"), + channelNum);) + + limSendHalStartScanReq(pMac, channelNum, eLIM_HAL_START_SCAN_WAIT_STATE); + return; +} /*** end limContinueChannelScan() ***/ + + + +/** + * limRestorePreScanState() + * + *FUNCTION: + * This function is called by limContinueChannelScan() + * to restore HW state prior to entering 'scan state' + * + *LOGIC + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @return None + */ +void +limRestorePreScanState(tpAniSirGlobal pMac) +{ + int i; + + /// Deactivate MIN/MAX channel timers if running + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + + /* Re-activate Heartbeat timers for connected sessions as scan + * is done if the DUT is in active mode + * AND it is not a ROAMING ("background") scan */ + if(pMac->psOffloadEnabled) + { + if((pMac->lim.gLimBackgroundScanMode != eSIR_ROAMING_SCAN) && + (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + for(i=0;ilim.maxBssId;i++) + { + tpPESession psessionEntry = peFindSessionBySessionId(pMac,i); + if(psessionEntry && psessionEntry->valid && + (eLIM_MLM_LINK_ESTABLISHED_STATE == + psessionEntry->limMlmState) && + (psessionEntry->pmmOffloadInfo.psstate == PMM_FULL_POWER)) + { + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + } + } + } + else if(((ePMM_STATE_BMPS_WAKEUP == pMac->pmm.gPmmState) || + (ePMM_STATE_READY == pMac->pmm.gPmmState)) + && (pMac->lim.gLimBackgroundScanMode != eSIR_ROAMING_SCAN )) + { + for(i=0;ilim.maxBssId;i++) + { + if((peFindSessionBySessionId(pMac,i) != NULL) && + (pMac->lim.gpSession[i].valid == TRUE) && + (eLIM_MLM_LINK_ESTABLISHED_STATE == pMac->lim.gpSession[i].limMlmState) && + (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + limReactivateHeartBeatTimer(pMac, peFindSessionBySessionId(pMac,i)); + } + } + } + + pMac->lim.gLimSystemInScanLearnMode = 0; + PELOG1(limLog(pMac, LOG1, FL("Scan ended, took %d tu"), (tx_time_get() - pMac->lim.scanStartTime));) +} /*** limRestorePreScanState() ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +void limSendHalOemDataReq(tpAniSirGlobal pMac) +{ + tSirMsgQ msg; + tpStartOemDataReq pStartOemDataReq = NULL; + tSirRetStatus rc = eSIR_SUCCESS; + tpLimMlmOemDataRsp pMlmOemDataRsp; + tANI_U32 reqLen = 0; + if(NULL == pMac->lim.gpLimMlmOemDataReq) + { + PELOGE(limLog(pMac, LOGE, FL("Null pointer"));) + goto error; + } + + reqLen = sizeof(tStartOemDataReq); + + pStartOemDataReq = vos_mem_malloc(reqLen); + if ( NULL == pStartOemDataReq ) + { + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq"));) + goto error; + } + + vos_mem_set((tANI_U8*)(pStartOemDataReq), reqLen, 0); + + //Now copy over the information to the OEM DATA REQ to HAL + vos_mem_copy(pStartOemDataReq->selfMacAddr, + pMac->lim.gpLimMlmOemDataReq->selfMacAddr, + sizeof(tSirMacAddr)); + + vos_mem_copy(pStartOemDataReq->oemDataReq, + pMac->lim.gpLimMlmOemDataReq->oemDataReq, + OEM_DATA_REQ_SIZE); + + //Create the message to be passed to HAL + msg.type = WDA_START_OEM_DATA_REQ; + msg.bodyptr = pStartOemDataReq; + msg.bodyval = 0; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + rc = wdaPostCtrlMsg(pMac, &msg); + if(rc == eSIR_SUCCESS) + { + return; + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pStartOemDataReq); + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_START_OEM_DATA_REQ to HAL failed"));) + +error: + pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState)); + + pMlmOemDataRsp = vos_mem_malloc(sizeof(tLimMlmOemDataRsp)); + if ( NULL == pMlmOemDataRsp ) + { + limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure")); + return; + } + + if(NULL != pMac->lim.gpLimMlmOemDataReq) + { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq); + pMac->lim.gpLimMlmOemDataReq = NULL; + } + + limPostSmeMessage(pMac, LIM_MLM_OEM_DATA_CNF, (tANI_U32*)pMlmOemDataRsp); + + return; +} +/** + * limSetOemDataReqModeFailed() + * + * FUNCTION: + * This function is used as callback to resume link after the suspend fails while + * starting oem data req mode. + * LOGIC: + * NA + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void limSetOemDataReqModeFailed(tpAniSirGlobal pMac, eHalStatus status, tANI_U32* data) +{ + tpLimMlmOemDataRsp pMlmOemDataRsp; + + pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState)); + + pMlmOemDataRsp = vos_mem_malloc(sizeof(tLimMlmOemDataRsp)); + if ( NULL == pMlmOemDataRsp ) + { + limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure")); + return; + } + + if (NULL != pMac->lim.gpLimMlmOemDataReq) + { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq); + pMac->lim.gpLimMlmOemDataReq = NULL; + } + + vos_mem_set(pMlmOemDataRsp, sizeof(tLimMlmOemDataRsp), 0); + + limPostSmeMessage(pMac, LIM_MLM_OEM_DATA_CNF, (tANI_U32*)pMlmOemDataRsp); + + return; +} + +/** + * limSetOemDataReqMode() + * + *FUNCTION: + * This function is called to setup system into OEM DATA REQ mode + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void limSetOemDataReqMode(tpAniSirGlobal pMac, eHalStatus status, tANI_U32* data) +{ + if(status != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGE, FL("OEM_DATA: failed in suspend link")); + /* If failed to suspend the link, there is no need + * to resume link. Return failure. + */ + limSetOemDataReqModeFailed(pMac, status, data); + } + else + { + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Calling limSendHalOemDataReq"));) + limSendHalOemDataReq(pMac); + } + + return; +} /*** end limSendHalOemDataReq() ***/ + +#endif //FEATURE_OEM_DATA_SUPPORT + +static void +mlm_add_sta( + tpAniSirGlobal pMac, + tpAddStaParams pSta, + tANI_U8 *pBssid, + tANI_U8 htCapable, + tpPESession psessionEntry) //psessionEntry may required in future +{ + tANI_U32 val; + int i; + tANI_U32 selfStaDot11Mode = 0; + + wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); + pSta->staType = STA_ENTRY_SELF; // Identifying self + + vos_mem_copy(pSta->bssId, pBssid, sizeof( tSirMacAddr )); + vos_mem_copy(pSta->staMac, psessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + + /* Configuration related parameters to be changed to support BT-AMP */ + + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_LISTEN_INTERVAL, &val )) + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); + + pSta->listenInterval = (tANI_U16) val; + + if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) ) + limLog(pMac, LOGP, FL("Couldn't get SHORT_PREAMBLE")); + pSta->shortPreambleSupported = (tANI_U8)val; + + pSta->assocId = 0; // Is SMAC OK with this? + pSta->wmmEnabled = 0; + pSta->uAPSD = 0; + pSta->maxSPLen = 0; + pSta->us32MaxAmpduDuration = 0; + pSta->maxAmpduSize = 0; // 0: 8k, 1: 16k,2: 32k,3: 64k, 4:128k + + + /* For Self STA get the LDPC capability from config.ini*/ + pSta->htLdpcCapable = + (psessionEntry->txLdpcIniFeatureEnabled & 0x01); + pSta->vhtLdpcCapable = + ((psessionEntry->txLdpcIniFeatureEnabled >> 1)& 0x01); + + if(IS_DOT11_MODE_HT(psessionEntry->dot11mode)) + { + pSta->htCapable = htCapable; + pSta->greenFieldCapable = limGetHTCapability( pMac, eHT_GREENFIELD, psessionEntry); + pSta->txChannelWidthSet = limGetHTCapability( pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry ); + pSta->mimoPS = (tSirMacHTMIMOPowerSaveState)limGetHTCapability( pMac, eHT_MIMO_POWER_SAVE, psessionEntry ); + pSta->rifsMode = limGetHTCapability( pMac, eHT_RIFS_MODE, psessionEntry ); + pSta->lsigTxopProtection = limGetHTCapability( pMac, eHT_LSIG_TXOP_PROTECTION, psessionEntry ); + pSta->delBASupport = limGetHTCapability( pMac, eHT_DELAYED_BA, psessionEntry ); + pSta->maxAmpduDensity = limGetHTCapability( pMac, eHT_MPDU_DENSITY, psessionEntry ); + pSta->maxAmsduSize = limGetHTCapability( pMac, eHT_MAX_AMSDU_LENGTH, psessionEntry ); + pSta->max_amsdu_num = limGetHTCapability(pMac, eHT_MAX_AMSDU_NUM, + psessionEntry); + pSta->fDsssCckMode40Mhz = limGetHTCapability( pMac, eHT_DSSS_CCK_MODE_40MHZ, psessionEntry); + pSta->fShortGI20Mhz = limGetHTCapability( pMac, eHT_SHORT_GI_20MHZ, psessionEntry); + pSta->fShortGI40Mhz = limGetHTCapability( pMac, eHT_SHORT_GI_40MHZ, psessionEntry); + } +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability) + { + pSta->vhtCapable = VOS_TRUE; + pSta->vhtTxBFCapable = psessionEntry->txBFIniFeatureEnabled; + pSta->vhtTxMUBformeeCapable = psessionEntry->txMuBformee; + } + + // Since this is Self-STA, need to populate Self MAX_AMPDU_SIZE capabilities + if( IS_DOT11_MODE_VHT(selfStaDot11Mode) ) + { + val = 0; // Default 8K AMPDU size + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, &val )) + limLog(pMac, LOGE, FL("Couldn't get WNI_CFG_VHT_AMPDU_LEN_EXPONENT")); + pSta->maxAmpduSize = (tANI_U8) val; + } + pSta->enableVhtpAid = psessionEntry->enableVhtpAid; +#endif + pSta->enableAmpduPs = psessionEntry->enableAmpduPs; + pSta->enableHtSmps = psessionEntry->enableHtSmps; + pSta->htSmpsconfig = psessionEntry->htSmpsvalue; + +#ifdef WLAN_FEATURE_11AC + limPopulateOwnRateSet(pMac, &pSta->supportedRates, NULL, false,psessionEntry,NULL); +#else + limPopulateOwnRateSet(pMac, &pSta->supportedRates, NULL, false,psessionEntry); +#endif + limFillSupportedRatesInfo(pMac, NULL, &pSta->supportedRates,psessionEntry); + + limLog( pMac, LOGE, FL( "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d, SGI20: %d, SGI40%d") , + pSta->greenFieldCapable, pSta->txChannelWidthSet, pSta->mimoPS, pSta->lsigTxopProtection, + pSta->fDsssCckMode40Mhz,pSta->fShortGI20Mhz, pSta->fShortGI40Mhz); + + if (VOS_P2P_GO_MODE == psessionEntry->pePersona) + { + pSta->p2pCapableSta = 1; + } + + //Disable BA. It will be set as part of ADDBA negotiation. + for( i = 0; i < STACFG_MAX_TC; i++ ) + { + pSta->staTCParams[i].txUseBA = eBA_DISABLE; + pSta->staTCParams[i].rxUseBA = eBA_DISABLE; + } + +} + +// +// New HAL interface - WDA_ADD_BSS_REQ +// Package WDA_ADD_BSS_REQ to HAL, in order to start a BSS +// +tSirResultCodes +limMlmAddBss ( + tpAniSirGlobal pMac, + tLimMlmStartReq *pMlmStartReq, + tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpAddBssParams pAddBssParams = NULL; + tANI_U32 retCode; + + // Package WDA_ADD_BSS_REQ message parameters + + pAddBssParams = vos_mem_malloc(sizeof( tAddBssParams )); + if ( NULL == pAddBssParams ) + { + limLog( pMac, LOGE, FL( "Unable to allocate memory during ADD_BSS" )); + // Respond to SME with LIM_MLM_START_CNF + return eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + + vos_mem_set(pAddBssParams, sizeof(tAddBssParams), 0); + + // Fill in tAddBssParams members + vos_mem_copy(pAddBssParams->bssId, pMlmStartReq->bssId, + sizeof( tSirMacAddr )); + + // Fill in tAddBssParams selfMacAddr + vos_mem_copy (pAddBssParams->selfMacAddr, + psessionEntry->selfMacAddr, + sizeof( tSirMacAddr )); + + pAddBssParams->bssType = pMlmStartReq->bssType; + if ((pMlmStartReq->bssType == eSIR_IBSS_MODE) || + (pMlmStartReq->bssType == eSIR_BTAMP_AP_MODE)|| + (pMlmStartReq->bssType == eSIR_BTAMP_STA_MODE)) { + pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA; + } + else if (pMlmStartReq->bssType == eSIR_INFRA_AP_MODE){ + pAddBssParams->operMode = BSS_OPERATIONAL_MODE_AP; + } + + pAddBssParams->shortSlotTimeSupported = psessionEntry->shortSlotTimeSupported; + + pAddBssParams->beaconInterval = pMlmStartReq->beaconPeriod; + pAddBssParams->dtimPeriod = pMlmStartReq->dtimPeriod; + pAddBssParams->wps_state = pMlmStartReq->wps_state; + pAddBssParams->cfParamSet.cfpCount = pMlmStartReq->cfParamSet.cfpCount; + pAddBssParams->cfParamSet.cfpPeriod = pMlmStartReq->cfParamSet.cfpPeriod; + pAddBssParams->cfParamSet.cfpMaxDuration = pMlmStartReq->cfParamSet.cfpMaxDuration; + pAddBssParams->cfParamSet.cfpDurRemaining = pMlmStartReq->cfParamSet.cfpDurRemaining; + + pAddBssParams->rateSet.numRates = pMlmStartReq->rateSet.numRates; + vos_mem_copy(pAddBssParams->rateSet.rate, + pMlmStartReq->rateSet.rate, pMlmStartReq->rateSet.numRates); + + pAddBssParams->nwType = pMlmStartReq->nwType; + + pAddBssParams->htCapable = pMlmStartReq->htCapable; +#ifdef WLAN_FEATURE_11AC + pAddBssParams->vhtCapable = psessionEntry->vhtCapability; + pAddBssParams->vhtTxChannelWidthSet = psessionEntry->vhtTxChannelWidthSet; +#endif + pAddBssParams->htOperMode = pMlmStartReq->htOperMode; + pAddBssParams->dualCTSProtection = pMlmStartReq->dualCTSProtection; + pAddBssParams->txChannelWidthSet = pMlmStartReq->txChannelWidthSet; + + pAddBssParams->currentOperChannel = pMlmStartReq->channelNumber; + pAddBssParams->currentExtChannel = pMlmStartReq->cbMode; + +#ifdef WLAN_FEATURE_11W + pAddBssParams->rmfEnabled = psessionEntry->limRmfEnabled; +#endif + + /* Update PE sessionId*/ + pAddBssParams->sessionId = pMlmStartReq->sessionId; + + //Send the SSID to HAL to enable SSID matching for IBSS + vos_mem_copy(&(pAddBssParams->ssId.ssId), + pMlmStartReq->ssId.ssId, + pMlmStartReq->ssId.length); + pAddBssParams->ssId.length = pMlmStartReq->ssId.length; + pAddBssParams->bHiddenSSIDEn = pMlmStartReq->ssidHidden; + limLog( pMac, LOGE, FL( "TRYING TO HIDE SSID %d" ),pAddBssParams->bHiddenSSIDEn); + // CR309183. Disable Proxy Probe Rsp. Host handles Probe Requests. Until FW fixed. + pAddBssParams->bProxyProbeRespEn = 0; + pAddBssParams->obssProtEnabled = pMlmStartReq->obssProtEnabled; + +#if defined WLAN_FEATURE_VOWIFI + pAddBssParams->maxTxPower = psessionEntry->maxTxPower; +#endif + mlm_add_sta(pMac, &pAddBssParams->staContext, + pAddBssParams->bssId, pAddBssParams->htCapable,psessionEntry); + + pAddBssParams->status = eHAL_STATUS_SUCCESS; + pAddBssParams->respReqd = 1; + + // Set a new state for MLME + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + pAddBssParams->halPersona=psessionEntry->pePersona; //pass on the session persona to hal + + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled || + limIsconnectedOnDFSChannel(pMlmStartReq->channelNumber); + +#if defined WLAN_FEATURE_VOWIFI_11R + pAddBssParams->extSetStaKeyParamValid = 0; +#endif + + if (VOS_IBSS_MODE == pAddBssParams->halPersona) { + pAddBssParams->nss_2g = pMac->vdev_type_nss_2g.ibss; + pAddBssParams->nss_5g = pMac->vdev_type_nss_5g.ibss; + } + pAddBssParams->dot11_mode = psessionEntry->dot11mode; + limLog(pMac, LOG2, FL("dot11_mode:%d"), pAddBssParams->dot11_mode); + + msgQ.type = WDA_ADD_BSS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pAddBssParams; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + limLog( pMac, LOGW, FL( "Sending WDA_ADD_BSS_REQ..." )); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), retCode ); + vos_mem_free(pAddBssParams); + return eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + + return eSIR_SME_SUCCESS; +} + + +/** + * limProcessMlmStartReq() + * + *FUNCTION: + * This function is called to process MLM_START_REQ message + * from SME + * + *LOGIC: + * 1) MLME receives LIM_MLM_START_REQ from LIM + * 2) MLME sends WDA_ADD_BSS_REQ to HAL + * 3) MLME changes state to eLIM_MLM_WT_ADD_BSS_RSP_STATE + * MLME now waits for HAL to send WDA_ADD_BSS_RSP + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmStartReq *pMlmStartReq; + tLimMlmStartCnf mlmStartCnf; + tpPESession psessionEntry = NULL; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmStartReq = (tLimMlmStartReq *) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmStartReq->sessionId))==NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + mlmStartCnf.resultCode = eSIR_SME_REFUSED; + goto end; + } + + if (psessionEntry->limMlmState != eLIM_MLM_IDLE_STATE) + { + /** + * Should not have received Start req in states other than idle. + * Return Start confirm with failure code. + */ + PELOGE(limLog(pMac, LOGE, FL("received unexpected MLM_START_REQ in state %X"),psessionEntry->limMlmState);) + limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); + mlmStartCnf.resultCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + goto end; + } + mlmStartCnf.resultCode = limMlmAddBss(pMac, pMlmStartReq,psessionEntry); + +end: + /* Update PE session Id */ + mlmStartCnf.sessionId = pMlmStartReq->sessionId; + + /// Free up buffer allocated for LimMlmScanReq + vos_mem_free(pMsgBuf); + + // + // Respond immediately to LIM, only if MLME has not been + // successfully able to send WDA_ADD_BSS_REQ to HAL. + // Else, LIM_MLM_START_CNF will be sent after receiving + // WDA_ADD_BSS_RSP from HAL + // + if( eSIR_SME_SUCCESS != mlmStartCnf.resultCode ) + limPostSmeMessage(pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf); +} /*** limProcessMlmStartReq() ***/ + + +/* +* This function checks if Scan is allowed or not. +* It checks each session and if any session is not in the normal state, +* it will return false. +* Note: BTAMP_STA can be in LINK_EST as well as BSS_STARTED State, so +* both cases are handled below. +*/ + +static tANI_U8 __limMlmScanAllowed(tpAniSirGlobal pMac) +{ + int i; + + if(pMac->lim.gLimMlmState != eLIM_MLM_IDLE_STATE) + { + return FALSE; + } + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + if(!( ( ( (pMac->lim.gpSession[i].bssType == eSIR_INFRASTRUCTURE_MODE) || + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_STA_ROLE))&& + (pMac->lim.gpSession[i].limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) )|| + + ( ( (pMac->lim.gpSession[i].bssType == eSIR_IBSS_MODE)|| + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_AP_ROLE)|| + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_STA_ROLE) )&& + (pMac->lim.gpSession[i].limMlmState == eLIM_MLM_BSS_STARTED_STATE) ) + || ( ( ( (pMac->lim.gpSession[i].bssType == eSIR_INFRA_AP_MODE) + && ( pMac->lim.gpSession[i].pePersona == VOS_P2P_GO_MODE) ) + || (pMac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) ) + && (pMac->lim.gpSession[i].limMlmState == eLIM_MLM_BSS_STARTED_STATE) ) + )) + { + return FALSE; + + } + } + } + + return TRUE; +} + + + +/** + * limProcessMlmScanReq() + * + *FUNCTION: + * This function is called to process MLM_SCAN_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmScanCnf mlmScanCnf; + tANI_U8 i = 0; + tANI_U32 val = 0; + + if (pMac->lim.gLimSystemInScanLearnMode) + { + PELOGE(limLog(pMac, LOGE, + FL("Sending START_SCAN from LIM while one req is pending"));) + vos_mem_free(pMsgBuf); + /*Send back a failure*/ + mlmScanCnf.resultCode = eSIR_SME_SCAN_FAILED; + mlmScanCnf.scanResultLength = 0; + limPostSmeMessage(pMac, + LIM_MLM_SCAN_CNF, + (tANI_U32 *) &mlmScanCnf); + return; + } + + if(__limMlmScanAllowed(pMac) && + (((tLimMlmScanReq *) pMsgBuf)->channelList.numChannels != 0)) + + { + /// Hold onto SCAN REQ criteria + pMac->lim.gpLimMlmScanReq = (tLimMlmScanReq *) pMsgBuf; + + PELOG3(limLog(pMac, LOG3, FL("Number of channels to scan are %d "), + pMac->lim.gpLimMlmScanReq->channelList.numChannels);) + + pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState; + + if (pMac->lim.gpLimMlmScanReq->scanType == eSIR_ACTIVE_SCAN) + pMac->lim.gLimMlmState = eLIM_MLM_WT_PROBE_RESP_STATE; + else + pMac->lim.gLimMlmState = eLIM_MLM_PASSIVE_SCAN_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState)); + + pMac->lim.gLimSystemInScanLearnMode = 1; + + /* temporary fix to handle case where NOA duration calculation is incorrect + * for scanning on DFS channels */ + + pMac->lim.gTotalScanDuration = 0; + + if (wlan_cfgGetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, &val) != eSIR_SUCCESS) + { + /* + * Could not get max channel value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); + + /* use a default value of 110ms */ + val = 110; + } + + for (i = 0; i < pMac->lim.gpLimMlmScanReq->channelList.numChannels; i++) { + tANI_U8 channelNum = pMac->lim.gpLimMlmScanReq->channelList.channelNumber[i]; + + if (limActiveScanAllowed(pMac, channelNum)) { + /* Use min + max channel time to calculate the total duration of scan */ + pMac->lim.gTotalScanDuration += pMac->lim.gpLimMlmScanReq->minChannelTime + pMac->lim.gpLimMlmScanReq->maxChannelTime; + } else { + /* using the value from WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME as is done in + * void limContinuePostChannelScan(tpAniSirGlobal pMac) + */ + pMac->lim.gTotalScanDuration += val; + } + } + + /* Adding an overhead of 5ms to account for the scan messaging delays */ + pMac->lim.gTotalScanDuration += 5; + limSetScanMode(pMac); + } + else + { + /** + * Should not have received SCAN req in other states + * OR should not have received LIM_MLM_SCAN_REQ with + * zero number of channels + * Log error + */ + limLog(pMac, LOGW, + FL("received unexpected MLM_SCAN_REQ in state %X OR zero number of channels: %X"), + pMac->lim.gLimMlmState, ((tLimMlmScanReq *) pMsgBuf)->channelList.numChannels); + limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); + + vos_mem_free(pMsgBuf); + + /// Return Scan confirm with INVALID_PARAMETERS + + mlmScanCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + mlmScanCnf.scanResultLength = 0; + limPostSmeMessage(pMac, + LIM_MLM_SCAN_CNF, + (tANI_U32 *) &mlmScanCnf); + } +} /*** limProcessMlmScanReq() ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT +static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmOemDataRsp* pMlmOemDataRsp; + + if (((pMac->lim.gLimMlmState == eLIM_MLM_IDLE_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_JOINED_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_AUTHENTICATED_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_BSS_STARTED_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE))) + { + //Hold onto the oem data request criteria + + /* + * Free gpLimMlmOemDataReq to avoid memory leak due to + * second OEM data request + */ + if (pMac->lim.gpLimMlmOemDataReq) { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq); + pMac->lim.gpLimMlmOemDataReq = NULL; + } + + pMac->lim.gpLimMlmOemDataReq = (tLimMlmOemDataReq*)pMsgBuf; + + pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState; + + PELOG2(limLog(pMac, LOG2, + FL("%s: Calling limSendHalOemDataReq"), __func__);) + limSendHalOemDataReq(pMac); + } + else + { + /** + * Should not have received oem data req in other states + * Log error + */ + + PELOGW(limLog(pMac, LOGW, FL("OEM_DATA: unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X"),pMac->lim.gLimMlmState);) + + limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); + + /// Free up buffer allocated + vos_mem_free(pMsgBuf); + + /// Return Meas confirm with INVALID_PARAMETERS + pMlmOemDataRsp = vos_mem_malloc(sizeof(tLimMlmOemDataRsp)); + if ( pMlmOemDataRsp != NULL) + { + limPostSmeMessage(pMac, LIM_MLM_OEM_DATA_CNF, (tANI_U32*)pMlmOemDataRsp); + vos_mem_free(pMlmOemDataRsp); + } + else + { + limLog(pMac, LOGP, FL("Could not allocate memory for pMlmOemDataRsp")); + return; + } + } + + return; +} +#endif //FEATURE_OEM_DATA_SUPPORT + +/** + * lim_post_join_set_link_state_callback()- registered callback to perform post + * peer creation operations + * + * @mac: pointer to global mac structure + * @callback_arg: registered callback argument + * @status: peer creation status + * + * this is registered callback function during association to perform + * post peer creation operation based on the peer creation status + * + * Return: none + */ +void lim_post_join_set_link_state_callback(tpAniSirGlobal mac, + void *callback_arg, bool status) +{ + uint8_t chan_num, sec_chan_offset; + tpPESession session_entry = (tpPESession) callback_arg; + tLimMlmJoinCnf mlm_join_cnf; + + limLog(mac, LOG1, FL("Sessionid %d set link state(%d) cb status:%d"), + session_entry->peSessionId, session_entry->limMlmState, + status); + + if (!status) { + limLog(mac, LOGE, FL("failed to find pe session for session id:%d"), + session_entry->peSessionId); + goto failure; + } + + chan_num = session_entry->currentOperChannel; + sec_chan_offset = session_entry->htSecondaryChannelOffset; + /* + * store the channel switch sessionEntry in the lim + * global variable + */ + session_entry->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_JOIN; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + session_entry->pLimMlmReassocRetryReq = NULL; +#endif + limLog(mac, LOG1, FL("[limProcessMlmJoinReq]: suspend link on sessionid: %d setting channel to: %d with secChanOffset:%d and maxtxPower: %d"), + session_entry->peSessionId, chan_num, + sec_chan_offset, + session_entry->maxTxPower); + limSetChannel(mac, chan_num, sec_chan_offset, + session_entry->maxTxPower, + session_entry->peSessionId); + return; + +failure: + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, session_entry->peSessionId, + session_entry->limMlmState)); + session_entry->limMlmState = eLIM_MLM_IDLE_STATE; + mlm_join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlm_join_cnf.sessionId = session_entry->peSessionId; + mlm_join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + limPostSmeMessage(mac, LIM_MLM_JOIN_CNF, (tANI_U32 *) &mlm_join_cnf); +} + +/** + * limProcessMlmPostJoinSuspendLink() + * + *FUNCTION: + * This function is called after the suspend link while joining + * off channel. + * + *LOGIC: + * Check for suspend state. + * If success, proceed with setting link state to recieve the + * probe response/beacon from intended AP. + * Switch to the APs channel. + * On an error case, send the MLM_JOIN_CNF with error status. + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param status status of suspend link. + * @param ctx passed while calling suspend link(psessionEntry) + * @return None + */ +static void +limProcessMlmPostJoinSuspendLink(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *ctx) +{ + tLimMlmJoinCnf mlmJoinCnf; + tpPESession psessionEntry = (tpPESession)ctx; + tSirLinkState linkState; + + if( eHAL_STATUS_SUCCESS != status ) + { + limLog(pMac, LOGE, FL("Sessionid %d Suspend link(NOTIFY_BSS) failed. " + "still proceeding with join"),psessionEntry->peSessionId); + } + + limDeactivateAndChangeTimer(pMac, eLIM_JOIN_FAIL_TIMER); + + //assign appropriate sessionId to the timer object + pMac->lim.limTimers.gLimJoinFailureTimer.sessionId = psessionEntry->peSessionId; + + linkState = LIM_IS_BT_AMP_STA_ROLE(psessionEntry) ? eSIR_LINK_BTAMP_PREASSOC_STATE : eSIR_LINK_PREASSOC_STATE; + limLog(pMac, LOG1, FL("[limProcessMlmJoinReq]: linkState:%d"),linkState); + + if (limSetLinkState(pMac, linkState, + psessionEntry->pLimMlmJoinReq->bssDescription.bssId, + psessionEntry->selfMacAddr, lim_post_join_set_link_state_callback, + psessionEntry) != eSIR_SUCCESS ) + { + limLog(pMac, LOGE, + FL("SessionId:%d limSetLinkState to eSIR_LINK_PREASSOC_STATE Failed!!"), + psessionEntry->peSessionId); + limPrintMacAddr(pMac, + psessionEntry->pLimMlmJoinReq->bssDescription.bssId,LOGE); + mlmJoinCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + goto error; + } + + return; +error: + mlmJoinCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmJoinCnf.sessionId = psessionEntry->peSessionId; + mlmJoinCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + limPostSmeMessage(pMac, LIM_MLM_JOIN_CNF, (tANI_U32 *) &mlmJoinCnf); +} + +/** + * limProcessMlmJoinReq() + * + *FUNCTION: + * This function is called to process MLM_JOIN_REQ message + * from SME + * + *LOGIC: + * 1) Initialize LIM, HAL, DPH + * 2) Configure the BSS for which the JOIN REQ was received + * a) Send WDA_ADD_BSS_REQ to HAL - + * This will identify the BSS that we are interested in + * --AND-- + * Add a STA entry for the AP (in a STA context) + * b) Wait for WDA_ADD_BSS_RSP + * c) Send WDA_ADD_STA_REQ to HAL + * This will add the "local STA" entry to the STA table + * 3) Continue as before, i.e, + * a) Send a PROBE REQ + * b) Wait for PROBE RSP/BEACON containing the SSID that + * we are interested in + * c) Then start an AUTH seq + * d) Followed by the ASSOC seq + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmJoinCnf mlmJoinCnf; + tANI_U8 sessionId; + tpPESession psessionEntry; + + sessionId = ((tpLimMlmJoinReq)pMsgBuf)->sessionId; + + if((psessionEntry = peFindSessionBySessionId(pMac,sessionId))== NULL) + { + limLog(pMac, LOGE, FL("SessionId:%d session does not exist"),sessionId); + goto error; + } + + if ((!LIM_IS_AP_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + ((psessionEntry->limMlmState == eLIM_MLM_IDLE_STATE) || + (psessionEntry->limMlmState == eLIM_MLM_JOINED_STATE)) && + (SIR_MAC_GET_ESS(((tpLimMlmJoinReq) pMsgBuf)->bssDescription.capabilityInfo) != + SIR_MAC_GET_IBSS( ((tpLimMlmJoinReq) pMsgBuf)->bssDescription.capabilityInfo))) + { + /// Hold onto Join request parameters + + psessionEntry->pLimMlmJoinReq =(tpLimMlmJoinReq) pMsgBuf; + + if( isLimSessionOffChannel(pMac, sessionId) ) + { + limLog(pMac,LOG1,"SessionId:%d LimSession is on OffChannel", + sessionId); + //suspend link + limLog(pMac, LOG1, FL("Suspend link as LimSession on sessionid %d" + "is off channel"),sessionId); + if (limIsLinkSuspended(pMac)) + { + limLog(pMac, LOGE, FL("Link is already suspended for some other" + " reason. Return failure on sessionId:%d"), sessionId); + goto error; + } + limSuspendLink(pMac, eSIR_DONT_CHECK_LINK_TRAFFIC_BEFORE_SCAN, + limProcessMlmPostJoinSuspendLink, (tANI_U32*)psessionEntry ); + } + else + { + limLog(pMac, LOG1, FL("No need to Suspend link as LimSession on " + "sessionid %d is not off channel, calling " + "limProcessMlmPostJoinSuspendLink with status as SUCCESS"), + sessionId); + //No need to suspend link. + limLog(pMac,LOG1,"SessionId:%d Join request on current channel", + sessionId); + limProcessMlmPostJoinSuspendLink( pMac, eHAL_STATUS_SUCCESS, + (tANI_U32*) psessionEntry ); + } + + return; + } + else + { + /** + * Should not have received JOIN req in states other than + * Idle state or on AP. + * Return join confirm with invalid parameters code. + */ + limLog(pMac, LOGE, + FL("SessionId:%d Unexpected Join request for role %d state %X "), + psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), + psessionEntry->limMlmState); + limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); + } + +error: + vos_mem_free(pMsgBuf); + if (psessionEntry != NULL) + psessionEntry->pLimMlmJoinReq = NULL; + + + mlmJoinCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmJoinCnf.sessionId = sessionId; + mlmJoinCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + limPostSmeMessage(pMac, LIM_MLM_JOIN_CNF, (tANI_U32 *) &mlmJoinCnf); + + +} /*** limProcessMlmJoinReq() ***/ + + + +/** + * limProcessMlmAuthReq() + * + *FUNCTION: + * This function is called to process MLM_AUTH_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U32 numPreAuthContexts; + tSirMacAddr currentBssId; + tSirMacAuthFrameBody authFrameBody; + tLimMlmAuthCnf mlmAuthCnf; + struct tLimPreAuthNode *preAuthNode; + tpDphHashNode pStaDs; + tANI_U8 sessionId; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMac->lim.gpLimMlmAuthReq = (tLimMlmAuthReq *) pMsgBuf; + sessionId = pMac->lim.gpLimMlmAuthReq->sessionId; + if((psessionEntry= peFindSessionBySessionId(pMac,sessionId) )== NULL) + { + limLog(pMac, LOGP, FL("SessionId:%d Session Does not exist"), + sessionId); + return; + } + + limLog(pMac, LOG1,FL("Process Auth Req on sessionID %d Systemrole %d " + "mlmstate %d from: "MAC_ADDRESS_STR" with authtype %d"), sessionId, + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, + MAC_ADDR_ARRAY(pMac->lim.gpLimMlmAuthReq->peerMacAddr), + pMac->lim.gpLimMlmAuthReq->authType); + + + /** + * Expect Auth request only when: + * 1. STA joined/associated with a BSS or + * 2. STA is in IBSS mode + * and STA is going to authenticate with a unicast + * adress and requested authentication algorithm is + * supported. + */ + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + if ((((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + ((psessionEntry->limMlmState == eLIM_MLM_JOINED_STATE) || + (psessionEntry->limMlmState == + eLIM_MLM_LINK_ESTABLISHED_STATE))) || + (LIM_IS_IBSS_ROLE(psessionEntry) && + (psessionEntry->limMlmState == eLIM_MLM_BSS_STARTED_STATE))) && + (limIsGroupAddr(pMac->lim.gpLimMlmAuthReq->peerMacAddr) + == false) && + (limIsAuthAlgoSupported( + pMac, + pMac->lim.gpLimMlmAuthReq->authType, + psessionEntry) == true) + ) + { + /** + * This is a request for pre-authentication. + * Check if there exists context already for + * the requested peer OR + * if this request is for the AP we're currently + * associated with. + * If yes, return auth confirm immediately when + * requested auth type is same as the one used before. + */ + if (((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->limMlmState == + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (((pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) != NULL) && + (pMac->lim.gpLimMlmAuthReq->authType == + pStaDs->mlmStaContext.authType)) && + (vos_mem_compare(pMac->lim.gpLimMlmAuthReq->peerMacAddr, + currentBssId, + sizeof(tSirMacAddr)) )) || + (((preAuthNode = + limSearchPreAuthList( + pMac, + pMac->lim.gpLimMlmAuthReq->peerMacAddr)) != NULL) && + (preAuthNode->authType == + pMac->lim.gpLimMlmAuthReq->authType))) + { + limLog(pMac, LOG2, + FL("Already have pre-auth context with peer: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMac->lim.gpLimMlmAuthReq->peerMacAddr)); + + mlmAuthCnf.resultCode = (tSirResultCodes) + eSIR_MAC_SUCCESS_STATUS; + + + goto end; + } + else + { + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_NUM_PRE_AUTH, + (tANI_U32 *) &numPreAuthContexts) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Could not retrieve NumPreAuthLimit from CFG")); + } + + if (pMac->lim.gLimNumPreAuthContexts == numPreAuthContexts) + { + PELOGW(limLog(pMac, LOGW, + FL("Number of pre-auth reached max limit"));) + + /// Return Auth confirm with reject code + mlmAuthCnf.resultCode = + eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED; + + goto end; + } + } + + // Delete pre-auth node if exists + if (preAuthNode) + limDeletePreAuthNode(pMac, + pMac->lim.gpLimMlmAuthReq->peerMacAddr); + + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + 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; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_AUTH_START_EVENT, psessionEntry, + eSIR_SUCCESS, authFrameBody.authStatusCode); +#endif + pMac->auth_ack_status = 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 */ + pMac->lim.limTimers.g_lim_periodic_auth_retry_timer.sessionId = sessionId; + 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")); + /* Clean up 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.g_lim_periodic_auth_retry_timer) + != TX_SUCCESS) { + limLog(pMac, LOGP, FL("could not activate Auth Retry timer")); + } + } + return; + } + else + { + /** + * Unexpected auth request. + * Return Auth confirm with Invalid parameters code. + */ + mlmAuthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + + goto end; + } + +end: + vos_mem_copy((tANI_U8 *) &mlmAuthCnf.peerMacAddr, + (tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)); + + mlmAuthCnf.authType = pMac->lim.gpLimMlmAuthReq->authType; + mlmAuthCnf.sessionId = sessionId; + + vos_mem_free( pMac->lim.gpLimMlmAuthReq); + pMac->lim.gpLimMlmAuthReq = NULL; + limLog(pMac,LOG1,"SessionId:%d LimPostSme LIM_MLM_AUTH_CNF ", + sessionId); + limPostSmeMessage(pMac, LIM_MLM_AUTH_CNF, (tANI_U32 *) &mlmAuthCnf); +} /*** limProcessMlmAuthReq() ***/ + + + +/** + * limProcessMlmAssocReq() + * + *FUNCTION: + * This function is called to process MLM_ASSOC_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMacAddr currentBssId; + tLimMlmAssocReq *pMlmAssocReq; + tLimMlmAssocCnf mlmAssocCnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmAssocReq = (tLimMlmAssocReq *) pMsgBuf; + + if( (psessionEntry = peFindSessionBySessionId(pMac,pMlmAssocReq->sessionId) )== NULL) + { + limLog(pMac, LOGP,FL("SessionId:%d Session Does not exist"), + pMlmAssocReq->sessionId); + vos_mem_free(pMlmAssocReq); + return; + } + + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + if ((!LIM_IS_AP_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (psessionEntry->limMlmState == eLIM_MLM_AUTHENTICATED_STATE || + psessionEntry->limMlmState == eLIM_MLM_JOINED_STATE) && + (vos_mem_compare(pMlmAssocReq->peerMacAddr, currentBssId, + sizeof(tSirMacAddr)))) { + /// map the session entry pointer to the AssocFailureTimer + pMac->lim.limTimers.gLimAssocFailureTimer.sessionId = pMlmAssocReq->sessionId; + +#ifdef WLAN_FEATURE_11W + /* + * Store current MLM state in case ASSOC response returns with + * TRY_AGAIN_LATER return code. + */ + if (psessionEntry->limRmfEnabled) { + psessionEntry->pmfComebackTimerInfo.limPrevMlmState = + psessionEntry->limPrevMlmState; + psessionEntry->pmfComebackTimerInfo.limMlmState = + psessionEntry->limMlmState; + } +#endif /* WLAN_FEATURE_11W */ + + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + psessionEntry->limMlmState = eLIM_MLM_WT_ASSOC_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + limLog(pMac,LOG1,"SessionId:%d Sending Assoc_Req Frame", + psessionEntry->peSessionId); + + /// Prepare and send Association request frame + limSendAssocReqMgmtFrame(pMac, pMlmAssocReq,psessionEntry); + + //Set the link state to postAssoc, so HW can start receiving frames from AP. + if ((psessionEntry->bssType == eSIR_BTAMP_STA_MODE) || + ((psessionEntry->bssType == eSIR_BTAMP_AP_MODE) && + LIM_IS_BT_AMP_STA_ROLE(psessionEntry))) { + if(limSetLinkState(pMac, eSIR_LINK_BTAMP_POSTASSOC_STATE, currentBssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) + } + /// Start association failure timer + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ASSOC_FAIL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimAssocFailureTimer) + != TX_SUCCESS) + { + /// Could not start Assoc failure timer. + // Log error + limLog(pMac, LOGP, + FL("SessionId:%d could not start Association failure timer"), + psessionEntry->peSessionId); + /* Clean up as if assoc timer expired */ + limProcessAssocFailureTimeout(pMac,LIM_ASSOC ); + + } + + return; + } + else + { + /** + * Received Association request either in invalid state + * or to a peer MAC entity whose address is different + * from one that STA is currently joined with or on AP. + * Return Assoc confirm with Invalid parameters code. + */ + + // Log error + PELOGW(limLog(pMac, LOGW, + FL("received unexpected MLM_ASSOC_CNF in state %X for role=%d, MAC addr= " + MAC_ADDRESS_STR), psessionEntry->limMlmState, + GET_LIM_SYSTEM_ROLE(psessionEntry), MAC_ADDR_ARRAY(pMlmAssocReq->peerMacAddr));) + limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); + + mlmAssocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + goto end; + } + +end: + /* Update PE session Id*/ + mlmAssocCnf.sessionId = pMlmAssocReq->sessionId; + + /// Free up buffer allocated for assocReq + vos_mem_free(pMlmAssocReq); + + limPostSmeMessage(pMac, LIM_MLM_ASSOC_CNF, (tANI_U32 *) &mlmAssocCnf); +} /*** limProcessMlmAssocReq() ***/ + + + +/** + * limProcessMlmReassocReq() + * + *FUNCTION: + * This function is called to process MLM_REASSOC_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U8 chanNum, secChannelOffset; + struct tLimPreAuthNode *pAuthNode; + tLimMlmReassocReq *pMlmReassocReq; + tLimMlmReassocCnf mlmReassocCnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmReassocReq = (tLimMlmReassocReq *) pMsgBuf; + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmReassocReq->sessionId)) == NULL) + { + limLog(pMac, LOGE,FL("Session Does not exist for given sessionId %d"), + pMlmReassocReq->sessionId); + vos_mem_free(pMlmReassocReq); + return; + } + + limLog(pMac, LOG1,FL("Process ReAssoc Req on sessionID %d Systemrole %d " + "mlmstate %d from: "MAC_ADDRESS_STR), pMlmReassocReq->sessionId, + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, + MAC_ADDR_ARRAY(pMlmReassocReq->peerMacAddr)); + + if ((!LIM_IS_AP_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE)) { + if (psessionEntry->pLimMlmReassocReq) + vos_mem_free(psessionEntry->pLimMlmReassocReq); + + /* Hold Re-Assoc request as part of Session, knock-out pMac */ + /// Hold onto Reassoc request parameters + psessionEntry->pLimMlmReassocReq = pMlmReassocReq; + + // See if we have pre-auth context with new AP + pAuthNode = limSearchPreAuthList(pMac, psessionEntry->limReAssocbssId); + + if (!pAuthNode && + (!vos_mem_compare(pMlmReassocReq->peerMacAddr, + psessionEntry->bssId, + sizeof(tSirMacAddr)) )) + { + // Either pre-auth context does not exist AND + // we are not reassociating with currently + // associated AP. + // Return Reassoc confirm with not authenticated + mlmReassocCnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + goto end; + } + + //assign the sessionId to the timer object + pMac->lim.limTimers.gLimReassocFailureTimer.sessionId = pMlmReassocReq->sessionId; + + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + psessionEntry->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + /** + * Derive channel from BSS description and + * store it at CFG. + */ + + chanNum = psessionEntry->limReassocChannelId; + secChannelOffset = psessionEntry->reAssocHtSecondaryChannelOffset; + + // Apply previously set configuration at HW + limApplyConfiguration(pMac,psessionEntry); + + //store the channel switch sessionEntry in the lim global var + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_REASSOC; + + /** Switch channel to the new Operating channel for Reassoc*/ + limSetChannel(pMac, chanNum, secChannelOffset, psessionEntry->maxTxPower, psessionEntry->peSessionId); + + return; + } + else + { + /** + * Received Reassoc request in invalid state or + * in AP role.Return Reassoc confirm with Invalid + * parameters code. + */ + + // Log error + limLog(pMac, LOGW, + FL("received unexpected MLM_REASSOC_CNF in state %X for role=%d, " + "MAC addr= " + MAC_ADDRESS_STR), psessionEntry->limMlmState, + GET_LIM_SYSTEM_ROLE(psessionEntry), + MAC_ADDR_ARRAY(pMlmReassocReq->peerMacAddr)); + limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); + + mlmReassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + goto end; + } + +end: + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE sessio Id*/ + mlmReassocCnf.sessionId = pMlmReassocReq->sessionId; + /// Free up buffer allocated for reassocReq + vos_mem_free(pMlmReassocReq); + psessionEntry->pLimReAssocReq = NULL; + + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); +} /*** limProcessMlmReassocReq() ***/ + + +static void +limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U32 *pMsgBuf) +{ + tANI_U16 aid; + tSirMacAddr currentBssId; + tpDphHashNode pStaDs; + tLimMlmDisassocReq *pMlmDisassocReq; + tLimMlmDisassocCnf mlmDisassocCnf; + tpPESession psessionEntry; + extern tANI_BOOLEAN sendDisassocFrame; + tSirSmeDisassocRsp *pSirSmeDisassocRsp; + tANI_U32 *pMsg; + tANI_U8 *pBuf; + + if(eHAL_STATUS_SUCCESS != suspendStatus) + { + PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X"), suspendStatus);) + } + + pMlmDisassocReq = (tLimMlmDisassocReq *) pMsgBuf; + + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocReq->sessionId))== NULL) + { + + limLog(pMac, LOGE, + FL("session does not exist for given sessionId %d"), + pMlmDisassocReq->sessionId); + mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + limLog(pMac, LOG1,FL("Process DisAssoc Req on sessionID %d Systemrole %d " + "mlmstate %d from: "MAC_ADDRESS_STR), pMlmDisassocReq->sessionId, + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, + MAC_ADDR_ARRAY(pMlmDisassocReq->peerMacAddr)); + + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + if ( !vos_mem_compare(pMlmDisassocReq->peerMacAddr, + currentBssId, + sizeof(tSirMacAddr)) ) + { + PELOGW(limLog(pMac, LOGW, + FL("received MLM_DISASSOC_REQ with invalid BSS id "));) + limPrintMacAddr(pMac, pMlmDisassocReq->peerMacAddr, LOGW); + + /* + * Disassociation response due to host triggered disassociation + */ + pSirSmeDisassocRsp = + vos_mem_malloc(sizeof(tSirSmeDisassocRsp)); + if (NULL == pSirSmeDisassocRsp) { + /* Log error */ + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_DISASSOC_RSP")); + return; + } + limLog(pMac, LOG1, + FL("send eWNI_SME_DISASSOC_RSP with retCode: %d for " MAC_ADDRESS_STR), + eSIR_SME_DEAUTH_STATUS, + MAC_ADDR_ARRAY(pMlmDisassocReq->peerMacAddr)); + pSirSmeDisassocRsp->messageType = eWNI_SME_DISASSOC_RSP; + pSirSmeDisassocRsp->length = sizeof(tSirSmeDisassocRsp); + pSirSmeDisassocRsp->sessionId = pMlmDisassocReq->sessionId; + pSirSmeDisassocRsp->transactionId = 0; + pSirSmeDisassocRsp->statusCode = eSIR_SME_DEAUTH_STATUS; + + pBuf = (tANI_U8 *) pSirSmeDisassocRsp->peerMacAddr; + vos_mem_copy( pBuf, pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)); + pMsg = (tANI_U32*) pSirSmeDisassocRsp; + + limSendSmeDisassocDeauthNtf(pMac, eHAL_STATUS_SUCCESS, + (tANI_U32*) pMsg); + return; + } + + break; + + case eLIM_STA_IN_IBSS_ROLE: + + break; + + case eLIM_AP_ROLE: + case eLIM_P2P_DEVICE_GO: + if(VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) { + limLog(pMac, LOGE, + FL("CAC timer is running, drop disassoc from going out")); + mlmDisassocCnf.resultCode = eSIR_SME_SUCCESS; + goto end; + } + break; + + default: + // Fall through + break; + + } // end switch (psessionEntry->limSystemRole) + + /** + * Check if there exists a context for the peer entity + * to be disassociated with. + */ + pStaDs = dphLookupHashEntry(pMac, pMlmDisassocReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); + if ((pStaDs == NULL) || + (pStaDs && + ((pStaDs->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_WT_ASSOC_CNF_STATE) && + (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_ASSOCIATED_STATE)))) + { + /** + * Received LIM_MLM_DISASSOC_REQ for STA that does not + * have context or in some transit state. + * Log error + */ + PELOGW(limLog(pMac, LOGW, + FL("received MLM_DISASSOC_REQ for STA that either has no context " + "or in some transit state, Addr= " + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pMlmDisassocReq->peerMacAddr));) + if (pStaDs != NULL) + limLog(pMac, LOGE, FL("Sta MlmState : %d"), + pStaDs->mlmStaContext.mlmState); + + /// Prepare and Send LIM_MLM_DISASSOC_CNF + + mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + + goto end; + } + + pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) + pMlmDisassocReq->reasonCode; + pStaDs->mlmStaContext.cleanupTrigger = pMlmDisassocReq->disassocTrigger; + + /* + * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE + * This is to address the issue of race condition between + * disconnect request from the HDD and deauth from AP + */ + + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + + /// Send Disassociate frame to peer entity + if (sendDisassocFrame && (pMlmDisassocReq->reasonCode != eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) + { + pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = pMlmDisassocReq; + limSendDisassocMgmtFrame(pMac, + pMlmDisassocReq->reasonCode, + pMlmDisassocReq->peerMacAddr, + psessionEntry, TRUE); + /* + * Abort Tx so that data frames won't be sent to the AP + * after sending Disassoc. + */ + if (LIM_IS_STA_ROLE(psessionEntry)) + WDA_TxAbort(psessionEntry->smeSessionId); + } + else + { + /* Disassoc frame is not sent OTA */ + sendDisassocFrame = 1; + // Receive path cleanup with dummy packet + if(eSIR_SUCCESS != limCleanupRxPath(pMac, pStaDs,psessionEntry)) + { + mlmDisassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + // Free up buffer allocated for mlmDisassocReq + vos_mem_free(pMlmDisassocReq); + } + + return; + +end: + vos_mem_copy((tANI_U8 *) &mlmDisassocCnf.peerMacAddr, + (tANI_U8 *) pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)); + mlmDisassocCnf.aid = pMlmDisassocReq->aid; + mlmDisassocCnf.disassocTrigger = pMlmDisassocReq->disassocTrigger; + + /* Update PE session ID*/ + mlmDisassocCnf.sessionId = pMlmDisassocReq->sessionId; + + /// Free up buffer allocated for mlmDisassocReq + vos_mem_free(pMlmDisassocReq); + + limPostSmeMessage(pMac, + LIM_MLM_DISASSOC_CNF, + (tANI_U32 *) &mlmDisassocCnf); +} + +tANI_BOOLEAN limCheckDisassocDeauthAckPending(tpAniSirGlobal pMac, + tANI_U8 *staMac + ) +{ + tLimMlmDisassocReq *pMlmDisassocReq; + tLimMlmDeauthReq *pMlmDeauthReq; + pMlmDisassocReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if ( + (pMlmDisassocReq && + (vos_mem_compare((tANI_U8 *) staMac, + (tANI_U8 *) &pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)))) + || + (pMlmDeauthReq && + (vos_mem_compare((tANI_U8 *) staMac, + (tANI_U8 *) &pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)))) + ) + { + PELOG1(limLog(pMac, LOG1, FL("Disassoc/Deauth ack pending"));) + return eANI_BOOLEAN_TRUE; + } + else + { + PELOG1(limLog(pMac, LOG1, FL("Disassoc/Deauth Ack not pending"));) + return eANI_BOOLEAN_FALSE; + } +} + +void limCleanUpDisassocDeauthReq(tpAniSirGlobal pMac, + tANI_U8 *staMac, + tANI_BOOLEAN cleanRxPath) +{ + tLimMlmDisassocReq *pMlmDisassocReq; + tLimMlmDeauthReq *pMlmDeauthReq; + pMlmDisassocReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + if (pMlmDisassocReq && + (vos_mem_compare((tANI_U8 *) staMac, + (tANI_U8 *) &pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)))) + { + if (cleanRxPath) + { + limProcessDisassocAckTimeout(pMac); + } + else + { + if (tx_timer_running(&pMac->lim.limTimers.gLimDisassocAckTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER); + } + vos_mem_free(pMlmDisassocReq); + pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL; + } + } + + pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (pMlmDeauthReq && + (vos_mem_compare((tANI_U8 *) staMac, + (tANI_U8 *) &pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)))) + { + if (cleanRxPath) + { + limProcessDeauthAckTimeout(pMac); + } + else + { + if (tx_timer_running(&pMac->lim.limTimers.gLimDeauthAckTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER); + } + vos_mem_free(pMlmDeauthReq); + pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; + } + } +} + +void limProcessDisassocAckTimeout(tpAniSirGlobal pMac) +{ + limLog(pMac, LOG1, FL("")); + limSendDisassocCnf(pMac); +} + +/** + * limProcessMlmDisassocReq() + * + *FUNCTION: + * This function is called to process MLM_DISASSOC_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmDisassocReq *pMlmDisassocReq; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmDisassocReq = (tLimMlmDisassocReq *) pMsgBuf; + limLog(pMac, LOG1,FL("Process DisAssoc Req on sessionID %d " + "from: "MAC_ADDRESS_STR), pMlmDisassocReq->sessionId, + MAC_ADDR_ARRAY(pMlmDisassocReq->peerMacAddr)); + limProcessMlmDisassocReqNtf( pMac, eHAL_STATUS_SUCCESS, (tANI_U32*) pMsgBuf ); + +} /*** limProcessMlmDisassocReq() ***/ + +static void +limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U32 *pMsgBuf) +{ + tANI_U16 aid; + tSirMacAddr currentBssId; + tpDphHashNode pStaDs; + struct tLimPreAuthNode *pAuthNode; + tLimMlmDeauthReq *pMlmDeauthReq; + tLimMlmDeauthCnf mlmDeauthCnf; + tpPESession psessionEntry; + tSirSmeDeauthRsp *pSirSmeDeauthRsp; + tANI_U8 *pBuf; + tANI_U32 *pMsg; + + if(eHAL_STATUS_SUCCESS != suspendStatus) + { + PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X"), suspendStatus);) + } + + pMlmDeauthReq = (tLimMlmDeauthReq *) pMsgBuf; + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthReq->sessionId))== NULL) + { + limLog(pMac, LOGE, FL("session does not exist for given sessionId %d"), + pMlmDeauthReq->sessionId); + vos_mem_free(pMlmDeauthReq); + return; + } + limLog(pMac, LOG1,FL("Process Deauth Req on sessionID %d Systemrole %d " + "mlmstate %d from: "MAC_ADDRESS_STR), pMlmDeauthReq->sessionId, + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, + MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr)); + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + switch (psessionEntry->limMlmState) + { + case eLIM_MLM_IDLE_STATE: + // Attempting to Deauthenticate + // with a pre-authenticated peer. + // Deauthetiate with peer if there + // exists a pre-auth context below. + break; + + case eLIM_MLM_AUTHENTICATED_STATE: + case eLIM_MLM_WT_ASSOC_RSP_STATE: + case eLIM_MLM_LINK_ESTABLISHED_STATE: + if (!vos_mem_compare(pMlmDeauthReq->peerMacAddr, + currentBssId, + sizeof(tSirMacAddr)) ) + { + limLog(pMac, LOGE, + FL("received MLM_DEAUTH_REQ with invalid BSS id " + "Peer MAC: "MAC_ADDRESS_STR " CFG BSSID Addr : " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr), + MAC_ADDR_ARRAY(currentBssId)); + + /* + * Deauthentication response to host triggered + * deauthentication. + */ + pSirSmeDeauthRsp = + vos_mem_malloc(sizeof(tSirSmeDeauthRsp)); + if (NULL == pSirSmeDeauthRsp) { + /* Log error */ + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_DEAUTH_RSP")); + return; + } + limLog(pMac, LOG1, + FL("send eWNI_SME_DEAUTH_RSP with retCode: %d for " MAC_ADDRESS_STR), + eSIR_SME_DEAUTH_STATUS, + MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr)); + pSirSmeDeauthRsp->messageType = eWNI_SME_DEAUTH_RSP; + pSirSmeDeauthRsp->length = sizeof(tSirSmeDeauthRsp); + pSirSmeDeauthRsp->statusCode = eSIR_SME_DEAUTH_STATUS; + pSirSmeDeauthRsp->sessionId = pMlmDeauthReq->sessionId; + pSirSmeDeauthRsp->transactionId = 0; + + pBuf = (tANI_U8 *) pSirSmeDeauthRsp->peerMacAddr; + vos_mem_copy(pBuf, pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)); + pMsg = (tANI_U32*)pSirSmeDeauthRsp; + + limSendSmeDisassocDeauthNtf(pMac, eHAL_STATUS_SUCCESS, + (tANI_U32*) pMsg); + + return; + } + + if ((psessionEntry->limMlmState == + eLIM_MLM_AUTHENTICATED_STATE) || + (psessionEntry->limMlmState == + eLIM_MLM_WT_ASSOC_RSP_STATE)) + { + // Send Deauthentication frame + // to peer entity + limSendDeauthMgmtFrame( + pMac, + pMlmDeauthReq->reasonCode, + pMlmDeauthReq->peerMacAddr, + psessionEntry, FALSE); + + /// Prepare and Send LIM_MLM_DEAUTH_CNF + mlmDeauthCnf.resultCode = eSIR_SME_SUCCESS; + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + goto end; + } + + break; + + default: + + PELOGW(limLog(pMac, LOGW, + FL("received MLM_DEAUTH_REQ with in state %d for peer "MAC_ADDRESS_STR), + psessionEntry->limMlmState,MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr));) + limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); + + /// Prepare and Send LIM_MLM_DEAUTH_CNF + mlmDeauthCnf.resultCode = + eSIR_SME_STA_NOT_AUTHENTICATED; + + goto end; + } + + break; + + case eLIM_STA_IN_IBSS_ROLE: + limLog(pMac, LOGE, + FL("received MLM_DEAUTH_REQ IBSS Mode ")); + mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + + + case eLIM_AP_ROLE: + case eLIM_P2P_DEVICE_GO: + if(VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) { + limLog(pMac, LOGE, + FL("CAC timer is running, drop deauth from going out")); + mlmDeauthCnf.resultCode = eSIR_SME_SUCCESS; + goto end; + } + break; + + default: + break; + + } // end switch (psessionEntry->limSystemRole) + + /** + * Check if there exists a context for the peer entity + * to be deauthenticated with. + */ + pStaDs = dphLookupHashEntry(pMac, pMlmDeauthReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) + { + /// Check if there exists pre-auth context for this STA + pAuthNode = limSearchPreAuthList(pMac, + pMlmDeauthReq->peerMacAddr); + + if (pAuthNode == NULL) + { + /** + * Received DEAUTH REQ for a STA that is neither + * Associated nor Pre-authenticated. Log error, + * Prepare and Send LIM_MLM_DEAUTH_CNF + */ + PELOGW(limLog(pMac, LOGW, + FL("received MLM_DEAUTH_REQ in mlme state %d for STA that " + "does not have context, Addr="MAC_ADDRESS_STR), + psessionEntry->limMlmState, + MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr));) + + mlmDeauthCnf.resultCode = + eSIR_SME_STA_NOT_AUTHENTICATED; + } + else + { + mlmDeauthCnf.resultCode = eSIR_SME_SUCCESS; + + /// Delete STA from pre-auth STA list + limDeletePreAuthNode(pMac, pMlmDeauthReq->peerMacAddr); + + /// Send Deauthentication frame to peer entity + limSendDeauthMgmtFrame(pMac, + pMlmDeauthReq->reasonCode, + pMlmDeauthReq->peerMacAddr, + psessionEntry, FALSE); + } + + goto end; + } + else if ((pStaDs->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_WT_ASSOC_CNF_STATE)) + { + /** + * Received LIM_MLM_DEAUTH_REQ for STA that is n + * some transit state. Log error. + */ + PELOGW(limLog(pMac, LOGW, + FL("received MLM_DEAUTH_REQ for STA that either has no context or in some transit state, Addr=" + MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr));) + + /// Prepare and Send LIM_MLM_DEAUTH_CNF + + mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + + goto end; + } + + //pStaDs->mlmStaContext.rxPurgeReq = 1; + pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) + pMlmDeauthReq->reasonCode; + pStaDs->mlmStaContext.cleanupTrigger = pMlmDeauthReq->deauthTrigger; + + pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = pMlmDeauthReq; + + /* Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE + * This is to address the issue of race condition between + * disconnect request from the HDD and disassoc from + * inactivity timer. This will make sure that we will not + * process disassoc if deauth is in progress for the station + * and thus mlmStaContext.cleanupTrigger will not be overwritten. + */ + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + /// Send Deauthentication frame to peer entity + limSendDeauthMgmtFrame(pMac, pMlmDeauthReq->reasonCode, + pMlmDeauthReq->peerMacAddr, + psessionEntry, TRUE); + + return; + +end: + vos_mem_copy((tANI_U8 *) &mlmDeauthCnf.peerMacAddr, + (tANI_U8 *) pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)); + mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger; + mlmDeauthCnf.aid = pMlmDeauthReq->aid; + mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId; + + // Free up buffer allocated + // for mlmDeauthReq + vos_mem_free(pMlmDeauthReq); + + limPostSmeMessage(pMac, + LIM_MLM_DEAUTH_CNF, + (tANI_U32 *) &mlmDeauthCnf); + +} + + +void limProcessDeauthAckTimeout(tpAniSirGlobal pMac) +{ + limLog(pMac, LOG1, FL("")); + limSendDeauthCnf(pMac); +} + +/** + * limProcessMlmDeauthReq() + * + *FUNCTION: + * This function is called to process MLM_DEAUTH_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmDeauthReq *pMlmDeauthReq; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmDeauthReq = (tLimMlmDeauthReq *) pMsgBuf; + + limLog(pMac, LOG1,FL("Process Deauth Req on sessionID %d " + "from: "MAC_ADDRESS_STR), pMlmDeauthReq->sessionId, + MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr)); + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthReq->sessionId))== NULL) + { + limLog(pMac, LOGE, FL("session does not exist for given sessionId %d"), + pMlmDeauthReq->sessionId); + return; + } + + limProcessMlmDeauthReqNtf( pMac, eHAL_STATUS_SUCCESS, (tANI_U32*) pMsgBuf ); + +} /*** limProcessMlmDeauthReq() ***/ + + + +/** + * @function : limProcessMlmSetKeysReq() + * + * @brief : This function is called to process MLM_SETKEYS_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmSetKeysReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ +tANI_U16 aid; +tANI_U16 staIdx = 0; +tANI_U32 defaultKeyId = 0; +tSirMacAddr currentBssId; +tpDphHashNode pStaDs; +tLimMlmSetKeysReq *pMlmSetKeysReq; +tLimMlmSetKeysCnf mlmSetKeysCnf; +tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + + pMlmSetKeysReq = (tLimMlmSetKeysReq *) pMsgBuf; + // Hold onto the SetKeys request parameters + pMac->lim.gpLimMlmSetKeysReq = (void *) pMlmSetKeysReq; + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmSetKeysReq->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) + return; + } + + limLog( pMac, LOGW, + FL( "Received MLM_SETKEYS_REQ with parameters:" + "AID [%d], ED Type [%d], # Keys [%d] & Peer MAC Addr - "), + pMlmSetKeysReq->aid, + pMlmSetKeysReq->edType, + pMlmSetKeysReq->numKeys ); + limPrintMacAddr( pMac, pMlmSetKeysReq->peerMacAddr, LOGW ); + + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + //In case of TDLS, peerMac address need not be BssId. Skip this check + //if TDLS is enabled. +#ifndef FEATURE_WLAN_TDLS + if((!limIsAddrBC( pMlmSetKeysReq->peerMacAddr ) ) && + (!vos_mem_compare(pMlmSetKeysReq->peerMacAddr, + currentBssId, sizeof(tSirMacAddr))) ){ + limLog( pMac, LOGW, FL("Received MLM_SETKEYS_REQ with invalid BSSID")); + limPrintMacAddr( pMac, pMlmSetKeysReq->peerMacAddr, LOGW ); + + // Prepare and Send LIM_MLM_SETKEYS_CNF with error code + mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } +#endif + // Fall thru' & 'Plumb' keys below + break; + case eLIM_STA_IN_IBSS_ROLE: + // update the IBSS PE session encrption type based on the key type + psessionEntry->encryptType = pMlmSetKeysReq->edType; + break; + default: // others + // Fall thru... + break; + } + + /** + * Use the "unicast" parameter to determine if the "Group Keys" + * are being set. + * pMlmSetKeysReq->key.unicast = 0 -> Multicast/broadcast + * pMlmSetKeysReq->key.unicast - 1 -> Unicast keys are being set + */ + if( limIsAddrBC( pMlmSetKeysReq->peerMacAddr )) { + limLog( pMac, LOG1, FL("Trying to set Group Keys...%d "), pMlmSetKeysReq->sessionId); + /** When trying to set Group Keys for any + * security mode other than WEP, use the + * STA Index corresponding to the AP... + */ + switch( pMlmSetKeysReq->edType ) { + case eSIR_ED_CCMP: + +#ifdef WLAN_FEATURE_11W + case eSIR_ED_AES_128_CMAC: +#endif + staIdx = psessionEntry->staId; + break; + + default: + break; + } + }else { + limLog( pMac, LOG1, FL("Trying to set Unicast Keys...")); + /** + * Check if there exists a context for the + * peer entity for which keys need to be set. + */ + + + pStaDs = dphLookupHashEntry( pMac, pMlmSetKeysReq->peerMacAddr, &aid , &psessionEntry->dph.dphHashTable); + + if ((pStaDs == NULL) || + ((pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) && + !LIM_IS_AP_ROLE(psessionEntry))) { + /** + * Received LIM_MLM_SETKEYS_REQ for STA + * that does not have context or in some + * transit state. Log error. + */ + limLog( pMac, LOG1, + FL("Received MLM_SETKEYS_REQ for STA that either has no context or in some transit state, Addr = ")); + limPrintMacAddr( pMac, pMlmSetKeysReq->peerMacAddr, LOGW ); + + // Prepare and Send LIM_MLM_SETKEYS_CNF + mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } else + staIdx = pStaDs->staIndex; + } + + if ((pMlmSetKeysReq->numKeys == 0) && (pMlmSetKeysReq->edType != eSIR_ED_NONE)) { + // + // Broadcast/Multicast Keys (for WEP!!) are NOT sent + // via this interface!! + // + // This indicates to HAL that the WEP Keys need to be + // extracted from the CFG and applied to hardware + defaultKeyId = 0xff; + }else if(pMlmSetKeysReq->key[0].keyId && + ((pMlmSetKeysReq->edType == eSIR_ED_WEP40) || + (pMlmSetKeysReq->edType == eSIR_ED_WEP104))){ + /* If the Key Id is non zero and encryption mode is WEP, + * the key index is coming from the upper layers so that key only + * need to be used as the default tx key, This is being used only + * in case of WEP mode in HAL */ + defaultKeyId = pMlmSetKeysReq->key[0].keyId; + }else + defaultKeyId = 0; + + limLog( pMac, LOG1, + FL( "Trying to set keys for STA Index [%d], using defaultKeyId [%d]" ), + staIdx, + defaultKeyId ); + + if(limIsAddrBC( pMlmSetKeysReq->peerMacAddr )) { + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + psessionEntry->limMlmState = eLIM_MLM_WT_SET_BSS_KEY_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + limLog( pMac, LOG1, FL("Trying to set Group Keys...%d "), + psessionEntry->peSessionId); + + // Package WDA_SET_BSSKEY_REQ message parameters + limSendSetBssKeyReq(pMac, pMlmSetKeysReq,psessionEntry); + return; + }else { + // Package WDA_SET_STAKEY_REQ / WDA_SET_STA_BCASTKEY_REQ message parameters + limSendSetStaKeyReq(pMac, pMlmSetKeysReq, staIdx, (tANI_U8) defaultKeyId,psessionEntry, TRUE); + return; + } + +end: + mlmSetKeysCnf.sessionId= pMlmSetKeysReq->sessionId; + limPostSmeSetKeysCnf( pMac, pMlmSetKeysReq, &mlmSetKeysCnf ); + +} /*** limProcessMlmSetKeysReq() ***/ + +/** + * limProcessMlmRemoveKeyReq() + * + *FUNCTION: + * This function is called to process MLM_REMOVEKEY_REQ message + * from SME + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the MLM message buffer + * @return None + */ + +static void +limProcessMlmRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ +tANI_U16 aid; +tANI_U16 staIdx = 0; +tSirMacAddr currentBssId; +tpDphHashNode pStaDs; +tLimMlmRemoveKeyReq *pMlmRemoveKeyReq; +tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmRemoveKeyReq = (tLimMlmRemoveKeyReq *) pMsgBuf; + + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmRemoveKeyReq->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for given sessionId"));) + vos_mem_free(pMsgBuf); + return; + } + + + if( pMac->lim.gpLimMlmRemoveKeyReq != NULL ) + { + // Free any previous requests. + vos_mem_free(pMac->lim.gpLimMlmRemoveKeyReq); + pMac->lim.gpLimMlmRemoveKeyReq = NULL; + } + // Hold onto the RemoveKeys request parameters + pMac->lim.gpLimMlmRemoveKeyReq = (void *) pMlmRemoveKeyReq; + + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + if (( limIsAddrBC( pMlmRemoveKeyReq->peerMacAddr ) != true ) && + (!vos_mem_compare(pMlmRemoveKeyReq->peerMacAddr, + currentBssId, + sizeof(tSirMacAddr)))) { + limLog( pMac, LOGW, + FL("Received MLM_REMOVEKEY_REQ with invalid BSSID")); + limPrintMacAddr( pMac, pMlmRemoveKeyReq->peerMacAddr, LOGW ); + + // Prepare and Send LIM_MLM_REMOVEKEY_CNF with error code + mlmRemoveKeyCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + break; + + case eLIM_STA_IN_IBSS_ROLE: + default: // eLIM_AP_ROLE + // Fall thru... + break; + } + + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + if(limIsAddrBC( pMlmRemoveKeyReq->peerMacAddr )) //Second condition for IBSS or AP role. + { + psessionEntry->limMlmState = eLIM_MLM_WT_REMOVE_BSS_KEY_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + // Package WDA_REMOVE_BSSKEY_REQ message parameters + limSendRemoveBssKeyReq( pMac,pMlmRemoveKeyReq,psessionEntry); + return; + } + + /** + * Check if there exists a context for the + * peer entity for which keys need to be removed. + */ + pStaDs = dphLookupHashEntry( pMac, pMlmRemoveKeyReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable ); + if ((pStaDs == NULL) || + (pStaDs && + (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE))) + { + /** + * Received LIM_MLM_REMOVEKEY_REQ for STA + * that does not have context or in some + * transit state. Log error. + */ + limLog( pMac, LOGW, + FL("Received MLM_REMOVEKEYS_REQ for STA that either has no context or in some transit state, Addr = ")); + limPrintMacAddr( pMac, pMlmRemoveKeyReq->peerMacAddr, LOGW ); + + // Prepare and Send LIM_MLM_REMOVEKEY_CNF + mlmRemoveKeyCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + mlmRemoveKeyCnf.sessionId = pMlmRemoveKeyReq->sessionId; + + + goto end; + } + else + staIdx = pStaDs->staIndex; + + + + psessionEntry->limMlmState = eLIM_MLM_WT_REMOVE_STA_KEY_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + // Package WDA_REMOVE_STAKEY_REQ message parameters + limSendRemoveStaKeyReq( pMac,pMlmRemoveKeyReq,staIdx,psessionEntry); + return; + +end: + limPostSmeRemoveKeyCnf( pMac, + psessionEntry, + pMlmRemoveKeyReq, + &mlmRemoveKeyCnf ); + +} /*** limProcessMlmRemoveKeyReq() ***/ + + +/** + * limProcessMinChannelTimeout() + * + *FUNCTION: + * This function is called to process Min Channel Timeout + * during channel scan. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessMinChannelTimeout(tpAniSirGlobal pMac) +{ + tANI_U8 channelNum; + + + /*do not process if we are in finish scan wait state i.e. + scan is aborted or finished*/ + if (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE && + pMac->lim.gLimHalScanState != eLIM_HAL_FINISH_SCAN_WAIT_STATE) + { + PELOG1(limLog(pMac, LOG1, FL("Scanning : min channel timeout occurred"));) + + /// Min channel timer timed out + pMac->lim.limTimers.gLimPeriodicProbeReqTimer.sessionId = 0xff; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_PROBE_REQ_TIMER); + pMac->lim.probeCounter = 0; + if (pMac->lim.gLimCurrentScanChannelId <= + (tANI_U32)(pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1)) + { + channelNum = (tANI_U8)limGetCurrentScanChannel(pMac); + } + else + { + // This shouldn't be the case, but when this happens, this timeout should be for the last channelId. + // Get the channelNum as close to correct as possible. + if(pMac->lim.gpLimMlmScanReq->channelList.channelNumber) + { + channelNum = pMac->lim.gpLimMlmScanReq->channelList.channelNumber[pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1]; + } + else + { + channelNum = 1; + } + } + + limLog(pMac, LOGW, + FL("Sending End Scan req from MIN_CH_TIMEOUT in state %X ch-%d"), + pMac->lim.gLimMlmState,channelNum); + limSendHalEndScanReq(pMac, channelNum, eLIM_HAL_END_SCAN_WAIT_STATE); + } + else + { + /** + * MIN channel timer should not have timed out + * in states other than wait_probe_response. + * Log error. + */ + limLog(pMac, LOGW, + FL("received unexpected MIN channel timeout in mlme state %X and hal scan State %X"), + pMac->lim.gLimMlmState,pMac->lim.gLimHalScanState); + limPrintMlmState(pMac, LOGE, pMac->lim.gLimMlmState); + } +} /*** limProcessMinChannelTimeout() ***/ + + + +/** + * limProcessMaxChannelTimeout() + * + *FUNCTION: + * This function is called to process Max Channel Timeout + * during channel scan. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessMaxChannelTimeout(tpAniSirGlobal pMac) +{ + tANI_U8 channelNum; + + /*do not process if we are in finish scan wait state i.e. + scan is aborted or finished*/ + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE || + pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) && + pMac->lim.gLimHalScanState != eLIM_HAL_FINISH_SCAN_WAIT_STATE) + { + PELOG1(limLog(pMac, LOG1, FL("Scanning : Max channel timed out"));) + /** + * MAX channel timer timed out + * Continue channel scan. + */ + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_PROBE_REQ_TIMER); + pMac->lim.limTimers.gLimPeriodicProbeReqTimer.sessionId = 0xff; + pMac->lim.probeCounter = 0; + + if (pMac->lim.gLimCurrentScanChannelId <= + (tANI_U32)(pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1)) + { + channelNum = limGetCurrentScanChannel(pMac); + } + else + { + if(pMac->lim.gpLimMlmScanReq->channelList.channelNumber) + { + channelNum = pMac->lim.gpLimMlmScanReq->channelList.channelNumber[pMac->lim.gpLimMlmScanReq->channelList.numChannels - 1]; + } + else + { + channelNum = 1; + } + } + limLog(pMac, LOGW, + FL("Sending End Scan req from MAX_CH_TIMEOUT in state %X on ch-%d"), + pMac->lim.gLimMlmState,channelNum); + limSendHalEndScanReq(pMac, channelNum, eLIM_HAL_END_SCAN_WAIT_STATE); + } + else + { + /** + * MAX channel timer should not have timed out + * in states other than wait_scan. + * Log error. + */ + limLog(pMac, LOGW, + FL("received unexpected MAX channel timeout in mlme state %X and hal scan state %X"), + pMac->lim.gLimMlmState, pMac->lim.gLimHalScanState); + limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); + } +} /*** limProcessMaxChannelTimeout() ***/ + +/** + * limProcessPeriodicProbeReqTimer() + * + *FUNCTION: + * This function is called to process periodic probe request + * to send during scan. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) +{ + tANI_U8 channelNum; + tANI_U8 i = 0; + tSirRetStatus status = eSIR_SUCCESS; + TX_TIMER *pPeriodicProbeReqTimer; + pPeriodicProbeReqTimer = &pMac->lim.limTimers.gLimPeriodicProbeReqTimer; + + if(vos_timer_getCurrentState(&pPeriodicProbeReqTimer->vosTimer) + != VOS_TIMER_STATE_STOPPED) + { + PELOG1(limLog(pMac, LOG1, FL("Invalid state of timer"));) + return; + } + + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) && + (pPeriodicProbeReqTimer->sessionId != 0xff) && (pMac->lim.probeCounter < pMac->lim.maxProbe)) + { + tLimMlmScanReq *pLimMlmScanReq = pMac->lim.gpLimMlmScanReq; + pMac->lim.probeCounter++; + /** + * Periodic channel timer timed out + * to send probe request. + */ + channelNum = limGetCurrentScanChannel(pMac); + do + { + /* Prepare and send Probe Request frame for all the SSIDs + * present in the saved MLM + */ + + status = limSendProbeReqMgmtFrame( pMac, &pLimMlmScanReq->ssId[i], + pLimMlmScanReq->bssId, channelNum, pMac->lim.gSelfMacAddr, + pLimMlmScanReq->dot11mode, pLimMlmScanReq->uIEFieldLen, + (tANI_U8 *)(pLimMlmScanReq) + pLimMlmScanReq->uIEFieldOffset); + + + if ( status != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID " + "%s on channel: %d"), + pLimMlmScanReq->ssId[i].ssId, + channelNum);) + return; + } + i++; + } while (i < pLimMlmScanReq->numSsid); + + /* Activate timer again */ + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, pPeriodicProbeReqTimer->sessionId, eLIM_PERIODIC_PROBE_REQ_TIMER)); + if (tx_timer_activate(pPeriodicProbeReqTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not start periodic probe" + " req timer")); + return; + } + } + else + { + /** + * Periodic scan is timeout is happening in + * in states other than wait_scan. + * Log error. + */ + limLog(pMac, LOG1, + FL("received unexpected Periodic scan timeout in state %X"), + pMac->lim.gLimMlmState); + } +} /*** limProcessPeriodicProbeReqTimer() ***/ + +/** + * limProcessJoinFailureTimeout() + * + *FUNCTION: + * This function is called to process JoinFailureTimeout + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessJoinFailureTimeout(tpAniSirGlobal pMac) +{ + tLimMlmJoinCnf mlmJoinCnf; + tANI_U32 len; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT_LIM + vos_log_rssi_pkt_type *pRssiLog = NULL; +#endif //FEATURE_WLAN_DIAG_SUPPORT_LIM + + //fetch the sessionEntry based on the sessionId + tpPESession psessionEntry; + + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimJoinFailureTimer.sessionId))== NULL) + { + limLog(pMac, LOGE, FL("Session Does not exist for given sessionID")); + return; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT_LIM + WLAN_VOS_DIAG_LOG_ALLOC(pRssiLog, + vos_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C); + if (pRssiLog) + { + pRssiLog->rssi = psessionEntry->rssi; + } + WLAN_VOS_DIAG_LOG_REPORT(pRssiLog); +#endif //FEATURE_WLAN_DIAG_SUPPORT_LIM + + if (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) + { + len = sizeof(tSirMacAddr); + + // 'Change' timer for future activations + limDeactivateAndChangeTimer(pMac, eLIM_JOIN_FAIL_TIMER); + // Change Periodic probe req timer for future activation + limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + /** + * Issue MLM join confirm with timeout reason code + */ + PELOGE(limLog(pMac, LOGE, + FL("Join Failure Timeout, In eLIM_MLM_WT_JOIN_BEACON_STATE session: %d"), + psessionEntry->peSessionId); + limPrintMacAddr(pMac, psessionEntry->bssId, LOGE);) + + mlmJoinCnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE; + mlmJoinCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) + /* Update PE session Id */ + mlmJoinCnf.sessionId = psessionEntry->peSessionId; + + + // Freeup buffer allocated to join request + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + limPostSmeMessage(pMac, + LIM_MLM_JOIN_CNF, + (tANI_U32 *) &mlmJoinCnf); + + return; + } + else + { + /** + * Join failure timer should not have timed out + * in states other than wait_join_beacon state. + * Log error. + */ + limLog(pMac, LOGW, + FL("received unexpected JOIN failure timeout in state %X"),psessionEntry->limMlmState); + limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); + } +} /*** limProcessJoinFailureTimeout() ***/ + + +/** + * limProcessPeriodicJoinProbeReqTimer() + * + *FUNCTION: + * This function is called to process periodic probe request + * send during joining process. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void limProcessPeriodicJoinProbeReqTimer(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry; + tSirMacSSid ssId; + + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId))== NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given SessionId : %d"), + pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId); + return; + } + + if((VOS_TRUE == tx_timer_running(&pMac->lim.limTimers.gLimJoinFailureTimer)) && + (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE)) + { + vos_mem_copy(ssId.ssId, + psessionEntry->ssId.ssId, + psessionEntry->ssId.length); + ssId.length = psessionEntry->ssId.length; + + limSendProbeReqMgmtFrame( pMac, &ssId, + psessionEntry->pLimMlmJoinReq->bssDescription.bssId, psessionEntry->currentOperChannel/*chanNum*/, + psessionEntry->selfMacAddr, psessionEntry->dot11mode, + psessionEntry->pLimJoinReq->addIEScan.length, psessionEntry->pLimJoinReq->addIEScan.addIEdata); + + limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + + // Activate Join Periodic Probe Req timer + if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer")); + return; + } + } + return; +} /*** limProcessPeriodicJoinProbeReqTimer() ***/ + +/** + * lim_process_auth_retry_timer()- function to Retry Auth + * @mac_ctx:pointer to global mac + * Return: void + */ + +static void lim_process_auth_retry_timer(tpAniSirGlobal mac_ctx) +{ + tpPESession session_entry; + + limLog(mac_ctx, LOG1, FL(" ENTER ")); + + session_entry = + peFindSessionBySessionId(mac_ctx, + mac_ctx->lim.limTimers.g_lim_periodic_auth_retry_timer.sessionId); + if (NULL == session_entry) { + limLog(mac_ctx, LOGE, + FL("session does not exist for given SessionId : %d"), + mac_ctx->lim.limTimers.g_lim_periodic_auth_retry_timer.sessionId); + return; + } + + if ((VOS_TRUE == + tx_timer_running(&mac_ctx->lim.limTimers.gLimAuthFailureTimer)) && + (session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) && + (LIM_AUTH_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) { + tSirMacAuthFrameBody auth_frame; + + /* Send the auth retry only in case we have received ack failure + * else just restart the retry timer. + */ + if (LIM_AUTH_ACK_RCD_FAILURE == mac_ctx->auth_ack_status) { + /* Prepare & send Authentication frame */ + auth_frame.authAlgoNumber = + (tANI_U8) mac_ctx->lim.gpLimMlmAuthReq->authType; + auth_frame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; + auth_frame.authStatusCode = 0; + limLog(mac_ctx, LOGW, FL("Retry Auth ")); + mac_ctx->auth_ack_status = LIM_AUTH_ACK_NOT_RCD; + limSendAuthMgmtFrame(mac_ctx, + &auth_frame, + mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr, + LIM_NO_WEP_IN_FC, session_entry, eSIR_TRUE); + } + + limDeactivateAndChangeTimer(mac_ctx, eLIM_AUTH_RETRY_TIMER); + + /* Activate Auth Retry timer */ + if (tx_timer_activate + (&mac_ctx->lim.limTimers.g_lim_periodic_auth_retry_timer) + != TX_SUCCESS) { + limLog(mac_ctx, LOGE, + FL("could not activate Auth Retry failure timer")); + return; + } + } + return; +} /*** lim_process_auth_retry_timer() ***/ + + +/** + * limProcessAuthFailureTimeout() + * + *FUNCTION: + * This function is called to process Min Channel Timeout + * during channel scan. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessAuthFailureTimeout(tpAniSirGlobal pMac) +{ + //fetch the sessionEntry based on the sessionId + tpPESession psessionEntry; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT_LIM + vos_log_rssi_pkt_type *pRssiLog = NULL; +#endif //FEATURE_WLAN_DIAG_SUPPORT_LIM + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAuthFailureTimer.sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + limLog(pMac, LOGE, FL("received AUTH failure timeout in sessionid %d " + "limMlmstate %X limSmeState %X"), psessionEntry->peSessionId, + psessionEntry->limMlmState, psessionEntry->limSmeState); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT_LIM + WLAN_VOS_DIAG_LOG_ALLOC(pRssiLog, + vos_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C); + if (pRssiLog) + { + pRssiLog->rssi = psessionEntry->rssi; + } + WLAN_VOS_DIAG_LOG_REPORT(pRssiLog); +#endif //FEATURE_WLAN_DIAG_SUPPORT_LIM + + switch (psessionEntry->limMlmState) + { + case eLIM_MLM_WT_AUTH_FRAME2_STATE: + case eLIM_MLM_WT_AUTH_FRAME4_STATE: + /** + * Requesting STA did not receive next auth frame + * before Auth Failure timeout. + * Issue MLM auth confirm with timeout reason code + */ + //Restore default failure timeout + if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona && psessionEntry->defaultAuthFailureTimeout) + { + ccmCfgSetInt(pMac,WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT , + psessionEntry->defaultAuthFailureTimeout, NULL, eANI_BOOLEAN_FALSE); + } + limRestoreFromAuthState(pMac,eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + break; + + default: + /** + * Auth failure timer should not have timed out + * in states other than wt_auth_frame2/4 + * Log error. + */ + PELOGE(limLog(pMac, LOGE, FL("received unexpected AUTH failure timeout in state %X"), psessionEntry->limMlmState);) + limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); + + break; + } +} /*** limProcessAuthFailureTimeout() ***/ + + + +/** + * limProcessAuthRspTimeout() + * + *FUNCTION: + * This function is called to process Min Channel Timeout + * during channel scan. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessAuthRspTimeout(tpAniSirGlobal pMac, tANI_U32 authIndex) +{ + struct tLimPreAuthNode *pAuthNode; + tpPESession psessionEntry; + tANI_U8 sessionId; + + pAuthNode = limGetPreAuthNodeFromIndex(pMac, &pMac->lim.gLimPreAuthTimerTable, authIndex); + + if (NULL == pAuthNode) + { + limLog(pMac, LOGW, FL("Invalid auth node")); + return; + } + + if ((psessionEntry = peFindSessionByBssid(pMac, pAuthNode->peerMacAddr, &sessionId)) == NULL) + { + limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) { + if (pAuthNode->mlmState != eLIM_MLM_WT_AUTH_FRAME3_STATE) + { + /** + * Authentication response timer timedout + * in unexpected state. Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("received AUTH rsp timeout in unexpected state " + "for MAC address: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pAuthNode->peerMacAddr));) + } + else + { + // Authentication response timer + // timedout for an STA. + pAuthNode->mlmState = eLIM_MLM_AUTH_RSP_TIMEOUT_STATE; + pAuthNode->fTimerStarted = 0; + PELOG1( limLog(pMac, LOG1, + FL("AUTH rsp timedout for MAC address "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pAuthNode->peerMacAddr));) + + // Change timer to reactivate it in future + limDeactivateAndChangePerStaIdTimer(pMac, + eLIM_AUTH_RSP_TIMER, + pAuthNode->authNodeIdx); + + limDeletePreAuthNode(pMac, pAuthNode->peerMacAddr); + } + } +} /*** limProcessAuthRspTimeout() ***/ + + +/** + * limProcessAssocFailureTimeout() + * + *FUNCTION: + * This function is called to process Min Channel Timeout + * during channel scan. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) +{ + + tLimMlmAssocCnf mlmAssocCnf; + tpPESession psessionEntry; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT_LIM + vos_log_rssi_pkt_type *pRssiLog = NULL; +#endif //FEATURE_WLAN_DIAG_SUPPORT_LIM + + //to fetch the lim/mlm state based on the sessionId, use the below sessionEntry + tANI_U8 sessionId; + + if(MsgType == LIM_ASSOC) + { + sessionId = pMac->lim.limTimers.gLimAssocFailureTimer.sessionId; + } + else + { + sessionId = pMac->lim.limTimers.gLimReassocFailureTimer.sessionId; + } + + if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT_LIM + WLAN_VOS_DIAG_LOG_ALLOC(pRssiLog, + vos_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C); + if (pRssiLog) + { + pRssiLog->rssi = psessionEntry->rssi; + } + WLAN_VOS_DIAG_LOG_REPORT(pRssiLog); +#endif //FEATURE_WLAN_DIAG_SUPPORT_LIM + + /** + * Expected Re/Association Response frame + * not received within Re/Association Failure Timeout. + */ + + + + + /* CR: vos packet memory is leaked when assoc rsp timeouted/failed. */ + /* notify TL that association is failed so that TL can flush the cached frame */ + WLANTL_AssocFailed (psessionEntry->staId); + + // Log error + PELOG1(limLog(pMac, LOG1, + FL("Re/Association Response not received before timeout "));) + + if ((LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) || + ((psessionEntry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) && + (psessionEntry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) && + (psessionEntry->limMlmState != eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) { + /** + * Re/Assoc failure timer should not have timedout on AP + * or in a state other than wt_re/assoc_response. + */ + + // Log error + limLog(pMac, LOGW, + FL("received unexpected REASSOC failure timeout in state %X for role %d"), + psessionEntry->limMlmState, GET_LIM_SYSTEM_ROLE(psessionEntry)); + limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); + } else { + if ((MsgType == LIM_ASSOC) || + ((MsgType == LIM_REASSOC) && (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) + { + PELOGE(limLog(pMac, LOGE, FL("(Re)Assoc Failure Timeout occurred."));) + + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + // 'Change' timer for future activations + limDeactivateAndChangeTimer(pMac, eLIM_ASSOC_FAIL_TIMER); + + // Free up buffer allocated for JoinReq held by + // MLM state machine + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + //To remove the preauth node in case of fail to associate + if (limSearchPreAuthList(pMac, psessionEntry->bssId)) + { + PELOG1(limLog(pMac, LOG1, FL(" delete pre auth node for " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(psessionEntry->bssId));) + limDeletePreAuthNode(pMac, psessionEntry->bssId); + } + + mlmAssocCnf.resultCode = + eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE; + mlmAssocCnf.protStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; + + /* Update PE session Id*/ + mlmAssocCnf.sessionId = psessionEntry->peSessionId; + if (MsgType == LIM_ASSOC) + limPostSmeMessage(pMac, LIM_MLM_ASSOC_CNF, (tANI_U32 *) &mlmAssocCnf); + else + { + /* Will come here only in case of 11r, Ese FT when reassoc rsp + is not received and we receive a reassoc - timesout */ + mlmAssocCnf.resultCode = eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE; + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmAssocCnf); + } + } + else + { + /** + * Restore pre-reassoc req state. + * Set BSSID to currently associated AP address. + */ + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + limRestorePreReassocState(pMac, + eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE, eSIR_MAC_UNSPEC_FAILURE_STATUS,psessionEntry); + } + } +} /*** limProcessAssocFailureTimeout() ***/ + + + +/** + * limCompleteMlmScan() + * + *FUNCTION: + * This function is called to send MLM_SCAN_CNF message + * to SME state machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param retCode Result code to be sent + * @return None + */ + +void +limCompleteMlmScan(tpAniSirGlobal pMac, tSirResultCodes retCode) +{ + tLimMlmScanCnf mlmScanCnf; + + /// Restore previous MLM state + pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState)); + limRestorePreScanState(pMac); + + // Free up pMac->lim.gLimMlmScanReq + if( NULL != pMac->lim.gpLimMlmScanReq ) + { + vos_mem_free(pMac->lim.gpLimMlmScanReq); + pMac->lim.gpLimMlmScanReq = NULL; + } + + mlmScanCnf.resultCode = retCode; + mlmScanCnf.scanResultLength = pMac->lim.gLimMlmScanResultLength; + + limPostSmeMessage(pMac, LIM_MLM_SCAN_CNF, (tANI_U32 *) &mlmScanCnf); + +} /*** limCompleteMlmScan() ***/ + +/** + * \brief Setup an A-MPDU/BA session + * + * \sa limProcessMlmAddBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pMsgBuf The MLME ADDBA Req message buffer + * + * \return none + */ +void limProcessMlmAddBAReq( tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf ) +{ +tSirRetStatus status = eSIR_SUCCESS; +tpLimMlmAddBAReq pMlmAddBAReq; +tpLimMlmAddBACnf pMlmAddBACnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmAddBAReq = (tpLimMlmAddBAReq) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBAReq->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for given sessionId"));) + vos_mem_free(pMsgBuf); + return; + } + + + // Send ADDBA Req over the air + status = limSendAddBAReq( pMac, pMlmAddBAReq,psessionEntry); + + // + // Respond immediately to LIM, only if MLME has not been + // successfully able to send WDA_ADDBA_REQ to HAL. + // Else, LIM_MLM_ADDBA_CNF will be sent after receiving + // ADDBA Rsp from peer entity + // + if( eSIR_SUCCESS != status ) + { + // Allocate for LIM_MLM_ADDBA_CNF + + pMlmAddBACnf = vos_mem_malloc(sizeof( tLimMlmAddBACnf )); + if ( NULL == pMlmAddBACnf ) + { + limLog( pMac, LOGP, + FL("AllocateMemory failed")); + vos_mem_free(pMsgBuf); + return; + } + else + { + vos_mem_set((void *) pMlmAddBACnf, sizeof( tLimMlmAddBACnf ), 0); + vos_mem_copy((void *) pMlmAddBACnf->peerMacAddr, + (void *) pMlmAddBAReq->peerMacAddr, + sizeof( tSirMacAddr )); + + pMlmAddBACnf->baDialogToken = pMlmAddBAReq->baDialogToken; + pMlmAddBACnf->baTID = pMlmAddBAReq->baTID; + pMlmAddBACnf->baPolicy = pMlmAddBAReq->baPolicy; + pMlmAddBACnf->baBufferSize = pMlmAddBAReq->baBufferSize; + pMlmAddBACnf->baTimeout = pMlmAddBAReq->baTimeout; + pMlmAddBACnf->sessionId = pMlmAddBAReq->sessionId; + + // Update the result code + pMlmAddBACnf->addBAResultCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + limPostSmeMessage( pMac, + LIM_MLM_ADDBA_CNF, + (tANI_U32 *) pMlmAddBACnf ); + } + + // Restore MLME state + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + } + + // Free the buffer allocated for tLimMlmAddBAReq + vos_mem_free(pMsgBuf); + +} + +/** + * \brief Send an ADDBA Rsp to peer STA in response + * to an ADDBA Req received earlier + * + * \sa limProcessMlmAddBARsp + * + * \param pMac The global tpAniSirGlobal object + * + * \param pMsgBuf The MLME ADDBA Rsp message buffer + * + * \return none + */ +void limProcessMlmAddBARsp( tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf ) +{ +tpLimMlmAddBARsp pMlmAddBARsp; + tANI_U16 aid; + tpDphHashNode pSta; + tpPESession psessionEntry; + + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + pMlmAddBARsp = (tpLimMlmAddBARsp) pMsgBuf; + + if(( psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBARsp->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for given session ID"));) + vos_mem_free(pMsgBuf); + return; + } + + + // Send ADDBA Rsp over the air + if( eSIR_SUCCESS != limSendAddBARsp( pMac,pMlmAddBARsp,psessionEntry)) + { + limLog( pMac, LOGE, + FL("Failed to send ADDBA Rsp to peer ")); + limPrintMacAddr( pMac, pMlmAddBARsp->peerMacAddr, LOGE ); + /* Clean the BA context maintained by HAL and TL on failure */ + pSta = dphLookupHashEntry( pMac, pMlmAddBARsp->peerMacAddr, &aid, + &psessionEntry->dph.dphHashTable); + if( NULL != pSta ) + { + limPostMsgDelBAInd( pMac, pSta, pMlmAddBARsp->baTID, eBA_RECIPIENT, + psessionEntry); + } + } + + // Time to post a WDA_DELBA_IND to HAL in order + // to cleanup the HAL and SoftMAC entries + + + // Free the buffer allocated for tLimMlmAddBARsp + vos_mem_free(pMsgBuf); + +} + +/** + * \brief Setup an A-MPDU/BA session + * + * \sa limProcessMlmDelBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pMsgBuf The MLME DELBA Req message buffer + * + * \return none + */ +void limProcessMlmDelBAReq( tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf ) +{ + tSirRetStatus status = eSIR_SUCCESS; + tpLimMlmDelBAReq pMlmDelBAReq; + tpLimMlmDelBACnf pMlmDelBACnf; + tpPESession psessionEntry; + + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + + // TODO - Need to validate MLME state + pMlmDelBAReq = (tpLimMlmDelBAReq) pMsgBuf; + + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDelBAReq->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) + vos_mem_free(pMsgBuf); + return; + } + + // Send DELBA Ind over the air + if( eSIR_SUCCESS != + (status = limSendDelBAInd( pMac, pMlmDelBAReq,psessionEntry))) + status = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + else + { + tANI_U16 aid; + tpDphHashNode pSta; + + // Time to post a WDA_DELBA_IND to HAL in order + // to cleanup the HAL and SoftMAC entries + pSta = dphLookupHashEntry( pMac, pMlmDelBAReq->peerMacAddr, &aid , &psessionEntry->dph.dphHashTable); + if( NULL != pSta ) + { + status = limPostMsgDelBAInd( pMac, + pSta, + pMlmDelBAReq->baTID, + pMlmDelBAReq->baDirection,psessionEntry); + + } + } + + // + // Respond immediately to SME with DELBA CNF using + // LIM_MLM_DELBA_CNF with appropriate status + // + + // Allocate for LIM_MLM_DELBA_CNF + + pMlmDelBACnf = vos_mem_malloc(sizeof( tLimMlmDelBACnf )); + if ( NULL == pMlmDelBACnf ) + { + limLog( pMac, LOGP, FL("AllocateMemory failed")); + vos_mem_free(pMsgBuf); + return; + } + else + { + vos_mem_set((void *) pMlmDelBACnf, sizeof( tLimMlmDelBACnf ), 0); + + vos_mem_copy((void *) pMlmDelBACnf, + (void *) pMlmDelBAReq, + sizeof( tLimMlmDelBAReq )); + + // Update DELBA result code + pMlmDelBACnf->delBAReasonCode = pMlmDelBAReq->delBAReasonCode; + + /* Update PE session Id*/ + pMlmDelBACnf->sessionId = pMlmDelBAReq->sessionId; + + limPostSmeMessage( pMac, + LIM_MLM_DELBA_CNF, + (tANI_U32 *) pMlmDelBACnf ); + } + + // Free the buffer allocated for tLimMlmDelBAReq + vos_mem_free(pMsgBuf); + +} + +/** + * @function : limSMPowerSaveStateInd( ) + * + * @brief : This function is called upon receiving the PMC Indication to update the STA's MimoPs State. + * + * LOGIC: + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param limMsg - Lim Message structure object with the MimoPSparam in body + * @return None + */ + +tSirRetStatus +limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) +{ +return eSIR_SUCCESS; +} + +#ifdef WLAN_FEATURE_11AC +ePhyChanBondState limGet11ACPhyCBState(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 htSecondaryChannelOffset,tANI_U8 peerCenterChan, tpPESession psessionEntry) +{ + ePhyChanBondState cbState = PHY_SINGLE_CHANNEL_CENTERED; + + if(!psessionEntry->apChanWidth) + { + return htSecondaryChannelOffset; + } + + if ( (htSecondaryChannelOffset + == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + ) + { + if ((channel + 2 ) == peerCenterChan ) + cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED; + else if ((channel + 6 ) == peerCenterChan ) + cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW; + else if ((channel - 2 ) == peerCenterChan ) + cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; + else + limLog (pMac, LOGP, + FL("Invalid Channel Number = %d Center Chan = %d "), + channel, peerCenterChan); + } + if ( (htSecondaryChannelOffset + == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + ) + { + if ((channel - 2 ) == peerCenterChan ) + cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED; + else if ((channel + 2 ) == peerCenterChan ) + cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW; + else if ((channel - 6 ) == peerCenterChan ) + cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; + else + limLog (pMac, LOGP, + FL("Invalid Channel Number = %d Center Chan = %d "), + channel, peerCenterChan); + } + return cbState; +} + +#endif + +void +limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tPowerdBm maxTxPower, tANI_U8 peSessionId) +{ +#if !defined WLAN_FEATURE_VOWIFI + tANI_U32 localPwrConstraint; +#endif + tpPESession peSession; + + peSession = peFindSessionBySessionId (pMac, peSessionId); + + if ( NULL == peSession) + { + limLog (pMac, LOGP, FL("Invalid PE session = %d"), peSessionId); + return; + } +#if defined WLAN_FEATURE_VOWIFI +#ifdef WLAN_FEATURE_11AC + if ( peSession->vhtCapability ) + { + limSendSwitchChnlParams(pMac, channel, + limGet11ACPhyCBState( pMac,channel, + secChannelOffset,peSession->apCenterChan, peSession), + maxTxPower, peSessionId, VOS_FALSE); + } + else +#endif + { + limSendSwitchChnlParams(pMac, channel, secChannelOffset, maxTxPower, + peSessionId, VOS_FALSE); + } +#else + if (wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { + limLog(pMac, LOGP, FL("could not read WNI_CFG_LOCAL_POWER_CONSTRAINT from CFG")); + return; + } + // Send WDA_CHNL_SWITCH_IND to HAL +#ifdef WLAN_FEATURE_11AC + if ( peSession->vhtCapability && peSession->vhtCapabilityPresentInBeacon) + { + limSendSwitchChnlParams(pMac, channel, + limGet11ACPhyCBState( pMac,channel, + secChannelOffset,peSession->apCenterChan, + peSession), maxTxPower, + peSessionId, VOS_FALSE); + } + else +#endif + { + limSendSwitchChnlParams(pMac, channel, secChannelOffset, + (tPowerdBm)localPwrConstraint, peSessionId, + VOS_FALSE); + } +#endif + + } diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c new file mode 100644 index 000000000000..416ae572d77a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -0,0 +1,5111 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limProcessMlmRspMessages.cc contains the code + * for processing response messages from MLM state machine. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "wniApi.h" +#include "wniCfgSta.h" +#include "cfgApi.h" +#include "sirApi.h" +#include "schApi.h" +#include "utilsApi.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limTimerUtils.h" +#include "limSendMessages.h" +#include "limAdmitControl.h" +#include "limSendMessages.h" +#include "limIbssPeerMgmt.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFT.h" +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "limSessionUtils.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif +#include "wlan_qct_wda.h" +#include "vos_utils.h" + +#define MAX_SUPPORTED_PEERS_WEP 16 + +static void limHandleSmeReaasocResult(tpAniSirGlobal, tSirResultCodes, tANI_U16, tpPESession); +void limProcessMlmScanCnf(tpAniSirGlobal, tANI_U32 *); +#ifdef FEATURE_OEM_DATA_SUPPORT +void limProcessMlmOemDataReqCnf(tpAniSirGlobal, tANI_U32 *); +#endif +void limProcessMlmJoinCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmAuthCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmStartCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmAuthInd(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmAssocInd(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmAssocCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmReassocCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmReassocInd(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmSetKeysCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmDisassocInd(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmDisassocCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmDeauthInd(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmDeauthCnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmPurgeStaInd(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmAddBACnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmDelBACnf(tpAniSirGlobal, tANI_U32 *); +void limProcessMlmRemoveKeyCnf(tpAniSirGlobal pMac, tANI_U32 * pMsgBuf); +static void limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession psessionEntry); +void limGetSessionInfo(tpAniSirGlobal pMac, tANI_U8 *, tANI_U8 *, tANI_U16 *); +static void +limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry); +/** + * limProcessMlmRspMessages() + * + *FUNCTION: + * This function is called to processes various MLM response (CNF/IND + * messages from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the MLM message type + * @param *pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmRspMessages(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) +{ + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + MTRACE(macTrace(pMac, TRACE_CODE_TX_LIM_MSG, 0, msgType)); + switch (msgType) + { + case LIM_MLM_SCAN_CNF: + limProcessMlmScanCnf(pMac, pMsgBuf); + break; + +#ifdef FEATURE_OEM_DATA_SUPPORT + case LIM_MLM_OEM_DATA_CNF: + limProcessMlmOemDataReqCnf(pMac, pMsgBuf); + pMsgBuf = NULL; + break; +#endif + + case LIM_MLM_AUTH_CNF: + limProcessMlmAuthCnf(pMac, pMsgBuf); + break; + case LIM_MLM_AUTH_IND: + limProcessMlmAuthInd(pMac, pMsgBuf); + break; + case LIM_MLM_ASSOC_CNF: + limProcessMlmAssocCnf(pMac, pMsgBuf); + break; + case LIM_MLM_START_CNF: + limProcessMlmStartCnf(pMac, pMsgBuf); + break; + case LIM_MLM_JOIN_CNF: + limProcessMlmJoinCnf(pMac, pMsgBuf); + break; + case LIM_MLM_ASSOC_IND: + limProcessMlmAssocInd(pMac, pMsgBuf); + break; + case LIM_MLM_REASSOC_CNF: + limProcessMlmReassocCnf(pMac, pMsgBuf); + break; + case LIM_MLM_REASSOC_IND: + limProcessMlmReassocInd(pMac, pMsgBuf); + break; + case LIM_MLM_DISASSOC_CNF: + limProcessMlmDisassocCnf(pMac, pMsgBuf); + break; + case LIM_MLM_DISASSOC_IND: + limProcessMlmDisassocInd(pMac, pMsgBuf); + break; + case LIM_MLM_PURGE_STA_IND: + limProcessMlmPurgeStaInd(pMac, pMsgBuf); + break; + case LIM_MLM_DEAUTH_CNF: + limProcessMlmDeauthCnf(pMac, pMsgBuf); + break; + case LIM_MLM_DEAUTH_IND: + limProcessMlmDeauthInd(pMac, pMsgBuf); + break; + case LIM_MLM_SETKEYS_CNF: + limProcessMlmSetKeysCnf(pMac, pMsgBuf); + break; + case LIM_MLM_REMOVEKEY_CNF: + limProcessMlmRemoveKeyCnf(pMac, pMsgBuf); + break; + case LIM_MLM_TSPEC_CNF: + break; + case LIM_MLM_ADDBA_CNF: + limProcessMlmAddBACnf( pMac, pMsgBuf ); + pMsgBuf = NULL; + break; + case LIM_MLM_DELBA_CNF: + limProcessMlmDelBACnf( pMac, pMsgBuf ); + pMsgBuf = NULL; + break; + default: + break; + } // switch (msgType) + return; +} /*** end limProcessMlmRspMessages() ***/ + +/** + * limProcessMlmScanCnf() + * + *FUNCTION: + * This function is called to processes MLM_SCAN_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmScanCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + switch(pMac->lim.gLimSmeState) + { + case eLIM_SME_WT_SCAN_STATE: + //case eLIM_SME_LINK_EST_WT_SCAN_STATE: //TO SUPPORT BT-AMP + //case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE: //TO SUPPORT BT-AMP + pMac->lim.gLimSmeState = pMac->lim.gLimPrevSmeState; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, NO_SESSION, pMac->lim.gLimSmeState)); + pMac->lim.gLimSystemInScanLearnMode = 0; + break; + default: + /** + * Should not have received scan confirm + * from MLM in other states. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("received unexpected MLM_SCAN_CNF in state %X"), + pMac->lim.gLimSmeState);) + return; + } + + /// Process received scan confirm + /// Increment length of cached scan results + pMac->lim.gLimSmeScanResultLength += + ((tLimMlmScanCnf *) pMsgBuf)->scanResultLength; + if ((pMac->lim.gLimRspReqd) || pMac->lim.gLimReportBackgroundScanResults) + { + tANI_U16 scanRspLen = 0; + /// Need to send response to Host + pMac->lim.gLimRspReqd = false; + if ((((tLimMlmScanCnf *) pMsgBuf)->resultCode == + eSIR_SME_SUCCESS) || + pMac->lim.gLimSmeScanResultLength) + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeScanResultLength - + sizeof(tSirBssDescription); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp); + } + if(pMac->lim.gLimReportBackgroundScanResults) + { + pMac->lim.gLimBackgroundScanTerminate = TRUE; + } + if (pMac->lim.gLimSmeScanResultLength == 0) + { + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId); + } + else + { + limSendSmeScanRsp(pMac, scanRspLen, + eSIR_SME_SUCCESS,pMac->lim.gSmeSessionId, pMac->lim.gTransactionId); + } + } // if (pMac->lim.gLimRspReqd) + //check to see whether we need to run bgScan timer + if(pMac->lim.gLimBackgroundScanTerminate == FALSE) + { + if (tx_timer_activate( + &pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) + { + /// Could not activate background scan timer. + // Log error + limLog(pMac, LOGP, + FL("could not activate background scan timer")); + pMac->lim.gLimBackgroundScanStarted = FALSE; + } + else + { + pMac->lim.gLimBackgroundScanStarted = TRUE; + } + } +} /*** end limProcessMlmScanCnf() ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * limProcessMlmOemDataReqCnf() + * + *FUNCTION: + * This function is called to processes LIM_MLM_OEM_DATA_REQ_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ + +void limProcessMlmOemDataReqCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmOemDataRsp* measRsp; + + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + + measRsp = (tLimMlmOemDataRsp*)(pMsgBuf); + + //Now send the meas confirm message to the sme + limSendSmeOemDataRsp(pMac, (tANI_U32*)measRsp, resultCode); + + //Dont free the memory here. It will be freed up by the callee + + return; +} +#endif + +/** + * limProcessMlmStartCnf() + * + *FUNCTION: + * This function is called to processes MLM_START_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpPESession psessionEntry = NULL; + tLimMlmStartCnf *pLimMlmStartCnf; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + tANI_U8 channelId; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pLimMlmStartCnf = (tLimMlmStartCnf*)pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmStartCnf->sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId "));) + return; + } + smesessionId = psessionEntry->smeSessionId; + smetransactionId = psessionEntry->transactionId; + + if (psessionEntry->limSmeState != eLIM_SME_WT_START_BSS_STATE) + { + /** + * Should not have received Start confirm from MLM + * in other states. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("received unexpected MLM_START_CNF in state %X"), + psessionEntry->limSmeState);) + return; + } + if (((tLimMlmStartCnf *) pMsgBuf)->resultCode == + eSIR_SME_SUCCESS) + { + + /** + * Update global SME state so that Beacon Generation + * module starts writing Beacon frames into TFP's + * Beacon file register. + */ + psessionEntry->limSmeState = eLIM_SME_NORMAL_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + if(psessionEntry->bssType == eSIR_BTAMP_STA_MODE) + { + limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP STA SIDE***")); + } + else if(psessionEntry->bssType == eSIR_BTAMP_AP_MODE) + { + limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP AP SIDE***")); + } + else if(psessionEntry->bssType == eSIR_INFRA_AP_MODE) + { + limLog(pMac, LOG1, FL("*** Started BSS in INFRA AP SIDE***")); + } + else + PELOG1(limLog(pMac, LOG1, FL("*** Started BSS ***"));) + } + else + { + /// Start BSS is a failure + peDeleteSession(pMac,psessionEntry); + psessionEntry = NULL; + PELOGE(limLog(pMac, LOGE,FL("Start BSS Failed "));) + } + /// Send response to Host + limSendSmeStartBssRsp(pMac, eWNI_SME_START_BSS_RSP, + ((tLimMlmStartCnf *) pMsgBuf)->resultCode,psessionEntry, + smesessionId,smetransactionId); + if ((psessionEntry != NULL) && + (((tLimMlmStartCnf *) pMsgBuf)->resultCode == eSIR_SME_SUCCESS)) + { + channelId = psessionEntry->pLimStartBssReq->channelId; + + // We should start beacon transmission only if the channel + // on which we are operating is non-DFS until the channel + // availability check is done. The PE will receive an explicit + // request from upper layers to start the beacon transmission + + + if (LIM_IS_IBSS_ROLE(psessionEntry) || (LIM_IS_AP_ROLE(psessionEntry) && + (vos_nv_getChannelEnabledState(channelId) != NV_CHANNEL_DFS))) { + //Configure beacon and send beacons to HAL + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("Start Beacon with ssid %s Ch %d"), + psessionEntry->ssId.ssId, + psessionEntry->currentOperChannel); + limSendBeaconInd(pMac, psessionEntry); + } + } +} + + /*** end limProcessMlmStartCnf() ***/ + +/** + * limProcessMlmJoinCnf() + * + *FUNCTION: + * This function is called to processes MLM_JOIN_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmJoinCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirResultCodes resultCode; + tLimMlmJoinCnf *pLimMlmJoinCnf; + tpPESession psessionEntry; + pLimMlmJoinCnf = (tLimMlmJoinCnf*)pMsgBuf; + if( (psessionEntry = peFindSessionBySessionId(pMac,pLimMlmJoinCnf->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("SessionId:%d Session does not exist"), + pLimMlmJoinCnf->sessionId);) + return; + } + + if (psessionEntry->limSmeState!= eLIM_SME_WT_JOIN_STATE) + { + PELOGE(limLog(pMac, LOGE, + FL("received unexpected MLM_JOIN_CNF in state %X"), + psessionEntry->limSmeState);) + return; + } + + resultCode = ((tLimMlmJoinCnf *) pMsgBuf)->resultCode ; + /// Process Join confirm from MLM + if (resultCode == eSIR_SME_SUCCESS) + { + PELOG1(limLog(pMac, LOG1, FL("***SessionId:%d Joined ESS ***"), + pLimMlmJoinCnf->sessionId);) + //Setup hardware upfront + if(limStaSendAddBssPreAssoc( pMac, false, psessionEntry) == eSIR_SUCCESS) + return; + else + resultCode = eSIR_SME_REFUSED; + } + { + /// Join failure + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + /// Send Join response to Host + limHandleSmeJoinResult(pMac, resultCode, ((tLimMlmJoinCnf *) pMsgBuf)->protStatusCode, psessionEntry ); + } +} /*** end limProcessMlmJoinCnf() ***/ + +/* + * limSendMlmAssocReq() + * + * FUNCTION: + * This function is sends ASSOC request MLM message to MLM State machine. + * ASSOC request packet would be by picking parameters from psessionEntry + * automatically based on the current state of MLM state machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * this function is called in middle of connection state machine and is + * expected to be called after auth cnf has been received or after ASSOC rsp + * with TRY_AGAIN_LATER was received and required time has elapsed after that. + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param psessionEntry Pointer to session etnry + * + * @return None + */ + +void +limSendMlmAssocReq( tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tLimMlmAssocReq *pMlmAssocReq; + tANI_U32 val; + tANI_U16 caps; + tANI_U32 teleBcnEn = 0; + + /* Successful MAC based authentication. Trigger Association with BSS */ + PELOG1(limLog(pMac, LOG1, FL("SessionId:%d Authenticated with BSS"), + psessionEntry->peSessionId);) + + if (NULL == psessionEntry->pLimJoinReq) { + limLog(pMac, LOGE, FL("Join Request is NULL.")); + /* No need to Assert. JOIN timeout will handle this error */ + return; + } + + pMlmAssocReq = vos_mem_malloc(sizeof(tLimMlmAssocReq)); + if ( NULL == pMlmAssocReq ) { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for mlmAssocReq")); + return; + } + val = sizeof(tSirMacAddr); + sirCopyMacAddr(pMlmAssocReq->peerMacAddr,psessionEntry->bssId); + if (wlan_cfgGetInt(pMac, + WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + (tANI_U32 *) &pMlmAssocReq->assocFailureTimeout) + != eSIR_SUCCESS) { + /* Could not get AssocFailureTimeout value from CFG. Log error */ + limLog(pMac, LOGP, FL("could not retrieve AssocFailureTimeout value")); + } + + if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { + /* Could not get Capabilities value from CFG. Log error */ + limLog(pMac, LOGP, + FL("could not retrieve Capabilities value")); + } + + /* Clear spectrum management bit if AP doesn't support it */ + if(!(psessionEntry->pLimJoinReq->bssDescription.capabilityInfo & + LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) { + /* + * AP doesn't support spectrum management + * clear spectrum management bit + */ + caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK); + } + + /* + * RM capability should be independent of AP's capabilities + * Refer 8.4.1.4 Capability Information field in 802.11-2012 + * Do not modify it. + */ + + /* Clear short preamble bit if AP does not support it */ + if(!(psessionEntry->pLimJoinReq->bssDescription.capabilityInfo & + (LIM_SHORT_PREAMBLE_BIT_MASK))) { + caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK); + limLog(pMac, LOG1, FL("Clearing short preamble:no AP support")); + } + + /* Clear immediate block ack bit if AP does not support it */ + if(!(psessionEntry->pLimJoinReq->bssDescription.capabilityInfo & + (LIM_IMMEDIATE_BLOCK_ACK_MASK))) { + caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK); + limLog(pMac, LOG1, FL("Clearing Immed Blk Ack:no AP support")); + } + + pMlmAssocReq->capabilityInfo = caps; + PELOG3(limLog(pMac, LOG3, + FL("Capabilities to be used in AssocReq=0x%X, " + "privacy bit=%x shortSlotTime %x"), + caps, + ((tpSirMacCapabilityInfo) &pMlmAssocReq->capabilityInfo)->privacy, + ((tpSirMacCapabilityInfo) &pMlmAssocReq->capabilityInfo)->shortSlotTime);) + + /* + * If telescopic beaconing is enabled, set listen interval to + * WNI_CFG_TELE_BCN_MAX_LI + */ + if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != + eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + + val = WNI_CFG_LISTEN_INTERVAL_STADEF; + + if(teleBcnEn) + { + if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != + eSIR_SUCCESS) + { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); + } + } else { + if (wlan_cfgGetInt(pMac, + WNI_CFG_LISTEN_INTERVAL, + &val) != eSIR_SUCCESS) { + /* + * Could not get ListenInterval value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); + } + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ASSOC_REQ_EVENT, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + pMlmAssocReq->listenInterval = (tANI_U16)val; + /* Update PE session ID*/ + pMlmAssocReq->sessionId = psessionEntry->peSessionId; + psessionEntry->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry->limSmeState = eLIM_SME_WT_ASSOC_STATE; + MTRACE(macTrace(pMac, + TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, + psessionEntry->limSmeState)); + limPostMlmMessage(pMac, + LIM_MLM_ASSOC_REQ, + (tANI_U32 *) pMlmAssocReq); +} + +#ifdef WLAN_FEATURE_11W +void limPmfComebackTimerCallback(void *context) +{ + tComebackTimerInfo *pInfo = (tComebackTimerInfo *)context; + tpAniSirGlobal pMac = pInfo->pMac; + tpPESession psessionEntry = &pMac->lim.gpSession[pInfo->sessionID]; + + PELOGE(limLog(pMac, LOGE, + FL("comeback later timer expired. sending MLM ASSOC req"));) + /* set MLM state such that ASSOC REQ packet will be sent out */ + psessionEntry->limPrevMlmState = pInfo->limPrevMlmState; + psessionEntry->limMlmState = pInfo->limMlmState; + limSendMlmAssocReq(pMac, psessionEntry); +} +#endif /* WLAN_FEATURE_11W */ + +/** + * limProcessMlmAuthCnf() + * + *FUNCTION: + * This function is called to processes MLM_AUTH_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tAniAuthType cfgAuthType, authMode; + tLimMlmAuthReq *pMlmAuthReq; + tLimMlmAuthCnf *pMlmAuthCnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pMlmAuthCnf = (tLimMlmAuthCnf*)pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAuthCnf->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE, FL("SessionId:%d session does not exist"), + pMlmAuthCnf->sessionId);) + return; + } + + if (((psessionEntry->limSmeState != eLIM_SME_WT_AUTH_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_PRE_AUTH_STATE)) || + LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + /** + * Should not have received AUTH confirm + * from MLM in other states or on AP. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("SessionId:%d received unexpected MLM_AUTH_CNF in state %X"), + psessionEntry->peSessionId,psessionEntry->limSmeState);) + return; + } + /// Process AUTH confirm from MLM + if (((tLimMlmAuthCnf *) pMsgBuf)->resultCode != eSIR_SME_SUCCESS) + { + if (psessionEntry->limSmeState == eLIM_SME_WT_AUTH_STATE) + { + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATION_TYPE, + (tANI_U32 *) &cfgAuthType) != eSIR_SUCCESS) + { + /** + * Could not get AuthType value from CFG. + * Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AuthType value")); + } + } + else + cfgAuthType = pMac->lim.gLimPreAuthType; + + if ((cfgAuthType == eSIR_AUTO_SWITCH) && + (((tLimMlmAuthCnf *) pMsgBuf)->authType == eSIR_OPEN_SYSTEM) + && (eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS == ((tLimMlmAuthCnf *) pMsgBuf)->protStatusCode)) + { + /** + * When Open authentication fails with reason code "13" and + * authType set to 'auto switch', Try with Shared Authentication + */ + authMode = eSIR_SHARED_KEY; + // Trigger MAC based Authentication + pMlmAuthReq = vos_mem_malloc(sizeof(tLimMlmAuthReq)); + if ( NULL == pMlmAuthReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmAuthReq")); + return; + } + vos_mem_set((tANI_U8 *) pMlmAuthReq, sizeof(tLimMlmAuthReq), 0); + if (psessionEntry->limSmeState == eLIM_SME_WT_AUTH_STATE) + { + sirCopyMacAddr(pMlmAuthReq->peerMacAddr,psessionEntry->bssId); + } + else + vos_mem_copy((tANI_U8 *) &pMlmAuthReq->peerMacAddr, + (tANI_U8 *) &pMac->lim.gLimPreAuthPeerAddr, + sizeof(tSirMacAddr)); + pMlmAuthReq->authType = authMode; + /* Update PE session Id*/ + pMlmAuthReq->sessionId = pMlmAuthCnf->sessionId; + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + (tANI_U32 *) &pMlmAuthReq->authFailureTimeout) + != eSIR_SUCCESS) + { + /** + * Could not get AuthFailureTimeout value from CFG. + * Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AuthFailureTimeout value")); + } + limPostMlmMessage(pMac, + LIM_MLM_AUTH_REQ, + (tANI_U32 *) pMlmAuthReq); + return; + } + else + { + // MAC based authentication failure + if (psessionEntry->limSmeState == eLIM_SME_WT_AUTH_STATE) + { + PELOGE(limLog(pMac, LOGE, FL("Auth Failure occurred."));) + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + /** + * Need to send Join response with + * auth failure to Host. + */ + limHandleSmeJoinResult(pMac, + ((tLimMlmAuthCnf *) pMsgBuf)->resultCode, ((tLimMlmAuthCnf *) pMsgBuf)->protStatusCode,psessionEntry); + } + else + { + /** + * Pre-authentication failure. + * Send Pre-auth failure response to host + */ + psessionEntry->limSmeState = psessionEntry->limPrevSmeState; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + } + } // end if (cfgAuthType == eAUTO_SWITCH) + } // if (((tLimMlmAuthCnf *) pMsgBuf)->resultCode != ... + else + { + if (psessionEntry->limSmeState == eLIM_SME_WT_AUTH_STATE) + { + limSendMlmAssocReq(pMac, psessionEntry); + } + else + { + /* Successful Pre-authentication. Send Pre-auth response to host */ + psessionEntry->limSmeState = psessionEntry->limPrevSmeState; + MTRACE(macTrace(pMac, + TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, + psessionEntry->limSmeState)); + } + } // end if (((tLimMlmAuthCnf *) pMsgBuf)->resultCode != ... +} /*** end limProcessMlmAuthCnf() ***/ + +/** + * limProcessMlmAssocCnf() + * + *FUNCTION: + * This function is called to processes MLM_ASSOC_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpPESession psessionEntry; + tLimMlmAssocCnf *pLimMlmAssocCnf; + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + pLimMlmAssocCnf = (tLimMlmAssocCnf*)pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmAssocCnf->sessionId)) == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("SessionId:%d Session does not exist"), + pLimMlmAssocCnf->sessionId);) + return; + } + if (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE || + LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + /** + * Should not have received Assocication confirm + * from MLM in other states OR on AP. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("SessionId:%d Received unexpected MLM_ASSOC_CNF in state %X"), + psessionEntry->peSessionId,psessionEntry->limSmeState);) + return; + } + if (((tLimMlmAssocCnf *) pMsgBuf)->resultCode != eSIR_SME_SUCCESS) + { + // Association failure + PELOG1(limLog(pMac, LOG1, FL("SessionId:%d Association failure" + "resultCode: resultCode: %d limSmeState:%d"), + psessionEntry->peSessionId, + psessionEntry->limSmeState);) + + /* If driver gets deauth when its waiting for ADD_STA_RSP then we need + * to do DEL_STA followed by DEL_BSS. So based on below reason-code here + * we decide whether to do only DEL_BSS or DEL_STA + DEL_BSS + */ + if (((tLimMlmAssocCnf *) pMsgBuf)->resultCode != + eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA) + { + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + } + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, + pMac->lim.gLimSmeState)); + /** + * Need to send Join response with + * Association failure to Host. + */ + limHandleSmeJoinResult(pMac, + ((tLimMlmAssocCnf *) pMsgBuf)->resultCode, + ((tLimMlmAssocCnf *) pMsgBuf)->protStatusCode,psessionEntry); + } // if (((tLimMlmAssocCnf *) pMsgBuf)->resultCode != ... + else + { + // Successful Association + PELOG1(limLog(pMac, LOG1, FL("SessionId:%d Associated with BSS"), + psessionEntry->peSessionId);) + psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + /** + * Need to send Join response with + * Association success to Host. + */ + limHandleSmeJoinResult(pMac, + ((tLimMlmAssocCnf *) pMsgBuf)->resultCode, + ((tLimMlmAssocCnf *) pMsgBuf)->protStatusCode,psessionEntry); + } // end if (((tLimMlmAssocCnf *) pMsgBuf)->resultCode != .... +} /*** end limProcessMlmAssocCnf() ***/ + +/** + * limProcessMlmReassocCnf() + * + *FUNCTION: + * This function is called to processes MLM_REASSOC_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpPESession psessionEntry; + tLimMlmReassocCnf *pLimMlmReassocCnf; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pLimMlmReassocCnf = (tLimMlmReassocCnf*) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmReassocCnf->sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE, FL("session Does not exist for given session Id"));) + return; + } + if ((psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE) || + LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + /** + * Should not have received Reassocication confirm + * from MLM in other states OR on AP. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X"), + GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limSmeState);) + return; + } + if (psessionEntry->pLimReAssocReq) { + vos_mem_free(psessionEntry->pLimReAssocReq); + psessionEntry->pLimReAssocReq = NULL; + } + + /* Upon Reassoc success or failure, freeup the cached + * preauth request, to ensure that channel switch is now + * allowed following any change in HT params. + */ + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + limLog(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + psessionEntry->ftPEContext.pFTPreAuthReq); + if (psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + vos_mem_free( + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + psessionEntry->ftPEContext.ftPreAuthSession = VOS_FALSE; + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:Re-set the LIM Ctxt Roam Synch In Progress"); + psessionEntry->bRoamSynchInProgress = VOS_FALSE; + } + +#endif + + PELOG1(limLog(pMac, LOG1, FL("Rcv MLM_REASSOC_CNF with result code %d"), pLimMlmReassocCnf->resultCode);) + if (pLimMlmReassocCnf->resultCode == eSIR_SME_SUCCESS) { + // Successful Reassociation + /* change logging before release */ + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "*** Reassociated with new BSS ***"); + + psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + /** + * Need to send Reassoc response with + * Reassociation success to Host. + */ + limSendSmeJoinReassocRsp( + pMac, eWNI_SME_REASSOC_RSP, + pLimMlmReassocCnf->resultCode, pLimMlmReassocCnf->protStatusCode,psessionEntry, + psessionEntry->smeSessionId,psessionEntry->transactionId); + }else if (pLimMlmReassocCnf->resultCode == eSIR_SME_REASSOC_REFUSED) { + /** Reassociation failure With the New AP + * but we still have the link with the Older AP + */ + psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + /** + * Need to send Reassoc response with + * Association failure to Host. + */ + limSendSmeJoinReassocRsp(pMac, eWNI_SME_REASSOC_RSP, + pLimMlmReassocCnf->resultCode, pLimMlmReassocCnf->protStatusCode,psessionEntry, + psessionEntry->smeSessionId,psessionEntry->transactionId); + }else { + /* If driver gets deauth when its waiting for ADD_STA_RSP then we need + * to do DEL_STA followed by DEL_BSS. So based on below reason-code here + * we decide whether to do only DEL_BSS or DEL_STA + DEL_BSS + */ + if(pLimMlmReassocCnf->resultCode + != eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA) + { + // Reassociation failure + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + + } + + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + /** + * Need to send Reassoc response with + * Association failure to Host. + */ + limHandleSmeReaasocResult(pMac, pLimMlmReassocCnf->resultCode, pLimMlmReassocCnf->protStatusCode, psessionEntry); + } +} /*** end limProcessMlmReassocCnf() ***/ + +/** + * limProcessMlmReassocInd() + * + *FUNCTION: + * This function is called to processes MLM_REASSOC_IND + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U32 len; + tSirMsgQ msgQ; + tSirSmeReassocInd *pSirSmeReassocInd; + tpDphHashNode pStaDs=0; + tpPESession psessionEntry; + tANI_U8 sessionId; + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + if((psessionEntry = peFindSessionByBssid(pMac,((tpLimMlmReassocInd)pMsgBuf)->peerMacAddr, &sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) + return; + } + /// Inform Host of STA reassociation + len = sizeof(tSirSmeReassocInd); + pSirSmeReassocInd = vos_mem_malloc(len); + if ( NULL == pSirSmeReassocInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_REASSOC_IND")); + return; + + } + sirStoreU16N((tANI_U8 *) &pSirSmeReassocInd->messageType, + eWNI_SME_REASSOC_IND); + limReassocIndSerDes(pMac, (tpLimMlmReassocInd) pMsgBuf, + (tANI_U8 *) &(pSirSmeReassocInd->length), psessionEntry); + + // Required for indicating the frames to upper layer + pSirSmeReassocInd->assocReqLength = ((tpLimMlmReassocInd) pMsgBuf)->assocReqLength; + pSirSmeReassocInd->assocReqPtr = ((tpLimMlmReassocInd) pMsgBuf)->assocReqPtr; + pSirSmeReassocInd->beaconPtr = psessionEntry->beacon; + pSirSmeReassocInd->beaconLength = psessionEntry->bcnLen; + + msgQ.type = eWNI_SME_REASSOC_IND; + msgQ.bodyptr = pSirSmeReassocInd; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOC_IND_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + pStaDs = dphGetHashEntry(pMac, ((tpLimMlmReassocInd) pMsgBuf)->aid, &psessionEntry->dph.dphHashTable); + if (! pStaDs) + { + limLog( pMac, LOGP, FL("MLM ReAssocInd: Station context no longer valid (aid %d)"), + ((tpLimMlmReassocInd) pMsgBuf)->aid); + vos_mem_free(pSirSmeReassocInd); + return; + } + + limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); + PELOG1(limLog(pMac, LOG1, + FL("Create CNF_WAIT_TIMER after received LIM_MLM_REASSOC_IND"));) + /* + ** turn on a timer to detect the loss of REASSOC CNF + **/ + limActivateCnfTimer(pMac, + (tANI_U16) ((tpLimMlmReassocInd) pMsgBuf)->aid, psessionEntry); +} /*** end limProcessMlmReassocInd() ***/ + +/** + * limProcessMlmAuthInd() + * + *FUNCTION: + * This function is called to processes MLM_AUTH_IND + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmAuthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMsgQ msgQ; + tSirSmeAuthInd *pSirSmeAuthInd; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pSirSmeAuthInd = vos_mem_malloc(sizeof(tSirSmeAuthInd)); + if ( NULL == pSirSmeAuthInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_AUTH_IND")); + } + limCopyU16((tANI_U8 *) &pSirSmeAuthInd->messageType, eWNI_SME_AUTH_IND); + limAuthIndSerDes(pMac, (tpLimMlmAuthInd) pMsgBuf, + (tANI_U8 *) &(pSirSmeAuthInd->length)); + msgQ.type = eWNI_SME_AUTH_IND; + msgQ.bodyptr = pSirSmeAuthInd; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_AUTH_IND_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); +} /*** end limProcessMlmAuthInd() ***/ + + + + +void +limFillAssocIndParams(tpAniSirGlobal pMac, tpLimMlmAssocInd pAssocInd, + tSirSmeAssocInd *pSirSmeAssocInd, + tpPESession psessionEntry) +{ + pSirSmeAssocInd->length = sizeof(tSirSmeAssocInd); + pSirSmeAssocInd->sessionId = psessionEntry->smeSessionId; + + // Required for indicating the frames to upper layer + pSirSmeAssocInd->assocReqLength = pAssocInd->assocReqLength; + pSirSmeAssocInd->assocReqPtr = pAssocInd->assocReqPtr; + + pSirSmeAssocInd->beaconPtr = psessionEntry->beacon; + pSirSmeAssocInd->beaconLength = psessionEntry->bcnLen; + + // Fill in peerMacAddr + vos_mem_copy(pSirSmeAssocInd->peerMacAddr, pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + + // Fill in aid + pSirSmeAssocInd->aid = pAssocInd->aid; + // Fill in bssId + vos_mem_copy(pSirSmeAssocInd->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + // Fill in authType + pSirSmeAssocInd->authType = pAssocInd->authType; + // Fill in ssId + vos_mem_copy((tANI_U8*)&pSirSmeAssocInd->ssId, + (tANI_U8 *) &(pAssocInd->ssId), pAssocInd->ssId.length + 1); + pSirSmeAssocInd->rsnIE.length = pAssocInd->rsnIE.length; + vos_mem_copy((tANI_U8*) &pSirSmeAssocInd->rsnIE.rsnIEdata, + (tANI_U8 *) &(pAssocInd->rsnIE.rsnIEdata), + pAssocInd->rsnIE.length); + +#ifdef FEATURE_WLAN_WAPI + pSirSmeAssocInd->wapiIE.length = pAssocInd->wapiIE.length; + vos_mem_copy((tANI_U8*) &pSirSmeAssocInd->wapiIE.wapiIEdata, + (tANI_U8 *) &(pAssocInd->wapiIE.wapiIEdata), + pAssocInd->wapiIE.length); +#endif + + pSirSmeAssocInd->addIE.length = pAssocInd->addIE.length; + vos_mem_copy((tANI_U8*) &pSirSmeAssocInd->addIE.addIEdata, + (tANI_U8 *) &(pAssocInd->addIE.addIEdata), + pAssocInd->addIE.length); + + pSirSmeAssocInd->spectrumMgtIndicator = pAssocInd->spectrumMgtIndicator; + if (pAssocInd->spectrumMgtIndicator == eSIR_TRUE) + { + pSirSmeAssocInd->powerCap.minTxPower = pAssocInd->powerCap.minTxPower; + pSirSmeAssocInd->powerCap.maxTxPower = pAssocInd->powerCap.maxTxPower; + pSirSmeAssocInd->supportedChannels.numChnl = pAssocInd->supportedChannels.numChnl; + vos_mem_copy((tANI_U8*) &pSirSmeAssocInd->supportedChannels.channelList, + (tANI_U8 *) &(pAssocInd->supportedChannels.channelList), + pAssocInd->supportedChannels.numChnl); + } + vos_mem_copy(&pSirSmeAssocInd->chan_info, &pAssocInd->chan_info, + sizeof(tSirSmeChanInfo)); + // Fill in WmmInfo + pSirSmeAssocInd->wmmEnabledSta = pAssocInd->WmmStaInfoPresent; +} /*** end limAssocIndSerDes() ***/ + + + +/** + * limProcessMlmAssocInd() + * + *FUNCTION: + * This function is called to processes MLM_ASSOC_IND + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U32 len; + tSirMsgQ msgQ; + tSirSmeAssocInd *pSirSmeAssocInd; + tpDphHashNode pStaDs=0; + tpPESession psessionEntry; + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + if((psessionEntry = peFindSessionBySessionId(pMac,((tpLimMlmAssocInd) pMsgBuf)->sessionId))== NULL) + { + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); + return; + } + /// Inform Host of STA association + len = sizeof(tSirSmeAssocInd); + pSirSmeAssocInd = vos_mem_malloc(len); + if ( NULL == pSirSmeAssocInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_ASSOC_IND")); + return; + } + + pSirSmeAssocInd->messageType = eWNI_SME_ASSOC_IND; + limFillAssocIndParams(pMac, (tpLimMlmAssocInd) pMsgBuf, pSirSmeAssocInd, psessionEntry); + msgQ.type = eWNI_SME_ASSOC_IND; + msgQ.bodyptr = pSirSmeAssocInd; + msgQ.bodyval = 0; + pStaDs = dphGetHashEntry(pMac, + ((tpLimMlmAssocInd) pMsgBuf)->aid, &psessionEntry->dph.dphHashTable); + if (! pStaDs) + { // good time to panic... + limLog(pMac, LOGE, FL("MLM AssocInd: Station context no longer valid (aid %d)"), + ((tpLimMlmAssocInd) pMsgBuf)->aid); + vos_mem_free(pSirSmeAssocInd); + + return; + } + pSirSmeAssocInd->staId = pStaDs->staIndex; + pSirSmeAssocInd->reassocReq = pStaDs->mlmStaContext.subType; + pSirSmeAssocInd->timingMeasCap = pStaDs->timingMeasCap; + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ASSOC_IND_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); + + PELOG1(limLog(pMac, LOG1, + FL("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND"));) + /* + ** turn on a timer to detect the loss of ASSOC CNF + **/ + limActivateCnfTimer(pMac, (tANI_U16) ((tpLimMlmAssocInd) pMsgBuf)->aid, psessionEntry); + +// Enable this Compile flag to test the BT-AMP -AP assoc sequence +#ifdef TEST_BTAMP_AP +//tANI_U32 *pMsgBuf; +{ + tpSirSmeAssocCnf pSmeAssoccnf; + pSmeAssoccnf = vos_mem_malloc(sizeof(tSirSmeAssocCnf)); + if ( NULL == pSmeAssoccnf ) + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed for pSmeAssoccnf "));) + pSmeAssoccnf->messageType = eWNI_SME_ASSOC_CNF; + pSmeAssoccnf->length = sizeof(tSirSmeAssocCnf); + vos_mem_copy(pSmeAssoccnf->peerMacAddr, + ((tpLimMlmAssocInd)pMsgBuf)->peerMacAddr, 6); + pSmeAssoccnf->statusCode = eSIR_SME_SUCCESS; + pSmeAssoccnf->aid = ((tpLimMlmAssocInd)pMsgBuf)->aid; + vos_mem_copy(pSmeAssoccnf->alternateBssId, + pSmeAssoccnf->peerMacAddr, sizeof(tSirMacAddr)); + pSmeAssoccnf->alternateChannelId = 6; + vos_mem_copy(pSmeAssoccnf->bssId, psessionEntry->selfMacAddr, 6); + pMsgBuf = (tANI_U32)pSmeAssoccnf; + __limProcessSmeAssocCnfNew(pMac, eWNI_SME_ASSOC_CNF, pMsgBuf); + vos_mem_free(pSmeAssoccnf); +} +#endif + + +} /*** end limProcessMlmAssocInd() ***/ + + + + +/** + * limProcessMlmDisassocInd() + * + *FUNCTION: + * This function is called to processes MLM_DISASSOC_IND + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmDisassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmDisassocInd *pMlmDisassocInd; + tpPESession psessionEntry; + pMlmDisassocInd = (tLimMlmDisassocInd *) pMsgBuf; + if( (psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocInd->sessionId) )== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) { + case eLIM_STA_IN_IBSS_ROLE: + break; + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + psessionEntry->limSmeState = eLIM_SME_WT_DISASSOC_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + break; + + default: // eLIM_AP_ROLE //eLIM_BT_AMP_AP_ROLE + PELOG1(limLog(pMac, LOG1, + FL("*** Peer staId=%d Disassociated ***"), + pMlmDisassocInd->aid);) + break; + } // end switch (psessionEntry->limSystemRole) +} /*** end limProcessMlmDisassocInd() ***/ + +/** + * limProcessMlmDisassocCnf() + * + *FUNCTION: + * This function is called to processes MLM_DISASSOC_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirResultCodes resultCode; + tLimMlmDisassocCnf *pMlmDisassocCnf; + tpPESession psessionEntry; + pMlmDisassocCnf = (tLimMlmDisassocCnf *) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocCnf->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id"));) + return; + } + resultCode = (tSirResultCodes) + (pMlmDisassocCnf->disassocTrigger == + eLIM_LINK_MONITORING_DISASSOC) ? + eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE : + pMlmDisassocCnf->resultCode; + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + // Disassociate Confirm from MLM + if ( (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE) ) + { + /** + * Should not have received + * Disassocate confirm + * from MLM in other states. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("received unexpected MLM_DISASSOC_CNF in state %X"),psessionEntry->limSmeState);) + return; + } + if (pMac->lim.gLimRspReqd) + pMac->lim.gLimRspReqd = false; + if (pMlmDisassocCnf->disassocTrigger == + eLIM_PROMISCUOUS_MODE_DISASSOC) + { + if (pMlmDisassocCnf->resultCode != eSIR_SME_SUCCESS) + psessionEntry->limSmeState = psessionEntry->limPrevSmeState; + else + psessionEntry->limSmeState = eLIM_SME_OFFLINE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + } + else + { + if (pMlmDisassocCnf->resultCode != eSIR_SME_SUCCESS) + psessionEntry->limSmeState = psessionEntry->limPrevSmeState; + else + psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + limSendSmeDisassocNtf(pMac, pMlmDisassocCnf->peerMacAddr, + resultCode, + pMlmDisassocCnf->disassocTrigger, + pMlmDisassocCnf->aid,psessionEntry->smeSessionId,psessionEntry->transactionId,psessionEntry); + } + } else if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + limSendSmeDisassocNtf(pMac, pMlmDisassocCnf->peerMacAddr, + resultCode, + pMlmDisassocCnf->disassocTrigger, + pMlmDisassocCnf->aid,psessionEntry->smeSessionId,psessionEntry->transactionId,psessionEntry); + } +} /*** end limProcessMlmDisassocCnf() ***/ + +/** + * limProcessMlmDeauthInd() + * + *FUNCTION: + * This function is called to processes MLM_DEAUTH_IND + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmDeauthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tLimMlmDeauthInd *pMlmDeauthInd; + tpPESession psessionEntry; + tANI_U8 sessionId; + pMlmDeauthInd = (tLimMlmDeauthInd *) pMsgBuf; + if((psessionEntry = peFindSessionByBssid(pMac,pMlmDeauthInd->peerMacAddr,&sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for Addr:" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDeauthInd->peerMacAddr));) + return; + } + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) { + case eLIM_STA_IN_IBSS_ROLE: + break; + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + psessionEntry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + default: // eLIM_AP_ROLE + PELOG1(limLog(pMac, LOG1, + FL("*** Received Deauthentication from staId=%d ***"), + pMlmDeauthInd->aid);) + break; + } // end switch (psessionEntry->limSystemRole) +} /*** end limProcessMlmDeauthInd() ***/ + +/** + * limProcessMlmDeauthCnf() + * + *FUNCTION: + * This function is called to processes MLM_DEAUTH_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U16 aid; + tSirResultCodes resultCode; + tLimMlmDeauthCnf *pMlmDeauthCnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pMlmDeauthCnf = (tLimMlmDeauthCnf *) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthCnf->sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given session Id "));) + return; + } + + resultCode = (tSirResultCodes) + (pMlmDeauthCnf->deauthTrigger == + eLIM_LINK_MONITORING_DEAUTH) ? + eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE : + pMlmDeauthCnf->resultCode; + aid = LIM_IS_AP_ROLE(psessionEntry) ? pMlmDeauthCnf->aid : 1; + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + // Deauth Confirm from MLM + if ((psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) { + /* + * Should not have received Deauth confirm + * from MLM in other states. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("received unexpected MLM_DEAUTH_CNF in state %X"), + psessionEntry->limSmeState);) + return; + } + if (pMlmDeauthCnf->resultCode == eSIR_SME_SUCCESS) + { + psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; + PELOG1(limLog(pMac, LOG1, + FL("*** Deauthenticated with BSS ***"));) + } + else + psessionEntry->limSmeState = psessionEntry->limPrevSmeState; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + if (pMac->lim.gLimRspReqd) + pMac->lim.gLimRspReqd = false; + } + // On STA or on BASIC AP, send SME_DEAUTH_RSP to host + limSendSmeDeauthNtf(pMac, pMlmDeauthCnf->peerMacAddr, + resultCode, + pMlmDeauthCnf->deauthTrigger, + aid,psessionEntry->smeSessionId,psessionEntry->transactionId); +} /*** end limProcessMlmDeauthCnf() ***/ + +/** + * limProcessMlmPurgeStaInd() + * + *FUNCTION: + * This function is called to processes MLM_PURGE_STA_IND + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmPurgeStaInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirResultCodes resultCode; + tpLimMlmPurgeStaInd pMlmPurgeStaInd; + tpPESession psessionEntry; + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pMlmPurgeStaInd = (tpLimMlmPurgeStaInd) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmPurgeStaInd->sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) + return; + } + // Purge STA indication from MLM + resultCode = (tSirResultCodes) pMlmPurgeStaInd->reasonCode; + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_IN_IBSS_ROLE: + break; + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + default: // eLIM_AP_ROLE + if (LIM_IS_STA_ROLE(psessionEntry) && + (psessionEntry->limSmeState != + eLIM_SME_WT_DISASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) + { + /** + * Should not have received + * Purge STA indication + * from MLM in other states. + * Log error + */ + PELOGE(limLog(pMac, LOGE, + FL("received unexpected MLM_PURGE_STA_IND in state %X"), + psessionEntry->limSmeState);) + break; + } + PELOG1(limLog(pMac, LOG1, + FL("*** Cleanup completed for staId=%d ***"), + pMlmPurgeStaInd->aid);) + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + } + if (pMlmPurgeStaInd->purgeTrigger == eLIM_PEER_ENTITY_DEAUTH) + { + limSendSmeDeauthNtf(pMac, + pMlmPurgeStaInd->peerMacAddr, + resultCode, + pMlmPurgeStaInd->purgeTrigger, + pMlmPurgeStaInd->aid,psessionEntry->smeSessionId,psessionEntry->transactionId); + } + else + limSendSmeDisassocNtf(pMac, + pMlmPurgeStaInd->peerMacAddr, + resultCode, + pMlmPurgeStaInd->purgeTrigger, + pMlmPurgeStaInd->aid,psessionEntry->smeSessionId,psessionEntry->transactionId,psessionEntry); + } // end switch (psessionEntry->limSystemRole) +} /*** end limProcessMlmPurgeStaInd() ***/ + +/** + * limProcessMlmSetKeysCnf() + * + *FUNCTION: + * This function is called to processes MLM_SETKEYS_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmSetKeysCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + // Prepare and send SME_SETCONTEXT_RSP message + tLimMlmSetKeysCnf *pMlmSetKeysCnf; + tpPESession psessionEntry; + tANI_U16 aid; + tpDphHashNode pStaDs; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pMlmSetKeysCnf = (tLimMlmSetKeysCnf *) pMsgBuf; + if ((psessionEntry = peFindSessionBySessionId(pMac, pMlmSetKeysCnf->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId "));) + return; + } + psessionEntry->isKeyInstalled = 0; + limLog( pMac, LOG1, + FL("Received MLM_SETKEYS_CNF with resultCode = %d"), + pMlmSetKeysCnf->resultCode ); + /* if the status is success keys are installed in the + * Firmware so we can set the protection bit + */ + if (eSIR_SME_SUCCESS == pMlmSetKeysCnf->resultCode) { + psessionEntry->isKeyInstalled = 1; + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + pStaDs = dphLookupHashEntry(pMac, pMlmSetKeysCnf->peerMacAddr, &aid, + &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + pStaDs->isKeyInstalled = 1; + } + } + limSendSmeSetContextRsp(pMac, + pMlmSetKeysCnf->peerMacAddr, + 1, + (tSirResultCodes) pMlmSetKeysCnf->resultCode,psessionEntry,psessionEntry->smeSessionId, + psessionEntry->transactionId); +} /*** end limProcessMlmSetKeysCnf() ***/ +/** + * limProcessMlmRemoveKeyCnf() + * + *FUNCTION: + * This function is called to processes MLM_REMOVEKEY_CNF + * message from MLM State machine. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +void +limProcessMlmRemoveKeyCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + // Prepare and send SME_REMOVECONTEXT_RSP message + tLimMlmRemoveKeyCnf *pMlmRemoveKeyCnf; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pMlmRemoveKeyCnf = (tLimMlmRemoveKeyCnf *) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmRemoveKeyCnf->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id"));) + return; + } + limLog( pMac, LOG1, + FL("Received MLM_REMOVEKEYS_CNF with resultCode = %d"), + pMlmRemoveKeyCnf->resultCode ); + limSendSmeRemoveKeyRsp(pMac, + pMlmRemoveKeyCnf->peerMacAddr, + (tSirResultCodes) pMlmRemoveKeyCnf->resultCode,psessionEntry, + psessionEntry->smeSessionId,psessionEntry->transactionId); +} /*** end limProcessMlmRemoveKeyCnf() ***/ + + +/** + * limHandleSmeJoinResult() + * + *FUNCTION: + * This function is called to process join/auth/assoc failures + * upon receiving MLM_JOIN/AUTH/ASSOC_CNF with a failure code or + * MLM_ASSOC_CNF with a success code in case of STA role and + * MLM_JOIN_CNF with success in case of STA in IBSS role. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param resultCode Failure code to be sent + * + * + * @return None + */ +void +limHandleSmeJoinResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 protStatusCode, tpPESession psessionEntry) +{ + tpDphHashNode pStaDs = NULL; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + /* Newly Added on oct 11 th*/ + if(psessionEntry == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL "));) + return; + } + smesessionId = psessionEntry->smeSessionId; + smetransactionId = psessionEntry->transactionId; + /* When associations is failed , delete the session created and pass NULL to limsendsmeJoinReassocRsp() */ + if(resultCode != eSIR_SME_SUCCESS) + { + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + pStaDs->mlmStaContext.disassocReason = eSIR_MAC_UNSPEC_FAILURE_REASON; + pStaDs->mlmStaContext.cleanupTrigger = eLIM_JOIN_FAILURE; + pStaDs->mlmStaContext.resultCode = resultCode; + pStaDs->mlmStaContext.protStatusCode = protStatusCode; + //Done: 7-27-2009. JIM_FIX_ME: at the end of limCleanupRxPath, make sure PE is sending eWNI_SME_JOIN_RSP to SME + limCleanupRxPath(pMac, pStaDs, psessionEntry); + /* Cleanup if add bss failed */ + if(psessionEntry->add_bss_failed) { + dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, + &psessionEntry->dph.dphHashTable); + goto error; + } + vos_mem_free(psessionEntry->pLimJoinReq); + psessionEntry->pLimJoinReq = NULL; + return; + } + } +error: + vos_mem_free(psessionEntry->pLimJoinReq); + psessionEntry->pLimJoinReq = NULL; + //Delete teh session if JOIN failure occurred. + if(resultCode != eSIR_SME_SUCCESS) + { + if(NULL != psessionEntry) + { + if(limSetLinkState(pMac, eSIR_LINK_DOWN_STATE,psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the DownState."));) + if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE,psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState."));) + peDeleteSession(pMac,psessionEntry); + psessionEntry = NULL; + } + } + limSendSmeJoinReassocRsp(pMac, eWNI_SME_JOIN_RSP, resultCode, protStatusCode,psessionEntry, + smesessionId, smetransactionId); +} /*** end limHandleSmeJoinResult() ***/ + +/** + * limHandleSmeReaasocResult() + * + *FUNCTION: + * This function is called to process reassoc failures + * upon receiving REASSOC_CNF with a failure code or + * MLM_REASSOC_CNF with a success code in case of STA role + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param resultCode Failure code to be sent + * + * + * @return None + */ +static void +limHandleSmeReaasocResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 protStatusCode, tpPESession psessionEntry) +{ + tpDphHashNode pStaDs = NULL; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + if(psessionEntry == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL "));) + return; + } + smesessionId = psessionEntry->smeSessionId; + smetransactionId = psessionEntry->transactionId; + /* When associations is failed , delete the session created and pass NULL to limsendsmeJoinReassocRsp() */ + if(resultCode != eSIR_SME_SUCCESS) + { + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + pStaDs->mlmStaContext.disassocReason = eSIR_MAC_UNSPEC_FAILURE_REASON; + pStaDs->mlmStaContext.cleanupTrigger = eLIM_JOIN_FAILURE; + pStaDs->mlmStaContext.resultCode = resultCode; + pStaDs->mlmStaContext.protStatusCode = protStatusCode; + /* Cleanup if add bss failed */ + if(psessionEntry->add_bss_failed) { + dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, + &psessionEntry->dph.dphHashTable); + goto error; + } + limCleanupRxPath(pMac, pStaDs, psessionEntry); + return; + } + } +error: + //Delete teh session if REASSOC failure occurred. + if(resultCode != eSIR_SME_SUCCESS) + { + if(NULL != psessionEntry) + { + peDeleteSession(pMac,psessionEntry); + psessionEntry = NULL; + } + } + limSendSmeJoinReassocRsp(pMac, eWNI_SME_REASSOC_RSP, resultCode, protStatusCode,psessionEntry, + smesessionId, smetransactionId); +} /*** end limHandleSmeReassocResult() ***/ + +/** + * limProcessMlmAddStaRsp() + * + *FUNCTION: + * This function is called to process a WDA_ADD_STA_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Determines the "state" in which this message was received + * > Forwards it to the appropriate callback + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +void limProcessMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry ) +{ + //we need to process the deferred message since the initiating req. there might be nested request. + //in the case of nested request the new request initiated from the response will take care of resetting + //the deffered flag. + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry)) { + limProcessBtAmpApMlmAddStaRsp(pMac, limMsgQ,psessionEntry); + return; + } + limProcessStaMlmAddStaRsp(pMac, limMsgQ,psessionEntry); +} +void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry) +{ + tLimMlmAssocCnf mlmAssocCnf; + tpDphHashNode pStaDs; + tANI_U32 mesgType = LIM_MLM_ASSOC_CNF; + tpAddStaParams pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr; + tpPESession pftSessionEntry = NULL; + tANI_U8 ftSessionId; + + if(NULL == pAddStaParams ) + { + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); + return; + } + + if (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + { + mesgType = LIM_MLM_REASSOC_CNF; + } + + if (true == psessionEntry->fDeauthReceived) + { + PELOGE(limLog(pMac, LOGE, + FL("Received Deauth frame in ADD_STA_RESP state"));) + if (eHAL_STATUS_SUCCESS == pAddStaParams->status) + { + PELOGE(limLog(pMac, LOGE, + FL("ADD_STA success, send update result code with" + "eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA staIdx: %d" + "limMlmState: %d"), pAddStaParams->staIdx, + psessionEntry->limMlmState);) + if(psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + mesgType = LIM_MLM_REASSOC_CNF; + /* + * We are sending result code eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA + * which will trigger proper cleanup (DEL_STA/DEL_BSS both required) in + * either assoc cnf or reassoc cnf handler. + */ + mlmAssocCnf.resultCode = + (tSirResultCodes) eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA; + psessionEntry->staId = pAddStaParams->staIdx; + goto end; + } + } + + if ( eHAL_STATUS_SUCCESS == pAddStaParams->status ) + { + if ( eLIM_MLM_WT_ADD_STA_RSP_STATE != psessionEntry->limMlmState) + { + //TODO: any response to be sent out here ? + limLog( pMac, LOGE, + FL( "Received unexpected WDA_ADD_STA_RSP in state %X" ), + psessionEntry->limMlmState); + mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; + goto end; + } + if (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + { +#ifdef WLAN_FEATURE_VOWIFI_11R + // Check if we have keys (PTK) to install in case of 11r + tpftPEContext pftPECntxt = &psessionEntry->ftPEContext; + pftSessionEntry = peFindSessionByBssid(pMac, + psessionEntry->limReAssocbssId, + &ftSessionId); + if (pftSessionEntry != NULL && + pftPECntxt->PreAuthKeyInfo.extSetStaKeyParamValid == TRUE) + { + tpLimMlmSetKeysReq pMlmStaKeys = &pftPECntxt->PreAuthKeyInfo.extSetStaKeyParam; + limSendSetStaKeyReq(pMac, pMlmStaKeys, 0, 0, pftSessionEntry, FALSE); + pftPECntxt->PreAuthKeyInfo.extSetStaKeyParamValid = FALSE; + } +#endif + } + // + // Update the DPH Hash Entry for this STA + // with proper state info + // + pStaDs = dphGetHashEntry( pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs) { + pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + pStaDs->nss = pAddStaParams->nss; + } + else + limLog( pMac, LOGW, + FL( "Unable to get the DPH Hash Entry for AID - %d" ), + DPH_STA_HASH_INDEX_PEER); + + psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + /* + * 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. + */ + psessionEntry->staId = pAddStaParams->staIdx; + //if the AssocRsp frame is not acknowledged, then keep alive timer will take care of the state +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) +#endif + { + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_KEEPALIVE_TIMER)); + + //assign the sessionId to the timer Object + pMac->lim.limTimers.gLimKeepaliveTimer.sessionId = psessionEntry->peSessionId; + if (tx_timer_activate(&pMac->lim.limTimers.gLimKeepaliveTimer) != TX_SUCCESS) + limLog(pMac, LOGP, FL("Cannot activate keepalive timer.")); +#ifdef WLAN_DEBUG + pMac->lim.gLimNumLinkEsts++; +#endif +#ifdef FEATURE_WLAN_TDLS + /* initialize TDLS peer related data */ + limInitTdlsData(pMac,psessionEntry); +#endif + // Return Assoc confirm to SME with success + // FIXME_GEN4 - Need the correct ASSOC RSP code to + // be passed in here.... + //mlmAssocCnf.resultCode = (tSirResultCodes) assoc.statusCode; + mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_SUCCESS; + } + else + { + limLog( pMac, LOGE, FL( "ADD_STA failed!")); + if (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + mlmAssocCnf.resultCode = (tSirResultCodes)eSIR_SME_FT_REASSOC_FAILURE; + else + mlmAssocCnf.resultCode = (tSirResultCodes)eSIR_SME_REFUSED; + } +end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddStaParams); + limMsgQ->bodyptr = NULL; + } + /* Updating PE session Id*/ + mlmAssocCnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage( pMac, mesgType, (tANI_U32 *) &mlmAssocCnf ); + if (true == psessionEntry->fDeauthReceived) + { + psessionEntry->fDeauthReceived = false; + } + return; +} +void limProcessMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + //we need to process the deferred message since the initiating req. there might be nested request. + //in the case of nested request the new request initiated from the response will take care of resetting + //the deffered flag. + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pMac->sys.gSysFrameCount[SIR_MAC_MGMT_FRAME][SIR_MAC_MGMT_DEAUTH] = 0; + + if ((LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry)) && + (psessionEntry->statypeForBss == STA_ENTRY_SELF)) { + limProcessBtAmpApMlmDelBssRsp(pMac, limMsgQ,psessionEntry); + return; + } + limProcessStaMlmDelBssRsp(pMac, limMsgQ,psessionEntry); + + if(!limIsInMCC(pMac)) + { + WDA_TrafficStatsTimerActivate(FALSE); + } + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled) + { + if ( eSIR_SUCCESS != limSendExcludeUnencryptInd(pMac, TRUE, psessionEntry) ) + { + limLog( pMac, LOGE, + FL( "Could not send down Exclude Unencrypted Indication!" ) ); + } + } +#endif +} + +void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + tpDeleteBssParams pDelBssParams = (tpDeleteBssParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + tSirResultCodes statusCode = eSIR_SME_SUCCESS; + + if (NULL == pDelBssParams) + { + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); + goto end; + } + if( eHAL_STATUS_SUCCESS == pDelBssParams->status ) + { + PELOGW(limLog( pMac, LOGW, + FL( "STA received the DEL_BSS_RSP for BSSID: %X."),pDelBssParams->bssIdx);) + if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + + { + PELOGE(limLog( pMac, LOGE, FL( "Failure in setting link state to IDLE"));) + statusCode = eSIR_SME_REFUSED; + goto end; + } + if(pStaDs == NULL) + { + limLog( pMac, LOGE, FL( "DPH Entry for STA 1 missing.")); + statusCode = eSIR_SME_REFUSED; + goto end; + } + if( eLIM_MLM_WT_DEL_BSS_RSP_STATE != pStaDs->mlmStaContext.mlmState) + { + PELOGE(limLog( pMac, LOGE, FL( "Received unexpected WDA_DEL_BSS_RSP in state %X" ), + pStaDs->mlmStaContext.mlmState);) + statusCode = eSIR_SME_REFUSED; + goto end; + } + PELOG1(limLog( pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId ); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) + } + else + { + limLog( pMac, LOGE, FL( "DEL BSS failed!" ) ); + statusCode = eSIR_SME_STOP_BSS_FAILURE; + } + end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pDelBssParams); + limMsgQ->bodyptr = NULL; + } + if(pStaDs == NULL) + return; + if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE && + psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE) && + pStaDs->mlmStaContext.cleanupTrigger != eLIM_JOIN_FAILURE) { + /** The Case where the DelBss is invoked from + * context of other than normal DisAssoc / Deauth OR + * as part of Join Failure. + */ + limHandleDelBssInReAssocContext(pMac, pStaDs,psessionEntry); + return; + } + limPrepareAndSendDelStaCnf(pMac, pStaDs, statusCode,psessionEntry); + return; +} + +void limProcessBtAmpApMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + tSirResultCodes rc = eSIR_SME_SUCCESS; + tSirRetStatus status; + tpDeleteBssParams pDelBss = (tpDeleteBssParams) limMsgQ->bodyptr; + tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + if(psessionEntry == NULL) + { + limLog(pMac, LOGE,FL("Session entry passed is NULL")); + if(pDelBss != NULL) + { + vos_mem_free(pDelBss); + limMsgQ->bodyptr = NULL; + } + return; + } + + if (pDelBss == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!"));) + rc = eSIR_SME_REFUSED; + goto end; + } + pMac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState)); + + if( eLIM_MLM_WT_DEL_BSS_RSP_STATE != psessionEntry->limMlmState) + { + limLog( pMac, LOGE, + FL( "Received unexpected WDA_DEL_BSS_RSP in state %X" ), + psessionEntry->limMlmState); + rc = eSIR_SME_REFUSED; + goto end; + } + if (pDelBss->status != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGE, FL("BSS: DEL_BSS_RSP error (%x) Bss %d "), + pDelBss->status, pDelBss->bssIdx); + rc = eSIR_SME_STOP_BSS_FAILURE; + goto end; + } + status = limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid, + psessionEntry->selfMacAddr, NULL, NULL); + if (status != eSIR_SUCCESS) + { + rc = eSIR_SME_REFUSED; + goto end; + } + /** Softmac may send all the buffered packets right after resuming the transmission hence + * to occupy the medium during non channel occupancy period. So resume the transmission after + * HAL gives back the response. + */ + dphHashTableClassInit(pMac, &psessionEntry->dph.dphHashTable); + limDeletePreAuthList(pMac); + //Initialize number of associated stations during cleanup + psessionEntry->gLimNumOfCurrentSTAs = 0; + end: + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, rc, psessionEntry->smeSessionId, psessionEntry->transactionId); + peDeleteSession(pMac, psessionEntry); + + if(pDelBss != NULL) + { + vos_mem_free(pDelBss); + limMsgQ->bodyptr = NULL; + } +} + +void limProcessMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) +{ + //we need to process the deferred message since the initiating req. there might be nested request. + //in the case of nested request the new request initiated from the response will take care of resetting + //the deffered flag. + + tpPESession psessionEntry; + tpDeleteStaParams pDeleteStaParams; + pDeleteStaParams = (tpDeleteStaParams)limMsgQ->bodyptr; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(NULL == pDeleteStaParams || + NULL == (psessionEntry = peFindSessionBySessionId(pMac, pDeleteStaParams->sessionId))) + { + limLog(pMac, LOGP,FL("Session Does not exist or invalid body pointer in message")); + if(pDeleteStaParams != NULL) + { + vos_mem_free(pDeleteStaParams); + limMsgQ->bodyptr = NULL; + } + return; + } + + if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry)) { + limProcessBtAmpApMlmDelStaRsp(pMac,limMsgQ,psessionEntry); + return; + } + limProcessStaMlmDelStaRsp(pMac, limMsgQ,psessionEntry); +} + +void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs; + tSirResultCodes statusCode = eSIR_SME_SUCCESS; + if(limMsgQ->bodyptr == NULL) + { + limLog( pMac, LOGE, + FL( "limMsgQ->bodyptry NULL")); + return; + } + pStaDs = dphGetHashEntry(pMac, pDelStaParams->assocId, &psessionEntry->dph.dphHashTable); + if(pStaDs == NULL) + { + limLog( pMac, LOGE, + FL( "DPH Entry for STA %X missing."), pDelStaParams->assocId); + statusCode = eSIR_SME_REFUSED; + vos_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + + return; + } + limLog( pMac, LOG1, + FL( "Received del Sta Rsp in StaD MlmState : %d"), + pStaDs->mlmStaContext.mlmState); + if( eHAL_STATUS_SUCCESS == pDelStaParams->status ) + { + limLog( pMac, LOGW, + FL( "AP received the DEL_STA_RSP for assocID: %X."), pDelStaParams->assocId); + + if(( eLIM_MLM_WT_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState) && + ( eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState)) + { + limLog( pMac, LOGE, + FL( "Received unexpected WDA_DEL_STA_RSP in state %s for staId %d assocId %d " ), + limMlmStateStr(pStaDs->mlmStaContext.mlmState), pStaDs->staIndex, pStaDs->assocId); + statusCode = eSIR_SME_REFUSED; + goto end; + } + + limLog( pMac, LOG1, + FL("Deleted STA AssocID %d staId %d MAC "), + pStaDs->assocId, pStaDs->staIndex); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1); + if(eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE == pStaDs->mlmStaContext.mlmState) + { + vos_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, + FL("could not Add STA with assocId=%d"), + pStaDs->assocId);) + // delete the TS if it has already been added. + // send the response with error status. + if(pStaDs->qos.addtsPresent) + { + tpLimTspecInfo pTspecInfo; + if(eSIR_SUCCESS == limTspecFindByAssocId(pMac, pStaDs->assocId, + &pStaDs->qos.addts.tspec, &pMac->lim.tspecInfo[0], &pTspecInfo)) + { + limAdmitControlDeleteTS(pMac, pStaDs->assocId, &pStaDs->qos.addts.tspec.tsinfo, + NULL, &pTspecInfo->idx); + } + } + limRejectAssociation(pMac, + pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + } + return; + } + } + else + { + limLog( pMac, LOGW, + FL( "DEL STA failed!" )); + statusCode = eSIR_SME_REFUSED; + } + end: + vos_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + if(eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState) + { + limPrepareAndSendDelStaCnf(pMac, pStaDs, statusCode,psessionEntry); + } + return; +} + +void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + tSirResultCodes statusCode = eSIR_SME_SUCCESS; + tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs = NULL; + if(NULL == pDelStaParams ) + { + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); + goto end; + } + + limLog(pMac, LOG1, FL("Del STA RSP received. Status:%d AssocID:%d"), + pDelStaParams->status, pDelStaParams->assocId); + + if (eHAL_STATUS_SUCCESS != pDelStaParams->status) + { + limLog(pMac, LOGE, FL("Del STA failed! Status:%d, still proceeding" + "with Del BSS"), pDelStaParams->status); + } + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) + { + limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing."), + pDelStaParams->assocId); + statusCode = eSIR_SME_REFUSED; + goto end; + } + + if (eLIM_MLM_WT_DEL_STA_RSP_STATE != psessionEntry->limMlmState) + { + limLog( pMac, LOGE, FL( + "Received unexpected WDA_DELETE_STA_RSP in state %s"), + limMlmStateStr(psessionEntry->limMlmState)); + statusCode = eSIR_SME_REFUSED; + goto end; + } + + limLog( pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId ); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1); + + //we must complete all cleanup related to delSta before calling limDelBSS. + if (0 != limMsgQ->bodyptr ) + { + vos_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + } + + // Proceed to do DelBSS even if DelSta resulted in failure + statusCode = (tSirResultCodes) limDelBss(pMac, pStaDs, 0,psessionEntry); + return; + +end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + } + return; +} + +void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + tpAddStaParams pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs = NULL; + + if (NULL == pAddStaParams) + { + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); + goto end; + } + + pStaDs = dphGetHashEntry(pMac, pAddStaParams->assocId, &psessionEntry->dph.dphHashTable); + if(pStaDs == NULL) + { + //TODO: any response to be sent out here ? + limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing."), pAddStaParams->assocId); + goto end; + } + // + // TODO & FIXME_GEN4 + // Need to inspect tSirMsgQ.reserved for a valid Dialog token! + // + //TODO: any check for pMac->lim.gLimMlmState ? + if( eLIM_MLM_WT_ADD_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState) + { + //TODO: any response to be sent out here ? + limLog( pMac, LOGE, + FL( "Received unexpected WDA_ADD_STA_RSP in state %X" ), + pStaDs->mlmStaContext.mlmState); + goto end; + } + if(eHAL_STATUS_SUCCESS != pAddStaParams->status) + { + PELOGE(limLog(pMac, LOGE, FL("Error! rcvd delSta rsp from HAL with status %d"),pAddStaParams->status);) + limRejectAssociation(pMac, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true, + (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + goto end; + } + pStaDs->bssId = pAddStaParams->bssIdx; + pStaDs->staIndex = pAddStaParams->staIdx; + pStaDs->nss = pAddStaParams->nss; + //if the AssocRsp frame is not acknowledged, then keep alive timer will take care of the state + pStaDs->valid = 1; + pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ASSOC_CNF_STATE; + limLog( pMac, LOG1, + FL("AddStaRsp Success.STA AssocID %d staId %d MAC "), + pStaDs->assocId, + pStaDs->staIndex); + limPrintMacAddr(pMac, pStaDs->staAddr, LOG1); + + /* For BTAMP-AP, the flow sequence shall be: + * 1) PE sends eWNI_SME_ASSOC_IND to SME + * 2) PE receives eWNI_SME_ASSOC_CNF from SME + * 3) BTAMP-AP sends Re/Association Response to BTAMP-STA + */ + limSendMlmAssocInd(pMac, pStaDs, psessionEntry); + // fall though to reclaim the original Add STA Response message +end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddStaParams); + limMsgQ->bodyptr = NULL; + } + return; +} + +/** + * limProcessApMlmAddBssRsp() + * + *FUNCTION: + * This function is called to process a WDA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Validates the result of WDA_ADD_BSS_REQ + * > Init other remaining LIM variables + * > Init the AID pool, for that BSSID + * > Init the Pre-AUTH list, for that BSSID + * > Create LIM timers, specific to that BSSID + * > Init DPH related parameters that are specific to that BSSID + * > TODO - When do we do the actual change channel? + * + *LOGIC: + * SME sends eWNI_SME_START_BSS_REQ to LIM + * LIM sends LIM_MLM_START_REQ to MLME + * MLME sends WDA_ADD_BSS_REQ to HAL + * HAL responds with WDA_ADD_BSS_RSP to MLME + * MLME responds with LIM_MLM_START_CNF to LIM + * LIM responds with eWNI_SME_START_BSS_RSP to SME + * + *ASSUMPTIONS: + * tSirMsgQ.body is allocated by MLME during limProcessMlmStartReq + * tSirMsgQ.body will now be freed by this routine + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +static void +limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) +{ + tLimMlmStartCnf mlmStartCnf; + tANI_U32 val; + tpPESession psessionEntry; + tANI_U8 isWepEnabled = FALSE; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + if(NULL == pAddBssParams ) + { + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); + goto end; + } + //TBD: free the memory before returning, do it for all places where lookup fails. + if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) + if( NULL != pAddBssParams ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } + return; + } + /* Update PE session Id*/ + mlmStartCnf.sessionId = pAddBssParams->sessionId; + if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) + { + PELOG2(limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS"));) + if (limSetLinkState(pMac, eSIR_LINK_AP_STATE,psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) + goto end; + // Set MLME state + psessionEntry->limMlmState = eLIM_MLM_BSS_STARTED_STATE; + psessionEntry->chainMask = pAddBssParams->chainMask; + psessionEntry->smpsMode = pAddBssParams->smpsMode; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + if( eSIR_IBSS_MODE == pAddBssParams->bssType ) + { + /** IBSS is 'active' when we receive + * Beacon frames from other STAs that are part of same IBSS. + * Mark internal state as inactive until then. + */ + psessionEntry->limIbssActive = false; + psessionEntry->statypeForBss = STA_ENTRY_PEER; //to know session created for self/peer + limResetHBPktCount( psessionEntry ); + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); + if (limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); + } + psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; + + psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; + + if ( eSIR_INFRA_AP_MODE == pAddBssParams->bssType ) + psessionEntry->limSystemRole = eLIM_AP_ROLE; + else + psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; + schEdcaProfileUpdate(pMac, psessionEntry); + limInitPreAuthList(pMac); + /* Check the SAP security configuration.If configured to + * WEP then max clients supported is 16 + */ + if (psessionEntry->privacy) + { + if ((psessionEntry->gStartBssRSNIe.present) || (psessionEntry->gStartBssWPAIe.present)) + limLog(pMac, LOG1, FL("WPA/WPA2 SAP configuration")); + else + { + if (pMac->lim.gLimAssocStaLimit > MAX_SUPPORTED_PEERS_WEP) + { + limLog(pMac, LOG1, FL("WEP SAP Configuration")); + pMac->lim.gLimAssocStaLimit = MAX_SUPPORTED_PEERS_WEP; + isWepEnabled = TRUE; + } + } + } + limInitPeerIdxpool(pMac,psessionEntry); + + // Start OLBC timer + if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("tx_timer_activate failed")); + } + + /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); + pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; + // Apply previously set configuration at HW + limApplyConfiguration(pMac,psessionEntry); + + /* In limApplyConfiguration gLimAssocStaLimit is assigned from cfg. + * So update the value to 16 in case SoftAP is configured in WEP. + */ + if ((pMac->lim.gLimAssocStaLimit > MAX_SUPPORTED_PEERS_WEP) && (isWepEnabled)) + pMac->lim.gLimAssocStaLimit = MAX_SUPPORTED_PEERS_WEP; + psessionEntry->staId = pAddBssParams->staContext.staIdx; + mlmStartCnf.resultCode = eSIR_SME_SUCCESS; + } + else + { + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ),pAddBssParams->status ); + mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + limPostSmeMessage( pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf ); + end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + + +/** + * limProcessIbssMlmAddBssRsp() + * + *FUNCTION: + * This function is called to process a WDA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Validates the result of WDA_ADD_BSS_REQ + * > Init other remaining LIM variables + * > Init the AID pool, for that BSSID + * > Init the Pre-AUTH list, for that BSSID + * > Create LIM timers, specific to that BSSID + * > Init DPH related parameters that are specific to that BSSID + * > TODO - When do we do the actual change channel? + * + *LOGIC: + * SME sends eWNI_SME_START_BSS_REQ to LIM + * LIM sends LIM_MLM_START_REQ to MLME + * MLME sends WDA_ADD_BSS_REQ to HAL + * HAL responds with WDA_ADD_BSS_RSP to MLME + * MLME responds with LIM_MLM_START_CNF to LIM + * LIM responds with eWNI_SME_START_BSS_RSP to SME + * + *ASSUMPTIONS: + * tSirMsgQ.body is allocated by MLME during limProcessMlmStartReq + * tSirMsgQ.body will now be freed by this routine + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +static void +limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry) +{ + tLimMlmStartCnf mlmStartCnf; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + tANI_U32 val; + + if (NULL == pAddBssParams) + { + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); + goto end; + } + if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) + { + PELOG1(limLog(pMac, LOG1, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS"));) + if (limSetLinkState(pMac, eSIR_LINK_IBSS_STATE,psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) + goto end; + // Set MLME state + psessionEntry->limMlmState = eLIM_MLM_BSS_STARTED_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + /** IBSS is 'active' when we receive + * Beacon frames from other STAs that are part of same IBSS. + * Mark internal state as inactive until then. + */ + psessionEntry->limIbssActive = false; + limResetHBPktCount( psessionEntry ); + /* Timer related functions are not modified for BT-AMP : To be Done */ + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); + if (limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); + psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; + psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; + psessionEntry->statypeForBss = STA_ENTRY_SELF; + schEdcaProfileUpdate(pMac, psessionEntry); + if (0 == psessionEntry->freePeerIdxHead) + limInitPeerIdxpool(pMac,psessionEntry); + + /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); + pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; + // Apply previously set configuration at HW + limApplyConfiguration(pMac,psessionEntry); + psessionEntry->staId = pAddBssParams->staContext.staIdx; + mlmStartCnf.resultCode = eSIR_SME_SUCCESS; + //If ADD BSS was issued as part of IBSS coalescing, don't send the message to SME, as that is internal to LIM + if(true == pMac->lim.gLimIbssCoalescingHappened) + { + limIbssAddBssRspWhenCoalescing(pMac, limMsgQ->bodyptr, psessionEntry); + goto end; + } + } + else + { + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ), + pAddBssParams->status ); + mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + //Send this message to SME, when ADD_BSS is initiated by SME + //If ADD_BSS is done as part of coalescing, this won't happen. + /* Update PE session Id*/ + mlmStartCnf.sessionId =psessionEntry->peSessionId; + limPostSmeMessage( pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf ); + end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + +static void +limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPESession psessionEntry ) +{ + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + tAniAuthType cfgAuthType, authMode; + tLimMlmAuthReq *pMlmAuthReq; + tpDphHashNode pStaDs = NULL; + + if (NULL == pAddBssParams) + { + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); + goto joinFailure; + } + if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) + { + if ((pStaDs = dphAddHashEntry(pMac, pAddBssParams->staContext.staMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) + { + // Could not add hash table entry + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) + limPrintMacAddr(pMac, pAddBssParams->staContext.staMac, LOGE); + goto joinFailure; + } + psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; + //Success, handle below + pStaDs->bssId = pAddBssParams->bssIdx; + //STA Index(genr by HAL) for the BSS entry is stored here + pStaDs->staIndex = pAddBssParams->staContext.staIdx; + // Trigger Authentication with AP + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATION_TYPE, + (tANI_U32 *) &cfgAuthType) != eSIR_SUCCESS) + { + /** + * Could not get AuthType from CFG. + * Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AuthType")); + } + if (cfgAuthType == eSIR_AUTO_SWITCH) + authMode = eSIR_OPEN_SYSTEM; // Try Open Authentication first + else + authMode = cfgAuthType; + + // Trigger MAC based Authentication + pMlmAuthReq = vos_mem_malloc(sizeof(tLimMlmAuthReq)); + if ( NULL == pMlmAuthReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmAuthReq")); + return; + } + sirCopyMacAddr(pMlmAuthReq->peerMacAddr,psessionEntry->bssId); + + pMlmAuthReq->authType = authMode; + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + (tANI_U32 *) &pMlmAuthReq->authFailureTimeout) + != eSIR_SUCCESS) + { + /** + * Could not get AuthFailureTimeout + * value from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AuthFailureTimeout value")); + } + psessionEntry->limMlmState = eLIM_MLM_JOINED_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_JOINED_STATE)); + pMlmAuthReq->sessionId = psessionEntry->peSessionId; + psessionEntry->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry->limSmeState = eLIM_SME_WT_AUTH_STATE; + // remember staId in case of assoc timeout/failure handling + psessionEntry->staId = pAddBssParams->staContext.staIdx; + + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, psessionEntry->limSmeState)); + limLog(pMac,LOG1,"SessionId:%d limPostMlmMessage LIM_MLM_AUTH_REQ with limSmeState:%d", + psessionEntry->peSessionId, + psessionEntry->limSmeState); + limPostMlmMessage(pMac, + LIM_MLM_AUTH_REQ, + (tANI_U32 *) pMlmAuthReq); + return; + } + +joinFailure: + { + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + /// Send Join response to Host + limHandleSmeJoinResult(pMac, eSIR_SME_REFUSED, eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + + } + +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/*------------------------------------------------------------------------------------------ + * + * Function to handle WDA_ADD_BSS_RSP, in FT reassoc state. + * Function to Send ReAssociation Request. + * + * + *------------------------------------------------------------------------------------------ + */ +static inline void +limProcessStaMlmAddBssRspFT(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; // keep sme + tpDphHashNode pStaDs = NULL; + tpAddStaParams pAddStaParams = NULL; + tANI_U32 listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + tANI_U32 selfStaDot11Mode = 0; + + /* Sanity Checks */ + + if (pAddBssParams == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Invalid parameters"));) + goto end; + } + if ( eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE != psessionEntry->limMlmState ) + { + goto end; + } + + if ((pStaDs = dphAddHashEntry(pMac, pAddBssParams->bssId, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable)) == NULL) + { + // Could not add hash table entry + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) + limPrintMacAddr(pMac, pAddBssParams->staContext.staMac, LOGE); + goto end; + } + // Prepare and send Reassociation request frame + // start reassoc timer. +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress != VOS_TRUE) + { +#endif + pMac->lim.limTimers.gLimReassocFailureTimer.sessionId = psessionEntry->peSessionId; + /// Start reassociation failure timer + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_REASSOC_FAIL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimReassocFailureTimer) + != TX_SUCCESS) + { + /// Could not start reassoc failure timer. + // Log error + limLog(pMac, LOGP, + FL("could not start Reassociation failure timer")); + // Return Reassoc confirm with + // Resources Unavailable + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + goto end; + } +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pMac->lim.pSessionEntry = psessionEntry; + if(NULL == pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) + { + /* Take a copy of reassoc request for retrying */ + pMac->lim.pSessionEntry->pLimMlmReassocRetryReq = vos_mem_malloc(sizeof(tLimMlmReassocReq)); + if ( NULL == pMac->lim.pSessionEntry->pLimMlmReassocRetryReq ) goto end; + vos_mem_set(pMac->lim.pSessionEntry->pLimMlmReassocRetryReq, sizeof(tLimMlmReassocReq), 0); + vos_mem_copy(pMac->lim.pSessionEntry->pLimMlmReassocRetryReq, + psessionEntry->pLimMlmReassocReq, + sizeof(tLimMlmReassocReq)); + } + pMac->lim.reAssocRetryAttempt = 0; +#endif + limSendReassocReqWithFTIEsMgmtFrame(pMac, psessionEntry->pLimMlmReassocReq, psessionEntry); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } else + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:Do not activate timer and dont send the reassoc req"); + } +#endif + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + psessionEntry->limMlmState = eLIM_MLM_WT_FT_REASSOC_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, eLIM_MLM_WT_FT_REASSOC_RSP_STATE)); + PELOGE(limLog(pMac, LOG1, FL("Set the mlm state to %d session=%d"), + psessionEntry->limMlmState, psessionEntry->peSessionId);) + + psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; + + //Success, handle below + pStaDs->bssId = pAddBssParams->bssIdx; + //STA Index(genr by HAL) for the BSS entry is stored here + pStaDs->staIndex = pAddBssParams->staContext.staIdx; + pStaDs->ucUcastSig = pAddBssParams->staContext.ucUcastSig; + pStaDs->ucBcastSig = pAddBssParams->staContext.ucBcastSig; + +#if defined WLAN_FEATURE_VOWIFI + rrmCacheMgmtTxPower( pMac, pAddBssParams->txMgmtPower, psessionEntry ); +#endif + + pAddStaParams = vos_mem_malloc(sizeof( tAddStaParams )); + if ( NULL == pAddStaParams ) + { + limLog( pMac, LOGP, FL( "Unable to allocate memory during ADD_STA" )); + goto end; + } + vos_mem_set((tANI_U8 *) pAddStaParams, sizeof(tAddStaParams), 0); + + /// Add STA context at MAC HW (BMU, RHP & TFP) + vos_mem_copy((tANI_U8 *) pAddStaParams->staMac, + (tANI_U8 *) psessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + + vos_mem_copy((tANI_U8 *) pAddStaParams->bssId, + psessionEntry->bssId, sizeof(tSirMacAddr)); + + pAddStaParams->staType = STA_ENTRY_SELF; + pAddStaParams->status = eHAL_STATUS_SUCCESS; + pAddStaParams->respReqd = 1; + + /* Update PE session ID */ + pAddStaParams->sessionId = psessionEntry->peSessionId; + pAddStaParams->smesessionId = psessionEntry->smeSessionId; + + // This will indicate HAL to "allocate" a new STA index +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress != VOS_TRUE) +#endif + pAddStaParams->staIdx = HAL_STA_INVALID_IDX; + pAddStaParams->updateSta = FALSE; + + pAddStaParams->shortPreambleSupported = (tANI_U8)psessionEntry->beaconParams.fShortPreamble; +#ifdef WLAN_FEATURE_11AC + limPopulatePeerRateSet(pMac, &pAddStaParams->supportedRates, NULL, false,psessionEntry, NULL); +#else + limPopulatePeerRateSet(pMac, &pAddStaParams->supportedRates, NULL, false,psessionEntry); +#endif + + if( psessionEntry->htCapability) + { + pAddStaParams->htCapable = psessionEntry->htCapability; +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = psessionEntry->vhtCapability; + pAddStaParams->vhtTxChannelWidthSet = psessionEntry->vhtTxChannelWidthSet; +#endif + + pAddStaParams->greenFieldCapable = limGetHTCapability( pMac, eHT_GREENFIELD, psessionEntry); + if (psessionEntry->limRFBand == SIR_BAND_2_4_GHZ) + { + pAddStaParams->txChannelWidthSet = + pMac->roam.configParam.channelBondingMode24GHz; + } + else + { + pAddStaParams->txChannelWidthSet = + pMac->roam.configParam.channelBondingMode5GHz; + } + pAddStaParams->mimoPS = limGetHTCapability( pMac, eHT_MIMO_POWER_SAVE, psessionEntry ); + pAddStaParams->rifsMode = limGetHTCapability( pMac, eHT_RIFS_MODE, psessionEntry ); + pAddStaParams->lsigTxopProtection = limGetHTCapability( pMac, eHT_LSIG_TXOP_PROTECTION, psessionEntry ); + pAddStaParams->delBASupport = limGetHTCapability( pMac, eHT_DELAYED_BA, psessionEntry ); + pAddStaParams->maxAmpduDensity = limGetHTCapability( pMac, eHT_MPDU_DENSITY, psessionEntry ); + pAddStaParams->maxAmpduSize = limGetHTCapability(pMac, eHT_MAX_RX_AMPDU_FACTOR, psessionEntry); + pAddStaParams->maxAmsduSize = limGetHTCapability( pMac, eHT_MAX_AMSDU_LENGTH, psessionEntry ); + pAddStaParams->max_amsdu_num = limGetHTCapability(pMac, + eHT_MAX_AMSDU_NUM, + psessionEntry); + pAddStaParams->fDsssCckMode40Mhz = limGetHTCapability( pMac, eHT_DSSS_CCK_MODE_40MHZ, psessionEntry); + pAddStaParams->fShortGI20Mhz = limGetHTCapability( pMac, eHT_SHORT_GI_20MHZ, psessionEntry); + pAddStaParams->fShortGI40Mhz = limGetHTCapability( pMac, eHT_SHORT_GI_40MHZ, psessionEntry); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); + pAddStaParams->listenInterval = (tANI_U16)listenInterval; + + wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); + pAddStaParams->supportedRates.opRateMode = limGetStaRateMode((tANI_U8)selfStaDot11Mode); + pAddStaParams->encryptType = psessionEntry->encryptType; + pAddStaParams->maxTxPower = psessionEntry->maxTxPower; + + // Lets save this for when we receive the Reassoc Rsp + psessionEntry->ftPEContext.pAddStaReq = pAddStaParams; + + if (pAddBssParams != NULL) + { + vos_mem_free(pAddBssParams); + pAddBssParams = NULL; + limMsgQ->bodyptr = NULL; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:Prepare and save pAddStaReq in pMac for post-assoc-rsp"); + limProcessAssocRspFrame(pMac, pMac->roam.pReassocResp, LIM_REASSOC, + psessionEntry); + } +#endif + return; + +end: + // Free up buffer allocated for reassocReq + if (psessionEntry != NULL) + if (psessionEntry->pLimMlmReassocReq != NULL) + { + vos_mem_free(psessionEntry->pLimMlmReassocReq); + psessionEntry->pLimMlmReassocReq = NULL; + } + + if (pAddBssParams != NULL) + { + vos_mem_free(pAddBssParams); + pAddBssParams = NULL; + limMsgQ->bodyptr = NULL; + } + + mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE session Id*/ + if (psessionEntry != NULL) + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + else + mlmReassocCnf.sessionId = 0; + + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ +/** + * limProcessStaMlmAddBssRsp() + * + *FUNCTION: + * This function is called to process a WDA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Validates the result of WDA_ADD_BSS_REQ + * > Now, send an ADD_STA to HAL and ADD the "local" STA itself + * + *LOGIC: + * MLME had sent WDA_ADD_BSS_REQ to HAL + * HAL responded with WDA_ADD_BSS_RSP to MLME + * MLME now sends WDA_ADD_STA_REQ to HAL + * + *ASSUMPTIONS: + * tSirMsgQ.body is allocated by MLME during limProcessMlmJoinReq + * tSirMsgQ.body will now be freed by this routine + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +static void +limProcessStaMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) +{ + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + tLimMlmAssocCnf mlmAssocCnf; + tANI_U32 mesgType = LIM_MLM_ASSOC_CNF; + tANI_U32 subType = LIM_ASSOC; + tpDphHashNode pStaDs = NULL; + tANI_U16 staIdx = HAL_STA_INVALID_IDX; + tANI_U8 updateSta = false; + mlmAssocCnf.resultCode = eSIR_SME_SUCCESS; + + if(eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE == psessionEntry->limMlmState) + { + limLog(pMac,LOG1,"SessionId:%d limProcessStaMlmAddBssRspPreAssoc", + psessionEntry->peSessionId); + limProcessStaMlmAddBssRspPreAssoc(pMac, limMsgQ, psessionEntry); + goto end; + } + if (eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE == psessionEntry->limMlmState +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + || (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == psessionEntry->limMlmState) +#endif + ) + { + mesgType = LIM_MLM_REASSOC_CNF; + subType = LIM_REASSOC; + //If Reassoc is happening for the same BSS, then use the existing StaId and indicate to HAL + //to update the existing STA entry. + //If Reassoc is happening for the new BSS, then old BSS and STA entry would have been already deleted + //before PE tries to add BSS for the new BSS, so set the updateSta to false and pass INVALID STA Index. + if (sirCompareMacAddr( psessionEntry->bssId, psessionEntry->limReAssocbssId)) + { + staIdx = psessionEntry->staId; + updateSta = true; + } + } + + if(pAddBssParams == 0) + goto end; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "LFR3:limProcessStaMlmAddBssRsp"); +#endif + + if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) + { +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if( eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == psessionEntry->limMlmState ) + { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOG1, FL("Mlm=%d %d"), + psessionEntry->limMlmState, + eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE);) +#endif + limProcessStaMlmAddBssRspFT( pMac, limMsgQ, psessionEntry); + goto end; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + // Set MLME state + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + psessionEntry->statypeForBss = STA_ENTRY_PEER; //to know the session started for self or for peer oct6th + // Now, send WDA_ADD_STA_REQ + limLog( pMac, LOGW, FL( "SessionId:%d On STA: ADD_BSS was successful"), + psessionEntry->peSessionId); + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("SessionId:%d could not Add Self Entry for the station"), + psessionEntry->peSessionId);) + mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; + } + else + { + psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; + //Success, handle below + pStaDs->bssId = pAddBssParams->bssIdx; + //STA Index(genr by HAL) for the BSS entry is stored here + pStaDs->staIndex = pAddBssParams->staContext.staIdx; + pStaDs->ucUcastSig = pAddBssParams->staContext.ucUcastSig; + pStaDs->ucBcastSig = pAddBssParams->staContext.ucBcastSig; + // Downgrade the EDCA parameters if needed + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); +#if defined WLAN_FEATURE_VOWIFI + rrmCacheMgmtTxPower( pMac, pAddBssParams->txMgmtPower, psessionEntry ); +#endif + + if (subType == LIM_REASSOC) + limDeactivateAndChangeTimer(pMac, eLIM_KEEPALIVE_TIMER); + if (limAddStaSelf(pMac,staIdx, updateSta, psessionEntry) != eSIR_SUCCESS) + { + // Add STA context at HW + PELOGE(limLog(pMac, LOGE, FL("SessionId:%d could not Add Self Entry for the station"), + psessionEntry->peSessionId);) + mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; + } + } + } else { + limLog(pMac, LOGP, FL("SessionId:%d ADD_BSS failed!"), + psessionEntry->peSessionId); + /* Return Assoc confirm to SME with failure */ + // Return Assoc confirm to SME with failure + if(eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == psessionEntry->limMlmState) + mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_FT_REASSOC_FAILURE; + else + mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; + psessionEntry->add_bss_failed = true; + } + + if(mlmAssocCnf.resultCode != eSIR_SME_SUCCESS) + { + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + //Set the RXP mode to IDLE, so it starts filtering the frames. + if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE,psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + limLog(pMac, LOGE, FL("Failed to set the LinkState")); + /* Update PE session Id*/ + mlmAssocCnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage( pMac, mesgType, (tANI_U32 *) &mlmAssocCnf ); + } + end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + + + +/** + * limProcessMlmAddBssRsp() + * + *FUNCTION: + * This function is called to process a WDA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Determines the "state" in which this message was received + * > Forwards it to the appropriate callback + * + *LOGIC: + * WDA_ADD_BSS_RSP can be received by MLME while the LIM is + * in the following two states: + * 1) As AP, LIM state = eLIM_SME_WT_START_BSS_STATE + * 2) As STA, LIM state = eLIM_SME_WT_JOIN_STATE + * Based on these two states, this API will determine where to + * route the message to + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) +{ + tLimMlmStartCnf mlmStartCnf; + tpPESession psessionEntry; + tpAddBssParams pAddBssParams = (tpAddBssParams) (limMsgQ->bodyptr); + + if(NULL == pAddBssParams ) + { + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); + return; + } + // + // TODO & FIXME_GEN4 + // Need to inspect tSirMsgQ.reserved for a valid Dialog token! + // + //we need to process the deferred message since the initiating req. there might be nested request. + //in the case of nested request the new request initiated from the response will take care of resetting + //the deffered flag. + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + // Validate SME/LIM state + // Validate MLME state + if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) + { + limLog( pMac, LOGE, FL( "SessionId:%d Session Does not exist" ), + pAddBssParams->sessionId); + if( NULL != pAddBssParams ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } + return; + } + /* update PE session Id*/ + mlmStartCnf.sessionId = psessionEntry->peSessionId; + if( eSIR_IBSS_MODE == psessionEntry->bssType ) + limProcessIbssMlmAddBssRsp( pMac, limMsgQ, psessionEntry ); + else + { + if( eLIM_SME_WT_START_BSS_STATE == psessionEntry->limSmeState ) + { + if( eLIM_MLM_WT_ADD_BSS_RSP_STATE != psessionEntry->limMlmState ) + { + // Mesg received from HAL in Invalid state! + limLog( pMac, LOGE,FL( "SessionId:%d Received unexpected WDA_ADD_BSS_RSP in state %X" ), + psessionEntry->peSessionId,psessionEntry->limMlmState); + mlmStartCnf.resultCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } + limPostSmeMessage( pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf ); + } + else if ((psessionEntry->bssType == eSIR_BTAMP_AP_MODE)||(psessionEntry->bssType == eSIR_BTAMP_STA_MODE)) + { + limProcessBtampAddBssRsp(pMac,limMsgQ,psessionEntry); + } + else + limProcessApMlmAddBssRsp( pMac,limMsgQ); + } + else + /* Called while processing assoc response */ + limProcessStaMlmAddBssRsp( pMac, limMsgQ,psessionEntry); + } + + if(limIsInMCC(pMac)) + { + WDA_TrafficStatsTimerActivate(TRUE); + } + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled) + { + if ( eSIR_SUCCESS != limSendExcludeUnencryptInd(pMac, FALSE, psessionEntry) ) + { + limLog( pMac, LOGE, + FL( "Could not send down Exclude Unencrypted Indication!" ) ); + } + } +#endif +} +/** + * limProcessMlmSetKeyRsp() + * + *FUNCTION: + * This function is called to process the following two + * messages from HAL: + * 1) WDA_SET_BSSKEY_RSP + * 2) WDA_SET_STAKEY_RSP + * 3) WDA_SET_STA_BCASTKEY_RSP + * Upon receipt of this message from HAL, + * MLME - + * > Determines the "state" in which this message was received + * > Forwards it to the appropriate callback + * + *LOGIC: + * WDA_SET_BSSKEY_RSP/WDA_SET_STAKEY_RSP can be + * received by MLME while in the following state: + * MLME state = eLIM_MLM_WT_SET_BSS_KEY_STATE --OR-- + * MLME state = eLIM_MLM_WT_SET_STA_KEY_STATE --OR-- + * MLME state = eLIM_MLM_WT_SET_STA_BCASTKEY_STATE + * Based on this state, this API will determine where to + * route the message to + * + *ASSUMPTIONS: + * ONLY the MLME state is being taken into account for now. + * This is because, it appears that the handling of the + * SETKEYS REQ is handled symmetrically on both the AP & STA + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +void limProcessMlmSetStaKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) +{ + tANI_U8 respReqd = 1; + tLimMlmSetKeysCnf mlmSetKeysCnf; + tANI_U8 sessionId = 0; + tpPESession psessionEntry; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_set((void *)&mlmSetKeysCnf, sizeof( tLimMlmSetKeysCnf ), 0); + //BTAMP + if( NULL == limMsgQ->bodyptr ) + { + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL"));) + return; + } + sessionId = ((tpSetStaKeyParams) limMsgQ->bodyptr)->sessionId; + if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return; + } + if( eLIM_MLM_WT_SET_STA_KEY_STATE != psessionEntry->limMlmState ) + { + // Mesg received from HAL in Invalid state! + limLog( pMac, LOGE, FL( "Received unexpected [Mesg Id - %d] in state %X" ), limMsgQ->type, psessionEntry->limMlmState ); + // There's not much that MLME can do at this stage... + respReqd = 0; + } + else + mlmSetKeysCnf.resultCode = (tANI_U16) (((tpSetStaKeyParams) limMsgQ->bodyptr)->status); + + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + // Restore MLME state + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + if( respReqd ) + { + tpLimMlmSetKeysReq lpLimMlmSetKeysReq = (tpLimMlmSetKeysReq) pMac->lim.gpLimMlmSetKeysReq; + // Prepare and Send LIM_MLM_SETKEYS_CNF + if( NULL != lpLimMlmSetKeysReq ) + { + vos_mem_copy((tANI_U8 *) &mlmSetKeysCnf.peerMacAddr, + (tANI_U8 *) lpLimMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + // Free the buffer cached for the global pMac->lim.gpLimMlmSetKeysReq + vos_mem_free(pMac->lim.gpLimMlmSetKeysReq); + pMac->lim.gpLimMlmSetKeysReq = NULL; + } + mlmSetKeysCnf.sessionId = sessionId; + limPostSmeMessage(pMac, LIM_MLM_SETKEYS_CNF, (tANI_U32 *) &mlmSetKeysCnf); + } +} +void limProcessMlmSetBssKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) +{ + tLimMlmSetKeysCnf mlmSetKeysCnf; + tANI_U16 resultCode; + tANI_U8 sessionId = 0; + tpPESession psessionEntry; + tpLimMlmSetKeysReq lpLimMlmSetKeysReq; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_set((void *)&mlmSetKeysCnf, sizeof( tLimMlmSetKeysCnf ), 0); + if (NULL == limMsgQ->bodyptr) { + PELOGE(limLog(pMac, LOGE, FL("limMsgQ bodyptr is null"));) + return; + } + sessionId = ((tpSetBssKeyParams) limMsgQ->bodyptr)->sessionId; + if ((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for given sessionId [%d]"), + sessionId);) + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return; + } + if (eLIM_MLM_WT_SET_BSS_KEY_STATE == psessionEntry->limMlmState) + resultCode = (tANI_U16) (((tpSetBssKeyParams)limMsgQ->bodyptr)->status); + else + /*BCAST key also uses tpSetStaKeyParams. Done this way for readabilty */ + resultCode = (tANI_U16) (((tpSetStaKeyParams)limMsgQ->bodyptr)->status); + + if (eLIM_MLM_WT_SET_BSS_KEY_STATE != psessionEntry->limMlmState && + eLIM_MLM_WT_SET_STA_BCASTKEY_STATE != psessionEntry->limMlmState) { + /* Mesg received from lower layer is in Invalid state */ + limLog(pMac, LOGE, + FL("Received unexpected [Mesg Id - %d] in state %X"), + limMsgQ->type, psessionEntry->limMlmState ); + mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_STATE; + } + else + mlmSetKeysCnf.resultCode = resultCode; + + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + /* Restore MLME state */ + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, psessionEntry->limMlmState)); + lpLimMlmSetKeysReq = (tpLimMlmSetKeysReq) pMac->lim.gpLimMlmSetKeysReq; + mlmSetKeysCnf.sessionId = sessionId; + + /* Prepare and Send LIM_MLM_SETKEYS_CNF */ + if (NULL != lpLimMlmSetKeysReq) { + vos_mem_copy((tANI_U8 *) &mlmSetKeysCnf.peerMacAddr, + (tANI_U8 *) lpLimMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + /* Free the buffer cached for the global pMac->lim.gpLimMlmSetKeysReq */ + vos_mem_free(pMac->lim.gpLimMlmSetKeysReq); + pMac->lim.gpLimMlmSetKeysReq = NULL; + } + limPostSmeMessage(pMac, LIM_MLM_SETKEYS_CNF, (tANI_U32 *) &mlmSetKeysCnf); +} +/** + * limProcessMlmRemoveKeyRsp() + * + *FUNCTION: + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param tSirMsgQ The MsgQ header, which contains the response buffer + * + * @return None + */ +void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) +{ + tANI_U8 respReqd = 1; + tLimMlmRemoveKeyCnf mlmRemoveCnf; + tANI_U16 resultCode; + tANI_U8 sessionId = 0; + tpPESession psessionEntry; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_set((void *) &mlmRemoveCnf, sizeof( tLimMlmRemoveKeyCnf ), 0); + + if( NULL == limMsgQ->bodyptr ) + { + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL"));) + return; + } + + if (limMsgQ->type == WDA_REMOVE_STAKEY_RSP) + sessionId = ((tpRemoveStaKeyParams) limMsgQ->bodyptr)->sessionId; + else if (limMsgQ->type == WDA_REMOVE_BSSKEY_RSP) + sessionId = ((tpRemoveBssKeyParams) limMsgQ->bodyptr)->sessionId; + + if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) + return; + } + + if( eLIM_MLM_WT_REMOVE_BSS_KEY_STATE == psessionEntry->limMlmState ) + resultCode = (tANI_U16) (((tpRemoveBssKeyParams) limMsgQ->bodyptr)->status); + else + resultCode = (tANI_U16) (((tpRemoveStaKeyParams) limMsgQ->bodyptr)->status); + + // Validate MLME state + if( eLIM_MLM_WT_REMOVE_BSS_KEY_STATE != psessionEntry->limMlmState && + eLIM_MLM_WT_REMOVE_STA_KEY_STATE != psessionEntry->limMlmState ) + { + // Mesg received from HAL in Invalid state! + limLog(pMac, LOGW, + FL("Received unexpected [Mesg Id - %d] in state %X"), + limMsgQ->type, + psessionEntry->limMlmState ); + respReqd = 0; + } + else + mlmRemoveCnf.resultCode = resultCode; + + // + // TODO & FIXME_GEN4 + // Need to inspect tSirMsgQ.reserved for a valid Dialog token! + // + + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + + // Restore MLME state + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + if( respReqd ) + { + tpLimMlmRemoveKeyReq lpLimMlmRemoveKeyReq = (tpLimMlmRemoveKeyReq) pMac->lim.gpLimMlmRemoveKeyReq; + mlmRemoveCnf.sessionId = sessionId; + + // Prepare and Send LIM_MLM_REMOVEKEY_CNF + if( NULL != lpLimMlmRemoveKeyReq ) + { + vos_mem_copy((tANI_U8 *) &mlmRemoveCnf.peerMacAddr, + (tANI_U8 *) lpLimMlmRemoveKeyReq->peerMacAddr, + sizeof( tSirMacAddr )); + // Free the buffer cached for the global pMac->lim.gpLimMlmRemoveKeyReq + vos_mem_free(pMac->lim.gpLimMlmRemoveKeyReq); + pMac->lim.gpLimMlmRemoveKeyReq = NULL; + } + limPostSmeMessage( pMac, LIM_MLM_REMOVEKEY_CNF, (tANI_U32 *) &mlmRemoveCnf ); + } +} + + +/** --------------------------------------------------------------------- +\fn limProcessInitScanRsp +\brief This function is called when LIM receives WDA_INIT_SCAN_RSP +\ message from HAL. If status code is failure, then +\ update the gLimNumOfConsecutiveBkgndScanFailure count. +\param tpAniSirGlobal pMac +\param tANI_U32 body +\return none +\ ----------------------------------------------------------------------- */ +void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) +{ + tpInitScanParams pInitScanParam; + eHalStatus status; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pInitScanParam = (tpInitScanParams) body; + status = pInitScanParam->status; + vos_mem_free(body); + + //Only abort scan if the we are scanning. + if( pMac->lim.abortScan && + (eLIM_HAL_INIT_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState) ) + { + limLog( pMac, LOGW, FL(" abort scan") ); + pMac->lim.abortScan = 0; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + if (status != eHAL_STATUS_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("InitScnRsp failed status=%d"),status);) + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + pMac->lim.gLimNumOfConsecutiveBkgndScanFailure += 1; + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); + return; + } + else + { + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + } + + } + switch(pMac->lim.gLimHalScanState) + { + case eLIM_HAL_INIT_SCAN_WAIT_STATE: + if (status != (tANI_U32) eHAL_STATUS_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("InitScanRsp with failed status= %d"), status);) + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + pMac->lim.gLimNumOfConsecutiveBkgndScanFailure += 1; + /* + * On Windows eSIR_SME_HAL_SCAN_INIT_FAILED message to CSR may trigger + * another Scan request in the same context (happens when 11d is enabled + * and first scan request with 11d channels fails for whatever reason, then CSR issues next init + * scan in the same context but with bigger channel list), so the state needs to be + * changed before this response message is sent. + */ + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); + return; + } + else if (status == eHAL_STATUS_SUCCESS) + { + /* since we have successfully triggered a background scan, + * reset the "consecutive bkgnd scan failure" count to 0 + */ + pMac->lim.gLimNumOfConsecutiveBkgndScanFailure = 0; + pMac->lim.gLimNumOfBackgroundScanSuccess += 1; + pMac->lim.probeCounter = 0; + } + limContinueChannelScan(pMac); + break; +//WLAN_SUSPEND_LINK Related + case eLIM_HAL_SUSPEND_LINK_WAIT_STATE: + if( pMac->lim.gpLimSuspendCallback ) + { + if( eHAL_STATUS_SUCCESS == status ) + { + pMac->lim.gLimHalScanState = eLIM_HAL_SUSPEND_LINK_STATE; + } + else + { + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + pMac->lim.gLimSystemInScanLearnMode = 0; + } + + pMac->lim.gpLimSuspendCallback( pMac, status, pMac->lim.gpLimSuspendData ); + pMac->lim.gpLimSuspendCallback = NULL; + pMac->lim.gpLimSuspendData = NULL; + } + else + { + limLog( pMac, LOGP, "No suspend link callback set but station is in suspend state"); + return; + } + break; +//end WLAN_SUSPEND_LINK Related + default: + limLog(pMac, LOGW, FL("limProcessInitScanRsp: Rcvd InitScanRsp not in WAIT State, state %d"), + pMac->lim.gLimHalScanState); + break; + } + return; +} +/** + * limProcessSwitchChannelReAssocReq() + * + *FUNCTION: + * This function is called to send the reassoc req mgmt frame after the + * switchChannelRsp message is received from HAL. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure. + * @param psessionEntry - session related information. + * @param status - channel switch success/failure. + * + * @return None + */ +static void limProcessSwitchChannelReAssocReq(tpAniSirGlobal pMac, tpPESession psessionEntry, eHalStatus status) +{ + tLimMlmReassocCnf mlmReassocCnf; + tLimMlmReassocReq *pMlmReassocReq; + pMlmReassocReq = (tLimMlmReassocReq *)(psessionEntry->pLimMlmReassocReq); + if(pMlmReassocReq == NULL) + { + limLog(pMac, LOGP, FL("pLimMlmReassocReq does not exist for given switchChanSession")); + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + + if(status != eHAL_STATUS_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!"));) + mlmReassocCnf.resultCode = eSIR_SME_CHANNEL_SWITCH_FAIL; + goto end; + } + /// Start reassociation failure timer + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_REASSOC_FAIL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimReassocFailureTimer) + != TX_SUCCESS) + { + /// Could not start reassoc failure timer. + // Log error + limLog(pMac, LOGP, + FL("could not start Reassociation failure timer")); + // Return Reassoc confirm with + // Resources Unavailable + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + /// Prepare and send Reassociation request frame + limSendReassocReqMgmtFrame(pMac, pMlmReassocReq, psessionEntry); + return; +end: + // Free up buffer allocated for reassocReq + if(pMlmReassocReq != NULL) + { + /* Update PE session Id*/ + mlmReassocCnf.sessionId = pMlmReassocReq->sessionId; + vos_mem_free(pMlmReassocReq); + psessionEntry->pLimMlmReassocReq = NULL; + } + else + { + mlmReassocCnf.sessionId = 0; + } + + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE sessio Id*/ + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); +} +/** + * limProcessSwitchChannelJoinReq() + * + *FUNCTION: + * This function is called to send the probe req mgmt frame after the + * switchChannelRsp message is received from HAL. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure. + * @param psessionEntry - session related information. + * @param status - channel switch success/failure. + * + * @return None + */ +static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession psessionEntry, eHalStatus status) +{ + tANI_U32 val; + tSirMacSSid ssId; + tLimMlmJoinCnf mlmJoinCnf; + if(status != eHAL_STATUS_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!"));) + goto error; + } + + if ( (NULL == psessionEntry ) || (NULL == psessionEntry->pLimMlmJoinReq) || + (NULL == psessionEntry->pLimJoinReq) ) + { + PELOGE(limLog(pMac, LOGE, FL("invalid pointer!!"));) + goto error; + } + + + /* eSIR_BTAMP_AP_MODE stroed as bss type in session Table when join req is received, is to be veified */ + if(psessionEntry->bssType == eSIR_BTAMP_AP_MODE) + { + if (limSetLinkState(pMac, eSIR_LINK_BTAMP_PREASSOC_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) + { + PELOGE(limLog(pMac, LOGE, FL("Sessionid: %d Set link state " + "failed!! BSSID:"MAC_ADDRESS_STR),psessionEntry->peSessionId, + MAC_ADDR_ARRAY(psessionEntry->bssId));) + goto error; + } + } + + psessionEntry->limPrevMlmState = psessionEntry->limMlmState; + psessionEntry->limMlmState = eLIM_MLM_WT_JOIN_BEACON_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, psessionEntry->limMlmState)); + + limLog(pMac, LOG1, + FL("Sessionid %d prev lim state %d new lim state %d systemrole %d"), + psessionEntry->peSessionId, + psessionEntry->limPrevMlmState, + psessionEntry->limMlmState, GET_LIM_SYSTEM_ROLE(psessionEntry)); + + /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ + if(wlan_cfgGetInt(pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("failed to get WNI_CFG_TRIG_STA_BK_SCAN cfg value!")); + pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; + /* Apply previously set configuration at HW */ + limApplyConfiguration(pMac, psessionEntry); + + /* + * If sendDeauthBeforeCon is enabled, Send Deauth first to AP if last + * disconnection was caused by HB failure. + */ + if(pMac->roam.configParam.sendDeauthBeforeCon) + { + int apCount; + + for(apCount = 0; apCount < 2; apCount++) + { + + if (vos_mem_compare(psessionEntry->pLimMlmJoinReq->bssDescription.bssId, + pMac->lim.gLimHeartBeatApMac[apCount], sizeof(tSirMacAddr))) + { + limLog(pMac, LOGE, FL("Index %d Sessionid: %d Send deauth on " + "channel %d to BSSID: "MAC_ADDRESS_STR ), apCount, + psessionEntry->peSessionId, psessionEntry->currentOperChannel, + MAC_ADDR_ARRAY(psessionEntry->pLimMlmJoinReq->bssDescription. + bssId)); + + limSendDeauthMgmtFrame( pMac, eSIR_MAC_UNSPEC_FAILURE_REASON, + psessionEntry->pLimMlmJoinReq->bssDescription.bssId, + psessionEntry, FALSE ); + + vos_mem_zero(pMac->lim.gLimHeartBeatApMac[apCount], + sizeof(tSirMacAddr)); + break; + } + } + } + + /// Wait for Beacon to announce join success + vos_mem_copy(ssId.ssId, + psessionEntry->ssId.ssId, + psessionEntry->ssId.length); + ssId.length = psessionEntry->ssId.length; + + limDeactivateAndChangeTimer(pMac, eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + + /* assign appropriate sessionId to the timer object */ + pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId = psessionEntry->peSessionId; + limLog(pMac, LOG1, FL("Sessionid: %d Send Probe req on channel %d ssid:%.*s" + "BSSID: "MAC_ADDRESS_STR), psessionEntry->peSessionId, + psessionEntry->currentOperChannel, ssId.length, ssId.ssId, + MAC_ADDR_ARRAY(psessionEntry->pLimMlmJoinReq->bssDescription.bssId)); + + /* + * We need to wait for probe response, so start join timeout timer. + * This timer will be deactivated once we receive probe response. + */ + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_JOIN_FAIL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimJoinFailureTimer) != + TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not activate Join failure timer")); + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, + pMac->lim.gLimMlmState)); + goto error; + } + + // include additional IE if there is + limSendProbeReqMgmtFrame( pMac, &ssId, + psessionEntry->pLimMlmJoinReq->bssDescription.bssId, psessionEntry->currentOperChannel/*chanNum*/, + psessionEntry->selfMacAddr, psessionEntry->dot11mode, + psessionEntry->pLimJoinReq->addIEScan.length, psessionEntry->pLimJoinReq->addIEScan.addIEdata); + + if( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) + { + // Activate Join Periodic Probe Req timer + if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer")); + goto error; + } + } + + return; +error: + if(NULL != psessionEntry) + { + if (psessionEntry->pLimMlmJoinReq) + { + vos_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + if (psessionEntry->pLimJoinReq) + { + vos_mem_free(psessionEntry->pLimJoinReq); + psessionEntry->pLimJoinReq = NULL; + } + mlmJoinCnf.sessionId = psessionEntry->peSessionId; + } + else + { + mlmJoinCnf.sessionId = 0; + } + mlmJoinCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmJoinCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + limPostSmeMessage(pMac, LIM_MLM_JOIN_CNF, (tANI_U32 *) &mlmJoinCnf); +} + +/** + * limProcessSwitchChannelRsp() + * + *FUNCTION: + * This function is called to process switchChannelRsp message from HAL. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param body - message body. + * + * @return None + */ +void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) +{ + tpSwitchChannelParams pChnlParams = NULL; + eHalStatus status; + tANI_U16 channelChangeReasonCode; + tANI_U8 peSessionId; + tpPESession psessionEntry; + //we need to process the deferred message since the initiating req. there might be nested request. + //in the case of nested request the new request initiated from the response will take care of resetting + //the deffered flag. + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pChnlParams = (tpSwitchChannelParams) body; + status = pChnlParams->status; + peSessionId = pChnlParams->peSessionId; + + if((psessionEntry = peFindSessionBySessionId(pMac, peSessionId))== NULL) + { + limLog(pMac, LOGP, FL("session does not exist for given sessionId")); + return; + } +#if defined WLAN_FEATURE_VOWIFI + //HAL fills in the tx power used for mgmt frames in this field. + //Store this value to use in TPC report IE. + rrmCacheMgmtTxPower( pMac, pChnlParams->txMgmtPower, psessionEntry ); +#endif + channelChangeReasonCode = psessionEntry->channelChangeReasonCode; + // initialize it back to invalid id + psessionEntry->chainMask = pChnlParams->chainMask; + psessionEntry->smpsMode = pChnlParams->smpsMode; + psessionEntry->channelChangeReasonCode = 0xBAD; + limLog(pMac, LOG1, FL("channelChangeReasonCode %d"),channelChangeReasonCode); + switch(channelChangeReasonCode) + { + case LIM_SWITCH_CHANNEL_REASSOC: + limProcessSwitchChannelReAssocReq(pMac, psessionEntry, status); + break; + case LIM_SWITCH_CHANNEL_JOIN: + limProcessSwitchChannelJoinReq(pMac, psessionEntry, status); + break; + + case LIM_SWITCH_CHANNEL_OPERATION: + /* + * The above code should also use the callback. + * mechanism below, there is scope for cleanup here. + * THat way all this response handler does is call the call back + * We can get rid of the reason code here. + */ + if (pMac->lim.gpchangeChannelCallback) + { + PELOG1(limLog( pMac, LOG1, "Channel changed hence invoke registered call back");) + pMac->lim.gpchangeChannelCallback(pMac, status, pMac->lim.gpchangeChannelData, psessionEntry); + } + break; + case LIM_SWITCH_CHANNEL_SAP_DFS: + { + /* Note: This event code specific to SAP mode + * When SAP session issues channel change as performing + * DFS, we will come here. Other sessions, for e.g. P2P + * will have to define their own event code and channel + * switch handler. This is required since the SME may + * require completely different information for P2P unlike + * SAP. + */ + limSendSmeAPChannelSwitchResp(pMac, psessionEntry, pChnlParams); + } + break; + default: + break; + } + vos_mem_free(body); +} +/** + * limProcessStartScanRsp() + * + *FUNCTION: + * This function is called to process startScanRsp message from HAL. If scan/learn was successful + * then it will start scan/learn on the next channel. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param body - message body. + * + * @return None + */ + +void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) +{ + tpStartScanParams pStartScanParam; + eHalStatus status; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pStartScanParam = (tpStartScanParams) body; + status = pStartScanParam->status; +#if defined WLAN_FEATURE_VOWIFI + //HAL fills in the tx power used for mgmt frames in this field. + //Store this value to use in TPC report IE. + rrmCacheMgmtTxPower( pMac, pStartScanParam->txMgmtPower, NULL ); + //Store start TSF of scan start. This will be stored in BSS params. + rrmUpdateStartTSF( pMac, pStartScanParam->startTSF ); +#endif + vos_mem_free(body); + body = NULL; + if( pMac->lim.abortScan ) + { + limLog( pMac, LOGW, FL(" finish scan") ); + pMac->lim.abortScan = 0; + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + } + switch(pMac->lim.gLimHalScanState) + { + case eLIM_HAL_START_SCAN_WAIT_STATE: + if (status != (tANI_U32) eHAL_STATUS_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("StartScanRsp with failed status= %d"), status);) + // + // FIXME - With this, LIM will try and recover state, but + // eWNI_SME_SCAN_CNF maybe reporting an incorrect + // status back to the SME + // + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq( pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE ); + } + else + { + pMac->lim.gLimHalScanState = eLIM_HAL_SCANNING_STATE; + limContinuePostChannelScan(pMac); + } + break; + default: + limLog(pMac, LOGW, FL("Rcvd StartScanRsp not in WAIT State, state %d"), + pMac->lim.gLimHalScanState); + break; + } + return; +} +void limProcessEndScanRsp(tpAniSirGlobal pMac, void *body) +{ + tpEndScanParams pEndScanParam; + eHalStatus status; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pEndScanParam = (tpEndScanParams) body; + status = pEndScanParam->status; + vos_mem_free(body); + body = NULL; + switch(pMac->lim.gLimHalScanState) + { + case eLIM_HAL_END_SCAN_WAIT_STATE: + if (status != (tANI_U32) eHAL_STATUS_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d"), status);) + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); + } + else + { + pMac->lim.gLimCurrentScanChannelId++; + limContinueChannelScan(pMac); + } + break; + default: + limLog(pMac, LOGW, FL("Rcvd endScanRsp not in WAIT State, state %d"), + pMac->lim.gLimHalScanState); + break; + } + return; +} +/** + * limStopTxAndSwitch() + * + *FUNCTION: + * Start channel switch on all sessions that is in channel switch state. + * + * @param pMac - pointer to global adapter context + * + * @return None + * + */ +static void +limStopTxAndSwitch (tpAniSirGlobal pMac) +{ + tANI_U8 i; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid && + pMac->lim.gpSession[i].gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) + { + limStopTxAndSwitchChannel(pMac, i); + } + } + return; +} +/** + * limStartQuietOnSession() + * + *FUNCTION: + * This function is called to start quiet timer after finish scan if there is + * qeuieting on any session. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * + * @return None + */ +static void +limStartQuietOnSession (tpAniSirGlobal pMac) +{ + tANI_U8 i; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid && + pMac->lim.gpSession[i].gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) + { + limStartQuietTimer(pMac, i); + } + } + return; +} +void limProcessFinishScanRsp(tpAniSirGlobal pMac, void *body) +{ + tpFinishScanParams pFinishScanParam; + eHalStatus status; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pFinishScanParam = (tpFinishScanParams) body; + status = pFinishScanParam->status; + vos_mem_free(body); + body = NULL; + + limLog(pMac, LOGW, FL("Rcvd FinishScanRsp in state %d"), + pMac->lim.gLimHalScanState); + + switch(pMac->lim.gLimHalScanState) + { + case eLIM_HAL_FINISH_SCAN_WAIT_STATE: + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + limCompleteMlmScan(pMac, eSIR_SME_SUCCESS); + if (limIsChanSwitchRunning(pMac)) + { + /** Right time to stop tx and start the timer for channel switch */ + /* Sending Session ID 0, may not be correct, since SCAN is global there should not + * be any associated session id + */ + limStopTxAndSwitch(pMac); + } + else if (limIsQuietBegin(pMac)) + { + /** Start the quieting */ + /* Sending Session ID 0, may not be correct, since SCAN is global there should not + * be any associated session id + */ + limStartQuietOnSession(pMac); + } + if (status != (tANI_U32) eHAL_STATUS_SUCCESS) + { + PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d"), status);) + } + break; +//WLAN_SUSPEND_LINK Related + case eLIM_HAL_RESUME_LINK_WAIT_STATE: + if( pMac->lim.gpLimResumeCallback ) + { + pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; + pMac->lim.gpLimResumeCallback( pMac, status, pMac->lim.gpLimResumeData ); + pMac->lim.gpLimResumeCallback = NULL; + pMac->lim.gpLimResumeData = NULL; + pMac->lim.gLimSystemInScanLearnMode = 0; + } + else + { + limLog( pMac, LOGP, "No Resume link callback set but station is in suspend state"); + return; + } + break; +//end WLAN_SUSPEND_LINK Related + + default: + limLog(pMac, LOGE, FL("Rcvd FinishScanRsp not in WAIT State, state %d"), + pMac->lim.gLimHalScanState); + break; + } + return; +} +/** + * @function : limProcessMlmHalAddBARsp + * + * @brief: Process WDA_ADDBA_RSP coming from HAL + * + * + * @param pMac The global tpAniSirGlobal object + * + * @param tSirMsgQ The MsgQ header containing the response buffer + * + * @return none + */ +void limProcessMlmHalAddBARsp( tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ ) +{ + // Send LIM_MLM_ADDBA_CNF to LIM + tpLimMlmAddBACnf pMlmAddBACnf; + tpPESession psessionEntry = NULL; + tpAddBAParams pAddBAParams = (tpAddBAParams) limMsgQ->bodyptr; + + //now LIM can process any defer message. + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + if (pAddBAParams == NULL) { + PELOGE(limLog(pMac, LOGE,FL("NULL ADD BA Response from HAL"));) + return; + } + if((psessionEntry = peFindSessionBySessionId(pMac, pAddBAParams->sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionID: %d"),pAddBAParams->sessionId );) + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_HAL_ADDBA_RSP_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + // Allocate for LIM_MLM_ADDBA_CNF + pMlmAddBACnf = vos_mem_malloc(sizeof(tLimMlmAddBACnf)); + if ( NULL == pMlmAddBACnf ) { + limLog( pMac, LOGP, FL(" AllocateMemory failed for pMlmAddBACnf")); + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return; + } + vos_mem_set((void *) pMlmAddBACnf, sizeof( tLimMlmAddBACnf ), 0); + // Copy the peer MAC + vos_mem_copy(pMlmAddBACnf->peerMacAddr, pAddBAParams->peerMacAddr, + sizeof( tSirMacAddr )); + // Copy other ADDBA Rsp parameters + pMlmAddBACnf->baDialogToken = pAddBAParams->baDialogToken; + pMlmAddBACnf->baTID = pAddBAParams->baTID; + pMlmAddBACnf->baPolicy = pAddBAParams->baPolicy; + pMlmAddBACnf->baBufferSize = pAddBAParams->baBufferSize; + pMlmAddBACnf->baTimeout = pAddBAParams->baTimeout; + pMlmAddBACnf->baDirection = pAddBAParams->baDirection; + pMlmAddBACnf->sessionId = psessionEntry->peSessionId; + if(eHAL_STATUS_SUCCESS == pAddBAParams->status) + pMlmAddBACnf->addBAResultCode = eSIR_MAC_SUCCESS_STATUS; + else + pMlmAddBACnf->addBAResultCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + // Send ADDBA CNF to LIM + limPostSmeMessage( pMac, LIM_MLM_ADDBA_CNF, (tANI_U32 *) pMlmAddBACnf ); +} +/** + * \brief Process LIM_MLM_ADDBA_CNF + * + * \sa limProcessMlmAddBACnf + * + * \param pMac The global tpAniSirGlobal object + * + * \param tSirMsgQ The MsgQ header containing the response buffer + * + * \return none + */ +void limProcessMlmAddBACnf( tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf ) +{ +tpLimMlmAddBACnf pMlmAddBACnf; +tpDphHashNode pSta; +tANI_U16 aid; +tLimBAState curBaState; +tpPESession psessionEntry = NULL; +if(pMsgBuf == NULL) +{ + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; +} +pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBACnf->sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) + vos_mem_free(pMsgBuf); + return; + } + // First, extract the DPH entry + pSta = dphLookupHashEntry( pMac, pMlmAddBACnf->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); + if( NULL == pSta ) + { + PELOGE(limLog( pMac, LOGE, + FL( "STA context not found - ignoring ADDBA CNF from HAL" ));) + vos_mem_free(pMsgBuf); + return; + } + LIM_GET_STA_BA_STATE(pSta, pMlmAddBACnf->baTID, &curBaState); + // Need to validate SME state + if( eLIM_BA_STATE_WT_ADD_RSP != curBaState) + { + PELOGE(limLog( pMac, LOGE, + FL( "Received unexpected ADDBA CNF when STA BA state is %d" ), + curBaState );) + vos_mem_free(pMsgBuf); + return; + } + // Restore STA BA state + LIM_SET_STA_BA_STATE(pSta, pMlmAddBACnf->baTID, eLIM_BA_STATE_IDLE); + if( eSIR_MAC_SUCCESS_STATUS == pMlmAddBACnf->addBAResultCode ) + { + // Update LIM internal cache... + if( eBA_RECIPIENT == pMlmAddBACnf->baDirection ) + { + pSta->tcCfg[pMlmAddBACnf->baTID].fUseBARx = 1; + pSta->tcCfg[pMlmAddBACnf->baTID].fRxCompBA = 1; + pSta->tcCfg[pMlmAddBACnf->baTID].fRxBApolicy = pMlmAddBACnf->baPolicy; + pSta->tcCfg[pMlmAddBACnf->baTID].rxBufSize = pMlmAddBACnf->baBufferSize; + pSta->tcCfg[pMlmAddBACnf->baTID].tuRxBAWaitTimeout = pMlmAddBACnf->baTimeout; + // Package LIM_MLM_ADDBA_RSP to MLME, with proper + // status code. MLME will then send an ADDBA RSP + // over the air to the peer MAC entity + if( eSIR_SUCCESS != limPostMlmAddBARsp( pMac, + pMlmAddBACnf->peerMacAddr, + pMlmAddBACnf->addBAResultCode, + pMlmAddBACnf->baDialogToken, + (tANI_U8) pMlmAddBACnf->baTID, + (tANI_U8) pMlmAddBACnf->baPolicy, + pMlmAddBACnf->baBufferSize, + pMlmAddBACnf->baTimeout,psessionEntry)) + { + PELOGW(limLog( pMac, LOGW, + FL( "Failed to post LIM_MLM_ADDBA_RSP to " )); + limPrintMacAddr( pMac, pMlmAddBACnf->peerMacAddr, LOGW );) + } + } + else + { + pSta->tcCfg[pMlmAddBACnf->baTID].fUseBATx = 1; + pSta->tcCfg[pMlmAddBACnf->baTID].fTxCompBA = 1; + pSta->tcCfg[pMlmAddBACnf->baTID].fTxBApolicy = pMlmAddBACnf->baPolicy; + pSta->tcCfg[pMlmAddBACnf->baTID].txBufSize = pMlmAddBACnf->baBufferSize; + pSta->tcCfg[pMlmAddBACnf->baTID].tuTxBAWaitTimeout = pMlmAddBACnf->baTimeout; + } + } + // Free the memory allocated for LIM_MLM_ADDBA_CNF + vos_mem_free(pMsgBuf); + pMsgBuf = NULL; +} +/** + * \brief Process LIM_MLM_DELBA_CNF + * + * \sa limProcessMlmDelBACnf + * + * \param pMac The global tpAniSirGlobal object + * + * \param tSirMsgQ The MsgQ header containing the response buffer + * + * \return none + */ +void limProcessMlmDelBACnf( tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf ) +{ + tpLimMlmDelBACnf pMlmDelBACnf; + tpDphHashNode pSta; + tANI_U16 aid; + tLimBAState curBaState; + tpPESession psessionEntry; + + if(pMsgBuf == NULL) + { + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) + return; + } + pMlmDelBACnf = (tpLimMlmDelBACnf) pMsgBuf; + if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDelBACnf->sessionId))== NULL) + { + limLog(pMac, LOGP,FL("SessionId:%d Session Does not exist"), + pMlmDelBACnf->sessionId); + vos_mem_free(pMsgBuf); + return; + } + // First, extract the DPH entry + pSta = dphLookupHashEntry( pMac, pMlmDelBACnf->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable ); + if( NULL == pSta ) + { + limLog( pMac, LOGE, + FL( "STA context not found - ignoring DELBA CNF from HAL" )); + vos_mem_free(pMsgBuf); + return; + } + if(NULL == pMlmDelBACnf) + { + limLog( pMac, LOGE, + FL( "pMlmDelBACnf is NULL - ignoring DELBA CNF from HAL" )); + return; + } + // Need to validate baState + LIM_GET_STA_BA_STATE(pSta, pMlmDelBACnf->baTID, &curBaState); + if( eLIM_BA_STATE_WT_DEL_RSP != curBaState ) + { + limLog( pMac, LOGE, + FL( "Received unexpected DELBA CNF when STA BA state is %d" ), + curBaState ); + vos_mem_free(pMsgBuf); + return; + } + // Restore STA BA state + LIM_SET_STA_BA_STATE(pSta, pMlmDelBACnf->baTID, eLIM_BA_STATE_IDLE); + // Free the memory allocated for LIM_MLM_DELBA_CNF + vos_mem_free(pMsgBuf); +} +/** + * \brief Process SIR_LIM_DEL_BA_IND + * + * \sa limProcessMlmHalBADeleteInd + * + * \param pMac The global tpAniSirGlobal object + * + * \param tSirMsgQ The MsgQ header containing the indication buffer + * + * \return none + */ +void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ ) +{ + tSirRetStatus status = eSIR_SUCCESS; + tpBADeleteParams pBADeleteParams; + tpDphHashNode pSta; + tANI_U16 aid; + tLimBAState curBaState; + tpPESession psessionEntry; + tANI_U8 sessionId; + + pBADeleteParams = (tpBADeleteParams) limMsgQ->bodyptr; + + if((psessionEntry = peFindSessionByBssid(pMac,pBADeleteParams->bssId,&sessionId))== NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return; + } + // First, extract the DPH entry + pSta = dphLookupHashEntry( pMac, pBADeleteParams->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable ); + if( NULL == pSta ) + { + limLog( pMac, LOGE, + FL( "STA context not found - ignoring BA Delete IND from HAL" )); + goto returnAfterCleanup; + } + + // Need to validate BA state + LIM_GET_STA_BA_STATE(pSta, pBADeleteParams->baTID, &curBaState); + if( eLIM_BA_STATE_IDLE != curBaState ) + { + limLog( pMac, LOGE, + FL( "Received unexpected BA Delete IND when STA BA state is %d" ), + curBaState ); + goto returnAfterCleanup; + } + + // Validate if a BA is active for the requested TID + // AND in that desired direction + if( eBA_INITIATOR == pBADeleteParams->baDirection ) + { + if( 0 == pSta->tcCfg[pBADeleteParams->baTID].fUseBATx ) + status = eSIR_FAILURE; + } + else + { + if( 0 == pSta->tcCfg[pBADeleteParams->baTID].fUseBARx ) + status = eSIR_FAILURE; + } + if( eSIR_FAILURE == status ) + { + limLog( pMac, LOGW, + FL("Received an INVALID DELBA Delete Ind for TID %d..."), + pBADeleteParams->baTID ); + } + else + { + // Post DELBA REQ to MLME... + if( eSIR_SUCCESS != + (status = limPostMlmDelBAReq( pMac, + pSta, + pBADeleteParams->baDirection, + pBADeleteParams->baTID, + eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry ))) + { + limLog( pMac, LOGE, + FL( "Attempt to post LIM_MLM_DELBA_REQ failed with status %d" ), status); + } + else + { + limLog( pMac, LOGE, + FL( "BA Delete - Reason 0x%08x. Attempting to delete BA session for TID %d with peer STA " ), + pBADeleteParams->reasonCode, pBADeleteParams->baTID ); + limPrintMacAddr( pMac, pSta->staAddr, LOGE ); + } + } +returnAfterCleanup: + // Free the memory allocated for SIR_LIM_DEL_BA_IND + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; +} + +/** + * @function : limHandleDelBssInReAssocContext + * @brief : While Processing the ReAssociation Response Frame in STA, + * a. immediately after receiving the Reassoc Response the RxCleanUp is + * being issued and the end of DelBSS the new BSS is being added. + * + * b .If an AP rejects the ReAssociation (Disassoc / Deauth) with some context + * change, We need to update CSR with ReAssocCNF Response with the + * ReAssoc Fail and the reason Code, that is also being handled in the DELBSS + * context only + * + * @param : pMac - tpAniSirGlobal + * pStaDs - Station Descriptor + * + * @return : none + */ +static void +limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; + /** Skipped the DeleteDPH Hash Entry as we need it for the new BSS*/ + /** Set the MlmState to IDLE*/ + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + /* Update PE session Id*/ + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + switch (psessionEntry->limSmeState) { + case eLIM_SME_WT_REASSOC_STATE : + { + tpSirAssocRsp assocRsp; + tpDphHashNode pStaDs; + tSirRetStatus retStatus = eSIR_SUCCESS; + tpSchBeaconStruct pBeaconStruct; + pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) + { + limLog(pMac, LOGE, FL("beaconStruct allocation failed")); + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + limDeleteDphHashEntry(pMac, psessionEntry->bssId, + DPH_STA_HASH_INDEX_PEER, psessionEntry); + goto Error; + } + /** Delete the older STA Table entry */ + limDeleteDphHashEntry(pMac, psessionEntry->bssId, DPH_STA_HASH_INDEX_PEER, psessionEntry); + /** + * Add an entry for AP to hash table + * maintained by DPH module + */ + if ((pStaDs = dphAddHashEntry(pMac, psessionEntry->limReAssocbssId, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) + { + // Could not add hash table entry + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) + limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE); + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; + goto Error; + } + /** While Processing the ReAssoc Response Frame the ReAssocRsp Frame + * is being stored to be used here for sending ADDBSS + */ + assocRsp = (tpSirAssocRsp)psessionEntry->limAssocResponseData; + limUpdateAssocStaDatas(pMac, pStaDs, assocRsp,psessionEntry); + limUpdateReAssocGlobals(pMac, assocRsp,psessionEntry); + limExtractApCapabilities( pMac, + (tANI_U8 *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, + limGetIElenFromBssDescription( &psessionEntry->pLimReAssocReq->bssDescription ), + pBeaconStruct ); + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, psessionEntry); + if(pBeaconStruct->erpPresent) { + if (pBeaconStruct->erpIEInfo.barkerPreambleMode) + psessionEntry->beaconParams.fShortPreamble = 0; + else + psessionEntry->beaconParams.fShortPreamble = 1; + } + //updateBss flag is false, as in this case, PE is first deleting the existing BSS and then adding a new one. + if (eSIR_SUCCESS != limStaSendAddBss( pMac, assocRsp, pBeaconStruct, + &psessionEntry->pLimReAssocReq->bssDescription, false, psessionEntry)) { + limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed ")); + retStatus = eSIR_FAILURE; + } + if (retStatus != eSIR_SUCCESS) + { + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + vos_mem_free(assocRsp); + pMac->lim.gLimAssocResponseData = NULL; + vos_mem_free(pBeaconStruct); + goto Error; + } + vos_mem_free(assocRsp); + vos_mem_free(pBeaconStruct); + psessionEntry->limAssocResponseData = NULL; + } + break; + case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE: + { + /** Case wherein the DisAssoc / Deauth + * being sent as response to ReAssoc Req*/ + /** Send the Reason code as the same received in Disassoc / Deauth Frame*/ + mlmReassocCnf.resultCode = pStaDs->mlmStaContext.disassocReason; + mlmReassocCnf.protStatusCode = pStaDs->mlmStaContext.cleanupTrigger; + /** Set the SME State back to WT_Reassoc State*/ + psessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId,psessionEntry); + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + } + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); + } + break; + default: + PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));) + mlmReassocCnf.resultCode = eSIR_SME_REFUSED; + mlmReassocCnf.protStatusCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + goto Error; + } + return; +Error: + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); +} + +/* Added For BT -AMP Support */ +static void +limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry) +{ + tLimMlmStartCnf mlmStartCnf; + tANI_U32 val; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + + if (NULL == pAddBssParams) + { + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); + goto end; + } + if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) + { + limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS")); + if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) + { + if (limSetLinkState(pMac, eSIR_LINK_BTAMP_AP_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) + goto end; + } else if (psessionEntry->bssType == eSIR_BTAMP_STA_MODE) { + if (limSetLinkState(pMac, eSIR_LINK_SCAN_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) + goto end; + } + + // Set MLME state + psessionEntry->limMlmState= eLIM_MLM_BSS_STARTED_STATE; + psessionEntry->statypeForBss = STA_ENTRY_SELF; // to know session started for peer or for self + psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; + schEdcaProfileUpdate(pMac, psessionEntry); + limInitPeerIdxpool(pMac,psessionEntry); + + /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); + pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; + // Apply previously set configuration at HW + limApplyConfiguration(pMac,psessionEntry); + psessionEntry->staId = pAddBssParams->staContext.staIdx; + mlmStartCnf.resultCode = eSIR_SME_SUCCESS; + } + else + { + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ),pAddBssParams->status ); + mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + mlmStartCnf.sessionId = psessionEntry->peSessionId; + limPostSmeMessage( pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf ); + end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + +/** + * @function : limHandleAddBssInReAssocContext + * @brief : While Processing the ReAssociation Response Frame in STA, + * a. immediately after receiving the Reassoc Response the RxCleanUp is + * being issued and the end of DelBSS the new BSS is being added. + * + * b .If an AP rejects the ReAssociation (Disassoc / Deauth) with some context + * change, We need to update CSR with ReAssocCNF Response with the + * ReAssoc Fail and the reason Code, that is also being handled in the DELBSS + * context only + * + * @param : pMac - tpAniSirGlobal + * pStaDs - Station Descriptor + * + * @return : none + */ +void +limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; + /** Skipped the DeleteDPH Hash Entry as we need it for the new BSS*/ + /** Set the MlmState to IDLE*/ + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + switch (psessionEntry->limSmeState) { + case eLIM_SME_WT_REASSOC_STATE : { + tpSirAssocRsp assocRsp; + tpDphHashNode pStaDs; + tSirRetStatus retStatus = eSIR_SUCCESS; + tSchBeaconStruct *pBeaconStruct; + pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); + if ( NULL == pBeaconStruct ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limHandleAddBssInReAssocContext") ); + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto Error; + } + + // Get the AP entry from DPH hash table + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL ) + { + PELOGE(limLog(pMac, LOGE, FL("Fail to get STA PEER entry from hash"));) + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; + vos_mem_free(pBeaconStruct); + goto Error; + } + /** While Processing the ReAssoc Response Frame the ReAssocRsp Frame + * is being stored to be used here for sending ADDBSS + */ + assocRsp = (tpSirAssocRsp)psessionEntry->limAssocResponseData; + limUpdateAssocStaDatas(pMac, pStaDs, assocRsp, psessionEntry); + limUpdateReAssocGlobals(pMac, assocRsp, psessionEntry); + limExtractApCapabilities( pMac, + (tANI_U8 *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, + limGetIElenFromBssDescription( &psessionEntry->pLimReAssocReq->bssDescription ), + pBeaconStruct ); + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, psessionEntry); + + if(pBeaconStruct->erpPresent) + { + if (pBeaconStruct->erpIEInfo.barkerPreambleMode) + psessionEntry->beaconParams.fShortPreamble = 0; + else + psessionEntry->beaconParams.fShortPreamble = 1; + } + /* to skip sending Add BSS and ADD STA incase of reassoc to + * same AP as part of HS2.0 set this flag + */ + psessionEntry->isNonRoamReassoc = 1; + if (eSIR_SUCCESS != limStaSendAddBss( pMac, assocRsp, pBeaconStruct, + &psessionEntry->pLimReAssocReq->bssDescription, true, psessionEntry)) { + limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed ")); + retStatus = eSIR_FAILURE; + } + if (retStatus != eSIR_SUCCESS) + { + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + vos_mem_free(assocRsp); + pMac->lim.gLimAssocResponseData = NULL; + vos_mem_free(pBeaconStruct); + goto Error; + } + vos_mem_free(assocRsp); + psessionEntry->limAssocResponseData = NULL; + vos_mem_free(pBeaconStruct); + } + break; + case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE: { /** Case wherein the DisAssoc / Deauth + * being sent as response to ReAssoc Req*/ + /** Send the Reason code as the same received in Disassoc / Deauth Frame*/ + mlmReassocCnf.resultCode = pStaDs->mlmStaContext.disassocReason; + mlmReassocCnf.protStatusCode = pStaDs->mlmStaContext.cleanupTrigger; + /** Set the SME State back to WT_Reassoc State*/ + psessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, psessionEntry); + if (LIM_IS_STA_ROLE(psessionEntry)) { + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + } + + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); + } + break; + default: + PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));) + mlmReassocCnf.resultCode = eSIR_SME_REFUSED; + mlmReassocCnf.protStatusCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + goto Error; + } +return; +Error: + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); +} + +void +limSendBeaconInd(tpAniSirGlobal pMac, tpPESession psessionEntry){ + tBeaconGenParams *pBeaconGenParams = NULL; + tSirMsgQ limMsg; + /** Allocate the Memory for Beacon Pre Message and for Stations in PoweSave*/ + if(psessionEntry == NULL ){ + PELOGE( limLog( pMac, LOGE, + FL( "Error:Unable to get the PESessionEntry" ));) + return; + } + pBeaconGenParams = vos_mem_malloc(sizeof(*pBeaconGenParams)); + if ( NULL == pBeaconGenParams ) + { + PELOGE( limLog( pMac, LOGP, + FL( "Unable to allocate memory during sending beaconPreMessage" ));) + return; + } + vos_mem_set(pBeaconGenParams, sizeof(*pBeaconGenParams), 0); + vos_mem_copy((void *) pBeaconGenParams->bssId, + (void *)psessionEntry->bssId, + SIR_MAC_ADDR_LENGTH ); + limMsg.bodyptr = pBeaconGenParams; + schProcessPreBeaconInd(pMac, &limMsg); + return; +} + +#ifdef FEATURE_WLAN_SCAN_PNO +/** + * limSendSmeScanCacheUpdatedInd() + * + *FUNCTION: + * This function is used to post WDA_SME_SCAN_CACHE_UPDATED message to WDA. + * This message is the indication to WDA that all scan cache results + * are updated from LIM to SME. Mainly used only in PNO offload case. + * + *LOGIC: + * + *ASSUMPTIONS: + * This function should be called after posting scan cache results to SME. + * + *NOTE: + * NA + * + * @return None + */ +void limSendSmeScanCacheUpdatedInd(tANI_U8 sessionId) +{ + vos_msg_t msg; + + msg.type = WDA_SME_SCAN_CACHE_UPDATED; + msg.reserved = 0; + msg.bodyptr = NULL; + msg.bodyval = sessionId; + + if (!VOS_IS_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_SME_SCAN_CACHE_UPDATED message to WDA", __func__); +} +#endif + +void limSendScanOffloadComplete(tpAniSirGlobal pMac, + tSirScanOffloadEvent *pScanEvent) +{ + tANI_U16 scanRspLen = 0; + + pMac->lim.gLimSmeScanResultLength += + pMac->lim.gLimMlmScanResultLength; + pMac->lim.gLimRspReqd = false; + if ((pScanEvent->reasonCode == eSIR_SME_SUCCESS) && + pMac->lim.gLimSmeScanResultLength) { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeScanResultLength - + sizeof(tSirBssDescription); + } + else + scanRspLen = sizeof(tSirSmeScanRsp); + + limSendSmeScanRsp(pMac, scanRspLen, pScanEvent->reasonCode, + pScanEvent->sessionId, + 0); +#ifdef FEATURE_WLAN_SCAN_PNO + limSendSmeScanCacheUpdatedInd(pScanEvent->sessionId); +#endif +} + + +void limProcessRxScanEvent(tpAniSirGlobal pMac, void *buf) +{ + tSirScanOffloadEvent *pScanEvent = (tSirScanOffloadEvent *) buf; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "scan_id = %u", pScanEvent->scanId); + + switch (pScanEvent->event) + { + case SCAN_EVENT_STARTED: + break; + case SCAN_EVENT_START_FAILED: + case SCAN_EVENT_COMPLETED: + pMac->lim.fOffloadScanPending = 0; + pMac->lim.fOffloadScanP2PSearch = 0; + pMac->lim.fOffloadScanP2PListen = 0; + if (P2P_SCAN_TYPE_LISTEN == pScanEvent->p2pScanType) + { + limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, + eHAL_STATUS_SUCCESS, + pScanEvent->sessionId, 0); + vos_mem_free(pMac->lim.gpLimRemainOnChanReq); + pMac->lim.gpLimRemainOnChanReq = NULL; + /* + * If remain on channel timer expired and action frame is + * pending then indicate confirmation with status failure + */ + if (pMac->lim.mgmtFrameSessionId != 0xff) { + limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + eSIR_SME_SEND_ACTION_FAIL, + pMac->lim.mgmtFrameSessionId, 0); + pMac->lim.mgmtFrameSessionId = 0xff; + } + + } + else + { + limSendScanOffloadComplete(pMac, pScanEvent); + } + break; + case SCAN_EVENT_FOREIGN_CHANNEL: + if (P2P_SCAN_TYPE_LISTEN == pScanEvent->p2pScanType) + { + /*Send Ready on channel indication to SME */ + if (pMac->lim.gpLimRemainOnChanReq) + { + limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RDY_IND, + eHAL_STATUS_SUCCESS, + pScanEvent->sessionId, 0); + } + else + { + limLog(pMac, LOGE, + FL(" NULL pointer of gpLimRemainOnChanReq")); + } + } + else + { + limAddScanChannelInfo(pMac, vos_freq_to_chan(pScanEvent->chanFreq)); + } + break; + case SCAN_EVENT_BSS_CHANNEL: + case SCAN_EVENT_DEQUEUED: + case SCAN_EVENT_PREEMPTED: + default: + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "Received unhandled scan event %u", pScanEvent->event); + } + vos_mem_free(buf); +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c new file mode 100644 index 000000000000..cd0763cd26ff --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c @@ -0,0 +1,735 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limProcessProbeReqFrame.cc contains the code + * for processing Probe Request Frame. + * Author: Chandra Modumudi + * Date: 02/28/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "cfgApi.h" + +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSerDesUtils.h" +#include "parserApi.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" + +void + +limSendSmeProbeReqInd(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tANI_U8 *pProbeReqIE, + tANI_U32 ProbeReqIELen, + tpPESession psessionEntry); + +/** + * limGetWPSPBCSessions + * + *FUNCTION: + * This function is called to query the WPS PBC overlap + * + *LOGIC: + * This function check WPS PBC probe request link list for PBC overlap + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param addr A pointer to probe request source MAC addresss + * @param uuid_e A pointer to UUIDE element of WPS IE in WPS PBC probe request + * @param psessionEntry A pointer to station PE session + * + * @return None + */ + +void limGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U8 *addr, + tANI_U8 *uuid_e, eWPSPBCOverlap *overlap, + tpPESession psessionEntry) +{ + int count = 0; + tSirWPSPBCSession *pbc; + tANI_TIMESTAMP curTime; + + curTime = (tANI_TIMESTAMP)(palGetTickCount(pMac->hHdd) / PAL_TICKS_PER_SECOND); + + vos_mem_set((tANI_U8 *)addr, sizeof(tSirMacAddr), 0); + vos_mem_set((tANI_U8 *)uuid_e, SIR_WPS_UUID_LEN, 0); + + for (pbc = psessionEntry->pAPWPSPBCSession; pbc; pbc = pbc->next) { + + if (curTime > pbc->timestamp + SIR_WPS_PBC_WALK_TIME) + break; + + count++; + if(count > 1) + break; + + vos_mem_copy((tANI_U8 *)addr, (tANI_U8 *)pbc->addr, sizeof(tSirMacAddr)); + vos_mem_copy((tANI_U8 *)uuid_e, (tANI_U8 *)pbc->uuid_e, SIR_WPS_UUID_LEN); + } + + if (count > 1) + { + *overlap = eSAP_WPSPBC_OVERLAP_IN120S; // Overlap + } + else if(count == 0) + { + *overlap = eSAP_WPSPBC_NO_WPSPBC_PROBE_REQ_IN120S; // no WPS probe request in 120 second + } else + { + *overlap = eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S; // One WPS probe request in 120 second + } + + PELOGE(limLog(pMac, LOGE, FL("overlap = %d"), *overlap);) + PELOGE(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOGE, addr, sizeof(tSirMacAddr));) + PELOGE(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOGE, uuid_e, SIR_WPS_UUID_LEN);) + + return; +} + +/** + * limRemoveTimeoutPBCsessions + * + *FUNCTION: + * This function is called to remove the WPS PBC probe request entires from specific entry to end. + * + *LOGIC: + * + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pbc The beginning entry in WPS PBC probe request link list + * + * @return None + */ +static void limRemoveTimeoutPBCsessions(tpAniSirGlobal pMac, tSirWPSPBCSession *pbc) +{ + tSirWPSPBCSession *prev; + + while (pbc) { + prev = pbc; + pbc = pbc->next; + + PELOG4(limLog(pMac, LOG4, FL("WPS PBC sessions remove"));) + PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, prev->addr, sizeof(tSirMacAddr));) + PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, prev->uuid_e, SIR_WPS_UUID_LEN);) + + vos_mem_free(prev); + } +} + +void limRemovePBCSessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac,tpPESession psessionEntry) +{ + tSirWPSPBCSession *pbc, *prev = NULL; + prev = pbc = psessionEntry->pAPWPSPBCSession; + + while (pbc) { + if (vos_mem_compare((tANI_U8 *)pbc->addr, + (tANI_U8 *)pRemoveMac, sizeof(tSirMacAddr))) { + prev->next = pbc->next; + if (pbc == psessionEntry->pAPWPSPBCSession) + psessionEntry->pAPWPSPBCSession = pbc->next; + vos_mem_free(pbc); + return; + } + prev = pbc; + pbc = pbc->next; + } + +} + +/** + * limUpdatePBCSessionEntry + * + *FUNCTION: + * This function is called when probe request with WPS PBC IE is received + * + *LOGIC: + * This function add the WPS PBC probe request in the WPS PBC probe request link list + * The link list is in decreased time order of probe request that is received. + * The entry that is more than 120 second is removed. + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param addr A pointer to probe request source MAC addresss + * @param uuid_e A pointer to UUIDE element of WPS IE + * @param psessionEntry A pointer to station PE session + * + * @return None + */ + +static void limUpdatePBCSessionEntry(tpAniSirGlobal pMac, + tANI_U8 *addr, tANI_U8 *uuid_e, + tpPESession psessionEntry) +{ + tSirWPSPBCSession *pbc, *prev = NULL; + + tANI_TIMESTAMP curTime; + + curTime = (tANI_TIMESTAMP)(palGetTickCount(pMac->hHdd) / PAL_TICKS_PER_SECOND); + + PELOG4(limLog(pMac, LOG4, FL("Receive WPS probe reques curTime=%d"), curTime);) + PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, addr, sizeof(tSirMacAddr));) + PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, uuid_e, SIR_WPS_UUID_LEN);) + + pbc = psessionEntry->pAPWPSPBCSession; + + while (pbc) { + if (vos_mem_compare((tANI_U8 *)pbc->addr, (tANI_U8 *)addr, sizeof(tSirMacAddr)) && + vos_mem_compare((tANI_U8 *)pbc->uuid_e, (tANI_U8 *)uuid_e, SIR_WPS_UUID_LEN)) { + if (prev) + prev->next = pbc->next; + else + psessionEntry->pAPWPSPBCSession = pbc->next; + break; + } + prev = pbc; + pbc = pbc->next; + } + + if (!pbc) { + pbc = vos_mem_malloc(sizeof(tSirWPSPBCSession)); + if ( NULL == pbc ) + { + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) + return; + } + vos_mem_copy((tANI_U8 *)pbc->addr, (tANI_U8 *)addr, sizeof(tSirMacAddr)); + + if (uuid_e) + vos_mem_copy((tANI_U8 *)pbc->uuid_e, (tANI_U8 *)uuid_e, SIR_WPS_UUID_LEN); + } + + pbc->next = psessionEntry->pAPWPSPBCSession; + psessionEntry->pAPWPSPBCSession = pbc; + pbc->timestamp = curTime; + + /* remove entries that have timed out */ + prev = pbc; + pbc = pbc->next; + + while (pbc) { + if (curTime > pbc->timestamp + SIR_WPS_PBC_WALK_TIME) { + prev->next = NULL; + limRemoveTimeoutPBCsessions(pMac, pbc); + break; + } + prev = pbc; + pbc = pbc->next; + } +} + +/** + * limWPSPBCClose + * + *FUNCTION: + * This function is called when BSS is closed + * + *LOGIC: + * This function remove all the WPS PBC entries + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param psessionEntry A pointer to station PE session + * + * @return None + */ + +void limWPSPBCClose(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + limRemoveTimeoutPBCsessions(pMac, psessionEntry->pAPWPSPBCSession); + +} + +/** + * limCheck11bRates + * + *FUNCTION: + * This function is called by limProcessProbeReqFrame() upon + * Probe Request frame reception. + * + *LOGIC: + * This function check 11b rates in supportedRates and extendedRates rates + * + *NOTE: + * + * @param rate + * + * @return BOOLEAN + */ + +tANI_BOOLEAN limCheck11bRates(tANI_U8 rate) +{ + if ( ( 0x02 == (rate)) + || ( 0x04 == (rate)) + || ( 0x0b == (rate)) + || ( 0x16 == (rate)) + ) + { + return TRUE; + } + return FALSE; +} + +/** + * limProcessProbeReqFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Probe Request frame reception. + * + *LOGIC: + * This function processes received Probe Request frame and responds + * with Probe Response. + * Only AP or STA in IBSS mode that sent last Beacon will respond to + * Probe Request. + * + *ASSUMPTIONS: + * 1. AP or STA in IBSS mode that sent last Beacon will always respond + * to Probe Request received with broadcast SSID. + * + *NOTE: + * 1. Dunno what to do with Rates received in Probe Request frame + * 2. Frames with out-of-order fields/IEs are dropped. + * + * @param pMac Pointer to Global MAC structure + * @param *pRxPacketInfo A pointer to Buffer descriptor + associated PDUs + * + * @return None + */ + +void +limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tANI_U8 *pBody; + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tSirProbeReq probeReq; + tAniSSID ssId; + tSirMsgQ msgQ; + tSirSmeProbeReq *pSirSmeProbeReq; + tANI_U32 wpsApEnable=0, tmp; + + do{ + // Don't send probe responses if disabled + if (pMac->lim.gLimProbeRespDisableFlag) + break; + + // Don't send probe response if P2P go is scanning till scan come to idle state. + if((psessionEntry->pePersona == VOS_P2P_GO_MODE) && ((pMac->lim.gpLimRemainOnChanReq ) + || (pMac->lim.gLimHalScanState != eLIM_HAL_IDLE_SCAN_STATE))) + { + limLog(pMac, LOG3, + FL("While GO is scanning, don't send probe response on diff channel")); + break; + } + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || + (LIM_IS_IBSS_ROLE(psessionEntry) && + (WDA_GET_RX_BEACON_SENT(pRxPacketInfo)))) { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + PELOG3(limLog(pMac, LOG3, FL("Received Probe Request %d bytes from "), frameLen); + limPrintMacAddr(pMac, pHdr->sa, LOG3);) + + // Get pointer to Probe Request frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + // Parse Probe Request frame + if (sirConvertProbeReqFrame2Struct(pMac, pBody, frameLen, &probeReq)==eSIR_FAILURE) + { + PELOGW(limLog(pMac, LOGE, + FL("Parse error ProbeRequest, length=%d, SA is: " + MAC_ADDRESS_STR), frameLen, MAC_ADDR_ARRAY(pHdr->sa));) + pMac->sys.probeError++; + break; + } + else + { + if (psessionEntry->pePersona == VOS_P2P_GO_MODE) + { + tANI_U8 i = 0, rate_11b = 0, other_rates = 0; + // Check 11b rates in supported rates + for ( i = 0 ; i < probeReq.supportedRates.numRates; + i++ ) + { + if (limCheck11bRates(probeReq.supportedRates.rate[i] & 0x7f)) + { + rate_11b++; + } + else + { + other_rates++; + } + } + + // Check 11b rates in extended rates + for ( i = 0 ; i < probeReq.extendedRates.numRates; i++ ) + { + if (limCheck11bRates(probeReq.extendedRates.rate[i] & 0x7f)) + { + rate_11b++; + } + else + { + other_rates++; + } + } + + if ( (rate_11b > 0) && (other_rates == 0) ) + { + PELOG3(limLog(pMac, LOG3, + FL("Received a probe request frame with only 11b rates, SA is: ")); + limPrintMacAddr(pMac, pHdr->sa, LOG3);) + return; + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ( (psessionEntry->APWPSIEs.SirWPSProbeRspIE.FieldPresent & + SIR_WPS_PROBRSP_VER_PRESENT) && + (probeReq.wscIePresent == 1) && + (probeReq.probeReqWscIeInfo.DevicePasswordID.id == + WSC_PASSWD_ID_PUSH_BUTTON) && + (probeReq.probeReqWscIeInfo.UUID_E.present == 1)) + { + if(psessionEntry->fwdWPSPBCProbeReq) + { + PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, + pHdr->sa, sizeof(tSirMacAddr));) + PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, pBody, frameLen);) + limSendSmeProbeReqInd(pMac, pHdr->sa, pBody, frameLen, psessionEntry); + } + else + { + limUpdatePBCSessionEntry(pMac, + pHdr->sa, probeReq.probeReqWscIeInfo.UUID_E.uuid, psessionEntry); + } + } + } + else + { + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) + limLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); + + wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; + if ((wpsApEnable) && + (probeReq.wscIePresent == 1) && + (probeReq.probeReqWscIeInfo.DevicePasswordID.id == WSC_PASSWD_ID_PUSH_BUTTON)) + { + // send the probe req to WSM when it is from a PBC station + pSirSmeProbeReq = vos_mem_malloc(sizeof(tSirSmeProbeReq)); + if ( NULL == pSirSmeProbeReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_PROBE_REQ")); + return; + } + msgQ.type = eWNI_SME_PROBE_REQ; + msgQ.bodyval = 0; + msgQ.bodyptr = pSirSmeProbeReq; + + pSirSmeProbeReq->messageType = eWNI_SME_PROBE_REQ; + pSirSmeProbeReq->length = sizeof(tSirSmeProbeReq); + pSirSmeProbeReq->sessionId = psessionEntry->smeSessionId; + vos_mem_copy(pSirSmeProbeReq->peerMacAddr, pHdr->sa, sizeof(tSirMacAddr)); + pSirSmeProbeReq->devicePasswdId = probeReq.probeReqWscIeInfo.DevicePasswordID.id; + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + if (limSysProcessMmhMsgApi(pMac, &msgQ, ePROT) != eSIR_SUCCESS){ + PELOG3(limLog(pMac, LOG3, FL("couldnt send the probe req to wsm "));) + } + } + } + } + + ssId.length = psessionEntry->ssId.length; + /* Copy the SSID from sessio entry to local variable */ + vos_mem_copy(ssId.ssId, + psessionEntry->ssId.ssId, + psessionEntry->ssId.length); + + // Compare received SSID with current SSID. If they + // match, reply with Probe Response. + if (probeReq.ssId.length) + { + if (!ssId.length) + goto multipleSSIDcheck; + + if (vos_mem_compare((tANI_U8 *) &ssId, + (tANI_U8 *) &(probeReq.ssId), (tANI_U8) (ssId.length + 1)) ) + { + limSendProbeRspMgmtFrame(pMac, pHdr->sa, &ssId, DPH_USE_MGMT_STAID, + DPH_NON_KEEPALIVE_FRAME, psessionEntry, + probeReq.p2pIePresent); + break; + } + else if (psessionEntry->pePersona == VOS_P2P_GO_MODE) + { + tANI_U8 direct_ssid[7] = "DIRECT-"; + tANI_U8 direct_ssid_len = 7; + if (vos_mem_compare((tANI_U8 *) &direct_ssid, + (tANI_U8 *) &(probeReq.ssId.ssId), (tANI_U8) (direct_ssid_len)) ) + { + limSendProbeRspMgmtFrame(pMac, pHdr->sa, &ssId, DPH_USE_MGMT_STAID, + DPH_NON_KEEPALIVE_FRAME, psessionEntry, + probeReq.p2pIePresent); + break; + } + } + else + { + PELOG3(limLog(pMac, LOG3, + FL("Ignoring ProbeReq frame with unmatched SSID received from ")); + limPrintMacAddr(pMac, pHdr->sa, LOG3);) + pMac->sys.probeBadSsid++; + } + } + else + { + { + // Broadcast SSID in the Probe Request. + // Reply with SSID we're configured with. + //Turn off the SSID length to 0 if hidden SSID feature is present + if(psessionEntry->ssidHidden) + /*We are returning from here as probe request contains the broadcast SSID. + So no need to send the probe resp*/ + return; + limSendProbeRspMgmtFrame(pMac, pHdr->sa, &ssId, DPH_USE_MGMT_STAID, + DPH_NON_KEEPALIVE_FRAME, psessionEntry, + probeReq.p2pIePresent); + } + break; + } +multipleSSIDcheck: + { + PELOG3(limLog(pMac, LOG3, + FL("Ignoring ProbeReq frame with unmatched SSID received from ")); + limPrintMacAddr(pMac, pHdr->sa, LOG3);) + pMac->sys.probeBadSsid++; + } + } + else + { + // Ignore received Probe Request frame + PELOG3(limLog(pMac, LOG3, FL("Ignoring Probe Request frame received from ")); + limPrintMacAddr(pMac, pHdr->sa, LOG3);) + pMac->sys.probeIgnore++; + break; + } + }while(0); + + return; +} /*** end limProcessProbeReqFrame() ***/ + +/** + * limIndicateProbeReqToHDD + * + *FUNCTION: + * This function is called by limProcessProbeReqFrame_multiple_BSS() upon + * Probe Request frame reception. + * + *LOGIC: + * This function processes received Probe Request frame and Pass + * Probe Request Frame to HDD. + * + * @param pMac Pointer to Global MAC structure + * @param *pBd A pointer to Buffer descriptor + associated PDUs + * @param psessionEntry A pointer to PE session + * + * @return None + */ + +static void +limIndicateProbeReqToHDD(tpAniSirGlobal pMac, tANI_U8 *pBd, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + + limLog( pMac, LOG1, FL("Received a probe request frame")); + + pHdr = WDA_GET_RX_MAC_HEADER(pBd); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd); + + //send the probe req to SME. + limSendSmeMgmtFrameInd( pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), + psessionEntry->smeSessionId, WDA_GET_RX_CH(pBd), + psessionEntry, 0); +} /*** end limIndicateProbeReqToHDD() ***/ + +/** + * limProcessProbeReqFrame_multiple_BSS + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Probe Request frame reception. + * + *LOGIC: + * This function call limIndicateProbeReqToHDD function to indicate + * Probe Request frame to HDD. It also call limProcessProbeReqFrame + * function which process received Probe Request frame and responds + * with Probe Response. + * + * @param pMac Pointer to Global MAC structure + * @param *pBd A pointer to Buffer descriptor + associated PDUs + * @param psessionEntry A pointer to PE session + * + * @return None + */ + +void +limProcessProbeReqFrame_multiple_BSS(tpAniSirGlobal pMac, tANI_U8 *pBd, tpPESession psessionEntry) +{ + tANI_U8 i; + + if (psessionEntry != NULL) + { + if (LIM_IS_AP_ROLE(psessionEntry)) { + limIndicateProbeReqToHDD(pMac, pBd, psessionEntry); + } + limProcessProbeReqFrame(pMac,pBd,psessionEntry); + return; + } + + for(i =0; i < pMac->lim.maxBssId;i++) + { + psessionEntry = peFindSessionBySessionId(pMac,i); + if ( (psessionEntry != NULL) ) + { + if (LIM_IS_AP_ROLE(psessionEntry)) { + limIndicateProbeReqToHDD(pMac, pBd, psessionEntry); + } + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_IBSS_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + limProcessProbeReqFrame(pMac,pBd,psessionEntry); + } + } + } + +} /*** end limProcessProbeReqFrame_multiple_BSS() ***/ + +/** + * limSendSmeProbeReqInd() + * + *FUNCTION: + * This function is to send + * eWNI_SME_WPS_PBC_PROBE_REQ_IND message to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * This function is used for sending eWNI_SME_WPS_PBC_PROBE_REQ_IND + * to host. + * + * @param peerMacAddr Indicates the peer MAC addr that the probe request + * is generated. + * @param pProbeReqIE pointer to RAW probe request IE + * @param ProbeReqIELen The length of probe request IE. + * @param psessionEntry A pointer to PE session + * + * @return None + */ +void +limSendSmeProbeReqInd(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tANI_U8 *pProbeReqIE, + tANI_U32 ProbeReqIELen, + tpPESession psessionEntry) +{ + tSirSmeProbeReqInd *pSirSmeProbeReqInd; + tSirMsgQ msgQ; + + pSirSmeProbeReqInd = vos_mem_malloc(sizeof(tSirSmeProbeReqInd)); + if ( NULL == pSirSmeProbeReqInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_PROBE_REQ")); + return; + } + + msgQ.type = eWNI_SME_WPS_PBC_PROBE_REQ_IND; + msgQ.bodyval = 0; + msgQ.bodyptr = pSirSmeProbeReqInd; + + pSirSmeProbeReqInd->messageType = eWNI_SME_WPS_PBC_PROBE_REQ_IND; + pSirSmeProbeReqInd->length = sizeof(tSirSmeProbeReq); + pSirSmeProbeReqInd->sessionId = psessionEntry->smeSessionId; + + vos_mem_copy(pSirSmeProbeReqInd->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + vos_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.peerMacAddr, peerMacAddr, sizeof(tSirMacAddr)); + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIELen = (tANI_U16)ProbeReqIELen; + vos_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIE, pProbeReqIE, ProbeReqIELen); + + if (limSysProcessMmhMsgApi(pMac, &msgQ, ePROT) != eSIR_SUCCESS){ + PELOGE(limLog(pMac, LOGE, FL("couldnt send the probe req to hdd"));) + } + +} /*** end limSendSmeProbeReqInd() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c new file mode 100644 index 000000000000..44ea55c6b01b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limProcessProbeRspFrame.cc contains the code + * for processing Probe Response Frame. + * Author: Chandra Modumudi + * Date: 03/01/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wniApi.h" +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "schApi.h" +#include "utilsApi.h" +#include "limApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limPropExtsUtils.h" +#include "limSerDesUtils.h" +#include "limSendMessages.h" + +#include "parserApi.h" + +tSirRetStatus +limValidateIEInformationInProbeRspFrame (tpAniSirGlobal pMac, + tANI_U8 *pRxPacketInfo) +{ + tSirRetStatus status = eSIR_SUCCESS; + tANI_U8 *pFrame; + tANI_U32 nFrame; + tANI_U32 nMissingRsnBytes; + + /* + * Validate a Probe response frame for malformed frame. + * If the frame is malformed then do not consider as it + * may cause problem fetching wrong IE values + */ + if (WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) < (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) + { + return eSIR_FAILURE; + } + + pFrame = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + nFrame = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + nMissingRsnBytes = 0; + + status = sirvalidateandrectifyies(pMac, pFrame, nFrame, &nMissingRsnBytes); + if ( status == eSIR_SUCCESS ) + { + WDA_GET_RX_MPDU_LEN(pRxPacketInfo) += nMissingRsnBytes; + } + + return status; +} + +/** + * limProcessProbeRspFrame + * + *FUNCTION: + * This function is called by limProcessMessageQueue() upon + * Probe Response frame reception. + * + *LOGIC: + * This function processes received Probe Response frame. + * + *ASSUMPTIONS: + * + *NOTE: + * 1. Frames with out-of-order IEs are dropped. + * 2. In case of IBSS, join 'success' makes MLM state machine + * transition into 'BSS started' state. This may have to change + * depending on supporting what kinda Authentication in IBSS. + * + * @param pMac Pointer to Global MAC structure + * @param *pRxPacketInfo A pointer to Buffer descriptor + associated PDUs + * @return None + */ + + +void +limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) +{ + tANI_U8 *pBody; + tANI_U32 frameLen = 0; + tSirMacAddr currentBssId; + tpSirMacMgmtHdr pHdr; + tSirProbeRespBeacon *pProbeRsp; + tANI_U8 qosEnabled = false; + tANI_U8 wmeEnabled = false; + + if (!psessionEntry) + { + limLog(pMac, LOGE, FL("psessionEntry is NULL") ); + return; + } + limLog(pMac,LOG1,"SessionId:%d ProbeRsp Frame is received", + psessionEntry->peSessionId); + + pProbeRsp = vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + if ( NULL == pProbeRsp ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limProcessProbeRspFrame") ); + return; + } + + pProbeRsp->ssId.length = 0; + pProbeRsp->wpa.length = 0; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + + PELOG2(limLog(pMac, LOG2, + FL("Received Probe Response frame with length=%d from "), + WDA_GET_RX_MPDU_LEN(pRxPacketInfo)); + limPrintMacAddr(pMac, pHdr->sa, LOG2);) + + if (!pMac->fScanOffload) + { + if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) + { + vos_mem_free(pProbeRsp); + return; + } + } + + // Validate IE information before processing Probe Response Frame + if (limValidateIEInformationInProbeRspFrame(pMac, pRxPacketInfo) + != eSIR_SUCCESS) + { + PELOG1(limLog(pMac, LOG1, + FL("Parse error ProbeResponse, length=%d"), frameLen);) + vos_mem_free(pProbeRsp); + return; + } + + /** + * Expect Probe Response only when + * 1. STA is in scan mode waiting for Beacon/Probe response or + * 2. STA is waiting for Beacon/Probe Response to announce + * join success or + * 3. STA is in IBSS mode in BSS started state or + * 4. STA/AP is in learn mode + * 5. STA in link established state. In this state, the probe response is + * expected for two scenarios: + * -- As part of heart beat mechanism, probe req is sent out + * -- If QoS Info IE in beacon has a different count for EDCA Params, + * and EDCA IE is not present in beacon, + * then probe req is sent out to get the EDCA params. + * + * Ignore Probe Response frame in all other states + */ + // TO SUPPORT BT-AMP + if (((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || //mlm state check should be global - 18th oct + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || //mlm state check should be global - 18th oct + (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) || //mlm state check should be global - 18th oct + (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) || + (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) )|| + (LIM_IS_IBSS_ROLE(psessionEntry) && + (psessionEntry->limMlmState == eLIM_MLM_BSS_STARTED_STATE)) || + pMac->fScanOffload) + { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED( + pRxPacketInfo))); + } + + // Get pointer to Probe Response frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE || + !pProbeRsp->ssidPresent) // Enforce Mandatory IEs + { + PELOG1(limLog(pMac, LOG1, + FL("Parse error ProbeResponse, length=%d"), + frameLen);) + vos_mem_free(pProbeRsp); + return; + } + + if (pMac->fScanOffload) + { + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, + eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + } + + //To Support BT-AMP + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || //mlm state check should be global - 18th oct + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, + ((pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) ? eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE), eANI_BOOLEAN_TRUE); + else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) //mlm state check should be global - 18th oct + { + } + else if (psessionEntry->limMlmState == + eLIM_MLM_WT_JOIN_BEACON_STATE) + { + if( psessionEntry->beacon != NULL )//Either Beacon/probe response is required. Hence store it in same buffer. + { + vos_mem_free(psessionEntry->beacon); + psessionEntry->beacon = NULL; + } + psessionEntry->bcnLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + psessionEntry->beacon = vos_mem_malloc(psessionEntry->bcnLen); + if ( NULL == psessionEntry->beacon ) + { + PELOGE(limLog(pMac, LOGE, + FL("Unable to allocate memory to store beacon"));) + } + else + { + //Store the Beacon/ProbeRsp. This is sent to csr/hdd in join cnf response. + vos_mem_copy(psessionEntry->beacon, + WDA_GET_RX_MPDU_DATA(pRxPacketInfo), + psessionEntry->bcnLen); + } + + // STA in WT_JOIN_BEACON_STATE + limCheckAndAnnounceJoinSuccess(pMac, pProbeRsp, pHdr, psessionEntry); + } + else if(psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) + { + tpDphHashNode pStaDs = NULL; + /** + * Check if this Probe Response is for + * our Probe Request sent upon reaching + * heart beat threshold + */ + sirCopyMacAddr(currentBssId,psessionEntry->bssId); + + if ( !vos_mem_compare(currentBssId, pHdr->bssId, sizeof(tSirMacAddr)) ) + { + vos_mem_free(pProbeRsp); + return; + } + + if (!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) + { + limLog(pMac, LOGW, + FL("Received Probe Resp from AP. So it is alive!!")); + + if (pProbeRsp->HTInfo.present) + limReceivedHBHandler(pMac, (tANI_U8)pProbeRsp->HTInfo.primaryChannel, psessionEntry); + else + limReceivedHBHandler(pMac, (tANI_U8)pProbeRsp->channelNumber, psessionEntry); + } + + + if (LIM_IS_STA_ROLE(psessionEntry)) { + if (pProbeRsp->channelSwitchPresent) + { +#ifdef FEATURE_WLAN_TDLS + /* + * on receiving channel switch announcement from AP, delete + * all TDLS peers before leaving BSS and proceed + * for channel switch + */ + limDeleteTDLSPeers(pMac, psessionEntry); +#endif + limUpdateChannelSwitch(pMac, pProbeRsp, psessionEntry); + } + else if (psessionEntry->gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) + { + limCancelDot11hChannelSwitch(pMac, psessionEntry); + } + } + + + /** + * Now Process EDCA Parameters, if EDCAParamSet count is different. + * -- While processing beacons in link established state if it is determined that + * QoS Info IE has a different count for EDCA Params, + * and EDCA IE is not present in beacon, + * then probe req is sent out to get the EDCA params. + */ + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + + limGetQosMode(psessionEntry, &qosEnabled); + limGetWmeMode(psessionEntry, &wmeEnabled); + PELOG2(limLog(pMac, LOG2, + FL("wmeEdcaPresent: %d wmeEnabled: %d, edcaPresent: %d, qosEnabled: %d, edcaParams.qosInfo.count: %d schObject.gLimEdcaParamSetCount: %d"), + pProbeRsp->wmeEdcaPresent, wmeEnabled, pProbeRsp->edcaPresent, qosEnabled, + pProbeRsp->edcaParams.qosInfo.count, psessionEntry->gLimEdcaParamSetCount);) + if (((pProbeRsp->wmeEdcaPresent && wmeEnabled) || + (pProbeRsp->edcaPresent && qosEnabled)) && + (pProbeRsp->edcaParams.qosInfo.count != psessionEntry->gLimEdcaParamSetCount)) + { + if (schBeaconEdcaProcess(pMac, &pProbeRsp->edcaParams, psessionEntry) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("EDCA parameter processing error"));) + else if (pStaDs != NULL) + { + // If needed, downgrade the EDCA parameters + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); + } + else + PELOGE(limLog(pMac, LOGE, FL("Self Entry missing in Hash Table"));) + + } + + if (psessionEntry->fWaitForProbeRsp == true) + { + limLog(pMac, LOGW, FL("Checking probe response for capability change\n") ); + limDetectChangeInApCapabilities(pMac, pProbeRsp, psessionEntry); + } + } + else if (LIM_IS_IBSS_ROLE(psessionEntry) && + (psessionEntry->limMlmState == eLIM_MLM_BSS_STARTED_STATE)) + limHandleIBSScoalescing(pMac, pProbeRsp, pRxPacketInfo,psessionEntry); + } // if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || ... + + vos_mem_free(pProbeRsp); + // Ignore Probe Response frame in all other states + return; +} /*** end limProcessProbeRspFrame() ***/ + + +void +limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) +{ + tANI_U8 *pBody; + tANI_U32 frameLen = 0; + tpSirMacMgmtHdr pHdr; + tSirProbeRespBeacon *pProbeRsp; + + pProbeRsp = vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + if ( NULL == pProbeRsp ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limProcessProbeRspFrameNoSession") ); + return; + } + + pProbeRsp->ssId.length = 0; + pProbeRsp->wpa.length = 0; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + + limLog(pMac, LOG2, + FL("Received Probe Response frame with length=%d from "), + WDA_GET_RX_MPDU_LEN(pRxPacketInfo)); + limPrintMacAddr(pMac, pHdr->sa, LOG2); + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || + WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo))) + { +#endif + if (!pMac->fScanOffload) + { + if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) + { + vos_mem_free(pProbeRsp); + return; + } + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + // Validate IE information before processing Probe Response Frame + if (limValidateIEInformationInProbeRspFrame(pMac, pRxPacketInfo) + != eSIR_SUCCESS) + { + PELOG1(limLog(pMac, LOG1,FL("Parse error ProbeResponse, length=%d"), + frameLen);) + vos_mem_free(pProbeRsp); + return; + } + /* Since there is no psessionEntry, PE cannot be in the following states: + * - eLIM_MLM_WT_JOIN_BEACON_STATE + * - eLIM_MLM_LINK_ESTABLISHED_STATE + * - eLIM_MLM_BSS_STARTED_STATE + * Hence, expect Probe Response only when + * 1. STA is in scan mode waiting for Beacon/Probe response + * 2. LFR logic in FW sends up candidate frames + * + * Ignore Probe Response frame in all other states + */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8) + WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo))); + } + + // Get pointer to Probe Response frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE) + { + limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d\n"), frameLen); + vos_mem_free(pProbeRsp); + return; + } + limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache")); + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, + eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + } + else +#endif + if (pMac->fScanOffload) + { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + // Get pointer to Probe Response frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) + == eSIR_FAILURE) + { + limLog(pMac, LOG1, + FL("Parse error ProbeResponse, length=%d\n"), frameLen); + vos_mem_free(pProbeRsp); + return; + } + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, + eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + } + else if( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || //mlm state check should be global - 18th oct + (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) ) + { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED( + pRxPacketInfo))); + } + + // Get pointer to Probe Response frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE) + { + limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d"), frameLen); + vos_mem_free(pProbeRsp); + return; + } + + if( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) ) + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) + { + } + } + vos_mem_free(pProbeRsp); + return; +} /*** end limProcessProbeRspFrameNew() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c new file mode 100644 index 000000000000..30caa7e1c2ad --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -0,0 +1,7058 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file limProcessSmeReqMessages.cc contains the code + * for processing SME request messages. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "palTypes.h" +#include "wniApi.h" +#include "wniCfgSta.h" +#include "cfgApi.h" +#include "sirApi.h" +#include "schApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limSmeReqUtils.h" +#include "limIbssPeerMgmt.h" +#include "limAdmitControl.h" +#include "dphHashTable.h" +#include "limSendMessages.h" +#include "limApi.h" +#include "wmmApsd.h" +#include "sirMacProtDef.h" +#include "regdomain_common.h" +#include "rrmApi.h" + + +#include "sapApi.h" + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseApi.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +#include +#endif + +/* This overhead is time for sending NOA start to host in case of GO/sending NULL data & receiving ACK + * in case of P2P Client and starting actual scanning with init scan req/rsp plus in case of concurrency, + * taking care of sending null data and receiving ACK to/from AP/Also SetChannel with calibration is taking + * around 7ms . + */ +#define SCAN_MESSAGING_OVERHEAD 20 // in msecs +#define JOIN_NOA_DURATION 2000 // in msecs +#define OEM_DATA_NOA_DURATION 60 // in msecs +#define DEFAULT_PASSIVE_MAX_CHANNEL_TIME 110 // in msecs + +#define CONV_MS_TO_US 1024 //conversion factor from ms to us +// SME REQ processing function templates +static void __limProcessSmeStartReq(tpAniSirGlobal, tANI_U32 *); +static tANI_BOOLEAN __limProcessSmeSysReadyInd(tpAniSirGlobal, tANI_U32 *); +static tANI_BOOLEAN __limProcessSmeStartBssReq(tpAniSirGlobal, tpSirMsgQ pMsg); +static void __limProcessSmeScanReq(tpAniSirGlobal, tANI_U32 *); +static void __limProcessSmeJoinReq(tpAniSirGlobal, tANI_U32 *); +static void __limProcessSmeReassocReq(tpAniSirGlobal, tANI_U32 *); +static void __limProcessSmeDisassocReq(tpAniSirGlobal, tANI_U32 *); +static void __limProcessSmeDisassocCnf(tpAniSirGlobal, tANI_U32 *); +static void __limProcessSmeDeauthReq(tpAniSirGlobal, tANI_U32 *); +static void __limProcessSmeSetContextReq(tpAniSirGlobal, tANI_U32 *); +static tANI_BOOLEAN __limProcessSmeStopBssReq(tpAniSirGlobal, tpSirMsgQ pMsg); +static void limProcessSmeChannelChangeRequest(tpAniSirGlobal pMac, + tANI_U32 *pMsg); +static void limProcessSmeStartBeaconReq(tpAniSirGlobal pMac, + tANI_U32 *pMsg); +static void limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg); + +static void limStartBssUpdateAddIEBuffer(tpAniSirGlobal pMac, + tANI_U8 **pDstData_buff, + tANI_U16 *pDstDataLen, + tANI_U8 *pSrcData_buff, + tANI_U16 srcDataLen); + +static void limUpdateAddIEBuffer(tpAniSirGlobal pMac, + tANI_U8 **pDstData_buff, + tANI_U16 *pDstDataLen, + tANI_U8 *pSrcData_buff, + tANI_U16 srcDataLen); +static void limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg); + +static void limProcessUpdateAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg); + +static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx, + uint32_t *msg); + +void __limProcessSmeAssocCnfNew(tpAniSirGlobal, tANI_U32, tANI_U32 *); + +extern void peRegisterTLHandle(tpAniSirGlobal pMac); + +static void lim_process_set_pdev_IEs(tpAniSirGlobal pMac, tANI_U32 *msg_buf); +static void lim_set_pdev_ht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, + tANI_U8 nss); +static void lim_set_pdev_vht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, + tANI_U8 nss); +#ifdef BACKGROUND_SCAN_ENABLED + +// start the background scan timers if it hasn't already started +static void +__limBackgroundScanInitiate(tpAniSirGlobal pMac) +{ + if (pMac->lim.gLimBackgroundScanStarted) + return; + + //make sure timer is created first + if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_BACKGROUND_SCAN_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) + limLog(pMac, LOGP, FL("could not activate background scan timer")); + pMac->lim.gLimBackgroundScanStarted = true; + pMac->lim.gLimBackgroundScanChannelId = 0; + } +} + +#endif // BACKGROUND_SCAN_ENABLED + +// determine if a fresh scan request must be issued or not +/* +* PE will do fresh scan, if all of the active sessions are in good state (Link Est or BSS Started) +* If one of the sessions is not in one of the above states, then PE does not do fresh scan +* If no session exists (scanning very first time), then PE will always do fresh scan if SME +* asks it to do that. +*/ +static tANI_U8 +__limFreshScanReqd(tpAniSirGlobal pMac, tANI_U8 returnFreshResults) +{ + + tANI_U8 validState = TRUE; + int i; + + limLog(pMac, LOG1, FL("gLimSmeState: %d, returnFreshResults 0x%x"), + pMac->lim.gLimSmeState, returnFreshResults); + if(pMac->lim.gLimSmeState != eLIM_SME_IDLE_STATE) + { + limLog(pMac, LOG1, FL("return FALSE")); + return FALSE; + } + for(i =0; i < pMac->lim.maxBssId; i++) + { + + if(pMac->lim.gpSession[i].valid == TRUE) + { + limLog(pMac, LOG1, + FL("session %d, bsstype %d, limSystemRole %d, limSmeState %d"), + i, + pMac->lim.gpSession[i].bssType, + pMac->lim.gpSession[i].limSystemRole, + pMac->lim.gpSession[i].limSmeState); + if(!( ( ( (pMac->lim.gpSession[i].bssType == eSIR_INFRASTRUCTURE_MODE) || + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_STA_ROLE))&& + (pMac->lim.gpSession[i].limSmeState == eLIM_SME_LINK_EST_STATE) )|| + + ( ( (pMac->lim.gpSession[i].bssType == eSIR_IBSS_MODE)|| + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_AP_ROLE)|| + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_STA_ROLE) )&& + (pMac->lim.gpSession[i].limSmeState == eLIM_SME_NORMAL_STATE) ) + || ( ( ( (pMac->lim.gpSession[i].bssType == eSIR_INFRA_AP_MODE) + && ( pMac->lim.gpSession[i].pePersona == VOS_P2P_GO_MODE) ) + || (pMac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) ) + && (pMac->lim.gpSession[i].limSmeState == eLIM_SME_NORMAL_STATE) ) + )) + { + validState = FALSE; + break; + } + + } + } + + + if((validState) && + (returnFreshResults & SIR_BG_SCAN_RETURN_FRESH_RESULTS)) { + limLog(pMac, LOG1, FL("validState: %d, return TRUE"), validState); + return TRUE; + } else { + limLog(pMac, LOG1, FL("validState: %d, return FALSE"), validState); + return FALSE; + } +} + + + +/** + * __limIsSmeAssocCnfValid() + * + *FUNCTION: + * This function is called by limProcessLmmMessages() upon + * receiving SME_ASSOC_CNF. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMeasReq Pointer to Received ASSOC_CNF message + * @return true When received SME_ASSOC_CNF is formatted + * correctly + * false otherwise + */ + +inline static tANI_U8 +__limIsSmeAssocCnfValid(tpSirSmeAssocCnf pAssocCnf) +{ + if (limIsGroupAddr(pAssocCnf->peerMacAddr)) + return false; + else + return true; +} /*** end __limIsSmeAssocCnfValid() ***/ + + +/** + * __limGetSmeJoinReqSizeForAlloc() + * + *FUNCTION: + * This function is called in various places to get IE length + * from tSirBssDescription structure + * number being scanned. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pBssDescr + * @return Total IE length + */ + +static tANI_U16 +__limGetSmeJoinReqSizeForAlloc(tANI_U8 *pBuf) +{ + tANI_U16 len = 0; + + if (!pBuf) + return len; + + pBuf += sizeof(tANI_U16); + len = limGetU16( pBuf ); + return (len + sizeof( tANI_U16 )); +} /*** end __limGetSmeJoinReqSizeForAlloc() ***/ + + +/**---------------------------------------------------------------- +\fn __limIsDeferedMsgForLearn + +\brief Has role only if 11h is enabled. Not used on STA side. + Defers the message if SME is in learn state and brings + the LIM back to normal mode. + +\param pMac +\param pMsg - Pointer to message posted from SME to LIM. +\return TRUE - If defered + FALSE - Otherwise +------------------------------------------------------------------*/ +static tANI_BOOLEAN +__limIsDeferedMsgForLearn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + if (limIsSystemInScanState(pMac)) + { + if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) + return eANI_BOOLEAN_FALSE; + } + PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), + pMsg->type);) + + /** Send finish scan req to HAL only if LIM is not waiting for any response + * from HAL like init scan rsp, start scan rsp etc. + */ + if (GET_LIM_PROCESS_DEFD_MESGS(pMac)) + { + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_LEARN_WAIT_STATE); + } + + return eANI_BOOLEAN_TRUE; + } + return eANI_BOOLEAN_FALSE; +} + +/**---------------------------------------------------------------- +\fn __limIsDeferedMsgForRadar + +\brief Has role only if 11h is enabled. Not used on STA side. + Defers the message if radar is detected. + +\param pMac +\param pMsg - Pointer to message posted from SME to LIM. +\return TRUE - If defered + FALSE - Otherwise +------------------------------------------------------------------*/ +static tANI_BOOLEAN +__limIsDeferedMsgForRadar(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + /** fRadarDetCurOperChan will be set only if we detect radar in current + * operating channel and System Role == AP ROLE */ + //TODO: Need to take care radar detection. + //if (LIM_IS_RADAR_DETECTED(pMac)) + if( 0 ) + { + if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) + return eANI_BOOLEAN_FALSE; + } + PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), + pMsg->type);) + return eANI_BOOLEAN_TRUE; + } + return eANI_BOOLEAN_FALSE; +} + + +/** + * __limProcessSmeStartReq() + * + *FUNCTION: + * This function is called to process SME_START_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + + PELOG1(limLog(pMac, LOG1, FL("Received START_REQ"));) + + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) + { + pMac->lim.gLimSmeState = eLIM_SME_IDLE_STATE; + + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, NO_SESSION, pMac->lim.gLimSmeState)); + + /// By default do not return after first scan match + pMac->lim.gLimReturnAfterFirstMatch = 0; + + /// By default return unique scan results + pMac->lim.gLimReturnUniqueResults = true; + pMac->lim.gLimSmeScanResultLength = 0; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->lim.gLimSmeLfrScanResultLength = 0; +#endif + + if (((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) + { + /* + * Need to indicate new BSSs found during background scanning to + * host. Update this parameter at CFG + */ + if (cfgSetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, ((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not set NEIGHBOR_BSS_IND at CFG")); + retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + } + } + } + else + { + /** + * Should not have received eWNI_SME_START_REQ in states + * other than OFFLINE. Return response to host and + * log error + */ + limLog(pMac, LOGE, FL("Invalid SME_START_REQ received in SME state %X"),pMac->lim.gLimSmeState ); + retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + } + limSendSmeRsp(pMac, eWNI_SME_START_RSP, retCode,smesessionId,smetransactionId); +} /*** end __limProcessSmeStartReq() ***/ + + +/** ------------------------------------------------------------- +\fn __limProcessSmeSysReadyInd +\brief handles the notification from HDD. PE just forwards this message to HAL. +\param tpAniSirGlobal pMac +\param tANI_U32* pMsgBuf +\return TRUE-Posting to HAL failed, so PE will consume the buffer. +\ FALSE-Posting to HAL successful, so HAL will consume the buffer. + -------------------------------------------------------------*/ +static tANI_BOOLEAN +__limProcessSmeSysReadyInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMsgQ msg; + + msg.type = WDA_SYS_READY_IND; + msg.reserved = 0; + msg.bodyptr = pMsgBuf; + msg.bodyval = 0; + + if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) { + peRegisterTLHandle(pMac); + } + PELOGW(limLog(pMac, LOGW, FL("sending WDA_SYS_READY_IND msg to HAL"));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); + return eANI_BOOLEAN_TRUE; + } + return eANI_BOOLEAN_FALSE; +} + +#ifdef WLAN_FEATURE_11AC + +tANI_U32 limGetCenterChannel(tpAniSirGlobal pMac,tANI_U8 primarychanNum,ePhyChanBondState secondaryChanOffset, tANI_U8 chanWidth) +{ + if (chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) + { + switch(secondaryChanOffset) + { + case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + return primarychanNum; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + return primarychanNum + 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + return primarychanNum - 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + return primarychanNum + 6; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + return primarychanNum + 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + return primarychanNum - 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + return primarychanNum - 6; + default : + return eSIR_CFG_INVALID_ID; + } + } + else if (chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) + { + switch(secondaryChanOffset) + { + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + return primarychanNum + 2; + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + return primarychanNum - 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + return primarychanNum; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + return primarychanNum + 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + return primarychanNum - 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + return primarychanNum + 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + return primarychanNum - 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + return primarychanNum + 2; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + return primarychanNum - 2; + default : + return eSIR_CFG_INVALID_ID; + } + } + return primarychanNum; +} + +#endif +/** + * __limHandleSmeStartBssRequest() + * + *FUNCTION: + * This function is called to process SME_START_BSS_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U16 size; + tANI_U32 val = 0; + tSirRetStatus retStatus; + tSirMacChanNum channelNumber; + tLimMlmStartReq *pMlmStartReq = NULL; + tpSirSmeStartBssReq pSmeStartBssReq = NULL; + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tANI_U32 autoGenBssId = FALSE; //Flag Used in case of IBSS to Auto generate BSSID. + tANI_U8 sessionId; + tpPESession psessionEntry = NULL; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + struct vdev_type_nss *vdev_type_nss; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + //Since the session is not created yet, sending NULL. The response should have the correct state. + limDiagEventReport(pMac, WLAN_PE_DIAG_START_BSS_REQ_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + PELOG1(limLog(pMac, LOG1, FL("Received START_BSS_REQ"));) + + /* Global Sme state and mlm states are not defined yet, for BT-AMP Suppoprt . TO BE DONE */ + if ( (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || + (pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) + { + size = sizeof(tSirSmeStartBssReq) + SIR_MAC_MAX_IE_LENGTH; + + pSmeStartBssReq = vos_mem_malloc(size); + if ( NULL == pSmeStartBssReq ) + { + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed for pMac->lim.gpLimStartBssReq"));) + /// Send failure response to host + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + + vos_mem_set((void *)pSmeStartBssReq, size, 0); + + if ((limStartBssReqSerDes(pMac, pSmeStartBssReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || + (!limIsSmeStartBssReqValid(pMac, pSmeStartBssReq))) + { + PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) + retCode = eSIR_SME_INVALID_PARAMETERS; + goto free; + } + + /* This is the place where PE is going to create a session. + * If session is not existed, then create a new session */ + if((psessionEntry = peFindSessionByBssid(pMac,pSmeStartBssReq->bssId,&sessionId)) != NULL) + { + limLog(pMac, LOGW, FL("Session Already exists for given BSSID")); + retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + psessionEntry = NULL; + goto free; + } + else + { + if((psessionEntry = peCreateSession(pMac, + pSmeStartBssReq->bssId, + &sessionId, + pMac->lim.maxStation, + pSmeStartBssReq->bssType)) == NULL) + { + limLog(pMac, LOGW, FL("Session Can not be created ")); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + } + + /* Probe resp add ie */ + limStartBssUpdateAddIEBuffer(pMac, + &psessionEntry->addIeParams.probeRespData_buff, + &psessionEntry->addIeParams.probeRespDataLen, + pSmeStartBssReq->addIeParams.probeRespData_buff, + pSmeStartBssReq->addIeParams.probeRespDataLen); + + /* Probe Beacon add ie */ + limStartBssUpdateAddIEBuffer(pMac, + &psessionEntry->addIeParams.probeRespBCNData_buff, + &psessionEntry->addIeParams.probeRespBCNDataLen, + pSmeStartBssReq->addIeParams.probeRespBCNData_buff, + pSmeStartBssReq->addIeParams.probeRespBCNDataLen); + + /* Assoc resp IE */ + limStartBssUpdateAddIEBuffer(pMac, + &psessionEntry->addIeParams.assocRespData_buff, + &psessionEntry->addIeParams.assocRespDataLen, + pSmeStartBssReq->addIeParams.assocRespData_buff, + pSmeStartBssReq->addIeParams.assocRespDataLen); + + /* Store the session related parameters in newly created session */ + psessionEntry->pLimStartBssReq = pSmeStartBssReq; + + /* Store PE sessionId in session Table */ + psessionEntry->peSessionId = sessionId; + + /* Store SME session Id in sessionTable */ + psessionEntry->smeSessionId = pSmeStartBssReq->sessionId; + + psessionEntry->transactionId = pSmeStartBssReq->transactionId; + + vos_mem_copy(&(psessionEntry->htConfig), &(pSmeStartBssReq->htConfig), + sizeof(psessionEntry->htConfig)); + + sirCopyMacAddr(psessionEntry->selfMacAddr,pSmeStartBssReq->selfMacAddr); + + /* Copy SSID to session table */ + vos_mem_copy( (tANI_U8 *)&psessionEntry->ssId, + (tANI_U8 *)&pSmeStartBssReq->ssId, + (pSmeStartBssReq->ssId.length + 1)); + + psessionEntry->bssType = pSmeStartBssReq->bssType; + + psessionEntry->nwType = pSmeStartBssReq->nwType; + + psessionEntry->beaconParams.beaconInterval = pSmeStartBssReq->beaconInterval; + + /* Store the channel number in session Table */ + psessionEntry->currentOperChannel = pSmeStartBssReq->channelId; + + /*Store Persona */ + psessionEntry->pePersona = pSmeStartBssReq->bssPersona; + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,FL("PE PERSONA=%d"), + psessionEntry->pePersona); + + /*Update the phymode*/ + psessionEntry->gLimPhyMode = pSmeStartBssReq->nwType; + + psessionEntry->maxTxPower = cfgGetRegulatoryMaxTransmitPower( pMac, + psessionEntry->currentOperChannel ); + /* Store the dot 11 mode in to the session Table*/ + psessionEntry->dot11mode = pSmeStartBssReq->dot11mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + psessionEntry->cc_switch_mode = pSmeStartBssReq->cc_switch_mode; +#endif + psessionEntry->htCapability = IS_DOT11_MODE_HT(psessionEntry->dot11mode); +#ifdef WLAN_FEATURE_11AC + psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(psessionEntry->dot11mode); + VOS_TRACE(VOS_MODULE_ID_PE,VOS_TRACE_LEVEL_INFO, + FL("*****psessionEntry->vhtCapability = %d"),psessionEntry->vhtCapability); +#endif + + psessionEntry->txLdpcIniFeatureEnabled = + pSmeStartBssReq->txLdpcIniFeatureEnabled; + +#ifdef WLAN_FEATURE_11W + psessionEntry->limRmfEnabled = pSmeStartBssReq->pmfCapable ? 1 : 0; + limLog(pMac, LOG1, FL("Session RMF enabled: %d"), psessionEntry->limRmfEnabled); +#endif + + vos_mem_copy((void*)&psessionEntry->rateSet, + (void*)&pSmeStartBssReq->operationalRateSet, + sizeof(tSirMacRateSet)); + vos_mem_copy((void*)&psessionEntry->extRateSet, + (void*)&pSmeStartBssReq->extendedRateSet, + sizeof(tSirMacRateSet)); + + if (IS_5G_CH(psessionEntry->currentOperChannel)) + vdev_type_nss = &pMac->vdev_type_nss_5g; + else + vdev_type_nss = &pMac->vdev_type_nss_2g; + switch(pSmeStartBssReq->bssType) + { + case eSIR_INFRA_AP_MODE: + psessionEntry->limSystemRole = eLIM_AP_ROLE; + psessionEntry->privacy = pSmeStartBssReq->privacy; + psessionEntry->fwdWPSPBCProbeReq = pSmeStartBssReq->fwdWPSPBCProbeReq; + psessionEntry->authType = pSmeStartBssReq->authType; + /* Store the DTIM period */ + psessionEntry->dtimPeriod = (tANI_U8)pSmeStartBssReq->dtimPeriod; + /*Enable/disable UAPSD*/ + psessionEntry->apUapsdEnable = pSmeStartBssReq->apUapsdEnable; + if (psessionEntry->pePersona == VOS_P2P_GO_MODE) + { + psessionEntry->proxyProbeRspEn = 0; + psessionEntry->vdev_nss = vdev_type_nss->p2p_go; + } + else + { + /* To detect PBC overlap in SAP WPS mode, Host handles + * Probe Requests. + */ + if(SAP_WPS_DISABLED == pSmeStartBssReq->wps_state) + { + psessionEntry->proxyProbeRspEn = 1; + } + else + { + psessionEntry->proxyProbeRspEn = 0; + } + psessionEntry->vdev_nss = vdev_type_nss->sap; + } + psessionEntry->ssidHidden = pSmeStartBssReq->ssidHidden; + psessionEntry->wps_state = pSmeStartBssReq->wps_state; + psessionEntry->sap_dot11mc = pSmeStartBssReq->sap_dot11mc; + limGetShortSlotFromPhyMode(pMac, psessionEntry, + psessionEntry->gLimPhyMode, + &psessionEntry->shortSlotTimeSupported); + psessionEntry->isCoalesingInIBSSAllowed = + pSmeStartBssReq->isCoalesingInIBSSAllowed; + break; + case eSIR_IBSS_MODE: + psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; + limGetShortSlotFromPhyMode(pMac, psessionEntry, + psessionEntry->gLimPhyMode, + &psessionEntry->shortSlotTimeSupported); + + // initialize to "OPEN". will be updated upon key installation + psessionEntry->encryptType = eSIR_ED_NONE; + psessionEntry->vdev_nss = vdev_type_nss->ibss; + break; + + case eSIR_BTAMP_AP_MODE: + psessionEntry->limSystemRole = eLIM_BT_AMP_AP_ROLE; + break; + + case eSIR_BTAMP_STA_MODE: + psessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; + break; + + /* There is one more mode called auto mode. which is used no where */ + + //FORBUILD -TEMPFIX.. HOW TO use AUTO MODE????? + + + default: + //not used anywhere...used in scan function + break; + } + limLog(pMac, LOG1, FL("persona - %d, nss - %d"), + psessionEntry->pePersona, psessionEntry->vdev_nss); + // BT-AMP: Allocate memory for the array of parsed (Re)Assoc request structure + if ( (pSmeStartBssReq->bssType == eSIR_BTAMP_AP_MODE) + || (pSmeStartBssReq->bssType == eSIR_INFRA_AP_MODE) + ) + { + psessionEntry->parsedAssocReq = vos_mem_malloc( + psessionEntry->dph.dphHashTable.size * sizeof(tpSirAssocReq)); + if ( NULL == psessionEntry->parsedAssocReq ) + { + limLog(pMac, LOGW, FL("AllocateMemory() failed")); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + vos_mem_set(psessionEntry->parsedAssocReq, + (psessionEntry->dph.dphHashTable.size * sizeof(tpSirAssocReq)), + 0 ); + } + + /* Channel Bonding is not addressd yet for BT-AMP Support.. sunit will address channel bonding */ + if (pSmeStartBssReq->channelId) + { + channelNumber = pSmeStartBssReq->channelId; +#ifdef QCA_HT_2040_COEX + if (pSmeStartBssReq->obssEnabled) + psessionEntry->htSupportedChannelWidthSet = + IS_DOT11_MODE_HT(psessionEntry->dot11mode) ? 1 : 0; + else +#endif + psessionEntry->htSupportedChannelWidthSet = + (pSmeStartBssReq->cbMode)?1:0; + psessionEntry->htSecondaryChannelOffset = pSmeStartBssReq->cbMode; + psessionEntry->htRecommendedTxWidthSet = + (psessionEntry->htSecondaryChannelOffset)? 1:0; + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("cbMode %u"), pSmeStartBssReq->cbMode); +#ifdef WLAN_FEATURE_11AC + if(psessionEntry->vhtCapability) + { + tANI_U32 centerChan; + tANI_U32 chanWidth; + + chanWidth = pSmeStartBssReq->vht_channel_width; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("vht_channel_width %u"), + pSmeStartBssReq->vht_channel_width); + + if(channelNumber <= RF_CHAN_14 && + chanWidth != eHT_CHANNEL_WIDTH_20MHZ) + { + chanWidth = eHT_CHANNEL_WIDTH_20MHZ; + limLog(pMac, LOG1, FL("Setting chanWidth to 20Mhz for" + " channel %d"),channelNumber); + } + + /* + * For Sta+p2p-Go concurrency + * vhtTxChannelWidthSet is used for storing p2p-GO channel width + * apChanWidth is used for storing the AP channel width that + * the Sta is going to associate. + * Initialize the apChanWidth same as p2p-GO channel width this + * gets over written once the station joins the AP + */ + if(chanWidth == eHT_CHANNEL_WIDTH_20MHZ || + chanWidth == eHT_CHANNEL_WIDTH_40MHZ) + { + psessionEntry->vhtTxChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + psessionEntry->apChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + } + if (chanWidth == eHT_CHANNEL_WIDTH_80MHZ) + { + psessionEntry->vhtTxChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + psessionEntry->apChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + + centerChan = limGetCenterChannel( pMac, channelNumber, + pSmeStartBssReq->cbMode, + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ); + if(centerChan != eSIR_CFG_INVALID_ID) + { + limLog(pMac, LOGW, FL("***Center Channel for " + "80MHZ channel width = %d"),centerChan); + psessionEntry->apCenterChan = centerChan; + if (cfgSetInt(pMac, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, + centerChan) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not set " + "WNI_CFG_CHANNEL_BONDING_MODE at CFG")); + retCode = eSIR_LOGP_EXCEPTION; + goto free; + } + } + } + + } + psessionEntry->htSecondaryChannelOffset = limGetHTCBState(pSmeStartBssReq->cbMode); +#endif + } + else + { + PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) + retCode = eSIR_SME_INVALID_PARAMETERS; + goto free; + } + + // Delete pre-auth list if any + limDeletePreAuthList(pMac); + + psessionEntry->htCapability = IS_DOT11_MODE_HT(pSmeStartBssReq->dot11mode); + + /* keep the RSN/WPA IE information in PE Session Entry + * later will be using this to check when received (Re)Assoc req + * */ + limSetRSNieWPAiefromSmeStartBSSReqMessage(pMac,&pSmeStartBssReq->rsnIE,psessionEntry); + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) { + psessionEntry->gLimProtectionControl = pSmeStartBssReq->protEnabled; + /*each byte will have the following info + *bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 + *reserved reserved RIFS Lsig n-GF ht20 11g 11b*/ + vos_mem_copy( (void *) &psessionEntry->cfgProtection, + (void *) &pSmeStartBssReq->ht_capab, + sizeof( tANI_U16 )); + psessionEntry->pAPWPSPBCSession = NULL; // Initialize WPS PBC session link list + } + + // Prepare and Issue LIM_MLM_START_REQ to MLM + pMlmStartReq = vos_mem_malloc(sizeof(tLimMlmStartReq)); + if ( NULL == pMlmStartReq ) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for mlmStartReq")); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + + vos_mem_set((void *) pMlmStartReq, sizeof(tLimMlmStartReq), 0); + + /* Copy SSID to the MLM start structure */ + vos_mem_copy( (tANI_U8 *) &pMlmStartReq->ssId, + (tANI_U8 *) &pSmeStartBssReq->ssId, + pSmeStartBssReq->ssId.length + 1); + pMlmStartReq->ssidHidden = pSmeStartBssReq->ssidHidden; + pMlmStartReq->obssProtEnabled = pSmeStartBssReq->obssProtEnabled; + + + pMlmStartReq->bssType = psessionEntry->bssType; + + /* Fill PE session Id from the session Table */ + pMlmStartReq->sessionId = psessionEntry->peSessionId; + + if( (pMlmStartReq->bssType == eSIR_BTAMP_STA_MODE) || (pMlmStartReq->bssType == eSIR_BTAMP_AP_MODE ) + || (pMlmStartReq->bssType == eSIR_INFRA_AP_MODE) + ) + { + /* Copy the BSSId from sessionTable to mlmStartReq struct */ + sirCopyMacAddr(pMlmStartReq->bssId,psessionEntry->bssId); + } + + else // ibss mode + { + pMac->lim.gLimIbssCoalescingHappened = false; + + if((retStatus = wlan_cfgGetInt(pMac, WNI_CFG_IBSS_AUTO_BSSID, &autoGenBssId)) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not retrieve Auto Gen BSSID, retStatus=%d"), retStatus); + retCode = eSIR_LOGP_EXCEPTION; + goto free; + } + + if(!autoGenBssId) + { + // We're not auto generating BSSID. Instead, get it from session entry + sirCopyMacAddr(pMlmStartReq->bssId,psessionEntry->bssId); + + if(pMlmStartReq->bssId[0] & 0x01) + { + PELOGE(limLog(pMac, LOGE, FL("Request to start IBSS with group BSSID\n Autogenerating the BSSID"));) + autoGenBssId = TRUE; + } + } + + if( autoGenBssId ) + { //if BSSID is not any uc id. then use locally generated BSSID. + //Autogenerate the BSSID + limGetRandomBssid( pMac, pMlmStartReq->bssId); + pMlmStartReq->bssId[0]= 0x02; + + /* Copy randomly generated BSSID to the session Table */ + sirCopyMacAddr(psessionEntry->bssId,pMlmStartReq->bssId); + } + } + /* store the channel num in mlmstart req structure */ + pMlmStartReq->channelNumber = psessionEntry->currentOperChannel; + pMlmStartReq->cbMode = pSmeStartBssReq->cbMode; + pMlmStartReq->beaconPeriod = psessionEntry->beaconParams.beaconInterval; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + pMlmStartReq->dtimPeriod = psessionEntry->dtimPeriod; + pMlmStartReq->wps_state = psessionEntry->wps_state; + } else { + if (wlan_cfgGetInt(pMac, WNI_CFG_DTIM_PERIOD, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("could not retrieve DTIM Period")); + pMlmStartReq->dtimPeriod = (tANI_U8)val; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_PERIOD, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("could not retrieve Beacon interval")); + pMlmStartReq->cfParamSet.cfpPeriod = (tANI_U8)val; + + if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_MAX_DURATION, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("could not retrieve CFPMaxDuration")); + pMlmStartReq->cfParamSet.cfpMaxDuration = (tANI_U16) val; + + //this may not be needed anymore now, as rateSet is now included in the session entry and MLM has session context. + vos_mem_copy((void*)&pMlmStartReq->rateSet, (void*)&psessionEntry->rateSet, + sizeof(tSirMacRateSet)); + + // Now populate the 11n related parameters + pMlmStartReq->nwType = psessionEntry->nwType; + pMlmStartReq->htCapable = psessionEntry->htCapability; + // + // FIXME_GEN4 - Determine the appropriate defaults... + // + pMlmStartReq->htOperMode = pMac->lim.gHTOperMode; + pMlmStartReq->dualCTSProtection = pMac->lim.gHTDualCTSProtection; // Unused + pMlmStartReq->txChannelWidthSet = psessionEntry->htRecommendedTxWidthSet; + + psessionEntry->limRFBand = limGetRFBand(channelNumber); + + // Initialize 11h Enable Flag + psessionEntry->lim11hEnable = 0; + if((pMlmStartReq->bssType != eSIR_IBSS_MODE) && + (SIR_BAND_5_GHZ == psessionEntry->limRFBand) ) + { + if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); + psessionEntry->lim11hEnable = val; + + if (psessionEntry->lim11hEnable && + (eSIR_INFRA_AP_MODE == pMlmStartReq->bssType)) + { + if (wlan_cfgGetInt(pMac, WNI_CFG_DFS_MASTER_ENABLED, &val) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("Fail to get WNI_CFG_DFS_MASTER_ENABLED")); + } + psessionEntry->lim11hEnable = val; + } + } + + if (!psessionEntry->lim11hEnable) + { + if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, 0) != eSIR_SUCCESS) + limLog(pMac, LOGE, FL + ("Fail to set value for WNI_CFG_LOCAL_POWER_CONSTRAINT")); + } + + psessionEntry ->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry ->limSmeState = eLIM_SME_WT_START_BSS_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry ->limSmeState)); + + limPostMlmMessage(pMac, LIM_MLM_START_REQ, (tANI_U32 *) pMlmStartReq); + return; + } + else + { + + limLog(pMac, LOGE, FL("Received unexpected START_BSS_REQ, in state %X"),pMac->lim.gLimSmeState); + retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + goto end; + } // if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) + +free: + if ((psessionEntry != NULL) && + (psessionEntry->pLimStartBssReq == pSmeStartBssReq)) + { + psessionEntry->pLimStartBssReq = NULL; + } + vos_mem_free( pSmeStartBssReq); + vos_mem_free( pMlmStartReq); + +end: + + /* This routine should return the sme sessionId and SME transaction Id */ + limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf,&smesessionId,&smetransactionId); + + if(NULL != psessionEntry) + { + peDeleteSession(pMac,psessionEntry); + psessionEntry = NULL; + } + limSendSmeStartBssRsp(pMac, eWNI_SME_START_BSS_RSP, retCode,psessionEntry,smesessionId,smetransactionId); +} /*** end __limHandleSmeStartBssRequest() ***/ + + +/**-------------------------------------------------------------- +\fn __limProcessSmeStartBssReq + +\brief Wrapper for the function __limHandleSmeStartBssRequest + This message will be defered until softmac come out of + scan mode or if we have detected radar on the current + operating channel. +\param pMac +\param pMsg + +\return TRUE - If we consumed the buffer + FALSE - If have defered the message. + ---------------------------------------------------------------*/ +static tANI_BOOLEAN +__limProcessSmeStartBssReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + if (__limIsDeferedMsgForLearn(pMac, pMsg) || + __limIsDeferedMsgForRadar(pMac, pMsg)) + { + /** + * If message defered, buffer is not consumed yet. + * So return false + */ + return eANI_BOOLEAN_FALSE; + } + + __limHandleSmeStartBssRequest(pMac, (tANI_U32 *) pMsg->bodyptr); + return eANI_BOOLEAN_TRUE; +} + + +/** + * limGetRandomBssid() + * + * FUNCTION:This function is called to process generate the random number for bssid + * This function is called to process SME_SCAN_REQ message + * from HDD or upper layer application. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * 1. geneartes the unique random number for bssid in ibss + * + * @param pMac Pointer to Global MAC structure + * @param *data Pointer to bssid buffer + * @return None + */ +void limGetRandomBssid(tpAniSirGlobal pMac, tANI_U8 *data) +{ + tANI_U32 random[2] ; + random[0] = tx_time_get(); + random[0] |= (random[0] << 15) ; + random[1] = random[0] >> 1; + vos_mem_copy( data, (tANI_U8*)random, sizeof(tSirMacAddr)); +} + +static eHalStatus limSendHalStartScanOffloadReq(tpAniSirGlobal pMac, + tpSirSmeScanReq pScanReq) +{ + tSirScanOffloadReq *pScanOffloadReq; + tANI_U8 *p; + tANI_U8 *ht_cap_ie; + tSirMsgQ msg; + tANI_U16 i, len; + tANI_U16 ht_cap_len = 0, addn_ie_len = 0; +#ifdef WLAN_FEATURE_11AC + tANI_U8 *vht_cap_ie; + tANI_U16 vht_cap_len = 0; +#endif /* WLAN_FEATURE_11AC */ + tSirRetStatus status, rc = eSIR_SUCCESS; + tDot11fIEExtCap extracted_extcap = {0}; + bool extcap_present = true; + + pMac->lim.fOffloadScanPending = 0; + pMac->lim.fOffloadScanP2PSearch = 0; + + if (pScanReq->uIEFieldLen) { + status = lim_strip_extcap_update_struct(pMac, + (uint8_t *) pScanReq + pScanReq->uIEFieldOffset, + &pScanReq->uIEFieldLen, &extracted_extcap); + + if (eSIR_SUCCESS != status) { + extcap_present = false; + limLog(pMac, LOG1, FL("Unable to Strip ExtCap IE from Scan Req")); + } + + if (extcap_present) { + limLog(pMac, LOG1, FL("Extcap was part of SCAN IE - Updating FW")); + lim_send_ext_cap_ie(pMac, pScanReq->sessionId, + &extracted_extcap, true); + } + } else { + limLog(pMac, LOG1, FL("No IEs in the scan request from supplicant")); + } + + /* The tSirScanOffloadReq will reserve the space for first channel, + so allocate the memory for (numChannels - 1) and uIEFieldLen */ + len = sizeof(tSirScanOffloadReq) + (pScanReq->channelList.numChannels - 1) + + pScanReq->uIEFieldLen; + + if (!pMac->per_band_chainmask_supp) { + if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { + limLog(pMac, LOG1, + FL("Adding HT Caps IE since dot11mode=%d"), + pScanReq->dot11mode); + ht_cap_len = 2 + sizeof(tHtCaps); /* 2 bytes for EID and Length */ + len += ht_cap_len; + addn_ie_len += ht_cap_len; + } + +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) { + limLog(pMac, LOG1, + FL("Adding VHT Caps IE since dot11mode=%d"), + pScanReq->dot11mode); + /* 2 bytes for EID and Length */ + vht_cap_len = 2 + sizeof(tSirMacVHTCapabilityInfo) + + sizeof(tSirVhtMcsInfo); + len += vht_cap_len; + addn_ie_len += vht_cap_len; + } +#endif /* WLAN_FEATURE_11AC */ + } + + pScanOffloadReq = vos_mem_malloc(len); + if ( NULL == pScanOffloadReq ) + { + limLog(pMac, LOGE, + FL("AllocateMemory failed for pScanOffloadReq")); + return eHAL_STATUS_FAILURE; + } + + vos_mem_set( (tANI_U8 *) pScanOffloadReq, len, 0); + + msg.type = WDA_START_SCAN_OFFLOAD_REQ; + msg.bodyptr = pScanOffloadReq; + msg.bodyval = 0; + + vos_mem_copy((tANI_U8 *) pScanOffloadReq->bssId, + (tANI_U8*) pScanReq->bssId, + sizeof(tSirMacAddr)); + + if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) + { + limLog(pMac, LOGE, + FL("Invalid value (%d) for numSsid"), SIR_SCAN_MAX_NUM_SSID); + vos_mem_free (pScanOffloadReq); + return eHAL_STATUS_FAILURE; + } + + pScanOffloadReq->numSsid = pScanReq->numSsid; + for (i = 0; i < pScanOffloadReq->numSsid; i++) + { + pScanOffloadReq->ssId[i].length = pScanReq->ssId[i].length; + vos_mem_copy((tANI_U8 *) pScanOffloadReq->ssId[i].ssId, + (tANI_U8 *) pScanReq->ssId[i].ssId, + pScanOffloadReq->ssId[i].length); + } + + pScanOffloadReq->hiddenSsid = pScanReq->hiddenSsid; + vos_mem_copy((tANI_U8 *) pScanOffloadReq->selfMacAddr, + (tANI_U8 *) pScanReq->selfMacAddr, + sizeof(tSirMacAddr)); + pScanOffloadReq->bssType = pScanReq->bssType; + pScanOffloadReq->dot11mode = pScanReq->dot11mode; + pScanOffloadReq->scanType = pScanReq->scanType; + pScanOffloadReq->minChannelTime = pScanReq->minChannelTime; + pScanOffloadReq->maxChannelTime = pScanReq->maxChannelTime; + pScanOffloadReq->restTime= pScanReq->restTime; + pScanOffloadReq->min_rest_time= pScanReq->min_rest_time; + pScanOffloadReq->idle_time= pScanReq->idle_time; + + + /* for normal scan, the value for p2pScanType should be 0 + always */ + if (pScanReq->p2pSearch) + pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_SEARCH; + + pScanOffloadReq->sessionId = pScanReq->sessionId; + + if (pScanOffloadReq->sessionId >= pMac->lim.maxBssId) + limLog(pMac, LOGE, FL("Invalid pe sessionID : %d"), + pScanOffloadReq->sessionId); + + pScanOffloadReq->channelList.numChannels = + pScanReq->channelList.numChannels; + p = &(pScanOffloadReq->channelList.channelNumber[0]); + for (i = 0; i < pScanOffloadReq->channelList.numChannels; i++) + p[i] = pScanReq->channelList.channelNumber[i]; + + pScanOffloadReq->uIEFieldLen = pScanReq->uIEFieldLen; + pScanOffloadReq->uIEFieldOffset = len - addn_ie_len - + pScanOffloadReq->uIEFieldLen; + vos_mem_copy( + (tANI_U8 *) pScanOffloadReq + pScanOffloadReq->uIEFieldOffset, + (tANI_U8 *) pScanReq + pScanReq->uIEFieldOffset, + pScanReq->uIEFieldLen); + + if (!pMac->per_band_chainmask_supp) { + /* Copy HT Capability info if dot11mode is HT */ + if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { + /* Populate EID and Length field here */ + ht_cap_ie = (tANI_U8 *) pScanOffloadReq + + pScanOffloadReq->uIEFieldOffset + + pScanOffloadReq->uIEFieldLen; + vos_mem_set(ht_cap_ie, ht_cap_len, 0); + *ht_cap_ie = SIR_MAC_HT_CAPABILITIES_EID; + *(ht_cap_ie + 1) = ht_cap_len - 2; + lim_set_ht_caps(pMac, NULL, ht_cap_ie, ht_cap_len); + pScanOffloadReq->uIEFieldLen += ht_cap_len; + } + +#ifdef WLAN_FEATURE_11AC + /* Copy VHT Capability info if dot11mode is VHT Capable */ + if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) { + /* Populate EID and Length field here */ + vht_cap_ie = (tANI_U8 *) pScanOffloadReq + + pScanOffloadReq->uIEFieldOffset + + pScanOffloadReq->uIEFieldLen; + vos_mem_set(vht_cap_ie, vht_cap_len, 0); + *vht_cap_ie = SIR_MAC_VHT_CAPABILITIES_EID; + *(vht_cap_ie + 1) = vht_cap_len - 2; + lim_set_vht_caps(pMac, NULL, vht_cap_ie, vht_cap_len); + pScanOffloadReq->uIEFieldLen += vht_cap_len; + } +#endif /* WLAN_FEATURE_11AC */ + } + + rc = wdaPostCtrlMsg(pMac, &msg); + if (rc != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("wdaPostCtrlMsg() return failure")); + vos_mem_free(pScanOffloadReq); + return eHAL_STATUS_FAILURE; + } + + pMac->lim.fOffloadScanPending = 1; + if (pScanReq->p2pSearch) + pMac->lim.fOffloadScanP2PSearch = 1; + + limLog(pMac, LOG1, FL("Processed Offload Scan Request Successfully")); + + return eHAL_STATUS_SUCCESS; +} + +/** + * __limProcessSmeScanReq() + * + *FUNCTION: + * This function is called to process SME_SCAN_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * 1. Periodic scanning should be requesting to return unique + * scan results. + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U32 len; + tLimMlmScanReq *pMlmScanReq; + tpSirSmeScanReq pScanReq; + tANI_U8 i = 0; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_SCAN_REQ_EVENT, NULL, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + + pScanReq = (tpSirSmeScanReq) pMsgBuf; + limLog(pMac, LOG1,FL("SME SCAN REQ numChan %d min %d max %d IELen %d" + "first %d fresh %d unique %d type %s (%d)" + " mode %s (%d)rsp %d"), + pScanReq->channelList.numChannels, + pScanReq->minChannelTime, + pScanReq->maxChannelTime, + pScanReq->uIEFieldLen, + pScanReq->returnAfterFirstMatch, + pScanReq->returnFreshResults, + pScanReq->returnUniqueResults, + lim_ScanTypetoString(pScanReq->scanType), + pScanReq->scanType, + lim_BackgroundScanModetoString(pScanReq->backgroundScanMode), + pScanReq->backgroundScanMode, pMac->lim.gLimRspReqd ? 1 : 0); + + + /* Since scan req always requires a response, we will overwrite response required here. + * This is added esp to take care of the condition where in p2p go case, we hold the scan req and + * insert single NOA. We send the held scan request to FW later on getting start NOA ind from FW so + * we lose state of the gLimRspReqd flag for the scan req if any other request comes by then. + * e.g. While unit testing, we found when insert single NOA is done, we see a get stats request which turns the flag + * gLimRspReqd to FALSE; now when we actually start the saved scan req for init scan after getting + * NOA started, the gLimRspReqd being a global flag is showing FALSE instead of TRUE value for + * this saved scan req. Since all scan reqs coming to lim require a response, there is no harm in setting + * the global flag gLimRspReqd to TRUE here. + */ + pMac->lim.gLimRspReqd = TRUE; + + /*copy the Self MAC address from SmeReq to the globalplace, used for sending probe req*/ + sirCopyMacAddr(pMac->lim.gSelfMacAddr, pScanReq->selfMacAddr); + + /* This routine should return the sme sessionId and SME transaction Id */ + + if (!limIsSmeScanReqValid(pMac, pScanReq)) + { + limLog(pMac, LOGE, FL("Received SME_SCAN_REQ with invalid parameters")); + + if (pMac->lim.gLimRspReqd) + { + pMac->lim.gLimRspReqd = false; + + limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_INVALID_PARAMETERS, pScanReq->sessionId, pScanReq->transactionId); + + } // if (pMac->lim.gLimRspReqd) + + return; + } + + /* + * if scan is disabled then return as invalid scan request. + * if scan in power save is disabled, and system is in power save mode, + * then ignore scan request. + */ + if((pMac->lim.fScanDisabled) || + (!pMac->psOffloadEnabled && + !pMac->lim.gScanInPowersave && + !limIsSystemInActiveState(pMac))) + { + limLog(pMac, LOGE, FL("SCAN is disabled or SCAN in power save" + " is disabled and system is in power save.")); + + limSendSmeScanRsp(pMac, offsetof(tSirSmeScanRsp,bssDescription[0]), eSIR_SME_INVALID_PARAMETERS, pScanReq->sessionId, pScanReq->transactionId); + return; + } + + /* Clear P2P scan entries before starting any scan */ + if (pMac->fScanOffload) + limFlushp2pScanResults(pMac); + + /** + * If scan request is received in idle, joinFailed + * states or in link established state (in STA role) + * or in normal state (in STA-in-IBSS/AP role) with + * 'return fresh scan results' request from HDD or + * it is periodic background scanning request, + * trigger fresh scan request to MLM + */ + if (__limFreshScanReqd(pMac, pScanReq->returnFreshResults)) + { + limLog(pMac, LOG1, FL("Fresh scan is required")); + + if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS) + { + // Discard previously cached scan results + limReInitScanResults(pMac); + } + + pMac->lim.gLim24Band11dScanDone = 0; + pMac->lim.gLim50Band11dScanDone = 0; + pMac->lim.gLimReturnAfterFirstMatch = + pScanReq->returnAfterFirstMatch; + pMac->lim.gLimBackgroundScanMode = + pScanReq->backgroundScanMode; + + pMac->lim.gLimReturnUniqueResults = + ((pScanReq->returnUniqueResults) > 0 ? true : false); + + if (pMac->psOffloadEnabled) + { + if ((pMac->lim.gLimBackgroundScanMode != eSIR_ROAMING_SCAN) && + (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + for (i=0;ilim.maxBssId;i++) + { + tpPESession psessionEntry = peFindSessionBySessionId(pMac,i); + if (psessionEntry && psessionEntry->valid && + (eLIM_MLM_LINK_ESTABLISHED_STATE == + psessionEntry->limMlmState) && + (psessionEntry->pmmOffloadInfo.psstate == PMM_FULL_POWER)) + { + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + } + } + } + } + /* De-activate Heartbeat timers for connected sessions while + * scan is in progress if the system is in Active mode * + * AND it is not a ROAMING ("background") scan */ + else if (((ePMM_STATE_BMPS_WAKEUP == pMac->pmm.gPmmState) || + (ePMM_STATE_READY == pMac->pmm.gPmmState)) && + (pScanReq->backgroundScanMode != eSIR_ROAMING_SCAN ) && + (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + for(i=0;ilim.maxBssId;i++) + { + if((peFindSessionBySessionId(pMac,i) != NULL) && + (pMac->lim.gpSession[i].valid == TRUE) && + (eLIM_MLM_LINK_ESTABLISHED_STATE == pMac->lim.gpSession[i].limMlmState)) + { + limHeartBeatDeactivateAndChangeTimer(pMac, peFindSessionBySessionId(pMac,i)); + } + } + } + + if (pMac->fScanOffload) + { + if (eHAL_STATUS_SUCCESS != + limSendHalStartScanOffloadReq(pMac, pScanReq)) + { + limLog(pMac, LOGE, FL("Couldn't send Offload scan request")); + limSendSmeScanRsp(pMac, + offsetof(tSirSmeScanRsp, bssDescription[0]), + eSIR_SME_INVALID_PARAMETERS, + pScanReq->sessionId, + pScanReq->transactionId); + return; + } + } + else + { + + /*Change Global SME state */ + /* Store the previous SME state */ + limLog(pMac, LOG1, FL("Non Offload SCAN request ")); + pMac->lim.gLimPrevSmeState = pMac->lim.gLimSmeState; + pMac->lim.gLimSmeState = eLIM_SME_WT_SCAN_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, pScanReq->sessionId, pMac->lim.gLimSmeState)); + + if (pScanReq->channelList.numChannels == 0) + { + tANI_U32 cfg_len; + + limLog(pMac, LOG1, + FL("Scan all channels as Number of channels is 0")); + + // Scan all channels + len = sizeof(tLimMlmScanReq) + + (sizeof( pScanReq->channelList.channelNumber ) * (WNI_CFG_VALID_CHANNEL_LIST_LEN - 1)) + + pScanReq->uIEFieldLen; + pMlmScanReq = vos_mem_malloc(len); + if ( NULL == pMlmScanReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmScanReq (%d)"), len); + + return; + } + + // Initialize this buffer + vos_mem_set( (tANI_U8 *) pMlmScanReq, len, 0 ); + + cfg_len = WNI_CFG_VALID_CHANNEL_LIST_LEN; + if (wlan_cfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + pMlmScanReq->channelList.channelNumber, + &cfg_len) != eSIR_SUCCESS) + { + /** + * Could not get Valid channel list from CFG. + * Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Valid channel list")); + } + pMlmScanReq->channelList.numChannels = (tANI_U8) cfg_len; + } + else + { + len = sizeof( tLimMlmScanReq ) - sizeof( pScanReq->channelList.channelNumber ) + + (sizeof( pScanReq->channelList.channelNumber ) * pScanReq->channelList.numChannels ) + + pScanReq->uIEFieldLen; + + pMlmScanReq = vos_mem_malloc(len); + if ( NULL == pMlmScanReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmScanReq(%d)"), len); + + return; + } + + // Initialize this buffer + vos_mem_set( (tANI_U8 *) pMlmScanReq, len, 0); + if (pScanReq->channelList.numChannels <= SIR_ESE_MAX_MEAS_IE_REQS) + { + pMlmScanReq->channelList.numChannels = + pScanReq->channelList.numChannels; + } + else + { + limLog(pMac, LOGE, + FL("numChannels is more than the size(%d)"), + pScanReq->channelList.numChannels); + pMlmScanReq->channelList.numChannels = + SIR_ESE_MAX_MEAS_IE_REQS; + } + + vos_mem_copy( pMlmScanReq->channelList.channelNumber, + pScanReq->channelList.channelNumber, + pMlmScanReq->channelList.numChannels); + } + + pMlmScanReq->uIEFieldLen = pScanReq->uIEFieldLen; + pMlmScanReq->uIEFieldOffset = len - pScanReq->uIEFieldLen; + if(pScanReq->uIEFieldLen) + { + vos_mem_copy( (tANI_U8 *)pMlmScanReq+ pMlmScanReq->uIEFieldOffset, + (tANI_U8 *)pScanReq+(pScanReq->uIEFieldOffset), + pScanReq->uIEFieldLen); + } + + pMlmScanReq->bssType = pScanReq->bssType; + vos_mem_copy( pMlmScanReq->bssId, + pScanReq->bssId, + sizeof(tSirMacAddr)); + pMlmScanReq->numSsid = pScanReq->numSsid; + pMlmScanReq->sessionId = pScanReq->sessionId; + + i = 0; + while (i < pMlmScanReq->numSsid) + { + vos_mem_copy( (tANI_U8 *) &pMlmScanReq->ssId[i], + (tANI_U8 *) &pScanReq->ssId[i], + pScanReq->ssId[i].length + 1); + + i++; + } + + + pMlmScanReq->scanType = pScanReq->scanType; + pMlmScanReq->backgroundScanMode = pScanReq->backgroundScanMode; + pMlmScanReq->minChannelTime = pScanReq->minChannelTime; + pMlmScanReq->maxChannelTime = pScanReq->maxChannelTime; + pMlmScanReq->minChannelTimeBtc = pScanReq->minChannelTimeBtc; + pMlmScanReq->maxChannelTimeBtc = pScanReq->maxChannelTimeBtc; + pMlmScanReq->dot11mode = pScanReq->dot11mode; + pMlmScanReq->p2pSearch = pScanReq->p2pSearch; + + //Store the smeSessionID and transaction ID for later use. + pMac->lim.gSmeSessionId = pScanReq->sessionId; + pMac->lim.gTransactionId = pScanReq->transactionId; + + // Issue LIM_MLM_SCAN_REQ to MLM + limLog(pMac, LOG1, FL("Issue Scan request command to MLM ")); + limPostMlmMessage(pMac, LIM_MLM_SCAN_REQ, (tANI_U32 *) pMlmScanReq); + } + } // if ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ... + + else + { + /// In all other cases return 'cached' scan results + if ((pMac->lim.gLimRspReqd) || pMac->lim.gLimReportBackgroundScanResults) + { + tANI_U16 scanRspLen = sizeof(tSirSmeScanRsp); + + pMac->lim.gLimRspReqd = false; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pScanReq->returnFreshResults & SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS) + { + pMac->lim.gLimSmeLfrScanResultLength = pMac->lim.gLimMlmLfrScanResultLength; + limLog(pMac, LOG1, + FL("Returned scan results from LFR cache, length = %d"), + pMac->lim.gLimSmeLfrScanResultLength); + + if (pMac->lim.gLimSmeLfrScanResultLength == 0) + { + limSendSmeLfrScanRsp(pMac, scanRspLen, + eSIR_SME_SUCCESS, + pScanReq->sessionId, + pScanReq->transactionId); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeLfrScanResultLength - + sizeof(tSirBssDescription); + limSendSmeLfrScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } + } + else + { +#endif + limLog(pMac, LOG1, + FL("Returned scan results from normal cache, length = %d"), + pMac->lim.gLimSmeScanResultLength); + if (pMac->lim.gLimSmeScanResultLength == 0) + { + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeScanResultLength - + sizeof(tSirBssDescription); + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + limLog(pMac, LOG1, FL("Cached scan results are returned ")); + + if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS) + { + // Discard previously cached scan results + limReInitScanResults(pMac); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_LFR_RESULTS) + { + // Discard previously cached scan results + limReInitLfrScanResults(pMac); + } +#endif + + } // if (pMac->lim.gLimRspReqd) + } // else ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ... + +#ifdef BACKGROUND_SCAN_ENABLED + // start background scans if needed + // There is a bug opened against softmac. Need to enable when the bug is fixed. + __limBackgroundScanInitiate(pMac); +#endif + +} /*** end __limProcessSmeScanReq() ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +static void __limProcessSmeOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirOemDataReq pOemDataReq; + tLimMlmOemDataReq* pMlmOemDataReq; + + pOemDataReq = (tpSirOemDataReq) pMsgBuf; + + //post the lim mlm message now + pMlmOemDataReq = vos_mem_malloc(sizeof(tLimMlmOemDataReq)); + if ( NULL == pMlmOemDataReq ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for mlmOemDataReq")); + return; + } + + //Initialize this buffer + vos_mem_set( pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)), 0); + + vos_mem_copy( pMlmOemDataReq->selfMacAddr, pOemDataReq->selfMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy( pMlmOemDataReq->oemDataReq, pOemDataReq->oemDataReq, + OEM_DATA_REQ_SIZE); + + //Issue LIM_MLM_OEM_DATA_REQ to MLM + limPostMlmMessage(pMac, LIM_MLM_OEM_DATA_REQ, (tANI_U32*)pMlmOemDataReq); + + return; + +} /*** end __limProcessSmeOemDataReq() ***/ + +#endif //FEATURE_OEM_DATA_SUPPORT + +/** + * __limProcessClearDfsChannelList() + * + *FUNCTION: + *Clear DFS channel list when country is changed/aquired. +.*This message is sent from SME. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void __limProcessClearDfsChannelList(tpAniSirGlobal pMac, + tpSirMsgQ pMsg) +{ + vos_mem_set( &pMac->lim.dfschannelList, + sizeof(tSirDFSChannelList), 0); +} + +/** + * __limProcessSmeJoinReq() + * + *FUNCTION: + * This function is called to process SME_JOIN_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + // tANI_U8 *pBuf; + //tANI_U32 len; +// tSirMacAddr currentBssId; + tpSirSmeJoinReq pSmeJoinReq = NULL; + tLimMlmJoinReq *pMlmJoinReq; + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tANI_U32 val = 0; + tANI_U16 nSize; + tANI_U8 sessionId; + tpPESession psessionEntry = NULL; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + tPowerdBm localPowerConstraint = 0, regMax = 0; + tANI_U16 ieLen; + v_U8_t *vendorIE; + struct vdev_type_nss *vdev_type_nss; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + //Not sending any session, since it is not created yet. The response whould have correct state. + limDiagEventReport(pMac, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + PELOG1(limLog(pMac, LOG1, FL("Received SME_JOIN_REQ"));) + + /** + * Expect Join request in idle state. + * Reassociate request is expected in link established state. + */ + + /* Global SME and LIM states are not defined yet for BT-AMP Support */ + if(pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) + { + nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8*) pMsgBuf); + + pSmeJoinReq = vos_mem_malloc(nSize); + if ( NULL == pSmeJoinReq ) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for " + "pSmeJoinReq")); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + (void) vos_mem_set((void *) pSmeJoinReq, nSize, 0); + + if ((limJoinReqSerDes(pMac, pSmeJoinReq, (tANI_U8 *)pMsgBuf) == eSIR_FAILURE) || + (!limIsSmeJoinReqValid(pMac, pSmeJoinReq))) + { + /// Received invalid eWNI_SME_JOIN_REQ + // Log the event + limLog(pMac, LOGW, FL("SessionId:%d Received SME_JOIN_REQ with invalid data"), + pSmeJoinReq->sessionId); + retCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + /* + * Update the capability here itself as this is used in + * limExtractAPCapability() below. If not updated issues like not + * honoring power constraint on 1st association after driver loading + * might occur. + */ + lim_update_rrm_capability(pMac, pSmeJoinReq); + + /* check for the existence of start BSS session */ + + if((psessionEntry = peFindSessionByBssid(pMac,pSmeJoinReq->bssDescription.bssId,&sessionId)) != NULL) + { + limLog(pMac, LOGE, FL("Session(%d) Already exists for BSSID: " + MAC_ADDRESS_STR" in limSmeState = %X"),sessionId, + MAC_ADDR_ARRAY(pSmeJoinReq->bssDescription.bssId), + psessionEntry->limSmeState); + + if(psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE && + psessionEntry->smeSessionId == pSmeJoinReq->sessionId) + { + // Received eWNI_SME_JOIN_REQ for same + // BSS as currently associated. + // Log the event and send success + PELOGW(limLog(pMac, LOGW, FL("SessionId:%d Received SME_JOIN_REQ for currently joined BSS"), + sessionId);) + /// Send Join success response to host + retCode = eSIR_SME_ALREADY_JOINED_A_BSS; + psessionEntry = NULL; + goto end; + } + else + { + PELOGE(limLog(pMac, LOGE, FL("SME_JOIN_REQ not for" + "currently joined BSS"));) + retCode = eSIR_SME_REFUSED; + psessionEntry = NULL; + goto end; + } + } + else /* Session Entry does not exist for given BSSId */ + { + /* Try to Create a new session */ + if((psessionEntry = peCreateSession(pMac, + pSmeJoinReq->bssDescription.bssId, + &sessionId, + pMac->lim.maxStation, + eSIR_INFRASTRUCTURE_MODE )) == NULL) + { + limLog(pMac, LOGE, FL("Session Can not be created ")); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + else + limLog(pMac,LOG1,FL("SessionId:%d New session created"), + sessionId); + } + psessionEntry->max_amsdu_num = pSmeJoinReq->max_amsdu_num; + + /* Store Session related parameters */ + /* Store PE session Id in session Table */ + psessionEntry->peSessionId = sessionId; + + /* store the smejoin req handle in session table */ + psessionEntry->pLimJoinReq = pSmeJoinReq; + + /* Store SME session Id in sessionTable */ + psessionEntry->smeSessionId = pSmeJoinReq->sessionId; + + /* Store SME transaction Id in session Table */ + psessionEntry->transactionId = pSmeJoinReq->transactionId; + + /* Store beaconInterval */ + psessionEntry->beaconParams.beaconInterval = pSmeJoinReq->bssDescription.beaconInterval; + + vos_mem_copy(&(psessionEntry->htConfig), &(pSmeJoinReq->htConfig), + sizeof(psessionEntry->htConfig)); + + /* Copying of bssId is already done, while creating session */ + sirCopyMacAddr(psessionEntry->selfMacAddr,pSmeJoinReq->selfMacAddr); + psessionEntry->bssType = pSmeJoinReq->bsstype; + + psessionEntry->statypeForBss = STA_ENTRY_PEER; + psessionEntry->limWmeEnabled = pSmeJoinReq->isWMEenabled; + psessionEntry->limQosEnabled = pSmeJoinReq->isQosEnabled; + + /* Store vendor specfic IE for CISCO AP */ + ieLen = (pSmeJoinReq->bssDescription.length + + sizeof( pSmeJoinReq->bssDescription.length ) - + GET_FIELD_OFFSET( tSirBssDescription, ieFields )); + + vendorIE = cfg_get_vendor_ie_ptr_from_oui(pMac, SIR_MAC_CISCO_OUI, + SIR_MAC_CISCO_OUI_SIZE, + ((tANI_U8 *)&pSmeJoinReq->bssDescription.ieFields) , ieLen); + + if (NULL != vendorIE) { + limLog(pMac, LOG1, FL("Cisco vendor OUI present")); + psessionEntry->isCiscoVendorAP = TRUE; + } else { + psessionEntry->isCiscoVendorAP = FALSE; + } + + /* Copy the dot 11 mode in to the session table */ + + psessionEntry->dot11mode = pSmeJoinReq->dot11mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + psessionEntry->cc_switch_mode = pSmeJoinReq->cc_switch_mode; +#endif + psessionEntry->nwType = pSmeJoinReq->bssDescription.nwType; + psessionEntry->enableAmpduPs = pSmeJoinReq->enableAmpduPs; + psessionEntry->enableHtSmps = pSmeJoinReq->enableHtSmps; + psessionEntry->htSmpsvalue = pSmeJoinReq->htSmps; + + limLog(pMac, LOG1, FL("enableHtSmps: %d htSmps: %d"), + psessionEntry->enableHtSmps, + psessionEntry->htSmpsvalue); + + /*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); + /* Copy The channel Id to the session Table */ + psessionEntry->currentOperChannel = + pSmeJoinReq->bssDescription.channelId; + if (IS_5G_CH(psessionEntry->currentOperChannel)) + vdev_type_nss = &pMac->vdev_type_nss_5g; + else + vdev_type_nss = &pMac->vdev_type_nss_2g; + if (psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) + psessionEntry->vdev_nss = vdev_type_nss->p2p_cli; + else + psessionEntry->vdev_nss = vdev_type_nss->sta; + + limLog(pMac, LOG1, FL("persona - %d, nss - %d"), + psessionEntry->pePersona, psessionEntry->vdev_nss); +#ifdef WLAN_FEATURE_11AC + psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(psessionEntry->dot11mode); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, + "***__limProcessSmeJoinReq: vhtCapability=%d****",psessionEntry->vhtCapability); + if (psessionEntry->vhtCapability ) + { + if (psessionEntry->pePersona == VOS_STA_MODE) + { + psessionEntry->txBFIniFeatureEnabled = pSmeJoinReq->txBFIniFeatureEnabled; + } + else + { + psessionEntry->txBFIniFeatureEnabled = 0; + } + psessionEntry->txMuBformee = pSmeJoinReq->txMuBformee; + psessionEntry->enableVhtpAid = pSmeJoinReq->enableVhtpAid; + psessionEntry->enableVhtGid = pSmeJoinReq->enableVhtGid; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, + "***__limProcessSmeJoinReq: txBFIniFeatureEnabled=%d****", + psessionEntry->txBFIniFeatureEnabled); + + if( psessionEntry->txBFIniFeatureEnabled ) + { + if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, psessionEntry->txBFIniFeatureEnabled) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not set " + "WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); + retCode = eSIR_LOGP_EXCEPTION; + goto end; + } + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, + "***__limProcessSmeJoinReq: txBFCsnValue=%d****", + pSmeJoinReq->txBFCsnValue); + + if (cfgSetInt(pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, pSmeJoinReq->txBFCsnValue) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not set " + "WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG")); + retCode = eSIR_LOGP_EXCEPTION; + goto end; + } + } + } + +#endif + + /*Phy mode*/ + psessionEntry->gLimPhyMode = pSmeJoinReq->bssDescription.nwType; + handleHTCapabilityandHTInfo(pMac, psessionEntry); + 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; + + /* Record if management frames need to be protected */ +#ifdef WLAN_FEATURE_11W + if(eSIR_ED_AES_128_CMAC == pSmeJoinReq->MgmtEncryptionType) + { + VOS_STATUS vosStatus; + psessionEntry->limRmfEnabled = 1; + /* + * For STA profile only: + * init pmf comeback timer and info struct only if PMF connection + */ + psessionEntry->pmfComebackTimerInfo.pMac = pMac; + psessionEntry->pmfComebackTimerInfo.sessionID = sessionId; + vosStatus = vos_timer_init(&psessionEntry->pmfComebackTimer, + VOS_TIMER_TYPE_SW, + limPmfComebackTimerCallback, + (void*)&psessionEntry->pmfComebackTimerInfo); + if (VOS_STATUS_SUCCESS != vosStatus) { + limLog(pMac, LOGP, + FL("cannot init pmf comeback timer.")); + retCode = eSIR_LOGP_EXCEPTION; + goto end; + } + } + else + { + psessionEntry->limRmfEnabled = 0; + } +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + psessionEntry->rssi = pSmeJoinReq->bssDescription.rssi; +#endif + + + /* Copy the SSID from smejoinreq to session entry */ + psessionEntry->ssId.length = pSmeJoinReq->ssId.length; + vos_mem_copy( psessionEntry->ssId.ssId, + pSmeJoinReq->ssId.ssId, psessionEntry->ssId.length); + + // Determin 11r or ESE connection based on input from SME + // which inturn is dependent on the profile the user wants to connect + // to, So input is coming from supplicant +#ifdef WLAN_FEATURE_VOWIFI_11R + psessionEntry->is11Rconnection = pSmeJoinReq->is11Rconnection; +#endif +#ifdef FEATURE_WLAN_ESE + psessionEntry->isESEconnection = pSmeJoinReq->isESEconnection; +#endif +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + psessionEntry->isFastTransitionEnabled = pSmeJoinReq->isFastTransitionEnabled; +#endif + +#ifdef FEATURE_WLAN_LFR + psessionEntry->isFastRoamIniFeatureEnabled = pSmeJoinReq->isFastRoamIniFeatureEnabled; +#endif + psessionEntry->txLdpcIniFeatureEnabled = pSmeJoinReq->txLdpcIniFeatureEnabled; + + if (psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) + { + psessionEntry->limSystemRole = eLIM_STA_ROLE; + } + else if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) + { + psessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; + } + else + { + /* Throw an error and return and make sure to delete the session.*/ + limLog(pMac, LOGE, FL("received SME_JOIN_REQ with invalid" + " bss type %d"), psessionEntry->bssType); + retCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + if (pSmeJoinReq->addIEScan.length) + { + vos_mem_copy( &psessionEntry->pLimJoinReq->addIEScan, + &pSmeJoinReq->addIEScan, sizeof(tSirAddie)); + } + + if (pSmeJoinReq->addIEAssoc.length) + { + vos_mem_copy( &psessionEntry->pLimJoinReq->addIEAssoc, + &pSmeJoinReq->addIEAssoc, sizeof(tSirAddie)); + } + + val = sizeof(tLimMlmJoinReq) + psessionEntry->pLimJoinReq->bssDescription.length + 2; + pMlmJoinReq = vos_mem_malloc(val); + if ( NULL == pMlmJoinReq ) + { + limLog(pMac, LOGP, FL("call to AllocateMemory " + "failed for mlmJoinReq")); + return; + } + (void) vos_mem_set((void *) pMlmJoinReq, val, 0); + + /* PE SessionId is stored as a part of JoinReq*/ + pMlmJoinReq->sessionId = psessionEntry->peSessionId; + + if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, (tANI_U32 *) &pMlmJoinReq->joinFailureTimeout) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not retrieve JoinFailureTimer value" + " setting to default value")); + pMlmJoinReq->joinFailureTimeout = + WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF; + } + /* copy operational rate from psessionEntry*/ + vos_mem_copy((void*)&psessionEntry->rateSet, (void*)&pSmeJoinReq->operationalRateSet, + sizeof(tSirMacRateSet)); + vos_mem_copy((void*)&psessionEntry->extRateSet, (void*)&pSmeJoinReq->extendedRateSet, + sizeof(tSirMacRateSet)); + //this may not be needed anymore now, as rateSet is now included in the session entry and MLM has session context. + vos_mem_copy((void*)&pMlmJoinReq->operationalRateSet, (void*)&psessionEntry->rateSet, + sizeof(tSirMacRateSet)); + + psessionEntry->encryptType = pSmeJoinReq->UCEncryptionType; + + pMlmJoinReq->bssDescription.length = psessionEntry->pLimJoinReq->bssDescription.length; + + vos_mem_copy((tANI_U8 *) &pMlmJoinReq->bssDescription.bssId, + (tANI_U8 *) &psessionEntry->pLimJoinReq->bssDescription.bssId, + psessionEntry->pLimJoinReq->bssDescription.length + 2); + + psessionEntry->limCurrentBssCaps = + psessionEntry->pLimJoinReq->bssDescription.capabilityInfo; + + regMax = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); + + if(!pMac->psOffloadEnabled) + { + limExtractApCapability( pMac, + (tANI_U8 *) psessionEntry->pLimJoinReq->bssDescription.ieFields, + limGetIElenFromBssDescription( + &psessionEntry->pLimJoinReq->bssDescription), + &psessionEntry->limCurrentBssQosCaps, + &psessionEntry->limCurrentBssPropCap, + &pMac->lim.gLimCurrentBssUapsd + , &localPowerConstraint, + psessionEntry + ); + } + else + { + limExtractApCapability( pMac, + (tANI_U8 *) psessionEntry->pLimJoinReq->bssDescription.ieFields, + limGetIElenFromBssDescription( + &psessionEntry->pLimJoinReq->bssDescription), + &psessionEntry->limCurrentBssQosCaps, + &psessionEntry->limCurrentBssPropCap, + &psessionEntry->gLimCurrentBssUapsd, + &localPowerConstraint, + psessionEntry + ); + } + + /* If power constraint is zero then update it with Region max. + * MaxTxpower will be the MIN of regmax and power constraint */ + if (localPowerConstraint == 0) + localPowerConstraint = regMax; + +#ifdef FEATURE_WLAN_ESE + psessionEntry->maxTxPower = limGetMaxTxPower(regMax, localPowerConstraint, pMac->roam.configParam.nTxPowerCap); +#else + psessionEntry->maxTxPower = VOS_MIN( regMax, (localPowerConstraint) ); +#endif + VOS_TRACE( VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "Regulatory max = %d, local power constraint = %d," + " max tx = %d", regMax, localPowerConstraint, + psessionEntry->maxTxPower ); + + if(!pMac->psOffloadEnabled) + { + if (pMac->lim.gLimCurrentBssUapsd) + { + pMac->lim.gUapsdPerAcBitmask = + psessionEntry->pLimJoinReq->uapsdPerAcBitmask; + limLog( pMac, LOG1, + FL("UAPSD flag for all AC - 0x%2x"), + pMac->lim.gUapsdPerAcBitmask); + + // resetting the dynamic uapsd mask + pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; + pMac->lim.gUapsdPerAcTriggerEnableMask = 0; + } + } + else + { + if (psessionEntry->gLimCurrentBssUapsd) + { + psessionEntry->gUapsdPerAcBitmask = + psessionEntry->pLimJoinReq->uapsdPerAcBitmask; + limLog( pMac, LOG1, + FL("UAPSD flag for all AC - 0x%2x"), + psessionEntry->gUapsdPerAcBitmask); + + /* resetting the dynamic uapsd mask */ + psessionEntry->gUapsdPerAcDeliveryEnableMask = 0; + psessionEntry->gUapsdPerAcTriggerEnableMask = 0; + } + } + + psessionEntry->limRFBand = limGetRFBand(psessionEntry->currentOperChannel); + + // Initialize 11h Enable Flag + if(SIR_BAND_5_GHZ == psessionEntry->limRFBand) + { + if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); + psessionEntry->lim11hEnable = WNI_CFG_11H_ENABLED_STADEF; + } + else { + psessionEntry->lim11hEnable = val; + } + } + else + psessionEntry->lim11hEnable = 0; + + //To care of the scenario when STA transitions from IBSS to Infrastructure mode. + pMac->lim.gLimIbssCoalescingHappened = false; + + psessionEntry->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry->limSmeState = eLIM_SME_WT_JOIN_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + limLog(pMac, LOG1, FL("SME JoinReq:Sessionid %d SSID len %d SSID : %s " + "Channel %d, BSSID "MAC_ADDRESS_STR), pMlmJoinReq->sessionId, + psessionEntry->ssId.length,psessionEntry->ssId.ssId, + psessionEntry->currentOperChannel, + MAC_ADDR_ARRAY(psessionEntry->bssId)); + + /* Indicate whether spectrum management is enabled*/ + psessionEntry->spectrumMgtEnabled = + pSmeJoinReq->spectrumMgtIndicator; + + /* Enable the spectrum management if this is a DFS channel */ + if (psessionEntry->countryInfoPresent && + limIsconnectedOnDFSChannel(psessionEntry->currentOperChannel)) + psessionEntry->spectrumMgtEnabled = TRUE; + + psessionEntry->isOSENConnection = + pSmeJoinReq->isOSENConnection; + + PELOG1(limLog(pMac,LOG1,FL("SessionId:%d MLM_JOIN_REQ is posted to MLM SM"), + pMlmJoinReq->sessionId)); + /* Issue LIM_MLM_JOIN_REQ to MLM */ + limPostMlmMessage(pMac, LIM_MLM_JOIN_REQ, (tANI_U32 *) pMlmJoinReq); + return; + + } + else + { + /* Received eWNI_SME_JOIN_REQ un expected state */ + limLog(pMac, LOGE, FL("received unexpected SME_JOIN_REQ " + "in state %X"), pMac->lim.gLimSmeState); + retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + psessionEntry = NULL; + goto end; + + } + +end: + limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf,&smesessionId,&smetransactionId); + + if(pSmeJoinReq) + { + vos_mem_free(pSmeJoinReq); + pSmeJoinReq = NULL; + if (NULL != psessionEntry) + { + psessionEntry->pLimJoinReq = NULL; + } + } + + if(retCode != eSIR_SME_SUCCESS) + { + if(NULL != psessionEntry) + { + peDeleteSession(pMac,psessionEntry); + psessionEntry = NULL; + } + } + limLog(pMac, LOG1, FL("Sending failure status limSendSmeJoinReassocRsp" + "on sessionid: %d with retCode = %d"),smesessionId, retCode); + limSendSmeJoinReassocRsp(pMac, eWNI_SME_JOIN_RSP, retCode, eSIR_MAC_UNSPEC_FAILURE_STATUS,psessionEntry,smesessionId,smetransactionId); +} /*** end __limProcessSmeJoinReq() ***/ + + +#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI +tANI_U8 limGetMaxTxPower(tPowerdBm regMax, tPowerdBm apTxPower, tANI_U8 iniTxPower) +{ + tANI_U8 maxTxPower = 0; + tANI_U8 txPower = VOS_MIN( regMax, (apTxPower) ); + txPower = VOS_MIN(txPower, iniTxPower); + if((txPower >= MIN_TX_PWR_CAP) && (txPower <= MAX_TX_PWR_CAP)) + maxTxPower = txPower; + else if (txPower < MIN_TX_PWR_CAP) + maxTxPower = MIN_TX_PWR_CAP; + else + maxTxPower = MAX_TX_PWR_CAP; + + return (maxTxPower); +} +#endif + +/** + * __limProcessSmeReassocReq() + * + *FUNCTION: + * This function is called to process SME_REASSOC_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U16 caps; + tANI_U32 val; + tpSirSmeJoinReq pReassocReq = NULL; + tLimMlmReassocReq *pMlmReassocReq; + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tpPESession psessionEntry = NULL; + tANI_U8 sessionId; + tANI_U8 smeSessionId; + tANI_U16 transactionId; + tPowerdBm localPowerConstraint = 0, regMax = 0; + tANI_U32 teleBcnEn = 0; + tANI_U16 nSize; + + + PELOG3(limLog(pMac, LOG3, FL("Received REASSOC_REQ"));) + + nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8 *) pMsgBuf); + pReassocReq = vos_mem_malloc(nSize); + if ( NULL == pReassocReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for pReassocReq")); + + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + (void) vos_mem_set((void *) pReassocReq, nSize, 0); + if ((limJoinReqSerDes(pMac, (tpSirSmeJoinReq) pReassocReq, + (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || + (!limIsSmeJoinReqValid(pMac, + (tpSirSmeJoinReq) pReassocReq))) + { + /// Received invalid eWNI_SME_REASSOC_REQ + // Log the event + limLog(pMac, LOGW, + FL("received SME_REASSOC_REQ with invalid data")); + + retCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + if((psessionEntry = peFindSessionByBssid(pMac,pReassocReq->bssDescription.bssId,&sessionId))==NULL) + { + limLog(pMac, LOGE, FL("Session does not exist for given bssId")); + limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); + retCode = eSIR_SME_INVALID_PARAMETERS; + + limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); + psessionEntry = pe_find_session_by_sme_session_id(pMac, smeSessionId); + + if (psessionEntry != NULL) + limHandleSmeJoinResult(pMac, eSIR_SME_INVALID_PARAMETERS, + eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + goto end; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOC_REQ_EVENT, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + //pMac->lim.gpLimReassocReq = pReassocReq;//TO SUPPORT BT-AMP + + /* Store the reassoc handle in the session Table.. 23rd sep review */ + psessionEntry->pLimReAssocReq = pReassocReq; + + psessionEntry->dot11mode = pReassocReq->dot11mode; + psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(pReassocReq->dot11mode); + + psessionEntry->enableHtSmps = pReassocReq->enableHtSmps; + psessionEntry->htSmpsvalue = pReassocReq->htSmps; + limLog(pMac, LOG1, FL("enableHtSmps: %d htSmps: %d"), + psessionEntry->enableHtSmps, + psessionEntry->htSmpsvalue); + + /** + * Reassociate request is expected + * in link established state only. + */ + + if (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE) + { +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + { + // May be from 11r FT pre-auth. So lets check it before we bail out + limLog(pMac, LOG1, FL("Session in reassoc state is %d"), + psessionEntry->peSessionId); + + // Make sure its our preauth bssid + if (!vos_mem_compare( pReassocReq->bssDescription.bssId, + psessionEntry->limReAssocbssId, 6)) + { + limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); + limLog(pMac, LOGP, FL("Unknown bssId in reassoc state")); + retCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + limProcessMlmFTReassocReq(pMac, pMsgBuf, psessionEntry); + return; + } +#endif + /// Should not have received eWNI_SME_REASSOC_REQ + // Log the event + limLog(pMac, LOGE, + FL("received unexpected SME_REASSOC_REQ in state %X"), + psessionEntry->limSmeState); + + retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + goto end; + } + + vos_mem_copy( psessionEntry->limReAssocbssId, + psessionEntry->pLimReAssocReq->bssDescription.bssId, + sizeof(tSirMacAddr)); + + psessionEntry->limReassocChannelId = + psessionEntry->pLimReAssocReq->bssDescription.channelId; + + psessionEntry->reAssocHtSupportedChannelWidthSet = + (psessionEntry->pLimReAssocReq->cbMode)?1:0; + psessionEntry->reAssocHtRecommendedTxWidthSet = + psessionEntry->reAssocHtSupportedChannelWidthSet; + psessionEntry->reAssocHtSecondaryChannelOffset = + psessionEntry->pLimReAssocReq->cbMode; + + psessionEntry->limReassocBssCaps = + psessionEntry->pLimReAssocReq->bssDescription.capabilityInfo; + regMax = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); + localPowerConstraint = regMax; + + if(!pMac->psOffloadEnabled) + { + limExtractApCapability( pMac, + (tANI_U8 *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, + limGetIElenFromBssDescription( + &psessionEntry->pLimReAssocReq->bssDescription), + &psessionEntry->limReassocBssQosCaps, + &psessionEntry->limReassocBssPropCap, + &pMac->lim.gLimCurrentBssUapsd + , &localPowerConstraint, + psessionEntry + ); + } + else + { + limExtractApCapability(pMac, + (tANI_U8 *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, + limGetIElenFromBssDescription( + &psessionEntry->pLimReAssocReq->bssDescription), + &psessionEntry->limReassocBssQosCaps, + &psessionEntry->limReassocBssPropCap, + &psessionEntry->gLimCurrentBssUapsd, + &localPowerConstraint, + psessionEntry); + } + + psessionEntry->maxTxPower = VOS_MIN( regMax, (localPowerConstraint) ); +#if defined WLAN_VOWIFI_DEBUG + limLog( pMac, LOGE, "Regulatory max = %d, local power constraint " + "= %d, max tx = %d", regMax, localPowerConstraint, + psessionEntry->maxTxPower ); +#endif + { + + /* Copy the SSID from session entry to local variable */ + psessionEntry->limReassocSSID.length = pReassocReq->ssId.length; + vos_mem_copy(psessionEntry->limReassocSSID.ssId, + pReassocReq->ssId.ssId, psessionEntry->limReassocSSID.length); + + } + + if(!pMac->psOffloadEnabled) + { + if (pMac->lim.gLimCurrentBssUapsd) + { + pMac->lim.gUapsdPerAcBitmask = + psessionEntry->pLimReAssocReq->uapsdPerAcBitmask; + limLog( pMac, LOG1, + FL("UAPSD flag for all AC - 0x%2x"), + pMac->lim.gUapsdPerAcBitmask); + } + } + else + { + if(psessionEntry->gLimCurrentBssUapsd) + { + psessionEntry->gUapsdPerAcBitmask = + psessionEntry->pLimReAssocReq->uapsdPerAcBitmask; + limLog( pMac, LOG1, + FL("UAPSD flag for all AC - 0x%2x"), + psessionEntry->gUapsdPerAcBitmask); + } + } + + pMlmReassocReq = vos_mem_malloc(sizeof(tLimMlmReassocReq)); + if ( NULL == pMlmReassocReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmReassocReq")); + + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + + vos_mem_copy( pMlmReassocReq->peerMacAddr, + psessionEntry->limReAssocbssId, + sizeof(tSirMacAddr)); + + if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + (tANI_U32 *) &pMlmReassocReq->reassocFailureTimeout) + != eSIR_SUCCESS) + { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve ReassocFailureTimeout value")); + } + + if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) + { + /** + * Could not get Capabilities value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Capabilities value")); + } + pMlmReassocReq->capabilityInfo = caps; + + /* Update PE sessionId*/ + pMlmReassocReq->sessionId = sessionId; + + /* If telescopic beaconing is enabled, set listen interval to + WNI_CFG_TELE_BCN_MAX_LI */ + if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != + eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + + val = WNI_CFG_LISTEN_INTERVAL_STADEF; + + if(teleBcnEn) + { + if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != + eSIR_SUCCESS) + { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); + } + } + else + { + if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) + { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); + } + } + + /* Delete all BA sessions before Re-Assoc. + * BA frames are class 3 frames and the session + * is lost upon disassociation and reassociation. + */ + + limDeleteBASessions(pMac, psessionEntry, BA_BOTH_DIRECTIONS); + + pMlmReassocReq->listenInterval = (tANI_U16) val; + + /* Indicate whether spectrum management is enabled*/ + psessionEntry->spectrumMgtEnabled = pReassocReq->spectrumMgtIndicator; + + /* Enable the spectrum management if this is a DFS channel */ + if (psessionEntry->countryInfoPresent && + limIsconnectedOnDFSChannel(psessionEntry->currentOperChannel)) + psessionEntry->spectrumMgtEnabled = TRUE; + + psessionEntry->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + limPostMlmMessage(pMac, + LIM_MLM_REASSOC_REQ, + (tANI_U32 *) pMlmReassocReq); + return; + +end: + if (pReassocReq) { + vos_mem_free( pReassocReq); + if (psessionEntry) + psessionEntry->pLimReAssocReq = NULL; + } + + if (psessionEntry) + { + // error occurred after we determined the session so extract + // session and transaction info from there + smeSessionId = psessionEntry->smeSessionId; + transactionId = psessionEntry->transactionId; + } + else + { + // error occurred before or during the time we determined the session + // so extract the session and transaction info from the message + limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); + } + + /// Send Reassoc failure response to host + /// (note psessionEntry may be NULL, but that's OK) + limSendSmeJoinReassocRsp(pMac, eWNI_SME_REASSOC_RSP, + retCode, eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry, smeSessionId, transactionId); + +} /*** end __limProcessSmeReassocReq() ***/ + + +tANI_BOOLEAN sendDisassocFrame = 1; +/** + * __limProcessSmeDisassocReq() + * + *FUNCTION: + * This function is called to process SME_DISASSOC_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U16 disassocTrigger, reasonCode; + tLimMlmDisassocReq *pMlmDisassocReq; + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tSirRetStatus status; + tSirSmeDisassocReq smeDisassocReq; + tpPESession psessionEntry = NULL; + tANI_U8 sessionId; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + if (pMsgBuf == NULL) + { + limLog(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + limGetSessionInfo(pMac, (tANI_U8 *)pMsgBuf,&smesessionId, &smetransactionId); + + status = limDisassocReqSerDes(pMac, &smeDisassocReq, (tANI_U8 *) pMsgBuf); + + if ( (eSIR_FAILURE == status) || + (!limIsSmeDisassocReqValid(pMac, &smeDisassocReq, psessionEntry)) ) + { + PELOGE(limLog(pMac, LOGE, + FL("received invalid SME_DISASSOC_REQ message"));) + + if (pMac->lim.gLimRspReqd) + { + pMac->lim.gLimRspReqd = false; + + retCode = eSIR_SME_INVALID_PARAMETERS; + disassocTrigger = eLIM_HOST_DISASSOC; + goto sendDisassoc; + } + + return; + } + + if((psessionEntry = peFindSessionByBssid(pMac,smeDisassocReq.bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given bssId "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(smeDisassocReq.bssId)); + retCode = eSIR_SME_INVALID_PARAMETERS; + disassocTrigger = eLIM_HOST_DISASSOC; + goto sendDisassoc; + + } + limLog(pMac, LOG1, FL("received DISASSOC_REQ message on sessionid %d " + "Systemrole %d Reason: %u SmeState: %d from: "MAC_ADDRESS_STR), + smesessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), + smeDisassocReq.reasonCode, pMac->lim.gLimSmeState, + MAC_ADDR_ARRAY(smeDisassocReq.peerMacAddr)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, psessionEntry, 0, smeDisassocReq.reasonCode); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /* Update SME session Id and SME transaction ID*/ + + psessionEntry->smeSessionId = smesessionId; + psessionEntry->transactionId = smetransactionId; + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + switch (psessionEntry->limSmeState) + { + case eLIM_SME_ASSOCIATED_STATE: + case eLIM_SME_LINK_EST_STATE: + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ in limSmeState: %d"), + psessionEntry->limSmeState); + psessionEntry->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; +#ifdef FEATURE_WLAN_TDLS + /* Delete all TDLS peers connected before leaving BSS*/ + limDeleteTDLSPeers(pMac, psessionEntry); +#endif + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + break; + + case eLIM_SME_WT_DEAUTH_STATE: + /* PE shall still process the DISASSOC_REQ and proceed with + * link tear down even if it had already sent a DEAUTH_IND to + * to SME. pMac->lim.gLimPrevSmeState shall remain the same as + * its been set when PE entered WT_DEAUTH_STATE. + */ + psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in " + "SME_WT_DEAUTH_STATE. ")); + break; + + case eLIM_SME_WT_DISASSOC_STATE: + /* PE Recieved a Disassoc frame. Normally it gets DISASSOC_CNF but it + * received DISASSOC_REQ. Which means host is also trying to disconnect. + * PE can continue processing DISASSOC_REQ and send the response instead + * of failing the request. SME will anyway ignore DEAUTH_IND that was sent + * for disassoc frame. + * + * It will send a disassoc, which is ok. However, we can use the global flag + * sendDisassoc to not send disassoc frame. + */ + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in " + "SME_WT_DISASSOC_STATE. ")); + break; + + case eLIM_SME_JOIN_FAILURE_STATE: { + /** Return Success as we are already in Disconnected State*/ + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in " + "eLIM_SME_JOIN_FAILURE_STATE. ")); + if (pMac->lim.gLimRspReqd) { + retCode = eSIR_SME_SUCCESS; + disassocTrigger = eLIM_HOST_DISASSOC; + goto sendDisassoc; + } + }break; + default: + /** + * STA is not currently associated. + * Log error and send response to host + */ + limLog(pMac, LOGE, + FL("received unexpected SME_DISASSOC_REQ in state %X"), + psessionEntry->limSmeState); + + if (pMac->lim.gLimRspReqd) + { + if (psessionEntry->limSmeState != + eLIM_SME_WT_ASSOC_STATE) + pMac->lim.gLimRspReqd = false; + + retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + disassocTrigger = eLIM_HOST_DISASSOC; + goto sendDisassoc; + } + + return; + } + + break; + + case eLIM_AP_ROLE: + case eLIM_BT_AMP_AP_ROLE: + // Fall through + break; + + case eLIM_STA_IN_IBSS_ROLE: + default: // eLIM_UNKNOWN_ROLE + limLog(pMac, LOGE, + FL("received unexpected SME_DISASSOC_REQ for role %d"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + disassocTrigger = eLIM_HOST_DISASSOC; + goto sendDisassoc; + } // end switch (pMac->lim.gLimSystemRole) + + disassocTrigger = eLIM_HOST_DISASSOC; + reasonCode = smeDisassocReq.reasonCode; + + if (smeDisassocReq.doNotSendOverTheAir) + { + limLog(pMac, LOG1, FL("do not send dissoc over the air")); + sendDisassocFrame = 0; + } + // Trigger Disassociation frame to peer MAC entity + limLog(pMac, LOG1, FL("Sending Disasscoc with disassoc Trigger" + " : %d, reasonCode : %d"), + disassocTrigger, reasonCode); + + pMlmDisassocReq = vos_mem_malloc(sizeof(tLimMlmDisassocReq)); + if ( NULL == pMlmDisassocReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmDisassocReq")); + + return; + } + + vos_mem_copy( (tANI_U8 *) &pMlmDisassocReq->peerMacAddr, + (tANI_U8 *) &smeDisassocReq.peerMacAddr, + sizeof(tSirMacAddr)); + + pMlmDisassocReq->reasonCode = reasonCode; + pMlmDisassocReq->disassocTrigger = disassocTrigger; + + /* Update PE session ID*/ + pMlmDisassocReq->sessionId = sessionId; + + limPostMlmMessage(pMac, + LIM_MLM_DISASSOC_REQ, + (tANI_U32 *) pMlmDisassocReq); + return; + +sendDisassoc: + if (psessionEntry) + limSendSmeDisassocNtf(pMac, smeDisassocReq.peerMacAddr, + retCode, + disassocTrigger, + 1,smesessionId,smetransactionId,psessionEntry); + else + limSendSmeDisassocNtf(pMac, smeDisassocReq.peerMacAddr, + retCode, + disassocTrigger, + 1, smesessionId, smetransactionId, NULL); + + +} /*** end __limProcessSmeDisassocReq() ***/ + + +/** ----------------------------------------------------------------- + \brief __limProcessSmeDisassocCnf() - Process SME_DISASSOC_CNF + + This function is called to process SME_DISASSOC_CNF message + from HDD or upper layer application. + + \param pMac - global mac structure + \param pStaDs - station dph hash node + \return none + \sa + ----------------------------------------------------------------- */ +static void +__limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirSmeDisassocCnf smeDisassocCnf; + tANI_U16 aid; + tpDphHashNode pStaDs; + tSirRetStatus status = eSIR_SUCCESS; + tpPESession psessionEntry; + tANI_U8 sessionId; + + + PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_CNF message"));) + + status = limDisassocCnfSerDes(pMac, &smeDisassocCnf,(tANI_U8 *) pMsgBuf); + + if (status == eSIR_FAILURE) + { + PELOGE(limLog(pMac, LOGE, FL("invalid SME_DISASSOC_CNF message"));) + return; + } + + if((psessionEntry = peFindSessionByBssid(pMac, smeDisassocCnf.bssId, &sessionId))== NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given bssId")); + return; + } + + if (!limIsSmeDisassocCnfValid(pMac, &smeDisassocCnf, psessionEntry)) + { + limLog(pMac, LOGE, FL("received invalid SME_DISASSOC_CNF message")); + return; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + if (smeDisassocCnf.messageType == eWNI_SME_DISASSOC_CNF) + limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT, psessionEntry, (tANI_U16)smeDisassocCnf.statusCode, 0); + else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF) + limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT, psessionEntry, (tANI_U16)smeDisassocCnf.statusCode, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: //To test reconn + if ((psessionEntry->limSmeState != eLIM_SME_IDLE_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) + { + limLog(pMac, LOGE, + FL("received unexp SME_DISASSOC_CNF in state %X"), + psessionEntry->limSmeState); + return; + } + break; + + case eLIM_AP_ROLE: + // Fall through + break; + + case eLIM_STA_IN_IBSS_ROLE: + default: // eLIM_UNKNOWN_ROLE + limLog(pMac, LOGE, + FL("received unexpected SME_DISASSOC_CNF role %d"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + return; + } + + if ((psessionEntry->limSmeState == eLIM_SME_WT_DISASSOC_STATE) || + (psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE) || + LIM_IS_AP_ROLE(psessionEntry)) { + pStaDs = dphLookupHashEntry(pMac, smeDisassocCnf.peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("received DISASSOC_CNF for a STA that " + "does not have context, addr= "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr));) + return; + } + + /* + * If MlM state is either of del_sta or del_bss state, then no need to + * go ahead and clean up further as there must be some cleanup in + * progress from upper layer disassoc/deauth request. + */ + if((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || + (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { + limLog(pMac, LOGE, FL("No need to cleanup for addr:"MAC_ADDRESS_STR + "as Mlm state is %d"), + MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr), + pStaDs->mlmStaContext.mlmState); + return; + } + +#if defined WLAN_FEATURE_VOWIFI_11R + /* Delete FT session if there exists one */ + limFTCleanupPreAuthInfo(pMac, psessionEntry); +#endif + limCleanupRxPath(pMac, pStaDs, psessionEntry); + + limCleanUpDisassocDeauthReq(pMac, (char*)&smeDisassocCnf.peerMacAddr, 0); + } + + return; +} + + +/** + * __limProcessSmeDeauthReq() + * + *FUNCTION: + * This function is called to process SME_DEAUTH_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U16 deauthTrigger, reasonCode; + tLimMlmDeauthReq *pMlmDeauthReq; + tSirSmeDeauthReq smeDeauthReq; + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tSirRetStatus status = eSIR_SUCCESS; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionId + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + PELOG1(limLog(pMac, LOG1,FL("received DEAUTH_REQ message"));) + + status = limDeauthReqSerDes(pMac, &smeDeauthReq,(tANI_U8 *) pMsgBuf); + + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + //We need to get a session first but we don't even know if the message is correct. + if((psessionEntry = peFindSessionByBssid(pMac, smeDeauthReq.bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given bssId")); + retCode = eSIR_SME_INVALID_PARAMETERS; + deauthTrigger = eLIM_HOST_DEAUTH; + goto sendDeauth; + + } + + if ((status == eSIR_FAILURE) || (!limIsSmeDeauthReqValid(pMac, &smeDeauthReq, psessionEntry))) + { + PELOGE(limLog(pMac, LOGE,FL + ("received invalid SME_DEAUTH_REQ message"));) + pMac->lim.gLimRspReqd = false; + + retCode = eSIR_SME_INVALID_PARAMETERS; + deauthTrigger = eLIM_HOST_DEAUTH; + goto sendDeauth; + } + limLog(pMac, LOG1,FL("received DEAUTH_REQ message on sessionid %d " + "Systemrole %d with reasoncode %u in limSmestate %d from " + MAC_ADDRESS_STR), smesessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), + smeDeauthReq.reasonCode, psessionEntry->limSmeState, + MAC_ADDR_ARRAY(smeDeauthReq.peerMacAddr)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_REQ_EVENT, psessionEntry, 0, smeDeauthReq.reasonCode); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /* Update SME session ID and Transaction ID */ + psessionEntry->smeSessionId = smesessionId; + psessionEntry->transactionId = smetransactionId; + + + switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) + { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + + switch (psessionEntry->limSmeState) + { + case eLIM_SME_ASSOCIATED_STATE: + case eLIM_SME_LINK_EST_STATE: + case eLIM_SME_WT_ASSOC_STATE: + case eLIM_SME_JOIN_FAILURE_STATE: + case eLIM_SME_IDLE_STATE: + psessionEntry->limPrevSmeState = psessionEntry->limSmeState; + psessionEntry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + // Send Deauthentication request to MLM below + + break; + case eLIM_SME_WT_DEAUTH_STATE: + case eLIM_SME_WT_DISASSOC_STATE: + /* + * PE Recieved a Deauth/Disassoc frame. Normally it gets + * DEAUTH_CNF/DISASSOC_CNF but it received DEAUTH_REQ. Which + * means host is also trying to disconnect. + * PE can continue processing DEAUTH_REQ and send + * the response instead of failing the request. + * SME will anyway ignore DEAUTH_IND/DISASSOC_IND that + * was sent for deauth/disassoc frame. + */ + psessionEntry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; + limLog(pMac, LOG1, FL("Rcvd SME_DEAUTH_REQ while in " + "SME_WT_DEAUTH_STATE. ")); + break; + default: + /** + * STA is not in a state to deauthenticate with + * peer. Log error and send response to host. + */ + limLog(pMac, LOGE, + FL("received unexp SME_DEAUTH_REQ in state %X"), + psessionEntry->limSmeState); + + if (pMac->lim.gLimRspReqd) + { + pMac->lim.gLimRspReqd = false; + + retCode = eSIR_SME_STA_NOT_AUTHENTICATED; + deauthTrigger = eLIM_HOST_DEAUTH; + +/* + here we received deauth request from AP so sme state is + eLIM_SME_WT_DEAUTH_STATE.if we have ISSUED delSta then + mlm state should be eLIM_MLM_WT_DEL_STA_RSP_STATE and if + we got delBSS rsp then mlm state should be eLIM_MLM_IDLE_STATE + so the below condition captures the state where delSta + not done and firmware still in connected state. +*/ + + if (psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE && + psessionEntry->limMlmState != eLIM_MLM_IDLE_STATE && + psessionEntry->limMlmState != eLIM_MLM_WT_DEL_STA_RSP_STATE) + { + retCode = eSIR_SME_DEAUTH_STATUS; + } + goto sendDeauth; + } + + return; + } + + break; + + case eLIM_STA_IN_IBSS_ROLE: + limLog(pMac, LOGE,FL("Deauth not allowed in IBSS")); + if (pMac->lim.gLimRspReqd) + { + pMac->lim.gLimRspReqd = false; + retCode = eSIR_SME_INVALID_PARAMETERS; + deauthTrigger = eLIM_HOST_DEAUTH; + goto sendDeauth; + } + return; + + case eLIM_AP_ROLE: + // Fall through + + break; + + default: + limLog(pMac, LOGE, + FL("received unexpected SME_DEAUTH_REQ for role %X"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + if (pMac->lim.gLimRspReqd) + { + pMac->lim.gLimRspReqd = false; + retCode = eSIR_SME_INVALID_PARAMETERS; + deauthTrigger = eLIM_HOST_DEAUTH; + goto sendDeauth; + } + return; + } // end switch (pMac->lim.gLimSystemRole) + + if (smeDeauthReq.reasonCode == eLIM_LINK_MONITORING_DEAUTH) + { + /// Deauthentication is triggered by Link Monitoring + PELOG1(limLog(pMac, LOG1, FL("**** Lost link with AP ****"));) + deauthTrigger = eLIM_LINK_MONITORING_DEAUTH; + reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; + } + else + { + deauthTrigger = eLIM_HOST_DEAUTH; + reasonCode = smeDeauthReq.reasonCode; + } + + // Trigger Deauthentication frame to peer MAC entity + pMlmDeauthReq = vos_mem_malloc(sizeof(tLimMlmDeauthReq)); + if ( NULL == pMlmDeauthReq ) + { + // Log error + limLog(pMac, LOGE, + FL("call to AllocateMemory failed for mlmDeauthReq")); + if (pMac->lim.gLimRspReqd) + { + pMac->lim.gLimRspReqd = false; + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + deauthTrigger = eLIM_HOST_DEAUTH; + goto sendDeauth; + } + return; + } + + vos_mem_copy( (tANI_U8 *) &pMlmDeauthReq->peerMacAddr, + (tANI_U8 *) &smeDeauthReq.peerMacAddr, + sizeof(tSirMacAddr)); + + pMlmDeauthReq->reasonCode = reasonCode; + pMlmDeauthReq->deauthTrigger = deauthTrigger; + + /* Update PE session Id*/ + pMlmDeauthReq->sessionId = sessionId; + + limPostMlmMessage(pMac, + LIM_MLM_DEAUTH_REQ, + (tANI_U32 *) pMlmDeauthReq); + return; + +sendDeauth: + limSendSmeDeauthNtf(pMac, smeDeauthReq.peerMacAddr, + retCode, + deauthTrigger, + 1, + smesessionId, smetransactionId); +} /*** end __limProcessSmeDeauthReq() ***/ + + + +/** + * __limProcessSmeSetContextReq() + * + *FUNCTION: + * This function is called to process SME_SETCONTEXT_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirSmeSetContextReq pSetContextReq; + tLimMlmSetKeysReq *pMlmSetKeysReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + + PELOG1(limLog(pMac, LOG1, + FL("received SETCONTEXT_REQ message"));); + + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + pSetContextReq = vos_mem_malloc(sizeof(tSirKeys) * SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS); + if ( NULL == pSetContextReq ) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for pSetContextReq")); + return; + } + + if ((limSetContextReqSerDes(pMac, pSetContextReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || + (!limIsSmeSetContextReqValid(pMac, pSetContextReq))) + { + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); + goto end; + } + + if(pSetContextReq->keyMaterial.numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) + { + PELOGE(limLog(pMac, LOGE, FL("numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"), pSetContextReq->keyMaterial.numKeys);) + limSendSmeSetContextRsp(pMac, + pSetContextReq->peerMacAddr, + 1, + eSIR_SME_INVALID_PARAMETERS,NULL, + smesessionId,smetransactionId); + + goto end; + } + + + if((psessionEntry = peFindSessionByBssid(pMac, pSetContextReq->bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); + limSendSmeSetContextRsp(pMac, + pSetContextReq->peerMacAddr, + 1, + eSIR_SME_INVALID_PARAMETERS,NULL, + smesessionId,smetransactionId); + + goto end; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + + if (((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE)) || + ((LIM_IS_IBSS_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE))) { + // Trigger MLM_SETKEYS_REQ + pMlmSetKeysReq = vos_mem_malloc(sizeof(tLimMlmSetKeysReq)); + if ( NULL == pMlmSetKeysReq ) + { + // Log error + limLog(pMac, LOGP, FL("call to AllocateMemory failed for mlmSetKeysReq")); + goto end; + } + + pMlmSetKeysReq->edType = pSetContextReq->keyMaterial.edType; + pMlmSetKeysReq->numKeys = pSetContextReq->keyMaterial.numKeys; + if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) + { + limLog(pMac, LOGP, FL("Num of keys exceeded max num of default keys limit")); + goto end; + } + vos_mem_copy( (tANI_U8 *) &pMlmSetKeysReq->peerMacAddr, + (tANI_U8 *) &pSetContextReq->peerMacAddr, + sizeof(tSirMacAddr)); + + + vos_mem_copy( (tANI_U8 *) &pMlmSetKeysReq->key, + (tANI_U8 *) &pSetContextReq->keyMaterial.key, + sizeof(tSirKeys) * (pMlmSetKeysReq->numKeys ? pMlmSetKeysReq->numKeys : 1)); + + pMlmSetKeysReq->sessionId = sessionId; + pMlmSetKeysReq->smesessionId = smesessionId; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog(pMac, LOG1, + FL("received SETCONTEXT_REQ message sessionId=%d"), pMlmSetKeysReq->sessionId);); +#endif + + if (((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP40) || + (pSetContextReq->keyMaterial.edType == eSIR_ED_WEP104)) && + LIM_IS_AP_ROLE(psessionEntry)) { + if(pSetContextReq->keyMaterial.key[0].keyLength) + { + tANI_U8 keyId; + keyId = pSetContextReq->keyMaterial.key[0].keyId; + vos_mem_copy( (tANI_U8 *)&psessionEntry->WEPKeyMaterial[keyId], + (tANI_U8 *) &pSetContextReq->keyMaterial, sizeof(tSirKeyMaterial)); + } + else { + tANI_U32 i; + for( i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) + { + vos_mem_copy( (tANI_U8 *) &pMlmSetKeysReq->key[i], + (tANI_U8 *)psessionEntry->WEPKeyMaterial[i].key, sizeof(tSirKeys)); + } + } + } + + limPostMlmMessage(pMac, LIM_MLM_SETKEYS_REQ, (tANI_U32 *) pMlmSetKeysReq); + } + else + { + limLog(pMac, LOGE, + FL("received unexpected SME_SETCONTEXT_REQ for role %d, state=%X"), + GET_LIM_SYSTEM_ROLE(psessionEntry), + psessionEntry->limSmeState); + + limSendSmeSetContextRsp(pMac, pSetContextReq->peerMacAddr, + 1, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,psessionEntry, + smesessionId, + smetransactionId); + } + +end: + vos_mem_free( pSetContextReq); + return; +} /*** end __limProcessSmeSetContextReq() ***/ + +/** + * __limProcessSmeRemoveKeyReq() + * + *FUNCTION: + * This function is called to process SME_REMOVEKEY_REQ message + * from HDD or upper layer application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirSmeRemoveKeyReq pRemoveKeyReq; + tLimMlmRemoveKeyReq *pMlmRemoveKeyReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + PELOG1(limLog(pMac, LOG1, + FL("received REMOVEKEY_REQ message"));) + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + pRemoveKeyReq = vos_mem_malloc(sizeof(*pRemoveKeyReq)); + if ( NULL == pRemoveKeyReq ) + { + //Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for pRemoveKeyReq")); + + return; + } + + if ((limRemoveKeyReqSerDes(pMac, + pRemoveKeyReq, + (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) + { + limLog(pMac, LOGW, + FL("received invalid SME_REMOVECONTEXT_REQ message")); + + /* extra look up is needed since, session entry to be passed il limsendremovekey response */ + + if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given bssId")); + //goto end; + } + + limSendSmeRemoveKeyRsp(pMac, + pRemoveKeyReq->peerMacAddr, + eSIR_SME_INVALID_PARAMETERS,psessionEntry, + smesessionId,smetransactionId); + + goto end; + } + + if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId, &sessionId))== NULL) + { + limLog(pMac, LOGE, + FL("session does not exist for given bssId")); + limSendSmeRemoveKeyRsp(pMac, + pRemoveKeyReq->peerMacAddr, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, NULL, + smesessionId, smetransactionId); + goto end; + } + + + if (((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + (psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE)) || + ((LIM_IS_IBSS_ROLE(psessionEntry) || + LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE))) { + // Trigger MLM_REMOVEKEYS_REQ + pMlmRemoveKeyReq = vos_mem_malloc(sizeof(tLimMlmRemoveKeyReq)); + if ( NULL == pMlmRemoveKeyReq ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for mlmRemoveKeysReq")); + + goto end; + } + + pMlmRemoveKeyReq->edType = (tAniEdType)pRemoveKeyReq->edType; + pMlmRemoveKeyReq->keyId = pRemoveKeyReq->keyId; + pMlmRemoveKeyReq->wepType = pRemoveKeyReq->wepType; + pMlmRemoveKeyReq->unicast = pRemoveKeyReq->unicast; + + /* Update PE session Id */ + pMlmRemoveKeyReq->sessionId = sessionId; + + vos_mem_copy( (tANI_U8 *) &pMlmRemoveKeyReq->peerMacAddr, + (tANI_U8 *) &pRemoveKeyReq->peerMacAddr, + sizeof(tSirMacAddr)); + + + limPostMlmMessage(pMac, + LIM_MLM_REMOVEKEY_REQ, + (tANI_U32 *) pMlmRemoveKeyReq); + } + else + { + limLog(pMac, LOGE, + FL("received unexpected SME_REMOVEKEY_REQ for role %d, state=%X"), + GET_LIM_SYSTEM_ROLE(psessionEntry), + psessionEntry->limSmeState); + + limSendSmeRemoveKeyRsp(pMac, + pRemoveKeyReq->peerMacAddr, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,psessionEntry, + smesessionId,smetransactionId); + } + +end: + vos_mem_free( pRemoveKeyReq); +} /*** end __limProcessSmeRemoveKeyReq() ***/ + +void limProcessSmeGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMsgQ mmhMsg; + tpSmeGetScanChnRsp pSirSmeRsp; + tANI_U16 len = 0; + tANI_U8 sessionId; + tANI_U16 transactionId; + + if(pMac->lim.scanChnInfo.numChnInfo > SIR_MAX_SUPPORTED_CHANNEL_LIST) + { + limLog(pMac, LOGW, FL("numChn is out of bounds %d"), + pMac->lim.scanChnInfo.numChnInfo); + pMac->lim.scanChnInfo.numChnInfo = SIR_MAX_SUPPORTED_CHANNEL_LIST; + } + + len = sizeof(tSmeGetScanChnRsp) + (pMac->lim.scanChnInfo.numChnInfo - 1) * sizeof(tLimScanChn); + pSirSmeRsp = vos_mem_malloc(len); + if ( NULL == pSirSmeRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for JOIN/REASSOC_RSP")); + + return; + } + vos_mem_set(pSirSmeRsp, len, 0); + + pSirSmeRsp->mesgType = eWNI_SME_GET_SCANNED_CHANNEL_RSP; + pSirSmeRsp->mesgLen = len; + + if (pMac->fScanOffload) + { + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&sessionId,&transactionId); + pSirSmeRsp->sessionId = sessionId; + } + else + pSirSmeRsp->sessionId = 0; + + if(pMac->lim.scanChnInfo.numChnInfo) + { + pSirSmeRsp->numChn = pMac->lim.scanChnInfo.numChnInfo; + vos_mem_copy( pSirSmeRsp->scanChn, pMac->lim.scanChnInfo.scanChn, + sizeof(tLimScanChn) * pSirSmeRsp->numChn); + } + //Clear the list + limRessetScanChannelInfo(pMac); + + mmhMsg.type = eWNI_SME_GET_SCANNED_CHANNEL_RSP; + mmhMsg.bodyptr = pSirSmeRsp; + mmhMsg.bodyval = 0; + + pMac->lim.gLimRspReqd = false; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + + +void limProcessSmeGetAssocSTAsInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirSmeGetAssocSTAsReq getAssocSTAsReq; + tpDphHashNode pStaDs = NULL; + tpPESession psessionEntry = NULL; + tSap_Event sapEvent; + tpWLAN_SAPEventCB pSapEventCallback = NULL; + tpSap_AssocMacAddr pAssocStasTemp = NULL;// #include "sapApi.h" + tANI_U8 sessionId = CSR_SESSION_ID_INVALID; + tANI_U8 assocId = 0; + tANI_U8 staCount = 0; + + if (!limIsSmeGetAssocSTAsReqValid(pMac, &getAssocSTAsReq, (tANI_U8 *) pMsgBuf)) + { + limLog(pMac, LOGE, + FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); + return; + } + + switch (getAssocSTAsReq.modId) + { + case VOS_MODULE_ID_PE: + default: + break; + } + + // Get Associated stations from PE + // Find PE session Entry + if ((psessionEntry = peFindSessionByBssid(pMac, getAssocSTAsReq.bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGE, + FL("session does not exist for given bssId")); + goto limAssocStaEnd; + } + + if (!LIM_IS_AP_ROLE(psessionEntry)) { + limLog(pMac, LOGE, + FL("Received unexpected message in state %X, in role %X"), + psessionEntry->limSmeState, GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto limAssocStaEnd; + } + + // Retrieve values obtained in the request message + pSapEventCallback = (tpWLAN_SAPEventCB)getAssocSTAsReq.pSapEventCallback; + pAssocStasTemp = (tpSap_AssocMacAddr)getAssocSTAsReq.pAssocStasArray; + + if (NULL == pAssocStasTemp) + goto limAssocStaEnd; + + for (assocId = 0; assocId < psessionEntry->dph.dphHashTable.size; assocId++)// Softap dphHashTable.size = 8 + { + pStaDs = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); + + if (NULL == pStaDs) + continue; + + if (pStaDs->valid) + { + vos_mem_copy((tANI_U8 *)&pAssocStasTemp->staMac, + (tANI_U8 *)&pStaDs->staAddr, + sizeof(v_MACADDR_t)); // Mac address + pAssocStasTemp->assocId = (v_U8_t)pStaDs->assocId; // Association Id + pAssocStasTemp->staId = (v_U8_t)pStaDs->staIndex; // Station Id + + vos_mem_copy((tANI_U8 *)&pAssocStasTemp->supportedRates, + (tANI_U8 *)&pStaDs->supportedRates, + sizeof(tSirSupportedRates)); + pAssocStasTemp->ShortGI40Mhz = pStaDs->htShortGI40Mhz; + pAssocStasTemp->ShortGI20Mhz = pStaDs->htShortGI20Mhz; + pAssocStasTemp->Support40Mhz = pStaDs->htDsssCckRate40MHzSupport; + + limLog(pMac, LOG1, FL("dph Station Number = %d"), staCount+1); + limLog(pMac, LOG1, FL("MAC = " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pStaDs->staAddr)); + limLog(pMac, LOG1, FL("Association Id = %d"),pStaDs->assocId); + limLog(pMac, LOG1, FL("Station Index = %d"),pStaDs->staIndex); + + pAssocStasTemp++; + staCount++; + } + } + +limAssocStaEnd: + // Call hdd callback with sap event to send the list of associated stations from PE + if (pSapEventCallback != NULL) + { + sapEvent.sapHddEventCode = eSAP_ASSOC_STA_CALLBACK_EVENT; + sapEvent.sapevt.sapAssocStaListEvent.module = VOS_MODULE_ID_PE; + sapEvent.sapevt.sapAssocStaListEvent.noOfAssocSta = staCount; + sapEvent.sapevt.sapAssocStaListEvent.pAssocStas = (tpSap_AssocMacAddr)getAssocSTAsReq.pAssocStasArray; + pSapEventCallback(&sapEvent, getAssocSTAsReq.pUsrContext); + } +} + + +/** + * limProcessSmeGetWPSPBCSessions + * + *FUNCTION: + * This function is called when query the WPS PBC overlap message is received + * + *LOGIC: + * This function parses get WPS PBC overlap information message and call callback to pass + * WPS PBC overlap information back to hdd. + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf A pointer to WPS PBC overlap query message +* + * @return None + */ +void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirSmeGetWPSPBCSessionsReq GetWPSPBCSessionsReq; + tpPESession psessionEntry = NULL; + tSap_Event sapEvent; + tpWLAN_SAPEventCB pSapEventCallback = NULL; + tANI_U8 sessionId = CSR_SESSION_ID_INVALID; + tSirMacAddr zeroMac = {0,0,0,0,0,0}; + + sapEvent.sapevt.sapGetWPSPBCSessionEvent.status = VOS_STATUS_E_FAULT; + + if (limIsSmeGetWPSPBCSessionsReqValid(pMac, &GetWPSPBCSessionsReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); + return; + } + + // Get Associated stations from PE + // Find PE session Entry + if ((psessionEntry = peFindSessionByBssid(pMac, GetWPSPBCSessionsReq.bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGE, + FL("session does not exist for given bssId")); + goto limGetWPSPBCSessionsEnd; + } + + if (!LIM_IS_AP_ROLE(psessionEntry)) { + limLog(pMac, LOGE, + FL("Received unexpected message in role %X"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto limGetWPSPBCSessionsEnd; + } + + // Call hdd callback with sap event to send the WPS PBC overlap information + sapEvent.sapHddEventCode = eSAP_GET_WPSPBC_SESSION_EVENT; + sapEvent.sapevt.sapGetWPSPBCSessionEvent.module = VOS_MODULE_ID_PE; + + if (vos_mem_compare( zeroMac, GetWPSPBCSessionsReq.pRemoveMac, sizeof(tSirMacAddr))) + { //This is GetWpsSession call + + limGetWPSPBCSessions(pMac, + sapEvent.sapevt.sapGetWPSPBCSessionEvent.addr.bytes, sapEvent.sapevt.sapGetWPSPBCSessionEvent.UUID_E, + &sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap, psessionEntry); + } + else + { + limRemovePBCSessions(pMac, GetWPSPBCSessionsReq.pRemoveMac,psessionEntry); + /* don't have to inform the HDD/Host */ + return; + } + + PELOG4(limLog(pMac, LOGE, FL("wpsPBCOverlap %d"), sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap);) + PELOG4(limPrintMacAddr(pMac, sapEvent.sapevt.sapGetWPSPBCSessionEvent.addr.bytes, LOG4);) + + sapEvent.sapevt.sapGetWPSPBCSessionEvent.status = VOS_STATUS_SUCCESS; + +limGetWPSPBCSessionsEnd: + pSapEventCallback = (tpWLAN_SAPEventCB)GetWPSPBCSessionsReq.pSapEventCallback; + if (NULL != pSapEventCallback) + pSapEventCallback(&sapEvent, GetWPSPBCSessionsReq.pUsrContext); +} + + + +/** + * __limCounterMeasures() + * + * FUNCTION: + * This function is called to "implement" MIC counter measure + * and is *temporary* only + * + * LOGIC: on AP, disassoc all STA associated thru TKIP, + * we don't do the proper STA disassoc sequence since the + * BSS will be stoped anyway + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +static void +__limCounterMeasures(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tSirMacAddr mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) + limSendDisassocMgmtFrame(pMac, eSIR_MAC_MIC_FAILURE_REASON, mac, psessionEntry, FALSE); +} + + +void +limProcessTkipCounterMeasures(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirSmeTkipCntrMeasReq tkipCntrMeasReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionId + + if ( limTkipCntrMeasReqSerDes( pMac, &tkipCntrMeasReq, (tANI_U8 *) pMsgBuf ) != eSIR_SUCCESS ) + { + limLog(pMac, LOGE, + FL("received invalid eWNI_SME_TKIP_CNTR_MEAS_REQ message")); + return; + } + + if ( NULL == (psessionEntry = peFindSessionByBssid( pMac, tkipCntrMeasReq.bssId, &sessionId )) ) + { + limLog(pMac, LOGE, FL("session does not exist for given BSSID ")); + return; + } + + if ( tkipCntrMeasReq.bEnable ) + { + __limCounterMeasures( pMac, psessionEntry ); + } + + psessionEntry->bTkipCntrMeasActive = tkipCntrMeasReq.bEnable; +} + + +static void +__limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirSmeStopBssReq stopBssReq; + tSirRetStatus status; + tLimSmeStates prevState; + tANI_U8 sessionId; //PE sessionId + tpPESession psessionEntry; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + tANI_U8 i = 0; + tpDphHashNode pStaDs = NULL; + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + + + if ((limStopBssReqSerDes(pMac, &stopBssReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) || + !limIsSmeStopBssReqValid(pMsgBuf)) + { + PELOGW(limLog(pMac, LOGW, FL("received invalid SME_STOP_BSS_REQ message"));) + /// Send Stop BSS response to host + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); + return; + } + + + if((psessionEntry = peFindSessionByBssid(pMac,stopBssReq.bssId,&sessionId)) == NULL) + { + limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); + return; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + + if ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) || /* Added For BT -AMP Support */ + LIM_IS_STA_ROLE(psessionEntry)) { + /** + * Should not have received STOP_BSS_REQ in states + * other than 'normal' state or on STA in Infrastructure + * mode. Log error and return response to host. + */ + limLog(pMac, LOGE, + FL("received unexpected SME_STOP_BSS_REQ in state %X, for role %d"), + psessionEntry->limSmeState, GET_LIM_SYSTEM_ROLE(psessionEntry)); + /// Send Stop BSS response to host + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,smesessionId,smetransactionId); + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + limWPSPBCClose(pMac, psessionEntry); + } + PELOGW(limLog(pMac, LOGW, FL("RECEIVED STOP_BSS_REQ with reason code=%d"), stopBssReq.reasonCode);) + + prevState = psessionEntry->limSmeState; + + psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + /* Update SME session Id and Transaction Id */ + psessionEntry->smeSessionId = smesessionId; + psessionEntry->transactionId = smetransactionId; + + /* BTAMP_STA and STA_IN_IBSS should NOT send Disassoc frame */ + if (!LIM_IS_IBSS_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + if ((stopBssReq.reasonCode == eSIR_SME_MIC_COUNTER_MEASURES)) + // Send disassoc all stations associated thru TKIP + __limCounterMeasures(pMac,psessionEntry); + else + limSendDisassocMgmtFrame(pMac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, bcAddr, psessionEntry, FALSE); + } + + /* Free the buffer allocated in START_BSS_REQ */ + vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); + psessionEntry->addIeParams.probeRespDataLen = 0; + psessionEntry->addIeParams.probeRespData_buff = NULL; + + vos_mem_free(psessionEntry->addIeParams.assocRespData_buff); + psessionEntry->addIeParams.assocRespDataLen = 0; + psessionEntry->addIeParams.assocRespData_buff = NULL; + + vos_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff); + psessionEntry->addIeParams.probeRespBCNDataLen = 0; + psessionEntry->addIeParams.probeRespBCNData_buff = NULL; + + //limDelBss is also called as part of coalescing, when we send DEL BSS followed by Add Bss msg. + pMac->lim.gLimIbssCoalescingHappened = false; + + for(i = 1 ; i < pMac->lim.gLimAssocStaLimit ; i++) + { + pStaDs = dphGetHashEntry(pMac, i, &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) + continue; + status = limDelSta(pMac, pStaDs, false, psessionEntry) ; + if(eSIR_SUCCESS == status) + { + limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, psessionEntry) ; + limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry) ; + } + else + { + limLog(pMac, LOGE, FL("limDelSta failed with Status : %d"), status); + VOS_ASSERT(0) ; + } + } + /* send a delBss to HAL and wait for a response */ + status = limDelBss(pMac, NULL,psessionEntry->bssIdx,psessionEntry); + + if (status != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d"), psessionEntry->bssIdx);) + psessionEntry->limSmeState= prevState; + + MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); + + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_STOP_BSS_FAILURE,smesessionId,smetransactionId); + } +} + + +/**-------------------------------------------------------------- +\fn __limProcessSmeStopBssReq + +\brief Wrapper for the function __limHandleSmeStopBssRequest + This message will be defered until softmac come out of + scan mode. Message should be handled even if we have + detected radar in the current operating channel. +\param pMac +\param pMsg + +\return TRUE - If we consumed the buffer + FALSE - If have defered the message. + ---------------------------------------------------------------*/ +static tANI_BOOLEAN +__limProcessSmeStopBssReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + if (__limIsDeferedMsgForLearn(pMac, pMsg)) + { + /** + * If message defered, buffer is not consumed yet. + * So return false + */ + return eANI_BOOLEAN_FALSE; + } + __limHandleSmeStopBssRequest(pMac, (tANI_U32 *) pMsg->bodyptr); + return eANI_BOOLEAN_TRUE; +} /*** end __limProcessSmeStopBssReq() ***/ + + +void limProcessSmeDelBssRsp( + tpAniSirGlobal pMac, + tANI_U32 body,tpPESession psessionEntry) +{ + + (void) body; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + limIbssDelete(pMac,psessionEntry); + dphHashTableClassInit(pMac, &psessionEntry->dph.dphHashTable); + limDeletePreAuthList(pMac); + limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_SUCCESS,psessionEntry->smeSessionId,psessionEntry->transactionId); + return; +} + + +/**--------------------------------------------------------------- +\fn __limProcessSmeAssocCnfNew +\brief This function handles SME_ASSOC_CNF/SME_REASSOC_CNF +\ in BTAMP AP. +\ +\param pMac +\param msgType - message type +\param pMsgBuf - a pointer to the SME message buffer +\return None +------------------------------------------------------------------*/ + + void +__limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) +{ + tSirSmeAssocCnf assocCnf; + tpDphHashNode pStaDs = NULL; + tpPESession psessionEntry= NULL; + tANI_U8 sessionId; + + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE, FL("pMsgBuf is NULL ")); + goto end; + } + + if ((limAssocCnfSerDes(pMac, &assocCnf, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || + !__limIsSmeAssocCnfValid(&assocCnf)) + { + limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); + goto end; + } + + if((psessionEntry = peFindSessionByBssid(pMac, assocCnf.bssId, &sessionId))== NULL) + { + limLog(pMac, LOGE, FL("session does not exist for given bssId")); + goto end; + } + + if ((!LIM_IS_AP_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) || + ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) && + (psessionEntry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { + limLog(pMac, LOGE, + FL("Received unexpected message %X in state %X, in role %X"), + msgType, psessionEntry->limSmeState, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto end; + } + + pStaDs = dphGetHashEntry(pMac, assocCnf.aid, &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) + { + limLog(pMac, LOGE, + FL("Received invalid message %X due to no STA context" + "for aid %d, peer "), + msgType, assocCnf.aid); + limPrintMacAddr(pMac, assocCnf.peerMacAddr, LOG1); + + /* + ** send a DISASSOC_IND message to WSM to make sure + ** the state in WSM and LIM is the same + **/ + limSendSmeDisassocNtf( pMac, assocCnf.peerMacAddr, eSIR_SME_STA_NOT_ASSOCIATED, + eLIM_PEER_ENTITY_DISASSOC, assocCnf.aid,psessionEntry->smeSessionId,psessionEntry->transactionId,psessionEntry); + goto end; + } + if ((pStaDs && + (( !vos_mem_compare( (tANI_U8 *) pStaDs->staAddr, + (tANI_U8 *) assocCnf.peerMacAddr, + sizeof(tSirMacAddr)) ) || + (pStaDs->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) || + ((pStaDs->mlmStaContext.subType == LIM_ASSOC) && + (msgType != eWNI_SME_ASSOC_CNF)) || + ((pStaDs->mlmStaContext.subType == LIM_REASSOC) && + (msgType != eWNI_SME_ASSOC_CNF))))) // since softap is passing this as ASSOC_CNF and subtype differs + { + limLog(pMac, LOG1, + FL("Received invalid message %X due to peerMacAddr mismatched" + "or not in eLIM_MLM_WT_ASSOC_CNF_STATE state, for aid %d, peer " + "StaD mlmState : %d"), + msgType, assocCnf.aid, pStaDs->mlmStaContext.mlmState); + limPrintMacAddr(pMac, assocCnf.peerMacAddr, LOG1); + goto end; + } + + /* + ** Deactivate/delet CNF_WAIT timer since ASSOC_CNF + ** has been received + **/ + limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); + limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, pStaDs->assocId); + + if (assocCnf.statusCode == eSIR_SME_SUCCESS) + { + /* In BTAMP-AP, PE already finished the WDA_ADD_STA sequence + * when it had received Assoc Request frame. Now, PE just needs to send + * Association Response frame to the requesting BTAMP-STA. + */ + 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); + goto end; + } // (assocCnf.statusCode == eSIR_SME_SUCCESS) + else + { + // SME_ASSOC_CNF status is non-success, so STA is not allowed to be associated + /*Since the HAL sta entry is created for denied STA we need to remove this HAL entry.So to do that set updateContext to 1*/ + if(!pStaDs->mlmStaContext.updateContext) + pStaDs->mlmStaContext.updateContext = 1; + limLog(pMac, LOG1, FL("Receive Assoc Cnf with status Code : %d(assoc id=%d) "), + assocCnf.statusCode, pStaDs->assocId); + limRejectAssociation(pMac, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true, + eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); + } + +end: + if((psessionEntry != NULL) && (pStaDs != NULL)) + { + if ( psessionEntry->parsedAssocReq[pStaDs->assocId] != NULL ) + { + if ( ((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame) + { + vos_mem_free(((tpSirAssocReq) + (psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame); + ((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame = NULL; + } + + vos_mem_free(psessionEntry->parsedAssocReq[pStaDs->assocId]); + psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL; + } + } + +} /*** end __limProcessSmeAssocCnfNew() ***/ + +#ifdef SAP_AUTH_OFFLOAD +/** + * __lim_process_sme_assoc_offload_cnf() station connect confirm + * @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 ")); + goto end; + } + + 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 ")); + goto end; + } + + 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) && + !LIM_IS_BT_AMP_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; + limDeactivateAndChangePerStaIdTimer(pmac, + eLIM_CNF_WAIT_TIMER, + aid); + } + +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 +__limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpDphHashNode pStaDs; + tSirMacAddr peerMac; + tpSirAddtsReq pSirAddts; + tANI_U32 timeout; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionId + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + pSirAddts = (tpSirAddtsReq) pMsgBuf; + + if((psessionEntry = peFindSessionByBssid(pMac, pSirAddts->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE, "Session Does not exist for given bssId"); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ADDTS_REQ_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + + + /* if sta + * - verify assoc state + * - send addts request to ap + * - wait for addts response from ap + * if ap, just ignore with error log + */ + PELOG1(limLog(pMac, LOG1, + FL("Received SME_ADDTS_REQ (TSid %d, UP %d)"), + pSirAddts->req.tspec.tsinfo.traffic.tsid, + pSirAddts->req.tspec.tsinfo.traffic.userPrio);) + + if (!LIM_IS_STA_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + PELOGE(limLog(pMac, LOGE, "AddTs received on AP - ignoring");) + limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, + smesessionId,smetransactionId); + return; + } + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + + if(pStaDs == NULL) + { + PELOGE(limLog(pMac, LOGE, "Cannot find AP context for addts req");) + limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, + smesessionId,smetransactionId); + return; + } + + if ((! pStaDs->valid) || + (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) + { + PELOGE(limLog(pMac, LOGE, "AddTs received in invalid MLM state");) + limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, + smesessionId,smetransactionId); + return; + } + + pSirAddts->req.wsmTspecPresent = 0; + pSirAddts->req.wmeTspecPresent = 0; + pSirAddts->req.lleTspecPresent = 0; + + if ((pStaDs->wsmEnabled) && + (pSirAddts->req.tspec.tsinfo.traffic.accessPolicy != SIR_MAC_ACCESSPOLICY_EDCA)) + pSirAddts->req.wsmTspecPresent = 1; + else if (pStaDs->wmeEnabled) + pSirAddts->req.wmeTspecPresent = 1; + else if (pStaDs->lleEnabled) + pSirAddts->req.lleTspecPresent = 1; + else + { + PELOGW(limLog(pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled"));) + limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, + smesessionId,smetransactionId); + return; + } + + if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) + { + limLog(pMac, LOGE, "AddTs received in invalid LIMsme state (%d)", + psessionEntry->limSmeState); + limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, + smesessionId,smetransactionId); + return; + } + + if (pMac->lim.gLimAddtsSent) + { + limLog(pMac, LOGE, "Addts (token %d, tsid %d, up %d) is still pending", + pMac->lim.gLimAddtsReq.req.dialogToken, + pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid, + pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.userPrio); + limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, + smesessionId,smetransactionId); + return; + } + + sirCopyMacAddr(peerMac,psessionEntry->bssId); + + // save the addts request + pMac->lim.gLimAddtsSent = true; + vos_mem_copy( (tANI_U8 *) &pMac->lim.gLimAddtsReq, (tANI_U8 *) pSirAddts, sizeof(tSirAddtsReq)); + + // ship out the message now + limSendAddtsReqActionFrame(pMac, peerMac, &pSirAddts->req, + psessionEntry); + PELOG1(limLog(pMac, LOG1, "Sent ADDTS request");) + + // start a timer to wait for the response + if (pSirAddts->timeout) + timeout = pSirAddts->timeout; + else if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &timeout) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Unable to get Cfg param %d (Addts Rsp Timeout)"), + WNI_CFG_ADDTS_RSP_TIMEOUT); + return; + } + + timeout = SYS_MS_TO_TICKS(timeout); + if (tx_timer_change(&pMac->lim.limTimers.gLimAddtsRspTimer, timeout, 0) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); + return; + } + pMac->lim.gLimAddtsRspTimerCount++; + if (tx_timer_change_context(&pMac->lim.limTimers.gLimAddtsRspTimer, + pMac->lim.gLimAddtsRspTimerCount) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); + return; + } + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ADDTS_RSP_TIMER)); + + //add the sessionId to the timer object + pMac->lim.limTimers.gLimAddtsRspTimer.sessionId = sessionId; + if (tx_timer_activate(&pMac->lim.limTimers.gLimAddtsRspTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("AddtsRsp timer activation failed!")); + return; + } + return; +} + + +static void +__limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMacAddr peerMacAddr; + tANI_U8 ac; + tSirMacTSInfo *pTsinfo; + tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) pMsgBuf; + tpDphHashNode pStaDs = NULL; + tpPESession psessionEntry; + tANI_U8 sessionId; + tANI_U32 status = eSIR_SUCCESS; + tANI_U8 smesessionId; + tANI_U16 smetransactionId; + + limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); + + if((psessionEntry = peFindSessionByBssid(pMac, pDeltsReq->bssId, &sessionId))== NULL) + { + limLog(pMac, LOGE, "Session Does not exist for given bssId"); + status = eSIR_FAILURE; + goto end; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DELTS_REQ_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + + if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDeltsReq, peerMacAddr,psessionEntry)) + { + PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) + status = eSIR_FAILURE; + limSendSmeDeltsRsp(pMac, pDeltsReq, eSIR_FAILURE,psessionEntry,smesessionId,smetransactionId); + return; + } + + PELOG1(limLog(pMac, LOG1, FL("Sent DELTS request to station with " + "assocId = %d MacAddr = "MAC_ADDRESS_STR), + pDeltsReq->aid, MAC_ADDR_ARRAY(peerMacAddr));) + + limSendDeltsReqActionFrame(pMac, peerMacAddr, pDeltsReq->req.wmeTspecPresent, &pDeltsReq->req.tsinfo, &pDeltsReq->req.tspec, + psessionEntry); + + pTsinfo = pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.tsinfo : &pDeltsReq->req.tsinfo; + + /* We've successfully send DELTS frame to AP. Update the + * dynamic UAPSD mask. The AC for this TSPEC to be deleted + * is no longer trigger enabled or delivery enabled + */ + if(!pMac->psOffloadEnabled) + { + limSetTspecUapsdMask(pMac, pTsinfo, CLEAR_UAPSD_MASK); + + /* We're deleting the TSPEC, so this particular AC is no longer + * admitted. PE needs to downgrade the EDCA + * parameters(for the AC for which TS is being deleted) to the + * next best AC for which ACM is not enabled, and send the + * updated values to HAL. + */ + ac = upToAc(pTsinfo->traffic.userPrio); + + if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + } + else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) + { + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + } + else + { + limSetTspecUapsdMaskPerSession(pMac, psessionEntry, + pTsinfo, CLEAR_UAPSD_MASK); + + /* We're deleting the TSPEC, so this particular AC is no longer + * admitted. PE needs to downgrade the EDCA + * parameters(for the AC for which TS is being deleted) to the + * next best AC for which ACM is not enabled, and send the + * updated values to HAL. + */ + ac = upToAc(pTsinfo->traffic.userPrio); + + if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + } + else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) + { + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); + } + } + + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + { + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); + status = eSIR_SUCCESS; + } + else + { + limLog(pMac, LOGE, FL("Self entry missing in Hash Table ")); + status = eSIR_FAILURE; + } +#ifdef FEATURE_WLAN_ESE +#ifdef FEATURE_WLAN_ESE_UPLOAD + limSendSmeTsmIEInd(pMac, psessionEntry, 0, 0, 0); +#else + limDeactivateAndChangeTimer(pMac,eLIM_TSM_TIMER); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + + // send an sme response back + end: + limSendSmeDeltsRsp(pMac, pDeltsReq, eSIR_SUCCESS,psessionEntry,smesessionId,smetransactionId); +} + + +void +limProcessSmeAddtsRspTimeout(tpAniSirGlobal pMac, tANI_U32 param) +{ + //fetch the sessionEntry based on the sessionId + tpPESession psessionEntry; + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAddtsRspTimer.sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if (!LIM_IS_STA_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + limLog(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + pMac->lim.gLimAddtsSent = false; + return; + } + + if (! pMac->lim.gLimAddtsSent) + { + PELOGW(limLog(pMac, LOGW, "AddtsRspTimeout but no AddtsSent");) + return; + } + + if (param != pMac->lim.gLimAddtsRspTimerCount) + { + limLog(pMac, LOGE, FL("Invalid AddtsRsp Timer count %d (exp %d)"), + param, pMac->lim.gLimAddtsRspTimerCount); + return; + } + + // this a real response timeout + pMac->lim.gLimAddtsSent = false; + pMac->lim.gLimAddtsRspTimerCount++; + + limSendSmeAddtsRsp(pMac, true, eSIR_SME_ADDTS_RSP_TIMEOUT, psessionEntry, pMac->lim.gLimAddtsReq.req.tspec, + psessionEntry->smeSessionId, psessionEntry->transactionId); +} + + +/** + * __limProcessSmeStatsRequest() + * + *FUNCTION: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpAniGetStatsReq pStatsReq; + tSirMsgQ msgQ; + tpPESession psessionEntry; + tANI_U8 sessionId; + + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pStatsReq = (tpAniGetStatsReq) pMsgBuf; + + if((psessionEntry = peFindSessionByBssid(pMac,pStatsReq->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE, FL("session does not exist for given bssId")); + vos_mem_free( pMsgBuf ); + pMsgBuf = NULL; + return; + } + + + + switch(pStatsReq->msgType) + { + //Add Lim stats here. and send reqsponse. + + //HAL maintained Stats. + case eWNI_SME_STA_STAT_REQ: + msgQ.type = WDA_STA_STAT_REQ; + break; + case eWNI_SME_AGGR_STAT_REQ: + msgQ.type = WDA_AGGR_STAT_REQ; + break; + case eWNI_SME_GLOBAL_STAT_REQ: + msgQ.type = WDA_GLOBAL_STAT_REQ; + break; + case eWNI_SME_STAT_SUMM_REQ: + msgQ.type = WDA_STAT_SUMM_REQ; + break; + default: //Unknown request. + PELOGE(limLog(pMac, LOGE, "Unknown Statistics request");) + vos_mem_free( pMsgBuf ); + pMsgBuf = NULL; + return; + } + + msgQ.reserved = 0; + msgQ.bodyptr = pMsgBuf; + msgQ.bodyval = 0; + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ + limLog(pMac, LOGP, "Unable to forward request"); + vos_mem_free( pMsgBuf ); + pMsgBuf = NULL; + return; + } + + return; +} + + +/** + * __limProcessSmeGetStatisticsRequest() + * + *FUNCTION: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__limProcessSmeGetStatisticsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpAniGetPEStatsReq pPEStatsReq; + tSirMsgQ msgQ; + + pPEStatsReq = (tpAniGetPEStatsReq) pMsgBuf; + + msgQ.type = WDA_GET_STATISTICS_REQ; + + msgQ.reserved = 0; + msgQ.bodyptr = pMsgBuf; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + + if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ + vos_mem_free( pMsgBuf ); + pMsgBuf = NULL; + limLog(pMac, LOGP, "Unable to forward request"); + return; + } + + return; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + *FUNCTION: __limProcessSmeGetTsmStatsRequest() + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__limProcessSmeGetTsmStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMsgQ msgQ; + + msgQ.type = WDA_TSM_STATS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pMsgBuf; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + + if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ + vos_mem_free( pMsgBuf ); + pMsgBuf = NULL; + limLog(pMac, LOGP, "Unable to forward request"); + return; + } +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +static void +__limProcessSmeUpdateAPWPSIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirUpdateAPWPSIEsReq pUpdateAPWPSIEsReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + + PELOG1(limLog(pMac, LOG1, + FL("received UPDATE_APWPSIEs_REQ message"));); + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pUpdateAPWPSIEsReq = vos_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); + if ( NULL == pUpdateAPWPSIEsReq ) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for pUpdateAPWPSIEsReq")); + return; + } + + if ((limUpdateAPWPSIEsReqSerDes(pMac, pUpdateAPWPSIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) + { + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); + goto end; + } + + if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPSIEsReq->bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); + goto end; + } + + vos_mem_copy( &psessionEntry->APWPSIEs, &pUpdateAPWPSIEsReq->APWPSIEs, sizeof(tSirAPWPSIEs)); + + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + +end: + vos_mem_free( pUpdateAPWPSIEsReq); + return; +} /*** end __limProcessSmeUpdateAPWPSIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ + +void +limSendVdevRestart(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tANI_U8 sessionId) +{ + tpHalHiddenSsidVdevRestart pHalHiddenSsidVdevRestart = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + if ( psessionEntry == NULL ) + { + PELOGE(limLog(pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ );) + return; + } + + pHalHiddenSsidVdevRestart = vos_mem_malloc(sizeof(tHalHiddenSsidVdevRestart)); + if (NULL == pHalHiddenSsidVdevRestart) + { + PELOGE(limLog(pMac, LOGE, "%s:%d: Unable to allocate memory", __func__, __LINE__ );) + return; + } + + pHalHiddenSsidVdevRestart->ssidHidden = psessionEntry->ssidHidden; + pHalHiddenSsidVdevRestart->sessionId = sessionId; + + msgQ.type = WDA_HIDDEN_SSID_VDEV_RESTART; + msgQ.bodyptr = pHalHiddenSsidVdevRestart; + msgQ.bodyval = 0; + + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) + { + PELOGE(limLog(pMac, LOGE, "%s:%d: wdaPostCtrlMsg() failed", __func__, __LINE__ );) + vos_mem_free(pHalHiddenSsidVdevRestart); + } +} +static void __lim_process_roam_restart_req(tpAniSirGlobal mac_ctx, + tANI_U32 *msg_buf) +{ + struct sir_sme_roam_restart_req *msg; + tSirRoamOffloadScanReq *req_buffer; + tpPESession pe_session; + tSirMsgQ wma_msg; + tSirRetStatus status; + + msg = (struct sir_sme_roam_restart_req *)msg_buf; + pe_session = pe_find_session_by_sme_session_id(mac_ctx, + msg->sme_session_id); + if (NULL == pe_session) { + limLog(mac_ctx, LOGE, + FL("session does not exist for sme_session: %d"), + msg->sme_session_id); + return; + } + /* Add log for unset of the flag */ + pe_session->roaming_in_progress = false; + req_buffer = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq)); + if (NULL == req_buffer) { + limLog(mac_ctx, LOGE, + FL("Mem Alloc failed for req buffer")); + return; + } + vos_mem_zero(req_buffer, sizeof(tSirRoamOffloadScanReq)); + vos_mem_zero(&wma_msg, sizeof(tSirMsgQ)); + req_buffer->Command = msg->command; + req_buffer->reason = msg->reason; + req_buffer->sessionId = msg->sme_session_id; + wma_msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; + wma_msg.bodyptr = req_buffer; + + status = wdaPostCtrlMsg(mac_ctx, &wma_msg); + if (eSIR_SUCCESS != status) + { + limLog(mac_ctx, LOGE, + FL("Posting WDA_ROAM_SCAN_OFFLOAD_REQ failed")); + vos_mem_free(req_buffer); + } +} +static void +__limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirUpdateParams pUpdateParams; + tpPESession psessionEntry; + + PELOG1(limLog(pMac, LOG1, + FL("received HIDE_SSID message"));); + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pUpdateParams = (tpSirUpdateParams)pMsgBuf; + + if((psessionEntry = peFindSessionBySessionId(pMac, pUpdateParams->sessionId)) == NULL) + { + limLog(pMac, LOGW, "Session does not exist for given sessionId %d", + pUpdateParams->sessionId); + return; + } + + /* Update the session entry */ + psessionEntry->ssidHidden = pUpdateParams->ssidHidden; + + /* Send vdev restart */ + limSendVdevRestart(pMac, psessionEntry, pUpdateParams->sessionId); + + /* Update beacon */ + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + + return; +} /*** end __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ + +static void +__limProcessSmeSetWPARSNIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirUpdateAPWPARSNIEsReq pUpdateAPWPARSNIEsReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pUpdateAPWPARSNIEsReq = vos_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); + if ( NULL == pUpdateAPWPARSNIEsReq ) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for pUpdateAPWPARSNIEsReq")); + return; + } + + if ((limUpdateAPWPARSNIEsReqSerDes(pMac, pUpdateAPWPARSNIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) + { + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); + goto end; + } + + if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPARSNIEsReq->bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); + goto end; + } + + vos_mem_copy(&psessionEntry->pLimStartBssReq->rsnIE, + &pUpdateAPWPARSNIEsReq->APWPARSNIEs, sizeof(tSirRSNie)); + + limSetRSNieWPAiefromSmeStartBSSReqMessage(pMac, &psessionEntry->pLimStartBssReq->rsnIE, psessionEntry); + + psessionEntry->pLimStartBssReq->privacy = 1; + psessionEntry->privacy = 1; + + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + +end: + vos_mem_free(pUpdateAPWPARSNIEsReq); + return; +} /*** end __limProcessSmeSetWPARSNIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ + +/* +Update the beacon Interval dynamically if beaconInterval is different in MCC +*/ +static void +__limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirChangeBIParams pChangeBIParams; + tpPESession psessionEntry; + tANI_U8 sessionId = 0; + tUpdateBeaconParams beaconParams; + + PELOG1(limLog(pMac, LOG1, + FL("received Update Beacon Interval message"));); + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); + pChangeBIParams = (tpSirChangeBIParams)pMsgBuf; + + if((psessionEntry = peFindSessionByBssid(pMac, pChangeBIParams->bssId, &sessionId)) == NULL) + { + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); + return; + } + + /*Update sessionEntry Beacon Interval*/ + if(psessionEntry->beaconParams.beaconInterval != + pChangeBIParams->beaconInterval ) + { + psessionEntry->beaconParams.beaconInterval = pChangeBIParams->beaconInterval; + } + + /*Update sch beaconInterval*/ + if(pMac->sch.schObject.gSchBeaconInterval != + pChangeBIParams->beaconInterval ) + { + pMac->sch.schObject.gSchBeaconInterval = pChangeBIParams->beaconInterval; + + PELOG1(limLog(pMac, LOG1, + FL("LIM send update BeaconInterval Indication : %d"),pChangeBIParams->beaconInterval);); + + if (VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + { + /* Update beacon */ + schSetFixedBeaconFields(pMac, psessionEntry); + + beaconParams.bssIdx = psessionEntry->bssIdx; + //Set change in beacon Interval + beaconParams.beaconInterval = pChangeBIParams->beaconInterval; + beaconParams.paramChangeBitmap = PARAM_BCN_INTERVAL_CHANGED; + limSendBeaconParams(pMac, &beaconParams, psessionEntry); + } + } + + return; +} /*** end __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ + +#ifdef QCA_HT_2040_COEX +static void __limProcessSmeSetHT2040Mode(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirSetHT2040Mode pSetHT2040Mode; + tpPESession psessionEntry; + tANI_U8 sessionId = 0; + vos_msg_t msg; + tUpdateVHTOpMode *pHtOpMode = NULL; + tANI_U16 staId = 0; + tpDphHashNode pStaDs = NULL; + + PELOG1(limLog(pMac, LOG1, + FL("received Set HT 20/40 mode message"));); + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pSetHT2040Mode = (tpSirSetHT2040Mode)pMsgBuf; + + if((psessionEntry = peFindSessionByBssid(pMac, pSetHT2040Mode->bssId, + &sessionId)) == NULL) + { + limLog(pMac, LOG1, FL("Session does not exist for given BSSID ")); + limPrintMacAddr(pMac, pSetHT2040Mode->bssId, LOG1); + return; + } + + limLog(pMac, LOG1, FL("Update session entry for cbMod=%d"), + pSetHT2040Mode->cbMode); + /*Update sessionEntry HT related fields*/ + switch(pSetHT2040Mode->cbMode) + { + case PHY_SINGLE_CHANNEL_CENTERED: + psessionEntry->htSecondaryChannelOffset = PHY_SINGLE_CHANNEL_CENTERED; + psessionEntry->htRecommendedTxWidthSet = 0; + if (pSetHT2040Mode->obssEnabled) + psessionEntry->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + else + psessionEntry->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ; + break; + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + psessionEntry->htSecondaryChannelOffset = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + psessionEntry->htRecommendedTxWidthSet = 1; + break; + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + psessionEntry->htSecondaryChannelOffset = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + psessionEntry->htRecommendedTxWidthSet = 1; + break; + default: + limLog(pMac, LOGE,FL("Invalid cbMode")); + return; + } + + /* Update beacon */ + schSetFixedBeaconFields(pMac, psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + + /* update OP Mode for each associated peer */ + for (staId = 0; staId < psessionEntry->dph.dphHashTable.size; staId++) + { + pStaDs = dphGetHashEntry(pMac, staId, &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) + continue; + + if (pStaDs->valid && pStaDs->htSupportedChannelWidthSet) + { + pHtOpMode = vos_mem_malloc(sizeof(tUpdateVHTOpMode)); + if ( NULL == pHtOpMode ) + { + limLog(pMac, LOGE, + FL("%s: Not able to allocate memory for setting OP mode"), + __func__); + return; + } + pHtOpMode->opMode = (psessionEntry->htSecondaryChannelOffset == + PHY_SINGLE_CHANNEL_CENTERED)? + eHT_CHANNEL_WIDTH_20MHZ:eHT_CHANNEL_WIDTH_40MHZ; + pHtOpMode->staId = staId; + vos_mem_copy(pHtOpMode->peer_mac, &pStaDs->staAddr, + sizeof(tSirMacAddr)); + pHtOpMode->smesessionId = sessionId; + + msg.type = WDA_UPDATE_OP_MODE; + msg.reserved = 0; + msg.bodyptr = pHtOpMode; + if (!VOS_IS_STATUS_SUCCESS( + vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) + { + limLog(pMac, LOGE, + FL("%s: Not able to post WDA_UPDATE_OP_MODE message to WDA"), + __func__); + vos_mem_free(pHtOpMode); + return; + } + limLog(pMac, LOG1, + FL("%s: Notifed FW about OP mode: %d for staId=%d"), + __func__, pHtOpMode->opMode, staId); + + } + else + limLog(pMac, LOG1, FL("%s: station %d does not support HT40\n"), + __func__, staId); + } + + return; +} +#endif + +/** ------------------------------------------------------------- +\fn limProcessSmeDelBaPeerInd +\brief handles indication message from HDD to send delete BA request +\param tpAniSirGlobal pMac +\param tANI_U32 pMsgBuf +\return None +-------------------------------------------------------------*/ +void +limProcessSmeDelBaPeerInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tANI_U16 assocId =0; + tpSmeDelBAPeerInd pSmeDelBAPeerInd = (tpSmeDelBAPeerInd)pMsgBuf; + tpDphHashNode pSta; + tpPESession psessionEntry; + tANI_U8 sessionId; + + + + if(NULL == pSmeDelBAPeerInd) + return; + + if ((psessionEntry = peFindSessionByBssid(pMac,pSmeDelBAPeerInd->bssId,&sessionId))==NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given bssId")); + return; + } + limLog(pMac, LOGW, FL("called with staId = %d, tid = %d, baDirection = %d"), + pSmeDelBAPeerInd->staIdx, pSmeDelBAPeerInd->baTID, pSmeDelBAPeerInd->baDirection); + + pSta = dphLookupAssocId(pMac, pSmeDelBAPeerInd->staIdx, &assocId, &psessionEntry->dph.dphHashTable); + if( eSIR_SUCCESS != limPostMlmDelBAReq( pMac, + pSta, + pSmeDelBAPeerInd->baDirection, + pSmeDelBAPeerInd->baTID, + eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry)) + { + limLog( pMac, LOGW, + FL( "Failed to post LIM_MLM_DELBA_REQ to " )); + if (pSta) + limPrintMacAddr(pMac, pSta->staAddr, LOGW); + } +} + +// -------------------------------------------------------------------- +/** + * __limProcessReportMessage + * + * FUNCTION: Processes the next received Radio Resource Management message + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void __limProcessReportMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ +#ifdef WLAN_FEATURE_VOWIFI + switch (pMsg->type) + { + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + rrmProcessNeighborReportReq( pMac, pMsg->bodyptr ); + break; + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: + { +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + tpSirBeaconReportXmitInd pBcnReport=NULL; + tpPESession psessionEntry=NULL; + tANI_U8 sessionId; + + if(pMsg->bodyptr == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + pBcnReport = (tpSirBeaconReportXmitInd )pMsg->bodyptr; + if((psessionEntry = peFindSessionByBssid(pMac, pBcnReport->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE, "Session Does not exist for given bssId"); + return; + } + if (psessionEntry->isESEconnection) + eseProcessBeaconReportXmit( pMac, pMsg->bodyptr); + else +#endif + rrmProcessBeaconReportXmit( pMac, pMsg->bodyptr ); + } + break; + default: + limLog(pMac, LOGE, FL("Invalid msg type:%d"), pMsg->type); + } +#endif +} + +#if defined(FEATURE_WLAN_ESE) || defined(WLAN_FEATURE_VOWIFI) +// -------------------------------------------------------------------- +/** + * limSendSetMaxTxPowerReq + * + * FUNCTION: Send SIR_HAL_SET_MAX_TX_POWER_REQ message to change the max tx power. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param txPower txPower to be set. + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus +limSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, tPowerdBm txPower, tpPESession pSessionEntry ) +{ + tpMaxTxPowerParams pMaxTxParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if( pSessionEntry == NULL ) + { + PELOGE(limLog(pMac, LOGE, "%s:%d: Inavalid parameters", __func__, __LINE__ );) + return eSIR_FAILURE; + } + + pMaxTxParams = vos_mem_malloc(sizeof(tMaxTxPowerParams)); + if ( NULL == pMaxTxParams ) + { + limLog( pMac, LOGP, "%s:%d:Unable to allocate memory for pMaxTxParams ", __func__, __LINE__); + return eSIR_MEM_ALLOC_FAILED; + + } +#if defined(WLAN_VOWIFI_DEBUG) || defined(FEATURE_WLAN_ESE) + PELOG1(limLog( pMac, LOG1, "%s:%d: Allocated memory for pMaxTxParams...will be freed in other module", __func__, __LINE__ );) +#endif + if( pMaxTxParams == NULL ) + { + limLog( pMac, LOGE, "%s:%d: pMaxTxParams is NULL", __func__, __LINE__); + return eSIR_FAILURE; + } + pMaxTxParams->power = txPower; + vos_mem_copy( pMaxTxParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr) ); + vos_mem_copy( pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, sizeof(tSirMacAddr) ); + + msgQ.type = WDA_SET_MAX_TX_POWER_REQ; + msgQ.bodyptr = pMaxTxParams; + msgQ.bodyval = 0; + PELOG1(limLog(pMac, LOG1, FL("Posting WDA_SET_MAX_TX_POWER_REQ to WDA"));) + MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) + { + PELOGE(limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed"));) + vos_mem_free(pMaxTxParams); + } + return retCode; +} +#endif + +/** + * __limProcessSmeAddStaSelfReq() + * + *FUNCTION: + * This function is called to process SME_ADD_STA_SELF_REQ message + * from SME. It sends a SIR_HAL_ADD_STA_SELF_REQ message to HAL. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeAddStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMsgQ msg; + tpAddStaSelfParams pAddStaSelfParams; + tpSirSmeAddStaSelfReq pSmeReq = (tpSirSmeAddStaSelfReq) pMsgBuf; + + pAddStaSelfParams = vos_mem_malloc(sizeof(tAddStaSelfParams)); + if ( NULL == pAddStaSelfParams ) + { + limLog( pMac, LOGP, FL("Unable to allocate memory for tAddSelfStaParams") ); + return; + } + + vos_mem_copy( pAddStaSelfParams->selfMacAddr, pSmeReq->selfMacAddr, sizeof(tSirMacAddr) ); + pAddStaSelfParams->currDeviceMode = pSmeReq->currDeviceMode; + pAddStaSelfParams->sessionId = pSmeReq->sessionId; + pAddStaSelfParams->type = pSmeReq->type; + pAddStaSelfParams->subType = pSmeReq->subType; + pAddStaSelfParams->pkt_err_disconn_th = pSmeReq->pkt_err_disconn_th; + pAddStaSelfParams->nss_2g = pSmeReq->nss_2g; + pAddStaSelfParams->nss_5g = pSmeReq->nss_5g; + + msg.type = SIR_HAL_ADD_STA_SELF_REQ; + msg.reserved = 0; + msg.bodyptr = pAddStaSelfParams; + msg.bodyval = 0; + + PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL"));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); + } + return; +} /*** end __limProcessAddStaSelfReq() ***/ + + +/** + * __limProcessSmeDelStaSelfReq() + * + *FUNCTION: + * This function is called to process SME_DEL_STA_SELF_REQ message + * from SME. It sends a SIR_HAL_DEL_STA_SELF_REQ message to HAL. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ + +static void +__limProcessSmeDelStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirMsgQ msg; + tpDelStaSelfParams pDelStaSelfParams; + tpSirSmeDelStaSelfReq pSmeReq = (tpSirSmeDelStaSelfReq) pMsgBuf; + + pDelStaSelfParams = vos_mem_malloc(sizeof( tDelStaSelfParams)); + if ( NULL == pDelStaSelfParams ) + { + limLog( pMac, LOGP, FL("Unable to allocate memory for tDelStaSelfParams") ); + return; + } + + vos_mem_copy( pDelStaSelfParams->selfMacAddr, pSmeReq->selfMacAddr, sizeof(tSirMacAddr) ); + + pDelStaSelfParams->sessionId = pSmeReq->sessionId; + msg.type = SIR_HAL_DEL_STA_SELF_REQ; + msg.reserved = 0; + msg.bodyptr = pDelStaSelfParams; + msg.bodyval = 0; + + PELOGW(limLog(pMac, LOG1, + FL("sending SIR_HAL_DEL_STA_SELF_REQ msg to HAL"));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); + vos_mem_free(pDelStaSelfParams); + } + return; +} /*** end __limProcessSmeDelStaSelfReq() ***/ + + +/** + * __limProcessSmeRegisterMgmtFrameReq() + * + *FUNCTION: + * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message + * from SME. It Register this information within PE. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__limProcessSmeRegisterMgmtFrameReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + VOS_STATUS vosStatus; + tpSirRegisterMgmtFrame pSmeReq = (tpSirRegisterMgmtFrame)pMsgBuf; + tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL, pNext = NULL; + tANI_BOOLEAN match = VOS_FALSE; + PELOG1(limLog(pMac, LOG1, + FL("registerFrame %d, frameType %d, matchLen %d"), + pSmeReq->registerFrame, pSmeReq->frameType, pSmeReq->matchLen);) + + /* First check whether entry exists already*/ + + vos_list_peek_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, + (vos_list_node_t**)&pLimMgmtRegistration); + + while(pLimMgmtRegistration != NULL) + { + if (pLimMgmtRegistration->frameType == pSmeReq->frameType) + { + if(pSmeReq->matchLen) + { + if (pLimMgmtRegistration->matchLen == pSmeReq->matchLen) + { + if (vos_mem_compare( pLimMgmtRegistration->matchData, + pSmeReq->matchData, pLimMgmtRegistration->matchLen)) + { + /* found match! */ + match = VOS_TRUE; + break; + } + } + } + else + { + /* found match! */ + match = VOS_TRUE; + break; + } + } + vosStatus = vos_list_peek_next ( + &pMac->lim.gLimMgmtFrameRegistratinQueue, + (vos_list_node_t*) pLimMgmtRegistration, + (vos_list_node_t**) &pNext ); + + pLimMgmtRegistration = pNext; + pNext = NULL; + + } + + if (match) + { + vos_list_remove_node(&pMac->lim.gLimMgmtFrameRegistratinQueue, + (vos_list_node_t*)pLimMgmtRegistration); + vos_mem_free(pLimMgmtRegistration); + } + + if(pSmeReq->registerFrame) + { + pLimMgmtRegistration = vos_mem_malloc(sizeof(tLimMgmtFrameRegistration) + pSmeReq->matchLen); + if ( pLimMgmtRegistration != NULL) + { + vos_mem_set((void*)pLimMgmtRegistration, + sizeof(tLimMgmtFrameRegistration) + pSmeReq->matchLen, 0 ); + pLimMgmtRegistration->frameType = pSmeReq->frameType; + pLimMgmtRegistration->matchLen = pSmeReq->matchLen; + pLimMgmtRegistration->sessionId = pSmeReq->sessionId; + if(pSmeReq->matchLen) + { + vos_mem_copy(pLimMgmtRegistration->matchData, + pSmeReq->matchData, pSmeReq->matchLen); + } + vos_list_insert_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, + &pLimMgmtRegistration->node); + } + } + + return; +} /*** end __limProcessSmeRegisterMgmtFrameReq() ***/ + +static tANI_BOOLEAN +__limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) +{ + tpP2pPsParams pMsgNoA; + tSirMsgQ msg; + + pMsgNoA = vos_mem_malloc(sizeof( tP2pPsConfig )); + if ( NULL == pMsgNoA ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during NoA Update" )); + goto error; + } + + vos_mem_set((tANI_U8 *)pMsgNoA, sizeof(tP2pPsConfig), 0); + /* Below params used for opp PS/periodic NOA and are don't care in this case - so initialized to 0 */ + pMsgNoA->opp_ps = 0; + pMsgNoA->ctWindow = 0; + pMsgNoA->duration = 0; + pMsgNoA->interval = 0; + pMsgNoA->count = 0; + + /* Below params used for Single Shot NOA - so assign proper values */ + pMsgNoA->psSelection = P2P_SINGLE_NOA; + pMsgNoA->single_noa_duration = noaDuration; + + /* Start Insert NOA timer + * If insert NOA req fails or NOA rsp fails or start NOA indication doesn't come from FW due to GO session deletion + * or any other failure or reason, we still need to process the deferred SME req. The insert NOA + * timer of 500 ms will ensure the stored SME req always gets processed + */ + if (tx_timer_activate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer) + == TX_TIMER_ERROR) + { + /// Could not activate Insert NOA timer. + // Log error + limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer")); + + // send the scan response back with status failure and do not even call insert NOA + limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_SCAN_FAILED, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId); + vos_mem_free(pMsgNoA); + goto error; + } + + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_INSERT_SINGLESHOT_NOA_TIMER)); + + msg.type = WDA_SET_P2P_GO_NOA_REQ; + msg.reserved = 0; + msg.bodyptr = pMsgNoA; + msg.bodyval = 0; + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + /* In this failure case, timer is already started, so its expiration will take care of sending scan response */ + limLog(pMac, LOGP, FL("wdaPost Msg failed")); + /* Deactivate the NOA timer in failure case */ + limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); + goto error; + } + return FALSE; + +error: + /* In any of the failure cases, just go ahead with the processing of registered deferred SME request without + * worrying about the NOA + */ + limProcessRegdDefdSmeReqAfterNOAStart(pMac); + // msg buffer is consumed and freed in above function so return FALSE + return FALSE; + +} + +static void __limRegisterDeferredSmeReqForNOAStart(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 *pMsgBuf) +{ + limLog(pMac, LOG1, FL("Reg msgType %d"), msgType) ; + pMac->lim.gDeferMsgTypeForNOA = msgType; + pMac->lim.gpDefdSmeMsgForNOA = pMsgBuf; +} + +static void __limDeregisterDeferredSmeReqAfterNOAStart(tpAniSirGlobal pMac) +{ + limLog(pMac, LOG1, FL("Dereg msgType %d"), pMac->lim.gDeferMsgTypeForNOA) ; + pMac->lim.gDeferMsgTypeForNOA = 0; + if (pMac->lim.gpDefdSmeMsgForNOA != NULL) + { + /* __limProcessSmeScanReq consumed the buffer. We can free it. */ + vos_mem_free(pMac->lim.gpDefdSmeMsgForNOA); + pMac->lim.gpDefdSmeMsgForNOA = NULL; + } +} + +static +tANI_U32 limCalculateNOADuration(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 *pMsgBuf) +{ + tANI_U32 noaDuration = 0; + + switch (msgType) + { + case eWNI_SME_SCAN_REQ: + { + tANI_U32 val; + tANI_U8 i; + tpSirSmeScanReq pScanReq = (tpSirSmeScanReq) pMsgBuf; + if (wlan_cfgGetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, &val) != eSIR_SUCCESS) + { + /* + * Could not get max channel value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); + + /* use a default value of 110ms */ + val = DEFAULT_PASSIVE_MAX_CHANNEL_TIME; + } + + for (i = 0; i < pScanReq->channelList.numChannels; i++) { + tANI_U8 channelNum = pScanReq->channelList.channelNumber[i]; + + if (limActiveScanAllowed(pMac, channelNum)) { + /* Use min + max channel time to calculate the total duration of scan */ + noaDuration += pScanReq->minChannelTime + pScanReq->maxChannelTime; + } else { + /* using the value from WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME as is done in + * void limContinuePostChannelScan(tpAniSirGlobal pMac) + */ + noaDuration += val; + } + } + + /* Adding an overhead of 20ms to account for the scan messaging delays */ + noaDuration += SCAN_MESSAGING_OVERHEAD; + noaDuration *= CONV_MS_TO_US; + + break; + } + +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: + noaDuration = OEM_DATA_NOA_DURATION*CONV_MS_TO_US; // use 60 msec as default + break; +#endif + + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + { + tSirRemainOnChnReq *pRemainOnChnReq = (tSirRemainOnChnReq *) pMsgBuf; + noaDuration = (pRemainOnChnReq->duration)*CONV_MS_TO_US; + break; + } + + case eWNI_SME_JOIN_REQ: + noaDuration = JOIN_NOA_DURATION*CONV_MS_TO_US; + break; + + default: + noaDuration = 0; + break; + + } + limLog(pMac, LOGW, FL("msgType %d noa %d"), msgType, noaDuration); + return noaDuration; +} + +void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) +{ + tANI_BOOLEAN bufConsumed = TRUE; + + limLog(pMac, LOG1, FL("Process defd sme req %d"), pMac->lim.gDeferMsgTypeForNOA); + if ( (pMac->lim.gDeferMsgTypeForNOA != 0) && + (pMac->lim.gpDefdSmeMsgForNOA != NULL) ) + { + switch (pMac->lim.gDeferMsgTypeForNOA) + { + case eWNI_SME_SCAN_REQ: + __limProcessSmeScanReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); + break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: + __limProcessSmeOemDataReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); + break; +#endif + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + bufConsumed = limProcessRemainOnChnlReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); + /* limProcessRemainOnChnlReq doesnt want us to free the buffer since + * it is freed in limRemainOnChnRsp. this change is to avoid "double free" + */ + if (FALSE == bufConsumed) + { + pMac->lim.gpDefdSmeMsgForNOA = NULL; + } + break; + case eWNI_SME_JOIN_REQ: + __limProcessSmeJoinReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); + break; + default: + limLog(pMac, LOGE, FL("Unknown deferred msg type %d"), pMac->lim.gDeferMsgTypeForNOA); + break; + } + __limDeregisterDeferredSmeReqAfterNOAStart(pMac); + } + else + { + limLog( pMac, LOGW, FL("start received from FW when no sme deferred msg pending. Do nothing." + "It might happen sometime when NOA start ind and timeout happen at the same time")); + } +} + + +static void +__limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tpSirResetAPCapsChange pResetCapsChange; + tpPESession psessionEntry; + tANI_U8 sessionId = 0; + if (pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pResetCapsChange = (tpSirResetAPCapsChange)pMsgBuf; + psessionEntry = peFindSessionByBssid(pMac, pResetCapsChange->bssId, &sessionId); + if (psessionEntry == NULL) + { + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); + return; + } + + psessionEntry->limSentCapsChangeNtf = false; + return; +} + +/** + * limProcessSmeReqMessages() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function processes SME request messages from HDD or upper layer + * application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the SME message type + * @param *pMsgBuf A pointer to the SME message buffer + * @return Boolean - TRUE - if pMsgBuf is consumed and can be freed. + * FALSE - if pMsgBuf is not to be freed. + */ + +tANI_BOOLEAN +limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tANI_BOOLEAN bufConsumed = TRUE; //Set this flag to false within case block of any following message, that doesnt want pMsgBuf to be freed. + tANI_U32 *pMsgBuf = pMsg->bodyptr; + tpSirSmeScanReq pScanReq; + PELOG1(limLog(pMac, LOG1, FL("LIM Received Global LimMlmState: %s(%d)"), + limMlmStateStr(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState );) + + pScanReq = (tpSirSmeScanReq) pMsgBuf; + /* Special handling of some SME Req msgs where we have an existing GO session and + * want to insert NOA before processing those msgs. These msgs will be processed later when + * start event happens + */ + MTRACE(macTraceMsgRx(pMac, NO_SESSION, pMsg->type)); + switch (pMsg->type) + { + case eWNI_SME_SCAN_REQ: + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + + /* If scan is disabled return from here + */ + if (pMac->lim.fScanDisabled) + { + if (pMsg->type == eWNI_SME_SCAN_REQ) + { + limSendSmeScanRsp(pMac, + offsetof(tSirSmeScanRsp,bssDescription[0]), + eSIR_SME_INVALID_PARAMETERS, + pScanReq->sessionId, + pScanReq->transactionId); + + bufConsumed = TRUE; + } + else if (pMsg->type == eWNI_SME_REMAIN_ON_CHANNEL_REQ) + { + pMac->lim.gpDefdSmeMsgForNOA = NULL; + pMac->lim.gpLimRemainOnChanReq = (tpSirRemainOnChnReq )pMsgBuf; + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + + /* + * limRemainOnChnRsp will free the buffer this change is to + * avoid "double free" + */ + bufConsumed = FALSE; + } + + limLog(pMac, LOGE, + FL("Error: Scan Disabled." + " Return with error status for SME Message type(%d)"), + pMsg->type); + + return bufConsumed; + } + /* + * Do not add BREAK here + */ +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: +#endif + case eWNI_SME_JOIN_REQ: + /* If we have an existing P2P GO session we need to insert NOA before actually process this SME Req */ + if (!pMac->fScanOffload && (limIsNOAInsertReqd(pMac) == TRUE) && + IS_FEATURE_SUPPORTED_BY_FW(P2P_GO_NOA_DECOUPLE_INIT_SCAN)) + { + tANI_U32 noaDuration; + __limRegisterDeferredSmeReqForNOAStart(pMac, pMsg->type, pMsgBuf); + noaDuration = limCalculateNOADuration(pMac, pMsg->type, pMsgBuf); + bufConsumed = __limInsertSingleShotNOAForScan(pMac, noaDuration); + return bufConsumed; + } + } + /* If no insert NOA required then execute the code below */ + + switch (pMsg->type) + { + case eWNI_SME_START_REQ: + __limProcessSmeStartReq(pMac, pMsgBuf); + break; + + case eWNI_SME_SYS_READY_IND: + bufConsumed = __limProcessSmeSysReadyInd(pMac, pMsgBuf); + break; + + case eWNI_SME_START_BSS_REQ: + bufConsumed = __limProcessSmeStartBssReq(pMac, pMsg); + break; + + case eWNI_SME_SCAN_REQ: + __limProcessSmeScanReq(pMac, pMsgBuf); + break; + +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: + __limProcessSmeOemDataReq(pMac, pMsgBuf); + break; +#endif + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + bufConsumed = limProcessRemainOnChnlReq(pMac, pMsgBuf); + break; + + case eWNI_SME_UPDATE_NOA: + __limProcessSmeNoAUpdate(pMac, pMsgBuf); + break; + case eWNI_SME_CLEAR_DFS_CHANNEL_LIST: + __limProcessClearDfsChannelList(pMac, pMsg); + break; + case eWNI_SME_CLEAR_LIM_SCAN_CACHE: + limReInitScanResults(pMac); + break; + case eWNI_SME_JOIN_REQ: + __limProcessSmeJoinReq(pMac, pMsgBuf); + break; + + case eWNI_SME_REASSOC_REQ: + __limProcessSmeReassocReq(pMac, pMsgBuf); + break; + + case eWNI_SME_DISASSOC_REQ: + __limProcessSmeDisassocReq(pMac, pMsgBuf); + break; + + case eWNI_SME_DISASSOC_CNF: + case eWNI_SME_DEAUTH_CNF: + __limProcessSmeDisassocCnf(pMac, pMsgBuf); + break; + + case eWNI_SME_DEAUTH_REQ: + __limProcessSmeDeauthReq(pMac, pMsgBuf); + break; + + case eWNI_SME_SETCONTEXT_REQ: + __limProcessSmeSetContextReq(pMac, pMsgBuf); + break; + + case eWNI_SME_REMOVEKEY_REQ: + __limProcessSmeRemoveKeyReq(pMac, pMsgBuf); + break; + + case eWNI_SME_STOP_BSS_REQ: + bufConsumed = __limProcessSmeStopBssReq(pMac, pMsg); + break; + + case eWNI_SME_ASSOC_CNF: + case eWNI_SME_REASSOC_CNF: + if (pMsg->type == eWNI_SME_ASSOC_CNF) + PELOG1(limLog(pMac, LOG1, FL("Received ASSOC_CNF message"));) + else + PELOG1(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: + PELOG1(limLog(pMac, LOG1, FL("Received ADDTS_REQ message"));) + __limProcessSmeAddtsReq(pMac, pMsgBuf); + break; + + case eWNI_SME_DELTS_REQ: + PELOG1(limLog(pMac, LOG1, FL("Received DELTS_REQ message"));) + __limProcessSmeDeltsReq(pMac, pMsgBuf); + break; + + case SIR_LIM_ADDTS_RSP_TIMEOUT: + PELOG1(limLog(pMac, LOG1, FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message "));) + limProcessSmeAddtsRspTimeout(pMac, pMsg->bodyval); + break; + + case eWNI_SME_STA_STAT_REQ: + case eWNI_SME_AGGR_STAT_REQ: + case eWNI_SME_GLOBAL_STAT_REQ: + case eWNI_SME_STAT_SUMM_REQ: + __limProcessSmeStatsRequest( pMac, pMsgBuf); + //HAL consumes pMsgBuf. It will be freed there. Set bufConsumed to false. + bufConsumed = FALSE; + break; + case eWNI_SME_GET_STATISTICS_REQ: + __limProcessSmeGetStatisticsRequest( pMac, pMsgBuf); + //HAL consumes pMsgBuf. It will be freed there. Set bufConsumed to false. + bufConsumed = FALSE; + break; +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_GET_TSM_STATS_REQ: + __limProcessSmeGetTsmStatsRequest( pMac, pMsgBuf); + bufConsumed = FALSE; + break; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_DEL_BA_PEER_IND: + limProcessSmeDelBaPeerInd(pMac, pMsgBuf); + break; + case eWNI_SME_GET_SCANNED_CHANNEL_REQ: + limProcessSmeGetScanChannelInfo(pMac, pMsgBuf); + break; + case eWNI_SME_GET_ASSOC_STAS_REQ: + limProcessSmeGetAssocSTAsInfo(pMac, pMsgBuf); + break; + case eWNI_SME_TKIP_CNTR_MEAS_REQ: + limProcessTkipCounterMeasures(pMac, pMsgBuf); + break; + case eWNI_SME_EXT_CHANGE_CHANNEL: + lim_process_ext_change_channel(pMac, pMsgBuf); + break; + case eWNI_SME_HIDE_SSID_REQ: + __limProcessSmeHideSSID(pMac, pMsgBuf); + break; + case eWNI_SME_ROAM_RESTART_REQ: + __lim_process_roam_restart_req(pMac, pMsgBuf); + break; + case eWNI_SME_UPDATE_APWPSIE_REQ: + __limProcessSmeUpdateAPWPSIEs(pMac, pMsgBuf); + break; + case eWNI_SME_GET_WPSPBC_SESSION_REQ: + limProcessSmeGetWPSPBCSessions(pMac, pMsgBuf); + break; + + case eWNI_SME_SET_APWPARSNIEs_REQ: + __limProcessSmeSetWPARSNIEs(pMac, pMsgBuf); + break; + + case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: + //Update the beaconInterval + __limProcessSmeChangeBI(pMac, pMsgBuf ); + break; + +#ifdef QCA_HT_2040_COEX + case eWNI_SME_SET_HT_2040_MODE: + __limProcessSmeSetHT2040Mode(pMac, pMsgBuf); + break; +#endif + +#if defined WLAN_FEATURE_VOWIFI + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: + __limProcessReportMessage(pMac, pMsg); + break; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_PRE_AUTH_REQ: + bufConsumed = (tANI_BOOLEAN)limProcessFTPreAuthReq(pMac, pMsg); + break; + case eWNI_SME_FT_UPDATE_KEY: + limProcessFTUpdateKey(pMac, pMsgBuf); + break; + + case eWNI_SME_FT_AGGR_QOS_REQ: + limProcessFTAggrQosReq(pMac, pMsgBuf); + break; +#endif + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_ESE_ADJACENT_AP_REPORT: + limProcessAdjacentAPRepMsg ( pMac, pMsgBuf ); + break; +#endif + case eWNI_SME_ADD_STA_SELF_REQ: + __limProcessSmeAddStaSelfReq( pMac, pMsgBuf ); + break; + case eWNI_SME_DEL_STA_SELF_REQ: + __limProcessSmeDelStaSelfReq( pMac, pMsgBuf ); + break; + + case eWNI_SME_REGISTER_MGMT_FRAME_REQ: + __limProcessSmeRegisterMgmtFrameReq( pMac, pMsgBuf ); + break; +#ifdef FEATURE_WLAN_TDLS + case eWNI_SME_TDLS_SEND_MGMT_REQ: + limProcessSmeTdlsMgmtSendReq(pMac, pMsgBuf); + break; + case eWNI_SME_TDLS_ADD_STA_REQ: + limProcessSmeTdlsAddStaReq(pMac, pMsgBuf); + break; + case eWNI_SME_TDLS_DEL_STA_REQ: + limProcessSmeTdlsDelStaReq(pMac, pMsgBuf); + break; + case eWNI_SME_TDLS_LINK_ESTABLISH_REQ: + limProcesSmeTdlsLinkEstablishReq(pMac, pMsgBuf); + break; +#endif + case eWNI_SME_RESET_AP_CAPS_CHANGED: + __limProcessSmeResetApCapsChange(pMac, pMsgBuf); + break; + + case eWNI_SME_SET_TX_POWER_REQ: + limSendSetTxPowerReq(pMac, pMsgBuf); + break ; + + case eWNI_SME_CHANNEL_CHANGE_REQ: + limProcessSmeChannelChangeRequest(pMac, pMsgBuf); + break; + + case eWNI_SME_START_BEACON_REQ: + limProcessSmeStartBeaconReq(pMac, pMsgBuf); + break; + + case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: + limProcessSmeDfsCsaIeRequest(pMac, pMsgBuf); + break; + + case eWNI_SME_UPDATE_ADDITIONAL_IES: + limProcessUpdateAddIEs(pMac, pMsgBuf); + break; + + case eWNI_SME_MODIFY_ADDITIONAL_IES: + limProcessModifyAddIEs(pMac, pMsgBuf); + break; + + case eWNI_SME_PDEV_SET_HT_VHT_IE: + lim_process_set_pdev_IEs(pMac, pMsgBuf); + break; + default: + vos_mem_free((v_VOID_t*)pMsg->bodyptr); + pMsg->bodyptr = NULL; + break; + } // switch (msgType) + + return bufConsumed; +} /*** end limProcessSmeReqMessages() ***/ + +/** + * limProcessSmeStartBeaconReq() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function processes SME request messages from HDD or upper layer + * application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the SME message type + * @param *pMsgBuf A pointer to the SME message buffer + * @return Boolean - TRUE - if pMsgBuf is consumed and can be freed. + * FALSE - if pMsgBuf is not to be freed. + */ +static void +limProcessSmeStartBeaconReq(tpAniSirGlobal pMac, tANI_U32 * pMsg) +{ + tpSirStartBeaconIndication pBeaconStartInd; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + + if( pMsg == NULL ) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + pBeaconStartInd = (tpSirStartBeaconIndication)pMsg; + if((psessionEntry = + peFindSessionByBssid(pMac, pBeaconStartInd->bssid, &sessionId)) + == NULL) + { + limPrintMacAddr(pMac, pBeaconStartInd->bssid, LOGE); + PELOGE(limLog(pMac, LOGE, + "%s[%d]: Session does not exist for given bssId", + __func__, __LINE__ );) + return; + } + + if (pBeaconStartInd->beaconStartStatus == VOS_TRUE) + { + /* + * Currently this Indication comes from SAP + * to start Beacon Tx on a DFS channel + * since beaconing has to be done on DFS + * channel only after CAC WAIT is completed. + * On a DFS Channel LIM does not start beacon + * Tx right after the WDA_ADD_BSS_RSP. + */ + limApplyConfiguration(pMac,psessionEntry); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("Start Beacon with ssid %s Ch %d"), + psessionEntry->ssId.ssId, + psessionEntry->currentOperChannel); + limSendBeaconInd(pMac, psessionEntry); + } + else + { + limLog(pMac, LOGE,FL("Invalid Beacon Start Indication")); + return; + } +} + +static void +limProcessSmeChannelChangeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + tpSirChanChangeRequest pChannelChangeReq; + tpPESession psessionEntry; + tANI_U8 sessionId; //PE sessionID + tPowerdBm maxTxPwr; + u_int32_t val = 0; +#ifdef WLAN_FEATURE_11AC + tANI_U32 centerChan; + tANI_U32 chanWidth; +#endif + if( pMsg == NULL ) + { + limLog(pMac, LOGE,FL("pMsg is NULL")); + return; + } + pChannelChangeReq = (tpSirChanChangeRequest)pMsg; + + if((psessionEntry = + peFindSessionByBssid(pMac, pChannelChangeReq->bssid, &sessionId)) + == NULL) + { + limPrintMacAddr(pMac, pChannelChangeReq->bssid, LOGE); + PELOGE(limLog(pMac, LOGE, + "%s[%d]: Session does not exist for given bssId", + __func__, __LINE__ );) + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry)) + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_SAP_DFS; + else + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; + + maxTxPwr = cfgGetRegulatoryMaxTransmitPower( pMac, + pChannelChangeReq->targetChannel ); + + if (pChannelChangeReq->messageType == eWNI_SME_CHANNEL_CHANGE_REQ + && + maxTxPwr != WDA_MAX_TXPOWER_INVALID) + { + + /* Store the New Channel Params in psessionEntry */ + if (psessionEntry->currentOperChannel != + pChannelChangeReq->targetChannel) + { + limLog(pMac, LOGE, + FL("switch old chnl %d --> new chnl %d and CH width - %d"), + psessionEntry->currentOperChannel, + pChannelChangeReq->targetChannel, + pChannelChangeReq->vht_channel_width); + + +#ifdef WLAN_FEATURE_11AC + if(psessionEntry->vhtCapability) + { + + chanWidth = pChannelChangeReq->vht_channel_width; + + if(chanWidth == eHT_CHANNEL_WIDTH_20MHZ || chanWidth == eHT_CHANNEL_WIDTH_40MHZ) + { + psessionEntry->vhtTxChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + psessionEntry->apChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + /* + * In case of DFS operation, If AP falls back to lower + * bandwidth [< 80Mhz] then there is no need of + * Center freq segment. So reset it to zero. + */ + if (cfgSetInt(pMac, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, + 0) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("couldn't reset center freq seg 0 in beacon")); + } + psessionEntry->apCenterChan = 0; + } + if (chanWidth == eHT_CHANNEL_WIDTH_80MHZ) + { + psessionEntry->vhtTxChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + psessionEntry->apChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + + centerChan = limGetCenterChannel(pMac, pChannelChangeReq->targetChannel, + pChannelChangeReq->cbMode,WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ); + if(centerChan != eSIR_CFG_INVALID_ID) + { + limLog(pMac, LOGW, FL("***Center Channel for 80MHZ channel width = %d"),centerChan); + psessionEntry->apCenterChan = centerChan; + if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, centerChan) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); + } + } + } + + } + psessionEntry->htSecondaryChannelOffset = limGetHTCBState(pChannelChangeReq->cbMode); + psessionEntry->htSupportedChannelWidthSet = (pChannelChangeReq->cbMode ? 1 : 0); + + psessionEntry->htRecommendedTxWidthSet = + psessionEntry->htSupportedChannelWidthSet; + psessionEntry->currentOperChannel = + pChannelChangeReq->targetChannel; + psessionEntry->limRFBand = + limGetRFBand(psessionEntry->currentOperChannel); + // Initialize 11h Enable Flag + if (SIR_BAND_5_GHZ == psessionEntry->limRFBand) + { + if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != + eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); + } + + psessionEntry->lim11hEnable = val; + psessionEntry->dot11mode = pChannelChangeReq->dot11mode; + + vos_mem_copy((void*)&psessionEntry->rateSet, + (void*)&pChannelChangeReq->operational_rateset, + sizeof(tSirMacRateSet)); + vos_mem_copy((void*)&psessionEntry->extRateSet, + (void*)&pChannelChangeReq->extended_rateset, + sizeof(tSirMacRateSet)); + + limSetChannel(pMac, pChannelChangeReq->targetChannel, + psessionEntry->htSecondaryChannelOffset, + maxTxPwr, + psessionEntry->peSessionId); +#endif + } + + } + else + { + limLog(pMac, LOGE,FL("Invalid Request/maxTxPwr")); + } +} + +/****************************************************************************** + * limStartBssUpdateAddIEBuffer() + * + *FUNCTION: + * This function checks the src buffer and its length and then malloc for + * dst buffer update the same + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param **pDstData_buff A pointer to pointer of tANI_U8 dst buffer + * @param *pDstDataLen A pointer to pointer of tANI_U16 dst buffer length + * @param *pSrcData_buff A pointer of tANI_U8 src buffer + * @param srcDataLen src buffer length +******************************************************************************/ + +static void +limStartBssUpdateAddIEBuffer(tpAniSirGlobal pMac, + tANI_U8 **pDstData_buff, + tANI_U16 *pDstDataLen, + tANI_U8 *pSrcData_buff, + tANI_U16 srcDataLen) +{ + + if (srcDataLen > 0 && pSrcData_buff != NULL) + { + *pDstDataLen = srcDataLen; + + *pDstData_buff = vos_mem_malloc(*pDstDataLen); + + if (NULL == *pDstData_buff) + { + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed for " + "pDstData_buff"));) + return; + } + vos_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); + } + else + { + *pDstData_buff = NULL; + *pDstDataLen = 0; + } +} +/****************************************************************************** + * limUpdateAddIEBuffer() + * + *FUNCTION: + * This function checks the src buffer and length if src buffer length more + * than dst buffer length then free the dst buffer and malloc for the new src + * length, and update the dst buffer and length. But if dst buffer is bigger + * than src buffer length then it just update the dst buffer and length + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param **pDstData_buff A pointer to pointer of tANI_U8 dst buffer + * @param *pDstDataLen A pointer to pointer of tANI_U16 dst buffer length + * @param *pSrcData_buff A pointer of tANI_U8 src buffer + * @param srcDataLen src buffer length +******************************************************************************/ + +static void +limUpdateAddIEBuffer(tpAniSirGlobal pMac, + tANI_U8 **pDstData_buff, + tANI_U16 *pDstDataLen, + tANI_U8 *pSrcData_buff, + tANI_U16 srcDataLen) +{ + + if (NULL == pSrcData_buff) + { + limLog(pMac, LOGE, FL("src buffer is null.")); + return; + } + + if (srcDataLen > *pDstDataLen) + { + *pDstDataLen = srcDataLen; + /* free old buffer */ + vos_mem_free(*pDstData_buff); + /* allocate a new */ + *pDstData_buff = vos_mem_malloc(*pDstDataLen); + + if (NULL == *pDstData_buff) + { + limLog(pMac, LOGE, FL("Memory allocation failed.")); + *pDstDataLen = 0; + return; + } + } + + /* copy the content of buffer into dst buffer + */ + *pDstDataLen = srcDataLen; + vos_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); + +} + +/****************************************************************************** + * limProcessModifyAddIEs() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function update the PE buffers for additional IEs. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer +******************************************************************************/ +static void +limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + tpSirModifyIEsInd pModifyAddIEs = (tpSirModifyIEsInd)pMsg; + tANI_U8 sessionId; + tANI_BOOLEAN ret = FALSE; + + /* Incoming message has smeSession, use BSSID to find PE session*/ + tpPESession psessionEntry = peFindSessionByBssid(pMac, + pModifyAddIEs->modifyIE.bssid, + &sessionId); + + if (NULL != psessionEntry) + { + if ((0 != pModifyAddIEs->modifyIE.ieBufferlength) && + (0 != pModifyAddIEs->modifyIE.ieIDLen) && + (NULL != pModifyAddIEs->modifyIE.pIEBuffer)) + { + + switch (pModifyAddIEs->updateType) + { + case eUPDATE_IE_PROBE_RESP: + { + /* Probe resp */ + break; + } + case eUPDATE_IE_ASSOC_RESP: + /* assoc resp IE */ + if (psessionEntry->addIeParams.assocRespDataLen == 0) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + FL("assoc resp add ie not present %d"), + psessionEntry->addIeParams.assocRespDataLen); + } + /* search through the buffer and modify the IE */ + break; + case eUPDATE_IE_PROBE_BCN: + { + /*probe beacon IE*/ + if (ret == TRUE && pModifyAddIEs->modifyIE.notify) + { + limHandleParamUpdate(pMac, pModifyAddIEs->updateType); + } + break; + } + default: + limLog(pMac, LOGE, FL("unhandled buffer type %d."), + pModifyAddIEs->updateType); + break; + } + } + else + { + limLog(pMac, LOGE, FL("Invalid request pIEBuffer %p ieBufferlength" + " %d ieIDLen %d ieID %d. update Type %d"), + pModifyAddIEs->modifyIE.pIEBuffer, + pModifyAddIEs->modifyIE.ieBufferlength, + pModifyAddIEs->modifyIE.ieID, + pModifyAddIEs->modifyIE.ieIDLen, + pModifyAddIEs->updateType); + } + } + else + { + limLog(pMac, LOGE, FL("Session not found for given bssid. " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pModifyAddIEs->modifyIE.bssid)); + } + vos_mem_free(pModifyAddIEs->modifyIE.pIEBuffer); + pModifyAddIEs->modifyIE.pIEBuffer = NULL; + +} + +/** + * lim_process_set_pdev_IEs() - process the set pdev IE req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: Pointer to the SME message buffer + * + * This function is called by limProcessMessageQueue(). This + * function sets the PDEV IEs to the FW. + * + * Return: None + */ +static void lim_process_set_pdev_IEs(tpAniSirGlobal mac_ctx, tANI_U32 *msg_buf) +{ + struct sir_set_ht_vht_cfg *ht_vht_cfg; + + ht_vht_cfg = (struct sir_set_ht_vht_cfg*)msg_buf; + + if (NULL == ht_vht_cfg) { + limLog(mac_ctx, LOGE, FL("NULL ht_vht_cfg")); + return; + } + + limLog(mac_ctx, LOG1, FL("rcvd set pdev ht vht ie req with nss = %d"), + ht_vht_cfg->nss); + lim_set_pdev_ht_ie(mac_ctx, ht_vht_cfg->pdev_id, ht_vht_cfg->nss); + + if (IS_DOT11_MODE_VHT(ht_vht_cfg->dot11mode)) + lim_set_pdev_vht_ie(mac_ctx, ht_vht_cfg->pdev_id, + ht_vht_cfg->nss); +} + +/** + * lim_set_pdev_ht_ie() - sends the set HT IE req to FW + * + * @mac_ctx: Pointer to Global MAC structure + * @pdev_id: pdev id to set the IE. + * @nss: Nss values to prepare the HT IE. + * + * Prepares the HT IE with self capabilities for different + * Nss values and sends the set HT IE req to FW. + * + * Return: None + */ +static void lim_set_pdev_ht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, + tANI_U8 nss) +{ + struct set_ie_param *ie_params; + tSirMsgQ msg; + tSirRetStatus rc = eSIR_SUCCESS; + v_U8_t *p_ie = NULL; + tHtCaps *p_ht_cap; + int i; + + for (i = nss; i > 0; i--) { + ie_params = vos_mem_malloc(sizeof(*ie_params)); + if (NULL == ie_params) { + limLog(mac_ctx, LOGE, FL("mem alloc failed")); + return; + } + ie_params->nss = i; + ie_params->pdev_id = pdev_id; + ie_params->ie_type = DOT11_HT_IE; + /* 2 for IE len and EID */ + ie_params->ie_len = 2 + sizeof(tHtCaps); + ie_params->ie_ptr = vos_mem_malloc(ie_params->ie_len); + if (NULL == ie_params->ie_ptr) { + vos_mem_free(ie_params); + limLog(mac_ctx, LOGE, FL("mem alloc failed")); + return; + } + *ie_params->ie_ptr = SIR_MAC_HT_CAPABILITIES_EID; + *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2; + lim_set_ht_caps(mac_ctx, NULL, ie_params->ie_ptr, + ie_params->ie_len); + + if (1 == i) { + p_ie = limGetIEPtr(mac_ctx, ie_params->ie_ptr, + ie_params->ie_len, + DOT11F_EID_HTCAPS, ONE_BYTE); + if (NULL == p_ie) { + vos_mem_free(ie_params->ie_ptr); + vos_mem_free(ie_params); + limLog(mac_ctx, LOGE, FL( + "failed to get IE ptr")); + return; + } + p_ht_cap = (tHtCaps *)&p_ie[2]; + p_ht_cap->supportedMCSSet[1] = 0; + p_ht_cap->txSTBC = 0; + } + + msg.type = WDA_SET_PDEV_IE_REQ; + msg.bodyptr = ie_params; + msg.bodyval = 0; + + rc = wdaPostCtrlMsg(mac_ctx, &msg); + if (rc != eSIR_SUCCESS) { + limLog(mac_ctx, LOGE, FL( + "wdaPostCtrlMsg() return failure")); + vos_mem_free(ie_params->ie_ptr); + vos_mem_free(ie_params); + return; + } + } +} + +/** + * lim_set_pdev_vht_ie() - sends the set VHT IE to req FW + * + * @mac_ctx: Pointer to Global MAC structure + * @pdev_id: pdev id to set the IE. + * @nss: Nss values to prepare the VHT IE. + * + * Prepares the VHT IE with self capabilities for different + * Nss values and sends the set VHT IE req to FW. + * + * Return: None + */ +static void lim_set_pdev_vht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, + tANI_U8 nss) +{ + struct set_ie_param *ie_params; + tSirMsgQ msg; + tSirRetStatus rc = eSIR_SUCCESS; + v_U8_t *p_ie = NULL; + tSirMacVHTCapabilityInfo *vht_cap; + int i; + tSirVhtMcsInfo *vht_mcs; + + for (i = nss; i > 0; i--) { + ie_params = vos_mem_malloc(sizeof(*ie_params)); + if (NULL == ie_params) { + limLog(mac_ctx, LOGE, FL("mem alloc failed")); + return; + } + ie_params->nss = i; + ie_params->pdev_id = pdev_id; + ie_params->ie_type = DOT11_VHT_IE; + /* 2 for IE len and EID */ + ie_params->ie_len = 2 + sizeof(tSirMacVHTCapabilityInfo) + + sizeof(tSirVhtMcsInfo); + ie_params->ie_ptr = vos_mem_malloc(ie_params->ie_len); + if (NULL == ie_params->ie_ptr) { + vos_mem_free(ie_params); + limLog(mac_ctx, LOGE, FL("mem alloc failed")); + return; + } + *ie_params->ie_ptr = SIR_MAC_VHT_CAPABILITIES_EID; + *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2; + lim_set_vht_caps(mac_ctx, NULL, ie_params->ie_ptr, + ie_params->ie_len); + + if (1 == i) { + p_ie = limGetIEPtr(mac_ctx, ie_params->ie_ptr, + ie_params->ie_len, + DOT11F_EID_VHTCAPS, ONE_BYTE); + if (NULL == p_ie) { + vos_mem_free(ie_params->ie_ptr); + vos_mem_free(ie_params); + limLog(mac_ctx, LOGE, FL( + "failed to get IE ptr")); + return; + } + vht_cap = (tSirMacVHTCapabilityInfo *)&p_ie[2]; + vht_cap->txSTBC = 0; + vht_mcs = + (tSirVhtMcsInfo *)&p_ie[2 + + sizeof(tSirMacVHTCapabilityInfo)]; + vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS; + vht_mcs->rxHighest = + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + vht_mcs->txMcsMap |= DISABLE_NSS2_MCS; + vht_mcs->txHighest = + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } + msg.type = WDA_SET_PDEV_IE_REQ; + msg.bodyptr = ie_params; + msg.bodyval = 0; + + rc = wdaPostCtrlMsg(mac_ctx, &msg); + if (rc != eSIR_SUCCESS) { + limLog(mac_ctx, LOGE, FL( + "wdaPostCtrlMsg() return failure")); + vos_mem_free(ie_params->ie_ptr); + vos_mem_free(ie_params); + return; + } + } +} +/****************************************************************************** + * limProcessUpdateAddIEs() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function update the PE buffers for additional IEs. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer +******************************************************************************/ +static void +limProcessUpdateAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + tpSirUpdateIEsInd pUpdateAddIEs = (tpSirUpdateIEsInd)pMsg; + tANI_U8 sessionId; + /* incoming message has smeSession, use BSSID to find PE session*/ + tpPESession psessionEntry = peFindSessionByBssid(pMac, + pUpdateAddIEs->updateIE.bssid, + &sessionId); + + if (NULL != psessionEntry) + { + /* if len is 0, upper layer requested freeing of buffer */ + if (0 == pUpdateAddIEs->updateIE.ieBufferlength) + { + switch (pUpdateAddIEs->updateType) + { + case eUPDATE_IE_PROBE_RESP: + vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); + psessionEntry->addIeParams.probeRespData_buff = NULL; + psessionEntry->addIeParams.probeRespDataLen = 0; + break; + case eUPDATE_IE_ASSOC_RESP: + vos_mem_free(psessionEntry->addIeParams.assocRespData_buff); + psessionEntry->addIeParams.assocRespData_buff = NULL; + psessionEntry->addIeParams.assocRespDataLen = 0; + break; + case eUPDATE_IE_PROBE_BCN: + vos_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff); + psessionEntry->addIeParams.probeRespBCNData_buff = NULL; + psessionEntry->addIeParams.probeRespBCNDataLen = 0; + + if (pUpdateAddIEs->updateIE.notify) + { + limHandleParamUpdate(pMac, pUpdateAddIEs->updateType); + } + break; + default: + break; + } + return; + } + + switch (pUpdateAddIEs->updateType) + { + case eUPDATE_IE_PROBE_RESP: + { + if (pUpdateAddIEs->updateIE.append) + { + /* In case of append, allocate new memory with combined length */ + tANI_U16 new_length = pUpdateAddIEs->updateIE.ieBufferlength + + psessionEntry->addIeParams.probeRespDataLen; + tANI_U8 *new_ptr = vos_mem_malloc(new_length); + if (NULL == new_ptr) + { + limLog(pMac, LOGE, FL("Memory allocation failed.")); + /* free incoming buffer in message */ + vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); + return; + } + /* append buffer to end of local buffers */ + vos_mem_copy(new_ptr, + psessionEntry->addIeParams.probeRespData_buff, + psessionEntry->addIeParams.probeRespDataLen); + vos_mem_copy(&new_ptr[psessionEntry->addIeParams.probeRespDataLen], + pUpdateAddIEs->updateIE.pAdditionIEBuffer, + pUpdateAddIEs->updateIE.ieBufferlength); + /* free old memory*/ + vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); + /* adjust length accordingly */ + psessionEntry->addIeParams.probeRespDataLen = new_length; + /* save refernece of local buffer in PE session */ + psessionEntry->addIeParams.probeRespData_buff = new_ptr; + /* free incoming buffer in message */ + vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); + return; + } + limUpdateAddIEBuffer(pMac, + &psessionEntry->addIeParams.probeRespData_buff, + &psessionEntry->addIeParams.probeRespDataLen, + pUpdateAddIEs->updateIE.pAdditionIEBuffer, + pUpdateAddIEs->updateIE.ieBufferlength); + break; + } + case eUPDATE_IE_ASSOC_RESP: + /*assoc resp IE*/ + limUpdateAddIEBuffer(pMac, + &psessionEntry->addIeParams.assocRespData_buff, + &psessionEntry->addIeParams.assocRespDataLen, + pUpdateAddIEs->updateIE.pAdditionIEBuffer, + pUpdateAddIEs->updateIE.ieBufferlength); + break; + case eUPDATE_IE_PROBE_BCN: + /*probe resp Bcn IE*/ + limUpdateAddIEBuffer(pMac, + &psessionEntry->addIeParams.probeRespBCNData_buff, + &psessionEntry->addIeParams.probeRespBCNDataLen, + pUpdateAddIEs->updateIE.pAdditionIEBuffer, + pUpdateAddIEs->updateIE.ieBufferlength); + if (pUpdateAddIEs->updateIE.notify) + { + limHandleParamUpdate(pMac, pUpdateAddIEs->updateType); + } + break; + default: + limLog(pMac, LOGE, FL("unhandled buffer type %d."), + pUpdateAddIEs->updateType); + break; + } + } + else + { + limLog(pMac, LOGE, FL("Session not found for given bssid. " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pUpdateAddIEs->updateIE.bssid)); + } + vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); + pUpdateAddIEs->updateIE.pAdditionIEBuffer = NULL; + +} + +/** + * send_extended_chan_switch_action_frame()- function to send ECSA + * action frame for each sta connected to SAP/GO and AP in case of + * STA . + * @mac_ctx: pointer to global mac structure + * @new_channel: new channel to switch to. + * @ch_bandwidth: BW of channel to calculate op_class + * @session_entry: pe session + * + * This function is called to send ECSA frame for STA/CLI and SAP/GO. + * + * Return: void + */ + +static void send_extended_chan_switch_action_frame(tpAniSirGlobal mac_ctx, + uint16_t new_channel, uint8_t ch_bandwidth, + tpPESession session_entry) +{ + uint16_t op_class; + uint8_t switch_mode = 0, i; + tpDphHashNode psta; + + + op_class = regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + new_channel, + ch_bandwidth); + + if (LIM_IS_AP_ROLE(session_entry) && + (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_FALSE)) + switch_mode = 1; + + if (LIM_IS_AP_ROLE(session_entry)) { + for (i = 0; i < mac_ctx->lim.maxStation; i++) { + psta = + session_entry->dph.dphHashTable.pDphNodeArray + i; + if (psta && psta->added) { + lim_send_extended_chan_switch_action_frame( + mac_ctx, + psta->staAddr, + switch_mode, op_class, new_channel, + LIM_MAX_CSA_IE_UPDATES, session_entry); + } + } + } else if (LIM_IS_STA_ROLE(session_entry)) { + lim_send_extended_chan_switch_action_frame(mac_ctx, + session_entry->bssId, + switch_mode, op_class, new_channel, + LIM_MAX_CSA_IE_UPDATES, session_entry); + } + +} + +/** + * limProcessSmeDfsCsaIeRequest() + * + *FUNCTION: + * This function is called by limProcessMessageQueue(). This + * function processes SME request messages from HDD or upper layer + * application. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + */ +static void +limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + + tpSirDfsCsaIeRequest pDfsCsaIeRequest = (tSirDfsCsaIeRequest *)pMsg; + tpPESession psessionEntry = NULL; + tANI_U32 chanWidth = 0; + tANI_U8 sessionId; + + if ( pMsg == NULL ) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + if ((psessionEntry = + peFindSessionByBssid(pMac, + pDfsCsaIeRequest->bssid, + &sessionId)) == NULL) + { + limLog(pMac, LOGE, + FL("Session not found for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDfsCsaIeRequest->bssid)); + return; + } + + if (psessionEntry->valid && !LIM_IS_AP_ROLE(psessionEntry)) { + limLog(pMac, LOGE, FL("Invalid SystemRole %d"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + return; + } + + if ( psessionEntry ) + { + /* target channel */ + psessionEntry->gLimChannelSwitch.primaryChannel = + pDfsCsaIeRequest->targetChannel; + + /* Channel switch announcement needs to be included in beacon */ + psessionEntry->dfsIncludeChanSwIe = VOS_TRUE; + psessionEntry->gLimChannelSwitch.switchCount = LIM_MAX_CSA_IE_UPDATES; + if (pMac->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_FALSE) + psessionEntry->gLimChannelSwitch.switchMode = 1; + psessionEntry->gLimChannelSwitch.secondarySubBand = + pDfsCsaIeRequest->ch_bandwidth; + + /* Validate if SAP is operating HT or VHT + * mode and set the Channel Switch Wrapper + * element with the Wide Band Switch + * subelement.. + */ +#ifdef WLAN_FEATURE_11AC + if (VOS_TRUE == psessionEntry->vhtCapability) + { + if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == + psessionEntry->vhtTxChannelWidthSet) + { + chanWidth = eHT_CHANNEL_WIDTH_80MHZ; + } + else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == + psessionEntry->vhtTxChannelWidthSet) + { + chanWidth = psessionEntry->htSupportedChannelWidthSet; + } + + /* + * Now encode the Wider Channel BW element + * depending on the chanWidth. + */ + switch(chanWidth) + { + case eHT_CHANNEL_WIDTH_20MHZ: + /* + * Wide channel BW sublement in channel + * wrapper element is not required in case + * of 20 Mhz operation. Currently It is set + * only set in case of 40/80 Mhz Operation. + */ + psessionEntry->dfsIncludeChanWrapperIe = VOS_FALSE; + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + break; + case eHT_CHANNEL_WIDTH_40MHZ: + psessionEntry->dfsIncludeChanWrapperIe = VOS_TRUE; + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + break; + case eHT_CHANNEL_WIDTH_80MHZ: + psessionEntry->dfsIncludeChanWrapperIe = VOS_TRUE; + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + break; + case eHT_CHANNEL_WIDTH_160MHZ: + psessionEntry->dfsIncludeChanWrapperIe = VOS_TRUE; + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + break; + default: + psessionEntry->dfsIncludeChanWrapperIe = VOS_FALSE; + /* Need to handle 80+80 Mhz Scenario + * When 80+80 is supported set the + * gLimWiderBWChannelSwitch.newChanWidth + * to 3 + */ + PELOGE(limLog(pMac, LOGE, FL("Invalid Channel Width"));) + break; + } + /* + * Fetch the center channel based on the channel width + */ + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = + limGetCenterChannel(pMac, + pDfsCsaIeRequest->targetChannel, + psessionEntry->htSecondaryChannelOffset, + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth); + /* + * This is not applicable for 20/40/80 Mhz. + * Only used when we support 80+80 Mhz + * operation. In case of 80+80 Mhz, this + * parameter indicates center channel + * frequency index of 80 Mhz channel + * of frequency segment 1. + */ + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = 0; + } +#endif + /* Send CSA IE request from here */ + if (schSetFixedBeaconFields(pMac, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to set CSA IE in beacon"));) + return; + } + + /* First beacon update request is sent here, the remaining updates are + * done when the FW responds back after sending the first beacon after + * the template update + */ + limSendBeaconInd(pMac, psessionEntry); + limLog(pMac, LOG1, + FL(" Updated CSA IE, IE COUNT = %d"), + psessionEntry->gLimChannelSwitch.switchCount ); + /* Send ECSA Action frame after updating the beacon */ + send_extended_chan_switch_action_frame(pMac, + psessionEntry->gLimChannelSwitch.primaryChannel, + psessionEntry->gLimChannelSwitch.secondarySubBand, + psessionEntry); + psessionEntry->gLimChannelSwitch.switchCount--; + } + return; +} + +/** + * lim_process_ext_change_channel()- function to send ECSA + * action frame for STA/CLI . + * @mac_ctx: pointer to global mac structure + * @msg: params from sme for new channel. + * + * This function is called to send ECSA frame for STA/CLI. + * + * Return: void + */ + +static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx, + uint32_t *msg) +{ + struct sir_sme_ext_cng_chan_req *ext_chng_channel = + (struct sir_sme_ext_cng_chan_req *) msg; + tpPESession session_entry = NULL; + + if (NULL == msg) { + limLog(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + session_entry = + pe_find_session_by_sme_session_id(mac_ctx, + ext_chng_channel->session_id); + if (NULL == session_entry) { + limLog(mac_ctx, LOGE, + FL("Session not found for given session %d"), + ext_chng_channel->session_id); + return; + } + if (LIM_IS_AP_ROLE(session_entry)) { + limLog(mac_ctx, LOGE, + FL("not an STA/CLI session")); + return; + } + send_extended_chan_switch_action_frame(mac_ctx, + ext_chng_channel->new_channel, + 0, session_entry); +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c new file mode 100644 index 000000000000..5ce5580f58f5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c @@ -0,0 +1,3326 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + limProcessTdls.c + + OVERVIEW: + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header$$DateTime$$Author$ + + + when who what, where, why +---------- --- -------------------------------------------------------- +05/05/2010 Ashwani Initial Creation, added TDLS action frame functionality, + TDLS message exchange with SME..etc.. + +===========================================================================*/ + + +/** + * \file limProcessTdls.c + * + * \brief Code for preparing,processing and sending 802.11z action frames + * + */ + +#ifdef FEATURE_WLAN_TDLS + +#include "sirApi.h" +#include "aniGlobal.h" +#include "sirMacProtDef.h" +#include "cfgApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limSecurityUtils.h" +#include "dot11f.h" +#include "limStaHashApi.h" +#include "schApi.h" +#include "limSendMessages.h" +#include "utilsParser.h" +#include "limAssocUtils.h" +#include "dphHashTable.h" +#include "wlan_qct_wda.h" +#include "regdomain_common.h" + +/* define NO_PAD_TDLS_MIN_8023_SIZE to NOT padding: See CR#447630 +There was IOT issue with cisco 1252 open mode, where it pads +discovery req/teardown frame with some junk value up to min size. +To avoid this issue, we pad QCOM_VENDOR_IE. +If there is other IOT issue because of this bandage, define NO_PAD... +*/ +#ifndef NO_PAD_TDLS_MIN_8023_SIZE +#define MIN_IEEE_8023_SIZE 46 +#define MIN_VENDOR_SPECIFIC_IE_SIZE 5 +#endif + +static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac, + tSirTdlsAddStaReq *pAddStaReq, + tpPESession psessionEntry) ; +void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry, + tDot11fIELinkIdentifier *linkIden, + tSirMacAddr peerMac, tANI_U8 reqType) ; +void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEExtCap *extCapability) ; + +void PopulateDot11fTdlsOffchannelParams(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIESuppChannels *suppChannels, + tDot11fIESuppOperatingClasses *suppOperClasses); +void limLogVHTCap(tpAniSirGlobal pMac, + tDot11fIEVHTCaps *pDot11f); +tSirRetStatus limPopulateVhtMcsSet(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tDot11fIEVHTCaps *pPeerVHTCaps, + tpPESession psessionEntry, + uint8_t nss); +ePhyChanBondState limGetHTCBState(ePhyChanBondState aniCBMode); + +/* + * TDLS data frames will go out/come in as non-qos data. + * so, eth_890d_header will be aligned access.. + */ +static const tANI_U8 eth_890d_header[] = +{ + 0xaa, 0xaa, 0x03, 0x00, + 0x00, 0x00, 0x89, 0x0d, +} ; + +/* + * type of links used in TDLS + */ +enum tdlsLinks +{ + TDLS_LINK_AP, + TDLS_LINK_DIRECT +} eTdlsLink ; + +/* + * node status in node searching + */ +enum tdlsLinkNodeStatus +{ + TDLS_NODE_NOT_FOUND, + TDLS_NODE_FOUND +} eTdlsLinkNodeStatus ; + + +enum tdlsReqType +{ + TDLS_INITIATOR, + TDLS_RESPONDER +} eTdlsReqType ; + +typedef enum tdlsLinkSetupStatus +{ + TDLS_SETUP_STATUS_SUCCESS = 0, + TDLS_SETUP_STATUS_FAILURE = 37 +}etdlsLinkSetupStatus ; + +/* These maps to Kernel TDLS peer capability + * flags and should get changed as and when necessary + */ +enum tdls_peer_capability { + TDLS_PEER_HT_CAP = 0, + TDLS_PEER_VHT_CAP = 1, + TDLS_PEER_WMM_CAP = 2 +} eTdlsPeerCapability; + +/* some local defines */ +#define LINK_IDEN_ADDR_OFFSET(x) (&x.LinkIdentifier) +#define PTI_LINK_IDEN_OFFSET (5) +#define PTI_BUF_STATUS_OFFSET (25) + +/* TODO, Move this parameters to configuration */ +#define PEER_PSM_SUPPORT (0) +#define TDLS_SUPPORT (1) +#define TDLS_PROHIBITED (0) +#define TDLS_CH_SWITCH_PROHIBITED (1) +/** @brief Set bit manipulation macro */ +#define SET_BIT(value,mask) ((value) |= (1 << (mask))) +/** @brief Clear bit manipulation macro */ +#define CLEAR_BIT(value,mask) ((value) &= ~(1 << (mask))) +/** @brief Check bit manipulation macro */ +#define CHECK_BIT(value, mask) ((value) & (1 << (mask))) + +#define SET_PEER_AID_BITMAP(peer_bitmap, aid) \ + if ((aid) < (sizeof(tANI_U32) << 3)) \ + SET_BIT(peer_bitmap[0], (aid)); \ + else if ((aid) < (sizeof(tANI_U32) << 4)) \ + SET_BIT(peer_bitmap[1], ((aid) - (sizeof(tANI_U32) << 3))); + +#define CLEAR_PEER_AID_BITMAP(peer_bitmap, aid) \ + if ((aid) < (sizeof(tANI_U32) << 3)) \ + CLEAR_BIT(peer_bitmap[0], (aid)); \ + else if ((aid) < (sizeof(tANI_U32) << 4)) \ + CLEAR_BIT(peer_bitmap[1], ((aid) - (sizeof(tANI_U32) << 3))); + + +#ifdef LIM_DEBUG_TDLS + +#ifdef FEATURE_WLAN_TDLS +#define WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT (800) +#define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200) +#endif + +#define IS_QOS_ENABLED(psessionEntry) ((((psessionEntry)->limQosEnabled) && \ + SIR_MAC_GET_QOS((psessionEntry)->limCurrentBssCaps)) || \ + (((psessionEntry)->limWmeEnabled ) && \ + LIM_BSS_CAPS_GET(WME, (psessionEntry)->limCurrentBssQosCaps))) + +#define TID_AC_VI 4 +#define TID_AC_BK 1 + +const tANI_U8* limTraceTdlsActionString( tANI_U8 tdlsActionCode ) +{ + switch( tdlsActionCode ) + { + CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_REQ); + CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_RSP); + CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_CNF); + CASE_RETURN_STRING(SIR_MAC_TDLS_TEARDOWN); + CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_IND); + CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_REQ); + CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_RSP); + CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_RSP); + CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_REQ); + CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_RSP); + } + return (const tANI_U8*)"UNKNOWN"; +} +#endif +/* + * initialize TDLS setup list and related data structures. + */ +void limInitTdlsData(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + limInitPeerIdxpool(pMac, pSessionEntry) ; + + return ; +} +/* + * prepare TDLS frame header, it includes + * | | | | + * |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD + * | | | | + */ +static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, + tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, + tANI_U8 tid, tpPESession psessionEntry) +{ + tpSirMacDataHdr3a pMacHdr ; + tANI_U32 header_offset = 0 ; + tANI_U8 *addr1 = NULL ; + tANI_U8 *addr3 = NULL ; + tpDphHashNode pStaDs = NULL; + tANI_U16 aid = 0; + tANI_U8 qosMode = 0; + + tANI_U8 toDs = (tdlsLinkType == TDLS_LINK_AP) + ? ANI_TXDIR_TODS :ANI_TXDIR_IBSS ; + tANI_U8 *peerMac = (reqType == TDLS_INITIATOR) + ? link_iden->RespStaAddr : link_iden->InitStaAddr; + tANI_U8 *staMac = (reqType == TDLS_INITIATOR) + ? link_iden->InitStaAddr : link_iden->RespStaAddr; + + pMacHdr = (tpSirMacDataHdr3a) (pFrame); + + /* + * if TDLS frame goes through the AP link, it follows normal address + * pattern, if TDLS frame goes thorugh the direct link, then + * A1--> Peer STA addr, A2-->Self STA address, A3--> BSSID + */ + (tdlsLinkType == TDLS_LINK_AP) ? ((addr1 = (link_iden->bssid)), + (addr3 = (peerMac))) + : ((addr1 = (peerMac)), + (addr3 = (link_iden->bssid))) ; + /* + * prepare 802.11 header + */ + pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + pMacHdr->fc.type = SIR_MAC_DATA_FRAME ; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, + &psessionEntry->dph.dphHashTable); + if (pStaDs) + { + qosMode = pStaDs->qosMode; + } + pMacHdr->fc.subType = ((IS_QOS_ENABLED(psessionEntry) && + (tdlsLinkType == TDLS_LINK_AP)) || + ((tdlsLinkType == TDLS_LINK_DIRECT) && qosMode)) + ? SIR_MAC_DATA_QOS_DATA : SIR_MAC_DATA_DATA; + + /* + * TL is not setting up below fields, so we are doing it here + */ + pMacHdr->fc.toDS = toDs ; + pMacHdr->fc.powerMgmt = 0 ; + pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE)? 0 : 1; + + + vos_mem_copy( (tANI_U8 *) pMacHdr->addr1, + (tANI_U8 *)addr1, + sizeof( tSirMacAddr )); + vos_mem_copy( (tANI_U8 *) pMacHdr->addr2, + (tANI_U8 *) staMac, + sizeof( tSirMacAddr )); + + vos_mem_copy( (tANI_U8 *) pMacHdr->addr3, + (tANI_U8 *) (addr3), + sizeof( tSirMacAddr )); + + limLog(pMac, LOG1, + FL("Preparing TDLS frame header to %s A1:"MAC_ADDRESS_STR", A2:"MAC_ADDRESS_STR", A3:"MAC_ADDRESS_STR), + (tdlsLinkType == TDLS_LINK_AP) ? "AP" : "DIRECT", + MAC_ADDR_ARRAY(pMacHdr->addr1), + MAC_ADDR_ARRAY(pMacHdr->addr2), + MAC_ADDR_ARRAY(pMacHdr->addr3)); + + if (((tdlsLinkType == TDLS_LINK_AP) && (IS_QOS_ENABLED(psessionEntry))) || + ((tdlsLinkType == TDLS_LINK_DIRECT) && qosMode)) + { + pMacHdr->qosControl.tid = tid; + header_offset += sizeof(tSirMacDataHdr3a); + } + else + header_offset += sizeof(tSirMacMgmtHdr); + + /* + * Now form RFC1042 header + */ + vos_mem_copy((tANI_U8 *)(pFrame + header_offset), + (tANI_U8 *)eth_890d_header, sizeof(eth_890d_header)) ; + + header_offset += sizeof(eth_890d_header) ; + + /* add payload type as TDLS */ + *(pFrame + header_offset) = PAYLOAD_TYPE_TDLS ; + + return(header_offset += PAYLOAD_TYPE_TDLS_SIZE) ; +} + +/* + * TX Complete for Management frames + */ + eHalStatus limMgmtTXComplete(tpAniSirGlobal pMac, + tANI_U32 txCompleteSuccess) +{ + tpPESession psessionEntry = NULL ; + + if (0xff != pMac->lim.mgmtFrameSessionId) + { + psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.mgmtFrameSessionId); + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("sessionID %d is not found"), + pMac->lim.mgmtFrameSessionId); + return eHAL_STATUS_FAILURE; + } + limSendSmeMgmtTXCompletion(pMac, psessionEntry, txCompleteSuccess); + pMac->lim.mgmtFrameSessionId = 0xff; + } + return eHAL_STATUS_SUCCESS; +} + +/* + * This function can be used for bacst or unicast discovery request + * We are not differentiating it here, it will all depnds on peer MAC address, + */ +tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, + tANI_U8 dialog, tpPESession psessionEntry) +{ + tDot11fTDLSDisReq tdlsDisReq ; + tANI_U32 status = 0 ; + tANI_U32 nPayload = 0 ; + tANI_U32 size = 0 ; + tANI_U32 nBytes = 0 ; + tANI_U32 header_offset = 0 ; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + tANI_U32 padLen = 0; +#endif + tANI_U8 smeSessionId = 0; + + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("psessionEntry is NULL")); + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11fPackProbeRequest' (for + * serialization). We start by zero-initializing the structure: + */ + vos_mem_set( (tANI_U8*)&tdlsDisReq, + sizeof( tDot11fTDLSDisReq ), 0 ); + + /* + * setup Fixed fields, + */ + tdlsDisReq.Category.category = SIR_MAC_ACTION_TDLS ; + tdlsDisReq.Action.action = SIR_MAC_TDLS_DIS_REQ ; + tdlsDisReq.DialogToken.token = dialog ; + + + size = sizeof(tSirMacAddr) ; + + PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsDisReq.LinkIdentifier, + peer_mac, TDLS_INITIATOR) ; + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11fGetPackedTDLSDisReqSize( pMac, &tdlsDisReq, &nPayload); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to calculate the packed size for a discovery Request (0x%08x)."), + status ); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof( tDot11fTDLSDisReq ); + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while calculating the packed size for a discovery Request (0x%08x)."), + status ); + } + + /* + * This frame is going out from PE as data frames with special ethertype + * 89-0d. + * 8 bytes of RFC 1042 header + */ + + + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE ; + +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) + Hence AP itself padding some bytes, which caused teardown packet is dropped at + receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64 + */ + if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) + { + padLen = MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE ) ; + + /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */ + if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE) + padLen = MIN_VENDOR_SPECIFIC_IE_SIZE; + + nBytes += padLen; + } +#endif + + /* Ok-- try to allocate memory from MGMT PKT pool */ + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("Failed to allocate %d bytes for a TDLS Discovery Request."), + nBytes ); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + vos_mem_set( pFrame, nBytes, 0 ); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, TID_AC_VI, psessionEntry) ; + + status = dot11fPackTDLSDisReq( pMac, &tdlsDisReq, pFrame + + header_offset, nPayload, &nPayload ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, FL("Failed to pack a TDLS discovery req (0x%08x)."), + status ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while packing TDLS Discovery Request (0x%08x)."), + status ); + } + +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + if (padLen != 0) + { + /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */ + tANI_U8 *padVendorSpecific = pFrame + header_offset + nPayload; + /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */ + padVendorSpecific[0] = 221; + padVendorSpecific[1] = padLen - 2; + padVendorSpecific[2] = 0x00; + padVendorSpecific[3] = 0xA0; + padVendorSpecific[4] = 0xC6; + + limLog(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"), padLen); + + /* padding zero if more than 5 bytes are required */ + if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE) + vos_mem_set( pFrame + header_offset + nPayload + MIN_VENDOR_SPECIFIC_IE_SIZE, + padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0); + } +#endif + + limLog(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_DIS_REQ, + limTraceTdlsActionString(SIR_MAC_TDLS_DIS_REQ), + MAC_ADDR_ARRAY(peer_mac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.mgmtFrameSessionId = 0xff; + limLog(pMac, LOGE, FL("could not send TDLS Discovery Request frame")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} + + + + +/* + * This static function is consistent with any kind of TDLS management + * frames we are sending. Currently it is being used by limSendTdlsDisRspFrame, + * limSendTdlsLinkSetupReqFrame and limSendTdlsSetupRspFrame + */ +static void PopulateDot11fTdlsHtVhtCap(tpAniSirGlobal pMac, uint32 selfDot11Mode, + tDot11fIEHTCaps *htCap, tDot11fIEVHTCaps *vhtCap, + tpPESession psessionEntry) +{ + uint8_t nss; + uint32_t val; + + if (IS_5G_CH(psessionEntry->currentOperChannel)) + nss = pMac->vdev_type_nss_5g.tdls; + else + nss = pMac->vdev_type_nss_2g.tdls; + + nss = VOS_MIN(nss, pMac->user_configured_nss); + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, htCap ); + val = SIZE_OF_SUPPORTED_MCS_SET; + wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET, + &htCap->supportedMCSSet[0], &val); + if (NSS_1x1_MODE == nss) + htCap->supportedMCSSet[1] = 0; + /* + * Advertize ht capability and max supported channel + * bandwidth when populating HT IE in TDLS Setup Request/ + * Setup Response/Setup Confirmation frames. + * 11.21.6.2 Setting up a 40 MHz direct link: A 40 MHz off-channel + * direct link may be started if both TDLS peer STAs indicated + * 40 MHz support in the Supported Channel Width Set field of the + * HT Capabilities element (which is included in the TDLS Setup Request + * frame and the TDLS Setup Response frame). Switching to a 40 MHz + * off-channel direct link is achieved by including the following + * information in the TDLS Channel Switch Request + * 11.21.1 General: The channel width of the TDLS direct link on the + * base channel shall not exceed the channel width of the BSS to which + * the TDLS peer STAs are associated. + */ + htCap->supportedChannelWidthSet = 1; + } + else + { + htCap->present = 0; + } + limLog(pMac, LOG1, FL("HT present = %hu, Chan Width = %hu"), + htCap->present, htCap->supportedChannelWidthSet); +#ifdef WLAN_FEATURE_11AC + if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) && + pMac->roam.configParam.enableVhtFor24GHz) || + (psessionEntry->currentOperChannel >= SIR_11B_CHANNEL_END)) + { + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps(pMac, psessionEntry, vhtCap); + vhtCap->suBeamformeeCap = 0; + vhtCap->suBeamFormerCap = 0; + vhtCap->muBeamformeeCap = 0; + vhtCap->muBeamformerCap = 0; + + wlan_cfgGetInt(pMac, WNI_CFG_VHT_RX_MCS_MAP, &val); + vhtCap->rxMCSMap = val; + wlan_cfgGetInt(pMac, WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + &val); + vhtCap->rxHighSupDataRate = val; + wlan_cfgGetInt(pMac, WNI_CFG_VHT_TX_MCS_MAP, &val); + vhtCap->txMCSMap = val; + wlan_cfgGetInt(pMac, WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + &val); + vhtCap->txSupDataRate = val; + if (nss == NSS_1x1_MODE) { + vhtCap->txMCSMap |= DISABLE_NSS2_MCS; + vhtCap->rxMCSMap |= DISABLE_NSS2_MCS; + vhtCap->txSupDataRate = + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + vhtCap->rxHighSupDataRate = + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } + } + else + { + vhtCap->present = 0; + } + } + else + { + /* Vht Disable from ini in 2.4 GHz */ + vhtCap->present = 0; + } + limLog(pMac, LOG1, FL("VHT present = %hu, Chan Width = %hu"), + vhtCap->present, vhtCap->supportedChannelWidthSet); +#endif +} + +/* + * Send TDLS discovery response frame on direct link. + */ + +static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, tANI_U8 dialog, + tpPESession psessionEntry, tANI_U8 *addIe, + tANI_U16 addIeLen) +{ + tDot11fTDLSDisRsp tdlsDisRsp ; + tANI_U16 caps = 0 ; + tANI_U32 status = 0 ; + tANI_U32 nPayload = 0 ; + tANI_U32 nBytes = 0 ; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; + tANI_U8 smeSessionId = 0; + + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("psessionEntry is NULL")); + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11fPackProbeRequest' (for + * serialization). We start by zero-initializing the structure: + */ + vos_mem_set( ( tANI_U8* )&tdlsDisRsp, + sizeof( tDot11fTDLSDisRsp ), 0 ); + + /* + * setup Fixed fields, + */ + tdlsDisRsp.Category.category = SIR_MAC_ACTION_PUBLIC_USAGE; + tdlsDisRsp.Action.action = SIR_MAC_TDLS_DIS_RSP ; + tdlsDisRsp.DialogToken.token = dialog ; + + PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsDisRsp.LinkIdentifier, + peerMac, TDLS_RESPONDER) ; + + if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS) + { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve Capabilities value")); + } + swapBitField16(caps, ( tANI_U16* )&tdlsDisRsp.Capabilities ); + + /* populate supported rate and ext supported rate IE */ + if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac, &tdlsDisRsp.SuppRates, + &tdlsDisRsp.ExtSuppRates)) + limLog(pMac, LOGE, FL("could not populate supported data rates")); + + + /* Populate extended capability IE */ + PopulateDot11fTdlsExtCapability(pMac, psessionEntry, &tdlsDisRsp.ExtCap); + + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + + /* Populate HT/VHT Capabilities */ + PopulateDot11fTdlsHtVhtCap( pMac, selfDot11Mode, &tdlsDisRsp.HTCaps, + &tdlsDisRsp.VHTCaps, psessionEntry ); + + /* Populate TDLS offchannel param only if offchannel is enabled + * and TDLS Channel Switching is not prohibited by AP in ExtCap + * IE in assoc/re-assoc response. + */ + if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) && + (!psessionEntry->tdls_chan_swit_prohibited)) + { + PopulateDot11fTdlsOffchannelParams( pMac, psessionEntry, + &tdlsDisRsp.SuppChannels, + &tdlsDisRsp.SuppOperatingClasses); + if ( pMac->roam.configParam.bandCapability != eCSR_BAND_24) + { + tdlsDisRsp.HT2040BSSCoexistence.present = 1; + tdlsDisRsp.HT2040BSSCoexistence.infoRequest = 1; + } + } + else + { + limLog(pMac, LOG1, + FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"), + pMac->lim.gLimTDLSOffChannelEnabled, + psessionEntry->tdls_chan_swit_prohibited); + } + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11fGetPackedTDLSDisRspSize( pMac, &tdlsDisRsp, &nPayload); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to calculate the packed size for a Discovery Response (0x%08x)."), + status ); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while calculating the packed size for a Discovery Response (0x%08x)."), + status); + } + + /* + * This frame is going out from PE as data frames with special ethertype + * 89-0d. + * 8 bytes of RFC 1042 header + */ + + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + addIeLen; + + /* Ok-- try to allocate memory from MGMT PKT pool */ + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("Failed to allocate %d bytes for a TDLS Discovery Response."), + nBytes ); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + vos_mem_set( pFrame, nBytes, 0 ); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * response frame + */ + + /* Make public Action Frame */ + + limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peerMac, psessionEntry->selfMacAddr); + + { + tpSirMacMgmtHdr pMacHdr; + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + pMacHdr->fc.toDS = ANI_TXDIR_IBSS; + pMacHdr->fc.powerMgmt = 0 ; + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + } + + status = dot11fPackTDLSDisRsp( pMac, &tdlsDisRsp, pFrame + + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to pack a TDLS Discovery Response (0x%08x)."), + status ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while packing TDLS Discovery Response (0x%08x)."), + status ); + } + if (0 != addIeLen) + { + limLog(pMac, LOG1, FL("Copy Additional Ie Len = %d"), addIeLen ); + vos_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload, + addIe, + addIeLen); + } + limLog(pMac, LOG1, + FL("[TDLS] action %d (%s) -DIRECT-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_DIS_RSP, + limTraceTdlsActionString(SIR_MAC_TDLS_DIS_RSP), + MAC_ADDR_ARRAY(peerMac)); + + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + /* + * Transmit Discovery response and watch if this is delivered to + * peer STA. + */ + /* In CLD 2.0, pass Discovery Response as mgmt frame so that + * wma does not do header conversion to 802.3 before calling tx/rx + * routine and subsequenly target also sends frame as is OTA + */ + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_IBSS, + 0, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_SELF_STA_REQUESTED_MASK, smeSessionId, false ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.mgmtFrameSessionId = 0xff; + limLog(pMac, LOGE, FL("could not send TDLS Discovery Response frame!")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} + +/* + * This static function is currently used by limSendTdlsLinkSetupReqFrame and + * limSendTdlsSetupRspFrame to populate the AID if device is 11ac capable. + */ +static void PopulateDotfTdlsVhtAID(tpAniSirGlobal pMac, uint32 selfDot11Mode, + tSirMacAddr peerMac, tDot11fIEAID *Aid, + tpPESession psessionEntry) +{ + if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) && + pMac->roam.configParam.enableVhtFor24GHz) || + (psessionEntry->currentOperChannel >= SIR_11B_CHANNEL_END)) + { + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + + tANI_U16 aid; + tpDphHashNode pStaDs; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs) + { + Aid->present = 1; + Aid->assocId = aid | LIM_AID_MASK; // set bit 14 and 15 1's + } + else + { + Aid->present = 0; + limLog(pMac, LOGE, FL("pStaDs is NULL for " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(peerMac)); + } + } + } + else + { + Aid->present = 0; + limLog(pMac, LOGW, FL("Vht not enable from ini for 2.4GHz.")); + } +} + +/* + * TDLS setup Request frame on AP link + */ + +tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry, + tANI_U8 *addIe, tANI_U16 addIeLen) +{ + tDot11fTDLSSetupReq tdlsSetupReq ; + tANI_U16 caps = 0 ; + tANI_U32 status = 0 ; + tANI_U32 nPayload = 0 ; + tANI_U32 nBytes = 0 ; + tANI_U32 header_offset = 0 ; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; + uint32 selfDot11Mode; + tANI_U8 smeSessionId = 0; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; + + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11fPackProbeRequest' (for + * serialization). We start by zero-initializing the structure: + */ + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set(( tANI_U8* )&tdlsSetupReq, sizeof( tDot11fTDLSSetupReq ), 0); + tdlsSetupReq.Category.category = SIR_MAC_ACTION_TDLS ; + tdlsSetupReq.Action.action = SIR_MAC_TDLS_SETUP_REQ ; + tdlsSetupReq.DialogToken.token = dialog ; + + + PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupReq.LinkIdentifier, + peerMac, TDLS_INITIATOR) ; + + if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS) + { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + limLog(pMac, LOGE, FL("could not retrieve Capabilities value")); + } + swapBitField16(caps, ( tANI_U16* )&tdlsSetupReq.Capabilities ); + + /* populate supported rate and ext supported rate IE */ + populate_dot11f_rates_tdls(pMac, &tdlsSetupReq.SuppRates, + &tdlsSetupReq.ExtSuppRates); + + /* Populate extended supported rates */ + PopulateDot11fTdlsExtCapability(pMac, psessionEntry, &tdlsSetupReq.ExtCap); + + if (1 == pMac->lim.gLimTDLSWmmMode) + { + tANI_U32 val = 0; + + limLog(pMac, LOG1, FL("populate WMM IE in Setup Request Frame")); + /* include WMM IE */ + tdlsSetupReq.WMMInfoStation.version = SIR_MAC_OUI_VERSION_1; + tdlsSetupReq.WMMInfoStation.acvo_uapsd = + (pMac->lim.gLimTDLSUapsdMask & 0x01); + tdlsSetupReq.WMMInfoStation.acvi_uapsd = + ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1); + tdlsSetupReq.WMMInfoStation.acbk_uapsd = + ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2); + tdlsSetupReq.WMMInfoStation.acbe_uapsd = + ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3); + + if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + limLog(pMac, LOGE, FL("could not retrieve Max SP Length")); + + tdlsSetupReq.WMMInfoStation.max_sp_length = (tANI_U8)val; + tdlsSetupReq.WMMInfoStation.present = 1; + } + else + { + /* + * TODO: we need to see if we have to support conditions where we have + * EDCA parameter info element is needed a) if we need different QOS + * parameters for off channel operations or QOS is not supported on + * AP link and we wanted to QOS on direct link. + */ + /* Populate QOS info, needed for Peer U-APSD session */ + /* TODO: Now hardcoded, because PopulateDot11fQOSCapsStation() depends + on AP's capability, and TDLS doesn't want to depend on AP's capability */ + limLog(pMac, LOG1, FL("populate QOS IE in Setup Request Frame")); + tdlsSetupReq.QOSCapsStation.present = 1; + tdlsSetupReq.QOSCapsStation.max_sp_length = 0; + tdlsSetupReq.QOSCapsStation.qack = 0; + tdlsSetupReq.QOSCapsStation.acbe_uapsd = ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3); + tdlsSetupReq.QOSCapsStation.acbk_uapsd = ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2); + tdlsSetupReq.QOSCapsStation.acvi_uapsd = ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1); + tdlsSetupReq.QOSCapsStation.acvo_uapsd = (pMac->lim.gLimTDLSUapsdMask & 0x01); + } + + /* + * we will always try to init TDLS link with 11n capabilities + * let TDLS setup response to come, and we will set our caps based + * of peer caps + */ + + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + + /* Populate HT/VHT Capabilities */ + PopulateDot11fTdlsHtVhtCap( pMac, selfDot11Mode, &tdlsSetupReq.HTCaps, + &tdlsSetupReq.VHTCaps, psessionEntry ); + + /* Populate AID */ + PopulateDotfTdlsVhtAID( pMac, selfDot11Mode, peerMac, + &tdlsSetupReq.AID, psessionEntry ); + + /* Populate TDLS offchannel param only if offchannel is enabled + * and TDLS Channel Switching is not prohibited by AP in ExtCap + * IE in assoc/re-assoc response. + */ + if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) && + (!psessionEntry->tdls_chan_swit_prohibited)) + { + PopulateDot11fTdlsOffchannelParams( pMac, psessionEntry, + &tdlsSetupReq.SuppChannels, + &tdlsSetupReq.SuppOperatingClasses); + if ( pMac->roam.configParam.bandCapability != eCSR_BAND_24) + { + tdlsSetupReq.HT2040BSSCoexistence.present = 1; + tdlsSetupReq.HT2040BSSCoexistence.infoRequest = 1; + } + } + else + { + limLog(pMac, LOG1, + FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"), + pMac->lim.gLimTDLSOffChannelEnabled, + psessionEntry->tdls_chan_swit_prohibited); + } + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11fGetPackedTDLSSetupReqSize( pMac, &tdlsSetupReq, + &nPayload); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to calculate the packed size for a Setup Request (0x%08x)."), + status); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while calculating the packed size for a Setup Request (0x%08x)."), + status); + } + + + /* + * This frame is going out from PE as data frames with special ethertype + * 89-0d. + * 8 bytes of RFC 1042 header + */ + + + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; + + /* Ok-- try to allocate memory from MGMT PKT pool */ + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("Failed to allocate %d bytes for a TDLS Setup Request."), + nBytes ); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + vos_mem_set( pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, + TDLS_INITIATOR, TID_AC_VI, psessionEntry) ; + + limLog(pMac, LOGW, FL("SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x"), + tdlsSetupReq.VHTCaps.supportedChannelWidthSet, + tdlsSetupReq.VHTCaps.rxMCSMap, + tdlsSetupReq.VHTCaps.txMCSMap, + tdlsSetupReq.VHTCaps.txSupDataRate); + + status = dot11fPackTDLSSetupReq( pMac, &tdlsSetupReq, pFrame + + header_offset, nPayload, &nPayload ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to pack a TDLS Setup Request (0x%08x)."), + status); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while packing TDLS Setup Request (0x%08x)."), + status); + } + + //Copy the additional IE. + //TODO : addIe is added at the end of the frame. This means it doesnt + //follow the order. This should be ok, but we should consider changing this + //if there is any IOT issue. + if( addIeLen != 0 ) + { + limLog(pMac, LOG1, FL("Copy Additional Ie Len = %d"), + addIeLen ); + vos_mem_copy( pFrame + header_offset + nPayload, addIe, addIeLen ); + } + + limLog(pMac, LOG1, FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_SETUP_REQ, + limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_REQ), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; +#if defined(CONFIG_HL_SUPPORT) + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, true ); +#else + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); +#endif + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.mgmtFrameSessionId = 0xff; + limLog(pMac, LOGE, FL("could not send TDLS Setup Request frame!")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} +/* + * Send TDLS Teardown frame on Direct link or AP link, depends on reason code. + */ + +tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, tANI_U16 reason, tANI_U8 responder, tpPESession psessionEntry, + tANI_U8 *addIe, tANI_U16 addIeLen) +{ + tDot11fTDLSTeardown teardown ; + tANI_U32 status = 0 ; + tANI_U32 nPayload = 0 ; + tANI_U32 nBytes = 0 ; + tANI_U32 header_offset = 0 ; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + tANI_U32 padLen = 0; +#endif + tANI_U8 smeSessionId = 0; + tpDphHashNode pStaDs = NULL; + tANI_U16 aid = 0; + tANI_U8 qosMode = 0; + tANI_U8 tdlsLinkType = 0; + + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("psessionEntry is NULL")); + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11fPackProbeRequest' (for + * serialization). We start by zero-initializing the structure: + */ + vos_mem_set( ( tANI_U8* )&teardown, sizeof( tDot11fTDLSTeardown ), 0 ); + teardown.Category.category = SIR_MAC_ACTION_TDLS ; + teardown.Action.action = SIR_MAC_TDLS_TEARDOWN ; + teardown.Reason.code = reason ; + + PopulateDot11fLinkIden( pMac, psessionEntry, &teardown.LinkIdentifier, + peerMac, (responder == TRUE) ? TDLS_RESPONDER : TDLS_INITIATOR) ; + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11fGetPackedTDLSTeardownSize( pMac, &teardown, &nPayload); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to calculate the packed size for Teardown frame (0x%08x)."), + status); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while calculating the packed size for Teardown frame (0x%08x)."), + status); + } + /* + * This frame is going out from PE as data frames with special ethertype + * 89-0d. + * 8 bytes of RFC 1042 header + */ + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, + &psessionEntry->dph.dphHashTable); + if (pStaDs) + { + qosMode = pStaDs->qosMode; + } + tdlsLinkType = (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) + ? TDLS_LINK_AP : TDLS_LINK_DIRECT; + nBytes = nPayload + (((IS_QOS_ENABLED(psessionEntry) && + (tdlsLinkType == TDLS_LINK_AP)) || + ((tdlsLinkType == TDLS_LINK_DIRECT) && qosMode)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; + +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) + Hence AP itself padding some bytes, which caused teardown packet is dropped at + receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64 + */ + if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) + { + padLen = MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE ) ; + + /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */ + if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE) + padLen = MIN_VENDOR_SPECIFIC_IE_SIZE; + + nBytes += padLen; + } +#endif + + /* Ok-- try to allocate memory from MGMT PKT pool */ + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("Failed to allocate %d bytes for a TDLS Teardown Frame."), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + vos_mem_set( pFrame, nBytes, 0 ); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + limLog(pMac, LOGE, FL("Reason of TDLS Teardown: %d"), reason); + /* fill out the buffer descriptor */ + header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET(teardown), + (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) + ? TDLS_LINK_AP : TDLS_LINK_DIRECT, + (responder == TRUE) ? TDLS_RESPONDER : TDLS_INITIATOR, + TID_AC_VI, psessionEntry); + + status = dot11fPackTDLSTeardown( pMac, &teardown, pFrame + + header_offset, nPayload, &nPayload ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, FL("Failed to pack a TDLS Teardown frame (0x%08x)."), + status ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while packing TDLS Teardown frame (0x%08x)."), + status); + } + + if( addIeLen != 0 ) + { + limLog(pMac, LOG1, FL("Copy Additional Ie Len = %d"), addIeLen); + vos_mem_copy( pFrame + header_offset + nPayload, addIe, addIeLen ); + } + +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + if (padLen != 0) + { + /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */ + tANI_U8 *padVendorSpecific = pFrame + header_offset + nPayload + addIeLen; + /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */ + padVendorSpecific[0] = 221; + padVendorSpecific[1] = padLen - 2; + padVendorSpecific[2] = 0x00; + padVendorSpecific[3] = 0xA0; + padVendorSpecific[4] = 0xC6; + + limLog(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"), padLen); + + /* padding zero if more than 5 bytes are required */ + if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE) + vos_mem_set( pFrame + header_offset + nPayload + addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE, + padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0); + } +#endif + limLog(pMac, LOG1, FL("[TDLS] action %d (%s) -%s-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_TEARDOWN, + limTraceTdlsActionString(SIR_MAC_TDLS_TEARDOWN), + ((reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? + "AP": "DIRECT"), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; +#if defined(CONFIG_HL_SUPPORT) + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, + (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? true : false ); +#else + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, + false ); +#endif + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.mgmtFrameSessionId = 0xff; + limLog(pMac, LOGE, FL("could not send TDLS Teardown frame")); + return eSIR_FAILURE; + + } + return eSIR_SUCCESS; + +} + +/* + * Send Setup RSP frame on AP link. + */ +static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry, + etdlsLinkSetupStatus setupStatus, tANI_U8 *addIe, tANI_U16 addIeLen ) +{ + tDot11fTDLSSetupRsp tdlsSetupRsp ; + tANI_U32 status = 0 ; + tANI_U16 caps = 0 ; + tANI_U32 nPayload = 0 ; + tANI_U32 header_offset = 0 ; + tANI_U32 nBytes = 0 ; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; + tANI_U8 smeSessionId = 0; + + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("psessionEntry is NULL")); + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11fPackProbeRequest' (for + * serialization). We start by zero-initializing the structure: + */ + vos_mem_set( ( tANI_U8* )&tdlsSetupRsp, sizeof( tDot11fTDLSSetupRsp ),0 ); + + /* + * setup Fixed fields, + */ + tdlsSetupRsp.Category.category = SIR_MAC_ACTION_TDLS; + tdlsSetupRsp.Action.action = SIR_MAC_TDLS_SETUP_RSP ; + tdlsSetupRsp.DialogToken.token = dialog; + + PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupRsp.LinkIdentifier, + peerMac, TDLS_RESPONDER) ; + + if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS) + { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + limLog(pMac, LOGE, FL("could not retrieve Capabilities value")); + } + swapBitField16(caps, ( tANI_U16* )&tdlsSetupRsp.Capabilities ); + + /* populate supported rate and ext supported rate IE */ + populate_dot11f_rates_tdls(pMac, &tdlsSetupRsp.SuppRates, + &tdlsSetupRsp.ExtSuppRates); + + /* Populate extended supported rates */ + PopulateDot11fTdlsExtCapability(pMac, psessionEntry, &tdlsSetupRsp.ExtCap); + + if (1 == pMac->lim.gLimTDLSWmmMode) + { + tANI_U32 val = 0; + + limLog(pMac, LOG1, FL("populate WMM IE in Setup Response frame")); + /* include WMM IE */ + tdlsSetupRsp.WMMInfoStation.version = SIR_MAC_OUI_VERSION_1; + tdlsSetupRsp.WMMInfoStation.acvo_uapsd = + (pMac->lim.gLimTDLSUapsdMask & 0x01); + tdlsSetupRsp.WMMInfoStation.acvi_uapsd = + ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1); + tdlsSetupRsp.WMMInfoStation.acbk_uapsd = + ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2); + tdlsSetupRsp.WMMInfoStation.acbe_uapsd = + ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3); + + if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + limLog(pMac, LOGE, FL("could not retrieve Max SP Length")); + + tdlsSetupRsp.WMMInfoStation.max_sp_length = (tANI_U8)val; + tdlsSetupRsp.WMMInfoStation.present = 1; + } + else + { + /* + * TODO: we need to see if we have to support conditions where we have + * EDCA parameter info element is needed a) if we need different QOS + * parameters for off channel operations or QOS is not supported on + * AP link and we wanted to QOS on direct link. + */ + /* Populate QOS info, needed for Peer U-APSD session */ + /* TODO: Now hardcoded, because PopulateDot11fQOSCapsStation() depends on AP's capability, and + TDLS doesn't want to depend on AP's capability */ + limLog(pMac, LOG1, FL("populate QOS IE in Setup Response frame")); + tdlsSetupRsp.QOSCapsStation.present = 1; + tdlsSetupRsp.QOSCapsStation.max_sp_length = 0; + tdlsSetupRsp.QOSCapsStation.qack = 0; + tdlsSetupRsp.QOSCapsStation.acbe_uapsd = ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3); + tdlsSetupRsp.QOSCapsStation.acbk_uapsd = ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2); + tdlsSetupRsp.QOSCapsStation.acvi_uapsd = ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1); + tdlsSetupRsp.QOSCapsStation.acvo_uapsd = (pMac->lim.gLimTDLSUapsdMask & 0x01); + } + + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + + /* Populate HT/VHT Capabilities */ + PopulateDot11fTdlsHtVhtCap( pMac, selfDot11Mode, &tdlsSetupRsp.HTCaps, + &tdlsSetupRsp.VHTCaps, psessionEntry ); + + /* Populate AID */ + PopulateDotfTdlsVhtAID( pMac, selfDot11Mode, peerMac, + &tdlsSetupRsp.AID, psessionEntry ); + + /* Populate TDLS offchannel param only if offchannel is enabled + * and TDLS Channel Switching is not prohibited by AP in ExtCap + * IE in assoc/re-assoc response. + */ + if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) && + (!psessionEntry->tdls_chan_swit_prohibited)) + { + PopulateDot11fTdlsOffchannelParams( pMac, psessionEntry, + &tdlsSetupRsp.SuppChannels, + &tdlsSetupRsp.SuppOperatingClasses); + if ( pMac->roam.configParam.bandCapability != eCSR_BAND_24) + { + tdlsSetupRsp.HT2040BSSCoexistence.present = 1; + tdlsSetupRsp.HT2040BSSCoexistence.infoRequest = 1; + } + } + else + { + limLog(pMac, LOG1, + FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"), + pMac->lim.gLimTDLSOffChannelEnabled, + psessionEntry->tdls_chan_swit_prohibited); + } + + tdlsSetupRsp.Status.status = setupStatus ; + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11fGetPackedTDLSSetupRspSize( pMac, &tdlsSetupRsp, + &nPayload); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to calculate the packed size for a Setup Response (0x%08x)."), + status); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while calculating the packed size for Setup Response (0x%08x)."), + status); + } + + /* + * This frame is going out from PE as data frames with special ethertype + * 89-0d. + * 8 bytes of RFC 1042 header + */ + + + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; + + /* Ok-- try to allocate memory from MGMT PKT pool */ + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("Failed to allocate %d bytes for a TDLS Setup Response."), + nBytes ); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + vos_mem_set( pFrame, nBytes, 0 ); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET(tdlsSetupRsp), + TDLS_LINK_AP, TDLS_RESPONDER, + TID_AC_VI, psessionEntry) ; + + limLog(pMac, LOG1, + FL("SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x"), + tdlsSetupRsp.VHTCaps.supportedChannelWidthSet, + tdlsSetupRsp.VHTCaps.rxMCSMap, + tdlsSetupRsp.VHTCaps.txMCSMap, + tdlsSetupRsp.VHTCaps.txSupDataRate); + status = dot11fPackTDLSSetupRsp( pMac, &tdlsSetupRsp, pFrame + + header_offset, nPayload, &nPayload ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to pack a TDLS Setup Response (0x%08x)."), + status); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while packing TDLS Setup Response (0x%08x)."), + status); + } + + //Copy the additional IE. + //TODO : addIe is added at the end of the frame. This means it doesnt + //follow the order. This should be ok, but we should consider changing this + //if there is any IOT issue. + if( addIeLen != 0 ) + { + vos_mem_copy( pFrame + header_offset + nPayload, addIe, addIeLen ); + } + + limLog(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_SETUP_RSP, + limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_RSP), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; +#if defined(CONFIG_HL_SUPPORT) + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, true ); +#else + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); +#endif + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.mgmtFrameSessionId = 0xff; + limLog(pMac, LOGE, FL("could not send TDLS Setup Response")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} + +/* + * Send TDLS setup CNF frame on AP link + */ + +tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, + tANI_U8 dialog, + tANI_U32 peerCapability, + tpPESession psessionEntry, + tANI_U8* addIe, tANI_U16 addIeLen) +{ + tDot11fTDLSSetupCnf tdlsSetupCnf ; + tANI_U32 status = 0 ; + tANI_U32 nPayload = 0 ; + tANI_U32 nBytes = 0 ; + tANI_U32 header_offset = 0 ; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + tANI_U32 padLen = 0; +#endif + tANI_U8 smeSessionId = 0; + + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11fPackProbeRequest' (for + * serialization). We start by zero-initializing the structure: + */ + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&tdlsSetupCnf, sizeof( tDot11fTDLSSetupCnf ), 0 ); + + /* + * setup Fixed fields, + */ + tdlsSetupCnf.Category.category = SIR_MAC_ACTION_TDLS; + tdlsSetupCnf.Action.action = SIR_MAC_TDLS_SETUP_CNF ; + tdlsSetupCnf.DialogToken.token = dialog ; + + PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupCnf.LinkIdentifier, + peerMac, TDLS_INITIATOR) ; + /* + * TODO: we need to see if we have to support conditions where we have + * EDCA parameter info element is needed a) if we need different QOS + * parameters for off channel operations or QOS is not supported on + * AP link and we wanted to QOS on direct link. + */ + + /* Check self and peer WMM capable */ + if ((1 == pMac->lim.gLimTDLSWmmMode) && + (CHECK_BIT(peerCapability, TDLS_PEER_WMM_CAP))) + { + limLog(pMac, LOG1, FL("populate WMM praram in Setup Confirm")); + PopulateDot11fWMMParams(pMac, &tdlsSetupCnf.WMMParams, psessionEntry); + } + + /* Check peer is VHT capable*/ + if (CHECK_BIT(peerCapability, TDLS_PEER_VHT_CAP)) + { + PopulateDot11fVHTOperation(pMac, + psessionEntry, + &tdlsSetupCnf.VHTOperation); + PopulateDot11fHTInfo( pMac, &tdlsSetupCnf.HTInfo, psessionEntry ); + } + else if (CHECK_BIT(peerCapability, TDLS_PEER_HT_CAP)) /* Check peer is HT capable */ + { + PopulateDot11fHTInfo( pMac, &tdlsSetupCnf.HTInfo, psessionEntry ); + } + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11fGetPackedTDLSSetupCnfSize( pMac, &tdlsSetupCnf, + &nPayload); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to calculate the packed size for Setup Confirm (0x%08x)."), + status); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while calculating the packed size for Setup Confirm (0x%08x)."), + status); + } + /* + * This frame is going out from PE as data frames with special ethertype + * 89-0d. + * 8 bytes of RFC 1042 header + */ + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; + +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) + Hence AP itself padding some bytes, which caused teardown packet is dropped at + receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64 + */ + if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) + { + padLen = MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE ) ; + + /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */ + if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE) + padLen = MIN_VENDOR_SPECIFIC_IE_SIZE; + + nBytes += padLen; + } +#endif + + + /* Ok-- try to allocate memory from MGMT PKT pool */ + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("Failed to allocate %d bytes for a TDLS Setup Confirm."), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + vos_mem_set( pFrame, nBytes, 0 ); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET(tdlsSetupCnf), TDLS_LINK_AP, TDLS_INITIATOR, + TID_AC_VI, psessionEntry) ; + + status = dot11fPackTDLSSetupCnf( pMac, &tdlsSetupCnf, pFrame + + header_offset, nPayload, &nPayload ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to pack a TDLS Setup Confirm (0x%08x)."), + status); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while packing TDLS Setup Confirm (0x%08x)."), + status); + } + //Copy the additional IE. + //TODO : addIe is added at the end of the frame. This means it doesnt + //follow the order. This should be ok, but we should consider changing this + //if there is any IOT issue. + if( addIeLen != 0 ) + { + vos_mem_copy( pFrame + header_offset + nPayload, addIe, addIeLen ); + } + +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + if (padLen != 0) + { + /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */ + tANI_U8 *padVendorSpecific = pFrame + header_offset + nPayload + addIeLen; + /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */ + padVendorSpecific[0] = 221; + padVendorSpecific[1] = padLen - 2; + padVendorSpecific[2] = 0x00; + padVendorSpecific[3] = 0xA0; + padVendorSpecific[4] = 0xC6; + + limLog(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"), padLen); + + /* padding zero if more than 5 bytes are required */ + if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE) + vos_mem_set( pFrame + header_offset + nPayload + addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE, + padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0); + } +#endif + + + limLog(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_SETUP_CNF, + limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_CNF), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; +#if defined(CONFIG_HL_SUPPORT) + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, true ); +#else + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + limTxComplete, pFrame, + limMgmtTXComplete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); +#endif + + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.mgmtFrameSessionId = 0xff; + limLog(pMac, LOGE, FL("could not send TDLS Setup Confirm frame")); + return eSIR_FAILURE; + + } + + return eSIR_SUCCESS; +} + + +/* This Function is similar to PopulateDot11fHTCaps, except that the HT Capabilities + * are considered from the AddStaReq rather from the cfg.dat as in PopulateDot11fHTCaps + */ +static tSirRetStatus limTdlsPopulateDot11fHTCaps(tpAniSirGlobal pMac, tpPESession psessionEntry, + tSirTdlsAddStaReq *pTdlsAddStaReq, tDot11fIEHTCaps *pDot11f) +{ + tANI_U32 nCfgValue; + tANI_U8 nCfgValue8; + tSirMacHTParametersInfo *pHTParametersInfo; + union { + tANI_U16 nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + tSirMacExtendedHTCapabilityInfo extHtCapInfo; + } uHTCapabilityInfo; + + tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo; + tSirMacASCapabilityInfo *pASCapabilityInfo; + + nCfgValue = pTdlsAddStaReq->htCap.capInfo; + + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + + pDot11f->advCodingCap = uHTCapabilityInfo.htCapInfo.advCodingCap; + pDot11f->mimoPowerSave = uHTCapabilityInfo.htCapInfo.mimoPowerSave; + pDot11f->greenField = uHTCapabilityInfo.htCapInfo.greenField; + pDot11f->shortGI20MHz = uHTCapabilityInfo.htCapInfo.shortGI20MHz; + pDot11f->shortGI40MHz = uHTCapabilityInfo.htCapInfo.shortGI40MHz; + pDot11f->txSTBC = uHTCapabilityInfo.htCapInfo.txSTBC; + pDot11f->rxSTBC = uHTCapabilityInfo.htCapInfo.rxSTBC; + pDot11f->delayedBA = uHTCapabilityInfo.htCapInfo.delayedBA; + pDot11f->maximalAMSDUsize = uHTCapabilityInfo.htCapInfo.maximalAMSDUsize; + pDot11f->dsssCckMode40MHz = uHTCapabilityInfo.htCapInfo.dsssCckMode40MHz; + pDot11f->psmp = uHTCapabilityInfo.htCapInfo.psmp; + pDot11f->stbcControlFrame = uHTCapabilityInfo.htCapInfo.stbcControlFrame; + pDot11f->lsigTXOPProtection = uHTCapabilityInfo.htCapInfo.lsigTXOPProtection; + + // All sessionized entries will need the check below + if (psessionEntry == NULL) // Only in case of NO session + { + pDot11f->supportedChannelWidthSet = uHTCapabilityInfo.htCapInfo.supportedChannelWidthSet; + } + else + { + pDot11f->supportedChannelWidthSet = psessionEntry->htSupportedChannelWidthSet; + } + + /* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is + eHT_CHANNEL_WIDTH_20MHZ */ + if(pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) + { + pDot11f->shortGI40MHz = 0; + } + + limLog(pMac, LOG1, + FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d"), + pDot11f->supportedChannelWidthSet, + pDot11f->mimoPowerSave, + pDot11f->greenField, + pDot11f->shortGI20MHz, + pDot11f->shortGI40MHz, + pDot11f->dsssCckMode40MHz); + + nCfgValue = pTdlsAddStaReq->htCap.ampduParamsInfo; + + nCfgValue8 = ( tANI_U8 ) nCfgValue; + pHTParametersInfo = ( tSirMacHTParametersInfo* ) &nCfgValue8; + + pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor; + pDot11f->mpduDensity = pHTParametersInfo->mpduDensity; + pDot11f->reserved1 = pHTParametersInfo->reserved; + + limLog(pMac, LOG1, FL("AMPDU Param: %x"), nCfgValue); + + vos_mem_copy( pDot11f->supportedMCSSet, pTdlsAddStaReq->htCap.suppMcsSet, + SIZE_OF_SUPPORTED_MCS_SET); + + nCfgValue = pTdlsAddStaReq->htCap.extendedHtCapInfo; + + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + + pDot11f->pco = uHTCapabilityInfo.extHtCapInfo.pco; + pDot11f->transitionTime = uHTCapabilityInfo.extHtCapInfo.transitionTime; + pDot11f->mcsFeedback = uHTCapabilityInfo.extHtCapInfo.mcsFeedback; + + nCfgValue = pTdlsAddStaReq->htCap.txBFCapInfo; + + pTxBFCapabilityInfo = ( tSirMacTxBFCapabilityInfo* ) &nCfgValue; + pDot11f->txBF = pTxBFCapabilityInfo->txBF; + pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding; + pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding; + pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF; + pDot11f->txZLF = pTxBFCapabilityInfo->txZLF; + pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF; + pDot11f->calibration = pTxBFCapabilityInfo->calibration; + pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF; + pDot11f->explicitUncompressedSteeringMatrix = pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix; + pDot11f->explicitBFCSIFeedback = pTxBFCapabilityInfo->explicitBFCSIFeedback; + pDot11f->explicitUncompressedSteeringMatrixFeedback = pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback; + pDot11f->explicitCompressedSteeringMatrixFeedback = pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback; + pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae; + pDot11f->uncompressedSteeringMatrixBFAntennae = pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae; + pDot11f->compressedSteeringMatrixBFAntennae = pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae; + + nCfgValue = pTdlsAddStaReq->htCap.antennaSelectionInfo; + + nCfgValue8 = ( tANI_U8 ) nCfgValue; + + pASCapabilityInfo = ( tSirMacASCapabilityInfo* ) &nCfgValue8; + pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection; + pDot11f->explicitCSIFeedbackTx = pASCapabilityInfo->explicitCSIFeedbackTx; + pDot11f->antennaIndicesFeedbackTx = pASCapabilityInfo->antennaIndicesFeedbackTx; + pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback; + pDot11f->antennaIndicesFeedback = pASCapabilityInfo->antennaIndicesFeedback; + pDot11f->rxAS = pASCapabilityInfo->rxAS; + pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs; + + pDot11f->present = pTdlsAddStaReq->htcap_present; + + return eSIR_SUCCESS; + +} + +tSirRetStatus +limTdlsPopulateDot11fVHTCaps(tpAniSirGlobal pMac, + tSirTdlsAddStaReq *pTdlsAddStaReq, + tDot11fIEVHTCaps *pDot11f) +{ + tANI_U32 nCfgValue=0; + union { + tANI_U32 nCfgValue32; + tSirMacVHTCapabilityInfo vhtCapInfo; + } uVHTCapabilityInfo; + union { + tANI_U16 nCfgValue16; + tSirMacVHTTxSupDataRateInfo vhtTxSupDataRateInfo; + tSirMacVHTRxSupDataRateInfo vhtRxsupDataRateInfo; + } uVHTSupDataRateInfo; + + pDot11f->present = pTdlsAddStaReq->vhtcap_present; + + nCfgValue = pTdlsAddStaReq->vhtCap.vhtCapInfo; + uVHTCapabilityInfo.nCfgValue32 = nCfgValue; + + pDot11f->maxMPDULen = uVHTCapabilityInfo.vhtCapInfo.maxMPDULen; + pDot11f->supportedChannelWidthSet = uVHTCapabilityInfo.vhtCapInfo.supportedChannelWidthSet; + pDot11f->ldpcCodingCap = uVHTCapabilityInfo.vhtCapInfo.ldpcCodingCap; + pDot11f->shortGI80MHz = uVHTCapabilityInfo.vhtCapInfo.shortGI80MHz; + pDot11f->shortGI160and80plus80MHz = uVHTCapabilityInfo.vhtCapInfo.shortGI160and80plus80MHz; + pDot11f->txSTBC = uVHTCapabilityInfo.vhtCapInfo.txSTBC; + pDot11f->rxSTBC = uVHTCapabilityInfo.vhtCapInfo.rxSTBC; + pDot11f->suBeamFormerCap = 0; + pDot11f->suBeamformeeCap = 0; + pDot11f->csnofBeamformerAntSup = uVHTCapabilityInfo.vhtCapInfo.csnofBeamformerAntSup; + pDot11f->numSoundingDim = uVHTCapabilityInfo.vhtCapInfo.numSoundingDim; + pDot11f->muBeamformerCap = 0; + pDot11f->muBeamformeeCap = 0; + pDot11f->vhtTXOPPS = uVHTCapabilityInfo.vhtCapInfo.vhtTXOPPS; + pDot11f->htcVHTCap = uVHTCapabilityInfo.vhtCapInfo.htcVHTCap; + pDot11f->maxAMPDULenExp = uVHTCapabilityInfo.vhtCapInfo.maxAMPDULenExp; + pDot11f->vhtLinkAdaptCap = uVHTCapabilityInfo.vhtCapInfo.vhtLinkAdaptCap; + pDot11f->rxAntPattern = uVHTCapabilityInfo.vhtCapInfo.rxAntPattern; + pDot11f->txAntPattern = uVHTCapabilityInfo.vhtCapInfo.txAntPattern; + pDot11f->reserved1= uVHTCapabilityInfo.vhtCapInfo.reserved1; + + pDot11f->rxMCSMap = pTdlsAddStaReq->vhtCap.suppMcs.rxMcsMap; + + nCfgValue = pTdlsAddStaReq->vhtCap.suppMcs.rxHighest; + uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff; + pDot11f->rxHighSupDataRate = uVHTSupDataRateInfo.vhtRxsupDataRateInfo.rxSupDataRate; + + pDot11f->txMCSMap = pTdlsAddStaReq->vhtCap.suppMcs.txMcsMap; + + nCfgValue = pTdlsAddStaReq->vhtCap.suppMcs.txHighest; + uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff; + pDot11f->txSupDataRate = uVHTSupDataRateInfo.vhtTxSupDataRateInfo.txSupDataRate; + + pDot11f->reserved3= uVHTSupDataRateInfo.vhtTxSupDataRateInfo.reserved; + + limLogVHTCap(pMac, pDot11f); + + return eSIR_SUCCESS; + +} + +static tSirRetStatus +limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tANI_U8 *pSupportedRateSet, + tANI_U8 supporteRatesLength, + tANI_U8* pSupportedMCSSet, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps) + +{ + tSirMacRateSet tempRateSet; + tANI_U32 i,j,val,min,isArate; + tSirMacRateSet tempRateSet2; + tANI_U32 phyMode; + tANI_U8 mcsSet[SIZE_OF_SUPPORTED_MCS_SET]; + uint8_t nss; + isArate=0; + tempRateSet2.numRates = 0; + + limGetPhyMode(pMac, &phyMode, NULL); + + // get own rate set + val = WNI_CFG_OPERATIONAL_RATE_SET_LEN; + if (wlan_cfgGetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, + (tANI_U8 *) &tempRateSet.rate, + &val) != eSIR_SUCCESS) + { + /// Could not get rateset from CFG. Log error. + limLog(pMac, LOGE, FL("could not retrieve rateset")); + val = 0; + } + tempRateSet.numRates = val; + + if (phyMode == WNI_CFG_PHY_MODE_11G) + { + + // get own extended rate set + val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN; + if (wlan_cfgGetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + (tANI_U8 *) &tempRateSet2.rate, + &val) != eSIR_SUCCESS) + tempRateSet2.numRates = val; + } + + if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) + { + limLog(pMac, LOGE, FL("more than 12 rates in CFG")); + goto error; + } + + /** + * Handling of the rate set IEs is the following: + * - keep only rates that we support and that the station supports + * - sort and the rates into the pSta->rate array + */ + + // Copy all rates in tempRateSet, there are 12 rates max + for (i = 0; i < tempRateSet2.numRates; i++) + tempRateSet.rate[i + tempRateSet.numRates] = tempRateSet2.rate[i]; + + tempRateSet.numRates += tempRateSet2.numRates; + + /** + * Sort rates in tempRateSet (they are likely to be already sorted) + * put the result in tempRateSet2 + */ + tempRateSet2.numRates = 0; + + for (i = 0;i < tempRateSet.numRates; i++) + { + min = 0; + val = 0xff; + + for(j = 0;j < tempRateSet.numRates; j++) + if ((tANI_U32) (tempRateSet.rate[j] & 0x7f) < val) + { + val = tempRateSet.rate[j] & 0x7f; + min = j; + } + + tempRateSet2.rate[tempRateSet2.numRates++] = tempRateSet.rate[min]; + tempRateSet.rate[min] = 0xff; + } + + /** + * Copy received rates in tempRateSet, the parser has ensured + * unicity of the rates so there cannot be more than 12 . + */ + if (supporteRatesLength > SIR_MAC_RATESET_EID_MAX) + { + limLog(pMac, LOGW, + FL("Supported rates length %d more than the Max limit, reset to Max"), + supporteRatesLength); + supporteRatesLength = SIR_MAC_RATESET_EID_MAX; + } + + for (i = 0; i < supporteRatesLength; i++) + { + tempRateSet.rate[i] = pSupportedRateSet[i]; + } + + tempRateSet.numRates = supporteRatesLength; + + { + tpSirSupportedRates rates = &pStaDs->supportedRates; + tANI_U8 aRateIndex = 0; + tANI_U8 bRateIndex = 0; + vos_mem_set( (tANI_U8 *) rates, sizeof(tSirSupportedRates), 0); + + for (i = 0;i < tempRateSet2.numRates; i++) + { + for (j = 0;j < tempRateSet.numRates; j++) + { + if ((tempRateSet2.rate[i] & 0x7F) == + (tempRateSet.rate[j] & 0x7F)) + { + + if ((bRateIndex > SIR_NUM_11B_RATES) || (aRateIndex > SIR_NUM_11A_RATES)) + { + limLog(pMac, LOGE, FL("Invalid number of rates (11b->%d, 11a->%d)"), + bRateIndex, + aRateIndex); + return eSIR_FAILURE; + } + + if (sirIsArate(tempRateSet2.rate[i] & 0x7f)) { + isArate=1; + if (aRateIndex < SIR_NUM_11A_RATES) + rates->llaRates[aRateIndex++] = tempRateSet2.rate[i]; + } + else { + if (bRateIndex < SIR_NUM_11B_RATES) + rates->llbRates[bRateIndex++] = tempRateSet2.rate[i]; + } + break; + } + } + } + } + + if (IS_5G_CH(psessionEntry->currentOperChannel)) + nss = pMac->vdev_type_nss_5g.tdls; + else + nss = pMac->vdev_type_nss_2g.tdls; + nss = VOS_MIN(nss, pMac->user_configured_nss); + //compute the matching MCS rate set, if peer is 11n capable and self mode is 11n +#ifdef FEATURE_WLAN_TDLS + if (pStaDs->mlmStaContext.htCapability) +#else + if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) && + (pStaDs->mlmStaContext.htCapability)) +#endif + { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET, + mcsSet, + &val) != eSIR_SUCCESS) + { + /// Could not get rateset from CFG. Log error. + limLog(pMac, LOGP, FL("could not retrieve supportedMCSSet")); + goto error; + } + if (NSS_1x1_MODE == nss) + mcsSet[1] = 0; + for (i=0; isupportedRates.supportedMCSSet[i] = mcsSet[i] & pSupportedMCSSet[i]; + + limLog(pMac, LOG1, FL("MCS Rate Set Bitmap from CFG and DPH:")); + for (i=0; isupportedRates.supportedMCSSet[i]); + } + } + +#ifdef WLAN_FEATURE_11AC + limPopulateVhtMcsSet(pMac, &pStaDs->supportedRates, pVHTCaps, + psessionEntry, nss); +#endif + /** + * Set the erpEnabled bit iff the phy is in G mode and at least + * one A rate is supported + */ + if ((phyMode == WNI_CFG_PHY_MODE_11G) && isArate) + pStaDs->erpEnabled = eHAL_SET; + + + + return eSIR_SUCCESS; + + error: + + return eSIR_FAILURE; +} + +/* + * update HASH node entry info + */ +static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs, + tSirTdlsAddStaReq *pTdlsAddStaReq, tpPESession psessionEntry) +{ + tDot11fIEHTCaps htCap = {0,}; + tDot11fIEHTCaps *htCaps; + tDot11fIEVHTCaps *pVhtCaps = NULL; + tDot11fIEVHTCaps *pVhtCaps_txbf = NULL; +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps vhtCap; + tANI_U8 cbMode; +#endif + tpDphHashNode pSessStaDs = NULL; + tANI_U16 aid; + + if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_ADD) + { + PopulateDot11fHTCaps(pMac, psessionEntry, &htCap); + } + else if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE) + { + limTdlsPopulateDot11fHTCaps(pMac, NULL, pTdlsAddStaReq, &htCap); + } + htCaps = &htCap; + if (htCaps->present) + { + pStaDs->mlmStaContext.htCapability = 1 ; + pStaDs->htGreenfield = htCaps->greenField ; + /* + * pStaDs->htSupportedChannelWidthSet should have the base channel + * capability. The htSupportedChannelWidthSet of the TDLS link on + * base channel should be less than or equal to channel width of + * STA-AP link. So take this setting from the psessionEntry. + */ + pStaDs->htSupportedChannelWidthSet = + psessionEntry->htSupportedChannelWidthSet; + pStaDs->htMIMOPSState = htCaps->mimoPowerSave ; + pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize; + pStaDs->htAMpduDensity = htCaps->mpduDensity; + pStaDs->htDsssCckRate40MHzSupport = htCaps->dsssCckMode40MHz ; + pStaDs->htShortGI20Mhz = htCaps->shortGI20MHz; + pStaDs->htShortGI40Mhz = htCaps->shortGI40MHz; + pStaDs->htMaxRxAMpduFactor = htCaps->maxRxAMPDUFactor; + limFillRxHighestSupportedRate(pMac, + &pStaDs->supportedRates.rxHighestDataRate, + htCaps->supportedMCSSet); + pStaDs->baPolicyFlag = 0xFF; + pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_N ; + pStaDs->ht_caps = pTdlsAddStaReq->htCap.capInfo; + } + else + { + pStaDs->mlmStaContext.htCapability = 0 ; + pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_BG ; + } +#ifdef WLAN_FEATURE_11AC + limTdlsPopulateDot11fVHTCaps(pMac, pTdlsAddStaReq, &vhtCap); + pVhtCaps = &vhtCap; + if (pVhtCaps->present) + { + pStaDs->mlmStaContext.vhtCapability = 1 ; + + /* + * channel width of TDLS link on base channel should not exceed + * channel width of STA-AP link. Hence take this setting from the + * psessionEntry. + */ + pStaDs->vhtSupportedChannelWidthSet = + psessionEntry->vhtTxChannelWidthSet; + pStaDs->vhtLdpcCapable = pVhtCaps->ldpcCodingCap; + pStaDs->vhtBeamFormerCapable = 0; + pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_AC; + pVhtCaps_txbf = (tDot11fIEVHTCaps *)(&pTdlsAddStaReq->vhtCap); + pVhtCaps_txbf->suBeamformeeCap = 0; + pVhtCaps_txbf->suBeamFormerCap = 0; + pVhtCaps_txbf->muBeamformerCap = 0; + pVhtCaps_txbf->muBeamformeeCap = 0; + pStaDs->vht_caps = pTdlsAddStaReq->vhtCap.vhtCapInfo; + } + else + { + pStaDs->mlmStaContext.vhtCapability = 0 ; + pStaDs->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + } +#endif + /*Calculate the Secondary Coannel Offset */ + cbMode = limSelectCBMode(pStaDs, psessionEntry, + psessionEntry->currentOperChannel, + pStaDs->vhtSupportedChannelWidthSet); + + pStaDs->htSecondaryChannelOffset = cbMode; + +#ifdef WLAN_FEATURE_11AC + if ( pStaDs->mlmStaContext.vhtCapability ) + { + pStaDs->htSecondaryChannelOffset = limGetHTCBState(cbMode); + } +#endif + + pSessStaDs = dphLookupHashEntry(pMac, psessionEntry->bssId, &aid, + &psessionEntry->dph.dphHashTable) ; + + /* Lets enable QOS parameter */ + pStaDs->qosMode = (pTdlsAddStaReq->capability & CAPABILITIES_QOS_OFFSET) + || pTdlsAddStaReq->htcap_present; + pStaDs->wmeEnabled = 1; + pStaDs->lleEnabled = 0; + /* TDLS Dummy AddSTA does not have qosInfo , is it OK ?? + */ + pStaDs->qos.capability.qosInfo = (*(tSirMacQosInfoStation *) &pTdlsAddStaReq->uapsd_queues); + + /* populate matching rate set */ + + /* TDLS Dummy AddSTA does not have HTCap,VHTCap,Rates info , is it OK ?? + */ + limTdlsPopulateMatchingRateSet(pMac, pStaDs, pTdlsAddStaReq->supported_rates, + pTdlsAddStaReq->supported_rates_length, + (tANI_U8 *)pTdlsAddStaReq->htCap.suppMcsSet, + psessionEntry, pVhtCaps); + + /* TDLS Dummy AddSTA does not have right capability , is it OK ?? + */ + pStaDs->mlmStaContext.capabilityInfo = ( *(tSirMacCapabilityInfo *) &pTdlsAddStaReq->capability); + + return ; +} + +/* + * Add STA for TDLS setup procedure + */ +static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac, + tSirTdlsAddStaReq *pAddStaReq, + tpPESession psessionEntry) +{ + tpDphHashNode pStaDs = NULL ; + tSirRetStatus status = eSIR_SUCCESS ; + tANI_U16 aid = 0 ; + + pStaDs = dphLookupHashEntry(pMac, pAddStaReq->peerMac, &aid, + &psessionEntry->dph.dphHashTable); + if(NULL == pStaDs) + { + aid = limAssignPeerIdx(pMac, psessionEntry) ; + + if( !aid ) + { + limLog(pMac, LOGE, FL("No more free AID for peer " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pAddStaReq->peerMac)); + return eSIR_FAILURE; + } + + /* Set the aid in peerAIDBitmap as it has been assigned to TDLS peer */ + SET_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap, aid); + + limLog(pMac, LOG1, FL("Aid = %d, for peer =" MAC_ADDRESS_STR), + aid, MAC_ADDR_ARRAY(pAddStaReq->peerMac)); + pStaDs = dphGetHashEntry(pMac, aid, &psessionEntry->dph.dphHashTable); + + if (pStaDs) + { + (void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry); + limDeleteDphHashEntry(pMac, pStaDs->staAddr, aid, psessionEntry); + } + + pStaDs = dphAddHashEntry(pMac, pAddStaReq->peerMac, aid, + &psessionEntry->dph.dphHashTable) ; + + if(NULL == pStaDs) + { + limLog(pMac, LOGE, FL("add hash entry failed")); + VOS_ASSERT(0) ; + return eSIR_FAILURE; + } + } + + limTdlsUpdateHashNodeInfo(pMac, pStaDs, pAddStaReq, psessionEntry) ; + + pStaDs->staType = STA_ENTRY_TDLS_PEER ; + + status = limAddSta(pMac, pStaDs, (pAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE) ? true: false, psessionEntry); + + if(eSIR_SUCCESS != status) + { + /* should not fail */ + VOS_ASSERT(0) ; + } + return status ; +} + +/* + * Del STA, after Link is teardown or discovery response sent on direct link + */ +static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, + tpPESession psessionEntry) +{ + tSirRetStatus status = eSIR_SUCCESS ; + tANI_U16 peerIdx = 0 ; + tpDphHashNode pStaDs = NULL ; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &peerIdx, + &psessionEntry->dph.dphHashTable) ; + + if(pStaDs) + { + + limLog(pMac, LOG1, FL("DEL STA peer MAC: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pStaDs->staAddr)); + limLog(pMac, LOG1, FL("STA type = %x, sta idx = %x"), + pStaDs->staType, + pStaDs->staIndex); + status = limDelSta(pMac, pStaDs, false, psessionEntry) ; + } + + return pStaDs ; +} + + +/* + * Once Link is setup with PEER, send Add STA ind to SME + */ +static eHalStatus limSendSmeTdlsAddStaRsp(tpAniSirGlobal pMac, + tANI_U8 sessionId, tSirMacAddr peerMac, tANI_U8 updateSta, + tDphHashNode *pStaDs, tANI_U8 status) +{ + tSirMsgQ mmhMsg = {0} ; + tSirTdlsAddStaRsp *addStaRsp = NULL ; + mmhMsg.type = eWNI_SME_TDLS_ADD_STA_RSP ; + + addStaRsp = vos_mem_malloc(sizeof(tSirTdlsAddStaRsp)); + if ( NULL == addStaRsp ) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + + addStaRsp->sessionId = sessionId; + addStaRsp->statusCode = status; + if( pStaDs ) + { + addStaRsp->staId = pStaDs->staIndex ; + addStaRsp->ucastSig = pStaDs->ucUcastSig ; + addStaRsp->bcastSig = pStaDs->ucBcastSig ; + } + if( peerMac ) + { + vos_mem_copy( addStaRsp->peerMac, + (tANI_U8 *) peerMac, sizeof(tSirMacAddr)); + } + if (updateSta) + addStaRsp->tdlsAddOper = TDLS_OPER_UPDATE; + else + addStaRsp->tdlsAddOper = TDLS_OPER_ADD; + + addStaRsp->length = sizeof(tSirTdlsAddStaRsp) ; + addStaRsp->messageType = eWNI_SME_TDLS_ADD_STA_RSP ; + + mmhMsg.bodyptr = addStaRsp; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return eSIR_SUCCESS ; + +} +/* + * STA RSP received from HAL + */ +eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, + tpPESession psessionEntry) +{ + tAddStaParams *pAddStaParams = (tAddStaParams *) msg ; + tANI_U8 status = eSIR_SUCCESS ; + tDphHashNode *pStaDs = NULL ; + tANI_U16 aid = 0 ; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + limLog(pMac, LOG1, FL("staIdx=%d, staMac="MAC_ADDRESS_STR), + pAddStaParams->staIdx, + MAC_ADDR_ARRAY(pAddStaParams->staMac)); + + if (pAddStaParams->status != eHAL_STATUS_SUCCESS) + { + VOS_ASSERT(0) ; + limLog(pMac, LOGE, FL("Add sta failed ")); + status = eSIR_FAILURE; + goto add_sta_error; + } + + pStaDs = dphLookupHashEntry(pMac, pAddStaParams->staMac, &aid, + &psessionEntry->dph.dphHashTable); + if(NULL == pStaDs) + { + limLog(pMac, LOGE, FL("pStaDs is NULL ")); + status = eSIR_FAILURE; + goto add_sta_error; + } + + pStaDs->bssId = pAddStaParams->bssIdx; + pStaDs->staIndex = pAddStaParams->staIdx; + pStaDs->ucUcastSig = pAddStaParams->ucUcastSig; + pStaDs->ucBcastSig = pAddStaParams->ucBcastSig; + pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + pStaDs->valid = 1 ; +add_sta_error: + status = limSendSmeTdlsAddStaRsp(pMac, psessionEntry->smeSessionId, + pAddStaParams->staMac, pAddStaParams->updateSta, pStaDs, status) ; + vos_mem_free( pAddStaParams ); + return status ; +} + +void PopulateDot11fTdlsOffchannelParams(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIESuppChannels *suppChannels, + tDot11fIESuppOperatingClasses *suppOperClasses) +{ + tANI_U32 numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + tANI_U8 validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_U8 i; + tANI_U8 valid_count = 0; + tANI_U8 chanOffset; + tANI_U8 op_class; + tANI_U8 numClasses; + uint32_t band; + uint8_t nss_2g; + uint8_t nss_5g; + tANI_U8 classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; + if (wlan_cfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + validChan, &numChans) != eSIR_SUCCESS) + { + /** + * Could not get Valid channel list from CFG. + * Log error. + */ + limLog(pMac, LOGE, FL("could not retrieve valid channel list")); + return; + } + + if (IS_5G_CH(psessionEntry->currentOperChannel)) + band = eCSR_BAND_5G; + else + band = eCSR_BAND_24; + + nss_5g = VOS_MIN(pMac->vdev_type_nss_5g.tdls, pMac->user_configured_nss); + nss_2g = VOS_MIN(pMac->vdev_type_nss_2g.tdls, pMac->user_configured_nss); + + /* validating the channel list for DFS and 2G channels */ + for (i = 0U; i < numChans; i++) { + if (band == eCSR_BAND_24) { + if (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(validChan[i])) { + limLog(pMac, LOG1, + FL("skipping DFS channel %d from the valid channel list"), + validChan[i]); + continue; + } + } else if ((NSS_2x2_MODE == nss_5g) && (NSS_1x1_MODE == nss_2g) && + (true == vos_nv_skip_dfs_and_2g(validChan[i]))){ + limLog(pMac, LOG1, + FL("skipping channel %d, nss_5g: %d, nss_2g: %d"), + validChan[i], nss_5g, nss_2g); + continue; + } + + if (valid_count >= + sizeof(suppChannels->bands) / sizeof(suppChannels->bands[0])) + break; + + suppChannels->bands[valid_count][0] = validChan[i]; + suppChannels->bands[valid_count][1] = 1; + valid_count++; + } + + suppChannels->num_bands = valid_count; + suppChannels->present = 1 ; + + /* find channel offset and get op class for current operating channel */ + switch (psessionEntry->htSecondaryChannelOffset) + { + case PHY_SINGLE_CHANNEL_CENTERED: + chanOffset = BW20; + break; + + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + chanOffset = BW40_LOW_PRIMARY; + break; + + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + chanOffset = BW40_HIGH_PRIMARY; + break; + + default: + chanOffset = BWALL; + break; + + } + + op_class = regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, + psessionEntry->currentOperChannel, + chanOffset); + if (op_class == 0) + { + limLog(pMac, LOGE, + FL("Present Operating class is wrong, countryCodeCurrent: %s, currentOperChannel: %d, htSecondaryChannelOffset: %d, chanOffset: %d"), + pMac->scan.countryCodeCurrent, + psessionEntry->currentOperChannel, + psessionEntry->htSecondaryChannelOffset, + chanOffset); + } + else + { + limLog(pMac, LOG1, + FL("Present Operating channel: %d chanOffset: %d, op class=%d"), + psessionEntry->currentOperChannel, + chanOffset, + op_class); + } + suppOperClasses->present = 1; + suppOperClasses->classes[0] = op_class; + + regdm_get_curr_opclasses(&numClasses, &classes[0]); + + for (i = 0; i < numClasses; i++) + { + suppOperClasses->classes[i+1] = classes[i]; + } + /* add one for present operating class, added in the beginning */ + suppOperClasses->num_classes = numClasses + 1; + + return ; +} +/* + * FUNCTION: Populate Link Identifier element IE + * + */ + + +void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry, + tDot11fIELinkIdentifier *linkIden, + tSirMacAddr peerMac, tANI_U8 reqType) +{ + tANI_U8 *initStaAddr = NULL ; + tANI_U8 *respStaAddr = NULL ; + + (reqType == TDLS_INITIATOR) ? ((initStaAddr = linkIden->InitStaAddr), + (respStaAddr = linkIden->RespStaAddr)) + : ((respStaAddr = linkIden->InitStaAddr ), + (initStaAddr = linkIden->RespStaAddr)) ; + vos_mem_copy( (tANI_U8 *)linkIden->bssid, + (tANI_U8 *) psessionEntry->bssId, sizeof(tSirMacAddr)) ; + + vos_mem_copy( (tANI_U8 *)initStaAddr, + psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ; + + vos_mem_copy( (tANI_U8 *)respStaAddr, (tANI_U8 *) peerMac, + sizeof( tSirMacAddr )); + + linkIden->present = 1 ; + return ; + +} + +void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEExtCap *extCapability) +{ + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extCapability->bytes; + + p_ext_cap->TDLSPeerPSMSupp = PEER_PSM_SUPPORT ; + p_ext_cap->TDLSPeerUAPSDBufferSTA = pMac->lim.gLimTDLSBufStaEnabled; + + /* Set TDLS channel switching bits only if offchannel is enabled + * and TDLS Channel Switching is not prohibited by AP in ExtCap + * IE in assoc/re-assoc response. + */ + if ((1== pMac->lim.gLimTDLSOffChannelEnabled) && + (!psessionEntry->tdls_chan_swit_prohibited)) { + p_ext_cap->TDLSChannelSwitching = 1; + p_ext_cap->TDLSChanSwitProhibited = 0; + } else { + p_ext_cap->TDLSChannelSwitching = 0; + p_ext_cap->TDLSChanSwitProhibited = TDLS_CH_SWITCH_PROHIBITED; + } + + p_ext_cap->TDLSSupport = TDLS_SUPPORT ; + p_ext_cap->TDLSProhibited = TDLS_PROHIBITED ; + + extCapability->present = 1 ; + /* For STA cases we alwasy support 11mc - Allow MAX length */ + extCapability->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + + return ; +} + + +/* + * Process Send Mgmt Request from SME and transmit to AP. + */ +tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf) +{ + /* get all discovery request parameters */ + tSirTdlsSendMgmtReq *pSendMgmtReq = (tSirTdlsSendMgmtReq*) pMsgBuf ; + tpPESession psessionEntry; + tANI_U8 sessionId; + tSirResultCodes resultCode = eSIR_SME_INVALID_PARAMETERS; + + limLog(pMac, LOG1, FL("Send Mgmt Recieved")); + + if((psessionEntry = peFindSessionByBssid(pMac, pSendMgmtReq->bssid, &sessionId)) + == NULL) + { + limLog(pMac, LOGE, + FL("PE Session does not exist for given sme sessionId %d"), + pSendMgmtReq->sessionId); + goto lim_tdls_send_mgmt_error; + } + + /* check if we are in proper state to work as TDLS client */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "send mgmt received in wrong system Role %d", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto lim_tdls_send_mgmt_error; + } + + /* + * if we are still good, go ahead and check if we are in proper state to + * do TDLS discovery req/rsp/....frames. + */ + if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) + { + + limLog(pMac, LOGE, FL("send mgmt received in invalid LIMsme state (%d)"), + psessionEntry->limSmeState); + goto lim_tdls_send_mgmt_error; + } + + switch( pSendMgmtReq->reqType ) + { + case SIR_MAC_TDLS_DIS_REQ: + limLog(pMac, LOG1, FL("Transmit Discovery Request Frame")); + /* format TDLS discovery request frame and transmit it */ + limSendTdlsDisReqFrame(pMac, pSendMgmtReq->peerMac, + pSendMgmtReq->dialog, + psessionEntry) ; + resultCode = eSIR_SME_SUCCESS; + break; + case SIR_MAC_TDLS_DIS_RSP: + { + limLog(pMac, LOG1, FL("Transmit Discovery Response Frame")); + //Send a response mgmt action frame + limSendTdlsDisRspFrame(pMac, pSendMgmtReq->peerMac, + pSendMgmtReq->dialog, psessionEntry, + &pSendMgmtReq->addIe[0], + (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq))); + resultCode = eSIR_SME_SUCCESS; + } + break; + case SIR_MAC_TDLS_SETUP_REQ: + { + limLog(pMac, LOG1, FL("Transmit Setup Request Frame")); + limSendTdlsLinkSetupReqFrame(pMac, + pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry, + &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq))); + resultCode = eSIR_SME_SUCCESS; + } + break; + case SIR_MAC_TDLS_SETUP_RSP: + { + limLog(pMac, LOG1, FL("Transmit Setup Response Frame")); + limSendTdlsSetupRspFrame(pMac, + pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry, pSendMgmtReq->statusCode, + &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq))); + resultCode = eSIR_SME_SUCCESS; + } + break; + case SIR_MAC_TDLS_SETUP_CNF: + { + limLog(pMac, LOG1, FL("Transmit Setup Confirm Frame")); + limSendTdlsLinkSetupCnfFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog, pSendMgmtReq->peerCapability, + psessionEntry, &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq))); + resultCode = eSIR_SME_SUCCESS; + } + break; + case SIR_MAC_TDLS_TEARDOWN: + { + limLog(pMac, LOG1, FL("Transmit Teardown Frame")); + limSendTdlsTeardownFrame(pMac, + pSendMgmtReq->peerMac, pSendMgmtReq->statusCode, pSendMgmtReq->responder, psessionEntry, + &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq))); + resultCode = eSIR_SME_SUCCESS; + } + break; + case SIR_MAC_TDLS_PEER_TRAFFIC_IND: + { + } + break; + case SIR_MAC_TDLS_CH_SWITCH_REQ: + { + } + break; + case SIR_MAC_TDLS_CH_SWITCH_RSP: + { + } + break; + case SIR_MAC_TDLS_PEER_TRAFFIC_RSP: + { + } + break; + default: + break; + } + +lim_tdls_send_mgmt_error: + + limSendSmeRsp( pMac, eWNI_SME_TDLS_SEND_MGMT_RSP, + resultCode, pSendMgmtReq->sessionId, pSendMgmtReq->transactionId); + + return eSIR_SUCCESS; +} + +/* + * Send Response to Link Establish Request to SME + */ +void limSendSmeTdlsLinkEstablishReqRsp(tpAniSirGlobal pMac, + tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs, + tANI_U8 status) +{ + tSirMsgQ mmhMsg = {0} ; + + tSirTdlsLinkEstablishReqRsp *pTdlsLinkEstablishReqRsp = NULL ; + + pTdlsLinkEstablishReqRsp = vos_mem_malloc(sizeof(tSirTdlsLinkEstablishReqRsp)); + if ( NULL == pTdlsLinkEstablishReqRsp ) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return ; + } + pTdlsLinkEstablishReqRsp->statusCode = status ; + if ( peerMac ) + { + vos_mem_copy(pTdlsLinkEstablishReqRsp->peerMac, peerMac, sizeof(tSirMacAddr)); + } + pTdlsLinkEstablishReqRsp->sessionId = sessionId; + mmhMsg.type = eWNI_SME_TDLS_LINK_ESTABLISH_RSP ; + mmhMsg.bodyptr = pTdlsLinkEstablishReqRsp; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return ; + + +} + +/* + * Once link is teardown, send Del Peer Ind to SME + */ +static eHalStatus limSendSmeTdlsDelStaRsp(tpAniSirGlobal pMac, + tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs, + tANI_U8 status) +{ + tSirMsgQ mmhMsg = {0} ; + tSirTdlsDelStaRsp *pDelSta = NULL ; + mmhMsg.type = eWNI_SME_TDLS_DEL_STA_RSP ; + + pDelSta = vos_mem_malloc(sizeof(tSirTdlsDelStaRsp)); + if ( NULL == pDelSta ) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + + pDelSta->sessionId = sessionId; + pDelSta->statusCode = status ; + if( pStaDs ) + { + pDelSta->staId = pStaDs->staIndex ; + } + else + pDelSta->staId = HAL_STA_INVALID_IDX; + + if( peerMac ) + { + vos_mem_copy(pDelSta->peerMac, peerMac, sizeof(tSirMacAddr)); + } + + pDelSta->length = sizeof(tSirTdlsDelStaRsp) ; + pDelSta->messageType = eWNI_SME_TDLS_DEL_STA_RSP ; + + mmhMsg.bodyptr = pDelSta; + + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return eSIR_SUCCESS ; + +} + +/* + * Process Send Mgmt Request from SME and transmit to AP. + */ +tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf) +{ + /* get all discovery request parameters */ + tSirTdlsAddStaReq *pAddStaReq = (tSirTdlsAddStaReq*) pMsgBuf ; + tpPESession psessionEntry; + tANI_U8 sessionId; + + limLog(pMac, LOG1, FL("TDLS Add STA Request Recieved")); + + if((psessionEntry = peFindSessionByBssid(pMac, pAddStaReq->bssid, &sessionId)) + == NULL) + { + limLog(pMac, LOGE, + FL("PE Session does not exist for given sme sessionId %d"), + pAddStaReq->sessionId); + goto lim_tdls_add_sta_error; + } + + /* check if we are in proper state to work as TDLS client */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "send mgmt received in wrong system Role %d", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto lim_tdls_add_sta_error; + } + + /* + * if we are still good, go ahead and check if we are in proper state to + * do TDLS discovery req/rsp/....frames. + */ + if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) + { + + limLog(pMac, LOGE, + FL("Add STA received in invalid LIMsme state (%d)"), + psessionEntry->limSmeState); + goto lim_tdls_add_sta_error; + } + + pMac->lim.gLimAddStaTdls = true ; + + /* To start with, send add STA request to HAL */ + if (eSIR_FAILURE == limTdlsSetupAddSta(pMac, pAddStaReq, psessionEntry)) + { + limLog(pMac, LOGE, FL("Add TDLS Station request failed")); + goto lim_tdls_add_sta_error; + } + return eSIR_SUCCESS; +lim_tdls_add_sta_error: + limSendSmeTdlsAddStaRsp(pMac, + pAddStaReq->sessionId, pAddStaReq->peerMac, + (pAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE), NULL, eSIR_FAILURE ); + + return eSIR_SUCCESS; +} +/* + * Process Del Sta Request from SME . + */ +tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf) +{ + /* get all discovery request parameters */ + tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq*) pMsgBuf ; + tpPESession psessionEntry; + tANI_U8 sessionId; + tpDphHashNode pStaDs = NULL ; + + limLog(pMac, LOG1, FL("TDLS Delete STA Request Recieved")); + + if((psessionEntry = peFindSessionByBssid(pMac, pDelStaReq->bssid, &sessionId)) + == NULL) + { + limLog(pMac, LOGE, + FL("PE Session does not exist for given sme sessionId %d"), + pDelStaReq->sessionId); + limSendSmeTdlsDelStaRsp(pMac, pDelStaReq->sessionId, pDelStaReq->peerMac, + NULL, eSIR_FAILURE) ; + return eSIR_FAILURE; + } + + /* check if we are in proper state to work as TDLS client */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "Del sta received in wrong system Role %d", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto lim_tdls_del_sta_error; + } + + /* + * if we are still good, go ahead and check if we are in proper state to + * do TDLS discovery req/rsp/....frames. + */ + if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) + { + + limLog(pMac, LOGE, FL("Del Sta received in invalid LIMsme state (%d)"), + psessionEntry->limSmeState); + goto lim_tdls_del_sta_error; + } + + pStaDs = limTdlsDelSta(pMac, pDelStaReq->peerMac, psessionEntry) ; + + /* now send indication to SME-->HDD->TL to remove STA from TL */ + + if(pStaDs) + { + limSendSmeTdlsDelStaRsp(pMac, psessionEntry->smeSessionId, pDelStaReq->peerMac, + pStaDs, eSIR_SUCCESS) ; + limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry) ; + + /* Clear the aid in peerAIDBitmap as this aid is now in freepool */ + CLEAR_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap, pStaDs->assocId); + limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, psessionEntry) ; + + return eSIR_SUCCESS; + + } + +lim_tdls_del_sta_error: + limSendSmeTdlsDelStaRsp(pMac, psessionEntry->smeSessionId, pDelStaReq->peerMac, + NULL, eSIR_FAILURE) ; + + return eSIR_SUCCESS; +} + +/* Intersects the two input arrays and outputs an array */ +/* For now the array length of tANI_U8 suffices */ +static void limTdlsGetIntersection(tANI_U8 *input_array1,tANI_U8 input1_length, + tANI_U8 *input_array2,tANI_U8 input2_length, + tANI_U8 *output_array,tANI_U8 *output_length) +{ + tANI_U8 i,j,k=0,flag=0; + + if (input1_length > WNI_CFG_VALID_CHANNEL_LIST_LEN) + input1_length = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + for(i=0;ibssid, &sessionId)) + == NULL) + { + limLog(pMac, LOGE, + FL("PE Session does not exist for given sme sessionId %d"), + pTdlsLinkEstablishReq->sessionId); + limSendSmeTdlsLinkEstablishReqRsp(pMac, pTdlsLinkEstablishReq->sessionId, pTdlsLinkEstablishReq->peerMac, + NULL, eSIR_FAILURE) ; + return eSIR_FAILURE; + } + + /* check if we are in proper state to work as TDLS client */ + if (!LIM_IS_STA_ROLE(psessionEntry)) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + "TDLS Link Establish Request received in wrong system Role %d", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + goto lim_tdls_link_establish_error; + } + + /* + * if we are still good, go ahead and check if we are in proper state to + * do TDLS discovery req/rsp/....frames. + */ + if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) + { + + limLog(pMac, LOGE, + FL("TDLS Link Establish Request received in invalid LIMsme state (%d)"), + psessionEntry->limSmeState); + goto lim_tdls_link_establish_error; + } + /*TODO Sunil , TDLSPeer Entry has the STA ID , Use it */ + pStaDs = dphLookupHashEntry(pMac, pTdlsLinkEstablishReq->peerMac, &peerIdx, + &psessionEntry->dph.dphHashTable) ; + if ( NULL == pStaDs ) + { + limLog(pMac, LOGE, FL( "pStaDs is NULL")); + goto lim_tdls_link_establish_error; + + } + pMsgTdlsLinkEstablishReq = vos_mem_malloc(sizeof( tTdlsLinkEstablishParams )); + if ( NULL == pMsgTdlsLinkEstablishReq ) + { + limLog(pMac, LOGE, + FL("Unable to allocate memory TDLS Link Establish Request")); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_set((tANI_U8 *)pMsgTdlsLinkEstablishReq, + sizeof(tTdlsLinkEstablishParams), 0); + + pMsgTdlsLinkEstablishReq->staIdx = pStaDs->staIndex; + pMsgTdlsLinkEstablishReq->isResponder = pTdlsLinkEstablishReq->isResponder; + pMsgTdlsLinkEstablishReq->uapsdQueues = pTdlsLinkEstablishReq->uapsdQueues; + pMsgTdlsLinkEstablishReq->maxSp = pTdlsLinkEstablishReq->maxSp; + pMsgTdlsLinkEstablishReq->isBufsta = pTdlsLinkEstablishReq->isBufSta; + pMsgTdlsLinkEstablishReq->isOffChannelSupported = + pTdlsLinkEstablishReq->isOffChannelSupported; + + if ((pTdlsLinkEstablishReq->supportedChannelsLen > 0) && + (pTdlsLinkEstablishReq->supportedChannelsLen <= + SIR_MAC_MAX_SUPP_CHANNELS)) { + tANI_U32 selfNumChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + tANI_U8 selfSupportedChannels[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + if (wlan_cfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + selfSupportedChannels, &selfNumChans) != eSIR_SUCCESS) + { + /** + * Could not get Valid channel list from CFG. + * Log error. + */ + limLog(pMac, LOGE, + FL("could not retrieve Valid channel list")); + } + + if (selfNumChans > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + limLog(pMac, LOGE, + FL("Channel List more than Valid Channel list")); + selfNumChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + + if (pTdlsLinkEstablishReq->supportedChannelsLen + > SIR_MAC_MAX_SUPP_CHANNELS ) { + limLog(pMac, LOGE, + FL("Channel List is more than the supported Channel list")); + pTdlsLinkEstablishReq->supportedChannelsLen + = SIR_MAC_MAX_SUPP_CHANNELS; + } + + limTdlsGetIntersection(selfSupportedChannels, selfNumChans, + pTdlsLinkEstablishReq->supportedChannels, + pTdlsLinkEstablishReq->supportedChannelsLen, + pMsgTdlsLinkEstablishReq->validChannels, + &pMsgTdlsLinkEstablishReq->validChannelsLen); + } + vos_mem_copy(pMsgTdlsLinkEstablishReq->validOperClasses, + pTdlsLinkEstablishReq->supportedOperClasses, pTdlsLinkEstablishReq->supportedOperClassesLen); + pMsgTdlsLinkEstablishReq->validOperClassesLen = + pTdlsLinkEstablishReq->supportedOperClassesLen; + msg.type = WDA_SET_TDLS_LINK_ESTABLISH_REQ; + msg.reserved = 0; + msg.bodyptr = pMsgTdlsLinkEstablishReq; + msg.bodyval = 0; + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGE, FL("halPostMsgApi failed")); + goto lim_tdls_link_establish_error; + } + return eSIR_SUCCESS; +lim_tdls_link_establish_error: + limSendSmeTdlsLinkEstablishReqRsp(pMac, psessionEntry->smeSessionId, pTdlsLinkEstablishReq->peerMac, + NULL, eSIR_FAILURE) ; + + return eSIR_SUCCESS; +} + + +/* Delete all the TDLS peer connected before leaving the BSS */ +tSirRetStatus limDeleteTDLSPeers(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tpDphHashNode pStaDs = NULL ; + int i, aid; + + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("NULL psessionEntry")); + return eSIR_FAILURE; + } + + /* Check all the set bit in peerAIDBitmap and delete the peer (with that aid) entry + from the hash table and add the aid in free pool */ + for (i = 0; i < sizeof(psessionEntry->peerAIDBitmap)/sizeof(tANI_U32); i++) + { + for (aid = 0; aid < (sizeof(tANI_U32) << 3); aid++) + { + if (CHECK_BIT(psessionEntry->peerAIDBitmap[i], aid)) + { + pStaDs = dphGetHashEntry(pMac, (aid + i*(sizeof(tANI_U32) << 3)), &psessionEntry->dph.dphHashTable); + + if (NULL != pStaDs) + { + limLog(pMac, LOGE, FL("Deleting "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pStaDs->staAddr)); + + limSendDeauthMgmtFrame(pMac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + pStaDs->staAddr, psessionEntry, FALSE); + dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, &psessionEntry->dph.dphHashTable); + } + limReleasePeerIdx(pMac, (aid + i*(sizeof(tANI_U32) << 3)), psessionEntry) ; + CLEAR_BIT(psessionEntry->peerAIDBitmap[i], aid); + } + } + } + limSendSmeTDLSDeleteAllPeerInd(pMac, psessionEntry); + + return eSIR_SUCCESS; +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c new file mode 100644 index 000000000000..4fa31061d6c0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limPropExtsUtils.cc contains the utility functions + * to populate, parse proprietary extensions required to + * support ANI feature set. + * + * Author: Chandra Modumudi + * Date: 11/27/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "aniGlobal.h" +#include "wniCfgSta.h" +#include "sirCommon.h" +#include "sirDebug.h" +#include "utilsApi.h" +#include "cfgApi.h" +#include "limApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limPropExtsUtils.h" +#include "limSerDesUtils.h" +#include "limTrace.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#define LIM_GET_NOISE_MAX_TRY 5 + +#include "wma.h" +/** + * limExtractApCapability() + * + *FUNCTION: + * This function is called to extract AP's HCF/WME/WSM capability + * from the IEs received from it in Beacon/Probe Response frames + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pIE Pointer to starting IE in Beacon/Probe Response + * @param ieLen Length of all IEs combined + * @param qosCap Bits are set according to capabilities + * @return 0 - If AP does not assert HCF capability & 1 - otherwise + */ +void +limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, + tANI_U8 *qosCap, tANI_U16 *propCap, tANI_U8 *uapsd, + tPowerdBm *localConstraint, + tpPESession psessionEntry + ) +{ + tSirProbeRespBeacon *pBeaconStruct; +#if !defined WLAN_FEATURE_VOWIFI + tANI_U32 localPowerConstraints = 0; +#endif + tANI_U32 enableTxBF20MHz; + + pBeaconStruct = vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + if ( NULL == pBeaconStruct ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limExtractApCapability") ); + return; + } + + vos_mem_set( (tANI_U8 *) pBeaconStruct, sizeof(tSirProbeRespBeacon), 0); + *qosCap = 0; + *propCap = 0; + *uapsd = 0; + PELOG3(limLog( pMac, LOG3, + FL("In limExtractApCapability: The IE's being received are:")); + sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG3, pIE, ieLen );) + if (sirParseBeaconIE(pMac, pBeaconStruct, pIE, (tANI_U32)ieLen) == eSIR_SUCCESS) + { + if (pBeaconStruct->wmeInfoPresent || pBeaconStruct->wmeEdcaPresent + || pBeaconStruct->HTCaps.present) + LIM_BSS_CAPS_SET(WME, *qosCap); + if (LIM_BSS_CAPS_GET(WME, *qosCap) && pBeaconStruct->wsmCapablePresent) + LIM_BSS_CAPS_SET(WSM, *qosCap); + if (pBeaconStruct->propIEinfo.capabilityPresent) + *propCap = pBeaconStruct->propIEinfo.capability; + if (pBeaconStruct->HTCaps.present) + pMac->lim.htCapabilityPresentInBeacon = 1; + else + pMac->lim.htCapabilityPresentInBeacon = 0; + +#ifdef WLAN_FEATURE_11AC + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, + "***beacon.VHTCaps.present*****=%d BSS_VHT_CAPABLE:%d", + pBeaconStruct->VHTCaps.present, + IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, + "***beacon.SU Beamformer Capable*****=%d",pBeaconStruct->VHTCaps.suBeamFormerCap); + + if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) && pBeaconStruct->VHTOperation.present) + { + /* If VHT is supported min 80 MHz support is must */ + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + uint32_t vht_ch_wd; + + psessionEntry->vhtCapabilityPresentInBeacon = 1; + vht_ch_wd = VOS_MIN(fw_vht_ch_wd, + pBeaconStruct->VHTOperation.chanWidth); + /* + * First block covers 2 cases: + * 1) AP and STA both have same vht capab + * 2) AP is 160 (80+80), we are 160 only + */ + if (vht_ch_wd == pBeaconStruct->VHTOperation.chanWidth || + vht_ch_wd >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ ) { + psessionEntry->apCenterChan = + pBeaconStruct->VHTOperation.chanCenterFreqSeg1; + } else { + /* This is the case when AP was 160 but we were 80 only */ + psessionEntry->apCenterChan = + lim_get_80Mhz_center_channel(pBeaconStruct->channelNumber); + } + psessionEntry->apChanWidth = vht_ch_wd; + psessionEntry->vhtTxChannelWidthSet = vht_ch_wd; + + if (pBeaconStruct->Vendor1IEPresent && + pBeaconStruct->Vendor2IEPresent && + pBeaconStruct->Vendor3IEPresent) + { + if (((pBeaconStruct->VHTCaps.txMCSMap & VHT_MCS_3x3_MASK) == + VHT_MCS_3x3_MASK) && + ((pBeaconStruct->VHTCaps.txMCSMap & VHT_MCS_2x2_MASK) != + VHT_MCS_2x2_MASK)) + { + psessionEntry->txBFIniFeatureEnabled = 0; + if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, 0) + != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not set " + "WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); + } + } + } + if (!psessionEntry->htSupportedChannelWidthSet) { + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + &enableTxBF20MHz))) { + if (VOS_FALSE == enableTxBF20MHz) { + psessionEntry->txBFIniFeatureEnabled = 0; + if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, 0) + != eSIR_SUCCESS) { + limLog(pMac, LOGP, FL("could not set " + "WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); + } + } + } + } + } + else + { + psessionEntry->vhtCapabilityPresentInBeacon = 0; + } +#endif + // Extract the UAPSD flag from WMM Parameter element + if (pBeaconStruct->wmeEdcaPresent) + *uapsd = pBeaconStruct->edcaParams.qosInfo.uapsd; +#if defined FEATURE_WLAN_ESE + /* If there is Power Constraint Element specifically, + * adapt to it. Hence there is else condition check + * for this if statement. + */ + if ( pBeaconStruct->eseTxPwr.present) + { + *localConstraint = pBeaconStruct->eseTxPwr.power_limit; + } + psessionEntry->is_ese_version_ie_present = + pBeaconStruct->is_ese_ver_ie_present; +#endif + if (pBeaconStruct->powerConstraintPresent) + { +#if defined WLAN_FEATURE_VOWIFI + *localConstraint -= pBeaconStruct->localPowerConstraint.localPowerConstraints; +#else + localPowerConstraints = (tANI_U32)pBeaconStruct->localPowerConstraint.localPowerConstraints; +#endif + } +#if !defined WLAN_FEATURE_VOWIFI + if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, localPowerConstraints) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not update local power constraint to cfg.")); + } +#endif + psessionEntry->countryInfoPresent = FALSE; + /* Initializing before first use */ + if (pBeaconStruct->countryInfoPresent) + psessionEntry->countryInfoPresent = TRUE; + } + vos_mem_free(pBeaconStruct); + return; +} /****** end limExtractApCapability() ******/ + +/** + * limGetHTCBState + * + *FUNCTION: + * This routing provides the translation of Airgo Enum to HT enum for determining + * secondary channel offset. + * Airgo Enum is required for backward compatibility purposes. + * + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return The corresponding HT enumeration + */ +ePhyChanBondState limGetHTCBState(ePhyChanBondState aniCBMode) +{ + switch ( aniCBMode ) + { +#ifdef WLAN_FEATURE_11AC + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: +#endif + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; +#ifdef WLAN_FEATURE_11AC + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: +#endif + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + return PHY_DOUBLE_CHANNEL_LOW_PRIMARY; +#ifdef WLAN_FEATURE_11AC + case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + return PHY_SINGLE_CHANNEL_CENTERED; +#endif + default : + return PHY_SINGLE_CHANNEL_CENTERED; + } +} + + /* + * limGetStaPeerType + * + *FUNCTION: + * This API returns STA peer type + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pStaDs - Pointer to the tpDphHashNode of the STA + * under consideration + * @return tStaRateMode + */ +tStaRateMode limGetStaPeerType( tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tpPESession psessionEntry) +{ + tStaRateMode staPeerType = eSTA_11b; +#ifdef WLAN_FEATURE_11AC + if(pStaDs->mlmStaContext.vhtCapability) + staPeerType = eSTA_11ac; +#endif + else if(pStaDs->mlmStaContext.htCapability) + staPeerType = eSTA_11n; + else if(pStaDs->erpEnabled) + staPeerType = eSTA_11bg; + else if(psessionEntry->limRFBand == SIR_BAND_5_GHZ) + staPeerType = eSTA_11a; + return staPeerType; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.h new file mode 100644 index 000000000000..612292d78ade --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limPropExtsUtils.h contains the definitions + * used by all LIM modules to support proprietary features. + * Author: Chandra Modumudi + * Date: 12/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __LIM_PROP_EXTS_UTILS_H +#define __LIM_PROP_EXTS_UTILS_H + + +// Function templates +void limQuietBss(tpAniSirGlobal, tANI_U32); +void limCleanupMeasData(tpAniSirGlobal); +void limDeleteMeasTimers(tpAniSirGlobal); +void limStopMeasTimers(tpAniSirGlobal pMac); +void limCleanupMeasResources(tpAniSirGlobal); +void limRestorePreLearnState(tpAniSirGlobal); +void limCollectMeasurementData(tpAniSirGlobal, + tANI_U32 *, tpSchBeaconStruct); +void limCollectRSSI(tpAniSirGlobal); +void limDeleteCurrentBssWdsNode(tpAniSirGlobal); +tANI_U32 limComputeAvg(tpAniSirGlobal, tANI_U32, tANI_U32); + + +/// Function to extract AP's HCF capability from IE fields +void limExtractApCapability(tpAniSirGlobal, tANI_U8 *, tANI_U16, tANI_U8 *, tANI_U16 *, tANI_U8 *, tPowerdBm*, tpPESession); + +tStaRateMode limGetStaPeerType( tpAniSirGlobal, tpDphHashNode ,tpPESession); +#ifdef WLAN_FEATURE_11AC +ePhyChanBondState limGetHTCBState(ePhyChanBondState aniCBMode) ; +#endif + + +#endif /* __LIM_PROP_EXTS_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limRoamingAlgo.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limRoamingAlgo.c new file mode 100644 index 000000000000..b44504681ce6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limRoamingAlgo.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limRoamingAlgo.cc contains the code for LIM + * algorithms. + * Author: Chandra Modumudi + * Date: 03/01/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wniCfgSta.h" +#include "cfgApi.h" +#include "limTypes.h" +#include "limTimerUtils.h" +#include "limTrace.h" + + + +/** ---------------------------------------------------------------------- +\fn limSelectsBackgroundScanMode() +\brief This function is called by limIsBackgroundScanAllowed(). +\ Here LIM decides whether we shall enforce this background +\ scan or let HAL decide whether to proceed with the background +\ scan as HAL sees fits. LIM shall enforce background scan if: +\ 1) station is not in link established state +\ 2) station is in link established state, but there has been +\ max number of consecutive background scan failure. +\ +\param tpAniSirGlobal pMac +\return none +\ ------------------------------------------------------------------------- */ +tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal pMac) +{ + tANI_U32 cfgVal; + + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE, &cfgVal) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE value")); + return eSIR_NORMAL_BACKGROUND_SCAN; + } + + if (cfgVal == 0) + return eSIR_NORMAL_BACKGROUND_SCAN; + + /* If the "number of consecutive background scan failure" + * exceeds the maximum allowed, then LIM shall trigger an + * aggressive background scan. + */ + if (pMac->lim.gLimNumOfConsecutiveBkgndScanFailure >= cfgVal) + { + pMac->lim.gLimNumOfForcedBkgndScan += 1; + limLog(pMac, LOGE, + FL("Had %d consec scan fail(when expect < %d). Trigger AGGRESSIVE bkgnd scan."), + pMac->lim.gLimNumOfConsecutiveBkgndScanFailure, cfgVal); + return eSIR_AGGRESSIVE_BACKGROUND_SCAN; + } + + return eSIR_NORMAL_BACKGROUND_SCAN; +} + + +/** ----------------------------------------------------------- +\fn limIsBackgroundScanAllowed +\brief This function determines if background scan should be +\ allowed. It is called by limTriggerBackgroundScan(). +\param tpAniSirGlobal pMac +\return none +\ ------------------------------------------------------------- */ +static tANI_U8 limIsBackgroundScanAllowed(tpAniSirGlobal pMac) +{ + // if we are in the middle of a scan already, skip the background scan + if (limIsSystemInScanState(pMac) || + (pMac->lim.gLimBackgroundScanDisable) || + (pMac->lim.gLimForceBackgroundScanDisable) || + (pMac->lim.gLimBackgroundScanTerminate)) + return false; + + //need to do background scan in IBSS mode. + if (pMac->lim.gLimSystemRole == eLIM_STA_IN_IBSS_ROLE) + { + if (pMac->lim.gLimSmeState != eLIM_SME_NORMAL_STATE) + return false; + return true; + } + + // If station is not in link established state, then skip background scan + if ( (pMac->lim.gLimSystemRole == eLIM_STA_ROLE) && (pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_STATE) ) + return false; + + /* now that we have checked for scan state, check for other transitional + * states which should not be interrupted by scans + */ + if ((! (pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) ) && + (! (pMac->lim.gLimSmeState == eLIM_SME_JOIN_FAILURE_STATE) ) && + (! (pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_STATE) ) ) + return false; + + return true; +} + + +/** --------------------------------------------------------------- +\fn limTriggerBackgroundScan() +\brief This function is called upon background scan interval +\ when there is an exisiting link with an AP. +\ SME_SCAN_REQ is issued to SME state machine with Active +\ scanning is performed on one channel at a time. +\ +\ Assumptions: +\ Valid channel list at CFG is either populated by Roaming +\ algorithm upon determining/selecting a regulatory domain +\ or by default has all 36 possible channels. +\ +\param tpAniSirGlobal pMac +\return none +\ ----------------------------------------------------------------- */ +void limTriggerBackgroundScan(tpAniSirGlobal pMac) +{ + tANI_U32 len = WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN; + tANI_U32 ssidLen = SIR_MAC_MAX_SSID_LENGTH; + tSirMacChanNum bgScanChannelList[WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN]; + tSirSmeScanReq smeScanReq; + tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + tSirBackgroundScanMode backgroundScan; + + PELOG1(limLog(pMac, LOG1, FL("Background Scan: %d success, %d consec fail "), + pMac->lim.gLimNumOfBackgroundScanSuccess, pMac->lim.gLimNumOfConsecutiveBkgndScanFailure);) + + if (! limIsBackgroundScanAllowed(pMac)) + { + PELOG1(limLog(pMac, LOG1, FL("Skipping Background Scan "));) + return; + } + + // Get background scan channel list from CFG + if (wlan_cfgGetStr(pMac, WNI_CFG_BG_SCAN_CHANNEL_LIST, + (tANI_U8 *) bgScanChannelList, + (tANI_U32 *) &len) != eSIR_SUCCESS) + { + /** + * Could not get Valid channel list from CFG. + * Log error. + */ + PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list"));) + + return; + } + + // Time to perform background scan. Prepare and issue + // SME_SCAN_REQ to SME State machine + smeScanReq.messageType = eWNI_SME_SCAN_REQ; + smeScanReq.length = sizeof(tSirSmeScanReq); + smeScanReq.bssType = eSIR_INFRASTRUCTURE_MODE; + vos_mem_copy( (tANI_U8 *) smeScanReq.bssId, + (tANI_U8 *) &bcAddr, sizeof(tSirMacAddr)); + + if (wlan_cfgGetStr(pMac, WNI_CFG_SSID, + (tANI_U8 *) (smeScanReq.ssId[0].ssId), + (tANI_U32 *) &ssidLen) != eSIR_SUCCESS) + { + /// Could not get SSID from CFG. Log error. + limLog(pMac, LOGP, FL("could not retrieve SSID")); + } + smeScanReq.ssId[0].length = (tANI_U8) ssidLen; + smeScanReq.numSsid = 1; + + smeScanReq.scanType = eSIR_ACTIVE_SCAN; + smeScanReq.sessionId = 0; + + if (wlan_cfgGetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + &smeScanReq.minChannelTime) != eSIR_SUCCESS) + { + /// Could not get minChlTime value from CFG. Log error. + PELOGE(limLog(pMac, LOGE, FL("could not retrieve minChlTime value"));) + + return; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + &smeScanReq.maxChannelTime) != eSIR_SUCCESS) + { + /// Could not get maxChlTime value from CFG. Log error. + PELOGE(limLog(pMac, LOGE, FL("could not retrieve maxChlTime value"));) + + return; + } + + smeScanReq.returnAfterFirstMatch = 0; + smeScanReq.returnUniqueResults = 1; + + //At the first channel scan, clear the cached results + if(pMac->lim.gLimBackgroundScanChannelId == 0) + { + /* + * Do not purge while starting a scan. Rome firmware sends results + * of roaming scan into this cache. + */ + smeScanReq.returnFreshResults = SIR_BG_SCAN_RETURN_FRESH_RESULTS; + } + else + { + smeScanReq.returnFreshResults = SIR_BG_SCAN_RETURN_FRESH_RESULTS; + } + + + smeScanReq.channelList.numChannels = 1; + if (pMac->lim.gLimBackgroundScanChannelId >= len) + { + pMac->lim.gLimBackgroundScanChannelId = 0; + + PELOGE(limLog(pMac, LOGE, FL("Skipping Background Scan since the channel list is exhausted."));) + PELOGE(limLog(pMac, LOGE, FL("SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD indication to start the background scan again."));) + + /* Stop the BG scan timer here. SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD + * indication to start the background scan again. + */ + if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_BACKGROUND_SCAN_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimBackgroundScanTimer) + != TX_SUCCESS) + { + // Could not deactivate BackgroundScanTimer timer. + // Log error + limLog(pMac, LOGP, + FL("unable to deactivate BackgroundScanTimer timer")); + } + } + + pMac->lim.gLimBackgroundScanTerminate = TRUE; + + PELOGE(limLog(pMac, LOGE, FL("Send dummy scan with returnFreshResults as 0 to report BG scan results to SME."));) + return; + } + smeScanReq.channelList.channelNumber[0] = + bgScanChannelList[pMac->lim.gLimBackgroundScanChannelId++]; + + smeScanReq.uIEFieldLen = 0; + smeScanReq.uIEFieldOffset = sizeof(tSirSmeScanReq); + + backgroundScan = limSelectsBackgroundScanMode(pMac); + PELOG1(limLog(pMac, LOG1, FL("Performing (mode %s (%d)) Background Scan"), + lim_BackgroundScanModetoString(backgroundScan), + backgroundScan);) + smeScanReq.backgroundScanMode = backgroundScan; + + //determine whether to send the results or not, If so, notify the BG scan results to SME + if (pMac->lim.gLimBackgroundScanChannelId >= len) + { + pMac->lim.gLimReportBackgroundScanResults = TRUE; + } + + limPostSmeMessage(pMac, + eWNI_SME_SCAN_REQ, + (tANI_U32 *) &smeScanReq); +} /*** limTriggerBackgroundScan() ***/ + + +/** ---------------------------------------------------------------------- +\fn limAbortBackgroundScan +\brief This function aborts background scan and send scan +\ response to SME. +\param tpAniSirGlobal pMac +\return none +\ ------------------------------------------------------------------------- */ +void limAbortBackgroundScan(tpAniSirGlobal pMac) +{ + tANI_U16 scanRspLen = 8; + + if(pMac->lim.gLimBackgroundScanTerminate == FALSE) + { + limLog(pMac, LOGE, FL("Abort Background Scan ")); + if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); + } + + pMac->lim.gLimBackgroundScanTerminate = TRUE; + pMac->lim.gLimBackgroundScanStarted = FALSE; + + if (pMac->lim.gLimSmeScanResultLength == 0) + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, 0, 0); + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeScanResultLength - + sizeof(tSirBssDescription); + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, 0, 0); + } + } + + // reset background scan variables + pMac->lim.gLimBackgroundScanChannelId = 0; + return; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.c new file mode 100644 index 000000000000..94ae6ad0d547 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -0,0 +1,1409 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limScanResultUtils.cc contains the utility functions + * LIM uses for maintaining and accessing scan results on STA. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "limTypes.h" +#include "limUtils.h" +#include "limSerDesUtils.h" +#include "limApi.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif +#include "vos_utils.h" + +/** + * limDeactiveMinChannelTimerDuringScan() + * + *FUNCTION: + * This function is called during scan upon receiving + * Beacon/Probe Response frame to deactivate MIN channel + * timer if running. + * + * This function should be called only when pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * + * @return eSIR_SUCCESS in case of success + */ + +tANI_U32 +limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal pMac) +{ + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) && (pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE)) + { + /** + * Beacon/Probe Response is received during active scanning. + * Deactivate MIN channel timer if running. + */ + + limDeactivateAndChangeTimer(pMac,eLIM_MIN_CHANNEL_TIMER); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_MAX_CHANNEL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) + == TX_TIMER_ERROR) + { + /// Could not activate max channel timer. + // Log error + limLog(pMac,LOGP, FL("could not activate max channel timer")); + + limCompleteMlmScan(pMac, eSIR_SME_RESOURCES_UNAVAILABLE); + return TX_TIMER_ERROR; + } + } + return eSIR_SUCCESS; +} /*** end limDeactivateMinChannelTimerDuringScan() ***/ + + + +/** + * limCollectBssDescription() + * + *FUNCTION: + * This function is called during scan upon receiving + * Beacon/Probe Response frame to check if the received + * frame matches scan criteria, collect BSS description + * and add it to cached scan results. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pBPR - Pointer to parsed Beacon/Probe Response structure + * @param pRxPacketInfo - Pointer to Received frame's BD + * ---------if defined WLAN_FEATURE_VOWIFI------ + * @param fScanning - flag to indicate if it is during scan. + * --------------------------------------------- + * + * @return None + */ +#if defined WLAN_FEATURE_VOWIFI +eHalStatus +limCollectBssDescription(tpAniSirGlobal pMac, + tSirBssDescription *pBssDescr, + tpSirProbeRespBeacon pBPR, + tANI_U8 *pRxPacketInfo, + tANI_U8 fScanning) +#else +eHalStatus +limCollectBssDescription(tpAniSirGlobal pMac, + tSirBssDescription *pBssDescr, + tpSirProbeRespBeacon pBPR, + tANI_U8 *pRxPacketInfo) +#endif +{ + tANI_U8 *pBody; + tANI_U32 ieLen = 0; + tpSirMacMgmtHdr pHdr; + tANI_U8 channelNum; + tANI_U8 rxChannel; + tANI_U8 rfBand = 0; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + if (SIR_MAC_B_PR_SSID_OFFSET > WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)) + { + VOS_ASSERT(WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) >= SIR_MAC_B_PR_SSID_OFFSET); + return eHAL_STATUS_FAILURE; + } + ieLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) - SIR_MAC_B_PR_SSID_OFFSET; + rxChannel = WDA_GET_RX_CH(pRxPacketInfo); + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + rfBand = WDA_GET_RX_RFBAND(pRxPacketInfo); + + /** + * Drop all the beacons and probe response without P2P IE during P2P search + */ + if ((NULL != pMac->lim.gpLimMlmScanReq && pMac->lim.gpLimMlmScanReq->p2pSearch) || + (pMac->fScanOffload && pMac->lim.fOffloadScanPending && + (pMac->lim.fOffloadScanP2PSearch || + pMac->lim.fOffloadScanP2PListen))) + { + if (NULL == limGetP2pIEPtr(pMac, (pBody + SIR_MAC_B_PR_SSID_OFFSET), ieLen)) + { + limLog( pMac, LOG3, MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pHdr->bssId)); + return eHAL_STATUS_FAILURE; + } + } + + /** + * Length of BSS desription is without length of + * length itself and length of pointer + * that holds ieFields + * + * tSirBssDescription + * +--------+---------------------------------+---------------+ + * | length | other fields | pointer to IEs| + * +--------+---------------------------------+---------------+ + * ^ + * ieFields + */ + pBssDescr->length = (tANI_U16)(offsetof(tSirBssDescription, ieFields[0]) - + sizeof(pBssDescr->length) + ieLen); + + // Copy BSS Id + vos_mem_copy((tANI_U8 *) &pBssDescr->bssId, + (tANI_U8 *) pHdr->bssId, + sizeof(tSirMacAddr)); + + // Copy Timestamp, Beacon Interval and Capability Info + pBssDescr->scanSysTimeMsec = vos_timer_get_system_time(); + + pBssDescr->timeStamp[0] = pBPR->timeStamp[0]; + pBssDescr->timeStamp[1] = pBPR->timeStamp[1]; + pBssDescr->beaconInterval = pBPR->beaconInterval; + pBssDescr->capabilityInfo = limGetU16((tANI_U8 *) &pBPR->capabilityInfo); + + if(!pBssDescr->beaconInterval ) + { + limLog(pMac, LOGW, + FL("Beacon Interval is ZERO, making it to default 100 " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->bssId)); + pBssDescr->beaconInterval= 100; + } + /* + * There is a narrow window after Channel Switch msg is sent to HAL and before the AGC is shut + * down and beacons/Probe Rsps can trickle in and we may report the incorrect channel in 5Ghz + * band, so not relying on the 'last Scanned Channel' stored in LIM. + * Instead use the value returned by RXP in BD. This the the same value which HAL programs into + * RXP before every channel switch. + * Right now there is a problem in 5Ghz, where we are receiving beacons from a channel different from + * the currently scanned channel. so incorrect channel is reported to CSR and association does not happen. + * So for now we keep on looking for the channel info in the beacon (DSParamSet IE OR HT Info IE), and only if it + * is not present in the beacon, we go for the channel info present in RXP. + * This fix will work for 5Ghz 11n devices, but for 11a devices, we have to rely on RXP routing flag to get the correct channel. + * So The problem of incorrect channel reporting in 5Ghz will still remain for 11a devices. + */ + pBssDescr->channelId = limGetChannelFromBeacon(pMac, pBPR); + + if (pBssDescr->channelId == 0) + { + /* If the channel Id is not retrieved from Beacon, extract the channel from BD */ + /* Unmapped the channel.This We have to do since we have done mapping in the hal to + overcome the limitation of RXBD of not able to accomodate the bigger channel number.*/ + if ((!rfBand) || IS_5G_BAND(rfBand)) + { + rxChannel = limUnmapChannel(rxChannel); + } + if (!rxChannel) + { + rxChannel = pMac->lim.gLimCurrentScanChannelId; + } + pBssDescr->channelId = rxChannel; + } + + pBssDescr->channelIdSelf = pBssDescr->channelId; + //set the network type in bss description + channelNum = pBssDescr->channelId; + pBssDescr->nwType = limGetNwType(pMac, channelNum, SIR_MAC_MGMT_FRAME, pBPR); + + // Copy RSSI & SINR from BD + + PELOG4(limLog(pMac, LOG4, "***********BSS Description for BSSID:*********** "); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, pBssDescr->bssId, 6 ); + sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG4, (tANI_U8*)pRxPacketInfo, 36 );) + + pBssDescr->rssi = (tANI_S8)WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + pBssDescr->rssi_raw = (tANI_S8)WDA_GET_RX_RSSI_RAW(pRxPacketInfo); + + //SINR no longer reported by HW + pBssDescr->sinr = 0; + pBssDescr->nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + pBssDescr->tsf_delta = WDA_GET_RX_TSF_DELTA(pRxPacketInfo); + + limLog(pMac, LOG1, + FL("BSSID: "MAC_ADDRESS_STR " rssi: normalized = %d, absolute = %d tsf_delta = %u"), + MAC_ADDR_ARRAY(pHdr->bssId), pBssDescr->rssi, pBssDescr->rssi_raw, + pBssDescr->tsf_delta); + +#if defined WLAN_FEATURE_VOWIFI + if( fScanning ) + { + rrmGetStartTSF( pMac, pBssDescr->startTSF ); + pBssDescr->parentTSF = WDA_GET_RX_TIMESTAMP(pRxPacketInfo); + } +#endif + +#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( pBPR->mdiePresent) + { + pBssDescr->mdiePresent = TRUE; + pBssDescr->mdie[0] = pBPR->mdie[0]; + pBssDescr->mdie[1] = pBPR->mdie[1]; + pBssDescr->mdie[2] = pBPR->mdie[2]; + } +#endif + +#ifdef FEATURE_WLAN_ESE + pBssDescr->QBSSLoad_present = FALSE; + pBssDescr->QBSSLoad_avail = 0; + if( pBPR->QBSSLoad.present) + { + pBssDescr->QBSSLoad_present = TRUE; + pBssDescr->QBSSLoad_avail = pBPR->QBSSLoad.avail; + } +#endif + // Copy IE fields + vos_mem_copy((tANI_U8 *) &pBssDescr->ieFields, + pBody + SIR_MAC_B_PR_SSID_OFFSET, + ieLen); + + /*set channel number in beacon in case it is not present*/ + pBPR->channelNumber = pBssDescr->channelId; + + limLog( pMac, LOG3, + FL("Collected BSS Description for Channel(%1d), length(%u), IE Fields(%u)"), + pBssDescr->channelId, + pBssDescr->length, + ieLen ); + + return eHAL_STATUS_SUCCESS; +} /*** end limCollectBssDescription() ***/ + +/** + * limIsScanRequestedSSID() + * + *FUNCTION: + * This function is called during scan upon receiving + * Beacon/Probe Response frame to check if the received + * SSID is present in the list of requested SSIDs in scan + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param ssId - SSID Received in beacons/Probe responses that is compared against the + requeusted SSID in scan list + * --------------------------------------------- + * + * @return boolean - TRUE if SSID is present in requested list, FALSE otherwise + */ + +tANI_BOOLEAN limIsScanRequestedSSID(tpAniSirGlobal pMac, tSirMacSSid *ssId) +{ + tANI_U8 i = 0; + + for (i = 0; i < pMac->lim.gpLimMlmScanReq->numSsid; i++) + { + if ( eANI_BOOLEAN_TRUE == vos_mem_compare((tANI_U8 *) ssId, + (tANI_U8 *) &pMac->lim.gpLimMlmScanReq->ssId[i], + (tANI_U8) (pMac->lim.gpLimMlmScanReq->ssId[i].length + 1))) + { + return eANI_BOOLEAN_TRUE; + } + } + return eANI_BOOLEAN_FALSE; +} + +/** + * limCheckAndAddBssDescription() + * + *FUNCTION: + * This function is called during scan upon receiving + * Beacon/Probe Response frame to check if the received + * frame matches scan criteria, collect BSS description + * and add it to cached scan results. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pBPR - Pointer to parsed Beacon/Probe Response structure + * @param pRxPacketInfo - Pointer to Received frame's BD + * @param fScanning - boolean to indicate whether the BSS is from current scan or just happen to receive a beacon + * + * @return None + */ + +void +limCheckAndAddBssDescription(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBPR, + tANI_U8 *pRxPacketInfo, + tANI_BOOLEAN fScanning, + tANI_U8 fProbeRsp) +{ + tLimScanResultNode *pBssDescr; + tANI_U32 frameLen, ieLen = 0; + tANI_U8 rxChannelInBeacon = 0; + eHalStatus status; + tANI_U8 dontUpdateAll = 0; + tANI_U8 rfBand = 0; + tANI_U8 rxChannelInBD = 0; + + tSirMacAddr bssid = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tSirMacAddr bssid_zero = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + tANI_BOOLEAN fFound = FALSE; + tpSirMacDataHdr3a pHdr; + + pHdr = WDA_GET_RX_MPDUHEADER3A((tANI_U8 *)pRxPacketInfo); + + // Check For Null BSSID; Skip in case of P2P. + if (vos_mem_compare(bssid_zero, &pHdr->addr3, 6)) + { + return ; + } + + //Checking if scanning for a particular BSSID + if ((fScanning) && (pMac->lim.gpLimMlmScanReq)) + { + fFound = vos_mem_compare(pHdr->addr3, &pMac->lim.gpLimMlmScanReq->bssId, 6); + if (!fFound) + { + if ((pMac->lim.gpLimMlmScanReq->p2pSearch) && + (vos_mem_compare(pBPR->P2PProbeRes.P2PDeviceInfo.P2PDeviceAddress, + &pMac->lim.gpLimMlmScanReq->bssId, 6))) + { + fFound = eANI_BOOLEAN_TRUE; + } + } + } + + /** + * Compare SSID with the one sent in + * Probe Request frame, if any. + * If they don't match, ignore the + * Beacon frame. + * pMac->lim.gLimMlmScanReq->ssId.length == 0 + * indicates Broadcast SSID. + * When gLimReturnAfterFirstMatch is set, it means the scan has to match + * a SSID (if it is also set). Ignore the other BSS in that case. + */ + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))) + { +#endif + if ((pMac->lim.gpLimMlmScanReq) && + (((fScanning) && + ( pMac->lim.gLimReturnAfterFirstMatch & 0x01 ) && + (pMac->lim.gpLimMlmScanReq->numSsid) && + !limIsScanRequestedSSID(pMac, &pBPR->ssId)) || + (!fFound && (pMac->lim.gpLimMlmScanReq && + pMac->lim.gpLimMlmScanReq->bssId) && + !vos_mem_compare(bssid, + &pMac->lim.gpLimMlmScanReq->bssId, 6)))) + { + /** + * Received SSID does not match with + * the one we're scanning for. + * Ignore received Beacon frame + */ + + return; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + + /* There is no point in caching & reporting the scan results for APs + * which are in the process of switching the channel. So, we are not + * caching the scan results for APs which are adverzing the channel-switch + * element in their beacons and probe responses. + */ + if(pBPR->channelSwitchPresent) + { + return; + } + + /* If beacon/probe resp DS param channel does not match with + * RX BD channel then don't save the results. It might be a beacon + * from another channel heard as noise on the current scanning channel + */ + + if ((pBPR->dsParamsPresent) || (pBPR->HTInfo.present)) + { + /* This means that we are in 2.4GHz mode or 5GHz 11n mode */ + rxChannelInBeacon = limGetChannelFromBeacon(pMac, pBPR); + rfBand = WDA_GET_RX_RFBAND(pRxPacketInfo); + rxChannelInBD = WDA_GET_RX_CH(pRxPacketInfo); + + if ((!rfBand) || IS_5G_BAND(rfBand)) + { + rxChannelInBD = limUnmapChannel(rxChannelInBD); + } + + if(rxChannelInBD != rxChannelInBeacon) + { + /* BCAST Frame, if CH do not match, Drop */ + if(WDA_IS_RX_BCAST(pRxPacketInfo)) + { + limLog(pMac, LOG3, FL("Beacon/Probe Rsp dropped. Channel in BD %d. " + "Channel in beacon" " %d"), + WDA_GET_RX_CH(pRxPacketInfo),limGetChannelFromBeacon(pMac, pBPR)); + return; + } + /* Unit cast frame, Probe RSP, do not drop */ + else + { + dontUpdateAll = 1; + limLog(pMac, LOG3, FL("SSID %s, CH in ProbeRsp %d, CH in BD %d, miss-match, Do Not Drop"), + pBPR->ssId.ssId, + rxChannelInBeacon, + WDA_GET_RX_CH(pRxPacketInfo)); + WDA_GET_RX_CH(pRxPacketInfo) = rxChannelInBeacon; + } + } + } + + /** + * Allocate buffer to hold BSS description from + * received Beacon frame. + * Include size of fixed fields and IEs length + */ + + ieLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + if (ieLen <= SIR_MAC_B_PR_SSID_OFFSET) + { + limLog(pMac, LOGP, + FL("RX packet has invalid length %d"), ieLen); + return; + } + + ieLen -= SIR_MAC_B_PR_SSID_OFFSET; + + frameLen = sizeof(tLimScanResultNode) + ieLen - sizeof(tANI_U32); //Sizeof(tANI_U32) is for ieFields[1] + + pBssDescr = vos_mem_malloc(frameLen); + if ( NULL == pBssDescr ) + { + // Log error + limLog(pMac, LOGP, + FL("call for AllocateMemory failed for storing BSS description")); + + return; + } + + // In scan state, store scan result. +#if defined WLAN_FEATURE_VOWIFI + status = limCollectBssDescription(pMac, &pBssDescr->bssDescription, + pBPR, pRxPacketInfo, fScanning); + if (eHAL_STATUS_SUCCESS != status) + { + goto last; + } +#else + status = limCollectBssDescription(pMac, &pBssDescr->bssDescription, + pBPR, pRxPacketInfo); + if (eHAL_STATUS_SUCCESS != status) + { + goto last; + } +#endif + pBssDescr->bssDescription.fProbeRsp = fProbeRsp; + + pBssDescr->next = NULL; + + /** + * Depending on whether to store unique or all + * scan results, pass hash update/add parameter + * For LFR candidates just add them on it's own cache + */ + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + limLog(pMac, LOG1, FL(" pHdr->addr1:"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->addr1)); + limLog(pMac, LOG1, FL(" pHdr->addr2:"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->addr2)); + limLog(pMac, LOG1, FL(" pHdr->addr3:"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->addr3)); + limLog( pMac, LOG1, FL("Save this entry in LFR cache")); + status = limLookupNaddLfrHashEntry(pMac, pBssDescr, LIM_HASH_ADD, dontUpdateAll); + } + else +#endif + //If it is not scanning, only save unique results + if (pMac->lim.gLimReturnUniqueResults || (!fScanning)) + { + status = limLookupNaddHashEntry(pMac, pBssDescr, LIM_HASH_UPDATE, dontUpdateAll); + } + else + { + status = limLookupNaddHashEntry(pMac, pBssDescr, LIM_HASH_ADD, dontUpdateAll); + } + + if(fScanning) + { + if ((pBssDescr->bssDescription.channelId <= 14) && + (pMac->lim.gLimReturnAfterFirstMatch & 0x40) && + pBPR->countryInfoPresent) + pMac->lim.gLim24Band11dScanDone = 1; + + if ((pBssDescr->bssDescription.channelId > 14) && + (pMac->lim.gLimReturnAfterFirstMatch & 0x80) && + pBPR->countryInfoPresent) + pMac->lim.gLim50Band11dScanDone = 1; + + if ( ( pMac->lim.gLimReturnAfterFirstMatch & 0x01 ) || + ( pMac->lim.gLim24Band11dScanDone && ( pMac->lim.gLimReturnAfterFirstMatch & 0x40 ) ) || + ( pMac->lim.gLim50Band11dScanDone && ( pMac->lim.gLimReturnAfterFirstMatch & 0x80 ) ) || + fFound ) + { + /** + * Stop scanning and return the BSS description(s) + * collected so far. + */ + limLog(pMac, + LOGW, + FL("Completed scan: 24Band11dScan = %d, 50Band11dScan = %d BSS id"), + pMac->lim.gLim24Band11dScanDone, + pMac->lim.gLim50Band11dScanDone); + + //Need to disable the timers. If they fire, they will send END_SCAN + //while we already send FINISH_SCAN here. This may mess up the gLimHalScanState + limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); + limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq( pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE ); + //limSendHalFinishScanReq( pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE ); + } + }//(eANI_BOOLEAN_TRUE == fScanning) + +last: + if( eHAL_STATUS_SUCCESS != status ) + { + vos_mem_free( pBssDescr ); + } + return; +} /****** end limCheckAndAddBssDescription() ******/ + + + +/** + * limScanHashFunction() + * + *FUNCTION: + * This function is called during scan hash entry operations + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param bssId - Received BSSid + * + * @return Hash index + */ + +tANI_U8 +limScanHashFunction(tSirMacAddr bssId) +{ + tANI_U16 i, hash = 0; + + for (i = 0; i < sizeof(tSirMacAddr); i++) + hash += bssId[i]; + + return hash % LIM_MAX_NUM_OF_SCAN_RESULTS; +} /****** end limScanHashFunction() ******/ + + + +/** + * limInitHashTable() + * + *FUNCTION: + * This function is called upon receiving SME_START_REQ + * to initialize global cached scan hash table + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limInitHashTable(tpAniSirGlobal pMac) +{ + tANI_U16 i; + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + pMac->lim.gLimCachedScanHashTable[i] = NULL; +} /****** end limInitHashTable() ******/ + + + +/** + * limLookupNaddHashEntry() + * + *FUNCTION: + * This function is called upon receiving a Beacon or + * Probe Response frame during scan phase to store + * received BSS description into scan result hash table. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pBssDescr - Pointer to BSS description to be + * added to the scan result hash table. + * @param action - Indicates action to be performed + * when same BSS description is found. This is + * dependent on whether unique scan result to + * be stored or not. + * + * @return None + */ + +eHalStatus +limLookupNaddHashEntry(tpAniSirGlobal pMac, + tLimScanResultNode *pBssDescr, tANI_U8 action, + tANI_U8 dontUpdateAll) +{ + tANI_U8 index, ssidLen = 0; + tANI_U8 found = false; + tLimScanResultNode *ptemp, *pprev; + tSirMacCapabilityInfo *pSirCap, *pSirCapTemp; + int idx, len; + tANI_U8 *pbIe; + tANI_S8 rssi = 0; + tANI_S8 rssi_raw = 0; + + index = limScanHashFunction(pBssDescr->bssDescription.bssId); + ptemp = pMac->lim.gLimCachedScanHashTable[index]; + + //ieFields start with TLV of SSID IE + ssidLen = * ((tANI_U8 *) &pBssDescr->bssDescription.ieFields + 1); + pSirCap = (tSirMacCapabilityInfo *)&pBssDescr->bssDescription.capabilityInfo; + + for (pprev = ptemp; ptemp; pprev = ptemp, ptemp = ptemp->next) + { + //For infrastructure, check BSSID and SSID. For IBSS, check more + pSirCapTemp = (tSirMacCapabilityInfo *)&ptemp->bssDescription.capabilityInfo; + if ((pSirCapTemp->ess == pSirCap->ess) && //matching ESS type first + (vos_mem_compare( (tANI_U8 *) pBssDescr->bssDescription.bssId, + (tANI_U8 *) ptemp->bssDescription.bssId, + sizeof(tSirMacAddr))) && //matching BSSID + // matching band to update new channel info + (vos_chan_to_band(pBssDescr->bssDescription.channelId) == + vos_chan_to_band(ptemp->bssDescription.channelId)) && + vos_mem_compare( ((tANI_U8 *) &pBssDescr->bssDescription.ieFields + 1), + ((tANI_U8 *) &ptemp->bssDescription.ieFields + 1), + (tANI_U8) (ssidLen + 1)) && + ((pSirCapTemp->ess) || //we are done for infrastructure + //For IBSS, nwType and channelId + (((pBssDescr->bssDescription.nwType == + ptemp->bssDescription.nwType) && + (pBssDescr->bssDescription.channelId == + ptemp->bssDescription.channelId)))) + ) + { + if (ptemp->bssDescription.fProbeRsp && + !pBssDescr->bssDescription.fProbeRsp) + { + /* If the previously saved frame is probe response + * and the current frame is beacon, then no need + * to update the scan database. Probe response is + * going to have more proper information than beacon + * frame. So it is better to inform the probe + * response frame instead of beacon for proper + * information. */ + return eHAL_STATUS_FAILURE; + } + // Found the same BSS description + if (action == LIM_HASH_UPDATE) + { + if(dontUpdateAll) + { + rssi = ptemp->bssDescription.rssi; + rssi_raw = ptemp->bssDescription.rssi_raw; + } + + if(pBssDescr->bssDescription.fProbeRsp != ptemp->bssDescription.fProbeRsp) + { + //We get a different, save the old frame WSC IE if it is there + idx = 0; + len = ptemp->bssDescription.length - sizeof(tSirBssDescription) + + sizeof(tANI_U16) + sizeof(tANI_U32) - DOT11F_IE_WSCPROBERES_MIN_LEN - 2; + pbIe = (tANI_U8 *)ptemp->bssDescription.ieFields; + //Save WPS IE if it exists + pBssDescr->bssDescription.WscIeLen = 0; + while(idx < len) + { + if((DOT11F_EID_WSCPROBERES == pbIe[0]) && + (0x00 == pbIe[2]) && (0x50 == pbIe[3]) && (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) + { + //Found it + if((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= pbIe[1]) + { + vos_mem_copy(pBssDescr->bssDescription.WscIeProbeRsp, + pbIe, pbIe[1] + 2); + pBssDescr->bssDescription.WscIeLen = pbIe[1] + 2; + } + break; + } + idx += pbIe[1] + 2; + pbIe += pbIe[1] + 2; + } + } + + + if(NULL != pMac->lim.gpLimMlmScanReq) + { + if((pMac->lim.gpLimMlmScanReq->numSsid)&& + ( limIsNullSsid((tSirMacSSid *)((tANI_U8 *) + &pBssDescr->bssDescription.ieFields + 1)))) + return eHAL_STATUS_FAILURE; + } + + // Delete this entry + if (ptemp == pMac->lim.gLimCachedScanHashTable[index]) + pprev = pMac->lim.gLimCachedScanHashTable[index] = ptemp->next; + else + pprev->next = ptemp->next; + + pMac->lim.gLimMlmScanResultLength -= + ptemp->bssDescription.length + sizeof(tANI_U16); + + vos_mem_free(ptemp); + } + found = true; + break; + } + } + + if ((false == found) && dontUpdateAll) + return eHAL_STATUS_FAILURE; + + //for now, only rssi, we can add more if needed + if ((action == LIM_HASH_UPDATE) && dontUpdateAll && rssi && rssi_raw) + { + pBssDescr->bssDescription.rssi = rssi; + pBssDescr->bssDescription.rssi_raw = rssi_raw; + } + + // Add this BSS description at same index + if (pprev == pMac->lim.gLimCachedScanHashTable[index]) + { + pBssDescr->next = pMac->lim.gLimCachedScanHashTable[index]; + pMac->lim.gLimCachedScanHashTable[index] = pBssDescr; + } + else + { + pBssDescr->next = pprev->next; + pprev->next = pBssDescr; + } + pMac->lim.gLimMlmScanResultLength += + pBssDescr->bssDescription.length + sizeof(tANI_U16); + + PELOG2(limLog(pMac, LOG2, FL("Added new BSS description size %d TOT %d BSS id"), + pBssDescr->bssDescription.length, + pMac->lim.gLimMlmScanResultLength); + limPrintMacAddr(pMac, pBssDescr->bssDescription.bssId, LOG2);) + + // Send new BSS found indication to HDD if CFG option is set + if (!found) limSendSmeNeighborBssInd(pMac, pBssDescr); + + // + // TODO: IF applicable, do we need to send: + // Mesg - eWNI_SME_WM_STATUS_CHANGE_NTF + // Status change code - eSIR_SME_CB_LEGACY_BSS_FOUND_BY_AP + // + return eHAL_STATUS_SUCCESS; +} + + + +/** + * limDeleteHashEntry() + * + *FUNCTION: + * This function is called upon to delete + * a BSS description from scan result hash table. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * Yet to find the utility of the function + * + * @param pBssDescr - Pointer to BSS description to be + * deleted from the scan result hash table. + * + * @return None + */ + +void limDeleteHashEntry(tLimScanResultNode *pBssDescr) +{ +} /****** end limDeleteHashEntry() ******/ + + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * limInitLfrHashTable() + * + *FUNCTION: + * This function is called upon receiving SME_START_REQ + * to initialize global cached Lfr scan hash table + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limInitLfrHashTable(tpAniSirGlobal pMac) +{ + tANI_U16 i; + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + pMac->lim.gLimCachedLfrScanHashTable[i] = NULL; +} /****** end limInitLfrHashTable() ******/ + + + +/** + * limLookupNaddLfrHashEntry() + * + *FUNCTION: + * This function is called upon receiving a Beacon or + * Probe Response frame during Lfr scan phase from FW to store + * received BSS description into Lfr scan result hash table. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pBssDescr - Pointer to BSS description to be + * added to the Lfr scan result hash table. + * @param action - Indicates action to be performed + * when same BSS description is found. This is + * dependent on whether unique scan result to + * be stored or not. + * + * @return None + */ + +eHalStatus +limLookupNaddLfrHashEntry(tpAniSirGlobal pMac, + tLimScanResultNode *pBssDescr, tANI_U8 action, + tANI_U8 dontUpdateAll) +{ + tANI_U8 index, ssidLen = 0; + tLimScanResultNode *ptemp, *pprev; + tSirMacCapabilityInfo *pSirCap, *pSirCapTemp; + int idx, len; + tANI_U8 *pbIe; + tANI_S8 rssi = 0; + tANI_S8 rssi_raw = 0; + + index = limScanHashFunction(pBssDescr->bssDescription.bssId); + ptemp = pMac->lim.gLimCachedLfrScanHashTable[index]; + + //ieFields start with TLV of SSID IE + ssidLen = * ((tANI_U8 *) &pBssDescr->bssDescription.ieFields + 1); + pSirCap = (tSirMacCapabilityInfo *)&pBssDescr->bssDescription.capabilityInfo; + + for (pprev = ptemp; ptemp; pprev = ptemp, ptemp = ptemp->next) + { + //For infrastructure, check BSSID and SSID. For IBSS, check more + pSirCapTemp = (tSirMacCapabilityInfo *)&ptemp->bssDescription.capabilityInfo; + if ((pSirCapTemp->ess == pSirCap->ess) && //matching ESS type first + (vos_mem_compare( (tANI_U8 *) pBssDescr->bssDescription.bssId, + (tANI_U8 *) ptemp->bssDescription.bssId, + sizeof(tSirMacAddr))) && //matching BSSID + (pBssDescr->bssDescription.channelId == + ptemp->bssDescription.channelId) && + vos_mem_compare( ((tANI_U8 *) &pBssDescr->bssDescription.ieFields + 1), + ((tANI_U8 *) &ptemp->bssDescription.ieFields + 1), + (tANI_U8) (ssidLen + 1)) && + ((pSirCapTemp->ess) || //we are done for infrastructure + //For IBSS, nwType and channelId + (((pBssDescr->bssDescription.nwType == + ptemp->bssDescription.nwType) && + (pBssDescr->bssDescription.channelId == + ptemp->bssDescription.channelId)))) + ) + { + // Found the same BSS description + if (action == LIM_HASH_UPDATE) + { + if(dontUpdateAll) + { + rssi = ptemp->bssDescription.rssi; + rssi_raw = ptemp->bssDescription.rssi_raw; + } + + if(pBssDescr->bssDescription.fProbeRsp != ptemp->bssDescription.fProbeRsp) + { + //We get a different, save the old frame WSC IE if it is there + idx = 0; + len = ptemp->bssDescription.length - sizeof(tSirBssDescription) + + sizeof(tANI_U16) + sizeof(tANI_U32) - DOT11F_IE_WSCPROBERES_MIN_LEN - 2; + pbIe = (tANI_U8 *)ptemp->bssDescription.ieFields; + //Save WPS IE if it exists + pBssDescr->bssDescription.WscIeLen = 0; + while(idx < len) + { + if((DOT11F_EID_WSCPROBERES == pbIe[0]) && + (0x00 == pbIe[2]) && (0x50 == pbIe[3]) && + (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) + { + //Found it + if((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= pbIe[1]) + { + vos_mem_copy( pBssDescr->bssDescription.WscIeProbeRsp, + pbIe, pbIe[1] + 2); + pBssDescr->bssDescription.WscIeLen = pbIe[1] + 2; + } + break; + } + idx += pbIe[1] + 2; + pbIe += pbIe[1] + 2; + } + } + + + if(NULL != pMac->lim.gpLimMlmScanReq) + { + if((pMac->lim.gpLimMlmScanReq->numSsid)&& + ( limIsNullSsid((tSirMacSSid *)((tANI_U8 *) + &pBssDescr->bssDescription.ieFields + 1)))) + return eHAL_STATUS_FAILURE; + } + + // Delete this entry + if (ptemp == pMac->lim.gLimCachedLfrScanHashTable[index]) + pprev = pMac->lim.gLimCachedLfrScanHashTable[index] = ptemp->next; + else + pprev->next = ptemp->next; + + pMac->lim.gLimMlmLfrScanResultLength -= + ptemp->bssDescription.length + sizeof(tANI_U16); + + vos_mem_free(ptemp); + } + break; + } + } + + //for now, only rssi, we can add more if needed + if ((action == LIM_HASH_UPDATE) && dontUpdateAll && rssi && rssi_raw) + { + pBssDescr->bssDescription.rssi = rssi; + pBssDescr->bssDescription.rssi_raw = rssi_raw; + } + + // Add this BSS description at same index + if (pprev == pMac->lim.gLimCachedLfrScanHashTable[index]) + { + pBssDescr->next = pMac->lim.gLimCachedLfrScanHashTable[index]; + pMac->lim.gLimCachedLfrScanHashTable[index] = pBssDescr; + } + else + { + pBssDescr->next = pprev->next; + pprev->next = pBssDescr; + } + pMac->lim.gLimMlmLfrScanResultLength += + pBssDescr->bssDescription.length + sizeof(tANI_U16); + + PELOG2(limLog(pMac, LOG2, FL("Added new BSS description size %d TOT %d BSS id\n"), + pBssDescr->bssDescription.length, + pMac->lim.gLimMlmLfrScanResultLength); + limPrintMacAddr(pMac, pBssDescr->bssDescription.bssId, LOG2);) + + // + // TODO: IF applicable, do we need to send: + // Mesg - eWNI_SME_WM_STATUS_CHANGE_NTF + // Status change code - eSIR_SME_CB_LEGACY_BSS_FOUND_BY_AP + // + return eHAL_STATUS_SUCCESS; +} + + + +/** + * limDeleteLfrHashEntry() + * + *FUNCTION: + * This function is called upon to delete + * a BSS description from LFR scan result hash table. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * Yet to find the utility of the function + * + * @param pBssDescr - Pointer to BSS description to be + * deleted from the LFR scan result hash table. + * + * @return None + */ + +void limDeleteLfrHashEntry(tLimScanResultNode *pBssDescr) +{ +} /****** end limDeleteLfrHashEntry() ******/ + +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +/** + * limCopyScanResult() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() while + * sending SME_SCAN_RSP with scan result to HDD. + * + *LOGIC: + * This function traverses the scan list stored in scan hash table + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param pDest - Destination pointer + * + * @return None + */ + +void +limCopyScanResult(tpAniSirGlobal pMac, tANI_U8 *pDest) +{ + tLimScanResultNode *ptemp; + tANI_U16 i; + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + if ((ptemp = pMac->lim.gLimCachedScanHashTable[i]) != NULL) + { + while(ptemp) + { + /// Copy entire BSS description including length + vos_mem_copy( pDest, + (tANI_U8 *) &ptemp->bssDescription, + ptemp->bssDescription.length + 2); + pDest += ptemp->bssDescription.length + 2; + ptemp = ptemp->next; + } + } + } +} /****** end limCopyScanResult() ******/ + + + +/** + * limDeleteCachedScanResults() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_SCAN_REQ with fresh scan result flag set. + * + *LOGIC: + * This function traverses the scan list stored in scan hash table + * and deletes the entries if any + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limDeleteCachedScanResults(tpAniSirGlobal pMac) +{ + tLimScanResultNode *pNode, *pNextNode; + tANI_U16 i; + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + if ((pNode = pMac->lim.gLimCachedScanHashTable[i]) != NULL) + { + while (pNode) + { + pNextNode = pNode->next; + + // Delete the current node + vos_mem_free(pNode); + + pNode = pNextNode; + } + } + } + + pMac->lim.gLimSmeScanResultLength = 0; +} /****** end limDeleteCachedScanResults() ******/ + +/** + * limFlushp2pScanResults() + * + *FUNCTION: + * This function is called before scan to flush the + * the p2p scan entries from LIM + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limFlushp2pScanResults(tpAniSirGlobal pMac) +{ + tLimScanResultNode *pNode, *pNextNode, *pPrev, *pHead, *pTemp; + tANI_U16 i; + tANI_U8 *pSsidStr; + tSirMacSSid *pSsid; + + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + if ((pNode = pMac->lim.gLimCachedScanHashTable[i]) != NULL) + { + pPrev = pNode; + pHead = pNode; + while (pNode) + { + pSsid = (tSirMacSSid *)((tANI_U8 *)&pNode->bssDescription.ieFields + 1); + pSsidStr = pSsid->ssId; + if (vos_mem_compare(pSsidStr, "DIRECT-", 7)) + { + if (pNode == pHead) + { + pTemp = pNode; + pNode = pNode->next; + pMac->lim.gLimSmeScanResultLength -= + (pTemp->bssDescription.length + + sizeof(pTemp->bssDescription.length)); + pPrev = pNode; + pHead = pNode; + vos_mem_free(pTemp); + pMac->lim.gLimCachedScanHashTable[i]= pHead; + } + else + { + pNextNode = pNode->next; + pMac->lim.gLimSmeScanResultLength -= + (pNode->bssDescription.length + + sizeof(pNode->bssDescription.length)); + vos_mem_free(pNode); + pPrev->next = pNextNode; + pNode = pNextNode; + } + } + else + { + pPrev = pNode; + pNode = pNode->next; + } + } + } + } +} /****** end limFlushp2pScanResults() ******/ + +/** + * limReInitScanResults() + * + *FUNCTION: + * This function is called delete exisiting scan results + * and initialize the scan hash table + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limReInitScanResults(tpAniSirGlobal pMac) +{ + limLog(pMac, LOG1, FL("Re initialize scan hash table.")); + limDeleteCachedScanResults(pMac); + limInitHashTable(pMac); + + // !!LAC - need to clear out the global scan result length + // since the list was just purged from the hash table. + pMac->lim.gLimMlmScanResultLength = 0; + +} /****** end limReInitScanResults() ******/ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * limDeleteCachedLfrScanResults() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_SCAN_REQ with flush scan result flag set for LFR. + * + *LOGIC: + * This function traverses the scan list stored in lfr scan hash + * table and deletes the entries if any + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limDeleteCachedLfrScanResults(tpAniSirGlobal pMac) +{ + tLimScanResultNode *pNode, *pNextNode; + tANI_U16 i; + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + if ((pNode = pMac->lim.gLimCachedLfrScanHashTable[i]) != NULL) + { + while (pNode) + { + pNextNode = pNode->next; + + // Delete the current node + vos_mem_free(pNode); + + pNode = pNextNode; + } + } + } + + pMac->lim.gLimSmeLfrScanResultLength = 0; +} /****** end limDeleteCachedLfrScanResults() ******/ + + + +/** + * limReInitLfrScanResults() + * + *FUNCTION: + * This function is called delete exisiting scan results + * and initialize the lfr scan hash table + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limReInitLfrScanResults(tpAniSirGlobal pMac) +{ + limLog(pMac, LOG1, FL("Re initialize lfr scan hash table.")); + limDeleteCachedLfrScanResults(pMac); + limInitLfrHashTable(pMac); + + // !!LAC - need to clear out the global scan result length + // since the list was just purged from the hash table. + pMac->lim.gLimMlmLfrScanResultLength = 0; + +} /****** end limReInitLfrScanResults() ******/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.h new file mode 100644 index 000000000000..7f04c94a49fc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limScanResultUtils.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limScanResultUtils.h contains the utility definitions + * LIM uses for maintaining and accessing scan results on STA. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __LIM_SCAN_UTILS_H +#define __LIM_SCAN_UTILS_H + +#include "parserApi.h" +#include "limTypes.h" + +// Scan result hash related functions +tANI_U8 limScanHashFunction(tSirMacAddr); +void limInitHashTable(tpAniSirGlobal); +eHalStatus + limLookupNaddHashEntry(tpAniSirGlobal, tLimScanResultNode *, tANI_U8, tANI_U8); +void limDeleteHashEntry(tLimScanResultNode *); +void limFlushp2pScanResults(tpAniSirGlobal); +void limDeleteCachedScanResults(tpAniSirGlobal); +void limRestorePreScanState(tpAniSirGlobal); +void limCopyScanResult(tpAniSirGlobal, tANI_U8 *); +void limReInitScanResults(tpAniSirGlobal); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limInitLfrHashTable(tpAniSirGlobal); +eHalStatus + limLookupNaddLfrHashEntry(tpAniSirGlobal, tLimScanResultNode *, tANI_U8, tANI_U8); +void limDeleteLfrHashEntry(tLimScanResultNode *); +void limDeleteCachedLfrScanResults(tpAniSirGlobal); +void limReInitLfrScanResults(tpAniSirGlobal); +#endif +tANI_U32 limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal); +void limCheckAndAddBssDescription(tpAniSirGlobal, tpSirProbeRespBeacon, tANI_U8 *, tANI_BOOLEAN, tANI_U8); +#if defined WLAN_FEATURE_VOWIFI +eHalStatus limCollectBssDescription(tpAniSirGlobal, + tSirBssDescription *, + tpSirProbeRespBeacon, + tANI_U8 *, + tANI_U8); +#else +eHalStatus limCollectBssDescription(tpAniSirGlobal, + tSirBssDescription *, + tpSirProbeRespBeacon, + tANI_U8 *); +#endif + +#endif /* __LIM_SCAN_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c new file mode 100644 index 000000000000..ffbe5b1730d2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c @@ -0,0 +1,1350 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limUtils.cc contains the utility functions + * LIM uses. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "aniGlobal.h" +#include "wniApi.h" + +#include "sirCommon.h" +#include "wniCfgSta.h" +#include "cfgApi.h" + + +#include "utilsApi.h" +#include "limUtils.h" +#include "limSecurityUtils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" + + +#define LIM_SEED_LENGTH 16 +/* + * preauth node timeout value in interval of 10msec + */ +#define LIM_OPENAUTH_TIMEOUT 500 + +/** + * limIsAuthAlgoSupported() + * + *FUNCTION: + * This function is called in various places within LIM code + * to determine whether passed authentication algorithm is enabled + * or not + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param authType Indicates MAC based authentication type + * (eSIR_OPEN_SYSTEM or eSIR_SHARED_KEY) + * If Shared Key authentication to be used, + * 'Privacy Option Implemented' flag is also + * checked. + * + * @return true if passed authType is enabled else false + */ +tANI_U8 +limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession psessionEntry) +{ + tANI_U32 algoEnable, privacyOptImp; + + if (authType == eSIR_OPEN_SYSTEM) + { + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((psessionEntry->authType == eSIR_OPEN_SYSTEM) || + (psessionEntry->authType == eSIR_AUTO_SWITCH)) + return true; + else + return false; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE, + &algoEnable) != eSIR_SUCCESS) + { + /** + * Could not get AuthAlgo1 Enable value + * from CFG. Log error. + */ + limLog(pMac, LOGE, + FL("could not retrieve AuthAlgo1 Enable value")); + + return false; + } + else + return ( (algoEnable > 0 ? true : false) ); + } + else + { + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((psessionEntry->authType == eSIR_SHARED_KEY) || + (psessionEntry->authType == eSIR_AUTO_SWITCH)) + algoEnable = true; + else + algoEnable = false; + } else if (wlan_cfgGetInt(pMac, WNI_CFG_SHARED_KEY_AUTH_ENABLE, + &algoEnable) != eSIR_SUCCESS) { + /** + * Could not get AuthAlgo2 Enable value + * from CFG. Log error. + */ + limLog(pMac, LOGE, + FL("could not retrieve AuthAlgo2 Enable value")); + + return false; + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + privacyOptImp = psessionEntry->privacy; + } else if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &privacyOptImp) != eSIR_SUCCESS) { + /** + * Could not get PrivacyOptionImplemented value + * from CFG. Log error. + */ + limLog(pMac, LOGE, + FL("could not retrieve PrivacyOptImplemented value")); + + return false; + } + return (algoEnable && privacyOptImp); + } +} /****** end limIsAuthAlgoSupported() ******/ + + + +/** + * limInitPreAuthList + * + *FUNCTION: + * This function is called while starting a BSS at AP + * to initialize MAC authenticated STA list. This may also be called + * while joining/starting an IBSS if MAC authentication is allowed + * in IBSS mode. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limInitPreAuthList(tpAniSirGlobal pMac) +{ + pMac->lim.pLimPreAuthList = NULL; + +} /*** end limInitPreAuthList() ***/ + + + +/** + * limDeletePreAuthList + * + *FUNCTION: + * This function is called cleanup Pre-auth list either on + * AP or on STA when moving from one persona to other. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limDeletePreAuthList(tpAniSirGlobal pMac) +{ + struct tLimPreAuthNode *pCurrNode, *pTempNode; + + pCurrNode = pTempNode = pMac->lim.pLimPreAuthList; + while (pCurrNode != NULL) + { + pTempNode = pCurrNode->next; + + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthList "));) + limReleasePreAuthNode(pMac, pCurrNode); + + pCurrNode = pTempNode; + } + pMac->lim.pLimPreAuthList = NULL; +} /*** end limDeletePreAuthList() ***/ + + + +/** + * limSearchPreAuthList + * + *FUNCTION: + * This function is called when Authentication frame is received + * by AP (or at a STA in IBSS supporting MAC based authentication) + * to search if a STA is in the middle of MAC Authentication + * transaction sequence. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param macAddr - MAC address of the STA that sent + * Authentication frame. + * + * @return Pointer to pre-auth node if found, else NULL + */ + +struct tLimPreAuthNode * +limSearchPreAuthList(tpAniSirGlobal pMac, tSirMacAddr macAddr) +{ + struct tLimPreAuthNode *pTempNode = pMac->lim.pLimPreAuthList; + + while (pTempNode != NULL) + { + if (vos_mem_compare( (tANI_U8 *) macAddr, + (tANI_U8 *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr)) ) + break; + + pTempNode = pTempNode->next; + } + + return pTempNode; +} /*** end limSearchPreAuthList() ***/ + +/** + * limDeleteOpenAuthPreAuthNode() - delete any stale preauth nodes + * @pMac: Pointer to Global MAC structure + * + * This function is called to delete any stale preauth nodes on + * receiving authentication frame and existing preauth nodes + * reached the maximum allowed limit. + * + * Return: return true if any preauthnode deleted else false + */ +tANI_U8 +limDeleteOpenAuthPreAuthNode(tpAniSirGlobal pMac) +{ + struct tLimPreAuthNode *pPrevNode, *pTempNode, *pFoundNode; + tANI_U8 authNodeFreed = false; + + pTempNode = pPrevNode = pMac->lim.pLimPreAuthList; + + if (pTempNode == NULL) + return authNodeFreed; + + while (pTempNode != NULL) + { + if (pTempNode->mlmState == eLIM_MLM_AUTHENTICATED_STATE && + pTempNode->authType == eSIR_OPEN_SYSTEM && + (vos_timer_get_system_ticks() > + (LIM_OPENAUTH_TIMEOUT + pTempNode->timestamp) || + vos_timer_get_system_ticks() < pTempNode->timestamp)) + { + // Found node to be deleted + authNodeFreed = true; + pFoundNode = pTempNode; + if (pMac->lim.pLimPreAuthList == pTempNode) + { + pPrevNode = pMac->lim.pLimPreAuthList = pTempNode = + pFoundNode->next; + } + else + { + pPrevNode->next = pTempNode->next; + pTempNode = pPrevNode->next; + } + + limReleasePreAuthNode(pMac, pFoundNode); + } + else + { + pPrevNode = pTempNode; + pTempNode = pPrevNode->next; + } + } + + return authNodeFreed; +} + +/** + * limAddPreAuthNode + * + *FUNCTION: + * This function is called at AP while sending Authentication + * frame2. + * This may also be called on a STA in IBSS if MAC authentication is + * allowed in IBSS mode. + * + *LOGIC: + * Node is always added to the front of the list + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pAuthNode - Pointer to pre-auth node to be added to the list. + * + * @return None + */ + +void +limAddPreAuthNode(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNode) +{ + pMac->lim.gLimNumPreAuthContexts++; + + pAuthNode->next = pMac->lim.pLimPreAuthList; + + pMac->lim.pLimPreAuthList = pAuthNode; +} /*** end limAddPreAuthNode() ***/ + + +/** + * limReleasePreAuthNode + * + *FUNCTION: + * This function is called to realease the accquired + * pre auth node from list. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param pAuthNode - Pointer to Pre Auth node to be released + * @return None + */ + +void +limReleasePreAuthNode(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode) +{ + pAuthNode->fFree = 1; + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_PRE_AUTH_CLEANUP_TIMER)); + tx_timer_deactivate(&pAuthNode->timer); + pMac->lim.gLimNumPreAuthContexts--; +} /*** end limReleasePreAuthNode() ***/ + + +/** + * limDeletePreAuthNode + * + *FUNCTION: + * This function is called at AP when a pre-authenticated STA is + * Associated/Reassociated or when AuthFrame4 is received after + * Auth Response timeout. + * This may also be called on a STA in IBSS if MAC authentication and + * Association/Reassociation is allowed in IBSS mode. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param peerMacAddr - MAC address of the STA that need to be deleted + * from pre-auth node list. + * + * @return None + */ + +void +limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr) +{ + struct tLimPreAuthNode *pPrevNode, *pTempNode; + + pTempNode = pPrevNode = pMac->lim.pLimPreAuthList; + + if (pTempNode == NULL) + return; + + if (vos_mem_compare( (tANI_U8 *) macAddr, + (tANI_U8 *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr)) ) + { + // First node to be deleted + + pMac->lim.pLimPreAuthList = pTempNode->next; + + + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : first node to delete"));) + PELOG1(limLog(pMac, LOG1, FL("Release data entry: %x id %d peer "), + pTempNode, pTempNode->authNodeIdx); + limPrintMacAddr(pMac, macAddr, LOG1);) + limReleasePreAuthNode(pMac, pTempNode); + + return; + } + + pTempNode = pTempNode->next; + + while (pTempNode != NULL) + { + if (vos_mem_compare( (tANI_U8 *) macAddr, + (tANI_U8 *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr)) ) + { + // Found node to be deleted + + pPrevNode->next = pTempNode->next; + + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : subsequent node to delete")); + limLog(pMac, LOG1, FL("Release data entry: %x id %d peer "), + pTempNode, pTempNode->authNodeIdx); + limPrintMacAddr(pMac, macAddr, LOG1);) + limReleasePreAuthNode(pMac, pTempNode); + + return; + } + + pPrevNode = pTempNode; + pTempNode = pTempNode->next; + } + + // Should not be here + // Log error + limLog(pMac, LOGP, FL("peer not found in pre-auth list, addr= ")); + limPrintMacAddr(pMac, macAddr, LOGP); + +} /*** end limDeletePreAuthNode() ***/ + + + + + +/** + * limRestoreFromPreAuthState + * + *FUNCTION: + * This function is called on STA whenever an Authentication + * sequence is complete and state prior to auth need to be + * restored. + * + *LOGIC: + * MLM_AUTH_CNF is prepared and sent to SME state machine. + * In case of restoring from pre-auth: + * - Channel Id is programmed at LO/RF synthesizer + * - BSSID is programmed at RHP + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param resultCode - result of authentication attempt + * @return None + */ + +void +limRestoreFromAuthState(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 protStatusCode,tpPESession sessionEntry) +{ + tSirMacAddr currentBssId; + tLimMlmAuthCnf mlmAuthCnf; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_AUTH_COMP_EVENT, sessionEntry, + resultCode, protStatusCode); +#endif + + vos_mem_copy( (tANI_U8 *) &mlmAuthCnf.peerMacAddr, + (tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)); + mlmAuthCnf.authType = pMac->lim.gpLimMlmAuthReq->authType; + mlmAuthCnf.resultCode = resultCode; + mlmAuthCnf.protStatusCode = protStatusCode; + + /* 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 + * host have received the auth rsp and no longer auth + * retry is needed also cancel the auth rety timer + */ + pMac->auth_ack_status = LIM_AUTH_ACK_RCD_SUCCESS; + /* 'Change' timer for future activations */ + limDeactivateAndChangeTimer(pMac, eLIM_AUTH_RETRY_TIMER); + // 'Change' timer for future activations + limDeactivateAndChangeTimer(pMac, eLIM_AUTH_FAIL_TIMER); + + sirCopyMacAddr(currentBssId,sessionEntry->bssId); + + if (sessionEntry->limSmeState == eLIM_SME_WT_PRE_AUTH_STATE) + { + pMac->lim.gLimPreAuthChannelNumber = 0; + } + + limPostSmeMessage(pMac, + LIM_MLM_AUTH_CNF, + (tANI_U32 *) &mlmAuthCnf); +} /*** end limRestoreFromAuthState() ***/ + + + +/** + * limLookUpKeyMappings() + * + *FUNCTION: + * This function is called in limProcessAuthFrame() function + * to determine if there exists a Key Mapping key for a given + * MAC address. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param macAddr MAC address of the peer STA for which existence + * of Key Mapping key is to be determined + * + * @return pKeyMapEntry - Pointer to the keyMapEntry returned by CFG + */ + +tCfgWepKeyEntry * +limLookUpKeyMappings(tSirMacAddr macAddr) +{ + return NULL; +} /****** end limLookUpKeyMappings() ******/ + + + +/** + * limEncryptAuthFrame() + * + *FUNCTION: + * This function is called in limProcessAuthFrame() function + * to encrypt Authentication frame3 body. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param keyId key id to used + * @param pKey Pointer to the key to be used for encryption + * @param pPlainText Pointer to the body to be encrypted + * @param pEncrBody Pointer to the encrypted auth frame body + * @param keyLength 8 (WEP40) or 16 (WEP104) + * @return None + */ + +void +limEncryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 keyId, tANI_U8 *pKey, tANI_U8 *pPlainText, + tANI_U8 *pEncrBody, tANI_U32 keyLength) +{ + tANI_U8 seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH]; + + keyLength += 3; + + // Bytes 0-2 of seed is IV + // Read TSF timestamp into seed to get random IV - 1st 3 bytes + halGetTxTSFtimer(pMac, (tSirMacTimeStamp *) &seed); + + // Bytes 3-7 of seed is key + 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)); + + vos_mem_copy( pPlainText + sizeof(tSirMacAuthFrameBody), + 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); + + // Prepare IV + pEncrBody[0] = seed[0]; + pEncrBody[1] = seed[1]; + pEncrBody[2] = seed[2]; + pEncrBody[3] = keyId << 6; +} /****** end limEncryptAuthFrame() ******/ + + + +/** + * limComputeCrc32() + * + *FUNCTION: + * This function is called to compute CRC-32 on a given source. + * Used while encrypting/decrypting Authentication frame 3. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pDest Destination location for computed CRC + * @param pSrc Source location to be CRC computed + * @param len Length over which CRC to be computed + * @return None + */ + +void +limComputeCrc32(tANI_U8 *pDest, tANI_U8 * pSrc, tANI_U8 len) +{ + tANI_U32 crc; + int i; + + crc = 0; + crc = ~crc; + + while(len-- > 0) + crc = limCrcUpdate(crc, *pSrc++); + + crc = ~crc; + + for (i=0; i < SIR_MAC_WEP_IV_LENGTH; i++) + { + pDest[i] = (tANI_U8)crc; + crc >>= 8; + } +} /****** end limComputeCrc32() ******/ + + + +/** + * limRC4() + * + *FUNCTION: + * This function is called to run RC4 algorithm. Called while + * encrypting/decrypting Authentication frame 3. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pDest Destination location for encrypted text + * @param pSrc Source location to be encrypted + * @param seed Contains seed (IV + key) for PRNG + * @param keyLength 8 (WEP40) or 16 (WEP104) + * @param frameLen Length of the frame + * + * @return None + */ + +void +limRC4(tANI_U8 *pDest, tANI_U8 *pSrc, tANI_U8 *seed, tANI_U32 keyLength, tANI_U16 frameLen) +{ + typedef struct + { + tANI_U8 i, j; + tANI_U8 sbox[256]; + } tRC4Context; + + tRC4Context ctx; + + { + tANI_U16 i, j, k; + + // + // Initialize sbox using seed + // + + ctx.i = ctx.j = 0; + for (i=0; i<256; i++) + ctx.sbox[i] = (tANI_U8)i; + + j = 0; + k = 0; + for (i=0; i<256; i++) + { + tANI_U8 temp; + if ( k < LIM_SEED_LENGTH ) + j = (tANI_U8)(j + ctx.sbox[i] + seed[k]); + temp = ctx.sbox[i]; + ctx.sbox[i] = ctx.sbox[j]; + ctx.sbox[j] = temp; + + if (++k >= keyLength) + k = 0; + } + } + + { + tANI_U8 i = ctx.i; + tANI_U8 j = ctx.j; + tANI_U8 len = (tANI_U8) frameLen; + + while (len-- > 0) + { + tANI_U8 temp1, temp2; + + i = (tANI_U8)(i+1); + temp1 = ctx.sbox[i]; + j = (tANI_U8)(j + temp1); + + ctx.sbox[i] = temp2 = ctx.sbox[j]; + ctx.sbox[j] = temp1; + + temp1 = (tANI_U8)(temp1 + temp2); + temp1 = ctx.sbox[temp1]; + temp2 = (tANI_U8)(pSrc ? *pSrc++ : 0); + + *pDest++ = (tANI_U8)(temp1 ^ temp2); + } + + ctx.i = i; + ctx.j = j; + } +} /****** end limRC4() ******/ + + + +/** + * limDecryptAuthFrame() + * + *FUNCTION: + * This function is called in limProcessAuthFrame() function + * to decrypt received Authentication frame3 body. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pKey Pointer to the key to be used for decryption + * @param pEncrBody Pointer to the body to be decrypted + * @param pPlainBody Pointer to the decrypted body + * @param keyLength 8 (WEP40) or 16 (WEP104) + * + * @return Decrypt result - eSIR_SUCCESS for success and + * LIM_DECRYPT_ICV_FAIL for ICV mismatch. + * If decryption is a success, pBody will + * have decrypted auth frame body. + */ + +tANI_U8 +limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody, + tANI_U8 *pPlainBody, tANI_U32 keyLength, tANI_U16 frameLen) +{ + tANI_U8 seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH]; + int i; + keyLength += 3; + + + // Bytes 0-2 of seed is received IV + vos_mem_copy((tANI_U8 *) seed, pEncrBody, SIR_MAC_WEP_IV_LENGTH - 1); + + // Bytes 3-7 of seed is key + vos_mem_copy((tANI_U8 *) &seed[3], pKey, keyLength - 3); + + // Run RC4 on encrypted text with the seed + limRC4(pPlainBody, + pEncrBody + SIR_MAC_WEP_IV_LENGTH, + seed, + keyLength, + frameLen); + + PELOG4(limLog(pMac, LOG4, FL("plainbody is ")); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen);) + + // Compute CRC-32 and place them in last 4 bytes of encrypted body + limComputeCrc32(icv, + (tANI_U8 *) pPlainBody, + (tANI_U8) (frameLen - SIR_MAC_WEP_ICV_LENGTH)); + + // Compare RX_ICV with computed ICV + for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) + { + PELOG4(limLog(pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]"), + i, icv[i], i, pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);) + if (icv[i] != pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]) + return LIM_DECRYPT_ICV_FAIL; + } + + return eSIR_SUCCESS; +} /****** end limDecryptAuthFrame() ******/ + +/** + * limPostSmeSetKeysCnf + * + * A utility API to send MLM_SETKEYS_CNF to SME + */ +void limPostSmeSetKeysCnf( tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + tLimMlmSetKeysCnf *mlmSetKeysCnf) +{ + // Prepare and Send LIM_MLM_SETKEYS_CNF + vos_mem_copy( (tANI_U8 *) &mlmSetKeysCnf->peerMacAddr, + (tANI_U8 *) pMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + + vos_mem_copy( (tANI_U8 *) &mlmSetKeysCnf->peerMacAddr, + (tANI_U8 *) pMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + + + /// Free up buffer allocated for mlmSetKeysReq + vos_mem_free( pMlmSetKeysReq ); + pMac->lim.gpLimMlmSetKeysReq = NULL; + + limPostSmeMessage( pMac, + LIM_MLM_SETKEYS_CNF, + (tANI_U32 *) mlmSetKeysCnf ); +} + +/** + * limPostSmeRemoveKeysCnf + * + * A utility API to send MLM_REMOVEKEY_CNF to SME + */ +void limPostSmeRemoveKeyCnf( tpAniSirGlobal pMac, + tpPESession psessionEntry, + tLimMlmRemoveKeyReq *pMlmRemoveKeyReq, + tLimMlmRemoveKeyCnf *mlmRemoveKeyCnf) +{ + // Prepare and Send LIM_MLM_REMOVEKEYS_CNF + vos_mem_copy( (tANI_U8 *) &mlmRemoveKeyCnf->peerMacAddr, + (tANI_U8 *) pMlmRemoveKeyReq->peerMacAddr, + sizeof(tSirMacAddr)); + + /// Free up buffer allocated for mlmRemoveKeysReq + vos_mem_free( pMlmRemoveKeyReq ); + pMac->lim.gpLimMlmRemoveKeyReq = NULL; + + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; //Restore the state. + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); + + limPostSmeMessage( pMac, + LIM_MLM_REMOVEKEY_CNF, + (tANI_U32 *) mlmRemoveKeyCnf ); +} + +/** + * limSendSetBssKeyReq() + * + *FUNCTION: + * This function is called from limProcessMlmSetKeysReq(), + * when PE is trying to setup the Group Keys related + * to a specified encryption type + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer + * @return none + */ +void limSendSetBssKeyReq( tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + tpPESession psessionEntry) +{ +tSirMsgQ msgQ; +tpSetBssKeyParams pSetBssKeyParams = NULL; +tLimMlmSetKeysCnf mlmSetKeysCnf; +tSirRetStatus retCode; +tANI_U32 val = 0; + + if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) + { + limLog( pMac, LOG1, + FL( "numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS" ), pMlmSetKeysReq->numKeys); + + // Respond to SME with error code + mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + // Package WDA_SET_BSSKEY_REQ message parameters + + pSetBssKeyParams = vos_mem_malloc(sizeof( tSetBssKeyParams )); + if ( NULL == pSetBssKeyParams ) + { + limLog( pMac, LOGE, + FL( "Unable to allocate memory during SET_BSSKEY" )); + + // Respond to SME with error code + mlmSetKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + else + vos_mem_set( (void *) pSetBssKeyParams, + sizeof( tSetBssKeyParams ), 0); + + // Update the WDA_SET_BSSKEY_REQ parameters + pSetBssKeyParams->bssIdx = psessionEntry->bssIdx; + pSetBssKeyParams->encType = pMlmSetKeysReq->edType; + + + if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) + { + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); + } + + pSetBssKeyParams->singleTidRc = (tANI_U8)val; + + /* Update PE session Id*/ + pSetBssKeyParams->sessionId = psessionEntry ->peSessionId; + + pSetBssKeyParams->smesessionId = pMlmSetKeysReq->smesessionId; + + if(pMlmSetKeysReq->key[0].keyId && + ((pMlmSetKeysReq->edType == eSIR_ED_WEP40) || + (pMlmSetKeysReq->edType == eSIR_ED_WEP104)) + ) + { + /* IF the key id is non-zero and encryption type is WEP, Send all the 4 + * keys to HAL with filling the key at right index in pSetBssKeyParams->key. */ + pSetBssKeyParams->numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + vos_mem_copy( (tANI_U8 *) &pSetBssKeyParams->key[pMlmSetKeysReq->key[0].keyId], + (tANI_U8 *) &pMlmSetKeysReq->key[0], sizeof(pMlmSetKeysReq->key[0])); + + } + else + { + pSetBssKeyParams->numKeys = pMlmSetKeysReq->numKeys; + vos_mem_copy( (tANI_U8 *) &pSetBssKeyParams->key, + (tANI_U8 *) &pMlmSetKeysReq->key, + sizeof( tSirKeys ) * pMlmSetKeysReq->numKeys ); + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + msgQ.type = WDA_SET_BSSKEY_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pSetBssKeyParams; + msgQ.bodyval = 0; + + limLog( pMac, LOGW, + FL( "Sending WDA_SET_BSSKEY_REQ..." )); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + limLog( pMac, LOGE, + FL("Posting SET_BSSKEY to HAL failed, reason=%X"), + retCode ); + + // Respond to SME with LIM_MLM_SETKEYS_CNF + mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + else + return; // Continue after WDA_SET_BSSKEY_RSP... + +end: + limPostSmeSetKeysCnf( pMac, + pMlmSetKeysReq, + &mlmSetKeysCnf ); + +} + +/** + * @function : limSendSetStaKeyReq() + * + * @brief : This function is called from limProcessMlmSetKeysReq(), + * when PE is trying to setup the Unicast Keys related + * to a specified STA with specified encryption type + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer + * @param staIdx STA index for which the keys are being set + * @param defWEPIdx The default WEP key index [0..3] + * @return none + */ +void limSendSetStaKeyReq( tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + tANI_U16 staIdx, + tANI_U8 defWEPIdx, + tpPESession sessionEntry, + tANI_BOOLEAN sendRsp) +{ + tSirMsgQ msgQ; + tpSetStaKeyParams pSetStaKeyParams = NULL; + tLimMlmSetKeysCnf mlmSetKeysCnf; + tSirRetStatus retCode; + tANI_U32 val = 0; + + // Package WDA_SET_STAKEY_REQ message parameters + pSetStaKeyParams = vos_mem_malloc(sizeof( tSetStaKeyParams )); + if ( NULL == pSetStaKeyParams ) + { + limLog( pMac, LOGP, FL( "Unable to allocate memory during SET_BSSKEY" )); + return; + } + else + vos_mem_set( (void *) pSetStaKeyParams, sizeof( tSetStaKeyParams ), 0); + + // Update the WDA_SET_STAKEY_REQ parameters + pSetStaKeyParams->staIdx = staIdx; + pSetStaKeyParams->encType = pMlmSetKeysReq->edType; + + + if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) + { + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); + } + + pSetStaKeyParams->singleTidRc = (tANI_U8)val; + + /* Update PE session ID*/ + pSetStaKeyParams->sessionId = sessionEntry->peSessionId; + + /** + * For WEP - defWEPIdx indicates the default WEP + * Key to be used for TX + * For all others, there's just one key that can + * be used and hence it is assumed that + * defWEPIdx = 0 (from the caller) + */ + + pSetStaKeyParams->defWEPIdx = defWEPIdx; + + pSetStaKeyParams->smesessionId = pMlmSetKeysReq->smesessionId; + vos_mem_copy(pSetStaKeyParams->peerMacAddr, + pMlmSetKeysReq->peerMacAddr, sizeof(tSirMacAddr)); + + if(sendRsp == eANI_BOOLEAN_TRUE) + { + /** Store the Previous MlmState*/ + sessionEntry->limPrevMlmState = sessionEntry->limMlmState; + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + } + + if (LIM_IS_IBSS_ROLE(sessionEntry) && !pMlmSetKeysReq->key[0].unicast) { + if (sendRsp == eANI_BOOLEAN_TRUE) + sessionEntry->limMlmState = eLIM_MLM_WT_SET_STA_BCASTKEY_STATE; + msgQ.type = WDA_SET_STA_BCASTKEY_REQ; + } else { + if (sendRsp == eANI_BOOLEAN_TRUE) + sessionEntry->limMlmState = eLIM_MLM_WT_SET_STA_KEY_STATE; + msgQ.type = WDA_SET_STAKEY_REQ; + } + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, sessionEntry->limMlmState)); + + /** + * In the Case of WEP_DYNAMIC, ED_TKIP and ED_CCMP + * the Key[0] contains the KEY, so just copy that alone, + * for the case of WEP_STATIC the hal gets the key from cfg + */ + switch( pMlmSetKeysReq->edType ) { + case eSIR_ED_WEP40: + case eSIR_ED_WEP104: + // FIXME! Is this OK? + if( 0 == pMlmSetKeysReq->numKeys ) { + tANI_U32 i; + + for(i=0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS ;i++) + { + vos_mem_copy( (tANI_U8 *) &pSetStaKeyParams->key[i], + (tANI_U8 *) &pMlmSetKeysReq->key[i], sizeof( tSirKeys )); + } + pSetStaKeyParams->wepType = eSIR_WEP_STATIC; + sessionEntry->limMlmState = eLIM_MLM_WT_SET_STA_KEY_STATE; + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, sessionEntry->limMlmState)); + }else { + /*This case the keys are coming from upper layer so need to fill the + * key at the default wep key index and send to the HAL */ + if (defWEPIdx < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) + { + vos_mem_copy((tANI_U8 *) &pSetStaKeyParams->key[defWEPIdx], + (tANI_U8 *) &pMlmSetKeysReq->key[0], sizeof( pMlmSetKeysReq->key[0] )); + pMlmSetKeysReq->numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + } + else + { + limLog( pMac, LOGE, FL( "Wrong Key Index %d" ), defWEPIdx); + vos_mem_free (pSetStaKeyParams); + return; + } + } + break; + case eSIR_ED_TKIP: + case eSIR_ED_CCMP: +#ifdef FEATURE_WLAN_WAPI + case eSIR_ED_WPI: +#endif + { + vos_mem_copy( (tANI_U8 *) &pSetStaKeyParams->key, + (tANI_U8 *) &pMlmSetKeysReq->key[0], sizeof( tSirKeys )); + } + break; + default: + break; + } + + pSetStaKeyParams->sendRsp = sendRsp; + + msgQ.reserved = 0; + msgQ.bodyptr = pSetStaKeyParams; + msgQ.bodyval = 0; + + limLog( pMac, LOG1, FL( "Sending WDA_SET_STAKEY_REQ..." )); + MTRACE(macTraceMsgTx(pMac, sessionEntry->peSessionId, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { + limLog( pMac, LOGE, FL("Posting SET_STAKEY to HAL failed, reason=%X"), retCode ); + // Respond to SME with LIM_MLM_SETKEYS_CNF + mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + }else + return; // Continue after WDA_SET_STAKEY_RSP... + + if(sendRsp == eANI_BOOLEAN_TRUE) + limPostSmeSetKeysCnf( pMac, pMlmSetKeysReq, &mlmSetKeysCnf ); +} + +/** + * limSendRemoveBssKeyReq() + * + *FUNCTION: + * This function is called from limProcessMlmRemoveReq(), + * when PE is trying to Remove a Group Key related + * to a specified encryption type + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pMlmRemoveKeyReq Pointer to MLM_REMOVEKEY_REQ buffer + * @return none + */ +void limSendRemoveBssKeyReq( tpAniSirGlobal pMac, + tLimMlmRemoveKeyReq *pMlmRemoveKeyReq, + tpPESession psessionEntry) +{ +tSirMsgQ msgQ; +tpRemoveBssKeyParams pRemoveBssKeyParams = NULL; +tLimMlmRemoveKeyCnf mlmRemoveKeysCnf; +tSirRetStatus retCode; + + // Package WDA_REMOVE_BSSKEY_REQ message parameters + pRemoveBssKeyParams = vos_mem_malloc(sizeof( tRemoveBssKeyParams )); + if ( NULL == pRemoveBssKeyParams ) + { + limLog( pMac, LOGE, + FL( "Unable to allocate memory during REMOVE_BSSKEY" )); + + // Respond to SME with error code + mlmRemoveKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + else + vos_mem_set( (void *) pRemoveBssKeyParams, + sizeof( tRemoveBssKeyParams ), 0); + + // Update the WDA_REMOVE_BSSKEY_REQ parameters + pRemoveBssKeyParams->bssIdx = psessionEntry->bssIdx; + pRemoveBssKeyParams->encType = pMlmRemoveKeyReq->edType; + pRemoveBssKeyParams->keyId = pMlmRemoveKeyReq->keyId; + pRemoveBssKeyParams->wepType = pMlmRemoveKeyReq->wepType; + + /* Update PE session Id*/ + + pRemoveBssKeyParams->sessionId = psessionEntry->peSessionId; + + msgQ.type = WDA_REMOVE_BSSKEY_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pRemoveBssKeyParams; + msgQ.bodyval = 0; + + limLog( pMac, LOGW, + FL( "Sending WDA_REMOVE_BSSKEY_REQ..." )); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + limLog( pMac, LOGE, + FL("Posting REMOVE_BSSKEY to HAL failed, reason=%X"), + retCode ); + + // Respond to SME with LIM_MLM_REMOVEKEYS_CNF + mlmRemoveKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + else + return; + +end: + limPostSmeRemoveKeyCnf( pMac, + psessionEntry, + pMlmRemoveKeyReq, + &mlmRemoveKeysCnf ); + +} + +/** + * limSendRemoveStaKeyReq() + * + *FUNCTION: + * This function is called from limProcessMlmRemoveKeysReq(), + * when PE is trying to setup the Unicast Keys related + * to a specified STA with specified encryption type + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pMlmRemoveKeysReq Pointer to MLM_REMOVEKEYS_REQ buffer + * @param staIdx STA index for which the keys are being set + * @return none + */ +void limSendRemoveStaKeyReq( tpAniSirGlobal pMac, + tLimMlmRemoveKeyReq *pMlmRemoveKeyReq, + tANI_U16 staIdx, + tpPESession psessionEntry) +{ +tSirMsgQ msgQ; +tpRemoveStaKeyParams pRemoveStaKeyParams = NULL; +tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; +tSirRetStatus retCode; + + pRemoveStaKeyParams = vos_mem_malloc(sizeof( tRemoveStaKeyParams )); + if ( NULL == pRemoveStaKeyParams ) + { + limLog( pMac, LOGE, + FL( "Unable to allocate memory during REMOVE_STAKEY" )); + + // Respond to SME with error code + mlmRemoveKeyCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + else + vos_mem_set( (void *) pRemoveStaKeyParams, + sizeof( tRemoveStaKeyParams ), 0); + + if( (pMlmRemoveKeyReq->edType == eSIR_ED_WEP104 || pMlmRemoveKeyReq->edType == eSIR_ED_WEP40) && + pMlmRemoveKeyReq->wepType == eSIR_WEP_STATIC ) + { + PELOGE(limLog(pMac, LOGE, FL("Request to remove static WEP keys through station interface\n Should use BSS interface"));) + mlmRemoveKeyCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + // Update the WDA_REMOVEKEY_REQ parameters + pRemoveStaKeyParams->staIdx = staIdx; + pRemoveStaKeyParams->encType = pMlmRemoveKeyReq->edType; + pRemoveStaKeyParams->keyId = pMlmRemoveKeyReq->keyId; + pRemoveStaKeyParams->unicast = pMlmRemoveKeyReq->unicast; + + /* Update PE session ID*/ + pRemoveStaKeyParams->sessionId = psessionEntry->peSessionId; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.type = WDA_REMOVE_STAKEY_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pRemoveStaKeyParams; + msgQ.bodyval = 0; + + limLog( pMac, LOGW, + FL( "Sending WDA_REMOVE_STAKEY_REQ..." )); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if (eSIR_SUCCESS != retCode) + { + limLog( pMac, LOGE, + FL("Posting REMOVE_STAKEY to HAL failed, reason=%X"), + retCode ); + vos_mem_free(pRemoveStaKeyParams); + pRemoveStaKeyParams = NULL; + + // Respond to SME with LIM_MLM_REMOVEKEY_CNF + mlmRemoveKeyCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + else + return; + +end: + if (pRemoveStaKeyParams) + { + vos_mem_free(pRemoveStaKeyParams); + } + limPostSmeRemoveKeyCnf( pMac, + psessionEntry, + pMlmRemoveKeyReq, + &mlmRemoveKeyCnf ); + +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h new file mode 100644 index 000000000000..4ede5005b556 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limSecurityUtils.h contains the utility definitions + * related to WEP encryption/decryption etc. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __LIM_SECURITY_UTILS_H +#define __LIM_SECURITY_UTILS_H +#include "sirMacProtDef.h" //for tSirMacAuthFrameBody + +#define LIM_ENCR_AUTH_BODY_LEN (sizeof(tSirMacAuthFrameBody) + \ + SIR_MAC_WEP_IV_LENGTH + \ + SIR_MAC_WEP_ICV_LENGTH) +struct tLimPreAuthNode; + +tANI_U8 limIsAuthAlgoSupported(tpAniSirGlobal, tAniAuthType, tpPESession); + +// MAC based authentication related functions +void limInitPreAuthList(tpAniSirGlobal); +void limDeletePreAuthList(tpAniSirGlobal); +struct tLimPreAuthNode *limSearchPreAuthList(tpAniSirGlobal, tSirMacAddr); +void limAddPreAuthNode(tpAniSirGlobal, struct tLimPreAuthNode *); +void limDeletePreAuthNode(tpAniSirGlobal, tSirMacAddr); +void limReleasePreAuthNode(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode); +void limRestoreFromAuthState(tpAniSirGlobal, + tSirResultCodes, tANI_U16,tpPESession); +tANI_U8 limDeleteOpenAuthPreAuthNode(tpAniSirGlobal pMac); + +// Encryption/Decryption related functions +tCfgWepKeyEntry *limLookUpKeyMappings(tSirMacAddr); +void limComputeCrc32(tANI_U8 *, tANI_U8 *, tANI_U8); +void limRC4(tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32, tANI_U16); +void limEncryptAuthFrame(tpAniSirGlobal, tANI_U8, tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32); +tANI_U8 limDecryptAuthFrame(tpAniSirGlobal, tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32, tANI_U16); + +void limSendSetBssKeyReq( tpAniSirGlobal, tLimMlmSetKeysReq *,tpPESession ); +void limSendSetStaKeyReq( tpAniSirGlobal, tLimMlmSetKeysReq *, tANI_U16, tANI_U8,tpPESession, tANI_BOOLEAN sendRsp); +void limPostSmeSetKeysCnf( tpAniSirGlobal, tLimMlmSetKeysReq *, tLimMlmSetKeysCnf * ); + +void limSendRemoveBssKeyReq(tpAniSirGlobal pMac, tLimMlmRemoveKeyReq * pMlmRemoveKeyReq,tpPESession); +void limSendRemoveStaKeyReq(tpAniSirGlobal pMac, tLimMlmRemoveKeyReq * pMlmRemoveKeyReq, tANI_U16 staIdx,tpPESession); +void limPostSmeRemoveKeyCnf(tpAniSirGlobal pMac, tpPESession psessionEntry, tLimMlmRemoveKeyReq * pMlmRemoveKeyReq, tLimMlmRemoveKeyCnf * mlmRemoveKeyCnf); + +#define PTAPS 0xedb88320 + +static inline tANI_U32 +limCrcUpdate(tANI_U32 crc, tANI_U8 x) +{ + + // Update CRC computation for 8 bits contained in x + // + tANI_U32 z; + tANI_U32 fb; + int i; + + z = crc^x; + for (i=0; i<8; i++) { + fb = z & 1; + z >>= 1; + if (fb) z ^= PTAPS; + } + return z; +} + +#endif /* __LIM_SECURITY_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c new file mode 100644 index 000000000000..dca9f844d348 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -0,0 +1,6319 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * \file limSendManagementFrames.c + * + * \brief Code for preparing and sending 802.11 Management frames + * + * + */ + +#include "sirApi.h" +#include "aniGlobal.h" +#include "sirMacProtDef.h" +#include "cfgApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limSecurityUtils.h" +#include "limPropExtsUtils.h" +#include "dot11f.h" +#include "limStaHashApi.h" +#include "schApi.h" +#include "limSendMessages.h" +#include "limAssocUtils.h" +#include "limFT.h" +#ifdef WLAN_FEATURE_11W +#include "wniCfgAp.h" +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "vos_utils.h" +#include "sme_Trace.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif + +#include "wlan_qct_wda.h" + + +//////////////////////////////////////////////////////////////////////// +/** + * + * \brief This function is called to add the sequence number to the + * management frames + * + * \param pMac Pointer to Global MAC structure + * + * \param pMacHdr Pointer to MAC management header + * + * The pMacHdr argument points to the MAC management header. The + * sequence number stored in the pMac structure will be incremented + * and updated to the MAC management header. The start sequence + * number is WLAN_HOST_SEQ_NUM_MIN and the end value is + * WLAN_HOST_SEQ_NUM_MAX. After reaching the MAX value, the sequence + * number will roll over. + * + */ +void +limAddMgmtSeqNum (tpAniSirGlobal pMac, tpSirMacMgmtHdr pMacHdr) +{ + if (pMac->mgmtSeqNum >= WLAN_HOST_SEQ_NUM_MAX) { + pMac->mgmtSeqNum = WLAN_HOST_SEQ_NUM_MIN-1; + } + + pMac->mgmtSeqNum++; + + pMacHdr->seqControl.seqNumLo = (pMac->mgmtSeqNum & LOW_SEQ_NUM_MASK); + pMacHdr->seqControl.seqNumHi = + ((pMac->mgmtSeqNum & HIGH_SEQ_NUM_MASK) >> HIGH_SEQ_NUM_OFFSET); +} + +/** + * + * \brief This function is called before sending a p2p action frame + * inorder to add sequence numbers to action packets + * + * \param pMac Pointer to Global MAC structure + * + * \param pBD Pointer to the frame buffer that needs to be populate + * + * The pMacHdr argument points to the MAC management header. The + * sequence number stored in the pMac structure will be incremented + * and updated to the MAC management header. The start sequence + * number is WLAN_HOST_SEQ_NUM_MIN and the end value is + * WLAN_HOST_SEQ_NUM_MAX. After reaching the MAX value, the sequence + * number will roll over. + * + */ +void +limPopulateP2pMacHeader(tpAniSirGlobal pMac, tANI_U8* pBD) +{ + tpSirMacMgmtHdr pMacHdr; + + /// Prepare MAC management header + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + /* Prepare sequence number */ + limAddMgmtSeqNum(pMac, pMacHdr); + limLog(pMac, LOG1,"seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d", + pMacHdr->seqControl.seqNumLo, + pMacHdr->seqControl.seqNumHi, + pMac->mgmtSeqNum); +} + +/** + * + * \brief This function is called by various LIM modules to prepare the + * 802.11 frame MAC header + * + * + * \param pMac Pointer to Global MAC structure + * + * \param pBD Pointer to the frame buffer that needs to be populate + * + * \param type Type of the frame + * + * \param subType Subtype of the frame + * + * \return eHalStatus + * + * + * The pFrameBuf argument points to the beginning of the frame buffer to + * which - a) The 802.11 MAC header is set b) Following this MAC header + * will be the MGMT frame payload The payload itself is populated by the + * caller API + * + * + */ + +tSirRetStatus limPopulateMacHeader( tpAniSirGlobal pMac, + tANI_U8* pBD, + tANI_U8 type, + tANI_U8 subType, + tSirMacAddr peerAddr, tSirMacAddr selfMacAddr) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tpSirMacMgmtHdr pMacHdr; + + /// Prepare MAC management header + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + // Prepare FC + pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + pMacHdr->fc.type = type; + pMacHdr->fc.subType = subType; + + // Prepare Address 1 + vos_mem_copy( (tANI_U8 *) pMacHdr->da, + (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + + // Prepare Address 2 + sirCopyMacAddr(pMacHdr->sa,selfMacAddr); + + // Prepare Address 3 + vos_mem_copy( (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + + /* Prepare sequence number */ + limAddMgmtSeqNum(pMac, pMacHdr); + limLog(pMac, LOG1,"seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d", + pMacHdr->seqControl.seqNumLo, + pMacHdr->seqControl.seqNumHi, + pMac->mgmtSeqNum); + + return statusCode; +} /*** end limPopulateMacHeader() ***/ + +/** + * \brief limSendProbeReqMgmtFrame + * + * + * \param pMac Pointer to Global MAC structure + * + * \param pSsid SSID to be sent in Probe Request frame + * + * \param bssid BSSID to be sent in Probe Request frame + * + * \param nProbeDelay probe delay to be used before sending Probe Request + * frame + * + * \param nChannelNum Channel # on which the Probe Request is going out + * + * \param nAdditionalIELen if non-zero, include pAdditionalIE in the Probe Request frame + * + * \param pAdditionalIE if nAdditionalIELen is non zero, include this field in the Probe Request frame + * + * This function is called by various LIM modules to send Probe Request frame + * during active scan/learn phase. + * Probe request is sent out in the following scenarios: + * --heartbeat failure: session needed + * --join req: session needed + * --foreground scan: no session + * --background scan: no session + * --schBeaconProcessing: to get EDCA parameters: session needed + * + * + */ +tSirRetStatus +limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, + tSirMacSSid *pSsid, + tSirMacAddr bssid, + tANI_U8 nChannelNum, + tSirMacAddr SelfMacAddr, + tANI_U32 dot11mode, + tANI_U32 nAdditionalIELen, + tANI_U8 *pAdditionalIE) +{ + tDot11fProbeRequest pr; + tANI_U32 nStatus, nBytes, nPayload; + tSirRetStatus nSirStatus, extcap_status; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; + tpPESession psessionEntry; + tANI_U8 sessionId; + tANI_U8 *p2pIe = NULL; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + bool isVHTEnabled = false; + uint16_t addn_ielen = nAdditionalIELen; + + + + + /* The probe req should not send 11ac capabilieties if band is 2.4GHz, + * unless enableVhtFor24GHz is enabled in INI. So if enableVhtFor24GHz + * is false and dot11mode is 11ac set it to 11n. + */ + if ( nChannelNum <= SIR_11B_CHANNEL_END && + ( FALSE == pMac->roam.configParam.enableVhtFor24GHz ) && + ( WNI_CFG_DOT11_MODE_11AC == dot11mode || + WNI_CFG_DOT11_MODE_11AC_ONLY == dot11mode ) ) + dot11mode = WNI_CFG_DOT11_MODE_11N; + /* + * session context may or may not be present, when probe request needs to be sent out. + * following cases exist: + * --heartbeat failure: session needed + * --join req: session needed + * --foreground scan: no session + * --background scan: no session + * --schBeaconProcessing: to get EDCA parameters: session needed + * If session context does not exist, some IEs will be populated from CFGs, + * e.g. Supported and Extended rate set IEs + */ + psessionEntry = peFindSessionByBssid(pMac,bssid,&sessionId); + + if (psessionEntry != NULL ) + smeSessionId = psessionEntry->smeSessionId; + + // The scheme here is to fill out a 'tDot11fProbeRequest' structure + // and then hand it off to 'dot11fPackProbeRequest' (for + // serialization). We start by zero-initializing the structure: + vos_mem_set(( tANI_U8* )&pr, sizeof( pr ), 0); + + // & delegating to assorted helpers: + PopulateDot11fSSID( pMac, pSsid, &pr.SSID ); + + if(addn_ielen && pAdditionalIE) { + p2pIe = limGetP2pIEPtr(pMac, pAdditionalIE, addn_ielen); + } + /* Don't include 11b rate only when device is doing P2P Search */ + if( ( WNI_CFG_DOT11_MODE_11B != dot11mode ) && + ( p2pIe != NULL ) && + /* Don't include 11b rate if it is a P2P serach or probe request is sent by P2P Client */ + ( ( ( pMac->lim.gpLimMlmScanReq != NULL ) && + pMac->lim.gpLimMlmScanReq->p2pSearch ) || + ( ( psessionEntry != NULL ) && + ( VOS_P2P_CLIENT_MODE == psessionEntry->pePersona ) ) + ) + ) + { + /* In the below API pass channel number > 14, do that it fills only + * 11a rates in supported rates */ + PopulateDot11fSuppRates( pMac, 15, &pr.SuppRates,psessionEntry); + } + else + { + PopulateDot11fSuppRates( pMac, nChannelNum, + &pr.SuppRates,psessionEntry); + + if ( WNI_CFG_DOT11_MODE_11B != dot11mode ) + { + PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); + } + } + +#if defined WLAN_FEATURE_VOWIFI + //Table 7-14 in IEEE Std. 802.11k-2008 says + //DS params "can" be present in RRM is disabled and "is" present if + //RRM is enabled. It should be ok even if we add it into probe req when + //RRM is not enabled. + PopulateDot11fDSParams( pMac, &pr.DSParams, nChannelNum, psessionEntry ); + //Call RRM module to get the tx power for management used. + { + tANI_U8 txPower = (tANI_U8) rrmGetMgmtTxPower( pMac, psessionEntry ); + PopulateDot11fWFATPC( pMac, &pr.WFATPC, txPower, 0 ); + } +#endif + + if (psessionEntry != NULL ) { + psessionEntry->htCapability = IS_DOT11_MODE_HT(dot11mode); + //Include HT Capability IE + if (psessionEntry->htCapability) + { + PopulateDot11fHTCaps( pMac, psessionEntry, &pr.HTCaps ); + } + } else { //psessionEntry == NULL + if (IS_DOT11_MODE_HT(dot11mode)) + { + PopulateDot11fHTCaps( pMac, psessionEntry, &pr.HTCaps ); + } + } + + /* Set channelbonding information as "disabled" when tunned to a 2.4 GHz channel */ + if( nChannelNum <= SIR_11B_CHANNEL_END) + { + if (pMac->roam.configParam.channelBondingMode24GHz + == PHY_SINGLE_CHANNEL_CENTERED) { + pr.HTCaps.supportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ; + pr.HTCaps.shortGI40MHz = 0; + } else { + pr.HTCaps.supportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + } + } + +#ifdef WLAN_FEATURE_11AC + if (psessionEntry != NULL ) { + psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(dot11mode); + /* Include VHT Capability IE */ + if (psessionEntry->vhtCapability) { + PopulateDot11fVHTCaps( pMac, psessionEntry, &pr.VHTCaps ); + isVHTEnabled = true; + } + } else { + if (IS_DOT11_MODE_VHT(dot11mode)) { + PopulateDot11fVHTCaps( pMac, psessionEntry, &pr.VHTCaps ); + isVHTEnabled = true; + } + } +#endif + + if (psessionEntry != NULL) + PopulateDot11fExtCap(pMac, isVHTEnabled, &pr.ExtCap, psessionEntry); + else + limLog(pMac, LOGE, + FL("session entry null, ext capabilities will not be populated")); + + // That's it-- now we pack it. First, how much space are we going to + // need? + nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Probe Request (0x%08x)."), nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating" + "the packed size for a Probe Request (" + "0x%08x)."), nStatus ); + } + + /* Strip extended capability IE (if present). FW will add that IE */ + if (addn_ielen) { + extcap_status = lim_strip_extcap_ie(pMac, pAdditionalIE, &addn_ielen, + NULL); + if (eSIR_SUCCESS != extcap_status) + limLog(pMac, LOGE, + FL("Error:(%d) stripping extcap IE"), extcap_status); + + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + addn_ielen; + + // Ok-- try to allocate some memory: + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Pro" + "be Request."), nBytes ); + return eSIR_MEM_ALLOC_FAILED; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssid, SelfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Probe Request (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return nSirStatus; // allocated! + } + + // That done, pack the Probe Request: + nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame + + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Probe Request (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a P" + "robe Request (0x%08x)."), nStatus ); + } + + /* Append any AddIE if present. */ + if(addn_ielen) { + vos_mem_copy(pFrame + sizeof(tSirMacMgmtHdr)+nPayload, + pAdditionalIE, addn_ielen); + nPayload += addn_ielen; + } + + /* If this probe request is sent during P2P Search State, then we need + * to send it at OFDM rate. + */ + if( ( SIR_BAND_5_GHZ == limGetRFBand(nChannelNum)) + || (( pMac->lim.gpLimMlmScanReq != NULL) && + pMac->lim.gpLimMlmScanReq->p2pSearch ) + /* For unicast probe req mgmt from Join function + we don't set above variables. So we need to add + one more check whether it is pePersona is P2P_CLIENT or not */ + || ( ( psessionEntry != NULL ) && + ( VOS_P2P_CLIENT_MODE == psessionEntry->pePersona ) ) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) sizeof(tSirMacMgmtHdr) + nPayload, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("could not send Probe Request frame!" )); + //Pkt will be freed up by the callback + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} // End limSendProbeReqMgmtFrame. + +tSirRetStatus limGetAddnIeForProbeResp(tpAniSirGlobal pMac, + tANI_U8* addIE, tANI_U16 *addnIELen, + tANI_U8 probeReqP2pIe) +{ + /* If Probe request doesn't have P2P IE, then take out P2P IE + from additional IE */ + if(!probeReqP2pIe) + { + tANI_U8* tempbuf = NULL; + tANI_U16 tempLen = 0; + int left = *addnIELen; + v_U8_t *ptr = addIE; + v_U8_t elem_id, elem_len; + + if(NULL == addIE) + { + PELOGE(limLog(pMac, LOGE, + FL(" NULL addIE pointer"));) + return eSIR_FAILURE; + } + + tempbuf = vos_mem_malloc(left); + if ( NULL == tempbuf ) + { + PELOGE(limLog(pMac, LOGE, + FL("Unable to allocate memory to store addn IE"));) + return eSIR_MEM_ALLOC_FAILED; + } + + while(left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) + { + limLog( pMac, LOGE, + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), + elem_id,elem_len,left); + vos_mem_free(tempbuf); + return eSIR_FAILURE; + } + if ( !( (SIR_MAC_EID_VENDOR == elem_id) && + (memcmp(&ptr[2], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE)==0) ) ) + { + vos_mem_copy (tempbuf + tempLen, &ptr[0], elem_len + 2); + tempLen += (elem_len + 2); + } + left -= elem_len; + ptr += (elem_len + 2); + } + vos_mem_copy (addIE, tempbuf, tempLen); + *addnIELen = tempLen; + vos_mem_free(tempbuf); + } + return eSIR_SUCCESS; +} + +void +limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tpAniSSID pSsid, + short nStaId, + tANI_U8 nKeepAlive, + tpPESession psessionEntry, + tANI_U8 probeReqP2pIe) +{ + tDot11fProbeResponse *pFrm; + tSirRetStatus nSirStatus; + tANI_U32 cfg, nPayload, nBytes, nStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U8 *pFrame; + void *pPacket; + eHalStatus halstatus; + tANI_U32 addnIEPresent = VOS_FALSE; + + tANI_U16 totalAddnIeLen = 0; + tANI_U32 wpsApEnable=0, tmp; + tANI_U8 txFlag = 0; + tANI_U8 *addIE = NULL; + tANI_U8 *pP2pIe = NULL; + tANI_U8 noaLen = 0; + tANI_U8 total_noaLen = 0; + tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + + SIR_P2P_IE_HEADER_LEN]; + tANI_U8 noaIe[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + tANI_U8 smeSessionId = 0; + tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + tDot11fIEExtCap extractedExtCap; + tANI_BOOLEAN extractedExtCapFlag = eANI_BOOLEAN_TRUE; + + if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) { + /* We don't answer requests in this case */ + return; + } + + if(NULL == psessionEntry) + { + return; + } + + /* + * In case when cac timer is running for this SAP session then + * avoid sending probe rsp out. It is violation of dfs specification. + */ + if (((psessionEntry->pePersona == VOS_STA_SAP_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) && + (VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("CAC timer is running, dropping the probe response")); + return; + } + smeSessionId = psessionEntry->smeSessionId; + pFrm = vos_mem_malloc(sizeof(tDot11fProbeResponse)); + if ( NULL == pFrm ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory in limSendProbeRspMgmtFrame") ); + return; + } + + vos_mem_set(( tANI_U8* )&extractedExtCap, sizeof( tDot11fIEExtCap ), 0); + + // Fill out 'frm', after which we'll just hand the struct off to + // 'dot11fPackProbeResponse'. + vos_mem_set(( tANI_U8* )pFrm, sizeof( tDot11fProbeResponse ), 0); + + // Timestamp to be updated by TFP, below. + + // Beacon Interval: + if (LIM_IS_AP_ROLE(psessionEntry)) { + pFrm->BeaconInterval.interval = pMac->sch.schObject.gSchBeaconInterval; + } else { + nSirStatus = wlan_cfgGetInt( pMac, WNI_CFG_BEACON_INTERVAL, &cfg); + if (eSIR_SUCCESS != nSirStatus) + { + limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BEACON_INTERVAL from CFG (%d)."), + nSirStatus ); + vos_mem_free(pFrm); + return; + } + pFrm->BeaconInterval.interval = ( tANI_U16 ) cfg; + } + + PopulateDot11fCapabilities( pMac, &pFrm->Capabilities, psessionEntry ); + PopulateDot11fSSID( pMac, ( tSirMacSSid* )pSsid, &pFrm->SSID ); + PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &pFrm->SuppRates,psessionEntry); + + PopulateDot11fDSParams( pMac, &pFrm->DSParams, psessionEntry->currentOperChannel,psessionEntry); + PopulateDot11fIBSSParams( pMac, &pFrm->IBSSParams, psessionEntry ); + + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(psessionEntry->wps_state != SAP_WPS_DISABLED) + { + PopulateDot11fProbeResWPSIEs(pMac, &pFrm->WscProbeRes, psessionEntry); + } + } else { + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) + limLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); + + wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; + + if (wpsApEnable) + { + PopulateDot11fWscInProbeRes(pMac, &pFrm->WscProbeRes); + } + + if (pMac->lim.wscIeInfo.probeRespWscEnrollmentState == eLIM_WSC_ENROLL_BEGIN) + { + PopulateDot11fWscRegistrarInfoInProbeRes(pMac, &pFrm->WscProbeRes); + pMac->lim.wscIeInfo.probeRespWscEnrollmentState = eLIM_WSC_ENROLL_IN_PROGRESS; + } + + if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_END) + { + DePopulateDot11fWscRegistrarInfoInProbeRes(pMac, &pFrm->WscProbeRes); + pMac->lim.wscIeInfo.probeRespWscEnrollmentState = eLIM_WSC_ENROLL_NOOP; + } + } + + PopulateDot11fCountry( pMac, &pFrm->Country, psessionEntry); + PopulateDot11fEDCAParamSet( pMac, &pFrm->EDCAParamSet, psessionEntry); + + + if (psessionEntry->dot11mode != WNI_CFG_DOT11_MODE_11B) + PopulateDot11fERPInfo( pMac, &pFrm->ERPInfo, psessionEntry); + + + // N.B. In earlier implementations, the RSN IE would be placed in + // the frame here, before the WPA IE, if 'RSN_BEFORE_WPA' was defined. + PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &pFrm->ExtSuppRates, psessionEntry ); + + //Populate HT IEs, when operating in 11n + if ( psessionEntry->htCapability ) + { + PopulateDot11fHTCaps( pMac, psessionEntry, &pFrm->HTCaps ); + PopulateDot11fHTInfo( pMac, &pFrm->HTInfo, psessionEntry ); + } +#ifdef WLAN_FEATURE_11AC + if(psessionEntry->vhtCapability) + { + limLog( pMac, LOG1, FL("Populate VHT IE in Probe Response")); + PopulateDot11fVHTCaps( pMac, psessionEntry, &pFrm->VHTCaps ); + PopulateDot11fVHTOperation( pMac, psessionEntry, &pFrm->VHTOperation ); + // we do not support multi users yet + //PopulateDot11fVHTExtBssLoad( pMac, &frm.VHTExtBssLoad ); + isVHTEnabled = eANI_BOOLEAN_TRUE; + } +#endif + + PopulateDot11fExtCap(pMac, isVHTEnabled, &pFrm->ExtCap, psessionEntry); + + if ( psessionEntry->pLimStartBssReq ) + { + PopulateDot11fWPA( pMac, &( psessionEntry->pLimStartBssReq->rsnIE ), + &pFrm->WPA ); + PopulateDot11fRSNOpaque( pMac, &( psessionEntry->pLimStartBssReq->rsnIE ), + &pFrm->RSNOpaque ); + } + + PopulateDot11fWMM( pMac, &pFrm->WMMInfoAp, &pFrm->WMMParams, &pFrm->WMMCaps, psessionEntry ); + +#if defined(FEATURE_WLAN_WAPI) + if( psessionEntry->pLimStartBssReq ) + { + PopulateDot11fWAPI( pMac, &( psessionEntry->pLimStartBssReq->rsnIE ), + &pFrm->WAPI ); + } + +#endif // defined(FEATURE_WLAN_WAPI) + + + nStatus = dot11fGetPackedProbeResponseSize( pMac, pFrm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Probe Response (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fProbeResponse ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating" + "the packed size for a Probe Response " + "(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + + if( pMac->lim.gpLimRemainOnChanReq ) + { + nBytes += (pMac->lim.gpLimRemainOnChanReq->length - sizeof( tSirRemainOnChnReq ) ); + } + //Only use CFG for non-listen mode. This CFG is not working for concurrency + //In listening mode, probe rsp IEs is passed in the message from SME to PE + else + { + addnIEPresent = (psessionEntry->addIeParams.probeRespDataLen != 0); + } + + if (addnIEPresent) + { + + addIE = vos_mem_malloc(psessionEntry->addIeParams.probeRespDataLen); + if ( NULL == addIE ) + { + PELOGE(limLog(pMac, LOGE, + FL("Unable to allocate memory to store addn IE"));) + vos_mem_free(pFrm); + return; + } + + vos_mem_copy(addIE, psessionEntry->addIeParams.probeRespData_buff, + psessionEntry->addIeParams.probeRespDataLen); + totalAddnIeLen = psessionEntry->addIeParams.probeRespDataLen; + + if(eSIR_SUCCESS != limGetAddnIeForProbeResp(pMac, addIE, + &totalAddnIeLen, probeReqP2pIe)) + { + limLog(pMac, LOGP, + FL("Unable to get final Additional IE for Probe Req")); + vos_mem_free(addIE); + vos_mem_free(pFrm); + return; + } + + nSirStatus = lim_strip_extcap_update_struct(pMac, + addIE, + &totalAddnIeLen, + &extractedExtCap ); + if(eSIR_SUCCESS != nSirStatus ) + { + extractedExtCapFlag = eANI_BOOLEAN_FALSE; + limLog(pMac, LOG1, + FL("Unable to Stripoff ExtCap IE from Probe Rsp")); + } + + nBytes = nBytes + totalAddnIeLen; + + if (probeReqP2pIe) + { + pP2pIe = limGetP2pIEPtr(pMac, &addIE[0], totalAddnIeLen); + if (pP2pIe != NULL) + { + //get NoA attribute stream P2P IE + noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry); + if (noaLen != 0) + { + total_noaLen = limBuildP2pIe(pMac, &noaIe[0], + &noaStream[0], noaLen); + nBytes = nBytes + total_noaLen; + } + } + } + } + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Pro" + "be Response."), nBytes ); + if ( addIE != NULL ) + { + vos_mem_free(addIE); + } + vos_mem_free(pFrm); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_RSP, peerMacAddr,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Probe Response (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + if ( addIE != NULL ) + { + vos_mem_free(addIE); + } + vos_mem_free(pFrm); + return; + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + + /*merge ExtCap IE*/ + if (extractedExtCapFlag) + { + lim_merge_extcap_struct(&pFrm->ExtCap, &extractedExtCap); + } + // That done, pack the Probe Response: + nStatus = dot11fPackProbeResponse( pMac, pFrm, pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + if ( addIE != NULL ) + { + vos_mem_free(addIE); + } + vos_mem_free(pFrm); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a P" + "robe Response (0x%08x)."), nStatus ); + } + + PELOG3(limLog( pMac, LOG3, FL("Sending Probe Response frame to ") ); + limPrintMacAddr( pMac, peerMacAddr, LOG3 );) + + pMac->sys.probeRespond++; + + if( pMac->lim.gpLimRemainOnChanReq ) + { + vos_mem_copy ( pFrame+sizeof(tSirMacMgmtHdr)+nPayload, + pMac->lim.gpLimRemainOnChanReq->probeRspIe, (pMac->lim.gpLimRemainOnChanReq->length - sizeof( tSirRemainOnChnReq )) ); + } + + if ( addnIEPresent ) + { + vos_mem_copy(pFrame+sizeof(tSirMacMgmtHdr)+nPayload, &addIE[0], totalAddnIeLen); + } + if (noaLen != 0) + { + if (total_noaLen > (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN)) + { + limLog(pMac, LOGE, + FL("Not able to insert NoA, total len=%d"), total_noaLen); + vos_mem_free(addIE); + vos_mem_free(pFrm); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; + } + else + { + vos_mem_copy( &pFrame[nBytes - (total_noaLen)], + &noaIe[0], total_noaLen); + } + } + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + // Queue Probe Response frame in high priority WQ + halstatus = halTxFrame( ( tHalHandle ) pMac, pPacket, + ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Could not send Probe Response.") ); + //Pkt will be freed up by the callback + } + + if ( addIE != NULL ) + { + vos_mem_free(addIE); + } + + vos_mem_free(pFrm); + return; + + +} // End limSendProbeRspMgmtFrame. + +void +limSendAddtsReqActionFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirAddtsReqInfo *pAddTS, + tpPESession psessionEntry) +{ + tANI_U16 i; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tDot11fAddTSRequest AddTSReq; + tDot11fWMMAddTSRequest WMMAddTSReq; + tANI_U32 nPayload, nBytes, nStatus; + tpSirMacMgmtHdr pMacHdr; + void *pPacket; +#ifdef FEATURE_WLAN_ESE + tANI_U32 phyMode; +#endif + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + if ( ! pAddTS->wmeTspecPresent ) + { + vos_mem_set(( tANI_U8* )&AddTSReq, sizeof( AddTSReq ), 0); + + AddTSReq.Action.action = SIR_MAC_QOS_ADD_TS_REQ; + AddTSReq.DialogToken.token = pAddTS->dialogToken; + AddTSReq.Category.category = SIR_MAC_ACTION_QOS_MGMT; + if ( pAddTS->lleTspecPresent ) + { + PopulateDot11fTSPEC( &pAddTS->tspec, &AddTSReq.TSPEC ); + } + else + { + PopulateDot11fWMMTSPEC( &pAddTS->tspec, &AddTSReq.WMMTSPEC ); + } + + if ( pAddTS->lleTspecPresent ) + { + AddTSReq.num_WMMTCLAS = 0; + AddTSReq.num_TCLAS = pAddTS->numTclas; + for ( i = 0; i < pAddTS->numTclas; ++i) + { + PopulateDot11fTCLAS( pMac, &pAddTS->tclasInfo[i], + &AddTSReq.TCLAS[i] ); + } + } + else + { + AddTSReq.num_TCLAS = 0; + AddTSReq.num_WMMTCLAS = pAddTS->numTclas; + for ( i = 0; i < pAddTS->numTclas; ++i) + { + PopulateDot11fWMMTCLAS( pMac, &pAddTS->tclasInfo[i], + &AddTSReq.WMMTCLAS[i] ); + } + } + + if ( pAddTS->tclasProcPresent ) + { + if ( pAddTS->lleTspecPresent ) + { + AddTSReq.TCLASSPROC.processing = pAddTS->tclasProc; + AddTSReq.TCLASSPROC.present = 1; + } + else + { + AddTSReq.WMMTCLASPROC.version = 1; + AddTSReq.WMMTCLASPROC.processing = pAddTS->tclasProc; + AddTSReq.WMMTCLASPROC.present = 1; + } + } + + nStatus = dot11fGetPackedAddTSRequestSize( pMac, &AddTSReq, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or an Add TS Request (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fAddTSRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating" + "the packed size for an Add TS Request" + " (0x%08x)."), nStatus ); + } + } + else + { + vos_mem_set(( tANI_U8* )&WMMAddTSReq, sizeof( WMMAddTSReq ), 0); + + WMMAddTSReq.Action.action = SIR_MAC_QOS_ADD_TS_REQ; + WMMAddTSReq.DialogToken.token = pAddTS->dialogToken; + WMMAddTSReq.Category.category = SIR_MAC_ACTION_WME; + + // WMM spec 2.2.10 - status code is only filled in for ADDTS response + WMMAddTSReq.StatusCode.statusCode = 0; + + PopulateDot11fWMMTSPEC( &pAddTS->tspec, &WMMAddTSReq.WMMTSPEC ); +#ifdef FEATURE_WLAN_ESE + limGetPhyMode(pMac, &phyMode, psessionEntry); + + if( phyMode == WNI_CFG_PHY_MODE_11G || phyMode == WNI_CFG_PHY_MODE_11A) + { + pAddTS->tsrsIE.rates[0] = TSRS_11AG_RATE_6MBPS; + } + else + { + pAddTS->tsrsIE.rates[0] = TSRS_11B_RATE_5_5MBPS; + } + PopulateDot11TSRSIE(pMac,&pAddTS->tsrsIE, &WMMAddTSReq.ESETrafStrmRateSet,sizeof(tANI_U8)); +#endif + // fillWmeTspecIE + + nStatus = dot11fGetPackedWMMAddTSRequestSize( pMac, &WMMAddTSReq, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a WMM Add TS Request (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fAddTSRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating" + "the packed size for a WMM Add TS Requ" + "est (0x%08x)."), nStatus ); + } + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" + "d TS Request."), nBytes ); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peerMacAddr,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Add TS Request (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peerMacAddr, pMacHdr); +#endif + + // That done, pack the struct: + if ( ! pAddTS->wmeTspecPresent ) + { + nStatus = dot11fPackAddTSRequest( pMac, &AddTSReq, + pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack an Add TS Request " + "(0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing " + "an Add TS Request (0x%08x)."), nStatus ); + } + } + else + { + nStatus = dot11fPackWMMAddTSRequest( pMac, &WMMAddTSReq, + pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a WMM Add TS Reque" + "st (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing " + "a WMM Add TS Request (0x%08x)."), nStatus ); + } + } + + PELOG3(limLog( pMac, LOG3, FL("Sending an Add TS Request frame to ") ); + limPrintMacAddr( pMac, peerMacAddr, LOG3 );) + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + + // Queue Addts Response frame in high priority WQ + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL( "*** Could not send an Add TS Request" + " (%X) ***" ), halstatus ); + //Pkt will be freed up by the callback + } + +} // End limSendAddtsReqActionFrame. + + + +void +limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, + tANI_U16 statusCode, + tANI_U16 aid, + tSirMacAddr peerMacAddr, + tANI_U8 subType, + tpDphHashNode pSta,tpPESession psessionEntry) +{ + static tDot11fAssocResponse frm; + tANI_U8 *pFrame, *macAddr; + tpSirMacMgmtHdr pMacHdr; + tSirRetStatus nSirStatus; + tANI_U8 lleMode = 0, fAddTS; + tHalBitVal qosMode, wmeMode; + tANI_U32 nPayload, nBytes, nStatus; + void *pPacket; + eHalStatus halstatus; + tUpdateBeaconParams beaconParams; + tANI_U8 txFlag = 0; + tANI_U32 addnIEPresent = false; + tANI_U32 addnIELen=0; + tANI_U8 addIE[WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN]; + tpSirAssocReq pAssocReq = NULL; + tANI_U8 smeSessionId = 0; + tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + tANI_U16 addStripoffIELen = 0; + tDot11fIEExtCap extractedExtCap; + tANI_BOOLEAN extractedExtCapFlag = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_11W + tANI_U32 retryInterval; + tANI_U32 maxRetries; +#endif + + if(NULL == psessionEntry) + { + limLog( pMac, LOGE, FL("psessionEntry is NULL")); + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + limGetQosMode(psessionEntry, &qosMode); + limGetWmeMode(psessionEntry, &wmeMode); + + // An Add TS IE is added only if the AP supports it and the requesting + // STA sent a traffic spec. + fAddTS = ( qosMode && pSta && pSta->qos.addtsPresent ) ? 1 : 0; + + frm.Status.status = statusCode; + + frm.AID.associd = aid | LIM_AID_MASK; + + if ( NULL == pSta ) + { + PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &frm.SuppRates,psessionEntry); + PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &frm.ExtSuppRates, psessionEntry ); + } + else + { + PopulateDot11fAssocRspRates( pMac, &frm.SuppRates, &frm.ExtSuppRates, + pSta->supportedRates.llbRates, pSta->supportedRates.llaRates ); + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if( pSta != NULL && eSIR_SUCCESS == statusCode ) + { + pAssocReq = + (tpSirAssocReq) psessionEntry->parsedAssocReq[pSta->assocId]; + /* populate P2P IE in AssocRsp when assocReq from the peer includes P2P IE */ + if( pAssocReq != NULL && pAssocReq->addIEPresent ) { + PopulateDot11AssocResP2PIE(pMac, &frm.P2PAssocRes, pAssocReq); + } + } + } + + if ( NULL != pSta ) + { + if ( eHAL_SET == qosMode ) + { + if ( pSta->lleEnabled ) + { + lleMode = 1; + PopulateDot11fEDCAParamSet( pMac, &frm.EDCAParamSet, psessionEntry); + } // End if on .11e enabled in 'pSta'. + } // End if on QOS Mode on. + + if ((!lleMode) && (eHAL_SET == wmeMode) && pSta->wmeEnabled) { + PopulateDot11fWMMParams(pMac, &frm.WMMParams, psessionEntry); + + if (pSta->wsmEnabled) { + PopulateDot11fWMMCaps(&frm.WMMCaps); + } + } + + if ( pSta->mlmStaContext.htCapability && + psessionEntry->htCapability ) + { + limLog(pMac, LOG1, FL("Populate HT IEs in Assoc Response")); + PopulateDot11fHTCaps( pMac, psessionEntry, &frm.HTCaps ); + PopulateDot11fHTInfo( pMac, &frm.HTInfo, psessionEntry ); + } + limLog(pMac, LOG1, FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d, AMPDU Param: %x"), + frm.HTCaps.supportedChannelWidthSet, frm.HTCaps.mimoPowerSave, + frm.HTCaps.greenField, frm.HTCaps.shortGI20MHz, + frm.HTCaps.shortGI40MHz, + frm.HTCaps.dsssCckMode40MHz, frm.HTCaps.maxRxAMPDUFactor); + + + +#ifdef WLAN_FEATURE_11AC + if( pSta->mlmStaContext.vhtCapability && + psessionEntry->vhtCapability ) + { + limLog( pMac, LOG1, FL("Populate VHT IEs in Assoc Response")); + PopulateDot11fVHTCaps( pMac, psessionEntry, &frm.VHTCaps ); + PopulateDot11fVHTOperation( pMac, psessionEntry, &frm.VHTOperation); + isVHTEnabled = eANI_BOOLEAN_TRUE; + } +#endif + + PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); + +#ifdef WLAN_FEATURE_11W + if( eSIR_MAC_TRY_AGAIN_LATER == statusCode ) + { + if ( wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + &maxRetries ) != eSIR_SUCCESS ) + limLog( pMac, LOGE, FL("Could not retrieve PMF SA " + "Query maximum retries value") ); + else + if ( wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + &retryInterval ) != eSIR_SUCCESS) + limLog( pMac, LOGE, FL("Could not retrieve PMF SA " + "Query timer interval value") ); + else + PopulateDot11fTimeoutInterval( + pMac, &frm.TimeoutInterval, + SIR_MAC_TI_TYPE_ASSOC_COMEBACK, + (maxRetries - pSta->pmfSaQueryRetryCount) * retryInterval ); + } +#endif + } // End if on non-NULL 'pSta'. + + vos_mem_set(( tANI_U8* )&beaconParams, sizeof( tUpdateBeaconParams), 0); + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(psessionEntry->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + limDecideApProtection(pMac, peerMacAddr, &beaconParams,psessionEntry); + } + + limUpdateShortPreamble(pMac, peerMacAddr, &beaconParams, psessionEntry); + limUpdateShortSlotTime(pMac, peerMacAddr, &beaconParams, psessionEntry); + + /* Populate Do11capabilities after updating session with Assos req details + */ + PopulateDot11fCapabilities( pMac, &frm.Capabilities, psessionEntry ); + + beaconParams.bssIdx = psessionEntry->bssIdx; + + //Send message to HAL about beacon parameter change. + if((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) + { + schSetFixedBeaconFields(pMac,psessionEntry); + limSendBeaconParams(pMac, &beaconParams, psessionEntry ); + } + + // Allocate a buffer for this frame: + nStatus = dot11fGetPackedAssocResponseSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to calculate the packed size f" + "or an Association Response (0x%08x)."), + nStatus ); + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for an Association Re" + "sponse (0x%08x)."), nStatus ); + } + + nBytes = sizeof( tSirMacMgmtHdr ) + nPayload; + + if ( pAssocReq != NULL ) + { + addnIEPresent = (psessionEntry->addIeParams.assocRespDataLen != 0); + + if (addnIEPresent) + { + //Assoc rsp IE available + + addnIELen = psessionEntry->addIeParams.assocRespDataLen; + + if (addnIELen <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN && addnIELen && + (nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) + { + vos_mem_copy(addIE, psessionEntry->addIeParams.assocRespData_buff, + psessionEntry->addIeParams.assocRespDataLen); + + if (addnIELen) + + { + vos_mem_set(( tANI_U8* )&extractedExtCap, + sizeof( tDot11fIEExtCap ), 0); + + addStripoffIELen = addnIELen; + nSirStatus = lim_strip_extcap_update_struct(pMac, + &addIE[0], + &addStripoffIELen, + &extractedExtCap ); + if(eSIR_SUCCESS != nSirStatus) + { + limLog(pMac, LOG1, + FL("Unable to Stripoff ExtCap IE from Assoc Rsp")); + } + else + { + addnIELen = addStripoffIELen; + extractedExtCapFlag = eANI_BOOLEAN_TRUE; + } + nBytes = nBytes + addnIELen; + } + } + } + else + { + limLog(pMac, LOG1, FL("addnIEPresent = %d for Assoc Resp : %d"), + addnIEPresent, pAssocReq->addIEPresent); + } + } + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGP, FL("Call to bufAlloc failed for RE/ASSOC RSP.")); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, + pFrame, + SIR_MAC_MGMT_FRAME, + ( LIM_ASSOC == subType ) ? + SIR_MAC_MGMT_ASSOC_RSP : + SIR_MAC_MGMT_REASSOC_RSP, + peerMacAddr,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Association Response (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + + /* merge the ExtCap struct*/ + if (extractedExtCapFlag) + { + lim_merge_extcap_struct(&(frm.ExtCap), &extractedExtCap); + } + nStatus = dot11fPackAssocResponse( pMac, &frm, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack an Association Response" + " (0x%08x)."), nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing an " + "Association Response (0x%08x)."), nStatus ); + } + + macAddr = pMacHdr->da; + + if (subType == LIM_ASSOC) + { + PELOG1(limLog(pMac, LOG1, + FL("*** Sending Assoc Resp status %d aid %d to "), + statusCode, aid);) + } + else{ + PELOG1(limLog(pMac, LOG1, + FL("*** Sending ReAssoc Resp status %d aid %d to "), + statusCode, aid);) + } + PELOG1(limPrintMacAddr(pMac, pMacHdr->da, LOG1);) + + if ( addnIEPresent && addnIELen <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN ) + { + vos_mem_copy( pFrame+sizeof(tSirMacMgmtHdr)+nPayload, + &addIE[0], addnIELen ) ; + } + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + /// Queue Association Response frame in high priority WQ + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog(pMac, LOGE, + FL("*** Could not Send Re/AssocRsp, retCode=%X ***"), + nSirStatus); + + //Pkt will be freed up by the callback + } + + // update the ANI peer station count + //FIXME_PROTECTION : take care of different type of station + // counter inside this function. + limUtilCountStaAdd(pMac, pSta, psessionEntry); + +} // End limSendAssocRspMgmtFrame. + + + +void +limSendAddtsRspActionFrame(tpAniSirGlobal pMac, + tSirMacAddr peer, + tANI_U16 nStatusCode, + tSirAddtsReqInfo *pAddTS, + tSirMacScheduleIE *pSchedule, + tpPESession psessionEntry) +{ + tANI_U8 *pFrame; + tpSirMacMgmtHdr pMacHdr; + tDot11fAddTSResponse AddTSRsp; + tDot11fWMMAddTSResponse WMMAddTSRsp; + tSirRetStatus nSirStatus; + tANI_U32 i, nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + if ( ! pAddTS->wmeTspecPresent ) + { + vos_mem_set( ( tANI_U8* )&AddTSRsp, sizeof( AddTSRsp ), 0 ); + + AddTSRsp.Category.category = SIR_MAC_ACTION_QOS_MGMT; + AddTSRsp.Action.action = SIR_MAC_QOS_ADD_TS_RSP; + AddTSRsp.DialogToken.token = pAddTS->dialogToken; + AddTSRsp.Status.status = nStatusCode; + + // The TsDelay information element is only filled in for a specific + // status code: + if ( eSIR_MAC_TS_NOT_CREATED_STATUS == nStatusCode ) + { + if ( pAddTS->wsmTspecPresent ) + { + AddTSRsp.WMMTSDelay.version = 1; + AddTSRsp.WMMTSDelay.delay = 10; + AddTSRsp.WMMTSDelay.present = 1; + } + else + { + AddTSRsp.TSDelay.delay = 10; + AddTSRsp.TSDelay.present = 1; + } + } + + if ( pAddTS->wsmTspecPresent ) + { + PopulateDot11fWMMTSPEC( &pAddTS->tspec, &AddTSRsp.WMMTSPEC ); + } + else + { + PopulateDot11fTSPEC( &pAddTS->tspec, &AddTSRsp.TSPEC ); + } + + if ( pAddTS->wsmTspecPresent ) + { + AddTSRsp.num_WMMTCLAS = 0; + AddTSRsp.num_TCLAS = pAddTS->numTclas; + for ( i = 0; i < AddTSRsp.num_TCLAS; ++i) + { + PopulateDot11fTCLAS( pMac, &pAddTS->tclasInfo[i], + &AddTSRsp.TCLAS[i] ); + } + } + else + { + AddTSRsp.num_TCLAS = 0; + AddTSRsp.num_WMMTCLAS = pAddTS->numTclas; + for ( i = 0; i < AddTSRsp.num_WMMTCLAS; ++i) + { + PopulateDot11fWMMTCLAS( pMac, &pAddTS->tclasInfo[i], + &AddTSRsp.WMMTCLAS[i] ); + } + } + + if ( pAddTS->tclasProcPresent ) + { + if ( pAddTS->wsmTspecPresent ) + { + AddTSRsp.WMMTCLASPROC.version = 1; + AddTSRsp.WMMTCLASPROC.processing = pAddTS->tclasProc; + AddTSRsp.WMMTCLASPROC.present = 1; + } + else + { + AddTSRsp.TCLASSPROC.processing = pAddTS->tclasProc; + AddTSRsp.TCLASSPROC.present = 1; + } + } + + // schedule element is included only if requested in the tspec and we are + // using hcca (or both edca and hcca) + // 11e-D8.0 is inconsistent on whether the schedule element is included + // based on tspec schedule bit or not. Sec 7.4.2.2. says one thing but + // pg 46, line 17-18 says something else. So just include it and let the + // sta figure it out + if ((pSchedule != NULL) && + ((pAddTS->tspec.tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) || + (pAddTS->tspec.tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_BOTH))) + { + if ( pAddTS->wsmTspecPresent ) + { + PopulateDot11fWMMSchedule( pSchedule, &AddTSRsp.WMMSchedule ); + } + else + { + PopulateDot11fSchedule( pSchedule, &AddTSRsp.Schedule ); + } + } + + nStatus = dot11fGetPackedAddTSResponseSize( pMac, &AddTSRsp, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed si" + "ze for an Add TS Response (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fAddTSResponse ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calcula" + "ting the packed size for an Add TS" + " Response (0x%08x)."), nStatus ); + } + } + else + { + vos_mem_set( ( tANI_U8* )&WMMAddTSRsp, sizeof( WMMAddTSRsp ), 0 ); + + WMMAddTSRsp.Category.category = SIR_MAC_ACTION_WME; + WMMAddTSRsp.Action.action = SIR_MAC_QOS_ADD_TS_RSP; + WMMAddTSRsp.DialogToken.token = pAddTS->dialogToken; + WMMAddTSRsp.StatusCode.statusCode = (tANI_U8)nStatusCode; + + PopulateDot11fWMMTSPEC( &pAddTS->tspec, &WMMAddTSRsp.WMMTSPEC ); + + nStatus = dot11fGetPackedWMMAddTSResponseSize( pMac, &WMMAddTSRsp, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed si" + "ze for a WMM Add TS Response (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fWMMAddTSResponse ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calcula" + "ting the packed size for a WMM Add" + "TS Response (0x%08x)."), nStatus ); + } + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" + "d TS Response."), nBytes ); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Add TS Response (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + // That done, pack the struct: + if ( ! pAddTS->wmeTspecPresent ) + { + nStatus = dot11fPackAddTSResponse( pMac, &AddTSRsp, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack an Add TS Response " + "(0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing " + "an Add TS Response (0x%08x)."), nStatus ); + } + } + else + { + nStatus = dot11fPackWMMAddTSResponse( pMac, &WMMAddTSRsp, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a WMM Add TS Response " + "(0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing " + "a WMM Add TS Response (0x%08x)."), nStatus ); + } + } + + PELOG1(limLog( pMac, LOG1, FL("Sending an Add TS Response (status %d) to "), + nStatusCode ); + limPrintMacAddr( pMac, pMacHdr->da, LOG1 );) + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + // Queue the frame in high priority WQ: + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send Add TS Response (%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + } + +} // End limSendAddtsRspActionFrame. + +void +limSendDeltsReqActionFrame(tpAniSirGlobal pMac, + tSirMacAddr peer, + tANI_U8 wmmTspecPresent, + tSirMacTSInfo *pTsinfo, + tSirMacTspecIE *pTspecIe, + tpPESession psessionEntry) +{ + tANI_U8 *pFrame; + tpSirMacMgmtHdr pMacHdr; + tDot11fDelTS DelTS; + tDot11fWMMDelTS WMMDelTS; + tSirRetStatus nSirStatus; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + if ( ! wmmTspecPresent ) + { + vos_mem_set( ( tANI_U8* )&DelTS, sizeof( DelTS ), 0 ); + + DelTS.Category.category = SIR_MAC_ACTION_QOS_MGMT; + DelTS.Action.action = SIR_MAC_QOS_DEL_TS_REQ; + PopulateDot11fTSInfo( pTsinfo, &DelTS.TSInfo ); + + nStatus = dot11fGetPackedDelTSSize( pMac, &DelTS, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed si" + "ze for a Del TS (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fDelTS ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calcula" + "ting the packed size for a Del TS" + " (0x%08x)."), nStatus ); + } + } + else + { + vos_mem_set( ( tANI_U8* )&WMMDelTS, sizeof( WMMDelTS ), 0 ); + + WMMDelTS.Category.category = SIR_MAC_ACTION_WME; + WMMDelTS.Action.action = SIR_MAC_QOS_DEL_TS_REQ; + WMMDelTS.DialogToken.token = 0; + WMMDelTS.StatusCode.statusCode = 0; + PopulateDot11fWMMTSPEC( pTspecIe, &WMMDelTS.WMMTSPEC ); + nStatus = dot11fGetPackedWMMDelTSSize( pMac, &WMMDelTS, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed si" + "ze for a WMM Del TS (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fDelTS ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calcula" + "ting the packed size for a WMM De" + "l TS (0x%08x)."), nStatus ); + } + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" + "d TS Response."), nBytes ); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, + psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Add TS Response (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + // That done, pack the struct: + if ( !wmmTspecPresent ) + { + nStatus = dot11fPackDelTS( pMac, &DelTS, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Del TS frame (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing " + "a Del TS frame (0x%08x)."), nStatus ); + } + } + else + { + nStatus = dot11fPackWMMDelTS( pMac, &WMMDelTS, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a WMM Del TS frame (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing " + "a WMM Del TS frame (0x%08x)."), nStatus ); + } + } + + PELOG1(limLog(pMac, LOG1, FL("Sending DELTS REQ (size %d) to "), nBytes); + limPrintMacAddr(pMac, pMacHdr->da, LOG1);) + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId,pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send Del TS (%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + } + +} // End limSendDeltsReqActionFrame. + +void +limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, + tLimMlmAssocReq *pMlmAssocReq, + tpPESession psessionEntry) +{ + tDot11fAssocRequest *pFrm; + tANI_U16 caps; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tLimMlmAssocCnf mlmAssocCnf; + tANI_U32 nBytes, nPayload, nStatus; + tANI_U8 fQosEnabled, fWmeEnabled, fWsmEnabled; + void *pPacket; + eHalStatus halstatus; + tANI_U16 nAddIELen; + tANI_U8 *pAddIE; + tANI_U8 *wpsIe = NULL; +#if defined WLAN_FEATURE_VOWIFI + tANI_U8 PowerCapsPopulated = FALSE; +#endif + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + tDot11fIEExtCap extractedExtCap; + tANI_BOOLEAN extractedExtCapFlag = eANI_BOOLEAN_TRUE; + tpSirMacMgmtHdr pMacHdr; + + if(NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("psessionEntry is NULL") ); + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + /* check this early to avoid unncessary operation */ + if(NULL == psessionEntry->pLimJoinReq) + { + limLog(pMac, LOGE, FL("psessionEntry->pLimJoinReq is NULL") ); + return; + } + nAddIELen = psessionEntry->pLimJoinReq->addIEAssoc.length; + pAddIE = psessionEntry->pLimJoinReq->addIEAssoc.addIEdata; + + pFrm = vos_mem_malloc(sizeof(tDot11fAssocRequest)); + if ( NULL == pFrm ) + { + limLog(pMac, LOGE, FL("Unable to allocate memory") ); + return; + } + + + vos_mem_set( ( tANI_U8* )pFrm, sizeof( tDot11fAssocRequest ), 0 ); + + if (nAddIELen) { + vos_mem_set(( tANI_U8* )&extractedExtCap, sizeof( tDot11fIEExtCap ), 0); + nSirStatus = lim_strip_extcap_update_struct(pMac, pAddIE, + &nAddIELen, + &extractedExtCap ); + if(eSIR_SUCCESS != nSirStatus ) + { + extractedExtCapFlag = eANI_BOOLEAN_FALSE; + limLog(pMac, LOG1, + FL("Unable to Stripoff ExtCap IE from Assoc Req")); + } + else + { + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) + extractedExtCap.bytes; + if (p_ext_cap->interworkingService || + p_ext_cap->bssTransition) + p_ext_cap->qosMap = 1; + else { + /* No need to merge the EXT Cap from Supplicant + * if interworkingService or bsstransition is not set, + * as currently driver is only interested in + * interworkingService and bsstransition capability from + * supplicant. + * if in future any other EXT Cap info is required from + * supplicant it needs to be handled here. + */ + extractedExtCapFlag = eANI_BOOLEAN_FALSE; + } + } + } else { + limLog(pMac, LOG1, FL("No additional IE for Assoc Request")); + extractedExtCapFlag = eANI_BOOLEAN_FALSE; + } + + caps = pMlmAssocReq->capabilityInfo; +#if defined(FEATURE_WLAN_WAPI) + /* CR: 262463 : + According to WAPI standard: + 7.3.1.4 Capability Information field + In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0 in transmitted + Association or Reassociation management frames. APs ignore the Privacy subfield within received Association and + Reassociation management frames. */ + if ( psessionEntry->encryptType == eSIR_ED_WPI) + ((tSirMacCapabilityInfo *) &caps)->privacy = 0; +#endif + swapBitField16(caps, ( tANI_U16* )&pFrm->Capabilities ); + + pFrm->ListenInterval.interval = pMlmAssocReq->listenInterval; + PopulateDot11fSSID2( pMac, &pFrm->SSID ); + PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &pFrm->SuppRates,psessionEntry); + + fQosEnabled = ( psessionEntry->limQosEnabled) && + SIR_MAC_GET_QOS( psessionEntry->limCurrentBssCaps ); + + fWmeEnabled = ( psessionEntry->limWmeEnabled ) && + LIM_BSS_CAPS_GET( WME, psessionEntry->limCurrentBssQosCaps ); + + // We prefer .11e asociations: + if ( fQosEnabled ) fWmeEnabled = false; + + fWsmEnabled = ( psessionEntry->limWsmEnabled ) && fWmeEnabled && + LIM_BSS_CAPS_GET( WSM, psessionEntry->limCurrentBssQosCaps ); + + if ( psessionEntry->lim11hEnable && + psessionEntry->pLimJoinReq->spectrumMgtIndicator == eSIR_TRUE ) + { +#if defined WLAN_FEATURE_VOWIFI + PowerCapsPopulated = TRUE; + + PopulateDot11fPowerCaps( pMac, &pFrm->PowerCaps, LIM_ASSOC,psessionEntry); +#endif + PopulateDot11fSuppChannels( pMac, &pFrm->SuppChannels, LIM_ASSOC,psessionEntry); + + } + +#if defined WLAN_FEATURE_VOWIFI + if( pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM( psessionEntry->limCurrentBssCaps ) ) + { + if (PowerCapsPopulated == FALSE) + { + PowerCapsPopulated = TRUE; + PopulateDot11fPowerCaps(pMac, &pFrm->PowerCaps, LIM_ASSOC, psessionEntry); + } + } +#endif + + if (fQosEnabled) + PopulateDot11fQOSCapsStation( pMac, &pFrm->QOSCapsStation ); + + PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &pFrm->ExtSuppRates, psessionEntry ); + +#if defined WLAN_FEATURE_VOWIFI + if (pMac->rrm.rrmPEContext.rrmEnable) + PopulateDot11fRRMIe(pMac, &pFrm->RRMEnabledCap, psessionEntry); +#endif + // The join request *should* contain zero or one of the WPA and RSN + // IEs. The payload send along with the request is a + // 'tSirSmeJoinReq'; the IE portion is held inside a 'tSirRSNie': + + // typedef struct sSirRSNie + // { + // tANI_U16 length; + // tANI_U8 rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2]; + // } tSirRSNie, *tpSirRSNie; + + // So, we should be able to make the following two calls harmlessly, + // since they do nothing if they don't find the given IE in the + // bytestream with which they're provided. + + // The net effect of this will be to faithfully transmit whatever + // security IE is in the join request. + + // *However*, if we're associating for the purpose of WPS + // enrollment, and we've been configured to indicate that by + // eliding the WPA or RSN IE, we just skip this: + if( nAddIELen && pAddIE ) + { + wpsIe = limGetWscIEPtr (pMac, pAddIE, nAddIELen); + } + if ( NULL == wpsIe ) + { + PopulateDot11fRSNOpaque( pMac, &( psessionEntry->pLimJoinReq->rsnIE ), + &pFrm->RSNOpaque ); + PopulateDot11fWPAOpaque( pMac, &( psessionEntry->pLimJoinReq->rsnIE ), + &pFrm->WPAOpaque ); +#if defined(FEATURE_WLAN_WAPI) + PopulateDot11fWAPIOpaque( pMac, &( psessionEntry->pLimJoinReq->rsnIE ), + &pFrm->WAPIOpaque ); +#endif // defined(FEATURE_WLAN_WAPI) + } + + // include WME EDCA IE as well + if (fWmeEnabled) { + if(!pMac->psOffloadEnabled) + PopulateDot11fWMMInfoStation( pMac, &pFrm->WMMInfoStation ); + else + PopulateDot11fWMMInfoStationPerSession(pMac, psessionEntry, + &pFrm->WMMInfoStation); + + if (fWsmEnabled) + PopulateDot11fWMMCaps( &pFrm->WMMCaps ); + } + + /* Populate HT IEs, when operating in 11n and + * when AP is also operating in 11n mode */ + if (psessionEntry->htCapability && + pMac->lim.htCapabilityPresentInBeacon) { + limLog(pMac, LOG1, FL("Populate HT IEs in Assoc Request")); + PopulateDot11fHTCaps(pMac, psessionEntry, &pFrm->HTCaps); + } + + limLog(pMac, LOG1, FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d, AMPDU Param: %x"), + pFrm->HTCaps.supportedChannelWidthSet, pFrm->HTCaps.mimoPowerSave, + pFrm->HTCaps.greenField, pFrm->HTCaps.shortGI20MHz, + pFrm->HTCaps.shortGI40MHz, + pFrm->HTCaps.dsssCckMode40MHz, pFrm->HTCaps.maxRxAMPDUFactor); + + +#ifdef WLAN_FEATURE_11AC + if ( psessionEntry->vhtCapability && + psessionEntry->vhtCapabilityPresentInBeacon) + { + limLog( pMac, LOG1, FL("Populate VHT IEs in Assoc Request")); + PopulateDot11fVHTCaps( pMac, psessionEntry, &pFrm->VHTCaps ); + isVHTEnabled = eANI_BOOLEAN_TRUE; + } +#endif + + PopulateDot11fExtCap( pMac, isVHTEnabled, &pFrm->ExtCap, psessionEntry); + +#if defined WLAN_FEATURE_VOWIFI_11R + if (psessionEntry->pLimJoinReq->is11Rconnection) + { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog( pMac, LOG1, FL("mdie = %02x %02x %02x"), + (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[0], + (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[1], + (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[2]); +#endif + PopulateMDIE( pMac, &pFrm->MobilityDomain, + psessionEntry->pLimJoinReq->bssDescription.mdie); + } + else + { + // No 11r IEs dont send any MDIE + limLog( pMac, LOG1, FL("MDIE not present")); + } +#endif + +#ifdef FEATURE_WLAN_ESE + /* + * ESE Version IE will be included in association request + * when ESE is enabled on DUT through ini and it is also + * advertised by the peer AP to which we are trying to + * associate to. + */ + if (psessionEntry->is_ese_version_ie_present && + pMac->roam.configParam.isEseIniFeatureEnabled) + { + PopulateDot11fESEVersion(&pFrm->ESEVersion); + } + /* For ESE Associations fill the ESE IEs */ + if (psessionEntry->isESEconnection && + psessionEntry->pLimJoinReq->isESEFeatureIniEnabled) + { +#ifndef FEATURE_DISABLE_RM + PopulateDot11fESERadMgmtCap(&pFrm->ESERadMgmtCap); +#endif + } +#endif + + nStatus = dot11fGetPackedAssocRequestSize( pMac, pFrm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or an Association Request (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fAssocRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for an Association Re " + "quest(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an As" + "sociation Request."), nBytes ); + + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, psessionEntry->limMlmState)); + + + /* Update PE session id*/ + mlmAssocCnf.sessionId = psessionEntry->peSessionId; + + mlmAssocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + + limPostSmeMessage( pMac, LIM_MLM_ASSOC_CNF, + ( tANI_U32* ) &mlmAssocCnf); + + vos_mem_free(pFrm); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ASSOC_REQ, psessionEntry->bssId,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Association Request (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + vos_mem_free(pFrm); + return; + } + /* merge the ExtCap struct*/ + if (extractedExtCapFlag) + { + lim_merge_extcap_struct(&pFrm->ExtCap, &extractedExtCap); + } + + // That done, pack the Assoc Request: + nStatus = dot11fPackAssocRequest( pMac, pFrm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Assoc Request (0x%0" + "8x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + vos_mem_free(pFrm); + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a Assoc" + "Request (0x%08x)."), nStatus ); + } + + PELOG1(limLog( pMac, LOG1, FL("*** Sending Association Request length %d" + "to "), + nBytes );) + if (psessionEntry->assocReq != NULL) { + vos_mem_free(psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; + } + + if( nAddIELen ) + { + vos_mem_copy( pFrame + sizeof(tSirMacMgmtHdr) + nPayload, + pAddIE, + nAddIELen ); + nPayload += nAddIELen; + } + + psessionEntry->assocReq = vos_mem_malloc(nPayload); + if ( NULL == psessionEntry->assocReq ) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store " + "assoc request"));) + psessionEntry->assocReqLen = 0; + } + else + { + //Store the Assoc request. This is sent to csr/hdd in join cnf response. + vos_mem_copy( psessionEntry->assocReq, pFrame + sizeof(tSirMacMgmtHdr), nPayload); + psessionEntry->assocReqLen = nPayload; + } + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if(psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) + { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ASSOC_START_EVENT, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) (sizeof(tSirMacMgmtHdr) + nPayload), + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send Association Request (%X)!"), + halstatus ); + //Pkt will be freed up by the callback + vos_mem_free(pFrm); + return; + } + + // Free up buffer allocated for mlmAssocReq + vos_mem_free(pMlmAssocReq); + pMlmAssocReq = NULL; + vos_mem_free(pFrm); + return; +} // End limSendAssocReqMgmtFrame + + +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) +/*------------------------------------------------------------------------------------ + * + * Send Reassoc Req with FTIEs. + * + *----------------------------------------------------------------------------------- + */ +void +limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq,tpPESession psessionEntry) +{ + static tDot11fReAssocRequest frm; + tANI_U16 caps; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tANI_U32 nBytes, nPayload, nStatus; + tANI_U8 fQosEnabled, fWmeEnabled, fWsmEnabled; + void *pPacket; + eHalStatus halstatus; +#if defined WLAN_FEATURE_VOWIFI + tANI_U8 PowerCapsPopulated = FALSE; +#endif + tANI_U16 ft_ies_length = 0; + tANI_U8 *pBody; + tANI_U16 nAddIELen; + tANI_U8 *pAddIE; +#if defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + tANI_U8 *wpsIe = NULL; +#endif + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + tpSirMacMgmtHdr pMacHdr; + + if (NULL == psessionEntry) { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + /* check this early to avoid unncessary operation */ + if(NULL == psessionEntry->pLimReAssocReq) { + return; + } + nAddIELen = psessionEntry->pLimReAssocReq->addIEAssoc.length; + pAddIE = psessionEntry->pLimReAssocReq->addIEAssoc.addIEdata; + limLog( pMac, LOG1, FL("limSendReassocReqWithFTIEsMgmtFrame received in " + "state (%d)."), psessionEntry->limMlmState); + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + caps = pMlmReassocReq->capabilityInfo; +#if defined(FEATURE_WLAN_WAPI) + /* CR: 262463 : + According to WAPI standard: + 7.3.1.4 Capability Information field + In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0 in transmitted + Association or Reassociation management frames. APs ignore the Privacy subfield within received Association and + Reassociation management frames. */ + if ( psessionEntry->encryptType == eSIR_ED_WPI) + ((tSirMacCapabilityInfo *) &caps)->privacy = 0; +#endif + swapBitField16(caps, ( tANI_U16* )&frm.Capabilities ); + + frm.ListenInterval.interval = pMlmReassocReq->listenInterval; + + /* * + * Get the bssid of the older AP. + * The previous ap bssid is stored in the FT Session + * while creating the PE FT Session for reassociation. + * */ + vos_mem_copy((tANI_U8*)frm.CurrentAPAddress.mac, + psessionEntry->prev_ap_bssid, sizeof(tSirMacAddr)); + + PopulateDot11fSSID2( pMac, &frm.SSID ); + PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.SuppRates,psessionEntry); + + fQosEnabled = ( psessionEntry->limQosEnabled) && + SIR_MAC_GET_QOS( psessionEntry->limReassocBssCaps ); + + fWmeEnabled = ( psessionEntry->limWmeEnabled ) && + LIM_BSS_CAPS_GET( WME, psessionEntry->limReassocBssQosCaps ); + + fWsmEnabled = ( psessionEntry->limWsmEnabled ) && fWmeEnabled && + LIM_BSS_CAPS_GET( WSM, psessionEntry->limReassocBssQosCaps ); + + if ( psessionEntry->lim11hEnable && + psessionEntry->pLimReAssocReq->spectrumMgtIndicator == eSIR_TRUE ) + { +#if defined WLAN_FEATURE_VOWIFI + PowerCapsPopulated = TRUE; + + PopulateDot11fPowerCaps(pMac, &frm.PowerCaps, + LIM_REASSOC,psessionEntry); + PopulateDot11fSuppChannels(pMac, &frm.SuppChannels, LIM_REASSOC, + psessionEntry); +#endif + } + +#if defined WLAN_FEATURE_VOWIFI + if( pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM( psessionEntry->limCurrentBssCaps ) ) + { + if (PowerCapsPopulated == FALSE) + { + PowerCapsPopulated = TRUE; + PopulateDot11fPowerCaps(pMac, &frm.PowerCaps, LIM_REASSOC, psessionEntry); + } + } +#endif + + if (fQosEnabled) + PopulateDot11fQOSCapsStation( pMac, &frm.QOSCapsStation ); + + PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.ExtSuppRates, psessionEntry ); + +#if defined WLAN_FEATURE_VOWIFI + if (pMac->rrm.rrmPEContext.rrmEnable) + PopulateDot11fRRMIe(pMac, &frm.RRMEnabledCap, psessionEntry); +#endif + + // Ideally this should be enabled for 11r also. But 11r does + // not follow the usual norm of using the Opaque object + // for rsnie and fties. Instead we just add + // the rsnie and fties at the end of the pack routine for 11r. + // This should ideally! be fixed. +#if defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + // + // The join request *should* contain zero or one of the WPA and RSN + // IEs. The payload send along with the request is a + // 'tSirSmeJoinReq'; the IE portion is held inside a 'tSirRSNie': + + // typedef struct sSirRSNie + // { + // tANI_U16 length; + // tANI_U8 rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2]; + // } tSirRSNie, *tpSirRSNie; + + // So, we should be able to make the following two calls harmlessly, + // since they do nothing if they don't find the given IE in the + // bytestream with which they're provided. + + // The net effect of this will be to faithfully transmit whatever + // security IE is in the join request. + + // *However*, if we're associating for the purpose of WPS + // enrollment, and we've been configured to indicate that by + // eliding the WPA or RSN IE, we just skip this: + if (!psessionEntry->is11Rconnection) + { + if( nAddIELen && pAddIE ) + { + wpsIe = limGetWscIEPtr(pMac, pAddIE, nAddIELen); + } + if ( NULL == wpsIe ) + { + PopulateDot11fRSNOpaque( pMac, &( psessionEntry->pLimReAssocReq->rsnIE ), + &frm.RSNOpaque ); + PopulateDot11fWPAOpaque( pMac, &( psessionEntry->pLimReAssocReq->rsnIE ), + &frm.WPAOpaque ); + } + +#ifdef FEATURE_WLAN_ESE + if (psessionEntry->pLimReAssocReq->cckmIE.length) + { + PopulateDot11fESECckmOpaque( pMac, &( psessionEntry->pLimReAssocReq->cckmIE ), + &frm.ESECckmOpaque ); + } +#endif //FEATURE_WLAN_ESE + } + +#ifdef FEATURE_WLAN_ESE + /* + * ESE Version IE will be included in association request + * when ESE is enabled on DUT through ini and it is also + * advertised by the peer AP to which we are trying to + * associate to. + */ + if (psessionEntry->is_ese_version_ie_present && + pMac->roam.configParam.isEseIniFeatureEnabled) + { + PopulateDot11fESEVersion(&frm.ESEVersion); + } + // For ESE Associations fill the ESE IEs + if (psessionEntry->isESEconnection && + psessionEntry->pLimReAssocReq->isESEFeatureIniEnabled) + { +#ifndef FEATURE_DISABLE_RM + PopulateDot11fESERadMgmtCap(&frm.ESERadMgmtCap); +#endif + } +#endif //FEATURE_WLAN_ESE +#endif //FEATURE_WLAN_ESE || FEATURE_WLAN_LFR + + // include WME EDCA IE as well + if ( fWmeEnabled ) + { + if(!pMac->psOffloadEnabled) + PopulateDot11fWMMInfoStation( pMac, &frm.WMMInfoStation ); + else + PopulateDot11fWMMInfoStationPerSession(pMac, psessionEntry, + &frm.WMMInfoStation); + + if (fWsmEnabled) + PopulateDot11fWMMCaps( &frm.WMMCaps ); +#ifdef FEATURE_WLAN_ESE + if (psessionEntry->isESEconnection) + { + PopulateDot11fReAssocTspec(pMac, &frm, psessionEntry); + + // Populate the TSRS IE if TSPEC is included in the reassoc request + if (psessionEntry->pLimReAssocReq->eseTspecInfo.numTspecs) + { + tANI_U32 phyMode; + tSirMacESETSRSIE tsrsIE; + limGetPhyMode(pMac, &phyMode, psessionEntry); + + tsrsIE.tsid = 0; + if( phyMode == WNI_CFG_PHY_MODE_11G || phyMode == WNI_CFG_PHY_MODE_11A) + { + tsrsIE.rates[0] = TSRS_11AG_RATE_6MBPS; + } + else + { + tsrsIE.rates[0] = TSRS_11B_RATE_5_5MBPS; + } + PopulateDot11TSRSIE(pMac,&tsrsIE, &frm.ESETrafStrmRateSet, sizeof(tANI_U8)); + } + } +#endif + } + + if ( psessionEntry->htCapability && + pMac->lim.htCapabilityPresentInBeacon) + { + PopulateDot11fHTCaps( pMac, psessionEntry, &frm.HTCaps ); + } + limLog(pMac, LOG1, FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d, AMPDU Param: %x"), + frm.HTCaps.supportedChannelWidthSet, frm.HTCaps.mimoPowerSave, + frm.HTCaps.greenField, frm.HTCaps.shortGI20MHz, + frm.HTCaps.shortGI40MHz, + frm.HTCaps.dsssCckMode40MHz, frm.HTCaps.maxRxAMPDUFactor); +#if defined WLAN_FEATURE_VOWIFI_11R + if ( psessionEntry->pLimReAssocReq->bssDescription.mdiePresent && + (pMac->roam.roamSession[smeSessionId].ftSmeContext.addMDIE == TRUE) +#if defined FEATURE_WLAN_ESE + && !psessionEntry->isESEconnection +#endif + ) + { + PopulateMDIE( pMac, &frm.MobilityDomain, psessionEntry->pLimReAssocReq->bssDescription.mdie); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if ( psessionEntry->vhtCapability && + psessionEntry->vhtCapabilityPresentInBeacon) + { + limLog( pMac, LOG1, FL("Populate VHT IEs in Re-Assoc Request")); + PopulateDot11fVHTCaps( pMac, psessionEntry, &frm.VHTCaps ); + isVHTEnabled = eANI_BOOLEAN_TRUE; + PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); + } +#endif + + nStatus = dot11fGetPackedReAssocRequestSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Re-Association Request (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fReAssocRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Re-Association Re " + "quest(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog( pMac, LOG1, FL("FT IE Reassoc Req (%d)."), + pMac->roam.roamSession[smeSessionId].ftSmeContext.reassoc_ft_ies_length); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + if (psessionEntry->is11Rconnection) + { + ft_ies_length = + pMac->roam.roamSession[smeSessionId].ftSmeContext.reassoc_ft_ies_length; + } +#endif + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes+ft_ies_length, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, psessionEntry->limMlmState)); + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Re-As" + "sociation Request."), nBytes ); + goto end; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes + ft_ies_length, 0); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOG1); +#endif + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_REASSOC_REQ, + psessionEntry->limReAssocbssId,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Association Request (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + goto end; + } + + pMacHdr = (tpSirMacMgmtHdr) pFrame; + // That done, pack the ReAssoc Request: + nStatus = dot11fPackReAssocRequest( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Re-Association Reque" + "st (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + goto end; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a R" + "e-Association Request (0x%08x)."), nStatus ); + } + + PELOG3(limLog( pMac, LOG3, + FL("*** Sending Re-Association Request length %d %d to "), + nBytes, nPayload );) + if( psessionEntry->assocReq != NULL ) + { + vos_mem_free(psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; + } + + if( nAddIELen ) + { + vos_mem_copy( pFrame + sizeof(tSirMacMgmtHdr) + nPayload, + pAddIE, + nAddIELen ); + nPayload += nAddIELen; + } + + psessionEntry->assocReq = vos_mem_malloc(nPayload); + if ( NULL == psessionEntry->assocReq ) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc request"));) + psessionEntry->assocReqLen = 0; + } + else + { + //Store the Assoc request. This is sent to csr/hdd in join cnf response. + vos_mem_copy( psessionEntry->assocReq, pFrame + sizeof(tSirMacMgmtHdr), nPayload); + psessionEntry->assocReqLen = nPayload; + } + + if (psessionEntry->is11Rconnection && + pMac->roam.roamSession[smeSessionId].ftSmeContext.reassoc_ft_ies) + { + int i = 0; + + pBody = pFrame + nBytes; + for (i=0; iroam.roamSession[smeSessionId].ftSmeContext.reassoc_ft_ies[i]; + pBody++; + } + } + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOG1, FL("Re-assoc Req Frame is: ")); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, + (tANI_U8 *)pFrame, + (nBytes + ft_ies_length));) +#endif + + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if( NULL != psessionEntry->assocReq ) + { + vos_mem_free(psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; + } + + if (ft_ies_length) { + psessionEntry->assocReq = vos_mem_malloc(ft_ies_length); + if (NULL == psessionEntry->assocReq) { + limLog(pMac, LOGE, FL("Unable to alloc mem for FT IEs")); + psessionEntry->assocReqLen = 0; + } else { + /* Store the FT IEs. This is sent to csr/hdd in join cnf response */ + vos_mem_copy( psessionEntry->assocReq, + pMac->roam.roamSession[smeSessionId].ftSmeContext.reassoc_ft_ies, + ft_ies_length); + psessionEntry->assocReqLen = ft_ies_length; + } + } else { + limLog(pMac, LOG1, FL("FT IEs not present")); + psessionEntry->assocReqLen = 0; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOC_START_EVENT, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) (nBytes + ft_ies_length), + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send Re-Association Request" + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + goto end; + } + +end: + // Free up buffer allocated for mlmAssocReq + vos_mem_free( pMlmReassocReq ); + psessionEntry->pLimMlmReassocReq = NULL; + +} + +void limSendRetryReassocReqFrame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq, + tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; // keep sme + tLimMlmReassocReq *pTmpMlmReassocReq = NULL; + if(NULL == pTmpMlmReassocReq) + { + pTmpMlmReassocReq = vos_mem_malloc(sizeof(tLimMlmReassocReq)); + if ( NULL == pTmpMlmReassocReq ) goto end; + vos_mem_set( pTmpMlmReassocReq, sizeof(tLimMlmReassocReq), 0); + vos_mem_copy( pTmpMlmReassocReq, pMlmReassocReq, sizeof(tLimMlmReassocReq)); + } + + // Prepare and send Reassociation request frame + // start reassoc timer. + pMac->lim.limTimers.gLimReassocFailureTimer.sessionId = psessionEntry->peSessionId; + // Start reassociation failure timer + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_REASSOC_FAIL_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimReassocFailureTimer) + != TX_SUCCESS) + { + // Could not start reassoc failure timer. + // Log error + limLog(pMac, LOGP, + FL("could not start Reassociation failure timer")); + // Return Reassoc confirm with + // Resources Unavailable + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + goto end; + } + + limSendReassocReqWithFTIEsMgmtFrame(pMac, pTmpMlmReassocReq, psessionEntry); + return; + +end: + // Free up buffer allocated for reassocReq + if (pMlmReassocReq != NULL) + { + vos_mem_free(pMlmReassocReq); + pMlmReassocReq = NULL; + } + if (pTmpMlmReassocReq != NULL) + { + vos_mem_free(pTmpMlmReassocReq); + pTmpMlmReassocReq = NULL; + } + mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; + mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE sessio Id*/ + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + + limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + +void +limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq,tpPESession psessionEntry) +{ + static tDot11fReAssocRequest frm; + tANI_U16 caps; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tANI_U32 nBytes, nPayload, nStatus; + tANI_U8 fQosEnabled, fWmeEnabled, fWsmEnabled; + void *pPacket; + eHalStatus halstatus; + tANI_U16 nAddIELen; + tANI_U8 *pAddIE; + tANI_U8 *wpsIe = NULL; + tANI_U8 txFlag = 0; +#if defined WLAN_FEATURE_VOWIFI + tANI_U8 PowerCapsPopulated = FALSE; +#endif + tANI_U8 smeSessionId = 0; + tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + tpSirMacMgmtHdr pMacHdr; + + if(NULL == psessionEntry) + { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + /* check this early to avoid unncessary operation */ + if(NULL == psessionEntry->pLimReAssocReq) + { + return; + } + nAddIELen = psessionEntry->pLimReAssocReq->addIEAssoc.length; + pAddIE = psessionEntry->pLimReAssocReq->addIEAssoc.addIEdata; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + caps = pMlmReassocReq->capabilityInfo; +#if defined(FEATURE_WLAN_WAPI) + /* CR: 262463 : + According to WAPI standard: + 7.3.1.4 Capability Information field + In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0 in transmitted + Association or Reassociation management frames. APs ignore the Privacy subfield within received Association and + Reassociation management frames. */ + if ( psessionEntry->encryptType == eSIR_ED_WPI) + ((tSirMacCapabilityInfo *) &caps)->privacy = 0; +#endif + swapBitField16(caps, ( tANI_U16* )&frm.Capabilities ); + + frm.ListenInterval.interval = pMlmReassocReq->listenInterval; + + vos_mem_copy(( tANI_U8* )frm.CurrentAPAddress.mac, + ( tANI_U8* )psessionEntry->bssId, 6 ); + + PopulateDot11fSSID2( pMac, &frm.SSID ); + PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.SuppRates,psessionEntry); + + fQosEnabled = ( psessionEntry->limQosEnabled ) && + SIR_MAC_GET_QOS( psessionEntry->limReassocBssCaps ); + + fWmeEnabled = ( psessionEntry->limWmeEnabled ) && + LIM_BSS_CAPS_GET( WME, psessionEntry->limReassocBssQosCaps ); + + fWsmEnabled = ( psessionEntry->limWsmEnabled ) && fWmeEnabled && + LIM_BSS_CAPS_GET( WSM, psessionEntry->limReassocBssQosCaps ); + + + if ( psessionEntry->lim11hEnable && + psessionEntry->pLimReAssocReq->spectrumMgtIndicator == eSIR_TRUE ) + { +#if defined WLAN_FEATURE_VOWIFI + PowerCapsPopulated = TRUE; + PopulateDot11fPowerCaps( pMac, &frm.PowerCaps, LIM_REASSOC,psessionEntry); + PopulateDot11fSuppChannels( pMac, &frm.SuppChannels, LIM_REASSOC,psessionEntry); +#endif + } + +#if defined WLAN_FEATURE_VOWIFI + if( pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM( psessionEntry->limCurrentBssCaps ) ) + { + if (PowerCapsPopulated == FALSE) + { + PowerCapsPopulated = TRUE; + PopulateDot11fPowerCaps(pMac, &frm.PowerCaps, LIM_REASSOC, psessionEntry); + } + } +#endif + + if (fQosEnabled) + PopulateDot11fQOSCapsStation( pMac, &frm.QOSCapsStation ); + + PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.ExtSuppRates, psessionEntry ); + +#if defined WLAN_FEATURE_VOWIFI + if (pMac->rrm.rrmPEContext.rrmEnable) + PopulateDot11fRRMIe(pMac, &frm.RRMEnabledCap, psessionEntry); +#endif + // The join request *should* contain zero or one of the WPA and RSN + // IEs. The payload send along with the request is a + // 'tSirSmeJoinReq'; the IE portion is held inside a 'tSirRSNie': + + // typedef struct sSirRSNie + // { + // tANI_U16 length; + // tANI_U8 rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2]; + // } tSirRSNie, *tpSirRSNie; + + // So, we should be able to make the following two calls harmlessly, + // since they do nothing if they don't find the given IE in the + // bytestream with which they're provided. + + // The net effect of this will be to faithfully transmit whatever + // security IE is in the join request. + + // *However*, if we're associating for the purpose of WPS + // enrollment, and we've been configured to indicate that by + // eliding the WPA or RSN IE, we just skip this: + if( nAddIELen && pAddIE ) + { + wpsIe = limGetWscIEPtr(pMac, pAddIE, nAddIELen); + } + if ( NULL == wpsIe ) + { + PopulateDot11fRSNOpaque( pMac, &( psessionEntry->pLimReAssocReq->rsnIE ), + &frm.RSNOpaque ); + PopulateDot11fWPAOpaque( pMac, &( psessionEntry->pLimReAssocReq->rsnIE ), + &frm.WPAOpaque ); +#if defined(FEATURE_WLAN_WAPI) + PopulateDot11fWAPIOpaque( pMac, &( psessionEntry->pLimReAssocReq->rsnIE ), + &frm.WAPIOpaque ); +#endif // defined(FEATURE_WLAN_WAPI) + } + + // include WME EDCA IE as well + if (fWmeEnabled) { + if(!pMac->psOffloadEnabled) + PopulateDot11fWMMInfoStation( pMac, &frm.WMMInfoStation ); + else + PopulateDot11fWMMInfoStationPerSession(pMac, psessionEntry, + &frm.WMMInfoStation); + + if (fWsmEnabled) + PopulateDot11fWMMCaps(&frm.WMMCaps); + } + + if ( psessionEntry->htCapability && + pMac->lim.htCapabilityPresentInBeacon) + { + PopulateDot11fHTCaps( pMac, psessionEntry, &frm.HTCaps ); + } + limLog(pMac, LOG1, FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d, AMPDU Param: %x"), + frm.HTCaps.supportedChannelWidthSet, frm.HTCaps.mimoPowerSave, + frm.HTCaps.greenField, frm.HTCaps.shortGI20MHz, + frm.HTCaps.shortGI40MHz, + frm.HTCaps.dsssCckMode40MHz, frm.HTCaps.maxRxAMPDUFactor); +#ifdef WLAN_FEATURE_11AC + if ( psessionEntry->vhtCapability && + psessionEntry->vhtCapabilityPresentInBeacon) + { + limLog( pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request")); + PopulateDot11fVHTCaps( pMac, psessionEntry, &frm.VHTCaps ); + isVHTEnabled = eANI_BOOLEAN_TRUE; + } +#endif + + PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); + + nStatus = dot11fGetPackedReAssocRequestSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Re-Association Request (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fReAssocRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Re-Association Re " + "quest(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, psessionEntry->limMlmState)); + limLog(pMac, LOGP, FL("Failed to allocate %d bytes for a Re-As" + "sociation Request."), nBytes ); + goto end; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_REASSOC_REQ, + psessionEntry->limReAssocbssId,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for an Association Request (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + goto end; + } + + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + // That done, pack the Probe Request: + nStatus = dot11fPackReAssocRequest( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Re-Association Reque" + "st (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + goto end; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a R" + "e-Association Request (0x%08x)."), nStatus ); + } + + PELOG1(limLog( pMac, LOG1, FL("*** Sending Re-Association Request length %d" + "to "), + nBytes );) + + if( psessionEntry->assocReq != NULL ) + { + vos_mem_free(psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; + } + + if( nAddIELen ) + { + vos_mem_copy( pFrame + sizeof(tSirMacMgmtHdr) + nPayload, + pAddIE, + nAddIELen ); + nPayload += nAddIELen; + } + + psessionEntry->assocReq = vos_mem_malloc(nPayload); + if ( NULL == psessionEntry->assocReq ) + { + limLog(pMac, LOGE, FL("Unable to alloc mem to store assoc request")); + psessionEntry->assocReqLen = 0; + } + else + { + //Store the Assoc request. This is sent to csr/hdd in join cnf response. + vos_mem_copy(psessionEntry->assocReq, pFrame + sizeof(tSirMacMgmtHdr), nPayload); + psessionEntry->assocReqLen = nPayload; + } + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if(psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) + { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOC_START_EVENT, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) (sizeof(tSirMacMgmtHdr) + nPayload), + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send Re-Association Request" + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + goto end; + } + +end: + // Free up buffer allocated for mlmAssocReq + vos_mem_free( pMlmReassocReq ); + psessionEntry->pLimMlmReassocReq = NULL; + +} // limSendReassocReqMgmtFrame + +/** + * lim_auth_tx_complete_cnf()- Confirmation for + * Auth Sent over the air + * @mac_ctx:pointer to global mac + * @tx_complete : Sent status + * Return: eHAL_STATUS_SUCCESS in case of success + */ + +eHalStatus lim_auth_tx_complete_cnf(tpAniSirGlobal mac_ctx, + tANI_U32 tx_complete) +{ + limLog(mac_ctx, LOG1, + FL("tx_complete= %d"), tx_complete); + if (tx_complete) { + mac_ctx->auth_ack_status = LIM_AUTH_ACK_RCD_SUCCESS; + /* 'Change' timer for future activations */ + limDeactivateAndChangeTimer(mac_ctx, eLIM_AUTH_RETRY_TIMER); + } else { + mac_ctx->auth_ack_status = LIM_AUTH_ACK_RCD_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + +/** + * \brief Send an Authentication frame + * + * + * \param pMac Pointer to Global MAC structure + * + * \param pAuthFrameBody Pointer to Authentication frame structure that need + * to be sent + * + * \param peerMacAddr MAC address of the peer entity to which Authentication + * frame is destined + * + * \param wepBit Indicates whether wep bit to be set in FC while sending + * Authentication frame3 + * + * + * This function is called by limProcessMlmMessages(). Authentication frame + * is formatted and sent when this function is called. + * + * + */ + +void +limSendAuthMgmtFrame(tpAniSirGlobal pMac, + tpSirMacAuthFrameBody pAuthFrameBody, + tSirMacAddr peerMacAddr, + tANI_U8 wepBit, + tpPESession psessionEntry, + tAniBool waitForAck) +{ + tANI_U8 *pFrame, *pBody; + tANI_U32 frameLen = 0, bodyLen = 0; + tpSirMacMgmtHdr pMacHdr; + tANI_U16 i; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("Error: psession Entry is NULL")); + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + limLog(pMac, LOG1, + FL("Sending Auth seq# %d status %d (%d) to "MAC_ADDRESS_STR), + pAuthFrameBody->authTransactionSeqNumber, + pAuthFrameBody->authStatusCode, + (pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS), + MAC_ADDR_ARRAY(peerMacAddr)); + if (wepBit == LIM_WEP_IN_FC) + { + /// Auth frame3 to be sent with encrypted framebody + /** + * Allocate buffer for Authenticaton frame of size equal + * to management frame header length plus 2 bytes each for + * auth algorithm number, transaction number, status code, + * 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; + } // if (wepBit == LIM_WEP_IN_FC) + else + { + switch (pAuthFrameBody->authTransactionSeqNumber) + { + case SIR_MAC_AUTH_FRAME_1: + /** + * Allocate buffer for Authenticaton frame of size + * equal to management frame header length plus 2 bytes + * each for auth algorithm number, transaction number + * and status code. + */ + + frameLen = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + bodyLen = SIR_MAC_AUTH_CHALLENGE_OFFSET; + +#if defined WLAN_FEATURE_VOWIFI_11R + if (pAuthFrameBody->authAlgoNumber == eSIR_FT_AUTH) + { + if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq && + 0 != psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length) + { + frameLen += + psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length; + limLog(pMac, LOG3, FL("Auth frame, FTIES length added=%d"), + psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length); + } + else + { + limLog(pMac, LOG3, FL("Auth frame, Does not contain " + "FTIES!!!")); + frameLen += (2+SIR_MDIE_SIZE); + } + } +#endif + break; + + case SIR_MAC_AUTH_FRAME_2: + if ((pAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) || + ((pAuthFrameBody->authAlgoNumber == eSIR_SHARED_KEY) && + (pAuthFrameBody->authStatusCode != + eSIR_MAC_SUCCESS_STATUS))) + { + /** + * Allocate buffer for Authenticaton frame of size + * equal to management frame header length plus + * 2 bytes each for auth algorithm number, + * transaction number and status code. + */ + + frameLen = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + bodyLen = SIR_MAC_AUTH_CHALLENGE_OFFSET; + } + else + { + // Shared Key algorithm with challenge text + // to be sent + /** + * Allocate buffer for Authenticaton frame of size + * equal to management frame header length plus + * 2 bytes each for auth algorithm number, + * transaction number, status code and 128 bytes + * for challenge text. + */ + + frameLen = sizeof(tSirMacMgmtHdr) + + sizeof(tSirMacAuthFrame); + bodyLen = sizeof(tSirMacAuthFrameBody); + } + + break; + + case SIR_MAC_AUTH_FRAME_3: + /// Auth frame3 to be sent without encrypted framebody + /** + * Allocate buffer for Authenticaton frame of size equal + * to management frame header length plus 2 bytes each + * for auth algorithm number, transaction number and + * status code. + */ + + frameLen = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + bodyLen = SIR_MAC_AUTH_CHALLENGE_OFFSET; + + break; + + case SIR_MAC_AUTH_FRAME_4: + /** + * Allocate buffer for Authenticaton frame of size equal + * to management frame header length plus 2 bytes each + * for auth algorithm number, transaction number and + * status code. + */ + + frameLen = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + bodyLen = SIR_MAC_AUTH_CHALLENGE_OFFSET; + + break; + } // switch (pAuthFrameBody->authTransactionSeqNumber) + } // end if (wepBit == LIM_WEP_IN_FC) + + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )frameLen, ( void** ) &pFrame, ( void** ) &pPacket ); + + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + // Log error + limLog(pMac, LOGP, FL("call to bufAlloc failed for AUTH frame")); + + return; + } + + for (i = 0; i < frameLen; i++) + pFrame[i] = 0; + + // Prepare BD + if (limPopulateMacHeader(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_AUTH, peerMacAddr,psessionEntry->selfMacAddr) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("call to limPopulateMacHeader failed for " + "AUTH frame")); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return; + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + pMacHdr->fc.wep = wepBit; + + // Prepare BSSId + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + vos_mem_copy( (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) psessionEntry->bssId, + sizeof( tSirMacAddr )); + } + + /// Prepare Authentication frame body + pBody = pFrame + sizeof(tSirMacMgmtHdr); + + if (wepBit == LIM_WEP_IN_FC) + { + vos_mem_copy(pBody, (tANI_U8 *) pAuthFrameBody, bodyLen); + + PELOG1(limLog(pMac, LOG1, + FL("*** Sending Auth seq# 3 status %d (%d) to"MAC_ADDRESS_STR), + pAuthFrameBody->authStatusCode, + (pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS), + MAC_ADDR_ARRAY(pMacHdr->da));) + + } + else + { + *((tANI_U16 *)(pBody)) = + sirSwapU16ifNeeded(pAuthFrameBody->authAlgoNumber); + pBody += sizeof(tANI_U16); + bodyLen -= sizeof(tANI_U16); + + *((tANI_U16 *)(pBody)) = + sirSwapU16ifNeeded(pAuthFrameBody->authTransactionSeqNumber); + pBody += sizeof(tANI_U16); + bodyLen -= sizeof(tANI_U16); + + *((tANI_U16 *)(pBody)) = + sirSwapU16ifNeeded(pAuthFrameBody->authStatusCode); + pBody += sizeof(tANI_U16); + bodyLen -= sizeof(tANI_U16); + if ( bodyLen <= (sizeof (pAuthFrameBody->type) + + sizeof (pAuthFrameBody->length) + + sizeof (pAuthFrameBody->challengeText))) + vos_mem_copy(pBody, (tANI_U8 *) &pAuthFrameBody->type, bodyLen); + +#if defined WLAN_FEATURE_VOWIFI_11R + if ((pAuthFrameBody->authAlgoNumber == eSIR_FT_AUTH) && + (pAuthFrameBody->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_1)) + { + + int i = 0; + if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq) + { + if (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length) + { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG2(limLog(pMac, LOG2, FL("Auth1 Frame FTIE is: ")); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, + (tANI_U8 *)pBody, + (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length));) +#endif + for (i = 0; + i < psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length; + i++) + { + *pBody = + psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[i]; + pBody++; + } + } + else + { + /* MDID attr is 54*/ + *pBody = 54; + pBody++; + *pBody = SIR_MDIE_SIZE; + pBody++; + if (NULL != + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) + { + for(i=0;iftPEContext.pFTPreAuthReq->pbssDescription->mdie[i]; + pBody++; + } + } + } + } + } +#endif + + PELOG1(limLog(pMac, LOG1, + FL("*** Sending Auth seq# %d status %d (%d) to "MAC_ADDRESS_STR), + pAuthFrameBody->authTransactionSeqNumber, + pAuthFrameBody->authStatusCode, + (pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS), + MAC_ADDR_ARRAY(pMacHdr->da));) + } + PELOG2(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pFrame, frameLen);) + + if( (SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) || + (psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE) +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + || ((NULL != psessionEntry->ftPEContext.pFTPreAuthReq) && + (SIR_BAND_5_GHZ == + limGetRFBand(psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum))) +#endif + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if(psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) + { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + + if (eSIR_TRUE == waitForAck) { + + pMac->auth_ack_status = LIM_AUTH_ACK_NOT_RCD; + halstatus = halTxFrameWithTxComplete(pMac, pPacket, + (tANI_U16)frameLen, + HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, + 7, limTxComplete, pFrame, + lim_auth_tx_complete_cnf, + txFlag, smeSessionId, false); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if (!HAL_STATUS_SUCCESS(halstatus)) { + limLog(pMac, LOGE, + FL("*** Could not send Auth frame, retCode=%X ***"), + halstatus); + pMac->auth_ack_status = LIM_AUTH_ACK_RCD_FAILURE; + /* Pkt will be freed up by the callback*/ + } + } else { + /* Queue Authentication frame in high priority WQ */ + halstatus = halTxFrame(pMac, pPacket, ( tANI_U16 ) frameLen, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if (!HAL_STATUS_SUCCESS(halstatus)) { + limLog(pMac, LOGE, + FL("*** Could not send Auth frame, retCode=%X ***"), + halstatus); + + /* Pkt will be freed up by the callback*/ + } + } + return; +} /*** end limSendAuthMgmtFrame() ***/ + +eHalStatus limSendDeauthCnf(tpAniSirGlobal pMac) +{ + tANI_U16 aid; + tpDphHashNode pStaDs; + tLimMlmDeauthReq *pMlmDeauthReq; + tLimMlmDeauthCnf mlmDeauthCnf; + tpPESession psessionEntry; + + pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (pMlmDeauthReq) + { + if (tx_timer_running(&pMac->lim.limTimers.gLimDeauthAckTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER); + } + + if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDeauthReq->sessionId))== NULL) + { + + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for given sessionId"));) + mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + pStaDs = dphLookupHashEntry(pMac, pMlmDeauthReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + + /// Receive path cleanup with dummy packet + limFTCleanupPreAuthInfo(pMac,psessionEntry); + limCleanupRxPath(pMac, pStaDs,psessionEntry); +#ifdef WLAN_FEATURE_VOWIFI_11R + if ((psessionEntry->limSystemRole == eLIM_STA_ROLE) && + ( +#ifdef FEATURE_WLAN_ESE + (psessionEntry->isESEconnection) || +#endif +#ifdef FEATURE_WLAN_LFR + (psessionEntry->isFastRoamIniFeatureEnabled) || +#endif + (psessionEntry->is11Rconnection ))) { + PELOGE(limLog(pMac, LOGE, + FL("FT Preauth Session (%p,%d) Cleanup" + " Deauth reason %d Trigger = %d"), + psessionEntry, psessionEntry->peSessionId, + pMlmDeauthReq->reasonCode, + pMlmDeauthReq->deauthTrigger);); + limFTCleanup(pMac, psessionEntry); + } else { + PELOGE(limLog(pMac, LOGE, + FL("No FT Preauth Session Cleanup in role %d" +#ifdef FEATURE_WLAN_ESE + " isESE %d" +#endif +#ifdef FEATURE_WLAN_LFR + " isLFR %d" +#endif + " is11r %d, Deauth reason %d Trigger = %d"), + psessionEntry->limSystemRole, +#ifdef FEATURE_WLAN_ESE + psessionEntry->isESEconnection, +#endif +#ifdef FEATURE_WLAN_LFR + psessionEntry->isFastRoamIniFeatureEnabled, +#endif + psessionEntry->is11Rconnection, + pMlmDeauthReq->reasonCode, + pMlmDeauthReq->deauthTrigger);); + } +#endif + /// Free up buffer allocated for mlmDeauthReq + vos_mem_free(pMlmDeauthReq); + pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; + } + return eHAL_STATUS_SUCCESS; +end: + vos_mem_copy( (tANI_U8 *) &mlmDeauthCnf.peerMacAddr, + (tANI_U8 *) pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)); + mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger; + mlmDeauthCnf.aid = pMlmDeauthReq->aid; + mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId; + + // Free up buffer allocated + // for mlmDeauthReq + vos_mem_free(pMlmDeauthReq); + + limPostSmeMessage(pMac, + LIM_MLM_DEAUTH_CNF, + (tANI_U32 *) &mlmDeauthCnf); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) +{ + tANI_U16 aid; + tpDphHashNode pStaDs; + tLimMlmDisassocCnf mlmDisassocCnf; + tpPESession psessionEntry; + tLimMlmDisassocReq *pMlmDisassocReq; + + pMlmDisassocReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + if (pMlmDisassocReq) + { + if (tx_timer_running(&pMac->lim.limTimers.gLimDisassocAckTimer)) + { + limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER); + } + + if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDisassocReq->sessionId))== NULL) + { + + PELOGE(limLog(pMac, LOGE, + FL("session does not exist for given sessionId"));) + mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + pStaDs = dphLookupHashEntry(pMac, pMlmDisassocReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + limLog(pMac, LOGE, + FL("StaDs Null")); + mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + /// Receive path cleanup with dummy packet + if(eSIR_SUCCESS != limCleanupRxPath(pMac, pStaDs, psessionEntry)) + { + mlmDisassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + limLog(pMac, LOGE, + FL("CleanupRxPath error")); + goto end; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (LIM_IS_STA_ROLE(psessionEntry) && + ( +#ifdef FEATURE_WLAN_ESE + (psessionEntry->isESEconnection ) || +#endif +#ifdef FEATURE_WLAN_LFR + (psessionEntry->isFastRoamIniFeatureEnabled ) || +#endif + (psessionEntry->is11Rconnection )) && + (pMlmDisassocReq->reasonCode != + eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) + { + PELOGE(limLog(pMac, LOG1, + FL("FT Preauth Session (%p,%d) Clean up"), + psessionEntry, psessionEntry->peSessionId);); + +#if defined WLAN_FEATURE_VOWIFI_11R + /* Delete FT session if there exists one */ + limFTCleanupPreAuthInfo(pMac, psessionEntry); +#endif + } + else + { + PELOGE(limLog(pMac, LOGE, + FL("No FT Preauth Session Clean up in role %d" +#ifdef FEATURE_WLAN_ESE + " isESE %d" +#endif +#ifdef FEATURE_WLAN_LFR + " isLFR %d" +#endif + " is11r %d reason %d"), + GET_LIM_SYSTEM_ROLE(psessionEntry), +#ifdef FEATURE_WLAN_ESE + psessionEntry->isESEconnection, +#endif +#ifdef FEATURE_WLAN_LFR + psessionEntry->isFastRoamIniFeatureEnabled, +#endif + psessionEntry->is11Rconnection, + pMlmDisassocReq->reasonCode);); + } +#endif + /// Free up buffer allocated for mlmDisassocReq + vos_mem_free(pMlmDisassocReq); + pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL; + return eHAL_STATUS_SUCCESS; + } + else + { + return eHAL_STATUS_SUCCESS; + } +end: + vos_mem_copy( (tANI_U8 *) &mlmDisassocCnf.peerMacAddr, + (tANI_U8 *) pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)); + mlmDisassocCnf.aid = pMlmDisassocReq->aid; + mlmDisassocCnf.disassocTrigger = pMlmDisassocReq->disassocTrigger; + + /* Update PE session ID*/ + mlmDisassocCnf.sessionId = pMlmDisassocReq->sessionId; + + if(pMlmDisassocReq != NULL) + { + /// Free up buffer allocated for mlmDisassocReq + vos_mem_free(pMlmDisassocReq); + pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL; + } + + limPostSmeMessage(pMac, + LIM_MLM_DISASSOC_CNF, + (tANI_U32 *) &mlmDisassocCnf); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus limDisassocTxCompleteCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess) +{ + return limSendDisassocCnf(pMac); +} + +eHalStatus limDeauthTxCompleteCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess) +{ + return limSendDeauthCnf(pMac); +} + +/** + * \brief This function is called to send Disassociate frame. + * + * + * \param pMac Pointer to Global MAC structure + * + * \param nReason Indicates the reason that need to be sent in + * Disassociation frame + * + * \param peerMacAddr MAC address of the STA to which Disassociation frame is + * sent + * + * + */ + +void +limSendDisassocMgmtFrame(tpAniSirGlobal pMac, + tANI_U16 nReason, + tSirMacAddr peer, + tpPESession psessionEntry, + tANI_BOOLEAN waitForAck) +{ + tDot11fDisassociation frm; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U32 val = 0; + tANI_U8 smeSessionId = 0; + if(NULL == psessionEntry) + { + return; + } + + /* + * In case when cac timer is running for this SAP session then + * avoid sending disassoc out. It is violation of dfs specification. + */ + if (((psessionEntry->pePersona == VOS_STA_SAP_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) && + (VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("CAC timer is running, drop disassoc from going out")); + return; + } + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0); + + frm.Reason.code = nReason; + + nStatus = dot11fGetPackedDisassociationSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Disassociation (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fDisassociation ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Disassociation " + "(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Dis" + "association."), nBytes ); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_DISASSOC, peer,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Disassociation (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; // just allocated... + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + // Prepare the BSSID + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11fPackDisassociation( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Disassociation (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a D" + "isassociation (0x%08x)."), nStatus ); + } + + limLog( pMac, LOG1, FL("***Sessionid %d Sending Disassociation frame with " + "reason %u and waitForAck %d to "MAC_ADDRESS_STR" ,From " + MAC_ADDRESS_STR), psessionEntry->peSessionId, nReason, waitForAck, + MAC_ADDR_ARRAY(pMacHdr->da), + MAC_ADDR_ARRAY(psessionEntry->selfMacAddr)); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if((psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + + if (waitForAck) + { + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + // Queue Disassociation frame in high priority WQ + /* get the duration from the request */ + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, limDisassocTxCompleteCnf, + txFlag, smeSessionId, false ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + + val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT); + + if (tx_timer_change( + &pMac->lim.limTimers.gLimDisassocAckTimer, val, 0) + != TX_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to change Disassoc ack Timer val")); + return; + } + else if(TX_SUCCESS != tx_timer_activate( + &pMac->lim.limTimers.gLimDisassocAckTimer)) + { + limLog(pMac, LOGP, + FL("Unable to activate Disassoc ack Timer")); + limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER); + return; + } + } + else + { + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + // Queue Disassociation frame in high priority WQ + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send Disassociation " + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + return; + } + } +} // End limSendDisassocMgmtFrame. + +/** + * \brief This function is called to send a Deauthenticate frame + * + * + * \param pMac Pointer to global MAC structure + * + * \param nReason Indicates the reason that need to be sent in the + * Deauthenticate frame + * + * \param peeer address of the STA to which the frame is to be sent + * + * + */ + +void +limSendDeauthMgmtFrame(tpAniSirGlobal pMac, + tANI_U16 nReason, + tSirMacAddr peer, + tpPESession psessionEntry, + tANI_BOOLEAN waitForAck) +{ + tDot11fDeAuth frm; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U32 val = 0; +#ifdef FEATURE_WLAN_TDLS + tANI_U16 aid; + tpDphHashNode pStaDs; +#endif + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + return; + } + + /* + * In case when cac timer is running for this SAP session then + * avoid deauth frame out. It is violation of dfs specification. + */ + if (((psessionEntry->pePersona == VOS_STA_SAP_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) && + (VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("CAC timer is running, drop the deauth from going out")); + return; + } + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* ) &frm, sizeof( frm ), 0 ); + + frm.Reason.code = nReason; + + nStatus = dot11fGetPackedDeAuthSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a De-Authentication (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fDeAuth ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a De-Authentication " + "(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )nBytes, ( void** ) &pFrame, + ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a De-" + "Authentication."), nBytes ); + return; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_DEAUTH, peer,psessionEntry->selfMacAddr); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a De-Authentication (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; // just allocated... + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + // Prepare the BSSID + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11fPackDeAuth( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a DeAuthentication (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pFrame, ( void* ) pPacket ); + return; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a D" + "e-Authentication (0x%08x)."), nStatus ); + } + limLog( pMac, LOG1, FL("***Sessionid %d Sending Deauth frame with " + "reason %u and waitForAck %d to "MAC_ADDRESS_STR" ,From " + MAC_ADDRESS_STR), psessionEntry->peSessionId, nReason, waitForAck, + MAC_ADDR_ARRAY(pMacHdr->da), + MAC_ADDR_ARRAY(psessionEntry->selfMacAddr)); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if((psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + +#ifdef FEATURE_WLAN_TDLS + pStaDs = dphLookupHashEntry(pMac, peer, &aid, &psessionEntry->dph.dphHashTable); +#endif + + if (waitForAck) + { + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + // Queue Disassociation frame in high priority WQ + halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, limDeauthTxCompleteCnf, txFlag, + smeSessionId, false ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send De-Authentication " + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback limTxComplete + + /*Call limProcessDeauthAckTimeout which will send + * DeauthCnf for this frame + */ + limProcessDeauthAckTimeout(pMac); + return; + } + + val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT); + + if (tx_timer_change( + &pMac->lim.limTimers.gLimDeauthAckTimer, val, 0) + != TX_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to change Deauth ack Timer val")); + return; + } + else if(TX_SUCCESS != tx_timer_activate( + &pMac->lim.limTimers.gLimDeauthAckTimer)) + { + limLog(pMac, LOGP, + FL("Unable to activate Deauth ack Timer")); + limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER); + return; + } + } + else + { + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); +#ifdef FEATURE_WLAN_TDLS + if ((NULL != pStaDs) && (STA_ENTRY_TDLS_PEER == pStaDs->staType)) + { + // Queue Disassociation frame in high priority WQ + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_IBSS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + } + else + { +#endif + // Queue Disassociation frame in high priority WQ + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); +#ifdef FEATURE_WLAN_TDLS + } +#endif + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send De-Authentication " + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + return; + } + } + +} // End limSendDeauthMgmtFrame. + + + + +/** + * \brief Send a Channel Switch Announcement + * + * + * \param pMac Pointer to the global MAC datastructure + * + * \param peer MAC address to which this frame will be sent + * + * \param nMode + * + * \param nNewChannel + * + * \param nCount + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, + tSirMacAddr peer, + tANI_U8 nMode, + tANI_U8 nNewChannel, + tANI_U8 nCount, + tpPESession psessionEntry ) +{ + tDot11fChannelSwitch frm; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus;//, nCfg; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + + tANI_U8 smeSessionId = 0; + + if (psessionEntry == NULL ) + { + PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT; + frm.Action.action = SIR_MAC_ACTION_CHANNEL_SWITCH_ID; + frm.ChanSwitchAnn.switchMode = nMode; + frm.ChanSwitchAnn.newChannel = nNewChannel; + frm.ChanSwitchAnn.switchCount = nCount; + frm.ChanSwitchAnn.present = 1; + + nStatus = dot11fGetPackedChannelSwitchSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Channel Switch (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fChannelSwitch ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Channel Switch (0x" + "%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" + " Report."), nBytes ); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + vos_mem_copy( (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) psessionEntry->bssId, + sizeof( tSirMacAddr )); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Channel Switch (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // just allocated... + } + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11fPackChannelSwitch( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a C" + "hannel Switch (0x%08x)."), nStatus ); + } + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send a Channel Switch " + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} // End limSendChannelSwitchMgmtFrame. + +/** + * lim_send_extended_chan_switch_action_frame()- function to send ECSA + * action frame over the air . + * @mac_ctx: pointer to global mac structure + * @peer: Destination mac. + * @mode: channel switch mode + * @new_op_class: new op class + * @new_channel: new channel to switch + * @count: channel switch count + * + * This function is called to send ECSA frame. + * + * Return: success if frame is sent else return failure + */ + +tSirRetStatus +lim_send_extended_chan_switch_action_frame(tpAniSirGlobal mac_ctx, + tSirMacAddr peer, uint8_t mode, uint8_t new_op_class, + uint8_t new_channel, uint8_t count, tpPESession session_entry) +{ + tDot11fext_channel_switch_action_frame frm; + uint8_t *frame; + tSirRetStatus sir_status; + tpSirMacMgmtHdr mac_hdr; + uint32_t num_bytes,n_payload, status; + void *packet; + eHalStatus hal_status; + uint8_t txFlag = 0; + uint8_t sme_session_id = 0; + + if (session_entry == NULL) { + limLog(mac_ctx, LOGE, FL("Session entry is NULL!!!")); + return eSIR_FAILURE; + } + + sme_session_id = session_entry->smeSessionId; + + vos_mem_set(&frm, sizeof(frm), 0); + + frm.Category.category = SIR_MAC_ACTION_PUBLIC_USAGE; + frm.Action.action = SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID; + + frm.ext_chan_switch_ann_action.switch_mode = mode; + frm.ext_chan_switch_ann_action.op_class = new_op_class; + frm.ext_chan_switch_ann_action.new_channel = new_channel; + frm.ext_chan_switch_ann_action.switch_count = count; + + + status = dot11fGetPackedext_channel_switch_action_frameSize(mac_ctx, + &frm, &n_payload); + if (DOT11F_FAILED(status)) { + limLog(mac_ctx, LOGP, + FL("Failed to get packed size for Channel Switch 0x%08x."), + status); + /* We'll fall back on the worst case scenario*/ + n_payload = sizeof(tDot11fext_channel_switch_action_frame); + } + else if (DOT11F_WARNED(status)) { + limLog(mac_ctx, LOGW, + FL("There were warnings while calculating the packed size for a Ext Channel Switch (0x%08x)."), + status); + } + + num_bytes = n_payload + sizeof(tSirMacMgmtHdr); + + hal_status = palPktAlloc(mac_ctx->hHdd, HAL_TXRX_FRM_802_11_MGMT, + (uint16_t)num_bytes, (void**) &frame, (void**) &packet); + + if (!HAL_STATUS_SUCCESS(hal_status)) { + limLog(mac_ctx, LOGP, + FL("Failed to allocate %d bytes for a Ext Channel Switch."), + num_bytes); + return eSIR_FAILURE; + } + + /* Paranoia*/ + vos_mem_set(frame, num_bytes, 0); + + /* Next, we fill out the buffer descriptor */ + sir_status = limPopulateMacHeader(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, session_entry->selfMacAddr); + mac_hdr = (tpSirMacMgmtHdr) frame; + vos_mem_copy((uint8_t *) mac_hdr->bssId, + (uint8_t *) session_entry->bssId, + sizeof(tSirMacAddr)); + if (eSIR_SUCCESS != sir_status) { + limLog(mac_ctx, LOGE, + FL("Failed to populate the buffer descriptor for a Ext Channel Switch %d."), + sir_status); + palPktFree(mac_ctx->hHdd, HAL_TXRX_FRM_802_11_MGMT, + (void*) frame, (void*) packet); + return eSIR_FAILURE; + } + + status = dot11fPackext_channel_switch_action_frame( mac_ctx, &frm, + frame + sizeof(tSirMacMgmtHdr), n_payload, &n_payload); + if (DOT11F_FAILED(status)) { + limLog(mac_ctx, LOGE, + FL("Failed to pack a Channel Switch 0x%08x."), + status); + palPktFree(mac_ctx->hHdd, HAL_TXRX_FRM_802_11_MGMT, + (void*) frame, (void*) packet); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + limLog(mac_ctx, LOGW, + FL("There were warnings while packing a Channel Switch 0x%08x."), + status); + } + + if ((SIR_BAND_5_GHZ == limGetRFBand(session_entry->currentOperChannel)) + || (session_entry->pePersona == VOS_P2P_CLIENT_MODE) || + (session_entry->pePersona == VOS_P2P_GO_MODE)) { + + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + limLog(mac_ctx, LOG1, + FL("Send Ext channel Switch to :"MAC_ADDRESS_STR" with swcount %d, swmode %d , newchannel %d newops %d"), + MAC_ADDR_ARRAY(mac_hdr->da), + frm.ext_chan_switch_ann_action.switch_count, + frm.ext_chan_switch_ann_action.switch_mode, + frm.ext_chan_switch_ann_action.new_channel, + frm.ext_chan_switch_ann_action.op_class); + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + session_entry->peSessionId, mac_hdr->fc.subType)); + hal_status = halTxFrame(mac_ctx, packet, (uint16_t) num_bytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, frame, + txFlag, sme_session_id); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + session_entry->peSessionId, hal_status)); + if (!HAL_STATUS_SUCCESS(hal_status)) { + limLog(mac_ctx, LOGE, + FL("Failed to send a Ext Channel Switch %X!"), + sir_status); + /* Pkt will be freed up by the callback */ + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +}/* End lim_send_extended_chan_switch_action_frame */ + + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, + tSirMacAddr peer, + tANI_U8 nMode, + tpPESession psessionEntry ) +{ + tDot11fOperatingMode frm; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload = 0, nStatus;//, nCfg; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + + tANI_U8 smeSessionId = 0; + + if (psessionEntry == NULL ) + { + PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + frm.Category.category = SIR_MAC_ACTION_VHT; + frm.Action.action = SIR_MAC_VHT_OPMODE_NOTIFICATION; + frm.OperatingMode.chanWidth = nMode; + frm.OperatingMode.rxNSS = 0; + frm.OperatingMode.rxNSSType = 0; + + nStatus = dot11fGetPackedOperatingModeSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Operating Mode (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fOperatingMode); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Operating Mode (0x" + "%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Operating Mode" + " Report."), nBytes ); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + + // Next, we fill out the buffer descriptor: + if(psessionEntry->pePersona == VOS_STA_SAP_MODE) { + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + } else + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, psessionEntry->bssId, psessionEntry->selfMacAddr); + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + vos_mem_copy( (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) psessionEntry->bssId, + sizeof( tSirMacAddr )); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Operating Mode (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // just allocated... + } + nStatus = dot11fPackOperatingMode( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Operating Mode (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a Operating Mode" + " (0x%08x)."), nStatus ); + } + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send a Channel Switch " + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +/** + * \brief Send a VHT Channel Switch Announcement + * + * + * \param pMac Pointer to the global MAC datastructure + * + * \param peer MAC address to which this frame will be sent + * + * \param nChanWidth + * + * \param nNewChannel + * + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, + tSirMacAddr peer, + tANI_U8 nChanWidth, + tANI_U8 nNewChannel, + tANI_U8 ncbMode, + tpPESession psessionEntry ) +{ + tDot11fChannelSwitch frm; + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus;//, nCfg; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + + tANI_U8 smeSessionId = 0; + + if (psessionEntry == NULL ) + { + PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + + frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT; + frm.Action.action = SIR_MAC_ACTION_CHANNEL_SWITCH_ID; + frm.ChanSwitchAnn.switchMode = 1; + frm.ChanSwitchAnn.newChannel = nNewChannel; + frm.ChanSwitchAnn.switchCount = 1; + frm.sec_chan_offset_ele.secondaryChannelOffset = limGetHTCBState(ncbMode); + frm.sec_chan_offset_ele.present = 1; + frm.WiderBWChanSwitchAnn.newChanWidth = nChanWidth; + frm.WiderBWChanSwitchAnn.newCenterChanFreq0 = limGetCenterChannel(pMac,nNewChannel,ncbMode,nChanWidth); + frm.WiderBWChanSwitchAnn.newCenterChanFreq1 = 0; + frm.ChanSwitchAnn.present = 1; + frm.WiderBWChanSwitchAnn.present = 1; + + nStatus = dot11fGetPackedChannelSwitchSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Channel Switch (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fChannelSwitch ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Channel Switch (0x" + "%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" + " Report."), nBytes ); + return eSIR_FAILURE; + } + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + vos_mem_copy( (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) psessionEntry->bssId, + sizeof( tSirMacAddr )); + if ( eSIR_SUCCESS != nSirStatus ) + { + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Channel Switch (%d)."), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // just allocated... + } + nStatus = dot11fPackChannelSwitch( pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x)."), + nStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while packing a C" + "hannel Switch (0x%08x)."), nStatus ); + } + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGE, FL("Failed to send a Channel Switch " + "(%X)!"), + nSirStatus ); + //Pkt will be freed up by the callback + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} // End limSendVHTChannelSwitchMgmtFrame. + + + +#endif + +/** + * \brief Send an ADDBA Req Action Frame to peer + * + * \sa limSendAddBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pMlmAddBAReq A pointer to tLimMlmAddBAReq. This contains + * the necessary parameters reqd by PE send the ADDBA Req Action + * Frame to the peer + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, + tpLimMlmAddBAReq pMlmAddBAReq, tpPESession psessionEntry) +{ + tDot11fAddBAReq frmAddBAReq; + tANI_U8 *pAddBAReqBuffer = NULL; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 frameLen = 0, nStatus, nPayload; + tSirRetStatus statusCode; + eHalStatus halStatus; + void *pPacket; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + return eSIR_FAILURE; + } + + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( (void *) &frmAddBAReq, sizeof( frmAddBAReq ), 0); + + // Category - 3 (BA) + frmAddBAReq.Category.category = SIR_MAC_ACTION_BLKACK; + + // Action - 0 (ADDBA Req) + frmAddBAReq.Action.action = SIR_MAC_BLKACK_ADD_REQ; + + // FIXME - Dialog Token, generalize this... + frmAddBAReq.DialogToken.token = pMlmAddBAReq->baDialogToken; + + // Fill the ADDBA Parameter Set + frmAddBAReq.AddBAParameterSet.tid = pMlmAddBAReq->baTID; + frmAddBAReq.AddBAParameterSet.policy = pMlmAddBAReq->baPolicy; + frmAddBAReq.AddBAParameterSet.bufferSize = pMlmAddBAReq->baBufferSize; + + // BA timeout + // 0 - indicates no BA timeout + frmAddBAReq.BATimeout.timeout = pMlmAddBAReq->baTimeout; + + // BA Starting Sequence Number + // Fragment number will always be zero + if (pMlmAddBAReq->baSSN < LIM_TX_FRAMES_THRESHOLD_ON_CHIP) { + pMlmAddBAReq->baSSN = LIM_TX_FRAMES_THRESHOLD_ON_CHIP; + } + + frmAddBAReq.BAStartingSequenceControl.ssn = + pMlmAddBAReq->baSSN - LIM_TX_FRAMES_THRESHOLD_ON_CHIP; + + nStatus = dot11fGetPackedAddBAReqSize( pMac, &frmAddBAReq, &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGW, + FL( "Failed to calculate the packed size for " + "an ADDBA Request (0x%08x)."), + nStatus ); + + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fAddBAReq ); + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while calculating " + "the packed size for an ADDBA Req (0x%08x)."), + nStatus ); + } + + // Add the MGMT header to frame length + frameLen = nPayload + sizeof( tSirMacMgmtHdr ); + + // Need to allocate a buffer for ADDBA AF + if( eHAL_STATUS_SUCCESS != + (halStatus = palPktAlloc( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (tANI_U16) frameLen, + (void **) &pAddBAReqBuffer, + (void **) &pPacket ))) + { + // Log error + limLog( pMac, LOGP, + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), + frameLen, + halStatus ); + + statusCode = eSIR_MEM_ALLOC_FAILED; + goto returnAfterError; + } + + vos_mem_set( (void *) pAddBAReqBuffer, frameLen, 0 ); + + // Copy necessary info to BD + if( eSIR_SUCCESS != + (statusCode = limPopulateMacHeader( pMac, + pAddBAReqBuffer, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + pMlmAddBAReq->peerMacAddr,psessionEntry->selfMacAddr))) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pAddBAReqBuffer; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, pMlmAddBAReq->peerMacAddr, pMacHdr); +#endif + + // Now, we're ready to "pack" the frames + nStatus = dot11fPackAddBAReq( pMac, + &frmAddBAReq, + pAddBAReqBuffer + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an ADDBA Req (0x%08x)." ), + nStatus ); + + // FIXME - Need to convert to tSirRetStatus + statusCode = eSIR_FAILURE; + goto returnAfterError; + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing an ADDBA Req (0x%08x)."), + nStatus ); + } + + limLog( pMac, LOG1, FL( "Sending an ADDBA REQ to "MAC_ADDRESS_STR " with" + " tid = %d policy = %d buffsize = %d " + " amsduSupported = %d"), + MAC_ADDR_ARRAY(pMlmAddBAReq->peerMacAddr), + frmAddBAReq.AddBAParameterSet.tid, + frmAddBAReq.AddBAParameterSet.policy, + frmAddBAReq.AddBAParameterSet.bufferSize, + frmAddBAReq.AddBAParameterSet.amsduSupported); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halStatus = halTxFrame( pMac, + pPacket, + (tANI_U16) frameLen, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pAddBAReqBuffer, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halStatus)); + if (eHAL_STATUS_SUCCESS != halStatus ) + { + limLog( pMac, LOGE, + FL( "halTxFrame FAILED! Status [%d]"), + halStatus ); + + // FIXME - Need to convert eHalStatus to tSirRetStatus + statusCode = eSIR_FAILURE; + //Pkt will be freed up by the callback + return statusCode; + } + else + return eSIR_SUCCESS; + +returnAfterError: + + // Release buffer, if allocated + if( NULL != pAddBAReqBuffer ) + palPktFree( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (void *) pAddBAReqBuffer, + (void *) pPacket ); + + return statusCode; +} + +/** + * \brief Send an ADDBA Rsp Action Frame to peer + * + * \sa limSendAddBARsp + * + * \param pMac The global tpAniSirGlobal object + * + * \param pMlmAddBARsp A pointer to tLimMlmAddBARsp. This contains + * the necessary parameters reqd by PE send the ADDBA Rsp Action + * Frame to the peer + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, + tpLimMlmAddBARsp pMlmAddBARsp, + tpPESession psessionEntry) +{ + tDot11fAddBARsp frmAddBARsp; + tANI_U8 *pAddBARspBuffer = NULL; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 frameLen = 0, nStatus, nPayload; + tSirRetStatus statusCode; + eHalStatus halStatus; + void *pPacket; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + + vos_mem_set( (void *) &frmAddBARsp, sizeof( frmAddBARsp ), 0); + + // Category - 3 (BA) + frmAddBARsp.Category.category = SIR_MAC_ACTION_BLKACK; + // Action - 1 (ADDBA Rsp) + frmAddBARsp.Action.action = SIR_MAC_BLKACK_ADD_RSP; + + // Should be same as the one we received in the ADDBA Req + frmAddBARsp.DialogToken.token = pMlmAddBARsp->baDialogToken; + + // ADDBA Req status + frmAddBARsp.Status.status = pMlmAddBARsp->addBAResultCode; + + // Fill the ADDBA Parameter Set as provided by caller + frmAddBARsp.AddBAParameterSet.tid = pMlmAddBARsp->baTID; + frmAddBARsp.AddBAParameterSet.policy = pMlmAddBARsp->baPolicy; + frmAddBARsp.AddBAParameterSet.bufferSize = pMlmAddBARsp->baBufferSize; + + if (psessionEntry->max_amsdu_num > 0) + { + frmAddBARsp.AddBAParameterSet.amsduSupported = + psessionEntry->amsduSupportedInBA; + } + else + { + frmAddBARsp.AddBAParameterSet.amsduSupported = 0; + } + + // BA timeout + // 0 - indicates no BA timeout + frmAddBARsp.BATimeout.timeout = pMlmAddBARsp->baTimeout; + + nStatus = dot11fGetPackedAddBARspSize( pMac, &frmAddBARsp, &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGW, + FL( "Failed to calculate the packed size for " + "an ADDBA Response (0x%08x)."), + nStatus ); + + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fAddBARsp ); + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while calculating " + "the packed size for an ADDBA Rsp (0x%08x)."), + nStatus ); + } + + // Need to allocate a buffer for ADDBA AF + frameLen = nPayload + sizeof( tSirMacMgmtHdr ); + + // Allocate shared memory + if( eHAL_STATUS_SUCCESS != + (halStatus = palPktAlloc( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (tANI_U16) frameLen, + (void **) &pAddBARspBuffer, + (void **) &pPacket ))) + { + // Log error + limLog( pMac, LOGP, + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), + frameLen, + halStatus ); + + statusCode = eSIR_MEM_ALLOC_FAILED; + goto returnAfterError; + } + + vos_mem_set( (void *) pAddBARspBuffer, frameLen, 0 ); + + // Copy necessary info to BD + if( eSIR_SUCCESS != + (statusCode = limPopulateMacHeader( pMac, + pAddBARspBuffer, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + pMlmAddBARsp->peerMacAddr,psessionEntry->selfMacAddr))) + goto returnAfterError; + + // Update A3 with the BSSID + + pMacHdr = ( tpSirMacMgmtHdr ) pAddBARspBuffer; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, pMlmAddBARsp->peerMacAddr, pMacHdr); +#endif + + // Now, we're ready to "pack" the frames + nStatus = dot11fPackAddBARsp( pMac, + &frmAddBARsp, + pAddBARspBuffer + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an ADDBA Rsp (0x%08x)." ), + nStatus ); + + // FIXME - Need to convert to tSirRetStatus + statusCode = eSIR_FAILURE; + goto returnAfterError; + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing an ADDBA Rsp (0x%08x)." ), + nStatus); + } + + limLog( pMac, LOG1, FL( "Sending an ADDBA RSP to "MAC_ADDRESS_STR " with" + " tid = %d policy = %d buffsize = %d" + " amsduSupported = %d status %d"), + MAC_ADDR_ARRAY(pMlmAddBARsp->peerMacAddr), + frmAddBARsp.AddBAParameterSet.tid, + frmAddBARsp.AddBAParameterSet.policy, + frmAddBARsp.AddBAParameterSet.bufferSize, + frmAddBARsp.AddBAParameterSet.amsduSupported, + frmAddBARsp.Status.status); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halStatus = halTxFrame( pMac, + pPacket, + (tANI_U16) frameLen, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pAddBARspBuffer, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halStatus)); + if (eHAL_STATUS_SUCCESS != halStatus ) + { + limLog( pMac, LOGE, + FL( "halTxFrame FAILED! Status [%d]" ), + halStatus ); + + // FIXME - HAL error codes are different from PE error + // codes!! And, this routine is returning tSirRetStatus + statusCode = eSIR_FAILURE; + //Pkt will be freed up by the callback + return statusCode; + } + else + return eSIR_SUCCESS; + + returnAfterError: + + // Release buffer, if allocated + if( NULL != pAddBARspBuffer ) + palPktFree( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (void *) pAddBARspBuffer, + (void *) pPacket ); + + return statusCode; +} + +/** + * \brief Send a DELBA Indication Action Frame to peer + * + * \sa limSendDelBAInd + * + * \param pMac The global tpAniSirGlobal object + * + * \param peerMacAddr MAC Address of peer + * + * \param reasonCode Reason for the DELBA notification + * + * \param pBAParameterSet The DELBA Parameter Set. + * This identifies the TID for which the BA session is + * being deleted. + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, + tpLimMlmDelBAReq pMlmDelBAReq,tpPESession psessionEntry) +{ + tDot11fDelBAInd frmDelBAInd; + tANI_U8 *pDelBAIndBuffer = NULL; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 frameLen = 0, nStatus, nPayload; + tSirRetStatus statusCode; + eHalStatus halStatus; + void *pPacket; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if(NULL == psessionEntry) + { + return eSIR_FAILURE; + } + + smeSessionId = psessionEntry->smeSessionId; + vos_mem_set( (void *) &frmDelBAInd, sizeof( frmDelBAInd ), 0); + + // Category - 3 (BA) + frmDelBAInd.Category.category = SIR_MAC_ACTION_BLKACK; + // Action - 2 (DELBA) + frmDelBAInd.Action.action = SIR_MAC_BLKACK_DEL; + + // Fill the DELBA Parameter Set as provided by caller + frmDelBAInd.DelBAParameterSet.tid = pMlmDelBAReq->baTID; + frmDelBAInd.DelBAParameterSet.initiator = pMlmDelBAReq->baDirection; + + // BA Starting Sequence Number + // Fragment number will always be zero + frmDelBAInd.Reason.code = pMlmDelBAReq->delBAReasonCode; + + nStatus = dot11fGetPackedDelBAIndSize( pMac, &frmDelBAInd, &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGW, + FL( "Failed to calculate the packed size for " + "an DELBA Indication (0x%08x)."), + nStatus ); + + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fDelBAInd ); + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while calculating " + "the packed size for an DELBA Ind (0x%08x)."), + nStatus ); + } + + // Add the MGMT header to frame length + frameLen = nPayload + sizeof( tSirMacMgmtHdr ); + + // Allocate shared memory + if( eHAL_STATUS_SUCCESS != + (halStatus = palPktAlloc( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (tANI_U16) frameLen, + (void **) &pDelBAIndBuffer, + (void **) &pPacket ))) + { + // Log error + limLog( pMac, LOGP, + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), + frameLen, + halStatus ); + + statusCode = eSIR_MEM_ALLOC_FAILED; + goto returnAfterError; + } + + vos_mem_set( (void *) pDelBAIndBuffer, frameLen, 0 ); + + // Copy necessary info to BD + if( eSIR_SUCCESS != + (statusCode = limPopulateMacHeader( pMac, + pDelBAIndBuffer, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + pMlmDelBAReq->peerMacAddr,psessionEntry->selfMacAddr))) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pDelBAIndBuffer; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, pMlmDelBAReq->peerMacAddr, pMacHdr); +#endif + + // Now, we're ready to "pack" the frames + nStatus = dot11fPackDelBAInd( pMac, + &frmDelBAInd, + pDelBAIndBuffer + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an DELBA Ind (0x%08x)." ), + nStatus ); + + // FIXME - Need to convert to tSirRetStatus + statusCode = eSIR_FAILURE; + goto returnAfterError; + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing an DELBA Ind (0x%08x)." ), + nStatus); + } + + limLog( pMac, LOGW, + FL( "Sending a DELBA IND to " )); + limPrintMacAddr( pMac, pMlmDelBAReq->peerMacAddr, LOGW ); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halStatus = halTxFrame( pMac, + pPacket, + (tANI_U16) frameLen, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pDelBAIndBuffer, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halStatus)); + if (eHAL_STATUS_SUCCESS != halStatus ) + { + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halStatus );) + statusCode = eSIR_FAILURE; + //Pkt will be freed up by the callback + return statusCode; + } + else + return eSIR_SUCCESS; + + returnAfterError: + + // Release buffer, if allocated + if( NULL != pDelBAIndBuffer ) + palPktFree( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (void *) pDelBAIndBuffer, + (void *) pPacket ); + + return statusCode; +} + +#if defined WLAN_FEATURE_VOWIFI + +/** + * \brief Send a Neighbor Report Request Action frame + * + * + * \param pMac Pointer to the global MAC structure + * + * \param pNeighborReq Address of a tSirMacNeighborReportReq + * + * \param peer mac address of peer station. + * + * \param psessionEntry address of session entry. + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, + tpSirMacNeighborReportReq pNeighborReq, + tSirMacAddr peer, + tpPESession psessionEntry + ) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tDot11fNeighborReportRequest frm; + tANI_U8 *pFrame; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + if ( psessionEntry == NULL ) + { + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Neighbor Report request action frame") ); + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + frm.Category.category = SIR_MAC_ACTION_RRM; + frm.Action.action = SIR_MAC_RRM_NEIGHBOR_REQ; + frm.DialogToken.token = pNeighborReq->dialogToken; + + + if( pNeighborReq->ssid_present ) + { + PopulateDot11fSSID( pMac, &pNeighborReq->ssid, &frm.SSID ); + } + + nStatus = dot11fGetPackedNeighborReportRequestSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Neighbor Report Request(0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fNeighborReportRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Neighbor Rep" + "ort Request(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Neighbor " + "Report Request."), nBytes ); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Copy necessary info to BD + if( eSIR_SUCCESS != + (statusCode = limPopulateMacHeader( pMac, + pFrame, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + peer, psessionEntry->selfMacAddr))) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + // Now, we're ready to "pack" the frames + nStatus = dot11fPackNeighborReportRequest( pMac, + &frm, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an Neighbor Report Request (0x%08x)." ), + nStatus ); + + // FIXME - Need to convert to tSirRetStatus + statusCode = eSIR_FAILURE; + goto returnAfterError; + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing Neighbor Report " + "Request (0x%08x)." ), nStatus); + } + + limLog( pMac, LOGW, + FL( "Sending a Neighbor Report Request to " )); + limPrintMacAddr( pMac, peer, LOGW ); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, + pPacket, + (tANI_U16) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pFrame, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if (eHAL_STATUS_SUCCESS != halstatus ) + { + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) + statusCode = eSIR_FAILURE; + //Pkt will be freed up by the callback + return statusCode; + } + else + return eSIR_SUCCESS; + +returnAfterError: + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + + return statusCode; +} // End limSendNeighborReportRequestFrame. + +/** + * \brief Send a Link Report Action frame + * + * + * \param pMac Pointer to the global MAC structure + * + * \param pLinkReport Address of a tSirMacLinkReport + * + * \param peer mac address of peer station. + * + * \param psessionEntry address of session entry. + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +limSendLinkReportActionFrame(tpAniSirGlobal pMac, + tpSirMacLinkReport pLinkReport, + tSirMacAddr peer, + tpPESession psessionEntry + ) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tDot11fLinkMeasurementReport frm; + tANI_U8 *pFrame; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + + if ( psessionEntry == NULL ) + { + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Link Report action frame") ); + return eSIR_FAILURE; + } + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + + frm.Category.category = SIR_MAC_ACTION_RRM; + frm.Action.action = SIR_MAC_RRM_LINK_MEASUREMENT_RPT; + frm.DialogToken.token = pLinkReport->dialogToken; + + + //IEEE Std. 802.11 7.3.2.18. for the report element. + //Even though TPC report an IE, it is represented using fixed fields since it is positioned + //in the middle of other fixed fields in the link report frame(IEEE Std. 802.11k section7.4.6.4 + //and frame parser always expects IEs to come after all fixed fields. It is easier to handle + //such case this way than changing the frame parser. + frm.TPCEleID.TPCId = SIR_MAC_TPC_RPT_EID; + frm.TPCEleLen.TPCLen = 2; + frm.TxPower.txPower = pLinkReport->txPower; + frm.LinkMargin.linkMargin = 0; + + frm.RxAntennaId.antennaId = pLinkReport->rxAntenna; + frm.TxAntennaId.antennaId = pLinkReport->txAntenna; + frm.RCPI.rcpi = pLinkReport->rcpi; + frm.RSNI.rsni = pLinkReport->rsni; + + nStatus = dot11fGetPackedLinkMeasurementReportSize( pMac, &frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Link Report (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fLinkMeasurementReport ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Link Rep" + "ort (0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Link " + "Report."), nBytes ); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Copy necessary info to BD + if( eSIR_SUCCESS != + (statusCode = limPopulateMacHeader( pMac, + pFrame, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + peer, psessionEntry->selfMacAddr))) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + // Now, we're ready to "pack" the frames + nStatus = dot11fPackLinkMeasurementReport( pMac, + &frm, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an Link Report (0x%08x)." ), + nStatus ); + + // FIXME - Need to convert to tSirRetStatus + statusCode = eSIR_FAILURE; + goto returnAfterError; + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing Link Report (0x%08x)." ), + nStatus ); + } + + limLog( pMac, LOGW, + FL( "Sending a Link Report to " )); + limPrintMacAddr( pMac, peer, LOGW ); + + if ((SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, + pPacket, + (tANI_U16) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pFrame, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if (eHAL_STATUS_SUCCESS != halstatus ) + { + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) + statusCode = eSIR_FAILURE; + //Pkt will be freed up by the callback + return statusCode; + } + else + return eSIR_SUCCESS; + +returnAfterError: + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + + return statusCode; +} // End limSendLinkReportActionFrame. + +/** + * \brief Send a Beacon Report Action frame + * + * + * \param pMac Pointer to the global MAC structure + * + * \param dialog_token dialog token to be used in the action frame. + * + * \param num_report number of reports in pRRMReport. + * + * \param pRRMReport Address of a tSirMacRadioMeasureReport. + * + * \param peer mac address of peer station. + * + * \param psessionEntry address of session entry. + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, + tANI_U8 dialog_token, + tANI_U8 num_report, + tpSirMacRadioMeasureReport pRRMReport, + tSirMacAddr peer, + tpPESession psessionEntry + ) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tANI_U8 *pFrame; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 i; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + tDot11fRadioMeasurementReport *frm = + vos_mem_malloc(sizeof(tDot11fRadioMeasurementReport)); + if (!frm) { + limLog( pMac, LOGE, FL("Not enough memory to allocate tDot11fRadioMeasurementReport") ); + return eSIR_FAILURE; + } + + if ( psessionEntry == NULL ) + { + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Beacon Report action frame") ); + vos_mem_free(frm); + return eSIR_FAILURE; + } + vos_mem_set( ( tANI_U8* )frm, sizeof( *frm ), 0 ); + + frm->Category.category = SIR_MAC_ACTION_RRM; + frm->Action.action = SIR_MAC_RRM_RADIO_MEASURE_RPT; + frm->DialogToken.token = dialog_token; + + frm->num_MeasurementReport = (num_report > RADIO_REPORTS_MAX_IN_A_FRAME ) ? RADIO_REPORTS_MAX_IN_A_FRAME : num_report; + + for( i = 0 ; i < frm->num_MeasurementReport ; i++ ) + { + frm->MeasurementReport[i].type = pRRMReport[i].type; + frm->MeasurementReport[i].token = pRRMReport[i].token; + frm->MeasurementReport[i].late = 0; //IEEE 802.11k section 7.3.22. (always zero in rrm) + switch( pRRMReport[i].type ) + { + case SIR_MAC_RRM_BEACON_TYPE: + PopulateDot11fBeaconReport( pMac, &frm->MeasurementReport[i], &pRRMReport[i].report.beaconReport ); + frm->MeasurementReport[i].incapable = pRRMReport[i].incapable; + frm->MeasurementReport[i].refused = pRRMReport[i].refused; + frm->MeasurementReport[i].present = 1; + break; + default: + frm->MeasurementReport[i].incapable = pRRMReport[i].incapable; + frm->MeasurementReport[i].refused = pRRMReport[i].refused; + frm->MeasurementReport[i].present = 1; + break; + } + } + + nStatus = dot11fGetPackedRadioMeasurementReportSize( pMac, frm, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Radio Measure Report (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fLinkMeasurementReport ); + vos_mem_free(frm); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Radio Measure Rep" + "ort (0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( tANI_U16 )nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Radio Measure " + "Report."), nBytes ); + vos_mem_free(frm); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Copy necessary info to BD + if( eSIR_SUCCESS != + (statusCode = limPopulateMacHeader( pMac, + pFrame, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + peer, psessionEntry->selfMacAddr))) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); + +#ifdef WLAN_FEATURE_11W + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); +#endif + + // Now, we're ready to "pack" the frames + nStatus = dot11fPackRadioMeasurementReport( pMac, + frm, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an Radio Measure Report (0x%08x)." ), + nStatus ); + + // FIXME - Need to convert to tSirRetStatus + statusCode = eSIR_FAILURE; + goto returnAfterError; + } + else if( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing Radio " + "Measure Report (0x%08x)." ), nStatus); + } + + limLog( pMac, LOGW, + FL( "Sending a Radio Measure Report to " )); + limPrintMacAddr( pMac, peer, LOGW ); + + if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE) + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, + pPacket, + (tANI_U16) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pFrame, txFlag, smeSessionId); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if (eHAL_STATUS_SUCCESS != halstatus ) + { + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) + statusCode = eSIR_FAILURE; + //Pkt will be freed up by the callback + vos_mem_free(frm); + return statusCode; + } + else + { + vos_mem_free(frm); + return eSIR_SUCCESS; + } + +returnAfterError: + vos_mem_free(frm); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return statusCode; +} // End limSendBeaconReportActionFrame. + +#endif + +#ifdef WLAN_FEATURE_11W +/** + * \brief Send SA query request action frame to peer + * + * \sa limSendSaQueryRequestFrame + * + * + * \param pMac The global tpAniSirGlobal object + * + * \param transId Transaction identifier + * + * \param peer The Mac address of the station to which this action frame is addressed + * + * \param psessionEntry The PE session entry + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ + +tSirRetStatus limSendSaQueryRequestFrame( tpAniSirGlobal pMac, tANI_U8 *transId, + tSirMacAddr peer, tpPESession psessionEntry ) +{ + + tDot11fSaQueryReq frm; // SA query request action frame + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + frm.Category.category = SIR_MAC_ACTION_SA_QUERY; + /* 11w action field is : + action: 0 --> SA Query Request action frame + action: 1 --> SA Query Response action frame */ + frm.Action.action = SIR_MAC_SA_QUERY_REQ; + /* 11w SA Query Request transId */ + vos_mem_copy( &frm.TransactionId.transId[0], &transId[0], 2 ); + + nStatus = dot11fGetPackedSaQueryReqSize(pMac, &frm, &nPayload); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size " + "for an SA Query Request (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fSaQueryReq ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for an SA Query Request" + " (0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a SA Query Request " + "action frame"), nBytes ); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Copy necessary info to BD + nSirStatus = limPopulateMacHeader( pMac, + pFrame, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + peer, psessionEntry->selfMacAddr ); + if ( eSIR_SUCCESS != nSirStatus ) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); + + // Since this is a SA Query Request, set the "protect" (aka WEP) bit + // in the FC + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); + + // Pack 11w SA Query Request frame + nStatus = dot11fPackSaQueryReq( pMac, + &frm, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if ( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an SA Query Request (0x%08x)." ), + nStatus ); + // FIXME - Need to convert to tSirRetStatus + nSirStatus = eSIR_FAILURE; + goto returnAfterError; + } + else if ( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing SA Query Request (0x%08x)." ), + nStatus); + } + + limLog( pMac, LOG1, + FL( "Sending an SA Query Request to " )); + limPrintMacAddr( pMac, peer, LOG1 ); + limLog( pMac, LOG1, + FL( "Sending an SA Query Request from " )); + limPrintMacAddr( pMac, psessionEntry->selfMacAddr, LOG1 ); + + if ( ( SIR_BAND_5_GHZ == limGetRFBand( psessionEntry->currentOperChannel ) ) +#ifdef WLAN_FEATURE_P2P + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE ) +#endif + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + smeSessionId = psessionEntry->smeSessionId; + + halstatus = halTxFrame( pMac, + pPacket, + (tANI_U16) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pFrame, txFlag, smeSessionId); + if ( eHAL_STATUS_SUCCESS != halstatus ) + { + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) + nSirStatus = eSIR_FAILURE; + //Pkt will be freed up by the callback + return nSirStatus; + } + else { + return eSIR_SUCCESS; + } + +returnAfterError: + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return nSirStatus; +} // End limSendSaQueryRequestFrame + +/** + * \brief Send SA query response action frame to peer + * + * \sa limSendSaQueryResponseFrame + * + * + * \param pMac The global tpAniSirGlobal object + * + * \param transId Transaction identifier received in SA query request action frame + * + * \param peer The Mac address of the AP to which this action frame is addressed + * + * \param psessionEntry The PE session entry + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ + +tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, tANI_U8 *transId, +tSirMacAddr peer,tpPESession psessionEntry) +{ + + tDot11fSaQueryRsp frm; // SA query reponse action frame + tANI_U8 *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 nBytes, nPayload, nStatus; + void *pPacket; + eHalStatus halstatus; + tANI_U8 txFlag = 0; + tANI_U8 smeSessionId = 0; + + smeSessionId = psessionEntry->smeSessionId; + + vos_mem_set( ( tANI_U8* )&frm, sizeof( frm ), 0 ); + frm.Category.category = SIR_MAC_ACTION_SA_QUERY; + /*11w action field is : + action: 0 --> SA query request action frame + action: 1 --> SA query response action frame */ + frm.Action.action = SIR_MAC_SA_QUERY_RSP; + /*11w SA query response transId is same as + SA query request transId*/ + vos_mem_copy( &frm.TransactionId.transId[0], &transId[0], 2 ); + + nStatus = dot11fGetPackedSaQueryRspSize(pMac, &frm, &nPayload); + if ( DOT11F_FAILED( nStatus ) ) + { + limLog( pMac, LOGP, FL("Failed to calculate the packed size f" + "or a SA Query Response (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fSaQueryRsp ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + limLog( pMac, LOGW, FL("There were warnings while calculating " + "the packed size for an SA Query Response" + " (0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a SA query response" + " action frame"), nBytes ); + return eSIR_FAILURE; + } + + // Paranoia: + vos_mem_set( pFrame, nBytes, 0 ); + + // Copy necessary info to BD + nSirStatus = limPopulateMacHeader( pMac, + pFrame, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, + peer, psessionEntry->selfMacAddr ); + if ( eSIR_SUCCESS != nSirStatus ) + goto returnAfterError; + + // Update A3 with the BSSID + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; + + sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); + + // Since this is a SA Query Response, set the "protect" (aka WEP) bit + // in the FC + limSetProtectedBit(pMac, psessionEntry, peer, pMacHdr); + + // Pack 11w SA query response frame + nStatus = dot11fPackSaQueryRsp( pMac, + &frm, + pFrame + sizeof( tSirMacMgmtHdr ), + nPayload, + &nPayload ); + + if ( DOT11F_FAILED( nStatus )) + { + limLog( pMac, LOGE, + FL( "Failed to pack an SA Query Response (0x%08x)." ), + nStatus ); + // FIXME - Need to convert to tSirRetStatus + nSirStatus = eSIR_FAILURE; + goto returnAfterError; + } + else if ( DOT11F_WARNED( nStatus )) + { + limLog( pMac, LOGW, + FL( "There were warnings while packing SA Query Response (0x%08x)." ), + nStatus); + } + + limLog( pMac, LOG1, + FL( "Sending a SA Query Response to " )); + limPrintMacAddr( pMac, peer, LOGW ); + + if ( ( SIR_BAND_5_GHZ == limGetRFBand( psessionEntry->currentOperChannel ) ) +#ifdef WLAN_FEATURE_P2P + || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || + ( psessionEntry->pePersona == VOS_P2P_GO_MODE ) +#endif + ) + { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + halstatus = halTxFrame( pMac, + pPacket, + (tANI_U16) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + limTxComplete, + pFrame, txFlag, smeSessionId ); + MTRACE(vos_trace(VOS_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, halstatus)); + if ( eHAL_STATUS_SUCCESS != halstatus ) + { + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) + nSirStatus = eSIR_FAILURE; + //Pkt will be freed up by the callback + return nSirStatus; + } + else { + return eSIR_SUCCESS; + } + +returnAfterError: + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return nSirStatus; +} // End limSendSaQueryResponseFrame +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.c new file mode 100644 index 000000000000..ac0928064552 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.c @@ -0,0 +1,952 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * limSendMessages.c: Provides functions to send messages or Indications to HAL. + * Author: Sunit Bhatia + * Date: 09/21/2006 + * History:- + * Date Modified by Modification Information + * + * -------------------------------------------------------------------------- + * + */ +#include "limSendMessages.h" +#include "cfgApi.h" +#include "limTrace.h" +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT +#include "vos_diag_core_log.h" +#endif //FEATURE_WLAN_DIAG_SUPPORT +/* When beacon filtering is enabled, firmware will + * analyze the selected beacons received during BMPS, + * and monitor any changes in the IEs as listed below. + * The format of the table is: + * - EID + * - Check for IE presence + * - Byte offset + * - Byte value + * - Bit Mask + * - Byte refrence + */ +static tBeaconFilterIe beaconFilterTable[] = { + {SIR_MAC_DS_PARAM_SET_EID, 0, {0, 0, DS_PARAM_CHANNEL_MASK, 0}}, + {SIR_MAC_ERP_INFO_EID, 0, {0, 0, ERP_FILTER_MASK, 0}}, + {SIR_MAC_EDCA_PARAM_SET_EID, 0, {0, 0, EDCA_FILTER_MASK, 0}}, + {SIR_MAC_QOS_CAPABILITY_EID, 0, {0, 0, QOS_FILTER_MASK, 0}}, + {SIR_MAC_CHNL_SWITCH_ANN_EID, 1, {0, 0, 0, 0}}, + {SIR_MAC_HT_INFO_EID, 0, {0, 0, HT_BYTE0_FILTER_MASK, 0}}, + {SIR_MAC_HT_INFO_EID, 0, {2, 0, HT_BYTE2_FILTER_MASK, 0}}, + {SIR_MAC_HT_INFO_EID, 0, {5, 0, HT_BYTE5_FILTER_MASK, 0}} +#if defined WLAN_FEATURE_VOWIFI + ,{SIR_MAC_PWR_CONSTRAINT_EID, 0, {0, 0, 0, 0}} +#endif +#ifdef WLAN_FEATURE_11AC + ,{SIR_MAC_VHT_OPMODE_EID, 0, {0, 0, 0, 0}} + ,{SIR_MAC_VHT_OPERATION_EID, 0, {0, 0, VHTOP_CHWIDTH_MASK, 0}} +#endif +}; + +/** + * limSendCFParams() + * + *FUNCTION: + * This function is called to send CFP Parameters to WDA, when they are changed. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param bssIdx Bss Index of the BSS to which STA is associated. + * @param cfpCount CFP Count, if that is changed. + * @param cfpPeriod CFP Period if that is changed. + * + * @return success if message send is ok, else false. + */ +tSirRetStatus limSendCFParams(tpAniSirGlobal pMac, tANI_U8 bssIdx, tANI_U8 cfpCount, tANI_U8 cfpPeriod) +{ + tpUpdateCFParams pCFParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pCFParams = vos_mem_malloc(sizeof( tUpdateCFParams )); + if ( NULL == pCFParams ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update CF Params" )); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + vos_mem_set( (tANI_U8 *) pCFParams, sizeof(tUpdateCFParams), 0); + pCFParams->cfpCount = cfpCount; + pCFParams->cfpPeriod = cfpPeriod; + pCFParams->bssIdx = bssIdx; + + msgQ.type = WDA_UPDATE_CF_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pCFParams; + msgQ.bodyval = 0; + limLog( pMac, LOG3, + FL( "Sending WDA_UPDATE_CF_IND..." )); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pCFParams); + limLog( pMac, LOGP, + FL("Posting WDA_UPDATE_CF_IND to WDA failed, reason=%X"), + retCode ); + } +returnFailure: + return retCode; +} + +/** + * limSendBeaconParams() + * + *FUNCTION: + * This function is called to send beacnon interval, short preamble or other + * parameters to WDA, which are changed and indication is received in beacon. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param tpUpdateBeaconParams pointer to the structure, + which contains the beacon parameters which are changed. + * + * @return success if message send is ok, else false. + */ +tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, + tpUpdateBeaconParams pUpdatedBcnParams, + tpPESession psessionEntry ) +{ + tpUpdateBeaconParams pBcnParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pBcnParams = vos_mem_malloc(sizeof(*pBcnParams)); + if ( NULL == pBcnParams ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update Beacon Params" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy((tANI_U8 *) pBcnParams, pUpdatedBcnParams, sizeof(*pBcnParams)); + msgQ.type = WDA_UPDATE_BEACON_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pBcnParams; + msgQ.bodyval = 0; + PELOG3(limLog( pMac, LOG3, + FL( "Sending WDA_UPDATE_BEACON_IND, paramChangeBitmap in hex = %x" ), + pUpdatedBcnParams->paramChangeBitmap);) + if(NULL == psessionEntry) + { + vos_mem_free(pBcnParams); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + return eSIR_FAILURE; + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + pBcnParams->smeSessionId = psessionEntry->smeSessionId; + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pBcnParams); + limLog( pMac, LOGP, + FL("Posting WDA_UPDATE_BEACON_IND to WDA failed, reason=%X"), + retCode ); + } + limSendBeaconInd(pMac, psessionEntry); + return retCode; +} + +/** + * limSendSwitchChnlParams() + * + *FUNCTION: + * This function is called to send Channel Switch Indication to WDA + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param chnlNumber New Channel Number to be switched to. + * @param secondaryChnlOffset an enum for secondary channel offset. + * @param localPowerConstraint 11h local power constraint value + * + * @return success if message send is ok, else false. + */ +#if !defined WLAN_FEATURE_VOWIFI +tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, + tANI_U8 chnlNumber, + ePhyChanBondState secondaryChnlOffset, + tANI_U8 localPwrConstraint, + tANI_U8 peSessionId, + uint8_t is_restart) +#else +tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, + tANI_U8 chnlNumber, + ePhyChanBondState secondaryChnlOffset, + tPowerdBm maxTxPower, tANI_U8 peSessionId, + uint8_t is_restart) +#endif +{ + tpSwitchChannelParams pChnlParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tpPESession pSessionEntry; + if((pSessionEntry = peFindSessionBySessionId(pMac, peSessionId)) == NULL) + { + limLog( pMac, LOGP, + FL( "Unable to get Session for session Id %d" ), peSessionId); + return eSIR_FAILURE; + } + pChnlParams = vos_mem_malloc(sizeof( tSwitchChannelParams )); + if ( NULL == pChnlParams ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Switch Channel Params" )); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + vos_mem_set((tANI_U8 *) pChnlParams, sizeof(tSwitchChannelParams), 0); + pChnlParams->secondaryChannelOffset = secondaryChnlOffset; + pChnlParams->channelNumber= chnlNumber; + vos_mem_copy( pChnlParams->selfStaMacAddr, pSessionEntry->selfMacAddr, sizeof(tSirMacAddr) ); +#if defined WLAN_FEATURE_VOWIFI + pChnlParams->maxTxPower = maxTxPower; +#else + pChnlParams->localPowerConstraint = localPwrConstraint; +#endif + vos_mem_copy( pChnlParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr) ); + pChnlParams->peSessionId = peSessionId; + pChnlParams->vhtCapable = pSessionEntry->vhtCapability; + pChnlParams->dot11_mode = pSessionEntry->dot11mode; + + /*Set DFS flag for DFS channel*/ + if (vos_nv_getChannelEnabledState(chnlNumber) == NV_CHANNEL_DFS) + pChnlParams->isDfsChannel= VOS_TRUE; + else + pChnlParams->isDfsChannel = VOS_FALSE; + + pChnlParams->restart_on_chan_switch = is_restart; + + //we need to defer the message until we get the response back from WDA. + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + msgQ.type = WDA_CHNL_SWITCH_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pChnlParams; + msgQ.bodyval = 0; +#if defined WLAN_FEATURE_VOWIFI + PELOG3(limLog( pMac, LOG3, + FL( "Sending WDA_CHNL_SWITCH_REQ with SecondaryChnOffset - %d, ChannelNumber - %d, maxTxPower - %d"), + pChnlParams->secondaryChannelOffset, pChnlParams->channelNumber, pChnlParams->maxTxPower);) +#else + PELOG3(limLog( pMac, LOG3, + FL( "Sending WDA_CHNL_SWITCH_REQ with SecondaryChnOffset - %d, ChannelNumber - %d, LocalPowerConstraint - %d"), + pChnlParams->secondaryChannelOffset, pChnlParams->channelNumber, pChnlParams->localPowerConstraint);) +#endif + MTRACE(macTraceMsgTx(pMac, peSessionId, msgQ.type)); + limLog(pMac,LOG1,"SessionId:%d WDA_CHNL_SWITCH_REQ for SSID:%s",peSessionId, + pSessionEntry->ssId.ssId); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pChnlParams); + limLog(pMac, LOGP, + FL("Posting WDA_CHNL_SWITCH_REQ to WDA failed, reason=%X"), + retCode ); + } +returnFailure: + return retCode; +} + +/** + * limSendEdcaParams() + * + *FUNCTION: + * This function is called to send dynamically changing EDCA Parameters to WDA. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param tpUpdatedEdcaParams pointer to the structure which contains + * dynamically changing EDCA parameters. + * @return success if message send is ok, else false. + */ +tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, + tSirMacEdcaParamRecord *pUpdatedEdcaParams, + tANI_U16 bssIdx) +{ + tEdcaParams *pEdcaParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pEdcaParams = vos_mem_malloc(sizeof(tEdcaParams)); + if ( NULL == pEdcaParams ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update EDCA Params" )); + retCode = eSIR_MEM_ALLOC_FAILED; + return retCode; + } + pEdcaParams->bssIdx = bssIdx; + pEdcaParams->acbe = pUpdatedEdcaParams[EDCA_AC_BE]; + pEdcaParams->acbk = pUpdatedEdcaParams[EDCA_AC_BK]; + pEdcaParams->acvi = pUpdatedEdcaParams[EDCA_AC_VI]; + pEdcaParams->acvo = pUpdatedEdcaParams[EDCA_AC_VO]; + msgQ.type = WDA_UPDATE_EDCA_PROFILE_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pEdcaParams; + msgQ.bodyval = 0; + { + tANI_U8 i; + PELOG1(limLog( pMac, LOG1,FL("Sending WDA_UPDATE_EDCA_PROFILE_IND with EDCA Parameters:" ));) + for(i=0; igLimEdcaParamsActive[EDCA_AC_BE] = plocalEdcaParams[EDCA_AC_BE]; + psessionEntry->gLimEdcaParamsActive[EDCA_AC_BK] = plocalEdcaParams[EDCA_AC_BK]; + psessionEntry->gLimEdcaParamsActive[EDCA_AC_VI] = plocalEdcaParams[EDCA_AC_VI]; + psessionEntry->gLimEdcaParamsActive[EDCA_AC_VO] = plocalEdcaParams[EDCA_AC_VO]; + /* An AC requires downgrade if the ACM bit is set, and the AC has not + * yet been admitted in uplink or bi-directions. + * If an AC requires downgrade, it will downgrade to the next beset AC + * for which ACM is not enabled. + * + * - There's no need to downgrade AC_BE since it IS the lowest AC. Hence + * start the for loop with AC_BK. + * - If ACM bit is set for an AC, initially downgrade it to AC_BE. Then + * traverse thru the AC list. If we do find the next best AC which is + * better than AC_BE, then use that one. For example, if ACM bits are set + * such that: BE_ACM=1, BK_ACM=1, VI_ACM=1, VO_ACM=0 + * then all AC will be downgraded to AC_BE. + */ + if(!pMac->psOffloadEnabled) + { + limLog(pMac, LOG1, FL("adAdmitMask[UPLINK] = 0x%x "), + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] ); + limLog(pMac, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x "), + pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] ); + } + else + { + limLog(pMac, LOG1, FL("adAdmitMask[UPLINK] = 0x%x "), + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] ); + limLog(pMac, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x "), + psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] ); + } + for (ac = EDCA_AC_BK; ac <= EDCA_AC_VO; ac++) + { + if(!pMac->psOffloadEnabled) + { + acAdmitted = ( (pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & + (1 << ac)) >> ac ); + } + else + { + acAdmitted = + ((psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & + (1 << ac)) >> ac ); + } + + limLog(pMac, LOG1, FL("For AC[%d]: acm=%d, acAdmit=%d "), ac, plocalEdcaParams[ac].aci.acm, acAdmitted); + if ( (plocalEdcaParams[ac].aci.acm == 1) && (acAdmitted == 0) ) + { + limLog(pMac, LOG1, FL("We need to downgrade AC %d!! "), ac); + newAc = EDCA_AC_BE; + for (i=ac-1; i>0; i--) + { + if (plocalEdcaParams[i].aci.acm == 0) + { + newAc = i; + break; + } + } + limLog(pMac, LOGW, FL("Downgrading AC %d ---> AC %d "), ac, newAc); + psessionEntry->gLimEdcaParamsActive[ac] = plocalEdcaParams[newAc]; + } + } +//log: LOG_WLAN_QOS_EDCA_C +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_qos_edca_pkt_type, LOG_WLAN_QOS_EDCA_C); + if(log_ptr) + { + log_ptr->aci_be = psessionEntry->gLimEdcaParamsActive[EDCA_AC_BE].aci.aci; + log_ptr->cw_be = psessionEntry->gLimEdcaParamsActive[EDCA_AC_BE].cw.max << 4 | + psessionEntry->gLimEdcaParamsActive[EDCA_AC_BE].cw.min; + log_ptr->txoplimit_be = psessionEntry->gLimEdcaParamsActive[EDCA_AC_BE].txoplimit; + log_ptr->aci_bk = psessionEntry->gLimEdcaParamsActive[EDCA_AC_BK].aci.aci; + log_ptr->cw_bk = psessionEntry->gLimEdcaParamsActive[EDCA_AC_BK].cw.max << 4 | + psessionEntry->gLimEdcaParamsActive[EDCA_AC_BK].cw.min; + log_ptr->txoplimit_bk = psessionEntry->gLimEdcaParamsActive[EDCA_AC_BK].txoplimit; + log_ptr->aci_vi = psessionEntry->gLimEdcaParamsActive[EDCA_AC_VI].aci.aci; + log_ptr->cw_vi = psessionEntry->gLimEdcaParamsActive[EDCA_AC_VI].cw.max << 4 | + psessionEntry->gLimEdcaParamsActive[EDCA_AC_VI].cw.min; + log_ptr->txoplimit_vi = psessionEntry->gLimEdcaParamsActive[EDCA_AC_VI].txoplimit; + log_ptr->aci_vo = psessionEntry->gLimEdcaParamsActive[EDCA_AC_VO].aci.aci; + log_ptr->cw_vo = psessionEntry->gLimEdcaParamsActive[EDCA_AC_VO].cw.max << 4 | + psessionEntry->gLimEdcaParamsActive[EDCA_AC_VO].cw.min; + log_ptr->txoplimit_vo = psessionEntry->gLimEdcaParamsActive[EDCA_AC_VO].txoplimit; + } + WLAN_VOS_DIAG_LOG_REPORT(log_ptr); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + return; + } + +/** --------------------------------------------------------- +\fn limSetLinkState +\brief LIM sends a message to WDA to set the link state +\param tpAniSirGlobal pMac +\param tSirLinkState state +\return None + -----------------------------------------------------------*/ +tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAddr bssId, + tSirMacAddr selfMacAddr, tpSetLinkStateCallback callback, + void *callbackArg) +{ + tSirMsgQ msgQ; + tSirRetStatus retCode; + tpLinkStateParams pLinkStateParams = NULL; + // Allocate memory. + pLinkStateParams = vos_mem_malloc(sizeof(tLinkStateParams)); + if ( NULL == pLinkStateParams ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory while sending Set Link State" )); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + return retCode; + } + vos_mem_set((tANI_U8 *) pLinkStateParams, sizeof(tLinkStateParams), 0); + pLinkStateParams->state = state; + pLinkStateParams->callback = callback; + pLinkStateParams->callbackArg = callbackArg; + + /* Copy Mac address */ + sirCopyMacAddr(pLinkStateParams->bssid,bssId); + sirCopyMacAddr(pLinkStateParams->selfMacAddr, selfMacAddr); + + msgQ.type = WDA_SET_LINK_STATE; + msgQ.reserved = 0; + msgQ.bodyptr = pLinkStateParams; + msgQ.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + + retCode = (tANI_U32)wdaPostCtrlMsg(pMac, &msgQ); + if (retCode != eSIR_SUCCESS) + { + vos_mem_free(pLinkStateParams); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), + state, retCode); + } + return retCode; +} +#ifdef WLAN_FEATURE_VOWIFI_11R +extern tSirRetStatus limSetLinkStateFT(tpAniSirGlobal pMac, tSirLinkState +state,tSirMacAddr bssId, tSirMacAddr selfMacAddr, int ft, tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tSirRetStatus retCode; + tpLinkStateParams pLinkStateParams = NULL; + // Allocate memory. + pLinkStateParams = vos_mem_malloc(sizeof(tLinkStateParams)); + if ( NULL == pLinkStateParams ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory while sending Set Link State" )); + retCode = eSIR_SME_RESOURCES_UNAVAILABLE; + return retCode; + } + vos_mem_set((tANI_U8 *) pLinkStateParams, sizeof(tLinkStateParams), 0); + pLinkStateParams->state = state; + /* Copy Mac address */ + sirCopyMacAddr(pLinkStateParams->bssid,bssId); + sirCopyMacAddr(pLinkStateParams->selfMacAddr, selfMacAddr); + pLinkStateParams->ft = 1; + pLinkStateParams->session = psessionEntry; + + msgQ.type = WDA_SET_LINK_STATE; + msgQ.reserved = 0; + msgQ.bodyptr = pLinkStateParams; + msgQ.bodyval = 0; + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + + retCode = (tANI_U32)wdaPostCtrlMsg(pMac, &msgQ); + if (retCode != eSIR_SUCCESS) + { + vos_mem_free(pLinkStateParams); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), + state, retCode); + } + return retCode; +} +#endif + +/** --------------------------------------------------------- +\fn limSendSetTxPowerReq +\brief LIM sends a WDA_SET_TX_POWER_REQ message to WDA +\param tpAniSirGlobal pMac +\param tpSirSetTxPowerReq request message +\return None + -----------------------------------------------------------*/ +tSirRetStatus limSendSetTxPowerReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) +{ + tSirSetTxPowerReq *txPowerReq; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tpPESession psessionEntry; + tANI_U8 sessionId = 0; + + if (NULL == pMsgBuf) + return eSIR_FAILURE; + + txPowerReq = vos_mem_malloc(sizeof(tSirSetTxPowerReq)); + if ( NULL == txPowerReq ) + { + return eSIR_FAILURE; + } + vos_mem_copy(txPowerReq, (tSirSetTxPowerReq *)pMsgBuf, sizeof(tSirSetTxPowerReq)); + + /* Found corresponding seesion to find BSS IDX */ + psessionEntry = peFindSessionByBssid(pMac, txPowerReq->bssId, &sessionId); + if (NULL == psessionEntry) + { + vos_mem_free(txPowerReq); + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); + return eSIR_FAILURE; + } + + /* FW API requests BSS IDX */ + txPowerReq->bssIdx = psessionEntry->bssIdx; + + msgQ.type = WDA_SET_TX_POWER_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = txPowerReq; + msgQ.bodyval = 0; + PELOGW(limLog(pMac, LOGW, FL("Sending WDA_SET_TX_POWER_REQ to WDA"));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) + { + limLog(pMac, LOGP, FL("Posting WDA_SET_TX_POWER_REQ to WDA failed, reason=%X"), retCode); + vos_mem_free(txPowerReq); + return retCode; + } + + return retCode; +} +/** --------------------------------------------------------- +\fn limSendGetTxPowerReq +\brief LIM sends a WDA_GET_TX_POWER_REQ message to WDA +\param tpAniSirGlobal pMac +\param tpSirGetTxPowerReq request message +\return None + -----------------------------------------------------------*/ +tSirRetStatus limSendGetTxPowerReq(tpAniSirGlobal pMac, tpSirGetTxPowerReq pTxPowerReq) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + if (NULL == pTxPowerReq) + return retCode; + msgQ.type = WDA_GET_TX_POWER_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pTxPowerReq; + msgQ.bodyval = 0; + PELOGW(limLog(pMac, LOGW, FL( "Sending WDA_GET_TX_POWER_REQ to WDA"));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + limLog( pMac, LOGP, FL("Posting WDA_GET_TX_POWER_REQ to WDA failed, reason=%X"), retCode ); + if (NULL != pTxPowerReq) + { + vos_mem_free(pTxPowerReq); + } + return retCode; + } + return retCode; +} +/** --------------------------------------------------------- +\fn limSendBeaconFilterInfo +\brief LIM sends beacon filtering info to WDA +\param tpAniSirGlobal pMac +\return None + -----------------------------------------------------------*/ +tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tpBeaconFilterMsg pBeaconFilterMsg = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tANI_U8 *ptr; + tANI_U32 i; + tANI_U32 msgSize; + tpBeaconFilterIe pIe; + + if( psessionEntry == NULL ) + { + limLog( pMac, LOGE, FL("Fail to find the right session ")); + retCode = eSIR_FAILURE; + return retCode; + } + msgSize = sizeof(tBeaconFilterMsg) + sizeof(beaconFilterTable); + pBeaconFilterMsg = vos_mem_malloc(msgSize); + if ( NULL == pBeaconFilterMsg ) + { + limLog( pMac, LOGP, FL("Fail to allocate memory for beaconFiilterMsg ")); + retCode = eSIR_MEM_ALLOC_FAILED; + return retCode; + } + vos_mem_set((tANI_U8 *) pBeaconFilterMsg, msgSize, 0); + // Fill in capability Info and mask + //Don't send this message if no active Infra session is found. + pBeaconFilterMsg->capabilityInfo = psessionEntry->limCurrentBssCaps; + pBeaconFilterMsg->capabilityMask = CAPABILITY_FILTER_MASK; + pBeaconFilterMsg->beaconInterval = (tANI_U16) psessionEntry->beaconParams.beaconInterval; + // Fill in number of IEs in beaconFilterTable + pBeaconFilterMsg->ieNum = (tANI_U16) (sizeof(beaconFilterTable) / sizeof(tBeaconFilterIe)); + //Fill the BSSIDX + pBeaconFilterMsg->bssIdx = psessionEntry->bssIdx; + + //Fill message with info contained in the beaconFilterTable + ptr = (tANI_U8 *)pBeaconFilterMsg + sizeof(tBeaconFilterMsg); + for(i=0; i < (pBeaconFilterMsg->ieNum); i++) + { + pIe = (tpBeaconFilterIe) ptr; + pIe->elementId = beaconFilterTable[i].elementId; + pIe->checkIePresence = beaconFilterTable[i].checkIePresence; + pIe->byte.offset = beaconFilterTable[i].byte.offset; + pIe->byte.value = beaconFilterTable[i].byte.value; + pIe->byte.bitMask = beaconFilterTable[i].byte.bitMask; + pIe->byte.ref = beaconFilterTable[i].byte.ref; + ptr += sizeof(tBeaconFilterIe); + } + msgQ.type = WDA_BEACON_FILTER_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pBeaconFilterMsg; + msgQ.bodyval = 0; + limLog( pMac, LOG3, FL( "Sending WDA_BEACON_FILTER_IND..." )); + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pBeaconFilterMsg); + limLog( pMac, LOGP, + FL("Posting WDA_BEACON_FILTER_IND to WDA failed, reason=%X"), + retCode ); + return retCode; + } + return retCode; +} + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus limSendModeUpdate(tpAniSirGlobal pMac, + tUpdateVHTOpMode *pTempParam, + tpPESession psessionEntry ) +{ + tUpdateVHTOpMode *pVhtOpMode = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pVhtOpMode = vos_mem_malloc(sizeof(tUpdateVHTOpMode)); + if ( NULL == pVhtOpMode ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update Op Mode" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy((tANI_U8 *)pVhtOpMode, pTempParam, sizeof(tUpdateVHTOpMode)); + msgQ.type = WDA_UPDATE_OP_MODE; + msgQ.reserved = 0; + msgQ.bodyptr = pVhtOpMode; + msgQ.bodyval = 0; + limLog(pMac, LOG3, FL( + "Sending WDA_UPDATE_OP_MODE, opMode - %d, staId - %d"), + pVhtOpMode->opMode, pVhtOpMode->staId); + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pVhtOpMode); + limLog( pMac, LOGP, + FL("Posting WDA_UPDATE_OP_MODE to WDA failed, reason=%X"), + retCode ); + } + + return retCode; +} + +tSirRetStatus limSendRxNssUpdate(tpAniSirGlobal pMac, + tUpdateRxNss *pTempParam, + tpPESession psessionEntry ) +{ + tUpdateRxNss *pRxNss = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pRxNss = vos_mem_malloc(sizeof(tUpdateRxNss)); + if ( NULL == pRxNss ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update Rx Nss" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy((tANI_U8 *)pRxNss, pTempParam, sizeof(tUpdateRxNss)); + msgQ.type = WDA_UPDATE_RX_NSS; + msgQ.reserved = 0; + msgQ.bodyptr = pRxNss; + msgQ.bodyval = 0; + PELOG3(limLog( pMac, LOG3, + FL( "Sending WDA_UPDATE_RX_NSS" ));) + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pRxNss); + limLog( pMac, LOGP, + FL("Posting WDA_UPDATE_RX_NSS to WDA failed, reason=%X"), + retCode ); + } + + return retCode; +} + +tSirRetStatus limSetMembership(tpAniSirGlobal pMac, + tUpdateMembership *pTempParam, + tpPESession psessionEntry ) +{ + tUpdateMembership *pMembership = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pMembership = vos_mem_malloc(sizeof(tUpdateMembership)); + if ( NULL == pMembership ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update Membership Mode" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy((tANI_U8 *)pMembership, pTempParam, sizeof(tUpdateMembership)); + + msgQ.type = WDA_UPDATE_MEMBERSHIP; + msgQ.reserved = 0; + msgQ.bodyptr = pMembership; + msgQ.bodyval = 0; + PELOG3(limLog( pMac, LOG3, + FL( "Sending WDA_UPDATE_MEMBERSHIP" ));) + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pMembership); + limLog( pMac, LOGP, + FL("Posting WDA_UPDATE_MEMBERSHIP to WDA failed, reason=%X"), + retCode ); + } + + return retCode; +} + +tSirRetStatus limSetUserPos(tpAniSirGlobal pMac, + tUpdateUserPos *pTempParam, + tpPESession psessionEntry ) +{ + tUpdateUserPos *pUserPos = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pUserPos = vos_mem_malloc(sizeof(tUpdateUserPos)); + if ( NULL == pUserPos ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Update User Position" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy((tANI_U8 *)pUserPos, pTempParam, sizeof(tUpdateUserPos)); + + msgQ.type = WDA_UPDATE_USERPOS; + msgQ.reserved = 0; + msgQ.bodyptr = pUserPos; + msgQ.bodyval = 0; + PELOG3(limLog( pMac, LOG3, + FL( "Sending WDA_UPDATE_USERPOS" ));) + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + } + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pUserPos); + limLog( pMac, LOGP, + FL("Posting WDA_UPDATE_USERPOS to WDA failed, reason=%X"), + retCode ); + } + + return retCode; +} + +#endif + + +#ifdef WLAN_FEATURE_11W +/** --------------------------------------------------------- +\fn limSendExcludeUnencryptInd +\brief LIM sends a message to HAL to indicate whether to + ignore or indicate the unprotected packet error +\param tpAniSirGlobal pMac +\param tANI_BOOLEAN excludeUnenc - true: ignore, false: + indicate +\param tpPESession psessionEntry - session context +\return status + -----------------------------------------------------------*/ +tSirRetStatus limSendExcludeUnencryptInd(tpAniSirGlobal pMac, + tANI_BOOLEAN excludeUnenc, + tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tSirWlanExcludeUnencryptParam * pExcludeUnencryptParam; + + pExcludeUnencryptParam = vos_mem_malloc(sizeof(tSirWlanExcludeUnencryptParam)); + if ( NULL == pExcludeUnencryptParam ) + { + limLog(pMac, LOGP, + FL( "Unable to allocate memory during limSendExcludeUnencryptInd")); + return eSIR_MEM_ALLOC_FAILED; + } + + pExcludeUnencryptParam->excludeUnencrypt = excludeUnenc; + sirCopyMacAddr(pExcludeUnencryptParam->bssId, psessionEntry->bssId); + + msgQ.type = WDA_EXCLUDE_UNENCRYPTED_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pExcludeUnencryptParam; + msgQ.bodyval = 0; + PELOG3(limLog(pMac, LOG3, + FL("Sending WDA_EXCLUDE_UNENCRYPTED_IND"));) + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) + { + vos_mem_free(pExcludeUnencryptParam); + limLog(pMac, LOGP, + FL("Posting WDA_EXCLUDE_UNENCRYPTED_IND to WDA failed, reason=%X"), + retCode); + } + + return retCode; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.h new file mode 100644 index 000000000000..dda834668646 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendMessages.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * limSendMessages.h: Provides functions to send messages or Indications to HAL. + * Author: Sunit Bhatia + * Date: 09/21/2006 + * History:- + * Date Modified by Modification Information + * + * -------------------------------------------------------------------------- + * + */ +#ifndef __LIM_SEND_MESSAGES_H +#define __LIM_SEND_MESSAGES_H + +#include "aniGlobal.h" +#include "limTypes.h" +#include "halMsgApi.h" +#include "sirParams.h" +tSirRetStatus limSendCFParams(tpAniSirGlobal pMac, tANI_U8 bssIdx, tANI_U8 cfpCount, tANI_U8 cfpPeriod); +tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, + tpUpdateBeaconParams pUpdatedBcnParams, + tpPESession psessionEntry ); +//tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, tpUpdateBeaconParams pUpdatedBcnParams); +#ifdef WLAN_FEATURE_11AC +tSirRetStatus limSendModeUpdate(tpAniSirGlobal pMac, + tUpdateVHTOpMode *tempParam, + tpPESession psessionEntry ); +tSirRetStatus limSendRxNssUpdate(tpAniSirGlobal pMac, + tUpdateRxNss *tempParam, + tpPESession psessionEntry ); + +tANI_U32 limGetCenterChannel(tpAniSirGlobal pMac, + tANI_U8 primarychanNum, + ePhyChanBondState secondaryChanOffset, + tANI_U8 chanWidth); + +tSirRetStatus limSetMembership(tpAniSirGlobal pMac, + tUpdateMembership *pTempParam, + tpPESession psessionEntry ); + +tSirRetStatus limSetUserPos(tpAniSirGlobal pMac, + tUpdateUserPos *pTempParam, + tpPESession psessionEntry ); +#endif +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, tANI_U8 chnlNumber, + ePhyChanBondState secondaryChnlOffset, + tPowerdBm maxTxPower,tANI_U8 peSessionId, + uint8_t is_restart); +#else +tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, tANI_U8 chnlNumber, + ePhyChanBondState secondaryChnlOffset, + tANI_U8 localPwrConstraint, + tANI_U8 peSessionId, + uint8_t is_restart); +#endif +tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, + tSirMacEdcaParamRecord *pUpdatedEdcaParams, + tANI_U16 bssIdx); +tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state, tSirMacAddr bssId, + tSirMacAddr selfMac, tpSetLinkStateCallback callback, + void *callbackArg); +#ifdef WLAN_FEATURE_VOWIFI_11R +extern tSirRetStatus limSetLinkStateFT(tpAniSirGlobal pMac, tSirLinkState +state,tSirMacAddr bssId, tSirMacAddr selfMacAddr, int ft, tpPESession psessionEntry); +#endif +tSirRetStatus limSendSetTxPowerReq(tpAniSirGlobal pMac, tANI_U32 *pTxPowerReq); +tSirRetStatus limSendGetTxPowerReq(tpAniSirGlobal pMac, tpSirGetTxPowerReq pTxPowerReq); +void limSetActiveEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *plocalEdcaParams, tpPESession psessionEntry); +#define CAPABILITY_FILTER_MASK 0x73CF +#define ERP_FILTER_MASK 0xF8 +#define EDCA_FILTER_MASK 0xF0 +#define QOS_FILTER_MASK 0xF0 +#define HT_BYTE0_FILTER_MASK 0x0 +#define HT_BYTE2_FILTER_MASK 0xEB +#define HT_BYTE5_FILTER_MASK 0xFD +#define DS_PARAM_CHANNEL_MASK 0x0 +#define VHTOP_CHWIDTH_MASK 0xFC + +tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac, tpPESession psessionEntry); + +#ifdef WLAN_FEATURE_11W +tSirRetStatus limSendExcludeUnencryptInd(tpAniSirGlobal pMac, + tANI_BOOLEAN excludeUnenc, + tpPESession psessionEntry ); +#endif +void limHandleSmeJoinResult(tpAniSirGlobal, tSirResultCodes, + tANI_U16, tpPESession); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c new file mode 100644 index 000000000000..6a7bd0b625d4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -0,0 +1,3343 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limSendSmeRspMessages.cc contains the functions + * for sending SME response/notification messages to applications + * above MAC software. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "vos_types.h" +#include "wniApi.h" +#include "sirCommon.h" +#include "aniGlobal.h" + +#include "wniCfgSta.h" +#include "sysDef.h" +#include "cfgApi.h" + + +#include "schApi.h" +#include "utilsApi.h" +#include "limUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" +#include "limSendSmeRspMessages.h" +#include "limIbssPeerMgmt.h" +#include "limSessionUtils.h" + +#include "sirApi.h" + +/** + * limRemoveSsidFromScanCache() + * + *FUNCTION: + * This function is called by limSendSmeLfrScanRsp() to clean given + * ssid from scan cache. + * + *PARAMS: + * @param pMac Pointer to Global MAC structure + * @param pSsid SSID to clean from scan list + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + * @return entriesLeft Number of SSID left in scan cache + */ +tANI_S16 limRemoveSsidFromScanCache(tpAniSirGlobal pMac, tSirMacSSid *pSsid) +{ + tANI_U16 i = 0; + tLimScanResultNode *pCurr = NULL; + tLimScanResultNode *pPrev = NULL; + tANI_S16 entriesLeft = 0; + + if (pSsid == NULL) + { + limLog(pMac, LOGW, FL("pSsid is NULL")); + return -1; + } + + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + if (pMac->lim.gLimCachedScanHashTable[i] != NULL) + { + pPrev = pMac->lim.gLimCachedScanHashTable[i]; + pCurr = pPrev->next; + while (pCurr) + { + entriesLeft++; + if (vos_mem_compare((tANI_U8* ) pCurr->bssDescription.ieFields+1, + (tANI_U8 *) &pSsid->length, + (tANI_U8) (pSsid->length + 1)) == VOS_TRUE) + { + pCurr=pCurr->next; + vos_mem_free(pPrev->next); + pPrev->next = pCurr; + entriesLeft--; + } + else + { + pCurr = pCurr->next; + pPrev = pPrev->next; + } + } /* while(pCurr) */ + pCurr = pMac->lim.gLimCachedScanHashTable[i]; + if (vos_mem_compare((tANI_U8* ) pCurr->bssDescription.ieFields+1, + (tANI_U8 *) &pSsid->length, + (tANI_U8) (pSsid->length + 1)) == VOS_TRUE) + { + pMac->lim.gLimCachedScanHashTable[i] = pMac->lim.gLimCachedScanHashTable[i]->next; + vos_mem_free(pCurr); + } + else + { + entriesLeft++; + } + } /* if( pMac->lim.gLimCachedScanHashTable[i] != NULL) */ + } /* for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) */ + return entriesLeft; +} + +/** + * limSendSmeRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_START_RSP, eWNI_SME_MEASUREMENT_RSP, eWNI_SME_STOP_BSS_RSP + * or eWNI_SME_SWITCH_CHL_RSP messages to applications above MAC + * Software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates message type + * @param resultCode Indicates the result of previously issued + * eWNI_SME_msgType_REQ message + * + * @return None + */ + +void +limSendSmeRsp(tpAniSirGlobal pMac, tANI_U16 msgType, + tSirResultCodes resultCode,tANI_U8 smesessionId, tANI_U16 smetransactionId) +{ + tSirMsgQ mmhMsg; + tSirSmeRsp *pSirSmeRsp; + + PELOG1(limLog(pMac, LOG1, + FL("Sending message type %d with reasonCode %s"), + msgType, limResultCodeStr(resultCode));) + + pSirSmeRsp = vos_mem_malloc(sizeof(tSirSmeRsp)); + if ( NULL == pSirSmeRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_*_RSP")); + + return; + } + + pSirSmeRsp->messageType = msgType; + pSirSmeRsp->length = sizeof(tSirSmeRsp); + pSirSmeRsp->statusCode = resultCode; + + /* Update SME session Id and Transaction Id */ + pSirSmeRsp->sessionId = smesessionId; + pSirSmeRsp->transactionId = smetransactionId; + + + mmhMsg.type = msgType; + mmhMsg.bodyptr = pSirSmeRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, smesessionId, mmhMsg.type)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + { + tpPESession psessionEntry = peGetValidPowerSaveSession(pMac); + switch(msgType) + { + case eWNI_PMC_ENTER_BMPS_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_BMPS_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_EXIT_BMPS_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_BMPS_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_ENTER_IMPS_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_IMPS_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_EXIT_IMPS_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_IMPS_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_ENTER_UAPSD_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_UAPSD_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_EXIT_UAPSD_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_UAPSD_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_SME_SWITCH_CHL_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_SWITCH_CHL_RSP_EVENT, NULL, (tANI_U16)resultCode, 0); + break; + case eWNI_SME_STOP_BSS_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_STOP_BSS_RSP_EVENT, NULL, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_ENTER_WOWL_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_WOWL_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + case eWNI_PMC_EXIT_WOWL_RSP: + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_WOWL_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + break; + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} /*** end limSendSmeRsp() ***/ + +/** + * lim_get_max_rate_flags() + * + *FUNCTION: + * This function is called to get the rate flags for a connection + * from the station ds structure depending on the ht and the vht + * channel width supported. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param mac_ctx Pointer to Global MAC structure + * @param sta_ds station ds structure + * + * @return rate_flags + */ +uint32_t lim_get_max_rate_flags(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds) +{ + uint32_t rate_flags = 0; + + if (sta_ds == NULL) { + limLog(mac_ctx, LOGE, FL("sta_ds is NULL")); + return rate_flags; + } + + if (!sta_ds->mlmStaContext.htCapability && + !sta_ds->mlmStaContext.vhtCapability) { + rate_flags |= eHAL_TX_RATE_LEGACY; + } else { + if (sta_ds->mlmStaContext.vhtCapability) { + if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == + sta_ds->vhtSupportedChannelWidthSet) { + rate_flags |= eHAL_TX_RATE_VHT80; + } else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == + sta_ds->vhtSupportedChannelWidthSet) { + if (sta_ds->htSupportedChannelWidthSet) + rate_flags |= eHAL_TX_RATE_VHT40; + else + rate_flags |= eHAL_TX_RATE_VHT20; + } + } else if (sta_ds->mlmStaContext.htCapability) { + if (sta_ds->htSupportedChannelWidthSet) + rate_flags |= eHAL_TX_RATE_HT40; + else + rate_flags |= eHAL_TX_RATE_HT20; + } + } + + if (sta_ds->htShortGI20Mhz || sta_ds->htShortGI40Mhz) + rate_flags |= eHAL_TX_RATE_SGI; + + return rate_flags; +} + +/** + * limSendSmeJoinReassocRspAfterResume() + * + *FUNCTION: + * This function is called to send Join/Reassoc rsp + * message to SME after the resume link. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param status Resume link status + * @param ctx context passed while calling resmune link. + * (join response to be sent) + * + * @return None + */ +static void limSendSmeJoinReassocRspAfterResume( tpAniSirGlobal pMac, + eHalStatus status, tANI_U32 *ctx) +{ + tSirMsgQ mmhMsg; + tpSirSmeJoinRsp pSirSmeJoinRsp = (tpSirSmeJoinRsp) ctx; + + mmhMsg.type = pSirSmeJoinRsp->messageType; + mmhMsg.bodyptr = pSirSmeJoinRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + + +/** + * limSendSmeJoinReassocRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_JOIN_RSP or eWNI_SME_REASSOC_RSP messages to applications + * above MAC Software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates message type + * @param resultCode Indicates the result of previously issued + * eWNI_SME_msgType_REQ message + * + * @return None + */ + +void +limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, + tSirResultCodes resultCode, tANI_U16 protStatusCode, + tpPESession psessionEntry,tANI_U8 smesessionId,tANI_U16 smetransactionId) +{ + tpSirSmeJoinRsp pSirSmeJoinRsp; + tANI_U32 rspLen; + tpDphHashNode pStaDs = NULL; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + if (msgType == eWNI_SME_REASSOC_RSP) + limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOC_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); + else + limDiagEventReport(pMac, WLAN_PE_DIAG_JOIN_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + PELOG1(limLog(pMac, LOG1, + FL("Sending message type %d with reasonCode %s"), + msgType, limResultCodeStr(resultCode));) + + if(psessionEntry == NULL) + { + + rspLen = sizeof(tSirSmeJoinRsp); + + pSirSmeJoinRsp = vos_mem_malloc(rspLen); + if ( NULL == pSirSmeJoinRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, FL("call to AllocateMemory failed for JOIN/REASSOC_RSP")); + return; + } + + vos_mem_set((tANI_U8*)pSirSmeJoinRsp, rspLen, 0); + + + pSirSmeJoinRsp->beaconLength = 0; + pSirSmeJoinRsp->assocReqLength = 0; + pSirSmeJoinRsp->assocRspLength = 0; + } + + else + { + rspLen = psessionEntry->assocReqLen + psessionEntry->assocRspLen + + psessionEntry->bcnLen + +#ifdef WLAN_FEATURE_VOWIFI_11R + psessionEntry->RICDataLen + +#endif +#ifdef FEATURE_WLAN_ESE + psessionEntry->tspecLen + +#endif + sizeof(tSirSmeJoinRsp) - sizeof(tANI_U8) ; + + pSirSmeJoinRsp = vos_mem_malloc(rspLen); + if ( NULL == pSirSmeJoinRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for JOIN/REASSOC_RSP")); + + return; + } + + vos_mem_set((tANI_U8*)pSirSmeJoinRsp, rspLen, 0); + + if (resultCode == eSIR_SME_SUCCESS) + { + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("could not Get Self Entry for the station"));) + } + else + { + //Pass the peer's staId + pSirSmeJoinRsp->staId = pStaDs->staIndex; + pSirSmeJoinRsp->ucastSig = pStaDs->ucUcastSig; + pSirSmeJoinRsp->bcastSig = pStaDs->ucBcastSig; + pSirSmeJoinRsp->timingMeasCap = pStaDs->timingMeasCap; +#ifdef FEATURE_WLAN_TDLS + pSirSmeJoinRsp->tdls_prohibited = + psessionEntry->tdls_prohibited; + pSirSmeJoinRsp->tdls_chan_swit_prohibited = + psessionEntry->tdls_chan_swit_prohibited; +#endif + pSirSmeJoinRsp->nss = pStaDs->nss; + pSirSmeJoinRsp->max_rate_flags = + lim_get_max_rate_flags(pMac, pStaDs); + } + } + + pSirSmeJoinRsp->beaconLength = 0; + pSirSmeJoinRsp->assocReqLength = 0; + pSirSmeJoinRsp->assocRspLength = 0; +#ifdef WLAN_FEATURE_VOWIFI_11R + pSirSmeJoinRsp->parsedRicRspLen = 0; +#endif +#ifdef FEATURE_WLAN_ESE + pSirSmeJoinRsp->tspecIeLen = 0; +#endif + + if(resultCode == eSIR_SME_SUCCESS) + { + + if(psessionEntry->beacon != NULL) + { + pSirSmeJoinRsp->beaconLength = psessionEntry->bcnLen; + vos_mem_copy( pSirSmeJoinRsp->frames, psessionEntry->beacon, + pSirSmeJoinRsp->beaconLength); + vos_mem_free( psessionEntry->beacon); + psessionEntry->beacon = NULL; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog(pMac, LOG1, FL("Beacon=%d"), psessionEntry->bcnLen);) +#endif + } + + if(psessionEntry->assocReq != NULL) + { + pSirSmeJoinRsp->assocReqLength = psessionEntry->assocReqLen; + vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen, + psessionEntry->assocReq, pSirSmeJoinRsp->assocReqLength); + vos_mem_free( psessionEntry->assocReq); + psessionEntry->assocReq = NULL; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d"), psessionEntry->assocReqLen);) +#endif + } + if(psessionEntry->assocRsp != NULL) + { + pSirSmeJoinRsp->assocRspLength = psessionEntry->assocRspLen; + vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen + + psessionEntry->assocReqLen, + psessionEntry->assocRsp, + pSirSmeJoinRsp->assocRspLength); + vos_mem_free( psessionEntry->assocRsp); + psessionEntry->assocRsp = NULL; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if(psessionEntry->ricData != NULL) + { + pSirSmeJoinRsp->parsedRicRspLen = psessionEntry->RICDataLen; + vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen + + psessionEntry->assocReqLen + psessionEntry->assocRspLen, + psessionEntry->ricData, pSirSmeJoinRsp->parsedRicRspLen); + vos_mem_free(psessionEntry->ricData); + psessionEntry->ricData = NULL; + PELOG1(limLog(pMac, LOG1, FL("RicLength=%d"), pSirSmeJoinRsp->parsedRicRspLen);) + } +#endif +#ifdef FEATURE_WLAN_ESE + if(psessionEntry->tspecIes != NULL) + { + pSirSmeJoinRsp->tspecIeLen = psessionEntry->tspecLen; + vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen + + psessionEntry->assocReqLen + psessionEntry->assocRspLen + + psessionEntry->RICDataLen, + psessionEntry->tspecIes, pSirSmeJoinRsp->tspecIeLen); + vos_mem_free(psessionEntry->tspecIes); + psessionEntry->tspecIes = NULL; + PELOG1(limLog(pMac, LOG1, FL("ESE-TspecLen=%d"), psessionEntry->tspecLen);) + } +#endif + pSirSmeJoinRsp->aid = psessionEntry->limAID; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d"), psessionEntry->assocRspLen);) +#endif + if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == + psessionEntry->apChanWidth) { + pSirSmeJoinRsp->vht_channel_width = eHT_CHANNEL_WIDTH_80MHZ; + } else if ((WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == + psessionEntry->apChanWidth) && + (psessionEntry->htSecondaryChannelOffset)) { + pSirSmeJoinRsp->vht_channel_width = eHT_CHANNEL_WIDTH_40MHZ; + } else { + pSirSmeJoinRsp->vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + } + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (psessionEntry->cc_switch_mode != VOS_MCC_TO_SCC_SWITCH_DISABLE) { + pSirSmeJoinRsp->HTProfile.htSupportedChannelWidthSet = + psessionEntry->htSupportedChannelWidthSet; + pSirSmeJoinRsp->HTProfile.htRecommendedTxWidthSet = + psessionEntry->htRecommendedTxWidthSet; + pSirSmeJoinRsp->HTProfile.htSecondaryChannelOffset = + psessionEntry->htSecondaryChannelOffset; + pSirSmeJoinRsp->HTProfile.dot11mode = + psessionEntry->dot11mode; + pSirSmeJoinRsp->HTProfile.htCapability = + psessionEntry->htCapability; +#ifdef WLAN_FEATURE_11AC + pSirSmeJoinRsp->HTProfile.vhtCapability = + psessionEntry->vhtCapability; + pSirSmeJoinRsp->HTProfile.vhtTxChannelWidthSet = + psessionEntry->vhtTxChannelWidthSet; + pSirSmeJoinRsp->HTProfile.apCenterChan = + psessionEntry->apCenterChan; + pSirSmeJoinRsp->HTProfile.apChanWidth = + psessionEntry->apChanWidth; +#endif + } +#endif + } + else + { + + if(psessionEntry->beacon != NULL) + { + vos_mem_free(psessionEntry->beacon); + psessionEntry->beacon = NULL; + } + + if(psessionEntry->assocReq != NULL) + { + vos_mem_free( psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + } + + if(psessionEntry->assocRsp != NULL) + { + vos_mem_free( psessionEntry->assocRsp); + psessionEntry->assocRsp = NULL; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if(psessionEntry->ricData != NULL) + { + vos_mem_free( psessionEntry->ricData); + psessionEntry->ricData = NULL; + } +#endif + +#ifdef FEATURE_WLAN_ESE + if(psessionEntry->tspecIes != NULL) + { + vos_mem_free(psessionEntry->tspecIes); + psessionEntry->tspecIes = NULL; + } +#endif + } + /* Send supported NSS 1x1 to SME */ + pSirSmeJoinRsp->supported_nss_1x1 = + psessionEntry->supported_nss_1x1; + PELOG1(limLog(pMac, LOG1, + FL("SME Join Rsp is supported NSS 1X1: %d"), + pSirSmeJoinRsp->supported_nss_1x1);) + } + + + pSirSmeJoinRsp->messageType = msgType; + pSirSmeJoinRsp->length = (tANI_U16) rspLen; + pSirSmeJoinRsp->statusCode = resultCode; + pSirSmeJoinRsp->protStatusCode = protStatusCode; + + /* Update SME session ID and transaction Id */ + pSirSmeJoinRsp->sessionId = smesessionId; + pSirSmeJoinRsp->transactionId = smetransactionId; + + if(IS_MCC_SUPPORTED && limIsLinkSuspended( pMac ) ) + { + if( psessionEntry && psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE ) + { + +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability) + { + ePhyChanBondState htSecondaryChannelOffset; + /*Get 11ac cbState from 11n cbState*/ + htSecondaryChannelOffset = limGet11ACPhyCBState(pMac, + psessionEntry->currentOperChannel, + psessionEntry->htSecondaryChannelOffset, + psessionEntry->apCenterChan, + psessionEntry); + peSetResumeChannel( pMac, psessionEntry->currentOperChannel, htSecondaryChannelOffset); + } + else +#endif + peSetResumeChannel( pMac, psessionEntry->currentOperChannel, psessionEntry->htSecondaryChannelOffset); + } + else + { + peSetResumeChannel( pMac, 0, 0); + } + limResumeLink( pMac, limSendSmeJoinReassocRspAfterResume, + (tANI_U32*) pSirSmeJoinRsp ); + } + else + { + limSendSmeJoinReassocRspAfterResume( pMac, eHAL_STATUS_SUCCESS, + (tANI_U32*) pSirSmeJoinRsp ); + } +} /*** end limSendSmeJoinReassocRsp() ***/ + + + +/** + * limSendSmeStartBssRsp() + * + *FUNCTION: + * This function is called to send eWNI_SME_START_BSS_RSP + * message to applications above MAC Software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates message type + * @param resultCode Indicates the result of previously issued + * eWNI_SME_msgType_REQ message + * + * @return None + */ + +void +limSendSmeStartBssRsp(tpAniSirGlobal pMac, + tANI_U16 msgType, tSirResultCodes resultCode,tpPESession psessionEntry, + tANI_U8 smesessionId,tANI_U16 smetransactionId) +{ + + + tANI_U16 size = 0; + tSirMsgQ mmhMsg; + tSirSmeStartBssRsp *pSirSmeRsp; + tANI_U16 ieLen; + tANI_U16 ieOffset, curLen; + + PELOG1(limLog(pMac, LOG1, FL("Sending message type %d with reasonCode %s"), + msgType, limResultCodeStr(resultCode));) + + size = sizeof(tSirSmeStartBssRsp); + + if(psessionEntry == NULL) + { + pSirSmeRsp = vos_mem_malloc(size); + if ( NULL == pSirSmeRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP,FL("call to AllocateMemory failed for eWNI_SME_START_BSS_RSP")); + return; + } + vos_mem_set((tANI_U8*)pSirSmeRsp, size, 0); + + } + else + { + //subtract size of beaconLength + Mac Hdr + Fixed Fields before SSID + ieOffset = sizeof(tAniBeaconStruct) + SIR_MAC_B_PR_SSID_OFFSET; + ieLen = psessionEntry->schBeaconOffsetBegin + + psessionEntry->schBeaconOffsetEnd - ieOffset; + //calculate the memory size to allocate + size += ieLen; + + pSirSmeRsp = vos_mem_malloc(size); + if ( NULL == pSirSmeRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_START_BSS_RSP")); + + return; + } + vos_mem_set((tANI_U8*)pSirSmeRsp, size, 0); + size = sizeof(tSirSmeStartBssRsp); + if (resultCode == eSIR_SME_SUCCESS) + { + + sirCopyMacAddr(pSirSmeRsp->bssDescription.bssId, psessionEntry->bssId); + + /* Read beacon interval from session */ + pSirSmeRsp->bssDescription.beaconInterval = (tANI_U16) psessionEntry->beaconParams.beaconInterval; + pSirSmeRsp->bssType = psessionEntry->bssType; + + if (cfgGetCapabilityInfo( pMac, &pSirSmeRsp->bssDescription.capabilityInfo,psessionEntry) + != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("could not retrieve Capabilities value")); + + limGetPhyMode(pMac, (tANI_U32 *)&pSirSmeRsp->bssDescription.nwType, psessionEntry); + + pSirSmeRsp->bssDescription.channelId = psessionEntry->currentOperChannel; + + curLen = psessionEntry->schBeaconOffsetBegin - ieOffset; + vos_mem_copy( (tANI_U8 *) &pSirSmeRsp->bssDescription.ieFields, + psessionEntry->pSchBeaconFrameBegin + ieOffset, + (tANI_U32)curLen); + + vos_mem_copy( ((tANI_U8 *) &pSirSmeRsp->bssDescription.ieFields) + curLen, + psessionEntry->pSchBeaconFrameEnd, + (tANI_U32)psessionEntry->schBeaconOffsetEnd); + + + //subtracting size of length indicator itself and size of pointer to ieFields + pSirSmeRsp->bssDescription.length = sizeof(tSirBssDescription) - + sizeof(tANI_U16) - sizeof(tANI_U32) + + ieLen; + //This is the size of the message, subtracting the size of the pointer to ieFields + size += ieLen - sizeof(tANI_U32); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (psessionEntry->cc_switch_mode + != VOS_MCC_TO_SCC_SWITCH_DISABLE) { + pSirSmeRsp->HTProfile.htSupportedChannelWidthSet = + psessionEntry->htSupportedChannelWidthSet; + pSirSmeRsp->HTProfile.htRecommendedTxWidthSet = + psessionEntry->htRecommendedTxWidthSet; + pSirSmeRsp->HTProfile.htSecondaryChannelOffset = + psessionEntry->htSecondaryChannelOffset; + pSirSmeRsp->HTProfile.dot11mode = + psessionEntry->dot11mode; + pSirSmeRsp->HTProfile.htCapability = + psessionEntry->htCapability; +#ifdef WLAN_FEATURE_11AC + pSirSmeRsp->HTProfile.vhtCapability = + psessionEntry->vhtCapability; + pSirSmeRsp->HTProfile.vhtTxChannelWidthSet = + psessionEntry->vhtTxChannelWidthSet; + pSirSmeRsp->HTProfile.apCenterChan = + psessionEntry->apCenterChan; + pSirSmeRsp->HTProfile.apChanWidth = + psessionEntry->apChanWidth; +#endif + } +#endif + } + + + + + } + + pSirSmeRsp->messageType = msgType; + pSirSmeRsp->length = size; + + /* Update SME session Id and transaction Id */ + pSirSmeRsp->sessionId = smesessionId; + pSirSmeRsp->transactionId = smetransactionId; + pSirSmeRsp->statusCode = resultCode; + if(psessionEntry != NULL ) + pSirSmeRsp->staId = psessionEntry->staId; //else it will be always zero smeRsp StaID = 0 + + + mmhMsg.type = msgType; + mmhMsg.bodyptr = pSirSmeRsp; + mmhMsg.bodyval = 0; + if(psessionEntry == NULL) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_START_BSS_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} /*** end limSendSmeStartBssRsp() ***/ + + + + + +#define LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED 20 +#define LIM_SIZE_OF_EACH_BSS 400 // this is a rough estimate + + +/** + * limSendSmeScanRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_SCAN_RSP message to applications above MAC + * Software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param length Indicates length of message + * @param resultCode Indicates the result of previously issued + * eWNI_SME_SCAN_REQ message + * + * @return None + */ + +void +limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, + tSirResultCodes resultCode,tANI_U8 smesessionId,tANI_U16 smetranscationId) +{ + tSirMsgQ mmhMsg; + tpSirSmeScanRsp pSirSmeScanRsp=NULL; + tLimScanResultNode *ptemp = NULL; + tANI_U16 msgLen, allocLength, curMsgLen = 0; + tANI_U16 i, bssCount; + tANI_U8 *pbBuf; + tSirBssDescription *pDesc; + + if (resultCode != eSIR_SME_SUCCESS) + { + limPostSmeScanRspMessage(pMac, length, resultCode,smesessionId,smetranscationId); + return; + } + + mmhMsg.type = eWNI_SME_SCAN_RSP; + i = 0; + bssCount = 0; + msgLen = 0; + allocLength = LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED * LIM_SIZE_OF_EACH_BSS; + pSirSmeScanRsp = vos_mem_malloc(allocLength); + if ( NULL == pSirSmeScanRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_SCAN_RSP")); + + return; + } + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + //when ptemp is not NULL it is a left over + ptemp = pMac->lim.gLimCachedScanHashTable[i]; + while(ptemp) + { + pbBuf = ((tANI_U8 *)pSirSmeScanRsp) + msgLen; + if(0 == bssCount) + { + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + } + else + { + msgLen += ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = (tSirBssDescription *)pbBuf; + } + if( (allocLength < msgLen) || + (LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED <= bssCount++) ) + { + pSirSmeScanRsp->statusCode = + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + pSirSmeScanRsp = vos_mem_malloc(allocLength); + if ( NULL == pSirSmeScanRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_SCAN_RSP")); + return; + } + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + bssCount = 1; + } + curMsgLen = msgLen; + + pDesc->length + = ptemp->bssDescription.length; + vos_mem_copy( (tANI_U8 *) &pDesc->bssId, + (tANI_U8 *) &ptemp->bssDescription.bssId, + ptemp->bssDescription.length); + limLog(pMac, LOG1, FL("ScanRsp : msgLen %d, bssDescr Len=%d BssID "MAC_ADDRESS_STR), + msgLen, ptemp->bssDescription.length, + MAC_ADDR_ARRAY(ptemp->bssDescription.bssId)); + + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + ptemp = ptemp->next; + } //while(ptemp) + } //for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + + if(0 == bssCount) + { + length = sizeof(tSirSmeScanRsp); + limPostSmeScanRspMessage(pMac, length, resultCode, smesessionId, smetranscationId); + if (NULL != pSirSmeScanRsp) + { + vos_mem_free( pSirSmeScanRsp); + pSirSmeScanRsp = NULL; + } + } + else + { + // send last message + pSirSmeScanRsp->statusCode = eSIR_SME_SUCCESS; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + + /* Update SME session Id and SME transcation Id */ + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + mmhMsg.type = eWNI_SME_SCAN_RSP; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS"));) + } + // Discard previously cached scan results + limReInitScanResults(pMac); + + return; + +} /*** end limSendSmeScanRsp() ***/ + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * limSendSmeLfrScanRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_SCAN_RSP message to applications above MAC Software + * only for sending up the roam candidates. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param length Indicates length of message + * @param resultCode Indicates the result of previously issued + * eWNI_SME_SCAN_REQ message + * + * @return None + */ + +void +limSendSmeLfrScanRsp(tpAniSirGlobal pMac, tANI_U16 length, + tSirResultCodes resultCode,tANI_U8 smesessionId,tANI_U16 smetranscationId) +{ + tSirMsgQ mmhMsg; + tpSirSmeScanRsp pSirSmeScanRsp=NULL; + tLimScanResultNode *ptemp = NULL; + tANI_U16 msgLen, allocLength, curMsgLen = 0; + tANI_U16 i, bssCount, j; + tANI_U8 *pbBuf; + tSirBssDescription *pDesc; + tANI_S16 scanEntriesLeft = 0; + tANI_U8 *currentBssid = + pMac->roam.roamSession[smesessionId].connectedProfile.bssid; + struct roam_ext_params *roam_params; + bool ssid_list_match = false; + + roam_params = &pMac->roam.configParam.roam_params; + + limLog(pMac, LOG1, + FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s\n"), + length, limResultCodeStr(resultCode)); + + if (resultCode != eSIR_SME_SUCCESS) + { + limPostSmeScanRspMessage(pMac, length, resultCode,smesessionId,smetranscationId); + return; + } + + mmhMsg.type = eWNI_SME_SCAN_RSP; + i = 0; + bssCount = 0; + msgLen = 0; + allocLength = LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED * LIM_SIZE_OF_EACH_BSS; + pSirSmeScanRsp = vos_mem_malloc(allocLength); + if ( NULL == pSirSmeScanRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + + return; + } + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + //when ptemp is not NULL it is a left over + ptemp = pMac->lim.gLimCachedLfrScanHashTable[i]; + while(ptemp) + { + if (vos_mem_compare(ptemp->bssDescription.bssId, + currentBssid, + sizeof(tSirMacAddr))) + { + ptemp = ptemp->next; + continue; + } + + pbBuf = ((tANI_U8 *)pSirSmeScanRsp) + msgLen; + if(0 == bssCount) + { + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + } + else + { + msgLen += ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = (tSirBssDescription *)pbBuf; + } + if ( (allocLength < msgLen) || + (LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED <= bssCount++) ) + { + pSirSmeScanRsp->statusCode = + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + pSirSmeScanRsp = vos_mem_malloc(allocLength); + if ( NULL == pSirSmeScanRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + return; + } + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + bssCount = 1; + } + curMsgLen = msgLen; + + PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"), + msgLen, ptemp->bssDescription.length);) + pDesc->length + = ptemp->bssDescription.length; + vos_mem_copy( (tANI_U8 *) &pDesc->bssId, + (tANI_U8 *) &ptemp->bssDescription.bssId, + ptemp->bssDescription.length); + + PELOG2(limLog(pMac, LOG2, FL("BssId ")); + limPrintMacAddr(pMac, ptemp->bssDescription.bssId, LOG2);) + + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + ptemp = ptemp->next; + } //while(ptemp) + } //for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + + /* Repeat for normal scan cache */ + if (pMac->roam.roamSession[smesessionId].connectedProfile.SSID.length != 0) { + tSirMacSSid *pSsid = &pMac->roam.roamSession[smesessionId].connectedProfile.SSID; + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + ptemp = pMac->lim.gLimCachedScanHashTable[i]; + while(ptemp) + { + ssid_list_match = false; + for (j = 0; j < roam_params->num_ssid_allowed_list; j++) { + if(vos_mem_compare((tANI_U8* ) ptemp->bssDescription.ieFields+1, + (tANI_U8 *) &roam_params->ssid_allowed_list[j].length, + (tANI_U8) (roam_params->ssid_allowed_list[j].length + 1))) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + FL("SSID Match with allowedlist")); + ssid_list_match = true; + break; + } + } + + if(ssid_list_match || + vos_mem_compare((tANI_U8* ) ptemp->bssDescription.ieFields+1, + (tANI_U8 *) &pSsid->length, + (tANI_U8) (pSsid->length + 1))) + { + if (vos_mem_compare(ptemp->bssDescription.bssId, + currentBssid, + sizeof(tSirMacAddr))) + { + ptemp = ptemp->next; + continue; + } + + pbBuf = ((tANI_U8 *)pSirSmeScanRsp) + msgLen; + if(0 == bssCount) + { + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + } + else + { + msgLen += ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = (tSirBssDescription *)pbBuf; + } + if ( (allocLength < msgLen) || + (LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED <= bssCount++) ) + { + pSirSmeScanRsp->statusCode = + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + pSirSmeScanRsp = vos_mem_malloc(allocLength); + if ( NULL == pSirSmeScanRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + return; + } + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + bssCount = 1; + } + curMsgLen = msgLen; + + PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"), + msgLen, ptemp->bssDescription.length);) + pDesc->length + = ptemp->bssDescription.length; + vos_mem_copy((tANI_U8 *) &pDesc->bssId, + (tANI_U8 *) &ptemp->bssDescription.bssId, + ptemp->bssDescription.length); + + PELOG2(limLog(pMac, LOG2, FL("BssId ")); + limPrintMacAddr(pMac, ptemp->bssDescription.bssId, LOG2);) + + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + } else { + PELOG2(limLog(pMac, LOG2, FL("SSID Mismatch with BSSID")); + limPrintMacAddr(pMac, ptemp->bssDescription.bssId, LOG2);) + } + ptemp = ptemp->next; + } //while(ptemp) + } //for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + } + if (0 == bssCount) + { + limPostSmeScanRspMessage(pMac, length, resultCode, smesessionId, smetranscationId); + if (NULL != pSirSmeScanRsp) + { + vos_mem_free( pSirSmeScanRsp); + pSirSmeScanRsp = NULL; + } + } + else + { + // send last message + pSirSmeScanRsp->statusCode = eSIR_SME_SUCCESS; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + + /* Update SME session Id and SME transcation Id */ + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + mmhMsg.type = eWNI_SME_SCAN_RSP; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS\n"));) + } + // Discard previously cached scan results + limReInitLfrScanResults(pMac); + + // delete the returned entries from normal cache (gLimCachedScanHashTable) + scanEntriesLeft = limRemoveSsidFromScanCache(pMac, + &pMac->roam.roamSession[smesessionId].connectedProfile.SSID); + PELOG2(limLog(pMac, + LOG2, + FL("Scan Entries Left after cleanup: %d", + scanEntriesLeft))); + + return; + +} /*** end limSendSmeLfrScanRsp() ***/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +/** + * limPostSmeScanRspMessage() + * + *FUNCTION: + * This function is called by limSendSmeScanRsp() to send + * eWNI_SME_SCAN_RSP message with failed result code + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param length Indicates length of message + * @param resultCode failed result code + * + * @return None + */ + +void +limPostSmeScanRspMessage(tpAniSirGlobal pMac, + tANI_U16 length, + tSirResultCodes resultCode,tANI_U8 smesessionId, tANI_U16 smetransactionId) +{ + tpSirSmeScanRsp pSirSmeScanRsp; + tSirMsgQ mmhMsg; + + limLog(pMac, LOG1, + FL("limPostSmeScanRspMessage: send SME_SCAN_RSP (len %d, reasonCode %s). "), + length, limResultCodeStr(resultCode)); + + pSirSmeScanRsp = vos_mem_malloc(length); + if ( NULL == pSirSmeScanRsp ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for eWNI_SME_SCAN_RSP")); + return; + } + vos_mem_set((void*)pSirSmeScanRsp, length, 0); + + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = length; + + if(sizeof(tSirSmeScanRsp) <= length) + { + pSirSmeScanRsp->bssDescription->length = sizeof(tSirBssDescription); + } + + pSirSmeScanRsp->statusCode = resultCode; + + /*Update SME session Id and transaction Id */ + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetransactionId; + + mmhMsg.type = eWNI_SME_SCAN_RSP; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_SCAN_RSP_EVENT, NULL, (tANI_U16)resultCode, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; + +} /*** limPostSmeScanRspMessage ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * limSendSmeOemDataRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_OEM_DATA_RSP message to applications above MAC + * Software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param pMsgBuf Indicates the mlm message + * @param resultCode Indicates the result of previously issued + * eWNI_SME_OEM_DATA_RSP message + * + * @return None + */ + +void limSendSmeOemDataRsp(tpAniSirGlobal pMac, tANI_U32* pMsgBuf, tSirResultCodes resultCode) +{ + tSirMsgQ mmhMsg; + tSirOemDataRsp* pSirSmeOemDataRsp=NULL; + tLimMlmOemDataRsp* pMlmOemDataRsp=NULL; + tANI_U16 msgLength; + + + //get the pointer to the mlm message + pMlmOemDataRsp = (tLimMlmOemDataRsp*)(pMsgBuf); + + msgLength = sizeof(tSirOemDataRsp); + + //now allocate memory for the char buffer + pSirSmeOemDataRsp = vos_mem_malloc(msgLength); + if (NULL == pSirSmeOemDataRsp) + { + limLog(pMac, LOGP, FL("call to AllocateMemory failed for pSirSmeOemDataRsp")); + return; + } + +#if defined (ANI_LITTLE_BYTE_ENDIAN) + sirStoreU16N((tANI_U8*)&pSirSmeOemDataRsp->length, msgLength); + sirStoreU16N((tANI_U8*)&pSirSmeOemDataRsp->messageType, eWNI_SME_OEM_DATA_RSP); +#else + pSirSmeOemDataRsp->length = msgLength; + pSirSmeOemDataRsp->messageType = eWNI_SME_OEM_DATA_RSP; +#endif + + vos_mem_copy(pSirSmeOemDataRsp->oemDataRsp, pMlmOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); + + //Now free the memory from MLM Rsp Message + vos_mem_free(pMlmOemDataRsp); + + mmhMsg.type = eWNI_SME_OEM_DATA_RSP; + mmhMsg.bodyptr = pSirSmeOemDataRsp; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} /*** limSendSmeOemDataRsp ***/ + +#endif + + +void limSendSmeDisassocDeauthNtf( tpAniSirGlobal pMac, + eHalStatus status, tANI_U32 *pCtx ) +{ + tSirMsgQ mmhMsg; + tSirMsgQ *pMsg = (tSirMsgQ*) pCtx; + + mmhMsg.type = pMsg->type; + mmhMsg.bodyptr = pMsg; + mmhMsg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} +/** + * limSendSmeDisassocNtf() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() to send + * eWNI_SME_DISASSOC_RSP/IND message to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * This function is used for sending eWNI_SME_DISASSOC_CNF, + * or eWNI_SME_DISASSOC_IND to host depending on + * disassociation trigger. + * + * @param peerMacAddr Indicates the peer MAC addr to which + * disassociate was initiated + * @param reasonCode Indicates the reason for Disassociation + * @param disassocTrigger Indicates the trigger for Disassociation + * @param aid Indicates the STAID. This parameter is + * present only on AP. + * + * @return None + */ +void +limSendSmeDisassocNtf(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirResultCodes reasonCode, + tANI_U16 disassocTrigger, + tANI_U16 aid, + tANI_U8 smesessionId, + tANI_U16 smetransactionId, + tpPESession psessionEntry) +{ + + tANI_U8 *pBuf; + tSirSmeDisassocRsp *pSirSmeDisassocRsp; + tSirSmeDisassocInd *pSirSmeDisassocInd; + tANI_U32 *pMsg; + bool failure = false; + + limLog(pMac, LOG1, FL("Disassoc Ntf with trigger : %d" + "reasonCode: %d"), + disassocTrigger, + reasonCode); + + switch (disassocTrigger) + { + case eLIM_PEER_ENTITY_DISASSOC: + if (reasonCode != eSIR_SME_STA_NOT_ASSOCIATED) { + failure = true; + goto error; + } + + case eLIM_HOST_DISASSOC: + /** + * Disassociation response due to + * host triggered disassociation + */ + + pSirSmeDisassocRsp = vos_mem_malloc(sizeof(tSirSmeDisassocRsp)); + if ( NULL == pSirSmeDisassocRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_DISASSOC_RSP")); + + failure = true; + goto error; + } + limLog(pMac, LOG1, FL("send eWNI_SME_DISASSOC_RSP with " + "retCode: %d for "MAC_ADDRESS_STR),reasonCode, + MAC_ADDR_ARRAY(peerMacAddr)); + pSirSmeDisassocRsp->messageType = eWNI_SME_DISASSOC_RSP; + pSirSmeDisassocRsp->length = sizeof(tSirSmeDisassocRsp); + //sessionId + pBuf = (tANI_U8 *) &pSirSmeDisassocRsp->sessionId; + *pBuf = smesessionId; + pBuf++; + + //transactionId + limCopyU16(pBuf, smetransactionId); + pBuf += sizeof(tANI_U16); + + //statusCode + limCopyU32(pBuf, reasonCode); + pBuf += sizeof(tSirResultCodes); + + //peerMacAddr + vos_mem_copy( pBuf, peerMacAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + // Clear Station Stats + //for sta, it is always 1, IBSS is handled at halInitSta + + + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + + limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_RSP_EVENT, + psessionEntry, (tANI_U16)reasonCode, 0); +#endif + pMsg = (tANI_U32*) pSirSmeDisassocRsp; + break; + + default: + /** + * Disassociation indication due to Disassociation + * frame reception from peer entity or due to + * loss of link with peer entity. + */ + pSirSmeDisassocInd = vos_mem_malloc(sizeof(tSirSmeDisassocInd)); + if ( NULL == pSirSmeDisassocInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_DISASSOC_IND")); + + failure = true; + goto error; + } + limLog(pMac, LOG1, FL("send eWNI_SME_DISASSOC_IND with " + "retCode: %d for "MAC_ADDRESS_STR),reasonCode, + MAC_ADDR_ARRAY(peerMacAddr)); + pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND; + pSirSmeDisassocInd->length = sizeof(tSirSmeDisassocInd); + + /* Update SME session Id and Transaction Id */ + pSirSmeDisassocInd->sessionId = smesessionId; + pSirSmeDisassocInd->transactionId = smetransactionId; + pSirSmeDisassocInd->reasonCode = reasonCode; + pBuf = (tANI_U8 *) &pSirSmeDisassocInd->statusCode; + + limCopyU32(pBuf, reasonCode); + pBuf += sizeof(tSirResultCodes); + + vos_mem_copy( pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + vos_mem_copy( pBuf, peerMacAddr, sizeof(tSirMacAddr)); + + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, + psessionEntry, (tANI_U16)reasonCode, 0); +#endif + pMsg = (tANI_U32*) pSirSmeDisassocInd; + + break; + } + +error: + /* Delete the PE session Created */ + if ((psessionEntry != NULL) && + (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry))) { + peDeleteSession(pMac,psessionEntry); + } + + if (false == failure) + limSendSmeDisassocDeauthNtf(pMac, eHAL_STATUS_SUCCESS, + (tANI_U32*) pMsg); +} /*** end limSendSmeDisassocNtf() ***/ + + +/** ----------------------------------------------------------------- + \brief limSendSmeDisassocInd() - sends SME_DISASSOC_IND + + After receiving disassociation frame from peer entity, this + function sends a eWNI_SME_DISASSOC_IND to SME with a specific + reason code. + + \param pMac - global mac structure + \param pStaDs - station dph hash node + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmeDisassocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirSmeDisassocInd *pSirSmeDisassocInd; + + pSirSmeDisassocInd = vos_mem_malloc(sizeof(tSirSmeDisassocInd)); + if ( NULL == pSirSmeDisassocInd ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for eWNI_SME_DISASSOC_IND")); + return; + } + + pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND; + pSirSmeDisassocInd->length = sizeof(tSirSmeDisassocInd); + + pSirSmeDisassocInd->sessionId = psessionEntry->smeSessionId; + pSirSmeDisassocInd->transactionId = psessionEntry->transactionId; + pSirSmeDisassocInd->statusCode = pStaDs->mlmStaContext.disassocReason; + pSirSmeDisassocInd->reasonCode = pStaDs->mlmStaContext.disassocReason; + + vos_mem_copy( pSirSmeDisassocInd->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + + vos_mem_copy( pSirSmeDisassocInd->peerMacAddr, pStaDs->staAddr, sizeof(tSirMacAddr)); + + pSirSmeDisassocInd->staId = pStaDs->staIndex; + + mmhMsg.type = eWNI_SME_DISASSOC_IND; + mmhMsg.bodyptr = pSirSmeDisassocInd; + mmhMsg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, psessionEntry, 0, (tANI_U16)pStaDs->mlmStaContext.disassocReason); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} /*** end limSendSmeDisassocInd() ***/ + + +/** ----------------------------------------------------------------- + \brief limSendSmeDeauthInd() - sends SME_DEAUTH_IND + + After receiving deauthentication frame from peer entity, this + function sends a eWNI_SME_DEAUTH_IND to SME with a specific + reason code. + + \param pMac - global mac structure + \param pStaDs - station dph hash node + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmeDeauthInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirSmeDeauthInd *pSirSmeDeauthInd; + + pSirSmeDeauthInd = vos_mem_malloc(sizeof(tSirSmeDeauthInd)); + if ( NULL == pSirSmeDeauthInd ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for eWNI_SME_DEAUTH_IND ")); + return; + } + + pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND; + pSirSmeDeauthInd->length = sizeof(tSirSmeDeauthInd); + + pSirSmeDeauthInd->sessionId = psessionEntry->smeSessionId; + pSirSmeDeauthInd->transactionId = psessionEntry->transactionId; + if(eSIR_INFRA_AP_MODE == psessionEntry->bssType) + { + pSirSmeDeauthInd->statusCode = (tSirResultCodes)pStaDs->mlmStaContext.cleanupTrigger; + } + else + { + //Need to indicatet he reascon code over the air + pSirSmeDeauthInd->statusCode = (tSirResultCodes)pStaDs->mlmStaContext.disassocReason; + } + //BSSID + vos_mem_copy( pSirSmeDeauthInd->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + //peerMacAddr + vos_mem_copy( pSirSmeDeauthInd->peerMacAddr, pStaDs->staAddr, sizeof(tSirMacAddr)); + pSirSmeDeauthInd->reasonCode = pStaDs->mlmStaContext.disassocReason; + + + if (eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON == + pStaDs->mlmStaContext.disassocReason) + + pSirSmeDeauthInd->rssi = pStaDs->del_sta_ctx_rssi; + + pSirSmeDeauthInd->staId = pStaDs->staIndex; + + mmhMsg.type = eWNI_SME_DEAUTH_IND; + mmhMsg.bodyptr = pSirSmeDeauthInd; + mmhMsg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, psessionEntry, 0, pStaDs->mlmStaContext.cleanupTrigger); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} /*** end limSendSmeDeauthInd() ***/ + +#ifdef FEATURE_WLAN_TDLS +/** + * limSendSmeTDLSDelStaInd() + * + *FUNCTION: + * This function is called to send the TDLS STA context deletion to SME. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param pMac - Pointer to global MAC structure + * @param pStaDs - Pointer to internal STA Datastructure + * @param psessionEntry - Pointer to the session entry + * @param reasonCode - Reason for TDLS sta deletion + * @return None + */ +void +limSendSmeTDLSDelStaInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry, tANI_U16 reasonCode) +{ + tSirMsgQ mmhMsg; + tSirTdlsDelStaInd *pSirTdlsDelStaInd; + + pSirTdlsDelStaInd = vos_mem_malloc(sizeof(tSirTdlsDelStaInd)); + if ( NULL == pSirTdlsDelStaInd ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for eWNI_SME_TDLS_DEL_STA_IND ")); + return; + } + + //messageType + pSirTdlsDelStaInd->messageType = eWNI_SME_TDLS_DEL_STA_IND; + pSirTdlsDelStaInd->length = sizeof(tSirTdlsDelStaInd); + + //sessionId + pSirTdlsDelStaInd->sessionId = psessionEntry->smeSessionId; + + //peerMacAddr + vos_mem_copy( pSirTdlsDelStaInd->peerMac, pStaDs->staAddr, sizeof(tSirMacAddr)); + + //staId + limCopyU16((tANI_U8*)(&pSirTdlsDelStaInd->staId), (tANI_U16)pStaDs->staIndex); + + //reasonCode + limCopyU16((tANI_U8*)(&pSirTdlsDelStaInd->reasonCode), reasonCode); + + mmhMsg.type = eWNI_SME_TDLS_DEL_STA_IND; + mmhMsg.bodyptr = pSirTdlsDelStaInd; + mmhMsg.bodyval = 0; + + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +}/*** end limSendSmeTDLSDelStaInd() ***/ + +/** + * limSendSmeTDLSDeleteAllPeerInd() + * + *FUNCTION: + * This function is called to send the eWNI_SME_TDLS_DEL_ALL_PEER_IND + * message to SME. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param pMac - Pointer to global MAC structure + * @param psessionEntry - Pointer to the session entry + * @return None + */ +void +limSendSmeTDLSDeleteAllPeerInd(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirTdlsDelAllPeerInd *pSirTdlsDelAllPeerInd; + + pSirTdlsDelAllPeerInd = vos_mem_malloc(sizeof(tSirTdlsDelAllPeerInd)); + if ( NULL == pSirTdlsDelAllPeerInd ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for eWNI_SME_TDLS_DEL_ALL_PEER_IND")); + return; + } + + //messageType + pSirTdlsDelAllPeerInd->messageType = eWNI_SME_TDLS_DEL_ALL_PEER_IND; + pSirTdlsDelAllPeerInd->length = sizeof(tSirTdlsDelAllPeerInd); + + //sessionId + pSirTdlsDelAllPeerInd->sessionId = psessionEntry->smeSessionId; + + mmhMsg.type = eWNI_SME_TDLS_DEL_ALL_PEER_IND; + mmhMsg.bodyptr = pSirTdlsDelAllPeerInd; + mmhMsg.bodyval = 0; + + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +}/*** end limSendSmeTDLSDeleteAllPeerInd() ***/ + +/** + * limSendSmeMgmtTXCompletion() + * + *FUNCTION: + * This function is called to send the eWNI_SME_MGMT_FRM_TX_COMPLETION_IND + * message to SME. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param pMac - Pointer to global MAC structure + * @param psessionEntry - Pointer to the session entry + * @param txCompleteStatus - TX Complete Status of Mgmt Frames + * @return None + */ +void +limSendSmeMgmtTXCompletion(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tANI_U32 txCompleteStatus) +{ + tSirMsgQ mmhMsg; + tSirMgmtTxCompletionInd *pSirMgmtTxCompletionInd; + + pSirMgmtTxCompletionInd = vos_mem_malloc(sizeof(tSirMgmtTxCompletionInd)); + if ( NULL == pSirMgmtTxCompletionInd ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for eWNI_SME_MGMT_FRM_TX_COMPLETION_IND")); + return; + } + + //messageType + pSirMgmtTxCompletionInd->messageType = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND; + pSirMgmtTxCompletionInd->length = sizeof(tSirMgmtTxCompletionInd); + + //sessionId + pSirMgmtTxCompletionInd->sessionId = psessionEntry->smeSessionId; + + pSirMgmtTxCompletionInd->txCompleteStatus = txCompleteStatus; + + mmhMsg.type = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND; + mmhMsg.bodyptr = pSirMgmtTxCompletionInd; + mmhMsg.bodyval = 0; + + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +}/*** end limSendSmeTDLSDeleteAllPeerInd() ***/ + +void limSendSmeTdlsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, + void *events) +{ + tSirMsgQ mmhMsg; + + switch (msgType) + { + case SIR_HAL_TDLS_SHOULD_DISCOVER: + mmhMsg.type = eWNI_SME_TDLS_SHOULD_DISCOVER; + break; + case SIR_HAL_TDLS_SHOULD_TEARDOWN: + mmhMsg.type = eWNI_SME_TDLS_SHOULD_TEARDOWN; + break; + case SIR_HAL_TDLS_PEER_DISCONNECTED: + mmhMsg.type = eWNI_SME_TDLS_PEER_DISCONNECTED; + break; + } + + mmhMsg.bodyptr = events; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} +#endif /* FEATURE_WLAN_TDLS */ + + +/** + * limSendSmeDeauthNtf() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() to send + * eWNI_SME_DISASSOC_RSP/IND message to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * This function is used for sending eWNI_SME_DEAUTH_CNF or + * eWNI_SME_DEAUTH_IND to host depending on deauthentication trigger. + * + * @param peerMacAddr Indicates the peer MAC addr to which + * deauthentication was initiated + * @param reasonCode Indicates the reason for Deauthetication + * @param deauthTrigger Indicates the trigger for Deauthetication + * @param aid Indicates the STAID. This parameter is present + * only on AP. + * + * @return None + */ +void +limSendSmeDeauthNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tSirResultCodes reasonCode, + tANI_U16 deauthTrigger, tANI_U16 aid,tANI_U8 smesessionId, tANI_U16 smetransactionId) +{ + tANI_U8 *pBuf; + tSirSmeDeauthRsp *pSirSmeDeauthRsp; + tSirSmeDeauthInd *pSirSmeDeauthInd; + tpPESession psessionEntry; + tANI_U8 sessionId; + tANI_U32 *pMsg; + + psessionEntry = peFindSessionByBssid(pMac,peerMacAddr,&sessionId); + switch (deauthTrigger) + { + case eLIM_PEER_ENTITY_DEAUTH: + return; + + case eLIM_HOST_DEAUTH: + /** + * Deauthentication response to host triggered + * deauthentication. + */ + pSirSmeDeauthRsp = vos_mem_malloc(sizeof(tSirSmeDeauthRsp)); + if ( NULL == pSirSmeDeauthRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_DEAUTH_RSP")); + + return; + } + limLog(pMac, LOG1, FL("send eWNI_SME_DEAUTH_RSP with " + "retCode: %d for"MAC_ADDRESS_STR),reasonCode, + MAC_ADDR_ARRAY(peerMacAddr)); + pSirSmeDeauthRsp->messageType = eWNI_SME_DEAUTH_RSP; + pSirSmeDeauthRsp->length = sizeof(tSirSmeDeauthRsp); + pSirSmeDeauthRsp->statusCode = reasonCode; + pSirSmeDeauthRsp->sessionId = smesessionId; + pSirSmeDeauthRsp->transactionId = smetransactionId; + + pBuf = (tANI_U8 *) pSirSmeDeauthRsp->peerMacAddr; + vos_mem_copy( pBuf, peerMacAddr, sizeof(tSirMacAddr)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_RSP_EVENT, + psessionEntry, 0, (tANI_U16)reasonCode); +#endif + pMsg = (tANI_U32*)pSirSmeDeauthRsp; + + break; + + default: + /** + * Deauthentication indication due to Deauthentication + * frame reception from peer entity or due to + * loss of link with peer entity. + */ + pSirSmeDeauthInd = vos_mem_malloc(sizeof(tSirSmeDeauthInd)); + if ( NULL == pSirSmeDeauthInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_DEAUTH_Ind")); + + return; + } + limLog(pMac, LOG1, FL("send eWNI_SME_DEAUTH_IND with " + "retCode: %d for "MAC_ADDRESS_STR),reasonCode, + MAC_ADDR_ARRAY(peerMacAddr)); + pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND; + pSirSmeDeauthInd->length = sizeof(tSirSmeDeauthInd); + pSirSmeDeauthInd->reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; + + // sessionId + pBuf = (tANI_U8*) &pSirSmeDeauthInd->sessionId; + *pBuf++ = smesessionId; + + //transaction ID + limCopyU16(pBuf, smetransactionId); + pBuf += sizeof(tANI_U16); + + // status code + limCopyU32(pBuf, reasonCode); + pBuf += sizeof(tSirResultCodes); + + //bssId + vos_mem_copy( pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + //peerMacAddr + vos_mem_copy( pSirSmeDeauthInd->peerMacAddr, peerMacAddr, sizeof(tSirMacAddr)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, + psessionEntry, 0, (tANI_U16)reasonCode); +#endif //FEATURE_WLAN_DIAG_SUPPORT + pMsg = (tANI_U32*)pSirSmeDeauthInd; + + break; + } + + /*Delete the PE session created */ + if(psessionEntry != NULL) + { + peDeleteSession(pMac,psessionEntry); + } + + limSendSmeDisassocDeauthNtf( pMac, eHAL_STATUS_SUCCESS, + (tANI_U32*) pMsg ); + +} /*** end limSendSmeDeauthNtf() ***/ + + +/** + * limSendSmeWmStatusChangeNtf() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() to send + * eWNI_SME_WM_STATUS_CHANGE_NTF message to host. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param statusChangeCode Indicates the change in the wireless medium. + * @param statusChangeInfo Indicates the information associated with + * change in the wireless medium. + * @param infoLen Indicates the length of status change information + * being sent. + * + * @return None + */ +void +limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusChangeCode, + tANI_U32 *pStatusChangeInfo, tANI_U16 infoLen, tANI_U8 sessionId) +{ + tSirMsgQ mmhMsg; + tSirSmeWmStatusChangeNtf *pSirSmeWmStatusChangeNtf; + pSirSmeWmStatusChangeNtf = vos_mem_malloc(sizeof(tSirSmeWmStatusChangeNtf)); + if ( NULL == pSirSmeWmStatusChangeNtf ) + { + limLog(pMac, LOGE, + FL("call to AllocateMemory failed for eWNI_SME_WM_STATUS_CHANGE_NTF")); + return; + } + + + mmhMsg.type = eWNI_SME_WM_STATUS_CHANGE_NTF; + mmhMsg.bodyval = 0; + mmhMsg.bodyptr = pSirSmeWmStatusChangeNtf; + + switch(statusChangeCode) + { + case eSIR_SME_RADAR_DETECTED: + + break; + + case eSIR_SME_CB_LEGACY_BSS_FOUND_BY_AP: + break; + + case eSIR_SME_BACKGROUND_SCAN_FAIL: + limPackBkgndScanFailNotify(pMac, + statusChangeCode, + (tpSirBackgroundScanInfo)pStatusChangeInfo, + pSirSmeWmStatusChangeNtf, sessionId); + break; + + default: + pSirSmeWmStatusChangeNtf->messageType = eWNI_SME_WM_STATUS_CHANGE_NTF; + pSirSmeWmStatusChangeNtf->statusChangeCode = statusChangeCode; + pSirSmeWmStatusChangeNtf->length = sizeof(tSirSmeWmStatusChangeNtf); + pSirSmeWmStatusChangeNtf->sessionId = sessionId; + if(sizeof(pSirSmeWmStatusChangeNtf->statusChangeInfo) >= infoLen) + { + vos_mem_copy( (tANI_U8 *)&pSirSmeWmStatusChangeNtf->statusChangeInfo, + (tANI_U8 *)pStatusChangeInfo, infoLen); + } + limLog(pMac, LOGE, FL("***---*** StatusChg: code 0x%x, length %d ***---***"), + statusChangeCode, infoLen); + break; + } + + + MTRACE(macTraceMsgTx(pMac, sessionId, mmhMsg.type)); + if (eSIR_SUCCESS != limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT)) + { + vos_mem_free(pSirSmeWmStatusChangeNtf); + limLog( pMac, LOGP, FL("limSysProcessMmhMsgApi failed")); + } + +} /*** end limSendSmeWmStatusChangeNtf() ***/ + + +/** + * limSendSmeSetContextRsp() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() to send + * eWNI_SME_SETCONTEXT_RSP message to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param peerMacAddr Indicates the peer MAC addr to which + * setContext was performed + * @param aid Indicates the aid corresponding to the peer MAC + * address + * @param resultCode Indicates the result of previously issued + * eWNI_SME_SETCONTEXT_RSP message + * + * @return None + */ +void +limSendSmeSetContextRsp(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, tANI_U16 aid, + tSirResultCodes resultCode, + tpPESession psessionEntry,tANI_U8 smesessionId,tANI_U16 smetransactionId) +{ + + tANI_U8 *pBuf; + tSirMsgQ mmhMsg; + tSirSmeSetContextRsp *pSirSmeSetContextRsp; + + pSirSmeSetContextRsp = vos_mem_malloc(sizeof(tSirSmeSetContextRsp)); + if ( NULL == pSirSmeSetContextRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for SmeSetContextRsp")); + + return; + } + + pSirSmeSetContextRsp->messageType = eWNI_SME_SETCONTEXT_RSP; + pSirSmeSetContextRsp->length = sizeof(tSirSmeSetContextRsp); + pSirSmeSetContextRsp->statusCode = resultCode; + + pBuf = pSirSmeSetContextRsp->peerMacAddr; + + vos_mem_copy( pBuf, (tANI_U8 *) peerMacAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + + /* Update SME session and transaction Id*/ + pSirSmeSetContextRsp->sessionId = smesessionId; + pSirSmeSetContextRsp->transactionId = smetransactionId; + + mmhMsg.type = eWNI_SME_SETCONTEXT_RSP; + mmhMsg.bodyptr = pSirSmeSetContextRsp; + mmhMsg.bodyval = 0; + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT, psessionEntry, (tANI_U16)resultCode, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} /*** end limSendSmeSetContextRsp() ***/ + +/** + * limSendSmeRemoveKeyRsp() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() to send + * eWNI_SME_REMOVEKEY_RSP message to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param peerMacAddr Indicates the peer MAC addr to which + * Removekey was performed + * @param aid Indicates the aid corresponding to the peer MAC + * address + * @param resultCode Indicates the result of previously issued + * eWNI_SME_REMOVEKEY_RSP message + * + * @return None + */ +void +limSendSmeRemoveKeyRsp(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirResultCodes resultCode, + tpPESession psessionEntry,tANI_U8 smesessionId, + tANI_U16 smetransactionId) +{ + tANI_U8 *pBuf; + tSirMsgQ mmhMsg; + tSirSmeRemoveKeyRsp *pSirSmeRemoveKeyRsp; + + pSirSmeRemoveKeyRsp = vos_mem_malloc(sizeof(tSirSmeRemoveKeyRsp)); + if ( NULL == pSirSmeRemoveKeyRsp ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for SmeRemoveKeyRsp")); + + return; + } + + + + if(psessionEntry != NULL) + { + pBuf = pSirSmeRemoveKeyRsp->peerMacAddr; + vos_mem_copy( pBuf, (tANI_U8 *) peerMacAddr, sizeof(tSirMacAddr)); + } + + pSirSmeRemoveKeyRsp->messageType = eWNI_SME_REMOVEKEY_RSP; + pSirSmeRemoveKeyRsp->length = sizeof(tSirSmeRemoveKeyRsp); + pSirSmeRemoveKeyRsp->statusCode = resultCode; + + /* Update SME session and transaction Id*/ + pSirSmeRemoveKeyRsp->sessionId = smesessionId; + pSirSmeRemoveKeyRsp->transactionId = smetransactionId; + + mmhMsg.type = eWNI_SME_REMOVEKEY_RSP; + mmhMsg.bodyptr = pSirSmeRemoveKeyRsp; + mmhMsg.bodyval = 0; + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + } + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} /*** end limSendSmeSetContextRsp() ***/ + + +/** + * limSendSmeNeighborBssInd() + * + *FUNCTION: + * This function is called by limLookupNaddHashEntry() to send + * eWNI_SME_NEIGHBOR_BSS_IND message to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * This function is used for sending eWNI_SME_NEIGHBOR_BSS_IND to + * host upon detecting new BSS during background scanning if CFG + * option is enabled for sending such indication + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void +limSendSmeNeighborBssInd(tpAniSirGlobal pMac, + tLimScanResultNode *pBssDescr) +{ + tSirMsgQ msgQ; + tANI_U32 val; + tSirSmeNeighborBssInd *pNewBssInd; + + if ((pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_WT_SCAN_STATE) || + ((pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE) && + pMac->lim.gLimRspReqd)) + { + // LIM is not in background scan state OR + // current scan is initiated by HDD. + // No need to send new BSS indication to HDD + return; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not get NEIGHBOR_BSS_IND from CFG")); + + return; + } + + if (val == 0) + return; + + /** + * Need to indicate new BSSs found during + * background scanning to host. + * Allocate buffer for sending indication. + * Length of buffer is length of BSS description + * and length of header itself + */ + val = pBssDescr->bssDescription.length + sizeof(tANI_U16) + sizeof(tANI_U32) + sizeof(tANI_U8); + pNewBssInd = vos_mem_malloc(val); + if ( NULL == pNewBssInd ) + { + // Log error + limLog(pMac, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND")); + + return; + } + + pNewBssInd->messageType = eWNI_SME_NEIGHBOR_BSS_IND; + pNewBssInd->length = (tANI_U16) val; + pNewBssInd->sessionId = 0; + + vos_mem_copy( (tANI_U8 *) pNewBssInd->bssDescription, + (tANI_U8 *) &pBssDescr->bssDescription, + pBssDescr->bssDescription.length + sizeof(tANI_U16)); + + msgQ.type = eWNI_SME_NEIGHBOR_BSS_IND; + msgQ.bodyptr = pNewBssInd; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); +} /*** end limSendSmeNeighborBssInd() ***/ + +/** ----------------------------------------------------------------- + \brief limSendSmeAddtsRsp() - sends SME ADDTS RSP + \ This function sends a eWNI_SME_ADDTS_RSP to SME. + \ SME only looks at rc and tspec field. + \param pMac - global mac structure + \param rspReqd - is SmeAddTsRsp required + \param status - status code of SME_ADD_TS_RSP + \return tspec + \sa + ----------------------------------------------------------------- */ +void +limSendSmeAddtsRsp(tpAniSirGlobal pMac, tANI_U8 rspReqd, tANI_U32 status, tpPESession psessionEntry, + tSirMacTspecIE tspec, tANI_U8 smesessionId, tANI_U16 smetransactionId) +{ + tpSirAddtsRsp rsp; + tSirMsgQ mmhMsg; + + if (! rspReqd) + return; + + rsp = vos_mem_malloc(sizeof(tSirAddtsRsp)); + if ( NULL == rsp ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for ADDTS_RSP")); + return; + } + + vos_mem_set( (tANI_U8 *) rsp, sizeof(*rsp), 0); + rsp->messageType = eWNI_SME_ADDTS_RSP; + rsp->rc = status; + rsp->rsp.status = (enum eSirMacStatusCodes) status; + rsp->rsp.tspec = tspec; + /* Update SME session Id and transcation Id */ + rsp->sessionId = smesessionId; + rsp->transactionId = smetransactionId; + + mmhMsg.type = eWNI_SME_ADDTS_RSP; + mmhMsg.bodyptr = rsp; + mmhMsg.bodyval = 0; + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ADDTS_RSP_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} + +void +limSendSmeAddtsInd(tpAniSirGlobal pMac, tpSirAddtsReqInfo addts) +{ + tpSirAddtsRsp rsp; + tSirMsgQ mmhMsg; + + limLog(pMac, LOGW, "SendSmeAddtsInd (token %d, tsid %d, up %d)", + addts->dialogToken, + addts->tspec.tsinfo.traffic.tsid, + addts->tspec.tsinfo.traffic.userPrio); + + rsp = vos_mem_malloc(sizeof(tSirAddtsRsp)); + if ( NULL == rsp ) + { + // Log error + limLog(pMac, LOGP, FL("AllocateMemory failed for ADDTS_IND")); + return; + } + vos_mem_set( (tANI_U8 *) rsp, sizeof(*rsp), 0); + + rsp->messageType = eWNI_SME_ADDTS_IND; + + vos_mem_copy( (tANI_U8 *) &rsp->rsp, (tANI_U8 *) addts, sizeof(*addts)); + + mmhMsg.type = eWNI_SME_ADDTS_IND; + mmhMsg.bodyptr = rsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + +void +limSendSmeDeltsRsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, tANI_U32 status,tpPESession psessionEntry,tANI_U8 smesessionId,tANI_U16 smetransactionId) +{ + tpSirDeltsRsp rsp; + tSirMsgQ mmhMsg; + + limLog(pMac, LOGW, "SendSmeDeltsRsp (aid %d, tsid %d, up %d) status %d", + delts->aid, + delts->req.tsinfo.traffic.tsid, + delts->req.tsinfo.traffic.userPrio, + status); + if (! delts->rspReqd) + return; + + rsp = vos_mem_malloc(sizeof(tSirDeltsRsp)); + if ( NULL == rsp ) + { + // Log error + limLog(pMac, LOGP, FL("AllocateMemory failed for DELTS_RSP")); + return; + } + vos_mem_set( (tANI_U8 *) rsp, sizeof(*rsp), 0); + + if(psessionEntry != NULL) + { + + rsp->aid = delts->aid; + vos_mem_copy( (tANI_U8 *) &rsp->macAddr[0], (tANI_U8 *) &delts->macAddr[0], 6); + vos_mem_copy( (tANI_U8 *) &rsp->rsp, (tANI_U8 *) &delts->req, sizeof(tSirDeltsReqInfo)); + } + + + rsp->messageType = eWNI_SME_DELTS_RSP; + rsp->rc = status; + + /* Update SME session Id and transcation Id */ + rsp->sessionId = smesessionId; + rsp->transactionId = smetransactionId; + + mmhMsg.type = eWNI_SME_DELTS_RSP; + mmhMsg.bodyptr = rsp; + mmhMsg.bodyval = 0; + if(NULL == psessionEntry) + { + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + } + else + { + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DELTS_RSP_EVENT, psessionEntry, (tANI_U16)status, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + +void +limSendSmeDeltsInd(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, tANI_U16 aid,tpPESession psessionEntry) +{ + tpSirDeltsRsp rsp; + tSirMsgQ mmhMsg; + + limLog(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)", + aid, + delts->tsinfo.traffic.tsid, + delts->tsinfo.traffic.userPrio); + + rsp = vos_mem_malloc(sizeof(tSirDeltsRsp)); + if ( NULL == rsp ) + { + // Log error + limLog(pMac, LOGP, FL("AllocateMemory failed for DELTS_IND")); + return; + } + vos_mem_set( (tANI_U8 *) rsp, sizeof(*rsp), 0); + + rsp->messageType = eWNI_SME_DELTS_IND; + rsp->rc = eSIR_SUCCESS; + rsp->aid = aid; + vos_mem_copy( (tANI_U8 *) &rsp->rsp, (tANI_U8 *) delts, sizeof(*delts)); + + /* Update SME session Id and SME transaction Id */ + + rsp->sessionId = psessionEntry->smeSessionId; + rsp->transactionId = psessionEntry->transactionId; + + mmhMsg.type = eWNI_SME_DELTS_IND; + mmhMsg.bodyptr = rsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_DELTS_IND_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + +/** + * limSendSmeStatsRsp() + * + *FUNCTION: + * This function is called to send 802.11 statistics response to HDD. + * This function posts the result back to HDD. This is a response to + * HDD's request for statistics. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param p80211Stats Statistics sent in response + * @param resultCode TODO: + * + * + * @return none + */ + +void +limSendSmeStatsRsp(tpAniSirGlobal pMac, tANI_U16 msgType, void* stats) +{ + tSirMsgQ mmhMsg; + tSirSmeRsp *pMsgHdr = (tSirSmeRsp*) stats; + + switch(msgType) + { + case WDA_STA_STAT_RSP: + mmhMsg.type = eWNI_SME_STA_STAT_RSP; + break; + case WDA_AGGR_STAT_RSP: + mmhMsg.type = eWNI_SME_AGGR_STAT_RSP; + break; + case WDA_GLOBAL_STAT_RSP: + mmhMsg.type = eWNI_SME_GLOBAL_STAT_RSP; + break; + case WDA_STAT_SUMM_RSP: + mmhMsg.type = eWNI_SME_STAT_SUMM_RSP; + break; + default: + mmhMsg.type = msgType; //Response from within PE + break; + } + + pMsgHdr->messageType = mmhMsg.type; + + mmhMsg.bodyptr = stats; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; + +} /*** end limSendSmeStatsRsp() ***/ + +/** + * limSendSmePEStatisticsRsp() + * + *FUNCTION: + * This function is called to send 802.11 statistics response to HDD. + * This function posts the result back to HDD. This is a response to + * HDD's request for statistics. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param p80211Stats Statistics sent in response + * @param resultCode TODO: + * + * + * @return none + */ + +void +limSendSmePEStatisticsRsp(tpAniSirGlobal pMac, tANI_U16 msgType, void* stats) +{ + tSirMsgQ mmhMsg; + tANI_U8 sessionId; + tAniGetPEStatsRsp *pPeStats = (tAniGetPEStatsRsp *) stats; + tpPESession pPeSessionEntry; + + //Get the Session Id based on Sta Id + pPeSessionEntry = peFindSessionByStaId(pMac, pPeStats->staId, &sessionId); + + //Fill the Session Id + if(NULL != pPeSessionEntry) + { + //Fill the Session Id + pPeStats->sessionId = pPeSessionEntry->smeSessionId; + } + + pPeStats->msgType = eWNI_SME_GET_STATISTICS_RSP; + + + //msgType should be WDA_GET_STATISTICS_RSP + mmhMsg.type = eWNI_SME_GET_STATISTICS_RSP; + + mmhMsg.bodyptr = stats; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; + +} /*** end limSendSmePEStatisticsRsp() ***/ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * limSendSmePEEseTsmRsp() + * + *FUNCTION: + * This function is called to send tsm stats response to HDD. + * This function posts the result back to HDD. This is a response to + * HDD's request to get tsm stats. + * + *PARAMS: + * @param pMac - Pointer to global pMac structure + * @param pStats - Pointer to TSM Stats + * + * @return none + */ + +void +limSendSmePEEseTsmRsp(tpAniSirGlobal pMac, tAniGetTsmStatsRsp *pStats) +{ + tSirMsgQ mmhMsg; + tANI_U8 sessionId; + tAniGetTsmStatsRsp *pPeStats = (tAniGetTsmStatsRsp *) pStats; + tpPESession pPeSessionEntry = NULL; + + //Get the Session Id based on Sta Id + pPeSessionEntry = peFindSessionByStaId(pMac, pPeStats->staId, &sessionId); + + //Fill the Session Id + if(NULL != pPeSessionEntry) + { + //Fill the Session Id + pPeStats->sessionId = pPeSessionEntry->smeSessionId; + } + else + { + PELOGE(limLog(pMac, LOGE, FL("Session not found for the Sta id(%d)"), + pPeStats->staId);) + return; + } + + pPeStats->msgType = eWNI_SME_GET_TSM_STATS_RSP; + pPeStats->tsmMetrics.RoamingCount + = pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingCount; + pPeStats->tsmMetrics.RoamingDly + = pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly; + + mmhMsg.type = eWNI_SME_GET_TSM_STATS_RSP; + mmhMsg.bodyptr = pStats; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, sessionId, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} /*** end limSendSmePEEseTsmRsp() ***/ + +#endif /* FEATURE_WLAN_ESE) && FEATURE_WLAN_ESE_UPLOAD */ + +void +limSendSmeIBSSPeerInd( + tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tANI_U16 staIndex, + tANI_U8 ucastIdx, + tANI_U8 bcastIdx, + tANI_U8 *beacon, + tANI_U16 beaconLen, + tANI_U16 msgType, + tANI_U8 sessionId) +{ + tSirMsgQ mmhMsg; + tSmeIbssPeerInd *pNewPeerInd; + + pNewPeerInd = vos_mem_malloc(sizeof(tSmeIbssPeerInd) + beaconLen); + if ( NULL == pNewPeerInd ) + { + PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));) + return; + } + + vos_mem_set((void *) pNewPeerInd, (sizeof(tSmeIbssPeerInd) + beaconLen), 0); + + vos_mem_copy( (tANI_U8 *) pNewPeerInd->peerAddr, + peerMacAddr, sizeof(tSirMacAddr)); + pNewPeerInd->staId= staIndex; + pNewPeerInd->ucastSig = ucastIdx; + pNewPeerInd->bcastSig = bcastIdx; + pNewPeerInd->mesgLen = sizeof(tSmeIbssPeerInd) + beaconLen; + pNewPeerInd->mesgType = msgType; + pNewPeerInd->sessionId = sessionId; + + if ( beacon != NULL ) + { + vos_mem_copy((void*) ((tANI_U8*)pNewPeerInd+sizeof(tSmeIbssPeerInd)), + (void*)beacon, beaconLen); + } + + mmhMsg.type = msgType; + mmhMsg.bodyptr = pNewPeerInd; + MTRACE(macTraceMsgTx(pMac, sessionId, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} + + +/** ----------------------------------------------------------------- + \brief limSendExitBmpsInd() - sends exit bmps indication + + This function sends a eWNI_PMC_EXIT_BMPS_IND with a specific reason + code to SME. This will trigger SME to get out of BMPS mode. + + \param pMac - global mac structure + \param reasonCode - reason for which PE wish to exit BMPS + \return none + \sa + ----------------------------------------------------------------- */ +void limSendExitBmpsInd(tpAniSirGlobal pMac, tExitBmpsReason reasonCode, + tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tANI_U16 msgLen = 0; + tpSirSmeExitBmpsInd pExitBmpsInd; + + msgLen = sizeof(tSirSmeExitBmpsInd); + pExitBmpsInd = vos_mem_malloc(msgLen); + if ( NULL == pExitBmpsInd ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for PMC_EXIT_BMPS_IND ")); + return; + } + vos_mem_set(pExitBmpsInd, msgLen, 0); + + pExitBmpsInd->mesgType = eWNI_PMC_EXIT_BMPS_IND; + pExitBmpsInd->mesgLen = msgLen; + pExitBmpsInd->exitBmpsReason = reasonCode; + pExitBmpsInd->statusCode = eSIR_SME_SUCCESS; + pExitBmpsInd->smeSessionId = psessionEntry->smeSessionId; + + mmhMsg.type = eWNI_PMC_EXIT_BMPS_IND; + mmhMsg.bodyptr = pExitBmpsInd; + mmhMsg.bodyval = 0; + + PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_PMC_EXIT_BMPS_IND to SME. "));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_BMPS_IND_EVENT, peGetValidPowerSaveSession(pMac), 0, (tANI_U16)reasonCode); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; + +} /*** end limSendExitBmpsInd() ***/ + +/*-------------------------------------------------------------------------- + \brief limHandleCSAoffloadMsg() - Handle CSA offload message + \param pMac - pointer to global adapter context + \param MsgQ - Message pointer. + \sa + --------------------------------------------------------------------------*/ +void limHandleCSAoffloadMsg(tpAniSirGlobal pMac,tpSirMsgQ MsgQ) +{ + tpPESession psessionEntry; + tSirMsgQ mmhMsg; + tpCSAOffloadParams csa_params = (tpCSAOffloadParams)(MsgQ->bodyptr); + tpSmeCsaOffloadInd pCsaOffloadInd; + tpDphHashNode pStaDs = NULL ; + tANI_U8 sessionId; + tANI_U16 aid = 0 ; + + if (!csa_params) { + limLog(pMac, LOGE, FL("limMsgQ body ptr is NULL")); + return; + } + + psessionEntry = peFindSessionByBssid(pMac, csa_params->bssId, &sessionId); + if (!psessionEntry) { + limLog(pMac, LOGE, FL("Session does not exist for given sessionID")); + goto err; + } + + pStaDs = dphLookupHashEntry(pMac, psessionEntry->bssId, &aid, + &psessionEntry->dph.dphHashTable); + + if (!pStaDs) { + limLog(pMac, LOGE, FL("pStaDs does not exist for given sessionID")); + goto err; + } + + + if (LIM_IS_STA_ROLE(psessionEntry)) { +#ifdef FEATURE_WLAN_TDLS + /* + * on receiving channel switch announcement from AP, delete all + * TDLS peers before leaving BSS and proceed for channel + * switch + */ + limDeleteTDLSPeers(pMac, psessionEntry); +#endif + psessionEntry->gLimChannelSwitch.switchMode = csa_params->switchmode; + /* timer already started by firmware, switch immediately */ + psessionEntry->gLimChannelSwitch.switchCount = 0; + psessionEntry->gLimChannelSwitch.primaryChannel = csa_params->channel; + psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + psessionEntry->gLimChannelSwitch.secondarySubBand = PHY_SINGLE_CHANNEL_CENTERED; + +#ifdef WLAN_FEATURE_11AC + if(psessionEntry->vhtCapability) + { + if ( csa_params->ies_present_flag & lim_wbw_ie_present ) + { + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = + csa_params->new_ch_width; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = + csa_params->new_ch_freq_seg1; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = + csa_params->new_ch_freq_seg2; + + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + + psessionEntry->gLimChannelSwitch.secondarySubBand = + limSelectCBMode(pStaDs, + psessionEntry, + csa_params->channel, + csa_params->new_ch_width); + } + + } else +#endif + if (psessionEntry->htCapability) { + psessionEntry->gLimChannelSwitch.secondarySubBand = + limSelectCBMode(pStaDs, + psessionEntry, + csa_params->channel, + csa_params->new_ch_width); + if (psessionEntry->gLimChannelSwitch.secondarySubBand) { + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + } + } + limLog(pMac, LOG1, FL("secondarySubBand = %d"), + psessionEntry->gLimChannelSwitch.secondarySubBand); + + limPrepareFor11hChannelSwitch(pMac, psessionEntry); + pCsaOffloadInd = vos_mem_malloc(sizeof(tSmeCsaOffloadInd)); + if (NULL == pCsaOffloadInd) { + limLog(pMac, LOGE, + FL("AllocateMemory failed for eWNI_SME_CSA_OFFLOAD_EVENT")); + goto err; + } + + vos_mem_set(pCsaOffloadInd, sizeof(tSmeCsaOffloadInd), 0); + pCsaOffloadInd->mesgType = eWNI_SME_CSA_OFFLOAD_EVENT; + pCsaOffloadInd->mesgLen = sizeof(tSmeCsaOffloadInd); + vos_mem_copy(pCsaOffloadInd->bssId, psessionEntry->bssId, + sizeof(tSirMacAddr)); + mmhMsg.type = eWNI_SME_CSA_OFFLOAD_EVENT; + mmhMsg.bodyptr = pCsaOffloadInd; + mmhMsg.bodyval = 0; + PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_SME_CSA_OFFLOAD_EVENT to SME. "));) + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + limDiagEventReport(pMac, WLAN_PE_DIAG_SWITCH_CHL_REQ_EVENT, psessionEntry, + eSIR_SUCCESS, eSIR_SUCCESS); + limReInitScanResults(pMac); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + } + +err: + vos_mem_free(csa_params); +} + +/*-------------------------------------------------------------------------- + \brief peDeleteSession() - Handle the Delete BSS Response from HAL. + + + \param pMac - pointer to global adapter context + \param sessionId - Message pointer. + + \sa + --------------------------------------------------------------------------*/ + +void limHandleDeleteBssRsp(tpAniSirGlobal pMac,tpSirMsgQ MsgQ) +{ + tpPESession psessionEntry; + tpDeleteBssParams pDelBss = (tpDeleteBssParams)(MsgQ->bodyptr); + if((psessionEntry = peFindSessionBySessionId(pMac,pDelBss->sessionId))==NULL) + { + limLog(pMac, LOGE,FL("Session Does not exist for given sessionID %d"), + pDelBss->sessionId); + return; + } + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + limIbssDelBssRsp(pMac, MsgQ->bodyptr, psessionEntry); + } else if(LIM_IS_UNKNOWN_ROLE(psessionEntry)) { + limProcessSmeDelBssRsp(pMac, MsgQ->bodyval,psessionEntry); + } else + limProcessMlmDelBssRsp(pMac,MsgQ,psessionEntry); + +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/** ----------------------------------------------------------------- + \brief limSendSmeAggrQosRsp() - sends SME FT AGGR QOS RSP + \ This function sends a eWNI_SME_FT_AGGR_QOS_RSP to SME. + \ SME only looks at rc and tspec field. + \param pMac - global mac structure + \param rspReqd - is SmeAddTsRsp required + \param status - status code of eWNI_SME_FT_AGGR_QOS_RSP + \return tspec + \sa + ----------------------------------------------------------------- */ +void +limSendSmeAggrQosRsp(tpAniSirGlobal pMac, tpSirAggrQosRsp aggrQosRsp, + tANI_U8 smesessionId) +{ + tSirMsgQ mmhMsg; + + mmhMsg.type = eWNI_SME_FT_AGGR_QOS_RSP; + mmhMsg.bodyptr = aggrQosRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, smesessionId, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} +#endif + +/** ----------------------------------------------------------------- + \brief limSendSmePreChannelSwitchInd() - sends an indication to SME + before switching channels for spectrum manangement. + + This function sends a eWNI_SME_PRE_SWITCH_CHL_IND to SME. + + \param pMac - global mac structure + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmePreChannelSwitchInd(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tANI_U16 msgLen = 0; + tpSirSmePreSwitchChannelInd pPreSwitchChInd; + + msgLen = sizeof(tSirSmePreSwitchChannelInd); + pPreSwitchChInd = vos_mem_malloc(msgLen); + if (NULL == pPreSwitchChInd) + { + limLog(pMac, LOGP, + FL("Memory allocation failed for eWNI_SME_PRE_SWITCH_CHL_IND ")); + return; + } + vos_mem_zero(pPreSwitchChInd, msgLen); + + pPreSwitchChInd->mesgType = eWNI_SME_PRE_SWITCH_CHL_IND; + pPreSwitchChInd->mesgLen = msgLen; + pPreSwitchChInd->sessionId = psessionEntry->smeSessionId; + + mmhMsg.type = eWNI_SME_PRE_SWITCH_CHL_IND; + mmhMsg.bodyptr = pPreSwitchChInd; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} + +/** ----------------------------------------------------------------- + \brief limSendSmePostChannelSwitchInd() - sends an indication to SME + after channel switch for spectrum manangement is complete. + + This function sends a eWNI_SME_POST_SWITCH_CHL_IND to SME. + + \param pMac - global mac structure + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmePostChannelSwitchInd(tpAniSirGlobal pMac) +{ + tSirMsgQ mmhMsg; + + mmhMsg.type = eWNI_SME_POST_SWITCH_CHL_IND; + mmhMsg.bodyptr = NULL; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} + +void limSendSmeMaxAssocExceededNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tANI_U8 smesessionId) +{ + tSirMsgQ mmhMsg; + tSmeMaxAssocInd *pSmeMaxAssocInd; + + pSmeMaxAssocInd = vos_mem_malloc(sizeof(tSmeMaxAssocInd)); + if ( NULL == pSmeMaxAssocInd ) + { + PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));) + return; + } + vos_mem_set((void *) pSmeMaxAssocInd, sizeof(tSmeMaxAssocInd),0); + vos_mem_copy( (tANI_U8 *)pSmeMaxAssocInd->peerMac, + (tANI_U8 *)peerMacAddr, sizeof(tSirMacAddr)); + pSmeMaxAssocInd->mesgType = eWNI_SME_MAX_ASSOC_EXCEEDED; + pSmeMaxAssocInd->mesgLen = sizeof(tSmeMaxAssocInd); + pSmeMaxAssocInd->sessionId = smesessionId; + mmhMsg.type = pSmeMaxAssocInd->mesgType; + mmhMsg.bodyptr = pSmeMaxAssocInd; + PELOG1(limLog(pMac, LOG1, FL("msgType %s peerMacAddr "MAC_ADDRESS_STR + " sme session id %d"), "eWNI_SME_MAX_ASSOC_EXCEEDED", MAC_ADDR_ARRAY(peerMacAddr));) + MTRACE(macTraceMsgTx(pMac, smesessionId, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return; +} +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +/** ----------------------------------------------------------------- + \brief limSendSmeCandidateFoundInd() - sends + eWNI_SME_CANDIDATE_FOUND_IND + + After receiving candidate found indication frame from FW, this + function sends a eWNI_SME_CANDIDATE_FOUND_IND to SME to notify + roam candidate(s) are available. + + \param pMac - global mac structure + \param psessionEntry - session info + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmeCandidateFoundInd(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tSirMsgQ mmhMsg; + tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd; + tpPESession pe_session; + + pe_session = pe_find_session_by_sme_session_id(pMac, sessionId); + if (pe_session == NULL) { + limLog(pMac, LOGE,FL("Session %d is invalid. Roaming will fail"), + sessionId); + return; + } + + pSirSmeCandidateFoundInd = vos_mem_malloc(sizeof(tSirSmeCandidateFoundInd)); + if (NULL == pSirSmeCandidateFoundInd) { + limLog(pMac, LOGP, + FL("AllocateMemory failed for eWNI_SME_CANDIDATE_FOUND_IND")); + return; + } + pe_session->roaming_in_progress = true; + limLog(pMac, LOGE,FL("Set roaming_in_progress for SME:%d, PE:%d session"), + sessionId, pe_session->peSessionId); + pSirSmeCandidateFoundInd->messageType = eWNI_SME_CANDIDATE_FOUND_IND; + pSirSmeCandidateFoundInd->length = sizeof(tSirSmeCandidateFoundInd); + pSirSmeCandidateFoundInd->sessionId = sessionId; + + limLog( pMac, LOG1, FL("posting candidate ind to SME")); + mmhMsg.type = eWNI_SME_CANDIDATE_FOUND_IND; + mmhMsg.bodyptr = pSirSmeCandidateFoundInd; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} /*** end limSendSmeCandidateFoundInd() ***/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +/** ----------------------------------------------------------------- + \brief limSendSmeDfsEventNotify() - sends + eWNI_SME_DFS_RADAR_FOUND + After receiving WMI_PHYERR_EVENTID indication frame from FW, this + function sends a eWNI_SME_DFS_RADAR_FOUND to SME to notify + that a RADAR is found on current operating channel and SAP- + has to move to a new channel. + \param pMac - global mac structure + \param msgType - message type received from lower layer + \param event - event data received from lower layer + \return none + \sa +----------------------------------------------------------------- */ +void +limSendSmeDfsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, void *event) +{ + tSirMsgQ mmhMsg; + mmhMsg.type = eWNI_SME_DFS_RADAR_FOUND; + mmhMsg.bodyptr = event; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + return; +} + + +/*-------------------------------------------------------------------------- + \brief limSendDfsChanSwIEUpdate() + This timer handler updates the channel switch IE in beacon template + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + \sa + --------------------------------------------------------------------------*/ +static void +limSendDfsChanSwIEUpdate(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + /* Update the beacon template and send to FW */ + if (schSetFixedBeaconFields(pMac, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to set CSA IE in beacon"));) + return; + } + + /* Send update beacon template message */ + limSendBeaconInd(pMac, psessionEntry); + PELOG1(limLog(pMac, LOG1, + FL(" Updated CSA IE, IE COUNT = %d"), + psessionEntry->gLimChannelSwitch.switchCount );) + + return; +} + + +/** ----------------------------------------------------------------- + \brief limSendSmeAPChannelSwitchResp() - sends + eWNI_SME_CHANNEL_CHANGE_RSP + After receiving WDA_SWITCH_CHANNEL_RSP indication this + function sends a eWNI_SME_CHANNEL_CHANGE_RSP to SME to notify + that the Channel change has been done to the specified target + channel in the Channel change request + \param pMac - global mac structure + \param psessionEntry - session info + \param pChnlParams - Channel switch params +--------------------------------------------------------------------*/ +void +limSendSmeAPChannelSwitchResp(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSwitchChannelParams pChnlParams) +{ + tSirMsgQ mmhMsg; + tpSwitchChannelParams pSmeSwithChnlParams; + tANI_U8 channelId; + + pSmeSwithChnlParams = (tSwitchChannelParams *) + vos_mem_malloc(sizeof(tSwitchChannelParams)); + if (NULL == pSmeSwithChnlParams) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for pSmeSwithChnlParams\n")); + return; + } + + vos_mem_set((v_VOID_t*)pSmeSwithChnlParams, + sizeof(tSwitchChannelParams), 0); + + vos_mem_copy(pSmeSwithChnlParams, pChnlParams, + sizeof(tSwitchChannelParams)); + + channelId = pSmeSwithChnlParams->channelNumber; + + /* + * Pass the sme sessionID to SME instead + * PE session ID. + */ + pSmeSwithChnlParams->peSessionId = psessionEntry->smeSessionId; + + mmhMsg.type = eWNI_SME_CHANNEL_CHANGE_RSP; + mmhMsg.bodyptr = (void *)pSmeSwithChnlParams; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + /* + * We should start beacon transmission only if the new + * channel after channel change is Non-DFS. For a DFS + * channel, PE will receive an explicit request from + * upper layers to start the beacon transmission . + */ + + if (NV_CHANNEL_DFS != vos_nv_getChannelEnabledState(channelId)) + { + if (channelId == psessionEntry->currentOperChannel) + { + limApplyConfiguration(pMac,psessionEntry); + limSendBeaconInd(pMac, psessionEntry); + } + else + { + PELOG1(limLog(pMac, LOG1, + FL("Failed to Transmit Beacons on channel = %d" + "after AP channel change response"), + psessionEntry->bcnLen);) + } + } + return; +} + +/** ----------------------------------------------------------------- + \brief limProcessBeaconTxSuccessInd() - This function is used + explicitely to handle successful beacon transmission indication + from the FW. This is a generic event generated by the FW afer the + first beacon is sent out after the beacon template update by the + host + \param pMac - global mac structure + \param psessionEntry - session info + \return none + \sa +----------------------------------------------------------------- */ +void +limProcessBeaconTxSuccessInd(tpAniSirGlobal pMac, tANI_U16 msgType, void *event) +{ + /* Currently, this event is used only for DFS channel switch announcement + * IE update in the template. If required to be used for other IE updates + * add appropriate code by introducing a state variable + */ + tpPESession psessionEntry; + tSirMsgQ mmhMsg; + tSirSmeCSAIeTxCompleteRsp *pChanSwTxResponse; + tANI_U8 length = sizeof(tSirSmeCSAIeTxCompleteRsp); + tpSirFirstBeaconTxCompleteInd pBcnTxInd = + (tSirFirstBeaconTxCompleteInd *)event; + + if((psessionEntry = + peFindSessionByBssIdx(pMac, pBcnTxInd->bssIdx))== NULL) + { + limLog(pMac, LOGE,FL("Session Does not exist for given sessionID")); + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry) && + VOS_TRUE == psessionEntry->dfsIncludeChanSwIe) { + /* Send only 5 beacons with CSA IE Set in when a radar is detected */ + if (psessionEntry->gLimChannelSwitch.switchCount > 0) + { + /* + * Send the next beacon with updated CSA IE count + */ + limSendDfsChanSwIEUpdate(pMac, psessionEntry); + /* Decrement the IE count */ + psessionEntry->gLimChannelSwitch.switchCount--; + } + else + { + /* Done with CSA IE update, send response back to SME */ + psessionEntry->gLimChannelSwitch.switchCount = 0; + if (pMac->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_FALSE) + psessionEntry->gLimChannelSwitch.switchMode = 0; + psessionEntry->dfsIncludeChanSwIe = VOS_FALSE; + psessionEntry->dfsIncludeChanWrapperIe = VOS_FALSE; + + + pChanSwTxResponse = (tSirSmeCSAIeTxCompleteRsp *) + vos_mem_malloc(length); + + if (NULL == pChanSwTxResponse) + { + limLog(pMac, LOGP, + FL("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp")); + return; + } + + vos_mem_set((void*)pChanSwTxResponse, length, 0); + pChanSwTxResponse->sessionId = psessionEntry->smeSessionId; + pChanSwTxResponse->chanSwIeTxStatus = VOS_STATUS_SUCCESS; + + mmhMsg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND; + mmhMsg.bodyptr = pChanSwTxResponse; + mmhMsg.bodyval = 0; + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + } + } + + return; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h new file mode 100644 index 000000000000..b56574b3d6f6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limSendSmeRspMessages.h contains the definitions for + * sending SME response/notification messages to applications above + * MAC software. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __LIM_SEND_SME_RSP_H +#define __LIM_SEND_SME_RSP_H + +#include "sirCommon.h" +#include "sirApi.h" +#include "sirMacProtDef.h" + + +// Functions for sending responses to Host +void limSendSmeRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes, tANI_U8 , tANI_U16); +void limSendSmeStartBssRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tpPESession,tANI_U8,tANI_U16); +void limSendSmeScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limSendSmeLfrScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16); +#endif +void limPostSmeScanRspMessage(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8,tANI_U16); + +void limSendSmeJoinReassocRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes, tANI_U16,tpPESession,tANI_U8,tANI_U16); +void limSendSmeDisassocNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U16, tANI_U16,tANI_U8,tANI_U16,tpPESession); +void limSendSmeDeauthNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U16, tANI_U16, tANI_U8, tANI_U16); +void limSendSmeDisassocInd(tpAniSirGlobal, tpDphHashNode,tpPESession); +void limSendSmeDeauthInd(tpAniSirGlobal, tpDphHashNode, tpPESession psessionEntry); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limSendSmeCandidateFoundInd(tpAniSirGlobal, tANI_U8); +#endif + +void limSendSmeWmStatusChangeNtf(tpAniSirGlobal, tSirSmeStatusChangeCode, tANI_U32 *, tANI_U16, tANI_U8); +void limSendSmeSetContextRsp(tpAniSirGlobal, + tSirMacAddr, tANI_U16, tSirResultCodes,tpPESession,tANI_U8,tANI_U16); +void limSendSmeNeighborBssInd(tpAniSirGlobal, + tLimScanResultNode *); +void limHandleDeleteBssRsp(tpAniSirGlobal pMac,tpSirMsgQ MsgQ); +void limHandleCSAoffloadMsg(tpAniSirGlobal pMac,tpSirMsgQ MsgQ); + +#ifdef WLAN_FEATURE_VOWIFI_11R +void +limSendSmeAggrQosRsp(tpAniSirGlobal pMac, tpSirAggrQosRsp aggrQosRsp, + tANI_U8 smesessionId); +#endif /*WLAN_FEATURE_VOWIFI_11R*/ + + +void limSendSmeAddtsRsp(tpAniSirGlobal pMac, tANI_U8 rspReqd, tANI_U32 status, tpPESession psessionEntry, tSirMacTspecIE tspec, tANI_U8 smesessionId, tANI_U16 smetransactionId); +void limSendSmeAddtsInd(tpAniSirGlobal pMac, tpSirAddtsReqInfo addts); +void limSendSmeDeltsRsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, tANI_U32 status,tpPESession psessionEntry,tANI_U8 smessionId,tANI_U16 smetransactionId); +void limSendSmeDeltsInd(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, tANI_U16 aid,tpPESession); +void limSendSmeStatsRsp(tpAniSirGlobal pMac, tANI_U16 msgtype, void * stats); + +void limSendSmePEStatisticsRsp(tpAniSirGlobal pMac, tANI_U16 msgtype, void * stats); +#ifdef FEATURE_WLAN_ESE_UPLOAD +void limSendSmePEEseTsmRsp(tpAniSirGlobal pMac, tAniGetTsmStatsRsp *pStats); +#endif +void limSendSmeRemoveKeyRsp(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tSirResultCodes resultCode,tpPESession,tANI_U8,tANI_U16); + + +void limSendSmeGetTxPowerRsp(tpAniSirGlobal pMac, tANI_U32 power, tANI_U32 status); +void limSendSmeGetNoiseRsp(tpAniSirGlobal pMac, tSirMacNoise noise); +void limSendSmeIBSSPeerInd(tpAniSirGlobal pMac,tSirMacAddr peerMacAddr,tANI_U16 staIndex,tANI_U8 ucastIdx,tANI_U8 bcastIdx, + tANI_U8 *beacon,tANI_U16 beaconLen, tANI_U16 msgType, tANI_U8 sessionId); +void limSendExitBmpsInd(tpAniSirGlobal pMac, tExitBmpsReason reasonCode, + tpPESession psessionEntry); + +#ifdef FEATURE_OEM_DATA_SUPPORT +void limSendSmeOemDataRsp(tpAniSirGlobal pMac, tANI_U32* pMsgBuf, tSirResultCodes resultCode); +#endif +void limSendSmePreChannelSwitchInd(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +void limSendSmePostChannelSwitchInd(tpAniSirGlobal pMac); +void limSendSmeMaxAssocExceededNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tANI_U8 smesessionId); +#ifdef FEATURE_WLAN_TDLS +void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tANI_U16 msgType); +void limSendSmeTdlsLinkStartRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tSirMacAddr peerMac, tANI_U16 msgType); +void limSendSmeTdlsTeardownRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tSirMacAddr peerMac, tANI_U16 msgType); +void limSendSmeTdlsLinkEstablishReqRsp(tpAniSirGlobal pMac, + tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs, + tANI_U8 status); +void limSendSmeTdlsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, + void *events); +#endif + +void limSendSmeDfsEventNotify(tpAniSirGlobal pMac, tANI_U16 msgType, + void *event); +void limSendSmeAPChannelSwitchResp(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSwitchChannelParams pChnlParams); +void +limProcessBeaconTxSuccessInd(tpAniSirGlobal pMac, tANI_U16 msgType, + void *event); + +typedef enum { + lim_csa_ie_present = 0x00000001, + lim_xcsa_ie_present = 0x00000002, + lim_wbw_ie_present = 0x00000004, + lim_cswarp_ie_present = 0x00000008, +}lim_csa_event_ies_present_flag; + +#endif /* __LIM_SEND_SME_RSP_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.c new file mode 100644 index 000000000000..34fce5ad8139 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.c @@ -0,0 +1,2773 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limSerDesUtils.cc contains the serializer/deserializer + * utility functions LIM uses while communicating with upper layer + * software entities + * Author: Chandra Modumudi + * Date: 10/20/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "aniSystemDefs.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limSerDesUtils.h" + + + +/** + * limCheckRemainingLength() + * + *FUNCTION: + * This function is called while de-serializing received SME_REQ + * message. + * + *LOGIC: + * Remaining message length is checked for > 0. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param len - Remaining message length + * @return retCode - eSIR_SUCCESS if len > 0, else eSIR_FAILURE + */ + +static inline tSirRetStatus +limCheckRemainingLength(tpAniSirGlobal pMac, tANI_S16 len) +{ + if (len > 0) + return eSIR_SUCCESS; + else + { + limLog(pMac, LOGW, + FL("Received SME message with invalid rem length=%d"), + len); + return eSIR_FAILURE; + } +} /*** end limCheckRemainingLength(pMac, ) ***/ + +/** + * limGetBssDescription() + * + *FUNCTION: + * This function is called by various LIM functions to copy + * BSS description from a tANI_U8* buffer pointer to tSirBssDescription + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pBssDescription Pointer to the BssDescription to be copied + * @param *pBuf Pointer to the source buffer + * @param rLen Remaining message length being extracted + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * failure (eSIR_FAILURE). + */ + +static tSirRetStatus +limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, + tANI_S16 rLen, tANI_S16 *lenUsed, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + + pBssDescription->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len = pBssDescription->length; + + if (rLen < (tANI_S16) (len + sizeof(tANI_U16))) + return eSIR_FAILURE; + + *lenUsed = len + sizeof(tANI_U16); + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pBssDescription->bssId, + pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract timer + vos_mem_copy( (tANI_U8 *) (&pBssDescription->scanSysTimeMsec), + pBuf, sizeof(v_TIME_t)); + pBuf += sizeof(v_TIME_t); + len -= sizeof(v_TIME_t); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract timeStamp + vos_mem_copy( (tANI_U8 *) pBssDescription->timeStamp, + pBuf, sizeof(tSirMacTimeStamp)); + pBuf += sizeof(tSirMacTimeStamp); + len -= sizeof(tSirMacTimeStamp); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract beaconInterval + pBssDescription->beaconInterval = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract capabilityInfo + pBssDescription->capabilityInfo = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract nwType + pBssDescription->nwType = (tSirNwType) limGetU32(pBuf); + pBuf += sizeof(tSirNwType); + len -= sizeof(tSirNwType); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract rssi + pBssDescription->rssi = (tANI_S8) *pBuf++; + len --; + + /* Extract raw rssi value */ + pBssDescription->rssi_raw = (tANI_S8) *pBuf++; + len--; + + // Extract sinr + pBssDescription->sinr = (tANI_S8) *pBuf++; + len --; + + // Extract channelId + pBssDescription->channelId = *pBuf++; + len --; + + // Extract channelIdSelf + pBssDescription->channelIdSelf = *pBuf++; + len --; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract reserved bssDescription + pBuf += sizeof(pBssDescription->sSirBssDescriptionRsvd); + len -= sizeof(pBssDescription->sSirBssDescriptionRsvd); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //pass the timestamp + pBssDescription->nReceivedTime = limGetU32( pBuf ); + pBuf += sizeof(tANI_TIMESTAMP); + len -= sizeof(tANI_TIMESTAMP); + +#if defined WLAN_FEATURE_VOWIFI + //TSF when the beacon received (parent TSF) + pBssDescription->parentTSF = limGetU32( pBuf ); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + + //start TSF of scan during which this BSS desc was updated. + pBssDescription->startTSF[0] = limGetU32( pBuf ); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + + //start TSF of scan during which this BSS desc was updated. + pBssDescription->startTSF[1] = limGetU32( pBuf ); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + // MobilityDomain + pBssDescription->mdiePresent = *pBuf++; + len --; + pBssDescription->mdie[0] = *pBuf++; + len --; + pBssDescription->mdie[1] = *pBuf++; + len --; + pBssDescription->mdie[2] = *pBuf++; + len --; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(limLog(pMac, LOG1, FL("mdie=%02x %02x %02x"), + pBssDescription->mdie[0], + pBssDescription->mdie[1], + pBssDescription->mdie[2]);) +#endif +#endif + +#ifdef FEATURE_WLAN_ESE + pBssDescription->QBSSLoad_present = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract QBSSLoad_avail + pBssDescription->QBSSLoad_avail = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + /* 4 reserved bytes for padding */ + pBuf += sizeof(tANI_U32); + len -= 4; +#endif + pBssDescription->fProbeRsp = *pBuf++; + len -= sizeof(tANI_U8); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + /* 3 reserved bytes for padding */ + pBuf += (3 * sizeof(tANI_U8)); + len -= 3; + + pBssDescription->WscIeLen = limGetU32( pBuf ); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + if (WSCIE_PROBE_RSP_LEN < len) + { + /* Do not copy with WscIeLen + * if WscIeLen is not set properly, memory overwrite happen + * Ended up with memory corruption and crash + * Copy with Fixed size */ + vos_mem_copy( (tANI_U8 *) pBssDescription->WscIeProbeRsp, + pBuf, + WSCIE_PROBE_RSP_LEN); + + } + else + { + limLog(pMac, LOGE, + FL("remaining bytes len %d is less than WSCIE_PROBE_RSP_LEN"), + pBssDescription->WscIeLen); + return eSIR_FAILURE; + } + + /* 1 reserved byte padding */ + pBuf += (WSCIE_PROBE_RSP_LEN + 1); + len -= (WSCIE_PROBE_RSP_LEN + 1); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pBssDescription->tsf_delta = limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + + if (len > 0) + { + vos_mem_copy( (tANI_U8 *) pBssDescription->ieFields, + pBuf, + len); + } + else if (len < 0) + { + limLog(pMac, LOGE, + FL("remaining length is negative. len = %d, actual length = %d"), + len, pBssDescription->length); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} /*** end limGetBssDescription() ***/ + + +/** + * limGetKeysInfo() + * + *FUNCTION: + * This function is called by various LIM functions to copy + * key information from a tANI_U8* buffer pointer to tSirKeys + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param *pKeyInfo Pointer to the keyInfo to be copied + * @param *pBuf Pointer to the source buffer + * + * @return Length of key info extracted + */ + +static tANI_U32 +limGetKeysInfo(tpAniSirGlobal pMac, tpSirKeys pKeyInfo, tANI_U8 *pBuf) +{ + tANI_U32 len = 0; + + pKeyInfo->keyId = *pBuf++; + len++; + pKeyInfo->unicast = *pBuf++; + len++; + pKeyInfo->keyDirection = (tAniKeyDirection) limGetU32(pBuf); + len += sizeof(tAniKeyDirection); + pBuf += sizeof(tAniKeyDirection); + + vos_mem_copy( pKeyInfo->keyRsc, pBuf, WLAN_MAX_KEY_RSC_LEN); + pBuf += WLAN_MAX_KEY_RSC_LEN; + len += WLAN_MAX_KEY_RSC_LEN; + + pKeyInfo->paeRole = *pBuf++; + len++; + + pKeyInfo->keyLength = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len += sizeof(tANI_U16); + vos_mem_copy( pKeyInfo->key, pBuf, pKeyInfo->keyLength); + pBuf += pKeyInfo->keyLength; + len += pKeyInfo->keyLength; + + PELOG3(limLog(pMac, LOG3, + FL("Extracted keyId=%d, keyLength=%d, Key is :"), + pKeyInfo->keyId, pKeyInfo->keyLength); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, + pKeyInfo->key, pKeyInfo->keyLength);) + + return len; +} /*** end limGetKeysInfo() ***/ + + + +/** + * limStartBssReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_START_BSS_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pStartBssReq Pointer to tSirSmeStartBssReq being extracted + * @param pBuf Pointer to serialized buffer + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + if (!pStartBssReq || !pBuf) + return eSIR_FAILURE; + + pStartBssReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pStartBssReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_START_BSS_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pStartBssReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pStartBssReq->transactionId = limGetU16( pBuf ); + pBuf += sizeof( tANI_U16 ); + len -= sizeof( tANI_U16 ); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pStartBssReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract selfMacAddr + vos_mem_copy( (tANI_U8 *) pStartBssReq->selfMacAddr, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract beaconInterval + pStartBssReq->beaconInterval = limGetU16( pBuf ); + pBuf += sizeof( tANI_U16 ); + len -= sizeof( tANI_U16 ); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract dot11Mode + pStartBssReq->dot11mode = *pBuf++; + len --; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + // Extract mcc to scc switch mode + pStartBssReq->cc_switch_mode = *pBuf++; + len --; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; +#endif + + // Extract bssType + pStartBssReq->bssType = (tSirBssType) limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract ssId + if (*pBuf > SIR_MAC_MAX_SSID_LENGTH) + { + // SSID length is more than max allowed 32 bytes + PELOGW(limLog(pMac, LOGW, FL("Invalid SSID length, len=%d"), *pBuf);) + return eSIR_FAILURE; + } + + pStartBssReq->ssId.length = *pBuf++; + len--; + if (len < pStartBssReq->ssId.length) + { + limLog(pMac, LOGW, + FL("SSID length is longer that the remaining length. SSID len=%d, remaining len=%d"), + pStartBssReq->ssId.length, len); + return eSIR_FAILURE; + } + + vos_mem_copy( (tANI_U8 *) pStartBssReq->ssId.ssId, + pBuf, + pStartBssReq->ssId.length); + pBuf += pStartBssReq->ssId.length; + len -= pStartBssReq->ssId.length; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract channelId + pStartBssReq->channelId = *pBuf++; + len--; + + // Extract CB secondary channel info + pStartBssReq->cbMode = (ePhyChanBondState)limGetU32( pBuf ); + pBuf += sizeof( tANI_U32 ); + len -= sizeof( tANI_U32 ); + + pStartBssReq->vht_channel_width = *pBuf++; + len--; + + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + + // Extract privacy setting + pStartBssReq->privacy = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //Extract Uapsd Enable + pStartBssReq->apUapsdEnable = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //Extract SSID hidden + pStartBssReq->ssidHidden = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pStartBssReq->fwdWPSPBCProbeReq = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //Extract HT Protection Enable + pStartBssReq->protEnabled = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //Extract OBSS Protection Enable + pStartBssReq->obssProtEnabled = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pStartBssReq->ht_capab = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract AuthType + pStartBssReq->authType = (tSirBssType) limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract dtimPeriod + pStartBssReq->dtimPeriod = limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract wps state + pStartBssReq->wps_state = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract isCoalesingInIBSSAllowed + pStartBssReq->isCoalesingInIBSSAllowed = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssPersona + pStartBssReq->bssPersona = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + + // Extract txLdpcIniFeatureEnabled + pStartBssReq->txLdpcIniFeatureEnabled = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + +#ifdef WLAN_FEATURE_11W + // Extract MFP capable/required + pStartBssReq->pmfCapable = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + pStartBssReq->pmfRequired = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; +#endif + + // Extract rsnIe + pStartBssReq->rsnIE.length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + // Check for RSN IE length (that includes length of type & length + if (pStartBssReq->rsnIE.length > SIR_MAC_MAX_IE_LENGTH + 2) + { + limLog(pMac, LOGW, + FL("Invalid RSN IE length %d in SME_START_BSS_REQ"), + pStartBssReq->rsnIE.length); + return eSIR_FAILURE; + } + + vos_mem_copy( pStartBssReq->rsnIE.rsnIEdata, + pBuf, pStartBssReq->rsnIE.length); + + len -= (sizeof(tANI_U16) + pStartBssReq->rsnIE.length); + pBuf += pStartBssReq->rsnIE.length; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract nwType + pStartBssReq->nwType = (tSirNwType) limGetU32(pBuf); + pBuf += sizeof(tSirNwType); + len -= sizeof(tSirNwType); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract operationalRateSet + pStartBssReq->operationalRateSet.numRates = *pBuf++; + + // Check for number of rates + if (pStartBssReq->operationalRateSet.numRates > + SIR_MAC_MAX_NUMBER_OF_RATES) + { + limLog(pMac, LOGW, FL("Invalid numRates %d in SME_START_BSS_REQ"), + pStartBssReq->operationalRateSet.numRates); + return eSIR_FAILURE; + } + + len--; + if (len < pStartBssReq->operationalRateSet.numRates) + return eSIR_FAILURE; + + vos_mem_copy( (tANI_U8 *) pStartBssReq->operationalRateSet.rate, + pBuf, + pStartBssReq->operationalRateSet.numRates); + pBuf += pStartBssReq->operationalRateSet.numRates; + len -= pStartBssReq->operationalRateSet.numRates; + + // Extract extendedRateSet + pStartBssReq->extendedRateSet.numRates = *pBuf++; + len--; + if ((pStartBssReq->nwType == eSIR_11G_NW_TYPE) || + (pStartBssReq->nwType == eSIR_11N_NW_TYPE )) + { + vos_mem_copy( pStartBssReq->extendedRateSet.rate, + pBuf, pStartBssReq->extendedRateSet.numRates); + pBuf += pStartBssReq->extendedRateSet.numRates; + len -= pStartBssReq->extendedRateSet.numRates; + } + else + { + pBuf += pStartBssReq->extendedRateSet.numRates; + len -= pStartBssReq->extendedRateSet.numRates; + pStartBssReq->extendedRateSet.numRates = 0; + } + + vos_mem_copy(&(pStartBssReq->htConfig), pBuf, + sizeof(tSirHTConfig)); + len -= sizeof(tSirHTConfig); + pBuf += sizeof(tSirHTConfig); + + vos_mem_copy(&(pStartBssReq->addIeParams), pBuf, sizeof(tSirAddIeParams)); + len -= sizeof(tSirAddIeParams); + pBuf += sizeof(tSirAddIeParams); + + /* extract obssEnabled */ + pStartBssReq->obssEnabled = *pBuf++; + len--; + + /* extract sap_dot11mc */ + pStartBssReq->sap_dot11mc = *pBuf++; + len--; + + if (len) + { + limLog(pMac, LOGW, FL("Extra bytes left in SME_START_BSS_REQ, len=%d"), len); + } + + return eSIR_SUCCESS; +} /*** end limStartBssReqSerDes() ***/ + + + +/** + * limStopBssReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_STOP_BSS_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pStopBssReq Pointer to tSirSmeStopBssReq being extracted + * @param pBuf Pointer to serialized buffer + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limStopBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStopBssReq pStopBssReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + pStopBssReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pStopBssReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_STOP_BSS_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pStopBssReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pStopBssReq->transactionId = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + + // Extract reasonCode + pStopBssReq->reasonCode = (tSirResultCodes) limGetU32(pBuf); + pBuf += sizeof(tSirResultCodes); + len -= sizeof(tSirResultCodes); + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pStopBssReq->bssId, pBuf, sizeof(tSirMacAddr)); + len -= sizeof(tSirMacAddr); + + if (len) + return eSIR_FAILURE; + else + return eSIR_SUCCESS; + +} /*** end limStopBssReqSerDes() ***/ + + + +/** + * limJoinReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_JOIN_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pJoinReq Pointer to tSirSmeJoinReq being extracted + * @param pBuf Pointer to serialized buffer + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + tANI_S16 lenUsed = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + if (!pJoinReq || !pBuf) + { + PELOGE(limLog(pMac, LOGE, FL("pJoinReq or pBuf is NULL"));) + return eSIR_FAILURE; + } + + // Extract messageType + pJoinReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + // Extract length + len = pJoinReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + if (pJoinReq->messageType == eWNI_SME_JOIN_REQ) + PELOG1(limLog(pMac, LOG3, FL("SME_JOIN_REQ length %d bytes is:"), len);) + else + PELOG1(limLog(pMac, LOG3, FL("SME_REASSOC_REQ length %d bytes is:"), + len);) + + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + { + PELOGE(limLog(pMac, LOGE, FL("len %d is too short"), len);) + return eSIR_FAILURE; + } + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + // Extract sessionId + pJoinReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + // Extract transactionId + pJoinReq->transactionId = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // Extract ssId + pJoinReq->ssId.length = *pBuf++; + len--; + vos_mem_copy( (tANI_U8 *) pJoinReq->ssId.ssId, pBuf, pJoinReq->ssId.length); + pBuf += pJoinReq->ssId.length; + len -= pJoinReq->ssId.length; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // Extract selfMacAddr + vos_mem_copy( pJoinReq->selfMacAddr, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // Extract bsstype + pJoinReq->bsstype = (tSirBssType) limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // Extract dot11mode + pJoinReq->dot11mode= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + // Extract mcc to scc switch mode + pJoinReq->cc_switch_mode= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#endif + + // Extract bssPersona + pJoinReq->staPersona = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // Extract cbMode + pJoinReq->cbMode = (ePhyChanBondState)limGetU32(pBuf); + pBuf += sizeof(ePhyChanBondState); + len -= sizeof(ePhyChanBondState); + + 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++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + + // Extract operationalRateSet + pJoinReq->operationalRateSet.numRates= *pBuf++; + len--; + if (pJoinReq->operationalRateSet.numRates) + { + vos_mem_copy( (tANI_U8 *) pJoinReq->operationalRateSet.rate, pBuf, + pJoinReq->operationalRateSet.numRates); + pBuf += pJoinReq->operationalRateSet.numRates; + len -= pJoinReq->operationalRateSet.numRates; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + } + + // Extract extendedRateSet + pJoinReq->extendedRateSet.numRates = *pBuf++; + len--; + if (pJoinReq->extendedRateSet.numRates) + { + vos_mem_copy( pJoinReq->extendedRateSet.rate, pBuf, pJoinReq->extendedRateSet.numRates); + pBuf += pJoinReq->extendedRateSet.numRates; + len -= pJoinReq->extendedRateSet.numRates; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + } + + // Extract RSN IE + pJoinReq->rsnIE.length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + + if (pJoinReq->rsnIE.length) + { + // Check for RSN IE length (that includes length of type & length) + if ((pJoinReq->rsnIE.length > SIR_MAC_MAX_IE_LENGTH + 2) || + (pJoinReq->rsnIE.length != 2 + *(pBuf + 1))) + { + limLog(pMac, LOGW, + FL("Invalid RSN IE length %d in SME_JOIN_REQ"), + pJoinReq->rsnIE.length); + return eSIR_FAILURE; + } + vos_mem_copy( (tANI_U8 *) pJoinReq->rsnIE.rsnIEdata, + pBuf, pJoinReq->rsnIE.length); + pBuf += pJoinReq->rsnIE.length; + len -= pJoinReq->rsnIE.length; // skip RSN IE + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + } + +#ifdef FEATURE_WLAN_ESE + // Extract CCKM IE + pJoinReq->cckmIE.length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (pJoinReq->cckmIE.length) + { + // Check for CCKM IE length (that includes length of type & length) + if ((pJoinReq->cckmIE.length > SIR_MAC_MAX_IE_LENGTH) || + (pJoinReq->cckmIE.length != (2 + *(pBuf + 1)))) + { + limLog(pMac, LOGW, + FL("Invalid CCKM IE length %d/%d in SME_JOIN/REASSOC_REQ"), + pJoinReq->cckmIE.length, 2 + *(pBuf + 1)); + return eSIR_FAILURE; + } + vos_mem_copy((tANI_U8 *) pJoinReq->cckmIE.cckmIEdata, + pBuf, pJoinReq->cckmIE.length); + pBuf += pJoinReq->cckmIE.length; + len -= pJoinReq->cckmIE.length; // skip CCKM IE + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + } +#endif + + // Extract Add IE for scan + pJoinReq->addIEScan.length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + + if (pJoinReq->addIEScan.length) + { + // Check for IE length (that includes length of type & length) + if (pJoinReq->addIEScan.length > SIR_MAC_MAX_ADD_IE_LENGTH + 2) + { + limLog(pMac, LOGE, + FL("Invalid addIE Scan length %d in SME_JOIN_REQ"), + pJoinReq->addIEScan.length); + return eSIR_FAILURE; + } + // Check for P2P IE length (that includes length of type & length) + vos_mem_copy( (tANI_U8 *) pJoinReq->addIEScan.addIEdata, + pBuf, pJoinReq->addIEScan.length); + pBuf += pJoinReq->addIEScan.length; + len -= pJoinReq->addIEScan.length; // skip add IE + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + } + + pJoinReq->addIEAssoc.length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + + // Extract Add IE for assoc + if (pJoinReq->addIEAssoc.length) + { + // Check for IE length (that includes length of type & length) + if (pJoinReq->addIEAssoc.length > SIR_MAC_MAX_IE_LENGTH + 2) + { + limLog(pMac, LOGE, + FL("Invalid addIE Assoc length %d in SME_JOIN_REQ"), + pJoinReq->addIEAssoc.length); + return eSIR_FAILURE; + } + // Check for P2P IE length (that includes length of type & length) + vos_mem_copy( (tANI_U8 *) pJoinReq->addIEAssoc.addIEdata, + pBuf, pJoinReq->addIEAssoc.length); + pBuf += pJoinReq->addIEAssoc.length; + len -= pJoinReq->addIEAssoc.length; // skip add IE + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + } + + pJoinReq->UCEncryptionType = limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + pJoinReq->MCEncryptionType = limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#ifdef WLAN_FEATURE_11W + pJoinReq->MgmtEncryptionType = limGetU32(pBuf); + pBuf += sizeof(tANI_U32); + len -= sizeof(tANI_U32); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + //is11Rconnection; + pJoinReq->is11Rconnection = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#endif + +#ifdef FEATURE_WLAN_ESE + //ESE version IE + pJoinReq->isESEFeatureIniEnabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + //isESEconnection; + pJoinReq->isESEconnection = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // TSPEC information + pJoinReq->eseTspecInfo.numTspecs = *pBuf++; + len -= sizeof(tANI_U8); + vos_mem_copy((void*)&pJoinReq->eseTspecInfo.tspec[0], pBuf, + (sizeof(tTspecInfo)* pJoinReq->eseTspecInfo.numTspecs)); + pBuf += sizeof(tTspecInfo)*SIR_ESE_MAX_TSPEC_IES; + len -= sizeof(tTspecInfo)*SIR_ESE_MAX_TSPEC_IES; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + //isFastTransitionEnabled; + pJoinReq->isFastTransitionEnabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#endif + +#ifdef FEATURE_WLAN_LFR + //isFastRoamIniFeatureEnabled; + pJoinReq->isFastRoamIniFeatureEnabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } +#endif + + //txLdpcIniFeatureEnabled + pJoinReq->txLdpcIniFeatureEnabled= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + //HT Config + vos_mem_copy(&(pJoinReq->htConfig), pBuf, sizeof(tSirHTConfig)); + len -= sizeof(tSirHTConfig); + pBuf += sizeof(tSirHTConfig); + + //txBFIniFeatureEnabled + pJoinReq->txBFIniFeatureEnabled= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + //txBFCsnValue + pJoinReq->txBFCsnValue= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + //MuBformee + pJoinReq->txMuBformee= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + //enableVhtpAid + pJoinReq->enableVhtpAid= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //enableVhtGid + pJoinReq->enableVhtGid= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //enableAmpduPs + pJoinReq->enableAmpduPs= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + //enableHtSmps + pJoinReq->enableHtSmps= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // htSmps + pJoinReq->htSmps= *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pJoinReq->max_amsdu_num = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pJoinReq->isWMEenabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pJoinReq->isQosEnabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pJoinReq->isOSENConnection = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + /* Extract rrm config */ + vos_mem_copy(&pJoinReq->rrm_config, pBuf, sizeof(struct rrm_config_param)); + pBuf += sizeof(struct rrm_config_param); + len -= sizeof(struct rrm_config_param); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract Spectrum Mgt Indicator + pJoinReq->spectrumMgtIndicator = (tAniBool) limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + + pJoinReq->powerCap.minTxPower = *pBuf++; + pJoinReq->powerCap.maxTxPower = *pBuf++; + len -=2; + + pJoinReq->supportedChannels.numChnl = *pBuf++; + len--; + vos_mem_copy( (tANI_U8 *) pJoinReq->supportedChannels.channelList, + pBuf, pJoinReq->supportedChannels.numChnl); + pBuf += pJoinReq->supportedChannels.numChnl; + len-= pJoinReq->supportedChannels.numChnl; + + PELOG2(limLog(pMac, LOG2, + FL("spectrumInd ON: minPower %d, maxPower %d , numChnls %d"), + pJoinReq->powerCap.minTxPower, + pJoinReq->powerCap.maxTxPower, + pJoinReq->supportedChannels.numChnl);) + + // Extract uapsdPerAcBitmask + pJoinReq->uapsdPerAcBitmask = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } + + // + // NOTE - tSirBssDescription is now moved to the end + // of tSirSmeJoinReq structure. This is to accomodate + // the variable length data member ieFields[1] + // + if (limGetBssDescription( pMac, &pJoinReq->bssDescription, + len, &lenUsed, pBuf) == eSIR_FAILURE) + { + PELOGE(limLog(pMac, LOGE, FL("get bss description failed"));) + return eSIR_FAILURE; + } + PELOG3(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, + (tANI_U8 *) &(pJoinReq->bssDescription), + pJoinReq->bssDescription.length + 2);) + pBuf += lenUsed; + len -= lenUsed; + + return eSIR_SUCCESS; +} /*** end limJoinReqSerDes() ***/ + + +/**--------------------------------------------------------------- +\fn limAssocIndSerDes +\brief This function is called by limProcessMlmAssocInd() to +\ populate the SME_ASSOC_IND message based on the received +\ MLM_ASSOC_IND. +\ +\param pMac +\param pAssocInd - Pointer to the received tLimMlmAssocInd +\param pBuf - Pointer to serialized buffer +\param psessionEntry - pointer to PE session entry +\ +\return None +------------------------------------------------------------------*/ +void +limAssocIndSerDes(tpAniSirGlobal pMac, tpLimMlmAssocInd pAssocInd, tANI_U8 *pBuf, tpPESession psessionEntry) +{ + tANI_U8 *pLen = pBuf; + tANI_U16 mLen = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + + mLen = sizeof(tANI_U32); + mLen += sizeof(tANI_U8); + pBuf += sizeof(tANI_U16); + *pBuf = psessionEntry->smeSessionId; + pBuf += sizeof(tANI_U8); + + // Fill in peerMacAddr + vos_mem_copy( pBuf, pAssocInd->peerMacAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + // Fill in aid + limCopyU16(pBuf, pAssocInd->aid); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + + // Fill in bssId + vos_mem_copy( pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + // Fill in staId + limCopyU16(pBuf, psessionEntry->staId); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + + // Fill in authType + limCopyU32(pBuf, pAssocInd->authType); + pBuf += sizeof(tANI_U32); + mLen += sizeof(tANI_U32); + + // Fill in ssId + vos_mem_copy( pBuf, (tANI_U8 *) &(pAssocInd->ssId), pAssocInd->ssId.length + 1); + pBuf += (1 + pAssocInd->ssId.length); + mLen += (1 + pAssocInd->ssId.length); + + // Fill in rsnIE + limCopyU16(pBuf, pAssocInd->rsnIE.length); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + vos_mem_copy( pBuf, (tANI_U8 *) &(pAssocInd->rsnIE.rsnIEdata), + pAssocInd->rsnIE.length); + pBuf += pAssocInd->rsnIE.length; + mLen += pAssocInd->rsnIE.length; + + + limCopyU32(pBuf, pAssocInd->spectrumMgtIndicator); + pBuf += sizeof(tAniBool); + mLen += sizeof(tAniBool); + + if (pAssocInd->spectrumMgtIndicator == eSIR_TRUE) + { + *pBuf = pAssocInd->powerCap.minTxPower; + pBuf++; + *pBuf = pAssocInd->powerCap.maxTxPower; + pBuf++; + mLen += sizeof(tSirMacPowerCapInfo); + + *pBuf = pAssocInd->supportedChannels.numChnl; + pBuf++; + mLen++; + + vos_mem_copy( pBuf, + (tANI_U8 *) &(pAssocInd->supportedChannels.channelList), + pAssocInd->supportedChannels.numChnl); + + + pBuf += pAssocInd->supportedChannels.numChnl; + mLen += pAssocInd->supportedChannels.numChnl; + } + limCopyU32(pBuf, pAssocInd->WmmStaInfoPresent); + pBuf += sizeof(tANI_U32); + mLen += sizeof(tANI_U32); + // Fill in length of SME_ASSOC_IND message + limCopyU16(pLen, mLen); + + PELOG1(limLog(pMac, LOG1, FL("Sending SME_ASSOC_IND length %d bytes:"), mLen);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) +} /*** end limAssocIndSerDes() ***/ + + + +/** + * limAssocCnfSerDes() + * + *FUNCTION: + * This function is called by limProcessLmmMessages() when + * SME_ASSOC_CNF or SME_REASSOC_CNF message is received from + * upper layer software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pAssocCnf Pointer to tSirSmeAssocCnf being extracted into + * @param pBuf Pointer to serialized buffer + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limAssocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeAssocCnf pAssocCnf, tANI_U8 *pBuf) +{ +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + if (!pAssocCnf || !pBuf) + return eSIR_FAILURE; + + pAssocCnf->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + pAssocCnf->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + if (pAssocCnf->messageType == eWNI_SME_ASSOC_CNF) + { + PELOG1(limLog(pMac, LOG1, FL("SME_ASSOC_CNF length %d bytes is:"), pAssocCnf->length);) + } + else + { + PELOG1(limLog(pMac, LOG1, FL("SME_REASSOC_CNF length %d bytes is:"), pAssocCnf->length);) + } + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, pAssocCnf->length);) + + // status code + pAssocCnf->statusCode = (tSirResultCodes) limGetU32(pBuf); + pBuf += sizeof(tSirResultCodes); + + // bssId + vos_mem_copy( pAssocCnf->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + // peerMacAddr + vos_mem_copy( pAssocCnf->peerMacAddr, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + + pAssocCnf->aid = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + // alternateBssId + vos_mem_copy( pAssocCnf->alternateBssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + // alternateChannelId + pAssocCnf->alternateChannelId = *pBuf; + pBuf++; + + return eSIR_SUCCESS; +} /*** end limAssocCnfSerDes() ***/ + + + +/** + * limDisassocCnfSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() when + * SME_DISASSOC_CNF message is received from upper layer software. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pDisassocCnf Pointer to tSirSmeDisassocCnf being + * extracted into + * @param pBuf Pointer to serialized buffer + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limDisassocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeDisassocCnf pDisassocCnf, tANI_U8 *pBuf) +{ +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + if (!pDisassocCnf || !pBuf) + return eSIR_FAILURE; + + pDisassocCnf->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + pDisassocCnf->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_CNF length %d bytes is:"), pDisassocCnf->length);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, pDisassocCnf->length);) + + pDisassocCnf->statusCode = (tSirResultCodes) limGetU32(pBuf); + pBuf += sizeof(tSirResultCodes); + + vos_mem_copy( pDisassocCnf->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + vos_mem_copy( pDisassocCnf->peerMacAddr, pBuf, sizeof(tSirMacAddr)); + + + return eSIR_SUCCESS; +} /*** end limDisassocCnfSerDes() ***/ + + + + + +/**--------------------------------------------------------------- +\fn limReassocIndSerDes +\brief This function is called by limProcessMlmReassocInd() to +\ populate the SME_REASSOC_IND message based on the received +\ MLM_REASSOC_IND. +\ +\param pMac +\param pReassocInd - Pointer to the received tLimMlmReassocInd +\param pBuf - Pointer to serialized buffer +\param psessionEntry - pointer to PE session entry +\ +\return None +------------------------------------------------------------------*/ +void +limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 *pBuf, tpPESession psessionEntry) +{ + tANI_U8 *pLen = pBuf; + tANI_U16 mLen = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + + mLen = sizeof(tANI_U32); + pBuf += sizeof(tANI_U16); + *pBuf++ = psessionEntry->smeSessionId; + mLen += sizeof(tANI_U8); + + // Fill in peerMacAddr + vos_mem_copy( pBuf, pReassocInd->peerMacAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + // Fill in oldMacAddr + vos_mem_copy( pBuf, pReassocInd->currentApAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + // Fill in aid + limCopyU16(pBuf, pReassocInd->aid); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + + // Fill in bssId + vos_mem_copy( pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + // Fill in staId + limCopyU16(pBuf, psessionEntry->staId); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + + // Fill in authType + limCopyU32(pBuf, pReassocInd->authType); + pBuf += sizeof(tAniAuthType); + mLen += sizeof(tAniAuthType); + + // 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; + + // Fill in rsnIE + limCopyU16(pBuf, pReassocInd->rsnIE.length); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + vos_mem_copy( pBuf, (tANI_U8 *) &(pReassocInd->rsnIE.rsnIEdata), + pReassocInd->rsnIE.length); + pBuf += pReassocInd->rsnIE.length; + mLen += pReassocInd->rsnIE.length; + + // Fill in addIE + limCopyU16(pBuf, pReassocInd->addIE.length); + pBuf += sizeof(tANI_U16); + mLen += sizeof(tANI_U16); + vos_mem_copy( pBuf, (tANI_U8*) &(pReassocInd->addIE.addIEdata), + pReassocInd->addIE.length); + pBuf += pReassocInd->addIE.length; + mLen += pReassocInd->addIE.length; + + + limCopyU32(pBuf, pReassocInd->spectrumMgtIndicator); + pBuf += sizeof(tAniBool); + mLen += sizeof(tAniBool); + + if (pReassocInd->spectrumMgtIndicator == eSIR_TRUE) + { + *pBuf = pReassocInd->powerCap.minTxPower; + pBuf++; + *pBuf = pReassocInd->powerCap.maxTxPower; + pBuf++; + mLen += sizeof(tSirMacPowerCapInfo); + + *pBuf = pReassocInd->supportedChannels.numChnl; + pBuf++; + mLen++; + + vos_mem_copy( pBuf, + (tANI_U8 *) &(pReassocInd->supportedChannels.channelList), + pReassocInd->supportedChannels.numChnl); + + pBuf += pReassocInd->supportedChannels.numChnl; + mLen += pReassocInd->supportedChannels.numChnl; + } + limCopyU32(pBuf, pReassocInd->WmmStaInfoPresent); + pBuf += sizeof(tANI_U32); + mLen += sizeof(tANI_U32); + + // 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);) +} /*** end limReassocIndSerDes() ***/ + + +/** + * limAuthIndSerDes() + * + *FUNCTION: + * This function is called by limProcessMlmAuthInd() while sending + * SME_AUTH_IND to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pAuthInd Pointer to tSirSmeAuthInd being sent + * @param pBuf Pointer to serialized buffer + * + * @return None + */ + +void +limAuthIndSerDes(tpAniSirGlobal pMac, tpLimMlmAuthInd pAuthInd, tANI_U8 *pBuf) +{ + tANI_U8 *pLen = pBuf; + tANI_U16 mLen = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + mLen = sizeof(tANI_U32); + pBuf += sizeof(tANI_U16); + *pBuf++ = pAuthInd->sessionId; + mLen += sizeof(tANI_U8); + + // BTAMP TODO: Fill in bssId + vos_mem_set(pBuf, sizeof(tSirMacAddr), 0); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + vos_mem_copy( pBuf, pAuthInd->peerMacAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + mLen += sizeof(tSirMacAddr); + + limCopyU32(pBuf, pAuthInd->authType); + pBuf += sizeof(tAniAuthType); + mLen += sizeof(tAniAuthType); + + 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);) +} /*** end limAuthIndSerDes() ***/ + + + +/** + * limSetContextReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_SETCONTEXT_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pSetContextReq Pointer to tSirSmeSetContextReq being + * extracted + * @param pBuf Pointer to serialized buffer + * + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limSetContextReqSerDes(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetContextReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + tANI_U16 totalKeySize = sizeof(tANI_U8); // initialized to sizeof numKeys + tANI_U8 numKeys; + tANI_U8 *pKeys; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + if (!pSetContextReq || !pBuf) + return eSIR_FAILURE; + + pSetContextReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pSetContextReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_SETCONTEXT_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pSetContextReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pSetContextReq->transactionId = sirReadU16N(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + vos_mem_copy( (tANI_U8 *) pSetContextReq->peerMacAddr, + pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + vos_mem_copy( pSetContextReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pSetContextReq->keyMaterial.length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pSetContextReq->keyMaterial.edType = (tAniEdType) limGetU32(pBuf); + pBuf += sizeof(tAniEdType); + len -= sizeof(tAniEdType); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + numKeys = pSetContextReq->keyMaterial.numKeys = *pBuf++; + len -= sizeof(numKeys); + + if (numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) + return eSIR_FAILURE; + + /** Initialize the Default Keys if no Keys are being sent from the upper layer*/ + if( limCheckRemainingLength(pMac, len) == eSIR_FAILURE) { + tpSirKeys pKeyinfo = pSetContextReq->keyMaterial.key; + + pKeyinfo->keyId = 0; + pKeyinfo->keyDirection = eSIR_TX_RX; + pKeyinfo->keyLength = 0; + + if (!limIsAddrBC(pSetContextReq->peerMacAddr)) + pKeyinfo->unicast = 1; + else + pKeyinfo->unicast = 0; + }else { + pKeys = (tANI_U8 *) pSetContextReq->keyMaterial.key; + do { + tANI_U32 keySize = limGetKeysInfo(pMac, (tpSirKeys) pKeys, + pBuf); + pBuf += keySize; + pKeys += sizeof(tSirKeys); + totalKeySize += (tANI_U16) keySize; + if (numKeys == 0) + break; + numKeys--; + }while (numKeys); + } + return eSIR_SUCCESS; +} /*** end limSetContextReqSerDes() ***/ + +/** + * limRemoveKeyReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_REMOVEKEY_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pRemoveKeyReq Pointer to tSirSmeRemoveKeyReq being + * extracted + * @param pBuf Pointer to serialized buffer + * + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limRemoveKeyReqSerDes(tpAniSirGlobal pMac, tpSirSmeRemoveKeyReq pRemoveKeyReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + if (!pRemoveKeyReq || !pBuf) + return eSIR_FAILURE; + + pRemoveKeyReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pRemoveKeyReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_REMOVEKEY_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + vos_mem_copy( (tANI_U8 *) pRemoveKeyReq->peerMacAddr, + pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + + pRemoveKeyReq->edType = *pBuf; + pBuf += sizeof(tANI_U8); + len -= sizeof(tANI_U8); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pRemoveKeyReq->wepType = *pBuf; + + pBuf += sizeof(tANI_U8); + len -= sizeof(tANI_U8); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pRemoveKeyReq->keyId = *pBuf; + + pBuf += sizeof(tANI_U8); + len -= sizeof(tANI_U8); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pRemoveKeyReq->unicast = *pBuf; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( pRemoveKeyReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pRemoveKeyReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pRemoveKeyReq->transactionId = sirReadU16N(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + return eSIR_SUCCESS; +} /*** end limRemoveKeyReqSerDes() ***/ + + + +/** + * limDisassocReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_DISASSOC_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pDisassocReq Pointer to tSirSmeDisassocReq being extracted + * @param pBuf Pointer to serialized buffer + * + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limDisassocReqSerDes(tpAniSirGlobal pMac, tSirSmeDisassocReq *pDisassocReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + if (!pDisassocReq || !pBuf) + return eSIR_FAILURE; + + pDisassocReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pDisassocReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionID + pDisassocReq->sessionId = *pBuf; + pBuf += sizeof(tANI_U8); + len -= sizeof(tANI_U8); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionid + pDisassocReq->transactionId = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pDisassocReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract peerMacAddr + vos_mem_copy( pDisassocReq->peerMacAddr, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract reasonCode + pDisassocReq->reasonCode = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + pDisassocReq->doNotSendOverTheAir = *pBuf; + pBuf += sizeof(tANI_U8); + len -= sizeof(tANI_U8); + + + return eSIR_SUCCESS; +} /*** end limDisassocReqSerDes() ***/ + + + +/** + * limDeauthReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * SME_DEAUTH_REQ from host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pDeauthReq Pointer to tSirSmeDeauthReq being extracted + * @param pBuf Pointer to serialized buffer + * + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ +tSirRetStatus +limDeauthReqSerDes(tpAniSirGlobal pMac, tSirSmeDeauthReq *pDeauthReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + if (!pDeauthReq || !pBuf) + return eSIR_FAILURE; + + pDeauthReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pDeauthReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_DEAUTH_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pDeauthReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pDeauthReq->transactionId = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( pDeauthReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract peerMacAddr + vos_mem_copy( pDeauthReq->peerMacAddr, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract reasonCode + pDeauthReq->reasonCode = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + + + return eSIR_SUCCESS; +} /*** end limDisassocReqSerDes() ***/ + + +/** + * limStatSerDes() + * + *FUNCTION: + * This function is called by limSendSmeDisassocNtf() while sending + * SME_DISASSOC_IND/eWNI_SME_DISASSOC_RSP to host + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pAssocInd Pointer to tpAniStaStatStruct being sent + * @param pBuf Pointer to serialized buffer + * + * @return None + */ + +void +limStatSerDes(tpAniSirGlobal pMac, tpAniStaStatStruct pStat, tANI_U8 *pBuf) +{ +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + limCopyU32(pBuf, pStat->sentAesBlksUcastHi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->sentAesBlksUcastLo); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->recvAesBlksUcastHi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->recvAesBlksUcastLo); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->aesFormatErrorUcastCnts); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->aesReplaysUcast); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->aesDecryptErrUcast); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->singleRetryPkts); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->failedTxPkts); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->ackTimeouts); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->multiRetryPkts); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->fragTxCntsHi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->fragTxCntsLo); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->transmittedPktsHi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->transmittedPktsLo); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->phyStatHi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->phyStatLo); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->uplinkRssi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->uplinkSinr); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->uplinkRate); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->downlinkRssi); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->downlinkSinr); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->downlinkRate); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->nRcvBytes); + pBuf += sizeof(tANI_U32); + + limCopyU32(pBuf, pStat->nXmitBytes); + pBuf += sizeof(tANI_U32); + + PELOG1(limLog(pMac, LOG1, FL("STAT: length %d bytes is:"), sizeof(tAniStaStatStruct));) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, sizeof(tAniStaStatStruct));) + +} /*** end limStatSerDes() ***/ + + + + +/** + * limPackBkgndScanFailNotify() + * + *FUNCTION: + * This function is called by limSendSmeWmStatusChangeNtf() + * to pack the tSirBackgroundScanInfo message + * + */ +void +limPackBkgndScanFailNotify(tpAniSirGlobal pMac, + tSirSmeStatusChangeCode statusChangeCode, + tpSirBackgroundScanInfo pScanInfo, + tSirSmeWmStatusChangeNtf *pSmeNtf, + tANI_U8 sessionId) +{ + + tANI_U16 length = (sizeof(tANI_U16) * 2) + sizeof(tANI_U8) + + sizeof(tSirSmeStatusChangeCode) + + sizeof(tSirBackgroundScanInfo); + + pSmeNtf->messageType = eWNI_SME_WM_STATUS_CHANGE_NTF; + pSmeNtf->statusChangeCode = statusChangeCode; + pSmeNtf->length = length; + pSmeNtf->sessionId = sessionId; + pSmeNtf->statusChangeInfo.bkgndScanInfo.numOfScanSuccess = pScanInfo->numOfScanSuccess; + pSmeNtf->statusChangeInfo.bkgndScanInfo.numOfScanFailure = pScanInfo->numOfScanFailure; + pSmeNtf->statusChangeInfo.bkgndScanInfo.reserved = pScanInfo->reserved; +} + + +/** + * limIsSmeGetAssocSTAsReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_GET_ASSOC_STAS_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pBuf - Pointer to a serialized SME_GET_ASSOC_STAS_REQ message + * @param pSmeMsg - Pointer to a tSirSmeGetAssocSTAsReq structure + * @return true if SME_GET_ASSOC_STAS_REQ message is formatted correctly + * false otherwise + */ +tANI_BOOLEAN +limIsSmeGetAssocSTAsReqValid(tpAniSirGlobal pMac, tpSirSmeGetAssocSTAsReq pGetAssocSTAsReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + + pGetAssocSTAsReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pGetAssocSTAsReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eANI_BOOLEAN_FALSE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eANI_BOOLEAN_FALSE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pGetAssocSTAsReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eANI_BOOLEAN_FALSE; + + // Extract modId + pGetAssocSTAsReq->modId = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eANI_BOOLEAN_FALSE; + + // Extract pUsrContext + vos_mem_copy((tANI_U8 *)pGetAssocSTAsReq->pUsrContext, pBuf, sizeof(void*)); + pBuf += sizeof(void*); + len -= sizeof(void*); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eANI_BOOLEAN_FALSE; + + // Extract pSapEventCallback + vos_mem_copy((tANI_U8 *)pGetAssocSTAsReq->pSapEventCallback, pBuf, sizeof(void*)); + pBuf += sizeof(void*); + len -= sizeof(void*); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eANI_BOOLEAN_FALSE; + + // Extract pAssocStasArray + vos_mem_copy((tANI_U8 *)pGetAssocSTAsReq->pAssocStasArray, pBuf, sizeof(void*)); + pBuf += sizeof(void*); + len -= sizeof(void*); + + PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes "), len);) + + if (len < 0) + { + PELOGE(limLog(pMac, LOGE, FL("SME_GET_ASSOC_STAS_REQ invalid length"));) + return eANI_BOOLEAN_FALSE; + } + + return eANI_BOOLEAN_TRUE; +} + +/** + * limTkipCntrMeasReqSerDes() + * + *FUNCTION: + * This function is called by limProcessSmeMessages() upon receiving + * eWNI_SME_TKIP_CNTR_MEAS_REQ from host HDD + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param tpSirSmeTkipCntrMeasReq Pointer to tSirSmeTkipCntrMeasReq being extracted + * @param pBuf Pointer to serialized buffer + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ +tSirRetStatus +limTkipCntrMeasReqSerDes(tpAniSirGlobal pMac, tpSirSmeTkipCntrMeasReq pTkipCntrMeasReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + +#ifdef PE_DEBUG_LOG1 + tANI_U8 *pTemp = pBuf; +#endif + + pTkipCntrMeasReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pTkipCntrMeasReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length %d bytes is:"), len);) + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pTkipCntrMeasReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pTkipCntrMeasReq->transactionId = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + len -= sizeof(tANI_U16); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pTkipCntrMeasReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bEnable + pTkipCntrMeasReq->bEnable = *pBuf++; + len --; + + PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length consumed %d bytes "), len);) + + if (len) + { + PELOGE(limLog(pMac, LOGE, FL("SME_TKIP_CNTR_MEAS_REQ invalid "));) + return eSIR_FAILURE; + } + else + return eSIR_SUCCESS; +} + +/** + * limIsSmeGetWPSPBCSessionsReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeGetWPSPBCSessions() upon + * receiving query WPS PBC overlap information message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pBuf - Pointer to a serialized SME_GET_WPSPBC_SESSION_REQ message + * @param pGetWPSPBCSessionsReq - Pointer to a tSirSmeGetWPSPBCSessionsReq structure + * @return true if SME_GET_WPSPBC_SESSION_REQ message is formatted correctly + * false otherwise + */ + +tSirRetStatus +limIsSmeGetWPSPBCSessionsReqValid(tpAniSirGlobal pMac, tSirSmeGetWPSPBCSessionsReq *pGetWPSPBCSessionsReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pBuf, sizeof(tSirSmeGetWPSPBCSessionsReq));) + + pGetWPSPBCSessionsReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pGetWPSPBCSessionsReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract pUsrContext + vos_mem_copy((tANI_U8 *)pGetWPSPBCSessionsReq->pUsrContext, pBuf, sizeof(void*)); + pBuf += sizeof(void*); + len -= sizeof(void*); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract pSapEventCallback + vos_mem_copy((tANI_U8 *)pGetWPSPBCSessionsReq->pSapEventCallback, pBuf, sizeof(void*)); + pBuf += sizeof(void*); + len -= sizeof(void*); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pGetWPSPBCSessionsReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + + // Extract MAC address of Station to be removed + vos_mem_copy( (tANI_U8 *) pGetWPSPBCSessionsReq->pRemoveMac, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + + PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes "), len);) + + if (len < 0) + { + PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length"));) + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + + +/**--------------------------------------------------------------- +\fn limGetSessionInfo +\brief This function returns the sessionId and transactionId +\ of a message. This assumes that the message structure +\ is of format: +\ tANI_U16 messageType +\ tANI_U16 messageLength +\ tANI_U8 sessionId +\ tANI_U16 transactionId +\param pMac - pMac global structure +\param *pBuf - pointer to the message buffer +\param sessionId - returned session id value +\param transactionId - returned transaction ID value +\return None +------------------------------------------------------------------*/ +void +limGetSessionInfo(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *sessionId, tANI_U16 *transactionId) +{ + if (!pBuf) + { + limLog(pMac, LOGE, FL("NULL ptr received. ")); + return; + } + + pBuf += sizeof(tANI_U16); // skip message type + pBuf += sizeof(tANI_U16); // skip message length + + *sessionId = *pBuf; // get sessionId + pBuf++; + *transactionId = limGetU16(pBuf); // get transactionId + + return; +} + + +/** + * limUpdateAPWPSIEsReqSerDes() + * + *FUNCTION: + * This function is to deserialize UpdateAPWPSIEs message + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pUpdateAPWPSIEsReq Pointer to tSirUpdateAPWPSIEsReq being + * extracted + * @param pBuf Pointer to serialized buffer + * + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limUpdateAPWPSIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPSIEsReq pUpdateAPWPSIEsReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pBuf, sizeof(tSirUpdateAPWPSIEsReq));) + + if (!pUpdateAPWPSIEsReq || !pBuf) + return eSIR_FAILURE; + + pUpdateAPWPSIEsReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pUpdateAPWPSIEsReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pUpdateAPWPSIEsReq->transactionId = limGetU16( pBuf ); + pBuf += sizeof( tANI_U16 ); + len -= sizeof( tANI_U16 ); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pUpdateAPWPSIEsReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pUpdateAPWPSIEsReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract APWPSIEs + vos_mem_copy( (tSirAPWPSIEs *) &pUpdateAPWPSIEsReq->APWPSIEs, pBuf, sizeof(tSirAPWPSIEs)); + pBuf += sizeof(tSirAPWPSIEs); + len -= sizeof(tSirAPWPSIEs); + + PELOG1(limLog(pMac, LOG1, FL("SME_UPDATE_APWPSIE_REQ length consumed %d bytes "), len);) + + if (len < 0) + { + PELOGE(limLog(pMac, LOGE, FL("SME_UPDATE_APWPSIE_REQ invalid length"));) + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} /*** end limSetContextReqSerDes() ***/ + +/** + * limUpdateAPWPARSNIEsReqSerDes () + * + *FUNCTION: + * This function is to deserialize UpdateAPWPSIEs message + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pUpdateAPWPARSNIEsReq Pointer to tpSirUpdateAPWPARSNIEsReq being + * extracted + * @param pBuf Pointer to serialized buffer + * + * @return retCode Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) + */ + +tSirRetStatus +limUpdateAPWPARSNIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPARSNIEsReq pUpdateAPWPARSNIEsReq, tANI_U8 *pBuf) +{ + tANI_S16 len = 0; + + PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pBuf, sizeof(tSirUpdateAPWPARSNIEsReq));) + + if (!pUpdateAPWPARSNIEsReq || !pBuf) + return eSIR_FAILURE; + + pUpdateAPWPARSNIEsReq->messageType = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + len = pUpdateAPWPARSNIEsReq->length = limGetU16(pBuf); + pBuf += sizeof(tANI_U16); + + if (len < (tANI_S16) sizeof(tANI_U32)) + return eSIR_FAILURE; + + len -= sizeof(tANI_U32); // skip message header + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract transactionId + pUpdateAPWPARSNIEsReq->transactionId = limGetU16( pBuf ); + pBuf += sizeof(tANI_U16); + len -= sizeof( tANI_U16 ); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract bssId + vos_mem_copy( (tANI_U8 *) pUpdateAPWPARSNIEsReq->bssId, pBuf, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + len -= sizeof(tSirMacAddr); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract sessionId + pUpdateAPWPARSNIEsReq->sessionId = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + + // Extract APWPARSNIEs + vos_mem_copy( (tSirRSNie *) &pUpdateAPWPARSNIEsReq->APWPARSNIEs, pBuf, sizeof(tSirRSNie)); + pBuf += sizeof(tSirRSNie); + len -= sizeof(tSirRSNie); + + if (len < 0) + { + PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length"));) + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} /*** end limUpdateAPWPARSNIEsReqSerDes() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.h new file mode 100644 index 000000000000..62e6129fe898 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSerDesUtils.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limSerDesUtils.h contains the utility definitions + * LIM uses while processing messages from upper layer software + * modules + * Author: Chandra Modumudi + * Date: 10/20/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __LIM_SERDES_UTILS_H +#define __LIM_SERDES_UTILS_H + +#include "sirApi.h" +#include "aniSystemDefs.h" +#include "sirMacProtDef.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limPropExtsUtils.h" + +tSirRetStatus limStartBssReqSerDes(tpAniSirGlobal, tpSirSmeStartBssReq, tANI_U8 *); +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 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 *); +void limStatSerDes(tpAniSirGlobal, tpAniStaStatStruct, tANI_U8 *); +void limGetSessionInfo(tpAniSirGlobal pMac, tANI_U8 *, tANI_U8 *, tANI_U16 *); + + +void limPackBkgndScanFailNotify(tpAniSirGlobal, tSirSmeStatusChangeCode, + tpSirBackgroundScanInfo, tSirSmeWmStatusChangeNtf *, tANI_U8); + + +tSirRetStatus limRemoveKeyReqSerDes(tpAniSirGlobal pMac, tpSirSmeRemoveKeyReq pRemoveKeyReq, tANI_U8 * pBuf); + +tANI_BOOLEAN limIsSmeGetAssocSTAsReqValid(tpAniSirGlobal pMac, tpSirSmeGetAssocSTAsReq pGetAssocSTAsReq, tANI_U8 *pBuf); +tSirRetStatus limTkipCntrMeasReqSerDes(tpAniSirGlobal pMac, tpSirSmeTkipCntrMeasReq ptkipCntrMeasReq, tANI_U8 *pBuf); + +tSirRetStatus limUpdateAPWPSIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPSIEsReq pUpdateAPWPSIEsReq, tANI_U8 *pBuf); +tSirRetStatus limUpdateAPWPARSNIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPARSNIEsReq pUpdateAPWPARSNIEsReq, tANI_U8 *pBuf); + + +// Byte String <--> tANI_U16/tANI_U32 copy functions +static inline void limCopyU16(tANI_U8 *ptr, tANI_U16 u16Val) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + *ptr++ = (tANI_U8) (u16Val & 0xff); + *ptr = (tANI_U8) ((u16Val >> 8) & 0xff); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +static inline tANI_U16 limGetU16(tANI_U8 *ptr) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + return (((tANI_U16) (*(ptr+1) << 8)) | + ((tANI_U16) (*ptr))); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +static inline void limCopyU32(tANI_U8 *ptr, tANI_U32 u32Val) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + *ptr++ = (tANI_U8) (u32Val & 0xff); + *ptr++ = (tANI_U8) ((u32Val >> 8) & 0xff); + *ptr++ = (tANI_U8) ((u32Val >> 16) & 0xff); + *ptr = (tANI_U8) ((u32Val >> 24) & 0xff); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +static inline tANI_U32 limGetU32(tANI_U8 *ptr) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + return ((*(ptr+3) << 24) | + (*(ptr+2) << 16) | + (*(ptr+1) << 8) | + (*(ptr))); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +#endif /* __LIM_SERDES_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c new file mode 100644 index 000000000000..d11b729d008a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c @@ -0,0 +1,850 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file limSession.c + + \brief implementation for lim Session related APIs + + \author Sunit Bhatia + + ========================================================================*/ + + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "aniGlobal.h" +#include "limDebug.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#include "limFT.h" +#endif +#include "limSession.h" +#include "limUtils.h" +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "eseApi.h" +#endif + +#include "pmmApi.h" +#include "schApi.h" +#include "limSendMessages.h" + +/*-------------------------------------------------------------------------- + + \brief peInitBeaconParams() - Initialize the beaconParams structure + + + \param tpPESession - pointer to the session context or NULL if session can not be created. + \return void + \sa + + --------------------------------------------------------------------------*/ + +void peInitBeaconParams(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + psessionEntry->beaconParams.beaconInterval = 0; + psessionEntry->beaconParams.fShortPreamble = 0; + psessionEntry->beaconParams.llaCoexist = 0; + psessionEntry->beaconParams.llbCoexist = 0; + psessionEntry->beaconParams.llgCoexist = 0; + psessionEntry->beaconParams.ht20Coexist = 0; + psessionEntry->beaconParams.llnNonGFCoexist = 0; + psessionEntry->beaconParams.fRIFSMode = 0; + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = 0; + psessionEntry->beaconParams.gHTObssMode = 0; + + // Number of legacy STAs associated + vos_mem_set((void*)&psessionEntry->gLim11bParams, sizeof(tLimProtStaParams), 0); + vos_mem_set((void*)&psessionEntry->gLim11aParams, sizeof(tLimProtStaParams), 0); + vos_mem_set((void*)&psessionEntry->gLim11gParams, sizeof(tLimProtStaParams), 0); + vos_mem_set((void*)&psessionEntry->gLimNonGfParams, sizeof(tLimProtStaParams), 0); + vos_mem_set((void*)&psessionEntry->gLimHt20Params, sizeof(tLimProtStaParams), 0); + vos_mem_set((void*)&psessionEntry->gLimLsigTxopParams, sizeof(tLimProtStaParams), 0); + vos_mem_set((void*)&psessionEntry->gLimOlbcParams, sizeof(tLimProtStaParams), 0); +} + +/** + * pe_reset_protection_callback() - resets protection structs so that when an AP + * causing use of protection goes away, corresponding protection bit can be + * reset + * @ptr: pointer to pSessionEntry + * + * This function resets protection structs so that when an AP causing use of + * protection goes away, corresponding protection bit can be reset. This allowes + * protection bits to be reset once legacy overlapping APs are gone. + * + * Return: void + */ +void pe_reset_protection_callback(void *ptr) +{ + tpPESession pe_session_entry = (tpPESession)ptr; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)pe_session_entry->mac_ctx; + int8_t i = 0; + tUpdateBeaconParams beacon_params; + tANI_U16 current_protection_state = 0; + tpDphHashNode station_hash_node = NULL; + tSirMacHTOperatingMode old_op_mode; + bool bcn_prms_changed = false; + + if (pe_session_entry->valid == false) { + VOS_TRACE(VOS_MODULE_ID_PE, + VOS_TRACE_LEVEL_ERROR, + FL("session already deleted. exiting timer callback")); + return; + } + + current_protection_state |= + pe_session_entry->gLimOverlap11gParams.protectionEnabled | + pe_session_entry->gLimOverlap11aParams.protectionEnabled << 1 | + pe_session_entry->gLimOverlapHt20Params.protectionEnabled << 2 | + pe_session_entry->gLimOverlapNonGfParams.protectionEnabled << 3 | + pe_session_entry->gLimOlbcParams.protectionEnabled << 4 ; + + VOS_TRACE(VOS_MODULE_ID_PE, + VOS_TRACE_LEVEL_INFO, + FL("old protection state: 0x%04X, new protection state: 0x%04X"), + pe_session_entry->old_protection_state, + current_protection_state); + + vos_mem_zero(&pe_session_entry->gLimOverlap11gParams, + sizeof(pe_session_entry->gLimOverlap11gParams)); + vos_mem_zero(&pe_session_entry->gLimOverlap11aParams, + sizeof(pe_session_entry->gLimOverlap11aParams)); + vos_mem_zero(&pe_session_entry->gLimOverlapHt20Params, + sizeof(pe_session_entry->gLimOverlapHt20Params)); + vos_mem_zero(&pe_session_entry->gLimOverlapNonGfParams, + sizeof(pe_session_entry->gLimOverlapNonGfParams)); + + vos_mem_zero(&pe_session_entry->gLimOlbcParams, + sizeof(pe_session_entry->gLimOlbcParams)); + + vos_mem_zero(&pe_session_entry->beaconParams, + sizeof(pe_session_entry->beaconParams)); + + vos_mem_zero(&mac_ctx->lim.gLimOverlap11gParams, + sizeof(mac_ctx->lim.gLimOverlap11gParams)); + vos_mem_zero(&mac_ctx->lim.gLimOverlap11aParams, + sizeof(mac_ctx->lim.gLimOverlap11aParams)); + vos_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params, + sizeof(mac_ctx->lim.gLimOverlapHt20Params)); + vos_mem_zero(&mac_ctx->lim.gLimOverlapNonGfParams, + sizeof(mac_ctx->lim.gLimOverlapNonGfParams)); + + old_op_mode = pe_session_entry->htOperMode; + pe_session_entry->htOperMode = eSIR_HT_OP_MODE_PURE; + + vos_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); + /* index 0, is self node, peers start from 1 */ + for(i = 1 ; i <= mac_ctx->lim.gLimAssocStaLimit ; i++) + { + station_hash_node = dphGetHashEntry(mac_ctx, i, + &pe_session_entry->dph.dphHashTable); + if (NULL == station_hash_node) + continue; + limDecideApProtection(mac_ctx, station_hash_node->staAddr, + &beacon_params, pe_session_entry); + } + + if (pe_session_entry->htOperMode != old_op_mode) + bcn_prms_changed = true; + + if ((current_protection_state != pe_session_entry->old_protection_state) && + (VOS_FALSE == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) { + VOS_TRACE(VOS_MODULE_ID_PE, + VOS_TRACE_LEVEL_ERROR, + FL("protection changed, update beacon template")); + /* update beacon fix params and send update to FW */ + vos_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); + beacon_params.bssIdx = pe_session_entry->bssIdx; + beacon_params.fShortPreamble = + pe_session_entry->beaconParams.fShortPreamble; + beacon_params.beaconInterval = + pe_session_entry->beaconParams.beaconInterval; + beacon_params.llaCoexist = + pe_session_entry->beaconParams.llaCoexist; + beacon_params.llbCoexist = + pe_session_entry->beaconParams.llbCoexist; + beacon_params.llgCoexist = + pe_session_entry->beaconParams.llgCoexist; + beacon_params.ht20MhzCoexist = + pe_session_entry->beaconParams.ht20Coexist; + beacon_params.llnNonGFCoexist = + pe_session_entry->beaconParams.llnNonGFCoexist; + beacon_params.fLsigTXOPProtectionFullSupport = + pe_session_entry->beaconParams.fLsigTXOPProtectionFullSupport; + beacon_params.fRIFSMode = + pe_session_entry->beaconParams.fRIFSMode; + beacon_params.smeSessionId = + pe_session_entry->smeSessionId; + bcn_prms_changed = true; + } + + if (bcn_prms_changed) { + schSetFixedBeaconFields(mac_ctx, pe_session_entry); + limSendBeaconParams(mac_ctx, &beacon_params, pe_session_entry); + } + + pe_session_entry->old_protection_state = current_protection_state; + if (VOS_STATUS_SUCCESS != vos_timer_start( + &pe_session_entry->protection_fields_reset_timer, + SCH_PROTECTION_RESET_TIME)) { + VOS_TRACE(VOS_MODULE_ID_PE, + VOS_TRACE_LEVEL_ERROR, + FL("cannot create or start protectionFieldsResetTimer")); + } +} + +/*-------------------------------------------------------------------------- + + \brief peCreateSession() - creates a new PE session given the BSSID + + This function returns the session context and the session ID if the session + corresponding to the passed BSSID is found in the PE session table. + + \param pMac - pointer to global adapter context + \param bssid - BSSID of the new session + \param sessionId - session ID is returned here, if session is created. + \param bssType - station or a + \return tpPESession - pointer to the session context or NULL if session + can not be created. + + \sa + + --------------------------------------------------------------------------*/ +tpPESession peCreateSession(tpAniSirGlobal pMac, + tANI_U8 *bssid, + tANI_U8* sessionId, + tANI_U16 numSta, + tSirBssType bssType) +{ + VOS_STATUS status; + tANI_U8 i; + for(i =0; i < pMac->lim.maxBssId; i++) + { + /* Find first free room in session table */ + if(pMac->lim.gpSession[i].valid == FALSE) + { + vos_mem_set((void*)&pMac->lim.gpSession[i], sizeof(tPESession), 0); + + //Allocate space for Station Table for this session. + pMac->lim.gpSession[i].dph.dphHashTable.pHashTable = vos_mem_malloc( + sizeof(tpDphHashNode)* (numSta + 1)); + if ( NULL == pMac->lim.gpSession[i].dph.dphHashTable.pHashTable ) + { + limLog(pMac, LOGE, FL("memory allocate failed!")); + return NULL; + } + pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray = vos_mem_malloc( + sizeof(tDphHashNode) * (numSta + 1)); + if ( NULL == pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray ) + { + limLog(pMac, LOGE, FL("memory allocate failed!")); + vos_mem_free(pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); + pMac->lim.gpSession[i].dph.dphHashTable.pHashTable = NULL; + return NULL; + } + + pMac->lim.gpSession[i].dph.dphHashTable.size = numSta + 1; + + dphHashTableClassInit(pMac, + &pMac->lim.gpSession[i].dph.dphHashTable); + + pMac->lim.gpSession[i].gpLimPeerIdxpool = vos_mem_malloc(sizeof( + *pMac->lim.gpSession[i].gpLimPeerIdxpool) * (numSta+1)); + if ( NULL == pMac->lim.gpSession[i].gpLimPeerIdxpool ) + { + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) + vos_mem_free(pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); + vos_mem_free(pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray); + pMac->lim.gpSession[i].dph.dphHashTable.pHashTable = NULL; + pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray = NULL; + return NULL; + } + vos_mem_set(pMac->lim.gpSession[i].gpLimPeerIdxpool, + sizeof(*pMac->lim.gpSession[i].gpLimPeerIdxpool) * (numSta+1), 0); + pMac->lim.gpSession[i].freePeerIdxHead = 0; + pMac->lim.gpSession[i].freePeerIdxTail = 0; + pMac->lim.gpSession[i].gLimNumOfCurrentSTAs = 0; + + /* Copy the BSSID to the session table */ + sirCopyMacAddr(pMac->lim.gpSession[i].bssId, bssid); + pMac->lim.gpSession[i].valid = TRUE; + + /* Initialize the SME and MLM states to IDLE */ + pMac->lim.gpSession[i].limMlmState = eLIM_MLM_IDLE_STATE; + pMac->lim.gpSession[i].limSmeState = eLIM_SME_IDLE_STATE; + pMac->lim.gpSession[i].limCurrentAuthType = eSIR_OPEN_SYSTEM; + peInitBeaconParams(pMac, &pMac->lim.gpSession[i]); +#ifdef WLAN_FEATURE_VOWIFI_11R + pMac->lim.gpSession[i].is11Rconnection = FALSE; +#endif + +#ifdef FEATURE_WLAN_ESE + pMac->lim.gpSession[i].isESEconnection = FALSE; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + pMac->lim.gpSession[i].isFastTransitionEnabled = FALSE; +#endif +#ifdef FEATURE_WLAN_LFR + pMac->lim.gpSession[i].isFastRoamIniFeatureEnabled = FALSE; +#endif + *sessionId = i; + + pMac->lim.gpSession[i].gLimPhyMode = WNI_CFG_PHY_MODE_11G; //TODO :Check with the team what should be default mode + /* Initialize CB mode variables when session is created */ + pMac->lim.gpSession[i].htSupportedChannelWidthSet = 0; + pMac->lim.gpSession[i].htRecommendedTxWidthSet = 0; + pMac->lim.gpSession[i].htSecondaryChannelOffset = 0; +#ifdef FEATURE_WLAN_TDLS + vos_mem_set(pMac->lim.gpSession[i].peerAIDBitmap, + sizeof(pMac->lim.gpSession[i].peerAIDBitmap), 0); + pMac->lim.gpSession[i].tdls_prohibited = false; + pMac->lim.gpSession[i].tdls_chan_swit_prohibited = false; +#endif + pMac->lim.gpSession[i].fWaitForProbeRsp = 0; + pMac->lim.gpSession[i].fIgnoreCapsChange = 0; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "Create a new PE session (%d) with BSSID: " + MAC_ADDRESS_STR " Max No. of STA %d", + pMac->lim.gpSession[i].peSessionId, + MAC_ADDR_ARRAY(bssid), numSta); + pMac->lim.gpSession[i].roaming_in_progress = false; + + /* Initialize PMM Ps Offload Module */ + if(pMac->psOffloadEnabled) + { + if(pmmPsOffloadOpen(pMac, &pMac->lim.gpSession[i]) + != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGE, + FL("Failed to open ps offload for pe session %x"), i); + } + } + + if (eSIR_INFRA_AP_MODE == bssType || + eSIR_IBSS_MODE == bssType || + eSIR_BTAMP_AP_MODE == bssType) + { + pMac->lim.gpSession[i].pSchProbeRspTemplate = + vos_mem_malloc(SCH_MAX_PROBE_RESP_SIZE); + pMac->lim.gpSession[i].pSchBeaconFrameBegin = + vos_mem_malloc(SCH_MAX_BEACON_SIZE); + pMac->lim.gpSession[i].pSchBeaconFrameEnd = + vos_mem_malloc(SCH_MAX_BEACON_SIZE); + if ( (NULL == pMac->lim.gpSession[i].pSchProbeRspTemplate) + || (NULL == pMac->lim.gpSession[i].pSchBeaconFrameBegin) + || (NULL == pMac->lim.gpSession[i].pSchBeaconFrameEnd) ) + { + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) + vos_mem_free(pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); + vos_mem_free(pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray); + vos_mem_free(pMac->lim.gpSession[i].gpLimPeerIdxpool); + vos_mem_free(pMac->lim.gpSession[i].pSchProbeRspTemplate); + vos_mem_free(pMac->lim.gpSession[i].pSchBeaconFrameBegin); + vos_mem_free(pMac->lim.gpSession[i].pSchBeaconFrameEnd); + + pMac->lim.gpSession[i].dph.dphHashTable.pHashTable = NULL; + pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray = NULL; + pMac->lim.gpSession[i].gpLimPeerIdxpool = NULL; + pMac->lim.gpSession[i].pSchProbeRspTemplate = NULL; + pMac->lim.gpSession[i].pSchBeaconFrameBegin = NULL; + pMac->lim.gpSession[i].pSchBeaconFrameEnd = NULL; + return NULL; + } + } + +#if defined WLAN_FEATURE_VOWIFI_11R + if (eSIR_INFRASTRUCTURE_MODE == bssType) { + limFTOpen(pMac, &pMac->lim.gpSession[i]); + } +#endif + + if (eSIR_INFRA_AP_MODE == bssType) { + pMac->lim.gpSession[i].old_protection_state = 0; + pMac->lim.gpSession[i].mac_ctx = (void *)pMac; + status = vos_timer_init( + &pMac->lim.gpSession[i].protection_fields_reset_timer, + VOS_TIMER_TYPE_SW, pe_reset_protection_callback, + (void *)&pMac->lim.gpSession[i]); + if (status == VOS_STATUS_SUCCESS) { + status = vos_timer_start( + &pMac->lim.gpSession[i].protection_fields_reset_timer, + SCH_PROTECTION_RESET_TIME); + } + if (status != VOS_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_PE, + VOS_TRACE_LEVEL_ERROR, + FL("cannot create or start protectionFieldsResetTimer")); + } + } + + return(&pMac->lim.gpSession[i]); + } + } + limLog(pMac, LOGE, + FL("Session can not be created.. Reached Max permitted sessions")); + return NULL; +} + +/*-------------------------------------------------------------------------- + \brief peFindSessionByBssid() - looks up the PE session given the BSSID. + + This function returns the session context and the session ID if the session + corresponding to the given BSSID is found in the PE session table. + + \param pMac - pointer to global adapter context + \param bssid - BSSID of the session + \param sessionId -session ID is returned here, if session is found. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ +tpPESession peFindSessionByBssid(tpAniSirGlobal pMac, tANI_U8* bssid, tANI_U8* sessionId) +{ + tANI_U8 i; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + /* If BSSID matches return corresponding tables address*/ + if( (pMac->lim.gpSession[i].valid) && (sirCompareMacAddr(pMac->lim.gpSession[i].bssId, bssid))) + { + *sessionId = i; + return(&pMac->lim.gpSession[i]); + } + } + + limLog(pMac, LOG4, FL("Session lookup fails for BSSID:")); + limPrintMacAddr(pMac, bssid, LOG4); + return(NULL); + +} + + +/*-------------------------------------------------------------------------- + \brief peFindSessionByBssIdx() - looks up the PE session given the bssIdx. + + This function returns the session context if the session + corresponding to the given bssIdx is found in the PE session table. + \param pMac - pointer to global adapter context + \param bssIdx - bss index of the session + \return tpPESession - pointer to the session context or NULL if session is not found. + \sa + --------------------------------------------------------------------------*/ +tpPESession peFindSessionByBssIdx(tpAniSirGlobal pMac, tANI_U8 bssIdx) +{ + tANI_U8 i; + 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].bssIdx == bssIdx)) + { + return &pMac->lim.gpSession[i]; + } + } + limLog(pMac, LOG4, FL("Session lookup fails for bssIdx: %d"), bssIdx); + return NULL; +} + +/** + * pe_find_session_by_sme_session_id() - looks up the PE session for given sme + * session id + * @mac_ctx: pointer to global adapter context + * @sme_session_id: sme session id + * + * looks up the PE session for given sme session id + * + * Return: pe session entry for given sme session if found else NULL + */ +tpPESession pe_find_session_by_sme_session_id(tpAniSirGlobal mac_ctx, + tANI_U8 sme_session_id) +{ + uint8_t i; + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + if ( (mac_ctx->lim.gpSession[i].valid) && + (mac_ctx->lim.gpSession[i].smeSessionId == + sme_session_id) ) { + return &mac_ctx->lim.gpSession[i]; + } + } + limLog(mac_ctx, LOG4, + FL("Session lookup fails for smeSessionID: %d"), + sme_session_id); + return NULL; +} + +/*-------------------------------------------------------------------------- + \brief peFindSessionBySessionId() - looks up the PE session given the session ID. + + This function returns the session context if the session + corresponding to the given session ID is found in the PE session table. + + \param pMac - pointer to global adapter context + \param sessionId -session ID for which session context needs to be looked up. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ + tpPESession peFindSessionBySessionId(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + if(sessionId >= pMac->lim.maxBssId) + { + limLog(pMac, LOGE, FL("Invalid sessionId: %d"), sessionId); + return(NULL); + } + if((pMac->lim.gpSession[sessionId].valid == TRUE)) + { + return(&pMac->lim.gpSession[sessionId]); + } + return(NULL); + +} + + +/*-------------------------------------------------------------------------- + \brief peFindSessionByStaId() - looks up the PE session given staid. + + This function returns the session context and the session ID if the session + corresponding to the given StaId is found in the PE session table. + + \param pMac - pointer to global adapter context + \param staid - StaId of the session + \param sessionId -session ID is returned here, if session is found. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ +tpPESession peFindSessionByStaId(tpAniSirGlobal pMac, tANI_U8 staid, tANI_U8* sessionId) +{ + tANI_U8 i, j; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid) + { + for(j = 0; j < pMac->lim.gpSession[i].dph.dphHashTable.size; j++) + { + if((pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray[j].valid) && + (pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray[j].added) && + (staid == pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray[j].staIndex)) + { + *sessionId = i; + return(&pMac->lim.gpSession[i]); + } + } + } + } + + limLog(pMac, LOG4, FL("Session lookup fails for StaId: %d"), staid); + return(NULL); +} + + + +/*-------------------------------------------------------------------------- + \brief peDeleteSession() - deletes the PE session given the session ID. + + + \param pMac - pointer to global adapter context + \param sessionId -session ID of the session which needs to be deleted. + + \sa + --------------------------------------------------------------------------*/ +void peDeleteSession(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tANI_U16 i = 0; + tANI_U16 n; + TX_TIMER *timer_ptr; + + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, + "Trying to delete PE session %d Opmode %d BssIdx %d" + " BSSID: " MAC_ADDRESS_STR, psessionEntry->peSessionId, + psessionEntry->operMode, psessionEntry->bssIdx, + MAC_ADDR_ARRAY(psessionEntry->bssId)); + + for (n = 0; n < (pMac->lim.maxStation + 1); n++) + { + timer_ptr = &pMac->lim.limTimers.gpLimCnfWaitTimer[n]; + + if(psessionEntry->peSessionId == timer_ptr->sessionId) + { + if(VOS_TRUE == tx_timer_running(timer_ptr)) + { + tx_timer_deactivate(timer_ptr); + } + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + vos_timer_stop(&psessionEntry->protection_fields_reset_timer); + vos_timer_destroy(&psessionEntry->protection_fields_reset_timer); + } + +#if defined (WLAN_FEATURE_VOWIFI_11R) + /* Delete FT related information */ + limFTCleanup(pMac, psessionEntry); +#endif + + if (psessionEntry->pLimStartBssReq != NULL) + { + vos_mem_free( psessionEntry->pLimStartBssReq ); + psessionEntry->pLimStartBssReq = NULL; + } + + if (psessionEntry->pLimJoinReq != NULL) + { + vos_mem_free( psessionEntry->pLimJoinReq ); + psessionEntry->pLimJoinReq = NULL; + } + + if (psessionEntry->pLimReAssocReq != NULL) + { + vos_mem_free( psessionEntry->pLimReAssocReq ); + psessionEntry->pLimReAssocReq = NULL; + } + + if (psessionEntry->pLimMlmJoinReq != NULL) + { + vos_mem_free( psessionEntry->pLimMlmJoinReq ); + psessionEntry->pLimMlmJoinReq = NULL; + } + + if (psessionEntry->dph.dphHashTable.pHashTable != NULL) + { + vos_mem_free(psessionEntry->dph.dphHashTable.pHashTable); + psessionEntry->dph.dphHashTable.pHashTable = NULL; + } + + if (psessionEntry->dph.dphHashTable.pDphNodeArray != NULL) + { + vos_mem_free(psessionEntry->dph.dphHashTable.pDphNodeArray); + psessionEntry->dph.dphHashTable.pDphNodeArray = NULL; + } + + if (psessionEntry->gpLimPeerIdxpool != NULL) + { + vos_mem_free(psessionEntry->gpLimPeerIdxpool); + psessionEntry->gpLimPeerIdxpool = NULL; + } + + if (psessionEntry->beacon != NULL) + { + vos_mem_free( psessionEntry->beacon); + psessionEntry->beacon = NULL; + } + + if (psessionEntry->assocReq != NULL) + { + vos_mem_free( psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + } + + if (psessionEntry->assocRsp != NULL) + { + vos_mem_free( psessionEntry->assocRsp); + psessionEntry->assocRsp = NULL; + } + + + if (psessionEntry->parsedAssocReq != NULL) + { + /* Clean up the individual allocation first */ + for (i=0; i < psessionEntry->dph.dphHashTable.size; i++) + { + if ( psessionEntry->parsedAssocReq[i] != NULL ) + { + if( ((tpSirAssocReq)(psessionEntry->parsedAssocReq[i]))->assocReqFrame ) + { + vos_mem_free(((tpSirAssocReq) + (psessionEntry->parsedAssocReq[i]))->assocReqFrame); + ((tpSirAssocReq)(psessionEntry->parsedAssocReq[i]))->assocReqFrame = NULL; + ((tpSirAssocReq)(psessionEntry->parsedAssocReq[i]))->assocReqFrameLength = 0; + } + vos_mem_free(psessionEntry->parsedAssocReq[i]); + psessionEntry->parsedAssocReq[i] = NULL; + } + } + /* Clean up the whole block */ + vos_mem_free(psessionEntry->parsedAssocReq); + psessionEntry->parsedAssocReq = NULL; + } + if (NULL != psessionEntry->limAssocResponseData) + { + vos_mem_free( psessionEntry->limAssocResponseData); + psessionEntry->limAssocResponseData = NULL; + } + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (NULL != psessionEntry->pLimMlmReassocRetryReq) + { + vos_mem_free( psessionEntry->pLimMlmReassocRetryReq); + psessionEntry->pLimMlmReassocRetryReq = NULL; + } +#endif + + if (NULL != psessionEntry->pLimMlmReassocReq) + { + vos_mem_free( psessionEntry->pLimMlmReassocReq); + psessionEntry->pLimMlmReassocReq = NULL; + } + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + limCleanupEseCtxt(pMac, psessionEntry); +#endif + + /* Initialize PMM Ps Offload Module */ + if(pMac->psOffloadEnabled) + { + if(pmmPsOffloadClose(pMac, psessionEntry) + != eHAL_STATUS_SUCCESS) + { + limLog(pMac, LOGW, + FL("Failed to close ps offload for pe session %x"), + psessionEntry->peSessionId); + } + } + + if (NULL != psessionEntry->pSchProbeRspTemplate) + { + vos_mem_free(psessionEntry->pSchProbeRspTemplate); + psessionEntry->pSchProbeRspTemplate = NULL; + } + + if (NULL != psessionEntry->pSchBeaconFrameBegin) + { + vos_mem_free(psessionEntry->pSchBeaconFrameBegin); + psessionEntry->pSchBeaconFrameBegin = NULL; + } + + if (NULL != psessionEntry->pSchBeaconFrameEnd) + { + vos_mem_free(psessionEntry->pSchBeaconFrameEnd); + psessionEntry->pSchBeaconFrameEnd = NULL; + } + + /* Must free the buffer before peSession invalid */ + if (NULL != psessionEntry->addIeParams.probeRespData_buff) + { + vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); + psessionEntry->addIeParams.probeRespData_buff = NULL; + psessionEntry->addIeParams.probeRespDataLen = 0; + } + if (NULL != psessionEntry->addIeParams.assocRespData_buff) + { + vos_mem_free(psessionEntry->addIeParams.assocRespData_buff); + psessionEntry->addIeParams.assocRespData_buff = NULL; + psessionEntry->addIeParams.assocRespDataLen = 0; + } + if (NULL != psessionEntry->addIeParams.probeRespBCNData_buff) + { + vos_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff); + psessionEntry->addIeParams.probeRespBCNData_buff = NULL; + psessionEntry->addIeParams.probeRespBCNDataLen = 0; + } + +#ifdef WLAN_FEATURE_11W + /* if PMF connection */ + if (psessionEntry->limRmfEnabled) { + vos_timer_destroy(&psessionEntry->pmfComebackTimer); + } +#endif + + psessionEntry->valid = FALSE; + + if (LIM_IS_AP_ROLE(psessionEntry)) + lim_check_and_reset_protection_params(pMac); + + return; +} + + +/*-------------------------------------------------------------------------- + \brief peFindSessionByPeerSta() - looks up the PE session given the Station Address. + + This function returns the session context and the session ID if the session + corresponding to the given station address is found in the PE session table. + + \param pMac - pointer to global adapter context + \param sa - Peer STA Address of the session + \param sessionId -session ID is returned here, if session is found. + + \return tpPESession - pointer to the session context or NULL if session is not found. + + \sa + --------------------------------------------------------------------------*/ + + +tpPESession peFindSessionByPeerSta(tpAniSirGlobal pMac, tANI_U8* sa, tANI_U8* sessionId) +{ + tANI_U8 i; + tpDphHashNode pSta; + tANI_U16 aid; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if( (pMac->lim.gpSession[i].valid)) + { + pSta = dphLookupHashEntry(pMac, sa, &aid, &pMac->lim.gpSession[i].dph.dphHashTable); + if (pSta != NULL) + { + *sessionId = i; + return &pMac->lim.gpSession[i]; + } + } + } + + limLog(pMac, LOG1, FL("Session lookup fails for Peer StaId:")); + limPrintMacAddr(pMac, sa, LOG1); + return NULL; +} + +/** + * pe_get_active_session_count() - function to return active pe session count + * + * @mac_ctx: pointer to global mac structure + * + * returns number of active pe session count + * + * Return: 0 if there are no active sessions else return number of active + * sessions + */ +int pe_get_active_session_count(tpAniSirGlobal mac_ctx) +{ + int i, active_session_count = 0; + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) + if (mac_ctx->lim.gpSession[i].valid) + active_session_count++; + + return active_session_count; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.c new file mode 100644 index 000000000000..d151cdef412f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.c @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file limSessionUtils.c + \brief implementation for lim Session Utility APIs + \author Sunit Bhatia +========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "aniGlobal.h" +#include "limDebug.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "limSessionUtils.h" +#include "limUtils.h" + +/*-------------------------------------------------------------------------- + \brief peGetVhtCapable() - Returns the Vht capable from a valid session. + + This function iterates the session Table and returns the VHT capable from + first valid session if no sessions are valid/present it returns FALSE + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + + \sa + + --------------------------------------------------------------------------*/ +tANI_U8 peGetVhtCapable(tpAniSirGlobal pMac) + +{ +#ifdef WLAN_FEATURE_11AC + tANI_U8 i; + //assumption here is that all the sessions will be on the same channel. + //This function will not work, once we have multiple channel support. + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid) + { + return(pMac->lim.gpSession[i].vhtCapability); + } + } +#endif + return FALSE; +} +/*-------------------------------------------------------------------------- + \brief peGetCurrentChannel() - Returns the channel number for scanning, + from a valid session. + This function iterates the session Table and returns the channel number + from first valid session if no sessions are valid/present it returns zero + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + \sa + --------------------------------------------------------------------------*/ +tANI_U8 peGetCurrentChannel(tpAniSirGlobal pMac) +{ + tANI_U8 i; + //assumption here is that all the sessions will be on the same channel. + //This function will not work, once we have multiple channel support. + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid) + { + return(pMac->lim.gpSession[i].currentOperChannel); + } + } + return(HAL_INVALID_CHANNEL_ID); +} + + +/*-------------------------------------------------------------------------- + + \brief peValidateJoinReq() - validates the Join request . + + This function is called to validate the Join Request for a BT-AMP station. If start BSS session is present + this function returns TRUE else returns FALSE. + PE will force SME to first issue ''START_BSS' request for BTAMP_STA, before sending a JOIN request. + + \param pMac - pointer to global adapter context + \return - return TRUE if start BSS session is present else return FALSE. + + \sa + --------------------------------------------------------------------------*/ + +tANI_U8 peValidateBtJoinRequest(tpAniSirGlobal pMac) +{ + + tANI_U8 i; + for(i =0; i < pMac->lim.maxBssId; i++) + { + if( (pMac->lim.gpSession[i].valid) && + (pMac->lim.gpSession[i].bssType == eSIR_BTAMP_STA_MODE) && + (pMac->lim.gpSession[i].statypeForBss == STA_ENTRY_SELF)) + { + return(TRUE); + } + + } + return(FALSE); + +} + +/*-------------------------------------------------------------------------- + \brief peGetValidPowerSaveSession() - Fetches the valid session for power save + + This function is called to check the valid session for power save, if more + than one session is active , this function it returns NULL. + if there is only one valid "infrastructure" session present in + "link established" state this function returns sessionentry. + For all other cases it returns NULL. + + \param pMac - pointer to global adapter context + \return - return session is address if valid session is present else return NULL. + + \sa + --------------------------------------------------------------------------*/ + + +tpPESession peGetValidPowerSaveSession(tpAniSirGlobal pMac) +{ + tANI_U8 i; + tANI_U8 sessioncount = 0; + tANI_U8 sessionId = 0; + + for(i = 0; i < pMac->lim.maxBssId; i++) + { + if( (pMac->lim.gpSession[i].valid == TRUE)&& + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE)&& + (pMac->lim.gpSession[i].limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE)) { + sessioncount++; + sessionId = i; + + if(sessioncount > 1) + { + return(NULL); + } + } + + } + + if( (pMac->lim.gpSession[sessionId].valid == TRUE)&& + (pMac->lim.gpSession[sessionId].limSystemRole == eLIM_STA_ROLE)&& + (pMac->lim.gpSession[sessionId].limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE)) + + { + return(&pMac->lim.gpSession[sessionId]); + } + return(NULL); + +} +/*-------------------------------------------------------------------------- + \brief peIsAnySessionActive() - checks for the active session presence . + + This function returns TRUE if at least one valid session is present + else it returns FALSE + + \param pMac - pointer to global adapter context + \return - return TRUE if at least one session + is active else return FALSE. + + \sa + --------------------------------------------------------------------------*/ + + +tANI_U8 peIsAnySessionActive(tpAniSirGlobal pMac) +{ + tANI_U8 i; + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + return(TRUE); + } + + } + return(FALSE); + +} + +/*-------------------------------------------------------------------------- + \brief pePrintActiveSession() - print all the active pesession present . + + This function print all the active pesession present + + \param pMac - pointer to global adapter context + + \sa + --------------------------------------------------------------------------*/ + + +void pePrintActiveSession(tpAniSirGlobal pMac) +{ + tANI_U8 i; + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + limLog(pMac, LOGE, FL("Active sessionId: %d BSID: "MAC_ADDRESS_STR + "opmode = %d bssIdx = %d"), i, + MAC_ADDR_ARRAY(pMac->lim.gpSession[i].bssId), + pMac->lim.gpSession[i].operMode, + pMac->lim.gpSession[i].bssIdx); + } + } + return; +} + +/*-------------------------------------------------------------------------- + \brief isLimSessionOffChannel() - Determines if the there is any other off channel + session. + + This function returns TRUE if the session Id passed needs to be on a different + channel than at least one session already active. + + \param pMac - pointer to global adapter context + \param sessionId - session ID of the session to be verified. + + \return tANI_U8 - Boolean value for off-channel operation. + + \sa + --------------------------------------------------------------------------*/ + +tANI_U8 +isLimSessionOffChannel(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tANI_U8 i; + + if(sessionId >= pMac->lim.maxBssId) + { + limLog(pMac, LOGE, FL("Invalid sessionId: %d"), sessionId); + return FALSE; + } + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if( i == sessionId ) + { + //Skip the sessionId that is to be joined. + continue; + } + /* If another session is valid and it is on different channel + it is an off channel operation. */ + if( (pMac->lim.gpSession[i].valid) && + (pMac->lim.gpSession[i].currentOperChannel != + pMac->lim.gpSession[sessionId].currentOperChannel) ) + { + return TRUE; + } + } + + return FALSE; + +} + +/*-------------------------------------------------------------------------- + \brief peGetActiveSessionChannel() - Gets the operating channel of first + valid session. Returns 0 if there is no + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - operating channel. + + \sa + --------------------------------------------------------------------------*/ +void +peGetActiveSessionChannel (tpAniSirGlobal pMac, tANI_U8* resumeChannel, ePhyChanBondState* resumePhyCbState) +{ + tANI_U8 i; + ePhyChanBondState prevPhyCbState = PHY_SINGLE_CHANNEL_CENTERED; + + // Initialize the pointers passed to INVALID values in case we don't find a valid session + *resumeChannel = 0; + *resumePhyCbState = 0; + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid) + { + *resumeChannel = pMac->lim.gpSession[i].currentOperChannel; + *resumePhyCbState = pMac->lim.gpSession[i].htSecondaryChannelOffset; + +#ifdef WLAN_FEATURE_11AC + if ((pMac->lim.gpSession[i].vhtCapability)) + { + /*Get 11ac cbState from 11n cbState*/ + *resumePhyCbState = limGet11ACPhyCBState(pMac, + pMac->lim.gpSession[i].currentOperChannel, + pMac->lim.gpSession[i].htSecondaryChannelOffset, + pMac->lim.gpSession[i].apCenterChan, + &pMac->lim.gpSession[i]); + } +#endif + *resumePhyCbState = (*resumePhyCbState > prevPhyCbState )? *resumePhyCbState : prevPhyCbState; + prevPhyCbState = *resumePhyCbState; + } + } + return; +} + +/*-------------------------------------------------------------------------- + \brief limIsChanSwitchRunning() - Check if channel switch is running on any + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - 1 - if chann switching running. + 0 - if chann switching is not running. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsChanSwitchRunning (tpAniSirGlobal pMac) +{ + tANI_U8 i; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid && + pMac->lim.gpSession[i].gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) + { + return 1; + } + } + return 0; +} +/*-------------------------------------------------------------------------- + \brief limIsInQuietDuration() - Check if channel quieting is running on any + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - 1 - if chann quiet running. + 0 - if chann quiet is not running. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsInQuietDuration (tpAniSirGlobal pMac) +{ + tANI_U8 i; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid && + pMac->lim.gpSession[i].gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) + { + return 1; + } + } + return 0; +} +/*-------------------------------------------------------------------------- + \brief limIsQuietBegin() - Check if channel quieting is beginning on any + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - 1 - if chann quiet running. + 0 - if chann quiet is not running. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsQuietBegin (tpAniSirGlobal pMac) +{ + tANI_U8 i; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid && + pMac->lim.gpSession[i].gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) + { + return 1; + } + } + return 0; +} + +/*-------------------------------------------------------------------------- + \brief limIsInMCC() - Check if Device is in MCC. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - TRUE - if in MCC. + FALSE - NOT in MCC. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsInMCC (tpAniSirGlobal pMac) +{ + tANI_U8 i; + tANI_U8 chan = 0; + + for(i = 0; i < pMac->lim.maxBssId; i++) + { + //if another session is valid and it is on different channel + //it is an off channel operation. + if( (pMac->lim.gpSession[i].valid) ) + { + if( chan == 0 ) + { + chan = pMac->lim.gpSession[i].currentOperChannel; + } + else if( chan != pMac->lim.gpSession[i].currentOperChannel) + { + return TRUE; + } + } + } + return FALSE; +} + +/*-------------------------------------------------------------------------- + \brief peGetCurrentSTAsCount() - Returns total stations associated on + all session. + + \param pMac - pointer to global adapter context + \return - Number of station active on all sessions. + + \sa + --------------------------------------------------------------------------*/ + +tANI_U8 peGetCurrentSTAsCount(tpAniSirGlobal pMac) +{ + tANI_U8 i; + tANI_U8 staCount = 0; + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + staCount += pMac->lim.gpSession[i].gLimNumOfCurrentSTAs; + } + } + return staCount; +} + +#ifdef FEATURE_WLAN_LFR +/*-------------------------------------------------------------------------- + \brief limIsFastRoamEnabled() - Check LFR is enabled or not + + This function returns the TRUE if LFR is enabled + + \param pMac - pointer to global adapter context + \param sessionId - session ID is returned here, if session is found. + + \return int - TRUE if enabled or else FALSE + + \sa + --------------------------------------------------------------------------*/ + +tANI_U8 limIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + if(TRUE == pMac->lim.gpSession[sessionId].valid) + { + if((eSIR_INFRASTRUCTURE_MODE == pMac->lim.gpSession[sessionId].bssType) && + (pMac->lim.gpSession[sessionId].isFastRoamIniFeatureEnabled)) + { + return TRUE; + } + } + + return FALSE; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.h new file mode 100644 index 000000000000..db56cc9b64b9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSessionUtils.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if!defined( __LIM_SESSION_UTILS_H ) +#define __LIM_SESSION_UTILS_H + +/**========================================================================= + + \file limSessionUtils.h + + \brief prototype for lim Session Utility related APIs + + \author Sunit Bhatia + + ========================================================================*/ + + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + + + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------- + Function declarations and documentation + ------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------- + + \brief peGetVhtCapable() - Returns the Vht capable from a valid session. + + This function iterates the session Table and returns the VHT capable from first valid session + if no sessions are valid/present it returns FALSE + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + + \sa + + --------------------------------------------------------------------------*/ +tANI_U8 peGetVhtCapable(tpAniSirGlobal pMac); + + +/*-------------------------------------------------------------------------- + \brief peValidateJoinReq() - validates the Join request . + + This function is called to validate the Join Request for a BT-AMP station. If start BSS session is present + this function returns TRUE else returns FALSE. + + \param pMac - pointer to global adapter context + \return - return TRUE if start BSS session is present else return FALSE. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 peValidateBtJoinRequest(tpAniSirGlobal pMac); + +/* --------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + \brief peGetValidPowerSaveSession() - Fetches the valid session for power save . + + This function is called to check the valid session for power save, if more than one session is active , this function + it returns NULL. + if there is only one valid "infrastructure" session present in + "link stablished" state this function returns sessionentry. + For all other cases it returns NULL. + + \param pMac - pointer to global adapter context + \return - return session is address if valid session is present else return NULL. + + \sa + --------------------------------------------------------------------------*/ + + +tpPESession peGetValidPowerSaveSession(tpAniSirGlobal pMac); + +/* --------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + \brief peIsAnySessionActive() - checks for the active session presence . + + This function returns TRUE if at least one valid session is present else it returns FALSE + + \param pMac - pointer to global adapter context + \return - return TRUE if at least one session is active + else return FALSE. + + \sa + --------------------------------------------------------------------------*/ + +tANI_U8 peIsAnySessionActive(tpAniSirGlobal pMac); + +/* --------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + \brief pePrintActiveSession() - print all the active pesession present . + + This function print all the active pesession present + + \param pMac - pointer to global adapter context + + \sa + --------------------------------------------------------------------------*/ + +void pePrintActiveSession(tpAniSirGlobal pMac); + +/* --------------------------------------------------------------------------*/ + + + +/*-------------------------------------------------------------------------- + \brief isLimSessionOffChannel() - Determines if the session is + off channel. + + This function returns TRUE if the session Id passed needs to be on a different + channel than atleast one session already active. + + \param pMac - pointer to global adapter context + \param sessionId - session ID of the session to be verified. + + \return tANI_U8 - Boolean value for off-channel operation. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +isLimSessionOffChannel(tpAniSirGlobal pMac, tANI_U8 sessionId); +/* --------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + \brief peGetActiveSessionChannel() - Gets the first valid sessions primary and secondary + channel. If not found returns invalid channel ID (=0) + \param pMac - pointer to global adapter context + \param resumeChannel - Primary channel of the first valid session. This is an output argument. + \return resumePhyCbState - Secondary channel of the first valid session. This is an output argument. +--------------------------------------------------------------------------*/ +void +peGetActiveSessionChannel(tpAniSirGlobal pMac, tANI_U8* resumeChannel, ePhyChanBondState* resumePhyCbState); + +/*-------------------------------------------------------------------------- + \brief limIsChanSwitchRunning() - Check if channel switch is running on any + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - 1 - if chann switching running. + 0 - if chann switching is not running. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsChanSwitchRunning (tpAniSirGlobal pMac); + +/*-------------------------------------------------------------------------- + \brief limIsInQuietDuration() - Check if channel quieting is running on any + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - 1 - if chann quiet running. + 0 - if chann quiet is not running. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsInQuietDuration (tpAniSirGlobal pMac); + +/*-------------------------------------------------------------------------- + \brief limIsQuietBegin() - Check if channel quieting is beginning on any + valid session. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - 1 - if chann quiet running. + 0 - if chann quiet is not running. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsQuietBegin (tpAniSirGlobal pMac); +/*-------------------------------------------------------------------------- + \brief limIsInMCC() - Check if Device is in MCC. + + \param pMac - pointer to global adapter context + + \return tANI_U8 - TRUE - if in MCC. + FALSE - NOT in MCC. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsInMCC (tpAniSirGlobal pMac); +/*-------------------------------------------------------------------------- + \brief peGetCurrentSTAsCount() - Returns total stations associated on + all session. + + \param pMac - pointer to global adapter context + \return - Number of station active on all sessions. + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +peGetCurrentSTAsCount(tpAniSirGlobal pMac); + +#ifdef FEATURE_WLAN_LFR +/*-------------------------------------------------------------------------- + \brief limIsFastRoamEnabled() - To check Fast roaming is enabled or not + + \param pMac - pointer to global adapter context + \param sessionId - session id + \return - TRUE or FALSE + + \sa + --------------------------------------------------------------------------*/ +tANI_U8 +limIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U8 sessionId); +#endif + + +#endif //#if !defined( __LIM_SESSION_UTILS_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.c new file mode 100644 index 000000000000..9bace4478822 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.c @@ -0,0 +1,1108 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limSmeReqUtils.cc contains the utility functions + * for processing SME request messages. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * 05/26/10 js WPA handling in (Re)Assoc frames + * + */ + +#include "wniApi.h" +#include "wniCfgSta.h" +#include "cfgApi.h" +#include "sirApi.h" +#include "schApi.h" +#include "utilsApi.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "limSerDesUtils.h" + + + +/** + * limIsRSNieValidInSmeReqMessage() + * + *FUNCTION: + * This function is called to verify if the RSN IE + * received in various SME_REQ messages is valid or not + * + *LOGIC: + * RSN IE validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pRSNie Pointer to received RSN IE + * @return true when RSN IE is valid, false otherwise + */ + +static tANI_U8 +limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) +{ + tANI_U8 startPos = 0; + tANI_U32 privacy, val; + int len; + + if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &privacy) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to retrieve POI from CFG")); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_RSN_ENABLED, + &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to retrieve RSN_ENABLED from CFG")); + } + + if (pRSNie->length && (!privacy || !val)) + { + // Privacy & RSN not enabled in CFG. + /** + * In order to allow mixed mode for Guest access + * allow BSS creation/join with no Privacy capability + * yet advertising WPA IE + */ + PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d"), + pRSNie->length, privacy, val);) + } + + if (pRSNie->length) + { + if ((pRSNie->rsnIEdata[0] != DOT11F_EID_RSN) && + (pRSNie->rsnIEdata[0] != DOT11F_EID_WPA) +#ifdef FEATURE_WLAN_WAPI + && (pRSNie->rsnIEdata[0] != DOT11F_EID_WAPI) +#endif + ) + { + limLog(pMac, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]"), + pRSNie->rsnIEdata[0], DOT11F_EID_RSN, + DOT11F_EID_WPA); + return false; + } + + len = pRSNie->length; + startPos = 0; + while(len > 0) + { + // Check validity of RSN IE + if (pRSNie->rsnIEdata[startPos] == DOT11F_EID_RSN) + { + if((pRSNie->rsnIEdata[startPos+1] > DOT11F_IE_RSN_MAX_LEN) || + (pRSNie->rsnIEdata[startPos+1] < DOT11F_IE_RSN_MIN_LEN)) + { + limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_RSN_MIN_LEN, + DOT11F_IE_RSN_MAX_LEN); + return false; + } + } + else if(pRSNie->rsnIEdata[startPos] == DOT11F_EID_WPA) + { + // Check validity of WPA IE + if (SIR_MAC_MAX_IE_LENGTH > startPos) + { + if (startPos <= (SIR_MAC_MAX_IE_LENGTH - sizeof(tANI_U32))) + val = sirReadU32((tANI_U8 *) &pRSNie->rsnIEdata[startPos + 2]); + if((pRSNie->rsnIEdata[startPos + 1] < DOT11F_IE_WPA_MIN_LEN) || + (pRSNie->rsnIEdata[startPos + 1] > DOT11F_IE_WPA_MAX_LEN) || + (SIR_MAC_WPA_OUI != val)) + { + limLog(pMac, LOGE, + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WPA_MIN_LEN, + DOT11F_IE_WPA_MAX_LEN, val, SIR_MAC_WPA_OUI); + + return false; + } + } + } +#ifdef FEATURE_WLAN_WAPI + else if(pRSNie->rsnIEdata[startPos] == DOT11F_EID_WAPI) + { + if((pRSNie->rsnIEdata[startPos+1] > DOT11F_IE_WAPI_MAX_LEN) || + (pRSNie->rsnIEdata[startPos+1] < DOT11F_IE_WAPI_MIN_LEN)) + { + limLog(pMac, LOGE, + FL("WAPI IE len %d not [%d,%d]"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WAPI_MIN_LEN, + DOT11F_IE_WAPI_MAX_LEN); + + return false; + } + } +#endif + else + { + //we will never be here, simply for completeness + return false; + } + startPos += 2 + pRSNie->rsnIEdata[startPos+1]; //EID + length field + length + len -= startPos; + }//while + + } + + return true; +} /*** end limIsRSNieValidInSmeReqMessage() ***/ + +/** + * limIsAddieValidInSmeReqMessage() + * + *FUNCTION: + * This function is called to verify if the Add IE + * received in various SME_REQ messages is valid or not + * + *LOGIC: + * Add IE validity checks are performed on only length + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pWSCie Pointer to received WSC IE + * @return true when WSC IE is valid, false otherwise + */ + +static tANI_U8 +limIsAddieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirAddie pAddie) +{ + int left = pAddie->length; + tANI_U8 *ptr = pAddie->addIEdata; + tANI_U8 elem_id, elem_len; + + if (left == 0) + return true; + + while(left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) + { + limLog( pMac, LOGE, + FL("****Invalid Add IEs eid = %d elem_len=%d left=%d*****"), + elem_id,elem_len,left); + return false; + } + + left -= elem_len; + ptr += (elem_len + 2); + } + // there shouldn't be any left byte + + + return true; +} /*** end limIsAddieValidInSmeReqMessage() ***/ + +/** + * limSetRSNieWPAiefromSmeStartBSSReqMessage() + * + *FUNCTION: + * This function is called to verify if the RSN IE + * received in various SME_REQ messages is valid or not + * + *LOGIC: + * RSN IE validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pRSNie Pointer to received RSN IE + * @return true when RSN IE is valid, false otherwise + */ + +tANI_U8 +limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, + tpSirRSNie pRSNie, + tpPESession pSessionEntry) +{ + tANI_U8 wpaIndex = 0; + tANI_U32 privacy, val; + + if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &privacy) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to retrieve POI from CFG")); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_RSN_ENABLED, + &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to retrieve RSN_ENABLED from CFG")); + } + + if (pRSNie->length && (!privacy || !val)) + { + // Privacy & RSN not enabled in CFG. + /** + * In order to allow mixed mode for Guest access + * allow BSS creation/join with no Privacy capability + * yet advertising WPA IE + */ + PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d"), + pRSNie->length, privacy, val);) + } + + if (pRSNie->length) + { + if ((pRSNie->rsnIEdata[0] != SIR_MAC_RSN_EID) && + (pRSNie->rsnIEdata[0] != SIR_MAC_WPA_EID)) + { + limLog(pMac, LOGE, FL("RSN/WPA EID %d not [%d || %d]"), + pRSNie->rsnIEdata[0], SIR_MAC_RSN_EID, + SIR_MAC_WPA_EID); + return false; + } + + // Check validity of RSN IE + if ((pRSNie->rsnIEdata[0] == SIR_MAC_RSN_EID) && + (pRSNie->rsnIEdata[1] < SIR_MAC_RSN_IE_MIN_LENGTH)) + { + limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]"), + pRSNie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, + SIR_MAC_RSN_IE_MAX_LENGTH); + return false; + } + + if (pRSNie->length > pRSNie->rsnIEdata[1] + 2) + { + if (pRSNie->rsnIEdata[0] != SIR_MAC_RSN_EID) + { + limLog(pMac, + LOGE, + FL("First byte[%d] in rsnIEdata is not RSN_EID"), + pRSNie->rsnIEdata[1]); + return false; + } + + limLog(pMac, + LOG1, + FL("WPA IE is present along with WPA2 IE")); + wpaIndex = 2 + pRSNie->rsnIEdata[1]; + } + else if ((pRSNie->length == pRSNie->rsnIEdata[1] + 2) && + (pRSNie->rsnIEdata[0] == SIR_MAC_RSN_EID)) + { + limLog(pMac, + LOG1, + FL("Only RSN IE is present")); + dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], + (tANI_U8)pRSNie->length,&pSessionEntry->gStartBssRSNIe); + } + else if ((pRSNie->length == pRSNie->rsnIEdata[1] + 2) && + (pRSNie->rsnIEdata[0] == SIR_MAC_WPA_EID)) + { + limLog(pMac, + LOG1, + FL("Only WPA IE is present")); + + dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6],(tANI_U8)pRSNie->length-4, + &pSessionEntry->gStartBssWPAIe); + } + + // Check validity of WPA IE + if(wpaIndex +6 < SIR_MAC_MAX_IE_LENGTH ) + { + val = sirReadU32((tANI_U8 *) &pRSNie->rsnIEdata[wpaIndex + 2]); + + if ((pRSNie->rsnIEdata[wpaIndex] == SIR_MAC_WPA_EID) && + ((pRSNie->rsnIEdata[wpaIndex + 1] < SIR_MAC_WPA_IE_MIN_LENGTH) || + (SIR_MAC_WPA_OUI != val))) + { + limLog(pMac, LOGE, + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), + pRSNie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, + SIR_MAC_RSN_IE_MAX_LENGTH, val, SIR_MAC_WPA_OUI); + + return false; + } + else + { + /* Both RSN and WPA IEs are present */ + dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], + (tANI_U8)pRSNie->length,&pSessionEntry->gStartBssRSNIe); + + dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[wpaIndex + 6], + pRSNie->rsnIEdata[wpaIndex + 1]-4, + &pSessionEntry->gStartBssWPAIe); + + } + } + else + { + return false; + } + } + + return true; +} /*** end limSetRSNieWPAiefromSmeStartBSSReqMessage() ***/ + + + + +/** + * limIsBssDescrValidInSmeReqMessage() + * + *FUNCTION: + * This function is called to verify if the BSS Descr + * received in various SME_REQ messages is valid or not + * + *LOGIC: + * BSS Description validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pBssDescr Pointer to received Bss Description + * @return true when BSS description is valid, false otherwise + */ + +static tANI_U8 +limIsBssDescrValidInSmeReqMessage(tpAniSirGlobal pMac, + tpSirBssDescription pBssDescr) +{ + tANI_U8 valid = true; + + if (limIsAddrBC(pBssDescr->bssId) || + !pBssDescr->channelId) + { + valid = false; + goto end; + } + +end: + return valid; +} /*** end limIsBssDescrValidInSmeReqMessage() ***/ + + + +/** + * limIsSmeStartReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_START_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMsg - Pointer to received SME_START_BSS_REQ message + * @return true when received SME_START_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeStartReqValid(tpAniSirGlobal pMac, tANI_U32 *pMsg) +{ + tANI_U8 valid = true; + + if (((tpSirSmeStartReq) pMsg)->length != sizeof(tSirSmeStartReq)) + { + /** + * Invalid length in START_REQ message + * Log error. + */ + limLog(pMac, LOGW, + FL("Invalid length %d in eWNI_SME_START_REQ"), + ((tpSirSmeStartReq) pMsg)->length); + + valid = false; + goto end; + } + +end: + return valid; +} /*** end limIsSmeStartReqValid() ***/ + + + +/** + * limIsSmeStartBssReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_START_BSS_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pStartBssReq Pointer to received SME_START_BSS_REQ message + * @return true when received SME_START_BSS_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeStartBssReqValid(tpAniSirGlobal pMac, + tpSirSmeStartBssReq pStartBssReq) +{ + tANI_U8 i = 0; + tANI_U8 valid = true; + + PELOG1(limLog(pMac, LOG1, + FL("Parsed START_BSS_REQ fields are bssType=%s (%d), channelId=%d," + " SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"), + lim_BssTypetoString(pStartBssReq->bssType), + pStartBssReq->bssType, + pStartBssReq->channelId, + pStartBssReq->ssId.length, + pStartBssReq->rsnIE.length, + pStartBssReq->nwType, + pStartBssReq->operationalRateSet.numRates);) + + switch (pStartBssReq->bssType) + { + case eSIR_INFRASTRUCTURE_MODE: + /** + * Should not have received start BSS req with bssType + * Infrastructure on STA. + * Log error. + */ + limLog(pMac, LOGE, + FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"), + pStartBssReq->bssType); + valid = false; + goto end; + break; + + case eSIR_IBSS_MODE: + break; + + /* Added for BT AMP support */ + case eSIR_BTAMP_STA_MODE: + break; + + /* Added for BT AMP support */ + case eSIR_BTAMP_AP_MODE: + break; + + /* Added for SoftAP support */ + case eSIR_INFRA_AP_MODE: + break; + + default: + /** + * Should not have received start BSS req with bssType + * other than Infrastructure/IBSS. + * Log error + */ + limLog(pMac, LOGW, + FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"), + pStartBssReq->bssType); + + valid = false; + goto end; + } + + /* This below code is client specific code. TODO */ + if (pStartBssReq->bssType == eSIR_IBSS_MODE) + { + if (!pStartBssReq->ssId.length || + (pStartBssReq->ssId.length > SIR_MAC_MAX_SSID_LENGTH)) + { + // Invalid length for SSID. + // Reject START_BSS_REQ + limLog(pMac, LOGW, + FL("Invalid SSID length in eWNI_SME_START_BSS_REQ")); + + valid = false; + goto end; + } + } + + + if (!limIsRSNieValidInSmeReqMessage(pMac, &pStartBssReq->rsnIE)) + { + valid = false; + goto end; + } + + if (pStartBssReq->nwType != eSIR_11A_NW_TYPE && + pStartBssReq->nwType != eSIR_11B_NW_TYPE && + pStartBssReq->nwType != eSIR_11G_NW_TYPE) + { + valid = false; + goto end; + } + + if (pStartBssReq->nwType == eSIR_11A_NW_TYPE) + { + for (i = 0; i < pStartBssReq->operationalRateSet.numRates; i++) + if (!sirIsArate(pStartBssReq->operationalRateSet.rate[i] & 0x7F)) + { + // Invalid Operational rates + // Reject START_BSS_REQ + limLog(pMac, LOGW, + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, + pStartBssReq->operationalRateSet.rate, + pStartBssReq->operationalRateSet.numRates); + + valid = false; + goto end; + } + } + /* Check if all the rates in the operational rate set are legal 11G rates */ + else if (pStartBssReq->nwType == eSIR_11G_NW_TYPE) + { + for (i = 0; i < pStartBssReq->operationalRateSet.numRates; i++) + if (!sirIsGrate(pStartBssReq->operationalRateSet.rate[i] & 0x7F)) + { + // Invalid Operational rates + // Reject START_BSS_REQ + limLog(pMac, LOGW, + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, + pStartBssReq->operationalRateSet.rate, + pStartBssReq->operationalRateSet.numRates); + + valid = false; + goto end; + } + } + else + { + for (i = 0; i < pStartBssReq->operationalRateSet.numRates; i++) + if (!sirIsBrate(pStartBssReq->operationalRateSet.rate[i] & 0x7F)) + { + // Invalid Operational rates + // Reject START_BSS_REQ + limLog(pMac, LOGW, + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); + sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, + pStartBssReq->operationalRateSet.rate, + pStartBssReq->operationalRateSet.numRates); + + valid = false; + goto end; + } + } + +end: + return valid; +} /*** end limIsSmeStartBssReqValid() ***/ + + + +/** + * limIsSmeJoinReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_JOIN_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pJoinReq Pointer to received SME_JOIN_REQ message + * @return true when received SME_JOIN_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) +{ + tANI_U8 valid = true; + + + if (!limIsRSNieValidInSmeReqMessage(pMac, &pJoinReq->rsnIE)) + { + limLog(pMac, LOGE, + FL("received SME_JOIN_REQ with invalid RSNIE")); + valid = false; + goto end; + } + + if (!limIsAddieValidInSmeReqMessage(pMac, &pJoinReq->addIEScan)) + { + limLog(pMac, LOGE, + FL("received SME_JOIN_REQ with invalid additional IE for scan")); + valid = false; + goto end; + } + + if (!limIsAddieValidInSmeReqMessage(pMac, &pJoinReq->addIEAssoc)) + { + limLog(pMac, LOGE, + FL("received SME_JOIN_REQ with invalid additional IE for assoc")); + valid = false; + goto end; + } + + + if (!limIsBssDescrValidInSmeReqMessage(pMac, + &pJoinReq->bssDescription)) + { + /// Received eWNI_SME_JOIN_REQ with invalid BSS Info + // Log the event + limLog(pMac, LOGE, + FL("received SME_JOIN_REQ with invalid bssInfo")); + + valid = false; + goto end; + } + + /* + Reject Join Req if the Self Mac Address and + the Ap's Mac Address is same + */ + if ( vos_mem_compare( (tANI_U8* ) pJoinReq->selfMacAddr, + (tANI_U8 *) pJoinReq->bssDescription.bssId, + (tANI_U8) (sizeof(tSirMacAddr)))) + { + // Log the event + limLog(pMac, LOGE, + FL("received SME_JOIN_REQ with Self Mac and BSSID Same")); + + valid = false; + goto end; + } + +end: + return valid; +} /*** end limIsSmeJoinReqValid() ***/ + + + +/** + * limIsSmeDisassocReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_DISASSOC_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pDisassocReq Pointer to received SME_DISASSOC_REQ message + * @return true When received SME_DISASSOC_REQ is formatted + * correctly + * false otherwise + */ + +tANI_U8 +limIsSmeDisassocReqValid(tpAniSirGlobal pMac, + tpSirSmeDisassocReq pDisassocReq, tpPESession psessionEntry) +{ + if (limIsGroupAddr(pDisassocReq->peerMacAddr) && + !limIsAddrBC(pDisassocReq->peerMacAddr)) + return false; + + + return true; +} /*** end limIsSmeDisassocReqValid() ***/ + + + +/** + * limIsSmeDisassocCnfValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_DISASSOC_CNF message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pDisassocCnf Pointer to received SME_DISASSOC_REQ message + * @return true When received SME_DISASSOC_CNF is formatted + * correctly + * false otherwise + */ + +tANI_U8 +limIsSmeDisassocCnfValid(tpAniSirGlobal pMac, + tpSirSmeDisassocCnf pDisassocCnf, tpPESession psessionEntry) +{ + if (limIsGroupAddr(pDisassocCnf->peerMacAddr)) + return false; + + return true; +} /*** end limIsSmeDisassocCnfValid() ***/ + + + +/** + * limIsSmeDeauthReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_DEAUTH_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pDeauthReq Pointer to received SME_DEAUTH_REQ message + * @return true When received SME_DEAUTH_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeDeauthReqValid(tpAniSirGlobal pMac, tpSirSmeDeauthReq pDeauthReq, tpPESession psessionEntry) +{ + if (limIsGroupAddr(pDeauthReq->peerMacAddr) && + !limIsAddrBC(pDeauthReq->peerMacAddr)) + return false; + + return true; +} /*** end limIsSmeDeauthReqValid() ***/ + + + +/** + * limIsSmeScanReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_SCAN_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pScanReq Pointer to received SME_SCAN_REQ message + * @return true when received SME_SCAN_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeScanReqValid(tpAniSirGlobal pMac, tpSirSmeScanReq pScanReq) +{ + tANI_U8 valid = true; + tANI_U8 i = 0; + + if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) + { + valid = false; + limLog(pMac, LOGE, FL("Number of SSIDs > SIR_SCAN_MAX_NUM_SSID")); + goto end; + } + + for (i = 0; i < pScanReq->numSsid; i++) + { + if (pScanReq->ssId[i].length > SIR_MAC_MAX_SSID_LENGTH) + { + limLog(pMac, LOGE, + FL("Requested SSID length > SIR_MAC_MAX_SSID_LENGTH")); + valid = false; + goto end; + } + } + if ((pScanReq->bssType < 0) || (pScanReq->bssType > eSIR_AUTO_MODE)) + { + limLog(pMac, LOGE, FL("Invalid BSS Type")); + valid = false; + } + if (limIsGroupAddr(pScanReq->bssId) && !limIsAddrBC(pScanReq->bssId)) + { + valid = false; + limLog(pMac, LOGE, FL("BSSID is group addr and is not Broadcast Addr")); + } + if (!(pScanReq->scanType == eSIR_PASSIVE_SCAN || pScanReq->scanType == eSIR_ACTIVE_SCAN)) + { + valid = false; + limLog(pMac, LOGE, FL("Invalid Scan Type")); + } + if (pScanReq->channelList.numChannels > SIR_MAX_NUM_CHANNELS) + { + valid = false; + limLog(pMac, LOGE, FL("Number of Channels > SIR_MAX_NUM_CHANNELS")); + } + + /* + ** check min/max channelTime range + **/ + if (valid) + { + if ((pScanReq->scanType == eSIR_ACTIVE_SCAN) && + (pScanReq->maxChannelTime < pScanReq->minChannelTime)) + { + limLog(pMac, LOGE, FL("Max Channel Time < Min Channel Time")); + valid = false; + goto end; + } + } + +end: + return valid; +} /*** end limIsSmeScanReqValid() ***/ + + +/** + * limIsSmeSetContextReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_SET_CONTEXT_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMsg - Pointer to received SME_SET_CONTEXT_REQ message + * @return true when received SME_SET_CONTEXT_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetContextReq) +{ + tANI_U8 i = 0; + tANI_U8 valid = true; + tpSirKeys pKey = pSetContextReq->keyMaterial.key; + + if ((pSetContextReq->keyMaterial.edType != eSIR_ED_WEP40) && + (pSetContextReq->keyMaterial.edType != eSIR_ED_WEP104) && + (pSetContextReq->keyMaterial.edType != eSIR_ED_NONE) && +#ifdef FEATURE_WLAN_WAPI + (pSetContextReq->keyMaterial.edType != eSIR_ED_WPI) && +#endif + !pSetContextReq->keyMaterial.numKeys) + { + /** + * No keys present in case of TKIP or CCMP + * Log error. + */ + limLog(pMac, LOGW, + FL("No keys present in SME_SETCONTEXT_REQ for edType=%d"), + pSetContextReq->keyMaterial.edType); + + valid = false; + goto end; + } + + if (pSetContextReq->keyMaterial.numKeys && + (pSetContextReq->keyMaterial.edType == eSIR_ED_NONE)) + { + /** + * Keys present in case of no ED policy + * Log error. + */ + limLog(pMac, LOGW, + FL("Keys present in SME_SETCONTEXT_REQ for edType=%d"), + pSetContextReq->keyMaterial.edType); + + valid = false; + goto end; + } + + if (pSetContextReq->keyMaterial.edType >= eSIR_ED_NOT_IMPLEMENTED) + { + /** + * Invalid edType in the message + * Log error. + */ + limLog(pMac, LOGW, + FL("Invalid edType=%d in SME_SETCONTEXT_REQ"), + pSetContextReq->keyMaterial.edType); + + valid = false; + goto end; + } + else if (pSetContextReq->keyMaterial.edType > eSIR_ED_NONE) + { + tANI_U32 poi; + + if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, + &poi) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, + FL("Unable to retrieve POI from CFG")); + } + + if (!poi) + { + /** + * Privacy is not enabled + * In order to allow mixed mode for Guest access + * allow BSS creation/join with no Privacy capability + * yet advertising WPA IE + */ + PELOG1(limLog(pMac, LOG1, + FL("Privacy is not enabled, yet non-None EDtype=%d in SME_SETCONTEXT_REQ"), + pSetContextReq->keyMaterial.edType);) + } + } + + for (i = 0; i < pSetContextReq->keyMaterial.numKeys; i++) + { + if (((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP40) && + (pKey->keyLength != 5)) || + ((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP104) && + (pKey->keyLength != 13)) || + ((pSetContextReq->keyMaterial.edType == eSIR_ED_TKIP) && + (pKey->keyLength != 32)) || +#ifdef FEATURE_WLAN_WAPI + ((pSetContextReq->keyMaterial.edType == eSIR_ED_WPI) && + (pKey->keyLength != 32)) || +#endif + ((pSetContextReq->keyMaterial.edType == eSIR_ED_CCMP) && + (pKey->keyLength != 16))) + { + /** + * Invalid key length for a given ED type + * Log error. + */ + limLog(pMac, LOGW, + FL("Invalid keyLength =%d for edType=%d in SME_SETCONTEXT_REQ"), + pKey->keyLength, pSetContextReq->keyMaterial.edType); + + valid = false; + goto end; + } + pKey++; + } + +end: + return valid; +} /*** end limIsSmeSetContextReqValid() ***/ + + + +/** + * limIsSmeStopBssReqValid() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() upon + * receiving SME_STOP_BSS_REQ message from application. + * + *LOGIC: + * Message validity checks are performed in this function + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMsg - Pointer to received SME_STOP_BSS_REQ message + * @return true when received SME_STOP_BSS_REQ is formatted correctly + * false otherwise + */ + +tANI_U8 +limIsSmeStopBssReqValid(tANI_U32 *pMsg) +{ + tANI_U8 valid = true; + + return valid; +} /*** end limIsSmeStopBssReqValid() ***/ + + +/** + * limGetBssIdFromSmeJoinReqMsg() + * + *FUNCTION: + * This function is called in various places to get BSSID + * from BSS description/Neighbor BSS Info in the SME_JOIN_REQ/ + * SME_REASSOC_REQ message. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pBuf - Pointer to received SME_JOIN/SME_REASSOC_REQ + * message + * @return pBssId - Pointer to BSSID + */ + +tANI_U8* +limGetBssIdFromSmeJoinReqMsg(tANI_U8 *pBuf) +{ + if (!pBuf) + return NULL; + + pBuf += sizeof(tANI_U32); // skip message header + + + pBuf += limGetU16(pBuf) + sizeof(tANI_U16); // skip RSN IE + + pBuf += sizeof(tANI_U16); // skip length of BSS description + + return (pBuf); +} /*** end limGetBssIdFromSmeJoinReqMsg() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.h new file mode 100644 index 000000000000..922d71600b18 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSmeReqUtils.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limSmeReqUtils.h contains the utility definitions + * LIM uses while processing SME request messages. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __LIM_SME_REQ_UTILS_H +#define __LIM_SME_REQ_UTILS_H + +#include "sirApi.h" +#include "limTypes.h" + + +// LIM SME request messages related utility functions +tANI_U8 limIsSmeStartReqValid(tpAniSirGlobal, tANI_U32 *); +tANI_U8 limIsSmeStartBssReqValid(tpAniSirGlobal, tpSirSmeStartBssReq); +tANI_U8 limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal, + tpSirRSNie, + tpPESession); +tANI_U8 limIsSmeScanReqValid(tpAniSirGlobal, tpSirSmeScanReq); +tANI_U8 limIsSmeJoinReqValid(tpAniSirGlobal, tpSirSmeJoinReq); +tANI_U8 limIsSmeDisassocReqValid(tpAniSirGlobal, tpSirSmeDisassocReq, tpPESession); +tANI_U8 limIsSmeDeauthReqValid(tpAniSirGlobal, tpSirSmeDeauthReq, tpPESession); +tANI_U8 limIsSmeSetContextReqValid(tpAniSirGlobal, tpSirSmeSetContextReq); +tANI_U8 limIsSmeStopBssReqValid(tANI_U32 *); +tANI_U8* limGetBssIdFromSmeJoinReqMsg(tANI_U8 *); +tANI_U8 limIsSmeDisassocCnfValid(tpAniSirGlobal, tpSirSmeDisassocCnf, tpPESession); + +#endif /* __LIM_SME_REQ_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.c new file mode 100644 index 000000000000..7c9476973dfc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * limStaHashApi.c: Provides access functions to get/set values of station hash entry fields. + * Author: Sunit Bhatia + * Date: 09/19/2006 + * History:- + * Date Modified by Modification Information + * + * -------------------------------------------------------------------------- + * + */ + +#include "limStaHashApi.h" + + +/** + * limGetStaHashBssidx() + * + *FUNCTION: + * This function is called to Get the Bss Index of the currently associated Station. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param assocId AssocID of the Station. + * @param bssidx pointer to the bss index, which will be returned by the function. + * + * @return success if GET operation is ok, else Failure. + */ + +tSirRetStatus limGetStaHashBssidx(tpAniSirGlobal pMac, tANI_U16 assocId, tANI_U8 *bssidx, tpPESession psessionEntry) +{ + tpDphHashNode pSta = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); + + if (pSta == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("invalid STA %d"), assocId);) + return eSIR_LIM_INVALID_STA; + } + + *bssidx = (tANI_U8)pSta->bssId; + return eSIR_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.h new file mode 100644 index 000000000000..06704a21bb91 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limStaHashApi.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limStaHashApi.h contains the + * function prototypes for accessing station hash entry fields. + * + * Author: Sunit Bhatia + * Date: 09/19/2006 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __LIM_STA_HASH_API_H__ +#define __LIM_STA_HASH_API_H__ + + +#include "aniGlobal.h" +#include "limTypes.h" + +tSirRetStatus limGetStaHashBssidx(tpAniSirGlobal pMac, tANI_U16 assocId, tANI_U8 *bssidx,tpPESession psessionEntry); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c new file mode 100644 index 000000000000..9b1dd118bd6a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c @@ -0,0 +1,2276 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limTimerUtils.cc contains the utility functions + * LIM uses for handling various timers. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "limTypes.h" +#include "limUtils.h" +#include "limAssocUtils.h" +#include "limSecurityUtils.h" +#include "pmmApi.h" + + +// default value 5000 ms for background scan period when it is disabled +#define LIM_BACKGROUND_SCAN_PERIOD_DEFAULT_MS 5000 +// channel Switch Timer in ticks +#define LIM_CHANNEL_SWITCH_TIMER_TICKS 1 +// Lim Quite timer in ticks +#define LIM_QUIET_TIMER_TICKS 100 +// Lim Quite BSS timer interval in ticks +#define LIM_QUIET_BSS_TIMER_TICK 100 +// Lim KeepAlive timer default (3000)ms +#define LIM_KEEPALIVE_TIMER_MS 3000 +// Lim JoinProbeRequest Retry timer default (200)ms +#define LIM_JOIN_PROBE_REQ_TIMER_MS 200 +#define LIM_AUTH_RETRY_TIMER_MS 60 + + +//default beacon interval value used in HB timer interval calculation +#define LIM_HB_TIMER_BEACON_INTERVAL 100 + +/* This timer is a periodic timer which expires at every 1 sec to + convert ACTIVE DFS channel to DFS channels */ +#define ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT 1000 + +/** + * limCreateTimers() + * + *FUNCTION: + * This function is called upon receiving + * 1. SME_START_REQ for STA in ESS role + * 2. SME_START_BSS_REQ for AP role & STA in IBSS role + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * + * @return None + */ + +v_UINT_t +limCreateTimers(tpAniSirGlobal pMac) +{ + tANI_U32 cfgValue, i=0; + tANI_U32 cfgValue1; + + PELOG1(limLog(pMac, LOG1, FL("Creating Timers used by LIM module in Role %d"), pMac->lim.gLimSystemRole);) + + if (wlan_cfgGetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get MinChannelTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, FL("could not retrieve MinChannelTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + // Create MIN/MAX channel timers and activate them later + if (tx_timer_create(&pMac->lim.limTimers.gLimMinChannelTimer, + "MIN CHANNEL TIMEOUT", + limTimerHandler, SIR_LIM_MIN_CHANNEL_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not start min channel timer. + // Log error + limLog(pMac, LOGP, FL("could not create MIN channel timer")); + return TX_TIMER_ERROR; + } + PELOG2(limLog(pMac, LOG2, FL("Created MinChannelTimer"));) + + /* Periodic probe request timer value is half of the Min channel + * timer. Probe request sends periodically till min/max channel + * timer expires + */ + + cfgValue1 = cfgValue/2 ; + if( cfgValue1 >= 1) + { + // Create periodic probe request timer and activate them later + if (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer, + "Periodic Probe Request Timer", + limTimerHandler, SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT, + cfgValue1, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not start Periodic Probe Req timer. + // Log error + limLog(pMac, LOGP, FL("could not create periodic probe timer")); + goto err_timer; + } + } + + + if (wlan_cfgGetInt(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get MAXChannelTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve MAXChannelTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + /* Limiting max number of probe req for each channel scan */ + pMac->lim.maxProbe = (cfgValue/cfgValue1); + + if (tx_timer_create(&pMac->lim.limTimers.gLimMaxChannelTimer, + "MAX CHANNEL TIMEOUT", + limTimerHandler, SIR_LIM_MAX_CHANNEL_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not start max channel timer. + // Log error + limLog(pMac, LOGP, FL("could not create MAX channel timer")); + + goto err_timer; + } + PELOG2(limLog(pMac, LOG2, FL("Created MaxChannelTimer"));) + + if (pMac->lim.gLimSystemRole != eLIM_AP_ROLE) + { + // Create Channel Switch Timer + if (tx_timer_create(&pMac->lim.limTimers.gLimChannelSwitchTimer, + "CHANNEL SWITCH TIMER", + limChannelSwitchTimerHandler, + 0, // expiration_input + LIM_CHANNEL_SWITCH_TIMER_TICKS, // initial_ticks + 0, // reschedule_ticks + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("failed to create Channel Switch timer")); + goto err_timer; + } + + // + // Create Quiet Timer + // This is used on the STA to go and shut-off + // Tx/Rx "after" the specified quiteInterval + // + if (tx_timer_create(&pMac->lim.limTimers.gLimQuietTimer, + "QUIET TIMER", + limQuietTimerHandler, + SIR_LIM_QUIET_TIMEOUT, // expiration_input + LIM_QUIET_TIMER_TICKS, // initial_ticks + 0, // reschedule_ticks + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer")); + goto err_timer; + } + + // + // Create Quiet BSS Timer + // After the specified quiteInterval, determined by + // gLimQuietTimer, this timer, gLimQuietBssTimer, + // trigger and put the STA to sleep for the specified + // gLimQuietDuration + // + if (tx_timer_create(&pMac->lim.limTimers.gLimQuietBssTimer, + "QUIET BSS TIMER", + limQuietBssTimerHandler, + SIR_LIM_QUIET_BSS_TIMEOUT, // expiration_input + LIM_QUIET_BSS_TIMER_TICK, // initial_ticks + 0, // reschedule_ticks + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer")); + goto err_timer; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get JoinFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve JoinFailureTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + // Create Join failure timer and activate it later + if (tx_timer_create(&pMac->lim.limTimers.gLimJoinFailureTimer, + "JOIN FAILURE TIMEOUT", + limTimerHandler, SIR_LIM_JOIN_FAIL_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not create Join failure timer. + // Log error + limLog(pMac, LOGP, FL("could not create Join failure timer")); + + goto err_timer; + } + + //Send unicast probe req frame every 200 ms + if ((tx_timer_create(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer, + "Periodic Join Probe Request Timer", + limTimerHandler, SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT, + SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS), 0, + TX_NO_ACTIVATE)) != TX_SUCCESS) + { + /// Could not create Periodic Join Probe Request timer. + // Log error + limLog(pMac, LOGP, FL("could not create Periodic Join Probe Request timer")); + goto err_timer; + } + //Send Auth frame every 60 ms + if ((tx_timer_create + (&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer, + "Periodic AUTH Timer", + limTimerHandler, SIR_LIM_AUTH_RETRY_TIMEOUT, + SYS_MS_TO_TICKS(LIM_AUTH_RETRY_TIMER_MS), 0, + TX_NO_ACTIVATE)) != TX_SUCCESS) + { + /// Could not create Periodic Join Probe Request timer. + // Log error + limLog(pMac, LOGP, FL("could not create Periodic AUTH Timer timer")); + goto err_timer; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get AssocFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AssocFailureTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + // Create Association failure timer and activate it later + if (tx_timer_create(&pMac->lim.limTimers.gLimAssocFailureTimer, + "ASSOC FAILURE TIMEOUT", + limAssocFailureTimerHandler, LIM_ASSOC, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not create Assoc failure timer. + // Log error + limLog(pMac, LOGP, + FL("could not create Association failure timer")); + + goto err_timer; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve ReassocFailureTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + // Create Association failure timer and activate it later + if (tx_timer_create(&pMac->lim.limTimers.gLimReassocFailureTimer, + "REASSOC FAILURE TIMEOUT", + limAssocFailureTimerHandler, LIM_REASSOC, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not create Reassoc failure timer. + // Log error + limLog(pMac, LOGP, + FL("could not create Reassociation failure timer")); + + goto err_timer; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &cfgValue) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_ADDTS_RSP_TIMEOUT ")); + + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + // Create Addts response timer and activate it later + if (tx_timer_create(&pMac->lim.limTimers.gLimAddtsRspTimer, + "ADDTS RSP TIMEOUT", + limAddtsResponseTimerHandler, + SIR_LIM_ADDTS_RSP_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not create Auth failure timer. + // Log error + limLog(pMac, LOGP, FL("could not create Addts response timer")); + + goto err_timer; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get AuthFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AuthFailureTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + // Create Auth failure timer and activate it later + if (tx_timer_create(&pMac->lim.limTimers.gLimAuthFailureTimer, + "AUTH FAILURE TIMEOUT", + limTimerHandler, + SIR_LIM_AUTH_FAIL_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not create Auth failure timer. + // Log error + limLog(pMac, LOGP, FL("could not create Auth failure timer")); + + goto err_timer; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get BEACON_INTERVAL value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve BEACON_INTERVAL value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.gLimHeartBeatTimer, + "Heartbeat TIMEOUT", + limTimerHandler, + SIR_LIM_HEART_BEAT_TIMEOUT, + cfgValue, + 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not start Heartbeat timer. + // Log error + limLog(pMac, LOGP, + FL("call to create heartbeat timer failed")); + goto err_timer; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get PROBE_AFTER_HB_FAILURE + * value from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value")); + } + + // Change timer to reactivate it in future + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.gLimProbeAfterHBTimer, + "Probe after Heartbeat TIMEOUT", + limTimerHandler, + SIR_LIM_PROBE_HB_FAILURE_TIMEOUT, + cfgValue, + 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /* Could not create wt-probe-after-HeartBeat-failure timer. + Log error */ + limLog(pMac, LOGP, + FL("unable to create ProbeAfterHBTimer")); + goto err_timer; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get Background scan period value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Background scan period value")); + } + + /* + * setting period to zero means disabling background scans when associated + * the way we do this is to set a flag indicating this and keeping + * the timer running, since it will be used for PDU leak workarounds + * as well as background scanning during SME idle states + */ + if (cfgValue == 0) + { + cfgValue = LIM_BACKGROUND_SCAN_PERIOD_DEFAULT_MS; + pMac->lim.gLimBackgroundScanDisable = true; + } + else + pMac->lim.gLimBackgroundScanDisable = false; + + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.gLimBackgroundScanTimer, + "Background scan TIMEOUT", + limTimerHandler, + SIR_LIM_CHANNEL_SCAN_TIMEOUT, + cfgValue, + cfgValue, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /// Could not start background scan timer. + // Log error + limLog(pMac, LOGP, + FL("call to create background scan timer failed")); + goto err_timer; + } + } + + + cfgValue = SYS_MS_TO_TICKS(LIM_HASH_MISS_TIMER_MS); + + if (tx_timer_create( + &pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer, + "Disassoc throttle TIMEOUT", + limSendDisassocFrameThresholdHandler, + SIR_LIM_HASH_MISS_THRES_TIMEOUT, + cfgValue, + cfgValue, + TX_AUTO_ACTIVATE) != TX_SUCCESS) + { + /// Could not start Send Disassociate Frame Threshold timer. + // Log error + limLog(pMac, LOGP, + FL("create Disassociate throttle timer failed")); + goto err_timer; + } + PELOG1(limLog(pMac, LOG1, + FL("Created Disassociate throttle timer "));) + + /** + * Create keep alive timer and activate it right away for AP role + */ + + if (wlan_cfgGetInt(pMac, WNI_CFG_KEEPALIVE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get keep alive timeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve keep alive timeout value")); + } + + // A value of zero implies keep alive should be disabled + if (cfgValue == 0) + { + cfgValue = LIM_KEEPALIVE_TIMER_MS; + pMac->sch.keepAlive = 0; + } else + pMac->sch.keepAlive = 1; + + + cfgValue = SYS_MS_TO_TICKS(cfgValue + SYS_TICK_DUR_MS - 1); + + if (tx_timer_create(&pMac->lim.limTimers.gLimKeepaliveTimer, + "KEEPALIVE_TIMEOUT", + limKeepaliveTmerHandler, + 0, + cfgValue, + cfgValue, + (pMac->lim.gLimSystemRole == eLIM_AP_ROLE) ? + TX_AUTO_ACTIVATE : TX_NO_ACTIVATE) + != TX_SUCCESS) + { + /* Cannot create keep alive timer. Log error. */ + limLog(pMac, LOGP, FL("Cannot create keep alive timer.")); + goto err_timer; + } + + /** + * Create all CNF_WAIT Timers upfront + */ + + if (wlan_cfgGetInt(pMac, WNI_CFG_WT_CNF_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get CNF_WAIT timeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve CNF timeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + for (i=0; i < (pMac->lim.maxStation + 1); i++) + { + if (tx_timer_create(&pMac->lim.limTimers.gpLimCnfWaitTimer[i], + "CNF_MISS_TIMEOUT", + limCnfWaitTmerHandler, + (tANI_U32)i, + cfgValue, + 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + // Cannot create timer. Log error. + limLog(pMac, LOGP, FL("Cannot create CNF wait timer.")); + goto err_timer; + } + } + + /* + ** Alloc and init table for the preAuth timer list + ** + **/ + + // get max number of Preauthentication + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_NUM_PRE_AUTH, + &cfgValue) != eSIR_SUCCESS) + { + /* + ** Could not get max preauth value + ** from CFG. Log error. + **/ + limLog(pMac, LOGP, + FL("could not retrieve mac preauth value")); + } + pMac->lim.gLimPreAuthTimerTable.numEntry = cfgValue; + pMac->lim.gLimPreAuthTimerTable.pTable = + vos_mem_malloc(cfgValue * sizeof(tLimPreAuthNode *)); + if (pMac->lim.gLimPreAuthTimerTable.pTable == NULL) { + pMac->lim.gLimPreAuthTimerTable.numEntry = 0; + limLog(pMac, LOGP, FL("AllocateMemory failed!")); + goto err_timer; + } + vos_mem_zero(pMac->lim.gLimPreAuthTimerTable.pTable, + cfgValue * sizeof(tLimPreAuthNode *)); + + for (i = 0; i < cfgValue; i++) { + pMac->lim.gLimPreAuthTimerTable.pTable[i] = + vos_mem_malloc(sizeof(tLimPreAuthNode)); + if (pMac->lim.gLimPreAuthTimerTable.pTable[i] == NULL) { + pMac->lim.gLimPreAuthTimerTable.numEntry = 0; + limLog(pMac, LOGP, FL("AllocateMemory failed!")); + goto err_timer; + } + } + + limInitPreAuthTimerTable(pMac, &pMac->lim.gLimPreAuthTimerTable); + PELOG1(limLog(pMac, LOG1, FL("alloc and init table for preAuth timers"));) + + + { + /** + * Create OLBC cache aging timer + */ + if (wlan_cfgGetInt(pMac, WNI_CFG_OLBC_DETECT_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + { + /** + * Could not get OLBC detect timeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve OLBD detect timeout value")); + } + + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create( + &pMac->lim.limTimers.gLimUpdateOlbcCacheTimer, + "OLBC UPDATE CACHE TIMEOUT", + limUpdateOlbcCacheTimerHandler, + SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT, + cfgValue, + cfgValue, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + // Cannot create update OLBC cache timer + // Log error + limLog(pMac, LOGP, FL("Cannot create update OLBC cache timer")); + goto err_timer; + } + } +#ifdef WLAN_FEATURE_VOWIFI_11R + // In future we need to use the auth timer, cause + // the pre auth session will be introduced before sending + // Auth frame. + // We need to go off channel and come back to home channel + cfgValue = 1000; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.gLimFTPreAuthRspTimer, + "FT PREAUTH RSP TIMEOUT", + limTimerHandler, SIR_LIM_FT_PREAUTH_RSP_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + // Could not create Join failure timer. + // Log error + limLog(pMac, LOGP, FL("could not create Join failure timer")); + goto err_timer; + } +#endif + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + cfgValue = 5000; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.gLimEseTsmTimer, + "ESE TSM Stats TIMEOUT", + limTimerHandler, SIR_LIM_ESE_TSM_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + // Could not create Join failure timer. + // Log error + limLog(pMac, LOGP, FL("could not create Join failure timer")); + goto err_timer; + } +#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ + + cfgValue = 1000; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create(&pMac->lim.limTimers.gLimRemainOnChannelTimer, + "FT PREAUTH RSP TIMEOUT", + limTimerHandler, SIR_LIM_REMAIN_CHN_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + // Could not create Join failure timer. + // Log error + limLog(pMac, LOGP, FL("could not create Join failure timer")); + goto err_timer; + } + + + cfgValue = 1000; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create(&pMac->lim.limTimers.gLimDisassocAckTimer, + "DISASSOC ACK TIMEOUT", + limTimerHandler, SIR_LIM_DISASSOC_ACK_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not DISASSOC ACK TIMEOUT timer")); + goto err_timer; + } + + cfgValue = 1000; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create(&pMac->lim.limTimers.gLimDeauthAckTimer, + "DISASSOC ACK TIMEOUT", + limTimerHandler, SIR_LIM_DEAUTH_ACK_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not create DEAUTH ACK TIMEOUT timer")); + goto err_timer; + } + + cfgValue = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; // (> no of BI* no of TUs per BI * 1TU in msec + p2p start time offset*1 TU in msec = 2*100*1.024 + 5*1.024 = 204.8 + 5.12 = 209.20) + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer, + "Single Shot NOA Insert timeout", + limTimerHandler, SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not create Single Shot NOA Insert Timeout timer")); + goto err_timer; + } + + cfgValue = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer, + "ACTIVE TO PASSIVE CHANNEL", limTimerHandler, + SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGW,FL("could not create timer for passive channel to active channel")); + goto err_timer; + } + + + return TX_SUCCESS; + + err_timer: + tx_timer_delete(&pMac->lim.limTimers.gLimDeauthAckTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimDisassocAckTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimRemainOnChannelTimer); + #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + tx_timer_delete(&pMac->lim.limTimers.gLimEseTsmTimer); + #endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ + tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer); + while(((tANI_S32)--i) >= 0) + { + tx_timer_delete(&pMac->lim.limTimers.gpLimCnfWaitTimer[i]); + } + tx_timer_delete(&pMac->lim.limTimers.gLimKeepaliveTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimBackgroundScanTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimProbeAfterHBTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimHeartBeatTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimAuthFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimAddtsRspTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimReassocFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimAssocFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimJoinFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer); + tx_timer_delete(&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer); + tx_timer_delete(&pMac->lim.limTimers.gLimQuietBssTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimQuietTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimChannelSwitchTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimMaxChannelTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimMinChannelTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + + if(NULL != pMac->lim.gLimPreAuthTimerTable.pTable) + { + for (i = 0; i < pMac->lim.gLimPreAuthTimerTable.numEntry; i++) + vos_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable[i]); + vos_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable); + pMac->lim.gLimPreAuthTimerTable.pTable = NULL; + } + + return TX_TIMER_ERROR; + +} /****** end limCreateTimers() ******/ + + + +/** + * limTimerHandler() + * + *FUNCTION: + * This function is called upon + * 1. MIN_CHANNEL, MAX_CHANNEL timer expiration during scanning + * 2. JOIN_FAILURE timer expiration while joining a BSS + * 3. AUTH_FAILURE timer expiration while authenticating with a peer + * 4. Heartbeat timer expiration on STA + * 5. Background scan timer expiration on STA + * 6. AID release, Pre-auth clean up and Link monitoring timer + * expiration on AP + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param param - Message corresponding to the timer that expired + * + * @return None + */ + +void +limTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tANI_U32 statusCode; + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + // Prepare and post message to LIM Message Queue + + msg.type = (tANI_U16) param; + msg.bodyptr = NULL; + msg.bodyval = 0; + + if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) + limLog(pMac, LOGE, + FL("posting message %X to LIM failed, reason=%d"), + msg.type, statusCode); +} /****** end limTimerHandler() ******/ + + +/** + * limAddtsResponseTimerHandler() + * + *FUNCTION: + * This function is called upon Addts response timer expiration on sta + * + *LOGIC: + * Message SIR_LIM_ADDTS_RSP_TIMEOUT is posted to gSirLimMsgQ + * when this function is executed. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param param - pointer to pre-auth node + * + * @return None + */ + +void +limAddtsResponseTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + // Prepare and post message to LIM Message Queue + + msg.type = SIR_LIM_ADDTS_RSP_TIMEOUT; + msg.bodyval = param; + msg.bodyptr = NULL; + + limPostMsgApi(pMac, &msg); +} /****** end limAuthResponseTimerHandler() ******/ + + +/** + * limAuthResponseTimerHandler() + * + *FUNCTION: + * This function is called upon Auth response timer expiration on AP + * + *LOGIC: + * Message SIR_LIM_AUTH_RSP_TIMEOUT is posted to gSirLimMsgQ + * when this function is executed. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param param - pointer to pre-auth node + * + * @return None + */ + +void +limAuthResponseTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + // Prepare and post message to LIM Message Queue + + msg.type = SIR_LIM_AUTH_RSP_TIMEOUT; + msg.bodyptr = NULL; + msg.bodyval = (tANI_U32)param; + + limPostMsgApi(pMac, &msg); +} /****** end limAuthResponseTimerHandler() ******/ + + + +/** + * limAssocFailureTimerHandler() + * + *FUNCTION: + * This function is called upon Re/Assoc failure timer expiration + * on STA + * + *LOGIC: + * Message SIR_LIM_ASSOC_FAIL_TIMEOUT is posted to gSirLimMsgQ + * when this function is executed. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param param - Indicates whether this is assoc or reassoc + * failure timeout + * @return None + */ + +void +limAssocFailureTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if((LIM_REASSOC == param) && + (NULL != pMac->lim.pSessionEntry) && + (pMac->lim.pSessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE)) + { + limLog(pMac, LOGE, FL("Reassoc timeout happened")); + if(pMac->lim.reAssocRetryAttempt < LIM_MAX_REASSOC_RETRY_LIMIT) + { + limSendRetryReassocReqFrame(pMac, pMac->lim.pSessionEntry->pLimMlmReassocRetryReq, pMac->lim.pSessionEntry); + pMac->lim.reAssocRetryAttempt++; + limLog(pMac, LOGW, FL("Reassoc request retry is sent %d times"), pMac->lim.reAssocRetryAttempt); + return; + } + else + { + limLog(pMac, LOGW, FL("Reassoc request retry MAX(%d) reached"), LIM_MAX_REASSOC_RETRY_LIMIT); + if(NULL != pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) + { + vos_mem_free( pMac->lim.pSessionEntry->pLimMlmReassocRetryReq); + pMac->lim.pSessionEntry->pLimMlmReassocRetryReq = NULL; + } + } + } +#endif + // Prepare and post message to LIM Message Queue + + msg.type = SIR_LIM_ASSOC_FAIL_TIMEOUT; + msg.bodyval = (tANI_U32)param; + msg.bodyptr = NULL; + + limPostMsgApi(pMac, &msg); +} /****** end limAssocFailureTimerHandler() ******/ + + +/** + * limUpdateOlbcCacheTimerHandler() + * + *FUNCTION: + * This function is called upon update olbc cache timer expiration + * on STA + * + *LOGIC: + * Message SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT is posted to gSirLimMsgQ + * when this function is executed. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param + * + * @return None + */ +void +limUpdateOlbcCacheTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + // Prepare and post message to LIM Message Queue + + msg.type = SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT; + msg.bodyval = 0; + msg.bodyptr = NULL; + + limPostMsgApi(pMac, &msg); +} /****** end limUpdateOlbcCacheTimerHandler() ******/ + +/** + * limDeactivateAndChangeTimer() + * + *FUNCTION: + * This function is called to deactivate and change a timer + * for future re-activation + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param timerId - enum of timer to be deactivated and changed + * This enum is defined in limUtils.h file + * + * @return None + */ + +void +limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) +{ + tANI_U32 val=0, val1=0; + tpPESession session_entry; + + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, timerId)); + + switch (timerId) + { + case eLIM_ADDTS_RSP_TIMER: + pMac->lim.gLimAddtsRspTimerCount++; + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimAddtsRspTimer) != TX_SUCCESS) + { + // Could not deactivate AddtsRsp Timer + // Log error + limLog(pMac, LOGP, + FL("Unable to deactivate AddtsRsp timer")); + } + break; + + case eLIM_MIN_CHANNEL_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimMinChannelTimer) + != TX_SUCCESS) + { + // Could not deactivate min channel timer. + // Log error + limLog(pMac, LOGP, + FL("Unable to deactivate min channel timer")); + } + + if (pMac->lim.gpLimMlmScanReq) { + val = + SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTime); + if (pMac->btc.btcScanCompromise) { + if (pMac->lim.gpLimMlmScanReq->minChannelTimeBtc) { + val = SYS_MS_TO_TICKS( + pMac->lim.gpLimMlmScanReq->minChannelTimeBtc); + limLog(pMac, LOG1, + FL("Using BTC Min Active Scan time")); + } else { + limLog(pMac, LOGE, + FL("BTC Active Scan Min Time is Not Set")); + } + } + } else { + limLog(pMac, LOGE, FL("gpLimMlmScanReq is NULL")); + break; + } + + if (tx_timer_change(&pMac->lim.limTimers.gLimMinChannelTimer, + val, 0) != TX_SUCCESS) + { + // Could not change min channel timer. + // Log error + limLog(pMac, LOGP, FL("Unable to change min channel timer")); + } + + break; + + case eLIM_PERIODIC_PROBE_REQ_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer) + != TX_SUCCESS) + { + // Could not deactivate min channel timer. + // Log error + limLog(pMac, LOGP, + FL("Unable to deactivate periodic timer")); + } + + val = SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTime)/2; + if (pMac->btc.btcScanCompromise) + { + if (pMac->lim.gpLimMlmScanReq->minChannelTimeBtc) + { + val = SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTimeBtc)/2; + } + else + { + limLog(pMac, LOGE, FL("BTC Active Scan Min Time is Not Set")); + } + } + if (tx_timer_change(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer, + val, 0) != TX_SUCCESS) + { + // Could not change min channel timer. + // Log error + limLog(pMac, LOGP, FL("Unable to change periodic timer")); + } + + break; + + case eLIM_MAX_CHANNEL_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimMaxChannelTimer) + != TX_SUCCESS) + { + // Could not deactivate max channel timer. + // Log error + limLog(pMac, LOGP, + FL("Unable to deactivate max channel timer")); + } + + // If a background was triggered via Quiet BSS, + // then we need to adjust the MIN and MAX channel + // timer's accordingly to the Quiet duration that + // was specified + if (pMac->lim.gLimSystemRole != eLIM_AP_ROLE) + { + if (pMac->lim.gpLimMlmScanReq) { + val = SYS_MS_TO_TICKS( + pMac->lim.gpLimMlmScanReq->maxChannelTime); + if (pMac->btc.btcScanCompromise) { + if (pMac->lim.gpLimMlmScanReq->maxChannelTimeBtc) { + val = SYS_MS_TO_TICKS( + pMac->lim.gpLimMlmScanReq->maxChannelTimeBtc); + limLog(pMac, LOG1, + FL("Using BTC Max Active Scan time")); + } else { + limLog(pMac, LOGE, + FL("BTC Active Scan Max Time is Not Set")); + } + } + } else { + limLog(pMac, LOGE, FL("gpLimMlmScanReq is NULL")); + break; + } + } + + if (tx_timer_change(&pMac->lim.limTimers.gLimMaxChannelTimer, + val, 0) != TX_SUCCESS) + { + // Could not change max channel timer. + // Log error + limLog(pMac, LOGP, + FL("Unable to change max channel timer")); + } + + break; + + case eLIM_JOIN_FAIL_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimJoinFailureTimer) + != TX_SUCCESS) + { + /** + * Could not deactivate Join Failure + * timer. Log error. + */ + limLog(pMac, LOGP, + FL("Unable to deactivate Join Failure timer")); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get JoinFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve JoinFailureTimeout value")); + } + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gLimJoinFailureTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Join Failure + * timer. Log error. + */ + limLog(pMac, LOGP, + FL("Unable to change Join Failure timer")); + } + + break; + + case eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) + != TX_SUCCESS) + { + // Could not deactivate periodic join req Times. + limLog(pMac, LOGP, + FL("Unable to deactivate periodic join request timer")); + } + + val = SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS); + if (tx_timer_change(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer, + val, 0) != TX_SUCCESS) + { + // Could not change periodic join req times. + // Log error + limLog(pMac, LOGP, FL("Unable to change periodic join request timer")); + } + + break; + + case eLIM_AUTH_FAIL_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimAuthFailureTimer) + != TX_SUCCESS) + { + // Could not deactivate Auth failure timer. + // Log error + limLog(pMac, LOGP, + FL("Unable to deactivate auth failure timer")); + } + + // Change timer to reactivate it in future + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get AuthFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AuthFailureTimeout value")); + } + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gLimAuthFailureTimer, + val, 0) != TX_SUCCESS) + { + // Could not change Authentication failure timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change Auth failure timer")); + } + + break; + + case eLIM_AUTH_RETRY_TIMER: + + if (tx_timer_deactivate + (&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer) + != TX_SUCCESS) { + // Could not deactivate Auth Retry Timer. + limLog(pMac, LOGP, + FL("Unable to deactivate Auth Retry timer")); + } + if ((session_entry = peFindSessionBySessionId(pMac, + pMac->lim.limTimers.g_lim_periodic_auth_retry_timer.sessionId)) + == NULL) { + limLog(pMac, LOGP, + FL("session does not exist for given SessionId : %d"), + pMac->lim.limTimers.g_lim_periodic_auth_retry_timer.sessionId); + break; + } + /* 3/5 of the beacon interval*/ + val = session_entry->beaconParams.beaconInterval * 3/5; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change + (&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer, + val, 0) != TX_SUCCESS) { + // Could not change Auth Retry timer. + // Log error + limLog(pMac, LOGP, FL("Unable to change Auth Retry timer")); + } + break; + + case eLIM_ASSOC_FAIL_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimAssocFailureTimer) != + TX_SUCCESS) + { + // Could not deactivate Association failure timer. + // Log error + limLog(pMac, LOGP, + FL("unable to deactivate Association failure timer")); + } + + // Change timer to reactivate it in future + if (wlan_cfgGetInt(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get AssocFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve AssocFailureTimeout value")); + } + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gLimAssocFailureTimer, + val, 0) != TX_SUCCESS) + { + // Could not change Association failure timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change Assoc failure timer")); + } + + break; + + case eLIM_REASSOC_FAIL_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimReassocFailureTimer) != + TX_SUCCESS) + { + // Could not deactivate Reassociation failure timer. + // Log error + limLog(pMac, LOGP, + FL("unable to deactivate Reassoc failure timer")); + } + + // Change timer to reactivate it in future + if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve ReassocFailureTimeout value")); + } + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gLimReassocFailureTimer, + val, 0) != TX_SUCCESS) + { + // Could not change Reassociation failure timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change Reassociation failure timer")); + } + + break; + + case eLIM_HEART_BEAT_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer) != + TX_SUCCESS) + { + // Could not deactivate Heartbeat timer. + // Log error + limLog(pMac, LOGP, + FL("unable to deactivate Heartbeat timer")); + } + else + { + limLog(pMac, LOGW, FL("Deactivated heartbeat link monitoring")); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, + &val) != eSIR_SUCCESS) + { + /** + * Could not get BEACON_INTERVAL value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve BEACON_INTERVAL value")); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != + eSIR_SUCCESS) + limLog(pMac, LOGP, + FL("could not retrieve heartbeat failure value")); + + // Change timer to reactivate it in future + val = SYS_MS_TO_TICKS(val * val1); + + if (tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, + val, 0) != TX_SUCCESS) + { + // Could not change HeartBeat timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change HeartBeat timer")); + } + else + { + limLog(pMac, LOGW, FL("HeartBeat timer value is changed = %u"), val); + } + break; + + case eLIM_PROBE_AFTER_HB_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != + TX_SUCCESS) + { + // Could not deactivate Heartbeat timer. + // Log error + limLog(pMac, LOGP, + FL("unable to deactivate probeAfterHBTimer")); + } + else + { + limLog(pMac, LOG1, FL("Deactivated probe after hb timer")); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get PROBE_AFTER_HB_FAILURE + * value from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value")); + } + + // Change timer to reactivate it in future + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gLimProbeAfterHBTimer, + val, 0) != TX_SUCCESS) + { + // Could not change HeartBeat timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change ProbeAfterHBTimer")); + } + else + { + limLog(pMac, LOGW, FL("Probe after HB timer value is changed = %u"), val); + } + + break; + + case eLIM_KEEPALIVE_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimKeepaliveTimer) + != TX_SUCCESS) + { + /* Could not deactivate Keep alive timer. Log error */ + limLog(pMac, LOGP, + FL("unable to deactivate KeepaliveTimer timer")); + } + + // Change timer to reactivate it in future + + if (wlan_cfgGetInt(pMac, WNI_CFG_KEEPALIVE_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get keep alive timeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve keep alive timeout value")); + } + if (val == 0) + { + val = 3000; + pMac->sch.keepAlive = 0; + } else + pMac->sch.keepAlive = 1; + + + + val = SYS_MS_TO_TICKS(val + SYS_TICK_DUR_MS - 1); + + if (tx_timer_change(&pMac->lim.limTimers.gLimKeepaliveTimer, + val, val) != TX_SUCCESS) + { + // Could not change KeepaliveTimer timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change KeepaliveTimer timer")); + } + + break; + + case eLIM_BACKGROUND_SCAN_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimBackgroundScanTimer) + != TX_SUCCESS) + { + // Could not deactivate BackgroundScanTimer timer. + // Log error + limLog(pMac, LOGP, + FL("unable to deactivate BackgroundScanTimer timer")); + } + + // Change timer to reactivate it in future + if (wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, + &val) != eSIR_SUCCESS) + { + /** + * Could not get Background scan period value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve Background scan period value")); + } + if (val == 0) + { + val = LIM_BACKGROUND_SCAN_PERIOD_DEFAULT_MS; + pMac->lim.gLimBackgroundScanDisable = true; + } + else + pMac->lim.gLimBackgroundScanDisable = false; + + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gLimBackgroundScanTimer, + val, val) != TX_SUCCESS) + { + // Could not change BackgroundScanTimer timer. + // Log error + limLog(pMac, LOGP, + FL("unable to change BackgroundScanTimer timer")); + } + + break; + + case eLIM_LEARN_DURATION_TIMER: + break; + +#ifdef WLAN_FEATURE_VOWIFI_11R + case eLIM_FT_PREAUTH_RSP_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer) != TX_SUCCESS) + { + /** + ** Could not deactivate Join Failure + ** timer. Log error. + **/ + limLog(pMac, LOGP, FL("Unable to deactivate Preauth response Failure timer")); + return; + } + val = 1000; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change(&pMac->lim.limTimers.gLimFTPreAuthRspTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Join Failure + * timer. Log error. + */ + limLog(pMac, LOGP, FL("Unable to change Join Failure 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) + != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("Unable to deactivate TSM timer")); + } + break; +#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ + case eLIM_REMAIN_CHN_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer) != TX_SUCCESS) + { + /** + ** Could not deactivate Join Failure + ** timer. Log error. + **/ + limLog(pMac, LOGP, FL("Unable to deactivate Remain on Chn timer")); + return; + } + val = 1000; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change(&pMac->lim.limTimers.gLimRemainOnChannelTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Join Failure + * timer. Log error. + */ + limLog(pMac, LOGP, FL("Unable to change timer")); + return; + } + break; + + case eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer) != TX_SUCCESS) + { + /** + ** Could not deactivate Active to passive channel timer. + ** Log error. + **/ + limLog(pMac, LOGP, FL("Unable to Deactivate " + "Active to passive channel timer")); + return; + } + val = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change timer to check scan type for passive channel. + * timer. Log error. + */ + limLog(pMac, LOGP, FL("Unable to change timer")); + return; + } + break; + + case eLIM_DISASSOC_ACK_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimDisassocAckTimer) != TX_SUCCESS) + { + /** + ** Could not deactivate Join Failure + ** timer. Log error. + **/ + limLog(pMac, LOGP, FL("Unable to deactivate Disassoc ack timer")); + return; + } + val = 1000; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change(&pMac->lim.limTimers.gLimDisassocAckTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Join Failure + * timer. Log error. + */ + limLog(pMac, LOGP, FL("Unable to change timer")); + return; + } + break; + + case eLIM_DEAUTH_ACK_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimDeauthAckTimer) != TX_SUCCESS) + { + /** + ** Could not deactivate Join Failure + ** timer. Log error. + **/ + limLog(pMac, LOGP, FL("Unable to deactivate Deauth ack timer")); + return; + } + val = 1000; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change(&pMac->lim.limTimers.gLimDeauthAckTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Join Failure + * timer. Log error. + */ + limLog(pMac, LOGP, FL("Unable to change timer")); + return; + } + break; + + case eLIM_INSERT_SINGLESHOT_NOA_TIMER: + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer) != TX_SUCCESS) + { + /** + ** Could not deactivate SingleShot NOA Insert + ** timer. Log error. + **/ + limLog(pMac, LOGP, FL("Unable to deactivate SingleShot NOA Insert timer")); + return; + } + val = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; + val = SYS_MS_TO_TICKS(val); + if (tx_timer_change(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer, + val, 0) != TX_SUCCESS) + { + /** + * Could not change Single Shot NOA Insert + * timer. Log error. + */ + limLog(pMac, LOGP, FL("Unable to change timer")); + return; + } + break; + + default: + // Invalid timerId. Log error + break; + } +} /****** end limDeactivateAndChangeTimer() ******/ + + + +/**--------------------------------------------------------------- +\fn limHeartBeatDeactivateAndChangeTimer +\brief This function deactivates and changes the heart beat +\ timer, eLIM_HEART_BEAT_TIMER. +\ +\param pMac +\param psessionEntry +\return None +------------------------------------------------------------------*/ +void +limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tANI_U32 val, val1; + + if (NULL == psessionEntry) { + limLog(pMac, LOGE, FL("%s: received session id NULL." + " Heartbeat timer config failed"), __func__); + return; + } + + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + return; +#endif + + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer) != TX_SUCCESS) + limLog(pMac, LOGP, FL("Fail to deactivate HeartBeatTimer ")); + + /* HB Timer sessionisation: In case of 2 or more sessions, the HB interval keeps + changing. to avoid this problem, HeartBeat interval is made constant, by + fixing beacon interval to 100ms immaterial of the beacon interval of the session */ + + //val = psessionEntry->beaconParams.beaconInterval; + val = LIM_HB_TIMER_BEACON_INTERVAL; + + if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_HEART_BEAT_THRESHOLD ")); + + PELOGW(limLog(pMac,LOGW, + FL("HB Timer Int.=100ms * %d, Beacon Int.=%dms,Session Id=%d "), + val1, psessionEntry->beaconParams.beaconInterval, + psessionEntry->peSessionId);) + + /* The HB timer timeout value of 4 seconds (40 beacon intervals) is not + * enough to judge the peer device inactivity when 32 peers are connected. + * Hence increasing the HB timer timeout to + * HBtimeout = (TBTT * num_beacons * num_peers) + */ + if (eSIR_IBSS_MODE == psessionEntry->bssType && + pMac->lim.gLimNumIbssPeers > 0) + { + val1 = val1 * pMac->lim.gLimNumIbssPeers; + } + + // Change timer to reactivate it in future + val = SYS_MS_TO_TICKS(val * val1); + + if (tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, val, 0) != TX_SUCCESS) + limLog(pMac, LOGP, FL("Fail to change HeartBeatTimer")); + +} /****** end limHeartBeatDeactivateAndChangeTimer() ******/ + + +/**--------------------------------------------------------------- +\fn limReactivateHeartBeatTimer +\brief This function s called to deactivate, change and +\ activate a timer. +\ +\param pMac - Pointer to Global MAC structure +\param psessionEntry +\return None +------------------------------------------------------------------*/ +void +limReactivateHeartBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + PELOG3(limLog(pMac, LOG3, FL("Rxed Heartbeat. Count=%d"), psessionEntry->LimRxedBeaconCntDuringHB);) + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + limLog(pMac, LOGW, FL("Active offload feature is enabled, FW takes care of HB monitoring")); + return; + } +#endif + + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); + + /* Only start the heartbeat-timer if the timeout value is non-zero */ + if(pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs > 0) + { + /* + * There is increasing need to limit the apps wakeup due to WLAN + * activity. During HB monitoring, the beacons from peer are sent to + * the host causing the host to wakeup. Hence, offloading the HB + * monitoring to LMAC + */ + if (LIM_IS_IBSS_ROLE(psessionEntry) && + IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE) { + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS) + { + limLog(pMac, LOGP,FL("IBSS HeartBeat Offloaded, Could not deactivate Heartbeat timer")); + } + else + { + limLog(pMac, LOGE, FL("IBSS HeartBeat Offloaded, Deactivated heartbeat link monitoring")); + } + } + else + { + if (tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS) + { + limLog(pMac, LOGP,FL("could not activate Heartbeat timer")); + } + else + { + limLog(pMac, LOGW, FL("Reactivated heartbeat link monitoring")); + } + } + limResetHBPktCount(psessionEntry); + } + +} /****** end limReactivateHeartBeatTimer() ******/ + + +/** + * limActivateHearBeatTimer() + * + * + * @brief: This function is called to activate heartbeat timer + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + * @note staId for eLIM_AUTH_RSP_TIMER is auth Node Index. + * + * @param pMac - Pointer to Global MAC structure + * @param psessionEntry - Session Entry + * + * @return TX_SUCCESS - timer is activated + * errors - fail to start the timer + */ +v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + v_UINT_t status = TX_TIMER_ERROR; + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + return (TX_SUCCESS); +#endif + + if(TX_AIRGO_TMR_SIGNATURE == pMac->lim.limTimers.gLimHeartBeatTimer.tmrSignature) + { + //consider 0 interval a ok case + if( pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs ) + { + if (LIM_IS_IBSS_ROLE(psessionEntry) && + IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE) { + /* HB offload in IBSS mode */ + status = tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer); + if (TX_SUCCESS != status) + { + PELOGE(limLog(pMac, LOGE, + FL("IBSS HB Offload, Could not deactivate HB timer status(%d)"), + status);) + } + else + { + PELOGE(limLog(pMac, LOGE, + FL("%s] IBSS HB Offloaded, Heartbeat timer deactivated"), + __func__);) + } + + } + else + { + status = tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer); + if ( TX_SUCCESS != status ) + { + PELOGE(limLog(pMac, LOGE, + FL("could not activate Heartbeat timer status(%d)"), status);) + } + else + { + PELOGE(limLog(pMac, LOGW, + FL("%s] Activated Heartbeat timer status(%d)"), __func__, status);) + } + } + } + else + { + status = TX_SUCCESS; + } + } + + return (status); +} + + + +/** + * limDeactivateAndChangePerStaIdTimer() + * + * + * @brief: This function is called to deactivate and change a per STA timer + * for future re-activation + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + * @note staId for eLIM_AUTH_RSP_TIMER is auth Node Index. + * + * @param pMac - Pointer to Global MAC structure + * @param timerId - enum of timer to be deactivated and changed + * This enum is defined in limUtils.h file + * @param staId - staId + * + * @return None + */ + +void +limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_U16 staId) +{ + tANI_U32 val; + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, timerId)); + + switch (timerId) + { + case eLIM_CNF_WAIT_TIMER: + + if (tx_timer_deactivate(&pMac->lim.limTimers.gpLimCnfWaitTimer[staId]) + != TX_SUCCESS) + { + limLog(pMac, LOGP, + FL("unable to deactivate CNF wait timer")); + + } + + // Change timer to reactivate it in future + + if (wlan_cfgGetInt(pMac, WNI_CFG_WT_CNF_TIMEOUT, + &val) != eSIR_SUCCESS) + { + /** + * Could not get cnf timeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve cnf timeout value")); + } + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pMac->lim.limTimers.gpLimCnfWaitTimer[staId], + val, val) != TX_SUCCESS) + { + // Could not change cnf timer. + // Log error + limLog(pMac, LOGP, FL("unable to change cnf wait timer")); + } + + break; + + case eLIM_AUTH_RSP_TIMER: + { + tLimPreAuthNode *pAuthNode; + + pAuthNode = limGetPreAuthNodeFromIndex(pMac, &pMac->lim.gLimPreAuthTimerTable, staId); + + if (pAuthNode == NULL) + { + limLog(pMac, LOGP, FL("Invalid Pre Auth Index passed :%d"), staId); + break; + } + + if (tx_timer_deactivate(&pAuthNode->timer) != TX_SUCCESS) + { + // Could not deactivate auth response timer. + // Log error + limLog(pMac, LOGP, FL("unable to deactivate auth response timer")); + } + + // Change timer to reactivate it in future + + if (wlan_cfgGetInt(pMac, WNI_CFG_AUTHENTICATE_RSP_TIMEOUT, &val) != eSIR_SUCCESS) + { + /** + * Could not get auth rsp timeout value + * from CFG. Log error. + */ + limLog(pMac, LOGP, + FL("could not retrieve auth response timeout value")); + } + + val = SYS_MS_TO_TICKS(val); + + if (tx_timer_change(&pAuthNode->timer, val, 0) != TX_SUCCESS) + { + // Could not change auth rsp timer. + // Log error + limLog(pMac, LOGP, FL("unable to change auth rsp timer")); + } + } + break; + + + default: + // Invalid timerId. Log error + break; + + } +} + + +/** + * limActivateCnfTimer() + * + *FUNCTION: + * This function is called to activate a per STA timer + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param StaId - staId + * + * @return None + */ + +void limActivateCnfTimer(tpAniSirGlobal pMac, tANI_U16 staId, tpPESession psessionEntry) +{ + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_CNF_WAIT_TIMER)); + pMac->lim.limTimers.gpLimCnfWaitTimer[staId].sessionId = psessionEntry->peSessionId; + if (tx_timer_activate(&pMac->lim.limTimers.gpLimCnfWaitTimer[staId]) + != TX_SUCCESS) + { + limLog(pMac, LOGP, + FL("could not activate cnf wait timer")); + } +} + +/** + * limActivateAuthRspTimer() + * + *FUNCTION: + * This function is called to activate a per STA timer + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param id - id + * + * @return None + */ + +void limActivateAuthRspTimer(tpAniSirGlobal pMac, tLimPreAuthNode *pAuthNode) +{ + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_AUTH_RESP_TIMER)); + if (tx_timer_activate(&pAuthNode->timer) != TX_SUCCESS) + { + /// Could not activate auth rsp timer. + // Log error + limLog(pMac, LOGP, + FL("could not activate auth rsp timer")); + } +} + + +/** + * limSendDisassocFrameThresholdHandler() + * + *FUNCTION: + * This function reloads the credit to the send disassociate frame bucket + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param + * + * @return None + */ + +void +limSendDisassocFrameThresholdHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tANI_U32 statusCode; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + msg.type = SIR_LIM_HASH_MISS_THRES_TIMEOUT; + msg.bodyval = 0; + msg.bodyptr = NULL; + + if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) + limLog(pMac, LOGE, + FL("posting to LIM failed, reason=%d"), statusCode); + +} + +/** + * limAssocCnfWaitTmerHandler() + * + *FUNCTION: + * This function post a message to send a disassociate frame out. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param + * + * @return None + */ + +void +limCnfWaitTmerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tANI_U32 statusCode; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + msg.type = SIR_LIM_CNF_WAIT_TIMEOUT; + msg.bodyval = (tANI_U32)param; + msg.bodyptr = NULL; + + if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) + limLog(pMac, LOGE, + FL("posting to LIM failed, reason=%d"), statusCode); + +} + +/** + * limKeepaliveTmerHandler() + * + *FUNCTION: + * This function post a message to send a NULL data frame. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * NA + * + * @param + * + * @return None + */ + +void +limKeepaliveTmerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tANI_U32 statusCode; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + msg.type = SIR_LIM_KEEPALIVE_TIMEOUT; + msg.bodyval = (tANI_U32)param; + msg.bodyptr = NULL; + + if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) + limLog(pMac, LOGE, + FL("posting to LIM failed, reason=%d"), statusCode); + +} + +void +limChannelSwitchTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + PELOG1(limLog(pMac, LOG1, + FL("ChannelSwitch Timer expired. Posting msg to LIM "));) + + msg.type = SIR_LIM_CHANNEL_SWITCH_TIMEOUT; + msg.bodyval = (tANI_U32)param; + msg.bodyptr = NULL; + + limPostMsgApi(pMac, &msg); +} + +void +limQuietTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + msg.type = SIR_LIM_QUIET_TIMEOUT; + msg.bodyval = (tANI_U32)param; + msg.bodyptr = NULL; + + PELOG1(limLog(pMac, LOG1, + FL("Post SIR_LIM_QUIET_TIMEOUT msg. "));) + limPostMsgApi(pMac, &msg); +} + +void +limQuietBssTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + msg.type = SIR_LIM_QUIET_BSS_TIMEOUT; + msg.bodyval = (tANI_U32)param; + msg.bodyptr = NULL; + PELOG1(limLog(pMac, LOG1, + FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. "));) + limPostMsgApi(pMac, &msg); +} + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE +/* ACTIVE_MODE_HB_OFFLOAD */ +/** + * limMissedBeaconInActiveMode() + * + *FUNCTION: + * This function handle beacon miss indication from FW + * in Active mode. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param param - Msg Type + * + * @return None + */ +void +limMissedBeaconInActiveMode(void *pMacGlobal, tpPESession psessionEntry) +{ + tANI_U32 statusCode; + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + + // Prepare and post message to LIM Message Queue + if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + msg.type = (tANI_U16) SIR_LIM_HEART_BEAT_TIMEOUT; + msg.bodyptr = psessionEntry; + msg.bodyval = 0; + limLog(pMac, LOGE, + FL("Heartbeat failure from Riva")); + if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) + limLog(pMac, LOGE, + FL("posting message %X to LIM failed, reason=%d"), + msg.type, statusCode); + } +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.h new file mode 100644 index 000000000000..ef833472bf7f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file limTimerUtils.h contains the utility definitions + * LIM uses for timer handling. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __LIM_TIMER_UTILS_H +#define __LIM_TIMER_UTILS_H + +#include "limTypes.h" + + +// Timer related functions +enum +{ + eLIM_MIN_CHANNEL_TIMER, + eLIM_MAX_CHANNEL_TIMER, + eLIM_JOIN_FAIL_TIMER, + eLIM_AUTH_FAIL_TIMER, + eLIM_AUTH_RESP_TIMER, + eLIM_ASSOC_FAIL_TIMER, + eLIM_REASSOC_FAIL_TIMER, + eLIM_PRE_AUTH_CLEANUP_TIMER, + eLIM_HEART_BEAT_TIMER, + eLIM_BACKGROUND_SCAN_TIMER, + eLIM_KEEPALIVE_TIMER, + eLIM_CNF_WAIT_TIMER, + eLIM_AUTH_RSP_TIMER, + eLIM_UPDATE_OLBC_CACHE_TIMER, + eLIM_PROBE_AFTER_HB_TIMER, + eLIM_ADDTS_RSP_TIMER, + eLIM_CHANNEL_SWITCH_TIMER, + eLIM_LEARN_DURATION_TIMER, + eLIM_QUIET_TIMER, + eLIM_QUIET_BSS_TIMER, + eLIM_WPS_OVERLAP_TIMER, +#ifdef WLAN_FEATURE_VOWIFI_11R + eLIM_FT_PREAUTH_RSP_TIMER, +#endif + eLIM_REMAIN_CHN_TIMER, + eLIM_PERIODIC_PROBE_REQ_TIMER, +#ifdef FEATURE_WLAN_ESE + eLIM_TSM_TIMER, +#endif + eLIM_DISASSOC_ACK_TIMER, + eLIM_DEAUTH_ACK_TIMER, + eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER, + eLIM_INSERT_SINGLESHOT_NOA_TIMER, + eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, + eLIM_AUTH_RETRY_TIMER +}; + +#define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT 500 +#define LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE 500 + + +// Timer Handler functions +v_UINT_t limCreateTimers(tpAniSirGlobal); +void limTimerHandler(void *, tANI_U32); +void limAuthResponseTimerHandler(void *, tANI_U32); +void limAssocFailureTimerHandler(void *, tANI_U32); +void limReassocFailureTimerHandler(void *, tANI_U32); + +void limDeactivateAndChangeTimer(tpAniSirGlobal, tANI_U32); +void limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal, tpPESession); +void limReactivateHeartBeatTimer(tpAniSirGlobal, tpPESession); +void limDummyPktExpTimerHandler(void *, tANI_U32); +void limSendDisassocFrameThresholdHandler(void *, tANI_U32); +void limCnfWaitTmerHandler(void *, tANI_U32); +void limKeepaliveTmerHandler(void *, tANI_U32); +void limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal, tANI_U32, tANI_U16); +void limActivateCnfTimer(tpAniSirGlobal, tANI_U16, tpPESession); +void limActivateAuthRspTimer(tpAniSirGlobal, tLimPreAuthNode *); +void limUpdateOlbcCacheTimerHandler(void *, tANI_U32); +void limAddtsResponseTimerHandler(void *, tANI_U32); +void limChannelSwitchTimerHandler(void *, tANI_U32); +void limQuietTimerHandler(void *, tANI_U32); +void limQuietBssTimerHandler(void *, tANI_U32); +void limCBScanIntervalTimerHandler(void *, tANI_U32); +void limCBScanDurationTimerHandler(void *, tANI_U32); +/** + * limActivateHearBeatTimer() + * + * + * @brief: This function is called to activate heartbeat timer + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + * @note staId for eLIM_AUTH_RSP_TIMER is auth Node Index. + * + * @param pMac - Pointer to Global MAC structure + * @param psessionEntry - Pointer to PE session entry + * + * @return TX_SUCCESS - timer is activated + * errors - fail to start the timer + */ +v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry); + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE +void limMissedBeaconInActiveMode(void *pMacGlobal, tpPESession psessionEntry); +#endif +#endif /* __LIM_TIMER_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTrace.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTrace.c new file mode 100644 index 000000000000..a6ea34c37585 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTrace.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file limTrace.c + + \brief implementation for trace related APIs + + \author Sunit Bhatia + + ========================================================================*/ + + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "aniGlobal.h" //for tpAniSirGlobal + +#include "limTrace.h" +#include "limTimerUtils.h" +#include "vos_trace.h" + + +#ifdef LIM_TRACE_RECORD +tANI_U32 gMgmtFrameStats[14]; + +#define LIM_TRACE_MAX_SUBTYPES 14 + + +static tANI_U8* __limTraceGetTimerString( tANI_U16 timerId ) +{ + switch( timerId ) + { + CASE_RETURN_STRING(eLIM_MIN_CHANNEL_TIMER); + CASE_RETURN_STRING(eLIM_MAX_CHANNEL_TIMER); + CASE_RETURN_STRING(eLIM_JOIN_FAIL_TIMER); + CASE_RETURN_STRING(eLIM_AUTH_FAIL_TIMER); + CASE_RETURN_STRING(eLIM_AUTH_RESP_TIMER); + CASE_RETURN_STRING(eLIM_ASSOC_FAIL_TIMER); + CASE_RETURN_STRING(eLIM_REASSOC_FAIL_TIMER); + CASE_RETURN_STRING(eLIM_PRE_AUTH_CLEANUP_TIMER); + CASE_RETURN_STRING(eLIM_HEART_BEAT_TIMER); + CASE_RETURN_STRING(eLIM_BACKGROUND_SCAN_TIMER); + CASE_RETURN_STRING(eLIM_KEEPALIVE_TIMER); + CASE_RETURN_STRING(eLIM_CNF_WAIT_TIMER); + CASE_RETURN_STRING(eLIM_AUTH_RSP_TIMER); + CASE_RETURN_STRING(eLIM_UPDATE_OLBC_CACHE_TIMER); + CASE_RETURN_STRING(eLIM_PROBE_AFTER_HB_TIMER); + CASE_RETURN_STRING(eLIM_ADDTS_RSP_TIMER); + CASE_RETURN_STRING(eLIM_CHANNEL_SWITCH_TIMER); + CASE_RETURN_STRING(eLIM_LEARN_DURATION_TIMER); + CASE_RETURN_STRING(eLIM_QUIET_TIMER); + CASE_RETURN_STRING(eLIM_QUIET_BSS_TIMER); + CASE_RETURN_STRING(eLIM_WPS_OVERLAP_TIMER); +#ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STRING(eLIM_FT_PREAUTH_RSP_TIMER); +#endif + CASE_RETURN_STRING(eLIM_REMAIN_CHN_TIMER); + CASE_RETURN_STRING(eLIM_PERIODIC_PROBE_REQ_TIMER); +#ifdef FEATURE_WLAN_ESE + CASE_RETURN_STRING(eLIM_TSM_TIMER); +#endif + CASE_RETURN_STRING(eLIM_DISASSOC_ACK_TIMER); + CASE_RETURN_STRING(eLIM_DEAUTH_ACK_TIMER); + CASE_RETURN_STRING(eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + CASE_RETURN_STRING(eLIM_INSERT_SINGLESHOT_NOA_TIMER); + CASE_RETURN_STRING(eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE); + CASE_RETURN_STRING(eLIM_AUTH_RETRY_TIMER); + default: + return( "UNKNOWN" ); + break; + } +} + + +static tANI_U8* __limTraceGetMgmtDropReasonString( tANI_U16 dropReason ) +{ + + switch( dropReason ) + { + CASE_RETURN_STRING(eMGMT_DROP_INFRA_BCN_IN_IBSS); + CASE_RETURN_STRING(eMGMT_DROP_INVALID_SIZE); + CASE_RETURN_STRING(eMGMT_DROP_NON_SCAN_MODE_FRAME); + CASE_RETURN_STRING(eMGMT_DROP_NOT_LAST_IBSS_BCN); + CASE_RETURN_STRING(eMGMT_DROP_NO_DROP); + CASE_RETURN_STRING(eMGMT_DROP_SCAN_MODE_FRAME); + + default: + return( "UNKNOWN" ); + break; + } +} + + + +void limTraceInit(tpAniSirGlobal pMac) +{ + vosTraceRegister(VOS_MODULE_ID_PE, (tpvosTraceCb)&limTraceDump); +} + + + + +void limTraceDump(tpAniSirGlobal pMac, tpvosTraceRecord pRecord, tANI_U16 recIndex) +{ + + static char *frameSubtypeStr[LIM_TRACE_MAX_SUBTYPES] = + { + "Association request", + "Association response", + "Reassociation request", + "Reassociation response", + "Probe request", + "Probe response", + NULL, + NULL, + "Beacon", + "ATIM", + "Disassociation", + "Authentication", + "Deauthentication", + "Action" + }; + + + switch (pRecord->code) { + case TRACE_CODE_MLM_STATE: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "MLM State:", limTraceGetMlmStateString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_SME_STATE: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "SME State:", limTraceGetSmeStateString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_TX_MGMT: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "TX Mgmt:", frameSubtypeStr[pRecord->data], pRecord->data); + break; + + case TRACE_CODE_RX_MGMT: + if (LIM_TRACE_MAX_SUBTYPES <= LIM_TRACE_GET_SUBTYPE(pRecord->data)) + { + limLog(pMac, LOG1, "Wrong Subtype - %d", + LIM_TRACE_GET_SUBTYPE(pRecord->data)); + } + else + { + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(%d) SN: %d", + recIndex, pRecord->time, pRecord->session, + "RX Mgmt:", + frameSubtypeStr[LIM_TRACE_GET_SUBTYPE(pRecord->data)], + LIM_TRACE_GET_SUBTYPE(pRecord->data), + LIM_TRACE_GET_SSN(pRecord->data) ); + } + break; + case TRACE_CODE_RX_MGMT_DROP: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(%d)", + recIndex, pRecord->time, pRecord->session, + "Drop RX Mgmt:", + __limTraceGetMgmtDropReasonString((tANI_U16)pRecord->data), + pRecord->data); + break; + + + case TRACE_CODE_RX_MGMT_TSF: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s0x%x(%d)", + recIndex, pRecord->time, pRecord->session, + "RX Mgmt TSF:", " ", pRecord->data, pRecord->data ); + break; + + case TRACE_CODE_TX_COMPLETE: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %d" , + recIndex, pRecord->time, pRecord->session, + "TX Complete", pRecord->data ); + break; + + case TRACE_CODE_TX_SME_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "TX SME Msg:", + macTraceGetSmeMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_RX_SME_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? + "Def/Drp LIM Msg:": "RX Sme Msg:", + macTraceGetSmeMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + + case TRACE_CODE_TX_WDA_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "TX WDA Msg:", + macTraceGetWdaMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + + case TRACE_CODE_RX_WDA_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? + "Def/Drp LIM Msg:": "RX WDA Msg:", + macTraceGetWdaMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + + case TRACE_CODE_TX_LIM_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "TX LIM Msg:", + macTraceGetLimMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_RX_LIM_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? + "Def/Drp LIM Msg:": "RX LIM Msg", + macTraceGetLimMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_TX_CFG_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "TX CFG Msg:", + macTraceGetCfgMsgString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_RX_CFG_MSG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? + "Def/Drp LIM Msg:": "RX CFG Msg:", + macTraceGetCfgMsgString + ((tANI_U16)MAC_TRACE_GET_MSG_ID(pRecord->data)), + pRecord->data ); + break; + + case TRACE_CODE_TIMER_ACTIVATE: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "Timer Actvtd", + __limTraceGetTimerString((tANI_U16)pRecord->data), + pRecord->data ); + break; + case TRACE_CODE_TIMER_DEACTIVATE: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "Timer DeActvtd", + __limTraceGetTimerString((tANI_U16)pRecord->data), + pRecord->data ); + break; + + case TRACE_CODE_INFO_LOG: + limLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "INFORMATION_LOG", + macTraceGetInfoLogString((tANI_U16)pRecord->data), + pRecord->data ); + break; + default : + limLog(pMac, LOG1, "%04d %012llu S%d %-14s(%d) (0x%x)", + recIndex, pRecord->time, pRecord->session, + "Unknown Code", pRecord->code, pRecord->data ); + break; + } +} + + +void macTraceMsgTx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data) +{ + + tANI_U16 msgId = (tANI_U16)MAC_TRACE_GET_MSG_ID(data); + tANI_U8 moduleId = (tANI_U8)MAC_TRACE_GET_MODULE_ID(data); + + switch(moduleId) + { + case SIR_LIM_MODULE_ID: + if(msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + macTrace(pMac, TRACE_CODE_TX_LIM_MSG, session, data); + else + macTrace(pMac, TRACE_CODE_TX_SME_MSG, session, data); + break; + case SIR_WDA_MODULE_ID: + macTrace(pMac, TRACE_CODE_TX_WDA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + macTrace(pMac, TRACE_CODE_TX_CFG_MSG, session, data); + break; + default: + macTrace(pMac, moduleId, session, data); + break; + } +} + + +void macTraceMsgTxNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 session, tANI_U32 data) +{ + tANI_U16 msgId = (tANI_U16)MAC_TRACE_GET_MSG_ID(data); + tANI_U8 moduleId = (tANI_U8)MAC_TRACE_GET_MODULE_ID(data); + + switch(moduleId) + { + case SIR_LIM_MODULE_ID: + if(msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + macTraceNew(pMac, module, TRACE_CODE_TX_LIM_MSG, session, data); + else + macTraceNew(pMac, module, TRACE_CODE_TX_SME_MSG, session, data); + break; + case SIR_WDA_MODULE_ID: + macTraceNew(pMac, module, TRACE_CODE_TX_WDA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + macTraceNew(pMac, module, TRACE_CODE_TX_CFG_MSG, session, data); + break; + default: + macTrace(pMac, moduleId, session, data); + break; + } +} + +/* +* bit31: Rx message defferred or not +* bit 0-15: message ID: +*/ +void macTraceMsgRx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data) +{ + tANI_U16 msgId = (tANI_U16)MAC_TRACE_GET_MSG_ID(data); + tANI_U8 moduleId = (tANI_U8)MAC_TRACE_GET_MODULE_ID(data); + + + switch(moduleId) + { + case SIR_LIM_MODULE_ID: + if(msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + macTrace(pMac, TRACE_CODE_RX_LIM_MSG, session, data); + else + macTrace(pMac, TRACE_CODE_RX_SME_MSG, session, data); + break; + case SIR_WDA_MODULE_ID: + macTrace(pMac, TRACE_CODE_RX_WDA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + macTrace(pMac, TRACE_CODE_RX_CFG_MSG, session, data); + break; + default: + macTrace(pMac, moduleId, session, data); + break; + } +} + + + +/* +* bit31: Rx message defferred or not +* bit 0-15: message ID: +*/ +void macTraceMsgRxNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 session, tANI_U32 data) +{ + tANI_U16 msgId = (tANI_U16)MAC_TRACE_GET_MSG_ID(data); + tANI_U8 moduleId = (tANI_U8)MAC_TRACE_GET_MODULE_ID(data); + + + switch(moduleId) + { + case SIR_LIM_MODULE_ID: + if(msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + macTraceNew(pMac, module, TRACE_CODE_RX_LIM_MSG, session, data); + else + macTraceNew(pMac, module, TRACE_CODE_RX_SME_MSG, session, data); + break; + case SIR_WDA_MODULE_ID: + macTraceNew(pMac, module, TRACE_CODE_RX_WDA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + macTraceNew(pMac, module, TRACE_CODE_RX_CFG_MSG, session, data); + break; + default: + macTrace(pMac, moduleId, session, data); + break; + } +} + + + +tANI_U8* limTraceGetMlmStateString( tANI_U32 mlmState ) +{ + switch( mlmState ) + { + CASE_RETURN_STRING( eLIM_MLM_OFFLINE_STATE); + CASE_RETURN_STRING( eLIM_MLM_IDLE_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_PROBE_RESP_STATE); + CASE_RETURN_STRING( eLIM_MLM_PASSIVE_SCAN_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_JOIN_BEACON_STATE); + CASE_RETURN_STRING( eLIM_MLM_JOINED_STATE); + CASE_RETURN_STRING( eLIM_MLM_BSS_STARTED_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_AUTH_FRAME2_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_AUTH_FRAME3_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_AUTH_FRAME4_STATE); + CASE_RETURN_STRING( eLIM_MLM_AUTH_RSP_TIMEOUT_STATE); + CASE_RETURN_STRING( eLIM_MLM_AUTHENTICATED_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ASSOC_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_REASSOC_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_ASSOCIATED_STATE); + CASE_RETURN_STRING( eLIM_MLM_REASSOCIATED_STATE); + CASE_RETURN_STRING( eLIM_MLM_LINK_ESTABLISHED_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ASSOC_CNF_STATE); + CASE_RETURN_STRING( eLIM_MLM_LEARN_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ADD_BSS_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_DEL_BSS_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ADD_STA_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_DEL_STA_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_SET_BSS_KEY_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_SET_STA_KEY_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_SET_STA_BCASTKEY_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_ADDBA_RSP_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_REMOVE_BSS_KEY_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_REMOVE_STA_KEY_STATE); + CASE_RETURN_STRING( eLIM_MLM_WT_SET_MIMOPS_STATE); + default: + return( "UNKNOWN" ); + break; + } +} + + +tANI_U8* limTraceGetSmeStateString( tANI_U32 smeState ) +{ + switch( smeState ) + { + + CASE_RETURN_STRING(eLIM_SME_OFFLINE_STATE); + CASE_RETURN_STRING(eLIM_SME_IDLE_STATE); + CASE_RETURN_STRING(eLIM_SME_SUSPEND_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_SCAN_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_JOIN_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_AUTH_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_ASSOC_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_REASSOC_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_REASSOC_LINK_FAIL_STATE); + CASE_RETURN_STRING(eLIM_SME_JOIN_FAILURE_STATE); + CASE_RETURN_STRING(eLIM_SME_ASSOCIATED_STATE); + CASE_RETURN_STRING(eLIM_SME_REASSOCIATED_STATE); + CASE_RETURN_STRING(eLIM_SME_LINK_EST_STATE); + CASE_RETURN_STRING(eLIM_SME_LINK_EST_WT_SCAN_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_PRE_AUTH_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_DISASSOC_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_DEAUTH_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_START_BSS_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_STOP_BSS_STATE); + CASE_RETURN_STRING(eLIM_SME_NORMAL_STATE); + CASE_RETURN_STRING(eLIM_SME_CHANNEL_SCAN_STATE); + CASE_RETURN_STRING(eLIM_SME_NORMAL_CHANNEL_SCAN_STATE); + default: + return( "UNKNOWN" ); + break; + } +} + + + + + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h new file mode 100644 index 000000000000..87d7c1604b97 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h @@ -0,0 +1,1085 @@ +/* + * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file limTypes.h contains the definitions used by all + * all LIM modules. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __LIM_TYPES_H +#define __LIM_TYPES_H + +#include "wniApi.h" +#include "sirApi.h" +#include "sirCommon.h" +#include "sirMacProtDef.h" +#include "utilsApi.h" + +#include "limApi.h" +#include "limDebug.h" +#include "limSendSmeRspMessages.h" +#include "sysGlobal.h" +#include "dphGlobal.h" +#include "parserApi.h" + +#define LINK_TEST_DEFER 1 + +#define TRACE_EVENT_CNF_TIMER_DEACT 0x6600 +#define TRACE_EVENT_CNF_TIMER_ACT 0x6601 +#define TRACE_EVENT_AUTH_RSP_TIMER_DEACT 0x6602 +#define TRACE_EVENT_AUTH_RSP_TIMER_ACT 0x6603 + +// MLM message types +#define LIM_MLM_MSG_START 1000 +#define LIM_MLM_SCAN_REQ LIM_MLM_MSG_START +#define LIM_MLM_SCAN_CNF (LIM_MLM_MSG_START + 1) +#define LIM_MLM_START_REQ (LIM_MLM_MSG_START + 2) +#define LIM_MLM_START_CNF (LIM_MLM_MSG_START + 3) +#define LIM_MLM_JOIN_REQ (LIM_MLM_MSG_START + 4) +#define LIM_MLM_JOIN_CNF (LIM_MLM_MSG_START + 5) +#define LIM_MLM_AUTH_REQ (LIM_MLM_MSG_START + 6) +#define LIM_MLM_AUTH_CNF (LIM_MLM_MSG_START + 7) +#define LIM_MLM_AUTH_IND (LIM_MLM_MSG_START + 8) +#define LIM_MLM_ASSOC_REQ (LIM_MLM_MSG_START + 9) +#define LIM_MLM_ASSOC_CNF (LIM_MLM_MSG_START + 10) +#define LIM_MLM_ASSOC_IND (LIM_MLM_MSG_START + 11) +#define LIM_MLM_DISASSOC_REQ (LIM_MLM_MSG_START + 12) +#define LIM_MLM_DISASSOC_CNF (LIM_MLM_MSG_START + 13) +#define LIM_MLM_DISASSOC_IND (LIM_MLM_MSG_START + 14) +#define LIM_MLM_REASSOC_REQ (LIM_MLM_MSG_START + 15) +#define LIM_MLM_REASSOC_CNF (LIM_MLM_MSG_START + 16) +#define LIM_MLM_REASSOC_IND (LIM_MLM_MSG_START + 17) +#define LIM_MLM_DEAUTH_REQ (LIM_MLM_MSG_START + 18) +#define LIM_MLM_DEAUTH_CNF (LIM_MLM_MSG_START + 19) +#define LIM_MLM_DEAUTH_IND (LIM_MLM_MSG_START + 20) +#define LIM_MLM_TSPEC_REQ (LIM_MLM_MSG_START + 21) +#define LIM_MLM_TSPEC_CNF (LIM_MLM_MSG_START + 22) +#define LIM_MLM_TSPEC_IND (LIM_MLM_MSG_START + 23) +#define LIM_MLM_SETKEYS_REQ (LIM_MLM_MSG_START + 24) +#define LIM_MLM_SETKEYS_CNF (LIM_MLM_MSG_START + 25) +#define LIM_MLM_LINK_TEST_STOP_REQ (LIM_MLM_MSG_START + 30) +#define LIM_MLM_PURGE_STA_IND (LIM_MLM_MSG_START + 31) +#define LIM_MLM_ADDBA_REQ (LIM_MLM_MSG_START + 32) +#define LIM_MLM_ADDBA_CNF (LIM_MLM_MSG_START + 33) +#define LIM_MLM_ADDBA_IND (LIM_MLM_MSG_START + 34) +#define LIM_MLM_ADDBA_RSP (LIM_MLM_MSG_START + 35) +#define LIM_MLM_DELBA_REQ (LIM_MLM_MSG_START + 36) +#define LIM_MLM_DELBA_CNF (LIM_MLM_MSG_START + 37) +#define LIM_MLM_DELBA_IND (LIM_MLM_MSG_START + 38) +#define LIM_MLM_REMOVEKEY_REQ (LIM_MLM_MSG_START + 39) +#define LIM_MLM_REMOVEKEY_CNF (LIM_MLM_MSG_START + 40) + +#ifdef FEATURE_OEM_DATA_SUPPORT +#define LIM_MLM_OEM_DATA_REQ (LIM_MLM_MSG_START + 41) +#define LIM_MLM_OEM_DATA_CNF (LIM_MLM_MSG_START + 42) +#endif + +#define LIM_HASH_ADD 0 +#define LIM_HASH_UPDATE 1 + +#define LIM_WEP_IN_FC 1 +#define LIM_NO_WEP_IN_FC 0 + +#define LIM_DECRYPT_ICV_FAIL 1 + +/* Definitions to distinguish between Association/Reassociation */ +#define LIM_ASSOC 0 +#define LIM_REASSOC 1 + +/// Minimum Memory blocks require for different scenario +#define LIM_MIN_MEM_ASSOC 4 + +/// Verifies whether given mac addr matches the CURRENT Bssid +#define IS_CURRENT_BSSID(pMac, addr,psessionEntry) (vos_mem_compare( addr, \ + psessionEntry->bssId, \ + sizeof(psessionEntry->bssId))) +/// Verifies whether given addr matches the REASSOC Bssid +#define IS_REASSOC_BSSID(pMac, addr,psessionEntry) (vos_mem_compare( addr, \ + psessionEntry->limReAssocbssId, \ + sizeof(psessionEntry->limReAssocbssId))) + +#define REQ_TYPE_REGISTRAR (0x2) +#define REQ_TYPE_WLAN_MANAGER_REGISTRAR (0x3) + +#define RESP_TYPE_REGISTRAR (0x2) +#define RESP_TYPE_ENROLLEE_INFO_ONLY (0x0) +#define RESP_TYPE_ENROLLEE_OPEN_8021X (0x1) +#define RESP_TYPE_AP (0x3) +#define LIM_TX_FRAMES_THRESHOLD_ON_CHIP 300 + + +// enums used by LIM are as follows + +enum eLimDisassocTrigger +{ + eLIM_HOST_DISASSOC, + eLIM_PEER_ENTITY_DISASSOC, + eLIM_LINK_MONITORING_DISASSOC, + eLIM_PROMISCUOUS_MODE_DISASSOC, + eLIM_HOST_DEAUTH, + eLIM_PEER_ENTITY_DEAUTH, + eLIM_LINK_MONITORING_DEAUTH, + eLIM_JOIN_FAILURE, + eLIM_REASSOC_REJECT +}; + +/* Reason code to determine the channel change context while sending + * WDA_CHNL_SWITCH_REQ message to HAL + */ +enum eChannelChangeReasonCodes +{ + LIM_SWITCH_CHANNEL_REASSOC, + LIM_SWITCH_CHANNEL_JOIN, + LIM_SWITCH_CHANNEL_OPERATION, // Generic change channel + LIM_SWITCH_CHANNEL_SAP_DFS, // DFS channel change +}; + +typedef struct sLimAuthRspTimeout +{ + tSirMacAddr peerMacAddr; +} tLimAuthRspTimeout; + +typedef struct sLimMlmStartReq +{ + tSirMacSSid ssId; + tSirBssType bssType; + tSirMacAddr bssId; + tSirMacBeaconInterval beaconPeriod; + tANI_U8 dtimPeriod; + tSirMacCfParamSet cfParamSet; + tSirMacChanNum channelNumber; + ePhyChanBondState cbMode; + tANI_U16 atimWindow; + tSirMacRateSet rateSet; + tANI_U8 sessionId; //Added For BT-AMP Support + + // Parameters reqd for new HAL (message) interface + tSirNwType nwType; + tANI_U8 htCapable; + tSirMacHTOperatingMode htOperMode; + tANI_U8 dualCTSProtection; + tANI_U8 txChannelWidthSet; + tANI_U8 ssidHidden; + tANI_U8 wps_state; + tANI_U8 obssProtEnabled; +} tLimMlmStartReq, *tpLimMlmStartReq; + +typedef struct sLimMlmStartCnf +{ + tSirResultCodes resultCode; + tANI_U8 sessionId; +} tLimMlmStartCnf, *tpLimMlmStartCnf; + +typedef struct sLimMlmScanCnf +{ + tSirResultCodes resultCode; + tANI_U16 scanResultLength; + tSirBssDescription bssDescription[1]; + tANI_U8 sessionId; +} tLimMlmScanCnf, *tpLimMlmScanCnf; + +typedef struct sLimScanResult +{ + tANI_U16 numBssDescriptions; + tSirBssDescription bssDescription[1]; +} tLimScanResult; + +typedef struct sLimMlmJoinCnf +{ + tSirResultCodes resultCode; + tANI_U16 protStatusCode; + tANI_U8 sessionId; +} tLimMlmJoinCnf, *tpLimMlmJoinCnf; + +typedef struct sLimMlmAssocReq +{ + tSirMacAddr peerMacAddr; + tANI_U32 assocFailureTimeout; + tANI_U16 capabilityInfo; + tSirMacListenInterval listenInterval; + tANI_U8 sessionId; +} tLimMlmAssocReq, *tpLimMlmAssocReq; + +typedef struct sLimMlmAssocCnf +{ + tSirResultCodes resultCode; //Internal status code. + tANI_U16 protStatusCode; //Protocol Status code. + tANI_U8 sessionId; +} tLimMlmAssocCnf, *tpLimMlmAssocCnf; + +typedef struct sLimMlmAssocInd +{ + tSirMacAddr peerMacAddr; + tANI_U16 aid; + tAniAuthType authType; + tAniSSID ssId; + tSirRSNie rsnIE; + tSirWAPIie wapiIE; + tSirAddie addIE; // additional IE received from the peer, which possibly includes WSC IE and/or P2P IE. + tSirMacCapabilityInfo capabilityInfo; + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; + tANI_U8 sessionId; + + + tAniBool WmmStaInfoPresent; + + // Required for indicating the frames to upper layer + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; + tSirSmeChanInfo chan_info; +} tLimMlmAssocInd, *tpLimMlmAssocInd; + +typedef struct sLimMlmReassocReq +{ + tSirMacAddr peerMacAddr; + tANI_U32 reassocFailureTimeout; + tANI_U16 capabilityInfo; + tSirMacListenInterval listenInterval; + tANI_U8 sessionId; +} tLimMlmReassocReq, *tpLimMlmReassocReq; + +typedef struct sLimMlmReassocCnf +{ + tSirResultCodes resultCode; + tANI_U16 protStatusCode; //Protocol Status code. + tANI_U8 sessionId; +} tLimMlmReassocCnf, *tpLimMlmReassocCnf; + +typedef struct sLimMlmReassocInd +{ + tSirMacAddr peerMacAddr; + tSirMacAddr currentApAddr; + tANI_U16 aid; + tAniAuthType authType; + tAniSSID ssId; + tSirRSNie rsnIE; + tSirWAPIie wapiIE; + tSirAddie addIE; // additional IE received from the peer, which can be WSC IE and/or P2P IE. + tSirMacCapabilityInfo capabilityInfo; + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; + + tAniBool WmmStaInfoPresent; + + // Required for indicating the frames to upper layer + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; +} tLimMlmReassocInd, *tpLimMlmReassocInd; + +typedef struct sLimMlmAuthCnf +{ + tSirMacAddr peerMacAddr; + tAniAuthType authType; + tSirResultCodes resultCode; + tANI_U16 protStatusCode; + tANI_U8 sessionId; +} tLimMlmAuthCnf, *tpLimMlmAuthCnf; + +typedef struct sLimMlmAuthInd +{ + tSirMacAddr peerMacAddr; + tAniAuthType authType; + tANI_U8 sessionId; +} tLimMlmAuthInd, *tpLimMlmAuthInd; + +typedef struct sLimMlmDeauthReq +{ + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; + tANI_U16 deauthTrigger; + tANI_U16 aid; + tANI_U8 sessionId; //Added for BT-AMP SUPPORT + +} tLimMlmDeauthReq, *tpLimMlmDeauthReq; + +typedef struct sLimMlmDeauthCnf +{ + tSirMacAddr peerMacAddr; + tSirResultCodes resultCode; + tANI_U16 deauthTrigger; + tANI_U16 aid; + tANI_U8 sessionId; +} tLimMlmDeauthCnf, *tpLimMLmDeauthCnf; + +typedef struct sLimMlmDeauthInd +{ + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; + tANI_U16 deauthTrigger; + tANI_U16 aid; +} tLimMlmDeauthInd, *tpLimMlmDeauthInd; + +typedef struct sLimMlmDisassocReq +{ + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; + tANI_U16 disassocTrigger; + tANI_U16 aid; + tANI_U8 sessionId; +} tLimMlmDisassocReq, *tpLimMlmDisassocReq; + +typedef struct sLimMlmDisassocCnf +{ + tSirMacAddr peerMacAddr; + tSirResultCodes resultCode; + tANI_U16 disassocTrigger; + tANI_U16 aid; + tANI_U8 sessionId; +} tLimMlmDisassocCnf, *tpLimMlmDisassocCnf; + +typedef struct sLimMlmDisassocInd +{ + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; + tANI_U16 disassocTrigger; + tANI_U16 aid; + tANI_U8 sessionId; +} tLimMlmDisassocInd, *tpLimMlmDisassocInd; + +typedef struct sLimMlmPurgeStaReq +{ + tSirMacAddr peerMacAddr; + tANI_U16 aid; + tANI_U8 sessionId;//Added For BT-AMP Support +} tLimMlmPurgeStaReq, *tpLimMlmPurgeStaReq; + +typedef struct sLimMlmPurgeStaInd +{ + tSirMacAddr peerMacAddr; + tANI_U16 reasonCode; + tANI_U16 purgeTrigger; + tANI_U16 aid; + tANI_U8 sessionId; +} tLimMlmPurgeStaInd, *tpLimMlmPurgeStaInd; + +typedef struct sLimMlmSetKeysCnf +{ + tSirMacAddr peerMacAddr; + tANI_U16 resultCode; + tANI_U16 aid; + tANI_U8 sessionId; +} tLimMlmSetKeysCnf, *tpLimMlmSetKeysCnf; + +typedef struct sLimMlmRemoveKeyReq +{ + tSirMacAddr peerMacAddr; + tANI_U8 sessionId; //Added FOr BT-AMP Support + tAniEdType edType; // Encryption/Decryption type + tANI_U8 wepType; //STATIC / DYNAMIC specifier + tANI_U8 keyId; //Key Id To be removed. + tANI_BOOLEAN unicast; +} tLimMlmRemoveKeyReq, *tpLimMlmRemoveKeyReq; + +typedef struct sLimMlmRemoveKeyCnf +{ + tSirMacAddr peerMacAddr; + tANI_U16 resultCode; + tANI_U8 sessionId; +} tLimMlmRemoveKeyCnf, *tpLimMlmRemoveKeyCnf; + + +typedef struct sLimMlmResetReq +{ + tSirMacAddr macAddr; + tANI_U8 performCleanup; + tANI_U8 sessionId; +} tLimMlmResetReq, *tpLimMlmResetReq; + +typedef struct sLimMlmResetCnf +{ + tSirMacAddr macAddr; + tSirResultCodes resultCode; + tANI_U8 sessionId; +} tLimMlmResetCnf, *tpLimMlmResetCnf; + + +typedef struct sLimMlmLinkTestStopReq +{ + tSirMacAddr peerMacAddr; + tANI_U8 sessionId; +} tLimMlmLinkTestStopReq, *tpLimMlmLinkTestStopReq; + + +// +// Block ACK related MLME data structures +// + +typedef struct sLimMlmAddBAReq +{ + + // ADDBA recipient + tSirMacAddr peerMacAddr; + + // ADDBA Action Frame dialog token + tANI_U8 baDialogToken; + + // ADDBA requested for TID + tANI_U8 baTID; + + // BA policy + // 0 - Delayed BA (Not supported) + // 1 - Immediate BA + tANI_U8 baPolicy; + + // BA buffer size - (0..127) max size MSDU's + tANI_U16 baBufferSize; + + // BA timeout in TU's + // 0 means no timeout will occur + tANI_U16 baTimeout; + + // ADDBA failure timeout in TU's + // Greater than or equal to 1 + tANI_U16 addBAFailureTimeout; + + // BA Starting Sequence Number + tANI_U16 baSSN; + + tANI_U8 sessionId; + +} tLimMlmAddBAReq, *tpLimMlmAddBAReq; + +typedef struct sLimMlmAddBACnf +{ + + // ADDBA recipient + tSirMacAddr peerMacAddr; + + // ADDBA Action Frame dialog token + tANI_U8 baDialogToken; + + // ADDBA requested for TID + tANI_U8 baTID; + + // BA status code + tSirMacStatusCodes addBAResultCode; + + // BA policy + // 0 - Delayed BA (Not supported) + // 1 - Immediate BA + tANI_U8 baPolicy; + + // BA buffer size - (0..127) max size MSDU's + tANI_U16 baBufferSize; + + // BA timeout in TU's + // 0 means no timeout will occur + tANI_U16 baTimeout; + + // ADDBA direction + // 1 - Originator + // 0 - Recipient + tANI_U8 baDirection; + tANI_U8 sessionId; + + +} tLimMlmAddBACnf, *tpLimMlmAddBACnf; + +typedef struct sLimMlmAddBAInd +{ + + // ADDBA recipient + tSirMacAddr peerMacAddr; + + // ADDBA Action Frame dialog token + tANI_U8 baDialogToken; + + // ADDBA requested for TID + tANI_U8 baTID; + + // BA policy + // 0 - Delayed BA (Not supported) + // 1 - Immediate BA + tANI_U8 baPolicy; + + // BA buffer size - (0..127) max size MSDU's + tANI_U16 baBufferSize; + + // BA timeout in TU's + // 0 means no timeout will occur + tANI_U16 baTimeout; + +} tLimMlmAddBAInd, *tpLimMlmAddBAInd; + +typedef struct sLimMlmAddBARsp +{ + + // ADDBA recipient + tSirMacAddr peerMacAddr; + + // ADDBA Action Frame dialog token + tANI_U8 baDialogToken; + + // ADDBA requested for TID + tANI_U8 baTID; + + // BA status code + tSirMacStatusCodes addBAResultCode; + + // BA policy + // 0 - Delayed BA (Not supported) + // 1 - Immediate BA + tANI_U8 baPolicy; + + // BA buffer size - (0..127) max size MSDU's + tANI_U16 baBufferSize; + + // BA timeout in TU's + // 0 means no timeout will occur + tANI_U16 baTimeout; + + //reserved for alignment + tANI_U8 rsvd[2]; + + /* PE session id*/ + tANI_U8 sessionId; + + } tLimMlmAddBARsp, *tpLimMlmAddBARsp; + +// +// NOTE - Overloading DELBA IND and DELBA CNF +// to use the same data structure as DELBA REQ +// as the parameters do not vary too much. +// +typedef struct sLimMlmDelBAReq +{ + + // ADDBA recipient + tSirMacAddr peerMacAddr; + + // DELBA direction + // 1 - Originator + // 0 - Recipient + tANI_U8 baDirection; + + // DELBA requested for TID + tANI_U8 baTID; + + // DELBA reason code + tSirMacReasonCodes delBAReasonCode; + + tANI_U8 sessionId; + +} tLimMlmDelBAReq, *tpLimMlmDelBAReq, tLimMlmDelBAInd, *tpLimMlmDelBAInd, tLimMlmDelBACnf, *tpLimMlmDelBACnf; + +// Function templates + +tANI_BOOLEAN limProcessSmeReqMessages(tpAniSirGlobal, tpSirMsgQ); +void limProcessMlmReqMessages(tpAniSirGlobal, tpSirMsgQ); +void limProcessMlmRspMessages(tpAniSirGlobal, tANI_U32, tANI_U32 *); +void limProcessLmmMessages(tpAniSirGlobal, tANI_U32, tANI_U32 *); +void limProcessSmeDelBssRsp( tpAniSirGlobal , tANI_U32,tpPESession); + +void limGetRandomBssid(tpAniSirGlobal pMac ,tANI_U8 *data); + +/* Function to handle HT and HT IE CFG parameter initializations */ +void handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntry); + +// Function to handle CFG parameter updates +void limHandleCFGparamUpdate(tpAniSirGlobal, tANI_U32); + +void limHandleParamUpdate(tpAniSirGlobal pMac, eUpdateIEsType cfgId); + +// Function to apply CFG parameters before join/reassoc/start BSS +void limApplyConfiguration(tpAniSirGlobal,tpPESession); + +void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry); + + +// Function to Initialize MLM state machine on STA +tSirRetStatus limInitMlm(tpAniSirGlobal); + +/* Function to clean up MLM state machine */ +void limCleanupMlm(tpAniSirGlobal); + +/* Function to clean up LMM state machine */ +void limCleanupLmm(tpAniSirGlobal); + +// Management frame handling functions +void limProcessBeaconFrame(tpAniSirGlobal, tANI_U8 *,tpPESession); +void limProcessBeaconFrameNoSession(tpAniSirGlobal, tANI_U8 *); +void limProcessProbeReqFrame(tpAniSirGlobal, tANI_U8 *, tpPESession); +void limProcessProbeRspFrame(tpAniSirGlobal, tANI_U8 *, tpPESession); +void limProcessProbeRspFrameNoSession(tpAniSirGlobal, tANI_U8 *); +void limProcessProbeReqFrame_multiple_BSS(tpAniSirGlobal, tANI_U8 *,tpPESession); + + +// Process Auth frame when we have a session in progress. +void limProcessAuthFrame(tpAniSirGlobal, tANI_U8 *,tpPESession); +#ifdef WLAN_FEATURE_VOWIFI_11R +tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *, void *body); +#endif + +void limProcessAssocReqFrame(tpAniSirGlobal, tANI_U8 *, tANI_U8, tpPESession); +void limSendMlmAssocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry); + + +void limProcessAssocRspFrame(tpAniSirGlobal, tANI_U8 *, tANI_U8,tpPESession); +void limProcessDisassocFrame(tpAniSirGlobal, tANI_U8 *,tpPESession); +void limProcessDeauthFrame(tpAniSirGlobal, tANI_U8 *,tpPESession); +void limProcessActionFrame(tpAniSirGlobal, tANI_U8 *,tpPESession); +void limProcessActionFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxMetaInfo); + +void limPopulateP2pMacHeader(tpAniSirGlobal, tANI_U8*); +tSirRetStatus limPopulateMacHeader(tpAniSirGlobal, tANI_U8*, tANI_U8, tANI_U8, tSirMacAddr,tSirMacAddr); +tSirRetStatus limSendProbeReqMgmtFrame(tpAniSirGlobal, tSirMacSSid *, tSirMacAddr, tANI_U8, tSirMacAddr, tANI_U32, tANI_U32, tANI_U8 *); +void limSendProbeRspMgmtFrame(tpAniSirGlobal, tSirMacAddr, tpAniSSID, short, tANI_U8, tpPESession, tANI_U8); +void limSendAuthMgmtFrame(tpAniSirGlobal, tSirMacAuthFrameBody *, tSirMacAddr, + tANI_U8, tpPESession , tAniBool); +void limSendAssocReqMgmtFrame(tpAniSirGlobal, tLimMlmAssocReq *,tpPESession); +void limSendReassocReqMgmtFrame(tpAniSirGlobal, tLimMlmReassocReq *,tpPESession); +#ifdef WLAN_FEATURE_VOWIFI_11R +void limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq,tpPESession psessionEntry); +#endif +void limSendDeltsReqActionFrame(tpAniSirGlobal pMac, tSirMacAddr peer, + tANI_U8 wmmTspecPresent, tSirMacTSInfo *pTsinfo, + tSirMacTspecIE *pTspecIe, tpPESession psessionEntry); +void limSendAddtsReqActionFrame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tSirAddtsReqInfo *addts,tpPESession); +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 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 limContinueChannelScan(tpAniSirGlobal); +tSirResultCodes limMlmAddBss(tpAniSirGlobal, tLimMlmStartReq *,tpPESession psessionEntry); + +tSirRetStatus limSendChannelSwitchMgmtFrame(tpAniSirGlobal, tSirMacAddr, tANI_U8, tANI_U8, tANI_U8, tpPESession); +tSirRetStatus lim_send_extended_chan_switch_action_frame(tpAniSirGlobal mac_ctx, + tSirMacAddr peer, uint8_t mode, uint8_t new_op_class, + uint8_t new_channel, uint8_t count, tpPESession session_entry); + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac,tSirMacAddr peer,tANI_U8 nMode, tpPESession psessionEntry ); +tSirRetStatus limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac,tSirMacAddr peer,tANI_U8 nChanWidth, tANI_U8 nNewChannel, tANI_U8 ncbMode, tpPESession psessionEntry ); +#endif + +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus limSendNeighborReportRequestFrame(tpAniSirGlobal, tpSirMacNeighborReportReq, tSirMacAddr, tpPESession); +tSirRetStatus limSendLinkReportActionFrame(tpAniSirGlobal, tpSirMacLinkReport, tSirMacAddr, tpPESession ); +tSirRetStatus limSendRadioMeasureReportActionFrame(tpAniSirGlobal, tANI_U8, tANI_U8, tpSirMacRadioMeasureReport, tSirMacAddr, tpPESession); +#endif + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +void limProcessIappFrame(tpAniSirGlobal, tANI_U8 *,tpPESession); +#endif + +#ifdef FEATURE_WLAN_TDLS +void limInitTdlsData(tpAniSirGlobal, tpPESession); +tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); +tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); +tSirRetStatus limProcesSmeTdlsLinkEstablishReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); +tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); +void limSendSmeTDLSDeleteAllPeerInd(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limSendSmeMgmtTXCompletion(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tANI_U32 txCompleteStatus); +tSirRetStatus limDeleteTDLSPeers(tpAniSirGlobal pMac, tpPESession psessionEntry); +eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, tpPESession); +tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, tANI_U16 reason, tANI_U8 responder, tpPESession psessionEntry, + tANI_U8 *addIe, tANI_U16 addIeLen); +#endif + +// Algorithms & Link Monitoring related functions +tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal); +void limTriggerBackgroundScan(tpAniSirGlobal); +void limAbortBackgroundScan(tpAniSirGlobal); + +/// Function that handles heartbeat failure +void limHandleHeartBeatFailure(tpAniSirGlobal,tpPESession); + +/// Function that triggers link tear down with AP upon HB failure +void limTearDownLinkWithAp(tpAniSirGlobal,tANI_U8, tSirMacReasonCodes); + + +/// Function that sends keep alive message to peer(s) +void limSendKeepAliveToPeer(tpAniSirGlobal); + +/// Function that processes Max retries interrupt from TFP +void limHandleMaxRetriesInterrupt(tANI_U32); + +/// Function that processes messages deferred during Learn mode +void limProcessDeferredMessageQueue(tpAniSirGlobal); + +/// Function that defers the messages received +tANI_U32 limDeferMsg(tpAniSirGlobal, tSirMsgQ *); + +/// Function that sets system into scan mode +void limSetScanMode(tpAniSirGlobal pMac); + +/// Function that Switches the Channel and sets the CB Mode +void limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tPowerdBm maxTxPower, tANI_U8 peSessionId); + +/// Function that completes channel scan +void limCompleteMlmScan(tpAniSirGlobal, tSirResultCodes); + +#ifdef FEATURE_OEM_DATA_SUPPORT +/* Function that sets system into meas mode for oem data req */ +void limSetOemDataReqMode(tpAniSirGlobal pMac, eHalStatus status, tANI_U32* data); +#endif + + +/// Function that sends TPC Request action frame +void limSendTpcRequestFrame(tpAniSirGlobal, tSirMacAddr, tpPESession psessionEntry); + +// Function(s) to handle responses received from HAL +void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ); +void limProcessMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQt,tpPESession psessionEntry); +void limProcessMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ); +void limProcessMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession); +void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry); +void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry); +void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry); +void limProcessMlmSetStaKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ); +void limProcessMlmSetBssKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ); + + + +// Function to process WDA_INIT_SCAN_RSP message +void limProcessInitScanRsp(tpAniSirGlobal, void * ); + +// Function to process WDA_START_SCAN_RSP message +void limProcessStartScanRsp(tpAniSirGlobal, void * ); + +// Function to process WDA_END_SCAN_RSP message +void limProcessEndScanRsp(tpAniSirGlobal, void * ); + +// Function to process WDA_FINISH_SCAN_RSP message +void limProcessFinishScanRsp(tpAniSirGlobal, void * ); + +// Function to process WDA_SWITCH_CHANNEL_RSP message +void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void * ); + +void limSendHalInitScanReq( tpAniSirGlobal, tLimLimHalScanState, tSirLinkTrafficCheck); +void limSendHalStartScanReq( tpAniSirGlobal, tANI_U8, tLimLimHalScanState); +void limSendHalEndScanReq( tpAniSirGlobal, tANI_U8, tLimLimHalScanState); +void limSendHalFinishScanReq( tpAniSirGlobal, tLimLimHalScanState); + +void limContinuePostChannelScan(tpAniSirGlobal pMac); +void limCovertChannelScanType(tpAniSirGlobal pMac,tANI_U8 channelNum, tANI_BOOLEAN passiveToActive); +void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannelList *dfsChannelList); +void limContinueChannelLearn( tpAniSirGlobal ); +//WLAN_SUSPEND_LINK Related +tANI_U8 limIsLinkSuspended(tpAniSirGlobal pMac); +void limSuspendLink(tpAniSirGlobal, tSirLinkTrafficCheck, SUSPEND_RESUME_LINK_CALLBACK, tANI_U32*); +void limResumeLink(tpAniSirGlobal, SUSPEND_RESUME_LINK_CALLBACK, tANI_U32*); +//end WLAN_SUSPEND_LINK Related + +tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, + tpLimMlmAddBAReq pMlmAddBAReq,tpPESession); + +tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, + tpLimMlmAddBARsp pMlmAddBARsp,tpPESession); + +tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, + tpLimMlmDelBAReq pMlmDelBAReq ,tpPESession psessionEntry); + +void limProcessMlmHalAddBARsp( tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ ); + +void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ ); + +void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ); + +void limProcessLearnIntervalTimeout(tpAniSirGlobal pMac); + +#ifdef WLAN_FEATURE_11W +//11w send SA query request action frame +tSirRetStatus limSendSaQueryRequestFrame( tpAniSirGlobal pMac, tANI_U8 *transId, + tSirMacAddr peer, tpPESession psessionEntry ); +//11w SA query request action frame handler +tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, + tANI_U8 *transId, tSirMacAddr peer,tpPESession psessionEntry); +#endif + +// Inline functions + +/** + * limPostSmeMessage() + * + *FUNCTION: + * This function is called by limProcessMlmMessages(). In this + * function MLM sub-module invokes MLM ind/cnf primitives. + * + *LOGIC: + * Initially MLM makes an SME function call to invoke MLM ind/cnf + * primitive. In future this can be enhanced to 'post' messages to SME. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the MLM primitive message type + * @param *pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +static inline void +limPostSmeMessage(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) +{ + tSirMsgQ msg; + + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + + msg.type = (tANI_U16)msgType; + msg.bodyptr = pMsgBuf; + msg.bodyval = 0; + if (msgType > eWNI_SME_MSG_TYPES_BEGIN) + limProcessSmeReqMessages(pMac, &msg); + else + limProcessMlmRspMessages(pMac, msgType, pMsgBuf); +} /*** end limPostSmeMessage() ***/ + +/** + * limPostMlmMessage() + * + *FUNCTION: + * This function is called by limProcessSmeMessages(). In this + * function SME invokes MLME primitives. + * + *PARAMS: + * + *LOGIC: + * Initially SME makes an MLM function call to invoke MLM primitive. + * In future this can be enhanced to 'post' messages to MLM. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param msgType Indicates the MLM primitive message type + * @param *pMsgBuf A pointer to the MLM message buffer + * + * @return None + */ +static inline void +limPostMlmMessage(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) +{ + + tSirMsgQ msg; + if(pMsgBuf == NULL) + { + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); + return; + } + msg.type = (tANI_U16) msgType; + msg.bodyptr = pMsgBuf; + msg.bodyval = 0; + limProcessMlmReqMessages(pMac, &msg); +} /*** end limPostMlmMessage() ***/ + + + +/** + * limGetCurrentScanChannel() + * + *FUNCTION: + * This function is called in various places to get current channel + * number being scanned. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @return Channel number + */ +static inline tANI_U8 +limGetCurrentScanChannel(tpAniSirGlobal pMac) +{ + tANI_U8 *pChanNum = pMac->lim.gpLimMlmScanReq->channelList.channelNumber; + + return (*(pChanNum + pMac->lim.gLimCurrentScanChannelId)); +} /*** end limGetCurrentScanChannel() ***/ + + + +/** + * limGetIElenFromBssDescription() + * + *FUNCTION: + * This function is called in various places to get IE length + * from tSirBssDescription structure + * number being scanned. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pBssDescr + * @return Total IE length + */ + +static inline tANI_U16 +limGetIElenFromBssDescription(tpSirBssDescription pBssDescr) +{ + uint16_t ielen; + + if (!pBssDescr) + return 0; + + /** + * Length of BSS desription is without length of + * length itself and length of pointer + * that holds ieFields + * + * <------------sizeof(tSirBssDescription)--------------------> + * +--------+---------------------------------+---------------+ + * | length | other fields | pointer to IEs| + * +--------+---------------------------------+---------------+ + * ^ + * ieFields + */ + + ielen = ((tANI_U16) (pBssDescr->length + sizeof(pBssDescr->length) + + sizeof(tANI_U32 *) - sizeof(tSirBssDescription))); + + return ielen; +} /*** end limGetIElenFromBssDescription() ***/ + +/** + * limSendBeaconInd() + * + *FUNCTION: + * This function is called to send the beacon indication + * number being scanned. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: +*/ + +void +limSendBeaconInd(tpAniSirGlobal pMac, tpPESession psessionEntry); + +void +limSendVdevRestart(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 sessionId); + +void limGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U8 *addr, tANI_U8 *uuid_e, eWPSPBCOverlap *overlap, tpPESession psessionEntry); +void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limWPSPBCClose(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limRemovePBCSessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac,tpPESession psessionEntry); + + +tSirRetStatus +limIsSmeGetWPSPBCSessionsReqValid(tpAniSirGlobal pMac, tSirSmeGetWPSPBCSessionsReq *pGetWPSPBCSessionsReq, tANI_U8 *pBuf); + +#define LIM_WPS_OVERLAP_TIMER_MS 10000 + +void +limSuspendLink(tpAniSirGlobal pMac, tSirLinkTrafficCheck trafficCheck, SUSPEND_RESUME_LINK_CALLBACK callback, tANI_U32 *data); +void +limResumeLink(tpAniSirGlobal pMac, SUSPEND_RESUME_LINK_CALLBACK callback, tANI_U32 *data); + +void +limChangeChannelWithCallback(tpAniSirGlobal pMac, tANI_U8 newChannel, + CHANGE_CHANNEL_CALLBACK callback, tANI_U32 *cbdata, tpPESession psessionEntry); + +void limSendSmeMgmtFrameInd( + tpAniSirGlobal pMac, tANI_U8 frameType, + tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, + tANI_U32 rxChan, tpPESession psessionEntry, + tANI_S8 rxRssi); +void limProcessRemainOnChnTimeout(tpAniSirGlobal pMac); +void limProcessInsertSingleShotNOATimeout(tpAniSirGlobal pMac); +void limConvertActiveChannelToPassiveChannel(tpAniSirGlobal pMac); +void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void limAbortRemainOnChan(tpAniSirGlobal pMac, tANI_U8 sessionId); +tSirRetStatus __limProcessSmeNoAUpdate(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf); +void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac); + +void limProcessDisassocAckTimeout(tpAniSirGlobal pMac); +void limProcessDeauthAckTimeout(tpAniSirGlobal pMac); +eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac); +eHalStatus limSendDeauthCnf(tpAniSirGlobal pMac); +eHalStatus limDisassocTxCompleteCnf(tpAniSirGlobal pMac, + tANI_U32 txCompleteSuccess); +eHalStatus limDeauthTxCompleteCnf(tpAniSirGlobal pMac, + tANI_U32 txCompleteSuccess); + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct sSetLinkCbackParams +{ + void * cbackDataPtr; +} tSetLinkCbackParams; +#endif + +void limProcessRxScanEvent(tpAniSirGlobal mac, void *buf); + +int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg); +void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); +#endif /* __LIM_TYPES_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c new file mode 100644 index 000000000000..d0e9e49ebf23 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c @@ -0,0 +1,8678 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limUtils.cc contains the utility functions + * LIM uses. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "schApi.h" +#include "limUtils.h" +#include "limTypes.h" +#include "limSecurityUtils.h" +#include "limPropExtsUtils.h" +#include "limSendMessages.h" +#include "limSerDesUtils.h" +#include "limAdmitControl.h" +#include "limStaHashApi.h" +#include "dot11f.h" +#include "dot11fdefs.h" +#include "wmmApsd.h" +#include "limTrace.h" +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "vos_diag_core_event.h" +#endif //FEATURE_WLAN_DIAG_SUPPORT +#include "limIbssPeerMgmt.h" +#include "limSessionUtils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "limFTDefs.h" +#endif +#include "limSession.h" +#include "vos_nvitem.h" + +#include "pmmApi.h" +#ifdef WLAN_FEATURE_11W +#include "wniCfgAp.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 + * traffic instead of going into scan. The recover function limProcessQuietBssTimeout() needs to have + * this information. */ +static tAniBool glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE; + +/* 11A Channel list to decode RX BD channel information */ +static const tANI_U8 abChannel[]= {36,40,44,48,52,56,60,64,100,104,108,112,116, + 120,124,128,132,136,140,149,153,157,161,165 +#ifdef FEATURE_WLAN_CH144 + ,144 +#endif +}; +#define abChannelSize (sizeof(abChannel)/ \ + sizeof(abChannel[0])) + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static const tANI_U8 aUnsortedChannelList[]= {52,56,60,64,100,104,108,112,116, + 120,124,128,132,136,140,36,40,44,48,149,153,157,161,165 +#ifdef FEATURE_WLAN_CH144 + ,144 +#endif +}; +#define aUnsortedChannelListSize (sizeof(aUnsortedChannelList)/ \ + sizeof(aUnsortedChannelList[0])) +#endif + +#define SUCCESS 1 + +#define MAX_BA_WINDOW_SIZE_FOR_CISCO 25 + +/** ------------------------------------------------------------- +\fn limAssignDialogueToken +\brief Assigns dialogue token. +\param tpAniSirGlobal pMac +\return tpDialogueToken - dialogueToken data structure. + -------------------------------------------------------------*/ + +tpDialogueToken +limAssignDialogueToken(tpAniSirGlobal pMac) +{ + static tANI_U8 token; + tpDialogueToken pCurrNode; + pCurrNode = vos_mem_malloc(sizeof(tDialogueToken)); + if ( NULL == pCurrNode ) + { + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed"));) + return NULL; + } + + vos_mem_set((void *) pCurrNode, sizeof(tDialogueToken), 0); + //first node in the list is being added. + if(NULL == pMac->lim.pDialogueTokenHead) + { + pMac->lim.pDialogueTokenHead = pMac->lim.pDialogueTokenTail = pCurrNode; + } + else + { + pMac->lim.pDialogueTokenTail->next = pCurrNode; + pMac->lim.pDialogueTokenTail = pCurrNode; + } + //assocId and tid of the node will be filled in by caller. + pCurrNode->next = NULL; + pCurrNode->token = token++; + + /* Dialog token should be a non-zero value */ + if (0 == pCurrNode->token) + pCurrNode->token = token; + + PELOG4(limLog(pMac, LOG4, FL("token assigned = %d"), pCurrNode->token);) + return pCurrNode; +} + +/** ------------------------------------------------------------- +\fn limSearchAndDeleteDialogueToken +\brief search dialogue token in the list and deletes it if found. returns failure if not found. +\param tpAniSirGlobal pMac +\param tANI_U8 token +\param tANI_U16 assocId +\param tANI_U16 tid +\return eSirRetStatus - status of the search + -------------------------------------------------------------*/ + + +tSirRetStatus +limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 assocId, tANI_U16 tid) +{ + tpDialogueToken pCurrNode = pMac->lim.pDialogueTokenHead; + tpDialogueToken pPrevNode = pMac->lim.pDialogueTokenHead; + + //if the list is empty + if(NULL == pCurrNode) + return eSIR_FAILURE; + + // if the matching node is the first node. + if(pCurrNode && + (assocId == pCurrNode->assocId) && + (tid == pCurrNode->tid)) + { + pMac->lim.pDialogueTokenHead = pCurrNode->next; + //there was only one node in the list. So tail pointer also needs to be adjusted. + if(NULL == pMac->lim.pDialogueTokenHead) + pMac->lim.pDialogueTokenTail = NULL; + vos_mem_free(pCurrNode); + pMac->lim.pDialogueTokenHead = NULL; + return eSIR_SUCCESS; + } + + //first node did not match. so move to the next one. + pCurrNode = pCurrNode->next; + while(NULL != pCurrNode ) + { + if(token == pCurrNode->token) + { + break; + } + + pPrevNode = pCurrNode; + pCurrNode = pCurrNode->next; + } + + if(pCurrNode && + (assocId == pCurrNode->assocId) && + (tid == pCurrNode->tid)) + { + pPrevNode->next = pCurrNode->next; + //if the node being deleted is the last one then we also need to move the tail pointer to the prevNode. + if(NULL == pCurrNode->next) + pMac->lim.pDialogueTokenTail = pPrevNode; + vos_mem_free(pCurrNode); + pMac->lim.pDialogueTokenHead = NULL; + return eSIR_SUCCESS; + } + + PELOGW(limLog(pMac, LOGW, FL("LIM does not have matching dialogue token node"));) + return eSIR_FAILURE; + +} + + +/** ------------------------------------------------------------- +\fn limDeleteDialogueTokenList +\brief deletes the complete lim dialogue token linked list. +\param tpAniSirGlobal pMac +\return None + -------------------------------------------------------------*/ +void +limDeleteDialogueTokenList(tpAniSirGlobal pMac) +{ + tpDialogueToken pCurrNode = pMac->lim.pDialogueTokenHead; + + while(NULL != pMac->lim.pDialogueTokenHead) + { + pCurrNode = pMac->lim.pDialogueTokenHead; + pMac->lim.pDialogueTokenHead = pMac->lim.pDialogueTokenHead->next; + vos_mem_free(pCurrNode); + pCurrNode = NULL; + } + pMac->lim.pDialogueTokenTail = NULL; +} + +void +limGetBssidFromBD(tpAniSirGlobal pMac, tANI_U8 * pRxPacketInfo, tANI_U8 *bssId, tANI_U32 *pIgnore) +{ + tpSirMacDataHdr3a pMh = WDA_GET_RX_MPDUHEADER3A(pRxPacketInfo); + *pIgnore = 0; + + if (pMh->fc.toDS == 1 && pMh->fc.fromDS == 0) + { + vos_mem_copy( bssId, pMh->addr1, 6); + *pIgnore = 1; + } + else if (pMh->fc.toDS == 0 && pMh->fc.fromDS == 1) + { + vos_mem_copy ( bssId, pMh->addr2, 6); + *pIgnore = 1; + } + else if (pMh->fc.toDS == 0 && pMh->fc.fromDS == 0) + { + vos_mem_copy( bssId, pMh->addr3, 6); + *pIgnore = 0; + } + else + { + vos_mem_copy( bssId, pMh->addr1, 6); + *pIgnore = 1; + } +} + + +char * +limDot11ReasonStr(tANI_U16 reasonCode) +{ + switch (reasonCode) + { + case 0: return " "; + CASE_RETURN_STRING(eSIR_MAC_UNSPEC_FAILURE_REASON); + CASE_RETURN_STRING(eSIR_MAC_PREV_AUTH_NOT_VALID_REASON); + CASE_RETURN_STRING(eSIR_MAC_DEAUTH_LEAVING_BSS_REASON); + CASE_RETURN_STRING(eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON); + CASE_RETURN_STRING(eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON); + CASE_RETURN_STRING(eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON); + CASE_RETURN_STRING(eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON); + CASE_RETURN_STRING(eSIR_MAC_DISASSOC_LEAVING_BSS_REASON); + CASE_RETURN_STRING(eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON); + CASE_RETURN_STRING(eSIR_MAC_PWR_CAPABILITY_BAD_REASON); + CASE_RETURN_STRING(eSIR_MAC_SPRTD_CHANNELS_BAD_REASON); + + CASE_RETURN_STRING(eSIR_MAC_INVALID_IE_REASON); + CASE_RETURN_STRING(eSIR_MAC_MIC_FAILURE_REASON); + CASE_RETURN_STRING(eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON); + CASE_RETURN_STRING(eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON); + CASE_RETURN_STRING(eSIR_MAC_RSN_IE_MISMATCH_REASON); + + CASE_RETURN_STRING(eSIR_MAC_INVALID_MC_CIPHER_REASON); + CASE_RETURN_STRING(eSIR_MAC_INVALID_UC_CIPHER_REASON); + CASE_RETURN_STRING(eSIR_MAC_INVALID_AKMP_REASON); + CASE_RETURN_STRING(eSIR_MAC_UNSUPPORTED_RSN_IE_VER_REASON); + CASE_RETURN_STRING(eSIR_MAC_INVALID_RSN_CAPABILITIES_REASON); + CASE_RETURN_STRING(eSIR_MAC_1X_AUTH_FAILURE_REASON); + CASE_RETURN_STRING(eSIR_MAC_CIPHER_SUITE_REJECTED_REASON); +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE); + CASE_RETURN_STRING(eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); +#endif + /* Reserved 27 - 30*/ +#ifdef WLAN_FEATURE_11W + CASE_RETURN_STRING(eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION); +#endif + CASE_RETURN_STRING(eSIR_MAC_QOS_UNSPECIFIED_REASON); + CASE_RETURN_STRING(eSIR_MAC_QAP_NO_BANDWIDTH_REASON); + CASE_RETURN_STRING(eSIR_MAC_XS_UNACKED_FRAMES_REASON); + CASE_RETURN_STRING(eSIR_MAC_BAD_TXOP_USE_REASON); + CASE_RETURN_STRING(eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON); + CASE_RETURN_STRING(eSIR_MAC_PEER_REJECT_MECHANISIM_REASON); + CASE_RETURN_STRING(eSIR_MAC_MECHANISM_NOT_SETUP_REASON); + + CASE_RETURN_STRING(eSIR_MAC_PEER_TIMEDOUT_REASON); + CASE_RETURN_STRING(eSIR_MAC_CIPHER_NOT_SUPPORTED_REASON); + CASE_RETURN_STRING(eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON); + /* Reserved 47 - 65535 */ + default: + return "Unknown"; + } +} + + +char * +limMlmStateStr(tLimMlmStates state) +{ + switch (state) + { + case eLIM_MLM_OFFLINE_STATE: + return "eLIM_MLM_OFFLINE_STATE"; + case eLIM_MLM_IDLE_STATE: + return "eLIM_MLM_IDLE_STATE"; + case eLIM_MLM_WT_PROBE_RESP_STATE: + return "eLIM_MLM_WT_PROBE_RESP_STATE"; + case eLIM_MLM_PASSIVE_SCAN_STATE: + return "eLIM_MLM_PASSIVE_SCAN_STATE"; + case eLIM_MLM_WT_JOIN_BEACON_STATE: + return "eLIM_MLM_WT_JOIN_BEACON_STATE"; + case eLIM_MLM_JOINED_STATE: + return "eLIM_MLM_JOINED_STATE"; + case eLIM_MLM_BSS_STARTED_STATE: + return "eLIM_MLM_BSS_STARTED_STATE"; + case eLIM_MLM_WT_AUTH_FRAME2_STATE: + return "eLIM_MLM_WT_AUTH_FRAME2_STATE"; + case eLIM_MLM_WT_AUTH_FRAME3_STATE: + return "eLIM_MLM_WT_AUTH_FRAME3_STATE"; + case eLIM_MLM_WT_AUTH_FRAME4_STATE: + return "eLIM_MLM_WT_AUTH_FRAME4_STATE"; + case eLIM_MLM_AUTH_RSP_TIMEOUT_STATE: + return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE"; + case eLIM_MLM_AUTHENTICATED_STATE: + return "eLIM_MLM_AUTHENTICATED_STATE"; + case eLIM_MLM_WT_ASSOC_RSP_STATE: + return "eLIM_MLM_WT_ASSOC_RSP_STATE"; + case eLIM_MLM_WT_REASSOC_RSP_STATE: + return "eLIM_MLM_WT_REASSOC_RSP_STATE"; + case eLIM_MLM_WT_FT_REASSOC_RSP_STATE: + return "eLIM_MLM_WT_FT_REASSOC_RSP_STATE"; + case eLIM_MLM_WT_DEL_STA_RSP_STATE: + return "eLIM_MLM_WT_DEL_STA_RSP_STATE"; + case eLIM_MLM_WT_DEL_BSS_RSP_STATE: + return "eLIM_MLM_WT_DEL_BSS_RSP_STATE"; + case eLIM_MLM_WT_ADD_STA_RSP_STATE: + return "eLIM_MLM_WT_ADD_STA_RSP_STATE"; + case eLIM_MLM_WT_ADD_BSS_RSP_STATE: + return "eLIM_MLM_WT_ADD_BSS_RSP_STATE"; + case eLIM_MLM_REASSOCIATED_STATE: + return "eLIM_MLM_REASSOCIATED_STATE"; + case eLIM_MLM_LINK_ESTABLISHED_STATE: + return "eLIM_MLM_LINK_ESTABLISHED_STATE"; + case eLIM_MLM_WT_ASSOC_CNF_STATE: + return "eLIM_MLM_WT_ASSOC_CNF_STATE"; + case eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE: + return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE"; + case eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE: + return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE"; + case eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE: + return "eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE"; + case eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE: + return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE"; + case eLIM_MLM_WT_SET_BSS_KEY_STATE: + return "eLIM_MLM_WT_SET_BSS_KEY_STATE"; + case eLIM_MLM_WT_SET_STA_KEY_STATE: + return "eLIM_MLM_WT_SET_STA_KEY_STATE"; + default: + return "INVALID MLM state"; + } +} + +void +limPrintMlmState(tpAniSirGlobal pMac, tANI_U16 logLevel, tLimMlmStates state) +{ + limLog(pMac, logLevel, limMlmStateStr(state)); +} + +char* limBssTypeStr(tSirBssType bssType) +{ + switch(bssType) + { + case eSIR_INFRASTRUCTURE_MODE: + return "eSIR_INFRASTRUCTURE_MODE"; + case eSIR_IBSS_MODE: + return "eSIR_IBSS_MODE"; + case eSIR_BTAMP_STA_MODE: + return "eSIR_BTAMP_STA_MODE"; + case eSIR_BTAMP_AP_MODE: + return "eSIR_BTAMP_AP_MODE"; + case eSIR_AUTO_MODE: + return "eSIR_AUTO_MODE"; + default: + return "Invalid BSS Type"; + } +} + +char *limResultCodeStr(tSirResultCodes resultCode) +{ + switch (resultCode) + { + case eSIR_SME_SUCCESS: + return "eSIR_SME_SUCCESS"; + case eSIR_EOF_SOF_EXCEPTION: + return "eSIR_EOF_SOF_EXCEPTION"; + case eSIR_BMU_EXCEPTION: + return "eSIR_BMU_EXCEPTION"; + case eSIR_LOW_PDU_EXCEPTION: + return "eSIR_LOW_PDU_EXCEPTION"; + case eSIR_USER_TRIG_RESET: + return"eSIR_USER_TRIG_RESET"; + case eSIR_LOGP_EXCEPTION: + return "eSIR_LOGP_EXCEPTION"; + case eSIR_CP_EXCEPTION: + return "eSIR_CP_EXCEPTION"; + case eSIR_STOP_BSS: + return "eSIR_STOP_BSS"; + case eSIR_AHB_HANG_EXCEPTION: + return "eSIR_AHB_HANG_EXCEPTION"; + case eSIR_DPU_EXCEPTION: + return "eSIR_DPU_EXCEPTION"; + case eSIR_RXP_EXCEPTION: + return "eSIR_RXP_EXCEPTION"; + case eSIR_MCPU_EXCEPTION: + return "eSIR_MCPU_EXCEPTION"; + case eSIR_MCU_EXCEPTION: + return "eSIR_MCU_EXCEPTION"; + case eSIR_MTU_EXCEPTION: + return "eSIR_MTU_EXCEPTION"; + case eSIR_MIF_EXCEPTION: + return "eSIR_MIF_EXCEPTION"; + case eSIR_FW_EXCEPTION: + return "eSIR_FW_EXCEPTION"; + case eSIR_MAILBOX_SANITY_CHK_FAILED: + return "eSIR_MAILBOX_SANITY_CHK_FAILED"; + case eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF: + return "eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF"; + case eSIR_CFB_FLAG_STUCK_EXCEPTION: + return "eSIR_CFB_FLAG_STUCK_EXCEPTION"; + case eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS: + return "eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS"; + case eSIR_SME_INVALID_PARAMETERS: + return "eSIR_SME_INVALID_PARAMETERS"; + case eSIR_SME_UNEXPECTED_REQ_RESULT_CODE: + return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE"; + case eSIR_SME_RESOURCES_UNAVAILABLE: + return "eSIR_SME_RESOURCES_UNAVAILABLE"; + case eSIR_SME_SCAN_FAILED: + return "eSIR_SME_SCAN_FAILED"; + case eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED: + return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED"; + case eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE: + return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE"; + case eSIR_SME_REFUSED: + return "eSIR_SME_REFUSED"; + case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE: + return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE"; + case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE: + return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE"; + case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE: + return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE"; + case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE: + return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE"; + case eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED: + return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED"; + case eSIR_SME_AUTH_REFUSED: + return "eSIR_SME_AUTH_REFUSED"; + case eSIR_SME_INVALID_WEP_DEFAULT_KEY: + return "eSIR_SME_INVALID_WEP_DEFAULT_KEY"; + case eSIR_SME_ASSOC_REFUSED: + return "eSIR_SME_ASSOC_REFUSED"; + case eSIR_SME_REASSOC_REFUSED: + return "eSIR_SME_REASSOC_REFUSED"; + case eSIR_SME_STA_NOT_AUTHENTICATED: + return "eSIR_SME_STA_NOT_AUTHENTICATED"; + case eSIR_SME_STA_NOT_ASSOCIATED: + return "eSIR_SME_STA_NOT_ASSOCIATED"; + case eSIR_SME_STA_DISASSOCIATED: + return "eSIR_SME_STA_DISASSOCIATED"; + case eSIR_SME_ALREADY_JOINED_A_BSS: + return "eSIR_SME_ALREADY_JOINED_A_BSS"; + case eSIR_ULA_COMPLETED: + return "eSIR_ULA_COMPLETED"; + case eSIR_ULA_FAILURE: + return "eSIR_ULA_FAILURE"; + case eSIR_SME_LINK_ESTABLISHED: + return "eSIR_SME_LINK_ESTABLISHED"; + case eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS: + return "eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS"; + case eSIR_SME_UNABLE_TO_PERFORM_DFS: + return "eSIR_SME_UNABLE_TO_PERFORM_DFS"; + case eSIR_SME_DFS_FAILED: + return "eSIR_SME_DFS_FAILED"; + case eSIR_SME_TRANSFER_STA: + return "eSIR_SME_TRANSFER_STA"; + case eSIR_SME_INVALID_LINK_TEST_PARAMETERS: + return "eSIR_SME_INVALID_LINK_TEST_PARAMETERS"; + case eSIR_SME_LINK_TEST_MAX_EXCEEDED: + return "eSIR_SME_LINK_TEST_MAX_EXCEEDED"; + case eSIR_SME_UNSUPPORTED_RATE: + return "eSIR_SME_UNSUPPORTED_RATE"; + case eSIR_SME_LINK_TEST_TIMEOUT: + return "eSIR_SME_LINK_TEST_TIMEOUT"; + case eSIR_SME_LINK_TEST_COMPLETE: + return "eSIR_SME_LINK_TEST_COMPLETE"; + case eSIR_SME_LINK_TEST_INVALID_STATE: + return "eSIR_SME_LINK_TEST_INVALID_STATE"; + case eSIR_SME_LINK_TEST_INVALID_ADDRESS: + return "eSIR_SME_LINK_TEST_INVALID_ADDRESS"; + case eSIR_SME_SETCONTEXT_FAILED: + return "eSIR_SME_SETCONTEXT_FAILED"; + case eSIR_SME_BSS_RESTART: + return "eSIR_SME_BSS_RESTART"; + case eSIR_SME_MORE_SCAN_RESULTS_FOLLOW: + return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW"; + case eSIR_SME_INVALID_ASSOC_RSP_RXED: + return "eSIR_SME_INVALID_ASSOC_RSP_RXED"; + case eSIR_SME_MIC_COUNTER_MEASURES: + return "eSIR_SME_MIC_COUNTER_MEASURES"; + case eSIR_SME_ADDTS_RSP_TIMEOUT: + return "eSIR_SME_ADDTS_RSP_TIMEOUT"; + case eSIR_SME_RECEIVED: + return "eSIR_SME_RECEIVED"; + case eSIR_SME_CHANNEL_SWITCH_FAIL: + return "eSIR_SME_CHANNEL_SWITCH_FAIL"; + case eSIR_SME_CHANNEL_SWITCH_DISABLED: + return "eSIR_SME_CHANNEL_SWITCH_DISABLED"; + case eSIR_SME_HAL_SCAN_INIT_FAILED: + return "eSIR_SME_HAL_SCAN_INIT_FAILED"; + case eSIR_SME_HAL_SCAN_START_FAILED: + return "eSIR_SME_HAL_SCAN_START_FAILED"; + case eSIR_SME_HAL_SCAN_END_FAILED: + return "eSIR_SME_HAL_SCAN_END_FAILED"; + case eSIR_SME_HAL_SCAN_FINISH_FAILED: + return "eSIR_SME_HAL_SCAN_FINISH_FAILED"; + case eSIR_SME_HAL_SEND_MESSAGE_FAIL: + return "eSIR_SME_HAL_SEND_MESSAGE_FAIL"; + + default: + return "INVALID resultCode"; + } +} + +/** + * limInitMlm() - This function is called by limProcessSmeMessages() + * to initialize MLM state machine on STA + * + * @pMac: Pointer to Global MAC structure + * + * @Return: Status of operation + */ +tSirRetStatus +limInitMlm(tpAniSirGlobal pMac) +{ + tANI_U32 retVal; + + pMac->lim.gLimTimersCreated = 0; + + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState)); + + /// Initialize scan result hash table + limReInitScanResults(pMac); //sep26th review + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /// Initialize lfr scan result hash table + // Could there be a problem in multisession with SAP/P2P GO, when in the + // middle of FW bg scan, SAP started; Again that could be a problem even on + // infra + SAP/P2P GO too - TBD + limReInitLfrScanResults(pMac); +#endif + + /// Initialize number of pre-auth contexts + pMac->lim.gLimNumPreAuthContexts = 0; + + /// Initialize MAC based Authentication STA list + limInitPreAuthList(pMac); + + // Create timers used by LIM + retVal = limCreateTimers(pMac); + if(retVal != TX_SUCCESS) { + limLog(pMac, LOGP, FL(" limCreateTimers Failed to create lim timers ")); + return eSIR_FAILURE; + } + + pMac->lim.gLimTimersCreated = 1; + return eSIR_SUCCESS; +} /*** end limInitMlm() ***/ + + + +/** + * limCleanupMlm() + * + *FUNCTION: + * This function is called to cleanup any resources + * allocated by the MLM state machine. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * It is assumed that BSS is already informed that we're leaving it + * before this function is called. + * + * @param pMac Pointer to Global MAC structure + * @param None + * @return None + */ +void +limCleanupMlm(tpAniSirGlobal pMac) +{ + tANI_U32 n; + tLimPreAuthNode **pAuthNode; +#ifdef WLAN_FEATURE_11W + tANI_U32 bss_entry, sta_entry; + tpDphHashNode pStaDs = NULL; + tpPESession psessionEntry = NULL; +#endif + + if (pMac->lim.gLimTimersCreated == 1) + { + // Deactivate and delete MIN/MAX channel timers. + tx_timer_deactivate(&pMac->lim.limTimers.gLimMinChannelTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimMinChannelTimer); + tx_timer_deactivate(&pMac->lim.limTimers.gLimMaxChannelTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimMaxChannelTimer); + tx_timer_deactivate(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer); + + + // Deactivate and delete channel switch timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimChannelSwitchTimer); + + + // Deactivate and delete addts response timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimAddtsRspTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimAddtsRspTimer); + + // Deactivate and delete Join failure timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimJoinFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimJoinFailureTimer); + + // Deactivate and delete Periodic Join Probe Request timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer); + + // Deactivate and delete Auth Retry timer. + tx_timer_deactivate(&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer); + tx_timer_delete(&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer); + + // Deactivate and delete Association failure timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimAssocFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimAssocFailureTimer); + + // Deactivate and delete Reassociation failure timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimReassocFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimReassocFailureTimer); + + // Deactivate and delete Authentication failure timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimAuthFailureTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimAuthFailureTimer); + + // Deactivate and delete Heartbeat timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimHeartBeatTimer); + + // Deactivate and delete wait-for-probe-after-Heartbeat timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimProbeAfterHBTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimProbeAfterHBTimer); + + // Deactivate and delete Quiet timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimQuietTimer); + + // Deactivate and delete Quiet BSS timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimQuietBssTimer); + + // Deactivate and delete LIM background scan timer. + tx_timer_deactivate(&pMac->lim.limTimers.gLimBackgroundScanTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimBackgroundScanTimer); + + + // Deactivate and delete cnf wait timer + for (n = 0; n < (pMac->lim.maxStation + 1); n++) + { + tx_timer_deactivate(&pMac->lim.limTimers.gpLimCnfWaitTimer[n]); + tx_timer_delete(&pMac->lim.limTimers.gpLimCnfWaitTimer[n]); + } + + // Deactivate and delete keepalive timer + tx_timer_deactivate(&pMac->lim.limTimers.gLimKeepaliveTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimKeepaliveTimer); + + pAuthNode = pMac->lim.gLimPreAuthTimerTable.pTable; + + //Deactivate any Authentication response timers + limDeletePreAuthList(pMac); + + for (n = 0; n < pMac->lim.gLimPreAuthTimerTable.numEntry; n++) + { + // Delete any Authentication response + // timers, which might have been started. + tx_timer_delete(&pAuthNode[n]->timer); + } + + // Deactivate and delete Hash Miss throttle timer + tx_timer_deactivate(&pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer); + + tx_timer_deactivate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer); + tx_timer_deactivate(&pMac->lim.limTimers.gLimPreAuthClnupTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimPreAuthClnupTimer); + +#ifdef WLAN_FEATURE_VOWIFI_11R + // Deactivate and delete FT Preauth response timer + tx_timer_deactivate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer); +#endif + + // Deactivate and delete remain on channel timer + tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimRemainOnChannelTimer); + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + // Deactivate and delete TSM + tx_timer_deactivate(&pMac->lim.limTimers.gLimEseTsmTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimEseTsmTimer); +#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ + + tx_timer_deactivate(&pMac->lim.limTimers.gLimDisassocAckTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimDisassocAckTimer); + + tx_timer_deactivate(&pMac->lim.limTimers.gLimDeauthAckTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimDeauthAckTimer); + + tx_timer_deactivate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer); + + tx_timer_deactivate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + + pMac->lim.gLimTimersCreated = 0; + } + +#ifdef WLAN_FEATURE_11W + /* + * When SSR is triggered, we need to loop through + * each STA associated per BSSId and deactivate/delete + * the pmfSaQueryTimer for it + */ + if (vos_is_logp_in_progress(VOS_MODULE_ID_PE, NULL)) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + FL("SSR is detected, proceed to clean up pmfSaQueryTimer")); + for (bss_entry = 0; bss_entry < pMac->lim.maxBssId; bss_entry++) + { + if (pMac->lim.gpSession[bss_entry].valid) + { + for (sta_entry = 1; sta_entry < pMac->lim.gLimAssocStaLimit; + sta_entry++) + { + psessionEntry = &pMac->lim.gpSession[bss_entry]; + pStaDs = dphGetHashEntry(pMac, sta_entry, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) + { + continue; + } + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + FL("Deleting pmfSaQueryTimer for staid[%d]"), + pStaDs->staIndex) ; + tx_timer_deactivate(&pStaDs->pmfSaQueryTimer); + tx_timer_delete(&pStaDs->pmfSaQueryTimer); + } + } + } + } +#endif + + /// Cleanup cached scan list + limReInitScanResults(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /// Cleanup cached scan list + limReInitLfrScanResults(pMac); +#endif + +} /*** end limCleanupMlm() ***/ + + + +/** + * limCleanupLmm() + * + *FUNCTION: + * This function is called to cleanup any resources + * allocated by LMM sub-module. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @return None + */ + +void +limCleanupLmm(tpAniSirGlobal pMac) +{ +} /*** end limCleanupLmm() ***/ + + + +/** + * limIsAddrBC() + * + *FUNCTION: + * This function is called in various places within LIM code + * to determine whether passed MAC address is a broadcast or not + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param macAddr Indicates MAC address that need to be determined + * whether it is Broadcast address or not + * + * @return true if passed address is Broadcast address else false + */ + +tANI_U8 +limIsAddrBC(tSirMacAddr macAddr) +{ + int i; + for (i = 0; i < 6; i++) + { + if ((macAddr[i] & 0xFF) != 0xFF) + return false; + } + + return true; +} /****** end limIsAddrBC() ******/ + + + +/** + * limIsGroupAddr() + * + *FUNCTION: + * This function is called in various places within LIM code + * to determine whether passed MAC address is a group address or not + * + *LOGIC: + * If least significant bit of first octet of the MAC address is + * set to 1, it is a Group address. + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param macAddr Indicates MAC address that need to be determined + * whether it is Group address or not + * + * @return true if passed address is Group address else false + */ + +tANI_U8 +limIsGroupAddr(tSirMacAddr macAddr) +{ + if ((macAddr[0] & 0x01) == 0x01) + return true; + else + return false; +} /****** end limIsGroupAddr() ******/ + +/** + * limPostMsgApiNoWait() + * + *FUNCTION: + * This function is called from other thread while posting a + * message to LIM message Queue gSirLimMsgQ with NO_WAIT option + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMsg - Pointer to the Global MAC structure + * @param pMsg - Pointer to the message structure + * @return None + */ + +tANI_U32 +limPostMsgApiNoWait(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + limProcessMessages(pMac, pMsg); + return TX_SUCCESS; +} /*** end limPostMsgApiNoWait() ***/ + + + +/** + * limPrintMacAddr() + * + *FUNCTION: + * This function is called to print passed MAC address + * in : format. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * @param macAddr - MacAddr to be printed + * @param logLevel - Loglevel to be used + * + * @return None. + */ + +void +limPrintMacAddr(tpAniSirGlobal pMac, tSirMacAddr macAddr, tANI_U8 logLevel) +{ + limLog(pMac, logLevel, + FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(macAddr)); +} /****** end limPrintMacAddr() ******/ + + + + + + +/* + * limResetDeferredMsgQ() + * + *FUNCTION: + * This function resets the deferred message queue parameters. + * + *PARAMS: + * @param pMac - Pointer to Global MAC structure + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + *RETURNS: + * None + */ + +void limResetDeferredMsgQ(tpAniSirGlobal pMac) +{ + pMac->lim.gLimDeferredMsgQ.size = + pMac->lim.gLimDeferredMsgQ.write = + pMac->lim.gLimDeferredMsgQ.read = 0; + +} + + +#define LIM_DEFERRED_Q_CHECK_THRESHOLD (MAX_DEFERRED_QUEUE_LEN/2) +#define LIM_MAX_NUM_MGMT_FRAME_DEFERRED (MAX_DEFERRED_QUEUE_LEN/2) + +/* + * limWriteDeferredMsgQ() + * + *FUNCTION: + * This function queues up a deferred message for later processing on the + * STA side. + * + *PARAMS: + * @param pMac - Pointer to Global MAC structure + * @param limMsg - a LIM message + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + *RETURNS: + * None + */ + +tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + PELOG1(limLog(pMac, LOG1, + FL("** Queue a deferred message (size %d, write %d) - type 0x%x **"), + pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.write, + limMsg->type);) + + /* + ** check if the deferred message queue is full + **/ + if (pMac->lim.gLimDeferredMsgQ.size >= MAX_DEFERRED_QUEUE_LEN) + { + if(!(pMac->lim.deferredMsgCnt & 0xF)) + { + PELOGE(limLog(pMac, LOGE, FL("Deferred Message Queue is full. Msg:%d Messages Failed:%d"), limMsg->type, ++pMac->lim.deferredMsgCnt);) + } + else + { + pMac->lim.deferredMsgCnt++; + } + return TX_QUEUE_FULL; + } + + /* + ** In the application, there should not be more than 1 message get + ** queued up. If happens, flags a warning. In the future, this can + ** happen. + **/ + if (pMac->lim.gLimDeferredMsgQ.size > 0) + { + PELOGW(limLog(pMac, LOGW, FL("%d Deferred messages (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)"), + pMac->lim.gLimDeferredMsgQ.size, limMsg->type, + limIsSystemInScanState(pMac), + pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, + pMac->lim.gLimAddtsSent);) + } + + /* + ** To prevent the deferred Q is full of management frames, only give them certain space + **/ + if( SIR_BB_XPORT_MGMT_MSG == limMsg->type ) + { + if( LIM_DEFERRED_Q_CHECK_THRESHOLD < pMac->lim.gLimDeferredMsgQ.size ) + { + tANI_U16 idx, count = 0; + for(idx = 0; idx < pMac->lim.gLimDeferredMsgQ.size; idx++) + { + if( SIR_BB_XPORT_MGMT_MSG == pMac->lim.gLimDeferredMsgQ.deferredQueue[idx].type ) + { + count++; + } + } + if( LIM_MAX_NUM_MGMT_FRAME_DEFERRED < count ) + { + //We reach the quota for management frames, drop this one + PELOGW(limLog(pMac, LOGW, FL("Cannot deferred. Msg: %d Too many (count=%d) already"), limMsg->type, count);) + //Return error, caller knows what to do + return TX_QUEUE_FULL; + } + } + } + + ++pMac->lim.gLimDeferredMsgQ.size; + + /* reset the count here since we are able to defer the message */ + if(pMac->lim.deferredMsgCnt != 0) + { + pMac->lim.deferredMsgCnt = 0; + } + + /* + ** if the write pointer hits the end of the queue, rewind it + **/ + if (pMac->lim.gLimDeferredMsgQ.write >= MAX_DEFERRED_QUEUE_LEN) + pMac->lim.gLimDeferredMsgQ.write = 0; + + /* + ** save the message to the queue and advanced the write pointer + **/ + vos_mem_copy( (tANI_U8 *)&pMac->lim.gLimDeferredMsgQ.deferredQueue[ + pMac->lim.gLimDeferredMsgQ.write++], + (tANI_U8 *)limMsg, + sizeof(tSirMsgQ)); + return TX_SUCCESS; + +} + +/* + * limReadDeferredMsgQ() + * + *FUNCTION: + * This function dequeues a deferred message for processing on the + * STA side. + * + *PARAMS: + * @param pMac - Pointer to Global MAC structure + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * + *RETURNS: + * Returns the message at the head of the deferred message queue + */ + +tSirMsgQ* limReadDeferredMsgQ(tpAniSirGlobal pMac) +{ + tSirMsgQ *msg; + + /* + ** check any messages left. If no, return + **/ + if (pMac->lim.gLimDeferredMsgQ.size <= 0) + return NULL; + + /* + ** decrement the queue size + **/ + pMac->lim.gLimDeferredMsgQ.size--; + + /* + ** retrieve the message from the head of the queue + **/ + msg = &pMac->lim.gLimDeferredMsgQ.deferredQueue[pMac->lim.gLimDeferredMsgQ.read]; + + /* + ** advance the read pointer + **/ + pMac->lim.gLimDeferredMsgQ.read++; + + /* + ** if the read pointer hits the end of the queue, rewind it + **/ + if (pMac->lim.gLimDeferredMsgQ.read >= MAX_DEFERRED_QUEUE_LEN) + pMac->lim.gLimDeferredMsgQ.read = 0; + + PELOG1(limLog(pMac, LOG1, + FL("** DeQueue a deferred message (size %d read %d) - type 0x%x **"), + pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.read, + msg->type);) + + PELOG1(limLog(pMac, LOG1, FL("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d"), + limIsSystemInScanState(pMac), + pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, + pMac->lim.gLimAddtsSent);) + + return(msg); +} + +tSirRetStatus +limSysProcessMmhMsgApi(tpAniSirGlobal pMac, + tSirMsgQ *pMsg, + tANI_U8 qType) +{ +// FIXME + SysProcessMmhMsg(pMac, pMsg); + return eSIR_SUCCESS; +} + +void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) +{ + int i; + static int enable; + tUpdateBeaconParams beaconParams; + + tpPESession psessionEntry = limIsApSessionActive(pMac); + + if (psessionEntry == NULL) + { + PELOGE(limLog(pMac, LOGE, FL(" Session not found"));) + return; + } + + vos_mem_set( ( tANI_U8* )&beaconParams, sizeof( tUpdateBeaconParams), 0); + beaconParams.bssIdx = psessionEntry->bssIdx; + + beaconParams.paramChangeBitmap = 0; + /* + ** This is doing a 2 pass check. The first pass is to invalidate + ** all the cache entries. The second pass is to decide whether to + ** disable protection. + **/ + if (!enable) + { + + PELOG2(limLog(pMac, LOG2, FL("Resetting OLBC cache"));) + psessionEntry->gLimOlbcParams.numSta = 0; + psessionEntry->gLimOverlap11gParams.numSta = 0; + psessionEntry->gLimOverlapHt20Params.numSta = 0; + psessionEntry->gLimNonGfParams.numSta = 0; + psessionEntry->gLimLsigTxopParams.numSta = 0; + + for (i=0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++) + pMac->lim.protStaOverlapCache[i].active = false; + + enable = 1; + } + else + { + + if (!psessionEntry->gLimOlbcParams.numSta) + { + if (psessionEntry->gLimOlbcParams.protectionEnabled) + { + if (!psessionEntry->gLim11bParams.protectionEnabled) + { + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11B STA detected"));) + limEnable11gProtection(pMac, false, true, &beaconParams, psessionEntry); + } + } + } + + if (!psessionEntry->gLimOverlap11gParams.numSta) + { + if (psessionEntry->gLimOverlap11gParams.protectionEnabled) + { + if (!psessionEntry->gLim11gParams.protectionEnabled) + { + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11G STA detected"));) + limEnableHtProtectionFrom11g(pMac, false, true, &beaconParams,psessionEntry); + } + } + } + + if (!psessionEntry->gLimOverlapHt20Params.numSta) + { + if (psessionEntry->gLimOverlapHt20Params.protectionEnabled) + { + if (!psessionEntry->gLimHt20Params.protectionEnabled) + { + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no HT20 STA detected"));) + limEnable11gProtection(pMac, false, true, &beaconParams,psessionEntry); + } + } + } + + enable = 0; + } + + if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) + { + schSetFixedBeaconFields(pMac,psessionEntry); + limSendBeaconParams(pMac, &beaconParams, psessionEntry); + } + + // Start OLBC timer + if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("tx_timer_activate failed")); + } +} + +/** + * limIsNullSsid() + * + *FUNCTION: + * This function checks if Ssid supplied is Null SSID + * + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param tSirMacSSid * + * + * + * @return true if SSID is Null SSID else false + */ + +tANI_U8 +limIsNullSsid( tSirMacSSid *pSsid ) +{ + tANI_U8 fNullSsid = false; + tANI_U32 SsidLength; + tANI_U8 *pSsidStr; + + do + { + if ( 0 == pSsid->length ) + { + fNullSsid = true; + break; + } + +#define ASCII_SPACE_CHARACTER 0x20 + /* If the first charactes is space and SSID length is 1 + * then consider it as NULL SSID*/ + if((ASCII_SPACE_CHARACTER == pSsid->ssId[0])&& + (pSsid->length == 1)) + { + fNullSsid = true; + break; + } + else + { + /* check if all the charactes in SSID are NULL*/ + SsidLength = pSsid->length; + pSsidStr = pSsid->ssId; + + while ( SsidLength ) + { + if( *pSsidStr ) + break; + + pSsidStr++; + SsidLength--; + } + + if( 0 == SsidLength ) + { + fNullSsid = true; + break; + } + } + } + while( 0 ); + + return fNullSsid; +} /****** end limIsNullSsid() ******/ + + + + +/** ------------------------------------------------------------- +\fn limUpdateProtStaParams +\brief updates protection related counters. +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tLimProtStaCacheType protStaCacheType +\param tHalBitVal gfSupported +\param tHalBitVal lsigTxopSupported +\return None + -------------------------------------------------------------*/ +void +limUpdateProtStaParams(tpAniSirGlobal pMac, +tSirMacAddr peerMacAddr, tLimProtStaCacheType protStaCacheType, +tHalBitVal gfSupported, tHalBitVal lsigTxopSupported, +tpPESession psessionEntry) +{ + tANI_U32 i; + + PELOG1(limLog(pMac,LOG1, FL("A STA is associated:")); + limLog(pMac,LOG1, FL("Addr : ")); + limPrintMacAddr(pMac, peerMacAddr, LOG1);) + + for (i=0; iprotStaCache[i].active) + { + PELOG1(limLog(pMac, LOG1, FL("Addr: "));) + PELOG1(limPrintMacAddr(pMac, psessionEntry->protStaCache[i].addr, LOG1);) + + if (vos_mem_compare( + psessionEntry->protStaCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) + { + PELOG1(limLog(pMac, LOG1, FL("matching cache entry at %d already active."), i);) + return; + } + } + } + + for (i=0; iprotStaCache[i].active) + break; + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) + { + PELOGE(limLog(pMac, LOGE, FL("No space in ProtStaCache"));) + return; + } + + vos_mem_copy( psessionEntry->protStaCache[i].addr, + peerMacAddr, + sizeof(tSirMacAddr)); + + psessionEntry->protStaCache[i].protStaCacheType = protStaCacheType; + psessionEntry->protStaCache[i].active = true; + if(eLIM_PROT_STA_CACHE_TYPE_llB == protStaCacheType) + { + psessionEntry->gLim11bParams.numSta++; + limLog(pMac,LOG1, FL("11B, ")); + } + else if(eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) + { + psessionEntry->gLim11gParams.numSta++; + limLog(pMac,LOG1, FL("11G, ")); + } + else if(eLIM_PROT_STA_CACHE_TYPE_HT20 == protStaCacheType) + { + psessionEntry->gLimHt20Params.numSta++; + limLog(pMac,LOG1, FL("HT20, ")); + } + + if(!gfSupported) + { + psessionEntry->gLimNonGfParams.numSta++; + limLog(pMac,LOG1, FL("NonGf, ")); + } + if(!lsigTxopSupported) + { + psessionEntry->gLimLsigTxopParams.numSta++; + limLog(pMac,LOG1, FL("!lsigTxopSupported")); + } +}// --------------------------------------------------------------------- + +/** ------------------------------------------------------------- +\fn limDecideApProtection +\brief Decides all the protection related staiton coexistence and also sets +\ short preamble and short slot appropriately. This function will be called +\ when AP is ready to send assocRsp tp the station joining right now. +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\return None + -------------------------------------------------------------*/ +void +limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + tANI_U16 tmpAid; + tpDphHashNode pStaDs; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + tANI_U32 phyMode; + tLimProtStaCacheType protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_INVALID; + tHalBitVal gfSupported = eHAL_SET, lsigTxopSupported = eHAL_SET; + + pBeaconParams->paramChangeBitmap = 0; + // check whether to enable protection or not + pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable); + if(NULL == pStaDs) + { + PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL"));) + return; + } + limGetRfBand(pMac, &rfBand, psessionEntry); + //if we are in 5 GHZ band + if(SIR_BAND_5_GHZ == rfBand) + { + //We are 11N. we need to protect from 11A and Ht20. we don't need any other protection in 5 GHZ. + //HT20 case is common between both the bands and handled down as common code. + if(true == psessionEntry->htCapability) + { + //we are 11N and 11A station is joining. + //protection from 11A required. + if(false == pStaDs->mlmStaContext.htCapability) + { + limEnable11aProtection(pMac, true, false, pBeaconParams,psessionEntry); + return; + } + } + } + else if(SIR_BAND_2_4_GHZ== rfBand) + { + limGetPhyMode(pMac, &phyMode, psessionEntry); + + //We are 11G. Check if we need protection from 11b Stations. + if ((phyMode == WNI_CFG_PHY_MODE_11G) && + (false == psessionEntry->htCapability)) + { + + if (pStaDs->erpEnabled== eHAL_CLEAR) + { + protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; + // enable protection + PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B"));) + limEnable11gProtection(pMac, true, false, pBeaconParams,psessionEntry); + } + } + + //HT station. + if (true == psessionEntry->htCapability) + { + //check if we need protection from 11b station + if ((pStaDs->erpEnabled == eHAL_CLEAR) && + (!pStaDs->mlmStaContext.htCapability)) + { + protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; + // enable protection + PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B"));) + limEnable11gProtection(pMac, true, false, pBeaconParams, psessionEntry); + } + //station being joined is non-11b and non-ht ==> 11g device + else if(!pStaDs->mlmStaContext.htCapability) + { + protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llG; + //enable protection + limEnableHtProtectionFrom11g(pMac, true, false, pBeaconParams, psessionEntry); + } + //ERP mode is enabled for the latest station joined + //latest station joined is HT capable + //This case is being handled in common code (commn between both the bands) below. + } + } + + //we are HT and HT station is joining. This code is common for both the bands. + if((true == psessionEntry->htCapability) && + (true == pStaDs->mlmStaContext.htCapability)) + { + if(!pStaDs->htGreenfield) + { + limEnableHTNonGfProtection(pMac, true, false, pBeaconParams, psessionEntry); + gfSupported = eHAL_CLEAR; + } + //Station joining is HT 20Mhz + if((eHT_CHANNEL_WIDTH_20MHZ == pStaDs->htSupportedChannelWidthSet)&& + (eHT_CHANNEL_WIDTH_20MHZ != psessionEntry->htSupportedChannelWidthSet)) + { + protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_HT20; + limEnableHT20Protection(pMac, true, false, pBeaconParams, psessionEntry); + } + //Station joining does not support LSIG TXOP Protection + if(!pStaDs->htLsigTXOPProtection) + { + limEnableHTLsigTxopProtection(pMac, false, false, pBeaconParams,psessionEntry); + lsigTxopSupported = eHAL_CLEAR; + } + } + + limUpdateProtStaParams(pMac, peerMacAddr, protStaCacheType, + gfSupported, lsigTxopSupported, psessionEntry); + + return; +} + + +/** ------------------------------------------------------------- +\fn limEnableOverlap11gProtection +\brief wrapper function for setting overlap 11g protection. +\param tpAniSirGlobal pMac +\param tpUpdateBeaconParams pBeaconParams +\param tpSirMacMgmtHdr pMh +\return None + -------------------------------------------------------------*/ +void +limEnableOverlap11gProtection(tpAniSirGlobal pMac, +tpUpdateBeaconParams pBeaconParams, tpSirMacMgmtHdr pMh,tpPESession psessionEntry) +{ + limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOlbcParams)); + + if (psessionEntry->gLimOlbcParams.numSta && + !psessionEntry->gLimOlbcParams.protectionEnabled) + { + // enable protection + PELOG1(limLog(pMac, LOG1, FL("OLBC happens!!!"));) + limEnable11gProtection(pMac, true, true, pBeaconParams,psessionEntry); + } +} + + +/** ------------------------------------------------------------- +\fn limUpdateShortPreamble +\brief Updates short preamble if needed when a new station joins. +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +void +limUpdateShortPreamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + tANI_U16 tmpAid; + tpDphHashNode pStaDs; + tANI_U32 phyMode; + tANI_U16 i; + + // check whether to enable protection or not + pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable); + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + if (pStaDs != NULL && phyMode == WNI_CFG_PHY_MODE_11G) + + { + if (pStaDs->shortPreambleEnabled == eHAL_CLEAR) + { + PELOG1(limLog(pMac,LOG1,FL("Short Preamble is not enabled in Assoc Req from ")); + limPrintMacAddr(pMac, peerMacAddr, LOG1);) + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(psessionEntry) && + psessionEntry->gLimNoShortParams.staNoShortCache[i].active) { + if (vos_mem_compare( + psessionEntry->gLimNoShortParams.staNoShortCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) + return; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + if (pMac->lim.gLimNoShortParams.staNoShortCache[i].active) { + if (vos_mem_compare( + pMac->lim.gLimNoShortParams.staNoShortCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) + return; + } + } + } + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->gLimNoShortParams.staNoShortCache[i].active) + break; + else { + if (!pMac->lim.gLimNoShortParams.staNoShortCache[i].active) + break; + } + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) { + if (LIM_IS_AP_ROLE(psessionEntry)) { + limLog(pMac, LOGE, FL("No space in Short cache (#active %d, #sta %d) for sta "), + i, psessionEntry->gLimNoShortParams.numNonShortPreambleSta); + limPrintMacAddr(pMac, peerMacAddr, LOGE); + return; + } else { + limLog(pMac, LOGE, FL("No space in Short cache (#active %d, #sta %d) for sta "), + i, pMac->lim.gLimNoShortParams.numNonShortPreambleSta); + limPrintMacAddr(pMac, peerMacAddr, LOGE); + return; + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + vos_mem_copy(psessionEntry->gLimNoShortParams.staNoShortCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr)); + psessionEntry->gLimNoShortParams.staNoShortCache[i].active = true; + psessionEntry->gLimNoShortParams.numNonShortPreambleSta++; + } else { + vos_mem_copy(pMac->lim.gLimNoShortParams.staNoShortCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr)); + pMac->lim.gLimNoShortParams.staNoShortCache[i].active = true; + pMac->lim.gLimNoShortParams.numNonShortPreambleSta++; + } + + + // enable long preamble + PELOG1(limLog(pMac, LOG1, FL("Disabling short preamble"));) + + if (limEnableShortPreamble(pMac, false, pBeaconParams, psessionEntry) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("Cannot enable long preamble"));) + } + } +} + +/** ------------------------------------------------------------- +\fn limUpdateShortSlotTime +\brief Updates short slot time if needed when a new station joins. +\param tpAniSirGlobal pMac +\param tSirMacAddr peerMacAddr +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ + +void +limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + tANI_U16 tmpAid; + tpDphHashNode pStaDs; + tANI_U32 phyMode; + tANI_U32 val; + tANI_U16 i; + + // check whether to enable protection or not + pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable); + limGetPhyMode(pMac, &phyMode, psessionEntry); + + /* Only in case of softap in 11g mode, slot time might change depending on the STA being added. In 11a case, it should + * be always 1 and in 11b case, it should be always 0 + */ + if (pStaDs != NULL && phyMode == WNI_CFG_PHY_MODE_11G) + { + /* Only when the new STA has short slot time disabled, we need to change softap's overall slot time settings + * else the default for softap is always short slot enabled. When the last long slot STA leaves softAP, we take care of + * it in limDecideShortSlot + */ + if (pStaDs->shortSlotTimeEnabled == eHAL_CLEAR) + { + PELOG1(limLog(pMac, LOG1, FL("Short Slot Time is not enabled in Assoc Req from ")); + limPrintMacAddr(pMac, peerMacAddr, LOG1);) + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) + { + if (LIM_IS_AP_ROLE(psessionEntry) && + psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active) { + if (vos_mem_compare( + psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) + return; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + if (pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active) + { + if (vos_mem_compare( + pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) + return; + } + } + } + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active) + break; + else { + if (!pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active) + break; + } + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) { + if (LIM_IS_AP_ROLE(psessionEntry)) { + limLog(pMac, LOGE, FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "), + i, psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta); + limPrintMacAddr(pMac, peerMacAddr, LOGE); + return; + } else { + limLog(pMac, LOGE, FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "), + i, pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta); + limPrintMacAddr(pMac, peerMacAddr, LOGE); + return; + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + vos_mem_copy(psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr)); + psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active = true; + psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta++; + } else { + vos_mem_copy( pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr)); + pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active = true; + pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta++; + } + wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val); + + /* Here we check if we are AP role and short slot enabled (both admin and oper modes) but we have atleast one STA connected with + * only long slot enabled, we need to change our beacon/pb rsp to broadcast short slot disabled + */ + if ((LIM_IS_AP_ROLE(psessionEntry)) && (val && + psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta && + psessionEntry->shortSlotTimeSupported)) { + // enable long slot time + pBeaconParams->fShortSlotTime = false; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; + PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));) + psessionEntry->shortSlotTimeSupported = false; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + if (val && pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta && + psessionEntry->shortSlotTimeSupported) { + // enable long slot time + pBeaconParams->fShortSlotTime = false; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; + PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));) + psessionEntry->shortSlotTimeSupported = false; + } + } + } + } +} + + +/** ------------------------------------------------------------- +\fn limDecideStaProtectionOnAssoc +\brief Decide protection related settings on Sta while association. +\param tpAniSirGlobal pMac +\param tpSchBeaconStruct pBeaconStruct +\return None + -------------------------------------------------------------*/ +void +limDecideStaProtectionOnAssoc(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeaconStruct, tpPESession psessionEntry) +{ + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + tANI_U32 phyMode = WNI_CFG_PHY_MODE_NONE; + + limGetRfBand(pMac, &rfBand, psessionEntry); + limGetPhyMode(pMac, &phyMode, psessionEntry); + + if(SIR_BAND_5_GHZ == rfBand) + { + if((eSIR_HT_OP_MODE_MIXED == pBeaconStruct->HTInfo.opMode) || + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == pBeaconStruct->HTInfo.opMode)) + { + if(pMac->lim.cfgProtection.fromlla) + psessionEntry->beaconParams.llaCoexist = true; + } + else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pBeaconStruct->HTInfo.opMode) + { + if(pMac->lim.cfgProtection.ht20) + psessionEntry->beaconParams.ht20Coexist = true; + } + + } + else if(SIR_BAND_2_4_GHZ == rfBand) + { + //spec 7.3.2.13 + //UseProtection will be set when nonERP STA is associated. + //NonERPPresent bit will be set when: + //--nonERP Sta is associated OR + //--nonERP Sta exists in overlapping BSS + //when useProtection is not set then protection from nonERP stations is optional. + + //CFG protection from 11b is enabled and + //11B device in the BSS + /* TODO, This is not sessionized */ + if (phyMode != WNI_CFG_PHY_MODE_11B) + { + if (pMac->lim.cfgProtection.fromllb && + pBeaconStruct->erpPresent && + (pBeaconStruct->erpIEInfo.useProtection || + pBeaconStruct->erpIEInfo.nonErpPresent)) + { + psessionEntry->beaconParams.llbCoexist = true; + } + //AP has no 11b station associated. + else + { + psessionEntry->beaconParams.llbCoexist = false; + } + } + //following code block is only for HT station. + if((psessionEntry->htCapability) && + (pBeaconStruct->HTInfo.present)) + { + tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo; + + //Obss Non HT STA present mode + psessionEntry->beaconParams.gHTObssMode = (tANI_U8)htInfo.obssNonHTStaPresent; + + + //CFG protection from 11G is enabled and + //our AP has at least one 11G station associated. + if(pMac->lim.cfgProtection.fromllg && + ((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) || + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode))&& + (!psessionEntry->beaconParams.llbCoexist)) + { + if(pMac->lim.cfgProtection.fromllg) + psessionEntry->beaconParams.llgCoexist = true; + } + + //AP has only HT stations associated and at least one station is HT 20 + //disable protection from any non-HT devices. + //decision for disabling protection from 11b has already been taken above. + if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == htInfo.opMode) + { + //Disable protection from 11G station. + psessionEntry->beaconParams.llgCoexist = false; + //CFG protection from HT 20 is enabled. + if(pMac->lim.cfgProtection.ht20) + psessionEntry->beaconParams.ht20Coexist = true; + } + //Disable protection from non-HT and HT20 devices. + //decision for disabling protection from 11b has already been taken above. + if(eSIR_HT_OP_MODE_PURE == htInfo.opMode) + { + psessionEntry->beaconParams.llgCoexist = false; + psessionEntry->beaconParams.ht20Coexist = false; + } + + } + } + + //protection related factors other than HT operating mode. Applies to 2.4 GHZ as well as 5 GHZ. + if((psessionEntry->htCapability) && + (pBeaconStruct->HTInfo.present)) + { + tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo; + psessionEntry->beaconParams.fRIFSMode = + ( tANI_U8 ) htInfo.rifsMode; + psessionEntry->beaconParams.llnNonGFCoexist = + ( tANI_U8 )htInfo.nonGFDevicesPresent; + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = + ( tANI_U8 )htInfo.lsigTXOPProtectionFullSupport; + } +} + + +/** ------------------------------------------------------------- +\fn limDecideStaProtection +\brief Decides protection related settings on Sta while processing beacon. +\param tpAniSirGlobal pMac +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +void +limDecideStaProtection(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeaconStruct, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + tANI_U32 phyMode = WNI_CFG_PHY_MODE_NONE; + + limGetRfBand(pMac, &rfBand, psessionEntry); + limGetPhyMode(pMac, &phyMode, psessionEntry); + + if(SIR_BAND_5_GHZ == rfBand) + { + //we are HT capable. + if((true == psessionEntry->htCapability) && + (pBeaconStruct->HTInfo.present)) + { + //we are HT capable, AP's HT OPMode is mixed / overlap legacy ==> need protection from 11A. + if((eSIR_HT_OP_MODE_MIXED == pBeaconStruct->HTInfo.opMode) || + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == pBeaconStruct->HTInfo.opMode)) + { + limEnable11aProtection(pMac, true, false, pBeaconParams,psessionEntry); + } + //we are HT capable, AP's HT OPMode is HT20 ==> disable protection from 11A if enabled. enabled + //protection from HT20 if needed. + else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT== pBeaconStruct->HTInfo.opMode) + { + limEnable11aProtection(pMac, false, false, pBeaconParams,psessionEntry); + limEnableHT20Protection(pMac, true, false, pBeaconParams,psessionEntry); + } + else if(eSIR_HT_OP_MODE_PURE == pBeaconStruct->HTInfo.opMode) + { + limEnable11aProtection(pMac, false, false, pBeaconParams,psessionEntry); + limEnableHT20Protection(pMac, false, false, pBeaconParams,psessionEntry); + } + } + } + else if(SIR_BAND_2_4_GHZ == rfBand) + { + /* spec 7.3.2.13 + * UseProtection will be set when nonERP STA is associated. + * NonERPPresent bit will be set when: + * --nonERP Sta is associated OR + * --nonERP Sta exists in overlapping BSS + * when useProtection is not set then protection from nonERP stations is optional. + */ + + if (phyMode != WNI_CFG_PHY_MODE_11B) + { + if (pBeaconStruct->erpPresent && + (pBeaconStruct->erpIEInfo.useProtection || + pBeaconStruct->erpIEInfo.nonErpPresent)) + { + limEnable11gProtection(pMac, true, false, pBeaconParams, psessionEntry); + } + //AP has no 11b station associated. + else + { + //disable protection from 11b station + limEnable11gProtection(pMac, false, false, pBeaconParams, psessionEntry); + } + } + + //following code block is only for HT station. + if((psessionEntry->htCapability) && + (pBeaconStruct->HTInfo.present)) + { + + tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo; + //AP has at least one 11G station associated. + if(((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) || + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode))&& + (!psessionEntry->beaconParams.llbCoexist)) + { + limEnableHtProtectionFrom11g(pMac, true, false, pBeaconParams,psessionEntry); + + } + + //no HT operating mode change ==> no change in protection settings except for MIXED_MODE/Legacy Mode. + //in Mixed mode/legacy Mode even if there is no change in HT operating mode, there might be change in 11bCoexist + //or 11gCoexist. that is why this check is being done after mixed/legacy mode check. + if ( pMac->lim.gHTOperMode != ( tSirMacHTOperatingMode )htInfo.opMode ) + { + pMac->lim.gHTOperMode = ( tSirMacHTOperatingMode )htInfo.opMode; + + //AP has only HT stations associated and at least one station is HT 20 + //disable protection from any non-HT devices. + //decision for disabling protection from 11b has already been taken above. + if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == htInfo.opMode) + { + //Disable protection from 11G station. + limEnableHtProtectionFrom11g(pMac, false, false, pBeaconParams,psessionEntry); + + limEnableHT20Protection(pMac, true, false, pBeaconParams,psessionEntry); + } + //Disable protection from non-HT and HT20 devices. + //decision for disabling protection from 11b has already been taken above. + else if(eSIR_HT_OP_MODE_PURE == htInfo.opMode) + { + limEnableHtProtectionFrom11g(pMac, false, false, pBeaconParams,psessionEntry); + limEnableHT20Protection(pMac, false, false, pBeaconParams,psessionEntry); + + } + } + } + } + + //following code block is only for HT station. ( 2.4 GHZ as well as 5 GHZ) + if((psessionEntry->htCapability) && + (pBeaconStruct->HTInfo.present)) + { + tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo; + //Check for changes in protection related factors other than HT operating mode. + //Check for changes in RIFS mode, nonGFDevicesPresent, lsigTXOPProtectionFullSupport. + if ( psessionEntry->beaconParams.fRIFSMode != + ( tANI_U8 ) htInfo.rifsMode ) + { + pBeaconParams->fRIFSMode = + psessionEntry->beaconParams.fRIFSMode = + ( tANI_U8 ) htInfo.rifsMode; + pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; + } + + if ( psessionEntry->beaconParams.llnNonGFCoexist != + htInfo.nonGFDevicesPresent ) + { + pBeaconParams->llnNonGFCoexist = + psessionEntry->beaconParams.llnNonGFCoexist = + ( tANI_U8 )htInfo.nonGFDevicesPresent; + pBeaconParams->paramChangeBitmap |= + PARAM_NON_GF_DEVICES_PRESENT_CHANGED; + } + + if ( psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport != + ( tANI_U8 )htInfo.lsigTXOPProtectionFullSupport ) + { + pBeaconParams->fLsigTXOPProtectionFullSupport = + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = + ( tANI_U8 )htInfo.lsigTXOPProtectionFullSupport; + pBeaconParams->paramChangeBitmap |= + PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; + } + + // For Station just update the global lim variable, no need to send message to HAL + // Station already taking care of HT OPR Mode=01, meaning AP is seeing legacy + //stations in overlapping BSS. + if ( psessionEntry->beaconParams.gHTObssMode != ( tANI_U8 )htInfo.obssNonHTStaPresent ) + psessionEntry->beaconParams.gHTObssMode = ( tANI_U8 )htInfo.obssNonHTStaPresent ; + + } +} + + +/** + * limProcessChannelSwitchTimeout() + * + *FUNCTION: + * This function is invoked when Channel Switch Timer expires at + * the STA. Now, STA must stop traffic, and then change/disable + * primary or secondary channel. + * + * + *NOTE: + * @param pMac - Pointer to Global MAC structure + * @return None + */ +void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry = NULL; + tANI_U8 channel; // This is received and stored from channelSwitch Action frame + tANI_U8 isSessionPowerActive = false; + + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if (!LIM_IS_STA_ROLE(psessionEntry)) { + PELOGW(limLog(pMac, LOGW, + "Channel switch can be done only in STA role, Current Role = %d", + GET_LIM_SYSTEM_ROLE(psessionEntry));) + return; + } + + if(pMac->psOffloadEnabled) + { + isSessionPowerActive = pmmPsOffloadIsActive(pMac, psessionEntry); + } + else + { + isSessionPowerActive = limIsSystemInActiveState(pMac); + } + + channel = psessionEntry->gLimChannelSwitch.primaryChannel; + + /* + * This potentially can create issues if the function tries to set + * channel while device is in power-save, hence putting an extra check + * to verify if the device is in power-save or not + */ + if(!isSessionPowerActive) + { + PELOGW(limLog(pMac, LOGW, FL("Device is not in active state, cannot switch channel"));) + return; + } + + // Restore Channel Switch parameters to default + psessionEntry->gLimChannelSwitch.switchTimeoutValue = 0; + + /* Channel-switch timeout has occurred. reset the state */ + psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_END; + + /* + * If Lim allows Switch channel on same channel on which preauth + * is going on then LIM will not post resume link(WDA_FINISH_SCAN) + * during preauth rsp handling hence firmware may crash on ENTER/ + * EXIT BMPS request. + */ + if(psessionEntry->ftPEContext.pFTPreAuthReq) + { + limLog(pMac, LOGE, + FL("Avoid Switch Channel req during pre auth")); + return; + } + /* If link is already suspended mean some off + * channel operation or scan is in progress, Allowing + * Change channel here will lead to either Init Scan + * sent twice or missing Finish scan when change + * channel is completed, this may lead + * to driver in invalid state and crash. + */ + if (limIsLinkSuspended(pMac)) + { + limLog(pMac, LOGE, FL("Link is already suspended for " + "some other reason. Return here for sessionId:%d"), + pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId); + return; + } + + /* Check if the AP is switching to a channel that we support. + * Else, just don't bother to switch. Indicate HDD to look for a + * better AP to associate + */ + if(!limIsChannelValidForChannelSwitch(pMac, channel)) + { + /* We need to restore pre-channelSwitch state on the STA */ + if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); + return; + } + + /* If the channel-list that AP is asking us to switch is invalid, + * then we cannot switch the channel. Just disassociate from AP. + * We will find a better AP !!! + */ + limTearDownLinkWithAp(pMac, + pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId, + eSIR_MAC_UNSPEC_FAILURE_REASON); + return; + } + limCovertChannelScanType(pMac, psessionEntry->currentOperChannel, false); + pMac->lim.dfschannelList.timeStamp[psessionEntry->currentOperChannel] = 0; + switch(psessionEntry->gLimChannelSwitch.state) + { + case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY: + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY "));) + limSwitchPrimaryChannel(pMac, psessionEntry->gLimChannelSwitch.primaryChannel,psessionEntry); + psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; + break; + + case eLIM_CHANNEL_SWITCH_SECONDARY_ONLY: + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_SECONDARY_ONLY "));) + limSwitchPrimarySecondaryChannel(pMac, psessionEntry, + psessionEntry->currentOperChannel, + psessionEntry->gLimChannelSwitch.secondarySubBand); + psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; + break; + + case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY: + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY"));) + limSwitchPrimarySecondaryChannel(pMac, psessionEntry, + psessionEntry->gLimChannelSwitch.primaryChannel, + psessionEntry->gLimChannelSwitch.secondarySubBand); + psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; + break; + + case eLIM_CHANNEL_SWITCH_IDLE: + default: + PELOGE(limLog(pMac, LOGE, FL("incorrect state "));) + if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); + } + return; /* Please note, this is 'return' and not 'break' */ + } +} + +/** + * limUpdateChannelSwitch() + * + *FUNCTION: + * This function is invoked whenever Station receives + * either 802.11h channel switch IE or airgo proprietary + * channel switch IE. + * + *NOTE: + * @param pMac - Pointer to Global MAC structure + * @return tpSirProbeRespBeacon - Pointer to Beacon/Probe Rsp + * @param psessionentry + */ +void +limUpdateChannelSwitch(struct sAniSirGlobal *pMac, tpSirProbeRespBeacon pBeacon, + tpPESession psessionEntry) +{ + tANI_U16 beaconPeriod; + tDot11fIEChanSwitchAnn *pChnlSwitch; +#ifdef WLAN_FEATURE_11AC + tDot11fIEWiderBWChanSwitchAnn *pWiderChnlSwitch; +#endif + + beaconPeriod = psessionEntry->beaconParams.beaconInterval; + + /* 802.11h standard channel switch IE */ + pChnlSwitch = &(pBeacon->channelSwitchIE); + psessionEntry->gLimChannelSwitch.primaryChannel = pChnlSwitch->newChannel; + psessionEntry->gLimChannelSwitch.switchCount = pChnlSwitch->switchCount; + psessionEntry->gLimChannelSwitch.switchTimeoutValue = + SYS_MS_TO_TICKS(beaconPeriod)* (pChnlSwitch->switchCount); + psessionEntry->gLimChannelSwitch.switchMode = pChnlSwitch->switchMode; +#ifdef WLAN_FEATURE_11AC + pWiderChnlSwitch = &(pBeacon->WiderBWChanSwitchAnn); + if (pBeacon->WiderBWChanSwitchAnnPresent) { + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = + pWiderChnlSwitch->newChanWidth; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = + pWiderChnlSwitch->newCenterChanFreq0; + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = + pWiderChnlSwitch->newCenterChanFreq1; + } +#endif + + /* Only primary channel switch element is present */ + psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + psessionEntry->gLimChannelSwitch.secondarySubBand = + PHY_SINGLE_CHANNEL_CENTERED; + + /* Do not bother to look and operate on extended channel switch element + * if our own channel-bonding state is not enabled + */ + if (psessionEntry->htSupportedChannelWidthSet) { + if (pBeacon->sec_chan_offset_present) { + if ((pBeacon->sec_chan_offset.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) || + (pBeacon->sec_chan_offset.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)) { + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + psessionEntry->gLimChannelSwitch.secondarySubBand = + pBeacon->sec_chan_offset.secondaryChannelOffset; + } +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && + pBeacon->WiderBWChanSwitchAnnPresent) { + if (pWiderChnlSwitch->newChanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + if (pBeacon->sec_chan_offset_present) { + if ((pBeacon->sec_chan_offset.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) || + (pBeacon->sec_chan_offset.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)) { + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + psessionEntry->gLimChannelSwitch.secondarySubBand = + limGet11ACPhyCBState(pMac, + psessionEntry->gLimChannelSwitch.primaryChannel, + pBeacon->sec_chan_offset.secondaryChannelOffset, + pWiderChnlSwitch->newCenterChanFreq0, + psessionEntry); + } + } + } + } +#endif + } + } + if (eSIR_SUCCESS != limStartChannelSwitch(pMac, psessionEntry)) { + PELOGW(limLog(pMac, LOGW, FL("Could not start Channel Switch"));) + } + + limLog(pMac, LOGW, + FL("session %d primary chl %d, subband %d, count %d (%d ticks)"), + psessionEntry->peSessionId, + psessionEntry->gLimChannelSwitch.primaryChannel, + psessionEntry->gLimChannelSwitch.secondarySubBand, + psessionEntry->gLimChannelSwitch.switchCount, + psessionEntry->gLimChannelSwitch.switchTimeoutValue); + return; +} + +/** + * limCancelDot11hChannelSwitch + * + *FUNCTION: + * This function is called when STA does not send updated channel-swith IE + * after indicating channel-switch start. This will cancel the channel-swith + * timer which is already running. + * + *LOGIC: + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac - Pointer to Global MAC structure + * + * @return None + */ +void limCancelDot11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (!LIM_IS_STA_ROLE(psessionEntry)) + return; + + PELOGW(limLog(pMac, LOGW, FL("Received a beacon without channel switch IE"));) + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER)); + + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed!"));) + } + + /* We need to restore pre-channelSwitch state on the STA */ + if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system"));) + + } +} + +/**---------------------------------------------- +\fn limCancelDot11hQuiet +\brief Cancel the quieting on Station if latest + beacon doesn't contain quiet IE in it. + +\param pMac +\return NONE +-----------------------------------------------*/ +void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (!LIM_IS_STA_ROLE(psessionEntry)) + return; + + if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != TX_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));) + } + } + else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) != TX_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));) + } + /** + * If the channel switch is already running in silent mode, dont resume the + * transmission. Channel switch timer when timeout, transmission will be resumed. + */ + if(!((psessionEntry->gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) && + (psessionEntry->gLimChannelSwitch.switchMode == eSIR_CHANSW_MODE_SILENT))) + { + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + limRestorePreQuietState(pMac, psessionEntry); + } + } + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; +} + +/** + * limProcessQuietTimeout + * + * FUNCTION: + * This function is active only on the STA. + * Handles SIR_LIM_QUIET_TIMEOUT + * + * LOGIC: + * This timeout can occur under only one circumstance: + * + * 1) When gLimQuietState = eLIM_QUIET_BEGIN + * This indicates that the timeout "interval" has + * expired. This is a trigger for the STA to now + * shut-off Tx/Rx for the specified gLimQuietDuration + * -> The TIMER object gLimQuietBssTimer is + * activated + * -> With timeout = gLimQuietDuration + * -> gLimQuietState is set to eLIM_QUIET_RUNNING + * + * ASSUMPTIONS: + * Using two TIMER objects - + * gLimQuietTimer & gLimQuietBssTimer + * + * NOTE: + * + * @param pMac - Pointer to Global MAC structure + * + * @return None + */ +void limProcessQuietTimeout(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry; + + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietTimer.sessionId))== NULL) + { + limLog(pMac, LOGE,FL("Session Does not exist for given sessionID")); + return; + } + + PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);) + switch( psessionEntry->gLimSpecMgmt.quietState ) + { + case eLIM_QUIET_BEGIN: + // Time to Stop data traffic for quietDuration + //limDeactivateAndChangeTimer(pMac, eLIM_QUIET_BSS_TIMER); + if (TX_SUCCESS != + tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)) + { + limLog( pMac, LOGE, + FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...")); + } + + // gLimQuietDuration appears to be in units of ticks + // Use it as is + if (TX_SUCCESS != + tx_timer_change( &pMac->lim.limTimers.gLimQuietBssTimer, + psessionEntry->gLimSpecMgmt.quietDuration, + 0)) + { + limLog( pMac, LOGE, + FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...")); + } + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, pMac->lim.limTimers.gLimQuietTimer.sessionId, eLIM_QUIET_BSS_TIMER)); + if( TX_SUCCESS != + tx_timer_activate( &pMac->lim.limTimers.gLimQuietBssTimer )) + { + limLog( pMac, LOGW, + FL("Unable to activate gLimQuietBssTimer! The STA will be unable to honor Quiet BSS...")); + } + else + { + // Transition to eLIM_QUIET_RUNNING + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_RUNNING; + + /* If we have sta bk scan triggered and trigger bk scan actually started successfully, */ + /* print message, otherwise, stop data traffic and stay quiet */ + if( pMac->lim.gLimTriggerBackgroundScanDuringQuietBss && + (eSIR_TRUE == (glimTriggerBackgroundScanDuringQuietBss_Status = limTriggerBackgroundScanDuringQuietBss( pMac ))) ) + { + limLog( pMac, LOG2, + FL("Attempting to trigger a background scan...")); + } + else + { + // Shut-off Tx/Rx for gLimSpecMgmt.quietDuration + /* freeze the transmission */ + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_STOP_TX); + + limLog( pMac, LOG2, + FL("Quiet BSS: STA shutting down for %d ticks"), + psessionEntry->gLimSpecMgmt.quietDuration ); + } + } + break; + + case eLIM_QUIET_RUNNING: + case eLIM_QUIET_INIT: + case eLIM_QUIET_END: + default: + // + // As of now, nothing to be done + // + break; + } +} + +/** + * limProcessQuietBssTimeout + * + * FUNCTION: + * This function is active on the AP and STA. + * Handles SIR_LIM_QUIET_BSS_TIMEOUT + * + * LOGIC: + * On the AP - + * When the SIR_LIM_QUIET_BSS_TIMEOUT is triggered, it is + * an indication for the AP to START sending out the + * Quiet BSS IE. + * If 802.11H is enabled, the Quiet BSS IE is sent as per + * the 11H spec + * If 802.11H is not enabled, the Quiet BSS IE is sent as + * a Proprietary IE. + * Transitioning gLimQuietState to eLIM_QUIET_BEGIN will + * initiate the SCH to include the Quiet BSS IE in all + * its subsequent Beacons/PR's. + * The Quiet BSS IE will be included in all the Beacons + * & PR's until the next DTIM period + * + * On the STA - + * When gLimQuietState = eLIM_QUIET_RUNNING + * This indicates that the STA was successfully shut-off + * for the specified gLimQuietDuration. This is a trigger + * for the STA to now resume data traffic. + * -> gLimQuietState is set to eLIM_QUIET_INIT + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac - Pointer to Global MAC structure + * + * @return None + */ +void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) +{ + tpPESession psessionEntry; + + if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietBssTimer.sessionId))== NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);) + if (LIM_IS_AP_ROLE(psessionEntry)) { + } else { + // eLIM_STA_ROLE + switch( psessionEntry->gLimSpecMgmt.quietState ) + { + case eLIM_QUIET_RUNNING: + // Transition to eLIM_QUIET_INIT + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + + if( !pMac->lim.gLimTriggerBackgroundScanDuringQuietBss || (glimTriggerBackgroundScanDuringQuietBss_Status == eSIR_FALSE) ) + { + // Resume data traffic only if channel switch is not running in silent mode. + if (!((psessionEntry->gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) && + (psessionEntry->gLimChannelSwitch.switchMode == eSIR_CHANSW_MODE_SILENT))) + { + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + limRestorePreQuietState(pMac, psessionEntry); + } + + /* Reset status flag */ + if(glimTriggerBackgroundScanDuringQuietBss_Status == eSIR_FALSE) + glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE; + + limLog( pMac, LOG2, + FL("Quiet BSS: Resuming traffic...")); + } + else + { + // + // Nothing specific to be done in this case + // A background scan that was triggered during + // SIR_LIM_QUIET_TIMEOUT will complete on its own + // + limLog( pMac, LOG2, + FL("Background scan should be complete now...")); + } + break; + + case eLIM_QUIET_INIT: + case eLIM_QUIET_BEGIN: + case eLIM_QUIET_END: + PELOG2(limLog(pMac, LOG2, FL("Quiet state not in RUNNING"));) + /* If the quiet period has ended, then resume the frame transmission */ + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + limRestorePreQuietState(pMac, psessionEntry); + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + break; + + default: + // + // As of now, nothing to be done + // + break; + } + } +} + +/**---------------------------------------------- +\fn limStartQuietTimer +\brief Starts the quiet timer. + +\param pMac +\return NONE +-----------------------------------------------*/ +void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tpPESession psessionEntry; + psessionEntry = peFindSessionBySessionId(pMac, sessionId); + + if(psessionEntry == NULL) { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if (!LIM_IS_STA_ROLE(psessionEntry)) + return; + + // First, de-activate Timer, if its already active + limCancelDot11hQuiet(pMac, psessionEntry); + + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, eLIM_QUIET_TIMER)); + if( TX_SUCCESS != tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) + { + limLog( pMac, LOGE, + FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway..." )); + } + + // Set the NEW timeout value, in ticks + if( TX_SUCCESS != tx_timer_change( &pMac->lim.limTimers.gLimQuietTimer, + SYS_MS_TO_TICKS(psessionEntry->gLimSpecMgmt.quietTimeoutValue), 0)) + { + limLog( pMac, LOGE, + FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway..." )); + } + + pMac->lim.limTimers.gLimQuietTimer.sessionId = sessionId; + if( TX_SUCCESS != tx_timer_activate(&pMac->lim.limTimers.gLimQuietTimer)) + { + limLog( pMac, LOGE, + FL("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!")); + limRestorePreQuietState(pMac, psessionEntry); + + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + return; + } +} + + +/** ------------------------------------------------------------------------ **/ +/** + * keep track of the number of ANI peers associated in the BSS + * For the first and last ANI peer, we have to update EDCA params as needed + * + * When the first ANI peer joins the BSS, we notify SCH + * When the last ANI peer leaves the BSS, we notify SCH + */ +void +limUtilCountStaAdd( + tpAniSirGlobal pMac, + tpDphHashNode pSta, + tpPESession psessionEntry) +{ + + if ((! pSta) || (! pSta->valid) || (pSta->fAniCount)) + return; + + pSta->fAniCount = 1; + + if (pMac->lim.gLimNumOfAniSTAs++ != 0) + return; + + // get here only if this is the first ANI peer in the BSS + schEdcaProfileUpdate(pMac, psessionEntry); +} + +void +limUtilCountStaDel( + tpAniSirGlobal pMac, + tpDphHashNode pSta, + tpPESession psessionEntry) +{ + + if ((pSta == NULL) || (! pSta->fAniCount)) + return; + + /* Only if sta is invalid and the validInDummyState bit is set to 1, + * then go ahead and update the count and profiles. This ensures + * that the "number of ani station" count is properly incremented/decremented. + */ + if (pSta->valid == 1) + return; + + pSta->fAniCount = 0; + + if (pMac->lim.gLimNumOfAniSTAs <= 0) + { + limLog(pMac, LOGE, FL("CountStaDel: ignoring Delete Req when AniPeer count is %d"), + pMac->lim.gLimNumOfAniSTAs); + return; + } + + pMac->lim.gLimNumOfAniSTAs--; + + if (pMac->lim.gLimNumOfAniSTAs != 0) + return; + + // get here only if this is the last ANI peer in the BSS + schEdcaProfileUpdate(pMac, psessionEntry); +} + +/** + * limSwitchChannelCback() + * + *FUNCTION: + * This is the callback function registered while requesting to switch channel + * after AP indicates a channel switch for spectrum management (11h). + * + *NOTE: + * @param pMac Pointer to Global MAC structure + * @param status Status of channel switch request + * @param data User data + * @param psessionEntry Session information + * @return NONE + */ +void limSwitchChannelCback(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg = {0}; + tSirSmeSwitchChannelInd *pSirSmeSwitchChInd; + + psessionEntry->currentOperChannel = psessionEntry->currentReqChannel; + + /* We need to restore pre-channelSwitch state on the STA */ + if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); + return; + } + + mmhMsg.type = eWNI_SME_SWITCH_CHL_REQ; + pSirSmeSwitchChInd = vos_mem_malloc(sizeof(tSirSmeSwitchChannelInd)); + if ( NULL == pSirSmeSwitchChInd ) + { + limLog(pMac, LOGP, FL("Failed to allocate buffer for buffer descriptor")); + return; + } + + pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_REQ; + pSirSmeSwitchChInd->length = sizeof(tSirSmeSwitchChannelInd); + pSirSmeSwitchChInd->newChannelId = psessionEntry->gLimChannelSwitch.primaryChannel; + pSirSmeSwitchChInd->sessionId = psessionEntry->smeSessionId; + vos_mem_copy( pSirSmeSwitchChInd->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + mmhMsg.bodyptr = pSirSmeSwitchChInd; + mmhMsg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + + SysProcessMmhMsg(pMac, &mmhMsg); +} + +/** + * limSwitchPrimaryChannel() + * + *FUNCTION: + * This function changes the current operating channel + * and sets the new new channel ID in WNI_CFG_CURRENT_CHANNEL. + * + *NOTE: + * @param pMac Pointer to Global MAC structure + * @param newChannel new channel ID + * @return NONE + */ +void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession psessionEntry) +{ +#if !defined WLAN_FEATURE_VOWIFI + tANI_U32 localPwrConstraint; +#endif + + PELOG3(limLog(pMac, LOG3, FL("limSwitchPrimaryChannel: old chnl %d --> new chnl %d "), + psessionEntry->currentOperChannel, newChannel);) + psessionEntry->currentReqChannel = newChannel; + psessionEntry->limRFBand = limGetRFBand(newChannel); + + psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; + + pMac->lim.gpchangeChannelCallback = limSwitchChannelCback; + pMac->lim.gpchangeChannelData = NULL; + +#if defined WLAN_FEATURE_VOWIFI + limSendSwitchChnlParams(pMac, newChannel, PHY_SINGLE_CHANNEL_CENTERED, + psessionEntry->maxTxPower, + psessionEntry->peSessionId, + VOS_FALSE); +#else + if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) + { + limLog( pMac, LOGP, FL( "Unable to read Local Power Constraint from cfg" )); + return; + } + limSendSwitchChnlParams(pMac, newChannel, PHY_SINGLE_CHANNEL_CENTERED, + (tPowerdBm)localPwrConstraint, + psessionEntry->peSessionId, + VOS_FALSE); +#endif + return; +} + +/** + * limSwitchPrimarySecondaryChannel() + * + *FUNCTION: + * This function changes the primary and secondary channel. + * If 11h is enabled and user provides a "new channel ID" + * that is different from the current operating channel, + * then we must set this new channel in WNI_CFG_CURRENT_CHANNEL, + * assign notify LIM of such change. + * + *NOTE: + * @param pMac Pointer to Global MAC structure + * @param newChannel New channel ID (or current channel ID) + * @param subband CB secondary info: + * - eANI_CB_SECONDARY_NONE + * - eANI_CB_SECONDARY_UP + * - eANI_CB_SECONDARY_DOWN + * @return NONE + */ +void limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 newChannel, ePhyChanBondState subband) +{ +#if !defined WLAN_FEATURE_VOWIFI + tANI_U32 localPwrConstraint; +#endif + +#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" )); + return; + } +#endif + + /* Assign the callback to resume TX once channel is changed */ + psessionEntry->currentReqChannel = newChannel; + psessionEntry->limRFBand = limGetRFBand(newChannel); + + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; + + pMac->lim.gpchangeChannelCallback = limSwitchChannelCback; + pMac->lim.gpchangeChannelData = NULL; + +#if defined WLAN_FEATURE_VOWIFI + limSendSwitchChnlParams(pMac, newChannel, subband, + psessionEntry->maxTxPower, + psessionEntry->peSessionId, + VOS_FALSE); +#else + limSendSwitchChnlParams(pMac, newChannel, subband, + (tPowerdBm)localPwrConstraint, + psessionEntry->peSessionId, + VOS_FALSE); +#endif + + // Store the new primary and secondary channel in session entries if different + if (psessionEntry->currentOperChannel != newChannel) + { + limLog(pMac, LOGW, + FL("switch old chnl %d --> new chnl %d "), + psessionEntry->currentOperChannel, newChannel); + psessionEntry->currentOperChannel = newChannel; + } + if (psessionEntry->htSecondaryChannelOffset != subband) + { + limLog(pMac, LOGW, + FL("switch old sec chnl %d --> new sec chnl %d "), + psessionEntry->htSecondaryChannelOffset, subband); + psessionEntry->htSecondaryChannelOffset = subband; + if (psessionEntry->htSecondaryChannelOffset == PHY_SINGLE_CHANNEL_CENTERED) + { + psessionEntry->htSupportedChannelWidthSet = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + } + else + { + psessionEntry->htSupportedChannelWidthSet = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + } + psessionEntry->htRecommendedTxWidthSet = psessionEntry->htSupportedChannelWidthSet; + } + + return; +} + + +/** + * limActiveScanAllowed() + * + *FUNCTION: + * Checks if active scans are permitted on the given channel + * + *LOGIC: + * The config variable SCAN_CONTROL_LIST contains pairs of (channelNum, activeScanAllowed) + * Need to check if the channelNum matches, then depending on the corresponding + * scan flag, return true (for activeScanAllowed==1) or false (otherwise). + * + *ASSUMPTIONS: + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param channelNum channel number + * @return None + */ + +tANI_U8 limActiveScanAllowed( + tpAniSirGlobal pMac, + tANI_U8 channelNum) +{ + tANI_U32 i; + tANI_U8 channelPair[WNI_CFG_SCAN_CONTROL_LIST_LEN]; + tANI_U32 len = WNI_CFG_SCAN_CONTROL_LIST_LEN; + if (wlan_cfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len) + != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list"));) + return false; + } + + if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) + { + limLog(pMac, LOGE, FL("Invalid scan control list length:%d"), + len); + return false; + } + + for (i=0; (i+1) < len; i+=2) + { + if (channelPair[i] == channelNum) + return ((channelPair[i+1] == eSIR_ACTIVE_SCAN) ? true : false); + } + return false; +} + +/** + * limTriggerBackgroundScanDuringQuietBss() + * + *FUNCTION: + * This function is applicable to the STA only. + * This function is called by limProcessQuietTimeout(), + * when it is time to honor the Quiet BSS IE from the AP. + * + *LOGIC: + * If 11H is enabled: + * We cannot trigger a background scan. The STA needs to + * shut-off Tx/Rx. + * If 11 is not enabled: + * Determine if the next channel that we are going to + * scan is NOT the same channel (or not) on which the + * Quiet BSS was requested. + * If yes, then we cannot trigger a background scan on + * this channel. Return with a false. + * If no, then trigger a background scan. Return with + * a true. + * + *ASSUMPTIONS: + * + *NOTE: + * This API is redundant if the existing API, + * limTriggerBackgroundScan(), were to return a valid + * response instead of returning void. + * If possible, try to revisit this API + * + * @param pMac Pointer to Global MAC structure + * @return eSIR_TRUE, if a background scan was attempted + * eSIR_FALSE, if not + */ +tAniBool limTriggerBackgroundScanDuringQuietBss( tpAniSirGlobal pMac ) +{ + tAniBool bScanTriggered = eSIR_FALSE; + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + if (!LIM_IS_STA_ROLE(psessionEntry)) + return bScanTriggered; + + if( !psessionEntry->lim11hEnable ) + { + tSirMacChanNum bgScanChannelList[WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN]; + tANI_U32 len = WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN; + + // Determine the next scan channel + + // Get background scan channel list from CFG + if( eSIR_SUCCESS == wlan_cfgGetStr( pMac, + WNI_CFG_BG_SCAN_CHANNEL_LIST, + (tANI_U8 *) bgScanChannelList, + (tANI_U32 *) &len )) + { + // Ensure that we do not go off scanning on the same + // channel on which the Quiet BSS was requested + if( psessionEntry->currentOperChannel!= + bgScanChannelList[pMac->lim.gLimBackgroundScanChannelId] ) + { + // For now, try and attempt a background scan. It will + // be ideal if this API actually returns a success or + // failure instead of having a void return type + limTriggerBackgroundScan( pMac ); + + bScanTriggered = eSIR_TRUE; + } + else + { + limLog( pMac, LOGW, + FL("The next SCAN channel is the current operating channel on which a Quiet BSS is requested.! A background scan will not be triggered during this Quiet BSS period...")); + } + } + else + { + limLog( pMac, LOGW, + FL("Unable to retrieve WNI_CFG_VALID_CHANNEL_LIST from CFG! A background scan will not be triggered during this Quiet BSS period...")); + } + } + return bScanTriggered; +} + + +/** + * limGetHTCapability() + * + *FUNCTION: + * A utility function that returns the "current HT capability state" for the HT + * capability of interest (as requested in the API) + * + *LOGIC: + * This routine will return with the "current" setting of a requested HT + * capability. This state info could be retrieved from - + * a) CFG (for static entries) + * b) Run time info + * - Dynamic state maintained by LIM + * - Configured at radio init time by SME + * + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param htCap The HT capability being queried + * @return tANI_U8 The current state of the requested HT capability is returned in a + * tANI_U8 variable + */ + +tANI_U8 limGetHTCapability( tpAniSirGlobal pMac, + tANI_U32 htCap, tpPESession psessionEntry) +{ +tANI_U8 retVal = 0; +tANI_U8 *ptr; +tANI_U32 cfgValue; +tSirMacHTCapabilityInfo macHTCapabilityInfo = {0}; +tSirMacExtendedHTCapabilityInfo macExtHTCapabilityInfo = {0}; +tSirMacTxBFCapabilityInfo macTxBFCapabilityInfo = {0}; +tSirMacASCapabilityInfo macASCapabilityInfo = {0}; + + // + // Determine which CFG to read from. Not ALL of the HT + // related CFG's need to be read each time this API is + // accessed + // + if( htCap >= eHT_ANTENNA_SELECTION && + htCap < eHT_SI_GRANULARITY ) + { + /* Get Antenna Selection HT Capabilities */ + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_AS_CAP, &cfgValue )) + cfgValue = 0; + ptr = (tANI_U8 *) &macASCapabilityInfo; + *((tANI_U8 *)ptr) = (tANI_U8) (cfgValue & 0xff); + } + else + { + if( htCap >= eHT_TX_BEAMFORMING && + htCap < eHT_ANTENNA_SELECTION ) + { + // Get Transmit Beam Forming HT Capabilities + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TX_BF_CAP, &cfgValue )) + cfgValue = 0; + ptr = (tANI_U8 *) &macTxBFCapabilityInfo; + *((tANI_U32 *)ptr) = (tANI_U32) (cfgValue); + } + else + { + if( htCap >= eHT_PCO && + htCap < eHT_TX_BEAMFORMING ) + { + // Get Extended HT Capabilities + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_EXT_HT_CAP_INFO, &cfgValue )) + cfgValue = 0; + ptr = (tANI_U8 *) &macExtHTCapabilityInfo; + *((tANI_U16 *)ptr) = (tANI_U16) (cfgValue & 0xffff); + } + else + { + if( htCap < eHT_MAX_RX_AMPDU_FACTOR ) + { + // Get HT Capabilities + if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_HT_CAP_INFO, &cfgValue )) + cfgValue = 0; + ptr = (tANI_U8 *) &macHTCapabilityInfo; + // CR 265282 MDM SoftAP 2.4PL: SoftAP boot up crash in 2.4 PL builds while same WLAN SU is working on 2.1 PL + *ptr++ = cfgValue & 0xff; + *ptr = (cfgValue >> 8) & 0xff; + } + } + } + } + + switch( htCap ) + { + case eHT_LSIG_TXOP_PROTECTION: + retVal = pMac->lim.gHTLsigTXOPProtection; + break; + + case eHT_STBC_CONTROL_FRAME: + retVal = (tANI_U8) macHTCapabilityInfo.stbcControlFrame; + break; + + case eHT_PSMP: + retVal = pMac->lim.gHTPSMPSupport; + break; + + case eHT_DSSS_CCK_MODE_40MHZ: + retVal = pMac->lim.gHTDsssCckRate40MHzSupport; + break; + + case eHT_MAX_AMSDU_LENGTH: + retVal = (tANI_U8) macHTCapabilityInfo.maximalAMSDUsize; + break; + + case eHT_MAX_AMSDU_NUM: + retVal = (tANI_U8) psessionEntry->max_amsdu_num; + break; + + case eHT_DELAYED_BA: + retVal = (tANI_U8) macHTCapabilityInfo.delayedBA; + break; + + case eHT_RX_STBC: + retVal = (tANI_U8) psessionEntry->htConfig.ht_rx_stbc; + break; + + case eHT_TX_STBC: + retVal = (tANI_U8) psessionEntry->htConfig.ht_tx_stbc; + break; + + case eHT_SHORT_GI_40MHZ: + retVal =(tANI_U8) + (psessionEntry->htConfig.ht_sgi)? macHTCapabilityInfo.shortGI40MHz : 0; + break; + + case eHT_SHORT_GI_20MHZ: + retVal = (tANI_U8) + (psessionEntry->htConfig.ht_sgi)? macHTCapabilityInfo.shortGI20MHz : 0; + break; + + case eHT_GREENFIELD: + retVal = (tANI_U8) macHTCapabilityInfo.greenField; + break; + + case eHT_MIMO_POWER_SAVE: + retVal = (tANI_U8) pMac->lim.gHTMIMOPSState; + break; + + case eHT_SUPPORTED_CHANNEL_WIDTH_SET: + retVal = (tANI_U8) psessionEntry->htSupportedChannelWidthSet; + break; + + case eHT_ADVANCED_CODING: + retVal = (tANI_U8) psessionEntry->htConfig.ht_rx_ldpc; + break; + + case eHT_MAX_RX_AMPDU_FACTOR: + retVal = pMac->lim.gHTMaxRxAMpduFactor; + break; + + case eHT_MPDU_DENSITY: + retVal = pMac->lim.gHTAMpduDensity; + break; + + case eHT_PCO: + retVal = (tANI_U8) macExtHTCapabilityInfo.pco; + break; + + case eHT_TRANSITION_TIME: + retVal = (tANI_U8) macExtHTCapabilityInfo.transitionTime; + break; + + case eHT_MCS_FEEDBACK: + retVal = (tANI_U8) macExtHTCapabilityInfo.mcsFeedback; + break; + + case eHT_TX_BEAMFORMING: + retVal = (tANI_U8) macTxBFCapabilityInfo.txBF; + break; + + case eHT_ANTENNA_SELECTION: + retVal = (tANI_U8) macASCapabilityInfo.antennaSelection; + break; + + case eHT_SI_GRANULARITY: + retVal = pMac->lim.gHTServiceIntervalGranularity; + break; + + case eHT_CONTROLLED_ACCESS: + retVal = pMac->lim.gHTControlledAccessOnly; + break; + + case eHT_RIFS_MODE: + retVal = psessionEntry->beaconParams.fRIFSMode; + break; + + case eHT_RECOMMENDED_TX_WIDTH_SET: + retVal = psessionEntry->htRecommendedTxWidthSet; + break; + + case eHT_EXTENSION_CHANNEL_OFFSET: + retVal = psessionEntry->htSecondaryChannelOffset; + break; + + case eHT_OP_MODE: + if (LIM_IS_AP_ROLE(psessionEntry)) + retVal = psessionEntry->htOperMode; + else + retVal = pMac->lim.gHTOperMode; + break; + + case eHT_BASIC_STBC_MCS: + retVal = pMac->lim.gHTSTBCBasicMCS; + break; + + case eHT_DUAL_CTS_PROTECTION: + retVal = pMac->lim.gHTDualCTSProtection; + break; + + case eHT_LSIG_TXOP_PROTECTION_FULL_SUPPORT: + retVal = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport; + break; + + case eHT_PCO_ACTIVE: + retVal = pMac->lim.gHTPCOActive; + break; + + case eHT_PCO_PHASE: + retVal = pMac->lim.gHTPCOPhase; + break; + + default: + break; + } + + return retVal; +} + +void limGetMyMacAddr(tpAniSirGlobal pMac, tANI_U8 *mac) +{ + vos_mem_copy( mac, pMac->lim.gLimMyMacAddr, sizeof(tSirMacAddr)); + return; +} + + + + +/** ------------------------------------------------------------- +\fn limEnable11aProtection +\brief based on config setting enables\disables 11a protection. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + if(NULL == psessionEntry) + { + PELOG3(limLog(pMac, LOG3, FL("psessionEntry is NULL"));) + return eSIR_FAILURE; + } + //overlapping protection configuration check. + if (overlap) { + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + (!psessionEntry->cfgProtection.fromlla)) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from 11a is disabled"));) + return eSIR_SUCCESS; + } + } + + if (enable) + { + //If we are AP and HT capable, we need to set the HT OP mode + //appropriately. + if ((LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (true == psessionEntry->htCapability)) { + if(overlap) + { + pMac->lim.gLimOverlap11aParams.protectionEnabled = true; + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != pMac->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode)) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + else + { + psessionEntry->gLim11aParams.protectionEnabled = true; + if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_MIXED; + psessionEntry->htOperMode = eSIR_HT_OP_MODE_MIXED; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + + } + } + } + + /* This part is common for station as well. */ + if(false == psessionEntry->beaconParams.llaCoexist) + { + PELOG1(limLog(pMac, LOG1, FL(" => protection from 11A Enabled"));) + pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; + } + } + else if (true == psessionEntry->beaconParams.llaCoexist) + { + //for AP role. + //we need to take care of HT OP mode change if needed. + //We need to take care of Overlap cases. + if (LIM_IS_AP_ROLE(psessionEntry)) { + if (overlap) { + //Overlap Legacy protection disabled. + pMac->lim.gLimOverlap11aParams.protectionEnabled = false; + + /* We need to take care of HT OP mode if we are HT AP. */ + if(psessionEntry->htCapability) + { + // no HT op mode change if any of the overlap protection enabled. + if(!(pMac->lim.gLimOverlap11aParams.protectionEnabled || + pMac->lim.gLimOverlapHt20Params.protectionEnabled || + pMac->lim.gLimOverlapNonGfParams.protectionEnabled)) + + { + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode) + { + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + if(psessionEntry->gLimHt20Params.protectionEnabled) + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + else + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + } + else + { + //Disable protection from 11A stations. + psessionEntry->gLim11aParams.protectionEnabled = false; + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + //Check if any other non-HT protection enabled. + //Right now we are in HT OP Mixed mode. + //Change HT op mode appropriately. + + //Change HT OP mode to 01 if any overlap protection enabled + if(pMac->lim.gLimOverlap11aParams.protectionEnabled || + pMac->lim.gLimOverlapHt20Params.protectionEnabled || + pMac->lim.gLimOverlapNonGfParams.protectionEnabled) + + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + else if(psessionEntry->gLimHt20Params.protectionEnabled) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + if(!pMac->lim.gLimOverlap11aParams.protectionEnabled && + !psessionEntry->gLim11aParams.protectionEnabled) + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));) + pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; + } + } + //for station role + else + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));) + pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; + } + } + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limEnable11gProtection +\brief based on config setting enables\disables 11g protection. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ + +tSirRetStatus +limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + //overlapping protection configuration check. + if (overlap) { + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.fromllb) { + // protection disabled. + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) + return eSIR_SUCCESS; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + if(!pMac->lim.cfgProtection.fromllb) { + // protection disabled. + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) + return eSIR_SUCCESS; + } + } + } + + if (enable) + { + //If we are AP and HT capable, we need to set the HT OP mode + //appropriately. + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(overlap) + { + psessionEntry->gLimOlbcParams.protectionEnabled = true; + PELOGE(limLog(pMac, LOG1, FL("protection from olbc is enabled"));) + if(true == psessionEntry->htCapability) + { + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) && + (eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode)) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + } + //CR-263021: OBSS bit is not switching back to 0 after disabling the overlapping legacy BSS + // This fixes issue of OBSS bit not set after 11b, 11g station leaves + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + //Not processing OBSS bit from other APs, as we are already taking care + //of Protection from overlapping BSS based on erp IE or useProtection bit + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams, psessionEntry); + } + } + else + { + psessionEntry->gLim11bParams.protectionEnabled = true; + PELOGE(limLog(pMac, LOG1, FL("protection from 11b is enabled"));) + if(true == psessionEntry->htCapability) + { + if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_MIXED; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + } + }else if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) && + (true == psessionEntry->htCapability)) { + if(overlap) + { + psessionEntry->gLimOlbcParams.protectionEnabled = true; + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != pMac->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode)) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + } + //CR-263021: OBSS bit is not switching back to 0 after disabling the overlapping legacy BSS + // This fixes issue of OBSS bit not set after 11b, 11g station leaves + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + //Not processing OBSS bit from other APs, as we are already taking care + //of Protection from overlapping BSS based on erp IE or useProtection bit + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams, psessionEntry); + } + else + { + psessionEntry->gLim11bParams.protectionEnabled = true; + if(eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_MIXED; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + } + + /* This part is common for station as well. */ + if(false == psessionEntry->beaconParams.llbCoexist) + { + PELOG1(limLog(pMac, LOG1, FL("=> 11G Protection Enabled"));) + pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + } + else if (true == psessionEntry->beaconParams.llbCoexist) + { + //for AP role. + //we need to take care of HT OP mode change if needed. + //We need to take care of Overlap cases. + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(overlap) + { + //Overlap Legacy protection disabled. + psessionEntry->gLimOlbcParams.protectionEnabled = false; + + //We need to take care of HT OP mode if we are HT AP. + if(psessionEntry->htCapability) + { + // no HT op mode change if any of the overlap protection enabled. + if(!(psessionEntry->gLimOverlap11gParams.protectionEnabled || + psessionEntry->gLimOverlapHt20Params.protectionEnabled || + psessionEntry->gLimOverlapNonGfParams.protectionEnabled)) + { + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == psessionEntry->htOperMode) + { + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + if (psessionEntry->gLimHt20Params.protectionEnabled) { + if (eHT_CHANNEL_WIDTH_20MHZ == + psessionEntry->htSupportedChannelWidthSet) + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_PURE; + else + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + } else + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + } + else + { + //Disable protection from 11B stations. + psessionEntry->gLim11bParams.protectionEnabled = false; + PELOGE(limLog(pMac, LOG1, FL("===> 11B Protection Disabled"));) + //Check if any other non-HT protection enabled. + if(!psessionEntry->gLim11gParams.protectionEnabled) + { + //Right now we are in HT OP Mixed mode. + //Change HT op mode appropriately. + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + //Change HT OP mode to 01 if any overlap protection enabled + if(psessionEntry->gLimOlbcParams.protectionEnabled || + psessionEntry->gLimOverlap11gParams.protectionEnabled || + psessionEntry->gLimOverlapHt20Params.protectionEnabled || + psessionEntry->gLimOverlapNonGfParams.protectionEnabled) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + PELOGE(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + else if(psessionEntry->gLimHt20Params.protectionEnabled) + { + if(eHT_CHANNEL_WIDTH_20MHZ == + psessionEntry->htSupportedChannelWidthSet) + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_PURE; + else + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + PELOGE(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + } + if(!psessionEntry->gLimOlbcParams.protectionEnabled && + !psessionEntry->gLim11bParams.protectionEnabled) + { + PELOGE(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) + pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + }else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + if(overlap) + { + //Overlap Legacy protection disabled. + psessionEntry->gLimOlbcParams.protectionEnabled = false; + + /* We need to take care of HT OP mode if we are HT AP. */ + if(psessionEntry->htCapability) + { + // no HT op mode change if any of the overlap protection enabled. + if(!(pMac->lim.gLimOverlap11gParams.protectionEnabled || + pMac->lim.gLimOverlapHt20Params.protectionEnabled || + pMac->lim.gLimOverlapNonGfParams.protectionEnabled)) + + { + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode) + { + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + if(psessionEntry->gLimHt20Params.protectionEnabled) + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + else + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + } + else + { + //Disable protection from 11B stations. + psessionEntry->gLim11bParams.protectionEnabled = false; + //Check if any other non-HT protection enabled. + if(!psessionEntry->gLim11gParams.protectionEnabled) + { + //Right now we are in HT OP Mixed mode. + //Change HT op mode appropriately. + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + //Change HT OP mode to 01 if any overlap protection enabled + if(psessionEntry->gLimOlbcParams.protectionEnabled || + pMac->lim.gLimOverlap11gParams.protectionEnabled || + pMac->lim.gLimOverlapHt20Params.protectionEnabled || + pMac->lim.gLimOverlapNonGfParams.protectionEnabled) + + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + else if(psessionEntry->gLimHt20Params.protectionEnabled) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + } + if(!psessionEntry->gLimOlbcParams.protectionEnabled && + !psessionEntry->gLim11bParams.protectionEnabled) + { + PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) + pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + } + //for station role + else + { + PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) + pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limEnableHtProtectionFrom11g +\brief based on cofig enables\disables protection from 11g. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + if(!psessionEntry->htCapability) + return eSIR_SUCCESS; // protection from 11g is only for HT stations. + + //overlapping protection configuration check. + if (overlap) { + if (LIM_IS_AP_ROLE(psessionEntry) && + (!psessionEntry->cfgProtection.overlapFromllg)) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled"));); + return eSIR_SUCCESS; + } else if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) && + (!pMac->lim.cfgProtection.overlapFromllg)) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled"));); + return eSIR_SUCCESS; + } + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.fromllg) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled"));) + return eSIR_SUCCESS; + } else if(!LIM_IS_AP_ROLE(psessionEntry)) { + if (!pMac->lim.cfgProtection.fromllg) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled"));) + return eSIR_SUCCESS; + } + } + } + + if (enable) { + //If we are AP and HT capable, we need to set the HT OP mode + //appropriately. + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(overlap) + { + psessionEntry->gLimOverlap11gParams.protectionEnabled = true; + //11g exists in overlap BSS. + //need not to change the operating mode to overlap_legacy + //if higher or same protection operating mode is enabled right now. + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) && + (eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode)) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + } + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams, psessionEntry); + } + else + { + //11g is associated to an AP operating in 11n mode. + //Change the HT operating mode to 'mixed mode'. + psessionEntry->gLim11gParams.protectionEnabled = true; + if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_MIXED; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + } else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + if(overlap) + { + pMac->lim.gLimOverlap11gParams.protectionEnabled = true; + //11g exists in overlap BSS. + //need not to change the operating mode to overlap_legacy + //if higher or same protection operating mode is enabled right now. + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != pMac->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode)) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + else + { + //11g is associated to an AP operating in 11n mode. + //Change the HT operating mode to 'mixed mode'. + psessionEntry->gLim11gParams.protectionEnabled = true; + if(eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_MIXED; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + } + + /* This part is common for station as well. */ + if(false == psessionEntry->beaconParams.llgCoexist) + { + pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; + } + else if (true == psessionEntry->gLimOverlap11gParams.protectionEnabled) + { + // As operating mode changed after G station assoc some way to update beacon + // This addresses the issue of mode not changing to - 11 in beacon when OBSS overlap is enabled + //pMac->sch.schObject.fBeaconChanged = 1; + pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; + } + } + else if (true == psessionEntry->beaconParams.llgCoexist) + { + //for AP role. + //we need to take care of HT OP mode change if needed. + //We need to take care of Overlap cases. + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if (overlap) { + //Overlap Legacy protection disabled. + if (psessionEntry->gLim11gParams.numSta == 0) + psessionEntry->gLimOverlap11gParams.protectionEnabled = false; + + // no HT op mode change if any of the overlap protection enabled. + if(!(psessionEntry->gLimOlbcParams.protectionEnabled || + psessionEntry->gLimOverlapHt20Params.protectionEnabled || + psessionEntry->gLimOverlapNonGfParams.protectionEnabled)) + { + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == psessionEntry->htOperMode) + { + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + if(psessionEntry->gLimHt20Params.protectionEnabled){ + if(eHT_CHANNEL_WIDTH_20MHZ == + psessionEntry->htSupportedChannelWidthSet) + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_PURE; + else + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + } + else + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + else + { + //Disable protection from 11G stations. + psessionEntry->gLim11gParams.protectionEnabled = false; + //Check if any other non-HT protection enabled. + if(!psessionEntry->gLim11bParams.protectionEnabled) + { + + //Right now we are in HT OP Mixed mode. + //Change HT op mode appropriately. + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + //Change HT OP mode to 01 if any overlap protection enabled + if(psessionEntry->gLimOlbcParams.protectionEnabled || + psessionEntry->gLimOverlap11gParams.protectionEnabled || + psessionEntry->gLimOverlapHt20Params.protectionEnabled || + psessionEntry->gLimOverlapNonGfParams.protectionEnabled) + + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + else if(psessionEntry->gLimHt20Params.protectionEnabled) + { + if(eHT_CHANNEL_WIDTH_20MHZ == + psessionEntry->htSupportedChannelWidthSet) + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_PURE; + else + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + } + if(!psessionEntry->gLimOverlap11gParams.protectionEnabled && + !psessionEntry->gLim11gParams.protectionEnabled) + { + limLog(pMac, LOG1, FL("===> Protection from 11G Disabled")); + pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; + } + } else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + if(overlap) + { + //Overlap Legacy protection disabled. + pMac->lim.gLimOverlap11gParams.protectionEnabled = false; + + // no HT op mode change if any of the overlap protection enabled. + if(!(psessionEntry->gLimOlbcParams.protectionEnabled || + psessionEntry->gLimOverlapHt20Params.protectionEnabled || + psessionEntry->gLimOverlapNonGfParams.protectionEnabled)) + { + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode) + { + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + if(psessionEntry->gLimHt20Params.protectionEnabled) + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + else + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + else + { + //Disable protection from 11G stations. + psessionEntry->gLim11gParams.protectionEnabled = false; + //Check if any other non-HT protection enabled. + if(!psessionEntry->gLim11bParams.protectionEnabled) + { + + //Right now we are in HT OP Mixed mode. + //Change HT op mode appropriately. + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + + //Change HT OP mode to 01 if any overlap protection enabled + if(psessionEntry->gLimOlbcParams.protectionEnabled || + pMac->lim.gLimOverlap11gParams.protectionEnabled || + pMac->lim.gLimOverlapHt20Params.protectionEnabled || + pMac->lim.gLimOverlapNonGfParams.protectionEnabled) + + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + else if(psessionEntry->gLimHt20Params.protectionEnabled) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + } + if(!pMac->lim.gLimOverlap11gParams.protectionEnabled && + !psessionEntry->gLim11gParams.protectionEnabled) + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) + pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; + } + } + //for station role + else + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) + pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; + } + } + return eSIR_SUCCESS; +} +//FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. +//This check will be done at the caller. + +/** ------------------------------------------------------------- +\fn limEnableHtObssProtection +\brief based on cofig enables\disables obss protection. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + + + if(!psessionEntry->htCapability) + return eSIR_SUCCESS; // this protection is only for HT stations. + + //overlapping protection configuration check. + if(overlap) + { + //overlapping protection configuration check. + } + else + { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.obss) { //ToDo Update this field + // protection disabled. + PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled"));) + return eSIR_SUCCESS; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + if (!pMac->lim.cfgProtection.obss) { //ToDo Update this field + // protection disabled. + PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled"));) + return eSIR_SUCCESS; + } + } + } + + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) ) + { + PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled"));) + psessionEntry->beaconParams.gHTObssMode = true; + pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; // UPDATE AN ENUM FOR OBSS MODE + + } + else if (!enable && (true == psessionEntry->beaconParams.gHTObssMode)) + { + PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled"));) + psessionEntry->beaconParams.gHTObssMode = false; + pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; + + } +//CR-263021: OBSS bit is not switching back to 0 after disabling the overlapping legacy BSS + if (!enable && !overlap) + { + psessionEntry->gLimOverlap11gParams.protectionEnabled = false; + } + } else + { + if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) ) + { + PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled"));) + psessionEntry->beaconParams.gHTObssMode = true; + pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; // UPDATE AN ENUM FOR OBSS MODE + + } + else if (!enable && (true == psessionEntry->beaconParams.gHTObssMode)) + { + + PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled"));) + psessionEntry->beaconParams.gHTObssMode = false; + pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; + + } + } + return eSIR_SUCCESS; +} +/** ------------------------------------------------------------- +\fn limEnableHT20Protection +\brief based on cofig enables\disables protection from Ht20. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + if(!psessionEntry->htCapability) + return eSIR_SUCCESS; // this protection is only for HT stations. + + //overlapping protection configuration check. + if(overlap) { + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.ht20) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));) + return eSIR_SUCCESS; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + if (!pMac->lim.cfgProtection.ht20) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));) + return eSIR_SUCCESS; + } + } + } + + if (enable) { + //If we are AP and HT capable, we need to set the HT OP mode + //appropriately. + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(overlap) + { + psessionEntry->gLimOverlapHt20Params.protectionEnabled = true; + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) && + (eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode)) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + else + { + psessionEntry->gLimHt20Params.protectionEnabled = true; + if(eSIR_HT_OP_MODE_PURE == psessionEntry->htOperMode) + { + if (psessionEntry->htSupportedChannelWidthSet != + eHT_CHANNEL_WIDTH_20MHZ) + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + } else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + if(overlap) + { + pMac->lim.gLimOverlapHt20Params.protectionEnabled = true; + if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != pMac->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode)) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); + } + } + else + { + psessionEntry->gLimHt20Params.protectionEnabled = true; + if(eSIR_HT_OP_MODE_PURE == pMac->lim.gHTOperMode) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + } + + /* This part is common for station as well. */ + if(false == psessionEntry->beaconParams.ht20Coexist) + { + PELOG1(limLog(pMac, LOG1, FL("=> Protection from HT20 Enabled"));) + pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; + } + } + else if (true == psessionEntry->beaconParams.ht20Coexist) + { + //for AP role. + //we need to take care of HT OP mode change if needed. + //We need to take care of Overlap cases. + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(overlap) + { + //Overlap Legacy protection disabled. + psessionEntry->gLimOverlapHt20Params.protectionEnabled = false; + + // no HT op mode change if any of the overlap protection enabled. + if(!(psessionEntry->gLimOlbcParams.protectionEnabled || + psessionEntry->gLimOverlap11gParams.protectionEnabled || + psessionEntry->gLimOverlapHt20Params.protectionEnabled || + psessionEntry->gLimOverlapNonGfParams.protectionEnabled)) + { + + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == psessionEntry->htOperMode) + { + if(psessionEntry->gLimHt20Params.protectionEnabled) + { + if (psessionEntry->htSupportedChannelWidthSet == + eHT_CHANNEL_WIDTH_20MHZ) + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + else + psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + } + else + { + //Disable protection from 11G stations. + psessionEntry->gLimHt20Params.protectionEnabled = false; + + //Change HT op mode appropriately. + if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == psessionEntry->htOperMode) + { + psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));) + pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; + } else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + if(overlap) + { + //Overlap Legacy protection disabled. + pMac->lim.gLimOverlapHt20Params.protectionEnabled = false; + + // no HT op mode change if any of the overlap protection enabled. + if(!(psessionEntry->gLimOlbcParams.protectionEnabled || + pMac->lim.gLimOverlap11gParams.protectionEnabled || + pMac->lim.gLimOverlapHt20Params.protectionEnabled || + pMac->lim.gLimOverlapNonGfParams.protectionEnabled)) + { + + //Check if there is a need to change HT OP mode. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode) + { + if(psessionEntry->gLimHt20Params.protectionEnabled) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + else + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } + } + else + { + //Disable protection from 11G stations. + psessionEntry->gLimHt20Params.protectionEnabled = false; + + //Change HT op mode appropriately. + if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pMac->lim.gHTOperMode) + { + pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); + } + } + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));) + pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; + } + //for station role + else + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT20 Disabled"));) + pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; + } + } + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limEnableHTNonGfProtection +\brief based on cofig enables\disables protection from NonGf. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + if(!psessionEntry->htCapability) + return eSIR_SUCCESS; // this protection is only for HT stations. + + //overlapping protection configuration check. + if(overlap) { + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.nonGf) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));) + return eSIR_SUCCESS; + } else if(!LIM_IS_AP_ROLE(psessionEntry)) { + //normal protection config check + if (!pMac->lim.cfgProtection.nonGf) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));) + return eSIR_SUCCESS; + } + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist)) + { + PELOG1(limLog(pMac, LOG1, FL(" => Protection from non GF Enabled"));) + pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; + } + else if (!enable && (true == psessionEntry->beaconParams.llnNonGFCoexist)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled"));) + pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; + } + } else { + if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist)) + { + PELOG1(limLog(pMac, LOG1, FL(" => Protection from non GF Enabled"));) + pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = true; + pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; + } + else if (!enable && (true == psessionEntry->beaconParams.llnNonGFCoexist)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled"));) + pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; + } + } + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limEnableHTLsigTxopProtection +\brief based on cofig enables\disables LsigTxop protection. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + if(!psessionEntry->htCapability) + return eSIR_SUCCESS; // this protection is only for HT stations. + + //overlapping protection configuration check. + if(overlap) { + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.lsigTxop) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled"));) + return eSIR_SUCCESS; + } else if(!LIM_IS_AP_ROLE(psessionEntry)) { + //normal protection config check + if(!pMac->lim.cfgProtection.lsigTxop) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled"));) + return eSIR_SUCCESS; + } + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((enable) && (false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) + { + PELOG1(limLog(pMac, LOG1, FL(" => Protection from LsigTxop Enabled"));) + pBeaconParams->fLsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = true; + pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; + } + else if (!enable && (true == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled"));) + pBeaconParams->fLsigTXOPProtectionFullSupport= psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = false; + pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; + } + } else { + if ((enable) && (false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) + { + PELOG1(limLog(pMac, LOG1, FL(" => Protection from LsigTxop Enabled"));) + pBeaconParams->fLsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = true; + pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; + } + else if (!enable && (true == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled"));) + pBeaconParams->fLsigTXOPProtectionFullSupport= psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = false; + pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; + } + } + return eSIR_SUCCESS; +} +//FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. +//This check will be done at the caller. +/** ------------------------------------------------------------- +\fn limEnableHtRifsProtection +\brief based on cofig enables\disables Rifs protection. +\param tANI_U8 enable : 1=> enable protection, 0=> disable protection. +\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context. +\param tpUpdateBeaconParams pBeaconParams +\return None + -------------------------------------------------------------*/ +tSirRetStatus +limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, + tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) +{ + if(!psessionEntry->htCapability) + return eSIR_SUCCESS; // this protection is only for HT stations. + + + //overlapping protection configuration check. + if(overlap) { + } else { + //normal protection config check + if (LIM_IS_AP_ROLE(psessionEntry) && + !psessionEntry->cfgProtection.rifs) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled"));) + return eSIR_SUCCESS; + } else if (!LIM_IS_AP_ROLE(psessionEntry)) { + //normal protection config check + if(!pMac->lim.cfgProtection.rifs) { + // protection disabled. + PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled"));) + return eSIR_SUCCESS; + } + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + // Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS + if ((!enable) && (false == psessionEntry->beaconParams.fRIFSMode)) + { + PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled"));) + pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = true; + pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; + } + // Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS + else if (enable && (true == psessionEntry->beaconParams.fRIFSMode)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));) + pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false; + pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; + } + }else + { + // Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS + if ((!enable) && (false == psessionEntry->beaconParams.fRIFSMode)) + { + PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled"));) + pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = true; + pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; + } + // Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS + else if (enable && (true == psessionEntry->beaconParams.fRIFSMode)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));) + pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false; + pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; + } + } + return eSIR_SUCCESS; +} + +// --------------------------------------------------------------------- +/** + * limEnableShortPreamble + * + * FUNCTION: + * Enable/Disable short preamble + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param enable Flag to enable/disable short preamble + * @return None + */ + +tSirRetStatus +limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry) +{ + tANI_U32 val; + + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) + { + /* Could not get short preamble enabled flag from CFG. Log error. */ + limLog(pMac, LOGP, FL("could not retrieve short preamble flag")); + return eSIR_FAILURE; + } + + if (!val) + return eSIR_SUCCESS; + + if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("could not retrieve 11G short preamble switching enabled flag")); + return eSIR_FAILURE; + } + + if (!val) // 11G short preamble switching is disabled. + return eSIR_SUCCESS; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if (enable && (psessionEntry->beaconParams.fShortPreamble == 0)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Enabled"));) + psessionEntry->beaconParams.fShortPreamble = true; + pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED; + } + else if (!enable && (psessionEntry->beaconParams.fShortPreamble == 1)) + { + PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Disabled"));) + psessionEntry->beaconParams.fShortPreamble = false; + pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble; + pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED; + } + } + + return eSIR_SUCCESS; +} + +/** + * limTxComplete + * + * Function: + * This is LIM's very own "TX MGMT frame complete" completion routine. + * + * Logic: + * LIM wants to send a MGMT frame (broadcast or unicast) + * LIM allocates memory using palPktAlloc( ..., **pData, **pPacket ) + * LIM transmits the MGMT frame using the API: + * halTxFrame( ... pPacket, ..., (void *) limTxComplete, pData ) + * HDD, via halTxFrame/DXE, "transfers" the packet over to BMU + * HDD, if it determines that a TX completion routine (in this case + * limTxComplete) has been provided, will invoke this callback + * LIM will try to free the TX MGMT packet that was earlier allocated, in order + * to send this MGMT frame, using the PAL API palPktFree( ... pData, pPacket ) + * + * Assumptions: + * Presently, this is ONLY being used for MGMT frames/packets + * TODO: + * Would it do good for LIM to have some sort of "signature" validation to + * ensure that the pData argument passed in was a buffer that was actually + * allocated by LIM and/or is not corrupted? + * + * Note: FIXME and TODO + * Looks like palPktFree() is interested in pPacket. But, when this completion + * routine is called, only pData is made available to LIM!! + * + * @param void A pointer to pData. Shouldn't it be pPacket?! + * + * @return none + */ +void limTxComplete( tHalHandle hHal, void *pData, v_BOOL_t free) +{ + tpAniSirGlobal pMac; + pMac = (tpAniSirGlobal)hHal; + +#ifdef FIXME_PRIMA + /* the trace logic needs to be fixed for Prima. Refer to CR 306075 */ +#ifdef TRACE_RECORD + { + tpSirMacMgmtHdr mHdr; + v_U8_t *pRxBd; + vos_pkt_t *pVosPkt; + VOS_STATUS vosStatus; + + + + pVosPkt = (vos_pkt_t *)pData; + vosStatus = vos_pkt_peek_data( pVosPkt, 0, (v_PVOID_t *)&pRxBd, WLANHAL_RX_BD_HEADER_SIZE); + + if(VOS_IS_STATUS_SUCCESS(vosStatus)) + { + mHdr = WDA_GET_RX_MAC_HEADER(pRxBd); + + } + } +#endif +#endif + + if (free) + palPktFree( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + (void *) NULL, /* this is ignored and will likely be removed */ + (void *) pData ); /* lim passed in pPacket in pData pointer */ +} + +/** + * \brief This function updates lim global structure, if CB parameters in the BSS + * have changed, and sends an indication to HAL also with the + * updated HT Parameters. + * This function does not detect the change in the primary channel, that is done as part + * of channel Switch IE processing. + * If STA is configured with '20Mhz only' mode, then this function does not do anything + * This function changes the CB mode, only if the self capability is set to '20 as well as 40Mhz' + * + * + * \param pMac Pointer to global MAC structure + * + * \param pRcvdHTInfo Pointer to HT Info IE obtained from a Beacon or + * Probe Response + * + * \param bssIdx BSS Index of the Bss to which Station is associated. + * + * + */ + +void limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac, + tDot11fIEHTInfo *pHTInfo, + tANI_U8 bssIdx, + tpPESession psessionEntry) +{ + ePhyChanBondState secondaryChnlOffset = PHY_SINGLE_CHANNEL_CENTERED; +#if !defined WLAN_FEATURE_VOWIFI + tANI_U32 localPwrConstraint; +#endif + + //If self capability is set to '20Mhz only', then do not change the CB mode. + if( !limGetHTCapability( pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry )) + 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" )); + return; + } +#endif + + if (psessionEntry->ftPEContext.ftPreAuthSession) { + limLog( pMac, LOGE, FL( "FT PREAUTH channel change is in progress")); + return; + } + + /* + * Do not try to switch channel if RoC is in progress. RoC code path uses + * pMac->lim.gpLimRemainOnChanReq to notify the upper layers that the device + * has started listening on the channel requested as part of RoC, if we set + * pMac->lim.gpLimRemainOnChanReq to NULL as we do below then the + * upper layers will think that the channel change is not successful and the + * RoC from the upper layer perspective will never end... + */ + if (pMac->lim.gpLimRemainOnChanReq) + { + limLog(pMac, LOGE, FL( "RoC is in progress")); + return; + } + + if ( psessionEntry->htSecondaryChannelOffset != ( tANI_U8 ) pHTInfo->secondaryChannelOffset || + psessionEntry->htRecommendedTxWidthSet != ( tANI_U8 ) pHTInfo->recommendedTxWidthSet ) + { + psessionEntry->htSecondaryChannelOffset = ( ePhyChanBondState ) pHTInfo->secondaryChannelOffset; + psessionEntry->htRecommendedTxWidthSet = ( tANI_U8 ) pHTInfo->recommendedTxWidthSet; + if ( eHT_CHANNEL_WIDTH_40MHZ == psessionEntry->htRecommendedTxWidthSet ) + secondaryChnlOffset = (ePhyChanBondState)pHTInfo->secondaryChannelOffset; + + // Notify HAL + limLog( pMac, LOGW, FL( "Channel Information in HT IE change" + "d; sending notification to HAL." ) ); + limLog( pMac, LOGW, FL( "Primary Channel: %d, Secondary Chan" + "nel Offset: %d, Channel Width: %d" ), + pHTInfo->primaryChannel, secondaryChnlOffset, + psessionEntry->htRecommendedTxWidthSet ); + psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; + pMac->lim.gpchangeChannelCallback = NULL; + pMac->lim.gpchangeChannelData = NULL; + +#if defined WLAN_FEATURE_VOWIFI + limSendSwitchChnlParams( pMac, ( tANI_U8 ) pHTInfo->primaryChannel, + secondaryChnlOffset, psessionEntry->maxTxPower, + psessionEntry->peSessionId, VOS_TRUE); +#else + limSendSwitchChnlParams( pMac, ( tANI_U8 ) pHTInfo->primaryChannel, + secondaryChnlOffset, + (tPowerdBm)localPwrConstraint, + psessionEntry->peSessionId, VOS_TRUE); +#endif + + //In case of IBSS, if STA should update HT Info IE in its beacons. + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + schSetFixedBeaconFields(pMac, psessionEntry); + } + } +} // End limUpdateStaRunTimeHTParams. + +/** + * \brief This function updates the lim global structure, if any of the + * HT Capabilities have changed. + * + * + * \param pMac Pointer to Global MAC structure + * + * \param pHTCapability Pointer to HT Capability Information Element + * obtained from a Beacon or Probe Response + * + * + * + */ + +void limUpdateStaRunTimeHTCapability( tpAniSirGlobal pMac, + tDot11fIEHTCaps *pHTCaps ) +{ + + if ( pMac->lim.gHTLsigTXOPProtection != ( tANI_U8 ) pHTCaps->lsigTXOPProtection ) + { + pMac->lim.gHTLsigTXOPProtection = ( tANI_U8 ) pHTCaps->lsigTXOPProtection; + // Send change notification to HAL + } + + if ( pMac->lim.gHTAMpduDensity != ( tANI_U8 ) pHTCaps->mpduDensity ) + { + pMac->lim.gHTAMpduDensity = ( tANI_U8 ) pHTCaps->mpduDensity; + // Send change notification to HAL + } + + if ( pMac->lim.gHTMaxRxAMpduFactor != ( tANI_U8 ) pHTCaps->maxRxAMPDUFactor ) + { + pMac->lim.gHTMaxRxAMpduFactor = ( tANI_U8 ) pHTCaps->maxRxAMPDUFactor; + // Send change notification to HAL + } + + +} // End limUpdateStaRunTimeHTCapability. + +/** + * \brief This function updates lim global structure, if any of the HT + * Info Parameters have changed. + * + * + * \param pMac Pointer to the global MAC structure + * + * \param pHTInfo Pointer to the HT Info IE obtained from a Beacon or + * Probe Response + * + * + */ + +void limUpdateStaRunTimeHTInfo( tpAniSirGlobal pMac, + tDot11fIEHTInfo *pHTInfo, tpPESession psessionEntry) +{ + if ( psessionEntry->htRecommendedTxWidthSet != ( tANI_U8 )pHTInfo->recommendedTxWidthSet ) + { + psessionEntry->htRecommendedTxWidthSet = ( tANI_U8 )pHTInfo->recommendedTxWidthSet; + // Send change notification to HAL + } + + if ( psessionEntry->beaconParams.fRIFSMode != ( tANI_U8 )pHTInfo->rifsMode ) + { + psessionEntry->beaconParams.fRIFSMode = ( tANI_U8 )pHTInfo->rifsMode; + // Send change notification to HAL + } + + if ( pMac->lim.gHTServiceIntervalGranularity != ( tANI_U8 )pHTInfo->serviceIntervalGranularity ) + { + pMac->lim.gHTServiceIntervalGranularity = ( tANI_U8 )pHTInfo->serviceIntervalGranularity; + // Send change notification to HAL + } + + if ( pMac->lim.gHTOperMode != ( tSirMacHTOperatingMode )pHTInfo->opMode ) + { + pMac->lim.gHTOperMode = ( tSirMacHTOperatingMode )pHTInfo->opMode; + // Send change notification to HAL + } + + if ( psessionEntry->beaconParams.llnNonGFCoexist != pHTInfo->nonGFDevicesPresent ) + { + psessionEntry->beaconParams.llnNonGFCoexist = ( tANI_U8 )pHTInfo->nonGFDevicesPresent; + } + + if ( pMac->lim.gHTSTBCBasicMCS != ( tANI_U8 )pHTInfo->basicSTBCMCS ) + { + pMac->lim.gHTSTBCBasicMCS = ( tANI_U8 )pHTInfo->basicSTBCMCS; + // Send change notification to HAL + } + + if ( pMac->lim.gHTDualCTSProtection != ( tANI_U8 )pHTInfo->dualCTSProtection ) + { + pMac->lim.gHTDualCTSProtection = ( tANI_U8 )pHTInfo->dualCTSProtection; + // Send change notification to HAL + } + + if ( pMac->lim.gHTSecondaryBeacon != ( tANI_U8 )pHTInfo->secondaryBeacon ) + { + pMac->lim.gHTSecondaryBeacon = ( tANI_U8 )pHTInfo->secondaryBeacon; + // Send change notification to HAL + } + + if ( psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport != ( tANI_U8 )pHTInfo->lsigTXOPProtectionFullSupport ) + { + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = ( tANI_U8 )pHTInfo->lsigTXOPProtectionFullSupport; + // Send change notification to HAL + } + + if ( pMac->lim.gHTPCOActive != ( tANI_U8 )pHTInfo->pcoActive ) + { + pMac->lim.gHTPCOActive = ( tANI_U8 )pHTInfo->pcoActive; + // Send change notification to HAL + } + + if ( pMac->lim.gHTPCOPhase != ( tANI_U8 )pHTInfo->pcoPhase ) + { + pMac->lim.gHTPCOPhase = ( tANI_U8 )pHTInfo->pcoPhase; + // Send change notification to HAL + } + +} // End limUpdateStaRunTimeHTInfo. + + +/** ------------------------------------------------------------- +\fn limProcessHalIndMessages +\brief callback function for HAL indication +\param tpAniSirGlobal pMac +\param tANI_U32 mesgId +\param void *mesgParam +\return tSirRetStatu - status + -------------------------------------------------------------*/ + +tSirRetStatus limProcessHalIndMessages(tpAniSirGlobal pMac, tANI_U32 msgId, void *msgParam ) +{ + //its PE's responsibility to free msgparam when its done extracting the message parameters. + tSirMsgQ msg; + + switch(msgId) + { + case SIR_LIM_DEL_TS_IND: + case SIR_LIM_ADD_BA_IND: + case SIR_LIM_DEL_BA_ALL_IND: + case SIR_LIM_DELETE_STA_CONTEXT_IND: + case SIR_LIM_BEACON_GEN_IND: + msg.type = (tANI_U16) msgId; + msg.bodyptr = msgParam; + msg.bodyval = 0; + break; + + default: + vos_mem_free(msgParam); + limLog(pMac, LOGP, FL("invalid message id = %d received"), msgId); + return eSIR_FAILURE; + } + + if (limPostMsgApi(pMac, &msg) != eSIR_SUCCESS) + { + vos_mem_free(msgParam); + limLog(pMac, LOGP, FL("limPostMsgApi failed for msgid = %d"), msg.type); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limValidateDeltsReq +\brief Validates DelTs req originated by SME or by HAL and also sends halMsg_DelTs to HAL +\param tpAniSirGlobal pMac +\param tpSirDeltsReq pDeltsReq +\param tSirMacAddr peerMacAddr +\return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr peerMacAddr,tpPESession psessionEntry) +{ + tpDphHashNode pSta; + tANI_U8 tsStatus; + tSirMacTSInfo *tsinfo; + tANI_U32 i; + tANI_U8 tspecIdx; + /* if sta + * - verify assoc state + * - del tspec locally + * if ap, + * - verify sta is in assoc state + * - del sta tspec locally + */ + if(pDeltsReq == NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Delete TS request pointer is NULL"));) + return eSIR_FAILURE; + } + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + tANI_U32 val; + + // station always talks to the AP + pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + + val = sizeof(tSirMacAddr); + sirCopyMacAddr(peerMacAddr,psessionEntry->bssId); + + } else { + tANI_U16 assocId; + tANI_U8 *macaddr = (tANI_U8 *) peerMacAddr; + + assocId = pDeltsReq->aid; + if (assocId != 0) + pSta = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); + else + pSta = dphLookupHashEntry(pMac, pDeltsReq->macAddr, &assocId, &psessionEntry->dph.dphHashTable); + + if (pSta != NULL) + // TBD: check sta assoc state as well + for (i =0; i < sizeof(tSirMacAddr); i++) + macaddr[i] = pSta->staAddr[i]; + } + + if (pSta == NULL) + { + PELOGE(limLog(pMac, LOGE, "Cannot find station context for delts req");) + return eSIR_FAILURE; + } + + if ((! pSta->valid) || + (pSta->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) + { + PELOGE(limLog(pMac, LOGE, "Invalid Sta (or state) for DelTsReq");) + return eSIR_FAILURE; + } + + pDeltsReq->req.wsmTspecPresent = 0; + pDeltsReq->req.wmeTspecPresent = 0; + pDeltsReq->req.lleTspecPresent = 0; + + if ((pSta->wsmEnabled) && + (pDeltsReq->req.tspec.tsinfo.traffic.accessPolicy != SIR_MAC_ACCESSPOLICY_EDCA)) + pDeltsReq->req.wsmTspecPresent = 1; + else if (pSta->wmeEnabled) + pDeltsReq->req.wmeTspecPresent = 1; + else if (pSta->lleEnabled) + pDeltsReq->req.lleTspecPresent = 1; + else + { + PELOGW(limLog(pMac, LOGW, FL("DELTS_REQ ignore - qos is disabled"));) + return eSIR_FAILURE; + } + + tsinfo = pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.tsinfo + : &pDeltsReq->req.tsinfo; + PELOG1(limLog(pMac, LOG1, + FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)"), + pDeltsReq->req.wmeTspecPresent, pDeltsReq->req.lleTspecPresent, pDeltsReq->req.wsmTspecPresent, + tsinfo->traffic.tsid, tsinfo->traffic.userPrio, tsinfo->traffic.direction);) + + // if no Access Control, ignore the request + + if (limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx) + != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, "ERROR DELTS request for sta assocId %d (tsid %d, up %d)", + pSta->assocId, tsinfo->traffic.tsid, tsinfo->traffic.userPrio);) + return eSIR_FAILURE; + } + else if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) || + (tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_BOTH)) + { + //edca only now. + } + else + { + if(tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) + { + //send message to HAL to delete TS + if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac, + pSta->staIndex, + tspecIdx, + pDeltsReq->req, + psessionEntry->peSessionId, + psessionEntry->bssId)) + { + limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"), + tsinfo->traffic.userPrio); + return eSIR_FAILURE; + } + } + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn limRegisterHalIndCallBack +\brief registers callback function to HAL for any indication. +\param tpAniSirGlobal pMac +\return none. + -------------------------------------------------------------*/ +void +limRegisterHalIndCallBack(tpAniSirGlobal pMac) +{ + tSirMsgQ msg; + tpHalIndCB pHalCB; + + pHalCB = vos_mem_malloc(sizeof(tHalIndCB)); + if ( NULL == pHalCB ) + { + limLog(pMac, LOGP, FL("AllocateMemory() failed")); + return; + } + + pHalCB->pHalIndCB = limProcessHalIndMessages; + + msg.type = WDA_REGISTER_PE_CALLBACK; + msg.bodyptr = pHalCB; + msg.bodyval = 0; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + vos_mem_free(pHalCB); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg() failed")); + } + + return; +} + + +/** ------------------------------------------------------------- +\fn limProcessAddBaInd + +\brief handles the BA activity check timeout indication coming from HAL. + Validates the request, posts request for sending addBaReq message for every candidate in the list. +\param tpAniSirGlobal pMac +\param tSirMsgQ limMsg +\return None +-------------------------------------------------------------*/ +void +limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tANI_U8 i; + tANI_U8 tid; + tANI_U16 assocId; + tpDphHashNode pSta; + tpAddBaCandidate pBaCandidate; + tANI_U32 baCandidateCnt; + tpBaActivityInd pBaActivityInd; + tpPESession psessionEntry; + tANI_U8 sessionId; +#ifdef FEATURE_WLAN_TDLS + boolean htCapable = FALSE; +#endif + + + if (limMsg->bodyptr == NULL) + return; + + pBaActivityInd = (tpBaActivityInd)limMsg->bodyptr; + baCandidateCnt = pBaActivityInd->baCandidateCnt; + + if ((psessionEntry = peFindSessionByBssid(pMac,pBaActivityInd->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given BSSId")); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + + //if we are not HT capable we don't need to handle BA timeout indication from HAL. +#ifdef FEATURE_WLAN_TDLS + if ((baCandidateCnt > pMac->lim.maxStation)) +#else + if ((baCandidateCnt > pMac->lim.maxStation) || !psessionEntry->htCapability ) +#endif + { + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + +#ifdef FEATURE_WLAN_TDLS + //if we have TDLS peers, we should look at peers HT capability, which can be different than + //AP capability + pBaCandidate = (tpAddBaCandidate) (((tANI_U8*)pBaActivityInd) + sizeof(tBaActivityInd)); + + for (i=0; istaAddr, &assocId, &psessionEntry->dph.dphHashTable); + if ((NULL == pSta) || (!pSta->valid)) + continue; + + if (STA_ENTRY_TDLS_PEER == pSta->staType) + htCapable = pSta->mlmStaContext.htCapability; + else + htCapable = psessionEntry->htCapability; + + if (htCapable) + break; + } + if (!htCapable) + { + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } +#endif + + /* Delete the complete dialogue token linked list */ + limDeleteDialogueTokenList(pMac); + pBaCandidate = (tpAddBaCandidate) (((tANI_U8*)pBaActivityInd) + sizeof(tBaActivityInd)); + + for (i=0; istaAddr, &assocId, &psessionEntry->dph.dphHashTable); + if ((NULL == pSta) || (!pSta->valid)) + continue; + + for (tid=0; tidtcCfg[tid].fUseBATx) && + (pBaCandidate->baInfo[tid].fBaEnable)) + { + limLog(pMac, LOG1, FL("BA setup for staId = %d, TID: %d, SSN: %d"), + pSta->staIndex, tid, pBaCandidate->baInfo[tid].startingSeqNum); + limPostMlmAddBAReq(pMac, pSta, tid, pBaCandidate->baInfo[tid].startingSeqNum,psessionEntry); + } + } + } + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; +} + + +/** ------------------------------------------------------------- +\fn limDeleteBASessions +\brief Deletes all the existing BA sessions for given session + and BA direction. +\param tpAniSirGlobal pMac +\param tpPESession pSessionEntry +\param tANI_U32 baDirection +\return None +-------------------------------------------------------------*/ + +void +limDeleteBASessions(tpAniSirGlobal pMac, tpPESession pSessionEntry, + tANI_U32 baDirection) +{ + tANI_U32 i; + tANI_U8 tid; + tpDphHashNode pSta; + + if (NULL == pSessionEntry) + { + limLog(pMac, LOGE, FL("Session does not exist")); + } + else + { + for(tid = 0; tid < STACFG_MAX_TC; tid++) + { + if (LIM_IS_AP_ROLE(pSessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(pSessionEntry) || + LIM_IS_IBSS_ROLE(pSessionEntry) || + LIM_IS_P2P_DEVICE_GO(pSessionEntry)) { + for (i = 0; i < pMac->lim.maxStation; i++) + { + pSta = pSessionEntry->dph.dphHashTable.pDphNodeArray + i; + if (pSta && pSta->added) + { + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) && + (baDirection & BA_INITIATOR)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) && + (baDirection & BA_RECIPIENT)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + } + } + } else if (LIM_IS_STA_ROLE(pSessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(pSessionEntry) || + LIM_IS_P2P_DEVICE_ROLE(pSessionEntry)) { + pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, + &pSessionEntry->dph.dphHashTable); + if (pSta && pSta->added) + { + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) && + (baDirection & BA_INITIATOR)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) && + (baDirection & BA_RECIPIENT)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + } + } + } + } +} + +/** ------------------------------------------------------------- +\fn limDelAllBASessions +\brief Deletes all the existing BA sessions. +\param tpAniSirGlobal pMac +\return None +-------------------------------------------------------------*/ + +void limDelAllBASessions(tpAniSirGlobal pMac) +{ + tANI_U32 i; + tpPESession pSessionEntry; + + for (i = 0; i < pMac->lim.maxBssId; i++) + { + pSessionEntry = peFindSessionBySessionId(pMac, i); + if (pSessionEntry) + { + limDeleteBASessions(pMac, pSessionEntry, BA_BOTH_DIRECTIONS); + } + } +} + +/** ------------------------------------------------------------- +\fn limDelAllBASessionsBtc +\brief Deletes all the existing BA recipient sessions in 2.4GHz + band. +\param tpAniSirGlobal pMac +\return None +-------------------------------------------------------------*/ + +void limDelPerBssBASessionsBtc(tpAniSirGlobal pMac) +{ + tANI_U8 sessionId; + tpPESession pSessionEntry; + pSessionEntry = peFindSessionByBssid(pMac,pMac->btc.btcBssfordisableaggr, + &sessionId); + if (pSessionEntry) + { + PELOGW(limLog(pMac, LOGW, + "Deleting the BA for session %d as host got BTC event", sessionId);) + limDeleteBASessions(pMac, pSessionEntry, BA_RECIPIENT); + } +} + +/** ------------------------------------------------------------- +\fn limProcessDelTsInd +\brief Handles the DeleteTS indication coming from HAL or generated by + PE itself in some error cases. Validates the request, sends the + DelTs action frame to the Peer and sends DelTs indication to HDD. +\param tpAniSirGlobal pMac +\param tSirMsgQ limMsg +\return None +-------------------------------------------------------------*/ +void +limProcessDelTsInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpDphHashNode pSta; + tpDelTsParams pDelTsParam = (tpDelTsParams) (limMsg->bodyptr); + tpSirDeltsReq pDelTsReq = NULL; + tSirMacAddr peerMacAddr; + tpSirDeltsReqInfo pDelTsReqInfo; + tpLimTspecInfo pTspecInfo; + tpPESession psessionEntry; + tANI_U8 sessionId; + +if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== NULL) + { + limLog(pMac, LOGE,FL("session does not exist for given BssId")); + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + + pTspecInfo = &(pMac->lim.tspecInfo[pDelTsParam->tspecIdx]); + if(pTspecInfo->inuse == false) + { + PELOGE(limLog(pMac, LOGE, FL("tspec entry with index %d is not in use"), pDelTsParam->tspecIdx);) + goto error1; + } + + pSta = dphGetHashEntry(pMac, pTspecInfo->assocId, &psessionEntry->dph.dphHashTable); + if(pSta == NULL) + { + limLog(pMac, LOGE, FL("Could not find entry in DPH table for assocId = %d"), + pTspecInfo->assocId); + goto error1; + } + + pDelTsReq = vos_mem_malloc(sizeof(tSirDeltsReq)); + if ( NULL == pDelTsReq ) + { + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory() failed"));) + goto error1; + } + + vos_mem_set( (tANI_U8 *)pDelTsReq, sizeof(tSirDeltsReq), 0); + + if(pSta->wmeEnabled) + vos_mem_copy( &(pDelTsReq->req.tspec), &(pTspecInfo->tspec), sizeof(tSirMacTspecIE)); + else + vos_mem_copy( &(pDelTsReq->req.tsinfo), &(pTspecInfo->tspec.tsinfo), sizeof(tSirMacTSInfo)); + + + //validate the req + if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDelTsReq, peerMacAddr,psessionEntry)) + { + PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) + goto error2; + } + PELOG1(limLog(pMac, LOG1, "Sent DELTS request to station with " + "assocId = %d MacAddr = "MAC_ADDRESS_STR, + pDelTsReq->aid, MAC_ADDR_ARRAY(peerMacAddr));) + + limSendDeltsReqActionFrame(pMac, peerMacAddr, pDelTsReq->req.wmeTspecPresent, &pDelTsReq->req.tsinfo, &pDelTsReq->req.tspec, + psessionEntry); + + // prepare and send an sme indication to HDD + pDelTsReqInfo = vos_mem_malloc(sizeof(tSirDeltsReqInfo)); + if ( NULL == pDelTsReqInfo ) + { + PELOGE(limLog(pMac, LOGE, FL("AllocateMemory() failed"));) + goto error3; + } + vos_mem_set( (tANI_U8 *)pDelTsReqInfo, sizeof(tSirDeltsReqInfo), 0); + + if(pSta->wmeEnabled) + vos_mem_copy( &(pDelTsReqInfo->tspec), &(pTspecInfo->tspec), sizeof(tSirMacTspecIE)); + else + vos_mem_copy( &(pDelTsReqInfo->tsinfo), &(pTspecInfo->tspec.tsinfo), sizeof(tSirMacTSInfo)); + + limSendSmeDeltsInd(pMac, pDelTsReqInfo, pDelTsReq->aid,psessionEntry); + +error3: + vos_mem_free(pDelTsReqInfo); +error2: + vos_mem_free(pDelTsReq); +error1: + vos_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; +} + +/** + * \brief Setup an A-MPDU/BA session + * + * \sa limPostMlmAddBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pStaDs DPH Hash Node object of peer STA + * + * \param tid TID for which a BA is being setup. + * If this is set to 0xFFFF, then we retrieve + * the default TID from the CFG + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tANI_U8 tid, tANI_U16 startingSeqNum,tpPESession psessionEntry) +{ + tSirRetStatus status = eSIR_SUCCESS; + tpLimMlmAddBAReq pMlmAddBAReq = NULL; + tpDialogueToken dialogueTokenNode; + tANI_U32 val = 0; + + // Allocate for LIM_MLM_ADDBA_REQ + pMlmAddBAReq = vos_mem_malloc(sizeof( tLimMlmAddBAReq )); + if ( NULL == pMlmAddBAReq ) + { + limLog( pMac, LOGP, FL("AllocateMemory failed")); + status = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + vos_mem_set( (void *) pMlmAddBAReq, sizeof( tLimMlmAddBAReq ), 0); + + // Copy the peer MAC + vos_mem_copy( + pMlmAddBAReq->peerMacAddr, + pStaDs->staAddr, + sizeof( tSirMacAddr )); + + // Update the TID + pMlmAddBAReq->baTID = tid; + + // Determine the supported BA policy of local STA + // for the TID of interest + pMlmAddBAReq->baPolicy = (pStaDs->baPolicyFlag >> tid) & 0x1; + + // BA Buffer Size + // Requesting the ADDBA recipient to populate the size. + // If ADDBA is accepted, a non-zero buffer size should + // be returned in the ADDBA Rsp + if ((TRUE == psessionEntry->isCiscoVendorAP) && + (eHT_CHANNEL_WIDTH_80MHZ != pStaDs->htSupportedChannelWidthSet)) + { + /* Cisco AP has issues in receiving more than 25 "mpdu in ampdu" + causing very low throughput in HT40 case */ + limLog( pMac, LOGW, + FL( "Requesting ADDBA with Cisco 1225 AP, window size 25")); + pMlmAddBAReq->baBufferSize = MAX_BA_WINDOW_SIZE_FOR_CISCO; + } + else + pMlmAddBAReq->baBufferSize = 0; + + limLog( pMac, LOGW, + FL( "Requesting an ADDBA to setup a %s BA session with STA %d for TID %d" ), + (pMlmAddBAReq->baPolicy ? "Immediate": "Delayed"), + pStaDs->staIndex, + tid ); + + // BA Timeout + if (wlan_cfgGetInt(pMac, WNI_CFG_BA_TIMEOUT, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("could not retrieve BA TIME OUT Param CFG")); + status = eSIR_FAILURE; + goto returnFailure; + } + pMlmAddBAReq->baTimeout = val; // In TU's + + // ADDBA Failure Timeout + // FIXME_AMPDU - Need to retrieve this from CFG. + //right now we are not checking for response timeout. so this field is dummy just to be compliant with the spec. + pMlmAddBAReq->addBAFailureTimeout = 2000; // In TU's + + // BA Starting Sequence Number + pMlmAddBAReq->baSSN = startingSeqNum; + + /* Update PE session Id*/ + pMlmAddBAReq->sessionId = psessionEntry->peSessionId; + + LIM_SET_STA_BA_STATE(pStaDs, tid, eLIM_BA_STATE_WT_ADD_RSP); + + dialogueTokenNode = limAssignDialogueToken(pMac); + if (NULL == dialogueTokenNode) + { + limLog(pMac, LOGE, FL("could not assign dialogue token")); + status = eSIR_FAILURE; + goto returnFailure; + } + + pMlmAddBAReq->baDialogToken = dialogueTokenNode->token; + //set assocId and tid information in the lim linked list + dialogueTokenNode->assocId = pStaDs->assocId; + dialogueTokenNode->tid = tid; + // Send ADDBA Req to MLME + limPostMlmMessage( pMac, + LIM_MLM_ADDBA_REQ, + (tANI_U32 *) pMlmAddBAReq ); + return eSIR_SUCCESS; + +returnFailure: + vos_mem_free(pMlmAddBAReq); + return status; +} + +/** + * \brief Post LIM_MLM_ADDBA_RSP to MLME. MLME + * will then send an ADDBA Rsp to peer MAC entity + * with the appropriate ADDBA status code + * + * \sa limPostMlmAddBARsp + * + * \param pMac The global tpAniSirGlobal object + * + * \param peerMacAddr MAC address of peer entity that will + * be the recipient of this ADDBA Rsp + * + * \param baStatusCode ADDBA Rsp status code + * + * \param baDialogToken ADDBA Rsp dialog token + * + * \param baTID TID of interest + * + * \param baPolicy The BA policy + * + * \param baBufferSize The BA buffer size + * + * \param baTimeout BA timeout in TU's + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +tSirRetStatus limPostMlmAddBARsp( tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirMacStatusCodes baStatusCode, + tANI_U8 baDialogToken, + tANI_U8 baTID, + tANI_U8 baPolicy, + tANI_U16 baBufferSize, + tANI_U16 baTimeout, + tpPESession psessionEntry) +{ +tSirRetStatus status = eSIR_SUCCESS; +tpLimMlmAddBARsp pMlmAddBARsp; + + // Allocate for LIM_MLM_ADDBA_RSP + pMlmAddBARsp = vos_mem_malloc(sizeof( tLimMlmAddBARsp )); + if ( NULL == pMlmAddBARsp ) + { + limLog( pMac, LOGE, + FL("AllocateMemory failed with error code %d"), + status ); + + status = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + vos_mem_set( (void *) pMlmAddBARsp, sizeof( tLimMlmAddBARsp ), 0); + + // Copy the peer MAC + vos_mem_copy( + pMlmAddBARsp->peerMacAddr, + peerMacAddr, + sizeof( tSirMacAddr )); + + pMlmAddBARsp->baDialogToken = baDialogToken; + pMlmAddBARsp->addBAResultCode = baStatusCode; + pMlmAddBARsp->baTID = baTID; + pMlmAddBARsp->baPolicy = baPolicy; + pMlmAddBARsp->baBufferSize = baBufferSize; + pMlmAddBARsp->baTimeout = baTimeout; + + /* UPdate PE session ID*/ + pMlmAddBARsp->sessionId = psessionEntry->peSessionId; + + // Send ADDBA Rsp to MLME + limPostMlmMessage( pMac, + LIM_MLM_ADDBA_RSP, + (tANI_U32 *) pMlmAddBARsp ); + +returnFailure: + + return status; +} + +/** + * \brief Post LIM_MLM_DELBA_REQ to MLME. MLME + * will then send an DELBA Ind to peer MAC entity + * with the appropriate DELBA status code + * + * \sa limPostMlmDelBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pSta DPH Hash Node object of peer MAC entity + * for which the BA session is being deleted + * + * \param baDirection DELBA direction + * + * \param baTID TID for which the BA session is being deleted + * + * \param baReasonCode DELBA Req reason code + * + * \return eSIR_SUCCESS if setup completes successfully + * eSIR_FAILURE is some problem is encountered + */ +tSirRetStatus limPostMlmDelBAReq( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tANI_U8 baDirection, + tANI_U8 baTID, + tSirMacReasonCodes baReasonCode, + tpPESession psessionEntry) +{ +tSirRetStatus status = eSIR_SUCCESS; +tpLimMlmDelBAReq pMlmDelBAReq; +tLimBAState curBaState; + +if(NULL == pSta) + return eSIR_FAILURE; + +LIM_GET_STA_BA_STATE(pSta, baTID, &curBaState); + + // Need to validate the current BA State. + if( eLIM_BA_STATE_IDLE != curBaState) + { + limLog( pMac, LOGE, + FL( "Received unexpected DELBA REQ when STA BA state for tid = %d is %d" ), + baTID, + curBaState); + + status = eSIR_FAILURE; + goto returnFailure; + } + + // Allocate for LIM_MLM_DELBA_REQ + pMlmDelBAReq = vos_mem_malloc(sizeof( tLimMlmDelBAReq )); + if ( NULL == pMlmDelBAReq ) + { + limLog( pMac, LOGE, + FL("AllocateMemory failed with error code %d"), + status ); + + status = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + vos_mem_set( (void *) pMlmDelBAReq, sizeof( tLimMlmDelBAReq ), 0); + + // Copy the peer MAC + vos_mem_copy( + pMlmDelBAReq->peerMacAddr, + pSta->staAddr, + sizeof( tSirMacAddr )); + + pMlmDelBAReq->baDirection = baDirection; + pMlmDelBAReq->baTID = baTID; + pMlmDelBAReq->delBAReasonCode = baReasonCode; + + /* Update PE session ID*/ + pMlmDelBAReq->sessionId = psessionEntry->peSessionId; + + //we don't have valid BA session for the given direction. + // HDD wants to get the BA session deleted on PEER in this case. + // in this case we just need to send DelBA to the peer. + if(((eBA_RECIPIENT == baDirection) && (eBA_DISABLE == pSta->tcCfg[baTID].fUseBARx)) || + ((eBA_INITIATOR == baDirection) && (eBA_DISABLE == pSta->tcCfg[baTID].fUseBATx))) + { + // Send DELBA Ind over the air + if( eSIR_SUCCESS != + (status = limSendDelBAInd( pMac, pMlmDelBAReq,psessionEntry))) + status = eSIR_FAILURE; + + vos_mem_free(pMlmDelBAReq); + return status; + } + + + // Update the BA state in STA + LIM_SET_STA_BA_STATE(pSta, pMlmDelBAReq->baTID, eLIM_BA_STATE_WT_DEL_RSP); + + // Send DELBA Req to MLME + limPostMlmMessage( pMac, + LIM_MLM_DELBA_REQ, + (tANI_U32 *) pMlmDelBAReq ); + +returnFailure: + + return status; +} + +/** + * \brief Send WDA_ADDBA_REQ to HAL, in order + * to setup a new BA session with a peer + * + * \sa limPostMsgAddBAReq + * + * \param pMac The global tpAniSirGlobal object + * + * \param pSta Runtime, STA-related configuration cached + * in the HashNode object + * + * \param baDialogToken The Action Frame dialog token + * + * \param baTID TID for which the BA session is being setup + * + * \param baPolicy BA Policy + * + * \param baBufferSize The requested BA buffer size + * + * \param baTimeout BA Timeout. 0 indicates no BA timeout enforced + * + * \param baSSN Starting Sequence Number for this BA session + * + * \param baDirection BA Direction: 1 - Initiator, 0 - Recipient + * + * \return none + * + */ +tSirRetStatus limPostMsgAddBAReq( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tANI_U8 baDialogToken, + tANI_U8 baTID, + tANI_U8 baPolicy, + tANI_U16 baBufferSize, + tANI_U16 baTimeout, + tANI_U16 baSSN, + tANI_U8 baDirection, + tpPESession psessionEntry) +{ +tpAddBAParams pAddBAParams = NULL; +tSirRetStatus retCode = eSIR_SUCCESS; +tSirMsgQ msgQ; + +#ifdef WLAN_SOFTAP_VSTA_FEATURE + // we can only do BA on "hard" STAs + if (!(IS_HWSTA_IDX(pSta->staIndex))) + { + retCode = eHAL_STATUS_FAILURE; + goto returnFailure; + } +#endif //WLAN_SOFTAP_VSTA_FEATURE + + // Allocate for WDA_ADDBA_REQ + pAddBAParams = vos_mem_malloc(sizeof( tAddBAParams )); + if ( NULL == pAddBAParams ) + { + limLog( pMac, LOGE, + FL("AllocateMemory failed") + ); + + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + vos_mem_set( (void *) pAddBAParams, sizeof( tAddBAParams ), 0); + + // Copy the peer MAC address + vos_mem_copy( + (void *) pAddBAParams->peerMacAddr, + (void *) pSta->staAddr, + sizeof( tSirMacAddr )); + + // Populate the REQ parameters + pAddBAParams->staIdx = pSta->staIndex; + pAddBAParams->baDialogToken = baDialogToken; + pAddBAParams->baTID = baTID; + pAddBAParams->baPolicy = baPolicy; + pAddBAParams->baBufferSize = baBufferSize; + pAddBAParams->baTimeout = baTimeout; + pAddBAParams->baSSN = baSSN; + pAddBAParams->baDirection = baDirection; + pAddBAParams->respReqd = 1; + + /* UPdate PE session ID */ + pAddBAParams->sessionId = psessionEntry->peSessionId; + + // Post WDA_ADDBA_REQ to HAL. + msgQ.type = WDA_ADDBA_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pAddBAParams; + msgQ.bodyval = 0; + + limLog( pMac, LOGW, + FL( "Sending WDA_ADDBA_REQ..." )); + + //defer any other message until we get response back. + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_HAL_ADDBA_REQ_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + limLog( pMac, LOGE, + FL("Posting WDA_ADDBA_REQ to HAL failed! Reason = %d"), + retCode ); + else + return retCode; + +returnFailure: + + // Clean-up... + if( NULL != pAddBAParams ) + vos_mem_free( pAddBAParams ); + + return retCode; + +} + +/** + * \brief Send WDA_DELBA_IND to HAL, in order + * to delete an existing BA session with peer + * + * \sa limPostMsgDelBAInd + * + * \param pMac The global tpAniSirGlobal object + * + * \param pSta Runtime, STA-related configuration cached + * in the HashNode object + * + * \param baTID TID for which the BA session is being setup + * + * \param baDirection Identifies whether the DELBA Ind was + * sent by the BA initiator or recipient + * + * \return none + * + */ +tSirRetStatus limPostMsgDelBAInd( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tANI_U8 baTID, + tANI_U8 baDirection, + tpPESession psessionEntry) +{ +tpDelBAParams pDelBAParams = NULL; +tSirRetStatus retCode = eSIR_SUCCESS; +tSirMsgQ msgQ; + + // Allocate for SIR_HAL_DELBA_IND + pDelBAParams = vos_mem_malloc(sizeof( tDelBAParams )); + if ( NULL == pDelBAParams ) + { + limLog( pMac, LOGE, + FL("AllocateMemory failed") + ); + + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + vos_mem_set( (void *) pDelBAParams, sizeof( tDelBAParams ), 0); + + // Populate the REQ parameters + pDelBAParams->staIdx = pSta->staIndex; + pDelBAParams->baTID = baTID; + pDelBAParams->baDirection = baDirection; + + // Post WDA_DELBA_IND to HAL. + msgQ.type = WDA_DELBA_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pDelBAParams; + msgQ.bodyval = 0; + + limLog( pMac, LOGW, + FL( "Sending SIR_HAL_DELBA_IND..." )); + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_HAL_DELBA_IND_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + limLog( pMac, LOGE, + FL("Posting WDA_DELBA_IND to HAL failed! Reason = %d"), + retCode ); + else + { + // Update LIM's internal cache... + if( eBA_INITIATOR == baDirection) + { + pSta->tcCfg[baTID].fUseBATx = 0; + pSta->tcCfg[baTID].txBufSize = 0; + } + else + { + pSta->tcCfg[baTID].fUseBARx = 0; + pSta->tcCfg[baTID].rxBufSize = 0; + } + + return retCode; + } + +returnFailure: + + // Clean-up... + if( NULL != pDelBAParams ) + vos_mem_free( pDelBAParams ); + + return retCode; + +} + +/** + * @function : limPostSMStateUpdate() + * + * @brief : This function Updates the HAL and Softmac about the change in the STA's SMPS state. + * + * LOGIC: + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param limMsg - Lim Message structure object with the MimoPSparam in body + * @return None + */ +tSirRetStatus +limPostSMStateUpdate(tpAniSirGlobal pMac, + tANI_U16 staIdx, tSirMacHTMIMOPowerSaveState state, + tANI_U8 *pPeerStaMac, tANI_U8 sessionId) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tpSetMIMOPS pMIMO_PSParams; + + msgQ.reserved = 0; + msgQ.type = WDA_SET_MIMOPS_REQ; + + // Allocate for WDA_SET_MIMOPS_REQ + pMIMO_PSParams = vos_mem_malloc(sizeof(tSetMIMOPS)); + if ( NULL == pMIMO_PSParams ) + { + limLog( pMac, LOGP,FL(" AllocateMemory failed")); + return eSIR_MEM_ALLOC_FAILED; + } + + pMIMO_PSParams->htMIMOPSState = state; + pMIMO_PSParams->staIdx = staIdx; + pMIMO_PSParams->fsendRsp = true; + pMIMO_PSParams->sessionId = sessionId; + vos_mem_copy(pMIMO_PSParams->peerMac, pPeerStaMac, + sizeof( tSirMacAddr )); + + msgQ.bodyptr = pMIMO_PSParams; + msgQ.bodyval = 0; + + limLog( pMac, LOG2, FL( "Sending WDA_SET_MIMOPS_REQ..." )); + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if (eSIR_SUCCESS != retCode) + { + limLog( pMac, LOGP, FL("Posting WDA_SET_MIMOPS_REQ to HAL failed! Reason = %d"), retCode ); + vos_mem_free(pMIMO_PSParams); + return retCode; + } + + return retCode; +} + +void limPktFree ( + tpAniSirGlobal pMac, + eFrameType frmType, + tANI_U8 *pRxPacketInfo, + void *pBody) +{ + (void) pMac; (void) frmType; (void) pRxPacketInfo; (void) pBody; +} + +/** + * limGetBDfromRxPacket() + * + *FUNCTION: + * This function is called to get pointer to + * Buffer Descriptor containing MAC header & other control + * info from the body of the message posted to LIM. + * + *LOGIC: + * NA + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param body - Received message body + * @param pRxPacketInfo - Pointer to received BD + * @return None + */ + +void +limGetBDfromRxPacket(tpAniSirGlobal pMac, void *body, tANI_U32 **pRxPacketInfo) +{ + *pRxPacketInfo = (tANI_U32 *) body; +} /*** end limGetBDfromRxPacket() ***/ + + + + + +void limRessetScanChannelInfo(tpAniSirGlobal pMac) +{ + vos_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0); +} + + +void limAddScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 channelId) +{ + tANI_U8 i; + tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE; + + for(i = 0; i < pMac->lim.scanChnInfo.numChnInfo; i++) + { + if(pMac->lim.scanChnInfo.scanChn[i].channelId == channelId) + { + pMac->lim.scanChnInfo.scanChn[i].numTimeScan++; + fFound = eANI_BOOLEAN_TRUE; + break; + } + } + if(eANI_BOOLEAN_FALSE == fFound) + { + if(pMac->lim.scanChnInfo.numChnInfo < SIR_MAX_SUPPORTED_CHANNEL_LIST) + { + pMac->lim.scanChnInfo.scanChn[pMac->lim.scanChnInfo.numChnInfo].channelId = channelId; + pMac->lim.scanChnInfo.scanChn[pMac->lim.scanChnInfo.numChnInfo++].numTimeScan = 1; + } + else + { + PELOGW(limLog(pMac, LOGW, FL(" -- number of channels exceed mac"));) + } + } +} + + +/** + * @function : limIsChannelValidForChannelSwitch() + * + * @brief : This function checks if the channel to which AP + * is expecting us to switch, is a valid channel for us. + * LOGIC: + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param channel - New channel to which we are expected to move + * @return None + */ +tAniBool +limIsChannelValidForChannelSwitch(tpAniSirGlobal pMac, tANI_U8 channel) +{ + tANI_U8 index; + tANI_U32 validChannelListLen = WNI_CFG_VALID_CHANNEL_LIST_LEN; + tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + + if (wlan_cfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + (tANI_U8 *)validChannelList, + (tANI_U32 *)&validChannelListLen) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list"));) + return (eSIR_FALSE); + } + + for(index = 0; index < validChannelListLen; index++) + { + if(validChannelList[index] == channel) + return (eSIR_TRUE); + } + + /* channel does not belong to list of valid channels */ + return (eSIR_FALSE); +} + +/**------------------------------------------------------ +\fn __limFillTxControlParams +\brief Fill the message for stopping/resuming tx. + +\param pMac +\param pTxCtrlMsg - Pointer to tx control message. +\param type - Which way we want to stop/ resume tx. +\param mode - To stop/resume. + -------------------------------------------------------*/ +static eHalStatus +__limFillTxControlParams(tpAniSirGlobal pMac, tpTxControlParams pTxCtrlMsg, + tLimQuietTxMode type, tLimControlTx mode) +{ + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + if (mode == eLIM_STOP_TX) + pTxCtrlMsg->stopTx = eANI_BOOLEAN_TRUE; + else + pTxCtrlMsg->stopTx = eANI_BOOLEAN_FALSE; + + switch (type) + { + case eLIM_TX_ALL: + /** Stops/resumes transmission completely */ + pTxCtrlMsg->fCtrlGlobal = 1; + break; + + case eLIM_TX_BSS_BUT_BEACON: + /** Stops/resumes transmission on a particular BSS. Stopping BSS, doesnt + * stop beacon transmission. + */ + pTxCtrlMsg->ctrlBss = 1; + pTxCtrlMsg->bssBitmap |= (1 << psessionEntry->bssIdx); + break; + + case eLIM_TX_STA: + /** Memory for station bitmap is allocated dynamically in caller of this + * so decode properly here and fill the bitmap. Now not implemented, + * fall through. + */ + case eLIM_TX_BSS: + //Fall thru... + default: + PELOGW(limLog(pMac, LOGW, FL("Invalid case: Not Handled"));) + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * @function : limFrameTransmissionControl() + * + * @brief : This API is called by the user to halt/resume any frame + * transmission from the device. If stopped, all frames will be + * queued starting from hardware. Then back-pressure + * is built till the driver. + * LOGIC: + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ +void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLimControlTx mode) +{ + + eHalStatus status = eHAL_STATUS_FAILURE; + tpTxControlParams pTxCtrlMsg; + tSirMsgQ msgQ; + tANI_U8 nBytes = 0; // No of bytes required for station bitmap. + + /** Allocate only required number of bytes for station bitmap + * Make it to align to 4 byte boundary */ + nBytes = (tANI_U8)HALMSG_NUMBYTES_STATION_BITMAP(pMac->lim.maxStation); + + pTxCtrlMsg = vos_mem_malloc(sizeof(*pTxCtrlMsg) + nBytes); + if ( NULL == pTxCtrlMsg ) + { + limLog(pMac, LOGP, FL("AllocateMemory() failed")); + return; + } + + vos_mem_set((void *) pTxCtrlMsg, + (sizeof(*pTxCtrlMsg) + nBytes), 0); + status = __limFillTxControlParams(pMac, pTxCtrlMsg, type, mode); + if (status != eHAL_STATUS_SUCCESS) + { + vos_mem_free(pTxCtrlMsg); + limLog(pMac, LOGP, FL("__limFillTxControlParams failed, status = %d"), status); + return; + } + + msgQ.bodyptr = (void *) pTxCtrlMsg; + msgQ.bodyval = 0; + msgQ.reserved = 0; + msgQ.type = WDA_TRANSMISSION_CONTROL_IND; + + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + if(wdaPostCtrlMsg( pMac, &msgQ) != eSIR_SUCCESS) + { + vos_mem_free(pTxCtrlMsg); + limLog( pMac, LOGP, FL("Posting Message to HAL failed")); + return; + } + + if (mode == eLIM_STOP_TX) + { + PELOG1(limLog(pMac, LOG1, FL("Stopping the transmission of all packets, indicated softmac"));) + } + else + { + PELOG1(limLog(pMac, LOG1, FL("Resuming the transmission of all packets, indicated softmac"));) + } + return; +} + + +/** + * @function : limRestorePreChannelSwitchState() + * + * @brief : This API is called by the user to undo any + * specific changes done on the device during + * channel switch. + * LOGIC: + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +tSirRetStatus +limRestorePreChannelSwitchState(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + tSirRetStatus retCode = eSIR_SUCCESS; + tANI_U32 val = 0; + + if (!LIM_IS_STA_ROLE(psessionEntry)) + return retCode; + + /* Channel switch should be ready for the next time */ + psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_INIT; + + /* Restore the frame transmission, all the time. */ + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + + /* Free to enter BMPS */ + limSendSmePostChannelSwitchInd(pMac); + + //Background scan is now enabled by SME + if(pMac->lim.gLimBackgroundScanTerminate == FALSE) + { + /* Enable background scan if already enabled, else don't bother */ + if ((retCode = wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, + &val)) != eSIR_SUCCESS) + + { + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); + return (retCode); + } + + if (val > 0 && TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_BACKGROUND_SCAN_TIMER)); + if(tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not restart background scan timer, doing LOGP")); + return (eSIR_FAILURE); + } + + } + } + + /* Enable heartbeat timer */ + if (TX_TIMER_VALID(pMac->lim.limTimers.gLimHeartBeatTimer)) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); + if((limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) && + (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) + { + limLog(pMac, LOGP, FL("Could not restart heartbeat timer, doing LOGP")); + return (eSIR_FAILURE); + } + } + return (retCode); +} + + +/**-------------------------------------------- +\fn limRestorePreQuietState +\brief Restore the pre quiet state + +\param pMac +\return NONE +---------------------------------------------*/ +tSirRetStatus limRestorePreQuietState(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + tSirRetStatus retCode = eSIR_SUCCESS; + tANI_U32 val = 0; + + if (pMac->lim.gLimSystemRole != eLIM_STA_ROLE) + return retCode; + + /* Quiet should be ready for the next time */ + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + + /* Restore the frame transmission, all the time. */ + if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) + limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + + + //Background scan is now enabled by SME + if(pMac->lim.gLimBackgroundScanTerminate == FALSE) + { + /* Enable background scan if already enabled, else don't bother */ + if ((retCode = wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, + &val)) != eSIR_SUCCESS) + + { + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); + return (retCode); + } + + if (val > 0 && TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_BACKGROUND_SCAN_TIMER)); + if(tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not restart background scan timer, doing LOGP")); + return (eSIR_FAILURE); + } + + } + } + + /* Enable heartbeat timer */ + if (TX_TIMER_VALID(pMac->lim.limTimers.gLimHeartBeatTimer)) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); + if(limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("Could not restart heartbeat timer, doing LOGP")); + return (eSIR_FAILURE); + } + } + return (retCode); +} + + +/** + * @function: limPrepareFor11hChannelSwitch() + * + * @brief : This API is called by the user to prepare for + * 11h channel switch. As of now, the API does + * very minimal work. User can add more into the + * same API if needed. + * LOGIC: + * + * ASSUMPTIONS: + * NA + * + * NOTE: + * NA + * + * @param pMac - Pointer to Global MAC structure + * @param psessionEntry + * @return None + */ +void +limPrepareFor11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (!LIM_IS_STA_ROLE(psessionEntry)) + return; + + /* Flag to indicate 11h channel switch in progress */ + psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_RUNNING; + + /* Disable, Stop background scan if enabled and running */ + limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); + + /* Stop heart-beat timer to stop heartbeat disassociation */ + limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); + + if(pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE || + pMac->lim.gLimSmeState == eLIM_SME_CHANNEL_SCAN_STATE) + { + PELOGE(limLog(pMac, LOG1, FL("Posting finish scan as we are in scan state"));) + /* Stop ongoing scanning if any */ + if (GET_LIM_PROCESS_DEFD_MESGS(pMac)) + { + //Set the resume channel to Any valid channel (invalid). + //This will instruct HAL to set it to any previous valid channel. + peSetResumeChannel(pMac, 0, 0); + limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE); + } + else + { + limRestorePreChannelSwitchState(pMac, psessionEntry); + } + return; + } + else + { + PELOGE(limLog(pMac, LOG1, FL("Not in scan state, start channel switch timer"));) + /** We are safe to switch channel at this point */ + limStopTxAndSwitchChannel(pMac, psessionEntry->peSessionId); + } +} + + + +/**---------------------------------------------------- +\fn limGetNwType + +\brief Get type of the network from data packet or beacon +\param pMac +\param channelNum - Channel number +\param type - Type of packet. +\param pBeacon - Pointer to beacon or probe response + +\return Network type a/b/g. +-----------------------------------------------------*/ +tSirNwType limGetNwType(tpAniSirGlobal pMac, tANI_U8 channelNum, tANI_U32 type, tpSchBeaconStruct pBeacon) +{ + tSirNwType nwType = eSIR_11B_NW_TYPE; + + if (type == SIR_MAC_DATA_FRAME) + { + if ((channelNum > 0) && (channelNum < 15)) + { + nwType = eSIR_11G_NW_TYPE; + } + else + { + nwType = eSIR_11A_NW_TYPE; + } + } + else + { + if ((channelNum > 0) && (channelNum < 15)) + { + int i; + /* + * 11b or 11g packet + * 11g if extended Rate IE is present or + * if there is an A rate in suppRate IE + */ + for (i = 0; i < pBeacon->supportedRates.numRates; i++) + { + if (sirIsArate(pBeacon->supportedRates.rate[i] & 0x7f)) + { + nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (pBeacon->extendedRatesPresent) + { + PELOG3(limLog(pMac, LOG3, FL("Beacon, nwtype=G"));) + nwType = eSIR_11G_NW_TYPE; + } + } + else + { + // 11a packet + PELOG3(limLog(pMac, LOG3,FL("Beacon, nwtype=A"));) + nwType = eSIR_11A_NW_TYPE; + } + } + return nwType; +} + + +/**--------------------------------------------------------- +\fn limGetChannelFromBeacon +\brief To extract channel number from beacon + +\param pMac +\param pBeacon - Pointer to beacon or probe rsp +\return channel number +-----------------------------------------------------------*/ +tANI_U8 limGetChannelFromBeacon(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon) +{ + tANI_U8 channelNum = 0; + + if (pBeacon->dsParamsPresent) + channelNum = pBeacon->channelNumber; + else if(pBeacon->HTInfo.present) + channelNum = pBeacon->HTInfo.primaryChannel; + else + channelNum = pBeacon->channelNumber; + + return channelNum; +} + + +/** --------------------------------------------------------- +\fn limSetTspecUapsdMask +\brief This function sets the PE global variable: +\ 1) gUapsdPerAcTriggerEnableMask and +\ 2) gUapsdPerAcDeliveryEnableMask +\ based on the user priority field and direction field +\ in the TS Info Fields. +\ +\ An AC is a trigger-enabled AC if the PSB subfield +\ is set to 1 in the up link direction. +\ An AC is a delivery-enabled AC if the PSB subfield +\ is set to 1 in the down-link direction. +\ +\param tpAniSirGlobal pMac +\param tSirMacTSInfo pTsInfo +\param tANI_U32 action +\return None + ------------------------------------------------------------*/ +void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 action) +{ + tANI_U8 userPrio = (tANI_U8)pTsInfo->traffic.userPrio; + tANI_U16 direction = pTsInfo->traffic.direction; + tANI_U8 ac = upToAc(userPrio); + + PELOG1(limLog(pMac, LOG1, FL(" Set UAPSD mask for AC %d, direction %d, action=%d (1=set,0=clear) "),ac, direction, action );) + + /* Converting AC to appropriate Uapsd Bit Mask + * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3) + * AC_BK(1) --> UAPSD_BITOFFSET_ACVO(2) + * AC_VI(2) --> UAPSD_BITOFFSET_ACVO(1) + * AC_VO(3) --> UAPSD_BITOFFSET_ACVO(0) + */ + ac = ((~ac) & 0x3); + + if (action == CLEAR_UAPSD_MASK) + { + if (direction == SIR_MAC_DIRECTION_UPLINK) + pMac->lim.gUapsdPerAcTriggerEnableMask &= ~(1 << ac); + else if (direction == SIR_MAC_DIRECTION_DNLINK) + pMac->lim.gUapsdPerAcDeliveryEnableMask &= ~(1 << ac); + else if (direction == SIR_MAC_DIRECTION_BIDIR) + { + pMac->lim.gUapsdPerAcTriggerEnableMask &= ~(1 << ac); + pMac->lim.gUapsdPerAcDeliveryEnableMask &= ~(1 << ac); + } + } + else if (action == SET_UAPSD_MASK) + { + if (direction == SIR_MAC_DIRECTION_UPLINK) + pMac->lim.gUapsdPerAcTriggerEnableMask |= (1 << ac); + else if (direction == SIR_MAC_DIRECTION_DNLINK) + pMac->lim.gUapsdPerAcDeliveryEnableMask |= (1 << ac); + else if (direction == SIR_MAC_DIRECTION_BIDIR) + { + pMac->lim.gUapsdPerAcTriggerEnableMask |= (1 << ac); + pMac->lim.gUapsdPerAcDeliveryEnableMask |= (1 << ac); + } + } + + limLog(pMac, LOG1, FL("New pMac->lim.gUapsdPerAcTriggerEnableMask = 0x%x "), pMac->lim.gUapsdPerAcTriggerEnableMask ); + limLog(pMac, LOG1, FL("New pMac->lim.gUapsdPerAcDeliveryEnableMask = 0x%x "), pMac->lim.gUapsdPerAcDeliveryEnableMask ); + + return; +} + +void limSetTspecUapsdMaskPerSession(tpAniSirGlobal pMac, + tpPESession psessionEntry, tSirMacTSInfo *pTsInfo, tANI_U32 action) +{ + tANI_U8 userPrio = (tANI_U8)pTsInfo->traffic.userPrio; + tANI_U16 direction = pTsInfo->traffic.direction; + tANI_U8 ac = upToAc(userPrio); + + PELOG1(limLog(pMac, LOG1, FL("Set UAPSD mask for AC %d, dir %d, action=%d") + ,ac, direction, action );) + + /* Converting AC to appropriate Uapsd Bit Mask + * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3) + * AC_BK(1) --> UAPSD_BITOFFSET_ACVO(2) + * AC_VI(2) --> UAPSD_BITOFFSET_ACVO(1) + * AC_VO(3) --> UAPSD_BITOFFSET_ACVO(0) + */ + ac = ((~ac) & 0x3); + + if (action == CLEAR_UAPSD_MASK) + { + if (direction == SIR_MAC_DIRECTION_UPLINK) + psessionEntry->gUapsdPerAcTriggerEnableMask &= ~(1 << ac); + else if (direction == SIR_MAC_DIRECTION_DNLINK) + psessionEntry->gUapsdPerAcDeliveryEnableMask &= ~(1 << ac); + else if (direction == SIR_MAC_DIRECTION_BIDIR) + { + psessionEntry->gUapsdPerAcTriggerEnableMask &= ~(1 << ac); + psessionEntry->gUapsdPerAcDeliveryEnableMask &= ~(1 << ac); + } + } + else if (action == SET_UAPSD_MASK) + { + if (direction == SIR_MAC_DIRECTION_UPLINK) + psessionEntry->gUapsdPerAcTriggerEnableMask |= (1 << ac); + else if (direction == SIR_MAC_DIRECTION_DNLINK) + psessionEntry->gUapsdPerAcDeliveryEnableMask |= (1 << ac); + else if (direction == SIR_MAC_DIRECTION_BIDIR) + { + psessionEntry->gUapsdPerAcTriggerEnableMask |= (1 << ac); + psessionEntry->gUapsdPerAcDeliveryEnableMask |= (1 << ac); + } + } + + limLog(pMac, LOG1, + FL("New psessionEntry->gUapsdPerAcTriggerEnableMask = 0x%x "), + psessionEntry->gUapsdPerAcTriggerEnableMask ); + limLog(pMac, LOG1, + FL("New psessionEntry->gUapsdPerAcDeliveryEnableMask = 0x%x "), + psessionEntry->gUapsdPerAcDeliveryEnableMask ); + + return; +} + +void limHandleHeartBeatTimeout(tpAniSirGlobal pMac ) +{ + + tANI_U8 i; + for(i =0;i < pMac->lim.maxBssId;i++) + { + if(pMac->lim.gpSession[i].valid == TRUE ) + { + if(pMac->lim.gpSession[i].bssType == eSIR_IBSS_MODE) + { + limIbssHeartBeatHandle(pMac,&pMac->lim.gpSession[i]); + break; + } + + if((pMac->lim.gpSession[i].bssType == eSIR_INFRASTRUCTURE_MODE) && + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE)) + { + limHandleHeartBeatFailure(pMac,&pMac->lim.gpSession[i]); + } + } + } + for(i=0; i< pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE ) + { + if((pMac->lim.gpSession[i].bssType == eSIR_INFRASTRUCTURE_MODE) && + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE)) + { + if(pMac->lim.gpSession[i].LimHBFailureStatus == eANI_BOOLEAN_TRUE) + { + /* Activate Probe After HeartBeat Timer in-case + HB Failure detected */ + PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"), + i);) + limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer")); + limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[i]); + } + break; + } + } + } + } +} + +void limHandleHeartBeatTimeoutForSession(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if(psessionEntry->valid == TRUE ) + { + if(psessionEntry->bssType == eSIR_IBSS_MODE) + { + limIbssHeartBeatHandle(pMac,psessionEntry); + } + if((psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) && + LIM_IS_STA_ROLE(psessionEntry)) { + limHandleHeartBeatFailure(pMac,psessionEntry); + } + } + /* In the function limHandleHeartBeatFailure things can change so check for the session entry valid + and the other things again */ + if(psessionEntry->valid == TRUE ) + { + if((psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) && + LIM_IS_STA_ROLE(psessionEntry)) { + if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE) + { + /* Activate Probe After HeartBeat Timer in-case + HB Failure detected */ + PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"), + psessionEntry->bssIdx);) + limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER); + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER)); + if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer")); + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + } + } + } +} + + +tANI_U8 limGetCurrentOperatingChannel(tpAniSirGlobal pMac) +{ + tANI_U8 i; + for(i =0;i < pMac->lim.maxBssId;i++) + { + if(pMac->lim.gpSession[i].valid == TRUE ) + { + if((pMac->lim.gpSession[i].bssType == eSIR_INFRASTRUCTURE_MODE) && + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE)) + { + return pMac->lim.gpSession[i].currentOperChannel; + } + } + } + return 0; +} + +void limProcessAddStaRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) +{ + tpPESession psessionEntry; + tpAddStaParams pAddStaParams; + + pAddStaParams = (tpAddStaParams)limMsgQ->bodyptr; + + if((psessionEntry = peFindSessionBySessionId(pMac,pAddStaParams->sessionId))==NULL) + { + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + vos_mem_free(pAddStaParams); + return; + } + psessionEntry->csaOffloadEnable = pAddStaParams->csaOffloadEnable; + if (LIM_IS_IBSS_ROLE(psessionEntry)) + (void) limIbssAddStaRsp(pMac, limMsgQ->bodyptr,psessionEntry); +#ifdef FEATURE_WLAN_TDLS + else if(pMac->lim.gLimAddStaTdls) + { + limProcessTdlsAddStaRsp(pMac, limMsgQ->bodyptr, psessionEntry) ; + pMac->lim.gLimAddStaTdls = FALSE ; + } +#endif + else + limProcessMlmAddStaRsp(pMac, limMsgQ,psessionEntry); + +} + + +void limUpdateBeacon(tpAniSirGlobal pMac) +{ + tANI_U8 i; + + for(i =0;i < pMac->lim.maxBssId;i++) + { + if(pMac->lim.gpSession[i].valid == TRUE ) + { + if( ( (pMac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) || + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_IN_IBSS_ROLE) ) + && (eLIM_SME_NORMAL_STATE == pMac->lim.gpSession[i].limSmeState) + ) + { + schSetFixedBeaconFields(pMac,&pMac->lim.gpSession[i]); + if (VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + { + limSendBeaconInd(pMac, &pMac->lim.gpSession[i]); + } + } + else + { + if( (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_AP_ROLE)|| + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_STA_ROLE)) + { + + if(pMac->lim.gpSession[i].statypeForBss == STA_ENTRY_SELF) + { + schSetFixedBeaconFields(pMac,&pMac->lim.gpSession[i]); + } + } + } + } + } +} + +void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac) +{ + tANI_U8 i; + tpPESession psessionEntry; + /* Probe response is not received after HB failure. This is handled by LMM sub module. */ + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + psessionEntry = &pMac->lim.gpSession[i]; + if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE) + { + limLog(pMac, LOGE, FL( + "Probe_hb_failure: SME %d, MLME %d, HB Cnt %d, BCN cnt %d"), + psessionEntry->limSmeState, + psessionEntry->limMlmState, + psessionEntry->LimRxedBeaconCntDuringHB, + psessionEntry->currentBssBeaconCnt); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_HB_FAILURE_TIMEOUT, psessionEntry, 0, 0); +#endif + if (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) + { + /* + * Disconnect even if we have not received a single beacon + * after connection. + */ + if (((!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) || + (0 == psessionEntry->currentBssBeaconCnt)) && + (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) + { + limLog(pMac, LOGE, FL("Probe_hb_failure: for session:%d " ),psessionEntry->peSessionId); + /* AP did not respond to Probe Request. Tear down link with it.*/ + limTearDownLinkWithAp(pMac, + psessionEntry->peSessionId, + eSIR_BEACON_MISSED); + pMac->lim.gLimProbeFailureAfterHBfailedCnt++ ; + } + else // restart heartbeat timer + { + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + } + else + { + limLog(pMac, LOGE, FL("Unexpected wt-probe-timeout in state ")); + limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + + } + } + } +} + + +/* +* This function assumes there will not be more than one IBSS session active at any time. +*/ +tpPESession limIsIBSSSessionActive(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_IN_IBSS_ROLE)) + return (&pMac->lim.gpSession[i]); + } + + return NULL; +} + +tpPESession limIsApSessionActive(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_AP_ROLE) || + (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_AP_ROLE))) + return (&pMac->lim.gpSession[i]); + } + + return NULL; +} + +/**--------------------------------------------------------- +\fn limHandleDeferMsgError +\brief handles error scenario, when the msg can not be deferred. +\param pMac +\param pLimMsg LIM msg, which could not be deferred. +\return void +-----------------------------------------------------------*/ + +void limHandleDeferMsgError(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg) +{ + if(SIR_BB_XPORT_MGMT_MSG == pLimMsg->type) + { + vos_pkt_return_packet((vos_pkt_t*)pLimMsg->bodyptr); + pLimMsg->bodyptr = NULL; + } + else if(pLimMsg->bodyptr != NULL) + { + vos_mem_free(pLimMsg->bodyptr); + pLimMsg->bodyptr = NULL; + } + +} + + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/**--------------------------------------------------------- +\fn limDiagEventReport +\brief This function reports Diag event +\param pMac +\param eventType +\param bssid +\param status +\param reasonCode +\return void +-----------------------------------------------------------*/ +void limDiagEventReport(tpAniSirGlobal pMac, tANI_U16 eventType, tpPESession pSessionEntry, tANI_U16 status, tANI_U16 reasonCode) +{ + tSirMacAddr nullBssid = { 0, 0, 0, 0, 0, 0 }; + WLAN_VOS_DIAG_EVENT_DEF(peEvent, vos_event_wlan_pe_payload_type); + + vos_mem_set(&peEvent, sizeof(vos_event_wlan_pe_payload_type), 0); + + if (NULL == pSessionEntry) + { + vos_mem_copy( peEvent.bssid, nullBssid, sizeof(tSirMacAddr)); + peEvent.sme_state = (tANI_U16)pMac->lim.gLimSmeState; + peEvent.mlm_state = (tANI_U16)pMac->lim.gLimMlmState; + + } + else + { + vos_mem_copy(peEvent.bssid, pSessionEntry->bssId, sizeof(tSirMacAddr)); + peEvent.sme_state = (tANI_U16)pSessionEntry->limSmeState; + peEvent.mlm_state = (tANI_U16)pSessionEntry->limMlmState; + } + peEvent.event_type = eventType; + peEvent.status = status; + peEvent.reason_code = reasonCode; + + WLAN_VOS_DIAG_EVENT_REPORT(&peEvent, EVENT_WLAN_PE); + return; +} + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +void limProcessAddStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) +{ + + tpAddStaSelfParams pAddStaSelfParams; + tSirMsgQ mmhMsg; + tpSirSmeAddStaSelfRsp pRsp; + eHalStatus status; + + pAddStaSelfParams = (tpAddStaSelfParams)limMsgQ->bodyptr; + + pRsp = vos_mem_malloc(sizeof(tSirSmeAddStaSelfRsp)); + if ( NULL == pRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, FL("call to AllocateMemory failed for Add Sta self RSP")); + vos_mem_free(pAddStaSelfParams); + limMsgQ->bodyptr = NULL; + return; + } + + vos_mem_set((tANI_U8*)pRsp, sizeof(tSirSmeAddStaSelfRsp), 0); + + pRsp->mesgType = eWNI_SME_ADD_STA_SELF_RSP; + pRsp->mesgLen = (tANI_U16) sizeof(tSirSmeAddStaSelfRsp); + pRsp->status = pAddStaSelfParams->status; + + vos_mem_copy( pRsp->selfMacAddr, pAddStaSelfParams->selfMacAddr, sizeof(tSirMacAddr) ); + + /* + * For FW generated probe requests, Host needs to send Extended Capbilities + * IE information. With this fix, Host will send the extended capabilites + * on getting eWNI_SME_ADD_STA_SELF_RSP message(after vdev create). + * + * This information is required for only STA/P2P as they are the one which + * sends probe request. + */ + if (VOS_STATUS_SUCCESS == pRsp->status && + (WMI_VDEV_TYPE_STA == pAddStaSelfParams->type || + (WMI_VDEV_TYPE_AP == pAddStaSelfParams->type && + WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == pAddStaSelfParams->subType))) { + limLog(pMac, LOG1, FL("Add sta success - send ext cap IE")); + status = lim_send_ext_cap_ie(pMac, pAddStaSelfParams->sessionId, NULL, + false); + if (eHAL_STATUS_SUCCESS != status) + limLog(pMac, LOGE, FL("Unable to send ExtCap to FW")); + } + + vos_mem_free(pAddStaSelfParams); + limMsgQ->bodyptr = NULL; + + mmhMsg.type = eWNI_SME_ADD_STA_SELF_RSP; + mmhMsg.bodyptr = pRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} + +/** + * lim_ScanTypetoString(): converts scan type enum to string. + * @scanType: enum value of scanType. + */ +const char * lim_ScanTypetoString(const v_U8_t scanType) +{ + switch (scanType) + { + CASE_RETURN_STRING( eSIR_PASSIVE_SCAN ); + CASE_RETURN_STRING( eSIR_ACTIVE_SCAN ); + CASE_RETURN_STRING( eSIR_BEACON_TABLE ); + default: + return "Unknown ScanType"; + } +} + +/** + * lim_BssTypetoString(): converts bss type enum to string. + * @bssType: enum value of bssType. + */ + +const char * lim_BssTypetoString(const v_U8_t bssType) +{ + switch (bssType) + { + CASE_RETURN_STRING( eSIR_INFRASTRUCTURE_MODE ); + CASE_RETURN_STRING( eSIR_INFRA_AP_MODE ); + CASE_RETURN_STRING( eSIR_IBSS_MODE ); + CASE_RETURN_STRING( eSIR_BTAMP_STA_MODE ); + CASE_RETURN_STRING( eSIR_BTAMP_AP_MODE ); + CASE_RETURN_STRING( eSIR_AUTO_MODE ); + default: + return "Unknown BssType"; + } +} + +/** + * lim_BackgroundScanModetoString():converts BG scan type to string. + * @mode: enum value of BG scan type. + */ + +const char *lim_BackgroundScanModetoString(const v_U8_t mode) +{ + switch (mode) + { + CASE_RETURN_STRING( eSIR_AGGRESSIVE_BACKGROUND_SCAN ); + CASE_RETURN_STRING( eSIR_NORMAL_BACKGROUND_SCAN ); + CASE_RETURN_STRING( eSIR_ROAMING_SCAN ); + default: + return "Unknown BgScanMode"; + } +} + +void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) +{ + + tpDelStaSelfParams pDelStaSelfParams; + tSirMsgQ mmhMsg; + tpSirSmeDelStaSelfRsp pRsp; + + + pDelStaSelfParams = (tpDelStaSelfParams)limMsgQ->bodyptr; + + pRsp = vos_mem_malloc(sizeof(tSirSmeDelStaSelfRsp)); + if ( NULL == pRsp ) + { + /// Buffer not available. Log error + limLog(pMac, LOGP, FL("call to AllocateMemory failed for Add Sta self RSP")); + vos_mem_free(pDelStaSelfParams); + limMsgQ->bodyptr = NULL; + return; + } + + vos_mem_set((tANI_U8*)pRsp, sizeof(tSirSmeDelStaSelfRsp), 0); + + pRsp->mesgType = eWNI_SME_DEL_STA_SELF_RSP; + pRsp->mesgLen = (tANI_U16) sizeof(tSirSmeDelStaSelfRsp); + pRsp->status = pDelStaSelfParams->status; + + vos_mem_copy( pRsp->selfMacAddr, pDelStaSelfParams->selfMacAddr, sizeof(tSirMacAddr) ); + + vos_mem_free(pDelStaSelfParams); + limMsgQ->bodyptr = NULL; + + mmhMsg.type = eWNI_SME_DEL_STA_SELF_RSP; + mmhMsg.bodyptr = pRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} + +/*************************************************************** +* tANI_U8 limUnmapChannel(tANI_U8 mapChannel) +* To unmap the channel to reverse the effect of mapping +* a band channel in hal .Mapping was done hal to overcome the +* limitation of the rxbd which use only 4 bit for channel number. +*****************************************************************/ +tANI_U8 limUnmapChannel(tANI_U8 mapChannel) +{ + return WDA_MapChannel(mapChannel); +} + + +v_U8_t* limGetIEPtr(tpAniSirGlobal pMac, v_U8_t *pIes, int length, v_U8_t eid,eSizeOfLenField size_of_len_field) +{ + int left = length; + v_U8_t *ptr = pIes; + v_U8_t elem_id; + v_U16_t elem_len; + + while(left >= (size_of_len_field+1)) + { + elem_id = ptr[0]; + if (size_of_len_field == TWO_BYTE) + { + elem_len = ((v_U16_t) ptr[1]) | (ptr[2]<<8); + } + else + { + elem_len = ptr[1]; + } + + + left -= (size_of_len_field+1); + if(elem_len > left) + { + limLog(pMac, LOGE, + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), + eid,elem_len,left); + return NULL; + } + if (elem_id == eid) + { + return ptr; + } + + left -= elem_len; + ptr += (elem_len + (size_of_len_field+1)); + } + return NULL; +} + +//Returns length of P2P stream and Pointer ie passed to this function is filled with noa stream + +v_U8_t limBuildP2pIe(tpAniSirGlobal pMac, tANI_U8 *ie, tANI_U8 *data, tANI_U8 ie_len) +{ + int length = 0; + tANI_U8 *ptr = ie; + + ptr[length++] = SIR_MAC_EID_VENDOR; + ptr[length++] = ie_len + SIR_MAC_P2P_OUI_SIZE; + vos_mem_copy(&ptr[length], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); + vos_mem_copy(&ptr[length + SIR_MAC_P2P_OUI_SIZE], data, ie_len); + return (ie_len + SIR_P2P_IE_HEADER_LEN); +} + +//Returns length of NoA stream and Pointer pNoaStream passed to this function is filled with noa stream + +v_U8_t limGetNoaAttrStreamInMultP2pIes(tpAniSirGlobal pMac,v_U8_t* noaStream,v_U8_t noaLen,v_U8_t overFlowLen) +{ + v_U8_t overFlowP2pStream[SIR_MAX_NOA_ATTR_LEN]; + + if ((noaLen <= (SIR_MAX_NOA_ATTR_LEN+SIR_P2P_IE_HEADER_LEN)) && + (noaLen >= overFlowLen) && (overFlowLen <= SIR_MAX_NOA_ATTR_LEN)) + { + vos_mem_copy(overFlowP2pStream, + noaStream + noaLen - overFlowLen, overFlowLen); + noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR; + noaStream[noaLen - overFlowLen + 1] = overFlowLen + SIR_MAC_P2P_OUI_SIZE; + vos_mem_copy(noaStream+noaLen-overFlowLen + 2, + SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); + vos_mem_copy(noaStream+noaLen + 2 + SIR_MAC_P2P_OUI_SIZE - overFlowLen, + overFlowP2pStream, overFlowLen); + } + + return (noaLen + SIR_P2P_IE_HEADER_LEN); + +} + +//Returns length of NoA stream and Pointer pNoaStream passed to this function is filled with noa stream +v_U8_t limGetNoaAttrStream(tpAniSirGlobal pMac, v_U8_t*pNoaStream,tpPESession psessionEntry) +{ + v_U8_t len=0; + + v_U8_t *pBody = pNoaStream; + + + if ( (psessionEntry != NULL) && (psessionEntry->valid) && + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { + if ((!(psessionEntry->p2pGoPsUpdate.uNoa1Duration)) && (!(psessionEntry->p2pGoPsUpdate.uNoa2Duration)) + && (!psessionEntry->p2pGoPsUpdate.oppPsFlag) + ) + return 0; //No NoA Descriptor then return 0 + + + pBody[0] = SIR_P2P_NOA_ATTR; + + pBody[3] = psessionEntry->p2pGoPsUpdate.index; + pBody[4] = psessionEntry->p2pGoPsUpdate.ctWin | (psessionEntry->p2pGoPsUpdate.oppPsFlag<<7); + len = 5; + pBody += len; + + + if (psessionEntry->p2pGoPsUpdate.uNoa1Duration) + { + *pBody = psessionEntry->p2pGoPsUpdate.uNoa1IntervalCnt; + pBody += 1; + len +=1; + + *((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa1Duration); + pBody += sizeof(tANI_U32); + len +=4; + + *((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa1Interval); + pBody += sizeof(tANI_U32); + len +=4; + + *((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa1StartTime); + pBody += sizeof(tANI_U32); + len +=4; + + } + + if (psessionEntry->p2pGoPsUpdate.uNoa2Duration) + { + *pBody = psessionEntry->p2pGoPsUpdate.uNoa2IntervalCnt; + pBody += 1; + len +=1; + + *((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa2Duration); + pBody += sizeof(tANI_U32); + len +=4; + + *((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa2Interval); + pBody += sizeof(tANI_U32); + len +=4; + + *((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa2StartTime); + pBody += sizeof(tANI_U32); + len +=4; + + } + + + pBody = pNoaStream + 1; + *((tANI_U16 *)(pBody)) = sirSwapU16ifNeeded(len-3);/*one byte for Attr and 2 bytes for length*/ + + return (len); + + } + return 0; + +} + +void peSetResumeChannel(tpAniSirGlobal pMac, tANI_U16 channel, ePhyChanBondState phyCbState) +{ + + pMac->lim.gResumeChannel = channel; + pMac->lim.gResumePhyCbState = phyCbState; +} + +/*-------------------------------------------------------------------------- + + \brief peGetResumeChannel() - Returns the channel number for scanning, from a valid session. + + This function returns the channel to resume to during link resume. channel id of 0 means HAL will + resume to previous channel before link suspend + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + + \sa + + --------------------------------------------------------------------------*/ +void peGetResumeChannel(tpAniSirGlobal pMac, tANI_U8* resumeChannel, ePhyChanBondState* resumePhyCbState) +{ + + //Rationale - this could be the suspend/resume for assoc and it is essential that + //the new BSS is active for some time. Other BSS was anyway suspended. + //TODO: Comeup with a better alternative. Sending NULL with PM=0 on other BSS means + //there will be trouble. But since it is sent on current channel, it will be missed by peer + //and hence should be ok. Need to discuss this further + if( !limIsInMCC(pMac) ) + { + //Get current active session channel + peGetActiveSessionChannel(pMac, resumeChannel, resumePhyCbState); + } + else + { + *resumeChannel = pMac->lim.gResumeChannel; + *resumePhyCbState = pMac->lim.gResumePhyCbState; + } + return; +} + +tANI_BOOLEAN limIsNOAInsertReqd(tpAniSirGlobal pMac) +{ + tANI_U8 i; + for(i =0; i < pMac->lim.maxBssId; i++) + { + if(pMac->lim.gpSession[i].valid == TRUE) + { + if( (eLIM_AP_ROLE == pMac->lim.gpSession[i].limSystemRole ) + && ( VOS_P2P_GO_MODE == pMac->lim.gpSession[i].pePersona ) + ) + { + return TRUE; + } + } + } + return FALSE; +} + + +tANI_BOOLEAN limIsconnectedOnDFSChannel(tANI_U8 currentChannel) +{ + if(NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(currentChannel)) + { + return eANI_BOOLEAN_TRUE; + } + else + { + return eANI_BOOLEAN_FALSE; + } +} + +#ifdef WLAN_FEATURE_11W +void limPmfSaQueryTimerHandler(void *pMacGlobal, tANI_U32 param) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; + tPmfSaQueryTimerId timerId; + tpPESession psessionEntry; + tpDphHashNode pSta; + tANI_U32 maxRetries; + + limLog(pMac, LOG1, FL("SA Query timer fires")); + timerId.value = param; + + // Check that SA Query is in progress + if ((psessionEntry = peFindSessionBySessionId( + pMac, timerId.fields.sessionId)) == NULL) + { + limLog(pMac, LOGE, FL("Session does not exist for given session ID %d"), + timerId.fields.sessionId); + return; + } + if ((pSta = dphGetHashEntry(pMac, timerId.fields.peerIdx, + &psessionEntry->dph.dphHashTable)) == NULL) + { + limLog(pMac, LOGE, FL("Entry does not exist for given peer index %d"), + timerId.fields.peerIdx); + return; + } + if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState) + return; + + // Increment the retry count, check if reached maximum + if (wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + &maxRetries) != eSIR_SUCCESS) + { + limLog(pMac, LOGE, FL("Could not retrieve PMF SA Query maximum retries value")); + pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; + return; + } + pSta->pmfSaQueryRetryCount++; + if (pSta->pmfSaQueryRetryCount >= maxRetries) + { + limLog(pMac, LOGE, FL("SA Query timed out,Deleting STA")); + limPrintMacAddr(pMac, pSta->staAddr, LOGE); + limSendDisassocMgmtFrame(pMac, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + pSta->staAddr, psessionEntry, FALSE); + limTriggerSTAdeletion(pMac, pSta, psessionEntry); + pSta->pmfSaQueryState = DPH_SA_QUERY_TIMED_OUT; + return; + } + + // Retry SA Query + limSendSaQueryRequestFrame(pMac, (tANI_U8 *)&(pSta->pmfSaQueryCurrentTransId), + pSta->staAddr, psessionEntry); + pSta->pmfSaQueryCurrentTransId++; + limLog(pMac, LOGE, FL("Starting SA Query retry %d"), pSta->pmfSaQueryRetryCount); + if (tx_timer_activate(&pSta->pmfSaQueryTimer) != TX_SUCCESS) + { + limLog(pMac, LOGE, FL("PMF SA Query timer activation failed!")); + pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; + } +} +#endif + + +#ifdef WLAN_FEATURE_11AC +tANI_BOOLEAN limCheckVHTOpModeChange( tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U8 chanWidth, tANI_U8 staId, tANI_U8 *peerMac) +{ + tUpdateVHTOpMode tempParam; + + tempParam.opMode = chanWidth; + tempParam.staId = staId; + tempParam.smesessionId = psessionEntry->smeSessionId; + vos_mem_copy(tempParam.peer_mac, peerMac, + sizeof(tSirMacAddr)); + + limSendModeUpdate( pMac, &tempParam, psessionEntry ); + + return eANI_BOOLEAN_TRUE; +} + +tANI_BOOLEAN limSetNssChange( tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 rxNss, + tANI_U8 staId, tANI_U8 *peerMac) +{ + tUpdateRxNss tempParam; + + tempParam.rxNss = rxNss; + tempParam.staId = staId; + tempParam.smesessionId = psessionEntry->smeSessionId; + vos_mem_copy(tempParam.peer_mac, peerMac, + sizeof(tSirMacAddr)); + + limSendRxNssUpdate( pMac, &tempParam, psessionEntry ); + + return eANI_BOOLEAN_TRUE; +} + +tANI_BOOLEAN limCheckMembershipUserPosition( tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U32 membership, tANI_U32 userPosition, + tANI_U8 staId) +{ + tUpdateMembership tempParamMembership; + tUpdateUserPos tempParamUserPosition; + + tempParamMembership.membership = membership; + tempParamMembership.staId = staId; + tempParamMembership.smesessionId = psessionEntry->smeSessionId; + vos_mem_copy(tempParamMembership.peer_mac, psessionEntry->bssId, + sizeof( tSirMacAddr )); + + + limSetMembership( pMac, &tempParamMembership, psessionEntry ); + + tempParamUserPosition.userPos = userPosition; + tempParamUserPosition.staId = staId; + tempParamUserPosition.smesessionId = psessionEntry->smeSessionId; + vos_mem_copy(tempParamUserPosition.peer_mac, psessionEntry->bssId, + sizeof( tSirMacAddr )); + + + limSetUserPos( pMac, &tempParamUserPosition, psessionEntry ); + + return eANI_BOOLEAN_TRUE; +} +#endif + +void limGetShortSlotFromPhyMode(tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U32 phyMode, tANI_U8 *pShortSlotEnabled) +{ + tANI_U8 val=0; + + //only 2.4G band should have short slot enable, rest it should be default + if (phyMode == WNI_CFG_PHY_MODE_11G) + { + /* short slot is default in all other modes */ + if ((psessionEntry->pePersona == VOS_STA_SAP_MODE) || + (psessionEntry->pePersona == VOS_IBSS_MODE) || + (psessionEntry->pePersona == VOS_P2P_GO_MODE)) + { + val = true; + } + if (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) + { + // Joining BSS. + val = SIR_MAC_GET_SHORT_SLOT_TIME( psessionEntry->limCurrentBssCaps); + } + else if (psessionEntry->limMlmState == eLIM_MLM_WT_REASSOC_RSP_STATE) + { + // Reassociating with AP. + val = SIR_MAC_GET_SHORT_SLOT_TIME( psessionEntry->limReassocBssCaps); + } + } + else + { + /* + * 11B does not short slot and short slot is default + * for 11A mode. Hence, not need to set this bit + */ + val = false; + } + + limLog(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u"), phyMode, val); + *pShortSlotEnabled = val; +} + +void limUtilsframeshtons(tpAniSirGlobal pCtx, + tANI_U8 *pOut, + tANI_U16 pIn, + tANI_U8 fMsb) +{ + (void)pCtx; +#if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + if ( !fMsb ) + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 2); + } + else + { + *pOut = ( pIn & 0xff00 ) >> 8; + *( pOut + 1 ) = pIn & 0xff; + } +#else + if ( !fMsb ) + { + *pOut = pIn & 0xff; + *( pOut + 1 ) = ( pIn & 0xff00 ) >> 8; + } + else + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 2); + } +#endif +} + +void limUtilsframeshtonl(tpAniSirGlobal pCtx, + tANI_U8 *pOut, + tANI_U32 pIn, + tANI_U8 fMsb) +{ + (void)pCtx; +#if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + if ( !fMsb ) + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 4); + } + else + { + *pOut = ( pIn & 0xff000000 ) >> 24; + *( pOut + 1 ) = ( pIn & 0x00ff0000 ) >> 16; + *( pOut + 2 ) = ( pIn & 0x0000ff00 ) >> 8; + *( pOut + 3 ) = ( pIn & 0x000000ff ); + } +#else + if ( !fMsb ) + { + *( pOut ) = ( pIn & 0x000000ff ); + *( pOut + 1 ) = ( pIn & 0x0000ff00 ) >> 8; + *( pOut + 2 ) = ( pIn & 0x00ff0000 ) >> 16; + *( pOut + 3 ) = ( pIn & 0xff000000 ) >> 24; + } + else + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 4); + } +#endif +} + +#ifdef WLAN_FEATURE_11W +/** + * + * \brief This function is called by various LIM modules to correctly set + * the Protected bit in the Frame Control Field of the 802.11 frame MAC header + * + * + * \param pMac Pointer to Global MAC structure + * + * \param psessionEntry Pointer to session corresponding to the connection + * + * \param peer Peer address of the STA to which the frame is to be sent + * + * \param pMacHdr Pointer to the frame MAC header + * + * \return nothing + * + * + */ +void +limSetProtectedBit(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacAddr peer, + tpSirMacMgmtHdr pMacHdr) +{ + tANI_U16 aid; + tpDphHashNode pStaDs; + + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + pStaDs = dphLookupHashEntry( pMac, peer, &aid, + &psessionEntry->dph.dphHashTable ); + if( pStaDs != NULL ) + /* rmfenabled will be set at the time of addbss. + * but sometimes EAP auth fails and keys are not + * installed then if we send any management frame + * like deauth/disassoc with this bit set then + * firmware crashes. so check for keys are + * installed or not also before setting the bit + */ + if (pStaDs->rmfEnabled && pStaDs->isKeyInstalled) + pMacHdr->fc.wep = 1; + } + else if ( psessionEntry->limRmfEnabled && psessionEntry->isKeyInstalled) + pMacHdr->fc.wep = 1; +} /*** end limSetProtectedBit() ***/ +#endif + +tANI_U8* lim_get_ie_ptr(tANI_U8 *pIes, int length, tANI_U8 eid) +{ + int left = length; + tANI_U8 *ptr = pIes; + tANI_U8 elem_id, elem_len; + + while(left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) + { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), + eid,elem_len, left); + + return NULL; + } + if (elem_id == eid) + { + return ptr; + } + + left -= elem_len; + ptr += (elem_len + 2); + } + return NULL; +} + +void lim_set_ht_caps(tpAniSirGlobal p_mac, tpPESession p_session_entry, + tANI_U8 *p_ie_start,tANI_U32 num_bytes) +{ + v_U8_t *p_ie=NULL; + tDot11fIEHTCaps dot11_ht_cap = {0,}; + + PopulateDot11fHTCaps(p_mac, p_session_entry, &dot11_ht_cap); + p_ie = limGetIEPtr(p_mac, p_ie_start, num_bytes, DOT11F_EID_HTCAPS, + ONE_BYTE); + limLog( p_mac, LOG2, FL("p_ie %p dot11_ht_cap.supportedMCSSet[0]=0x%x"), + p_ie, dot11_ht_cap.supportedMCSSet[0]); + + if(p_ie) + { + /* convert from unpacked to packed structure */ + tHtCaps *p_ht_cap = (tHtCaps *)&p_ie[2]; + + p_ht_cap->advCodingCap = dot11_ht_cap.advCodingCap; + p_ht_cap->supportedChannelWidthSet = + dot11_ht_cap.supportedChannelWidthSet; + p_ht_cap->mimoPowerSave = dot11_ht_cap.mimoPowerSave; + p_ht_cap->greenField = dot11_ht_cap.greenField; + p_ht_cap->shortGI20MHz = dot11_ht_cap.shortGI20MHz; + p_ht_cap->shortGI40MHz = dot11_ht_cap.shortGI40MHz; + p_ht_cap->txSTBC = dot11_ht_cap.txSTBC; + p_ht_cap->rxSTBC = dot11_ht_cap.rxSTBC; + p_ht_cap->delayedBA = dot11_ht_cap.delayedBA ; + p_ht_cap->maximalAMSDUsize = dot11_ht_cap.maximalAMSDUsize; + p_ht_cap->dsssCckMode40MHz = dot11_ht_cap.dsssCckMode40MHz; + p_ht_cap->psmp = dot11_ht_cap.psmp; + p_ht_cap->stbcControlFrame = dot11_ht_cap.stbcControlFrame; + p_ht_cap->lsigTXOPProtection = dot11_ht_cap.lsigTXOPProtection; + p_ht_cap->maxRxAMPDUFactor = dot11_ht_cap.maxRxAMPDUFactor; + p_ht_cap->mpduDensity = dot11_ht_cap.mpduDensity; + vos_mem_copy((void *)p_ht_cap->supportedMCSSet, + (void *)(dot11_ht_cap.supportedMCSSet), + sizeof(p_ht_cap->supportedMCSSet)); + p_ht_cap->pco = dot11_ht_cap.pco; + p_ht_cap->transitionTime = dot11_ht_cap.transitionTime; + p_ht_cap->mcsFeedback = dot11_ht_cap.mcsFeedback; + p_ht_cap->txBF = dot11_ht_cap.txBF; + p_ht_cap->rxStaggeredSounding = dot11_ht_cap.rxStaggeredSounding; + p_ht_cap->txStaggeredSounding = dot11_ht_cap.txStaggeredSounding; + p_ht_cap->rxZLF = dot11_ht_cap.rxZLF; + p_ht_cap->txZLF = dot11_ht_cap.txZLF; + p_ht_cap->implicitTxBF = dot11_ht_cap.implicitTxBF; + p_ht_cap->calibration = dot11_ht_cap.calibration; + p_ht_cap->explicitCSITxBF = dot11_ht_cap.explicitCSITxBF; + p_ht_cap->explicitUncompressedSteeringMatrix = + dot11_ht_cap.explicitUncompressedSteeringMatrix; + p_ht_cap->explicitBFCSIFeedback = dot11_ht_cap.explicitBFCSIFeedback; + p_ht_cap->explicitUncompressedSteeringMatrixFeedback = + dot11_ht_cap.explicitUncompressedSteeringMatrixFeedback; + p_ht_cap->explicitCompressedSteeringMatrixFeedback = + dot11_ht_cap.explicitCompressedSteeringMatrixFeedback; + p_ht_cap->csiNumBFAntennae = dot11_ht_cap.csiNumBFAntennae; + p_ht_cap->uncompressedSteeringMatrixBFAntennae = + dot11_ht_cap.uncompressedSteeringMatrixBFAntennae; + p_ht_cap->compressedSteeringMatrixBFAntennae = + dot11_ht_cap.compressedSteeringMatrixBFAntennae; + p_ht_cap->antennaSelection = dot11_ht_cap.antennaSelection; + p_ht_cap->explicitCSIFeedbackTx = dot11_ht_cap.explicitCSIFeedbackTx; + p_ht_cap->antennaIndicesFeedbackTx = + dot11_ht_cap.antennaIndicesFeedbackTx; + p_ht_cap->explicitCSIFeedback = dot11_ht_cap.explicitCSIFeedback; + p_ht_cap->antennaIndicesFeedback = dot11_ht_cap.antennaIndicesFeedback; + p_ht_cap->rxAS = dot11_ht_cap.rxAS; + p_ht_cap->txSoundingPPDUs = dot11_ht_cap.txSoundingPPDUs; + } +} + +#ifdef WLAN_FEATURE_11AC +void lim_set_vht_caps(tpAniSirGlobal p_mac, tpPESession p_session_entry, + tANI_U8 *p_ie_start,tANI_U32 num_bytes) +{ + v_U8_t *p_ie=NULL; + tDot11fIEVHTCaps dot11_vht_cap; + + PopulateDot11fVHTCaps(p_mac, p_session_entry, &dot11_vht_cap); + p_ie = limGetIEPtr(p_mac, p_ie_start, num_bytes, DOT11F_EID_VHTCAPS, + ONE_BYTE); + + if(p_ie) { + tSirMacVHTCapabilityInfo *vht_cap = + (tSirMacVHTCapabilityInfo *) &p_ie[2]; + tSirVhtMcsInfo *vht_mcs = (tSirVhtMcsInfo *) + &p_ie[2 + sizeof(tSirMacVHTCapabilityInfo)]; + union { + tANI_U16 u_value; + tSirMacVHTRxSupDataRateInfo vht_rx_supp_rate; + tSirMacVHTTxSupDataRateInfo vht_tx_supp_rate; + } u_vht_data_rate_info; + + + vht_cap->maxMPDULen = dot11_vht_cap.maxMPDULen; + vht_cap->supportedChannelWidthSet = + dot11_vht_cap.supportedChannelWidthSet; + vht_cap->ldpcCodingCap = dot11_vht_cap.ldpcCodingCap; + vht_cap->shortGI80MHz = dot11_vht_cap.shortGI80MHz; + vht_cap->shortGI160and80plus80MHz = + dot11_vht_cap.shortGI160and80plus80MHz; + vht_cap->txSTBC = dot11_vht_cap.txSTBC; + vht_cap->rxSTBC = dot11_vht_cap.rxSTBC; + vht_cap->suBeamFormerCap = dot11_vht_cap.suBeamFormerCap; + vht_cap->suBeamformeeCap = dot11_vht_cap.suBeamformeeCap; + vht_cap->csnofBeamformerAntSup = dot11_vht_cap.csnofBeamformerAntSup; + vht_cap->numSoundingDim = dot11_vht_cap.numSoundingDim; + vht_cap->muBeamformerCap = dot11_vht_cap.muBeamformerCap; + vht_cap->muBeamformeeCap = dot11_vht_cap.muBeamformeeCap; + vht_cap->vhtTXOPPS = dot11_vht_cap.vhtTXOPPS; + vht_cap->htcVHTCap = dot11_vht_cap.htcVHTCap; + vht_cap->maxAMPDULenExp = dot11_vht_cap.maxAMPDULenExp; + vht_cap->vhtLinkAdaptCap = dot11_vht_cap.vhtLinkAdaptCap; + vht_cap->rxAntPattern = dot11_vht_cap.rxAntPattern; + vht_cap->txAntPattern = dot11_vht_cap.txAntPattern; + vht_cap->reserved1 = dot11_vht_cap.reserved1; + + /* Populate VHT MCS Information */ + vht_mcs->rxMcsMap = dot11_vht_cap.rxMCSMap; + u_vht_data_rate_info.vht_rx_supp_rate.rxSupDataRate = + dot11_vht_cap.rxHighSupDataRate; + u_vht_data_rate_info.vht_rx_supp_rate.reserved = + dot11_vht_cap.reserved2; + vht_mcs->rxHighest = u_vht_data_rate_info.u_value; + + vht_mcs->txMcsMap = dot11_vht_cap.txMCSMap; + u_vht_data_rate_info.vht_tx_supp_rate.txSupDataRate = + dot11_vht_cap.txSupDataRate; + u_vht_data_rate_info.vht_tx_supp_rate.reserved = + dot11_vht_cap.reserved3; + vht_mcs->txHighest = u_vht_data_rate_info.u_value; + } +} +#endif /* WLAN_FEATURE_11AC */ + +#ifdef SAP_AUTH_OFFLOAD +static tpDphHashNode +_sap_offload_parse_assoc_req(tpAniSirGlobal pmac, + tpSirAssocReq assoc_req, + struct sap_offload_add_sta_req *add_sta_req, bool *pinuse) +{ + tpSirMacAssocReqFrame mac_assoc_req = NULL; + tpSirAssocReq temp_assoc_req; + tSirRetStatus status; + tpSirMacMgmtHdr mac_hdr = NULL; + tpDphHashNode sta_ds = NULL; + uint8_t *frame_body; + + tpPESession session_entry = limIsApSessionActive(pmac); + mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req; + + if (dph_entry_exist(pmac, + mac_hdr->sa, + add_sta_req->assoc_id, + &session_entry->dph.dphHashTable)) { + *pinuse = true; + return NULL; + } + + /* Update Attribute and Remove IE for + * Software AP Authentication Offload + */ + frame_body = (tANI_U8 *)add_sta_req->conn_req + sizeof(*mac_hdr); + mac_assoc_req = (tpSirMacAssocReqFrame)frame_body; + mac_assoc_req->capabilityInfo.privacy = 0; + + if (mac_hdr->fc.subType == SIR_MAC_MGMT_ASSOC_REQ) { + status = sirConvertAssocReqFrame2Struct(pmac, + frame_body, + add_sta_req->conn_req_len, + assoc_req); + } else { + status = sirConvertReassocReqFrame2Struct(pmac, + frame_body, + add_sta_req->conn_req_len, + assoc_req); + } + + if (status != eSIR_SUCCESS) { + limLog(pmac, LOGW, FL("sap_offload_add_sta_req parse error\n")); + 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, + mac_hdr->sa, + 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(mac_hdr->sa)); + 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; +} + +static void +_sap_offload_parse_sta_capability(tpDphHashNode sta_ds, + tpSirAssocReq assoc_req, + struct sap_offload_add_sta_req *add_sta_req) +{ + tpSirMacMgmtHdr mac_hdr = NULL; + + mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_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; + + /* Re/Assoc Response frame to requesting STA */ + sta_ds->mlmStaContext.subType = mac_hdr->fc.subType; + + 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; +} + +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, + 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; + } + +#ifdef WLAN_FEATURE_11AC + if (assoc_req->operMode.present) { + sta_ds->vhtSupportedRxNss = assoc_req->operMode.rxNSS + 1; + } else { + sta_ds->vhtSupportedRxNss = + ((sta_ds->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2) + == MCSMAPMASK2x2) ? 1 : 2; + } +#endif + + return eSIR_SUCCESS; +error: + return eSIR_FAILURE; +} + +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_pop_sap_deferred_msg() - pop deferred sap message + * + * @pmac: pointer to mac + * @psessionentry: session of this entry + * + * This function is used to pop msg that in the deferred queue. + * + */ +void +lim_pop_sap_deferred_msg(tpAniSirGlobal pmac, tpPESession sessionentry) +{ + struct slim_deferred_sap_msg* pdefermsg, *tmp; + tpSirMacMgmtHdr mac_hdr; + struct sap_offload_add_sta_req *add_sta_req; + tANI_U32 assoc_id; + + if (pmac == NULL || sessionentry == NULL ) + return; + + TAILQ_FOREACH_SAFE(pdefermsg, &pmac->lim.glim_sap_deferred_msgq.tq_head, + list_elem, tmp) { + + add_sta_req = pdefermsg->deferredmsg.bodyptr; + if (add_sta_req == NULL) { + TAILQ_REMOVE(&pmac->lim.glim_sap_deferred_msgq.tq_head, + pdefermsg, list_elem); + limDeferMsg(pmac, &pdefermsg->deferredmsg); + vos_mem_free(pdefermsg); + continue; + } + assoc_id = add_sta_req->assoc_id; + mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req; + + if (mac_hdr == NULL) { + TAILQ_REMOVE(&pmac->lim.glim_sap_deferred_msgq.tq_head, + pdefermsg, list_elem); + limDeferMsg(pmac, &pdefermsg->deferredmsg); + vos_mem_free(pdefermsg); + continue; + } + if (!dph_entry_exist(pmac, + mac_hdr->sa, assoc_id, + &sessionentry->dph.dphHashTable)) { + TAILQ_REMOVE(&pmac->lim.glim_sap_deferred_msgq.tq_head, + pdefermsg, list_elem); + + limLog(pmac, LOGE, FL("pop def msg(H %p T %p)." + "assid= %d, %pM"), + TAILQ_FIRST(&pmac->lim.glim_sap_deferred_msgq.tq_head), + TAILQ_LAST(&pmac->lim.glim_sap_deferred_msgq.tq_head, + t_slim_deferred_sap_msg_head), + assoc_id, mac_hdr->sa); + limDeferMsg(pmac, &pdefermsg->deferredmsg); + vos_mem_free(pdefermsg); + } + limLog(pmac, LOGE, FL("msg not pop." + "assid= %d, %pM"), assoc_id, mac_hdr->sa); + } +} + +/** + * lim_push_sap_deferred_msg() - push sap message into queue + * + * @pmac: pointer to mac + * @lim_msgq: msg queue to store deferred msg + * + * This function is used to store msg into deferred queue. + * + */ +void +lim_push_sap_deferred_msg(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq) +{ + struct slim_deferred_sap_msg *pdefermsg; + + pdefermsg = vos_mem_malloc(sizeof(*pdefermsg)); + if (pdefermsg == NULL) { + limLog(pmac, LOGE, FL("No mem for push msg %p!"), lim_msgq); + vos_mem_free(lim_msgq->bodyptr); + return; + } + vos_mem_copy((tANI_U8 *)&pdefermsg->deferredmsg, + (tANI_U8 *)lim_msgq, + sizeof(tSirMsgQ)); + TAILQ_INSERT_TAIL(&pmac->lim.glim_sap_deferred_msgq.tq_head, pdefermsg, + list_elem); + + limLog(pmac, LOGW, FL("push def msg(H %p T %p): P %p."), + TAILQ_FIRST(&pmac->lim.glim_sap_deferred_msgq.tq_head), + TAILQ_LAST(&pmac->lim.glim_sap_deferred_msgq.tq_head, + t_slim_deferred_sap_msg_head), + pdefermsg); +} + +/** + * lim_init_sap_deferred_msg() - init sap deferred msg queue head + * + * @pmac: pointer to mac + * + * This function is used to int sap deferred msg queue head + * + */ +void +lim_init_sap_deferred_msg_queue(tpAniSirGlobal pmac) +{ + TAILQ_INIT(&pmac->lim.glim_sap_deferred_msgq.tq_head); +} + +/** + * lim_cleanup_sap_deferred_msg() - cleanup sap deferred msg queue elements + * + * @pmac: pointer to mac + * + * This function is used to cleanup sap deferred msg queue elements + * + */ +void +lim_cleanup_sap_deferred_msg_queue(tpAniSirGlobal pmac) +{ + struct slim_deferred_sap_msg *pdefermsg; + tSirMsgQ *lim_msgq; + + while (!TAILQ_EMPTY(&pmac->lim.glim_sap_deferred_msgq.tq_head)) { + pdefermsg = (struct slim_deferred_sap_msg*)TAILQ_FIRST( + &pmac->lim.glim_sap_deferred_msgq.tq_head); + lim_msgq = &pdefermsg->deferredmsg; + vos_mem_free(lim_msgq->bodyptr); + vos_mem_free(pdefermsg); + } +} + +void lim_sap_offload_add_sta(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq) +{ + tpSirAssocReq assoc_req = NULL; + tpDphHashNode sta_ds = NULL; + tpSirMacMgmtHdr mac_hdr = NULL; + struct sap_offload_add_sta_req *add_sta_req = NULL; + tpPESession session_entry = limIsApSessionActive(pmac); + bool sta_inuse = false; + + add_sta_req = (struct sap_offload_add_sta_req *)lim_msgq->bodyptr; + mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req; + + limLog(pmac, LOGW, FL("sta %pM aid %d"), + mac_hdr->sa, add_sta_req->assoc_id); + + if (session_entry == NULL) { + PELOGE(limLog(pmac, LOGE, FL(" Session not found"));) + return; + } + assoc_req = vos_mem_malloc(sizeof(*assoc_req)); + if (NULL == assoc_req) { + PELOGE(limLog(pmac, LOGE, FL("Allocate Memory failed in assoc_req"));) + goto error; + } + 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, &sta_inuse); + + if (sta_inuse == true) { + lim_push_sap_deferred_msg(pmac, lim_msgq); + vos_mem_free(assoc_req ); + return; + } + + if (sta_ds == NULL) { + limSendDisassocMgmtFrame(pmac, + eSIR_MAC_UNSPEC_FAILURE_REASON, + mac_hdr->sa, + session_entry, FALSE); + PELOGE(limLog(pmac, LOGE, FL("could not add hash entry." + " disassoc sta %pM"),mac_hdr->sa);) + 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) { + limSendDisassocMgmtFrame(pmac, + eSIR_MAC_UNSPEC_FAILURE_REASON, + mac_hdr->sa, + session_entry, FALSE); + PELOGE(limLog(pmac, LOGE, FL("mismatch ht/vht information" + " disassoc sta %pM"),mac_hdr->sa);) + vos_mem_free(assoc_req); + goto error; + } + + /* Parse Station QOS information */ + _sap_offload_parse_sta_qos(pmac, sta_ds, assoc_req); + + if (assoc_req->ExtCap.present) { + lim_set_stads_rtt_cap(sta_ds, + (struct s_ext_cap *) assoc_req->ExtCap.bytes); + } else { + sta_ds->timingMeasCap = 0; + PELOG1(limLog(pmac, LOG1, FL("ExtCap not present"));) + } + + session_entry->parsedAssocReq[sta_ds->assocId] = assoc_req; + + if (limAddSta(pmac, sta_ds, false, session_entry) != eSIR_SUCCESS) { + limLog(pmac, LOGE, FL("could not Add STA %pM with assocId=%d"), + mac_hdr->sa, sta_ds->assocId); + limSendDisassocMgmtFrame(pmac, + eSIR_MAC_UNSPEC_FAILURE_REASON, + mac_hdr->sa, + session_entry, FALSE); + } + +error: + vos_mem_free(add_sta_req); + return; +} + +void +lim_sap_offload_del_sta(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq) +{ + struct sap_offload_del_sta_req *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"));) + return; + } + + del_sta_req = ( struct sap_offload_del_sta_req *)lim_msgq->bodyptr; + sta_ds = dphLookupHashEntry(pmac, + del_sta_req->sta_mac, + &assoc_id, + &psession_entry->dph.dphHashTable); + limLog(pmac, LOGW, FL("sta %pM aid %d reason %x flag %x"), + del_sta_req->sta_mac, del_sta_req->assoc_id, + del_sta_req->reason_code,del_sta_req->flags); + + 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_code, + MAC_ADDR_ARRAY(del_sta_req->sta_mac));) + 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; + + if (SAP_OFL_DEL_STA_FLAG_RECONNECT == del_sta_req->flags) { + sta_ds->mlmStaContext.disassocReason = + (tSirMacReasonCodes)eSIR_SME_SAP_AUTH_OFFLOAD_PEER_UPDATE_STATUS; + } else { + sta_ds->mlmStaContext.disassocReason = + (tSirMacReasonCodes)del_sta_req->reason_code; + } + sta_ds->mlmStaContext.updateContext = 1; + + limSendSmeDisassocInd(pmac, sta_ds, psession_entry); + +error: + vos_mem_free(del_sta_req); + return; +} +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * lim_validate_received_frame_a1_addr() - To validate received frame's A1 addr + * @mac_ctx: pointer to mac context + * @a1: received frame's a1 address which is nothing but our self address + * @session: PE session pointer + * + * This routine will validate, A1 addres of the received frame + * + * Return: true or false + */ +bool lim_validate_received_frame_a1_addr(tpAniSirGlobal mac_ctx, + tSirMacAddr a1, tpPESession session) +{ + if (mac_ctx == NULL || session == NULL) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "mac or session context is null"); + /* let main routine handle it */ + return true; + } + if (limIsGroupAddr(a1) || limIsAddrBC(a1)) { + /* just for fail safe, don't handle MC/BC a1 in this routine */ + return true; + } + if (!vos_mem_compare(a1, session->selfMacAddr, 6)) { + limLog(mac_ctx, LOGE, + FL("Invalid A1 address in received frame")); + return false; + } + return true; +} + +/** + * lim_set_stads_rtt_cap() - update station node RTT capability + * @sta_ds: Station hash node + * @ext_cap: Pointer to extended capability + * + * This funciton update hash node's RTT capability based on received + * Extended capability IE. + * + * Return: None + */ +void lim_set_stads_rtt_cap(tpDphHashNode sta_ds, struct s_ext_cap *ext_cap) +{ + sta_ds->timingMeasCap = 0; + sta_ds->timingMeasCap |= (ext_cap->timingMeas)? + RTT_TIMING_MEAS_CAPABILITY : + RTT_INVALID; + sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_initiator)? + RTT_FINE_TIME_MEAS_INITIATOR_CAPABILITY : + RTT_INVALID; + sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_responder)? + RTT_FINE_TIME_MEAS_RESPONDER_CAPABILITY : + RTT_INVALID; + + PELOG1(limLog(pMac, LOG1, + FL("ExtCap present, timingMeas: %d Initiator: %d Responder: %d"), + ext_cap->timingMeas, ext_cap->fine_time_meas_initiator, + ext_cap->fine_time_meas_responder);) +} + +/** + * lim_check_and_reset_protection_params() - reset protection related parameters + * + * @mac_ctx: pointer to global mac structure + * + * resets protection related global parameters if the pe active session count + * is zero. + * + * Return: None + */ +void lim_check_and_reset_protection_params(tpAniSirGlobal mac_ctx) +{ + if (!pe_get_active_session_count(mac_ctx)) { + vos_mem_zero(&mac_ctx->lim.gLimOverlap11gParams, + sizeof(mac_ctx->lim.gLimOverlap11gParams)); + vos_mem_zero(&mac_ctx->lim.gLimOverlap11aParams, + sizeof(mac_ctx->lim.gLimOverlap11aParams)); + vos_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params, + sizeof(mac_ctx->lim.gLimOverlapHt20Params)); + vos_mem_zero(&mac_ctx->lim.gLimOverlapNonGfParams, + sizeof(mac_ctx->lim.gLimOverlapNonGfParams)); + + mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } +} + +/** + * lim_send_ext_cap_ie() - send ext cap IE to FW + * @mac_ctx: global MAC context + * @session_entry: PE session + * @extra_extcap: extracted ext cap + * @merge: merge extra ext cap + * + * This function is invoked after VDEV is created to update firmware + * about the extended capabilities that the corresponding VDEV is capable + * of. Since STA/SAP can have different Extended capabilities set, this function + * is called per vdev creation. + * + * Return: eHalStatus + */ +eHalStatus lim_send_ext_cap_ie(tpAniSirGlobal mac_ctx, + uint32_t session_id, + tDot11fIEExtCap *extra_extcap, bool merge) +{ + tDot11fIEExtCap ext_cap_data = {0}; + uint32_t dot11mode, num_bytes; + bool vht_enabled = false; + struct vdev_ie_info *vdev_ie; + vos_msg_t msg = {0}; + tSirRetStatus status; + uint8_t *temp, i; + + wlan_cfgGetInt(mac_ctx, WNI_CFG_DOT11_MODE, &dot11mode); + if (IS_DOT11_MODE_VHT(dot11mode)) + vht_enabled = true; + + status = PopulateDot11fExtCap(mac_ctx, vht_enabled, &ext_cap_data, + NULL); + if (eSIR_SUCCESS != status) { + limLog(mac_ctx, LOGE, FL("Failed to populate ext cap IE")); + return eHAL_STATUS_FAILURE; + } + num_bytes = ext_cap_data.num_bytes; + + if (merge && NULL != extra_extcap && extra_extcap->num_bytes > 0) { + if (extra_extcap->num_bytes > ext_cap_data.num_bytes) + num_bytes = extra_extcap->num_bytes; + lim_merge_extcap_struct(&ext_cap_data, extra_extcap); + } + + /* Allocate memory for the WMI request, and copy the parameter */ + vdev_ie = vos_mem_malloc(sizeof(*vdev_ie) + num_bytes); + if (!vdev_ie) { + limLog(mac_ctx, LOGE, FL("Failed to allocate memory")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vdev_ie->vdev_id = session_id; + vdev_ie->ie_id = DOT11F_EID_EXTCAP; + vdev_ie->length = num_bytes; + + limLog(mac_ctx, LOG1, FL("vdev %d ieid %d len %d"), session_id, + DOT11F_EID_EXTCAP, num_bytes); + temp = ext_cap_data.bytes; + for (i=0; i < num_bytes; i++, temp++) + limLog(mac_ctx, LOG1, FL("%d byte is %02x"), i+1, *temp); + + vdev_ie->data = (uint8_t *)vdev_ie + sizeof(*vdev_ie); + vos_mem_copy(vdev_ie->data, ext_cap_data.bytes, num_bytes); + + msg.type = WDA_SET_IE_INFO; + msg.bodyptr = vdev_ie; + msg.reserved = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { + limLog(mac_ctx, LOGE, + FL("Not able to post WDA_SET_IE_INFO to WDA")); + vos_mem_free(vdev_ie); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * lim_strip_extcap_ie() - strip extended capability IE from IE buffer + * @mac_ctx: global MAC context + * @addn_ie: Additional IE buffer + * @addn_ielen: Length of additional IE + * @extracted_ie: if not NULL, copy the stripped IE to this buffer + * + * This utility function is used to strip of the extended capability IE present + * in additional IE buffer. + * + * Return: tSirRetStatus + */ +tSirRetStatus lim_strip_extcap_ie(tpAniSirGlobal mac_ctx, + uint8_t *addn_ie, uint16_t *addn_ielen, uint8_t *extracted_ie) +{ + uint8_t* tempbuf = NULL; + uint16_t templen = 0; + int left = *addn_ielen; + uint8_t *ptr = addn_ie; + uint8_t elem_id, elem_len; + + if (NULL == addn_ie) { + limLog(mac_ctx, LOG1, FL("NULL addn_ie pointer")); + return eSIR_IGNORE_IE ; + } + + tempbuf = vos_mem_malloc(left); + if (NULL == tempbuf) { + limLog(mac_ctx, LOGE, FL("Unable to allocate memory")); + return eSIR_MEM_ALLOC_FAILED; + } + + while(left >= 2) { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if (elem_len > left) { + limLog( mac_ctx, LOGE, + FL("Invalid IEs eid = %d elem_len=%d left=%d"), + elem_id, elem_len, left); + vos_mem_free(tempbuf); + return eSIR_FAILURE; + } + if (!(DOT11F_EID_EXTCAP == elem_id)) { + vos_mem_copy (tempbuf + templen, &ptr[0], elem_len + 2); + templen += (elem_len + 2); + } else { + if (NULL != extracted_ie) { + vos_mem_set(extracted_ie, + DOT11F_IE_EXTCAP_MAX_LEN + 2, 0); + if (elem_len <= DOT11F_IE_EXTCAP_MAX_LEN) + vos_mem_copy(extracted_ie, &ptr[0], + elem_len + 2); + } + } + left -= elem_len; + ptr += (elem_len + 2); + } + vos_mem_copy (addn_ie, tempbuf, templen); + + *addn_ielen = templen; + vos_mem_free(tempbuf); + + return eSIR_SUCCESS; +} + +/** + * lim_update_extcap_struct() - poputlate the dot11f structure + * @mac_ctx: global MAC context + * @buf: extracted IE buffer + * @dst: extended capability IE structure to be updated + * + * This function is used to update the extended capability structure + * with @buf. + * + * Return: None + */ +void lim_update_extcap_struct(tpAniSirGlobal mac_ctx, + uint8_t *buf, tDot11fIEExtCap *dst) +{ + uint8_t out[DOT11F_IE_EXTCAP_MAX_LEN]; + + if (NULL == buf) { + limLog( mac_ctx, LOGE, FL("Invalid Buffer Address")); + return; + } + + if(NULL == dst) { + limLog(mac_ctx, LOGE, FL("NULL dst pointer")); + return ; + } + + if (DOT11F_EID_EXTCAP != buf[0] || buf[1] > DOT11F_IE_EXTCAP_MAX_LEN) { + limLog(mac_ctx, LOG1, FL("Invalid IEs eid = %d elem_len=%d "), + buf[0],buf[1]); + return; + } + + vos_mem_set((uint8_t *)&out[0], DOT11F_IE_EXTCAP_MAX_LEN, 0); + vos_mem_copy(&out[0], &buf[2], DOT11F_IE_EXTCAP_MAX_LEN); + + if (DOT11F_PARSE_SUCCESS != dot11fUnpackIeExtCap(mac_ctx, &out[0], + DOT11F_IE_EXTCAP_MAX_LEN, dst)) + limLog(mac_ctx, LOGE, FL("dot11fUnpackIeExtCap Parse Error ")); +} + +/** + * lim_strip_extcap_update_struct - strip extended capability IE and populate + * the dot11f structure + * @mac_ctx: global MAC context + * @addn_ie: Additional IE buffer + * @addn_ielen: Length of additional IE + * @dst: extended capability IE structure to be updated + * + * This function is used to strip extended capability IE from IE buffer and + * update the passed structure. + * + * Return: tSirRetStatus + */ +tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx, + uint8_t* addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst) +{ + uint8_t extracted_buff[DOT11F_IE_EXTCAP_MAX_LEN + 2]; + tSirRetStatus status; + + vos_mem_set((uint8_t* )&extracted_buff[0], DOT11F_IE_EXTCAP_MAX_LEN + 2, + 0); + status = lim_strip_extcap_ie(mac_ctx, addn_ie, addn_ielen, + extracted_buff); + if (eSIR_SUCCESS != status) { + limLog(mac_ctx, LOG1, + FL("Failed to strip extcap IE status = (%d)."), status); + return status; + } + + /* update the extracted ExtCap to struct*/ + lim_update_extcap_struct(mac_ctx, extracted_buff, dst); + return status; +} + +/** + * lim_merge_extcap_struct() - merge extended capabilities info + * @dst: destination extended capabilities + * @src: source extended capabilities + * + * This function is used to take @src info and merge it with @dst + * extended capabilities info. + * + * Return: None + */ +void lim_merge_extcap_struct(tDot11fIEExtCap *dst, + tDot11fIEExtCap *src) +{ + uint8_t *tempdst = (uint8_t *)dst->bytes; + uint8_t *tempsrc = (uint8_t *)src->bytes; + uint8_t structlen = member_size(tDot11fIEExtCap, bytes); + + while(tempdst && tempsrc && structlen--) { + *tempdst |= *tempsrc; + tempdst++; + tempsrc++; + } +} + +/** + * lim_get_80Mhz_center_channel - finds 80 Mhz center channel + * + * @primary_channel: Primary channel for given 80 MHz band + * + * There are fixed 80MHz band and for each fixed band there is only one center + * valid channel. Also location of primary channel decides what 80 MHz band will + * it use, hence it decides what center channel will be used. This function + * does thus calculation and returns the center channel. + * + * Return: center channel + */ +uint8_t +lim_get_80Mhz_center_channel(uint8_t primary_channel) +{ + if(primary_channel >= 36 && primary_channel <= 48) + return (36+48)/2; + if(primary_channel >= 52 && primary_channel <= 64) + return (52+64)/2; + if(primary_channel >= 100 && primary_channel <= 112) + return (100+112)/2; + if(primary_channel >= 116 && primary_channel <= 128) + return (116+128)/2; + if(primary_channel >= 132 && primary_channel <= 144) + return (132+144)/2; + if(primary_channel >= 149 && primary_channel <= 161) + return (149+161)/2; + + return HAL_INVALID_CHANNEL_ID; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h new file mode 100644 index 000000000000..83081c3453e1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file limUtils.h contains the utility definitions + * LIM uses. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __LIM_UTILS_H +#define __LIM_UTILS_H + +#include "sirApi.h" +#include "sirDebug.h" +#include "cfgApi.h" + +#include "limTypes.h" +#include "limScanResultUtils.h" +#include "limTimerUtils.h" +#include "limTrace.h" +typedef enum +{ + ONE_BYTE = 1, + TWO_BYTE = 2 +} eSizeOfLenField; + +#define LIM_STA_ID_MASK 0x00FF +#define LIM_AID_MASK 0xC000 +#define LIM_SPECTRUM_MANAGEMENT_BIT_MASK 0x0100 +#define LIM_RRM_BIT_MASK 0x1000 +#define LIM_SHORT_PREAMBLE_BIT_MASK 0x0020 +#define LIM_IMMEDIATE_BLOCK_ACK_MASK 0x8000 +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +#define LIM_MAX_REASSOC_RETRY_LIMIT 2 +#endif + +// classifier ID is coded as 0-3: tsid, 4-5:direction +#define LIM_MAKE_CLSID(tsid, dir) (((tsid) & 0x0F) | (((dir) & 0x03) << 4)) + +#define LIM_SET_STA_BA_STATE(pSta, tid, newVal) \ +{\ + pSta->baState = ((pSta->baState | (0x3 << tid*2)) & ((newVal << tid*2) | ~(0x3 << tid*2)));\ +} + +#define LIM_GET_STA_BA_STATE(pSta, tid, pCurVal)\ +{\ + *pCurVal = (tLimBAState)(((pSta->baState >> tid*2) & 0x3));\ +} + +#define VHT_MCS_3x3_MASK 0x30 +#define VHT_MCS_2x2_MASK 0x0C + +typedef struct sAddBaInfo +{ + tANI_U16 fBaEnable : 1; + tANI_U16 startingSeqNum: 12; + tANI_U16 reserved : 3; +}tAddBaInfo, *tpAddBaInfo; + +typedef struct sAddBaCandidate +{ + tSirMacAddr staAddr; + tAddBaInfo baInfo[STACFG_MAX_TC]; +}tAddBaCandidate, *tpAddBaCandidate; + +#ifdef WLAN_FEATURE_11W +typedef union uPmfSaQueryTimerId +{ + struct + { + tANI_U8 sessionId; + tANI_U16 peerIdx; + } fields; + tANI_U32 value; +} tPmfSaQueryTimerId, *tpPmfSaQueryTimerId; +#endif + +// LIM utility functions +void limGetBssidFromPkt(tpAniSirGlobal, tANI_U8 *, tANI_U8 *, tANI_U32 *); +char * limDot11ReasonStr(tANI_U16 reasonCode); +char * limMlmStateStr(tLimMlmStates state); +char * limResultCodeStr(tSirResultCodes resultCode); +void limPrintMlmState(tpAniSirGlobal pMac, tANI_U16 logLevel, tLimMlmStates state); +char* limBssTypeStr(tSirBssType bssType); + +#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI +extern tSirRetStatus limSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, + tPowerdBm txPower, + tpPESession pSessionEntry ); +extern tANI_U8 limGetMaxTxPower(tPowerdBm regMax, tPowerdBm apTxPower, tANI_U8 iniTxPower); +#endif + +tANI_U32 limPostMsgApiNoWait(tpAniSirGlobal, tSirMsgQ *); +tANI_U8 limIsAddrBC(tSirMacAddr); +tANI_U8 limIsGroupAddr(tSirMacAddr); + +// check for type of scan allowed +tANI_U8 limActiveScanAllowed(tpAniSirGlobal, tANI_U8); + +// AID pool management functions +void limInitPeerIdxpool(tpAniSirGlobal,tpPESession); +tANI_U16 limAssignPeerIdx(tpAniSirGlobal,tpPESession); + +void limEnableOverlap11gProtection(tpAniSirGlobal pMac, tpUpdateBeaconParams pBeaconParams, tpSirMacMgmtHdr pMh,tpPESession psessionEntry); +void limUpdateOverlapStaParam(tpAniSirGlobal pMac, tSirMacAddr bssId, tpLimProtStaParams pStaParams); +void limUpdateShortPreamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry); +void limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry); + +/* + * The below 'product' check to be removed if 'Association' is + * allowed in IBSS. + */ +void limReleasePeerIdx(tpAniSirGlobal, tANI_U16, tpPESession); + + +void limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeaconParams pBeaconParams,tpPESession); +void +limDecideApProtectionOnDelete(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry); + +extern tSirRetStatus limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession); +extern tSirRetStatus limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry); +extern tSirRetStatus limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry); +extern tSirRetStatus limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession sessionEntry); +extern tSirRetStatus limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession); +extern tSirRetStatus limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry); +extern tSirRetStatus limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession); +extern tSirRetStatus limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry); +extern tSirRetStatus limEnableHtOBSSProtection (tpAniSirGlobal pMac, tANI_U8 enable, tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams, tpPESession); +void limDecideStaProtection(tpAniSirGlobal pMac, tpSchBeaconStruct pBeaconStruct, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry); +void limDecideStaProtectionOnAssoc(tpAniSirGlobal pMac, tpSchBeaconStruct pBeaconStruct, tpPESession psessionEntry); +void limUpdateStaRunTimeHTSwitchChnlParams(tpAniSirGlobal pMac, tDot11fIEHTInfo * pHTInfo, tANI_U8 bssIdx, tpPESession psessionEntry); +// Print MAC address utility function +void limPrintMacAddr(tpAniSirGlobal, tSirMacAddr, tANI_U8); + + + +// Deferred Message Queue read/write +tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirMsgQ* limReadDeferredMsgQ(tpAniSirGlobal pMac); +void limHandleDeferMsgError(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg); + +// Deferred Message Queue Reset +void limResetDeferredMsgQ(tpAniSirGlobal pMac); + +tSirRetStatus limSysProcessMmhMsgApi(tpAniSirGlobal, tSirMsgQ*, tANI_U8); + +void limHandleUpdateOlbcCache(tpAniSirGlobal pMac); + +tANI_U8 limIsNullSsid( tSirMacSSid *pSsid ); + +void limProcessAddtsRspTimeout(tpAniSirGlobal pMac, tANI_U32 param); + +// 11h Support +void limStopTxAndSwitchChannel(tpAniSirGlobal pMac, tANI_U8 sessionId); +void limProcessChannelSwitchTimeout(tpAniSirGlobal); +tSirRetStatus limStartChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limUpdateChannelSwitch(tpAniSirGlobal, tpSirProbeRespBeacon, tpPESession psessionEntry); +void limProcessQuietTimeout(tpAniSirGlobal); +void limProcessQuietBssTimeout(tpAniSirGlobal); + +void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId); +void limSwitchPrimaryChannel(tpAniSirGlobal, tANI_U8,tpPESession); +void limSwitchPrimarySecondaryChannel(tpAniSirGlobal, tpPESession, tANI_U8, ePhyChanBondState); +tAniBool limTriggerBackgroundScanDuringQuietBss(tpAniSirGlobal); +void limUpdateStaRunTimeHTSwtichChnlParams(tpAniSirGlobal pMac, tDot11fIEHTInfo *pRcvdHTInfo, tANI_U8 bssIdx); +void limUpdateStaRunTimeHTCapability(tpAniSirGlobal pMac, tDot11fIEHTCaps *pHTCaps); +void limUpdateStaRunTimeHTInfo(struct sAniSirGlobal *pMac, tDot11fIEHTInfo *pRcvdHTInfo, tpPESession psessionEntry); +void limCancelDot11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry); +tAniBool limIsChannelValidForChannelSwitch(tpAniSirGlobal pMac, tANI_U8 channel); +void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLimControlTx mode); +tSirRetStatus limRestorePreChannelSwitchState(tpAniSirGlobal pMac, tpPESession psessionEntry); +tSirRetStatus limRestorePreQuietState(tpAniSirGlobal pMac, tpPESession psessionEntry); + +void limPrepareFor11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry); +void limSwitchChannelCback(tpAniSirGlobal pMac, eHalStatus status, + tANI_U32 *data, tpPESession psessionEntry); + +static inline tSirRFBand limGetRFBand(tANI_U8 channel) +{ + if ((channel >= SIR_11A_CHANNEL_BEGIN) && + (channel <= SIR_11A_CHANNEL_END)) + return SIR_BAND_5_GHZ; + + if ((channel >= SIR_11B_CHANNEL_BEGIN) && + (channel <= SIR_11B_CHANNEL_END)) + return SIR_BAND_2_4_GHZ; + + return SIR_BAND_UNKNOWN; +} + + +static inline tSirRetStatus +limGetMgmtStaid(tpAniSirGlobal pMac, tANI_U16 *staid, tpPESession psessionEntry) +{ + if (LIM_IS_AP_ROLE(psessionEntry)) + *staid = 1; + else if (LIM_IS_STA_ROLE(psessionEntry)) + *staid = 0; + else + return eSIR_FAILURE; + + return eSIR_SUCCESS; +} + +static inline tANI_U8 +limIsSystemInSetMimopsState(tpAniSirGlobal pMac) +{ + if (pMac->lim.gLimMlmState == eLIM_MLM_WT_SET_MIMOPS_STATE) + return true; + return false; +} + +static inline tANI_U8 + isEnteringMimoPS(tSirMacHTMIMOPowerSaveState curState, tSirMacHTMIMOPowerSaveState newState) + { + if (curState == eSIR_HT_MIMO_PS_NO_LIMIT && + (newState == eSIR_HT_MIMO_PS_DYNAMIC ||newState == eSIR_HT_MIMO_PS_STATIC)) + return TRUE; + return FALSE; +} + +static inline int limSelectCBMode(tDphHashNode *pStaDs, tpPESession psessionEntry, + tANI_U8 channel, tANI_U8 chan_bw) +{ + if ( pStaDs->mlmStaContext.vhtCapability && chan_bw) + { + if ( channel== 36 || channel == 52 || channel == 100 || + channel == 116 || channel == 149 ) + { + return PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1; + } + else if ( channel == 40 || channel == 56 || channel == 104 || + channel == 120 || channel == 153 ) + { + return PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1; + } + else if ( channel == 44 || channel == 60 || channel == 108 || + channel == 124 || channel == 157 ) + { + return PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1; + } + else if ( channel == 48 || channel == 64 || channel == 112 || + channel == 128 || channel == 161 ) + { + return PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1; + } + else if ( channel == 165 ) + { + return PHY_SINGLE_CHANNEL_CENTERED; + } + } + else if ( pStaDs->mlmStaContext.htCapability ) + { + if ( channel== 40 || channel == 48 || channel == 56 || + channel == 64 || channel == 104 || channel == 112 || + channel == 120 || channel == 128 || channel == 136 || + channel == 144 || channel == 153 || channel == 161 ) + { + return PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + } + else if ( channel== 36 || channel == 44 || channel == 52 || + channel == 60 || channel == 100 || channel == 108 || + channel == 116 || channel == 124 || channel == 132 || + channel == 140 || channel == 149 || channel == 157 ) + { + return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + } + else if ( channel == 165 ) + { + return PHY_SINGLE_CHANNEL_CENTERED; + } + } + return PHY_SINGLE_CHANNEL_CENTERED; +} + +/// ANI peer station count management and associated actions +void limUtilCountStaAdd(tpAniSirGlobal pMac, tpDphHashNode pSta, tpPESession psessionEntry); +void limUtilCountStaDel(tpAniSirGlobal pMac, tpDphHashNode pSta, tpPESession psessionEntry); + +tANI_U8 limGetHTCapability( tpAniSirGlobal, tANI_U32, tpPESession); +void limTxComplete( tHalHandle hHal, void *pData, v_BOOL_t free ); + +/**********Admit Control***************************************/ + +//callback function for HAL to issue DelTS request to PE. +//This function will be registered with HAL for callback when TSPEC inactivity timer fires. + +void limProcessDelTsInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirRetStatus limProcessHalIndMessages(tpAniSirGlobal pMac, tANI_U32 mesgId, void *mesgParam ); +tSirRetStatus limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr peerMacAddr,tpPESession psessionEntry); +/**********************************************************/ + +//callback function registration to HAL for any indication. +void limRegisterHalIndCallBack(tpAniSirGlobal pMac); +void limPktFree ( + tpAniSirGlobal pMac, + eFrameType frmType, + tANI_U8 *pBD, + void *body); + + + +void limGetBDfromRxPacket(tpAniSirGlobal pMac, void *body, tANI_U32 **pBD); + +/** + * \brief Given a base(X) and power(Y), this API will return + * the result of base raised to power - (X ^ Y) + * + * \sa utilsPowerXY + * + * \param base Base value + * + * \param power Base raised to this Power value + * + * \return Result of X^Y + * + */ +static inline tANI_U32 utilsPowerXY( tANI_U16 base, tANI_U16 power ) +{ +tANI_U32 result = 1, i; + + for( i = 0; i < power; i++ ) + result *= base; + + return result; +} + + + +tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tANI_U8 tid, tANI_U16 startingSeqNum,tpPESession psessionEntry); +tSirRetStatus limPostMlmAddBARsp( tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirMacStatusCodes baStatusCode, + tANI_U8 baDialogToken, + tANI_U8 baTID, + tANI_U8 baPolicy, + tANI_U16 baBufferSize, + tANI_U16 baTimeout, + tpPESession psessionEntry); +tSirRetStatus limPostMlmDelBAReq( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tANI_U8 baDirection, + tANI_U8 baTID, + tSirMacReasonCodes baReasonCode , + tpPESession psessionEntry); +tSirRetStatus limPostMsgAddBAReq( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tANI_U8 baDialogToken, + tANI_U8 baTID, + tANI_U8 baPolicy, + tANI_U16 baBufferSize, + tANI_U16 baTimeout, + tANI_U16 baSSN, + tANI_U8 baDirection, + tpPESession psessionEntry); +tSirRetStatus limPostMsgDelBAInd( tpAniSirGlobal pMac, + tpDphHashNode pSta, + tANI_U8 baTID, + tANI_U8 baDirection, + tpPESession psessionEntry); + +tSirRetStatus limPostSMStateUpdate(tpAniSirGlobal pMac, + tANI_U16 StaIdx, + tSirMacHTMIMOPowerSaveState MIMOPSState, + tANI_U8 *pPeerStaMac, tANI_U8 sessionId); + +void limDeleteStaContext(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void limDeleteBASessions(tpAniSirGlobal pMac, tpPESession pSessionEntry, tANI_U32 baDirection); +void limDelPerBssBASessionsBtc(tpAniSirGlobal pMac); +void limDelAllBASessions(tpAniSirGlobal pMac); +void limDeleteDialogueTokenList(tpAniSirGlobal pMac); +tSirRetStatus limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 assocId, tANI_U16 tid); +void limRessetScanChannelInfo(tpAniSirGlobal pMac); +void limAddScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 channelId); + +tANI_U8 limGetChannelFromBeacon(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon); +tSirNwType limGetNwType(tpAniSirGlobal pMac, tANI_U8 channelNum, tANI_U32 type, tpSchBeaconStruct pBeacon); +void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 action); + +void limSetTspecUapsdMaskPerSession(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacTSInfo *pTsInfo, + tANI_U32 action); + +void limHandleHeartBeatTimeout(tpAniSirGlobal pMac); +void limHandleHeartBeatTimeoutForSession(tpAniSirGlobal pMac, tpPESession psessionEntry); + +//void limProcessBtampAddBssRsp(tpAniSirGlobal pMac,tpSirMsgQ pMsgQ,tpPESession peSession); +void limProcessAddStaRsp(tpAniSirGlobal pMac,tpSirMsgQ pMsgQ); + +void limUpdateBeacon(tpAniSirGlobal pMac); + +void limProcessBtAmpApMlmAddStaRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ, tpPESession psessionEntry); +void limProcessBtAmpApMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry); + +void limProcessBtAmpApMlmDelStaRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ,tpPESession psessionEntry); +tpPESession limIsIBSSSessionActive(tpAniSirGlobal pMac); +tpPESession limIsApSessionActive(tpAniSirGlobal pMac); +void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac); + +void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ); +void limProcessAddStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ); +v_U8_t* limGetIEPtr(tpAniSirGlobal pMac, v_U8_t *pIes, int length, v_U8_t eid,eSizeOfLenField size_of_len_field); + +tANI_U8 limUnmapChannel(tANI_U8 mapChannel); + +#define limGetWscIEPtr(pMac, ie, ie_len) \ + cfg_get_vendor_ie_ptr_from_oui(pMac, SIR_MAC_WSC_OUI, SIR_MAC_WSC_OUI_SIZE, ie, ie_len) + +#define limGetP2pIEPtr(pMac, ie, ie_len) \ + cfg_get_vendor_ie_ptr_from_oui(pMac, SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE, ie, ie_len) + +v_U8_t limGetNoaAttrStreamInMultP2pIes(tpAniSirGlobal pMac,v_U8_t* noaStream,v_U8_t noaLen,v_U8_t overFlowLen); +v_U8_t limGetNoaAttrStream(tpAniSirGlobal pMac, v_U8_t*pNoaStream,tpPESession psessionEntry); + +v_U8_t limBuildP2pIe(tpAniSirGlobal pMac, tANI_U8 *ie, tANI_U8 *data, tANI_U8 ie_len); +tANI_BOOLEAN limIsNOAInsertReqd(tpAniSirGlobal pMac); +tANI_BOOLEAN limIsconnectedOnDFSChannel(tANI_U8 currentChannel); +tANI_U8 limGetCurrentOperatingChannel(tpAniSirGlobal pMac); + +uint32_t lim_get_max_rate_flags(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds); + +#ifdef WLAN_FEATURE_11AC +tANI_BOOLEAN limCheckVHTOpModeChange( tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U8 chanWidth, tANI_U8 staId, tANI_U8 *peerMac); +tANI_BOOLEAN limSetNssChange( tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U8 rxNss, tANI_U8 staId, tANI_U8 *peerMac); +tANI_BOOLEAN limCheckMembershipUserPosition( tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U32 membership, tANI_U32 userPosition, + tANI_U8 staId); +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + +typedef enum +{ + WLAN_PE_DIAG_SCAN_REQ_EVENT = 0, + WLAN_PE_DIAG_SCAN_ABORT_IND_EVENT, + WLAN_PE_DIAG_SCAN_RSP_EVENT, + WLAN_PE_DIAG_JOIN_REQ_EVENT, + WLAN_PE_DIAG_JOIN_RSP_EVENT, + WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT, + WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT, + WLAN_PE_DIAG_REASSOC_REQ_EVENT, + WLAN_PE_DIAG_REASSOC_RSP_EVENT, + WLAN_PE_DIAG_AUTH_REQ_EVENT, + WLAN_PE_DIAG_AUTH_RSP_EVENT = 10, + WLAN_PE_DIAG_DISASSOC_REQ_EVENT, + WLAN_PE_DIAG_DISASSOC_RSP_EVENT, + WLAN_PE_DIAG_DISASSOC_IND_EVENT, + WLAN_PE_DIAG_DISASSOC_CNF_EVENT, + WLAN_PE_DIAG_DEAUTH_REQ_EVENT, + WLAN_PE_DIAG_DEAUTH_RSP_EVENT, + WLAN_PE_DIAG_DEAUTH_IND_EVENT, + WLAN_PE_DIAG_START_BSS_REQ_EVENT, + WLAN_PE_DIAG_START_BSS_RSP_EVENT, + WLAN_PE_DIAG_AUTH_IND_EVENT = 20, + WLAN_PE_DIAG_ASSOC_IND_EVENT, + WLAN_PE_DIAG_ASSOC_CNF_EVENT, + WLAN_PE_DIAG_REASSOC_IND_EVENT, + WLAN_PE_DIAG_SWITCH_CHL_REQ_EVENT, + WLAN_PE_DIAG_SWITCH_CHL_RSP_EVENT, + WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, + WLAN_PE_DIAG_STOP_BSS_RSP_EVENT, + WLAN_PE_DIAG_DEAUTH_CNF_EVENT, + WLAN_PE_DIAG_ADDTS_REQ_EVENT, + WLAN_PE_DIAG_ADDTS_RSP_EVENT = 30, + WLAN_PE_DIAG_DELTS_REQ_EVENT, + WLAN_PE_DIAG_DELTS_RSP_EVENT, + WLAN_PE_DIAG_DELTS_IND_EVENT, + WLAN_PE_DIAG_ENTER_BMPS_REQ_EVENT, + WLAN_PE_DIAG_ENTER_BMPS_RSP_EVENT, + WLAN_PE_DIAG_EXIT_BMPS_REQ_EVENT, + WLAN_PE_DIAG_EXIT_BMPS_RSP_EVENT, + WLAN_PE_DIAG_EXIT_BMPS_IND_EVENT, + WLAN_PE_DIAG_ENTER_IMPS_REQ_EVENT, + WLAN_PE_DIAG_ENTER_IMPS_RSP_EVENT = 40, + WLAN_PE_DIAG_EXIT_IMPS_REQ_EVENT, + WLAN_PE_DIAG_EXIT_IMPS_RSP_EVENT, + WLAN_PE_DIAG_ENTER_UAPSD_REQ_EVENT, + WLAN_PE_DIAG_ENTER_UAPSD_RSP_EVENT, + WLAN_PE_DIAG_EXIT_UAPSD_REQ_EVENT, + WLAN_PE_DIAG_EXIT_UAPSD_RSP_EVENT, + WLAN_PE_DIAG_WOWL_ADD_BCAST_PTRN_EVENT, + WLAN_PE_DIAG_WOWL_DEL_BCAST_PTRN_EVENT, + WLAN_PE_DIAG_ENTER_WOWL_REQ_EVENT, + WLAN_PE_DIAG_ENTER_WOWL_RSP_EVENT = 50, + WLAN_PE_DIAG_EXIT_WOWL_REQ_EVENT, + WLAN_PE_DIAG_EXIT_WOWL_RSP_EVENT, + WLAN_PE_DIAG_HAL_ADDBA_REQ_EVENT, + WLAN_PE_DIAG_HAL_ADDBA_RSP_EVENT, + WLAN_PE_DIAG_HAL_DELBA_IND_EVENT, + WLAN_PE_DIAG_HB_FAILURE_TIMEOUT, + WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, + WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, + WLAN_PE_DIAG_PREAUTH_DONE, + WLAN_PE_DIAG_REASSOCIATING = 60, + WLAN_PE_DIAG_CONNECTED, + WLAN_PE_DIAG_ASSOC_REQ_EVENT, + WLAN_PE_DIAG_AUTH_COMP_EVENT, + WLAN_PE_DIAG_ASSOC_COMP_EVENT, + WLAN_PE_DIAG_AUTH_START_EVENT, + WLAN_PE_DIAG_ASSOC_START_EVENT, + WLAN_PE_DIAG_REASSOC_START_EVENT, + WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, + WLAN_PE_DIAG_ROAM_AUTH_COMP_EVENT, + WLAN_PE_DIAG_ROAM_ASSOC_START_EVENT = 70, + WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT, + RESERVED1, /* = 72 for SCAN_COMPLETE */ + RESERVED2, /* = 73 for SCAN_RES_FOUND */ +} WLAN_PE_DIAG_EVENT_TYPE; + +void limDiagEventReport(tpAniSirGlobal pMac, tANI_U16 eventType, tpPESession pSessionEntry, tANI_U16 status, tANI_U16 reasonCode); + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +void peSetResumeChannel(tpAniSirGlobal pMac, tANI_U16 channel, ePhyChanBondState cbState); +/*-------------------------------------------------------------------------- + + \brief peGetResumeChannel() - Returns the channel number for scanning, from a valid session. + + This function returns the channel to resume to during link resume. channel id of 0 means HAL will + resume to previous channel before link suspend + + \param pMac - pointer to global adapter context + \return - channel to scan from valid session else zero. + + \sa + + --------------------------------------------------------------------------*/ +void peGetResumeChannel(tpAniSirGlobal pMac, tANI_U8* resumeChannel, ePhyChanBondState* resumePhyCbState); + + +void limGetShortSlotFromPhyMode(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U32 phyMode, + tANI_U8 *pShortSlotEnable); + +void limCleanUpDisassocDeauthReq(tpAniSirGlobal pMac, tANI_U8 *staMac, tANI_BOOLEAN cleanRxPath); + +tANI_BOOLEAN limCheckDisassocDeauthAckPending(tpAniSirGlobal pMac, tANI_U8 *staMac); + +#ifdef WLAN_FEATURE_11W +void limPmfSaQueryTimerHandler(void *pMacGlobal, tANI_U32 param); +#endif + + + +void limUtilsframeshtons(tpAniSirGlobal pCtx, + tANI_U8 *pOut, + tANI_U16 pIn, + tANI_U8 fMsb); + +void limUtilsframeshtonl(tpAniSirGlobal pCtx, + tANI_U8 *pOut, + tANI_U32 pIn, + tANI_U8 fMsb); + +void limSetProtectedBit(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacAddr peer, + tpSirMacMgmtHdr pMacHdr); + +tANI_U8* lim_get_ie_ptr(tANI_U8 *pIes, int length, tANI_U8 eid); + +#ifdef WLAN_FEATURE_11W +void limPmfComebackTimerCallback(void *context); +#endif /* WLAN_FEATURE_11W */ + +void lim_set_ht_caps(tpAniSirGlobal p_mac, + tpPESession p_session_entry, + tANI_U8 *p_ie_start, + tANI_U32 num_bytes); +#ifdef WLAN_FEATURE_11AC +void lim_set_vht_caps(tpAniSirGlobal p_mac, + tpPESession p_session_entry, + tANI_U8 *p_ie_start, + tANI_U32 num_bytes); +#endif /* WLAN_FEATURE_11AC */ + +#ifdef SAP_AUTH_OFFLOAD +void lim_sap_offload_add_sta(tpAniSirGlobal pmac, + tpSirMsgQ lim_msgq); +void lim_sap_offload_del_sta(tpAniSirGlobal pmac, + tpSirMsgQ lim_msgq); +void +lim_pop_sap_deferred_msg(tpAniSirGlobal pmac, tpPESession sessionentry); + +void +lim_push_sap_deferred_msg(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq); + +void +lim_init_sap_deferred_msg_queue(tpAniSirGlobal pmac); + +void +lim_cleanup_sap_deferred_msg_queue(tpAniSirGlobal pmac); +#else +static inline void +lim_pop_sap_deferred_msg(tpAniSirGlobal pmac, tpPESession sessionentry) +{ + return; +} +static inline void +lim_push_sap_deferred_msg(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq) +{ + return; +} +static inline void +lim_init_sap_deferred_msg_queue(tpAniSirGlobal pmac) +{ + return; +} +static inline void +lim_cleanup_sap_deferred_msg_queue(tpAniSirGlobal pmac) +{ + return; +} +#endif /* SAP_AUTH_OFFLOAD */ +bool lim_validate_received_frame_a1_addr(tpAniSirGlobal mac_ctx, + tSirMacAddr a1, tpPESession session); + +void lim_set_stads_rtt_cap(tpDphHashNode sta_ds, struct s_ext_cap *ext_cap); +void lim_check_and_reset_protection_params(tpAniSirGlobal mac_ctx); +eHalStatus lim_send_ext_cap_ie(tpAniSirGlobal mac_ctx, + uint32_t session_id, + tDot11fIEExtCap *extracted_extcap, bool merge); + +tSirRetStatus lim_strip_extcap_ie(tpAniSirGlobal mac_ctx, uint8_t *addn_ie, + uint16_t *addn_ielen, uint8_t *extracted_extcap); +void lim_update_extcap_struct(tpAniSirGlobal mac_ctx, uint8_t *buf, + tDot11fIEExtCap *ext_cap); +tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx, + uint8_t* addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst); +void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src); +uint8_t +lim_get_80Mhz_center_channel(uint8_t primary_channel); +#endif /* __LIM_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmAP.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmAP.c new file mode 100644 index 000000000000..d3ee1b4d54ce --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmAP.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file pmmAP.cc contains AP PM functions + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "sirCommon.h" + +#include "aniGlobal.h" + +#include "schApi.h" +#include "limApi.h" +#include "cfgApi.h" +#include "wniCfgSta.h" + +#include "pmmApi.h" +#include "pmmDebug.h" + +/** + * pmmGenerateTIM + * + * FUNCTION: + * Generate TIM + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac pointer to global mac structure + * @param **pPtr pointer to the buffer, where the TIM bit is to be written. + * @param *timLength pointer to limLength, which needs to be returned. + * @return None + */ +void pmmGenerateTIM(tpAniSirGlobal pMac, tANI_U8 **pPtr, tANI_U16 *timLength, tANI_U8 dtimPeriod) +{ + tANI_U8 *ptr = *pPtr; + tANI_U32 val = 0; + tANI_U32 minAid = 1; // Always start with AID 1 as minimum + tANI_U32 maxAid = HAL_NUM_STA; + + + // Generate partial virtual bitmap + tANI_U8 N1 = minAid / 8; + tANI_U8 N2 = maxAid / 8; + if (N1 & 1) N1--; + + *timLength = N2 - N1 + 4; + val = dtimPeriod; + + /* + * 09/23/2011 - ASW team decision; + * Write 0xFF to firmware's field to detect firmware's mal-function early. + * DTIM count and bitmap control usually cannot be 0xFF, so it is easy to know that + * firmware never updated DTIM count/bitmap control field after host driver downloaded + * beacon template if end-user complaints that DTIM count and bitmapControl is 0xFF. + */ + *ptr++ = SIR_MAC_TIM_EID; + *ptr++ = (tANI_U8)(*timLength); + *ptr++ = 0xFF; // location for dtimCount. will be filled in by FW. + *ptr++ = (tANI_U8)val; + + *ptr++ = 0xFF; // location for bitmap control. will be filled in by FW. + ptr += (N2 - N1 + 1); + + PELOG2(sirDumpBuf(pMac, SIR_PMM_MODULE_ID, LOG2, *pPtr, (*timLength)+2);) + *pPtr = ptr; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmApi.c new file mode 100644 index 000000000000..2a3c24983a7f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmApi.c @@ -0,0 +1,3694 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file pmmApi.cc contains functions related to the API exposed + * by power management module + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "palTypes.h" +#include "wniCfgSta.h" + +#include "sirCommon.h" +#include "aniGlobal.h" + +#include "schApi.h" +#include "limApi.h" +#include "limSendMessages.h" +#include "cfgApi.h" +#include "limSessionUtils.h" +#include "limFT.h" + +#include "pmmApi.h" +#include "pmmDebug.h" +#include "sirApi.h" +#include "wmmApsd.h" + +#include "limSendSmeRspMessages.h" +#include "limTimerUtils.h" +#include "limTrace.h" +#include "limUtils.h" +#include "VossWrapper.h" +#include "vos_status.h" //VOS_STATUS +#include "vos_mq.h" //vos_mq_post_message() + +#include "wlan_qct_wda.h" + +#define LIM_ADMIT_MASK_FLAG_ACBE 1 +#define LIM_ADMIT_MASK_FLAG_ACBK 2 +#define LIM_ADMIT_MASK_FLAG_ACVI 4 +#define LIM_ADMIT_MASK_FLAG_ACVO 8 + +// -------------------------------------------------------------------- +/** + * pmmInitialize + * + * FUNCTION: + * Initialize PMM module + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param mode + * @param rate + * @return None + */ + +tSirRetStatus +pmmInitialize(tpAniSirGlobal pMac) +{ + + + pmmResetStats(pMac); + + pMac->pmm.gPmmBeaconInterval = WNI_CFG_BEACON_INTERVAL_STADEF; + pMac->pmm.gPmmState = ePMM_STATE_READY; + + + + pMac->pmm.inMissedBeaconScenario = FALSE; + + return eSIR_SUCCESS; +} + +// -------------------------------------------------------------------- +/** + * pmmResetStats + * + * FUNCTION: + * Resets the statistics + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac + * + * @return None + */ + +void +pmmResetStats(void *pvMac) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)pvMac; + + pMac->pmm.BmpsmaxSleepTime = 0; + pMac->pmm.BmpsavgSleepTime = 0; + pMac->pmm.BmpsminSleepTime = 0; + pMac->pmm.BmpscntSleep = 0; + + pMac->pmm.BmpsmaxTimeAwake = 0; + pMac->pmm.BmpsavgTimeAwake = 0; + pMac->pmm.BmpsminTimeAwake = 0; + pMac->pmm.BmpscntAwake = 0; + + pMac->pmm.BmpsWakeupTimeStamp = 0; + pMac->pmm.BmpsSleepTimeStamp = 0; + + pMac->pmm.BmpsHalReqFailCnt = 0; + pMac->pmm.BmpsInitFailCnt = 0; + pMac->pmm.BmpsInitFailCnt= 0; + pMac->pmm.BmpsInvStateCnt= 0; + pMac->pmm.BmpsPktDrpInSleepMode= 0; + pMac->pmm.BmpsReqInInvalidRoleCnt= 0; + pMac->pmm.BmpsSleeReqFailCnt= 0; + pMac->pmm.BmpsWakeupIndCnt= 0; + + pMac->pmm.ImpsWakeupTimeStamp = 0; + pMac->pmm.ImpsSleepTimeStamp = 0; + pMac->pmm.ImpsMaxTimeAwake = 0; + pMac->pmm.ImpsMinTimeAwake = 0; + pMac->pmm.ImpsAvgTimeAwake = 0; + pMac->pmm.ImpsCntAwake = 0; + + pMac->pmm.ImpsCntSleep = 0; + pMac->pmm.ImpsMaxSleepTime = 0; + pMac->pmm.ImpsMinSleepTime = 0; + pMac->pmm.ImpsAvgSleepTime = 0; + + pMac->pmm.ImpsSleepErrCnt = 0; + pMac->pmm.ImpsWakeupErrCnt = 0; + pMac->pmm.ImpsLastErr = 0; + pMac->pmm.ImpsInvalidStateCnt = 0; + + return; +} + + + +// -------------------------------------------------------------------- +/** + * pmmInitBmpsResponseHandler + * + * FUNCTION: + * This function processes the SIR_HAL_ENTER_BMPS_RSP from HAL. + * If the response is successful, it puts PMM in ePMM_STATE_BMP_SLEEP state + * and sends back success response to PMC. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * @return None + */ + +void pmmInitBmpsResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg ) +{ + + + tPmmState nextState = pMac->pmm.gPmmState; + tSirResultCodes retStatus = eSIR_SME_SUCCESS; + tpPESession psessionEntry; + tpEnterBmpsParams pEnterBmpsParams; + + /* we need to process all the deferred messages enqueued since + * the initiating the SIR_HAL_ENTER_BMPS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(pMac->pmm.gPmmState != ePMM_STATE_BMPS_WT_INIT_RSP) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmBmps: Received 'InitPwrSaveRsp' while in incorrect state: %d"), + pMac->pmm.gPmmState);) + + retStatus = eSIR_SME_INVALID_PMM_STATE; + pmmBmpsUpdateInvalidStateCnt(pMac); + goto failure; + } + + if (NULL == limMsg->bodyptr) + { + PELOGE(pmmLog(pMac, LOGE, FL("pmmBmps: Received SIR_HAL_ENTER_BMPS_RSP with NULL "));) + goto failure; + } + pEnterBmpsParams = (tpEnterBmpsParams)(limMsg->bodyptr); + + //if response is success, then set PMM to BMPS_SLEEP state and send response back to PMC. + //If response is failure, then send the response back to PMC and reset its state. + if(pEnterBmpsParams->status == eHAL_STATUS_SUCCESS) + { + PELOG2(pmmLog(pMac, LOG2, + FL("pmmBmps: Received successful response from HAL to enter BMPS_POWER_SAVE "));) + + pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; + + // Disable background scan mode + pMac->sys.gSysEnableScanMode = false; + + if (pMac->lim.gLimTimersCreated) + { + /* Disable heartbeat timer as well */ + if(pMac->lim.limTimers.gLimHeartBeatTimer.pMac) + { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_HEART_BEAT_TIMER)); + tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer); + } + } + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, retStatus, 0, 0); + } + else + { + //if init req failed, then go back to WAKEUP state. + PELOGE(pmmLog(pMac, LOGE, + FL("pmmBmps: BMPS_INIT_PWR_SAVE_REQ failed, informing SME"));) + + pmmBmpsUpdateInitFailureCnt(pMac); + nextState = ePMM_STATE_READY; + retStatus = eSIR_SME_BMPS_REQ_FAILED; + goto failure; + } + return; + +failure: + psessionEntry = peGetValidPowerSaveSession(pMac); + if(psessionEntry != NULL) + { + if (pMac->lim.gLimTimersCreated && pMac->lim.limTimers.gLimHeartBeatTimer.pMac) + { + if(VOS_TRUE != tx_timer_running(&pMac->lim.limTimers.gLimHeartBeatTimer)) + { + PELOGE(pmmLog(pMac, LOGE, FL("Unexpected heartbeat timer not running"));) + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + } + } + + //Generate an error response back to PMC + pMac->pmm.gPmmState = nextState; + pmmBmpsUpdateSleepReqFailureCnt(pMac); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, retStatus, 0, 0); + return; + +} + +// -------------------------------------------------------------------- +/** + * pmmExitBmpsRequestHandler + * + * FUNCTION: + * This function will send the wakeup message to HAL + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac pointer to Global Mac structure. + + * @return None + */ + +void pmmExitBmpsRequestHandler(tpAniSirGlobal pMac, tpExitBmpsInfo pExitBmpsInfo) +{ + tSirResultCodes respStatus = eSIR_SME_SUCCESS; + + tPmmState origState = pMac->pmm.gPmmState; + + if (NULL == pExitBmpsInfo) + { + respStatus = eSIR_SME_BMPS_REQ_REJECT; + PELOGW(pmmLog(pMac, LOGW, FL("pmmBmps: Rcvd EXIT_BMPS with NULL body"));) + goto failure; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_BMPS_REQ_EVENT, + peGetValidPowerSaveSession(pMac), 0, + (tANI_U16)pExitBmpsInfo->exitBmpsReason); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /* PMC is not aware of Background scan, which is done in + * BMPS mode while Nth Beacon is delivered. Essentially, PMC + * can request the device to get out of power-save while + * background scanning is happening. since, the device is already + * out of power save, just inform that device is out of power save + */ + if(limIsSystemInScanState(pMac)) + { + PELOGW(pmmLog(pMac, LOGW, + FL("pmmBmps: Device is already awake and scanning, returning success to PMC "));) + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, respStatus, 0, 0); + return; + } + + /* send wakeup request, only when in sleep state */ + PELOGW(pmmLog(pMac, LOGW, FL("pmmBmps: Sending eWNI_PMC_EXIT_BMPS_REQ to HAL"));) + if ((pMac->pmm.gPmmState == ePMM_STATE_BMPS_SLEEP) || + (pMac->pmm.gPmmState == ePMM_STATE_UAPSD_SLEEP)) + { + /* Store the reason code for exiting BMPS. This value will be + * checked when PMM receives SIR_HAL_EXIT_BMPS_RSP from HAL + */ + pMac->pmm.gPmmExitBmpsReasonCode = pExitBmpsInfo->exitBmpsReason; + vos_mem_free(pExitBmpsInfo); + + PELOGW(pmmLog(pMac, LOGW, + FL("pmmBmps: Rcvd EXIT_BMPS with reason code%d "), pMac->pmm.gPmmExitBmpsReasonCode);) + + + // Set PMM to BMPS_WT_WAKEUP_RSP state + pMac->pmm.gPmmState = ePMM_STATE_BMPS_WT_WAKEUP_RSP; + if(pmmSendChangePowerSaveMsg(pMac) != eSIR_SUCCESS) + { + /* Wakeup request failed */ + respStatus = eSIR_SME_BMPS_REQ_REJECT; + pmmBmpsUpdateHalReqFailureCnt(pMac); + goto failure; + } + else + { + PELOG1(pmmLog(pMac, LOG1, + FL("pmmBmps: eWNI_PMC_EXIT_BMPS_REQ was successfully sent to HAL"));) + } + } + else + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmBmps: eWNI_PMC_EXIT_BMPS_REQ received in invalid state: %d"), + pMac->pmm.gPmmState );) + + respStatus = eSIR_SME_INVALID_PMM_STATE; + pmmBmpsUpdateInvalidStateCnt(pMac); + vos_mem_free(pExitBmpsInfo); + goto failure; + } + return; + +failure: + pMac->pmm.gPmmState = origState; + pmmBmpsUpdateWakeupReqFailureCnt(pMac); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, respStatus, 0, 0); +} + + +// -------------------------------------------------------------------- +/** + * pmmInitBmpsPwrSave + * + * FUNCTION: + * This function process the eWNI_PMC_ENTER_PMC_REQ from PMC. + * It checks for certain conditions before it puts PMM into + * BMPS power save state: ePMM_STATE_BMPS_WT_INIT_RSP + * It also invokes pmmSendInitPowerSaveMsg() to send ENTER_BMPS_REQ + * to HAL. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param mode can be either 0(sleep mode) or 1 (active mode) + * @param pMac pointer to Global Mac structure. + + * @return None + */ + + +void pmmInitBmpsPwrSave(tpAniSirGlobal pMac) +{ + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirResultCodes respStatus = eSIR_SME_SUCCESS; + tpPESession psessionEntry; + + tPmmState origState = pMac->pmm.gPmmState; + + if((psessionEntry = peGetValidPowerSaveSession(pMac))== NULL) + { + respStatus = eSIR_SME_BMPS_REQ_REJECT; + goto failure; + } +#ifndef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + // sending beacon filtering information down to HAL + if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); + } +#else + if(!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); + } + } +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_BMPS_REQ_EVENT, psessionEntry, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if ( ((pMac->pmm.gPmmState != ePMM_STATE_READY) && + (pMac->pmm.gPmmState != ePMM_STATE_BMPS_WAKEUP)) || + limIsSystemInScanState(pMac) || + limIsChanSwitchRunning(pMac) || + limIsInQuietDuration(pMac) ) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmBmps: BMPS Request received in invalid state PMM=%d, SME=%d, rejecting the initpwrsave request"), + pMac->pmm.gPmmState, pMac->lim.gLimSmeState);) + + respStatus = eSIR_SME_INVALID_PMM_STATE; + pmmBmpsUpdateInvalidStateCnt(pMac); + goto failure; + } + + //If we are in a missed beacon scenario, we should not be attempting to enter BMPS as heartbeat probe is going on + if(pMac->pmm.inMissedBeaconScenario) + { + if (pMac->lim.gLimTimersCreated && pMac->lim.limTimers.gLimHeartBeatTimer.pMac) + { + if(VOS_TRUE != tx_timer_running(&pMac->lim.limTimers.gLimHeartBeatTimer)) + { + PELOGE(pmmLog(pMac, LOGE, FL("Unexpected heartbeat timer not running"));) + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + } + respStatus = eSIR_SME_BMPS_REQ_REJECT; + goto failure; + } + + /* At this point, device is associated and PMM is not in BMPS_SLEEP state. + * Heartbeat timer not running is an indication that PE have detected a + * loss of link. In this case, reject BMPS request. + */ + + //If the following function returns SUCCESS, then PMM will wait for an explicit + //response message from softmac. + + //changing PMM state before posting message to HAL, as this is a synchronous call to HAL + pMac->pmm.gPmmState = ePMM_STATE_BMPS_WT_INIT_RSP; + if((retStatus = pmmSendInitPowerSaveMsg(pMac,psessionEntry)) != eSIR_SUCCESS) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmBmps: Init Power Save Request Failed: Sending Response: %d"), + retStatus);) + + respStatus = eSIR_SME_BMPS_REQ_REJECT; + pmmBmpsUpdateHalReqFailureCnt(pMac); + goto failure; + } + //Update the powerSave sessionId + pMac->pmm.sessionId = psessionEntry->peSessionId; + return; + +failure: + + // Change the state back to original state + pMac->pmm.gPmmState =origState; + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, respStatus, 0, 0); + return; +} + + +/** + * pmmSendChangePowerSaveMsg() + * + *FUNCTION: + * This function is called to send SIR_HAL_EXIT_BMPS_REQ to HAL. + * This message will trigger HAL to program HW to wake up. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @return success if message send is ok, else false. + */ +tSirRetStatus pmmSendChangePowerSaveMsg(tpAniSirGlobal pMac) +{ + tSirRetStatus retStatus = eSIR_SUCCESS; + tpExitBmpsParams pExitBmpsParams; + tSirMsgQ msgQ; + tpPESession psessionEntry; + tANI_U8 currentOperatingChannel = limGetCurrentOperatingChannel(pMac); + + pExitBmpsParams = vos_mem_malloc(sizeof(*pExitBmpsParams)); + if ( NULL == pExitBmpsParams ) + { + pmmLog(pMac, LOGW, FL("Failed to allocate memory")); + retStatus = eSIR_MEM_ALLOC_FAILED; + return retStatus; + } + + if((psessionEntry = peGetValidPowerSaveSession(pMac)) == NULL ) + { + retStatus = eSIR_FAILURE; + vos_mem_free(pExitBmpsParams); + return retStatus; + } + + vos_mem_zero(pExitBmpsParams, sizeof(*pExitBmpsParams)); + msgQ.type = WDA_EXIT_BMPS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pExitBmpsParams; + msgQ.bodyval = 0; + + /* If reason for full power is disconnecting (ie. link is + * disconnected) or because of channel switch or full power requested + * because of beacon miss and connected on DFS channel + * then we should not send data null. + * For all other reason code, send data null. + */ + if ( !(SIR_IS_FULL_POWER_REASON_DISCONNECTED(pMac->pmm.gPmmExitBmpsReasonCode) || + ( (eSME_MISSED_BEACON_IND_RCVD == pMac->pmm.gPmmExitBmpsReasonCode) && + limIsconnectedOnDFSChannel(currentOperatingChannel)))) + pExitBmpsParams->sendDataNull = 1; + + pExitBmpsParams->bssIdx = psessionEntry->bssIdx; + + /* we need to defer any incoming messages until we + * get a WDA_EXIT_BMPS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + retStatus = wdaPostCtrlMsg( pMac, &msgQ); + if( eSIR_SUCCESS != retStatus ) + { + PELOGE(pmmLog( pMac, LOGE, FL("Sending WDA_EXIT_BMPS_REQ failed, reason=%X "), retStatus );) + vos_mem_free(pExitBmpsParams); + return retStatus; + } + + PELOG1(pmmLog(pMac, LOG1, FL("WDA_EXIT_BMPS_REQ has been successfully sent to HAL"));) + return retStatus; +} + + +/** + * pmmSendInitPowerSaveMsg() + * + *FUNCTION: + * This function is called to send ENTER_BMPS_REQ message to HAL. + * This message is sent to initialize the process of bringing the + * station into power save state. + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param mode The Power Save or Active State + * + * @return success if message send is ok, else false. + */ + +tSirRetStatus pmmSendInitPowerSaveMsg(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tpEnterBmpsParams pBmpsParams = NULL; + tANI_U32 rssiFilterPeriod = 5; + tANI_U32 numBeaconPerRssiAverage = 20; + tANI_U32 bRssiFilterEnable = FALSE; + + if(psessionEntry->currentBssBeaconCnt == 0 ) + { + PELOGE(pmmLog( pMac, LOGE, FL("Beacon count is zero, can not retrieve the TSF, failing the Enter Bmps Request"));) + return eSIR_FAILURE; + } + + pBmpsParams = vos_mem_malloc(sizeof(*pBmpsParams)); + if ( NULL == pBmpsParams ) + { + pmmLog(pMac, LOGP, "PMM: Not able to allocate memory for Enter Bmps"); + return eSIR_FAILURE; + } + + vos_mem_zero(pBmpsParams, sizeof(*pBmpsParams)); + + pMac->pmm.inMissedBeaconScenario = FALSE; + pBmpsParams->respReqd = TRUE; + + pBmpsParams->tbtt = psessionEntry->lastBeaconTimeStamp; + pBmpsParams->dtimCount = psessionEntry->lastBeaconDtimCount; + pBmpsParams->dtimPeriod = psessionEntry->lastBeaconDtimPeriod; + pBmpsParams->bssIdx = psessionEntry->bssIdx; + + /* TODO: Config parameters (Rssi filter period, FW RSSI Monitoring + and Number of beacons per RSSI average) values sent down to FW during + initial exchange (driver load) is same as ENTER_BMPS_REQ. + Sending these values again in ENTER_BMPS_REQ is not required + (can be removed). This is kept as-is for now to support + backward compatibility with the older host running on new FW. */ + + if(wlan_cfgGetInt(pMac, WNI_CFG_RSSI_FILTER_PERIOD, &rssiFilterPeriod) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Rssi filter period")); + pBmpsParams->rssiFilterPeriod = (tANI_U8)rssiFilterPeriod; + + if(wlan_cfgGetInt(pMac, WNI_CFG_PS_ENABLE_RSSI_MONITOR, &bRssiFilterEnable) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Rssi monitor enable flag")); + pBmpsParams->bRssiFilterEnable = bRssiFilterEnable; + + /* The numBeaconPerRssiAverage should be less than + the max allowed (default set to 20 in CFG) */ + if(wlan_cfgGetInt(pMac, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE, &numBeaconPerRssiAverage) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for num beacon per rssi")); + + pBmpsParams->numBeaconPerRssiAverage = + (tANI_U8)GET_MIN_VALUE((tANI_U8) numBeaconPerRssiAverage, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX); + + pmmLog (pMac, LOG1, + "%s: RssiFilterInfo..%d %x %x", __func__, (int)pBmpsParams->bRssiFilterEnable, + (unsigned int)pBmpsParams->rssiFilterPeriod, (unsigned int)pBmpsParams->numBeaconPerRssiAverage); + + msgQ.type = WDA_ENTER_BMPS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pBmpsParams; + msgQ.bodyval = 0; + + PELOG2(pmmLog( pMac, LOG2, + FL( "pmmBmps: Sending WDA_ENTER_BMPS_REQ" ));) + + /* we need to defer any incoming messages until we get a + * WDA_ENTER_BMPS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + vos_mem_free(pBmpsParams); + PELOGE(pmmLog( pMac, LOGE, + FL("Posting WDA_ENTER_BMPS_REQ to HAL failed, reason=%X"), + retCode );) + } + + return retCode; +} + +/** + * pmmSendPowerSaveCfg() + * + *FUNCTION: + * This function is called to send power save configuration. + * + *NOTE: + * + * @param pMac pointer to Global Mac structure. + * @param mode The Power Save or Active State + * + * @return success if message send is ok, else false. + */ +tSirRetStatus pmmSendPowerSaveCfg(tpAniSirGlobal pMac, tpSirPowerSaveCfg pUpdatedPwrSaveCfg) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tANI_U32 listenInterval; + tANI_U32 HeartBeatCount = 1; + tANI_U32 maxPsPoll; + tANI_U32 numBeaconPerRssiAverage; + tANI_U32 minRssiThreshold; + tANI_U32 nthBeaconFilter; + tANI_U32 broadcastFrameFilter; + tANI_U32 rssiFilterPeriod; + tANI_U32 ignoreDtim; + + if (NULL == pUpdatedPwrSaveCfg) + goto returnFailure; + + if(pMac->lim.gLimSmeState != eLIM_SME_IDLE_STATE ) + { + pmmLog(pMac, LOGE, + FL("pmmCfg: Power Save Configuration received in invalid global sme state %d"), + pMac->lim.gLimSmeState); + retCode = eSIR_SME_INVALID_STATE; + goto returnFailure; + } + + // Get power save configuration CFG values + if(wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for listen interval")); + pUpdatedPwrSaveCfg->listenInterval = (tANI_U16)listenInterval; + + if(wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &HeartBeatCount) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for heart beat thresh")); + + pMac->lim.gLimHeartBeatCount = HeartBeatCount; + pUpdatedPwrSaveCfg->HeartBeatCount = HeartBeatCount; + + if(wlan_cfgGetInt(pMac, WNI_CFG_NTH_BEACON_FILTER, &nthBeaconFilter) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Nth beacon filter")); + pUpdatedPwrSaveCfg->nthBeaconFilter = nthBeaconFilter; + + if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_PS_POLL, &maxPsPoll) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for max poll")); + pUpdatedPwrSaveCfg->maxPsPoll = maxPsPoll; + + if(wlan_cfgGetInt(pMac, WNI_CFG_MIN_RSSI_THRESHOLD, &minRssiThreshold) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for min RSSI Threshold")); + pUpdatedPwrSaveCfg->minRssiThreshold = minRssiThreshold; + + if(wlan_cfgGetInt(pMac, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE, &numBeaconPerRssiAverage) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for num beacon per rssi")); + pUpdatedPwrSaveCfg->numBeaconPerRssiAverage = (tANI_U8) numBeaconPerRssiAverage; + + if(wlan_cfgGetInt(pMac, WNI_CFG_RSSI_FILTER_PERIOD, &rssiFilterPeriod) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Rssi filter period")); + pUpdatedPwrSaveCfg->rssiFilterPeriod = (tANI_U8) rssiFilterPeriod; + + if(wlan_cfgGetInt(pMac, WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE, &broadcastFrameFilter) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Nth beacon filter")); + pUpdatedPwrSaveCfg->broadcastFrameFilter = (tANI_U8) broadcastFrameFilter; + + if(wlan_cfgGetInt(pMac, WNI_CFG_IGNORE_DTIM, &ignoreDtim) != eSIR_SUCCESS) + pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for ignoreDtim")); + pUpdatedPwrSaveCfg->ignoreDtim = (tANI_U8) ignoreDtim; + + //Save a copy of the CFG in global pmm context. + vos_mem_copy( (tANI_U8 *) &pMac->pmm.gPmmCfg, pUpdatedPwrSaveCfg, sizeof(tSirPowerSaveCfg)); + + + msgQ.type = WDA_PWR_SAVE_CFG; + msgQ.reserved = 0; + msgQ.bodyptr = pUpdatedPwrSaveCfg; + msgQ.bodyval = 0; + + PELOG1(pmmLog( pMac, LOG1, FL( "pmmBmps: Sending WDA_PWR_SAVE_CFG to HAL"));) + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + pmmLog( pMac, LOGP, + FL("Posting WDA_PWR_SAVE_CFG to HAL failed, reason=%X"), + retCode ); + goto returnFailure; + } + return retCode; + +returnFailure: + + /* In case of failure, we need to free the memory */ + if (NULL != pUpdatedPwrSaveCfg) + { + vos_mem_free(pUpdatedPwrSaveCfg); + } + return retCode; +} + +/** + * pmmExitBmpsResponseHandler + * + *FUNCTION: + * This function processes the Wakeup Rsp from HAL and if successful, + * sends a response back to PMC layer. + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param rspStatus Status of the response, Success or an error code. + * + * @return none. + */ +void pmmExitBmpsResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpExitBmpsParams pExitBmpsRsp; + eHalStatus rspStatus; + tANI_U8 PowersavesessionId; + tpPESession psessionEntry; + tSirResultCodes retStatus = eSIR_SME_SUCCESS; + + /* Copy the power save sessionId to the local variable */ + PowersavesessionId = pMac->pmm.sessionId; + + /* we need to process all the deferred messages enqueued since + * the initiating the SIR_HAL_EXIT_BMPS_REQ. + */ + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if((psessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId))==NULL) + { + pmmLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if (NULL == limMsg->bodyptr) + { + pmmLog(pMac, LOGE, FL("Received SIR_HAL_EXIT_BMPS_RSP with NULL ")); + return; + } + pExitBmpsRsp = (tpExitBmpsParams)(limMsg->bodyptr); + rspStatus = pExitBmpsRsp->status; + + if(pMac->pmm.gPmmState != ePMM_STATE_BMPS_WT_WAKEUP_RSP) + { + PELOGE(pmmLog(pMac, LOGE, + FL("Received SIR_HAL_EXIT_BMPS_RSP while in incorrect state: %d"), + pMac->pmm.gPmmState);) + + retStatus = eSIR_SME_INVALID_PMM_STATE; + pmmBmpsUpdateInvalidStateCnt(pMac); + } + else + { + PELOGW(pmmLog(pMac, LOGW, FL("Received SIR_HAL_EXIT_BMPS_RSP in correct state. "));) + } + + /* PE is going to wakeup irrespective of whether + * SIR_HAL_EXIT_BMPS_REQ was successful or not + */ + switch (rspStatus) + { + case eHAL_STATUS_SUCCESS: + pMac->pmm.gPmmState = ePMM_STATE_BMPS_WAKEUP; + retStatus = eSIR_SME_SUCCESS; + break; + + default: + { + /* PE is going to be awake irrespective of whether EXIT_BMPS_REQ + * failed or not. This is mainly to eliminate the dead-lock condition + * But, PMC will be informed about the error. + */ + retStatus = eSIR_SME_BMPS_REQ_FAILED; + pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; + } + break; + + } + + // turn on background scan + pMac->sys.gSysEnableScanMode = true; + + // send response to PMC + if(IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) ) + { + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, retStatus, + psessionEntry->smeSessionId, psessionEntry->transactionId); + } + else + { + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, retStatus, 0, 0); + } + + if ( pMac->pmm.gPmmExitBmpsReasonCode == eSME_MISSED_BEACON_IND_RCVD) + { + PELOGW(pmmLog(pMac, LOGW, FL("Rcvd SIR_HAL_EXIT_BMPS_RSP with MISSED_BEACON"));) + pmmMissedBeaconHandler(pMac); + } + else if(pMac->pmm.inMissedBeaconScenario) + { + PELOGW(pmmLog(pMac, LOGW, FL("Rcvd SIR_HAL_EXIT_BMPS_RSP in missed beacon scenario but reason code not correct"));) + pmmMissedBeaconHandler(pMac); + } + else + { + // Enable heartbeat timer + limReactivateHeartBeatTimer(pMac, psessionEntry); + } + return; +} + + +/** + * pmmMissedBeaconHandler() + * + *FUNCTION: + * This function is called when PMM receives an eWNI_PMC_EXIT_BMPS_REQ + * with reason code being eSME_MISSED_BEACON_IND_RCVD. + * + *NOTE: + * @param pMac pointer to Global Mac structure. + * @return none + */ +void pmmMissedBeaconHandler(tpAniSirGlobal pMac) +{ + tANI_U8 pwrSaveSessionId; + tANI_U32 beaconInterval = 0; + tANI_U32 heartBeatInterval = pMac->lim.gLimHeartBeatCount; + tpPESession psessionEntry; + + /* Copy the power save sessionId to the local variable */ + pwrSaveSessionId = pMac->pmm.sessionId; + + if((psessionEntry = peFindSessionBySessionId(pMac,pwrSaveSessionId))==NULL) + { + pmmLog(pMac, LOGE,FL("Session Does not exist for given sessionID")); + return; + } + + + PELOGE(pmmLog(pMac, LOG1, FL("The device woke up due to MISSED BEACON "));) + + /* Proceed only if HeartBeat timer is created */ + if((pMac->lim.limTimers.gLimHeartBeatTimer.pMac) && + (pMac->lim.gLimTimersCreated)) + { + if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &beaconInterval) != eSIR_SUCCESS) + PELOG1(pmmLog(pMac, LOG1, FL("Fail to get BEACON_INTERVAL value"));) + + /* Change timer to reactivate it in future */ + heartBeatInterval= SYS_MS_TO_TICKS(beaconInterval * heartBeatInterval); + + if( tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, + (tANI_U32)heartBeatInterval, 0) != TX_SUCCESS) + { + PELOG1(pmmLog(pMac, LOG1, FL("Fail to change HeartBeat timer"));) + } + + /* update some statistics */ + if(LIM_IS_CONNECTION_ACTIVE(psessionEntry)) + { + if(psessionEntry->LimRxedBeaconCntDuringHB < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL) + pMac->lim.gLimHeartBeatBeaconStats[psessionEntry->LimRxedBeaconCntDuringHB]++; + else + pMac->lim.gLimHeartBeatBeaconStats[0]++; + } + + /* To handle the missed beacon failure, message is being posted to self as if the + * actual timer has expired. This is done to make sure that there exists one + * common entry and exit points + */ + limResetHBPktCount(psessionEntry); // 090805: This is what it SHOULD be. If we even need it. + pmmSendMessageToLim(pMac, SIR_LIM_HEART_BEAT_TIMEOUT); + } + else + { + PELOGE(pmmLog(pMac, LOGE, FL("HeartBeat Timer is not created, cannot re-activate"));) + } + + return; +} + + +/** + * pmmExitBmpsIndicationHandler + * + *FUNCTION: + * This function sends a Power Save Indication. back to PMC layer. + * This indication is originated from softmac and will occur in the following two + * scenarios: + * 1) When softmac is in sleep state and wakes up to parse TIM and finds that + * AP has the data pending for this STA, then it sends this indication to let PMC know + * that it is going to be awake and pass the control over to PMC + * 2) When softmac is in sleep state and wakes up to parse TIM and determines that + * current TIM is DTIM and AP has buffered broadcast/multicast frames. + * In this scenario, softmac needs to remain awake for broadcast/multicast frames and it + * sends an indication to PMC that it is awake and passes the control over to PMC. + * 3) If station is awake and 'fEnablePwrSaveImmediately' flag is set, then softmac will transmit all + * frames in its queues and go to sleep. Before going to sleep it sends the notification to PMC that + * it is going to sleep. + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param rspStatus Status of the response, Success or an error code. + * + * @return none. + */ + +void pmmExitBmpsIndicationHandler(tpAniSirGlobal pMac, tANI_U8 mode, eHalStatus rspStatus) +{ + + tANI_U32 beaconInterval = 0; + tANI_U32 heartBeatInterval = pMac->lim.gLimHeartBeatCount; + tANI_U8 powersavesessionId; + tpPESession psessionEntry; + + /* Copy the power save sessionId to the local variable */ + powersavesessionId = pMac->pmm.sessionId; + + psessionEntry = peFindSessionBySessionId(pMac,powersavesessionId); + + if(psessionEntry == NULL) + { + PELOGE(pmmLog(pMac, LOGE, + FL("Session does Not exist with given sessionId :%d "),powersavesessionId);) + return; + } + + /* Since, the hardware is already woken up, PE also wakes up and informs + * the upper layers that the system is waking up. Hence always Success is + * sent in the reason code for the message sent to PMC + */ + + PELOGW(pmmLog(pMac, LOGW, + FL("pmmBmps: Received SIR_HAL_EXIT_BMPS_IND from HAL, Exiting BMPS sleep mode")); ) + + pMac->pmm.gPmmState = ePMM_STATE_BMPS_WAKEUP; + + /* turn on background scan */ + pMac->sys.gSysEnableScanMode = true; + + pmmBmpsUpdateWakeupIndCnt(pMac); + + /* Inform SME about the system awake state */ + limSendSmeRsp(pMac, + eWNI_PMC_EXIT_BMPS_IND, + eSIR_SME_SUCCESS, 0, 0); + + switch(rspStatus) + { + + /* The SoftMAC sends wakeup indication even when Heart-Beat timer expired + * The PE should start taking action against this as soon as it identifies + * that the SoftMAC has identified heart-beat miss + */ + case eHAL_STATUS_HEARTBEAT_TMOUT: + { + PELOG1(pmmLog(pMac, LOG1, + FL("pmmBmps: The device woke up due to HeartBeat Timeout"));) + + /* Proceed only if HeartBeat timer is created */ + if((pMac->lim.limTimers.gLimHeartBeatTimer.pMac) && + (pMac->lim.gLimTimersCreated)) + { + + /* Read the beacon interval from sessionTable */ + beaconInterval = psessionEntry->beaconParams.beaconInterval; + + /* Change timer to reactivate it in future */ + heartBeatInterval= SYS_MS_TO_TICKS(beaconInterval * heartBeatInterval); + + if(tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, + (tANI_U32)heartBeatInterval, 0) != TX_SUCCESS) + { + PELOG1(pmmLog(pMac, LOG1, + FL("pmmBmps: Unable to change HeartBeat timer"));) + } + + /* update some statistics */ + if(LIM_IS_CONNECTION_ACTIVE(psessionEntry)) + { + if(psessionEntry->LimRxedBeaconCntDuringHB < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL) + pMac->lim.gLimHeartBeatBeaconStats[psessionEntry->LimRxedBeaconCntDuringHB]++; + else + pMac->lim.gLimHeartBeatBeaconStats[0]++; + } + + /* To handle the heartbeat failure, message is being posted to self as if the + * actual timer has expired. This is done to make sure that there exists one + * common entry and exit points + */ + pmmSendMessageToLim(pMac, SIR_LIM_HEART_BEAT_TIMEOUT); + + } + else + { + + PELOGE(pmmLog(pMac, LOGE, + FL("pmmBmps: HeartBeat Timer is not created, cannot re-activate"));) + } + } + break; + + case eHAL_STATUS_NTH_BEACON_DELIVERY: + break; + + default: + break; + + } + + return; + +} + + +// -------------------------------------------------------------------- +/** + * pmmProcessMessage + * + * FUNCTION: Processes the next received Power Management message + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void pmmProcessMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + switch (pMsg->type) + { + case eWNI_PMC_PWR_SAVE_CFG: + { + tpSirPowerSaveCfg pPSCfg; + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + + pPSCfg = vos_mem_malloc(sizeof(*pPSCfg)); + if ( NULL == pPSCfg ) + { + pmmLog(pMac, LOGP, "PMM: Not able to allocate memory for PMC Config"); + } + vos_mem_copy(pPSCfg, pMbMsg->data, sizeof(*pPSCfg)); + pmmSendPowerSaveCfg(pMac, pPSCfg); + } + break; + + case eWNI_PMC_ENTER_BMPS_REQ: + pmmInitBmpsPwrSave(pMac); + break; + + case WDA_ENTER_BMPS_RSP: + pmmInitBmpsResponseHandler(pMac, pMsg); + break; + + case eWNI_PMC_EXIT_BMPS_REQ: + { + tpExitBmpsInfo pExitBmpsInfo; + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + + pExitBmpsInfo = vos_mem_malloc(sizeof(*pExitBmpsInfo)); + if ( NULL == pExitBmpsInfo ) + { + pmmLog(pMac, LOGP, "PMM: Failed to allocate memory for Exit BMPS Info "); + } + vos_mem_copy(pExitBmpsInfo, pMbMsg->data, sizeof(*pExitBmpsInfo)); + pmmExitBmpsRequestHandler(pMac, pExitBmpsInfo); + } + break; + + case WDA_EXIT_BMPS_RSP: + pmmExitBmpsResponseHandler(pMac, pMsg); + break; + + case WDA_EXIT_BMPS_IND: + pmmExitBmpsIndicationHandler(pMac, SIR_PM_ACTIVE_MODE, (eHalStatus)pMsg->bodyval); + break; + + case eWNI_PMC_ENTER_IMPS_REQ: + pmmEnterImpsRequestHandler(pMac); + break; + + case WDA_ENTER_IMPS_RSP: + pmmEnterImpsResponseHandler(pMac, (eHalStatus)pMsg->bodyval); + break; + + case eWNI_PMC_EXIT_IMPS_REQ: + pmmExitImpsRequestHandler(pMac); + break; + + case WDA_EXIT_IMPS_RSP: + pmmExitImpsResponseHandler(pMac, (eHalStatus)pMsg->bodyval); + break; + + case eWNI_PMC_ENTER_UAPSD_REQ: + pmmEnterUapsdRequestHandler(pMac); + break; + + case WDA_ENTER_UAPSD_RSP: + pmmEnterUapsdResponseHandler(pMac, pMsg); + break; + + case eWNI_PMC_EXIT_UAPSD_REQ: + pmmExitUapsdRequestHandler(pMac); + break; + + case WDA_EXIT_UAPSD_RSP: + pmmExitUapsdResponseHandler(pMac, pMsg); + break; + + case eWNI_PMC_WOWL_ADD_BCAST_PTRN: + pmmSendWowlAddBcastPtrn(pMac, pMsg); + break; + + case eWNI_PMC_WOWL_DEL_BCAST_PTRN: + pmmSendWowlDelBcastPtrn(pMac, pMsg); + break; + + case eWNI_PMC_ENTER_WOWL_REQ: + pmmEnterWowlRequestHandler(pMac, pMsg); + break; + + case WDA_WOWL_ENTER_RSP: + pmmEnterWowlanResponseHandler(pMac, pMsg); + break; + + case eWNI_PMC_EXIT_WOWL_REQ: + pmmExitWowlanRequestHandler(pMac, pMsg); + break; + + case WDA_WOWL_EXIT_RSP: + pmmExitWowlanResponseHandler(pMac, pMsg); + break; +#ifdef WLAN_FEATURE_PACKET_FILTERING + case WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP: + pmmFilterMatchCountResponseHandler(pMac, pMsg); + break; +#endif // WLAN_FEATURE_PACKET_FILTERING + + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + case WDA_GTK_OFFLOAD_GETINFO_RSP: + pmmGTKOffloadGetInfoResponseHandler(pMac, pMsg); + break; +#endif // WLAN_FEATURE_GTK_OFFLOAD + + default: + PELOGW(pmmLog(pMac, LOGW, + FL("PMM: Unknown message in pmmMsgQ type %d, potential memory leak!!"), + pMsg->type);) + } + + if (NULL != pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + pMsg->bodyptr = NULL; + } +} + + + + + + +// -------------------------------------------------------------------- +/** + * pmmPostMessage + * + * FUNCTION: + * Post a message to the pmm message queue + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMsg pointer to message + * @return None + */ + +tSirRetStatus +pmmPostMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + VOS_STATUS vosStatus; + vosStatus = vos_mq_post_message(VOS_MQ_ID_PE, (vos_msg_t *) pMsg); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + pmmLog(pMac, LOGP, FL("vos_mq_post_message failed with status code %d"), vosStatus); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +// -------------------------------------------------------------------- +/** + * pmmEnterImpsRequestHandler + * + * FUNCTION: + * This function sends the idle mode power save request from host device + * drive to HAL. This function is called from pmmProcessMsg() + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ +void pmmEnterImpsRequestHandler (tpAniSirGlobal pMac) +{ + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + tSirRetStatus retStatus = eSIR_SUCCESS; + tPmmState origState = pMac->pmm.gPmmState; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_IMPS_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + /*Returns True even single active session present */ + if(peIsAnySessionActive(pMac)) + { + /* Print active pesession and tracedump once in every 16 + * continuous error. + */ + if (!(pMac->pmc.ImpsReqFailCnt & 0xF)) + { + pePrintActiveSession(pMac); + } + resultCode = eSIR_SME_INVALID_STATE; + pmmLog(pMac, LOGE, FL("Session is active go to failure resultCode = " + "eSIR_SME_INVALID_STATE (%d)"),resultCode); + goto failure; + } + + if ( ((pMac->pmm.gPmmState != ePMM_STATE_READY) && + (pMac->pmm.gPmmState != ePMM_STATE_IMPS_WAKEUP)) || + ((pMac->lim.gLimSmeState != eLIM_SME_IDLE_STATE) && + (pMac->lim.gLimSmeState != eLIM_SME_JOIN_FAILURE_STATE)) || + (pMac->lim.gLimMlmState != eLIM_MLM_IDLE_STATE) || + limIsChanSwitchRunning (pMac) || + limIsInQuietDuration (pMac) ) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImps: PMM State = %d, Global MLM State = %d, Global SME State = %d, rejecting the sleep mode request"), + pMac->pmm.gPmmState, pMac->lim.gLimMlmState, pMac->lim.gLimSmeState);) + + resultCode = eSIR_SME_INVALID_PMM_STATE; + pmmImpsUpdateErrStateStats(pMac); + goto failure; + } + + // change PE state and send the request to HAL + pMac->pmm.gPmmState = ePMM_STATE_IMPS_WT_SLEEP_RSP; + if( (retStatus = pmmImpsSendChangePwrSaveMsg(pMac, SIR_PM_SLEEP_MODE)) != eSIR_SUCCESS) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImps: IMPS Sleep Request failed: sending response: %x"), retStatus);) + + resultCode = eSIR_SME_IMPS_REQ_FAILED; + goto failure; + } + else + { + PELOG1(pmmLog(pMac, LOG1, + FL("pmmImps: Waiting for SoftMac response for IMPS request"));) + } + return; + +failure: + pMac->pmm.gPmmState = origState; + pmmImpsUpdateSleepErrStats(pMac, retStatus); + + limSendSmeRsp(pMac, + eWNI_PMC_ENTER_IMPS_RSP, + resultCode, 0, 0); + +} + +// -------------------------------------------------------------------- +/** + * pmmEnterImpsResponseHandler + * + * FUNCTION: + * This function receives the response from HAL layer for the idle mode + * power save request sent. The function is also responsible for checking + * the correctness of the system state before configuring the new state + * on success. This function is called by pmmProcessMsg() + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC, Status code + * @return None + */ +void pmmEnterImpsResponseHandler (tpAniSirGlobal pMac, eHalStatus rspStatus) +{ + tPmmState nextState = pMac->pmm.gPmmState; + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + + /* we need to process all the deferred messages enqueued since + * the initiating the WDA_ENTER_IMPS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(pMac->pmm.gPmmState != ePMM_STATE_IMPS_WT_SLEEP_RSP) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImps: Receives IMPS sleep rsp in invalid state: %d"), + pMac->pmm.gPmmState);) + + resultCode = eSIR_SME_INVALID_PMM_STATE; + pmmImpsUpdateErrStateStats(pMac); + + goto failure; + } + + if(eHAL_STATUS_SUCCESS == rspStatus) + { + //if success, change the state to IMPS sleep mode + pMac->pmm.gPmmState = ePMM_STATE_IMPS_SLEEP; + + PELOG2(pmmLog(pMac, LOG2, + FL("pmmImps: Received successful WDA_ENTER_IMPS_RSP from HAL"));) + + //update power save statistics + pmmImpsUpdatePwrSaveStats(pMac); + + limSendSmeRsp(pMac, + eWNI_PMC_ENTER_IMPS_RSP, + resultCode, 0, 0); + } + else + { + // go back to previous state if request failed + nextState = ePMM_STATE_READY; + resultCode = eSIR_SME_CANNOT_ENTER_IMPS; + goto failure; + } + return; + +failure: + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImpsSleepRsp failed, Ret Code: %d, next state will be: %d"), + rspStatus, + pMac->pmm.gPmmState);) + + pMac->pmm.gPmmState = nextState; + + limSendSmeRsp(pMac, + eWNI_PMC_ENTER_IMPS_RSP, + resultCode, 0, 0); +} + + +// -------------------------------------------------------------------- +/** + * pmmExitImpsRequestHandler + * + * FUNCTION: + * This function is called by pmmProcessMsg(). The function sends a request + * to HAL to wakeup the device from idle mode power save mode. + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ +void pmmExitImpsRequestHandler (tpAniSirGlobal pMac) +{ + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + + tPmmState origState = pMac->pmm.gPmmState; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_IMPS_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if (ePMM_STATE_IMPS_SLEEP == pMac->pmm.gPmmState) + { + pMac->pmm.gPmmState = ePMM_STATE_IMPS_WT_WAKEUP_RSP; + if( (retStatus = pmmImpsSendChangePwrSaveMsg(pMac, SIR_PM_ACTIVE_MODE)) != + eSIR_SUCCESS) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImps: Wakeup request message sent to SoftMac failed"));) + resultCode = eSIR_SME_IMPS_REQ_FAILED; + goto failure; + } + } + else + { + // PE in invalid state + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImps: Wakeup Req received in invalid state: %x"), + pMac->pmm.gPmmState);) + + resultCode = eSIR_SME_INVALID_PMM_STATE; + pmmImpsUpdateErrStateStats(pMac); + + goto failure; + } + return; + +failure: + PELOGE(pmmLog (pMac, LOGE, + FL("pmmImps: Changing to IMPS wakeup mode failed, Ret Code: %d, Next State: %d"), + retStatus, pMac->pmm.gPmmState);) + + pMac->pmm.gPmmState = origState; + pmmImpsUpdateWakeupErrStats(pMac, retStatus); + + limSendSmeRsp(pMac, + eWNI_PMC_EXIT_IMPS_RSP, + resultCode, 0, 0); +} + + +// -------------------------------------------------------------------- +/** + * pmmExitImpsResponseHandler + * + * FUNCTION: + * This function receives the response from HAL layer for the idle mode + * power save request sent. The function is also responsible for checking + * the correctness of the system state before configuring the new state + * on success. This function is called by pmmProcessMsg() + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ +void pmmExitImpsResponseHandler(tpAniSirGlobal pMac, eHalStatus rspStatus) +{ + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + + /* we need to process all the deferred messages enqueued since + * the initiating the WDA_EXIT_IMPS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if (pMac->pmm.gPmmState != ePMM_STATE_IMPS_WT_WAKEUP_RSP) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmImps: Received 'Wakeup' response in invalid state: %d"), + pMac->pmm.gPmmState);) + + resultCode = eSIR_SME_INVALID_PMM_STATE; + pmmImpsUpdateErrStateStats(pMac); + } + + switch(rspStatus) + { + case eHAL_STATUS_SUCCESS: + { + resultCode = eSIR_SME_SUCCESS; + pMac->pmm.gPmmState = ePMM_STATE_IMPS_WAKEUP; + PELOG2(pmmLog(pMac, LOG2, + FL("pmmImps: Received WDA_EXIT_IMPS_RSP with Successful response from HAL"));) + } + break; + + default: + { + resultCode = eSIR_SME_IMPS_REQ_FAILED; + /* Set the status back to IMPS SLEEP as we failed + * to come out of sleep + */ + pMac->pmm.gPmmState = ePMM_STATE_IMPS_SLEEP; + PELOGW(pmmLog(pMac, LOGW, + FL("pmmImps: Received WDA_EXIT_IMPS_RSP with Failure Status from HAL"));) + } + break; + } + + //update power save statistics + pmmImpsUpdateWakeupStats(pMac); + + limSendSmeRsp(pMac, + eWNI_PMC_EXIT_IMPS_RSP, + resultCode, 0, 0); + return; + +} + +// -------------------------------------------------------------------- +/** + * pmmEnterUapsdRequestHandler + * + * FUNCTION: + * This function process the eWNI_PMC_ENTER_UAPSD_REQ from PMC, + * checks the correctness of the system state before configuring + * PMM to the new ePMM_STATE_UAPSD_WT_SLEEP_RSP state, and invokes + * invokes pmmUapsdSendChangePwrSaveMsg() to send + * WDA_ENTER_UAPSD_REQ to HAL. + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ +void pmmEnterUapsdRequestHandler (tpAniSirGlobal pMac) +{ + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + tSirRetStatus retStatus = eSIR_SUCCESS; + + tPmmState origState = pMac->pmm.gPmmState; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_UAPSD_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if ( (pMac->pmm.gPmmState != ePMM_STATE_BMPS_SLEEP) || + limIsSystemInScanState(pMac) ) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: PMM State = %d, Global MLM State = %d, Global SME State = %d, rejecting the sleep mode request"), + pMac->pmm.gPmmState, pMac->lim.gLimMlmState, pMac->lim.gLimSmeState);) + + resultCode = eSIR_SME_INVALID_PMM_STATE; + goto failure; + } + + pMac->pmm.gPmmState = ePMM_STATE_UAPSD_WT_SLEEP_RSP; + + if( (retStatus = pmmUapsdSendChangePwrSaveMsg(pMac, SIR_PM_SLEEP_MODE)) != eSIR_SUCCESS) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: HAL_ENTER_UAPSD_REQ failed with response: %x"), retStatus);) + resultCode = eSIR_SME_UAPSD_REQ_FAILED; + goto failure; + } + + PELOG1(pmmLog(pMac, LOG1, FL("pmmUapsd: Waiting for WDA_ENTER_UAPSD_RSP "));) + return; + +failure: + pMac->pmm.gPmmState = origState; + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, resultCode, 0, 0); + return; +} + + +// -------------------------------------------------------------------- +/** + * pmmEnterUapsdResponseHandler + * + * FUNCTION: + * This function processes the SIR_HAL_ENTER_UAPSD_RSP from HAL. + * If the response is successful, it puts PMM into ePMM_STATE_UAPSD_SLEEP + * state and sends back success response to PMC. + * + * NOTE: + * + * @param limMsg + * @return None + */ +void pmmEnterUapsdResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpUapsdParams pUapsdRspMsg; + tSirResultCodes retStatus = eSIR_SME_SUCCESS; + + tANI_U8 PowersavesessionId; + tpPESession psessionEntry; + + /* we need to process all the deferred messages enqueued since + * the initiating the SIR_HAL_ENTER_UAPSD_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + /* Copy the power save sessionId to the local variable */ + PowersavesessionId = pMac->pmm.sessionId; + + if (NULL == limMsg->bodyptr) + { + PELOGE(pmmLog(pMac, LOGE, FL("pmmUapsd: Received SIR_HAL_ENTER_UAPSD_RSP with NULL "));) + return; + } + + pUapsdRspMsg = (tpUapsdParams)(limMsg->bodyptr); + + if((psessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId))==NULL) + { + pmmLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if(pMac->pmm.gPmmState != ePMM_STATE_UAPSD_WT_SLEEP_RSP) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: Received SIR_HAL_ENTER_UAPSD_RSP while in incorrect state: %d"), + pMac->pmm.gPmmState);) + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_SME_INVALID_PMM_STATE, 0, 0); + return; + } + + if(pUapsdRspMsg->status == eHAL_STATUS_SUCCESS) + { + PELOGW(pmmLog(pMac, LOGW, + FL("pmmUapsd: Received successful response from HAL to enter UAPSD mode "));) + pMac->pmm.gPmmState = ePMM_STATE_UAPSD_SLEEP; + } + else + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: SIR_HAL_ENTER_UAPSD_RSP failed, informing SME"));) + pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; + retStatus = eSIR_SME_UAPSD_REQ_FAILED; + } + + if(IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION)) + { + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, retStatus, + psessionEntry->smeSessionId, psessionEntry->transactionId); + } + else + { + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, retStatus, 0, 0); + } + + return; +} + + +// -------------------------------------------------------------------- +/** + * pmmExitUapsdRequestHandler + * + * FUNCTION: + * This function process the eWNI_PMC_EXIT_UAPSD_REQ from PMC, + * checks the correctness of the system state before configuring + * PMM to the new ePMM_STATE_UAPSD_WT_WAKEUP_RSP state, and + * invokes pmmUapsdSendChangePwrSaveMsg() to send + * SIR_HAL_EXIT_UAPSD_REQ to HAL. + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ +void pmmExitUapsdRequestHandler(tpAniSirGlobal pMac) +{ + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + + tPmmState origState = pMac->pmm.gPmmState; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_UAPSD_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if (ePMM_STATE_UAPSD_SLEEP == pMac->pmm.gPmmState) + { + pMac->pmm.gPmmState = ePMM_STATE_UAPSD_WT_WAKEUP_RSP; + if( (retStatus = pmmUapsdSendChangePwrSaveMsg(pMac, SIR_PM_ACTIVE_MODE)) != + eSIR_SUCCESS) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: sending EXIT_UAPSD to HAL failed "));) + resultCode = eSIR_SME_UAPSD_REQ_FAILED; + goto failure; + } + } + else + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: Rcv EXIT_UAPSD from PMC in invalid state: %x"), + pMac->pmm.gPmmState);) + + resultCode = eSIR_SME_INVALID_PMM_STATE; + goto failure; + } + return; + +failure: + pMac->pmm.gPmmState = origState; + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: Waking up from UAPSD mode failed, Ret Code: %d, Next State: %d"), + retStatus, pMac->pmm.gPmmState);) + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, resultCode, 0, 0); +} + + +// -------------------------------------------------------------------- +/** + * pmmExitUapsdResponseHandler + * + * FUNCTION: + * This function receives the SIR_HAL_EXIT_UAPSD_RSP from HAL and is + * responsible for checking the correctness of the system state + * before configuring PMM to the new ePMM_STATE_BMPS_SLEEP state + * and send eWNI_PMC_EXIT_UAPSD_RSP to PMC. + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ +void pmmExitUapsdResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + tANI_U8 PowersavesessionId; + tpPESession psessionEntry; + tUapsdParams *pUapsdExitRspParams; + + /* we need to process all the deferred messages enqueued since + * the initiating the SIR_HAL_EXIT_UAPSD_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if (pMac->pmm.gPmmState != ePMM_STATE_UAPSD_WT_WAKEUP_RSP) + { + PELOGE(pmmLog(pMac, LOGE, + FL("Received HAL_EXIT_UAPSD_RSP in invalid state: %d"), + pMac->pmm.gPmmState);) + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SME_INVALID_PMM_STATE, 0, 0); + return; + } + pUapsdExitRspParams = (tUapsdParams *)(limMsg->bodyptr); + + PowersavesessionId = pMac->pmm.sessionId; + if((psessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId))==NULL) + { + pmmLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); + return; + } + + if(NULL == pUapsdExitRspParams ) + { + PELOGE(pmmLog(pMac, LOGE, + FL("Received HAL_EXIT_UAPSD_RSP message with zero parameters:"));) + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SME_UAPSD_REQ_FAILED, 0, 0); + return; + } + switch(pUapsdExitRspParams->status) + { + case eHAL_STATUS_SUCCESS: + resultCode = eSIR_SME_SUCCESS; + PELOGW(pmmLog(pMac, LOGW, + FL("Received SIR_HAL_EXIT_UAPSD_RSP with Successful response "));) + break; + default: + resultCode = eSIR_SME_UAPSD_REQ_FAILED; + PELOGE(pmmLog(pMac, LOGW, + FL("Received SIR_HAL_EXIT_UAPSD_RSP with Failure Status"));) + break; + } + + pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; + + if(IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION)) + { + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, resultCode, psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + else + { + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, resultCode, 0, 0); + } + return; +} + +/** ------------------------------------------------------------ +\fn pmmSendWowlAddBcastPtrn +\brief This function sends a SIR_HAL_WOWL_ADD_BCAST_PTRN +\ message to HAL. +\param tpAniSirGlobal pMac +\param tpSirMsgQ pMsg +\return None + --------------------------------------------------------------*/ +void pmmSendWowlAddBcastPtrn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirWowlAddBcastPtrn pBcastPtrn; + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pBcastPtrn = vos_mem_malloc(sizeof(*pBcastPtrn)); + if ( NULL == pBcastPtrn ) + { + pmmLog(pMac, LOGP, FL("Fail to allocate memory for WoWLAN Add Bcast Pattern ")); + return; + } + vos_mem_copy(pBcastPtrn, pMbMsg->data, sizeof(*pBcastPtrn)); + + if (NULL == pBcastPtrn) + { + pmmLog(pMac, LOGE, FL("Add broadcast pattern message is NULL ")); + return; + } + + msgQ.type = WDA_WOWL_ADD_BCAST_PTRN; + msgQ.reserved = 0; + msgQ.bodyptr = pBcastPtrn; + msgQ.bodyval = 0; + + pmmLog(pMac, LOG1, FL( "Sending WDA_WOWL_ADD_BCAST_PTRN to HAL")); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_WOWL_ADD_BCAST_PTRN_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + if (pBcastPtrn != NULL) + vos_mem_free(pBcastPtrn); + pmmLog( pMac, LOGP, FL("Posting WDA_WOWL_ADD_BCAST_PTRN failed, reason=%X"), retCode ); + } + return; +} + +/** ------------------------------------------------------------ +\fn pmmSendWowlDelBcastPtrn +\brief This function sends a SIR_HAL_WOWL_DEL_BCAST_PTRN +\ message to HAL. +\param tpAniSirGlobal pMac +\param tpSirMsgQ pMsg +\return None + --------------------------------------------------------------*/ +void pmmSendWowlDelBcastPtrn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirWowlDelBcastPtrn pDeletePtrn; + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pDeletePtrn = vos_mem_malloc(sizeof(*pDeletePtrn)); + if ( NULL == pDeletePtrn ) + { + pmmLog(pMac, LOGP, FL("Fail to allocate memory for WoWLAN Delete Bcast Pattern ")); + return; + } + vos_mem_copy(pDeletePtrn, pMbMsg->data, sizeof(*pDeletePtrn)); + + if (NULL == pDeletePtrn) + { + pmmLog(pMac, LOGE, FL("Delete broadcast pattern message is NULL ")); + return; + } + + msgQ.type = WDA_WOWL_DEL_BCAST_PTRN; + msgQ.reserved = 0; + msgQ.bodyptr = pDeletePtrn; + msgQ.bodyval = 0; + + pmmLog(pMac, LOG1, FL( "Sending WDA_WOWL_DEL_BCAST_PTRN")); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_WOWL_DEL_BCAST_PTRN_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + if (NULL != pDeletePtrn) + vos_mem_free(pDeletePtrn); + pmmLog( pMac, LOGP, FL("Posting WDA_WOWL_DEL_BCAST_PTRN failed, reason=%X"), retCode ); + } + return; +} + +/** --------------------------------------------------------- +\fn pmmEnterWowlRequestHandler +\brief LIM process the eWNI_PMC_ENTER_WOWL_REQ message, and +\ invokes pmmSendWowlEnterRequest() to send +\ WDA_WOWL_ENTER_REQ message to HAL. +\param tpAniSirGlobal pMac +\param tpSirMsgQ pMsg +\return None + ------------------------------------------------------------*/ +void pmmEnterWowlRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirSmeWowlEnterParams pSmeWowlParams = NULL; + tpSirHalWowlEnterParams pHalWowlParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tANI_U32 cfgValue = 0; + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + tpPESession pSessionEntry = NULL; + tANI_U8 peSessionId = 0; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_WOWL_REQ_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + pSmeWowlParams = (tpSirSmeWowlEnterParams)(pMbMsg->data); + if (NULL == pSmeWowlParams) + { + pmmLog(pMac, LOGE, + FL("NULL message received")); + return; + } + + if (pMac->psOffloadEnabled) + goto skip_pmm_state_check; + + pSessionEntry = peFindSessionByBssid(pMac, pSmeWowlParams->bssId, + &peSessionId); + if (NULL == pSessionEntry) + { + pmmLog(pMac, LOGE, + FL("session does not exist for given BSSId")); + goto end; + } + pMac->pmm.sessionId = peSessionId; + + 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; + } + +skip_pmm_state_check: + + pHalWowlParams = vos_mem_malloc(sizeof(*pHalWowlParams)); + if ( NULL == pHalWowlParams ) + { + pmmLog(pMac, LOGP, FL("Fail to allocate memory for Enter Wowl Request ")); + goto end; + } + vos_mem_zero(pHalWowlParams, sizeof(*pHalWowlParams)); + + // fill in the message field + pHalWowlParams->ucMagicPktEnable = pSmeWowlParams->ucMagicPktEnable; + pHalWowlParams->ucPatternFilteringEnable = pSmeWowlParams->ucPatternFilteringEnable; + vos_mem_copy(pHalWowlParams->magicPtrn, + pSmeWowlParams->magicPtrn, sizeof(tSirMacAddr)); + +#ifdef WLAN_WAKEUP_EVENTS + pHalWowlParams->ucWoWEAPIDRequestEnable = pSmeWowlParams->ucWoWEAPIDRequestEnable; + pHalWowlParams->ucWoWEAPOL4WayEnable = pSmeWowlParams->ucWoWEAPOL4WayEnable; + pHalWowlParams->ucWowNetScanOffloadMatch = pSmeWowlParams->ucWowNetScanOffloadMatch; + pHalWowlParams->ucWowGTKRekeyError = pSmeWowlParams->ucWowGTKRekeyError; + pHalWowlParams->ucWoWBSSConnLoss = pSmeWowlParams->ucWoWBSSConnLoss; +#endif // WLAN_WAKEUP_EVENTS + + if (!pMac->psOffloadEnabled) + pHalWowlParams->bssIdx = pSessionEntry->bssIdx; + + if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE, &cfgValue) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE")); + goto end; + } + pHalWowlParams->ucUcastPatternFilteringEnable = (tANI_U8)cfgValue; + + if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE, &cfgValue) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE")); + goto end; + } + pHalWowlParams->ucWowChnlSwitchRcv = (tANI_U8)cfgValue; + + if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_DEAUTH_ENABLE, &cfgValue) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_DEAUTH_ENABLE ")); + goto end; + } + pHalWowlParams->ucWowDeauthRcv = (tANI_U8)cfgValue; + + if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_DISASSOC_ENABLE, &cfgValue) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_DEAUTH_ENABLE ")); + goto end; + } + pHalWowlParams->ucWowDisassocRcv = (tANI_U8)cfgValue; + + if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_MAX_MISSED_BEACON, &cfgValue) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_MAX_MISSED_BEACON ")); + goto end; + } + pHalWowlParams->ucWowMaxMissedBeacons = (tANI_U8)cfgValue; + + if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD, &cfgValue) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD ")); + goto end; + } + pHalWowlParams->ucWowMaxSleepUsec = (tANI_U8)cfgValue; + + pHalWowlParams->sessionId = pSmeWowlParams->sessionId; + //Send message to HAL + if( eSIR_SUCCESS != (retCode = pmmSendWowlEnterRequest( pMac, pHalWowlParams))) + { + pmmLog(pMac, LOGE, FL("Send ENTER_WOWL_REQ to HAL failed, reasonCode %d "), retCode); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, eSIR_SME_WOWL_ENTER_REQ_FAILED, 0, 0); + goto end; + } + return; + +end: + if (pHalWowlParams != NULL) + vos_mem_free(pHalWowlParams); + return; +} + + +/** ------------------------------------------------------------ +\fn pmmSendWowlEnterRequest +\brief LIM sends a WDA_WOWL_ENTER_REQ message to HAL with +\ the message structure pHalWowlParams. HAL shall later +\ send a WDA_WOWL_ENTER_RSP with the same pointer +\ to the message structure back to PMM. +\param tpAniSirGlobal pMac +\param tpSirHalWowlEnterParams pHalWowlParams +\return tSirRetStatus + --------------------------------------------------------------*/ +tSirRetStatus pmmSendWowlEnterRequest(tpAniSirGlobal pMac, tpSirHalWowlEnterParams pHalWowlParams) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if (NULL == pHalWowlParams) + return eSIR_FAILURE; + + msgQ.type = WDA_WOWL_ENTER_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pHalWowlParams; + msgQ.bodyval = 0; + + if (!pMac->psOffloadEnabled) + { + /* Defer any incoming message until we get + * a WDA_WOWL_ENTER_RSP from HAL + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + } + + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if( eSIR_SUCCESS != retCode ) + { + pmmLog( pMac, LOGE, FL("Posting WDA_WOWL_ENTER_REQ failed, reason=%X"), retCode ); + return retCode; + } + return retCode; +} + +/** --------------------------------------------------------- +\fn pmmEnterWowlanResponseHandler +\brief LIM process the WDA_WOWL_ENTER_RSP message. +\ and sends eWNI_PMC_ENTER_WOWL_RSP to SME. +\param tpAniSirGlobal pMac +\param tpSirMsgQ limMsg +\return None + ------------------------------------------------------------*/ +void pmmEnterWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpSirHalWowlEnterParams pWowlEnterParams; + eHalStatus rspStatus; + tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; + + /* we need to process all the deferred messages enqueued + * since the initiating the WDA_WOWL_ENTER_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + pWowlEnterParams = (tpSirHalWowlEnterParams)(limMsg->bodyptr); + if (NULL == pWowlEnterParams) + { + pmmLog(pMac, LOGE, FL("Recvd WDA_WOWL_ENTER_RSP with NULL msg ")); + smeRspCode = eSIR_SME_WOWL_ENTER_REQ_FAILED; + } + else + { + rspStatus = pWowlEnterParams->status; + + if(rspStatus == eHAL_STATUS_SUCCESS) + { + pmmLog(pMac, LOGW, FL("Rcv successful response from HAL to enter WOWLAN ")); + pMac->pmm.gPmmState = ePMM_STATE_WOWLAN; + } + else + { + pmmLog(pMac, LOGE, FL("HAL enter WOWLAN failed, informing SME")); + smeRspCode = eSIR_SME_WOWL_ENTER_REQ_FAILED; + } + } + + limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, smeRspCode, 0, 0); + return; +} + +/** --------------------------------------------------------- +\fn pmmExitWowlanRequestHandler +\brief PE process the eWNI_PMC_EXIT_WOWL_REQ message. +\ and sends WDA_WOWL_EXIT_REQ to HAL. +\param tpAniSirGlobal pMac +\return None + ------------------------------------------------------------*/ +void pmmExitWowlanRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirSmeWowlExitParams pSmeWowlParams = NULL; + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; + tpPESession pSessionEntry = NULL; + tpSirHalWowlExitParams pHalWowlMsg = NULL; + tANI_U8 PowersavesessionId = 0; + + pSmeWowlParams = (tpSirSmeWowlExitParams)(pMbMsg->data); + if (NULL == pSmeWowlParams) + { + limLog(pMac, LOGE, + FL("NULL message received")); + return; + } + + if (pMac->psOffloadEnabled) + goto skip_pe_session_lookup; + + PowersavesessionId = pMac->pmm.sessionId; + + if((pSessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId)) == NULL ) + { + PELOGW(pmmLog(pMac, LOGE, FL("pmmWowl : failed to allocate memory"));) + smeRspCode = eSIR_SME_WOWL_EXIT_REQ_FAILED; + goto failure; + } + +skip_pe_session_lookup: + + pHalWowlMsg = vos_mem_malloc(sizeof(*pHalWowlMsg)); + if ( NULL == pHalWowlMsg ) + { + pmmLog(pMac, LOGP, FL("Fail to allocate memory for WoWLAN Add Bcast Pattern ")); + smeRspCode = eSIR_SME_WOWL_EXIT_REQ_FAILED; + goto failure; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_WOWL_REQ_EVENT, NULL, 0, 0); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + if ( !pMac->psOffloadEnabled && pMac->pmm.gPmmState != ePMM_STATE_WOWLAN ) + { + pmmLog(pMac, LOGE, + FL("Exit WOWLAN Request received in invalid state PMM=%d "), + pMac->pmm.gPmmState); + smeRspCode = eSIR_SME_INVALID_PMM_STATE; + goto failure; + } + + vos_mem_zero(pHalWowlMsg, sizeof(*pHalWowlMsg)); + + if (!pMac->psOffloadEnabled) + pHalWowlMsg->bssIdx = pSessionEntry->bssIdx; + + pHalWowlMsg->sessionId = pSmeWowlParams->sessionId; + if((retStatus = pmmSendExitWowlReq(pMac, pHalWowlMsg)) != eSIR_SUCCESS) + { + pmmLog(pMac, LOGE, + FL("Fail to send WDA_WOWL_EXIT_REQ, reason code %d"), + retStatus); + smeRspCode = eSIR_SME_WOWL_EXIT_REQ_FAILED; + goto failure; + } + return; + +failure: + if (pHalWowlMsg != NULL) + vos_mem_free(pHalWowlMsg); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, smeRspCode, 0, 0); + return; +} + +/** --------------------------------------------------------- +\fn pmmSendExitWowlReq +\brief This function sends the WDA_WOWL_EXIT_REQ +\ message to HAL. +\param tpAniSirGlobal pMac +\return None + ------------------------------------------------------------*/ +tSirRetStatus pmmSendExitWowlReq(tpAniSirGlobal pMac, tpSirHalWowlExitParams pHalWowlParams) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if (NULL == pHalWowlParams) + return eSIR_FAILURE; + + msgQ.type = WDA_WOWL_EXIT_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pHalWowlParams; + msgQ.bodyval = 0; + + pmmLog(pMac, LOGW, FL("Sending WDA_WOWL_EXIT_REQ")); + + if (!pMac->psOffloadEnabled) + { + /* we need to defer any incoming messages until + * we get a WDA_WOWL_EXIT_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + } + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + pmmLog( pMac, LOGE, + FL("Posting WDA_WOWL_EXIT_REQ failed, reason=%X"), + retCode ); + + return retCode; +} + +/** --------------------------------------------------------- +\fn pmmExitWowlanResponseHandler +\brief This function process the WDA_WOWL_EXIT_RSP message. +\ and sends back eWNI_PMC_EXIT_WOWL_RSP to SME. +\param tpAniSirGlobal pMac +\return None + ------------------------------------------------------------*/ +void pmmExitWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + + tpSirHalWowlExitParams pHalWowlRspMsg; + eHalStatus rspStatus = eHAL_STATUS_FAILURE; + + /* we need to process all the deferred messages enqueued + * since the initiating the WDA_WOWL_EXIT_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + pHalWowlRspMsg = (tpSirHalWowlExitParams)(limMsg->bodyptr); + if (NULL == pHalWowlRspMsg) + { + pmmLog(pMac, LOGE, FL("Recvd WDA_WOWL_ENTER_RSP with NULL msg ")); + } + else + { + // restore PMM state to BMPS mode + pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; + rspStatus = pHalWowlRspMsg->status; + } + + 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); + } + 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); + } + return; +} + + +// -------------------------------------------------------------------- +/** + * pmmImpsSendChangePwrSaveMsg + * + * FUNCTION: + * This function is called to toggle the Idle mode power save mode + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC + * @param mode to be configured + * @return None + */ + +tSirRetStatus pmmImpsSendChangePwrSaveMsg(tpAniSirGlobal pMac, tANI_U8 mode) +{ + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if (SIR_PM_SLEEP_MODE == mode) + { + msgQ.type = WDA_ENTER_IMPS_REQ; + PELOG2(pmmLog (pMac, LOG2, FL("Sending WDA_ENTER_IMPS_REQ to HAL"));) + } + else + { + msgQ.type = WDA_EXIT_IMPS_REQ; + PELOG2(pmmLog (pMac, LOG2, FL("Sending WDA_EXIT_IMPS_REQ to HAL"));) + } + + msgQ.reserved = 0; + msgQ.bodyptr = NULL; + msgQ.bodyval = 0; + + /* we need to defer any incoming messages until we get a + * WDA_ENTER_IMPS_REQ or WDA_EXIT_IMPS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + retStatus = wdaPostCtrlMsg(pMac, &msgQ); + if ( eSIR_SUCCESS != retStatus ) + { + PELOGE(pmmLog(pMac, LOGE, + FL("WDA_ENTER/EXIT_IMPS_REQ to HAL failed, reason=%X"), retStatus);) + } + + return retStatus; +} + +// -------------------------------------------------------------------- +/** + * pmmUapsdSendChangePwrSaveMsg + * + * FUNCTION: + * This function is called to send either WDA_ENTER_UAPSD_REQ + * or WDA_EXIT_UAPSD_REQ to HAL. + * + * NOTE: + * + * @param pMac Global handle to MAC + * @param mode mode to be configured + * @return tSirRetStatus + */ +tSirRetStatus pmmUapsdSendChangePwrSaveMsg (tpAniSirGlobal pMac, tANI_U8 mode) +{ + tSirRetStatus retStatus = eSIR_SUCCESS; + tpUapsdParams pUapsdParams = NULL; + tSirMsgQ msgQ; + tpPESession pSessionEntry; + tpExitUapsdParams pExitUapsdParams = NULL; + + if((pSessionEntry = peGetValidPowerSaveSession(pMac)) == NULL ) + { + PELOGW(pmmLog(pMac, LOGW, FL("pmmUapsd : failed to allocate memory"));) + retStatus = eSIR_FAILURE; + return retStatus; + } + + if (SIR_PM_SLEEP_MODE == mode) + { + pUapsdParams = vos_mem_malloc(sizeof(*pUapsdParams)); + if ( NULL == pUapsdParams ) + { + PELOGW(pmmLog(pMac, LOGW, FL("pmmUapsd : failed to allocate memory"));) + retStatus = eSIR_MEM_ALLOC_FAILED; + return retStatus; + } + + vos_mem_zero(pUapsdParams, sizeof(*pUapsdParams)); + msgQ.type = WDA_ENTER_UAPSD_REQ; + msgQ.bodyptr = pUapsdParams; + + /* + * An AC is delivery enabled AC if the bit for that AC is set into the + * gAcAdmitMask[SIR_MAC_DIRECTION_DLINK],it is not set then we will take Static values. + */ + + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBE) + { + pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); + } + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBK) + { + pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); + } + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVI) + { + pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); + } + + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVO) + { + pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); + } + + /* + * An AC is trigger enabled AC if the bit for that AC is set into the + * gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK],it is not set then we will take Static values. + */ + + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBE) + { + pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); + } + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBK) + { + pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); + } + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVI) + { + pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); + } + + if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVO) + { + pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); + } + + pUapsdParams->bssIdx = pSessionEntry->bssIdx; + + PELOGW(pmmLog(pMac, LOGW, + FL("UAPSD Mask: static = 0x%x, DeliveryEnabled = 0x%x, TriggerEnabled = 0x%x "), + pMac->lim.gUapsdPerAcBitmask, + pMac->lim.gUapsdPerAcDeliveryEnableMask, + pMac->lim.gUapsdPerAcTriggerEnableMask);) + + PELOGW(pmmLog(pMac, LOGW, FL("Delivery Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "), + pUapsdParams->bkDeliveryEnabled, + pUapsdParams->beDeliveryEnabled, + pUapsdParams->viDeliveryEnabled, + pUapsdParams->voDeliveryEnabled);) + + PELOGW(pmmLog(pMac, LOGW, FL("Trigger Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "), + pUapsdParams->bkTriggerEnabled, + pUapsdParams->beTriggerEnabled, + pUapsdParams->viTriggerEnabled, + pUapsdParams->voTriggerEnabled);) + + PELOGW(pmmLog (pMac, LOGW, FL("pmmUapsd: Sending WDA_ENTER_UAPSD_REQ to HAL"));) + } + else + { + pExitUapsdParams = vos_mem_malloc(sizeof(*pExitUapsdParams)); + if ( NULL == pExitUapsdParams ) + { + PELOGW(pmmLog(pMac, LOGW, FL("pmmUapsd : failed to allocate memory"));) + retStatus = eSIR_MEM_ALLOC_FAILED; + return retStatus; + } + + vos_mem_zero(pExitUapsdParams, sizeof(*pExitUapsdParams)); + msgQ.type = WDA_EXIT_UAPSD_REQ; + msgQ.bodyptr = pExitUapsdParams; + pExitUapsdParams->bssIdx = pSessionEntry->bssIdx; + PELOGW(pmmLog (pMac, LOGW, FL("pmmUapsd: Sending WDA_EXIT_UAPSD_REQ to HAL"));) + } + + /* we need to defer any incoming messages until we get a + * WDA_ENTER/EXIT_UAPSD_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.reserved = 0; + msgQ.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); + retStatus = wdaPostCtrlMsg(pMac, &msgQ); + if ( eSIR_SUCCESS != retStatus ) + { + PELOGE(pmmLog(pMac, LOGE, + FL("pmmUapsd: WDA_ENTER/EXIT_UAPSD_REQ to HAL failed, reason=%X"), + retStatus);) + if (SIR_PM_SLEEP_MODE == mode) + vos_mem_free(pUapsdParams); + else + vos_mem_free(pExitUapsdParams); + } + + return retStatus; +} + + +// -------------------------------------------------------------------- +/** + * pmmUpdateImpsPwrSaveStats + * + * FUNCTION: + * This function is called to update the power save statistics in MAC + * for Idle mode power save + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ + +void pmmImpsUpdatePwrSaveStats(tpAniSirGlobal pMac) +{ +} + + +// -------------------------------------------------------------------- +/** + * pmmImpsUpdateWakeupStats + * + * FUNCTION: + * This function is called to update the Wake up statistics in MAC + * for Idle mode power save + * + * LOGIC: + * + * ASSUMPTIONS: + * None + * + * NOTE: + * + * @param Global handle to MAC + * @return None + */ + +void pmmImpsUpdateWakeupStats (tpAniSirGlobal pMac) +{ +} + +// Collects number of times error occurred while going to sleep mode +void pmmImpsUpdateSleepErrStats(tpAniSirGlobal pMac, + tSirRetStatus retStatus) +{ + pMac->pmm.ImpsSleepErrCnt++; + pMac->pmm.ImpsLastErr = retStatus; + return; +} + +// Collects number of times error occurred while waking up from sleep mode +void pmmImpsUpdateWakeupErrStats(tpAniSirGlobal pMac, + tSirRetStatus retStatus) +{ + pMac->pmm.ImpsWakeupErrCnt++; + pMac->pmm.ImpsLastErr = retStatus; + return; +} + + +// Collects number of times the system has received request or +// response in an invalid state +void pmmImpsUpdateErrStateStats(tpAniSirGlobal pMac) +{ + pMac->pmm.ImpsInvalidStateCnt++; + return; +} + +// Collects number of packets dropped while in IMPS mode +void pmmImpsUpdatePktDropStats(tpAniSirGlobal pMac) +{ + + pMac->pmm.ImpsPktDrpInSleepMode++; + return; +} + +// Collects number of packets dropped while in BMPS mode +void pmmBmpsUpdatePktDropStats(tpAniSirGlobal pMac) +{ + + pMac->pmm.BmpsPktDrpInSleepMode++; + return; +} + +// Collects statistics for number of times BMPS init failed +void pmmBmpsUpdateInitFailureCnt(tpAniSirGlobal pMac) +{ + + pMac->pmm.BmpsInitFailCnt++; + return; +} + +// Collects statistics for number of times sleep request failed +void pmmBmpsUpdateSleepReqFailureCnt(tpAniSirGlobal pMac) +{ + + pMac->pmm.BmpsSleeReqFailCnt++; + return; +} + +// Collects statistics for number of times Wakeup request failed +void pmmBmpsUpdateWakeupReqFailureCnt(tpAniSirGlobal pMac) +{ + + pMac->pmm.BmpsWakeupReqFailCnt++; + return; +} + +// Collects statistics for number of times request / response received in invalid state +void pmmBmpsUpdateInvalidStateCnt(tpAniSirGlobal pMac) +{ + + pMac->pmm.BmpsInvStateCnt++; + return; +} + +// Collects statistics for number of times wakeup indications received +void pmmBmpsUpdateWakeupIndCnt(tpAniSirGlobal pMac) +{ + pMac->pmm.BmpsWakeupIndCnt++; + return; +} + +// Collects statistics for number of times wakeup indications received +void pmmBmpsUpdateHalReqFailureCnt(tpAniSirGlobal pMac) +{ + pMac->pmm.BmpsHalReqFailCnt++; + return; +} + +// Collects statistics for number of times requests received from HDD in +// invalid device role +void pmmBmpsUpdateReqInInvalidRoleCnt(tpAniSirGlobal pMac) +{ + pMac->pmm.BmpsReqInInvalidRoleCnt++; + return; +} + +// Resets PMM state ePMM_STATE_READY +void pmmResetPmmState(tpAniSirGlobal pMac) +{ + pMac->pmm.gPmmState = ePMM_STATE_READY; + + pMac->pmm.inMissedBeaconScenario = FALSE; + return; +} + +/* Sends Background scan message back to Lim */ +void pmmSendMessageToLim(tpAniSirGlobal pMac, + tANI_U32 msgId) +{ + tSirMsgQ limMsg; + tANI_U32 statusCode; + + limMsg.type = (tANI_U16) msgId; + limMsg.bodyptr = NULL; + limMsg.bodyval = 0; + + if ((statusCode = limPostMsgApi(pMac, &limMsg)) != eSIR_SUCCESS) + { + PELOGW(pmmLog(pMac, LOGW, + FL("posting message %X to LIM failed, reason=%d"), + limMsg.type, statusCode);) + } +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +void pmmFilterMatchCountResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpSirRcvFltPktMatchRsp pRcvFltPktMatchCntRsp; + eHalStatus rspStatus; + tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; + + /* we need to process all the deferred messages enqueued + * since the initiating the WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + pRcvFltPktMatchCntRsp = (tpSirRcvFltPktMatchRsp)(limMsg->bodyptr); + if (NULL == pRcvFltPktMatchCntRsp) + { + pmmLog(pMac, LOGE, FL("Received " + "WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP with NULL msg ")); + smeRspCode = eSIR_SME_PC_FILTER_MATCH_COUNT_REQ_FAILED; + } + else + { + rspStatus = pRcvFltPktMatchCntRsp->status; + if (eHAL_STATUS_SUCCESS == rspStatus) + { + pmmLog(pMac, LOGE, FL("Rcv successful response from HAL to get " + "Packet Coalescing Filter Match Count")); + } + else + { + pmmLog(pMac, LOGE, FL("HAL failed to get Packet Coalescing " + "Filter Match Count, informing SME")); + smeRspCode = eSIR_SME_PC_FILTER_MATCH_COUNT_REQ_FAILED; + } + } + + limSendSmeRsp(pMac, eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP, + smeRspCode, 0, 0); + return; +} +#endif // WLAN_FEATURE_PACKET_FILTERING + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void pmmGTKOffloadGetInfoResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRspParams; + eHalStatus rspStatus; + tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; + + /* we need to process all the deferred messages enqueued + * since the initiating the WDA_GTK_OFFLOAD_GETINFO_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + pGtkOffloadGetInfoRspParams = (tpSirGtkOffloadGetInfoRspParams)(limMsg->bodyptr); + if (NULL == pGtkOffloadGetInfoRspParams) + { + pmmLog(pMac, LOGE, FL("Received WDA_GTK_OFFLOAD_GETINFO_RSP with NULL msg ")); + smeRspCode = eSIR_SME_GTK_OFFLOAD_GETINFO_REQ_FAILED; + } + else + { + rspStatus = pGtkOffloadGetInfoRspParams->ulStatus; + if(rspStatus == eHAL_STATUS_SUCCESS) + { + pmmLog(pMac, LOGW, FL("Rcv successful response from HAL to get GTK Offload Information")); + } + else + { + pmmLog(pMac, LOGE, FL("HAL failed to get GTK Offload Information, informing SME")); + smeRspCode = eSIR_SME_GTK_OFFLOAD_GETINFO_REQ_FAILED; + } + } + + limSendSmeRsp(pMac, eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP, smeRspCode, 0, 0); + return; +} +#endif // WLAN_FEATURE_GTK_OFFLOAD + +/* Power save Offload Implementation */ +eHalStatus pmmPsOffloadOpen(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + if(psessionEntry->valid) + { + psessionEntry->pmmOffloadInfo.psstate = PMM_FULL_POWER; + psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; + + pmmLog(pMac, LOG1, + FL("ps offload open success for pe session %x"), + psessionEntry->peSessionId); + + return eHAL_STATUS_SUCCESS; + } + else + { + pmmLog(pMac, LOGE, + FL("ps offload open failed:invalid pe session")); + return eHAL_STATUS_FAILURE; + } +} + +eHalStatus pmmPsOffloadClose(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if(psessionEntry->valid) + { + psessionEntry->pmmOffloadInfo.psstate = PMM_FULL_POWER; + psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; + pmmLog(pMac, LOG1, + FL("ps offload close success for pe session %x"), + psessionEntry->peSessionId); + return eHAL_STATUS_SUCCESS; + } + else + { + pmmLog(pMac, LOGW, + FL("ps offload close failed:invalid pe session")); + return eHAL_STATUS_FAILURE; + } +} + +tANI_U8 pmmPsOffloadIsActive(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if(psessionEntry->valid && + psessionEntry->pmmOffloadInfo.psstate == PMM_FULL_POWER) + { + /* Session is in Active State */ + return TRUE; + } + else + { + /* Session is in Power Save State */ + return FALSE; + } +} + +tSirRetStatus pmmOffloadEnterBmpsRespHandler(tpAniSirGlobal pMac, + void *pRespData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpEnablePsParams psRespData = (tpEnablePsParams)pRespData; + + /* + * we need to process all the deferred messages enqueued since + * initiating SIR_HAL_ENTER_BMPS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(!pRespData) + { + pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Enter Bmps Resp"); + return eSIR_FAILURE; + } + + pmmLog(pMac, LOG1, + "pmmOffloadEnterBmpsRespHandler Status %x", psRespData->status); + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); + + if(!psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Enter Bmps Request"); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_SME_INVALID_STATE, + psRespData->sessionid, 0); + return eSIR_FAILURE; + } + + if(eHAL_STATUS_SUCCESS == psRespData->status) + { + psessionEntry->pmmOffloadInfo.psstate = PMM_POWER_SAVE; + pmmLog(pMac, LOG1, + "EnterBmpsResp Success PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_SUCCESS, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + else + { + pmmLog(pMac, LOGE, + "EnterBmpsResp Failed PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + return eSIR_SUCCESS; +} + +eHalStatus pmmOffloadFillUapsdParams(tpPESession psessionEntry, + tpUapsd_Params pUapsdParams) +{ + /* + * If gAcAdmitMask[SIR_MAC_DIRECTION_DLINK] is set,DeliveryEnabled bits are filled + * based on PSB from addts dynamically. If it is not set, DeliveryEnabled bits are + * filled from static values as per UapsdMask in ini file. + */ + + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBE) + { + pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcBitmask); + } + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBK) + { + pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcBitmask); + } + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVI) + { + pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcBitmask); + } + + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVO) + { + pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcDeliveryEnableMask); + } + else + { + pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcBitmask); + } + + /* + * If gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] is set,TriggerEnabled bits are filled + * based on PSB from addts dynamically. If it is not set, TriggerEnabled bits are + * filled from static values as per UapsdMask in ini file. + */ + + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBE) + { + pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcBitmask); + } + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBK) + { + pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcBitmask); + } + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVI) + { + pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcBitmask); + } + + if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVO) + { + pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcTriggerEnableMask); + } + else + { + pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcBitmask); + } + + return eHAL_STATUS_SUCCESS; +} + +tSirRetStatus pmmOffloadEnterBmpsReqHandler(tpAniSirGlobal pMac, + void *pReqData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpEnablePsParams pEnablePsReqParams; + tSirMsgQ msgQ; + tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; + + if(!psReqData) + { + pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Enter Bmps Request"); + return eSIR_FAILURE; + } + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); + + if(NULL == psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Enter Bmps Request"); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, 0, 0); + return eSIR_FAILURE; + } + + /* Missed Beacon Scenario. Don't allow Power Save */ + if(TRUE == psessionEntry->pmmOffloadInfo.bcnmiss) + { + pmmLog(pMac, LOGE, "Enter Bmps Request in Missed Beacon Scenario"); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + return eSIR_SUCCESS; + } + + pEnablePsReqParams = vos_mem_malloc(sizeof(*pEnablePsReqParams)); + if (NULL == pEnablePsReqParams) + { + pmmLog(pMac, LOGE, + FL("Memory allocation failed for pEnablePsReqParams")); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_zero(pEnablePsReqParams, sizeof(*pEnablePsReqParams)); + /* Fill the BSSID corresponding to PS Req */ + vos_mem_copy(pEnablePsReqParams->bssid, psReqData->bssId, + sizeof(tSirMacAddr)); + + /* Fill the Sme Session Id */ + pEnablePsReqParams->sessionid = psessionEntry->smeSessionId; + + /* Fill the Last Beacon DTIM Period */ + pEnablePsReqParams->bcnDtimPeriod = psessionEntry->lastBeaconDtimPeriod; + + /* Fill the additional power save setting */ + pEnablePsReqParams->psSetting = psReqData->addOnReq; + + if(eSIR_ADDON_ENABLE_UAPSD == pEnablePsReqParams->psSetting) + { + pmmOffloadFillUapsdParams(psessionEntry, + &pEnablePsReqParams->uapsdParams); + } + + msgQ.type = WDA_ENTER_BMPS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pEnablePsReqParams; + msgQ.bodyval = 0; + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) + { + pmmLog(pMac, LOGE, FL("Posting WDA_ENTER_BMPS_REQ failed")); + vos_mem_free(pEnablePsReqParams); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + return eSIR_FAILURE; + } + /* + * we need to defer any incoming messages until we + * get a WDA_EXIT_BMPS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + pmmLog(pMac, LOG1, FL("WDA_ENTER_BMPS_REQ Successfully sent to WDA")); + + return eSIR_SUCCESS; +} + +tSirRetStatus pmmOffloadExitBmpsRespHandler(tpAniSirGlobal pMac, + void *pRespData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpDisablePsParams psRespData = (tpDisablePsParams)pRespData; + + /* + * we need to process all the deferred messages enqueued since + * initiating SIR_HAL_EXIT_BMPS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(!pRespData) + { + pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Enter Bmps Resp"); + return eSIR_FAILURE; + } + + pmmLog(pMac, LOG1, + "pmmOffloadExitBmpsRespHandler Status %x", psRespData->status); + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); + + if(!psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Exit Bmps Request"); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_SME_INVALID_STATE, + psRespData->sessionid, 0); + return eSIR_FAILURE; + } + + if(eHAL_STATUS_SUCCESS == psRespData->status) + { + psessionEntry->pmmOffloadInfo.psstate = PMM_FULL_POWER; + pmmLog(pMac, LOG1, + "ExitBmpsResp Success PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_SUCCESS, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + else + { + pmmLog(pMac, LOGE, + "ExitBmpsResp Failed PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + + if(TRUE == psessionEntry->pmmOffloadInfo.bcnmiss) + { + pmmLog(pMac, LOGE, + "Exit BMPS:- Missed Bcn Scenario PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + /* Missed Beacon Scenario */ + limSendHeartBeatTimeoutInd(pMac, psessionEntry); + } + return eSIR_SUCCESS; +} + +tSirRetStatus pmmOffloadExitBmpsReqHandler(tpAniSirGlobal pMac, + void *pReqData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpDisablePsParams pDisablePsReqParams; + tSirMsgQ msgQ; + tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; + + if(!psReqData) + { + pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Exit Bmps Request"); + return eSIR_FAILURE; + } + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); + + if(NULL == psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Enter Bmps Request"); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, 0, 0); + return eSIR_FAILURE; + } + + pDisablePsReqParams = vos_mem_malloc(sizeof(*pDisablePsReqParams)); + if (NULL == pDisablePsReqParams) + { + pmmLog(pMac, LOGE, FL("Memory allocation failed for tDisablePsParams")); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_zero(pDisablePsReqParams, sizeof(*pDisablePsReqParams)); + /* Fill the BSSID corresponding to PS Req */ + vos_mem_copy(pDisablePsReqParams->bssid, psReqData->bssId, + sizeof(tSirMacAddr)); + + /* Fill the Sme Session Id */ + pDisablePsReqParams->sessionid = psessionEntry->smeSessionId; + + msgQ.type = WDA_EXIT_BMPS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pDisablePsReqParams; + msgQ.bodyval = 0; + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) + { + pmmLog(pMac, LOGE, FL("Posting WDA_EXIT_BMPS_REQ failed")); + vos_mem_free(pDisablePsReqParams); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + return eSIR_FAILURE; + } + /* + * we need to defer any incoming messages until we + * get a WDA_EXIT_BMPS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + pmmLog(pMac, LOG1, FL("WDA_EXIT_BMPS_REQ Successfully sent to WDA")); + + return eSIR_SUCCESS; +} + +tSirRetStatus pmmOffloadEnterUapsdRespHandler(tpAniSirGlobal pMac, + void *pRespData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpEnableUapsdParams psRespData = (tpEnableUapsdParams)pRespData; + + /* + * we need to process all the deferred messages enqueued since + * initiating SIR_HAL_ENTER_UAPSD_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(!pRespData) + { + pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Enter Uapsd Resp"); + return eSIR_FAILURE; + } + + pmmLog(pMac, LOG1, + "pmmOffloadEnterUapsdRespHandler Status %x", psRespData->status); + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); + + if(!psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Enter Uapsd Request"); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_SME_INVALID_STATE, + psRespData->sessionid, 0); + return eSIR_FAILURE; + } + + if(eHAL_STATUS_SUCCESS == psRespData->status) + { + pmmLog(pMac, LOG1, + "EnterUapsdResp Success PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_SUCCESS, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + else + { + pmmLog(pMac, LOGE, + "EnterUapsdResp Failed PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + return eSIR_SUCCESS; +} + + +tSirRetStatus pmmOffloadEnterUapsdReqHandler(tpAniSirGlobal pMac, + void *pReqData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpEnableUapsdParams pEnableUapsdReqParams; + tSirMsgQ msgQ; + tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; + tANI_U8 uapsdDeliveryMask = 0; + tANI_U8 uapsdTriggerMask = 0; + + if(!psReqData) + { + pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Enter Uapsd Request"); + return eSIR_FAILURE; + } + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); + + if(NULL == psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Enter Uapsd Request"); + return eSIR_FAILURE; + } + + pEnableUapsdReqParams = vos_mem_malloc(sizeof(*pEnableUapsdReqParams)); + if (NULL == pEnableUapsdReqParams) + { + pmmLog(pMac, LOGE, + FL("Memory allocation failed for pEnableUapsdReqParams")); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_zero(pEnableUapsdReqParams, sizeof(*pEnableUapsdReqParams)); + uapsdDeliveryMask = (psessionEntry->gUapsdPerAcBitmask | + psessionEntry->gUapsdPerAcDeliveryEnableMask); + + uapsdTriggerMask = (psessionEntry->gUapsdPerAcBitmask | + psessionEntry->gUapsdPerAcTriggerEnableMask); + + pEnableUapsdReqParams->uapsdParams.bkDeliveryEnabled = + LIM_UAPSD_GET(ACBK, uapsdDeliveryMask); + + pEnableUapsdReqParams->uapsdParams.beDeliveryEnabled = + LIM_UAPSD_GET(ACBE, uapsdDeliveryMask); + + pEnableUapsdReqParams->uapsdParams.viDeliveryEnabled = + LIM_UAPSD_GET(ACVI, uapsdDeliveryMask); + + pEnableUapsdReqParams->uapsdParams.voDeliveryEnabled = + LIM_UAPSD_GET(ACVO, uapsdDeliveryMask); + + pEnableUapsdReqParams->uapsdParams.bkTriggerEnabled = + LIM_UAPSD_GET(ACBK, uapsdTriggerMask); + + pEnableUapsdReqParams->uapsdParams.beTriggerEnabled = + LIM_UAPSD_GET(ACBE, uapsdTriggerMask); + + pEnableUapsdReqParams->uapsdParams.viTriggerEnabled = + LIM_UAPSD_GET(ACVI, uapsdTriggerMask); + + pEnableUapsdReqParams->uapsdParams.voTriggerEnabled = + LIM_UAPSD_GET(ACVO, uapsdTriggerMask); + + /* Fill the BSSID corresponding to PS Req */ + vos_mem_copy(pEnableUapsdReqParams->bssid, psReqData->bssId, + sizeof(tSirMacAddr)); + + /* Fill the Sme Session Id */ + pEnableUapsdReqParams->sessionid = psessionEntry->smeSessionId; + + msgQ.type = WDA_ENTER_UAPSD_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pEnableUapsdReqParams; + msgQ.bodyval = 0; + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) + { + pmmLog(pMac, LOGE, FL("Posting WDA_ENTER_UAPSD_REQ failed")); + vos_mem_free(pEnableUapsdReqParams); + return eSIR_FAILURE; + } + + /* + * we need to defer any incoming messages until we + * get a WDA_EXIT_UAPSD_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + pmmLog(pMac, LOG1, FL("WDA_ENTER_UAPSD_REQ Successfully sent to WDA")); + return eSIR_SUCCESS; +} + +tSirRetStatus pmmOffloadExitUapsdRespHandler(tpAniSirGlobal pMac, + void *pRespData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpDisableUapsdParams psRespData = (tpDisableUapsdParams)pRespData; + + /* + * we need to process all the deferred messages enqueued since + * initiating SIR_HAL_EXIT_UAPSD_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if(!pRespData) + { + pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Exit Uapsd Resp"); + return eSIR_FAILURE; + } + + pmmLog(pMac, LOG1, + "pmmOffloadExitUapsdRespHandler Status %x", psRespData->status); + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); + + if(!psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Exit Uapsd Request"); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SME_INVALID_STATE, + psRespData->sessionid, 0); + return eSIR_FAILURE; + } + + if(eHAL_STATUS_SUCCESS == psRespData->status) + { + pmmLog(pMac, LOG1, + "ExitUapsdResp Success PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SUCCESS, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + else + { + pmmLog(pMac, LOGE, + "ExitUapsdResp Failed PeSessionId %x SmeSessionId %x", + psessionEntry->peSessionId, psessionEntry->smeSessionId); + + limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_FAILURE, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } + return eSIR_SUCCESS; +} + +tSirRetStatus pmmOffloadExitUapsdReqHandler(tpAniSirGlobal pMac, + void *pReqData) +{ + tANI_U8 sessionId; + tpPESession psessionEntry; + tpDisableUapsdParams pDisableUapsdReqParams; + tSirMsgQ msgQ; + tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; + + if(!psReqData) + { + pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Exit Uapsd Request"); + return eSIR_FAILURE; + } + + /* Get the PE Session Corresponding to BSSID */ + psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); + + if(NULL == psessionEntry) + { + pmmLog(pMac, LOGE, + " No PE Session for given BSSID : Invalid Enter Uapsd Request"); + return eSIR_FAILURE; + } + + pDisableUapsdReqParams = vos_mem_malloc(sizeof(*pDisableUapsdReqParams)); + if (NULL == pDisableUapsdReqParams) + { + pmmLog(pMac, LOGE, + FL("Memory allocation failed for pDisableUapsdReqParams")); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_zero(pDisableUapsdReqParams, sizeof(*pDisableUapsdReqParams)); + /* Fill the BSSID corresponding to PS Req */ + vos_mem_copy(pDisableUapsdReqParams->bssid, psReqData->bssId, + sizeof(tSirMacAddr)); + + /* Fill the Sme Session Id */ + pDisableUapsdReqParams->sessionid = psessionEntry->smeSessionId; + + msgQ.type = WDA_EXIT_UAPSD_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pDisableUapsdReqParams; + msgQ.bodyval = 0; + + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) + { + pmmLog(pMac, LOGE, FL("Posting WDA_EXIT_UAPSD_REQ failed")); + vos_mem_free(pDisableUapsdReqParams); + return eSIR_FAILURE; + } + + /* + * we need to defer any incoming messages until we + * get a WDA_EXIT_UAPSD_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + pmmLog(pMac, LOG1, FL("WDA_EXIT_UAPSD_REQ Successfully sent to WDA")); + return eSIR_SUCCESS; +} + +void pmmOffloadProcessMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + switch (pMsg->type) + { + case eWNI_PMC_ENTER_BMPS_REQ: + { + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + + if(eSIR_SUCCESS != + pmmOffloadEnterBmpsReqHandler(pMac, pMbMsg->data)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process eWNI_PMC_ENTER_BMPS_REQ"); + } + } + break; + + case WDA_ENTER_BMPS_RSP: + if(eSIR_SUCCESS != + pmmOffloadEnterBmpsRespHandler(pMac, pMsg->bodyptr)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process WDA_ENTER_BMPS_RSP"); + } + break; + + case eWNI_PMC_EXIT_BMPS_REQ: + { + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + + if(eSIR_SUCCESS != + pmmOffloadExitBmpsReqHandler(pMac, pMbMsg->data)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process eWNI_PMC_EXIT_BMPS_REQ"); + } + } + break; + + case WDA_EXIT_BMPS_RSP: + if(eSIR_SUCCESS != + pmmOffloadExitBmpsRespHandler(pMac, pMsg->bodyptr)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process WDA_EXIT_BMPS_RSP"); + } + break; + + case eWNI_PMC_ENTER_UAPSD_REQ: + { + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + if(eSIR_SUCCESS != + pmmOffloadEnterUapsdReqHandler(pMac, pMbMsg->data)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process eWNI_PMC_ENTER_UAPSD_REQ"); + } + } + break; + + case WDA_ENTER_UAPSD_RSP: + if(eSIR_SUCCESS != + pmmOffloadEnterUapsdRespHandler(pMac, pMsg->bodyptr)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process WDA_ENTER_UAPSD_RSP"); + } + break; + + case eWNI_PMC_EXIT_UAPSD_REQ: + { + tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; + if(eSIR_SUCCESS != + pmmOffloadExitUapsdReqHandler(pMac, pMbMsg->data)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process eWNI_PMC_EXIT_UAPSD_REQ"); + } + } + break; + + case WDA_EXIT_UAPSD_RSP: + if(eSIR_SUCCESS != + pmmOffloadExitUapsdRespHandler(pMac, pMsg->bodyptr)) + { + pmmLog(pMac, LOGE, + "PMM: Failed to Process WDA_EXIT_UAPSD_RSP"); + } + break; + + case eWNI_PMC_WOWL_ADD_BCAST_PTRN: + pmmSendWowlAddBcastPtrn(pMac, pMsg); + break; + + case eWNI_PMC_WOWL_DEL_BCAST_PTRN: + pmmSendWowlDelBcastPtrn(pMac, pMsg); + break; + + case eWNI_PMC_ENTER_WOWL_REQ: + pmmEnterWowlRequestHandler(pMac, pMsg); + break; + + case WDA_WOWL_ENTER_RSP: + pmmLog(pMac, LOGE, + "PMM: WDA_WOWL_ENTER_RSP not supported yet"); + break; + + case eWNI_PMC_EXIT_WOWL_REQ: + pmmExitWowlanRequestHandler(pMac, pMsg); + break; + + case WDA_WOWL_EXIT_RSP: + pmmLog(pMac, LOGE, + "PMM: WDA_WOWL_EXIT_RSP not supported yet"); + break; + + default: + PELOGW(pmmLog(pMac, LOGW, + FL("PMM: Unknown message in pmmMsgQ type %d, potential memory leak!!"), + pMsg->type);) + } + + if (NULL != pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + pMsg->bodyptr = NULL; + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.c new file mode 100644 index 000000000000..2f0be76ce107 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file pmmDebug.c + + \brief implementation for log Debug related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +#include "vos_trace.h" +#include "pmmDebug.h" +#define LOG_SIZE 256 + +void pmmLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...) + { + VOS_TRACE_LEVEL vosDebugLevel; + char logBuffer[LOG_SIZE]; + va_list marker; + + /* getting proper Debug level */ + vosDebugLevel = getVosDebugLevel(loglevel); + + /* extracting arguments from pstring */ + va_start( marker, pString ); + vsnprintf(logBuffer, LOG_SIZE, pString, marker); + + VOS_TRACE(VOS_MODULE_ID_PMC, vosDebugLevel, "%s", logBuffer); + va_end( marker ); + } diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.h new file mode 100644 index 000000000000..6a748c4d3294 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/pmm/pmmDebug.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __PMM_DEBUG_H__ +#define __PMM_DEBUG_H__ + +#include "utilsApi.h" +#include "sirDebug.h" + +#define UL_HI( field ) ( *( ( (ULONG *)(&(field)) ) + 1 ) ) +#define UL_LO( field ) ( *( ( (ULONG *)(&(field)) ) + 0 ) ) + +#if !defined(__printf) +#define __printf(a,b) +#endif + +void __printf(3,4) pmmLog(tpAniSirGlobal pMac, tANI_U32 loglevel, + const char *pString, ...) ; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c new file mode 100644 index 000000000000..8d1e10af5ff9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/rrm/rrmApi.c @@ -0,0 +1,1327 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file rrmApi.c + + \brief implementation for PE RRM APIs + +========================================================================*/ + +/* $Header$ */ + +#if defined WLAN_FEATURE_VOWIFI + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "palTypes.h" +#include "wniApi.h" +#include "sirApi.h" +#include "aniGlobal.h" +#include "wniCfgSta.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limSendSmeRspMessages.h" +#include "parserApi.h" +#include "limSendMessages.h" +#include "rrmGlobal.h" +#include "rrmApi.h" + +tANI_U8 +rrmGetMinOfMaxTxPower(tpAniSirGlobal pMac, + tPowerdBm regMax, tPowerdBm apTxPower) +{ + tANI_U8 maxTxPower = 0; + tANI_U8 txPower = VOS_MIN( regMax, (apTxPower) ); + if((txPower >= RRM_MIN_TX_PWR_CAP) && (txPower <= RRM_MAX_TX_PWR_CAP)) + maxTxPower = txPower; + else if (txPower < RRM_MIN_TX_PWR_CAP) + maxTxPower = RRM_MIN_TX_PWR_CAP; + else + maxTxPower = RRM_MAX_TX_PWR_CAP; + + limLog( pMac, LOG3, + "%s: regulatoryMax = %d, apTxPwr = %d, maxTxpwr = %d", + __func__, regMax, apTxPower, maxTxPower ); + return maxTxPower; +} + +// -------------------------------------------------------------------- +/** + * rrmCacheMgmtTxPower + ** + * FUNCTION: Store Tx power for management frames. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry session entry. + * @return None + */ +void +rrmCacheMgmtTxPower ( tpAniSirGlobal pMac, tPowerdBm txPower, tpPESession pSessionEntry ) +{ + limLog( pMac, LOG3, "Cache Mgmt Tx Power = %d", txPower ); + + if( pSessionEntry == NULL ) + { + limLog( pMac, LOG3, "%s: pSessionEntry is NULL", __func__); + pMac->rrm.rrmPEContext.txMgmtPower = txPower; + } + else + pSessionEntry->txMgmtPower = txPower; +} + +// -------------------------------------------------------------------- +/** + * rrmGetMgmtTxPower + * + * FUNCTION: Get the Tx power for management frames. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry session entry. + * @return txPower + */ +tPowerdBm +rrmGetMgmtTxPower ( tpAniSirGlobal pMac, tpPESession pSessionEntry ) +{ + limLog( pMac, LOG3, "RrmGetMgmtTxPower called" ); + + if( pSessionEntry == NULL ) + { + limLog( pMac, LOG3, "%s: txpower from rrmPEContext: %d", + __func__, pMac->rrm.rrmPEContext.txMgmtPower); + return pMac->rrm.rrmPEContext.txMgmtPower; + } + + return pSessionEntry->txMgmtPower; +} + +// -------------------------------------------------------------------- +/** + * rrmSendSetMaxTxPowerReq + * + * FUNCTION: Send WDA_SET_MAX_TX_POWER_REQ message to change the max tx power. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param txPower txPower to be set. + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus +rrmSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, tPowerdBm txPower, tpPESession pSessionEntry ) +{ + tpMaxTxPowerParams pMaxTxParams; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if( pSessionEntry == NULL ) + { + PELOGE(limLog(pMac, LOGE, FL("Invalid parameters"));) + return eSIR_FAILURE; + } + pMaxTxParams = vos_mem_malloc(sizeof(tMaxTxPowerParams)); + if ( NULL == pMaxTxParams ) + { + limLog( pMac, LOGP, FL("Unable to allocate memory for pMaxTxParams ") ); + return eSIR_MEM_ALLOC_FAILED; + + } + /* Allocated memory for pMaxTxParams...will be freed in other module */ + pMaxTxParams->power = txPower; + vos_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr)); + vos_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + + + msgQ.type = WDA_SET_MAX_TX_POWER_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pMaxTxParams; + msgQ.bodyval = 0; + + limLog(pMac, LOG3, + FL( "Sending WDA_SET_MAX_TX_POWER_REQ with power(%d) to HAL"), + txPower); + + MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + limLog( pMac, LOGP, FL("Posting WDA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X"), retCode ); + vos_mem_free(pMaxTxParams); + return retCode; + } + return retCode; +} + + +// -------------------------------------------------------------------- +/** + * rrmSetMaxTxPowerRsp + * + * FUNCTION: Process WDA_SET_MAX_TX_POWER_RSP message. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param txPower txPower to be set. + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus +rrmSetMaxTxPowerRsp ( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; + tpPESession pSessionEntry; + tANI_U8 sessionId, i; + tSirMacAddr bssid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + if( vos_mem_compare(bssid, pMaxTxParams->bssId, sizeof(tSirMacAddr))) + { + for (i =0;i < pMac->lim.maxBssId;i++) + { + if ( (pMac->lim.gpSession[i].valid == TRUE )) + { + pSessionEntry = &pMac->lim.gpSession[i]; + rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + } + } + } + else + { + if((pSessionEntry = peFindSessionByBssid(pMac, pMaxTxParams->bssId, &sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to find session:") );) + retCode = eSIR_FAILURE; + } + else + { + rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + } + } + + vos_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return retCode; +} +// -------------------------------------------------------------------- +/** + * rrmProcessLinkMeasurementRequest + * + * FUNCTION: Processes the Link measurement request and send the report. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pBd pointer to BD to extract RSSI and SNR + * @param pLinkReq pointer to the Link request frame structure. + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus +rrmProcessLinkMeasurementRequest( tpAniSirGlobal pMac, + tANI_U8 *pRxPacketInfo, + tDot11fLinkMeasurementRequest *pLinkReq, + tpPESession pSessionEntry ) +{ + tSirMacLinkReport LinkReport; + tpSirMacMgmtHdr pHdr; + v_S7_t currentRSSI = 0; + + limLog( pMac, LOG3, "Received Link measurement request"); + + if( pRxPacketInfo == NULL || pLinkReq == NULL || pSessionEntry == NULL ) + { + PELOGE(limLog( pMac, LOGE, + "%s Invalid parameters - Ignoring the request", __func__);) + return eSIR_FAILURE; + } + pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); + + LinkReport.txPower = limGetMaxTxPower (pLinkReq->MaxTxPower.maxTxPower, + pLinkReq->MaxTxPower.maxTxPower, + pMac->roam.configParam.nTxPowerCap); + + if ((LinkReport.txPower != (uint8)(pSessionEntry->maxTxPower)) && + (eSIR_SUCCESS == rrmSendSetMaxTxPowerReq (pMac, + (tPowerdBm)(LinkReport.txPower), + pSessionEntry))) + { + PELOGW (limLog (pMac, + LOGW, + FL(" maxTx power in link report is not same as local..." + " Local = %d Link Request TxPower = %d" + " Link Report TxPower = %d"), + pSessionEntry->maxTxPower, + LinkReport.txPower, + pLinkReq->MaxTxPower.maxTxPower);) + pSessionEntry->maxTxPower = (tPowerdBm)(LinkReport.txPower); + } + + LinkReport.dialogToken = pLinkReq->DialogToken.token; + LinkReport.rxAntenna = 0; + LinkReport.txAntenna = 0; + currentRSSI = WDA_GET_RX_RSSI_RAW(pRxPacketInfo); + + limLog( pMac, LOG1, + "Received Link report frame with %d", currentRSSI); + + // 2008 11k spec reference: 18.4.8.5 RCPI Measurement + if ((currentRSSI) <= RCPI_LOW_RSSI_VALUE) + LinkReport.rcpi = 0; + else if ((currentRSSI > RCPI_LOW_RSSI_VALUE) && (currentRSSI <= 0)) + LinkReport.rcpi = CALCULATE_RCPI(currentRSSI); + else + LinkReport.rcpi = RCPI_MAX_VALUE; + + LinkReport.rsni = WDA_GET_RX_SNR(pRxPacketInfo); + + limLog( pMac, LOG3, "Sending Link report frame"); + + return limSendLinkReportActionFrame( pMac, &LinkReport, pHdr->sa, pSessionEntry ); +} + +// -------------------------------------------------------------------- +/** + * rrmProcessNeighborReportResponse + * + * FUNCTION: Processes the Neighbor Report response from the peer AP. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pNeighborRep pointer to the Neighbor report frame structure. + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus +rrmProcessNeighborReportResponse( tpAniSirGlobal pMac, + tDot11fNeighborReportResponse *pNeighborRep, + tpPESession pSessionEntry ) +{ + tSirRetStatus status = eSIR_FAILURE; + tpSirNeighborReportInd pSmeNeighborRpt = NULL; + tANI_U16 length; + tANI_U8 i; + tSirMsgQ mmhMsg; + + if( pNeighborRep == NULL || pSessionEntry == NULL ) + { + PELOGE(limLog( pMac, LOGE, FL(" Invalid parameters") );) + return status; + } + + limLog( pMac, LOG3, FL("Neighbor report response received ") ); + + // Dialog token + if( pMac->rrm.rrmPEContext.DialogToken != pNeighborRep->DialogToken.token ) + { + PELOGE(limLog( pMac, LOGE, + "Dialog token mismatch in the received Neighbor report");) + return eSIR_FAILURE; + } + if( pNeighborRep->num_NeighborReport == 0 ) + { + PELOGE(limLog( pMac, LOGE, "No neighbor report in the frame...Dropping it");) + return eSIR_FAILURE; + } + length = (sizeof( tSirNeighborReportInd )) + + (sizeof( tSirNeighborBssDescription ) * (pNeighborRep->num_NeighborReport - 1) ) ; + + //Prepare the request to send to SME. + pSmeNeighborRpt = vos_mem_malloc(length); + if( NULL == pSmeNeighborRpt ) + { + PELOGE(limLog( pMac, LOGP, FL("Unable to allocate memory") );) + return eSIR_MEM_ALLOC_FAILED; + + } + vos_mem_set(pSmeNeighborRpt, length, 0); + + /* Allocated memory for pSmeNeighborRpt...will be freed by other module */ + + for( i = 0 ; i < pNeighborRep->num_NeighborReport ; i++ ) + { + pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof( tSirNeighborBssDescription ); /*+ any optional ies */ + vos_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId, + pNeighborRep->NeighborReport[i].bssid, + sizeof(tSirMacAddr)); + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fApPreauthReachable = pNeighborRep->NeighborReport[i].APReachability; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fSameSecurityMode = pNeighborRep->NeighborReport[i].Security; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fSameAuthenticator = pNeighborRep->NeighborReport[i].KeyScope; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fCapSpectrumMeasurement = pNeighborRep->NeighborReport[i].SpecMgmtCap; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fCapQos = pNeighborRep->NeighborReport[i].QosCap; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fCapApsd = pNeighborRep->NeighborReport[i].apsd; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fCapDelayedBlockAck = pNeighborRep->NeighborReport[i].DelayedBA; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fCapImmediateBlockAck = pNeighborRep->NeighborReport[i].ImmBA; + pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.fMobilityDomain = pNeighborRep->NeighborReport[i].MobilityDomain; + + pSmeNeighborRpt->sNeighborBssDescription[i].regClass = pNeighborRep->NeighborReport[i].regulatoryClass; + pSmeNeighborRpt->sNeighborBssDescription[i].channel = pNeighborRep->NeighborReport[i].channel; + pSmeNeighborRpt->sNeighborBssDescription[i].phyType = pNeighborRep->NeighborReport[i].PhyType; + } + + pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND; + pSmeNeighborRpt->length = length; + pSmeNeighborRpt->sessionId = pSessionEntry->smeSessionId; + pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport; + vos_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr)); + + //Send request to SME. + mmhMsg.type = pSmeNeighborRpt->messageType; + mmhMsg.bodyptr = pSmeNeighborRpt; + MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, mmhMsg.type)); + status = limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + + return status; + +} + +// -------------------------------------------------------------------- +/** + * rrmProcessNeighborReportReq + * + * FUNCTION: + * + * LOGIC: Create a Neighbor report request and send it to peer. + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pNeighborReq Neighbor report request params . + * @return None + */ +tSirRetStatus +rrmProcessNeighborReportReq( tpAniSirGlobal pMac, + tpSirNeighborReportReqInd pNeighborReq ) +{ + tSirRetStatus status = eSIR_SUCCESS; + tSirMacNeighborReportReq NeighborReportReq; + tpPESession pSessionEntry ; + tANI_U8 sessionId; + + if( pNeighborReq == NULL ) + { + PELOGE(limLog( pMac, LOGE, "NeighborReq is NULL" );) + return eSIR_FAILURE; + } + if ((pSessionEntry = peFindSessionByBssid(pMac,pNeighborReq->bssId,&sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) + return eSIR_FAILURE; + } + + limLog( pMac, LOG1, FL("SSID present = %d "), pNeighborReq->noSSID ); + + vos_mem_set(&NeighborReportReq,sizeof( tSirMacNeighborReportReq ), 0); + + NeighborReportReq.dialogToken = ++pMac->rrm.rrmPEContext.DialogToken; + NeighborReportReq.ssid_present = !pNeighborReq->noSSID; + if( NeighborReportReq.ssid_present ) + { + vos_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID, sizeof(tSirMacSSid)); + PELOGE(sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOGE, (tANI_U8*) NeighborReportReq.ssid.ssId, NeighborReportReq.ssid.length );) + } + + status = limSendNeighborReportRequestFrame( pMac, &NeighborReportReq, pNeighborReq->bssId, pSessionEntry ); + + return status; +} + +#define ABS(x) ((x < 0) ? -x : x) +// -------------------------------------------------------------------- +/** + * rrmProcessBeaconReportReq + * + * FUNCTION: Processes the Beacon report request from the peer AP. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pCurrentReq pointer to the current Req context. + * @param pBeaconReq pointer to the beacon report request IE from the peer. + * @param pSessionEntry session entry. + * @return None + */ +static tRrmRetStatus +rrmProcessBeaconReportReq( tpAniSirGlobal pMac, + tpRRMReq pCurrentReq, + tDot11fIEMeasurementRequest *pBeaconReq, + tpPESession pSessionEntry ) +{ + tSirMsgQ mmhMsg; + tpSirBeaconReportReqInd pSmeBcnReportReq; + tANI_U8 num_channels = 0, num_APChanReport; + tANI_U16 measDuration, maxMeasduration; + tANI_S8 maxDuration; + tANI_U8 sign; + + if( pBeaconReq->measurement_request.Beacon.BeaconReporting.present && + (pBeaconReq->measurement_request.Beacon.BeaconReporting.reportingCondition != 0) ) + { + /* + * Repeated measurement is not supported. This means number of repetitions + * should be zero.(Already checked). + * All test case in VoWifi(as of version 0.36) use zero for number of + * repetitions. Beacon reporting should not be included in request + * if number of repetitions is zero. + * IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 + */ + + PELOGE(limLog( pMac, LOGE, "Dropping the request: Reporting condition included in beacon report request and it is not zero");) + return eRRM_INCAPABLE; + } + + /* The logic here is to check the measurement duration passed in the beacon request. Following are the cases handled. + Case 1: If measurement duration received in the beacon request is greater than the max measurement duration advertised + in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 1, REFUSE the beacon request + Case 2: If measurement duration received in the beacon request is greater than the max measurement duration advertised + in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 0, perform measurement for + the duration advertised in the RRM capabilities + + maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval + */ + maxDuration = pMac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4; + sign = (maxDuration < 0) ? 1 : 0; + maxDuration = (1L << ABS(maxDuration)); + if (!sign) + maxMeasduration = maxDuration * pSessionEntry->beaconParams.beaconInterval; + else + maxMeasduration = pSessionEntry->beaconParams.beaconInterval / maxDuration; + + measDuration = pBeaconReq->measurement_request.Beacon.meas_duration; + + limLog( pMac, LOG3, + "maxDuration = %d sign = %d maxMeasduration = %d measDuration = %d", + maxDuration, sign, maxMeasduration, measDuration ); + + if( maxMeasduration < measDuration ) + { + if( pBeaconReq->durationMandatory ) + { + PELOGE(limLog( pMac, LOGE, "Dropping the request: duration mandatory and maxduration > measduration");) + return eRRM_REFUSED; + } + else + measDuration = maxMeasduration; + } + + //Cache the data required for sending report. + pCurrentReq->request.Beacon.reportingDetail = pBeaconReq->measurement_request.Beacon.BcnReportingDetail.present ? + pBeaconReq->measurement_request.Beacon.BcnReportingDetail.reportingDetail : + BEACON_REPORTING_DETAIL_ALL_FF_IE ; + + if( pBeaconReq->measurement_request.Beacon.RequestedInfo.present ) + { + pCurrentReq->request.Beacon.reqIes.pElementIds = vos_mem_malloc(sizeof(tANI_U8) * + pBeaconReq->measurement_request.Beacon.RequestedInfo.num_requested_eids); + if ( NULL == pCurrentReq->request.Beacon.reqIes.pElementIds ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory for request IEs buffer" )); + return eRRM_FAILURE; + } + limLog( pMac, LOG3, FL(" Allocated memory for pElementIds") ); + + pCurrentReq->request.Beacon.reqIes.num = pBeaconReq->measurement_request.Beacon.RequestedInfo.num_requested_eids; + vos_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds, + pBeaconReq->measurement_request.Beacon.RequestedInfo.requested_eids, + pCurrentReq->request.Beacon.reqIes.num); + } + + if( pBeaconReq->measurement_request.Beacon.num_APChannelReport ) + { + for( num_APChanReport = 0 ; num_APChanReport < pBeaconReq->measurement_request.Beacon.num_APChannelReport ; num_APChanReport++ ) + num_channels += pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList; + } + + //Prepare the request to send to SME. + pSmeBcnReportReq = vos_mem_malloc(sizeof( tSirBeaconReportReqInd )); + if ( NULL == pSmeBcnReportReq ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during Beacon Report Req Ind to SME" )); + + return eRRM_FAILURE; + + } + + vos_mem_set(pSmeBcnReportReq,sizeof( tSirBeaconReportReqInd ),0); + + /* Allocated memory for pSmeBcnReportReq will be freed by other modules */ + vos_mem_copy(pSmeBcnReportReq->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr)); + pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND; + pSmeBcnReportReq->length = sizeof( tSirBeaconReportReqInd ); + pSmeBcnReportReq->uDialogToken = pBeaconReq->measurement_token; + pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_11K; + pSmeBcnReportReq->randomizationInterval = SYS_TU_TO_MS (pBeaconReq->measurement_request.Beacon.randomization); + pSmeBcnReportReq->channelInfo.regulatoryClass = pBeaconReq->measurement_request.Beacon.regClass; + pSmeBcnReportReq->channelInfo.channelNum = pBeaconReq->measurement_request.Beacon.channel; + pSmeBcnReportReq->measurementDuration[0] = SYS_TU_TO_MS(measDuration); + pSmeBcnReportReq->fMeasurementtype[0] = pBeaconReq->measurement_request.Beacon.meas_mode; + vos_mem_copy(pSmeBcnReportReq->macaddrBssid, pBeaconReq->measurement_request.Beacon.BSSID, + sizeof(tSirMacAddr)); + + if( pBeaconReq->measurement_request.Beacon.SSID.present ) + { + pSmeBcnReportReq->ssId.length = pBeaconReq->measurement_request.Beacon.SSID.num_ssid; + vos_mem_copy(pSmeBcnReportReq->ssId.ssId, + pBeaconReq->measurement_request.Beacon.SSID.ssid, + pSmeBcnReportReq->ssId.length); + } + + pCurrentReq->token = pBeaconReq->measurement_token; + + pSmeBcnReportReq->channelList.numChannels = num_channels; + if( pBeaconReq->measurement_request.Beacon.num_APChannelReport ) + { + tANI_U8 *pChanList = pSmeBcnReportReq->channelList.channelNumber; + for( num_APChanReport = 0 ; num_APChanReport < pBeaconReq->measurement_request.Beacon.num_APChannelReport ; num_APChanReport++ ) + { + vos_mem_copy(pChanList, + pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].channelList, + pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList); + + pChanList += pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList; + } + } + + //Send request to SME. + mmhMsg.type = eWNI_SME_BEACON_REPORT_REQ_IND; + mmhMsg.bodyptr = pSmeBcnReportReq; + MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, mmhMsg.type)); + return limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); +} + +// -------------------------------------------------------------------- +/** + * rrmFillBeaconIes + * + * FUNCTION: + * + * LOGIC: Fills Fixed fields and Ies in bss description to an array of tANI_U8. + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pIes - pointer to the buffer that should be populated with ies. + * @param pNumIes - returns the num of ies filled in this param. + * @param pIesMaxSize - Max size of the buffer pIes. + * @param eids - pointer to array of eids. If NULL, all ies will be populated. + * @param numEids - number of elements in array eids. + * @param pBssDesc - pointer to Bss Description. + * @return None + */ +static void +rrmFillBeaconIes( tpAniSirGlobal pMac, + tANI_U8 *pIes, tANI_U8 *pNumIes, tANI_U8 pIesMaxSize, + tANI_U8 *eids, tANI_U8 numEids, + tpSirBssDescription pBssDesc ) +{ + tANI_U8 len, *pBcnIes, count = 0, i; + tANI_U8 BcnNumIes; + + if( (pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL) ) + { + PELOGE(limLog( pMac, LOGE, FL(" Invalid parameters") );) + return; + } + + //Make sure that if eid is null, numEids is set to zero. + numEids = (eids == NULL) ? 0 : numEids; + + pBcnIes = (tANI_U8*) &pBssDesc->ieFields[0]; + BcnNumIes = (tANI_U8)GET_IE_LEN_IN_BSS( pBssDesc->length ); + + *pNumIes = 0; + + *((tANI_U32*)pIes) = pBssDesc->timeStamp[0]; + *pNumIes+=sizeof(tANI_U32); pIes+=sizeof(tANI_U32); + *((tANI_U32*)pIes) = pBssDesc->timeStamp[1]; + *pNumIes+=sizeof(tANI_U32); pIes+=sizeof(tANI_U32); + *((tANI_U16*)pIes) = pBssDesc->beaconInterval; + *pNumIes+=sizeof(tANI_U16); pIes+=sizeof(tANI_U16); + *((tANI_U16*)pIes) = pBssDesc->capabilityInfo; + *pNumIes+=sizeof(tANI_U16); pIes+=sizeof(tANI_U16); + + while ( BcnNumIes > 0 ) + { + len = *(pBcnIes + 1) + 2; //element id + length. + limLog( pMac, LOG3, "EID = %d, len = %d total = %d", + *pBcnIes, *(pBcnIes+1), len ); + + i = 0; + do + { + if( ( (eids == NULL) || ( *pBcnIes == eids[i] ) ) && + ( (*pNumIes) + len) < pIesMaxSize ) + { + limLog( pMac, LOG3, "Adding Eid %d, len=%d", *pBcnIes, len ); + + vos_mem_copy(pIes, pBcnIes, len); + pIes += len; + *pNumIes += len; + count++; + break; + } + i++; + }while( i < numEids ); + + pBcnIes += len; + BcnNumIes -= len; + } + limLog( pMac, LOG1, "Total length of Ies added = %d", *pNumIes ); +} + +// -------------------------------------------------------------------- +/** + * rrmProcessBeaconReportXmit + * + * FUNCTION: + * + * LOGIC: Create a Radio measurement report action frame and send it to peer. + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pBcnReport Data for beacon report IE from SME. + * @return None + */ +tSirRetStatus +rrmProcessBeaconReportXmit( tpAniSirGlobal pMac, + tpSirBeaconReportXmitInd pBcnReport) +{ + tSirRetStatus status = eSIR_SUCCESS; + tSirMacRadioMeasureReport *pReport = NULL; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + tpPESession pSessionEntry ; + tANI_U8 sessionId; + v_U8_t flagBSSPresent = FALSE, bssDescCnt = 0; + + limLog( pMac, LOG1, "Received beacon report xmit indication"); + + if (NULL == pBcnReport) + { + PELOGE(limLog( pMac, LOGE, + "Received pBcnReport is NULL in PE");) + return eSIR_FAILURE; + } + + if (NULL == pCurrentReq) + { + PELOGE(limLog( pMac, LOGE, + "Received report xmit while there is no request pending in PE");) + return eSIR_FAILURE; + } + + if( (pBcnReport->numBssDesc) || + (!pBcnReport->numBssDesc && pCurrentReq->sendEmptyBcnRpt) ) + { + pBcnReport->numBssDesc = (pBcnReport->numBssDesc == RRM_BCN_RPT_NO_BSS_INFO)? + RRM_BCN_RPT_MIN_RPT : pBcnReport->numBssDesc; + + if (NULL == (pSessionEntry = peFindSessionByBssid(pMac, + pBcnReport->bssId, + &sessionId))) + { + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given bssId"));) + return eSIR_FAILURE; + } + + pReport = vos_mem_malloc(pBcnReport->numBssDesc * + sizeof(tSirMacRadioMeasureReport)); + + if (NULL == pReport) + { + PELOGE(limLog(pMac, LOGE, FL("RRM Report is NULL, allocation failed"));) + return eSIR_FAILURE; + } + + vos_mem_zero( pReport, + pBcnReport->numBssDesc * sizeof(tSirMacRadioMeasureReport) ); + + for (bssDescCnt = 0; bssDescCnt < pBcnReport->numBssDesc; bssDescCnt++) + { + //Prepare the beacon report and send it to the peer. + pReport[bssDescCnt].token = pBcnReport->uDialogToken; + pReport[bssDescCnt].refused = 0; + pReport[bssDescCnt].incapable = 0; + pReport[bssDescCnt].type = SIR_MAC_RRM_BEACON_TYPE; + + //If the scan result is NULL then send report request with + //option subelement as NULL.. + if ( NULL != pBcnReport->pBssDescription[bssDescCnt] ) + { + flagBSSPresent = TRUE; + } + + //Valid response is included if the size of beacon xmit + //is == size of beacon xmit ind + ies + if ( pBcnReport->length >= sizeof( tSirBeaconReportXmitInd ) ) + { + pReport[bssDescCnt].report.beaconReport.regClass = pBcnReport->regClass; + if ( flagBSSPresent ) + { + pReport[bssDescCnt].report.beaconReport.channel = + pBcnReport->pBssDescription[bssDescCnt]->channelId; + vos_mem_copy( pReport[bssDescCnt].report.beaconReport.measStartTime, + pBcnReport->pBssDescription[bssDescCnt]->startTSF, + sizeof( pBcnReport->pBssDescription[bssDescCnt]->startTSF) ); + pReport[bssDescCnt].report.beaconReport.measDuration = + SYS_MS_TO_TU(pBcnReport->duration); + pReport[bssDescCnt].report.beaconReport.phyType = + pBcnReport->pBssDescription[bssDescCnt]->nwType; + pReport[bssDescCnt].report.beaconReport.bcnProbeRsp = 1; + pReport[bssDescCnt].report.beaconReport.rsni = + pBcnReport->pBssDescription[bssDescCnt]->sinr; + pReport[bssDescCnt].report.beaconReport.rcpi = + pBcnReport->pBssDescription[bssDescCnt]->rssi; + + pReport[bssDescCnt].report.beaconReport.antennaId = 0; + pReport[bssDescCnt].report.beaconReport.parentTSF = + pBcnReport->pBssDescription[bssDescCnt]->parentTSF; + vos_mem_copy( pReport[bssDescCnt].report.beaconReport.bssid, + pBcnReport->pBssDescription[bssDescCnt]->bssId, + sizeof(tSirMacAddr)); + } + + switch ( pCurrentReq->request.Beacon.reportingDetail ) + { + case BEACON_REPORTING_DETAIL_NO_FF_IE: + //0 No need to include any elements. + limLog(pMac, LOG3, "No reporting detail requested"); + break; + case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE: + //1: Include all FFs and Requested Ies. + limLog(pMac, LOG3, + "Only requested IEs in reporting detail requested"); + + if ( flagBSSPresent ) + { + rrmFillBeaconIes( pMac, + (tANI_U8*) &pReport[bssDescCnt].report.beaconReport.Ies[0], + (tANI_U8*) &pReport[bssDescCnt].report.beaconReport.numIes, + BEACON_REPORT_MAX_IES, + pCurrentReq->request.Beacon.reqIes.pElementIds, + pCurrentReq->request.Beacon.reqIes.num, + pBcnReport->pBssDescription[bssDescCnt] ); + } + + break; + case BEACON_REPORTING_DETAIL_ALL_FF_IE: + //2 / default - Include all FFs and all Ies. + default: + limLog(pMac, LOG3, "Default all IEs and FFs"); + if ( flagBSSPresent ) + { + rrmFillBeaconIes( pMac, + (tANI_U8*) &pReport[bssDescCnt].report.beaconReport.Ies[0], + (tANI_U8*) &pReport[bssDescCnt].report.beaconReport.numIes, + BEACON_REPORT_MAX_IES, + NULL, 0, + pBcnReport->pBssDescription[bssDescCnt] ); + } + break; + } + } + } + + limLog( pMac, LOG1, "Sending Action frame with %d bss info", bssDescCnt); + limSendRadioMeasureReportActionFrame( pMac, + pCurrentReq->dialog_token, + bssDescCnt, + pReport, + pBcnReport->bssId, + pSessionEntry ); + + pCurrentReq->sendEmptyBcnRpt = false; + } + + if( pBcnReport->fMeasureDone ) + { + limLog( pMac, LOG3, "Measurement done....cleanup the context"); + + rrmCleanup(pMac); + } + + if( NULL != pReport ) + vos_mem_free(pReport); + + return status; +} + +void rrmProcessBeaconRequestFailure(tpAniSirGlobal pMac, tpPESession pSessionEntry, + tSirMacAddr peer, tRrmRetStatus status) +{ + tpSirMacRadioMeasureReport pReport = NULL; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + + pReport = vos_mem_malloc(sizeof( tSirMacRadioMeasureReport )); + if ( NULL == pReport ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during RRM Req processing" )); + return; + } + vos_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0); + pReport->token = pCurrentReq->token; + pReport->type = SIR_MAC_RRM_BEACON_TYPE; + + switch (status) + { + case eRRM_REFUSED: + pReport->refused = 1; + break; + case eRRM_INCAPABLE: + pReport->incapable = 1; + break; + default: + PELOGE(limLog( pMac, LOGE, + FL(" Beacon request processing failed no report sent with status %d "), + status);); + vos_mem_free(pReport); + return; + } + + limSendRadioMeasureReportActionFrame( pMac, pCurrentReq->dialog_token, 1, + pReport, peer, pSessionEntry ); + + vos_mem_free(pReport); + limLog( pMac, LOG3, FL(" Free memory for pReport") ); + return; +} + +// -------------------------------------------------------------------- +/** + * rrmProcessRadioMeasurementRequest + * + * FUNCTION: Processes the Radio Resource Measurement request. + * + * LOGIC: + + +* + * ASSUMPTIONS: + * + * NOTE: + * + * @param peer Macaddress of the peer requesting the radio measurement. + * @param pRRMReq Array of Measurement request IEs + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus +rrmProcessRadioMeasurementRequest( tpAniSirGlobal pMac, + tSirMacAddr peer, + tDot11fRadioMeasurementRequest *pRRMReq, + tpPESession pSessionEntry ) +{ + tANI_U8 i; + tSirRetStatus status = eSIR_SUCCESS; + tpSirMacRadioMeasureReport pReport = NULL; + tANI_U8 num_report = 0; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + tRrmRetStatus rrmStatus = eRRM_SUCCESS; + + if( !pRRMReq->num_MeasurementRequest ) + { + //No measurement requests.... + // + pReport = vos_mem_malloc(sizeof( tSirMacRadioMeasureReport )); + if ( NULL == pReport ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during RRM Req processing" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set(pReport, sizeof(tSirMacRadioMeasureReport),0); + PELOGE(limLog( pMac, LOGE, + FL("No requestIes in the measurement request, sending incapable report"));) + pReport->incapable = 1; + num_report = 1; + limSendRadioMeasureReportActionFrame( pMac, pRRMReq->DialogToken.token, num_report, + pReport, peer, pSessionEntry ); + vos_mem_free(pReport); + return eSIR_FAILURE; + } + + // PF Fix + if( pRRMReq->NumOfRepetitions.repetitions > 0 ) + { + limLog( pMac, LOG1, + FL(" number of repetitions %d"), + pRRMReq->NumOfRepetitions.repetitions ); + + //Send a report with incapable bit set. Not supporting repetitions. + pReport = vos_mem_malloc(sizeof( tSirMacRadioMeasureReport )); + if ( NULL == pReport ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during RRM Req processing" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0); + PELOGE(limLog( pMac, LOGE, FL(" Allocated memory for pReport") );) + pReport->incapable = 1; + pReport->type = pRRMReq->MeasurementRequest[0].measurement_type; + num_report = 1; + goto end; + + } + + for( i= 0; i < pRRMReq->num_MeasurementRequest; i++ ) + { + switch( pRRMReq->MeasurementRequest[i].measurement_type ) + { + case SIR_MAC_RRM_BEACON_TYPE: + //Process beacon request. + if( pCurrentReq ) + { + if ( pReport == NULL ) //Allocate memory to send reports for any subsequent requests. + { + pReport = vos_mem_malloc(sizeof( tSirMacRadioMeasureReport ) + * (pRRMReq->num_MeasurementRequest - i)); + if ( NULL == pReport ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during RRM Req processing" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set(pReport, + sizeof( tSirMacRadioMeasureReport ) + * (pRRMReq->num_MeasurementRequest - i), + 0); + limLog( pMac, LOG3, + FL(" rrm beacon type refused of %d report in beacon table"), + num_report ); + + } + pReport[num_report].refused = 1; + pReport[num_report].type = SIR_MAC_RRM_BEACON_TYPE; + pReport[num_report].token = pRRMReq->MeasurementRequest[i].measurement_token; + num_report++; + continue; + } + else + { + pCurrentReq = vos_mem_malloc(sizeof( *pCurrentReq )); + if ( NULL == pCurrentReq ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during RRM Req processing" )); + vos_mem_free(pReport); + return eSIR_MEM_ALLOC_FAILED; + } + limLog( pMac, LOG3, FL(" Processing Beacon Report request") ); + vos_mem_set(pCurrentReq, sizeof( *pCurrentReq ), 0); + pCurrentReq->dialog_token = pRRMReq->DialogToken.token; + pCurrentReq->token = pRRMReq->MeasurementRequest[i].measurement_token; + pCurrentReq->sendEmptyBcnRpt = true; + pMac->rrm.rrmPEContext.pCurrentReq = pCurrentReq; + rrmStatus = rrmProcessBeaconReportReq( pMac, pCurrentReq, &pRRMReq->MeasurementRequest[i], pSessionEntry ); + if (eRRM_SUCCESS != rrmStatus) + { + rrmProcessBeaconRequestFailure(pMac, pSessionEntry, peer, rrmStatus); + rrmCleanup(pMac); + } + } + break; + case SIR_MAC_RRM_LCI_TYPE: + case SIR_MAC_RRM_LOCATION_CIVIC_TYPE: + case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE: + limLog(pMac, LOG1, FL("RRM with type: %d sent to userspace"), + pRRMReq->MeasurementRequest[i].measurement_type); + break; + default: + /* Send a report with incapable bit set. */ + if ( pReport == NULL ) //Allocate memory to send reports for any subsequent requests. + { + pReport = vos_mem_malloc(sizeof( tSirMacRadioMeasureReport ) + * (pRRMReq->num_MeasurementRequest - i)); + if ( NULL == pReport ) + { + limLog( pMac, LOGP, + FL( "Unable to allocate memory during RRM Req processing" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set(pReport, + sizeof( tSirMacRadioMeasureReport ) + * (pRRMReq->num_MeasurementRequest - i), + 0); + limLog( pMac, LOG3, + FL("rrm beacon type incapable of %d report "), + num_report ); + } + pReport[num_report].incapable = 1; + pReport[num_report].type = pRRMReq->MeasurementRequest[i].measurement_type; + pReport[num_report].token = pRRMReq->MeasurementRequest[i].measurement_token; + num_report++; + break; + } + } + +end: + if( pReport ) + { + limSendRadioMeasureReportActionFrame( pMac, pRRMReq->DialogToken.token, num_report, + pReport, peer, pSessionEntry ); + + vos_mem_free(pReport); + limLog( pMac, LOG3, FL(" Free memory for pReport") ); + } + return status; + +} + +// -------------------------------------------------------------------- +/** + * rrmUpdateStartTSF + ** + * FUNCTION: Store start TSF of measurement. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param startTSF - TSF value at the start of measurement. + * @return None + */ +void +rrmUpdateStartTSF ( tpAniSirGlobal pMac, tANI_U32 startTSF[2] ) +{ + pMac->rrm.rrmPEContext.startTSF[0] = startTSF[0]; + pMac->rrm.rrmPEContext.startTSF[1] = startTSF[1]; +} + +// -------------------------------------------------------------------- +/** + * rrmGetStartTSF + * + * FUNCTION: Get the Start TSF. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param startTSF - store star TSF in this buffer. + * @return txPower + */ +void +rrmGetStartTSF ( tpAniSirGlobal pMac, tANI_U32 *pStartTSF ) +{ + pStartTSF[0] = pMac->rrm.rrmPEContext.startTSF[0]; + pStartTSF[1] = pMac->rrm.rrmPEContext.startTSF[1]; + +} +// -------------------------------------------------------------------- +/** + * rrmGetCapabilities + * + * FUNCTION: + * Returns a pointer to tpRRMCaps with all the caps enabled in RRM + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry + * @return pointer to tRRMCaps + */ +tpRRMCaps rrmGetCapabilities ( tpAniSirGlobal pMac, + tpPESession pSessionEntry ) +{ + return &pMac->rrm.rrmPEContext.rrmEnabledCaps; +} + +// -------------------------------------------------------------------- +/** + * rrmInitialize + * + * FUNCTION: + * Initialize RRM module + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @return None + */ + +tSirRetStatus +rrmInitialize(tpAniSirGlobal pMac) +{ + tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps; + + pMac->rrm.rrmPEContext.pCurrentReq = NULL; + pMac->rrm.rrmPEContext.txMgmtPower = 0; + pMac->rrm.rrmPEContext.DialogToken = 0; + + pMac->rrm.rrmPEContext.rrmEnable = 0; + + vos_mem_set(pRRMCaps, sizeof(tRRMCaps), 0); + pRRMCaps->LinkMeasurement = 1; + pRRMCaps->NeighborRpt = 1; + pRRMCaps->BeaconPassive = 1; + pRRMCaps->BeaconActive = 1; + pRRMCaps->BeaconTable = 1; + pRRMCaps->APChanReport = 1; + pRRMCaps->fine_time_meas_rpt = 1; + pRRMCaps->lci_capability = 1; + + pRRMCaps->operatingChanMax = 3; + pRRMCaps->nonOperatingChanMax = 3; + + return eSIR_SUCCESS; +} + +// -------------------------------------------------------------------- +/** + * rrmCleanup + * + * FUNCTION: + * cleanup RRM module + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param mode + * @param rate + * @return None + */ + +tSirRetStatus +rrmCleanup(tpAniSirGlobal pMac) +{ + if( pMac->rrm.rrmPEContext.pCurrentReq ) + { + if( pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes.pElementIds ) + { + vos_mem_free(pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes.pElementIds); + limLog( pMac, LOG4, FL(" Free memory for pElementIds") ); + } + + vos_mem_free(pMac->rrm.rrmPEContext.pCurrentReq); + limLog( pMac, LOG4, FL(" Free memory for pCurrentReq") ); + } + + pMac->rrm.rrmPEContext.pCurrentReq = NULL; + return eSIR_SUCCESS; +} + +// -------------------------------------------------------------------- +/** + * rrmProcessMessage + * + * FUNCTION: Processes the next received Radio Resource Management message + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void rrmProcessMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + switch (pMsg->type) + { + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + rrmProcessNeighborReportReq( pMac, pMsg->bodyptr ); + break; + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: + rrmProcessBeaconReportXmit( pMac, pMsg->bodyptr ); + break; + default: + limLog(pMac, LOGE, FL("Invalid msg type:%d"), pMsg->type); + } + +} + +/** + * lim_update_rrm_capability() - Update PE context's rrm capability + * @mac_ctx: Global pointer to MAC context + * @join_req: Pointer to SME join request. + * + * Update PE context's rrm capability based on SME join request. + * + * Return: None + */ +void lim_update_rrm_capability(tpAniSirGlobal mac_ctx, + tpSirSmeJoinReq join_req) +{ + mac_ctx->rrm.rrmPEContext.rrmEnable = join_req->rrm_config.rrm_enabled; + vos_mem_copy(&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps, + &join_req->rrm_config.rm_capability, + RMENABLEDCAP_MAX_LEN); + + return; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c new file mode 100644 index 000000000000..8052338b18bd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c @@ -0,0 +1,664 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file schApi.cc contains functions related to the API exposed + * by scheduler module + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "aniGlobal.h" +#include "wniCfgSta.h" + +#include "sirMacProtDef.h" +#include "sirMacPropExts.h" +#include "sirCommon.h" + + +#include "cfgApi.h" +#include "pmmApi.h" + +#include "limApi.h" + +#include "schApi.h" +#include "schDebug.h" + +#include "schSysParams.h" +#include "limTrace.h" +#include "limTypes.h" + +#include "wlan_qct_wda.h" + +//-------------------------------------------------------------------- +// +// Static Variables +// +//------------------------------------------------------------------- + +// -------------------------------------------------------------------- +/** + * schGetCFPCount + * + * FUNCTION: + * Function used by other Sirius modules to read CFPcount + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +tANI_U8 +schGetCFPCount(tpAniSirGlobal pMac) +{ + return pMac->sch.schObject.gSchCFPCount; +} + +// -------------------------------------------------------------------- +/** + * schGetCFPDurRemaining + * + * FUNCTION: + * Function used by other Sirius modules to read CFPDuration remaining + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +tANI_U16 +schGetCFPDurRemaining(tpAniSirGlobal pMac) +{ + return pMac->sch.schObject.gSchCFPDurRemaining; +} + + +// -------------------------------------------------------------------- +/** + * schInitialize + * + * FUNCTION: + * Initialize + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void +schInitialize(tpAniSirGlobal pMac) +{ + pmmInitialize(pMac); +} + +// -------------------------------------------------------------------- +/** + * schInitGlobals + * + * FUNCTION: + * Initialize globals + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void +schInitGlobals(tpAniSirGlobal pMac) +{ + pMac->sch.gSchHcfEnabled = false; + + pMac->sch.gSchScanRequested = false; + pMac->sch.gSchScanReqRcvd = false; + + pMac->sch.gSchGenBeacon = 1; + pMac->sch.gSchBeaconsSent = 0; + pMac->sch.gSchBeaconsWritten = 0; + pMac->sch.gSchBcnParseErrorCnt = 0; + pMac->sch.gSchBcnIgnored = 0; + pMac->sch.gSchBBXportRcvCnt = 0; + pMac->sch.gSchUnknownRcvCnt = 0; + pMac->sch.gSchBcnRcvCnt = 0; + pMac->sch.gSchRRRcvCnt = 0; + pMac->sch.qosNullCnt = 0; + pMac->sch.numData = 0; + pMac->sch.numPoll = 0; + pMac->sch.numCorrupt = 0; + pMac->sch.numBogusInt = 0; + pMac->sch.numTxAct0 = 0; + pMac->sch.rrTimeout = SCH_RR_TIMEOUT; + pMac->sch.pollPeriod = SCH_POLL_PERIOD; + pMac->sch.keepAlive = 0; + pMac->sch.multipleSched = 1; + pMac->sch.maxPollTimeouts = 20; + pMac->sch.checkCfbFlagStuck = 0; +} + +// -------------------------------------------------------------------- +/** + * schPostMessage + * + * FUNCTION: + * Post the beacon message to the scheduler message queue + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMsg pointer to message + * @return None + */ + +tSirRetStatus +schPostMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + schProcessMessage(pMac, pMsg); + + return eSIR_SUCCESS; +} + + + + + +// --------------------------------------------------------------------------- +/** + * schSendStartScanRsp + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void +schSendStartScanRsp(tpAniSirGlobal pMac) +{ + tSirMsgQ msgQ; + tANI_U32 retCode; + + PELOG1(schLog(pMac, LOG1, FL("Sending LIM message to go into scan"));) + msgQ.type = SIR_SCH_START_SCAN_RSP; + if ((retCode = limPostMsgApi(pMac, &msgQ)) != eSIR_SUCCESS) + schLog(pMac, LOGE, + FL("Posting START_SCAN_RSP to LIM failed, reason=%X"), retCode); +} + +/** + * schSendBeaconReq + * + * FUNCTION: + * + * LOGIC: + * 1) SCH received SIR_SCH_BEACON_GEN_IND + * 2) SCH updates TIM IE and other beacon related IE's + * 3) SCH sends WDA_SEND_BEACON_REQ to HAL. HAL then copies the beacon + * template to memory + * + * ASSUMPTIONS: + * Memory allocation is reqd to send this message and SCH allocates memory. + * The assumption is that HAL will "free" this memory. + * + * NOTE: + * + * @param pMac global + * + * @param beaconPayload + * + * @param size - Length of the beacon + * + * @return eHalStatus + */ +tSirRetStatus schSendBeaconReq( tpAniSirGlobal pMac, tANI_U8 *beaconPayload, tANI_U16 size, tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpSendbeaconParams beaconParams = NULL; + tSirRetStatus retCode; + + schLog( pMac, LOG2, + FL( "Indicating HAL to copy the beacon template [%d bytes] to memory" ), + size ); + + beaconParams = vos_mem_malloc(sizeof(tSendbeaconParams)); + if ( NULL == beaconParams ) + return eSIR_FAILURE; + + msgQ.type = WDA_SEND_BEACON_REQ; + + // No Dialog Token reqd, as a response is not solicited + msgQ.reserved = 0; + + // Fill in tSendbeaconParams members + vos_mem_copy(beaconParams->bssId, psessionEntry->bssId, sizeof(psessionEntry->bssId)); + + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + beaconParams->timIeOffset = 0; + } else { + beaconParams->timIeOffset = psessionEntry->schBeaconOffsetBegin; + } + + /* p2pIeOffset should be at-least greater than timIeOffset */ + if ((pMac->sch.schObject.p2pIeOffset != 0) && + (pMac->sch.schObject.p2pIeOffset < + psessionEntry->schBeaconOffsetBegin)) + { + schLog(pMac, LOGE,FL("Invalid p2pIeOffset:[%d]"), + pMac->sch.schObject.p2pIeOffset); + VOS_ASSERT( 0 ); + vos_mem_free(beaconParams); + return eSIR_FAILURE; + } + beaconParams->p2pIeOffset = pMac->sch.schObject.p2pIeOffset; +#ifdef WLAN_SOFTAP_FW_BEACON_TX_PRNT_LOG + schLog(pMac, LOGE,FL("TimIeOffset:[%d]"),beaconParams->TimIeOffset ); +#endif + + beaconParams->beacon = beaconPayload; + beaconParams->beaconLength = (tANI_U32) size; + msgQ.bodyptr = beaconParams; + msgQ.bodyval = 0; + + // Keep a copy of recent beacon frame sent + + // free previous copy of the beacon + if (psessionEntry->beacon ) + { + vos_mem_free(psessionEntry->beacon); + } + + psessionEntry->bcnLen = 0; + psessionEntry->beacon = NULL; + + psessionEntry->beacon = vos_mem_malloc(size); + if ( psessionEntry->beacon != NULL ) + { + vos_mem_copy(psessionEntry->beacon, beaconPayload, size); + psessionEntry->bcnLen = size; + } + + MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + schLog( pMac, LOGE, + FL("Posting SEND_BEACON_REQ to HAL failed, reason=%X"), + retCode ); + } else + { + schLog( pMac, LOG2, + FL("Successfully posted WDA_SEND_BEACON_REQ to HAL")); + + if (LIM_IS_AP_ROLE(psessionEntry) && + pMac->sch.schObject.fBeaconChanged) { + if(eSIR_SUCCESS != (retCode = limSendProbeRspTemplateToHal(pMac,psessionEntry, + &psessionEntry->DefProbeRspIeBitmap[0]))) + { + /* check whether we have to free any memory */ + schLog(pMac, LOGE, FL("FAILED to send probe response template with retCode %d"), retCode); + } + } + } + + return retCode; +} + +tANI_U32 limRemoveP2pIeFromAddIe(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tANI_U8 *addIeWoP2pIe, + tANI_U32 *addnIELenWoP2pIe) +{ + tANI_U32 left = psessionEntry->addIeParams.probeRespDataLen; + v_U8_t *ptr = psessionEntry->addIeParams.probeRespData_buff; + v_U8_t elem_id,elem_len; + tANI_U32 offset=0; + v_U8_t eid = 0xDD; + + vos_mem_copy(addIeWoP2pIe, ptr, left); + *addnIELenWoP2pIe = left; + + if (addIeWoP2pIe != NULL) + { + while (left >= 2) + { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if(elem_len > left) + { + schLog(pMac, LOGE, FL("Invalid IEs")); + return eSIR_FAILURE; + } + if ((elem_id == eid) && + (vos_mem_compare( &ptr[2], "\x50\x6f\x9a\x09", 4)==VOS_TRUE)) + { + left -= elem_len; + ptr += (elem_len + 2); + vos_mem_copy(&addIeWoP2pIe[offset], ptr, left); + *addnIELenWoP2pIe -= (2 + elem_len); + } + else + { + left -= elem_len; + ptr += (elem_len + 2); + offset += 2 + elem_len; + } + } + } + return eSIR_SUCCESS; +} + +tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEntry + ,tANI_U32* IeBitmap) +{ + tSirMsgQ msgQ; + tANI_U8 *pFrame2Hal = psessionEntry->pSchProbeRspTemplate; + tpSendProbeRespParams pprobeRespParams=NULL; + tANI_U32 retCode = eSIR_FAILURE; + tANI_U32 nPayload,nBytes,nStatus; + tpSirMacMgmtHdr pMacHdr; + tANI_U32 addnIEPresent = VOS_FALSE; + tANI_U32 addnIELen=0; + tSirRetStatus nSirStatus; + tANI_U8 *addIE = NULL; + tANI_U8 *addIeWoP2pIe = NULL; + tANI_U32 addnIELenWoP2pIe = 0; + tANI_U32 retStatus; + + nStatus = dot11fGetPackedProbeResponseSize( pMac, &psessionEntry->probeRespFrame, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + schLog( pMac, LOGE, FL("Failed to calculate the packed size f" + "or a Probe Response (0x%08x)."), + nStatus ); + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fProbeResponse ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + schLog( pMac, LOGE, FL("There were warnings while calculating" + "the packed size for a Probe Response " + "(0x%08x)."), nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + //Check if probe response IE is present or not + addnIEPresent = (psessionEntry->addIeParams.probeRespDataLen != 0); + if (addnIEPresent) + { + /* + * probe response template should not have P2P IE. + * In case probe request has P2P IE or WPS IE, the + * probe request will be forwarded to the Host and + * Host will send the probe response. In other cases + * FW will send the probe response. So, if the template + * has P2P IE, the probe response sent to non P2P devices + * by the FW, may also have P2P IE which will fail + * P2P cert case 6.1.3 + */ + addIeWoP2pIe = vos_mem_malloc(psessionEntry->addIeParams.probeRespDataLen); + if ( NULL == addIeWoP2pIe ) + { + schLog(pMac, LOGE, FL("FAILED to alloc memory when removing P2P IE")); + return eSIR_FAILURE; + } + + retStatus = limRemoveP2pIeFromAddIe(pMac, psessionEntry, + addIeWoP2pIe, &addnIELenWoP2pIe); + if (retStatus != eSIR_SUCCESS) + { + vos_mem_free(addIeWoP2pIe); + return eSIR_FAILURE; + } + + //Probe rsp IE available + /*need to check the data length*/ + addIE = vos_mem_malloc(addnIELenWoP2pIe); + + if ( NULL == addIE ) + { + schLog(pMac, LOGE, + FL("Unable to get WNI_CFG_PROBE_RSP_ADDNIE_DATA1 length")); + vos_mem_free(addIeWoP2pIe); + return retCode; + } + addnIELen = addnIELenWoP2pIe; + + if (addnIELen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addnIELen && + (nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) + { + vos_mem_copy(addIE, addIeWoP2pIe, addnIELenWoP2pIe); + } + vos_mem_free(addIeWoP2pIe); + } + + if (addnIEPresent) + { + if ((nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE ) + nBytes += addnIELen; + else + addnIEPresent = false; //Dont include the IE. + } + + // Paranoia: + vos_mem_set(pFrame2Hal, nBytes, 0); + + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame2Hal, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_RSP, psessionEntry->selfMacAddr,psessionEntry->selfMacAddr); + + if ( eSIR_SUCCESS != nSirStatus ) + { + schLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a Probe Response (%d)."), + nSirStatus ); + + vos_mem_free(addIE); + return retCode; + } + + pMacHdr = ( tpSirMacMgmtHdr ) pFrame2Hal; + + sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + + // That done, pack the Probe Response: + nStatus = dot11fPackProbeResponse( pMac, &psessionEntry->probeRespFrame, pFrame2Hal + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload ); + + if ( DOT11F_FAILED( nStatus ) ) + { + schLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x)."), + nStatus ); + + vos_mem_free(addIE); + return retCode; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + schLog( pMac, LOGE, FL("There were warnings while packing a P" + "robe Response (0x%08x)."), nStatus ); + } + + if (addnIEPresent) + { + vos_mem_copy ( &pFrame2Hal[nBytes - addnIELen], + &addIE[0], addnIELen); + } + + /* free the allocated Memory */ + vos_mem_free(addIE); + + pprobeRespParams = vos_mem_malloc(sizeof( tSendProbeRespParams )); + if ( NULL == pprobeRespParams ) + { + schLog( pMac, LOGE, FL("limSendProbeRspTemplateToHal: HAL probe response params malloc failed for bytes %d"), nBytes ); + } + else + { + sirCopyMacAddr( pprobeRespParams->bssId, psessionEntry->bssId); + pprobeRespParams->pProbeRespTemplate = pFrame2Hal; + pprobeRespParams->probeRespTemplateLen = nBytes; + vos_mem_copy(pprobeRespParams->ucProxyProbeReqValidIEBmap,IeBitmap,(sizeof(tANI_U32) * 8)); + msgQ.type = WDA_SEND_PROBE_RSP_TMPL; + msgQ.reserved = 0; + msgQ.bodyptr = pprobeRespParams; + msgQ.bodyval = 0; + + if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + { + /* free the allocated Memory */ + schLog( pMac,LOGE, FL("limSendProbeRspTemplateToHal: FAIL bytes %d retcode[%X]"), nBytes, retCode ); + vos_mem_free(pprobeRespParams); + } + else + { + schLog( pMac,LOG1, FL("limSendProbeRspTemplateToHal: Probe response template msg posted to HAL of bytes %d"),nBytes ); + } + } + + return retCode; +} + +/** + * schGenTimingAdvertFrame() - Generate the TA frame and populate the buffer + * @pMac: the global MAC context + * @self_addr: the self MAC address + * @buf: the buffer that will contain the frame + * @timestamp_offset: return for the offset of the timestamp field + * @time_value_offset: return for the time_value field in the TA IE + * + * Return: the length of the buffer. + */ +int schGenTimingAdvertFrame(tpAniSirGlobal mac_ctx, tSirMacAddr self_addr, + uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset) +{ + tDot11fTimingAdvertisementFrame frame; + uint32_t payload_size, buf_size; + int status; + v_MACADDR_t wildcard_bssid = { + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }; + + vos_mem_zero((uint8_t*)&frame, sizeof(tDot11fTimingAdvertisementFrame)); + + /* Populate the TA fields */ + status = PopulateDot11fTimingAdvertFrame(mac_ctx, &frame); + if (status) { + schLog(mac_ctx, LOGE, FL("Error populating TA frame %x"), status); + return status; + } + + status = dot11fGetPackedTimingAdvertisementFrameSize(mac_ctx, &frame, + &payload_size); + if (DOT11F_FAILED(status)) { + schLog(mac_ctx, LOGE, FL("Error getting packed frame size %x"), status); + return status; + } else if (DOT11F_WARNED(status)) { + schLog(mac_ctx, LOGW, FL("Warning getting packed frame size")); + } + + buf_size = sizeof(tSirMacMgmtHdr) + payload_size; + *buf = vos_mem_malloc(buf_size); + if (*buf == NULL) { + schLog(mac_ctx, LOGE, FL("Cannot allocate memory")); + return eSIR_FAILURE; + } + vos_mem_zero(*buf, buf_size); + + payload_size = 0; + status = dot11fPackTimingAdvertisementFrame(mac_ctx, &frame, + *buf + sizeof(tSirMacMgmtHdr), buf_size - sizeof(tSirMacMgmtHdr), + &payload_size); + schLog(mac_ctx, LOGE, FL("TA payload size2 = %d"), payload_size); + if (DOT11F_FAILED(status)) { + schLog(mac_ctx, LOGE, FL("Error packing frame %x"), status); + goto fail; + } else if (DOT11F_WARNED(status)) { + schLog(mac_ctx, LOGE, FL("Warning packing frame")); + } + + limPopulateMacHeader(mac_ctx, *buf, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_TIME_ADVERT, wildcard_bssid.bytes, self_addr); + + /* The timestamp field is right after the header */ + *timestamp_offset = sizeof(tSirMacMgmtHdr); + + *time_value_offset = sizeof(tSirMacMgmtHdr) + sizeof(tDot11fFfTimeStamp) + + sizeof(tDot11fFfCapabilities); + + /* Add the Country IE length */ + dot11fGetPackedIECountry(mac_ctx, &frame.Country, time_value_offset); + /* Add 2 for Country IE EID and Length fields */ + *time_value_offset += 2; + + /* Add the PowerConstraint IE size */ + if (frame.Country.present == 1) + *time_value_offset += 3; + + /* Add the offset inside TA IE */ + *time_value_offset += 3; + + return payload_size + sizeof(tSirMacMgmtHdr); + +fail: + if (*buf) + vos_mem_free(*buf); + return status; +} \ No newline at end of file diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c new file mode 100644 index 000000000000..9dac92550e6c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c @@ -0,0 +1,904 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file schBeaconGen.cc contains beacon generation related + * functions + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "palTypes.h" +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "sirMacProtDef.h" + +#include "limUtils.h" +#include "limApi.h" + + +#include "halMsgApi.h" +#include "cfgApi.h" +#include "pmmApi.h" +#include "schApi.h" + +#include "parserApi.h" + +#include "schDebug.h" + +// +// March 15, 2006 +// Temporarily (maybe for all of Alpha-1), assuming TIM = 0 +// + +const tANI_U8 P2pOui[] = {0x50, 0x6F, 0x9A, 0x9}; + + +tSirRetStatus schGetP2pIeOffset(tANI_U8 *pExtraIe, tANI_U32 extraIeLen, tANI_U16 *pP2pIeOffset) +{ + tSirRetStatus status = eSIR_FAILURE; + *pP2pIeOffset = 0; + + // Extra IE is not present + if(0 == extraIeLen) + { + return status; + } + + // Calculate the P2P IE Offset + do + { + if(*pExtraIe == 0xDD) + { + if ( vos_mem_compare ( (void *)(pExtraIe+2), &P2pOui, sizeof(P2pOui) ) ) + { + status = eSIR_SUCCESS; + break; + } + } + + (*pP2pIeOffset)++; + pExtraIe++; + }while(--extraIeLen > 0); + + return status; +} + +tSirRetStatus schAppendAddnIE(tpAniSirGlobal pMac, tpPESession psessionEntry, + tANI_U8 *pFrame, tANI_U32 maxBeaconSize, + tANI_U32 *nBytes) +{ + tSirRetStatus status = eSIR_FAILURE; + tANI_U32 present, len; + tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN]; + + present = (psessionEntry->addIeParams.probeRespBCNDataLen != 0); + if(present) + { + len = psessionEntry->addIeParams.probeRespBCNDataLen; + + if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len && + ((len + *nBytes) <= maxBeaconSize)) + { + + vos_mem_copy(&addIE[0], + psessionEntry->addIeParams.probeRespBCNData_buff, len); + + { + tANI_U8* pP2pIe = limGetP2pIEPtr(pMac, &addIE[0], len); + if ((pP2pIe != NULL) && !pMac->beacon_offload) + { + tANI_U8 noaLen = 0; + tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + //get NoA attribute stream P2P IE + noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry); + if(noaLen) + { + if ((noaLen + len) <= + WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) { + vos_mem_copy(&addIE[len], noaStream, noaLen); + len += noaLen; + /* Update IE Len */ + pP2pIe[1] += noaLen; + } + else + { + schLog(pMac, LOGE, + FL("Not able to insert NoA because of length constraint")); + } + } + } + if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) + { + vos_mem_copy(pFrame, &addIE[0], len); + *nBytes = *nBytes + len; + } + else + { + schLog(pMac, LOGW, FL("Not able to insert because of" + " length constraint %d"), len); + } + } + } + } + + return status; +} + +// -------------------------------------------------------------------- +/** + * schSetFixedBeaconFields + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tpAniBeaconStruct pBeacon = (tpAniBeaconStruct) + psessionEntry->pSchBeaconFrameBegin; + tpSirMacMgmtHdr mac; + tANI_U16 offset; + tANI_U8 *ptr; + tDot11fBeacon1 *pBcn1; + tDot11fBeacon2 *pBcn2; + tANI_U32 i, nStatus, nBytes; + tANI_U32 wpsApEnable=0, tmp; + tDot11fIEWscProbeRes *pWscProbeRes; + tANI_U8 *pExtraIe = NULL; + tANI_U32 extraIeLen =0; + tANI_U16 extraIeOffset = 0; + tANI_U16 p2pIeOffset = 0; + tSirRetStatus status = eSIR_SUCCESS; + tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + + pBcn1 = vos_mem_malloc(sizeof(tDot11fBeacon1)); + if ( NULL == pBcn1 ) + { + schLog(pMac, LOGE, FL("Failed to allocate memory") ); + return eSIR_FAILURE; + } + + pBcn2 = vos_mem_malloc(sizeof(tDot11fBeacon2)); + if ( NULL == pBcn2 ) + { + schLog(pMac, LOGE, FL("Failed to allocate memory") ); + vos_mem_free(pBcn1); + return eSIR_FAILURE; + } + + pWscProbeRes = vos_mem_malloc(sizeof(tDot11fIEWscProbeRes)); + if ( NULL == pWscProbeRes ) + { + schLog(pMac, LOGE, FL("Failed to allocate memory") ); + vos_mem_free(pBcn1); + vos_mem_free(pBcn2); + return eSIR_FAILURE; + } + + PELOG1(schLog(pMac, LOG1, FL("Setting fixed beacon fields"));) + + /* + * First set the fixed fields + */ + + // set the TFP headers + + // set the mac header + vos_mem_set(( tANI_U8*) &pBeacon->macHdr, sizeof( tSirMacMgmtHdr ),0); + mac = (tpSirMacMgmtHdr) &pBeacon->macHdr; + mac->fc.type = SIR_MAC_MGMT_FRAME; + mac->fc.subType = SIR_MAC_MGMT_BEACON; + + for (i=0; i<6; i++) + mac->da[i] = 0xff; + + vos_mem_copy(mac->sa, psessionEntry->selfMacAddr, sizeof(psessionEntry->selfMacAddr)); + vos_mem_copy(mac->bssId, psessionEntry->bssId, sizeof (psessionEntry->bssId)); + + mac->fc.fromDS = 0; + mac->fc.toDS = 0; + + /* + * Now set the beacon body + */ + + vos_mem_set(( tANI_U8*) pBcn1, sizeof( tDot11fBeacon1 ), 0); + + /* Skip over the time stamp (it'll be updated later). */ + + pBcn1->BeaconInterval.interval = pMac->sch.schObject.gSchBeaconInterval; + PopulateDot11fCapabilities( pMac, &pBcn1->Capabilities, psessionEntry ); + if (psessionEntry->ssidHidden) + { + pBcn1->SSID.present = 1; /* Rest of the fields are 0 for hidden ssid */ + if((psessionEntry->ssId.length) && + (psessionEntry->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS)) + pBcn1->SSID.num_ssid = psessionEntry->ssId.length; + } + else + { + PopulateDot11fSSID( pMac, &psessionEntry->ssId, &pBcn1->SSID ); + } + + + PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &pBcn1->SuppRates,psessionEntry); + PopulateDot11fDSParams( pMac, &pBcn1->DSParams, psessionEntry->currentOperChannel, psessionEntry); + PopulateDot11fIBSSParams( pMac, &pBcn1->IBSSParams,psessionEntry); + + offset = sizeof( tAniBeaconStruct ); + ptr = psessionEntry->pSchBeaconFrameBegin + offset; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + /* Initialize the default IE bitmap to zero */ + vos_mem_set(( tANI_U8* )&(psessionEntry->DefProbeRspIeBitmap), (sizeof( tANI_U32 ) * 8), 0); + + /* Initialize the default IE bitmap to zero */ + vos_mem_set(( tANI_U8* )&(psessionEntry->probeRespFrame), + sizeof(psessionEntry->probeRespFrame), 0); + + /* Can be efficiently updated whenever new IE added + * in Probe response in future + */ + if (limUpdateProbeRspTemplateIeBitmapBeacon1(pMac, pBcn1, + psessionEntry) != eSIR_SUCCESS) { + schLog(pMac, LOGE, + FL("Failed to build ProbeRsp template")); + } + } + + nStatus = dot11fPackBeacon1( pMac, pBcn1, ptr, + SCH_MAX_BEACON_SIZE - offset, + &nBytes ); + if ( DOT11F_FAILED( nStatus ) ) + { + schLog( pMac, LOGE, FL("Failed to packed a tDot11fBeacon1 (0x%0" + "8x.)."), nStatus ); + vos_mem_free(pBcn1); + vos_mem_free(pBcn2); + vos_mem_free(pWscProbeRes); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + schLog( pMac, LOGE, FL("There were warnings while packing a tDo" + "t11fBeacon1 (0x%08x.)."), nStatus ); + } + /*changed to correct beacon corruption */ + vos_mem_set(( tANI_U8*) pBcn2, sizeof( tDot11fBeacon2 ), 0); + psessionEntry->schBeaconOffsetBegin = offset + ( tANI_U16 )nBytes; + schLog( pMac, LOG1, FL("Initialized beacon begin, offset %d"), offset ); + + /* + * Initialize the 'new' fields at the end of the beacon + */ + + if ((psessionEntry->limSystemRole == eLIM_AP_ROLE) && + psessionEntry->dfsIncludeChanSwIe == VOS_TRUE) { + populate_dot_11_f_ext_chann_switch_ann(pMac, + &pBcn2->ext_chan_switch_ann, + psessionEntry); + } + + populate_dot11_supp_operating_classes(pMac, &pBcn2->SuppOperatingClasses, + psessionEntry); + PopulateDot11fCountry( pMac, &pBcn2->Country, psessionEntry); + if(pBcn1->Capabilities.qos) + { + PopulateDot11fEDCAParamSet( pMac, &pBcn2->EDCAParamSet, psessionEntry); + } + + if(psessionEntry->lim11hEnable) + { + PopulateDot11fPowerConstraints( pMac, &pBcn2->PowerConstraints ); + PopulateDot11fTPCReport( pMac, &pBcn2->TPCReport, psessionEntry); + + /* Need to insert channel switch announcement here */ + if ((LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_P2P_DEVICE_GO(psessionEntry)) && + psessionEntry->dfsIncludeChanSwIe == VOS_TRUE) { + /* Channel switch announcement only if radar is detected + * and SAP has instructed to announce channel switch IEs + * in beacon and probe responses + */ + PopulateDot11fChanSwitchAnn(pMac, &pBcn2->ChanSwitchAnn, + psessionEntry); +#ifdef WLAN_FEATURE_11AC + /* TODO: If in 11AC mode, wider bw channel switch announcement needs + * to be called + */ + /*PopulateDot11fWiderBWChanSwitchAnn(pMac, &pBcn2->WiderBWChanSwitchAnn, + psessionEntry);*/ +#endif + /* + * Populate the Channel Switch Wrapper Element if + * SAP operates in 40/80 Mhz Channel Width. + */ + if (VOS_TRUE == psessionEntry->dfsIncludeChanWrapperIe) + { + PopulateDot11fChanSwitchWrapper(pMac, + &pBcn2->ChannelSwitchWrapper, + psessionEntry); + } + } + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* populate proprietary IE for MDM device operating in AP-MCC */ + populate_dot11f_avoid_channel_ie(pMac, &pBcn2->QComVendorIE, psessionEntry); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + if (psessionEntry->dot11mode != WNI_CFG_DOT11_MODE_11B) + PopulateDot11fERPInfo( pMac, &pBcn2->ERPInfo, psessionEntry ); + + if(psessionEntry->htCapability) + { + PopulateDot11fHTCaps( pMac,psessionEntry, &pBcn2->HTCaps ); + PopulateDot11fHTInfo( pMac, &pBcn2->HTInfo, psessionEntry ); + } +#ifdef WLAN_FEATURE_11AC + if(psessionEntry->vhtCapability) + { + schLog( pMac, LOGW, FL("Populate VHT IEs in Beacon")); + PopulateDot11fVHTCaps( pMac, psessionEntry, &pBcn2->VHTCaps ); + PopulateDot11fVHTOperation( pMac, psessionEntry, &pBcn2->VHTOperation); + isVHTEnabled = eANI_BOOLEAN_TRUE; + // we do not support multi users yet + //PopulateDot11fVHTExtBssLoad( pMac, &bcn2.VHTExtBssLoad); + if(psessionEntry->gLimOperatingMode.present) + PopulateDot11fOperatingMode( pMac, &pBcn2->OperatingMode, psessionEntry ); + } +#endif + + PopulateDot11fExtCap(pMac, isVHTEnabled, &pBcn2->ExtCap, psessionEntry); + + PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &pBcn2->ExtSuppRates, psessionEntry ); + + if( psessionEntry->pLimStartBssReq != NULL ) + { + PopulateDot11fWPA( pMac, &psessionEntry->pLimStartBssReq->rsnIE, + &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) + { + PopulateDot11fWMM( pMac, &pBcn2->WMMInfoAp, &pBcn2->WMMParams, &pBcn2->WMMCaps, psessionEntry); + } + if (LIM_IS_AP_ROLE(psessionEntry)) { + if(psessionEntry->wps_state != SAP_WPS_DISABLED) + { + PopulateDot11fBeaconWPSIEs( pMac, &pBcn2->WscBeacon, psessionEntry); + } + } + else + { + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) + schLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); + + wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; + + if (wpsApEnable) + { + PopulateDot11fWsc(pMac, &pBcn2->WscBeacon); + } + + if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_BEGIN) + { + PopulateDot11fWscRegistrarInfo(pMac, &pBcn2->WscBeacon); + pMac->lim.wscIeInfo.wscEnrollmentState = eLIM_WSC_ENROLL_IN_PROGRESS; + } + + if (pMac->lim.wscIeInfo.wscEnrollmentState == eLIM_WSC_ENROLL_END) + { + DePopulateDot11fWscRegistrarInfo(pMac, &pBcn2->WscBeacon); + pMac->lim.wscIeInfo.wscEnrollmentState = eLIM_WSC_ENROLL_NOOP; + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + /* Can be efficiently updated whenever new IE added in Probe response in future */ + limUpdateProbeRspTemplateIeBitmapBeacon2(pMac,pBcn2,&psessionEntry->DefProbeRspIeBitmap[0], + &psessionEntry->probeRespFrame); + + /* update probe response WPS IE instead of beacon WPS IE + * */ + if(psessionEntry->wps_state != SAP_WPS_DISABLED) + { + if(psessionEntry->APWPSIEs.SirWPSProbeRspIE.FieldPresent) + { + PopulateDot11fProbeResWPSIEs(pMac, pWscProbeRes, psessionEntry); + } + else + { + pWscProbeRes->present = 0; + } + if(pWscProbeRes->present) + { + SetProbeRspIeBitmap(&psessionEntry->DefProbeRspIeBitmap[0],SIR_MAC_WPA_EID); + vos_mem_copy((void *)&psessionEntry->probeRespFrame.WscProbeRes, + (void *)pWscProbeRes, + sizeof(tDot11fIEWscProbeRes)); + } + } + + } + + nStatus = dot11fPackBeacon2( pMac, pBcn2, + psessionEntry->pSchBeaconFrameEnd, + SCH_MAX_BEACON_SIZE, &nBytes ); + if ( DOT11F_FAILED( nStatus ) ) + { + schLog( pMac, LOGE, FL("Failed to packed a tDot11fBeacon2 (0x%0" + "8x.)."), nStatus ); + vos_mem_free(pBcn1); + vos_mem_free(pBcn2); + vos_mem_free(pWscProbeRes); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + schLog( pMac, LOGE, FL("There were warnings while packing a tDo" + "t11fBeacon2 (0x%08x.)."), nStatus ); + } + + pExtraIe = psessionEntry->pSchBeaconFrameEnd + nBytes; + extraIeOffset = nBytes; + + //TODO: Append additional IE here. + schAppendAddnIE(pMac, psessionEntry, + psessionEntry->pSchBeaconFrameEnd + nBytes, + SCH_MAX_BEACON_SIZE, &nBytes); + + psessionEntry->schBeaconOffsetEnd = ( tANI_U16 )nBytes; + + extraIeLen = nBytes - extraIeOffset; + + //Get the p2p Ie Offset + status = schGetP2pIeOffset(pExtraIe, extraIeLen, &p2pIeOffset); + + if(eSIR_SUCCESS == status) + { + //Update the P2P Ie Offset + pMac->sch.schObject.p2pIeOffset = + psessionEntry->schBeaconOffsetBegin + TIM_IE_SIZE + + extraIeOffset + p2pIeOffset; + } + else + { + pMac->sch.schObject.p2pIeOffset = 0; + } + + schLog( pMac, LOG1, FL("Initialized beacon end, offset %d"), + psessionEntry->schBeaconOffsetEnd ); + + pMac->sch.schObject.fBeaconChanged = 1; + vos_mem_free(pBcn1); + vos_mem_free(pBcn2); + vos_mem_free(pWscProbeRes); + return eSIR_SUCCESS; +} + +tSirRetStatus limUpdateProbeRspTemplateIeBitmapBeacon1(tpAniSirGlobal pMac, + tDot11fBeacon1* beacon1, + tpPESession psessionEntry) +{ + tANI_U32* DefProbeRspIeBitmap; + tDot11fProbeResponse* prb_rsp; + + if (!psessionEntry) { + schLog(pMac, LOGE, FL("PESession is null!")); + return eSIR_FAILURE; + } + + DefProbeRspIeBitmap = &psessionEntry->DefProbeRspIeBitmap[0]; + prb_rsp = &psessionEntry->probeRespFrame; + + prb_rsp->BeaconInterval = beacon1->BeaconInterval; + vos_mem_copy((void *)&prb_rsp->Capabilities, (void *)&beacon1->Capabilities, + sizeof(beacon1->Capabilities)); + + /* SSID */ + if(beacon1->SSID.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_SSID_EID); + /* populating it, because probe response has to go with + * SSID even in hidden case + */ + PopulateDot11fSSID(pMac, &psessionEntry->ssId, &prb_rsp->SSID); + } + /* supported rates */ + if(beacon1->SuppRates.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_RATESET_EID); + vos_mem_copy((void *)&prb_rsp->SuppRates, (void *)&beacon1->SuppRates, + sizeof(beacon1->SuppRates)); + + } + /* DS Parameter set */ + if(beacon1->DSParams.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_DS_PARAM_SET_EID); + vos_mem_copy((void *)&prb_rsp->DSParams, (void *)&beacon1->DSParams, + sizeof(beacon1->DSParams)); + + } + + /* IBSS params will not be present in the Beacons transmitted by AP */ + + return eSIR_SUCCESS; +} + +void limUpdateProbeRspTemplateIeBitmapBeacon2(tpAniSirGlobal pMac, + tDot11fBeacon2* beacon2, + tANI_U32* DefProbeRspIeBitmap, + tDot11fProbeResponse* prb_rsp) +{ + /* IBSS parameter set - will not be present in probe response tx by AP */ + /* country */ + if(beacon2->Country.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_COUNTRY_EID); + vos_mem_copy((void *)&prb_rsp->Country, (void *)&beacon2->Country, + sizeof(beacon2->Country)); + + } + /* Power constraint */ + if(beacon2->PowerConstraints.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_PWR_CONSTRAINT_EID); + vos_mem_copy((void *)&prb_rsp->PowerConstraints, (void *)&beacon2->PowerConstraints, + sizeof(beacon2->PowerConstraints)); + + } + /* Channel Switch Announcement SIR_MAC_CHNL_SWITCH_ANN_EID */ + if(beacon2->ChanSwitchAnn.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_CHNL_SWITCH_ANN_EID); + vos_mem_copy((void *)&prb_rsp->ChanSwitchAnn, (void *)&beacon2->ChanSwitchAnn, + sizeof(beacon2->ChanSwitchAnn)); + + } + + /* EXT Channel Switch Announcement CHNL_EXTENDED_SWITCH_ANN_EID*/ + if (beacon2->ext_chan_switch_ann.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap, + SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID); + vos_mem_copy((void *)&prb_rsp->ext_chan_switch_ann, + (void *)&beacon2->ext_chan_switch_ann, + sizeof(beacon2->ext_chan_switch_ann)); + } + /* Supported operating class */ + if(beacon2->SuppOperatingClasses.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_OPERATING_CLASS_EID); + vos_mem_copy((void *)&prb_rsp->SuppOperatingClasses, + (void *)&beacon2->SuppOperatingClasses, + sizeof(beacon2->SuppOperatingClasses)); + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if(beacon2->QComVendorIE.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap, SIR_MAC_QCOM_VENDOR_EID); + vos_mem_copy((void *)&prb_rsp->QComVendorIE, + (void *)&beacon2->QComVendorIE, + sizeof(beacon2->QComVendorIE)); + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + /* ERP information */ + if(beacon2->ERPInfo.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_ERP_INFO_EID); + vos_mem_copy((void *)&prb_rsp->ERPInfo, (void *)&beacon2->ERPInfo, + sizeof(beacon2->ERPInfo)); + + } + /* Extended supported rates */ + if(beacon2->ExtSuppRates.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_EXTENDED_RATE_EID); + vos_mem_copy((void *)&prb_rsp->ExtSuppRates, (void *)&beacon2->ExtSuppRates, + sizeof(beacon2->ExtSuppRates)); + + } + + /* WPA */ + if(beacon2->WPA.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID); + vos_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA, + sizeof(beacon2->WPA)); + + } + + /* RSN */ + if(beacon2->RSNOpaque.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_RSN_EID); + vos_mem_copy((void *)&prb_rsp->RSNOpaque, (void *)&beacon2->RSNOpaque, + sizeof(beacon2->RSNOpaque)); + } + + /* EDCA Parameter set */ + if(beacon2->EDCAParamSet.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_EDCA_PARAM_SET_EID); + vos_mem_copy((void *)&prb_rsp->EDCAParamSet, (void *)&beacon2->EDCAParamSet, + sizeof(beacon2->EDCAParamSet)); + + } + /* Vendor specific - currently no vendor specific IEs added */ + /* Requested IEs - currently we are not processing this will be added later */ + //HT capability IE + if(beacon2->HTCaps.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_HT_CAPABILITIES_EID); + vos_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps, + sizeof(beacon2->HTCaps)); + } + // HT Info IE + if(beacon2->HTInfo.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_HT_INFO_EID); + vos_mem_copy((void *)&prb_rsp->HTInfo, (void *)&beacon2->HTInfo, + sizeof(beacon2->HTInfo)); + } + +#ifdef WLAN_FEATURE_11AC + if(beacon2->VHTCaps.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_CAPABILITIES_EID); + vos_mem_copy((void *)&prb_rsp->VHTCaps, (void *)&beacon2->VHTCaps, + sizeof(beacon2->VHTCaps)); + } + if(beacon2->VHTOperation.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_OPERATION_EID); + vos_mem_copy((void *)&prb_rsp->VHTOperation, (void *)&beacon2->VHTOperation, + sizeof(beacon2->VHTOperation)); + } + if(beacon2->VHTExtBssLoad.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_VHT_EXT_BSS_LOAD_EID); + vos_mem_copy((void *)&prb_rsp->VHTExtBssLoad, (void *)&beacon2->VHTExtBssLoad, + sizeof(beacon2->VHTExtBssLoad)); + } +#endif + + //WMM IE + if(beacon2->WMMParams.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID); + vos_mem_copy((void *)&prb_rsp->WMMParams, (void *)&beacon2->WMMParams, + sizeof(beacon2->WMMParams)); + } + //WMM capability - most of the case won't be present + if(beacon2->WMMCaps.present) + { + SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_WPA_EID); + vos_mem_copy((void *)&prb_rsp->WMMCaps, (void *)&beacon2->WMMCaps, + sizeof(beacon2->WMMCaps)); + } + + /* Extended Capability */ + if (beacon2->ExtCap.present) { + SetProbeRspIeBitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP); + vos_mem_copy((void *)&prb_rsp->ExtCap, (void *)&beacon2->ExtCap, + sizeof(beacon2->ExtCap)); + } + +} + +void SetProbeRspIeBitmap(tANI_U32* IeBitmap,tANI_U32 pos) +{ + tANI_U32 index,temp; + + index = pos >> 5; + if(index >= 8 ) + { + return; + } + temp = IeBitmap[index]; + + temp |= 1 << (pos & 0x1F); + + IeBitmap[index] = temp; +} + + + +// -------------------------------------------------------------------- +/** + * writeBeaconToMemory + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @param size Size of the beacon to write to memory + * @param length Length field of the beacon to write to memory + * @return None + */ + +void writeBeaconToMemory(tpAniSirGlobal pMac, tANI_U16 size, tANI_U16 length, tpPESession psessionEntry) +{ + tANI_U16 i; + tpAniBeaconStruct pBeacon; + + // copy end of beacon only if length > 0 + if (length > 0) + { + for (i=0; i < psessionEntry->schBeaconOffsetEnd; i++) + psessionEntry->pSchBeaconFrameBegin[size++] = psessionEntry->pSchBeaconFrameEnd[i]; + } + + // Update the beacon length + pBeacon = (tpAniBeaconStruct) psessionEntry->pSchBeaconFrameBegin; + // Do not include the beaconLength indicator itself + if (length == 0) + { + pBeacon->beaconLength = 0; + // Dont copy entire beacon, Copy length field alone + size = 4; + } + else + pBeacon->beaconLength = (tANI_U32) size - sizeof( tANI_U32 ); + + // write size bytes from pSchBeaconFrameBegin + PELOG2(schLog(pMac, LOG2, FL("Beacon size - %d bytes"), size);) + PELOG2(sirDumpBuf(pMac, SIR_SCH_MODULE_ID, LOG2, psessionEntry->pSchBeaconFrameBegin, size);) + + if (! pMac->sch.schObject.fBeaconChanged) + return; + + pMac->sch.gSchGenBeacon = 1; + if (pMac->sch.gSchGenBeacon) + { + pMac->sch.gSchBeaconsSent++; + + // + // Copy beacon data to SoftMAC shared memory... + // Do this by sending a message to HAL + // + + size = (size + 3) & (~3); + if( eSIR_SUCCESS != schSendBeaconReq( pMac, psessionEntry->pSchBeaconFrameBegin, + size, psessionEntry)) + PELOGE(schLog(pMac, LOGE, FL("schSendBeaconReq() returned an error (zsize %d)"), size);) + else + { + pMac->sch.gSchBeaconsWritten++; + } + } + pMac->sch.schObject.fBeaconChanged = 0; +} + +// -------------------------------------------------------------------- +/** + * @function: SchProcessPreBeaconInd + * + * @brief : Process the PreBeacon Indication from the Lim + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param : pMac - tpAniSirGlobal + * + * @return None + */ + +void +schProcessPreBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpBeaconGenParams pMsg = (tpBeaconGenParams)limMsg->bodyptr; + tANI_U32 beaconSize; + tpPESession psessionEntry; + tANI_U8 sessionId; + + if((psessionEntry = peFindSessionByBssid(pMac,pMsg->bssId, &sessionId))== NULL) + { + PELOGE(schLog(pMac, LOGE, FL("session lookup fails"));) + goto end; + } + + + beaconSize = psessionEntry->schBeaconOffsetBegin; + + // If SME is not in normal mode, no need to generate beacon + if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) + { + PELOGE(schLog(pMac, LOG1, FL("PreBeaconInd received in invalid state: %d"), psessionEntry->limSmeState);) + goto end; + } + + switch(GET_LIM_SYSTEM_ROLE(psessionEntry)) { + case eLIM_STA_IN_IBSS_ROLE: + case eLIM_BT_AMP_AP_ROLE: + case eLIM_BT_AMP_STA_ROLE: + /* Generate IBSS parameter set */ + if(psessionEntry->statypeForBss == STA_ENTRY_SELF) + writeBeaconToMemory(pMac, (tANI_U16) beaconSize, + (tANI_U16)beaconSize, psessionEntry); + else + PELOGE(schLog(pMac, LOGE, FL("can not send beacon for PEER session entry"));) + break; + + case eLIM_AP_ROLE: { + tANI_U8 *ptr = &psessionEntry->pSchBeaconFrameBegin[psessionEntry->schBeaconOffsetBegin]; + tANI_U16 timLength = 0; + + if (psessionEntry->statypeForBss == STA_ENTRY_SELF) { + pmmGenerateTIM(pMac, &ptr, &timLength, psessionEntry->dtimPeriod); + beaconSize += 2 + timLength; + writeBeaconToMemory(pMac, (tANI_U16) beaconSize, + (tANI_U16)beaconSize, psessionEntry); + } else + PELOGE(schLog(pMac, LOGE, FL("can not send beacon for PEER session entry"));) + } + break; + + default: + PELOGE(schLog(pMac, LOGE, + FL("Error-PE has Receive PreBeconGenIndication when System is in %d role"), + GET_LIM_SYSTEM_ROLE(psessionEntry));) + } + +end: + vos_mem_free(pMsg); + +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconProcess.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconProcess.c new file mode 100644 index 000000000000..218fe3cfc5f4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconProcess.c @@ -0,0 +1,925 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file schBeaconProcess.cc contains beacon processing related + * functions + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "palTypes.h" +#include "wniCfgSta.h" + +#include "cfgApi.h" +#include "pmmApi.h" +#include "limApi.h" +#include "utilsApi.h" +#include "schDebug.h" +#include "schApi.h" + +#include "wma.h" + +#include "limUtils.h" +#include "limSendMessages.h" +#include "limStaHashApi.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "vos_diag_core_log.h" +#endif //FEATURE_WLAN_DIAG_SUPPORT + +/** + * Number of bytes of variation in beacon length from the last beacon + * to trigger reprogramming of rx delay register + */ +#define SCH_BEACON_LEN_DELTA 3 + +// calculate 2^cw - 1 +#define CW_GET(cw) (((cw) == 0) ? 1 : ((1 << (cw)) - 1)) + +static void +ap_beacon_process( + tpAniSirGlobal pMac, + tANI_U8* pRxPacketInfo, + tpSchBeaconStruct pBcnStruct, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pMh = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + tANI_U32 phyMode; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + //Get RF band from psessionEntry + rfBand = psessionEntry->limRFBand; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + if(SIR_BAND_5_GHZ == rfBand) + { + if (psessionEntry->htCapability) + { + if (pBcnStruct->channelNumber == psessionEntry->currentOperChannel) + { + //11a (non HT) AP overlaps or + //HT AP with HT op mode as mixed overlaps. + //HT AP with HT op mode as overlap legacy overlaps. + if ((!pBcnStruct->HTInfo.present) || + (eSIR_HT_OP_MODE_MIXED == pBcnStruct->HTInfo.opMode) || + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == pBcnStruct->HTInfo.opMode)) + { + limUpdateOverlapStaParam(pMac, pMh->bssId, &(pMac->lim.gLimOverlap11aParams)); + + if (pMac->lim.gLimOverlap11aParams.numSta && + !pMac->lim.gLimOverlap11aParams.protectionEnabled) + { + limEnable11aProtection(pMac, true, true, pBeaconParams,psessionEntry); + } + } + //HT AP with HT20 op mode overlaps. + else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pBcnStruct->HTInfo.opMode) + { + limUpdateOverlapStaParam(pMac, pMh->bssId, &(pMac->lim.gLimOverlapHt20Params)); + + if (pMac->lim.gLimOverlapHt20Params.numSta && + !pMac->lim.gLimOverlapHt20Params.protectionEnabled) + { + limEnableHT20Protection(pMac, true, true, pBeaconParams,psessionEntry); + } + } + } + } + } + else if(SIR_BAND_2_4_GHZ == rfBand) + { + //We are 11G AP. + if ((phyMode == WNI_CFG_PHY_MODE_11G) && + (false == psessionEntry->htCapability)) + { + if (pBcnStruct->channelNumber == psessionEntry->currentOperChannel) + { + if (((!(pBcnStruct->erpPresent)) && + !(pBcnStruct->HTInfo.present))|| + //if erp not present then 11B AP overlapping + (!pMac->roam.configParam.ignorePeerErpInfo && + pBcnStruct->erpPresent && + (pBcnStruct->erpIEInfo.useProtection || + pBcnStruct->erpIEInfo.nonErpPresent))) + { +#ifdef FEATURE_WLAN_ESE + if( psessionEntry->isESEconnection ) + { + VOS_TRACE (VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "%s: [INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d", __func__, + pBcnStruct->erpPresent, + pBcnStruct->erpIEInfo.useProtection, + pBcnStruct->erpIEInfo.nonErpPresent); + } +#endif + limEnableOverlap11gProtection(pMac, pBeaconParams, pMh,psessionEntry); + } + + } + } + // handling the case when HT AP has overlapping legacy BSS. + else if(psessionEntry->htCapability) + { + if (pBcnStruct->channelNumber == psessionEntry->currentOperChannel) + { + if (((!(pBcnStruct->erpPresent)) && + !(pBcnStruct->HTInfo.present))|| + //if erp not present then 11B AP overlapping + (!pMac->roam.configParam.ignorePeerErpInfo && + pBcnStruct->erpPresent && + (pBcnStruct->erpIEInfo.useProtection || + pBcnStruct->erpIEInfo.nonErpPresent))) + { +#ifdef FEATURE_WLAN_ESE + if( psessionEntry->isESEconnection ) + { + VOS_TRACE (VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "%s: [INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d", __func__, + pBcnStruct->erpPresent, + pBcnStruct->erpIEInfo.useProtection, + pBcnStruct->erpIEInfo.nonErpPresent); + } +#endif + limEnableOverlap11gProtection(pMac, pBeaconParams, pMh,psessionEntry); + } + + //11g device overlaps + if (pBcnStruct->erpPresent && + !(pBcnStruct->erpIEInfo.useProtection || + pBcnStruct->erpIEInfo.nonErpPresent) && !(pBcnStruct->HTInfo.present)) + { + limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOverlap11gParams)); + + if (psessionEntry->gLimOverlap11gParams.numSta && + !psessionEntry->gLimOverlap11gParams.protectionEnabled) + { + limEnableHtProtectionFrom11g(pMac, true, true, pBeaconParams,psessionEntry); + } + } + + //ht device overlaps. + //here we will check for HT related devices only which might need protection. + //check for 11b and 11g is already done in the previous blocks. + //so we will not check for HT operating mode as MIXED. + if (pBcnStruct->HTInfo.present) + { + //if we are not already in mixed mode or legacy mode as HT operating mode + //and received beacon has HT operating mode as legacy + //then we need to enable protection from 11g station. + //we don't need protection from 11b because if that's needed then our operating + //mode would have already been set to legacy in the previous blocks. + if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pBcnStruct->HTInfo.opMode) + { + if((eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_OVERLAP_LEGACY != pMac->lim.gHTOperMode)) + { + limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOverlap11gParams)); + if (psessionEntry->gLimOverlap11gParams.numSta && + !psessionEntry->gLimOverlap11gParams.protectionEnabled) + { + limEnableHtProtectionFrom11g(pMac, true, true, pBeaconParams,psessionEntry); + } + } + } + else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pBcnStruct->HTInfo.opMode) + { + limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOverlapHt20Params)); + if (psessionEntry->gLimOverlapHt20Params.numSta && + !psessionEntry->gLimOverlapHt20Params.protectionEnabled) + { + limEnableHT20Protection(pMac, true, true, pBeaconParams,psessionEntry); + } + } + } + + } + } + } + pMac->sch.gSchBcnIgnored++; +} +// -------------------------------------------------------------------- + + + + +/** + * __schBeaconProcessNoSession + * + * FUNCTION: + * Process the received beacon frame when + * -- Station is not scanning + * -- No corresponding session is found + * + * LOGIC: + * Following scenarios exist when Session Does not exist: + * * IBSS Beacons, when IBSS session already exists with same SSID, + * but from STA which has not yet joined and has a different BSSID. + * - invoke limHandleIBSScoalescing with the session context of existing IBSS session. + * + * * IBSS Beacons when IBSS session does not exist, only Infra or BT-AMP session exists, + * then save the beacon in the scan results and throw it away. + * + * * Infra Beacons + * - beacons received when no session active + * should not come here, it should be handled as part of scanning, + * else they should not be getting received, should update scan results and drop it if that happens. + * - beacons received when IBSS session active: + * update scan results and drop it. + * - beacons received when Infra session(STA) is active: + * update scan results and drop it + * - beacons received when BT-STA session is active: + * update scan results and drop it. + * - beacons received when Infra/BT-STA or Infra/IBSS is active. + * update scan results and drop it. + * + + */ +static void __schBeaconProcessNoSession(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon,tANI_U8* pRxPacketInfo) +{ + tpPESession psessionEntry = NULL; + + if( (psessionEntry = limIsIBSSSessionActive(pMac)) != NULL) + { + limHandleIBSScoalescing(pMac, pBeacon, pRxPacketInfo, psessionEntry); + } + + /* + * If station(STA/BT-STA/BT-AP/IBSS) mode, Always save the beacon in the + * scan results, if at-least one session is active schBeaconProcessNoSession + * will be called only when there is at-least one session active, + * so not checking it again here. + */ + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + return; +} + + + +/* + * __schBeaconProcessForSession + * + * FUNCTION: + * Process the received beacon frame when + * -- Station is not scanning + * -- Corresponding session is found + * + * LOGIC: + * Following scenarios exist when Session exists + * * IBSS STA receiving beacons from IBSS Peers, who are part of IBSS. + * - call limHandleIBSScoalescing with that session context. + * * Infra STA receiving beacons from AP to which it is connected + * - call schBeaconProcessFromAP with that session's context. + * * BTAMP STA receiving beacons from BTAMP AP + * - call schBeaconProcessFromAP with that session's context. + * * BTAMP AP receiving beacons from BTAMP STA + * (here need to make sure BTAP creates session entry for BT STA) + * - just update the beacon count for heart beat purposes for now, + * for now, don't process the beacon. + * * Infra/IBSS both active and receives IBSS beacon: + * - call limHandleIBSScoalescing with that session context. + * * Infra/IBSS both active and receives Infra beacon: + * - call schBeaconProcessFromAP with that session's context. + * any updates to EDCA parameters will be effective for IBSS as well, + * even though no WMM for IBSS ?? Need to figure out how to handle this scenario. + * * Infra/BTSTA both active and receive Infra beacon. + * - change in EDCA parameters on Infra affect the BTSTA link. + * Update the same parameters on BT link + * * Infra/BTSTA both active and receive BT-AP beacon. + * -update beacon cnt for heartbeat + * * Infra/BTAP both active and receive Infra beacon. + * - BT-AP starts advertising BE parameters from Infra AP, if they get changed. + * + * * Infra/BTAP both active and receive BTSTA beacon. + * - update beacon cnt for heartbeat + */ + +static void __schBeaconProcessForSession( tpAniSirGlobal pMac, + tpSchBeaconStruct pBeacon, + tANI_U8* pRxPacketInfo, + tpPESession psessionEntry) +{ + tANI_U32 bi; + tANI_U8 bssIdx = 0; + //tpSirMacMgmtHdr pMh = SIR_MAC_BD_TO_MPDUHEADER(pRxPacketInfo); + //tANI_U8 bssid[sizeof(tSirMacAddr)]; + tUpdateBeaconParams beaconParams; + tANI_U8 sendProbeReq = FALSE; + tpDphHashNode pStaDs = NULL; +#ifdef WLAN_FEATURE_11AC + tpSirMacMgmtHdr pMh = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + tANI_U16 aid; + tANI_U8 operMode; + tANI_U8 chWidth = 0; + tANI_U8 skip_opmode_update = false; +#endif +#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI + tPowerdBm regMax = 0,maxTxPower = 0; +#endif + tANI_U8 cbMode; + + vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); + beaconParams.paramChangeBitmap = 0; + + if (RF_CHAN_14 >= psessionEntry->currentOperChannel) + cbMode = pMac->roam.configParam.channelBondingMode24GHz; + else + cbMode = pMac->roam.configParam.channelBondingMode5GHz; + + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + limHandleIBSScoalescing(pMac, pBeacon, pRxPacketInfo, psessionEntry); + } else if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + /* + * This handles two cases: + * -- Infra STA receiving beacons from AP + * -- BTAMP_STA receiving beacons from BTAMP_AP + */ + //Always save the beacon into LIM's cached scan results + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + + /** + * This is the Beacon received from the AP we're currently associated with. Check + * if there are any changes in AP's capabilities + */ + if((tANI_U8) pBeacon->channelNumber != psessionEntry->currentOperChannel) + { + PELOGE(schLog(pMac, LOGE, FL("Channel Change from %d --> %d - " + "Ignoring beacon!"), + psessionEntry->currentOperChannel, pBeacon->channelNumber);) + goto fail; + } + + limDetectChangeInApCapabilities(pMac, pBeacon, psessionEntry); + if(limGetStaHashBssidx(pMac, DPH_STA_HASH_INDEX_PEER, &bssIdx, psessionEntry) != eSIR_SUCCESS) + goto fail; + beaconParams.bssIdx = bssIdx; + vos_mem_copy(( tANI_U8* )&psessionEntry->lastBeaconTimeStamp, + ( tANI_U8* )pBeacon->timeStamp, sizeof(tANI_U64)); + psessionEntry->lastBeaconDtimCount = pBeacon->tim.dtimCount; + psessionEntry->lastBeaconDtimPeriod= pBeacon->tim.dtimPeriod; + psessionEntry->currentBssBeaconCnt++; + + + + MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_TSF, psessionEntry->peSessionId, pBeacon->timeStamp[0]);) + MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_TSF, psessionEntry->peSessionId, pBeacon->timeStamp[1]);) + + /* Read beacon interval session Entry */ + bi = psessionEntry->beaconParams.beaconInterval; + if (bi != pBeacon->beaconInterval) + { + PELOG1(schLog(pMac, LOG1, FL("Beacon interval changed from %d to %d"), + pBeacon->beaconInterval, bi);) + + bi = pBeacon->beaconInterval; + psessionEntry->beaconParams.beaconInterval = (tANI_U16) bi; + beaconParams.paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED; + beaconParams.beaconInterval = (tANI_U16)bi; + } + + if (pBeacon->cfPresent) + { + cfgSetInt(pMac, WNI_CFG_CFP_PERIOD, pBeacon->cfParamSet.cfpPeriod); + limSendCFParams(pMac, bssIdx, pBeacon->cfParamSet.cfpCount, pBeacon->cfParamSet.cfpPeriod); + } + + if (pBeacon->timPresent) + { + cfgSetInt(pMac, WNI_CFG_DTIM_PERIOD, pBeacon->tim.dtimPeriod); + //No need to send DTIM Period and Count to HAL/SMAC + //SMAC already parses TIM bit. + } + + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + + limDecideStaProtection(pMac, pBeacon, &beaconParams, psessionEntry); + if (pBeacon->erpPresent) + { + if (pBeacon->erpIEInfo.barkerPreambleMode) + limEnableShortPreamble(pMac, false, &beaconParams, psessionEntry); + else + limEnableShortPreamble(pMac, true, &beaconParams, psessionEntry); + } + limUpdateShortSlot(pMac, pBeacon, &beaconParams,psessionEntry); + + pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); + if ((pBeacon->wmeEdcaPresent && (psessionEntry->limWmeEnabled)) || + (pBeacon->edcaPresent && (psessionEntry->limQosEnabled))) + { + if(pBeacon->edcaParams.qosInfo.count != psessionEntry->gLimEdcaParamSetCount) + { + if (schBeaconEdcaProcess(pMac, &pBeacon->edcaParams, psessionEntry) != eSIR_SUCCESS) + PELOGE(schLog(pMac, LOGE, FL("EDCA parameter processing error"));) + else if(pStaDs != NULL) + { + // If needed, downgrade the EDCA parameters + limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); + + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); + } + else + PELOGE(schLog(pMac, LOGE, FL("Self Entry missing in Hash Table"));) + } + } + else if( (pBeacon->qosCapabilityPresent && psessionEntry->limQosEnabled) && + (pBeacon->qosCapability.qosInfo.count != psessionEntry->gLimEdcaParamSetCount)) + sendProbeReq = TRUE; + } + + if ( psessionEntry->htCapability && pBeacon->HTInfo.present ) + { + limUpdateStaRunTimeHTSwitchChnlParams( pMac, &pBeacon->HTInfo, bssIdx,psessionEntry); + } + + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || + LIM_IS_IBSS_ROLE(psessionEntry)) { + /* Channel Switch information element updated */ + if (pBeacon->channelSwitchPresent) { +#ifdef FEATURE_WLAN_TDLS + /* + * on receiving channel switch announcement from AP, delete all + * TDLS peers before leaving BSS and proceed for channel switch + */ + if (LIM_IS_STA_ROLE(psessionEntry)) + limDeleteTDLSPeers(pMac, psessionEntry); +#endif + limUpdateChannelSwitch(pMac, pBeacon, psessionEntry); + } else if (psessionEntry->gLimSpecMgmt.dot11hChanSwState == + eLIM_11H_CHANSW_RUNNING) { + limCancelDot11hChannelSwitch(pMac, psessionEntry); + } + } + +#ifdef WLAN_FEATURE_11AC + if (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || + LIM_IS_IBSS_ROLE(psessionEntry)) { + // check for VHT capability + pStaDs = dphLookupHashEntry(pMac, pMh->sa, &aid, + &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs && (HAL_STA_INVALID_IDX != pStaDs->staIndex ) && + (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != cbMode)) + { + if (psessionEntry->vhtCapability && pBeacon->OperatingMode.present ) + { + operMode = pStaDs->vhtSupportedChannelWidthSet ? + eHT_CHANNEL_WIDTH_80MHZ : + pStaDs->htSupportedChannelWidthSet ? + eHT_CHANNEL_WIDTH_40MHZ: eHT_CHANNEL_WIDTH_20MHZ; + if ((operMode == eHT_CHANNEL_WIDTH_80MHZ) && + (pBeacon->OperatingMode.chanWidth > + eHT_CHANNEL_WIDTH_80MHZ)) + skip_opmode_update = true; + + if (!skip_opmode_update && + (operMode != pBeacon->OperatingMode.chanWidth)) + { + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + PELOG1(schLog(pMac, LOG1, + FL(" received OpMode Chanwidth %d, staIdx = %d"), + pBeacon->OperatingMode.chanWidth, + pStaDs->staIndex);) + PELOG1(schLog(pMac, LOG1, FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), + pMh->sa[0], + pMh->sa[1], + pMh->sa[2], + pMh->sa[3], + pMh->sa[4], + pMh->sa[5]);) + + if ((pBeacon->OperatingMode.chanWidth > + eHT_CHANNEL_WIDTH_80MHZ) && + (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + chWidth = eHT_CHANNEL_WIDTH_160MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (pBeacon->OperatingMode.chanWidth >= + eHT_CHANNEL_WIDTH_80MHZ) { + PELOG1(schLog(pMac, LOG1, + FL("Updating the CH Width to 80MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + chWidth = eHT_CHANNEL_WIDTH_80MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (pBeacon->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_40MHZ) { + PELOG1(schLog(pMac, LOG1, + FL("Updating the CH Width to 40MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_40MHZ; + } else if (pBeacon->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_20MHZ) { + PELOG1(schLog(pMac, LOG1, + FL("Updating the CH Width to 20MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + chWidth = eHT_CHANNEL_WIDTH_20MHZ; + } + limCheckVHTOpModeChange(pMac, psessionEntry, + chWidth, + pStaDs->staIndex, pMh->sa); + } + /* Update Nss setting */ + if (pStaDs->vhtSupportedRxNss != + (pBeacon->OperatingMode.rxNSS + 1)) { + pStaDs->vhtSupportedRxNss = + (pBeacon->OperatingMode.rxNSS + 1); + limSetNssChange( pMac, psessionEntry, + pStaDs->vhtSupportedRxNss, + pStaDs->staIndex, pMh->sa); + } + } + else if (psessionEntry->vhtCapability && pBeacon->VHTOperation.present) + { + operMode = pStaDs->vhtSupportedChannelWidthSet; + if ((operMode == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) && + (operMode < pBeacon->VHTOperation.chanWidth)) + skip_opmode_update = true; + + if (!skip_opmode_update && + (operMode != pBeacon->VHTOperation.chanWidth)) + { + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + PELOG1(schLog(pMac, LOG1, + FL(" received VHTOP CHWidth %d staIdx = %d"), + pBeacon->VHTOperation.chanWidth, + pStaDs->staIndex);) + PELOG1(schLog(pMac, LOG1, FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), + pMh->sa[0], + pMh->sa[1], + pMh->sa[2], + pMh->sa[3], + pMh->sa[4], + pMh->sa[5]);) + + if ((pBeacon->VHTOperation.chanWidth > + eHT_CHANNEL_WIDTH_80MHZ) && + (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_160MHZ; + } else if (pBeacon->VHTOperation.chanWidth >= + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + PELOG1(schLog(pMac, LOG1, + FL("Updating the CH Width to 80MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_80MHZ; + } else if (pBeacon->VHTOperation.chanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) { + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + if (pBeacon->HTCaps.supportedChannelWidthSet) + { + PELOG1(schLog(pMac, LOG1, + FL("Updating the CH Width to 40MHz"));) + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_40MHZ; + } + else + { + PELOG1(schLog(pMac, LOG1, + FL("Updating the CH Width to 20MHz"));) + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + chWidth = eHT_CHANNEL_WIDTH_20MHZ; + } + } + limCheckVHTOpModeChange(pMac, psessionEntry, + chWidth, pStaDs->staIndex, pMh->sa); + + } + } + } + } +#endif + +#if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI) + /* Obtain the Max Tx power for the current regulatory */ + regMax = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); +#endif + +#if defined WLAN_FEATURE_VOWIFI + { + tPowerdBm localRRMConstraint = 0; + if ( pMac->rrm.rrmPEContext.rrmEnable && pBeacon->powerConstraintPresent ) + { + localRRMConstraint = pBeacon->localPowerConstraint.localPowerConstraints; + } + else + { + localRRMConstraint = 0; + } + maxTxPower = limGetMaxTxPower(regMax, regMax - localRRMConstraint, + pMac->roam.configParam.nTxPowerCap); + } +#elif defined FEATURE_WLAN_ESE + maxTxPower = regMax; +#endif + +#if defined FEATURE_WLAN_ESE + if( psessionEntry->isESEconnection ) + { + tPowerdBm localESEConstraint = 0; + if (pBeacon->eseTxPwr.present) + { + localESEConstraint = pBeacon->eseTxPwr.power_limit; + maxTxPower = limGetMaxTxPower(maxTxPower, localESEConstraint, pMac->roam.configParam.nTxPowerCap); + } + schLog( pMac, LOG1, "RegMax = %d, localEseCons = %d, MaxTx = %d", regMax, localESEConstraint, maxTxPower ); + } +#endif + +#if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI) + { + //If maxTxPower is increased or decreased + if( maxTxPower != psessionEntry->maxTxPower ) + { + schLog( pMac, LOG1, "Local power constraint change..updating new maxTx power %d to HAL",maxTxPower); + if( limSendSetMaxTxPowerReq ( pMac, maxTxPower, psessionEntry ) == eSIR_SUCCESS ) + psessionEntry->maxTxPower = maxTxPower; + } + } +#endif + + // Indicate to LIM that Beacon is received + + if (pBeacon->HTInfo.present) + limReceivedHBHandler(pMac, (tANI_U8)pBeacon->HTInfo.primaryChannel, psessionEntry); + else + limReceivedHBHandler(pMac, (tANI_U8)pBeacon->channelNumber, psessionEntry); + + // I don't know if any additional IE is required here. Currently, not include addIE. + if(sendProbeReq) + limSendProbeReqMgmtFrame(pMac, &psessionEntry->ssId, + psessionEntry->bssId, psessionEntry->currentOperChannel,psessionEntry->selfMacAddr, + psessionEntry->dot11mode, 0, NULL); + + if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) + { + PELOGW(schLog(pMac, LOGW, FL("Beacon for session[%d] got changed. "), psessionEntry->peSessionId);) + PELOGW(schLog(pMac, LOGW, FL("sending beacon param change bitmap: 0x%x "), beaconParams.paramChangeBitmap);) + limSendBeaconParams(pMac, &beaconParams, psessionEntry); + } + +fail: + return; + +} + + + +/** + * schBeaconProcess + * + * FUNCTION: + * Process the received beacon frame + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pRxPacketInfo pointer to buffer descriptor + * @return None + */ + +void schBeaconProcess(tpAniSirGlobal pMac, tANI_U8* pRxPacketInfo, tpPESession psessionEntry) +{ + static tSchBeaconStruct beaconStruct; + tUpdateBeaconParams beaconParams; + tpPESession pAPSession = NULL; +#ifdef WLAN_FEATURE_MBSSID + tANI_U8 i; +#endif + + vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); + beaconParams.paramChangeBitmap = 0; + + pMac->sch.gSchBcnRcvCnt++; + + // Convert the beacon frame into a structure + if (sirConvertBeaconFrame2Struct(pMac, (tANI_U8 *) pRxPacketInfo, &beaconStruct)!= eSIR_SUCCESS) + { + PELOGE(schLog(pMac, LOGE, FL("beacon parsing failed"));) + pMac->sch.gSchBcnParseErrorCnt++; + return; + } + + if (beaconStruct.ssidPresent) + { + beaconStruct.ssId.ssId[beaconStruct.ssId.length] = 0; + } + + /* + * First process the beacon in the context of any existing AP or BTAP session. + * This takes cares of following two scenarios: + * - psessionEntry = NULL: + * e.g. beacon received from a neighboring BSS, you want to apply the protection settings to BTAP/InfraAP beacons + * - psessionEntry is non NULL: + * e.g. beacon received is from the INFRA AP to which you are connected on another concurrent link. + * In this case also, we want to apply the protection settings(as advertised by Infra AP) to BTAP beacons + * + * + */ + +#ifdef WLAN_FEATURE_MBSSID + + for (i =0; i < pMac->lim.maxBssId; i++) + { + if (((pAPSession = peFindSessionBySessionId(pMac, i)) != NULL) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))) +#endif + ) + { + if (!LIM_IS_AP_ROLE(pAPSession)) { + continue; + } + + beaconParams.bssIdx = pAPSession->bssIdx; + if (pAPSession->gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + ap_beacon_process(pMac, pRxPacketInfo, &beaconStruct, + &beaconParams, pAPSession); + + if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) + { + //Update the beacons and apply the new settings to HAL + schSetFixedBeaconFields(pMac, pAPSession); + PELOG1(schLog(pMac, LOG1, + FL("Beacon for PE session[%d] got changed."), + pAPSession->peSessionId);) + PELOG1(schLog(pMac, LOG1, + FL("sending beacon param change bitmap: 0x%x"), + beaconParams.paramChangeBitmap);) + limSendBeaconParams(pMac, &beaconParams, pAPSession); + } + } + } + +#else + + if (((pAPSession = limIsApSessionActive(pMac)) != NULL) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))) +#endif + ) + { + beaconParams.bssIdx = pAPSession->bssIdx; + if (pAPSession->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + ap_beacon_process(pMac, pRxPacketInfo, &beaconStruct, &beaconParams, pAPSession); + + if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) + { + //Update the beacons and apply the new settings to HAL + schSetFixedBeaconFields(pMac, pAPSession); + PELOG1(schLog(pMac, LOG1, FL("Beacon for PE session[%d] got changed. "), pAPSession->peSessionId);) + PELOG1(schLog(pMac, LOG1, FL("sending beacon param change bitmap: 0x%x "), beaconParams.paramChangeBitmap);) + limSendBeaconParams(pMac, &beaconParams, pAPSession); + } + } + +#endif + + /* + * Now process the beacon in the context of the BSS which is transmitting the beacons, if one is found + */ + if(psessionEntry == NULL) + { + __schBeaconProcessNoSession(pMac, &beaconStruct, pRxPacketInfo ); + } + else + { + __schBeaconProcessForSession(pMac, &beaconStruct, pRxPacketInfo, psessionEntry ); + } + +} + + + + + +// -------------------------------------------------------------------- +/** + * schBeaconEdcaProcess + * + * FUNCTION: + * Process the EDCA parameter set in the received beacon frame + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param edca reference to edca parameters in beacon struct + * @return success + */ + +tSirRetStatus schBeaconEdcaProcess(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry) +{ + tANI_U8 i; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + vos_log_qos_edca_pkt_type *log_ptr = NULL; +#endif //FEATURE_WLAN_DIAG_SUPPORT + + PELOG1(schLog(pMac, LOG1, FL("Updating parameter set count: Old %d ---> new %d"), + psessionEntry->gLimEdcaParamSetCount, edca->qosInfo.count);) + + psessionEntry->gLimEdcaParamSetCount = edca->qosInfo.count; + psessionEntry->gLimEdcaParams[EDCA_AC_BE] = edca->acbe; + psessionEntry->gLimEdcaParams[EDCA_AC_BK] = edca->acbk; + psessionEntry->gLimEdcaParams[EDCA_AC_VI] = edca->acvi; + psessionEntry->gLimEdcaParams[EDCA_AC_VO] = edca->acvo; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_qos_edca_pkt_type, LOG_WLAN_QOS_EDCA_C); + if(log_ptr) + { + log_ptr->aci_be = psessionEntry->gLimEdcaParams[EDCA_AC_BE].aci.aci; + log_ptr->cw_be = psessionEntry->gLimEdcaParams[EDCA_AC_BE].cw.max << 4 | + psessionEntry->gLimEdcaParams[EDCA_AC_BE].cw.min; + log_ptr->txoplimit_be = psessionEntry->gLimEdcaParams[EDCA_AC_BE].txoplimit; + log_ptr->aci_bk = psessionEntry->gLimEdcaParams[EDCA_AC_BK].aci.aci; + log_ptr->cw_bk = psessionEntry->gLimEdcaParams[EDCA_AC_BK].cw.max << 4 | + psessionEntry->gLimEdcaParams[EDCA_AC_BK].cw.min; + log_ptr->txoplimit_bk = psessionEntry->gLimEdcaParams[EDCA_AC_BK].txoplimit; + log_ptr->aci_vi = psessionEntry->gLimEdcaParams[EDCA_AC_VI].aci.aci; + log_ptr->cw_vi = psessionEntry->gLimEdcaParams[EDCA_AC_VI].cw.max << 4 | + psessionEntry->gLimEdcaParams[EDCA_AC_VI].cw.min; + log_ptr->txoplimit_vi = psessionEntry->gLimEdcaParams[EDCA_AC_VI].txoplimit; + log_ptr->aci_vo = psessionEntry->gLimEdcaParams[EDCA_AC_VO].aci.aci; + log_ptr->cw_vo = psessionEntry->gLimEdcaParams[EDCA_AC_VO].cw.max << 4 | + psessionEntry->gLimEdcaParams[EDCA_AC_VO].cw.min; + log_ptr->txoplimit_vo = psessionEntry->gLimEdcaParams[EDCA_AC_VO].txoplimit; + } + WLAN_VOS_DIAG_LOG_REPORT(log_ptr); +#endif //FEATURE_WLAN_DIAG_SUPPORT + PELOG1(schLog(pMac, LOGE, FL("Updating Local EDCA Params(gLimEdcaParams) to: "));) + for(i=0; igLimEdcaParams[i].aci.aifsn, + psessionEntry->gLimEdcaParams[i].aci.acm, + psessionEntry->gLimEdcaParams[i].cw.min, + psessionEntry->gLimEdcaParams[i].cw.max, + psessionEntry->gLimEdcaParams[i].txoplimit);) + } + + return eSIR_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.c new file mode 100644 index 000000000000..61178feef0d8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file schDebug.cc contains some debug functions. + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + + +#include "vos_trace.h" +#include "schDebug.h" +#define LOG_SIZE 256 + +void schLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...) +{ + + VOS_TRACE_LEVEL vosDebugLevel; + char logBuffer[LOG_SIZE]; + va_list marker; + + /* getting proper Debug level*/ + vosDebugLevel = getVosDebugLevel(loglevel); + + /* extracting arguments from pstring */ + va_start( marker, pString ); + vsnprintf(logBuffer, LOG_SIZE, pString, marker); + VOS_TRACE(VOS_MODULE_ID_PE, vosDebugLevel, "%s", logBuffer); + va_end( marker ); + } + + + +// -------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.h new file mode 100644 index 000000000000..4bf6ac6b61ad --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schDebug.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file schDebug.h contains some debug macros. + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __SCH_DEBUG_H__ +#define __SCH_DEBUG_H__ + +#include "utilsApi.h" +#include "sirDebug.h" + +#if !defined(__printf) +#define __printf(a,b) +#endif + +void __printf(3,4) schLog(tpAniSirGlobal pMac, tANI_U32 loglevel, + const char *pString, ...); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schMessage.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schMessage.c new file mode 100644 index 000000000000..734b28c9c8a1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schMessage.c @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file schMessage.cc contains the message handler + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "palTypes.h" +#include "sirCommon.h" + +#include "wniCfgSta.h" +#include "aniGlobal.h" +#include "cfgApi.h" +#include "limApi.h" +#include "pmmApi.h" +#include "limSendMessages.h" + + +#include "schApi.h" +#include "schDebug.h" + +/// Minimum beacon interval allowed (in Kus) +#define SCH_BEACON_INTERVAL_MIN 10 + +/// Maximum beacon interval allowed (in Kus) +#define SCH_BEACON_INTERVAL_MAX 10000 + +/// convert the CW values into a tANI_U16 +#define GET_CW(pCw) ((tANI_U16) ((*(pCw) << 8) + *((pCw) + 1))) + +// local functions +static tSirRetStatus getWmmLocalParams(tpAniSirGlobal pMac, tANI_U32 params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]); +static void setSchEdcaParams(tpAniSirGlobal pMac, tANI_U32 params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], tpPESession psessionEntry); + +// -------------------------------------------------------------------- +/** + * schSetBeaconInterval + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void schSetBeaconInterval(tpAniSirGlobal pMac,tpPESession psessionEntry) +{ + tANI_U32 bi; + + bi = psessionEntry->beaconParams.beaconInterval; + + if (bi < SCH_BEACON_INTERVAL_MIN || bi > SCH_BEACON_INTERVAL_MAX) + { + schLog(pMac, LOGE, FL("Invalid beacon interval %d (should be [%d,%d]"), + bi, SCH_BEACON_INTERVAL_MIN, SCH_BEACON_INTERVAL_MAX); + return; + } + + pMac->sch.schObject.gSchBeaconInterval = (tANI_U16)bi; +} + + +// -------------------------------------------------------------------- +/** + * schProcessMessage + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void schProcessMessage(tpAniSirGlobal pMac,tpSirMsgQ pSchMsg) +{ + tANI_U32 val; + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + PELOG3(schLog(pMac, LOG3, FL("Received message (%x) "), pSchMsg->type);) + + switch (pSchMsg->type) + { + + case SIR_SCH_CHANNEL_SWITCH_REQUEST: + schLog(pMac, LOGE, + FL("Channel switch request not handled")); + break; + + case SIR_SCH_START_SCAN_REQ: + pMac->sch.gSchScanReqRcvd = true; + if (pMac->sch.gSchHcfEnabled) + { + // In HCF mode, wait for TFP to stop before sending a response + if (pMac->sch.schObject.gSchCFBInitiated || + pMac->sch.schObject.gSchCFPInitiated) + { + PELOG1(schLog(pMac, LOG1, + FL("Waiting for TFP to halt before sending " + "start scan response"));) + } + else + schSendStartScanRsp(pMac); + } + else + { + // In eDCF mode, send the response right away + schSendStartScanRsp(pMac); + } + break; + + case SIR_SCH_END_SCAN_NTF: + PELOG3(schLog(pMac, LOG3, + FL("Received STOP_SCAN_NTF from LIM"));) + pMac->sch.gSchScanReqRcvd = false; + break; + + case SIR_CFG_PARAM_UPDATE_IND: + + if (wlan_cfgGetInt(pMac, (tANI_U16) pSchMsg->bodyval, &val) != eSIR_SUCCESS) + schLog(pMac, LOGP, FL("failed to cfg get id %d"), pSchMsg->bodyval); + + switch (pSchMsg->bodyval) + { + case WNI_CFG_BEACON_INTERVAL: + // What to do for IBSS ?? - TBD + if (LIM_IS_AP_ROLE(psessionEntry)) + schSetBeaconInterval(pMac,psessionEntry); + break; + + + case WNI_CFG_DTIM_PERIOD: + pMac->sch.schObject.gSchDTIMCount = 0; + break; + + case WNI_CFG_CFP_PERIOD: + pMac->sch.schObject.gSchCFPCount = 0; + break; + + case WNI_CFG_EDCA_PROFILE: + schEdcaProfileUpdate(pMac, psessionEntry); + break; + + case WNI_CFG_EDCA_ANI_ACBK_LOCAL: + case WNI_CFG_EDCA_ANI_ACBE_LOCAL: + case WNI_CFG_EDCA_ANI_ACVI_LOCAL: + case WNI_CFG_EDCA_ANI_ACVO_LOCAL: + case WNI_CFG_EDCA_WME_ACBK_LOCAL: + case WNI_CFG_EDCA_WME_ACBE_LOCAL: + case WNI_CFG_EDCA_WME_ACVI_LOCAL: + case WNI_CFG_EDCA_WME_ACVO_LOCAL: + if (LIM_IS_AP_ROLE(psessionEntry)) + schQosUpdateLocal(pMac, psessionEntry); + break; + + case WNI_CFG_EDCA_ANI_ACBK: + case WNI_CFG_EDCA_ANI_ACBE: + case WNI_CFG_EDCA_ANI_ACVI: + case WNI_CFG_EDCA_ANI_ACVO: + case WNI_CFG_EDCA_WME_ACBK: + case WNI_CFG_EDCA_WME_ACBE: + case WNI_CFG_EDCA_WME_ACVI: + case WNI_CFG_EDCA_WME_ACVO: + if (LIM_IS_AP_ROLE(psessionEntry)) { + psessionEntry->gLimEdcaParamSetCount++; + schQosUpdateBroadcast(pMac, psessionEntry); + } + break; + + default: + schLog(pMac, LOGE, FL("Cfg param %d indication not handled"), + pSchMsg->bodyval); + } + break; + + default: + schLog(pMac, LOGE, FL("Unknown message in schMsgQ type %d"), + pSchMsg->type); + } + +} + + +/* Get the local or broadcast parameters based on the profile specified in the + config params are delivered in this order: BK, BE, VI, VO */ +tSirRetStatus +schGetParams( + tpAniSirGlobal pMac, + tANI_U32 params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], + tANI_U8 local) +{ + tANI_U32 val; + tANI_U32 i,idx; + tANI_U32 *prf; + + tANI_U32 ani_l[] = { WNI_CFG_EDCA_ANI_ACBE_LOCAL,WNI_CFG_EDCA_ANI_ACBK_LOCAL, + WNI_CFG_EDCA_ANI_ACVI_LOCAL, WNI_CFG_EDCA_ANI_ACVO_LOCAL }; + tANI_U32 wme_l[] = {WNI_CFG_EDCA_WME_ACBE_LOCAL, WNI_CFG_EDCA_WME_ACBK_LOCAL, + WNI_CFG_EDCA_WME_ACVI_LOCAL, WNI_CFG_EDCA_WME_ACVO_LOCAL}; + tANI_U32 ani_b[] = {WNI_CFG_EDCA_ANI_ACBE, WNI_CFG_EDCA_ANI_ACBK, + WNI_CFG_EDCA_ANI_ACVI, WNI_CFG_EDCA_ANI_ACVO}; + tANI_U32 wme_b[] = {WNI_CFG_EDCA_WME_ACBE, WNI_CFG_EDCA_WME_ACBK, + WNI_CFG_EDCA_WME_ACVI, WNI_CFG_EDCA_WME_ACVO}; + + if (wlan_cfgGetInt(pMac, WNI_CFG_EDCA_PROFILE, &val) != eSIR_SUCCESS) + { + schLog(pMac, LOGP, FL("failed to cfg get EDCA_PROFILE id %d"), + WNI_CFG_EDCA_PROFILE); + return eSIR_FAILURE; + } + + if (val >= WNI_CFG_EDCA_PROFILE_MAX) + { + schLog(pMac, LOGE, FL("Invalid EDCA_PROFILE %d, using %d instead"), + val, WNI_CFG_EDCA_PROFILE_ANI); + val = WNI_CFG_EDCA_PROFILE_ANI; + } + + schLog(pMac, LOGW, FL("EdcaProfile: Using %d (%s)"), val, + ((val == WNI_CFG_EDCA_PROFILE_WMM) ? "WMM" : "HiPerf")); + + if (local) + { + switch (val) + { + case WNI_CFG_EDCA_PROFILE_WMM: + prf = &wme_l[0]; + break; + case WNI_CFG_EDCA_PROFILE_ANI: + default: + prf = &ani_l[0]; + break; + } + } + else + { + switch (val) + { + case WNI_CFG_EDCA_PROFILE_WMM: + prf = &wme_b[0]; + break; + case WNI_CFG_EDCA_PROFILE_ANI: + default: + prf = &ani_b[0]; + break; + } + } + + for (i=0; i < 4; i++) + { + tANI_U8 data[WNI_CFG_EDCA_ANI_ACBK_LEN]; + tANI_U32 len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN; + if (wlan_cfgGetStr(pMac, (tANI_U16) prf[i], (tANI_U8 *) &data[0], &len) != eSIR_SUCCESS) + { + schLog(pMac, LOGP, FL("cfgGet failed for %d"), prf[i]); + return eSIR_FAILURE; + } + if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) + { + schLog(pMac, LOGE, FL("cfgGet for %d: length is %d instead of %d"), + prf[i], len, WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN); + return eSIR_FAILURE; + } + for (idx=0; idx < len; idx++) + params[i][idx] = (tANI_U32) data[idx]; + } + PELOG1(schLog(pMac, LOG1, FL("GetParams: local=%d, profile = %d Done"), local, val);) + return eSIR_SUCCESS; +} + +static void broadcastWMMOfConcurrentSTASession(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tANI_U8 i,j; + tpPESession pConcurrentStaSessionEntry; + + for (i =0;i < pMac->lim.maxBssId;i++) + { + /* Find another INFRA STA AP session on same operating channel. The session entry passed to this API is for GO/SoftAP session that is getting added currently */ + if ( (pMac->lim.gpSession[i].valid == TRUE ) && + (pMac->lim.gpSession[i].peSessionId != psessionEntry->peSessionId) && + (pMac->lim.gpSession[i].currentOperChannel == psessionEntry->currentOperChannel) && + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE) + ) + { + pConcurrentStaSessionEntry = &(pMac->lim.gpSession[i]); + for (j=0; jgLimEdcaParamsBC[j].aci.acm = pConcurrentStaSessionEntry->gLimEdcaParams[j].aci.acm; + psessionEntry->gLimEdcaParamsBC[j].aci.aifsn = pConcurrentStaSessionEntry->gLimEdcaParams[j].aci.aifsn; + psessionEntry->gLimEdcaParamsBC[j].cw.min = pConcurrentStaSessionEntry->gLimEdcaParams[j].cw.min; + psessionEntry->gLimEdcaParamsBC[j].cw.max = pConcurrentStaSessionEntry->gLimEdcaParams[j].cw.max; + psessionEntry->gLimEdcaParamsBC[j].txoplimit= pConcurrentStaSessionEntry->gLimEdcaParams[j].txoplimit; + + PELOG1(schLog(pMac, LOG1, "QoSUpdateBCast changed again due to concurrent INFRA STA session: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d", + j, + psessionEntry->gLimEdcaParamsBC[j].aci.aifsn, + psessionEntry->gLimEdcaParamsBC[j].aci.acm, + psessionEntry->gLimEdcaParamsBC[j].cw.min, + psessionEntry->gLimEdcaParamsBC[j].cw.max, + psessionEntry->gLimEdcaParamsBC[j].txoplimit);) + + } + /* + * Once at-least one concurrent session on same channel is found + * and WMM broadcast params for current SoftAP/GO session updated, + * return + */ + break; + } + } +} + +void +schQosUpdateBroadcast(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tANI_U32 params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]; + tANI_U32 cwminidx, cwmaxidx, txopidx; + tANI_U32 phyMode; + tANI_U8 i; + + if (schGetParams(pMac, params, false) != eSIR_SUCCESS) + { + PELOGE(schLog(pMac, LOGE, FL("QosUpdateBroadcast: failed"));) + return; + } + limGetPhyMode(pMac, &phyMode, psessionEntry); + + PELOG1(schLog(pMac, LOG1, "QosUpdBcast: mode %d", phyMode);) + + if (phyMode == WNI_CFG_PHY_MODE_11G) + { + cwminidx = WNI_CFG_EDCA_PROFILE_CWMING_IDX; + cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXG_IDX; + txopidx = WNI_CFG_EDCA_PROFILE_TXOPG_IDX; + } + else if (phyMode == WNI_CFG_PHY_MODE_11B) + { + cwminidx = WNI_CFG_EDCA_PROFILE_CWMINB_IDX; + cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXB_IDX; + txopidx = WNI_CFG_EDCA_PROFILE_TXOPB_IDX; + } + else // This can happen if mode is not set yet, assume 11a mode + { + cwminidx = WNI_CFG_EDCA_PROFILE_CWMINA_IDX; + cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXA_IDX; + txopidx = WNI_CFG_EDCA_PROFILE_TXOPA_IDX; + } + + + for(i=0; igLimEdcaParamsBC[i].aci.acm = (tANI_U8) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX]; + psessionEntry->gLimEdcaParamsBC[i].aci.aifsn = (tANI_U8) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX]; + psessionEntry->gLimEdcaParamsBC[i].cw.min = convertCW(GET_CW(¶ms[i][cwminidx])); + psessionEntry->gLimEdcaParamsBC[i].cw.max = convertCW(GET_CW(¶ms[i][cwmaxidx])); + psessionEntry->gLimEdcaParamsBC[i].txoplimit= (tANI_U16) params[i][txopidx]; + + PELOG1(schLog(pMac, LOG1, "QoSUpdateBCast: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d", i, + psessionEntry->gLimEdcaParamsBC[i].aci.aifsn, + psessionEntry->gLimEdcaParamsBC[i].aci.acm, + psessionEntry->gLimEdcaParamsBC[i].cw.min, + psessionEntry->gLimEdcaParamsBC[i].cw.max, + psessionEntry->gLimEdcaParamsBC[i].txoplimit);) + + } + + /* If there exists a concurrent STA-AP session, use its WMM params to broadcast in beacons. WFA Wifi Direct test plan 6.1.14 requirement */ + broadcastWMMOfConcurrentSTASession(pMac, psessionEntry); + + if (schSetFixedBeaconFields(pMac,psessionEntry) != eSIR_SUCCESS) + PELOGE(schLog(pMac, LOGE, "Unable to set beacon fields!");) +} + +void +schQosUpdateLocal(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + tANI_U32 params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]; + + if (schGetParams(pMac, params, true /*local*/) != eSIR_SUCCESS) + { + PELOGE(schLog(pMac, LOGE, FL("schGetParams(local) failed"));) + return; + } + + setSchEdcaParams(pMac, params, psessionEntry); + + //For AP, the bssID is stored in LIM Global context. + limSendEdcaParams(pMac, psessionEntry->gLimEdcaParams, + psessionEntry->bssIdx); +} + +/** ---------------------------------------------------------- +\fn schSetDefaultEdcaParams +\brief This function sets the gLimEdcaParams to the default +\ local wmm profile. +\param tpAniSirGlobal pMac +\return none +\ ------------------------------------------------------------ */ +void +schSetDefaultEdcaParams(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tANI_U32 params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]; + + if (getWmmLocalParams(pMac, params) != eSIR_SUCCESS) + { + PELOGE(schLog(pMac, LOGE, FL("getWmmLocalParams() failed"));) + return; + } + + setSchEdcaParams(pMac, params, psessionEntry); + return; +} + + +/** ---------------------------------------------------------- +\fn setSchEdcaParams +\brief This function fills in the gLimEdcaParams structure +\ with the given edca params. +\param tpAniSirGlobal pMac +\return none +\ ------------------------------------------------------------ */ +static void +setSchEdcaParams(tpAniSirGlobal pMac, tANI_U32 params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], tpPESession psessionEntry) +{ + tANI_U32 i; + tANI_U32 cwminidx, cwmaxidx, txopidx; + tANI_U32 phyMode; + + limGetPhyMode(pMac, &phyMode, psessionEntry); + + PELOG1(schLog(pMac, LOG1, FL("limGetPhyMode() = %d"), phyMode);) + + //if (pMac->lim.gLimPhyMode == WNI_CFG_PHY_MODE_11G) + if (phyMode == WNI_CFG_PHY_MODE_11G) + { + cwminidx = WNI_CFG_EDCA_PROFILE_CWMING_IDX; + cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXG_IDX; + txopidx = WNI_CFG_EDCA_PROFILE_TXOPG_IDX; + } + //else if (pMac->lim.gLimPhyMode == WNI_CFG_PHY_MODE_11B) + else if (phyMode == WNI_CFG_PHY_MODE_11B) + { + cwminidx = WNI_CFG_EDCA_PROFILE_CWMINB_IDX; + cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXB_IDX; + txopidx = WNI_CFG_EDCA_PROFILE_TXOPB_IDX; + } + else // This can happen if mode is not set yet, assume 11a mode + { + cwminidx = WNI_CFG_EDCA_PROFILE_CWMINA_IDX; + cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXA_IDX; + txopidx = WNI_CFG_EDCA_PROFILE_TXOPA_IDX; + } + + for(i=0; igLimEdcaParams[i].aci.acm = (tANI_U8) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX]; + psessionEntry->gLimEdcaParams[i].aci.aifsn = (tANI_U8) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX]; + psessionEntry->gLimEdcaParams[i].cw.min = convertCW(GET_CW(¶ms[i][cwminidx])); + psessionEntry->gLimEdcaParams[i].cw.max = convertCW(GET_CW(¶ms[i][cwmaxidx])); + psessionEntry->gLimEdcaParams[i].txoplimit= (tANI_U16) params[i][txopidx]; + + PELOG1(schLog(pMac, LOG1, FL("AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"), i, + psessionEntry->gLimEdcaParams[i].aci.aifsn, + psessionEntry->gLimEdcaParams[i].aci.acm, + psessionEntry->gLimEdcaParams[i].cw.min, + psessionEntry->gLimEdcaParams[i].cw.max, + psessionEntry->gLimEdcaParams[i].txoplimit);) + + } + return; +} + +/** ---------------------------------------------------------- +\fn getWmmLocalParams +\brief This function gets the WMM local edca parameters. +\param tpAniSirGlobal pMac +\param tANI_U32 params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN] +\return none +\ ------------------------------------------------------------ */ +static tSirRetStatus +getWmmLocalParams(tpAniSirGlobal pMac, tANI_U32 params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]) +{ + tANI_U32 i,idx; + tANI_U32 *prf; + tANI_U32 wme_l[] = {WNI_CFG_EDCA_WME_ACBE_LOCAL, WNI_CFG_EDCA_WME_ACBK_LOCAL, + WNI_CFG_EDCA_WME_ACVI_LOCAL, WNI_CFG_EDCA_WME_ACVO_LOCAL}; + + prf = &wme_l[0]; + for (i=0; i < 4; i++) + { + tANI_U8 data[WNI_CFG_EDCA_ANI_ACBK_LEN]; + tANI_U32 len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN; + if (wlan_cfgGetStr(pMac, (tANI_U16) prf[i], (tANI_U8 *) &data[0], &len) != eSIR_SUCCESS) + { + schLog(pMac, LOGP, FL("cfgGet failed for %d"), prf[i]); + return eSIR_FAILURE; + } + if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) + { + schLog(pMac, LOGE, FL("cfgGet for %d: length is %d instead of %d"), + prf[i], len, WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN); + return eSIR_FAILURE; + } + for (idx=0; idx < len; idx++) + params[i][idx] = (tANI_U32) data[idx]; + } + return eSIR_SUCCESS; +} + + +/** ---------------------------------------------------------- +\fn schEdcaProfileUpdate +\brief This function updates the local and broadcast +\ EDCA params in the gLimEdcaParams structure. It also +\ updates the edcaParamSetCount. +\param tpAniSirGlobal pMac +\return none +\ ------------------------------------------------------------ */ +void +schEdcaProfileUpdate(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) { + schQosUpdateLocal(pMac, psessionEntry); + psessionEntry->gLimEdcaParamSetCount++; + schQosUpdateBroadcast(pMac, psessionEntry); + } +} + +// -------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schSysParams.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schSysParams.h new file mode 100644 index 000000000000..55ddf027935e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schSysParams.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file schSysParams.h contains scheduler parameter definitions + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __SCH_SYS_PARAMS_H__ +#define __SCH_SYS_PARAMS_H__ + +/// Unsolicited poll period (ms) (0 to disable) +#define SCH_POLL_PERIOD 1000 + +/// RR timeout value (ms) (0 to disable) +#define SCH_RR_TIMEOUT_MS 40 + +/// Default CP:CFP ratio +#define SCH_DEFAULT_CP_TO_CFP_RATIO 0 + +/// Default maximum CFP duration (us) +#define SCH_DEFAULT_MAX_CFP_TIME 60000 + +/// Default minimum CP duration (us) +#define SCH_DEFAULT_MIN_CP_TIME 100 + +/// Amount of delay prior to starting CFP (us) +#define SCH_CFP_START_DELAY 100 + +/// Unit of Txop in micro seconds +#define TXOP_UNIT_IN_USEC 32 + +/// Minimum amount of time granted per instruction on average (units of txop) +#define MIN_TXOP_PER_INSTRUCTION 50 + +/// Maximum amount of time granted per instruction (units of txop) +#define MAX_TXOP_PER_INSTRUCTION 300 // HACK - 100 + +/// Maximum amount of time granted to one entire schedule (units of txop) +#define MAX_TXOP_PER_SCHEDULE 400 + +/// Scheduling quantum (units of TXOP) +#define SCH_QUANTUM_QUEUE 4 + +/// Maximum unused quantum allowed to be accumulated by a queue +#define MAX_ACCUMULATED_QUANTUM 500 + +/// Minimum allocated quantum for an uplink flow before a poll instruction is written +#define SCH_MIN_UL_ALLOC 12 + +// ---- Scheduling Policy ---- + +/// Number of QOS classes +#define SCH_NUM_QOS_CLASSES 2 + +#define SCH_POLICY_STRICT_PRI 0 +#define SCH_POLICY_DRR 1 + +/// Scheduling quantum for each class if using DRR +#define SCH_QUANTUM_CLASS 100 + +/// The default scheduling policy between classes +#define SCH_POLICY_DEFAULT SCH_POLICY_STRICT_PRI + +// Scheduling weights for each priority + +#define SCH_QUANTUM_0 40 +#define SCH_QUANTUM_1 36 +#define SCH_QUANTUM_2 32 +#define SCH_QUANTUM_3 28 +#define SCH_QUANTUM_4 24 +#define SCH_QUANTUM_5 20 +#define SCH_QUANTUM_6 16 +#define SCH_QUANTUM_7 12 + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h b/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h new file mode 100644 index 000000000000..9fd1c101f53a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h @@ -0,0 +1,2385 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WLAN_QCT_WLANSAP_H +#define WLAN_QCT_WLANSAP_H + +/*=========================================================================== + + W L A N S O F T A P P A L L A Y E R + E X T E R N A L A P I + + +DESCRIPTION + This file contains the external API exposed by the wlan SAP PAL layer + module. +===========================================================================*/ + + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header: /cygdrive/d/Builds/M7201JSDCAAPAD52240B/WM/platform/msm7200/Src/Drivers/SD/ClientDrivers/WLAN/QCT_BTAMP_RSN/CORE/SAP/inc/sapApi.h,v 1.21 2009/03/09 08:58:26 jzmuda Exp jzmuda $ $DateTime: $ $Author: jzmuda $ + + +when who what, where, why +-------- --- ---------------------------------------------------------- +07/01/08 SAP team Created module. + +===========================================================================*/ + + + +/*=========================================================================== + + INCLUDE FILES FOR MODULE + +===========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "vos_api.h" +#include "vos_packet.h" +#include "vos_types.h" + +#include "p2p_Api.h" +#include "sme_Api.h" +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + #ifdef __cplusplus + extern "C" { + #endif + + + +/*---------------------------------------------------------------------------- + * Defines + * -------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + defines and enum + ------------------------------------------------------------------------*/ + +#define MAX_SSID_LEN 32 +#define MAX_ACL_MAC_ADDRESS 32 +#define AUTO_CHANNEL_SELECT 0 +#define MAX_ASSOC_IND_IE_LEN 255 + +#define MAX_NAME_SIZE 64 +#define MAX_TEXT_SIZE 32 + +#define MAX_CHANNEL_LIST_LEN 256 +#ifdef WLAN_FEATURE_MBSSID +#define VOS_MAX_NO_OF_SAP_MODE 2 // max # of SAP +#else +#define VOS_MAX_NO_OF_SAP_MODE 1 // max # of SAP +#endif +#define SAP_MAX_NUM_SESSION 5 +#define SAP_MAX_OBSS_STA_CNT 1 // max # of OBSS STA + +/*-------------------------------------------------------------------------- + reasonCode take form 802.11 standard Table 7-22 to be passed to WLANSAP_DisassocSta api. + ------------------------------------------------------------------------*/ + +typedef enum{ + eSAP_RC_RESERVED0, /*0*/ + eSAP_RC_UNSPECIFIED, /*1*/ + eSAP_RC_PREV_AUTH_INVALID, /*2*/ + eSAP_RC_STA_LEFT_DEAUTH, /*3*/ + eSAP_RC_INACTIVITY_DISASSOC, /*4*/ + eSAP_RC_AP_CAPACITY_FULL, /*5*/ + eSAP_RC_CLS2_FROM_NON_AUTH_STA, /*6*/ + eSAP_RC_CLS3_FROM_NON_AUTH_STA, /*7*/ + eSAP_RC_STA_LEFT_DISASSOC, /*8*/ + eSAP_RC_STA_NOT_AUTH, /*9*/ + eSAP_RC_PC_UNACCEPTABLE, /*10*/ + eSAP_RC_SC_UNACCEPTABLE, /*11*/ + eSAP_RC_RESERVED1, /*12*/ + eSAP_RC_INVALID_IE, /*13*/ + eSAP_RC_MIC_FAIL, /*14*/ + eSAP_RC_4_WAY_HANDSHAKE_TO, /*15*/ + eSAP_RC_GO_KEY_HANDSHAKE_TO, /*16*/ + eSAP_RC_IE_MISMATCH, /*17*/ + eSAP_RC_INVALID_GRP_CHIPHER, /*18*/ + eSAP_RC_INVALID_PAIR_CHIPHER, /*19*/ + eSAP_RC_INVALID_AKMP, /*20*/ + eSAP_RC_UNSUPPORTED_RSN, /*21*/ + eSAP_RC_INVALID_RSN, /*22*/ + eSAP_RC_1X_AUTH_FAILED, /*23*/ + eSAP_RC_CHIPER_SUITE_REJECTED, /*24*/ +}eSapReasonCode; + +typedef enum { + eSAP_ACCEPT_UNLESS_DENIED = 0, + eSAP_DENY_UNLESS_ACCEPTED = 1, + eSAP_SUPPORT_ACCEPT_AND_DENY = 2, /* this type is added to support both accept and deny lists at the same time */ + eSAP_ALLOW_ALL = 3, /*In this mode all MAC addresses are allowed to connect*/ +} eSapMacAddrACL; + +typedef enum { + eSAP_BLACK_LIST = 0, /* List of mac addresses NOT allowed to assoc */ + eSAP_WHITE_LIST = 1, /* List of mac addresses allowed to assoc */ +} eSapACLType; + +typedef enum { + ADD_STA_TO_ACL = 0, /* cmd to add STA to access control list */ + DELETE_STA_FROM_ACL = 1, /* cmd to delete STA from access control list */ +} eSapACLCmdType; + +typedef enum { + eSAP_START_BSS_EVENT = 0, /*Event sent when BSS is started*/ + eSAP_STOP_BSS_EVENT, /*Event sent when BSS is stopped*/ + eSAP_STA_ASSOC_IND, /* Indicate the association request to upper layers */ + eSAP_STA_ASSOC_EVENT, /*Event sent when we have successfully associated a station and + upper layer neeeds to allocate a context*/ + eSAP_STA_REASSOC_EVENT, /*Event sent when we have successfully reassociated a station and + upper layer neeeds to allocate a context*/ + eSAP_STA_DISASSOC_EVENT, /*Event sent when associated a station has disassociated as a result of various conditions */ + eSAP_STA_SET_KEY_EVENT, /*Event sent when user called WLANSAP_SetKeySta */ + eSAP_STA_DEL_KEY_EVENT, /*Event sent when user called WLANSAP_DelKeySta */ + eSAP_STA_MIC_FAILURE_EVENT, /*Event sent whenever there is MIC failure detected */ + eSAP_ASSOC_STA_CALLBACK_EVENT, /*Event sent when user called WLANSAP_GetAssocStations */ + eSAP_GET_WPSPBC_SESSION_EVENT, /* Event send when user call WLANSAP_getWpsSessionOverlap */ + eSAP_WPS_PBC_PROBE_REQ_EVENT, /* Event send on WPS PBC probe request is received */ + eSAP_INDICATE_MGMT_FRAME, + eSAP_REMAIN_CHAN_READY, + eSAP_SEND_ACTION_CNF, + eSAP_DISCONNECT_ALL_P2P_CLIENT, + eSAP_MAC_TRIG_STOP_BSS_EVENT, + eSAP_UNKNOWN_STA_JOIN, /* Event send when a STA in neither white list or black list tries to associate in softap mode */ + eSAP_MAX_ASSOC_EXCEEDED, /* Event send when a new STA is rejected association since softAP max assoc limit has reached */ + eSAP_CHANNEL_CHANGE_EVENT, + eSAP_DFS_CAC_START, + eSAP_DFS_CAC_INTERRUPTED, + eSAP_DFS_CAC_END, + eSAP_DFS_RADAR_DETECT, + eSAP_DFS_NOL_GET, /* Event sent when user need to get the DFS NOL from CNSS */ + eSAP_DFS_NOL_SET, /* Event sent when user need to set the DFS NOL to CNSS */ + eSAP_DFS_NO_AVAILABLE_CHANNEL, /* No ch available after DFS RADAR detect */ +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + eSAP_ACS_SCAN_SUCCESS_EVENT, +#endif + eSAP_ACS_CHANNEL_SELECTED, + eSAP_ECSA_CHANGE_CHAN_IND, +} eSapHddEvent; + +typedef enum { + eSAP_OPEN_SYSTEM, + eSAP_SHARED_KEY, + eSAP_AUTO_SWITCH + } eSapAuthType; + +typedef enum { + eSAP_MAC_INITATED_DISASSOC = 0x10000, /*Disassociation was internally initated from CORE stack*/ + eSAP_USR_INITATED_DISASSOC /*Disassociation was internally initated from host by invoking WLANSAP_DisassocSta call*/ + } eSapDisassocReason; + +/*Handle boolean over here*/ +typedef enum { + eSAP_FALSE, + eSAP_TRUE, +}eSapBool; + +typedef enum { + eSAP_DFS_NOL_CLEAR, + eSAP_DFS_NOL_RANDOMIZE, +}eSapDfsNolType; + +/*--------------------------------------------------------------------------- +SAP PAL "status" and "reason" error code defines + ---------------------------------------------------------------------------*/ +typedef enum { + eSAP_STATUS_SUCCESS, /* Success. */ + eSAP_STATUS_FAILURE, /* General Failure. */ + eSAP_START_BSS_CHANNEL_NOT_SELECTED, /* Channel not selected during intial scan. */ + eSAP_ERROR_MAC_START_FAIL, /* Failed to start Infra BSS */ +}eSapStatus; + +/*--------------------------------------------------------------------------- +SAP PAL "status" and "reason" error code defines + ---------------------------------------------------------------------------*/ +typedef enum { + eSAP_WPSPBC_OVERLAP_IN120S, /* Overlap */ + eSAP_WPSPBC_NO_WPSPBC_PROBE_REQ_IN120S, /* no WPS probe request in 120 second */ + eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S, /* One WPS probe request in 120 second */ +}eWPSPBCOverlap; + +/*---------------------------------------------------------------------------- + * Typedefs + * -------------------------------------------------------------------------*/ +typedef struct sap_StartBssCompleteEvent_s { + v_U8_t status; + v_U8_t operatingChannel; + v_U16_t staId; //self StaID + v_U8_t sessionId; /* SoftAP SME session ID */ +} tSap_StartBssCompleteEvent; + +typedef struct sap_StopBssCompleteEvent_s { + v_U8_t status; +} tSap_StopBssCompleteEvent; + +typedef struct sap_StationAssocIndication_s { + v_MACADDR_t staMac; + v_U8_t assoId; + v_U8_t staId; + v_U8_t status; + // Required for indicating the frames to upper layer + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; + tANI_BOOLEAN fWmmEnabled; + eCsrAuthType negotiatedAuthType; + eCsrEncryptionType negotiatedUCEncryptionType; + eCsrEncryptionType negotiatedMCEncryptionType; + tANI_BOOLEAN fAuthRequired; +} tSap_StationAssocIndication; + +typedef struct sap_StationAssocReassocCompleteEvent_s { + v_MACADDR_t staMac; + v_U8_t staId; + v_U8_t status; + v_U8_t ies[MAX_ASSOC_IND_IE_LEN]; + v_U16_t iesLen; + v_U32_t statusCode; + eSapAuthType SapAuthType; + v_BOOL_t wmmEnabled; + // Required for indicating the frames to upper layer + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; + tANI_U32 assocRespLength; + tANI_U8* assocRespPtr; + tANI_U8 timingMeasCap; + tSirSmeChanInfo chan_info; +} tSap_StationAssocReassocCompleteEvent; + +typedef struct sap_StationDisassocCompleteEvent_s { + v_MACADDR_t staMac; + v_U8_t staId; //STAID should not be used + v_U8_t status; + v_U32_t statusCode; + eSapDisassocReason reason; +} tSap_StationDisassocCompleteEvent; + +typedef struct sap_StationSetKeyCompleteEvent_s { + v_U8_t status; + v_MACADDR_t peerMacAddr; +} tSap_StationSetKeyCompleteEvent; + +/*struct corresponding to SAP_STA_DEL_KEY_EVENT */ +typedef struct sap_StationDeleteKeyCompleteEvent_s { + v_U8_t status; + v_U8_t keyId; /* Key index */ +} tSap_StationDeleteKeyCompleteEvent; + +/*struct corresponding to SAP_STA_MIC_FAILURE_EVENT */ +typedef struct sap_StationMICFailureEvent_s { + v_MACADDR_t srcMacAddr; //address used to compute MIC + v_MACADDR_t staMac; //taMacAddr transmitter address + v_MACADDR_t dstMacAddr; + eSapBool multicast; + v_U8_t IV1; // first byte of IV + v_U8_t keyId; // second byte of IV + v_U8_t TSC[SIR_CIPHER_SEQ_CTR_SIZE]; // sequence number + +} tSap_StationMICFailureEvent; +/*Structure to return MAC address of associated stations */ +typedef struct sap_AssocMacAddr_s { + v_MACADDR_t staMac; /*MAC address of Station that is associated*/ + v_U8_t assocId; /*Association ID for the station that is associated*/ + v_U8_t staId; /*Station Id that is allocated to the station*/ + v_U8_t ShortGI40Mhz; + v_U8_t ShortGI20Mhz; + v_U8_t Support40Mhz; + v_U32_t requestedMCRate; + tSirSupportedRates supportedRates; +} tSap_AssocMacAddr, *tpSap_AssocMacAddr; + +/*struct corresponding to SAP_ASSOC_STA_CALLBACK_EVENT */ +typedef struct sap_AssocStaListEvent_s { + VOS_MODULE_ID module; /* module id that was passed in WLANSAP_GetAssocStations API*/ + v_U8_t noOfAssocSta; /* Number of associated stations*/ + tpSap_AssocMacAddr pAssocStas; /*Pointer to pre allocated memory to obtain list of associated + stations passed in WLANSAP_GetAssocStations API*/ +} tSap_AssocStaListEvent; + +typedef struct sap_GetWPSPBCSessionEvent_s { + v_U8_t status; + VOS_MODULE_ID module; /* module id that was passed in WLANSAP_GetAssocStations API*/ + v_U8_t UUID_E[16]; // Unique identifier of the AP. + v_MACADDR_t addr; + eWPSPBCOverlap wpsPBCOverlap; +} tSap_GetWPSPBCSessionEvent; + +typedef struct sap_WPSPBCProbeReqEvent_s { + v_U8_t status; + VOS_MODULE_ID module; /* module id that was passed in WLANSAP_GetAssocStations API*/ + tSirWPSPBCProbeReq WPSPBCProbeReq; +} tSap_WPSPBCProbeReqEvent; + +typedef struct sap_ManagementFrameInfo_s { + tANI_U32 nFrameLength; + tANI_U8 frameType; + tANI_U32 rxChan; //Channel of where packet is received + tANI_U8 *pbFrames; //Point to a buffer contain the beacon, assoc req, assoc rsp frame, in that order + //user needs to use nBeaconLength, nAssocReqLength, nAssocRspLength to desice where + //each frame starts and ends. +} tSap_ManagementFrameInfo; + +typedef struct sap_SendActionCnf_s { + eSapStatus actionSendSuccess; +} tSap_SendActionCnf; + +typedef struct sap_UnknownSTAJoinEvent_s { + v_MACADDR_t macaddr; +} tSap_UnknownSTAJoinEvent; + +typedef struct sap_MaxAssocExceededEvent_s { + v_MACADDR_t macaddr; +} tSap_MaxAssocExceededEvent; + +typedef struct sap_DfsNolInfo_s { + v_U16_t sDfsList; /* size of pDfsList in byte */ + v_PVOID_t pDfsList; /* pointer to pDfsList buffer */ +} tSap_DfsNolInfo; + +typedef struct sap_ChSelected_s { + uint16_t pri_ch; + uint16_t ht_sec_ch; + uint16_t vht_seg0_center_ch; + uint16_t vht_seg1_center_ch; + uint16_t ch_width; +} tSap_ChSelectedEvent; + +/** + * struct sap_ch_change_ind - channel change indication + * @new_chan: channel to change + */ +struct sap_ch_change_ind { + uint16_t new_chan; +}; + + +/* + This struct will be filled in and passed to tpWLAN_SAPEventCB that is provided during WLANSAP_StartBss call + The event id corresponding to structure in the union is defined in comment next to the structure +*/ + +typedef struct sap_Event_s { + eSapHddEvent sapHddEventCode; + union { + tSap_StartBssCompleteEvent sapStartBssCompleteEvent; /*SAP_START_BSS_EVENT*/ + tSap_StopBssCompleteEvent sapStopBssCompleteEvent; /*SAP_STOP_BSS_EVENT*/ + tSap_StationAssocIndication sapAssocIndication; /*SAP_ASSOC_INDICATION */ + tSap_StationAssocReassocCompleteEvent sapStationAssocReassocCompleteEvent; /*SAP_STA_ASSOC_EVENT, SAP_STA_REASSOC_EVENT*/ + tSap_StationDisassocCompleteEvent sapStationDisassocCompleteEvent;/*SAP_STA_DISASSOC_EVENT*/ + tSap_StationSetKeyCompleteEvent sapStationSetKeyCompleteEvent;/*SAP_STA_SET_KEY_EVENT*/ + tSap_StationDeleteKeyCompleteEvent sapStationDeleteKeyCompleteEvent;/*SAP_STA_DEL_KEY_EVENT*/ + tSap_StationMICFailureEvent sapStationMICFailureEvent; /*SAP_STA_MIC_FAILURE_EVENT */ + tSap_AssocStaListEvent sapAssocStaListEvent; /*SAP_ASSOC_STA_CALLBACK_EVENT */ + tSap_GetWPSPBCSessionEvent sapGetWPSPBCSessionEvent; /*SAP_GET_WPSPBC_SESSION_EVENT */ + tSap_WPSPBCProbeReqEvent sapPBCProbeReqEvent; /*eSAP_WPS_PBC_PROBE_REQ_EVENT */ + tSap_ManagementFrameInfo sapManagementFrameInfo; /*eSAP_INDICATE_MGMT_FRAME*/ + tSap_SendActionCnf sapActionCnf; /* eSAP_SEND_ACTION_CNF */ + tSap_UnknownSTAJoinEvent sapUnknownSTAJoin; /* eSAP_UNKNOWN_STA_JOIN */ + tSap_MaxAssocExceededEvent sapMaxAssocExceeded; /* eSAP_MAX_ASSOC_EXCEEDED */ + tSap_DfsNolInfo sapDfsNolInfo; /*eSAP_DFS_NOL_XXX */ + /*eSAP_ACS_CHANNEL_SELECTED */ + tSap_ChSelectedEvent sapChSelected; + struct sap_ch_change_ind sap_chan_cng_ind; + } sapevt; +} tSap_Event, *tpSap_Event; + + +typedef __ani_attr_pre_packed struct sap_SSID { + v_U8_t length; + v_U8_t ssId[MAX_SSID_LEN]; +} __ani_attr_packed tSap_SSID_t; + +typedef __ani_attr_pre_packed struct sap_SSIDInfo { + tSap_SSID_t ssid; /*SSID of the AP*/ + v_U8_t ssidHidden; /*SSID shouldn't/should be broadcast in probe RSP and beacon*/ +} __ani_attr_packed tSap_SSIDInfo_t; + +struct sap_acs_cfg { + /* ACS Algo Input */ + uint8_t acs_mode; + uint32_t hw_mode; + uint8_t start_ch; + uint8_t end_ch; + uint8_t *ch_list; + uint8_t ch_list_count; +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + uint8_t skip_scan_status; + uint8_t skip_scan_range1_stch; + uint8_t skip_scan_range1_endch; + uint8_t skip_scan_range2_stch; + uint8_t skip_scan_range2_endch; +#endif + + uint16_t ch_width; + /* ACS Algo Output */ + uint8_t pri_ch; + uint8_t ht_sec_ch; + uint8_t vht_seg0_center_ch; + uint8_t vht_seg1_center_ch; +}; + + +typedef struct sap_Config { + tSap_SSIDInfo_t SSIDinfo; + eCsrPhyMode SapHw_mode; /* Wireless Mode */ + eSapMacAddrACL SapMacaddr_acl; + v_MACADDR_t accept_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ + v_BOOL_t ieee80211d; /*Specify if 11D is enabled or disabled*/ + v_BOOL_t protEnabled; /*Specify if protection is enabled or disabled*/ + v_BOOL_t obssProtEnabled; /*Specify if OBSS protection is enabled or disabled*/ + v_MACADDR_t deny_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ + v_MACADDR_t self_macaddr; //self macaddress or BSSID + + v_U8_t channel; /* Operation channel */ + uint8_t sec_ch; + uint16_t vht_channel_width; + uint16_t ch_width_orig; + v_U8_t max_num_sta; /* maximum number of STAs in station table */ + v_U8_t dtim_period; /* dtim interval */ + v_U8_t num_accept_mac; + v_U8_t num_deny_mac; + /* Max ie length 255 * 2(WPA+RSN) + 2 bytes(vendor specific ID) * 2 */ + v_U8_t RSNWPAReqIE[(SIR_MAC_MAX_IE_LENGTH * 2) + 4]; + v_U8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; //it is ignored if [0] is 0. + v_U8_t RSNAuthType; + v_U8_t RSNEncryptType; + v_U8_t mcRSNEncryptType; + eSapAuthType authType; + v_BOOL_t privacy; + v_BOOL_t UapsdEnable; + v_BOOL_t fwdWPSPBCProbeReq; + v_U8_t wps_state; // 0 - disabled, 1 - not configured , 2 - configured + + v_U16_t ht_capab; + v_U16_t RSNWPAReqIELength; //The byte count in the pWPAReqIE + + v_U32_t beacon_int; /* Beacon Interval */ + v_U32_t ap_table_max_size; + v_U32_t ap_table_expiration_time; + v_U32_t ht_op_mode_fixed; + tVOS_CON_MODE persona; /*Tells us which persona it is GO or AP for now*/ + v_U8_t disableDFSChSwitch; + eCsrBand scanBandPreference; + v_BOOL_t enOverLapCh; + v_U16_t acsBandSwitchThreshold; + struct sap_acs_cfg acs_cfg; +#ifdef WLAN_FEATURE_11W + v_BOOL_t mfpRequired; + v_BOOL_t mfpCapable; +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + v_U8_t cc_switch_mode; +#endif + + v_U16_t probeRespIEsBufferLen; + v_PVOID_t pProbeRespIEsBuffer; /* buffer for addn ies comes from hostapd*/ + + v_U16_t assocRespIEsLen; + v_PVOID_t pAssocRespIEsBuffer; /* buffer for addn ies comes from hostapd*/ + + v_U16_t probeRespBcnIEsLen; + v_PVOID_t pProbeRespBcnIEsBuffer; /* buffer for addn ies comes from hostapd*/ + uint8_t sap_dot11mc; /* Specify if 11MC is enabled or disabled*/ + +} tsap_Config_t; + +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE +typedef enum { + eSAP_DO_NEW_ACS_SCAN, + eSAP_DO_PAR_ACS_SCAN, + eSAP_SKIP_ACS_SCAN +} tSap_skip_acs_scan; +#endif + +typedef enum { + eSAP_WPS_PROBE_RSP_IE, + eSAP_WPS_BEACON_IE, + eSAP_WPS_ASSOC_RSP_IE +} eSapWPSIE_CODE; + +typedef struct sSapName { + v_U8_t num_name; + v_U8_t name[MAX_NAME_SIZE]; +} tSapName; + +typedef struct sSapText { + v_U8_t num_text; + v_U8_t text[MAX_TEXT_SIZE]; +} tSapText; + +typedef enum +{ + eSAP_DFS_DO_NOT_SKIP_CAC, + eSAP_DFS_SKIP_CAC +} eSapDfsCACState_t; + +typedef enum +{ + eSAP_DFS_CHANNEL_USABLE, + eSAP_DFS_CHANNEL_AVAILABLE, + eSAP_DFS_CHANNEL_UNAVAILABLE +} eSapDfsChanStatus_t; + +typedef struct sSapDfsNolInfo +{ + v_U8_t dfs_channel_number; + eSapDfsChanStatus_t radar_status_flag; + v_U64_t radar_found_timestamp; +} tSapDfsNolInfo; + +typedef struct sSapDfsInfo +{ + vos_timer_t sap_dfs_cac_timer; + v_U8_t sap_radar_found_status; + /* + * New channel to move to when a Radar is + * detected on current Channel + */ + v_U8_t target_channel; + v_U8_t last_radar_found_channel; + v_U8_t ignore_cac; + eSapDfsCACState_t cac_state; + v_U8_t user_provided_target_channel; + + /* Requests for Channel Switch Announcement IE + * generation and transmission + */ + v_U8_t csaIERequired; + v_U8_t numCurrentRegDomainDfsChannels; + tSapDfsNolInfo sapDfsChannelNolList[NUM_5GHZ_CHANNELS]; + v_U8_t is_dfs_cac_timer_running; + /* + * New channel width and new channel bonding mode + * will only be updated via channel fallback mechanism + */ + tANI_U8 orig_cbMode; + tANI_U8 orig_chanWidth; + tANI_U8 new_chanWidth; + tANI_U8 new_cbMode; + + /* + * INI param to enable/disable SAP W53 + * channel operation. + */ + v_U8_t is_dfs_w53_disabled; + + /* + * sap_operating_channel_location holds SAP indoor, + * outdoor location information. Currently, if this + * param is set this Indoor/outdoor channel interop + * restriction will only be implemented for JAPAN + * regulatory domain. + * + * 0 - Indicates that location unknown + * (or) SAP Indoor/outdoor interop is allowed + * + * 1 - Indicates device is operating on Indoor channels + * and SAP cannot pick next random channel from outdoor + * list of channels when a radar is found on current operating + * DFS channel. + * + * 2 - Indicates device is operating on Outdoor Channels + * and SAP cannot pick next random channel from indoor + * list of channels when a radar is found on current + * operating DFS channel. + */ + v_U8_t sap_operating_chan_preferred_location; + + /* + * Flag to indicate if DFS test mode is enabled and + * channel switch is disabled. + */ + v_U8_t disable_dfs_ch_switch; +} tSapDfsInfo; + +typedef struct tagSapCtxList +{ + v_U8_t sessionID; + v_VOID_t* pSapContext; + tVOS_CON_MODE sapPersona; +} tSapCtxList, tpSapCtxList; + +typedef struct tagSapStruct +{ + //Information Required for SAP DFS Master mode + tSapDfsInfo SapDfsInfo; + tSapCtxList sapCtxList[SAP_MAX_NUM_SESSION]; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + bool sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + bool enable_dfs_phy_error_logs; +} tSapStruct, *tpSapStruct; + +#define WPS_PROBRSP_VER_PRESENT 0x00000001 +#define WPS_PROBRSP_STATE_PRESENT 0x00000002 +#define WPS_PROBRSP_APSETUPLOCK_PRESENT 0x00000004 +#define WPS_PROBRSP_SELECTEDREGISTRA_PRESENT 0x00000008 +#define WPS_PROBRSP_DEVICEPASSWORDID_PRESENT 0x00000010 +#define WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT 0x00000020 +#define WPS_PROBRSP_RESPONSETYPE_PRESENT 0x00000040 +#define WPS_PROBRSP_UUIDE_PRESENT 0x00000080 +#define WPS_PROBRSP_MANUFACTURE_PRESENT 0x00000100 +#define WPS_PROBRSP_MODELNAME_PRESENT 0x00000200 +#define WPS_PROBRSP_MODELNUMBER_PRESENT 0x00000400 +#define WPS_PROBRSP_SERIALNUMBER_PRESENT 0x00000800 +#define WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT 0x00001000 +#define WPS_PROBRSP_DEVICENAME_PRESENT 0x00002000 +#define WPS_PROBRSP_CONFIGMETHODS_PRESENT 0x00004000 +#define WPS_PROBRSP_RF_BANDS_PRESENT 0x00008000 + +typedef struct sap_WPSProbeRspIE_s { + v_U32_t FieldPresent; + v_U32_t Version; // Version. 0x10 = version 1.0, 0x11 = etc. + v_U32_t wpsState; // 1 = unconfigured, 2 = configured. + v_BOOL_t APSetupLocked; // Must be included if value is TRUE + v_BOOL_t SelectedRegistra; //BOOL: indicates if the user has recently activated a Registrar to add an Enrollee. + v_U16_t DevicePasswordID; // Device Password ID + v_U16_t SelectedRegistraCfgMethod; // Selected Registrar config method + v_U8_t ResponseType; // Response type + v_U8_t UUID_E[16]; // Unique identifier of the AP. + tSapName Manufacture; + tSapText ModelName; + tSapText ModelNumber; + tSapText SerialNumber; + v_U32_t PrimaryDeviceCategory ; // Device Category ID: 1Computer, 2Input Device, ... + v_U8_t PrimaryDeviceOUI[4] ; // Vendor specific OUI for Device Sub Category + v_U32_t DeviceSubCategory ; // Device Sub Category ID: 1-PC, 2-Server if Device Category ID is computer + tSapText DeviceName; + v_U16_t ConfigMethod; // Configuaration method + v_U8_t RFBand; // RF bands available on the AP +} tSap_WPSProbeRspIE; + +#define WPS_BEACON_VER_PRESENT 0x00000001 +#define WPS_BEACON_STATE_PRESENT 0x00000002 +#define WPS_BEACON_APSETUPLOCK_PRESENT 0x00000004 +#define WPS_BEACON_SELECTEDREGISTRA_PRESENT 0x00000008 +#define WPS_BEACON_DEVICEPASSWORDID_PRESENT 0x00000010 +#define WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT 0x00000020 +#define WPS_BEACON_UUIDE_PRESENT 0x00000080 +#define WPS_BEACON_RF_BANDS_PRESENT 0x00000100 + +typedef struct sap_WPSBeaconIE_s { + v_U32_t FieldPresent; + v_U32_t Version; // Version. 0x10 = version 1.0, 0x11 = etc. + v_U32_t wpsState; // 1 = unconfigured, 2 = configured. + v_BOOL_t APSetupLocked; // Must be included if value is TRUE + v_BOOL_t SelectedRegistra; //BOOL: indicates if the user has recently activated a Registrar to add an Enrollee. + v_U16_t DevicePasswordID; // Device Password ID + v_U16_t SelectedRegistraCfgMethod; // Selected Registrar config method + v_U8_t UUID_E[16]; // Unique identifier of the AP. + v_U8_t RFBand; // RF bands available on the AP +} tSap_WPSBeaconIE; + +#define WPS_ASSOCRSP_VER_PRESENT 0x00000001 +#define WPS_ASSOCRSP_RESPONSETYPE_PRESENT 0x00000002 + +typedef struct sap_WPSAssocRspIE_s { + v_U32_t FieldPresent; + v_U32_t Version; + v_U8_t ResposeType; +} tSap_WPSAssocRspIE; + +typedef struct sap_WPSIE_s { + eSapWPSIE_CODE sapWPSIECode; + union { + tSap_WPSProbeRspIE sapWPSProbeRspIE; /*WPS Set Probe Respose IE*/ + tSap_WPSBeaconIE sapWPSBeaconIE; /*WPS Set Beacon IE*/ + tSap_WPSAssocRspIE sapWPSAssocRspIE; /*WPS Set Assoc Response IE*/ + } sapwpsie; +} tSap_WPSIE, *tpSap_WPSIE; + +#ifdef WLANTL_DEBUG +#define MAX_RATE_INDEX 136 +#define MAX_NUM_RSSI 100 +#define MAX_RSSI_INTERVAL 5 +#endif + +typedef struct sap_SoftapStats_s { + v_U32_t txUCFcnt; + v_U32_t txMCFcnt; + v_U32_t txBCFcnt; + v_U32_t txUCBcnt; + v_U32_t txMCBcnt; + v_U32_t txBCBcnt; + v_U32_t rxUCFcnt; + v_U32_t rxMCFcnt; + v_U32_t rxBCFcnt; + v_U32_t rxUCBcnt; + v_U32_t rxMCBcnt; + v_U32_t rxBCBcnt; + v_U32_t rxBcnt; + v_U32_t rxBcntCRCok; + v_U32_t rxRate; +#ifdef WLANTL_DEBUG + v_U32_t pktCounterRateIdx[MAX_RATE_INDEX]; + v_U32_t pktCounterRssi[MAX_NUM_RSSI]; +#endif +} tSap_SoftapStats, *tpSap_SoftapStats; + +int sapSetPreferredChannel +( +#ifdef WLAN_FEATURE_MBSSID + v_PVOID_t sapContext, +#endif + tANI_U8* ptr +); + +/* Channel/Frequency table */ +extern const tRfChannelProps rfChannels[NUM_RF_CHANNELS]; + +#ifdef FEATURE_WLAN_CH_AVOID +/* Store channel safety information */ +typedef struct +{ + v_U16_t channelNumber; + v_BOOL_t isSafe; +} sapSafeChannelType; +#endif //FEATURE_WLAN_CH_AVOID + +#ifdef WLAN_FEATURE_MBSSID +void sapCleanupChannelList(v_PVOID_t sapContext); +#else +void sapCleanupChannelList(void); +#endif + +void sapCleanupAllChannelList(void); + +/*========================================================================== + FUNCTION WLANSAP_Set_WpsIe + + DESCRIPTION + This api function provides for Ap App/HDD to set WPS IE. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pWPSIE: tSap_WPSIE structure for the station + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Set_WpsIe +( + v_PVOID_t pvosGCtx, + tSap_WPSIE *pWPSIe +); + +/*========================================================================== + FUNCTION WLANSAP_Update_WpsIe + + DESCRIPTION + This api function provides for Ap App/HDD to start WPS session. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Update_WpsIe +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_Stop_Wps + + DESCRIPTION + This api function provides for Ap App/HDD to stop WPS session. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Stop_Wps +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_Get_WPS_State + + DESCRIPTION + This api function provides for Ap App/HDD to get WPS state. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure + + OUT +pbWPSState: Pointer to variable to indicate if it is in WPS Registration state + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Get_WPS_State +( + v_PVOID_t pvosGCtx, + v_BOOL_t * pbWPSState +); + +/*---------------------------------------------------------------------------- + * Opaque SAP handle Type Declaration + * -------------------------------------------------------------------------*/ + +typedef v_PVOID_t tSapHandle, *ptSapHandle; + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + FUNCTION WLANSAP_Open + + DESCRIPTION + Called at driver initialization (vos_open). SAP will initialize + all its internal resources and will wait for the call to start to + register with the other modules. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS +============================================================================*/ +#ifdef WLAN_FEATURE_MBSSID +v_PVOID_t +#else +VOS_STATUS +#endif +WLANSAP_Open +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_Start + + DESCRIPTION + Called as part of the overall start procedure (vos_start). + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + Other codes can be returned as a result of a BAL failure; + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Start +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_Stop + + DESCRIPTION + Called by vos_stop to stop operation in SAP, before close. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Stop +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_Close + + DESCRIPTION + Called by vos_close during general driver close procedure. SAP will clean up + all the internal resources. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Close +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION (*tpWLAN_SAPEventCB) + + DESCRIPTION + Implements the callback for ALL asynchronous events. + Including Events resulting from: + * Start BSS + * Stop BSS,... + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSapEvent: pointer to the union of "Sap Event" structures. This now encodes ALL event types. + Including Command Complete and Command Status + pUsrContext : pUsrContext parameter that was passed to sapStartBss + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to pSapEvent is NULL + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +typedef VOS_STATUS (*tpWLAN_SAPEventCB)( tpSap_Event pSapEvent, v_PVOID_t pUsrContext); + + + +/*========================================================================== + FUNCTION WLANSAP_getState + + DESCRIPTION + This api returns the current SAP state to the caller. + + DEPENDENCIES + + PARAMETERS + + IN + pContext : Pointer to Sap Context structure + + RETURN VALUE + Returns the SAP FSM state. +============================================================================*/ + +v_U8_t WLANSAP_getState +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_StartBss + + DESCRIPTION + This api function provides SAP FSM event eWLAN_SAP_HDD_PHYSICAL_LINK_CREATE for +starting AP BSS + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pConfig: Pointer to configuration structure passed down from HDD(HostApd for Android) +hdd_SapEventCallback: Callback function in HDD called by SAP to inform HDD about SAP results +usrDataForCallback: Parameter that will be passed back in all the SAP callback events. + + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_StartBss +( + v_PVOID_t pvosGCtx, + tpWLAN_SAPEventCB pSapEventCallback, + tsap_Config_t *pConfig, + v_PVOID_t pUsrContext +); + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/*========================================================================== + FUNCTION WLANSAP_CheckCCIntf + + DESCRIPTION Restart SAP if Concurrent Channel interfering + + DEPENDENCIES NA. + + PARAMETERS + IN + Ctx: Pointer to vos Context or Sap Context based on MBSSID + + RETURN VALUE Interference channel value + + SIDE EFFECTS +============================================================================*/ +v_U16_t WLANSAP_CheckCCIntf(v_PVOID_t Ctx); +#endif +/*========================================================================== + FUNCTION WLANSAP_SetMacACL + + DESCRIPTION + This api function provides SAP to set mac list entry in accept list as well + as deny list + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pConfig: Pointer to configuration structure passed down from + HDD(HostApd for Android) + + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMacACL +( + v_PVOID_t pvosGCtx, + tsap_Config_t *pConfig +); + +/*========================================================================== + FUNCTION WLANSAP_Stop + + DESCRIPTION + This api function provides SAP FSM event eWLAN_SAP_HDD_PHYSICAL_LINK_DISCONNECT for +stopping BSS + + DEPENDENCIES + NA. + + PARAMETERS W + + IN + pvosGCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_StopBss +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_DisassocSta + + DESCRIPTION + This api function provides for Ap App/HDD initiated disassociation of station + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx : Pointer to vos global context structure + pPeerStaMac : Mac address of the station to disassociate + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DisassocSta +( + v_PVOID_t pvosGCtx, + struct tagCsrDelStaParams *pDelStaParams +); + +/*========================================================================== + FUNCTION WLANSAP_DeauthSta + + DESCRIPTION + This api function provides for Ap App/HDD initiated deauthentication of station + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx : Pointer to vos global context structure + pDelStaParams : Pointer to parameters of the station to + deauthenticate + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DeauthSta +( + v_PVOID_t pvosGCtx, + struct tagCsrDelStaParams *pDelStaParams +); + +/*========================================================================== + FUNCTION WLANSAP_SetChannelChangeWithCsa + + DESCRIPTION + This api function does a channel change to the target channel specified + through an iwpriv. CSA IE is included in the beacons before doing a + channel change. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx : Pointer to vos global context structure + targetChannel : New target channel to change to. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetChannelChangeWithCsa(v_PVOID_t pvosGCtx, v_U32_t targetChannel); + +/*========================================================================== + FUNCTION WLANSAP_SetKeySta + + DESCRIPTION + This api function provides for Ap App/HDD to delete key for a station. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pSetKeyInfo: tCsrRoamSetKey structure for the station + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetKeySta +( + v_PVOID_t pvosGCtx, + tCsrRoamSetKey *pSetKeyInfo +); + +/*========================================================================== + FUNCTION WLANSAP_DelKeySta + + DESCRIPTION + This api function provides for Ap App/HDD to delete key for a station. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pSetKeyInfo: tCsrRoamSetKey structure for the station + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DelKeySta +( + v_PVOID_t pvosGCtx, + tCsrRoamRemoveKey *pDelKeyInfo +); + + +/*========================================================================== + FUNCTION WLANSAP_GetAssocStations + + DESCRIPTION + This api function is used to probe the list of associated stations from various modules of CORE stack + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +mod: Module from whom list of associtated stations is supposed to be probed. If an invalid module is passed +then by default VOS_MODULE_ID_PE will be probed + IN/OUT +pNoOfAssocStas:- Number of associated stations that are known to the module specified in mod parameter +pAssocStas: Pointer to list of associated stations that are known to the module specified in mod parameter +NOTE:- The memory for this list will be allocated by the caller of this API + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_GetAssocStations +( + v_PVOID_t pvosGCtx, + VOS_MODULE_ID module, + tpSap_AssocMacAddr pAssocStas +); +/*========================================================================== + FUNCTION WLANSAP_RemoveWpsSessionOverlap + + DESCRIPTION + This api function provides for Ap App/HDD to remove an entry from session session overlap info. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pRemoveMac: pointer to v_MACADDR_t for session MAC address that needs to be removed from wps session + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + VOS_STATUS_E_FAULT: Session is not dectected. The parameter is function not valid. + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_RemoveWpsSessionOverlap + +( + v_PVOID_t pvosGCtx, + v_MACADDR_t pRemoveMac +); + +/*========================================================================== + FUNCTION WLANSAP_getWpsSessionOverlap + + DESCRIPTION + This api function provides for Ap App/HDD to get WPS session overlap info. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pSessionMac: pointer to v_MACADDR_t for session MAC address +uuide: Pointer to 16 bytes array for session UUID_E + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + VOS_STATUS_E_FAULT: Overlap is dectected. The parameter is function not valid. + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_getWpsSessionOverlap +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_SetCounterMeasure + + DESCRIPTION + This api function is used to disassociate all the stations and prevent + association for any other station.Whenever Authenticator receives 2 mic failures + within 60 seconds, Authenticator will enable counter measure at SAP Layer. + Authenticator will start the 60 seconds timer. Core stack will not allow any + STA to associate till HDD disables counter meassure. Core stack shall kick out all the + STA which are currently associated and DIASSOC Event will be propogated to HDD for + each STA to clean up the HDD STA table.Once the 60 seconds timer expires, Authenticator + will disable the counter meassure at core stack. Now core stack can allow STAs to associate. + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +bEnable: If TRUE than all stations will be disassociated and no more will be allowed to associate. If FALSE than CORE +will come out of this state. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetCounterMeasure +( + v_PVOID_t pvosGCtx, + v_BOOL_t bEnable +); + +/*========================================================================== + FUNCTION WLANSap_getstationIE_information + + DESCRIPTION + This api function provides for Ap App/HDD to retrive the WPA and RSNIE of a station. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pLen : length of WPARSN elment IE where it would be copied + pBuf : buf to copy the WPARSNIe + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSap_getstationIE_information +( + v_PVOID_t pvosGCtx, + v_U32_t *pLen, + v_U8_t *pBuf +); + +/*========================================================================== + FUNCTION WLANSAP_ClearACL + + DESCRIPTION + This api function removes all the entries in both accept and deny lists. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_ClearACL +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANSAP_GetACLAcceptList + + DESCRIPTION + This api function to get ACL accept list. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pAcceptList: ACL Accept list entries + nAcceptList: Number of entries in ACL Accept list + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_GetACLAcceptList +( + v_PVOID_t pvosGCtx, + v_MACADDR_t *pAcceptList, + v_U8_t *nAcceptList +); + +/*========================================================================== + FUNCTION WLANSAP_GetACLDenyList + + DESCRIPTION + This api function to get ACL Deny list. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pAcceptList: ACL Deny list entries + nAcceptList: Number of entries in ACL Deny list + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_GetACLDenyList +( + v_PVOID_t pCtx, + v_MACADDR_t *pDenyList, + v_U8_t *nDenyList +); + +/*========================================================================== + FUNCTION WLANSAP_SetMode + + DESCRIPTION + This api is used to set mode for ACL + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMode +( + v_PVOID_t pvosGCtx, + v_U32_t mode +); + +/*========================================================================== + FUNCTION WLANSAP_GetACLMode + + DESCRIPTION + This api is used to get mode for ACL + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + mode: Current Mode of the ACL + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_GetACLMode +( + v_PVOID_t pvosGCtx, + eSapMacAddrACL *mode +); + +/*========================================================================== + FUNCTION WLANSAP_ModifyACL + + DESCRIPTION + This api function provides for Ap App/HDD to add/remove mac addresses from black/white lists (ACLs). + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx : Pointer to vos global context structure + pPeerStaMac : MAC address to be added or removed + listType : add/remove to be done on black or white list + cmd : Are we doing to add or delete a mac addr from an ACL. + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_ModifyACL +( + v_PVOID_t pvosGCtx, + v_U8_t *pPeerStaMac, + eSapACLType listType, + eSapACLCmdType cmd +); + +/*========================================================================== + FUNCTION WLANSAP_Set_WPARSNIes + + DESCRIPTION + This api function provides for Ap App/HDD to set AP WPA and RSN IE in its beacon and probe response. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pWPARSNIEs: buffer to the WPA/RSN IEs + WPARSNIEsLen: length of WPA/RSN IEs + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_Set_WPARSNIes +( + v_PVOID_t pvosGCtx, + v_U8_t *pWPARSNIEs, + v_U32_t WPARSNIEsLen +); + +/*========================================================================== + FUNCTION WLANSAP_GetStatistics + + DESCRIPTION + This api function provides for Ap App/HDD to get TL statistics for all stations of Soft AP. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + bReset: If set TL statistics will be cleared after reading + OUT + statBuf: Buffer to get the statistics + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_GetStatistics +( + v_PVOID_t pvosGCtx, + tSap_SoftapStats *statBuf, + v_BOOL_t bReset +); + +/*========================================================================== + + FUNCTION WLANSAP_SendAction + + DESCRIPTION + This api function provides to send action frame sent by upper layer. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pBuf: Pointer of the action frame to be transmitted + len: Length of the action frame + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_SendAction +( + v_PVOID_t pvosGCtx, + const tANI_U8 *pBuf, + tANI_U32 len, + tANI_U16 wait +); + +/*========================================================================== + + FUNCTION WLANSAP_RemainOnChannel + + DESCRIPTION + This api function provides to set Remain On channel on specified channel + for specified duration. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + channel: Channel on which driver has to listen + duration: Duration for which driver has to listen on specified channel + callback: Callback function to be called once Listen is done. + pContext: Context needs to be called in callback function. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_RemainOnChannel +( + v_PVOID_t pvosGCtx, + tANI_U8 channel, + tANI_U32 duration, + remainOnChanCallback callback, + void *pContext +); + +/*========================================================================== + + FUNCTION WLANSAP_CancelRemainOnChannel + + DESCRIPTION + This api cancel previous remain on channel request. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_CancelRemainOnChannel +( + v_PVOID_t pvosGCtx +); + + +/*========================================================================== + + FUNCTION WLANSAP_RegisterMgmtFrame + + DESCRIPTION + HDD use this API to register specified type of frame with CORE stack. + On receiving such kind of frame CORE stack should pass this frame to HDD + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + frameType: frameType that needs to be registered with PE. + matchData: Data pointer which should be matched after frame type is matched. + matchLen: Length of the matchData + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_RegisterMgmtFrame +( + v_PVOID_t pvosGCtx, + tANI_U16 frameType, + tANI_U8* matchData, + tANI_U16 matchLen +); + +/*========================================================================== + + FUNCTION WLANSAP_DeRegisterMgmtFrame + + DESCRIPTION + This API is used to deregister previously registered frame. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + frameType: frameType that needs to be De-registered with PE. + matchData: Data pointer which should be matched after frame type is matched. + matchLen: Length of the matchData + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_DeRegisterMgmtFrame +( + v_PVOID_t pvosGCtx, + tANI_U16 frameType, + tANI_U8* matchData, + tANI_U16 matchLen +); + +/*========================================================================== + + FUNCTION WLANSAP_ChannelChangeRequest + DESCRIPTION + This API is used to send an Indication to SME/PE to change the + current operating channel to a different target channel. + + The Channel change will be issued by SAP under the following + scenarios. + 1. A radar indication is received during SAP CAC WAIT STATE and + channel change is required. + 2. A radar indication is received during SAP STARTED STATE and + channel change is required. + + DEPENDENCIES + NA. + +PARAMETERS + +IN + pvosGCtx: Pointer to vos global context structure + TargetChannel: New target channel for channel change. + +RETURN VALUE + The VOS_STATUS code associated with performing the operation + +VOS_STATUS_SUCCESS: Success + +SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_ChannelChangeRequest(v_PVOID_t pvosGCtx, tANI_U8 tArgetChannel); + +/*========================================================================== + + FUNCTION WLANSAP_StartBeaconReq + DESCRIPTION + This API is used to send an Indication to SME/PE to start + beaconing on the current operating channel. + + Brief:When SAP is started on DFS channel and when ADD BSS RESP is received + LIM temporarily holds off Beaconing for SAP to do CAC WAIT. When + CAC WAIT is done SAP resumes the Beacon Tx by sending a start beacon + request to LIM. + + DEPENDENCIES + NA. + +PARAMETERS + +IN + pvosGCtx: Pointer to vos global context structure + +RETURN VALUE + The VOS_STATUS code associated with performing the operation + +VOS_STATUS_SUCCESS: Success + +SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_StartBeaconReq(v_PVOID_t pSapCtx); + +/*========================================================================== + FUNCTION WLANSAP_DfsSendCSAIeRequest + + DESCRIPTION + This API is used to send channel switch announcement request to PE + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DfsSendCSAIeRequest(v_PVOID_t pSapCtx); + +/*========================================================================== + FUNCTION WLANSAP_Get_Dfs_Ignore_CAC + + DESCRIPTION + This API is used to get ignore_cac flag. + + DEPENDENCIES + NA. + + PARAMETERS + IN + pvosGCtx: Pointer to vos global context structure + + PARAMETERS + OUT + pIgnore_cac: pointer to variable + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANSAP_Get_Dfs_Ignore_CAC(tHalHandle hHal, v_U8_t *pIgnore_cac); + + +/*========================================================================== + FUNCTION WLANSAP_Set_Dfs_Ignore_CAC + + DESCRIPTION + This API is used to set ignore_cac flag, used for ignoring the CAC operation for DFS channel. + If the flag set to 1 or TRUE then it will avoid CAC. + + DEPENDENCIES + NA. + + PARAMETERS + IN + pvosGCtx: Pointer to vos global context structure + + PARAMETERS + IN + ignore_cac: value to be set + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANSAP_Set_Dfs_Ignore_CAC(tHalHandle hHal, v_U8_t ignore_cac); + +/*========================================================================== + FUNCTION WLANSAP_set_Dfs_Restrict_JapanW53 + + DESCRIPTION + This API is used to enable or disable Japan W53 Band + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + disable_Dfs_JapanW3 :Indicates if Japan W53 is disabled when set to 1 + Indicates if Japan W53 is enabled when set to 0 + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_set_Dfs_Restrict_JapanW53(tHalHandle hHal, v_U8_t disable_Dfs_JapanW3); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * wlan_sap_set_channel_avoidance() - sets sap mcc channel avoidance ini param + * @hal: hal handle + * @sap_channel_avoidance: ini parameter value + * + * sets sap mcc channel avoidance ini param, to be called in sap_start + * + * Return: success of failure of operation + */ +VOS_STATUS +wlan_sap_set_channel_avoidance(tHalHandle hal, bool sap_channel_avoidance); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/*========================================================================== + FUNCTION WLANSAP_set_Dfs_Preferred_Channel_location + + DESCRIPTION + This API is used to set sap preferred channels location + to resetrict the DFS random channel selection algorithm + either Indoor/Outdoor channels only. + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + dfs_Preferred_Channels_location : + 0 - Indicates No preferred channel location restrictions + 1 - Indicates SAP Indoor Channels operation only. + 2 - Indicates SAP Outdoor Channels operation only. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_set_Dfs_Preferred_Channel_location(tHalHandle hHal, + v_U8_t dfs_Preferred_Channels_location); + +/*========================================================================== + FUNCTION WLANSAP_Set_Dfs_Target_Chnl + + DESCRIPTION + This API is used to set next target chnl as provided channel. + you can provide any valid channel to this API. + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal: Pointer to HAL + + PARAMETERS + IN + target_channel: target channel number + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANSAP_Set_Dfs_Target_Chnl(tHalHandle hHal, + v_U8_t target_channel); + + + +/*========================================================================== + FUNCTION wlan_sap_get_vht_ch_width + + DESCRIPTION Returns the SAP VHT channel width. + + DEPENDENCIES NA. + + PARAMETERS + IN + ctx: Pointer to vos Context or Sap Context based on MBSSID + + RETURN VALUE VHT channnel width + + SIDE EFFECTS +============================================================================*/ +v_U32_t wlan_sap_get_vht_ch_width(v_PVOID_t ctx); + +/*========================================================================== + FUNCTION wlan_sap_set_vht_ch_width + + DESCRIPTION Sets the SAP VHT channel width. + + DEPENDENCIES NA. + + PARAMETERS + IN + ctx: Pointer to vos Context or Sap Context based on MBSSID + vht_channel_width - VHT channel width + + RETURN VALUE NONE + + SIDE EFFECTS +============================================================================*/ +void wlan_sap_set_vht_ch_width(v_PVOID_t ctx, v_U32_t vht_channel_width); + +/*========================================================================== + FUNCTION WLANSAP_UpdateSapConfigAddIE + + DESCRIPTION + This API is used to set sap config parameter. + + DEPENDENCIES + NA. + + PARAMETERS + IN OUT + pConfig: Pointer to sap config + + PARAMETERS + IN + additionIEBuffer - buffer containing addition IE from hostapd + + PARAMETERS + IN + additionIELength - length of buffer + + PARAMETERS + IN + updateType - Type of buffer + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS WLANSAP_UpdateSapConfigAddIE(tsap_Config_t *pConfig, + const tANI_U8 *pAdditionIEBuffer, + tANI_U16 additionIELength, + eUpdateIEsType updateType); + +/*========================================================================== + FUNCTION WLANSAP_ResetSapConfigAddIE + + DESCRIPTION + This API is used to reset and clear the buffer in sap config. + + DEPENDENCIES + NA. + + PARAMETERS + IN OUT + pConfig: Pointer to sap config + PARAMETERS + IN + updateType: type buffer + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANSAP_ResetSapConfigAddIE(tsap_Config_t *pConfig, + eUpdateIEsType updateType); + +/*========================================================================== +FUNCTION WLANSAP_extend_to_acs_range + +DESCRIPTION Function extends give channel range to consider ACS chan bonding + +DEPENDENCIES PARAMETERS + +IN /OUT +*startChannelNum : ACS extend start ch +*endChannelNum : ACS extended End ch +*bandStartChannel: Band start ch +*bandEndChannel : Band end ch + +RETURN VALUE NONE + +SIDE EFFECTS +============================================================================*/ +v_VOID_t WLANSAP_extend_to_acs_range(v_U8_t *startChannelNum, + v_U8_t *endChannelNum, + v_U8_t *bandStartChannel, + v_U8_t *bandEndChannel); + +/*========================================================================== + FUNCTION WLANSAP_Get_DfsNol + + DESCRIPTION + This API is used to dump the dfs nol + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Get_DfsNol(v_PVOID_t pSapCtx); + +/*========================================================================== + FUNCTION WLANSAP_Set_DfsNol + + DESCRIPTION + This API is used to set the dfs nol + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + conf: set type + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Set_DfsNol(v_PVOID_t pSapCtx, eSapDfsNolType conf); + +/*========================================================================== + FUNCTION WLANSAP_PopulateDelStaParams + + DESCRIPTION + This API is used to populate del station parameters + DEPENDENCIES + NA. + + PARAMETERS + IN + mac: pointer to peer mac address. + reason_code: Reason code for the disassoc/deauth. + subtype: subtype points to either disassoc/deauth frame. + pDelStaParams: address where parameters to be populated. + + RETURN VALUE NONE + + SIDE EFFECTS +============================================================================*/ + +void WLANSAP_PopulateDelStaParams(const v_U8_t *mac, + v_U16_t reason_code, + v_U8_t subtype, + struct tagCsrDelStaParams *pDelStaParams); + +/*========================================================================== + FUNCTION WLANSAP_ACS_CHSelect + + DESCRIPTION + This api function provides ACS selection for BSS + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pConfig: Pointer to configuration structure passed down from HDD + pACSEventCallback: Callback function in HDD called by SAP to inform + HDD about channel section result + usrDataForCallback: Parameter that will be passed back in all the + SAP callback events. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_ACS_CHSelect(v_PVOID_t pvosGCtx, + tpWLAN_SAPEventCB pACSEventCallback, + tsap_Config_t *pConfig, + v_PVOID_t pUsrContext); + +eCsrPhyMode +wlansap_get_phymode(v_PVOID_t pctx); +#ifdef __cplusplus + } +#endif + + +#endif /* #ifndef WLAN_QCT_WLANSAP_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c new file mode 100644 index 000000000000..3a7f689f1284 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c @@ -0,0 +1,1417 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + s a p A p i L i n k C n t l . C + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP modules + Link Control functions. + + The functions externalized by this module are to be called ONLY by other + WLAN modules (HDD) + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header: /cygdrive/c/Dropbox/M7201JSDCAAPAD52240B/WM/platform/msm7200/Src/Drivers/SD/ClientDrivers/WLAN/QCT_SAP_PAL/CORE/SAP/src/sapApiLinkCntl.c,v 1.7 2008/12/18 19:44:11 jzmuda Exp jzmuda $$DateTime$$Author: jzmuda $ + + + when who what, where, why +---------- --- -------------------------------------------------------- +2010-03-15 Created module + +===========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "vos_trace.h" +// Pick up the CSR callback definition +#include "csrApi.h" +#include "sme_Api.h" +// SAP Internal API header file +#include "sapInternal.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define SAP_DEBUG + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Function Declarations and Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Externalized Function Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + FUNCTION WLANSAP_ScanCallback() + + DESCRIPTION + Callback for Scan (scan results) Events + + DEPENDENCIES + NA. + + PARAMETERS + + IN + tHalHandle : tHalHandle passed in with the scan request + *pContext : The second context pass in for the caller (sapContext) + scanID : scanID got after the scan + status : Status of scan -success, failure or abort + + RETURN VALUE + The eHalStatus code associated with performing the operation + + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +eHalStatus +WLANSAP_ScanCallback +( + tHalHandle halHandle, + void *pContext, /* Opaque SAP handle */ + v_U8_t sessionId, + v_U32_t scanID, + eCsrScanStatus scanStatus +) +{ + tScanResultHandle pResult = NULL; + eHalStatus scanGetResultStatus = eHAL_STATUS_FAILURE; + ptSapContext psapContext = (ptSapContext)pContext; + tWLAN_SAPEvent sapEvent; /* State machine event */ + v_U8_t operChannel = 0; + VOS_STATUS sapstatus; + tpAniSirGlobal pMac = NULL; +#ifdef SOFTAP_CHANNEL_RANGE + v_U32_t event; +#endif + + if (NULL == halHandle) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return eHAL_STATUS_FAILURE; + } + else + { + pMac = PMAC_STRUCT( halHandle ); + } + + if (psapContext->sapsMachine == eSAP_DISCONNECTED) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "In %s BSS already stopped", __func__); + return eHAL_STATUS_FAILURE; + } + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, before switch on scanStatus = %d", __func__, scanStatus); + + switch (scanStatus) + { + case eCSR_SCAN_SUCCESS: + // sapScanCompleteCallback with eCSR_SCAN_SUCCESS + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, CSR scanStatus = %s (%d)", __func__, "eCSR_SCAN_SUCCESS", scanStatus); + + // Get scan results, Run channel selection algorithm, select channel and keep in pSapContext->Channel + scanGetResultStatus = sme_ScanGetResult(halHandle, psapContext->sessionId, NULL, &pResult); + + event = eSAP_MAC_SCAN_COMPLETE; + + if ((scanGetResultStatus != eHAL_STATUS_SUCCESS)&& (scanGetResultStatus != eHAL_STATUS_E_NULL_VALUE)) + { + // No scan results + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, Get scan result failed! ret = %d", + __func__, scanGetResultStatus); + break; + } +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (scanID != 0) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Sending ACS Scan skip event", __func__); + sapSignalHDDevent(psapContext, NULL, + eSAP_ACS_SCAN_SUCCESS_EVENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + } else + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: ACS scan id: %d (skipped ACS SCAN)", __func__, scanID); +#endif + operChannel = sapSelectChannel(halHandle, psapContext, pResult); + + sme_ScanResultPurge(halHandle, pResult); + break; + + default: + event = eSAP_CHANNEL_SELECTION_FAILED; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, CSR scanStatus = %s (%d)", __func__, "eCSR_SCAN_ABORT/FAILURE", scanStatus); + } + + if (operChannel == SAP_CHANNEL_NOT_SELECTED) +#ifdef SOFTAP_CHANNEL_RANGE + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: No suitable channel selected due to DFS, LTE-Coex and " + "Concurrent mode restrictions", __func__); + + if ( eCSR_BAND_ALL == psapContext->scanBandPreference || + psapContext->allBandScanned == eSAP_TRUE) + { + psapContext->sapsMachine = eSAP_CH_SELECT; + event = eSAP_CHANNEL_SELECTION_FAILED; + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Has scan band preference", + __func__); + if (eCSR_BAND_24 == psapContext->currentPreferredBand) + psapContext->currentPreferredBand = eCSR_BAND_5G; + else + psapContext->currentPreferredBand = eCSR_BAND_24; + + psapContext->allBandScanned = eSAP_TRUE; + //go back to DISCONNECT state, scan next band + psapContext->sapsMachine = eSAP_DISCONNECTED; + event = eSAP_CHANNEL_SELECTION_RETRY; + } + } +#else + psapContext->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#endif + else + { + psapContext->channel = operChannel; + } + + sme_SelectCBMode(halHandle, + psapContext->csrRoamProfile.phyMode, + psapContext->channel, psapContext->secondary_ch, + &psapContext->vht_channel_width, + psapContext->ch_width_orig); +#ifdef SOFTAP_CHANNEL_RANGE + if(psapContext->channelList != NULL) + { + /* Always free up the memory for channel selection whatever + * the result */ + vos_mem_free(psapContext->channelList); + psapContext->channelList = NULL; + } +#endif + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Channel selected = %d", __func__, psapContext->channel); + + /* Fill in the event structure */ + sapEvent.event = event; + sapEvent.params = 0; // pCsrRoamInfo; + sapEvent.u1 = scanStatus; // roamstatus + sapEvent.u2 = 0; // roamResult + + /* Handle event */ + sapstatus = sapFsm(psapContext, &sapEvent); + + return sapstatus; +}// WLANSAP_ScanCallback + +/** + * sap_config_acs_result : Generate ACS result params based on ch constraints + * @sap_ctx: pointer to SAP context data struct + * @hal: HAL Handle pointer + * + * This function calculates the ACS result params: ht sec channel, vht channel + * information and channel bonding based on selected ACS channel. + * + * Return: None + */ + +void sap_config_acs_result(tHalHandle hal, ptSapContext sap_ctx, uint32_t sec_ch) +{ + uint32_t channel = sap_ctx->acs_cfg->pri_ch; + uint8_t cb_mode = eCSR_INI_SINGLE_CHANNEL_CENTERED; + + sap_ctx->acs_cfg->vht_seg0_center_ch = 0; + sap_ctx->acs_cfg->vht_seg1_center_ch = 0; + sap_ctx->acs_cfg->ht_sec_ch = 0; + + cb_mode = sme_SelectCBMode(hal, sap_ctx->csrRoamProfile.phyMode, + channel, sec_ch, + &sap_ctx->acs_cfg->ch_width, + sap_ctx->acs_cfg->ch_width); + + if (cb_mode == eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY) { + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch + 4; + } else if (cb_mode == eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY) { + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch - 4; + } else if (cb_mode == eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW) { + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch + 4; + sap_ctx->acs_cfg->vht_seg0_center_ch = sap_ctx->acs_cfg->pri_ch + + 6; + } else if (cb_mode == eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW) { + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch - 4; + sap_ctx->acs_cfg->vht_seg0_center_ch = sap_ctx->acs_cfg->pri_ch + + 2; + } else if (cb_mode == eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH) { + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch + 4; + sap_ctx->acs_cfg->vht_seg0_center_ch = sap_ctx->acs_cfg->pri_ch + - 2; + } else if (cb_mode == eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH) { + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch - 4; + sap_ctx->acs_cfg->vht_seg0_center_ch = sap_ctx->acs_cfg->pri_ch + - 6; + } + +} + + + +/*========================================================================== + + FUNCTION WLANSAP_PreStartBssAcsScanCallback() + + DESCRIPTION + Callback for Scan (scan results) Events + + DEPENDENCIES + NA. + + PARAMETERS + + IN + tHalHandle: the tHalHandle passed in with the scan request + *p2: the second context pass in for the caller, opaque sap Handle here + scanID: + sessionId: Session identifier + status: Status of scan -success, failure or abort + + RETURN VALUE + The eHalStatus code associated with performing the operation + + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS + +============================================================================*/ +eHalStatus +WLANSAP_PreStartBssAcsScanCallback +( + tHalHandle halHandle, + void *pContext, + v_U8_t sessionId, + v_U32_t scanID, + eCsrScanStatus scanStatus +) +{ + tScanResultHandle pResult = NULL; + eHalStatus scanGetResultStatus = eHAL_STATUS_FAILURE; + ptSapContext psapContext = (ptSapContext)pContext; + v_U8_t operChannel = 0; + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if ( eCSR_SCAN_SUCCESS == scanStatus) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR scanStatus = %s (%d)"), + "eCSR_SCAN_SUCCESS", scanStatus); + /* + * Now do + * 1. Get scan results + * 2. Run channel selection algorithm + * select channel and store in pSapContext->Channel + */ + scanGetResultStatus = sme_ScanGetResult(halHandle, + psapContext->sessionId, + NULL, &pResult); + + if ((scanGetResultStatus != eHAL_STATUS_SUCCESS) && + (scanGetResultStatus != eHAL_STATUS_E_NULL_VALUE)) + { + /* + * No scan results + * So, set the operation channel not selected + * to allow the default channel to be set when + * reporting to HDD + */ + operChannel = SAP_CHANNEL_NOT_SELECTED; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Get scan result failed! ret = %d"), + scanGetResultStatus); + } + else + { +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (scanID != 0) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Sending ACS Scan skip event", __func__); + sapSignalHDDevent(psapContext, NULL, + eSAP_ACS_SCAN_SUCCESS_EVENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: ACS scan id: %d (skipped ACS SCAN)", + __func__, scanID); + } +#endif + operChannel = sapSelectChannel(halHandle, psapContext, pResult); + + sme_ScanResultPurge(halHandle, pResult); + } + + if (operChannel == SAP_CHANNEL_NOT_SELECTED) +#ifdef SOFTAP_CHANNEL_RANGE + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("No suitable channel selected")); + + if ( eCSR_BAND_ALL == psapContext->scanBandPreference || + psapContext->allBandScanned == eSAP_TRUE) + { + halStatus = sapSignalHDDevent(psapContext, NULL, + eSAP_ACS_CHANNEL_SELECTED, + (v_PVOID_t) eSAP_STATUS_FAILURE); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("Has scan band preference")); + if (eCSR_BAND_24 == psapContext->currentPreferredBand) + psapContext->currentPreferredBand = eCSR_BAND_5G; + else + psapContext->currentPreferredBand = eCSR_BAND_24; + + psapContext->allBandScanned = eSAP_TRUE; + /* + * Go back to scanning, scan next band + * + * 1. No need to pass the second parameter + * as the SAP state machine is not started yet + * and there is no need for any event posting. + * + * 2. Set third parameter to TRUE to indicate the + * channel selection function to register a + * different scan callback fucntion to process + * the results pre start BSS. + */ + vosStatus = sapGotoChannelSel(psapContext, NULL, VOS_TRUE); + if (VOS_STATUS_SUCCESS == vosStatus) + { + halStatus = eHAL_STATUS_SUCCESS; + } + return halStatus; + } + } +#else + psapContext->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#endif + else + { + /* + * Valid Channel Found from scan results. + */ + psapContext->acs_cfg->pri_ch = operChannel; + psapContext->channel = operChannel; + sap_config_acs_result(halHandle, psapContext, + psapContext->acs_cfg->ht_sec_ch); + } + +#ifdef SOFTAP_CHANNEL_RANGE + if(psapContext->channelList != NULL) + { + /* + * Always free up the memory for + * channel selection whatever + * the result + */ + vos_mem_free(psapContext->channelList); + psapContext->channelList = NULL; + } +#endif + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Channel selected = %d"), psapContext->channel); + + /* + * By now, Channel should be selected + * post a message to HDD to indicate + * the ACS channel selection complete. + */ + halStatus = sapSignalHDDevent(psapContext, NULL, + eSAP_ACS_CHANNEL_SELECTED, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("CSR scanStatus = %s (%d), choose default channel"), + "eCSR_SCAN_ABORT/FAILURE", scanStatus ); +#ifdef SOFTAP_CHANNEL_RANGE + if(psapContext->acs_cfg->hw_mode == eCSR_DOT11_MODE_11a) + psapContext->channel = SAP_DEFAULT_5GHZ_CHANNEL; + else + psapContext->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#else + psapContext->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#endif + halStatus = sapSignalHDDevent(psapContext, NULL, + eSAP_ACS_CHANNEL_SELECTED, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + } + + if(eHAL_STATUS_SUCCESS != sme_CloseSession(halHandle, + psapContext->sessionId, NULL, NULL)) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s CloseSession error", __func__); + } else { + psapContext->isScanSessionOpen = eSAP_FALSE; + } + psapContext->sessionId = 0xff; + + return halStatus; +} + +/*========================================================================== + FUNCTION WLANSAP_RoamCallback() + + DESCRIPTION + Callback for Roam (connection status) Events + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pContext : pContext passed in with the roam request + pCsrRoamInfo : Pointer to a tCsrRoamInfo, see definition of eRoamCmdStatus and + eRoamCmdResult: For detail valid members. It may be NULL + roamId : To identify the callback related roam request. 0 means unsolicited + roamStatus : Flag indicating the status of the callback + roamResult : Result + + RETURN VALUE + The eHalStatus code associated with performing the operation + + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +eHalStatus +WLANSAP_RoamCallback +( + void *pContext, /* Opaque SAP handle */ + tCsrRoamInfo *pCsrRoamInfo, + v_U32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult +) +{ + /* sapContext value */ + ptSapContext sapContext = (ptSapContext) pContext; + tWLAN_SAPEvent sapEvent; /* State machine event */ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal pMac = NULL; + tANI_U8 dfs_beacon_start_req = 0; + + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + halStatus = eHAL_STATUS_FAILED_ALLOC; + return halStatus; + } + else + { + pMac = PMAC_STRUCT( hHal ); + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("before switch on roamStatus = %d"), + roamStatus); + switch(roamStatus) + { + case eCSR_ROAM_SESSION_OPENED: + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Before switch on roamStatus = %d"), + roamStatus); + sapContext->isSapSessionOpen = eSAP_TRUE; + halStatus = sme_RoamConnect(hHal, sapContext->sessionId, + &sapContext->csrRoamProfile, + &sapContext->csrRoamId); + break; + } + + case eCSR_ROAM_INFRA_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_INFRA_IND", roamStatus); + if(roamResult == eCSR_ROAM_RESULT_INFRA_START_FAILED) + { + /* Fill in the event structure */ + sapEvent.event = eSAP_MAC_START_FAILS; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = roamStatus; + sapEvent.u2 = roamResult; + + /* Handle event */ + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + break; + + case eCSR_ROAM_LOSTLINK: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_LOSTLINK", roamStatus); + break; + + case eCSR_ROAM_MIC_ERROR_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_MIC_ERROR_IND", roamStatus); + break; + + case eCSR_ROAM_SET_KEY_COMPLETE: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_SET_KEY_COMPLETE", roamStatus); + if (roamResult == eCSR_ROAM_RESULT_FAILURE ) + { + /* Format the SET KEY complete information pass to HDD... */ + sapSignalHDDevent(sapContext, pCsrRoamInfo, eSAP_STA_SET_KEY_EVENT,(v_PVOID_t) eSAP_STATUS_FAILURE); + } + break; + + case eCSR_ROAM_REMOVE_KEY_COMPLETE: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_REMOVE_KEY_COMPLETE", roamStatus); + if (roamResult == eCSR_ROAM_RESULT_FAILURE ) + { + /* Format the SET KEY complete information pass to HDD... */ + sapSignalHDDevent(sapContext, pCsrRoamInfo, eSAP_STA_DEL_KEY_EVENT, (v_PVOID_t)eSAP_STATUS_FAILURE); + } + break; + + case eCSR_ROAM_ASSOCIATION_COMPLETION: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_ASSOCIATION_COMPLETION", roamStatus); + if (roamResult == eCSR_ROAM_RESULT_FAILURE ) + { + /* Format the SET KEY complete information pass to HDD... */ + sapSignalHDDevent(sapContext, pCsrRoamInfo, eSAP_STA_REASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_FAILURE); + } + break; + + case eCSR_ROAM_DISASSOCIATED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_DISASSOCIATED", roamStatus); + if (roamResult == eCSR_ROAM_RESULT_MIC_FAILURE) + { + /* Format the MIC failure event to return... */ + sapSignalHDDevent(sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) eSAP_STATUS_FAILURE); + } + break; + + case eCSR_ROAM_WPS_PBC_PROBE_REQ_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_WPS_PBC_PROBE_REQ_IND", roamStatus); + break; + + case eCSR_ROAM_INDICATE_MGMT_FRAME: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_INDICATE_MGMT_FRAME", roamStatus); + sapSignalHDDevent(sapContext, pCsrRoamInfo, + eSAP_INDICATE_MGMT_FRAME, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_REMAIN_CHAN_READY: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_REMAIN_CHAN_READY", roamStatus); + sapSignalHDDevent(sapContext, pCsrRoamInfo, + eSAP_REMAIN_CHAN_READY, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_SEND_ACTION_CNF: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_SEND_ACTION_CNF", roamStatus); + sapSignalHDDevent(sapContext, pCsrRoamInfo, + eSAP_SEND_ACTION_CNF, + (v_PVOID_t)((eSapStatus)((roamResult == eCSR_ROAM_RESULT_NONE) + ? eSAP_STATUS_SUCCESS : eSAP_STATUS_FAILURE))); + break; + + case eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamStatus = %s (%d)"), + "eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS", roamStatus); + sapSignalHDDevent(sapContext, pCsrRoamInfo, + eSAP_DISCONNECT_ALL_P2P_CLIENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS ); + break; + + case eCSR_ROAM_SEND_P2P_STOP_BSS: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Received stopbss")); + sapSignalHDDevent(sapContext, pCsrRoamInfo, + eSAP_MAC_TRIG_STOP_BSS_EVENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS ); + break; + + case eCSR_ROAM_DFS_RADAR_IND: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Received Radar Indication")); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Indicate eSAP_DFS_RADAR_DETECT to HDD"); + sapSignalHDDevent(sapContext, NULL, eSAP_DFS_RADAR_DETECT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + /* sync to latest DFS-NOL */ + sapSignalHDDevent(sapContext, NULL, eSAP_DFS_NOL_GET, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + pMac->sap.SapDfsInfo.target_channel = + sapIndicateRadar(sapContext, &pCsrRoamInfo->dfs_event); + + /* if there is an assigned next channel hopping */ + if (0 < pMac->sap.SapDfsInfo.user_provided_target_channel) + { + pMac->sap.SapDfsInfo.target_channel = + pMac->sap.SapDfsInfo.user_provided_target_channel; + pMac->sap.SapDfsInfo.user_provided_target_channel = 0; + } + + if (pMac->sap.SapDfsInfo.target_channel == 0) { + /* No available channel found */ + v_U8_t intf; + /* Issue stopbss for each sapctx */ + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext pSapContext; + + if (((VOS_STA_SAP_MODE == + pMac->sap.sapCtxList[intf].sapPersona) || + (VOS_P2P_GO_MODE == + pMac->sap.sapCtxList[intf].sapPersona)) && + pMac->sap.sapCtxList[intf].pSapContext != NULL ) + { + pSapContext = pMac->sap.sapCtxList[intf].pSapContext; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_ERROR, + "sapdfs: no available channel for sapctx[%p], StopBss", + pSapContext); + + WLANSAP_StopBss(pSapContext); + } + } + break; + } + + pMac->sap.SapDfsInfo.cac_state = eSAP_DFS_DO_NOT_SKIP_CAC; + sap_CacResetNotify(hHal); + + /* set DFS-NOL back to keep it update-to-date in CNSS */ + sapSignalHDDevent(sapContext, NULL, eSAP_DFS_NOL_SET, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + break; + + case eCSR_ROAM_DFS_CHAN_SW_NOTIFY: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Received Chan Sw Update Notification", __func__); + break; + + case eCSR_ROAM_SET_CHANNEL_RSP: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Received set channel response", __func__); + break; + case eCSR_ROAM_EXT_CHG_CHNL_IND: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Received set channel Indication", __func__); + break; + default: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("CSR roamStatus not handled roamStatus = %s (%d)"), + get_eRoamCmdStatus_str(roamStatus), roamStatus); + break; + + } + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Before switch on roamResult = %d"), roamResult); + switch (roamResult) + { + case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL( "CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND", + roamResult); + sapContext->nStaWPARSnReqIeLength = pCsrRoamInfo->rsnIELen; + + if(sapContext->nStaWPARSnReqIeLength) + vos_mem_copy( sapContext->pStaWpaRsnReqIE, + pCsrRoamInfo->prsnIE, sapContext->nStaWPARSnReqIeLength); + +#ifdef FEATURE_WLAN_WAPI + sapContext->nStaWAPIReqIeLength = pCsrRoamInfo->wapiIELen; + + if(sapContext->nStaWAPIReqIeLength) + vos_mem_copy( sapContext->pStaWapiReqIE, + pCsrRoamInfo->pwapiIE, sapContext->nStaWAPIReqIeLength); +#endif + sapContext->nStaAddIeLength = pCsrRoamInfo->addIELen; + + if(sapContext->nStaAddIeLength) + vos_mem_copy( sapContext->pStaAddIE, + pCsrRoamInfo->paddIE, sapContext->nStaAddIeLength); + + sapContext->SapQosCfg.WmmIsEnabled = pCsrRoamInfo->wmmEnabledSta; + // MAC filtering + vosStatus = sapIsPeerMacAllowed(sapContext, (v_U8_t *)pCsrRoamInfo->peerMac); + + if ( VOS_STATUS_SUCCESS == vosStatus ) + { + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_ASSOC_IND, (v_PVOID_t)eSAP_STATUS_SUCCESS); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("CSR roamResult = (%d) MAC (" + MAC_ADDRESS_STR") fail"), + roamResult, + MAC_ADDR_ARRAY(pCsrRoamInfo->peerMac)); + halStatus = eHAL_STATUS_FAILURE; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + FL("CSR roamResult = (%d) MAC (" + MAC_ADDRESS_STR") not allowed"), + roamResult, + MAC_ADDR_ARRAY(pCsrRoamInfo->peerMac)); + halStatus = eHAL_STATUS_FAILURE; + } + + break; + + case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF", + roamResult); + + sapContext->nStaWPARSnReqIeLength = pCsrRoamInfo->rsnIELen; + if (sapContext->nStaWPARSnReqIeLength) + vos_mem_copy( sapContext->pStaWpaRsnReqIE, + pCsrRoamInfo->prsnIE, sapContext->nStaWPARSnReqIeLength); + + sapContext->nStaAddIeLength = pCsrRoamInfo->addIELen; + if(sapContext->nStaAddIeLength) + vos_mem_copy( sapContext->pStaAddIE, + pCsrRoamInfo->paddIE, sapContext->nStaAddIeLength); + + sapContext->SapQosCfg.WmmIsEnabled = pCsrRoamInfo->wmmEnabledSta; + /* Fill in the event structure */ + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_ASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_DISASSOC_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_DISASSOC_IND", + roamResult); + /* Fill in the event structure */ + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_DISASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_DEAUTH_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_DEAUTH_IND", + roamResult); + /* Fill in the event structure */ + //TODO: we will use the same event inorder to inform HDD to disassociate the station + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_DISASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_MIC_ERROR_GROUP: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_MIC_ERROR_GROUP", + roamResult); + /* Fill in the event structure */ + //TODO: support for group key MIC failure event to be handled + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) NULL); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_MIC_ERROR_UNICAST: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_MIC_ERROR_UNICAST", + roamResult); + /* Fill in the event structure */ + //TODO: support for unicast key MIC failure event to be handled + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_MIC_FAILURE_EVENT,(v_PVOID_t) NULL); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_AUTHENTICATED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_AUTHENTICATED", + roamResult); + /* Fill in the event structure */ + sapSignalHDDevent( sapContext, pCsrRoamInfo,eSAP_STA_SET_KEY_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_ASSOCIATED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_ASSOCIATED", + roamResult); + /* Fill in the event structure */ + sapSignalHDDevent( sapContext, pCsrRoamInfo,eSAP_STA_REASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + break; + + case eCSR_ROAM_RESULT_INFRA_STARTED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_INFRA_STARTED", + roamResult); + + /* In the current implementation, hostapd is not aware that + * drive will support DFS. Hence, driver should inform + * eSAP_MAC_START_BSS_SUCCESS to upper layers and then perform + * CAC underneath + */ + sapEvent.event = eSAP_MAC_START_BSS_SUCCESS; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = roamStatus; + sapEvent.u2 = roamResult; + + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_INFRA_STOPPED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_INFRA_STOPPED", + roamResult); + /* Fill in the event structure */ + sapEvent.event = eSAP_MAC_READY_FOR_CONNECTIONS; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = roamStatus; + sapEvent.u2 = roamResult; + + /* Handle event */ + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND", + roamResult); + /* Fill in the event structure */ + //TODO: support for group key MIC failure event to be handled + vosStatus = sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_WPS_PBC_PROBE_REQ_EVENT,(v_PVOID_t) NULL); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + + case eCSR_ROAM_RESULT_FORCED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_FORCED", + roamResult); + //This event can be used to inform hdd about user triggered disassoc event + /* Fill in the event structure */ + sapSignalHDDevent( sapContext, pCsrRoamInfo, eSAP_STA_DISASSOC_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + break; + + case eCSR_ROAM_RESULT_NONE: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_NONE", + roamResult); + //This event can be used to inform hdd about user triggered disassoc event + /* Fill in the event structure */ + if ( roamStatus == eCSR_ROAM_SET_KEY_COMPLETE) + { + sapSignalHDDevent( sapContext, pCsrRoamInfo,eSAP_STA_SET_KEY_EVENT,(v_PVOID_t) eSAP_STATUS_SUCCESS); + } + else if (roamStatus == eCSR_ROAM_REMOVE_KEY_COMPLETE ) + { + sapSignalHDDevent( sapContext, pCsrRoamInfo,eSAP_STA_DEL_KEY_EVENT,(v_PVOID_t) eSAP_STATUS_SUCCESS); + } + break; + + case eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CSR roamResult = %s (%d)"), + "eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED", + roamResult); + /* Fill in the event structure */ + vosStatus = sapSignalHDDevent(sapContext, pCsrRoamInfo, eSAP_MAX_ASSOC_EXCEEDED, (v_PVOID_t)NULL); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + + break; + + case eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND: + if (eSAP_DFS_CAC_WAIT == sapContext->sapsMachine) + { + if (sapContext->csrRoamProfile.disableDFSChSwitch) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "sapdfs: DFS channel switch disabled"); + break; + } + if (VOS_TRUE == pMac->sap.SapDfsInfo.sap_radar_found_status) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs:Posting event eSAP_DFS_CHANNEL_CAC_RADAR_FOUND"); + /* + * If Radar is found, while in DFS CAC WAIT State then + * post stop and destroy the CAC timer and post a + * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND to sapFsm. + */ + vos_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + + /* + * User space is already indicated the CAC start and if + * CAC end on this channel is not indicated, the user + * space will be in some undefined state (e.g., UI frozen) + */ + vosStatus = sapSignalHDDevent(sapContext, NULL, + eSAP_DFS_CAC_INTERRUPTED, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + if (VOS_STATUS_SUCCESS != vosStatus) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Failed to send CAC end")); + /* Want to still proceed and try to switch channel. + * Lets try not to be on the DFS channel + */ + } + + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + + sapEvent.event = eSAP_DFS_CHANNEL_CAC_RADAR_FOUND; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + } + else if(eSAP_STARTED == sapContext->sapsMachine) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs:Posting event eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START"); + + /* Radar found on the operating channel in STARTED state, + * new operating channel has already been selected. Send + * request to SME-->PE for sending CSA IE + */ + sapEvent.event = eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + else + { + /* Further actions to be taken here */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state" + , __func__, sapContext->sapsMachine); + } + break; + + case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS: + case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE: + { + eCsrPhyMode phyMode = sapContext->csrRoamProfile.phyMode; + + if (sapContext->csrRoamProfile.disableDFSChSwitch) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "sapdfs: DFS channel switch disabled"); + /* + * Send a beacon start request to PE. CSA IE required + * flag from beacon template will be cleared by now. + * A new beacon template with no CSA IE will be sent + * to firmware. + */ + dfs_beacon_start_req = VOS_TRUE; + halStatus = sme_RoamStartBeaconReq( hHal, + sapContext->bssid, + dfs_beacon_start_req); + break; + } + + /* Both success and failure cases are handled intentionally handled + * together. Irrespective of whether the channel switch IE was + * sent out successfully or not, SAP should still vacate the + * channel immediately + */ + if (eSAP_STARTED == sapContext->sapsMachine) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: from state %s => %s", + "eSAP_STARTED", "eSAP_DISCONNECTING"); + + /* SAP to be moved to DISCONNECTING state */ + sapContext->sapsMachine = eSAP_DISCONNECTING; + + /* The associated stations have been informed to move + * to a different channel. However, the AP may not always + * select the advertised channel for operation if the radar + * is seen. In that case, the stations will experience link-loss + * and return back through scanning if they wish to + */ + + /* Send channel change request + * From spec it is required that the AP should continue to + * operate in the same mode as it is operating currently. + * For e.g. 20/40/80 MHz operation + */ + if (pMac->sap.SapDfsInfo.target_channel) + { + sme_SelectCBMode(hHal, phyMode, + pMac->sap.SapDfsInfo.target_channel, + 0, &sapContext->vht_channel_width, + sapContext->ch_width_orig); + } + + /* + * Fetch the number of SAP interfaces. + * If the number of sap Interface more than + * one then we will make is_sap_ready_for_chnl_chng to true + * for that sapctx + * + * If there is only one SAP interface then process immediately + */ + + if (sap_get_total_number_sap_intf(hHal) > 1) + { + v_U8_t intf; + sapContext->is_sap_ready_for_chnl_chng = VOS_TRUE; + /* + * now check if the con-current sap interface is ready + * for channel change. + * If yes then we issue channel change for both the + * SAPs. + * If no then simply return success & we will issue channel + * change when second AP's 5 CSA beacon Tx is completed. + */ + if (VOS_TRUE == + is_concurrent_sap_ready_for_channel_change(hHal, + sapContext)) + { + /* Issue channel change req for each sapctx */ + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext pSapContext; + if (((VOS_STA_SAP_MODE == + pMac->sap.sapCtxList[intf].sapPersona) || + (VOS_P2P_GO_MODE == + pMac->sap.sapCtxList[intf].sapPersona)) && + (pMac->sap.sapCtxList[intf].pSapContext != + NULL)) + { + pSapContext = + pMac->sap.sapCtxList[intf].pSapContext; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_MED, + "sapdfs:issue chnl change for sapctx[%p]", + pSapContext); + /* Send channel switch request */ + sapEvent.event = eWNI_SME_CHANNEL_CHANGE_REQ; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + + + /* Handle event */ + vosStatus = sapFsm(pSapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_ERROR, + FL("post chnl chng req failed, sap[%p]"), + sapContext); + } + else + { + pSapContext->is_sap_ready_for_chnl_chng = + VOS_FALSE; + } + + } + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + FL("sapdfs: sapctx[%p] ready but not concurrent sap"), + sapContext); + + halStatus = eHAL_STATUS_SUCCESS; + } + } + else + { + /* Send channel switch request */ + sapEvent.event = eWNI_SME_CHANNEL_CHANGE_REQ; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Posting event eWNI_SME_CHANNEL_CHANGE_REQ to sapFSM"); + + /* Handle event */ + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + } + } + else + { + /* Further actions to be taken here */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "In %s, eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state", + __func__, sapContext->sapsMachine); + } + break; + } + case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS: + { + /* Channel change is successful. If the new channel is a DFS + * channel, then we will to perform channel availability check + * for 60 seconds + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: changing target channel to [%d]", + pMac->sap.SapDfsInfo.target_channel); + + sapContext->channel = + pMac->sap.SapDfsInfo.target_channel; + + /* Identify if this is channel change in radar detected state */ + if (eSAP_DISCONNECTING == sapContext->sapsMachine) + { + /* check if currently selected channel is a DFS channel */ + if (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(sapContext->channel)) + { + if ((VOS_FALSE == pMac->sap.SapDfsInfo.ignore_cac) && + (eSAP_DFS_DO_NOT_SKIP_CAC == + pMac->sap.SapDfsInfo.cac_state)) + { + sapContext->sapsMachine = eSAP_DISCONNECTED; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: from state %s => %s with ignore cac FALSE on sapctx[%p]", + "eSAP_DISCONNECTING", "DISCONNECTED", sapContext); + + /* DFS Channel */ + sapEvent.event = eSAP_DFS_CHANNEL_CAC_START; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: from state %s => %s with ignore cac TRUE on sapctx[%p]", + "eSAP_DISCONNECTING", "eSAP_STARTING", sapContext); + + /* Start beaconing on the new channel */ + WLANSAP_StartBeaconReq((v_PVOID_t)sapContext); + sapContext->sapsMachine = eSAP_STARTING; + pMac->sap.SapDfsInfo.sap_radar_found_status = VOS_FALSE; + sapEvent.event = eSAP_MAC_START_BSS_SUCCESS; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = eCSR_ROAM_INFRA_IND; + sapEvent.u2 = eCSR_ROAM_RESULT_INFRA_STARTED; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: from state %s => %s on sapctx[%p]", + "eSAP_DISCONNECTING", "eSAP_STARTING", sapContext); + + /* non-DFS channel */ + sapContext->sapsMachine = eSAP_STARTING; + pMac->sap.SapDfsInfo.sap_radar_found_status = VOS_FALSE; + sapEvent.event = eSAP_MAC_START_BSS_SUCCESS; + sapEvent.params = pCsrRoamInfo; + sapEvent.u1 = eCSR_ROAM_INFRA_IND; + sapEvent.u2 = eCSR_ROAM_RESULT_INFRA_STARTED; + } + + /* Handle the event */ + vosStatus = sapFsm(sapContext, &sapEvent); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + + } + else + { + /* We may have a requirment in the future for SAP to perform + * channel change, hence leaving this here + */ + } + + break; + } + case eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE: + { + /* This is much more serious issue, we have to vacate the + * channel due to the presence of radar but our channel change + * failed, stop the BSS operation completely and inform hostapd + */ + sapContext->sapsMachine = eSAP_DISCONNECTED; + + /* Inform cfg80211 and hostapd that BSS is not alive anymore */ + } + case eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND: + { + vosStatus = sapSignalHDDevent(sapContext, pCsrRoamInfo, + eSAP_ECSA_CHANGE_CHAN_IND, (v_PVOID_t)NULL); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + halStatus = eHAL_STATUS_FAILURE; + } + break; + } + default: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("CSR roamResult = %s (%d) not handled"), + get_eCsrRoamResult_str(roamResult), + roamResult); + break; + } + + return halStatus; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c new file mode 100644 index 000000000000..39db899d5993 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c @@ -0,0 +1,2647 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + s a p C h S e l e c t . C + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP modules + functions for channel selection. + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- +2010-03-15 SOFTAP Created module + +===========================================================================*/ + + +/*-------------------------------------------------------------------------- + Include Files +------------------------------------------------------------------------*/ +#include "vos_trace.h" +#include "csrApi.h" +#include "sme_Api.h" +#include "sapChSelect.h" +#include "sapInternal.h" +#ifdef ANI_OS_TYPE_QNX +#include "stdio.h" +#endif +#include "wlan_hdd_main.h" + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#include "limUtils.h" +#include "parserApi.h" +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/*-------------------------------------------------------------------------- + Function definitions +--------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Defines +--------------------------------------------------------------------------*/ +#define SAP_DEBUG + +#define IS_RSSI_VALID( extRssi, rssi ) \ +( \ + ((extRssi < rssi)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) + +#define SET_ACS_BAND(acs_band, pSapCtx) \ +{ \ + if (pSapCtx->acs_cfg->start_ch <= 14 && \ + pSapCtx->acs_cfg->end_ch <= 14) \ + acs_band = eCSR_DOT11_MODE_11g; \ + else \ + acs_band = eCSR_DOT11_MODE_11a;\ +} + +#ifdef FEATURE_WLAN_CH_AVOID +sapSafeChannelType safeChannels[NUM_20MHZ_RF_CHANNELS] = +{ + /*CH , SAFE, default safe */ + {1 , VOS_TRUE}, //RF_CHAN_1, + {2 , VOS_TRUE}, //RF_CHAN_2, + {3 , VOS_TRUE}, //RF_CHAN_3, + {4 , VOS_TRUE}, //RF_CHAN_4, + {5 , VOS_TRUE}, //RF_CHAN_5, + {6 , VOS_TRUE}, //RF_CHAN_6, + {7 , VOS_TRUE}, //RF_CHAN_7, + {8 , VOS_TRUE}, //RF_CHAN_8, + {9 , VOS_TRUE}, //RF_CHAN_9, + {10 , VOS_TRUE}, //RF_CHAN_10, + {11 , VOS_TRUE}, //RF_CHAN_11, + {12 , VOS_TRUE}, //RF_CHAN_12, + {13 , VOS_TRUE}, //RF_CHAN_13, + {14 , VOS_TRUE}, //RF_CHAN_14, + {240, VOS_TRUE}, //RF_CHAN_240, + {244, VOS_TRUE}, //RF_CHAN_244, + {248, VOS_TRUE}, //RF_CHAN_248, + {252, VOS_TRUE}, //RF_CHAN_252, + {208, VOS_TRUE}, //RF_CHAN_208, + {212, VOS_TRUE}, //RF_CHAN_212, + {216, VOS_TRUE}, //RF_CHAN_216, + {36 , VOS_TRUE}, //RF_CHAN_36, + {40 , VOS_TRUE}, //RF_CHAN_40, + {44 , VOS_TRUE}, //RF_CHAN_44, + {48 , VOS_TRUE}, //RF_CHAN_48, + {52 , VOS_TRUE}, //RF_CHAN_52, + {56 , VOS_TRUE}, //RF_CHAN_56, + {60 , VOS_TRUE}, //RF_CHAN_60, + {64 , VOS_TRUE}, //RF_CHAN_64, + {100, VOS_TRUE}, //RF_CHAN_100, + {104, VOS_TRUE}, //RF_CHAN_104, + {108, VOS_TRUE}, //RF_CHAN_108, + {112, VOS_TRUE}, //RF_CHAN_112, + {116, VOS_TRUE}, //RF_CHAN_116, + {120, VOS_TRUE}, //RF_CHAN_120, + {124, VOS_TRUE}, //RF_CHAN_124, + {128, VOS_TRUE}, //RF_CHAN_128, + {132, VOS_TRUE}, //RF_CHAN_132, + {136, VOS_TRUE}, //RF_CHAN_136, + {140, VOS_TRUE}, //RF_CHAN_140, +#ifdef FEATURE_WLAN_CH144 + {144, VOS_TRUE}, //RF_CHAN_144, +#endif + {149, VOS_TRUE}, //RF_CHAN_149, + {153, VOS_TRUE}, //RF_CHAN_153, + {157, VOS_TRUE}, //RF_CHAN_157, + {161, VOS_TRUE}, //RF_CHAN_161, + {165, VOS_TRUE}, //RF_CHAN_165, +}; +#endif + +typedef struct +{ + v_U16_t chStartNum; + v_U32_t weight; +} sapAcsChannelInfo; + +#define ACS_WEIGHT_MAX 4444 + +sapAcsChannelInfo acsHT40Channels5G[ ] = { + {36, ACS_WEIGHT_MAX}, + {44, ACS_WEIGHT_MAX}, + {52, ACS_WEIGHT_MAX}, + {60, ACS_WEIGHT_MAX}, + {100, ACS_WEIGHT_MAX}, + {108, ACS_WEIGHT_MAX}, + {116, ACS_WEIGHT_MAX}, + {124, ACS_WEIGHT_MAX}, + {132, ACS_WEIGHT_MAX}, + {140, ACS_WEIGHT_MAX}, + {149, ACS_WEIGHT_MAX}, + {157, ACS_WEIGHT_MAX}, +}; + +sapAcsChannelInfo acsHT80Channels[ ] = { + {36, ACS_WEIGHT_MAX}, + {52, ACS_WEIGHT_MAX}, + {100, ACS_WEIGHT_MAX}, + {116, ACS_WEIGHT_MAX}, + {132, ACS_WEIGHT_MAX}, + {149, ACS_WEIGHT_MAX}, +}; + +sapAcsChannelInfo acsHT40Channels24G[ ] = { + {1, ACS_WEIGHT_MAX}, + {2, ACS_WEIGHT_MAX}, + {3, ACS_WEIGHT_MAX}, + {4, ACS_WEIGHT_MAX}, + {9, ACS_WEIGHT_MAX}, +}; + +#define CHANNEL_165 165 + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * sap_check_n_add_channel() - checks and add given channel in sap context's + * avoid_channels_info struct + * @sap_ctx: sap context. + * @new_channel: channel to be added to sap_ctx's avoid ch info + * + * sap_ctx contains sap_avoid_ch_info strcut containing the list of channels on + * which MDM device's AP with MCC was detected. This function will add channels + * to that list after checking for duplicates. + * + * Return: true: if channel was added or already present + * else false: if channel list was already full. + */ +bool +sap_check_n_add_channel(ptSapContext sap_ctx, + uint8_t new_channel) +{ + uint8_t i = 0; + struct sap_avoid_channels_info *ie_info = + &sap_ctx->sap_detected_avoid_ch_ie; + + for (i = 0; i < sizeof(ie_info->channels); i++) { + if (ie_info->channels[i] == new_channel) + break; + + if (ie_info->channels[i] == 0) { + ie_info->channels[i] = new_channel; + break; + } + } + if(i == sizeof(ie_info->channels)) + return false; + else + return true; +} + +/** + * sap_check_n_add_overlapped_chnls() - checks & add overlapped channels + * to primary channel in 2.4Ghz band. + * @sap_ctx: sap context. + * @primary_chnl: primary channel to be avoided. + * + * sap_ctx contains sap_avoid_ch_info struct containing the list of channels on + * which MDM device's AP with MCC was detected. This function will add channels + * to that list after checking for duplicates. + * + * Return: true: if channel was added or already present + * else false: if channel list was already full. + */ +static bool +sap_check_n_add_overlapped_chnls(ptSapContext sap_ctx, + uint8_t primary_channel) +{ + uint8_t i = 0, j = 0, upper_chnl = 0, lower_chnl = 0; + struct sap_avoid_channels_info *ie_info = + &sap_ctx->sap_detected_avoid_ch_ie; + /* + * if primary channel less than channel 1 or out of 2g band then + * no further process is required. return true in this case. + */ + if (primary_channel < CHANNEL_1 || primary_channel > CHANNEL_14) + return true; + + /* lower channel is one channel right before primary channel */ + lower_chnl = primary_channel - 1; + /* upper channel is one channel right after primary channel */ + upper_chnl = primary_channel + 1; + + /* lower channel needs to be non-zero, zero is not valid channel */ + if (lower_chnl > (CHANNEL_1 - 1)) { + for (i = 0; i < sizeof(ie_info->channels); i++) { + if (ie_info->channels[i] == lower_chnl) + break; + if (ie_info->channels[i] == 0) { + ie_info->channels[i] = lower_chnl; + break; + } + } + } + /* upper channel needs to be atleast last channel in 2.4Ghz band */ + if (upper_chnl < (CHANNEL_14 + 1)) { + for (j = 0; j < sizeof(ie_info->channels); j++) { + if (ie_info->channels[j] == upper_chnl) + break; + if (ie_info->channels[j] == 0) { + ie_info->channels[j] = upper_chnl; + break; + } + } + } + if (i == sizeof(ie_info->channels) || j == sizeof(ie_info->channels)) + return false; + else + return true; +} + +/** + * sap_process_avoid_ie() - processes the detected Q2Q IE + * context's avoid_channels_info struct + * @hal: hal handle + * @sap_ctx: sap context. + * @scan_result: scan results for ACS scan. + * @spect_info: spectrum weights array to update + * + * Detection of Q2Q IE indicates presence of another MDM device with its AP + * operating in MCC mode. This function parses the scan results and processes + * the Q2Q IE if found. It then extracts the channels and populates them in + * sap_ctx struct. It also increases the weights of those channels so that + * ACS logic will avoid those channels in its selection algorithm. + * + * Return: void + */ + +void +sap_process_avoid_ie(tHalHandle hal, + ptSapContext sap_ctx, + tScanResultHandle scan_result, + tSapChSelSpectInfo *spect_info) +{ + uint32_t total_ie_len = 0; + uint8_t *temp_ptr = NULL; + uint8_t i = 0; + struct sAvoidChannelIE *avoid_ch_ie; + tCsrScanResultInfo *node = NULL; + tpAniSirGlobal mac_ctx = NULL; + tSapSpectChInfo *spect_ch = NULL; + + mac_ctx = PMAC_STRUCT(hal); + spect_ch = spect_info->pSpectCh; + node = sme_ScanResultGetFirst(hal, scan_result); + + while (node) { + total_ie_len = (node->BssDescriptor.length + + sizeof(tANI_U16) + sizeof(tANI_U32) - + sizeof(tSirBssDescription)); + temp_ptr = cfg_get_vendor_ie_ptr_from_oui(mac_ctx, + SIR_MAC_QCOM_VENDOR_OUI, + SIR_MAC_QCOM_VENDOR_SIZE, + ((tANI_U8 *)&node->BssDescriptor.ieFields), + total_ie_len); + + if (temp_ptr) { + avoid_ch_ie = (struct sAvoidChannelIE*)temp_ptr; + if (avoid_ch_ie->type != QCOM_VENDOR_IE_MCC_AVOID_CH) { + continue; + } + sap_ctx->sap_detected_avoid_ch_ie.present = 1; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_DEBUG, + "Q2Q IE - avoid ch %d", + avoid_ch_ie->channel); + /* add this channel to to_avoid channel list */ + sap_check_n_add_channel(sap_ctx, + avoid_ch_ie->channel); + sap_check_n_add_overlapped_chnls(sap_ctx, + avoid_ch_ie->channel); + /* + * Mark weight of these channel present in IE to MAX + * so that ACS logic will to avoid thse channels + */ + for (i = 0; i < spect_info->numSpectChans; i++) { + if (spect_ch[i].chNum == avoid_ch_ie->channel) { + /* + * weight is set more than max so that, + * in the case of other channels being + * assigned max weight due to noise, + * they may be preferred over channels + * with Q2Q IE. + */ + spect_ch[i].weight = ACS_WEIGHT_MAX + 1; + spect_ch[i].weight_copy = + ACS_WEIGHT_MAX + 1; + break; + } + } + } /* if (temp_ptr) */ + node = sme_ScanResultGetNext(hal, scan_result); + } +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#ifdef FEATURE_WLAN_CH_AVOID +/*========================================================================== + FUNCTION sapUpdateUnsafeChannelList + + DESCRIPTION + Function Undate unsafe channel list table + + DEPENDENCIES + NA. + + IN + SapContext pointer + + RETURN VALUE + NULL +============================================================================*/ +void sapUpdateUnsafeChannelList(ptSapContext pSapCtx) +{ + v_U16_t i, j; + + v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_SAP, NULL); + struct hdd_context_s *hdd_ctxt; + + if (NULL == pvosGCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "VOSS Global Context is NULL"); + return ; + } + + hdd_ctxt = (struct hdd_context_s *) vos_get_context(VOS_MODULE_ID_HDD, pvosGCtx); + + if (NULL == hdd_ctxt) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "HDD Context is NULL"); + return ; + } + + /* Flush, default set all channel safe */ + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) + { + safeChannels[i].isSafe = VOS_TRUE; + } + + /* Try to find unsafe channel */ +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || \ + defined(WLAN_FEATURE_MBSSID) + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { + if (pSapCtx->dfs_ch_disable == VOS_TRUE) { + if (VOS_IS_DFS_CH(safeChannels[i].channelNumber)) { + safeChannels[i].isSafe = VOS_FALSE; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: DFS Ch %d is not safe in Concurrent mode", __func__, + safeChannels[i].channelNumber); + } + } + } +#endif + + for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) + { + for (j = 0; j < NUM_20MHZ_RF_CHANNELS; j++) + { + if(safeChannels[j].channelNumber == hdd_ctxt->unsafe_channel_list[i]) + { + /* Found unsafe channel, update it */ + safeChannels[j].isSafe = VOS_FALSE; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s : CH %d is not safe", + __func__, hdd_ctxt->unsafe_channel_list[i]); + break; + } + } + } + + return; +} + +#endif /* FEATURE_WLAN_CH_AVOID */ + +/*========================================================================== + FUNCTION sapCleanupChannelList + + DESCRIPTION + Function sapCleanupChannelList frees up the memory allocated to the channel list. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + NULL + + RETURN VALUE + NULL +============================================================================*/ + +void sapCleanupChannelList +( +#ifdef WLAN_FEATURE_MBSSID + v_PVOID_t pvosGCtx +#else + void +#endif +) +{ +#ifndef WLAN_FEATURE_MBSSID + v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_SAP, NULL); +#endif + ptSapContext pSapCtx; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "Cleaning up the channel list structure"); + + if (NULL == pvosGCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "SAP Global Context is NULL"); + return ; + } + + pSapCtx = VOS_GET_SAP_CB(pvosGCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "SAP Context is NULL"); + return ; + } + + pSapCtx->SapChnlList.numChannel = 0; + if (pSapCtx->SapChnlList.channelList) { + vos_mem_free(pSapCtx->SapChnlList.channelList); + pSapCtx->SapChnlList.channelList = NULL; + } + + pSapCtx->SapAllChnlList.numChannel = 0; + if (pSapCtx->SapAllChnlList.channelList) { + vos_mem_free(pSapCtx->SapAllChnlList.channelList); + pSapCtx->SapAllChnlList.channelList = NULL; + } +} + +/*========================================================================== + FUNCTION sapSelectPreferredChannelFromChannelList + + DESCRIPTION + Function sapSelectPreferredChannelFromChannelList calculates the best channel + among the configured channel list. If channel list not configured then returns + the best channel calculated among all the channel list. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + *pSpectInfoParams : Pointer to tSapChSelSpectInfo structure + bestChNum: best channel already calculated among all the chanels + pSapCtx: having info of channel list from which best channel is selected + + RETURN VALUE + v_U8_t: best channel +============================================================================*/ +v_U8_t sapSelectPreferredChannelFromChannelList(v_U8_t bestChNum, + ptSapContext pSapCtx, + tSapChSelSpectInfo *pSpectInfoParams) +{ + v_U8_t j = 0; + v_U8_t count = 0; + + //If Channel List is not Configured don't do anything + //Else return the Best Channel from the Channel List + if((NULL == pSapCtx->acs_cfg->ch_list) || + (NULL == pSpectInfoParams)) + { + return bestChNum; + } + + if (bestChNum > 0 && bestChNum <= 252) + { + for(count=0; count < pSpectInfoParams->numSpectChans ; count++) + { + bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; + // Select the best channel from allowed list + for(j=0;j < pSapCtx->acs_cfg->ch_list_count;j++) + { + if( (pSapCtx->acs_cfg->ch_list[j]) == bestChNum) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "Best channel computed from Channel List is: %d", + bestChNum); + return bestChNum; + } + } + } + + return SAP_CHANNEL_NOT_SELECTED; + } + else + return SAP_CHANNEL_NOT_SELECTED; +} + + +/*========================================================================== + FUNCTION sapChanSelInit + + DESCRIPTION + Function sapChanSelInit allocates the memory, intializes the + structures used by the channel selection algorithm + + DEPENDENCIES + NA. + + PARAMETERS + + IN + halHandle : Pointer to tHalHandle + *pSpectInfoParams : Pointer to tSapChSelSpectInfo structure + pSapCtx : Pointer to SAP Context + + RETURN VALUE + v_BOOL_t: Success or FAIL + + SIDE EFFECTS +============================================================================*/ +v_BOOL_t sapChanSelInit(tHalHandle halHandle, + tSapChSelSpectInfo *pSpectInfoParams, + ptSapContext pSapCtx) +{ + tSapSpectChInfo *pSpectCh = NULL; + v_U8_t *pChans = NULL; + v_U16_t channelnum = 0; + tpAniSirGlobal pMac = PMAC_STRUCT(halHandle); + v_BOOL_t chSafe = VOS_TRUE; +#ifdef FEATURE_WLAN_CH_AVOID + v_U16_t i; +#endif + v_U32_t dfs_master_cap_enabled; + v_BOOL_t include_dfs_ch = VOS_TRUE; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s", __func__); + + pSpectInfoParams->numSpectChans = pMac->scan.base20MHzChannels.numChannels; + + // Allocate memory for weight computation of 2.4GHz + pSpectCh = (tSapSpectChInfo *)vos_mem_malloc((pSpectInfoParams->numSpectChans) * sizeof(*pSpectCh)); + + if(pSpectCh == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, VOS_MALLOC_ERR", __func__); + return eSAP_FALSE; + } + + vos_mem_zero(pSpectCh, (pSpectInfoParams->numSpectChans) * sizeof(*pSpectCh)); + + // Initialize the pointers in the DfsParams to the allocated memory + pSpectInfoParams->pSpectCh = pSpectCh; + + pChans = pMac->scan.base20MHzChannels.channelList; +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || defined(WLAN_FEATURE_MBSSID) + if (pSapCtx->dfs_ch_disable == VOS_TRUE) + include_dfs_ch = VOS_FALSE; +#endif + ccmCfgGetInt(halHandle, WNI_CFG_DFS_MASTER_ENABLED, + &dfs_master_cap_enabled); + if (dfs_master_cap_enabled == 0) + include_dfs_ch = VOS_FALSE; + + // Fill the channel number in the spectrum in the operating freq band + for (channelnum = 0; + channelnum < pSpectInfoParams->numSpectChans; + channelnum++, pChans++, pSpectCh++) { + chSafe = VOS_TRUE; + + /* check if the channel is in NOL blacklist */ + if(sapDfsIsChannelInNolList(pSapCtx, *pChans, + PHY_SINGLE_CHANNEL_CENTERED)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Ch %d is in NOL list", __func__, *pChans); + chSafe = VOS_FALSE; + continue; + } + + if (include_dfs_ch == VOS_FALSE) { + if (VOS_IS_DFS_CH(*pChans)) { + chSafe = VOS_FALSE; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, DFS Ch %d not considered for ACS", __func__, + *pChans); + continue; + } + } + +#ifdef FEATURE_WLAN_CH_AVOID + for(i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { + if((safeChannels[i].channelNumber == *pChans) && + (VOS_FALSE == safeChannels[i].isSafe)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Ch %d is not safe", + __func__, *pChans); + chSafe = VOS_FALSE; + break; + } + } +#endif /* FEATURE_WLAN_CH_AVOID */ + + /* OFDM rates are not supported on channel 14 */ + if(*pChans == 14 && + eCSR_DOT11_MODE_11b != pSapCtx->csrRoamProfile.phyMode) + { + continue; + } + + if (VOS_TRUE == chSafe) + { + pSpectCh->chNum = *pChans; + pSpectCh->valid = eSAP_TRUE; + pSpectCh->rssiAgr = SOFTAP_MIN_RSSI;// Initialise for all channels + pSpectCh->channelWidth = SOFTAP_HT20_CHANNELWIDTH; // Initialise 20MHz for all the Channels + } + } + return eSAP_TRUE; +} + +/*========================================================================== + FUNCTION sapweightRssiCount + + DESCRIPTION + Function weightRssiCount calculates the channel weight due to rssi + and data count(here number of BSS observed) + + DEPENDENCIES + NA. + + PARAMETERS + + IN + rssi : Max signal strength receieved from a BSS for the channel + count : Number of BSS observed in the channel + + RETURN VALUE + v_U32_t : Calculated channel weight based on above two + + SIDE EFFECTS +============================================================================*/ +v_U32_t sapweightRssiCount(v_S7_t rssi, v_U16_t count) +{ + v_S31_t rssiWeight=0; + v_S31_t countWeight=0; + v_U32_t rssicountWeight=0; + + // Weight from RSSI + rssiWeight = SOFTAP_RSSI_WEIGHT * (rssi - SOFTAP_MIN_RSSI) + /(SOFTAP_MAX_RSSI - SOFTAP_MIN_RSSI); + + if(rssiWeight > SOFTAP_RSSI_WEIGHT) + rssiWeight = SOFTAP_RSSI_WEIGHT; + else if (rssiWeight < 0) + rssiWeight = 0; + + // Weight from data count + countWeight = SOFTAP_COUNT_WEIGHT * (count - SOFTAP_MIN_COUNT) + /(SOFTAP_MAX_COUNT - SOFTAP_MIN_COUNT); + + if(countWeight > SOFTAP_COUNT_WEIGHT) + countWeight = SOFTAP_COUNT_WEIGHT; + + rssicountWeight = rssiWeight + countWeight; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, rssiWeight=%d, countWeight=%d, rssicountWeight=%d", + __func__, rssiWeight, countWeight, rssicountWeight); + + return(rssicountWeight); +} + + +/*========================================================================== + FUNCTION sapInterferenceRssiCount + + DESCRIPTION + Function sapInterferenceRssiCount Considers the Adjacent channel rssi + and data count(here number of BSS observed) + + DEPENDENCIES + NA. + + PARAMETERS + + pSpectCh : Channel Information + + RETURN VALUE + NA. + + SIDE EFFECTS +============================================================================*/ +void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) +{ + tSapSpectChInfo *pExtSpectCh = NULL; + v_S31_t rssi; + + if (NULL == pSpectCh) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: pSpectCh is NULL", __func__); + return; + } + + switch(pSpectCh->chNum) + { + case CHANNEL_1: + pExtSpectCh = (pSpectCh + 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case CHANNEL_2: + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + case CHANNEL_3: + pExtSpectCh = (pSpectCh - 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + case CHANNEL_4: + pExtSpectCh = (pSpectCh - 3); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case CHANNEL_5: + case CHANNEL_6: + case CHANNEL_7: + case CHANNEL_8: + case CHANNEL_9: + case CHANNEL_10: + pExtSpectCh = (pSpectCh - 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 4); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case CHANNEL_11: + pExtSpectCh = (pSpectCh - 4); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + + pExtSpectCh = (pSpectCh - 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case CHANNEL_12: + pExtSpectCh = (pSpectCh - 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + + pExtSpectCh = (pSpectCh - 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case CHANNEL_13: + pExtSpectCh = (pSpectCh - 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + + pExtSpectCh = (pSpectCh - 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if ((pExtSpectCh != NULL) && (pExtSpectCh->chNum <= CHANNEL_14)) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case CHANNEL_14: + pExtSpectCh = (pSpectCh - 1); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 3); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 4); + if (pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + default: + break; + } +} + +/*========================================================================== + FUNCTION sapComputeSpectWeight + + DESCRIPTION + Main function for computing the weight of each channel in the + spectrum based on the RSSI value of the BSSes on the channel + and number of BSS + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSpectInfoParams : Pointer to the tSpectInfoParams structure + halHandle : Pointer to HAL handle + pResult : Pointer to tScanResultHandle + sap_ctx : Pointer to Sap context + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, + tHalHandle halHandle, tScanResultHandle pResult, + ptSapContext sap_ctx) +{ + v_S7_t rssi = 0; + v_U8_t chn_num = 0; + v_U8_t channel_id = 0; + + tCsrScanResultInfo *pScanResult; + tSapSpectChInfo *pSpectCh = pSpectInfoParams->pSpectCh; + v_U32_t operatingBand = eCSR_DOT11_MODE_11g; + v_U16_t channelWidth; + v_U16_t secondaryChannelOffset; + v_U16_t centerFreq; + v_U16_t vhtSupport; + v_U32_t ieLen = 0; + tSirProbeRespBeacon *pBeaconStruct; + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + + pBeaconStruct = vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + if ( NULL == pBeaconStruct ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "Unable to allocate memory in sapComputeSpectWeight"); + return; + } + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Computing spectral weight", __func__); + + /** + * Soft AP specific channel weight calculation using DFS formula + */ + SET_ACS_BAND(operatingBand, sap_ctx); + + pScanResult = sme_ScanResultGetFirst(halHandle, pResult); + + while (pScanResult) { + pSpectCh = pSpectInfoParams->pSpectCh; + // Defining the default values, so that any value will hold the default values + channelWidth = eHT_CHANNEL_WIDTH_20MHZ; + secondaryChannelOffset = PHY_SINGLE_CHANNEL_CENTERED; + vhtSupport = 0; + centerFreq = 0; + + if (pScanResult->BssDescriptor.ieFields != NULL) + { + ieLen = (pScanResult->BssDescriptor.length + sizeof(tANI_U16) + sizeof(tANI_U32) - sizeof(tSirBssDescription)); + vos_mem_set((tANI_U8 *) pBeaconStruct, sizeof(tSirProbeRespBeacon), 0); + + if ((sirParseBeaconIE(pMac, pBeaconStruct,(tANI_U8 *)( pScanResult->BssDescriptor.ieFields), ieLen)) == eSIR_SUCCESS) + { + if (pBeaconStruct->HTCaps.present && pBeaconStruct->HTInfo.present) + { + channelWidth = pBeaconStruct->HTCaps.supportedChannelWidthSet; + secondaryChannelOffset = pBeaconStruct->HTInfo.secondaryChannelOffset; + if(pBeaconStruct->VHTOperation.present) + { + vhtSupport = pBeaconStruct->VHTOperation.present; + if(pBeaconStruct->VHTOperation.chanWidth > WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) + { + channelWidth = eHT_CHANNEL_WIDTH_80MHZ; + centerFreq = pBeaconStruct->VHTOperation.chanCenterFreqSeg1; + } + } + } + } + } + // Processing for each tCsrScanResultInfo in the tCsrScanResult DLink list + for (chn_num = 0; chn_num < pSpectInfoParams->numSpectChans; chn_num++) { + + /* + * if the Beacon has channel ID, use it other wise we will + * rely on the channelIdSelf + */ + if(pScanResult->BssDescriptor.channelId == 0) + channel_id = pScanResult->BssDescriptor.channelIdSelf; + else + channel_id = pScanResult->BssDescriptor.channelId; + + if (pSpectCh && (channel_id == pSpectCh->chNum)) { + if (pSpectCh->rssiAgr < pScanResult->BssDescriptor.rssi) + pSpectCh->rssiAgr = pScanResult->BssDescriptor.rssi; + + ++pSpectCh->bssCount; // Increment the count of BSS + + if(operatingBand) // Connsidering the Extension Channel only in a channels + { + /* Updating the received ChannelWidth */ + if (pSpectCh->channelWidth != channelWidth) + pSpectCh->channelWidth = channelWidth; + /* If received ChannelWidth is other than HT20, we need to update the extension channel Params as well */ + /* channelWidth == 0, HT20 */ + /* channelWidth == 1, HT40 */ + /* channelWidth == 2, VHT80*/ + switch(pSpectCh->channelWidth) + { + case eHT_CHANNEL_WIDTH_40MHZ: //HT40 + switch( secondaryChannelOffset) + { + tSapSpectChInfo *pExtSpectCh = NULL; + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: // Above the Primary Channel + pExtSpectCh = (pSpectCh + 1); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + // REducing the rssi by -20 and assigning it to Extension channel + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + break; + + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: // Below the Primary channel + pExtSpectCh = (pSpectCh - 1); + if(pExtSpectCh != NULL) + { + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + ++pExtSpectCh->bssCount; + } + break; + } + break; + case eHT_CHANNEL_WIDTH_80MHZ: // VHT80 + if((centerFreq - channel_id) == 6) + { + tSapSpectChInfo *pExtSpectCh = NULL; + pExtSpectCh = (pSpectCh + 1); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -20 and assigning it to Subband 1 + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -30 and assigning it to Subband 2 + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 3); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -40 and assigning it to Subband 3 + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + } + else if((centerFreq - channel_id) == 2) + { + tSapSpectChInfo *pExtSpectCh = NULL; + pExtSpectCh = (pSpectCh - 1 ); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 2); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + } + else if((centerFreq - channel_id) == -2) + { + tSapSpectChInfo *pExtSpectCh = NULL; + pExtSpectCh = (pSpectCh - 1 ); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh + 1); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + } + else if((centerFreq - channel_id) == -6) + { + tSapSpectChInfo *pExtSpectCh = NULL; + pExtSpectCh = (pSpectCh - 1 ); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 2); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + pExtSpectCh = (pSpectCh - 3); + if(pExtSpectCh != NULL) + { + ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } + if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } + } + break; + } + } + + if(operatingBand == eCSR_DOT11_MODE_11g) + { + sapInterferenceRssiCount(pSpectCh); + } + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=%p, ChannelWidth %d, secondaryChanOffset %d, center frequency %d", + __func__, pScanResult->BssDescriptor.channelIdSelf, + pScanResult->BssDescriptor.channelId, + pScanResult->BssDescriptor.rssi, pSpectCh->bssCount, + pScanResult, pSpectCh->channelWidth, + secondaryChannelOffset, centerFreq); + + pSpectCh++; + break; + } else { + pSpectCh++; + } + } + + pScanResult = sme_ScanResultGetNext(halHandle, pResult); + } + + // Calculate the weights for all channels in the spectrum pSpectCh + pSpectCh = pSpectInfoParams->pSpectCh; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Spectrum Channels Weight", __func__); + + for (chn_num = 0; chn_num < (pSpectInfoParams->numSpectChans); chn_num++) { + + /* + rssi : Maximum received signal strength among all BSS on that channel + bssCount : Number of BSS on that channel + */ + + rssi = (v_S7_t)pSpectCh->rssiAgr; + + pSpectCh->weight = SAPDFS_NORMALISE_1000 * sapweightRssiCount(rssi, pSpectCh->bssCount); + pSpectCh->weight_copy = pSpectCh->weight; + + //------ Debug Info ------ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Chan=%d Weight= %d rssiAgr=%d bssCount=%d", __func__, + pSpectCh->chNum, pSpectCh->weight, + pSpectCh->rssiAgr, pSpectCh->bssCount); + //------ Debug Info ------ + pSpectCh++; + } + vos_mem_free(pBeaconStruct); +} + +/*========================================================================== + FUNCTION sapChanSelExit + + DESCRIPTION + Exit function for free out the allocated memory, to be called + at the end of the dfsSelectChannel function + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure + + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapChanSelExit( tSapChSelSpectInfo *pSpectInfoParams ) +{ + // Free all the allocated memory + vos_mem_free(pSpectInfoParams->pSpectCh); +} + +/*========================================================================== + FUNCTION sapSortChlWeight + + DESCRIPTION + Funtion to sort the channels with the least weight first for 20MHz channels + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure + + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapSortChlWeight(tSapChSelSpectInfo *pSpectInfoParams) +{ + tSapSpectChInfo temp; + + tSapSpectChInfo *pSpectCh = NULL; + v_U32_t i = 0, j = 0, minWeightIndex = 0; + + pSpectCh = pSpectInfoParams->pSpectCh; + for (i = 0; i < pSpectInfoParams->numSpectChans; i++) { + minWeightIndex = i; + for( j = i + 1; j < pSpectInfoParams->numSpectChans; j++) { + if(pSpectCh[j].weight < pSpectCh[minWeightIndex].weight) { + minWeightIndex = j; + } + } + if(minWeightIndex != i) { + vos_mem_copy(&temp, &pSpectCh[minWeightIndex], sizeof(*pSpectCh)); + vos_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i], sizeof(*pSpectCh)); + vos_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh)); + } + } +} + +/*========================================================================== + FUNCTION sapSortChlWeightHT80 + + DESCRIPTION + Funtion to sort the channels with the least weight first for HT80 channels + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure + + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapSortChlWeightHT80(tSapChSelSpectInfo *pSpectInfoParams) +{ + v_U8_t i, j, n; + tSapSpectChInfo *pSpectInfo; + v_U8_t minIdx; + + pSpectInfo = pSpectInfoParams->pSpectCh; + /* for each HT80 channel, calculate the combined weight of the + four 20MHz weight */ + for (i = 0; i < ARRAY_SIZE(acsHT80Channels); i++) + { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) + { + if ( pSpectInfo[j].chNum == acsHT80Channels[i].chStartNum ) + break; + } + if (j == pSpectInfoParams->numSpectChans) + continue; + + /*found the channel, add the 4 adjacent channels' weight*/ + if (((pSpectInfo[j].chNum +4) == pSpectInfo[j+1].chNum) && + ((pSpectInfo[j].chNum +8) == pSpectInfo[j+2].chNum) && + ((pSpectInfo[j].chNum +12) == pSpectInfo[j+3].chNum)) + { + acsHT80Channels[i].weight = pSpectInfo[j].weight + + pSpectInfo[j+1].weight + + pSpectInfo[j+2].weight + + pSpectInfo[j+3].weight; + /* find best channel among 4 channels as the primary channel */ + if ((pSpectInfo[j].weight + pSpectInfo[j+1].weight) < + (pSpectInfo[j+2].weight + pSpectInfo[j+3].weight)) + { + /* lower 2 channels are better choice */ + if (pSpectInfo[j].weight < pSpectInfo[j+1].weight) + minIdx = 0; + else + minIdx = 1; + } + else + { + /* upper 2 channels are better choice */ + if (pSpectInfo[j+2].weight <= pSpectInfo[j+3].weight) + minIdx = 2; + else + minIdx = 3; + } + + /* set all 4 channels to max value first, then reset the + best channel as the selected primary channel, update its + weightage with the combined weight value */ + for (n=0; n<4; n++) + pSpectInfo[j+n].weight = ACS_WEIGHT_MAX * 4; + + pSpectInfo[j+minIdx].weight = acsHT80Channels[i].weight; + } + else + { + /* some channels does not exist in pSectInfo array, + skip this channel and those in the same HT80 width*/ + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 4; + if ((pSpectInfo[j].chNum +4) == pSpectInfo[j+1].chNum) + pSpectInfo[j+1].weight = ACS_WEIGHT_MAX * 4; + if ((pSpectInfo[j].chNum +8) == pSpectInfo[j+2].chNum) + pSpectInfo[j+2].weight = ACS_WEIGHT_MAX * 4; + if ((pSpectInfo[j].chNum +12) == pSpectInfo[j+3].chNum) + pSpectInfo[j+3].weight = ACS_WEIGHT_MAX * 4; + } + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) + { + if ( CHANNEL_165 == pSpectInfo[j].chNum ) + { + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 4; + break; + } + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d", + __func__, pSpectInfo->chNum, pSpectInfo->weight, + pSpectInfo->rssiAgr, pSpectInfo->bssCount); + pSpectInfo++; + } + + sapSortChlWeight(pSpectInfoParams); +} + +/*========================================================================== + FUNCTION sapSortChlWeightHT40_24G + + DESCRIPTION + Funtion to sort the channels with the least weight first for HT40 channels + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure + + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapSortChlWeightHT40_24G(tSapChSelSpectInfo *pSpectInfoParams) +{ + v_U8_t i, j; + tSapSpectChInfo *pSpectInfo; + v_U32_t tmpWeight1, tmpWeight2; + + pSpectInfo = pSpectInfoParams->pSpectCh; + /*for each HT40 channel, calculate the combined weight of the + two 20MHz weight */ + for (i = 0; i < ARRAY_SIZE(acsHT40Channels24G); i++) + { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) + { + if (pSpectInfo[j].chNum == acsHT40Channels24G[i].chStartNum) + break; + } + if (j == pSpectInfoParams->numSpectChans) + continue; + + if ((pSpectInfo[j].chNum +4) == pSpectInfo[j+4].chNum) + { + /* check if there is another channel combination possiblity + e.g., {1, 5} & {5, 9} */ + if ((pSpectInfo[j+4].chNum + 4)== pSpectInfo[j+8].chNum) + { + /* need to compare two channel pairs */ + tmpWeight1 = pSpectInfo[j].weight + pSpectInfo[j+4].weight; + tmpWeight2 = pSpectInfo[j+4].weight + pSpectInfo[j+8].weight; + if (tmpWeight1 <= tmpWeight2) + { + if (pSpectInfo[j].weight <= pSpectInfo[j+4].weight) + { + pSpectInfo[j].weight = tmpWeight1; + pSpectInfo[j+4].weight = ACS_WEIGHT_MAX * 2; + pSpectInfo[j+8].weight = ACS_WEIGHT_MAX * 2; + } + else + { + pSpectInfo[j+4].weight = tmpWeight1; + /* for secondary channel selection */ + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2 - 1; + pSpectInfo[j+8].weight = ACS_WEIGHT_MAX * 2; + } + } + else + { + if (pSpectInfo[j+4].weight <= pSpectInfo[j+8].weight) + { + pSpectInfo[j+4].weight = tmpWeight2; + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + /* for secondary channel selection */ + pSpectInfo[j+8].weight = ACS_WEIGHT_MAX * 2 - 1; + } + else + { + pSpectInfo[j+8].weight = tmpWeight2; + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + pSpectInfo[j+4].weight = ACS_WEIGHT_MAX * 2; + } + } + } + else + { + tmpWeight1 = pSpectInfo[j].weight + pSpectInfo[j+4].weight; + if (pSpectInfo[j].weight <= pSpectInfo[j+4].weight) + { + pSpectInfo[j].weight = tmpWeight1; + pSpectInfo[j+4].weight = ACS_WEIGHT_MAX * 2; + } + else + { + pSpectInfo[j+4].weight = tmpWeight1; + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + } + } + } + else + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + } + + sapSortChlWeight(pSpectInfoParams); +} + + +/*========================================================================== + FUNCTION sapSortChlWeightHT40_5G + + DESCRIPTION + Funtion to sort the channels with the least weight first for HT40 channels + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure + + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapSortChlWeightHT40_5G(tSapChSelSpectInfo *pSpectInfoParams) +{ + v_U8_t i, j; + tSapSpectChInfo *pSpectInfo; + + pSpectInfo = pSpectInfoParams->pSpectCh; + /*for each HT40 channel, calculate the combined weight of the + two 20MHz weight */ + for (i = 0; i < ARRAY_SIZE(acsHT40Channels5G); i++) + { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) + { + if (pSpectInfo[j].chNum == acsHT40Channels5G[i].chStartNum) + break; + } + if (j == pSpectInfoParams->numSpectChans) + continue; + + /* found the channel, add the two adjacent channels' weight */ + if ( (pSpectInfo[j].chNum +4) == pSpectInfo[j+1].chNum) + { + acsHT40Channels5G[i].weight = pSpectInfo[j].weight + + pSpectInfo[j+1].weight; + /* select better of the adjact channel as the primary channel */ + if (pSpectInfo[j].weight <= pSpectInfo[j+1].weight) + { + pSpectInfo[j].weight = acsHT40Channels5G[i].weight; + /* mark the adjacent channel's weight as max value so + that it will be sorted to the bottom */ + pSpectInfo[j+1].weight = ACS_WEIGHT_MAX * 2; + } + else + { + pSpectInfo[j+1].weight = acsHT40Channels5G[i].weight; + /* mark the adjacent channel's weight as max value so + that it will be sorted to the bottom */ + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + } + + } + else + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + } + + /* avoid channel 165 by setting its weight to max */ + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) + { + if ( CHANNEL_165 == pSpectInfo[j].chNum ) + { + pSpectInfo[j].weight = ACS_WEIGHT_MAX * 2; + break; + } + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d", + __func__, pSpectInfo->chNum, pSpectInfo->weight, + pSpectInfo->rssiAgr, pSpectInfo->bssCount); + pSpectInfo++; + } + + sapSortChlWeight(pSpectInfoParams); +} + +/*========================================================================== + FUNCTION sapSortChlWeightAll + + DESCRIPTION + Funtion to sort the channels with the least weight first + + DEPENDENCIES + NA. + + PARAMETERS + + IN + ptSapContext : Pointer to the ptSapContext structure + pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure + + RETURN VALUE + void : NULL + + SIDE EFFECTS +============================================================================*/ +void sapSortChlWeightAll(ptSapContext pSapCtx, + tSapChSelSpectInfo *pSpectInfoParams, + v_U32_t operatingBand) +{ + tSapSpectChInfo *pSpectCh = NULL; + v_U32_t j = 0; +#ifndef SOFTAP_CHANNEL_RANGE + v_U32_t i = 0; +#endif + + pSpectCh = pSpectInfoParams->pSpectCh; +#ifdef SOFTAP_CHANNEL_RANGE + + switch (pSapCtx->acs_cfg->ch_width) + { + case eHT_CHANNEL_WIDTH_40MHZ: + if (eCSR_DOT11_MODE_11a == operatingBand) + sapSortChlWeightHT40_5G(pSpectInfoParams); + else + sapSortChlWeightHT40_24G(pSpectInfoParams); + break; + + case eHT_CHANNEL_WIDTH_80MHZ: + sapSortChlWeightHT80(pSpectInfoParams); + break; + + case eHT_CHANNEL_WIDTH_20MHZ: + default: + /* Sorting the channels as per weights as 20MHz channels */ + sapSortChlWeight(pSpectInfoParams); + } + +#else + /* Sorting the channels as per weights */ + for (i = 0; i < SPECT_24GHZ_CH_COUNT; i++) { + minWeightIndex = i; + for( j = i + 1; j < SPECT_24GHZ_CH_COUNT; j++) { + if(pSpectCh[j].weight < pSpectCh[minWeightIndex].weight) { + minWeightIndex = j; + } + } + if(minWeightIndex != i) { + vos_mem_copy(&temp, &pSpectCh[minWeightIndex], sizeof(*pSpectCh)); + vos_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i], + sizeof(*pSpectCh)); + vos_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh)); + } + } +#endif + + /* For testing */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Sorted Spectrum Channels Weight", __func__); + pSpectCh = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d", + __func__, pSpectCh->chNum, pSpectCh->weight, + pSpectCh->rssiAgr, pSpectCh->bssCount); + pSpectCh++; + } + +} + +/*========================================================================== + FUNCTION sapFilterOverLapCh + + DESCRIPTION + return true if ch is acceptable. + This function will decide if we will filter over lap channel or not. + + DEPENDENCIES + shall called after ap start. + + PARAMETERS + + IN + pSapCtx : Pointer to ptSapContext. + chNum : Filter channel number. + + RETURN VALUE + v_BOOL_t : true if channel is accepted. + + SIDE EFFECTS +============================================================================*/ +v_BOOL_t sapFilterOverLapCh(ptSapContext pSapCtx, v_U16_t chNum) +{ + if (pSapCtx->enableOverLapCh) + return eSAP_TRUE; + else if((chNum == CHANNEL_1) || + (chNum == CHANNEL_6) || + (chNum == CHANNEL_11)) + return eSAP_TRUE; + + return eSAP_FALSE; +} + +/*========================================================================== + FUNCTION sapSelectChannel + + DESCRIPTION + Runs a algorithm to select the best channel to operate in based on BSS + rssi and bss count on each channel + + DEPENDENCIES + NA. + + PARAMETERS + + IN + halHandle : Pointer to HAL handle + pResult : Pointer to tScanResultHandle + + RETURN VALUE + v_U8_t : Success - channel number, Fail - zero + + SIDE EFFECTS +============================================================================*/ +v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResultHandle pScanResult) +{ + // DFS param object holding all the data req by the algo + tSapChSelSpectInfo oSpectInfoParams = {NULL,0}; + tSapChSelSpectInfo *pSpectInfoParams = &oSpectInfoParams; // Memory? NB + v_U8_t bestChNum = SAP_CHANNEL_NOT_SELECTED; +#ifdef FEATURE_WLAN_CH_AVOID + v_U8_t i; + v_U8_t firstSafeChannelInRange = SAP_CHANNEL_NOT_SELECTED; +#endif +#ifdef SOFTAP_CHANNEL_RANGE + v_U32_t startChannelNum; + v_U32_t endChannelNum; + v_U32_t operatingBand = 0; + v_U32_t tmpChNum; + v_U8_t count; +#endif + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch Select", __func__); + +#ifdef FEATURE_WLAN_CH_AVOID + sapUpdateUnsafeChannelList(pSapCtx); +#endif + + if (NULL == pScanResult) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: No external AP present", __func__); + +#ifndef SOFTAP_CHANNEL_RANGE + return bestChNum; +#else + //scan is successfull, but no AP is present + startChannelNum = pSapCtx->acs_cfg->start_ch; + endChannelNum = pSapCtx->acs_cfg->end_ch; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: start - end: %d - %d", __func__, + startChannelNum, endChannelNum); + +#ifndef FEATURE_WLAN_CH_AVOID /* FEATURE_WLAN_CH_AVOID NOT defined case*/ + // pick the first channel in configured range + pSapCtx->acs_cfg->pri_ch = startChannelNum; + pSapCtx->acs_cfg->ht_sec_ch = 0; + return startChannelNum; +#else /* FEATURE_WLAN_CH_AVOID defined */ + + // any safe channels in the configured range? + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) + { + if((safeChannels[i].channelNumber >= startChannelNum) && + (safeChannels[i].channelNumber <= endChannelNum)) + { + eNVChannelEnabledType enable_type = + vos_nv_getChannelEnabledState(safeChannels[i].channelNumber); + if ((NV_CHANNEL_DISABLE == enable_type) || + (NV_CHANNEL_INVALID == enable_type)) + continue; + + if (safeChannels[i].isSafe == VOS_TRUE) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: channel %d in the configuration is safe", + __func__, safeChannels[i].channelNumber); + firstSafeChannelInRange = safeChannels[i].channelNumber; + break; + } + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: channel %d in the configuration is unsafe", __func__, + safeChannels[i].channelNumber); + } + } + + /* if there is no channel selected return SAP_CHANNEL_NOT_SELECTED */ + return firstSafeChannelInRange; +#endif /* !FEATURE_WLAN_CH_AVOID */ +#endif /* SOFTAP_CHANNEL_RANGE */ + } + + // Initialize the structure pointed by pSpectInfoParams + if (sapChanSelInit( halHandle, pSpectInfoParams, pSapCtx ) != eSAP_TRUE ) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, Ch Select initialization failed", __func__); + return SAP_CHANNEL_NOT_SELECTED; + } + + // Compute the weight of the entire spectrum in the operating band + sapComputeSpectWeight( pSpectInfoParams, halHandle, pScanResult, pSapCtx); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* process avoid channel IE to collect all channels to avoid */ + sap_process_avoid_ie(halHandle, pSapCtx, pScanResult, pSpectInfoParams); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#ifdef SOFTAP_CHANNEL_RANGE + if (eCSR_BAND_ALL == pSapCtx->scanBandPreference) + { + startChannelNum = pSapCtx->acs_cfg->start_ch; + endChannelNum = pSapCtx->acs_cfg->end_ch; + SET_ACS_BAND(operatingBand, pSapCtx); + } + else + { + if (eCSR_BAND_24 == pSapCtx->currentPreferredBand) + { + startChannelNum = rfChannels[RF_CHAN_1].channelNum; + endChannelNum = rfChannels[RF_CHAN_14].channelNum; + operatingBand = eCSR_DOT11_MODE_11g; + } + else + { + startChannelNum = rfChannels[RF_CHAN_36].channelNum; + endChannelNum = rfChannels[RF_CHAN_165].channelNum; + operatingBand = eCSR_DOT11_MODE_11a; + } + } + + pSapCtx->acsBestChannelInfo.channelNum = 0; + pSapCtx->acsBestChannelInfo.weight = CFG_ACS_BAND_SWITCH_THRESHOLD_MAX; + + /* Sort the channel list as per the computed weights, lesser weight first.*/ + sapSortChlWeightAll(pSapCtx, pSpectInfoParams, operatingBand); + + /*Loop till get the best channel in the given range */ + for (count=0; count < pSpectInfoParams->numSpectChans ; count++) + { + if ((startChannelNum <= pSpectInfoParams->pSpectCh[count].chNum)&& + (endChannelNum >= pSpectInfoParams->pSpectCh[count].chNum)) + { + if (bestChNum == SAP_CHANNEL_NOT_SELECTED) + { + bestChNum = pSpectInfoParams->pSpectCh[count].chNum; + /* check if bestChNum is in preferred channel list */ + bestChNum = sapSelectPreferredChannelFromChannelList( + bestChNum, pSapCtx, pSpectInfoParams); + if (bestChNum == SAP_CHANNEL_NOT_SELECTED) + { + /* not in preferred channel list, go to next best channel*/ + continue; + } + + if (pSpectInfoParams->pSpectCh[count].weight_copy > + pSapCtx->acsBandSwitchThreshold) + { + /* the best channel exceeds the threshold + check if need to scan next band */ + if ((eCSR_BAND_ALL != pSapCtx->scanBandPreference) && + !pSapCtx->allBandScanned) + { + /* store best channel for later comparison */ + pSapCtx->acsBestChannelInfo.channelNum = bestChNum; + pSapCtx->acsBestChannelInfo.weight = + pSpectInfoParams->pSpectCh[count].weight; + bestChNum = SAP_CHANNEL_NOT_SELECTED; + break; + } + else + { + /* all bands are scanned, compare current best channel + with channel scanned previously */ + if (( pSpectInfoParams->pSpectCh[count].weight_copy > + pSapCtx->acsBestChannelInfo.weight) +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* Weight of the channels(MDM device's AP is + operating) increased to MAX+1 so that they will + be choosen only when there is no other best channel + to choose*/ + && !sap_check_in_avoid_ch_list(pSapCtx, bestChNum) +#endif + ) + { + /* previous stored channel is better */ + bestChNum = pSapCtx->acsBestChannelInfo.channelNum; + } + else + { + pSapCtx->acsBestChannelInfo.channelNum = bestChNum; + pSapCtx->acsBestChannelInfo.weight = + pSpectInfoParams->pSpectCh[count].weight_copy; + } + } + } + else + { + pSapCtx->acsBestChannelInfo.channelNum = bestChNum; + pSapCtx->acsBestChannelInfo.weight = + pSpectInfoParams->pSpectCh[count].weight_copy; + } + } + + if (bestChNum != SAP_CHANNEL_NOT_SELECTED) + { + if (operatingBand == eCSR_DOT11_MODE_11g) + { + /* Give preference to Non-overlap channels */ + if (sapFilterOverLapCh(pSapCtx, + pSpectInfoParams->pSpectCh[count].chNum) && + (pSpectInfoParams->pSpectCh[count].weight_copy <= + pSapCtx->acsBestChannelInfo.weight)) + { + tmpChNum = pSpectInfoParams->pSpectCh[count].chNum; + tmpChNum = sapSelectPreferredChannelFromChannelList( + tmpChNum, pSapCtx, pSpectInfoParams); + if ( tmpChNum != SAP_CHANNEL_NOT_SELECTED) + { + bestChNum = tmpChNum; + break; + } + } + } + } + } + } +#else + // Sort the channel list as per the computed weights, lesser weight first. + sapSortChlWeightAll(pSapCtx, halHandle, pSpectInfoParams); + // Get the first channel in sorted array as best 20M Channel + bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[0].chNum; + //Select Best Channel from Channel List if Configured + bestChNum = sapSelectPreferredChannelFromChannelList(bestChNum, + pSapCtx, pSpectInfoParams); +#endif + + pSapCtx->acs_cfg->pri_ch = bestChNum; + /* determine secondary channel for 2.4G channel 5, 6, 7 in HT40 */ + if ((operatingBand == eCSR_DOT11_MODE_11g) && (pSapCtx->acs_cfg->ch_width == + eHT_CHANNEL_WIDTH_40MHZ)) { + + if ((bestChNum >= 5) && (bestChNum <= 7)) { + int weight_below, weight_above, i; + tSapSpectChInfo *pSpectInfo; + + weight_below = weight_above = ACS_WEIGHT_MAX; + pSpectInfo = pSpectInfoParams->pSpectCh; + + for (i = 0; i < pSpectInfoParams->numSpectChans ; i++) { + if (pSpectInfo[i].chNum == (bestChNum - 4)) + weight_below = pSpectInfo[i].weight; + + if (pSpectInfo[i].chNum == (bestChNum + 4)) + weight_above = pSpectInfo[i].weight; + } + + if (weight_below < weight_above) + pSapCtx->acs_cfg->ht_sec_ch = pSapCtx->acs_cfg->pri_ch - 4; + else + pSapCtx->acs_cfg->ht_sec_ch = pSapCtx->acs_cfg->pri_ch + 4; + } else { + if (bestChNum >= 1 && bestChNum <= 4) + pSapCtx->acs_cfg->ht_sec_ch = pSapCtx->acs_cfg->pri_ch + 4; + else if (bestChNum >= 8 && bestChNum <= 13) + pSapCtx->acs_cfg->ht_sec_ch = pSapCtx->acs_cfg->pri_ch - 4; + else if (bestChNum ==14) + pSapCtx->acs_cfg->ht_sec_ch = 0; + } + pSapCtx->secondary_ch = pSapCtx->acs_cfg->ht_sec_ch; + } + + // Free all the allocated memory + sapChanSelExit(pSpectInfoParams); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch select Completed, Ch=%d", + __func__, bestChNum); + if (bestChNum > 0 && bestChNum <= 252) + return bestChNum; + else + return SAP_CHANNEL_NOT_SELECTED; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.h b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.h new file mode 100644 index 000000000000..e81bab19e469 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __SAP_CH_SELECT_H ) +#define __SAP_CH_SELECT_H + +/*=========================================================================== + + s a p C h S e l e c t . h + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP modules + functions for channel selection. + + DEPENDENCIES: + + + Are listed for each API below. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- ----- -------------------------------------------------------- +2010-03-15 SoftAP Created module + +===========================================================================*/ + + +/*-------------------------------------------------------------------------- + Include Files +------------------------------------------------------------------------*/ +#include "aniGlobal.h" +/*-------------------------------------------------------------------------- + defines and enum +--------------------------------------------------------------------------*/ + +#define SPECT_24GHZ_CH_COUNT (11) // USA regulatory domain +#define SAPDFS_NORMALISE_1000 (1000/9) // Case of spec20 with channel diff = 0 +/* Gen 5 values +#define SOFTAP_MIN_RSSI (-85) +#define SOFTAP_MAX_RSSI (-45) +*/ +#define SOFTAP_MIN_RSSI (-100) +#define SOFTAP_MAX_RSSI (0) +#define SOFTAP_MIN_COUNT (0) +#define SOFTAP_MAX_COUNT (60) +#define SOFTAP_RSSI_WEIGHT (20) +#define SOFTAP_COUNT_WEIGHT (20) + +#define SAP_DEFAULT_24GHZ_CHANNEL (6) +#define SAP_DEFAULT_5GHZ_CHANNEL (40) +#define SAP_CHANNEL_NOT_SELECTED (0) + +#define SOFTAP_HT20_CHANNELWIDTH 0 +#define SAP_SUBBAND1_RSSI_EFFECT_PRIMARY (-20) // In HT40/VHT80, Effect of primary Channel RSSi on Subband1 +#define SAP_SUBBAND2_RSSI_EFFECT_PRIMARY (-30) // In VHT80, Effect of primary Channel RSSI on Subband2 +#define SAP_SUBBAND3_RSSI_EFFECT_PRIMARY (-40) // In VHT80, Effect of Primary Channel RSSI on Subband3 + +#define SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY (-10) // In 2.4GHZ, Effect of Primary Channel RSSI on First Overlapping Channel +#define SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY (-20) // In 2.4GHZ, Effect of Primary Channel RSSI on Second Overlapping Channel +#define SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY (-30) // In 2.4GHZ, Effect of Primary Channel RSSI on Third Overlapping Channel +#define SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY (-40) // In 2.4GHZ, Effect of Primary Channel RSSI on Fourth Overlapping Channel + +typedef enum +{ + CHANNEL_1 = 1, + CHANNEL_2, + CHANNEL_3, + CHANNEL_4, + CHANNEL_5, + CHANNEL_6, + CHANNEL_7, + CHANNEL_8, + CHANNEL_9, + CHANNEL_10, + CHANNEL_11, + CHANNEL_12, + CHANNEL_13, + CHANNEL_14 +} tSapChannel; + +#define MAX_80MHZ_BANDS 6 +#define SAP_80MHZ_MASK 0x0F +#define SAP_40MHZ_MASK_L 0x03 +#define SAP_40MHZ_MASK_H 0x0C + +/* + * structs for holding channel bonding bitmap + * used for finding new channel when SAP is on + * DFS channel and radar is detected. + */ +typedef struct sChannelBondingInfo { + v_U8_t channelMap:4; + v_U8_t rsvd:4; + v_U8_t startChannel; +} tChannelBondingInfo; + +typedef struct __chan_bonding_bitmap { + tChannelBondingInfo chanBondingSet[MAX_80MHZ_BANDS]; +} chan_bonding_bitmap; + +/** +* Structure holding information of each channel in the spectrum, +* it contains the channel number, the computed weight +*/ +typedef struct sChannelInfo { + v_U8_t channel; + v_BOOL_t valid; // if the channel is valid to be picked as new channel +} tChannelInfo; + +typedef struct sAll5GChannelList{ + v_U8_t numChannel; + tChannelInfo *channelList; +} tAll5GChannelList; + +typedef struct sSapChannelListInfo{ + v_U8_t numChannel; + v_U8_t *channelList; +} tSapChannelListInfo; + +typedef struct { + v_U16_t chNum; // Channel Number + v_U16_t channelWidth; // Channel Width + v_U16_t bssCount; // bss found in scanresult for this channel + v_S31_t rssiAgr; // Max value of rssi among all BSS(es) from scanresult for this channel + v_U32_t weight; // Weightage of this channel + v_U32_t weight_copy; //copy of the orignal weight + v_BOOL_t valid; // Is this a valid center frequency for regulatory domain +} tSapSpectChInfo;//tDfsSpectChInfo; + +/** +* Structure holding all the information required to make a +* decision for the best operating channel based on dfs formula +*/ + +typedef struct { + tSapSpectChInfo *pSpectCh;//tDfsSpectChInfo *pSpectCh; // Ptr to the channels in the entire spectrum band + v_U8_t numSpectChans; // Total num of channels in the spectrum +} tSapChSelSpectInfo;//tDfsChSelParams; + +/** + * Structure for channel weight calculation parameters + */ +typedef struct sSapChSelParams { + void *pSpectInfoParams;//*pDfsParams; // Filled with tSapChSelSpectInfo + v_U16_t numChannels; +} tSapChSelParams; + +#define SAP_TX_LEAKAGE_THRES 310 +#define SAP_TX_LEAKAGE_MAX 1000 +#define SAP_TX_LEAKAGE_MIN 200 +/* + * This define is used to block additional channels + * based on the new data gathered on auto platforms + * and to differentiate the leakage data among different + * platforms. + */ +#define SAP_TX_LEAKAGE_AUTO_MIN 210 + +typedef struct sSapTxLeakInfo { + v_U8_t leak_chan; /* leak channel */ + v_U32_t leak_lvl; /* tx leakage lvl */ +} tSapTxLeakInfo; + +typedef struct sSapChanMatrixInfo { + v_U8_t channel; /* channel to switch from */ +#ifdef FEATURE_WLAN_CH144 + tSapTxLeakInfo chan_matrix[RF_CHAN_144 - RF_CHAN_36 + 1]; +#else + tSapTxLeakInfo chan_matrix[RF_CHAN_140 - RF_CHAN_36 + 1]; +#endif +} tSapChanMatrixInfo; + +#endif // if !defined __SAP_CH_SELECT_H diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c new file mode 100644 index 000000000000..eeac1a8d1053 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c @@ -0,0 +1,4909 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + s a p F s m . C + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP Finite + State Machine modules + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- +2010-03-15 Created module + +===========================================================================*/ + + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "sapInternal.h" +// Pick up the SME API definitions +#include "sme_Api.h" +#include "smeInside.h" +// Pick up the PMC API definitions +#include "pmcApi.h" +#include "wlan_nv.h" +#include "vos_utils.h" +#include "_ieee80211_common.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * External declarations for global context + * -------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_CH_AVOID +extern sapSafeChannelType safeChannels[]; +#endif /* FEATURE_WLAN_CH_AVOID */ + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION +/* + * TODO: At present SAP Channel leakage matrix for ch 144 + * is not available from system's team. So to play it safe + * and avoid crash if channel 144 is request, in following + * matix channel 144 is added such that it will cause code + * to avoid selecting channel 144. + * + * THESE ENTRIES SHOULD BE REPLACED WITH CORRECT VALUES AS + * PROVIDED BY SYSTEM'S TEAM. + */ +/* channel tx leakage table - ht80 */ +tSapChanMatrixInfo ht80_chan[] = +{ + {52, + {{36, 148}, {40, 199}, + {44, 193}, {48, 197}, + {52, SAP_TX_LEAKAGE_MIN}, {56, 153}, + {60, 137}, {64, 134}, + {100, 358}, {104, 350}, + {108, 404}, {112, 344}, + {116, 424}, {120, 429}, + {124, 437}, {128, 435}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + + {56, + {{36, 171}, {40, 178}, + {44, 171}, {48, 178}, + {52, SAP_TX_LEAKAGE_MIN}, {56, SAP_TX_LEAKAGE_MIN}, + {60, SAP_TX_LEAKAGE_MIN}, {64, 280}, + {100, 351}, {104, 376}, + {108, 362}, {112, 362}, + {116, 403}, {120, 397}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {60, + {{36, 156}, {40, 146}, + {44, SAP_TX_LEAKAGE_MIN}, {48, SAP_TX_LEAKAGE_MIN}, + {52, 180}, {56, SAP_TX_LEAKAGE_MIN}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, 376}, {104, 360}, + {108, SAP_TX_LEAKAGE_MAX},{112, SAP_TX_LEAKAGE_MAX}, + {116, 395}, {120, 399}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {64, + {{36, 217}, {40, 221}, + {44, SAP_TX_LEAKAGE_MIN}, {48, SAP_TX_LEAKAGE_MIN}, + {52, 176}, {56, 176}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, 384}, {104, 390}, + {108, SAP_TX_LEAKAGE_MAX},{112, SAP_TX_LEAKAGE_MAX}, + {116, 375}, {120, 374}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {100, + {{36, 357}, {40, 326}, + {44, 321}, {48, 326}, + {52, 378}, {56, 396}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, SAP_TX_LEAKAGE_MIN},{104, SAP_TX_LEAKAGE_MIN}, + {108, 196}, {112, 116}, + {116, 166}, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {104, + {{36, 325}, {40, 325}, + {44, 305}, {48, 352}, + {52, 411}, {56, 411}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, SAP_TX_LEAKAGE_MIN},{104, SAP_TX_LEAKAGE_MIN}, + {108, SAP_TX_LEAKAGE_MIN},{112, 460}, + {116, 198}, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {108, + {{36, 304}, {40, 332}, + {44, 310}, {48, 335}, + {52, 431}, {56, 391}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 280}, {104, SAP_TX_LEAKAGE_MIN}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, 185}, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {112, + {{36, 327}, {40, 335}, + {44, 331}, {48, 345}, + {52, 367}, {56, 401}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 131}, {104, 132}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, 189}, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {116, + {{36, 384}, {40, 372}, + {44, 389}, {48, 396}, + {52, 348}, {56, 336}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 172}, {104, 169}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {120, + {{36, 395}, {40, 419}, + {44, 439}, {48, 407}, + {52, 321}, {56, 334}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 134}, {104, 186}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, 159}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {124, + {{36, 469}, {40, 433}, + {44, 434}, {48, 435}, + {52, 332}, {56, 345}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 146}, {104, 177}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, 350}, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, 138}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {128, + {{36, 408}, {40, 434}, + {44, 449}, {48, 444}, + {52, 341}, {56, 374}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 205}, {104, 208}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, 142}, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {132, + {{36, SAP_TX_LEAKAGE_MAX }, {40, SAP_TX_LEAKAGE_MAX }, + {44, SAP_TX_LEAKAGE_MAX }, {48, SAP_TX_LEAKAGE_MAX }, + {52, SAP_TX_LEAKAGE_MAX }, {56, SAP_TX_LEAKAGE_MAX }, + {60, SAP_TX_LEAKAGE_MIN }, {64, SAP_TX_LEAKAGE_MIN }, + {100, SAP_TX_LEAKAGE_MIN },{104, SAP_TX_LEAKAGE_MIN }, + {108, SAP_TX_LEAKAGE_MIN }, {112, SAP_TX_LEAKAGE_MIN }, + {116, SAP_TX_LEAKAGE_MIN },{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN } +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {136, + {{36, SAP_TX_LEAKAGE_MAX }, {40, SAP_TX_LEAKAGE_MAX }, + {44, SAP_TX_LEAKAGE_MAX }, {48, SAP_TX_LEAKAGE_MAX }, + {52, SAP_TX_LEAKAGE_MAX }, {56, SAP_TX_LEAKAGE_MAX }, + {60, SAP_TX_LEAKAGE_MIN }, {64, SAP_TX_LEAKAGE_MIN }, + {100, SAP_TX_LEAKAGE_MIN },{104, SAP_TX_LEAKAGE_MIN }, + {108, SAP_TX_LEAKAGE_MIN },{112, SAP_TX_LEAKAGE_MIN }, + {116, SAP_TX_LEAKAGE_MIN }, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN } +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {140, + {{36, SAP_TX_LEAKAGE_MAX }, {40, SAP_TX_LEAKAGE_MAX }, + {44, SAP_TX_LEAKAGE_MAX }, {48, SAP_TX_LEAKAGE_MAX }, + {52, SAP_TX_LEAKAGE_MAX }, {56, SAP_TX_LEAKAGE_MAX }, + {60, SAP_TX_LEAKAGE_MIN }, {64, SAP_TX_LEAKAGE_MIN }, + {100, SAP_TX_LEAKAGE_MIN },{104, SAP_TX_LEAKAGE_MIN }, + {108, SAP_TX_LEAKAGE_MIN },{112, SAP_TX_LEAKAGE_MIN }, + {116, SAP_TX_LEAKAGE_MIN }, {120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, +}; + +/* channel tx leakage table - ht40 */ +tSapChanMatrixInfo ht40_chan[] = +{ + {52, + {{36, SAP_TX_LEAKAGE_AUTO_MIN}, {40, SAP_TX_LEAKAGE_AUTO_MIN}, + {44, 230}, {48, 230 }, + {52, SAP_TX_LEAKAGE_MIN}, {56, SAP_TX_LEAKAGE_MIN}, + {60, SAP_TX_LEAKAGE_AUTO_MIN}, {64, SAP_TX_LEAKAGE_AUTO_MIN}, + {100, 625}, {104, 323 }, + {108, 646},{112, 646 }, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {56, + {{36, SAP_TX_LEAKAGE_AUTO_MIN}, {40, SAP_TX_LEAKAGE_AUTO_MIN}, + {44, SAP_TX_LEAKAGE_AUTO_MIN}, {48, SAP_TX_LEAKAGE_AUTO_MIN}, + {52, SAP_TX_LEAKAGE_MIN}, {56, SAP_TX_LEAKAGE_MIN}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, 611},{104, 611 }, + {108, 617},{112, 617 }, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {60, + {{36, SAP_TX_LEAKAGE_AUTO_MIN}, {40,SAP_TX_LEAKAGE_AUTO_MIN}, + {44, SAP_TX_LEAKAGE_AUTO_MIN}, {48, SAP_TX_LEAKAGE_AUTO_MIN}, + {52, 190}, {56, 190}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, 608},{104, 608 }, + {108, 623},{112, 623 }, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {64, + {{36, SAP_TX_LEAKAGE_AUTO_MIN}, {40, SAP_TX_LEAKAGE_AUTO_MIN}, + {44, SAP_TX_LEAKAGE_AUTO_MIN}, {48, SAP_TX_LEAKAGE_AUTO_MIN}, + {52, 295}, {56, 295 }, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, 594}, {104, 594 }, + {108, 625},{112, 625 }, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {100, + {{36, 618}, {40, 618 }, + {44, 604}, {48, 604 }, + {52, 596}, {56, 596 }, + {60, 584}, {64, 584 }, + {100, SAP_TX_LEAKAGE_MIN},{104, SAP_TX_LEAKAGE_MIN }, + {108, 299}, {112, 299 }, + {116, SAP_TX_LEAKAGE_AUTO_MIN}, {120, SAP_TX_LEAKAGE_AUTO_MIN}, + {124, SAP_TX_LEAKAGE_AUTO_MIN}, {128, SAP_TX_LEAKAGE_AUTO_MIN}, + {132, 538}, {136, 538 }, + {140, 598} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {104, + {{36, 636}, {40, 636 }, + {44, 601}, {48, 601 }, + {52, 616}, {56, 616 }, + {60, 584}, {64, 584 }, + {100, SAP_TX_LEAKAGE_MIN},{104, SAP_TX_LEAKAGE_MIN}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_AUTO_MIN},{120, SAP_TX_LEAKAGE_AUTO_MIN}, + {124, SAP_TX_LEAKAGE_AUTO_MIN},{128, SAP_TX_LEAKAGE_AUTO_MIN}, + {132, 553}, {136, 553 }, + {140, 568} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {108, + {{36, 600}, {40, 600 }, + {44, 627}, {48, 627 }, + {52, 611}, {56, 611 }, + {60, 611}, {64, 611 }, + {100, 214},{104, 214}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_AUTO_MIN},{120, SAP_TX_LEAKAGE_AUTO_MIN}, + {124, SAP_TX_LEAKAGE_AUTO_MIN},{128, SAP_TX_LEAKAGE_AUTO_MIN}, + {132, SAP_TX_LEAKAGE_AUTO_MIN},{136, SAP_TX_LEAKAGE_AUTO_MIN}, + {140, 534} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {112, + {{36, 645}, {40, 645 }, + {44, 641}, {48, 641 }, + {52, 618}, {56, 618 }, + {60, 612}, {64, 612 }, + {100, 293},{104, 293}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_AUTO_MIN},{128, SAP_TX_LEAKAGE_AUTO_MIN}, + {132, SAP_TX_LEAKAGE_AUTO_MIN},{136, SAP_TX_LEAKAGE_AUTO_MIN}, + {140, 521} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {116, + {{36, 661}, {40, 661 }, + {44, 624}, {48, 624 }, + {52, 634}, {56, 634 }, + {60, 611}, {64, 611 }, + {100, SAP_TX_LEAKAGE_AUTO_MIN},{104, SAP_TX_LEAKAGE_AUTO_MIN}, + {108, 217},{112, 217 }, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_AUTO_MIN},{128, SAP_TX_LEAKAGE_AUTO_MIN}, + {132, SAP_TX_LEAKAGE_AUTO_MIN},{136, SAP_TX_LEAKAGE_AUTO_MIN}, + {140, SAP_TX_LEAKAGE_AUTO_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {120, + {{36, 667}, {40, 667 }, + {44, 645}, {48, 645 }, + {52, 633}, {56, 633 }, + {60, 619}, {64, 619 }, + {100, SAP_TX_LEAKAGE_AUTO_MIN}, {104, SAP_TX_LEAKAGE_AUTO_MIN}, + {108, 291},{112, 291}, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_AUTO_MIN},{136, SAP_TX_LEAKAGE_AUTO_MIN}, + {140, SAP_TX_LEAKAGE_AUTO_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {124, + {{36, 676}, {40, 676 }, + {44, 668}, {48, 668 }, + {52, 595}, {56, 595 }, + {60, 622}, {64, 622 }, + {100, SAP_TX_LEAKAGE_AUTO_MIN}, {104, SAP_TX_LEAKAGE_AUTO_MIN}, + {108, SAP_TX_LEAKAGE_AUTO_MIN}, {112, SAP_TX_LEAKAGE_AUTO_MIN}, + {116, 225},{120, 225}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_AUTO_MIN},{136, SAP_TX_LEAKAGE_AUTO_MIN}, + {140, SAP_TX_LEAKAGE_AUTO_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {128, + {{36, 678}, {40, 678 }, + {44, 664}, {48, 664 }, + {52, 651}, {56, 651 }, + {60, 643}, {64, 643 }, + {100, SAP_TX_LEAKAGE_AUTO_MIN}, {104, SAP_TX_LEAKAGE_AUTO_MIN}, + {108, SAP_TX_LEAKAGE_AUTO_MIN}, {112, SAP_TX_LEAKAGE_AUTO_MIN}, + {116, 293},{120, 293}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_AUTO_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {132, + {{36, 689}, {40, 689 }, + {44, 669}, {48, 669 }, + {52, 662}, {56, 662 }, + {60, 609}, {64, 609 }, + {100, 538},{104, 538 }, + {108, SAP_TX_LEAKAGE_AUTO_MIN}, {112, SAP_TX_LEAKAGE_AUTO_MIN}, + {116, SAP_TX_LEAKAGE_AUTO_MIN}, {120, SAP_TX_LEAKAGE_AUTO_MIN}, + {124, 247},{128, 247}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN } +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {136, + {{36, 703}, {40, 703 }, + {44, 688}, {48, SAP_TX_LEAKAGE_MIN }, + {52, 671}, {56, 671 }, + {60, 658}, {64, 658 }, + {100, 504},{104, 504 }, + {108, SAP_TX_LEAKAGE_AUTO_MIN},{112, SAP_TX_LEAKAGE_AUTO_MIN}, + {116, SAP_TX_LEAKAGE_AUTO_MIN},{120, SAP_TX_LEAKAGE_AUTO_MIN}, + {124, 289},{128, 289}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN } +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {140, + {{36, 695}, {40, 695 }, + {44, 684}, {48, 684 }, + {52, 664}, {56, 664 }, + {60, 658}, {64, 658 }, + {100, 601},{104, 601 }, + {108, 545},{112, 545 }, + {116, SAP_TX_LEAKAGE_AUTO_MIN}, {120, SAP_TX_LEAKAGE_AUTO_MIN}, + {124, SAP_TX_LEAKAGE_AUTO_MIN}, {128, SAP_TX_LEAKAGE_AUTO_MIN}, + {132, 262},{136, 262}, + {140, SAP_TX_LEAKAGE_MIN } +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, +}; + + +/* channel tx leakage table - ht20 */ +tSapChanMatrixInfo ht20_chan[] = +{ + {52, + {{36, SAP_TX_LEAKAGE_AUTO_MIN}, {40, 286}, + {44, 225}, {48, 121}, + {52, SAP_TX_LEAKAGE_MIN}, {56, SAP_TX_LEAKAGE_MIN}, + {60, 300}, {64, SAP_TX_LEAKAGE_AUTO_MIN}, + {100, 637}, {104, SAP_TX_LEAKAGE_MAX}, + {108, SAP_TX_LEAKAGE_MAX},{112, SAP_TX_LEAKAGE_MAX}, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {56, + {{36, 468}, {40, SAP_TX_LEAKAGE_AUTO_MIN}, + {44, SAP_TX_LEAKAGE_AUTO_MIN}, {48, 206}, + {52, SAP_TX_LEAKAGE_MIN}, {56, SAP_TX_LEAKAGE_MIN}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, SAP_TX_LEAKAGE_MAX},{104, SAP_TX_LEAKAGE_MAX}, + {108, SAP_TX_LEAKAGE_MAX},{112, SAP_TX_LEAKAGE_MAX}, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {60, + {{36, 507}, {40, 440}, + {44, SAP_TX_LEAKAGE_AUTO_MIN}, {48, 313}, + {52, SAP_TX_LEAKAGE_MIN}, {56, SAP_TX_LEAKAGE_MIN}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, SAP_TX_LEAKAGE_MAX},{104, SAP_TX_LEAKAGE_MAX}, + {108, SAP_TX_LEAKAGE_MAX},{112, SAP_TX_LEAKAGE_MAX}, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {64, + {{36, 516}, {40, 520}, + {44, 506}, {48, SAP_TX_LEAKAGE_AUTO_MIN}, + {52, 301}, {56, 258}, + {60, SAP_TX_LEAKAGE_MIN}, {64, SAP_TX_LEAKAGE_MIN}, + {100, 620}, {104, 617}, + {108, SAP_TX_LEAKAGE_MAX},{112, SAP_TX_LEAKAGE_MAX}, + {116, SAP_TX_LEAKAGE_MAX},{120, SAP_TX_LEAKAGE_MAX}, + {124, SAP_TX_LEAKAGE_MAX},{128, SAP_TX_LEAKAGE_MAX}, + {132, SAP_TX_LEAKAGE_MAX},{136, SAP_TX_LEAKAGE_MAX}, + {140, SAP_TX_LEAKAGE_MAX} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {100, + {{36, 616}, {40, 601}, + {44, 604}, {48, 589}, + {52, 612}, {56, 592}, + {60, 590}, {64, 582}, + {100, SAP_TX_LEAKAGE_MIN},{104, 131}, + {108, SAP_TX_LEAKAGE_AUTO_MIN}, {112, SAP_TX_LEAKAGE_AUTO_MIN}, + {116, SAP_TX_LEAKAGE_AUTO_MIN}, {120, 522}, + {124, 571}, {128, 589}, + {132, 593}, {136, 598}, + {140, 594} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {104, + {{36, 622}, {40, 624}, + {44, 618}, {48, 610}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, SAP_TX_LEAKAGE_MIN},{104, SAP_TX_LEAKAGE_MIN}, + {108, SAP_TX_LEAKAGE_MIN},{112, 463}, + {116, 483},{120, 503}, + {124, 523}, {128, 565}, + {132, 570}, {136, 588}, + {140, 585} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {108, + {{36, 620}, {40, 638}, + {44, 611}, {48, 614}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 477},{104, SAP_TX_LEAKAGE_MIN}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, 477},{120, 497}, + {124, 517},{128, 537}, + {132, 557},{136, 577}, + {140, 603} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {112, + {{36, 636}, {40, 623}, + {44, 638}, {48, 628}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, 606}, + {100, 501},{104, 481}, + {108, SAP_TX_LEAKAGE_MIN},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_MIN},{120, 481}, + {124, 501},{128, 421}, + {132, 541},{136, 561}, + {140, 583} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {116, + {{36, 646}, {40, 648}, + {44, 633}, {48, 634}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, 615}, {64, 594}, + {100, 575},{104, 554}, + {108, 534},{112, SAP_TX_LEAKAGE_MIN}, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, 534},{136, 554}, + {140, 574} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {120, + {{36, 643}, {40, 649}, + {44, 654}, {48, 629}, + {52, SAP_TX_LEAKAGE_MAX}, {56, 621}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 565}, {104, 545}, + {108, 525},{112, 505}, + {116, SAP_TX_LEAKAGE_MIN},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, 505}, + {132, 525},{136, 545}, + {140, 565} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {124, + {{36, 638}, {40, 657}, + {44, 663}, {48, 649}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 581}, {104, 561}, + {108, 541},{112, 521}, + {116, 499},{120, SAP_TX_LEAKAGE_MIN}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, 499},{136, 519}, + {140, 539} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {128, + {{36, 651}, {40, 651}, + {44, 674}, {48, 640}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, 603}, {104, 560}, + {108, 540},{112, 520}, + {116, 499},{120, 479}, + {124, SAP_TX_LEAKAGE_MIN},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, 479}, + {140, 499} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {132, + {{36, 643}, {40, 668}, + {44, 651}, {48, 657}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, SAP_TX_LEAKAGE_MAX},{104, 602}, + {108, 578}, {112, 570}, + {116, 550},{120, 530}, + {124, 510},{128, SAP_TX_LEAKAGE_MIN}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, 490} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {136, + {{36, 654}, {40, 667}, + {44, 666}, {48, 642}, + {52, SAP_TX_LEAKAGE_MAX}, {56, SAP_TX_LEAKAGE_MAX}, + {60, SAP_TX_LEAKAGE_MAX}, {64, SAP_TX_LEAKAGE_MAX}, + {100, SAP_TX_LEAKAGE_MAX},{104, SAP_TX_LEAKAGE_MAX}, + {108, SAP_TX_LEAKAGE_MAX},{112, 596}, + {116, 555}, {120, 535}, + {124, 515},{128, 495}, + {132, SAP_TX_LEAKAGE_MIN},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, + + {140, + {{36, 679}, {40, 673}, + {44, 667}, {48, 656}, + {52, 634}, {56, 663}, + {60, 662}, {64, 660}, + {100, SAP_TX_LEAKAGE_MAX},{104, SAP_TX_LEAKAGE_MAX}, + {108, SAP_TX_LEAKAGE_MAX},{112, 590}, + {116, 573}, {120, 553}, + {124, 533},{128, 513}, + {132, 490},{136, SAP_TX_LEAKAGE_MIN}, + {140, SAP_TX_LEAKAGE_MIN} +#ifdef FEATURE_WLAN_CH144 + ,{144, SAP_TX_LEAKAGE_MIN} +#endif +}}, +}; +#endif //end of WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + + +/*---------------------------------------------------------------------------- + * Static Function Declarations and Definitions + * -------------------------------------------------------------------------*/ +#ifdef SOFTAP_CHANNEL_RANGE +static VOS_STATUS sapGetChannelList(ptSapContext sapContext, v_U8_t **channelList, + v_U8_t *numberOfChannels); +#endif + +/*========================================================================== + FUNCTION sapGet5GHzChannelList + + DESCRIPTION + Function for initializing list of 2.4/5 Ghz [NON-DFS/DFS] available + channels in the current regulatory domain. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext: SAP Context + + RETURN VALUE + NA + + SIDE EFFECTS +============================================================================*/ +static VOS_STATUS sapGet5GHzChannelList(ptSapContext sapContext); + +/*========================================================================== + FUNCTION sapStopDfsCacTimer + + DESCRIPTION + Function to sttop the DFS CAC timer when SAP is stopped + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext: SAP Context + RETURN VALUE + DFS Timer start status + SIDE EFFECTS +============================================================================*/ + +static int sapStopDfsCacTimer(ptSapContext sapContext); + +/*========================================================================== + FUNCTION sapStartDfsCacTimer + + DESCRIPTION + Function to start the DFS CAC timer when SAP is started on DFS Channel + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext: SAP Context + RETURN VALUE + DFS Timer start status + SIDE EFFECTS +============================================================================*/ + +int sapStartDfsCacTimer(ptSapContext sapContext); + +/*---------------------------------------------------------------------------- + * Externalized Function Definitions +* -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + FUNCTION sapEventInit + + DESCRIPTION + Function for initializing sWLAN_SAPEvent structure + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapEvent : State machine event + + RETURN VALUE + + None + + SIDE EFFECTS +============================================================================*/ +static inline void sapEventInit(ptWLAN_SAPEvent sapEvent) +{ + sapEvent->event = eSAP_MAC_SCAN_COMPLETE; + sapEvent->params = 0; + sapEvent->u1 = 0; + sapEvent->u2 = 0; +} + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION +/* + * This function gives the leakage matrix for given NOL channel and cbMode + * + * PARAMETERS + * IN + * sapContext : Pointer to vos global context structure + * cbMode : target channel bonding mode + * NOL_channel : the NOL channel whose leakage matrix is required + * pTarget_chnl_mtrx : pointer to target channel matrix returned. + * + * RETURN VALUE + * BOOLEAN + * TRUE: leakage matrix was found + * FALSE: leakage matrix was not found + */ +v_BOOL_t +sapFindTargetChannelInChannelMatrix(ptSapContext sapContext, + ePhyChanBondState cbMode, + v_U8_t NOL_channel, + tSapTxLeakInfo **pTarget_chnl_mtrx) +{ + tSapTxLeakInfo *target_chan_matrix = NULL; + tSapChanMatrixInfo *pchan_matrix = NULL; + v_U32_t nchan_matrix; + int i = 0; + + switch (cbMode) { + case PHY_SINGLE_CHANNEL_CENTERED: + /* HT20 */ + pchan_matrix = ht20_chan; + nchan_matrix = sizeof(ht20_chan)/sizeof(tSapChanMatrixInfo); + break; + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + /* HT40 */ + pchan_matrix = ht40_chan; + nchan_matrix = sizeof(ht40_chan)/sizeof(tSapChanMatrixInfo); + break; +#ifdef WLAN_FEATURE_11AC + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + /* HT80 */ + pchan_matrix = ht80_chan; + nchan_matrix = sizeof(ht80_chan)/sizeof(tSapChanMatrixInfo); + break; +#endif + default: + /* handle exception and fall back to HT20 table */ + pchan_matrix = ht20_chan; + nchan_matrix = sizeof(ht20_chan)/sizeof(tSapChanMatrixInfo); + break; + } + + for (i = 0; i < nchan_matrix; i++) + { + /* find the SAP channel to map the leakage matrix */ + if (NOL_channel == pchan_matrix[i].channel) + { + target_chan_matrix = pchan_matrix[i].chan_matrix; + break; + } + } + + if (NULL == target_chan_matrix) + { + return VOS_FALSE; + } else { + *pTarget_chnl_mtrx = target_chan_matrix; + return VOS_TRUE; + } +} + +/* + * This function removes the channels from temp channel list that + * (if selected as target channel) will cause leakage in one of + * the NOL channels + * + * PARAMETERS + * IN + * sapContext : Pointer to vos global context structure + * cbMode : target channel bonding mode + * pNol : DFS NOL + * pTempChannelList : the target channel list + * + * RETURN VALUE + * VOS_STATUS code associated with performing the operation + */ + +VOS_STATUS +sapMarkChannelsLeakingIntoNOL(ptSapContext sapContext, + ePhyChanBondState cbMode, + tSapDfsNolInfo *pNol, + v_U8_t tempChannelListSize, + v_U8_t *pTempChannelList) +{ + tSapTxLeakInfo *target_chan_matrix = NULL; +#ifdef FEATURE_WLAN_CH144 + v_U32_t num_channel = (RF_CHAN_144 - RF_CHAN_36) + 1; +#else + v_U32_t num_channel = (RF_CHAN_140 - RF_CHAN_36) + 1; +#endif + v_U32_t i = 0; + v_U32_t j = 0; + v_U32_t k = 0; + v_U8_t dfs_nol_channel; + + + /* traverse target_chan_matrix and */ + for (i = 0; i < NUM_5GHZ_CHANNELS ; i++) { + dfs_nol_channel = pNol[i].dfs_channel_number; + if ( pNol[i].radar_status_flag == eSAP_DFS_CHANNEL_USABLE || + pNol[i].radar_status_flag == eSAP_DFS_CHANNEL_AVAILABLE ) { + /* not present in NOL */ + continue; + } + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_DEBUG, + FL("sapdfs: processing NOL channel: %d"), + dfs_nol_channel ); + if (VOS_FALSE == sapFindTargetChannelInChannelMatrix(sapContext, + cbMode, + dfs_nol_channel, + &target_chan_matrix)) + { + /* + * should never happen, we should always find a table here, + * if we don't, need a fix here! + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Couldn't find target channel matrix!")); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* + * following is based on assumption that both pTempChannelList + * and target channel matrix are in increasing order of channelID + */ + for (j = 0, k = 0; j < tempChannelListSize && + k < num_channel; ) { + if (pTempChannelList[j] == 0) { + j++; + } else { + if (target_chan_matrix[k].leak_chan != pTempChannelList[j]) { + k++; + } else { + /* check leakage from candidate channel to NOL channel */ + if (target_chan_matrix[k].leak_lvl <= SAP_TX_LEAKAGE_THRES) + { + /* + * this means that candidate channel will have bad + * leakage in NOL channel, remove the candidate channel + * from temp list + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: channel: %d will have bad leakage" + " due to channel: %d\n"), + dfs_nol_channel, + pTempChannelList[j]); + pTempChannelList[j] = 0; + break; + } + j++; + k++; + } + } + } /* end of for loop checking temp channel list leakage into NOL */ + } /* end of loop that selects each NOL */ + return VOS_STATUS_SUCCESS; +} + +#endif // end of WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + +/* + * This function adds availabe channel to bitmap + * + * PARAMETERS + * IN + * pBitmap: bitmap to populate + * channel: channel to set in bitmap + */ +static void sapSetBitmap(chan_bonding_bitmap *pBitmap, v_U8_t channel) +{ + int i = 0; + int start_channel = 0; + for ( i = 0; i < MAX_80MHZ_BANDS; i++ ) { + start_channel = pBitmap->chanBondingSet[i].startChannel; + if (channel >= start_channel && channel <= start_channel + 12) { + pBitmap->chanBondingSet[i].channelMap |= + 1 << ((channel - start_channel)/4); + return; + } + } + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Channel=%d is not in the bitmap"), channel); +} + +/* + * This function reads the bitmap and populates available channel + * list according to channel bonding mode. This will be called for + * 80 MHz and 40 Mhz only. For 20 MHz no need for bitmap hence list + * is directly created while parsing the main list + * + * PARAMETERS + * IN + * pBitmap: bitmap to populate + * cbModeCurrent: cb mode to check for channel availability + * availableChannels: available channel list to populate + * + * RETURN VALUE + * number of channels found + */ +static v_U8_t sapPopulateAvailableChannels(chan_bonding_bitmap *pBitmap, + ePhyChanBondState cbModeCurrent, + v_U8_t *availableChannels) +{ + v_U8_t i = 0; + v_U8_t channelCount = 0; + v_U8_t start_channel = 0; + + switch (cbModeCurrent) { +#ifdef WLAN_FEATURE_11AC + /* HT80 */ + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + for ( i = 0; i < MAX_80MHZ_BANDS; i++ ) { + start_channel = pBitmap->chanBondingSet[i].startChannel; + if (pBitmap->chanBondingSet[i].channelMap == SAP_80MHZ_MASK) { + availableChannels[channelCount++] = start_channel; + availableChannels[channelCount++] = start_channel + 4; + availableChannels[channelCount++] = start_channel + 8; + availableChannels[channelCount++] = start_channel + 12; + } + } + break; +#endif + /* HT40 */ + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + for ( i = 0; i < MAX_80MHZ_BANDS; i++ ) { + start_channel = pBitmap->chanBondingSet[i].startChannel; + if ((pBitmap->chanBondingSet[i].channelMap & SAP_40MHZ_MASK_L) + == SAP_40MHZ_MASK_L) { + availableChannels[channelCount++] = start_channel; + availableChannels[channelCount++] = start_channel + 4; + } else { + if ((pBitmap->chanBondingSet[i].channelMap & + SAP_40MHZ_MASK_H) == SAP_40MHZ_MASK_H) { + availableChannels[channelCount++] = start_channel + 8; + availableChannels[channelCount++] = start_channel + 12; + } + } + } + break; + default: + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Invalid case.")); + break; + } + + return channelCount; +} + +/* + * FUNCTION sapDfsIsW53Invalid + * + * DESCRIPTION Checks if the passed channel is W53 and returns if + * SAP W53 opearation is allowed. + * + * DEPENDENCIES PARAMETERS + * IN hHAL : HAL pointer + * channelID: Channel Number to be verified + * + * RETURN VALUE : v_BOOL_t + * VOS_TRUE: If W53 operation is disabled + * VOS_FALSE: If W53 operation is enabled + * + * SIDE EFFECTS + */ +v_BOOL_t sapDfsIsW53Invalid(tHalHandle hHal, v_U8_t channelID) +{ + tpAniSirGlobal pMac; + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("invalid pMac")); + return VOS_FALSE; + } + + /* + * Check for JAPAN W53 Channel operation capability + */ + if (VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_w53_disabled && + VOS_TRUE == IS_CHAN_JAPAN_W53(channelID)) + { + return VOS_TRUE; + } + + return VOS_FALSE; +} + +/* + * FUNCTION sapDfsIsChannelInPreferredLocation + * + * DESCRIPTION Checks if the passed channel is in accordance with preferred + * Channel location settings. + * + * DEPENDENCIES PARAMETERS + * IN hHAL : HAL pointer + * channelID: Channel Number to be verified + * + * RETURN VALUE :v_BOOL_t + * VOS_TRUE:If Channel location is same as the preferred location + * VOS_FALSE:If Channel location is not same as the preferred location + * + * SIDE EFFECTS + */ +v_BOOL_t sapDfsIsChannelInPreferredLocation(tHalHandle hHal, v_U8_t channelID) +{ + tpAniSirGlobal pMac; + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("invalid pMac")); + return VOS_TRUE; + } + if ( (SAP_CHAN_PREFERRED_INDOOR == + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location) && + (VOS_TRUE == IS_CHAN_JAPAN_OUTDOOR(channelID)) ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("CHAN=%d is Outdoor so invalid,preferred Indoor only"), + channelID); + return VOS_FALSE; + } + else if ( (SAP_CHAN_PREFERRED_OUTDOOR == + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location) && + (VOS_TRUE == IS_CHAN_JAPAN_INDOOR(channelID)) ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("CHAN=%d is Indoor so invalid,preferred Outdoor only"), + channelID); + return VOS_FALSE; + } + + return VOS_TRUE; +} + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * sap_check_in_avoid_ch_list() - checks if given channel present is channel + * avoidance list + * avoid_channels_info struct + * @sap_ctx: sap context. + * @channel: channel to be checked in sap_ctx's avoid ch list + * + * sap_ctx contains sap_avoid_ch_info strcut containing the list of channels on + * which MDM device's AP with MCC was detected. This function checks if given + * channel is present in that list. + * + * Return: true, if channel was present, false othersie. + */ +bool +sap_check_in_avoid_ch_list(ptSapContext sap_ctx, uint8_t channel) +{ + uint8_t i = 0; + struct sap_avoid_channels_info *ie_info = + &sap_ctx->sap_detected_avoid_ch_ie; + + for (i = 0; i < sizeof(ie_info->channels); i++) { + if (ie_info->channels[i] == channel) + return true; + } + return false; +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/* + * This function randomly pick up an AVAILABLE channel + */ +static v_U8_t sapRandomChannelSel(ptSapContext sapContext) +{ + v_U32_t random_byte = 0; + v_U8_t available_chnl_count = 0; + uint8_t avail_dfs_chan_count = 0; + uint8_t avail_non_dfs_chan_count = 0; + v_U8_t valid_chnl_count = 0; + v_U8_t availableChannels[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0,}; + uint8_t avail_dfs_chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0,}; + uint8_t avail_non_dfs_chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0,}; + v_U8_t target_channel = 0; + v_BOOL_t isChannelNol = VOS_FALSE; + v_BOOL_t isOutOfRange = VOS_FALSE; + chan_bonding_bitmap channelBitmap; + v_U8_t i = 0; + v_U8_t channelID; + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal pMac; + tANI_U32 chanWidth; + ePhyChanBondState cbModeCurrent; + v_U8_t *tempChannels = NULL; + uint8_t dfs_region; + + if (NULL == hHal) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("invalid hHal")); + return target_channel; + } + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("invalid pMac")); + return target_channel; + } + + /* + * Retrieve the original one and store it. + * use the stored original value when you call this function next time + * so fall back mechanism always starts with original ini value. + */ + + if (pMac->sap.SapDfsInfo.orig_cbMode == 0) + { + pMac->sap.SapDfsInfo.orig_cbMode = sme_SelectCBMode(hHal, + sapContext->csrRoamProfile.phyMode, + sapContext->channel, + sapContext->secondary_ch, + &sapContext->vht_channel_width, + sapContext->ch_width_orig); + pMac->sap.SapDfsInfo.orig_cbMode = csrConvertCBIniValueToPhyCBState( + pMac->sap.SapDfsInfo.orig_cbMode); + cbModeCurrent = pMac->sap.SapDfsInfo.orig_cbMode; + } + else + { + cbModeCurrent = pMac->sap.SapDfsInfo.orig_cbMode; + } + + /* + * Retrieve the original one and store it. + * use the stored original value when you call this function next time + * so fall back mechanism always starts with original ini value. + */ + if (pMac->sap.SapDfsInfo.orig_chanWidth == 0) + { + pMac->sap.SapDfsInfo.orig_chanWidth = + sapContext->ch_width_orig; + chanWidth = pMac->sap.SapDfsInfo.orig_chanWidth; + } + else + { + chanWidth = pMac->sap.SapDfsInfo.orig_chanWidth; + } + + if (sapGet5GHzChannelList(sapContext)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("Getting 5Ghz channel list failed")); + return target_channel; + } + + vos_nv_get_dfs_region(&dfs_region); + + /* + * valid_chnl_count will be used to find number of valid channels + * after following for loop ends + */ + valid_chnl_count = sapContext->SapAllChnlList.numChannel; + /* loop to check ACS range or NOL channels */ + for (i = 0; i < sapContext->SapAllChnlList.numChannel; i++) + { + channelID = sapContext->SapAllChnlList.channelList[i].channel; + + /* + * IN JAPAN REGULATORY DOMAIN CHECK IF THE FOLLOWING TWO + * TWO RULES APPLY AND FILTER THE AVAILABLE CHANNELS + * ACCORDINGLY. + * + * 1. If we are operating in Japan regulatory domain + * Check if Japan W53 Channel operation is NOT + * allowed and if its not allowed then mark all the + * W53 channels as Invalid. + * + * 2. If we are operating in Japan regulatory domain + * Check if channel switch between Indoor/Outdoor + * is allowed. If it is not allowed then limit + * the avaiable channels to Indoor or Outdoor + * channels only based up on the SAP Channel location + * indicated by "sap_operating_channel_location" param. + */ + if (DFS_MKK4_DOMAIN == dfs_region) + { + /* + * Check for JAPAN W53 Channel operation capability + */ + if (VOS_TRUE == sapDfsIsW53Invalid(hHal, channelID)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("index:%d, Channel=%d Invalid,Japan W53 Disabled"), + i, channelID); + sapContext->SapAllChnlList.channelList[i].valid = VOS_FALSE; + valid_chnl_count--; + continue; + } + + /* + * If SAP's preferred channel location is Indoor + * then set all the outdoor channels in the domain + * to invalid.If the preferred channel location is + * outdoor then set all the Indoor channels in the + * domain to Invalid. + */ + if (VOS_FALSE == + sapDfsIsChannelInPreferredLocation(hHal, channelID)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("CHAN=%d is invalid,preferred Channel Location %d Only"), + channelID, + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location); + sapContext->SapAllChnlList.channelList[i].valid = VOS_FALSE; + valid_chnl_count--; + continue; + } + } + + if (vos_nv_getChannelEnabledState(channelID) == NV_CHANNEL_DFS) + { + isChannelNol = sapDfsIsChannelInNolList(sapContext, + channelID, + PHY_SINGLE_CHANNEL_CENTERED); + if (VOS_TRUE == isChannelNol) + { + /* + * Mark this channel invalid since it is still in + * DFS Non-Occupancy-Period which is 30 mins. + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("index: %d, Channel = %d Present in NOL"), + i, channelID); + sapContext->SapAllChnlList.channelList[i].valid = VOS_FALSE; + valid_chnl_count--; + continue; + } + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* avoid channels on which another MDM AP in MCC mode is detected. */ + if (pMac->sap.sap_channel_avoidance + && sapContext->sap_detected_avoid_ch_ie.present) { + if (sap_check_in_avoid_ch_list(sapContext, channelID)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("index: %d, Channel = %d, avoided due to " + "presence of another AP+AP MCC device in same " + "channel."), + i, channelID); + sapContext->SapAllChnlList.channelList[i].valid = VOS_FALSE; + } + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + /* check if the channel is within ACS channel range */ + isOutOfRange = sapAcsChannelCheck(sapContext, + channelID); + if (VOS_TRUE == isOutOfRange) + { + /* + * mark this channel invalid since it is out of ACS channel range + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("index: %d, Channel = %d out of ACS channel range"), + i, channelID); + sapContext->SapAllChnlList.channelList[i].valid = VOS_FALSE; + valid_chnl_count--; + continue; + } + } /* end of check for NOL or ACS channels */ + + /* valid_chnl_count now have number of valid channels */ + tempChannels = vos_mem_malloc(valid_chnl_count); + if (tempChannels == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("sapdfs: memory alloc failed")); + return target_channel; + } + + do + { + v_U8_t j = 0; +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + tSapDfsNolInfo *pNol = pMac->sap.SapDfsInfo.sapDfsChannelNolList; +#endif + + /* prepare temp list of just the valid channels */ + for (i = 0; i < sapContext->SapAllChnlList.numChannel; i++) { + if (sapContext->SapAllChnlList.channelList[i].valid) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("sapdfs: Adding Channel = %d to temp List"), + sapContext->SapAllChnlList.channelList[i].channel); + tempChannels[j++] = + sapContext->SapAllChnlList.channelList[i].channel; + } + } + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("sapdfs: Processing temp channel list against NOL.")); + if (VOS_STATUS_SUCCESS != sapMarkChannelsLeakingIntoNOL(sapContext, + cbModeCurrent, + pNol, + valid_chnl_count, + tempChannels)) { + vos_mem_free(tempChannels); + return target_channel; + } +#endif + vos_mem_zero(availableChannels, sizeof(availableChannels)); + vos_mem_zero(&channelBitmap, sizeof(channelBitmap)); + channelBitmap.chanBondingSet[0].startChannel = 36; + channelBitmap.chanBondingSet[1].startChannel = 52; + channelBitmap.chanBondingSet[2].startChannel = 100; + channelBitmap.chanBondingSet[3].startChannel = 116; + channelBitmap.chanBondingSet[3].startChannel = 132; + channelBitmap.chanBondingSet[4].startChannel = 149; + /* now loop through whatever is left of channel list */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("sapdfs: Moving temp channel list to final.")); + for (i = 0; i < valid_chnl_count; i++ ){ + /* + * add channel from temp channel list to bitmap or fianl + * channel list (in case of 20MHz width) + */ + if (tempChannels[i] != 0) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_DEBUG, + FL("sapdfs: processing channel: %d "), + tempChannels[i]); + /* for 20MHz, directly create available channel list */ + if (cbModeCurrent == PHY_SINGLE_CHANNEL_CENTERED) { + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_DEBUG, + FL("sapdfs: Channel=%d added to available list"), + tempChannels[i]); + availableChannels[available_chnl_count++] = + tempChannels[i]; + } else { + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_DEBUG, + FL("sapdfs: Channel=%d added to bitmap"), + tempChannels[i]); + sapSetBitmap(&channelBitmap, tempChannels[i]); + } + } + } + + /* if 40 MHz or 80 MHz, populate available channel list from bitmap */ + if (cbModeCurrent != PHY_SINGLE_CHANNEL_CENTERED) { + available_chnl_count = sapPopulateAvailableChannels(&channelBitmap, + cbModeCurrent, + availableChannels); + /* if no valid channel bonding found, fallback to lower bandwidth */ + if (available_chnl_count == 0) { + if (cbModeCurrent >= + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED) { + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_WARN, + FL("sapdfs:No 80MHz cb found, falling to 40MHz")); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_WARN, + FL("sapdfs:Changing chanWidth from [%d] to [%d]"), + chanWidth, eHT_CHANNEL_WIDTH_40MHZ); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_WARN, + FL("sapdfs:Changing CB mode from [%d] to [%d]"), + cbModeCurrent, PHY_DOUBLE_CHANNEL_LOW_PRIMARY); + cbModeCurrent = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + chanWidth = eHT_CHANNEL_WIDTH_40MHZ; + /* continue to start of do loop */ + continue; + } else if (cbModeCurrent >= + PHY_DOUBLE_CHANNEL_LOW_PRIMARY ) { + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_WARN, + FL("sapdfs:No 40MHz cb found, falling to 20MHz")); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_WARN, + FL("sapdfs:Changing chanWidth from [%d] to [%d]"), + chanWidth, eHT_CHANNEL_WIDTH_20MHZ); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_WARN, + FL("sapdfs:Changing CB mode from [%d] to [%d]"), + cbModeCurrent, PHY_SINGLE_CHANNEL_CENTERED); + cbModeCurrent = PHY_SINGLE_CHANNEL_CENTERED; + chanWidth = eHT_CHANNEL_WIDTH_20MHZ; + /* continue to start of do loop */ + continue; + } + } + } + + /* + * by now, available channels list will be populated or + * no channels are avaialbe + */ + if (available_chnl_count) { + for (i=0;if_prefer_non_dfs_on_radar) { + i = (random_byte + vos_timer_get_system_ticks()) % + available_chnl_count; + target_channel = availableChannels[i]; + } else if (avail_non_dfs_chan_count) { + i = (random_byte + vos_timer_get_system_ticks()) % + avail_non_dfs_chan_count; + target_channel = avail_non_dfs_chan_list[i]; + } else { + i = (random_byte + vos_timer_get_system_ticks()) % + avail_dfs_chan_count; + target_channel = avail_dfs_chan_list[i]; + } + + pMac->sap.SapDfsInfo.new_chanWidth = chanWidth; + pMac->sap.SapDfsInfo.new_cbMode = cbModeCurrent; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: New CB mode = %d"), + pMac->sap.SapDfsInfo.new_cbMode); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: New Channel width = %d"), + pMac->sap.SapDfsInfo.new_chanWidth); + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: target_channel = %d"), target_channel); + break; + } while(1); /* this loop will iterate at max 3 times */ + + vos_mem_free(tempChannels); + return target_channel; +} + +v_BOOL_t +sapAcsChannelCheck(ptSapContext sapContext, v_U8_t channelNumber) +{ + int i = 0; + if (!sapContext->acs_cfg->acs_mode) + return VOS_FALSE; + + if ((channelNumber >= sapContext->acs_cfg->start_ch) || + (channelNumber <= sapContext->acs_cfg->end_ch)) { + if (!sapContext->acs_cfg->ch_list) { + return VOS_FALSE; + } else { + for (i = 0; i < sapContext->acs_cfg->ch_list_count; i++) + if (channelNumber == sapContext->acs_cfg->ch_list[i]) + return VOS_FALSE; + } + } + return VOS_TRUE; +} + +/* + * Mark the channels in NOL with time and eSAP_DFS_CHANNEL_UNAVAILABLE + */ +void sapMarkDfsChannels(ptSapContext sapContext, v_U8_t* channels, + v_U8_t numChannels, v_U64_t time) +{ + int i, j; + tSapDfsNolInfo *psapDfsChannelNolList = NULL; + v_U8_t nRegDomainDfsChannels; + tHalHandle hHal; + tpAniSirGlobal pMac; + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + + if (NULL == channels) + return; + + if (NULL == hHal) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("invalid hHal")); + return; + } + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("invalid pMac")); + return; + } + + /* + * Mark the current channel on which Radar is found + * in the NOL list as eSAP_DFS_CHANNEL_UNAVAILABLE. + */ + + psapDfsChannelNolList = pMac->sap.SapDfsInfo.sapDfsChannelNolList; + nRegDomainDfsChannels = pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; + + for (i = 0; i < numChannels; i++) { + for (j = 0; j <= nRegDomainDfsChannels; j++) + { + if (psapDfsChannelNolList[j].dfs_channel_number == + channels[i]) + { + /* If channel is already in NOL, don't update it again. + * This is useful when marking bonding channels which are + * already unavailable. + */ + if( psapDfsChannelNolList[j].radar_status_flag == + eSAP_DFS_CHANNEL_UNAVAILABLE) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Channel=%d already in NOL"), + channels[i]); + } + else + { + /* + * Capture the Radar Found timestamp on the Current + * Channel in ms. + */ + psapDfsChannelNolList[j].radar_found_timestamp = time; + /* Mark the Channel to be UNAVAILABLE for next 30 mins */ + psapDfsChannelNolList[j].radar_status_flag = + eSAP_DFS_CHANNEL_UNAVAILABLE; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Channel=%d Added to NOL LIST"), + channels[i]); + } + } + } + } +} + + +/* + * This Function is to get bonding channels from primary channel. + * + */ +v_U8_t sapGetBondingChannels(ptSapContext sapContext, v_U8_t channel, + v_U8_t* channels, v_U8_t size, ePhyChanBondState chanBondState) +{ + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal pMac; + v_U8_t numChannel; + + if(channels == NULL) + return 0; + + if(size < MAX_BONDED_CHANNELS) return 0; + + if (NULL != hHal) + { + pMac = PMAC_STRUCT( hHal ); + } + else + return 0; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("cbmode: %d, channel: %d"), + chanBondState, channel); + + switch (chanBondState) { + case PHY_SINGLE_CHANNEL_CENTERED: + numChannel = 1; + channels[0] = channel; + break; + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + numChannel = 2; + channels[0] = channel - 4; + channels[1] = channel; + break; + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + numChannel = 2; + channels[0] = channel; + channels[1] = channel + 4; + break; +#ifdef WLAN_FEATURE_11AC + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + numChannel = 4; + channels[0] = channel; + channels[1] = channel + 4; + channels[2] = channel + 8; + channels[3] = channel + 12; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + numChannel = 4; + channels[0] = channel - 4; + channels[1] = channel; + channels[2] = channel + 4; + channels[3] = channel + 8; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + numChannel = 4; + channels[0] = channel - 8; + channels[1] = channel - 4; + channels[2] = channel; + channels[3] = channel + 4; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + numChannel = 4; + channels[0] = channel - 12; + channels[1] = channel - 8; + channels[2] = channel - 4; + channels[3] = channel; + break; +#endif + default: + numChannel = 1; + channels[0] = channel; + break; + } + + return numChannel; +} + +/* + * This Function Checks if a given bonded channel is AVAILABLE or USABLE + * for DFS operation. + */ +v_BOOL_t +sapDfsIsChannelInNolList(ptSapContext sapContext, v_U8_t channelNumber, + ePhyChanBondState chanBondState) +{ + int i, j; + v_U64_t timeElapsedSinceLastRadar,timeWhenRadarFound,currentTime = 0; + v_U64_t max_jiffies; + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal pMac; + v_U8_t channels[MAX_BONDED_CHANNELS]; + v_U8_t numChannels; + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return VOS_FALSE; + } + else + { + pMac = PMAC_STRUCT( hHal ); + } + + if ((pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels == 0) || + (pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels > + NUM_5GHZ_CHANNELS)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s: invalid dfs channel count %d", + __func__, + pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels); + return VOS_FALSE; + } + + /* get the bonded channels */ + numChannels = sapGetBondingChannels(sapContext, channelNumber, channels, + MAX_BONDED_CHANNELS, chanBondState ); + + /* check for NOL, first on will break the loop */ + for (j=0; j < numChannels; j++) + { + for (i =0 ; i< pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; i++) + { + if(pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .dfs_channel_number == channels[j]) + { + if ( (pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_status_flag == eSAP_DFS_CHANNEL_USABLE) + || + (pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_status_flag == eSAP_DFS_CHANNEL_AVAILABLE) ) + { + /* + * Allow SAP operation on this channel + * either the DFS channel has not been used + * for SAP operation or it is available for + * SAP operation since it is past Non-Occupancy-Period + * so, return FALSE. + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("Channel = %d not in NOL, CHANNEL AVAILABLE"), + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .dfs_channel_number); + } + else if (pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_status_flag == eSAP_DFS_CHANNEL_UNAVAILABLE) + { + /* + * If a DFS Channel is UNAVAILABLE then + * check to see if it is past Non-occupancy-period + * of 30 minutes. If it is past 30 mins then + * mark the channel as AVAILABLE and return FALSE + * as the channel is not anymore in NON-Occupancy-Period. + */ + timeWhenRadarFound = pMac->sap.SapDfsInfo + .sapDfsChannelNolList[i] + .radar_found_timestamp; + currentTime = vos_get_monotonic_boottime(); + + if (currentTime < timeWhenRadarFound) { + /* vos_get_monotonic_boottime() can overflow. Jiffies is + * initialized such that 32 bit jiffies value wrap 5 minutes + * after boot so jiffies wrap bugs show up earlier. + */ + max_jiffies = (v_U64_t)UINT_MAX * 1000; + timeElapsedSinceLastRadar = (max_jiffies - + timeWhenRadarFound) + (currentTime); + } else { + timeElapsedSinceLastRadar = currentTime - + timeWhenRadarFound; + } + if (timeElapsedSinceLastRadar >= SAP_DFS_NON_OCCUPANCY_PERIOD) + { + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_status_flag = eSAP_DFS_CHANNEL_AVAILABLE; + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_found_timestamp = 0; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("Channel=%d not in NOL, CHANNEL AVAILABLE"), + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .dfs_channel_number); + } + else + { + /* + * Channel is not still available for SAP operation + * so return TRUE; As the Channel is still + * in Non-occupancy-Period. + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + FL("Channel=%d still in NOL, CHANNEL UNAVAILABLE"), + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .dfs_channel_number); + break; + } + } + } /* if */ + } /* loop for dfs channels */ + + if (i < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels) + break; + + } /* loop for bonded channels */ + + /* if any of the channel is not available, mark all available channels as + * unavailable with same time stamp. + */ + if (j < numChannels && + i < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels) + { + if (numChannels > MAX_BONDED_CHANNELS) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + FL( "numChannels > MAX_BONDED_CHANNELS so resetting")); + numChannels = MAX_BONDED_CHANNELS; + } + sapMarkDfsChannels(sapContext, + channels, + numChannels, + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_found_timestamp); + + /* set DFS-NOL back to keep it update-to-date in CNSS */ + sapSignalHDDevent(sapContext, NULL, eSAP_DFS_NOL_SET, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + return VOS_TRUE; + } + + return VOS_FALSE; +} + + +/*========================================================================== + FUNCTION sapGotoChannelSel + + DESCRIPTION + Function for initiating scan request for SME + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + sapEvent : State machine event + sapDoAcsPreStartBss: VOS_TRUE, if ACS scan is issued pre start BSS. + VOS_FALSE, if ACS scan is issued post start BSS. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapGotoChannelSel +( + ptSapContext sapContext, + ptWLAN_SAPEvent sapEvent, + v_BOOL_t sapDoAcsPreStartBss +) +{ + /* Initiate a SCAN request */ + eHalStatus halStatus; + tCsrScanRequest scanRequest;/* To be initialised if scan is required */ + v_U32_t scanRequestID = 0; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + +#ifdef SOFTAP_CHANNEL_RANGE + v_U8_t *channelList = NULL; + v_U8_t numOfChannels = 0 ; +#endif + tHalHandle hHal; + tANI_U8 con_ch; + + hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, sapContext->pvosGCtx); + if (NULL == hHal) + { + /* we have a serious problem */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "In %s, invalid hHal", __func__); + return VOS_STATUS_E_FAULT; + } + +#ifdef WLAN_FEATURE_MBSSID + if (vos_concurrent_beaconing_sessions_running()) { + con_ch = sme_GetConcurrentOperationChannel(hHal); + + if (con_ch && sapContext->channel == AUTO_CHANNEL_SELECT) { + sapContext->dfs_ch_disable = VOS_TRUE; + } else if (con_ch && sapContext->channel != con_ch && + VOS_IS_DFS_CH(sapContext->channel)) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "In %s, MCC DFS not supported in AP_AP Mode", __func__); + return VOS_STATUS_E_ABORTED; + } +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (sapContext->cc_switch_mode != VOS_MCC_TO_SCC_SWITCH_DISABLE) { + con_ch = sme_CheckConcurrentChannelOverlap(hHal, + sapContext->channel, + sapContext->csrRoamProfile.phyMode, + sapContext->cc_switch_mode); + if (con_ch) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Override Chosen Ch:%d to %d due to CC Intf!!", + __func__,sapContext->channel, con_ch); + sapContext->channel = con_ch; + } + } +#endif + } +#endif + + if (vos_get_concurrency_mode() == VOS_STA_SAP) + { +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + if (sapContext->channel == AUTO_CHANNEL_SELECT) + sapContext->dfs_ch_disable = VOS_TRUE; + else if (VOS_IS_DFS_CH(sapContext->channel)) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "In %s, DFS not supported in STA_AP Mode", __func__); + return VOS_STATUS_E_ABORTED; + } +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (sapContext->cc_switch_mode != VOS_MCC_TO_SCC_SWITCH_DISABLE) { + con_ch = sme_CheckConcurrentChannelOverlap(hHal, + sapContext->channel, + sapContext->csrRoamProfile.phyMode, + sapContext->cc_switch_mode); + if (con_ch && !VOS_IS_DFS_CH(con_ch)) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Override Chosen Ch:%d to %d due to CC Intf!!", + __func__,sapContext->channel, con_ch); + sapContext->channel = con_ch; + } + } +#else + /* If STA-AP concurrency is enabled take the concurrent connected + * channel first. In other cases wpa_supplicant should take care */ + con_ch = sme_GetConcurrentOperationChannel(hHal); + if (con_ch) + { /*if a valid channel is returned then use concurrent channel. + Else take whatever comes from configuartion*/ + sapContext->channel = con_ch; + sme_SelectCBMode(hHal, sapContext->csrRoamProfile.phyMode, + con_ch, 0, &sapContext->vht_channel_width, + sapContext->ch_width_orig); + } +#endif + } + + if (sapContext->channel == AUTO_CHANNEL_SELECT) + { +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s acs_cfg->skip_status = %d ", __func__, + sapContext->acs_cfg->skip_scan_status); + if (sapContext->acs_cfg->skip_scan_status != eSAP_SKIP_ACS_SCAN) { +#endif + vos_mem_zero(&scanRequest, sizeof(scanRequest)); + + /* Set scanType to Active scan. FW takes care of using passive + * scan for DFS and active for non DFS channels. + */ + scanRequest.scanType = eSIR_ACTIVE_SCAN; + + /* Set min and max channel time to zero */ + scanRequest.minChnTime = 0; + scanRequest.maxChnTime = 0; + + /* Set BSSType to default type */ + scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + +#ifndef SOFTAP_CHANNEL_RANGE + /*Scan all the channels */ + scanRequest.ChannelInfo.numOfChannels = 0; + + scanRequest.ChannelInfo.ChannelList = NULL; + + scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + //eCSR_SCAN_REQUEST_11D_SCAN; + +#else + + sapGetChannelList(sapContext, &channelList, &numOfChannels); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (numOfChannels != 0) { +#endif + /*Scan the channels in the list*/ + scanRequest.ChannelInfo.numOfChannels = numOfChannels; + + scanRequest.ChannelInfo.ChannelList = channelList; + + scanRequest.requestType = eCSR_SCAN_SOFTAP_CHANNEL_RANGE; + + sapContext->channelList = channelList; + +#endif + /* Set requestType to Full scan */ + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, calling sme_ScanRequest", __func__); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (sapContext->acs_cfg->skip_scan_status == eSAP_DO_NEW_ACS_SCAN) { +#endif + sme_ScanFlushResult(hHal, sapContext->sessionId); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + } +#endif + + if (VOS_TRUE == sapDoAcsPreStartBss) + { + halStatus = sme_ScanRequest(hHal, + sapContext->sessionId, + &scanRequest, + /* when ID == 0 11D scan/active + * scan with callback, + * min-maxChntime set in csrScanRequest()? + */ + &scanRequestID, + /*csrScanCompleteCallback callback,*/ + &WLANSAP_PreStartBssAcsScanCallback, + /* pContext scanRequestID filled up*/ + sapContext); + + } + else + { + halStatus = sme_ScanRequest(hHal, + sapContext->sessionId, + &scanRequest, + /* when ID == 0 11D scan/active + * scan with callback, + * min-maxChntime set in csrScanRequest()? + */ + &scanRequestID, + /*csrScanCompleteCallback callback,*/ + &WLANSAP_ScanCallback, + /* pContext scanRequestID filled up*/ + sapContext); + } + if (eHAL_STATUS_SUCCESS != halStatus) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s:sme_ScanRequest fail %d!!!", __func__, halStatus); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "SoftAP Configuring for default channel, Ch= %d", + sapContext->channel); + /* In case of error, switch to default channel */ + sapContext->channel = SAP_DEFAULT_24GHZ_CHANNEL; + +#ifdef SOFTAP_CHANNEL_RANGE + if(sapContext->channelList != NULL) + { + sapContext->channel = sapContext->channelList[0]; + vos_mem_free(sapContext->channelList); + sapContext->channelList = NULL; + } +#endif + if (VOS_TRUE == sapDoAcsPreStartBss) + { + /* + * In case of ACS req before start Bss, + * return failure so that the calling + * fucntion can use the default channel. + */ + return VOS_STATUS_E_FAILURE; + } + else + { + /* Fill in the event structure */ + sapEventInit(sapEvent); + /* Handle event */ + vosStatus = sapFsm(sapContext, sapEvent); + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, return from sme_ScanReq, scanID=%d, Ch= %d", + __func__, scanRequestID, sapContext->channel); + } +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + } else + sapContext->acs_cfg->skip_scan_status = eSAP_SKIP_ACS_SCAN; + } + + if (sapContext->acs_cfg->skip_scan_status == eSAP_SKIP_ACS_SCAN) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "## %s SKIPPED ACS SCAN", __func__); + if (VOS_TRUE == sapDoAcsPreStartBss) + { + WLANSAP_PreStartBssAcsScanCallback(hHal, sapContext, + sapContext->sessionId, + 0, + eCSR_SCAN_SUCCESS); + } + else + { + WLANSAP_ScanCallback(hHal, sapContext, + sapContext->sessionId, + 0, + eCSR_SCAN_SUCCESS); + } + } +#endif + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, for configured channel, Ch= %d", + __func__, sapContext->channel); + if (VOS_TRUE == sapDoAcsPreStartBss) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "In %s, ACS end due to channel override, Selected Ch= %d", + __func__, sapContext->channel); + + sapContext->acs_cfg->pri_ch = sapContext->channel; + sapContext->acs_cfg->ch_width = sapContext->ch_width_orig; + sap_config_acs_result(hHal, sapContext, 0); + return VOS_STATUS_E_CANCELED; + } + else + { + /* Fill in the event structure */ + // Eventhough scan was not done, means a user set channel was chosen + sapEventInit(sapEvent); + /* Handle event */ + vosStatus = sapFsm(sapContext, sapEvent); + } + } + + /* If scan failed, get default channel and advance state machine as success with default channel */ + /* Have to wait for the call back to be called to get the channel cannot advance state machine here as said above */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, before exiting sapGotoChannelSel channel=%d", __func__, sapContext->channel); + + return VOS_STATUS_SUCCESS; +}// sapGotoChannelSel + +/*========================================================================== + FUNCTION sap_OpenSession + + DESCRIPTION + Function for opening SME and SAP sessions when system is in SoftAP role + + DEPENDENCIES + NA. + + PARAMETERS + + IN + hHal : Hal handle + sapContext : Sap Context value + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sap_OpenSession (tHalHandle hHal, ptSapContext sapContext) +{ + tANI_U32 type, subType; + eHalStatus halStatus; + VOS_STATUS status = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (sapContext->csrRoamProfile.csrPersona == VOS_P2P_GO_MODE) + status = vos_get_vdev_types(VOS_P2P_GO_MODE, &type, &subType); + else + status = vos_get_vdev_types(VOS_STA_SAP_MODE, &type, &subType); + + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, "failed to get vdev type"); + return VOS_STATUS_E_FAILURE; + } + /* Open SME Session for Softap */ + halStatus = sme_OpenSession(hHal, + &WLANSAP_RoamCallback, + sapContext, + sapContext->self_mac_addr, + &sapContext->sessionId, + type, subType); + + if(eHAL_STATUS_SUCCESS != halStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Error: In %s calling sme_RoamConnect status = %d", + __func__, halStatus); + + return VOS_STATUS_E_FAILURE; + } + + pMac->sap.sapCtxList [ sapContext->sessionId ].sessionID = + sapContext->sessionId; + pMac->sap.sapCtxList [ sapContext->sessionId ].pSapContext = sapContext; + pMac->sap.sapCtxList [ sapContext->sessionId ].sapPersona= + sapContext->csrRoamProfile.csrPersona; + return VOS_STATUS_SUCCESS; +} + + +/*========================================================================== + FUNCTION sapGotoStarting + + DESCRIPTION + Function for initiating start bss request for SME + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + sapEvent : State machine event + bssType : Type of bss to start, INRA AP + status : Return the SAP status here + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapGotoStarting +( + ptSapContext sapContext, + ptWLAN_SAPEvent sapEvent, + eCsrRoamBssType bssType +) +{ + /* tHalHandle */ + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + eHalStatus halStatus; + + /*- - - - - - - - TODO:once configs from hdd available - - - - - - - - -*/ + char key_material[32]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,}; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + sapContext->key_type = 0x05; + sapContext->key_length = 32; + vos_mem_copy(sapContext->key_material, key_material, sizeof(key_material)); /* Need a key size define */ + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s", __func__); + + if (NULL == hHal) + { + /* we have a serious problem */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "In %s, invalid hHal", __func__); + return VOS_STATUS_E_FAULT; + } + + /* No Need to Req for Power with power offload enabled */ + if(!pMac->psOffloadEnabled) + { + //TODO: What shall we do if failure???? + halStatus = pmcRequestFullPower( hHal, + WLANSAP_pmcFullPwrReqCB, + sapContext, + eSME_REASON_OTHER); + } + + halStatus = sap_OpenSession(hHal, sapContext); + + if(eHAL_STATUS_SUCCESS != halStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Error: In %s calling sap_OpenSession status = %d", + __func__, halStatus); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +}// sapGotoStarting + +/*========================================================================== + FUNCTION sapGotoDisconnecting + + DESCRIPTION + Processing of SAP FSM Disconnecting state + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + status : Return the SAP status here + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapGotoDisconnecting +( + ptSapContext sapContext +) +{ + eHalStatus halStatus; + tHalHandle hHal; + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + /* we have a serious problem */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, invalid hHal", __func__); + return VOS_STATUS_E_FAULT; + } + + sapFreeRoamProfile(&sapContext->csrRoamProfile); + halStatus = sme_RoamStopBss(hHal, sapContext->sessionId); + if(eHAL_STATUS_SUCCESS != halStatus ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "Error: In %s calling sme_RoamStopBss status = %d", __func__, halStatus); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +static eHalStatus sapRoamSessionCloseCallback(void *pContext) +{ + ptSapContext sapContext = (ptSapContext)pContext; + return sapSignalHDDevent(sapContext, NULL, + eSAP_STOP_BSS_EVENT, (v_PVOID_t) eSAP_STATUS_SUCCESS); +} + +/*========================================================================== + FUNCTION sapGotoDisconnected + + DESCRIPTION + Function for setting the SAP FSM to Disconnection state + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + sapEvent : State machine event + status : Return the SAP status here + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapGotoDisconnected +( + ptSapContext sapContext +) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + tWLAN_SAPEvent sapEvent; + // Processing has to be coded + // Clean up stations from TL etc as AP BSS is shut down then set event + sapEvent.event = eSAP_MAC_READY_FOR_CONNECTIONS;// hardcoded + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + /* Handle event */ + vosStatus = sapFsm(sapContext, &sapEvent); + + return vosStatus; +} + +/*========================================================================== + FUNCTION sapSignalHDDevent + + DESCRIPTION + Function for HDD to send the event notification using callback + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + pCsrRoamInfo : Pointer to CSR roam information + sapHddevent : SAP HDD event + context : to pass the element for future support + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapSignalHDDevent +( + ptSapContext sapContext, /* sapContext value */ + tCsrRoamInfo *pCsrRoamInfo, + eSapHddEvent sapHddevent, + void *context +) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tSap_Event sapApAppEvent; /* This now encodes ALL event types */ + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal pMac; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /* Format the Start BSS Complete event to return... */ + if (NULL == sapContext->pfnSapEventCallback) + { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return VOS_STATUS_E_FAILURE; + } + pMac = PMAC_STRUCT( hHal ); + + switch (sapHddevent) + { + case eSAP_STA_ASSOC_IND: + // TODO - Indicate the assoc request indication to OS + sapApAppEvent.sapHddEventCode = eSAP_STA_ASSOC_IND; + + vos_mem_copy( &sapApAppEvent.sapevt.sapAssocIndication.staMac, pCsrRoamInfo->peerMac,sizeof(tSirMacAddr)); + sapApAppEvent.sapevt.sapAssocIndication.staId = pCsrRoamInfo->staId; + sapApAppEvent.sapevt.sapAssocIndication.status = 0; + // Required for indicating the frames to upper layer + sapApAppEvent.sapevt.sapAssocIndication.beaconLength = pCsrRoamInfo->beaconLength; + sapApAppEvent.sapevt.sapAssocIndication.beaconPtr = pCsrRoamInfo->beaconPtr; + sapApAppEvent.sapevt.sapAssocIndication.assocReqLength = pCsrRoamInfo->assocReqLength; + sapApAppEvent.sapevt.sapAssocIndication.assocReqPtr = pCsrRoamInfo->assocReqPtr; + sapApAppEvent.sapevt.sapAssocIndication.fWmmEnabled = pCsrRoamInfo->wmmEnabledSta; + if ( pCsrRoamInfo->u.pConnectedProfile != NULL ) + { + sapApAppEvent.sapevt.sapAssocIndication.negotiatedAuthType = pCsrRoamInfo->u.pConnectedProfile->AuthType; + sapApAppEvent.sapevt.sapAssocIndication.negotiatedUCEncryptionType = pCsrRoamInfo->u.pConnectedProfile->EncryptionType; + sapApAppEvent.sapevt.sapAssocIndication.negotiatedMCEncryptionType = pCsrRoamInfo->u.pConnectedProfile->mcEncryptionType; + sapApAppEvent.sapevt.sapAssocIndication.fAuthRequired = pCsrRoamInfo->fAuthRequired; + } + break; + case eSAP_START_BSS_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_START_BSS_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_START_BSS_EVENT; + sapApAppEvent.sapevt.sapStartBssCompleteEvent.status = (eSapStatus )context; + if(pCsrRoamInfo != NULL ){ + sapApAppEvent.sapevt.sapStartBssCompleteEvent.staId = pCsrRoamInfo->staId; + } + else + { + sapApAppEvent.sapevt.sapStartBssCompleteEvent.staId = 0; + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s(eSAP_START_BSS_EVENT): staId = %d", + __func__, sapApAppEvent.sapevt.sapStartBssCompleteEvent.staId); + + sapApAppEvent.sapevt.sapStartBssCompleteEvent.operatingChannel = (v_U8_t)sapContext->channel; + sapApAppEvent.sapevt.sapStartBssCompleteEvent.sessionId = + sapContext->sessionId; + break; + + case eSAP_DFS_CAC_START: + case eSAP_DFS_CAC_INTERRUPTED: + case eSAP_DFS_CAC_END: + case eSAP_DFS_RADAR_DETECT: + case eSAP_DFS_NO_AVAILABLE_CHANNEL: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s : %d", __func__, + "eSAP_DFS event", sapHddevent); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + case eSAP_ACS_SCAN_SUCCESS_EVENT: +#endif + sapApAppEvent.sapHddEventCode = sapHddevent; + sapApAppEvent.sapevt.sapStopBssCompleteEvent.status = + (eSapStatus )context; + break; + + case eSAP_ACS_CHANNEL_SELECTED: + sapApAppEvent.sapHddEventCode = sapHddevent; + if ( eSAP_STATUS_SUCCESS == (eSapStatus )context) + { + sapApAppEvent.sapevt.sapChSelected.pri_ch = + sapContext->acs_cfg->pri_ch; + sapApAppEvent.sapevt.sapChSelected.ht_sec_ch = + sapContext->acs_cfg->ht_sec_ch; + sapApAppEvent.sapevt.sapChSelected.ch_width = + sapContext->acs_cfg->ch_width; + sapApAppEvent.sapevt.sapChSelected.vht_seg0_center_ch = + sapContext->acs_cfg->vht_seg0_center_ch; + sapApAppEvent.sapevt.sapChSelected.vht_seg1_center_ch = + sapContext->acs_cfg->vht_seg1_center_ch; + } + else if (eSAP_STATUS_FAILURE == (eSapStatus )context) + { + sapApAppEvent.sapevt.sapChSelected.pri_ch = 0; + } + break; + + case eSAP_STOP_BSS_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_STOP_BSS_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_STOP_BSS_EVENT; + sapApAppEvent.sapevt.sapStopBssCompleteEvent.status = (eSapStatus )context; + break; + + case eSAP_STA_ASSOC_EVENT: + case eSAP_STA_REASSOC_EVENT: + { + tSirSmeChanInfo *pChanInfo; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_STA_ASSOC_EVENT"); + if (pCsrRoamInfo->fReassocReq) + sapApAppEvent.sapHddEventCode = eSAP_STA_REASSOC_EVENT; + else + sapApAppEvent.sapHddEventCode = eSAP_STA_ASSOC_EVENT; + + //TODO: Need to fill the SET KEY information and pass to HDD + vos_mem_copy( &sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.staMac, + pCsrRoamInfo->peerMac,sizeof(tSirMacAddr)); + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.staId = pCsrRoamInfo->staId ; + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.statusCode = pCsrRoamInfo->statusCode; + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.iesLen = pCsrRoamInfo->rsnIELen; + vos_mem_copy(sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.ies, pCsrRoamInfo->prsnIE, + pCsrRoamInfo->rsnIELen); + +#ifdef FEATURE_WLAN_WAPI + if(pCsrRoamInfo->wapiIELen) + { + v_U8_t len = sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.iesLen; + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.iesLen + += pCsrRoamInfo->wapiIELen; + vos_mem_copy(&sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.ies[len], + pCsrRoamInfo->pwapiIE, + pCsrRoamInfo->wapiIELen); + } +#endif + + if(pCsrRoamInfo->addIELen) + { + v_U8_t len = sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.iesLen; + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.iesLen + += pCsrRoamInfo->addIELen; + vos_mem_copy(&sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.ies[len], pCsrRoamInfo->paddIE, + pCsrRoamInfo->addIELen); + } + + /* also fill up the channel info from the csrRoamInfo */ + pChanInfo = + &sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.chan_info; + + pChanInfo->chan_id = pCsrRoamInfo->chan_info.chan_id; + pChanInfo->mhz = pCsrRoamInfo->chan_info.mhz; + pChanInfo->info = pCsrRoamInfo->chan_info.info; + pChanInfo->band_center_freq1 = pCsrRoamInfo->chan_info.band_center_freq1; + pChanInfo->band_center_freq2 = pCsrRoamInfo->chan_info.band_center_freq2; + pChanInfo->reg_info_1 = pCsrRoamInfo->chan_info.reg_info_1; + pChanInfo->reg_info_2 = pCsrRoamInfo->chan_info.reg_info_2; + pChanInfo->nss = pCsrRoamInfo->chan_info.nss; + pChanInfo->rate_flags = pCsrRoamInfo->chan_info.rate_flags; + + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled = pCsrRoamInfo->wmmEnabledSta; + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.status = (eSapStatus )context; + sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.timingMeasCap = pCsrRoamInfo->timingMeasCap; + //TODO: Need to fill sapAuthType + //sapApAppEvent.sapevt.sapStationAssocReassocCompleteEvent.SapAuthType = pCsrRoamInfo->pProfile->negotiatedAuthType; + break; + } + + case eSAP_STA_DISASSOC_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_STA_DISASSOC_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_STA_DISASSOC_EVENT; + + vos_mem_copy( &sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.staMac, + pCsrRoamInfo->peerMac, sizeof(tSirMacAddr)); + sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.staId = pCsrRoamInfo->staId; + if (pCsrRoamInfo->reasonCode == eCSR_ROAM_RESULT_FORCED) + sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.reason = eSAP_USR_INITATED_DISASSOC; + else + sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.reason = eSAP_MAC_INITATED_DISASSOC; + + sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.statusCode = pCsrRoamInfo->statusCode; + sapApAppEvent.sapevt.sapStationDisassocCompleteEvent.status = (eSapStatus )context; + break; + + case eSAP_STA_SET_KEY_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_STA_SET_KEY_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_STA_SET_KEY_EVENT; + sapApAppEvent.sapevt.sapStationSetKeyCompleteEvent.status = (eSapStatus )context; + vos_mem_copy(&sapApAppEvent.sapevt.sapStationSetKeyCompleteEvent.peerMacAddr, + pCsrRoamInfo->peerMac,sizeof(tSirMacAddr)); + break; + + case eSAP_STA_DEL_KEY_EVENT : + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_STA_DEL_KEY_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_STA_DEL_KEY_EVENT; + sapApAppEvent.sapevt.sapStationDeleteKeyCompleteEvent.status = (eSapStatus )context; + //TODO: Should we need to send the key information + //sapApAppEvent.sapevt.sapStationDeleteKeyCompleteEvent.keyId = ; + break; + + case eSAP_STA_MIC_FAILURE_EVENT : + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_STA_MIC_FAILURE_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_STA_MIC_FAILURE_EVENT; + vos_mem_copy( &sapApAppEvent.sapevt.sapStationMICFailureEvent.srcMacAddr, + pCsrRoamInfo->u.pMICFailureInfo->srcMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy( &sapApAppEvent.sapevt.sapStationMICFailureEvent.staMac, + pCsrRoamInfo->u.pMICFailureInfo->taMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy( &sapApAppEvent.sapevt.sapStationMICFailureEvent.dstMacAddr, + pCsrRoamInfo->u.pMICFailureInfo->dstMacAddr, + sizeof(tSirMacAddr)); + sapApAppEvent.sapevt.sapStationMICFailureEvent.multicast = pCsrRoamInfo->u.pMICFailureInfo->multicast; + sapApAppEvent.sapevt.sapStationMICFailureEvent.IV1 = pCsrRoamInfo->u.pMICFailureInfo->IV1; + sapApAppEvent.sapevt.sapStationMICFailureEvent.keyId = pCsrRoamInfo->u.pMICFailureInfo->keyId; + vos_mem_copy( sapApAppEvent.sapevt.sapStationMICFailureEvent.TSC, + pCsrRoamInfo->u.pMICFailureInfo->TSC, + SIR_CIPHER_SEQ_CTR_SIZE); + break; + + case eSAP_ASSOC_STA_CALLBACK_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_ASSOC_STA_CALLBACK_EVENT"); + break; + + case eSAP_WPS_PBC_PROBE_REQ_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_WPS_PBC_PROBE_REQ_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_WPS_PBC_PROBE_REQ_EVENT; + + vos_mem_copy( &sapApAppEvent.sapevt.sapPBCProbeReqEvent.WPSPBCProbeReq, + pCsrRoamInfo->u.pWPSPBCProbeReq, + sizeof(tSirWPSPBCProbeReq)); + break; + + case eSAP_INDICATE_MGMT_FRAME: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_INDICATE_MGMT_FRAME"); + sapApAppEvent.sapHddEventCode = eSAP_INDICATE_MGMT_FRAME; + sapApAppEvent.sapevt.sapManagementFrameInfo.nFrameLength + = pCsrRoamInfo->nFrameLength; + sapApAppEvent.sapevt.sapManagementFrameInfo.pbFrames + = pCsrRoamInfo->pbFrames; + sapApAppEvent.sapevt.sapManagementFrameInfo.frameType + = pCsrRoamInfo->frameType; + sapApAppEvent.sapevt.sapManagementFrameInfo.rxChan + = pCsrRoamInfo->rxChan; + + break; + case eSAP_REMAIN_CHAN_READY: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_REMAIN_CHAN_READY"); + sapApAppEvent.sapHddEventCode = eSAP_REMAIN_CHAN_READY; + break; + case eSAP_SEND_ACTION_CNF: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_SEND_ACTION_CNF"); + sapApAppEvent.sapHddEventCode = eSAP_SEND_ACTION_CNF; + sapApAppEvent.sapevt.sapActionCnf.actionSendSuccess = (eSapStatus)context; + break; + + case eSAP_DISCONNECT_ALL_P2P_CLIENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_DISCONNECT_ALL_P2P_CLIENT"); + sapApAppEvent.sapHddEventCode = eSAP_DISCONNECT_ALL_P2P_CLIENT; + sapApAppEvent.sapevt.sapActionCnf.actionSendSuccess = (eSapStatus)context; + break; + + case eSAP_MAC_TRIG_STOP_BSS_EVENT : + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_MAC_TRIG_STOP_BSS_EVENT"); + sapApAppEvent.sapHddEventCode = eSAP_MAC_TRIG_STOP_BSS_EVENT; + sapApAppEvent.sapevt.sapActionCnf.actionSendSuccess = (eSapStatus)context; + break; + + + case eSAP_UNKNOWN_STA_JOIN: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_UNKNOWN_STA_JOIN"); + sapApAppEvent.sapHddEventCode = eSAP_UNKNOWN_STA_JOIN; + vos_mem_copy((v_PVOID_t)sapApAppEvent.sapevt.sapUnknownSTAJoin.macaddr.bytes, + (v_PVOID_t)context, sizeof(v_MACADDR_t)); + break; + + case eSAP_MAX_ASSOC_EXCEEDED: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + "eSAP_MAX_ASSOC_EXCEEDED"); + sapApAppEvent.sapHddEventCode = eSAP_MAX_ASSOC_EXCEEDED; + vos_mem_copy((v_PVOID_t)sapApAppEvent.sapevt.sapMaxAssocExceeded.macaddr.bytes, + (v_PVOID_t)pCsrRoamInfo->peerMac, sizeof(v_MACADDR_t)); + break; + + case eSAP_CHANNEL_CHANGE_EVENT: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s", + __func__, "eSAP_CHANNEL_CHANGE_EVENT"); + /* Reconfig ACS result info. For DFS AP-AP Mode Sec AP ACS + * follows pri AP + */ + sapContext->acs_cfg->pri_ch = sapContext->channel; + sapContext->acs_cfg->ch_width = sapContext->vht_channel_width; + sap_config_acs_result(hHal, sapContext, sapContext->secondary_ch); + + sapApAppEvent.sapHddEventCode = eSAP_CHANNEL_CHANGE_EVENT; + sapApAppEvent.sapevt.sapChSelected.pri_ch = + sapContext->acs_cfg->pri_ch; + sapApAppEvent.sapevt.sapChSelected.ht_sec_ch = + sapContext->acs_cfg->ht_sec_ch; + sapApAppEvent.sapevt.sapChSelected.ch_width = + sapContext->acs_cfg->ch_width; + sapApAppEvent.sapevt.sapChSelected.vht_seg0_center_ch = + sapContext->acs_cfg->vht_seg0_center_ch; + sapApAppEvent.sapevt.sapChSelected.vht_seg1_center_ch = + sapContext->acs_cfg->vht_seg1_center_ch; + break; + + case eSAP_DFS_NOL_GET: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s", + __func__, "eSAP_DFS_NOL_GET"); + sapApAppEvent.sapHddEventCode = eSAP_DFS_NOL_GET; + sapApAppEvent.sapevt.sapDfsNolInfo.sDfsList = + NUM_5GHZ_CHANNELS * sizeof(tSapDfsNolInfo); + sapApAppEvent.sapevt.sapDfsNolInfo.pDfsList = + (v_PVOID_t)(&pMac->sap.SapDfsInfo.sapDfsChannelNolList[0]); + break; + + case eSAP_DFS_NOL_SET: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s", + __func__, "eSAP_DFS_NOL_SET"); + sapApAppEvent.sapHddEventCode = eSAP_DFS_NOL_SET; + sapApAppEvent.sapevt.sapDfsNolInfo.sDfsList = + pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels * + sizeof(tSapDfsNolInfo); + sapApAppEvent.sapevt.sapDfsNolInfo.pDfsList = + (v_PVOID_t)(&pMac->sap.SapDfsInfo.sapDfsChannelNolList[0]); + break; + case eSAP_ECSA_CHANGE_CHAN_IND: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s", + __func__, "eSAP_ECSA_CHANGE_CHAN_IND"); + sapApAppEvent.sapHddEventCode = eSAP_ECSA_CHANGE_CHAN_IND; + sapApAppEvent.sapevt.sap_chan_cng_ind.new_chan = + pCsrRoamInfo->target_channel; + break; + default: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("SAP Unknown callback event = %d"), + sapHddevent); + break; + } + vosStatus = (*sapContext->pfnSapEventCallback) + ( + &sapApAppEvent, + sapContext->pUsrContext//userdataforcallback - hdd opaque handle + ); + + return vosStatus; + +} /* sapSignalApAppStartBssEvent */ + +/*========================================================================== + FUNCTION sap_find_valid_concurrent_session + + DESCRIPTION + This function will return sapcontext of any valid sap session. + + PARAMETERS + + IN + hHal : HAL pointer + + RETURN VALUE + ptSapContext : valid sap context + + SIDE EFFECTS + NA +============================================================================*/ +ptSapContext sap_find_valid_concurrent_session (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_U8_t intf = 0; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + if (((VOS_STA_SAP_MODE == pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList[intf].pSapContext != NULL) + { + return pMac->sap.sapCtxList[intf].pSapContext; + } + } + + return NULL; +} + +/*========================================================================== + FUNCTION sap_CloseSession + + DESCRIPTION + This function will close all the sme sessions as well as zero-out the + sap global structure + + PARAMETERS + + IN + hHal : HAL pointer + sapContext : Sap Context value + callback : Roam Session close callback + valid : Sap context is valid or no + + RETURN VALUE + The eHalStatus code associated with performing the operation + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS + NA +============================================================================*/ +eHalStatus sap_CloseSession(tHalHandle hHal, + ptSapContext sapContext, + csrRoamSessionCloseCallback callback, + v_BOOL_t valid) +{ + eHalStatus halstatus; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (FALSE == valid) + { + halstatus = sme_CloseSession(hHal, + sapContext->sessionId, + callback, NULL); + } + else + { + halstatus = sme_CloseSession(hHal, + sapContext->sessionId, + callback, sapContext); + } + + sapContext->isCacStartNotified = VOS_FALSE; + sapContext->isCacEndNotified = VOS_FALSE; + pMac->sap.sapCtxList[sapContext->sessionId].pSapContext = NULL; + + if (NULL == sap_find_valid_concurrent_session(hHal)) + { + /* If timer is running then stop the timer and destory + * it + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: no session are valid, so clearing dfs global structure"); + /* CAC timer will be initiated and started only when SAP starts on + * DFS channel and it will be stopped and destroyed immediately once the + * radar detected or timedout. So as per design CAC timer should be + * destroyed after stop..*/ + if (pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + { + vos_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + } + pMac->sap.SapDfsInfo.cac_state = eSAP_DFS_DO_NOT_SKIP_CAC; + sap_CacResetNotify(hHal); + vos_mem_zero(&pMac->sap, sizeof(pMac->sap)); + } + + return halstatus; +} + +/*========================================================================== + FUNCTION sap_CacResetNotify + + DESCRIPTION Function will be called up on stop bss indication to clean up + DFS global structure. + + DEPENDENCIES PARAMETERS + IN hHAL : HAL pointer + + RETURN VALUE : void. + + SIDE EFFECTS +============================================================================*/ +void sap_CacResetNotify(tHalHandle hHal) +{ + v_U8_t intf = 0; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext pSapContext = + (ptSapContext)pMac->sap.sapCtxList [intf].pSapContext; + if (((VOS_STA_SAP_MODE == pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList [intf].pSapContext != NULL) + { + pSapContext->isCacStartNotified = VOS_FALSE; + pSapContext->isCacEndNotified = VOS_FALSE; + } + } +} + +/*========================================================================== + FUNCTION sap_CacStartNotify + + DESCRIPTION Function will be called to Notify eSAP_DFS_CAC_START event + to HDD + + DEPENDENCIES PARAMETERS + IN hHAL : HAL pointer + + RETURN VALUE : VOS_STATUS. + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS sap_CacStartNotify(tHalHandle hHal) +{ + v_U8_t intf = 0; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext pSapContext = + (ptSapContext)pMac->sap.sapCtxList [intf].pSapContext; + if (((VOS_STA_SAP_MODE == pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList [intf].pSapContext != NULL && + (VOS_FALSE == pSapContext->isCacStartNotified)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Signaling eSAP_DFS_CAC_START to HDD for sapctx[%p]", + pSapContext); + + vosStatus = sapSignalHDDevent(pSapContext, NULL, + eSAP_DFS_CAC_START, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + if (VOS_STATUS_SUCCESS != vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, failed setting isCacStartNotified on interface[%d]", + __func__, intf); + return vosStatus; + } + pSapContext->isCacStartNotified = VOS_TRUE; + } + } + return vosStatus; +} + +/*========================================================================== + FUNCTION sap_CacEndNotify + + DESCRIPTION Function will be called to Notify eSAP_DFS_CAC_END event + to HDD + + DEPENDENCIES PARAMETERS + IN hHAL : HAL pointer + + RETURN VALUE : VOS_STATUS. + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS sap_CacEndNotify(tHalHandle hHal, tCsrRoamInfo *roamInfo) +{ + v_U8_t intf; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + + /* + * eSAP_DFS_CHANNEL_CAC_END: + * CAC Period elapsed and there was no radar + * found so, SAP can continue beaconing. + * sap_radar_found_status is set to 0 + */ + for ( intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext pSapContext = + (ptSapContext)pMac->sap.sapCtxList [intf].pSapContext; + if (((VOS_STA_SAP_MODE == pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList [intf].pSapContext != NULL && + (VOS_FALSE == pSapContext->isCacEndNotified)) + { + pSapContext = pMac->sap.sapCtxList [intf].pSapContext; + vosStatus = sapSignalHDDevent(pSapContext, NULL, + eSAP_DFS_CAC_END, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + if (VOS_STATUS_SUCCESS != vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, failed setting isCacEndNotified on interface[%d]", + __func__, intf); + return vosStatus; + } + pSapContext->isCacEndNotified = VOS_TRUE; + pMac->sap.SapDfsInfo.sap_radar_found_status = VOS_FALSE; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Start beacon request on sapctx[%p]", + pSapContext); + + /* Start beaconing on the new channel */ + WLANSAP_StartBeaconReq((v_PVOID_t)pSapContext); + + /* Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: channel[%d] from state %s => %s", + pSapContext->channel, "eSAP_STARTING", + "eSAP_STARTED"); + + pSapContext->sapsMachine = eSAP_STARTED; + + /*Action code for transition */ + vosStatus = sapSignalHDDevent(pSapContext, roamInfo, + eSAP_START_BSS_EVENT, + (v_PVOID_t)eSAP_STATUS_SUCCESS); + if (VOS_STATUS_SUCCESS != vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, failed setting isCacEndNotified on interface[%d]", + __func__, intf); + return vosStatus; + } + + /* Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", + __func__, "eSAP_DFS_CAC_WAIT", "eSAP_STARTED"); + } + } + /* + * All APs are done with CAC timer, all APs should start beaconing. + * Lets assume AP1 and AP2 started beaconing on DFS channel, Now lets + * say AP1 goes down and comes back on same DFS channel. In this case + * AP1 shouldn't start CAC timer and start beacon immediately beacause + * AP2 is already beaconing on this channel. This case will be handled + * by checking against eSAP_DFS_SKIP_CAC while starting the timer. + */ + pMac->sap.SapDfsInfo.cac_state = eSAP_DFS_SKIP_CAC; + return vosStatus; +} + +/*========================================================================== + FUNCTION sapFsm + + DESCRIPTION + SAP State machine entry function + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + sapEvent : State machine event + status : Return the SAP status here + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapFsm +( + ptSapContext sapContext, /* sapContext value */ + ptWLAN_SAPEvent sapEvent /* State machine event */ +) +{ + /* Retrieve the phy link state machine structure + * from the sapContext value + */ + eSapFsmStates_t stateVar = sapContext->sapsMachine; /*state var that keeps track of state machine*/ + tCsrRoamInfo *roamInfo = (tCsrRoamInfo *)(sapEvent->params); + v_U32_t msg = sapEvent->event; /* State machine input event message */ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal pMac; + v_U32_t cbMode; + v_BOOL_t b_leak_chan = FALSE; +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + v_U8_t temp_chan; + tSapDfsNolInfo *pNol; +#endif + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return VOS_STATUS_E_FAILURE; + } + pMac = PMAC_STRUCT( hHal ); + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_DEBUG, "%s: sapContext=%p, stateVar=%d, msg=0x%x", __func__, sapContext, stateVar, msg); + + switch (stateVar) + { + case eSAP_DISCONNECTED: + if ((msg == eSAP_HDD_START_INFRA_BSS)) + { + /* Transition from eSAP_DISCONNECTED to eSAP_CH_SELECT (both without substates) */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, new from state %s => %s", + __func__, "eSAP_DISCONNECTED", "eSAP_CH_SELECT"); + + /* There can be one SAP Session for softap */ + if (sapContext->isSapSessionOpen == eSAP_TRUE) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "%s:SME Session is already opened\n",__func__); + return VOS_STATUS_E_EXISTS; + } + + sapContext->sessionId = 0xff; + + if ((sapContext->channel == AUTO_CHANNEL_SELECT) && + (sapContext->isScanSessionOpen == eSAP_FALSE)) + { + tANI_U32 type, subType; + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, NULL hHal in state %s, msg %d", + __func__, "eSAP_DISCONNECTED", msg); + } + else if(VOS_STATUS_SUCCESS == vos_get_vdev_types(VOS_STA_MODE, + &type, &subType)) { + /* Open SME Session for scan */ + if(eHAL_STATUS_SUCCESS != sme_OpenSession(hHal, + NULL, sapContext, sapContext->self_mac_addr, + &sapContext->sessionId, type, subType)) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Error: In %s calling sme_OpenSession", __func__); + } else { + sapContext->isScanSessionOpen = eSAP_TRUE; + } + } + } + /* init dfs channel nol */ + sapInitDfsChannelNolList(sapContext); + + /* Set SAP device role */ + sapContext->sapsMachine = eSAP_CH_SELECT; + + /* + * Perform sme_ScanRequest + * This scan request is post start bss + * request so, set the third to false. + */ + vosStatus = sapGotoChannelSel(sapContext, sapEvent, VOS_FALSE); + + /* Transition from eSAP_DISCONNECTED to eSAP_CH_SELECT (both without substates) */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_DISCONNECTED", "eSAP_CH_SELECT"); + } + else if (msg == eSAP_DFS_CHANNEL_CAC_START) + { + /* No need of state check here, caller is expected to perform + * the checks before sending the event + */ + sapContext->sapsMachine = eSAP_DFS_CAC_WAIT; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: from state eSAP_DISCONNECTED => SAP_DFS_CAC_WAIT"); + if ( pMac->sap.SapDfsInfo.is_dfs_cac_timer_running != VOS_TRUE) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: starting dfs cac timer on sapctx[%p]", + sapContext); + sapStartDfsCacTimer(sapContext); + } + + vosStatus = sap_CacStartNotify(hHal); + } + else if (msg == eSAP_CHANNEL_SELECTION_RETRY) + { + /* Set SAP device role */ + sapContext->sapsMachine = eSAP_CH_SELECT; + + /* + * Perform sme_ScanRequest + * This scan request is post start bss + * request so, set the third to false. + */ + vosStatus = sapGotoChannelSel(sapContext, sapEvent, VOS_FALSE); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, event msg %d", + __func__, "eSAP_DISCONNECTED", msg); + } + + break; + + case eSAP_CH_SELECT: + if (sapContext->isScanSessionOpen == eSAP_TRUE) + { + /* scan completed, so close the session */ + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, NULL hHal in state %s, msg %d", + __func__, "eSAP_CH_SELECT", msg); + } else { + if(eHAL_STATUS_SUCCESS != sme_CloseSession(hHal, + sapContext->sessionId, NULL, NULL)) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s CloseSession error event msg %d", + __func__, msg); + } else { + sapContext->isScanSessionOpen = eSAP_FALSE; + } + } + sapContext->sessionId = 0xff; + } + + if (msg == eSAP_MAC_SCAN_COMPLETE) + { + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, NULL hHal in state %s, msg %d ", __func__, + "eSAP_CH_SELECT", msg); + return VOS_STATUS_E_FAULT; + } + cbMode = sme_SelectCBMode(hHal, + sapContext->csrRoamProfile.phyMode, + sapContext->channel, + sapContext->secondary_ch, + &sapContext->vht_channel_width, + sapContext->ch_width_orig); + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + temp_chan = sapContext->channel; + pNol = pMac->sap.SapDfsInfo.sapDfsChannelNolList; + + sapMarkChannelsLeakingIntoNOL(sapContext, + cbMode, pNol, 1, &temp_chan); + + /* if selelcted channel has leakage to channels + in NOL, the temp_chan will be reset */ + b_leak_chan = (temp_chan != sapContext->channel); +#endif + /* check if channel is in DFS_NOL or + if the channel has leakage to the channels in NOL */ + if (sapDfsIsChannelInNolList(sapContext, sapContext->channel, + cbMode) || b_leak_chan) + { + v_U8_t ch; + + /* find a new available channel */ + ch = sapRandomChannelSel(sapContext); + if (ch == 0) { + /* No available channel found */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("No available channel found!!!")); + sapSignalHDDevent(sapContext, NULL, + eSAP_DFS_NO_AVAILABLE_CHANNEL, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + return VOS_STATUS_E_FAULT; + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("channel %d is in NOL, StartBss on new channel %d"), + sapContext->channel, ch); + + sapContext->channel = ch; + sme_SelectCBMode(hHal, sapContext->csrRoamProfile.phyMode, + sapContext->channel, + sapContext->secondary_ch, + &sapContext->vht_channel_width, + sapContext->ch_width_orig); + } + if (sapContext->channel > 14 && + (sapContext->csrRoamProfile.phyMode == + eCSR_DOT11_MODE_11g || + sapContext->csrRoamProfile.phyMode == + eCSR_DOT11_MODE_11g_ONLY)) + sapContext->csrRoamProfile.phyMode = eCSR_DOT11_MODE_11a; + +#ifdef WLAN_FEATURE_MBSSID + /* when AP2 is started while AP1 is performing ACS, we may not + * have the AP1 channel yet.So here after the completion of AP2 + * ACS check if AP1 ACS resulting channel is DFS and if yes + * override AP2 ACS scan result with AP1 DFS channel + */ + if (vos_concurrent_beaconing_sessions_running()) { + v_U16_t con_ch; + + con_ch = sme_GetConcurrentOperationChannel(hHal); + if (con_ch && VOS_IS_DFS_CH(con_ch)) + sapContext->channel = con_ch; + } +#endif + /* Transition from eSAP_CH_SELECT to eSAP_STARTING (both without substates) */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_CH_SELECT", "eSAP_STARTING"); + // Channel selected. Now can sapGotoStarting + sapContext->sapsMachine = eSAP_STARTING; + // Specify the channel + sapContext->csrRoamProfile.ChannelInfo.numOfChannels = 1; + sapContext->csrRoamProfile.ChannelInfo.ChannelList = &sapContext->csrRoamProfile.operationChannel; + sapContext->csrRoamProfile.operationChannel = (tANI_U8)sapContext->channel; + sapContext->csrRoamProfile.vht_channel_width = + sapContext->vht_channel_width; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: notify hostapd about channel selection: %d", + __func__, sapContext->channel); + sapSignalHDDevent(sapContext, NULL, eSAP_CHANNEL_CHANGE_EVENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + vosStatus = sapGotoStarting( sapContext, sapEvent, eCSR_BSS_TYPE_INFRA_AP); + } + else if (msg == eSAP_CHANNEL_SELECTION_FAILED) { + sapContext->sapsMachine = eSAP_DISCONNECTED; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "\n\n***In %s, Cannot start BSS, ACS Fail***\n\n", + __func__); + } else if (msg == eSAP_HDD_STOP_INFRA_BSS) { + sapContext->sapsMachine = eSAP_DISCONNECTED; + sapSignalHDDevent(sapContext, NULL, eSAP_START_BSS_EVENT, + (v_PVOID_t)eSAP_STATUS_FAILURE); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: BSS stopped during Ch select in Progress", __func__); + } else { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, invalid event msg %d", + __func__, "eSAP_CH_SELECT", msg); + } + break; + + case eSAP_DFS_CAC_WAIT: + if (msg == eSAP_DFS_CHANNEL_CAC_START) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_CH_SELECT", "eSAP_DFS_CAC_WAIT"); + if ( pMac->sap.SapDfsInfo.is_dfs_cac_timer_running != VOS_TRUE) + sapStartDfsCacTimer(sapContext); + + vosStatus = sap_CacStartNotify(hHal); + + } + else if (msg == eSAP_DFS_CHANNEL_CAC_RADAR_FOUND) + { + v_U8_t intf; + /* Radar found while performing channel availability + * check, need to switch the channel again + */ + eCsrPhyMode phyMode = sapContext->csrRoamProfile.phyMode; + tHalHandle hHal = + (tHalHandle)vos_get_context(VOS_MODULE_ID_SME, sapContext->pvosGCtx); + + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "ENTERTRED CAC WAIT STATE-->eSAP_DISCONNECTING\n"); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, NULL hHal in state %s, msg %d", + __func__, "eSAP_DFS_CAC_WAIT", msg); + } + else if (pMac->sap.SapDfsInfo.target_channel) + { + sme_SelectCBMode(hHal, phyMode, + pMac->sap.SapDfsInfo.target_channel, + 0, &sapContext->vht_channel_width, + sapContext->ch_width_orig); + } + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext sapContext; + if (((VOS_STA_SAP_MODE == + pMac->sap.sapCtxList[intf].sapPersona) || + (VOS_P2P_GO_MODE == + pMac->sap.sapCtxList[intf].sapPersona)) && + pMac->sap.sapCtxList [intf].pSapContext != NULL) + { + sapContext = pMac->sap.sapCtxList [intf].pSapContext; + /* SAP to be moved to DISCONNECTING state */ + sapContext->sapsMachine = eSAP_DISCONNECTING; + /* + * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND: + * A Radar is found on current DFS Channel + * while in CAC WAIT period So, do a channel switch + * to randomly selected target channel. + * Send the Channel change message to SME/PE. + * sap_radar_found_status is set to 1 + */ + sapSignalHDDevent(sapContext, NULL, + eSAP_DFS_RADAR_DETECT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + WLANSAP_ChannelChangeRequest((v_PVOID_t)sapContext, + pMac->sap.SapDfsInfo.target_channel); + } + } + } + else if (msg == eSAP_DFS_CHANNEL_CAC_END) + { + vosStatus = sap_CacEndNotify(hHal, roamInfo); + } + else if (msg == eSAP_HDD_STOP_INFRA_BSS) + { + /* Transition from eSAP_DFS_CAC_WAIT to eSAP_DISCONNECTING */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", + __func__, + "eSAP_DFS_CAC_WAIT", + "eSAP_DISCONNECTING"); + + /* + * Stop the CAC timer only in following conditions + * single AP: if there is a single AP then stop the timer + * mulitple APs: incase of multiple APs, make sure that + * all APs are down. + */ + if (NULL == sap_find_valid_concurrent_session(hHal)) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: no sessions are valid, stopping timer"); + + sapStopDfsCacTimer(sapContext); + } + + sapContext->sapsMachine = eSAP_DISCONNECTING; + vosStatus = sapGotoDisconnecting(sapContext); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, in state %s, invalid event msg %d", + __func__, "eSAP_DFS_CAC_WAIT", msg); + } + break; + + case eSAP_STARTING: + if (msg == eSAP_MAC_START_BSS_SUCCESS ) + { + /* Transition from eSAP_STARTING to eSAP_STARTED (both without substates) */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state channel = %d %s => %s", + __func__,sapContext->channel, "eSAP_STARTING", "eSAP_STARTED"); + + sapContext->sapsMachine = eSAP_STARTED; + + /*Action code for transition */ + vosStatus = sapSignalHDDevent( sapContext, roamInfo, eSAP_START_BSS_EVENT, (v_PVOID_t)eSAP_STATUS_SUCCESS); + + /* The upper layers have been informed that AP is up and + * running, however, the AP is still not beaconing, until + * CAC is done if the operating channel is DFS + */ + if (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(sapContext->channel) + ) + { + if ((VOS_FALSE == pMac->sap.SapDfsInfo.ignore_cac) && + (eSAP_DFS_DO_NOT_SKIP_CAC == + pMac->sap.SapDfsInfo.cac_state)) + { + /* Move the device in CAC_WAIT_STATE */ + sapContext->sapsMachine = eSAP_DFS_CAC_WAIT; + + /* TODO: Need to stop the OS transmit queues, + * so that no traffic can flow down the stack + */ + + /* Start CAC wait timer */ + if (pMac->sap.SapDfsInfo.is_dfs_cac_timer_running != + TRUE) + sapStartDfsCacTimer(sapContext); + + vosStatus = sap_CacStartNotify(hHal); + + } + else + { + WLANSAP_StartBeaconReq((v_PVOID_t)sapContext); + } + } + } + else if (msg == eSAP_HDD_STOP_INFRA_BSS || + msg == eSAP_MAC_START_FAILS) + { + /*Transition from eSAP_STARTING to eSAP_DISCONNECTED (both without substates)*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_STARTING", "eSAP_DISCONNECTED"); + + /*Advance outer statevar */ + sapContext->sapsMachine = eSAP_DISCONNECTED; + vosStatus = sapSignalHDDevent( sapContext, NULL, eSAP_START_BSS_EVENT, (v_PVOID_t)eSAP_STATUS_FAILURE); + vosStatus = sapGotoDisconnected(sapContext); + /* Close the SME session*/ + + if (eSAP_TRUE == sapContext->isSapSessionOpen) + { + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, NULL hHal in state %s, msg %d", + __func__, "eSAP_STARTING", msg); + } + else if (eHAL_STATUS_SUCCESS == + sap_CloseSession(hHal, + sapContext, NULL, FALSE)) + { + sapContext->isSapSessionOpen = eSAP_FALSE; + } + } + } + else if (msg == eSAP_OPERATING_CHANNEL_CHANGED) + { + /* The operating channel has changed, update hostapd */ + sapContext->channel = + (tANI_U8)pMac->sap.SapDfsInfo.target_channel; + sapContext->sapsMachine = eSAP_STARTED; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, from state %s => %s", + __func__, "eSAP_STARTING", "eSAP_STARTED"); + + /* Indicate change in the state to upper layers */ + vosStatus = sapSignalHDDevent(sapContext, roamInfo, + eSAP_START_BSS_EVENT, + (v_PVOID_t)eSAP_STATUS_SUCCESS); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, in state %s, invalid event msg %d", + __func__, "eSAP_STARTING", msg); + /* Intentionally left blank */ + } + break; + + case eSAP_STARTED: + if (msg == eSAP_HDD_STOP_INFRA_BSS) + { + /* Transition from eSAP_STARTED to eSAP_DISCONNECTING (both without substates) */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_STARTED", "eSAP_DISCONNECTING"); + sapContext->sapsMachine = eSAP_DISCONNECTING; + vosStatus = sapGotoDisconnecting(sapContext); + } + else if (eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START == msg) + { + v_U8_t intf; + /* Radar is seen on the current operating channel + * send CSA IE for all associated stations + */ + if (pMac != NULL) + { + /* Request for CSA IE transmission */ + for ( intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) + { + ptSapContext pSapContext; + + if (((VOS_STA_SAP_MODE == + pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == + pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList [intf].pSapContext != NULL ) + { + pSapContext = pMac->sap.sapCtxList [intf].pSapContext; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Sending CSAIE for sapctx[%p]", + pSapContext); + + vosStatus = + WLANSAP_DfsSendCSAIeRequest((v_PVOID_t)pSapContext); + } + } + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, invalid event msg %d", + __func__, "eSAP_STARTED", msg); + } + break; + + case eSAP_DISCONNECTING: + if (msg == eSAP_MAC_READY_FOR_CONNECTIONS) + { + /* Transition from eSAP_DISCONNECTING to eSAP_DISCONNECTED (both without substates) */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s", + __func__, "eSAP_DISCONNECTING", "eSAP_DISCONNECTED"); + + sapContext->sapsMachine = eSAP_DISCONNECTED; + + /* Close the SME session*/ + if (eSAP_TRUE == sapContext->isSapSessionOpen) + { + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, NULL hHal in state %s, msg %d", + __func__, "eSAP_DISCONNECTING", msg); + } + else + { + sapContext->isSapSessionOpen = eSAP_FALSE; + if (!HAL_STATUS_SUCCESS( + sap_CloseSession(hHal, + sapContext, + sapRoamSessionCloseCallback, TRUE))) + { + vosStatus = sapSignalHDDevent(sapContext, NULL, + eSAP_STOP_BSS_EVENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + } + } + } + } + else if (msg == eWNI_SME_CHANNEL_CHANGE_REQ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Send channel change request on sapctx[%p]", + sapContext); + /* Most likely, radar has been detected and SAP wants to + * change the channel + */ + vosStatus = WLANSAP_ChannelChangeRequest((v_PVOID_t)sapContext, + pMac->sap.SapDfsInfo.target_channel); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "In %s, Sending DFS eWNI_SME_CHANNEL_CHANGE_REQ", + __func__); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s, in state %s, invalid event msg %d", + __func__, "eSAP_DISCONNECTING", msg); + } + break; + } + return vosStatus; +}// sapFsm + + +eSapStatus +sapconvertToCsrProfile(tsap_Config_t *pconfig_params, eCsrRoamBssType bssType, tCsrRoamProfile *profile) +{ + //Create Roam profile for SoftAP to connect + profile->BSSType = eCSR_BSS_TYPE_INFRA_AP; + profile->SSIDs.numOfSSIDs = 1; + profile->csrPersona = pconfig_params->persona; + profile->disableDFSChSwitch = pconfig_params->disableDFSChSwitch; + + vos_mem_zero(profile->SSIDs.SSIDList[0].SSID.ssId, + sizeof(profile->SSIDs.SSIDList[0].SSID.ssId)); + + //Flag to not broadcast the SSID information + profile->SSIDs.SSIDList[0].ssidHidden = pconfig_params->SSIDinfo.ssidHidden; + + profile->SSIDs.SSIDList[0].SSID.length = pconfig_params->SSIDinfo.ssid.length; + vos_mem_copy(&profile->SSIDs.SSIDList[0].SSID.ssId, pconfig_params->SSIDinfo.ssid.ssId, + sizeof(pconfig_params->SSIDinfo.ssid.ssId)); + + profile->negotiatedAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + if (pconfig_params->authType == eSAP_OPEN_SYSTEM) + { + profile->negotiatedAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + } + else if (pconfig_params->authType == eSAP_SHARED_KEY) + { + profile->negotiatedAuthType = eCSR_AUTH_TYPE_SHARED_KEY; + } + else + { + profile->negotiatedAuthType = eCSR_AUTH_TYPE_AUTOSWITCH; + } + + profile->AuthType.numEntries = 1; + profile->AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + //Always set the Encryption Type + profile->EncryptionType.numEntries = 1; + profile->EncryptionType.encryptionType[0] = pconfig_params->RSNEncryptType; + + profile->mcEncryptionType.numEntries = 1; + profile->mcEncryptionType.encryptionType[0] = pconfig_params->mcRSNEncryptType; + + if (pconfig_params->privacy & eSAP_SHARED_KEY) + { + profile->AuthType.authType[0] = eCSR_AUTH_TYPE_SHARED_KEY; + } + + profile->privacy = pconfig_params->privacy; + profile->fwdWPSPBCProbeReq = pconfig_params->fwdWPSPBCProbeReq; + + if (pconfig_params->authType == eSAP_SHARED_KEY) + { + profile->csr80211AuthType = eSIR_SHARED_KEY; + } + else if (pconfig_params->authType == eSAP_OPEN_SYSTEM) + { + profile->csr80211AuthType = eSIR_OPEN_SYSTEM; + } + else + { + profile->csr80211AuthType = eSIR_AUTO_SWITCH; + } + + //Initialize we are not going to use it + profile->pWPAReqIE = NULL; + profile->nWPAReqIELength = 0; + + //set the RSN/WPA IE + profile->pRSNReqIE = NULL; + profile->nRSNReqIELength = pconfig_params->RSNWPAReqIELength; + if (pconfig_params->RSNWPAReqIELength) + { + profile->pRSNReqIE = vos_mem_malloc(pconfig_params->RSNWPAReqIELength); + if( NULL == profile->pRSNReqIE ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, " %s Fail to alloc memory", __func__); + return eSAP_STATUS_FAILURE; + } + vos_mem_copy(profile->pRSNReqIE, pconfig_params->RSNWPAReqIE, + pconfig_params->RSNWPAReqIELength); + profile->nRSNReqIELength = pconfig_params->RSNWPAReqIELength; + } + + // Turn off CB mode + profile->CBMode = eCSR_CB_OFF; + + //set the phyMode to accept anything + //Best means everything because it covers all the things we support + /*eCSR_DOT11_MODE_BEST*/ + profile->phyMode = pconfig_params->SapHw_mode; + + //Configure beaconInterval + profile->beaconInterval = (tANI_U16)pconfig_params->beacon_int; + + // set DTIM period + profile->dtimPeriod = pconfig_params->dtim_period; + + //set Uapsd enable bit + profile->ApUapsdEnable = pconfig_params->UapsdEnable; + + //Enable protection parameters + profile->protEnabled = pconfig_params->protEnabled; + profile->obssProtEnabled = pconfig_params->obssProtEnabled; + profile->cfg_protection = pconfig_params->ht_capab; + + //country code + if (pconfig_params->countryCode[0]) + vos_mem_copy(profile->countryCode, pconfig_params->countryCode, WNI_CFG_COUNTRY_CODE_LEN); + profile->ieee80211d = pconfig_params->ieee80211d; + //wps config info + profile->wps_state = pconfig_params->wps_state; + +#ifdef WLAN_FEATURE_11W + // MFP capable/required + profile->MFPCapable = pconfig_params->mfpCapable ? 1 : 0; + profile->MFPRequired = pconfig_params->mfpRequired ? 1 : 0; +#endif + + if (pconfig_params->probeRespIEsBufferLen > 0 && + pconfig_params->pProbeRespIEsBuffer != NULL) + { + profile->addIeParams.probeRespDataLen = + pconfig_params->probeRespIEsBufferLen; + profile->addIeParams.probeRespData_buff = + pconfig_params->pProbeRespIEsBuffer; + } + else + { + profile->addIeParams.probeRespDataLen = 0; + profile->addIeParams.probeRespData_buff = NULL; + } + /*assoc resp IE */ + if (pconfig_params->assocRespIEsLen > 0 && + pconfig_params->pAssocRespIEsBuffer != NULL) + { + profile->addIeParams.assocRespDataLen = + pconfig_params->assocRespIEsLen; + profile->addIeParams.assocRespData_buff = + pconfig_params->pAssocRespIEsBuffer; + } + else + { + profile->addIeParams.assocRespDataLen = 0; + profile->addIeParams.assocRespData_buff = NULL; + } + + if (pconfig_params->probeRespBcnIEsLen > 0 && + pconfig_params->pProbeRespBcnIEsBuffer!= NULL) + { + profile->addIeParams.probeRespBCNDataLen = + pconfig_params->probeRespBcnIEsLen; + profile->addIeParams.probeRespBCNData_buff = + pconfig_params->pProbeRespBcnIEsBuffer; + } + else + { + profile->addIeParams.probeRespBCNDataLen = 0; + profile->addIeParams.probeRespBCNData_buff = NULL; + } + profile->sap_dot11mc = pconfig_params->sap_dot11mc; + + return eSAP_STATUS_SUCCESS; /* Success. */ +} + +void sapFreeRoamProfile(tCsrRoamProfile *profile) +{ + if(profile->pRSNReqIE) + { + vos_mem_free(profile->pRSNReqIE); + profile->pRSNReqIE = NULL; + } +} + + +void +sapSortMacList(v_MACADDR_t *macList, v_U8_t size) +{ + v_U8_t outer, inner; + v_MACADDR_t temp; + v_SINT_t nRes = -1; + + if ((NULL == macList) || (size > MAX_ACL_MAC_ADDRESS)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("either buffer is NULL or size = %d is more."), size); + return; + } + + for(outer = 0; outer < size; outer++) + { + for(inner = 0; inner < size - 1; inner++) + { + nRes = vos_mem_compare2((macList + inner)->bytes, (macList + inner + 1)->bytes, sizeof(v_MACADDR_t)); + if (nRes > 0) + { + vos_mem_copy(temp.bytes, (macList + inner + 1)->bytes, sizeof(v_MACADDR_t)); + vos_mem_copy((macList + inner + 1)->bytes, (macList + inner)->bytes, sizeof(v_MACADDR_t)); + vos_mem_copy((macList + inner)->bytes, temp.bytes, sizeof(v_MACADDR_t)); + } + } + } +} + +eSapBool +sapSearchMacList(v_MACADDR_t *macList, v_U8_t num_mac, v_U8_t *peerMac, v_U8_t *index) +{ + v_SINT_t nRes = -1; + v_S7_t nStart = 0, nEnd, nMiddle; + nEnd = num_mac - 1; + + if ((NULL == macList) || (num_mac > MAX_ACL_MAC_ADDRESS)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("either buffer is NULL or size = %d is more."), + num_mac); + return eSAP_FALSE; + } + + while (nStart <= nEnd) + { + nMiddle = (nStart + nEnd) / 2; + nRes = vos_mem_compare2(&macList[nMiddle], peerMac, sizeof(v_MACADDR_t)); + + if (0 == nRes) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "search SUCC"); + // "index equals NULL" means the caller does not need the + // index value of the peerMac being searched + if (index != NULL) + { + *index = (v_U8_t) nMiddle; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "index %d", *index); + } + return eSAP_TRUE; + } + if (nRes < 0) + nStart = nMiddle + 1; + else + nEnd = nMiddle - 1; + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "search not succ"); + return eSAP_FALSE; +} + +void +sapAddMacToACL(v_MACADDR_t *macList, v_U8_t *size, v_U8_t *peerMac) +{ + v_SINT_t nRes = -1; + int i; + + if ((NULL == macList) || (*size > MAX_ACL_MAC_ADDRESS)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("either buffer is NULL or size = %d is incorrect."), + *size); + return; + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"add acl entered"); + for (i=((*size)-1); i>=0; i--) + { + nRes = vos_mem_compare2(&macList[i], peerMac, sizeof(v_MACADDR_t)); + if (nRes > 0) + { + /* Move alphabetically greater mac addresses one index down to allow for insertion + of new mac in sorted order */ + vos_mem_copy((macList+i+1)->bytes,(macList+i)->bytes, sizeof(v_MACADDR_t)); + } + else + { + break; + } + } + //This should also take care of if the element is the first to be added in the list + vos_mem_copy((macList+i+1)->bytes, peerMac, sizeof(v_MACADDR_t)); + // increment the list size + (*size)++; +} + +void +sapRemoveMacFromACL(v_MACADDR_t *macList, v_U8_t *size, v_U8_t index) +{ + int i; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"remove acl entered"); + /* return if the list passed is empty. Ideally this should never happen since this funcn is always + called after sapSearchMacList to get the index of the mac addr to be removed and this will + only get called if the search is successful. Still no harm in having the check */ + if ((NULL == macList) || (*size == 0) || (*size > MAX_ACL_MAC_ADDRESS)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("either buffer is NULL or size = %d is incorrect"), + *size); + return; + } + + for (i=index; i<((*size)-1); i++) + { + /* Move mac addresses starting from "index" passed one index up to delete the void + created by deletion of a mac address in ACL */ + vos_mem_copy((macList+i)->bytes,(macList+i+1)->bytes, sizeof(v_MACADDR_t)); + } + // The last space should be made empty since all mac addesses moved one step up + vos_mem_zero((macList+(*size)-1)->bytes, sizeof(v_MACADDR_t)); + //reduce the list size by 1 + (*size)--; +} + +void sapPrintACL(v_MACADDR_t *macList, v_U8_t size) +{ + int i; + v_BYTE_t *macArray; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"print acl entered"); + + if ((NULL == macList) || (size == 0) || (size >= MAX_ACL_MAC_ADDRESS)) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, either buffer is NULL or size %d is incorrect." + , __func__, size); + return; + } + + for (i=0; ibytes; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "** ACL entry %i - "MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(macArray)); + } + return; +} + +VOS_STATUS +sapIsPeerMacAllowed(ptSapContext sapContext, v_U8_t *peerMac) +{ + if (eSAP_ALLOW_ALL == sapContext->eSapMacAddrAclMode) + return VOS_STATUS_SUCCESS; + + if (sapSearchMacList(sapContext->acceptMacList, sapContext->nAcceptMac, peerMac, NULL)) + return VOS_STATUS_SUCCESS; + + if (sapSearchMacList(sapContext->denyMacList, sapContext->nDenyMac, peerMac, NULL)) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Peer "MAC_ADDRESS_STR" in deny list", + __func__, MAC_ADDR_ARRAY(peerMac)); + return VOS_STATUS_E_FAILURE; + } + + // A new station CAN associate, unless in deny list. Less stringent mode + if (eSAP_ACCEPT_UNLESS_DENIED == sapContext->eSapMacAddrAclMode) + return VOS_STATUS_SUCCESS; + + // A new station CANNOT associate, unless in accept list. More stringent mode + if (eSAP_DENY_UNLESS_ACCEPTED == sapContext->eSapMacAddrAclMode) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Peer "MAC_ADDRESS_STR" denied, Mac filter mode is eSAP_DENY_UNLESS_ACCEPTED", + __func__, MAC_ADDR_ARRAY(peerMac)); + return VOS_STATUS_E_FAILURE; + } + + /* The new STA is neither in accept list nor in deny list. In this case, deny the association + * but send a wifi event notification indicating the mac address being denied + */ + if (eSAP_SUPPORT_ACCEPT_AND_DENY == sapContext->eSapMacAddrAclMode) + { + sapSignalHDDevent(sapContext, NULL, eSAP_UNKNOWN_STA_JOIN, (v_PVOID_t)peerMac); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "In %s, Peer "MAC_ADDRESS_STR" denied, Mac filter mode is eSAP_SUPPORT_ACCEPT_AND_DENY", + __func__, MAC_ADDR_ARRAY(peerMac)); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +#ifdef SOFTAP_CHANNEL_RANGE +static VOS_STATUS sapGetChannelList(ptSapContext sapContext, + v_U8_t **channelList, v_U8_t *numberOfChannels) +{ + v_U8_t loopCount; + v_U8_t *list; + v_U8_t channelCount; + v_U8_t startChannelNum, bandStartChannel; + v_U8_t endChannelNum, bandEndChannel ; + v_U32_t enableLTECoex; + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); +#ifdef FEATURE_WLAN_CH_AVOID + v_U8_t i; +#endif + tpAniSirGlobal pmac = PMAC_STRUCT(hHal); + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Invalid HAL pointer from pvosGCtx on sapGetChannelList"); + *numberOfChannels = 0; + *channelList = NULL; + return VOS_STATUS_E_FAULT; + } + + if ( eCSR_BAND_ALL == sapContext->scanBandPreference) + { + startChannelNum = sapContext->acs_cfg->start_ch; + endChannelNum = sapContext->acs_cfg->end_ch; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: startChannel %d, EndChannel %d, HW:%d", + __func__, startChannelNum, endChannelNum, + sapContext->acs_cfg->hw_mode); + + WLANSAP_extend_to_acs_range(&startChannelNum, &endChannelNum, + &bandStartChannel, &bandEndChannel); + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: expanded startChannel %d,EndChannel %d", + __func__,startChannelNum,endChannelNum); + } + else + { + if ( sapContext->allBandScanned == eSAP_FALSE ) + { + //first band scan + sapContext->currentPreferredBand = sapContext->scanBandPreference; + } + else + { + //scan next band + if ( eCSR_BAND_24 == sapContext->scanBandPreference ) + sapContext->currentPreferredBand = eCSR_BAND_5G; + else + sapContext->currentPreferredBand = eCSR_BAND_24; + } + switch(sapContext->currentPreferredBand) + { + case eCSR_BAND_24: + bandStartChannel = RF_CHAN_1; + bandEndChannel = RF_CHAN_14; + startChannelNum = 1; + endChannelNum = 14; + break; + + case eCSR_BAND_5G: + bandStartChannel = RF_CHAN_36; + bandEndChannel = RF_CHAN_165; + startChannelNum = 36; + endChannelNum = 165; + break; + + default: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "sapGetChannelList:bandPreference not valid "); + /* assume 2.4 GHz */ + bandStartChannel = RF_CHAN_1; + bandEndChannel = RF_CHAN_14; + startChannelNum = 1; + endChannelNum = 14; + break; + } + } + + ccmCfgGetInt(hHal, WNI_CFG_ENABLE_LTE_COEX, &enableLTECoex); + + /*Check if LTE coex is enabled and 2.4GHz is selected*/ + if (enableLTECoex && (bandStartChannel == RF_CHAN_1) + && (bandEndChannel == RF_CHAN_14)) + { + /*Set 2.4GHz upper limit to channel 9 for LTE COEX*/ + bandEndChannel = RF_CHAN_9; + } + /* Allocate the max number of channel supported */ + list = (v_U8_t *)vos_mem_malloc(NUM_5GHZ_CHANNELS); + if (NULL == list) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to allocate channel list", __func__); + *numberOfChannels = 0; + *channelList = NULL; + return VOS_STATUS_E_RESOURCES; + } + + /*Search for the Active channels in the given range */ + channelCount = 0; + for( loopCount = bandStartChannel; loopCount <= bandEndChannel; loopCount++ ) + { + if((startChannelNum <= rfChannels[loopCount].channelNum)&& + (endChannelNum >= rfChannels[loopCount].channelNum )) + { + if (((TRUE == pmac->scan.fEnableDFSChnlScan) && + (regChannels[loopCount].enabled)) || + ((FALSE == pmac->scan.fEnableDFSChnlScan) && + (NV_CHANNEL_ENABLE == regChannels[loopCount].enabled))) + { +#ifdef FEATURE_WLAN_CH_AVOID + for( i = 0; i < NUM_20MHZ_RF_CHANNELS; i++ ) + { + if( (safeChannels[i].channelNumber == + rfChannels[loopCount].channelNum) ) + { + /* Check if channel is safe */ + if(VOS_TRUE == safeChannels[i].isSafe) + { +#endif +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + v_U8_t ch; + ch = rfChannels[loopCount].channelNum; + if ((sapContext->acs_cfg->skip_scan_status + == eSAP_DO_PAR_ACS_SCAN)) { + if ((ch >= sapContext->acs_cfg->skip_scan_range1_stch && + ch <= sapContext->acs_cfg->skip_scan_range1_endch) || + (ch >= sapContext->acs_cfg->skip_scan_range2_stch && + ch <= sapContext->acs_cfg->skip_scan_range2_endch)) { + + list[channelCount] = + rfChannels[loopCount].channelNum; + channelCount++; + VOS_TRACE( VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO, + "%s:%d %d added to ACS ch range", + __func__, channelCount, ch); + } else + VOS_TRACE( VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_HIGH, + "%s:%d %d skipped from ACS ch range", + __func__, channelCount, ch); + + } else { + list[channelCount] = + rfChannels[loopCount].channelNum; + channelCount++; + VOS_TRACE( VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO, + "%s:%d %d added to ACS ch range", + __func__, channelCount, ch); + } +#else + list[channelCount] = + rfChannels[loopCount].channelNum; + channelCount++; +#endif +#ifdef FEATURE_WLAN_CH_AVOID + } + break; + } + } +#endif + } + } + } + if (0 == channelCount) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "sapGetChannelList:No active channels present in the given range for the current region"); + /*LTE COEX: channel range outside the restricted 2.4GHz band limits*/ + if (enableLTECoex && (startChannelNum > bandEndChannel)) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "sapGetChannelList:SAP cannot be started as LTE COEX restricted 2.4GHz limits"); + } + } + + /* return the channel list and number of channels to scan*/ + *numberOfChannels = channelCount; + if(channelCount != 0) + { + *channelList = list; + } + else + { + *channelList = NULL; + vos_mem_free(list); + } + + for (loopCount = 0; loopCount SapAllChnlList.channelList) { + vos_mem_free(sapContext->SapAllChnlList.channelList); + sapContext->SapAllChnlList.channelList = NULL; + } + + sapContext->SapAllChnlList.channelList = + (tChannelInfo *)vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN * + sizeof(tChannelInfo)); + if (NULL == sapContext->SapAllChnlList.channelList) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + " Memory Allocation failed sapGetChannelList"); + return VOS_STATUS_E_FAULT; + } + + for( i = RF_CHAN_36; i <= RF_CHAN_165; i++ ) + { + if( regChannels[i].enabled == NV_CHANNEL_ENABLE || + regChannels[i].enabled == NV_CHANNEL_DFS ) + { + sapContext->SapAllChnlList.channelList[count].channel = + rfChannels[i].channelNum; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s[%d] CHANNEL = %d",__func__, __LINE__, + sapContext->SapAllChnlList.channelList[count].channel); + sapContext->SapAllChnlList.channelList[count].valid = VOS_TRUE; + count++; + } + } + + sapContext->SapAllChnlList.numChannel = count; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s[%d] NUMBER OF CHANNELS count = %d" + "sapContext->SapAllChnlList.numChannel = %d", + __func__,__LINE__,count,sapContext->SapAllChnlList.numChannel); + return VOS_STATUS_SUCCESS; +} + +/* + * This function randomly selects the channel to switch after the detection + * of radar + * param sapContext - sap context + * dfs_event - Dfs information from DFS + * return - channel to which AP wishes to switch + */ +v_U8_t sapIndicateRadar(ptSapContext sapContext, tSirSmeDfsEventInd *dfs_event) +{ + v_U8_t target_channel = 0; + tHalHandle hHal; + tpAniSirGlobal pMac; + + if (NULL == sapContext || NULL == dfs_event) + { + /* Invalid sap context of dfs event passed */ + return 0; + } + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return 0; + } + pMac = PMAC_STRUCT( hHal ); + + if (!dfs_event->dfs_radar_status) + { + /*dfs status does not indicate a radar on the channel-- False Alarm*/ + return 0; + } + + /* + * SAP needs to generate Channel Switch IE + * if the radar is found in the STARTED state + */ + if (eSAP_STARTED == sapContext->sapsMachine) + pMac->sap.SapDfsInfo.csaIERequired = VOS_TRUE; + + if (sapContext->csrRoamProfile.disableDFSChSwitch) + { + return sapContext->channel; + } + + /* set the Radar Found flag in SapDfsInfo */ + pMac->sap.SapDfsInfo.sap_radar_found_status = VOS_TRUE; + + sapGet5GHzChannelList(sapContext); + + if (dfs_event->chan_list.nchannels > SIR_DFS_MAX_20M_SUB_CH) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + FL("nchannels >SIR_DFS_MAX_20M_SUB_CH so resetting")); + dfs_event->chan_list.nchannels = SIR_DFS_MAX_20M_SUB_CH; + } + + sapMarkDfsChannels(sapContext, dfs_event->chan_list.channels, + dfs_event->chan_list.nchannels, vos_get_monotonic_boottime()); + + /* + * (1) skip static turbo channel as it will require STA to be in + * static turbo to work. + * (2) skip channel which's marked with radar detction + * (3) WAR: we allow user to config not to use any DFS channel + * (4) When we pick a channel, skip excluded 11D channels + * (5) Create the available channel list with the above rules + */ + + target_channel = sapRandomChannelSel(sapContext); + if (0 == target_channel) + { + sapSignalHDDevent(sapContext, NULL, eSAP_DFS_NO_AVAILABLE_CHANNEL, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + } + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + FL("sapdfs: New selected target channel is [%d]"), + target_channel); + return target_channel; +} + +/* + * CAC timer callback function. + * Post eSAP_DFS_CHANNEL_CAC_END event to sapFsm(). + */ +void sapDfsCacTimerCallback(void *data) +{ + ptSapContext sapContext; + tWLAN_SAPEvent sapEvent; + tHalHandle hHal = (tHalHandle)data; + tpAniSirGlobal pMac; + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return; + } + pMac = PMAC_STRUCT( hHal ); + sapContext = sap_find_valid_concurrent_session(hHal); + + if (NULL == sapContext) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s no SAP contexts are found", __func__); + return; + } + + /* Check to ensure that SAP is in DFS WAIT state*/ + if (sapContext->sapsMachine == eSAP_DFS_CAC_WAIT) + { + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = VOS_FALSE; + + + /* + * CAC Complete, post eSAP_DFS_CHANNEL_CAC_END to sapFsm + */ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Sending eSAP_DFS_CHANNEL_CAC_END for target_channel = %d on sapctx[%p]", + sapContext->channel, sapContext); + + sapEvent.event = eSAP_DFS_CHANNEL_CAC_END; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + + sapFsm(sapContext, &sapEvent); + } + +} + +/* + * Function to stop the DFS CAC Timer + */ +static int sapStopDfsCacTimer(ptSapContext sapContext) +{ + tHalHandle hHal; + tpAniSirGlobal pMac; + if (sapContext == NULL) + return 0; + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return 0; + } + pMac = PMAC_STRUCT(hHal); + + if (VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState( + &pMac->sap.SapDfsInfo.sap_dfs_cac_timer)) { + return 0; + } + + vos_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + + return 0; +} + +/** + * sap_is_channel_bonding_etsi_weather_channel() - Routine to check if + * sap channel is bonded to + * weather radar channel. + * @sap_context: SAP context + * + * Check if the current SAP operating channel is bonded to weather radar + * channel in ETSI domain. + * + * Return: True if bonded to weather channel in ETSI + */ +static bool +sap_is_channel_bonding_etsi_weather_channel(ptSapContext sap_context) +{ + if(IS_CH_BONDING_WITH_WEATHER_CH(sap_context->channel) && + (sap_context->vht_channel_width != eHT_CHANNEL_WIDTH_20MHZ)) { + return true; + } + return false; +} + +/* + * Function to start the DFS CAC Timer + * when SAP is started on a DFS channel + */ +int sapStartDfsCacTimer(ptSapContext sapContext) +{ + VOS_STATUS status; + v_U32_t cacTimeOut; + tHalHandle hHal = NULL; + tpAniSirGlobal pMac = NULL; + uint8_t dfs_region; + + if (sapContext == NULL) + { + return 0; + } + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return 0; + } + pMac = PMAC_STRUCT( hHal ); + + if (pMac->sap.SapDfsInfo.ignore_cac) + { + /* + * If User has set to ignore the CAC + * so, continue without CAC Timer. + */ + return 2; + } + cacTimeOut = DEFAULT_CAC_TIMEOUT; + + vos_nv_get_dfs_region(&dfs_region); + + if ((dfs_region == DFS_ETSI_DOMAIN) && + ((IS_ETSI_WEATHER_CH(sapContext->channel)) || + (sap_is_channel_bonding_etsi_weather_channel(sapContext)))) + { + cacTimeOut = ETSI_WEATHER_CH_CAC_TIMEOUT; + } + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: SAP_DFS_CHANNEL_CAC_START on CH - %d, CAC TIMEOUT - %d sec", + sapContext->channel, cacTimeOut/1000); + + vos_timer_init(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer, + VOS_TIMER_TYPE_SW, + sapDfsCacTimerCallback, (v_PVOID_t)hHal); + + /*Start the CAC timer*/ + status = vos_timer_start(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer, cacTimeOut); + if (status == VOS_STATUS_SUCCESS) + { + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = VOS_TRUE; + return 1; + } + else + { + return 0; + } +} + +/* + * This function initializes the NOL list + * parameters required to track the radar + * found DFS channels in the current Reg. Domain . + */ +VOS_STATUS sapInitDfsChannelNolList(ptSapContext sapContext) +{ + v_U8_t count = 0; + int i; + v_BOOL_t bFound = FALSE; + tHalHandle hHal; + tpAniSirGlobal pMac; + + if (NULL == sapContext) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Invalid sapContext pointer on sapInitDfsChannelNolList"); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return VOS_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT( hHal ); + + /* to indicate hdd to get cnss dfs nol */ + if (VOS_STATUS_SUCCESS == sapSignalHDDevent(sapContext, NULL, + eSAP_DFS_NOL_GET, + (v_PVOID_t) eSAP_STATUS_SUCCESS)) + { + bFound = TRUE; + } + + for ( i = RF_CHAN_36; i <= RF_CHAN_165; i++ ) + { + if ( regChannels[i].enabled == NV_CHANNEL_DFS ) + { + /* if dfs nol is not found, initialize it */ + if (!bFound) + { + pMac->sap.SapDfsInfo.sapDfsChannelNolList[count] + .dfs_channel_number = rfChannels[i].channelNum; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s: CHANNEL = %d", __func__, + pMac->sap.SapDfsInfo + .sapDfsChannelNolList[count].dfs_channel_number); + + pMac->sap.SapDfsInfo.sapDfsChannelNolList[count] + .radar_status_flag = eSAP_DFS_CHANNEL_USABLE; + pMac->sap.SapDfsInfo.sapDfsChannelNolList[count] + .radar_found_timestamp = 0; + } + count++; + } + } + + pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels = count; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "%s[%d] NUMBER OF DFS CHANNELS = %d", + __func__, __LINE__, + pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels); + + return VOS_STATUS_SUCCESS; +} + +/* + * This function will calculate how many interfaces + * have sap persona and returns total number of sap persona. + */ +v_U8_t sap_get_total_number_sap_intf(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_U8_t intf = 0; + v_U8_t intf_count = 0; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + if (((VOS_STA_SAP_MODE == pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList[intf].pSapContext != NULL) { + intf_count++; + } + } + return intf_count; +} + +/* + * This function will find the concurrent sap context apart from + * passed sap context and return its channel change ready status + */ +tANI_BOOLEAN is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, + ptSapContext sapContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + ptSapContext pSapContext; + v_U8_t intf = 0; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + if (((VOS_STA_SAP_MODE == pMac->sap.sapCtxList [intf].sapPersona) || + (VOS_P2P_GO_MODE == pMac->sap.sapCtxList [intf].sapPersona)) && + pMac->sap.sapCtxList[intf].pSapContext != NULL) { + pSapContext = + (ptSapContext)pMac->sap.sapCtxList [intf].pSapContext; + if (pSapContext == sapContext) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("sapCtx matched [%p]"), sapContext); + continue; + } else { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("concurrent sapCtx[%p] didn't matche with [%p]"), + pSapContext, sapContext); + return pSapContext->is_sap_ready_for_chnl_chng; + } + } + } + return VOS_FALSE; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm_ext.h b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm_ext.h new file mode 100644 index 000000000000..23c806d0de24 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm_ext.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* This file is generated from btampFsm.cdd - do not edit manually*/ +/* Generated on: Thu Oct 16 15:40:39 PDT 2008 */ + + +#ifndef __SAPFSM_EXT_H__ +#define __SAPFSM_EXT_H__ + +/* Events that can be sent to the SAP state-machine */ +typedef enum +{ + eSAP_TIMER_CONNECT_ACCEPT_TIMEOUT=0U, + eSAP_MAC_CONNECT_COMPLETED, + eSAP_CHANNEL_SELECTION_FAILED, + eSAP_MAC_CONNECT_INDICATION, + eSAP_MAC_KEY_SET_SUCCESS, + eSAP_RSN_FAILURE, + eSAP_MAC_SCAN_COMPLETE, + eSAP_HDD_START_INFRA_BSS, + eSAP_MAC_READY_FOR_CONNECTIONS, + eSAP_MAC_START_BSS_SUCCESS, + eSAP_MAC_START_BSS_FAILURE, + eSAP_RSN_SUCCESS, + eSAP_MAC_START_FAILS, + eSAP_HDD_STOP_INFRA_BSS, + eSAP_WRITE_REMOTE_AMP_ASSOC, + eSAP_DFS_CHANNEL_CAC_START, + eSAP_DFS_CHANNEL_CAC_RADAR_FOUND, + eSAP_DFS_CHANNEL_CAC_END, + eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START, + eSAP_OPERATING_CHANNEL_CHANGED, + eSAP_CHANNEL_SELECTION_RETRY, + + eSAP_NO_MSG +}eSapMsg_t; + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapInternal.h b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapInternal.h new file mode 100644 index 000000000000..892307856592 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapInternal.h @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WLAN_QCT_WLANSAP_INTERNAL_H +#define WLAN_QCT_WLANSAP_INTERNAL_H + +/*=========================================================================== + + W L A N S A P P A L L A Y E R + I N T E R N A L A P I + + +DESCRIPTION + This file contains the internal API exposed by the wlan SAP PAL layer + module. +===========================================================================*/ + + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header: /cygdrive/d/Builds/M7201JSDCAAPAD52240B/WM/platform/msm7200/Src/Drivers/SD/ClientDrivers/WLAN/QCT_BTAMP_RSN/CORE/BAP/src/bapInternal.h,v 1.7 2009/03/09 08:50:43 rgidvani Exp rgidvani $ $DateTime: $ $Author: jzmuda $ + + +when who what, where, why +-------- --- ---------------------------------------------------------- +09/15/08 SOFTAP Created module. + +===========================================================================*/ + + + +/*=========================================================================== + + INCLUDE FILES FOR MODULE + +===========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "vos_api.h" +#include "vos_packet.h" + +// Pick up the CSR API definitions +#include "csrApi.h" +#include "sapApi.h" +#include "sapFsm_ext.h" +#include "sapChSelect.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + #ifdef __cplusplus + extern "C" { + #endif + + +/*---------------------------------------------------------------------------- + * Defines + * -------------------------------------------------------------------------*/ +//DFS Non Occupancy Period =30 minutes, in microseconds +#define SAP_DFS_NON_OCCUPANCY_PERIOD (30 * 60 * 1000 * 1000) + +#define SAP_DEBUG +// Used to enable or disable security on the BT-AMP link +#define WLANSAP_SECURITY_ENABLED_STATE VOS_TRUE +#ifdef WLAN_FEATURE_MBSSID +// When MBSSID feature is enabled, SAP context is directly passed to SAP APIs +#define VOS_GET_SAP_CB(ctx) (ptSapContext)(ctx) +#else +// How do I get SAP context from voss context? +#define VOS_GET_SAP_CB(ctx) vos_get_context( VOS_MODULE_ID_SAP, ctx) +#endif + +#define VOS_GET_HAL_CB(ctx) vos_get_context( VOS_MODULE_ID_PE, ctx) +//MAC Address length +#define ANI_EAPOL_KEY_RSN_NONCE_SIZE 32 + +#define IS_ETSI_WEATHER_CH(_ch) ((_ch >= 120) && (_ch <= 130)) +#define IS_CH_BONDING_WITH_WEATHER_CH(_ch) (_ch == 116) +#define IS_CHAN_JAPAN_W53(_ch) ((_ch >= 52) && (_ch <= 64)) +#define IS_CHAN_JAPAN_INDOOR(_ch) ((_ch >= 36) && (_ch <= 64)) +#define IS_CHAN_JAPAN_OUTDOOR(_ch)((_ch >= 100) && (_ch <= 140)) +#define DEFAULT_CAC_TIMEOUT (60 * 1000) //msecs - 1 min +#define ETSI_WEATHER_CH_CAC_TIMEOUT (10 * 60 * 1000) //msecs - 10 min +#define SAP_CHAN_PREFERRED_INDOOR 1 +#define SAP_CHAN_PREFERRED_OUTDOOR 2 + +extern const sRegulatoryChannel *regChannels; + +/*---------------------------------------------------------------------------- + * Typedefs + * -------------------------------------------------------------------------*/ +typedef struct sSapContext tSapContext; +// tSapContext, *ptSapContext; +/*---------------------------------------------------------------------------- + * Type Declarations - For internal SAP context information + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Opaque SAP context Type Declaration + * -------------------------------------------------------------------------*/ +// We were only using this syntax, when this was truly opaque. +// (I.E., it was defined in a different file.) + + +/* SAP FSM states for Access Point role */ +typedef enum { + eSAP_DISCONNECTED, + eSAP_CH_SELECT, + eSAP_DFS_CAC_WAIT, + eSAP_STARTING, + eSAP_STARTED, + eSAP_DISCONNECTING +} eSapFsmStates_t; + +/*---------------------------------------------------------------------------- + * SAP context Data Type Declaration + * -------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------- + * Type Declarations - QOS related + * -------------------------------------------------------------------------*/ +/* SAP QOS config */ +typedef struct sSapQosCfg { + v_U8_t WmmIsEnabled; +} tSapQosCfg; + +typedef struct sSapAcsChannelInfo { + v_U32_t channelNum; + v_U32_t weight; +}tSapAcsChannelInfo; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/* + * In a setup having two MDM both operating in AP+AP MCC scenario + * if both the AP decides to use same or close channel set, CTS to + * self, mechanism is causing issues with connectivity. For this, its + * proposed that 2nd MDM devices which comes up later should detect + * presence of first MDM device via special Q2Q IE present in becon + * and avoid those channels mentioned in IE. + * + * Following struct will keep this info in sapCtx struct, and will be used + * to avoid such channels in Random Channel Select in case of radar ind. + */ +struct sap_avoid_channels_info { + bool present; + uint8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +}; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +typedef struct sSapContext { + + vos_lock_t SapGlobalLock; + + // Include the current channel of AP + v_U32_t channel; + v_U32_t secondary_ch; + + // Include the SME(CSR) sessionId here + v_U8_t sessionId; + + // Include the key material for this physical link + v_U8_t key_type; + v_U8_t key_length; + v_U8_t key_material[32]; + + // Include the associations MAC addresses + v_U8_t self_mac_addr[VOS_MAC_ADDRESS_LEN]; + + // Own SSID + v_U8_t ownSsid[MAX_SSID_LEN]; + v_U32_t ownSsidLen; + + // Flag for signaling if security is enabled + v_U8_t ucSecEnabled; + + // Include the SME(CSR) context here + tCsrRoamProfile csrRoamProfile; + v_U32_t csrRoamId; + + //Sap session + tANI_BOOLEAN isSapSessionOpen; + + // SAP event Callback to hdd + tpWLAN_SAPEventCB pfnSapEventCallback; + + // Include the enclosing VOSS context here + v_PVOID_t pvosGCtx; + + // Include the state machine structure here, state var that keeps track of state machine + eSapFsmStates_t sapsMachine; + + // Actual storage for AP and self (STA) SSID + tCsrSSIDInfo SSIDList[2]; + + // Actual storage for AP bssid + tCsrBssid bssid; + + // Mac filtering settings + eSapMacAddrACL eSapMacAddrAclMode; + v_MACADDR_t acceptMacList[MAX_ACL_MAC_ADDRESS]; + v_U8_t nAcceptMac; + v_MACADDR_t denyMacList[MAX_ACL_MAC_ADDRESS]; + v_U8_t nDenyMac; + + // QOS config + tSapQosCfg SapQosCfg; + + v_PVOID_t pUsrContext; + + v_U32_t nStaWPARSnReqIeLength; + v_U8_t pStaWpaRsnReqIE[MAX_ASSOC_IND_IE_LEN]; + tSirAPWPSIEs APWPSIEs; + tSirRSNie APWPARSNIEs; + +#ifdef FEATURE_WLAN_WAPI + v_U32_t nStaWAPIReqIeLength; + v_U8_t pStaWapiReqIE[MAX_ASSOC_IND_IE_LEN]; +#endif + + v_U32_t nStaAddIeLength; + v_U8_t pStaAddIE[MAX_ASSOC_IND_IE_LEN]; + v_U8_t *channelList; + tSapChannelListInfo SapChnlList; + uint16_t vht_channel_width; + uint16_t ch_width_orig; + + // session to scan + tANI_BOOLEAN isScanSessionOpen; + /* + * This list of channels will hold 5Ghz enabled,DFS in the + * Current RegDomain.This list will be used to select a channel, + * for SAP to start including any DFS channel and also to select + * any random channel[5Ghz-(NON-DFS/DFS)],if SAP is operating + * on a DFS channel and a RADAR is detected on the channel. + */ + tAll5GChannelList SapAllChnlList; + + + tANI_BOOLEAN allBandScanned; + eCsrBand currentPreferredBand; + eCsrBand scanBandPreference; + v_U16_t acsBandSwitchThreshold; + tSapAcsChannelInfo acsBestChannelInfo; + tANI_BOOLEAN enableOverLapCh; + + struct sap_acs_cfg *acs_cfg; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + v_U8_t cc_switch_mode; +#endif + +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) ||\ + defined(WLAN_FEATURE_MBSSID) + v_BOOL_t dfs_ch_disable; +#endif + tANI_BOOLEAN isCacEndNotified; + tANI_BOOLEAN isCacStartNotified; + tANI_BOOLEAN is_sap_ready_for_chnl_chng; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* + * In a setup having two MDM both operating in AP+AP MCC scenario + * if both the AP decides to use same or close channel set, CTS to + * self, mechanism is causing issues with connectivity. For this, its + * proposed that 2nd MDM devices which comes up later should detect + * presence of first MDM device via special Q2Q IE present in becon + * and avoid those channels mentioned in IE. + * + * this struct contains the list of channels on which another MDM AP + * in MCC mode were detected. + */ + struct sap_avoid_channels_info sap_detected_avoid_ch_ie; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ +} *ptSapContext; + + +/*---------------------------------------------------------------------------- + * External declarations for global context + * -------------------------------------------------------------------------*/ +// The main per-Physical Link (per WLAN association) context. +extern ptSapContext gpSapCtx; + +/*---------------------------------------------------------------------------- + * SAP state machine event definition + * -------------------------------------------------------------------------*/ +/* The event structure */ +typedef struct sWLAN_SAPEvent { + v_PVOID_t params; /* A VOID pointer type for all possible inputs */ + v_U32_t event; /* State machine input event message */ + v_U32_t u1; /* introduced to handle csrRoamCompleteCallback roamStatus */ + v_U32_t u2; /* introduced to handle csrRoamCompleteCallback roamResult */ +} tWLAN_SAPEvent, *ptWLAN_SAPEvent; + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANSAP_ScanCallback() + + DESCRIPTION + Callback for Scan (scan results) Events + + DEPENDENCIES + NA. + + PARAMETERS + + IN + tHalHandle: the tHalHandle passed in with the scan request + *p2: the second context pass in for the caller, opaque sap Handle here + scanID: + sessionId: Session identifier + status: Status of scan -success, failure or abort + + RETURN VALUE + The eHalStatus code associated with performing the operation + + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS + +============================================================================*/ +eHalStatus +WLANSAP_ScanCallback +( + tHalHandle halHandle, + void *pContext, + v_U8_t sessionId, + v_U32_t scanID, + eCsrScanStatus scanStatus +); + +/*========================================================================== + + FUNCTION WLANSAP_PreStartBssAcsScanCallback() + + DESCRIPTION + Callback for Scan (scan results) Events + + DEPENDENCIES + NA. + + PARAMETERS + + IN + tHalHandle: the tHalHandle passed in with the scan request + *p2: the second context pass in for the caller, opaque sap Handle here + scanID: + sessionId: Session identifier + status: Status of scan -success, failure or abort + + RETURN VALUE + The eHalStatus code associated with performing the operation + + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS + +============================================================================*/ +eHalStatus +WLANSAP_PreStartBssAcsScanCallback +( + tHalHandle halHandle, + void *pContext, + v_U8_t sessionId, + v_U32_t scanID, + eCsrScanStatus scanStatus +); + +/*========================================================================== + + FUNCTION WLANSAP_RoamCallback() + + DESCRIPTION + Callback for Roam (connection status) Events + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pContext: is the pContext passed in with the roam request + pCsrRoamInfo: is a pointer to a tCsrRoamInfo, see definition of eRoamCmdStatus and + eRoamCmdResult: for detail valid members. It may be NULL + roamId: is to identify the callback related roam request. 0 means unsolicited + roamStatus: is a flag indicating the status of the callback + roamResult: is the result + + RETURN VALUE + The eHalStatus code associated with performing the operation + + eHAL_STATUS_SUCCESS: Success + + SIDE EFFECTS + +============================================================================*/ +eHalStatus +WLANSAP_RoamCallback +( + void *pContext, + tCsrRoamInfo *pCsrRoamInfo, + v_U32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult +); + +/*========================================================================== + + FUNCTION WLANSAP_CleanCB + + DESCRIPTION + Clear out all fields in the SAP context. + + DEPENDENCIES + + PARAMETERS + + IN + pSapCtx: pointer to the SAP control block + freeFlag: flag indicating whether to free any allocations. + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANSAP_CleanCB +( + ptSapContext pSapCtx, + v_U32_t freeFlag /* If 0 do not empty */ +); +/*========================================================================== + + FUNCTION WLANSapFsm + + DESCRIPTION + SAP forward state machine to handle the states of the SAP + + DEPENDENCIES + + PARAMETERS + + IN + sapContext: pointer to the SAP control block + sapEvent : SAP event + status : status of SAP state machine + + RETURN VALUE + Status of the SAP forward machine + + VOS_STATUS_E_FAULT: pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ + +VOS_STATUS +SapFsm +( + ptSapContext sapContext, /* sapContext value */ + ptWLAN_SAPEvent sapEvent, /* State machine event */ + v_U8_t *status /* return the SAP status here */ +); + +/*========================================================================== + + FUNCTION WLANSAP_pmcFullPwrReqCB + + DESCRIPTION + Callback provide to PMC in the pmcRequestFullPower API. + + DEPENDENCIES + + PARAMETERS + + IN + callbackContext: The user passed in a context to identify + status: The halStatus + + RETURN VALUE + None + + SIDE EFFECTS + +============================================================================*/ +void +WLANSAP_pmcFullPwrReqCB +( + void *callbackContext, + eHalStatus status +); + +/*========================================================================== + + FUNCTION sapSelectChannel + + DESCRIPTION + Runs a algorithm to select the best channel to operate in for Soft AP in 2.4GHz band + + DEPENDENCIES + + PARAMETERS + + IN + halHandle : Pointer to HAL handle + pSapCtx : Pointer to SAP context + pResult : Pointer to tScanResultHandle + + RETURN VALUE + If SUCCESS channel number or zero for FAILURE. + + SIDE EFFECTS + +============================================================================*/ + +v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResultHandle pScanResult); + +/*========================================================================== + + FUNCTION sapSignalHDDevent + + DESCRIPTION + SAP HDD event callback function + + DEPENDENCIES + + PARAMETERS + + IN + sapContext : Pointer to SAP handle + pCsrRoamInfo : csrRoamprofile + sapHddevent : SAP HDD callback event + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ + +VOS_STATUS +sapSignalHDDevent( ptSapContext sapContext, tCsrRoamInfo * pCsrRoamInfo, eSapHddEvent sapHddevent, void *); + +/*========================================================================== + + FUNCTION sapFsm + + DESCRIPTION + SAP Forward state machine + + DEPENDENCIES + + PARAMETERS + + IN + sapContext : Pointer to SAP handle + sapEvent : state machine event + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +sapFsm +( + ptSapContext sapContext, /* sapContext value */ + ptWLAN_SAPEvent sapEvent /* State machine event */ +); + +/*========================================================================== + FUNCTION sapGotoChannelSel + + DESCRIPTION + Function for initiating scan request for SME + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapContext : Sap Context value + sapEvent : State machine event/ NULL if no FSM event is required. + sapDoAcsPreStartBss: VOS_TRUE, if ACS scan is issued pre start BSS. + VOS_FALSE, if ACS scan is issued post start BSS. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +sapGotoChannelSel +( + ptSapContext sapContext, + ptWLAN_SAPEvent sapEvent, + v_BOOL_t sapDoAcsPreStartBss +); + +/*========================================================================== + + FUNCTION sapConvertToCsrProfile + + DESCRIPTION + sapConvertToCsrProfile + + DEPENDENCIES + + PARAMETERS + + IN + pconfig_params : Pointer to configuration structure + bssType : SoftAP type + profile : pointer to a csrProfile that needs to be passed + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ +eSapStatus +sapconvertToCsrProfile(tsap_Config_t *pconfig_params, eCsrRoamBssType bssType, tCsrRoamProfile *profile); + +/*========================================================================== + + FUNCTION sapFreeRoamProfile + + DESCRIPTION + sapConvertToCsrProfile + + DEPENDENCIES + + PARAMETERS + + IN + profile : pointer to a csrProfile that needs to be freed + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ +void sapFreeRoamProfile(tCsrRoamProfile *profile); + +/*========================================================================== + + FUNCTION sapIsPeerMacAllowed + + DESCRIPTION + Function to implement MAC filtering for station association in SoftAP + + DEPENDENCIES + + PARAMETERS + + IN + sapContext : Pointer to SAP handle + peerMac : Mac address of the peer + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +sapIsPeerMacAllowed(ptSapContext sapContext, v_U8_t *peerMac); + +/*========================================================================== + + FUNCTION sapSortMacList + + DESCRIPTION + Function to implement sorting of MAC addresses + + DEPENDENCIES + + PARAMETERS + + IN + macList : Pointer to mac address array + size : Number of entries in mac address array + + RETURN VALUE + None + + SIDE EFFECTS + +============================================================================*/ +void +sapSortMacList(v_MACADDR_t *macList, v_U8_t size); + +/*========================================================================== + + FUNCTION sapAddMacToACL + + DESCRIPTION + Function to ADD a mac address in an ACL. + The function ensures that the ACL list remains sorted after the addition. + This API does not take care of buffer overflow i.e. if the list is already + maxed out while adding a mac address, it will still try to add. + The caller must take care that the ACL size is less than MAX_ACL_MAC_ADDRESS + before calling this function. + + DEPENDENCIES + + PARAMETERS + + IN + macList : ACL list of mac addresses (black/white list) + size (I/O) : size of the ACL. It is an I/O arg. The API takes care + of incrementing the size by 1. + peerMac : Mac address of the peer to be added + + RETURN VALUE + None. + + SIDE EFFECTS + +============================================================================*/ +void +sapAddMacToACL(v_MACADDR_t *macList, v_U8_t *size, v_U8_t *peerMac); + +/*========================================================================== + + FUNCTION sapRemoveMacFromACL + + DESCRIPTION + Function to REMOVE a mac address from an ACL. + The function ensures that the ACL list remains sorted after the DELETION. + + DEPENDENCIES + + PARAMETERS + + IN + macList : ACL list of mac addresses (black/white list) + size (I/O) : size of the ACL. It is an I/O arg. The API takes care of decrementing the size by 1. + index : index in the ACL list where the peerMac is present + This index can be found by using the "sapSearchMacList" API which returns the index of the MAC + addr, if found in an ACL, in one of the arguments passed by the caller. + + RETURN VALUE + None. + + SIDE EFFECTS + +============================================================================*/ +void +sapRemoveMacFromACL(v_MACADDR_t *macList, v_U8_t *size, v_U8_t index); + +/*========================================================================== + + FUNCTION sapPrintACL + + DESCRIPTION + Function to print all the mac address of an ACL. + Useful for debug. + + DEPENDENCIES + + PARAMETERS + + IN + macList : ACL list of mac addresses (black/white list) + size : size of the ACL + + RETURN VALUE + None. + + SIDE EFFECTS + +============================================================================*/ +void +sapPrintACL(v_MACADDR_t *macList, v_U8_t size); + +/*========================================================================== + + FUNCTION sapSearchMacList + + DESCRIPTION + Function to search for a mac address in an ACL + + DEPENDENCIES + + PARAMETERS + + IN + macList : list of mac addresses (black/white list) + num_mac : size of the ACL + peerMac : Mac address of the peer + OP + index : the index at which the peer mac is found + this value gets filled in this function. If the caller is not interested + in the index of the peerMac to be searched, it can pass NULL here. + + RETURN VALUE + SUCCESS : if the mac addr being searched for is found + FAILURE : if the mac addr being searched for is NOT found + + SIDE EFFECTS + +============================================================================*/ +eSapBool +sapSearchMacList(v_MACADDR_t *macList, v_U8_t num_mac, v_U8_t *peerMac, v_U8_t *index); + + +/*========================================================================== + + FUNCTION sap_AcquireGlobalLock + + DESCRIPTION + Function to implement acquire SAP global lock + + DEPENDENCIES + + PARAMETERS + + IN + sapContext : Pointer to SAP handle + peerMac : Mac address of the peer + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +sap_AcquireGlobalLock( ptSapContext pSapCtx ); + +/*========================================================================== + + FUNCTION sapIsPeerMacAllowed + + DESCRIPTION + Function to implement release SAP global lock + + DEPENDENCIES + + PARAMETERS + + IN + sapContext : Pointer to SAP handle + peerMac : Mac address of the peer + + RETURN VALUE + If SUCCESS or FAILURE. + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +sap_ReleaseGlobalLock( ptSapContext pSapCtx ); + +#ifdef FEATURE_WLAN_CH_AVOID +/*========================================================================== + FUNCTION sapUpdateUnsafeChannelList + + DESCRIPTION + Function sapUpdateUnsafeChannelList updates the SAP context of unsafe channels. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + Pointer to sap context + + RETURN VALUE + NULL +============================================================================*/ +void sapUpdateUnsafeChannelList(ptSapContext pSapCtx); +#endif /* FEATURE_WLAN_CH_AVOID */ + +/*--------------------------------------------------------------------------- +FUNCTION sapIndicateRadar + +DESCRIPTION Function to implement actions on Radar Detection when SAP is on + DFS Channel + +DEPENDENCIES PARAMETERS +IN sapContext : Sap Context which hold SapDfsInfo + dfs_event : Event from DFS Module + +RETURN VALUE : Target Channel For SAP to Move on to when Radar is Detected. + +SIDE EFFECTS +---------------------------------------------------------------------------*/ +v_U8_t +sapIndicateRadar(ptSapContext sapContext,tSirSmeDfsEventInd *dfs_event); + +/* + * This function initializes the NOL list + * parameters required to track the radar + * found DFS channels in the current Reg. Domain. + */ +VOS_STATUS +sapInitDfsChannelNolList(ptSapContext sapContext); + +/* + * This Function Checks if a given channel is AVAILABLE or USABLE + * for DFS operation. + */ +v_BOOL_t sapDfsIsChannelInNolList(ptSapContext sapContext, + v_U8_t channelNumber, ePhyChanBondState chanBondState); +/*--------------------------------------------------------------------------- +FUNCTION sapDfsCacTimerCallback + +DESCRIPTION Function will be called up on DFS CAC timer expiry + +DEPENDENCIES PARAMETERS + data : void pointer to the data which being passed. + +RETURN VALUE : void + +SIDE EFFECTS +---------------------------------------------------------------------------*/ +void sapDfsCacTimerCallback(void *data); + + +/*--------------------------------------------------------------------------- +FUNCTION sap_CacResetNotify + +DESCRIPTION Function will be called up on stop bss indication to clean up + DFS global structure. + +DEPENDENCIES PARAMETERS +IN hHAL : HAL pointer + +RETURN VALUE : void. + +SIDE EFFECTS +---------------------------------------------------------------------------*/ +void sap_CacResetNotify(tHalHandle hHal); + +v_BOOL_t sapAcsChannelCheck(ptSapContext sapContext, v_U8_t channelNumber); + +/* + * This function is added to check if channel is in tx leak range + * + * PARAMETERS + * IN + * sapContext: Pointer to vos global context structure + * target_channel: the target channel to switch to + * + * RETURN VALUE + * BOOLEAN to indicate if the target channel is good or bad to switch + * + * TRUE: the channel is above the tx leak threshold + * FALSE: good to be used + */ +v_BOOL_t +sapChannelMatrixCheck(ptSapContext sapContext, + ePhyChanBondState cbMode, + v_U8_t target_channel); + +/* + * This function will find the concurrent sap context apart from + * passed sap context and return its channel change ready status + * + * PARAMETERS + * IN + * sapContext: pointer to sap context + * hHal: pointer to hal structure. + * + * RETURN VALUE + * v_BOOL_t + * returns change change ready indication for concurrent sapctx + */ +v_BOOL_t is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, + ptSapContext sapContext); + +/* + * This function will calculate how many interfaces + * have sap persona and returns total number of sap persona. + * + * PARAMETERS + * IN + * hHal: pointer to hal structure. + * + * RETURN VALUE + * v_U8_t + * Returns total number of sap interfaces. + * + */ +v_U8_t sap_get_total_number_sap_intf(tHalHandle hHal); + +/*--------------------------------------------------------------------------- +FUNCTION sapDfsIsW53Invalid + +DESCRIPTION Checks if the passed channel is W53 and returns if + SAP W53 opearation is allowed. + +DEPENDENCIES PARAMETERS +IN hHAL : HAL pointer +channelID: Channel Number to be verified + +RETURN VALUE : v_BOOL_t + VOS_TRUE: If W53 operation is disabled + VOS_FALSE: If W53 operation is enabled + +SIDE EFFECTS +---------------------------------------------------------------------------*/ +v_BOOL_t sapDfsIsW53Invalid(tHalHandle hHal, v_U8_t channelID); + +/*--------------------------------------------------------------------------- +FUNCTION sapDfsIsChannelInPreferredLocation + +DESCRIPTION Checks if the passed channel is in accordance with preferred + Channel location settings. + +DEPENDENCIES PARAMETERS +IN hHAL : HAL pointer +channelID: Channel Number to be verified + +RETURN VALUE :v_BOOL_t + VOS_TRUE:If Channel location is same as the preferred location + VOS_FALSE:If Channel location is not same as the preferred location + +SIDE EFFECTS +---------------------------------------------------------------------------*/ +v_BOOL_t sapDfsIsChannelInPreferredLocation(tHalHandle hHal, v_U8_t channelID); + +void sap_config_acs_result(tHalHandle hal, ptSapContext sap_ctx, + uint32_t sec_ch); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * sap_check_in_avoid_ch_list() - checks if given channel present is channel + * avoidance list + * avoid_channels_info struct + * @sap_ctx: sap context. + * @channel: channel to be checked in sap_ctx's avoid ch list + * + * sap_ctx contains sap_avoid_ch_info strcut containing the list of channels on + * which MDM device's AP with MCC was detected. This function checks if given + * channel is present in that list. + * + * Return: true, if channel was present, false othersie. + */ +bool sap_check_in_avoid_ch_list(ptSapContext sap_ctx, uint8_t channel); +#endif +#ifdef __cplusplus +} +#endif +#endif /* #ifndef WLAN_QCT_WLANSAP_INTERNAL_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c new file mode 100644 index 000000000000..a1e4547548af --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c @@ -0,0 +1,3972 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + s a p M o d u l e . C + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP modules + functions providing EXTERNAL APIs. It is also where the global SAP module + context gets initialised + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- +03/15/10 SOFTAP team Created module +06/03/10 js Added support to hostapd driven + * deauth/disassoc/mic failure + +===========================================================================*/ + +/* $Header$ */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "wlan_qct_tl.h" +#include "vos_trace.h" + +// Pick up the sme callback registration API +#include "sme_Api.h" + +// SAP API header file + +#include "sapInternal.h" +#include "smeInside.h" +#include "regdomain_common.h" +#include "_ieee80211_common.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define SAP_DEBUG + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * External declarations for global context + * -------------------------------------------------------------------------*/ +// No! Get this from VOS. +// The main per-Physical Link (per WLAN association) context. +ptSapContext gpSapCtx; + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Function Declarations and Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Externalized Function Definitions +* -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + FUNCTION WLANSAP_Open + + DESCRIPTION + Called at driver initialization (vos_open). SAP will initialize + all its internal resources and will wait for the call to start to + register with the other modules. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx : Pointer to the global vos context; a handle to SAP's + + RETURN VALUE + The result code associated with performing the operation + +#ifdef WLAN_FEATURE_MBSSID + v_PVOID_t : Pointer to the SAP context +#else + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success +#endif + + SIDE EFFECTS +============================================================================*/ +#ifdef WLAN_FEATURE_MBSSID +v_PVOID_t +#else +VOS_STATUS +#endif +WLANSAP_Open +( + v_PVOID_t pvosGCtx +) +{ + ptSapContext pSapCtx = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +#ifdef WLAN_FEATURE_MBSSID + // amically allocate the sapContext + pSapCtx = (ptSapContext)vos_mem_malloc(sizeof(tSapContext)); +#else + if (NULL == pvosGCtx) + { + VOS_ASSERT(pvosGCtx); + return VOS_STATUS_E_FAULT; + } + /*------------------------------------------------------------------------ + Allocate (and sanity check?!) SAP control block + ------------------------------------------------------------------------*/ + vos_alloc_context(pvosGCtx, VOS_MODULE_ID_SAP, (v_VOID_t **)&pSapCtx, sizeof(tSapContext)); +#endif + + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); +#ifdef WLAN_FEATURE_MBSSID + return NULL; +#else + return VOS_STATUS_E_FAULT; +#endif + } + + /*------------------------------------------------------------------------ + Clean up SAP control block, initialize all values + ------------------------------------------------------------------------*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANSAP_Open"); + + WLANSAP_CleanCB(pSapCtx, 0 /*do not empty*/); + + // Setup the "link back" to the VOSS context + pSapCtx->pvosGCtx = pvosGCtx; + + // Store a pointer to the SAP context provided by VOSS + gpSapCtx = pSapCtx; + + /*------------------------------------------------------------------------ + Allocate internal resources + ------------------------------------------------------------------------*/ + +#ifdef WLAN_FEATURE_MBSSID + return pSapCtx; +#else + return VOS_STATUS_SUCCESS; +#endif +}// WLANSAP_Open + +/*========================================================================== + FUNCTION WLANSAP_Start + + DESCRIPTION + Called as part of the overall start procedure (vos_start). SAP will + use this call to register with TL as the SAP entity for + SAP RSN frames. + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANSAP_Start +( + v_PVOID_t pCtx +) +{ + ptSapContext pSapCtx = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_Start invoked successfully"); + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + pSapCtx = VOS_GET_SAP_CB(pCtx); + + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + For now, presume security is not enabled. + -----------------------------------------------------------------------*/ + pSapCtx->ucSecEnabled = WLANSAP_SECURITY_ENABLED_STATE; + + + /*------------------------------------------------------------------------ + Now configure the roaming profile links. To SSID and bssid. + ------------------------------------------------------------------------*/ + // We have room for two SSIDs. + pSapCtx->csrRoamProfile.SSIDs.numOfSSIDs = 1; // This is true for now. + pSapCtx->csrRoamProfile.SSIDs.SSIDList = pSapCtx->SSIDList; //Array of two + pSapCtx->csrRoamProfile.SSIDs.SSIDList[0].SSID.length = 0; + pSapCtx->csrRoamProfile.SSIDs.SSIDList[0].handoffPermitted = VOS_FALSE; + pSapCtx->csrRoamProfile.SSIDs.SSIDList[0].ssidHidden = pSapCtx->SSIDList[0].ssidHidden; + + pSapCtx->csrRoamProfile.BSSIDs.numOfBSSIDs = 1; // This is true for now. + pSapCtx->csrRoamProfile.BSSIDs.bssid = &pSapCtx->bssid; + + // Now configure the auth type in the roaming profile. To open. + pSapCtx->csrRoamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; // open is the default + + if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pSapCtx->SapGlobalLock))) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "WLANSAP_Start failed init lock"); + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_SUCCESS; +}/* WLANSAP_Start */ + +/*========================================================================== + + FUNCTION WLANSAP_Stop + + DESCRIPTION + Called by vos_stop to stop operation in SAP, before close. SAP will suspend all + BT-AMP Protocol Adaption Layer operation and will wait for the close + request to clean up its resources. + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Stop +( + v_PVOID_t pCtx +) +{ + ptSapContext pSapCtx = NULL; + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_Stop invoked successfully "); + + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + sapFreeRoamProfile(&pSapCtx->csrRoamProfile); + + if( !VOS_IS_STATUS_SUCCESS( vos_lock_destroy( &pSapCtx->SapGlobalLock ) ) ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "WLANSAP_Stop failed destroy lock"); + return VOS_STATUS_E_FAULT; + } + /*------------------------------------------------------------------------ + Stop SAP (de-register RSN handler!?) + ------------------------------------------------------------------------*/ + + return VOS_STATUS_SUCCESS; +}/* WLANSAP_Stop */ + +/*========================================================================== + FUNCTION WLANSAP_Close + + DESCRIPTION + Called by vos_close during general driver close procedure. SAP will clean up + all the internal resources. + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Close +( + v_PVOID_t pCtx +) +{ + ptSapContext pSapCtx = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_Close invoked"); + + + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + Cleanup SAP control block. + ------------------------------------------------------------------------*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANSAP_Close"); + WLANSAP_CleanCB(pSapCtx, VOS_TRUE /* empty queues/lists/pkts if any*/); + +#ifdef WLAN_FEATURE_MBSSID + vos_mem_free(pSapCtx); +#else + /*------------------------------------------------------------------------ + Free SAP context from VOSS global + ------------------------------------------------------------------------*/ + vos_free_context(pCtx, VOS_MODULE_ID_SAP, pSapCtx); +#endif + + return VOS_STATUS_SUCCESS; +}/* WLANSAP_Close */ + +/*---------------------------------------------------------------------------- + * Utility Function implementations + * -------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANSAP_CleanCB + + DESCRIPTION + Clear out all fields in the SAP context. + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_CleanCB +( + ptSapContext pSapCtx, + v_U32_t freeFlag // 0 /*do not empty*/); +) +{ + /*------------------------------------------------------------------------ + Sanity check SAP control block + ------------------------------------------------------------------------*/ + + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + Clean up SAP control block, initialize all values + ------------------------------------------------------------------------*/ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLANSAP_CleanCB"); + + vos_mem_zero( pSapCtx, sizeof(tSapContext)); + + pSapCtx->pvosGCtx = NULL; + + pSapCtx->sapsMachine= eSAP_DISCONNECTED; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Initializing State: %d, sapContext value = %p", + __func__, pSapCtx->sapsMachine, pSapCtx); + pSapCtx->sessionId = 0; + pSapCtx->channel = 0; + pSapCtx->isSapSessionOpen = eSAP_FALSE; + + return VOS_STATUS_SUCCESS; +}// WLANSAP_CleanCB + +/*========================================================================== + FUNCTION WLANSAP_pmcFullPwrReqCB + + DESCRIPTION + Callback provide to PMC in the pmcRequestFullPower API. + + DEPENDENCIES + + PARAMETERS + + IN + callbackContext: The user passed in a context to identify + status: The halStatus + + RETURN VALUE + None + + SIDE EFFECTS +============================================================================*/ +void +WLANSAP_pmcFullPwrReqCB +( + void *callbackContext, + eHalStatus status +) +{ + if(HAL_STATUS_SUCCESS(status)) + { + //If success what else to be handled??? + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "WLANSAP_pmcFullPwrReqCB: PMC failed to put the chip in Full power"); + + } + +}// WLANSAP_pmcFullPwrReqCB + +/*========================================================================== + FUNCTION WLANSAP_getState + + DESCRIPTION + This api returns the current SAP state to the caller. + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + Returns the SAP FSM state. +============================================================================*/ + +v_U8_t WLANSAP_getState +( + v_PVOID_t pCtx +) +{ + ptSapContext pSapCtx = NULL; + + pSapCtx = VOS_GET_SAP_CB(pCtx); + + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + return pSapCtx->sapsMachine; +} + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/*========================================================================== + FUNCTION WLANSAP_CheckCCIntf + + DESCRIPTION Restart SAP if Concurrent Channel interfering + + DEPENDENCIES NA. + + PARAMETERS + IN + Ctx: Pointer to vos Context or Sap Context based on MBSSID + + RETURN VALUE NONE + + SIDE EFFECTS +============================================================================*/ +v_U16_t WLANSAP_CheckCCIntf(v_PVOID_t Ctx) +{ + tHalHandle hHal; + v_U16_t intf_ch; + ptSapContext pSapCtx = VOS_GET_SAP_CB(Ctx); + + hHal = (tHalHandle)VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid MAC context from pvosGCtx", __func__); + return 0; + } + intf_ch = sme_CheckConcurrentChannelOverlap(hHal, 0, 0, + pSapCtx->cc_switch_mode); + return intf_ch; +} +#endif + +/*========================================================================== + FUNCTION wlan_sap_get_vht_ch_width + + DESCRIPTION Returns the SAP VHT channel width. + + DEPENDENCIES NA. + + PARAMETERS + IN + ctx: Pointer to vos Context or Sap Context based on MBSSID + + RETURN VALUE VHT channnel width + + SIDE EFFECTS +============================================================================*/ +v_U32_t wlan_sap_get_vht_ch_width(v_PVOID_t ctx) { + ptSapContext sap_ctx = VOS_GET_SAP_CB(ctx); + + if (!sap_ctx) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from ctx", __func__); + return 0; + } + + return sap_ctx->vht_channel_width; +} + +/*========================================================================== + FUNCTION wlan_sap_set_vht_ch_width + + DESCRIPTION Sets the SAP VHT channel width. + + DEPENDENCIES NA. + + PARAMETERS + IN + ctx: Pointer to vos Context or Sap Context based on MBSSID + vht_channel_width - VHT channel width + + RETURN VALUE NONE + + SIDE EFFECTS +============================================================================*/ +void wlan_sap_set_vht_ch_width(v_PVOID_t ctx, v_U32_t vht_channel_width) { + ptSapContext sap_ctx = VOS_GET_SAP_CB(ctx); + + if (!sap_ctx) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from ctx", __func__); + return; + } + + sap_ctx->vht_channel_width = vht_channel_width; +} + +/*========================================================================== + FUNCTION WLANSAP_SetScanAcsChannelParams + + DESCRIPTION + This api function is used to copy Scan and Channel parameters from sap + config to sap context. + + DEPENDENCIES + + PARAMETERS + + IN + pConfig : Pointer to the SAP config + sapContext : Pointer to the SAP Context. + pUsrContext: Parameter that will be passed + back in all the SAP callback events. + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetScanAcsChannelParams(tsap_Config_t *pConfig, + ptSapContext pSapCtx, + v_PVOID_t pUsrContext) +{ + tHalHandle hHal = NULL; + tANI_BOOLEAN restartNeeded; + + if (NULL == pConfig) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pConfig passed ", __func__); + return VOS_STATUS_E_FAULT; + } + + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pConfig passed ", __func__); + return VOS_STATUS_E_FAULT; + } + + /* Channel selection is auto or configured */ + pSapCtx->channel = pConfig->channel; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + pSapCtx->cc_switch_mode = pConfig->cc_switch_mode; +#endif + pSapCtx->scanBandPreference = pConfig->scanBandPreference; + pSapCtx->acsBandSwitchThreshold = pConfig->acsBandSwitchThreshold; + pSapCtx->pUsrContext = pUsrContext; + pSapCtx->enableOverLapCh = pConfig->enOverLapCh; + /* + * Set the BSSID to your "self MAC Addr" read + * the mac address from Configuation ITEM received + * from HDD + */ + pSapCtx->csrRoamProfile.BSSIDs.numOfBSSIDs = 1; + vos_mem_copy(pSapCtx->csrRoamProfile.BSSIDs.bssid, + pSapCtx->self_mac_addr, + sizeof( tCsrBssid )); + + /* + * Save a copy to SAP context + */ + vos_mem_copy(pSapCtx->csrRoamProfile.BSSIDs.bssid, + pConfig->self_macaddr.bytes, sizeof(v_MACADDR_t)); + vos_mem_copy(pSapCtx->self_mac_addr, + pConfig->self_macaddr.bytes, sizeof(v_MACADDR_t)); + + hHal = (tHalHandle)VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid MAC context from pvosGCtx", __func__); + } + else + { + //If concurrent session is running that is already associated + //then we just follow that sessions country info (whether + //present or not doesn't maater as we have to follow whatever + //STA session does) + if ((0 == sme_GetConcurrentOperationChannel(hHal)) && + pConfig->ieee80211d) + { + /* Setting the region/country information */ + sme_setRegInfo(hHal, pConfig->countryCode); + sme_ResetCountryCodeInformation(hHal, &restartNeeded); + } + } + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_StartBss + + DESCRIPTION + This api function provides SAP FSM event eWLAN_SAP_PHYSICAL_LINK_CREATE for + starting AP BSS + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pQctCommitConfig : Pointer to configuration structure passed down from HDD(HostApd for Android) + hdd_SapEventCallback: Callback function in HDD called by SAP to inform HDD about SAP results + pUsrContext : Parameter that will be passed back in all the SAP callback events. + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_StartBss +( + v_PVOID_t pCtx,//pwextCtx + tpWLAN_SAPEventCB pSapEventCallback, + tsap_Config_t *pConfig, + v_PVOID_t pUsrContext +) +{ + tWLAN_SAPEvent sapEvent; /* State machine event*/ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + tANI_BOOLEAN restartNeeded; + tHalHandle hHal; + tpAniSirGlobal pmac = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (VOS_STA_SAP_MODE == vos_get_conparam ()) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_StartBss: sapContext=%p", pSapCtx); + + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + pSapCtx->sapsMachine = eSAP_DISCONNECTED; + + /* Channel selection is auto or configured */ + pSapCtx->channel = pConfig->channel; + pSapCtx->vht_channel_width = pConfig->vht_channel_width; + pSapCtx->ch_width_orig = pConfig->ch_width_orig; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + pSapCtx->cc_switch_mode = pConfig->cc_switch_mode; +#endif + pSapCtx->scanBandPreference = pConfig->scanBandPreference; + pSapCtx->acsBandSwitchThreshold = pConfig->acsBandSwitchThreshold; + pSapCtx->pUsrContext = pUsrContext; + pSapCtx->enableOverLapCh = pConfig->enOverLapCh; + pSapCtx->acs_cfg = &pConfig->acs_cfg; + pSapCtx->secondary_ch = pConfig->sec_ch; + + //Set the BSSID to your "self MAC Addr" read the mac address from Configuation ITEM received from HDD + pSapCtx->csrRoamProfile.BSSIDs.numOfBSSIDs = 1; + + //Save a copy to SAP context + vos_mem_copy(pSapCtx->csrRoamProfile.BSSIDs.bssid, + pConfig->self_macaddr.bytes, sizeof(v_MACADDR_t)); + vos_mem_copy(pSapCtx->self_mac_addr, + pConfig->self_macaddr.bytes, sizeof(v_MACADDR_t)); + + //copy the configuration items to csrProfile + sapconvertToCsrProfile( pConfig, eCSR_BSS_TYPE_INFRA_AP, &pSapCtx->csrRoamProfile); + hHal = (tHalHandle)VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid MAC context from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + else + { + //If concurrent session is running that is already associated + //then we just follow that sessions country info (whether + //present or not doesn't maater as we have to follow whatever + //STA session does) + if ((0 == sme_GetConcurrentOperationChannel(hHal)) && + pConfig->ieee80211d) + { + /* Setting the region/country information */ + sme_setRegInfo(hHal, pConfig->countryCode); + sme_ResetCountryCodeInformation(hHal, &restartNeeded); + } + } + + pmac = PMAC_STRUCT( hHal ); + /* + * Copy the DFS Test Mode setting to pmac for + * access in lower layers + */ + pmac->sap.SapDfsInfo.disable_dfs_ch_switch = + pConfig->disableDFSChSwitch; + // Copy MAC filtering settings to sap context + pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; + vos_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sapSortMacList(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + vos_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sapSortMacList(pSapCtx->denyMacList, pSapCtx->nDenyMac); + /* Fill in the event structure for FSM */ + sapEvent.event = eSAP_HDD_START_INFRA_BSS; + sapEvent.params = 0;//pSapPhysLinkCreate + + /* Store the HDD callback in SAP context */ + pSapCtx->pfnSapEventCallback = pSapEventCallback; + + /* Handle event*/ + vosStatus = sapFsm(pSapCtx, &sapEvent); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "SoftAp role has not been enabled"); + } + + return vosStatus; +}// WLANSAP_StartBss + +/*========================================================================== + FUNCTION WLANSAP_SetMacACL + + DESCRIPTION + This api function provides SAP to set mac list entry in accept list as well + as deny list + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pQctCommitConfig : Pointer to configuration structure passed down from + HDD(HostApd for Android) + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMacACL +( + v_PVOID_t pCtx, //pwextCtx + tsap_Config_t *pConfig +) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_SetMacACL"); + + if (VOS_STA_SAP_MODE == vos_get_conparam ()) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + // Copy MAC filtering settings to sap context + pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; + + if (eSAP_DENY_UNLESS_ACCEPTED == pSapCtx->eSapMacAddrAclMode) + { + vos_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sapSortMacList(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + } + else if (eSAP_ACCEPT_UNLESS_DENIED == pSapCtx->eSapMacAddrAclMode) + { + vos_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sapSortMacList(pSapCtx->denyMacList, pSapCtx->nDenyMac); + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s : SoftAp role has not been enabled", __func__); + return VOS_STATUS_E_FAULT; + } + + return vosStatus; +}//WLANSAP_SetMacACL + +/*========================================================================== + FUNCTION WLANSAP_StopBss + + DESCRIPTION + This api function provides SAP FSM event eSAP_HDD_STOP_INFRA_BSS for + stopping AP BSS + + DEPENDENCIES + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to VOSS GC is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_StopBss +( + v_PVOID_t pCtx +) +{ + tWLAN_SAPEvent sapEvent; /* State machine event*/ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if ( NULL == pCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Global VOSS handle", __func__); + return VOS_STATUS_E_FAULT; + } + + pSapCtx = VOS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + /* Fill in the event structure for FSM */ + sapEvent.event = eSAP_HDD_STOP_INFRA_BSS; + sapEvent.params = 0; + + /* Handle event*/ + vosStatus = sapFsm(pSapCtx, &sapEvent); + + return vosStatus; +} + +/*========================================================================== + FUNCTION WLANSAP_GetAssocStations + + DESCRIPTION + This api function is used to probe the list of associated stations from various modules of CORE stack + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + modId : Module from whom list of associtated stations is supposed to be probed. If an invalid module is passed + then by default VOS_MODULE_ID_PE will be probed + IN/OUT + pAssocStas : Pointer to list of associated stations that are known to the module specified in mod parameter + + NOTE: The memory for this list will be allocated by the caller of this API + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_GetAssocStations +( + v_PVOID_t pCtx, + VOS_MODULE_ID modId, + tpSap_AssocMacAddr pAssocStas +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + sme_RoamGetAssociatedStas( VOS_GET_HAL_CB(pSapCtx->pvosGCtx), pSapCtx->sessionId, + modId, + pSapCtx->pUsrContext, + (v_PVOID_t *)pSapCtx->pfnSapEventCallback, + (v_U8_t *)pAssocStas ); + + return VOS_STATUS_SUCCESS; +} + + +/*========================================================================== + FUNCTION WLANSAP_RemoveWpsSessionOverlap + + DESCRIPTION + This api function provides for Ap App/HDD to remove an entry from session session overlap info. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pRemoveMac: pointer to v_MACADDR_t for session MAC address + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + VOS_STATUS_E_FAULT: Session is not dectected. The parameter is function not valid. + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_RemoveWpsSessionOverlap + +( + v_PVOID_t pCtx, + v_MACADDR_t pRemoveMac +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + sme_RoamGetWpsSessionOverlap( VOS_GET_HAL_CB(pSapCtx->pvosGCtx), pSapCtx->sessionId, + pSapCtx->pUsrContext, + (v_PVOID_t *)pSapCtx->pfnSapEventCallback, + pRemoveMac); + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_getWpsSessionOverlap + + DESCRIPTION + This api function provides for Ap App/HDD to get WPS session overlap info. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_getWpsSessionOverlap +( + v_PVOID_t pCtx +) +{ + v_MACADDR_t pRemoveMac = VOS_MAC_ADDR_ZERO_INITIALIZER; + + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + sme_RoamGetWpsSessionOverlap( VOS_GET_HAL_CB(pSapCtx->pvosGCtx), pSapCtx->sessionId, + pSapCtx->pUsrContext, + (v_PVOID_t *)pSapCtx->pfnSapEventCallback, + pRemoveMac); + + return VOS_STATUS_SUCCESS; +} + + +/* This routine will set the mode of operation for ACL dynamically*/ +VOS_STATUS +WLANSAP_SetMode +( + v_PVOID_t pCtx, + v_U32_t mode +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + pSapCtx->eSapMacAddrAclMode = (eSapMacAddrACL)mode; + return VOS_STATUS_SUCCESS; +} + +/* Get ACL Mode */ +VOS_STATUS +WLANSAP_GetACLMode +( + v_PVOID_t pCtx, + eSapMacAddrACL *mode +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + *mode = pSapCtx->eSapMacAddrAclMode; + return VOS_STATUS_SUCCESS; +} + +/* API to get ACL Accept List */ +VOS_STATUS +WLANSAP_GetACLAcceptList +( + v_PVOID_t pCtx, + v_MACADDR_t *pAcceptList, + v_U8_t *nAcceptList +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + memcpy((void *)pAcceptList, (void *)pSapCtx->acceptMacList, + (pSapCtx->nAcceptMac*sizeof(v_MACADDR_t))); + *nAcceptList = pSapCtx->nAcceptMac; + return VOS_STATUS_SUCCESS; +} + +/* API to get Deny List */ +VOS_STATUS +WLANSAP_GetACLDenyList +( + v_PVOID_t pCtx, + v_MACADDR_t *pDenyList, + v_U8_t *nDenyList +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + memcpy((void *)pDenyList, (void *)pSapCtx->denyMacList, + (pSapCtx->nDenyMac*sizeof(v_MACADDR_t))); + *nDenyList = pSapCtx->nDenyMac; + return VOS_STATUS_SUCCESS; +} + +/* This routine will clear all the entries in accept list as well as deny list */ + +VOS_STATUS +WLANSAP_ClearACL +( + v_PVOID_t pCtx +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + v_U8_t i; + + if (NULL == pSapCtx) + { + return VOS_STATUS_E_RESOURCES; + } + + if (pSapCtx->denyMacList != NULL) + { + for (i = 0; i < (pSapCtx->nDenyMac-1); i++) + { + vos_mem_zero((pSapCtx->denyMacList+i)->bytes, sizeof(v_MACADDR_t)); + + } + } + sapPrintACL(pSapCtx->denyMacList, pSapCtx->nDenyMac); + pSapCtx->nDenyMac = 0; + + if (pSapCtx->acceptMacList!=NULL) + { + for (i = 0; i < (pSapCtx->nAcceptMac-1); i++) + { + vos_mem_zero((pSapCtx->acceptMacList+i)->bytes, sizeof(v_MACADDR_t)); + + } + } + sapPrintACL(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + pSapCtx->nAcceptMac = 0; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS +WLANSAP_ModifyACL +( + v_PVOID_t pCtx, + v_U8_t *pPeerStaMac, + eSapACLType listType, + eSapACLCmdType cmd +) +{ + eSapBool staInWhiteList=eSAP_FALSE, staInBlackList=eSAP_FALSE; + v_U8_t staWLIndex, staBLIndex; + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP Context", __func__); + return VOS_STATUS_E_FAULT; + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW,"Modify ACL entered\n" + "Before modification of ACL\n" + "size of accept and deny lists %d %d", + pSapCtx->nAcceptMac, pSapCtx->nDenyMac); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"*** WHITE LIST ***"); + sapPrintACL(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"*** BLACK LIST ***"); + sapPrintACL(pSapCtx->denyMacList, pSapCtx->nDenyMac); + + /* the expectation is a mac addr will not be in both the lists at the same time. + It is the responsiblity of userspace to ensure this */ + staInWhiteList = sapSearchMacList(pSapCtx->acceptMacList, pSapCtx->nAcceptMac, pPeerStaMac, &staWLIndex); + staInBlackList = sapSearchMacList(pSapCtx->denyMacList, pSapCtx->nDenyMac, pPeerStaMac, &staBLIndex); + + if (staInWhiteList && staInBlackList) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Peer mac "MAC_ADDRESS_STR" found in white and black lists." + "Initial lists passed incorrect. Cannot execute this command.", + MAC_ADDR_ARRAY(pPeerStaMac)); + return VOS_STATUS_E_FAILURE; + + } + + switch(listType) + { + case eSAP_WHITE_LIST: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, "cmd %d", cmd); + if (cmd == ADD_STA_TO_ACL) + { + //error check + // if list is already at max, return failure + if (pSapCtx->nAcceptMac == MAX_ACL_MAC_ADDRESS) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "White list is already maxed out. Cannot accept "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPeerStaMac)); + return VOS_STATUS_E_FAILURE; + } + if (staInWhiteList) + { + //Do nothing if already present in white list. Just print a warning + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "MAC address already present in white list "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPeerStaMac)); + } else + { + if (staInBlackList) + { + //remove it from black list before adding to the white list + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "STA present in black list so first remove from it"); + sapRemoveMacFromACL(pSapCtx->denyMacList, &pSapCtx->nDenyMac, staBLIndex); + } + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "... Now add to the white list"); + sapAddMacToACL(pSapCtx->acceptMacList, &pSapCtx->nAcceptMac, pPeerStaMac); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, "size of accept and deny lists %d %d", + pSapCtx->nAcceptMac, pSapCtx->nDenyMac); + } + } + else if (cmd == DELETE_STA_FROM_ACL) + { + if (staInWhiteList) + { + struct tagCsrDelStaParams delStaParams; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "Delete from white list"); + sapRemoveMacFromACL(pSapCtx->acceptMacList, &pSapCtx->nAcceptMac, staWLIndex); + /* If a client is deleted from white list and the client is connected, send deauth*/ + WLANSAP_PopulateDelStaParams(pPeerStaMac, + eCsrForcedDeauthSta, + (SIR_MAC_MGMT_DEAUTH >> 4), + &delStaParams); + WLANSAP_DeauthSta(pCtx, &delStaParams); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, "size of accept and deny lists %d %d", + pSapCtx->nAcceptMac, pSapCtx->nDenyMac); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "MAC address to be deleted is not present in the white list "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPeerStaMac)); + return VOS_STATUS_E_FAILURE; + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "Invalid cmd type passed"); + return VOS_STATUS_E_FAILURE; + } + break; + + case eSAP_BLACK_LIST: + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW, + "cmd %d", cmd); + if (cmd == ADD_STA_TO_ACL) + { + //error check + // if list is already at max, return failure + if (pSapCtx->nDenyMac == MAX_ACL_MAC_ADDRESS) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Black list is already maxed out. Cannot accept "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPeerStaMac)); + return VOS_STATUS_E_FAILURE; + } + if (staInBlackList) + { + //Do nothing if already present in white list + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "MAC address already present in black list "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPeerStaMac)); + } else + { + struct tagCsrDelStaParams delStaParams; + if (staInWhiteList) + { + //remove it from white list before adding to the black list + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "Present in white list so first remove from it"); + sapRemoveMacFromACL(pSapCtx->acceptMacList, &pSapCtx->nAcceptMac, staWLIndex); + } + /* If we are adding a client to the black list; if its connected, send deauth */ + WLANSAP_PopulateDelStaParams(pPeerStaMac, + eCsrForcedDeauthSta, + (SIR_MAC_MGMT_DEAUTH >> 4), + &delStaParams); + WLANSAP_DeauthSta(pCtx, &delStaParams); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "... Now add to black list"); + sapAddMacToACL(pSapCtx->denyMacList, &pSapCtx->nDenyMac, pPeerStaMac); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW,"size of accept and deny lists %d %d", + pSapCtx->nAcceptMac, pSapCtx->nDenyMac); + } + } + else if (cmd == DELETE_STA_FROM_ACL) + { + if (staInBlackList) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "Delete from black list"); + sapRemoveMacFromACL(pSapCtx->denyMacList, &pSapCtx->nDenyMac, staBLIndex); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW,"no accept and deny mac %d %d", + pSapCtx->nAcceptMac, pSapCtx->nDenyMac); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN, + "MAC address to be deleted is not present in the black list "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPeerStaMac)); + return VOS_STATUS_E_FAILURE; + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "Invalid cmd type passed"); + return VOS_STATUS_E_FAILURE; + } + break; + + default: + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Invalid list type passed %d",listType); + return VOS_STATUS_E_FAILURE; + } + } + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_LOW,"After modification of ACL"); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"*** WHITE LIST ***"); + sapPrintACL(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,"*** BLACK LIST ***"); + sapPrintACL(pSapCtx->denyMacList, pSapCtx->nDenyMac); + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_DisassocSta + + DESCRIPTION + This api function provides for Ap App/HDD initiated disassociation of station + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pPeerStaMac : Mac address of the station to disassociate + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DisassocSta +( + v_PVOID_t pCtx, + struct tagCsrDelStaParams *pDelStaParams +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + sme_RoamDisconnectSta(VOS_GET_HAL_CB(pSapCtx->pvosGCtx), pSapCtx->sessionId, + pDelStaParams); + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_DeauthSta + + DESCRIPTION + This api function provides for Ap App/HDD initiated deauthentication of station + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pDelStaParams : Pointer to parameters of the station to + deauthenticate + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DeauthSta +( + v_PVOID_t pCtx, + struct tagCsrDelStaParams *pDelStaParams +) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + VOS_STATUS vosStatus = VOS_STATUS_E_FAULT; + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return vosStatus; + } + + halStatus = sme_RoamDeauthSta(VOS_GET_HAL_CB(pSapCtx->pvosGCtx), + pSapCtx->sessionId, pDelStaParams); + + if (halStatus == eHAL_STATUS_SUCCESS) + { + vosStatus = VOS_STATUS_SUCCESS; + } + return vosStatus; +} + +/*========================================================================== + FUNCTION WLANSAP_SetChannelChangeWithCsa + + DESCRIPTION + This api function does a channel change to the target channel specified + through an iwpriv. CSA IE is included in the beacons before doing a + channel change. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx : Pointer to vos global context structure + targetChannel : New target channel to change to. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetChannelChangeWithCsa(v_PVOID_t pvosGCtx, v_U32_t targetChannel) +{ + + ptSapContext sapContext = NULL; + tWLAN_SAPEvent sapEvent; + tpAniSirGlobal pMac = NULL; + v_PVOID_t hHal = NULL; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + bool valid; +#endif + tSmeConfigParams sme_config; + + sapContext = VOS_GET_SAP_CB( pvosGCtx ); + if (NULL == sapContext) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT( hHal ); + + /* + * Now, validate if the passed channel is valid in the + * current regulatory domain. + */ + if ( sapContext->channel != targetChannel && + ((vos_nv_getChannelEnabledState(targetChannel) == NV_CHANNEL_ENABLE) + || + (vos_nv_getChannelEnabledState(targetChannel) == NV_CHANNEL_DFS && + !vos_concurrent_open_sessions_running())) ) + { +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + /* + * validate target channel switch w.r.t various concurrency rules set. + */ + valid = sme_validate_sap_channel_switch(VOS_GET_HAL_CB(sapContext->pvosGCtx), + targetChannel, sapContext->csrRoamProfile.phyMode, + sapContext->cc_switch_mode, sapContext->sessionId); + if (!valid) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Channel switch to %u is not allowed due to concurrent channel interference"), + targetChannel); + return VOS_STATUS_E_FAULT; + } +#endif + /* + * Post a CSA IE request to SAP state machine with + * target channel information and also CSA IE required + * flag set in sapContext only, if SAP is in eSAP_STARTED + * state. + */ + if (eSAP_STARTED == sapContext->sapsMachine) + { + /* + * currently OBSS scan is done in hostapd, so to avoid + * SAP coming up in HT40 on channel switch we are + * disabling channel bonding in 2.4ghz. + */ + if (targetChannel <= RF_CHAN_14) + { + sme_GetConfigParam(pMac, &sme_config); + sme_config.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + sme_UpdateConfig(pMac, &sme_config); + } + + /* + * Copy the requested target channel + * to sap context. + */ + pMac->sap.SapDfsInfo.target_channel = targetChannel; + pMac->sap.SapDfsInfo.new_chanWidth = + sapContext->ch_width_orig; + + /* + * Set the CSA IE required flag. + */ + pMac->sap.SapDfsInfo.csaIERequired = VOS_TRUE; + + /* + * Set the radar found status to allow the channel + * change to happen same as in the case of a radar + * detection. Since, this will allow SAP to be in + * correct state and also resume the netif queues + * that were suspended in HDD before the channel + * request was issued. + */ + pMac->sap.SapDfsInfo.sap_radar_found_status = VOS_TRUE; + pMac->sap.SapDfsInfo.cac_state = eSAP_DFS_DO_NOT_SKIP_CAC; + sap_CacResetNotify(hHal); + + /* + * Post the eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START + * to SAP state machine to process the channel + * request with CSA IE set in the beacons. + */ + sapEvent.event = eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START; + sapEvent.params = 0; + sapEvent.u1 = 0; + sapEvent.u2 = 0; + + sapFsm(sapContext, &sapEvent); + + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to request Channel Change, since" + "SAP is not in eSAP_STARTED state", __func__); + return VOS_STATUS_E_FAULT; + } + + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Channel = %d is not valid in the current" + "regulatory domain", + __func__, targetChannel); + + return VOS_STATUS_E_FAULT; + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Posted eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START" + "successfully to sapFsm for Channel = %d", + __func__, targetChannel); + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_SetCounterMeasure + + DESCRIPTION + This api function is used to disassociate all the stations and prevent + association for any other station.Whenever Authenticator receives 2 mic failures + within 60 seconds, Authenticator will enable counter measure at SAP Layer. + Authenticator will start the 60 seconds timer. Core stack will not allow any + STA to associate till HDD disables counter meassure. Core stack shall kick out all the + STA which are currently associated and DIASSOC Event will be propogated to HDD for + each STA to clean up the HDD STA table.Once the 60 seconds timer expires, Authenticator + will disable the counter meassure at core stack. Now core stack can allow STAs to associate. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + bEnable: If TRUE than all stations will be disassociated and no more + will be allowed to associate. If FALSE than CORE + will come out of this state. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetCounterMeasure +( + v_PVOID_t pCtx, + v_BOOL_t bEnable +) +{ + ptSapContext pSapCtx = VOS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + sme_RoamTKIPCounterMeasures(VOS_GET_HAL_CB(pSapCtx->pvosGCtx), pSapCtx->sessionId, bEnable); + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + + FUNCTION WLANSAP_SetKeysSta + + DESCRIPTION + This api function provides for Ap App/HDD to set key for a station. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pSetKeyInfo : tCsrRoamSetKey structure for the station + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetKeySta +( + v_PVOID_t pCtx, + tCsrRoamSetKey *pSetKeyInfo +) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_U32_t roamId=0xFF; + + if (VOS_STA_SAP_MODE == vos_get_conparam ( )) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + halStatus = sme_RoamSetKey(hHal, pSapCtx->sessionId, pSetKeyInfo, &roamId); + + if (halStatus == eHAL_STATUS_SUCCESS) + { + vosStatus = VOS_STATUS_SUCCESS; + } else + { + vosStatus = VOS_STATUS_E_FAULT; + } + } + else + vosStatus = VOS_STATUS_E_FAULT; + + return vosStatus; +} + +/*========================================================================== + FUNCTION WLANSAP_DelKeySta + + DESCRIPTION + This api function provides for Ap App/HDD to delete key for a station. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pSetKeyInfo : tCsrRoamRemoveKey structure for the station + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DelKeySta +( + v_PVOID_t pCtx, + tCsrRoamRemoveKey *pRemoveKeyInfo +) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_U32_t roamId=0xFF; + tCsrRoamRemoveKey RemoveKeyInfo; + + if (VOS_STA_SAP_MODE == vos_get_conparam ( )) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + vos_mem_zero(&RemoveKeyInfo, sizeof(RemoveKeyInfo)); + RemoveKeyInfo.encType = pRemoveKeyInfo->encType; + vos_mem_copy(RemoveKeyInfo.peerMac, pRemoveKeyInfo->peerMac, VOS_MAC_ADDR_SIZE); + RemoveKeyInfo.keyId = pRemoveKeyInfo->keyId; + + halStatus = sme_RoamRemoveKey(hHal, pSapCtx->sessionId, &RemoveKeyInfo, &roamId); + + if (HAL_STATUS_SUCCESS(halStatus)) + { + vosStatus = VOS_STATUS_SUCCESS; + } + else + { + vosStatus = VOS_STATUS_E_FAULT; + } + } + else + vosStatus = VOS_STATUS_E_FAULT; + + return vosStatus; +} + +VOS_STATUS +WLANSap_getstationIE_information +( + v_PVOID_t pCtx, + v_U32_t *pLen, + v_U8_t *pBuf +) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + ptSapContext pSapCtx = NULL; + v_U32_t len = 0; + + if (VOS_STA_SAP_MODE == vos_get_conparam ( )){ + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + if (pLen) + { + len = *pLen; + *pLen = pSapCtx->nStaWPARSnReqIeLength; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: WPAIE len : %x", __func__, *pLen); + if(pBuf) + { + if(len >= pSapCtx->nStaWPARSnReqIeLength) + { + vos_mem_copy( pBuf, pSapCtx->pStaWpaRsnReqIE, pSapCtx->nStaWPARSnReqIeLength); + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: WPAIE: %02x:%02x:%02x:%02x:%02x:%02x", + __func__, + pBuf[0], pBuf[1], pBuf[2], + pBuf[3], pBuf[4], pBuf[5]); + vosStatus = VOS_STATUS_SUCCESS; + } + } + } + } + + if( VOS_STATUS_E_FAILURE == vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Error unable to populate the RSNWPAIE", + __func__); + } + + return vosStatus; + +} + +/*========================================================================== + FUNCTION WLANSAP_Set_WpsIe + + DESCRIPTION + This api function provides for Ap App/HDD to set WPS IE. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pWPSIE : tSap_WPSIE structure that include WPS IEs + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Set_WpsIe +( + v_PVOID_t pCtx, + tSap_WPSIE *pSap_WPSIe +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s, %d", __func__, __LINE__); + + if(VOS_STA_SAP_MODE == vos_get_conparam ( )) { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if ( NULL == hHal ){ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( sap_AcquireGlobalLock( pSapCtx ) == VOS_STATUS_SUCCESS ) + { + if (pSap_WPSIe->sapWPSIECode == eSAP_WPS_BEACON_IE) + { + vos_mem_copy(&pSapCtx->APWPSIEs.SirWPSBeaconIE, &pSap_WPSIe->sapwpsie.sapWPSBeaconIE, sizeof(tSap_WPSBeaconIE)); + } + else if (pSap_WPSIe->sapWPSIECode == eSAP_WPS_PROBE_RSP_IE) + { + vos_mem_copy(&pSapCtx->APWPSIEs.SirWPSProbeRspIE, &pSap_WPSIe->sapwpsie.sapWPSProbeRspIE, sizeof(tSap_WPSProbeRspIE)); + } + else + { + sap_ReleaseGlobalLock( pSapCtx ); + return VOS_STATUS_E_FAULT; + } + sap_ReleaseGlobalLock( pSapCtx ); + return VOS_STATUS_SUCCESS; + } + else + return VOS_STATUS_E_FAULT; + } + else + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + FUNCTION WLANSAP_Update_WpsIe + + DESCRIPTION + This api function provides for Ap App/HDD to update WPS IEs. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Update_WpsIe +( + v_PVOID_t pCtx +) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAULT; + ptSapContext pSapCtx = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s, %d", __func__, __LINE__); + + if(VOS_STA_SAP_MODE == vos_get_conparam ( )){ + pSapCtx = VOS_GET_SAP_CB(pCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if ( NULL == hHal ){ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_RoamUpdateAPWPSIE( hHal, pSapCtx->sessionId, &pSapCtx->APWPSIEs); + + if(halStatus == eHAL_STATUS_SUCCESS) { + vosStatus = VOS_STATUS_SUCCESS; + } else + { + vosStatus = VOS_STATUS_E_FAULT; + } + + } + + return vosStatus; +} + +/*========================================================================== + FUNCTION WLANSAP_Get_WPS_State + + DESCRIPTION + This api function provides for Ap App/HDD to check if WPS session in process. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + OUT + pbWPSState: Pointer to variable to indicate if it is in WPS Registration state + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Get_WPS_State +( + v_PVOID_t pCtx, + v_BOOL_t *bWPSState +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s, %d", __func__, __LINE__); + + if(VOS_STA_SAP_MODE == vos_get_conparam ( )){ + + pSapCtx = VOS_GET_SAP_CB(pCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if ( NULL == hHal ){ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( sap_AcquireGlobalLock(pSapCtx ) == VOS_STATUS_SUCCESS ) + { + if(pSapCtx->APWPSIEs.SirWPSProbeRspIE.FieldPresent & SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT) + *bWPSState = eANI_BOOLEAN_TRUE; + else + *bWPSState = eANI_BOOLEAN_FALSE; + + sap_ReleaseGlobalLock( pSapCtx ); + + return VOS_STATUS_SUCCESS; + } + else + return VOS_STATUS_E_FAULT; + } + else + return VOS_STATUS_E_FAULT; + +} + +VOS_STATUS +sap_AcquireGlobalLock +( + ptSapContext pSapCtx +) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAULT; + + if( VOS_IS_STATUS_SUCCESS( vos_lock_acquire( &pSapCtx->SapGlobalLock) ) ) + { + vosStatus = VOS_STATUS_SUCCESS; + } + + return (vosStatus); +} + +VOS_STATUS +sap_ReleaseGlobalLock +( + ptSapContext pSapCtx +) +{ + VOS_STATUS vosStatus = VOS_STATUS_E_FAULT; + + if( VOS_IS_STATUS_SUCCESS( vos_lock_release( &pSapCtx->SapGlobalLock) ) ) + { + vosStatus = VOS_STATUS_SUCCESS; + } + + return (vosStatus); +} + +/*========================================================================== + FUNCTION WLANSAP_Set_WPARSNIes + + DESCRIPTION + This api function provides for Ap App/HDD to set AP WPA and RSN IE in its beacon and probe response. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pWPARSNIEs : buffer to the WPA/RSN IEs + WPARSNIEsLen: length of WPA/RSN IEs + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_Set_WPARSNIes +( + v_PVOID_t pCtx, + v_U8_t *pWPARSNIEs, + v_U32_t WPARSNIEsLen +) +{ + ptSapContext pSapCtx = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + + if(VOS_STA_SAP_MODE == vos_get_conparam ( )){ + pSapCtx = VOS_GET_SAP_CB(pCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if ( NULL == hHal ){ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + pSapCtx->APWPARSNIEs.length = (tANI_U16)WPARSNIEsLen; + vos_mem_copy(pSapCtx->APWPARSNIEs.rsnIEdata, pWPARSNIEs, WPARSNIEsLen); + + halStatus = sme_RoamUpdateAPWPARSNIEs( hHal, pSapCtx->sessionId, &pSapCtx->APWPARSNIEs); + + if(halStatus == eHAL_STATUS_SUCCESS) { + return VOS_STATUS_SUCCESS; + } else + { + return VOS_STATUS_E_FAULT; + } + } + + return VOS_STATUS_E_FAULT; +} + +VOS_STATUS WLANSAP_GetStatistics +( + v_PVOID_t pCtx, + tSap_SoftapStats *statBuf, + v_BOOL_t bReset +) +{ + if (NULL == pCtx) + { + return VOS_STATUS_E_FAULT; + } + + return (WLANTL_GetSoftAPStatistics(pCtx, statBuf, bReset)); +} + +/*========================================================================== + + FUNCTION WLANSAP_SendAction + + DESCRIPTION + This api function provides to send action frame sent by upper layer. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + pBuf: Pointer of the action frame to be transmitted + len: Length of the action frame + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_SendAction +( + v_PVOID_t pCtx, + const tANI_U8 *pBuf, + tANI_U32 len, tANI_U16 wait +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if( VOS_STA_SAP_MODE == vos_get_conparam ( ) ) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if( ( NULL == hHal ) || ( eSAP_TRUE != pSapCtx->isSapSessionOpen ) ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen ); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_sendAction( hHal, pSapCtx->sessionId, pBuf, len, 0 , 0); + + if ( eHAL_STATUS_SUCCESS == halStatus ) + { + return VOS_STATUS_SUCCESS; + } + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Failed to Send Action Frame"); + + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION WLANSAP_RemainOnChannel + + DESCRIPTION + This api function provides to set Remain On channel on specified channel + for specified duration. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + channel: Channel on which driver has to listen + duration: Duration for which driver has to listen on specified channel + callback: Callback function to be called once Listen is done. + pContext: Context needs to be called in callback function. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_RemainOnChannel +( + v_PVOID_t pCtx, + tANI_U8 channel, + tANI_U32 duration, + remainOnChanCallback callback, + void *pContext +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if( VOS_STA_SAP_MODE == vos_get_conparam ( ) ) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if( ( NULL == hHal ) || ( eSAP_TRUE != pSapCtx->isSapSessionOpen ) ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen ); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_RemainOnChannel( hHal, pSapCtx->sessionId, + channel, duration, callback, pContext, TRUE ); + + if( eHAL_STATUS_SUCCESS == halStatus ) + { + return VOS_STATUS_SUCCESS; + } + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Failed to Set Remain on Channel"); + + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION WLANSAP_CancelRemainOnChannel + + DESCRIPTION + This api cancel previous remain on channel request. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_CancelRemainOnChannel +( + v_PVOID_t pCtx +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if( VOS_STA_SAP_MODE == vos_get_conparam ( ) ) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if( ( NULL == hHal ) || ( eSAP_TRUE != pSapCtx->isSapSessionOpen ) ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen ); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_CancelRemainOnChannel( hHal, pSapCtx->sessionId ); + + if( eHAL_STATUS_SUCCESS == halStatus ) + { + return VOS_STATUS_SUCCESS; + } + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Failed to Cancel Remain on Channel"); + + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION WLANSAP_RegisterMgmtFrame + + DESCRIPTION + HDD use this API to register specified type of frame with CORE stack. + On receiving such kind of frame CORE stack should pass this frame to HDD + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + frameType: frameType that needs to be registered with PE. + matchData: Data pointer which should be matched after frame type is matched. + matchLen: Length of the matchData + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_RegisterMgmtFrame +( + v_PVOID_t pCtx, + tANI_U16 frameType, + tANI_U8* matchData, + tANI_U16 matchLen +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if( VOS_STA_SAP_MODE == vos_get_conparam ( ) ) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if( ( NULL == hHal ) || ( eSAP_TRUE != pSapCtx->isSapSessionOpen ) ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen ); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_RegisterMgmtFrame(hHal, pSapCtx->sessionId, + frameType, matchData, matchLen); + + if( eHAL_STATUS_SUCCESS == halStatus ) + { + return VOS_STATUS_SUCCESS; + } + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Failed to Register MGMT frame"); + + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION WLANSAP_DeRegisterMgmtFrame + + DESCRIPTION + This API is used to deregister previously registered frame. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pCtx : Pointer to the global vos context; a handle to SAP's + control block can be extracted from its context + When MBSSID feature is enabled, SAP context is directly + passed to SAP APIs + frameType: frameType that needs to be De-registered with PE. + matchData: Data pointer which should be matched after frame type is matched. + matchLen: Length of the matchData + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_DeRegisterMgmtFrame +( + v_PVOID_t pCtx, + tANI_U16 frameType, + tANI_U8* matchData, + tANI_U16 matchLen +) +{ + ptSapContext pSapCtx = NULL; + v_PVOID_t hHal = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + + if( VOS_STA_SAP_MODE == vos_get_conparam ( ) ) + { + pSapCtx = VOS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(pSapCtx->pvosGCtx); + if( ( NULL == hHal ) || ( eSAP_TRUE != pSapCtx->isSapSessionOpen ) ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen ); + return VOS_STATUS_E_FAULT; + } + + halStatus = sme_DeregisterMgmtFrame( hHal, pSapCtx->sessionId, + frameType, matchData, matchLen ); + + if( eHAL_STATUS_SUCCESS == halStatus ) + { + return VOS_STATUS_SUCCESS; + } + } + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Failed to Deregister MGMT frame"); + + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + FUNCTION WLANSAP_ChannelChangeRequest + + DESCRIPTION + This API is used to send an Indication to SME/PE to change the + current operating channel to a different target channel. + + The Channel change will be issued by SAP under the following + scenarios. + 1. A radar indication is received during SAP CAC WAIT STATE and + channel change is required. + 2. A radar indication is received during SAP STARTED STATE and + channel change is required. + DEPENDENCIES + NA. + + PARAMETERS + IN + pSapCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_ChannelChangeRequest(v_PVOID_t pSapCtx, uint8_t target_channel) +{ + ptSapContext sapContext = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + tpAniSirGlobal pMac = NULL; + eCsrPhyMode phyMode; + tANI_U32 cbMode; + uint16_t vhtChannelWidth; + sapContext = (ptSapContext)pSapCtx; + + if ( NULL == sapContext ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT( hHal ); + phyMode = sapContext->csrRoamProfile.phyMode; + sapContext->csrRoamProfile.ChannelInfo.ChannelList[0] = target_channel; + /* + * We are getting channel bonding mode from sapDfsInfor structure + * because we've implemented channel width fallback mechanism for DFS + * which will result in width of channel changing dynamically. + */ + cbMode = pMac->sap.SapDfsInfo.new_cbMode; + vhtChannelWidth = pMac->sap.SapDfsInfo.new_chanWidth; + sme_SelectCBMode(hHal, phyMode, target_channel, 0, &vhtChannelWidth, + pMac->sap.SapDfsInfo.new_chanWidth); + sapContext->csrRoamProfile.vht_channel_width = vhtChannelWidth; + sapContext->vht_channel_width = vhtChannelWidth; + /* Update the channel as this will be used to + * send event to supplicant + */ + sapContext->channel = target_channel; + halStatus = sme_RoamChannelChangeReq(hHal, sapContext->bssid, + cbMode, &sapContext->csrRoamProfile); + + if (halStatus == eHAL_STATUS_SUCCESS) + { + sapSignalHDDevent(sapContext, NULL, eSAP_CHANNEL_CHANGE_EVENT, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION WLANSAP_StartBeaconReq + DESCRIPTION + This API is used to send an Indication to SME/PE to start + beaconing on the current operating channel. + + Brief:When SAP is started on DFS channel and when ADD BSS RESP is received + LIM temporarily holds off Beaconing for SAP to do CAC WAIT. When + CAC WAIT is done SAP resumes the Beacon Tx by sending a start beacon + request to LIM. + + DEPENDENCIES + NA. + +PARAMETERS + +IN + pSapCtx: Pointer to vos global context structure + +RETURN VALUE + The VOS_STATUS code associated with performing the operation + +VOS_STATUS_SUCCESS: Success + +SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_StartBeaconReq(v_PVOID_t pSapCtx) +{ + ptSapContext sapContext = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + tANI_U8 dfsCacWaitStatus = 0; + tpAniSirGlobal pMac = NULL; + sapContext = (ptSapContext)pSapCtx; + + if ( NULL == sapContext ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT( hHal ); + + /* No Radar was found during CAC WAIT, So start Beaconing */ + if (pMac->sap.SapDfsInfo.sap_radar_found_status == VOS_FALSE) + { + /* CAC Wait done without any Radar Detection */ + dfsCacWaitStatus = VOS_TRUE; + halStatus = sme_RoamStartBeaconReq( hHal, + sapContext->bssid, dfsCacWaitStatus); + if (halStatus == eHAL_STATUS_SUCCESS) + { + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_E_FAULT; +} + + +/*========================================================================== + FUNCTION WLANSAP_DfsSendCSAIeRequest + + DESCRIPTION + This API is used to send channel switch announcement request to PE + DEPENDENCIES + NA. + + PARAMETERS + IN + pSapCtx: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_DfsSendCSAIeRequest(v_PVOID_t pSapCtx) +{ + ptSapContext sapContext = NULL; + eHalStatus halStatus = eHAL_STATUS_FAILURE; + v_PVOID_t hHal = NULL; + tpAniSirGlobal pMac = NULL; + uint16_t cbmode, vht_ch_width; + uint8_t ch_bandwidth; + + sapContext = (ptSapContext)pSapCtx; + + if ( NULL == sapContext ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + pMac = PMAC_STRUCT( hHal ); + + vht_ch_width = pMac->sap.SapDfsInfo.new_chanWidth; + cbmode = sme_SelectCBMode(hHal, + sapContext->csrRoamProfile.phyMode, + pMac->sap.SapDfsInfo.target_channel, 0, + &vht_ch_width, sapContext->ch_width_orig); + + if (pMac->sap.SapDfsInfo.target_channel <= 14 || + vht_ch_width == eHT_CHANNEL_WIDTH_40MHZ || + vht_ch_width == eHT_CHANNEL_WIDTH_20MHZ) + { + switch (cbmode) + { + case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY: + ch_bandwidth = BW40_HIGH_PRIMARY; + break; + case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY: + ch_bandwidth = BW40_LOW_PRIMARY; + break; + case eCSR_INI_SINGLE_CHANNEL_CENTERED: + default: + ch_bandwidth = BW20; + break; + } + } + else + ch_bandwidth = BW80; + + halStatus = sme_RoamCsaIeRequest(hHal, + sapContext->bssid, + pMac->sap.SapDfsInfo.target_channel, + pMac->sap.SapDfsInfo.csaIERequired, + ch_bandwidth); + + if (halStatus == eHAL_STATUS_SUCCESS) + { + return VOS_STATUS_SUCCESS; + } + + return VOS_STATUS_E_FAULT; +} + +/*========================================================================== + FUNCTION WLANSAP_Get_Dfs_Ignore_CAC + + DESCRIPTION + This API is used to get the value of ignore_cac value + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + pIgnore_cac : pointer to ignore_cac variable + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_Get_Dfs_Ignore_CAC(tHalHandle hHal, v_U8_t *pIgnore_cac) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL != hHal) + { + pMac = PMAC_STRUCT( hHal ); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + *pIgnore_cac = pMac->sap.SapDfsInfo.ignore_cac; + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_Set_Dfs_Ignore_CAC + + DESCRIPTION + This API is used to Set the value of ignore_cac value + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + ignore_cac : value to set for ignore_cac variable in DFS global structure. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_Set_Dfs_Ignore_CAC(tHalHandle hHal, v_U8_t ignore_cac) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL != hHal) + { + pMac = PMAC_STRUCT( hHal ); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + pMac->sap.SapDfsInfo.ignore_cac = (ignore_cac >= VOS_TRUE)? + VOS_TRUE : VOS_FALSE; + return VOS_STATUS_SUCCESS; +} + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * wlan_sap_set_channel_avoidance() - sets sap mcc channel avoidance ini param + * @hal: hal handle + * @sap_channel_avoidance: ini parameter value + * + * sets sap mcc channel avoidance ini param, to be called in sap_start + * + * Return: success of failure of operation + */ +VOS_STATUS +wlan_sap_set_channel_avoidance(tHalHandle hal, bool sap_channel_avoidance) +{ + tpAniSirGlobal mac_ctx = NULL; + + if (NULL != hal) + mac_ctx = PMAC_STRUCT(hal); + + if (mac_ctx == NULL || hal == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_ERROR, + FL("hal or mac_ctx pointer NULL")); + return VOS_STATUS_E_FAULT; + } + mac_ctx->sap.sap_channel_avoidance = sap_channel_avoidance; + return VOS_STATUS_SUCCESS; +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/*========================================================================== + FUNCTION WLANSAP_set_Dfs_Restrict_JapanW53 + + DESCRIPTION + This API is used to enable or disable Japan W53 Band + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + disable_Dfs_JapanW3 :Indicates if Japan W53 is disabled when set to 1 + Indicates if Japan W53 is enabled when set to 0 + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_set_Dfs_Restrict_JapanW53(tHalHandle hHal, v_U8_t disable_Dfs_W53) +{ + tpAniSirGlobal pMac = NULL; + VOS_STATUS status; + uint8_t dfs_region; + + if (NULL != hHal) + { + pMac = PMAC_STRUCT( hHal ); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + vos_nv_get_dfs_region(&dfs_region); + + /* + * Set the JAPAN W53 restriction only if the current + * regulatory domain is JAPAN. + */ + if (DFS_MKK4_DOMAIN == dfs_region) + { + pMac->sap.SapDfsInfo.is_dfs_w53_disabled = disable_Dfs_W53; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: SET DFS JAPAN W53 DISABLED = %d"), + pMac->sap.SapDfsInfo.is_dfs_w53_disabled); + + status = VOS_STATUS_SUCCESS; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Regdomain not japan, set disable JP W53 not valid")); + + status = VOS_STATUS_E_FAULT; + } + + return status; +} + +/*========================================================================== + FUNCTION WLANSAP_set_Dfs_Preferred_Channel_location + + DESCRIPTION + This API is used to set sap preferred channels location + to resetrict the DFS random channel selection algorithm + either Indoor/Outdoor channels only. + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + dfs_Preferred_Channels_location : + 0 - Indicates No preferred channel location restrictions + 1 - Indicates SAP Indoor Channels operation only. + 2 - Indicates SAP Outdoor Channels operation only. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_set_Dfs_Preferred_Channel_location(tHalHandle hHal, + v_U8_t dfs_Preferred_Channels_location) +{ + tpAniSirGlobal pMac = NULL; + VOS_STATUS status; + uint8_t dfs_region; + + if (NULL != hHal) + { + pMac = PMAC_STRUCT( hHal ); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + vos_nv_get_dfs_region(&dfs_region); + + /* + * The Indoor/Outdoor only random channel selection + * restriction is currently enforeced only for + * JAPAN regulatory domain. + */ + if (DFS_MKK4_DOMAIN == dfs_region) + { + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location = + dfs_Preferred_Channels_location; + VOS_TRACE(VOS_MODULE_ID_SAP, + VOS_TRACE_LEVEL_INFO_LOW, + FL("sapdfs:Set Preferred Operating Channel location=%d"), + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location); + + status = VOS_STATUS_SUCCESS; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("sapdfs:NOT JAPAN REG, Invalid Set preferred chans location")); + + status = VOS_STATUS_E_FAULT; + } + + return status; +} + +/*========================================================================== + FUNCTION WLANSAP_Set_Dfs_Target_Chnl + + DESCRIPTION + This API is used to set next target chnl as provided channel. + you can provide any valid channel to this API. + + DEPENDENCIES + NA. + + PARAMETERS + IN + hHal : HAL pointer + target_channel : target channel to be set + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS WLANSAP_Set_Dfs_Target_Chnl(tHalHandle hHal, v_U8_t target_channel) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL != hHal) + { + pMac = PMAC_STRUCT( hHal ); + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + if (target_channel > 0) + { + pMac->sap.SapDfsInfo.user_provided_target_channel = target_channel; + } + else + { + pMac->sap.SapDfsInfo.user_provided_target_channel = 0; + } + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS +WLANSAP_UpdateSapConfigAddIE(tsap_Config_t *pConfig, + const tANI_U8 *pAdditionIEBuffer, + tANI_U16 additionIELength, + eUpdateIEsType updateType) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tANI_U8 bufferValid = VOS_FALSE; + tANI_U16 bufferLength = 0; + tANI_U8 *pBuffer = NULL; + + if (NULL == pConfig) + { + return VOS_STATUS_E_FAULT; + } + + if ( (pAdditionIEBuffer != NULL) && (additionIELength != 0) ) + { + /* initialize the buffer pointer so that pe can copy*/ + if (additionIELength > 0) + { + bufferLength = additionIELength; + pBuffer = vos_mem_malloc(bufferLength); + if (NULL == pBuffer) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Could not allocate the buffer ")); + return VOS_STATUS_E_NOMEM; + } + vos_mem_copy(pBuffer, pAdditionIEBuffer, bufferLength); + bufferValid = VOS_TRUE; + } + } + + switch(updateType) + { + case eUPDATE_IE_PROBE_BCN: + if (bufferValid) + { + pConfig->probeRespBcnIEsLen = bufferLength; + pConfig->pProbeRespBcnIEsBuffer = pBuffer; + } + else + { + vos_mem_free(pConfig->pProbeRespBcnIEsBuffer); + pConfig->probeRespBcnIEsLen = 0; + pConfig->pProbeRespBcnIEsBuffer = NULL; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("No Probe Resp beacone IE received in set beacon")); + } + break; + case eUPDATE_IE_PROBE_RESP: + if (bufferValid) + { + pConfig->probeRespIEsBufferLen= bufferLength; + pConfig->pProbeRespIEsBuffer = pBuffer; + } + else + { + vos_mem_free(pConfig->pProbeRespIEsBuffer); + pConfig->probeRespIEsBufferLen = 0; + pConfig->pProbeRespIEsBuffer = NULL; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("No Probe Response IE received in set beacon")); + } + break; + case eUPDATE_IE_ASSOC_RESP: + if (bufferValid) + { + pConfig->assocRespIEsLen = bufferLength; + pConfig->pAssocRespIEsBuffer = pBuffer; + } + else + { + vos_mem_free(pConfig->pAssocRespIEsBuffer); + pConfig->assocRespIEsLen = 0; + pConfig->pAssocRespIEsBuffer = NULL; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("No Assoc Response IE received in set beacon")); + } + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("No matching buffer type %d"), updateType); + if (pBuffer != NULL) + vos_mem_free(pBuffer); + break; + } + + return (status); +} + + +VOS_STATUS +WLANSAP_ResetSapConfigAddIE(tsap_Config_t *pConfig, + eUpdateIEsType updateType) +{ + if (NULL == pConfig) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Config pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + switch (updateType) + { + case eUPDATE_IE_ALL: /*only used to reset*/ + case eUPDATE_IE_PROBE_RESP: + vos_mem_free( pConfig->pProbeRespIEsBuffer); + pConfig->probeRespIEsBufferLen = 0; + pConfig->pProbeRespIEsBuffer = NULL; + if(eUPDATE_IE_ALL != updateType) break; + + case eUPDATE_IE_ASSOC_RESP: + vos_mem_free( pConfig->pAssocRespIEsBuffer); + pConfig->assocRespIEsLen = 0; + pConfig->pAssocRespIEsBuffer = NULL; + if(eUPDATE_IE_ALL != updateType) break; + + case eUPDATE_IE_PROBE_BCN: + vos_mem_free(pConfig->pProbeRespBcnIEsBuffer ); + pConfig->probeRespBcnIEsLen = 0; + pConfig->pProbeRespBcnIEsBuffer = NULL; + if(eUPDATE_IE_ALL != updateType) break; + + default: + if(eUPDATE_IE_ALL != updateType) + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Invalid buffer type %d"), updateType); + break; + } + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== +FUNCTION WLANSAP_extend_to_acs_range + +DESCRIPTION Function extends give channel range to consider ACS chan bonding + +DEPENDENCIES PARAMETERS + +IN /OUT +*startChannelNum : ACS extend start ch +*endChannelNum : ACS extended End ch +*bandStartChannel: Band start ch +*bandEndChannel : Band end ch + +RETURN VALUE NONE + +SIDE EFFECTS +============================================================================*/ +v_VOID_t WLANSAP_extend_to_acs_range(v_U8_t *startChannelNum, + v_U8_t *endChannelNum, + v_U8_t *bandStartChannel, + v_U8_t *bandEndChannel) +{ +#define ACS_WLAN_20M_CH_INC 4 +#define ACS_2G_EXTEND ACS_WLAN_20M_CH_INC +#define ACS_5G_EXTEND (ACS_WLAN_20M_CH_INC * 3) + + v_U8_t tmp_startChannelNum = 0, tmp_endChannelNum = 0; + + if (*startChannelNum <= 14) { + *bandStartChannel = RF_CHAN_1; + *bandEndChannel = RF_CHAN_14; + tmp_startChannelNum = *startChannelNum > 5 ? + (*startChannelNum - ACS_2G_EXTEND): 1; + tmp_endChannelNum = (*endChannelNum + ACS_2G_EXTEND) <= 14 ? + (*endChannelNum + ACS_2G_EXTEND):14; + } else { + *bandStartChannel = RF_CHAN_36; + *bandEndChannel = RF_CHAN_165; + tmp_startChannelNum = (*startChannelNum - ACS_5G_EXTEND) > 36 ? + (*startChannelNum - ACS_5G_EXTEND):36; + tmp_endChannelNum = (*endChannelNum + ACS_5G_EXTEND) <= 165 ? + (*endChannelNum + ACS_5G_EXTEND):165; + } + + /* Note if the ACS range include only DFS channels, do not cross the range. + * Active scanning in adjacent non DFS channels results in transmission + * spikes in DFS specturm channels which is due to emission spill. + * Remove the active channels from extend ACS range for DFS only range + */ + if (VOS_IS_DFS_CH(*startChannelNum)) { + while (!VOS_IS_DFS_CH(tmp_startChannelNum) && tmp_startChannelNum < + *startChannelNum) + tmp_startChannelNum += ACS_WLAN_20M_CH_INC; + + *startChannelNum = tmp_startChannelNum; + } + if (VOS_IS_DFS_CH(*endChannelNum)) { + while (!VOS_IS_DFS_CH(tmp_endChannelNum) && tmp_endChannelNum > + *endChannelNum) + tmp_endChannelNum -= ACS_WLAN_20M_CH_INC; + + *endChannelNum = tmp_endChannelNum; + } +} + +/*========================================================================== + FUNCTION WLANSAP_Get_DfsNol + + DESCRIPTION + This API is used to dump the dfs nol + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Get_DfsNol(v_PVOID_t pSapCtx) +{ + int i = 0; + ptSapContext sapContext = (ptSapContext)pSapCtx; + v_PVOID_t hHal = NULL; + tpAniSirGlobal pMac = NULL; + v_U64_t current_time, found_time, elapsed_time; + unsigned long left_time; + tSapDfsNolInfo *dfs_nol = NULL; + v_BOOL_t bAvailable = FALSE; + + if (NULL == sapContext) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT( hHal ); + + if (!pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: DFS NOL is empty", __func__); + return VOS_STATUS_SUCCESS; + } + + dfs_nol = pMac->sap.SapDfsInfo.sapDfsChannelNolList; + + if (!dfs_nol) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: DFS NOL context is null", __func__); + return VOS_STATUS_E_FAULT; + } + + for (i = 0; i < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; i++) + { + if (!dfs_nol[i].dfs_channel_number) + continue; + + current_time = vos_get_monotonic_boottime(); + found_time = dfs_nol[i].radar_found_timestamp; + + elapsed_time = current_time - found_time; + + /* check if channel is available + * if either channel is usable or available, or timer expired 30mins + */ + bAvailable = + ((dfs_nol[i].radar_status_flag == eSAP_DFS_CHANNEL_AVAILABLE) || + (dfs_nol[i].radar_status_flag == eSAP_DFS_CHANNEL_USABLE) || + (elapsed_time >= SAP_DFS_NON_OCCUPANCY_PERIOD)); + + if (bAvailable) + { + dfs_nol[i].radar_status_flag = eSAP_DFS_CHANNEL_AVAILABLE; + dfs_nol[i].radar_found_timestamp = 0; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Channel[%d] is AVAILABLE", + __func__, + dfs_nol[i].dfs_channel_number); + } else { + + /* the time left in min */ + left_time = SAP_DFS_NON_OCCUPANCY_PERIOD - elapsed_time; + left_time = left_time / (60 * 1000 * 1000); + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Channel[%d] is UNAVAILABLE [%lu min left]", + __func__, + dfs_nol[i].dfs_channel_number, + left_time); + } + } + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_Set_DfsNol + + DESCRIPTION + This API is used to set the dfs nol + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to vos global context structure + conf: set type + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_Set_DfsNol(v_PVOID_t pSapCtx, eSapDfsNolType conf) +{ + int i = 0; + ptSapContext sapContext = (ptSapContext)pSapCtx; + v_PVOID_t hHal = NULL; + tpAniSirGlobal pMac = NULL; + + if (NULL == sapContext) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT( hHal ); + + if (!pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: DFS NOL is empty", __func__); + return VOS_STATUS_SUCCESS; + } + + if (conf == eSAP_DFS_NOL_CLEAR) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: clear the DFS NOL", + __func__); + + for (i = 0; i < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; + i++) + { + if (!pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + dfs_channel_number) + continue; + + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + radar_status_flag = eSAP_DFS_CHANNEL_AVAILABLE; + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + radar_found_timestamp = 0; + } + } else if (conf == eSAP_DFS_NOL_RANDOMIZE) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Randomize the DFS NOL", + __func__); + + /* random 1/0 to decide to put the channel into NOL */ + for (i = 0; i < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; + i++) + { + v_U32_t random_bytes = 0; + get_random_bytes(&random_bytes, 1); + + if (!pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + dfs_channel_number) + continue; + + if ((random_bytes + jiffies) % 2) { + /* mark the channel unavailable */ + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_status_flag = eSAP_DFS_CHANNEL_UNAVAILABLE; + + /* mark the timestamp */ + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .radar_found_timestamp = vos_get_monotonic_boottime(); + } else { + /* mark the channel available */ + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + radar_status_flag = eSAP_DFS_CHANNEL_AVAILABLE; + + /* clear the timestamp */ + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + radar_found_timestamp = 0; + } + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Set channel[%d] %s", + __func__, + pMac->sap.SapDfsInfo.sapDfsChannelNolList[i] + .dfs_channel_number, + (pMac->sap.SapDfsInfo.sapDfsChannelNolList[i]. + radar_status_flag > eSAP_DFS_CHANNEL_AVAILABLE) ? + "UNAVAILABLE" : "AVAILABLE"); + } + } else { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: unsupport type %d", + __func__, conf); + } + + /* set DFS-NOL back to keep it update-to-date in CNSS */ + sapSignalHDDevent(sapContext, NULL, eSAP_DFS_NOL_SET, + (v_PVOID_t) eSAP_STATUS_SUCCESS); + + return VOS_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION WLANSAP_PopulateDelStaParams + + DESCRIPTION + This API is used to populate del station parameters + DEPENDENCIES + NA. + + PARAMETERS + IN + mac: pointer to peer mac address. + reason_code: Reason code for the disassoc/deauth. + subtype: subtype points to either disassoc/deauth frame. + pDelStaParams: address where parameters to be populated. + + RETURN VALUE NONE + + SIDE EFFECTS +============================================================================*/ +void WLANSAP_PopulateDelStaParams(const v_U8_t *mac, + v_U16_t reason_code, + v_U8_t subtype, + struct tagCsrDelStaParams *pDelStaParams) +{ + if (NULL == mac) + memset(pDelStaParams->peerMacAddr, 0xff, VOS_MAC_ADDR_SIZE); + else + vos_mem_copy(pDelStaParams->peerMacAddr, mac, VOS_MAC_ADDR_SIZE); + + if (reason_code == 0) + pDelStaParams->reason_code = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON; + else + pDelStaParams->reason_code = reason_code; + + if (subtype == (SIR_MAC_MGMT_DEAUTH >> 4) || + subtype == (SIR_MAC_MGMT_DISASSOC >> 4)) + pDelStaParams->subtype = subtype; + else + pDelStaParams->subtype = (SIR_MAC_MGMT_DEAUTH >> 4); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + FL("Delete STA with RC:%hu subtype:%hhu MAC::" MAC_ADDRESS_STR), + pDelStaParams->reason_code, pDelStaParams->subtype, + MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr)); +} + +/*========================================================================== + FUNCTION WLANSAP_ACS_CHSelect + + DESCRIPTION + This api function provides ACS selection for BSS + + DEPENDENCIES + NA. + + PARAMETERS + + IN + pvosGCtx: Pointer to vos global context structure + pConfig: Pointer to configuration structure passed down from HDD + pACSEventCallback: Callback function in HDD called by SAP to inform + HDD about channel section result + usrDataForCallback: Parameter that will be passed back in all the + SAP callback events. + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_ACS_CHSelect(v_PVOID_t pvosGCtx, + tpWLAN_SAPEventCB pACSEventCallback, + tsap_Config_t *pConfig, + v_PVOID_t pUsrContext) +{ + ptSapContext sapContext = NULL; + tHalHandle hHal = NULL; + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = NULL; + + sapContext = VOS_GET_SAP_CB( pvosGCtx ); + if (NULL == sapContext) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + + return VOS_STATUS_E_FAULT; + } + + hHal = (tHalHandle)VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (NULL == hHal) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid MAC context from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + if (sapContext->isSapSessionOpen == eSAP_TRUE) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL, + "%s:SME Session is already opened\n",__func__); + return VOS_STATUS_E_EXISTS; + } + + sapContext->sessionId = 0xff; + + pMac = PMAC_STRUCT( hHal ); + sapContext->acs_cfg = &pConfig->acs_cfg; + sapContext->csrRoamProfile.phyMode = sapContext->acs_cfg->hw_mode; + + if (sapContext->isScanSessionOpen == eSAP_FALSE) { + tANI_U32 type, subType; + + if(VOS_STATUS_SUCCESS == + vos_get_vdev_types(VOS_STA_MODE, &type, &subType)) { + /* + * Open SME Session for scan + */ + if(eHAL_STATUS_SUCCESS != sme_OpenSession(hHal, NULL, sapContext, + sapContext->self_mac_addr, + &sapContext->sessionId, + type, subType)) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "Error: In %s calling sme_OpenSession", __func__); + return VOS_STATUS_E_FAILURE; + } + else + sapContext->isScanSessionOpen = eSAP_TRUE; + } + + /* + * Copy the HDD callback function to report the + * ACS result after scan in SAP context callback function. + */ + sapContext->pfnSapEventCallback = pACSEventCallback; + /* + * init dfs channel nol + */ + sapInitDfsChannelNolList(sapContext); + + /* + * Now, configure the scan and ACS channel params + * to issue a scan request. + */ + WLANSAP_SetScanAcsChannelParams(pConfig, sapContext, pUsrContext); + + /* + * Issue the scan request. This scan request is + * issued before the start BSS is done so + * + * 1. No need to pass the second parameter + * as the SAP state machine is not started yet + * and there is no need for any event posting. + * + * 2. Set third parameter to TRUE to indicate the + * channel selection function to register a + * different scan callback fucntion to process + * the results pre start BSS. + */ + vosStatus = sapGotoChannelSel(sapContext, NULL, VOS_TRUE); + + if (VOS_STATUS_E_ABORTED == vosStatus) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "In %s,DFS not supported in the current operating mode", + __func__); + return VOS_STATUS_E_FAILURE; + } + else if (VOS_STATUS_E_CANCELED == vosStatus) { + /* + * ERROR is returned when either the SME scan request + * failed or ACS is overridden due to other constraints + * So send this channel to HDD. + */ + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + FL("Scan Req Failed/ACS Overridden, Selected channel = %d"), + sapContext->channel); + + if (sapContext->isScanSessionOpen == eSAP_TRUE) { + /* acs scan not needed so close the session */ + tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + if (hHal == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: HAL Handle NULL. ACS Scan session close fail!", + __func__); + return VOS_STATUS_E_FAILURE; + } + if (eHAL_STATUS_SUCCESS == sme_CloseSession(hHal, + sapContext->sessionId, NULL, NULL)) { + sapContext->isScanSessionOpen = eSAP_FALSE; + } else { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: ACS Scan session close fail!", __func__); + } + sapContext->sessionId = 0xff; + } + + return sapSignalHDDevent(sapContext, NULL, + eSAP_ACS_CHANNEL_SELECTED, (v_PVOID_t) eSAP_STATUS_SUCCESS); + } + else if (VOS_STATUS_SUCCESS == vosStatus) + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Successfully Issued a Pre Start Bss Scan Request")); + } + return vosStatus; +} +/** +* wlansap_get_phymode() - get SAP phymode. +* @pctx: Pointer to the global vos context; a handle to SAP's control block +* can be extracted from its context. When MBSSID feature is enabled, +* SAP context is directly passed to SAP APIs. +* +* This function provides current phymode of SAP interface. +* +* Return: phymode with eCsrPhyMode type. +*/ +eCsrPhyMode +wlansap_get_phymode(v_PVOID_t pctx) +{ + ptSapContext psapctx = VOS_GET_SAP_CB(pctx); + + if ( NULL == psapctx) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return eCSR_DOT11_MODE_AUTO; + } + return psapctx->csrRoamProfile.phyMode; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ar6320v2_dbg_regtable.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ar6320v2_dbg_regtable.h new file mode 100644 index 000000000000..e75534a5d49d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ar6320v2_dbg_regtable.h @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320V2_DBG_REGTABLE_H_ +#define _AR6320V2_DBG_REGTABLE_H_ + +#include "regtable.h" + +#define AR6320_REV2_1_REG_SIZE 0x0007F820 +#define AR6320_REV3_REG_SIZE 0x0007F820 + +#ifdef HIF_PCI +/* + * Redefine the register list. To minimize the size of the array, the list must + * obey the below format. {start0, end0}, {start1, end1}, {start2, end2}....... + * The value below must obey to "start0 < end0 < start1 < end1 < start2 < ...", + * otherwise we may encouter error in the dump processing. + */ + +static const tgt_reg_section ar6320v2_reg_table[] = +{ + {0x800, 0x810}, + {0x820, 0x82C}, + {0x830, 0x8F4}, + {0x90C, 0x91C}, + {0xA14, 0xA18}, + {0xA84, 0xA94}, + {0xAA8, 0xAD4}, + {0xADC, 0xB40}, + {0x1000, 0x10A4}, + {0x10BC, 0x111C}, + {0x1134, 0x1138}, + {0x1144, 0x114C}, + {0x1150, 0x115C}, + {0x1160, 0x1178}, + {0x1240, 0x1260}, + {0x2000, 0x207C}, + {0x3000, 0x3014}, + {0x4000, 0x4014}, + {0x5000, 0x5124}, + {0x6000, 0x6040}, + {0x6080, 0x60CC}, + {0x6100, 0x611C}, + {0x6140, 0x61D8}, + {0x6200, 0x6238}, + {0x6240, 0x628C}, + {0x62C0, 0x62EC}, + {0x6380, 0x63E8}, + {0x6400, 0x6440}, + {0x6480, 0x64CC}, + {0x6500, 0x651C}, + {0x6540, 0x6580}, + {0x6600, 0x6638}, + {0x6640, 0x668C}, + {0x66C0, 0x66EC}, + {0x6780, 0x67E8}, + {0x7080, 0x708C}, + {0x70C0, 0x70C8}, + {0x7400, 0x741C}, + {0x7440, 0x7454}, + {0x7800, 0x7818}, + {0x8000, 0x8004}, + {0x8010, 0x8064}, + {0x8080, 0x8084}, + {0x80A0, 0x80A4}, + {0x80C0, 0x80C4}, + {0x80E0, 0x80F4}, + {0x8100, 0x8104}, + {0x8110, 0x812C}, + {0x9000, 0x9004}, + {0x9800, 0x982C}, + {0x9830, 0x9838}, + {0x9840, 0x986C}, + {0x9870, 0x9898}, + {0x9A00, 0x9C00}, + {0xD580, 0xD59C}, + {0xF000, 0xF0E0}, + {0xF140, 0xF190}, + {0xF250, 0xF25C}, + {0xF260, 0xF268}, + {0xF26C, 0xF2A8}, + {0x10008, 0x1000C}, + {0x10014, 0x10018}, + {0x1001C, 0x10020}, + {0x10024, 0x10028}, + {0x10030, 0x10034}, + {0x10040, 0x10054}, + {0x10058, 0x1007C}, + {0x10080, 0x100C4}, + {0x100C8, 0x10114}, + {0x1012C, 0x10130}, + {0x10138, 0x10144}, + {0x10200, 0x10220}, + {0x10230, 0x10250}, + {0x10260, 0x10280}, + {0x10290, 0x102B0}, + {0x102C0, 0x102DC}, + {0x102E0, 0x102F4}, + {0x102FC, 0x1037C}, + {0x10380, 0x10390}, + {0x10800, 0x10828}, + {0x10840, 0x10844}, + {0x10880, 0x10884}, + {0x108C0, 0x108E8}, + {0x10900, 0x10928}, + {0x10940, 0x10944}, + {0x10980, 0x10984}, + {0x109C0, 0x109E8}, + {0x10A00, 0x10A28}, + {0x10A40, 0x10A50}, + {0x11000, 0x11028}, + {0x11030, 0x11034}, + {0x11038, 0x11068}, + {0x11070, 0x11074}, + {0x11078, 0x110A8}, + {0x110B0, 0x110B4}, + {0x110B8, 0x110E8}, + {0x110F0, 0x110F4}, + {0x110F8, 0x11128}, + {0x11138, 0x11144}, + {0x11178, 0x11180}, + {0x111B8, 0x111C0}, + {0x111F8, 0x11200}, + {0x11238, 0x1123C}, + {0x11270, 0x11274}, + {0x11278, 0x1127C}, + {0x112B0, 0x112B4}, + {0x112B8, 0x112BC}, + {0x112F0, 0x112F4}, + {0x112F8, 0x112FC}, + {0x11338, 0x1133C}, + {0x11378, 0x1137C}, + {0x113B8, 0x113BC}, + {0x113F8, 0x113FC}, + {0x11438, 0x11440}, + {0x11478, 0x11480}, + {0x114B8, 0x114BC}, + {0x114F8, 0x114FC}, + {0x11538, 0x1153C}, + {0x11578, 0x1157C}, + {0x115B8, 0x115BC}, + {0x115F8, 0x115FC}, + {0x11638, 0x1163C}, + {0x11678, 0x1167C}, + {0x116B8, 0x116BC}, + {0x116F8, 0x116FC}, + {0x11738, 0x1173C}, + {0x11778, 0x1177C}, + {0x117B8, 0x117BC}, + {0x117F8, 0x117FC}, + {0x17000, 0x1701C}, + {0x17020, 0x170AC}, + {0x18000, 0x18050}, + {0x18054, 0x18074}, + {0x18080, 0x180D4}, + {0x180DC, 0x18104}, + {0x18108, 0x1813C}, + {0x18144, 0x18148}, + {0x18168, 0x18174}, + {0x18178, 0x18180}, + {0x181C8, 0x181E0}, + {0x181E4, 0x181E8}, + {0x181EC, 0x1820C}, + {0x1825C, 0x18280}, + {0x18284, 0x18290}, + {0x18294, 0x182A0}, + {0x18300, 0x18304}, + {0x18314, 0x18320}, + {0x18328, 0x18350}, + {0x1835C, 0x1836C}, + {0x18370, 0x18390}, + {0x18398, 0x183AC}, + {0x183BC, 0x183D8}, + {0x183DC, 0x183F4}, + {0x18400, 0x186F4}, + {0x186F8, 0x1871C}, + {0x18720, 0x18790}, + {0x19800, 0x19830}, + {0x19834, 0x19840}, + {0x19880, 0x1989C}, + {0x198A4, 0x198B0}, + {0x198BC, 0x19900}, + {0x19C00, 0x19C88}, + {0x19D00, 0x19D20}, + {0x19E00, 0x19E7C}, + {0x19E80, 0x19E94}, + {0x19E98, 0x19EAC}, + {0x19EB0, 0x19EBC}, + {0x19F70, 0x19F74}, + {0x19F80, 0x19F8C}, + {0x19FA0, 0x19FB4}, + {0x19FC0, 0x19FD8}, + {0x1A000, 0x1A200}, + {0x1A204, 0x1A210}, + {0x1A228, 0x1A22C}, + {0x1A230, 0x1A248}, + {0x1A250, 0x1A270}, + {0x1A280, 0x1A290}, + {0x1A2A0, 0x1A2A4}, + {0x1A2C0, 0x1A2EC}, + {0x1A300, 0x1A3BC}, + {0x1A3F0, 0x1A3F4}, + {0x1A3F8, 0x1A434}, + {0x1A438, 0x1A444}, + {0x1A448, 0x1A468}, + {0x1A580, 0x1A58C}, + {0x1A644, 0x1A654}, + {0x1A670, 0x1A698}, + {0x1A6AC, 0x1A6B0}, + {0x1A6D0, 0x1A6D4}, + {0x1A6EC, 0x1A70C}, + {0x1A710, 0x1A738}, + {0x1A7C0, 0x1A7D0}, + {0x1A7D4, 0x1A7D8}, + {0x1A7DC, 0x1A7E4}, + {0x1A7F0, 0x1A7F8}, + {0x1A888, 0x1A89C}, + {0x1A8A8, 0x1A8AC}, + {0x1A8C0, 0x1A8DC}, + {0x1A8F0, 0x1A8FC}, + {0x1AE04, 0x1AE08}, + {0x1AE18, 0x1AE24}, + {0x1AF80, 0x1AF8C}, + {0x1AFA0, 0x1AFB4}, + {0x1B000, 0x1B200}, + {0x1B284, 0x1B288}, + {0x1B2D0, 0x1B2D8}, + {0x1B2DC, 0x1B2EC}, + {0x1B300, 0x1B340}, + {0x1B374, 0x1B378}, + {0x1B380, 0x1B384}, + {0x1B388, 0x1B38C}, + {0x1B404, 0x1B408}, + {0x1B420, 0x1B428}, + {0x1B440, 0x1B444}, + {0x1B448, 0x1B44C}, + {0x1B450, 0x1B458}, + {0x1B45C, 0x1B468}, + {0x1B584, 0x1B58C}, + {0x1B68C, 0x1B690}, + {0x1B6AC, 0x1B6B0}, + {0x1B7F0, 0x1B7F8}, + {0x1C800, 0x1CC00}, + {0x1CE00, 0x1CE04}, + {0x1CF80, 0x1CF84}, + {0x1D200, 0x1D800}, + {0x1E000, 0x20014}, + {0x20100, 0x20124}, + {0x21400, 0x217A8}, + {0x21800, 0x21BA8}, + {0x21C00, 0x21FA8}, + {0x22000, 0x223A8}, + {0x22400, 0x227A8}, + {0x22800, 0x22BA8}, + {0x22C00, 0x22FA8}, + {0x23000, 0x233A8}, + {0x24000, 0x24034}, + + /* + * EFUSE0,1,2 is disabled here + * because it's state may be reset + * + * {0x24800, 0x24804}, + * {0x25000, 0x25004}, + * {0x25800, 0x25804}, + */ + + {0x26000, 0x26064}, + {0x27000, 0x27024}, + {0x34000, 0x3400C}, + {0x34400, 0x3445C}, + {0x34800, 0x3485C}, + {0x34C00, 0x34C5C}, + {0x35000, 0x3505C}, + {0x35400, 0x3545C}, + {0x35800, 0x3585C}, + {0x35C00, 0x35C5C}, + {0x36000, 0x3605C}, + {0x38000, 0x38064}, + {0x38070, 0x380E0}, + {0x3A000, 0x3A064}, + + /* DBI windows is skipped here, it can be only accessed when pcie + * is active (not in reset) and CORE_CTRL_PCIE_LTSSM_EN = 0 && + * PCIE_CTRL_APP_LTSSM_ENALBE=0. + * {0x3C000 , 0x3C004}, + */ + + {0x40000, 0x400A4}, + + /* + * SI register is skiped here. + * Because it will cause bus hang + * + * {0x50000, 0x50018}, + */ + + {0x80000, 0x8000C}, + {0x80010, 0x80020}, +}; + +static const tgt_reg_section ar6320v3_reg_table[] = +{ + {0x800, 0x810}, + {0x820, 0x82C}, + {0x830, 0x8F4}, + {0x90C, 0x91C}, + {0xA14, 0xA18}, + {0xA84, 0xA94}, + {0xAA8, 0xAD4}, + {0xADC, 0xB40}, + {0x1000, 0x10A4}, + {0x10BC, 0x111C}, + {0x1134, 0x1138}, + {0x1144, 0x114C}, + {0x1150, 0x115C}, + {0x1160, 0x1178}, + {0x1240, 0x1260}, + {0x2000, 0x207C}, + {0x3000, 0x3014}, + {0x4000, 0x4014}, + {0x5000, 0x5124}, + {0x6000, 0x6040}, + {0x6080, 0x60CC}, + {0x6100, 0x611C}, + {0x6140, 0x61D8}, + {0x6200, 0x6238}, + {0x6240, 0x628C}, + {0x62C0, 0x62EC}, + {0x6380, 0x63E8}, + {0x6400, 0x6440}, + {0x6480, 0x64CC}, + {0x6500, 0x651C}, + {0x6540, 0x6580}, + {0x6600, 0x6638}, + {0x6640, 0x668C}, + {0x66C0, 0x66EC}, + {0x6780, 0x67E8}, + {0x7080, 0x708C}, + {0x70C0, 0x70C8}, + {0x7400, 0x741C}, + {0x7440, 0x7454}, + {0x7800, 0x7818}, + {0x8000, 0x8004}, + {0x8010, 0x8064}, + {0x8080, 0x8084}, + {0x80A0, 0x80A4}, + {0x80C0, 0x80C4}, + {0x80E0, 0x80F4}, + {0x8100, 0x8104}, + {0x8110, 0x812C}, + {0x9000, 0x9004}, + {0x9800, 0x982C}, + {0x9830, 0x9838}, + {0x9840, 0x986C}, + {0x9870, 0x9898}, + {0x9A00, 0x9C00}, + {0xD580, 0xD59C}, + {0xF000, 0xF0E0}, + {0xF140, 0xF190}, + {0xF250, 0xF25C}, + {0xF260, 0xF268}, + {0xF26C, 0xF2A8}, + {0x10008, 0x1000C}, + {0x10014, 0x10018}, + {0x1001C, 0x10020}, + {0x10024, 0x10028}, + {0x10030, 0x10034}, + {0x10040, 0x10054}, + {0x10058, 0x1007C}, + {0x10080, 0x100C4}, + {0x100C8, 0x10114}, + {0x1012C, 0x10130}, + {0x10138, 0x10144}, + {0x10200, 0x10220}, + {0x10230, 0x10250}, + {0x10260, 0x10280}, + {0x10290, 0x102B0}, + {0x102C0, 0x102DC}, + {0x102E0, 0x102F4}, + {0x102FC, 0x1037C}, + {0x10380, 0x10390}, + {0x10800, 0x10828}, + {0x10840, 0x10844}, + {0x10880, 0x10884}, + {0x108C0, 0x108E8}, + {0x10900, 0x10928}, + {0x10940, 0x10944}, + {0x10980, 0x10984}, + {0x109C0, 0x109E8}, + {0x10A00, 0x10A28}, + {0x10A40, 0x10A50}, + {0x11000, 0x11028}, + {0x11030, 0x11034}, + {0x11038, 0x11068}, + {0x11070, 0x11074}, + {0x11078, 0x110A8}, + {0x110B0, 0x110B4}, + {0x110B8, 0x110E8}, + {0x110F0, 0x110F4}, + {0x110F8, 0x11128}, + {0x11138, 0x11144}, + {0x11178, 0x11180}, + {0x111B8, 0x111C0}, + {0x111F8, 0x11200}, + {0x11238, 0x1123C}, + {0x11270, 0x11274}, + {0x11278, 0x1127C}, + {0x112B0, 0x112B4}, + {0x112B8, 0x112BC}, + {0x112F0, 0x112F4}, + {0x112F8, 0x112FC}, + {0x11338, 0x1133C}, + {0x11378, 0x1137C}, + {0x113B8, 0x113BC}, + {0x113F8, 0x113FC}, + {0x11438, 0x11440}, + {0x11478, 0x11480}, + {0x114B8, 0x114BC}, + {0x114F8, 0x114FC}, + {0x11538, 0x1153C}, + {0x11578, 0x1157C}, + {0x115B8, 0x115BC}, + {0x115F8, 0x115FC}, + {0x11638, 0x1163C}, + {0x11678, 0x1167C}, + {0x116B8, 0x116BC}, + {0x116F8, 0x116FC}, + {0x11738, 0x1173C}, + {0x11778, 0x1177C}, + {0x117B8, 0x117BC}, + {0x117F8, 0x117FC}, + {0x17000, 0x1701C}, + {0x17020, 0x170AC}, + {0x18000, 0x18050}, + {0x18054, 0x18074}, + {0x18080, 0x180D4}, + {0x180DC, 0x18104}, + {0x18108, 0x1813C}, + {0x18144, 0x18148}, + {0x18168, 0x18174}, + {0x18178, 0x18180}, + {0x181C8, 0x181E0}, + {0x181E4, 0x181E8}, + {0x181EC, 0x1820C}, + {0x1825C, 0x18280}, + {0x18284, 0x18290}, + {0x18294, 0x182A0}, + {0x18300, 0x18304}, + {0x18314, 0x18320}, + {0x18328, 0x18350}, + {0x1835C, 0x1836C}, + {0x18370, 0x18390}, + {0x18398, 0x183AC}, + {0x183BC, 0x183D8}, + {0x183DC, 0x183F4}, + {0x18400, 0x186F4}, + {0x186F8, 0x1871C}, + {0x18720, 0x18790}, + {0x19800, 0x19830}, + {0x19834, 0x19840}, + {0x19880, 0x1989C}, + {0x198A4, 0x198B0}, + {0x198BC, 0x19900}, + {0x19C00, 0x19C88}, + {0x19D00, 0x19D20}, + {0x19E00, 0x19E7C}, + {0x19E80, 0x19E94}, + {0x19E98, 0x19EAC}, + {0x19EB0, 0x19EBC}, + {0x19F70, 0x19F74}, + {0x19F80, 0x19F8C}, + {0x19FA0, 0x19FB4}, + {0x19FC0, 0x19FD8}, + {0x1A000, 0x1A200}, + {0x1A204, 0x1A210}, + {0x1A228, 0x1A22C}, + {0x1A230, 0x1A248}, + {0x1A250, 0x1A270}, + {0x1A280, 0x1A290}, + {0x1A2A0, 0x1A2A4}, + {0x1A2C0, 0x1A2EC}, + {0x1A300, 0x1A3BC}, + {0x1A3F0, 0x1A3F4}, + {0x1A3F8, 0x1A434}, + {0x1A438, 0x1A444}, + {0x1A448, 0x1A468}, + {0x1A580, 0x1A58C}, + {0x1A644, 0x1A654}, + {0x1A670, 0x1A698}, + {0x1A6AC, 0x1A6B0}, + {0x1A6D0, 0x1A6D4}, + {0x1A6EC, 0x1A70C}, + {0x1A710, 0x1A738}, + {0x1A7C0, 0x1A7D0}, + {0x1A7D4, 0x1A7D8}, + {0x1A7DC, 0x1A7E4}, + {0x1A7F0, 0x1A7F8}, + {0x1A888, 0x1A89C}, + {0x1A8A8, 0x1A8AC}, + {0x1A8C0, 0x1A8DC}, + {0x1A8F0, 0x1A8FC}, + {0x1AE04, 0x1AE08}, + {0x1AE18, 0x1AE24}, + {0x1AF80, 0x1AF8C}, + {0x1AFA0, 0x1AFB4}, + {0x1B000, 0x1B200}, + {0x1B284, 0x1B288}, + {0x1B2D0, 0x1B2D8}, + {0x1B2DC, 0x1B2EC}, + {0x1B300, 0x1B340}, + {0x1B374, 0x1B378}, + {0x1B380, 0x1B384}, + {0x1B388, 0x1B38C}, + {0x1B404, 0x1B408}, + {0x1B420, 0x1B428}, + {0x1B440, 0x1B444}, + {0x1B448, 0x1B44C}, + {0x1B450, 0x1B458}, + {0x1B45C, 0x1B468}, + {0x1B584, 0x1B58C}, + {0x1B68C, 0x1B690}, + {0x1B6AC, 0x1B6B0}, + {0x1B7F0, 0x1B7F8}, + {0x1C800, 0x1CC00}, + {0x1CE00, 0x1CE04}, + {0x1CF80, 0x1CF84}, + {0x1D200, 0x1D800}, + {0x1E000, 0x20014}, + {0x20100, 0x20124}, + {0x21400, 0x217A8}, + {0x21800, 0x21BA8}, + {0x21C00, 0x21FA8}, + {0x22000, 0x223A8}, + {0x22400, 0x227A8}, + {0x22800, 0x22BA8}, + {0x22C00, 0x22FA8}, + {0x23000, 0x233A8}, + {0x24000, 0x24034}, + + /* + * EFUSE0,1,2 is disabled here + * because it's state may be reset + * + * {0x24800, 0x24804}, + * {0x25000, 0x25004}, + * {0x25800, 0x25804}, + */ + + {0x26000, 0x26064}, + {0x27000, 0x27024}, + {0x34000, 0x3400C}, + {0x34400, 0x3445C}, + {0x34800, 0x3485C}, + {0x34C00, 0x34C5C}, + {0x35000, 0x3505C}, + {0x35400, 0x3545C}, + {0x35800, 0x3585C}, + {0x35C00, 0x35C5C}, + {0x36000, 0x3605C}, + {0x38000, 0x38064}, + {0x38070, 0x380E0}, + {0x3A000, 0x3A074}, + + /* + * DBI windows is skipped here, it can be only accessed when pcie + * is active (not in reset) and CORE_CTRL_PCIE_LTSSM_EN = 0 && + * PCIE_CTRL_APP_LTSSM_ENALBE=0. + * {0x3C000 , 0x3C004}, + */ + + {0x40000, 0x400A4}, + + /* + * SI register is skiped here. + * Because it will cause bus hang + * + * {0x50000, 0x50018}, + */ + + {0x80000, 0x8000C}, + {0x80010, 0x80020}, +}; +#endif +#endif /* #ifndef _AR6320V2_DBG_REGTABLE_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bin_sig.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bin_sig.h new file mode 100644 index 000000000000..7266945cc705 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bin_sig.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef BIN_SIGN_H_ +#define BIN_SIGN_H_ + +#define SIGN_HEADER_MAGIC 0x454D4F52 + +/* Signed binary MetaData */ +typedef struct { + unsigned int magic_num; + unsigned int total_len; + unsigned int rampatch_len; + unsigned int product_id; + unsigned int patch_ver; + unsigned short sign_format_ver; + unsigned short sign_algorithm; + unsigned char reserved[8]; +} SIGN_HEADER_T; + +#endif /* BIN_SIGN_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi.c new file mode 100644 index 000000000000..d487d522dc25 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi.c @@ -0,0 +1,902 @@ +/* + * copyright (c) 2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "hif.h" +#include "bmi.h" +#include "bmi_internal.h" +#include "ol_fw.h" + +#ifdef HIF_MESSAGE_BASED + +#ifdef HIF_USB +#include "a_usb_defs.h" +#endif + +#if defined(HIF_BMI_MAX_TRANSFER_SIZE) + +#if BMI_DATASZ_MAX > HIF_BMI_MAX_TRANSFER_SIZE + /* override */ +#undef BMI_DATASZ_MAX +#define BMI_DATASZ_MAX HIF_BMI_MAX_TRANSFER_SIZE +#endif +#endif + +#endif + +#ifdef DEBUG +static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = { + { ATH_DEBUG_BMI , "BMI Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, + "bmi", + "Boot Manager Interface", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), + bmi_debug_desc); + +#endif + +/* +Although we had envisioned BMI to run on top of HTC, this is not how the +final implementation ended up. On the Target side, BMI is a part of the BSP +and does not use the HTC protocol nor even DMA -- it is intentionally kept +very simple. +*/ + +#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \ + sizeof(A_UINT32) /* cmd */ + \ + sizeof(A_UINT32) /* addr */ + \ + sizeof(A_UINT32))/* length */ +#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ) +#define BMI_EXCHANGE_TIMEOUT_MS 1000 + +/* APIs visible to the driver */ +void +BMIInit(struct ol_softc *scn) +{ + if (!scn) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid scn context\n")); + ASSERT(0); + return; + } + scn->bmiDone = FALSE; + + /* + * On some platforms, it's not possible to DMA to a static variable + * in a device driver (e.g. Linux loadable driver module). + * So we need to A_MALLOC space for "command credits" and for commands. + * + * Note: implicitly relies on A_MALLOC to provide a buffer that is + * suitable for DMA (or PIO). This buffer will be passed down the + * bus stack. + */ + + if (!scn->pBMICmdBuf) { +#ifndef HIF_PCI + scn->pBMICmdBuf = + (A_UCHAR *)A_MALLOC(MAX_BMI_CMDBUF_SZ); +#else + scn->pBMICmdBuf = + (A_UCHAR *)pci_alloc_consistent(scn->sc_osdev->bdev, + MAX_BMI_CMDBUF_SZ, + &scn->BMICmd_pa); +#endif + ASSERT(scn->pBMICmdBuf); + } + + if (!scn->pBMIRspBuf) { +#ifndef HIF_PCI + scn->pBMIRspBuf = + (A_UCHAR *)A_MALLOC(MAX_BMI_CMDBUF_SZ); +#else + scn->pBMIRspBuf = + (A_UCHAR *)pci_alloc_consistent(scn->sc_osdev->bdev, + MAX_BMI_CMDBUF_SZ, + &scn->BMIRsp_pa); +#endif + ASSERT(scn->pBMIRspBuf); + } + + A_REGISTER_MODULE_DEBUG_INFO(bmi); +} + +void +BMICleanup(struct ol_softc *scn) +{ + if (scn->pBMICmdBuf) { +#ifndef HIF_PCI + A_FREE(scn->pBMICmdBuf ); +#else + pci_free_consistent(scn->sc_osdev->bdev, MAX_BMI_CMDBUF_SZ, + scn->pBMICmdBuf, scn->BMICmd_pa); +#endif + scn->pBMICmdBuf = NULL; + scn->BMICmd_pa = 0; + } + + if (scn->pBMIRspBuf) { +#ifndef HIF_PCI + A_FREE(scn->pBMIRspBuf); +#else + pci_free_consistent(scn->sc_osdev->bdev, MAX_BMI_CMDBUF_SZ, + scn->pBMIRspBuf, scn->BMIRsp_pa); +#endif + scn->pBMIRspBuf = NULL; + scn->BMIRsp_pa = 0; + } +} + +static A_STATUS +BMIDone(HIF_DEVICE *device, struct ol_softc *scn) +{ + A_STATUS status; + A_UINT32 cid; + + if (!scn) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid scn context\n")); + ASSERT(0); + return A_ERROR; + } + + if (scn->bmiDone) { + AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n")); + return A_OK; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device)); + +#if defined(A_SIMOS_DEVHOST) + /* Let HIF layer know that BMI phase is done. + * Note that this call enqueues a bunch of receive buffers, + * so it is important that this complete before we tell the + * target about BMI_DONE. + */ + (void)HIFConfigureDevice(device, HIF_BMI_DONE, NULL, 0); +#endif + + scn->bmiDone = TRUE; + cid = BMI_DONE; + + if (!scn->pBMICmdBuf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid scn BMICmdBuff\n")); + ASSERT(0); + return A_ERROR; + } + + A_MEMCPY(scn->pBMICmdBuf,&cid,sizeof(cid)); + + status = HIFExchangeBMIMsg(device, scn->pBMICmdBuf, sizeof(cid), NULL, NULL, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + if (scn->pBMICmdBuf) { +#ifndef HIF_PCI + A_FREE(scn->pBMICmdBuf); +#else + pci_free_consistent(scn->sc_osdev->bdev, MAX_BMI_CMDBUF_SZ, + scn->pBMICmdBuf, scn->BMICmd_pa); +#endif + scn->pBMICmdBuf = NULL; + scn->BMICmd_pa = 0; + } + + if (scn->pBMIRspBuf) { +#ifndef HIF_PCI + A_FREE(scn->pBMIRspBuf); +#else + pci_free_consistent(scn->sc_osdev->bdev, MAX_BMI_CMDBUF_SZ, + scn->pBMIRspBuf, scn->BMIRsp_pa); +#endif + scn->pBMIRspBuf = NULL; + scn->BMIRsp_pa = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n")); + + return A_OK; +} + +A_STATUS bmi_done(struct ol_softc *scn) +{ + HIFClaimDevice(scn->hif_hdl, scn); + + if (BMIDone(scn->hif_hdl, scn) != A_OK) + return -1; + + return 0; +} + +void bmi_target_ready(struct ol_softc *scn, void *cfg_ctx) +{ + ol_target_ready(scn, cfg_ctx); +} + +#ifndef HIF_MESSAGE_BASED +extern A_STATUS HIFRegBasedGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info); +#endif + +static A_STATUS +BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info, struct ol_softc *scn) +{ +#ifndef HIF_MESSAGE_BASED +#else + A_STATUS status; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + A_UCHAR *pBMIRspBuf = scn->pBMIRspBuf; +#endif + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Get Target Info Command disallowed\n")); + return A_ERROR; + } + +#ifndef HIF_MESSAGE_BASED + /* getting the target ID requires special handling because of the variable length + * message */ + return HIFRegBasedGetTargetInfo(device,targ_info); +#else + + { + A_UINT32 cid; + A_UINT32 length; + + cid = BMI_GET_TARGET_INFO; + + A_MEMCPY(pBMICmdBuf,&cid,sizeof(cid)); + length = sizeof(struct bmi_target_info); + + status = HIFExchangeBMIMsg(device, + pBMICmdBuf, + sizeof(cid), + (A_UINT8 *)pBMIRspBuf, + &length, + BMI_EXCHANGE_TIMEOUT_MS); + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to get target information from the device\n")); + return A_ERROR; + } + + A_MEMCPY(targ_info, pBMIRspBuf, length); + return status; + } +#endif +} + +A_STATUS bmi_download_firmware(struct ol_softc *scn) +{ + struct bmi_target_info targ_info; + OS_MEMZERO(&targ_info, sizeof(targ_info)); + + if (!scn){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid scn context\n")); + ASSERT(0); + return A_EINVAL; + } + + /* Initialize BMI */ + BMIInit(scn); + + if (scn->pBMICmdBuf == NULL || scn->pBMIRspBuf == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIInit failed!\n")); + return -1; + } + + /* Get target information */ + if (BMIGetTargetInfo(scn->hif_hdl, &targ_info, scn) != A_OK) + return -1; + + scn->target_type = targ_info.target_type; + scn->target_version = targ_info.target_ver; + + /* Configure target */ + if (ol_configure_target(scn) != A_OK) + return -1; + + if (ol_download_firmware(scn) != EOK) + return -EIO; + + return 0; +} + +A_STATUS +BMIReadMemory(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UINT32 remaining, rxlen; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + A_UCHAR *pBMIRspBuf = scn->pBMIRspBuf; + A_UINT32 align; + + ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length))); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)); + memset (pBMIRspBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_READ_MEMORY; +#if defined(SDIO_3_0) + /* 4bytes align operation */ + align = 4 - (length & 3); + remaining = length + align; +#else + align = 0; + remaining = length; +#endif + while (remaining) + { + rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX; + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + A_MEMCPY(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen)); + offset += sizeof(length); + + status = HIFExchangeBMIMsg(device, + pBMICmdBuf, + offset, + pBMIRspBuf, /* note we reuse the same buffer to receive on */ + &rxlen, + BMI_EXCHANGE_TIMEOUT_MS); + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + if (remaining == rxlen) { + A_MEMCPY(&buffer[length - remaining + align], pBMIRspBuf, rxlen - align); /* last align bytes are invalid */ + } else { + A_MEMCPY(&buffer[length - remaining + align], pBMIRspBuf, rxlen); + } + remaining -= rxlen; address += rxlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n")); + return A_OK; +} + +A_STATUS +BMIWriteMemory(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UINT32 remaining, txlen; + const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length); + A_UCHAR alignedBuffer[BMI_DATASZ_MAX]; + A_UCHAR *src; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + + ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_WRITE_MEMORY; + + remaining = length; + while (remaining) + { + src = &buffer[length - remaining]; + if (remaining < (BMI_DATASZ_MAX - header)) { + if (remaining & 3) { + /* align it with 4 bytes */ + remaining = remaining + (4 - (remaining & 3)); + memcpy(alignedBuffer, src, remaining); + src = alignedBuffer; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + A_MEMCPY(&(pBMICmdBuf[offset]), src, txlen); + offset += txlen; + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, BMI_EXCHANGE_TIMEOUT_MS); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; address += txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n")); + + return A_OK; +} + +A_STATUS +BMIExecute(HIF_DEVICE *device, + A_UINT32 address, + A_UINT32 *param, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UINT32 paramLen; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + A_UCHAR *pBMIRspBuf = scn->pBMIRspBuf; + + ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + memset (pBMIRspBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n", + device, address, *param)); + + cid = BMI_EXECUTE; + + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + A_MEMCPY(&(pBMICmdBuf[offset]), param, sizeof(*param)); + offset += sizeof(*param); + paramLen = sizeof(*param); + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMIRspBuf, ¶mLen, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + + A_MEMCPY(param, pBMIRspBuf, sizeof(*param)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param)); + return A_OK; +} + +A_STATUS +BMISetAppStart(HIF_DEVICE *device, + A_UINT32 address, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + + ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_SET_APP_START; + + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n")); + return A_OK; +} + +A_STATUS +BMIReadSOCRegister(HIF_DEVICE *device, + A_UINT32 address, + A_UINT32 *param, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset,paramLen; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + A_UCHAR *pBMIRspBuf = scn->pBMIRspBuf; + + ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + memset (pBMIRspBuf, 0, sizeof(cid) + sizeof(address)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_READ_SOC_REGISTER; + + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + paramLen = sizeof(*param); + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMIRspBuf, ¶mLen, BMI_EXCHANGE_TIMEOUT_MS); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + A_MEMCPY(param, pBMIRspBuf, sizeof(*param)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param)); + return A_OK; +} + +A_STATUS +BMIWriteSOCRegister(HIF_DEVICE *device, + A_UINT32 address, + A_UINT32 param, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + + ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n", + device, address, param)); + + cid = BMI_WRITE_SOC_REGISTER; + + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + A_MEMCPY(&(pBMICmdBuf[offset]), ¶m, sizeof(param)); + offset += sizeof(param); + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n")); + return A_OK; +} + +A_STATUS +BMILZData(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UINT32 remaining, txlen; + const A_UINT32 header = sizeof(cid) + sizeof(length); + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + + ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header)); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n", + device, length)); + + cid = BMI_LZ_DATA; + + remaining = length; + while (remaining) + { + txlen = (remaining < (BMI_DATASZ_MAX - header)) ? + remaining : (BMI_DATASZ_MAX - header); + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + A_MEMCPY(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen); + offset += txlen; + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n")); + + return A_OK; +} + +A_STATUS +BMISignStreamStart(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length); + A_UCHAR alignedBuffer[BMI_DATASZ_MAX + 4]; + A_UCHAR *src; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + A_UINT32 remaining, txlen; + + ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + header); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI SIGN Stream Start: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_SIGN_STREAM_START; + remaining = length; + while (remaining) + { + src = &buffer[length - remaining]; + if (remaining < (BMI_DATASZ_MAX - header)) { + /* Actually it shall be aligned binary from header definition. + * Not necessary for align process. Kept for possible changes + */ + if (remaining & 0x3) { + remaining = remaining + (4 - (remaining & 0x3)); + memcpy(alignedBuffer, src, remaining); + src = alignedBuffer; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(offset); + A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + A_MEMCPY(&(pBMICmdBuf[offset]), src, txlen); + offset += txlen; + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, BMI_EXCHANGE_TIMEOUT_MS); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI SIGN Stream Start: Exit\n")); + + return A_OK; +} + +A_STATUS +BMILZStreamStart(HIF_DEVICE *device, + A_UINT32 address, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + + ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_LZ_STREAM_START; + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n")); + + return A_OK; +} + +A_STATUS +BMIFastDownload(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, struct ol_softc *scn) +{ + A_STATUS status = A_ERROR; + A_UINT32 lastWord = 0; + A_UINT32 lastWordOffset = length & ~0x3; + A_UINT32 unalignedBytes = length & 0x3; + + status = BMILZStreamStart (device, address, scn); + if (A_FAILED(status)) { + return A_ERROR; + } + + if (unalignedBytes) { + /* copy the last word into a zero padded buffer */ + A_MEMCPY(&lastWord, &buffer[lastWordOffset], unalignedBytes); + } + + status = BMILZData(device, buffer, lastWordOffset, scn); + + if (A_FAILED(status)) { + return A_ERROR; + } + + if (unalignedBytes) { + status = BMILZData(device, (A_UINT8 *)&lastWord, 4, scn); + } + + if (A_SUCCESS(status)) { + // + // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. + // + status = BMILZStreamStart (device, 0x00, scn); + if (A_FAILED(status)) { + return A_ERROR; + } + } + return status; +} + +A_STATUS +BMInvramProcess(HIF_DEVICE *device, A_UCHAR *seg_name, A_UINT32 *retval, + struct ol_softc *scn) +{ + A_UINT32 cid; + A_STATUS status; + A_UINT32 offset; + A_UINT32 retvalLen; + A_UCHAR *pBMICmdBuf = scn->pBMICmdBuf; + A_UCHAR *pBMIRspBuf = scn->pBMIRspBuf; + + ASSERT(BMI_COMMAND_FITS(sizeof(cid) + BMI_NVRAM_SEG_NAME_SZ)); + + if (scn->bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI NVRAM Process: Enter (device: 0x%p, name: %s)\n", + device, seg_name)); + + cid = BMI_NVRAM_PROCESS; + offset = 0; + A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + A_MEMCPY(&(pBMICmdBuf[offset]), seg_name, BMI_NVRAM_SEG_NAME_SZ); + offset += BMI_NVRAM_SEG_NAME_SZ; + retvalLen = sizeof(*retval); + status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMIRspBuf, &retvalLen, 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to access the device\n")); + return A_ERROR; + } + + A_MEMCPY(retval, pBMIRspBuf, sizeof(*retval)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI NVRAM Process: Exit\n")); + + return A_OK; +} + +#ifdef HIF_MESSAGE_BASED + +/* TODO.. stubs.. for message-based HIFs, the RAW access APIs need to be changed + */ + +A_STATUS +BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length) +{ + /* TODO */ + return A_ERROR; +} + +A_STATUS +BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout) +{ + /* TODO */ + return A_ERROR; +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi_internal.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi_internal.h new file mode 100644 index 000000000000..5f5d775bcdc0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/bmi_internal.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef BMI_INTERNAL_H +#define BMI_INTERNAL_H + +#include +//#include "a_config.h" +#include "athdefs.h" +#include "a_types.h" +#include "osapi_linux.h" +#define ATH_MODULE_NAME bmi +#include "a_debug.h" +#include "bmi_msg.h" + +#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) + +/* ------ Global Variable Declarations ------- */ +//A_BOOL bmiDone; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/fw_one_bin.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/fw_one_bin.h new file mode 100644 index 000000000000..4f7c40cb2242 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/fw_one_bin.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * fw_one_bin.h + */ + +#ifndef FW_ONE_BIN_H_ +#define FW_ONE_BIN_H_ + +/* Firmware Single Binary Magic Number */ +#define ONE_BIN_MAGIC_NUM ('Q' | 'C' << 8 | 'A' << 16 | 'W' << 24) + +/* Format version */ +#define ONE_BIN_FORMAT_MAJOR 0x1 +#define ONE_BIN_FORMAT_MINOR 0 +#define ONE_BIN_FORMAT_VER (ONE_BIN_FORMAT_MAJOR << 16 | ONE_BIN_FORMAT_MINOR) + +/* CHIP ID */ +#define AR6320_1_0_CHIP_ID 0x5000000 +#define AR6320_1_1_CHIP_ID 0x5000001 +#define AR6320_1_3_CHIP_ID 0x5000003 +#define AR6320_2_0_CHIP_ID 0x5010000 + +/* WLAN BINARY_ID */ +#define WLAN_SETUP_BIN_ID 0x01 +#define WLAN_OTP_BIN_ID 0x02 +#define WLAN_ATHWLAN_BIN_ID 0x0F + +/* UTF BINARY_ID */ +#define UTF_SETUP_BIN_ID 0x10 +#define UTF_OTP_BIN_ID 0x20 +#define UTF_UTF_BIN_ID 0xF0 + +/* BINARY_GROUP_ID */ +#define WLAN_GROUP_ID 0x80000000 +#define UTF_GROUP_ID 0x40000000 + +/* ACTION */ +#define ACTION_PARSE_SIG 0x80000000 /* parse signature */ +#define ACTION_DOWNLOAD 0x1 /* download only */ +#define ACTION_DOWNLOAD_EXEC 0x3 /* download binary and execute */ + +/* Binary Meta Header */ +typedef struct { + unsigned int magic_num; /* = ONE_BIN_MAGIC_NUM */ + unsigned int total_len; /* single binary file length */ + unsigned int format_ver; /* single binary format version */ + unsigned int fst_tag_off; /* offset of the first binary's CHIP_ID */ +} FW_ONE_BIN_META_T; + +/* Binary description header */ +typedef struct { + unsigned int chip_id; /* CHIP_ID */ + unsigned int binary_id; /* BINARY_ID */ + unsigned int bin_group_id; /* BINARY_GROUP_ID */ + unsigned int next_tag_off; /* Offset of the next binary's CHIP_ID */ + unsigned int binary_off; /* Offset of binary */ + unsigned int binary_len; /* Length of binary */ + unsigned int action; /* Action of binary operation */ + unsigned int reserved; /* 0, reserved */ +} FW_BIN_HEADER_T; + +#endif /* FW_ONE_BIN_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c new file mode 100644 index 000000000000..69b3152c8e98 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c @@ -0,0 +1,2717 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include "ol_if_athvar.h" +#include "ol_fw.h" +#include "targaddrs.h" +#include "bmi.h" +#include "ol_cfg.h" +#include "vos_api.h" +#include "wma_api.h" +#include "wma.h" +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#else +#include "if_ath_sdio.h" +#include "regtable.h" +#endif + +#define ATH_MODULE_NAME bmi +#include "a_debug.h" +#include "fw_one_bin.h" +#include "bin_sig.h" +#include "ar6320v2_dbg_regtable.h" +#include "epping_main.h" +#if defined(CONFIG_CNSS) +#include +#endif + +#ifndef REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "pktlog_ac.h" +#endif + +#include "qwlan_version.h" + +#ifdef FEATURE_SECURE_FIRMWARE +static struct hash_fw fw_hash; +#endif + +#if defined(HIF_PCI) || defined(HIF_SDIO) +static u_int32_t refclk_speed_to_hz[] = { + 48000000, /* SOC_REFCLK_48_MHZ */ + 19200000, /* SOC_REFCLK_19_2_MHZ */ + 24000000, /* SOC_REFCLK_24_MHZ */ + 26000000, /* SOC_REFCLK_26_MHZ */ + 37400000, /* SOC_REFCLK_37_4_MHZ */ + 38400000, /* SOC_REFCLK_38_4_MHZ */ + 40000000, /* SOC_REFCLK_40_MHZ */ + 52000000, /* SOC_REFCLK_52_MHZ */ +}; +#endif + +#ifdef HIF_SDIO +static struct ol_fw_files FW_FILES_QCA6174_FW_1_1 = { + "qwlan11.bin", "bdwlan11.bin", "otp11.bin", "utf11.bin", + "utfbd11.bin", "qsetup11.bin", "epping11.bin"}; +static struct ol_fw_files FW_FILES_QCA6174_FW_2_0 = { + "qwlan20.bin", "bdwlan20.bin", "otp20.bin", "utf20.bin", + "utfbd20.bin", "qsetup20.bin", "epping20.bin"}; +static struct ol_fw_files FW_FILES_QCA6174_FW_1_3 = { + "qwlan13.bin", "bdwlan13.bin", "otp13.bin", "utf13.bin", + "utfbd13.bin", "qsetup13.bin", "epping13.bin"}; +static struct ol_fw_files FW_FILES_QCA6174_FW_3_0 = { + "qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin", + "utfbd30.bin", "qsetup30.bin", "epping30.bin"}; +static struct ol_fw_files FW_FILES_DEFAULT = { + "qwlan.bin", "bdwlan.bin", "otp.bin", "utf.bin", + "utfbd.bin", "qsetup.bin", "epping.bin"}; + +static A_STATUS ol_sdio_extra_initialization(struct ol_softc *scn); + +static int ol_get_fw_files_for_target(struct ol_fw_files *pfw_files, + u32 target_version) +{ + if (!pfw_files) + return -ENODEV; + + switch (target_version) { + case AR6320_REV1_VERSION: + case AR6320_REV1_1_VERSION: + memcpy(pfw_files, &FW_FILES_QCA6174_FW_1_1, sizeof(*pfw_files)); + break; + case AR6320_REV1_3_VERSION: + memcpy(pfw_files, &FW_FILES_QCA6174_FW_1_3, sizeof(*pfw_files)); + break; + case AR6320_REV2_1_VERSION: + memcpy(pfw_files, &FW_FILES_QCA6174_FW_2_0, sizeof(*pfw_files)); + break; + case AR6320_REV3_VERSION: + case AR6320_REV3_2_VERSION: + case QCA9377_REV1_1_VERSION: + memcpy(pfw_files, &FW_FILES_QCA6174_FW_3_0, sizeof(*pfw_files)); + break; + default: + memcpy(pfw_files, &FW_FILES_DEFAULT, sizeof(*pfw_files)); + pr_err("%s version mismatch 0x%X ", + __func__, target_version); + break; + } + return 0; +} +#endif + +#ifdef HIF_USB +static A_STATUS ol_usb_extra_initialization(struct ol_softc *scn); +#endif + +extern int +dbglog_parse_debug_logs(ol_scn_t scn, u_int8_t *datap, u_int32_t len); + +static int ol_transfer_single_bin_file(struct ol_softc *scn, + u_int32_t address, + bool compressed) +{ + int status = EOK; + const char *filename = AR61X4_SINGLE_FILE; + const struct firmware *fw_entry; + u_int32_t fw_entry_size; + u_int8_t *temp_eeprom = NULL; + FW_ONE_BIN_META_T *one_bin_meta_header = NULL; + FW_BIN_HEADER_T *one_bin_header = NULL; + SIGN_HEADER_T *sign_header = NULL; + unsigned char *fw_entry_data = NULL; + u_int32_t groupid = WLAN_GROUP_ID; + u_int32_t binary_offset = 0; + u_int32_t binary_len = 0; + u_int32_t next_tag_offset = 0; + u_int32_t param = 0; + bool meta_header = FALSE; + bool fw_sign = FALSE; + bool is_group = FALSE; + +#ifdef QCA_WIFI_FTM + if (vos_get_conparam() == VOS_FTM_MODE) + groupid = UTF_GROUP_ID; +#endif + + if (groupid == WLAN_GROUP_ID) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("%s: Downloading mission mode firmware\n", + __func__)); + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("%s: Downloading test mode firmware\n", + __func__)); + } + + if (request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Failed to get %s\n", + __func__, filename)); + return -ENOENT; + } + + if (!fw_entry) { + return A_ERROR; + } + fw_entry_size = fw_entry->size; + fw_entry_data = (unsigned char *)fw_entry->data; + binary_len = fw_entry_size; + + temp_eeprom = OS_MALLOC(scn->sc_osdev, fw_entry_size, GFP_ATOMIC); + if (!temp_eeprom) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Memory allocation failed\n", + __func__)); + release_firmware(fw_entry); + return A_ERROR; + } + + OS_MEMCPY(temp_eeprom, (u_int8_t *)fw_entry->data, fw_entry_size); + + is_group = FALSE; + do { + if (!meta_header) { + if (fw_entry_size <= sizeof(FW_ONE_BIN_META_T) + + sizeof(FW_BIN_HEADER_T)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: file size error!\n", + __func__)); + status = A_ERROR; + goto exit; + } + + one_bin_meta_header = (FW_ONE_BIN_META_T*)fw_entry_data; + if (one_bin_meta_header->magic_num != ONE_BIN_MAGIC_NUM) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: one binary magic num err: %d\n", + __func__, + one_bin_meta_header->magic_num)); + status = A_ERROR; + goto exit; + } + if (one_bin_meta_header->fst_tag_off + + sizeof(FW_BIN_HEADER_T) >= fw_entry_size) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: one binary first tag offset error: %d\n", + __func__, one_bin_meta_header->fst_tag_off)); + status = A_ERROR; + goto exit; + } + + one_bin_header = (FW_BIN_HEADER_T *)( + (u_int8_t *)fw_entry_data + + one_bin_meta_header->fst_tag_off); + + while (one_bin_header->bin_group_id != groupid) + { + if (one_bin_header->next_tag_off + + sizeof(FW_BIN_HEADER_T) > fw_entry_size) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: tag offset is error: bin id: %d, bin len: %d, tag offset: %d \n", + __func__, one_bin_header->binary_id, + one_bin_header->binary_len, + one_bin_header->next_tag_off)); + status = A_ERROR; + goto exit; + } + + one_bin_header = (FW_BIN_HEADER_T *)( + (u_int8_t *)fw_entry_data + + one_bin_header->next_tag_off); + } + + meta_header = TRUE; + } + + binary_offset = one_bin_header->binary_off; + binary_len = one_bin_header->binary_len; + next_tag_offset = one_bin_header->next_tag_off; + + if (one_bin_header->action & ACTION_PARSE_SIG) + fw_sign = TRUE; + else + fw_sign = FALSE; + + if (fw_sign) + { + if (binary_len < sizeof(SIGN_HEADER_T)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: sign header size is error: bin id: %d, bin len: %d, sign header size: %zu \n", + __func__, one_bin_header->binary_id, + one_bin_header->binary_len, + sizeof(SIGN_HEADER_T))); + status = A_ERROR; + goto exit; + } + sign_header = (SIGN_HEADER_T *)((u_int8_t *)fw_entry_data + + binary_offset); + + status = BMISignStreamStart(scn->hif_hdl, address, + (u_int8_t *)fw_entry_data + + binary_offset, + sizeof(SIGN_HEADER_T), scn); + if (status != EOK) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: unable to start sign stream\n", + __func__)); + status = A_ERROR; + goto exit; + } + + binary_offset += sizeof(SIGN_HEADER_T); + binary_len = sign_header->rampatch_len + - sizeof(SIGN_HEADER_T); + } + + if (compressed) + status = BMIFastDownload(scn->hif_hdl, address, + (u_int8_t *)fw_entry_data + + binary_offset, + binary_len, scn); + else + status = BMIWriteMemory(scn->hif_hdl, address, + (u_int8_t *)fw_entry_data + + binary_offset, + binary_len, scn); + + if (fw_sign) + { + binary_offset += binary_len; + binary_len = sign_header->total_len + - sign_header->rampatch_len; + + if (binary_len > 0) + { + status = BMISignStreamStart(scn->hif_hdl, 0, + (u_int8_t *)fw_entry_data + + binary_offset, + binary_len, scn); + if (status != EOK) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s:sign stream error\n", + __func__)); + } + } + } + + if ((one_bin_header->action & ACTION_DOWNLOAD_EXEC) + == ACTION_DOWNLOAD_EXEC) + { + param = 0; + BMIExecute(scn->hif_hdl, address, ¶m, scn); + } + + if ((next_tag_offset) > 0 && + (one_bin_header->bin_group_id == groupid)) + { + one_bin_header = (FW_BIN_HEADER_T *)( + (u_int8_t *)fw_entry_data + + one_bin_header->next_tag_off); + if (one_bin_header->bin_group_id == groupid) + is_group = TRUE; + else + is_group = FALSE; + } + else { + is_group = FALSE; + } + + if (!is_group) + next_tag_offset = 0; + + } while (next_tag_offset > 0); + +exit: + if (temp_eeprom) + OS_FREE(temp_eeprom); + + if (status != EOK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMI operation failed: %d\n", __LINE__)); + release_firmware(fw_entry); + return -1; + } + + release_firmware(fw_entry); + + return status; +} + +#ifdef FEATURE_SECURE_FIRMWARE +static int ol_check_fw_hash(const u8* data, u32 fw_size, ATH_BIN_FILE file) +{ + u8 *fw_mem = NULL; + u8 *hash = NULL; +#ifdef CONFIG_CNSS + u8 digest[SHA256_DIGEST_SIZE]; +#endif + u8 temp[SHA256_DIGEST_SIZE] = {}; + int ret = 0; + + switch(file) { + case ATH_BOARD_DATA_FILE: + hash = fw_hash.bdwlan; + break; + case ATH_OTP_FILE: + hash = fw_hash.otp; + break; + case ATH_FIRMWARE_FILE: +#ifdef QCA_WIFI_FTM + if (vos_get_conparam() == VOS_FTM_MODE) { + hash = fw_hash.utf; + break; + } +#endif + hash = fw_hash.qwlan; + default: + break; + } + + if (!hash) { + pr_err("No entry for file:%d Download FW in non-secure mode\n", file); + goto end; + } + + if (!OS_MEMCMP(hash, temp, SHA256_DIGEST_SIZE)) { + pr_err("Download FW in non-secure mode:%d\n", file); + goto end; + } + + fw_mem = (u8 *)cnss_get_fw_ptr(); + + if (!fw_mem || (fw_size > MAX_FIRMWARE_SIZE)) { + pr_err("No enough memory to copy FW data\n"); + ret = A_ERROR; + goto end; + } + + OS_MEMCPY(fw_mem, data, fw_size); + +#ifdef CONFIG_CNSS + ret = cnss_get_sha_hash(fw_mem, fw_size, "sha256", digest); + + if (ret) { + pr_err("Sha256 Hash computation fialed err:%d\n", ret); + goto end; + } + + if (OS_MEMCMP(hash, digest, SHA256_DIGEST_SIZE) != 0) { + pr_err("Hash Mismatch"); + vos_trace_hex_dump(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + digest, SHA256_DIGEST_SIZE); + vos_trace_hex_dump(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + hash, SHA256_DIGEST_SIZE); + ret = A_ERROR; + } +#endif +end: + return ret; +} +#endif + +/** + * ol_board_id_to_filename() - Auto BDF board_id to filename conversion + * @scn: ol_softc structure for board_id and chip_id info + * @board_file: o/p filename based on board_id and chip_id + * + * The API return board filename based on the board_id and chip_id. + * eg: input = "bdwlan30.bin", board_id = 0x01, board_file = "bdwlan30.b01" + * Return: The buffer with the formated board filename. + */ + +#if (defined(CONFIG_CNSS) || defined(HIF_SDIO)) +static char *ol_board_id_to_filename(struct ol_softc *scn, uint16_t board_id) +{ + int input_len; + const char *input; + char *dest = NULL; + + if (vos_get_conparam() == VOS_FTM_MODE) + input = scn->fw_files.utf_board_data; + else + input = scn->fw_files.board_data; + + dest = kstrdup(input, GFP_KERNEL); + + if (!dest) + goto out; + + input_len = adf_os_str_len(input); + + if (board_id > 0xFF) + board_id = 0x0; + + snprintf(&dest[input_len - 2], 3, "%.2x", board_id); +out: + return dest; +} +#else +static char *ol_board_id_to_filename(struct ol_softc *scn, uint16_t board_id) +{ + return kstrdup(QCA_BOARD_DATA_FILE, GFP_KERNEL); +} +#endif + +static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, + u_int32_t address, bool compressed) +{ + int status = EOK; + const char *filename = NULL; + const struct firmware *fw_entry; + u_int32_t fw_entry_size; + u_int8_t *tempEeprom; + u_int32_t board_data_size; +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bool bin_sign = FALSE; + int bin_off, bin_len; + SIGN_HEADER_T *sign_header; +#endif + int ret; + char *bd_id_filename = NULL; + + if (scn->enablesinglebinary && file != ATH_BOARD_DATA_FILE) { + /* + * Fallback to load split binaries if single binary is not found + */ + ret = ol_transfer_single_bin_file(scn, + address, + compressed); + + if (!ret) + return ret; + + if (ret != -ENOENT) + return -1; + } + + switch (file) { + default: + printk("%s: Unknown file type\n", __func__); + return -1; + case ATH_OTP_FILE: +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) + filename = scn->fw_files.otp_data; +#else + filename = QCA_OTP_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = TRUE; +#endif + break; + case ATH_FIRMWARE_FILE: + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) + filename = scn->fw_files.epping_file; +#else + filename = QCA_FIRMWARE_EPPING_FILE; +#endif + printk(KERN_INFO "%s: Loading epping firmware file %s\n", + __func__, filename); + break; + } +#ifdef QCA_WIFI_FTM + if (vos_get_conparam() == VOS_FTM_MODE) { +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) + filename = scn->fw_files.utf_file; +#else + filename = QCA_UTF_FIRMWARE_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = TRUE; +#endif + printk(KERN_INFO "%s: Loading firmware file %s\n", + __func__, filename); + break; + } +#endif +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) + filename = scn->fw_files.image_file; +#else + filename = QCA_FIRMWARE_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = TRUE; +#endif + break; + case ATH_PATCH_FILE: + printk("%s: no Patch file defined\n", __func__); + return EOK; + case ATH_BOARD_DATA_FILE: + bd_id_filename = ol_board_id_to_filename(scn, scn->board_id); + if (bd_id_filename) + filename = bd_id_filename; + else { + pr_err("%s: No memory to allocate board filename\n", + __func__); + return -1; + } + +#ifdef QCA_WIFI_FTM + if (vos_get_conparam() == VOS_FTM_MODE) { +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = TRUE; +#endif + printk(KERN_INFO "%s: Loading board data file %s\n", + __func__, filename); + break; + } +#endif /* QCA_WIFI_FTM */ + +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = FALSE; +#endif + break; + case ATH_SETUP_FILE: + if (vos_get_conparam() != VOS_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { +#ifdef CONFIG_CNSS + printk("%s: no Setup file defined\n", __func__); + return -1; +#else +#ifdef HIF_SDIO + filename = scn->fw_files.setup_file; +#else + filename = QCA_SETUP_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = TRUE; +#endif + printk(KERN_INFO "%s: Loading setup file %s\n", + __func__, filename); +#endif /* CONFIG_CNSS */ + } else { + printk("%s: no Setup file needed\n", __func__); + return -1; + } + break; + } + + if (request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) + { + pr_err("%s: Failed to get %s\n", __func__, filename); + + if (file == ATH_OTP_FILE) + return -ENOENT; + +#if (defined(CONFIG_CNSS) || defined(HIF_SDIO)) + + if (file == ATH_BOARD_DATA_FILE) { + if (strcmp(filename, scn->fw_files.board_data)) + filename = scn->fw_files.board_data; + else { + kfree(bd_id_filename); + return -1; + } + + pr_info("%s: Trying to load default %s\n", + __func__, filename); + + if (request_firmware(&fw_entry, filename, + scn->sc_osdev->device) != 0) { + pr_err("%s: Failed to get %s\n", + __func__, filename); + kfree(bd_id_filename); + return -1; + } + } else + return -1; +#else + kfree(bd_id_filename); + return -1; +#endif + } + + if (!fw_entry || !fw_entry->data) { + pr_err("%s: Invalid fw_entries\n", __func__); + if (bd_id_filename) + kfree(bd_id_filename); + return A_ERROR; + } + + fw_entry_size = fw_entry->size; + tempEeprom = NULL; + +#ifdef FEATURE_SECURE_FIRMWARE + if (scn->enable_fw_hash_check && + ol_check_fw_hash(fw_entry->data, fw_entry_size, file)) { + pr_err("Hash Check failed for file:%s\n", filename); + status = A_ERROR; + goto end; + } +#endif + + if (file == ATH_BOARD_DATA_FILE) + { + u_int32_t board_ext_address; + int32_t board_ext_data_size; + + tempEeprom = OS_MALLOC(scn->sc_osdev, fw_entry_size, GFP_ATOMIC); + if (!tempEeprom) { + pr_err("%s: Memory allocation failed\n", __func__); + status = A_NO_MEMORY; + goto release_fw; + } + + OS_MEMCPY(tempEeprom, (u_int8_t *)fw_entry->data, fw_entry_size); + + switch (scn->target_type) { + default: + board_data_size = 0; + board_ext_data_size = 0; + break; + case TARGET_TYPE_AR6004: + board_data_size = AR6004_BOARD_DATA_SZ; + board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ; + case TARGET_TYPE_AR9888: + board_data_size = AR9888_BOARD_DATA_SZ; + board_ext_data_size = AR9888_BOARD_EXT_DATA_SZ; + break; + } + + /* Determine where in Target RAM to write Board Data */ + BMIReadMemory(scn->hif_hdl, + HOST_INTEREST_ITEM_ADDRESS(scn->target_type, hi_board_ext_data), + (u_int8_t *)&board_ext_address, 4, scn); + printk("Board extended Data download address: 0x%x\n", board_ext_address); + + /* + * Check whether the target has allocated memory for extended board + * data and file contains extended board data + */ + if ((board_ext_address) && (fw_entry_size == (board_data_size + board_ext_data_size))) + { + u_int32_t param; + + status = BMIWriteMemory(scn->hif_hdl, board_ext_address, + (u_int8_t *)(tempEeprom + board_data_size), board_ext_data_size, scn); + + if (status != EOK) + goto end; + + /* Record the fact that extended board Data IS initialized */ + param = (board_ext_data_size << 16) | 1; + BMIWriteMemory(scn->hif_hdl, + HOST_INTEREST_ITEM_ADDRESS(scn->target_type, hi_board_ext_data_config), + (u_int8_t *)¶m, 4, scn); + + fw_entry_size = board_data_size; + } + } + +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + if (bin_sign) { + u_int32_t chip_id; + + if (fw_entry_size < sizeof(SIGN_HEADER_T)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Invalid binary size %d\n", __func__, + fw_entry_size)); + status = A_ERROR; + goto end; + } + + sign_header = (SIGN_HEADER_T *)fw_entry->data; + chip_id = cpu_to_le32(sign_header->product_id); + if (sign_header->magic_num == SIGN_HEADER_MAGIC + && (chip_id == AR6320_REV1_1_VERSION + || chip_id == AR6320_REV1_3_VERSION + || chip_id == AR6320_REV2_1_VERSION)) { + + status = BMISignStreamStart(scn->hif_hdl, address, + (u_int8_t *)fw_entry->data, + sizeof(SIGN_HEADER_T), scn); + if (status != EOK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: unable to start sign stream\n", + __func__)); + status = A_ERROR; + goto end; + } + + bin_off = sizeof(SIGN_HEADER_T); + bin_len = sign_header->rampatch_len + - sizeof(SIGN_HEADER_T); + } else { + bin_sign = FALSE; + bin_off = 0; + bin_len = fw_entry_size; + } + } else { + bin_len = fw_entry_size; + bin_off = 0; + } + + if (compressed) { + status = BMIFastDownload(scn->hif_hdl, address, + (u_int8_t *)fw_entry->data + bin_off, + bin_len, scn); + } else { + if (file == ATH_BOARD_DATA_FILE && fw_entry->data) { + status = BMIWriteMemory(scn->hif_hdl, address, + (u_int8_t *)tempEeprom, + fw_entry_size, scn); + } else { + status = BMIWriteMemory(scn->hif_hdl, address, + (u_int8_t *)fw_entry->data + + bin_off, + bin_len, scn); + } + } + + if (bin_sign) { + bin_off += bin_len; + bin_len = sign_header->total_len + - sign_header->rampatch_len; + + if (bin_len > 0) { + status = BMISignStreamStart(scn->hif_hdl, 0, + (u_int8_t *)fw_entry->data + bin_off, + bin_len, scn); + if (status != EOK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s:sign stream error\n", + __func__)); + } + } + } +#else + if (compressed) { + status = BMIFastDownload(scn->hif_hdl, address, + (u_int8_t *)fw_entry->data, + fw_entry_size, scn); + } else { + if (file == ATH_BOARD_DATA_FILE && fw_entry->data) { + status = BMIWriteMemory(scn->hif_hdl, address, + (u_int8_t *)tempEeprom, + fw_entry_size, scn); + } else { + status = BMIWriteMemory(scn->hif_hdl, address, + (u_int8_t *)fw_entry->data, + fw_entry_size, scn); + } + } +#endif /* QCA_SIGNED_SPLIT_BINARY_SUPPORT */ + +end: + if (tempEeprom) { + OS_FREE(tempEeprom); + } + + if (status != EOK) { + pr_err("%s, BMI operation failed: %d\n", __func__, __LINE__); + goto release_fw; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: transferring file: %s size %d bytes done!", __func__, + (filename!=NULL)?filename:"", fw_entry_size); + +release_fw: + release_firmware(fw_entry); + + if (bd_id_filename) + kfree(bd_id_filename); + + return status; +} + +static int ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, + u_int32_t address, bool compressed) +{ + int ret; + +#ifdef CONFIG_CNSS + /* Wait until suspend and resume are completed before loading FW */ + cnss_lock_pm_sem(); +#endif + + ret = __ol_transfer_bin_file(scn, file, address, compressed); + +#ifdef CONFIG_CNSS + cnss_release_pm_sem(); +#endif + + return ret; +} + +u_int32_t host_interest_item_address(u_int32_t target_type, u_int32_t item_offset) +{ + switch (target_type) { + default: + ASSERT(0); + case TARGET_TYPE_AR6002: + return (AR6002_HOST_INTEREST_ADDRESS + item_offset); + case TARGET_TYPE_AR6003: + return (AR6003_HOST_INTEREST_ADDRESS + item_offset); + case TARGET_TYPE_AR6004: + return (AR6004_HOST_INTEREST_ADDRESS + item_offset); + case TARGET_TYPE_AR6006: + return (AR6006_HOST_INTEREST_ADDRESS + item_offset); + case TARGET_TYPE_AR9888: + return (AR9888_HOST_INTEREST_ADDRESS + item_offset); + case TARGET_TYPE_AR6320: + case TARGET_TYPE_AR6320V2: + return (AR6320_HOST_INTEREST_ADDRESS + item_offset); + } +} + +#ifdef HIF_PCI +int dump_CE_register(struct ol_softc *scn) +{ +#ifdef HIF_USB + struct hif_usb_softc *sc = scn->hif_sc; +#else + struct hif_pci_softc *sc = scn->hif_sc; +#endif + A_UINT32 CE_reg_address = CE0_BASE_ADDRESS; + A_UINT32 CE_reg_values[8][CE_USEFUL_SIZE>>2]; + A_UINT32 CE_reg_word_size = CE_USEFUL_SIZE>>2; + A_UINT16 i, j; + + for(i = 0; i < 8; i++, CE_reg_address += CE_OFFSET) { + if (HIFDiagReadMem(scn->hif_hdl, CE_reg_address, + (A_UCHAR*)&CE_reg_values[i][0], + CE_reg_word_size * sizeof(A_UINT32)) != A_OK) + { + printk(KERN_ERR "Dumping CE register failed!\n"); + return -EACCES; + } + } + + for (i = 0; i < 8; i++) { + printk("CE%d Registers:\n", i); + for (j = 0; j < CE_reg_word_size; j++) { + printk("0x%08x ", CE_reg_values[i][j]); + if (!((j+1)%5) || (CE_reg_word_size - 1) == j) + printk("\n"); + } + } + + return EOK; +} +#endif + +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) +static struct ol_softc *ramdump_scn; +#ifdef TARGET_DUMP_FOR_NON_QC_PLATFORM +void *ol_fw_dram_addr=NULL; +void *ol_fw_iram_addr=NULL; +void *ol_fw_axi_addr=NULL; +u_int32_t ol_fw_dram_size; +u_int32_t ol_fw_iram_size; +u_int32_t ol_fw_axi_size; +#endif + +int ol_copy_ramdump(struct ol_softc *scn) +{ + int ret; + + if (!scn->ramdump_base || !scn->ramdump_size) { + pr_info("%s: No RAM dump will be collected since ramdump_base " + "is NULL or ramdump_size is 0!\n", __func__); + ret = -EACCES; + goto out; + } + + ret = ol_target_coredump(scn, scn->ramdump_base, scn->ramdump_size); + +out: + return ret; +} + +static void ramdump_work_handler(struct work_struct *ramdump) +{ +#if !defined(HIF_SDIO) + int ret; +#endif + u_int32_t host_interest_address; + u_int32_t dram_dump_values[4]; +#ifdef TARGET_DUMP_FOR_NON_QC_PLATFORM + u_int8_t *byte_ptr; +#endif + + if (!ramdump_scn) { + printk("No RAM dump will be collected since ramdump_scn is NULL!\n"); + goto out_fail; + } +#if !defined(HIF_SDIO) +#ifdef DEBUG + ret = hif_pci_check_soc_status(ramdump_scn->hif_sc); + if (ret) + goto out_fail; + + ret = dump_CE_register(ramdump_scn); + if (ret) + goto out_fail; + + dump_CE_debug_register(ramdump_scn->hif_sc); +#endif +#endif + + if (HIFDiagReadMem(ramdump_scn->hif_hdl, + host_interest_item_address(ramdump_scn->target_type, + offsetof(struct host_interest_s, hi_failure_state)), + (A_UCHAR *)&host_interest_address, sizeof(u_int32_t)) != A_OK) { + printk(KERN_ERR "HifDiagReadiMem FW Dump Area Pointer failed!\n"); +#if !defined(HIF_SDIO) + ol_copy_ramdump(ramdump_scn); + cnss_device_crashed(); + return; +#endif + goto out_fail; + } + printk("Host interest item address: 0x%08x\n", host_interest_address); + + if (HIFDiagReadMem(ramdump_scn->hif_hdl, host_interest_address, + (A_UCHAR *)&dram_dump_values[0], 4 * sizeof(u_int32_t)) != A_OK) + { + printk("HifDiagReadiMem FW Dump Area failed!\n"); + goto out_fail; + } + printk("FW Assertion at PC: 0x%08x BadVA: 0x%08x TargetID: 0x%08x\n", + dram_dump_values[2], dram_dump_values[3], dram_dump_values[0]); + +#ifdef TARGET_DUMP_FOR_NON_QC_PLATFORM + /* Allocate memory to save ramdump */ + if (ramdump_scn->enableFwSelfRecovery) { + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE); +#if defined(HIF_SDIO) && defined(WLAN_OPEN_SOURCE) + kobject_uevent(&ramdump_scn->adf_dev->dev->kobj, KOBJ_OFFLINE); +#endif + goto out_fail; + } + + ramdump_scn->ramdump_size = DRAM_SIZE + IRAM_SIZE + AXI_SIZE; + ramdump_scn->ramdump_base = + kmalloc(ramdump_scn->ramdump_size, GFP_KERNEL); + + if (!ramdump_scn->ramdump_base) { + pr_err("%s: fail to alloc mem for FW RAM dump\n", + __func__); + goto out_fail; + } + + ol_fw_dram_size = DRAM_SIZE; + ol_fw_iram_size = IRAM_SIZE; + ol_fw_axi_size = AXI_SIZE; + ol_fw_dram_addr = ramdump_scn->ramdump_base; + byte_ptr = (u_int8_t *)ol_fw_dram_addr; + ol_fw_axi_addr = (void *)(byte_ptr + DRAM_SIZE); + ol_fw_iram_addr = (void *)(byte_ptr + DRAM_SIZE + AXI_SIZE); + + pr_err("%s: DRAM => mem = %#08x, len = %d\n", __func__, + (u_int32_t)ol_fw_dram_addr, DRAM_SIZE); + pr_err("%s: AXI => mem = %#08x, len = %d\n", __func__, + (u_int32_t)ol_fw_axi_addr, AXI_SIZE); + pr_err("%s: IRAM => mem = %#08x, len = %d\n", __func__, + (u_int32_t)ol_fw_iram_addr, IRAM_SIZE); +#endif + + if (ol_copy_ramdump(ramdump_scn)) + goto out_fail; + + printk("%s: RAM dump collecting completed!\n", __func__); + +#if defined(HIF_SDIO) + panic("CNSS Ram dump collected\n"); +#else + /* Notify SSR framework the target has crashed. */ + cnss_device_crashed(); +#endif + return; + +out_fail: + /* Silent SSR on dump failure */ +#if defined(CNSS_SELF_RECOVERY) || defined(TARGET_DUMP_FOR_NON_QC_PLATFORM) +#if !defined(HIF_SDIO) + cnss_device_self_recovery(); +#endif +#else + +#if defined(HIF_SDIO) + panic("CNSS Ram dump collection failed \n"); +#else + cnss_device_crashed(); +#endif +#endif + return; +} + +static DECLARE_WORK(ramdump_work, ramdump_work_handler); + +void ol_schedule_ramdump_work(struct ol_softc *scn) +{ + ramdump_scn = scn; + schedule_work(&ramdump_work); +} + +static void fw_indication_work_handler(struct work_struct *fw_indication) +{ +#if !defined(HIF_SDIO) + cnss_device_self_recovery(); +#endif +} + +static DECLARE_WORK(fw_indication_work, fw_indication_work_handler); + +void ol_schedule_fw_indication_work(struct ol_softc *scn) +{ + schedule_work(&fw_indication_work); +} +#endif + +#ifdef HIF_USB +/* Save memory addresses where we save FW ram dump, and then we could obtain + * them by symbol table. */ +A_UINT32 fw_stack_addr; +void *fw_ram_seg_addr[FW_RAM_SEG_CNT]; + +/* ol_ramdump_handler is to receive information of firmware crash dump, and + * save it in host memory. It consists of 5 parts: registers, call stack, + * DRAM dump, IRAM dump, and AXI dump, and they are reported to host in order. + * + * registers: wrapped in a USB packet by starting as FW_ASSERT_PATTERN and + * 60 registers. + * call stack: wrapped in multiple USB packets, and each of them starts as + * FW_REG_PATTERN and contains multiple double-words. The tail + * of the last packet is FW_REG_END_PATTERN. + * DRAM dump: wrapped in multiple USB pakcets, and each of them start as + * FW_RAMDUMP_PATTERN and contains multiple double-wors. The tail + * of the last packet is FW_RAMDUMP_END_PATTERN; + * IRAM dump and AXI dump are with the same format as DRAM dump. + */ +void ol_ramdump_handler(struct ol_softc *scn) +{ + A_UINT32 *reg, pattern, i, start_addr = 0; + A_UINT32 MSPId = 0, mSPId = 0, SIId = 0, CRMId = 0, len; + A_UINT8 *data; + A_UINT8 str_buf[128]; + A_UINT8 *ram_ptr = NULL; + A_UINT32 remaining; + char *fw_ram_seg_name[FW_RAM_SEG_CNT] = {"DRAM", "IRAM", "AXI"}; + + data = scn->hif_sc->fw_data; + len = scn->hif_sc->fw_data_len; + pattern = *((A_UINT32 *) data); + + if (pattern == FW_ASSERT_PATTERN) { + MSPId = (scn->target_fw_version & 0xf0000000) >> 28; + mSPId = (scn->target_fw_version & 0xf000000) >> 24; + SIId = (scn->target_fw_version & 0xf00000) >> 20; + CRMId = scn->target_fw_version & 0x7fff; + pr_err("Firmware crash detected...\n"); + pr_err("Host SW version: %s\n", QWLAN_VERSIONSTR); + pr_err("FW version: %d.%d.%d.%d", MSPId, mSPId, SIId, CRMId); + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + printk("%s: Loading/Unloading is in progress, ignore!\n", + __func__); + return; + } + + reg = (A_UINT32 *) (data + 4); + print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, 16, 4, reg, + min_t(A_UINT32, len - 4, FW_REG_DUMP_CNT * 4), + false); + scn->fw_ram_dumping = 0; + + if (scn->enableFwSelfRecovery) + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + } + else if (pattern == FW_REG_PATTERN) { + reg = (A_UINT32 *) (data + 4); + start_addr = *reg++; + if (scn->fw_ram_dumping == 0) { + pr_err("Firmware stack dump:"); + scn->fw_ram_dumping = 1; + fw_stack_addr = start_addr; + } + remaining = len - 8; + /* len is in byte, but it's printed in double-word. */ + for (i = 0; i < (len - 8); i += 16) { + if ((*reg == FW_REG_END_PATTERN) && (i == len - 12)) { + scn->fw_ram_dumping = 0; + pr_err("Stack start address = %#08x\n", + fw_stack_addr); + break; + } + hex_dump_to_buffer(reg, remaining, 16, 4, str_buf, + sizeof(str_buf), false); + pr_err("%#08x: %s\n", start_addr + i, str_buf); + remaining -= 16; + reg += 4; + } + } + else if ((!scn->enableFwSelfRecovery)&& + ((pattern & FW_RAMDUMP_PATTERN_MASK) == + FW_RAMDUMP_PATTERN)) { + VOS_ASSERT(scn->ramdump_index < FW_RAM_SEG_CNT); + i = scn->ramdump_index; + reg = (A_UINT32 *) (data + 4); + if (scn->fw_ram_dumping == 0) { + scn->fw_ram_dumping = 1; + pr_err("Firmware %s dump:\n", fw_ram_seg_name[i]); + scn->ramdump[i] = kmalloc(sizeof(struct fw_ramdump) + + FW_RAMDUMP_SEG_SIZE, + GFP_KERNEL); + if (!scn->ramdump[i]) { + pr_err("Fail to allocate memory for ram dump"); + VOS_BUG(0); + } + (scn->ramdump[i])->mem = + (A_UINT8 *) (scn->ramdump[i] + 1); + fw_ram_seg_addr[i] = (scn->ramdump[i])->mem; + pr_err("FW %s start addr = %#08x\n", + fw_ram_seg_name[i], *reg); + pr_err("Memory addr for %s = %p\n", + fw_ram_seg_name[i], + (scn->ramdump[i])->mem); + (scn->ramdump[i])->start_addr = *reg; + (scn->ramdump[i])->length = 0; + } + reg++; + ram_ptr = (scn->ramdump[i])->mem + (scn->ramdump[i])->length; + (scn->ramdump[i])->length += (len - 8); + memcpy(ram_ptr, (A_UINT8 *) reg, len - 8); + + if (pattern == FW_RAMDUMP_END_PATTERN) { + pr_err("%s memory size = %d\n", fw_ram_seg_name[i], + (scn->ramdump[i])->length); + if (i == (FW_RAM_SEG_CNT - 1)) { + VOS_BUG(0); + } + + scn->ramdump_index++; + scn->fw_ram_dumping = 0; + } + } +} +#endif + +#define REGISTER_DUMP_LEN_MAX 60 +#define REG_DUMP_COUNT 60 + +void ol_target_failure(void *instance, A_STATUS status) +{ + struct ol_softc *scn = (struct ol_softc *)instance; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); +#ifndef CONFIG_CNSS + A_UINT32 reg_dump_area = 0; + A_UINT32 reg_dump_values[REGISTER_DUMP_LEN_MAX]; + A_UINT32 reg_dump_cnt = 0; + A_UINT32 i; + A_UINT32 dbglog_hdr_address; + struct dbglog_hdr_host dbglog_hdr; + struct dbglog_buf_host dbglog_buf; + A_UINT8 *dbglog_data; +#else + int ret; +#endif + +#ifdef HIF_USB + /* Currently, only firmware crash triggers ol_target_failure. + In case, we need to dump RAM data. */ + if (status == A_USB_ERROR) { + ol_ramdump_handler(scn); + return; + } +#endif + + vos_event_set(&wma->recovery_event); + + if (OL_TRGET_STATUS_RESET == scn->target_status) { + printk("Target is already asserted, ignore!\n"); + return; + } + + scn->target_status = OL_TRGET_STATUS_RESET; + + if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + pr_info("%s: LOGP is in progress, ignore!\n", __func__); + return; + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + printk("%s: Loading/Unloading is in progress, ignore!\n", + __func__); + return; + } + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + +#ifdef CONFIG_CNSS + ret = hif_pci_check_fw_reg(scn->hif_sc); + if (0 == ret) { + if (scn->enable_self_recovery) { + ol_schedule_fw_indication_work(scn); + return; + } + } else if (-1 == ret) { + return; + } +#endif + + printk("XXX TARGET ASSERTED XXX\n"); + +#ifndef CONFIG_CNSS + if (HIFDiagReadMem(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_failure_state)), + (A_UCHAR *)®_dump_area, + sizeof(A_UINT32))!= A_OK) + { + printk("HifDiagReadiMem FW Dump Area Pointer failed\n"); + return; + } + + printk("Target Register Dump Location 0x%08X\n", reg_dump_area); + + reg_dump_cnt = REG_DUMP_COUNT; + + if (HIFDiagReadMem(scn->hif_hdl, + reg_dump_area, + (A_UCHAR*)®_dump_values[0], + reg_dump_cnt * sizeof(A_UINT32))!= A_OK) + { + printk("HifDiagReadiMem for FW Dump Area failed\n"); + return; + } + + printk("Target Register Dump\n"); + for (i = 0; i < reg_dump_cnt; i++) { + printk("[%02d] : 0x%08X\n", i, reg_dump_values[i]); + } + + if (!scn->enablefwlog) { + printk("%s: FWLog is disabled in ini\n", __func__); + goto disable_fwlog; + } + + if (HIFDiagReadMem(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_dbglog_hdr)), + (A_UCHAR *)&dbglog_hdr_address, + sizeof(dbglog_hdr_address))!= A_OK) + { + printk("HifDiagReadiMem FW dbglog_hdr_address failed\n"); + return; + } + + if (HIFDiagReadMem(scn->hif_hdl, + dbglog_hdr_address, + (A_UCHAR *)&dbglog_hdr, + sizeof(dbglog_hdr))!= A_OK) + { + printk("HifDiagReadiMem FW dbglog_hdr failed\n"); + return; + } + + if (HIFDiagReadMem(scn->hif_hdl, + (A_UINT32)dbglog_hdr.dbuf, + (A_UCHAR *)&dbglog_buf, + sizeof(dbglog_buf))!= A_OK) + { + printk("HifDiagReadiMem FW dbglog_buf failed\n"); + return; + } + + dbglog_data = adf_os_mem_alloc(scn->adf_dev, dbglog_buf.length + 4); + if (dbglog_data) { + if (HIFDiagReadMem(scn->hif_hdl, + (A_UINT32)dbglog_buf.buffer, + dbglog_data + 4, + dbglog_buf.length)!= A_OK) + { + printk("HifDiagReadiMem FW dbglog_data failed\n"); + } else { + printk("dbglog_hdr.dbuf=%u dbglog_data=%p dbglog_buf.buffer=%u dbglog_buf.length=%u\n", + dbglog_hdr.dbuf, dbglog_data, dbglog_buf.buffer, dbglog_buf.length); + + + OS_MEMCPY(dbglog_data, &dbglog_hdr.dropped, 4); + if (wma) { + wma->is_fw_assert = 1; + (void)dbglog_parse_debug_logs(wma, dbglog_data, dbglog_buf.length + 4); + } + } + + adf_os_mem_free(dbglog_data); + } + +disable_fwlog: +#endif + +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) + /* Collect the RAM dump through a workqueue */ + if (scn->enableRamdumpCollection) + ol_schedule_ramdump_work(scn); + else + printk("%s: athdiag read for target reg\n", __func__); +#endif + + return; +} + +int +ol_configure_target(struct ol_softc *scn) +{ + u_int32_t param; +#ifdef CONFIG_CNSS + struct cnss_platform_cap cap; +#endif + + /* Tell target which HTC version it is used*/ + param = HTC_PROTOCOL_VERSION; + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_app_host_interest)), + (u_int8_t *)¶m, + 4, scn)!= A_OK) + { + printk("BMIWriteMemory for htc version failed \n"); + return -1; + } + + /* set the firmware mode to STA/IBSS/AP */ + { + if (BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag)), + (A_UCHAR *)¶m, + 4, scn)!= A_OK) + { + printk("BMIReadMemory for setting fwmode failed \n"); + return A_ERROR; + } + + /* TODO following parameters need to be re-visited. */ + param |= (1 << HI_OPTION_NUM_DEV_SHIFT); //num_device + param |= (HI_OPTION_FW_MODE_AP << HI_OPTION_FW_MODE_SHIFT); //Firmware mode ?? + param |= (1 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); //mac_addr_method + param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); //firmware_bridge + param |= (0 << HI_OPTION_FW_SUBMODE_SHIFT); //fwsubmode + + printk("NUM_DEV=%d FWMODE=0x%x FWSUBMODE=0x%x FWBR_BUF %d\n", + 1, HI_OPTION_FW_MODE_AP, 0, 0); + + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag)), + (A_UCHAR *)¶m, + 4, scn) != A_OK) + { + printk("BMIWriteMemory for setting fwmode failed \n"); + return A_ERROR; + } + } + +#if defined(HIF_PCI) +#if (CONFIG_DISABLE_CDC_MAX_PERF_WAR) + { + /* set the firmware to disable CDC max perf WAR */ + if (BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag2)), + (A_UCHAR *)¶m, + 4, scn)!= A_OK) + { + printk("BMIReadMemory for setting cdc max perf failed \n"); + return A_ERROR; + } + + param |= HI_OPTION_DISABLE_CDC_MAX_PERF_WAR; + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag2)), + (A_UCHAR *)¶m, + 4, scn) != A_OK) + { + printk("BMIWriteMemory for setting cdc max perf failed \n"); + return A_ERROR; + } + } +#endif /* CONFIG_CDC_MAX_PERF_WAR */ + +#endif /*HIF_PCI*/ + +#ifdef CONFIG_CNSS + { + int ret; + + ret = cnss_get_platform_cap(&cap); + if (ret) + pr_err("platform capability info from CNSS not available\n"); + + if (!ret && cap.cap_flag & CNSS_HAS_EXTERNAL_SWREG) { + if (BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (A_UCHAR *)¶m, 4, scn)!= A_OK) { + printk("BMIReadMemory for setting external SWREG failed\n"); + return A_ERROR; + } + + param |= HI_OPTION_USE_EXT_LDO; + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (A_UCHAR *)¶m, 4, scn) != A_OK) { + printk("BMIWriteMemory for setting external SWREG failed\n"); + return A_ERROR; + } + } + } +#endif + +#ifdef WLAN_FEATURE_LPSS + if (scn->enablelpasssupport) { + if (BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (A_UCHAR *)¶m, 4, scn)!= A_OK) { + printk("BMIReadMemory for setting LPASS Support failed\n"); + return A_ERROR; + } + + param |= HI_OPTION_DBUART_SUPPORT; + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (A_UCHAR *)¶m, 4, scn) != A_OK) { + printk("BMIWriteMemory for setting LPASS Support failed\n"); + return A_ERROR; + } + } +#endif + + /* If host is running on a BE CPU, set the host interest area */ + { +#ifdef BIG_ENDIAN_HOST + param = 1; +#else + param = 0; +#endif + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_be)), + (A_UCHAR *)¶m, + 4, scn) != A_OK) + { + printk("BMIWriteMemory for setting host CPU BE mode failed \n"); + return A_ERROR; + } + } + + /* FW descriptor/Data swap flags */ + { + param = 0; + if (BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_fw_swap)), + (A_UCHAR *)¶m, + 4, scn) != A_OK) + { + printk("BMIWriteMemory for setting FW data/desc swap flags failed \n"); + return A_ERROR; + } + } + + return A_OK; +} + +static int +ol_check_dataset_patch(struct ol_softc *scn, u_int32_t *address) +{ + /* Check if patch file needed for this target type/version. */ + return 0; +} + +#if defined(HIF_PCI) || defined(HIF_SDIO) + +A_STATUS ol_fw_populate_clk_settings(A_refclk_speed_t refclk, + struct cmnos_clock_s *clock_s) +{ + if (!clock_s) + return A_ERROR; + + switch (refclk) { + case SOC_REFCLK_48_MHZ: + clock_s->wlan_pll.div = 0xE; + clock_s->wlan_pll.rnfrac = 0x2AAA8; + clock_s->pll_settling_time = 2400; + break; + case SOC_REFCLK_19_2_MHZ: + clock_s->wlan_pll.div = 0x24; + clock_s->wlan_pll.rnfrac = 0x2AAA8; + clock_s->pll_settling_time = 960; + break; + case SOC_REFCLK_24_MHZ: + clock_s->wlan_pll.div = 0x1D; + clock_s->wlan_pll.rnfrac = 0x15551; + clock_s->pll_settling_time = 1200; + break; + case SOC_REFCLK_26_MHZ: + clock_s->wlan_pll.div = 0x1B; + clock_s->wlan_pll.rnfrac = 0x4EC4; + clock_s->pll_settling_time = 1300; + break; + case SOC_REFCLK_37_4_MHZ: + clock_s->wlan_pll.div = 0x12; + clock_s->wlan_pll.rnfrac = 0x34B49; + clock_s->pll_settling_time = 1870; + break; + case SOC_REFCLK_38_4_MHZ: + clock_s->wlan_pll.div = 0x12; + clock_s->wlan_pll.rnfrac = 0x15551; + clock_s->pll_settling_time = 1920; + break; + case SOC_REFCLK_40_MHZ: + clock_s->wlan_pll.div = 0x11; + clock_s->wlan_pll.rnfrac = 0x26665; + clock_s->pll_settling_time = 2000; + break; + case SOC_REFCLK_52_MHZ: + clock_s->wlan_pll.div = 0x1B; + clock_s->wlan_pll.rnfrac = 0x4EC4; + clock_s->pll_settling_time = 2600; + break; + case SOC_REFCLK_UNKNOWN: + clock_s->wlan_pll.refdiv = 0; + clock_s->wlan_pll.div = 0; + clock_s->wlan_pll.rnfrac = 0; + clock_s->wlan_pll.outdiv = 0; + clock_s->pll_settling_time = 1024; + clock_s->refclk_hz = 0; + default: + return A_ERROR; + } + + clock_s->refclk_hz = refclk_speed_to_hz[refclk]; + clock_s->wlan_pll.refdiv = 0; + clock_s->wlan_pll.outdiv = 1; + + return A_OK; +} + +A_STATUS ol_patch_pll_switch(struct ol_softc * scn) +{ + HIF_DEVICE *hif_device = scn->hif_hdl; + A_STATUS status; + u_int32_t addr = 0; + u_int32_t reg_val = 0; + u_int32_t mem_val = 0; + struct cmnos_clock_s clock_s; + u_int32_t cmnos_core_clk_div_addr = 0; + u_int32_t cmnos_cpu_pll_init_done_addr = 0; + u_int32_t cmnos_cpu_speed_addr = 0; +#ifdef HIF_USB/* fail for USB case */ + struct hif_usb_softc *sc = scn->hif_sc; +#elif defined HIF_PCI + struct hif_pci_softc *sc = scn->hif_sc; +#else + struct ath_hif_sdio_softc *sc = scn->hif_sc; +#endif + + switch (scn->target_version) { + case AR6320_REV1_1_VERSION: + cmnos_core_clk_div_addr = AR6320_CORE_CLK_DIV_ADDR; + cmnos_cpu_pll_init_done_addr = AR6320_CPU_PLL_INIT_DONE_ADDR; + cmnos_cpu_speed_addr = AR6320_CPU_SPEED_ADDR; + break; + case AR6320_REV1_3_VERSION: + case AR6320_REV2_1_VERSION: + cmnos_core_clk_div_addr = AR6320V2_CORE_CLK_DIV_ADDR; + cmnos_cpu_pll_init_done_addr = AR6320V2_CPU_PLL_INIT_DONE_ADDR; + cmnos_cpu_speed_addr = AR6320V2_CPU_SPEED_ADDR; + break; + case AR6320_REV3_VERSION: + case AR6320_REV3_2_VERSION: + case QCA9377_REV1_1_VERSION: + cmnos_core_clk_div_addr = AR6320V3_CORE_CLK_DIV_ADDR; + cmnos_cpu_pll_init_done_addr = AR6320V3_CPU_PLL_INIT_DONE_ADDR; + cmnos_cpu_speed_addr = AR6320V3_CPU_SPEED_ADDR; + break; + default: + pr_err("%s: Unsupported target version %x\n", __func__, + scn->target_version); + return A_ERROR; + } + + addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read EFUSE Addr\n"); + return status; + } + + status = ol_fw_populate_clk_settings(EFUSE_XTAL_SEL_GET(reg_val), + &clock_s); + if (status != A_OK) { + pr_err("Failed to set clock settings\n"); + return status; + } + pr_debug("crystal_freq: %dHz\n", clock_s.refclk_hz); + + /* ------Step 1----*/ + reg_val = 0; + addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read PLL_CONFIG Addr\n"); + return status; + } + pr_debug("Step 1a: %8X\n", reg_val); + + reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK); + reg_val |= (BB_PLL_CONFIG_FRAC_SET(clock_s.wlan_pll.rnfrac) | + BB_PLL_CONFIG_OUTDIV_SET(clock_s.wlan_pll.outdiv)); + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write PLL_CONFIG Addr\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back PLL_CONFIG Addr\n"); + return status; + } + pr_debug("Step 1b: %8X\n", reg_val); + + /* ------Step 2----*/ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read PLL_SETTLE Addr\n"); + return status; + } + pr_debug("Step 2a: %8X\n", reg_val); + + reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK; + reg_val |= WLAN_PLL_SETTLE_TIME_SET(clock_s.pll_settling_time); + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write PLL_SETTLE Addr\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back PLL_SETTLE Addr\n"); + return status; + } + pr_debug("Step 2b: %8X\n", reg_val); + + /* ------Step 3----*/ + reg_val = 0; + addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read CLK_CTRL Addr\n"); + return status; + } + pr_debug("Step 3a: %8X\n", reg_val); + + reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK; + reg_val |= SOC_CORE_CLK_CTRL_DIV_SET(1); + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write CLK_CTRL Addr\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back CLK_CTRL Addr\n"); + return status; + } + pr_debug("Step 3b: %8X\n", reg_val); + + /* ------Step 4-----*/ + mem_val = 1; + status = BMIWriteMemory(hif_device, cmnos_core_clk_div_addr, + (A_UCHAR *)&mem_val, 4, scn); + if (status != A_OK) { + pr_err("Failed to write CLK_DIV Addr\n"); + return status; + } + + /* ------Step 5-----*/ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read PLL_CTRL Addr\n"); + return status; + } + pr_debug("Step 5a: %8X\n", reg_val); + + reg_val &= ~(WLAN_PLL_CONTROL_REFDIV_MASK | WLAN_PLL_CONTROL_DIV_MASK | + WLAN_PLL_CONTROL_NOPWD_MASK); + reg_val |= (WLAN_PLL_CONTROL_REFDIV_SET(clock_s.wlan_pll.refdiv) | + WLAN_PLL_CONTROL_DIV_SET(clock_s.wlan_pll.div) | + WLAN_PLL_CONTROL_NOPWD_SET(1)); + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write PLL_CTRL Addr\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back PLL_CTRL Addr\n"); + return status; + } + OS_DELAY(100); + pr_debug("Step 5b: %8X\n", reg_val); + + /* ------Step 6-------*/ + do { + reg_val = 0; + status = BMIReadSOCRegister(hif_device, (RTC_WMAC_BASE_ADDRESS | + RTC_SYNC_STATUS_OFFSET), ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read RTC_SYNC_STATUS Addr\n"); + return status; + } + } while(RTC_SYNC_STATUS_PLL_CHANGING_GET(reg_val)); + + /* ------Step 7-------*/ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read PLL_CTRL Addr for CTRL_BYPASS\n"); + return status; + } + pr_debug("Step 7a: %8X\n", reg_val); + + reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK; + reg_val |= WLAN_PLL_CONTROL_BYPASS_SET(0); + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write PLL_CTRL Addr for CTRL_BYPASS\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back PLL_CTRL Addr for CTRL_BYPASS\n"); + return status; + } + pr_debug("Step 7b: %8X\n", reg_val); + + /* ------Step 8--------*/ + do { + reg_val = 0; + status = BMIReadSOCRegister(hif_device, + (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET), + ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read SYNC_STATUS Addr\n"); + return status; + } + } while(RTC_SYNC_STATUS_PLL_CHANGING_GET(reg_val)); + + /* ------Step 9--------*/ + reg_val = 0; + addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read CPU_CLK Addr\n"); + return status; + } + pr_debug("Step 9a: %8X\n", reg_val); + + reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK; + reg_val |= SOC_CPU_CLOCK_STANDARD_SET(1);; + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write CPU_CLK Addr\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back CPU_CLK Addr\n"); + return status; + } + pr_debug("Step 9b: %8X\n", reg_val); + + /* ------Step 10-------*/ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read PLL_CTRL Addr for NOPWD\n"); + return status; + } + pr_debug("Step 10a: %8X\n", reg_val); + + reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK; + status = BMIWriteSOCRegister(hif_device, addr, reg_val, scn); + if (status != A_OK) { + pr_err("Failed to write PLL_CTRL Addr for NOPWD\n"); + return status; + } + + reg_val = 0; + status = BMIReadSOCRegister(hif_device, addr, ®_val, scn); + if (status != A_OK) { + pr_err("Failed to read back PLL_CTRL Addr for NOPWD\n"); + return status; + } + pr_debug("Step 10b: %8X\n", reg_val); + + /* ------Step 11-------*/ + mem_val = 1; + status = BMIWriteMemory(hif_device, cmnos_cpu_pll_init_done_addr, + (A_UCHAR *)&mem_val, 4, scn); + if (status != A_OK) { + pr_err("Failed to write PLL_INIT Addr\n"); + return status; + } + + mem_val = TARGET_CPU_FREQ; + status = BMIWriteMemory(hif_device, cmnos_cpu_speed_addr, + (A_UCHAR *)&mem_val, 4, scn); + if (status != A_OK) { + pr_err("Failed to write CPU_SPEED Addr\n"); + return status; + } + + return status; +} +#endif + +#ifdef CONFIG_CNSS +/* AXI Start Address */ +#define TARGET_ADDR (0xa0000) + +void ol_transfer_codeswap_struct(struct ol_softc *scn) { + struct hif_pci_softc *sc = scn->hif_sc; + struct codeswap_codeseg_info wlan_codeswap; + A_STATUS rv; + + if (!sc || !sc->hif_device) { + pr_err("%s: hif_pci_softc is null\n", __func__); + return; + } + + if (cnss_get_codeswap_struct(&wlan_codeswap)) { + pr_err("%s: failed to get codeswap structure\n", __func__); + return; + } + + rv = BMIWriteMemory(scn->hif_hdl, TARGET_ADDR, + (u_int8_t *)&wlan_codeswap, sizeof(wlan_codeswap), scn); + + if (rv != A_OK) { + pr_err("Failed to Write 0xa0000 for Target Memory Expansion\n"); + return; + } + pr_info("%s:codeswap structure is successfully downloaded\n", __func__); +} +#endif + +int ol_download_firmware(struct ol_softc *scn) +{ + uint32_t param, address = 0; + uint8_t bdf_ret = 0; + int status = !EOK; +#if defined(HIF_PCI) || defined(HIF_SDIO) + A_STATUS ret; +#endif + +#ifdef CONFIG_CNSS + if (0 != cnss_get_fw_files_for_target(&scn->fw_files, + scn->target_type, + scn->target_version)) { + printk("%s: No FW files from CNSS driver\n", __func__); + return -1; + } +#elif defined(HIF_SDIO) + if (0 != ol_get_fw_files_for_target(&scn->fw_files, + scn->target_version)) { + printk("%s: No FW files from driver\n", __func__); + return -1; + } +#endif + /* Transfer Board Data from Target EEPROM to Target RAM */ + /* Determine where in Target RAM to write Board Data */ + BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_board_data)), + (u_int8_t *)&address, 4, scn); + + if (!address) { + address = AR6004_REV5_BOARD_DATA_ADDRESS; + printk("%s: Target address not known! Using 0x%x\n", __func__, address); + } + +#if defined(HIF_PCI) || defined(HIF_SDIO) + ret = ol_patch_pll_switch(scn); + if (ret) { + pr_err("pll switch failed. status %d\n", ret); + return -1; + } +#endif + + if (scn->cal_in_flash) { + /* Write EEPROM or Flash data to Target RAM */ + status = ol_transfer_bin_file(scn, ATH_FLASH_FILE, address, FALSE); + } + + if (status == EOK) { + /* Record the fact that Board Data is initialized */ + param = 1; + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_board_data_initialized)), + (u_int8_t *)¶m, 4, scn); + } else { + /* Transfer One Time Programmable data */ + address = BMI_SEGMENTED_WRITE_ADDR; + printk("%s: Using 0x%x for the remainder of init\n", __func__, address); + + if ( scn->enablesinglebinary == FALSE ) { +#ifdef CONFIG_CNSS + ol_transfer_codeswap_struct(scn); +#endif + + status = ol_transfer_bin_file(scn, ATH_OTP_FILE, + address, TRUE); + if (status == EOK) { + /* Execute the OTP code only if entry found and downloaded */ + param = 0x10; + BMIExecute(scn->hif_hdl, address, ¶m, scn); + bdf_ret = param & 0xff; + if (!bdf_ret) + scn->board_id = (param >> 8) & 0xffff; + pr_debug("%s: chip_id:0x%0x board_id:0x%0x\n", + __func__, scn->target_version, + scn->board_id); + } else if (status < 0) { + return status; + } + } + + BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_board_data)), + (u_int8_t *)&address, 4, scn); + + if (!address) { + address = AR6004_REV5_BOARD_DATA_ADDRESS; + pr_err("%s: Target address not known! Using 0x%x\n", + __func__, address); + } + + /* Flash is either not available or invalid */ + if (ol_transfer_bin_file(scn, ATH_BOARD_DATA_FILE, + address, FALSE) != EOK) { + pr_err("%s: Board Data Download Failed\n", __func__); + return -1; + } + + /* Record the fact that Board Data is initialized */ + param = 1; + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_board_data_initialized)), + (u_int8_t *)¶m, 4, scn); + + address = BMI_SEGMENTED_WRITE_ADDR; + param = 0x0; + BMIExecute(scn->hif_hdl, address, ¶m, scn); + } + + if (scn->target_version == AR6320_REV1_1_VERSION){ + /* To disable PCIe use 96 AXI memory as internal buffering, + * highest bit of PCIE_TXBUF_ADDRESS need be set as 1 + */ + u_int32_t addr = 0x3A058; /* PCIE_TXBUF_ADDRESS */ + u_int32_t value = 0; + /* Disable PCIe AXI memory */ + BMIReadMemory(scn->hif_hdl, addr, (A_UCHAR*)&value, 4, scn); + value |= 0x80000000; /* PCIE_TXBUF_BYPASS_SET(1) */ + BMIWriteMemory(scn->hif_hdl, addr, (A_UCHAR*)&value, 4, scn); + value = 0; + BMIReadMemory(scn->hif_hdl, addr, (A_UCHAR*)&value, 4, scn); + printk("Disable PCIe use AXI memory:0x%08X-0x%08X\n", addr, value); + } + + address = BMI_SEGMENTED_WRITE_ADDR; + if (scn->enablesinglebinary == FALSE) { + if (ol_transfer_bin_file(scn, ATH_SETUP_FILE, + BMI_SEGMENTED_WRITE_ADDR, TRUE) == EOK) { + /* Execute the SETUP code only if entry found and downloaded */ + param = 0; + BMIExecute(scn->hif_hdl, address, ¶m, scn); + } + } + + /* Download Target firmware - TODO point to target specific files in runtime */ + if (ol_transfer_bin_file(scn, ATH_FIRMWARE_FILE, address, TRUE) != EOK) { + return -1; + } + + /* Apply the patches */ + if (ol_check_dataset_patch(scn, &address)) + { + if ((ol_transfer_bin_file(scn, ATH_PATCH_FILE, address, FALSE)) != EOK) { + return -1; + } + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_dset_list_head)), + (u_int8_t *)&address, 4, scn); + } + + if (scn->enableuartprint || + (WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && + WLAN_IS_EPPING_FW_UART(vos_get_conparam()))) { + switch (scn->target_version){ + case AR6004_VERSION_REV1_3: + param = 11; + break; + case AR6320_REV1_VERSION: + case AR6320_REV2_VERSION: + case AR6320_REV3_VERSION: + case AR6320_REV3_2_VERSION: + case QCA9377_REV1_1_VERSION: + case AR6320_REV4_VERSION: + case AR6320_DEV_VERSION: + /* for SDIO, debug uart output gpio is 29, otherwise it is 6. */ +#ifdef HIF_SDIO + param = 19; +#else + param = 6; +#endif + break; + default: + /* Configure GPIO AR9888 UART */ + param = 7; + } + + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_dbg_uart_txpin)), + (u_int8_t *)¶m, 4, scn); + param = 1; + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_serial_enable)), + (u_int8_t *)¶m, 4, scn); + } else { + /* + * Explicitly setting UART prints to zero as target turns it on + * based on scratch registers. + */ + param = 0; + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s,hi_serial_enable)), + (u_int8_t *)¶m, 4, scn); + } + +#ifdef HIF_SDIO + /* HACK override dbg TX pin to avoid side effects of default GPIO_6 */ + param = 19; + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_dbg_uart_txpin)), + (u_int8_t *)¶m, 4, scn); +#endif + + + if (scn->enablefwlog) { + BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag)), + (u_int8_t *)¶m, 4, scn); + + param &= ~(HI_OPTION_DISABLE_DBGLOG); + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag)), + (u_int8_t *)¶m, 4, scn); + } else { + /* + * Explicitly setting fwlog prints to zero as target turns it on + * based on scratch registers. + */ + BMIReadMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag)), + (u_int8_t *)¶m, 4, scn); + + param |= HI_OPTION_DISABLE_DBGLOG; + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag)), + (u_int8_t *)¶m, 4, scn); + } + +#ifdef HIF_SDIO + status = ol_sdio_extra_initialization(scn); +#elif defined(HIF_USB) + status = ol_usb_extra_initialization(scn); +#endif + + return status; +} + +#if defined(HIF_PCI) || defined(HIF_SDIO) +int ol_diag_read(struct ol_softc *scn, u_int8_t *buffer, + u_int32_t pos, size_t count) +{ + int result = 0; + + if ((4 == count) && ((pos & 3) == 0)) { + result = HIFDiagReadAccess(scn->hif_hdl, pos, + (u_int32_t*)buffer); + } else { +#ifdef HIF_PCI + size_t amountRead = 0; + size_t readSize = PCIE_READ_LIMIT; + size_t remainder = 0; + if (count > PCIE_READ_LIMIT) { + while ((amountRead < count) && (0 == result)) { + result = HIFDiagReadMem(scn->hif_hdl, pos, + buffer, readSize); + if (0 == result) { + buffer += readSize; + pos += readSize; + amountRead += readSize; + remainder = count - amountRead; + if (remainder < PCIE_READ_LIMIT) + readSize = remainder; + } + } + } else { +#endif + result = HIFDiagReadMem(scn->hif_hdl, pos, + buffer, count); +#ifdef HIF_PCI + } +#endif + } + + if (!result) { + return count; + } else { + return -EIO; + } +} + +#if defined(HIF_PCI) +static int ol_ath_get_reg_table(A_UINT32 target_version, + tgt_reg_table *reg_table) +{ + int section_len = 0; + + if (!reg_table) { + ASSERT(0); + return section_len; + } + + switch (target_version) { + case AR6320_REV2_1_VERSION: + reg_table->section = (tgt_reg_section *)&ar6320v2_reg_table[0]; + reg_table->section_size = sizeof(ar6320v2_reg_table) + /sizeof(ar6320v2_reg_table[0]); + section_len = AR6320_REV2_1_REG_SIZE; + break; + case AR6320_REV3_VERSION: + case AR6320_REV3_2_VERSION: + case QCA9377_REV1_1_VERSION: + reg_table->section = (tgt_reg_section *)&ar6320v3_reg_table[0]; + reg_table->section_size = sizeof(ar6320v3_reg_table) + /sizeof(ar6320v3_reg_table[0]); + section_len = AR6320_REV3_REG_SIZE; + break; + default: + reg_table->section = (void *)NULL; + reg_table->section_size = 0; + section_len = 0; + } + + return section_len; +} + +static int ol_diag_read_reg_loc(struct ol_softc *scn, u_int8_t *buffer, + u_int32_t buffer_len) +{ + int i, len, section_len, fill_len; + int dump_len, result = 0; + tgt_reg_table reg_table; + tgt_reg_section *curr_sec, *next_sec; + + section_len = ol_ath_get_reg_table(scn->target_version, ®_table); + + if (!reg_table.section || !reg_table.section_size || !section_len) { + printk(KERN_ERR "%s: failed to get reg table\n", __func__); + result = -EIO; + goto out; + } + + curr_sec = reg_table.section; + for (i = 0; i < reg_table.section_size; i++) { + + dump_len = curr_sec->end_addr - curr_sec->start_addr; + + if ((buffer_len - result) < dump_len) { + printk("Not enough memory to dump the registers:" + " %d: 0x%08x-0x%08x\n", i, + curr_sec->start_addr, + curr_sec->end_addr); + goto out; + } + + len = ol_diag_read(scn, buffer, curr_sec->start_addr, dump_len); + + if (len != -EIO) { + buffer += len; + result += len; + } else { + printk(KERN_ERR "%s: can't read reg 0x%08x len = %d\n", + __func__, curr_sec->start_addr, dump_len); + result = -EIO; + goto out; + } + + if (result < section_len) { + next_sec = (tgt_reg_section *)((u_int8_t *)curr_sec + + sizeof(*curr_sec)); + fill_len = next_sec->start_addr - curr_sec->end_addr; + if ((buffer_len - result) < fill_len) { + printk("Not enough memory to fill registers:" + " %d: 0x%08x-0x%08x\n", i, + curr_sec->end_addr, + next_sec->start_addr); + goto out; + } + + if (fill_len) { + buffer += fill_len; + result += fill_len; + } + } + curr_sec++; + } + +out: + return result; +} + +void ol_dump_target_memory(HIF_DEVICE *hif_device, void *memoryBlock) +{ + char *bufferLoc = memoryBlock; + u_int32_t sectionCount = 0; + u_int32_t address = 0; + u_int32_t size = 0; + + for ( ; sectionCount < 2; sectionCount++) { + switch (sectionCount) { + case 0: + address = DRAM_LOCAL_BASE_ADDRESS; + size = DRAM_SIZE; + break; + case 1: + address = AXI_LOCATION; + size = AXI_SIZE; + default: + break; + } + + HIFDumpTargetMemory(hif_device, bufferLoc, address, size); + bufferLoc += size; + } +} +#endif + +/**--------------------------------------------------------------------------- + * \brief ol_target_coredump + * + * Function to perform core dump for the target + * + * \param: scn - ol_softc handler + * memoryBlock - non-NULL reserved memory location + * blockLength - size of the dump to collect + * + * \return: None + * --------------------------------------------------------------------------*/ +int ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength) +{ + struct ol_softc *scn = (struct ol_softc *)inst; + char *bufferLoc = memoryBlock; + int result = 0; + int ret = 0; + u_int32_t amountRead = 0; + u_int32_t sectionCount = 0; + u_int32_t pos = 0; + u_int32_t readLen = 0; + + /* + * SECTION = DRAM + * START = 0x00400000 + * LENGTH = 0x000a8000 + * + * SECTION = AXI + * START = 0x000a0000 + * LENGTH = 0x00018000 + * + * SECTION = REG + * START = 0x00000800 + * LENGTH = 0x0007F820 + * + * SECTION = IRAM1 + * START = 0x00980000 + * LENGTH = 0x00080000 + * + * SECTION = IRAM2 + * START = 0x00a00000 + * LENGTH = 0x00040000 + */ +#ifdef TARGET_DUMP_FOR_NON_QC_PLATFORM + while ((sectionCount < 4) && (amountRead < blockLength)) { +#else +#ifdef HIF_PCI + while ((sectionCount < 5) && (amountRead < blockLength)) { +#else + while ((sectionCount < 3) && (amountRead < blockLength)) { +#endif +#endif + switch (sectionCount) { + case 0: + /* DRAM SECTION */ + pos = DRAM_LOCATION; + readLen = DRAM_SIZE; + pr_err("%s: Dumping DRAM section...\n", __func__); + break; + case 1: + /* AXI SECTION */ + pos = AXI_LOCATION; + readLen = AXI_SIZE; + pr_err("%s: Dumping AXI section...\n", __func__); + break; + case 2: + /* REG SECTION */ + pos = REGISTER_LOCATION; + /* ol_diag_read_reg_loc checks for buffer overrun */ + readLen = 0; + pr_err("%s: Dumping Register section...\n", __func__); + break; +#ifdef TARGET_DUMP_FOR_NON_QC_PLATFORM + case 3: + /* IRAM SECTION */ + pos = IRAM_LOCATION; + readLen = IRAM_SIZE; + pr_err("%s: Dumping IRAM section...\n", __func__); + break; +#else +#ifdef HIF_PCI + case 3: + if ((scn->target_status != OL_TRGET_STATUS_RESET) || + hif_pci_set_ram_config_reg(scn->hif_sc, + IRAM1_LOCATION >> 20)) { + pr_debug("%s: Skipping IRAM1 section...\n", + __func__); + return 0; + } + + /* IRAM1 SECTION */ + pos = IRAM1_LOCATION; + readLen = IRAM1_SIZE; + pr_err("%s: Dumping IRAM1 section...\n", __func__); + break; + case 4: + if (hif_pci_set_ram_config_reg(scn->hif_sc, + IRAM2_LOCATION >> 20)) { + pr_debug("%s: Skipping IRAM2 section...\n", + __func__); + return 0; + } + + /* IRAM2 SECTION */ + pos = IRAM2_LOCATION; + readLen = IRAM2_SIZE; + pr_err("%s: Dumping IRAM2 section...\n", __func__); + break; +#endif +#endif + } + + if ((blockLength - amountRead) >= readLen) { +#if !defined(HIF_SDIO) + if (pos == REGISTER_LOCATION) + result = ol_diag_read_reg_loc(scn, bufferLoc, + blockLength - amountRead); + else +#endif + result = ol_diag_read(scn, bufferLoc, + pos, readLen); + if (result != -EIO) { + amountRead += result; + bufferLoc += result; + sectionCount++; + } else { +#ifdef CONFIG_HL_SUPPORT +#else + pr_err("Could not read dump section!\n"); + dump_CE_register(scn); + dump_CE_debug_register(scn->hif_sc); + ol_dump_target_memory(scn->hif_hdl, memoryBlock); + ret = -EACCES; +#endif + break; /* Could not read the section */ + } + } else { + pr_err("Insufficient room in dump buffer!\n"); + break; /* Insufficient room in buffer */ + } + } + return ret; +} +#endif + + +#if defined(CONFIG_HL_SUPPORT) +#define MAX_SUPPORTED_PEERS_REV1_1 9 +#ifdef HIF_SDIO +#define MAX_SUPPORTED_PEERS 32 +#else +#define MAX_SUPPORTED_PEERS 10 +#endif +#else +#define MAX_SUPPORTED_PEERS_REV1_1 14 +#define MAX_SUPPORTED_PEERS 32 +#endif + +u_int8_t ol_get_number_of_peers_supported(struct ol_softc *scn) +{ + u_int8_t max_no_of_peers = 0; + + switch (scn->target_version) { + case AR6320_REV1_1_VERSION: + if(scn->max_no_of_peers > MAX_SUPPORTED_PEERS_REV1_1) + max_no_of_peers = MAX_SUPPORTED_PEERS_REV1_1; + else + max_no_of_peers = scn->max_no_of_peers; + break; + + default: + if(scn->max_no_of_peers > MAX_SUPPORTED_PEERS) + max_no_of_peers = MAX_SUPPORTED_PEERS; + else + max_no_of_peers = scn->max_no_of_peers; + break; + + } + return max_no_of_peers; +} + +#ifdef HIF_SDIO + +/*Setting SDIO block size, mbox ISR yield limit for SDIO based HIF*/ +static A_STATUS +ol_sdio_extra_initialization(struct ol_softc *scn) +{ + + A_STATUS status; + u_int32_t param; +#ifdef CONFIG_DISABLE_SLEEP_BMI_OPTION + uint32 value; +#endif + + do{ + A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; + unsigned int MboxIsrYieldValue = 99; + A_UINT32 TargetType = TARGET_TYPE_AR6320; + /* get the block sizes */ + status = HIFConfigureDevice(scn->hif_hdl, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + + if (A_FAILED(status)) { + printk("Failed to get block size info from HIF layer...\n"); + break; + } + /* note: we actually get the block size for mailbox 1, for SDIO the block + size on mailbox 0 is artificially set to 1 must be a power of 2 */ + A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0); + + /* set the host interest area for the block size */ + status = BMIWriteMemory(scn->hif_hdl, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz), + (A_UCHAR *)&blocksizes[1], + 4, + scn); + + if (A_FAILED(status)) { + printk("BMIWriteMemory for IO block size failed \n"); + break; + } + + if (MboxIsrYieldValue != 0) { + /* set the host interest area for the mbox ISR yield limit */ + status = BMIWriteMemory(scn->hif_hdl, + HOST_INTEREST_ITEM_ADDRESS(TargetType, + hi_mbox_isr_yield_limit), + (A_UCHAR *)&MboxIsrYieldValue, + 4, + scn); + + if (A_FAILED(status)) { + printk("BMIWriteMemory for yield limit failed \n"); + break; + } + } + +#ifdef CONFIG_DISABLE_SLEEP_BMI_OPTION + + printk("%s: prevent ROME from sleeping\n",__func__); + BMIReadSOCRegister(scn->hif_hdl, + MBOX_BASE_ADDRESS + LOCAL_SCRATCH_OFFSET, + /* this address should be 0x80C0 for ROME*/ + &value, + scn); + + value |= SOC_OPTION_SLEEP_DISABLE; + + BMIWriteSOCRegister(scn->hif_hdl, + MBOX_BASE_ADDRESS + LOCAL_SCRATCH_OFFSET, + value, + scn); +#endif + status = BMIReadMemory(scn->hif_hdl, + HOST_INTEREST_ITEM_ADDRESS(scn->target_type, + hi_acs_flags), + (u_int8_t *)¶m, + 4, + scn); + if (A_FAILED(status)) { + printk("BMIReadMemory for hi_acs_flags failed \n"); + break; + } + + param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET| + HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET| + HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE); + + BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_acs_flags)), + (u_int8_t *)¶m, 4, scn); + + }while(FALSE); + + return status; +} + +void +ol_target_ready(struct ol_softc *scn, void *cfg_ctx) +{ + u_int32_t value = 0; + A_STATUS status = EOK; + + status = HIFDiagReadMem(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_acs_flags)), + (A_UCHAR *)&value, sizeof(u_int32_t)); + + if (status != EOK) { + printk("%s: HIFDiagReadMem failed:%d\n", __func__, status); + return; + } + + if (value & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) { + printk("MAILBOX SWAP Service is enabled!\n"); + HIFSetMailboxSwap(scn->hif_hdl); + } + + if (value & HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK) { + printk("Reduced Tx Complete service is enabled!\n"); + ol_cfg_set_tx_free_at_download(cfg_ctx); + + } +#ifdef HIF_MBOX_SLEEP_WAR + HIFSetMboxSleep(scn->hif_hdl, true, true, true); +#endif +} +#endif + +#ifdef HIF_USB +static A_STATUS +ol_usb_extra_initialization(struct ol_softc *scn) +{ + A_STATUS status = !EOK; + u_int32_t param = 0; + + param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; + status = BMIWriteMemory(scn->hif_hdl, + host_interest_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_acs_flags)), + (u_int8_t *)¶m, 4, scn); + + return status; +} +#endif + +/** + * ol_pktlog_init()- Pktlog Module initialization + * @hif_sc: ol_softc structure. + * + * The API is used to initialize pktlog module for + * all bus types. + * + */ + +#ifndef REMOVE_PKT_LOG +void ol_pktlog_init(void *hif_sc) +{ + struct ol_softc *ol_sc = (struct ol_softc *)hif_sc; + int ret; + + ol_pl_sethandle(&ol_sc->pdev_txrx_handle->pl_dev, ol_sc); + + ret = pktlogmod_init(ol_sc); + + if (ret) + pr_err("%s: pktlogmod_init failed ret:%d\n", __func__, ret); + else + pr_info("%s: pktlogmod_init successfull\n", __func__); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.h new file mode 100644 index 000000000000..eb7edf2d0a7e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_FW_H_ +#define _OL_FW_H_ + +#ifdef QCA_WIFI_FTM +#include "vos_types.h" +#endif + +#define AR6004_VERSION_REV1_3 0x31c8088a + +#define AR9888_REV1_VERSION 0x4000002c +#define AR9888_REV2_VERSION 0x4100016c +#define QCA_VERSION 0x4100270f +#define AR6320_REV1_VERSION 0x5000000 +#define AR6320_REV1_1_VERSION 0x5000001 +#define AR6320_REV1_VERSION_1 AR6320_REV1_1_VERSION +#define AR6320_REV1_3_VERSION 0x5000003 +#define AR6320_REV2_VERSION AR6320_REV1_1_VERSION +#define AR6320_REV2_1_VERSION 0x5010000 +#define AR6320_REV3_VERSION 0x5020000 +#define QCA9377_REV1_1_VERSION 0x5020001 +#define AR6320_REV3_2_VERSION 0x5030000 +#define AR6320_REV4_VERSION AR6320_REV2_1_VERSION +#define AR6320_DEV_VERSION 0x1000000 +#define QCA_FIRMWARE_FILE "athwlan.bin" +#define QCA_UTF_FIRMWARE_FILE "utf.bin" +#define QCA_BOARD_DATA_FILE "fakeboar.bin" +#define QCA_OTP_FILE "otp.bin" +#define QCA_SETUP_FILE "athsetup.bin" +#define AR61X4_SINGLE_FILE "qca61x4.bin" +#define QCA_FIRMWARE_EPPING_FILE "epping.bin" + +/* Configuration for statistics pushed by firmware */ +#define PDEV_DEFAULT_STATS_UPDATE_PERIOD 500 +#define VDEV_DEFAULT_STATS_UPDATE_PERIOD 500 +#define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 + +/* + * Note that not all the register locations are accessible. + * A list of accessible target registers are specified with + * their start and end addresses in a table for given target + * version. We should NOT access other locations as either + * they are invalid locations or host does not have read + * access to it or the value of the particular register + * read might change + */ +#define REGISTER_LOCATION 0x00000800 + +#ifdef TARGET_DUMP_FOR_NON_QC_PLATFORM +#define DRAM_LOCATION 0x00400000 +#define DRAM_SIZE 0x00097FFC + +#define IRAM_LOCATION 0x00980000 +#define IRAM_SIZE 0x000BFFFC + +#define AXI_LOCATION 0x000a0000 +#define AXI_SIZE 0x0001FFFC +#else +#define DRAM_LOCATION 0x00400000 +#define DRAM_SIZE 0x000a8000 +#define DRAM_LOCAL_BASE_ADDRESS (0x100000) + +#ifdef HIF_PCI +#define IRAM1_LOCATION 0x00980000 +#define IRAM1_SIZE 0x00080000 +#define IRAM2_LOCATION 0x00a00000 +#define IRAM2_SIZE 0x00040000 +#else +#define IRAM_LOCATION 0x00980000 +#define IRAM_SIZE 0x00038000 +#endif + +#define AXI_LOCATION 0x000a0000 +#ifdef HIF_PCI +#define AXI_SIZE 0x00018000 +#else +#define AXI_SIZE 0x00020000 +#endif /* #ifdef HIF_PCIE */ +#endif + +#define CE_OFFSET 0x00000400 +#define CE_USEFUL_SIZE 0x00000058 + +#define TOTAL_DUMP_SIZE 0x00200000 +#define PCIE_READ_LIMIT 0x00005000 + +#define SHA256_DIGEST_SIZE 32 + +struct hash_fw { + u8 qwlan[SHA256_DIGEST_SIZE]; + u8 otp[SHA256_DIGEST_SIZE]; + u8 bdwlan[SHA256_DIGEST_SIZE]; + u8 utf[SHA256_DIGEST_SIZE]; +}; + +int ol_target_coredump(void *instance, void* memoryBlock, + u_int32_t blockLength); +int ol_diag_read(struct ol_softc *scn, u_int8_t* buffer, + u_int32_t pos, size_t count); +void ol_schedule_ramdump_work(struct ol_softc *scn); +void ol_schedule_fw_indication_work(struct ol_softc *scn); +int ol_copy_ramdump(struct ol_softc *scn); +int dump_CE_register(struct ol_softc *scn); +int ol_download_firmware(struct ol_softc *scn); +int ol_configure_target(struct ol_softc *scn); +void ol_target_failure(void *instance, A_STATUS status); +u_int8_t ol_get_number_of_peers_supported(struct ol_softc *scn); + +#ifdef REMOVE_PKT_LOG +static inline void ol_pktlog_init(void *) +{ +} +#else +void ol_pktlog_init(void *); +#endif + +#if defined(HIF_SDIO) +void ol_target_ready(struct ol_softc *scn, void *cfg_ctx); +#else +static inline void ol_target_ready(struct ol_softc *scn, void *cfg_ctx) +{ + +} +#endif + +#endif /* _OL_FW_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/_ieee80211_common.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/_ieee80211_common.h new file mode 100644 index 000000000000..f4a92944d878 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/_ieee80211_common.h @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _COMMON__IEEE80211_H_ +#define _COMMON__IEEE80211_H_ + +/* These defines should match the table from ah_internal.h */ +typedef enum { + DFS_UNINIT_DOMAIN = 0, /* Uninitialized dfs domain */ + DFS_FCC_DOMAIN = 1, /* FCC3 dfs domain */ + DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */ + DFS_MKK4_DOMAIN = 3 /* Japan dfs domain */ +}HAL_DFS_DOMAIN; + +/* XXX not really a mode; there are really multiple PHY's */ +enum ieee80211_phymode { + IEEE80211_MODE_AUTO = 0, /* autoselect */ + IEEE80211_MODE_11A = 1, /* 5GHz, OFDM */ + IEEE80211_MODE_11B = 2, /* 2GHz, CCK */ + IEEE80211_MODE_11G = 3, /* 2GHz, OFDM */ + IEEE80211_MODE_FH = 4, /* 2GHz, GFSK */ + IEEE80211_MODE_TURBO_A = 5, /* 5GHz, OFDM, 2x clock dynamic turbo */ + IEEE80211_MODE_TURBO_G = 6, /* 2GHz, OFDM, 2x clock dynamic turbo */ + IEEE80211_MODE_11NA_HT20 = 7, /* 5Ghz, HT20 */ + IEEE80211_MODE_11NG_HT20 = 8, /* 2Ghz, HT20 */ + IEEE80211_MODE_11NA_HT40PLUS = 9, /* 5Ghz, HT40 (ext ch +1) */ + IEEE80211_MODE_11NA_HT40MINUS = 10, /* 5Ghz, HT40 (ext ch -1) */ + IEEE80211_MODE_11NG_HT40PLUS = 11, /* 2Ghz, HT40 (ext ch +1) */ + IEEE80211_MODE_11NG_HT40MINUS = 12, /* 2Ghz, HT40 (ext ch -1) */ + IEEE80211_MODE_11NG_HT40 = 13, /* 2Ghz, Auto HT40 */ + IEEE80211_MODE_11NA_HT40 = 14, /* 2Ghz, Auto HT40 */ + IEEE80211_MODE_11AC_VHT20 = 15, /* 5Ghz, VHT20 */ + IEEE80211_MODE_11AC_VHT40PLUS = 16, /* 5Ghz, VHT40 (Ext ch +1) */ + IEEE80211_MODE_11AC_VHT40MINUS = 17, /* 5Ghz VHT40 (Ext ch -1) */ + IEEE80211_MODE_11AC_VHT40 = 18, /* 5Ghz, VHT40 */ + IEEE80211_MODE_11AC_VHT80 = 19, /* 5Ghz, VHT80 */ + IEEE80211_MODE_2G_AUTO = 20, /* 2G 11 b/g/n autoselect */ + IEEE80211_MODE_5G_AUTO = 21, /* 5G 11 a/n/ac autoselect */ + IEEE80211_MODE_11AGN = 22, /* Support 11N in both 2G and 5G */ +}; +#define IEEE80211_MODE_MAX (IEEE80211_MODE_11AC_VHT80 + 1) + +enum ieee80211_opmode { + IEEE80211_M_STA = 1, /* infrastructure station */ + IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */ + IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */ + IEEE80211_M_HOSTAP = 6, /* Software Access Point */ + IEEE80211_M_MONITOR = 8, /* Monitor mode */ + IEEE80211_M_WDS = 2, /* WDS link */ + IEEE80211_M_BTAMP = 9, /* VAP for BT AMP */ + + IEEE80211_M_P2P_GO = 33, /* P2P GO */ + IEEE80211_M_P2P_CLIENT = 34, /* P2P Client */ + IEEE80211_M_P2P_DEVICE = 35, /* P2P Device */ + + + IEEE80211_OPMODE_MAX = IEEE80211_M_BTAMP, /* Highest numbered opmode in the list */ + + IEEE80211_M_ANY = 0xFF /* Any of the above; used by NDIS 6.x */ +}; + +/* + * 802.11n + */ +#define IEEE80211_CWM_EXTCH_BUSY_THRESHOLD 30 + +enum ieee80211_cwm_mode { + IEEE80211_CWM_MODE20, + IEEE80211_CWM_MODE2040, + IEEE80211_CWM_MODE40, + IEEE80211_CWM_MODEMAX + +}; + +enum ieee80211_cwm_extprotspacing { + IEEE80211_CWM_EXTPROTSPACING20, + IEEE80211_CWM_EXTPROTSPACING25, + IEEE80211_CWM_EXTPROTSPACINGMAX +}; + +enum ieee80211_cwm_width { + IEEE80211_CWM_WIDTH20, + IEEE80211_CWM_WIDTH40, + IEEE80211_CWM_WIDTH80, + IEEE80211_CWM_WIDTHINVALID = 0xff /* user invalid value */ +}; + +enum ieee80211_cwm_extprotmode { + IEEE80211_CWM_EXTPROTNONE, /* no protection */ + IEEE80211_CWM_EXTPROTCTSONLY, /* CTS to self */ + IEEE80211_CWM_EXTPROTRTSCTS, /* RTS-CTS */ + IEEE80211_CWM_EXTPROTMAX +}; + +enum ieee80211_fixed_rate_mode { + IEEE80211_FIXED_RATE_NONE = 0, + IEEE80211_FIXED_RATE_MCS = 1, /* HT rates */ + IEEE80211_FIXED_RATE_LEGACY = 2, /* legacy rates */ + IEEE80211_FIXED_RATE_VHT = 3 /* VHT rates */ +}; + +/* Holds the fixed rate information for each VAP */ +struct ieee80211_fixed_rate { + enum ieee80211_fixed_rate_mode mode; + u_int32_t series; + u_int32_t retries; +}; + +/* + * 802.11g protection mode. + */ +enum ieee80211_protmode { + IEEE80211_PROT_NONE = 0, /* no protection */ + IEEE80211_PROT_CTSONLY = 1, /* CTS to self */ + IEEE80211_PROT_RTSCTS = 2, /* RTS-CTS */ +}; + +/* + * Roaming mode is effectively who controls the operation + * of the 802.11 state machine when operating as a station. + * State transitions are controlled either by the driver + * (typically when management frames are processed by the + * hardware/firmware), the host (auto/normal operation of + * the 802.11 layer), or explicitly through ioctl requests + * when applications like wpa_supplicant want control. + */ +enum ieee80211_roamingmode { + IEEE80211_ROAMING_DEVICE= 0, /* driver/hardware control */ + IEEE80211_ROAMING_AUTO = 1, /* 802.11 layer control */ + IEEE80211_ROAMING_MANUAL= 2, /* application control */ +}; + +/* + * Scanning mode controls station scanning work; this is + * used only when roaming mode permits the host to select + * the bss to join/channel to use. + */ +enum ieee80211_scanmode { + IEEE80211_SCAN_DEVICE = 0, /* driver/hardware control */ + IEEE80211_SCAN_BEST = 1, /* 802.11 layer selects best */ + IEEE80211_SCAN_FIRST = 2, /* take first suitable candidate */ +}; + +#define IEEE80211_NWID_LEN 32 +#define IEEE80211_CHAN_MAX 255 +#define IEEE80211_CHAN_BYTES 32 /* howmany(IEEE80211_CHAN_MAX, NBBY) */ +#define IEEE80211_CHAN_ANY (-1) /* token for ``any channel'' */ +#define IEEE80211_CHAN_ANYC \ + ((struct ieee80211_channel *) IEEE80211_CHAN_ANY) + +#define IEEE80211_CHAN_DEFAULT 11 +#define IEEE80211_CHAN_DEFAULT_11A 52 +#define IEEE80211_CHAN_ADHOC_DEFAULT1 10 +#define IEEE80211_CHAN_ADHOC_DEFAULT2 11 + +#define IEEE80211_RADAR_11HCOUNT 5 +#define IEEE80211_RADAR_TEST_MUTE_CHAN_11A 36 /* Move to channel 36 for mute test */ +#define IEEE80211_RADAR_TEST_MUTE_CHAN_11NHT20 36 +#define IEEE80211_RADAR_TEST_MUTE_CHAN_11NHT40U 36 +#define IEEE80211_RADAR_TEST_MUTE_CHAN_11NHT40D 40 /* Move to channel 40 for HT40D mute test */ +#define IEEE80211_RADAR_DETECT_DEFAULT_DELAY 60000 /* STA ignore AP beacons during this period in millisecond */ + +#define IEEE80211_2GCSA_TBTTCOUNT 3 + +/* bits 0-3 are for private use by drivers */ +/* channel attributes */ +#define IEEE80211_CHAN_TURBO 0x00000010 /* Turbo channel */ +#define IEEE80211_CHAN_CCK 0x00000020 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x00000040 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x00000080 /* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_5GHZ 0x00000100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_PASSIVE 0x00000200 /* Only passive scan allowed */ +#define IEEE80211_CHAN_DYN 0x00000400 /* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_GFSK 0x00000800 /* GFSK channel (FHSS PHY) */ +#define IEEE80211_CHAN_RADAR_DFS 0x00001000 /* Radar found on channel */ +#define IEEE80211_CHAN_STURBO 0x00002000 /* 11a static turbo channel only */ +#define IEEE80211_CHAN_HALF 0x00004000 /* Half rate channel */ +#define IEEE80211_CHAN_QUARTER 0x00008000 /* Quarter rate channel */ +#define IEEE80211_CHAN_HT20 0x00010000 /* HT 20 channel */ +#define IEEE80211_CHAN_HT40PLUS 0x00020000 /* HT 40 with extension channel above */ +#define IEEE80211_CHAN_HT40MINUS 0x00040000 /* HT 40 with extension channel below */ +#define IEEE80211_CHAN_HT40INTOL 0x00080000 /* HT 40 Intolerant */ +#define IEEE80211_CHAN_VHT20 0x00100000 /* VHT 20 channel */ +#define IEEE80211_CHAN_VHT40PLUS 0x00200000 /* VHT 40 with extension channel above */ +#define IEEE80211_CHAN_VHT40MINUS 0x00400000 /* VHT 40 with extension channel below */ +#define IEEE80211_CHAN_VHT80 0x00800000 /* VHT 80 channel */ + +/* flagext */ +#define IEEE80211_CHAN_RADAR_FOUND 0x01 +#define IEEE80211_CHAN_DFS 0x0002 /* DFS required on channel */ +#define IEEE80211_CHAN_DFS_CLEAR 0x0008 /* if channel has been checked for DFS */ +#define IEEE80211_CHAN_11D_EXCLUDED 0x0010 /* excluded in 11D */ +#define IEEE80211_CHAN_CSA_RECEIVED 0x0020 /* Channel Switch Announcement received on this channel */ +#define IEEE80211_CHAN_DISALLOW_ADHOC 0x0040 /* ad-hoc is not allowed */ +#define IEEE80211_CHAN_DISALLOW_HOSTAP 0x0080 /* Station only channel */ + +/* + * Useful combinations of channel characteristics. + */ +#define IEEE80211_CHAN_FHSS \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) +#define IEEE80211_CHAN_A \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_B \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) +#define IEEE80211_CHAN_PUREG \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) +#define IEEE80211_CHAN_108A \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) +#define IEEE80211_CHAN_108G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) +#define IEEE80211_CHAN_ST \ + (IEEE80211_CHAN_108A | IEEE80211_CHAN_STURBO) + +#define IEEE80211_IS_CHAN_11AC_2G(_c) \ + (IEEE80211_IS_CHAN_2GHZ((_c)) && IEEE80211_IS_CHAN_VHT((_c))) +#define IEEE80211_CHAN_11AC_VHT20_2G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_VHT20) +#define IEEE80211_CHAN_11AC_VHT40_2G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_VHT40PLUS | IEEE80211_CHAN_VHT40MINUS) +#define IEEE80211_CHAN_11AC_VHT80_2G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_VHT80) + +#define IEEE80211_IS_CHAN_11AC_VHT20_2G(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT20_2G) == IEEE80211_CHAN_11AC_VHT20_2G) +#define IEEE80211_IS_CHAN_11AC_VHT40_2G(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT40_2G) != 0) +#define IEEE80211_IS_CHAN_11AC_VHT80_2G(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80_2G) == IEEE80211_CHAN_11AC_VHT80_2G) + +#define IEEE80211_CHAN_11NG_HT20 \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_HT20) +#define IEEE80211_CHAN_11NA_HT20 \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_HT20) +#define IEEE80211_CHAN_11NG_HT40PLUS \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_HT40PLUS) +#define IEEE80211_CHAN_11NG_HT40MINUS \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_HT40MINUS) +#define IEEE80211_CHAN_11NA_HT40PLUS \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_HT40PLUS) +#define IEEE80211_CHAN_11NA_HT40MINUS \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_HT40MINUS) + +#define IEEE80211_CHAN_ALL \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_GFSK | \ + IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN | \ + IEEE80211_CHAN_HT20 | IEEE80211_CHAN_HT40PLUS | IEEE80211_CHAN_HT40MINUS | \ + IEEE80211_CHAN_VHT20 | IEEE80211_CHAN_VHT40PLUS | IEEE80211_CHAN_VHT40MINUS | IEEE80211_CHAN_VHT80 | \ + IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER) +#define IEEE80211_CHAN_ALLTURBO \ + (IEEE80211_CHAN_ALL | IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO) + +#define IEEE80211_IS_CHAN_FHSS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) +#define IEEE80211_IS_CHAN_A(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) +#define IEEE80211_IS_CHAN_B(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) +#define IEEE80211_IS_CHAN_PUREG(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) +#define IEEE80211_IS_CHAN_G(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) +#define IEEE80211_IS_CHAN_ANYG(_c) \ + (IEEE80211_IS_CHAN_PUREG(_c) || IEEE80211_IS_CHAN_G(_c)) +#define IEEE80211_IS_CHAN_ST(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_ST) == IEEE80211_CHAN_ST) +#define IEEE80211_IS_CHAN_108A(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_108A) == IEEE80211_CHAN_108A) +#define IEEE80211_IS_CHAN_108G(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G) + +#define IEEE80211_IS_CHAN_2GHZ(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_2GHZ) != 0) +#define IEEE80211_IS_CHAN_5GHZ(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_5GHZ) != 0) +#define IEEE80211_IS_CHAN_OFDM(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_OFDM) != 0) +#define IEEE80211_IS_CHAN_CCK(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_CCK) != 0) +#define IEEE80211_IS_CHAN_GFSK(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_GFSK) != 0) +#define IEEE80211_IS_CHAN_TURBO(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_TURBO) != 0) +#define IEEE80211_IS_CHAN_WEATHER_RADAR(_c) \ + ((((_c)->ic_freq >= 5600) && ((_c)->ic_freq <= 5650)) \ + || (((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) && (5580 == (_c)->ic_freq))) +#define IEEE80211_IS_CHAN_STURBO(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_STURBO) != 0) +#define IEEE80211_IS_CHAN_DTURBO(_c) \ + (((_c)->ic_flags & \ + (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)) == IEEE80211_CHAN_TURBO) +#define IEEE80211_IS_CHAN_HALF(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HALF) != 0) +#define IEEE80211_IS_CHAN_QUARTER(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_QUARTER) != 0) +#define IEEE80211_IS_CHAN_PASSIVE(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_PASSIVE) != 0) + +#define IEEE80211_IS_CHAN_DFS(_c) \ + (((_c)->ic_flagext & (IEEE80211_CHAN_DFS|IEEE80211_CHAN_DFS_CLEAR)) == IEEE80211_CHAN_DFS) +#define IEEE80211_IS_CHAN_DFSFLAG(_c) \ + (((_c)->ic_flagext & IEEE80211_CHAN_DFS) == IEEE80211_CHAN_DFS) +#define IEEE80211_IS_CHAN_DISALLOW_ADHOC(_c) \ + (((_c)->ic_flagext & IEEE80211_CHAN_DISALLOW_ADHOC) != 0) +#define IEEE80211_IS_CHAN_11D_EXCLUDED(_c) \ + (((_c)->ic_flagext & IEEE80211_CHAN_11D_EXCLUDED) != 0) +#define IEEE80211_IS_CHAN_CSA(_c) \ + (((_c)->ic_flagext & IEEE80211_CHAN_CSA_RECEIVED) != 0) +#define IEEE80211_IS_CHAN_ODD(_c) \ + (((_c)->ic_freq == 5170) || ((_c)->ic_freq == 5190) || \ + ((_c)->ic_freq == 5210) || ((_c)->ic_freq == 5230)) +#define IEEE80211_IS_CHAN_DISALLOW_HOSTAP(_c) \ + (((_c)->ic_flagext & IEEE80211_CHAN_DISALLOW_HOSTAP) != 0) + +#define IEEE80211_IS_CHAN_11NG_HT20(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11NG_HT20) == IEEE80211_CHAN_11NG_HT20) +#define IEEE80211_IS_CHAN_11NA_HT20(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11NA_HT20) == IEEE80211_CHAN_11NA_HT20) +#define IEEE80211_IS_CHAN_11NG_HT40PLUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11NG_HT40PLUS) == IEEE80211_CHAN_11NG_HT40PLUS) +#define IEEE80211_IS_CHAN_11NG_HT40MINUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11NG_HT40MINUS) == IEEE80211_CHAN_11NG_HT40MINUS) +#define IEEE80211_IS_CHAN_11NA_HT40PLUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11NA_HT40PLUS) == IEEE80211_CHAN_11NA_HT40PLUS) +#define IEEE80211_IS_CHAN_11NA_HT40MINUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11NA_HT40MINUS) == IEEE80211_CHAN_11NA_HT40MINUS) + +#define IEEE80211_IS_CHAN_11N(_c) \ + (((_c)->ic_flags & (IEEE80211_CHAN_HT20 | IEEE80211_CHAN_HT40PLUS | IEEE80211_CHAN_HT40MINUS)) != 0) +#define IEEE80211_IS_CHAN_11N_HT20(_c) \ + (((_c)->ic_flags & (IEEE80211_CHAN_HT20)) != 0) +#define IEEE80211_IS_CHAN_11N_HT40(_c) \ + (((_c)->ic_flags & (IEEE80211_CHAN_HT40PLUS | IEEE80211_CHAN_HT40MINUS)) != 0) +#define IEEE80211_IS_CHAN_11NG(_c) \ + (IEEE80211_IS_CHAN_2GHZ((_c)) && IEEE80211_IS_CHAN_11N((_c))) +#define IEEE80211_IS_CHAN_11NA(_c) \ + (IEEE80211_IS_CHAN_5GHZ((_c)) && IEEE80211_IS_CHAN_11N((_c))) +#define IEEE80211_IS_CHAN_11N_HT40PLUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) != 0) +#define IEEE80211_IS_CHAN_11N_HT40MINUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) != 0) + +#define IEEE80211_IS_CHAN_HT20_CAPABLE(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT20) == IEEE80211_CHAN_HT20) +#define IEEE80211_IS_CHAN_HT40PLUS_CAPABLE(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) == IEEE80211_CHAN_HT40PLUS) +#define IEEE80211_IS_CHAN_HT40MINUS_CAPABLE(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) == IEEE80211_CHAN_HT40MINUS) +#define IEEE80211_IS_CHAN_HT40_CAPABLE(_c) \ + (IEEE80211_IS_CHAN_HT40PLUS_CAPABLE(_c) || IEEE80211_IS_CHAN_HT40MINUS_CAPABLE(_c)) +#define IEEE80211_IS_CHAN_HT_CAPABLE(_c) \ + (IEEE80211_IS_CHAN_HT20_CAPABLE(_c) || IEEE80211_IS_CHAN_HT40_CAPABLE(_c)) +#define IEEE80211_IS_CHAN_11N_CTL_CAPABLE(_c) IEEE80211_IS_CHAN_HT20_CAPABLE(_c) +#define IEEE80211_IS_CHAN_11N_CTL_U_CAPABLE(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) == IEEE80211_CHAN_HT40PLUS) +#define IEEE80211_IS_CHAN_11N_CTL_L_CAPABLE(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) == IEEE80211_CHAN_HT40MINUS) +#define IEEE80211_IS_CHAN_11N_CTL_40_CAPABLE(_c) \ + (IEEE80211_IS_CHAN_11N_CTL_U_CAPABLE((_c)) || IEEE80211_IS_CHAN_11N_CTL_L_CAPABLE((_c))) + + +#define IEEE80211_IS_CHAN_VHT(_c) \ + (((_c)->ic_flags & (IEEE80211_CHAN_VHT20 | \ + IEEE80211_CHAN_VHT40PLUS | IEEE80211_CHAN_VHT40MINUS | IEEE80211_CHAN_VHT80)) != 0) +#define IEEE80211_IS_CHAN_11AC(_c) \ + ( IEEE80211_IS_CHAN_5GHZ((_c)) && IEEE80211_IS_CHAN_VHT((_c)) ) +#define IEEE80211_CHAN_11AC_VHT20 \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT20) +#define IEEE80211_CHAN_11AC_VHT40 \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT40PLUS | IEEE80211_CHAN_VHT40MINUS ) +#define IEEE80211_CHAN_11AC_VHT40PLUS \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT40PLUS) +#define IEEE80211_CHAN_11AC_VHT40MINUS \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT40MINUS) +#define IEEE80211_CHAN_11AC_VHT80 \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT80) +#define IEEE80211_IS_CHAN_11AC_VHT20(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT20) == IEEE80211_CHAN_11AC_VHT20) + +#define IEEE80211_IS_CHAN_11AC_VHT40(_c) \ + (((_c)->ic_flags & (IEEE80211_CHAN_VHT40PLUS | IEEE80211_CHAN_VHT40MINUS)) !=0) +#define IEEE80211_IS_CHAN_11AC_VHT40PLUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT40PLUS) == IEEE80211_CHAN_11AC_VHT40PLUS) +#define IEEE80211_IS_CHAN_11AC_VHT40MINUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT40MINUS) == IEEE80211_CHAN_11AC_VHT40MINUS) +#define IEEE80211_IS_CHAN_11AC_VHT80(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == IEEE80211_CHAN_11AC_VHT80) + +#define IEEE80211_IS_CHAN_RADAR(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_RADAR_DFS) == IEEE80211_CHAN_RADAR_DFS) +#define IEEE80211_CHAN_SET_RADAR(_c) \ + ((_c)->ic_flags |= IEEE80211_CHAN_RADAR_DFS) +#define IEEE80211_CHAN_CLR_RADAR(_c) \ + ((_c)->ic_flags &= ~IEEE80211_CHAN_RADAR_DFS) +#define IEEE80211_CHAN_SET_DISALLOW_ADHOC(_c) \ + ((_c)->ic_flagext |= IEEE80211_CHAN_DISALLOW_ADHOC) +#define IEEE80211_CHAN_SET_DISALLOW_HOSTAP(_c) \ + ((_c)->ic_flagext |= IEEE80211_CHAN_DISALLOW_HOSTAP) +#define IEEE80211_CHAN_SET_DFS(_c) \ + ((_c)->ic_flagext |= IEEE80211_CHAN_DFS) +#define IEEE80211_CHAN_SET_DFS_CLEAR(_c) \ + ((_c)->ic_flagext |= IEEE80211_CHAN_DFS_CLEAR) +#define IEEE80211_CHAN_EXCLUDE_11D(_c) \ + ((_c)->ic_flagext |= IEEE80211_CHAN_11D_EXCLUDED) + +/* channel encoding for FH phy */ +#define IEEE80211_FH_CHANMOD 80 +#define IEEE80211_FH_CHAN(set,pat) (((set)-1)*IEEE80211_FH_CHANMOD+(pat)) +#define IEEE80211_FH_CHANSET(chan) ((chan)/IEEE80211_FH_CHANMOD+1) +#define IEEE80211_FH_CHANPAT(chan) ((chan)%IEEE80211_FH_CHANMOD) + +/* + * 802.11 rate set. + */ +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */ +#define IEEE80211_RATE_MAXSIZE 36 /* max rates we'll handle */ +#define IEEE80211_HT_RATE_SIZE 128 +#define IEEE80211_RATE_SINGLE_STREAM_MCS_MAX 7 /* MCS7 */ + +#define IEEE80211_RATE_MCS 0x8000 +#define IEEE80211_RATE_MCS_VAL 0x7FFF + +#define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8))) + +/* + * RSSI range + */ +#define IEEE80211_RSSI_MAX -10 /* in db */ +#define IEEE80211_RSSI_MIN -200 + +/* + * 11n A-MPDU & A-MSDU limits + */ +#define IEEE80211_AMPDU_LIMIT_MIN (1 * 1024) +#define IEEE80211_AMPDU_LIMIT_MAX (64 * 1024 - 1) +#define IEEE80211_AMPDU_LIMIT_DEFAULT IEEE80211_AMPDU_LIMIT_MAX +#define IEEE80211_AMPDU_SUBFRAME_MIN 2 +#define IEEE80211_AMPDU_SUBFRAME_MAX 64 +#define IEEE80211_AMPDU_SUBFRAME_DEFAULT 32 +#define IEEE80211_AMSDU_LIMIT_MAX 4096 +#define IEEE80211_RIFS_AGGR_DIV 10 +#define IEEE80211_MAX_AMPDU_MIN 0 +#define IEEE80211_MAX_AMPDU_MAX 3 + +/* + * 11ac A-MPDU limits + */ +#define IEEE80211_VHT_MAX_AMPDU_MIN 0 +#define IEEE80211_VHT_MAX_AMPDU_MAX 7 + + + +struct ieee80211_rateset { + u_int8_t rs_nrates; + u_int8_t rs_rates[IEEE80211_RATE_MAXSIZE]; +}; + +struct ieee80211_beacon_info{ + u_int8_t essid[IEEE80211_NWID_LEN+1]; + u_int8_t esslen; + u_int8_t rssi_ctl_0; + u_int8_t rssi_ctl_1; + u_int8_t rssi_ctl_2; + int numchains; +}; + +struct ieee80211_ibss_peer_list{ + u_int8_t bssid[6]; +}; + +struct ieee80211_roam { + int8_t rssi11a; /* rssi thresh for 11a bss */ + int8_t rssi11b; /* for 11g sta in 11b bss */ + int8_t rssi11bOnly; /* for 11b sta */ + u_int8_t pad1; + u_int8_t rate11a; /* rate thresh for 11a bss */ + u_int8_t rate11b; /* for 11g sta in 11b bss */ + u_int8_t rate11bOnly; /* for 11b sta */ + u_int8_t pad2; +}; + +#define IEEE80211_TID_SIZE 17 /* total number of TIDs */ +#define IEEE80211_NON_QOS_SEQ 16 /* index for non-QoS (including management) sequence number space */ +#define IEEE80211_SEQ_MASK 0xfff /* sequence generator mask*/ +#define MIN_SW_SEQ 0x100 /* minimum sequence for SW generate packect*/ + +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ + +/* crypto related defines*/ +#define IEEE80211_KEYBUF_SIZE 16 +#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx+rx keys */ + +enum ieee80211_clist_cmd { + CLIST_UPDATE, + CLIST_DFS_UPDATE, + CLIST_NEW_COUNTRY, + CLIST_NOL_UPDATE +}; + +enum ieee80211_nawds_param { + IEEE80211_NAWDS_PARAM_NUM = 0, + IEEE80211_NAWDS_PARAM_MODE, + IEEE80211_NAWDS_PARAM_DEFCAPS, + IEEE80211_NAWDS_PARAM_OVERRIDE, +}; + +struct ieee80211_mib_cycle_cnts { + u_int32_t tx_frame_count; + u_int32_t rx_frame_count; + u_int32_t rx_clear_count; + u_int32_t cycle_count; + u_int8_t is_rx_active; + u_int8_t is_tx_active; +}; + +struct ieee80211_chanutil_info { + u_int32_t rx_clear_count; + u_int32_t cycle_count; + u_int8_t value; + u_int32_t beacon_count; + u_int8_t beacon_intervals; +}; + +#endif /* _COMMON__IEEE80211_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_debug.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_debug.h new file mode 100644 index 000000000000..7ef6e2b43afb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_debug.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _A_DEBUG_H_ +#define _A_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include "osapi_linux.h" + + /* standard debug print masks bits 0..7 */ +#define ATH_DEBUG_ERR (1 << 0) /* errors */ +#define ATH_DEBUG_WARN (1 << 1) /* warnings */ +#define ATH_DEBUG_INFO (1 << 2) /* informational (module startup info) */ +#define ATH_DEBUG_TRC (1 << 3) /* generic function call tracing */ +#define ATH_DEBUG_RSVD1 (1 << 4) +#define ATH_DEBUG_RSVD2 (1 << 5) +#define ATH_DEBUG_RSVD3 (1 << 6) +#define ATH_DEBUG_RSVD4 (1 << 7) + +#define ATH_DEBUG_MASK_DEFAULTS (ATH_DEBUG_ERR | ATH_DEBUG_WARN) +#define ATH_DEBUG_ANY 0xFFFF + + /* other aliases used throughout */ +#define ATH_DEBUG_ERROR ATH_DEBUG_ERR +#define ATH_LOG_ERR ATH_DEBUG_ERR +#define ATH_LOG_INF ATH_DEBUG_INFO +#define ATH_LOG_TRC ATH_DEBUG_TRC +#define ATH_DEBUG_TRACE ATH_DEBUG_TRC +#define ATH_DEBUG_INIT ATH_DEBUG_INFO + + /* bits 8..31 are module-specific masks */ +#define ATH_DEBUG_MODULE_MASK_SHIFT 8 + + /* macro to make a module-specific masks */ +#define ATH_DEBUG_MAKE_MODULE_MASK(index) (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index))) + +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription); + +/* Debug support on a per-module basis + * + * Usage: + * + * Each module can utilize it's own debug mask variable. A set of commonly used + * masks are provided (ERRORS, WARNINGS, TRACE etc..). It is up to each module + * to define module-specific masks using the macros above. + * + * Each module defines a single debug mask variable debug_XXX where the "name" of the module is + * common to all C-files within that module. This requires every C-file that includes a_debug.h + * to define the module name in that file. + * + * Example: + * + * #define ATH_MODULE_NAME htc + * #include "a_debug.h" + * + * This will define a debug mask structure called debug_htc and all debug macros will reference this + * variable. + * + * A module can define module-specific bit masks using the ATH_DEBUG_MAKE_MODULE_MASK() macro: + * + * #define ATH_DEBUG_MY_MASK1 ATH_DEBUG_MAKE_MODULE_MASK(0) + * #define ATH_DEBUG_MY_MASK2 ATH_DEBUG_MAKE_MODULE_MASK(1) + * + * The instantiation of the debug structure should be made by the module. When a module is + * instantiated, the module can set a description string, a default mask and an array of description + * entries containing information on each module-defined debug mask. + * NOTE: The instantiation is statically allocated, only one instance can exist per module. + * + * Example: + * + * + * #define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) + * + * #ifdef DEBUG + * static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = { + * { ATH_DEBUG_BMI , "BMI Tracing"}, <== description of the module specific mask + * }; + * + * ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, + * "bmi" <== module name + * "Boot Manager Interface", <== description of module + * ATH_DEBUG_MASK_DEFAULTS, <== defaults + * ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), + * bmi_debug_desc); + * + * #endif + * + * A module can optionally register it's debug module information in order for other tools to change the + * bit mask at runtime. A module can call A_REGISTER_MODULE_DEBUG_INFO() in it's module + * init code. This macro can be called multiple times without consequence. The debug info maintains + * state to indicate whether the information was previously registered. + * + * */ + +#define ATH_DEBUG_MAX_MASK_DESC_LENGTH 32 +#define ATH_DEBUG_MAX_MOD_DESC_LENGTH 64 + +typedef struct { + A_UINT32 Mask; + A_CHAR Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH]; +} ATH_DEBUG_MASK_DESCRIPTION; + +#define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0) + +typedef struct _ATH_DEBUG_MODULE_DBG_INFO{ + struct _ATH_DEBUG_MODULE_DBG_INFO *pNext; + A_CHAR ModuleName[16]; + A_CHAR ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH]; + A_UINT32 Flags; + A_UINT32 CurrentMask; + int MaxDescriptions; + ATH_DEBUG_MASK_DESCRIPTION *pMaskDescriptions; /* pointer to array of descriptions */ +} ATH_DEBUG_MODULE_DBG_INFO; + +#define ATH_DEBUG_DESCRIPTION_COUNT(d) (int)((sizeof((d))) / (sizeof(ATH_DEBUG_MASK_DESCRIPTION))) + +#define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s) +#define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask +#define _XGET_ATH_MODULE_NAME_DEBUG_(s) debug_ ## s + +#ifdef DEBUG + + /* for source files that will instantiate the debug variables */ +#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) \ +ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) = \ + {NULL,(name),(moddesc),0,(initmask),count,(descriptions)} + +#ifdef ATH_MODULE_NAME +extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(ATH_MODULE_NAME); +#define AR_DEBUG_LVL_CHECK(lvl) (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (lvl)) +#endif /* ATH_MODULE_NAME */ + +#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) GET_ATH_MODULE_DEBUG_VAR_MASK(s) = (lvl) + +#define ATH_DEBUG_DECLARE_EXTERN(s) \ + extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) + +#define AR_DEBUG_PRINTBUF(buffer, length, desc) DebugDumpBytes(buffer,length,desc) + + +#define AR_DEBUG_ASSERT A_ASSERT + +void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo); +void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo); +#ifdef A_SIMOS_DEVHOST +#define A_DUMP_MODULE_DEBUG_INFO(s) a_dump_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s))) +#define A_REGISTER_MODULE_DEBUG_INFO(s) a_register_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s))) +#else +#define A_DUMP_MODULE_DEBUG_INFO(s) +#define A_REGISTER_MODULE_DEBUG_INFO(s) +#endif + +#else /* !DEBUG */ + /* NON DEBUG */ +#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) +#define AR_DEBUG_LVL_CHECK(lvl) 0 +#define AR_DEBUG_PRINTBUF(buffer, length, desc) +#define AR_DEBUG_ASSERT(test) +#define ATH_DEBUG_DECLARE_EXTERN(s) +#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) +#define A_DUMP_MODULE_DEBUG_INFO(s) +#define A_REGISTER_MODULE_DEBUG_INFO(s) + +#endif + +A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask); +A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask); +void a_dump_module_debug_info_by_name(A_CHAR *module_name); +void a_module_debug_support_init(void); +void a_module_debug_support_cleanup(void); + +#if defined(__linux__) && !defined(LINUX_EMULATION) +#include "debug_linux.h" +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_osapi.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_osapi.h new file mode 100644 index 000000000000..a8c9c2b0e946 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_osapi.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//============================================================================== +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_OSAPI_H_ +#define _A_OSAPI_H_ + +#if defined(__linux__) && !defined(LINUX_EMULATION) +#include "osapi_linux.h" +#endif + +/*=== the following primitives have the same definition for all platforms ===*/ + +#define A_COMPILE_TIME_ASSERT(assertion_name, predicate) \ + typedef char assertion_name[(predicate) ? 1 : -1] + +/* + * If N is a power of 2, then N and N-1 are orthogonal + * (N-1 has all the least-significant bits set which are zero in N) + * so N ^ (N-1) = (N << 1) - 1 + */ +#define A_COMPILE_TIME_ASSERT_IS_PWR2(assertion_name, value) \ + A_COMPILE_TIME_ASSERT(assertion_name, \ + (((value) ^ ((value)-1)) == ((value) << 1) - 1)) + +#ifndef __ubicom32__ +#define HIF_MALLOC_DIAGMEM(osdev, size, pa, context, retry) \ + OS_MALLOC_CONSISTENT(osdev, size, pa, context, retry) +#define HIF_FREE_DIAGMEM(osdev, size, vaddr, pa, context) \ + OS_FREE_CONSISTENT(osdev, size, vaddr, pa, context) +#define HIF_DIAGMEM_SYNC(osdev, pa, size, dir, context) +#else +#define HIF_MALLOC_DIAGMEM(osdev, size, pa, context, retry) \ + OS_MALLOC_NONCONSISTENT(osdev, size, pa, context, retry) +#define HIF_FREE_DIAGMEM(osdev, size, vaddr, pa, context) \ + OS_FREE_NONCONSISTENT(osdev, size, vaddr, pa, context) +#define HIF_DIAGMEM_SYNC(osdev, pa, size, dir, context) \ + OS_SYNC_SINGLE(osdev, pa, size, dir, context) +#endif /* ubicom32 */ + +#endif /* _OSAPI_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_types.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_types.h new file mode 100644 index 000000000000..768a7a80c2e7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_types.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//depot/sw/qca_main/perf_pwr_offload/drivers/host/include/a_types.h#7 - integrate change 1327637 (ktext) +//============================================================================== +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _A_TYPES_H_ +#define _A_TYPES_H_ +#include + +typedef unsigned int A_UINT32; +typedef unsigned long long A_UINT64; +typedef unsigned short A_UINT16; +typedef unsigned char A_UINT8; +typedef int A_INT32; +typedef short A_INT16; +typedef char A_INT8; +typedef unsigned char A_UCHAR; +typedef char A_CHAR; +typedef _Bool A_BOOL; + +#endif /* _ATHTYPES_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_usb_defs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_usb_defs.h new file mode 100644 index 000000000000..5208f4273578 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/a_usb_defs.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* +* This file was originally distributed by Qualcomm Atheros, Inc. +* under proprietary terms before Copyright ownership was assigned +* to the Linux Foundation. +*/ +/* + * Shared USB definitions + * + * + * + * + */ + +#ifndef __A_USB_DEFS_H__ +#define __A_USB_DEFS_H__ + +#ifndef ATH_TARGET +#include "athstartpack.h" +#endif + +/* USB endpoint definitions */ + +#define USB_EP_ADDR_APP_CTRL_IN 0x81 +#define USB_EP_ADDR_APP_DATA_IN 0x82 +#define USB_EP_ADDR_APP_DATA2_IN 0x83 +#define USB_EP_ADDR_APP_INT_IN 0x84 + + + +#define USB_EP_ADDR_APP_CTRL_OUT 0x01 +#define USB_EP_ADDR_APP_DATA_LP_OUT 0x02 +#define USB_EP_ADDR_APP_DATA_MP_OUT 0x03 +#define USB_EP_ADDR_APP_DATA_HP_OUT 0x04 + +#define USB_CONTROL_REQ_SEND_BMI_CMD 1 +#define USB_CONTROL_REQ_RECV_BMI_RESP 2 +#define USB_CONTROL_REQ_DIAG_CMD 3 +#define USB_CONTROL_REQ_DIAG_RESP 4 + + +/* #define USB_CONTROL_MAX_BMI_TRANSFER_SIZE 64 */ +#define USB_CONTROL_MAX_BMI_TRANSFER_SIZE 252 + +#define HIF_BMI_MAX_TRANSFER_SIZE USB_CONTROL_MAX_BMI_TRANSFER_SIZE + +/* 512 Bytes Maxp for High Speed for BULK EP */ +#define USB_HS_BULK_MAXP_SIZE 0x200 +/* 64 Bytes Maxp for Full Speed for BULK EP */ +#define USB_FS_BULK_MAXP_SIZE 0x40 + + + +/* diagnostic command defnitions */ +#define USB_CTRL_DIAG_CC_READ 0 +#define USB_CTRL_DIAG_CC_WRITE 1 +#define USB_CTRL_DIAG_CC_WARM_RESET 2 + +typedef PREPACK struct { + A_UINT32 Cmd; + A_UINT32 Address; + A_UINT32 Value; + A_UINT32 _pad[1]; +} POSTPACK USB_CTRL_DIAG_CMD_WRITE; + +typedef PREPACK struct { + A_UINT32 Cmd; + A_UINT32 Address; +} POSTPACK USB_CTRL_DIAG_CMD_READ; + +typedef PREPACK struct { + A_UINT32 ReadValue; +} POSTPACK USB_CTRL_DIAG_RESP_READ; + +#define USB_CTRL_MAX_DIAG_CMD_SIZE (sizeof(USB_CTRL_DIAG_CMD_WRITE)) +#define USB_CTRL_MAX_DIAG_RESP_SIZE (sizeof(USB_CTRL_DIAG_RESP_READ)) + +#ifndef ATH_TARGET +#include "athendpack.h" +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/a_base_types.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/a_base_types.h new file mode 100644 index 000000000000..ac80788b700f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/a_base_types.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef __A_BASE_TYPES_H +#define __A_BASE_TYPES_H + + + +/** + * @brief The basic data types + */ +typedef __a_uint8_t a_uint8_t; /**< 1 Byte */ +typedef __a_uint16_t a_uint16_t;/**< 2 Bytes */ +typedef __a_uint32_t a_uint32_t;/**< 4 Bytes */ +typedef __a_uint64_t a_uint64_t;/**< 4 Bytes */ + +typedef __a_int8_t a_int8_t; /**< 1 Byte */ +typedef __a_int16_t a_int16_t;/**< 2 Bytes */ +typedef __a_int32_t a_int32_t;/**< 4 Bytes */ +typedef __a_int64_t a_int64_t;/**< 4 Bytes */ + +enum a_bool { + A_FALSE = 0, + A_TRUE = 1 +}; +typedef a_uint8_t a_bool_t;/**< 1 Byte */ + + +/** + * @brief Generic status for the API's + */ +enum { + A_STATUS_OK = 0, + A_STATUS_FAILED, + A_STATUS_ENOENT, + A_STATUS_ENOMEM, + A_STATUS_EINVAL, + A_STATUS_EINPROGRESS, + A_STATUS_ENOTSUPP, + A_STATUS_EBUSY, + A_STATUS_E2BIG, + A_STATUS_ENOSPC, + A_STATUS_EADDRNOTAVAIL, + A_STATUS_ENXIO, + A_STATUS_ENETDOWN, + A_STATUS_EFAULT, + A_STATUS_EIO, + A_STATUS_ENETRESET, + A_STATUS_EEXIST, + A_STATUS_SIG /* Exit due to received SIGINT */ +}; +typedef a_uint32_t a_status_t; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c new file mode 100644 index 000000000000..8a97c4c1daaf --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC +#include +#endif + +adf_nbuf_trace_update_t trace_update_cb = NULL; + +#if defined(CONFIG_WCNSS_MEM_PRE_ALLOC) && defined(WITH_BACKPORTS) +struct sk_buff *__adf_nbuf_pre_alloc(adf_os_device_t osdev, size_t size) +{ + struct sk_buff *skb = NULL; + + if (size >= WCNSS_PRE_SKB_ALLOC_GET_THRESHOLD) + skb = wcnss_skb_prealloc_get(size); + + return skb; +} + +int __adf_nbuf_pre_alloc_free(struct sk_buff *skb) +{ + return wcnss_skb_prealloc_put(skb); +} +#else +struct sk_buff *__adf_nbuf_pre_alloc(adf_os_device_t osdev, size_t size) +{ + return NULL; +} + +int __adf_nbuf_pre_alloc_free(struct sk_buff *skb) +{ + return 0; +} +#endif + +/* + * @brief This allocates an nbuf aligns if needed and reserves + * some space in the front, since the reserve is done + * after alignment the reserve value if being unaligned + * will result in an unaligned address. + * + * @param hdl + * @param size + * @param reserve + * @param align + * + * @return nbuf or NULL if no memory + */ +struct sk_buff * +__adf_nbuf_alloc(adf_os_device_t osdev, size_t size, int reserve, int align, int prio) +{ + struct sk_buff *skb; + unsigned long offset; + + if(align) + size += (align - 1); + + skb = __adf_nbuf_pre_alloc(osdev, size); + + if (skb) + goto skb_cb; + + skb = dev_alloc_skb(size); + + if (!skb) { + printk("ERROR:NBUF alloc failed\n"); + return NULL; + } + +skb_cb: + memset(skb->cb, 0x0, sizeof(skb->cb)); + + /* + * The default is for netbuf fragments to be interpreted + * as wordstreams rather than bytestreams. + * Set the CVG_NBUF_MAX_EXTRA_FRAGS+1 wordstream_flags bits, + * to provide this default. + */ + NBUF_EXTRA_FRAG_WORDSTREAM_FLAGS(skb) = + (1 << (CVG_NBUF_MAX_EXTRA_FRAGS + 1)) - 1; + + /** + * XXX:how about we reserve first then align + */ + + /** + * Align & make sure that the tail & data are adjusted properly + */ + if(align){ + offset = ((unsigned long) skb->data) % align; + if(offset) + skb_reserve(skb, align - offset); + } + + /** + * NOTE:alloc doesn't take responsibility if reserve unaligns the data + * pointer + */ + skb_reserve(skb, reserve); + + return skb; +} + +#ifdef QCA_ARP_SPOOFING_WAR +/* + * __adf_rx_nbuf_alloc() Rx buffer allocation function * + * @hdl: + * @size: + * @reserve: + * @align: + * + * Use existing buffer allocation API and overwrite + * priv_data field of skb->cb for registering callback + * as it is not used for Rx case. + * + * Return: nbuf or NULL if no memory + */ +struct sk_buff * +__adf_rx_nbuf_alloc(adf_os_device_t osdev, size_t size, int reserve, int align, int prio) +{ + struct sk_buff *skb; + + skb = __adf_nbuf_alloc(osdev, size, reserve,align, prio); + if (skb) { + NBUF_CB_PTR(skb) = osdev->filter_cb; + } + return skb; +} +#endif +/* + * @brief free the nbuf its interrupt safe + * @param skb + */ +void +__adf_nbuf_free(struct sk_buff *skb) +{ +#ifdef QCA_MDM_DEVICE +#if defined(IPA_OFFLOAD) && (!defined(IPA_UC_OFFLOAD) ||\ + (defined(IPA_UC_OFFLOAD) && defined(IPA_UC_STA_OFFLOAD))) + if( (NBUF_OWNER_ID(skb) == IPA_NBUF_OWNER_ID) && NBUF_CALLBACK_FN(skb) ) + NBUF_CALLBACK_FN_EXEC(skb); + else +#endif +#endif /* QCA_MDM_DEVICE */ + { + if (__adf_nbuf_pre_alloc_free(skb)) + return; + dev_kfree_skb_any(skb); + } +} + + +/* + * @brief Reference the nbuf so it can get held until the last free. + * @param skb + */ + +void +__adf_nbuf_ref(struct sk_buff *skb) +{ + skb_get(skb); +} + +/** + * @brief Check whether the buffer is shared + * @param skb: buffer to check + * + * Returns true if more than one person has a reference to this + * buffer. + */ +int +__adf_nbuf_shared(struct sk_buff *skb) +{ + return skb_shared(skb); +} +/** + * @brief create a nbuf map + * @param osdev + * @param dmap + * + * @return a_status_t + */ +a_status_t +__adf_nbuf_dmamap_create(adf_os_device_t osdev, __adf_os_dma_map_t *dmap) +{ + a_status_t error = A_STATUS_OK; + /** + * XXX: driver can tell its SG capablity, it must be handled. + * XXX: Bounce buffers if they are there + */ + (*dmap) = kzalloc(sizeof(struct __adf_os_dma_map), GFP_KERNEL); + if(!(*dmap)) + error = A_STATUS_ENOMEM; + + return error; +} + +/** + * @brief free the nbuf map + * + * @param osdev + * @param dmap + */ +void +__adf_nbuf_dmamap_destroy(adf_os_device_t osdev, __adf_os_dma_map_t dmap) +{ + kfree(dmap); +} + +/** + * @brief get the dma map of the nbuf + * + * @param osdev + * @param bmap + * @param skb + * @param dir + * + * @return a_status_t + */ +a_status_t +__adf_nbuf_map( + adf_os_device_t osdev, + struct sk_buff *skb, + adf_os_dma_dir_t dir) +{ +#ifdef ADF_OS_DEBUG + struct skb_shared_info *sh = skb_shinfo(skb); +#endif + adf_os_assert( + (dir == ADF_OS_DMA_TO_DEVICE) || (dir == ADF_OS_DMA_FROM_DEVICE)); + + /* + * Assume there's only a single fragment. + * To support multiple fragments, it would be necessary to change + * adf_nbuf_t to be a separate object that stores meta-info + * (including the bus address for each fragment) and a pointer + * to the underlying sk_buff. + */ + adf_os_assert(sh->nr_frags == 0); + + return __adf_nbuf_map_single(osdev, skb, dir); + + return A_STATUS_OK; +} + +/** + * @brief adf_nbuf_unmap() - to unmap a previously mapped buf + */ +void +__adf_nbuf_unmap( + adf_os_device_t osdev, + struct sk_buff *skb, + adf_os_dma_dir_t dir) +{ + adf_os_assert( + (dir == ADF_OS_DMA_TO_DEVICE) || (dir == ADF_OS_DMA_FROM_DEVICE)); + + adf_os_assert(((dir == ADF_OS_DMA_TO_DEVICE) || (dir == ADF_OS_DMA_FROM_DEVICE))); + /* + * Assume there's a single fragment. + * If this is not true, the assertion in __adf_nbuf_map will catch it. + */ + __adf_nbuf_unmap_single(osdev, skb, dir); +} + +a_status_t +__adf_nbuf_map_single( + adf_os_device_t osdev, adf_nbuf_t buf, adf_os_dma_dir_t dir) +{ + u_int32_t paddr_lo; + +/* tempory hack for simulation */ +#ifdef A_SIMOS_DEVHOST + NBUF_MAPPED_PADDR_LO(buf) = paddr_lo = (u_int32_t) buf->data; + return A_STATUS_OK; +#else + /* assume that the OS only provides a single fragment */ + NBUF_MAPPED_PADDR_LO(buf) = paddr_lo = + dma_map_single(osdev->dev, buf->data, + skb_end_pointer(buf) - buf->data, dir); + return dma_mapping_error(osdev->dev, paddr_lo) ? + A_STATUS_FAILED : A_STATUS_OK; +#endif /* #ifdef A_SIMOS_DEVHOST */ +} + +void +__adf_nbuf_unmap_single( + adf_os_device_t osdev, adf_nbuf_t buf, adf_os_dma_dir_t dir) +{ +#if !defined(A_SIMOS_DEVHOST) + dma_unmap_single(osdev->dev, NBUF_MAPPED_PADDR_LO(buf), + skb_end_pointer(buf) - buf->data, dir); +#endif /* #if !defined(A_SIMOS_DEVHOST) */ +} + +/** + * @brief return the dma map info + * + * @param[in] bmap + * @param[out] sg (map_info ptr) + */ +void +__adf_nbuf_dmamap_info(__adf_os_dma_map_t bmap, adf_os_dmamap_info_t *sg) +{ + adf_os_assert(bmap->mapped); + adf_os_assert(bmap->nsegs <= ADF_OS_MAX_SCATTER); + + memcpy(sg->dma_segs, bmap->seg, bmap->nsegs * + sizeof(struct __adf_os_segment)); + sg->nsegs = bmap->nsegs; +} +/** + * @brief return the frag data & len, where frag no. is + * specified by the index + * + * @param[in] buf + * @param[out] sg (scatter/gather list of all the frags) + * + */ +void +__adf_nbuf_frag_info(struct sk_buff *skb, adf_os_sglist_t *sg) +{ +#if defined(ADF_OS_DEBUG) || defined(__ADF_SUPPORT_FRAG_MEM) + struct skb_shared_info *sh = skb_shinfo(skb); +#endif + adf_os_assert(skb != NULL); + sg->sg_segs[0].vaddr = skb->data; + sg->sg_segs[0].len = skb->len; + sg->nsegs = 1; + +#ifndef __ADF_SUPPORT_FRAG_MEM + adf_os_assert(sh->nr_frags == 0); +#else + for(int i = 1; i <= sh->nr_frags; i++){ + skb_frag_t *f = &sh->frags[i - 1]; + sg->sg_segs[i].vaddr = (uint8_t *)(page_address(f->page) + + f->page_offset); + sg->sg_segs[i].len = f->size; + + adf_os_assert(i < ADF_OS_MAX_SGLIST); + } + sg->nsegs += i; +#endif +} + +a_status_t +__adf_nbuf_set_rx_cksum(struct sk_buff *skb, adf_nbuf_rx_cksum_t *cksum) +{ + switch (cksum->l4_result) { + case ADF_NBUF_RX_CKSUM_NONE: + skb->ip_summed = CHECKSUM_NONE; + break; + case ADF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY: + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + case ADF_NBUF_RX_CKSUM_TCP_UDP_HW: + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = cksum->val; + break; + default: + printk("ADF_NET:Unknown checksum type\n"); + adf_os_assert(0); + return A_STATUS_ENOTSUPP; + } + return A_STATUS_OK; +} + +adf_nbuf_tx_cksum_t +__adf_nbuf_get_tx_cksum(struct sk_buff *skb) +{ + switch (skb->ip_summed) { + case CHECKSUM_NONE: + return ADF_NBUF_TX_CKSUM_NONE; + case CHECKSUM_PARTIAL: + /* XXX ADF and Linux checksum don't map with 1-to-1. This is not 100% + * correct. */ + return ADF_NBUF_TX_CKSUM_TCP_UDP; + case CHECKSUM_COMPLETE: + return ADF_NBUF_TX_CKSUM_TCP_UDP_IP; + default: + return ADF_NBUF_TX_CKSUM_NONE; + } +} + +a_status_t +__adf_nbuf_get_vlan_info(adf_net_handle_t hdl, struct sk_buff *skb, + adf_net_vlanhdr_t *vlan) +{ + return A_STATUS_OK; +} + +a_uint8_t +__adf_nbuf_get_tid(struct sk_buff *skb) +{ + return skb->priority; +} + +void +__adf_nbuf_set_tid(struct sk_buff *skb, a_uint8_t tid) +{ + skb->priority = tid; +} + +a_uint8_t +__adf_nbuf_get_exemption_type(struct sk_buff *skb) +{ + return ADF_NBUF_EXEMPT_NO_EXEMPTION; +} + +void +__adf_nbuf_dmamap_set_cb(__adf_os_dma_map_t dmap, void *cb, void *arg) +{ + return; +} + +void +__adf_nbuf_reg_trace_cb(adf_nbuf_trace_update_t cb_func_ptr) +{ + trace_update_cb = cb_func_ptr; + return; +} + +a_status_t +__adf_nbuf_is_dhcp_pkt(struct sk_buff *skb) +{ + a_uint16_t SPort; + a_uint16_t DPort; + + SPort = (a_uint16_t)(*(a_uint16_t *)(skb->data + ADF_NBUF_TRAC_IPV4_OFFSET + + ADF_NBUF_TRAC_IPV4_HEADER_SIZE)); + DPort = (a_uint16_t)(*(a_uint16_t *)(skb->data + ADF_NBUF_TRAC_IPV4_OFFSET + + ADF_NBUF_TRAC_IPV4_HEADER_SIZE + sizeof(a_uint16_t))); + + if (((ADF_NBUF_TRAC_DHCP_SRV_PORT == adf_os_cpu_to_be16(SPort)) && + (ADF_NBUF_TRAC_DHCP_CLI_PORT == adf_os_cpu_to_be16(DPort))) || + ((ADF_NBUF_TRAC_DHCP_CLI_PORT == adf_os_cpu_to_be16(SPort)) && + (ADF_NBUF_TRAC_DHCP_SRV_PORT == adf_os_cpu_to_be16(DPort)))) + { + return A_STATUS_OK; + } + else + { + return A_STATUS_FAILED; + } +} + +a_status_t +__adf_nbuf_is_eapol_pkt(struct sk_buff *skb) +{ + a_uint16_t ether_type; + + ether_type = (a_uint16_t)(*(a_uint16_t *)(skb->data + ADF_NBUF_TRAC_ETH_TYPE_OFFSET)); + if (ADF_NBUF_TRAC_EAPOL_ETH_TYPE == adf_os_cpu_to_be16(ether_type)) + { + return A_STATUS_OK; + } + else + { + return A_STATUS_FAILED; + } +} + +#ifdef QCA_PKT_PROTO_TRACE +void +__adf_nbuf_trace_update(struct sk_buff *buf, char *event_string) +{ + char string_buf[NBUF_PKT_TRAC_MAX_STRING]; + + if ((!trace_update_cb) || (!event_string)) { + return; + } + + if (!adf_nbuf_trace_get_proto_type(buf)) { + return; + } + + /* Buffer over flow */ + if (NBUF_PKT_TRAC_MAX_STRING <= + (adf_os_str_len(event_string) + NBUF_PKT_TRAC_PROTO_STRING)) { + return; + } + + adf_os_mem_zero(string_buf, + NBUF_PKT_TRAC_MAX_STRING); + adf_os_mem_copy(string_buf, + event_string, adf_os_str_len(event_string)); + if (NBUF_PKT_TRAC_TYPE_EAPOL & + adf_nbuf_trace_get_proto_type(buf)) { + adf_os_mem_copy(string_buf + adf_os_str_len(event_string), + "EPL", + NBUF_PKT_TRAC_PROTO_STRING); + } + else if (NBUF_PKT_TRAC_TYPE_DHCP & + adf_nbuf_trace_get_proto_type(buf)) { + adf_os_mem_copy(string_buf + adf_os_str_len(event_string), + "DHC", + NBUF_PKT_TRAC_PROTO_STRING); + } else if (NBUF_PKT_TRAC_TYPE_MGMT_ACTION & + adf_nbuf_trace_get_proto_type(buf)) { + adf_os_mem_copy(string_buf + adf_os_str_len(event_string), + "MACT", + NBUF_PKT_TRAC_PROTO_STRING); + } + + trace_update_cb(string_buf); + return; +} +#endif /* QCA_PKT_PROTO_TRACE */ + +EXPORT_SYMBOL(__adf_nbuf_alloc); +#ifdef QCA_ARP_SPOOFING_WAR +EXPORT_SYMBOL(__adf_rx_nbuf_alloc); +#endif +EXPORT_SYMBOL(__adf_nbuf_free); +EXPORT_SYMBOL(__adf_nbuf_ref); +EXPORT_SYMBOL(__adf_nbuf_shared); +EXPORT_SYMBOL(__adf_nbuf_frag_info); +EXPORT_SYMBOL(__adf_nbuf_dmamap_create); +EXPORT_SYMBOL(__adf_nbuf_dmamap_destroy); +EXPORT_SYMBOL(__adf_nbuf_map); +EXPORT_SYMBOL(__adf_nbuf_unmap); +EXPORT_SYMBOL(__adf_nbuf_map_single); +EXPORT_SYMBOL(__adf_nbuf_unmap_single); +EXPORT_SYMBOL(__adf_nbuf_dmamap_info); +EXPORT_SYMBOL(__adf_nbuf_set_rx_cksum); +EXPORT_SYMBOL(__adf_nbuf_get_tx_cksum); +EXPORT_SYMBOL(__adf_nbuf_get_vlan_info); +EXPORT_SYMBOL(__adf_nbuf_get_tid); +EXPORT_SYMBOL(__adf_nbuf_set_tid); +EXPORT_SYMBOL(__adf_nbuf_get_exemption_type); +EXPORT_SYMBOL(__adf_nbuf_dmamap_set_cb); +EXPORT_SYMBOL(__adf_nbuf_is_dhcp_pkt); +EXPORT_SYMBOL(__adf_nbuf_is_eapol_pkt); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h new file mode 100644 index 000000000000..7b49f0d8b0d5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h @@ -0,0 +1,1194 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @defgroup adf_nbuf_public network buffer API + */ + +/** + * @ingroup adf_nbuf_public + * @file adf_nbuf.h + * This file defines the network buffer abstraction. + */ + +#ifndef _ADF_NBUF_H +#define _ADF_NBUF_H +#include +#include +#include +#include +#include + +#ifdef IPA_OFFLOAD +#define IPA_NBUF_OWNER_ID 0xaa55aa55 +#endif + +#define NBUF_PKT_TRAC_TYPE_EAPOL 0x02 +#define NBUF_PKT_TRAC_TYPE_DHCP 0x04 +#define NBUF_PKT_TRAC_TYPE_MGMT_ACTION 0x08 +#define NBUF_PKT_TRAC_MAX_STRING 12 +#define NBUF_PKT_TRAC_PROTO_STRING 4 + +#define ADF_NBUF_TRAC_IPV4_OFFSET 14 +#define ADF_NBUF_TRAC_IPV4_HEADER_SIZE 20 +#define ADF_NBUF_TRAC_DHCP_SRV_PORT 67 +#define ADF_NBUF_TRAC_DHCP_CLI_PORT 68 +#define ADF_NBUF_TRAC_ETH_TYPE_OFFSET 12 +#define ADF_NBUF_TRAC_EAPOL_ETH_TYPE 0x888E + +/** + * @brief Platform indepedent packet abstraction + */ +typedef __adf_nbuf_t adf_nbuf_t; + +/** + * @brief Dma map callback prototype + */ +typedef void (*adf_os_dma_map_cb_t)(void *arg, adf_nbuf_t buf, + adf_os_dma_map_t dmap); + +/** + * @brief invalid handle + */ +#define ADF_NBUF_NULL __ADF_NBUF_NULL +/** + * @brief Platform independent packet queue abstraction + */ +typedef __adf_nbuf_queue_t adf_nbuf_queue_t; + +/** + * BUS/DMA mapping routines + */ + +/** + * @brief Create a DMA map. This can later be used to map + * networking buffers. They : + * - need space in adf_drv's software descriptor + * - are typically created during adf_drv_create + * - need to be created before any API(adf_nbuf_map) that uses them + * + * @param[in] osdev os device + * @param[out] dmap map handle + * + * @return status of the operation + */ +static inline a_status_t +adf_nbuf_dmamap_create(adf_os_device_t osdev, + adf_os_dma_map_t *dmap) +{ + return (__adf_nbuf_dmamap_create(osdev, dmap)); +} + + +/** + * @brief Delete a dmap map + * + * @param[in] osdev os device + * @param[in] dmap + */ +static inline void +adf_nbuf_dmamap_destroy(adf_os_device_t osdev, adf_os_dma_map_t dmap) +{ + __adf_nbuf_dmamap_destroy(osdev, dmap); +} + +/** + * @brief Setup the map callback for a dma map + * + * @param[in] map DMA map + * @param[in] cb callback function + * @param[in] arg context for callback function + */ +static inline void +adf_nbuf_dmamap_set_cb(adf_os_dma_map_t dmap, adf_os_dma_map_cb_t cb, + void *arg) +{ + __adf_nbuf_dmamap_set_cb(dmap, cb, arg); +} + +/** + * @brief Map a buffer to local bus address space + * + * @param[in] osdev os device + * @param[in] buf buf to be mapped + * (mapping info is stored in the buf's meta-data area) + * @param[in] dir DMA direction + * + * @return status of the operation + */ +static inline a_status_t +adf_nbuf_map(adf_os_device_t osdev, + adf_nbuf_t buf, + adf_os_dma_dir_t dir) +{ +#if defined(HIF_PCI) + return __adf_nbuf_map(osdev, buf, dir); +#else + return 0; +#endif +} + + +/** + * @brief Unmap a previously mapped buf + * + * @param[in] osdev os device + * @param[in] buf buf to be unmapped + * (mapping info is stored in the buf's meta-data area) + * @param[in] dir DMA direction + */ +static inline void +adf_nbuf_unmap(adf_os_device_t osdev, + adf_nbuf_t buf, + adf_os_dma_dir_t dir) +{ +#if defined(HIF_PCI) + __adf_nbuf_unmap(osdev, buf, dir); +#endif +} + +static inline a_status_t +adf_nbuf_map_single( + adf_os_device_t osdev, adf_nbuf_t buf, adf_os_dma_dir_t dir) +{ +#if defined(HIF_PCI) + return __adf_nbuf_map_single(osdev, buf, dir); +#else + return 0; +#endif +} + +static inline void +adf_nbuf_unmap_single( + adf_os_device_t osdev, adf_nbuf_t buf, adf_os_dma_dir_t dir) +{ +#if defined(HIF_PCI) + __adf_nbuf_unmap_single(osdev, buf, dir); +#endif +} + +static inline int +adf_nbuf_get_num_frags(adf_nbuf_t buf) +{ + return __adf_nbuf_get_num_frags(buf); +} + +static inline int +adf_nbuf_get_frag_len(adf_nbuf_t buf, int frag_num) +{ + return __adf_nbuf_get_frag_len(buf, frag_num); +} + +static inline unsigned char * +adf_nbuf_get_frag_vaddr(adf_nbuf_t buf, int frag_num) +{ + return __adf_nbuf_get_frag_vaddr(buf, frag_num); +} + +static inline a_uint32_t +adf_nbuf_get_frag_paddr_lo(adf_nbuf_t buf, int frag_num) +{ + return __adf_nbuf_get_frag_paddr_lo(buf, frag_num); +} + +static inline int +adf_nbuf_get_frag_is_wordstream(adf_nbuf_t buf, int frag_num) +{ + return __adf_nbuf_get_frag_is_wordstream(buf, frag_num); +} + +static inline void +adf_nbuf_set_frag_is_wordstream(adf_nbuf_t buf, int frag_num, int is_wordstream) +{ + __adf_nbuf_set_frag_is_wordstream(buf, frag_num, is_wordstream); +} + +static inline void +adf_nbuf_frag_push_head( + adf_nbuf_t buf, + int frag_len, + char *frag_vaddr, + u_int32_t frag_paddr_lo, + u_int32_t frag_paddr_hi) +{ + __adf_nbuf_frag_push_head( + buf, frag_len, frag_vaddr, frag_paddr_lo, frag_paddr_hi); +} + +/** + * @brief returns information about the mapped buf + * + * @param[in] bmap map handle + * @param[out] sg map info + */ +static inline void +adf_nbuf_dmamap_info(adf_os_dma_map_t bmap, adf_os_dmamap_info_t *sg) +{ + __adf_nbuf_dmamap_info(bmap, sg); +} + + + +/* + * nbuf allocation rouines + */ + + +/** + * @brief Allocate adf_nbuf + * + * The nbuf created is guarenteed to have only 1 physical segment + * + * @param[in] hdl platform device object + * @param[in] size data buffer size for this adf_nbuf including max header + * size + * @param[in] reserve headroom to start with. + * @param[in] align alignment for the start buffer. + * @param[i] prio Indicate if the nbuf is high priority (some OSes e.g darwin + * polls few times if allocation fails and priority is TRUE) + * + * @return The new adf_nbuf instance or NULL if there's not enough memory. + */ +static inline adf_nbuf_t +adf_nbuf_alloc(adf_os_device_t osdev, + adf_os_size_t size, + int reserve, + int align, + int prio) +{ + return __adf_nbuf_alloc(osdev, size, reserve,align, prio); +} + +#ifdef QCA_ARP_SPOOFING_WAR +/** + * adf_rx_nbuf_alloc() Allocate adf_nbuf for Rx packet + * + * The nbuf created is guarenteed to have only 1 physical segment + * + * @hdl: platform device object + * @size: data buffer size for this adf_nbuf including max header + * size + * @reserve: headroom to start with. + * @align: alignment for the start buffer. + * @prio: Indicate if the nbuf is high priority (some OSes e.g darwin + * polls few times if allocation fails and priority is TRUE) + * + * Return: The new adf_nbuf instance or NULL if there's not enough memory. + */ +static inline adf_nbuf_t +adf_rx_nbuf_alloc(adf_os_device_t osdev, + adf_os_size_t size, + int reserve, + int align, + int prio) +{ + return __adf_rx_nbuf_alloc(osdev, size, reserve,align, prio); +} +#endif + +/** + * @brief Free adf_nbuf + * + * @param[in] buf buffer to free + */ +static inline void +adf_nbuf_free(adf_nbuf_t buf) +{ + __adf_nbuf_free(buf); +} + +/** + * @brief Free adf_nbuf + * + * @param[in] buf buffer to free + */ +static inline void +adf_nbuf_ref(adf_nbuf_t buf) +{ + __adf_nbuf_ref(buf); +} + +/** + * @brief Check whether the buffer is shared + * @param skb: buffer to check + * + * Returns true if more than one person has a reference to this + * buffer. + */ +static inline int +adf_nbuf_shared(adf_nbuf_t buf) +{ + return __adf_nbuf_shared(buf); +} + + +/** + * @brief Free a list of adf_nbufs and tell the OS their tx status (if req'd) + * + * @param[in] bufs - list of netbufs to free + * @param[in] tx_err - whether the tx frames were transmitted successfully + */ +static inline void +adf_nbuf_tx_free(adf_nbuf_t buf_list, int tx_err) +{ + __adf_nbuf_tx_free(buf_list, tx_err); +} + +/** + * @brief Reallocate such that there's required headroom in + * buf. Note that this can allocate a new buffer, or + * change geometry of the orignial buffer. The new buffer + * is returned in the (new_buf). + * + * @param[in] buf (older buffer) + * @param[in] headroom + * + * @return newly allocated buffer + */ +static inline adf_nbuf_t +adf_nbuf_realloc_headroom(adf_nbuf_t buf, a_uint32_t headroom) +{ + return (__adf_nbuf_realloc_headroom(buf, headroom)); +} + + +/** + * @brief expand the tailroom to the new tailroom, but the buffer + * remains the same + * + * @param[in] buf buffer + * @param[in] tailroom new tailroom + * + * @return expanded buffer or NULL on failure + */ +static inline adf_nbuf_t +adf_nbuf_realloc_tailroom(adf_nbuf_t buf, a_uint32_t tailroom) +{ + return (__adf_nbuf_realloc_tailroom(buf, tailroom)); +} + + +/** + * @brief this will expand both tail & head room for a given + * buffer, you may or may not get a new buffer.Use it + * only when its required to expand both. Otherwise use + * realloc (head/tail) will solve the purpose. Reason for + * having an extra API is that some OS do this in more + * optimized way, rather than calling realloc (head/tail) + * back to back. + * + * @param[in] buf buffer + * @param[in] headroom new headroom + * @param[in] tailroom new tailroom + * + * @return expanded buffer + */ +static inline adf_nbuf_t +adf_nbuf_expand(adf_nbuf_t buf, a_uint32_t headroom, a_uint32_t tailroom) +{ + return (__adf_nbuf_expand(buf,headroom,tailroom)); +} + + +/** + * @brief Copy src buffer into dst. This API is useful, for + * example, because most native buffer provide a way to + * copy a chain into a single buffer. Therefore as a side + * effect, it also "linearizes" a buffer (which is + * perhaps why you'll use it mostly). It creates a + * writeable copy. + * + * @param[in] buf source nbuf to copy from + * + * @return the new nbuf + */ +static inline adf_nbuf_t +adf_nbuf_copy(adf_nbuf_t buf) +{ + return(__adf_nbuf_copy(buf)); +} + + +/** + * @brief link two nbufs, the new buf is piggybacked into the + * older one. + * + * @param[in] dst buffer to piggyback into + * @param[in] src buffer to put + * + * @return status of the call - 0 successful + */ +static inline a_status_t +adf_nbuf_cat(adf_nbuf_t dst, adf_nbuf_t src) +{ + return __adf_nbuf_cat(dst, src); +} + + +/** + * @brief return the length of the copy bits for skb + * + * @param skb, offset, len, to + * + * @return int32_t + */ +static inline int32_t +adf_nbuf_copy_bits(adf_nbuf_t nbuf, u_int32_t offset, u_int32_t len, void *to) +{ + return __adf_nbuf_copy_bits(nbuf, offset, len, to); +} + + +/** + * @brief clone the nbuf (copy is readonly) + * + * @param[in] buf nbuf to clone from + * + * @return cloned buffer + */ +static inline adf_nbuf_t +adf_nbuf_clone(adf_nbuf_t buf) +{ + return(__adf_nbuf_clone(buf)); +} + + +/** + * @brief Create a version of the specified nbuf whose + * contents can be safely modified without affecting + * other users.If the nbuf is a clone then this function + * creates a new copy of the data. If the buffer is not + * a clone the original buffer is returned. + * + * @param[in] buf source nbuf to create a writable copy from + * + * @return new buffer which is writeable + */ +static inline adf_nbuf_t +adf_nbuf_unshare(adf_nbuf_t buf) +{ + return(__adf_nbuf_unshare(buf)); +} + + + +/* + * nbuf manipulation routines + */ + +/** + * @brief return the address of an nbuf's buffer + * + * @param[in] buf netbuf + * + * @return head address + */ +static inline a_uint8_t * +adf_nbuf_head(adf_nbuf_t buf) +{ + return __adf_nbuf_head(buf); +} + +/** + * @brief return the address of the start of data within an nbuf + * + * @param[in] buf buffer + * + * @return data address + */ +static inline a_uint8_t * +adf_nbuf_data(adf_nbuf_t buf) +{ + return __adf_nbuf_data(buf); +} + + +/** + * @brief return the amount of headroom int the current nbuf + * + * @param[in] buf buffer + * + * @return amount of head room + */ +static inline a_uint32_t +adf_nbuf_headroom(adf_nbuf_t buf) +{ + return (__adf_nbuf_headroom(buf)); +} + + +/** + * @brief return the amount of tail space available + * + * @param[in] buf buffer + * + * @return amount of tail room + */ +static inline a_uint32_t +adf_nbuf_tailroom(adf_nbuf_t buf) +{ + return (__adf_nbuf_tailroom(buf)); +} + + +/** + * @brief Push data in the front + * + * @param[in] buf buf instance + * @param[in] size size to be pushed + * + * @return New data pointer of this buf after data has been pushed, + * or NULL if there is not enough room in this buf. + */ +static inline a_uint8_t * +adf_nbuf_push_head(adf_nbuf_t buf, adf_os_size_t size) +{ + return __adf_nbuf_push_head(buf, size); +} + + +/** + * @brief Puts data in the end + * + * @param[in] buf buf instance + * @param[in] size size to be pushed + * + * @return data pointer of this buf where new data has to be + * put, or NULL if there is not enough room in this buf. + */ +static inline a_uint8_t * +adf_nbuf_put_tail(adf_nbuf_t buf, adf_os_size_t size) +{ + return __adf_nbuf_put_tail(buf, size); +} + +/** + * @brief before put buf into pool,turn it to init state + * + * @param[in] buf buf instance + * @param[in] reserve headroom to start with. + * @param[in] align alignment for the start buffer. + * @param[in] tail_size put size to the tail of buffer + * + * @return data pointer of this buf where new data has to be + * put, or NULL if there is not enough room in this buf. + */ + +static inline a_uint8_t * +adf_nbuf_init(adf_nbuf_t buf, adf_os_size_t reverse, adf_os_size_t align, adf_os_size_t tail_size) +{ + return __adf_nbuf_init(buf, reverse, align, tail_size); +} + +static inline void +adf_nbuf_free_pool(adf_nbuf_t buf) +{ + __adf_nbuf_free_pool(buf); +} + +/** + * @brief pull data out from the front + * + * @param[in] buf buf instance + * @param[in] size size to be popped + * + * @return New data pointer of this buf after data has been popped, + * or NULL if there is not sufficient data to pull. + */ +static inline a_uint8_t * +adf_nbuf_pull_head(adf_nbuf_t buf, adf_os_size_t size) +{ + return __adf_nbuf_pull_head(buf, size); +} + + +/** + * + * @brief trim data out from the end + * + * @param[in] buf buf instance + * @param[in] size size to be popped + * + * @return none + */ +static inline void +adf_nbuf_trim_tail(adf_nbuf_t buf, adf_os_size_t size) +{ + __adf_nbuf_trim_tail(buf, size); +} + + +/** + * @brief Get the length of the buf + * + * @param[in] buf the buf instance + * + * @return The total length of this buf. + */ +static inline adf_os_size_t +adf_nbuf_len(adf_nbuf_t buf) +{ + return (__adf_nbuf_len(buf)); +} + +/** + * @brief Set the length of the buf + * + * @param[in] buf the buf instance + * @param[in] size to be set + * + * @return none + */ +static inline void +adf_nbuf_set_pktlen(adf_nbuf_t buf, uint32_t len) +{ + __adf_nbuf_set_pktlen(buf, len); +} + +/** + * @brief test whether the nbuf is cloned or not + * + * @param[in] buf buffer + * + * @return TRUE if it is cloned, else FALSE + */ +static inline a_bool_t +adf_nbuf_is_cloned(adf_nbuf_t buf) +{ + return (__adf_nbuf_is_cloned(buf)); +} + +/** + * + * @brief trim data out from the end + * + * @param[in] buf buf instance + * @param[in] size size to be popped + * + * @return none + */ +static inline void +adf_nbuf_reserve(adf_nbuf_t buf, adf_os_size_t size) +{ + __adf_nbuf_reserve(buf, size); +} + + +/* + * nbuf frag routines + */ + +/** + * @brief return the frag pointer & length of the frag + * + * @param[in] buf buffer + * @param[out] sg this will return all the frags of the nbuf + * + */ +static inline void +adf_nbuf_frag_info(adf_nbuf_t buf, adf_os_sglist_t *sg) +{ + __adf_nbuf_frag_info(buf, sg); +} +/** + * @brief return the data pointer & length of the header + * + * @param[in] buf nbuf + * @param[out] addr data pointer + * @param[out] len length of the data + * + */ +static inline void +adf_nbuf_peek_header(adf_nbuf_t buf, a_uint8_t **addr, a_uint32_t *len) +{ + __adf_nbuf_peek_header(buf, addr, len); +} +/* + * nbuf private context routines + */ + +/** + * @brief get the priv pointer from the nbuf'f private space + * + * @param[in] buf + * + * @return data pointer to typecast into your priv structure + */ +static inline a_uint8_t * +adf_nbuf_get_priv(adf_nbuf_t buf) +{ + return (__adf_nbuf_get_priv(buf)); +} + + +/* + * nbuf queue routines + */ + + +/** + * @brief Initialize buf queue + * + * @param[in] head buf queue head + */ +static inline void +adf_nbuf_queue_init(adf_nbuf_queue_t *head) +{ + __adf_nbuf_queue_init(head); +} + + +/** + * @brief Append a nbuf to the tail of the buf queue + * + * @param[in] head buf queue head + * @param[in] buf buf + */ +static inline void +adf_nbuf_queue_add(adf_nbuf_queue_t *head, adf_nbuf_t buf) +{ + __adf_nbuf_queue_add(head, buf); +} + +/** + * @brief Insert nbuf at the head of queue + * + * @param[in] head buf queue head + * @param[in] buf buf + */ +static inline void +adf_nbuf_queue_insert_head(adf_nbuf_queue_t *head, adf_nbuf_t buf) +{ + __adf_nbuf_queue_insert_head(head, buf); +} + +/** + * @brief Retrieve a buf from the head of the buf queue + * + * @param[in] head buf queue head + * + * @return The head buf in the buf queue. + */ +static inline adf_nbuf_t +adf_nbuf_queue_remove(adf_nbuf_queue_t *head) +{ + return __adf_nbuf_queue_remove(head); +} + + +/** + * @brief get the length of the queue + * + * @param[in] head buf queue head + * + * @return length of the queue + */ +static inline a_uint32_t +adf_nbuf_queue_len(adf_nbuf_queue_t *head) +{ + return __adf_nbuf_queue_len(head); +} + + +/** + * @brief get the first guy/packet in the queue + * + * @param[in] head buf queue head + * + * @return first buffer in queue + */ +static inline adf_nbuf_t +adf_nbuf_queue_first(adf_nbuf_queue_t *head) +{ + return (__adf_nbuf_queue_first(head)); +} + + +/** + * @brief get the next guy/packet of the given buffer (or + * packet) + * + * @param[in] buf buffer + * + * @return next buffer/packet + */ +static inline adf_nbuf_t +adf_nbuf_queue_next(adf_nbuf_t buf) +{ + return (__adf_nbuf_queue_next(buf)); +} + + +/** + * @brief Check if the buf queue is empty + * + * @param[in] nbq buf queue handle + * + * @return TRUE if queue is empty + * @return FALSE if queue is not emty + */ +static inline a_bool_t +adf_nbuf_is_queue_empty(adf_nbuf_queue_t * nbq) +{ + return __adf_nbuf_is_queue_empty(nbq); +} + + +/** + * @brief get the next packet in the linked list + * @details + * This function can be used when nbufs are directly linked into a list, + * rather than using a separate network buffer queue object. + * + * @param[in] buf buffer + * + * @return next network buffer in the linked list + */ +static inline adf_nbuf_t +adf_nbuf_next(adf_nbuf_t buf) +{ + return __adf_nbuf_next(buf); +} + + +/** + * @brief add a packet to a linked list + * @details + * This function can be used to directly link nbufs, rather than using + * a separate network buffer queue object. + * + * @param[in] this_buf predecessor buffer + * @param[in] next_buf successor buffer + */ +static inline void +adf_nbuf_set_next(adf_nbuf_t this_buf, adf_nbuf_t next_buf) +{ + __adf_nbuf_set_next(this_buf, next_buf); +} + + +/* + * nbuf extension routines XXX + */ + +/** + * @brief link extension of this packet contained in a new nbuf + * @details + * This function is used to link up many nbufs containing a single logical + * packet - not a collection of packets. Do not use for linking the first + * extension to the head + * @param[in] this_buf predecessor buffer + * @param[in] next_buf successor buffer + */ +static inline void +adf_nbuf_set_next_ext(adf_nbuf_t this_buf, adf_nbuf_t next_buf) +{ + __adf_nbuf_set_next_ext(this_buf, next_buf); +} + +/** + * @brief get the next packet extension in the linked list + * @details + * + * @param[in] buf buffer + * + * @return next network buffer in the linked list + */ +static inline adf_nbuf_t +adf_nbuf_next_ext(adf_nbuf_t buf) +{ + return __adf_nbuf_next_ext(buf); +} + +/** + * @brief link list of packet extensions to the head segment + * @details + * This function is used to link up a list of packet extensions (seg1, 2, + * ...) to the nbuf holding the head segment (seg0) + * @param[in] head_buf nbuf holding head segment (single) + * @param[in] ext_list nbuf list holding linked extensions to the head + * @param[in] ext_len Total length of all buffers in the extension list + */ +static inline void +adf_nbuf_append_ext_list(adf_nbuf_t head_buf, adf_nbuf_t ext_list, + adf_os_size_t ext_len) +{ + __adf_nbuf_append_ext_list(head_buf, ext_list, ext_len); +} + +/** + * @brief Gets the tx checksumming to be performed on this buf + * + * @param[in] buf buffer + * @param[out] hdr_off the (tcp) header start + * @param[out] where the checksum offset + */ +static inline adf_net_cksum_type_t +adf_nbuf_tx_cksum_info(adf_nbuf_t buf, a_uint8_t **hdr_off, a_uint8_t **where) +{ + return(__adf_nbuf_tx_cksum_info(buf, hdr_off, where)); +} + + +/** + * @brief Gets the tx checksum offload demand + * + * @param[in] buf buffer + * @return adf_nbuf_tx_cksum_t checksum offload demand for the frame + */ +static inline adf_nbuf_tx_cksum_t +adf_nbuf_get_tx_cksum(adf_nbuf_t buf) +{ + return (__adf_nbuf_get_tx_cksum(buf)); +} + +/** + * @brief Drivers that support hw checksumming use this to + * indicate checksum info to the stack. + * + * @param[in] buf buffer + * @param[in] cksum checksum + */ +static inline void +adf_nbuf_set_rx_cksum(adf_nbuf_t buf, adf_nbuf_rx_cksum_t *cksum) +{ + __adf_nbuf_set_rx_cksum(buf, cksum); +} + + +/** + * @brief Drivers that are capable of TCP Large segment offload + * use this to get the offload info out of an buf. + * + * @param[in] buf buffer + * @param[out] tso offload info + */ +static inline void +adf_nbuf_get_tso_info(adf_nbuf_t buf, adf_nbuf_tso_t *tso) +{ + __adf_nbuf_get_tso_info(buf, tso); +} + + +/*static inline void +adf_nbuf_set_vlan_info(adf_nbuf_t buf, adf_net_vlan_tag_t vlan_tag) +{ + __adf_nbuf_set_vlan_info(buf, vlan_tag); +}*/ + +/** + * @brief This function extracts the vid & priority from an + * nbuf + * + * + * @param[in] hdl net handle + * @param[in] buf buffer + * @param[in] vlan vlan header + * + * @return status of the operation + */ +static inline a_status_t +adf_nbuf_get_vlan_info(adf_net_handle_t hdl, adf_nbuf_t buf, + adf_net_vlanhdr_t *vlan) +{ + return __adf_nbuf_get_vlan_info(hdl, buf, vlan); +} + +/** + * @brief This function extracts the TID value from nbuf + * + * @param[in] buf buffer + * + * @return TID value + */ +static inline a_uint8_t +adf_nbuf_get_tid(adf_nbuf_t buf) +{ + return __adf_nbuf_get_tid(buf); +} + +/** + * @brief This function sets the TID value in nbuf + * + * @param[in] buf buffer + * + * @param[in] tid TID value + */ +static inline void +adf_nbuf_set_tid(adf_nbuf_t buf, a_uint8_t tid) +{ + __adf_nbuf_set_tid(buf, tid); +} + +/** + * @brief This function extracts the exemption type from nbuf + * + * @param[in] buf buffer + * + * @return exemption type + */ +static inline a_uint8_t +adf_nbuf_get_exemption_type(adf_nbuf_t buf) +{ + return __adf_nbuf_get_exemption_type(buf); +} + +static inline void +adf_nbuf_reset_ctxt(__adf_nbuf_t nbuf) +{ + __adf_nbuf_reset_ctxt(nbuf); +} + +/** + * @brief This function peeks data into the buffer at given offset + * + * @param[in] buf buffer + * @param[out] data peeked output buffer + * @param[in] off offset + * @param[in] len length of buffer requested beyond offset + * + * @return status of operation + */ +static inline a_status_t +adf_nbuf_peek_data(adf_nbuf_t buf, void **data, a_uint32_t off, + a_uint32_t len) +{ + return __adf_nbuf_peek_data(buf, data, off, len); +} + +/** + * @brief This function peeks data into the buffer at given offset + * + * @param[in] buf buffer + * @param[in] proto protocol + */ +static inline void +adf_nbuf_set_protocol(adf_nbuf_t buf, uint16_t proto) +{ + __adf_nbuf_set_protocol(buf, proto); +} + +/** + * @brief This function return packet proto type + * + * @param[in] buf buffer + */ +static inline uint8_t +adf_nbuf_trace_get_proto_type(adf_nbuf_t buf) +{ + return __adf_nbuf_trace_get_proto_type(buf); +} + +/** + * @brief This function updates packet proto type + * + * @param[in] buf buffer + * @param[in] proto_type protocol type +*/ +static inline void +adf_nbuf_trace_set_proto_type(adf_nbuf_t buf, uint8_t proto_type) +{ + __adf_nbuf_trace_set_proto_type(buf, proto_type); +} + +/** + * @brief This function registers protocol trace callback + * + * @param[in] adf_nbuf_trace_update_t callback pointer + */ +static inline void +adf_nbuf_reg_trace_cb(adf_nbuf_trace_update_t cb_func_ptr) +{ + __adf_nbuf_reg_trace_cb(cb_func_ptr); +} + +/** + * @brief This function updates protocol event + * + * @param[in] buf buffer + * @param[in] char * event string + */ +static inline void +adf_nbuf_trace_update(adf_nbuf_t buf, char *event_string) +{ + __adf_nbuf_trace_update(buf, event_string); +} + +/** + * @brief This function stores a flag specifying this TX frame + * is suitable for downloading though a 2nd TX data pipe + * that is used for short frames for protocols that can + * accept out-of-order delivery. + * + * @param[in] buf buffer + * @param[in] candi candidate of parallel download frame + */ +static inline void +adf_nbuf_set_tx_parallel_dnload_frm(adf_nbuf_t buf, uint8_t candi) +{ + __adf_nbuf_set_tx_htt2_frm(buf, candi); +} + +/** + * @brief This function return whether this TX frame is allow + * to download though a 2nd TX data pipe or not. + * + * @param[in] buf buffer + */ +static inline uint8_t +adf_nbuf_get_tx_parallel_dnload_frm(adf_nbuf_t buf) +{ + return __adf_nbuf_get_tx_htt2_frm(buf); +} + +/** + * @brief this will return if the skb data is a dhcp packet or not + * + * @param[in] buf buffer + * + * @return A_STATUS_OK if packet is DHCP packet + */ +static inline a_status_t +adf_nbuf_is_dhcp_pkt(adf_nbuf_t buf) +{ + return (__adf_nbuf_is_dhcp_pkt(buf)); +} + +/** + * @brief this will return if the skb data is a eapol packet or not + * + * @param[in] buf buffer + * + * @return A_STATUS_OK if packet is EAPOL packet + */ +static inline a_status_t +adf_nbuf_is_eapol_pkt(adf_nbuf_t buf) +{ + return (__adf_nbuf_is_eapol_pkt(buf)); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_net_types.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_net_types.h new file mode 100644 index 000000000000..95428eb5596b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_net_types.h @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2011,2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @ingroup adf_net_public + * @file adf_net_types.h + * This file defines types used in the networking stack abstraction. + */ + +#ifndef _ADF_NET_TYPES_H +#define _ADF_NET_TYPES_H + +#include /* a_uint8_t, etc. */ + +/** + * @brief These control/get info from the device + */ +#define ADF_NET_CMD(_x) \ + ADF_NET_CMD_GET_##_x, \ + ADF_NET_CMD_SET_##_x + +/** + * @brief Get/Set commands from anet to adf_drv + */ +typedef enum { + ADF_NET_CMD(LINK_INFO), + ADF_NET_CMD(POLL_INFO), + ADF_NET_CMD(CKSUM_INFO), + ADF_NET_CMD(RING_INFO), + ADF_NET_CMD(MAC_ADDR), + ADF_NET_CMD(MTU), + ADF_NET_CMD_GET_DMA_INFO, + ADF_NET_CMD_GET_OFFLOAD_CAP, + ADF_NET_CMD_GET_STATS, + ADF_NET_CMD_ADD_VID, + ADF_NET_CMD_DEL_VID, + ADF_NET_CMD_SET_MCAST, + ADF_NET_CMD_GET_MCAST_CAP +}adf_net_cmd_t; + + + +/** + * @brief Indicates what features are supported by the interface. + */ +#define ADF_NET_LINK_SUPP_10baseT_Half (1 << 0) +#define ADF_NET_LINK_SUPP_10baseT_Full (1 << 1) +#define ADF_NET_LINK_SUPP_100baseT_Half (1 << 2) +#define ADF_NET_LINK_SUPP_100baseT_Full (1 << 3) +#define ADF_NET_LINK_SUPP_1000baseT_Half (1 << 4) +#define ADF_NET_LINK_SUPP_1000baseT_Full (1 << 5) +#define ADF_NET_LINK_SUPP_Autoneg (1 << 6) +#define ADF_NET_LINK_SUPP_Pause (1 << 7) +#define ADF_NET_LINK_SUPP_Asym_Pause (1 << 8) + +#define ADF_NET_LINK_SUPP_100 (ADF_NET_LINK_SUPP_10baseT_Half | \ + ADF_NET_LINK_SUPP_10baseT_Full | \ + ADF_NET_LINK_SUPP_100baseT_Half | \ + ADF_NET_LINK_SUPP_100baseT_Full) + +#define ADF_NET_LINK_SUPP_1000 (ADF_NET_LINK_SUPP_100 | \ + ADF_NET_LINK_SUPP_1000baseT_Full) + +/** + * @brief Indicates what features are advertised by the interface. + */ +#define ADF_NET_LINK_ADV_10baseT_Half (1 << 0) +#define ADF_NET_LINK_ADV_10baseT_Full (1 << 1) +#define ADF_NET_LINK_ADV_100baseT_Half (1 << 2) +#define ADF_NET_LINK_ADV_100baseT_Full (1 << 3) +#define ADF_NET_LINK_ADV_1000baseT_Half (1 << 4) +#define ADF_NET_LINK_ADV_1000baseT_Full (1 << 5) +#define ADF_NET_LINK_ADV_Autoneg (1 << 6) +#define ADF_NET_LINK_ADV_Pause (1 << 7) +#define ADF_NET_LINK_ADV_Asym_Pause (1 << 8) + +#define ADF_NET_LINK_ADV_100 (ADF_NET_LINK_ADV_10baseT_Half | \ + ADF_NET_LINK_ADV_10baseT_Full | \ + ADF_NET_LINK_ADV_100baseT_Half | \ + ADF_NET_LINK_ADV_100baseT_Full) + +#define ADF_NET_LINK_ADV_1000 (ADF_NET_LINK_ADV_100 | \ + ADF_NET_LINK_ADV_1000baseT_Full) + +/** + * @brief The forced/current speed/duplex/autoneg + */ +#define ADF_NET_LINK_SPEED_10 10 +#define ADF_NET_LINK_SPEED_100 100 +#define ADF_NET_LINK_SPEED_1000 1000 + +#define ADF_NET_LINK_DUPLEX_HALF 0x00 +#define ADF_NET_LINK_DUPLEX_FULL 0x01 + +#define ADF_NET_LINK_AUTONEG_DISABLE 0x00 +#define ADF_NET_LINK_AUTONEG_ENABLE 0x01 + +#define ADF_NET_MAC_ADDR_MAX_LEN 6 +#define ADF_NET_IF_NAME_SIZE 64 +#define ADF_NET_ETH_LEN ADF_NET_MAC_ADDR_MAX_LEN +#define ADF_NET_MAX_MCAST_ADDR 64 + + +/** + * @brief Extended Traffic ID passed to target if the TID is unknown + */ +#define ADF_NBUF_TX_EXT_TID_INVALID 0x1f + + +/** + * @brief Specify whether to encrypt frame or not + */ +enum adf_nbuf_exemption_type { + ADF_NBUF_EXEMPT_NO_EXEMPTION = 0, + ADF_NBUF_EXEMPT_ALWAYS, + ADF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE +}; + +typedef enum adf_net_flags{ + ADF_NET_IS_RUNNING = 0x0001, + ADF_NET_IS_UP = 0x0002, + ADF_NET_IS_ALLMULTI = 0x0004, + ADF_NET_IS_PROMISC = 0x0008 +}adf_net_flags_t; +/** + * @brief link info capability/parameters for the device + * Note the flags below + */ +typedef struct { + a_uint32_t supported; /*RO Features this if supports*/ + a_uint32_t advertized; /*Features this interface advertizes*/ + a_int16_t speed; /*Force speed 10M, 100M, gigE*/ + a_int8_t duplex; /*duplex full or half*/ + a_uint8_t autoneg; /*Enabled/disable autoneg*/ +}adf_net_cmd_link_info_t; + +typedef struct adf_net_ethaddr{ + a_uint8_t addr[ADF_NET_ETH_LEN]; +} adf_net_ethaddr_t; +typedef struct { + a_uint8_t ether_dhost[ADF_NET_ETH_LEN]; /* destination eth addr */ + a_uint8_t ether_shost[ADF_NET_ETH_LEN]; /* source ether addr */ + a_uint16_t ether_type; /* packet type ID field */ +}adf_net_ethhdr_t; + +typedef struct { +#if defined (ADF_LITTLE_ENDIAN_MACHINE) + a_uint8_t ip_hl:4, + ip_version:4; +#elif defined (ADF_BIG_ENDIAN_MACHINE) + a_uint8_t ip_version:4, + ip_hl:4; +#else +#error "Please fix" +#endif + a_uint8_t ip_tos; + + a_uint16_t ip_len; + a_uint16_t ip_id; + a_uint16_t ip_frag_off; + a_uint8_t ip_ttl; + a_uint8_t ip_proto; + a_uint16_t ip_check; + a_uint32_t ip_saddr; + a_uint32_t ip_daddr; + /*The options start here. */ + }adf_net_iphdr_t; + +typedef struct { + a_uint16_t src_port; + a_uint16_t dst_port; + a_uint16_t udp_len; + a_uint16_t udp_cksum; + }adf_net_udphdr_t; + +typedef struct { + a_uint8_t dhcp_msg_type; + a_uint8_t dhcp_hw_type; + a_uint8_t dhcp_hw_addr_len; + a_uint8_t dhcp_num_hops; + a_uint32_t dhcp_transc_id; + a_uint16_t dhcp_secs_elapsed; + a_uint16_t dhcp_flags; + a_uint32_t dhcp_ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ + a_uint32_t dhcp_yiaddr; /* 'your' (client) IP address */ + /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ + a_uint32_t dhcp_siaddr_nip; + a_uint32_t dhcp_gateway_nip; /* relay agent IP address */ + a_uint8_t dhcp_chaddr[16]; /* link-layer client hardware address (MAC) */ + a_uint8_t dhcp_sname[64]; /* server host name (ASCIZ) */ + a_uint8_t dhcp_file[128]; /* boot file name (ASCIZ) */ + a_uint8_t dhcp_cookie[4]; /* fixed first four option bytes (99,130,83,99 dec) */ + } adf_net_dhcphdr_t; + +/* @brief V3 group record types [grec_type] */ +#define IGMPV3_MODE_IS_INCLUDE 1 +#define IGMPV3_MODE_IS_EXCLUDE 2 +#define IGMPV3_CHANGE_TO_INCLUDE 3 +#define IGMPV3_CHANGE_TO_EXCLUDE 4 +#define IGMPV3_ALLOW_NEW_SOURCES 5 +#define IGMPV3_BLOCK_OLD_SOURCES 6 + +typedef struct { + a_uint8_t igmp_type; + a_uint8_t igmp_code; /* For newer IGMP */ + a_uint16_t igmp_csum; + a_uint32_t igmp_group; +} adf_net_igmphdr_t; + +typedef struct { + a_uint8_t grec_type; + a_uint8_t grec_auxwords; + a_uint16_t grec_nsrcs; + a_uint32_t grec_mca; + a_uint32_t grec_src[1]; +} adf_net_igmpv3_grec_t; + +/** + * @brief IGMP version 3 specific datatypes + */ +typedef struct { + a_uint8_t igmpv3_type; + a_uint8_t igmpv3_resv1; + a_uint16_t igmpv3_csum; + a_uint16_t igmpv3_resv2; + a_uint16_t igmpv3_ngrec; + adf_net_igmpv3_grec_t igmpv3_grec[1]; +} adf_net_igmpv3_report_t; + + +/** + * @brief Vlan header + */ +typedef struct adf_net_vlanhdr{ + a_uint16_t tpid; +#if defined (ADF_LITTLE_ENDIAN_MACHINE) + a_uint16_t vid:12; /* Vlan id*/ + a_uint8_t cfi:1; /* reserved for CFI, don't use*/ + a_uint8_t prio:3; /* Priority*/ +#elif defined (ADF_BIG_ENDIAN_MACHINE) + a_uint8_t prio:3; /* Priority*/ + a_uint8_t cfi:1; /* reserved for CFI, don't use*/ + a_uint16_t vid:12; /* Vlan id*/ +#else +#error "Please fix" +#endif +}adf_net_vlanhdr_t; + +typedef struct adf_net_vid{ +#if defined (ADF_LITTLE_ENDIAN_MACHINE) + a_uint16_t val:12; + a_uint8_t res:4; +#elif defined (ADF_BIG_ENDIAN_MACHINE) + a_uint8_t res:4; + a_uint16_t val:12; +#else +#error "Please fix" +#endif +}adf_net_vid_t; + + +/** + * @brief Command for setting ring paramters. + */ +typedef struct { + a_uint32_t rx_bufsize; /*Ro field. For shim's that maintain a pool*/ + a_uint32_t rx_ndesc; + a_uint32_t tx_ndesc; +}adf_net_cmd_ring_info_t; + +/** + * @brief Whether the interface is polled or not. If so, the polling bias (number of + * packets it wants to process per invocation + */ +typedef struct { + a_bool_t polled; + a_uint32_t poll_wt; +}adf_net_cmd_poll_info_t; + +/** + * @brief Basic device info + */ +typedef struct { + a_uint8_t if_name[ADF_NET_IF_NAME_SIZE]; + a_uint8_t dev_addr[ADF_NET_MAC_ADDR_MAX_LEN]; + a_uint16_t header_len; + a_uint16_t mtu_size; +}adf_net_dev_info_t; + +typedef struct adf_dma_info { + adf_os_dma_mask_t dma_mask; + a_uint32_t sg_nsegs; /**< scatter segments */ +}adf_net_cmd_dma_info_t; + +/** + * @brief Defines the TX and RX checksumming capabilities/state of the device + * The actual checksum handling happens on an adf_nbuf + * If offload capability command not supported, all offloads are assumed to be + * none. + */ +typedef enum { + ADF_NET_CKSUM_NONE, /*Cannot do any checksum*/ + ADF_NET_CKSUM_TCP_UDP_IPv4, /*tcp/udp on ipv4 with pseudo hdr*/ + ADF_NET_CKSUM_TCP_UDP_IPv6, /*tcp/udp on ipv6*/ +}adf_net_cksum_type_t; + +typedef struct { + adf_net_cksum_type_t tx_cksum; + adf_net_cksum_type_t rx_cksum; +}adf_net_cksum_info_t; + +typedef adf_net_cksum_info_t adf_net_cmd_cksum_info_t; /*XXX needed?*/ + +/** + * @brief Command for set/unset vid + */ +typedef a_uint16_t adf_net_cmd_vid_t ; /*get/set vlan id*/ + +typedef enum { + ADF_NET_TSO_NONE, + ADF_NET_TSO_IPV4, /**< for tsp ipv4 only*/ + ADF_NET_TSO_ALL, /**< ip4 & ipv6*/ +}adf_net_tso_type_t; + +/** + * @brief Command for getting offloading capabilities of a device + */ +typedef struct { + adf_net_cksum_info_t cksum_cap; + adf_net_tso_type_t tso; + a_uint8_t vlan_supported; +}adf_net_cmd_offload_cap_t; + +/** + * @brief Command for getting general stats from a device + */ +typedef struct { + a_uint32_t tx_packets; /**< total packets transmitted*/ + a_uint32_t rx_packets; /**< total packets recieved*/ + a_uint32_t tx_bytes; /**< total bytes transmitted*/ + a_uint32_t rx_bytes; /**< total bytes recieved*/ + a_uint32_t tx_dropped; /**< total tx dropped because of lack of buffers*/ + a_uint32_t rx_dropped; /**< total rx dropped because of lack of buffers*/ + a_uint32_t rx_errors; /**< bad packet recieved*/ + a_uint32_t tx_errors; /**< transmisison problems*/ +}adf_net_cmd_stats_t; + +typedef enum adf_net_cmd_mcast_cap{ + ADF_NET_MCAST_SUP=0, + ADF_NET_MCAST_NOTSUP +}adf_net_cmd_mcast_cap_t; + +typedef struct adf_net_devaddr{ + a_uint32_t num; /**< No. of mcast addresses*/ + a_uint8_t *da_addr[ADF_NET_MAX_MCAST_ADDR]; +}adf_net_devaddr_t; + +typedef adf_net_devaddr_t adf_net_cmd_mcaddr_t; +typedef adf_net_ethaddr_t adf_net_cmd_macaddr_t; + +typedef union { + adf_net_cmd_link_info_t link_info; + adf_net_cmd_poll_info_t poll_info; + adf_net_cmd_cksum_info_t cksum_info; + adf_net_cmd_ring_info_t ring_info; + adf_net_cmd_dma_info_t dma_info; + adf_net_cmd_vid_t vid; + adf_net_cmd_offload_cap_t offload_cap; + adf_net_cmd_stats_t stats; + adf_net_cmd_mcaddr_t mcast_info; + adf_net_cmd_mcast_cap_t mcast_cap; + adf_net_cmd_macaddr_t mac_addr; +}adf_net_cmd_data_t; + +/** + * @brief For polled devices, adf_drv responds with one of the following status in + * its poll function. + */ +typedef enum { + ADF_NET_POLL_DONE, + ADF_NET_POLL_NOT_DONE, + ADF_NET_POLL_OOM, +}adf_net_poll_resp_t; + +/** + * @brief For transmit checksum API + */ + +typedef enum { + ADF_NBUF_TX_CKSUM_NONE, /* No ckecksum offload */ + ADF_NBUF_TX_CKSUM_IP, /* IP header ckecksum offload */ + ADF_NBUF_TX_CKSUM_TCP_UDP, /* TCP/UDP ckecksum offload */ + ADF_NBUF_TX_CKSUM_TCP_UDP_IP, /* TCP/UDP checksum and IP header ckecksum offload */ + +}adf_nbuf_tx_cksum_t; + +/** + * @brief For recieve checksum API + */ +typedef enum { + ADF_NBUF_RX_CKSUM_TCP = 0x0001, + ADF_NBUF_RX_CKSUM_UDP = 0x0002, + ADF_NBUF_RX_CKSUM_TCPIPV6 = 0x0010, + ADF_NBUF_RX_CKSUM_UDPIPV6 = 0x0020, + ADF_NBUF_RX_CKSUM_TCP_NOPSEUDOHEADER = 0x0100, + ADF_NBUF_RX_CKSUM_UDP_NOPSEUDOHEADER = 0x0200, + ADF_NBUF_RX_CKSUM_TCPSUM16 = 0x1000, +}adf_nbuf_l4_rx_cksum_type_t; + +typedef enum { + ADF_NBUF_RX_CKSUM_NONE = 0x0000, /* device failed to ckecksum */ + ADF_NBUF_RX_CKSUM_TCP_UDP_HW = 0x0010, /* TCP/UDP cksum successful and value returned */ + ADF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY = 0x0020, /* TCP/UDP cksum successful, no value */ +}adf_nbuf_l4_rx_cksum_result_t; + +typedef struct { + adf_nbuf_l4_rx_cksum_type_t l4_type; + adf_nbuf_l4_rx_cksum_result_t l4_result; + a_uint32_t val; +}adf_nbuf_rx_cksum_t; + +/** + * @brief For TCP large Segment Offload + */ +typedef struct { + adf_net_tso_type_t type; + a_uint16_t mss; + a_uint8_t hdr_off; +}adf_nbuf_tso_t; + +/** + * @brief Wireless events + * ADF_IEEE80211_ASSOC = station associate (bss mode) + * ADF_IEEE80211_REASSOC = station re-associate (bss mode) + * ADF_IEEE80211_DISASSOC = station disassociate (bss mode) + * ADF_IEEE80211_JOIN = station join (ap mode) + * ADF_IEEE80211_LEAVE = station leave (ap mode) + * ADF_IEEE80211_SCAN = scan complete, results available + * ADF_IEEE80211_REPLAY = sequence counter replay detected + * ADF_IEEE80211_MICHAEL = Michael MIC failure detected + * ADF_IEEE80211_REJOIN = station re-associate (ap mode) + * ADF_CUSTOM_PUSH_BUTTON = + */ +typedef enum adf_net_wireless_events{ + ADF_IEEE80211_ASSOC = __ADF_IEEE80211_ASSOC, + ADF_IEEE80211_REASSOC = __ADF_IEEE80211_REASSOC, + ADF_IEEE80211_DISASSOC = __ADF_IEEE80211_DISASSOC, + ADF_IEEE80211_JOIN = __ADF_IEEE80211_JOIN, + ADF_IEEE80211_LEAVE = __ADF_IEEE80211_LEAVE, + ADF_IEEE80211_SCAN = __ADF_IEEE80211_SCAN, + ADF_IEEE80211_REPLAY = __ADF_IEEE80211_REPLAY, + ADF_IEEE80211_MICHAEL = __ADF_IEEE80211_MICHAEL, + ADF_IEEE80211_REJOIN = __ADF_IEEE80211_REJOIN, + ADF_CUSTOM_PUSH_BUTTON = __ADF_CUSTOM_PUSH_BUTTON +}adf_net_wireless_event_t; + +#define ADF_ARP_REQ 1 /* ARP request */ +#define ADF_ARP_RSP 2 /* ARP response */ +#define ADF_ARP_RREQ 3 /* RARP request */ +#define ADF_ARP_RRSP 4 /* RARP response */ + +#define ADF_NEXTHDR_ICMP 58 /* ICMP for IPv6. */ + +/* Neighbor Discovery */ +#define ADF_ND_RSOL 133 /* Router Solicitation */ +#define ADF_ND_RADVT 134 /* Router Advertisement */ +#define ADF_ND_NSOL 135 /* Neighbor Solicitation */ +#define ADF_ND_NADVT 136 /* Neighbor Advertisement */ + +/** + * @brief IPv6 Address + */ +typedef struct { + union { + a_uint8_t u6_addr8[16]; + a_uint16_t u6_addr16[8]; + a_uint32_t u6_addr32[4]; + } in6_u; +//#define s6_addr in6_u.u6_addr8 +//#define s6_addr16 in6_u.u6_addr16 +//#define s6_addr32 in6_u.u6_addr32 +} adf_net_ipv6_addr_t; + +/** + * @brief IPv6 Header + */ +typedef struct { +#if defined(ADF_LITTLE_ENDIAN_MACHINE) + a_uint8_t ipv6_priority:4, + ipv6_version:4; +#elif defined(ADF_BIG_ENDIAN_MACHINE) + a_uint8_t ipv6_version:4, + ipv6_priority:4; +#else +#error "Please fix" +#endif + a_uint8_t ipv6_flow_lbl[3]; + + a_uint16_t ipv6_payload_len; + a_uint8_t ipv6_nexthdr, + ipv6_hop_limit; + + adf_net_ipv6_addr_t ipv6_saddr, + ipv6_daddr; +} adf_net_ipv6hdr_t; + +/** + * @brief ICMPv6 Header + */ +typedef struct { + + a_uint8_t icmp6_type; + a_uint8_t icmp6_code; + a_uint16_t icmp6_cksum; + + union { + a_uint32_t un_data32[1]; + a_uint16_t un_data16[2]; + a_uint8_t un_data8[4]; + + struct { + a_uint16_t identifier; + a_uint16_t sequence; + } u_echo; + + struct { +#if defined(ADF_LITTLE_ENDIAN_MACHINE) + a_uint32_t reserved:5, + override:1, + solicited:1, + router:1, + reserved2:24; +#elif defined(ADF_BIG_ENDIAN_MACHINE) + a_uint32_t router:1, + solicited:1, + override:1, + reserved:29; +#else +#error "Please fix" +#endif + } u_nd_advt; + + struct { + a_uint8_t hop_limit; +#if defined(ADF_LITTLE_ENDIAN_MACHINE) + a_uint8_t reserved:6, + other:1, + managed:1; + +#elif defined(ADF_BIG_ENDIAN_MACHINE) + a_uint8_t managed:1, + other:1, + reserved:6; +#else +#error "Please fix" +#endif + a_uint16_t rt_lifetime; + } u_nd_ra; + + } icmp6_dataun; + +} adf_net_icmpv6hdr_t; + +/** + * @brief Neighbor Discovery Message + */ +typedef struct { + adf_net_icmpv6hdr_t nd_icmph; + adf_net_ipv6_addr_t nd_target; + a_uint8_t nd_opt[0]; +} adf_net_nd_msg_t; + +#define adf_csum_ipv6(s, d, l, p, sum) \ + csum_ipv6_magic((struct in6_addr *)s, \ + (struct in6_addr *)d, l, p, sum) +/** + * @brief + * + * @param addr1 + * @param addr2 + * + * @return Compare two ethernet addresses, returns A_TRUE if equal + * + */ +static adf_os_inline a_bool_t +adf_net_cmp_ether_addr(const a_uint8_t *addr1,const a_uint8_t *addr2) +{ + const a_uint16_t *a = (const a_uint16_t *) addr1; + const a_uint16_t *b = (const a_uint16_t *) addr2; + + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0; +} + +#endif /*_ADF_NET_TYPES_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_atomic.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_atomic.h new file mode 100644 index 000000000000..4e386dc90953 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_atomic.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_atomic.h + * This file abstracts an atomic counter. + */ + +#ifndef _ADF_OS_ATOMIC_H +#define _ADF_OS_ATOMIC_H + +#include +/** + * @brief Atomic type of variable. + * Use this when you want a simple resource counter etc. which is atomic + * across multiple CPU's. These maybe slower than usual counters on some + * platforms/OS'es, so use them with caution. + */ +typedef __adf_os_atomic_t adf_os_atomic_t; + +/** + * @brief Initialize an atomic type variable + * @param[in] v a pointer to an opaque atomic variable + */ +static inline void +adf_os_atomic_init(adf_os_atomic_t *v) +{ + __adf_os_atomic_init(v); +} + +/** + * @brief Read the value of an atomic variable. + * @param[in] v a pointer to an opaque atomic variable + * + * @return the current value of the variable + */ +static inline a_uint32_t +adf_os_atomic_read(adf_os_atomic_t *v) +{ + return (__adf_os_atomic_read(v)); +} + +/** + * @brief Increment the value of an atomic variable. + * @param[in] v a pointer to an opaque atomic variable + */ +static inline void +adf_os_atomic_inc(adf_os_atomic_t *v) +{ + __adf_os_atomic_inc(v); +} + +/** + * @brief Decrement the value of an atomic variable. + * @param v a pointer to an opaque atomic variable + */ +static inline void +adf_os_atomic_dec(adf_os_atomic_t *v) +{ + __adf_os_atomic_dec(v); +} + +/** + * @brief Add a value to the value of an atomic variable. + * @param v a pointer to an opaque atomic variable + * @param i the amount by which to increase the atomic counter + */ +static inline void +adf_os_atomic_add(int i, adf_os_atomic_t *v) +{ + __adf_os_atomic_add(i, v); +} + +/** + * @brief Decrement an atomic variable and check if the new value is zero. + * @param v a pointer to an opaque atomic variable + * @return + * true (non-zero) if the new value is zero, + * or false (0) if the new value is non-zero + */ +static inline a_uint32_t +adf_os_atomic_dec_and_test(adf_os_atomic_t *v) +{ + return __adf_os_atomic_dec_and_test(v); +} + +/** + * @brief Set a value to the value of an atomic variable. + * @param v a pointer to an opaque atomic variable + * @param i the amount by which to increase the atomic counter + */ +static inline void +adf_os_atomic_set(adf_os_atomic_t *v, int i) +{ + __adf_os_atomic_set(v, i); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_bitops.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_bitops.h new file mode 100644 index 000000000000..42a64d797124 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_bitops.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_bitops.h + * This file abstracts bit-level operations on a stream of bytes. + */ + +#ifndef _ADF_OS_BITOPS_H +#define _ADF_OS_BITOPS_H + +#include + +/** + * @brief Set a bit atomically + * @param[in] nr Bit to change + * @param[in] addr Address to start counting from + * + * @note its atomic and cannot be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_set_bit_a(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_set_bit_a(nr, addr); +} + +/** + * @brief Set a bit + * @param[in] nr Bit to change + * @param[in] addr Address to start counting from + * + * @note its not atomic and can be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_set_bit(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_set_bit(nr, addr); +} + +/** + * @brief Clear a bit atomically + * @param[in] nr Bit to change + * @param[in] addr Address to start counting from + * + * @note its atomic and cannot be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_clear_bit_a(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_clear_bit_a(nr, addr); +} + +/** + * @brief Clear a bit + * @param[in] nr Bit to change + * @param[in] addr Address to start counting from + * + * @note its not atomic and can be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_clear_bit(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_clear_bit(nr, addr); +} + +/** + * @brief Toggle a bit atomically + * @param[in] nr Bit to change + * @param[in] addr Address to start counting from + * + * @note its atomic and cannot be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_change_bit_a(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_change_bit_a(nr, addr); +} + +/** + * @brief Toggle a bit + * @param[in] nr Bit to change + * @param[in] addr Address to start counting from + * + * @note its not atomic and can be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_change_bit(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_change_bit(nr, addr); +} + +/** + * @brief Test and Set a bit atomically + * @param[in] nr Bit to set + * @param[in] addr Address to start counting from + * + * @note its atomic and cannot be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_test_and_set_bit_a(a_uint32_t nr, + volatile a_uint32_t *addr) +{ + __adf_os_test_and_set_bit_a(nr, addr); +} + +/** + * @brief Test and Set a bit + * @param[in] nr Bit to set + * @param[in] addr Address to start counting from + * + * @note its not atomic and can be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_test_and_set_bit(a_uint32_t nr, + volatile a_uint32_t *addr) +{ + __adf_os_test_and_set_bit(nr, addr); +} + +/** + * @brief Test and clear a bit atomically + * @param[in] nr Bit to set + * @param[in] addr Address to start counting from + * + * @note its atomic and cannot be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_test_and_clear_bit_a(a_uint32_t nr, + volatile a_uint32_t *addr) +{ + __adf_os_test_and_clear_bit_a(nr, addr); +} + +/** + * @brief Test and clear a bit + * @param[in] nr Bit to set + * @param[in] addr Address to start counting from + * + * @note its not atomic and can be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_test_and_clear_bit(a_uint32_t nr, + volatile a_uint32_t *addr) +{ + __adf_os_test_and_clear_bit(nr, addr); +} + +/** + * @brief Test and change a bit atomically + * @param[in] nr Bit to set + * @param[in] addr Address to start counting from + * + * @note its atomic and cannot be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_test_and_change_bit_a(a_uint32_t nr, + volatile a_uint32_t *addr) +{ + __adf_os_test_and_change_bit_a(nr, addr); +} + +/** + * @brief Test and clear a bit + * @param[in] nr Bit to set + * @param[in] addr Address to start counting from + * + * @note its not atomic and can be re-ordered. + * Note that nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void adf_os_test_and_change_bit(a_uint32_t nr, + volatile a_uint32_t *addr) +{ + __adf_os_test_and_change_bit(nr, addr); +} + +/** + * @brief test_bit - Determine whether a bit is set + * @param[in] nr bit number to test + * @param[in] addr Address to start counting from + * + * @return 1 if set, 0 if not + */ +static inline int adf_os_test_bit(a_uint32_t nr, volatile a_uint32_t *addr) +{ + __adf_os_test_bit(nr, addr); +} + + +#endif /**_AOD_BITOPS_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_defer.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_defer.h new file mode 100644 index 000000000000..2ec5635c0758 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_defer.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_defer.h + * This file abstracts deferred execution contexts. + */ + +#ifndef __ADF_OS_DEFER_H +#define __ADF_OS_DEFER_H + +#include +#include + +/** + * TODO This implements work queues (worker threads, kernel threads etc.). + * Note that there is no cancel on a scheduled work. You cannot free a work + * item if its queued. You cannot know if a work item is queued or not unless + * its running, whence you know its not queued. + * + * so if, say, a module is asked to unload itself, how exactly will it make + * sure that the work's not queued, for OS'es that dont provide such a + * mechanism?? + */ + +/** + * @brief Representation of a work queue. + */ +typedef __adf_os_work_t adf_os_work_t; +typedef __adf_os_delayed_work_t adf_os_delayed_work_t; +typedef __adf_os_workqueue_t adf_os_workqueue_t; +/** + * @brief Representation of a bottom half. + */ +typedef __adf_os_bh_t adf_os_bh_t; + + + +/** + * @brief This creates the Bottom half deferred handler + * + * @param[in] hdl OS handle + * @param[in] bh bottom instance + * @param[in] func deferred function to run at bottom half interrupt + * context. + * @param[in] arg argument for the deferred function + */ +static inline void +adf_os_create_bh(adf_os_handle_t hdl, adf_os_bh_t *bh, + adf_os_defer_fn_t func,void *arg) +{ + __adf_os_init_bh(hdl, bh, func, arg); +} + + +/** + * @brief schedule a bottom half (DPC) + * + * @param[in] hdl OS handle + * @param[in] bh bottom instance + */ +static inline void +adf_os_sched_bh(adf_os_handle_t hdl, adf_os_bh_t *bh) +{ + __adf_os_sched_bh(hdl, bh); +} + +/** + * @brief destroy the bh (synchronous) + * + * @param[in] hdl OS handle + * @param[in] bh bottom instance + */ +static inline void +adf_os_destroy_bh(adf_os_handle_t hdl, adf_os_bh_t *bh) +{ + __adf_os_disable_bh(hdl,bh); +} + +/*********************Non-Interrupt Context deferred Execution***************/ + +/** + * @brief create a work/task queue, This runs in non-interrupt + * context, so can be preempted by H/W & S/W intr + * + * @param[in] hdl OS handle + * @param[in] work work instance + * @param[in] func deferred function to run at bottom half non-interrupt + * context. + * @param[in] arg argument for the deferred function + */ +static inline void +adf_os_create_work(adf_os_handle_t hdl, adf_os_work_t *work, + adf_os_defer_fn_t func, void *arg) +{ + __adf_os_init_work(hdl, work, func, arg); +} + +static inline void +adf_os_create_delayed_work(adf_os_handle_t hdl, adf_os_delayed_work_t *work, + adf_os_defer_fn_t func, void *arg) +{ + __adf_os_init_delayed_work(hdl, work, func, arg); +} + +static inline adf_os_workqueue_t* +adf_os_create_workqueue(char *name) +{ + return __adf_os_create_workqueue(name); +} + +static inline void +adf_os_queue_work(adf_os_handle_t hdl, adf_os_workqueue_t *wqueue, adf_os_work_t* work) +{ + return __adf_os_queue_work(hdl, wqueue, work); +} + +static inline void +adf_os_queue_delayed_work(adf_os_handle_t hdl, adf_os_workqueue_t *wqueue, adf_os_delayed_work_t* work, a_uint32_t delay) +{ + return __adf_os_queue_delayed_work(hdl, wqueue, work, delay); +} + +static inline void +adf_os_flush_workqueue(adf_os_handle_t hdl, adf_os_workqueue_t *wqueue) +{ + return __adf_os_flush_workqueue(hdl, wqueue); +} + +static inline void +adf_os_destroy_workqueue(adf_os_handle_t hdl, adf_os_workqueue_t *wqueue) +{ + return __adf_os_destroy_workqueue(hdl, wqueue); +} + +/** + * @brief Schedule a deferred task on non-interrupt context + * + * @param[in] hdl OS handle + * @param[in] work work instance + */ +static inline void +adf_os_sched_work(adf_os_handle_t hdl, adf_os_work_t *work) +{ + __adf_os_sched_work(hdl, work); +} + +/** + *@brief destroy the deferred task (synchronous) + * + *@param[in] hdl OS handle + *@param[in] work work instance + */ +static inline void +adf_os_destroy_work(adf_os_handle_t hdl, adf_os_work_t *work) +{ + __adf_os_disable_work(hdl, work); +} + + +/** + * XXX API to specify processor while scheduling a bh => only on vista + */ + + +#endif /*_ADF_OS_DEFER_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_dma.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_dma.h new file mode 100644 index 000000000000..f18bcdeb9022 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_dma.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2011,2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @ingroup adf_os_public + * @file adf_os_dma.h + * This file abstracts DMA operations. + */ + +#ifndef _ADF_OS_DMA_H +#define _ADF_OS_DMA_H + +#include +#include + +/* + * @brief a dma address representation of a platform + */ + +/** + * @brief Allocate a DMA buffer and map it to local bus address space + * + * @param[in] osdev platform device instance + * @param[in] size DMA buffer size + * @param[in] coherent 0 => cached. + * @param[out] dmap opaque coherent memory handle + * + * @return returns the virtual address of the memory + */ +static inline void * +adf_os_dmamem_alloc(adf_os_device_t osdev, + adf_os_size_t size, + a_bool_t coherent, + adf_os_dma_map_t *dmap) +{ + return __adf_os_dmamem_alloc(osdev, size, coherent, dmap); +} + +/** + * @brief Free a previously mapped DMA buffer + * + * @param[in] osdev platform device instance + * @param[in] size DMA buffer size + * @param[in] coherent 0 => cached. + * @param[in] vaddr virtual address of DMA buffer + * @param[in] dmap memory handle + */ +static inline void +adf_os_dmamem_free(adf_os_device_t osdev, + adf_os_size_t size, + a_bool_t coherent, + void *vaddr, + adf_os_dma_map_t dmap) +{ + __adf_os_dmamem_free(osdev, size, coherent, vaddr, dmap); +} + +/** + * @brief given a dmamem map, returns the (bus) address + * + * @param[in] dmap memory handle + * + * @return the (bus) address + */ +static inline adf_os_dma_addr_t +adf_os_dmamem_map2addr(adf_os_dma_map_t dmap) +{ + return(__adf_os_dmamem_map2addr(dmap)); +} + +/** + * @brief Flush and invalidate cache for a given dmamem map + * + * @param[in] osdev platform device instance + * @param[in] dmap mem handle + * @param[in] op op code for sync type, (see @ref adf_os_types.h) + */ +static inline void +adf_os_dmamem_cache_sync(adf_os_device_t osdev, + adf_os_dma_map_t dmap, + adf_os_cache_sync_t op) +{ + __adf_os_dmamem_cache_sync(osdev, dmap, op); +} + +/** + * @brief Get the cpu cache line size + * + * @return The CPU cache line size in bytes. + */ +static inline adf_os_size_t +adf_os_cache_line_size(void) +{ + return __adf_os_cache_line_size(); +} + +/** + * @brief invalidate the virtual address range specified by + * start and end addresses. + * Note: This does not write back the cache entries. + * + * @return void + */ +static inline void +adf_os_invalidate_range(void * start, void * end) +{ + return __adf_os_invalidate_range(start, end); +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_io.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_io.h new file mode 100644 index 000000000000..40baece1d63c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_io.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_io.h + * This file abstracts I/O operations. + */ + +#ifndef _ADF_OS_IO_H +#define _ADF_OS_IO_H + +#include + + +/** + * @brief Read an 8-bit register value + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * + * @return An 8-bit register value. + */ +#define adf_os_reg_read8(osdev, addr) __adf_os_reg_read8(osdev, addr) + +/** + * @brief Read a 16-bit register value + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * + * @return A 16-bit register value. + */ +#define adf_os_reg_read16(osdev, addr) __adf_os_reg_read16(osdev, addr) + +/** + * @brief Read a 32-bit register value + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * + * @return A 32-bit register value. + */ +#define adf_os_reg_read32(osdev, addr) __adf_os_reg_read32(osdev, addr) + +/** + * @brief Read a 64-bit register value + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * + * @return A 64-bit register value. + */ +#define adf_os_reg_read64(osdev, addr) __adf_os_reg_read64(osdev, addr) + +/** + * @brief Write an 8-bit value into register + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * @param[in] b the 8-bit value to be written + */ +#define adf_os_reg_write8(osdev, addr, b) __adf_os_reg_write8(osdev, addr, b) + +/** + * @brief Write a 16-bit value into register + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * @param[in] w the 16-bit value to be written + */ +#define adf_os_reg_write16(osdev, addr, w) __adf_os_reg_write16(osdev, addr, w) + +/** + * @brief Write a 32-bit value into register + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * @param[in] l the 32-bit value to be written + */ +#define adf_os_reg_write32(osdev, addr, l) __adf_os_reg_write32(osdev, addr, l) + +/** + * @brief Write a 64-bit value into register + * + * @param[in] osdev platform device object + * @param[in] addr register addr + * @param[in] q the 64-bit value to be written + */ +#define adf_os_reg_write64(osdev, addr, q) __adf_os_reg_write64(osdev, addr, q) + + +/** + * @brief io remaps a physical address to a i/o address + * + * @param[in] addr physical address + * @param[in] size size of memeory to be remaped + */ +#define adf_os_ioremap(addr, size) __adf_os_ioremap(addr, size) + +/** + * @brief Convert a 16-bit value from network byte order to host byte order + */ +#define adf_os_ntohs(x) __adf_os_ntohs(x) + +/** + * @brief Convert a 32-bit value from network byte order to host byte order + */ +#define adf_os_ntohl(x) __adf_os_ntohl(x) + +/** + * @brief Convert a 16-bit value from host byte order to network byte order + */ +#define adf_os_htons(x) __adf_os_htons(x) + +/** + * @brief Convert a 32-bit value from host byte order to network byte order + */ +#define adf_os_htonl(x) __adf_os_htonl(x) + +/** + * @brief Convert a 16-bit value from CPU byte order to big-endian byte order + */ +#define adf_os_cpu_to_be16(x) __adf_os_cpu_to_be16(x) + +/** + * @brief Convert a 32-bit value from CPU byte order to big-endian byte order + */ +#define adf_os_cpu_to_be32(x) __adf_os_cpu_to_be32(x) + +/** + * @brief Convert a 64-bit value from CPU byte order to big-endian byte order + */ +#define adf_os_cpu_to_be64(x) __adf_os_cpu_to_be64(x) + +/** + * @brief Convert a 16-bit value from CPU byte order to little-endian byte order + */ +#define adf_os_cpu_to_le16(x) __adf_os_cpu_to_le16(x) + +/** + * @brief Convert a 32-bit value from CPU byte order to little-endian byte order + */ +#define adf_os_cpu_to_le32(x) __adf_os_cpu_to_le32(x) + +/** + * @brief Convert a 64-bit value from CPU byte order to little-endian byte order + */ +#define adf_os_cpu_to_le64(x) __adf_os_cpu_to_le64(x) + +/** + * @brief Convert a 16-bit value from big-endian byte order to CPU byte order + */ +#define adf_os_be16_to_cpu(x) __adf_os_be16_to_cpu(x) + +/** + * @brief Convert a 32-bit value from big-endian byte order to CPU byte order + */ +#define adf_os_be32_to_cpu(x) __adf_os_be32_to_cpu(x) + +/** + * @brief Convert a 64-bit value from big-endian byte order to CPU byte order + */ +#define adf_os_be64_to_cpu(x) __adf_os_be64_to_cpu(x) + +/** + * @brief Convert a 16-bit value from little-endian byte order to CPU byte order + */ +#define adf_os_le16_to_cpu(x) __adf_os_le16_to_cpu(x) + +/** + * @brief Convert a 32-bit value from little-endian byte order to CPU byte order + */ +#define adf_os_le32_to_cpu(x) __adf_os_le32_to_cpu(x) + +/** + * @brief Convert a 64-bit value from little-endian byte order to CPU byte order + */ +#define adf_os_le64_to_cpu(x) __adf_os_le64_to_cpu(x) + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.c new file mode 100644 index 000000000000..77104a4fc913 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include + +void adf_os_spin_lock_bh_outline(adf_os_spinlock_t *lock) +{ + adf_os_spin_lock_bh(lock); +} + +void adf_os_spin_unlock_bh_outline(adf_os_spinlock_t *lock) +{ + adf_os_spin_unlock_bh(lock); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.h new file mode 100644 index 000000000000..9e0a733e36ad --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_lock.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_lock.h + * This file abstracts locking operations. + */ + +#ifndef _ADF_OS_LOCK_H +#define _ADF_OS_LOCK_H + +#include +#include + +/** + * @brief Platform spinlock object + */ +typedef __adf_os_spinlock_t adf_os_spinlock_t; +/** + * @brief Platform mutex object + */ +typedef __adf_os_mutex_t adf_os_mutex_t; + + + +/** + * @brief Initialize a mutex + * + * @param[in] m mutex to initialize + */ +static inline void adf_os_init_mutex(adf_os_mutex_t *m) +{ + __adf_os_init_mutex(m); +} + + +/** + * @brief Take the mutex + * + * @param[in] m mutex to take + */ +static inline int adf_os_mutex_acquire(adf_os_device_t osdev, adf_os_mutex_t *m) +{ + return (__adf_os_mutex_acquire(osdev, m)); +} + +/** + * @brief Give the mutex + * + * @param[in] m mutex to give + */ +static inline void adf_os_mutex_release(adf_os_device_t osdev, adf_os_mutex_t *m) +{ + __adf_os_mutex_release(osdev, m); +} +/** + * @brief Platform specific semaphore object + */ +typedef __adf_os_mutex_t adf_os_sem_t; +#define adf_os_sem_init adf_os_init_mutex +#define adf_os_sem_acquire adf_os_mutex_acquire +#define adf_os_sem_release adf_os_mutex_release + + +/** + * @brief Initialize a spinlock + * + * @param[in] lock spinlock object pointer + */ +static inline void +adf_os_spinlock_init(adf_os_spinlock_t *lock) +{ + __adf_os_spinlock_init(lock); +} + +/** + * @brief Delete a spinlock + * + * @param[in] lock spinlock object pointer + */ +static inline void +adf_os_spinlock_destroy(adf_os_spinlock_t *lock) +{ + __adf_os_spinlock_destroy(lock); +} + +#define adf_os_spin_lock( _lock) __adf_os_spin_lock(_lock) +#define adf_os_spin_unlock( _lock ) __adf_os_spin_unlock(_lock) +#define adf_os_spin_lock_irqsave( _lock) __adf_os_spin_lock_irqsave(_lock) +#define adf_os_spin_unlock_irqrestore( _lock ) \ + __adf_os_spin_unlock_irqrestore(_lock) + +/** + * @brief locks the spinlock mutex in soft irq context + * + * @param[in] lock spinlock object pointer + */ +static inline void +adf_os_spin_lock_bh(adf_os_spinlock_t *lock) +{ + __adf_os_spin_lock_bh(lock); +} + +void adf_os_spin_lock_bh_outline(adf_os_spinlock_t *lock); + +/** + * @brief unlocks the spinlock mutex in soft irq context + * + * @param[in] lock spinlock object pointer + */ +static inline void +adf_os_spin_unlock_bh(adf_os_spinlock_t *lock) +{ + __adf_os_spin_unlock_bh(lock); +} + +void adf_os_spin_unlock_bh_outline(adf_os_spinlock_t *lock); + +/** + * @brief Execute the input function with spinlock held and interrupt disabled. + * + * @param[in] hdl OS handle + * @param[in] lock spinlock to be held for the critical region + * @param[in] func critical region function that to be executed + * @param[in] context context of the critical region function + * + * @return Boolean status returned by the critical region function + */ +static inline a_bool_t +adf_os_spinlock_irq_exec(adf_os_handle_t hdl, + adf_os_spinlock_t *lock, + adf_os_irqlocked_func_t func, + void *arg) +{ + return __adf_os_spinlock_irq_exec(hdl, lock, func, arg); +} + +/** + * @brief locks the spinlock in irq context + * + * @param[in] lock spinlock object pointer + * @param[in] flags flags value + * + */ +#define adf_os_spin_lock_irq(_pLock, _flags) __adf_os_spin_lock_irq(_pLock, _flags) +#define adf_os_spin_unlock_irq(_pLock, _flags) __adf_os_spin_unlock_irq(_pLock, _flags) + +#define adf_os_in_softirq() __adf_os_in_softirq() + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.c new file mode 100644 index 000000000000..b1f43e5cb6f1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010,2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include +#ifdef MEMORY_DEBUG +#include +#endif + +#ifdef MEMORY_DEBUG +void * +adf_os_mem_alloc_debug(adf_os_device_t osdev, + adf_os_size_t size, + const char *fileName, + a_uint32_t lineNum) +{ + void *p = vos_mem_malloc_debug(size, fileName, lineNum); + if (p) { + memset(p, 0, size); + } + return p; +} + +void +adf_os_mem_free_debug(void *buf) +{ + vos_mem_free(buf); +} + +#endif + +void * +adf_os_mem_alloc_outline(adf_os_device_t osdev, size_t size) +{ + return __adf_os_mem_alloc(osdev, size); +} + +void +adf_os_mem_free_outline(void *buf) +{ + __adf_os_mem_free(buf); +} + +void +adf_os_mem_zero_outline(void *buf, adf_os_size_t size) +{ + __adf_os_mem_zero(buf, size); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.h new file mode 100644 index 000000000000..fc14518f91ff --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_mem.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2011,2013,2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @ingroup adf_os_public + * @file adf_os_mem.h + * This file abstracts memory operations. + */ + +#ifndef _ADF_OS_MEM_H +#define _ADF_OS_MEM_H + +#include +#include + +#ifdef CONFIG_CNSS +#include +#endif + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC +#include +#endif + +#include + +#ifdef MEMORY_DEBUG +#define adf_os_mem_alloc(_osdev, _size) adf_os_mem_alloc_debug(_osdev,\ + _size, __FILE__, __LINE__) + +void * +adf_os_mem_alloc_debug(adf_os_device_t osdev, adf_os_size_t size, + const char *fileName, a_uint32_t lineNum); + + +#define adf_os_mem_free(_buf) adf_os_mem_free_debug(_buf) + +void +adf_os_mem_free_debug(void *buf); + +#else +/** + * @brief Allocate a memory buffer. Note this call can block. + * + * @param[in] size buffer size + * + * @return Buffer pointer or NULL if there's not enough memory. + */ +static inline void * +adf_os_mem_alloc(adf_os_device_t osdev, adf_os_size_t size) +{ +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + void *p_mem; +#endif + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + if (size > WCNSS_PRE_ALLOC_GET_THRESHOLD) + { + p_mem = wcnss_prealloc_get(size); + if (NULL != p_mem) + return p_mem; + } +#endif + + return __adf_os_mem_alloc(osdev, size); +} + +/** + * @brief Free malloc'ed buffer + * + * @param[in] buf buffer pointer allocated by @ref adf_os_mem_alloc + */ +static inline void +adf_os_mem_free(void *buf) +{ +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + if (wcnss_prealloc_put(buf)) + { + return; + } +#endif + + __adf_os_mem_free(buf); +} + +#endif + +void * +adf_os_mem_alloc_outline(adf_os_device_t osdev, adf_os_size_t size); + +void +adf_os_mem_free_outline(void *buf); + +static inline void * +adf_os_mem_alloc_consistent( + adf_os_device_t osdev, adf_os_size_t size, adf_os_dma_addr_t *paddr, adf_os_dma_context_t mctx) +{ + return __adf_os_mem_alloc_consistent(osdev, size, paddr, mctx); +} + +static inline void +adf_os_mem_free_consistent( + adf_os_device_t osdev, + adf_os_size_t size, + void *vaddr, + adf_os_dma_addr_t paddr, + adf_os_dma_context_t memctx) +{ + __adf_os_mem_free_consistent(osdev, size, vaddr, paddr, memctx); +} + +/** + * @brief Move a memory buffer. Overlapping regions are not allowed. + * + * @param[in] dst destination address + * @param[in] src source address + * @param[in] size buffer size + */ +static inline __ahdecl void +adf_os_mem_copy(void *dst, const void *src, adf_os_size_t size) +{ + __adf_os_mem_copy(dst, src, size); +} + +/** + * @brief Does a non-destructive copy of memory buffer + * + * @param[in] dst destination address + * @param[in] src source address + * @param[in] size buffer size + */ +static inline void +adf_os_mem_move(void *dst, void *src, adf_os_size_t size) +{ + __adf_os_mem_move(dst,src,size); +} + + +/** + * @brief Fill a memory buffer + * + * @param[in] buf buffer to be filled + * @param[in] b byte to fill + * @param[in] size buffer size + */ +static inline void +adf_os_mem_set(void *buf, a_uint8_t b, adf_os_size_t size) +{ + __adf_os_mem_set(buf, b, size); +} + + +/** + * @brief Zero a memory buffer + * + * @param[in] buf buffer to be zeroed + * @param[in] size buffer size + */ +static inline __ahdecl void +adf_os_mem_zero(void *buf, adf_os_size_t size) +{ + __adf_os_mem_zero(buf, size); +} + +void +adf_os_mem_zero_outline(void *buf, adf_os_size_t size); + +/** + * @brief Compare two memory buffers + * + * @param[in] buf1 first buffer + * @param[in] buf2 second buffer + * @param[in] size buffer size + * + * @retval 0 equal + * @retval 1 not equal + */ +static inline int +adf_os_mem_cmp(const void *buf1, const void *buf2, adf_os_size_t size) +{ + return __adf_os_mem_cmp(buf1, buf2, size); +} + +/** + * @brief Compare two strings + * + * @param[in] str1 First string + * @param[in] str2 Second string + * + * @retval 0 equal + * @retval >0 not equal, if str1 sorts lexicographically after str2 + * @retval <0 not equal, if str1 sorts lexicographically before str2 + */ +static inline a_int32_t +adf_os_str_cmp(const char *str1, const char *str2) +{ + return __adf_os_str_cmp(str1, str2); +} + +/** + * @brief Returns the length of a string + * + * @param[in] str input string + * + * @return length of string + */ +static inline a_int32_t +adf_os_str_len(const char *str) +{ + return (a_int32_t)__adf_os_str_len(str); +} + +/** + * @brief Returns the system default page size + * + * @retval system default page size + */ +static inline a_int32_t +adf_os_mem_get_page_size(void) +{ + return __adf_os_mem_get_page_size(); +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_module.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_module.h new file mode 100644 index 000000000000..a67a9d678d77 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_module.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_module.h + * This file abstracts "kernel module" semantics. + */ + +#ifndef _ADF_OS_MODULE_H +#define _ADF_OS_MODULE_H + +#include + +typedef a_status_t (*module_init_func_t)(void); + +/** + * @brief Specify the module's entry point. + */ +#define adf_os_virt_module_init(_mod_init_func) __adf_os_virt_module_init(_mod_init_func) + +/** + * @brief Specify the module's exit point. + */ +#define adf_os_virt_module_exit(_mod_exit_func) __adf_os_virt_module_exit(_mod_exit_func) + +/** + * @brief Specify the module's name. + */ +#define adf_os_virt_module_name(_name) __adf_os_virt_module_name(_name) + +/** + * @brief Specify the module's dependency on another module. + */ +#define adf_os_module_dep(_name,_dep) __adf_os_module_dep(_name,_dep) +/** + * @brief Module parameter of type char + */ +#define ADF_OS_PARAM_TYPE_INT8 __ADF_OS_PARAM_TYPE_INT8 + +/** + * @brief Module parameter of type unsigned char + */ +#define ADF_OS_PARAM_TYPE_UINT8 __ADF_OS_PARAM_TYPE_UINT8 +/** + * @brief Module parameter of type short + */ +#define ADF_OS_PARAM_TYPE_INT16 __ADF_OS_PARAM_TYPE_INT16 + +/** + * @brief Module parameter of type unsigned short + */ +#define ADF_OS_PARAM_TYPE_UINT16 __ADF_OS_PARAM_TYPE_UINT16 + +/** + * @brief Module parameter of type integer. + */ +#define ADF_OS_PARAM_TYPE_INT32 __ADF_OS_PARAM_TYPE_INT32 + +/** + * @brief Module parameter of type unsigned integer. + */ +#define ADF_OS_PARAM_TYPE_UINT32 __ADF_OS_PARAM_TYPE_UINT32 + +/** + * @brief Module parameter of type string. + */ +#define ADF_OS_PARAM_TYPE_STRING __ADF_OS_PARAM_TYPE_STRING + +/** + * @brief Export a symbol from a module. + */ +#define adf_os_export_symbol(_sym) __adf_os_export_symbol(_sym) +/** + * @brief Declare a module parameter. + + */ +#define adf_os_declare_param(name, type) __adf_os_declare_param(name, type) + +/** + * @brief Read a parameter's value + * + */ +#define adf_os_read_param(osdev, name, type, pval) \ + __adf_os_read_param(osdev, name, type, pval) + +#endif /*_ADF_OS_MODULE_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_stdtypes.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_stdtypes.h new file mode 100644 index 000000000000..a4f07ead473f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_stdtypes.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011,2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @defgroup adf_os_public OS abstraction API + */ + +/** + * @ingroup adf_os_public + * @file adf_os_stdtypes.h + * This file defines standard types. + */ + +#ifndef _ADF_OS_STDTYPES_H +#define _ADF_OS_STDTYPES_H +#include +#include + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_time.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_time.h new file mode 100644 index 000000000000..a60e5bfcbeba --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_time.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_time.h + * This file abstracts time related functionality. + */ +#ifndef _ADF_OS_TIME_H +#define _ADF_OS_TIME_H + +#include +#ifdef CONFIG_CNSS +#include +#endif + +typedef __adf_time_t adf_os_time_t; + +/** + * @brief count the number of ticks elapsed from the time when + * the system booted + * + * @return ticks + */ +static inline unsigned long +adf_os_ticks(void) +{ + return __adf_os_ticks(); +} + +/** + * @brief convert ticks to milliseconds + * + * @param[in] ticks number of ticks + * @return time in milliseconds + */ +static inline a_uint32_t +adf_os_ticks_to_msecs(unsigned long clock_ticks) +{ + return (__adf_os_ticks_to_msecs(clock_ticks)); +} + +/** + * @brief convert milliseconds to ticks + * + * @param[in] time in milliseconds + * @return number of ticks + */ +static inline unsigned long +adf_os_msecs_to_ticks(a_uint32_t msecs) +{ + return (__adf_os_msecs_to_ticks(msecs)); +} + +/** + * @brief Return a monotonically increasing time. This increments once per HZ ticks + */ +static inline unsigned long +adf_os_getuptime(void) +{ + return (__adf_os_getuptime()); +} + +/** + * @brief Return current timestamp. + */ +static inline unsigned long +adf_os_gettimestamp(void) +{ + return (__adf_os_gettimestamp()); +} + +/** + * @brief Delay in microseconds + * + * @param[in] microseconds to delay + */ +static inline void +adf_os_udelay(int usecs) +{ + __adf_os_udelay(usecs); +} + +/** + * @brief Delay in milliseconds. + * + * @param[in] milliseconds to delay + */ +static inline void +adf_os_mdelay(int msecs) +{ + __adf_os_mdelay(msecs); +} + +/** + * @brief Check if _a is later than _b. + */ +#define adf_os_time_after(_a, _b) __adf_os_time_after(_a, _b) + +/** + * @brief Check if _a is prior to _b. + */ +#define adf_os_time_before(_a, _b) __adf_os_time_before(_a, _b) + +/** + * @brief Check if _a atleast as recent as _b, if not later. + */ +#define adf_os_time_after_eq(_a, _b) __adf_os_time_after_eq(_a, _b) + +/** + * @brief Get kernel boot time. + * + * @return Time in microseconds + */ +static inline a_uint64_t adf_get_boottime(void) +{ +#ifdef CONFIG_CNSS + struct timespec ts; + + cnss_get_boottime(&ts); + + return (((a_uint64_t)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000)); +#else + return adf_os_ticks_to_msecs(adf_os_ticks()) * 1000; +#endif /* CONFIG_CNSS */ +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_timer.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_timer.h new file mode 100644 index 000000000000..fdbe31227cf6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_timer.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/** + * @ingroup adf_os_public + * @file adf_os_timer.h + * This file abstracts OS timers. + */ + +#ifndef _ADF_OS_TIMER_H +#define _ADF_OS_TIMER_H + +#include +#include + + +/** + * @brief Platform timer object + */ +typedef __adf_os_timer_t adf_os_timer_t; + + +/** + * @brief Initialize a timer + * + * @param[in] hdl OS handle + * @param[in] timer timer object pointer + * @param[in] func timer function + * @param[in] context context of timer function + */ +static inline void +adf_os_timer_init(adf_os_handle_t hdl, + adf_os_timer_t *timer, + adf_os_timer_func_t func, + void *arg, + uint8_t type) +{ + __adf_os_timer_init(hdl, timer, func, arg, type); +} + +/** + * @brief Start a one-shot timer + * + * @param[in] timer timer object pointer + * @param[in] msec expiration period in milliseconds + */ +static inline void +adf_os_timer_start(adf_os_timer_t *timer, int msec) +{ + __adf_os_timer_start(timer, msec); +} + +/** + * @brief Modify existing timer to new timeout value + * + * @param[in] timer timer object pointer + * @param[in] msec expiration period in milliseconds + */ +static inline void +adf_os_timer_mod(adf_os_timer_t *timer, int msec) +{ + __adf_os_timer_mod(timer, msec); +} + +/** + * @brief Cancel a timer + * The function will return after any running timer completes. + * + * @param[in] timer timer object pointer + * + * @retval TRUE timer was cancelled and deactived + * @retval FALSE timer was cancelled but already got fired. + */ +static inline a_bool_t +adf_os_timer_cancel(adf_os_timer_t *timer) +{ + return __adf_os_timer_cancel(timer); +} + +/** + * @brief Free a timer + * The function will return after any running timer completes. + * + * @param[in] timer timer object pointer + * + */ +static inline void +adf_os_timer_free(adf_os_timer_t *timer) +{ + __adf_os_timer_free(timer); +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_types.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_types.h new file mode 100644 index 000000000000..5a67902711ef --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_types.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @ingroup adf_os_public + * @file adf_os_types.h + * This file defines types used in the OS abstraction API. + */ + +#ifndef _ADF_OS_TYPES_H +#define _ADF_OS_TYPES_H + + +#include +#include + +#ifndef __ahdecl +#ifdef __i386__ +#define __ahdecl __attribute__((regparm(0))) +#else +#define __ahdecl +#endif +#endif + +#define ADF_OS_MAX_SCATTER __ADF_OS_MAX_SCATTER +/** + * @brief Max number of scatter-gather segments. + */ +#define ADF_OS_MAX_SGLIST 4 + +/** + * @brief denotes structure is packed. + */ +#define adf_os_packed __adf_os_packed + +/** + * @brief handles opaque to each other + */ +typedef void * adf_net_handle_t; + +typedef void * adf_netlink_handle_t; +typedef void * adf_drv_handle_t; +typedef void * adf_os_handle_t; + +/* + * XXX FIXME For compilation only. + * + */ +typedef void * adf_os_pm_t; + +/** + * @brief Platform/bus generic handle. Used for bus specific functions. + */ +typedef __adf_os_device_t adf_os_device_t; + +/** + * @brief size of an object + */ +typedef __adf_os_size_t adf_os_size_t; + +/** + * @brief offset for API's that need them. + */ +typedef __adf_os_off_t adf_os_off_t; + +/** + * @brief abstraction for completion structure + */ +typedef __adf_os_comp_t adf_os_comp_t; +/** + * @brief DMA mapping object. + */ +typedef __adf_os_dma_map_t adf_os_dma_map_t; + +/** + * @brief DMA address. + */ +typedef __adf_os_dma_addr_t adf_os_dma_addr_t; + +/** + * @brief DMA size. + */ +typedef __adf_os_dma_size_t adf_os_dma_size_t; + +/** + * @brief DMA context. + */ +typedef __adf_os_dma_context_t adf_os_dma_context_t; + +/** + * @brief Information inside a DMA map. + */ +typedef struct adf_os_dmamap_info{ + a_uint32_t nsegs; /**< total number mapped segments*/ + struct __dma_segs{ + adf_os_dma_addr_t paddr; /**< physical(dma'able) address of the segment*/ + adf_os_dma_size_t len; /**< length of the segment*/ + } dma_segs[ADF_OS_MAX_SCATTER]; + +}adf_os_dmamap_info_t; + +/** + * @brief Representation of a scatter-gather list. + */ +typedef struct adf_os_sglist{ + a_uint32_t nsegs; /**< total number of segments*/ + struct __sg_segs{ + a_uint8_t *vaddr; /**< Virtual address of the segment*/ + a_uint32_t len; /**< Length of the segment*/ + } sg_segs[ADF_OS_MAX_SGLIST]; + +}adf_os_sglist_t; + +/** + * @brief All operations specified below are performed from + * the host memory point of view, where a read + * implies data coming from the device to the host + * memory, and a write implies data going from the + * host memory to the device. Alternately, the + * operations can be thought of in terms of driver + * operations, where reading a network packet or + * storage sector corresponds to a read operation in + * bus_dma. + * + * ADF_SYNC_PREREAD Perform any synchronization + * required prior to an update + * of host memory by the DMA + * read operation. + * ADF_SYNC_PREWRITE Perform any synchronization + * required after an update of + * host memory by the CPU and + * prior to DMA write + * operations. + * ADF_SYNC_POSTREAD Perform any synchronization + * required after DMA read + * operations and prior to CPU + * access to host + * memory. + * ADF_SYNC_POSTWRITE Perform any synchronization + * required after DMA write + * operations. + */ + +typedef enum adf_os_cache_sync{ + ADF_SYNC_PREREAD=__ADF_SYNC_PREREAD, + ADF_SYNC_PREWRITE=__ADF_SYNC_PREWRITE, + ADF_SYNC_POSTREAD=__ADF_SYNC_POSTREAD, + ADF_SYNC_POSTWRITE=__ADF_SYNC_POSTWRITE +}adf_os_cache_sync_t; + +/** + * @brief Generic status to be used by adf_drv. + */ +/** + * @brief An ecore needs to provide a table of all pci device/vendor id's it + * supports + * + * This table should be terminated by a NULL entry , i.e. {0} + */ +typedef struct { + a_uint32_t vendor; + a_uint32_t device; + a_uint32_t subvendor; + a_uint32_t subdevice; +}adf_os_pci_dev_id_t; + +#define ADF_OS_PCI_ANY_ID (~0) + +/** + * @brief Typically core's can use this macro to create a table of various device + * ID's + */ +#define ADF_OS_PCI_DEVICE(_vendor, _device) \ + (_vendor), (_device), ADF_OS_PCI_ANY_ID, ADF_OS_PCI_ANY_ID + + +#define adf_os_iomem_t __adf_os_iomem_t; +/** + * @brief These define the hw resources the OS has allocated for the device + * Note that start defines a mapped area. + */ +typedef enum { + ADF_OS_RESOURCE_TYPE_MEM, + ADF_OS_RESOURCE_TYPE_IO, +}adf_os_resource_type_t; + +/** + * @brief Representation of a h/w resource. + */ +typedef struct { + a_uint64_t start; + a_uint64_t end; + adf_os_resource_type_t type; +}adf_os_resource_t; + +#define ADF_OS_DEV_ID_TABLE_MAX 256 + +/** + * @brief Representation of bus registration data. + */ +typedef union { + adf_os_pci_dev_id_t *pci; + void *raw; +}adf_os_bus_reg_data_t; + +/** + * @brief Representation of data required for attach. + */ +typedef union { + adf_os_pci_dev_id_t pci; + void *raw; +}adf_os_attach_data_t; + +#define ADF_OS_REGIONS_MAX 5 + +/** + * @brief Types of buses. + */ +typedef enum { + ADF_OS_BUS_TYPE_PCI = 1, + ADF_OS_BUS_TYPE_GENERIC, +}adf_os_bus_type_t; + +/** + * @brief IRQ handler response codes. + */ +typedef enum { + ADF_OS_IRQ_NONE, + ADF_OS_IRQ_HANDLED, +}adf_os_irq_resp_t; + +/** + * @brief DMA mask types. + */ +typedef enum { + ADF_OS_DMA_MASK_32BIT, + ADF_OS_DMA_MASK_64BIT, +}adf_os_dma_mask_t; + + +/** + * @brief DMA directions + * ADF_OS_DMA_TO_DEVICE (data going from device to memory) + * ADF_OS_DMA_FROM_DEVICE (data going from memory to device) + */ +typedef enum { + ADF_OS_DMA_BIDIRECTIONAL = __ADF_OS_DMA_BIDIRECTIONAL, + ADF_OS_DMA_TO_DEVICE = __ADF_OS_DMA_TO_DEVICE, + ADF_OS_DMA_FROM_DEVICE = __ADF_OS_DMA_FROM_DEVICE, +} adf_os_dma_dir_t; + +/* + * Protoypes shared between public and private headers + */ + + +/** + * @brief work queue(kernel thread)/DPC function callback + */ +typedef void (*adf_os_defer_fn_t)(void *); + +/** + * @brief Prototype of the critical region function that is to be + * executed with spinlock held and interrupt disalbed + */ +typedef a_bool_t (*adf_os_irqlocked_func_t)(void *); + + +/** + * @brief Prototype of timer function + */ +typedef void (*adf_os_timer_func_t)(void *); + +/** + * @brief Prototype of IRQ function. + */ +typedef adf_os_irq_resp_t (*adf_os_drv_intr)(adf_drv_handle_t hdl); + +/** + * @brief The OS print routine. + */ +#define adf_os_print __adf_os_print +#define adf_os_vprint __adf_os_vprint +#define adf_os_snprint __adf_os_snprint +#define adf_os_vsnprint __adf_os_vsnprint +#define adf_os_inline __adf_os_inline +/** + * @brief driver info structure needed while we do the register + * for the driver to the shim. + */ +typedef struct _adf_drv_info{ + /** + * @brief driver specific functions + */ + adf_drv_handle_t (*drv_attach) (adf_os_resource_t *res, int count, + adf_os_attach_data_t *data, + adf_os_device_t osdev); + void (*drv_detach) (adf_drv_handle_t hdl); + void (*drv_suspend) (adf_drv_handle_t hdl, adf_os_pm_t pm); + void (*drv_resume) (adf_drv_handle_t hdl); + /** + * @brief driver specific data + */ + adf_os_bus_type_t bus_type; + adf_os_bus_reg_data_t bus_data; + unsigned char *mod_name; + unsigned char *ifname; +}adf_drv_info_t; + +#define adf_os_offsetof(type, field) offsetof(type, field) + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_util.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_util.h new file mode 100644 index 000000000000..5676ca8097dd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_os_util.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @ingroup adf_os_public + * @file adf_os_util.h + * This file defines utility functions. + */ + +#ifndef _ADF_OS_UTIL_H +#define _ADF_OS_UTIL_H + +#include + +/** + * @brief Compiler-dependent macro denoting code likely to execute. + */ +#define adf_os_unlikely(_expr) __adf_os_unlikely(_expr) + +/** + * @brief Compiler-dependent macro denoting code unlikely to execute. + */ +#define adf_os_likely(_expr) __adf_os_likely(_expr) + +/** + * @brief read memory barrier. + */ +#define adf_os_wmb() __adf_os_wmb() + +/** + * @brief write memory barrier. + */ +#define adf_os_rmb() __adf_os_rmb() + +/** + * @brief read + write memory barrier. + */ +#define adf_os_mb() __adf_os_mb() + +/** + * @brief return the lesser of a, b + */ +#define adf_os_min(_a, _b) __adf_os_min(_a, _b) + +/** + * @brief return the larger of a, b + */ +#define adf_os_max(_a, _b) __adf_os_max(_a, _b) + +/** + * @brief assert "expr" evaluates to false. + */ +#ifdef ADF_OS_DEBUG +#define adf_os_assert(expr) __adf_os_assert(expr) +#else +#define adf_os_assert(expr) +#endif /* ADF_OS_DEBUG */ + +/** + * @brief alway assert "expr" evaluates to false. + */ +#define adf_os_assert_always(expr) __adf_os_assert(expr) + +/** + * @brief warn & dump backtrace if expr evaluates true + */ +#define adf_os_warn(expr) __adf_os_warn(expr) +/** + * @brief supply pseudo-random numbers + */ +static inline void adf_os_get_rand(adf_os_handle_t hdl, + a_uint8_t *ptr, + a_uint32_t len) +{ + __adf_os_get_rand(hdl, ptr, len); +} + + + +/** + * @brief return the absolute value of a + */ +#define adf_os_abs(_a) __adf_os_abs(_a) + +/** + * @brief replace with the name of the current function + */ +#define adf_os_function __adf_os_function + + + +/** + * @brief return square root + */ + +/** + * @brief Math function for getting a square root + * + * @param[in] x Number to compute the sqaure root + * + * @return Sqaure root as integer + */ +static adf_os_inline a_uint32_t +adf_os_int_sqrt(a_uint32_t x) +{ + return __adf_os_int_sqrt(x); +} + +/** + * @brief initialize completion structure + * + * @param[in] ptr - completion structure + */ +static inline void +adf_os_init_completion(adf_os_comp_t *ptr) +{ + __adf_os_init_completion(ptr); +} + +/** + * @brief wait for completion till timeout + * @param[in] ptr - completion structure + * @param[in] timeout - timeout value in jiffies + * + * @Return: 0 if timed out, and positive on completion + */ +static inline unsigned long +adf_os_wait_for_completion_timeout(adf_os_comp_t *ptr, unsigned long timeout) +{ + return __adf_os_wait_for_completion_timeout(ptr, timeout); +} + +/** + * @brief wake up the thread waiting for this completion + * + * @param[in] ptr - completion structure + */ +static inline void +adf_os_complete(adf_os_comp_t *ptr) +{ + __adf_os_complete(ptr); +} +#endif /*_ADF_OS_UTIL_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h new file mode 100644 index 000000000000..de3203b42610 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h @@ -0,0 +1,1237 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * Linux implemenation of skbuf + */ +#ifndef _ADF_CMN_NET_PVT_BUF_H +#define _ADF_CMN_NET_PVT_BUF_H + +#include +#include +#include +#include +#include +#include + +#define __ADF_NBUF_NULL NULL + +/* + * Use socket buffer as the underlying implentation as skbuf . + * Linux use sk_buff to represent both packet and data, + * so we use sk_buffer to represent both skbuf . + */ +typedef struct sk_buff * __adf_nbuf_t; + +typedef void (*__adf_nbuf_callback_fn) (struct sk_buff *skb); +#define OSDEP_EAPOL_TID 6 /* send it on VO queue */ + +/* CVG_NBUF_MAX_OS_FRAGS - + * max tx fragments provided by the OS + */ +#define CVG_NBUF_MAX_OS_FRAGS 1 + +/* CVG_NBUF_MAX_EXTRA_FRAGS - + * max tx fragments added by the driver + * The driver will always add one tx fragment (the tx descriptor) and may + * add a second tx fragment (e.g. a TSO segment's modified IP header). + */ +#define CVG_NBUF_MAX_EXTRA_FRAGS 2 + +typedef void (*adf_nbuf_trace_update_t)(char *); + +struct cvg_nbuf_cb { + /* + * Store a pointer to a parent network buffer. + * This is used during TSO to allow the network buffers used for + * segments of the jumbo tx frame to reference the jumbo frame's + * original network buffer, so as each TSO segment's network buffer + * is freed, the original jumbo tx frame's reference count can be + * decremented, and ultimately freed once all the segments have been + * freed. + */ + union { + struct sk_buff *parent; + void *ptr; +#ifdef DEBUG_RX_RING_BUFFER + uint32_t map_index; +#endif + } txrx_field; + + /* + * Store the DMA mapping info for the network buffer fragments + * provided by the OS. + */ + u_int32_t mapped_paddr_lo[CVG_NBUF_MAX_OS_FRAGS]; + + /* + * place tx_desc_id after mapped_paddr_lo to avoid cb length overflow + */ +#ifdef CONFIG_HL_SUPPORT + uint16_t tx_desc_id; +#endif + /* store extra tx fragments provided by the driver */ + struct { + /* vaddr - + * CPU address (a.k.a. virtual address) of the tx fragments added + * by the driver + */ + unsigned char *vaddr[CVG_NBUF_MAX_EXTRA_FRAGS]; + /* paddr_lo - + * bus address (a.k.a. physical address) of the tx fragments added + * by the driver + */ + u_int32_t paddr_lo[CVG_NBUF_MAX_EXTRA_FRAGS]; + u_int16_t len[CVG_NBUF_MAX_EXTRA_FRAGS]; + u_int8_t num; /* how many extra frags has the driver added */ + u_int8_t + /* + * Store a wordstream vs. bytestream flag for each extra fragment, + * plus one more flag for the original fragment(s) of the netbuf. + */ + wordstream_flags : CVG_NBUF_MAX_EXTRA_FRAGS+1; + } extra_frags; +#ifdef QCA_MDM_DEVICE + uint32_t owner_id; + __adf_nbuf_callback_fn adf_nbuf_callback_fn; +#ifdef IPA_OFFLOAD + unsigned long priv_data; +#endif +#endif /* QCA_MDM_DEVICE */ +#ifdef QCA_PKT_PROTO_TRACE + unsigned char proto_type; + unsigned char vdev_id; +#endif /* QCA_PKT_PROTO_TRACE */ +#ifdef QCA_TX_HTT2_SUPPORT + unsigned char tx_htt2_frm: 1; + unsigned char tx_htt2_reserved: 7; +#endif /* QCA_TX_HTT2_SUPPORT */ +}; + +#ifdef QCA_ARP_SPOOFING_WAR +#define NBUF_CB_PTR(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->txrx_field.ptr) +#endif + +#ifdef DEBUG_RX_RING_BUFFER +#define NBUF_MAP_ID(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->txrx_field.map_index) +#endif + +#ifdef QCA_MDM_DEVICE +#define NBUF_OWNER_ID(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->owner_id) +#ifdef IPA_OFFLOAD +#define NBUF_OWNER_PRIV_DATA(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->priv_data) +#endif +#define NBUF_CALLBACK_FN(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->adf_nbuf_callback_fn) +#define NBUF_CALLBACK_FN_EXEC(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->adf_nbuf_callback_fn)(skb) +#endif /* QCA_MDM_DEVICE */ +#define NBUF_MAPPED_PADDR_LO(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->mapped_paddr_lo[0]) +#define NBUF_NUM_EXTRA_FRAGS(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->extra_frags.num) +#define NBUF_EXTRA_FRAG_VADDR(skb, frag_num) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->extra_frags.vaddr[(frag_num)]) +#define NBUF_EXTRA_FRAG_PADDR_LO(skb, frag_num) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->extra_frags.paddr_lo[(frag_num)]) +#define NBUF_EXTRA_FRAG_LEN(skb, frag_num) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->extra_frags.len[(frag_num)]) +#define NBUF_EXTRA_FRAG_WORDSTREAM_FLAGS(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->extra_frags.wordstream_flags) + +#ifdef QCA_PKT_PROTO_TRACE +#define NBUF_SET_PROTO_TYPE(skb, proto_type) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->proto_type = proto_type) +#define NBUF_GET_PROTO_TYPE(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->proto_type) +#else +#define NBUF_SET_PROTO_TYPE(skb, proto_type); +#define NBUF_GET_PROTO_TYPE(skb) 0; +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef QCA_TX_HTT2_SUPPORT +#define NBUF_SET_TX_HTT2_FRM(skb, candi) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->tx_htt2_frm = candi) +#define NBUF_GET_TX_HTT2_FRM(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->tx_htt2_frm) +#else +#define NBUF_SET_TX_HTT2_FRM(skb, candi) +#define NBUF_GET_TX_HTT2_FRM(skb) 0 +#endif /* QCA_TX_HTT2_SUPPORT */ + +#ifdef CONFIG_HL_SUPPORT +#define NBUF_CB_ID(skb) \ + (&((struct cvg_nbuf_cb *)((skb)->cb))->tx_desc_id) +#endif + +#define __adf_nbuf_get_num_frags(skb) \ + /* assume the OS provides a single fragment */ \ + (NBUF_NUM_EXTRA_FRAGS(skb) + 1) + + +#define __adf_nbuf_frag_push_head( \ + skb, frag_len, frag_vaddr, frag_paddr_lo, frag_paddr_hi) \ + do { \ + int frag_num = NBUF_NUM_EXTRA_FRAGS(skb)++; \ + NBUF_EXTRA_FRAG_VADDR(skb, frag_num) = frag_vaddr; \ + NBUF_EXTRA_FRAG_PADDR_LO(skb, frag_num) = frag_paddr_lo; \ + NBUF_EXTRA_FRAG_LEN(skb, frag_num) = frag_len; \ + } while (0) + +#define __adf_nbuf_get_frag_len(skb, frag_num) \ + ((frag_num < NBUF_NUM_EXTRA_FRAGS(skb)) ? \ + NBUF_EXTRA_FRAG_LEN(skb, frag_num) : (skb)->len) + +#define __adf_nbuf_get_frag_vaddr(skb, frag_num) \ + ((frag_num < NBUF_NUM_EXTRA_FRAGS(skb)) ? \ + NBUF_EXTRA_FRAG_VADDR(skb, frag_num) : ((skb)->data)) + +#define __adf_nbuf_get_frag_paddr_lo(skb, frag_num) \ + ((frag_num < NBUF_NUM_EXTRA_FRAGS(skb)) ? \ + NBUF_EXTRA_FRAG_PADDR_LO(skb, frag_num) : \ + /* assume that the OS only provides a single fragment */ \ + NBUF_MAPPED_PADDR_LO(skb)) + +#define __adf_nbuf_get_frag_is_wordstream(skb, frag_num) \ + ((frag_num < NBUF_NUM_EXTRA_FRAGS(skb)) ? \ + (NBUF_EXTRA_FRAG_WORDSTREAM_FLAGS(skb) >> \ + (frag_num)) & 0x1 : \ + (NBUF_EXTRA_FRAG_WORDSTREAM_FLAGS(skb) >> \ + (CVG_NBUF_MAX_EXTRA_FRAGS)) & 0x1) + +#define __adf_nbuf_set_frag_is_wordstream(skb, frag_num, is_wordstream) \ + do { \ + if (frag_num >= NBUF_NUM_EXTRA_FRAGS(skb)) { \ + frag_num = CVG_NBUF_MAX_EXTRA_FRAGS; \ + } \ + /* clear the old value */ \ + NBUF_EXTRA_FRAG_WORDSTREAM_FLAGS(skb) &= ~(1 << frag_num); \ + /* set the new value */ \ + NBUF_EXTRA_FRAG_WORDSTREAM_FLAGS(skb) |= \ + ((is_wordstream) << frag_num); \ + } while (0) + +#define __adf_nbuf_trace_set_proto_type(skb, proto_type) \ + NBUF_SET_PROTO_TYPE(skb, proto_type) +#define __adf_nbuf_trace_get_proto_type(skb) \ + NBUF_GET_PROTO_TYPE(skb); + +typedef struct __adf_nbuf_qhead { + struct sk_buff *head; + struct sk_buff *tail; + unsigned int qlen; +}__adf_nbuf_queue_t; + +// typedef struct sk_buff_head __adf_nbuf_queue_t; + +// struct anet_dma_info { +// dma_addr_t daddr; +// uint32_t len; +// }; +// +// struct __adf_nbuf_map { +// int nelem; +// struct anet_dma_info dma[1]; +// }; +// +// typedef struct __adf_nbuf_map *__adf_nbuf_dmamap_t; + + +/* + * Use sk_buff_head as the implementation of adf_nbuf_queue_t. + * Because the queue head will most likely put in some structure, + * we don't use pointer type as the definition. + */ + + +/* + * prototypes. Implemented in adf_nbuf_pvt.c + */ +__adf_nbuf_t __adf_nbuf_alloc(__adf_os_device_t osdev, size_t size, int reserve, int align, int prio); +#ifdef QCA_ARP_SPOOFING_WAR +__adf_nbuf_t __adf_rx_nbuf_alloc(__adf_os_device_t osdev, size_t size, + int reserve, int align, int prio); +#endif +void __adf_nbuf_free (struct sk_buff *skb); +void __adf_nbuf_ref (struct sk_buff *skb); +int __adf_nbuf_shared (struct sk_buff *skb); +a_status_t __adf_nbuf_dmamap_create(__adf_os_device_t osdev, + __adf_os_dma_map_t *dmap); +void __adf_nbuf_dmamap_destroy(__adf_os_device_t osdev, + __adf_os_dma_map_t dmap); +a_status_t __adf_nbuf_map(__adf_os_device_t osdev, + struct sk_buff *skb, adf_os_dma_dir_t dir); +void __adf_nbuf_unmap(__adf_os_device_t osdev, + struct sk_buff *skb, adf_os_dma_dir_t dir); +a_status_t __adf_nbuf_map_single(__adf_os_device_t osdev, + struct sk_buff *skb, adf_os_dma_dir_t dir); +void __adf_nbuf_unmap_single(__adf_os_device_t osdev, + struct sk_buff *skb, adf_os_dma_dir_t dir); +void __adf_nbuf_dmamap_info(__adf_os_dma_map_t bmap, adf_os_dmamap_info_t *sg); +void __adf_nbuf_frag_info(struct sk_buff *skb, adf_os_sglist_t *sg); +void __adf_nbuf_dmamap_set_cb(__adf_os_dma_map_t dmap, void *cb, void *arg); +void __adf_nbuf_reg_trace_cb(adf_nbuf_trace_update_t cb_func_ptr); +a_status_t __adf_nbuf_is_dhcp_pkt(struct sk_buff *skb); +a_status_t __adf_nbuf_is_eapol_pkt(struct sk_buff *skb); + +#ifdef QCA_PKT_PROTO_TRACE +void +__adf_nbuf_trace_update(struct sk_buff *buf, char *event_string); +#else +#define __adf_nbuf_trace_update(skb, event_string) +#endif /* QCA_PKT_PROTO_TRACE */ + +static inline a_status_t +__adf_os_to_status(signed int error) +{ + switch(error){ + case 0: + return A_STATUS_OK; + case ENOMEM: + case -ENOMEM: + return A_STATUS_ENOMEM; + default: + return A_STATUS_ENOTSUPP; + } +} + + + +/** + * @brief This keeps the skb shell intact expands the headroom + * in the data region. In case of failure the skb is + * released. + * + * @param skb + * @param headroom + * + * @return skb or NULL + */ +static inline struct sk_buff * +__adf_nbuf_realloc_headroom(struct sk_buff *skb, uint32_t headroom) +{ + if(pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)){ + dev_kfree_skb_any(skb); + skb = NULL; + } + return skb; +} +/** + * @brief This keeps the skb shell intact exapnds the tailroom + * in data region. In case of failure it releases the + * skb. + * + * @param skb + * @param tailroom + * + * @return skb or NULL + */ +static inline struct sk_buff * +__adf_nbuf_realloc_tailroom(struct sk_buff *skb, uint32_t tailroom) +{ + if(likely(!pskb_expand_head(skb, 0, tailroom, GFP_ATOMIC))) + return skb; + /** + * unlikely path + */ + dev_kfree_skb_any(skb); + return NULL; +} +/** + * @brief return the amount of valid data in the skb, If there + * are frags then it returns total length. + * + * @param skb + * + * @return size_t + */ +static inline size_t +__adf_nbuf_len(struct sk_buff *skb) +{ + int i, extra_frag_len = 0; + + i = NBUF_NUM_EXTRA_FRAGS(skb); + while (i-- > 0) { + extra_frag_len += NBUF_EXTRA_FRAG_LEN(skb, i); + } + return (extra_frag_len + skb->len); +} + + +/** + * @brief link two nbufs, the new buf is piggybacked into the + * older one. The older (src) skb is released. + * + * @param dst( buffer to piggyback into) + * @param src (buffer to put) + * + * @return a_status_t (status of the call) if failed the src skb + * is released + */ +static inline a_status_t +__adf_nbuf_cat(struct sk_buff *dst, struct sk_buff *src) +{ + a_status_t error = 0; + + adf_os_assert(dst && src); + + /* + * Since pskb_expand_head unconditionally reallocates the skb->head buffer, + * first check whether the current buffer is already large enough. + */ + if (skb_tailroom(dst) < src->len) { + error = pskb_expand_head(dst, 0, src->len, GFP_ATOMIC); + if (error) { + return __adf_os_to_status(error); + } + } + memcpy(skb_tail_pointer(dst), src->data, src->len); + + skb_put(dst, src->len); + dev_kfree_skb_any(src); + + return __adf_os_to_status(error); +} + + +/** + * @brief create a version of the specified nbuf whose contents + * can be safely modified without affecting other + * users.If the nbuf is a clone then this function + * creates a new copy of the data. If the buffer is not + * a clone the original buffer is returned. + * + * @param skb (source nbuf to create a writable copy from) + * + * @return skb or NULL + */ +static inline struct sk_buff * +__adf_nbuf_unshare(struct sk_buff *skb) +{ + return skb_unshare(skb, GFP_ATOMIC); +} +/**************************nbuf manipulation routines*****************/ + +static inline int +__adf_nbuf_headroom(struct sk_buff *skb) +{ + return skb_headroom(skb); +} +/** + * @brief return the amount of tail space available + * + * @param buf + * + * @return amount of tail room + */ +static inline uint32_t +__adf_nbuf_tailroom(struct sk_buff *skb) +{ + return skb_tailroom(skb); +} + +/** + * @brief Push data in the front + * + * @param[in] buf buf instance + * @param[in] size size to be pushed + * + * @return New data pointer of this buf after data has been pushed, + * or NULL if there is not enough room in this buf. + */ +static inline uint8_t * +__adf_nbuf_push_head(struct sk_buff *skb, size_t size) +{ + if(NBUF_MAPPED_PADDR_LO(skb)) { + NBUF_MAPPED_PADDR_LO(skb) -= size; + } + return skb_push(skb, size); +} +/** + * @brief Puts data in the end + * + * @param[in] buf buf instance + * @param[in] size size to be pushed + * + * @return data pointer of this buf where new data has to be + * put, or NULL if there is not enough room in this buf. + */ +static inline uint8_t * +__adf_nbuf_put_tail(struct sk_buff *skb, size_t size) +{ + if (skb_tailroom(skb) < size) { + if(unlikely(pskb_expand_head(skb, 0, size-skb_tailroom(skb), GFP_ATOMIC))) { + dev_kfree_skb_any(skb); + return NULL; + } + } + return skb_put(skb, size); +} + +/** + * @brief pull data out from the front + * + * @param[in] buf buf instance + * @param[in] size size to be popped + * + * @return New data pointer of this buf after data has been popped, + * or NULL if there is not sufficient data to pull. + */ +static inline uint8_t * +__adf_nbuf_pull_head(struct sk_buff *skb, size_t size) +{ + if(NBUF_MAPPED_PADDR_LO(skb)) { + NBUF_MAPPED_PADDR_LO(skb) += size; + } + return skb_pull(skb, size); +} +/** + * + * @brief trim data out from the end + * + * @param[in] buf buf instance + * @param[in] size size to be popped + * + * @return none + */ +static inline void +__adf_nbuf_trim_tail(struct sk_buff *skb, size_t size) +{ + return skb_trim(skb, skb->len - size); +} + +/** + * @brief test whether the nbuf is cloned or not + * + * @param buf + * + * @return a_bool_t (TRUE if it is cloned or else FALSE) + */ +static inline a_bool_t +__adf_nbuf_is_cloned(struct sk_buff *skb) +{ + return skb_cloned(skb); +} + +/* TODO: Fix this */ +static inline uint8_t * +__adf_nbuf_init(struct sk_buff *skb, size_t reserve, size_t align, size_t tail_size) +{ +#if 0 + unsigned long offset; + /** + * Align & make sure that the tail & data are adjusted properly + */ + if(align){ + offset = ((unsigned long) skb->data) % align; + if(offset) + skb_reserve(skb, align - offset); + } + + /** + * NOTE:alloc doesn't take responsibility if reserve unaligns the data + * pointer + */ + skb_reserve(skb, reserve); + return skb; +#endif + return NULL; +} + +static inline void +__adf_nbuf_free_pool(struct sk_buff *skb) +{ + return; +} + +/*********************nbuf private buffer routines*************/ + +/** + * @brief get the priv pointer from the nbuf'f private space + * + * @param buf + * + * @return data pointer to typecast into your priv structure + */ +static inline uint8_t * +__adf_nbuf_get_priv(struct sk_buff *skb) +{ + return &skb->cb[8]; +} + +/** + * @brief This will return the header's addr & m_len + */ +static inline void +__adf_nbuf_peek_header(struct sk_buff *skb, uint8_t **addr, + uint32_t *len) +{ + *addr = skb->data; + *len = skb->len; +} + + /* adf_nbuf_queue_init() - initialize a skbuf queue + */ +/* static inline void */ +/* __adf_nbuf_queue_init(struct sk_buff_head *qhead) */ +/* { */ +/* skb_queue_head_init(qhead); */ +/* } */ + +/* /\* */ +/* * adf_nbuf_queue_add() - add a skbuf to the end of the skbuf queue */ + +/* * We use the non-locked version because */ +/* * there's no need to use the irq safe version of spinlock. */ +/* * However, the caller has to do synchronization by itself. */ +/* *\/ */ +/* static inline void */ +/* __adf_nbuf_queue_add(struct sk_buff_head *qhead, */ +/* struct sk_buff *skb) */ +/* { */ +/* __skb_queue_tail(qhead, skb); */ +/* adf_os_assert(qhead->next == qhead->prev); */ +/* } */ + +/* /\* */ +/* * adf_nbuf_queue_remove() - remove a skbuf from the head of the skbuf queue */ +/* * */ +/* * We use the non-locked version because */ +/* * there's no need to use the irq safe version of spinlock. */ +/* * However, the caller has to do synchronization by itself. */ +/* *\/ */ +/* static inline struct sk_buff * */ +/* __adf_nbuf_queue_remove(struct sk_buff_head * qhead) */ +/* { */ +/* adf_os_assert(qhead->next == qhead->prev); */ +/* return __skb_dequeue(qhead); */ +/* } */ + +/* static inline uint32_t */ +/* __adf_nbuf_queue_len(struct sk_buff_head * qhead) */ +/* { */ +/* adf_os_assert(qhead->next == qhead->prev); */ +/* return qhead->qlen; */ +/* } */ +/* /\** */ +/* * @brief returns the first guy in the Q */ +/* * @param qhead */ +/* * */ +/* * @return (NULL if the Q is empty) */ +/* *\/ */ +/* static inline struct sk_buff * */ +/* __adf_nbuf_queue_first(struct sk_buff_head *qhead) */ +/* { */ +/* adf_os_assert(qhead->next == qhead->prev); */ +/* return (skb_queue_empty(qhead) ? NULL : qhead->next); */ +/* } */ +/* /\** */ +/* * @brief return the next packet from packet chain */ +/* * */ +/* * @param buf (packet) */ +/* * */ +/* * @return (NULL if no packets are there) */ +/* *\/ */ +/* static inline struct sk_buff * */ +/* __adf_nbuf_queue_next(struct sk_buff *skb) */ +/* { */ +/* return NULL; // skb->next; */ +/* } */ +/* /\** */ +/* * adf_nbuf_queue_empty() - check if the skbuf queue is empty */ +/* *\/ */ +/* static inline a_bool_t */ +/* __adf_nbuf_is_queue_empty(struct sk_buff_head *qhead) */ +/* { */ +/* adf_os_assert(qhead->next == qhead->prev); */ +/* return skb_queue_empty(qhead); */ +/* } */ + +/******************Custom queue*************/ + + + +/** + * @brief initiallize the queue head + * + * @param qhead + */ +static inline a_status_t +__adf_nbuf_queue_init(__adf_nbuf_queue_t *qhead) +{ + memset(qhead, 0, sizeof(struct __adf_nbuf_qhead)); + return A_STATUS_OK; +} + + +/** + * @brief add an skb in the tail of the queue. This is a + * lockless version, driver must acquire locks if it + * needs to synchronize + * + * @param qhead + * @param skb + */ +static inline void +__adf_nbuf_queue_add(__adf_nbuf_queue_t *qhead, + struct sk_buff *skb) +{ + skb->next = NULL;/*Nullify the next ptr*/ + + if(!qhead->head) + qhead->head = skb; + else + qhead->tail->next = skb; + + qhead->tail = skb; + qhead->qlen++; +} + +/** + * @brief add an skb at the head of the queue. This is a + * lockless version, driver must acquire locks if it + * needs to synchronize + * + * @param qhead + * @param skb + */ +static inline void +__adf_nbuf_queue_insert_head(__adf_nbuf_queue_t *qhead, + __adf_nbuf_t skb) +{ + if(!qhead->head){ + /*Empty queue Tail pointer Must be updated */ + qhead->tail = skb; + } + skb->next = qhead->head; + qhead->head = skb; + qhead->qlen++; +} + +/** + * @brief remove a skb from the head of the queue, this is a + * lockless version. Driver should take care of the locks + * + * @param qhead + * + * @return skb or NULL + */ +static inline struct sk_buff * +__adf_nbuf_queue_remove(__adf_nbuf_queue_t * qhead) +{ + __adf_nbuf_t tmp = NULL; + + if (qhead->head) { + qhead->qlen--; + tmp = qhead->head; + if ( qhead->head == qhead->tail ) { + qhead->head = NULL; + qhead->tail = NULL; + } else { + qhead->head = tmp->next; + } + tmp->next = NULL; + } + return tmp; +} +/** + * @brief return the queue length + * + * @param qhead + * + * @return uint32_t + */ +static inline uint32_t +__adf_nbuf_queue_len(__adf_nbuf_queue_t * qhead) +{ + return qhead->qlen; +} +/** + * @brief returns the first skb in the queue + * + * @param qhead + * + * @return (NULL if the Q is empty) + */ +static inline struct sk_buff * +__adf_nbuf_queue_first(__adf_nbuf_queue_t *qhead) +{ + return qhead->head; +} +/** + * @brief return the next skb from packet chain, remember the + * skb is still in the queue + * + * @param buf (packet) + * + * @return (NULL if no packets are there) + */ +static inline struct sk_buff * +__adf_nbuf_queue_next(struct sk_buff *skb) +{ + return skb->next; +} +/** + * @brief check if the queue is empty or not + * + * @param qhead + * + * @return a_bool_t + */ +static inline a_bool_t +__adf_nbuf_is_queue_empty(__adf_nbuf_queue_t *qhead) +{ + return (qhead->qlen == 0); +} + +/* + * Use sk_buff_head as the implementation of adf_nbuf_queue_t. + * Because the queue head will most likely put in some structure, + * we don't use pointer type as the definition. + */ + + +/* + * prototypes. Implemented in adf_nbuf_pvt.c + */ +adf_nbuf_tx_cksum_t __adf_nbuf_get_tx_cksum(struct sk_buff *skb); +a_status_t __adf_nbuf_set_rx_cksum(struct sk_buff *skb, + adf_nbuf_rx_cksum_t *cksum); +a_status_t __adf_nbuf_get_vlan_info(adf_net_handle_t hdl, + struct sk_buff *skb, + adf_net_vlanhdr_t *vlan); +a_uint8_t __adf_nbuf_get_tid(struct sk_buff *skb); +void __adf_nbuf_set_tid(struct sk_buff *skb, a_uint8_t tid); +a_uint8_t __adf_nbuf_get_exemption_type(struct sk_buff *skb); +/* + * adf_nbuf_pool_init() implementation - do nothing in Linux + */ +static inline a_status_t +__adf_nbuf_pool_init(adf_net_handle_t anet) +{ + return A_STATUS_OK; +} + +/* + * adf_nbuf_pool_delete() implementation - do nothing in linux + */ +#define __adf_nbuf_pool_delete(osdev) + + +/** + * @brief Expand both tailroom & headroom. In case of failure + * release the skb. + * + * @param skb + * @param headroom + * @param tailroom + * + * @return skb or NULL + */ +static inline struct sk_buff * +__adf_nbuf_expand(struct sk_buff *skb, uint32_t headroom, uint32_t tailroom) +{ + if(likely(!pskb_expand_head(skb, headroom, tailroom, GFP_ATOMIC))) + return skb; + + dev_kfree_skb_any(skb); + return NULL; +} + + +/** + * @brief clone the nbuf (copy is readonly) + * + * @param src_nbuf (nbuf to clone from) + * @param dst_nbuf (address of the cloned nbuf) + * + * @return status + * + * @note if GFP_ATOMIC is overkill then we can check whether its + * called from interrupt context and then do it or else in + * normal case use GFP_KERNEL + * @example use "in_irq() || irqs_disabled()" + * + * + */ +static inline struct sk_buff * +__adf_nbuf_clone(struct sk_buff *skb) +{ + return skb_clone(skb, GFP_ATOMIC); +} +/** + * @brief returns a private copy of the skb, the skb returned is + * completely modifiable + * + * @param skb + * + * @return skb or NULL + */ +static inline struct sk_buff * +__adf_nbuf_copy(struct sk_buff *skb) +{ + return skb_copy(skb, GFP_ATOMIC); +} + +#define __adf_nbuf_reserve skb_reserve + +/***********************XXX: misc api's************************/ +static inline a_bool_t +__adf_nbuf_tx_cksum_info(struct sk_buff *skb, uint8_t **hdr_off, + uint8_t **where) +{ +// if (skb->ip_summed == CHECKSUM_NONE) +// return A_FALSE; +// +// if (skb->ip_summed == CHECKSUM_HW) { +// *hdr_off = (uint8_t *)(skb->h.raw - skb->data); +// *where = *hdr_off + skb->csum; +// return A_TRUE; +// } + + adf_os_assert(0); + return A_FALSE; +} + + +/* + * XXX What about other unions in skb? Windows might not have it, but we + * should penalize linux drivers for it. + * Besides this function is not likely doint the correct thing. + */ +static inline a_status_t +__adf_nbuf_get_tso_info(struct sk_buff *skb, adf_nbuf_tso_t *tso) +{ + adf_os_assert(0); + return A_STATUS_ENOTSUPP; +/* + if (!skb_shinfo(skb)->tso_size) { + tso->type = adf_net_TSO_NONE; + return; + } + + tso->mss = skb_shinfo(skb)->tso_size; +*/ +// tso->hdr_off = (uint8_t)(skb->h.raw - skb->data); +// +// if (skb->protocol == ntohs(ETH_P_IP)) +// tso->type = ADF_NET_TSO_IPV4; +// else if (skb->protocol == ntohs(ETH_P_IPV6)) +// tso->type = ADF_NET_TSO_ALL; +// else +// tso->type = ADF_NET_TSO_NONE; +} + +/** + * @brief return the pointer the skb's buffer + * + * @param skb + * + * @return uint8_t * + */ +static inline uint8_t * +__adf_nbuf_head(struct sk_buff *skb) +{ + return skb->head; +} + +/** + * @brief return the pointer to data header in the skb + * + * @param skb + * + * @return uint8_t * + */ +static inline uint8_t * +__adf_nbuf_data(struct sk_buff *skb) +{ + return skb->data; +} + +/** + * @brief return the priority value of the skb + * + * @param skb + * + * @return uint32_t + */ +static inline uint32_t +__adf_nbuf_get_priority(struct sk_buff *skb) +{ + return skb->priority; +} + +/** + * @brief sets the priority value of the skb + * + * @param skb, priority + * + * @return void + */ +static inline void +__adf_nbuf_set_priority(struct sk_buff *skb, uint32_t p) +{ + skb->priority = p; +} + +/** + * @brief sets the next skb pointer of the current skb + * + * @param skb and next_skb + * + * @return void + */ +static inline void +__adf_nbuf_set_next(struct sk_buff *skb, struct sk_buff *skb_next) +{ + skb->next = skb_next; +} + +/** + * @brief return the next skb pointer of the current skb + * + * @param skb - the current skb + * + * @return the next skb pointed to by the current skb + */ +static inline struct sk_buff * +__adf_nbuf_next(struct sk_buff *skb) +{ + return skb->next; +} + +/** + * @brief sets the next skb pointer of the current skb. This fn is used to + * link up extensions to the head skb. Does not handle linking to the head + * + * @param skb and next_skb + * + * @return void + */ +static inline void +__adf_nbuf_set_next_ext(struct sk_buff *skb, struct sk_buff *skb_next) +{ + skb->next = skb_next; +} + +/** + * @brief return the next skb pointer of the current skb + * + * @param skb - the current skb + * + * @return the next skb pointed to by the current skb + */ +static inline struct sk_buff * +__adf_nbuf_next_ext(struct sk_buff *skb) +{ + return skb->next; +} + +/** + * @brief link list of packet extensions to the head segment + * @details + * This function is used to link up a list of packet extensions (seg1, 2, + * ...) to the nbuf holding the head segment (seg0) + * @param[in] head_buf nbuf holding head segment (single) + * @param[in] ext_list nbuf list holding linked extensions to the head + * @param[in] ext_len Total length of all buffers in the extension list + */ +static inline void +__adf_nbuf_append_ext_list( + struct sk_buff *skb_head, + struct sk_buff * ext_list, + size_t ext_len) +{ + skb_shinfo(skb_head)->frag_list = ext_list; + skb_head->data_len = ext_len; + skb_head->len += skb_head->data_len; +} + +static inline void +__adf_nbuf_tx_free(struct sk_buff *bufs, int tx_err) +{ + while (bufs) { + struct sk_buff *next = __adf_nbuf_next(bufs); + __adf_nbuf_free(bufs); + bufs = next; + } +} + +/** + * @brief return the checksum value of the skb + * + * @param skb + * + * @return uint32_t + */ +static inline uint32_t +__adf_nbuf_get_age(struct sk_buff *skb) +{ + return skb->csum; +} + +/** + * @brief sets the checksum value of the skb + * + * @param skb, value + * + * @return void + */ +static inline void +__adf_nbuf_set_age(struct sk_buff *skb, uint32_t v) +{ + skb->csum = v; +} + +/** + * @brief adjusts the checksum/age value of the skb + * + * @param skb, adj + * + * @return void + */ +static inline void +__adf_nbuf_adj_age(struct sk_buff *skb, uint32_t adj) +{ + skb->csum -= adj; +} + +/** + * @brief return the length of the copy bits for skb + * + * @param skb, offset, len, to + * + * @return int32_t + */ +static inline int32_t +__adf_nbuf_copy_bits(struct sk_buff *skb, int32_t offset, int32_t len, void *to) +{ + return skb_copy_bits(skb, offset, to, len); +} + +/** + * @brief sets the length of the skb and adjust the tail + * + * @param skb, length + * + * @return void + */ +static inline void +__adf_nbuf_set_pktlen(struct sk_buff *skb, uint32_t len) +{ + if (skb->len > len) { + skb_trim(skb, len); + } + else { + if (skb_tailroom(skb) < len - skb->len) { + if(unlikely(pskb_expand_head( + skb, 0, len - skb->len -skb_tailroom(skb), GFP_ATOMIC))) + { + dev_kfree_skb_any(skb); + //KASSERT(0, ("No enough tailroom for skb, failed to alloc")); + adf_os_assert(0); + } + } + skb_put(skb, (len - skb->len)); + } +} + +/** + * @brief sets the protocol value of the skb + * + * @param skb, protocol + * + * @return void + */ +static inline void +__adf_nbuf_set_protocol(struct sk_buff *skb, uint16_t protocol) +{ + skb->protocol = protocol; +} + +/** + * @brief test whether the nbuf is nonlinear or not + * + * @param buf + * + * @return a_bool_t (TRUE if it is nonlinear or else FALSE) + */ +static inline a_bool_t +__adf_nbuf_is_nonlinear(struct sk_buff *skb) +{ + return skb_is_nonlinear(skb); +} + +/** + * @brief zeros out cb + * + * @param nbuf + * + * @return void + */ +static inline void +__adf_nbuf_reset_ctxt(__adf_nbuf_t nbuf) +{ + adf_os_mem_zero(nbuf->cb, sizeof(nbuf->cb)); +} + +/** + * @brief This function peeks data into the buffer at given offset + * + * @param[in] buf buffer + * @param[out] data peeked output buffer + * @param[in] off offset + * @param[in] len length of buffer requested beyond offset + * + * @return status of operation + */ +static inline a_status_t +__adf_nbuf_peek_data(__adf_nbuf_t buf, void **data, a_uint32_t off, + a_uint32_t len) +{ + /* check if we can peek data of len bytes from the offset */ + if (buf->len < (off + len)) { + *data = NULL; + return A_STATUS_ENOMEM; + } + + *data = (void*)&buf->data[off]; + + return A_STATUS_OK; +} + +#define __adf_nbuf_set_tx_htt2_frm(skb, candi) \ + NBUF_SET_TX_HTT2_FRM(skb, candi) +#define __adf_nbuf_get_tx_htt2_frm(skb) \ + NBUF_GET_TX_HTT2_FRM(skb) + +#endif /*_adf_nbuf_PVT_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_atomic_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_atomic_pvt.h new file mode 100644 index 000000000000..4b4c8ff544e2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_atomic_pvt.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2010 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef ADF_OS_ATOMIC_PVT_H +#define ADF_OS_ATOMIC_PVT_H + +#include /* a_status_t */ + +#include + +typedef atomic_t __adf_os_atomic_t; + +static inline a_status_t +__adf_os_atomic_init(__adf_os_atomic_t *v) +{ + atomic_set(v, 0); + + return A_STATUS_OK; +} + +static inline a_uint32_t +__adf_os_atomic_read(__adf_os_atomic_t *v) +{ + return (atomic_read(v)); +} +static inline void +__adf_os_atomic_inc(__adf_os_atomic_t *v) +{ + atomic_inc(v); +} + +static inline void +__adf_os_atomic_dec(__adf_os_atomic_t *v) +{ + atomic_dec(v); +} + +static inline void +__adf_os_atomic_add(int i, __adf_os_atomic_t *v) +{ + atomic_add(i, v); +} + +static inline a_uint32_t + __adf_os_atomic_dec_and_test(__adf_os_atomic_t *v) +{ + return(atomic_dec_and_test(v)); +} + +static inline void + __adf_os_atomic_set(__adf_os_atomic_t *v, int i) +{ + atomic_set(v, i); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.c new file mode 100644 index 000000000000..e54b99e83052 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include +#include +#include +#include + +#include "adf_os_defer_pvt.h" + +void +__adf_os_defer_func(struct work_struct *work) +{ + __adf_os_work_t *ctx = container_of(work, __adf_os_work_t, work); + if (ctx->fn == NULL) + { + printk("BugCheck: Callback is not initilized while creating work queue\n"); + return; + } + ctx->fn(ctx->arg); +} + +void +__adf_os_defer_delayed_func(struct work_struct *dwork) +{ + __adf_os_delayed_work_t *ctx = container_of(dwork, __adf_os_delayed_work_t, dwork.work); + if (ctx->fn == NULL) + { + printk("BugCheck: Callback is not initilized while creating delayed work queue\n"); + return; + } + ctx->fn(ctx->arg); +} +EXPORT_SYMBOL(__adf_os_defer_func); +EXPORT_SYMBOL(__adf_os_defer_delayed_func); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.h new file mode 100644 index 000000000000..1b1462503ec2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_defer_pvt.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_DEFER_PVT_H +#define _ADF_CMN_OS_DEFER_PVT_H + +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#endif +#include + +typedef struct tasklet_struct __adf_os_bh_t; +typedef struct workqueue_struct __adf_os_workqueue_t; + +/** + * wrapper around the real task func + */ +typedef struct { + struct work_struct work; + adf_os_defer_fn_t fn; + void *arg; +}__adf_os_work_t; + +typedef struct { + struct delayed_work dwork; + adf_os_defer_fn_t fn; + void *arg; +}__adf_os_delayed_work_t; + +extern void __adf_os_defer_func(struct work_struct *work); +extern void __adf_os_defer_delayed_func(struct work_struct *work); + +typedef void (*__adf_os_bh_fn_t)(unsigned long arg); + +static inline a_status_t +__adf_os_init_work(adf_os_handle_t hdl, + __adf_os_work_t *work, + adf_os_defer_fn_t func, + void *arg) +{ + /*Initilize func and argument in work struct */ + work->fn = func; + work->arg = arg; +#ifdef CONFIG_CNSS + cnss_init_work(&work->work, __adf_os_defer_func); +#else + INIT_WORK(&work->work, __adf_os_defer_func); +#endif + return A_STATUS_OK; +} + +static inline a_status_t +__adf_os_init_delayed_work(adf_os_handle_t hdl, + __adf_os_delayed_work_t *work, + adf_os_defer_fn_t func, + void *arg) +{ + /*Initilize func and argument in work struct */ + work->fn = func; + work->arg = arg; +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&work->dwork, __adf_os_defer_delayed_func); +#else + INIT_DELAYED_WORK(&work->dwork, __adf_os_defer_delayed_func); +#endif + return A_STATUS_OK; +} + +static inline __adf_os_workqueue_t* __adf_os_create_workqueue(char *name) +{ + return create_workqueue(name); +} + +static inline void __adf_os_queue_work(adf_os_handle_t hdl, __adf_os_workqueue_t *wqueue, __adf_os_work_t* work) +{ + queue_work(wqueue, &work->work); +} + +static inline void __adf_os_queue_delayed_work(adf_os_handle_t hdl, __adf_os_workqueue_t *wqueue, __adf_os_delayed_work_t* work, a_uint32_t delay) +{ + queue_delayed_work(wqueue, &work->dwork, delay); +} + +static inline void __adf_os_flush_workqueue(adf_os_handle_t hdl, __adf_os_workqueue_t *wqueue) +{ + flush_workqueue(wqueue); +} + +static inline void __adf_os_destroy_workqueue(adf_os_handle_t hdl, __adf_os_workqueue_t *wqueue) +{ + destroy_workqueue(wqueue); +} + +static inline a_status_t __adf_os_init_bh(adf_os_handle_t hdl, + struct tasklet_struct *bh, + adf_os_defer_fn_t func, + void *arg) +{ + tasklet_init(bh, (__adf_os_bh_fn_t)func, (unsigned long)arg); + + return A_STATUS_OK; +} + +static inline a_status_t +__adf_os_sched_work(adf_os_handle_t hdl, __adf_os_work_t * work) +{ + schedule_work(&work->work); + return A_STATUS_OK; +} + +static inline a_status_t __adf_os_sched_bh(adf_os_handle_t hdl, + struct tasklet_struct * bh) +{ + tasklet_schedule(bh); + + return A_STATUS_OK; +} + +static inline a_status_t +__adf_os_disable_work(adf_os_handle_t hdl, __adf_os_work_t * work) +{ + /** + * XXX:??? + */ + return A_STATUS_OK; +} +static inline a_status_t +__adf_os_disable_bh(adf_os_handle_t hdl, struct tasklet_struct *bh) +{ + tasklet_kill(bh); + + return A_STATUS_OK; +} +#endif /*_ADF_CMN_OS_DEFER_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_dma_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_dma_pvt.h new file mode 100644 index 000000000000..d0e9e6322ed4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_dma_pvt.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_DMA_PVT_H +#define _ADF_CMN_OS_DMA_PVT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + * XXX:error handling + * + * @brief allocate a DMA buffer mapped to local bus Direction + * doesnt matter, since this API is called at init time. + * + * @param size + * @param coherentSMP_CACHE_BYTES + * @param dmap + * + * @return void* + */ +static inline void * +__adf_os_dmamem_alloc(adf_os_device_t osdev, + size_t size, + a_bool_t coherent, + __adf_os_dma_map_t *dmap) +{ + void *vaddr; + __adf_os_dma_map_t lmap; + + lmap = kzalloc(sizeof(struct __adf_os_dma_map), GFP_KERNEL); + + adf_os_assert(lmap); + + lmap->nsegs = 1; + lmap->coherent = coherent; + + if(coherent) + vaddr = dma_alloc_coherent(osdev->dev, size, &lmap->seg[0].daddr, + GFP_ATOMIC); + else + vaddr = dma_alloc_noncoherent(osdev->dev, size, &lmap->seg[0].daddr, + GFP_ATOMIC); + + adf_os_assert(vaddr); + + lmap->seg[0].len = size; + lmap->mapped = 1; + + (*dmap) = lmap; + + return vaddr; +} + +/* + * Free a previously mapped DMA buffer + * Direction doesnt matter, since this API is called at closing time. + */ +static inline void +__adf_os_dmamem_free(adf_os_device_t osdev, __adf_os_size_t size, + a_bool_t coherent, void *vaddr, __adf_os_dma_map_t dmap) +{ + adf_os_assert(dmap->mapped); + + if(coherent) + dma_free_coherent(osdev->dev, size, vaddr, dmap->seg[0].daddr); + else + dma_free_noncoherent(osdev->dev, size, vaddr, dmap->seg[0].daddr); + + kfree(dmap); +} + + +#define __adf_os_dmamem_map2addr(_dmap) ((_dmap)->seg[0].daddr) + +static inline void +__adf_os_dmamem_cache_sync(__adf_os_device_t osdev, __adf_os_dma_map_t dmap, + adf_os_cache_sync_t sync) +{ + if(!dmap->coherent){ + dma_sync_single_for_cpu(osdev->dev, dmap->seg[0].daddr, dmap->seg[0].len, + DMA_BIDIRECTIONAL); + } +} +static inline adf_os_size_t +__adf_os_cache_line_size(void) +{ + return SMP_CACHE_BYTES; +} + +static inline void +__adf_os_invalidate_range(void * start, void * end) +{ +#ifdef MSM_PLATFORM + dmac_inv_range(start, end); +#else + //TODO figure out how to invalidate cache on x86 and other non-MSM platform + __adf_os_print("Cache Invalidate not yet implemented for non-MSM platform\n"); + return; +#endif +} + + +#endif /*_ADF_CMN_OS_DMA_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_io_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_io_pvt.h new file mode 100644 index 000000000000..04050fd5682f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_io_pvt.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_IO_PVT_H +#define _ADF_CMN_OS_IO_PVT_H + +#include +#include + +#ifdef QCA_PARTNER_PLATFORM +#include "ath_carr_pltfrm.h" +#else +#include +#endif + + +#define __adf_os_reg_read8(_dev, _addr) \ + readb((volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_reg_read16(_dev, _addr) \ + readw((volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_reg_read32(_dev, _addr) \ + readl((volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_reg_read64(_dev, _addr) \ + readq((volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + + +#define __adf_os_reg_write8(_dev, _addr, _val) \ + writeb(_val, (volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_reg_write16(_dev, _addr, _val) \ + writew(_val, (volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_reg_write32(_dev, _addr, _val) \ + writel(_val, (volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_reg_write64(_dev, _addr, _val) \ + writeq(_val, (volatile void __iomem *)((_dev)->res.vaddr + (_addr))) + +#define __adf_os_ioremap(_addr, _len) \ + ioremap(_addr, _len) + + +#define __adf_os_ntohs ntohs +#define __adf_os_ntohl ntohl + +#define __adf_os_htons htons +#define __adf_os_htonl htonl + +#define __adf_os_cpu_to_le16 cpu_to_le16 +#define __adf_os_cpu_to_le32 cpu_to_le32 +#define __adf_os_cpu_to_le64 cpu_to_le64 + +#define __adf_os_cpu_to_be16 cpu_to_be16 +#define __adf_os_cpu_to_be32 cpu_to_be32 +#define __adf_os_cpu_to_be64 cpu_to_be64 + +#define __adf_os_le16_to_cpu le16_to_cpu +#define __adf_os_le32_to_cpu le32_to_cpu +#define __adf_os_le64_to_cpu le64_to_cpu + +#define __adf_os_be16_to_cpu be16_to_cpu +#define __adf_os_be32_to_cpu be32_to_cpu +#define __adf_os_be64_to_cpu be64_to_cpu + +#endif /*_ADF_CMN_OS_IO_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.c new file mode 100644 index 000000000000..c24684f1c196 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include + +#include "adf_os_lock.h" + +EXPORT_SYMBOL(adf_os_spin_lock_bh_outline); +EXPORT_SYMBOL(adf_os_spin_unlock_bh_outline); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.h new file mode 100644 index 000000000000..9bfdb501dde2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_lock_pvt.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_LOCK_PVT_H +#define _ADF_CMN_OS_LOCK_PVT_H + +#include +#include +#include +#include + +typedef struct __adf_os_linux_spinlock { + spinlock_t spinlock; + unsigned int flags; + unsigned long _flags; +} adf_os_linux_spinlock_t; + +/* define for flag */ +#define ADF_OS_LINUX_UNLOCK_BH 1 + +typedef adf_os_linux_spinlock_t __adf_os_spinlock_t; +typedef struct semaphore __adf_os_mutex_t; + +/** + * @brief Initialize the mutex + * + * @param mutex + * + * @return + */ +static inline a_status_t +__adf_os_init_mutex(struct semaphore *m) +{ + sema_init(m, 1); + return A_STATUS_OK; +} + + + + +static inline int +__adf_os_mutex_acquire(adf_os_device_t osdev, struct semaphore *m) +{ + down(m); + return 0; +} + +static inline void +__adf_os_mutex_release(adf_os_device_t osdev, struct semaphore *m) +{ + up(m); +} + +static inline a_status_t +__adf_os_spinlock_init(__adf_os_spinlock_t *lock) +{ + spin_lock_init(&lock->spinlock); + lock->flags = 0; + + return A_STATUS_OK; +} + +#define __adf_os_spinlock_destroy(lock) +/** + * @brief Acquire a Spinlock (SMP) & disable Preemption (Preemptive) + * + * @param lock (Lock object) + * @param flags (Current IRQ mask) + */ +static inline void +__adf_os_spin_lock(__adf_os_spinlock_t *lock) +{ + spin_lock(&lock->spinlock); +} + +/** + * @brief Unlock the spinlock and enables the Preemption + * + * @param lock + * @param flags + */ +static inline void +__adf_os_spin_unlock(__adf_os_spinlock_t *lock) +{ + spin_unlock(&lock->spinlock); +} + +/** + * @brief Acquire a Spinlock (SMP) & disable Preemption (Preemptive) + * Disable IRQs + * @param lock (Lock object) + */ +static inline void +__adf_os_spin_lock_irqsave(__adf_os_spinlock_t *lock) +{ + spin_lock_irqsave(&lock->spinlock, lock->_flags); +} + +/** + * @brief Unlock the spinlock and enables the Preemption + * Enable IRQ + * @param lock (Lock object) + */ +static inline void +__adf_os_spin_unlock_irqrestore(__adf_os_spinlock_t *lock) +{ + spin_unlock_irqrestore(&lock->spinlock, lock->_flags); +} + +/** + * @brief Acquire the spinlock and disable bottom halves + * + * @param lock + */ + +/* + * Synchronous versions - only for OS' that have interrupt disable + */ +#define __adf_os_spin_lock_irq(_pLock, _flags) spin_lock_irqsave(_pLock, _flags) +#define __adf_os_spin_unlock_irq(_pLock, _flags) spin_unlock_irqrestore(_pLock, _flags) + +static inline void +__adf_os_spin_lock_bh(__adf_os_spinlock_t *lock) +{ + if (likely(irqs_disabled() || in_softirq())) { + spin_lock(&lock->spinlock); + } else { + spin_lock_bh(&lock->spinlock); + lock->flags |= ADF_OS_LINUX_UNLOCK_BH; + } + +} +static inline void +__adf_os_spin_unlock_bh(__adf_os_spinlock_t *lock) +{ + if (unlikely(lock->flags & ADF_OS_LINUX_UNLOCK_BH)) { + lock->flags &= ~ADF_OS_LINUX_UNLOCK_BH; + spin_unlock_bh(&lock->spinlock); + } else + spin_unlock(&lock->spinlock); +} + +static inline a_bool_t +__adf_os_spinlock_irq_exec(adf_os_handle_t hdl, + __adf_os_spinlock_t *lock, + adf_os_irqlocked_func_t func, + void *arg) +{ + unsigned long flags; + a_bool_t ret; + + spin_lock_irqsave(&lock->spinlock, flags); + ret = func(arg); + spin_unlock_irqrestore(&lock->spinlock, flags); + + return ret; +} + + +static inline a_bool_t +__adf_os_in_softirq(void) +{ + return (in_softirq()); +} +#endif /*_ADF_CMN_OS_LOCK_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.c new file mode 100644 index 000000000000..511f97a5de6d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include "adf_os_mem.h" +#include "adf_os_module.h" + + +int adf_dbg_mask; +adf_os_declare_param(adf_dbg_mask, ADF_OS_PARAM_TYPE_INT32); + + +EXPORT_SYMBOL(adf_os_mem_alloc_outline); +EXPORT_SYMBOL(adf_os_mem_free_outline); +EXPORT_SYMBOL(adf_os_mem_zero_outline); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.h new file mode 100644 index 000000000000..d1205ddf36c7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_mem_pvt.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef ADF_CMN_OS_MEM_PVT_H +#define ADF_CMN_OS_MEM_PVT_H + +#ifdef __KERNEL__ +#include +#include +#include +#include +#if defined(HIF_USB) +#include +#elif defined(HIF_PCI) +#include /* pci_alloc_consistent */ +#endif +#else +/* + * Provide dummy defs for kernel data types, functions, and enums + * used in this header file. + */ +#define GFP_KERNEL 0 +#define GFP_ATOMIC 0 +#define kzalloc(size, flags) NULL +#define vmalloc(size) NULL +#define kfree(buf) +#define vfree(buf) +#define pci_alloc_consistent(dev, size, paddr) NULL +#endif /* __KERNEL__ */ + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif /* PAGE_SIZE */ + +static inline void * +__adf_os_mem_alloc(adf_os_device_t osdev, size_t size) +{ + int flags = GFP_KERNEL; + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + + return kzalloc(size, flags); +} + + +static inline void +__adf_os_mem_free(void *buf) +{ + kfree(buf); +} + + +static inline void * +__adf_os_mem_alloc_consistent( + adf_os_device_t osdev, adf_os_size_t size, adf_os_dma_addr_t *paddr, adf_os_dma_context_t memctx) +{ +#if defined(A_SIMOS_DEVHOST) + static int first = 1; + void *vaddr; + + if (first) { + first = 0; + printk("Warning: bypassing %s\n", __func__); + } + vaddr = __adf_os_mem_alloc(osdev, size); + *paddr = ((adf_os_dma_addr_t) vaddr); + return vaddr; +#else + void* alloc_mem = NULL; + alloc_mem = dma_alloc_coherent(osdev->dev, size, paddr, GFP_KERNEL); + if (alloc_mem == NULL) + pr_err("%s Warning: unable to alloc consistent memory of size %zu!\n", + __func__, size); + return alloc_mem; +#endif +} + +static inline void +__adf_os_mem_free_consistent( + adf_os_device_t osdev, + adf_os_size_t size, + void *vaddr, + adf_os_dma_addr_t paddr, + adf_os_dma_context_t memctx) +{ +#if defined(A_SIMOS_DEVHOST) + static int first = 1; + + if (first) { + first = 0; + printk("Warning: bypassing %s\n", __func__); + } + __adf_os_mem_free(vaddr); + return; +#else + dma_free_coherent(osdev->dev, size, vaddr, paddr); +#endif +} + +/* move a memory buffer */ +static inline void +__adf_os_mem_copy(void *dst, const void *src, size_t size) +{ + memcpy(dst, src, size); +} + +/* set a memory buffer */ +static inline void +__adf_os_mem_set(void *buf, uint8_t b, size_t size) +{ + memset(buf, b, size); +} + +/* zero a memory buffer */ +static inline void +__adf_os_mem_zero(void *buf, size_t size) +{ + memset(buf, 0, size); +} + +/* compare two memory buffers */ +static inline int +__adf_os_mem_cmp(const void *buf1, const void *buf2, size_t size) +{ + return memcmp(buf1, buf2, size); +} + +/** + * @brief Unlike memcpy(), memmove() copes with overlapping + * areas. + * @param src + * @param dst + * @param size + */ +static inline void +__adf_os_mem_move(void *dst, const void *src, size_t size) +{ + memmove(dst, src, size); +} + +/** + * @brief Compare two strings + * + * @param[in] str1 First string + * @param[in] str2 Second string + * + * @retval 0 equal + * @retval >0 not equal, if str1 sorts lexicographically after str2 + * @retval <0 not equal, if str1 sorts lexicographically before str2 + */ +static inline a_int32_t +__adf_os_str_cmp(const char *str1, const char *str2) +{ + return strcmp(str1, str2); +} + +/** + * @brief Returns the length of a string + * + * @param[in] str input string + * + * @retval length of string + */ +static inline adf_os_size_t +__adf_os_str_len(const char *str) +{ + return strlen(str); +} + +/** + * @brief Returns the system default page size + * + * @retval system default page size + */ +static inline a_int32_t +__adf_os_mem_get_page_size(void) +{ + return PAGE_SIZE; +} + +#endif /*ADF_OS_MEM_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_module_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_module_pvt.h new file mode 100644 index 000000000000..a1e7595e8700 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_module_pvt.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_MODULE_PVT_H +#define _ADF_CMN_OS_MODULE_PVT_H + +#include +#include +#include +#include + + +#define __adf_os_virt_module_init(_x) \ + static int _x##_mod(void) \ + { \ + a_status_t st; \ + st = (_x)(); \ + if (st != A_STATUS_OK) \ + return -1; \ + else \ + return 0; \ + } \ + module_init(_x##_mod); + +#define __adf_os_virt_module_exit(_x) module_exit(_x) + +#define __adf_os_virt_module_name(_name) MODULE_LICENSE("Dual BSD/GPL"); + +#define __adf_os_module_dep(_name, _dep) + +#define __adf_os_export_symbol(_sym) EXPORT_SYMBOL(_sym) + + + +#define __ADF_OS_PARAM_TYPE_INT8 byte +#define __ADF_OS_PARAM_TYPE_INT16 short +#define __ADF_OS_PARAM_TYPE_INT32 int + + +#define __ADF_OS_PARAM_TYPE_UINT8 byte +#define __ADF_OS_PARAM_TYPE_UINT16 ushort +#define __ADF_OS_PARAM_TYPE_UINT32 uint + +#define __ADF_OS_PARAM_TYPE_STRING charp + +#define __adf_os_declare_param(_name, _type) \ + module_param(_name, _type, 0600) + +#define __adf_os_read_param(_osdev, _name, _type, _pval) + +#endif /*_ADF_CMN_OS_MODULE_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_postpack_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_postpack_pvt.h new file mode 100644 index 000000000000..ce26e170295c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_postpack_pvt.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @brief Linux does not require a postpack # directive. + */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_prepack_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_prepack_pvt.h new file mode 100644 index 000000000000..17e49f860add --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_prepack_pvt.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** + * @brief Linux does not require a prepack # directive. + */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_pseudo_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_pseudo_pvt.h new file mode 100644 index 000000000000..605aa1360d5c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_pseudo_pvt.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef __ADF_HST_OS_PSEUDO_PVT_H +#define __ADF_HST_OS_PSEUDO_PVT_H + +#include + +#define NUM_PSEUDO_DEVS 2 + +#define __adf_os_pseudo_module_init(_fn) \ + static inline int __adf_os_pseudo_mod_init(void) \ + { \ + a_status_t st; \ + int i = 0; \ + st = (_fn)(); \ + for(i = 0; i < NUM_PSEUDO_DEVS; i++) \ + __adf_net_pseudo_attach(mod_name); \ + return st; \ + } \ + module_init(__adf_os_pseudo_mod_init); + +#define __adf_os_pseudo_module_exit(_fn) \ + static inline void __adf_os_pseudo_mod_exit(void) \ + { \ + int i = 0; \ + for(i = 0; i < NUM_PSEUDO_DEVS; i++) \ + __adf_net_pseudo_detach(mod_name); \ + (_fn)(); \ + } \ + module_exit(__adf_os_pseudo_mod_exit); + + +/** + * initiallize the PCI driver structure + * Instance name will be _pci_info + */ +#define __adf_os_pseudo_set_drv_info(_name, _ifname, _pseudo_ids, _attach, _detach, \ + _suspend, _resume) \ +{ \ + .drv_attach = (_attach), \ + .drv_detach = (_detach), \ + .drv_suspend = (_suspend), \ + .drv_resume = (_resume), \ + .pci_id = (_pseudo_ids), \ + .mod_name = #_name, \ + .ifname = #_ifname, \ +}; \ +const char *mod_name = #_name; \ +extern int __adf_net_pseudo_attach(const char *mod_name); \ +extern int __adf_net_pseudo_detach(const char *mod_name); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h new file mode 100644 index 000000000000..d8e07af89614 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_time_pvt.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_TIME_PVT_H +#define _ADF_CMN_OS_TIME_PVT_H + +#include +#include + +typedef unsigned long __adf_time_t; + +static inline __adf_time_t +__adf_os_ticks(void) +{ + return (jiffies); +} +static inline uint32_t +__adf_os_ticks_to_msecs(unsigned long ticks) +{ + return (jiffies_to_msecs(ticks)); +} +static inline __adf_time_t +__adf_os_msecs_to_ticks(a_uint32_t msecs) +{ + return (msecs_to_jiffies(msecs)); +} +static inline __adf_time_t +__adf_os_getuptime(void) +{ + return jiffies; +} + +static inline __adf_time_t +__adf_os_gettimestamp(void) +{ + return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ); +} + +static inline void +__adf_os_udelay(a_uint32_t usecs) +{ +#ifdef CONFIG_ARM + /* + ** This is in support of XScale build. They have a limit on the udelay + ** value, so we have to make sure we don't approach the limit + */ + + a_uint32_t mticks; + a_uint32_t leftover; + int i; + + /* + ** slice into 1024 usec chunks (simplifies calculation) + */ + + mticks = usecs >> 10; + leftover = usecs - (mticks << 10); + + for(i = 0;i < mticks;i++) + { + udelay(1024); + } + + udelay(leftover); + +#else + /* + * Normal Delay functions. Time specified in microseconds. + */ + udelay(usecs); + +#endif +} + +static inline void +__adf_os_mdelay(a_uint32_t msecs) +{ + mdelay(msecs); +} + +/** + * @brief Check if _a is later than _b. + */ +static inline a_bool_t +__adf_os_time_after(__adf_time_t a, __adf_time_t b) +{ + return ((long)(b) - (long)(a) < 0); +} + +/** + * @brief Check if _a is prior to _b. + */ +static inline a_bool_t +__adf_os_time_before(__adf_time_t a, __adf_time_t b) +{ + return __adf_os_time_after(b,a); +} + +/** + * @brief Check if _a atleast as recent as _b, if not later. + */ +static inline a_bool_t +__adf_os_time_after_eq(__adf_time_t a, __adf_time_t b) +{ + return ((long)(a) - (long)(b) >= 0); +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_timer_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_timer_pvt.h new file mode 100644 index 000000000000..b57b1b6573d3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_timer_pvt.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_TIMER_PVT_H +#define _ADF_CMN_OS_TIMER_PVT_H + +#include +#include +#include +#include +#include + +#define ADF_DEFERRABLE_TIMER 0 +#define ADF_NON_DEFERRABLE_TIMER 1 + +/* + * timer data type + */ +typedef struct timer_list __adf_os_timer_t; + +/* + * ugly - but every other OS takes, sanely, a void* + */ + +typedef void (*adf_dummy_timer_func_t)(unsigned long arg); + +/* + * Initialize a timer + */ +static inline a_status_t +__adf_os_timer_init(adf_os_handle_t hdl, + struct timer_list *timer, + adf_os_timer_func_t func, + void *arg, + uint8_t type) +{ + if (ADF_DEFERRABLE_TIMER == type) + init_timer_deferrable(timer); + else + init_timer(timer); + timer->function = (adf_dummy_timer_func_t)func; + timer->data = (unsigned long)arg; + + return A_STATUS_OK; +} + +/* + * start a timer + */ +static inline a_status_t +__adf_os_timer_start(struct timer_list *timer, a_uint32_t delay) +{ + timer->expires = jiffies + msecs_to_jiffies(delay); + add_timer(timer); + + return A_STATUS_OK; +} + +/* + * modify a timer + */ +static inline a_status_t +__adf_os_timer_mod(struct timer_list *timer, a_uint32_t delay) +{ + mod_timer(timer, jiffies + msecs_to_jiffies(delay)); + + return A_STATUS_OK; +} + +/* + * Cancel a timer + * + * Return: TRUE if timer was cancelled and deactived, + * FALSE if timer was cancelled but already got fired. + */ +static inline a_bool_t +__adf_os_timer_cancel(struct timer_list *timer) +{ + if (likely(del_timer(timer))) + return 1; + else + return 0; +} + +/* + * Free a timer + * + * Return: TRUE if timer was cancelled and deactived, + * FALSE if timer was cancelled but already got fired. + */ +static inline void +__adf_os_timer_free(struct timer_list *timer) +{ + del_timer_sync(timer); +} + +/* + * XXX Synchronously canel a timer + * + * Return: TRUE if timer was cancelled and deactived, + * FALSE if timer was cancelled but already got fired. + * + * Synchronization Rules: + * 1. caller must make sure timer function will not use + * adf_os_set_timer to add iteself again. + * 2. caller must not hold any lock that timer function + * is likely to hold as well. + * 3. It can't be called from interrupt context. + */ +static inline a_bool_t +__adf_os_timer_sync_cancel(struct timer_list *timer) +{ + return del_timer_sync(timer); +} + + + +#endif /*_ADF_OS_TIMER_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_trace.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_trace.h new file mode 100644 index 000000000000..4532fdaae638 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_trace.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_TRACE_H +#define _ADF_TRACE_H + +#include + +/* + * Log levels +*/ +#define ADF_DEBUG_FUNCTRACE 0x01 +#define ADF_DEBUG_LEVEL0 0x02 +#define ADF_DEBUG_LEVEL1 0x04 +#define ADF_DEBUG_LEVEL2 0x08 +#define ADf_DEBUG_LEVEL3 0x10 +#define ADF_DEBUG_ERROR 0x20 +#define ADF_DEBUG_CFG 0x40 + +#define adf_trace(log_level, args...) \ + do{ \ + extern int adf_dbg_mask; \ + if(adf_dbg_mask >= log_level) { \ + printk("adf: "args); \ + printk("\n"); \ + } \ + }while(0) + + +#endif //_ADF_TRACE_H diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_types_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_types_pvt.h new file mode 100644 index 000000000000..7904fd47af9e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_types_pvt.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_TYPES_PVT_H +#define _ADF_CMN_OS_TYPES_PVT_H + +#ifndef __KERNEL__ +#define __iomem +#else +#include +#endif + +#include +#include +#include + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#else +/* + * Provide dummy defs for kernel data types, functions, and enums + * used in this header file. + */ + +/* + * Hack - coexist with prior defs of dma_addr_t. + * Eventually all other defs of dma_addr_t should be removed. + * At that point, the "already_defined" wrapper can be removed. + */ +#ifndef __dma_addr_t_already_defined__ +#define __dma_addr_t_already_defined__ +typedef unsigned long dma_addr_t; +#endif + +#define uint64_t u_int64_t +#define uint32_t u_int32_t +#define uint16_t u_int16_t +#define uint8_t u_int8_t +#define SIOCGIWAP 0 +#define IWEVCUSTOM 0 +#define IWEVREGISTERED 0 +#define IWEVEXPIRED 0 +#define SIOCGIWSCAN 0 +#define DMA_TO_DEVICE 0 +#define DMA_FROM_DEVICE 0 +#define __iomem +#endif /* __KERNEL__ */ + +/** + * max sg that we support + */ +#define __ADF_OS_MAX_SCATTER 1 +#define __ADF_OS_NAME_SIZE IFNAMSIZ + +#if defined(__LITTLE_ENDIAN_BITFIELD) +#define ADF_LITTLE_ENDIAN_MACHINE +#elif defined (__BIG_ENDIAN_BITFIELD) +#define ADF_BIG_ENDIAN_MACHINE +#else +#error "Please fix " +#endif + +#define __adf_os_packed __attribute__ ((packed)) + +#define __adf_os_ull(_num) _num ## ULL + +typedef struct completion __adf_os_comp_t; +struct __adf_net_drv; + +typedef int (*__adf_os_intr)(void *); +/** + * Private definitions of general data types + */ +typedef dma_addr_t __adf_os_dma_addr_t; +typedef size_t __adf_os_dma_size_t; +typedef dma_addr_t __adf_os_dma_context_t; + +#define adf_os_dma_mem_context(context) dma_addr_t context +#define adf_os_get_dma_mem_context(var, field) ((adf_os_dma_context_t)(var->field)) + + +typedef enum __adf_os_cache_sync{ + __ADF_SYNC_PREREAD, + __ADF_SYNC_PREWRITE, + __ADF_SYNC_POSTREAD, + __ADF_SYNC_POSTWRITE +}__adf_os_cache_sync_t; + +typedef struct __adf_os_resource{ + unsigned long paddr; + void __iomem * vaddr; + unsigned long len; +}__adf_os_resource_t; + +/** + * generic data types + */ +struct __adf_device { + void *drv; + void *drv_hdl; + char *drv_name; + int irq; + struct device *dev; + __adf_os_resource_t res; + __adf_os_intr func;/*Interrupt handler*/ +#ifdef QCA_ARP_SPOOFING_WAR + void *filter_cb; +#endif +}; + +typedef struct __adf_device *__adf_os_device_t; + +typedef size_t __adf_os_size_t; +typedef off_t __adf_os_off_t; +typedef uint8_t __iomem * __adf_os_iomem_t; + +typedef struct __adf_os_segment{ + dma_addr_t daddr; + uint32_t len; +}__adf_os_segment_t; + +struct __adf_os_dma_map{ + uint32_t mapped; + uint32_t nsegs; + uint32_t coherent; + __adf_os_segment_t seg[__ADF_OS_MAX_SCATTER]; +}; +typedef struct __adf_os_dma_map *__adf_os_dma_map_t; +typedef uint32_t ath_dma_addr_t; +typedef uint8_t __a_uint8_t; +typedef int8_t __a_int8_t; +typedef uint16_t __a_uint16_t; +typedef int16_t __a_int16_t; +typedef uint32_t __a_uint32_t; +typedef int32_t __a_int32_t; +typedef uint64_t __a_uint64_t; +typedef int64_t __a_int64_t; + +enum __adf_net_wireless_evcode{ + __ADF_IEEE80211_ASSOC = SIOCGIWAP, + __ADF_IEEE80211_REASSOC =IWEVCUSTOM, + __ADF_IEEE80211_DISASSOC = SIOCGIWAP, + __ADF_IEEE80211_JOIN = IWEVREGISTERED, + __ADF_IEEE80211_LEAVE = IWEVEXPIRED, + __ADF_IEEE80211_SCAN = SIOCGIWSCAN, + __ADF_IEEE80211_REPLAY = IWEVCUSTOM, + __ADF_IEEE80211_MICHAEL = IWEVCUSTOM, + __ADF_IEEE80211_REJOIN = IWEVCUSTOM, + __ADF_CUSTOM_PUSH_BUTTON = IWEVCUSTOM, +}; + +#define __adf_os_print printk +#define __adf_os_vprint vprintk +#define __adf_os_snprint snprintf +#define __adf_os_vsnprint vsnprintf + +#define __ADF_OS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL +#define __ADF_OS_DMA_TO_DEVICE DMA_TO_DEVICE +#define __ADF_OS_DMA_FROM_DEVICE DMA_FROM_DEVICE +#define __adf_os_inline inline + +#endif /*_ADF_CMN_OS_TYPES_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_util_pvt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_util_pvt.h new file mode 100644 index 000000000000..5584698fe31a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/linux/adf_os_util_pvt.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ADF_CMN_OS_UTIL_PVT_H +#define _ADF_CMN_OS_UTIL_PVT_H + +#include +#include +#include + +#include + +//#include +#include +/* + * Generic compiler-dependent macros if defined by the OS + */ + +#define __adf_os_unlikely(_expr) unlikely(_expr) +#define __adf_os_likely(_expr) likely(_expr) + +/** + * @brief memory barriers. + */ +#define __adf_os_wmb() wmb() +#define __adf_os_rmb() rmb() +#define __adf_os_mb() mb() + +#define __adf_os_min(_a, _b) ((_a) < (_b) ? _a : _b) +#define __adf_os_max(_a, _b) ((_a) > (_b) ? _a : _b) + +#define __adf_os_abs(_a) __builtin_abs(_a) + +/** + * @brief Assert + */ +#define __adf_os_assert(expr) do { \ + if(unlikely(!(expr))) { \ + printk(KERN_ERR "Assertion failed! %s:%s %s:%d\n", \ + #expr, __FUNCTION__, __FILE__, __LINE__); \ + dump_stack(); \ + BUG_ON(1); \ + } \ +}while(0) + +/** + * @brief Warning + */ +#define __adf_os_warn(cond) ({ \ + int __ret_warn = !!(cond); \ + if (unlikely(__ret_warn)) { \ + printk("WARNING: at %s:%d %s()\n", __FILE__, \ + __LINE__, __FUNCTION__); \ + dump_stack(); \ + } \ + unlikely(__ret_warn); \ +}) + +/** + * @brief replace with the name of the function + */ +#define __adf_os_function __FUNCTION__ + +static inline a_status_t +__adf_os_get_rand(adf_os_handle_t hdl, uint8_t *ptr, uint32_t len) +{ + get_random_bytes(ptr, len); + + return A_STATUS_OK; +} + +/** + * @brief return square root + */ +static __adf_os_inline a_uint32_t __adf_os_int_sqrt(a_uint32_t x) +{ + return int_sqrt(x); +} + +/** + * @brief completion structure initialization + */ +static __adf_os_inline void +__adf_os_init_completion(adf_os_comp_t *ptr) +{ + init_completion(ptr); +} + + +/** + * @brief wait for completion till timeout + * + * @Return: 0 if timed out, and positive on completion + */ +static __adf_os_inline unsigned long +__adf_os_wait_for_completion_timeout(adf_os_comp_t *ptr, unsigned long timeout) +{ + return wait_for_completion_timeout(ptr, timeout); +} + +static __adf_os_inline void +__adf_os_complete(adf_os_comp_t *ptr) +{ + complete(ptr); +} +#endif /*_ADF_CMN_OS_UTIL_PVT_H*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ah_osdep.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ah_osdep.h new file mode 100644 index 000000000000..44e3e5c3ee68 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ah_osdep.h @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ATH_AH_OSDEP_H_ + +#define _ATH_AH_OSDEP_H_ + +/* + + * Atheros Hardware Access Layer (HAL) OS Dependent Definitions. + + */ + + + +/* + + * We're releasing binary HAL as a stand-alone module, so we don't + + * need to worry about compatibilities regarding calling convention. + + * By default, Windows uses PASCAL convention. + + */ + +#ifndef __ahdecl + +#define __ahdecl + +#endif + + + +#define __va_list va_list + +#define OS_INLINE __inline + +#ifndef inline + +#define inline __inline + +#endif + +//typedef unsigned int uintptr_t; + +//typedef unsigned long dma_addr_t; + +typedef int bus_space_tag_t; + +typedef char * bus_space_handle_t; + +typedef u_int32_t bus_addr_t; + + + +typedef void* HAL_SOFTC; + +typedef bus_space_handle_t HAL_BUS_HANDLE; + +typedef void* HAL_ADAPTER_HANDLE; + +typedef u_int32_t HAL_BUS_ADDR; /* XXX architecture dependent */ + +typedef bus_space_tag_t HAL_BUS_TAG; + +/* + + * Atomic interface + + */ + +typedef u_int32_t os_atomic_t; + + +/* no-ops */ +#define HAL_USE_INTERSPERSED_READS +#define HAL_NO_INTERSPERSED_READS + +//#define OS_ATOMIC_READ(_patomic_arg) (*(_patomic_arg)) + +//#define OS_ATOMIC_SET(_patomic_arg, v) InterlockedExchange(_patomic_arg, (v)) + +//#define OS_ATOMIC_ADD(v, _patomic_arg) InterlockedExchangeAdd(_patomic_arg, (v)) + +#define OS_ATOMIC_INC(_patomic_arg) ((*_patomic_arg)++) + +#define OS_ATOMIC_DEC(_patomic_arg) ((*_patomic_arg)--) + +//#define OS_ATOMIC_DEC_AND_TEST(_patomic_arg) (NdisInterlockedDecrement(_patomic_arg) == 0) + + + +//#define OS_CMPXCHG(_m, _old, _new) InterlockedCompareExchange(_m, _new, _old) + + + +/* + + * Supported Bus types + + */ + +typedef enum ath_hal_bus_type { + + HAL_BUS_TYPE_PCI, + HAL_BUS_TYPE_AHB, + HAL_BUS_TYPE_SIM, /* simulator */ + HAL_BUS_TYPE_SDIO, +} HAL_BUS_TYPE; + + + + + +/* + + * Bus to hal context handoff + + */ + +typedef struct hal_bus_context { + + HAL_BUS_TAG bc_tag; + + HAL_BUS_HANDLE bc_handle; + + HAL_BUS_TYPE bc_bustype; + +} HAL_BUS_CONTEXT; + + + +#ifndef abs + +#define abs(_a) ( (_a) < 0 ? -(_a) : (_a) ) + +#endif + + + +#define __printflike(_a,_b) \ + __attribute__ ((__format__ (__printf__, _a, _b))) + + + +struct ath_hal; + +struct hal_reg_parm { + + u_int8_t halPciePowerSaveEnable; // Program Serdes; Use ASPM + + u_int8_t halPcieL1SKPEnable; // Enable L1 SKP workaround + + u_int8_t halPcieClockReq; + + u_int32_t halPciePowerReset; + + u_int32_t halPcieWaen; + + u_int32_t halPcieDetach; + + u_int8_t halPcieRestore; + + u_int8_t halPllPwrSave; + + u_int8_t htEnable; // Enable/disable 11n mode + + u_int32_t ofdmTrigLow; + + u_int32_t ofdmTrigHigh; + + u_int32_t cckTrigHigh; + + u_int32_t cckTrigLow; + + u_int32_t enableANI; + + u_int8_t noiseImmunityLvl; + + u_int32_t ofdmWeakSigDet; + + u_int32_t cckWeakSigThr; + + u_int8_t spurImmunityLvl; + + u_int8_t firStepLvl; + + int8_t rssiThrHigh; + + int8_t rssiThrLow; + + u_int16_t diversityControl; // Enable/disable antenna diversity + + u_int16_t antennaSwitchSwap; + + u_int32_t forceBias; + + u_int32_t forceBiasAuto; + + int calInFlash; + +#ifdef ATH_SUPPORT_TxBF + + u_int8_t CVTimeOut; + + u_int16_t TxBFCtl; + +#endif + +}; + + + +/* + + * Byte order/swapping support. + + */ + +#define AH_LITTLE_ENDIAN 1234 + +#define AH_BIG_ENDIAN 4321 + + + +#ifdef MIPS32 + +#define AH_BYTE_ORDER AH_BIG_ENDIAN + +#endif + + + +#if AH_BYTE_ORDER == AH_BIG_ENDIAN + +/* + + * This could be optimized but since we only use it for + + * a few registers there's little reason to do so. + + */ + +static OS_INLINE u_int32_t + +__bswap32(u_int32_t _x) + +{ + + return ((u_int32_t)( + + (((const u_int8_t *)(&_x))[0] ) | + + (((const u_int8_t *)(&_x))[1]<< 8) | + + (((const u_int8_t *)(&_x))[2]<<16) | + + (((const u_int8_t *)(&_x))[3]<<24)) + + ); + +} + + + +#ifndef __BIG_ENDIAN__ + +#define __BIG_ENDIAN__ + +#endif + + + +#else + +#define __bswap32(_x) (_x) + +#endif + + + +/* + + * Register read/write; we assume the registers will always + + * be memory-mapped. Note that register accesses are done + + * using target-specific functions when debugging is enabled + + * (AH_DEBUG) or we are explicitly configured this way. The + + * latter is used on some platforms where the full i/o space + + * cannot be directly mapped. + + * + + * The hardware registers are native little-endian byte order. + + * Big-endian hosts are handled by enabling hardware byte-swap + + * of register reads and writes at reset. But the PCI clock + + * domain registers are not byte swapped! Thus, on big-endian + + * platforms we have to byte-swap thoese registers specifically. + + * Most of this code is collapsed at compile time because the + + * register values are constants. + + */ + + + +#if AH_BYTE_ORDER == AH_BIG_ENDIAN + + + +#define _OS_REG_WRITE(_ah, _reg, _val) \ + *((volatile u_int32_t *)(AH_PRIVATE(_ah)->ah_sh + (_reg))) = (_val) + +#define _OS_REG_READ(_ah, _reg) \ + *((volatile u_int32_t *)(AH_PRIVATE(_ah)->ah_sh + (_reg))) + + + +#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +#define __bswap32(_x) (_x) + +#define _OS_REG_WRITE(_ah, _reg, _val) \ + bus_space_write_4(AH_PRIVATE(_ah)->ah_st, AH_PRIVATE(_ah)->ah_sh, (_reg), (_val)) + +#define _OS_REG_READ(_ah, _reg) \ + ((u_int32_t) bus_space_read_4(AH_PRIVATE(_ah)->ah_st, AH_PRIVATE(_ah)->ah_sh, (_reg))) + +#endif /* _BYTE_ORDER */ + + +#ifndef ATH_SUPPORT_HTC + +/* no-op for non-USB solutions */ +#define ENABLE_REG_WRITE_BUFFER +#define DISABLE_REG_WRITE_BUFFER +#define OS_REG_WRITE_FLUSH(_ah) +#define HTC_SET_PS_STATE(_ah, _mode) + +#else /* ATH_SUPPORT_HTC */ + +#define ENABLE_REG_WRITE_BUFFER \ + if (!AH_PRIVATE(ah)->ah_reg_write_buffer_flag) \ + AH_PRIVATE(ah)->ah_reg_write_buffer_flag = 1; \ + else \ + HDPRINTF(ah, HAL_DBG_REG_IO, "%s: Error:REG_WRITE_BUFFER " \ + "had not been correctly disabled!\n", __func__); + +#define DISABLE_REG_WRITE_BUFFER \ + if (AH_PRIVATE(ah)->ah_reg_write_buffer_flag) \ + AH_PRIVATE(ah)->ah_reg_write_buffer_flag = 0; \ + else \ + HDPRINTF(ah, HAL_DBG_REG_IO, "%s: Error:REG_WRITE_BUFFER " \ + "had not been correctly disabled!\n", _func__); + +#define OS_REG_WRITE_FLUSH(_ah) \ + if (AH_PRIVATE(_ah)->ah_reg_write_buffer_flag) { \ + _OS_REG_WRITE_FLUSH(_ah); \ + } else \ + HDPRINTF(ah, HAL_DBG_REG_IO, "%s: Error:REG_WRITE_BUFFER " \ + "must be enabled!\n", _func__); + +extern void ath_hal_wmi_ps_set_state(struct ath_hal *ah, u_int16_t mode); + +#define HTC_SET_PS_STATE(_ah, _mode) \ + ath_hal_wmi_ps_set_state(_ah, _mode); + +#endif /* ATH_SUPPORT_HTC */ + + +#if defined(AH_DEBUG) || defined(AH_REGOPS_FUNC) || defined(AH_DEBUG_ALQ) + +#define OS_REG_WRITE(_ah, _reg, _val) ath_hal_reg_write(_ah, _reg, _val) +#define OS_REG_READ(_ah, _reg) ath_hal_reg_read(_ah, _reg) + +u_int32_t __ahdecl ath_hal_reg_read(struct ath_hal *, u_int32_t); +void __ahdecl ath_hal_reg_write(struct ath_hal *, u_int32_t, u_int32_t); + +#else + +#define OS_REG_WRITE(_ah, _reg, _val) _OS_REG_WRITE(_ah, _reg, _val) +#define OS_REG_READ(_ah, _reg) _OS_REG_READ(_ah, _reg) + +#endif /* AH_DEBUG || AH_REGFUNC || AH_DEBUG_ALQ */ + + +#ifdef AH_DEBUG_ALQ +extern void __ahdecl OS_MARK(struct ath_hal *, u_int id, u_int32_t value); +#else +#define OS_MARK(_ah, _id, _v) +#endif + + +/* + * Linux-specific attach/detach methods needed for module reference counting. + * + * XXX We can't use HAL_STATUS because the type isn't defined at this + * point (circular dependency); we wack the type and patch things + * up in the function. + * + * NB: These are intentionally not marked __ahdecl since they are + * compiled with the default calling convetion and are not called + * from within the HAL. + */ + +typedef u_int32_t (*HAL_BUS_CONFIG_READER)(HAL_SOFTC sc, u_int32_t offset, void *pBuffer, u_int32_t length); + +struct ath_hal_callback { + /* Callback Functions */ + HAL_BUS_CONFIG_READER read_pci_config_space; +}; + + +/* + * osdev_t specific flags. + */ +#define ATH_ATTACHED 0x0001 /* attach has succeeded */ +#define ATH_ENABLED 0x0002 /* chip is enabled */ +#define ATH_RXREFILL 0x0004 /* Refill the recv bufs */ + +#define ATH_IS_ENABLED(osdev) ((osdev)->sc_flags & ATH_ENABLED) + +#ifdef AR9100 +extern void ath_hal_ahb_mac_reset(void); +extern void ath_hal_get_chip_revisionid(u_int32_t *); +#endif + +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#endif /* _ATH_AH_OSDEP_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/apb_athr_wlan_map.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/apb_athr_wlan_map.h new file mode 100644 index 000000000000..f88171fcb32d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/apb_athr_wlan_map.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _APB_ATHR_WLAN_MAP_H_ +#define _APB_ATHR_WLAN_MAP_H_ + +#define RTC_SOC_BASE_ADDRESS 0x00004000 +#define RTC_WMAC_BASE_ADDRESS 0x00005000 +#define MAC_COEX_BASE_ADDRESS 0x00006000 +#define BT_COEX_BASE_ADDRESS 0x00007000 +#define SOC_PCIE_BASE_ADDRESS 0x00008000 +#define SOC_CORE_BASE_ADDRESS 0x00009000 +#define WLAN_UART_BASE_ADDRESS 0x0000c000 +#define WLAN_SI_BASE_ADDRESS 0x00010000 +#define WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 +#define WLAN_MAC_BASE_ADDRESS 0x00020000 +#define EFUSE_BASE_ADDRESS 0x00030000 +#define FPGA_REG_BASE_ADDRESS 0x00039000 +#define WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define CE_WRAPPER_BASE_ADDRESS 0x00057000 +#define CE0_BASE_ADDRESS 0x00057400 +#define CE1_BASE_ADDRESS 0x00057800 +#define CE2_BASE_ADDRESS 0x00057c00 +#define CE3_BASE_ADDRESS 0x00058000 +#define CE4_BASE_ADDRESS 0x00058400 +#define CE5_BASE_ADDRESS 0x00058800 +#define CE6_BASE_ADDRESS 0x00058c00 +#define CE7_BASE_ADDRESS 0x00059000 +#define DBI_BASE_ADDRESS 0x00060000 +#define WLAN_MBOX_BASE_ADDRESS 0x00068000 +#define WLAN_DBG_UART_BASE_ADDRESS 0x00069000 +#define USB_DMA_BASE_ADDRESS 0x0006a000 + +#endif /* _APB_ATHR_WLAN_MAP_REG_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athdefs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athdefs.h new file mode 100644 index 000000000000..11ce362e3f85 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athdefs.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef __ATHDEFS_H__ +#define __ATHDEFS_H__ + +/* + * This file contains definitions that may be used across both + * Host and Target software. Nothing here is module-dependent + * or platform-dependent. + */ + +/* + * Generic error codes that can be used by hw, sta, ap, sim, dk + * and any other environments. Since these are enums, feel free to + * add any more codes that you need. + */ + +typedef enum { + A_ERROR = -1, /* Generic error return */ + A_OK = 0, /* success */ + /* Following values start at 1 */ + A_DEVICE_NOT_FOUND, /* not able to find PCI device */ + A_NO_MEMORY, /* not able to allocate memory, not available */ + A_MEMORY_NOT_AVAIL, /* memory region is not free for mapping */ + A_NO_FREE_DESC, /* no free descriptors available */ + A_BAD_ADDRESS, /* address does not match descriptor */ + A_WIN_DRIVER_ERROR, /* used in NT_HW version, if problem at init */ + A_REGS_NOT_MAPPED, /* registers not correctly mapped */ + A_EPERM, /* Not superuser */ + A_EACCES, /* Access denied */ + A_ENOENT, /* No such entry, search failed, etc. */ + A_EEXIST, /* The object already exists (can't create) */ + A_EFAULT, /* Bad address fault */ + A_EBUSY, /* Object is busy */ + A_EINVAL, /* Invalid parameter */ + A_EMSGSIZE, /* Inappropriate message buffer length */ + A_ECANCELED, /* Operation canceled */ + A_ENOTSUP, /* Operation not supported */ + A_ECOMM, /* Communication error on send */ + A_EPROTO, /* Protocol error */ + A_ENODEV, /* No such device */ + A_EDEVNOTUP, /* device is not UP */ + A_NO_RESOURCE, /* No resources for requested operation */ + A_HARDWARE, /* Hardware failure */ + A_PENDING, /* Asynchronous routine; will send up results la +ter (typically in callback) */ + A_EBADCHANNEL, /* The channel cannot be used */ + A_DECRYPT_ERROR, /* Decryption error */ + A_PHY_ERROR, /* RX PHY error */ + A_CONSUMED, /* Object was consumed */ + A_CLONE, /* The buffer is cloned */ + A_USB_ERROR, /* Rome USB Target error */ +} A_STATUS; + +#define A_SUCCESS(x) (x == A_OK) +#define A_FAILED(x) (!A_SUCCESS(x)) + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif /* __ATHDEFS_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athendpack.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athendpack.h new file mode 100644 index 000000000000..cff17850abee --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athendpack.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef VXWORKS +#endif /* VXWORKS */ + +#if defined(LINUX) || defined(__linux__) +#endif /* LINUX */ + +#ifdef QNX +#endif /* QNX */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athstartpack.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athstartpack.h new file mode 100644 index 000000000000..1a8db88c6d7f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/athstartpack.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// start compiler-specific structure packing +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _ATHSTARTPACK_H +#define _ATHSTARTPACK_H + +#if defined(LINUX) || defined(__linux__) +#include "osapi_linux.h" +#endif /* LINUX */ + +#ifdef QNX +#endif /* QNX */ + +#if __LONG_MAX__ == __INT_MAX__ +/* 32-bit compilation */ +#define PREPACK64 +#define POSTPACK64 +#else +/* 64-bit compilation */ +#define PREPACK64 PREPACK +#define POSTPACK64 POSTPACK +#endif + +#endif /* _ATHSTARTPACK_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi.h new file mode 100644 index 000000000000..b04ec16e9690 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//============================================================================== +// BMI declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _BMI_H_ +#define _BMI_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "athdefs.h" +#include "a_types.h" +#include "hif.h" +#include "osapi_linux.h" +#include "bmi_msg.h" +#include "ol_if_athvar.h" + +A_STATUS bmi_download_firmware(struct ol_softc *scn); +void bmi_target_ready(struct ol_softc *scn, void *cfg_ctx); +void +BMICleanup(struct ol_softc *scn); + +A_STATUS +bmi_done(struct ol_softc *scn); + +A_STATUS +BMIReadMemory(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn); + +A_STATUS +BMIWriteMemory(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn); + +A_STATUS +BMIExecute(HIF_DEVICE *device, + A_UINT32 address, + A_UINT32 *param, + struct ol_softc *scn); + +A_STATUS +BMISetAppStart(HIF_DEVICE *device, + A_UINT32 address, + struct ol_softc *scn); + +A_STATUS +BMIReadSOCRegister(HIF_DEVICE *device, + A_UINT32 address, + A_UINT32 *param, + struct ol_softc *scn); + +A_STATUS +BMIWriteSOCRegister(HIF_DEVICE *device, + A_UINT32 address, + A_UINT32 param, + struct ol_softc *scn); + +A_STATUS +BMIrompatchInstall(HIF_DEVICE *device, + A_UINT32 ROM_addr, + A_UINT32 RAM_addr, + A_UINT32 nbytes, + A_UINT32 do_activate, + A_UINT32 *patch_id, + struct ol_softc *scn); + +A_STATUS +BMIrompatchUninstall(HIF_DEVICE *device, + A_UINT32 rompatch_id, + struct ol_softc *scn); + +A_STATUS +BMIrompatchActivate(HIF_DEVICE *device, + A_UINT32 rompatch_count, + A_UINT32 *rompatch_list, + struct ol_softc *scn); + +A_STATUS +BMIrompatchDeactivate(HIF_DEVICE *device, + A_UINT32 rompatch_count, + A_UINT32 *rompatch_list, + struct ol_softc *scn); + +A_STATUS +BMISignStreamStart(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn); + +A_STATUS +BMILZStreamStart(HIF_DEVICE *device, + A_UINT32 address, + struct ol_softc *scn); + +A_STATUS +BMILZData(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn); + +A_STATUS +BMIFastDownload(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + struct ol_softc *scn); + +A_STATUS +BMInvramProcess(HIF_DEVICE *device, + A_UCHAR *seg_name, + A_UINT32 *retval, + struct ol_softc *scn); + +A_STATUS +BMIRawWrite(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length); + +A_STATUS +BMIRawRead(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length, + A_BOOL want_timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* _BMI_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi_msg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi_msg.h new file mode 100644 index 000000000000..bff2ed63d076 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/bmi_msg.h @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2012 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __BMI_MSG_H__ +#define __BMI_MSG_H__ + +#ifndef ATH_TARGET +#include "athstartpack.h" +#endif + +/* + * Bootloader Messaging Interface (BMI) + * + * BMI is a very simple messaging interface used during initialization + * to read memory, write memory, execute code, and to define an + * application entry PC. + * + * It is used to download an application to AR6K, to provide + * patches to code that is already resident on AR6K, and generally + * to examine and modify state. The Host has an opportunity to use + * BMI only once during bootup. Once the Host issues a BMI_DONE + * command, this opportunity ends. + * + * The Host writes BMI requests to mailbox0, and reads BMI responses + * from mailbox0. BMI requests all begin with a command + * (see below for specific commands), and are followed by + * command-specific data. + * + * Flow control: + * The Host can only issue a command once the Target gives it a + * "BMI Command Credit", using AR6K Counter #4. As soon as the + * Target has completed a command, it issues another BMI Command + * Credit (so the Host can issue the next command). + * + * BMI handles all required Target-side cache flushing. + */ + + +/* Maximum data size used for BMI transfers */ +#define BMI_DATASZ_MAX 256 + +/* BMI Commands */ + +#define BMI_NO_COMMAND 0 + +#define BMI_DONE 1 + /* + * Semantics: Host is done using BMI + * Request format: + * A_UINT32 command (BMI_DONE) + * Response format: none + */ + +#define BMI_READ_MEMORY 2 + /* + * Semantics: Host reads AR6K memory + * Request format: + * A_UINT32 command (BMI_READ_MEMORY) + * A_UINT32 address + * A_UINT32 length, at most BMI_DATASZ_MAX + * Response format: + * A_UINT8 data[length] + */ + +#define BMI_WRITE_MEMORY 3 + /* + * Semantics: Host writes AR6K memory + * Request format: + * A_UINT32 command (BMI_WRITE_MEMORY) + * A_UINT32 address + * A_UINT32 length, at most BMI_DATASZ_MAX + * A_UINT8 data[length] + * Response format: none + */ +/* + * Capbility to write "segmented files" is provided for two reasons + * 1) backwards compatibility for certain situations where Hosts + * have limited flexibility + * 2) because it's darn convenient. + * + * A segmented file consists of a file header followed by an arbitrary number + * of segments. Each segment contains segment metadata -- a Target address and + * a length -- followed by "length" bytes of data. A segmented file ends with + * a segment that specifies length=BMI_SGMTFILE_DONE. When a segmented file + * is sent to the Target, firmware writes each segment to the specified address. + * + * Special cases: + * 1) If a segment's metadata indicates length=BMI_SGMTFILE_EXEC, then the + * specified address is used as a function entry point for a brief function + * with prototype "(void *)(void)". That function is called immediately. + * After execution of the function completes, firmware continues with the + * next segment. No data is expected when length=BMI_SGMTFILE_EXEC. + * + * 2) If a segment's metadata indicates length=BMI_SGMTFILE_BEGINADDR, then + * the specified address is established as the application start address + * so that a subsequent BMI_DONE jumps there. + * + * 3) If a segment's metadata indicates length=BMI_SGMTFILE_BDDATA, then + * the specified address is used as the (possibly compressed) length of board + * data, which is loaded into the proper Target address as specified by + * hi_board_data. In addition, the hi_board_data_initialized flag is set. + * + * A segmented file is sent to the Target using a sequence of 1 or more + * BMI_WRITE_MEMORY commands. The first such command must have + * address=BMI_SEGMENTED_WRITE_ADDR. Subsequent BMI_WRITE_MEMORY commands + * can use an arbitrary address. In each BMI_WRITE_MEMORY command, the + * length specifies the number of data bytes transmitted (except for the + * special cases listed above). + * + * Alternatively, a segmented file may be sent to the Target using a + * BMI_LZ_STREAM_START command with address=BMI_SEGMENTED_WRITE_ADDR + * followed by a series of BMI_LZ_DATA commands that each send the next portion + * of the segmented file. + * + * The data segments may be lz77 compressed. In this case, the segmented file + * header flag, BMI_SGMTFILE_FLAG_COMPRESS, must be set. Note that segmented + * file METAdata is never compressed; only the data segments themselves are + * compressed. There is no way to mix compressed and uncompressed data segments + * in a single segmented file. Compressed (or uncompressed) segments are handled + * by both BMI_WRITE_MEMORY and by BMI_LZ_DATA commands. (Compression is an + * attribute of the segmented file rather than of the command used to transmit + * it.) + */ +#define BMI_SEGMENTED_WRITE_ADDR 0x1234 + +/* File header for a segmented file */ +struct bmi_segmented_file_header { + A_UINT32 magic_num; + A_UINT32 file_flags; +}; +#define BMI_SGMTFILE_MAGIC_NUM 0x544d4753 /* "SGMT" */ +#define BMI_SGMTFILE_FLAG_COMPRESS 1 + +/* Metadata for a segmented file segment */ +struct bmi_segmented_metadata { + A_UINT32 addr; + A_UINT32 length; +}; +/* Special values for bmi_segmented_metadata.length (all have high bit set) */ +#define BMI_SGMTFILE_DONE 0xffffffff /* end of segmented data */ +#define BMI_SGMTFILE_BDDATA 0xfffffffe /* Board Data segment */ +#define BMI_SGMTFILE_BEGINADDR 0xfffffffd /* set beginning address */ +#define BMI_SGMTFILE_EXEC 0xfffffffc /* immediate function execution */ + +#define BMI_EXECUTE 4 + /* + * Semantics: Causes AR6K to execute code + * Request format: + * A_UINT32 command (BMI_EXECUTE) + * A_UINT32 address + * A_UINT32 parameter + * Response format: + * A_UINT32 return value + */ +/* + * Note: In order to support the segmented file feature + * (see BMI_WRITE_MEMORY), when the address specified in a + * BMI_EXECUTE command matches (same physical address) + * BMI_SEGMENTED_WRITE_ADDR, it is ignored. Instead, execution + * begins at the address specified by hi_app_start. + */ + +#define BMI_SET_APP_START 5 + /* + * Semantics: Set Target application starting address + * Request format: + * A_UINT32 command (BMI_SET_APP_START) + * A_UINT32 address + * Response format: none + */ + +#define BMI_READ_SOC_REGISTER 6 +#define BMI_READ_SOC_WORD 6 + /* + * Semantics: Read a 32-bit Target SOC word. + * Request format: + * A_UINT32 command (BMI_READ_REGISTER) + * A_UINT32 address + * Response format: + * A_UINT32 value + */ + +#define BMI_WRITE_SOC_REGISTER 7 +#define BMI_WRITE_SOC_WORD 7 + /* + * Semantics: Write a 32-bit Target SOC word. + * Request format: + * A_UINT32 command (BMI_WRITE_REGISTER) + * A_UINT32 address + * A_UINT32 value + * + * Response format: none + */ + +#define BMI_GET_TARGET_ID 8 +#define BMI_GET_TARGET_INFO 8 + /* + * Semantics: Fetch the 4-byte Target information + * Request format: + * A_UINT32 command (BMI_GET_TARGET_ID/INFO) + * + * Response format1 (old firmware): + * A_UINT32 TargetVersionID + * + * Response format2 (intermediate firmware, during transition): + * A_UINT32 TARGET_VERSION_SENTINAL + * struct bmi_target_info; + * + * Response format3 (newest firmware) + * struct bmi_target_info; + */ + +PREPACK struct bmi_target_info { + A_UINT32 target_info_byte_count; /* size of this structure */ + A_UINT32 target_ver; /* Target Version ID */ + A_UINT32 target_type; /* Target type */ +} POSTPACK; +#define TARGET_VERSION_SENTINAL 0xffffffff +#define TARGET_TYPE_UNKNOWN 0 +#define TARGET_TYPE_AR6001 1 +#define TARGET_TYPE_AR6002 2 +#define TARGET_TYPE_AR6003 3 +#define TARGET_TYPE_AR6004 5 +#define TARGET_TYPE_AR6006 6 +#define TARGET_TYPE_AR9888 7 +#define TARGET_TYPE_AR6320 8 +#define TARGET_TYPE_AR900B 9 +/* For attach Peregrine 2.0 board target_reg_tbl only */ +#define TARGET_TYPE_AR9888V2 10 +/* For attach Rome1.0 target_reg_tbl only*/ +#define TARGET_TYPE_AR6320V1 11 +/* For Rome2.0/2.1 target_reg_tbl ID*/ +#define TARGET_TYPE_AR6320V2 12 +/* For Rome3.0 target_reg_tbl ID*/ +#define TARGET_TYPE_AR6320V3 13 +/* For Tufello1.0 target_reg_tbl ID*/ +#define TARGET_TYPE_QCA9377V1 14 + +#define BMI_ROMPATCH_INSTALL 9 + /* + * Semantics: Install a ROM Patch. + * Request format: + * A_UINT32 command (BMI_ROMPATCH_INSTALL) + * A_UINT32 Target ROM Address + * A_UINT32 Target RAM Address or Value (depending on Target Type) + * A_UINT32 Size, in bytes + * A_UINT32 Activate? 1-->activate; + * 0-->install but do not activate + * Response format: + * A_UINT32 PatchID + */ + +#define BMI_ROMPATCH_UNINSTALL 10 + /* + * Semantics: Uninstall a previously-installed ROM Patch, + * automatically deactivating, if necessary. + * Request format: + * A_UINT32 command (BMI_ROMPATCH_UNINSTALL) + * A_UINT32 PatchID + * + * Response format: none + */ + +#define BMI_ROMPATCH_ACTIVATE 11 + /* + * Semantics: Activate a list of previously-installed ROM Patches. + * Request format: + * A_UINT32 command (BMI_ROMPATCH_ACTIVATE) + * A_UINT32 rompatch_count + * A_UINT32 PatchID[rompatch_count] + * + * Response format: none + */ + +#define BMI_ROMPATCH_DEACTIVATE 12 + /* + * Semantics: Deactivate a list of active ROM Patches. + * Request format: + * A_UINT32 command (BMI_ROMPATCH_DEACTIVATE) + * A_UINT32 rompatch_count + * A_UINT32 PatchID[rompatch_count] + * + * Response format: none + */ + + +#define BMI_LZ_STREAM_START 13 + /* + * Semantics: Begin an LZ-compressed stream of input + * which is to be uncompressed by the Target to an + * output buffer at address. The output buffer must + * be sufficiently large to hold the uncompressed + * output from the compressed input stream. This BMI + * command should be followed by a series of 1 or more + * BMI_LZ_DATA commands. + * A_UINT32 command (BMI_LZ_STREAM_START) + * A_UINT32 address + * Note: Not supported on all versions of ROM firmware. + */ + +#define BMI_LZ_DATA 14 + /* + * Semantics: Host writes AR6K memory with LZ-compressed + * data which is uncompressed by the Target. This command + * must be preceded by a BMI_LZ_STREAM_START command. A series + * of BMI_LZ_DATA commands are considered part of a single + * input stream until another BMI_LZ_STREAM_START is issued. + * Request format: + * A_UINT32 command (BMI_LZ_DATA) + * A_UINT32 length (of compressed data), + * at most BMI_DATASZ_MAX + * A_UINT8 CompressedData[length] + * Response format: none + * Note: Not supported on all versions of ROM firmware. + */ + +#define BMI_NVRAM_PROCESS 15 +#define BMI_NVRAM_SEG_NAME_SZ 16 + /* + * Semantics: Cause Target to search NVRAM (if any) for a + * segment with the specified name and process it according + * to NVRAM metadata. + * Request format: + * A_UINT32 command (BMI_NVRAM_PROCESS) + * A_UCHAR name[BMI_NVRAM_SEG_NAME_SZ] name (LE format) + * Response format: + * A_UINT32 0, if nothing was executed; + * otherwise the value returned from the + * last NVRAM segment that was executed + */ + +#define BMI_SIGN_STREAM_START 17 + /* + * Semantics: Trigger target start/end binary signature verification + * flow. + * Request format: + * A_UINT32 command (BMI_SIGN_STREAM_START) + * A_UINT32 address + * A_UINT32 length, at most BMI_DATASZ_MAX + * A_UINT8 data[length] + * Response format: none + */ + +#ifndef ATH_TARGET +#include "athendpack.h" +#endif + +/* TBDXXX: Need a better place for these */ +#define BMI_CE_NUM_TO_TARG 0 +#define BMI_CE_NUM_TO_HOST 1 + +#endif /* __BMI_MSG_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog.h new file mode 100644 index 000000000000..9874ac8998b2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2012, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DBGLOG_H_ +#define _DBGLOG_H_ + +#ifndef ATH_TARGET +#include "athstartpack.h" +#endif + +#include "wlan_module_ids.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define DBGLOG_TIMESTAMP_OFFSET 0 +#define DBGLOG_TIMESTAMP_MASK 0xFFFFFFFF /* Bit 0-15. Contains bit + 8-23 of the LF0 timer */ +#define DBGLOG_DBGID_OFFSET 0 +#define DBGLOG_DBGID_MASK 0x000003FF /* Bit 0-9 */ +#define DBGLOG_DBGID_NUM_MAX 256 /* Upper limit is width of mask */ + +#define DBGLOG_MODULEID_OFFSET 10 +#define DBGLOG_MODULEID_MASK 0x0003FC00 /* Bit 10-17 */ +#define DBGLOG_MODULEID_NUM_MAX 32 /* Upper limit is width of mask */ + +#define DBGLOG_VDEVID_OFFSET 18 +#define DBGLOG_VDEVID_MASK 0x03FC0000 /* Bit 20-25*/ +#define DBGLOG_VDEVID_NUM_MAX 16 + +#define DBGLOG_NUM_ARGS_OFFSET 26 +#define DBGLOG_NUM_ARGS_MASK 0xFC000000 /* Bit 26-31 */ +#define DBGLOG_NUM_ARGS_MAX 9 /* it is bcoz of limitation + of corebsp MSG*() to accept max 9 arg */ + +#define DBGLOG_LOG_BUFFER_SIZE 1500 +#define DBGLOG_DBGID_DEFINITION_LEN_MAX 90 + +#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE + +#define DBGLOG_GET_DBGID(arg) \ + ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET) + +#define DBGLOG_GET_MODULEID(arg) \ + ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET) + +#define DBGLOG_GET_VDEVID(arg) \ + ((arg & DBGLOG_VDEVID_MASK) >> DBGLOG_VDEVID_OFFSET) + +#define DBGLOG_GET_NUMARGS(arg) \ + ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET) + +#define DBGLOG_GET_TIME_STAMP(arg) \ + ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET) + + +#define DIAG_FWID_OFFSET 24 +#define DIAG_FWID_MASK 0xFF000000 /* Bit 24-31 */ + +#define DIAG_TIMESTAMP_OFFSET 0 +#define DIAG_TIMESTAMP_MASK 0x00FFFFFF /* Bit 0-23 */ + +#define DIAG_ID_OFFSET 16 +#define DIAG_ID_MASK 0xFFFF0000 /* Bit 16-31 */ + +#define DIAG_VDEVID_OFFSET 11 +#define DIAG_VDEVID_MASK 0x0000F800 /* Bit 11-15 */ +#define DIAG_VDEVID_NUM_MAX 16 + +#define DIAG_VDEVLEVEL_OFFSET 8 +#define DIAG_VDEVLEVEL_MASK 0x00000700 /* Bit 8-10 */ + +#define DIAG_PAYLEN_OFFSET 0 +#define DIAG_PAYLEN_MASK 0x000000FF /* Bit 0-7 */ + +#define DIAG_PAYLEN_OFFSET16 0 +#define DIAG_PAYLEN_MASK16 0x0000FFFF /* Bit 0-16 */ + +#define DIAG_GET_TYPE(arg) \ + ((arg & DIAG_FWID_MASK) >> DIAG_FWID_OFFSET) + +#define DIAG_GET_TIME_STAMP(arg) \ + ((arg & DIAG_TIMESTAMP_MASK) >> DIAG_TIMESTAMP_OFFSET) + +#define DIAG_GET_ID(arg) \ + ((arg & DIAG_ID_MASK) >> DIAG_ID_OFFSET) + +#define DIAG_GET_VDEVID(arg) \ + ((arg & DIAG_VDEVID_MASK) >> DIAG_VDEVID_OFFSET) + +#define DIAG_GET_VDEVLEVEL(arg) \ + ((arg & DIAG_VDEVLEVEL_MASK) >> DIAG_VDEVLEVEL_OFFSET) + +#define DIAG_GET_PAYLEN(arg) \ + ((arg & DIAG_PAYLEN_MASK) >> DIAG_PAYLEN_OFFSET) + +#define DIAG_GET_PAYLEN16(arg) \ + ((arg & DIAG_PAYLEN_MASK16) >> DIAG_PAYLEN_OFFSET16) + +/* Debug Log levels*/ + +typedef enum { + DBGLOG_VERBOSE = 0, + DBGLOG_INFO, + DBGLOG_INFO_LVL_1, + DBGLOG_INFO_LVL_2, + DBGLOG_WARN, + DBGLOG_ERR, + DBGLOG_LVL_MAX +}DBGLOG_LOG_LVL; + +PREPACK struct dbglog_buf_s { + struct dbglog_buf_s *next; + A_UINT8 *buffer; + A_UINT32 bufsize; + A_UINT32 length; + A_UINT32 count; + A_UINT32 free; +} POSTPACK; + +PREPACK struct dbglog_hdr_s { + struct dbglog_buf_s *dbuf; + A_UINT32 dropped; +} POSTPACK; + +PREPACK struct dbglog_buf_host { + A_UINT32 next; + A_UINT32 buffer; + A_UINT32 bufsize; + A_UINT32 length; + A_UINT32 count; + A_UINT32 free; +} POSTPACK; + +PREPACK struct dbglog_hdr_host { + A_UINT32 dbuf; + A_UINT32 dropped; +} POSTPACK; + +#define DBGLOG_MAX_VDEVID 15 /* 0-15 */ + +#ifdef __cplusplus +} +#endif + + +#endif /* _DBGLOG_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_host.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_host.h new file mode 100644 index 000000000000..ee5e02581f84 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_host.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _DBGLOG_HOST_H_ +#define _DBGLOG_HOST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog_id.h" +#include "dbglog.h" +#include "ol_defines.h" + +#define MAX_DBG_MSGS 256 + +#define CLD_NETLINK_USER 17 + +#define LOGFILE_FLAG 0x01 +#define CONSOLE_FLAG 0x02 +#define QXDM_FLAG 0x04 +#define SILENT_FLAG 0x08 +#define DEBUG_FLAG 0x10 + +#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 + +#define HDRLEN 16 +#define RECLEN (HDRLEN + ATH6KL_FWLOG_PAYLOAD_SIZE) + +#define DBGLOG_PRINT_PREFIX "FWLOG: " + +/* Handy Macros to read data length and type from FW */ +#define WLAN_DIAG_0_TYPE_S 0 +#define WLAN_DIAG_0_TYPE 0x000000ff +#define WLAN_DIAG_0_TYPE_GET(x) WMI_F_MS(x, WLAN_DIAG_0_TYPE) +#define WLAN_DIAG_0_TYPE_SET(x, y) WMI_F_RMW(x, y, WLAN_DIAG_0_TYPE) +/* bits 8-15 reserved */ + +/* length includes the size of wlan_diag_data */ +#define WLAN_DIAG_0_LEN_S 16 +#define WLAN_DIAG_0_LEN 0xffff0000 +#define WLAN_DIAG_0_LEN_GET(x) WMI_F_MS(x, WLAN_DIAG_0_LEN) +#define WLAN_DIAG_0_LEN_SET(x, y) WMI_F_RMW(x, y, WLAN_DIAG_0_LEN) + +#define CNSS_DIAG_SLEEP_INTERVAL 5 /* In secs */ + +#define SIZEOF_NL_MSG_LOAD 28 /* sizeof nlmsg and load length */ +#define SIZEOF_NL_MSG_UNLOAD 28 /* sizeof nlmsg and Unload length */ +#define SIZEOF_NL_MSG_DBG_MSG 1532 +#define ATH6KL_FWLOG_MAX_ENTRIES 20 +#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 + +#define DIAG_WLAN_DRIVER_UNLOADED 6 +#define DIAG_WLAN_DRIVER_LOADED 7 +#define DIAG_TYPE_LOGS 1 +#define DIAG_TYPE_EVENTS 2 + + +typedef enum { + DBGLOG_PROCESS_DEFAULT = 0, + DBGLOG_PROCESS_PRINT_RAW, /* print them in debug view */ + DBGLOG_PROCESS_POOL_RAW, /* user buffer pool to save them */ + DBGLOG_PROCESS_NET_RAW, /* user buffer pool to save them */ + DBGLOG_PROCESS_MAX, +} dbglog_process_t; + +enum cnss_diag_type { + DIAG_TYPE_FW_EVENT, /* send fw event- to diag*/ + DIAG_TYPE_FW_LOG, /* send log event- to diag*/ + DIAG_TYPE_FW_DEBUG_MSG, /* send dbg message- to diag*/ + DIAG_TYPE_INIT_REQ, /* cnss_diag nitialization- from diag */ + DIAG_TYPE_FW_MSG, /* fw msg command-to diag */ + DIAG_TYPE_HOST_MSG, /* host command-to diag */ + DIAG_TYPE_CRASH_INJECT, /*crash inject-from diag */ + DIAG_TYPE_DBG_LEVEL, /* DBG LEVEL-from diag */ +}; + +enum wlan_diag_config_type { + DIAG_VERSION_INFO, +}; + +enum wlan_diag_frame_type { + WLAN_DIAG_TYPE_CONFIG, + WLAN_DIAG_TYPE_EVENT, + WLAN_DIAG_TYPE_LOG, + WLAN_DIAG_TYPE_MSG, + WLAN_DIAG_TYPE_LEGACY_MSG, +}; + +/* log/event are always 32-bit aligned. Padding is inserted after + * optional payload to satisify this requirement */ +struct wlan_diag_data { + unsigned int word0; /* type, length */ + unsigned int target_time; + unsigned int code; /* Diag log or event Code */ + u_int8_t payload[0]; +}; + + +struct dbglog_slot { + unsigned int diag_type; + unsigned int timestamp; + unsigned int length; + unsigned int dropped; + /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */ + u_int8_t payload[0]; +}__packed; + +typedef struct event_report_s { + unsigned int diag_type; + unsigned short event_id; + unsigned short length; +} event_report_t; + +typedef struct wlan_bringup_s { + unsigned short wlanStatus; + char driverVersion[10]; +} wlan_bringup_t; + +static inline unsigned int get_32(const unsigned char *pos) +{ + return pos[0] | (pos[1] << 8) | (pos[2] << 16) | (pos[3] << 24); +} + +/* + * set the dbglog parser type + */ +int +dbglog_parser_type_init(wmi_unified_t wmi_handle, int type); + +/** dbglog_int - Registers a WMI event handle for WMI_DBGMSG_EVENT +* @brief wmi_handle - handle to wmi module +*/ +int +dbglog_init(wmi_unified_t wmi_handle); + +/** dbglog_deinit - UnRegisters a WMI event handle for WMI_DBGMSG_EVENT +* @brief wmi_handle - handle to wmi module +*/ +int +dbglog_deinit(wmi_unified_t wmi_handle); + +/** set the size of the report size +* @brief wmi_handle - handle to Wmi module +* @brief size - Report size +*/ +int +dbglog_set_report_size(wmi_unified_t wmi_handle, A_UINT16 size); + +/** Set the resolution for time stamp +* @brief wmi_handle - handle to Wmi module +* @ brief tsr - time stamp resolution +*/ +int +dbglog_set_timestamp_resolution(wmi_unified_t wmi_handle, A_UINT16 tsr); + +/** Enable reporting. If it is set to false then Traget wont deliver +* any debug information +*/ +int +dbglog_report_enable(wmi_unified_t wmi_handle, A_BOOL isenable); + +/** Set the log level +* @brief DBGLOG_INFO - Information lowest log level +* @brief DBGLOG_WARNING +* @brief DBGLOG_ERROR - default log level +*/ +int +dbglog_set_log_lvl(wmi_unified_t wmi_handle, DBGLOG_LOG_LVL log_lvl); + +/* + * set the debug log level for a given module + * mod_id_lvl : the format is more user friendly. + * module_id = mod_id_lvl/10; + * log_level = mod_id_lvl%10; + * example : mod_id_lvl is 153. then module id is 15 and log level is 3. this format allows + * user to pass a sinlge value (which is the most convenient way for most of the OSs) + * to be passed from user to the driver. + */ +int +dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, A_UINT32 mod_id_lvl); + +/** Enable/Disable the logging for VAP */ +int +dbglog_vap_log_enable(wmi_unified_t wmi_handle, A_UINT16 vap_id, + A_BOOL isenable); +/** Enable/Disable logging for Module */ +int +dbglog_module_log_enable(wmi_unified_t wmi_handle, A_UINT32 mod_id, + A_BOOL isenable); + +/** set vap enablie bitmap */ +void +dbglog_set_vap_enable_bitmap(wmi_unified_t wmi_handle, A_UINT32 vap_enable_bitmap); + +/** set log level for all the modules specified in the bitmap. for all other modules + * with 0 in the bitmap (or) outside the bitmap , the log level be reset to DBGLOG_ERR. + */ +void +dbglog_set_mod_enable_bitmap(wmi_unified_t wmi_handle,A_UINT32 log_level, + A_UINT32 *mod_enable_bitmap, A_UINT32 bitmap_len ); + +/** Custome debug_print handlers */ +/* Args: + module Id + vap id + debug msg id + Time stamp + no of arguments + pointer to the buffer holding the args +*/ +typedef A_BOOL (*module_dbg_print) (A_UINT32, A_UINT16, A_UINT32, A_UINT32, + A_UINT16, A_UINT32 *); + +/** Register module specific dbg print*/ +void dbglog_reg_modprint(A_UINT32 mod_id, module_dbg_print printfn); + +/** Register the cnss_diag activate with the wlan driver */ +int cnss_diag_activate_service(void); +int cnss_diag_notify_wlan_close(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_HOST_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_id.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_id.h new file mode 100644 index 000000000000..63384d7f2404 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dbglog_id.h @@ -0,0 +1,1621 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _DBGLOG_ID_H_ +#define _DBGLOG_ID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The target state machine framework will send dbglog messages on behalf on + * other modules. We do this do avoid each target module adding identical + * dbglog code for state transitions and event processing. We also don't want + * to force each module to define the the same XXX_DBGID_SM_MSG with the same + * value below. Instead we use a special ID that the host dbglog code + * recognizes as a message sent by the SM on behalf on another module. + */ +#define DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG 1000 + +/* + * The nomenclature for the debug identifiers is MODULE_DESCRIPTION. + * Please ensure that the definition of any new debugid introduced is captured + * between the _DBGID_DEFINITION_START and + * _DBGID_DEFINITION_END defines. The structure is required for the + * parser to correctly pick up the values for different debug identifiers. + */ + +/* +* The target state machine framework will send dbglog messages on behalf on +* other modules. We do this do avoid each module adding identical dbglog code +* for state transitions and event processing. We also don't want to force each +* module to define the the same XXX_DBGID_SM_MSG with the same value below. +* Instead we use a special ID that the host dbglog code recognizes as a +* message sent by the SM on behalf on another module. +*/ +#define DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG 1000 + + +/* INF debug identifier definitions */ +#define INF_DBGID_DEFINITION_START 0 +#define INF_ASSERTION_FAILED 1 +#define INF_TARGET_ID 2 +#define INF_TARGET_MEM_REMAING 3 +#define INF_TARGET_MEM_EXT_REMAING 4 +#define INF_TARGET_MEM_ALLOC_TRACK 5 +#define INF_TARGET_MEM_ALLOC_RAM 6 +#define INF_DBGID_DEFINITION_END 7 + +/* WMI debug identifier definitions */ +#define WMI_DBGID_DEFINITION_START 0 +#define WMI_CMD_RX_XTND_PKT_TOO_SHORT 1 +#define WMI_EXTENDED_CMD_NOT_HANDLED 2 +#define WMI_CMD_RX_PKT_TOO_SHORT 3 +#define WMI_CALLING_WMI_EXTENSION_FN 4 +#define WMI_CMD_NOT_HANDLED 5 +#define WMI_IN_SYNC 6 +#define WMI_TARGET_WMI_SYNC_CMD 7 +#define WMI_SET_SNR_THRESHOLD_PARAMS 8 +#define WMI_SET_RSSI_THRESHOLD_PARAMS 9 +#define WMI_SET_LQ_TRESHOLD_PARAMS 10 +#define WMI_TARGET_CREATE_PSTREAM_CMD 11 +#define WMI_WI_DTM_INUSE 12 +#define WMI_TARGET_DELETE_PSTREAM_CMD 13 +#define WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD 14 +#define WMI_TARGET_GET_BIT_RATE_CMD 15 +#define WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS 16 +#define WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD 17 +#define WMI_TARGET_GET_TX_PWR_CMD 18 +#define WMI_FREE_EVBUF_WMIBUF 19 +#define WMI_FREE_EVBUF_DATABUF 20 +#define WMI_FREE_EVBUF_BADFLAG 21 +#define WMI_HTC_RX_ERROR_DATA_PACKET 22 +#define WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX 23 +#define WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT 24 +#define WMI_SENDING_READY_EVENT 25 +#define WMI_SETPOWER_MDOE_TO_MAXPERF 26 +#define WMI_SETPOWER_MDOE_TO_REC 27 +#define WMI_BSSINFO_EVENT_FROM 28 +#define WMI_TARGET_GET_STATS_CMD 29 +#define WMI_SENDING_SCAN_COMPLETE_EVENT 30 +#define WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT 31 +#define WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT 32 +#define WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT 33 +#define WMI_SENDING_ERROR_REPORT_EVENT 34 +#define WMI_SENDING_CAC_EVENT 35 +#define WMI_TARGET_GET_ROAM_TABLE_CMD 36 +#define WMI_TARGET_GET_ROAM_DATA_CMD 37 +#define WMI_SENDING_GPIO_INTR_EVENT 38 +#define WMI_SENDING_GPIO_ACK_EVENT 39 +#define WMI_SENDING_GPIO_DATA_EVENT 40 +#define WMI_CMD_RX 41 +#define WMI_CMD_RX_XTND 42 +#define WMI_EVENT_SEND 43 +#define WMI_EVENT_SEND_XTND 44 +#define WMI_CMD_PARAMS_DUMP_START 45 +#define WMI_CMD_PARAMS_DUMP_END 46 +#define WMI_CMD_PARAMS 47 +#define WMI_EVENT_ALLOC_FAILURE 48 +#define WMI_DBGID_DCS_PARAM_CMD 49 +#define WMI_SEND_EVENT_WRONG_TLV 50 +#define WMI_SEND_EVENT_NO_TLV_DEF 51 +#define WMI_RECV_CMD_WRONG_TLV 52 +#define WMI_CHECK_TLV_PARAM_GET_NUM_TLVS_ERROR 53 +#define WMI_CHECK_TLV_PARAM_TLV_LEN_EXCEEDED_BUF_LEN 54 +#define WMI_CHECK_TLV_PARAM_NONEXISTING_TAG_ORDER 55 +#define WMI_CHECK_TLV_PARAM_WRONG_TAG_ORDER 56 +#define WMI_CHECK_TLV_PARAM_INVALID_TLV_DEF_ARRAY_SIZE 57 +#define WMI_CHECK_TLV_PARAM_INVALID_TLV_DEF_VARIED_SIZE 58 +#define WMI_CHECK_TLV_PARAM_WRONG_TLV_LENGTH 59 +#define WMI_CHECK_TLV_PARAM_UNALIGNED_TLV_LEN 60 +#define WMI_CHECK_TLV_PARAM_WRONG_INNER_TLV_LEN 61 +#define WMI_CHECK_TLV_PARAM_UNSUPPORTED_ARRAY_TAG 62 +#define WMI_CHECK_TLV_PARAM_EXCEEDED_MAX_TLVs 63 +#define WMI_CHECK_TLV_PARAM_CMD_BUF_ALLOC_FAILED 64 +#define WMI_CHECK_TLV_PARAM_TLV_INFO 65 +#define WMI_DBGID_DEFINITION_END 66 + +/* PM Message definition*/ +#define PS_STA_DEFINITION_START 0 +#define PS_STA_PM_ARB_REQUEST 1 +#define PS_STA_DELIVER_EVENT 2 +#define PS_STA_PSPOLL_SEQ_DONE 3 +#define PS_STA_COEX_MODE 4 +#define PS_STA_PSPOLL_ALLOW 5 +#define PS_STA_SET_PARAM 6 +#define PS_STA_SPECPOLL_TIMER_STARTED 7 +#define PS_STA_SPECPOLL_TIMER_STOPPED 8 +#define PS_STA_AVG_CHANNEL_CONGESTION 9 +#define PS_STA_DEFINITION_END 10 + +/** RESMGR dbg ids */ +/* TODO: 1. Segregate IDs as per sub-module. (Give 100 per sub-module?) + * 2. Add chmgr IDs over here. + * 3. Update prints in dbglog_host.c + * 4. Deprecate WLAN_MODULE_RESMGR_CHAN_MANAGER */ +#define RESMGR_DEFINITION_START 0 +#define RESMGR_OCS_ALLOCRAM_SIZE 1 +#define RESMGR_OCS_RESOURCES 2 +#define RESMGR_LINK_CREATE 3 +#define RESMGR_LINK_DELETE 4 +#define RESMGR_OCS_CHREQ_CREATE 5 +#define RESMGR_OCS_CHREQ_DELETE 6 +#define RESMGR_OCS_CHREQ_START 7 +#define RESMGR_OCS_CHREQ_STOP 8 +#define RESMGR_OCS_SCHEDULER_INVOKED 9 +#define RESMGR_OCS_CHREQ_GRANT 10 +#define RESMGR_OCS_CHREQ_COMPLETE 11 +#define RESMGR_OCS_NEXT_TSFTIME 12 +#define RESMGR_OCS_TSF_TIMEOUT_US 13 +#define RESMGR_OCS_CURR_CAT_WINDOW 14 +#define RESMGR_OCS_CURR_CAT_WINDOW_REQ 15 +#define RESMGR_OCS_CURR_CAT_WINDOW_TIMESLOT 16 +#define RESMGR_OCS_CHREQ_RESTART 17 +#define RESMGR_OCS_CLEANUP_CH_ALLOCATORS 18 +#define RESMGR_OCS_PURGE_CHREQ 19 +#define RESMGR_OCS_CH_ALLOCATOR_FREE 20 +#define RESMGR_OCS_RECOMPUTE_SCHEDULE 21 +#define RESMGR_OCS_NEW_CAT_WINDOW_REQ 22 +#define RESMGR_OCS_NEW_CAT_WINDOW_TIMESLOT 23 +#define RESMGR_OCS_CUR_CH_ALLOC 24 +#define RESMGR_OCS_WIN_CH_ALLOC 25 +#define RESMGR_OCS_SCHED_CH_CHANGE 26 +#define RESMGR_OCS_CONSTRUCT_CAT_WIN 27 +#define RESMGR_OCS_CHREQ_PREEMPTED 28 +#define RESMGR_OCS_CH_SWITCH_REQ 29 +#define RESMGR_OCS_CHANNEL_SWITCHED 30 +#define RESMGR_OCS_CLEANUP_STALE_REQS 31 +#define RESMGR_OCS_CHREQ_UPDATE 32 +#define RESMGR_OCS_REG_NOA_NOTIF 33 +#define RESMGR_OCS_DEREG_NOA_NOTIF 34 +#define RESMGR_OCS_GEN_PERIODIC_NOA 35 +#define RESMGR_OCS_RECAL_QUOTAS 36 +#define RESMGR_OCS_GRANTED_QUOTA_STATS 37 +#define RESMGR_OCS_ALLOCATED_QUOTA_STATS 38 +#define RESMGR_OCS_REQ_QUOTA_STATS 39 +#define RESMGR_OCS_TRACKING_TIME_FIRED 40 +#define RESMGR_VC_ARBITRATE_ATTRIBUTES 41 +#define RESMGR_OCS_LATENCY_STRICT_TIME_SLOT 42 +#define RESMGR_OCS_CURR_TSF 43 +#define RESMGR_OCS_QUOTA_REM 44 +#define RESMGR_OCS_LATENCY_CASE_NO 45 +#define RESMGR_OCS_WIN_CAT_DUR 46 +#define RESMGR_VC_UPDATE_CUR_VC 47 +#define RESMGR_VC_REG_UNREG_LINK 48 +#define RESMGR_VC_PRINT_LINK 49 +#define RESMGR_OCS_MISS_TOLERANCE 50 +#define RESMGR_DYN_SCH_ALLOCRAM_SIZE 51 +#define RESMGR_DYN_SCH_ENABLE 52 +#define RESMGR_DYN_SCH_ACTIVE 53 +#define RESMGR_DYN_SCH_CH_STATS_START 54 +#define RESMGR_DYN_SCH_CH_SX_STATS 55 +#define RESMGR_DYN_SCH_TOT_UTIL_PER 56 +#define RESMGR_DYN_SCH_HOME_CH_QUOTA 57 +#define RESMGR_OCS_REG_RECAL_QUOTA_NOTIF 58 +#define RESMGR_OCS_DEREG_RECAL_QUOTA_NOTIF 59 +#define RESMGR_DYN_SCH_CH_STATS_END 60 +#define RESMGR_DEFINITION_END 61 + +/* RESMGR CHNMGR debug ids */ +#define RESMGR_CHMGR_DEFINITION_START 0 +#define RESMGR_CHMGR_PAUSE_COMPLETE 1 +#define RESMGR_CHMGR_CHANNEL_CHANGE 2 +#define RESMGR_CHMGR_RESUME_COMPLETE 3 +#define RESMGR_CHMGR_VDEV_PAUSE 4 +#define RESMGR_CHMGR_VDEV_UNPAUSE 5 +#define RESMGR_CHMGR_CTS2S_TX_COMP 6 +#define RESMGR_CHMGR_CFEND_TX_COMP 7 +#define RESMGR_CHMGR_DEFINITION_END 8 + +/* VDEV manager debug ids */ +#define VDEV_MGR_DEFINITION_START 0 +#define VDEV_MGR_FIRST_BMISS_DETECTED 1 +#define VDEV_MGR_FINAL_BMISS_DETECTED 2 +#define VDEV_MGR_BCN_IN_SYNC 3 +#define VDEV_MGR_AP_KEEPALIVE_IDLE 4 +#define VDEV_MGR_AP_KEEPALIVE_INACTIVE 5 +#define VDEV_MGR_AP_KEEPALIVE_UNRESPONSIVE 6 +#define VDEV_MGR_AP_TBTT_CONFIG 7 +#define VDEV_MGR_FIRST_BCN_RECEIVED 8 +#define VDEV_MGR_VDEV_START 9 +#define VDEV_MGR_VDEV_UP 10 +#define VDEV_MGR_PEER_AUTHORIZED 11 +#define VDEV_MGR_OCS_HP_LP_REQ_POSTED 12 +#define VDEV_MGR_VDEV_START_OCS_HP_REQ_COMPLETE 13 +#define VDEV_MGR_VDEV_START_OCS_HP_REQ_STOP 14 +#define VDEV_MGR_HP_START_TIME 15 +#define VDEV_MGR_VDEV_PAUSE_DELAY_UPDATE 16 +#define VDEV_MGR_VDEV_PAUSE_FAIL 17 +#define VDEV_MGR_GEN_PERIODIC_NOA 18 +#define VDEV_MGR_OFF_CHAN_GO_CH_REQ_SETUP 19 +#define VDEV_MGR_DEFINITION_END 20 + +/* WHAL debug identifier definitions */ +#define WHAL_DBGID_DEFINITION_START 0 +#define WHAL_ERROR_ANI_CONTROL 1 +#define WHAL_ERROR_CHIP_TEST1 2 +#define WHAL_ERROR_CHIP_TEST2 3 +#define WHAL_ERROR_EEPROM_CHECKSUM 4 +#define WHAL_ERROR_EEPROM_MACADDR 5 +#define WHAL_ERROR_INTERRUPT_HIU 6 +#define WHAL_ERROR_KEYCACHE_RESET 7 +#define WHAL_ERROR_KEYCACHE_SET 8 +#define WHAL_ERROR_KEYCACHE_TYPE 9 +#define WHAL_ERROR_KEYCACHE_TKIPENTRY 10 +#define WHAL_ERROR_KEYCACHE_WEPLENGTH 11 +#define WHAL_ERROR_PHY_INVALID_CHANNEL 12 +#define WHAL_ERROR_POWER_AWAKE 13 +#define WHAL_ERROR_POWER_SET 14 +#define WHAL_ERROR_RECV_STOPDMA 15 +#define WHAL_ERROR_RECV_STOPPCU 16 +#define WHAL_ERROR_RESET_CHANNF1 17 +#define WHAL_ERROR_RESET_CHANNF2 18 +#define WHAL_ERROR_RESET_PM 19 +#define WHAL_ERROR_RESET_OFFSETCAL 20 +#define WHAL_ERROR_RESET_RFGRANT 21 +#define WHAL_ERROR_RESET_RXFRAME 22 +#define WHAL_ERROR_RESET_STOPDMA 23 +#define WHAL_ERROR_RESET_ERRID 24 +#define WHAL_ERROR_RESET_ADCDCCAL1 25 +#define WHAL_ERROR_RESET_ADCDCCAL2 26 +#define WHAL_ERROR_RESET_TXIQCAL 27 +#define WHAL_ERROR_RESET_RXIQCAL 28 +#define WHAL_ERROR_RESET_CARRIERLEAK 29 +#define WHAL_ERROR_XMIT_COMPUTE 30 +#define WHAL_ERROR_XMIT_NOQUEUE 31 +#define WHAL_ERROR_XMIT_ACTIVEQUEUE 32 +#define WHAL_ERROR_XMIT_BADTYPE 33 +#define WHAL_ERROR_XMIT_STOPDMA 34 +#define WHAL_ERROR_INTERRUPT_BB_PANIC 35 +#define WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW 36 +#define WHAL_ERROR_QCU_HW_PAUSE_MISMATCH 37 +#define WHAL_ERROR_POWER_RFLP_CONFIG 38 +#define WHAL_ERROR_POWER_RFLP_SYNTHBYPASS_CONFIG 39 +#define WHAL_ERROR_POWER_RFLP_BIAS2X_CONFIG 40 +#define WHAL_ERROR_POWER_RFLP_PLLBYPASS_CONFIG 41 +#define WHAL_ERROR_POWER_RFLP_OFF1CHAN_CONFIG 42 +#define WHAL_ERROR_POWER_ANTENNA_LMIT 43 +#define WHAL_ERROR_POWER_REGDMN_TX_LMIT 44 +#define WHAL_ERROR_POWER_MODE_SCALED_PWR 45 +#define WHAL_ERROR_POWER_EDGE_PWR_TPSCALE 46 +#define WHAL_ERROR_POWER_CHAN_REGALLOW 47 +#define WHAL_ERROR_WAIT_REG_TIMEOUT 48 +#define WHAL_ERROR_XTAL_SET 49 +#define WHAL_DBGID_DEFINITION_END 50 + +#define COEX_DEBUGID_START 0 +#define BTCOEX_DBG_MCI_1 1 +#define BTCOEX_DBG_MCI_2 2 +#define BTCOEX_DBG_MCI_3 3 +#define BTCOEX_DBG_MCI_4 4 +#define BTCOEX_DBG_MCI_5 5 +#define BTCOEX_DBG_MCI_6 6 +#define BTCOEX_DBG_MCI_7 7 +#define BTCOEX_DBG_MCI_8 8 +#define BTCOEX_DBG_MCI_9 9 +#define BTCOEX_DBG_MCI_10 10 +#define COEX_WAL_BTCOEX_INIT 11 +#define COEX_WAL_PAUSE 12 +#define COEX_WAL_RESUME 13 +#define COEX_UPDATE_AFH 14 +#define COEX_HWQ_EMPTY_CB 15 +#define COEX_MCI_TIMER_HANDLER 16 +#define COEX_MCI_RECOVER 17 +#define ERROR_COEX_MCI_ISR 18 +#define ERROR_COEX_MCI_GPM 19 +#define COEX_ProfileType 20 +#define COEX_LinkID 21 +#define COEX_LinkState 22 +#define COEX_LinkRole 23 +#define COEX_LinkRate 24 +#define COEX_VoiceType 25 +#define COEX_TInterval 26 +#define COEX_WRetrx 27 +#define COEX_Attempts 28 +#define COEX_PerformanceState 29 +#define COEX_LinkType 30 +#define COEX_RX_MCI_GPM_VERSION_QUERY 31 +#define COEX_RX_MCI_GPM_VERSION_RESPONSE 32 +#define COEX_RX_MCI_GPM_STATUS_QUERY 33 +#define COEX_STATE_WLAN_VDEV_DOWN 34 +#define COEX_STATE_WLAN_VDEV_START 35 +#define COEX_STATE_WLAN_VDEV_CONNECTED 36 +#define COEX_STATE_WLAN_VDEV_SCAN_STARTED 37 +#define COEX_STATE_WLAN_VDEV_SCAN_END 38 +#define COEX_STATE_WLAN_DEFAULT 39 +#define COEX_CHANNEL_CHANGE 40 +#define COEX_POWER_CHANGE 41 +#define COEX_CONFIG_MGR 42 +#define COEX_TX_MCI_GPM_BT_CAL_REQ 43 +#define COEX_TX_MCI_GPM_BT_CAL_GRANT 44 +#define COEX_TX_MCI_GPM_BT_CAL_DONE 45 +#define COEX_TX_MCI_GPM_WLAN_CAL_REQ 46 +#define COEX_TX_MCI_GPM_WLAN_CAL_GRANT 47 +#define COEX_TX_MCI_GPM_WLAN_CAL_DONE 48 +#define COEX_TX_MCI_GPM_BT_DEBUG 49 +#define COEX_TX_MCI_GPM_VERSION_QUERY 50 +#define COEX_TX_MCI_GPM_VERSION_RESPONSE 51 +#define COEX_TX_MCI_GPM_STATUS_QUERY 52 +#define COEX_TX_MCI_GPM_HALT_BT_GPM 53 +#define COEX_TX_MCI_GPM_WLAN_CHANNELS 54 +#define COEX_TX_MCI_GPM_BT_PROFILE_INFO 55 +#define COEX_TX_MCI_GPM_BT_STATUS_UPDATE 56 +#define COEX_TX_MCI_GPM_BT_UPDATE_FLAGS 57 +#define COEX_TX_MCI_GPM_UNKNOWN 58 +#define COEX_TX_MCI_SYS_WAKING 59 +#define COEX_TX_MCI_LNA_TAKE 60 +#define COEX_TX_MCI_LNA_TRANS 61 +#define COEX_TX_MCI_SYS_SLEEPING 62 +#define COEX_TX_MCI_REQ_WAKE 63 +#define COEX_TX_MCI_REMOTE_RESET 64 +#define COEX_TX_MCI_TYPE_UNKNOWN 65 +#define COEX_WHAL_MCI_RESET 66 +#define COEX_POLL_BT_CAL_DONE_TIMEOUT 67 +#define COEX_WHAL_PAUSE 68 +#define COEX_RX_MCI_GPM_BT_CAL_REQ 69 +#define COEX_RX_MCI_GPM_BT_CAL_DONE 70 +#define COEX_RX_MCI_GPM_BT_CAL_GRANT 71 +#define COEX_WLAN_CAL_START 72 +#define COEX_WLAN_CAL_RESULT 73 +#define COEX_BtMciState 74 +#define COEX_BtCalState 75 +#define COEX_WlanCalState 76 +#define COEX_RxReqWakeCount 77 +#define COEX_RxRemoteResetCount 78 +#define COEX_RESTART_CAL 79 +#define COEX_SENDMSG_QUEUE 80 +#define COEX_RESETSEQ_LNAINFO_TIMEOUT 81 +#define COEX_MCI_ISR_IntRaw 82 +#define COEX_MCI_ISR_Int1Raw 83 +#define COEX_MCI_ISR_RxMsgRaw 84 +#define COEX_WHAL_COEX_RESET 85 +#define COEX_WAL_COEX_INIT 86 +#define COEX_TXRX_CNT_LIMIT_ISR 87 +#define COEX_CH_BUSY 88 +#define COEX_REASSESS_WLAN_STATE 89 +#define COEX_BTCOEX_WLAN_STATE_UPDATE 90 +#define COEX_BT_NUM_OF_PROFILES 91 +#define COEX_BT_NUM_OF_HID_PROFILES 92 +#define COEX_BT_NUM_OF_ACL_PROFILES 93 +#define COEX_BT_NUM_OF_HI_ACL_PROFILES 94 +#define COEX_BT_NUM_OF_VOICE_PROFILES 95 +#define COEX_WLAN_AGGR_LIMIT 96 +#define COEX_BT_LOW_PRIO_BUDGET 97 +#define COEX_BT_HI_PRIO_BUDGET 98 +#define COEX_BT_IDLE_TIME 99 +#define COEX_SET_COEX_WEIGHT 100 +#define COEX_WLAN_WEIGHT_GROUP 101 +#define COEX_BT_WEIGHT_GROUP 102 +#define COEX_BT_INTERVAL_ALLOC 103 +#define COEX_BT_SCHEME 104 +#define COEX_BT_MGR 105 +#define COEX_BT_SM_ERROR 106 +#define COEX_SYSTEM_UPDATE 107 +#define COEX_LOW_PRIO_LIMIT 108 +#define COEX_HI_PRIO_LIMIT 109 +#define COEX_BT_INTERVAL_START 110 +#define COEX_WLAN_INTERVAL_START 111 +#define COEX_NON_LINK_BUDGET 112 +#define COEX_CONTENTION_MSG 113 +#define COEX_SET_NSS 114 +#define COEX_SELF_GEN_MASK 115 +#define COEX_PROFILE_ERROR 116 +#define COEX_WLAN_INIT 117 +#define COEX_BEACON_MISS 118 +#define COEX_BEACON_OK 119 +#define COEX_BTCOEX_SCAN_ACTIVITY 120 +#define COEX_SCAN_ACTIVITY 121 +#define COEX_FORCE_QUIETTIME 122 +#define COEX_BT_MGR_QUIETTIME 123 +#define COEX_BT_INACTIVITY_TRIGGER 124 +#define COEX_BT_INACTIVITY_REPORTED 125 +#define COEX_TX_MCI_GPM_WLAN_PRIO 126 +#define COEX_TX_MCI_GPM_BT_PAUSE_PROFILE 127 +#define COEX_TX_MCI_GPM_WLAN_SET_ACL_INACTIVITY 128 +#define COEX_RX_MCI_GPM_BT_ACL_INACTIVITY_REPORT 129 +#define COEX_GENERIC_ERROR 130 +#define COEX_RX_RATE_THRESHOLD 131 +#define COEX_RSSI 132 + +#define COEX_WLAN_VDEV_NOTIF_START 133 +#define COEX_WLAN_VDEV_NOTIF_UP 134 +#define COEX_WLAN_VDEV_NOTIF_DOWN 135 +#define COEX_WLAN_VDEV_NOTIF_STOP 136 +#define COEX_WLAN_VDEV_NOTIF_ADD_PEER 137 +#define COEX_WLAN_VDEV_NOTIF_DELETE_PEER 138 +#define COEX_WLAN_VDEV_NOTIF_CONNECTED_PEER 139 +#define COEX_WLAN_VDEV_NOTIF_PAUSE 140 +#define COEX_WLAN_VDEV_NOTIF_UNPAUSED 141 +#define COEX_STATE_WLAN_VDEV_PEER_ADD 142 +#define COEX_STATE_WLAN_VDEV_CONNECTED_PEER 143 +#define COEX_STATE_WLAN_VDEV_DELETE_PEER 144 +#define COEX_STATE_WLAN_VDEV_PAUSE 145 +#define COEX_STATE_WLAN_VDEV_UNPAUSED 146 +#define COEX_SCAN_CALLBACK 147 +#define COEX_RC_SET_CHAINMASK 148 +#define COEX_TX_MCI_GPM_WLAN_SET_BT_RXSS_THRES 149 +#define COEX_TX_MCI_GPM_BT_RXSS_THRES_QUERY 150 +#define COEX_BT_RXSS_THRES 151 +#define COEX_BT_PROFILE_ADD_RMV 152 +#define COEX_BT_SCHED_INFO 153 +#define COEX_TRF_MGMT 154 +#define COEX_SCHED_START 155 +#define COEX_SCHED_RESULT 156 +#define COEX_SCHED_ERROR 157 +#define COEX_SCHED_PRE_OP 158 +#define COEX_SCHED_POST_OP 159 +#define COEX_RX_RATE 160 +#define COEX_ACK_PRIORITY 161 +#define COEX_STATE_WLAN_VDEV_UP 162 +#define COEX_STATE_WLAN_VDEV_PEER_UPDATE 163 +#define COEX_STATE_WLAN_VDEV_STOP 164 +#define COEX_WLAN_PAUSE_PEER 165 +#define COEX_WLAN_UNPAUSE_PEER 166 +#define COEX_WLAN_PAUSE_INTERVAL_START 167 +#define COEX_WLAN_POSTPAUSE_INTERVAL_START 168 +#define COEX_TRF_FREERUN 169 +#define COEX_TRF_SHAPE_PM 170 +#define COEX_TRF_SHAPE_PSP 171 +#define COEX_TRF_SHAPE_S_CTS 172 +#define COEX_CHAIN_CONFIG 173 +#define COEX_SYSTEM_MONITOR 174 +#define COEX_SINGLECHAIN_INIT 175 +#define COEX_MULTICHAIN_INIT 176 +#define COEX_SINGLECHAIN_DBG_1 177 +#define COEX_SINGLECHAIN_DBG_2 178 +#define COEX_SINGLECHAIN_DBG_3 179 +#define COEX_MULTICHAIN_DBG_1 180 +#define COEX_MULTICHAIN_DBG_2 181 +#define COEX_MULTICHAIN_DBG_3 182 +#define COEX_PSP_TX_CB 183 +#define COEX_PSP_RX_CB 184 +#define COEX_PSP_STAT_1 185 +#define COEX_PSP_SPEC_POLL 186 +#define COEX_PSP_READY_STATE 187 +#define COEX_PSP_TX_STATUS_STATE 188 +#define COEX_PSP_RX_STATUS_STATE_1 189 +#define COEX_PSP_NOT_READY_STATE 190 +#define COEX_PSP_DISABLED_STATE 191 +#define COEX_PSP_ENABLED_STATE 192 +#define COEX_PSP_SEND_PSPOLL 193 +#define COEX_PSP_MGR_ENTER 194 +#define COEX_PSP_MGR_RESULT 195 +#define COEX_PSP_NONWLAN_INTERVAL 196 +#define COEX_PSP_STAT_2 197 +#define COEX_PSP_RX_STATUS_STATE_2 198 +#define COEX_PSP_ERROR 199 +#define COEX_T2BT 200 +#define COEX_BT_DURATION 201 +#define COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG 202 +#define COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG_RSP 203 +#define COEX_TX_MCI_GPM_SCAN_OP 204 +#define COEX_TX_MCI_GPM_BT_PAUSE_GPM_TX 205 +#define COEX_CTS2S_SEND 206 +#define COEX_CTS2S_RESULT 207 +#define COEX_ENTER_OCS 208 +#define COEX_EXIT_OCS 209 +#define COEX_UPDATE_OCS 210 +#define COEX_STATUS_OCS 211 +#define COEX_STATS_BT 212 + +#define COEX_MWS_WLAN_INIT 213 +#define COEX_MWS_WBTMR_SYNC 214 +#define COEX_MWS_TYPE2_RX 215 +#define COEX_MWS_TYPE2_TX 216 +#define COEX_MWS_WLAN_CHAVD 217 +#define COEX_MWS_WLAN_CHAVD_INSERT 218 +#define COEX_MWS_WLAN_CHAVD_MERGE 219 +#define COEX_MWS_WLAN_CHAVD_RPT 220 +#define COEX_MWS_CP_MSG_SEND 221 +#define COEX_MWS_CP_ESCAPE 222 +#define COEX_MWS_CP_UNFRAME 223 +#define COEX_MWS_CP_SYNC_UPDATE 224 +#define COEX_MWS_CP_SYNC 225 +#define COEX_MWS_CP_WLAN_STATE_IND 226 +#define COEX_MWS_CP_SYNCRESP_TIMEOUT 227 +#define COEX_MWS_SCHEME_UPDATE 228 +#define COEX_MWS_WLAN_EVENT 229 +#define COEX_MWS_UART_UNESCAPE 230 +#define COEX_MWS_UART_ENCODE_SEND 231 +#define COEX_MWS_UART_RECV_DECODE 232 +#define COEX_MWS_UL_HDL 233 +#define COEX_MWS_REMOTE_EVENT 234 +#define COEX_MWS_OTHER 235 +#define COEX_MWS_ERROR 236 +#define COEX_MWS_ANT_DIVERSITY 237 + +#define COEX_P2P_GO 238 +#define COEX_P2P_CLIENT 239 +#define COEX_SCC_1 240 +#define COEX_SCC_2 241 +#define COEX_MCC_1 242 +#define COEX_MCC_2 243 +#define COEX_TRF_SHAPE_NOA 244 +#define COEX_NOA_ONESHOT 245 +#define COEX_NOA_PERIODIC 246 +#define COEX_LE_1 247 +#define COEX_LE_2 248 +#define COEX_ANT_1 249 +#define COEX_ANT_2 250 +#define COEX_ENTER_NOA 251 +#define COEX_EXIT_NOA 252 +#define COEX_BT_SCAN_PROTECT 253 + +#define COEX_DEBUG_ID_END 254 + +#define SCAN_START_COMMAND_FAILED 0 +#define SCAN_STOP_COMMAND_FAILED 1 +#define SCAN_EVENT_SEND_FAILED 2 +#define SCAN_ENGINE_START 3 +#define SCAN_ENGINE_CANCEL_COMMAND 4 +#define SCAN_ENGINE_STOP_DUE_TO_TIMEOUT 5 +#define SCAN_EVENT_SEND_TO_HOST 6 +#define SCAN_FWLOG_EVENT_ADD 7 +#define SCAN_FWLOG_EVENT_REM 8 +#define SCAN_FWLOG_EVENT_PREEMPTED 9 +#define SCAN_FWLOG_EVENT_RESTARTED 10 +#define SCAN_FWLOG_EVENT_COMPLETED 11 +#define SCAN_SM_REQ_NEXT_CH 12 +#define SCAN_DBGID_DEFINITION_END 13 + +#define BEACON_EVENT_SWBA_SEND_FAILED 0 +#define BEACON_EVENT_EARLY_RX_BMISS_STATUS 1 +#define BEACON_EVENT_EARLY_RX_SLEEP_SLOP 2 +#define BEACON_EVENT_EARLY_RX_CONT_BMISS_TIMEOUT 3 +#define BEACON_EVENT_EARLY_RX_PAUSE_SKIP_BCN_NUM 4 +#define BEACON_EVENT_EARLY_RX_CLK_DRIFT 5 +#define BEACON_EVENT_EARLY_RX_AP_DRIFT 6 +#define BEACON_EVENT_EARLY_RX_BCN_TYPE 7 + +#define RATECTRL_DBGID_DEFINITION_START 0 +#define RATECTRL_DBGID_ASSOC 1 +#define RATECTRL_DBGID_NSS_CHANGE 2 +#define RATECTRL_DBGID_CHAINMASK_ERR 3 +#define RATECTRL_DBGID_UNEXPECTED_FRAME 4 +#define RATECTRL_DBGID_WAL_RCQUERY 5 +#define RATECTRL_DBGID_WAL_RCUPDATE 6 +#define RATECTRL_DBGID_GTX_UPDATE 7 +#define RATECTRL_DBGID_DEFINITION_END 8 + +#define AP_PS_DBGID_DEFINITION_START 0 +#define AP_PS_DBGID_UPDATE_TIM 1 +#define AP_PS_DBGID_PEER_STATE_CHANGE 2 +#define AP_PS_DBGID_PSPOLL 3 +#define AP_PS_DBGID_PEER_CREATE 4 +#define AP_PS_DBGID_PEER_DELETE 5 +#define AP_PS_DBGID_VDEV_CREATE 6 +#define AP_PS_DBGID_VDEV_DELETE 7 +#define AP_PS_DBGID_SYNC_TIM 8 +#define AP_PS_DBGID_NEXT_RESPONSE 9 +#define AP_PS_DBGID_START_SP 10 +#define AP_PS_DBGID_COMPLETED_EOSP 11 +#define AP_PS_DBGID_TRIGGER 12 +#define AP_PS_DBGID_DUPLICATE_TRIGGER 13 +#define AP_PS_DBGID_UAPSD_RESPONSE 14 +#define AP_PS_DBGID_SEND_COMPLETE 15 +#define AP_PS_DBGID_SEND_N_COMPLETE 16 +#define AP_PS_DBGID_DETECT_OUT_OF_SYNC_STA 17 +#define AP_PS_DBGID_DELIVER_CAB 18 +#define AP_PS_DBGID_NO_CLIENT 27 +#define AP_PS_DBGID_CLIENT_IN_PS_ACTIVE 28 +#define AP_PS_DBGID_CLIENT_IN_PS_NON_ACTIVE 29 +#define AP_PS_DBGID_CLIENT_IN_AWAKE 30 +/* Enhanced Green AP DBGIDs */ +#define AP_PS_DBGID_EGAP_SET_PARAM 31 +#define AP_PS_DBGID_EGAP_VDEV_START 32 +#define AP_PS_DBGID_EGAP_VDEV_STOP 33 +#define AP_PS_DBGID_EGAP_CONN_PEER 34 +#define AP_PS_DBGID_EGAP_DELETE_PEER 35 +#define AP_PS_DBGID_EGAP_WAL_PEER_EVENT 36 +#define AP_PS_DBGID_EGAP_WAL_PDEV_EVENT 37 +#define AP_PS_DBGID_EGAP_NOTIF_STA_SLEEPING 38 +#define AP_PS_DBGID_EGAP_PROC_STA_SLEEPING 39 +#define AP_PS_DBGID_EGAP_PROC_STA_INACTIVITY 40 +#define AP_PS_DBGID_EGAP_CHANGE_CHAINMASK 41 +#define AP_PS_DBGID_EGAP_CHANGE_SM_STATE 42 + +/* WLAN_MODULE_MGMT_TXRX Debugids*/ +#define MGMT_TXRX_DBGID_DEFINITION_START 0 +#define MGMT_TXRX_FORWARD_TO_HOST 1 +#define MGMT_TXRX_MGMT_FRAME_BUFFER_FULL 2 +#define MGMT_TXRX_VDEV_USED_TO_SEND_FRAME_IS_FREE 3 +#define MGMT_TXRX_LOCAL_FRAME_SEND_FAILED 4 +#define MGMT_TXRX_DBGID_DEFINITION_END 5 + +#define WAL_DBGID_DEFINITION_START 0 +#define WAL_DBGID_FAST_WAKE_REQUEST 1 +#define WAL_DBGID_FAST_WAKE_RELEASE 2 +#define WAL_DBGID_SET_POWER_STATE 3 +#define WAL_DBGID_CHANNEL_CHANGE_FORCE_RESET 5 +#define WAL_DBGID_CHANNEL_CHANGE 6 +#define WAL_DBGID_VDEV_START 7 +#define WAL_DBGID_VDEV_STOP 8 +#define WAL_DBGID_VDEV_UP 9 +#define WAL_DBGID_VDEV_DOWN 10 +#define WAL_DBGID_SW_WDOG_RESET 11 +#define WAL_DBGID_TX_SCH_REGISTER_TIDQ 12 +#define WAL_DBGID_TX_SCH_UNREGISTER_TIDQ 13 +#define WAL_DBGID_TX_SCH_TICKLE_TIDQ 14 + + +#define WAL_DBGID_XCESS_FAILURES 15 +#define WAL_DBGID_AST_ADD_WDS_ENTRY 16 +#define WAL_DBGID_AST_DEL_WDS_ENTRY 17 +#define WAL_DBGID_AST_WDS_ENTRY_PEER_CHG 18 +#define WAL_DBGID_AST_WDS_SRC_LEARN_FAIL 19 +#define WAL_DBGID_STA_KICKOUT 20 +#define WAL_DBGID_BAR_TX_FAIL 21 +#define WAL_DBGID_BAR_ALLOC_FAIL 22 +#define WAL_DBGID_LOCAL_DATA_TX_FAIL 23 +#define WAL_DBGID_SECURITY_PM4_QUEUED 24 +#define WAL_DBGID_SECURITY_GM1_QUEUED 25 +#define WAL_DBGID_SECURITY_PM4_SENT 26 +#define WAL_DBGID_SECURITY_ALLOW_DATA 27 +#define WAL_DBGID_SECURITY_UCAST_KEY_SET 28 +#define WAL_DBGID_SECURITY_MCAST_KEY_SET 29 +#define WAL_DBGID_SECURITY_ENCR_EN 30 +#define WAL_DBGID_BB_WDOG_TRIGGERED 31 +#define WAL_DBGID_RX_LOCAL_BUFS_LWM 32 +#define WAL_DBGID_RX_LOCAL_DROP_LARGE_MGMT 33 +#define WAL_DBGID_VHT_ILLEGAL_RATE_PHY_ERR_DETECTED 34 +#define WAL_DBGID_DEV_RESET 35 +#define WAL_DBGID_TX_BA_SETUP 36 +#define WAL_DBGID_RX_BA_SETUP 37 +#define WAL_DBGID_DEV_TX_TIMEOUT 38 +#define WAL_DBGID_DEV_RX_TIMEOUT 39 +#define WAL_DBGID_STA_VDEV_XRETRY 40 +#define WAL_DBGID_DCS 41 +#define WAL_DBGID_MGMT_TX_FAIL 42 +#define WAL_DBGID_SET_M4_SENT_MANUALLY 43 +#define WAL_DBGID_PROCESS_4_WAY_HANDSHAKE 44 +#define WAL_DBGID_WAL_CHANNEL_CHANGE_START 45 +#define WAL_DBGID_WAL_CHANNEL_CHANGE_COMPLETE 46 +#define WAL_DBGID_WHAL_CHANNEL_CHANGE_START 47 +#define WAL_DBGID_WHAL_CHANNEL_CHANGE_COMPLETE 48 +#define WAL_DBGID_TX_MGMT_DESCID_SEQ_TYPE_LEN 49 +#define WAL_DBGID_TX_DATA_MSDUID_SEQ_TYPE_LEN 50 +#define WAL_DBGID_TX_DISCARD 51 +#define WAL_DBGID_TX_MGMT_COMP_DESCID_STATUS 52 +#define WAL_DBGID_TX_DATA_COMP_MSDUID_STATUS 53 +#define WAL_DBGID_RESET_PCU_CYCLE_CNT 54 +#define WAL_DBGID_SETUP_RSSI_INTERRUPTS 55 +#define WAL_DBGID_BRSSI_CONFIG 56 +#define WAL_DBGID_CURRENT_BRSSI_AVE 57 +#define WAL_DBGID_BCN_TX_COMP 58 +#define WAL_DBGID_RX_REENTRY 59 +#define WAL_DBGID_SET_HW_CHAINMASK 60 +#define WAL_DBGID_SET_HW_CHAINMASK_TXRX_STOP_FAIL 61 +#define WAL_DBGID_GET_HW_CHAINMASK 62 +#define WAL_DBGID_SMPS_DISABLE 63 +#define WAL_DBGID_SMPS_ENABLE_HW_CNTRL 64 +#define WAL_DBGID_SMPS_SWSEL_CHAINMASK 65 +#define WAL_DBGID_SUSPEND 66 +#define WAL_DBGID_RESUME 67 +#define WAL_DBGID_PEER_TX_FAIL_CNT_THRES_EXCEEDED 68 +#define WAL_DBGID_RX_FULL_REORDER_SUPPORT 69 +#define WAL_DBGID_HCM_BIN 70 +#define WAL_DBGID_HCM_BIN_PENALIZE 71 +#define WAL_DBGID_HCM_BIN_DEPENALIZE 72 +#define WAL_DBGID_AST_UPDATE_WDS_ENTRY 73 +#define WAL_DBGID_PEER_EXT_STATS 74 +#define WAL_DBGID_TX_AC_BUFFER_SET 75 +#define WAL_DBGID_AST_ENTRY_EXIST 76 +#define WAL_DBGID_AST_ENTRY_FULL 77 +#define WAL_DBGID_WMMAC_TXQ_STATUS 78 +#define WAL_DBGID_PROLONGED_TX_PPDU_TOTAL_US 79 +#define WAL_DBGID_UPDATE_USED_TIME 80 +#define WAL_DBGID_PAST_WB_ACK_TIMESTAMP 81 +#define WAL_DBGID_WMMAC_ADD_DEL_TSPEC 82 +#define WAL_DBGID_WMMAC_TIMER_EXPIRY 83 +#define WAL_DBGID_WMMAC_PARAMS 84 +#define WAL_DBGID_TX_MGMT_WAL_PEER_DOES_NOT_EXIST 85 +#define WAL_DBGID_TX_MGMT_WAL_PEER_DELETE_IN_PROGRESS 86 +#define WAL_DBGID_TX_MGMT_FRAME_DESC_ALLOC_FAILED 87 +#define WAL_DBGID_TX_MGMT_TID_STRUCT_NOT_FOUND 88 +#define WAL_DBGID_TX_MGMT_ENQUEUE_FAILED 89 +#define WAL_DBGID_DEFINITION_END 90 + +#define ANI_DBGID_POLL 0 +#define ANI_DBGID_CONTROL 1 +#define ANI_DBGID_OFDM_PARAMS 2 +#define ANI_DBGID_CCK_PARAMS 3 +#define ANI_DBGID_RESET 4 +#define ANI_DBGID_RESTART 5 +#define ANI_DBGID_OFDM_LEVEL 6 +#define ANI_DBGID_CCK_LEVEL 7 +#define ANI_DBGID_FIRSTEP 8 +#define ANI_DBGID_CYCPWR 9 +#define ANI_DBGID_MRC_CCK 10 +#define ANI_DBGID_SELF_CORR_LOW 11 +#define ANI_DBGID_ENABLE 12 + +#define ANI_DBGID_CURRENT_LEVEL 13 +#define ANI_DBGID_POLL_PERIOD 14 +#define ANI_DBGID_LISTEN_PERIOD 15 +#define ANI_DBGID_OFDM_LEVEL_CFG 16 +#define ANI_DBGID_CCK_LEVEL_CFG 17 + +/* OFFLOAD Manager Debugids*/ +#define OFFLOAD_MGR_DBGID_DEFINITION_START 0 +#define OFFLOADMGR_REGISTER_OFFLOAD 1 +#define OFFLOADMGR_DEREGISTER_OFFLOAD 2 +#define OFFLOADMGR_NO_REG_DATA_HANDLERS 3 +#define OFFLOADMGR_NO_REG_EVENT_HANDLERS 4 +#define OFFLOADMGR_REG_OFFLOAD_FAILED 5 +#define OFFLOADMGR_DEREG_OFFLOAD_FAILED 6 +#define OFFLOADMGR_ENTER_FAILED 7 +#define OFFLOADMGR_EXIT_FAILED 8 +#define OFFLOADMGR_DBGID_DEFINITION_END 9 + +/*Resource Debug IDs*/ +#define RESOURCE_DBGID_DEFINITION_START 0 +#define RESOURCE_PEER_ALLOC 1 +#define RESOURCE_PEER_FREE 2 +#define RESOURCE_PEER_ALLOC_WAL_PEER 3 +#define RESOURCE_PEER_NBRHOOD_MGMT_ALLOC 4 +#define RESOURCE_PEER_NBRHOOD_MGMT_INFO 5 +#define RESOURCE_SMALL_MGMT_BUF_FULL 6 +#define RESOURCE_MGMT_AVAIL_BUF_CNT_NOT_ENOUGH 7 +#define RESOURCE_MGMT_BUF_FULL 8 +#define RESOURCE_MGMT_BUF_INC 9 +#define RESOURCE_MGMT_BUF_DEC 10 +#define RESOURCE_DBGID_DEFINITION_END 11 + +/* DCS debug IDs*/ +#define WLAN_DCS_DBGID_INIT 0 +#define WLAN_DCS_DBGID_WMI_CWINT 1 +#define WLAN_DCS_DBGID_TIMER 2 +#define WLAN_DCS_DBGID_CMDG 3 +#define WLAN_DCS_DBGID_CMDS 4 +#define WLAN_DCS_DBGID_DINIT 5 + +/*P2P Module ids*/ +#define P2P_DBGID_DEFINITION_START 0 +#define P2P_DEV_REGISTER 1 +#define P2P_HANDLE_NOA 2 +#define P2P_UPDATE_SCHEDULE_OPPS 3 +#define P2P_UPDATE_SCHEDULE 4 +#define P2P_UPDATE_START_TIME 5 +#define P2P_UPDATE_START_TIME_DIFF_TSF32 6 +#define P2P_UPDATE_START_TIME_FINAL 7 +#define P2P_SETUP_SCHEDULE_TIMER 8 +#define P2P_PROCESS_SCHEDULE_AFTER_CALC 9 +#define P2P_PROCESS_SCHEDULE_STARTED_TIMER 10 +#define P2P_CALC_SCHEDULES_FIRST_CALL_ALL_NEXT_EVENT 11 +#define P2P_CALC_SCHEDULES_FIRST_VALUE 12 +#define P2P_CALC_SCHEDULES_EARLIEST_NEXT_EVENT 13 +#define P2P_CALC_SCHEDULES_SANITY_COUNT 14 +#define P2P_CALC_SCHEDULES_CALL_ALL_NEXT_EVENT_FROM_WHILE_LOOP 15 +#define P2P_CALC_SCHEDULES_TIMEOUT_1 16 +#define P2P_CALC_SCHEDULES_TIMEOUT_2 17 +#define P2P_FIND_ALL_NEXT_EVENTS_REQ_EXPIRED 18 +#define P2P_FIND_ALL_NEXT_EVENTS_REQ_ACTIVE 19 +#define P2P_FIND_NEXT_EVENT_REQ_NOT_STARTED 20 +#define P2P_FIND_NEXT_EVENT_REQ_COMPLETE_NON_PERIODIC 21 +#define P2P_FIND_NEXT_EVENT_IN_MID_OF_NOA 22 +#define P2P_FIND_NEXT_EVENT_REQ_COMPLETE 23 +#define P2P_SCHEDULE_TIMEOUT 24 +#define P2P_CALC_SCHEDULES_ENTER 25 +#define P2P_PROCESS_SCHEDULE_ENTER 26 +#define P2P_FIND_ALL_NEXT_EVENTS_INDIVIDUAL_REQ_AFTER_CHANGE 27 +#define P2P_FIND_ALL_NEXT_EVENTS_INDIVIDUAL_REQ_BEFORE_CHANGE 28 +#define P2P_FIND_ALL_NEXT_EVENTS_ENTER 29 +#define P2P_FIND_NEXT_EVENT_ENTER 30 +#define P2P_NOA_GO_PRESENT 31 +#define P2P_NOA_GO_ABSENT 32 +#define P2P_GO_NOA_NOTIF 33 +#define P2P_GO_TBTT_OFFSET 34 +#define P2P_GO_GET_NOA_INFO 35 +#define P2P_GO_ADD_ONE_SHOT_NOA 36 +#define P2P_GO_GET_NOA_IE 37 +#define P2P_GO_BCN_TX_COMP 38 +#define P2P_DBGID_DEFINITION_END 39 + + +//CSA modules DBGIDs +#define CSA_DBGID_DEFINITION_START 0 +#define CSA_OFFLOAD_POOL_INIT 1 +#define CSA_OFFLOAD_REGISTER_VDEV 2 +#define CSA_OFFLOAD_DEREGISTER_VDEV 3 +#define CSA_DEREGISTER_VDEV_ERROR 4 +#define CSA_OFFLOAD_BEACON_RECEIVED 5 +#define CSA_OFFLOAD_BEACON_CSA_RECV 6 +#define CSA_OFFLOAD_CSA_RECV_ERROR_IE 7 +#define CSA_OFFLOAD_CSA_TIMER_ERROR 8 +#define CSA_OFFLOAD_CSA_TIMER_EXP 9 +#define CSA_OFFLOAD_WMI_EVENT_ERROR 10 +#define CSA_OFFLOAD_WMI_EVENT_SENT 11 +#define CSA_OFFLOAD_WMI_CHANSWITCH_RECV 12 +#define CSA_DBGID_DEFINITION_END 13 + +/* Chatter module DBGIDs */ +#define WLAN_CHATTER_DBGID_DEFINITION_START 0 +#define WLAN_CHATTER_ENTER 1 +#define WLAN_CHATTER_EXIT 2 +#define WLAN_CHATTER_FILTER_HIT 3 +#define WLAN_CHATTER_FILTER_MISS 4 +#define WLAN_CHATTER_FILTER_FULL 5 +#define WLAN_CHATTER_FILTER_TM_ADJ 6 +#define WLAN_CHATTER_BUFFER_FULL 7 +#define WLAN_CHATTER_TIMEOUT 8 +#define WLAN_CHATTER_MC_FILTER_ADD 9 +#define WLAN_CHATTER_MC_FILTER_DEL 10 +#define WLAN_CHATTER_MC_FILTER_ALLOW 11 +#define WLAN_CHATTER_MC_FILTER_DROP 12 +#define WLAN_CHATTER_COALESCING_FILTER_ADD 13 +#define WLAN_CHATTER_COALESCING_FILTER_DEL 14 +#define WLAN_CHATTER_DBGID_DEFINITION_END 15 + +#define WOW_DBGID_DEFINITION_START 0 +#define WOW_ENABLE_CMDID 1 +#define WOW_RECV_DATA_PKT 2 +#define WOW_WAKE_HOST_DATA 3 +#define WOW_RECV_MGMT 4 +#define WOW_WAKE_HOST_MGMT 5 +#define WOW_RECV_EVENT 6 +#define WOW_WAKE_HOST_EVENT 7 +#define WOW_INIT 8 +#define WOW_RECV_MAGIC_PKT 9 +#define WOW_RECV_BITMAP_PATTERN 10 +#define WOW_AP_VDEV_DISALLOW 11 +#define WOW_STA_VDEV_DISALLOW 12 +#define WOW_P2PGO_VDEV_DISALLOW 13 +#define WOW_NS_OFLD_ENABLE 14 +#define WOW_ARP_OFLD_ENABLE 15 +#define WOW_NS_ARP_OFLD_DISABLE 16 +#define WOW_NS_RECEIVED 17 +#define WOW_NS_REPLIED 18 +#define WOW_ARP_RECEIVED 19 +#define WOW_ARP_REPLIED 20 +#define WOW_BEACON_OFFLOAD_TX 21 +#define WOW_BEACON_OFFLOAD_CFG 22 +#define WOW_IBSS_VDEV_ALLOW 23 +#define WOW_DBGID_DEFINITION_END 24 + +/* SWBMISS module DBGIDs */ +#define SWBMISS_DBGID_DEFINITION_START 0 +#define SWBMISS_ENABLED 1 +#define SWBMISS_DISABLED 2 +#define SWBMISS_UPDATE_BEACON_RSSI 3 +#define SWBMISS_CHECK_RSSI_OUTLIER 4 +#define SWBMISS_TIMER_SET 5 +#define SWBMISS_DBGID_DEFINITION_END 6 + +/* WLAN module DBGIDS */ +#define ROAM_DBGID_DEFINITION_START 0 +#define ROAM_MODULE_INIT 1 +#define ROAM_DEV_START 2 +#define ROAM_CONFIG_RSSI_THRESH 3 +#define ROAM_CONFIG_SCAN_PERIOD 4 +#define ROAM_CONFIG_AP_PROFILE 5 +#define ROAM_CONFIG_CHAN_LIST 6 +#define ROAM_CONFIG_SCAN_PARAMS 7 +#define ROAM_CONFIG_RSSI_CHANGE 8 +#define ROAM_SCAN_TIMER_START 9 +#define ROAM_SCAN_TIMER_EXPIRE 10 +#define ROAM_SCAN_TIMER_STOP 11 +#define ROAM_SCAN_STARTED 12 +#define ROAM_SCAN_COMPLETE 13 +#define ROAM_SCAN_CANCELLED 14 +#define ROAM_CANDIDATE_FOUND 15 +#define ROAM_RSSI_ACTIVE_SCAN 16 +#define ROAM_RSSI_ACTIVE_ROAM 17 +#define ROAM_RSSI_GOOD 18 +#define ROAM_BMISS_FIRST_RECV 19 +#define ROAM_DEV_STOP 20 +#define ROAM_FW_OFFLOAD_ENABLE 21 +#define ROAM_CANDIDATE_SSID_MATCH 22 +#define ROAM_CANDIDATE_SECURITY_MATCH 23 +#define ROAM_LOW_RSSI_INTERRUPT 24 +#define ROAM_HIGH_RSSI_INTERRUPT 25 +#define ROAM_SCAN_REQUESTED 26 +#define ROAM_BETTER_CANDIDATE_FOUND 27 +#define ROAM_BETTER_AP_EVENT 28 +#define ROAM_CANCEL_LOW_PRIO_SCAN 29 +#define ROAM_FINAL_BMISS_RECVD 30 +#define ROAM_CONFIG_SCAN_MODE 31 +#define ROAM_BMISS_FINAL_SCAN_ENABLE 32 +#define ROAM_SUITABLE_AP_EVENT 33 +#define ROAM_RSN_IE_PARSE_ERROR 34 +#define ROAM_WPA_IE_PARSE_ERROR 35 +#define ROAM_SCAN_CMD_FROM_HOST 36 +#define ROAM_HO_SORT_CANDIDATE 37 +#define ROAM_HO_SAVE_CANDIDATE 38 +#define ROAM_HO_GET_CANDIDATE 39 +#define ROAM_HO_OFFLOAD_SET_PARAM 40 +#define ROAM_HO_SM 41 +#define ROAM_HO_HTT_SAVED 42 +#define ROAM_HO_SYNC_START 43 +#define ROAM_HO_START 44 +#define ROAM_HO_SYNC_COMPLETE 45 +#define ROAM_HO_STOP 46 +#define ROAM_HO_HTT_FORWARD 47 +#define ROAM_CONFIG_SCAN_PARAMS_1 48 +#define ROAM_SCAN_COMPLETE_1 49 +#define ROAM_SWBMISS_BCN_RECV_VAL 50 +#define ROAM_SWBMISS_BCN_RECV_THRE2 51 +#define ROAM_SCAN_REQUESTED_1 52 +#define ROAM_HO_SORT_CANDIDATE_CUR 53 +#define ROAM_HO_SAVE_CANDIDATE_DUP 54 +#define ROAM_HO_SM_EVENT 55 +#define ROAM_HO_ENTER_CH 56 +#define ROAM_HO_MGMT_RX 57 +#define ROAM_HO_CANDIDATE_INFO 58 +#define ROAM_HO_OFFLD_DATA_STORE 59 +#define ROAM_HO_HTT_DATA_STORE 60 +#define ROAM_HO_UPDATE_STATUS 61 +#define ROAM_HO_OCS_CH_CB 62 +#define ROAM_RSSI_INTERRUPT_STATE 63 +#define ROAM_INVOKE_PARAM_CHECK 64 +#define ROAM_INVOKE_PARAM_CHAN 65 +#define ROAM_INVOKE_PARAM_BSSID 66 +#define ROAM_INVOKE_STATE_CHECK 67 +#define ROAM_INVOKE_START_SUCCESS 68 +#define ROAM_INVOKE_START_FAILURE 69 +#define ROAM_INVOKE_BSSID_CHECK 70 +#define ROAM_CANDIDATE_INFO 71 +#define ROAM_CANDIDATE_FILTER_MATCH 72 +#define ROAM_CANDIDATE_RSSI_ADJUST 73 +#define ROAM_CONFIG_ROAM_FILTER 74 +#define ROAM_EXTENDED_RSSI_TRESHOLD_1 75 +#define ROAM_EXTENDED_RSSI_TRESHOLD_2 76 +#define ROAM_BLACKLIST_BSSID 77 +#define ROAM_WHITELIST_SSID 78 +#define ROAM_WHITELIST_SSID_2 79 +#define ROAM_PREFERRED_BSSID 80 +#define ROAM_PREFERRED_FACTOR 81 +#define ROAM_SCAN_HIRSSI_THRESHOLD 82 +#define ROAM_SCAN_HIRSSI_CHECK 83 +#define ROAM_SCAN_HIRSSI_TIMER_EXPIRED 84 +#define ROAM_SCAN_EXTSCAN_CHECK 85 +#define ROAM_DBGID_DEFINITION_END 86 + +/* DATA_TXRX module DBGIDs*/ +#define DATA_TXRX_DBGID_DEFINITION_START 0 +#define DATA_TXRX_DBGID_RX_DATA_SEQ_LEN_INFO 1 +#define DATA_TXRX_DBGID_REPLAY_CHECK 2 +#define DATA_TXRX_DBGID_DUP_CHECK 3 +#define DATA_TXRX_INVALID_PEER_AST_STA 4 +#define DATA_TXRX_INVALID_PEER_AST_P2P 5 +#define DATA_TXRX_INVALID_ADDR1_STA 6 +#define DATA_TXRX_INVALID_ADDR1_P2P 7 +#define DATA_TXRX_MULTICAST_BROADCAST_FRAME 8 +#define DATA_TXRX_INVALID_FRAME_CTRL_OR_ADDR 9 +#define DATA_TXRX_DBGID_DEFINITION_END 10 + +/* HTT module DBGIDs */ +#define HTT_DBGID_DEFINITION_START 0 +#define HTT_DBGID_INVALID_VDEVID_OR_GROUP 1 +#define HTT_DBGID_DISCARD_INTERNAL_PKTS 2 +#define HTT_DBGID_DISCARD_TX_PKTS 3 +#define HTT_DBGID_GROUP_CHANGE 4 +#define HTT_DBGID_GROUP_CREDIT_STATS 5 +#define HTT_DBGID_DISCARD_INTERNAL_PKTS_NUM 6 +#define HTT_DBGID_DEFINITION_END 7 + +/* TDLS module DBGIDs*/ +#define TDLS_DBGID_DEFINITION_START 0 +#define TDLS_DBGID_VDEV_CREATE 1 +#define TDLS_DBGID_VDEV_DELETE 2 +#define TDLS_DBGID_ENABLED_PASSIVE 3 +#define TDLS_DBGID_ENABLED_ACTIVE 4 +#define TDLS_DBGID_DISABLED 5 +#define TDLS_DBGID_CONNTRACK_TIMER 6 +#define TDLS_DBGID_WAL_SET 7 +#define TDLS_DBGID_WAL_GET 8 +#define TDLS_DBGID_WAL_PEER_UPDATE_SET 9 +#define TDLS_DBGID_WAL_PEER_UPDATE_EVT 10 +#define TDLS_DBGID_WAL_VDEV_CREATE 11 +#define TDLS_DBGID_WAL_VDEV_DELETE 12 +#define TDLS_DBGID_WLAN_EVENT 13 +#define TDLS_DBGID_WLAN_PEER_UPDATE_SET 14 +#define TDLS_DBGID_PEER_EVT_DRP_THRESH 15 +#define TDLS_DBGID_PEER_EVT_DRP_RATE 16 +#define TDLS_DBGID_PEER_EVT_DRP_RSSI 17 +#define TDLS_DBGID_PEER_EVT_DISCOVER 18 +#define TDLS_DBGID_PEER_EVT_DELETE 19 +#define TDLS_DBGID_PEER_CAP_UPDATE 20 +#define TDLS_DBGID_UAPSD_SEND_PTI_FRAME 21 +#define TDLS_DBGID_UAPSD_SEND_PTI_FRAME2PEER 22 +#define TDLS_DBGID_UAPSD_START_PTR_TIMER 23 +#define TDLS_DBGID_UAPSD_CANCEL_PTR_TIMER 24 +#define TDLS_DBGID_UAPSD_PTR_TIMER_TIMEOUT 25 +#define TDLS_DBGID_UAPSD_STA_PS_EVENT_HANDLER 26 +#define TDLS_DBGID_UAPSD_PEER_EVENT_HANDLER 27 +#define TDLS_DBGID_UAPSD_PS_DEFAULT_SETTINGS 28 +#define TDLS_DBGID_UAPSD_GENERIC 29 + + +/* TXBF Module IDs */ +#define TXBFEE_DBGID_START 0 +#define TXBFEE_DBGID_NDPA_RECEIVED 1 +#define TXBFEE_DBGID_HOST_CONFIG_TXBFEE_TYPE 2 +#define TXBFER_DBGID_SEND_NDPA 3 +#define TXBFER_DBGID_GET_NDPA_BUF_FAIL 4 +#define TXBFER_DBGID_SEND_NDPA_FAIL 5 +#define TXBFER_DBGID_GET_NDP_BUF_FAIL 6 +#define TXBFER_DBGID_SEND_NDP_FAIL 7 +#define TXBFER_DBGID_GET_BRPOLL_BUF_FAIL 8 +#define TXBFER_DBGID_SEND_BRPOLL_FAIL 9 +#define TXBFER_DBGID_HOST_CONFIG_CMDID 10 +#define TXBFEE_DBGID_HOST_CONFIG_CMDID 11 +#define TXBFEE_DBGID_ENABLE_UPLOAD_H 12 +#define TXBFEE_DBGID_UPLOADH_CV_TAG 13 +#define TXBFEE_DBGID_UPLOADH_H_TAG 14 +#define TXBFEE_DBGID_CAPTUREH_RECEIVED 15 +#define TXBFEE_DBGID_PACKET_IS_STEERED 16 +#define TXBFEE_UPLOADH_EVENT_ALLOC_MEM_FAIL 17 +#define TXBFEE_DBGID_SW_WAR_AID_ZERO 18 +#define TXBFEE_DBGID_BRPOLL_RECEIVED 19 +#define TXBFEE_DBGID_GID_RECEIVED 20 +#define TXBFEE_DBGID_END 21 + +/* SMPS module DBGIDs */ +#define STA_SMPS_DBGID_DEFINITION_START 0 +#define STA_SMPS_DBGID_CREATE_PDEV_INSTANCE 1 +#define STA_SMPS_DBGID_CREATE_VIRTUAL_CHAN_INSTANCE 2 +#define STA_SMPS_DBGID_DELETE_VIRTUAL_CHAN_INSTANCE 3 +#define STA_SMPS_DBGID_CREATE_STA_INSTANCE 4 +#define STA_SMPS_DBGID_DELETE_STA_INSTANCE 5 +#define STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_START 6 +#define STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_STOP 7 +#define STA_SMPS_DBGID_SEND_SMPS_ACTION_FRAME 8 +#define STA_SMPS_DBGID_HOST_FORCED_MODE 9 +#define STA_SMPS_DBGID_FW_FORCED_MODE 10 +#define STA_SMPS_DBGID_RSSI_THRESHOLD_CROSSED 11 +#define STA_SMPS_DBGID_SMPS_ACTION_FRAME_COMPLETION 12 +#define STA_SMPS_DBGID_DTIM_EBT_EVENT_CHMASK_UPDATE 13 +#define STA_SMPS_DBGID_DTIM_CHMASK_UPDATE 14 +#define STA_SMPS_DBGID_DTIM_BEACON_EVENT_CHMASK_UPDATE 15 +#define STA_SMPS_DBGID_DTIM_POWER_STATE_CHANGE 16 +#define STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_SLEEP 17 +#define STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_AWAKE 18 + +#define STA_SMPS_DBGID_DEFINITION_END 18 + +/* RTT module DBGIDs*/ +#define RTT_CALL_FLOW 0 +#define RTT_REQ_SUB_TYPE 1 +#define RTT_MEAS_REQ_HEAD 2 +#define RTT_MEAS_REQ_BODY 3 +#define RTT_INIT_GLOBAL_STATE 6 +#define RTT_REPORT 8 +#define RTT_ERROR_REPORT 10 +#define RTT_TIMER_STOP 11 +#define RTT_SEND_TM_FRAME 12 +#define RTT_V3_RESP_CNT 13 +#define RTT_V3_RESP_FINISH 14 +#define RTT_CHANNEL_SWITCH_REQ 15 +#define RTT_CHANNEL_SWITCH_GRANT 16 +#define RTT_CHANNEL_SWITCH_COMPLETE 17 +#define RTT_CHANNEL_SWITCH_PREEMPT 18 +#define RTT_CHANNEL_SWITCH_STOP 19 +#define RTT_TIMER_START 20 +#define RTT_FTM_PARAM_INFO 21 +#define RTT_RX_TM_FRAME 22 +#define RTT_INITR_TSTAMP 23 +#define RTT_RSPDR_TSTAMP 24 +#define RTT_TX_COMP_STATUS 25 +#define RTT_ERROR_WMI_EVENT 26 +#define RTT_MEASUREMENT_VALUES 27 + +/* WLAN HB module DBGIDs */ +#define WLAN_HB_DBGID_DEFINITION_START 0 +#define WLAN_HB_DBGID_INIT 1 +#define WLAN_HB_DBGID_TCP_GET_TXBUF_FAIL 2 +#define WLAN_HB_DBGID_TCP_SEND_FAIL 3 +#define WLAN_HB_DBGID_BSS_PEER_NULL 4 +#define WLAN_HB_DBGID_UDP_GET_TXBUF_FAIL 5 +#define WLAN_HB_DBGID_UDP_SEND_FAIL 6 +#define WLAN_HB_DBGID_WMI_CMD_INVALID_PARAM 7 +#define WLAN_HB_DBGID_WMI_CMD_INVALID_OP 8 +#define WLAN_HB_DBGID_WOW_NOT_ENTERED 9 +#define WLAN_HB_DBGID_ALLOC_SESS_FAIL 10 +#define WLAN_HB_DBGID_CTX_NULL 11 +#define WLAN_HB_DBGID_CHKSUM_ERR 12 +#define WLAN_HB_DBGID_UDP_TX 13 +#define WLAN_HB_DBGID_TCP_TX 14 +#define WLAN_HB_DBGID_DEFINITION_END 15 + +/* Thermal Manager DBGIDs*/ +#define THERMAL_MGR_DBGID_DEFINITION_START 0 +#define THERMAL_MGR_NEW_THRESH 1 +#define THERMAL_MGR_THRESH_CROSSED 2 +#define THERMAL_MGR_DBGID_DEFINITION_END 3 + +/* WLAN PHYERR DFS(parse/filter) DBGIDs */ +#define WLAN_PHYERR_DFS_DBGID_DEFINITION_START 0 +#define WLAN_PHYERR_DFS_PHYERR_INFO_CHAN_BUFLEN 1 +#define WLAN_PHYERR_DFS_PHYERR_INFO_PPDU 2 +#define WLAN_PHYERR_DFS_DBDID_RADAR_SUMMARY 3 +#define WLAN_PHYERR_DFS_DBDID_SEARCH_FFT 4 +#define WLAN_PHTERR_DFS_DBDID_FILTER_STATUS 5 +#define WLAN_PHYERR_DFS_DBGID_DEFINITION_END 6 + +/* RMC DBGIDs */ +#define RMC_DBGID_DEFINITION_START 0 +#define RMC_SM_INIT_ERR 1 +#define RMC_VDEV_ALLOC_ERR 2 +#define RMC_CREATE_INSTANCE 3 +#define RMC_DELETE_INSTANCE 4 +#define RMC_NEW_PRI_LEADER 5 +#define RMC_NEW_SEC_LEADER 6 +#define RMC_NO_LDR_CHANGE 7 +#define RMC_LDR_INFORM_SENT 8 +#define RMC_PEER_ADD 9 +#define RMC_PEER_DELETE 10 +#define RMC_PEER_UNKNOWN 11 +#define RMC_PRI_LDR_RSSI_UPDATE 12 +#define RMC_SEC_LDR_RSSI_UPDATE 13 +#define RMC_SET_MODE 14 +#define RMC_SET_ACTION_PERIOD 15 +#define RMC_DBGID_DEFINITION_END 16 + +/* UNIT_TEST module DBGIDs */ +#define UNIT_TEST_GEN 0 + +/* MLME module DBGIDs */ +#define MLME_DEBUG_CMN 0 +#define MLME_DEBUG_IF 1 +#define MLME_DEBUG_AUTH 2 +#define MLME_DEBUG_REASSOC 3 +#define MLME_DEBUG_DEAUTH 4 +#define MLME_DEBUG_DISASSOC 5 +#define MLME_DEBUG_ROAM 6 +#define MLME_DEBUG_RETRY 7 +#define MLME_DEBUG_TIMER 8 +#define MLME_DEBUG_FRAMEPARSE 9 + +/* SUPPL module DBGIDs */ +#define SUPPL_DBGID_INIT 0 +#define SUPPL_DBGID_RECV_EAPOL 1 +#define SUPPL_DBGID_RECV_EAPOL_TIMEOUT 2 +#define SUPPL_DBGID_SEND_EAPOL 3 +#define SUPPL_DBGID_MIC_MISMATCH 4 +#define SUPPL_DBGID_FINISH 5 +#define SUPPL_DBGID_GET_FRM_INFO 6 +#define SUPPL_DBGID_DUMP_TYPE 7 +#define SUPPL_DBGID_DUMP_HEX 8 +#define SUPPL_DBGID_NODE_NOT_FOUND 9 +#define SUPPL_DBGID_GET_EAPOL_BUF 10 +#define SUPPL_DBGID_GET_BUF_FAIL 11 +#define SUPPL_DBGID_RECV_EAPOL_ERROR 12 + +/* Stats Module DBGIDs */ +#define WLAN_STATS_DBGID_DEFINITION_START 0 +#define WLAN_STATS_DBGID_EST_LINKSPEED_VDEV_EN_DIS 1 +#define WLAN_STATS_DBGID_EST_LINKSPEED_CHAN_TIME_START 2 +#define WLAN_STATS_DBGID_EST_LINKSPEED_CHAN_TIME_END 3 +#define WLAN_STATS_DBGID_EST_LINKSPEED_CALC 4 +#define WLAN_STATS_DBGID_EST_LINKSPEED_UPDATE_HOME_CHAN 5 +#define WLAN_STATS_DBGID_DEFINITION_END 6 +/* NAN DBGIDs */ +#define NAN_DBGID_START 0 + +/* Debug IDs for debug logs. 3 args max, not fixed. */ +#define NAN_DBGID_DBG_LOG_FIRST 1 +#define NAN_DBGID_FUNC_BEGIN NAN_DBGID_DBG_LOG_FIRST +#define NAN_DBGID_FUNC_END 2 +#define NAN_DBGID_MAIN_DEBUG 3 +#define NAN_DBGID_MAC_DEBUG 4 +#define NAN_DBGID_BLOOM_FILTER_DEBUG 5 +#define NAN_DBGID_MAC_ADDR 6 +#define NAN_DBGID_PARAM_UPDATED 7 +#define NAN_DBGID_NULL_PTR 8 +#define NAN_DBGID_INVALID_FUNC_ARG 9 +#define NAN_DBGID_INVALID_MSG_PARAM 10 +#define NAN_DBGID_MISSING_MSG_PARAM 11 +#define NAN_DBGID_DEPRECATED_MSG_PARAM 12 +#define NAN_DBGID_UNSUPPORTED_MSG_PARAM 13 +#define NAN_DBGID_INVALID_PKT_DATA 14 +#define NAN_DBGID_LOG_PKT_DATA 15 +#define NAN_DBGID_INVALID_VALUE 16 +#define NAN_DBGID_INVALID_OPERATION 17 +#define NAN_DBGID_INVALID_STATE 18 +#define NAN_DBGID_FUNCTION_ENABLED 19 +#define NAN_DBGID_FUNCTION_DISABLED 20 +#define NAN_DBGID_INVALID_FUNCTION_STATE 21 +#define NAN_DBGID_READ_ERROR 22 +#define NAN_DBGID_WRITE_ERROR 23 +#define NAN_DBGID_RECEIVE_ERROR 24 +#define NAN_DBGID_TRANSMIT_ERROR 25 +#define NAN_DBGID_PARSE_ERROR 26 +#define NAN_DBGID_RES_ALLOC_ERROR 27 +/* PLEASE KEEP THIS ONE AT THE END */ +#define NAN_DBGID_DBG_LOG_LAST 28 + +/* Debug IDs for event logs. */ + +#define NAN_DBGID_EVT_BASE NAN_DBGID_DBG_LOG_LAST +/* args: */ +#define NAN_DBGID_NAN_ENABLED (NAN_DBGID_EVT_BASE + 0) +/* args: */ +#define NAN_DBGID_NAN_DISABLED (NAN_DBGID_EVT_BASE + 1) +/* args: */ +#define NAN_DBGID_CONFIG_RESTORED (NAN_DBGID_EVT_BASE + 2) +/* args: framesQueued */ +#define NAN_DBGID_SDF_QUEUED (NAN_DBGID_EVT_BASE + 3) +/* args: old, new */ +#define NAN_DBGID_TW_CHANGED (NAN_DBGID_EVT_BASE + 4) +/* args: */ +#define NAN_DBGID_DW_START (NAN_DBGID_EVT_BASE + 5) +/* args: busyDiff */ +#define NAN_DBGID_DW_END (NAN_DBGID_EVT_BASE + 6) +/* args: oldClusterId, newClusterId */ +#define NAN_DBGID_CLUSTER_ID_CHANGED (NAN_DBGID_EVT_BASE + 7) +/* args: cmd, buffer, length */ +#define NAN_DBGID_WMI_CMD_RECEIVED (NAN_DBGID_EVT_BASE + 8) +/* args: pEventPkt, pEventBuf, eventSize, dataSize */ +#define NAN_DBGID_WMI_EVT_SENT (NAN_DBGID_EVT_BASE + 9) +/* args: type length, readLen */ +#define NAN_DBGID_TLV_READ (NAN_DBGID_EVT_BASE + 10) +/* args: type length, writeLen */ +#define NAN_DBGID_TLV_WRITE (NAN_DBGID_EVT_BASE + 11) +/* args: handle */ +#define NAN_DBGID_PUBSUB_UPDATED (NAN_DBGID_EVT_BASE + 12) +/* args: handle */ +#define NAN_DBGID_PUBSUB_REMOVE_DEFERED (NAN_DBGID_EVT_BASE + 13) +/* args: handle */ +#define NAN_DBGID_PUBSUB_REMOVE_PENDING (NAN_DBGID_EVT_BASE + 14) +/* args: handle */ +#define NAN_DBGID_PUBSUB_REMOVED (NAN_DBGID_EVT_BASE + 15) +/* args: handle */ +#define NAN_DBGID_PUBSUB_PROCESSED (NAN_DBGID_EVT_BASE + 16) +/* args: handle, sid1, sid2, svcCtrl, length */ +#define NAN_DBGID_PUBSUB_MATCHED (NAN_DBGID_EVT_BASE + 17) +/* args: handle, flags */ +#define NAN_DBGID_PUBSUB_PREPARED (NAN_DBGID_EVT_BASE + 18) +/* args: handle, mac1, mac2 */ +#define NAN_DBGID_PUBSUB_FOLLOWUP_TRANSMIT (NAN_DBGID_EVT_BASE + 19) +/* args: handle, mac1, mac2 */ +#define NAN_DBGID_PUBSUB_FOLLOWUP_RECEIVED (NAN_DBGID_EVT_BASE + 20) +/* args: subscribeHandle, matchHandle, oldTimeout, newTimeout */ +#define NAN_DBGID_SUBSCRIBE_UNMATCH_TIMEOUT_UPDATE (NAN_DBGID_EVT_BASE + 21) +/* args: subscribeHandle, matchHandle, timestamp*/ +#define NAN_DBGID_SUBSCRIBE_MATCH_NEW (NAN_DBGID_EVT_BASE + 22) +/* args: subscribeHandle, matchHandle, timestamp*/ +#define NAN_DBGID_SUBSCRIBE_MATCH_REPEAT (NAN_DBGID_EVT_BASE + 23) +/* args: subscribeHandle, matchHandle, matchTimestamp, timestamp*/ +#define NAN_DBGID_SUBSCRIBE_MATCH_EXPIRED (NAN_DBGID_EVT_BASE + 24) +/* args: subscribeHandle, matchHandle, matchTimestamp, timestamp */ +#define NAN_DBGID_SUBSCRIBE_MATCH_LOG (NAN_DBGID_EVT_BASE + 25) +/* args: sid1, sid2 */ +#define NAN_DBGID_SERVICE_ID_CREATED (NAN_DBGID_EVT_BASE + 26) +/* args: size */ +#define NAN_DBGID_SD_ATTR_BUILT (NAN_DBGID_EVT_BASE + 27) +/* args: offset */ +#define NAN_DBGID_SERVICE_RSP_OFFSET (NAN_DBGID_EVT_BASE + 28) +/* args: offset */ +#define NAN_DBGID_SERVICE_INFO_OFFSET (NAN_DBGID_EVT_BASE + 29) +/* args: chan, interval, start_time */ +#define NAN_DBGID_CHREQ_CREATE (NAN_DBGID_EVT_BASE + 30) +/* args: start_time, status */ +#define NAN_DBGID_CHREQ_UPDATE (NAN_DBGID_EVT_BASE + 31) +/* args: chan, interval, status */ +#define NAN_DBGID_CHREQ_REMOVE (NAN_DBGID_EVT_BASE + 32) +/* args: type, timestamp */ +#define NAN_DBGID_CHREQ_GRANT (NAN_DBGID_EVT_BASE + 33) +/* args: type, timestamp */ +#define NAN_DBGID_CHREQ_END (NAN_DBGID_EVT_BASE + 34) +/* args: type, timestamp */ +#define NAN_DBGID_CHREQ_ERROR (NAN_DBGID_EVT_BASE + 35) +/* args: type, length, timestamp, rssi */ +#define NAN_DBGID_RX_CALLBACK (NAN_DBGID_EVT_BASE + 36) +/* args: type, handle, bufp, status, timestamp */ +#define NAN_DBGID_TX_COMPLETE (NAN_DBGID_EVT_BASE + 37) +/* args: tsf, tsf */ +#define NAN_DBGID_TSF_TIMEOUT (NAN_DBGID_EVT_BASE + 38) +/* args: clusterId, clusterStart */ +#define NAN_DBGID_SYNC_START (NAN_DBGID_EVT_BASE + 39) +/* args: clusterId */ +#define NAN_DBGID_SYNC_STOP (NAN_DBGID_EVT_BASE + 40) +/* args: enable, scanType, rval */ +#define NAN_DBGID_NAN_SCAN (NAN_DBGID_EVT_BASE + 41) +/* args: scanType */ +#define NAN_DBGID_NAN_SCAN_COMPLETE (NAN_DBGID_EVT_BASE + 42) +/* args: masterPref */ +#define NAN_DBGID_MPREF_CHANGE (NAN_DBGID_EVT_BASE + 43) +/* args: masterPref, randFactor */ +#define NAN_DBGID_WARMUP_EXPIRE (NAN_DBGID_EVT_BASE + 44) +/* args: randFactor */ +#define NAN_DBGID_RANDOM_FACTOR_EXPIRE (NAN_DBGID_EVT_BASE + 45) +/* args: tsf, tsf */ +#define NAN_DBGID_DW_SKIP (NAN_DBGID_EVT_BASE + 46) +/* args: type, tsfDiff */ +#define NAN_DBGID_DB_SKIP (NAN_DBGID_EVT_BASE + 47) +/* args: TBD */ +#define NAN_DBGID_BEACON_RX (NAN_DBGID_EVT_BASE + 48) +/* args: TBD */ +#define NAN_DBGID_BEACON_TX (NAN_DBGID_EVT_BASE + 49) +/* args: clusterId */ +#define NAN_DBGID_CLUSTER_MERGE (NAN_DBGID_EVT_BASE + 50) +/* args: cmd, status, value */ +#define NAN_DBGID_TEST_CMD_EXEC (NAN_DBGID_EVT_BASE + 51) +/* args: tsfHi, tsfLo, age */ +#define NAN_DBGID_APPLY_BEACON_TSF (NAN_DBGID_EVT_BASE + 52) +/* args: behindFlag, diff */ +#define NAN_DBGID_TSF_UPDATE (NAN_DBGID_EVT_BASE + 53) +/* args: argc==4 (rawTsfHi, rawTsfLo, nanTsfHi, nanTsfLo), argc==2(offsetHi, offsetLo) */ +#define NAN_DBGID_SET_TSF (NAN_DBGID_EVT_BASE + 54) +/* args: rankHi, rankLo, mp, rf */ +#define NAN_DBGID_NEW_MASTERRANK (NAN_DBGID_EVT_BASE + 55) +/* args: amRankHi, amRankLo, mp, rf */ +#define NAN_DBGID_NEW_ANCHORMASTER (NAN_DBGID_EVT_BASE + 56) +/* args: amRankHi, amRankLo, HC, BTT */ +#define NAN_DBGID_ANCHORMASTER_RECORD_UPDATE (NAN_DBGID_EVT_BASE + 57) +/* args: amRankHi, amRankLo, HC, BTT */ +#define NAN_DBGID_ANCHORMASTER_RECORD_EXPIRED (NAN_DBGID_EVT_BASE + 58) +/* args: reason, transitionsToAM */ +#define NAN_DBGID_BECOMING_ANCHORMASTER (NAN_DBGID_EVT_BASE + 59) +/* args: oldRole, newRole */ +#define NAN_DBGID_ROLE_CHANGE (NAN_DBGID_EVT_BASE + 60) +/* args: TBD */ +#define NAN_DBGID_SYNC_BEACON_DW_STATS (NAN_DBGID_EVT_BASE + 61) +/* args: attrId */ +#define NAN_DBGID_RX_UNSUPPORTED_SDF_ATTR_ID (NAN_DBGID_EVT_BASE + 62) +/* args: handle, sid1, sid2, svcCtrl, length */ +#define NAN_DBGID_PUBSUB_MATCHED_SKIPPED_SSI (NAN_DBGID_EVT_BASE + 63) +/* args: offset */ +#define NAN_DBGID_MATCH_FILTER_OFFSET (NAN_DBGID_EVT_BASE + 64) +/* args: twSize, n, twIndex */ +#define NAN_DBGID_TW_PARAMS (NAN_DBGID_EVT_BASE + 65) +/* args: */ +#define NAN_DBGID_BEACON_SENDER (NAN_DBGID_EVT_BASE + 66) +/* args: currTsf, nextDwTsf */ +#define NAN_DBGID_TSF_DUMP (NAN_DBGID_EVT_BASE + 67) +/* args: chan, startSlot, numSlots, repeat */ +#define NAN_DBGID_FAW_CONFIG (NAN_DBGID_EVT_BASE + 68) +/* args: */ +#define NAN_DBGID_FAW_START (NAN_DBGID_EVT_BASE + 69) +/* args: */ +#define NAN_DBGID_FAW_END (NAN_DBGID_EVT_BASE + 70) +/* args: offset, oldval, newval */ +#define NAN_DBGID_CONFIG_PARAM_CHANGED (NAN_DBGID_EVT_BASE + 71) +/* args: */ +#define NAN_DBGID_CONN_CAP_ATTR_CLEARED (NAN_DBGID_EVT_BASE + 72) +/* args: connType */ +#define NAN_DBGID_POST_DISC_ATTR_CLEARED (NAN_DBGID_EVT_BASE + 73) +/* args: */ +#define NAN_DBGID_VENDOR_SPECIFIC_ATTR_CLEARED (NAN_DBGID_EVT_BASE + 74) +/* args: offset */ +#define NAN_DBGID_WLAN_INFRA_MAP_CTRL_OFFSET (NAN_DBGID_EVT_BASE + 75) +/* args: offset */ +#define NAN_DBGID_WLAN_INFRA_AI_BITMAP_OFFSET (NAN_DBGID_EVT_BASE + 76) +/* args: offset */ +#define NAN_DBGID_WLAN_INFRA_DEVICE_ROLE_OFFSET (NAN_DBGID_EVT_BASE + 77) +/* args: offset */ +#define NAN_DBGID_MESH_ID_OFFSET (NAN_DBGID_EVT_BASE + 78) +/* args: */ +#define NAN_DBGID_SPARE_79 (NAN_DBGID_EVT_BASE + 79) +/* args: */ +#define NAN_DBGID_SPARE_80 (NAN_DBGID_EVT_BASE + 80) +/* args: */ +#define NAN_DBGID_SPARE_81 (NAN_DBGID_EVT_BASE + 81) +/* args: */ +#define NAN_DBGID_SPARE_82 (NAN_DBGID_EVT_BASE + 82) +/* args: */ +#define NAN_DBGID_SPARE_83 (NAN_DBGID_EVT_BASE + 83) +/* PLEASE KEEP THIS ONE AT THE END */ +#define NAN_DBGID_EVT_LOG_LAST (NAN_DBGID_EVT_BASE + 84) + +/* Debug IDs for message logs. */ +#define NAN_DBGID_API_MSG_BASE NAN_DBGID_EVT_LOG_LAST +#define NAN_DBGID_API_MSG_HEADER (NAN_DBGID_API_MSG_BASE + 0) +#define NAN_DBGID_API_MSG_DATA (NAN_DBGID_API_MSG_BASE + 1) +#define NAN_DBGID_API_MSG_LAST (NAN_DBGID_API_MSG_BASE + 2) + +/* Debug IDs for packet logs. */ +#define NAN_DBGID_OTA_PKT_BASE NAN_DBGID_API_MSG_LAST +#define NAN_DBGID_OTA_PKT_HEADER (NAN_DBGID_OTA_PKT_BASE + 0) +#define NAN_DBGID_OTA_PKT_DATA (NAN_DBGID_OTA_PKT_BASE + 1) +#define NAN_DBGID_OTA_PKT_LAST (NAN_DBGID_OTA_PKT_BASE + 2) /* not really the last! */ + +#define NAN_DBGID_BEACON_RX_TIMES (NAN_DBGID_OTA_PKT_LAST + 0) +#define NAN_DBGID_BEACON_RX_MANDATORY_ATTRS (NAN_DBGID_OTA_PKT_LAST + 1) +#define NAN_DBGID_BEACON_RX_SID_ATTR (NAN_DBGID_OTA_PKT_LAST + 2) +#define NAN_DBGID_BEACON_RX_VSA_ATTR (NAN_DBGID_OTA_PKT_LAST + 3) +#define NAN_DBGID_BEACON_RX_AVG_RSSI (NAN_DBGID_OTA_PKT_LAST + 4) +#define NAN_DBGID_CANDIDATE_BEACONS (NAN_DBGID_OTA_PKT_LAST + 5) +#define NAN_DBGID_TSF_OFFSET (NAN_DBGID_OTA_PKT_LAST + 6) +#define NAN_DBGID_ANCHORMASTER_RECORD_UPDATE_LAST (NAN_DBGID_OTA_PKT_LAST + 7) +#define NAN_DBGID_ANCHORMASTER_RECORD_EXPIRED2 (NAN_DBGID_OTA_PKT_LAST + 8) +#define NAN_DBGID_BEACON_TX_SEND (NAN_DBGID_OTA_PKT_LAST + 9) +#define NAN_DBGID_BEACON_TX_CANCEL (NAN_DBGID_OTA_PKT_LAST + 10) +#define NAN_DBGID_NAN_SCAN_EVENT (NAN_DBGID_OTA_PKT_LAST + 11) +#define NAN_DBGID_NAN_SDF_QUEUED (NAN_DBGID_OTA_PKT_LAST + 12) +#define NAN_DBGID_NAN_BEACON_QUEUED (NAN_DBGID_OTA_PKT_LAST + 13) +#define NAN_DBGID_NAN_NOT_ALLOWED (NAN_DBGID_OTA_PKT_LAST + 14) +#define NAN_DBGID_NAN_TX_FOLLOWUP_REQ_TR_ID (NAN_DBGID_OTA_PKT_LAST + 15) +#define NAN_DBGID_NAN_TX_FOLLOWUP_RESP_TR_ID (NAN_DBGID_OTA_PKT_LAST + 16) + +#define NAN_DBGID_END (NAN_DBGID_NAN_TX_FOLLOWUP_RESP_TR_ID + 1) + +/* IBSS PS module DBGIDs*/ +#define IBSS_PS_DBGID_DEFINITION_START 0 +#define IBSS_PS_DBGID_PEER_CREATE 1 +#define IBSS_PS_DBGID_PEER_DELETE 2 +#define IBSS_PS_DBGID_VDEV_CREATE 3 +#define IBSS_PS_DBGID_VDEV_DELETE 4 +#define IBSS_PS_DBGID_VDEV_EVENT 5 +#define IBSS_PS_DBGID_PEER_EVENT 6 +#define IBSS_PS_DBGID_DELIVER_CAB 7 +#define IBSS_PS_DBGID_DELIVER_UC_DATA 8 +#define IBSS_PS_DBGID_DELIVER_UC_DATA_ERROR 9 +#define IBSS_PS_DBGID_UC_INACTIVITY_TMR_RESTART 10 +#define IBSS_PS_DBGID_MC_INACTIVITY_TMR_RESTART 11 +#define IBSS_PS_DBGID_NULL_TX_COMPLETION 12 +#define IBSS_PS_DBGID_ATIM_TIMER_START 13 +#define IBSS_PS_DBGID_UC_ATIM_SEND 14 +#define IBSS_PS_DBGID_BC_ATIM_SEND 15 +#define IBSS_PS_DBGID_UC_TIMEOUT 16 +#define IBSS_PS_DBGID_PWR_COLLAPSE_ALLOWED 17 +#define IBSS_PS_DBGID_PWR_COLLAPSE_NOT_ALLOWED 18 +#define IBSS_PS_DBGID_SET_PARAM 19 +#define IBSS_PS_DBGID_HOST_TX_PAUSE 20 +#define IBSS_PS_DBGID_HOST_TX_UNPAUSE 21 +#define IBSS_PS_DBGID_PS_DESC_BIN_HWM 22 +#define IBSS_PS_DBGID_PS_DESC_BIN_LWM 23 +#define IBSS_PS_DBGID_PS_KICKOUT_PEER 24 +#define IBSS_PS_DBGID_SET_PEER_PARAM 25 +#define IBSS_PS_DBGID_BCN_ATIM_WIN_MISMATCH 26 +#define IBSS_PS_DBGID_RX_CHAINMASK_CHANGE 27 + +/* HIF UART Interface DBGIDs */ +#define HIF_UART_DBGID_START 0 +#define HIF_UART_DBGID_POWER_STATE 1 +#define HIF_UART_DBGID_TXRX_FLOW 2 +#define HIF_UART_DBGID_TXRX_CTRL_CHAR 3 +#define HIF_UART_DBGID_TXRX_BUF_DUMP 4 + +/* EXTSCAN DBGIDs */ +#define EXTSCAN_START 0 +#define EXTSCAN_STOP 1 +#define EXTSCAN_CLEAR_ENTRY_CONTENT 2 +#define EXTSCAN_GET_FREE_ENTRY_SUCCESS 3 +#define EXTSCAN_GET_FREE_ENTRY_INCONSISTENT 4 +#define EXTSCAN_GET_FREE_ENTRY_NO_MORE_ENTRIES 5 +#define EXTSCAN_CREATE_ENTRY_SUCCESS 6 +#define EXTSCAN_CREATE_ENTRY_ERROR 7 +#define EXTSCAN_SEARCH_SCAN_ENTRY_QUEUE 8 +#define EXTSCAN_SEARCH_SCAN_ENTRY_KEY_FOUND 9 +#define EXTSCAN_SEARCH_SCAN_ENTRY_KEY_NOT_FOUND 10 +#define EXTSCAN_ADD_ENTRY 11 +#define EXTSCAN_BUCKET_SEND_OPERATION_EVENT 12 +#define EXTSCAN_BUCKET_SEND_OPERATION_EVENT_FAILED 13 +#define EXTSCAN_BUCKET_START_SCAN_CYCLE 14 +#define EXTSCAN_BUCKET_PERIODIC_TIMER 15 +#define EXTSCAN_SEND_START_STOP_EVENT 16 +#define EXTSCAN_NOTIFY_WLAN_CHANGE 17 +#define EXTSCAN_NOTIFY_WLAN_HOTLIST_MATCH 18 +#define EXTSCAN_MAIN_RECEIVED_FRAME 19 +#define EXTSCAN_MAIN_NO_SSID_IE 20 +#define EXTSCAN_MAIN_MALFORMED_FRAME 21 +#define EXTSCAN_FIND_BSSID_BY_REFERENCE 22 +#define EXTSCAN_FIND_BSSID_BY_REFERENCE_ERROR 23 +#define EXTSCAN_NOTIFY_TABLE_USAGE 24 +#define EXTSCAN_FOUND_RSSI_ENTRY 25 +#define EXTSCAN_BSSID_FOUND_RSSI_SAMPLE 26 +#define EXTSCAN_BSSID_ADDED_RSSI_SAMPLE 27 +#define EXTSCAN_BSSID_REPLACED_RSSI_SAMPLE 28 +#define EXTSCAN_BSSID_TRANSFER_CURRENT_SAMPLES 29 +#define EXTSCAN_BUCKET_PROCESS_SCAN_EVENT 30 +#define EXTSCAN_BUCKET_CANNOT_FIND_BUCKET 31 +#define EXTSCAN_START_SCAN_REQUEST_FAILED 32 +#define EXTSCAN_BUCKET_STOP_CURRENT_SCANS 33 +#define EXTSCAN_BUCKET_SCAN_STOP_REQUEST 34 +#define EXTSCAN_BUCKET_PERIODIC_TIMER_ERROR 35 +#define EXTSCAN_BUCKET_START_OPERATION 36 +#define EXTSCAN_START_INTERNAL_ERROR 37 +#define EXTSCAN_NOTIFY_HOTLIST_MATCH 38 +#define EXTSCAN_CONFIG_HOTLIST_TABLE 39 +#define EXTSCAN_CONFIG_WLAN_CHANGE_TABLE 40 + +/* NLO DBGIDs */ +#define NLO_DBGID_SSID_TO_BE_SCANNED_LIST 0 +#define NLO_DBGID_SSID_TO_BE_SKIPPED_LIST 1 + +/* Channel prediction/reduction DBGIDs */ +#define SCAN_CH_PREDICT_DBGID_DEFINITION_START 0 +#define SCAN_CH_PREDICT_CALCULATE 1 +#define SCAN_CH_PREDICT_CALCULATE_SAMPLE 2 +#define SCAN_CH_PREDICT_CALCULATE_RESULT 3 +#define SCAN_CH_PREDICT_FOUND_BSS 4 +#define SCAN_CH_PREDICT_SCAN_START 5 +#define SCAN_CH_PREDICT_START 6 +#define SCAN_CH_PREDICT_STOP 7 +#define SCAN_CH_PREDICT_DBGID_DEFINITION_END 8 + +/* DSRC DBGIDs */ +#define OCB_DBGID_VDEV_CREATE 0 +#define OCB_DBGID_VDEV_DELETE 1 +#define OCB_DBGID_CHAN_PAUSE 2 +#define OCB_DBGID_CHAN_UNPAUSE 3 +#define OCB_DBGID_PEER_CREATE 4 +#define OCB_DBGID_PEER_DELETE 5 +#define OCB_DBGID_DCC_START 6 +#define OCB_DBGID_DCC_STOP 7 +#define OCB_DBGID_SET_CONFIG_CMD 8 +#define OCB_DBGID_SET_UTC_TIME_CMD 9 +#define OCB_DBGID_START_TIMING_ADVERT_CMD 10 +#define OCB_DBGID_STOP_TIMING_ADVERT_CMD 11 +#define OCB_DBGID_GET_TSF_TIMER_CMD 12 +#define OCB_DBGID_GET_DCC_STATS_CMD 13 +#define OCB_DBGID_UPDATE_DCC_NDL_CMD 14 +#define OCB_DBGID_SET_CONFIG_RESP_EVENT 15 +#define OCB_DBGID_GET_TSF_TIMER_RESP_EVENT 16 +#define OCB_DBGID_GET_DCC_STATS_RESP_EVENT 17 +#define OCB_DBGID_DCC_STATS_EVENT 18 +#define OCB_UPDATE_DCC_NDL_RESP_EVENT 19 +#define OCB_DBGID_GENERIC 20 +#define OCB_DBGID_VDEV_START 21 +#define OCB_DBGID_CHANNEL_SCHED_EVENT 22 +#define OCB_DBGID_GPS_EVENT_START 23 +#define OCB_DBGID_GPS_EVENT_END 24 +#define OCB_DBGID_TX_TA_FRAME 25 +#define OCB_DBGID_RX_TA_FRAME 26 + +/* Up to 255 reserved for OCB debug IDs */ + +#define DCC_DBGID_START 256 +#define DCC_DBGID_STOP 257 +#define DCC_DBGID_DCC_STATS_EVENT 258 +#define DCC_DBGID_SM_INIT 259 +#define DCC_DBGID_SM_EVENT 260 +#define DCC_DBGID_SM_CHANGE 261 +#define DCC_DBGID_GET_TX_ALLOWED 262 +#define DCC_DBGID_NOTIFY_TX_COMPLETION 263 +#define DCC_DBGID_NOTIFY_RX 264 +#define DCC_DBGID_GET_TX_POWER 265 +#define DCC_DBGID_GET_TX_RATE 266 +#define DCC_DBGID_TICKLE_SCHED 267 +#define DCC_DBGID_GENERIC 268 +#define DCC_DBGID_RX_PATH 269 +#define DCC_DBGID_TX_PATH 270 + +/* RSSI Threshold Monitor DBGIDs*/ +#define RSSI_MONITOR_DBGID_DEFINITION_START 0 +#define RSSI_MONITOR_VDEV_INIT 1 +#define RSSI_MONITOR_VDEV_FREE 2 +#define RSSI_MONITOR_VDEV_EVENT 3 +#define RSSI_MONITOR_HW_EVENT 4 +#define RSSI_MONITOR_ENABLE_THRESHOLDS_CLIENT_REQ 5 +#define RSSI_MONITOR_ENABLE_THRESHOLDS_CLIENT_REQ_ERR 6 +#define RSSI_MONITOR_DISABLE_THRESHOLDS_CLIENT_REQ 7 +#define RSSI_MONITOR_DISABLE_THRESHOLDS_CLIENT_REQ_ERR 8 +#define RSSI_MONITOR_ARBITER 9 +#define RSSI_MONITOR_ARBITER_CONFIG_HW 10 +#define RSSI_MONITOR_CHECK_AND_DELIVER_EVENT 11 +#define RSSI_MONITOR_DELIVER_EVENT 12 +#define RSSI_MONITOR_UPDATE_BEACON_RSSI 13 +#define RSSI_MONITOR_DBGID_DEFINITION_END 14 + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_ID_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/debug_linux.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/debug_linux.h new file mode 100644 index 000000000000..3636ad350411 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/debug_linux.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _DEBUG_LINUX_H_ +#define _DEBUG_LINUX_H_ + + /* macro to remove parens */ +#define ATH_PRINTX_ARG(arg...) arg + +#ifdef DEBUG + /* NOTE: the AR_DEBUG_PRINTF macro is defined here to handle special handling of variable arg macros + * which may be compiler dependent. */ +#define AR_DEBUG_PRINTF(mask, args) do { \ + if (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (mask)) { \ + A_LOGGER(mask, ATH_MODULE_NAME, ATH_PRINTX_ARG args); \ + } \ +} while (0) +#else + /* on non-debug builds, keep in error and warning messages in the driver, all other + * message tracing will get compiled out */ +#define AR_DEBUG_PRINTF(mask, args) \ + if ((mask) & (ATH_DEBUG_ERR | ATH_DEBUG_WARN)) { A_PRINTF(ATH_PRINTX_ARG args); } + +#endif + + /* compile specific macro to get the function name string */ +#define _A_FUNCNAME_ __func__ + + +#endif /* _DEBUG_LINUX_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dl_list.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dl_list.h new file mode 100644 index 000000000000..241c81a91e4a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/dl_list.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//============================================================================== +// Double-link list definitions (adapted from Atheros SDIO stack) +// +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __DL_LIST_H___ +#define __DL_LIST_H___ + +#define A_CONTAINING_STRUCT(address, struct_type, field_name)\ + ((struct_type *)((char *)(address) - (char *)(&((struct_type *)0)->field_name))) + +/* list functions */ +/* pointers for the list */ +typedef struct _DL_LIST { + struct _DL_LIST *pPrev; + struct _DL_LIST *pNext; +}DL_LIST, *PDL_LIST; +/* + * DL_LIST_INIT , initialize doubly linked list +*/ +#define DL_LIST_INIT(pList)\ + {(pList)->pPrev = pList; (pList)->pNext = pList;} + +/* faster macro to init list and add a single item */ +#define DL_LIST_INIT_AND_ADD(pList,pItem) \ +{ (pList)->pPrev = (pItem); \ + (pList)->pNext = (pItem); \ + (pItem)->pNext = (pList); \ + (pItem)->pPrev = (pList); \ +} + +#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList))) +#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext +#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev +/* + * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member + * NOT: do not use this function if the items in the list are deleted inside the + * iteration loop +*/ +#define ITERATE_OVER_LIST(pStart, pTemp) \ + for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext) + +static __inline bool DL_ListIsEntryInList(const DL_LIST * pList, const DL_LIST * pEntry) { + const DL_LIST * pTmp; + + if (pList == pEntry) return true; + + ITERATE_OVER_LIST(pList, pTmp) { + if (pTmp == pEntry) { + return true; + } + } + + return false; +} + +/* safe iterate macro that allows the item to be removed from the list + * the iteration continues to the next item in the list + */ +#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \ +{ \ + PDL_LIST pTemp; \ + pTemp = (pStart)->pNext; \ + while (pTemp != (pStart)) { \ + (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \ + pTemp = pTemp->pNext; \ + +#define ITERATE_IS_VALID(pStart) DL_ListIsEntryInList(pStart, pTemp) +#define ITERATE_RESET(pStart) pTemp=(pStart)->pNext + +#define ITERATE_END }} + +/* + * DL_ListInsertTail - insert pAdd to the end of the list +*/ +static __inline PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) { + /* insert at tail */ + pAdd->pPrev = pList->pPrev; + pAdd->pNext = pList; + if (pList->pPrev) { + pList->pPrev->pNext = pAdd; + } + pList->pPrev = pAdd; + return pAdd; +} + +/* + * DL_ListInsertHead - insert pAdd into the head of the list +*/ +static __inline PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) { + /* insert at head */ + pAdd->pPrev = pList; + pAdd->pNext = pList->pNext; + pList->pNext->pPrev = pAdd; + pList->pNext = pAdd; + return pAdd; +} + +#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem)) +/* + * DL_ListRemove - remove pDel from list +*/ +static __inline PDL_LIST DL_ListRemove(PDL_LIST pDel) { + if (pDel->pNext != NULL) { + pDel->pNext->pPrev = pDel->pPrev; + } + if (pDel->pPrev != NULL) { + pDel->pPrev->pNext = pDel->pNext; + } + + /* point back to itself just to be safe, incase remove is called again */ + pDel->pNext = pDel; + pDel->pPrev = pDel; + return pDel; +} + +/* + * DL_ListRemoveItemFromHead - get a list item from the head +*/ +static __inline PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) { + PDL_LIST pItem = NULL; + if (pList->pNext != pList) { + pItem = pList->pNext; + /* remove the first item from head */ + DL_ListRemove(pItem); + } + return pItem; +} + +static __inline PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) { + PDL_LIST pItem = NULL; + if (pList->pPrev != pList) { + pItem = pList->pPrev; + /* remove the item from tail */ + DL_ListRemove(pItem); + } + return pItem; +} + +/* transfer src list items to the tail of the destination list */ +static __inline void DL_ListTransferItemsToTail(PDL_LIST pDest, PDL_LIST pSrc) { + /* only concatenate if src is not empty */ + if (!DL_LIST_IS_EMPTY(pSrc)) { + /* cut out circular list in src and re-attach to end of dest */ + pSrc->pPrev->pNext = pDest; + pSrc->pNext->pPrev = pDest->pPrev; + pDest->pPrev->pNext = pSrc->pNext; + pDest->pPrev = pSrc->pPrev; + /* terminate src list, it is now empty */ + pSrc->pPrev = pSrc; + pSrc->pNext = pSrc; + } +} + +/* transfer src list items to the head of the destination list */ +static __inline void DL_ListTransferItemsToHead(PDL_LIST pDest, PDL_LIST pSrc) { + /* only concatenate if src is not empty */ + if (!DL_LIST_IS_EMPTY(pSrc)) { + /* cut out circular list in src and re-attach to start of dest */ + pSrc->pNext->pPrev = pDest; + pDest->pNext->pPrev = pSrc->pPrev; + pSrc->pPrev->pNext = pDest->pNext; + pDest->pNext = pSrc->pNext; + /* terminate src list, it is now empty */ + pSrc->pPrev = pSrc; + pSrc->pNext = pSrc; + } +} + +#endif /* __DL_LIST_H___ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/efuse_reg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/efuse_reg.h new file mode 100644 index 000000000000..29fe800f5af8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/efuse_reg.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _EFUSE_REG_REG_H_ +#define _EFUSE_REG_REG_H_ + +#define EFUSE_WR_ENABLE_REG_ADDRESS 0x00000000 +#define EFUSE_WR_ENABLE_REG_OFFSET 0x00000000 +#define EFUSE_WR_ENABLE_REG_V_MSB 0 +#define EFUSE_WR_ENABLE_REG_V_LSB 0 +#define EFUSE_WR_ENABLE_REG_V_MASK 0x00000001 +#define EFUSE_WR_ENABLE_REG_V_GET(x) (((x) & EFUSE_WR_ENABLE_REG_V_MASK) >> EFUSE_WR_ENABLE_REG_V_LSB) +#define EFUSE_WR_ENABLE_REG_V_SET(x) (((x) << EFUSE_WR_ENABLE_REG_V_LSB) & EFUSE_WR_ENABLE_REG_V_MASK) + +#define EFUSE_INT_ENABLE_REG_ADDRESS 0x00000004 +#define EFUSE_INT_ENABLE_REG_OFFSET 0x00000004 +#define EFUSE_INT_ENABLE_REG_V_MSB 0 +#define EFUSE_INT_ENABLE_REG_V_LSB 0 +#define EFUSE_INT_ENABLE_REG_V_MASK 0x00000001 +#define EFUSE_INT_ENABLE_REG_V_GET(x) (((x) & EFUSE_INT_ENABLE_REG_V_MASK) >> EFUSE_INT_ENABLE_REG_V_LSB) +#define EFUSE_INT_ENABLE_REG_V_SET(x) (((x) << EFUSE_INT_ENABLE_REG_V_LSB) & EFUSE_INT_ENABLE_REG_V_MASK) + +#define EFUSE_INT_STATUS_REG_ADDRESS 0x00000008 +#define EFUSE_INT_STATUS_REG_OFFSET 0x00000008 +#define EFUSE_INT_STATUS_REG_V_MSB 0 +#define EFUSE_INT_STATUS_REG_V_LSB 0 +#define EFUSE_INT_STATUS_REG_V_MASK 0x00000001 +#define EFUSE_INT_STATUS_REG_V_GET(x) (((x) & EFUSE_INT_STATUS_REG_V_MASK) >> EFUSE_INT_STATUS_REG_V_LSB) +#define EFUSE_INT_STATUS_REG_V_SET(x) (((x) << EFUSE_INT_STATUS_REG_V_LSB) & EFUSE_INT_STATUS_REG_V_MASK) + +#define BITMASK_WR_REG_ADDRESS 0x0000000c +#define BITMASK_WR_REG_OFFSET 0x0000000c +#define BITMASK_WR_REG_V_MSB 31 +#define BITMASK_WR_REG_V_LSB 0 +#define BITMASK_WR_REG_V_MASK 0xffffffff +#define BITMASK_WR_REG_V_GET(x) (((x) & BITMASK_WR_REG_V_MASK) >> BITMASK_WR_REG_V_LSB) +#define BITMASK_WR_REG_V_SET(x) (((x) << BITMASK_WR_REG_V_LSB) & BITMASK_WR_REG_V_MASK) + +#define VDDQ_SETTLE_TIME_REG_ADDRESS 0x00000010 +#define VDDQ_SETTLE_TIME_REG_OFFSET 0x00000010 +#define VDDQ_SETTLE_TIME_REG_V_MSB 31 +#define VDDQ_SETTLE_TIME_REG_V_LSB 0 +#define VDDQ_SETTLE_TIME_REG_V_MASK 0xffffffff +#define VDDQ_SETTLE_TIME_REG_V_GET(x) (((x) & VDDQ_SETTLE_TIME_REG_V_MASK) >> VDDQ_SETTLE_TIME_REG_V_LSB) +#define VDDQ_SETTLE_TIME_REG_V_SET(x) (((x) << VDDQ_SETTLE_TIME_REG_V_LSB) & VDDQ_SETTLE_TIME_REG_V_MASK) + +#define VDDQ_HOLD_TIME_REG_ADDRESS 0x00000014 +#define VDDQ_HOLD_TIME_REG_OFFSET 0x00000014 +#define VDDQ_HOLD_TIME_REG_V_MSB 31 +#define VDDQ_HOLD_TIME_REG_V_LSB 0 +#define VDDQ_HOLD_TIME_REG_V_MASK 0xffffffff +#define VDDQ_HOLD_TIME_REG_V_GET(x) (((x) & VDDQ_HOLD_TIME_REG_V_MASK) >> VDDQ_HOLD_TIME_REG_V_LSB) +#define VDDQ_HOLD_TIME_REG_V_SET(x) (((x) << VDDQ_HOLD_TIME_REG_V_LSB) & VDDQ_HOLD_TIME_REG_V_MASK) + +#define RD_STROBE_PW_REG_ADDRESS 0x00000018 +#define RD_STROBE_PW_REG_OFFSET 0x00000018 +#define RD_STROBE_PW_REG_V_MSB 31 +#define RD_STROBE_PW_REG_V_LSB 0 +#define RD_STROBE_PW_REG_V_MASK 0xffffffff +#define RD_STROBE_PW_REG_V_GET(x) (((x) & RD_STROBE_PW_REG_V_MASK) >> RD_STROBE_PW_REG_V_LSB) +#define RD_STROBE_PW_REG_V_SET(x) (((x) << RD_STROBE_PW_REG_V_LSB) & RD_STROBE_PW_REG_V_MASK) + +#define PG_STROBE_PW_REG_ADDRESS 0x0000001c +#define PG_STROBE_PW_REG_OFFSET 0x0000001c +#define PG_STROBE_PW_REG_V_MSB 31 +#define PG_STROBE_PW_REG_V_LSB 0 +#define PG_STROBE_PW_REG_V_MASK 0xffffffff +#define PG_STROBE_PW_REG_V_GET(x) (((x) & PG_STROBE_PW_REG_V_MASK) >> PG_STROBE_PW_REG_V_LSB) +#define PG_STROBE_PW_REG_V_SET(x) (((x) << PG_STROBE_PW_REG_V_LSB) & PG_STROBE_PW_REG_V_MASK) + +#define PGENB_SETUP_HOLD_TIME_REG_ADDRESS 0x00000020 +#define PGENB_SETUP_HOLD_TIME_REG_OFFSET 0x00000020 +#define PGENB_SETUP_HOLD_TIME_REG_V_MSB 31 +#define PGENB_SETUP_HOLD_TIME_REG_V_LSB 0 +#define PGENB_SETUP_HOLD_TIME_REG_V_MASK 0xffffffff +#define PGENB_SETUP_HOLD_TIME_REG_V_GET(x) (((x) & PGENB_SETUP_HOLD_TIME_REG_V_MASK) >> PGENB_SETUP_HOLD_TIME_REG_V_LSB) +#define PGENB_SETUP_HOLD_TIME_REG_V_SET(x) (((x) << PGENB_SETUP_HOLD_TIME_REG_V_LSB) & PGENB_SETUP_HOLD_TIME_REG_V_MASK) + +#define STROBE_PULSE_INTERVAL_REG_ADDRESS 0x00000024 +#define STROBE_PULSE_INTERVAL_REG_OFFSET 0x00000024 +#define STROBE_PULSE_INTERVAL_REG_V_MSB 31 +#define STROBE_PULSE_INTERVAL_REG_V_LSB 0 +#define STROBE_PULSE_INTERVAL_REG_V_MASK 0xffffffff +#define STROBE_PULSE_INTERVAL_REG_V_GET(x) (((x) & STROBE_PULSE_INTERVAL_REG_V_MASK) >> STROBE_PULSE_INTERVAL_REG_V_LSB) +#define STROBE_PULSE_INTERVAL_REG_V_SET(x) (((x) << STROBE_PULSE_INTERVAL_REG_V_LSB) & STROBE_PULSE_INTERVAL_REG_V_MASK) + +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_ADDRESS 0x00000028 +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_OFFSET 0x00000028 +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_V_MSB 31 +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_V_LSB 0 +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_V_MASK 0xffffffff +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_V_GET(x) (((x) & CSB_ADDR_LOAD_SETUP_HOLD_REG_V_MASK) >> CSB_ADDR_LOAD_SETUP_HOLD_REG_V_LSB) +#define CSB_ADDR_LOAD_SETUP_HOLD_REG_V_SET(x) (((x) << CSB_ADDR_LOAD_SETUP_HOLD_REG_V_LSB) & CSB_ADDR_LOAD_SETUP_HOLD_REG_V_MASK) + +#define EFUSE_INTF0_ADDRESS 0x00000800 +#define EFUSE_INTF0_OFFSET 0x00000800 +#define EFUSE_INTF0_R_MSB 31 +#define EFUSE_INTF0_R_LSB 0 +#define EFUSE_INTF0_R_MASK 0xffffffff +#define EFUSE_INTF0_R_GET(x) (((x) & EFUSE_INTF0_R_MASK) >> EFUSE_INTF0_R_LSB) +#define EFUSE_INTF0_R_SET(x) (((x) << EFUSE_INTF0_R_LSB) & EFUSE_INTF0_R_MASK) + +#define EFUSE_INTF1_ADDRESS 0x00001000 +#define EFUSE_INTF1_OFFSET 0x00001000 +#define EFUSE_INTF1_R_MSB 31 +#define EFUSE_INTF1_R_LSB 0 +#define EFUSE_INTF1_R_MASK 0xffffffff +#define EFUSE_INTF1_R_GET(x) (((x) & EFUSE_INTF1_R_MASK) >> EFUSE_INTF1_R_LSB) +#define EFUSE_INTF1_R_SET(x) (((x) << EFUSE_INTF1_R_LSB) & EFUSE_INTF1_R_MASK) + +#ifndef __ASSEMBLER__ +typedef struct efuse_reg_reg_s { + volatile unsigned int efuse_wr_enable_reg; + volatile unsigned int efuse_int_enable_reg; + volatile unsigned int efuse_int_status_reg; + volatile unsigned int bitmask_wr_reg; + volatile unsigned int vddq_settle_time_reg; + volatile unsigned int vddq_hold_time_reg; + volatile unsigned int rd_strobe_pw_reg; + volatile unsigned int pg_strobe_pw_reg; + volatile unsigned int pgenb_setup_hold_time_reg; + volatile unsigned int strobe_pulse_interval_reg; + volatile unsigned int csb_addr_load_setup_hold_reg; + unsigned char pad0[2004]; /* pad to 0x800 */ + volatile unsigned int efuse_intf0[512]; + volatile unsigned int efuse_intf1[512]; +} efuse_reg_reg_t; +#endif /* __ASSEMBLER__ */ + +#endif /* _EFUSE_REG_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/enet.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/enet.h new file mode 100644 index 000000000000..a9f03b7e6869 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/enet.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _ENET__H_ +#define _ENET__H_ + +#if defined(ATH_TARGET) +#include /* A_UINT8 */ +#else +#include /* A_UINT8 */ +#endif + + +#define ETHERNET_ADDR_LEN 6 /* bytes */ +#define ETHERNET_TYPE_LEN 2 /* bytes - length of the Ethernet type field */ + +struct ethernet_hdr_t { + A_UINT8 dest_addr[ETHERNET_ADDR_LEN]; + A_UINT8 src_addr[ETHERNET_ADDR_LEN]; + A_UINT8 ethertype[ETHERNET_TYPE_LEN]; +}; + +#define ETHERNET_HDR_LEN (sizeof(struct ethernet_hdr_t)) + +#define ETHERNET_CRC_LEN 4 /* bytes - length of the Ethernet CRC */ +#define ETHERNET_MAX_LEN 1518 /* bytes */ + +#define ETHERNET_MTU (ETHERNET_MAX_LEN - (ETHERNET_HDR_LEN + ETHER_CRC_LEN)) + + +struct llc_snap_hdr_t { + A_UINT8 dsap; + A_UINT8 ssap; + A_UINT8 cntl; + A_UINT8 org_code[3]; + A_UINT8 ethertype[2]; +}; + +#define LLC_SNAP_HDR_LEN (sizeof(struct llc_snap_hdr_t)) +#define LLC_SNAP_HDR_OFFSET_ETHERTYPE \ + (offsetof(struct llc_snap_hdr_t, ethertype[0])) + +#define ETHERTYPE_VLAN_LEN 4 + +struct ethernet_vlan_hdr_t { + A_UINT8 dest_addr[ETHERNET_ADDR_LEN]; + A_UINT8 src_addr[ETHERNET_ADDR_LEN]; + A_UINT8 vlan_tpid[2]; + A_UINT8 vlan_tci[2]; + A_UINT8 ethertype[2]; +}; + +#define ETHERTYPE_IS_EAPOL_WAPI(typeorlen) \ + ((typeorlen) == ETHERTYPE_PAE || \ + (typeorlen) == ETHERTYPE_WAI) + +#define IS_ETHERTYPE(_typeOrLen) ((_typeOrLen) >= 0x0600) + +#ifndef ETHERTYPE_IPV4 +#define ETHERTYPE_IPV4 0x0800 /* Internet Protocol, Version 4 (IPv4) */ +#endif + +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 /* Internal QCA AARP protocol */ +#endif + +#ifndef ETHERTYPE_IPX +#define ETHERTYPE_IPX 0x8137 /* IPX over DIX protocol */ +#endif + +#ifndef ETHERTYPE_ARP +#define ETHERTYPE_ARP 0x0806 /* Address Resolution Protocol (ARP) */ +#endif + +#ifndef ETHERTYPE_RARP +#define ETHERTYPE_RARP 0x8035 /* Reverse Address Resolution Protocol (RARP) */ +#endif + +#ifndef ETHERTYPE_VLAN +#define ETHERTYPE_VLAN 0x8100 /* VLAN TAG protocol */ +#endif + +#ifndef ETHERTYPE_SNMP +#define ETHERTYPE_SNMP 0x814C /* Simple Network Management Protocol (SNMP) */ +#endif + +#ifndef ETHERTYPE_IPV6 +#define ETHERTYPE_IPV6 0x86DD /* Internet Protocol, Version 6 (IPv6) */ +#endif + +#ifndef ETHERTYPE_PAE +#define ETHERTYPE_PAE 0x888E /* EAP over LAN (EAPOL) */ +#endif + +#ifndef ETHERTYPE_WAI +#define ETHERTYPE_WAI 0x88B4 /* WAPI */ +#endif + +#ifndef ETHERTYPE_TDLS +#define ETHERTYPE_TDLS 0x890D /* TDLS */ +#endif + +#define LLC_SNAP_LSAP 0xaa +#define LLC_UI 0x3 + +#define RFC1042_SNAP_ORGCODE_0 0x00 +#define RFC1042_SNAP_ORGCODE_1 0x00 +#define RFC1042_SNAP_ORGCODE_2 0x00 + +#define BTEP_SNAP_ORGCODE_0 0x00 +#define BTEP_SNAP_ORGCODE_1 0x00 +#define BTEP_SNAP_ORGCODE_2 0xf8 + + +#define IS_SNAP(_llc) ((_llc)->dsap == LLC_SNAP_LSAP && \ + (_llc)->ssap == LLC_SNAP_LSAP && \ + (_llc)->cntl == LLC_UI) + +#define IS_RFC1042(_llc) ((_llc)->org_code[0] == RFC1042_SNAP_ORGCODE_0 && \ + (_llc)->org_code[1] == RFC1042_SNAP_ORGCODE_1 && \ + (_llc)->org_code[2] == RFC1042_SNAP_ORGCODE_2) + +#define IS_BTEP(_llc) ((_llc)->org_code[0] == BTEP_SNAP_ORGCODE_0 && \ + (_llc)->org_code[1] == BTEP_SNAP_ORGCODE_1 && \ + (_llc)->org_code[2] == BTEP_SNAP_ORGCODE_2) + + +#endif /* _ENET__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h new file mode 100644 index 000000000000..7b998630371f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h @@ -0,0 +1,870 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//============================================================================== +// HIF specific declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HIF_H_ +#define _HIF_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +//#include "a_config.h" +#include "athdefs.h" +#include "a_types.h" +#include "osapi_linux.h" +#include "dl_list.h" + +#define ENABLE_MBOX_DUMMY_SPACE_FEATURE 1 + +typedef struct htc_callbacks HTC_CALLBACKS; +typedef struct hif_device HIF_DEVICE; +typedef void __iomem *A_target_id_t; + +#define HIF_TYPE_AR6002 2 +#define HIF_TYPE_AR6003 3 +#define HIF_TYPE_AR6004 5 +#define HIF_TYPE_AR9888 6 +#define HIF_TYPE_AR6320 7 +#define HIF_TYPE_AR6320V2 8 +/* For attaching Peregrine 2.0 board host_reg_tbl only */ +#define HIF_TYPE_AR9888V2 8 + +/* + * direction - Direction of transfer (HIF_READ/HIF_WRITE). + */ +#define HIF_READ 0x00000001 +#define HIF_WRITE 0x00000002 +#define HIF_DIR_MASK (HIF_READ | HIF_WRITE) + +/* + * type - An interface may support different kind of read/write commands. + * For example: SDIO supports CMD52/CMD53s. In case of MSIO it + * translates to using different kinds of TPCs. The command type + * is thus divided into a basic and an extended command and can + * be specified using HIF_BASIC_IO/HIF_EXTENDED_IO. + */ +#define HIF_BASIC_IO 0x00000004 +#define HIF_EXTENDED_IO 0x00000008 +#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO) + +/* + * emode - This indicates the whether the command is to be executed in a + * blocking or non-blocking fashion (HIF_SYNCHRONOUS/ + * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been + * implemented using the asynchronous mode allowing the the bus + * driver to indicate the completion of operation through the + * registered callback routine. The requirement primarily comes + * from the contexts these operations get called from (a driver's + * transmit context or the ISR context in case of receive). + * Support for both of these modes is essential. + */ +#define HIF_SYNCHRONOUS 0x00000010 +#define HIF_ASYNCHRONOUS 0x00000020 +#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS) + +/* + * dmode - An interface may support different kinds of commands based on + * the tradeoff between the amount of data it can carry and the + * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/ + * HIF_BLOCK_BASIS). In case of latter, the data is rounded off + * to the nearest block size by padding. The size of the block is + * configurable at compile time using the HIF_BLOCK_SIZE and is + * negotiated with the target during initialization after the + * AR6000 interrupts are enabled. + */ +#define HIF_BYTE_BASIS 0x00000040 +#define HIF_BLOCK_BASIS 0x00000080 +#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS) + +/* + * amode - This indicates if the address has to be incremented on AR6000 + * after every read/write operation (HIF?FIXED_ADDRESS/ + * HIF_INCREMENTAL_ADDRESS). + */ +#define HIF_FIXED_ADDRESS 0x00000100 +#define HIF_INCREMENTAL_ADDRESS 0x00000200 +#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS) + +/* + * dummy - data written into the dummy space will not put into the final mbox FIFO + */ +#define HIF_DUMMY_SPACE_MASK 0xFFFF0000 + + +#define HIF_WR_ASYNC_BYTE_FIX \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_ASYNC_BYTE_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_ASYNC_BLOCK_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_SYNC_BYTE_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_SYNC_BYTE_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_SYNC_BLOCK_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_ASYNC_BLOCK_FIX \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_SYNC_BLOCK_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_SYNC_BYTE_INC \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BYTE_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BYTE_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BLOCK_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BYTE_INC \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_ASYNC_BLOCK_INC \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BLOCK_INC \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BLOCK_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) + +typedef enum { + HIF_DEVICE_POWER_STATE = 0, + HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + HIF_DEVICE_GET_MBOX_ADDR, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + HIF_DEVICE_GET_IRQ_PROC_MODE, + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, + HIF_DEVICE_POWER_STATE_CHANGE, + HIF_DEVICE_GET_IRQ_YIELD_PARAMS, + HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, + HIF_DEVICE_GET_OS_DEVICE, + HIF_DEVICE_DEBUG_BUS_STATE, + HIF_BMI_DONE, + HIF_DEVICE_SET_TARGET_TYPE, + HIF_DEVICE_SET_HTC_CONTEXT, + HIF_DEVICE_GET_HTC_CONTEXT, +} HIF_DEVICE_CONFIG_OPCODE; + +/* + * HIF CONFIGURE definitions: + * + * HIF_DEVICE_GET_MBOX_BLOCK_SIZE + * input : none + * output : array of 4 u_int32_ts + * notes: block size is returned for each mailbox (4) + * + * HIF_DEVICE_GET_MBOX_ADDR + * input : none + * output : HIF_DEVICE_MBOX_INFO + * notes: + * + * HIF_DEVICE_GET_PENDING_EVENTS_FUNC + * input : none + * output: HIF_PENDING_EVENTS_FUNC function pointer + * notes: this is optional for the HIF layer, if the request is + * not handled then it indicates that the upper layer can use + * the standard device methods to get pending events (IRQs, mailbox messages etc..) + * otherwise it can call the function pointer to check pending events. + * + * HIF_DEVICE_GET_IRQ_PROC_MODE + * input : none + * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode) + * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF + * layer can report whether IRQ processing is requires synchronous behavior or + * can be processed using asynchronous bus requests (typically faster). + * + * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC + * input : + * output : HIF_MASK_UNMASK_RECV_EVENT function pointer + * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism + * to mask receive message events. The upper layer can call this pointer when it needs + * to mask/unmask receive events (in case it runs out of buffers). + * + * HIF_DEVICE_POWER_STATE_CHANGE + * + * input : HIF_DEVICE_POWER_CHANGE_TYPE + * output : none + * note: this is optional for the HIF layer. The HIF layer can handle power on/off state change + * requests in an interconnect specific way. This is highly OS and bus driver dependent. + * The caller must guarantee that no HIF read/write requests will be made after the device + * is powered down. + * + * HIF_DEVICE_GET_IRQ_YIELD_PARAMS + * + * input : none + * output : HIF_DEVICE_IRQ_YIELD_PARAMS + * note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler. + * The DSR callback handler will exit after a fixed number of RX packets or events are processed. + * This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY. + * The HIF implementation can ignore this command if it does not desire the DSR callback to yield. + * The HIF layer can indicate the maximum number of IRQ processing units (RX packets) before the + * DSR handler callback must yield and return control back to the HIF layer. When a yield limit is + * used the DSR callback will not call HIFAckInterrupts() as it would normally do before returning. + * The HIF implementation that requires a yield count must call HIFAckInterrupt() when it is prepared + * to process interrupts again. + * + * HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT + * input : none + * output : HIF_DEVICE_SCATTER_SUPPORT_INFO + * note: This query checks if the HIF layer implements the SCATTER request interface. Scatter requests + * allows upper layers to submit mailbox I/O operations using a list of buffers. This is useful for + * multi-message transfers that can better utilize the bus interconnect. + * + * + * HIF_DEVICE_GET_OS_DEVICE + * intput : none + * output : HIF_DEVICE_OS_DEVICE_INFO; + * note: On some operating systems, the HIF layer has a parent device object for the bus. This object + * may be required to register certain types of logical devices. + * + * HIF_DEVICE_DEBUG_BUS_STATE + * input : none + * output : none + * note: This configure option triggers the HIF interface to dump as much bus interface state. This + * configuration request is optional (No-OP on some HIF implementations) + * + * HIF_DEVICE_SET_TARGET_TYPE + * input : TARGET_TYPE_* + * output : none + * note: Some HIF implementations may need to know TargetType in order to access + * Target registers or Host Interest Area. (No-OP on some HIF implementations) + */ + +typedef struct { + u_int32_t ExtendedAddress; /* extended address for larger writes */ + u_int32_t ExtendedSize; +} HIF_MBOX_PROPERTIES; + +#define HIF_MBOX_FLAG_NO_BUNDLING (1 << 0) /* do not allow bundling over the mailbox */ + +typedef struct { + u_int32_t MboxAddresses[4]; /* must be first element for legacy HIFs that return the address in + and ARRAY of 32-bit words */ + + /* the following describe extended mailbox properties */ + HIF_MBOX_PROPERTIES MboxProp[4]; + /* if the HIF supports the GMbox extended address region it can report it + * here, some interfaces cannot support the GMBOX address range and not set this */ + u_int32_t GMboxAddress; + u_int32_t GMboxSize; + u_int32_t Flags; /* flags to describe mbox behavior or usage */ +} HIF_DEVICE_MBOX_INFO; + +typedef enum { + HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all + interrupts before returning */ + HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts + using ASYNC I/O (that is HIFAckInterrupt can be called at a + later time */ +} HIF_DEVICE_IRQ_PROCESSING_MODE; + +typedef enum { + HIF_DEVICE_POWER_UP, /* HIF layer should power up interface and/or module */ + HIF_DEVICE_POWER_DOWN, /* HIF layer should initiate bus-specific measures to minimize power */ + HIF_DEVICE_POWER_CUT /* HIF layer should initiate bus-specific AND/OR platform-specific measures + to completely power-off the module and associated hardware (i.e. cut power supplies) + */ +} HIF_DEVICE_POWER_CHANGE_TYPE; + +typedef enum { + HIF_DEVICE_STATE_ON, + HIF_DEVICE_STATE_DEEPSLEEP, + HIF_DEVICE_STATE_CUTPOWER, + HIF_DEVICE_STATE_WOW +} HIF_DEVICE_STATE; + +typedef struct { + int RecvPacketYieldCount; /* max number of packets to force DSR to return */ +} HIF_DEVICE_IRQ_YIELD_PARAMS; + + +typedef struct _HIF_SCATTER_ITEM { + u_int8_t *pBuffer; /* CPU accessible address of buffer */ + int Length; /* length of transfer to/from this buffer */ + void *pCallerContexts[2]; /* space for caller to insert a context associated with this item */ +} HIF_SCATTER_ITEM; + +struct _HIF_SCATTER_REQ; + +typedef void ( *HIF_SCATTER_COMP_CB)(struct _HIF_SCATTER_REQ *); + +typedef enum _HIF_SCATTER_METHOD { + HIF_SCATTER_NONE = 0, + HIF_SCATTER_DMA_REAL, /* Real SG support no restrictions */ + HIF_SCATTER_DMA_BOUNCE, /* Uses SG DMA but HIF layer uses an internal bounce buffer */ +} HIF_SCATTER_METHOD; + +typedef struct _HIF_SCATTER_REQ { + DL_LIST ListLink; /* link management */ + u_int32_t Address; /* address for the read/write operation */ + u_int32_t Request; /* request flags */ + u_int32_t TotalLength; /* total length of entire transfer */ + u_int32_t CallerFlags; /* caller specific flags can be stored here */ + HIF_SCATTER_COMP_CB CompletionRoutine; /* completion routine set by caller */ + int CompletionStatus; /* status of completion */ + void *Context; /* caller context for this request */ + int ValidScatterEntries; /* number of valid entries set by caller */ + HIF_SCATTER_METHOD ScatterMethod; /* scatter method handled by HIF */ + void *HIFPrivate[4]; /* HIF private area */ + u_int8_t *pScatterBounceBuffer; /* bounce buffer for upper layers to copy to/from */ + HIF_SCATTER_ITEM ScatterList[1]; /* start of scatter list */ +} HIF_SCATTER_REQ; + +typedef HIF_SCATTER_REQ * ( *HIF_ALLOCATE_SCATTER_REQUEST)(HIF_DEVICE *device); +typedef void ( *HIF_FREE_SCATTER_REQUEST)(HIF_DEVICE *device, HIF_SCATTER_REQ *request); +typedef int ( *HIF_READWRITE_SCATTER)(HIF_DEVICE *device, HIF_SCATTER_REQ *request); + +typedef struct _HIF_DEVICE_SCATTER_SUPPORT_INFO { + /* information returned from HIF layer */ + HIF_ALLOCATE_SCATTER_REQUEST pAllocateReqFunc; + HIF_FREE_SCATTER_REQUEST pFreeReqFunc; + HIF_READWRITE_SCATTER pReadWriteScatterFunc; + int MaxScatterEntries; + int MaxTransferSizePerScatterReq; +} HIF_DEVICE_SCATTER_SUPPORT_INFO; + +typedef struct { + void *pOSDevice; +} HIF_DEVICE_OS_DEVICE_INFO; + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +typedef struct _HID_ACCESS_LOG { + A_UINT32 seqnum; + bool is_write; + void *addr; + A_UINT32 value; +}HIF_ACCESS_LOG; +#endif + +#define HIF_MAX_DEVICES 1 + +struct htc_callbacks { + void *context; /* context to pass to the dsrhandler + note : rwCompletionHandler is provided the context passed to HIFReadWrite */ + int (* rwCompletionHandler)(void *rwContext, int status); + int (* dsrHandler)(void *context); +}; + +typedef struct osdrv_callbacks { + void *context; /* context to pass for all callbacks except deviceRemovedHandler + the deviceRemovedHandler is only called if the device is claimed */ + int (* deviceInsertedHandler)(void *context, void *hif_handle); + int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle); + int (* deviceSuspendHandler)(void *context); + int (* deviceResumeHandler)(void *context); + int (* deviceWakeupHandler)(void *context); + int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config); +} OSDRV_CALLBACKS; + +#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host + needs to read the register table to figure out what */ +#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */ + +typedef struct _HIF_PENDING_EVENTS_INFO { + u_int32_t Events; + u_int32_t LookAhead; + u_int32_t AvailableRecvBytes; +} HIF_PENDING_EVENTS_INFO; + + /* function to get pending events , some HIF modules use special mechanisms + * to detect packet available and other interrupts */ +typedef int ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE *device, + HIF_PENDING_EVENTS_INFO *pEvents, + void *AsyncContext); + +#define HIF_MASK_RECV TRUE +#define HIF_UNMASK_RECV FALSE + /* function to mask recv events */ +typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE *device, + bool Mask, + void *AsyncContext); + +#ifdef HIF_MBOX_SLEEP_WAR +/* This API is used to update the target sleep state */ +void +HIFSetMboxSleep(HIF_DEVICE *device, bool sleep, bool wait, bool cache); +#endif +/* + * This API is used to perform any global initialization of the HIF layer + * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer + * + */ +int HIFInit(OSDRV_CALLBACKS *callbacks); + +/* This API claims the HIF device and provides a context for handling removal. + * The device removal callback is only called when the OSDRV layer claims + * a device. The claimed context must be non-NULL */ +void HIFClaimDevice(HIF_DEVICE *device, void *claimedContext); +/* release the claimed device */ +void HIFReleaseDevice(HIF_DEVICE *device); + +/* This API allows the HTC layer to attach to the HIF device */ +int HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks); +/* This API detaches the HTC layer from the HIF device */ +void HIFDetachHTC(HIF_DEVICE *device); + +A_STATUS +HIFSyncRead(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + A_UINT32 request, + void *context); + +/* + * This API is used to provide the read/write interface over the specific bus + * interface. + * address - Starting address in the AR6000's address space. For mailbox + * writes, it refers to the start of the mbox boundary. It should + * be ensured that the last byte falls on the mailbox's EOM. For + * mailbox reads, it refers to the end of the mbox boundary. + * buffer - Pointer to the buffer containg the data to be transmitted or + * received. + * length - Amount of data to be transmitted or received. + * request - Characterizes the attributes of the command. + */ +int +HIFReadWrite(HIF_DEVICE *device, + u_int32_t address, + u_char *buffer, + u_int32_t length, + u_int32_t request, + void *context); + +/* + * This can be initiated from the unload driver context when the OSDRV layer has no more use for + * the device. + */ +void HIFShutDownDevice(HIF_DEVICE *device); +void HIFSurpriseRemoved(HIF_DEVICE *device); + +/* + * This should translate to an acknowledgment to the bus driver indicating that + * the previous interrupt request has been serviced and the all the relevant + * sources have been cleared. HTC is ready to process more interrupts. + * This should prevent the bus driver from raising an interrupt unless the + * previous one has been serviced and acknowledged using the previous API. + */ +void HIFAckInterrupt(HIF_DEVICE *device); + +void HIFMaskInterrupt(HIF_DEVICE *device); + +void HIFUnMaskInterrupt(HIF_DEVICE *device); + +int +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, u_int32_t configLen); + +/* + * This API wait for the remaining MBOX messages to be drained + * This should be moved to HTC AR6K layer + */ +int hifWaitForPendingRecv(HIF_DEVICE *device); + +/****************************************************************/ +/* BMI and Diag window abstraction */ +/****************************************************************/ + +#define HIF_BMI_EXCHANGE_NO_TIMEOUT ((u_int32_t)(0)) + +#define DIAG_TRANSFER_LIMIT 2048U /* maximum number of bytes that can be + handled atomically by DiagRead/DiagWrite */ + + /* API to handle HIF-specific BMI message exchanges, this API is synchronous + * and only allowed to be called from a context that can block (sleep) */ +int HIFExchangeBMIMsg(HIF_DEVICE *device, + u_int8_t *pSendMessage, + u_int32_t Length, + u_int8_t *pResponseMessage, + u_int32_t *pResponseLength, + u_int32_t TimeoutMS); + + + + /* + * APIs to handle HIF specific diagnostic read accesses. These APIs are + * synchronous and only allowed to be called from a context that can block (sleep). + * They are not high performance APIs. + * + * HIFDiagReadAccess reads a 4 Byte aligned/length value from a Target register + * or memory word. + * + * HIFDiagReadMem reads an arbitrary length of arbitrarily aligned memory. + */ +int HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 *data); +int HIFDiagReadMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes); +void HIFDumpTargetMemory(HIF_DEVICE *hif_device, void *ramdump_base, + u_int32_t address, u_int32_t size); + /* + * APIs to handle HIF specific diagnostic write accesses. These APIs are + * synchronous and only allowed to be called from a context that can block (sleep). + * They are not high performance APIs. + * + * HIFDiagWriteAccess writes a 4 Byte aligned/length value to a Target register + * or memory word. + * + * HIFDiagWriteMem writes an arbitrary length of arbitrarily aligned memory. + */ +int HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 data); +int HIFDiagWriteMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes); +#if defined(HIF_PCI) && ! defined(A_SIMOS_DEVHOST) +/* + * This API allows the Host to access Target registers of a given + * A_target_id_t directly and relatively efficiently over PCIe. + * This allows the Host to avoid extra overhead associated with + * sending a message to firmware and waiting for a response message + * from firmware, as is done on other interconnects. + * + * Yet there is some complexity with direct accesses because the + * Target's power state is not known a priori. The Host must issue + * special PCIe reads/writes in order to explicitly wake the Target + * and to verify that it is awake and will remain awake. + * + * NB: Host endianness conversion is left for the caller to handle. + * These interfaces handle access; not interpretation. + * + * Usage: + * During initialization, use A_TARGET_ID to obtain an 'target ID' + * for use with these interfaces. + * + * Use A_TARGET_READ and A_TARGET_WRITE to access Target space. + * These calls must be bracketed by A_TARGET_ACCESS_BEGIN and + * A_TARGET_ACCESS_END. A single BEGIN/END pair is adequate for + * multiple READ/WRITE operations. + * + * Use A_TARGET_ACCESS_BEGIN to put the Target in a state in + * which it is legal for the Host to directly access it. This + * may involve waking the Target from a low power state, which + * may take up to 2Ms! + * + * Use A_TARGET_ACCESS_END to tell the Target that as far as + * this code path is concerned, it no longer needs to remain + * directly accessible. BEGIN/END is under a reference counter; + * multiple code paths may issue BEGIN/END on a single targid. + * + * For added efficiency, the Host may use A_TARGET_ACCESS_LIKELY. + * The LIKELY interface works just like A_TARGET_ACCESS_BEGIN, + * except that it may return before the Target is actually + * available. It's a vague indication that some Target accesses + * are expected "soon". When the LIKELY API is used, + * A_TARGET_ACCESS_BEGIN must be used before any access. + * + * There are several uses for the LIKELY/UNLIKELY API: + * -If there is some potential time before Target accesses + * and we want to get a head start on waking the Target + * (e.g. to overlap Target wake with Host-side malloc) + * -High-level code knows that it will call low-level + * functions that will use BEGIN/END, and we don't want + * to allow the Target to sleep until the entire sequence + * has completed. + * + * A_TARGET_ACCESS_OK verifies that the Target can be + * accessed. In general, this should not be needed, but it + * may be useful for debugging or for special uses. + * + * Note that there must be a matching END for each BEGIN + * AND there must be a matching UNLIKELY for each LIKELY! + * + * NB: This API is designed to allow some flexibility in tradeoffs + * between Target power utilization and Host efficiency and + * system performance. + */ + +/* + * For maximum performance and no power management, set this to 1. + * For power management at the cost of performance, set this to 0. + */ +#define CONFIG_ATH_PCIE_MAX_PERF 0 + +/* + * For keeping the target awake till the driver is + * loaded, set this to 1 + */ +#define CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD 1 + +/* + * When CONFIG_ATH_PCIE_MAX_PERF is 0: + * To use LIKELY hints, set this to 1 (slightly better performance, more power) + * To ignore "LIKELY" hints, set this to 0 (slightly worse performance, less power) + */ +#if defined(CONFIG_ATH_PCIE_MAX_PERF) +#define CONFIG_ATH_PCIE_ACCESS_LIKELY 0 +#else +#define CONFIG_ATH_PCIE_ACCESS_LIKELY 1 +#endif + +/* + * Enable/disable CDC max performance workaround + * For max-performace set this to 0 + * To allow SoC to enter sleep set this to 1 + */ +#define CONFIG_DISABLE_CDC_MAX_PERF_WAR 0 + +/* + * PCI-E L1 ASPPM sub-states + * To enable clock gating in L1 state, set this to 1. (less power, slightly more wakeup latency) + * To disable clock gating in L1 state, set this to 0. (slighly more power) + */ +#define CONFIG_PCIE_ENABLE_L1_CLOCK_GATE 1 + +/* + * PCIE_ACCESS_LOG_NUM specifies the number of + * read/write records to store + */ +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +#define PCIE_ACCESS_LOG_NUM 500 +#endif + +/* 64-bit MSI support */ +#define CONFIG_PCIE_64BIT_MSI 0 + +/* BAR0 ready checking for AR6320v2 */ +#define PCIE_BAR0_READY_CHECKING 0 + +/* AXI gating when L1, L2 to reduce power consumption */ +#define CONFIG_PCIE_ENABLE_AXI_CLK_GATE 0 + +extern A_target_id_t HIFGetTargetId(HIF_DEVICE *hifDevice); +extern int HIFTargetSleepStateAdjust(A_target_id_t targid, A_BOOL sleep_ok, A_BOOL wait_for_it); +extern void +HIFSetTargetSleep(HIF_DEVICE *hif_device, A_BOOL sleep_ok, A_BOOL wait_for_it); +extern A_BOOL HIFTargetForcedAwake(A_target_id_t targid); +extern void +HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device); + +#define A_TARGET_ID(hifDevice) HIFGetTargetId(hifDevice) + +#if CONFIG_ATH_PCIE_MAX_PERF +#define A_TARGET_ACCESS_BEGIN(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_END(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_OK(targid) 1 + +#define A_TARGET_ACCESS_LIKELY(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_UNLIKELY(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_READ(targid, offset) \ + A_PCI_READ32(TARGID_TO_PCI_ADDR(targid)+(offset)) + +#if 0 +#define A_TARGET_WRITE(targid, offset, value) \ + A_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid)+(offset), (value)) +#else /* WORKAROUND */ +void WAR_PCI_WRITE32(char *addr, u32 offset, u32 value); +#define A_TARGET_WRITE(targid, offset, value) \ + WAR_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid), (offset), (value)) +#endif +#define A_TARGET_ACCESS_BEGIN_RET(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_BEGIN_RET_EXT(targid, val) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_BEGIN_RET_PTR(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_END_RET(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_END_RET_EXT(targid, val) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_END_RET_PTR(targid) \ + do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) + +#else /* CONFIG_ATH_PCIE_MAX_PERF */ + +void WAR_PCI_WRITE32(char *addr, u32 offset, u32 value); + +#define A_TARGET_ACCESS_BEGIN_RET_EXT(targid, val) \ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_BEGIN(targid) < 0 ) \ + val = -1; + +#define A_TARGET_ACCESS_BEGIN_RET(targid) \ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_BEGIN(targid) < 0) \ + return -1; + +#define A_TARGET_ACCESS_BEGIN_RET_PTR(targid) \ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_BEGIN(targid) < 0) \ + return NULL; + +#define A_TARGET_ACCESS_BEGIN(targid) \ + if(Q_TARGET_ACCESS_BEGIN(targid) < 0) \ + return; + +#define Q_TARGET_ACCESS_BEGIN(targid) \ + HIFTargetSleepStateAdjust((targid), FALSE, TRUE) + +#define A_TARGET_ACCESS_END_RET(targid) \ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_END(targid) < 0) \ + return -1; + +#define A_TARGET_ACCESS_END_RET_EXT(targid, val) \ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_END(targid) < 0) \ + val = -1; + +#define A_TARGET_ACCESS_END_RET_PTR(targid) \ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_END(targid) < 0) \ + return NULL; + +#define A_TARGET_ACCESS_END(targid) \ + if (Q_TARGET_ACCESS_END(targid) < 0) \ + return; + +#define Q_TARGET_ACCESS_END(targid) \ + HIFTargetSleepStateAdjust((targid), TRUE, FALSE) + +#define A_TARGET_ACCESS_OK(targid) HIFTargetForcedAwake(targid) + +#if CONFIG_ATH_PCIE_ACCESS_LIKELY +#define A_TARGET_ACCESS_LIKELY(targid) HIFTargetSleepStateAdjust((targid), FALSE, FALSE) +#define A_TARGET_ACCESS_UNLIKELY(targid) HIFTargetSleepStateAdjust((targid), TRUE, FALSE) +#else /* CONFIG_ATH_PCIE_ACCESS_LIKELY */ +#define A_TARGET_ACCESS_LIKELY(targid) \ + do {unsigned long unused = (unsigned long)(targid); unused = unused;} while(0) + +#define A_TARGET_ACCESS_UNLIKELY(targid) \ + do {unsigned long unused = (unsigned long)(targid); unused = unused;} while(0) +#endif /* CONFIG_ATH_PCIE_ACCESS_LIKELY */ + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +extern A_UINT32 HIFTargetReadChecked(A_target_id_t targid, A_UINT32 offset); +extern void HIFTargetWriteChecked(A_target_id_t targid, A_UINT32 offset, A_UINT32 value); +#define A_TARGET_READ(targid, offset) HIFTargetReadChecked((targid), (offset)) +#define A_TARGET_WRITE(targid, offset, value) HIFTargetWriteChecked((targid), (offset), (value)) +#else /* CONFIG_ATH_PCIE_ACCESS_DEBUG */ +#define A_TARGET_READ(targid, offset) A_PCI_READ32(TARGID_TO_PCI_ADDR(targid)+(offset)) +#if 0 +#define A_TARGET_WRITE(targid, offset, value) \ + A_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid)+(offset), (value)) +#else /* WORKAROUND */ +#define A_TARGET_WRITE(targid, offset, value) \ + WAR_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid), (offset), (value)) +#endif +#endif + +#endif /* CONFIG_ATH_PCIE_MAX_PERF */ + +/*Macro to increment the HIF layer packet error count*/ +#define OL_ATH_HIF_PKT_ERROR_COUNT_INCR(_hif_state,_hif_ecode);\ +{\ + if(_hif_ecode==HIF_PIPE_NO_RESOURCE)(_hif_state->sc->ol_sc->pkt_stats.hif_pipe_no_resrc_count)+=1;\ +} +/* + * This macro implementation is exposed for efficiency only. + * The implementation may change and callers should + * consider the targid to be a completely opaque handle. + */ +#define TARGID_TO_PCI_ADDR(targid) (*((A_target_id_t *)(targid))) + +void *HIFDeviceToOsDevice(HIF_DEVICE *hif_device); + +#elif defined(A_SIMOS_DEVHOST) + +struct ol_softc; + +u_int32_t sim_target_register_read(struct ol_softc *scn, u_int32_t addr); +void sim_target_register_write(struct ol_softc *scn, u_int32_t addr, u_int32_t val); + +#define A_TARGET_ID(hifDevice) 0 +#define A_TARGET_READ(ar, addr) sim_target_register_read(ar, addr) +#define A_TARGET_WRITE(ar, addr, val) sim_target_register_write(ar, addr, val) +#define A_TARGET_ACCESS_BEGIN(targid) +#define A_TARGET_ACCESS_END(targid) + +#define HIFDeviceToOsDevice(hif_device) NULL + +#else + +#define HIFDeviceToOsDevice(hif_device) NULL + +#endif + +#ifdef IPA_UC_OFFLOAD +/* + * IPA micro controller data path offload feature enabled, + * HIF should release copy engine related resource information to IPA UC + * IPA UC will access hardware resource with released information + */ +void HIFIpaGetCEResource(HIF_DEVICE *hif_device, + A_UINT32 *ce_sr_base_paddr, + A_UINT32 *ce_sr_ring_size, + A_UINT32 *ce_reg_paddr); +#endif /* IPA_UC_OFFLOAD */ + +void HIFSetMailboxSwap(HIF_DEVICE *device); + +#ifdef FEATURE_RUNTIME_PM +/* Runtime power management API of HIF to control + * runtime pm. During Runtime Suspend the get API + * return -EAGAIN. The caller can queue the cmd or return. + * The put API decrements the usage count. + * The get API increments the usage count. + * The API's are exposed to HTT and WMI Services only. + */ +int hif_pm_runtime_get(HIF_DEVICE *); +int hif_pm_runtime_put(HIF_DEVICE *); +void *hif_runtime_pm_prevent_suspend_init(const char *); +void hif_runtime_pm_prevent_suspend_deinit(void *data); +int hif_pm_runtime_prevent_suspend(void *ol_sc, void *data); +int hif_pm_runtime_allow_suspend(void *ol_sc, void *data); +int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, void *data, + unsigned int delay); +#else +static inline int hif_pm_runtime_get(HIF_DEVICE *device) { return 0; } +static inline int hif_pm_runtime_put(HIF_DEVICE *device) { return 0; } +static inline int +hif_pm_runtime_prevent_suspend(void *ol_sc, void *context) { return 0; } +static inline int +hif_pm_runtime_allow_suspend(void *ol_sc, void *context) { return 0; } +static inline int +hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, void *context, + unsigned int msec) +{ + return 0; +} +static inline void * +hif_runtime_pm_prevent_suspend_init(const char *name) { return NULL; } +static inline void +hif_runtime_pm_prevent_suspend_deinit(void *context) { } +#endif +#ifdef __cplusplus +} +#endif + +A_BOOL HIFIsMailBoxSwapped(HIF_DEVICE *hd); + +#endif /* _HIF_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif_msg_based.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif_msg_based.h new file mode 100644 index 000000000000..f7143aab3d48 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif_msg_based.h @@ -0,0 +1,155 @@ +/* + *Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +//============================================================================== +// HIF definitions for message based HIFs +//============================================================================== +#ifndef _HIF_MSG_BASED_H_ +#define _HIF_MSG_BASED_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "hif.h" + +/** + * @brief List of callbacks - filled in by HTC. + */ +typedef struct { + void *Context; /**< context meaningful to HTC */ + A_STATUS (*txCompletionHandler)(void *Context, adf_nbuf_t wbuf, + unsigned transferID); + A_STATUS (*rxCompletionHandler)(void *Context, adf_nbuf_t wbuf, + u_int8_t pipeID); + void (*txResourceAvailHandler)(void *context, u_int8_t pipe); + void (*fwEventHandler)(void *context, A_STATUS status); + void (*txResumeAllHandler)(void *context); +} MSG_BASED_HIF_CALLBACKS; + +int HIF_deregister(void); + +/** + * @brief: This API is used by the HTC layer to initialize the HIF layer and to + * register different callback routines. Support for following events has + * been captured - DSR, Read/Write completion, Device insertion/removal, + * Device suspension/resumption/wakeup. In addition to this, the API is + * also used to register the name and the revision of the chip. The latter + * can be used to verify the revision of the chip read from the device + * before reporting it to HTC. + * @param[in]: callbacks - List of HTC callbacks + * @param[out]: + * @return: an opaque HIF handle + */ +//void *HIFInit(void *hHTC, HTC_CALLBACKS *callbacks); + +void HIFPostInit(HIF_DEVICE *hifDevice, void *hHTC, MSG_BASED_HIF_CALLBACKS *callbacks); + +A_STATUS HIFStart(HIF_DEVICE *hifDevice); + +void HIFStop(HIF_DEVICE *hifDevice); +void HIFFlushSurpriseRemove(HIF_DEVICE *hifDevice); + +void HIFGrowBuffers(void* hif_hdl); + +void HIFDump(HIF_DEVICE *hifDevice, u_int8_t CmdId, bool start); +/** + * @brief: Send a buffer to HIF for transmission to the target. + * @param[in]: hifDevice - HIF handle + * @param[in]: pipeID - pipe to use + * @param[in]: hdr_buf - unused + * @param[in]: buf - buffer to send + * @param[out]: + * @return: Status of the send operation. + */ +int HIFSend(HIF_DEVICE *hifDevice, u_int8_t PipeID, + adf_nbuf_t hdr_buf, adf_nbuf_t wbuf); + +/** + * @brief: Send the head of a buffer to HIF for transmission to the target. + * @param[in]: hifDevice - HIF handle + * @param[in]: pipeID - pipe to use + * @param[in]: transferID - upper-layer ID for this transfer, used in the + * send completion callback to identify the transfer + * @param[in]: nbytes - number of initial bytes to send + * @param[in]: buf - buffer to send + * @param[out]: + * @return: Status of the send operation. + */ +int HIFSend_head(HIF_DEVICE *hifDevice, u_int8_t PipeID, + unsigned int transferID, unsigned int nbytes, adf_nbuf_t wbuf); + +/** + * @brief: Check if prior sends have completed. + * @details: + * Check whether the pipe in question has any completed sends that have + * not yet been processed. + * This function is only relevant for HIF pipes that are configured to be + * polled rather than interrupt-driven. + * + * @param[in]: hifDevice - HIF handle + * @param[in]: pipeID - pipe used for the prior sends + * @param[in]: force - whether this is a poll suggestion or poll command + */ +void HIFSendCompleteCheck(HIF_DEVICE *hifDevice, u_int8_t PipeID, int force); +void HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device); + +/** + * @brief: Shutdown the HIF layer. + * @param[in]: HIFHandle - opaque HIF handle. + * @param[out]: + * @return: + */ +void HIFShutDown(HIF_DEVICE *hifDevice); + +u_int32_t HIFQueryQueueDepth(HIF_DEVICE *hifDevice, u_int8_t epnum); + +void HIFGetDefaultPipe(HIF_DEVICE *hifDevice, u_int8_t *ULPipe, u_int8_t *DLPipe); + +int HIFMapServiceToPipe(HIF_DEVICE *hifDevice, u_int16_t ServiceId, u_int8_t *ULPipe, u_int8_t *DLPipe, int *ul_is_polled, int *dl_is_polled); + +u_int8_t HIFGetULPipeNum(void); +u_int8_t HIFGetDLPipeNum(void); + +//a_status_t HIFGetProductInfo(HIF_DEVICE *hifDevice, adf_net_dev_product_info_t *info); + +u_int16_t HIFGetFreeQueueNumber(HIF_DEVICE *hifDevice, u_int8_t PipeID); +u_int16_t HIFGetMaxQueueNumber(HIF_DEVICE *hifDevice, u_int8_t PipeID); + +void HIFDumpInfo(HIF_DEVICE *hifDevice); +void *hif_get_targetdef(HIF_DEVICE *hif_device); +void HIFsuspendwow(HIF_DEVICE *hif_device); +#if defined(HIF_SDIO) || defined(HIF_USB) +void HIFSetBundleMode(HIF_DEVICE *hif_device, bool enabled, int rx_bundle_cnt); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _HIF_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc.h new file mode 100644 index 000000000000..e61555ee6c45 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc.h @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __HTC_H__ +#define __HTC_H__ + +#ifndef ATH_TARGET +#include "athstartpack.h" +#endif +#undef MS +#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) +#undef SM +#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) +#undef WO +#define WO(_f) ((_f##_OFFSET) >> 2) + +#undef GET_FIELD +#define GET_FIELD(_addr, _f) MS(*((A_UINT32 *)(_addr) + WO(_f)), _f) +#undef SET_FIELD +#define SET_FIELD(_addr, _f, _val) \ + (*((A_UINT32 *)(_addr) + WO(_f)) = \ + (*((A_UINT32 *)(_addr) + WO(_f)) & ~_f##_MASK) | SM(_val, _f)) + +#define HTC_GET_FIELD(_msg_buf, _msg_type, _f) \ + GET_FIELD(_msg_buf, _msg_type ## _ ## _f) + +#define HTC_SET_FIELD(_msg_buf, _msg_type, _f, _val) \ + SET_FIELD(_msg_buf, _msg_type ## _ ## _f, _val) + +#define HTC_WRITE32(_addr, _val) \ + (*(A_UINT32 *)(_addr) = (_val)) + +#ifndef A_OFFSETOF +#define A_OFFSETOF(type,field) (unsigned long)(&(((type *)NULL)->field)) +#endif + +#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \ + (((A_UINT16)(((A_UINT8 *)(p))[(highbyte)])) << 8 | (A_UINT16)(((A_UINT8 *)(p))[(lowbyte)])) + +/****** DANGER DANGER *************** + * + * The frame header length and message formats defined herein were + * selected to accommodate optimal alignment for target processing. This reduces code + * size and improves performance. + * + * Any changes to the header length may alter the alignment and cause exceptions + * on the target. When adding to the message structures insure that fields are + * properly aligned. + * + */ + +/* HTC frame header */ +typedef PREPACK struct _HTC_FRAME_HDR{ + /* do not remove or re-arrange these fields, these are minimally required + * to take advantage of 4-byte lookaheads in some hardware implementations */ + A_UINT32 EndpointID : 8, + Flags : 8, + PayloadLen : 16; /* length of data (including trailer) that follows the header */ + + /***** end of 4-byte lookahead ****/ + + A_UINT32 ControlBytes0 : 8, /* used for CRC check if CRC_CHECK flag set */ + ControlBytes1 : 8, /* used for seq check if SEQ_CHECK flag set */ + reserved : 16; /* used by bundle processing in SDIO systems */ + + /* message payload starts after the header */ + +} POSTPACK HTC_FRAME_HDR; + +#define HTC_FRAME_HDR_ENDPOINTID_LSB 0 +#define HTC_FRAME_HDR_ENDPOINTID_MASK 0x000000ff +#define HTC_FRAME_HDR_ENDPOINTID_OFFSET 0x00000000 +#define HTC_FRAME_HDR_FLAGS_LSB 8 +#define HTC_FRAME_HDR_FLAGS_MASK 0x0000ff00 +#define HTC_FRAME_HDR_FLAGS_OFFSET 0x00000000 +#define HTC_FRAME_HDR_PAYLOADLEN_LSB 16 +#define HTC_FRAME_HDR_PAYLOADLEN_MASK 0xffff0000 +#define HTC_FRAME_HDR_PAYLOADLEN_OFFSET 0x00000000 +#define HTC_FRAME_HDR_CONTROLBYTES0_LSB 0 +#define HTC_FRAME_HDR_CONTROLBYTES0_MASK 0x000000ff +#define HTC_FRAME_HDR_CONTROLBYTES0_OFFSET 0x00000004 +#define HTC_FRAME_HDR_CONTROLBYTES1_LSB 8 +#define HTC_FRAME_HDR_CONTROLBYTES1_MASK 0x0000ff00 +#define HTC_FRAME_HDR_CONTROLBYTES1_OFFSET 0x00000004 +#define HTC_FRAME_HDR_RESERVED_LSB 16 +#define HTC_FRAME_HDR_RESERVED_MASK 0xffff0000 +#define HTC_FRAME_HDR_RESERVED_OFFSET 0x00000004 + +/* frame header flags */ + + /* send direction */ +#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) +#define HTC_FLAGS_SEND_BUNDLE (1 << 1) /* start or part of bundle */ +#define HTC_FLAGS_SEQ_CHECK (1 << 2) /* seq check on rx side */ +#define HTC_FLAGS_CRC CHECK (1 << 3) /* CRC check on rx side */ + + +/* New Flags definition in Receive Direction + + Bit 0 - Bundle trailer needs 1 extra block towards the end + If this bit is set, it implies that the last msg of the bundle has a + lookahead trailer and it needs additional block. + This bit is set in the 1st pack of the bundle. + It gives the host a heads up on the size it wants to receive. + + HOST calculates the total bundle length (for CMD53) as + + L = n * [padded length] + size of trailer information + n: number of msgs in the bundle + padded length: padded length of 1st msg of the bundle. + + + Bit 1- Recv Trailer is present, length of data is in control byte 0 + This is contained in the last packet of the bundle + + Bits 2-7 indicate the Bundle count. When non-zero the number of frames + behind the current frame with the same padded length. The split is : + + Bit 2..3 Higher 2 bits of Recv Bundle Count + Bit 4..7 Lower 4 bits of Recv Bundle Count + (This weird arrangement is to stick to legacy implementation where + only bits 4..7 were used) +*/ + + /* receive direction */ +#define HTC_FLAGS_RECV_1MORE_BLOCK (1 << 0) /*bit0 heads up-additional block*/ +#define HTC_FLAGS_RECV_TRAILER (1 << 1) /*bit1 trailer data present */ + +#define GET_RECV_BUNDLE_COUNT(f) (BUNDLE_COUNT_HIGH(f)+BUNDLE_COUNT_LOW(f)) + +/* high nibble*/ +#define BUNDLE_COUNT_HIGH(f) ((f & 0x0C) << 2) + +/* low nibble*/ +#define BUNDLE_COUNT_LOW(f) ((f & 0xF0) >> 4) + + +#define HTC_HDR_LENGTH (sizeof(HTC_FRAME_HDR)) +#define HTC_HDR_ALIGNMENT_PADDING \ + (((sizeof(HTC_FRAME_HDR) + 3) & (~0x3)) - sizeof(HTC_FRAME_HDR)) +#define HTC_MAX_TRAILER_LENGTH 255 +#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(HTC_FRAME_HDR)) + +/* HTC control message IDs */ + +#define HTC_MSG_READY_ID 1 +#define HTC_MSG_CONNECT_SERVICE_ID 2 +#define HTC_MSG_CONNECT_SERVICE_RESPONSE_ID 3 +#define HTC_MSG_SETUP_COMPLETE_ID 4 +#define HTC_MSG_SETUP_COMPLETE_EX_ID 5 +#define HTC_MSG_SEND_SUSPEND_COMPLETE 6 +#define HTC_MSG_NACK_SUSPEND 7 + +#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256 + +/* base message ID header */ +typedef PREPACK struct { + A_UINT32 MessageID : 16, + reserved : 16; +} POSTPACK HTC_UNKNOWN_MSG; + +#define HTC_UNKNOWN_MSG_MESSAGEID_LSB 0 +#define HTC_UNKNOWN_MSG_MESSAGEID_MASK 0x0000ffff +#define HTC_UNKNOWN_MSG_MESSAGEID_OFFSET 0x00000000 + +/* HTC ready message + * direction : target-to-host */ +typedef PREPACK struct { + A_UINT32 MessageID : 16, /* ID */ + CreditCount: 16; /* number of credits the target can offer */ + A_UINT32 CreditSize : 16, /* size of each credit */ + MaxEndpoints : 8, /* maximum number of endpoints the target has resources for */ + _Pad1 : 8; +} POSTPACK HTC_READY_MSG; + +#define HTC_READY_MSG_MESSAGEID_LSB 0 +#define HTC_READY_MSG_MESSAGEID_MASK 0x0000ffff +#define HTC_READY_MSG_MESSAGEID_OFFSET 0x00000000 +#define HTC_READY_MSG_CREDITCOUNT_LSB 16 +#define HTC_READY_MSG_CREDITCOUNT_MASK 0xffff0000 +#define HTC_READY_MSG_CREDITCOUNT_OFFSET 0x00000000 +#define HTC_READY_MSG_CREDITSIZE_LSB 0 +#define HTC_READY_MSG_CREDITSIZE_MASK 0x0000ffff +#define HTC_READY_MSG_CREDITSIZE_OFFSET 0x00000004 +#define HTC_READY_MSG_MAXENDPOINTS_LSB 16 +#define HTC_READY_MSG_MAXENDPOINTS_MASK 0x00ff0000 +#define HTC_READY_MSG_MAXENDPOINTS_OFFSET 0x00000004 + + /* extended HTC ready message */ +typedef PREPACK struct { + HTC_READY_MSG Version2_0_Info; /* legacy version 2.0 information at the front... */ + /* extended information */ + A_UINT32 HTCVersion : 8, + MaxMsgsPerHTCBundle : 8, + AltDataCreditSize : 12, + Reserved : 4; +} POSTPACK HTC_READY_EX_MSG; + +#define HTC_READY_EX_MSG_HTCVERSION_LSB 0 +#define HTC_READY_EX_MSG_HTCVERSION_MASK 0x000000ff +#define HTC_READY_EX_MSG_HTCVERSION_OFFSET sizeof(HTC_READY_MSG) + +#define HTC_READY_EX_MSG_MAXMSGSPERHTCBUNDLE_LSB 8 +#define HTC_READY_EX_MSG_MAXMSGSPERHTCBUNDLE_MASK 0x0000ff00 +#define HTC_READY_EX_MSG_MAXMSGSPERHTCBUNDLE_OFFSET sizeof(HTC_READY_MSG) + +#define HTC_READY_EX_MSG_ALTDATACREDITSIZE_LSB 16 +#define HTC_READY_EX_MSG_ALTDATACREDITSIZE_MASK 0x0fff0000 +#define HTC_READY_EX_MSG_ALTDATACREDITSIZE_OFFSET sizeof(HTC_READY_MSG) + +#define HTC_VERSION_2P0 0x00 +#define HTC_VERSION_2P1 0x01 /* HTC 2.1 */ + +#define HTC_SERVICE_META_DATA_MAX_LENGTH 128 + +/* connect service + * direction : host-to-target */ +typedef PREPACK struct { + A_UINT32 MessageID : 16, + ServiceID : 16; /* service ID of the service to connect to */ + A_UINT32 ConnectionFlags : 16, /* connection flags */ + +#define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when + the host needs credits */ +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK (0x3) +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH 0x0 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF 0x1 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS 0x2 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY 0x3 + /* disable credit flow control on a specific service */ +#define HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL (1 << 3) + /* enable htc schedule on a specific service */ +#define HTC_CONNECT_FLAGS_ENABLE_HTC_SCHEDULE (1 << 4) + + ServiceMetaLength : 8, /* length of meta data that follows */ + _Pad1 : 8; + + /* service-specific meta data starts after the header */ + +} POSTPACK HTC_CONNECT_SERVICE_MSG; + +#define HTC_CONNECT_SERVICE_MSG_MESSAGEID_LSB 0 +#define HTC_CONNECT_SERVICE_MSG_MESSAGEID_MASK 0x0000ffff +#define HTC_CONNECT_SERVICE_MSG_MESSAGEID_OFFSET 0x00000000 +#define HTC_CONNECT_SERVICE_MSG_SERVICE_ID_LSB 16 +#define HTC_CONNECT_SERVICE_MSG_SERVICE_ID_MASK 0xffff0000 +#define HTC_CONNECT_SERVICE_MSG_SERVICE_ID_OFFSET 0x00000000 +#define HTC_CONNECT_SERVICE_MSG_CONNECTIONFLAGS_LSB 0 +#define HTC_CONNECT_SERVICE_MSG_CONNECTIONFLAGS_MASK 0x0000ffff +#define HTC_CONNECT_SERVICE_MSG_CONNECTIONFLAGS_OFFSET 0x00000004 +#define HTC_CONNECT_SERVICE_MSG_SERVICEMETALENGTH_LSB 16 +#define HTC_CONNECT_SERVICE_MSG_SERVICEMETALENGTH_MASK 0x00ff0000 +#define HTC_CONNECT_SERVICE_MSG_SERVICEMETALENGTH_OFFSET 0x00000004 + +#define HTC_SET_RECV_ALLOC_SHIFT 8 +#define HTC_SET_RECV_ALLOC_MASK 0xFF00 +#define HTC_CONNECT_FLAGS_SET_RECV_ALLOCATION(value) (((A_UINT8)value) << HTC_SET_RECV_ALLOC_SHIFT) +#define HTC_CONNECT_FLAGS_GET_RECV_ALLOCATION(value) (A_UINT8)(((value) & HTC_SET_RECV_ALLOC_MASK) >> HTC_SET_RECV_ALLOC_SHIFT) + +/* connect response + * direction : target-to-host */ +typedef PREPACK struct { + A_UINT32 MessageID : 16, + ServiceID : 16; /* service ID that the connection request was made */ + A_UINT32 Status : 8, /* service connection status */ + EndpointID : 8, /* assigned endpoint ID */ + MaxMsgSize : 16; /* maximum expected message size on this endpoint */ + A_UINT32 ServiceMetaLength : 8, /* length of meta data that follows */ + _Pad1 : 8, + reserved : 16; + + /* service-specific meta data starts after the header */ + +} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG; + +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_MESSAGEID_LSB 0 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_MESSAGEID_MASK 0x0000ffff +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_MESSAGEID_OFFSET 0x00000000 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEID_LSB 16 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEID_MASK 0xffff0000 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEID_OFFSET 0x00000000 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_STATUS_LSB 0 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_STATUS_MASK 0x000000ff +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_STATUS_OFFSET 0x00000004 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_ENDPOINTID_LSB 8 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_ENDPOINTID_MASK 0x0000ff00 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_ENDPOINTID_OFFSET 0x00000004 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_MAXMSGSIZE_LSB 16 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_MAXMSGSIZE_MASK 0xffff0000 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_MAXMSGSIZE_OFFSET 0x00000004 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEMETALENGTH_LSB 0 +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEMETALENGTH_MASK 0x000000ff +#define HTC_CONNECT_SERVICE_RESPONSE_MSG_SERVICEMETALENGTH_OFFSET 0x00000008 + +typedef PREPACK struct { + A_UINT32 MessageID : 16, + reserved : 16; + /* currently, no other fields */ +} POSTPACK HTC_SETUP_COMPLETE_MSG; + +#define HTC_SETUP_COMPLETE_MSG_MESSAGEID_LSB 0 +#define HTC_SETUP_COMPLETE_MSG_MESSAGEID_MASK 0x0000ffff +#define HTC_SETUP_COMPLETE_MSG_MESSAGEID_OFFSET 0x00000000 + + /* extended setup completion message */ +typedef PREPACK struct { + A_UINT32 MessageID : 16, + reserved : 16; + A_UINT32 SetupFlags : 32; + A_UINT32 MaxMsgsPerBundledRecv : 8, + Rsvd0 : 8, + Rsvd1 : 8, + Rsvd2 : 8; +} POSTPACK HTC_SETUP_COMPLETE_EX_MSG; + +#define HTC_SETUP_COMPLETE_EX_MSG_MESSAGEID_LSB 0 +#define HTC_SETUP_COMPLETE_EX_MSG_MESSAGEID_MASK 0x0000ffff +#define HTC_SETUP_COMPLETE_EX_MSG_MESSAGEID_OFFSET 0x00000000 +#define HTC_SETUP_COMPLETE_EX_MSG_SETUPFLAGS_LSB 0 +#define HTC_SETUP_COMPLETE_EX_MSG_SETUPFLAGS_MASK 0xffffffff +#define HTC_SETUP_COMPLETE_EX_MSG_SETUPFLAGS_OFFSET 0x00000004 +#define HTC_SETUP_COMPLETE_EX_MSG_MAXMSGSPERBUNDLEDRECV_LSB 0 +#define HTC_SETUP_COMPLETE_EX_MSG_MAXMSGSPERBUNDLEDRECV_MASK 0x000000ff +#define HTC_SETUP_COMPLETE_EX_MSG_MAXMSGSPERBUNDLEDRECV_OFFSET 0x00000008 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD0_LSB 8 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD0_MASK 0x0000ff00 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD0_OFFSET 0x00000008 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD1_LSB 16 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD1_MASK 0x00ff0000 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD1_OFFSET 0x00000008 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD2_LSB 24 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD2_MASK 0xff000000 +#define HTC_SETUP_COMPLETE_EX_MSG_RSVD2_OFFSET 0x00000008 + +#define HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV (1 << 0) /* enable recv bundling from target */ +#define HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW (1 << 1) /* disable credit based flow control, + only supported on some interconnects */ + +/* connect response status codes */ +#define HTC_SERVICE_SUCCESS 0 /* success */ +#define HTC_SERVICE_NOT_FOUND 1 /* service could not be found */ +#define HTC_SERVICE_FAILED 2 /* specific service failed the connect */ +#define HTC_SERVICE_NO_RESOURCES 3 /* no resources (i.e. no more endpoints) */ +#define HTC_SERVICE_NO_MORE_EP 4 /* specific service is not allowing any more + endpoints */ + +/* report record IDs */ + +#define HTC_RECORD_NULL 0 +#define HTC_RECORD_CREDITS 1 +#define HTC_RECORD_LOOKAHEAD 2 +#define HTC_RECORD_LOOKAHEAD_BUNDLE 3 + +typedef PREPACK struct { + A_UINT32 RecordID : 8, /* Record ID */ + Length : 8, /* Length of record */ + reserved : 16; +} POSTPACK HTC_RECORD_HDR; + +#define HTC_RECORD_HDR_RECORDID_LSB 0 +#define HTC_RECORD_HDR_RECORDID_MASK 0x000000ff +#define HTC_RECORD_HDR_RECORDID_OFFSET 0x00000000 +#define HTC_RECORD_HDR_LENGTH_LSB 8 +#define HTC_RECORD_HDR_LENGTH_MASK 0x0000ff00 +#define HTC_RECORD_HDR_LENGTH_OFFSET 0x00000000 + +typedef PREPACK struct { + A_UINT32 EndpointID : 8, /* Endpoint that owns these credits */ + Credits : 8, /* credits to report since last report */ + reserved : 16; +} POSTPACK HTC_CREDIT_REPORT; + +#define HTC_CREDIT_REPORT_ENDPOINTID_LSB 0 +#define HTC_CREDIT_REPORT_ENDPOINTID_MASK 0x000000ff +#define HTC_CREDIT_REPORT_ENDPOINTID_OFFSET 0x00000000 +#define HTC_CREDIT_REPORT_CREDITS_LSB 8 +#define HTC_CREDIT_REPORT_CREDITS_MASK 0x0000ff00 +#define HTC_CREDIT_REPORT_CREDITS_OFFSET 0x00000000 + +typedef PREPACK struct { + A_UINT32 PreValid : 8, /* pre valid guard */ + reserved0 : 24; + A_UINT32 LookAhead0 : 8, /* 4 byte lookahead */ + LookAhead1 : 8, + LookAhead2 : 8, + LookAhead3 : 8; + A_UINT32 PostValid : 8, /* post valid guard */ + reserved1 : 24; + + /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes. + * The PreValid bytes must equal the inverse of the PostValid byte */ + +} POSTPACK HTC_LOOKAHEAD_REPORT; + +#define HTC_LOOKAHEAD_REPORT_PREVALID_LSB 0 +#define HTC_LOOKAHEAD_REPORT_PREVALID_MASK 0x000000ff +#define HTC_LOOKAHEAD_REPORT_PREVALID_OFFSET 0x00000000 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD0_LSB 0 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD0_MASK 0x000000ff +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD0_OFFSET 0x00000004 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD1_LSB 8 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD1_MASK 0x0000ff00 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD1_OFFSET 0x00000004 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD2_LSB 16 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD2_MASK 0x00ff0000 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD2_OFFSET 0x00000004 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD3_LSB 24 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD3_MASK 0xff000000 +#define HTC_LOOKAHEAD_REPORT_LOOKAHEAD3_OFFSET 0x00000004 +#define HTC_LOOKAHEAD_REPORT_POSTVALID_LSB 0 +#define HTC_LOOKAHEAD_REPORT_POSTVALID_MASK 0x000000ff +#define HTC_LOOKAHEAD_REPORT_POSTVALID_OFFSET 0x00000008 + +typedef PREPACK struct { + A_UINT32 LookAhead0 : 8, /* 4 byte lookahead */ + LookAhead1 : 8, + LookAhead2 : 8, + LookAhead3 : 8; +} POSTPACK HTC_BUNDLED_LOOKAHEAD_REPORT; + +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD0_LSB 0 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD0_MASK 0x000000ff +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD0_OFFSET 0x00000000 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD1_LSB 8 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD1_MASK 0x0000ff00 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD1_OFFSET 0x00000000 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD2_LSB 16 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD2_MASK 0x00ff0000 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD2_OFFSET 0x00000000 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD3_LSB 24 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD3_MASK 0xff000000 +#define HTC_BUNDLED_LOOKAHEAD_REPORT_LOOKAHEAD3_OFFSET 0x00000000 + +#ifndef ATH_TARGET +#include "athendpack.h" +#endif + + +#endif /* __HTC_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_api.h new file mode 100644 index 000000000000..46b9f77700bb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_api.h @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _HTC_API_H_ +#define _HTC_API_H_ + +#include +#include "osapi_linux.h" +#include "htc_packet.h" +#include +#include +#include /* adf_os_device_t */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* TODO.. for BMI */ +#define ENDPOINT1 0 +// TODO -remove me, but we have to fix BMI first +#define HTC_MAILBOX_NUM_MAX 4 + +/* this is the amount of header room required by users of HTC */ +#define HTC_HEADER_LEN HTC_HDR_LENGTH + +typedef void *HTC_HANDLE; + +typedef A_UINT16 HTC_SERVICE_ID; + +typedef void (*HTC_TARGET_FAILURE)(void *Instance, A_STATUS Status); + +typedef struct _HTC_INIT_INFO { + void *pContext; /* context for target notifications */ + void (*TargetFailure)(void *Instance, A_STATUS Status); + void (*TargetSendSuspendComplete)(void *ctx); +} HTC_INIT_INFO; + +/* Struct for HTC layer packet stats*/ +struct ol_ath_htc_stats { + int htc_get_pkt_q_fail_count; + int htc_pkt_q_empty_count; + int htc_send_q_empty_count; +}; + +/* To resume HTT Tx queue during runtime resume */ +typedef void (*HTC_EP_RESUME_TX_QUEUE)(void *); +/* per service connection send completion */ +typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,HTC_PACKET *); +/* per service connection callback when a plurality of packets have been sent + * The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback) + * to hold a list of completed send packets. + * If the handler cannot fully traverse the packet queue before returning, it should + * transfer the items of the queue into the caller's private queue using: + * HTC_PACKET_ENQUEUE() */ +typedef void (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,HTC_PACKET_QUEUE *); +/* per service connection pkt received */ +typedef void (*HTC_EP_RECV_PKT)(void *,HTC_PACKET *); +/* per service connection callback when a plurality of packets are received + * The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback) + * to hold a list of recv packets. + * If the handler cannot fully traverse the packet queue before returning, it should + * transfer the items of the queue into the caller's private queue using: + * HTC_PACKET_ENQUEUE() */ +typedef void (*HTC_EP_RECV_PKT_MULTIPLE)(void *,HTC_PACKET_QUEUE *); + +/* Optional per service connection receive buffer re-fill callback, + * On some OSes (like Linux) packets are allocated from a global pool and indicated up + * to the network stack. The driver never gets the packets back from the OS. For these OSes + * a refill callback can be used to allocate and re-queue buffers into HTC. + * + * On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and + * the driver can re-queue these buffers into HTC. In this regard a refill callback is + * unnecessary */ +typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint); + +/* Optional per service connection receive buffer allocation callback. + * On some systems packet buffers are an extremely limited resource. Rather than + * queue largest-possible-sized buffers to HTC, some systems would rather + * allocate a specific size as the packet is received. The trade off is + * slightly more processing (callback invoked for each RX packet) + * for the benefit of committing fewer buffer resources into HTC. + * + * The callback is provided the length of the pending packet to fetch. This includes the + * HTC header length plus the length of payload. The callback can return a pointer to + * the allocated HTC packet for immediate use. + * + * Alternatively a variant of this handler can be used to allocate large receive packets as needed. + * For example an application can use the refill mechanism for normal packets and the recv-alloc mechanism to + * handle the case where a large packet buffer is required. This can significantly reduce the + * amount of "committed" memory used to receive packets. + * + * */ +typedef HTC_PACKET *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length); + +typedef enum _HTC_SEND_FULL_ACTION { + HTC_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */ + HTC_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */ +} HTC_SEND_FULL_ACTION; + +/* Optional per service connection callback when a send queue is full. This can occur if the + * host continues queueing up TX packets faster than credits can arrive + * To prevent the host (on some Oses like Linux) from continuously queueing packets + * and consuming resources, this callback is provided so that that the host + * can disable TX in the subsystem (i.e. network stack). + * This callback is invoked for each packet that "overflows" the HTC queue. The callback can + * determine whether the new packet that overflowed the queue can be kept (HTC_SEND_FULL_KEEP) or + * dropped (HTC_SEND_FULL_DROP). If a packet is dropped, the EpTxComplete handler will be called + * and the packet's status field will be set to A_NO_RESOURCE. + * Other OSes require a "per-packet" indication for each completed TX packet, this + * closed loop mechanism will prevent the network stack from overunning the NIC + * The packet to keep or drop is passed for inspection to the registered handler the handler + * must ONLY inspect the packet, it may not free or reclaim the packet. */ +typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_PACKET *pPacket); + +typedef struct _HTC_EP_CALLBACKS { + void *pContext; /* context for each callback */ + HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */ + HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */ + HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */ + HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */ + HTC_EP_RECV_ALLOC EpRecvAlloc; /* OPTIONAL recv allocation callback */ + HTC_EP_RESUME_TX_QUEUE EpResumeTxQueue; /*OPTIONAL for WMI. Needed for HTT Service */ + HTC_EP_RECV_ALLOC EpRecvAllocThresh; /* OPTIONAL recv allocation callback based on a threshold */ + HTC_EP_SEND_PKT_COMP_MULTIPLE EpTxCompleteMultiple; /* OPTIONAL completion handler for multiple complete + indications (EpTxComplete must be NULL) */ + HTC_EP_RECV_PKT_MULTIPLE EpRecvPktMultiple; /* OPTIONAL completion handler for multiple + recv packet indications (EpRecv must be NULL) */ + int RecvAllocThreshold; /* if EpRecvAllocThresh is non-NULL, HTC will compare the + threshold value to the current recv packet length and invoke + the EpRecvAllocThresh callback to acquire a packet buffer */ + int RecvRefillWaterMark; /* if a EpRecvRefill handler is provided, this value + can be used to set a trigger refill callback + when the recv queue drops below this value + if set to 0, the refill is only called when packets + are empty */ +} HTC_EP_CALLBACKS; + +/* service connection information */ +typedef struct _HTC_SERVICE_CONNECT_REQ { + HTC_SERVICE_ID ServiceID; /* service ID to connect to */ + A_UINT16 ConnectionFlags; /* connection flags, see htc protocol definition */ + A_UINT8 *pMetaData; /* ptr to optional service-specific meta-data */ + A_UINT8 MetaDataLength; /* optional meta data length */ + HTC_EP_CALLBACKS EpCallbacks; /* endpoint callbacks */ + int MaxSendQueueDepth; /* maximum depth of any send queue */ + A_UINT32 LocalConnectionFlags; /* HTC flags for the host-side (local) connection */ + unsigned int MaxSendMsgSize; /* override max message size in send direction */ +} HTC_SERVICE_CONNECT_REQ; + +#define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0) /* enable send bundle padding for this endpoint */ + +/* service connection response information */ +typedef struct _HTC_SERVICE_CONNECT_RESP { + A_UINT8 *pMetaData; /* caller supplied buffer to optional meta-data */ + A_UINT8 BufferLength; /* length of caller supplied buffer */ + A_UINT8 ActualLength; /* actual length of meta data */ + HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */ + unsigned int MaxMsgLength; /* max length of all messages over this endpoint */ + A_UINT8 ConnectRespCode; /* connect response code from target */ +} HTC_SERVICE_CONNECT_RESP; + +/* endpoint distribution structure */ +typedef struct _HTC_ENDPOINT_CREDIT_DIST { + struct _HTC_ENDPOINT_CREDIT_DIST *pNext; + struct _HTC_ENDPOINT_CREDIT_DIST *pPrev; + HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */ + HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */ + A_UINT32 DistFlags; /* distribution flags, distribution function can + set default activity using SET_EP_ACTIVE() macro */ + int TxCreditsNorm; /* credits for normal operation, anything above this + indicates the endpoint is over-subscribed, this field + is only relevant to the credit distribution function */ + int TxCreditsMin; /* floor for credit distribution, this field is + only relevant to the credit distribution function */ + int TxCreditsAssigned; /* number of credits assigned to this EP, this field + is only relevant to the credit dist function */ + int TxCredits; /* current credits available, this field is used by + HTC to determine whether a message can be sent or + must be queued */ + int TxCreditsToDist; /* pending credits to distribute on this endpoint, this + is set by HTC when credit reports arrive. + The credit distribution functions sets this to zero + when it distributes the credits */ + int TxCreditsSeek; /* this is the number of credits that the current pending TX + packet needs to transmit. This is set by HTC when + and endpoint needs credits in order to transmit */ + int TxCreditSize; /* size in bytes of each credit (set by HTC) */ + int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */ + void *pHTCReserved; /* reserved for HTC use */ + int TxQueueDepth; /* current depth of TX queue , i.e. messages waiting for credits + This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE + or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint + that has non-zero credits to recover + */ +} HTC_ENDPOINT_CREDIT_DIST; + +#define HTC_EP_ACTIVE ((A_UINT32) (1u << 31)) + +/* macro to check if an endpoint has gone active, useful for credit + * distributions */ +#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE) +#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE + + /* credit distibution code that is passed into the distrbution function, + * there are mandatory and optional codes that must be handled */ +typedef enum _HTC_CREDIT_DIST_REASON { + HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed + send operations (MANDATORY) resulting in credit reports */ + HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occured (OPTIONAL) */ + HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */ + HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by + the distribution function */ +} HTC_CREDIT_DIST_REASON; + +typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context, + HTC_ENDPOINT_CREDIT_DIST *pEPList, + HTC_CREDIT_DIST_REASON Reason); + +typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context, + HTC_ENDPOINT_CREDIT_DIST *pEPList, + int TotalCredits); + + /* endpoint statistics action */ +typedef enum _HTC_ENDPOINT_STAT_ACTION { + HTC_EP_STAT_SAMPLE = 0, /* only read statistics */ + HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */ + HTC_EP_STAT_CLEAR /* clear only */ +} HTC_ENDPOINT_STAT_ACTION; + + /* endpoint statistics */ +typedef struct _HTC_ENDPOINT_STATS { + A_UINT32 TxPosted; /* number of TX packets posted to the endpoint */ + A_UINT32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on + this endpoint */ + A_UINT32 TxIssued; /* running count of total TX packets issued */ + A_UINT32 TxPacketsBundled; /* running count of TX packets that were issued in bundles */ + A_UINT32 TxBundles; /* running count of TX bundles that were issued */ + A_UINT32 TxDropped; /* tx packets that were dropped */ + A_UINT32 TxCreditRpts; /* running count of total credit reports received for this endpoint */ + A_UINT32 TxCreditRptsFromRx; /* credit reports received from this endpoint's RX packets */ + A_UINT32 TxCreditRptsFromOther; /* credit reports received from RX packets of other endpoints */ + A_UINT32 TxCreditRptsFromEp0; /* credit reports received from endpoint 0 RX packets */ + A_UINT32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */ + A_UINT32 TxCreditsFromOther; /* count of credits received via another endpoint */ + A_UINT32 TxCreditsFromEp0; /* count of credits received via another endpoint */ + A_UINT32 TxCreditsConsummed; /* count of consummed credits */ + A_UINT32 TxCreditsReturned; /* count of credits returned */ + A_UINT32 RxReceived; /* count of RX packets received */ + A_UINT32 RxLookAheads; /* count of lookahead records + found in messages received on this endpoint */ + A_UINT32 RxPacketsBundled; /* count of recv packets received in a bundle */ + A_UINT32 RxBundleLookAheads; /* count of number of bundled lookaheads */ + A_UINT32 RxBundleIndFromHdr; /* count of the number of bundle indications from the HTC header */ + A_UINT32 RxAllocThreshHit; /* count of the number of times the recv allocation threshhold was hit */ + A_UINT32 RxAllocThreshBytes; /* total number of bytes */ + + A_UINT32 HIFDSRCount; /* total number of interrupts */ + +} HTC_ENDPOINT_STATS; + +/* ------ Function Prototypes ------ */ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Create an instance of HTC over the underlying HIF device + @function name: HTCCreate + @input: HifDevice - hif device handle, + pInfo - initialization information + @output: + @return: HTC_HANDLE on success, NULL on failure + @notes: + @example: + @see also: HTCDestroy ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +HTC_HANDLE HTCCreate(void *HifDevice, + HTC_INIT_INFO *pInfo, + adf_os_device_t osdev); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the underlying HIF device handle + @function name: HTCGetHifDevice + @input: HTCHandle - handle passed into the AddInstance callback + @output: + @return: opaque HIF device handle usable in HIF API calls. + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void *HTCGetHifDevice(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set credit distribution parameters + @function name: HTCSetCreditDistribution + @input: HTCHandle - HTC handle + pCreditDistCont - caller supplied context to pass into distribution functions + CreditDistFunc - Distribution function callback + CreditDistInit - Credit Distribution initialization callback + ServicePriorityOrder - Array containing list of service IDs, lowest index is highest + priority + ListLength - number of elements in ServicePriorityOrder + @output: + @return: + @notes: The user can set a custom credit distribution function to handle special requirements + for each endpoint. A default credit distribution routine can be used by setting + CreditInitFunc to NULL. The default credit distribution is only provided for simple + "fair" credit distribution without regard to any prioritization. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, + void *pCreditDistContext, + HTC_CREDIT_DIST_CALLBACK CreditDistFunc, + HTC_CREDIT_INIT_CALLBACK CreditInitFunc, + HTC_SERVICE_ID ServicePriorityOrder[], + int ListLength); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Wait for the target to indicate the HTC layer is ready + @function name: HTCWaitTarget + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This API blocks until the target responds with an HTC ready message. + The caller should not connect services until the target has indicated it is + ready. + @example: + @see also: HTCConnectService ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Start target service communications + @function name: HTCStart + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This API indicates to the target that the service connection phase is complete + and the target can freely start all connected services. This API should only be + called AFTER all service connections have been made. TCStart will issue a + SETUP_COMPLETE message to the target to indicate that all service connections + have been made and the target can start communicating over the endpoints. + @example: + @see also: HTCConnectService ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCStart(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add receive packet to HTC + @function name: HTCAddReceivePkt + @input: HTCHandle - HTC handle + pPacket - HTC receive packet to add + @output: + @return: A_OK on success + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Connect to an HTC service + @function name: HTCConnectService + @input: HTCHandle - HTC handle + pReq - connection details + @output: pResp - connection response + @return: + @notes: Service connections must be performed before HTCStart. User provides callback handlers + for various endpoint events. + @example: + @see also: HTCStart ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, + HTC_SERVICE_CONNECT_REQ *pReq, + HTC_SERVICE_CONNECT_RESP *pResp); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: HTC register log dump + @function name: HTCDump + @input: HTCHandle - HTC handle + CmdId - Log command + start - start/print logs + @output: + @return: + @notes: Register logs will be started/printed. + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +void HTCDump(HTC_HANDLE HTCHandle, u_int8_t CmdId, bool start); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HTC packet + @function name: HTCSendPkt + @input: HTCHandle - HTC handle + pPacket - packet to send + @output: + @return: A_OK + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro. + This interface is fully asynchronous. On error, HTC SendPkt will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: HTCFlushEndpoint ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HTC packet containing a tx descriptor and data + @function name: HTCSendDataPkt + @input: HTCHandle - HTC handle + pPacket - packet to send + @output: + @return: A_OK + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro. + Caller must provide headroom in an initial fragment added to the + network buffer to store a HTC_FRAME_HDR. + This interface is fully asynchronous. On error, HTCSendDataPkt will + call the registered Endpoint EpDataTxComplete callback to cleanup + the packet. + @example: + @see also: HTCSendPkt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#ifdef ATH_11AC_TXCOMPACT +A_STATUS HTCSendDataPkt(HTC_HANDLE HTCHandle, adf_nbuf_t netbuf, + int Epid, int ActualLength); +#else /*ATH_11AC_TXCOMPACT*/ +A_STATUS HTCSendDataPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, + A_UINT8 more_data); +#endif /*ATH_11AC_TXCOMPACT*/ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Flush HTC when target is removed surprisely service communications + @function name: HTCFlushSurpriseRemove + @input: HTCHandle - HTC handle + @output: + @return: + @notes: All receive and pending TX packets will + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCFlushSurpriseRemove(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Stop HTC service communications + @function name: HTCStop + @input: HTCHandle - HTC handle + @output: + @return: + @notes: HTC communications is halted. All receive and pending TX packets will + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCStop(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Destory HTC service + @function name: HTCDestroy + @input: HTCHandle + @output: + @return: + @notes: This cleans up all resources allocated by HTCCreate(). + @example: + @see also: HTCCreate ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCDestroy(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Flush pending TX packets + @function name: HTCFlushEndpoint + @input: HTCHandle - HTC handle + Endpoint - Endpoint to flush + Tag - flush tag + @output: + @return: + @notes: The Tag parameter is used to selectively flush packets with matching tags. + The value of 0 forces all packets to be flush regardless of tag. + @example: + @see also: HTCSendPkt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Dump credit distribution state + @function name: HTCDumpCreditStates + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This dumps all credit distribution information to the debugger + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCDumpCreditStates(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Indicate a traffic activity change on an endpoint + @function name: HTCIndicateActivityChange + @input: HTCHandle - HTC handle + Endpoint - endpoint in which activity has changed + Active - TRUE if active, FALSE if it has become inactive + @output: + @return: + @notes: This triggers the registered credit distribution function to + re-adjust credits for active/inactive endpoints. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + A_BOOL Active); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get endpoint statistics + @function name: HTCGetEndpointStatistics + @input: HTCHandle - HTC handle + Endpoint - Endpoint identifier + Action - action to take with statistics + @output: + pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR) + + @return: TRUE if statistics profiling is enabled, otherwise FALSE. + + @notes: Statistics is a compile-time option and this function may return FALSE + if HTC is not compiled with profiling. + + The caller can specify the statistic "action" to take when sampling + the statistics. This includes: + + HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values. + HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics + are cleared. + HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for + pStats + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + HTC_ENDPOINT_STATS *pStats); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Unblock HTC message reception + @function name: HTCUnblockRecv + @input: HTCHandle - HTC handle + @output: + @return: + @notes: + HTC will block the receiver if the EpRecvAlloc callback fails to provide a packet. + The caller can use this API to indicate to HTC when resources (buffers) are available + such that the receiver can be unblocked and HTC may re-attempt fetching the pending message. + + This API is not required if the user uses the EpRecvRefill callback or uses the HTCAddReceivePacket() + API to recycle or provide receive packets to HTC. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCUnblockRecv(HTC_HANDLE HTCHandle); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: send a series of HTC packets + @function name: HTCSendPktsMultiple + @input: HTCHandle - HTC handle + pPktQueue - local queue holding packets to send + @output: + @return: A_OK + @notes: Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro. + The queue must only contain packets directed at the same endpoint. + Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the TX packets in FIFO order. + This API will remove the packets from the pkt queue and place them into the HTC Tx Queue + and bundle messages where possible. + The caller may allocate the pkt queue on the stack to hold the packets. + This interface is fully asynchronous. On error, HTCSendPkts will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: HTCFlushEndpoint ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add multiple receive packets to HTC + @function name: HTCAddReceivePktMultiple + @input: HTCHandle - HTC handle + pPktQueue - HTC receive packet queue holding packets to add + @output: + @return: A_OK on success + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. The queue must only contain recv packets for the same endpoint. + Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the recv packet. + This API will remove the packets from the pkt queue and place them into internal + recv packet list. + The caller may allocate the pkt queue on the stack to hold the packets. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Check if an endpoint is marked active + @function name: HTCIsEndpointActive + @input: HTCHandle - HTC handle + Endpoint - endpoint to check for active state + @output: + @return: returns TRUE if Endpoint is Active + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_BOOL HTCIsEndpointActive(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the number of recv buffers currently queued into an HTC endpoint + @function name: HTCGetNumRecvBuffers + @input: HTCHandle - HTC handle + Endpoint - endpoint to check + @output: + @return: returns number of buffers in queue + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set the target failure handling callback in HTC layer + @function name: HTCSetTargetFailureCallback + @input: HTCHandle - HTC handle + Callback - target failure handling callback + @output: + @return: + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCSetTargetFailureCallback(HTC_HANDLE HTCHandle, + HTC_TARGET_FAILURE Callback); + +/* internally used functions for testing... */ +void HTCEnableRecv(HTC_HANDLE HTCHandle); +void HTCDisableRecv(HTC_HANDLE HTCHandle); +A_STATUS HTCWaitForPendingRecv(HTC_HANDLE HTCHandle, + A_UINT32 TimeoutInMs, + A_BOOL *pbIsRecvPending); + +/* function to fetch stats from htc layer*/ +struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle); + +#ifdef HIF_USB +#define HTCReturnReceivePkt(target,p,osbuf) \ + A_NETBUF_FREE(osbuf); \ + if(p->Status == A_CLONE) { \ + A_FREE(p); \ + } +#else +#define HTCReturnReceivePkt(target,p,osbuf) HTCAddReceivePkt(target,p) +#endif + +#ifdef __cplusplus +} +#endif + +void HTCGetControlEndpointTxHostCredits(HTC_HANDLE HTCHandle, int *credit); +void HTC_dump_counter_info(HTC_HANDLE HTCHandle); +void *htc_get_targetdef(HTC_HANDLE htc_handle); +void HTCSetTargetToSleep(void *context); +void HTCCancelDeferredTargetSleep(void *context); + +/* Disable ASPM : Disable PCIe low power */ +void htc_disable_aspm(void); + +#ifdef IPA_UC_OFFLOAD +void HTCIpaGetCEResource(HTC_HANDLE htc_handle, + a_uint32_t *ce_sr_base_paddr, + a_uint32_t *ce_sr_ring_size, + a_uint32_t *ce_reg_paddr); +#endif/* IPA_UC_OFFLOAD */ + + +void HTCEndpointDumpCreditStats(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint); +void HTCDumpBundleStats(HTC_HANDLE HTCHandle); +void HTCClearBundleStats(HTC_HANDLE HTCHandle); + +#ifdef FEATURE_RUNTIME_PM +int htc_pm_runtime_get(HTC_HANDLE htc_handle); +int htc_pm_runtime_put(HTC_HANDLE htc_handle); +#else +static inline int htc_pm_runtime_get(HTC_HANDLE htc_handle) { return 0; } +static inline int htc_pm_runtime_put(HTC_HANDLE htc_handle) { return 0; } +#endif +#endif /* _HTC_API_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_packet.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_packet.h new file mode 100644 index 000000000000..ce4532fd071d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_packet.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef HTC_PACKET_H_ +#define HTC_PACKET_H_ + +#include +#include /* A_UINT16, etc. */ +#include "dl_list.h" + +/* ------ Endpoint IDS ------ */ +typedef enum +{ + ENDPOINT_UNUSED = -1, + ENDPOINT_0 = 0, + ENDPOINT_1 = 1, + ENDPOINT_2 = 2, + ENDPOINT_3, + ENDPOINT_4, + ENDPOINT_5, + ENDPOINT_6, + ENDPOINT_7, + ENDPOINT_8, + ENDPOINT_MAX, +} HTC_ENDPOINT_ID; + +struct _HTC_PACKET; + +typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *); + +typedef A_UINT16 HTC_TX_TAG; + +typedef struct _HTC_TX_PACKET_INFO { + HTC_TX_TAG Tag; /* tag used to selective flush packets */ + int CreditsUsed; /* number of credits used for this TX packet (HTC internal) */ + A_UINT8 SendFlags; /* send flags (HTC internal) */ + int SeqNo; /* internal seq no for debugging (HTC internal) */ + A_UINT32 Flags; /* internal use */ +} HTC_TX_PACKET_INFO; + +#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */ +#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */ +#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */ +#define HTC_TX_PACKET_TAG_BUNDLED HTC_TX_PACKET_TAG_USER_DEFINED + 1 /* indicate this is bundled TX packet */ +#define HTC_TX_PACKET_TAG_AUTO_PM HTC_TX_PACKET_TAG_USER_DEFINED + 2 /* indicate this is AUTO PM tagged */ +#define HTC_TX_PACKET_TAG_RUNTIME_PUT HTC_TX_PACKET_TAG_USER_DEFINED + 3 /* To indicate HTC to do PUT for these packets as these packets doesn't get the tx complete */ + +#define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0) + +typedef struct _HTC_RX_PACKET_INFO { + A_UINT32 ExpectedHdr; /* HTC internal use */ + A_UINT32 HTCRxFlags; /* HTC internal use */ + A_UINT32 IndicationFlags; /* indication flags set on each RX packet indication */ +} HTC_RX_PACKET_INFO; + +#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) /* more packets on this endpoint are being fetched */ + +/* wrapper around endpoint-specific packets */ +typedef struct _HTC_PACKET { + DL_LIST ListLink; /* double link */ + void *pPktContext; /* caller's per packet specific context */ + + A_UINT8 *pBufferStart; /* the true buffer start , the caller can + store the real buffer start here. In + receive callbacks, the HTC layer sets pBuffer + to the start of the payload past the header. This + field allows the caller to reset pBuffer when it + recycles receive packets back to HTC */ + /* + * Pointer to the start of the buffer. In the transmit + * direction this points to the start of the payload. In the + * receive direction, however, the buffer when queued up + * points to the start of the HTC header but when returned + * to the caller points to the start of the payload + */ + A_UINT8 *pBuffer; /* payload start (RX/TX) */ + A_UINT32 BufferLength; /* length of buffer */ + A_UINT32 ActualLength; /* actual length of payload */ + HTC_ENDPOINT_ID Endpoint; /* endpoint that this packet was sent/recv'd from */ + A_STATUS Status; /* completion status */ + union { + HTC_TX_PACKET_INFO AsTx; /* Tx Packet specific info */ + HTC_RX_PACKET_INFO AsRx; /* Rx Packet specific info */ + } PktInfo; + + /* the following fields are for internal HTC use */ + A_UINT32 netbufOrigHeadRoom; + HTC_PACKET_COMPLETION Completion; /* completion */ + void *pContext; /* HTC private completion context */ + void *pNetBufContext; /* optimization for network-oriented data, the HTC packet + can pass the network buffer corresponding to the HTC packet + lower layers may optimized the transfer knowing this is + a network buffer */ +} HTC_PACKET; + + + +#define COMPLETE_HTC_PACKET(p,status) \ +{ \ + (p)->Status = (status); \ + (p)->Completion((p)->pContext,(p)); \ +} + +#define INIT_HTC_PACKET_INFO(p,b,len) \ +{ \ + (p)->pBufferStart = (b); \ + (p)->BufferLength = (len); \ +} + +/* macro to set an initial RX packet for refilling HTC */ +#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \ +{ \ + (p)->pPktContext = (c); \ + (p)->pBuffer = (b); \ + (p)->pBufferStart = (b); \ + (p)->BufferLength = (len); \ + (p)->Endpoint = (ep); \ +} + +/* fast macro to recycle an RX packet that will be re-queued to HTC */ +#define HTC_PACKET_RESET_RX(p) \ + { (p)->pBuffer = (p)->pBufferStart; (p)->ActualLength = 0; } + +/* macro to set packet parameters for TX */ +#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \ +{ \ + (p)->pPktContext = (c); \ + (p)->pBuffer = (b); \ + (p)->ActualLength = (len); \ + (p)->Endpoint = (ep); \ + (p)->PktInfo.AsTx.Tag = (tag); \ + (p)->PktInfo.AsTx.Flags = 0; \ + (p)->PktInfo.AsTx.SendFlags = 0; \ +} + +#define SET_HTC_PACKET_NET_BUF_CONTEXT(p,nb) \ + (p)->pNetBufContext = (nb) + +#define GET_HTC_PACKET_NET_BUF_CONTEXT(p) (p)->pNetBufContext + +/* HTC Packet Queueing Macros */ +typedef struct _HTC_PACKET_QUEUE { + DL_LIST QueueHead; + int Depth; +} HTC_PACKET_QUEUE; + +/* initialize queue */ +#define INIT_HTC_PACKET_QUEUE(pQ) \ +{ \ + DL_LIST_INIT(&(pQ)->QueueHead); \ + (pQ)->Depth = 0; \ +} + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE(pQ,p) \ +{ DL_ListInsertTail(&(pQ)->QueueHead,&(p)->ListLink); \ + (pQ)->Depth++; \ +} + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE_TO_HEAD(pQ,p) \ +{ DL_ListInsertHead(&(pQ)->QueueHead,&(p)->ListLink); \ + (pQ)->Depth++; \ +} +/* test if a queue is empty */ +#define HTC_QUEUE_EMPTY(pQ) ((pQ)->Depth == 0) +/* get packet at head without removing it */ +static INLINE HTC_PACKET *HTC_GET_PKT_AT_HEAD(HTC_PACKET_QUEUE *queue) { + if (queue->Depth == 0) { + return NULL; + } + return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),HTC_PACKET,ListLink); +} +/* remove a packet from a queue, where-ever it is in the queue */ +#define HTC_PACKET_REMOVE(pQ,p) \ +{ \ + DL_ListRemove(&(p)->ListLink); \ + (pQ)->Depth--; \ +} + +/* dequeue an HTC packet from the head of the queue */ +static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE(HTC_PACKET_QUEUE *queue) { + DL_LIST *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead); + if (pItem != NULL) { + queue->Depth--; + return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink); + } + return NULL; +} + +/* dequeue an HTC packet from the tail of the queue */ +static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE_TAIL(HTC_PACKET_QUEUE *queue) { + DL_LIST *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead); + if (pItem != NULL) { + queue->Depth--; + return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink); + } + return NULL; +} + +#define HTC_PACKET_QUEUE_DEPTH(pQ) (pQ)->Depth + + +#define HTC_GET_ENDPOINT_FROM_PKT(p) (p)->Endpoint +#define HTC_GET_TAG_FROM_PKT(p) (p)->PktInfo.AsTx.Tag + + /* transfer the packets from one queue to the tail of another queue */ +#define HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(pQDest,pQSrc) \ +{ \ + DL_ListTransferItemsToTail(&(pQDest)->QueueHead,&(pQSrc)->QueueHead); \ + (pQDest)->Depth += (pQSrc)->Depth; \ + (pQSrc)->Depth = 0; \ +} + +/* + * Transfer the packets from one queue to the head of another queue. + * This xfer_to_head(q1,q2) is basically equivalent to xfer_to_tail(q2,q1), + * but it updates the queue descriptor object for the initial queue to refer + * to the concatenated queue. + */ +#define HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(pQDest, pQSrc) \ +{ \ + DL_ListTransferItemsToHead(&(pQDest)->QueueHead,&(pQSrc)->QueueHead); \ + (pQDest)->Depth += (pQSrc)->Depth; \ + (pQSrc)->Depth = 0; \ +} + + /* fast version to init and add a single packet to a queue */ +#define INIT_HTC_PACKET_QUEUE_AND_ADD(pQ,pP) \ +{ \ + DL_LIST_INIT_AND_ADD(&(pQ)->QueueHead,&(pP)->ListLink) \ + (pQ)->Depth = 1; \ +} + +#define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \ + ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), HTC_PACKET, ListLink) + +#define HTC_PACKET_QUEUE_ITERATE_IS_VALID(pQ) ITERATE_IS_VALID(&(pQ)->QueueHead) +#define HTC_PACKET_QUEUE_ITERATE_RESET(pQ) ITERATE_RESET(&(pQ)->QueueHead) + +#define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END + +#endif /*HTC_PACKET_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_services.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_services.h new file mode 100644 index 000000000000..73062f3fdcbd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/htc_services.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __HTC_SERVICES_H__ +#define __HTC_SERVICES_H__ + +/* Current service IDs */ + +typedef enum { + RSVD_SERVICE_GROUP = 0, + WMI_SERVICE_GROUP = 1, + NMI_SERVICE_GROUP = 2, + HTT_SERVICE_GROUP = 3, + CFG_NV_SERVICE_GROUP = 4, +#ifdef IPA_UC_OFFLOAD + WDI_IPA_SERVICE_GROUP = 5, +#endif /* IPA_UC_OFFLOAD */ + HTC_TEST_GROUP = 254, + HTC_SERVICE_GROUP_LAST = 255 +}HTC_SERVICE_GROUP_IDS; + +#define MAKE_SERVICE_ID(group,index) \ + (int)(((int)group << 8) | (int)(index)) + +/* NOTE: service ID of 0x0000 is reserved and should never be used */ +#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1) +#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0) +#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1) +#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2) +#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3) +#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4) +#define WMI_MAX_SERVICES 5 + +#define NMI_CONTROL_SVC MAKE_SERVICE_ID(NMI_SERVICE_GROUP,0) +#define NMI_DATA_SVC MAKE_SERVICE_ID(NMI_SERVICE_GROUP,1) + +#define HTT_DATA_MSG_SVC MAKE_SERVICE_ID(HTT_SERVICE_GROUP,0) +#define HTT_DATA2_MSG_SVC MAKE_SERVICE_ID(HTT_SERVICE_GROUP,1) + +/* raw stream service (i.e. flash, tcmd, calibration apps) */ +#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0) + +#define CFG_NV_SVC MAKE_SERVICE_ID(CFG_NV_SERVICE_GROUP,0) +#ifdef IPA_UC_OFFLOAD +#define WDI_IPA_TX_SVC MAKE_SERVICE_ID(WDI_IPA_SERVICE_GROUP,0) +#endif /* IPA_UC_OFFLOAD */ +/* + * Directions for interconnect pipe configuration. + * These definitions may be used during configuration and are shared + * between Host and Target. + * + * Pipe Directions are relative to the Host, so PIPEDIR_IN means + * "coming IN over air through Target to Host" as with a WiFi Rx operation. + * Conversely, PIPEDIR_OUT means "going OUT from Host through Target over air" + * as with a WiFi Tx operation. This is somewhat awkward for the "middle-man" + * Target since things that are "PIPEDIR_OUT" are coming IN to the Target + * over the interconnect. + */ +typedef A_UINT32 PIPEDIR; +#define PIPEDIR_NONE 0 +#define PIPEDIR_IN 1 /* Target-->Host, WiFi Rx direction */ +#define PIPEDIR_OUT 2 /* Host->Target, WiFi Tx direction */ +#define PIPEDIR_INOUT 3 /* bidirectional */ +#define PIPEDIR_MATCH(d1, d2) (((PIPEDIR)(d1) & (PIPEDIR)(d2)) != 0) + +/* Establish a mapping between a service/direction and a pipe. */ +struct service_to_pipe { + A_UINT32 service_id; + A_UINT32 pipedir; + A_UINT32 pipenum; +}; + + +#endif /*HTC_SERVICES_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hwdef.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hwdef.h new file mode 100644 index 000000000000..9aacae9c88d6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hwdef.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _HW_DEF_H +#define _HW_DEF_H + +/* + * Atheros-specific + */ +typedef enum { + ANTENNA_CONTROLLABLE, + ANTENNA_FIXED_A, + ANTENNA_FIXED_B, + ANTENNA_DUMMY_MAX +} ANTENNA_CONTROL; + +/* + * Number of (OEM-defined) functions using GPIO pins currently defined + * + * Function 0: Link/Power LED + * Function 1: Network/Activity LED + * Function 2: Connection LED + */ +#define NUM_GPIO_FUNCS 3 + +/* +** Default cache line size, in bytes. +** Used when PCI device not fully initialized by bootrom/BIOS +*/ + +#define DEFAULT_CACHELINE 32 + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_common.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_common.h new file mode 100644 index 000000000000..fd9692bfe5e7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_common.h @@ -0,0 +1,2235 @@ +/* + * Copyright (c) 2011,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +#ifndef EXTERNAL_USE_ONLY +#include "osdep.h" +#endif /* EXTERNAL_USE_ONLY */ +#include "_ieee80211_common.h" + +#ifndef _COMMON_IEEE80211_H_ +#define _COMMON_IEEE80211_H_ + +/* + * 802.11 protocol definitions. + */ + +/* is 802.11 address multicast/broadcast? */ +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) + +#define IEEE80211_IS_IPV4_MULTICAST(_a) (*(_a) == 0x01) + +#define IEEE80211_IS_IPV6_MULTICAST(_a) \ + ((_a)[0] == 0x33 && \ + (_a)[1] == 0x33) + + +#define IEEE80211_IS_BROADCAST(_a) \ + ((_a)[0] == 0xff && \ + (_a)[1] == 0xff && \ + (_a)[2] == 0xff && \ + (_a)[3] == 0xff && \ + (_a)[4] == 0xff && \ + (_a)[5] == 0xff) + +/* IEEE 802.11 PLCP header */ +struct ieee80211_plcp_hdr { + u_int16_t i_sfd; + u_int8_t i_signal; + u_int8_t i_service; + u_int16_t i_length; + u_int16_t i_crc; +} __packed; + +#define IEEE80211_PLCP_SFD 0xF3A0 +#define IEEE80211_PLCP_SERVICE 0x00 + +/* + * generic definitions for IEEE 802.11 frames + */ +struct ieee80211_frame { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + union { + struct { + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + }; + u_int8_t i_addr_all[3 * IEEE80211_ADDR_LEN]; + }; + u_int8_t i_seq[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __packed; + +struct ieee80211_qosframe { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_qos[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __packed; + +struct ieee80211_qoscntl { + u_int8_t i_qos[2]; +}; + +struct ieee80211_frame_addr4 { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_addr4[IEEE80211_ADDR_LEN]; +} __packed; + +struct ieee80211_qosframe_addr4 { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_addr4[IEEE80211_ADDR_LEN]; + u_int8_t i_qos[2]; +} __packed; + +/* HTC frame for TxBF*/ +// for TxBF RC +struct ieee80211_frame_min_one { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + +} __packed;// For TxBF RC + +struct ieee80211_qosframe_htc { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_qos[2]; + u_int8_t i_htc[4]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __packed; +struct ieee80211_qosframe_htc_addr4 { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + u_int8_t i_addr3[IEEE80211_ADDR_LEN]; + u_int8_t i_seq[2]; + u_int8_t i_addr4[IEEE80211_ADDR_LEN]; + u_int8_t i_qos[2]; + u_int8_t i_htc[4]; +} __packed; +struct ieee80211_htc { + u_int8_t i_htc[4]; +}; +/*HTC frame for TxBF*/ + +struct ieee80211_ctlframe_addr2 { + u_int8_t i_fc[2]; + u_int8_t i_aidordur[2]; /* AID or duration */ + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; +} __packed; + +#define IEEE80211_WHQ(wh) ((struct ieee80211_qosframe *)(wh)) +#define IEEE80211_WH4(wh) ((struct ieee80211_frame_addr4 *)(wh)) +#define IEEE80211_WHQ4(wh) ((struct ieee80211_qosframe_addr4 *)(wh)) + +#define IEEE80211_FC0_VERSION_MASK 0x03 +#define IEEE80211_FC0_VERSION_SHIFT 0 +#define IEEE80211_FC0_VERSION_0 0x00 +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_SHIFT 2 +#define IEEE80211_FC0_TYPE_MGT 0x00 +#define IEEE80211_FC0_TYPE_CTL 0x04 +#define IEEE80211_FC0_TYPE_DATA 0x08 + +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4 +/* for TYPE_MGT */ +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACTION 0xd0 +#define IEEE80211_FCO_SUBTYPE_ACTION_NO_ACK 0xe0 +/* for TYPE_CTL */ +#define IEEE80211_FCO_SUBTYPE_Control_Wrapper 0x70 // For TxBF RC +#define IEEE80211_FC0_SUBTYPE_BAR 0x80 +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 +/* for TYPE_DATA (bit combination) */ +#define IEEE80211_FC0_SUBTYPE_DATA 0x00 +#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10 +#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20 +#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 +#define IEEE80211_FC0_SUBTYPE_CFACK 0x50 +#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60 +#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 +#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0 + +#define IEEE80211_FC1_DIR_MASK 0x03 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ + +#define IEEE80211_FC1_MORE_FRAG 0x04 +#define IEEE80211_FC1_RETRY 0x08 +#define IEEE80211_FC1_PWR_MGT 0x10 +#define IEEE80211_FC1_MORE_DATA 0x20 +#define IEEE80211_FC1_WEP 0x40 +#define IEEE80211_FC1_ORDER 0x80 + +#define IEEE80211_SEQ_FRAG_MASK 0x000f +#define IEEE80211_SEQ_FRAG_SHIFT 0 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0 +#define IEEE80211_SEQ_SEQ_SHIFT 4 +#define IEEE80211_SEQ_MAX 4096 + +#define IEEE80211_SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) + + +#define IEEE80211_QOS_TXOP 0x00ff + +#define IEEE80211_QOS_AMSDU 0x80 +#define IEEE80211_QOS_AMSDU_S 7 +#define IEEE80211_QOS_ACKPOLICY 0x60 +#define IEEE80211_QOS_ACKPOLICY_S 5 +#define IEEE80211_QOS_EOSP 0x10 +#define IEEE80211_QOS_EOSP_S 4 +#define IEEE80211_QOS_TID 0x0f +#define IEEE80211_MFP_TID 0xff + +#define IEEE80211_HTC0_TRQ 0x02 +#define IEEE80211_HTC2_CalPos 0x03 +#define IEEE80211_HTC2_CalSeq 0x0C +#define IEEE80211_HTC2_CSI_NONCOMP_BF 0x80 +#define IEEE80211_HTC2_CSI_COMP_BF 0xc0 + +/* Set bits 14 and 15 to 1 when duration field carries Association ID */ +#define IEEE80211_FIELD_TYPE_AID 0xC000 + +#define IEEE80211_IS_BEACON(_frame) ((((_frame)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) && \ + (((_frame)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_BEACON)) +#define IEEE80211_IS_DATA(_frame) (((_frame)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) + +#define IEEE80211_IS_MFP_FRAME(_frame) ((((_frame)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) && \ + ((_frame)->i_fc[1] & IEEE80211_FC1_WEP) && \ + ((((_frame)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_DEAUTH) || \ + (((_frame)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_DISASSOC) || \ + (((_frame)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_ACTION))) +#define IEEE80211_IS_AUTH(_frame) ((((_frame)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) && \ + (((_frame)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_AUTH)) + +/* MCS Set */ +#define IEEE80211_RX_MCS_1_STREAM_BYTE_OFFSET 0 +#define IEEE80211_RX_MCS_2_STREAM_BYTE_OFFSET 1 +#define IEEE80211_RX_MCS_3_STREAM_BYTE_OFFSET 2 +#define IEEE80211_RX_MCS_ALL_NSTREAM_RATES 0xff +#define IEEE80211_TX_MCS_OFFSET 12 + +#define IEEE80211_TX_MCS_SET_DEFINED 0x80 +#define IEEE80211_TX_RX_MCS_SET_NOT_EQUAL 0x40 +#define IEEE80211_TX_1_SPATIAL_STREAMS 0x0 +#define IEEE80211_TX_2_SPATIAL_STREAMS 0x10 +#define IEEE80211_TX_3_SPATIAL_STREAMS 0x20 +#define IEEE80211_TX_4_SPATIAL_STREAMS 0x30 + +#define IEEE80211_TX_MCS_SET 0xf8 + +/* + * Subtype data: If bit 6 is set then the data frame contains no actual data. + */ +#define IEEE80211_FC0_SUBTYPE_NO_DATA_MASK 0x40 +#define IEEE80211_CONTAIN_DATA(_subtype) \ + (! ((_subtype) & IEEE80211_FC0_SUBTYPE_NO_DATA_MASK)) + +#define IEEE8023_MAX_LEN 0x600 /* 1536 - larger is Ethernet II */ +#define RFC1042_SNAP_ORGCODE_0 0x00 +#define RFC1042_SNAP_ORGCODE_1 0x00 +#define RFC1042_SNAP_ORGCODE_2 0x00 + +#define BTEP_SNAP_ORGCODE_0 0x00 +#define BTEP_SNAP_ORGCODE_1 0x00 +#define BTEP_SNAP_ORGCODE_2 0xf8 + +/* BT 3.0 */ +#define BTAMP_SNAP_ORGCODE_0 0x00 +#define BTAMP_SNAP_ORGCODE_1 0x19 +#define BTAMP_SNAP_ORGCODE_2 0x58 + +/* Aironet OUI Codes */ +#define AIRONET_SNAP_CODE_0 0x00 +#define AIRONET_SNAP_CODE_1 0x40 +#define AIRONET_SNAP_CODE_2 0x96 + +#define IEEE80211_LSIG_LEN 3 +#define IEEE80211_HTSIG_LEN 6 +#define IEEE80211_SB_LEN 2 + +/* + * Information element header format + */ +struct ieee80211_ie_header { + u_int8_t element_id; /* Element Id */ + u_int8_t length; /* IE Length */ +} __packed; + +/* + * Country information element. + */ +#define IEEE80211_COUNTRY_MAX_TRIPLETS (83) +struct ieee80211_ie_country { + u_int8_t country_id; + u_int8_t country_len; + u_int8_t country_str[3]; + u_int8_t country_triplet[IEEE80211_COUNTRY_MAX_TRIPLETS*3]; +} __packed; + +/* does frame have QoS sequence control data */ +#define IEEE80211_QOS_HAS_SEQ(wh) \ + (((wh)->i_fc[0] & \ + (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \ + (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) + +#define WME_QOSINFO_UAPSD 0x80 /* Mask for U-APSD field */ +#define WME_QOSINFO_COUNT 0x0f /* Mask for Param Set Count field */ +/* + * WME/802.11e information element. + */ +struct ieee80211_ie_wme { + u_int8_t wme_id; /* IEEE80211_ELEMID_VENDOR */ + u_int8_t wme_len; /* length in bytes */ + u_int8_t wme_oui[3]; /* 0x00, 0x50, 0xf2 */ + u_int8_t wme_type; /* OUI type */ + u_int8_t wme_subtype; /* OUI subtype */ + u_int8_t wme_version; /* spec revision */ + u_int8_t wme_info; /* QoS info */ +} __packed; + +/* + * TS INFO part of the tspec element is a collection of bit flags + */ +#if _BYTE_ORDER == _BIG_ENDIAN +struct ieee80211_tsinfo_bitmap { + u_int8_t one : 1, + direction : 2, + tid : 4, + reserved1 : 1; + u_int8_t reserved2 : 2, + dot1Dtag : 3, + psb : 1, + reserved3 : 1, + zero : 1; + u_int8_t reserved5 : 7, + reserved4 : 1; +} __packed; +#else +struct ieee80211_tsinfo_bitmap { + u_int8_t reserved1 : 1, + tid : 4, + direction : 2, + one : 1; + u_int8_t zero : 1, + reserved3 : 1, + psb : 1, + dot1Dtag : 3, + reserved2 : 2; + u_int8_t reserved4 : 1, + reserved5 : 7; +} __packed; +#endif + +/* + * WME/802.11e Tspec Element + */ +struct ieee80211_wme_tspec { + u_int8_t ts_id; + u_int8_t ts_len; + u_int8_t ts_oui[3]; + u_int8_t ts_oui_type; + u_int8_t ts_oui_subtype; + u_int8_t ts_version; + u_int8_t ts_tsinfo[3]; + u_int8_t ts_nom_msdu[2]; + u_int8_t ts_max_msdu[2]; + u_int8_t ts_min_svc[4]; + u_int8_t ts_max_svc[4]; + u_int8_t ts_inactv_intv[4]; + u_int8_t ts_susp_intv[4]; + u_int8_t ts_start_svc[4]; + u_int8_t ts_min_rate[4]; + u_int8_t ts_mean_rate[4]; + u_int8_t ts_peak_rate[4]; + u_int8_t ts_max_burst[4]; + u_int8_t ts_delay[4]; + u_int8_t ts_min_phy[4]; + u_int8_t ts_surplus[2]; + u_int8_t ts_medium_time[2]; +} __packed; + +/* + * WME AC parameter field + */ +struct ieee80211_wme_acparams { + u_int8_t acp_aci_aifsn; + u_int8_t acp_logcwminmax; + u_int16_t acp_txop; +} __packed; + +#define IEEE80211_WME_PARAM_LEN 24 +#define WME_NUM_AC 4 /* 4 AC categories */ + +#define WME_PARAM_ACI 0x60 /* Mask for ACI field */ +#define WME_PARAM_ACI_S 5 /* Shift for ACI field */ +#define WME_PARAM_ACM 0x10 /* Mask for ACM bit */ +#define WME_PARAM_ACM_S 4 /* Shift for ACM bit */ +#define WME_PARAM_AIFSN 0x0f /* Mask for aifsn field */ +#define WME_PARAM_AIFSN_S 0 /* Shift for aifsn field */ +#define WME_PARAM_LOGCWMIN 0x0f /* Mask for CwMin field (in log) */ +#define WME_PARAM_LOGCWMIN_S 0 /* Shift for CwMin field */ +#define WME_PARAM_LOGCWMAX 0xf0 /* Mask for CwMax field (in log) */ +#define WME_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */ + +#define WME_AC_TO_TID(_ac) ( \ + ((_ac) == WME_AC_VO) ? 6 : \ + ((_ac) == WME_AC_VI) ? 5 : \ + ((_ac) == WME_AC_BK) ? 1 : \ + 0) + +#define TID_TO_WME_AC(_tid) ( \ + (((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ + (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ + (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ + WME_AC_VO) + +/* + * WME Parameter Element + */ +struct ieee80211_wme_param { + u_int8_t param_id; + u_int8_t param_len; + u_int8_t param_oui[3]; + u_int8_t param_oui_type; + u_int8_t param_oui_sybtype; + u_int8_t param_version; + u_int8_t param_qosInfo; + u_int8_t param_reserved; + struct ieee80211_wme_acparams params_acParams[WME_NUM_AC]; +} __packed; + +/* + * WME U-APSD qos info field defines + */ +#define WME_CAPINFO_UAPSD_EN 0x00000080 +#define WME_CAPINFO_UAPSD_VO 0x00000001 +#define WME_CAPINFO_UAPSD_VI 0x00000002 +#define WME_CAPINFO_UAPSD_BK 0x00000004 +#define WME_CAPINFO_UAPSD_BE 0x00000008 +#define WME_CAPINFO_UAPSD_ACFLAGS_SHIFT 0 +#define WME_CAPINFO_UAPSD_ACFLAGS_MASK 0xF +#define WME_CAPINFO_UAPSD_MAXSP_SHIFT 5 +#define WME_CAPINFO_UAPSD_MAXSP_MASK 0x3 +#define WME_CAPINFO_IE_OFFSET 8 +#define WME_UAPSD_MAXSP(_qosinfo) (((_qosinfo) >> WME_CAPINFO_UAPSD_MAXSP_SHIFT) & WME_CAPINFO_UAPSD_MAXSP_MASK) +#define WME_UAPSD_AC_ENABLED(_ac, _qosinfo) ( (1<<(3 - (_ac))) & \ + (((_qosinfo) >> WME_CAPINFO_UAPSD_ACFLAGS_SHIFT) & WME_CAPINFO_UAPSD_ACFLAGS_MASK) ) + +/* Mask used to determined whether all queues are UAPSD-enabled */ +#define WME_CAPINFO_UAPSD_ALL (WME_CAPINFO_UAPSD_VO | \ + WME_CAPINFO_UAPSD_VI | \ + WME_CAPINFO_UAPSD_BK | \ + WME_CAPINFO_UAPSD_BE) +#define WME_CAPINFO_UAPSD_NONE 0 + +#define WME_UAPSD_AC_MAX_VAL 1 +#define WME_UAPSD_AC_INVAL WME_UAPSD_AC_MAX_VAL+1 + +/* + * Atheros Advanced Capability information element. + */ +struct ieee80211_ie_athAdvCap { + u_int8_t athAdvCap_id; /* IEEE80211_ELEMID_VENDOR */ + u_int8_t athAdvCap_len; /* length in bytes */ + u_int8_t athAdvCap_oui[3]; /* 0x00, 0x03, 0x7f */ + u_int8_t athAdvCap_type; /* OUI type */ + u_int16_t athAdvCap_version; /* spec revision */ + u_int8_t athAdvCap_capability; /* Capability info */ + u_int16_t athAdvCap_defKeyIndex; +} __packed; + +/* + * Atheros Extended Capability information element. + */ +struct ieee80211_ie_ath_extcap { + u_int8_t ath_extcap_id; /* IEEE80211_ELEMID_VENDOR */ + u_int8_t ath_extcap_len; /* length in bytes */ + u_int8_t ath_extcap_oui[3]; /* 0x00, 0x03, 0x7f */ + u_int8_t ath_extcap_type; /* OUI type */ + u_int8_t ath_extcap_subtype; /* OUI subtype */ + u_int8_t ath_extcap_version; /* spec revision */ + u_int32_t ath_extcap_extcap : 16, /* B0-15 extended capabilities */ + ath_extcap_weptkipaggr_rxdelim : 8, /* B16-23 num delimiters for receiving WEP/TKIP aggregates */ + ath_extcap_reserved : 8; /* B24-31 reserved */ +} __packed; + +/* + * Atheros XR information element. + */ +struct ieee80211_xr_param { + u_int8_t param_id; + u_int8_t param_len; + u_int8_t param_oui[3]; + u_int8_t param_oui_type; + u_int8_t param_oui_sybtype; + u_int8_t param_version; + u_int8_t param_Info; + u_int8_t param_base_bssid[IEEE80211_ADDR_LEN]; + u_int8_t param_xr_bssid[IEEE80211_ADDR_LEN]; + u_int16_t param_xr_beacon_interval; + u_int8_t param_base_ath_capability; + u_int8_t param_xr_ath_capability; +} __packed; + +/* + * SFA information element. + */ +struct ieee80211_ie_sfa { + u_int8_t sfa_id; /* IEEE80211_ELEMID_VENDOR */ + u_int8_t sfa_len; /* length in bytes */ + u_int8_t sfa_oui[3]; /* 0x00, 0x40, 0x96 */ + u_int8_t sfa_type; /* OUI type */ + u_int8_t sfa_caps; /* Capabilities */ +} __packed; + +/* Atheros capabilities */ +#define IEEE80211_ATHC_TURBOP 0x0001 /* Turbo Prime */ +#define IEEE80211_ATHC_COMP 0x0002 /* Compression */ +#define IEEE80211_ATHC_FF 0x0004 /* Fast Frames */ +#define IEEE80211_ATHC_XR 0x0008 /* Xtended Range support */ +#define IEEE80211_ATHC_AR 0x0010 /* Advanced Radar support */ +#define IEEE80211_ATHC_BURST 0x0020 /* Bursting - not negotiated */ +#define IEEE80211_ATHC_WME 0x0040 /* CWMin tuning */ +#define IEEE80211_ATHC_BOOST 0x0080 /* Boost */ +#define IEEE80211_ATHC_TDLS 0x0100 /* TDLS */ + +/* Atheros extended capabilities */ +/* OWL device capable of WDS workaround */ +#define IEEE80211_ATHEC_OWLWDSWAR 0x0001 +#define IEEE80211_ATHEC_WEPTKIPAGGR 0x0002 +#define IEEE80211_ATHEC_EXTRADELIMWAR 0x0004 +/* + * Management Frames + */ + +/* + * *** Platform-specific code?? *** + * In Vista one must use bit fields of type (unsigned short = u_int16_t) to + * ensure data structure is of the correct size. ANSI C used to specify only + * "int" bit fields, which led to a larger structure size in Windows (32 bits). + * + * We must make sure the following construction is valid in all OS's. + */ +union ieee80211_capability { + struct { + u_int16_t ess : 1; + u_int16_t ibss : 1; + u_int16_t cf_pollable : 1; + u_int16_t cf_poll_request : 1; + u_int16_t privacy : 1; + u_int16_t short_preamble : 1; + u_int16_t pbcc : 1; + u_int16_t channel_agility : 1; + u_int16_t spectrum_management : 1; + u_int16_t qos : 1; + u_int16_t short_slot_time : 1; + u_int16_t apsd : 1; + u_int16_t reserved2 : 1; + u_int16_t dsss_ofdm : 1; + u_int16_t del_block_ack : 1; + u_int16_t immed_block_ack : 1; + }; + + u_int16_t value; +} __packed; + +struct ieee80211_beacon_frame { + u_int8_t timestamp[8]; /* the value of sender's TSFTIMER */ + u_int16_t beacon_interval; /* the number of time units between target beacon transmission times */ + union ieee80211_capability capability; +/* Value of capability for every bit +#define IEEE80211_CAPINFO_ESS 0x0001 +#define IEEE80211_CAPINFO_IBSS 0x0002 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 +#define IEEE80211_CAPINFO_PRIVACY 0x0010 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 +#define IEEE80211_CAPINFO_PBCC 0x0040 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 +#define IEEE80211_CAPINFO_SPECTRUM_MGMT 0x0100 +#define IEEE80211_CAPINFO_QOS 0x0200 +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 +#define IEEE80211_CAPINFO_APSD 0x0800 +#define IEEE80211_CAPINFO_RADIOMEAS 0x1000 +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 +bits 14-15 are reserved +*/ + struct ieee80211_ie_header info_elements; +} __packed; + +/* + * Management Action Frames + */ + +/* generic frame format */ +struct ieee80211_action { + u_int8_t ia_category; + u_int8_t ia_action; +} __packed; + +/* spectrum action frame header */ +struct ieee80211_action_measrep_header { + struct ieee80211_action action_header; + u_int8_t dialog_token; +} __packed; + +/* categories */ +#define IEEE80211_ACTION_CAT_SPECTRUM 0 /* Spectrum management */ +#define IEEE80211_ACTION_CAT_QOS 1 /* IEEE QoS */ +#define IEEE80211_ACTION_CAT_DLS 2 /* DLS */ +#define IEEE80211_ACTION_CAT_BA 3 /* BA */ +#define IEEE80211_ACTION_CAT_PUBLIC 4 /* Public Action Frame */ +#define IEEE80211_ACTION_CAT_HT 7 /* HT per IEEE802.11n-D1.06 */ +#define IEEE80211_ACTION_CAT_SA_QUERY 8 /* SA Query per IEEE802.11w, PMF */ +#define IEEE80211_ACTION_CAT_WMM_QOS 17 /* QoS from WMM specification */ +#define IEEE80211_ACTION_CAT_VHT 21 /* VHT Action */ + +/* Spectrum Management actions */ +#define IEEE80211_ACTION_MEAS_REQUEST 0 /* Measure channels */ +#define IEEE80211_ACTION_MEAS_REPORT 1 +#define IEEE80211_ACTION_TPC_REQUEST 2 /* Transmit Power control */ +#define IEEE80211_ACTION_TPC_REPORT 3 +#define IEEE80211_ACTION_CHAN_SWITCH 4 /* 802.11h Channel Switch Announcement */ + +/* HT actions */ +#define IEEE80211_ACTION_HT_TXCHWIDTH 0 /* recommended transmission channel width */ +#define IEEE80211_ACTION_HT_SMPOWERSAVE 1 /* Spatial Multiplexing (SM) Power Save */ +#define IEEE80211_ACTION_HT_CSI 4 /* CSI Frame */ +#define IEEE80211_ACTION_HT_NONCOMP_BF 5 /* Non-compressed Beamforming*/ +#define IEEE80211_ACTION_HT_COMP_BF 6 /* Compressed Beamforming*/ + +/* VHT actions */ +#define IEEE80211_ACTION_VHT_OPMODE 2 /* Operating mode notification */ + +/* Spectrum channel switch action frame after IE*/ +/* Public Actions*/ +#define IEEE80211_ACTION_TDLS_DISCRESP 14 /* TDLS Discovery Response frame */ + +/* HT - recommended transmission channel width */ +struct ieee80211_action_ht_txchwidth { + struct ieee80211_action at_header; + u_int8_t at_chwidth; +} __packed; + +#define IEEE80211_A_HT_TXCHWIDTH_20 0 +#define IEEE80211_A_HT_TXCHWIDTH_2040 1 + +/* HT - Spatial Multiplexing (SM) Power Save */ +struct ieee80211_action_ht_smpowersave { + struct ieee80211_action as_header; + u_int8_t as_control; +} __packed; + +/*HT - CSI Frame */ //for TxBF RC +#define MIMO_CONTROL_LEN 6 +struct ieee80211_action_ht_CSI { + struct ieee80211_action as_header; + u_int8_t mimo_control[MIMO_CONTROL_LEN]; +} __packed; + +/*HT - V/CV report frame*/ +struct ieee80211_action_ht_txbf_rpt { + struct ieee80211_action as_header; + u_int8_t mimo_control[MIMO_CONTROL_LEN]; +} __packed; + +/* + * 802.11ac Operating Mode Notification + */ +struct ieee80211_ie_op_mode { +#if _BYTE_ORDER == _BIG_ENDIAN + u_int8_t rx_nss_type : 1, + rx_nss : 3, + reserved : 2, + ch_width : 2; +#else + u_int8_t ch_width : 2, + reserved : 2, + rx_nss : 3, + rx_nss_type : 1; +#endif +} __packed; + +struct ieee80211_ie_op_mode_ntfy { + u_int8_t elem_id; + u_int8_t elem_len; + struct ieee80211_ie_op_mode opmode; +} __packed; + + +/* VHT - recommended Channel width and Nss */ +struct ieee80211_action_vht_opmode { + struct ieee80211_action at_header; + struct ieee80211_ie_op_mode at_op_mode; +} __packed; + +/* values defined for 'as_control' field per 802.11n-D1.06 */ +#define IEEE80211_A_HT_SMPOWERSAVE_DISABLED 0x00 /* SM Power Save Disabled, SM packets ok */ +#define IEEE80211_A_HT_SMPOWERSAVE_ENABLED 0x01 /* SM Power Save Enabled bit */ +#define IEEE80211_A_HT_SMPOWERSAVE_MODE 0x02 /* SM Power Save Mode bit */ +#define IEEE80211_A_HT_SMPOWERSAVE_RESERVED 0xFC /* SM Power Save Reserved bits */ + +/* values defined for SM Power Save Mode bit */ +#define IEEE80211_A_HT_SMPOWERSAVE_STATIC 0x00 /* Static, SM packets not ok */ +#define IEEE80211_A_HT_SMPOWERSAVE_DYNAMIC 0x02 /* Dynamic, SM packets ok if preceded by RTS */ + +/* DLS actions */ +#define IEEE80211_ACTION_DLS_REQUEST 0 +#define IEEE80211_ACTION_DLS_RESPONSE 1 +#define IEEE80211_ACTION_DLS_TEARDOWN 2 + +struct ieee80211_dls_request { + struct ieee80211_action hdr; + u_int8_t dst_addr[IEEE80211_ADDR_LEN]; + u_int8_t src_addr[IEEE80211_ADDR_LEN]; + u_int16_t capa_info; + u_int16_t timeout; +} __packed; + +struct ieee80211_dls_response { + struct ieee80211_action hdr; + u_int16_t statuscode; + u_int8_t dst_addr[IEEE80211_ADDR_LEN]; + u_int8_t src_addr[IEEE80211_ADDR_LEN]; +} __packed; + +/* BA actions */ +#define IEEE80211_ACTION_BA_ADDBA_REQUEST 0 /* ADDBA request */ +#define IEEE80211_ACTION_BA_ADDBA_RESPONSE 1 /* ADDBA response */ +#define IEEE80211_ACTION_BA_DELBA 2 /* DELBA */ + +struct ieee80211_ba_parameterset { +#if _BYTE_ORDER == _BIG_ENDIAN + u_int16_t buffersize : 10, /* B6-15 buffer size */ + tid : 4, /* B2-5 TID */ + bapolicy : 1, /* B1 block ack policy */ + amsdusupported : 1; /* B0 amsdu supported */ +#else + u_int16_t amsdusupported : 1, /* B0 amsdu supported */ + bapolicy : 1, /* B1 block ack policy */ + tid : 4, /* B2-5 TID */ + buffersize : 10; /* B6-15 buffer size */ +#endif +} __packed; + +#define IEEE80211_BA_POLICY_DELAYED 0 +#define IEEE80211_BA_POLICY_IMMEDIATE 1 +#define IEEE80211_BA_AMSDU_SUPPORTED 1 + +struct ieee80211_ba_seqctrl { +#if _BYTE_ORDER == _BIG_ENDIAN + u_int16_t startseqnum : 12, /* B4-15 starting sequence number */ + fragnum : 4; /* B0-3 fragment number */ +#else + u_int16_t fragnum : 4, /* B0-3 fragment number */ + startseqnum : 12; /* B4-15 starting sequence number */ +#endif +} __packed; + +struct ieee80211_delba_parameterset { +#if _BYTE_ORDER == _BIG_ENDIAN + u_int16_t tid : 4, /* B12-15 tid */ + initiator : 1, /* B11 initiator */ + reserved0 : 11; /* B0-10 reserved */ +#else + u_int16_t reserved0 : 11, /* B0-10 reserved */ + initiator : 1, /* B11 initiator */ + tid : 4; /* B12-15 tid */ +#endif +} __packed; + +/* BA - ADDBA request */ +struct ieee80211_action_ba_addbarequest { + struct ieee80211_action rq_header; + u_int8_t rq_dialogtoken; + struct ieee80211_ba_parameterset rq_baparamset; + u_int16_t rq_batimeout; /* in TUs */ + struct ieee80211_ba_seqctrl rq_basequencectrl; +} __packed; + +/* BA - ADDBA response */ +struct ieee80211_action_ba_addbaresponse { + struct ieee80211_action rs_header; + u_int8_t rs_dialogtoken; + u_int16_t rs_statuscode; + struct ieee80211_ba_parameterset rs_baparamset; + u_int16_t rs_batimeout; /* in TUs */ +} __packed; + +/* BA - DELBA */ +struct ieee80211_action_ba_delba { + struct ieee80211_action dl_header; + struct ieee80211_delba_parameterset dl_delbaparamset; + u_int16_t dl_reasoncode; +} __packed; + +/* MGT Notif actions */ +#define IEEE80211_WMM_QOS_ACTION_SETUP_REQ 0 +#define IEEE80211_WMM_QOS_ACTION_SETUP_RESP 1 +#define IEEE80211_WMM_QOS_ACTION_TEARDOWN 2 + +#define IEEE80211_WMM_QOS_DIALOG_TEARDOWN 0 +#define IEEE80211_WMM_QOS_DIALOG_SETUP 1 + +#define IEEE80211_WMM_QOS_TSID_DATA_TSPEC 6 +#define IEEE80211_WMM_QOS_TSID_SIG_TSPEC 7 + +struct ieee80211_action_wmm_qos { + struct ieee80211_action ts_header; + u_int8_t ts_dialogtoken; + u_int8_t ts_statuscode; + struct ieee80211_wme_tspec ts_tspecie; +} __packed; + +/* + * Control frames. + */ +struct ieee80211_frame_min { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_addr1[IEEE80211_ADDR_LEN]; + u_int8_t i_addr2[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +/* + * BAR frame format + */ +#define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ +#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */ +#define IEEE80211_BAR_CTL_NOACK 0x0001 /* no-ack policy */ +#define IEEE80211_BAR_CTL_COMBA 0x0004 /* compressed block-ack */ + +/* + * SA Query Action mgmt Frame + */ +struct ieee80211_action_sa_query { + struct ieee80211_action sa_header; + u_int16_t sa_transId; +}; + +typedef enum ieee80211_action_sa_query_type{ + IEEE80211_ACTION_SA_QUERY_REQUEST, + IEEE80211_ACTION_SA_QUERY_RESPONSE +}ieee80211_action_sa_query_type_t; + +struct ieee80211_frame_bar { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + u_int8_t i_ta[IEEE80211_ADDR_LEN]; + u_int16_t i_ctl; + u_int16_t i_seq; + /* FCS */ +} __packed; + +struct ieee80211_frame_rts { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + u_int8_t i_ta[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_cts { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_ack { + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_pspoll { + u_int8_t i_fc[2]; + u_int8_t i_aid[2]; + u_int8_t i_bssid[IEEE80211_ADDR_LEN]; + u_int8_t i_ta[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_cfend { /* NB: also CF-End+CF-Ack */ + u_int8_t i_fc[2]; + u_int8_t i_dur[2]; /* should be zero */ + u_int8_t i_ra[IEEE80211_ADDR_LEN]; + u_int8_t i_bssid[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +/* + * BEACON management packets + * + * octet timestamp[8] + * octet beacon interval[2] + * octet capability information[2] + * information element + * octet elemid + * octet length + * octet information[length] + */ + +typedef u_int8_t *ieee80211_mgt_beacon_t; + +#define IEEE80211_BEACON_INTERVAL(beacon) \ + ((beacon)[8] | ((beacon)[9] << 8)) +#define IEEE80211_BEACON_CAPABILITY(beacon) \ + ((beacon)[10] | ((beacon)[11] << 8)) + +#define IEEE80211_CAPINFO_ESS 0x0001 +#define IEEE80211_CAPINFO_IBSS 0x0002 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 +#define IEEE80211_CAPINFO_PRIVACY 0x0010 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 +#define IEEE80211_CAPINFO_PBCC 0x0040 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 +#define IEEE80211_CAPINFO_SPECTRUM_MGMT 0x0100 +#define IEEE80211_CAPINFO_QOS 0x0200 +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 +#define IEEE80211_CAPINFO_APSD 0x0800 +#define IEEE80211_CAPINFO_RADIOMEAS 0x1000 +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 +/* bits 14-15 are reserved */ + +/* + * 802.11i/WPA information element (maximally sized). + */ +struct ieee80211_ie_wpa { + u_int8_t wpa_id; /* IEEE80211_ELEMID_VENDOR */ + u_int8_t wpa_len; /* length in bytes */ + u_int8_t wpa_oui[3]; /* 0x00, 0x50, 0xf2 */ + u_int8_t wpa_type; /* OUI type */ + u_int16_t wpa_version; /* spec revision */ + u_int32_t wpa_mcipher[1]; /* multicast/group key cipher */ + u_int16_t wpa_uciphercnt; /* # pairwise key ciphers */ + u_int32_t wpa_uciphers[8]; /* ciphers */ + u_int16_t wpa_authselcnt; /* authentication selector cnt */ + u_int32_t wpa_authsels[8]; /* selectors */ + u_int16_t wpa_caps; /* 802.11i capabilities */ + u_int16_t wpa_pmkidcnt; /* 802.11i pmkid count */ + u_int16_t wpa_pmkids[8]; /* 802.11i pmkids */ +} __packed; + +#ifndef _BYTE_ORDER +#error "Don't know native byte order" +#endif + +#ifndef IEEE80211N_IE +/* Temporary vendor specific IE for 11n pre-standard interoperability */ +#define VENDOR_HT_OUI 0x00904c +#define VENDOR_HT_CAP_ID 51 +#define VENDOR_HT_INFO_ID 52 +#endif + +#ifdef ATH_SUPPORT_TxBF +union ieee80211_hc_txbf { + struct { +#if _BYTE_ORDER == _BIG_ENDIAN + u_int32_t reserved : 3, + channel_estimation_cap : 2, + csi_max_rows_bfer : 2, + comp_bfer_antennas : 2, + noncomp_bfer_antennas : 2, + csi_bfer_antennas : 2, + minimal_grouping : 2, + explicit_comp_bf : 2, + explicit_noncomp_bf : 2, + explicit_csi_feedback : 2, + explicit_comp_steering : 1, + explicit_noncomp_steering : 1, + explicit_csi_txbf_capable : 1, + calibration : 2, + implicit_txbf_capable : 1, + tx_ndp_capable : 1, + rx_ndp_capable : 1, + tx_staggered_sounding : 1, + rx_staggered_sounding : 1, + implicit_rx_capable : 1; +#else + u_int32_t implicit_rx_capable : 1, + rx_staggered_sounding : 1, + tx_staggered_sounding : 1, + rx_ndp_capable : 1, + tx_ndp_capable : 1, + implicit_txbf_capable : 1, + calibration : 2, + explicit_csi_txbf_capable : 1, + explicit_noncomp_steering : 1, + explicit_comp_steering : 1, + explicit_csi_feedback : 2, + explicit_noncomp_bf : 2, + explicit_comp_bf : 2, + minimal_grouping : 2, + csi_bfer_antennas : 2, + noncomp_bfer_antennas : 2, + comp_bfer_antennas : 2, + csi_max_rows_bfer : 2, + channel_estimation_cap : 2, + reserved : 3; +#endif + }; + + u_int32_t value; +} __packed; +#endif + +struct ieee80211_ie_htcap_cmn { + u_int16_t hc_cap; /* HT capabilities */ +#if _BYTE_ORDER == _BIG_ENDIAN + u_int8_t hc_reserved : 3, /* B5-7 reserved */ + hc_mpdudensity : 3, /* B2-4 MPDU density (aka Minimum MPDU Start Spacing) */ + hc_maxampdu : 2; /* B0-1 maximum rx A-MPDU factor */ +#else + u_int8_t hc_maxampdu : 2, /* B0-1 maximum rx A-MPDU factor */ + hc_mpdudensity : 3, /* B2-4 MPDU density (aka Minimum MPDU Start Spacing) */ + hc_reserved : 3; /* B5-7 reserved */ +#endif + u_int8_t hc_mcsset[16]; /* supported MCS set */ + u_int16_t hc_extcap; /* extended HT capabilities */ +#ifdef ATH_SUPPORT_TxBF + union ieee80211_hc_txbf hc_txbf; /* txbf capabilities */ +#else + u_int32_t hc_txbf; /* txbf capabilities */ +#endif + u_int8_t hc_antenna; /* antenna capabilities */ +} __packed; + +/* + * 802.11n HT Capability IE + */ +struct ieee80211_ie_htcap { + u_int8_t hc_id; /* element ID */ + u_int8_t hc_len; /* length in bytes */ + struct ieee80211_ie_htcap_cmn hc_ie; +} __packed; + +/* + * Temporary vendor private HT Capability IE + */ +struct vendor_ie_htcap { + u_int8_t hc_id; /* element ID */ + u_int8_t hc_len; /* length in bytes */ + u_int8_t hc_oui[3]; + u_int8_t hc_ouitype; + struct ieee80211_ie_htcap_cmn hc_ie; +} __packed; + +/* HT capability flags */ +#define IEEE80211_HTCAP_C_ADVCODING 0x0001 +#define IEEE80211_HTCAP_C_CHWIDTH40 0x0002 +#define IEEE80211_HTCAP_C_SMPOWERSAVE_STATIC 0x0000 /* Capable of SM Power Save (Static) */ +#define IEEE80211_HTCAP_C_SMPOWERSAVE_DYNAMIC 0x0004 /* Capable of SM Power Save (Dynamic) */ +#define IEEE80211_HTCAP_C_SM_RESERVED 0x0008 /* Reserved */ +#define IEEE80211_HTCAP_C_SM_ENABLED 0x000c /* SM enabled, no SM Power Save */ +#define IEEE80211_HTCAP_C_GREENFIELD 0x0010 +#define IEEE80211_HTCAP_C_SHORTGI20 0x0020 +#define IEEE80211_HTCAP_C_SHORTGI40 0x0040 +#define IEEE80211_HTCAP_C_TXSTBC 0x0080 +#define IEEE80211_HTCAP_C_TXSTBC_S 7 +#define IEEE80211_HTCAP_C_RXSTBC 0x0300 /* 2 bits */ +#define IEEE80211_HTCAP_C_RXSTBC_S 8 +#define IEEE80211_HTCAP_C_DELAYEDBLKACK 0x0400 +#define IEEE80211_HTCAP_C_MAXAMSDUSIZE 0x0800 /* 1 = 8K, 0 = 3839B */ +#define IEEE80211_HTCAP_C_DSSSCCK40 0x1000 +#define IEEE80211_HTCAP_C_PSMP 0x2000 +#define IEEE80211_HTCAP_C_INTOLERANT40 0x4000 +#define IEEE80211_HTCAP_C_LSIGTXOPPROT 0x8000 + +#define IEEE80211_HTCAP_C_SM_MASK 0x000c /* Spatial Multiplexing (SM) capabitlity bitmask */ + +/* B0-1 maximum rx A-MPDU factor 2^(13+Max Rx A-MPDU Factor) */ +enum { + IEEE80211_HTCAP_MAXRXAMPDU_8192, /* 2 ^ 13 */ + IEEE80211_HTCAP_MAXRXAMPDU_16384, /* 2 ^ 14 */ + IEEE80211_HTCAP_MAXRXAMPDU_32768, /* 2 ^ 15 */ + IEEE80211_HTCAP_MAXRXAMPDU_65536, /* 2 ^ 16 */ +}; +#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 + +/* B2-4 MPDU density (usec) */ +enum { + IEEE80211_HTCAP_MPDUDENSITY_NA, /* No time restriction */ + IEEE80211_HTCAP_MPDUDENSITY_0_25, /* 1/4 usec */ + IEEE80211_HTCAP_MPDUDENSITY_0_5, /* 1/2 usec */ + IEEE80211_HTCAP_MPDUDENSITY_1, /* 1 usec */ + IEEE80211_HTCAP_MPDUDENSITY_2, /* 2 usec */ + IEEE80211_HTCAP_MPDUDENSITY_4, /* 4 usec */ + IEEE80211_HTCAP_MPDUDENSITY_8, /* 8 usec */ + IEEE80211_HTCAP_MPDUDENSITY_16, /* 16 usec */ +}; + +/* HT extended capability flags */ +#define IEEE80211_HTCAP_EXTC_PCO 0x0001 +#define IEEE80211_HTCAP_EXTC_TRANS_TIME_RSVD 0x0000 +#define IEEE80211_HTCAP_EXTC_TRANS_TIME_400 0x0002 /* 20-40 switch time */ +#define IEEE80211_HTCAP_EXTC_TRANS_TIME_1500 0x0004 /* in us */ +#define IEEE80211_HTCAP_EXTC_TRANS_TIME_5000 0x0006 +#define IEEE80211_HTCAP_EXTC_RSVD_1 0x00f8 +#define IEEE80211_HTCAP_EXTC_MCS_FEEDBACK_NONE 0x0000 +#define IEEE80211_HTCAP_EXTC_MCS_FEEDBACK_RSVD 0x0100 +#define IEEE80211_HTCAP_EXTC_MCS_FEEDBACK_UNSOL 0x0200 +#define IEEE80211_HTCAP_EXTC_MCS_FEEDBACK_FULL 0x0300 +#define IEEE80211_HTCAP_EXTC_RSVD_2 0xfc00 +#ifdef ATH_SUPPORT_TxBF +#define IEEE80211_HTCAP_EXTC_HTC_SUPPORT 0x0400 +#endif + +struct ieee80211_ie_htinfo_cmn { + u_int8_t hi_ctrlchannel; /* control channel */ +#if _BYTE_ORDER == _BIG_ENDIAN + u_int8_t hi_serviceinterval : 3, /* B5-7 svc interval granularity */ + hi_ctrlaccess : 1, /* B4 controlled access only */ + hi_rifsmode : 1, /* B3 rifs mode */ + hi_txchwidth : 1, /* B2 recommended xmiss width set */ + hi_extchoff : 2; /* B0-1 extension channel offset */ + + +/* + + * The following 2 consecutive bytes are defined in word in 80211n spec. + + * Some processors store MSB byte into lower memory address which causes wrong + + * wrong byte sequence in beacon. Thus we break into byte definition which should + + * avoid the problem for all processors + + */ + + u_int8_t hi_reserved3 : 3, /* B5-7 reserved */ + + hi_obssnonhtpresent : 1, /* B4 OBSS non-HT STA present */ + + hi_txburstlimit : 1, /* B3 transmit burst limit */ + + hi_nongfpresent : 1, /* B2 non greenfield devices present */ + + hi_opmode : 2; /* B0-1 operating mode */ + + u_int8_t hi_reserved0 ; /* B0-7 (B8-15 in 11n) reserved */ + + + +/* The following 2 consecutive bytes are defined in word in 80211n spec. */ + + u_int8_t hi_dualctsprot : 1, /* B7 dual CTS protection */ + hi_dualbeacon : 1, /* B6 dual beacon */ + hi_reserved2 : 6; /* B0-5 reserved */ + u_int8_t hi_reserved1 : 4, /* B4-7 (B12-15 in 11n) reserved */ + hi_pcophase : 1, /* B3 (B11 in 11n) pco phase */ + hi_pcoactive : 1, /* B2 (B10 in 11n) pco active */ + hi_lsigtxopprot : 1, /* B1 (B9 in 11n) l-sig txop protection full support */ + hi_stbcbeacon : 1; /* B0 (B8 in 11n) STBC beacon */ +#else + u_int8_t hi_extchoff : 2, /* B0-1 extension channel offset */ + hi_txchwidth : 1, /* B2 recommended xmiss width set */ + hi_rifsmode : 1, /* B3 rifs mode */ + hi_ctrlaccess : 1, /* B4 controlled access only */ + hi_serviceinterval : 3; /* B5-7 svc interval granularity */ + u_int16_t hi_opmode : 2, /* B0-1 operating mode */ + hi_nongfpresent : 1, /* B2 non greenfield devices present */ + hi_txburstlimit : 1, /* B3 transmit burst limit */ + hi_obssnonhtpresent : 1, /* B4 OBSS non-HT STA present */ + hi_reserved0 : 11; /* B5-15 reserved */ + u_int16_t hi_reserved2 : 6, /* B0-5 reserved */ + hi_dualbeacon : 1, /* B6 dual beacon */ + hi_dualctsprot : 1, /* B7 dual CTS protection */ + hi_stbcbeacon : 1, /* B8 STBC beacon */ + hi_lsigtxopprot : 1, /* B9 l-sig txop protection full support */ + hi_pcoactive : 1, /* B10 pco active */ + hi_pcophase : 1, /* B11 pco phase */ + hi_reserved1 : 4; /* B12-15 reserved */ +#endif + u_int8_t hi_basicmcsset[16]; /* basic MCS set */ +} __packed; + +/* + * 802.11n HT Information IE + */ +struct ieee80211_ie_htinfo { + u_int8_t hi_id; /* element ID */ + u_int8_t hi_len; /* length in bytes */ + struct ieee80211_ie_htinfo_cmn hi_ie; +} __packed; + +/* + * Temporary vendor private HT Information IE + */ +struct vendor_ie_htinfo { + u_int8_t hi_id; /* element ID */ + u_int8_t hi_len; /* length in bytes */ + u_int8_t hi_oui[3]; + u_int8_t hi_ouitype; + struct ieee80211_ie_htinfo_cmn hi_ie; +} __packed; + +/* extension channel offset (2 bit signed number) */ +enum { + IEEE80211_HTINFO_EXTOFFSET_NA = 0, /* 0 no extension channel is present */ + IEEE80211_HTINFO_EXTOFFSET_ABOVE = 1, /* +1 extension channel above control channel */ + IEEE80211_HTINFO_EXTOFFSET_UNDEF = 2, /* -2 undefined */ + IEEE80211_HTINFO_EXTOFFSET_BELOW = 3 /* -1 extension channel below control channel*/ +}; + +/* recommended transmission width set */ +enum { + IEEE80211_HTINFO_TXWIDTH_20, + IEEE80211_HTINFO_TXWIDTH_2040 +}; + +/* operating flags */ +#define IEEE80211_HTINFO_OPMODE_PURE 0x00 /* no protection */ +#define IEEE80211_HTINFO_OPMODE_MIXED_PROT_OPT 0x01 /* prot optional (legacy device maybe present) */ +#define IEEE80211_HTINFO_OPMODE_MIXED_PROT_40 0x02 /* prot required (20 MHz) */ +#define IEEE80211_HTINFO_OPMODE_MIXED_PROT_ALL 0x03 /* prot required (legacy devices present) */ +#define IEEE80211_HTINFO_OPMODE_NON_GF_PRESENT 0x04 /* non-greenfield devices present */ + +#define IEEE80211_HTINFO_OPMODE_MASK 0x03 /* For protection 0x00-0x03 */ + +/* Non-greenfield STAs present */ +enum { + IEEE80211_HTINFO_NON_GF_NOT_PRESENT, /* Non-greenfield STAs not present */ + IEEE80211_HTINFO_NON_GF_PRESENT, /* Non-greenfield STAs present */ +}; + +/* Transmit Burst Limit */ +enum { + IEEE80211_HTINFO_TXBURST_UNLIMITED, /* Transmit Burst is unlimited */ + IEEE80211_HTINFO_TXBURST_LIMITED, /* Transmit Burst is limited */ +}; + +/* OBSS Non-HT STAs present */ +enum { + IEEE80211_HTINFO_OBSS_NONHT_NOT_PRESENT, /* OBSS Non-HT STAs not present */ + IEEE80211_HTINFO_OBSS_NONHT_PRESENT, /* OBSS Non-HT STAs present */ +}; + +/* misc flags */ +#define IEEE80211_HTINFO_DUALBEACON 0x0040 /* B6 dual beacon */ +#define IEEE80211_HTINFO_DUALCTSPROT 0x0080 /* B7 dual stbc protection */ +#define IEEE80211_HTINFO_STBCBEACON 0x0100 /* B8 secondary beacon */ +#define IEEE80211_HTINFO_LSIGTXOPPROT 0x0200 /* B9 lsig txop prot full support */ +#define IEEE80211_HTINFO_PCOACTIVE 0x0400 /* B10 pco active */ +#define IEEE80211_HTINFO_PCOPHASE 0x0800 /* B11 pco phase */ + +/* Secondary Channel offset for for 40MHz direct link */ +#define IEEE80211_SECONDARY_CHANNEL_ABOVE 1 +#define IEEE80211_SECONDARY_CHANNEL_BELOW 3 + +#define IEEE80211_TDLS_CHAN_SX_PROHIBIT 0x00000002 /* bit-2 TDLS Channel Switch Prohibit */ + +/* RIFS mode */ +enum { + IEEE80211_HTINFO_RIFSMODE_PROHIBITED, /* use of rifs prohibited */ + IEEE80211_HTINFO_RIFSMODE_ALLOWED, /* use of rifs permitted */ +}; + +/* + * Management information element payloads. + */ +enum { + IEEE80211_ELEMID_SSID = 0, + IEEE80211_ELEMID_RATES = 1, + IEEE80211_ELEMID_FHPARMS = 2, + IEEE80211_ELEMID_DSPARMS = 3, + IEEE80211_ELEMID_CFPARMS = 4, + IEEE80211_ELEMID_TIM = 5, + IEEE80211_ELEMID_IBSSPARMS = 6, + IEEE80211_ELEMID_COUNTRY = 7, + IEEE80211_ELEMID_REQINFO = 10, + IEEE80211_ELEMID_QBSS_LOAD = 11, + IEEE80211_ELEMID_TCLAS = 14, + IEEE80211_ELEMID_CHALLENGE = 16, + /* 17-31 reserved for challenge text extension */ + IEEE80211_ELEMID_PWRCNSTR = 32, + IEEE80211_ELEMID_PWRCAP = 33, + IEEE80211_ELEMID_TPCREQ = 34, + IEEE80211_ELEMID_TPCREP = 35, + IEEE80211_ELEMID_SUPPCHAN = 36, + IEEE80211_ELEMID_CHANSWITCHANN = 37, + IEEE80211_ELEMID_MEASREQ = 38, + IEEE80211_ELEMID_MEASREP = 39, + IEEE80211_ELEMID_QUIET = 40, + IEEE80211_ELEMID_IBSSDFS = 41, + IEEE80211_ELEMID_ERP = 42, + IEEE80211_ELEMID_TCLAS_PROCESS = 44, + IEEE80211_ELEMID_HTCAP_ANA = 45, + IEEE80211_ELEMID_RESERVED_47 = 47, + IEEE80211_ELEMID_RSN = 48, + IEEE80211_ELEMID_XRATES = 50, + IEEE80211_ELEMID_HTCAP = 51, + IEEE80211_ELEMID_HTINFO = 52, + IEEE80211_ELEMID_MOBILITY_DOMAIN = 54, + IEEE80211_ELEMID_FT = 55, + IEEE80211_ELEMID_TIMEOUT_INTERVAL = 56, + IEEE80211_ELEMID_EXTCHANSWITCHANN = 60, + IEEE80211_ELEMID_HTINFO_ANA = 61, + IEEE80211_ELEMID_SECCHANOFFSET = 62, + IEEE80211_ELEMID_WAPI = 68, /*IE for WAPI*/ + IEEE80211_ELEMID_TIME_ADVERTISEMENT = 69, + IEEE80211_ELEMID_RRM = 70, /* Radio resource measurement */ + IEEE80211_ELEMID_2040_COEXT = 72, + IEEE80211_ELEMID_2040_INTOL = 73, + IEEE80211_ELEMID_OBSS_SCAN = 74, + IEEE80211_ELEMID_MMIE = 76, /* 802.11w Management MIC IE */ + IEEE80211_ELEMID_FMS_DESCRIPTOR = 86, /* 802.11v FMS descriptor IE */ + IEEE80211_ELEMID_FMS_REQUEST = 87, /* 802.11v FMS request IE */ + IEEE80211_ELEMID_FMS_RESPONSE = 88, /* 802.11v FMS response IE */ + IEEE80211_ELEMID_BSSMAX_IDLE_PERIOD = 90, /* BSS MAX IDLE PERIOD */ + IEEE80211_ELEMID_TFS_REQUEST = 91, + IEEE80211_ELEMID_TFS_RESPONSE = 92, + IEEE80211_ELEMID_TIM_BCAST_REQUEST = 94, + IEEE80211_ELEMID_TIM_BCAST_RESPONSE = 95, + IEEE80211_ELEMID_INTERWORKING = 107, + IEEE80211_ELEMID_XCAPS = 127, + IEEE80211_ELEMID_RESERVED_133 = 133, + IEEE80211_ELEMID_TPC = 150, + IEEE80211_ELEMID_CCKM = 156, + IEEE80211_ELEMID_VHTCAP = 191, /* VHT Capabilities */ + IEEE80211_ELEMID_VHTOP = 192, /* VHT Operation */ + IEEE80211_ELEMID_EXT_BSS_LOAD = 193, /* Extended BSS Load */ + IEEE80211_ELEMID_WIDE_BAND_CHAN_SWITCH = 194, /* Wide Band Channel Switch */ + IEEE80211_ELEMID_VHT_TX_PWR_ENVLP = 195, /* VHT Transmit Power Envelope */ + IEEE80211_ELEMID_CHAN_SWITCH_WRAP = 196, /* Channel Switch Wrapper */ + IEEE80211_ELEMID_AID = 197, /* AID */ + IEEE80211_ELEMID_QUIET_CHANNEL = 198, /* Quiet Channel */ + IEEE80211_ELEMID_OP_MODE_NOTIFY = 199, /* Operating Mode Notification */ + IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ +}; + +#define IEEE80211_MAX_IE_LEN 255 +#define IEEE80211_RSN_IE_LEN 22 + +#define IEEE80211_CHANSWITCHANN_BYTES 5 +#define IEEE80211_EXTCHANSWITCHANN_BYTES 6 + +//TODO -> Need to Check Redefinition Error used in only UMAC +#if 0 +struct ieee80211_tim_ie { + u_int8_t tim_ie; /* IEEE80211_ELEMID_TIM */ + u_int8_t tim_len; + u_int8_t tim_count; /* DTIM count */ + u_int8_t tim_period; /* DTIM period */ + u_int8_t tim_bitctl; /* bitmap control */ + u_int8_t tim_bitmap[1]; /* variable-length bitmap */ +} __packed; +#endif + +/* Country IE channel triplet */ +struct country_ie_triplet { + union{ + u_int8_t schan; /* starting channel */ + u_int8_t regextid; /* Regulatory Extension Identifier */ + }; + union{ + u_int8_t nchan; /* number of channels */ + u_int8_t regclass; /* Regulatory Class */ + }; + union{ + u_int8_t maxtxpwr; /* tx power */ + u_int8_t coverageclass; /* Coverage Class */ + }; +}__packed; + +struct ieee80211_country_ie { + u_int8_t ie; /* IEEE80211_ELEMID_COUNTRY */ + u_int8_t len; + u_int8_t cc[3]; /* ISO CC+(I)ndoor/(O)utdoor */ + struct country_ie_triplet triplet[1]; +} __packed; + +struct ieee80211_fh_ie { + u_int8_t ie; /* IEEE80211_ELEMID_FHPARMS */ + u_int8_t len; + u_int16_t dwell_time; // endianess?? + u_int8_t hop_set; + u_int8_t hop_pattern; + u_int8_t hop_index; +} __packed; + +struct ieee80211_ds_ie { + u_int8_t ie; /* IEEE80211_ELEMID_DSPARMS */ + u_int8_t len; + u_int8_t current_channel; +} __packed; + +struct ieee80211_erp_ie { + u_int8_t ie; /* IEEE80211_ELEMID_ERP */ + u_int8_t len; + u_int8_t value; +} __packed; + +//TODO -> Need to Check Redefinition Error used in only UMAC +#if 0 +struct ieee80211_quiet_ie { + u_int8_t ie; /* IEEE80211_ELEMID_QUIET */ + u_int8_t len; + u_int8_t tbttcount; /* quiet start */ + u_int8_t period; /* beacon intervals between quiets*/ + u_int16_t duration; /* TUs of each quiet*/ + u_int16_t offset; /* TUs of from TBTT of quiet start*/ +} __packed; +#endif + +struct ieee80211_channelswitch_ie { + u_int8_t ie; /* IEEE80211_ELEMID_CHANSWITCHANN */ + u_int8_t len; + u_int8_t switchmode; + u_int8_t newchannel; + u_int8_t tbttcount; +} __packed; + +/* channel switch action frame format definition */ +struct ieee80211_action_spectrum_channel_switch { + struct ieee80211_action csa_header; + struct ieee80211_channelswitch_ie csa_element; +}__packed; + +struct ieee80211_extendedchannelswitch_ie { + u_int8_t ie; /* IEEE80211_ELEMID_EXTCHANSWITCHANN */ + u_int8_t len; + u_int8_t switchmode; + u_int8_t newClass; + u_int8_t newchannel; + u_int8_t tbttcount; +} __packed; + +struct ieee80211_tpc_ie { + u_int8_t ie; + u_int8_t len; + u_int8_t pwrlimit; +} __packed; + +/* + * MHDRIE included in TKIP MFP protected management frames + */ +struct ieee80211_ese_mhdr_ie { + u_int8_t mhdr_id; + u_int8_t mhdr_len; + u_int8_t mhdr_oui[3]; + u_int8_t mhdr_oui_type; + u_int8_t mhdr_fc[2]; + u_int8_t mhdr_bssid[6]; +} __packed; + +/* + * SSID IE + */ +struct ieee80211_ie_ssid { + u_int8_t ssid_id; + u_int8_t ssid_len; + u_int8_t ssid[32]; +} __packed; + +/* + * Supported rates + */ +#define IEEE80211_MAX_SUPPORTED_RATES 8 + +struct ieee80211_ie_rates { + u_int8_t rate_id; /* Element Id */ + u_int8_t rate_len; /* IE Length */ + u_int8_t rate[IEEE80211_MAX_SUPPORTED_RATES]; /* IE Length */ +} __packed; + +/* + * Extended rates + */ +#define IEEE80211_MAX_EXTENDED_RATES 256 + +struct ieee80211_ie_xrates { + u_int8_t xrate_id; /* Element Id */ + u_int8_t xrate_len; /* IE Length */ + u_int8_t xrate[IEEE80211_MAX_EXTENDED_RATES]; /* IE Length */ +} __packed; + +/* + * WPS SSID list information element (maximally sized). + */ +struct ieee80211_ie_ssidl { + u_int8_t ssidl_id; /* IEEE80211_ELEMID_VENDOR */ + u_int8_t ssidl_len; /* length in bytes */ + u_int8_t ssidl_oui[3]; /* 0x00, 0x50, 0xf2 */ + u_int8_t ssidl_type; /* OUI type */ + u_int8_t ssidl_prim_cap; /* Primary capabilities */ + u_int8_t ssidl_count; /* # of secondary SSIDs */ + u_int16_t ssidl_value[248]; +} __packed; + +#if _BYTE_ORDER == _BIG_ENDIAN +struct ieee80211_sec_ssid_cap { + u_int32_t reserved0 :1, + akmlist :6, + reserved1 :4, + reeserved2 :2, + ucipher :15, + mcipher :4; +}; +#else +struct ieee80211_sec_ssid_cap { + u_int32_t mcipher :4, + ucipher :15, + reserved2 :2, + reserved1 :4, + akmlist :6, + reserved0 :1; +}; +#endif + +struct ieee80211_ie_qbssload { + u_int8_t elem_id; /* IEEE80211_ELEMID_QBSS_LOAD */ + u_int8_t length; /* length in bytes */ + u_int16_t station_count; /* number of station associated */ + u_int8_t channel_utilization; /* channel busy time in 0-255 scale */ + u_int16_t aac; /* available admission capacity */ +} __packed; + +#define SEC_SSID_HEADER_LEN 6 +#define SSIDL_IE_HEADER_LEN 6 + +struct ieee80211_sec_ssid { + u_int8_t sec_ext_cap; + struct ieee80211_sec_ssid_cap sec_cap; + u_int8_t sec_ssid_len; + u_int8_t sec_ssid[32]; +} __packed; + +/* Definitions of SSIDL IE */ +enum { + CAP_MCIPHER_ENUM_NONE = 0, + CAP_MCIPHER_ENUM_WEP40, + CAP_MCIPHER_ENUM_WEP104, + CAP_MCIPHER_ENUM_TKIP, + CAP_MCIPHER_ENUM_CCMP, + CAP_MCIPHER_ENUM_CKIP_CMIC, + CAP_MCIPHER_ENUM_CKIP, + CAP_MCIPHER_ENUM_CMIC +}; + + +#define CAP_UCIPHER_BIT_NONE 0x0001 +#define CAP_UCIPHER_BIT_WEP40 0x0002 +#define CAP_UCIPHER_BIT_WEP104 0x0004 +#define CAP_UCIPHER_BIT_TKIP 0x0008 +#define CAP_UCIPHER_BIT_CCMP 0x0010 +#define CAP_UCIPHER_BIT_CKIP_CMIC 0x0020 +#define CAP_UCIPHER_BIT_CKIP 0x0040 +#define CAP_UCIPHER_BIT_CMIC 0x0080 +#define CAP_UCIPHER_BIT_WPA2_WEP40 0x0100 +#define CAP_UCIPHER_BIT_WPA2_WEP104 0x0200 +#define CAP_UCIPHER_BIT_WPA2_TKIP 0x0400 +#define CAP_UCIPHER_BIT_WPA2_CCMP 0x0800 +#define CAP_UCIPHER_BIT_WPA2_CKIP_CMIC 0x1000 +#define CAP_UCIPHER_BIT_WPA2_CKIP 0x2000 +#define CAP_UCIPHER_BIT_WPA2_CMIC 0x4000 + +#define CAP_AKM_BIT_WPA1_1X 0x01 +#define CAP_AKM_BIT_WPA1_PSK 0x02 +#define CAP_AKM_BIT_WPA2_1X 0x04 +#define CAP_AKM_BIT_WPA2_PSK 0x08 +#define CAP_AKM_BIT_WPA1_CCKM 0x10 +#define CAP_AKM_BIT_WPA2_CCKM 0x20 + +#define IEEE80211_CHALLENGE_LEN 128 + +#define IEEE80211_SUPPCHAN_LEN 26 + +#define IEEE80211_RATE_BASIC 0x80 +#define IEEE80211_RATE_VAL 0x7f + +/* EPR information element flags */ +#define IEEE80211_ERP_NON_ERP_PRESENT 0x01 +#define IEEE80211_ERP_USE_PROTECTION 0x02 +#define IEEE80211_ERP_LONG_PREAMBLE 0x04 + +/* Atheros private advanced capabilities info */ +#define ATHEROS_CAP_TURBO_PRIME 0x01 +#define ATHEROS_CAP_COMPRESSION 0x02 +#define ATHEROS_CAP_FAST_FRAME 0x04 +/* bits 3-6 reserved */ +#define ATHEROS_CAP_BOOST 0x80 + +#define ATH_OUI 0x7f0300 /* Atheros OUI */ +#define ATH_OUI_TYPE 0x01 +#define ATH_OUI_SUBTYPE 0x01 +#define ATH_OUI_VERSION 0x00 +#define ATH_OUI_TYPE_XR 0x03 +#define ATH_OUI_VER_XR 0x01 +#define ATH_OUI_EXTCAP_TYPE 0x04 /* Atheros Extended Cap Type */ +#define ATH_OUI_EXTCAP_SUBTYPE 0x01 /* Atheros Extended Cap Sub-type */ +#define ATH_OUI_EXTCAP_VERSION 0x00 /* Atheros Extended Cap Version */ + +#define WPA_OUI 0xf25000 +#define WPA_VERSION 1 /* current supported version */ +#define CSCO_OUI 0x964000 /* Cisco OUI */ +#define AOW_OUI 0x4a0100 /* AoW OUI, workaround */ +#define AOW_OUI_TYPE 0x01 +#define AOW_OUI_VERSION 0x01 + +#define WSC_OUI 0x0050f204 + +#define WPA_CSE_NULL 0x00 +#define WPA_CSE_WEP40 0x01 +#define WPA_CSE_TKIP 0x02 +#define WPA_CSE_CCMP 0x04 +#define WPA_CSE_WEP104 0x05 + +#define WPA_ASE_NONE 0x00 +#define WPA_ASE_8021X_UNSPEC 0x01 +#define WPA_ASE_8021X_PSK 0x02 +#define WPA_ASE_FT_IEEE8021X 0x20 +#define WPA_ASE_FT_PSK 0x40 +#define WPA_ASE_SHA256_IEEE8021X 0x80 +#define WPA_ASE_SHA256_PSK 0x100 +#define WPA_ASE_WPS 0x200 + + +#define RSN_OUI 0xac0f00 +#define RSN_VERSION 1 /* current supported version */ + +#define RSN_CSE_NULL 0x00 +#define RSN_CSE_WEP40 0x01 +#define RSN_CSE_TKIP 0x02 +#define RSN_CSE_WRAP 0x03 +#define RSN_CSE_CCMP 0x04 +#define RSN_CSE_WEP104 0x05 +#define RSN_CSE_AES_CMAC 0x06 + +#define RSN_ASE_NONE 0x00 +#define RSN_ASE_8021X_UNSPEC 0x01 +#define RSN_ASE_8021X_PSK 0x02 +#define RSN_ASE_FT_IEEE8021X 0x20 +#define RSN_ASE_FT_PSK 0x40 +#define RSN_ASE_SHA256_IEEE8021X 0x80 +#define RSN_ASE_SHA256_PSK 0x100 +#define RSN_ASE_WPS 0x200 + +#define AKM_SUITE_TYPE_IEEE8021X 0x01 +#define AKM_SUITE_TYPE_PSK 0x02 +#define AKM_SUITE_TYPE_FT_IEEE8021X 0x03 +#define AKM_SUITE_TYPE_FT_PSK 0x04 +#define AKM_SUITE_TYPE_SHA256_IEEE8021X 0x05 +#define AKM_SUITE_TYPE_SHA256_PSK 0x06 + +#define RSN_CAP_PREAUTH 0x01 +#define RSN_CAP_PTKSA_REPLAYCOUNTER 0x0c +#define RSN_CAP_GTKSA_REPLAYCOUNTER 0x30 +#define RSN_CAP_MFP_REQUIRED 0x40 +#define RSN_CAP_MFP_ENABLED 0x80 + +#define CCKM_OUI 0x964000 +#define CCKM_ASE_UNSPEC 0 +#define WPA_CCKM_AKM 0x00964000 +#define RSN_CCKM_AKM 0x00964000 + +#define WME_OUI 0xf25000 +#define WME_OUI_TYPE 0x02 +#define WME_INFO_OUI_SUBTYPE 0x00 +#define WME_PARAM_OUI_SUBTYPE 0x01 +#define WME_TSPEC_OUI_SUBTYPE 0x02 + +#define WME_PARAM_OUI_VERSION 1 +#define WME_TSPEC_OUI_VERSION 1 +#define WME_VERSION 1 + +/* WME stream classes */ +#define WME_AC_BE 0 /* best effort */ +#define WME_AC_BK 1 /* background */ +#define WME_AC_VI 2 /* video */ +#define WME_AC_VO 3 /* voice */ + +/* WCN IE */ +#define WCN_OUI 0xf25000 /* Microsoft OUI */ +#define WCN_OUI_TYPE 0x04 /* WCN */ + +/* Atheros htoui for ht vender ie; use Epigram OUI for compatibility with pre11n devices */ +#define ATH_HTOUI 0x00904c + +#define SFA_OUI 0x964000 +#define SFA_OUI_TYPE 0x14 +#define SFA_IE_CAP_MFP 0x01 +#define SFA_IE_CAP_DIAG_CHANNEL 0x02 +#define SFA_IE_CAP_LOCATION_SVCS 0x04 +#define SFA_IE_CAP_EXP_BANDWIDTH 0x08 + +#define WPA_OUI_BYTES 0x00, 0x50, 0xf2 +#define RSN_OUI_BYTES 0x00, 0x0f, 0xac +#define WME_OUI_BYTES 0x00, 0x50, 0xf2 +#define ATH_OUI_BYTES 0x00, 0x03, 0x7f +#define SFA_OUI_BYTES 0x00, 0x40, 0x96 +#define CCKM_OUI_BYTES 0x00, 0x40, 0x96 +#define WPA_SEL(x) (((x)<<24)|WPA_OUI) +#define RSN_SEL(x) (((x)<<24)|RSN_OUI) +#define SFA_SEL(x) (((x)<<24)|SFA_OUI) +#define CCKM_SEL(x) (((x)<<24)|CCKM_OUI) + +#define IEEE80211_RV(v) ((v) & IEEE80211_RATE_VAL) +#define IEEE80211_N(a) (sizeof(a) / sizeof(a[0])) + +/* + * AUTH management packets + * + * octet algo[2] + * octet seq[2] + * octet status[2] + * octet chal.id + * octet chal.length + * octet chal.text[253] + */ + +typedef u_int8_t *ieee80211_mgt_auth_t; + +#define IEEE80211_AUTH_ALGORITHM(auth) \ + ((auth)[0] | ((auth)[1] << 8)) +#define IEEE80211_AUTH_TRANSACTION(auth) \ + ((auth)[2] | ((auth)[3] << 8)) +#define IEEE80211_AUTH_STATUS(auth) \ + ((auth)[4] | ((auth)[5] << 8)) + +#define IEEE80211_AUTH_ALG_OPEN 0x0000 +#define IEEE80211_AUTH_ALG_SHARED 0x0001 +#define IEEE80211_AUTH_ALG_FT 0x0002 +#define IEEE80211_AUTH_ALG_LEAP 0x0080 + +enum { + IEEE80211_AUTH_OPEN_REQUEST = 1, + IEEE80211_AUTH_OPEN_RESPONSE = 2, +}; + +enum { + IEEE80211_AUTH_SHARED_REQUEST = 1, + IEEE80211_AUTH_SHARED_CHALLENGE = 2, + IEEE80211_AUTH_SHARED_RESPONSE = 3, + IEEE80211_AUTH_SHARED_PASS = 4, +}; + +/* + * Reason codes + * + * Unlisted codes are reserved + */ + +enum { + IEEE80211_REASON_UNSPECIFIED = 1, + IEEE80211_REASON_AUTH_EXPIRE = 2, + IEEE80211_REASON_AUTH_LEAVE = 3, + IEEE80211_REASON_ASSOC_EXPIRE = 4, + IEEE80211_REASON_ASSOC_TOOMANY = 5, + IEEE80211_REASON_NOT_AUTHED = 6, + IEEE80211_REASON_NOT_ASSOCED = 7, + IEEE80211_REASON_ASSOC_LEAVE = 8, + IEEE80211_REASON_ASSOC_NOT_AUTHED = 9, + + IEEE80211_REASON_RSN_REQUIRED = 11, + IEEE80211_REASON_RSN_INCONSISTENT = 12, + IEEE80211_REASON_IE_INVALID = 13, + IEEE80211_REASON_MIC_FAILURE = 14, + + IEEE80211_REASON_QOS = 32, + IEEE80211_REASON_QOS_BANDWITDH = 33, + IEEE80211_REASON_QOS_CH_CONDITIONS = 34, + IEEE80211_REASON_QOS_TXOP = 35, + IEEE80211_REASON_QOS_LEAVE = 36, + IEEE80211_REASON_QOS_DECLINED = 37, + IEEE80211_REASON_QOS_SETUP_REQUIRED = 38, + IEEE80211_REASON_QOS_TIMEOUT = 39, + IEEE80211_REASON_QOS_CIPHER = 45, + + IEEE80211_STATUS_SUCCESS = 0, + IEEE80211_STATUS_UNSPECIFIED = 1, + IEEE80211_STATUS_CAPINFO = 10, + IEEE80211_STATUS_NOT_ASSOCED = 11, + IEEE80211_STATUS_OTHER = 12, + IEEE80211_STATUS_ALG = 13, + IEEE80211_STATUS_SEQUENCE = 14, + IEEE80211_STATUS_CHALLENGE = 15, + IEEE80211_STATUS_TIMEOUT = 16, + IEEE80211_STATUS_TOOMANY = 17, + IEEE80211_STATUS_BASIC_RATE = 18, + IEEE80211_STATUS_SP_REQUIRED = 19, + IEEE80211_STATUS_PBCC_REQUIRED = 20, + IEEE80211_STATUS_CA_REQUIRED = 21, + IEEE80211_STATUS_TOO_MANY_STATIONS = 22, + IEEE80211_STATUS_RATES = 23, + IEEE80211_STATUS_SHORTSLOT_REQUIRED = 25, + IEEE80211_STATUS_DSSSOFDM_REQUIRED = 26, + IEEE80211_STATUS_NO_HT = 27, + IEEE80211_STATUS_REJECT_TEMP = 30, + IEEE80211_STATUS_MFP_VIOLATION = 31, + IEEE80211_STATUS_REFUSED = 37, + IEEE80211_STATUS_INVALID_PARAM = 38, + + IEEE80211_STATUS_DLS_NOT_ALLOWED = 48, +}; + +/* private IEEE80211_STATUS */ +#define IEEE80211_STATUS_CANCEL -1 +#define IEEE80211_STATUS_INVALID_IE -2 +#define IEEE80211_STATUS_INVALID_CHANNEL -3 + +#define IEEE80211_WEP_KEYLEN 5 /* 40bit */ +#define IEEE80211_WEP_IVLEN 3 /* 24bit */ +#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */ +#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */ +#define IEEE80211_WEP_NKID 4 /* number of key ids */ + +/* + * 802.11i defines an extended IV for use with non-WEP ciphers. + * When the EXTIV bit is set in the key id byte an additional + * 4 bytes immediately follow the IV for TKIP. For CCMP the + * EXTIV bit is likewise set but the 8 bytes represent the + * CCMP header rather than IV+extended-IV. + */ +#define IEEE80211_WEP_EXTIV 0x20 +#define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */ +#define IEEE80211_WEP_MICLEN 8 /* trailing MIC */ + +#define IEEE80211_CCMP_HEADERLEN 8 +#define IEEE80211_CCMP_MICLEN 8 + +/* + * 802.11w defines a MMIE chunk to be attached at the end of + * any outgoing broadcast or multicast robust management frame. + * MMIE field is total 18 bytes in size. Following the diagram of MMIE + * + * <------------ 18 Bytes MMIE -----------------------> + * +--------+---------+---------+-----------+---------+ + * |Element | Length | Key id | IPN | MIC | + * | id | | | | | + * +--------+---------+---------+-----------+---------+ + * bytes 1 1 2 6 8 + * + */ +#define IEEE80211_MMIE_LEN 18 +#define IEEE80211_MMIE_ELEMENTIDLEN 1 +#define IEEE80211_MMIE_LENGTHLEN 1 +#define IEEE80211_MMIE_KEYIDLEN 2 +#define IEEE80211_MMIE_IPNLEN 6 +#define IEEE80211_MMIE_MICLEN 8 + +#define IEEE80211_CRC_LEN 4 + +#define IEEE80211_8021Q_HEADER_LEN 4 +/* + * Maximum acceptable MTU is: + * IEEE80211_MAX_LEN - WEP overhead - CRC - + * QoS overhead - RSN/WPA overhead + * Min is arbitrarily chosen > IEEE80211_MIN_LEN. The default + * mtu is Ethernet-compatible; it's set by ether_ifattach. + */ +#define IEEE80211_MTU_MAX 2290 +#define IEEE80211_MTU_MIN 32 + +/* Rather than using this default value, customer platforms can provide a custom value for this constant. + Coustomer platform will use the different define value by themself */ +#ifndef IEEE80211_MAX_MPDU_LEN +#define IEEE80211_MAX_MPDU_LEN (3840 + IEEE80211_CRC_LEN + \ + (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN)) +#endif +#define IEEE80211_ACK_LEN \ + (sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN) +#define IEEE80211_MIN_LEN \ + (sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN) + +/* An 802.11 data frame can be one of three types: +1. An unaggregated frame: The maximum length of an unaggregated data frame is 2324 bytes + headers. +2. A data frame that is part of an AMPDU: The maximum length of an AMPDU may be upto 65535 bytes, but data frame is limited to 2324 bytes + header. +3. An AMSDU: The maximum length of an AMSDU is eihther 3839 or 7095 bytes. +The maximum frame length supported by hardware is 4095 bytes. +A length of 3839 bytes is chosen here to support unaggregated data frames, any size AMPDUs and 3839 byte AMSDUs. +*/ +#define IEEE80211N_MAX_FRAMELEN 3839 +#define IEEE80211N_MAX_LEN (IEEE80211N_MAX_FRAMELEN + IEEE80211_CRC_LEN + \ + (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN)) + +#define IEEE80211_TX_CHAINMASK_MIN 1 +#define IEEE80211_TX_CHAINMASK_MAX 7 + +#define IEEE80211_RX_CHAINMASK_MIN 1 +#define IEEE80211_RX_CHAINMASK_MAX 7 + +/* + * The 802.11 spec says at most 2007 stations may be + * associated at once. For most AP's this is way more + * than is feasible so we use a default of 128. This + * number may be overridden by the driver and/or by + * user configuration. + */ +#define IEEE80211_AID_MAX 2007 +#define IEEE80211_AID_DEF 128 + +#define IEEE80211_AID(b) ((b) &~ 0xc000) + +/* + * RTS frame length parameters. The default is specified in + * the 802.11 spec. The max may be wrong for jumbo frames. + */ +#define IEEE80211_RTS_DEFAULT 512 +#define IEEE80211_RTS_MIN 0 +#define IEEE80211_RTS_MAX 2347 + +/* + * Fragmentation limits + */ +#define IEEE80211_FRAGMT_THRESHOLD_MIN 540 /* min frag threshold */ +#define IEEE80211_FRAGMT_THRESHOLD_MAX 2346 /* max frag threshold */ + +/* + * Regulatory extention identifier for country IE. + */ +#define IEEE80211_REG_EXT_ID 201 + +/* + * overlapping BSS + */ +#define IEEE80211_OBSS_SCAN_PASSIVE_DWELL_DEF 20 +#define IEEE80211_OBSS_SCAN_ACTIVE_DWELL_DEF 10 +#define IEEE80211_OBSS_SCAN_INTERVAL_DEF 300 +#define IEEE80211_OBSS_SCAN_PASSIVE_TOTAL_DEF 200 +#define IEEE80211_OBSS_SCAN_ACTIVE_TOTAL_DEF 20 +#define IEEE80211_OBSS_SCAN_THRESH_DEF 25 +#define IEEE80211_OBSS_SCAN_DELAY_DEF 5 + +/* + * overlapping BSS scan ie + */ +struct ieee80211_ie_obss_scan { + u_int8_t elem_id; + u_int8_t elem_len; + u_int16_t scan_passive_dwell; + u_int16_t scan_active_dwell; + u_int16_t scan_interval; + u_int16_t scan_passive_total; + u_int16_t scan_active_total; + u_int16_t scan_delay; + u_int16_t scan_thresh; +} __packed; + +/* + * Extended capability ie + */ +struct ieee80211_ie_ext_cap { + u_int8_t elem_id; + u_int8_t elem_len; + u_int32_t ext_capflags; + u_int32_t ext_capflags2; +} __packed; + +/* Extended capability IE flags */ +#define IEEE80211_EXTCAPIE_2040COEXTMGMT 0x00000001 +#define IEEE80211_EXTCAPIE_TFS 0x00010000 +#define IEEE80211_EXTCAPIE_FMS 0x00000800 +#define IEEE80211_EXTCAPIE_WNMSLEEPMODE 0x00020000 +#define IEEE80211_EXTCAPIE_TIMBROADCAST 0x00040000 +#define IEEE80211_EXTCAPIE_PROXYARP 0x00001000 +#define IEEE80211_EXTCAPIE_BSSTRANSITION 0x00080000 +/* Tunneled Direct Link Setup (TDLS) extended capability bits */ +#define IEEE80211_EXTCAPIE_PEER_UAPSD_BUF_STA 0x10000000 +#define IEEE80211_EXTCAPIE_TDLS_PEER_PSM 0x20000000 +#define IEEE80211_EXTCAPIE_TDLS_CHAN_SX 0x40000000 +/* 2nd Extended capability IE flags bit32-bit63*/ +#define IEEE80211_EXTCAPIE_TDLSSUPPORT 0x00000020 /* bit-37 TDLS Support */ +#define IEEE80211_EXTCAPIE_TDLSPROHIBIT 0x00000040 /* bit-38 TDLS Prohibit Support */ +#define IEEE80211_EXTCAPIE_TDLSCHANSXPROHIBIT 0x00000080 /* bit-39 TDLS Channel Switch Prohibit */ +#define IEEE80211_EXTCAPIE_TDLS_WIDE_BAND 0x20000080 /* bit-61 TDLS Wide Bandwidth support */ +#define IEEE80211_EXTCAPIE_OP_MODE_NOTIFY 0x40000000 /* bit-62 Operating Mode notification */ + +/* + * These caps are populated when we recieve beacon/probe response + * This is used to maintain local TDLS cap bit masks + */ + +#define IEEE80211_TDLS_PROHIBIT 0x00000001 /* bit-1 TDLS Prohibit Support */ + +/* + * 20/40 BSS coexistence ie + */ +struct ieee80211_ie_bss_coex { + u_int8_t elem_id; + u_int8_t elem_len; +#if _BYTE_ORDER == _BIG_ENDIAN + u_int8_t reserved1 : 1, + reserved2 : 1, + reserved3 : 1, + obss_exempt_grant : 1, + obss_exempt_req : 1, + ht20_width_req : 1, + ht40_intolerant : 1, + inf_request : 1; +#else + u_int8_t inf_request : 1, + ht40_intolerant : 1, + ht20_width_req : 1, + obss_exempt_req : 1, + obss_exempt_grant : 1, + reserved3 : 1, + reserved2 : 1, + reserved1 : 1; +#endif +} __packed; + +/* + * 20/40 BSS intolerant channel report ie + */ +struct ieee80211_ie_intolerant_report { + u_int8_t elem_id; + u_int8_t elem_len; + u_int8_t reg_class; + u_int8_t chan_list[1]; /* variable-length channel list */ +} __packed; + +/* + * 20/40 coext management action frame + */ +struct ieee80211_action_bss_coex_frame { + struct ieee80211_action ac_header; + struct ieee80211_ie_bss_coex coex; + struct ieee80211_ie_intolerant_report chan_report; +} __packed; + +typedef enum ieee80211_tie_interval_type{ + IEEE80211_TIE_INTERVAL_TYPE_RESERVED = 0, + IEEE80211_TIE_INTERVAL_TYPE_REASSOC_DEADLINE_INTERVAL = 1, + IEEE80211_TIE_INTERVAL_TYPE_KEY_LIFETIME_INTERVAL = 2, + IEEE80211_TIE_INTERVAL_TYPE_ASSOC_COMEBACK_TIME = 3, +}ieee80211_tie_interval_type_t; + +struct ieee80211_ie_timeout_interval { + u_int8_t elem_id; + u_int8_t elem_len; + u_int8_t interval_type; + u_int32_t value; +} __packed; + +//TODO -> Need to Check Redefinition Error used in only UMAC +#if 0 +/* Management MIC information element (IEEE 802.11w) */ +struct ieee80211_mmie { + u_int8_t element_id; + u_int8_t length; + u_int16_t key_id; + u_int8_t sequence_number[6]; + u_int8_t mic[8]; +} __packed; +#endif + +/* VHT capability flags */ +/* B0-B1 Maximum MPDU Length */ +#define IEEE80211_VHTCAP_MAX_MPDU_LEN_3839 0x00000000 /* A-MSDU Length 3839 octets */ +#define IEEE80211_VHTCAP_MAX_MPDU_LEN_7935 0x00000001 /* A-MSDU Length 7991 octets */ +#define IEEE80211_VHTCAP_MAX_MPDU_LEN_11454 0x00000002 /* A-MSDU Length 11454 octets */ + +/* B2-B3 Supported Channel Width */ +#define IEEE80211_VHTCAP_SUP_CHAN_WIDTH_80 0x00000000 /* Does not support 160 or 80+80 */ +#define IEEE80211_VHTCAP_SUP_CHAN_WIDTH_160 0x00000004 /* Supports 160 */ +#define IEEE80211_VHTCAP_SUP_CHAN_WIDTH_80_160 0x00000008 /* Support both 160 or 80+80 */ +#define IEEE80211_VHTCAP_SUP_CHAN_WIDTH_S 2 /* B2-B3 */ + +#define IEEE80211_VHTCAP_RX_LDPC 0x00000010 /* B4 RX LDPC */ +#define IEEE80211_VHTCAP_SHORTGI_80 0x00000020 /* B5 Short GI for 80MHz */ +#define IEEE80211_VHTCAP_SHORTGI_160 0x00000040 /* B6 Short GI for 160 and 80+80 MHz */ +#define IEEE80211_VHTCAP_TX_STBC 0x00000080 /* B7 Tx STBC */ +#define IEEE80211_VHTCAP_TX_STBC_S 7 + +#define IEEE80211_VHTCAP_RX_STBC 0x00000700 /* B8-B10 Rx STBC */ +#define IEEE80211_VHTCAP_RX_STBC_S 8 + +#define IEEE80211_VHTCAP_SU_BFORMER 0x00000800 /* B11 SU Beam former capable */ +#define IEEE80211_VHTCAP_SU_BFORMEE 0x00001000 /* B12 SU Beam formee capable */ +#define IEEE80211_VHTCAP_BF_MAX_ANT 0x0000E000 /* B13-B15 Compressed steering number of + * beacomformer Antennas supported */ +#define IEEE80211_VHTCAP_BF_MAX_ANT_S 13 + +#define IEEE80211_VHTCAP_SOUND_DIMENSIONS 0x00070000 /* B16-B18 Sounding Dimensions */ +#define IEEE80211_VHTCAP_SOUND_DIMENSIONS_S 16 + +#define IEEE80211_VHTCAP_MU_BFORMER 0x00080000 /* B19 MU Beam Former */ +#define IEEE80211_VHTCAP_MU_BFORMEE 0x00100000 /* B20 MU Beam Formee */ +#define IEEE80211_VHTCAP_TXOP_PS 0x00200000 /* B21 VHT TXOP PS */ +#define IEEE80211_VHTCAP_PLUS_HTC_VHT 0x00400000 /* B22 +HTC-VHT capable */ + +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_FACTOR 13 +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_EXP 0x03800000 /* B23-B25 maximum AMPDU Length Exponent */ +#define IEEE80211_VHTCAP_MAX_AMPDU_LEN_EXP_S 23 + +#define IEEE80211_VHTCAP_LINK_ADAPT 0x0C000000 /* B26-B27 VHT Link Adaptation capable */ +#define IEEE80211_VHTCAP_RESERVED 0xF0000000 /* B28-B31 Reserved */ + +/* + * 802.11ac VHT Capability IE + */ +struct ieee80211_ie_vhtcap { + u_int8_t elem_id; + u_int8_t elem_len; + u_int32_t vht_cap_info; + u_int16_t rx_mcs_map; /* B0-B15 Max Rx MCS for each SS */ + u_int16_t rx_high_data_rate; /* B16-B28 Max Rx data rate, + Note: B29-B31 reserved */ + u_int16_t tx_mcs_map; /* B32-B47 Max Tx MCS for each SS */ + u_int16_t tx_high_data_rate; /* B48-B60 Max Tx data rate, + Note: B61-B63 reserved */ +} __packed; + + +/* VHT Operation */ +#define IEEE80211_VHTOP_CHWIDTH_2040 0 /* 20/40 MHz Operating Channel */ +#define IEEE80211_VHTOP_CHWIDTH_80 1 /* 80 MHz Operating Channel */ +#define IEEE80211_VHTOP_CHWIDTH_160 2 /* 160 MHz Operating Channel */ +#define IEEE80211_VHTOP_CHWIDTH_80_80 3 /* 80 + 80 MHz Operating Channel */ + +/* + * 802.11ac VHT Operation IE + */ +struct ieee80211_ie_vhtop { + u_int8_t elem_id; + u_int8_t elem_len; + u_int8_t vht_op_chwidth; /* BSS Operational Channel width */ + u_int8_t vht_op_ch_freq_seg1; /* Channel Center frequency */ + u_int8_t vht_op_ch_freq_seg2; /* Channel Center frequency applicable + * for 80+80MHz mode of operation */ + u_int16_t vhtop_basic_mcs_set; /* Basic MCS set */ +} __packed; + +/* + * 802.11n Secondary Channel Offset element + */ +#define IEEE80211_SEC_CHAN_OFFSET_SCN 0 /* no secondary channel */ +#define IEEE80211_SEC_CHAN_OFFSET_SCA 1 /* secondary channel above */ +#define IEEE80211_SEC_CHAN_OFFSET_SCB 3 /* secondary channel below */ + +struct ieee80211_ie_sec_chan_offset { + u_int8_t elem_id; + u_int8_t len; + u_int8_t sec_chan_offset; +} __packed; + +/* + * 802.11ac Transmit Power Envelope element + */ +#define IEEE80211_VHT_TXPWR_IS_SUB_ELEMENT 1 /* It checks whether its sub element */ +#define IEEE80211_VHT_TXPWR_MAX_POWER_COUNT 4 /* Max TX power elements valid */ +#define IEEE80211_VHT_TXPWR_NUM_POWER_SUPPORTED 3 /* Max TX power elements supported */ +#define IEEE80211_VHT_TXPWR_LCL_MAX_PWR_UNITS_SHFT 3 /* B3-B5 Local Max transmit power units */ + +struct ieee80211_ie_vht_txpwr_env { + u_int8_t elem_id; + u_int8_t elem_len; + u_int8_t txpwr_info; /* Transmit Power Information */ + u_int8_t local_max_txpwr[4]; /* Local Max TxPower for 20,40,80,160MHz */ +} __packed; + +/* + * 802.11ac Wide Bandwidth Channel Switch Element + */ + +#define IEEE80211_VHT_EXTCH_SWITCH 1 /* For extension channel switch */ +#define CHWIDTH_VHT20 20 /* Channel width 20 */ +#define CHWIDTH_VHT40 40 /* Channel width 40 */ +#define CHWIDTH_VHT80 80 /* Channel width 80 */ +#define CHWIDTH_VHT160 160 /* Channel width 160 */ + +struct ieee80211_ie_wide_bw_switch { + u_int8_t elem_id; + u_int8_t elem_len; + u_int8_t new_ch_width; /* New channel width */ + u_int8_t new_ch_freq_seg1; /* Channel Center frequency 1 */ + u_int8_t new_ch_freq_seg2; /* Channel Center frequency 2 */ +} __packed; + +#define IEEE80211_RSSI_RX 0x00000001 +#define IEEE80211_RSSI_TX 0x00000002 +#define IEEE80211_RSSI_EXTCHAN 0x00000004 +#define IEEE80211_RSSI_BEACON 0x00000008 +#define IEEE80211_RSSI_RXDATA 0x00000010 + +#define IEEE80211_RATE_TX 0 +#define IEEE80211_RATE_RX 1 +#define IEEE80211_LASTRATE_TX 2 +#define IEEE80211_LASTRATE_RX 3 +#define IEEE80211_RATECODE_TX 4 +#define IEEE80211_RATECODE_RX 5 + +#define IEEE80211_MAX_RATE_PER_CLIENT 8 +/* Define for the P2P Wildcard SSID */ +#define IEEE80211_P2P_WILDCARD_SSID "DIRECT-" + +#define IEEE80211_P2P_WILDCARD_SSID_LEN (sizeof(IEEE80211_P2P_WILDCARD_SSID) - 1) + +#endif /* _COMMON_IEEE80211_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_defines.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_defines.h new file mode 100644 index 000000000000..039718acb24f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ieee80211_defines.h @@ -0,0 +1,1381 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +#ifndef _IEEE80211_DEFINES_H_ +#define _IEEE80211_DEFINES_H_ + +#include "ieee80211_common.h" +#ifndef EXTERNAL_USE_ONLY +#include "_ieee80211_common.h" /* IEEE80211_ADDR_LEN, iee80211_phymode */ +#endif + +/* + * Public defines for Atheros Upper MAC Layer + */ + +/** + * @brief Opaque handle of 802.11 protocal layer. + */ +struct ieee80211com; +typedef struct ieee80211com *wlan_dev_t; + +/** + * @brief Opaque handle to App IE module. +*/ +struct wlan_mlme_app_ie; +typedef struct wlan_mlme_app_ie *wlan_mlme_app_ie_t; + +/** + * @brief Opaque handle of network instance (vap) in 802.11 protocal layer. +*/ +struct ieee80211vap; +typedef struct ieee80211vap *wlan_if_t; + +struct ieee80211vapprofile; +typedef struct ieee80211vapprofile *wlan_if_info_t; + +/** + * @brief Opaque handle of a node in the wifi network. + */ +struct ieee80211_node; +typedef struct ieee80211_node *wlan_node_t; + +/** + * @brief Opaque handle of OS interface (ifp in the case of unix ). + */ +struct _os_if_t; +typedef struct _os_if_t *os_if_t; + +/** + * + * @brief Opaque handle. + */ +typedef void *os_handle_t; + +/** + * @brief Opaque handle of a channel. + */ +struct ieee80211_channel; +typedef struct ieee80211_channel *wlan_chan_t; + +/** + * @brief Opaque handle scan_entry. + */ +struct ieee80211_scan_entry; +typedef struct ieee80211_scan_entry *wlan_scan_entry_t; + +/* AoW related defines */ +#define AOW_MAX_RECEIVER_COUNT 10 + + + +#define IEEE80211_NWID_LEN 32 +#define IEEE80211_ISO_COUNTRY_LENGTH 3 /* length of 11d ISO country string */ + +typedef struct _ieee80211_ssid { + int len; + u_int8_t ssid[IEEE80211_NWID_LEN]; +} ieee80211_ssid; + +typedef struct ieee80211_tx_status { + int ts_flags; +#define IEEE80211_TX_ERROR 0x01 +#define IEEE80211_TX_XRETRY 0x02 + + int ts_retries; /* number of retries to successfully transmit this frame */ +#ifdef ATH_SUPPORT_TxBF + u_int8_t ts_txbfstatus; +#define AR_BW_Mismatch 0x1 +#define AR_Stream_Miss 0x2 +#define AR_CV_Missed 0x4 +#define AR_Dest_Miss 0x8 +#define AR_Expired 0x10 +#define AR_TxBF_Valid_HW_Status (AR_BW_Mismatch|AR_Stream_Miss|AR_CV_Missed|AR_Dest_Miss|AR_Expired) +#define TxBF_STATUS_Sounding_Complete 0x20 +#define TxBF_STATUS_Sounding_Request 0x40 +#define TxBF_Valid_SW_Status (TxBF_STATUS_Sounding_Complete | TxBF_STATUS_Sounding_Request) +#define TxBF_Valid_Status (AR_TxBF_Valid_HW_Status | TxBF_Valid_SW_Status) + u_int32_t ts_tstamp; /* tx time stamp */ +#endif +#ifdef ATH_SUPPORT_FLOWMAC_MODULE + u_int8_t ts_flowmac_flags; +#define IEEE80211_TX_FLOWMAC_DONE 0x01 +#endif + u_int32_t ts_rateKbps; +} ieee80211_xmit_status; + +#ifndef EXTERNAL_USE_ONLY +typedef struct ieee80211_rx_status { + int rs_numchains; + int rs_flags; +#define IEEE80211_RX_FCS_ERROR 0x01 +#define IEEE80211_RX_MIC_ERROR 0x02 +#define IEEE80211_RX_DECRYPT_ERROR 0x04 +/* holes in flags here between, ATH_RX_XXXX to IEEE80211_RX_XXX */ +#define IEEE80211_RX_KEYMISS 0x200 + int rs_rssi; /* RSSI (noise floor ajusted) */ + int rs_abs_rssi; /* absolute RSSI */ + int rs_datarate; /* data rate received */ + int rs_rateieee; + int rs_ratephy; + +#define IEEE80211_MAX_ANTENNA 3 /* Keep the same as ATH_MAX_ANTENNA */ + u_int8_t rs_rssictl[IEEE80211_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ + u_int8_t rs_rssiextn[IEEE80211_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ + u_int8_t rs_isvalidrssi; /* rs_rssi is valid or not */ + + enum ieee80211_phymode rs_phymode; + int rs_freq; + + union { + u_int8_t data[8]; + u_int64_t tsf; + } rs_tstamp; + + /* + * Detail channel structure of recv frame. + * It could be NULL if not available + */ + struct ieee80211_channel *rs_full_chan; + + u_int8_t rs_isaggr; + u_int8_t rs_isapsd; + int16_t rs_noisefloor; + u_int16_t rs_channel; +#ifdef ATH_SUPPORT_TxBF + u_int32_t rs_rpttstamp; /* txbf report time stamp*/ +#endif + + /* The following counts are meant to assist in stats calculation. + These variables are incremented only in specific situations, and + should not be relied upon for any purpose other than the original + stats related purpose they have been introduced for. */ + + u_int16_t rs_cryptodecapcount; /* Crypto bytes decapped/demic'ed. */ + u_int8_t rs_padspace; /* No. of padding bytes present after header + in wbuf. */ + u_int8_t rs_qosdecapcount; /* QoS/HTC bytes decapped. */ + + /* End of stats calculation related counts. */ + + uint8_t rs_lsig[IEEE80211_LSIG_LEN]; + uint8_t rs_htsig[IEEE80211_HTSIG_LEN]; + uint8_t rs_servicebytes[IEEE80211_SB_LEN]; + +} ieee80211_recv_status; +#endif /* EXTERNAL_USE_ONLY */ + +/* + * flags to be passed to ieee80211_vap_create function . + */ +#define IEEE80211_CLONE_BSSID 0x0001 /* allocate unique mac/bssid */ +#define IEEE80211_CLONE_NOBEACONS 0x0002 /* don't setup beacon timers */ +#define IEEE80211_CLONE_WDS 0x0004 /* enable WDS processing */ +#define IEEE80211_CLONE_WDSLEGACY 0x0008 /* legacy WDS operation */ +#define IEEE80211_PRIMARY_VAP 0x0010 /* primary vap */ +#define IEEE80211_P2PDEV_VAP 0x0020 /* p2pdev vap */ +#define IEEE80211_P2PGO_VAP 0x0040 /* p2p-go vap */ +#define IEEE80211_P2PCLI_VAP 0x0080 /* p2p-client vap */ +#define IEEE80211_CLONE_MACADDR 0x0100 /* create vap w/ specified mac/bssid */ +#define IEEE80211_CLONE_MATADDR 0x0200 /* create vap w/ specified MAT addr */ +#define IEEE80211_WRAP_VAP 0x0400 /* wireless repeater ap vap */ + +/* + * For the new multi-vap scan feature, there is a set of default priority tables + * for each OpMode. + * The following are the default list of the VAP Scan Priority Mapping based on OpModes. + * NOTE: the following are only used when "#if ATH_SUPPORT_MULTIPLE_SCANS" is true. + */ +/* For IBSS opmode */ +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_IBSS_BASE 0 +/* For STA opmode */ +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_STA_BASE 0 +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_STA_P2P_CLIENT 1 +/* For HostAp opmode */ +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_AP_BASE 0 +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_AP_P2P_GO 1 +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_AP_P2P_DEVICE 2 +/* For BTAmp opmode */ +#define DEF_VAP_SCAN_PRI_MAP_OPMODE_BTAMP_BASE 0 + +typedef enum _ieee80211_dev_vap_event { + IEEE80211_VAP_CREATED = 1, + IEEE80211_VAP_STOPPED, + IEEE80211_VAP_DELETED +} ieee80211_dev_vap_event; + +typedef struct _wlan_dev_event_handler_table { + void (*wlan_dev_vap_event) (void *event_arg, wlan_dev_t, os_if_t, ieee80211_dev_vap_event); /* callback to receive vap events*/ +#ifdef ATH_SUPPORT_SPECTRAL + void (*wlan_dev_spectral_indicate)(void*, void*, u_int32_t); +#endif +} wlan_dev_event_handler_table; + +typedef enum _ieee80211_ap_stopped_reason { + IEEE80211_AP_STOPPED_REASON_DUMMY = 0, /* Dummy placeholder. Should not use */ + IEEE80211_AP_STOPPED_REASON_CHANNEL_DFS = 1, +} ieee80211_ap_stopped_reason; + +typedef int IEEE80211_REASON_CODE; +typedef int IEEE80211_STATUS; + +/* + * scan API related structs. + */ +typedef enum _ieee80211_scan_type { + IEEE80211_SCAN_BACKGROUND, + IEEE80211_SCAN_FOREGROUND, + IEEE80211_SCAN_SPECTRAL, + IEEE80211_SCAN_REPEATER_BACKGROUND, + IEEE80211_SCAN_REPEATER_EXT_BACKGROUND, + IEEE80211_SCAN_RADIO_MEASUREMENTS, +} ieee80211_scan_type; + +/* + * Priority numbers must be sequential, starting with 0. + */ +typedef enum ieee80211_scan_priority_t { + IEEE80211_SCAN_PRIORITY_VERY_LOW = 0, + IEEE80211_SCAN_PRIORITY_LOW, + IEEE80211_SCAN_PRIORITY_MEDIUM, + IEEE80211_SCAN_PRIORITY_HIGH, + IEEE80211_SCAN_PRIORITY_VERY_HIGH, + + IEEE80211_SCAN_PRIORITY_COUNT /* number of priorities supported */ +} IEEE80211_SCAN_PRIORITY; + +typedef u_int16_t IEEE80211_SCAN_REQUESTOR; +typedef u_int32_t IEEE80211_SCAN_ID; + +#define IEEE80211_SCAN_ID_NONE 0 + +/* All P2P scans currently use medium priority */ +#define IEEE80211_P2P_DEFAULT_SCAN_PRIORITY IEEE80211_SCAN_PRIORITY_MEDIUM +#define IEEE80211_P2P_SCAN_PRIORITY_HIGH IEEE80211_SCAN_PRIORITY_HIGH + +/* Masks identifying types/ID of scans */ +#define IEEE80211_SPECIFIC_SCAN 0x00000000 +#define IEEE80211_VAP_SCAN 0x01000000 +#define IEEE80211_ALL_SCANS 0x04000000 + +/** + * host scan bit. only relevant for host/target architecture. + * do not reuse this bit definition. target uses this . + * + */ +#define IEEE80211_HOST_SCAN 0x80000000 +#define IEEE80211_SCAN_CLASS_MASK 0xFF000000 + +#define IEEE80211_SCAN_PASSIVE 0x0001 /* passively scan all the channels */ +#define IEEE80211_SCAN_ACTIVE 0x0002 /* actively scan all the channels (regdomain rules still apply) */ +#define IEEE80211_SCAN_2GHZ 0x0004 /* scan 2GHz band */ +#define IEEE80211_SCAN_5GHZ 0x0008 /* scan 5GHz band */ +#define IEEE80211_SCAN_ALLBANDS (IEEE80211_SCAN_5GHZ | IEEE80211_SCAN_2GHZ) +#define IEEE80211_SCAN_CONTINUOUS 0x0010 /* keep scanning until maxscantime expires */ +#define IEEE80211_SCAN_FORCED 0x0020 /* forced scan (OS request) - should proceed even in the presence of data traffic */ +#define IEEE80211_SCAN_NOW 0x0040 /* scan now (User request) - should proceed even in the presence of data traffic */ +#define IEEE80211_SCAN_ADD_BCAST_PROBE 0x0080 /* add wildcard ssid and broadcast probe request if there is none */ +#define IEEE80211_SCAN_EXTERNAL 0x0100 /* scan requested by OS */ +#define IEEE80211_SCAN_BURST 0x0200 /* scan multiple channels before returning to BSS channel */ +#define IEEE80211_SCAN_CHAN_EVENT 0x0400 /* scan chan event for offload architectures */ +#define IEEE80211_SCAN_FILTER_PROBE_REQ 0x0800 /* Filter probe requests- applicable only for offload architectures*/ + +#define IEEE80211_SCAN_PARAMS_MAX_SSID 10 +#define IEEE80211_SCAN_PARAMS_MAX_BSSID 10 + + +/* flag definitions passed to scan_cancel API */ + +#define IEEE80211_SCAN_CANCEL_ASYNC 0x0 /* asynchronouly wait for scan SM to complete cancel */ +#define IEEE80211_SCAN_CANCEL_WAIT 0x1 /* wait for scan SM to complete cancel */ +#define IEEE80211_SCAN_CANCEL_SYNC 0x2 /* synchronously execute cancel scan */ + +#ifndef EXTERNAL_USE_ONLY +typedef bool (*ieee80211_scan_termination_check) (void *arg); + +typedef struct _ieee80211_scan_params { + ieee80211_scan_type type; + int min_dwell_time_active; /* min time in msec on active channels */ + int max_dwell_time_active; /* max time in msec on active channels (if no response) */ + int min_dwell_time_passive; /* min time in msec on passive channels */ + int max_dwell_time_passive; /* max time in msec on passive channels (if no response) */ + int min_rest_time; /* min time in msec on the BSS channel, only valid for BG scan */ + int max_rest_time; /* max time in msec on the BSS channel, only valid for BG scan */ + int max_offchannel_time; /* max time away from BSS channel, in ms */ + int repeat_probe_time; /* time before sending second probe request */ + int idle_time; /* time in msec on bss channel before switching channel */ + int max_scan_time; /* maximum time in msec allowed for scan */ + int probe_delay; /* delay in msec before sending probe request */ + int offchan_retry_delay; /* delay in msec before retrying off-channel switch */ + int min_beacon_count; /* number of home AP beacons to receive before leaving the home channel */ + int max_offchan_retries; /* maximum number of times to retry off-channel switch */ + int beacon_timeout; /* maximum time to wait for beacons */ + int flags; /* scan flags */ + int num_channels; /* number of channels to scan */ + bool multiple_ports_active; /* driver has multiple ports active in the home channel */ + bool restricted_scan; /* Perform restricted scan */ + bool chan_list_allocated; + IEEE80211_SCAN_PRIORITY p2p_scan_priority; /* indicates the scan priority if this is a P2P-related scan */ + u_int32_t *chan_list; /* array of ieee channels (or) frequencies to scan */ + int num_ssid; /* number of desired ssids */ + ieee80211_ssid ssid_list[IEEE80211_SCAN_PARAMS_MAX_SSID]; + int num_bssid; /* number of desired bssids */ + u_int8_t bssid_list[IEEE80211_SCAN_PARAMS_MAX_BSSID][IEEE80211_ADDR_LEN]; + struct ieee80211_node *bss_node; /* BSS node */ + int ie_len; /* length of the ie data to be added to probe req */ + u_int8_t *ie_data; /* pointer to ie data */ + ieee80211_scan_termination_check check_termination_function; /* function checking for termination condition */ + void *check_termination_context; /* context passed to function above */ +} ieee80211_scan_params; + +/* Data types used to specify scan priorities */ +typedef u_int32_t IEEE80211_PRIORITY_MAPPING[IEEE80211_SCAN_PRIORITY_COUNT]; + +/************************************** + * Called before attempting to roam. Modifies the rssiAdder of a BSS + * based on the preferred status of a BSS. + * + * According to CCX spec, AP in the neighbor list is not meant for giving extra + * weightage in roaming. By doing so, roaming becomes sticky. See bug 21220. + * Change the weightage to 0. Cisco may ask in future for a user control of + * this weightage. + */ +#define PREFERRED_BSS_RANK 20 +#define NEIGHBOR_BSS_RANK 0 /* must be less than preferred BSS rank */ + +/* + * The utility of the BSS is the metric used in the selection + * of a BSS. The Utility of the BSS is reduced if we just left the BSS. + * The Utility of the BSS is not reduced if we have left the + * BSS for 8 seconds (8000ms) or more. + * 2^13 milliseconds is a close approximation to avoid expensive division + */ +#define LAST_ASSOC_TIME_DELTA_REQUIREMENT (1 << 13) // 8192 + +#define QBSS_SCALE_MAX 255 /* Qbss channel load Max value */ +#define QBSS_SCALE_DOWN_FACTOR 2 /* scale factor to reduce Qbss channel load */ +#define QBSS_HYST_ADJ 60 /* Qbss Weightage factor for the current AP */ + +/* + * Flags used to set field APState + */ +#define AP_STATE_GOOD 0x00 +#define AP_STATE_BAD 0x01 +#define AP_STATE_RETRY 0x10 +#define BAD_AP_TIMEOUT 6000 // In milli seconds +/* + * To disable BAD_AP status check on any scan entry + */ +#define BAD_AP_TIMEOUT_DISABLED 0 + +/* + * BAD_AP timeout specified in seconds + */ +#define BAD_AP_TIMEOUT_IN_SECONDS 10 + +/* + * State values used to represent our assoc_state with ap (discrete, not bitmasks) + */ +#define AP_ASSOC_STATE_NONE 0 +#define AP_ASSOC_STATE_AUTH 1 +#define AP_ASSOC_STATE_ASSOC 2 + +/* + * Entries in the scan list are considered obsolete after 75 seconds. + */ +#define IEEE80211_SCAN_ENTRY_EXPIRE_TIME 75000 + +/* + * idle time is only valid for scan type IEEE80211_SCAN_BACKGROUND. + * if idle time is set then the scanner would change channel from BSS + * channel to foreign channel only if both resttime is expired and + * the theres was not traffic for idletime msec on the bss channel. + * value of 0 for idletime would cause the channel to switch from BSS + * channel to foreign channel as soon as the resttime is expired. + * + * if maxscantime is nonzero and if the scanner can not complete the + * scan in maxscantime msec then the scanner will cancel the scan and + * post IEEE80211_SCAN_COMPLETED event with reason SCAN_TIMEDOUT. + * + */ + +/* + * chanlist can be either ieee channels (or) frequencies. + * if a value is less than 1000 implementation assumes it + * as ieee channel # otherwise implementation assumes it + * as frequency in Mhz. + */ + +typedef enum _ieee80211_scan_event_type { + IEEE80211_SCAN_STARTED, + IEEE80211_SCAN_COMPLETED, + IEEE80211_SCAN_RADIO_MEASUREMENT_START, + IEEE80211_SCAN_RADIO_MEASUREMENT_END, + IEEE80211_SCAN_RESTARTED, + IEEE80211_SCAN_HOME_CHANNEL, + IEEE80211_SCAN_FOREIGN_CHANNEL, + IEEE80211_SCAN_BSSID_MATCH, + IEEE80211_SCAN_FOREIGN_CHANNEL_GET_NF, + IEEE80211_SCAN_DEQUEUED, + IEEE80211_SCAN_PREEMPTED, + + IEEE80211_SCAN_EVENT_COUNT +} ieee80211_scan_event_type; + +typedef enum ieee80211_scan_completion_reason { + IEEE80211_REASON_NONE, + IEEE80211_REASON_COMPLETED, + IEEE80211_REASON_CANCELLED, + IEEE80211_REASON_TIMEDOUT, + IEEE80211_REASON_TERMINATION_FUNCTION, + IEEE80211_REASON_MAX_OFFCHAN_RETRIES, + IEEE80211_REASON_PREEMPTED, + IEEE80211_REASON_RUN_FAILED, + IEEE80211_REASON_INTERNAL_STOP, + + IEEE80211_REASON_COUNT +} ieee80211_scan_completion_reason; + +typedef struct _ieee80211_scan_event { + ieee80211_scan_event_type type; + ieee80211_scan_completion_reason reason; + wlan_chan_t chan; + IEEE80211_SCAN_REQUESTOR requestor; /* Requestor ID passed to the scan_start function */ + IEEE80211_SCAN_ID scan_id; /* Specific ID of the scan reporting the event */ +} ieee80211_scan_event; + +typedef enum _ieee80211_scan_request_status { + IEEE80211_SCAN_STATUS_QUEUED, + IEEE80211_SCAN_STATUS_RUNNING, + IEEE80211_SCAN_STATUS_PREEMPTED, + IEEE80211_SCAN_STATUS_COMPLETED +} ieee80211_scan_request_status; + +/* + * the sentry field of tht ieee80211_scan_event is only valid if the + * event type is IEEE80211_SCAN_BSSID_MATCH. + */ + +typedef void (*ieee80211_scan_event_handler) (wlan_if_t vaphandle, ieee80211_scan_event *event, void *arg); + +typedef struct _ieee80211_scan_info { + ieee80211_scan_type type; + IEEE80211_SCAN_REQUESTOR requestor; /* Originator ID passed to the scan_start function */ + IEEE80211_SCAN_ID scan_id; /* Specific ID of the scan reporting the event */ + IEEE80211_SCAN_PRIORITY priority; /* Requested priority level (low/medium/high) */ + ieee80211_scan_request_status scheduling_status; /* Queued/running/preempted/completed */ + int min_dwell_time_active; /* min time in msec on active channels */ + int max_dwell_time_active; /* max time in msec on active channel (if no response) */ + int min_dwell_time_passive; /* min time in msec on passive channels */ + int max_dwell_time_passive; /* max time in msec on passive channel*/ + int min_rest_time; /* min time in msec on the BSS channel, only valid for BG scan */ + int max_rest_time; /* max time in msec on the BSS channel, only valid for BG scan */ + int max_offchannel_time; /* max time away from BSS channel, in ms */ + int repeat_probe_time; /* time before sending second probe request */ + int min_beacon_count; /* number of home AP beacons to receive before leaving the home channel */ + int flags; /* scan flags */ + systime_t scan_start_time; /* system time when last scani started */ + int scanned_channels; /* number of scanned channels */ + int default_channel_list_length; /* number of channels in the default channel list */ + int channel_list_length; /* number of channels in the channel list used for the current scan */ + u_int8_t in_progress : 1, /* if the scan is in progress */ + cancelled : 1, /* if the scan is cancelled */ + preempted : 1, /* if the scan is preempted */ + restricted : 1; /* if the scan is restricted */ +} ieee80211_scan_info; + +typedef struct _ieee80211_scan_request_info { + wlan_if_t vaphandle; + IEEE80211_SCAN_REQUESTOR requestor; + IEEE80211_SCAN_PRIORITY requested_priority; + IEEE80211_SCAN_PRIORITY absolute_priority; + IEEE80211_SCAN_ID scan_id; + ieee80211_scan_request_status scheduling_status; + ieee80211_scan_params params; + systime_t request_timestamp; + u_int32_t maximum_duration; +} ieee80211_scan_request_info; + +#endif /* EXTERNAL_USE_ONLY */ + +#ifndef EXTERNAL_USE_ONLY +typedef void (*ieee80211_acs_event_handler) (void *arg, wlan_chan_t channel); +#endif /* EXTERNAL_USE_ONLY */ + +#define MAX_CHAINS 3 + +typedef struct _wlan_rssi_info { + int8_t avg_rssi; /* average rssi */ + u_int8_t valid_mask; /* bitmap of valid elements in rssi_ctrl/ext array */ + int8_t rssi_ctrl[MAX_CHAINS]; + int8_t rssi_ext[MAX_CHAINS]; +} wlan_rssi_info; + +typedef enum _wlan_rssi_type { + WLAN_RSSI_TX, + WLAN_RSSI_RX, + WLAN_RSSI_BEACON, /* rssi of the beacon, only valid for STA/IBSS vap */ + WLAN_RSSI_RX_DATA +} wlan_rssi_type; + +typedef enum _ieee80211_rate_type { + IEEE80211_RATE_TYPE_LEGACY, + IEEE80211_RATE_TYPE_MCS, +} ieee80211_rate_type; + +typedef struct _ieee80211_rate_info { + ieee80211_rate_type type; + u_int32_t rate; /* average rate in kbps */ + u_int32_t lastrate; /* last packet rate in kbps */ + u_int8_t mcs; /* mcs index . is valid if rate type is MCS20 or MCS40 */ + u_int8_t maxrate_per_client; +} ieee80211_rate_info; + +typedef enum _ieee80211_node_param_type { + IEEE80211_NODE_PARAM_TX_POWER, + IEEE80211_NODE_PARAM_ASSOCID, + IEEE80211_NODE_PARAM_INACT, /* inactivity timer value */ + IEEE80211_NODE_PARAM_AUTH_MODE, /* auth mode */ + IEEE80211_NODE_PARAM_CAP_INFO, /* auth mode */ +} ieee80211_node_param_type; + +/* + * Per/node (station) statistics available when operating as an AP. + */ +struct ieee80211_nodestats { + u_int32_t ns_rx_data; /* rx data frames */ + u_int32_t ns_rx_mgmt; /* rx management frames */ + u_int32_t ns_rx_ctrl; /* rx control frames */ + u_int32_t ns_rx_ucast; /* rx unicast frames */ + u_int32_t ns_rx_mcast; /* rx multi/broadcast frames */ + u_int64_t ns_rx_bytes; /* rx data count (bytes) */ + u_int64_t ns_rx_beacons; /* rx beacon frames */ + u_int32_t ns_rx_proberesp; /* rx probe response frames */ + + u_int32_t ns_rx_dup; /* rx discard 'cuz dup */ + u_int32_t ns_rx_noprivacy; /* rx w/ wep but privacy off */ + u_int32_t ns_rx_wepfail; /* rx wep processing failed */ + u_int32_t ns_rx_demicfail; /* rx demic failed */ + + /* We log MIC and decryption failures against Transmitter STA stats. + Though the frames may not actually be sent by STAs corresponding + to TA, the stats are still valuable for some customers as a sort + of rough indication. + Also note that the mapping from TA to STA may fail sometimes. */ + u_int32_t ns_rx_tkipmic; /* rx TKIP MIC failure */ + u_int32_t ns_rx_ccmpmic; /* rx CCMP MIC failure */ + u_int32_t ns_rx_wpimic; /* rx WAPI MIC failure */ + u_int32_t ns_rx_tkipicv; /* rx ICV check failed (TKIP) */ + u_int32_t ns_rx_decap; /* rx decapsulation failed */ + u_int32_t ns_rx_defrag; /* rx defragmentation failed */ + u_int32_t ns_rx_disassoc; /* rx disassociation */ + u_int32_t ns_rx_deauth; /* rx deauthentication */ + u_int32_t ns_rx_action; /* rx action */ + u_int32_t ns_rx_decryptcrc; /* rx decrypt failed on crc */ + u_int32_t ns_rx_unauth; /* rx on unauthorized port */ + u_int32_t ns_rx_unencrypted; /* rx unecrypted w/ privacy */ + + u_int32_t ns_tx_data; /* tx data frames */ + u_int32_t ns_tx_data_success; /* tx data frames successfully + transmitted (unicast only) */ + u_int32_t ns_tx_mgmt; /* tx management frames */ + u_int32_t ns_tx_ucast; /* tx unicast frames */ + u_int32_t ns_tx_mcast; /* tx multi/broadcast frames */ + u_int64_t ns_tx_bytes; /* tx data count (bytes) */ + u_int64_t ns_tx_bytes_success; /* tx success data count - unicast only + (bytes) */ + u_int32_t ns_tx_probereq; /* tx probe request frames */ + u_int32_t ns_tx_uapsd; /* tx on uapsd queue */ + u_int32_t ns_tx_discard; /* tx dropped by NIC */ + + u_int32_t ns_tx_novlantag; /* tx discard 'cuz no tag */ + u_int32_t ns_tx_vlanmismatch; /* tx discard 'cuz bad tag */ + + u_int32_t ns_tx_eosplost; /* uapsd EOSP retried out */ + + u_int32_t ns_ps_discard; /* ps discard 'cuz of age */ + + u_int32_t ns_uapsd_triggers; /* uapsd triggers */ + u_int32_t ns_uapsd_duptriggers; /* uapsd duplicate triggers */ + u_int32_t ns_uapsd_ignoretriggers; /* uapsd duplicate triggers */ + u_int32_t ns_uapsd_active; /* uapsd duplicate triggers */ + u_int32_t ns_uapsd_triggerenabled; /* uapsd duplicate triggers */ + + + /* MIB-related state */ + u_int32_t ns_tx_assoc; /* [re]associations */ + u_int32_t ns_tx_assoc_fail; /* [re]association failures */ + u_int32_t ns_tx_auth; /* [re]authentications */ + u_int32_t ns_tx_auth_fail; /* [re]authentication failures*/ + u_int32_t ns_tx_deauth; /* deauthentications */ + u_int32_t ns_tx_deauth_code; /* last deauth reason */ + u_int32_t ns_tx_disassoc; /* disassociations */ + u_int32_t ns_tx_disassoc_code; /* last disassociation reason */ + u_int32_t ns_psq_drops; /* power save queue drops */ +}; + +/* + * station power save mode. + */ +typedef enum ieee80211_psmode { + IEEE80211_PWRSAVE_NONE = 0, /* no power save */ + IEEE80211_PWRSAVE_LOW, + IEEE80211_PWRSAVE_NORMAL, + IEEE80211_PWRSAVE_MAXIMUM, + IEEE80211_PWRSAVE_WNM /* WNM-Sleep Mode */ +} ieee80211_pwrsave_mode; + +/* station power save pspoll handling */ +typedef enum { + IEEE80211_CONTINUE_PSPOLL_FOR_MORE_DATA, + IEEE80211_WAKEUP_FOR_MORE_DATA, +} ieee80211_pspoll_moredata_handling; + +/* + * apps power save state. + */ +typedef enum { + APPS_AWAKE = 0, + APPS_PENDING_SLEEP, + APPS_SLEEP, + APPS_FAKE_SLEEP, /* Pending blocking sleep */ + APPS_FAKING_SLEEP, /* Blocking sleep */ + APPS_UNKNOWN_PWRSAVE, +} ieee80211_apps_pwrsave_state; + +typedef enum _iee80211_mimo_powersave_mode { + IEEE80211_MIMO_POWERSAVE_NONE, /* no mimo power save */ + IEEE80211_MIMO_POWERSAVE_STATIC, /* static mimo power save */ + IEEE80211_MIMO_POWERSAVE_DYNAMIC /* dynamic mimo powersave */ +} ieee80211_mimo_powersave_mode; + +#ifdef ATH_COALESCING +typedef enum _ieee80211_coalescing_state { + IEEE80211_COALESCING_DISABLED = 0, /* Coalescing is disabled*/ + IEEE80211_COALESCING_DYNAMIC = 1, /* Dynamically move to Enabled state based on Uruns*/ + IEEE80211_COALESCING_ENABLED = 2, /* Coalescing is enabled*/ +} ieee80211_coalescing_state; + +#define IEEE80211_TX_COALESCING_THRESHOLD 5 /* Number of underrun errors to trigger coalescing */ +#endif + +typedef enum _ieee80211_cap { + IEEE80211_CAP_SHSLOT, /* CAPABILITY: short slot */ + IEEE80211_CAP_SHPREAMBLE, /* CAPABILITY: short premable */ + IEEE80211_CAP_MULTI_DOMAIN, /* CAPABILITY: multiple domain */ + IEEE80211_CAP_WMM, /* CAPABILITY: WMM */ + IEEE80211_CAP_HT, /* CAPABILITY: HT */ + IEEE80211_CAP_PERF_PWR_OFLD, /* CAPABILITY: power performance offload support */ + IEEE80211_CAP_11AC, /* CAPABILITY: 11ac support */ +} ieee80211_cap; + +typedef enum _ieee80211_device_param { + IEEE80211_DEVICE_RSSI_CTL, + IEEE80211_DEVICE_NUM_TX_CHAIN, + IEEE80211_DEVICE_NUM_RX_CHAIN, + IEEE80211_DEVICE_TX_CHAIN_MASK, + IEEE80211_DEVICE_RX_CHAIN_MASK, + IEEE80211_DEVICE_TX_CHAIN_MASK_LEGACY, + IEEE80211_DEVICE_RX_CHAIN_MASK_LEGACY, + IEEE80211_DEVICE_BMISS_LIMIT, /* # of beacon misses for HW to generate BMISS intr */ + IEEE80211_DEVICE_PROTECTION_MODE, /* protection mode*/ + IEEE80211_DEVICE_BLKDFSCHAN, /* block the use of DFS channels */ + IEEE80211_DEVICE_GREEN_AP_PS_ENABLE, + IEEE80211_DEVICE_GREEN_AP_PS_TIMEOUT, + IEEE80211_DEVICE_GREEN_AP_PS_ON_TIME, + IEEE80211_DEVICE_CWM_EXTPROTMODE, + IEEE80211_DEVICE_CWM_EXTPROTSPACING, + IEEE80211_DEVICE_CWM_ENABLE, + IEEE80211_DEVICE_CWM_EXTBUSYTHRESHOLD, + IEEE80211_DEVICE_DOTH, + IEEE80211_DEVICE_ADDBA_MODE, + IEEE80211_DEVICE_COUNTRYCODE, + IEEE80211_DEVICE_MULTI_CHANNEL, /* turn on/off off channel support */ + IEEE80211_DEVICE_MAX_AMSDU_SIZE, /* Size of AMSDU to be sent on the air */ + IEEE80211_DEVICE_P2P, /* Enable or Disable P2P */ + IEEE80211_DEVICE_OVERRIDE_SCAN_PROBERESPONSE_IE, /* Override scan Probe response IE, 0: Don't over-ride */ + IEEE80211_DEVICE_2G_CSA, + IEEE80211_DEVICE_PWRTARGET, + IEEE80211_DEVICE_OFF_CHANNEL_SUPPORT, +} ieee80211_device_param; + +typedef enum _ieee80211_param { + IEEE80211_BEACON_INTVAL, /* in TUs */ + IEEE80211_LISTEN_INTVAL, /* number of beacons */ + IEEE80211_DTIM_INTVAL, /* number of beacons */ + IEEE80211_BMISS_COUNT_RESET, /* number of beacon miss intrs before reset */ + IEEE80211_BMISS_COUNT_MAX, /* number of beacon miss intrs for bmiss notificationst */ + IEEE80211_ATIM_WINDOW, /* ATIM window */ + IEEE80211_SHORT_SLOT, /* short slot on/off */ + IEEE80211_SHORT_PREAMBLE, /* short preamble on/off */ + IEEE80211_RTS_THRESHOLD, /* rts threshold, 0 means no rts threshold */ + IEEE80211_FRAG_THRESHOLD, /* fragmentation threshold, 0 means no rts threshold */ + IEEE80211_FIXED_RATE, /* + * rate code series(0: auto rate, 32 bit value: rate + * codes for 4 rate series. each byte for one rate series) + */ + IEEE80211_MCAST_RATE, /* rate in Kbps */ + IEEE80211_TXPOWER, /* in 0.5db units */ + IEEE80211_AMPDU_DENCITY, /* AMPDU dencity*/ + IEEE80211_AMPDU_LIMIT, /* AMPDU limit*/ + IEEE80211_MAX_AMPDU, /* Max AMPDU Exp*/ + IEEE80211_VHT_MAX_AMPDU, /* VHT Max AMPDU Exp */ + IEEE80211_WPS_MODE, /* WPS mode*/ + IEEE80211_TSN_MODE, /* TSN mode*/ + IEEE80211_MULTI_DOMAIN, /* Multiple domain */ + IEEE80211_SAFE_MODE, /* Safe mode */ + IEEE80211_NOBRIDGE_MODE, /* No bridging done, all frames sent up the stack */ + IEEE80211_PERSTA_KEYTABLE_SIZE, /* IBSS-only, read-only: persta key table size */ + IEEE80211_RECEIVE_80211, /* deliver std 802.11 frames 802.11 instead of ethernet frames on the rx */ + IEEE80211_SEND_80211, /* OS sends std 802.11 frames 802.11 instead of ethernet frames on tx side */ + IEEE80211_MIN_BEACON_COUNT, /* minumum number beacons to tx/rx before vap can pause */ + IEEE80211_IDLE_TIME, /* minimun no activity time before vap can pause */ + IEEE80211_MIN_FRAMESIZE, /* smallest frame size we are allowed to receive */ + /* features. 0:feature is off. 1:feature is on. */ + IEEE80211_FEATURE_WMM, /* WMM */ + IEEE80211_FEATURE_WMM_PWRSAVE, /* WMM Power Save */ + IEEE80211_FEATURE_UAPSD, /* UAPSD setting (BE/BK/VI/VO) */ + IEEE80211_FEATURE_WDS, /* dynamic WDS feature */ + IEEE80211_FEATURE_PRIVACY, /* encryption */ + IEEE80211_FEATURE_DROP_UNENC, /* drop un encrypted frames */ + IEEE80211_FEATURE_COUNTER_MEASURES , /* turn on couter measures */ + IEEE80211_FEATURE_HIDE_SSID, /* turn on hide ssid feature */ + IEEE80211_FEATURE_APBRIDGE, /* turn on internal mcast traffic bridging for AP */ + IEEE80211_FEATURE_PUREB, /* turn on pure B mode for AP */ + IEEE80211_FEATURE_PUREG, /* turn on pure G mode for AP */ + IEEE80211_FEATURE_REGCLASS, /* add regulatory class IE in AP */ + IEEE80211_FEATURE_COUNTRY_IE, /* add country IE for vap in AP */ + IEEE80211_FEATURE_IC_COUNTRY_IE, /* add country IE for ic in AP */ + IEEE80211_FEATURE_DOTH, /* enable 802.11h */ + IEEE80211_FEATURE_PURE11N, /* enable pure 11n mode */ + IEEE80211_FEATURE_PRIVATE_RSNIE, /* enable OS shim to setup RSN IE*/ + IEEE80211_FEATURE_COPY_BEACON, /* keep a copy of beacon */ + IEEE80211_FEATURE_PSPOLL, /* enable/disable pspoll mode in power save SM */ + IEEE80211_FEATURE_CONTINUE_PSPOLL_FOR_MOREDATA, /* enable/disable option to contunue sending ps polls when there is more data */ + IEEE80211_FEATURE_AMPDU, /* Enable or Disable Aggregation */ +#ifdef ATH_COALESCING + IEEE80211_FEATURE_TX_COALESCING, /* enable tx coalescing */ +#endif + IEEE80211_FEATURE_VAP_IND, /* Repeater independant VAP */ + IEEE80211_FIXED_RETRIES, /* fixed retries 0-4 */ + IEEE80211_SHORT_GI, /* short gi on/off */ + IEEE80211_HT40_INTOLERANT, + IEEE80211_CHWIDTH, + IEEE80211_CHEXTOFFSET, + IEEE80211_DISABLE_2040COEXIST, + IEEE80211_DISABLE_HTPROTECTION, + IEEE80211_STA_QUICKKICKOUT, + IEEE80211_CHSCANINIT, + IEEE80211_FEATURE_STAFWD, /* dynamic AP Client feature */ + IEEE80211_DRIVER_CAPS, + IEEE80211_UAPSD_MAXSP, /* UAPSD service period setting (0:unlimited, 2,4,6) */ + IEEE80211_WEP_MBSSID, + IEEE80211_MGMT_RATE, /* ieee rate to be used for management*/ + IEEE80211_RESMGR_VAP_AIR_TIME_LIMIT, /* When multi-channel enabled, restrict air-time allocated to a VAP */ + IEEE80211_TDLS_MACADDR1, /* Upper 4 bytes of device's MAC address */ + IEEE80211_TDLS_MACADDR2, /* Lower 2 bytes of device's MAC address */ + IEEE80211_TDLS_ACTION, /* TDLS action requested */ + IEEE80211_AUTO_ASSOC, + IEEE80211_PROTECTION_MODE, /* per VAP protection mode*/ + IEEE80211_AUTH_INACT_TIMEOUT, /* inactivity time while waiting for 802.11x auth to complete */ + IEEE80211_INIT_INACT_TIMEOUT, /* inactivity time while waiting for 802.11 auth/assoc to complete */ + IEEE80211_RUN_INACT_TIMEOUT, /* inactivity time when fully authed*/ + IEEE80211_PROBE_INACT_TIMEOUT, /* inactivity counter value below which starts probing */ + IEEE80211_QBSS_LOAD, + IEEE80211_WNM_CAP, + IEEE80211_WNM_BSS_CAP, + IEEE80211_WNM_TFS_CAP, + IEEE80211_WNM_TIM_CAP, + IEEE80211_WNM_SLEEP_CAP, + IEEE80211_WNM_FMS_CAP, + IEEE80211_AP_REJECT_DFS_CHAN, /* AP to reject resuming on DFS Channel */ + IEEE80211_ABOLT, + IEEE80211_COMP, + IEEE80211_FF, + IEEE80211_TURBO, + IEEE80211_BURST, + IEEE80211_AR, + IEEE80211_SLEEP, + IEEE80211_EOSPDROP, + IEEE80211_MARKDFS, + IEEE80211_WDS_AUTODETECT, + IEEE80211_WEP_TKIP_HT, + IEEE80211_ATH_RADIO, + IEEE80211_IGNORE_11DBEACON, + /* Video debug feature */ + IEEE80211_VI_DBG_CFG, /* Video debug configuration - Bit0- enable dbg, Bit1 - enable stats log */ + IEEE80211_VI_DBG_NUM_STREAMS, /* Total number of receive streams */ + IEEE80211_VI_STREAM_NUM, /* the stream number whose marker parameters are being set */ + IEEE80211_VI_DBG_NUM_MARKERS, /* total number of markers used to filter pkts */ + IEEE80211_VI_MARKER_NUM, /* the marker number whose parameters (offset, size & match) are being set */ + IEEE80211_VI_MARKER_OFFSET_SIZE, /* byte offset from skb start (upper 16 bits) & size in bytes(lower 16 bits) */ + IEEE80211_VI_MARKER_MATCH, /* marker pattern match used in filtering */ + IEEE80211_VI_RXSEQ_OFFSET_SIZE, /* Rx Seq num offset skb start (upper 16 bits) & size in bytes(lower 16 bits) */ + IEEE80211_VI_RX_SEQ_RSHIFT, /* right-shift value in case field is not word aligned */ + IEEE80211_VI_RX_SEQ_MAX, /* maximum Rx Seq number (to check wrap around) */ + IEEE80211_VI_RX_SEQ_DROP, /* Indicator to the debug app that a particular seq num has been dropped */ + IEEE80211_VI_TIME_OFFSET_SIZE, /* Timestamp offset skb start (upper 16 bits) & size in bytes(lower 16 bits) */ + IEEE80211_VI_RESTART, /* If set to 1 resets all internal variables/counters & restarts debug tool*/ + IEEE80211_VI_RXDROP_STATUS, /* Total RX drops in wireless */ + IEEE80211_TRIGGER_MLME_RESP, /* Option for App to trigger mlme response */ +#ifdef ATH_SUPPORT_TxBF + IEEE80211_TXBF_AUTO_CVUPDATE, /* auto CV update enable */ + IEEE80211_TXBF_CVUPDATE_PER, /* per threshold to initial CV update*/ +#endif + IEEE80211_MAX_CLIENT_NUMBERS, + IEEE80211_SMARTNET, + IEEE80211_FEATURE_MFP_TEST, /* MFP test */ + IEEE80211_WEATHER_RADAR, /* weather radar channel skip */ + IEEE80211_WEP_KEYCACHE, /* WEP KEYCACHE is enable */ + IEEE80211_SEND_DEAUTH, /* send deauth instead of disassoc while doing interface down */ + IEEE80211_SET_TXPWRADJUST, + IEEE80211_RRM_CAP, + IEEE80211_RRM_DEBUG, + IEEE80211_RRM_STATS, + IEEE80211_RRM_SLWINDOW, + IEEE80211_FEATURE_OFF_CHANNEL_SUPPORT, + IEEE80211_FIXED_VHT_MCS, /* VHT mcs index */ + IEEE80211_FIXED_NSS, /* Spatial Streams count */ + IEEE80211_SUPPORT_LDPC, /* LDPC Support */ + IEEE80211_SUPPORT_TX_STBC, /* TX STBC enable/disable */ + IEEE80211_SUPPORT_RX_STBC, /* RX STBC enable/disable */ + IEEE80211_DEFAULT_KEYID, /* XMIT default key */ + IEEE80211_OPMODE_NOTIFY_ENABLE, /* Op mode notification enable/disable */ + IEEE80211_ENABLE_RTSCTS, /* Enable/Disable RTS-CTS */ + IEEE80211_VHT_MCSMAP, /* VHT MCS Map */ + IEEE80211_GET_ACS_STATE, /* get acs state */ + IEEE80211_GET_CAC_STATE, /* get cac state */ +} ieee80211_param; + +#define IEEE80211_PROTECTION_NONE 0 +#define IEEE80211_PROTECTION_CTSTOSELF 1 +#define IEEE80211_PROTECTION_RTS_CTS 2 + +typedef enum _ieee80211_privacy_filter { + IEEE80211_PRIVACY_FILTER_ALLWAYS, + IEEE80211_PRIVACY_FILTER_KEY_UNAVAILABLE, +} ieee80211_privacy_filter ; + +typedef enum _ieee80211_privacy_filter_packet_type { + IEEE80211_PRIVACY_FILTER_PACKET_UNICAST, + IEEE80211_PRIVACY_FILTER_PACKET_MULTICAST, + IEEE80211_PRIVACY_FILTER_PACKET_BOTH +} ieee80211_privacy_filter_packet_type ; + +typedef struct _ieee80211_privacy_excemption_filter { + u_int16_t ether_type; /* type of ethernet to apply this filter, in host byte order*/ + ieee80211_privacy_filter filter_type; + ieee80211_privacy_filter_packet_type packet_type; +} ieee80211_privacy_exemption; + +/* + * Authentication mode. + * NB: the usage of auth modes NONE, AUTO are deprecated, + * they are implemented through combinations of other auth modes + * and cipher types. The deprecated values are preserved here to + * maintain binary compatibility with applications like + * wpa_supplicant and hostapd. + */ +typedef enum _ieee80211_auth_mode { + IEEE80211_AUTH_NONE = 0, /* deprecated */ + IEEE80211_AUTH_OPEN = 1, /* open */ + IEEE80211_AUTH_SHARED = 2, /* shared-key */ + IEEE80211_AUTH_8021X = 3, /* 802.1x */ + IEEE80211_AUTH_AUTO = 4, /* deprecated */ + IEEE80211_AUTH_WPA = 5, /* WPA */ + IEEE80211_AUTH_RSNA = 6, /* WPA2/RSNA */ + IEEE80211_AUTH_CCKM = 7, /* CCK */ + IEEE80211_AUTH_WAPI = 8, /* WAPI */ +} ieee80211_auth_mode; + +#define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WAPI+1) + +/* + * Cipher types. + * NB: The values are preserved here to maintain binary compatibility + * with applications like wpa_supplicant and hostapd. + */ +typedef enum _ieee80211_cipher_type { + IEEE80211_CIPHER_WEP = 0, + IEEE80211_CIPHER_TKIP = 1, + IEEE80211_CIPHER_AES_OCB = 2, + IEEE80211_CIPHER_AES_CCM = 3, + IEEE80211_CIPHER_WAPI = 4, + IEEE80211_CIPHER_CKIP = 5, + IEEE80211_CIPHER_AES_CMAC = 6, + IEEE80211_CIPHER_NONE = 7, +} ieee80211_cipher_type; + +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1) + +/* key direction */ +typedef enum _ieee80211_key_direction { + IEEE80211_KEY_DIR_TX, + IEEE80211_KEY_DIR_RX, + IEEE80211_KEY_DIR_BOTH +} ieee80211_key_direction; + +#define IEEE80211_KEYIX_NONE ((u_int16_t) -1) + +typedef struct _ieee80211_keyval { + ieee80211_cipher_type keytype; + ieee80211_key_direction keydir; + u_int persistent:1, /* persistent key */ + mfp:1; /* management frame protection */ + u_int16_t keylen; /* length of the key data fields */ + u_int8_t *macaddr; /* mac address of length IEEE80211_ADDR_LEN . all bytes are 0xff for multicast key */ + u_int64_t keyrsc; + u_int64_t keytsc; + u_int16_t txmic_offset; /* TKIP/SMS4 only: offset to tx mic key */ + u_int16_t rxmic_offset; /* TKIP/SMS4 only: offset to rx mic key */ + u_int8_t *keydata; +#ifdef ATH_SUPPORT_WAPI + u_int8_t key_used; /*index for WAPI rekey labeling*/ +#endif +} ieee80211_keyval; + +#define IEEE80211_AES_CMAC_LEN 128 +typedef enum _ieee80211_rsn_param { + IEEE80211_UCAST_CIPHER_LEN, + IEEE80211_MCAST_CIPHER_LEN, + IEEE80211_MCASTMGMT_CIPHER_LEN, + IEEE80211_KEYMGT_ALGS, + IEEE80211_RSN_CAPS +} ieee80211_rsn_param; + +#define IEEE80211_PMKID_LEN 16 + +typedef struct _ieee80211_pmkid_entry { + u_int8_t bssid[IEEE80211_ADDR_LEN]; + u_int8_t pmkid[IEEE80211_PMKID_LEN]; +} ieee80211_pmkid_entry; + +typedef enum _wlan_wme_param { + WLAN_WME_CWMIN, + WLAN_WME_CWMAX, + WLAN_WME_AIFS, + WLAN_WME_TXOPLIMIT, + WLAN_WME_ACM, /*bss only*/ + WLAN_WME_ACKPOLICY /*bss only*/ +} wlan_wme_param; + +typedef enum _ieee80211_frame_type { + IEEE80211_FRAME_TYPE_PROBEREQ, + IEEE80211_FRAME_TYPE_BEACON, + IEEE80211_FRAME_TYPE_PROBERESP, + IEEE80211_FRAME_TYPE_ASSOCREQ, + IEEE80211_FRAME_TYPE_ASSOCRESP, + IEEE80211_FRAME_TYPE_AUTH +} ieee80211_frame_type; + +#define IEEE80211_FRAME_TYPE_MAX (IEEE80211_FRAME_TYPE_AUTH+1) + +typedef enum _ieee80211_ampdu_mode { + IEEE80211_AMPDU_MODE_OFF, /* disable AMPDU */ + IEEE80211_AMPDU_MODE_ON, /* enable AMPDU */ + IEEE80211_AMPDU_MODE_WDSVAR /* enable AMPDU with 4addr WAR */ +} ieee80211_ampdu_mode; + +typedef enum _ieee80211_reset_type { + IEEE80211_RESET_TYPE_DEVICE = 0, /* device reset on error: tx timeout and etc. */ + IEEE80211_RESET_TYPE_DOT11_INTF, /* dot11 reset: only reset one network interface (vap) */ + IEEE80211_RESET_TYPE_INTERNAL, /* internal reset */ +} ieee80211_reset_type; + +typedef struct _ieee80211_reset_request { + ieee80211_reset_type type; + + u_int reset_hw:1, /* reset the actual H/W */ + /* + * The following fields are only valid for DOT11 reset, i.e., + * IEEE80211_RESET_TYPE_DOT11_INTF + */ + reset_phy:1, /* reset PHY */ + reset_mac:1, /* reset MAC */ + set_default_mib:1, /* set default MIB variables */ + no_flush:1; + u_int8_t macaddr[IEEE80211_ADDR_LEN]; + enum ieee80211_phymode phy_mode; +} ieee80211_reset_request; + +#define IEEE80211_MSG_MAX 63 +#define IEEE80211_MSG_SMARTANT 7 /* Bit 7 (0x80)for Smart Antenna debug */ +enum { + /* IEEE80211_PARAM_DBG_LVL */ + IEEE80211_MSG_TDLS = 0, /* TDLS */ + IEEE80211_MSG_ACS, /* auto channel selection */ + IEEE80211_MSG_SCAN_SM, /* scan state machine */ + IEEE80211_MSG_SCANENTRY, /* scan entry */ + IEEE80211_MSG_WDS, /* WDS handling */ + IEEE80211_MSG_ACTION, /* action management frames */ + IEEE80211_MSG_ROAM, /* sta-mode roaming */ + IEEE80211_MSG_INACT, /* inactivity handling */ + IEEE80211_MSG_DOTH = 8, /* 11.h */ + IEEE80211_MSG_IQUE, /* IQUE features */ + IEEE80211_MSG_WME, /* WME protocol */ + IEEE80211_MSG_ACL, /* ACL handling */ + IEEE80211_MSG_WPA, /* WPA/RSN protocol */ + IEEE80211_MSG_RADKEYS, /* dump 802.1x keys */ + IEEE80211_MSG_RADDUMP, /* dump 802.1x radius packets */ + IEEE80211_MSG_RADIUS, /* 802.1x radius client */ + IEEE80211_MSG_DOT1XSM = 16, /* 802.1x state machine */ + IEEE80211_MSG_DOT1X, /* 802.1x authenticator */ + IEEE80211_MSG_POWER, /* power save handling */ + IEEE80211_MSG_STATE, /* state machine */ + IEEE80211_MSG_OUTPUT, /* output handling */ + IEEE80211_MSG_SCAN, /* scanning */ + IEEE80211_MSG_AUTH, /* authentication handling */ + IEEE80211_MSG_ASSOC, /* association handling */ + IEEE80211_MSG_NODE = 24, /* node handling */ + IEEE80211_MSG_ELEMID, /* element id parsing */ + IEEE80211_MSG_XRATE, /* rate set handling */ + IEEE80211_MSG_INPUT, /* input handling */ + IEEE80211_MSG_CRYPTO, /* crypto work */ + IEEE80211_MSG_DUMPPKTS, /* IFF_LINK2 equivalant */ + IEEE80211_MSG_DEBUG, /* IFF_DEBUG equivalent */ + IEEE80211_MSG_MLME, /* MLME */ + /* IEEE80211_PARAM_DBG_LVL_HIGH */ + IEEE80211_MSG_RRM = 32, /* Radio resource measurement */ + IEEE80211_MSG_WNM, /* Wireless Network Management */ + IEEE80211_MSG_P2P_PROT, /* P2P Protocol driver */ + IEEE80211_MSG_PROXYARP, /* 11v Proxy ARP */ + IEEE80211_MSG_L2TIF, /* Hotspot 2.0 L2 TIF */ + IEEE80211_MSG_WIFIPOS, /* WifiPositioning Feature */ + IEEE80211_MSG_WRAP, /* WRAP or Wireless ProxySTA */ + IEEE80211_MSG_DFS, /* DFS debug mesg */ + + IEEE80211_MSG_NUM_CATEGORIES, /* total ieee80211 messages */ + IEEE80211_MSG_UNMASKABLE = IEEE80211_MSG_MAX, /* anything */ + IEEE80211_MSG_ANY = IEEE80211_MSG_MAX, /* anything */ +}; + +/* verbosity levels */ +#define IEEE80211_VERBOSE_OFF 100 +#define IEEE80211_VERBOSE_FORCE 1 +#define IEEE80211_VERBOSE_SERIOUS 2 +#define IEEE80211_VERBOSE_NORMAL 3 +#define IEEE80211_VERBOSE_LOUD 4 +#define IEEE80211_VERBOSE_DETAILED 5 +#define IEEE80211_VERBOSE_COMPLEX 6 +#define IEEE80211_VERBOSE_FUNCTION 7 +#define IEEE80211_VERBOSE_TRACE 8 + +#define IEEE80211_DEBUG_DEFAULT IEEE80211_MSG_DEBUG + +/* + * the lower 4 bits of the msg flags are used for extending the + * debug flags. + */ + +/* + * flag defintions for wlan_mlme_stop_bss(vap) API. + */ +#define WLAN_MLME_STOP_BSS_F_SEND_DEAUTH 0x01 +#define WLAN_MLME_STOP_BSS_F_CLEAR_ASSOC_STATE 0x02 +#define WLAN_MLME_STOP_BSS_F_FORCE_STOP_RESET 0x04 +#define WLAN_MLME_STOP_BSS_F_WAIT_RX_DONE 0x08 +#define WLAN_MLME_STOP_BSS_F_NO_RESET 0x10 +#define WLAN_MLME_STOP_BSS_F_STANDBY 0x20 + +/* + * WAPI commands to authenticator + */ +#define WAPI_WAI_REQUEST (u_int16_t)0x00F1 +#define WAPI_UNICAST_REKEY (u_int16_t)0x00F2 +#define WAPI_STA_AGING (u_int16_t)0x00F3 +#define WAPI_MULTI_REKEY (u_int16_t)0x00F4 +#define WAPI_STA_STATS (u_int16_t)0x00F5 + +/* + * IEEE80211 PHY Statistics. + */ +struct ieee80211_phy_stats { + u_int64_t ips_tx_packets; /* frames successfully transmitted */ + u_int64_t ips_tx_multicast; /* multicast/broadcast frames successfully transmitted */ + u_int64_t ips_tx_fragments; /* fragments successfully transmitted */ + u_int64_t ips_tx_xretries; /* frames that are xretried. NB: not number of retries */ + u_int64_t ips_tx_retries; /* frames transmitted after retries. NB: not number of retries */ + u_int64_t ips_tx_multiretries; /* frames transmitted after more than one retry. */ + u_int64_t ips_tx_timeout; /* frames that expire the dot11MaxTransmitMSDULifetime */ + u_int64_t ips_rx_packets; /* frames successfully received */ + u_int64_t ips_rx_multicast; /* multicast/broadcast frames successfully received */ + u_int64_t ips_rx_fragments; /* fragments successfully received */ + u_int64_t ips_rx_timeout; /* frmaes that expired the dot11MaxReceiveLifetime */ + u_int64_t ips_rx_dup; /* duplicated fragments */ + u_int64_t ips_rx_mdup; /* multiple duplicated fragments */ + u_int64_t ips_rx_promiscuous; /* frames that are received only because promiscuous filter is on */ + u_int64_t ips_rx_promiscuous_fragments; /* fragments that are received only because promiscuous filter is on */ + u_int64_t ips_tx_rts; /* RTS success count */ + u_int64_t ips_tx_shortretry; /* tx on-chip retries (short). RTSFailCnt */ + u_int64_t ips_tx_longretry; /* tx on-chip retries (long). DataFailCnt */ + u_int64_t ips_rx_crcerr; /* rx failed 'cuz of bad CRC */ + u_int64_t ips_rx_fifoerr; /* rx failed 'cuz of FIFO overrun */ + u_int64_t ips_rx_decrypterr; /* rx decryption error */ +}; + +struct ieee80211_chan_stats { + u_int32_t chan_clr_cnt; + u_int32_t cycle_cnt; + u_int32_t phy_err_cnt; +}; + +struct ieee80211_mac_stats { + u_int64_t ims_tx_packets; /* frames successfully transmitted */ + u_int64_t ims_rx_packets; /* frames successfully received */ + u_int64_t ims_tx_bytes; /* bytes successfully transmitted */ + u_int64_t ims_rx_bytes; /* bytes successfully received */ + + /* TODO: For the byte counts below, we need to handle some scenarios + such as encryption related decaps, etc */ + u_int64_t ims_tx_data_packets;/* data frames successfully transmitted */ + u_int64_t ims_rx_data_packets;/* data frames successfully received */ + u_int64_t ims_tx_data_bytes; /* data bytes successfully transmitted, + inclusive of FCS. */ + u_int64_t ims_rx_data_bytes; /* data bytes successfully received, + inclusive of FCS. */ + + u_int64_t ims_tx_datapyld_bytes; /* data payload bytes successfully + transmitted */ + u_int64_t ims_rx_datapyld_bytes; /* data payload successfully + received */ + + /* Decryption errors */ + u_int64_t ims_rx_unencrypted; /* rx w/o wep and privacy on */ + u_int64_t ims_rx_badkeyid; /* rx w/ incorrect keyid */ + u_int64_t ims_rx_decryptok; /* rx decrypt okay */ + u_int64_t ims_rx_decryptcrc; /* rx decrypt failed on crc */ + u_int64_t ims_rx_wepfail; /* rx wep processing failed */ + u_int64_t ims_rx_tkipreplay; /* rx seq# violation (TKIP) */ + u_int64_t ims_rx_tkipformat; /* rx format bad (TKIP) */ + u_int64_t ims_rx_tkipmic; /* rx MIC check failed (TKIP) */ + u_int64_t ims_rx_tkipicv; /* rx ICV check failed (TKIP) */ + u_int64_t ims_rx_ccmpreplay; /* rx seq# violation (CCMP) */ + u_int64_t ims_rx_ccmpformat; /* rx format bad (CCMP) */ + u_int64_t ims_rx_ccmpmic; /* rx MIC check failed (CCMP) */ +/*this file can be included by applications as 80211stats that has no such MACRO definition*/ +//#if ATH_SUPPORT_WAPI + u_int64_t ims_rx_wpireplay; /* rx seq# violation (WPI) */ + u_int64_t ims_rx_wpimic; /* rx MIC check failed (WPI) */ +//#endif + /* Other Tx/Rx errors */ + u_int64_t ims_tx_discard; /* tx dropped by NIC */ + u_int64_t ims_rx_discard; /* rx dropped by NIC */ + + u_int64_t ims_rx_countermeasure; /* rx TKIP countermeasure activation count */ +}; + +/* + * Summary statistics. + */ +struct ieee80211_stats { + u_int32_t is_rx_badversion; /* rx frame with bad version */ + u_int32_t is_rx_tooshort; /* rx frame too short */ + u_int32_t is_rx_wrongbss; /* rx from wrong bssid */ + u_int32_t is_rx_wrongdir; /* rx w/ wrong direction */ + u_int32_t is_rx_mcastecho; /* rx discard 'cuz mcast echo */ + u_int32_t is_rx_notassoc; /* rx discard 'cuz sta !assoc */ + u_int32_t is_rx_noprivacy; /* rx w/ wep but privacy off */ + u_int32_t is_rx_decap; /* rx decapsulation failed */ + u_int32_t is_rx_mgtdiscard; /* rx discard mgt frames */ + u_int32_t is_rx_ctl; /* rx discard ctrl frames */ + u_int32_t is_rx_beacon; /* rx beacon frames */ + u_int32_t is_rx_rstoobig; /* rx rate set truncated */ + u_int32_t is_rx_elem_missing; /* rx required element missing*/ + u_int32_t is_rx_elem_toobig; /* rx element too big */ + u_int32_t is_rx_elem_toosmall; /* rx element too small */ + u_int32_t is_rx_elem_unknown; /* rx element unknown */ + u_int32_t is_rx_badchan; /* rx frame w/ invalid chan */ + u_int32_t is_rx_chanmismatch; /* rx frame chan mismatch */ + u_int32_t is_rx_nodealloc; /* rx frame dropped */ + u_int32_t is_rx_ssidmismatch; /* rx frame ssid mismatch */ + u_int32_t is_rx_auth_unsupported; /* rx w/ unsupported auth alg */ + u_int32_t is_rx_auth_fail; /* rx sta auth failure */ + u_int32_t is_rx_auth_countermeasures;/* rx auth discard 'cuz CM */ + u_int32_t is_rx_assoc_bss; /* rx assoc from wrong bssid */ + u_int32_t is_rx_assoc_notauth; /* rx assoc w/o auth */ + u_int32_t is_rx_assoc_capmismatch; /* rx assoc w/ cap mismatch */ + u_int32_t is_rx_assoc_norate; /* rx assoc w/ no rate match */ + u_int32_t is_rx_assoc_badwpaie; /* rx assoc w/ bad WPA IE */ + u_int32_t is_rx_deauth; /* rx deauthentication */ + u_int32_t is_rx_disassoc; /* rx disassociation */ + u_int32_t is_rx_action; /* rx action mgt */ + u_int32_t is_rx_badsubtype; /* rx frame w/ unknown subtype*/ + u_int32_t is_rx_nobuf; /* rx failed for lack of buf */ + u_int32_t is_rx_ahdemo_mgt; /* rx discard ahdemo mgt frame*/ + u_int32_t is_rx_bad_auth; /* rx bad auth request */ + u_int32_t is_rx_unauth; /* rx on unauthorized port */ + u_int32_t is_rx_badcipher; /* rx failed 'cuz key type */ + u_int32_t is_tx_nodefkey; /* tx failed 'cuz no defkey */ + u_int32_t is_tx_noheadroom; /* tx failed 'cuz no space */ + u_int32_t is_rx_nocipherctx; /* rx failed 'cuz key !setup */ + u_int32_t is_rx_acl; /* rx discard 'cuz acl policy */ + u_int32_t is_rx_ffcnt; /* rx fast frames */ + u_int32_t is_rx_badathtnl; /* driver key alloc failed */ + u_int32_t is_rx_nowds; /* 4-addr packets received with no wds enabled */ + u_int32_t is_tx_nobuf; /* tx failed for lack of buf */ + u_int32_t is_tx_nonode; /* tx failed for no node */ + u_int32_t is_tx_unknownmgt; /* tx of unknown mgt frame */ + u_int32_t is_tx_badcipher; /* tx failed 'cuz key type */ + u_int32_t is_tx_ffokcnt; /* tx fast frames sent success */ + u_int32_t is_tx_fferrcnt; /* tx fast frames sent success */ + u_int32_t is_scan_active; /* active scans started */ + u_int32_t is_scan_passive; /* passive scans started */ + u_int32_t is_node_timeout; /* nodes timed out inactivity */ + u_int32_t is_crypto_nomem; /* no memory for crypto ctx */ + u_int32_t is_crypto_tkip; /* tkip crypto done in s/w */ + u_int32_t is_crypto_tkipenmic; /* tkip en-MIC done in s/w */ + u_int32_t is_crypto_tkipdemic; /* tkip de-MIC done in s/w */ + u_int32_t is_crypto_tkipcm; /* tkip counter measures */ + u_int32_t is_crypto_ccmp; /* ccmp crypto done in s/w */ + u_int32_t is_crypto_wep; /* wep crypto done in s/w */ + u_int32_t is_crypto_setkey_cipher; /* cipher rejected key */ + u_int32_t is_crypto_setkey_nokey; /* no key index for setkey */ + u_int32_t is_crypto_delkey; /* driver key delete failed */ + u_int32_t is_crypto_badcipher; /* unknown cipher */ + u_int32_t is_crypto_nocipher; /* cipher not available */ + u_int32_t is_crypto_attachfail; /* cipher attach failed */ + u_int32_t is_crypto_swfallback; /* cipher fallback to s/w */ + u_int32_t is_crypto_keyfail; /* driver key alloc failed */ + u_int32_t is_crypto_enmicfail; /* en-MIC failed */ + u_int32_t is_ibss_capmismatch; /* merge failed-cap mismatch */ + u_int32_t is_ibss_norate; /* merge failed-rate mismatch */ + u_int32_t is_ps_unassoc; /* ps-poll for unassoc. sta */ + u_int32_t is_ps_badaid; /* ps-poll w/ incorrect aid */ + u_int32_t is_ps_qempty; /* ps-poll w/ nothing to send */ +}; + +typedef enum _ieee80211_send_frame_type { + IEEE80211_SEND_NULL, + IEEE80211_SEND_QOSNULL, +} ieee80211_send_frame_type; + +typedef struct _ieee80211_tspec_info { + u_int8_t traffic_type; + u_int8_t direction; + u_int8_t dot1Dtag; + u_int8_t tid; + u_int8_t acc_policy_edca; + u_int8_t acc_policy_hcca; + u_int8_t aggregation; + u_int8_t psb; + u_int8_t ack_policy; + u_int16_t norminal_msdu_size; + u_int16_t max_msdu_size; + u_int32_t min_srv_interval; + u_int32_t max_srv_interval; + u_int32_t inactivity_interval; + u_int32_t suspension_interval; + u_int32_t srv_start_time; + u_int32_t min_data_rate; + u_int32_t mean_data_rate; + u_int32_t peak_data_rate; + u_int32_t max_burst_size; + u_int32_t delay_bound; + u_int32_t min_phy_rate; + u_int16_t surplus_bw; + u_int16_t medium_time; +} ieee80211_tspec_info; + +#ifndef EXTERNAL_USE_ONLY +/* + * Manual ADDBA support + */ +enum { + ADDBA_SEND = 0, + ADDBA_STATUS = 1, + DELBA_SEND = 2, + ADDBA_RESP = 3, + ADDBA_CLR_RESP = 4, + SINGLE_AMSDU = 5, +}; + +enum { + ADDBA_MODE_AUTO = 0, + ADDBA_MODE_MANUAL = 1, +}; + +struct ieee80211_addba_delba_request { + wlan_dev_t ic; + u_int8_t action; + u_int8_t tid; + u_int16_t status; + u_int16_t aid; + u_int32_t arg1; + u_int32_t arg2; +}; +#endif /* EXTERNAL_USE_ONLY */ + +#ifdef ATH_BT_COEX +typedef enum _ieee80211_bt_coex_info_type { + IEEE80211_BT_COEX_INFO_SCHEME = 0, + IEEE80211_BT_COEX_INFO_BTBUSY = 1, +} ieee80211_bt_coex_info_type; +#endif + +struct tkip_countermeasure { + u_int16_t mic_count_in_60s; + u_int32_t timestamp; +} ; + +enum _ieee80211_qos_frame_direction { + IEEE80211_RX_QOS_FRAME = 0, + IEEE80211_TX_QOS_FRAME = 1, + IEEE80211_TX_COMPLETE_QOS_FRAME = 2 +}; + +typedef struct ieee80211_vap_opmode_count { + int total_vaps; + int ibss_count; + int sta_count; + int wds_count; + int ahdemo_count; + int ap_count; + int monitor_count; + int btamp_count; + int unknown_count; +} ieee80211_vap_opmode_count; + +struct ieee80211_app_ie_t { + u_int32_t length; + u_int8_t *ie; +}; + +/* + * MAC ACL operations. + */ +enum { + IEEE80211_MACCMD_POLICY_OPEN = 0, /* set policy: no ACL's */ + IEEE80211_MACCMD_POLICY_ALLOW = 1, /* set policy: allow traffic */ + IEEE80211_MACCMD_POLICY_DENY = 2, /* set policy: deny traffic */ + IEEE80211_MACCMD_FLUSH = 3, /* flush ACL database */ + IEEE80211_MACCMD_DETACH = 4, /* detach ACL policy */ + IEEE80211_MACCMD_POLICY_RADIUS = 5, /* set policy: RADIUS managed ACLs */ +}; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/if_upperproto.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/if_upperproto.h new file mode 100644 index 000000000000..1e869ccf4736 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/if_upperproto.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +//#ifndef _NET_IF_ETHERSUBR_H_ +//#define _NET_IF_ETHERSUBR_H_ +#ifndef _NET_IF_UPPERPROTO_H_ +#define _NET_IF_UPPERPROTO_H_ + +#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ +#define ETHER_TYPE_LEN 2 /* length of the Ethernet type field */ +#define ETHER_CRC_LEN 4 /* length of the Ethernet CRC */ +#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN) +#define ETHER_MAX_LEN 1518 + +#define ETHERMTU (ETHER_MAX_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN) + +/* + * Structure of a 10Mb/s Ethernet header. + */ +#ifndef _NET_ETHERNET_H_ +struct ether_header { + u_int8_t ether_dhost[ETHER_ADDR_LEN]; + u_int8_t ether_shost[ETHER_ADDR_LEN]; + u_int16_t ether_type; +} __packed; +#endif +#ifndef _LINUX_IF_VLAN_H_ +struct vlan_hdr { + u_int16_t h_vlan_TCI; + u_int16_t h_vlan_encapsulated_proto; +} __packed; +#define VLAN_VID_MASK 0xfff +#endif + +#ifndef ETHERTYPE_PAE +#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ +#endif +#ifndef ETHERTYPE_IP +#define ETHERTYPE_IP 0x0800 /* IP protocol */ +#endif +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 /* Appletalk AARP protocol */ +#endif +#ifndef ETHERTYPE_IPX +#define ETHERTYPE_IPX 0x8137 /* IPX over DIX protocol */ +#endif +#ifndef ETHERTYPE_ARP +#define ETHERTYPE_ARP 0x0806 /* ARP protocol */ +#endif +#ifndef ETHERTYPE_IPV6 +#define ETHERTYPE_IPV6 0x86dd /* IPv6 */ +#endif +#ifndef ETHERTYPE_8021Q +#define ETHERTYPE_8021Q 0x8100 /* 802.1Q vlan protocol */ +#endif +#ifndef ETHERTYPE_VLAN +#define ETHERTYPE_VLAN 0x8100 /* VLAN TAG protocol */ +#endif +#ifndef TX_QUEUE_FOR_EAPOL_FRAME +#define TX_QUEUE_FOR_EAPOL_FRAME 0x7 /* queue eapol frame to queue 7 to avoid aggregation disorder */ +#endif + +/* + * define WAI ethertype + */ +#ifndef ETHERTYPE_WAI +#define ETHERTYPE_WAI 0x88b4 /* WAI/WAPI */ +#endif + +#define ETHERTYPE_OCB_TX 0x8151 +#define ETHERTYPE_OCB_RX 0x8152 + +/* + * Structure of a 48-bit Ethernet address. + */ +#if 0 +#ifndef _NET_ETHERNET_H_ +struct ether_addr { + u_int8_t octet[ETHER_ADDR_LEN]; +} __packed; +#endif +#endif + +#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ + +#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */ +#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */ + +/* + * Structure of the IP frame + */ +struct ip_header { + u_int8_t version_ihl; + u_int8_t tos; + u_int16_t tot_len; + u_int16_t id; + u_int16_t frag_off; + u_int8_t ttl; + u_int8_t protocol; + u_int16_t check; + u_int32_t saddr; + u_int32_t daddr; + /*The options start here. */ +}; +#ifndef IP_PROTO_TCP +#define IP_PROTO_TCP 0x6 /* TCP protocol */ +#endif +#ifndef IP_PROTO_UDP +#define IP_PROTO_UDP 17 +#endif + +/* + * IGMP protocol structures + */ + +/* IGMP record type */ +#define IGMP_QUERY_TYPE 0x11 +#define IGMPV1_REPORT_TYPE 0x12 +#define IGMPV2_REPORT_TYPE 0x16 +#define IGMPV2_LEAVE_TYPE 0x17 +#define IGMPV3_REPORT_TYPE 0x22 + +/* Is packet type is either leave or report */ +#define IS_IGMP_REPORT_LEAVE_PACKET(type) (\ + (IGMPV1_REPORT_TYPE == type)\ + || (IGMPV2_REPORT_TYPE == type)\ + || (IGMPV2_LEAVE_TYPE == type)\ + || (IGMPV3_REPORT_TYPE == type)\ + ) +/* + * Header in on cable format + */ + +struct igmp_header +{ + u_int8_t type; + u_int8_t code; /* For newer IGMP */ + u_int16_t csum; + u_int32_t group; +}; + +/* V3 group record types [grec_type] */ +#define IGMPV3_MODE_IS_INCLUDE 1 +#define IGMPV3_MODE_IS_EXCLUDE 2 +#define IGMPV3_CHANGE_TO_INCLUDE 3 +#define IGMPV3_CHANGE_TO_EXCLUDE 4 +#define IGMPV3_ALLOW_NEW_SOURCES 5 +#define IGMPV3_BLOCK_OLD_SOURCES 6 + +/* Group record format + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Record Type | Aux Data Len | Number of Sources (N) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Multicast Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Address [1] | + +- -+ + | Source Address [2] | + +- -+ + . . . + . . . + . . . + +- -+ + | Source Address [N] | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Auxiliary Data . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct igmp_v3_grec { + u_int8_t grec_type; + u_int8_t grec_auxwords; + u_int16_t grec_nsrcs; + u_int32_t grec_mca; +}; + +/* IGMPv3 report format + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type = 0x22 | Reserved | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | Number of Group Records (M) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Group Record [1] . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Group Record [2] . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | . | + . . . + | . | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Group Record [M] . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct igmp_v3_report { + u_int8_t type; + u_int8_t resv1; + u_int16_t csum; + u_int16_t resv2; + u_int16_t ngrec; +}; + +/* Calculate the group record length*/ +#define IGMPV3_GRP_REC_LEN(x) (8 + (4 * x->grec_nsrcs) + (4 * x->grec_auxwords) ) + +#endif /* _NET_IF_ETHERSUBR_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ip_prot.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ip_prot.h new file mode 100644 index 000000000000..6b72caa046eb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ip_prot.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _IP_PROT__H_ +#define _IP_PROT__H_ + + +#define IP_PROTOCOL_ICMP 0x01 /* Internet Control Message Protocol */ +#define IP_PROTOCOL_IGMP 0x02 /* Internet Group Management Protocol */ +#define IP_PROTOCOL_IPV4 0x04 /* IPv4 (encapsulation) */ +#define IP_PROTOCOL_TCP 0x06 /* Transmission Control Protocol */ +#define IP_PROTOCOL_UDP 0x11 /* User Datagram Protocol */ +#define IP_PROTOCOL_RDP 0x1B /* Reliable Datagram Protocol */ +#define IP_PROTOCOL_IPV6 0x29 /* IPv6 (encapsulation) */ +#define IP_PROTOCOL_IPV6_ROUTE 0x2B /* Routing Header for IPv6 */ +#define IP_PROTOCOL_IPV6_FRAG 0x2C /* Fragment Header for IPv6 */ +#define IP_PROTOCOL_RSVP 0x2E /* Resource Reservation Protocol */ +#define IP_PROTOCOL_GRE 0x2F /* Generic Routing Encapsulation */ +#define IP_PROTOCOL_MHRP 0x30 /* Mobile Host Routing Protocol */ +#define IP_PROTOCOL_BNA 0x31 /* BNA */ +#define IP_PROTOCOL_ESP 0x32 /* Encapsulating Security Payload */ +#define IP_PROTOCOL_MOBILE 0x37 /* IP Mobility (Min Encap) */ +#define IP_PROTOCOL_IPV6_ICMP 0x3A /* ICMP for IPv6 */ +#define IP_PROTOCOL_IPV6_NONXT 0x3B /* No Next Header for IPv6 */ +#define IP_PROTOCOL_IPV6_OPTS 0x3C /* Destination Options for IPv6 */ +#define IP_PROTOCOL_IPCOMP 0x6C /* IP Payload Compression Protocol */ +#define IP_PROTOCOL_L2TP 0x73 /* Layer Two Tunneling Protocol Version 3 */ +#define IP_PROTOCOL_SMP 0x79 /* Simple Message Protocol */ +#define IP_PROTOCOL_SCTP 0x84 /* Stream Control Transmission Protocol */ +#define IP_PROTOCOL_SHIM6 0x8C /* Site Multihoming by IPv6 Intermediation */ + + + +/* IPv6 ICMP types */ +#define IPV6_ICMP_TYPE_MLD 0x8F + +#endif /* _IP_PROT__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv4.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv4.h new file mode 100644 index 000000000000..7e8ba9182b60 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv4.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _IPV4__H_ +#define _IPV4__H_ + +#if defined(ATH_TARGET) +#include /* A_UINT8 */ +#else +#include /* A_UINT8 */ +#endif + +#define IPV4_ADDR_LEN 4 /* bytes */ +struct ipv4_hdr_t { + A_UINT8 ver_hdrlen; /* version and hdr length */ + A_UINT8 tos; /* type of service */ + A_UINT8 len[2]; /* total length */ + A_UINT8 id[2]; + A_UINT8 flags_fragoff[2]; /* flags and fragment offset field */ + A_UINT8 ttl; /* time to live */ + A_UINT8 protocol; + A_UINT8 hdr_checksum[2]; + A_UINT8 src_addr[IPV4_ADDR_LEN]; + A_UINT8 dst_addr[IPV4_ADDR_LEN]; +}; + +#define IPV4_HDR_LEN (sizeof(struct ipv4_hdr_t)) +#define IPV4_HDR_OFFSET_PROTOCOL (offsetof(struct ipv4_hdr_t, protocol)) +#define IPV4_HDR_OFFSET_DST_ADDR (offsetof(struct ipv4_hdr_t, dst_addr[0])) + +#endif /* _IPV4__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv6_defs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv6_defs.h new file mode 100644 index 000000000000..c07faac43100 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ipv6_defs.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _IPV6__H_ +#define _IPV6__H_ + +#if defined(ATH_TARGET) +#include /* A_UINT8 */ +#else +#include /* A_UINT8 */ +#include /* A_COMPILE_TIME_ASSERT */ +#endif + +/* utilities for converting between network byte order and native endianness */ +#ifndef BYTESWAP32 +#define BYTESWAP32(x) \ + ((((x) & 0x000000ff) << 24) /* byte 0 -> byte 3 */ | \ + (((x) & 0x0000ff00) << 8) /* byte 1 -> byte 2 */ | \ + (((x) & 0x00ff0000) >> 8) /* byte 2 -> byte 1 */ | \ + (((x) & 0xff000000) >> 24) /* byte 3 -> byte 0 */) +#endif /* BYTESWAP32 */ + +#ifndef BE_TO_CPU32 + #if defined(ATH_TARGET) + /* assume target is little-endian */ + #define BE_TO_CPU32(x) BYTESWAP32(x) + #else + #ifdef BIG_ENDIAN_HOST + #define BE_TO_CPU32(x) (x) + #else + #define BE_TO_CPU32(x) BYTESWAP32(x) + #endif + #endif +#endif /* BE_TO_CPU32 */ + + +/* IPv6 header definition */ + +#define IPV6_ADDR_LEN 4 /* bytes */ +struct ipv6_hdr_t { + A_UINT32 ver_tclass_flowlabel; /* version, traffic class, and flow label */ + A_UINT8 pyld_len[2]; /* payload length */ + A_UINT8 next_hdr; + A_UINT8 hop_limit; + A_UINT8 src_addr[IPV6_ADDR_LEN]; + A_UINT8 dst_addr[IPV6_ADDR_LEN]; +}; + +#define IPV6_HDR_LEN (sizeof(struct ipv6_hdr_t)) +#define IPV6_HDR_OFFSET_NEXT_HDR (offsetof(struct ipv6_hdr_t, next_hdr)) +#define IPV6_HDR_OFFSET_DST_ADDR (offsetof(struct ipv6_hdr_t, dst_addr[0])) + + +/* IPv6 header field access macros */ + +#define IPV6_HDR_VERSION_M 0xF0000000 +#define IPV6_HDR_VERSION_S 28 + +#define IPV6_HDR_TRAFFIC_CLASS_M 0x0FF00000 +#define IPV6_HDR_TRAFFIC_CLASS_S 20 + +#define IPV6_HDR_FLOW_LABEL_M 0x000FFFFF +#define IPV6_HDR_FLOW_LABEL_S 0 + +static inline A_UINT8 IPV6_VERSION(struct ipv6_hdr_t *ipv6_hdr) +{ + return + (BE_TO_CPU32(ipv6_hdr->ver_tclass_flowlabel) & + IPV6_HDR_VERSION_M) >> IPV6_HDR_VERSION_S; +} + +static inline A_UINT8 IPV6_TRAFFIC_CLASS(struct ipv6_hdr_t *ipv6_hdr) +{ + return + (A_UINT8)((BE_TO_CPU32(ipv6_hdr->ver_tclass_flowlabel) & + IPV6_HDR_TRAFFIC_CLASS_M) >> IPV6_HDR_TRAFFIC_CLASS_S); +} + +static inline A_UINT32 IPV6_FLOW_LABEL(struct ipv6_hdr_t *ipv6_hdr) +{ + return + (BE_TO_CPU32(ipv6_hdr->ver_tclass_flowlabel) & + IPV6_HDR_FLOW_LABEL_M) >> IPV6_HDR_FLOW_LABEL_S; +} + +#endif /* _IPV6__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/isoc_hw_desc.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/isoc_hw_desc.h new file mode 100644 index 000000000000..6e0a53e238a2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/isoc_hw_desc.h @@ -0,0 +1,1197 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** +* @file isoc_hw_desc.h +* @brief Define the Tx BD and Rx BD structs +*/ +#ifndef _ISOC_HW_DESC__H_ +#define _ISOC_HW_DESC__H_ + +#include /* A_UINT32 */ + +#include /* adf_os_print */ +#include /* adf_os_assert */ + + +/*** + NOTE: For Pronto definition, only V1 is defined. For V2, it needs to add other fields +***/ + +/** +* @brief isoc_rx_bd_t - the format of the "RX BD" (rx buffer descriptor) +*/ + +typedef struct +{ + /* 0x00 */ +#ifdef BIG_ENDIAN_HOST + + /** (Only used by the DPU) + This routing flag indicates the WQ number to which the DPU will push the + frame after it finished processing it. */ + A_UINT32 dpu_routing_flag:8; + + /** This is DPU sig inserted by RXP. Signature on RA's DPU descriptor */ + A_UINT32 dpu_signature:3; + + /** When set Sta is authenticated. SW needs to set bit + addr2_auth_extract_enable in rxp_config2 register. Then RXP will use bit 3 + in DPU sig to say whether STA is authenticated or not. In this case only + lower 2bits of DPU Sig is valid */ + A_UINT32 sta_authenticated:1; + + /** When set address2 is not valid */ + A_UINT32 addr2_invalid:1; + + /** When set it indicates TPE has sent the Beacon frame */ + A_UINT32 beacon_sent:1; + + /** This bit filled by rxp when set indicates if the current tsf is smaller + than received tsf */ + A_UINT32 rx_tsf_later:1; + + /** These two fields are used by SW to carry the Rx Channel number and SCAN bit in RxBD*/ + A_UINT32 rx_channel:4; + /** For WMI host, this bit means band 0 - 2.4Ghz 1 - 5GHz*/ + A_UINT32 band_5ghz:1; + + A_UINT32 reserved0:1; + + /** LLC Removed + This bit is only used in Libra rsvd for Virgo1.0/Virgo2.0 + Filled by ADU when it is set LLC is removed from packet */ + A_UINT32 llc_removed:1; + + A_UINT32 uma_bypass:1; + + /** This bit is only available in Virgo2.0/libra it is reserved in Virgo1.0 + Robust Management frame. This bit indicates to DPU that the packet is a + robust management frame which requires decryption(this bit is only valid for + management unicast encrypted frames) + 1 - Needs decryption + 0 - No decryption required */ + A_UINT32 robust_mgmt:1; + + /** + This bit is only in Virgo2.0/libra it is reserved in Virgo 1.0 + This 1-bit field indicates to DPU Unicast/BC/MC packet + 0 - Unicast packet + 1 - Broadcast/Multicast packet + This bit is only valid when robust_mgmt bit is 1 */ + A_UINT32 not_unicast:1; + + /** This is the KEY ID extracted from WEP packets and is used for determine + the RX Key Index to use in the DPU Descriptror. + This field is 2bits for virgo 1.0 + And 3 bits in virgo2.0 and Libra + In virgo2.0/libra it is 3bits for the BC/MC packets */ + A_UINT32 rx_key_id:3; + + /** (Only used by the DPU) + No encryption/decryption + 0: No action + 1: DPU will not encrypt/decrypt the frame, and discard any encryption + related settings in the PDU descriptor. */ + A_UINT32 dpu_no_encrypt:1; + + /** + This is only available in libra/virgo2.0 it is reserved for virgo1.0 + This bit is filled by RXP and modified by ADU + This bit indicates to ADU/UMA module that the packet requires 802.11n to + 802.3 frame translation. Once ADU/UMA is done with translation they + overwrite it with 1'b0/1'b1 depending on how the translation resulted + When used by ADU + 0 - No frame translation required + 1 - Frame Translation required + When used by SW + 0 - Frame translation not done, MPDU header offset points to 802.11 header.. + 1 - Frame translation done ; hence MPDU header offset will point to a + 802.3 header */ + A_UINT32 frame_translate:1; + + /** (Only used by the DPU) + BD Type + 00: 'Generic BD', as indicted above + 01: De-fragmentation format + 10-11: Reserved for future use. */ + A_UINT32 bd_type:2; + +#else + A_UINT32 bd_type:2; + A_UINT32 frame_translate:1; + A_UINT32 dpu_no_encrypt:1; + A_UINT32 rx_key_id:3; + A_UINT32 not_unicast:1; + A_UINT32 robust_mgmt:1; + A_UINT32 reserved1:1; + A_UINT32 llc_removed:1; + A_UINT32 reserved0:1; + /** For WMI host, this bit means band 0 - 2.4Ghz 1 - 5GHz*/ + A_UINT32 band_5ghz:1; + A_UINT32 rx_channel:4; + A_UINT32 rx_tsf_later:1; + A_UINT32 beacon_sent:1; + A_UINT32 addr2_invalid:1; + A_UINT32 sta_authenticated:1; + A_UINT32 dpu_signature:3; + A_UINT32 dpu_routing_flag:8; +#endif + + /* 0x04 */ +#ifdef BIG_ENDIAN_HOST + + /** This is used for AMSDU this is the PDU index of the PDU which is the + one before last PDU; for all non AMSDU frames, this field SHALL be 0. + Used in ADU (for AMSDU deaggregation) */ + A_UINT32 amsdu_pdu_idx:16; + +#ifdef QCA_ISOC_PRONTO + A_UINT32 adu_feedback:7; + //ToDO: Add meaning of this bit + A_UINT32 dpu_magic_packet: 1; +#else + A_UINT32 adu_feedback:8; +#endif //QCA_ISOC_PRONTO + + /** DPU feedback */ + A_UINT32 dpu_feedback:8; + +#else + A_UINT32 dpu_feedback:8; +#ifdef QCA_ISOC_PRONTO + A_UINT32 dpu_magic_packet: 1; + A_UINT32 adu_feedback:7; +#else + A_UINT32 adu_feedback:8; +#endif //QCA_ISOC_PRONTO + + A_UINT32 amsdu_pdu_idx:16; +#endif + + /* 0x08 */ +#ifdef BIG_ENDIAN_HOST + + /** In case PDUs are linked to the BD, this field indicates the index of + the first PDU linked to the BD. When PDU count is zero, this field has an + undefined value. */ + A_UINT32 head_pdu_idx:16; + + /** In case PDUs are linked to the BD, this field indicates the index of + the last PDU. When PDU count is zero, this field has an undefined value.*/ + A_UINT32 tail_pdu_idx:16; + +#else + A_UINT32 tail_pdu_idx:16; + A_UINT32 head_pdu_idx:16; +#endif + + /* 0x0c */ +#ifdef BIG_ENDIAN_HOST + + /** The length (in number of bytes) of the MPDU header. + Limitation: The MPDU header offset + MPDU header length can never go beyond + the end of the first PDU */ + A_UINT32 mpdu_header_length:8; + + /** The start byte number of the MPDU header. + The byte numbering is done in the BE format. Word 0x0, bits [31:24] has + byte index 0. */ + A_UINT32 mpdu_header_offset:8; + + /** The start byte number of the MPDU data. + The byte numbering is done in the BE format. Word 0x0, bits [31:24] has + byte index 0. Note that this offset can point all the way into the first + linked PDU. + Limitation: MPDU DATA OFFSET can not point into the 2nd linked PDU */ + A_UINT32 mpdu_data_offset:9; + + /** The number of PDUs linked to the BD. + This field should always indicate the correct amount. */ + A_UINT32 pdu_count:7; +#else + + A_UINT32 pdu_count:7; + A_UINT32 mpdu_data_offset:9; + A_UINT32 mpdu_header_offset:8; + A_UINT32 mpdu_header_length:8; +#endif + + /* 0x10 */ +#ifdef BIG_ENDIAN_HOST + + /** This is the length (in number of bytes) of the entire MPDU + (header and data). Note that the length does not include FCS field. */ + A_UINT32 mpdu_length:16; + + A_UINT32 reserved3: 3; + //ToDO: Add meaning of this bit + A_UINT32 rx_dxe_priority_routing:1; + + /** Traffic Identifier + Indicates the traffic class the frame belongs to. For non QoS frames, + this field is set to zero. */ + A_UINT32 tid:4; + + /* + * For the HW and FW, reserved4 is 6 bits long. + * However, the host SW uses two of these bits as flags to remember what + * to do with the rx frame. Hence, for the SW, reserved4 is only 4 bits. + */ + A_UINT32 sw_flag_forward:1; /* SW-only field, unused by FW+HW */ + A_UINT32 sw_flag_discard:1; /* SW-only field, unused by FW+HW */ + A_UINT32 reserved4:4; /* SW perspective: 4 bits reserved */ + //A_UINT32 reserved4:6; /* FW+HW perspecitve: 6 bits reserved */ + A_UINT32 htt_t2h_msg:1; + A_UINT32 flow_control:1; +#else + A_UINT32 flow_control:1; + A_UINT32 htt_t2h_msg:1; + //A_UINT32 reserved4:6; /* FW+HW perspecitve: 6 bits reserved */ + A_UINT32 reserved4:4; /* SW perspective: 4 bits reserved */ + A_UINT32 sw_flag_discard:1; + A_UINT32 sw_flag_forward:1; + A_UINT32 tid:4; + A_UINT32 rx_dxe_priority_routing:1; + A_UINT32 reserved3: 3; + A_UINT32 mpdu_length:16; +#endif + + /* 0x14 */ +#ifdef BIG_ENDIAN_HOST + + /** (Only used by the DPU) + The DPU descriptor index is used to calculate where in memory the DPU can + find the DPU descriptor related to this frame. The DPU calculates the + address by multiplying this index with the DPU descriptor size and adding + the DPU descriptors base address. The DPU descriptor contains information + specifying the encryption and compression type and contains references to + where encryption keys can be found. */ + A_UINT32 dpu_desc_idx:8; + + /** The result from the binary address search on the ADDR1 of the incoming + frame. See chapter: RXP filter for encoding of this field. */ + A_UINT32 addr1_index:8; + + /** The result from the binary address search on the ADDR2 of the incoming + frame. See chapter: RXP filter for encoding of this field. */ + A_UINT32 addr2_index:8; + + /** The result from the binary address search on the ADDR3 of the incoming + frame. See chapter: RXP filter for encoding of this field. */ + A_UINT32 addr3_index:8; +#else + A_UINT32 addr3_index:8; + A_UINT32 addr2_index:8; + A_UINT32 addr1_index:8; + A_UINT32 dpu_desc_idx:8; +#endif + + /* 0x18 */ +#ifdef BIG_ENDIAN_HOST + + /** Indicates Rate Index of packet received */ + A_UINT32 rate_index:9; + + /** An overview of RXP status information related to receiving the frame.*/ + A_UINT32 rxp_flags_has_fcs_en:1; + A_UINT32 rxp_flags_set_nav:1; + A_UINT32 rxp_flags_clear_nav:1; + A_UINT32 rxp_flags_rmf_keyid_vld:1; + A_UINT32 rxp_flags_addr3_index_invalid:1; + A_UINT32 rxp_flags_addr2_index_invalid:1; + A_UINT32 rxp_flags_addr1_index_invalid:1; + A_UINT32 rxp_flags_errored_rmf_frame:1; + A_UINT32 rxp_flags_ampdu_flag:1; + A_UINT32 rxp_flags_rmf_keyid:3; + A_UINT32 rxp_flags_last_mpdu:1; + A_UINT32 rxp_flags_first_mpdu:1; + A_UINT32 rxp_flags_has_phy_cmd:1; + A_UINT32 rxp_flags_has_phy_stats:1; + A_UINT32 rxp_flags_has_dlm:1; + A_UINT32 rxp_flags_byp_dlm_proc:1; + A_UINT32 rxp_flags_byp_mpdu_proc:1; + A_UINT32 rxp_flags_fail_filter:1; + A_UINT32 rxp_flags_fail_max_ptklen:1; + A_UINT32 rxp_flags_fcs_err:1; + A_UINT32 rxp_flags_err:1; + +#else + + A_UINT32 rxp_flags_err:1; + A_UINT32 rxp_flags_fcs_err:1; + A_UINT32 rxp_flags_fail_max_ptklen:1; + A_UINT32 rxp_flags_fail_filter:1; + A_UINT32 rxp_flags_byp_mpdu_proc:1; + A_UINT32 rxp_flags_byp_dlm_proc:1; + A_UINT32 rxp_flags_has_dlm:1; + A_UINT32 rxp_flags_has_phy_stats:1; + A_UINT32 rxp_flags_has_phy_cmd:1; + A_UINT32 rxp_flags_first_mpdu:1; + A_UINT32 rxp_flags_last_mpdu:1; + A_UINT32 rxp_flags_rmf_keyid:3; + A_UINT32 rxp_flags_ampdu_flag:1; + A_UINT32 rxp_flags_errored_rmf_frame:1; + A_UINT32 rxp_flags_addr1_index_invalid:1; + A_UINT32 rxp_flags_addr2_index_invalid:1; + A_UINT32 rxp_flags_addr3_index_invalid:1; + A_UINT32 rxp_flags_rmf_keyid_vld:1; + A_UINT32 rxp_flags_clear_nav:1; + A_UINT32 rxp_flags_set_nav:1; + A_UINT32 rxp_flags_has_fcs_en:1; + + A_UINT32 rate_index:9; + +#endif + /* 0x1c */ + /** The PHY can be programmed to put all the PHY STATS received from the + PHY when receiving a frame in the BD. */ +#ifdef BIG_ENDIAN_HOST + A_UINT32 rssi0:8; + A_UINT32 rssi1:8; + A_UINT32 rssi2:8; + A_UINT32 rssi3:8; +#else + A_UINT32 rssi3:8; + A_UINT32 rssi2:8; + A_UINT32 rssi1:8; + A_UINT32 rssi0:8; +#endif + + /* 0x20 */ + A_UINT32 phy_stats1; /* PHY status word 1: snr */ + + /* 0x24 */ + /** The value of the TSF[31:0] bits at the moment that the RXP start + receiving a frame from the PHY RX. */ + A_UINT32 rx_timestamp; /* Rx timestamp, microsecond based*/ + + /* 0x28~0x38 */ + /** The bits from the PMI command as received from the PHY RX. */ + A_UINT32 pmi_cmd4to23[5]; /* PMI cmd rcvd from RxP */ + + /* 0x3c */ + /** The bits from the PMI command as received from the PHY RX. */ +#ifdef QCA_ISOC__PRONTO + +#ifdef BIG_ENDIAN_HOST + /** The bits from the PMI command as received from the PHY RX. */ + A_UINT32 pmi_cmd24to25:16; + + /* 16-bit CSU Checksum value for the fragmented receive frames */ + A_UINT32 csu_checksum:16; +#else + A_UINT32 csu_checksum:16; + A_UINT32 pmi_cmd24to25:16; +#endif + +#else + /** The bits from the PMI command as received from the PHY RX. */ +#ifdef BIG_ENDIAN_HOST + A_UINT32 pmi_cmd24to25:16; + A_UINT32 pmi_cmd26to27:16; +#else + A_UINT32 pmi_cmd26to27:16; + A_UINT32 pmi_cmd24to25:16; +#endif + +#endif // QCA_ISOC__PRONTO + + /* 0x40 */ +#ifdef BIG_ENDIAN_HOST + + /** Gives commands to software upon which host will perform some commands. + Please refer to following RPE document for description of all different + values for this field. */ + A_UINT32 reorder_opcode:4; /* isoc_rx_opcode */ + + A_UINT32 reserved6:12; + + /** Filled by RPE to Indicate to the host up to which slot the host needs + to forward the packets to upper Mac layer. This field mostly used for AMDPU + packets */ + A_UINT32 reorder_fwd_idx:6; + + /** Filled by RPE which indicates to the host which one of slots in the + available 64 slots should the host Queue the packet. This field only + applied to AMPDU packets. */ + A_UINT32 reorder_slot_idx:6; + + A_UINT32 reserved7: 2; + //ToDo: Add meaning to the bits + A_UINT32 out_of_order_forward: 1; + A_UINT32 reorder_enable: 1; + +#else + + A_UINT32 reorder_enable: 1; + A_UINT32 out_of_order_forward: 1; + A_UINT32 reserved7: 2; + + A_UINT32 reorder_slot_idx:6; + A_UINT32 reorder_fwd_idx:6; + A_UINT32 reserved6:12; + A_UINT32 reorder_opcode:4; +#endif + + /* 0x44 */ +#ifdef BIG_ENDIAN_HOST + /** reserved8 from a hardware perspective. + Used by SW to propogate frame type/subtype information */ + A_UINT32 frame_type_subtype:8; + + /** Filled RPE gives the current sequence number in bitmap */ + A_UINT32 current_pkt_seqno:12; + + /** Filled by RPE which gives the sequence number of next expected packet + in bitmap */ + A_UINT32 expected_pkt_seqno:12; +#else + A_UINT32 expected_pkt_seqno:12; + A_UINT32 current_pkt_seqno:12; + A_UINT32 frame_type_subtype:8; +#endif + + /* 0x48 */ +#ifdef BIG_ENDIAN_HOST + + /** When set it is the AMSDU subframe */ + A_UINT32 amsdu:1; + + /** When set it is the First subframe of the AMSDU packet */ + A_UINT32 amsdu_first:1; + + /** When set it is the last subframe of the AMSDU packet */ + A_UINT32 amsdu_last:1; + + /** When set it indicates an Errored AMSDU packet */ + A_UINT32 amsdu_error:1; + + A_UINT32 reserved9:4; + + /** It gives the order in which the AMSDU packet is processed + Basically this is a number which increments by one for every AMSDU frame + received. Mainly for debugging purpose. */ + A_UINT32 process_order:4; + + /** It is the order of the subframe of AMSDU that is processed by ADU. + This is reset to 0 when ADU deaggregates the first subframe from a new + AMSDU and increments by 1 for every new subframe deaggregated within the + AMSDU, after it reaches 4'hf it stops incrementing. That means host should + not rely on this field as index for subframe queuing. Theoretically there + can be way more than 16 subframes in an AMSDU. This is only used for debug + purpose, SW should use LSF and FSF bits to determine first and last + subframes. */ + A_UINT32 amsdu_idx:4; + + /** Filled by ADU this is the total AMSDU size */ + A_UINT32 total_amsdu_size:16; +#else + A_UINT32 total_amsdu_size:16; + A_UINT32 amsdu_idx:4; + A_UINT32 process_order:4; + A_UINT32 reserved9:4; + A_UINT32 amsdu_error:1; + A_UINT32 amsdu_last:1; + A_UINT32 amsdu_first:1; + A_UINT32 amsdu:1; +#endif + +} isoc_rx_bd_t; + + +/** +* @brief specify whether to process or defer rx MPDUs +* @details +* The rx reorder opcode indicates which rx MPDUs should be deferred, +* due to prior MPDUs that have not yet arrived, and which shoudl be +* processed, due to having all prior MPDUs already received. +* The possibilities are: +* - There were no missing MPDUs, and a new in-order MPDU is received: +* release the new MPDU +* - A single missing MPDU is received: +* release the queued old MPDUs that were waiting on this new MPDU, +* and also release this new MPDU +* - A MPDU that is not the initial missing MPDU is received: +* store the new MPDU in the rx reordering queue until missing +* prior MPDUs have been received +* - A new MPDU shifts the block ack window, and one of the following... +* - All old MPDUs are no longer covered by the shifted block ack +* window. +* Release all old MPDUs, and store the new MPDU. +* - The missing MPDU that old MPDUs were waiting for is no longer +* covered by the shifted block ack window. Release all such +* old MPDUs, and if the new MPDU is in-order, release it too. +* - Some old MPDUs are still covered by the shifted block ack +* window, and so is a missing MPDU preceding the old MPDUs. +* Any old MPDUs that are no longer covered by the shifted block +* ack window are released, as are any old MPDUs that don't have +* any missing prior MPDU. All remaing MPDUs, including the new +* MPDU, are left queued in the rx reorder array. +* - A block ack request control message causes the block ack window +* to shift: release queued MPDUs that are no longer covered by the +* shifted block ack window. +*/ +typedef enum +{ + ISOC_RX_OPCODE_INVALID = 0, + + /* QUEUECUR_FWDBUF + * The new MPDU fills a hole (or is at the front of the block ack + * window) - release any buffered MPDUs that were waiting for this + * new MPDU (and then release this new MPDU too). + */ + ISOC_RX_OPCODE_QUEUECUR_FWDBUF = 1, + + /* FWDBUF_FWDCUR + * The new MPDU shifts the block ack window, causing all old MPDUs + * to no longer be within the shifted block ack window. + * Thus, all bufferend MPDUs are released. Since the new MPDU is at + * the front of the shifted block ack window, it too is released. + */ + ISOC_RX_OPCODE_FWDBUF_FWDCUR = 2, + + /* QUEUECUR + * The new MPDU is waiting for missing prior MPDUs. + */ + ISOC_RX_OPCODE_QUEUECUR = 3, + + /* FWDBUF_QUEUECUR + * The new MPDU results in the block ack window being shifted, + * and the new MPDU's position within the new block ack window + * potentially falls on top of an old MPDU's position within the + * old block ack window. + * The new MPDU is waiting for a missing prior MPDU that falls within + * the new position of the block ack window. + * Thus, first release all the MPDUs that are no longer covered by the + * shifted block ack window, then store the new MPDU. + * This is the same as FWDALL_QUEUECUR, except that in this case some + * of the old MPDUs still are covered by the shifted block ack window + * and have a missing MPDU that they are waiting for. + */ + ISOC_RX_OPCODE_FWDBUF_QUEUECUR = 4, + + /* FWDBUF_DROPCUR + * A block ack request control message shifts the block ack window, + * causing some of the queued MPDUs to be no longer covered by the + * shifted block ack window. + * Release these MPDUs that are no longer within the block ack window, + * and any MPDUs that are at the start of the new window, while retaining + * MPDUs within the window that are preceded by a missing MPDU. + */ + ISOC_RX_OPCODE_FWDBUF_DROPCUR = 5, + + /* FWDALL_DROPCUR + * A block ack request control message shifts the block ack window, + * causing all of the queued MPDUs to be no longer covered by the + * shifted block ack window. Release all queued MPDUs. + */ + ISOC_RX_OPCODE_FWDALL_DROPCUR = 6, + + /* FWDALL_QUEUECUR + * This is equivalent to FWDBUF_QUEUECUR, but all old MPDUs are released, + * either becaues they all are no longer covered by the shifted block ack + * window, or because the missing MPDU they were waiting for is no longer + * covered by the shifted block ack window, so though (some of) the old + * MPDUs are still covered by the shifted block ack window, they no longer + * have a missing prior MPDU within the block ack window. + */ + ISOC_RX_OPCODE_FWDALL_QUEUECUR = 7, + + ISOC_RX_OPCODE_TEARDOWN = 8, /* not used? */ + + ISOC_RX_OPCODE_DROPCUR = 9, /* not used? */ + + ISOC_RX_OPCODE_MAX +} isoc_rx_opcode; + + +/* bd_type defined */ +enum { + ISOC_BD_TYPE_GENERIC = 0, + ISOC_BD_TYPE_DEFRAG = 1, +}; + +/* dpu_feedback defined */ +enum { + ISOC_DPU_FEEDBACK_MULTI_ERROR = 0, /* DPU detected multiple errors. Should never occur. */ + ISOC_DPU_FEEDBACK_BAD_TAG, /* Tag fields in the BD and associated DPU descriptor did not match. */ + ISOC_DPU_FEEDBACK_BAD_BD, /* At least one of the following conditions applied: + * The BD type was not 0 (normal BD) in a TX packet. + * The BD type was not either 0 or 1 (normal or defrag BD) in an RX packet. + * The MPDU Length field was less than the MPDU Header Length field. + * The MPDU header was not located entirely within the BD. + * The MPDU Data Offset pointed past the end of the first PDU. + */ + ISOC_DPU_FEEDBACK_BAD_TKIP_MIC, /* The TKIP MIC of a received packet is incorrect. */ + ISOC_DPU_FEEDBACK_BAD_DECRYPT, /* Decryption of an RX fragment has failed.This error occurs only if none of the following more specific conditions applied. */ + ISOC_DPU_FEEDBACK_ENVELOPE_ONLY, /* The received protected fragment had exactly sufficient MPDU data for an empty cryptographic envelope of the selected encryption mode. */ + ISOC_DPU_FEEDBACK_ENVELOPE_PART, /* The received protected fragment had less MPDU data than required for the cryptographic envelope of the selected encryption mode. */ + ISOC_DPU_FEEDBACK_ZERO_LENGTH, /* The received fragment had no MPDU data at all. */ + ISOC_DPU_FEEDBACK_BAD_EXTIV, /* The received AES or TKIP fragment did not have the EXTIV bit set in the IV field of the cryptographic envelope. */ + ISOC_DPU_FEEDBACK_BAD_KID, /* The KID field extracted from the received fragment did not match that in the DPU descriptor (or the BD for WEP encryption modes). */ + ISOC_DPU_FEEDBACK_BAD_WEP_SEED, /* The received TKIP fragment�s computed WEP Seed did not match that in the IV. */ + ISOC_DPU_FEEDBACK_UNPROTECTED, /* The received packet was unprotected, but the associated DPU descriptor had encryption enabled. */ + ISOC_DPU_FEEDBACK_PROTECTED, /* The received packet was protected, but the associated DPU descriptor did not have an encryption mode enabled. */ + ISOC_DPU_FEEDBACK_BAD_REPLAY, /* The received packet failed replay count checking. */ + ISOC_DPU_FEEDBACK_DPU_STALL, /* The DPU stalled with a watchdog timeout and the forced packet completion event occurred. */ + ISOC_DPU_FEEDBACK_WAPI_WAI_FRAME, /* If the encryption mode is WAPI and the recived frame is WAI */ +}; + +/** +* @brief isoc_tx_bd_t - the format of the "TX BD" (tx buffer descriptor) +*/ +typedef struct +{ + /* byte offset 0x0 */ +#ifdef BIG_ENDIAN_HOST + /** + * (Only used by the DPU) This routing flag indicates the WQ number to + * which the DPU will push the frame after it finished processing it. + */ + A_UINT32 dpu_routing_flag: 8; + + /** + * DPU signature + * The DPU signature is used by the Tx MAC HW for a sanity check + * that the specified DPU index (i.e. security key ID) is valid. + */ + A_UINT32 dpu_signature: 3; + + /** Reserved */ + A_UINT32 reserved0:2; + + /** Set to '1' to terminate the current AMPDU session. Added based on the + request for WiFi Display */ + A_UINT32 terminate_ampdu:1; + + /** Bssid index to indicate ADU to use which of the 4 default MAC address + to use while 802.3 to 802.11 translation in case search in ADU UMA table + fails. The default MAC address should be appropriately programmed in the + uma_tx_default_wmacaddr_u(_1,_2,_3) and uma_tx_default_wmacaddr_l(_1,_2,_3) + registers */ + A_UINT32 uma_bssid_idx:2; + + /** Set to 1 to enable uma filling the BD when FT is not enabled. + Ignored when FT is enabled. */ + A_UINT32 uma_bd_enable:1; + + /** (Only used by the CSU) + 0: No action + 1: Host will indicate TCP/UPD header start location and provide pseudo header value in BD. + */ + A_UINT32 csu_sw_mode:1; + + /** Enable/Disable CSU on TX direction. + 0: Disable Checksum Unit (CSU) for Transmit. + 1: Enable + */ + A_UINT32 csu_tx_enable:1; + + /** Enable/Disable Transport layer Checksum in CSU + 0: Disable TCP UDP checksum generation for TX. + 1: Enable TCP UDP checksum generation for TX. + */ + A_UINT32 csu_enable_tl_checksum:1; + + /** Enable/Disable IP layer Checksum in CSU + 0: Disable IPv4/IPv6 checksum generation for TX + 1: Enable IPv4/IPv6 checksum generation for TX + */ + A_UINT32 csu_enable_ip_checksum:1; + + /** Filled by CSU to indicate whether transport layer Checksum is generated by CSU or not + 0: TCP/UDP checksum is being generated for TX. + 1: TCP/UDP checksum is NOT being generated for TX. + */ + A_UINT32 csu_tl_checksum_generated:1; + + /** Filled by CSU in error scenario + 1: No valid header found during parsing. Therefore no checksum was validated. + 0: Valid header found + */ + A_UINT32 csu_no_valid_header:1; + + /** + * Robust Management Frames + * This bit indicates to DPU that the packet is a robust management + * frame which requires encryption (this bit is only valid for + * certain management frames) + * 1 - Needs encryption + * 0 - No encrytion required + * It is only set when Privacy bit=1 AND type/subtype=Deauth, Action, + * Disassoc. Otherwise it should always be 0. + */ + A_UINT32 robust_mgmt: 1; + + /** + * This 1-bit field indicates to DPU Unicast/BC/MC packet + * 0 - Unicast packet + * 1 - Broadcast/Multicast packet + * This bit is valid only if RMF bit is set + */ + A_UINT32 not_unicast: 1; + + A_UINT32 reserved1: 1; + + /** + * This bit indicates TPE has to assert the TX complete interrupt. + * 0 - no interrupt + * 1 - generate interrupt */ + A_UINT32 tx_complete_intr: 1; + + A_UINT32 fw_tx_complete_intr: 1; + + /** + * No encryption/decryption + * 0: No action + * 1: DPU will not encrypt/decrypt the frame, and discard any encryption + * related settings in the PDU descriptor. + * (Only used by the DPU) + */ + A_UINT32 dpu_no_encrypt: 1; + + /** + * This bit indicates to ADU/UMA module that the packet requires 802.11n + * to 802.3 frame translation. When used by ADU + * 0 - No frame translation required + * 1 - Frame Translation required + */ + A_UINT32 frame_translate: 1; + + /** + * BD Type + * 00: 'Generic BD', as indicted above + * 01: De-fragmentation format + * 10-11: Reserved for future use. + */ + A_UINT32 bd_type: 2; +#else + A_UINT32 bd_type: 2; + A_UINT32 frame_translate: 1; + A_UINT32 dpu_no_encrypt: 1; + A_UINT32 fw_tx_complete_intr: 1; + A_UINT32 tx_complete_intr: 1; + A_UINT32 reserved1: 1; + A_UINT32 not_unicast: 1; + A_UINT32 robust_mgmt: 1; + + A_UINT32 csu_no_valid_header:1; + A_UINT32 csu_tl_checksum_generated:1; + A_UINT32 csu_enable_ip_checksum:1; + A_UINT32 csu_enable_tl_checksum:1; + A_UINT32 csu_tx_enable:1; + A_UINT32 csu_sw_mode:1; + A_UINT32 uma_bd_enable:1; + A_UINT32 uma_bssid_idx:2; + A_UINT32 terminate_ampdu:1; + A_UINT32 reserved0:2; + + A_UINT32 dpu_signature: 3; + A_UINT32 dpu_routing_flag: 8; +#endif + + /* byte offset 0x4 */ +#ifdef BIG_ENDIAN_HOST + A_UINT32 reserved2: 16; /* MUST BE 0 otherwise triggers BMU error*/ + A_UINT32 adu_feedback: 8; + /* DPU feedback in Tx path.*/ + A_UINT32 dpu_feedback: 8; + +#else + A_UINT32 dpu_feedback: 8; + A_UINT32 adu_feedback: 8; + A_UINT32 reserved2: 16; +#endif + + /* byte offset 0x8 */ +#ifdef BIG_ENDIAN_HOST + /** + * head PDU index + * It is initially filled by DXE then if encryption is on, + * then DPU will overwrite these fields. + * In case PDUs are linked to the BD, this field indicates + * the index of the first PDU linked to the BD. + * When PDU count is zero, this field has an undefined value. + */ + A_UINT32 head_pdu_idx: 16; + + /** + * head PDU index + * It is initially filled by DXE then if encryption is on, + * then DPU will overwrite these fields. + * In case PDUs are linked to the BD, this field indicates + * the index of the last PDU. + * When PDU count is zero, this field has an undefined value. + */ + A_UINT32 tail_pdu_idx: 16; +#else + A_UINT32 tail_pdu_idx: 16; + A_UINT32 head_pdu_idx: 16; +#endif + + /* byte offset 0xc */ +#ifdef BIG_ENDIAN_HOST + /** + * The length (in number of bytes) of the MPDU header. + * Limitation: The MPDU header offset + MPDU header length + * can never go beyond the end of the first PDU + */ + A_UINT32 mpdu_header_length: 8; + + /** + * The start byte number of the MPDU header. + * The byte numbering is done in the BE format. + * Word 0x0, bits [31:24] has byte index 0. + */ + A_UINT32 mpdu_header_offset: 8; + + /** + * The start byte number of the MPDU data. + * The byte numbering is done in the BE format. + * Word 0x0, bits [31:24] has byte index 0. + * Note that this offset can point all the way into the + * first linked PDU. + * Limitation: MPDU DATA OFFSET can not point into the + * 2nd linked PDU + */ + A_UINT32 mpdu_data_offset: 9; + + /** + * PDU count + * It is initially filled by DXE then if encryption is on, + * DPU will overwrite these fields. + * The number of PDUs linked to the BD. + * This field should always indicate the correct amount. + */ + A_UINT32 pdu_count: 7; +#else + A_UINT32 pdu_count: 7; + A_UINT32 mpdu_data_offset: 9; + A_UINT32 mpdu_header_offset: 8; + A_UINT32 mpdu_header_length: 8; +#endif + + /* byte offset 0x10 */ +#ifdef BIG_ENDIAN_HOST + /** + * This covers MPDU header length + MPDU data length. + * This does not include FCS. + * For single frame transmission, PSDU size is mpdu_length + 4. + */ + A_UINT32 mpdu_length: 16; + + A_UINT32 reserved3: 2; + + /** + * Sequence number insertion by DPU + * 00: Leave sequence number as is, as filled by host + * 01: DPU to insert non TID based sequence number + * (If not TID based, then how does DPU know what seq to fill? + * Is this the non-Qos/Mgmt sequence number?) + * 10: DPU to insert a sequence number based on TID. + * 11: Reserved + */ + A_UINT32 bd_seq_num_src:2; + + /** + * Traffic Identifier + * Indicates the traffic class the frame belongs to. + * For non QoS frames, this field is set to zero. + */ + A_UINT32 tid: 4; + + A_UINT32 reserved4: 8; +#else + A_UINT32 reserved4: 8; + A_UINT32 tid: 4; + A_UINT32 bd_seq_num_src: 2; + A_UINT32 reserved3: 2; + A_UINT32 mpdu_length: 16; +#endif + + /* byte offset 0x14 */ +#ifdef BIG_ENDIAN_HOST + /** + * (Only used by the DPU) + * The DPU descriptor index is used to calculate where in + * memory the DPU can find the DPU descriptor related to this frame. + * The DPU calculates the address by multiplying this index + * with the DPU descriptor size and adding the DPU descriptor + * array's base address. + * The DPU descriptor contains information specifying the encryption + * and compression type and contains references to where encryption + * keys can be found. + */ + A_UINT32 dpu_desc_idx: 8; + + /** + * The STAid of the RA address, a.k.a. peer ID + */ + A_UINT32 sta_index: 8; + + /** + * A field passed on to TPE which influences the ACK policy + * to be used for this frame + * 00 - ack + * 01,10,11 - No Ack + */ + A_UINT32 ack_policy: 2; + + /** + * Overwrite option for the transmit rate + * 00: Use rate programmed in the TPE STA descriptor + * 01: Use TPE BD rate 1 + * 10: Use TPE BD rate 2 + * 11: Delayed Use TPE BD rate 3 + */ + A_UINT32 bd_rate: 2; + + /** + * Which HW tx queue the frame should go into + */ + A_UINT32 queue_id: 5; + + A_UINT32 reserved5: 7; +#else + A_UINT32 reserved5: 7; + A_UINT32 queue_id: 5; + A_UINT32 bd_rate: 2; + A_UINT32 ack_policy: 2; + A_UINT32 sta_index: 8; + A_UINT32 dpu_desc_idx: 8; +#endif + + /* byte offset 0x18 */ + A_UINT32 tx_bd_signature; + + /* byte offset 0x1c */ + A_UINT32 reserved6; + + /* byte offset 0x20 */ + /* Timestamp filled by DXE. Timestamp for current transfer */ + A_UINT32 dxe_h2b_start_timestamp; + + /* byte offset 0x24 */ + /* Timestamp filled by DXE. Timestamp for previous transfer */ + A_UINT32 dxe_h2b_end_timestamp; + +#ifdef QCA_ISOC_PRONTO + + /* byte offset 0x28 */ +#ifdef BIG_ENDIAN_HOST + /** 10 bit value to indicate the start of TCP UDP frame relative to + * the first IP frame header */ + A_UINT32 csu_tcp_udp_start_offset:10; + + /** 16 bit pseudo header for TCP UDP used by CSU to generate TCP/UDP + * frame checksum */ + A_UINT32 csu_pseudo_header_checksum:16; + + A_UINT32 reserved7:6; +#else + A_UINT32 reserved7:6; + A_UINT32 csu_pseudo_header_checksum:16; + A_UINT32 csu_tcp_udp_start_offset:10; +#endif + +#endif /*QCA_ISOC_PRONTO*/ + +} isoc_tx_bd_t; + +/** +* @brief utility function to swap bytes within a series of u_int32_t words +* @details +* This function swaps bytes 0 <-> 3 and bytes 1 <-> 2 within each 4-byte +* word within a specified address range. +* The address range is assumed to be aligned to a 4-byte boundary, and +* to have a length that is a multiple of 4 bytes. +* This function can be used for endianness correction - after swapping +* the bytes within a 4-byte word, the native u_int32_t value will have +* bitfields within the u_int32_t word in the expected positions. +* For example, if a structure that is initially stored in big-endian +* format needs to be interpreted in a little-endian processor: +* +* original 32-bit word: +* bit number +* 31 24 23 16 15 8 7 0 +* |--------------+----------------+----------------+---------------| +* | C | B | A_hi | A_lo | +* |--------------+----------------+----------------+---------------| +* +* stored in +* big-endian format: +* byte contents +* +---------+ +---------+ +* 0 | C | | A_lo | +* +---------+ +---------+ +* 1 | B | byte-swapped | A_hi | +* +---------+ ================> +---------+ +* 2 | A_hi | | B | +* +---------+ +---------+ +* 3 | A_lo | | C | +* +---------+ +---------+ +* +* byte-swapped values read into a 32-bit word on a little-endian processor: +* bit number +* 31 24 23 16 15 8 7 0 +* |--------------+----------------+----------------+---------------| +* | C | B | A_hi | A_lo | +* |--------------+----------------+----------------+---------------| +*/ +static inline void + isoc_hw_bd_swap_bytes32(char *addr, int bytes) +{ + u_int32_t *p32 = (u_int32_t *) addr; + int i, num_words32; + + /* confirm that the address range has the expected alignment */ + adf_os_assert((((unsigned) addr) & 0x3) == 0); + /* confirm that the address range has the expected length quantum */ + adf_os_assert((bytes & 0x3) == 0); + + num_words32 = bytes >> 2; + for (i = 0; i < num_words32; i++, p32++) { + u_int32_t word = *p32; + *p32 = + ((word & 0x000000ff) << 24) | /* move byte 0 --> byte 3 */ + ((word & 0x0000ff00) << 8) | /* move byte 1 --> byte 2 */ + ((word & 0x00ff0000) >> 8) | /* move byte 2 --> byte 1 */ + ((word & 0xff000000) >> 24); /* move byte 3 --> byte 0 */ + } +} + +static inline void + isoc_tx_bd_dump(isoc_tx_bd_t *tx_bd) +{ + char *p; + int i; + + adf_os_print("Tx BD (%p)\n", tx_bd); + + adf_os_print("structured view:\n"); + adf_os_print(" BD type: %d\n", tx_bd->bd_type); + adf_os_print(" frame translate: %d\n", tx_bd->frame_translate); + adf_os_print(" DPU no-encrypt: %d\n", tx_bd->dpu_no_encrypt); + adf_os_print(" FW tx complete intr: %d\n", tx_bd->fw_tx_complete_intr); + adf_os_print(" tx complete intr: %d\n", tx_bd->tx_complete_intr); + adf_os_print(" not unicast: %d\n", tx_bd->not_unicast); + adf_os_print(" robust mgmt: %d\n", tx_bd->robust_mgmt); + adf_os_print(" DPU signature: %d\n", tx_bd->dpu_signature); + adf_os_print(" DPU routing flag: %d\n", tx_bd->dpu_routing_flag); + adf_os_print(" DPU feedback: %#x\n", tx_bd->dpu_feedback); + adf_os_print(" ADU feedback: %#x\n", tx_bd->adu_feedback); + adf_os_print(" tail PDU idx: %d\n", tx_bd->tail_pdu_idx); + adf_os_print(" head PDU idx: %d\n", tx_bd->head_pdu_idx); + adf_os_print(" PDU count: %d\n", tx_bd->pdu_count); + adf_os_print(" MPDU data offset: %d\n", tx_bd->mpdu_data_offset); + adf_os_print(" MPDU header offset: %d\n", tx_bd->mpdu_header_offset); + adf_os_print(" MPDU header length: %d\n", tx_bd->mpdu_header_length); + adf_os_print(" TID: %d\n", tx_bd->tid); + adf_os_print(" BD seq num src: %d\n", tx_bd->bd_seq_num_src); + adf_os_print(" MPDU length: %d\n", tx_bd->mpdu_length); + adf_os_print(" queue ID: %d\n", tx_bd->queue_id); + adf_os_print(" BD rate: %d\n", tx_bd->bd_rate); + adf_os_print(" ack policy: %d\n", tx_bd->ack_policy); + adf_os_print(" STA index: %d\n", tx_bd->sta_index); + adf_os_print(" DPU desc idx: %d\n", tx_bd->dpu_desc_idx); + adf_os_print(" Tx BD signature: %d\n", tx_bd->tx_bd_signature); + adf_os_print(" DXE start timestamp: %d\n", tx_bd->dxe_h2b_start_timestamp); + adf_os_print(" DXE end timestamp: %d\n", tx_bd->dxe_h2b_end_timestamp); + + adf_os_print("raw view:\n "); + p = (char *) tx_bd; + for (i = 0; i < sizeof(*tx_bd); i++, p++) { + adf_os_print("%#02x ", *p); + if ((i+1) % 8 == 0) { + adf_os_print("\n "); + } + } + adf_os_print("\n"); +} + +static inline void + isoc_rx_bd_dump(isoc_rx_bd_t *rx_bd) +{ + char *p; + int i; + + adf_os_print("Rx BD (%p)\n", rx_bd); + + adf_os_print("structured view:\n"); + adf_os_print(" BD type: %d\n", rx_bd->bd_type); + adf_os_print(" frame translate: %d\n", rx_bd->frame_translate); + adf_os_print(" DPU no-encrypt: %d\n", rx_bd->dpu_no_encrypt); + adf_os_print(" not unicast: %d\n", rx_bd->not_unicast); + adf_os_print(" robust mgmt: %d\n", rx_bd->robust_mgmt); + adf_os_print(" LLC removed: %d\n", rx_bd->llc_removed); + adf_os_print(" DPU signature: %d\n", rx_bd->dpu_signature); + adf_os_print(" DPU routing flag: %d\n", rx_bd->dpu_routing_flag); + adf_os_print(" addr1 index: %d\n", rx_bd->addr1_index); + adf_os_print(" addr2 index invalid: %d\n", rx_bd->addr2_invalid); + adf_os_print(" addr2 index: %d\n", rx_bd->addr2_index); + adf_os_print(" addr3 index: %d\n", rx_bd->addr3_index); + adf_os_print(" DPU feedback: %#x\n", rx_bd->dpu_feedback); + adf_os_print(" ADU feedback: %#x\n", rx_bd->adu_feedback); + adf_os_print(" tail PDU idx: %d\n", rx_bd->tail_pdu_idx); + adf_os_print(" head PDU idx: %d\n", rx_bd->head_pdu_idx); + adf_os_print(" PDU count: %d\n", rx_bd->pdu_count); + adf_os_print(" MPDU data offset: %d\n", rx_bd->mpdu_data_offset); + adf_os_print(" MPDU header offset: %d\n", rx_bd->mpdu_header_offset); + adf_os_print(" MPDU header length: %d\n", rx_bd->mpdu_header_length); + adf_os_print(" TID: %d\n", rx_bd->tid); + adf_os_print(" MPDU length: %d\n", rx_bd->mpdu_length); + adf_os_print(" DPU desc idx: %d\n", rx_bd->dpu_desc_idx); + adf_os_print(" HTT T2H Msg: %d\n", rx_bd->htt_t2h_msg); + adf_os_print(" Flow Control: %d\n", rx_bd->flow_control); + adf_os_print(" Current Pkt Sequence No: %d\n", rx_bd->current_pkt_seqno); + adf_os_print(" Expected Pkt Sequence No: %d\n", rx_bd->expected_pkt_seqno); + adf_os_print(" frame subtype: %d\n", rx_bd->frame_type_subtype); + adf_os_print(" RSSI0: %d\n", rx_bd->rssi0); + adf_os_print(" reorder opcode: %d\n", rx_bd->reorder_opcode); + adf_os_print(" reorder fwd index: %d\n", rx_bd->reorder_fwd_idx); + adf_os_print(" reorder slot index: %d\n", rx_bd->reorder_slot_idx); + adf_os_print(" AMSDU Size: %d\n", rx_bd->total_amsdu_size); + adf_os_print(" AMSDU IDX: %d\n", rx_bd->amsdu_idx); + adf_os_print(" AMSDU: %d\n", rx_bd->amsdu); + adf_os_print(" AMSDU first subfrm: %d\n", rx_bd->amsdu_first); + adf_os_print(" AMSDU last subfrm: %d\n", rx_bd->amsdu_last); + adf_os_print(" AMSDU error: %d\n", rx_bd->amsdu_error); + adf_os_print(" RX timestamp: %d\n", rx_bd->rx_timestamp); + + adf_os_print("raw view start:\n "); + p = (char *) rx_bd; + for (i = 0; i < sizeof(*rx_bd); i++, p++) { + adf_os_print("%#02x ", *p); + if ((i+1) % 8 == 0) { + adf_os_print("\n "); + } + } + adf_os_print("raw view end\n"); +} + +#endif /* _ISOC_HW_DESC__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_cfg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_cfg.h new file mode 100644 index 000000000000..af5448db9c32 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_cfg.h @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_CFG__H_ +#define _OL_CFG__H_ + +#include /* u_int32_t */ +#include /* ol_pdev_handle */ +#include "ieee80211_common.h" /* ieee80211_qosframe_htc_addr4 */ +#include /* LLC_SNAP_HDR_LEN */ + +#if defined(CONFIG_HL_SUPPORT) +#include "wlan_tgt_def_config_hl.h" +#else +#include "wlan_tgt_def_config.h" +#endif + +/** + * @brief format of data frames delivered to/from the WLAN driver by/to the OS + */ +enum wlan_frm_fmt { + wlan_frm_fmt_unknown, + wlan_frm_fmt_raw, + wlan_frm_fmt_native_wifi, + wlan_frm_fmt_802_3, +}; + +#ifdef IPA_UC_OFFLOAD +struct wlan_ipa_uc_rsc_t { + u8 uc_offload_enabled; + u32 tx_max_buf_cnt; + u32 tx_buf_size; + u32 rx_ind_ring_size; + u32 tx_partition_base; +}; +#endif /* IPA_UC_OFFLOAD */ + +/* Config parameters for txrx_pdev */ +struct txrx_pdev_cfg_t { + u8 is_high_latency; + u8 defrag_timeout_check; + u8 rx_pn_check; + u8 pn_rx_fwd_check; + u8 host_addba; + u8 tx_free_at_download; + u8 rx_fwd_inter_bss; + u32 max_thruput_mbps; + u32 target_tx_credit; + u32 vow_config; + u32 tx_download_size; + u32 max_peer_id; + u32 max_vdev; + u32 max_nbuf_frags; + u32 throttle_period_ms; + enum wlan_frm_fmt frame_type; + u8 rx_fwd_disabled; + u8 is_packet_log_enabled; + u8 is_full_reorder_offload; +#ifdef IPA_UC_OFFLOAD + struct wlan_ipa_uc_rsc_t ipa_uc_rsc; +#endif /* IPA_UC_OFFLOAD */ +}; + +/** + * @brief Specify whether the system is high-latency or low-latency. + * @details + * Indicate whether the system is operating in high-latency (message + * based, e.g. USB) mode or low-latency (memory-mapped, e.g. PCIe) mode. + * Some chips support just one type of host / target interface. + * Other chips support both LL and HL interfaces (e.g. PCIe and USB), + * so the selection will be made based on which bus HW is present, or + * which is preferred if both are present. + * + * @param pdev - handle to the physical device + * @return 1 -> high-latency -OR- 0 -> low-latency + */ +int ol_cfg_is_high_latency(ol_pdev_handle pdev); + +/** + * @brief Specify the range of peer IDs. + * @details + * Specify the maximum peer ID. This is the maximum number of peers, + * minus one. + * This is used by the host to determine the size of arrays indexed by + * peer ID. + * + * @param pdev - handle to the physical device + * @return maximum peer ID + */ +int ol_cfg_max_peer_id(ol_pdev_handle pdev); + +/** + * @brief Specify the max number of virtual devices within a physical device. + * @details + * Specify how many virtual devices may exist within a physical device. + * + * @param pdev - handle to the physical device + * @return maximum number of virtual devices + */ +int ol_cfg_max_vdevs(ol_pdev_handle pdev); + +/** + * @brief Check whether host-side rx PN check is enabled or disabled. + * @details + * Choose whether to allocate rx PN state information and perform + * rx PN checks (if applicable, based on security type) on the host. + * If the rx PN check is specified to be done on the host, the host SW + * will determine which peers are using a security type (e.g. CCMP) that + * requires a PN check. + * + * @param pdev - handle to the physical device + * @return 1 -> host performs rx PN check -OR- 0 -> no host-side rx PN check + */ +int ol_cfg_rx_pn_check(ol_pdev_handle pdev); + + +/** + * @brief Check whether host-side rx forwarding is enabled or disabled. + * @details + * Choose whether to check whether to forward rx frames to tx on the host. + * For LL systems, this rx -> tx host-side forwarding check is typically + * enabled. + * For HL systems, the rx -> tx forwarding check is typically done on the + * target. However, even in HL systems, the host-side rx -> tx forwarding + * will typically be enabled, as a second-tier safety net in case the + * target doesn't have enough memory to store all rx -> tx forwarded frames. + * + * @param pdev - handle to the physical device + * @return 1 -> host does rx->tx forward -OR- 0 -> no host-side rx->tx forward + */ +int ol_cfg_rx_fwd_check(ol_pdev_handle pdev); + +/** + * @brief set rx fwd disable/enable. + * @details + * Choose whether to forward rx frames to tx (where applicable) within the + * WLAN driver, or to leave all forwarding up to the operating system. + * currently only intra-bss fwd is supported. + * + * @param pdev - handle to the physical device + * @param disable_rx_fwd 1 -> no rx->tx forward -> rx->tx forward + */ +void ol_set_cfg_rx_fwd_disabled(ol_pdev_handle pdev, u_int8_t disalbe_rx_fwd); + +/** + * @brief Check whether rx forwarding is enabled or disabled. + * @details + * Choose whether to forward rx frames to tx (where applicable) within the + * WLAN driver, or to leave all forwarding up to the operating system. + * + * @param pdev - handle to the physical device + * @return 1 -> no rx->tx forward -OR- 0 -> rx->tx forward (in host or target) + */ +int ol_cfg_rx_fwd_disabled(ol_pdev_handle pdev); + +/** + * @brief Check whether to perform inter-BSS or intra-BSS rx->tx forwarding. + * @details + * Check whether data received by an AP on one virtual device destined + * to a STA associated with a different virtual device within the same + * physical device should be forwarded within the driver, or whether + * forwarding should only be done within a virtual device. + * + * @param pdev - handle to the physical device + * @return + * 1 -> forward both within and between vdevs + * -OR- + * 0 -> forward only within a vdev + */ +int ol_cfg_rx_fwd_inter_bss(ol_pdev_handle pdev); + +/** + * @brief Specify data frame format used by the OS. + * @details + * Specify what type of frame (802.3 or native WiFi) the host data SW + * should expect from and provide to the OS shim. + * + * @param pdev - handle to the physical device + * @return enumerated data frame format + */ +enum wlan_frm_fmt ol_cfg_frame_type(ol_pdev_handle pdev); + +/** + * @brief Specify the peak throughput. + * @details + * Specify the peak throughput that a system is expected to support. + * The data SW uses this configuration to help choose the size for its + * tx descriptor pool and rx buffer ring. + * The data SW assumes that the peak throughput applies to either rx or tx, + * rather than having separate specs of the rx max throughput vs. the tx + * max throughput. + * + * @param pdev - handle to the physical device + * @return maximum supported throughput in Mbps (not MBps) + */ +int ol_cfg_max_thruput_mbps(ol_pdev_handle pdev); + + +/** + * @brief Specify the maximum number of fragments per tx network buffer. + * @details + * Specify the maximum number of fragments that a tx frame provided to + * the WLAN driver by the OS may contain. + * In LL systems, the host data SW uses this maximum fragment count to + * determine how many elements to allocate in the fragmentation descriptor + * it creates to specify to the tx MAC DMA where to locate the tx frame's + * data. + * This maximum fragments count is only for regular frames, not TSO frames, + * since TSO frames are sent in segments with a limited number of fragments + * per segment. + * + * @param pdev - handle to the physical device + * @return maximum number of fragments that can occur in a regular tx frame + */ +int ol_cfg_netbuf_frags_max(ol_pdev_handle pdev); + + +/** + * @brief For HL systems, specify when to free tx frames. + * @details + * In LL systems, the host's tx frame is referenced by the MAC DMA, and + * thus cannot be freed until the target indicates that it is finished + * transmitting the frame. + * In HL systems, the entire tx frame is downloaded to the target. + * Consequently, the target has its own copy of the tx frame, and the + * host can free the tx frame as soon as the download completes. + * Alternatively, the HL host can keep the frame allocated until the + * target explicitly tells the HL host it is done transmitting the frame. + * This gives the target the option of discarding its copy of the tx + * frame, and then later getting a new copy from the host. + * This function tells the host whether it should retain its copy of the + * transmit frames until the target explicitly indicates it is finished + * transmitting them, or if it should free its copy as soon as the + * tx frame is downloaded to the target. + * + * @param pdev - handle to the physical device + * @return + * 0 -> retain the tx frame until the target indicates it is done + * transmitting the frame + * -OR- + * 1 -> free the tx frame as soon as the download completes + */ +int ol_cfg_tx_free_at_download(ol_pdev_handle pdev); +void ol_cfg_set_tx_free_at_download(ol_pdev_handle pdev); + +/** + * @brief Low water mark for target tx credit. + * Tx completion handler is invoked to reap the buffers when the target tx + * credit goes below Low Water Mark. + */ +#define OL_CFG_NUM_MSDU_REAP 512 +#define ol_cfg_tx_credit_lwm(pdev) \ + ((CFG_TGT_NUM_MSDU_DESC > OL_CFG_NUM_MSDU_REAP) ? \ + (CFG_TGT_NUM_MSDU_DESC - OL_CFG_NUM_MSDU_REAP) : 0) + +/** + * @brief In a HL system, specify the target initial credit count. + * @details + * The HL host tx data SW includes a module for determining which tx frames + * to download to the target at a given time. + * To make this judgement, the HL tx download scheduler has to know + * how many buffers the HL target has available to hold tx frames. + * Due to the possibility that a single target buffer pool can be shared + * between rx and tx frames, the host may not be able to obtain a precise + * specification of the tx buffer space available in the target, but it + * uses the best estimate, as provided by this configuration function, + * to determine how best to schedule the tx frame downloads. + * + * @param pdev - handle to the physical device + * @return the number of tx buffers available in a HL target + */ +u_int16_t ol_cfg_target_tx_credit(ol_pdev_handle pdev); + + +/** + * @brief Specify the LL tx MSDU header download size. + * @details + * In LL systems, determine how many bytes from a tx frame to download, + * in order to provide the target FW's Descriptor Engine with enough of + * the packet's payload to interpret what kind of traffic this is, + * and who it is for. + * This download size specification does not include the 802.3 / 802.11 + * frame encapsulation headers; it starts with the encapsulated IP packet + * (or whatever ethertype is carried within the ethernet-ish frame). + * The LL host data SW will determine how many bytes of the MSDU header to + * download by adding this download size specification to the size of the + * frame header format specified by the ol_cfg_frame_type configuration + * function. + * + * @param pdev - handle to the physical device + * @return the number of bytes beyond the 802.3 or native WiFi header to + * download to the target for tx classification + */ +int ol_cfg_tx_download_size(ol_pdev_handle pdev); + +/** + * brief Specify where defrag timeout and duplicate detection is handled + * @details + * non-aggregate duplicate detection and timing out stale fragments + * requires additional target memory. To reach max client + * configurations (128+), non-aggregate duplicate detection and the + * logic to time out stale fragments is moved to the host. + * + * @param pdev - handle to the physical device + * @return + * 0 -> target is responsible non-aggregate duplicate detection and + * timing out stale fragments. + * + * 1 -> host is responsible non-aggregate duplicate detection and + * timing out stale fragments. + */ +int ol_cfg_rx_host_defrag_timeout_duplicate_check(ol_pdev_handle pdev); + +/** + * brief Query for the period in ms used for throttling for + * thermal mitigation + * @details + * In LL systems, transmit data throttling is used for thermal + * mitigation where data is paused and resumed during the + * throttle period i.e. the throttle period consists of an + * "on" phase when transmit is allowed and an "off" phase when + * transmit is suspended. This function returns the total + * period used for throttling. + * + * @param pdev - handle to the physical device + * @return the total throttle period in ms + */ +int ol_cfg_throttle_period_ms(ol_pdev_handle pdev); + +/** + * brief Check whether full reorder offload is + * enabled/disable by the host + * @details + * If the host does not support receive reorder (i.e. the + * target performs full receive re-ordering) this will return + * "enabled" + * + * @param pdev - handle to the physical device + * @return 1 - enable, 0 - disable + */ +int ol_cfg_is_full_reorder_offload(ol_pdev_handle pdev); + +typedef enum { + wlan_frm_tran_cap_raw = 0x01, + wlan_frm_tran_cap_native_wifi = 0x02, + wlan_frm_tran_cap_8023 = 0x04, +} wlan_target_fmt_translation_caps; + +/** + * @brief Specify the maximum header size added by SW tx encapsulation + * @details + * This function returns the maximum size of the new L2 header, not the + * difference between the new and old L2 headers. + * Thus, this function returns the maximum 802.11 header size that the + * tx SW may need to add to tx data frames. + * + * @param pdev - handle to the physical device + */ +static inline int +ol_cfg_sw_encap_hdr_max_size(ol_pdev_handle pdev) +{ + /* + * 24 byte basic 802.11 header + * + 6 byte 4th addr + * + 2 byte QoS control + * + 4 byte HT control + * + 8 byte LLC/SNAP + */ + return sizeof(struct ieee80211_qosframe_htc_addr4) + LLC_SNAP_HDR_LEN; +} + +static inline u_int8_t +ol_cfg_tx_encap(ol_pdev_handle pdev) +{ + /* tx encap done in HW */ + return 0; +} + +static inline int +ol_cfg_host_addba(ol_pdev_handle pdev) +{ + /* + * ADDBA negotiation is handled by the target FW for Peregrine + Rome. + */ + return 0; +} + +/** + * @brief If the host SW's ADDBA negotiation fails, should it be retried? + * + * @param pdev - handle to the physical device + */ +static inline int +ol_cfg_addba_retry(ol_pdev_handle pdev) +{ + return 0; /* disabled for now */ +} + +/** + * @brief How many frames to hold in a paused vdev's tx queue in LL systems + */ +static inline int +ol_tx_cfg_max_tx_queue_depth_ll(ol_pdev_handle pdev) +{ + /* + * Store up to 1500 frames for a paused vdev. + * For example, if the vdev is sending 300 Mbps of traffic, and the + * PHY is capable of 600 Mbps, then it will take 56 ms for the PHY to + * drain both the 700 frames that are queued initially, plus the next + * 700 frames that come in while the PHY is catching up. + * So in this example scenario, the PHY will remain fully utilized + * in a MCC system that has a channel-switching period of 56 ms or less. + * 700 frames calculation was correct when FW drain packet without + * any overhead. Actual situation drain overhead will slowdown drain + * speed. And channel period is less than 56 msec + * Worst scenario, 1500 frames should be stored in host. + */ + return 1500; +} + +/** + * @brief Set packet log config in HTT config based on CFG ini configuration + */ +void ol_set_cfg_packet_log_enabled(ol_pdev_handle pdev, u_int8_t val); + +/** + * @brief Get packet log config from HTT config + */ +u_int8_t ol_cfg_is_packet_log_enabled(ol_pdev_handle pdev); + +#ifdef IPA_UC_OFFLOAD +/** + * @brief IPA micro controller data path offload enable or not + * @detail + * This function returns IPA micro controller data path offload + * feature enabled or not + * + * @param pdev - handle to the physical device + */ +unsigned int ol_cfg_ipa_uc_offload_enabled(ol_pdev_handle pdev); +/** + * @brief IPA micro controller data path TX buffer size + * @detail + * This function returns IPA micro controller data path offload + * TX buffer size which should be pre-allocated by driver. + * Default buffer size is 2K + * + * @param pdev - handle to the physical device + */ +unsigned int ol_cfg_ipa_uc_tx_buf_size(ol_pdev_handle pdev); +/** + * @brief IPA micro controller data path TX buffer size + * @detail + * This function returns IPA micro controller data path offload + * TX buffer count which should be pre-allocated by driver. + * + * @param pdev - handle to the physical device + */ +unsigned int ol_cfg_ipa_uc_tx_max_buf_cnt(ol_pdev_handle pdev); +/** + * @brief IPA micro controller data path TX buffer size + * @detail + * This function returns IPA micro controller data path offload + * RX indication ring size which will notified by WLAN FW to IPA + * micro controller + * + * @param pdev - handle to the physical device + */ +unsigned int ol_cfg_ipa_uc_rx_ind_ring_size(ol_pdev_handle pdev); +/** + * @brief IPA micro controller data path TX buffer size + * @param pdev - handle to the physical device + */ +unsigned int ol_cfg_ipa_uc_tx_partition_base(ol_pdev_handle pdev); +#endif /* IPA_UC_OFFLOAD */ +#endif /* _OL_CFG__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_addba_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_addba_api.h new file mode 100644 index 000000000000..4cc20f00fa5c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_addba_api.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _OL_CTRL_ADDBA_API_H_ +#define _OL_CTRL_ADDBA_API_H_ +#define ol_ctrl_addba_attach(a,b,c,d,e) 0 +#define ol_ctrl_addba_detach(a) 0 +#define ol_ctrl_addba_init(a,b,c,d,e) 0 +#define ol_ctrl_addba_cleanup(a) 0 +#define ol_ctrl_addba_request_setup(a,b,c,d,e,f) 0 +#define ol_ctrl_addba_response_setup(a,b,c,d,e,f) 0 +#define ol_ctrl_addba_request_process(a,b,c,d,e) 0 +#define ol_ctrl_addba_response_process(a,b,c,d) 0 +#define ol_ctrl_addba_clear(a) 0 +#define ol_ctrl_delba_process(a,b,c) 0 +#define ol_ctrl_addba_get_status(a,b) 0 +#define ol_ctrl_addba_set_response(a,b,c); 0 +#define ol_ctrl_addba_clear_response(a); 0 +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_api.h new file mode 100644 index 000000000000..9ce5764091e4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_ctrl_api.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_ctrl_api.h + * @brief Definitions used in multiple external interfaces to the control SW. + */ +#ifndef _OL_CTRL_API__H_ +#define _OL_CTRL_API__H_ + +struct ol_pdev_t; +typedef struct ol_pdev_t* ol_pdev_handle; + +struct ol_vdev_t; +typedef struct ol_vdev_t* ol_vdev_handle; + +struct ol_peer_t; +typedef struct ol_peer_t* ol_peer_handle; + +#endif /* _OL_CTRL_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_defines.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_defines.h new file mode 100644 index 000000000000..50166964240e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_defines.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * Offload specific Opaque Data types. + */ +#ifndef _DEV_OL_DEFINES_H +#define _DEV_OL_DEFINES_H + +/** + * @brief Opaque handle of wmi structure + */ +struct wmi_unified; +typedef struct wmi_unified *wmi_unified_t; + +typedef void* ol_scn_t; +/** + * @wmi_event_handler function prototype + */ +typedef int (*wmi_unified_event_handler) (ol_scn_t scn_handle, + u_int8_t *event_buf, + u_int32_t len); + +#endif /* _DEV_OL_DEFINES_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_fw_tx_dbg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_fw_tx_dbg.h new file mode 100644 index 000000000000..e99ddce59399 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_fw_tx_dbg.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_fw_tx_dbg.h + * + * @details data structs used for uploading summary info about the FW's tx + */ + +#ifndef _OL_FW_TX_DBG__H_ +#define _OL_FW_TX_DBG__H_ + +/* + * Undef ATH_SUPPORT_FW_TX_DBG to remove the FW tx debug feature. + * Removing the FW tx debug feature saves a modest amount of program memory. + * The data memory allocation for the FW tx debug feature is controlled + * by the host --> target resource configuration parameters; even if + * ATH_SUPPORT_FW_TX_DBG is defined, no data memory will be allocated for + * the FW tx debug log unless the host --> target resource configuration + * specifies it. + */ +#define ATH_SUPPORT_FW_TX_DBG 1 /* enabled */ +//#undef ATH_SUPPORT_FW_TX_DBG /* disabled */ + + +#if defined(ATH_TARGET) +#include /* A_UINT32 */ +#else +#include /* A_UINT32 */ +#include /* PREPACK, POSTPACK */ +#endif + +enum ol_fw_tx_dbg_log_mode { + ol_fw_tx_dbg_log_mode_wraparound, /* overwrite old data with new */ + ol_fw_tx_dbg_log_mode_single, /* fill log once, then stop */ +}; + +/* + * tx PPDU stats upload message header + */ +struct ol_fw_tx_dbg_ppdu_msg_hdr { + /* word 0 */ + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MPDU_BYTES_WORD 0 + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MPDU_BYTES_S 0 + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MPDU_BYTES_M 0x000000ff + A_UINT8 mpdu_bytes_array_len; /* length of array of per-MPDU byte counts */ + + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MSDU_BYTES_WORD 0 + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MSDU_BYTES_S 8 + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MSDU_BYTES_M 0x0000ff00 + A_UINT8 msdu_bytes_array_len; /* length of array of per-MSDU byte counts */ + + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MPDU_MSDUS_WORD 0 + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MPDU_MSDUS_S 16 + #define OL_FW_TX_DBG_PPDU_HDR_NUM_MPDU_MSDUS_M 0x00ff0000 + A_UINT8 mpdu_msdus_array_len; /* length of array of per-MPDU MSDU counts */ + + A_UINT8 reserved; + + /* word 1 */ + #define OL_FW_TX_DBG_PPDU_HDR_MICROSEC_PER_TICK_WORD 1 + #define OL_FW_TX_DBG_PPDU_HDR_MICROSEC_PER_TICK_S 0 + #define OL_FW_TX_DBG_PPDU_HDR_MICROSEC_PER_TICK_M 0xffffffff + A_UINT32 microsec_per_tick; /* conversion for timestamp entries */ +}; + +/* + * tx PPDU log element / stats upload message element + */ +struct ol_fw_tx_dbg_ppdu_base { + /* word 0 - filled in during tx enqueue */ + #define OL_FW_TX_DBG_PPDU_START_SEQ_NUM_WORD 0 + #define OL_FW_TX_DBG_PPDU_START_SEQ_NUM_S 0 + #define OL_FW_TX_DBG_PPDU_START_SEQ_NUM_M 0x0000ffff + A_UINT16 start_seq_num; + #define OL_FW_TX_DBG_PPDU_START_PN_LSBS_WORD 0 + #define OL_FW_TX_DBG_PPDU_START_PN_LSBS_S 16 + #define OL_FW_TX_DBG_PPDU_START_PN_LSBS_M 0xffff0000 + A_UINT16 start_pn_lsbs; + + /* word 1 - filled in during tx enqueue */ + #define OL_FW_TX_DBG_PPDU_NUM_BYTES_WORD 1 + #define OL_FW_TX_DBG_PPDU_NUM_BYTES_S 0 + #define OL_FW_TX_DBG_PPDU_NUM_BYTES_M 0xffffffff + A_UINT32 num_bytes; + + /* word 2 - filled in during tx enqueue */ + #define OL_FW_TX_DBG_PPDU_NUM_MSDUS_WORD 2 + #define OL_FW_TX_DBG_PPDU_NUM_MSDUS_S 0 + #define OL_FW_TX_DBG_PPDU_NUM_MSDUS_M 0x000000ff + A_UINT8 num_msdus; + #define OL_FW_TX_DBG_PPDU_NUM_MPDUS_WORD 2 + #define OL_FW_TX_DBG_PPDU_NUM_MPDUS_S 8 + #define OL_FW_TX_DBG_PPDU_NUM_MPDUS_M 0x0000ff00 + A_UINT8 num_mpdus; + A_UINT16 + #define OL_FW_TX_DBG_PPDU_EXT_TID_WORD 2 + #define OL_FW_TX_DBG_PPDU_EXT_TID_S 16 + #define OL_FW_TX_DBG_PPDU_EXT_TID_M 0x001f0000 + ext_tid : 5, + #define OL_FW_TX_DBG_PPDU_PEER_ID_WORD 2 + #define OL_FW_TX_DBG_PPDU_PEER_ID_S 21 + #define OL_FW_TX_DBG_PPDU_PEER_ID_M 0xffe00000 + peer_id : 11; + + /* word 3 - filled in during tx enqueue */ + #define OL_FW_TX_DBG_PPDU_TIME_ENQUEUE_WORD 3 + #define OL_FW_TX_DBG_PPDU_TIME_ENQUEUE_S 0 + #define OL_FW_TX_DBG_PPDU_TIME_ENQUEUE_M 0xffffffff + A_UINT32 timestamp_enqueue; + + /* word 4 - filled in during tx completion */ + #define OL_FW_TX_DBG_PPDU_TIME_COMPL_WORD 4 + #define OL_FW_TX_DBG_PPDU_TIME_COMPL_S 0 + #define OL_FW_TX_DBG_PPDU_TIME_COMPL_M 0xffffffff + A_UINT32 timestamp_completion; + + /* word 5 - filled in during tx completion */ + #define OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_WORD 5 + #define OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_S 0 + #define OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_M 0xffffffff + A_UINT32 block_ack_bitmap_lsbs; + + /* word 6 - filled in during tx completion */ + #define OL_FW_TX_DBG_PPDU_BLOCK_ACK_MSBS_WORD 6 + #define OL_FW_TX_DBG_PPDU_BLOCK_ACK_MSBS_S 0 + #define OL_FW_TX_DBG_PPDU_BLOCK_ACK_MSBS_M 0xffffffff + A_UINT32 block_ack_bitmap_msbs; + + /* word 7 - filled in during tx completion (enqueue would work too) */ + #define OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_WORD 7 + #define OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_S 0 + #define OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_M 0xffffffff + A_UINT32 enqueued_bitmap_lsbs; + + /* word 8 - filled in during tx completion (enqueue would work too) */ + #define OL_FW_TX_DBG_PPDU_ENQUEUED_MSBS_WORD 8 + #define OL_FW_TX_DBG_PPDU_ENQUEUED_MSBS_S 0 + #define OL_FW_TX_DBG_PPDU_ENQUEUED_MSBS_M 0xffffffff + A_UINT32 enqueued_bitmap_msbs; + + /* word 9 - filled in during tx completion */ + #define OL_FW_TX_DBG_PPDU_RATE_CODE_WORD 9 + #define OL_FW_TX_DBG_PPDU_RATE_CODE_S 0 + #define OL_FW_TX_DBG_PPDU_RATE_CODE_M 0x000000ff + A_UINT8 rate_code; + #define OL_FW_TX_DBG_PPDU_RATE_FLAGS_WORD 9 + #define OL_FW_TX_DBG_PPDU_RATE_FLAGS_S 8 + #define OL_FW_TX_DBG_PPDU_RATE_FLAGS_M 0x0000ff00 + A_UINT8 rate_flags; /* includes dynamic bandwidth info */ + #define OL_FW_TX_DBG_PPDU_TRIES_WORD 9 + #define OL_FW_TX_DBG_PPDU_TRIES_S 16 + #define OL_FW_TX_DBG_PPDU_TRIES_M 0x00ff0000 + A_UINT8 tries; + #define OL_FW_TX_DBG_PPDU_COMPLETE_WORD 9 + #define OL_FW_TX_DBG_PPDU_COMPLETE_S 24 + #define OL_FW_TX_DBG_PPDU_COMPLETE_M 0xff000000 + A_UINT8 complete; +}; + + +#endif /* _OL_FW_TX_DBG__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_api.h new file mode 100644 index 000000000000..55d15565c035 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_api.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_htt_api.h + * @brief Specify the general HTT API functions called by the host data SW. + * @details + * This file declares the HTT API functions that are not specific to + * either tx nor rx. + */ +#ifndef _OL_HTT_API__H_ +#define _OL_HTT_API__H_ + +#include /* adf_os_device_t */ +#include /* adf_nbuf_t */ +#include /* A_STATUS */ +#include /* HTC_HANDLE */ +#include /* ol_pdev_handle */ +#include /* ol_txrx_pdev_handle */ +#include "htt.h" /* htt_dbg_stats_type, etc. */ + +/* TID */ +#define OL_HTT_TID_NON_QOS_UNICAST 16 +#define OL_HTT_TID_NON_QOS_MCAST_BCAST 18 + + +struct htt_pdev_t; +typedef struct htt_pdev_t *htt_pdev_handle; + +/** + * @brief Allocate and initialize a HTT instance. + * @details + * This function allocates and initializes an HTT instance. + * This involves allocating a pool of HTT tx descriptors in + * consistent memory, allocating and filling a rx ring (LL only), + * and connecting the HTC's HTT_DATA_MSG service. + * The HTC service connect call will block, so this function + * needs to be called in passive context. + * Because HTC setup has not been completed at the time this function + * is called, this function cannot send any HTC messages to the target. + * Messages to configure the target are instead sent in the + * htc_attach_target function. + * + * @param txrx_pdev - data SW's physical device handle + * (used as context pointer during HTT -> txrx calls) + * @param ctrl_pdev - control SW's physical device handle + * (used to query configuration functions) + * @param osdev - abstract OS device handle + * (used for mem allocation) + * @param desc_pool_size - number of HTT descriptors to (pre)allocate + * @return success -> HTT pdev handle; failure -> NULL + */ +htt_pdev_handle +htt_attach( + ol_txrx_pdev_handle txrx_pdev, + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, + adf_os_device_t osdev, + int desc_pool_size); + +/** + * @brief Send HTT configuration messages to the target. + * @details + * For LL only, this function sends a rx ring configuration message to the + * target. For HL, this function is a no-op. + * + * @param htt_pdev - handle to the HTT instance being initialized + */ +A_STATUS +htt_attach_target(htt_pdev_handle htt_pdev); + +/** + * @brief modes that a virtual device can operate as + * @details + * A virtual device can operate as an AP, an IBSS, a STA + * (client), in monitor mode or in OCB mode + */ +enum htt_op_mode { + htt_op_mode_unknown, + htt_op_mode_ap, + htt_op_mode_ibss, + htt_op_mode_sta, + htt_op_mode_monitor, + htt_op_mode_ocb, +}; + +/* no-ops */ +#define htt_vdev_attach(htt_pdev, vdev_id, op_mode) +#define htt_vdev_detach(htt_pdev, vdev_id) +#define htt_peer_qos_update(htt_pdev, peer_id, qos_capable) +#define htt_peer_uapsdmask_update(htt_pdev, peer_id, uapsd_mask) + +/** + * @brief Deallocate a HTT instance. + * + * @param htt_pdev - handle to the HTT instance being torn down + */ +void +htt_detach(htt_pdev_handle htt_pdev); + +/** + * @brief Stop the communication between HTT and target + * @details + * For ISOC solution, this function stop the communication between HTT and target. + * For Peregrine/Rome, it's already stopped by ol_ath_disconnect_htc + * before ol_txrx_pdev_detach called in ol_ath_detach. So this function is a no-op. + * Peregrine/Rome HTT layer is on top of HTC while ISOC solution HTT layer is + * on top of DXE layer. + * + * @param htt_pdev - handle to the HTT instance being initialized + */ +void +htt_detach_target(htt_pdev_handle htt_pdev); + +/* + * @brief Tell the target side of HTT to suspend H2T processing until synced + * @param htt_pdev - the host HTT object + * @param sync_cnt - what sync count value the target HTT FW should wait for + * before resuming H2T processing + */ +A_STATUS +htt_h2t_sync_msg(htt_pdev_handle htt_pdev, u_int8_t sync_cnt); + + +int +htt_h2t_aggr_cfg_msg(htt_pdev_handle htt_pdev, + int max_subfrms_ampdu, + int max_subfrms_amsdu); + +/** + * @brief Get the FW status + * @details + * Trigger FW HTT to retrieve FW status. + * A separate HTT message will come back with the statistics we want. + * + * @param pdev - handle to the HTT instance + * @param stats_type_upload_mask - bitmask identifying which stats to upload + * @param stats_type_reset_mask - bitmask identifying which stats to reset + * @param cookie - unique value to distinguish and identify stats requests + * @return 0 - succeed to send the request to FW; otherwise, failed to do so. + */ +int +htt_h2t_dbg_stats_get( + struct htt_pdev_t *pdev, + u_int32_t stats_type_upload_mask, + u_int32_t stats_type_reset_mask, + u_int8_t cfg_stats_type, + u_int32_t cfg_val, + u_int64_t cookie); + +/** + * @brief Get the fields from HTT T2H stats upload message's stats info header + * @details + * Parse the a HTT T2H message's stats info tag-length-value header, + * to obtain the stats type, status, data lenght, and data address. + * + * @param stats_info_list - address of stats record's header + * @param[out] type - which type of FW stats are contained in the record + * @param[out] status - whether the stats are (fully) present in the record + * @param[out] length - how large the data portion of the stats record is + * @param[out] stats_data - where the data portion of the stats record is + */ +void +htt_t2h_dbg_stats_hdr_parse( + u_int8_t *stats_info_list, + enum htt_dbg_stats_type *type, + enum htt_dbg_stats_status *status, + int *length, + u_int8_t **stats_data); + +/** + * @brief Display a stats record from the HTT T2H STATS_CONF message. + * @details + * Parse the stats type and status, and invoke a type-specified printout + * to display the stats values. + * + * @param stats_data - buffer holding the stats record from the STATS_CONF msg + * @param concise - whether to do a verbose or concise printout + */ +void +htt_t2h_stats_print(u_int8_t *stats_data, int concise); + +#ifndef HTT_DEBUG_LEVEL +#if defined(DEBUG) +#define HTT_DEBUG_LEVEL 10 +#else +#define HTT_DEBUG_LEVEL 0 +#endif +#endif + +#if HTT_DEBUG_LEVEL > 5 +void htt_display(htt_pdev_handle pdev, int indent); +#else +#define htt_display(pdev, indent) +#endif + +#define HTT_DXE_RX_LOG 0 +#define htt_rx_reorder_log_print(pdev) + +#ifdef IPA_UC_OFFLOAD +/** + * @brief send IPA UC resource config message to firmware with HTT message + * @details + * send IPA UC resource config message to firmware with HTT message + * + * @param pdev - handle to the HTT instance + */ +int +htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev); + +/** + * @brief Client request resource information + * @details + * OL client will reuqest IPA UC related resource information + * Resource information will be distributted to IPA module + * All of the required resources should be pre-allocated + * + * @param pdev - handle to the HTT instance + * @param ce_sr_base_paddr - copy engine source ring base physical address + * @param ce_sr_ring_size - copy engine source ring size + * @param ce_reg_paddr - copy engine register physical address + * @param tx_comp_ring_base_paddr - tx comp ring base physical address + * @param tx_comp_ring_size - tx comp ring size + * @param tx_num_alloc_buffer - number of allocated tx buffer + * @param rx_rdy_ring_base_paddr - rx ready ring base physical address + * @param rx_rdy_ring_size - rx ready ring size + * @param rx_proc_done_idx_paddr - rx process done index physical address + */ +int +htt_ipa_uc_get_resource(htt_pdev_handle pdev, + a_uint32_t *ce_sr_base_paddr, + a_uint32_t *ce_sr_ring_size, + a_uint32_t *ce_reg_paddr, + a_uint32_t *tx_comp_ring_base_paddr, + a_uint32_t *tx_comp_ring_size, + a_uint32_t *tx_num_alloc_buffer, + a_uint32_t *rx_rdy_ring_base_paddr, + a_uint32_t *rx_rdy_ring_size, + a_uint32_t *rx_proc_done_idx_paddr); + +/** + * @brief Client set IPA UC doorbell register + * @details + * IPA UC let know doorbell register physical address + * WLAN firmware will use this physical address to notify IPA UC + * + * @param pdev - handle to the HTT instance + * @param ipa_uc_tx_doorbell_paddr - tx comp doorbell physical address + * @param ipa_uc_rx_doorbell_paddr - rx ready doorbell physical address + */ +int +htt_ipa_uc_set_doorbell_paddr(htt_pdev_handle pdev, + a_uint32_t ipa_uc_tx_doorbell_paddr, + a_uint32_t ipa_uc_rx_doorbell_paddr); + +/** + * @brief Client notify IPA UC data path active or not + * + * @param pdev - handle to the HTT instance + * @param uc_active - UC data path is active or not + * @param is_tx - UC TX is active or not + */ +int +htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, + a_bool_t uc_active, + a_bool_t is_tx); + +/** + * @brief query uc data path stats + * + * @param pdev - handle to the HTT instance + */ +int +htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev); + +/** + * @brief Attach IPA UC data path + * + * @param pdev - handle to the HTT instance + */ +int +htt_ipa_uc_attach(struct htt_pdev_t *pdev); + +/** + * @brief detach IPA UC data path + * + * @param pdev - handle to the HTT instance + */ +void +htt_ipa_uc_detach(struct htt_pdev_t *pdev); +#endif /* IPA_UC_OFFLOAD */ + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) +void +htt_dump_bundle_stats(struct htt_pdev_t *pdev); +void +htt_clear_bundle_stats(struct htt_pdev_t *pdev); +#else + +#define htt_dump_bundle_stats(pdev) /*no-op*/ +#define htt_clear_bundle_stats(pdev) /*no-op*/ + +#endif + +#endif /* _OL_HTT_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_rx_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_rx_api.h new file mode 100644 index 000000000000..b8e98250a4be --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_rx_api.h @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_htt_rx_api.h + * @brief Specify the rx HTT API functions called by the host data SW. + * @details + * This file declares the HTT API functions that are specifically + * related to receive processing. + * In particular, this file specifies methods of the abstract HTT rx + * descriptor, and functions to iterate though a series of rx descriptors + * and rx MSDU buffers. + */ +#ifndef _OL_HTT_RX_API__H_ +#define _OL_HTT_RX_API__H_ + +//#include /* u_int16_t, etc. */ +#include /* u_int16_t, etc. */ +#include /* adf_nbuf_t */ +#include /* a_bool_t */ + +#include /* HTT_RX_IND_MPDU_STATUS */ +#include /* htt_pdev_handle */ + +#include /* ieee80211_rx_status */ +#include + + +/*================ constants and types used in the rx API ===================*/ + +#define HTT_RSSI_INVALID 0x7fff + +/** + * @brief RX stats header + * @details + * When receiving an OCB packet, the RX stats is sent to the user application + * so that the user application can do processing based on the RX stats. + * This structure will be preceded by an ethernet header with + * the proto field set to 0x8152. This struct includes various RX + * paramaters including RSSI, data rate, and center frequency. + */ +PREPACK struct ocb_rx_stats_hdr_t { + /* version - The version must be 1. */ + A_UINT16 version; + /* length - The length of this structure */ + A_UINT16 length; + /* channel_freq - The center frequency for the packet */ + A_UINT16 channel_freq; + /* rssi_cmb - combined RSSI from all chains */ + A_INT16 rssi_cmb; + /* rssi - rssi for chains 0 through 3 (for 20 MHz bandwidth) */ + A_INT16 rssi[4]; + /* tsf32 - timestamp in TSF units */ + A_UINT32 tsf32; + /* timestamp_microsec - timestamp in microseconds */ + A_UINT32 timestamp_microsec; + /* datarate - MCS index */ + A_UINT8 datarate; + /* timestamp_submicrosec - submicrosecond portion of the timestamp */ + A_UINT8 timestamp_submicrosec; + /* ext_tid - Extended TID */ + A_UINT8 ext_tid; + /* Ensure the size of the structure is a multiple of 4 */ + A_UINT8 reserved; +}; + +/*================ rx indication message field access methods ===============*/ + +/** + * @brief Check if a rx indication message has a rx reorder flush command. + * @details + * Space is reserved in each rx indication message for a rx reorder flush + * command, to release specified MPDUs from the rx reorder holding array + * before processing the new MPDUs referenced by the rx indication message. + * This rx reorder flush command contains a flag to show whether the command + * is valid within a given rx indication message. + * This function checks the validity flag from the rx indication + * flush command IE within the rx indication message. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @return + * 1 - the message's rx flush command is valid and should be processed + * before processing new rx MPDUs, + * -OR- + * 0 - the message's rx flush command is invalid and should be ignored + */ +int +htt_rx_ind_flush(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); + +/** + * @brief Return the sequence number starting the range of MPDUs to flush. + * @details + * Read the fields of the rx indication message that identify the start + * and end of the range of MPDUs to flush from the rx reorder holding array + * and send on to subsequent stages of rx processing. + * These sequence numbers are the 6 LSBs of the 12-bit 802.11 sequence + * number. These sequence numbers are masked with the block ack window size, + * rounded up to a power of two (minus one, to create a bitmask) to obtain + * the corresponding index into the rx reorder holding array. + * The series of MPDUs to flush includes the one specified by the start + * sequence number. + * The series of MPDUs to flush excludes the one specified by the end + * sequence number; the MPDUs up to but not including the end sequence number + * are to be flushed. + * These start and end seq num fields are only valid if the "flush valid" + * flag is set. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @param seq_num_start - (call-by-reference output) sequence number + * for the start of the range of MPDUs to flush + * @param seq_num_end - (call-by-reference output) sequence number + * for the end of the range of MPDUs to flush + */ +void +htt_rx_ind_flush_seq_num_range( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + unsigned *seq_num_start, + unsigned *seq_num_end); + +/** + * @brief Check if a rx indication message has a rx reorder release command. + * @details + * Space is reserved in each rx indication message for a rx reorder release + * command, to release specified MPDUs from the rx reorder holding array + * after processing the new MPDUs referenced by the rx indication message. + * This rx reorder release command contains a flag to show whether the command + * is valid within a given rx indication message. + * This function checks the validity flag from the rx indication + * release command IE within the rx indication message. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @return + * 1 - the message's rx release command is valid and should be processed + * after processing new rx MPDUs, + * -OR- + * 0 - the message's rx release command is invalid and should be ignored + */ +int +htt_rx_ind_release(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); + +/** + * @brief Return the sequence number starting the range of MPDUs to release. + * @details + * Read the fields of the rx indication message that identify the start + * and end of the range of MPDUs to release from the rx reorder holding + * array and send on to subsequent stages of rx processing. + * These sequence numbers are the 6 LSBs of the 12-bit 802.11 sequence + * number. These sequence numbers are masked with the block ack window size, + * rounded up to a power of two (minus one, to create a bitmask) to obtain + * the corresponding index into the rx reorder holding array. + * The series of MPDUs to release includes the one specified by the start + * sequence number. + * The series of MPDUs to release excludes the one specified by the end + * sequence number; the MPDUs up to but not including the end sequence number + * are to be released. + * These start and end seq num fields are only valid if the "release valid" + * flag is set. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @param seq_num_start - (call-by-reference output) sequence number + * for the start of the range of MPDUs to release + * @param seq_num_end - (call-by-reference output) sequence number + * for the end of the range of MPDUs to release + */ +void +htt_rx_ind_release_seq_num_range( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + unsigned *seq_num_start, + unsigned *seq_num_end); + +/* + * For now, the host HTT -> host data rx status enum + * exactly matches the target HTT -> host HTT rx status enum; + * no translation is required. + * However, the host data SW should only use the htt_rx_status, + * so that in the future a translation from target HTT rx status + * to host HTT rx status can be added, if the need ever arises. + */ +enum htt_rx_status { + htt_rx_status_unknown = HTT_RX_IND_MPDU_STATUS_UNKNOWN, + htt_rx_status_ok = HTT_RX_IND_MPDU_STATUS_OK, + htt_rx_status_err_fcs = HTT_RX_IND_MPDU_STATUS_ERR_FCS, + htt_rx_status_err_dup = HTT_RX_IND_MPDU_STATUS_ERR_DUP, + htt_rx_status_err_replay = HTT_RX_IND_MPDU_STATUS_ERR_REPLAY, + htt_rx_status_err_inv_peer = HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER, + htt_rx_status_ctrl_mgmt_null = HTT_RX_IND_MPDU_STATUS_MGMT_CTRL, + htt_rx_status_tkip_mic_err = HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR, + + htt_rx_status_err_misc = HTT_RX_IND_MPDU_STATUS_ERR_MISC +}; + +/** + * @brief Check the status MPDU range referenced by a rx indication message. + * @details + * Check the status of a range of MPDUs referenced by a rx indication message. + * This status determines whether the MPDUs should be processed or discarded. + * If the status is OK, then the MPDUs within the range should be processed + * as usual. + * Otherwise (FCS error, duplicate error, replay error, unknown sender error, + * etc.) the MPDUs within the range should be discarded. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @param mpdu_range_num - which MPDU range within the rx ind msg to check, + * starting from 0 + * @param status - (call-by-reference output) MPDU status + * @param mpdu_count - (call-by-reference output) count of MPDUs comprising + * the specified MPDU range + */ +void +htt_rx_ind_mpdu_range_info( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + int mpdu_range_num, + enum htt_rx_status *status, + int *mpdu_count); + +int16_t +htt_rx_ind_rssi_dbm(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); + +int16_t +htt_rx_ind_rssi_dbm_chain(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg, + int8_t chain); + +void +htt_rx_ind_legacy_rate(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg, + uint8_t *legacy_rate, uint8_t *legacy_rate_sel); + + +void +htt_rx_ind_timestamp(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg, + uint32_t *timestamp_microsec, uint8_t *timestamp_submicrosec); + +uint32_t +htt_rx_ind_tsf32(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); + +uint8_t +htt_rx_ind_ext_tid(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); + + +/*==================== rx MPDU descriptor access methods ====================*/ + +extern +bool (*htt_rx_mpdu_desc_retry)( + htt_pdev_handle pdev, void *mpdu_desc); +/** + * @brief Return a rx MPDU's sequence number. + * @details + * This function returns the LSBs of the 802.11 sequence number for the + * provided rx MPDU descriptor. + * Depending on the system, 6-12 LSBs from the 802.11 sequence number are + * returned. (Typically, either the 8 or 12 LSBs are returned.) + * This sequence number is masked with the block ack window size, + * rounded up to a power of two (minus one, to create a bitmask) to obtain + * the corresponding index into the rx reorder holding array. + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return the LSBs of the sequence number for the MPDU + */ +extern a_uint16_t +(*htt_rx_mpdu_desc_seq_num)(htt_pdev_handle pdev, void *mpdu_desc); + +/** + * @brief Return a rx MPDU's rx reorder array index, based on sequence number. + * @details + * This function returns a sequence-number based index into the rx + * reorder array for the specified MPDU. + * In some systems, this rx reorder array is simply the LSBs of the + * sequence number, or possibly even the full sequence number. + * To support such systems, the returned index has to be masked with + * the power-of-two array size before using the value to index the + * rx reorder array. + * In other systems, this rx reorder array index is + * (sequence number) % (block ack window size) + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return the rx reorder array index the MPDU goes into + */ +/* use sequence number (or LSBs thereof) as rx reorder array index */ +#define htt_rx_mpdu_desc_reorder_idx htt_rx_mpdu_desc_seq_num + +union htt_rx_pn_t { + /* WEP: 24-bit PN */ + u_int32_t pn24; + + /* TKIP or CCMP: 48-bit PN */ + u_int64_t pn48; + + /* WAPI: 128-bit PN */ + u_int64_t pn128[2]; +}; + +/** + * @brief Find the packet number (PN) for a MPDU. + * @details + * This function only applies when the rx PN check is configured to be + * performed in the host rather than the target, and on peers using a + * security type for which a PN check applies. + * The pn_len_bits argument is used to determine which element of the + * htt_rx_pn_t union to deposit the PN value read from the MPDU descriptor + * into. + * A 24-bit PN is deposited into pn->pn24. + * A 48-bit PN is deposited into pn->pn48. + * A 128-bit PN is deposited in little-endian order into pn->pn128. + * Specifically, bits 63:0 of the PN are copied into pn->pn128[0], while + * bits 127:64 of the PN are copied into pn->pn128[1]. + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @param pn - the location to copy the packet number into + * @param pn_len_bits - the PN size, in bits + */ +extern void (*htt_rx_mpdu_desc_pn)( + htt_pdev_handle pdev, + void *mpdu_desc, + union htt_rx_pn_t *pn, + int pn_len_bits); + +extern +uint8_t (*htt_rx_mpdu_desc_tid)( + htt_pdev_handle pdev, void *mpdu_desc); + +/** + * @brief Return the TSF timestamp indicating when a MPDU was received. + * @details + * This function provides the timestamp indicating when the PPDU that + * the specified MPDU belongs to was received. + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return 32 LSBs of TSF time at which the MPDU's PPDU was received + */ +u_int32_t +htt_rx_mpdu_desc_tsf32( + htt_pdev_handle pdev, + void *mpdu_desc); + +/** + * @brief Return the 802.11 header of the MPDU + * @details + * This function provides a pointer to the start of the 802.11 header + * of the Rx MPDU + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return pointer to 802.11 header of the received MPDU + */ +char * +htt_rx_mpdu_wifi_hdr_retrieve( + htt_pdev_handle pdev, + void *mpdu_desc); + +/** + * @brief Return the RSSI provided in a rx descriptor. + * @details + * Return the RSSI from a rx descriptor, converted to dBm units. + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return RSSI in dBm, or HTT_INVALID_RSSI + */ +int16_t +htt_rx_mpdu_desc_rssi_dbm(htt_pdev_handle pdev, void *mpdu_desc); + + +/*==================== rx MSDU descriptor access methods ====================*/ + +/** + * @brief Check if a MSDU completes a MPDU. + * @details + * When A-MSDU aggregation is used, a single MPDU will consist of + * multiple MSDUs. This function checks a MSDU's rx descriptor to + * see whether the MSDU is the final MSDU within a MPDU. + * + * @param pdev - the handle of the physical device the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - there are subsequent MSDUs within the A-MSDU / MPDU + * -OR- + * 1 - this is the last MSDU within its MPDU + */ +extern a_bool_t (*htt_rx_msdu_desc_completes_mpdu)( + htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Check if a MSDU is first msdu of MPDU. + * @details + * When A-MSDU aggregation is used, a single MPDU will consist of + * multiple MSDUs. This function checks a MSDU's rx descriptor to + * see whether the MSDU is the first MSDU within a MPDU. + * + * @param pdev - the handle of the physical device the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - this is interior MSDU in the A-MSDU / MPDU + * -OR- + * 1 - this is the first MSDU within its MPDU + */ +extern a_bool_t (*htt_rx_msdu_first_msdu_flag)( + htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Retrieve encrypt bit from a mpdu desc. + * @details + * Fw will pass all the frame to the host whether encrypted or not, and will + * indicate the encrypt flag in the desc, this function is to get the info and used + * to make a judge whether should make pn check, because non-encrypted frames + * always get the same pn number 0. + * + * @param pdev - the HTT instance the rx data was received on + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return 0 - the frame was not encrypted + * 1 - the frame was encrypted + */ +extern a_bool_t +(*htt_rx_mpdu_is_encrypted)(htt_pdev_handle pdev, void *mpdu_desc); + +/** + * @brief Indicate whether a rx desc has a WLAN unicast vs. mcast/bcast flag. + * @details + * A flag indicating whether a MPDU was delivered over WLAN as unicast or + * multicast/broadcast may be only valid once per MPDU (LL), or within each + * rx descriptor for the MSDUs within the MPDU (HL). (In practice, it is + * unlikely that A-MSDU aggregation will be used in HL, so typically HL will + * only have one MSDU per MPDU anyway.) + * This function indicates whether the specified rx descriptor contains + * a WLAN ucast vs. mcast/bcast flag. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - The rx descriptor does not contain a WLAN ucast vs. mcast flag. + * -OR- + * 1 - The rx descriptor has a valid WLAN ucast vs. mcast flag. + */ +extern int (*htt_rx_msdu_has_wlan_mcast_flag)( + htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Indicate whether a MSDU was received as unicast or mcast/bcast + * @details + * Indicate whether the MPDU that the specified MSDU belonged to was + * delivered over the WLAN as unicast, or as multicast/broadcast. + * This query can only be performed on rx descriptors for which + * htt_rx_msdu_has_wlan_mcast_flag is true. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - The MSDU was delivered over the WLAN as unicast. + * -OR- + * 1 - The MSDU was delivered over the WLAN as broadcast or multicast. + */ +extern a_bool_t (*htt_rx_msdu_is_wlan_mcast)( + htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Indicate whether a MSDU was received as a fragmented frame + * @details + * This query can only be performed on LL system. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - The MSDU was a non-fragmented frame. + * -OR- + * 1 - The MSDU was fragmented frame. + */ +extern int (*htt_rx_msdu_is_frag)( + htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Indicate if a MSDU should be delivered to the OS shim or discarded. + * @details + * Indicate whether a MSDU should be discarded or delivered to the OS shim. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - The MSDU should be delivered to the OS + * -OR- + * non-zero - The MSDU should not be delivered to the OS. + * If the "forward" flag is set, it should be forwarded to tx. + * Else, it should be discarded. + */ +int +htt_rx_msdu_discard(htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Indicate whether a MSDU should be forwarded to tx. + * @details + * Indicate whether a MSDU should be forwarded to tx, e.g. for intra-BSS + * STA-to-STA forwarding in an AP, or for multicast echo in an AP. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - The MSDU should not be forwarded + * -OR- + * non-zero - The MSDU should be forwarded. + * If the "discard" flag is set, then the original MSDU can be + * directly forwarded into the tx path. + * Else, a copy (clone?) of the rx MSDU needs to be created to + * send to the tx path. + */ +int +htt_rx_msdu_forward(htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Indicate whether a MSDU's contents need to be inspected. + * @details + * Indicate whether the host data SW needs to examine the contents of the + * received MSDU, and based on the packet type infer what special handling + * to provide for the MSDU. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @return + * 0 - No inspection + special handling is required. + * -OR- + * non-zero - Inspect the MSDU contents to infer what special handling + * to apply to the MSDU. + */ +int +htt_rx_msdu_inspect(htt_pdev_handle pdev, void *msdu_desc); + +/** + * @brief Provide all action specifications for a rx MSDU + * @details + * Provide all action specifications together. This provides the same + * information in a single function call as would be provided by calling + * the functions htt_rx_msdu_discard, htt_rx_msdu_forward, and + * htt_rx_msdu_inspect. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @param[out] discard - 1: discard the MSDU, 0: deliver the MSDU to the OS + * @param[out] forward - 1: forward the rx MSDU to tx, 0: no rx->tx forward + * @param[out] inspect - 1: process according to MSDU contents, 0: no inspect + */ +void +htt_rx_msdu_actions( + htt_pdev_handle pdev, + void *msdu_desc, + int *discard, + int *forward, + int *inspect); + +/** + * @brief Get the key id sent in IV of the frame + * @details + * Provide the key index octet which is taken from IV. + * This is valid only for the first MSDU. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the abstract descriptor for the MSDU in question + * @key_id - Key id octet + * @return indication of whether key id access is successful + * A_TRUE - Success + * A_FALSE - if this is not first msdu + */ +extern a_bool_t +(*htt_rx_msdu_desc_key_id)( + htt_pdev_handle pdev, + void *mpdu_desc, + u_int8_t *key_id); + +extern a_bool_t +(*htt_rx_msdu_chan_info_present)( + htt_pdev_handle pdev, + void *mpdu_desc); + +extern a_bool_t +(*htt_rx_msdu_center_freq)( + htt_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + void *mpdu_desc, + uint16_t *primary_chan_center_freq_mhz, + uint16_t *contig_chan1_center_freq_mhz, + uint16_t *contig_chan2_center_freq_mhz, + uint8_t *phy_mode); + +/*====================== rx MSDU + descriptor delivery ======================*/ + +/** + * @brief Return a linked-list of network buffer holding the next rx A-MSDU. + * @details + * In some systems, the rx MSDUs are uploaded along with the rx + * indication message, while in other systems the rx MSDUs are uploaded + * out of band, via MAC DMA. + * This function provides an abstract way to obtain a linked-list of the + * next MSDUs, regardless of whether the MSDU was delivered in-band with + * the rx indication message, or out of band through MAC DMA. + * In a LL system, this function returns a linked list of the one or more + * MSDUs that together comprise an A-MSDU. + * In a HL system, this function returns a degenerate linked list consisting + * of a single MSDU (head_msdu == tail_msdu). + * This function also makes sure each MSDU's rx descriptor can be found + * through the MSDU's network buffer. + * In most systems, this is trivial - a single network buffer stores both + * the MSDU rx descriptor and the MSDU payload. + * In systems where the rx descriptor is in a separate buffer from the + * network buffer holding the MSDU payload, a pointer to the rx descriptor + * has to be stored in the network buffer. + * After this function call, the descriptor for a given MSDU can be + * obtained via the htt_rx_msdu_desc_retrieve function. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @param head_msdu - call-by-reference network buffer handle, which gets set + * in this function to point to the head MSDU of the A-MSDU + * @param tail_msdu - call-by-reference network buffer handle, which gets set + * in this function to point to the tail MSDU of the A-MSDU, or the + * same MSDU that the head_msdu points to if only a single MSDU is + * delivered at a time. + * @return indication of whether any MSDUs in the AMSDU use chaining: + * 0 - no buffer chaining + * 1 - buffers are chained + */ +extern int +(*htt_rx_amsdu_pop)( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu); + +extern int +(*htt_rx_frag_pop)( + htt_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + adf_nbuf_t *head_msdu, + adf_nbuf_t *tail_msdu); + +/** + * @brief Return a linked list of buffers holding one MSDU + * In some systems the buffers are delivered along with offload delivery + * indication message itself, while in other systems the buffers are uploaded + * out of band, via MAC DMA. + * @details + * This function provides an abstract way to obtain a linked-list of the + * buffers corresponding to an msdu, regardless of whether the MSDU was + * delivered in-band with the rx indication message, or out of band through + * MAC DMA. + * In a LL system, this function returns a linked list of one or more + * buffers corresponding to an MSDU + * In a HL system , TODO + * + * @param pdev - the HTT instance the rx data was received on + * @param offload_deliver_msg - the nebuf containing the offload deliver message + * @param head_msdu - call-by-reference network buffer handle, which gets set in this + * function to the head buffer of this MSDU + * @param tail_msdu - call-by-reference network buffer handle, which gets set in this + * function to the tail buffer of this MSDU + */ +extern int +(*htt_rx_offload_msdu_pop)( + htt_pdev_handle pdev, + adf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + u_int8_t *fw_desc, + adf_nbuf_t *head_buf, + adf_nbuf_t *tail_buf); + +/** + * @brief Return the rx descriptor for the next rx MPDU. + * @details + * The rx MSDU descriptors may be uploaded as part of the rx indication + * message, or delivered separately out of band. + * This function provides an abstract way to obtain the next MPDU descriptor, + * regardless of whether the MPDU descriptors are delivered in-band with + * the rx indication message, or out of band. + * This is used to iterate through the series of MPDU descriptors referenced + * by a rx indication message. + * The htt_rx_amsdu_pop function should be called before this function + * (or at least before using the returned rx descriptor handle), so that + * the cache location for the rx descriptor will be flushed before the + * rx descriptor gets used. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @return next abstract rx descriptor from the series of MPDUs referenced + * by an rx ind msg + */ +extern void * +(*htt_rx_mpdu_desc_list_next)(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg); + +/** + * @brief Retrieve a previously-stored rx descriptor from a MSDU buffer. + * @details + * The data SW will call the htt_rx_msdu_desc_link macro/function to + * link a MSDU's rx descriptor with the buffer holding the MSDU payload. + * This function retrieves the rx MSDU descriptor. + * + * @param pdev - the HTT instance the rx data was received on + * @param msdu - the buffer containing the MSDU payload + * @return the corresponding abstract rx MSDU descriptor + */ +extern void * +(*htt_rx_msdu_desc_retrieve)(htt_pdev_handle pdev, adf_nbuf_t msdu); + +/** + * @brief Free both an rx MSDU descriptor and the associated MSDU buffer. + * @details + * Usually the WLAN driver does not free rx MSDU buffers, but needs to + * do so when an invalid frame (e.g. FCS error) was deposited into the + * queue of rx buffers. + * This function frees both the rx descriptor and the rx frame. + * On some systems, the rx descriptor and rx frame are stored in the + * same buffer, and thus one free suffices for both objects. + * On other systems, the rx descriptor and rx frame are stored + * separately, so distinct frees are internally needed. + * However, in either case, the rx descriptor has been associated with + * the MSDU buffer, and can be retrieved by htt_rx_msdu_desc_retrieve. + * Hence, it is only necessary to provide the MSDU buffer; the HTT SW + * internally finds the corresponding MSDU rx descriptor. + * + * @param htt_pdev - the HTT instance the rx data was received on + * @param rx_msdu_desc - rx descriptor for the MSDU being freed + * @param msdu - rx frame buffer for the MSDU being freed + */ +void +htt_rx_desc_frame_free( + htt_pdev_handle htt_pdev, + adf_nbuf_t msdu); + +/** + * @brief Look up and free the rx descriptor for a MSDU. + * @details + * When the driver delivers rx frames to the OS, it first needs + * to free the associated rx descriptors. + * In some systems the rx descriptors are allocated in the same + * buffer as the rx frames, so this operation is a no-op. + * In other systems, the rx descriptors are stored separately + * from the rx frames, so the rx descriptor has to be freed. + * The descriptor is located from the MSDU buffer with the + * htt_rx_desc_frame_free macro/function. + * + * @param htt_pdev - the HTT instance the rx data was received on + * @param msdu - rx frame buffer for the rx MSDU descriptor being freed + */ +void +htt_rx_msdu_desc_free(htt_pdev_handle htt_pdev, adf_nbuf_t msdu); + +/** + * @brief Add new MSDU buffers for the target to fill. + * @details + * In some systems, the underlying upload mechanism (HIF) allocates new rx + * buffers itself. In other systems, the underlying upload mechanism + * (MAC DMA) needs to be provided with new rx buffers. + * This function is used as an abstract method to indicate to the underlying + * data upload mechanism when it is an appropriate time to allocate new rx + * buffers. + * If the allocation is automatically handled, a la HIF, then this function + * call is ignored. + * If the allocation has to be done explicitly, a la MAC DMA, then this + * function provides the context and timing for such replenishment + * allocations. + * + * @param pdev - the HTT instance the rx data will be received on + */ +void +htt_rx_msdu_buff_replenish(htt_pdev_handle pdev); + +/** + * @brief Links list of MSDUs into an single MPDU. Updates RX stats + * @details + * When HW MSDU splitting is turned on each MSDU in an AMSDU MPDU occupies + * a separate wbuf for delivery to the network stack. For delivery to the + * monitor mode interface they need to be restitched into an MPDU. This + * function does this. Also updates the RX status if the MPDU starts + * a new PPDU + * + * @param pdev - the HTT instance the rx data was received on + * @param head_msdu - network buffer handle, which points to the first MSDU + * in the list. This is a NULL terminated list + * @param rx_staus - pointer to the status associated with this MPDU. + * Updated only if there is a new PPDU and new status associated with it + * @param clone_not_reqd - If set the MPDU linking destroys the passed in + * list, else operates on a cloned nbuf + * @return network buffer handle to the MPDU + */ +adf_nbuf_t +htt_rx_restitch_mpdu_from_msdus( + htt_pdev_handle pdev, + adf_nbuf_t head_msdu, + struct ieee80211_rx_status *rx_status, + unsigned clone_not_reqd); + +/** + * @brief Return the sequence number of MPDUs to flush. + * @param pdev - the HTT instance the rx data was received on + * @param rx_frag_ind_msg - the netbuf containing the rx fragment indication message + * @param seq_num_start - (call-by-reference output) sequence number + * for the start of the range of MPDUs to flush + * @param seq_num_end - (call-by-reference output) sequence number + * for the end of the range of MPDUs to flush + */ +void +htt_rx_frag_ind_flush_seq_num_range( + htt_pdev_handle pdev, + adf_nbuf_t rx_frag_ind_msg, + int *seq_num_start, + int *seq_num_end); +/** + * @brief Return the HL rx desc size + * @param pdev - the HTT instance the rx data was received on + * @param msdu_desc - the hl rx desc pointer + * + */ +u_int16_t +htt_rx_msdu_rx_desc_size_hl( + htt_pdev_handle pdev, + void *msdu_desc); + +/** + * @brief populates vowext stats by processing RX desc. + * @param msdu - network buffer handle + * @param vowstats - handle to vow ext stats. + */ +void htt_rx_get_vowext_stats(adf_nbuf_t msdu,struct vow_extstats *vowstats); + +/** + * @brief parses the offload message passed by the target. + * @param pdev - pdev handle + * @param paddr - physical address of the rx buffer + * @param vdev_id - reference to vdev id to be filled + * @param peer_id - reference to the peer id to be filled + * @param tid - reference to the tid to be filled + * @param fw_desc - reference to the fw descriptor to be filled + * @param peer_id - reference to the peer id to be filled + * @param head_buf - reference to the head buffer + * @param tail_buf - reference to the tail buffer + */ +int +htt_rx_offload_paddr_msdu_pop_ll( + htt_pdev_handle pdev, + u_int32_t * msg_word, + int msdu_iter, + int *vdev_id, + int *peer_id, + int *tid, + u_int8_t *fw_desc, + adf_nbuf_t *head_buf, + adf_nbuf_t *tail_buf); +#endif /* _OL_HTT_RX_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_tx_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_tx_api.h new file mode 100644 index 000000000000..7e208012333a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_htt_tx_api.h @@ -0,0 +1,846 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_htt_tx_api.h + * @brief Specify the tx HTT API functions called by the host data SW. + * @details + * This file declares the HTT API functions that are specifically + * related to transmit processing. + * In particular, the methods of the abstract HTT tx descriptor are + * specified. + */ +#ifndef _OL_HTT_TX_API__H_ +#define _OL_HTT_TX_API__H_ + +//#include /* u_int16_t, etc. */ +#include /* u_int16_t, etc. */ +#include /* adf_nbuf_t */ +#include /* wlan_frm_fmt */ + +#include /* needed by inline functions */ +#include +#include /* htt_pdev_handle */ +#include +#include + +/* Remove these macros when they get added to htt.h. */ +#ifndef HTT_TX_DESC_EXTENSION_GET +#define HTT_TX_DESC_EXTENSION_OFFSET_BYTES 0 +#define HTT_TX_DESC_EXTENSION_OFFSET_DWORD 0 +#define HTT_TX_DESC_EXTENSION_M 0x10000000 +#define HTT_TX_DESC_EXTENSION_S 28 + +#define HTT_TX_DESC_EXTENSION_GET(_var) \ + (((_var) & HTT_TX_DESC_EXTENSION_M) >> HTT_TX_DESC_EXTENSION_S) +#define HTT_TX_DESC_EXTENSION_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_TX_DESC_EXTENSION, _val); \ + ((_var) |= ((_val) << HTT_TX_DESC_EXTENSION_S)); \ + } while (0) +#endif + +/*================ meta-info about tx MSDUs =================================*/ + +/* + * For simplicity, use the IEEE 802.11 frame type values. + */ +enum htt_frm_type { + htt_frm_type_mgmt = 0, + htt_frm_type_ctrl = 1, + htt_frm_type_data = 2 +}; + +/* + * For simplicity, use the IEEE 802.11 frame sub-type values. + */ +enum htt_frm_subtype { + htt_frm_subtype_mgmt_assoc_req = 0, + htt_frm_subtype_mgmt_assoc_resp = 1, + htt_frm_subtype_mgmt_reassoc_req = 2, + htt_frm_subtype_mgmt_reassoc_resp = 3, + htt_frm_subtype_mgmt_probe_req = 4, + htt_frm_subtype_mgmt_probe_resp = 5, + htt_frm_subtype_mgmt_timing_adv = 6, + htt_frm_subtype_mgmt_beacon = 8, + htt_frm_subtype_mgmt_atim = 9, + htt_frm_subtype_mgmt_disassoc = 10, + htt_frm_subtype_mgmt_auth = 11, + htt_frm_subtype_mgmt_deauth = 12, + htt_frm_subtype_mgmt_action = 13, + htt_frm_subtype_mgmt_action_no_ack = 14, + + htt_frm_subtype_data_data = 0, + htt_frm_subtype_data_data_cf_ack = 1, + htt_frm_subtype_data_data_cf_poll = 2, + htt_frm_subtype_data_data_cf_ack_cf_poll = 3, + htt_frm_subtype_data_null = 4, + htt_frm_subtype_data_cf_ack = 5, + htt_frm_subtype_data_cf_poll = 6, + htt_frm_subtype_data_cf_ack_cf_poll = 7, + htt_frm_subtype_data_QoS_data = 8, + htt_frm_subtype_data_QoS_data_cf_ack = 9, + htt_frm_subtype_data_QoS_data_cf_poll = 10, + htt_frm_subtype_data_QoS_data_cf_ack_cf_poll = 11, + htt_frm_subtype_data_QoS_null = 12, + htt_frm_subtype_data_QoS_cf_poll = 14, + htt_frm_subtype_data_QoS_cf_ack_cf_poll = 15, +}; + +enum htt_ofdm_datarate { // Value MBPS Modulation Coding + htt_ofdm_datarate_6_mbps = 0, // 0 6 BPSK 1/2 + htt_ofdm_datarate_9_mbps = 1, // 1 9 BPSK 3/4 + htt_ofdm_datarate_12_mbps = 2, // 2 12 QPSK 1/2 + htt_ofdm_datarate_18_mbps = 3, // 3 18 QPSK 3/4 + htt_ofdm_datarate_24_mbps = 4, // 4 24 16-QAM 1/2 + htt_ofdm_datarate_36_mbps = 5, // 5 36 16-QAM 3/4 + htt_ofdm_datarate_48_mbps = 6, // 6 48 64-QAM 1/2 + htt_ofdm_datarate_54_mbps = 7, // 7 54 64-QAM 3/4 + htt_ofdm_datarate_max = 7, +}; + +/** + * @brief TX control header + * @details + * When sending an OCB packet, the user application has + * the option of including the following struct following an ethernet header + * with the proto field set to 0x8151. This struct includes various TX + * paramaters including the TX power and MCS. + */ +PREPACK struct ocb_tx_ctrl_hdr_t { + /* The version must be 1. */ + A_UINT16 version; + A_UINT16 length; + A_UINT16 channel_freq; + + /* flags */ + union { + struct { + A_UINT16 + /* bit 0: if set, tx pwr spec is valid */ + valid_pwr: 1, + /* bit 1: if set, tx MCS mask spec is valid */ + valid_datarate: 1, + /* bit 2: if set, tx retries spec is valid */ + valid_retries: 1, + /* bit 3: if set, chain mask is valid */ + valid_chain_mask: 1, + /* bit 4: if set, tx expire TSF spec is valid*/ + valid_expire_tsf: 1, + /* bit 5: if set, TID is valid */ + valid_tid: 1, + reserved0_15_6: 10; /* bits 15:6 - unused, set to 0x0 */ + }; + A_UINT16 all_flags; + }; + + /* TX expiry time (TSF) LSBs */ + A_UINT32 expire_tsf_lo; + + /* TX expiry time (TSF) MSBs */ + A_UINT32 expire_tsf_hi; + + /* pwr - + * Specify what power the tx frame needs to be transmitted at. + * The power a signed (two's complement) value is in units of 0.5 dBm. + * The value needs to be appropriately sign-extended when extracting + * the value from the message and storing it in a variable that is + * larger than A_INT8. + * If the transmission uses multiple tx chains, this power spec is + * the total transmit power, assuming incoherent combination of + * per-chain power to produce the total power. + */ + A_INT8 pwr; + + /* datarate - + * The desired modulation and coding scheme. + * + * VALUE DATA RATE MODULATION CODING RATE + * @ 20 MHz + * (MBPS) + * 0 6 BPSK 1/2 + * 1 9 BPSK 3/4 + * 2 12 QPSK 1/2 + * 3 18 QPSK 3/4 + * 4 24 16-QAM 1/2 + * 5 36 16-QAM 3/4 + * 6 48 64-QAM 1/2 + * 7 54 64-QAM 3/4 + */ + A_UINT8 datarate; + + /* retry_limit - + * Specify the maximum number of transmissions, including the + * initial transmission, to attempt before giving up if no ack + * is received. + * If the tx rate is specified, then all retries shall use the + * same rate as the initial transmission. + * If no tx rate is specified, the target can choose whether to + * retain the original rate during the retransmissions, or to + * fall back to a more robust rate. + */ + A_UINT8 retry_limit; + + /* Chain mask - specify which chains to transmit from. */ + A_UINT8 chain_mask; + + /* Extended Traffic ID (0-15) */ + A_UINT8 ext_tid; + + /* Ensure that the size of the structure is a multiple of 4. */ + A_UINT8 reserved[3]; + +} POSTPACK; + +/** + * @brief tx MSDU meta-data that HTT may use to program the FW/HW tx descriptor + */ +struct htt_msdu_info_t { + /* the info sub-struct specifies the characteristics of the MSDU */ + struct { + u_int16_t ethertype; + #define HTT_INVALID_PEER_ID 0xffff + u_int16_t peer_id; + u_int8_t vdev_id; + u_int8_t ext_tid; + /* + * l2_hdr_type - L2 format (802.3, native WiFi 802.11, or raw 802.11) + * Based on attach-time configuration, the tx frames provided by the + * OS to the tx data SW are expected to be either 802.3 format or + * the "native WiFi" variant of 802.11 format. + * Internally, the driver may also inject tx frames into the tx + * datapath, and these frames may be either 802.3 format, or 802.11 + * "raw" format, with no further 802.11 encapsulation needed. + * The tx frames are tagged with their frame format, so the target + * FW/HW will know how to interpret the packet's encapsulation + * headers when doing tx classification, and what form of 802.11 + * header encapsulation is needed, if any. + */ + u_int8_t l2_hdr_type; /* enum htt_pkt_type */ + /* + * frame_type - is the tx frame management or data? + * Just to avoid confusion, the enum values for this frame type field + * use the 802.11 frame type values, although it is unexpected for + * control frames to be sent through the host data path. + */ + u_int8_t frame_type; /* enum htt_frm_type */ + /* + * frame subtype - this field specifies the sub-type of management + * frames + * Just to avoid confusion, the enum values for this frame subtype + * field use the 802.11 management frame subtype values. + */ + u_int8_t frame_subtype; /* enum htt_frm_subtype */ + u_int8_t is_unicast; + + /* dest_addr is not currently used. + * It could be used as an input to a Tx BD (Riva tx descriptor) + * signature computation. + u_int8_t *dest_addr; + */ + + u_int8_t l3_hdr_offset; // w.r.t. adf_nbuf_data(msdu), in bytes + + /* l4_hdr_offset is not currently used. + * It could be used to specify to a TCP/UDP checksum computation + * engine where the TCP/UDP header starts. + u_int8_t l4_hdr_offset; // w.r.t. adf_nbuf_data(msdu), in bytes + */ + } info; + /* the action sub-struct specifies how to process the MSDU */ + struct { + u_int8_t use_6mbps; /* mgmt frames: option to force 6 Mbps rate */ + u_int8_t do_encrypt; + u_int8_t do_tx_complete; + u_int8_t tx_comp_req; + + /* + * cksum_offload - Specify whether checksum offload is enabled or not + * Target FW uses this flag to turn on HW checksumming + * 0x0 - No checksum offload + * 0x1 - L3 header checksum only + * 0x2 - L4 checksum only + * 0x3 - L3 header checksum + L4 checksum + */ + adf_nbuf_tx_cksum_t cksum_offload; + } action; +}; + +static inline void +htt_msdu_info_dump(struct htt_msdu_info_t *msdu_info) +{ + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + "HTT MSDU info object (%p)\n", msdu_info); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " ethertype: %#x\n", msdu_info->info.ethertype); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " peer_id: %d\n", msdu_info->info.peer_id); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " vdev_id: %d\n", msdu_info->info.vdev_id); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " ext_tid: %d\n", msdu_info->info.ext_tid); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " l2_hdr_type: %d\n", msdu_info->info.l2_hdr_type); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " frame_type: %d\n", msdu_info->info.frame_type); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " frame_subtype: %d\n", msdu_info->info.frame_subtype); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " is_unicast: %u\n", msdu_info->info.is_unicast); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " l3_hdr_offset: %u\n", msdu_info->info.l3_hdr_offset); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " use 6 Mbps: %d\n", msdu_info->action.use_6mbps); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " do_encrypt: %d\n", msdu_info->action.do_encrypt); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " do_tx_complete: %d\n", msdu_info->action.do_tx_complete); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " is_unicast: %u\n", msdu_info->info.is_unicast); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW, + " is_unicast: %u\n", msdu_info->info.is_unicast); +} + + +/*================ tx completion message field access methods ===============*/ + + +/** + * @brief Look up the descriptor ID of the nth MSDU from a tx completion msg. + * @details + * A tx completion message tells the host that the target is done + * transmitting a series of MSDUs. The message uses a descriptor ID + * to identify each such MSDU. This function/macro is used to + * find the ID of one such MSDU referenced by the tx completion message. + * + * @param iterator - tx completion message context provided by HTT to the + * tx completion message handler. This abstract reference to the + * HTT tx completion message's payload allows the data SW's tx + * completion handler to not care about the format of the HTT + * tx completion message. + * @param num - (zero-based) index to specify a single MSDU within the + * series of MSDUs referenced by the tx completion message + * @return descriptor ID for the specified MSDU + */ +u_int16_t +htt_tx_compl_desc_id(void *iterator, int num); + + +/*========================= tx descriptor operations ========================*/ + + +/** + * @brief Allocate a HTT abstract tx descriptor. + * @details + * Allocate a HTT abstract tx descriptor from a pool within "consistent" + * memory, which is accessible by HIF and/or MAC DMA as well as by the + * host CPU. + * It is expected that the tx datapath will allocate HTT tx descriptors + * and link them with datapath SW tx descriptors up front as the driver + * is loaded. Thereafter, the link from datapath SW tx descriptor to + * HTT tx descriptor will be maintained until the driver is unloaded. + * + * @param htt_pdev - handle to the HTT instance making the allocation + * @param[OUT] paddr_lo - physical address of the HTT descriptor + * @return success -> descriptor handle, -OR- failure -> NULL + */ +void * +htt_tx_desc_alloc(htt_pdev_handle htt_pdev, u_int32_t *paddr_lo); + +/** + * @brief Free a HTT abstract tx descriptor. + * + * @param htt_pdev - handle to the HTT instance that made the allocation + * @param htt_tx_desc - the descriptor to free + */ +void +htt_tx_desc_free(htt_pdev_handle htt_pdev, void *htt_tx_desc); + +/** +* @brief Discard all tx frames in the process of being downloaded. +* @details +* This function dicards any tx frames queued in HTT or the layers +* under HTT. +* The download completion callback is invoked on these frames. +* +* @param htt_pdev - handle to the HTT instance +*/ +#if defined(CONFIG_HL_SUPPORT) +#define htt_tx_pending_discard(pdev) /* no-op */ +#else +void +htt_tx_pending_discard(htt_pdev_handle pdev); +#endif + +/** + * @brief Download a MSDU descriptor and (a portion of) the MSDU payload. + * @details + * This function is used within LL systems to download a tx descriptor and + * the initial portion of the tx MSDU payload, and within HL systems to + * download the tx descriptor and the entire tx MSDU payload. + * The HTT layer determines internally how much of the tx descriptor + * actually needs to be downloaded. In particular, the HTT layer does not + * download the fragmentation descriptor, and only for the LL case downloads + * the physical address of the fragmentation descriptor. + * In HL systems, the tx descriptor and the entire frame are downloaded. + * In LL systems, only the tx descriptor and the header of the frame are + * downloaded. To determine how much of the tx frame to download, this + * function assumes the tx frame is the default frame type, as specified + * by ol_cfg_frame_type. "Raw" frames need to be transmitted through the + * alternate htt_tx_send_nonstd function. + * The tx descriptor has already been attached to the adf_nbuf object during + * a preceding call to htt_tx_desc_init. + * + * @param htt_pdev - the handle of the physical device sending the tx data + * @param msdu - the frame being transmitted + * @param msdu_id - unique ID for the frame being transmitted + * @return 0 -> success, -OR- 1 -> failure + */ +int +htt_tx_send_std( + htt_pdev_handle htt_pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id); + +/** + * @brief Download a Batch Of Tx MSDUs + * @details + * Each MSDU already has the MSDU ID stored in the headroom of the + * netbuf data buffer, and has the HTT tx descriptor already attached + * as a prefix fragment to the netbuf. + * + * @param htt_pdev - the handle of the physical device sending the tx data + * @param head_msdu - the MSDU Head for Tx batch being transmitted + * @param num_msdus - The total Number of MSDU's provided for batch tx + * @return null-terminated linked-list of unaccepted frames + */ +adf_nbuf_t +htt_tx_send_batch( + htt_pdev_handle htt_pdev, + adf_nbuf_t head_msdu, + int num_msdus); + + + +/* The htt scheduler for queued packets in htt + * htt when unable to send to HTC because of lack of resource + * forms a nbuf queue which is flushed when tx completion event from + * target is recieved + */ + +void +htt_tx_sched(htt_pdev_handle pdev); + + +/** + * @brief Same as htt_tx_send_std, but can handle raw frames. + */ +int +htt_tx_send_nonstd( + htt_pdev_handle htt_pdev, + adf_nbuf_t msdu, + u_int16_t msdu_id, + enum htt_pkt_type pkt_type); + +/** + * @brief Initialize the tx descriptor. + * @details + * This function initializes the tx descriptor. + * The values for the standard tx descriptor fields are provided as + * function arguments. Non-standard descriptor fields, which don't + * have function arguments to specify their value, are set to zero. + * An exception to this initialization of non-standard fields to zero + * is the "extended TID" field, which is initialized to the "invalid" + * value (0x1f). + * + * @param pdev - the handle of the physical device sending the tx data + * @param htt_tx_desc - abstract handle to the tx descriptor + * @param htt_tx_desc_paddr_lo - physical address of the HTT tx descriptor + * @param desc_id - ID to tag the descriptor with. + * The target FW uses this ID to identify to the host which MSDUs + * the target is referring to in its tx completion / postpone / drop + * messages. + * This ID is abstract - it is only interpreted inside the host + * tx datapath SW. In practice, though, the ID is an index into an + * array of tx descriptor structs. + * This ID is used for both HL and LL systems, since in both systems + * the target may need to refer to a particular MSDU to explicitly tell + * the host when it may free the MSDU descriptor and network buffer. + * @param msdu - the MSDU that is being prepared for transmission + * @param msdu_info - tx MSDU meta-data + */ + +/* + * Provide a constant to specify the offset of the HTT portion of the + * HTT tx descriptor, to avoid having to export the descriptor defintion. + * The htt module checks internally that this exported offset is consistent + * with the private tx descriptor definition. + * + * Similarly, export a definition of the HTT tx descriptor size, and then + * check internally that this exported constant matches the private tx + * descriptor definition. + */ +#define HTT_TX_DESC_VADDR_OFFSET 8 +#define HTT_TX_DESC_SIZE 24 +static inline +void +htt_tx_desc_init( + htt_pdev_handle pdev, + void *htt_tx_desc, + u_int32_t htt_tx_desc_paddr_lo, + u_int16_t msdu_id, + adf_nbuf_t msdu, + struct htt_msdu_info_t *msdu_info, + struct ocb_tx_ctrl_hdr_t *tx_ctrl, + u_int8_t is_dsrc) +{ + u_int32_t *word0, *word1, *word3; + u_int32_t local_word0, local_word1, local_word3; + struct htt_host_tx_desc_t *htt_host_tx_desc = (struct htt_host_tx_desc_t *) + (((char *) htt_tx_desc) - HTT_TX_DESC_VADDR_OFFSET); + bool desc_ext_required = (tx_ctrl && tx_ctrl->all_flags != 0); + + word0 = (u_int32_t *) htt_tx_desc; + word1 = word0 + 1; + /* + * word2 is frag desc pointer + * word3 is peer_id + */ + word3 = word0 + 3; // Dword 3 + + /* + * HTT Tx Desc is in uncached memory. Used cached writes per word, to + * reduce unnecessary memory access. + */ + + local_word0 = 0; + HTT_H2T_MSG_TYPE_SET(local_word0, HTT_H2T_MSG_TYPE_TX_FRM); + HTT_TX_DESC_PKT_TYPE_SET(local_word0, msdu_info->info.l2_hdr_type); + HTT_TX_DESC_VDEV_ID_SET(local_word0, msdu_info->info.vdev_id); + if (tx_ctrl && tx_ctrl->valid_tid) { + HTT_TX_DESC_EXT_TID_SET(local_word0, tx_ctrl->ext_tid); + } else { + HTT_TX_DESC_EXT_TID_SET(local_word0, msdu_info->info.ext_tid); + } + HTT_TX_DESC_CKSUM_OFFLOAD_SET(local_word0, msdu_info->action.cksum_offload); + HTT_TX_DESC_EXTENSION_SET(local_word0, desc_ext_required); + if (pdev->cfg.is_high_latency) + HTT_TX_DESC_TX_COMP_SET(local_word0, msdu_info->action.tx_comp_req); + HTT_TX_DESC_NO_ENCRYPT_SET(local_word0, msdu_info->action.do_encrypt ? 0 : 1); + *word0 = local_word0; + + local_word1 = 0; + HTT_TX_DESC_FRM_LEN_SET(local_word1, adf_nbuf_len(msdu)); + HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id); + + *word1 = local_word1; + + /* Initialize peer_id to INVALID_PEER bcoz this is NOT Reinjection path*/ + local_word3 = HTT_INVALID_PEER; + if (tx_ctrl && tx_ctrl->channel_freq) { + HTT_TX_DESC_CHAN_FREQ_SET(local_word3, tx_ctrl->channel_freq); + } + *word3 = local_word3; + + /* + * If any of the tx control flags are set, then we need the extended + * HTT header. + */ + if (desc_ext_required) + { + struct htt_tx_msdu_desc_ext_t local_desc_ext = {0}; + + /* + * Copy the info that was read from TX control header from the user + * application to the extended HTT header. + * First copy everything + * to a local temp structure, and then copy everything to the + * actual uncached structure in one go to save memory writes. + */ + local_desc_ext.valid_pwr = tx_ctrl->valid_pwr; + local_desc_ext.valid_mcs_mask = tx_ctrl->valid_datarate; + local_desc_ext.valid_retries = tx_ctrl->valid_retries; + local_desc_ext.valid_expire_tsf = tx_ctrl->valid_expire_tsf; + local_desc_ext.valid_chainmask = tx_ctrl->valid_chain_mask; + + local_desc_ext.pwr = tx_ctrl->pwr; + if (tx_ctrl->valid_datarate && + tx_ctrl->datarate <= htt_ofdm_datarate_max) + local_desc_ext.mcs_mask = (1 << (tx_ctrl->datarate + 4)); + local_desc_ext.retry_limit = tx_ctrl->retry_limit; + local_desc_ext.expire_tsf_lo = tx_ctrl->expire_tsf_lo; + local_desc_ext.expire_tsf_hi = tx_ctrl->expire_tsf_hi; + local_desc_ext.chain_mask = tx_ctrl->chain_mask; + + local_desc_ext.is_dsrc = (is_dsrc != 0); + + adf_nbuf_push_head(msdu, sizeof(local_desc_ext)); + adf_os_mem_copy(adf_nbuf_data(msdu), &local_desc_ext, + sizeof(local_desc_ext)); } + + /* + * Specify that the data provided by the OS is a bytestream, + * and thus should not be byte-swapped during the HIF download + * even if the host is big-endian. + * There could be extra fragments added before the OS's fragments, + * e.g. for TSO, so it's incorrect to clear the frag 0 wordstream flag. + * Instead, clear the wordstream flag for the final fragment, which + * is certain to be (one of the) fragment(s) provided by the OS. + * Setting the flag for this final fragment suffices for specifying + * all fragments provided by the OS rather than added by the driver. + */ + adf_nbuf_set_frag_is_wordstream(msdu, adf_nbuf_get_num_frags(msdu) - 1, 0); + + /* store a link to the HTT tx descriptor within the netbuf */ + adf_nbuf_frag_push_head( + msdu, + HTT_TX_DESC_SIZE, + (char *) htt_host_tx_desc, /* virtual addr */ + htt_tx_desc_paddr_lo, 0 /* phys addr MSBs - n/a */); + + /* + * Indicate that the HTT header (and HTC header) is a meta-data + * "wordstream", i.e. series of u_int32_t, rather than a data + * bytestream. + * This allows the HIF download to byteswap the HTT + HTC headers if + * the host is big-endian, to convert to the target's little-endian + * format. + */ + adf_nbuf_set_frag_is_wordstream(msdu, 0, 1); +} + +/** + * @brief Set a flag to indicate that the MSDU in question was postponed. + * @details + * In systems in which the host retains its tx frame until the target sends + * a tx completion, the target has the option of discarding it's copy of + * the tx descriptor (and frame, for HL) and sending a "postpone" message + * to the host, to inform the host that it must eventually download the + * tx descriptor (and frame, for HL). + * Before the host downloads the postponed tx desc/frame again, it will use + * this function to set a flag in the HTT tx descriptor indicating that this + * is a re-send of a postponed frame, rather than a new frame. The target + * uses this flag to keep the correct order between re-sent and new tx frames. + * This function is relevant for LL systems. + * + * @param pdev - the handle of the physical device sending the tx data + * @param desc - abstract handle to the tx descriptor + */ +void +htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc); + +/** + * @brief Set a flag to tell the target that more tx downloads are en route. + * @details + * At times, particularly in response to a U-APSD trigger in a HL system, the + * host will download multiple tx descriptors (+ frames, in HL) in a batch. + * The host will use this function to set a "more" flag in the initial + * and interior frames of the batch, to tell the target that more tx frame + * downloads within the batch are imminent. + * + * @param pdev - the handle of the physical device sending the tx data + * @param desc - abstract handle to the tx descriptor + */ +void +htt_tx_desc_flag_batch_more(htt_pdev_handle pdev, void *desc); + +/** + * @brief Specify the number of fragments in the fragmentation descriptor. + * @details + * Specify the number of fragments within the MSDU, i.e. the number of + * elements within the fragmentation descriptor. + * For LL, this is used to terminate the list of fragments used by the + * HW's tx MAC DMA. + * For HL, this is used to terminate the list of fragments provided to + * HTC for download. + * + * @param pdev - the handle of the physical device sending the tx data + * @param desc - abstract handle to the tx descriptor + * @param num_frags - the number of fragments comprising the MSDU + */ +static inline +void +htt_tx_desc_num_frags(htt_pdev_handle pdev, void *desc, u_int32_t num_frags) +{ + /* + * Set the element after the valid frag elems to 0x0, + * to terminate the list of fragments. + */ + *((u_int32_t *) + (((char *) desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0; +} + +/** + * @brief Specify the location and size of a fragment of a tx MSDU. + * @details + * In LL systems, the tx MAC DMA needs to know how the MSDU is constructed + * from fragments. + * In LL and HL systems, the HIF's download DMA to the target (LL: tx desc + * + header of tx payload; HL: tx desc + entire tx payload) needs to know + * where to find the fragments to download. + * The tx data SW uses this function to specify the location and size of + * each of the MSDU's fragments. + * + * @param pdev - the handle of the physical device sending the tx data + * @param desc - abstract handle to the HTT tx descriptor + * @param frag_num - which fragment is being specified (zero-based indexing) + * @param frag_phys_addr - DMA/physical address of the fragment + * @param frag_len - number of bytes within the fragment + */ +static inline +void +htt_tx_desc_frag( + htt_pdev_handle pdev, + void *desc, + int frag_num, + u_int32_t frag_phys_addr, + u_int16_t frag_len) +{ + u_int32_t *word = + (u_int32_t *) (((char *) desc) + HTT_TX_DESC_LEN + frag_num * 8); + *word = frag_phys_addr; + word++; + *word = frag_len; +} + +void htt_tx_desc_frags_table_set( + htt_pdev_handle pdev, + void *desc, + u_int32_t paddr, + int reset); + +/** + * @brief Specify the type and subtype of a tx frame. + * + * @param pdev - the handle of the physical device sending the tx data + * @param type - format of the MSDU (802.3, native WiFi, raw, or mgmt) + * @param sub_type - sub_type (relevant for raw frames) + */ +static inline +void +htt_tx_desc_type( + htt_pdev_handle pdev, + void *htt_tx_desc, + enum wlan_frm_fmt type, + u_int8_t sub_type) +{ + u_int32_t *word0; + + word0 = (u_int32_t *) htt_tx_desc; + /* clear old values */ + *word0 &= ~(HTT_TX_DESC_PKT_TYPE_M | HTT_TX_DESC_PKT_SUBTYPE_M); + /* write new values */ + HTT_TX_DESC_PKT_TYPE_SET(*word0, type); + HTT_TX_DESC_PKT_SUBTYPE_SET(*word0, sub_type); +} + +/***** TX MGMT DESC management APIs ****/ + +/* Number of mgmt descriptors in the pool */ +#define HTT_MAX_NUM_MGMT_DESCS 32 + +/** htt_tx_mgmt_desc_pool_alloc + * @description - allocates the memory for mgmt frame descriptors + * @param - htt pdev object + * @param - num of descriptors to be allocated in the pool + */ +void +htt_tx_mgmt_desc_pool_alloc(struct htt_pdev_t *pdev, A_UINT32 num_elems); + +/** htt_tx_mgmt_desc_alloc + * @description - reserves a mgmt descriptor from the pool + * @param - htt pdev object + * @param - pointer to variable to hold the allocated desc id + * @param - pointer to the mamangement from UMAC + * @return - pointer the allocated mgmt descriptor + */ +adf_nbuf_t +htt_tx_mgmt_desc_alloc(struct htt_pdev_t *pdev, A_UINT32 *desc_id, adf_nbuf_t mgmt_frm); + +/** htt_tx_mgmt_desc_free + * @description - releases the management descriptor back to the pool + * @param - htt pdev object + * @param - descriptor ID + */ +void +htt_tx_mgmt_desc_free(struct htt_pdev_t *pdev, A_UINT8 desc_id, A_UINT32 status); + +/** htt_tx_mgmt_desc_pool_free + * @description - releases all the resources allocated for mgmt desc pool + * @param - htt pdev object + */ +void +htt_tx_mgmt_desc_pool_free(struct htt_pdev_t *pdev); + + +/** + * @brief Provide a buffer to store a 802.11 header added by SW tx encap + * + * @param htt_tx_desc - which frame the 802.11 header is being added to + * @param new_l2_hdr_size - how large the buffer needs to be + */ +#define htt_tx_desc_mpdu_header(htt_tx_desc, new_l2_hdr_size) /*NULL*/ + +/** + * @brief How many tx credits would be consumed by the specified tx frame. + * + * @param msdu - the tx frame in question + * @return number of credits used for this tx frame + */ +#define htt_tx_msdu_credit(msdu) 1 /* 1 credit per buffer */ + + + +#ifdef HTT_DBG +void +htt_tx_desc_display(void *tx_desc); +#else +#define htt_tx_desc_display(tx_desc) +#endif + +static inline +void htt_tx_desc_set_peer_id(void *htt_tx_desc, u_int16_t peer_id) +{ + u_int16_t *peer_id_field_ptr; + + peer_id_field_ptr = (u_int16_t *) + (htt_tx_desc + HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES); + + *peer_id_field_ptr = peer_id; +} +static inline +void htt_tx_desc_set_chanfreq(void *htt_tx_desc, u_int16_t chanfreq) +{ + u_int16_t *chanfreq_field_ptr; + + chanfreq_field_ptr = (u_int16_t *) + (htt_tx_desc + HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES); + + *chanfreq_field_ptr = chanfreq; +} + +#endif /* _OL_HTT_TX_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_if_athvar.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_if_athvar.h new file mode 100644 index 000000000000..7cdc283b4a1a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_if_athvar.h @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * Defintions for the Atheros Wireless LAN controller driver. + */ +#ifndef _DEV_OL_ATH_ATHVAR_H +#define _DEV_OL_ATH_ATHVAR_H + +#include +#include +#include +#include "adf_os_types.h" +#include "adf_os_lock.h" +#include "wmi_unified_api.h" +#include "htc_api.h" +#include "bmi_msg.h" +#include "ol_txrx_api.h" +#include "ol_txrx_ctrl_api.h" +#include "ol_txrx_osif_api.h" +#include "ol_params.h" +#include + +#ifdef CONFIG_CNSS +#include +#endif + + +#include "ol_ctrl_addba_api.h" +typedef void * hif_handle_t; + +struct ol_version { + u_int32_t host_ver; + u_int32_t target_ver; + u_int32_t wlan_ver; + u_int32_t wlan_ver_1; + u_int32_t abi_ver; +}; + +typedef enum _ATH_BIN_FILE { + ATH_OTP_FILE, + ATH_FIRMWARE_FILE, + ATH_PATCH_FILE, + ATH_BOARD_DATA_FILE, + ATH_FLASH_FILE, + ATH_SETUP_FILE, +} ATH_BIN_FILE; + +typedef enum _ol_target_status { + OL_TRGET_STATUS_CONNECTED = 0, /* target connected */ + OL_TRGET_STATUS_RESET, /* target got reset */ + OL_TRGET_STATUS_EJECT, /* target got ejected */ + OL_TRGET_STATUS_SUSPEND /*target got suspend*/ +} ol_target_status; + +enum ol_ath_tx_ecodes { + TX_IN_PKT_INCR=0, + TX_OUT_HDR_COMPL, + TX_OUT_PKT_COMPL, + PKT_ENCAP_FAIL, + TX_PKT_BAD, + RX_RCV_MSG_RX_IND, + RX_RCV_MSG_PEER_MAP, + RX_RCV_MSG_TYPE_TEST +} ; + +#ifdef HIF_SDIO +#define MAX_FILE_NAME 20 +struct ol_fw_files { + char image_file[MAX_FILE_NAME]; + char board_data[MAX_FILE_NAME]; + char otp_data[MAX_FILE_NAME]; + char utf_file[MAX_FILE_NAME]; + char utf_board_data[MAX_FILE_NAME]; + char setup_file[MAX_FILE_NAME]; + char epping_file[MAX_FILE_NAME]; +}; +#endif + +#ifdef QCA_ARP_SPOOFING_WAR +enum { + RX_INTRA_BSS_FWD, + FILTER_NONE +}; + +typedef int (*hdd_filter_cb_t)(u_int32_t, adf_nbuf_t, u_int32_t); +#endif + +#ifndef ATH_CAP_DCS_CWIM +#define ATH_CAP_DCS_CWIM 0x1 +#define ATH_CAP_DCS_WLANIM 0x2 +#endif +/* + * structure to hold the packet error count for CE and hif layer +*/ +struct ol_ath_stats { + int hif_pipe_no_resrc_count; + int ce_ring_delta_fail_count; +}; + +#ifdef HIF_USB +/* Magic patterns for FW to report crash information (Rome USB) */ +#define FW_ASSERT_PATTERN 0x0000c600 +#define FW_REG_PATTERN 0x0000d600 +#define FW_REG_END_PATTERN 0x0000e600 +#define FW_RAMDUMP_PATTERN 0x0000f600 +#define FW_RAMDUMP_END_PATTERN 0x0000f601 +#define FW_RAMDUMP_PATTERN_MASK 0xfffffff0 + +#define FW_REG_DUMP_CNT 60 + +/* FW RAM segments (Rome USB) */ +enum { + FW_RAM_SEG_DRAM, + FW_RAM_SEG_IRAM, + FW_RAM_SEG_AXI, + FW_RAM_SEG_CNT +}; + +/* Allocate 384K memory to save each segment of ram dump */ +#define FW_RAMDUMP_SEG_SIZE 393216 + +/* structure to save RAM dump information */ +struct fw_ramdump { + A_UINT32 start_addr; + A_UINT32 length; + A_UINT8 *mem; +}; +#endif + +struct ol_softc { + /* + * handle for code that uses the osdep.h version of OS + * abstraction primitives + */ + osdev_t sc_osdev; + + /* + * handle for code that uses adf version of OS + * abstraction primitives + */ + adf_os_device_t adf_dev; + + struct ol_version version; + + /* Packet statistics */ + struct ol_ath_stats pkt_stats; + + u_int32_t target_type; /* A_TARGET_TYPE_* */ + u_int32_t target_fw_version; + u_int32_t target_version; + u_int32_t target_revision; + u_int8_t crm_version_string[64]; /* store pHalStartRsp->startRspParams.wcnssCrmVersionString */ + u_int8_t wlan_version_string[64]; /* store pHalStartRsp->startRspParams.wcnssWlanVersionString */ + ol_target_status target_status; /* target status */ + bool is_sim; /* is this a simulator */ + u_int8_t *cal_in_flash; /* calibration data is stored in flash */ + void *cal_mem; /* virtual address for the calibration data on the flash */ + + WLAN_INIT_STATUS wlan_init_status; /* status of target init */ + + /* BMI info */ + void *bmi_ol_priv; /* OS-dependent private info for BMI */ + bool bmiDone; + bool bmiUADone; + u_int8_t *pBMICmdBuf; + dma_addr_t BMICmd_pa; + OS_DMA_MEM_CONTEXT(bmicmd_dmacontext) + + u_int8_t *pBMIRspBuf; + dma_addr_t BMIRsp_pa; + u_int32_t last_rxlen; /* length of last response */ + OS_DMA_MEM_CONTEXT(bmirsp_dmacontext) + + void *MSI_magic; + dma_addr_t MSI_magic_dma; + OS_DMA_MEM_CONTEXT(MSI_dmacontext) + + /* Handles for Lower Layers : filled in at init time */ + hif_handle_t hif_hdl; +#if defined(HIF_PCI) + struct hif_pci_softc *hif_sc; +#elif defined(HIF_USB) + struct hif_usb_softc *hif_sc; +#else + struct ath_hif_sdio_softc *hif_sc; +#endif + + /* HTC handles */ + void *htc_handle; + + bool IdlePowerSave; + int ProtocolPowerSave; + A_BOOL fEnableBeaconEarlyTermination; + u_int8_t bcnEarlyTermWakeInterval; + + /* ol data path handle */ + ol_txrx_pdev_handle pdev_txrx_handle; + + /* UTF event information */ + struct { + u_int8_t *data; + u_int32_t length; + adf_os_size_t offset; + u_int8_t currentSeq; + u_int8_t expectedSeq; + } utf_event_info; + + struct ol_wow_info *scn_wowInfo; + +#ifdef PERE_IP_HDR_ALIGNMENT_WAR + bool host_80211_enable; /* Enables native-wifi mode on host */ +#endif + bool enableuartprint; /* enable uart/serial prints from target */ + bool enablefwlog; /* enable fwlog */ + /* enable FW self-recovery for Rome USB */ + bool enableFwSelfRecovery; +#ifdef HIF_USB + /* structure to save FW RAM dump (Rome USB) */ + struct fw_ramdump *ramdump[FW_RAM_SEG_CNT]; + A_UINT8 ramdump_index; + bool fw_ram_dumping; +#endif + + bool enablesinglebinary; /* Use single binary for FW */ + HAL_REG_CAPABILITIES hal_reg_capabilities; + struct ol_regdmn *ol_regdmn_handle; + u_int8_t bcn_mode; + u_int8_t arp_override; + /* + * Includes host side stack level stats + + * radio level athstats + */ + struct wlan_dbg_stats ath_stats; + int16_t chan_nf; /* noise_floor */ + u_int32_t min_tx_power; + u_int32_t max_tx_power; + u_int32_t txpowlimit2G; + u_int32_t txpowlimit5G; + u_int32_t txpower_scale; + u_int32_t chan_tx_pwr; + u_int32_t vdev_count; + u_int32_t max_bcn_ie_size; + adf_os_spinlock_t scn_lock; + + u_int8_t vow_extstats; + + u_int8_t scn_dcs; /* if dcs enabled or not*/ + wdi_event_subscribe scn_rx_peer_invalid_subscriber; + u_int8_t proxy_sta; + u_int8_t bcn_enabled; + u_int8_t dtcs; /* Dynamic Tx Chainmask Selection enabled/disabled */ + u_int32_t set_ht_vht_ies:1; /* true if vht ies are set on target */ + bool scn_cwmenable; /*CWM enable/disable state*/ + u_int8_t max_no_of_peers; +#ifdef CONFIG_CNSS + struct cnss_fw_files fw_files; +#elif defined(HIF_SDIO) + struct ol_fw_files fw_files; +#endif +#if defined(CONFIG_CNSS) || defined(HIF_SDIO) + void *ramdump_base; + unsigned long ramdump_address; + unsigned long ramdump_size; +#endif + bool enable_self_recovery; +#ifdef WLAN_FEATURE_LPSS + bool enablelpasssupport; +#endif + bool enableRamdumpCollection; +#ifdef FEATURE_RUNTIME_PM + bool enable_runtime_pm; + u_int32_t runtime_pm_delay; +#endif +#ifdef FEATURE_SECURE_FIRMWARE + bool enable_fw_hash_check; +#endif + uint16_t board_id; +}; + +#ifdef PERE_IP_HDR_ALIGNMENT_WAR +#define ol_scn_host_80211_enable_get(_ol_pdev_hdl) \ + ((struct ol_softc *)(_ol_pdev_hdl))->host_80211_enable +#endif + +struct bcn_buf_entry { + A_BOOL is_dma_mapped; + adf_nbuf_t bcn_buf; + TAILQ_ENTRY(bcn_buf_entry) deferred_bcn_list_elem; +}; + +struct ol_ath_vap_net80211 { + struct ol_softc *av_sc; /* back pointer to softc */ + ol_txrx_vdev_handle av_txrx_handle; /* ol data path handle */ + u_int32_t av_if_id; /* interface id */ + u_int64_t av_tsfadjust; /* Adjusted TSF, host endian */ + bool av_beacon_offload; /* Handle beacons in FW */ + adf_nbuf_t av_wbuf; /* Beacon buffer */ + A_BOOL is_dma_mapped; + os_timer_t av_timer; + bool av_ol_resmgr_wait; /* UMAC waits for target */ + /* event to bringup vap*/ + adf_os_spinlock_t avn_lock; + TAILQ_HEAD(, bcn_buf_entry) deferred_bcn_list; + os_timer_t av_target_stop_timer; + bool av_set_target_stopping; + bool av_target_stopped; +}; +#define OL_ATH_VAP_NET80211(_vap) ((struct ol_ath_vap_net80211 *)(_vap)) + +struct ol_ath_node_net80211 { + ol_txrx_peer_handle an_txrx_handle; /* ol data path handle */ +}; + +#define OL_ATH_NODE_NET80211(_ni) ((struct ol_ath_node_net80211 *)(_ni)) + +#define UAPSD_SRV_INTERVAL_DEFAULT_BK_BE_VI 300 /* Default U-APSD Service Interval in msec for BK, BE and VI */ +#define UAPSD_SRV_INTERVAL_DEFAULT_VO 20 /* Default U-APSD Service Interval in msec for VO */ +#define UAPSD_SUS_INTERVAL_DEFAULT 2000 /* Default U-APSD Suspend Interval in msec for BK, BE and VI */ +#define UAPSD_DELAY_INTERVAL_DEFAULT 3000 /* Default U-APSD Delay Interval in msec for BK, BE and VI */ +#define UAPSD_USER_PRIO_BE 0 +#define UAPSD_USER_PRIO_BK 2 +#define UAPSD_USER_PRIO_VI 5 +#define UAPSD_USER_PRIO_VO 7 + +#define SIR_MAC_DS_PARAM_SET_EID 3 +#define SIR_MAC_EDCA_PARAM_SET_EID 12 +#define SIR_MAC_CHNL_SWITCH_ANN_EID 37 +#define SIR_MAC_QUIET_EID 40 +#define SIR_MAC_ERP_INFO_EID 42 +#define SIR_MAC_QOS_CAPABILITY_EID 46 +#define SIR_MAC_HT_INFO_EID 61 + + void ol_target_failure(void *instance, A_STATUS status); + +int ol_asf_adf_attach(struct ol_softc *scn); + +int ol_ath_detach(struct ol_softc *scn, int force); +void ol_ath_utf_detach(struct ol_softc *scn); +#ifdef QVIT +void ol_ath_qvit_detach(struct ol_softc *scn); +void ol_ath_qvit_attach(struct ol_softc *scn); +#endif + +int ol_ath_resume(struct ol_softc *scn); + +int ol_ath_suspend(struct ol_softc *scn); + +int ol_ath_cwm_attach(struct ol_softc *scn); + +u_int8_t *ol_ath_vap_get_myaddr(struct ol_softc *scn, u_int8_t vdev_id); + +void ol_ath_utf_attach(struct ol_softc *scn); + +void ol_ath_vap_send_hdr_complete(void *ctx, HTC_PACKET_QUEUE *htc_pkt_list); + + +void ol_rx_indicate(void *ctx, adf_nbuf_t wbuf); + +void ol_rx_handler(void *ctx, HTC_PACKET *htc_packet); + +void ol_ath_beacon_stop(struct ol_softc *scn, + struct ol_ath_vap_net80211 *avn); + +u_int32_t host_interest_item_address(u_int32_t target_type, u_int32_t item_offset); + +int +ol_ath_set_config_param(struct ol_softc *scn, ol_ath_param_t param, void *buff); + +int +ol_ath_get_config_param(struct ol_softc *scn, ol_ath_param_t param, void *buff); + +int +ol_hal_set_config_param(struct ol_softc *scn, ol_hal_param_t param, void *buff); + +int +ol_hal_get_config_param(struct ol_softc *scn, ol_hal_param_t param, void *buff); + +void ol_ath_host_config_update(struct ol_softc *scn); + +int ol_ath_suspend_target(struct ol_softc *scn, int disable_target_intr); +int ol_ath_resume_target(struct ol_softc *scn); + +int wmi_unified_pdev_get_tpc_config(wmi_unified_t wmi_handle, u_int32_t param); +void ol_get_wlan_dbg_stats(struct ol_softc *scn, struct wlan_dbg_stats *dbg_stats); + +int +wmi_unified_node_set_param(wmi_unified_t wmi_handle, u_int8_t *peer_addr,u_int32_t param_id, + u_int32_t param_val,u_int32_t vdev_id); + + +#ifdef BIG_ENDIAN_HOST + /* This API is used in copying in elements to WMI message, + since WMI message uses multilpes of 4 bytes, This API + converts length into multiples of 4 bytes, and performs copy + */ +#define OL_IF_MSG_COPY_CHAR_ARRAY(destp, srcp, len) do { \ + int j; \ + u_int32_t *src, *dest; \ + src = (u_int32_t *)srcp; \ + dest = (u_int32_t *)destp; \ + for(j=0; j < roundup(len, sizeof(u_int32_t))/4; j++) { \ + *(dest+j) = adf_os_le32_to_cpu(*(src+j)); \ + } \ + } while(0) + +#else + +#define OL_IF_MSG_COPY_CHAR_ARRAY(destp, srcp, len) do { \ + OS_MEMCPY(destp, srcp, len); \ + } while(0) + +#endif + +/* Keep Alive KeepAliveParam. */ +typedef struct +{ + u_int8_t keepAliveEnable;//Enable or Disable + u_int32_t keepAliveMethod;// Type of frame which need to send for keep alive purpose + u_int32_t keepAliveInterval;//Interval in Seconds + u_int8_t hostIpv4Addr[4]; //Used only when method type is Arp + u_int8_t destIpv4Addr[4];//Used only when method type is Arp + u_int8_t destMacAddr[6];//Used only when method type is Arp +} KeepAliveParam, *pKeepAliveParam; + +#endif /* _DEV_OL_ATH_ATHVAR_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_osif_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_osif_api.h new file mode 100644 index 000000000000..2c13692de3a8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_osif_api.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_osif_api.h + * @brief Definitions used in multiple external interfaces to the txrx SW. + */ +#ifndef _OL_OSIF_API__H_ +#define _OL_OSIF_API__H_ + +/** + * @typedef ol_osif_vdev_handle + * @brief opaque handle for OS shim virtual device object + */ +struct ol_osif_vdev_t; +typedef struct ol_osif_vdev_t* ol_osif_vdev_handle; + +#endif /* _OL_OSIF_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_params.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_params.h new file mode 100644 index 000000000000..452cc0839be8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_params.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * Defintions for the Atheros Wireless LAN controller driver. + */ +#ifndef _DEV_OL_PARAMS_H +#define _DEV_OL_PARAMS_H +#include "ol_txrx_stats.h" +#include "wlan_defs.h" /* for wlan statst definitions */ +/* +** Enumeration of PDEV Configuration parameter +*/ + +typedef enum _ol_ath_param_t { + OL_ATH_PARAM_TXCHAINMASK = 0, + OL_ATH_PARAM_RXCHAINMASK, + OL_ATH_PARAM_TXCHAINMASKLEGACY, + OL_ATH_PARAM_RXCHAINMASKLEGACY, + OL_ATH_PARAM_CHAINMASK_SEL, + OL_ATH_PARAM_AMPDU, + OL_ATH_PARAM_AMPDU_LIMIT, + OL_ATH_PARAM_AMPDU_SUBFRAMES, + OL_ATH_PARAM_LDPC, + OL_ATH_PARAM_NON_AGG_SW_RETRY_TH, + OL_ATH_PARAM_AGG_SW_RETRY_TH, + OL_ATH_PARAM_STA_KICKOUT_TH, + OL_ATH_PARAM_WLAN_PROF_ENABLE, + OL_ATH_PARAM_LTR_ENABLE, + OL_ATH_PARAM_LTR_AC_LATENCY_BE, + OL_ATH_PARAM_LTR_AC_LATENCY_BK, + OL_ATH_PARAM_LTR_AC_LATENCY_VI, + OL_ATH_PARAM_LTR_AC_LATENCY_VO, + OL_ATH_PARAM_LTR_AC_LATENCY_TIMEOUT, + OL_ATH_PARAM_LTR_TX_ACTIVITY_TIMEOUT, + OL_ATH_PARAM_LTR_SLEEP_OVERRIDE, + OL_ATH_PARAM_LTR_RX_OVERRIDE, + OL_ATH_PARAM_L1SS_ENABLE, + OL_ATH_PARAM_DSLEEP_ENABLE, + OL_ATH_PARAM_PCIELP_TXBUF_FLUSH, + OL_ATH_PARAM_PCIELP_TXBUF_WATERMARK, + OL_ATH_PARAM_PCIELP_TXBUF_TMO_EN, + OL_ATH_PARAM_PCIELP_TXBUF_TMO_VALUE, + OL_ATH_PARAM_BCN_BURST, + OL_ATH_PARAM_ARP_AC_OVERRIDE, + OL_ATH_PARAM_TXPOWER_LIMIT2G, + OL_ATH_PARAM_TXPOWER_LIMIT5G, + OL_ATH_PARAM_TXPOWER_SCALE, + OL_ATH_PARAM_DCS, + OL_ATH_PARAM_ANI_ENABLE, + OL_ATH_PARAM_ANI_POLL_PERIOD, + OL_ATH_PARAM_ANI_LISTEN_PERIOD, + OL_ATH_PARAM_ANI_OFDM_LEVEL, + OL_ATH_PARAM_ANI_CCK_LEVEL, + OL_ATH_PARAM_PROXYSTA, + OL_ATH_PARAM_DYN_TX_CHAINMASK, + OL_ATH_PARAM_VOW_EXT_STATS, + OL_ATH_PARAM_PWR_GATING_ENABLE, + OL_ATH_PARAM_CHATTER, +} ol_ath_param_t; + +/* +** Enumeration of PDEV Configuration parameter +*/ + +typedef enum _ol_hal_param_t { + OL_HAL_CONFIG_DMA_BEACON_RESPONSE_TIME = 0 +} ol_hal_param_t; + + +/* +** structure to hold all stats information +** for offload device interface +*/ +struct ol_stats { + int txrx_stats_level; + struct ol_txrx_stats txrx_stats; + struct wlan_dbg_stats stats; +}; +#endif /* _DEV_OL_PARAMS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_api.h new file mode 100644 index 000000000000..59434116c97c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_api.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_api.h + * @brief Definitions used in multiple external interfaces to the txrx SW. + */ +#ifndef _OL_TXRX_API__H_ +#define _OL_TXRX_API__H_ + +/** + * @typedef ol_txrx_pdev_handle + * @brief opaque handle for txrx physical device object + */ +struct ol_txrx_pdev_t; +typedef struct ol_txrx_pdev_t* ol_txrx_pdev_handle; + +/** + * @typedef ol_txrx_vdev_handle + * @brief opaque handle for txrx virtual device object + */ +struct ol_txrx_vdev_t; +typedef struct ol_txrx_vdev_t* ol_txrx_vdev_handle; + +/** + * @typedef ol_txrx_peer_handle + * @brief opaque handle for txrx peer object + */ +struct ol_txrx_peer_t; +typedef struct ol_txrx_peer_t* ol_txrx_peer_handle; + +/** + * @brief ADDBA negotiation status, used both during requests and confirmations + */ +enum ol_addba_status { + /* status: negotiation started or completed successfully */ + ol_addba_success, + + /* reject: aggregation is not applicable - don't try again */ + ol_addba_reject, + + /* busy: ADDBA negotiation couldn't be performed - try again later */ + ol_addba_busy, +}; + +enum ol_sec_type { + ol_sec_type_none, + ol_sec_type_wep128, + ol_sec_type_wep104, + ol_sec_type_wep40, + ol_sec_type_tkip, + ol_sec_type_tkip_nomic, + ol_sec_type_aes_ccmp, + ol_sec_type_wapi, + + /* keep this last! */ + ol_sec_type_types +}; + +/** + * @enum ol_tx_spec + * @brief indicate what non-standard transmission actions to apply + * @details + * Indicate one or more of the following: + * - The tx frame already has a complete 802.11 header. + * Thus, skip 802.3/native-WiFi to 802.11 header encapsulation and + * A-MSDU aggregation. + * - The tx frame should not be aggregated (A-MPDU or A-MSDU) + * - The tx frame is already encrypted - don't attempt encryption. + * - The tx frame is a segment of a TCP jumbo frame. + * - This tx frame should not be unmapped and freed by the txrx layer + * after transmission, but instead given to a registered tx completion + * callback. + * More than one of these specification can apply, though typically + * only a single specification is applied to a tx frame. + * A compound specification can be created, as a bit-OR of these + * specifications. + */ +enum ol_tx_spec { + ol_tx_spec_std = 0x0, /* do regular processing */ + ol_tx_spec_raw = 0x1, /* skip encap + A-MSDU aggr */ + ol_tx_spec_no_aggr = 0x2, /* skip encap + all aggr */ + ol_tx_spec_no_encrypt = 0x4, /* skip encap + encrypt */ + ol_tx_spec_tso = 0x8, /* TCP segmented */ + ol_tx_spec_nwifi_no_encrypt = 0x10, /* skip encrypt for nwifi */ + ol_tx_spec_no_free = 0x20, /* give to cb rather than free */ +}; + +#endif /* _OL_TXRX_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h new file mode 100644 index 000000000000..ce59ca18ff6f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h @@ -0,0 +1,1334 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_ctrl_api.h + * @brief Define the host data API functions called by the host control SW. + */ +#ifndef _OL_TXRX_CTRL_API__H_ +#define _OL_TXRX_CTRL_API__H_ + +#include /* A_STATUS */ +#include /* adf_nbuf_t */ +#include /* adf_os_device_t */ +#include /* HTC_HANDLE */ + +#include /* ol_osif_vdev_handle */ +#include /* ol_txrx_pdev_handle, etc. */ +#include /* ol_pdev_handle, ol_vdev_handle */ + +#include /* MAX_SPATIAL_STREAM */ + +/** + * @brief modes that a virtual device can operate as + * @details + * A virtual device can operate as an AP, an IBSS, a STA (client), + * in monitor mode or in OCB mode + */ +enum wlan_op_mode { + wlan_op_mode_unknown, + wlan_op_mode_ap, + wlan_op_mode_ibss, + wlan_op_mode_sta, + wlan_op_mode_monitor, + wlan_op_mode_ocb, +}; + +#define OL_TXQ_PAUSE_REASON_FW (1 << 0) +#define OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED (1 << 1) +#define OL_TXQ_PAUSE_REASON_TX_ABORT (1 << 2) +#define OL_TXQ_PAUSE_REASON_VDEV_STOP (1 << 3) +#define OL_TXQ_PAUSE_REASON_VDEV_SUSPEND (1 << 4) + +/* command options for dumpStats*/ +#define WLAN_HDD_STATS 0 +#define WLAN_TXRX_STATS 1 +#define WLAN_TXRX_HIST_STATS 2 +#ifdef CONFIG_HL_SUPPORT +#define WLAN_SCHEDULER_STATS 21 +#define WLAN_TX_QUEUE_STATS 22 +#define WLAN_BUNDLE_STATS 23 +#define WLAN_CREDIT_STATS 24 +#endif + +/** + * @brief Set up the data SW subsystem. + * @details + * As part of the WLAN device attach, the data SW subsystem has + * to be attached as a component within the WLAN device. + * This attach allocates and initializes the physical device object + * used by the data SW. + * The data SW subsystem attach needs to happen after the target has + * be started, and host / target parameter negotiation has completed, + * since the host data SW uses some of these host/target negotiated + * parameters (e.g. peer ID range) during the initializations within + * its attach function. + * However, the host data SW is not allowed to send HTC messages to the + * target within this pdev_attach function call, since the HTC setup + * has not complete at this stage of initializations. Any messaging + * to the target has to be done in the separate pdev_attach_target call + * that is invoked after HTC setup is complete. + * + * @param ctrl_pdev - control SW's physical device handle, needed as an + * argument for dynamic configuration queries + * @param htc_pdev - the HTC physical device handle. This is not needed + * by the txrx module, but needs to be passed along to the HTT module. + * @param osdev - OS handle needed as an argument for some OS primitives + * @return the data physical device object + */ +ol_txrx_pdev_handle +ol_txrx_pdev_attach( + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, + adf_os_device_t osdev); + +/** + * @brief Do final steps of data SW setup that send messages to the target. + * @details + * The majority of the data SW setup are done by the pdev_attach function, + * but this function completes the data SW setup by sending datapath + * configuration messages to the target. + * + * @param data_pdev - the physical device being initialized + */ +A_STATUS +ol_txrx_pdev_attach_target(ol_txrx_pdev_handle data_pdev); + + +/** + * @brief Allocate and initialize the data object for a new virtual device. + * @param data_pdev - the physical device the virtual device belongs to + * @param vdev_mac_addr - the MAC address of the virtual device + * @param vdev_id - the ID used to identify the virtual device to the target + * @param op_mode - whether this virtual device is operating as an AP, + * an IBSS, or a STA + * @return + * success: handle to new data vdev object, -OR- + * failure: NULL + */ +ol_txrx_vdev_handle +ol_txrx_vdev_attach( + ol_txrx_pdev_handle data_pdev, + u_int8_t *vdev_mac_addr, + u_int8_t vdev_id, + enum wlan_op_mode op_mode); + +/** + * @brief Allocate and set up references for a data peer object. + * @details + * When an association with a peer starts, the host's control SW + * uses this function to inform the host data SW. + * The host data SW allocates its own peer object, and stores a + * reference to the control peer object within the data peer object. + * The host data SW also stores a reference to the virtual device + * that the peer is associated with. This virtual device handle is + * used when the data SW delivers rx data frames to the OS shim layer. + * The host data SW returns a handle to the new peer data object, + * so a reference within the control peer object can be set to the + * data peer object. + * + * @param data_pdev - data physical device object that will indirectly + * own the data_peer object + * @param data_vdev - data virtual device object that will directly + * own the data_peer object + * @param peer_mac_addr - MAC address of the new peer + * @return handle to new data peer object, or NULL if the attach fails + */ +ol_txrx_peer_handle +ol_txrx_peer_attach( + ol_txrx_pdev_handle data_pdev, + ol_txrx_vdev_handle data_vdev, + u_int8_t *peer_mac_addr); + +/** +* @brief Parameter type to be input to ol_txrx_peer_update +* @details +* This struct is union,to be used to specify various informations to update +* txrx peer object. +*/ +typedef union { + u_int8_t qos_capable; + u_int8_t uapsd_mask; + enum ol_sec_type sec_type; +}ol_txrx_peer_update_param_t; + +/** +* @brief Parameter type to be input to ol_txrx_peer_update +* @details +* This enum is used to specify what exact information in ol_txrx_peer_update_param_t +* is used to update the txrx peer object. +*/ +typedef enum { + ol_txrx_peer_update_qos_capable = 1, + ol_txrx_peer_update_uapsdMask, + ol_txrx_peer_update_peer_security, +} ol_txrx_peer_update_select_t; + +/** + * @brief Update the data peer object as some informaiton changed in node. + * @details + * Only a single prarameter can be changed for each call to this func. + * + * @param peer - pointer to the node's object + * @param param - new param to be upated in peer object. + * @param select - specify what's parameter needed to be update + */ +void +ol_txrx_peer_update(ol_txrx_vdev_handle data_vdev, u_int8_t *peer_mac, + ol_txrx_peer_update_param_t *param, + ol_txrx_peer_update_select_t select); + +enum { + OL_TX_WMM_AC_BE, + OL_TX_WMM_AC_BK, + OL_TX_WMM_AC_VI, + OL_TX_WMM_AC_VO, + + OL_TX_NUM_WMM_AC +}; + +/** + * @brief Parameter type to pass WMM setting to wdi_in_set_wmm_param + * @details + * The struct is used to specify informaiton to update TX WMM scheduler. + */ +struct ol_tx_ac_param_t { + u_int32_t aifs; + u_int32_t cwmin; + u_int32_t cwmax; +}; + +struct ol_tx_wmm_param_t { + struct ol_tx_ac_param_t ac[OL_TX_NUM_WMM_AC]; +}; + +/** + * @brief Set paramters of WMM scheduler per AC settings. . + * @details + * This function applies only to HL systems. + * + * @param data_pdev - the physical device being paused + * @param wmm_param - the wmm parameters + */ +#if defined(CONFIG_HL_SUPPORT) +void +ol_txrx_set_wmm_param(ol_txrx_pdev_handle data_pdev, struct ol_tx_wmm_param_t wmm_param); +#else +#define ol_txrx_set_wmm_param(data_pdev, wmm_param) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Notify tx data SW that a peer's transmissions are suspended. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * The HL host tx data SW is doing tx classification and tx download + * scheduling, and therefore also needs to actively participate in tx + * flow control. Specifically, the HL tx data SW needs to check whether a + * given peer is available to transmit to, or is paused. + * This function is used to tell the HL tx data SW when a peer is paused, + * so the host tx data SW can hold the tx frames for that SW. + * + * @param data_peer - which peer is being paused + */ +#define ol_txrx_peer_pause(data_peer) /* no-op */ + +/** + * @brief Notify tx data SW that a peer-TID is ready to transmit to. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * If a peer-TID has tx paused, then the tx datapath will end up queuing + * any tx frames that arrive from the OS shim for that peer-TID. + * In a HL system, the host tx data SW itself will classify the tx frame, + * and determine that it needs to be queued rather than downloaded to the + * target for transmission. + * Once the peer-TID is ready to accept data, the host control SW will call + * this function to notify the host data SW that the queued frames can be + * enabled for transmission, or specifically to download the tx frames + * to the target to transmit. + * The TID parameter is an extended version of the QoS TID. Values 0-15 + * indicate a regular QoS TID, and the value 16 indicates either non-QoS + * data, multicast data, or broadcast data. + * + * @param data_peer - which peer is being unpaused + * @param tid - which TID within the peer is being unpaused, or -1 as a + * wildcard to unpause all TIDs within the peer + */ +#if defined(CONFIG_HL_SUPPORT) +void +ol_txrx_peer_tid_unpause(ol_txrx_peer_handle data_peer, int tid); +#else +#define ol_txrx_peer_tid_unpause(data_peer, tid) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Tell a paused peer to release a specified number of tx frames. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * Download up to a specified maximum number of tx frames from the tx + * queues of the specified TIDs within the specified paused peer, usually + * in response to a U-APSD trigger from the peer. + * It is up to the host data SW to determine how to choose frames from the + * tx queues of the specified TIDs. However, the host data SW does need to + * provide long-term fairness across the U-APSD enabled TIDs. + * The host data SW will notify the target data FW when it is done downloading + * the batch of U-APSD triggered tx frames, so the target data FW can + * differentiate between an in-progress download versus a case when there are + * fewer tx frames available than the specified limit. + * This function is relevant primarily to HL U-APSD, where the frames are + * held in the host. + * + * @param peer - which peer sent the U-APSD trigger + * @param tid_mask - bitmask of U-APSD enabled TIDs from whose tx queues + * tx frames can be released + * @param max_frms - limit on the number of tx frames to release from the + * specified TID's queues within the specified peer + */ +#if defined(CONFIG_HL_SUPPORT) +void +ol_txrx_tx_release( + ol_txrx_peer_handle peer, + u_int32_t tid_mask, + int max_frms); +#else +#define ol_txrx_tx_release(peer, tid_mask, max_frms) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Suspend all tx data for the specified virtual device. + * @details + * This function applies primarily to HL systems, but also applies to + * LL systems that use per-vdev tx queues for MCC or thermal throttling. + * As an example, this function could be used when a single-channel physical + * device supports multiple channels by jumping back and forth between the + * channels in a time-shared manner. As the device is switched from channel + * A to channel B, the virtual devices that operate on channel A will be + * paused. + * + * @param data_vdev - the virtual device being paused + * @param reason - the reason for which vdev queue is getting paused + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, u_int32_t reason); +#else +#define ol_txrx_vdev_pause(data_vdev, reason) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Drop all tx data for the specified virtual device. + * @details + * This function applies primarily to HL systems, but also applies to + * LL systems that use per-vdev tx queues for MCC or thermal throttling. + * This function would typically be used by the ctrl SW after it parks + * a STA vdev and then resumes it, but to a new AP. In this case, though + * the same vdev can be used, any old tx frames queued inside it would be + * stale, and would need to be discarded. + * + * @param data_vdev - the virtual device being flushed + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +ol_txrx_vdev_flush(ol_txrx_vdev_handle data_vdev); +#else +#define ol_txrx_vdev_flush(data_vdev) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Resume tx for the specified virtual device. + * @details + * This function applies primarily to HL systems, but also applies to + * LL systems that use per-vdev tx queues for MCC or thermal throttling. + * + * @param data_vdev - the virtual device being unpaused + * @param reason - the reason for which vdev queue is getting unpaused + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +ol_txrx_vdev_unpause(ol_txrx_vdev_handle data_vdev, u_int32_t reason); +#else +#define ol_txrx_vdev_unpause(data_vdev, reason) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Suspend all tx data per thermal event/timer for the + * specified physical device + * @details + * This function applies only to HL systerms, and it makes pause and + * unpause operations happen in pairs. + */ +#if defined(CONFIG_HL_SUPPORT) +void +ol_txrx_throttle_pause(ol_txrx_pdev_handle data_pdev); +#else +#define ol_txrx_throttle_pause(data_pdev) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + + +/** + * @brief Resume all tx data per thermal event/timer for the + * specified physical device + * @details + * This function applies only to HL systerms, and it makes pause and + * unpause operations happen in pairs. + */ +#if defined(CONFIG_HL_SUPPORT) +void +ol_txrx_throttle_unpause(ol_txrx_pdev_handle data_pdev); +#else +#define ol_txrx_throttle_unpause(data_pdev) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * ol_txrx_pdev_pause() - Suspend all tx data for the specified physical device. + * @data_pdev: the physical device being paused. + * @reason: pause reason. + * One can provide multiple line descriptions + * for arguments. + * + * This function applies to HL systems - + * in LL systems, applies when txrx_vdev_pause_all is enabled. + * In some systems it is necessary to be able to temporarily + * suspend all WLAN traffic, e.g. to allow another device such as bluetooth + * to temporarily have exclusive access to shared RF chain resources. + * This function suspends tx traffic within the specified physical device. + * + * + * Return: None + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +ol_txrx_pdev_pause(ol_txrx_pdev_handle data_pdev, u_int32_t reason); +#else +#define ol_txrx_pdev_pause(data_pdev,reason) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * ol_txrx_pdev_unpause() - Resume tx for the specified physical device.. + * @data_pdev: the physical device being paused. + * @reason: pause reason. + * + * This function applies to HL systems - + * in LL systems, applies when txrx_vdev_pause_all is enabled. + * + * + * Return: None + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +ol_txrx_pdev_unpause(ol_txrx_pdev_handle data_pdev, u_int32_t reason); +#else +#define ol_txrx_pdev_unpause(data_pdev,reason) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Synchronize the data-path tx with a control-path target download + * @dtails + * @param data_pdev - the data-path physical device object + * @param sync_cnt - after the host data-path SW downloads this sync request + * to the target data-path FW, the target tx data-path will hold itself + * in suspension until it is given an out-of-band sync counter value that + * is equal to or greater than this counter value + */ +void +ol_txrx_tx_sync(ol_txrx_pdev_handle data_pdev, u_int8_t sync_cnt); + +/** + * @brief Delete a peer's data object. + * @details + * When the host's control SW disassociates a peer, it calls this + * function to delete the peer's data object. + * The reference stored in the control peer object to the data peer + * object (set up by a call to ol_peer_store()) is provided. + * + * @param data_peer - the object to delete + */ +void +ol_txrx_peer_detach(ol_txrx_peer_handle data_peer); + +typedef void (*ol_txrx_vdev_delete_cb)(void *context); + +/** + * @brief Deallocate the specified data virtual device object. + * @details + * All peers associated with the virtual device need to be deleted + * (ol_txrx_peer_detach) before the virtual device itself is deleted. + * However, for the peers to be fully deleted, the peer deletion has to + * percolate through the target data FW and back up to the host data SW. + * Thus, even though the host control SW may have issued a peer_detach + * call for each of the vdev's peers, the peer objects may still be + * allocated, pending removal of all references to them by the target FW. + * In this case, though the vdev_detach function call will still return + * immediately, the vdev itself won't actually be deleted, until the + * deletions of all its peers complete. + * The caller can provide a callback function pointer to be notified when + * the vdev deletion actually happens - whether it's directly within the + * vdev_detach call, or if it's deferred until all in-progress peer + * deletions have completed. + * + * @param data_vdev - data object for the virtual device in question + * @param callback - function to call (if non-NULL) once the vdev has + * been wholly deleted + * @param callback_context - context to provide in the callback + */ +void +ol_txrx_vdev_detach( + ol_txrx_vdev_handle data_vdev, + ol_txrx_vdev_delete_cb callback, + void *callback_context); + +/** + * @brief Delete the data SW state. + * @details + * This function is used when the WLAN driver is being removed to + * remove the host data component within the driver. + * All virtual devices within the physical device need to be deleted + * (ol_txrx_vdev_detach) before the physical device itself is deleted. + * + * @param data_pdev - the data physical device object being removed + * @param force - delete the pdev (and its vdevs and peers) even if there + * are outstanding references by the target to the vdevs and peers + * within the pdev + */ +void +ol_txrx_pdev_detach(ol_txrx_pdev_handle data_pdev, int force); + +typedef void +(*ol_txrx_data_tx_cb)(void *ctxt, adf_nbuf_t tx_frm, int had_error); + +/** + * @brief Store a delivery notification callback for specific data frames. + * @details + * Through a non-std tx function, the txrx SW can be given tx data frames + * that are specially marked to not be unmapped and freed by the tx SW + * when transmission completes. Rather, these specially-marked frames + * are provided to the callback registered with this function. + * + * @param data_vdev - which vdev the callback is being registered with + * (Currently the callback is stored in the pdev rather than the vdev.) + * @param callback - the function to call when tx frames marked as "no free" + * are done being transmitted + * @param ctxt - the context argument provided to the callback function + */ +void +ol_txrx_data_tx_cb_set( + ol_txrx_vdev_handle data_vdev, + ol_txrx_data_tx_cb callback, + void *ctxt); + + +/** + * @brief Allow the control-path SW to send data frames. + * @details + * Generally, all tx data frames come from the OS shim into the txrx layer. + * However, there are rare cases such as TDLS messaging where the UMAC + * control-path SW creates tx data frames. + * This UMAC SW can call this function to provide the tx data frames to + * the txrx layer. + * The UMAC SW can request a callback for these data frames after their + * transmission completes, by using the ol_txrx_data_tx_cb_set function + * to register a tx completion callback, and by specifying + * ol_tx_spec_no_free as the tx_spec arg when giving the frames to + * ol_tx_non_std. + * The MSDUs need to have the appropriate L2 header type (802.3 vs. 802.11), + * as specified by ol_cfg_frame_type(). + * + * @param data_vdev - which vdev should transmit the tx data frames + * @param tx_spec - what non-standard handling to apply to the tx data frames + * @param msdu_list - NULL-terminated list of tx MSDUs + */ +adf_nbuf_t +ol_tx_non_std( + ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list); + + +typedef void +(*ol_txrx_mgmt_tx_cb)(void *ctxt, adf_nbuf_t tx_mgmt_frm, int had_error); + +/** + * @brief Store a callback for delivery notifications for management frames. + * @details + * When the txrx SW receives notifications from the target that a tx frame + * has been delivered to its recipient, it will check if the tx frame + * is a management frame. If so, the txrx SW will check the management + * frame type specified when the frame was submitted for transmission. + * If there is a callback function registered for the type of managment + * frame in question, the txrx code will invoke the callback to inform + * the management + control SW that the mgmt frame was delivered. + * This function is used by the control SW to store a callback pointer + * for a given type of management frame. + * + * @param pdev - the data physical device object + * @param type - the type of mgmt frame the callback is used for + * @param download_cb - the callback for notification of delivery to the target + * @param ota_ack_cb - the callback for notification of delivery to the peer + * @param ctxt - context to use with the callback + */ +void +ol_txrx_mgmt_tx_cb_set( + ol_txrx_pdev_handle pdev, + u_int8_t type, + ol_txrx_mgmt_tx_cb download_cb, + ol_txrx_mgmt_tx_cb ota_ack_cb, + void *ctxt); + +/** + * @brief Transmit a management frame. + * @details + * Send the specified management frame from the specified virtual device. + * The type is used for determining whether to invoke a callback to inform + * the sender that the tx mgmt frame was delivered, and if so, which + * callback to use. + * + * @param vdev - virtual device transmitting the frame + * @param tx_mgmt_frm - management frame to transmit + * @param type - the type of managment frame (determines what callback to use) + * @param use_6mbps - specify whether management frame to transmit should use 6 Mbps + * rather than 1 Mbps min rate(for 5GHz band or P2P) + * @return + * 0 -> the frame is accepted for transmission, -OR- + * 1 -> the frame was not accepted + */ +int +ol_txrx_mgmt_send( + ol_txrx_vdev_handle vdev, + adf_nbuf_t tx_mgmt_frm, + u_int8_t type, + u_int8_t use_6mbps, + u_int16_t chanfreq); + +/** + * @brief Setup the monitor mode vap (vdev) for this pdev + * @details + * When a non-NULL vdev handle is registered as the monitor mode vdev, all + * packets received by the system are delivered to the OS stack on this + * interface in 802.11 MPDU format. Only a single monitor mode interface + * can be up at any timer. When the vdev handle is set to NULL the monitor + * mode delivery is stopped. This handle may either be a unique vdev + * object that only receives monitor mode packets OR a point to a a vdev + * object that also receives non-monitor traffic. In the second case the + * OS stack is responsible for delivering the two streams using approprate + * OS APIs + * + * @param pdev - the data physical device object + * @param vdev - the data virtual device object to deliver monitor mode + * packets on + * @return + * 0 -> the monitor mode vap was sucessfully setup + * -1 -> Unable to setup monitor mode + */ +int +ol_txrx_set_monitor_mode_vap( + ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev); + +/** + * @brief Setup the current operating channel of the device + * @details + * Mainly used when populating monitor mode status that requires the + * current operating channel + * + * @param pdev - the data physical device object + * @param chan_mhz - the channel frequency (mhz) + * packets on + * @return - void + */ +void +ol_txrx_set_curchan( + ol_txrx_pdev_handle pdev, + u_int32_t chan_mhz); + +/** + * @brief Get the number of pending transmit frames that are awaiting completion. + * @details + * Mainly used in clean up path to make sure all buffers have been free'ed + * + * @param pdev - the data physical device object + * @return - count of pending frames + */ +int +ol_txrx_get_tx_pending( + ol_txrx_pdev_handle pdev); + +void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev); + +/** + * @brief Discard all tx frames that are pending in txrx. + * @details + * Mainly used in clean up path to make sure all pending tx packets + * held by txrx are returned back to OS shim immediately. + * + * @param pdev - the data physical device object + * @return - void + */ +void +ol_txrx_discard_tx_pending( + ol_txrx_pdev_handle pdev); + +/** + * @brief set the safemode of the device + * @details + * This flag is used to bypass the encrypt and decrypt processes when send and + * receive packets. It works like open AUTH mode, HW will treate all packets + * as non-encrypt frames because no key installed. For rx fragmented frames, + * it bypasses all the rx defragmentaion. + * + * @param vdev - the data virtual device object + * @param val - the safemode state + * @return - void + */ +void +ol_txrx_set_safemode( + ol_txrx_vdev_handle vdev, + u_int32_t val); + +/** + * @brief set the privacy filter + * @details + * Rx related. Set the privacy filters. When rx packets, check the ether type, filter type and + * packet type to decide whether discard these packets. + * + * @param vdev - the data virtual device object + * @param filter - filters to be set + * @param num - the number of filters + * @return - void + */ +void +ol_txrx_set_privacy_filters( + ol_txrx_vdev_handle vdev, + void *filter, + u_int32_t num); + +/** + * @brief configure the drop unencrypted frame flag + * @details + * Rx related. When set this flag, all the unencrypted frames + * received over a secure connection will be discarded + * + * @param vdev - the data virtual device object + * @param val - flag + * @return - void + */ +void +ol_txrx_set_drop_unenc( + ol_txrx_vdev_handle vdev, + u_int32_t val); + +enum ol_txrx_peer_state { + ol_txrx_peer_state_invalid, + ol_txrx_peer_state_disc, /* initial state */ + ol_txrx_peer_state_conn, /* authentication in progress */ + ol_txrx_peer_state_auth, /* authentication completed successfully */ +}; + +/** + * @brief specify the peer's authentication state + * @details + * Specify the peer's authentication state (none, connected, authenticated) + * to allow the data SW to determine whether to filter out invalid data frames. + * (In the "connected" state, where security is enabled, but authentication + * has not completed, tx and rx data frames other than EAPOL or WAPI should + * be discarded.) + * This function is only relevant for systems in which the tx and rx filtering + * are done in the host rather than in the target. + * + * @param data_peer - which peer has changed its state + * @param state - the new state of the peer + */ +void +ol_txrx_peer_state_update(ol_txrx_pdev_handle pdev, u_int8_t *peer_addr, + enum ol_txrx_peer_state state); + +void +ol_txrx_peer_keyinstalled_state_update( + ol_txrx_peer_handle data_peer, + u_int8_t val); + +#define ol_tx_addba_conf(data_peer, tid, status) /* no-op */ + +/** + * @brief Find a txrx peer handle from the peer's MAC address + * @details + * The control SW typically uses the txrx peer handle to refer to the peer. + * In unusual circumstances, if it is infeasible for the control SW maintain + * the txrx peer handle but it can maintain the peer's MAC address, + * this function allows the peer handled to be retrieved, based on the peer's + * MAC address. + * In cases where there are multiple peer objects with the same MAC address, + * it is undefined which such object is returned. + * This function does not increment the peer's reference count. Thus, it is + * only suitable for use as long as the control SW has assurance that it has + * not deleted the peer object, by calling ol_txrx_peer_detach. + * + * @param pdev - the data physical device object + * @param peer_mac_addr - MAC address of the peer in question + * @return handle to the txrx peer object + */ +ol_txrx_peer_handle +ol_txrx_peer_find_by_addr(ol_txrx_pdev_handle pdev, u_int8_t *peer_mac_addr); + +/** + * @brief Find a txrx peer handle from a peer's local ID + * @details + * The control SW typically uses the txrx peer handle to refer to the peer. + * In unusual circumstances, if it is infeasible for the control SW maintain + * the txrx peer handle but it can maintain a small integer local peer ID, + * this function allows the peer handled to be retrieved, based on the local + * peer ID. + * + * @param pdev - the data physical device object + * @param local_peer_id - the ID txrx assigned locally to the peer in question + * @return handle to the txrx peer object + */ +#if QCA_SUPPORT_TXRX_LOCAL_PEER_ID +ol_txrx_peer_handle +ol_txrx_peer_find_by_local_id( + ol_txrx_pdev_handle pdev, + u_int8_t local_peer_id); +#else +#define ol_txrx_peer_find_by_local_id(pdev, local_peer_id) NULL +#endif + +typedef struct { + struct { + struct { + u_int32_t ucast; + u_int32_t mcast; + u_int32_t bcast; + } frms; + struct { + u_int32_t ucast; + u_int32_t mcast; + u_int32_t bcast; + } bytes; + } tx; + struct { + struct { + u_int32_t ucast; + u_int32_t mcast; + u_int32_t bcast; + } frms; + struct { + u_int32_t ucast; + u_int32_t mcast; + u_int32_t bcast; + } bytes; + } rx; +} ol_txrx_peer_stats_t; + +/** + * @brief Provide a snapshot of the txrx counters for the specified peer + * @details + * The txrx layer optionally maintains per-peer stats counters. + * This function provides the caller with a consistent snapshot of the + * txrx stats counters for the specified peer. + * + * @param pdev - the data physical device object + * @param peer - which peer's stats counters are requested + * @param stats - buffer for holding the stats counters snapshot + * @return success / failure status + */ +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS +A_STATUS +ol_txrx_peer_stats_copy( + ol_txrx_pdev_handle pdev, + ol_txrx_peer_handle peer, + ol_txrx_peer_stats_t *stats); +#else +#define ol_txrx_peer_stats_copy(pdev, peer, stats) A_ERROR /* failure */ +#endif /* QCA_ENABLE_OL_TXRX_PEER_STATS */ + +/* Config parameters for txrx_pdev */ +struct txrx_pdev_cfg_param_t { + u_int8_t is_full_reorder_offload; + /* IPA Micro controller data path offload enable flag */ + u_int8_t is_uc_offload_enabled; + /* IPA Micro controller data path offload TX buffer count */ + u_int32_t uc_tx_buffer_count; + /* IPA Micro controller data path offload TX buffer size */ + u_int32_t uc_tx_buffer_size; + /* IPA Micro controller data path offload RX indication ring count */ + u_int32_t uc_rx_indication_ring_count; + /* IPA Micro controller data path offload TX partition base */ + u_int32_t uc_tx_partition_base; +}; + +/** + * @brief Setup configuration parameters + * @details + * Allocation configuration context that will be used across data path + * + * @param osdev - OS handle needed as an argument for some OS primitives + * @return the control device object + */ +ol_pdev_handle ol_pdev_cfg_attach(adf_os_device_t osdev, + struct txrx_pdev_cfg_param_t cfg_param); + +#define OL_TXRX_INVALID_LOCAL_PEER_ID 0xffff +#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID +u_int16_t ol_txrx_local_peer_id(ol_txrx_peer_handle peer); +ol_txrx_peer_handle ol_txrx_find_peer_by_addr(ol_txrx_pdev_handle pdev, + u_int8_t *peer_addr, + u_int8_t *peer_id); +ol_txrx_peer_handle +ol_txrx_find_peer_by_addr_and_vdev(ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, + u_int8_t *peer_addr, + u_int8_t *peer_id); +#else +#define ol_txrx_local_peer_id(peer) OL_TXRX_INVALID_LOCAL_PEER_ID +#define ol_txrx_find_peer_by_addr(pdev, peer_addr, peer_id) NULL +#define ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, peer_addr, peer_id) NULL +#endif + +#define OL_TXRX_RSSI_INVALID 0xffff +/** + * @brief Provide the current RSSI average from data frames sent by a peer. + * @details + * If a peer has sent data frames, the data SW will optionally keep + * a running average of the RSSI observed for those data frames. + * This function returns that time-average RSSI if is it available, + * or OL_TXRX_RSSI_INVALID if either RSSI tracking is disabled or if + * no data frame indications with valid RSSI meta-data have been received. + * The RSSI is in approximate dBm units, and is normalized with respect + * to a 20 MHz channel. For example, if a data frame is received on a + * 40 MHz channel, wherein both the primary 20 MHz channel and the + * secondary 20 MHz channel have an RSSI of -77 dBm, the reported RSSI + * will be -77 dBm, rather than the actual -74 dBm RSSI from the + * combination of the primary + extension 20 MHz channels. + * Alternatively, the RSSI may be evaluated only on the primary 20 MHz + * channel. + * + * @param peer - which peer's RSSI is desired + * @return RSSI evaluted from frames sent by the specified peer + */ +#ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI +int16_t +ol_txrx_peer_rssi(ol_txrx_peer_handle peer); +#else +#define ol_txrx_peer_rssi(peer) OL_TXRX_RSSI_INVALID +#endif /* QCA_SUPPORT_PEER_DATA_RX_RSSI */ + +#define OL_TXRX_INVALID_LOCAL_PEER_ID 0xffff +#if QCA_SUPPORT_TXRX_LOCAL_PEER_ID +u_int16_t ol_txrx_local_peer_id(ol_txrx_peer_handle peer); +#else +#define ol_txrx_local_peer_id(peer) OL_TXRX_INVALID_LOCAL_PEER_ID +#endif + +#ifdef QCA_COMPUTE_TX_DELAY +/** + * @brief updates the compute interval period for TSM stats. + * @details + * @param interval - interval for stats computation + */ +void +ol_tx_set_compute_interval( + ol_txrx_pdev_handle pdev, + u_int32_t interval); + +/** + * @brief Return the uplink (transmitted) packet count and loss count. + * @details + * This function will be called for getting uplink packet count and + * loss count for given stream (access category) a regular interval. + * This also resets the counters hence, the value returned is packets + * counted in last 5(default) second interval. These counter are + * incremented per access category in ol_tx_completion_handler() + * + * @param category - access category of interest + * @param out_packet_count - number of packets transmitted + * @param out_packet_loss_count - number of packets lost + */ +void +ol_tx_packet_count( + ol_txrx_pdev_handle pdev, + u_int16_t *out_packet_count, + u_int16_t *out_packet_loss_count, + int category); +#endif + +/** + * @brief Return the average delays for tx frames. + * @details + * Return the average of the total time tx frames spend within the driver + * and the average time tx frames take to be transmitted. + * These averages are computed over a 5 second time interval. + * These averages are computed separately for separate access categories, + * if the QCA_COMPUTE_TX_DELAY_PER_AC flag is set. + * + * @param pdev - the data physical device instance + * @param queue_delay_microsec - average time tx frms spend in the WLAN driver + * @param tx_delay_microsec - average time for frames to be transmitted + * @param category - category (TID) of interest + */ +#ifdef QCA_COMPUTE_TX_DELAY +void +ol_tx_delay( + ol_txrx_pdev_handle pdev, + u_int32_t *queue_delay_microsec, + u_int32_t *tx_delay_microsec, + int category); +#else +static inline void +ol_tx_delay( + ol_txrx_pdev_handle pdev, + u_int32_t *queue_delay_microsec, + u_int32_t *tx_delay_microsec, + int category) +{ + /* no-op version if QCA_COMPUTE_TX_DELAY is not set */ + *queue_delay_microsec = *tx_delay_microsec = 0; +} +#endif + +/* + * Bins used for reporting delay histogram: + * bin 0: 0 - 10 ms delay + * bin 1: 10 - 20 ms delay + * bin 2: 20 - 40 ms delay + * bin 3: 40 - 80 ms delay + * bin 4: 80 - 160 ms delay + * bin 5: > 160 ms delay + */ +#define QCA_TX_DELAY_HIST_REPORT_BINS 6 +/** + * @brief Provide a histogram of tx queuing delays. + * @details + * Return a histogram showing the number of tx frames of the specified + * category for each of the delay levels in the histogram bin spacings + * listed above. + * These histograms are computed over a 5 second time interval. + * These histograms are computed separately for separate access categories, + * if the QCA_COMPUTE_TX_DELAY_PER_AC flag is set. + * + * @param pdev - the data physical device instance + * @param bin_values - an array of QCA_TX_DELAY_HIST_REPORT_BINS elements + * This array gets filled in with the histogram bin counts. + * @param category - category (TID) of interest + */ +#ifdef QCA_COMPUTE_TX_DELAY +void +ol_tx_delay_hist(ol_txrx_pdev_handle pdev, u_int16_t *bin_values, + int category); +#else +static inline void +ol_tx_delay_hist(ol_txrx_pdev_handle pdev, u_int16_t *bin_values, + int category) +{ + /* no-op version if QCA_COMPUTE_TX_DELAY is not set */ + adf_os_assert(bin_values); + adf_os_mem_zero( + bin_values, QCA_TX_DELAY_HIST_REPORT_BINS * sizeof(*bin_values)); +} +#endif + +#if defined(QCA_SUPPORT_TX_THROTTLE) +/** + * @brief Set the thermal mitgation throttling level. + * @details + * This function applies only to LL systems. This function is used set the + * tx throttle level used for thermal mitigation + * + * @param pdev - the physics device being throttled + */ +void ol_tx_throttle_set_level(struct ol_txrx_pdev_t *pdev, int level); +#else +static inline void ol_tx_throttle_set_level(struct ol_txrx_pdev_t *pdev, + int level) +{ + /* no-op */ +} +#endif /* QCA_SUPPORT_TX_THROTTLE */ + +#if defined(QCA_SUPPORT_TX_THROTTLE) +/** + * @brief Configure the thermal mitgation throttling period. + * @details + * This function applies only to LL systems. This function is used set the + * period over which data will be throttled + * + * @param pdev - the physics device being throttled + */ +void ol_tx_throttle_init_period(struct ol_txrx_pdev_t *pdev, int period); +#else +static inline void ol_tx_throttle_init_period(struct ol_txrx_pdev_t *pdev, + int period) +{ + /* no-op */ +} +#endif /* QCA_SUPPORT_TX_THROTTLE */ + +void ol_vdev_rx_set_intrabss_fwd(ol_txrx_vdev_handle vdev, a_bool_t val); + +#ifdef QCA_LL_TX_FLOW_CT +/** + * @brief Query TX resource availability by OS IF + * @details + * OS IF will query TX resource status to decide back pressuring or not + * + * @param vdev - the virtual device + * @param low_watermark - low free descriptor count to pause os tx q + * @param high_watermark_offset - high free descriptor count to resume os tx q + * offset value from low watermark. + * high watermark = low watermark + high_watermark_offset + * @return boolean- true if tx data path has enough resource + false if tx data path does not have enough resource + */ +a_bool_t +ol_txrx_get_tx_resource( + ol_txrx_vdev_handle vdev, + unsigned int low_watermark, + unsigned int high_watermark_offset +); + +/** + * @brief Set MAX LL TX Pause Q depth per vdev + * @details + * Each vdev will have different TX Pause Q depth + * High bandwidth vdev may have more TX Pause Q depth + * Low bandwidth vdev will have less TX Pause Q depth not to block + * high bandwidth vdev + * + * @param vdev - the virtual device + * @param pause_q_depth - TX Pause Q depth per vdev + * @return NONE + */ +void +ol_txrx_ll_set_tx_pause_q_depth( + ol_txrx_vdev_handle vdev, + int pause_q_depth +); +#endif /* QCA_LL_TX_FLOW_CT */ + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +/** + * @brief Configure the bad peer tx limit setting. + * @details + * + * @param pdev - the physics device + */ +void +ol_txrx_bad_peer_txctl_set_setting( + struct ol_txrx_pdev_t *pdev, + int enable, + int period, + int txq_limit); +#else +static inline void +ol_txrx_bad_peer_txctl_set_setting( + struct ol_txrx_pdev_t *pdev, + int enable, + int period, + int txq_limit) +{ + /* no-op */ +} +#endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */ + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +/** + * @brief Configure the bad peer tx threshold limit + * @details + * + * @param pdev - the physics device + */ +void +ol_txrx_bad_peer_txctl_update_threshold( + struct ol_txrx_pdev_t *pdev, + int level, + int tput_thresh, + int tx_limit); +#else +static inline void +ol_txrx_bad_peer_txctl_update_threshold( + struct ol_txrx_pdev_t *pdev, + int level, + int tput_thresh, + int tx_limit) +{ + /* no-op */ +} +#endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */ + +#ifdef IPA_UC_OFFLOAD +/** + * @brief Client request resource information + * @details +d * OL client will reuqest IPA UC related resource information + * Resource information will be distributted to IPA module + * All of the required resources should be pre-allocated + * + * @param pdev - handle to the HTT instance + * @param ce_sr_base_paddr - copy engine source ring base physical address + * @param ce_sr_ring_size - copy engine source ring size + * @param ce_reg_paddr - copy engine register physical address + * @param tx_comp_ring_base_paddr - tx comp ring base physical address + * @param tx_comp_ring_size - tx comp ring size + * @param tx_num_alloc_buffer - number of allocated tx buffer + * @param rx_rdy_ring_base_paddr - rx ready ring base physical address + * @param rx_rdy_ring_size - rx ready ring size + * @param rx_proc_done_idx_paddr - rx process done index physical address + */ +void +ol_txrx_ipa_uc_get_resource( + ol_txrx_pdev_handle pdev, + u_int32_t *ce_sr_base_paddr, + u_int32_t *ce_sr_ring_size, + u_int32_t *ce_reg_paddr, + u_int32_t *tx_comp_ring_base_paddr, + u_int32_t *tx_comp_ring_size, + u_int32_t *tx_num_alloc_buffer, + u_int32_t *rx_rdy_ring_base_paddr, + u_int32_t *rx_rdy_ring_size, + u_int32_t *rx_proc_done_idx_paddr +); + +/** + * @brief Client set IPA UC doorbell register + * @details + * IPA UC let know doorbell register physical address + * WLAN firmware will use this physical address to notify IPA UC + * + * @param pdev - handle to the HTT instance + * @param ipa_uc_tx_doorbell_paddr - tx comp doorbell physical address + * @param ipa_uc_rx_doorbell_paddr - rx ready doorbell physical address + */ +void +ol_txrx_ipa_uc_set_doorbell_paddr( + ol_txrx_pdev_handle pdev, + u_int32_t ipa_tx_uc_doorbell_paddr, + u_int32_t ipa_rx_uc_doorbell_paddr +); + +/** + * @brief Client notify IPA UC data path active or not + * + * @param pdev - handle to the HTT instance + * @param uc_active - UC data path is active or not + * @param is_tx - UC TX is active or not + */ +void +ol_txrx_ipa_uc_set_active( + ol_txrx_pdev_handle pdev, + a_bool_t uc_active, + a_bool_t is_tx +); + +/** + * @brief Offload data path activation notificaiton + * @details + * Firmware notification handler for offload datapath activity + * + * @param pdev - handle to the HTT instance + * @param op_code - activated for tx or rx data patrh + */ +void +ol_txrx_ipa_uc_op_response( + ol_txrx_pdev_handle pdev, + u_int8_t *op_msg); + +/** + * @brief callback function registration + * @details + * OSIF layer callback function registration API + * OSIF layer will register firmware offload datapath activity + * notification callback + * + * @param pdev - handle to the HTT instance + * @param ipa_uc_op_cb_type - callback function pointer should be registered + * @param osif_dev - osif instance pointer + */ +void ol_txrx_ipa_uc_register_op_cb( + ol_txrx_pdev_handle pdev, + void (*ipa_uc_op_cb_type)(u_int8_t *op_msg, void *osif_ctxt), + void *osif_dev); + +/** + * @brief query uc data path stats + * @details + * Query uc data path stats from firmware + * + * @param pdev - handle to the HTT instance + */ +void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev); +#else +#define ol_txrx_ipa_uc_get_resource( \ + pdev, \ + ce_sr_base_paddr, \ + ce_sr_ring_size, \ + ce_reg_paddr, \ + tx_comp_ring_base_paddr, \ + tx_comp_ring_size, \ + tx_num_alloc_buffer, \ + rx_rdy_ring_base_paddr, \ + rx_rdy_ring_size, \ + rx_proc_done_idx_paddr) /* NO-OP */ + +#define ol_txrx_ipa_uc_set_doorbell_paddr( \ + pdev, \ + ipa_tx_uc_doorbell_paddr, \ + ipa_rx_uc_doorbell_paddr) /* NO-OP */ + +#define ol_txrx_ipa_uc_set_active( \ + pdev, \ + uc_active, \ + is_tx) /* NO-OP */ + +#define ol_txrx_ipa_uc_op_response( \ + pdev, \ + op_data) /* NO-OP */ + +#define ol_txrx_ipa_uc_register_op_cb( \ + pdev, \ + ipa_uc_op_cb_type, \ + osif_dev) /* NO-OP */ + +#define ol_txrx_ipa_uc_get_stat(pdev) /* NO-OP */ +#endif /* IPA_UC_OFFLOAD */ + +/** + * @brief Setter function to store OCB Peer. + */ +void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer); + +/** + * @brief Getter function to retrieve OCB peer. + * @details + * Returns A_TRUE if ocb_peer is valid + * Otherwise, returns A_FALSE + */ +a_bool_t ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t **peer); + +void ol_txrx_display_stats(struct ol_txrx_pdev_t *pdev, uint16_t bitmap); +void ol_txrx_clear_stats(struct ol_txrx_pdev_t *pdev, uint16_t bitmap); + +#endif /* _OL_TXRX_CTRL_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h new file mode 100644 index 000000000000..168658d6edd3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_dbg.h + * @brief Functions provided for visibility and debugging. + */ +#ifndef _OL_TXRX_DBG__H_ +#define _OL_TXRX_DBG__H_ + +#include /* A_STATUS, u_int64_t */ +#include /* adf_os_mutex_t */ +#include /* htt_dbg_stats_type */ +#include /* ol_txrx_stats */ + +typedef void (*ol_txrx_stats_callback)( + void *ctxt, + enum htt_dbg_stats_type type, + u_int8_t *buf, + int bytes); + +struct ol_txrx_stats_req { + u_int32_t stats_type_upload_mask; /* which stats to upload */ + u_int32_t stats_type_reset_mask; /* which stats to reset */ + + /* stats will be printed if either print element is set */ + struct { + int verbose; /* verbose stats printout */ + int concise; /* concise stats printout (takes precedence) */ + } print; /* print uploaded stats */ + + /* stats notify callback will be invoked if fp is non-NULL */ + struct { + ol_txrx_stats_callback fp; + void *ctxt; + } callback; + + /* stats will be copied into the specified buffer if buf is non-NULL */ + struct { + u_int8_t *buf; + int byte_limit; /* don't copy more than this */ + } copy; + + /* + * If blocking is true, the caller will take the specified semaphore + * to wait for the stats to be uploaded, and the driver will release + * the semaphore when the stats are done being uploaded. + */ + struct { + int blocking; + adf_os_mutex_t *sem_ptr; + } wait; +}; + +#ifndef TXRX_DEBUG_LEVEL +#define TXRX_DEBUG_LEVEL 0 /* no debug info */ +#endif + +#ifndef ATH_PERF_PWR_OFFLOAD /*---------------------------------------------*/ + +#define ol_txrx_debug(vdev, debug_specs) 0 +#define ol_txrx_fw_stats_cfg(vdev, type, val) 0 +#define ol_txrx_fw_stats_get(vdev, req) 0 +#define ol_txrx_aggr_cfg(vdev, max_subfrms_ampdu, max_subfrms_amsdu) 0 + +#else /*---------------------------------------------------------------------*/ + + +#include /* ol_txrx_pdev_handle, etc. */ + +int ol_txrx_debug(ol_txrx_vdev_handle vdev, int debug_specs); + +void ol_txrx_fw_stats_cfg( + ol_txrx_vdev_handle vdev, + u_int8_t cfg_stats_type, + u_int32_t cfg_val); + +int ol_txrx_fw_stats_get( + ol_txrx_vdev_handle vdev, + struct ol_txrx_stats_req *req); + + +int ol_txrx_aggr_cfg(ol_txrx_vdev_handle vdev, + int max_subfrms_ampdu, + int max_subfrms_amsdu); + +enum { + TXRX_DBG_MASK_OBJS = 0x01, + TXRX_DBG_MASK_STATS = 0x02, + TXRX_DBG_MASK_PROT_ANALYZE = 0x04, + TXRX_DBG_MASK_RX_REORDER_TRACE = 0x08, + TXRX_DBG_MASK_RX_PN_TRACE = 0x10 +}; + +/*--- txrx printouts ---*/ + +/* + * Uncomment this to enable txrx printouts with dynamically adjustable + * verbosity. These printouts should not impact performance. + */ +#define TXRX_PRINT_ENABLE 1 +/* uncomment this for verbose txrx printouts (may impact performance) */ +//#define TXRX_PRINT_VERBOSE_ENABLE 1 + +void ol_txrx_print_level_set(unsigned level); + +/*--- txrx object (pdev, vdev, peer) display debug functions ---*/ + +#if TXRX_DEBUG_LEVEL > 5 +void ol_txrx_pdev_display(ol_txrx_pdev_handle pdev, int indent); +void ol_txrx_vdev_display(ol_txrx_vdev_handle vdev, int indent); +void ol_txrx_peer_display(ol_txrx_peer_handle peer, int indent); +#else +#define ol_txrx_pdev_display(pdev, indent) +#define ol_txrx_vdev_display(vdev, indent) +#define ol_txrx_peer_display(peer, indent) +#endif + +/*--- txrx stats display debug functions ---*/ +void ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, + unsigned length); + +#if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF + +void ol_txrx_stats_display(ol_txrx_pdev_handle pdev); + +int +ol_txrx_stats_publish(ol_txrx_pdev_handle pdev, struct ol_txrx_stats *buf); + +void ol_txrx_stats_clear(ol_txrx_pdev_handle pdev); +#else +#define ol_txrx_stats_display(pdev) +#define ol_txrx_stats_clear(pdev) +#define ol_txrx_stats_publish(pdev, buf) TXRX_STATS_LEVEL_OFF +#endif /* TXRX_STATS_LEVEL */ + +/*--- txrx protocol analyzer debug feature ---*/ + +/* uncomment this to enable the protocol analzyer feature */ +//#define ENABLE_TXRX_PROT_ANALYZE 1 + +#if defined(ENABLE_TXRX_PROT_ANALYZE) + +void ol_txrx_prot_ans_display(ol_txrx_pdev_handle pdev); + +#else + +#define ol_txrx_prot_ans_display(pdev) + +#endif /* ENABLE_TXRX_PROT_ANALYZE */ + +/*--- txrx sequence number trace debug feature ---*/ + +/* uncomment this to enable the rx reorder trace feature */ +//#define ENABLE_RX_REORDER_TRACE 1 + +#define ol_txrx_seq_num_trace_display(pdev) \ + ol_rx_reorder_trace_display(pdev, 0, 0) + +#if defined(ENABLE_RX_REORDER_TRACE) + +void +ol_rx_reorder_trace_display(ol_txrx_pdev_handle pdev, int just_once, int limit); + +#else + +#define ol_rx_reorder_trace_display(pdev, just_once, limit) + +#endif /* ENABLE_RX_REORDER_TRACE */ + +/*--- txrx packet number trace debug feature ---*/ + +/* uncomment this to enable the rx PN trace feature */ +//#define ENABLE_RX_PN_TRACE 1 + +#define ol_txrx_pn_trace_display(pdev) ol_rx_pn_trace_display(pdev, 0) + +#if defined(ENABLE_RX_PN_TRACE) + +void +ol_rx_pn_trace_display(ol_txrx_pdev_handle pdev, int just_once); + +#else + +#define ol_rx_pn_trace_display(pdev, just_once) + +#endif /* ENABLE_RX_PN_TRACE */ + +/*--- tx queue log debug feature ---*/ +/* uncomment this to enable the tx queue log feature */ + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + +void +ol_tx_queue_log_display(ol_txrx_pdev_handle pdev); + +void ol_tx_queue_log_clear(ol_txrx_pdev_handle pdev); + +#else + +#define ol_tx_queue_log_display(pdev) +#define ol_tx_queue_log_clear(pdev) + +#endif /* defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) */ + +#endif /* ATH_PERF_PWR_OFFLOAD */ /*----------------------------------------*/ + +#endif /* _OL_TXRX_DBG__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_htt_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_htt_api.h new file mode 100644 index 000000000000..0baafe0f6bde --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_htt_api.h @@ -0,0 +1,733 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_htt_api.h + * @brief Define the host data API functions called by the host HTT SW. + */ +#ifndef _OL_TXRX_HTT_API__H_ +#define _OL_TXRX_HTT_API__H_ + +#include /* HTT_TX_COMPL_IND_STAT */ +#include /* A_STATUS */ +#include /* adf_nbuf_t */ + +#include /* ol_txrx_pdev_handle */ + +#ifdef CONFIG_HL_SUPPORT +static inline u_int16_t * +ol_tx_msdu_id_storage(adf_nbuf_t msdu) +{ + return NBUF_CB_ID(msdu); +} +#else +static inline u_int16_t * +ol_tx_msdu_id_storage(adf_nbuf_t msdu) +{ + adf_os_assert(adf_nbuf_headroom(msdu) >= (sizeof(u_int16_t) * 2 - 1)); + return (u_int16_t *) (((adf_os_size_t) (adf_nbuf_head(msdu) + 1)) & ~0x1); +} +#endif + +/** + * @brief Tx MSDU download completion for a LL system + * @details + * Release the reference to the downloaded tx descriptor. + * In the unlikely event that the reference count is zero, free + * the tx descriptor and tx frame. + * + * @param pdev - (abstract) pointer to the txrx physical device + * @param status - indication of whether the download succeeded + * @param msdu - the downloaded tx frame + * @param msdu_id - the txrx ID of the tx frame - this is used for + * locating the frame's tx descriptor + */ +void +ol_tx_download_done_ll( + void *pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id); + +/** + * @brief Tx MSDU download completion for HL system without tx completion msgs + * @details + * Free the tx descriptor and tx frame. + * Invoke the HL tx download scheduler. + * + * @param pdev - (abstract) pointer to the txrx physical device + * @param status - indication of whether the download succeeded + * @param msdu - the downloaded tx frame + * @param msdu_id - the txrx ID of the tx frame - this is used for + * locating the frame's tx descriptor + */ +void +ol_tx_download_done_hl_free( + void *pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id); + +/** + * @brief Tx MSDU download completion for HL system with tx completion msgs + * @details + * Release the reference to the downloaded tx descriptor. + * In the unlikely event that the reference count is zero, free + * the tx descriptor and tx frame. + * Optionally, invoke the HL tx download scheduler. (It is probable that + * the HL tx download scheduler would operate in response to tx completion + * messages rather than download completion events.) + * + * @param pdev - (abstract) pointer to the txrx physical device + * @param status - indication of whether the download succeeded + * @param msdu - the downloaded tx frame + * @param msdu_id - the txrx ID of the tx frame - this is used for + * locating the frame's tx descriptor + */ +void +ol_tx_download_done_hl_retain( + void *pdev, + A_STATUS status, + adf_nbuf_t msdu, + u_int16_t msdu_id); + +/* + * For now, make the host HTT -> host txrx tx completion status + * match the target HTT -> host HTT tx completion status, so no + * translation is needed. + */ +/* + * host-only statuses use a different part of the number space + * than host-target statuses + */ +#define HTT_HOST_ONLY_STATUS_CODE_START 128 +enum htt_tx_status { + /* ok - successfully sent + acked */ + htt_tx_status_ok = HTT_TX_COMPL_IND_STAT_OK, + + /* discard - not sent (congestion control) */ + htt_tx_status_discard = HTT_TX_COMPL_IND_STAT_DISCARD, + + /* no_ack - sent, but no ack */ + htt_tx_status_no_ack = HTT_TX_COMPL_IND_STAT_NO_ACK, + + /* download_fail - the host could not deliver the tx frame to the target */ + htt_tx_status_download_fail = HTT_HOST_ONLY_STATUS_CODE_START, + + /* peer_del - tx completion for alreay deleted peer used for HL case */ + htt_tx_status_peer_del = HTT_TX_COMPL_IND_STAT_PEER_DEL, +}; + +/** + * @brief Process a tx completion message sent by the target. + * @details + * When the target is done transmitting a tx frame (either because + * the frame was sent + acknowledged, or because the target gave up) + * it sends a tx completion message to the host. + * This notification function is used regardless of whether the + * transmission succeeded or not; the status argument indicates whether + * the transmission succeeded. + * This tx completion message indicates via the descriptor ID which + * tx frames were completed, and indicates via the status whether the + * frames were transmitted successfully. + * The host frees the completed descriptors / frames (updating stats + * in the process). + * + * @param pdev - the data physical device that sent the tx frames + * (registered with HTT as a context pointer during attach time) + * @param num_msdus - how many MSDUs are referenced by the tx completion + * message + * @param status - whether transmission was successful + * @param tx_msdu_id_iterator - abstract method of finding the IDs for the + * individual MSDUs referenced by the tx completion message, via the + * htt_tx_compl_desc_id API function + */ +void +ol_tx_completion_handler( + ol_txrx_pdev_handle pdev, + int num_msdus, + enum htt_tx_status status, + void *tx_msdu_id_iterator); + +void +ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits); + + + +struct rate_report_t{ + u_int16_t id; + u_int16_t phy : 4; + u_int32_t rate; +}; + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +/** + * @brief Process a link status report for all peers. + * @details + * The ol_txrx_peer_link_status_handler function performs basic peer link + * status analysis + * + * According to the design, there are 3 kinds of peers which will be + * treated differently: + * 1) normal: not do any flow control for the peer + * 2) limited: will apply flow control for the peer, but frames are allowed to send + * 3) paused: will apply flow control for the peer, no frame is allowed to send + * + * @param pdev - the data physical device that sent the tx frames + * @param status - the number of peers need to be handled + * @param peer_link_report - the link status dedail message + */ +void +ol_txrx_peer_link_status_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_num, + struct rate_report_t* peer_link_status); + + +#else +static inline void ol_txrx_peer_link_status_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_num, + struct rate_report_t* peer_link_status) +{ + /* no-op */ +} +#endif + + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +void +ol_txrx_update_tx_queue_groups( + ol_txrx_pdev_handle pdev, + u_int8_t group_id, + int32_t credit, + u_int8_t absolute, + u_int32_t vdev_id_mask, + u_int32_t ac_mask +); + +void +ol_tx_desc_update_group_credit( + ol_txrx_pdev_handle pdev, + u_int16_t tx_desc_id, + int credit, u_int8_t absolute, enum htt_tx_status status); +#define OL_TX_DESC_UPDATE_GROUP_CREDIT ol_tx_desc_update_group_credit + +#ifdef DEBUG_HL_LOGGING +void +ol_tx_update_group_credit_stats(ol_txrx_pdev_handle pdev); + +void +ol_tx_dump_group_credit_stats(ol_txrx_pdev_handle pdev); + +void +ol_tx_clear_group_credit_stats(ol_txrx_pdev_handle pdev); + +#define OL_TX_UPDATE_GROUP_CREDIT_STATS ol_tx_update_group_credit_stats +#define OL_TX_DUMP_GROUP_CREDIT_STATS ol_tx_dump_group_credit_stats +#define OL_TX_CLEAR_GROUP_CREDIT_STATS ol_tx_clear_group_credit_stats +#else +#define OL_TX_UPDATE_GROUP_CREDIT_STATS(pdev) /* no -op*/ +#define OL_TX_DUMP_GROUP_CREDIT_STATS(pdev) /* no -op*/ +#define OL_TX_CLEAR_GROUP_CREDIT_STATS(pdev) /* no -op*/ +#endif + +#else +#define OL_TX_DESC_UPDATE_GROUP_CREDIT(pdev, tx_desc_id, credit, absolute, status) /* no-op */ +#endif + +/** + * @brief Init the total amount of target credit. + * @details + * + * @param pdev - the data physical device that sent the tx frames + * @param credit_delta - how much to increment the target's tx credit by + */ +void +ol_tx_target_credit_init(struct ol_txrx_pdev_t *pdev, int credit_delta); + +/** + * @brief Process a tx completion message for a single MSDU. + * @details + * The ol_tx_single_completion_handler function performs the same tx + * completion processing as the ol_tx_completion_handler, but for a + * single frame. + * ol_tx_completion_handler is optimized to handle batch completions + * as efficiently as possible; in contrast ol_tx_single_completion_handler + * handles single frames as simply and generally as possible. + * Thus, this ol_tx_single_completion_handler function is suitable for + * intermittent usage, such as for tx mgmt frames. + * + * @param pdev - the data physical device that sent the tx frames + * @param status - whether transmission was successful + * @param tx_msdu_id - ID of the frame which completed transmission + */ +void +ol_tx_single_completion_handler( + ol_txrx_pdev_handle pdev, + enum htt_tx_status status, + u_int16_t tx_desc_id); + +/** + * @brief Update the amount of target credit. + * @details + * When the target finishes with an old transmit frame, it can use the + * space that was occupied by the old tx frame to store a new tx frame. + * This function is used to inform the txrx layer, where the HL tx download + * scheduler resides, about such updates to the target's tx credit. + * This credit update is done explicitly, rather than having the txrx layer + * update the credit count itself inside the ol_tx_completion handler + * function. This provides HTT with the flexibility to limit the rate of + * downloads from the TXRX layer's download scheduler, by controlling how + * much credit the download scheduler gets, and also provides the flexibility + * to account for a change in the tx memory pool size within the target. + * This function is only used for HL systems; in LL systems, each tx frame + * is assumed to use exactly one credit (for its target-side tx descriptor), + * and any rate limiting is managed within the target. + * + * @param pdev - the data physical device that sent the tx frames + * @param credit_delta - how much to increment the target's tx credit by + */ +void +ol_tx_target_credit_update(struct ol_txrx_pdev_t *pdev, int credit_delta); + + +/** + * @brief Process an rx indication message sent by the target. + * @details + * The target sends a rx indication message to the host as a + * notification that there are new rx frames available for the + * host to process. + * The HTT host layer locates the rx descriptors and rx frames + * associated with the indication, and calls this function to + * invoke the rx data processing on the new frames. + * (For LL, the rx descriptors and frames are delivered directly + * to the host via MAC DMA, while for HL the rx descriptor and + * frame for individual frames are combined with the rx indication + * message.) + * All MPDUs referenced by a rx indication message belong to the + * same peer-TID. + * + * @param pdev - the data physical device that received the frames + * (registered with HTT as a context pointer during attach time) + * @param rx_ind_msg - the network buffer holding the rx indication message + * (For HL, this netbuf also holds the rx desc and rx payload, but + * the data SW is agnostic to whether the desc and payload are + * piggybacked with the rx indication message.) + * @param peer_id - which peer sent this rx data + * @param tid - what (extended) traffic type the rx data is + * @param num_mpdu_ranges - how many ranges of MPDUs does the message describe. + * Each MPDU within the range has the same rx status. + */ +void +ol_rx_indication_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + u_int16_t peer_id, + u_int8_t tid, + int num_mpdu_ranges); + +/** + * @brief Process an rx fragment indication message sent by the target. + * @details + * The target sends a rx fragment indication message to the host as a + * notification that there are new rx fragment available for the + * host to process. + * The HTT host layer locates the rx descriptors and rx fragment + * associated with the indication, and calls this function to + * invoke the rx fragment data processing on the new fragment. + * + * @param pdev - the data physical device that received the frames + * (registered with HTT as a context pointer during attach time) + * @param rx_frag_ind_msg - the network buffer holding the rx fragment indication message + * @param peer_id - which peer sent this rx data + * @param tid - what (extended) traffic type the rx data is + */ +void ol_rx_frag_indication_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t rx_frag_ind_msg, + u_int16_t peer_id, + u_int8_t tid); + +/** + * @brief Process rx offload deliver indication message sent by the target. + * @details + * When the target exits offload mode, target delivers packets that it has held in its + * memory to the host using this message. + * Low latency case: + * The message contains the number of MSDUs that are being delivered by the target to the + * host. The packet itself resides in host ring along with some metadata describing the peer + * id, vdev id, tid, FW desc and length of the packet being delivered. + * Hight letency case: + * The message itself contains the payload of the MSDU being delivered by the target to the + * host. The message also contains meta data describing the packet such as peer id, vdev id, + * tid, FW desc and length of the packet being delivered. Refer to htt.h for the exact structure + * of the message. + * @param pdev - the data physical device that received the frame. + * @param msg - offload deliver indication message + * @param msdu_cnt - number of MSDUs being delivred. + */ +void +ol_rx_offload_deliver_ind_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t msg, + int msdu_cnt); + +/** + * @brief Process a peer map message sent by the target. + * @details + * Each time the target allocates a new peer ID, it will inform the + * host via the "peer map" message. This function processes that + * message. The host data SW looks for a peer object whose MAC address + * matches the MAC address specified in the peer map message, and then + * sets up a mapping between the peer ID specified in the message and + * the peer object that was found. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - ID generated by the target to refer to the peer in question + * The target may create multiple IDs for a single peer. + * @param vdev_id - Reference to the virtual device the peer is associated with + * @param peer_mac_addr - MAC address of the peer in question + * @param tx_ready - whether transmits to this peer can be done already, or + * need to wait for a call to peer_tx_ready (only applies to HL systems) + */ +void +ol_rx_peer_map_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tx_ready); + +/** + * @brief Notify the host that the target is ready to transmit to a new peer. + * @details + * Some targets can immediately accept tx frames for a new peer, as soon as + * the peer's association completes. Other target need a short setup time + * before they are ready to accept tx frames for the new peer. + * If the target needs time for setup, it will provide a peer_tx_ready + * message when it is done with the setup. This function forwards this + * notification from the target to the host's tx queue manager. + * This function only applies for HL systems, in which the host determines + * which peer a given tx frame is for, and stores the tx frames in queues. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - ID for the new peer which can now accept tx frames + */ +void +ol_txrx_peer_tx_ready_handler(ol_txrx_pdev_handle pdev, u_int16_t peer_id); + +/** + * @brief Process a peer unmap message sent by the target. + * @details + * Each time the target frees a peer ID, it will inform the host via the + * "peer unmap" message. This function processes that message. + * The host data SW uses the peer ID from the message to find the peer + * object from peer_map[peer_id], then invalidates peer_map[peer_id] + * (by setting it to NULL), and checks whether there are any remaining + * references to the peer object. If not, the function deletes the + * peer object. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - ID that is being freed. + * The target may create multiple IDs for a single peer. + */ +void +ol_rx_peer_unmap_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id); + +/** + * @brief Process a security indication message sent by the target. + * @details + * When a key is assigned to a peer, the target will inform the host + * with a security indication message. + * The host remembers the security type, and infers whether a rx PN + * check is needed. + * + * @param pdev - data physical device handle + * @param peer_id - which peer the security info is for + * @param sec_type - which type of security / key the peer is using + * @param is_unicast - whether security spec is for a unicast or multicast key + * @param michael_key - key used for TKIP MIC (if sec_type == TKIP) + * @param rx_pn - RSC used for WAPI PN replay check (if sec_type == WAPI) + */ +void +ol_rx_sec_ind_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + enum htt_sec_type sec_type, + int is_unicast, + u_int32_t *michael_key, + u_int32_t *rx_pn); + +/** + * @brief Process an ADDBA message sent by the target. + * @details + * When the target notifies the host of an ADDBA event for a specified + * peer-TID, the host will set up the rx reordering state for the peer-TID. + * Specifically, the host will create a rx reordering array whose length + * is based on the window size specified in the ADDBA. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - which peer the ADDBA event is for + * @param tid - which traffic ID within the peer the ADDBA event is for + * @param win_sz - how many sequence numbers are in the ARQ block ack window + * set up by the ADDBA event + * @param start_seq_num - the initial value of the sequence number during the + * block ack agreement, as specified by the ADDBA request. + * @param failed - indicate whether the target's ADDBA setup succeeded: + * 0 -> success, 1 -> fail + */ +void +ol_rx_addba_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid, + u_int8_t win_sz, + u_int16_t start_seq_num, + u_int8_t failed); + +/** + * @brief Process a DELBA message sent by the target. + * @details + * When the target notifies the host of a DELBA event for a specified + * peer-TID, the host will clean up the rx reordering state for the peer-TID. + * Specifically, the host will remove the rx reordering array, and will + * set the reorder window size to be 1 (stop and go ARQ). + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - which peer the ADDBA event is for + * @param tid - which traffic ID within the peer the ADDBA event is for + */ +void +ol_rx_delba_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid); + +enum htt_rx_flush_action { + htt_rx_flush_release, + htt_rx_flush_discard, +}; + +/** + * @brief Process a rx reorder flush message sent by the target. + * @details + * The target's rx reorder logic can send a flush indication to the + * host's rx reorder buffering either as a flush IE within a rx + * indication message, or as a standalone rx reorder flush message. + * This ol_rx_flush_handler function processes the standalone rx + * reorder flush message from the target. + * The flush message specifies a range of sequence numbers whose + * rx frames are flushed. + * Some sequence numbers within the specified range may not have + * rx frames; the host needs to check for each sequence number in + * the specified range whether there are rx frames held for that + * sequence number. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - which peer's rx data is being flushed + * @param tid - which traffic ID within the peer has the rx data being flushed + * @param seq_num_start - Which sequence number within the rx reordering + * buffer the flushing should start with. + * This is the LSBs of the 802.11 sequence number. + * This sequence number is masked with the rounded-to-power-of-two + * window size to generate a reorder buffer index. + * The flush includes this initial sequence number. + * @param seq_num_end - Which sequence number within the rx reordering + * buffer the flushing should stop at. + * This is the LSBs of the 802.11 sequence number. + * This sequence number is masked with the rounded-to-power-of-two + * window size to generate a reorder buffer index. + * The flush excludes this final sequence number. + * @param action - whether to release or discard the rx frames + */ +void +ol_rx_flush_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid, + u_int16_t seq_num_start, + u_int16_t seq_num_end, + enum htt_rx_flush_action action); + +/** + * @brief Process a rx pn indication message + * @details + * When the peer is configured to get PN checking done in target, + * the target instead of sending reorder flush/release messages + * sends PN indication messages which contain the start and end + * sequence numbers to be flushed/released along with the sequence + * numbers of MPDUs that failed the PN check in target. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - which peer's rx data is being flushed + * @param tid - which traffic ID within the peer + * @param seq_num_start - Which sequence number within the rx reordering + * buffer to start with. + * This is the LSBs of the 802.11 sequence number. + * This sequence number is masked with the rounded-to-power-of-two + * window size to generate a reorder buffer index. + * This is the initial sequence number. + * @param seq_num_end - Which sequence number within the rx reordering + * buffer to stop at. + * This is the LSBs of the 802.11 sequence number. + * This sequence number is masked with the rounded-to-power-of-two + * window size to generate a reorder buffer index. + * The processing stops right before this sequence number + * @param pn_ie_cnt - Indicates the number of PN information elements. + * @param pn_ie - Pointer to the array of PN information elements. Each + * PN information element contains the LSBs of the 802.11 sequence number + * of the MPDU that failed the PN checking in target. + */ +void +ol_rx_pn_ind_handler( + ol_txrx_pdev_handle pdev, + u_int16_t peer_id, + u_int8_t tid, + int seq_num_start, + int seq_num_end, + u_int8_t pn_ie_cnt, + u_int8_t *pn_ie); + +/** + * @brief Process a stats message sent by the target. + * @details + * The host can request target for stats. + * The target sends the stats to the host via a confirmation message. + * This ol_txrx_fw_stats_handler function processes the confirmation message. + * Currently, this processing consists of copying the stats from the message + * buffer into the txrx pdev object, and waking the sleeping host context + * that requested the stats. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param cookie - Value echoed from the cookie in the stats request + * message. This allows the host SW to find the stats request object. + * (Currently, this cookie is unused.) + * @param stats_info_list - stats confirmation message contents, containing + * a list of the stats requested from the target + */ +void +ol_txrx_fw_stats_handler( + ol_txrx_pdev_handle pdev, + u_int64_t cookie, + u_int8_t *stats_info_list); + +/** + * @brief Process a tx inspect message sent by the target. + * @details: + * TODO: update + * This tx inspect message indicates via the descriptor ID + * which tx frames are to be inspected by host. The host + * re-injects the packet back to the host for a number of + * cases. + * + * @param pdev - the data physical device that sent the tx frames + * (registered with HTT as a context pointer during attach time) + * @param num_msdus - how many MSDUs are referenced by the tx completion + * message + * @param tx_msdu_id_iterator - abstract method of finding the IDs for the + * individual MSDUs referenced by the tx completion message, via the + * htt_tx_compl_desc_id API function + */ +void +ol_tx_inspect_handler( + ol_txrx_pdev_handle pdev, + int num_msdus, + void *tx_desc_id_iterator); + +/** + * @brief Get the UAPSD mask. + * @details + * This function will return the UAPSD TID mask. + * + * @param txrx_pdev - pointer to the txrx pdev object + * @param peer_id - PeerID. + * @return uapsd mask value + */ +u_int8_t +ol_txrx_peer_uapsdmask_get(struct ol_txrx_pdev_t * txrx_pdev, + u_int16_t peer_id); + +/** + * @brief Get the Qos Capable. + * @details + * This function will return the txrx_peer qos_capable. + * + * @param txrx_pdev - pointer to the txrx pdev object + * @param peer_id - PeerID. + * @return qos_capable value + */ +u_int8_t +ol_txrx_peer_qoscapable_get(struct ol_txrx_pdev_t * txrx_pdev, + u_int16_t peer_id); + +/** + * @brief Process an rx indication message sent by the target. + * @details + * The target sends a rx indication message to the host as a + * notification that there are new rx frames available for the + * host to process. + * The HTT host layer locates the rx descriptors and rx frames + * associated with the indication, and calls this function to + * invoke the rx data processing on the new frames. + * All MPDUs referenced by a rx indication message belong to the + * same peer-TID. The frames indicated have been re-ordered by + * the target. + * + * @param pdev - the data physical device that received the frames + * (registered with HTT as a context pointer during attach time) + * @param rx_ind_msg - the network buffer holding the rx indication message + * @param peer_id - which peer sent this rx data + * @param tid - what (extended) traffic type the rx data is + * @param is_offload - is this an offload indication? + */ +void +ol_rx_in_order_indication_handler( + ol_txrx_pdev_handle pdev, + adf_nbuf_t rx_ind_msg, + u_int16_t peer_id, + u_int8_t tid, + u_int8_t is_offload ); + +#ifdef FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL +u_int32_t ol_tx_get_max_tx_groups_supported(struct ol_txrx_pdev_t *pdev); +#define OL_TX_GET_MAX_GROUPS ol_tx_get_max_tx_groups_supported +#else +#define OL_TX_GET_MAX_GROUPS(pdev) 0 +#endif + +#endif /* _OL_TXRX_HTT_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_osif_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_osif_api.h new file mode 100644 index 000000000000..6808f64a782a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_osif_api.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_osif_api.h + * @brief Define the host data API functions called by the host OS shim SW. + */ +#ifndef _OL_TXRX_OSIF_API__H_ +#define _OL_TXRX_OSIF_API__H_ + +#include /* adf_nbuf_t */ + +#include /* ol_osif_vdev_handle */ +#include /* ol_txrx_pdev_handle, etc. */ + +/** + * @typedef ol_txrx_tx_fp + * @brief top-level transmit function + */ +typedef adf_nbuf_t (*ol_txrx_tx_fp)( + ol_txrx_vdev_handle data_vdev, adf_nbuf_t msdu_list); + +/** + * @typedef ol_txrx_tx_non_std_fp + * @brief top-level transmit function for non-standard tx frames + * @details + * This function pointer provides an alternative to the ol_txrx_tx_fp + * to support non-standard transmits. In particular, this function + * supports transmission of: + * 1. "Raw" frames + * These raw frames already have an 802.11 header; the usual + * 802.11 header encapsulation by the driver does not apply. + * 2. TSO segments + * During tx completion, the txrx layer needs to reclaim the buffer + * that holds the ethernet/IP/TCP header created for the TSO segment. + * Thus, these tx frames need to be marked as TSO, to show that they + * need this special handling during tx completion. + * + * @param data_vdev - which virtual device should transmit the frame + * @param tx_spec - what non-standard operations to apply to the tx frame + * @param msdu_list - tx frame(s), in a null-terminated list + */ +typedef adf_nbuf_t (*ol_txrx_tx_non_std_fp)( + ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list); + +struct txrx_rx_metainfo; + +#ifdef OSIF_NEED_RX_PEER_ID +/** + * @typedef ol_txrx_rx_fp + * @brief receive function to hand batches of data frames from txrx to OS shim + * @details this version of rx callback is for the OS shim, for example CLD, which + * depends on peer id information in data rx. + */ +typedef void (*ol_txrx_rx_fp)(void *osif_dev, u_int16_t peer_id, + adf_nbuf_t msdus); +#else + +/** + * @typedef ol_txrx_rx_fp + * @brief receive function to hand batches of data frames from txrx to OS shim + */ +typedef void (*ol_txrx_rx_fp)(void *osif_dev, adf_nbuf_t msdus); +#endif /* OSIF_NEED_RX_PEER_ID */ + +/** + * @typedef ol_txrx_tx_fc_fp + * @brief tx flow control notification function from txrx to OS shim + * @param osif_dev - the virtual device's OS shim object + * @param vdev_id - virtual device id + * @param tx_resume - tx os q should be resumed or not + */ +typedef void (*ol_txrx_tx_flow_control_fp)(void *osif_dev, + u_int8_t vdev_id, a_bool_t tx_resume); + +/** + * @typedef ol_txrx_rx_fp + * @brief receive function to hand batches of data frames from txrx to OS shim + */ + +struct ol_txrx_osif_ops { + /* tx function pointers - specified by txrx, stored by OS shim */ + struct { + ol_txrx_tx_fp std; + ol_txrx_tx_non_std_fp non_std; + ol_txrx_tx_flow_control_fp flow_control_cb; + } tx; + + /* rx function pointers - specified by OS shim, stored by txrx */ + struct { + ol_txrx_rx_fp std; + } rx; +}; + +/** + * @brief Link a vdev's data object with the matching OS shim vdev object. + * @details + * The data object for a virtual device is created by the function + * ol_txrx_vdev_attach. However, rather than fully linking the + * data vdev object with the vdev objects from the other subsystems + * that the data vdev object interacts with, the txrx_vdev_attach + * function focuses primarily on creating the data vdev object. + * After the creation of both the data vdev object and the OS shim + * vdev object, this txrx_osif_vdev_attach function is used to connect + * the two vdev objects, so the data SW can use the OS shim vdev handle + * when passing rx data received by a vdev up to the OS shim. + * + * @param txrx_vdev - the virtual device's data object + * @param osif_vdev - the virtual device's OS shim object + * @param txrx_ops - (pointers to) the functions used for tx and rx data xfer + * There are two portions of these txrx operations. + * The rx portion is filled in by OSIF SW before calling + * ol_txrx_osif_vdev_register; inside the ol_txrx_osif_vdev_register + * the txrx SW stores a copy of these rx function pointers, to use + * as it delivers rx data frames to the OSIF SW. + * The tx portion is filled in by the txrx SW inside + * ol_txrx_osif_vdev_register; when the function call returns, + * the OSIF SW stores a copy of these tx functions to use as it + * delivers tx data frames to the txrx SW. + * The rx function pointer inputs consist of the following: + * rx: the OS shim rx function to deliver rx data frames to. + * This can have different values for different virtual devices, + * e.g. so one virtual device's OS shim directly hands rx frames to + * the OS, but another virtual device's OS shim filters out P2P + * messages before sending the rx frames to the OS. + * The netbufs delivered to the osif_rx function are in the format + * specified by the OS to use for tx and rx frames (either 802.3 or + * native WiFi). + * rx_mon: the OS shim rx monitor function to deliver monitor data to + * Though in practice, it is probable that the same function will + * be used for delivering rx monitor data for all virtual devices, + * in theory each different virtual device can have a different + * OS shim function for accepting rx monitor data. + * The netbufs delivered to the osif_rx_mon function are in 802.11 + * format. Each netbuf holds a 802.11 MPDU, not an 802.11 MSDU. + * Depending on compile-time configuration, each netbuf may also + * have a monitor-mode encapsulation header such as a radiotap + * header added before the MPDU contents. + * The tx function pointer outputs consist of the following: + * tx: the tx function pointer for standard data frames + * This function pointer is set by the txrx SW to perform + * host-side transmit operations based on whether a HL or LL + * host/target interface is in use. + * tx_non_std: the tx function pointer for non-standard data frames, + * such as TSO frames, explicitly-prioritized frames, or "raw" + * frames which skip some of the tx operations, such as 802.11 + * MAC header encapsulation. + */ +void +ol_txrx_osif_vdev_register( + ol_txrx_vdev_handle txrx_vdev, + void *osif_vdev, + struct ol_txrx_osif_ops *txrx_ops); + +/** + * @brief Divide a jumbo TCP frame into smaller segments. + * @details + * For efficiency, the protocol stack above the WLAN driver may operate + * on jumbo tx frames, which are larger than the 802.11 MTU. + * The OSIF SW uses this txrx API function to divide the jumbo tx TCP frame + * into a series of segment frames. + * The segments are created as clones of the input jumbo frame. + * The txrx SW generates a new encapsulation header (ethernet + IP + TCP) + * for each of the output segment frames. The exact format of this header, + * e.g. 802.3 vs. Ethernet II, and IPv4 vs. IPv6, is chosen to match the + * header format of the input jumbo frame. + * The input jumbo frame is not modified. + * After the ol_txrx_osif_tso_segment returns, the OSIF SW needs to perform + * DMA mapping on each of the segment network buffers, and also needs to + * + * @param txrx_vdev - which virtual device will transmit the TSO segments + * @param max_seg_payload_bytes - the maximum size for the TCP payload of + * each segment frame. + * This does not include the ethernet + IP + TCP header sizes. + * @param jumbo_tcp_frame - jumbo frame which needs to be cloned+segmented + * @return + * NULL if the segmentation fails, - OR - + * a NULL-terminated list of segment network buffers + */ +adf_nbuf_t ol_txrx_osif_tso_segment( + ol_txrx_vdev_handle txrx_vdev, + int max_seg_payload_bytes, + adf_nbuf_t jumbo_tcp_frame); + +#endif /* _OL_TXRX_OSIF_API__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_stats.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_stats.h new file mode 100644 index 000000000000..afc67d543d7f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_stats.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @file ol_txrx_status.h + * @brief Functions provided for visibility and debugging. + * NOTE: This file is used by both kernel driver SW and userspace SW. + * Thus, do not reference use any kernel header files or defs in this file! + */ +#ifndef _OL_TXRX_STATS__H_ +#define _OL_TXRX_STATS__H_ + +#include /* u_int64_t */ + +#define TXRX_STATS_LEVEL_OFF 0 +#define TXRX_STATS_LEVEL_BASIC 1 +#define TXRX_STATS_LEVEL_FULL 2 + +#ifndef TXRX_STATS_LEVEL +#ifdef CONFIG_HL_SUPPORT +#define TXRX_STATS_LEVEL TXRX_STATS_LEVEL_BASIC +#else +#define TXRX_STATS_LEVEL TXRX_STATS_LEVEL_FULL +#endif +#endif + +typedef struct { + u_int64_t pkts; + u_int64_t bytes; +} ol_txrx_stats_elem; + +/** + * @brief data stats published by the host txrx layer + */ +struct ol_txrx_stats { + struct { + /* MSDUs given to the txrx layer by the management stack */ + ol_txrx_stats_elem mgmt; + /* MSDUs successfully sent across the WLAN */ + ol_txrx_stats_elem delivered; + struct { + /* MSDUs that the host did not accept */ + ol_txrx_stats_elem host_reject; + /* MSDUs which could not be downloaded to the target */ + ol_txrx_stats_elem download_fail; + /* MSDUs which the target discarded (lack of mem or old age) */ + ol_txrx_stats_elem target_discard; + /* MSDUs which the target sent but couldn't get an ack for */ + ol_txrx_stats_elem no_ack; + } dropped; + /* contains information of packets recevied per tx completion*/ + struct { + u_int32_t pkts_1; + u_int32_t pkts_2_10; + u_int32_t pkts_11_20; + u_int32_t pkts_21_30; + u_int32_t pkts_31_40; + u_int32_t pkts_41_50; + u_int32_t pkts_51_60; + u_int32_t pkts_61_plus; + } comp_histogram; + } tx; + struct { + /* MSDUs given to the OS shim */ + ol_txrx_stats_elem delivered; + struct { + /* MSDUs forwarded to network stack */ + u_int32_t packets_stack; + /* MSDUs forwarded from the rx path to the tx path */ + u_int32_t packets_fwd; + /* MSDUs forwarded to stack and tx path */ + u_int32_t packets_stack_n_fwd; + } intra_bss_fwd; + } rx; +}; + +/* + * Structure to consolidate host stats + */ +struct ieee80211req_ol_ath_host_stats { + struct ol_txrx_stats txrx_stats; + struct { + int pkt_q_fail_count; + int pkt_q_empty_count; + int send_q_empty_count; + } htc; + struct { + int pipe_no_resrc_count; + int ce_ring_delta_fail_count; + } hif; +}; + +#endif /* _OL_TXRX_STATS__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_vowext_dbg_defs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_vowext_dbg_defs.h new file mode 100644 index 000000000000..3c8c8039a1cb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_vowext_dbg_defs.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _VOW_DEFINES__H_ +#define _VOW_DEFINES__H_ + + +#define UDP_CKSUM_OFFSET 40 /* UDP check sum offset in network buffer */ +#define RTP_HDR_OFFSET 42 /* RTP header offset in network buffer */ +#define EXT_HDR_OFFSET 54 /* Extension header offset in network buffer */ +#define UDP_PDU_RTP_EXT 0x90 /* ((2 << 6) | (1 << 4)) RTP Version 2 + X bit */ +#define IP_VER4_N_NO_EXTRA_HEADERS 0x45 +#define IPERF3_DATA_OFFSET 12 /* iperf3 data offset from EXT_HDR_OFFSET */ +#define HAL_RX_40 0x08 /* 40 Mhz */ +#define HAL_RX_GI 0x04 /* full gi */ + +struct vow_extstats { + u_int8_t rx_rssi_ctl0; /* control channel chain0 rssi */ + u_int8_t rx_rssi_ctl1; /* control channel chain1 rssi */ + u_int8_t rx_rssi_ctl2; /* control channel chain2 rssi */ + u_int8_t rx_rssi_ext0; /* extention channel chain0 rssi */ + u_int8_t rx_rssi_ext1; /* extention channel chain1 rssi */ + u_int8_t rx_rssi_ext2; /* extention channel chain2 rssi */ + u_int8_t rx_rssi_comb; /* combined RSSI value */ + u_int8_t rx_bw; /* Band width 0-20, 1-40, 2-80 */ + u_int8_t rx_sgi; /* Guard interval, 0-Long GI, 1-Short GI */ + u_int8_t rx_nss; /* Number of spatial streams */ + u_int8_t rx_mcs; /* Rate MCS value */ + u_int8_t rx_ratecode; /* Hardware rate code */ + u_int8_t rx_rs_flags; /* Recieve misc flags */ + u_int8_t rx_moreaggr; /* 0 - non aggr frame */ + u_int32_t rx_macTs; /* Time stamp */ + u_int16_t rx_seqno; /* rx sequence number*/ +}; + +/** + * @brief populates vow ext stats in given network buffer. + * @param msdu - network buffer handle + * @param pdev - handle to htt dev. + */ +void ol_ath_add_vow_extstats(htt_pdev_handle pdev, adf_nbuf_t msdu); + +#endif /* _VOW_DEFINES__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osapi_linux.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osapi_linux.h new file mode 100644 index 000000000000..6a8517527b69 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osapi_linux.h @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +//------------------------------------------------------------------------------ +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +//------------------------------------------------------------------------------ + +#ifndef _OSAPI_LINUX_H_ +#define _OSAPI_LINUX_H_ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//#include +#include "a_types.h" + +#ifdef __GNUC__ +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#else /* Not GCC */ +#define __ATTRIB_PACK +#define __ATTRIB_PRINTF +#define __ATTRIB_NORETURN +#endif /* End __GNUC__ */ + +#define PREPACK +#define POSTPACK __ATTRIB_PACK + +/* + * Endianes macros + */ +#define A_BE2CPU8(x) ntohb(x) +#define A_BE2CPU16(x) ntohs(x) +#define A_BE2CPU32(x) ntohl(x) + +#define A_LE2CPU8(x) (x) +#define A_LE2CPU16(x) (x) +#define A_LE2CPU32(x) (x) + +#define A_CPU2BE8(x) htonb(x) +#define A_CPU2BE16(x) htons(x) +#define A_CPU2BE32(x) htonl(x) + +#define A_MEMCPY(dst, src, len) memcpy((A_UINT8 *)(dst), (src), (len)) +#define A_MEMZERO(addr, len) memset(addr, 0, len) +#define A_MEMSET(addr, value, size) memset((addr), (value), (size)) +#define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len)) + +#ifdef AR6K_ALLOC_DEBUG +#define a_meminfo_add(p, s) __a_meminfo_add(p, s, __func__, __LINE) +#define a_mem_trace(ptr) __a_mem_trace(ptr, __func__, __LINE__) +void __a_mem_trace(void *ptr, const char *func, int lineno); +void __a_meminfo_add(void *ptr, size_t msize, const char *func, int lineno); +void a_meminfo_del(void *ptr); +void* a_mem_alloc(size_t msize, int type, const char *func, int lineno); +void a_mem_free(void *ptr); +void a_meminfo_report(int clear); +#define A_MALLOC(size) a_mem_alloc((size), GFP_KERNEL, __func__, __LINE__) +#define A_MALLOC_NOWAIT(size) a_mem_alloc((size), GFP_ATOMIC, __func__, __LINE__) +#define A_FREE(addr) a_mem_free(addr) +#define A_NETIF_RX(skb) do { a_meminfo_del(skb); netif_rx(skb); } while (0) +#define A_NETIF_RX_NI(skb) do { a_meminfo_del(skb); netif_rx_ni(skb); } while (0) +#else +#define a_meminfo_report(_c) +#define A_MALLOC(size) adf_os_mem_alloc(NULL, size) +#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) +#define a_mem_trace(ptr) +#define A_FREE(addr) adf_os_mem_free(addr) +#define A_NETIF_RX(skb) netif_rx(skb) +#define A_NETIF_RX_NI(skb) netif_rx_ni(skb) +#endif + +#define OS_DMA_MALLOC(size) kmalloc((size), GFP_ATOMIC) +#define OS_DMA_FREE(addr) kfree(addr) + +#define A_VMALLOC(size) vmalloc((size)) +#define A_VFREE(addr) vfree(addr) +#if defined(ANDROID_ENV) && defined(CONFIG_ANDROID_LOGGER) +extern unsigned int enablelogcat; +extern int android_logger_lv(void* module, int mask); +enum logidx { LOG_MAIN_IDX = 0 }; +extern int logger_write(const enum logidx idx, + const unsigned char prio, + const char __kernel * const tag, + const char __kernel * const fmt, + ...); +#define A_ANDROID_PRINTF(mask, module, tags, args...) do { \ + if (enablelogcat) \ + logger_write(LOG_MAIN_IDX, android_logger_lv(module, mask), tags, args); \ + else \ + printk(KERN_ALERT args); \ +} while (0) +#ifdef DEBUG +#define A_LOGGER_MODULE_NAME(x) #x +#define A_LOGGER(mask, mod, args...) \ + A_ANDROID_PRINTF(mask, &GET_ATH_MODULE_DEBUG_VAR_NAME(mod), "ar6k_" A_LOGGER_MODULE_NAME(mod), args); +#endif +#define A_PRINTF(args...) A_ANDROID_PRINTF(ATH_DEBUG_INFO, NULL, "ar6k_driver", args) +#else +#define A_LOGGER(mask, mod, args...) printk(args) +#define A_PRINTF(args...) printk(args) +#endif /* ANDROID */ +#define A_PRINTF_LOG(args...) printk(args) +#define A_SNPRINTF(buf, len, args...) snprintf (buf, len, args) + +/* Mutual Exclusion */ +typedef spinlock_t A_MUTEX_T; +#define A_MUTEX_INIT(mutex) spin_lock_init(mutex) +#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex) +#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex) +#define A_IS_MUTEX_VALID(mutex) TRUE /* okay to return true, since A_MUTEX_DELETE does nothing */ +#define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */ + +/* Get current time in ms adding a constant offset (in ms) */ +#define A_GET_MS(offset) \ + (((jiffies / HZ) * 1000) + (offset)) + +/* + * Timer Functions + */ +#define A_MDELAY(msecs) mdelay(msecs) +#define A_MSLEEP(msecs) \ +{ \ + set_current_state(TASK_INTERRUPTIBLE); \ + schedule_timeout((HZ * (msecs)) / 1000); \ + set_current_state(TASK_RUNNING); \ +} + +typedef struct timer_list A_TIMER; + +#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \ + init_timer_deferrable(pTimer); \ + (pTimer)->function = (pFunction); \ + (pTimer)->data = (unsigned long)(pArg); \ +} while (0) + +/* + * Start a Timer that elapses after 'periodMSec' milli-seconds + * Support is provided for a one-shot timer. The 'repeatFlag' is + * ignored. + */ +#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \ + if (repeatFlag) { \ + printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \ + panic("Timer Repeat"); \ + } \ + mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \ +} while (0) + +/* + * Cancel the Timer. + */ +#define A_UNTIMEOUT(pTimer) do { \ + del_timer((pTimer)); \ +} while (0) + +#define A_DELETE_TIMER(pTimer) do { \ +} while (0) + +/* + * Wait Queue related functions + */ +typedef wait_queue_head_t A_WAITQUEUE_HEAD; +#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head) +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif /* wait_event_interruptible_timeout */ + +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ + wait_event_interruptible_timeout(head, condition, timeout); \ +} while (0) + +#define A_WAKE_UP(head) wake_up(head) + +#ifdef DEBUG +#ifdef A_SIMOS_DEVHOST +extern unsigned int panic_on_assert; +#define A_ASSERT(expr) \ + if (!(expr)) { \ + printk(KERN_ALERT"Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#expr); \ + if (panic_on_assert) panic(#expr); \ + } +#else +#define A_ASSERT(expr) \ + if (!(expr)) { \ + printk(KERN_ALERT "Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#expr); \ + } +#endif +#else +#define A_ASSERT(expr) +#endif /* DEBUG */ + +#ifdef ANDROID_ENV +struct firmware; +int android_request_firmware(const struct firmware **firmware_p, const char *filename, + struct device *device); +void android_release_firmware(const struct firmware *firmware); +#define A_REQUEST_FIRMWARE(_ppf, _pfile, _dev) android_request_firmware(_ppf, _pfile, _dev) +#define A_RELEASE_FIRMWARE(_pf) android_release_firmware(_pf) +#else +#define A_REQUEST_FIRMWARE(_ppf, _pfile, _dev) request_firmware(_ppf, _pfile, _dev) +#define A_RELEASE_FIRMWARE(_pf) release_firmware(_pf) +#endif + +/* + * Initialization of the network buffer subsystem + */ +#define A_NETBUF_INIT() + +/* + * Network buffer queue support + */ +typedef struct sk_buff_head A_NETBUF_QUEUE_T; + +#define A_NETBUF_QUEUE_INIT(q) \ + a_netbuf_queue_init(q) + +#define A_NETBUF_ENQUEUE(q, pkt) \ + a_netbuf_enqueue((q), (pkt)) +#define A_NETBUF_PREQUEUE(q, pkt) \ + a_netbuf_prequeue((q), (pkt)) +#define A_NETBUF_DEQUEUE(q) \ + (a_netbuf_dequeue(q)) +#define A_NETBUF_QUEUE_SIZE(q) \ + a_netbuf_queue_size(q) +#define A_NETBUF_QUEUE_EMPTY(q) \ + a_netbuf_queue_empty(q) + +/* + * Network buffer support + */ +#ifdef AR6K_ALLOC_DEBUG +#define A_NETBUF_ALLOC(size) \ + a_netbuf_alloc(size, __func__, __LINE__) +#define A_NETBUF_ALLOC_RAW(size) \ + a_netbuf_alloc_raw(size, __func__, __LINE__) +#define A_NETBUF_MANAGE(bufPtr) \ + a_netbuf_manage(bufPtr, __func__, __LINE__) +#define A_NETBUF_UNMANAGE(bufPtr) \ + a_netbuf_unmanage(bufPtr) +#else +#define A_NETBUF_ALLOC(size) \ + a_netbuf_alloc(size) +#define A_NETBUF_ALLOC_RAW(size) \ + a_netbuf_alloc_raw(size) +#define A_NETBUF_MANAGE(bufPtr) +#define A_NETBUF_UNMANAGE(bufPtr) +#endif /* AR6K_ALLOC_DEBUG */ +#define A_NETBUF_FREE(bufPtr) \ + a_netbuf_free(bufPtr) +#define A_NETBUF_LEN(bufPtr) \ + a_netbuf_to_len(bufPtr) +#define A_NETBUF_PUSH(bufPtr, len) \ + a_netbuf_push(bufPtr, len) +#define A_NETBUF_PUT(bufPtr, len) \ + a_netbuf_put(bufPtr, len) +#define A_NETBUF_TRIM(bufPtr,len) \ + a_netbuf_trim(bufPtr, len) +#define A_NETBUF_PULL(bufPtr, len) \ + a_netbuf_pull(bufPtr, len) +#define A_NETBUF_HEADROOM(bufPtr)\ + a_netbuf_headroom(bufPtr) +#define A_NETBUF_SETLEN(bufPtr,len) \ + a_netbuf_setlen(bufPtr, len) + +/* Add data to end of a buffer */ +#define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \ + a_netbuf_put_data(bufPtr, srcPtr, len) + +/* Add data to start of the buffer */ +#define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \ + a_netbuf_push_data(bufPtr, srcPtr, len) + +/* Remove data at start of the buffer */ +#define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \ + a_netbuf_pull_data(bufPtr, dstPtr, len) + +/* Remove data from the end of the buffer */ +#define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \ + a_netbuf_trim_data(bufPtr, dstPtr, len) + +/* View data as "size" contiguous bytes of type "t" */ +#define A_NETBUF_VIEW_DATA(bufPtr, t, size) \ + (t )( ((struct skbuf *)(bufPtr))->data) + +/* return the beginning of the headroom for the buffer */ +#define A_NETBUF_HEAD(bufPtr) \ + ((((struct sk_buff *)(bufPtr))->head)) + +/* + * OS specific network buffer access routines + */ +#ifdef AR6K_ALLOC_DEBUG +void *a_netbuf_alloc(int size, const char *func, int lineno); +void *a_netbuf_alloc_raw(int size, const char *func, int lineno); +void a_netbuf_manage(void *bufPtr, const char *func, int lineno); +void a_netbuf_unmanage(void *bufPtr); +#else +void *a_netbuf_alloc(int size); +void *a_netbuf_alloc_raw(int size); +#endif +void a_netbuf_free(void *bufPtr); +void *a_netbuf_to_data(void *bufPtr); +A_UINT32 a_netbuf_to_len(void *bufPtr); +A_STATUS a_netbuf_push(void *bufPtr, A_INT32 len); +A_STATUS a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len); +A_STATUS a_netbuf_put(void *bufPtr, A_INT32 len); +A_STATUS a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len); +A_STATUS a_netbuf_pull(void *bufPtr, A_INT32 len); +A_STATUS a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len); +A_STATUS a_netbuf_trim(void *bufPtr, A_INT32 len); +A_STATUS a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len); +A_STATUS a_netbuf_setlen(void *bufPtr, A_INT32 len); +A_INT32 a_netbuf_headroom(void *bufPtr); +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt); +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt); +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q); + +/* + * Kernel v.s User space functions + */ +A_UINT32 a_copy_to_user(void *to, const void *from, A_UINT32 n); +A_UINT32 a_copy_from_user(void *to, const void *from, A_UINT32 n); + +/* In linux, WLAN Rx and Tx run in different contexts, so no need to check + * for any commands/data queued for WLAN */ +#define A_CHECK_DRV_TX() + +#define A_GET_CACHE_LINE_BYTES() L1_CACHE_BYTES + +#define A_CACHE_LINE_PAD 128 + +static inline void *A_ALIGN_TO_CACHE_LINE(void *ptr) { + return (void *)L1_CACHE_ALIGN((unsigned long)ptr); +} + +#ifdef QCA_PARTNER_PLATFORM + +#include "ath_carr_pltfrm.h" + +#else +#define A_PCI_READ32(addr) ioread32((void __iomem *)addr) +#define A_PCI_WRITE32(addr, value) iowrite32((u32)(value), (void __iomem *)(addr)) +#endif /* QCA_PARTNER_PLATFORM */ + +typedef struct semaphore A_SEMA; +#define A_SEMA_INIT(_sem, _val) sema_init((_sem), (_val)) +static __inline__ +void A_SEMA_WAKEUP(void *osdev, A_SEMA *sem) +{ + up(sem); +} +static __inline__ +bool A_SEMA_SLEEP(void *osdev, A_SEMA *sem) +{ + return down_timeout(sem, HZ); +} + + +typedef struct ieee80211_cb wbuf_context; +#define wbuf_get_cb(skb) ((skb)->cb) + +#else /* __KERNEL__ */ + +#ifdef __GNUC__ +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#ifndef INLINE +#define INLINE __inline__ +#endif +#else /* Not GCC */ +#define __ATTRIB_PACK +#define __ATTRIB_PRINTF +#define __ATTRIB_NORETURN +#ifndef INLINE +#define INLINE __inline +#endif +#endif /* End __GNUC__ */ + +#define PREPACK +#define POSTPACK __ATTRIB_PACK + +#define A_MEMCPY(dst, src, len) memcpy((dst), (src), (len)) +#define A_MEMSET(addr, value, size) memset((addr), (value), (size)) +#define A_MEMZERO(addr, len) memset((addr), 0, (len)) +#define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len)) +#define A_MALLOC(size) malloc(size) +#define A_FREE(addr) free(addr) + + +#ifdef ANDROID +#ifndef err +#include +#define err(_s, args...) do { \ + fprintf(stderr, "%s: line %d ", __FILE__, __LINE__); \ + fprintf(stderr, args); fprintf(stderr, ": %d\n", errno); \ + exit(_s); } while (0) +#endif +#else +#include +#endif + +#endif /* __KERNEL__ */ + +#endif /* _OSAPI_LINUX_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep.h new file mode 100644 index 000000000000..46248546c22e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ATH_LINUX_OSDEP_H +#define _ATH_LINUX_OSDEP_H +#include "wlan_opts.h" + +#ifdef ADF_SUPPORT +#include "osdep_adf.h" +#endif /* end of ADF_SUPPORT */ + +#ifdef HOST_OFFLOAD + +void atd_proxy_arp_send(struct sk_buff *nbuf); +void atd_rx_from_wlan(struct sk_buff * nbuf); + +static inline int _copy_to_user(void *dst ,void *src, int size) +{ + memcpy(dst,src,size); + return 0; +} +static inline int _copy_from_user(void *dst ,void *src, int size) +{ + memcpy(dst,src,size); + return 0; +} + +#define _netif_carrier_on(dev) \ + do { \ + union iwreq_data w; \ + netif_carrier_on(dev); \ + memset(&w, 0, sizeof(w)); \ + w.data.flags = IEEE80211_EV_IF_RUNNING; \ + wireless_send_event(dev, \ + IWEVCUSTOM, &w, NULL); \ + } while (0) +#define _netif_carrier_off(dev) \ + do { \ + union iwreq_data w; \ + netif_carrier_off(dev); \ + memset(&w, 0, sizeof(w)); \ + w.data.flags = IEEE80211_EV_IF_NOT_RUNNING; \ + wireless_send_event(dev, \ + IWEVCUSTOM, &w, NULL); \ + } while (0) + +void +atd_event_handler(struct net_device *dev, unsigned int cmd, + union iwreq_data *wreq, char *extra); + +#define __osif_deliver_data(_osif, _skb) \ +{\ + struct net_device *dev = ((osif_dev*)(_osif))->netdev;\ + _skb->dev = dev;\ + atd_rx_from_wlan(_skb);\ +} + +#undef wireless_send_event + +#define wireless_send_event atd_event_handler + +#else + +#define __osif_deliver_data(_osif, _skb) osif_deliver_data(_osif, _skb) +#define _copy_to_user copy_to_user +#define _copy_from_user copy_from_user +#define _netif_carrier_on netif_carrier_on +#define _netif_carrier_off netif_carrier_off + +#endif + +#ifndef OS_EXPORT_SYMBOL +#define OS_EXPORT_SYMBOL(_sym) EXPORT_SYMBOL(_sym) +#endif + +#ifndef OS_WMB +#define OS_WMB() wmb() +#endif + +#endif /* end of _ATH_LINUX_OSDEP_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep_adf.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep_adf.h new file mode 100644 index 000000000000..9d7f0cf2d412 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/osdep_adf.h @@ -0,0 +1,1245 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _ATH_LINUX_OSDEP_ADF_H +#define _ATH_LINUX_OSDEP_ADF_H + +#include "wlan_opts.h" +#include +#include +#include +#include +#include +#include +#include + + #include + #include + #include +#if defined(HIF_USB) +#include +#else + #include +#endif + #include + #include + #include + #include + #include + + + #include + #include + #include + + +#include +#include + +#include + +#include "if_upperproto.h" +#include "ah_osdep.h" + +#ifdef AR9100 +#include +#endif /* AR9100 */ + +#define INLINE __adf_os_inline + +/* UNREFERENCED_PARAMETER - provide a dummy reference */ +#define UNREFERENCED_PARAMETER(an) ((void) (an)) + +#if ATH_DEBUG +#ifndef ASSERT +#define ASSERT(expr) adf_os_assert(expr) +#endif +#else +#define ASSERT(expr) +#endif /* ATH_DEBUG */ + +#define OS_LOG_DBGPRINT(_xfmt, ...) + +#ifdef AR9100 +/* + * Howl needs DDR FIFO flush before any desc/dma data can be read. + */ +#define ATH_FLUSH_FIFO ar9100_flush_wmac +#else +#define ATH_FLUSH_FIFO() +#endif + +#define KASSERT(exp, msg) do { \ + if (unlikely(!(exp))) { \ + printk msg; \ + BUG(); \ + } \ +} while (0) + +/* + * Map Linux spin locks to OS independent names + */ +#ifdef ANDROID +static inline void spin_lock_dpc(spinlock_t *lock) +{ + adf_os_spin_lock_bh((adf_os_spinlock_t *)lock); +} +static inline void spin_unlock_dpc(spinlock_t *lock) +{ + adf_os_spin_unlock_bh((adf_os_spinlock_t *)lock); +} +#else +#define spin_lock_dpc(a) adf_os_spin_lock_bh(a) +#define spin_unlock_dpc(a) adf_os_spin_unlock_bh(a) +#endif + +#define spin_lock_destroy(a) + +#define os_tasklet_lock(a, b) adf_os_spin_lock_irq(a, b) +#define os_tasklet_unlock(a, b) adf_os_spin_unlock_irq(a, b) + +/* +** Need to define byte order based on the CPU configuration. +*/ +#ifndef _LITTLE_ENDIAN +#define _LITTLE_ENDIAN 1234 +#endif +#ifndef _BIG_ENDIAN +#define _BIG_ENDIAN 4321 +#endif +#ifdef __BIG_ENDIAN + #define _BYTE_ORDER _BIG_ENDIAN +#else + #define _BYTE_ORDER _LITTLE_ENDIAN +#endif + +/* + * Work Queue related macros + */ + +#define ATH_CREATE_WQUEUE(name) adf_os_create_workqueue(name) +#define ATH_CREATE_WORK(a,b,c) adf_os_create_work(0, a, b, c) +#define ATH_CREATE_DELAYED_WORK(a,b,c) adf_os_create_delayed_work(0, a, b, c) +#define ATH_QUEUE_WORK(a,b) adf_os_queue_work(0, a, b) +#define ATH_QUEUE_DELAYED_WORK(a,b,c) adf_os_queue_delayed_work(0, a, b, c) +#define ATH_FLUSH_WQUEUE(a) adf_os_flush_workqueue(0, a) +#define ATH_DESTROY_WQUEUE(a) adf_os_destroy_workqueue(0, a) + +/* + * Deduce if tasklets are available. If not then + * fall back to using the immediate work queue. + */ +#define tq_struct adf_os_bh_t +#define ATH_INIT_TQUEUE(a,b,c) adf_os_create_bh(0, a, b, c) +#define ATH_SCHEDULE_TQUEUE(a,b) adf_os_sched_bh(0, a) +typedef unsigned long TQUEUE_ARG; +#define mark_bh(a) + +#define ATH_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \ + f(struct ctl_table *ctl, int write, void *buffer, \ + size_t *lenp, loff_t *ppos) +#define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \ + proc_dointvec(ctl, write, buffer, lenp, ppos) +#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \ + proc_dostring(ctl, write, filp, buffer, lenp, ppos) + +/* + * Byte Order stuff + */ +#define le16toh(_x) le16_to_cpu(_x) +#define htole16(_x) cpu_to_le16(_x) +#define htobe16(_x) cpu_to_be16(_x) +#define le32toh(_x) le32_to_cpu(_x) +#define htole32(_x) cpu_to_le32(_x) +#define be16toh(_x) be16_to_cpu(_x) +#define be32toh(_x) be32_to_cpu(_x) +#define htobe32(_x) cpu_to_be32(_x) + +#define EOK (0) + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define IP_PRI_SHIFT 5 + +#ifndef IPV6_VERSION_MASK +#define IPV6_VERSION_MASK 0xF0000000 +#endif +#ifndef IPV6_PRIORITY_MASK +#define IPV6_PRIORITY_MASK 0x0FF00000 +#endif +#ifndef IPV6_FLOWLABEL_MASK +#define IPV6_FLOWLABEL_MASK 0x000FFFFF +#endif +#ifndef IPV6_VERSION_SHIFT +#define IPV6_VERSION_SHIFT 28 +#endif +#ifndef IPV6_PRIORITY_SHIFT +#define IPV6_PRIORITY_SHIFT 20 +#endif +#ifndef IPV6_FLOWLABEL_SHIFT +#define IPV6_FLOWLABEL_SHIFT 0 +#endif + +#ifndef ARPHRD_IEEE80211 +#define ARPHRD_IEEE80211 801 /* IEEE 802.11. */ +#endif + +#define MAX_TX_RX_PACKET_SIZE 2500 + +static INLINE const char * +ether_sprintf(const uint8_t mac[6]) +{ + static char buf[32]; + + __adf_os_snprint(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return buf; +} + +typedef unsigned int rwlock_state_t __attribute__((unused)); + +#define OS_ATOMIC_CMPXCHG(_Counter, _cmp, _xchg) cmpxchg((int32_t*)(_Counter), _cmp, _xchg) + +/* + * Normal Delay functions. Time specified in microseconds. + */ +#define OS_DELAY(_us) adf_os_udelay(_us) + +#define OS_SLEEP(_us) schedule_timeout_uninterruptible(usecs_to_jiffies(_us)) + +#define OS_MEMCPY(_dst, _src, _len) adf_os_mem_copy(_dst, _src, _len) +#define OS_MEMMOVE(_dst, _src, _len) adf_os_mem_move(_dst, _src, _len) +#define OS_MEMZERO(_buf, _len) adf_os_mem_zero(_buf, _len) +#define OS_MEMSET(_buf, _ch, _len) adf_os_mem_set(_buf, _ch, _len) +#define OS_MEMCMP(_mem1, _mem2, _len) adf_os_mem_cmp(_mem1, _mem2, _len) + +#define OS_SET_WDTIMEOUT(__sc, __timeo) \ +{\ + ((__sc)->sc_osdev->netdev)->watchdog_timeo = (__timeo);\ +} + +#define OS_CLR_NETDEV_FLAG(__sc, __flag)\ +{\ + ((__sc)->sc_osdev->netdev)->flags &= ~(__flag);\ +} +#define OS_NETIF_WAKE_QUEUE(__sc)\ +{\ + netif_wake_queue(((__sc)->sc_osdev->netdev));\ +} +#define OS_NETIF_STOP_QUEUE(__sc)\ +{\ + netif_stop_queue(((__sc)->sc_osdev->netdev));\ +} +#define OS_NETDEV_UPDATE_TRANS(__sc)\ +{\ + ((__sc)->sc_osdev->netdev)->trans_start = jiffies;\ +} + +/* + * Locking interface for node + */ +#ifdef ATH_USB +typedef rwlock_t usb_readwrite_lock_t; +#endif + +#define OS_RWLOCK_INIT(_rwl) rwlock_init(_rwl) +#define OS_RWLOCK_DESTROY(_nt) + +#ifdef CONFIG_SMP +/* Undo the one provided by the kernel to debug spin locks */ +#undef spin_lock +#undef spin_unlock +#undef spin_trylock + +#define spin_lock(x) \ +do { \ + spin_lock_bh(x);\ +} while (0) + +#define spin_unlock(x) \ +do { \ +if (!spin_is_locked(x)) { \ +WARN_ON(1); \ +printk(KERN_EMERG " %s:%d unlock addr=%p, %s \n", __func__, __LINE__, x, \ +!spin_is_locked(x)? "Not locked":""); \ +} \ +spin_unlock_bh(x);\ +} while (0) + +#define spin_trylock(x) spin_trylock_bh(x) + +#define OS_SUPPORT_ASYNC_Q 1 /* support for handling asyn function calls */ + +#endif // ifdef CONFIG_SMP + +#define OS_RWLOCK_READ_LOCK(rwl, lock_state) do {\ + if (irqs_disabled() || in_irq()) {\ + read_lock(rwl);\ + } else {\ + read_lock_bh(rwl);\ + }\ +} while (0) + +#define OS_RWLOCK_WRITE_LOCK(rwl, lock_state) do { \ + if (irqs_disabled() || in_irq()) {\ + write_lock(rwl);\ + } else {\ + write_lock_bh(rwl);\ + }\ +} while(0) + +#define OS_RWLOCK_READ_UNLOCK(rwl, lock_state) do {\ + if (irqs_disabled() || in_irq()) {\ + read_unlock(rwl);\ + } else {\ + read_unlock_bh(rwl);\ + }\ +} while (0) + +#define OS_RWLOCK_WRITE_UNLOCK(rwl, lock_state) do {\ + if (irqs_disabled() || in_irq()) {\ + write_unlock(rwl);\ + } else {\ + write_unlock_bh(rwl);\ + }\ +} while (0) + +#define OS_RWLOCK_READ_LOCK_BH(rwl, lock_state) do { \ + read_lock_bh(rwl); \ +} while (0) + +#define OS_RWLOCK_WRITE_LOCK_BH(rwl, lock_state) do { \ + write_lock_bh(rwl); \ +} while (0) + +#define OS_RWLOCK_READ_UNLOCK_BH(rwl, lock_state) do { \ + read_unlock_bh(rwl); \ +} while (0) + +#define OS_RWLOCK_WRITE_UNLOCK_BH(rwl, lock_state) do { \ + write_unlock_bh(rwl); \ +} while (0) + +/* Irqsave/restore version */ +#define OS_RWLOCK_READ_LOCK_IRQSAVE(rwl, lock_state, flags) do { \ + read_lock_irqsave(rwl, flags); \ +} while (0) + +#define OS_RWLOCK_WRITE_LOCK_IRQSAVE(rwl, lock_state, flags) do { \ + write_lock_irqsave(rwl, flags); \ +} while (0) + +#define OS_RWLOCK_READ_UNLOCK_IRQRESTORE(rwl, lock_state, flags) do { \ + read_unlock_irqrestore(rwl, flags); \ +} while (0) + +#define OS_RWLOCK_WRITE_UNLOCK_IRQRESTORE(rwl, lock_state, flags) do { \ + write_unlock_irqrestore(rwl, flags); \ +} while (0) + + +#ifndef OS_SUPPORT_ASYNC_Q +#define OS_SUPPORT_ASYNC_Q 0 +#endif + +/* Calculate the modulo with the following restrictions: + lowest 10 bits of div is zero. + div is at most 20 bits. + +Theory for the math. + Suppose x = A + B + Then x % r = ((A % r) + B) % r + + For our case, we let A be the top 32-bits of x which is non-zero. + Then x = (2^22 * a) + b. +*/ +static INLINE u_int32_t OS_MOD64_TBTT_OFFSET(u_int64_t num64, u_int32_t div) +{ + + u_int32_t remainder_last10bits = (u_int32_t)num64 & 0x003FF; + + /* Remove the low 10 bits. */ + div = div >> 10; + num64 = num64 >> 10; + + { + /* Get the mod of the top 32 bits */ + u_int32_t num_hi = (u_int32_t)(num64 >> 22); +#define BITS_22_MASK 0x003FFFFF +#define BITS_10_MASK 0x000003FF + u_int32_t num_lo = (u_int32_t)(num64) & BITS_22_MASK; + + u_int32_t remainder_hi = num_hi % div; + u_int32_t remainder_lo = num_lo; + + u_int32_t remainder32 = (remainder_hi << 22) + remainder_lo; + + remainder32 = remainder32 % div; + /* Put back the last 10 bits */ + remainder32 = (remainder32 << 10) + remainder_last10bits; + + return(remainder32); + } +} + +/* + * System time interface + */ + +typedef adf_os_time_t systime_t; +typedef adf_os_time_t systick_t; + +static INLINE adf_os_time_t +OS_GET_TIMESTAMP(void) +{ + return adf_os_ticks(); /* Fix double conversion from jiffies to ms */ +} + +static INLINE adf_os_time_t +OS_GET_TICKS(void) +{ + return adf_os_ticks(); +} + +#define CONVERT_SYSTEM_TIME_TO_MS(_t) adf_os_ticks_to_msecs(_t) +#define CONVERT_SYSTEM_TIME_TO_SEC(_t) (adf_os_ticks_to_msecs(_t) / 1000) +#define CONVERT_SEC_TO_SYSTEM_TIME(_t) ((_t) * HZ) +#define CONVERT_MS_TO_SYSTEM_TIME(_t) ((_t) * HZ/1000) + +struct _NIC_DEV; + +typedef struct _NIC_DEV * osdev_t; + + +typedef struct timer_list os_timer_t; +typedef void (*timer_func)(void *); + +typedef struct _os_mesg_t { + STAILQ_ENTRY(_os_mesg_t) mesg_next; + u_int16_t mesg_type; + u_int16_t mesg_len; + /* followed by mesg_len bytes */ +} os_mesg_t; + +#define OS_ASYNC_Q_MAX_MESGS 4 + +#define OS_SCHEDULE_ROUTING_MESG_TYPE 1 + +typedef void* os_task_handle_t; +typedef void (*os_tasklet_routine_t)( + void *context, + os_task_handle_t task_handle + ); + +typedef struct { + os_tasklet_routine_t routine; + atomic_t queued; + void *data; + spinlock_t lock; +} os_task_t; + +typedef struct _os_schedule_routing_mesg { + os_tasklet_routine_t routine; + void* context; +} os_schedule_routing_mesg ; + +typedef union _os_async_q_mesg { + os_schedule_routing_mesg s_mesg; +} os_async_q_mesg; + + +typedef void (*os_mesg_handler_t)( + void *ctx, + u_int16_t mesg_type, + u_int16_t mesg_len, + void *mesg + ); + +typedef struct { + osdev_t dev_handle; + int32_t num_queued; + int32_t mesg_len; + u_int8_t *mesg_queue_buf; + STAILQ_HEAD(, _os_mesg_t) mesg_head; /* queued mesg buffers */ + STAILQ_HEAD(, _os_mesg_t) mesg_free_head; /* free mesg buffers */ + spinlock_t lock; + spinlock_t ev_handler_lock; +#ifdef USE_SOFTINTR + void *_task; +#else + os_timer_t _timer; +#endif + os_mesg_handler_t handler; + void *ctx; + u_int8_t is_synchronous:1; +} os_mesg_queue_t; + +struct ath_freebuf_bin { + TAILQ_ENTRY(ath_freebuf_bin) buf_list; + unsigned char *head; + unsigned char *end; + struct sk_buff *skb; + int lifetime; +}; + +typedef TAILQ_HEAD(ath_freebufhead_s, ath_freebuf_bin) ath_freebufhead; + +struct rxbuf_recycle_ops { + void (*osdev_wbuf_collect)(void *, void *); + void * (*osdev_wbuf_recycle)(void *); +}; +/* + * Definition of OS-dependent device structure. + * It'll be opaque to the actual ATH layer. + */ +struct _NIC_DEV { + void *bdev; /* bus device handle */ + struct net_device *netdev; /* net device handle (wifi%d) */ + adf_os_bh_t intr_tq; /* tasklet */ + struct net_device_stats devstats; /* net device statisitics */ + HAL_BUS_CONTEXT bc; +#ifdef ATH_PERF_PWR_OFFLOAD + struct device *device; /* generic device */ + wait_queue_head_t event_queue; +#endif /* PERF_PWR_OFFLOAD */ +#if OS_SUPPORT_ASYNC_Q + os_mesg_queue_t async_q; /* mesgq to handle async calls */ +#endif +#ifdef ATH_BUS_PM + u_int8_t isDeviceAsleep; +#endif /* ATH_BUS_PM */ +}; + +static INLINE unsigned char * +OS_MALLOC(osdev_t pNicDev, unsigned long ulSizeInBytes, int gfp) +{ + return adf_os_mem_alloc(NULL, ulSizeInBytes); +} +#define OS_FREE(_p) adf_os_mem_free(_p) + +#define OS_MALLOC_WITH_TAG(_ppMem, _size, _tag) do { \ + *(_ppMem) = adf_os_mem_alloc(NULL, _size); \ +} while(0) + +#define OS_FREE_WITH_TAG(_pMem, _size) adf_os_mem_free(_pMem) + +static INLINE void * +OS_ALLOC_VAP(osdev_t osdev, u_int32_t len) +{ + void *netif; + + /* + * In NDIS, we just allocate memory for interface object here. + * For Linux, it may need to allocate and setup a net_device. + */ + netif = adf_os_mem_alloc(NULL, len); + if (netif != NULL) + { + adf_os_mem_zero(netif, len); + } + + return netif; +} + +static INLINE void +OS_FREE_VAP(void *netif) +{ + /* Just free the structure in NDIS. + * In Linux, it should call unregister_netdevice + * to free the memory */ + adf_os_mem_free(netif); +} + +#define bus_type_error 0 + +#define BUS_DMA_FROMDEVICE 0 +#define BUS_DMA_TODEVICE 1 + +#if bus_type_error +#error "No bus type is specified" +#endif + +typedef dma_addr_t * dma_context_t; + +#define OS_DMA_MEM_CONTEXT(context) \ + dma_addr_t context; + +#define OS_GET_DMA_MEM_CONTEXT(var, field) \ + &(var->field) + +#define OS_COPY_DMA_MEM_CONTEXT(dst, src) \ + *dst = *src + +#define OS_ZERO_DMA_MEM_CONTEXT(context) \ + *context = 0 + +#ifdef ATH_SUPPORT_SHARED_IRQ +#define ATH_LOCK_IRQ(_osdev) disable_irq(_osdev->netdev->irq) +#define ATH_UNLOCK_IRQ(_osdev) enable_irq(_osdev->netdev->irq) +#else +#define ATH_LOCK_IRQ(_osdev) +#define ATH_UNLOCK_IRQ(_osdev) +#endif + +#ifdef ATH_SUPPORT_HTC +#define OS_EXEC_INTSAFE(_osdev, _fn, _arg) do { \ + _fn(_arg); \ +} while (0) +#else /* #ifdef ATH_SUPPORT_HTC */ +#define OS_EXEC_INTSAFE(_osdev, _fn, _arg) do { \ + unsigned long flags; \ + ATH_LOCK_IRQ(_osdev); \ + local_irq_save(flags); \ + _fn(_arg); \ + local_irq_restore(flags); \ + ATH_UNLOCK_IRQ(_osdev); \ +} while (0) +#endif /* #ifdef ATH_SUPPORT_HTC */ + +/* + * Timer Interfaces. Use these macros to declare timer + * and retrieve timer argument. This is mainly for resolving + * different argument types for timer function in different OS. + */ + +#define OS_DECLARE_TIMER(_fn) void _fn(void *) + +#define OS_TIMER_FUNC(_fn) \ + void _fn(void *timer_arg) + +#define OS_GET_TIMER_ARG(_arg, _type) \ + (_arg) = (_type)(timer_arg) + + +#define OS_INIT_TIMER(_osdev, _timer, _fn, _ctx, type) adf_os_timer_init(_osdev, _timer, _fn, _ctx, type) + +#define OS_SET_TIMER(_timer, _ms) adf_os_timer_mod(_timer, _ms) + +#define OS_CANCEL_TIMER(_timer) adf_os_timer_cancel(_timer) + +#define OS_FREE_TIMER(_timer) adf_os_timer_cancel(_timer) + +static INLINE void +OS_GET_RANDOM_BYTES(void *p, u_int16_t n) +{ + get_random_bytes(p, n); +} + +typedef enum _mesgq_priority_t { + MESGQ_PRIORITY_LOW, + MESGQ_PRIORITY_NORMAL, + MESGQ_PRIORITY_HIGH +} mesgq_priority_t; + +typedef enum _mesgq_event_delivery_type { + MESGQ_ASYNCHRONOUS_EVENT_DELIVERY, + MESGQ_SYNCHRONOUS_EVENT_DELIVERY, +} mesgq_event_delivery_type; + + + + +/* + * OS_MESGQ_* API to deliver messages(events) asynchronosly. + * messages are queued up into a queue and are delivered in the context of + * timer thread. this will avoid reentrency issues across different + * module boundaries. + */ + +static INLINE void +os_mesgq_handler(void *timer_arg) +{ + os_mesg_queue_t *queue = (os_mesg_queue_t*)timer_arg; + os_mesg_t *mesg = NULL; + void *msg; + + /* + * Request access to message queue to retrieve message for processing + */ + spin_lock(&(queue->lock)); + + mesg = STAILQ_FIRST(&queue->mesg_head); + while(mesg) { + STAILQ_REMOVE_HEAD(&queue->mesg_head, mesg_next); + if (mesg->mesg_len) { + msg = (void *) (mesg+1); + } else { + msg = NULL; + } + /* + * Release access to message queue before processing message + */ + spin_unlock(&(queue->lock)); + + /* + * Ensure just one message can be processes at a time. + */ + spin_lock(&(queue->ev_handler_lock)); + queue->handler(queue->ctx,mesg->mesg_type,mesg->mesg_len, msg); + spin_unlock(&(queue->ev_handler_lock)); + + /* + * Request access to message queue to retrieve next message + */ + spin_lock(&(queue->lock)); + queue->num_queued--; + STAILQ_INSERT_TAIL(&queue->mesg_free_head,mesg, mesg_next); + mesg = STAILQ_FIRST(&queue->mesg_head); + } + + /* + * Release message queue + */ + spin_unlock(&(queue->lock)); +} + +/* + * initialize message queue. + * devhandle : os dev handle. + * queue : message queue. + * mesg_len : maximum length of message. + * max_queued : maximum number of messages that can be queued at any time. + * msg_handler : handler function which will be called + * asynchronously to deliver each message. + */ +static INLINE int OS_MESGQ_INIT(osdev_t devhandle, os_mesg_queue_t *queue, + u_int32_t mesg_len, u_int32_t max_queued, + os_mesg_handler_t msg_handler, void *context, + mesgq_priority_t priority, + mesgq_event_delivery_type mq_type) +{ + int i,len; + os_mesg_t *mesg; + + len = (mesg_len + sizeof(struct _os_mesg_t)); + queue->mesg_queue_buf = adf_os_mem_alloc(NULL, (adf_os_size_t) len*max_queued); + if (!queue->mesg_queue_buf) + return -ENOMEM; + queue->dev_handle = devhandle; + STAILQ_INIT(&queue->mesg_head); + STAILQ_INIT(&queue->mesg_free_head); + spin_lock_init(&(queue->lock)); + spin_lock_init(&(queue->ev_handler_lock)); + mesg = (os_mesg_t *)queue->mesg_queue_buf; + for (i=0;imesg_free_head,mesg,mesg_next); + mesg = (os_mesg_t *) ((u_int8_t *) mesg + len); + } + queue->mesg_len = mesg_len; + queue->ctx = context; + queue->handler = msg_handler; + queue->num_queued = 0; + if (mq_type == MESGQ_ASYNCHRONOUS_EVENT_DELIVERY) { + queue->is_synchronous=0; + } else { + queue->is_synchronous=1; + } +#ifdef USE_SOFTINTR + queue->_task = softintr_establish(IPL_SOFTNET,os_mesgq_handler,(void *)queue); +#else + OS_INIT_TIMER(devhandle,&queue->_timer, os_mesgq_handler, queue, + ADF_DEFERRABLE_TIMER); +#endif + + return 0; +} + +/* + * send a message. + * queue : message queue. + * msg : message (opaque) . the size of the message + * is equal to the mesg_length passed to the OS_MESG_INIT + * + */ +static INLINE int OS_MESGQ_SEND(os_mesg_queue_t *queue,u_int16_t type, u_int16_t len, void *msg) +{ + os_mesg_t *mesg; + + spin_lock(&(queue->lock)); + if (queue->is_synchronous ) { + queue->handler(queue->ctx,type,len, msg); + } else { + mesg = STAILQ_FIRST(&queue->mesg_free_head); + KASSERT(len <= queue->mesg_len, ("len <= queue->mesg_len")); + if (mesg) { + STAILQ_REMOVE_HEAD(&queue->mesg_free_head, mesg_next); + mesg->mesg_type = type; + mesg->mesg_len = len; + if (len) { + OS_MEMCPY((u_int8_t *)(mesg+1),msg,len); + } + STAILQ_INSERT_TAIL(&queue->mesg_head, mesg, mesg_next); + queue->num_queued++; + } else { + spin_unlock(&(queue->lock)); + printk("No more message queue buffers !!! \n"); + return -ENOMEM; + } + if (queue->num_queued == 1) { + /* schedule a task (timer) to handle the messages */ +#ifdef USE_SOFTINTR + softintr_schedule(queue->_task); +#else + OS_SET_TIMER(&queue->_timer,0); +#endif + } + } + spin_unlock(&(queue->lock)); + return 0; +} + +/* + * this is only for single threaded operating systems. + * assert for now. + */ +static INLINE int OS_MESGQ_SEND_SYNC(os_mesg_queue_t *queue,u_int16_t type, u_int16_t len, void *msg, bool flush) +{ + KASSERT(0,(" mesg queue sync send is not supported by linux")); + return 0; +} + +static INLINE int OS_MESGQ_CAN_SEND_SYNC(void) +{ + return TRUE; +} + +/* + * drain all the messages. + * queue : message queue. + */ +static INLINE void OS_MESGQ_DRAIN(os_mesg_queue_t *queue, os_mesg_handler_t msg_handler) +{ + os_mesg_t *mesg = NULL; + void *msg; + + spin_lock(&(queue->lock)); +#ifndef USE_SOFTINTR + OS_CANCEL_TIMER(&queue->_timer); +#endif + mesg = STAILQ_FIRST(&queue->mesg_head); + while(mesg) { + STAILQ_REMOVE_HEAD(&queue->mesg_head, mesg_next); + queue->num_queued--; + if (msg_handler != NULL) { + if (mesg->mesg_len) { + msg = (void *) (mesg+1); + } else { + msg = NULL; + } + msg_handler(queue->ctx, mesg->mesg_type, mesg->mesg_len, msg); + } + STAILQ_INSERT_TAIL(&queue->mesg_free_head,mesg, mesg_next); + mesg = STAILQ_FIRST(&queue->mesg_head); + }; + STAILQ_INIT(&queue->mesg_head); + spin_unlock(&(queue->lock)); +} + + +/* + * destroy the message queue. + * queue : message queue. + * reclaim all the resorces. + */ + +static INLINE void OS_MESGQ_DESTROY(os_mesg_queue_t *queue) +{ + spin_lock(&(queue->lock)); +#ifdef USE_SOFTINTR + softintr_disestablish(queue->_task); +#else + OS_CANCEL_TIMER(&queue->_timer); +#endif + queue->num_queued = 0; + STAILQ_INIT(&queue->mesg_head); + STAILQ_INIT(&queue->mesg_free_head); + adf_os_mem_free(queue->mesg_queue_buf); +#ifndef USE_SOFTINTR + OS_FREE_TIMER(&queue->_timer); +#endif + spin_unlock(&(queue->lock)); + spin_lock_destroy(&(queue->lock)); + spin_lock_destroy(&(queue->ev_handler_lock)); +} + + + +/* + * temp WAR for windows hang (dead lock). It can be removed when VAP SM is re-written (bug 65137). + */ +static INLINE int +OS_SCHEDULE_ROUTING(osdev_t pNicDev, + os_tasklet_routine_t routine, + void* context) +{ +#if OS_SUPPORT_ASYNC_Q + os_schedule_routing_mesg s_mesg ; + s_mesg.routine = routine; + s_mesg.context = context; + OS_MESGQ_SEND(&pNicDev->async_q,OS_SCHEDULE_ROUTING_MESG_TYPE, sizeof(os_schedule_routing_mesg), &s_mesg); + +#else + routine(context, NULL); +#endif + return 0; +} + +static INLINE void +OS_FREE_ROUTING(void* workItemHandle) +{ +} + +/* +** These are required for network manager support +*/ + +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(ndev, pdev) +#endif + +#ifdef to_net_dev +#define ATH_GET_NETDEV_DEV(ndev) ((ndev)->dev.parent) +#else +#define ATH_GET_NETDEV_DEV(ndev) ((ndev)->class_dev.dev) +#endif + + + +/* + * Opaque S/G List Entry + */ +typedef struct scatterlist sg_t; + +#include "hwdef.h" + +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#define MIN(a, b) adf_os_min(a, b) +#define MAX(a, b) adf_os_max(a, b) + +/* + * PCI configuration space access + */ +#ifdef ATH_PCI + +static INLINE u_int32_t +OS_PCI_READ_CONFIG(osdev_t osdev, u_int32_t offset, void *p, u_int32_t bytes) +{ + struct pci_dev *pdev = (struct pci_dev *)osdev->bdev; + + switch (bytes) { + case 1: + pci_read_config_byte(pdev, offset, p); + break; + case 2: + pci_read_config_word(pdev, offset, p); + break; + case 4: + pci_read_config_dword(pdev, offset, p); + break; + } + return bytes; +} + +static INLINE void +OS_PCI_WRITE_CONFIG(osdev_t osdev, u_int32_t offset, void *p, u_int32_t bytes) +{ + struct pci_dev *pdev = (struct pci_dev *)osdev->bdev; + + switch (bytes) { + case 1: + pci_write_config_byte(pdev, offset, *(u_int8_t *)p); + break; + case 2: + pci_write_config_word(pdev, offset, *(u_int16_t *)p); + break; + case 4: + pci_write_config_dword(pdev, offset, *(u_int32_t *)p); + break; + } +} + +#else + +static INLINE u_int32_t +OS_PCI_READ_CONFIG(osdev_t osdev, u_int32_t offset, void *p, u_int32_t bytes) +{ + OS_MEMSET(p, 0xff, bytes); + return 0; +} + +#define OS_PCI_WRITE_CONFIG(_osdev, _offset, _p, _bytes) + +#endif + +void *OS_ALLOC_VAP(osdev_t dev, u_int32_t len); +void OS_FREE_VAP(void *netif); + +// ALLOC_DMA_MAP_CONTEXT_AREA is a NULL macro and is implemented only for BSD. +#define ALLOC_DMA_MAP_CONTEXT_AREA(os_handle, p_memctx) +#define FREE_DMA_CONTEXT_POOL(os_handle, name) +#define ALLOC_DMA_CONTEXT_POOL(os_handle, name, numdesc) + +#define ATH_QOSNULL_TXDESC 64 +#define ATH_FRAG_PER_MSDU 1 +#ifndef ATH_TXBUF +#define ATH_TXBUF 512/ATH_FRAG_PER_MSDU +#endif + +/* + * minimum h/w qdepth to be sustained to maximize aggregation + */ +#define ATH_AGGR_MIN_QDEPTH 2 +#define OS_MAX_RXBUF_SIZE(_statuslen) (IEEE80211_MAX_MPDU_LEN + _statuslen) + +#define ATH_GET_RX_CONTEXT_BUF(_wbuf) \ + (ATH_RX_CONTEXT(_wbuf)->ctx_rxbuf) +#define ATH_SET_RX_CONTEXT_BUF(_wbuf, _bf) \ + (ATH_GET_RX_CONTEXT_BUF(_wbuf) = _bf) + +// This macro is used to avoid another wrapper around ath_rxbuf_alloc. +// For Mac OS, we need to OR in ATH_RXBUF_ALLOC_DONTWAIT with length. +// Not needed for other OS'. +#define ATH_ALLOCATE_RXBUFFER(_sc, _len) ath_rxbuf_alloc(_sc, _len) + +#ifndef OS_EXPORT_SYMBOL +#define OS_EXPORT_SYMBOL(_sym) EXPORT_SYMBOL(_sym) +#endif + +struct ieee80211_node; +struct ieee80211_cb { + u_int8_t vlan[8]; /* reserve for vlan tag info */ + struct ieee80211_node *ni; + u_int32_t flags; +#define N_LINK0 0x01 /* frame needs WEP encryption */ +#define N_FF 0x02 /* fast frame */ +#define N_PWR_SAV 0x04 /* bypass power save handling */ +#define N_UAPSD 0x08 /* frame flagged for u-apsd handling */ +#define N_EAPOL 0x10 /* frame flagged for EAPOL handling */ +#define N_AMSDU 0x20 /* frame flagged for AMSDU handling */ +#define N_NULL_PWR_SAV 0x40 /* null data with power save bit on */ +#define N_PROBING 0x80 /* frame flagged as a probing one */ +#define N_ERROR 0x100 /* frame flagged as a error one */ +#define N_MOREDATA 0x200 /* more data flag */ +#define N_SMPSACTM 0x400 /* This frame is SM power save Action Mgmt frame */ +#define N_QOS 0x800 /* This is a QOS frame*/ +#define N_ENCAP_DONE 0x1000 /* This frame is marked as fast-path pkts, some encapsulation work has been done by h/w */ +#define N_CLONED 0x2000 /* frame is cloned in rx path */ +#define N_ANT_TRAIN 0x8000 /* frame is smart antenna training packet */ +#define N_ANT_TRAIN_LAST 0x20000 /* Last smart antenna training packet */ +#ifdef ATH_SUPPORT_WAPI +#define N_WAI 0x40000 /* frame flagged for WAPI handling */ +#endif +#define N_FMSS 0x100000 /* frame needs FMS handling */ + + u_int8_t u_tid; /* user priority from vlan/ip tos */ + u_int8_t exemptiontype; /* exemption type of this frame (0,1,2)*/ + u_int8_t type; /* type of this frame */ + + union { + void *context; /* pointer to context area */ + }_u; + +#if defined(ATH_SUPPORT_P2P) || defined(ATH_SUPPORT_TDLS) + void *complete_handler; /* complete handler */ + void *complete_handler_arg; /* complete handler arg */ +#endif +}; +//#endif /* CONVERGED_SW */ + +#ifndef ATH_SUPPORT_HTC +/* + * For packet capture, define the same physical layer packet header + * structure as used in the wlan-ng driver + */ +typedef struct { + u_int32_t did; + u_int16_t status; + u_int16_t len; + u_int32_t data; +} p80211item_uint32_t; + +typedef struct { + u_int32_t msgcode; + u_int32_t msglen; +#define WLAN_DEVNAMELEN_MAX 16 + u_int8_t devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t hosttime; + p80211item_uint32_t mactime; + p80211item_uint32_t channel; + p80211item_uint32_t rssi; + p80211item_uint32_t sq; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_uint32_t rate; + p80211item_uint32_t istx; + p80211item_uint32_t frmlen; +} wlan_ng_prism2_header; + +#endif + +#define N_FLAG_SET(_nbf, _flag) \ + (((struct ieee80211_cb *)(_nbf)->cb)->flags |= (_flag)) +#define N_FLAG_CLR(_nbf, _flag) \ + (((struct ieee80211_cb *)(_nbf)->cb)->flags &= ~(_flag)) +#define N_FLAG_GET(_nbf, _flag) \ + (((struct ieee80211_cb *)(_nbf)->cb)->flags & (_flag)) +#define N_FLAG_IS(_nbf, _flag) \ + ((((struct ieee80211_cb *)(_nbf)->cb)->flags & (_flag)) == (_flag)) +#define N_FLAG_KEEP_ONLY(_nbf, _flag) \ + (((struct ieee80211_cb *)(_nbf)->cb)->flags &= (_flag)) + +#define N_PWR_SAV_SET(nbf) N_FLAG_SET((nbf), N_PWR_SAV) +#define N_PWR_SAV_CLR(nbf) N_FLAG_CLR((nbf), N_PWR_SAV) +#define N_PWR_SAV_GET(nbf) N_FLAG_GET((nbf), N_PWR_SAV) +#define N_PWR_SAV_IS(nbf) N_FLAG_IS((nbf), N_PWR_SAV) + +#define N_NULL_PWR_SAV_SET(nbf) N_FLAG_SET((nbf), N_NULL_PWR_SAV) +#define N_NULL_PWR_SAV_CLR(nbf) N_FLAG_CLR((nbf), N_NULL_PWR_SAV) +#define N_NULL_PWR_SAV_GET(nbf) N_FLAG_GET((nbf), N_NULL_PWR_SAV) +#define N_NULL_PWR_SAV_IS(nbf) N_FLAG_IS((nbf), N_NULL_PWR_SAV) + +#define N_PROBING_SET(nbf) N_FLAG_SET((nbf), N_PROBING) +#define N_PROBING_CLR(nbf) N_FLAG_CLR((nbf), N_PROBING) +#define N_PROBING_GET(nbf) N_FLAG_GET((nbf), N_PROBING) +#define N_PROBING_IS(nbf) N_FLAG_IS((nbf), N_PROBING) + +#define N_CLONED_SET(nbf) N_FLAG_SET((nbf), N_CLONED) +#define N_CLONED_CLR(nbf) N_FLAG_CLR((nbf), N_CLONED) +#define N_CLONED_GET(nbf) N_FLAG_GET((nbf), N_CLONED) +#define N_CLONED_IS(nbf) N_FLAG_IS((nbf), N_CLONED) + +#define N_MOREDATA_SET(nbf) N_FLAG_SET((nbf), N_MOREDATA) +#define N_MOREDATA_CLR(nbf) N_FLAG_CLR((nbf), N_MOREDATA) +#define N_MOREDATA_GET(nbf) N_FLAG_GET((nbf), N_MOREDATA) +#define N_MOREDATA_IS(nbf) N_FLAG_IS((nbf), N_MOREDATA) + +#define N_SMPSACTM_SET(nbf) N_FLAG_SET((nbf), N_SMPSACTM) +#define N_SMPSACTM_CLR(nbf) N_FLAG_CLR((nbf), N_SMPSACTM) +#define N_SMPSACTM_GET(nbf) N_FLAG_GET((nbf), N_SMPSACTM) +#define N_SMPSACTM_IS(nbf) N_FLAG_IS((nbf), N_SMPSACTM) + +#define N_QOS_SET(nbf) N_FLAG_SET((nbf), N_QOS) +#define N_QOS_CLR(nbf) N_FLAG_CLR((nbf), N_QOS) +#define N_QOS_GET(nbf) N_FLAG_GET((nbf), N_QOS) +#define N_QOS_IS(nbf) N_FLAG_IS((nbf), N_QOS) + +#define N_EAPOL_SET(nbf) N_FLAG_SET((nbf), N_EAPOL) +#define N_EAPOL_IS(nbf) N_FLAG_IS((nbf), N_EAPOL) + +#define N_AMSDU_SET(nbf) N_FLAG_SET((nbf), N_AMSDU) +#define N_AMSDU_IS(nbf) N_FLAG_IS((nbf), N_AMSDU) + +#define N_FF_SET(nbf) N_FLAG_SET((nbf), N_FF) +#define N_FF_IS(nbf) N_FLAG_IS((nbf), N_FF) + +#define N_UAPSD_SET(nbf) N_FLAG_SET((nbf), N_UAPSD) +#define N_UAPSD_CLR(nbf) N_FLAG_CLR((nbf), N_UAPSD) +#define N_UAPSD_IS(nbf) N_FLAG_IS((nbf), N_UAPSD) + +#define N_ENCAP_DONE_IS(nbf) N_FLAG_IS((nbf), N_ENCAP_DONE) +#define N_ENCAP_DONE_SET(nbf) N_FLAG_SET((nbf), N_ENCAP_DONE) +#define N_ENCAP_DONE_CLR(nbf) N_FLAG_CLR((nbf), N_ENCAP_DONE) + +#define N_STATUS_SET(nbf, _status) + +#define N_STATUS_GET(nbf) \ + if(N_FLAG_IS((nbf), N_ERROR)) \ + return WB_STATUS_TX_ERROR; \ + else \ + return WB_STATUS_OK; + +#define N_CONTEXT_SET(_nbf, _context) \ + (((struct ieee80211_cb *)(_nbf)->cb)->_u.context = (_context)) +#define N_CONTEXT_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->_u.context) + +#define N_TYPE_SET(_nbf, _type) \ + (((struct ieee80211_cb *)(_nbf)->cb)->type = (_type)) +#define N_TYPE_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->type) + +#define N_NODE_SET(_nbf, _ni) \ + (((struct ieee80211_cb *)(_nbf)->cb)->ni = (_ni)) +#define N_NODE_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->ni) + +#define N_COMPLETE_HANDLER_SET(_nbf, _handler) \ + (((struct ieee80211_cb *)(_nbf)->cb)->complete_handler = (_handler)) +#define N_COMPLETE_HANDLER_ARG_SET(_nbf, _arg) \ + (((struct ieee80211_cb *)(_nbf)->cb)->complete_handler_arg = (_arg)) + +#define N_COMPLETE_HANDLER_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->complete_handler) +#define N_COMPLETE_HANDLER_ARG_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->complete_handler_arg) + +#define N_EXMTYPE_SET(_nbf, _type) \ + (((struct ieee80211_cb *)(_nbf)->cb)->exemptiontype = (_type)) +#define N_EXMTYPE_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->exemptiontype) + +#define N_TID_SET(_nbf, _tid) \ + (((struct ieee80211_cb *)(_nbf)->cb)->u_tid = (_tid)) +#define N_TID_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->u_tid) + +#define N_ANT_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->smart_antenna) +#define N_RATE_INDEX_GET(_nbf) \ + (((struct ieee80211_cb *)(_nbf)->cb)->rateIndex) +#define N_TRAIN_PKT_IS(nbf) N_FLAG_IS((nbf), N_ANT_TRAIN) +#define N_TRAIN_LASTPKT_IS(nbf) N_FLAG_IS((nbf), N_ANT_TRAIN_LAST) + +#define N_ANT_SET(_nbf, _antenna) \ + (((struct ieee80211_cb *)(_nbf)->cb)->smart_antenna = (_antenna)) +#define N_RATE_INDEX_SET(_nbf, _idx) \ + (((struct ieee80211_cb *)(_nbf)->cb)->rateIndex = (_idx)) +#define N_TRAIN_PKT_SET(nbf) N_FLAG_SET((nbf), N_ANT_TRAIN) +#define N_TRAIN_PKT_UNSET(nbf) N_FLAG_CLR((nbf), N_ANT_TRAIN) +#define N_TRAIN_LASTPKT_SET(nbf) N_FLAG_SET((nbf), N_ANT_TRAIN_LAST) + +/* + * nbufs on the power save queue are tagged with an age and + * timed out. We reuse the hardware checksum field in the + * nbuf packet header to store this data. + * XXX use private cb area + */ +#define N_AGE_SET(skb, v) (skb)->csum = (v) +#define N_AGE_GET(skb) (skb)->csum +#define N_AGE_SUB(skb, adj) (skb)->csum -= (adj) + + +#endif /* end of _ATH_LINUX_OSDEP_ADF_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog.h new file mode 100644 index 000000000000..5619593775fc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _PKTLOG_ +#define _PKTLOG_ +#ifndef REMOVE_PKT_LOG + +/** + * @typedef ol_pktlog_dev_handle + * @brief opaque handle for pktlog device object + */ +struct ol_pktlog_dev_t; +typedef struct ol_pktlog_dev_t* ol_pktlog_dev_handle; +#endif /* #ifndef REMOVE_PKT_LOG */ +#endif /* _PKTLOG_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog_ac_fmt.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog_ac_fmt.h new file mode 100644 index 000000000000..622ce4175120 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/pktlog_ac_fmt.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2012-2013, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef REMOVE_PKT_LOG +#ifndef _PKTLOG_FMT_H_ +#define _PKTLOG_FMT_H_ + +#define CUR_PKTLOG_VER 10010 /* Packet log version */ +#define PKTLOG_MAGIC_NUM 7735225 + +#ifndef MAX_TX_RATE_TBL +#define MAX_TX_RATE_TBL 72 +#endif + +#ifdef __linux__ +#define PKTLOG_PROC_DIR "ath_pktlog" +#define PKTLOG_PROC_SYSTEM "system" +#define WLANDEV_BASENAME "cld" +#endif + +#ifdef WIN32 +#pragma pack(push, pktlog_fmt, 1) +#define __ATTRIB_PACK +#elif defined(__EFI__) +#define __ATTRIB_PACK +#else +#ifndef __ATTRIB_PACK +#define __ATTRIB_PACK __attribute__ ((packed)) +#endif +#endif +#include +/* + * Each packet log entry consists of the following fixed length header + * followed by variable length log information determined by log_type + */ + +struct ath_pktlog_hdr { + u_int16_t flags; + u_int16_t missed_cnt; + u_int16_t log_type; + u_int16_t size; + u_int32_t timestamp; +}__ATTRIB_PACK; + +#define ATH_PKTLOG_HDR_FLAGS_MASK 0xffff +#define ATH_PKTLOG_HDR_FLAGS_SHIFT 0 +#define ATH_PKTLOG_HDR_FLAGS_OFFSET 0 +#define ATH_PKTLOG_HDR_MISSED_CNT_MASK 0xffff0000 +#define ATH_PKTLOG_HDR_MISSED_CNT_SHIFT 16 +#define ATH_PKTLOG_HDR_MISSED_CNT_OFFSET 0 +#define ATH_PKTLOG_HDR_LOG_TYPE_MASK 0xffff +#define ATH_PKTLOG_HDR_LOG_TYPE_SHIFT 0 +#define ATH_PKTLOG_HDR_LOG_TYPE_OFFSET 1 +#define ATH_PKTLOG_HDR_SIZE_MASK 0xffff0000 +#define ATH_PKTLOG_HDR_SIZE_SHIFT 16 +#define ATH_PKTLOG_HDR_SIZE_OFFSET 1 +#define ATH_PKTLOG_HDR_TIMESTAMP_OFFSET 2 + +enum { + PKTLOG_FLG_FRM_TYPE_LOCAL_S = 0, + PKTLOG_FLG_FRM_TYPE_REMOTE_S, + PKTLOG_FLG_FRM_TYPE_UNKNOWN_S +}; + +/**************************** + * Pktlog flag field details + * packet origin [1:0] + * 00 - Local + * 01 - Remote + * 10 - Unknown/Not applicable + * 11 - Reserved + * reserved [15:2] + * *************************/ + +#define PHFLAGS_PROTO_MASK 0x0000f000 +#define PHFLAGS_PROTO_SFT 12 +#define PHFLAGS_MACVERSION_MASK 0x0fff0000 +#define PHFLAGS_MACVERSION_SFT 16 +/* + * XXX: This need not be part of packetlog header flags - Should be + * moved to plinfo + */ + +#define PHFLAGS_INTERRUPT_CONTEXT 0x80000000 + +/* flags in pktlog header */ +#define PHFLAGS_MISCCNT_MASK 0x000F /* Indicates no. of misc log parameters + (32-bit integers) at the end of a + log entry */ + +#define PHFLAGS_MACREV_MASK 0xff0 /* MAC revision */ +#define PHFLAGS_MACREV_SFT 4 + +/* Types of protocol logging flags */ +//#define PHFLAGS_PROTO_MASK 0xf000 +//#define PHFLAGS_PROTO_SFT 12 +#define PKTLOG_PROTO_NONE 0 +#define PKTLOG_PROTO_UDP 1 +#define PKTLOG_PROTO_TCP 2 + +/* Masks for setting pktlog events filters */ +#define ATH_PKTLOG_TX 0x000000001 +#define ATH_PKTLOG_RX 0x000000002 +#define ATH_PKTLOG_RCFIND 0x000000004 +#define ATH_PKTLOG_RCUPDATE 0x000000008 +#define ATH_PKTLOG_ANI 0x000000010 +#define ATH_PKTLOG_TEXT 0x000000020 +#define ATH_PKTLOG_PHYERR 0x000000040 +#define ATH_PKTLOG_PROMISC 0x000000080 + +/* Masks for setting pktlog info filters */ +#define ATH_PKTLOG_PROTO 0x00000001 /* Decode and log protocol headers */ +#define ATH_PKTLOG_TRIGGER_SACK 0x00000002 /* Triggered stop as seeing TCP SACK packets */ +#define ATH_PKTLOG_TRIGGER_THRUPUT 0x00000004 /* Triggered stop as throughput drops below a threshold */ +#define ATH_PKTLOG_TRIGGER_PER 0x00000008 /* Triggered stop as PER goes above a threshold */ +#define ATH_PKTLOG_TRIGGER_PHYERR 0x00000010 /* Triggered stop as # of phyerrs goes above a threshold */ + +/* Types of packet log events */ +#define PKTLOG_TYPE_TX_CTRL 1 +#define PKTLOG_TYPE_TX_STAT 2 +#define PKTLOG_TYPE_TX_MSDU_ID 3 +#define PKTLOG_TYPE_TX_FRM_HDR 4 +#define PKTLOG_TYPE_RX_STAT 5 +#define PKTLOG_TYPE_RC_FIND 6 +#define PKTLOG_TYPE_RC_UPDATE 7 +#define PKTLOG_TYPE_TX_VIRT_ADDR 8 +#define PKTLOG_TYPE_MAX 9 + +/*#define PKTLOG_TYPE_TXCTL 0 +#define PKTLOG_TYPE_TXSTATUS 1 +#define PKTLOG_TYPE_RX 2 +#define PKTLOG_TYPE_RCFIND 3 +#define PKTLOG_TYPE_RCUPDATE 4 +#define PKTLOG_TYPE_ANI 5 +#define PKTLOG_TYPE_TEXT 6*/ + +#define PKTLOG_MAX_TXCTL_WORDS 57 /* +2 words for bitmap */ +#define PKTLOG_MAX_TXSTATUS_WORDS 32 +#define PKTLOG_MAX_PROTO_WORDS 16 +#define PKTLOG_MAX_RXDESC_WORDS 62 + +struct txctl_frm_hdr { + u_int16_t framectrl; /* frame control field from header */ + u_int16_t seqctrl; /* frame control field from header */ + u_int16_t bssid_tail; /* last two octets of bssid */ + u_int16_t sa_tail; /* last two octets of SA */ + u_int16_t da_tail; /* last two octets of DA */ + u_int16_t resvd; +}; + +/* Peregrine 11ac based */ +#define MAX_PKT_INFO_MSDU_ID 192 +/* + * msdu_id_info_t is defined for reference only + */ +typedef struct { + A_UINT32 num_msdu; + A_UINT8 bound_bmap[MAX_PKT_INFO_MSDU_ID>>3]; + /* TODO: + * Convert the id's to uint32_t + * Reduces computation in the driver code + */ + A_UINT16 id[MAX_PKT_INFO_MSDU_ID]; +}__ATTRIB_PACK msdu_id_info_t; +#define MSDU_ID_INFO_NUM_MSDU_OFFSET 0 /* char offset */ +#define MSDU_ID_INFO_BOUND_BM_OFFSET 4 +#define MSDU_ID_INFO_ID_OFFSET \ + ((MAX_PKT_INFO_MSDU_ID >> 3) + 4) + +struct ath_pktlog_txctl { + struct ath_pktlog_hdr pl_hdr; + //struct txctl_frm_hdr frm_hdr; + void *txdesc_hdr_ctl; /* frm_hdr + Tx descriptor words */ + struct { + struct txctl_frm_hdr frm_hdr; + u_int32_t txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS]; + //u_int32_t *proto_hdr; /* protocol header (variable length!) */ + //u_int32_t *misc; /* Can be used for HT specific or other misc info */ + } priv; +} __ATTRIB_PACK; + +struct ath_pktlog_tx_status { + struct ath_pktlog_hdr pl_hdr; + void *ds_status; + int32_t misc[0]; /* Can be used for HT specific or other misc info */ +}__ATTRIB_PACK; + +struct ath_pktlog_msdu_info { + struct ath_pktlog_hdr pl_hdr; + void *ath_msdu_info; + A_UINT32 num_msdu; + struct { + /* + * Provision to add more information fields + */ + struct msdu_info_t { + A_UINT32 num_msdu; + A_UINT8 bound_bmap[MAX_PKT_INFO_MSDU_ID>>3]; + } msdu_id_info; + /* + * array of num_msdu + * Static implementation will consume unwanted memory + * Need to split the pktlog_get_buf to get the buffer pointer only + */ + uint16_t msdu_len[MAX_PKT_INFO_MSDU_ID]; + } priv; + size_t priv_size; + +}__ATTRIB_PACK; + +struct ath_pktlog_rx_info { + struct ath_pktlog_hdr pl_hdr; + void *rx_desc; +}__ATTRIB_PACK; + +struct ath_pktlog_rc_find { + struct ath_pktlog_hdr pl_hdr; + void *rcFind; +}__ATTRIB_PACK; + +struct ath_pktlog_rc_update { + struct ath_pktlog_hdr pl_hdr; + void *txRateCtrl;/* rate control state proper */ +}__ATTRIB_PACK; + +#define PKTLOG_MAX_RXSTATUS_WORDS 11 + +struct ath_pktlog_ani { + u_int8_t phyStatsDisable; + u_int8_t noiseImmunLvl; + u_int8_t spurImmunLvl; + u_int8_t ofdmWeakDet; + u_int8_t cckWeakThr; + int8_t rssi; + u_int16_t firLvl; + u_int16_t listenTime; + u_int16_t resvd; + u_int32_t cycleCount; + u_int32_t ofdmPhyErrCount; + u_int32_t cckPhyErrCount; + int32_t misc[0]; /* Can be used for HT specific or other misc info */ +} __ATTRIB_PACK; + + +struct ath_pktlog_rcfind { + u_int8_t rate; + u_int8_t rateCode; + int8_t rcRssiLast; + int8_t rcRssiLastPrev; + int8_t rcRssiLastPrev2; + int8_t rssiReduce; + u_int8_t rcProbeRate; + int8_t isProbing; + int8_t primeInUse; + int8_t currentPrimeState; + u_int8_t rcRateTableSize; + u_int8_t rcRateMax; + u_int8_t ac; + int32_t misc[0]; /* Can be used for HT specific or other misc info */ +} __ATTRIB_PACK; + + +struct ath_pktlog_rcupdate { + u_int8_t txRate; + u_int8_t rateCode; + int8_t rssiAck; + u_int8_t Xretries; + u_int8_t retries; + int8_t rcRssiLast; + int8_t rcRssiLastLkup; + int8_t rcRssiLastPrev; + int8_t rcRssiLastPrev2; + u_int8_t rcProbeRate; + u_int8_t rcRateMax; + int8_t useTurboPrime; + int8_t currentBoostState; + u_int8_t rcHwMaxRetryRate; + u_int8_t ac; + u_int8_t resvd[2]; + int8_t rcRssiThres[MAX_TX_RATE_TBL]; + u_int8_t rcPer[MAX_TX_RATE_TBL]; + u_int8_t rcMaxAggrSize[MAX_TX_RATE_TBL]; + u_int8_t headFail; /* rate control and aggregation variables ( part of ATH_SUPPORT_VOWEXT ) */ + u_int8_t tailFail; /* rate control and aggregation variables ( part of ATH_SUPPORT_VOWEXT ) */ + u_int8_t aggrSize; /* rate control and aggregation variables ( part of ATH_SUPPORT_VOWEXT ) */ + u_int8_t aggrLimit;/* rate control and aggregation variables ( part of ATH_SUPPORT_VOWEXT ) */ + u_int8_t lastRate; /* rate control and aggregation variables ( part of ATH_SUPPORT_VOWEXT ) */ + int32_t misc[0]; /* Can be used for HT specific or other misc info */ + /* TBD: Add any new parameters required */ +} __ATTRIB_PACK; + +#ifdef WIN32 +#pragma pack(pop, pktlog_fmt) +#endif +#ifdef __ATTRIB_PACK +#undef __ATTRIB_PACK +#endif /* __ATTRIB_PACK */ + +/* + * The following header is included in the beginning of the file, + * followed by log entries when the log buffer is read through procfs + */ + +struct ath_pktlog_bufhdr { + u_int32_t magic_num; /* Used by post processing scripts */ + u_int32_t version; /* Set to CUR_PKTLOG_VER */ +}; + +struct ath_pktlog_buf { + struct ath_pktlog_bufhdr bufhdr; + int32_t rd_offset; + volatile int32_t wr_offset; + /* Whenever this bytes written value croses 4K bytes, + * logging will be triggered + */ + int32_t bytes_written; + /* Index of the messages sent to userspace */ + uint32_t msg_index; + /* Offset for read */ + loff_t offset; + char log_data[0]; +}; + +#define PKTLOG_MOV_RD_IDX(_rd_offset, _log_buf, _log_size) \ + do { \ + if((_rd_offset + sizeof(struct ath_pktlog_hdr) + \ + ((struct ath_pktlog_hdr *)((_log_buf)->log_data + \ + (_rd_offset)))->size) <= _log_size) { \ + _rd_offset = ((_rd_offset) + sizeof(struct ath_pktlog_hdr) + \ + ((struct ath_pktlog_hdr *)((_log_buf)->log_data + \ + (_rd_offset)))->size); \ + } else { \ + _rd_offset = ((struct ath_pktlog_hdr *)((_log_buf)->log_data + \ + (_rd_offset)))->size; \ + } \ + (_rd_offset) = (((_log_size) - (_rd_offset)) >= \ + sizeof(struct ath_pktlog_hdr)) ? _rd_offset:0;\ + } while(0) + +#endif /* _PKTLOG_FMT_H_ */ +#endif /* REMOVE_PKT_LOG */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/queue.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/queue.h new file mode 100644 index 000000000000..5da9b068e9ce --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/queue.h @@ -0,0 +1,563 @@ +// +// Copyright (c) 1991, 1993 +// The Regents of the University of California. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. 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. +// 3. All advertising materials mentioning features or use of this software +// must display the following acknowledgement: +// This product includes software developed by the University of +// California, Berkeley and its contributors. +// 4. Neither the name of the University 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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. +// +// @(#)queue.h 8.5 (Berkeley) 8/20/94 +// $FreeBSD: src/sys/sys/queue.h,v 1.58 2004/04/07 04:19:49 imp Exp $ +// + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#define QUEUE_MACRO_DEBUG 0 +#if QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ + } \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#if !defined(FIELD_OFFSET) +#define FIELD_OFFSET(type, field) ((int)(int *)&(((struct type *)0)->field)) +#endif + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *) \ + ((char *)((head)->stqh_last) - FIELD_OFFSET(type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_CONCAT_ELEM(prevelm, elm, field) do { \ + prevelm->field.stqe_next = elm; \ +} while (0) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define ATH_LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !(__GNUC__ || __INTEL_COMPILER) */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __GNUC__ || __INTEL_COMPILER */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/rtc_soc_reg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/rtc_soc_reg.h new file mode 100644 index 000000000000..713aeb413bfe --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/rtc_soc_reg.h @@ -0,0 +1,1966 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _RTC_SOC_REG_REG_H_ +#define _RTC_SOC_REG_REG_H_ + +#define SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define SOC_RESET_CONTROL_OFFSET 0x00000000 +#define SOC_RESET_CONTROL_SPI2_RST_MSB 30 +#define SOC_RESET_CONTROL_SPI2_RST_LSB 30 +#define SOC_RESET_CONTROL_SPI2_RST_MASK 0x40000000 +#define SOC_RESET_CONTROL_SPI2_RST_GET(x) (((x) & SOC_RESET_CONTROL_SPI2_RST_MASK) >> SOC_RESET_CONTROL_SPI2_RST_LSB) +#define SOC_RESET_CONTROL_SPI2_RST_SET(x) (((x) << SOC_RESET_CONTROL_SPI2_RST_LSB) & SOC_RESET_CONTROL_SPI2_RST_MASK) +#define SOC_RESET_CONTROL_I2S_1_RST_MSB 29 +#define SOC_RESET_CONTROL_I2S_1_RST_LSB 29 +#define SOC_RESET_CONTROL_I2S_1_RST_MASK 0x20000000 +#define SOC_RESET_CONTROL_I2S_1_RST_GET(x) (((x) & SOC_RESET_CONTROL_I2S_1_RST_MASK) >> SOC_RESET_CONTROL_I2S_1_RST_LSB) +#define SOC_RESET_CONTROL_I2S_1_RST_SET(x) (((x) << SOC_RESET_CONTROL_I2S_1_RST_LSB) & SOC_RESET_CONTROL_I2S_1_RST_MASK) +#define SOC_RESET_CONTROL_I2S_1_MBOX_RST_MSB 28 +#define SOC_RESET_CONTROL_I2S_1_MBOX_RST_LSB 28 +#define SOC_RESET_CONTROL_I2S_1_MBOX_RST_MASK 0x10000000 +#define SOC_RESET_CONTROL_I2S_1_MBOX_RST_GET(x) (((x) & SOC_RESET_CONTROL_I2S_1_MBOX_RST_MASK) >> SOC_RESET_CONTROL_I2S_1_MBOX_RST_LSB) +#define SOC_RESET_CONTROL_I2S_1_MBOX_RST_SET(x) (((x) << SOC_RESET_CONTROL_I2S_1_MBOX_RST_LSB) & SOC_RESET_CONTROL_I2S_1_MBOX_RST_MASK) +#define SOC_RESET_CONTROL_I2C_SLAVE_RST_MSB 27 +#define SOC_RESET_CONTROL_I2C_SLAVE_RST_LSB 27 +#define SOC_RESET_CONTROL_I2C_SLAVE_RST_MASK 0x08000000 +#define SOC_RESET_CONTROL_I2C_SLAVE_RST_GET(x) (((x) & SOC_RESET_CONTROL_I2C_SLAVE_RST_MASK) >> SOC_RESET_CONTROL_I2C_SLAVE_RST_LSB) +#define SOC_RESET_CONTROL_I2C_SLAVE_RST_SET(x) (((x) << SOC_RESET_CONTROL_I2C_SLAVE_RST_LSB) & SOC_RESET_CONTROL_I2C_SLAVE_RST_MASK) +#define SOC_RESET_CONTROL_USB_PHY_ARST_MSB 26 +#define SOC_RESET_CONTROL_USB_PHY_ARST_LSB 26 +#define SOC_RESET_CONTROL_USB_PHY_ARST_MASK 0x04000000 +#define SOC_RESET_CONTROL_USB_PHY_ARST_GET(x) (((x) & SOC_RESET_CONTROL_USB_PHY_ARST_MASK) >> SOC_RESET_CONTROL_USB_PHY_ARST_LSB) +#define SOC_RESET_CONTROL_USB_PHY_ARST_SET(x) (((x) << SOC_RESET_CONTROL_USB_PHY_ARST_LSB) & SOC_RESET_CONTROL_USB_PHY_ARST_MASK) +#define SOC_RESET_CONTROL_USB_PHY_RST_MSB 25 +#define SOC_RESET_CONTROL_USB_PHY_RST_LSB 25 +#define SOC_RESET_CONTROL_USB_PHY_RST_MASK 0x02000000 +#define SOC_RESET_CONTROL_USB_PHY_RST_GET(x) (((x) & SOC_RESET_CONTROL_USB_PHY_RST_MASK) >> SOC_RESET_CONTROL_USB_PHY_RST_LSB) +#define SOC_RESET_CONTROL_USB_PHY_RST_SET(x) (((x) << SOC_RESET_CONTROL_USB_PHY_RST_LSB) & SOC_RESET_CONTROL_USB_PHY_RST_MASK) +#define SOC_RESET_CONTROL_USB_RST_MSB 24 +#define SOC_RESET_CONTROL_USB_RST_LSB 24 +#define SOC_RESET_CONTROL_USB_RST_MASK 0x01000000 +#define SOC_RESET_CONTROL_USB_RST_GET(x) (((x) & SOC_RESET_CONTROL_USB_RST_MASK) >> SOC_RESET_CONTROL_USB_RST_LSB) +#define SOC_RESET_CONTROL_USB_RST_SET(x) (((x) << SOC_RESET_CONTROL_USB_RST_LSB) & SOC_RESET_CONTROL_USB_RST_MASK) +#define SOC_RESET_CONTROL_MMAC_RST_MSB 23 +#define SOC_RESET_CONTROL_MMAC_RST_LSB 23 +#define SOC_RESET_CONTROL_MMAC_RST_MASK 0x00800000 +#define SOC_RESET_CONTROL_MMAC_RST_GET(x) (((x) & SOC_RESET_CONTROL_MMAC_RST_MASK) >> SOC_RESET_CONTROL_MMAC_RST_LSB) +#define SOC_RESET_CONTROL_MMAC_RST_SET(x) (((x) << SOC_RESET_CONTROL_MMAC_RST_LSB) & SOC_RESET_CONTROL_MMAC_RST_MASK) +#define SOC_RESET_CONTROL_MDIO_RST_MSB 22 +#define SOC_RESET_CONTROL_MDIO_RST_LSB 22 +#define SOC_RESET_CONTROL_MDIO_RST_MASK 0x00400000 +#define SOC_RESET_CONTROL_MDIO_RST_GET(x) (((x) & SOC_RESET_CONTROL_MDIO_RST_MASK) >> SOC_RESET_CONTROL_MDIO_RST_LSB) +#define SOC_RESET_CONTROL_MDIO_RST_SET(x) (((x) << SOC_RESET_CONTROL_MDIO_RST_LSB) & SOC_RESET_CONTROL_MDIO_RST_MASK) +#define SOC_RESET_CONTROL_GE0_RST_MSB 21 +#define SOC_RESET_CONTROL_GE0_RST_LSB 21 +#define SOC_RESET_CONTROL_GE0_RST_MASK 0x00200000 +#define SOC_RESET_CONTROL_GE0_RST_GET(x) (((x) & SOC_RESET_CONTROL_GE0_RST_MASK) >> SOC_RESET_CONTROL_GE0_RST_LSB) +#define SOC_RESET_CONTROL_GE0_RST_SET(x) (((x) << SOC_RESET_CONTROL_GE0_RST_LSB) & SOC_RESET_CONTROL_GE0_RST_MASK) +#define SOC_RESET_CONTROL_I2S_RST_MSB 20 +#define SOC_RESET_CONTROL_I2S_RST_LSB 20 +#define SOC_RESET_CONTROL_I2S_RST_MASK 0x00100000 +#define SOC_RESET_CONTROL_I2S_RST_GET(x) (((x) & SOC_RESET_CONTROL_I2S_RST_MASK) >> SOC_RESET_CONTROL_I2S_RST_LSB) +#define SOC_RESET_CONTROL_I2S_RST_SET(x) (((x) << SOC_RESET_CONTROL_I2S_RST_LSB) & SOC_RESET_CONTROL_I2S_RST_MASK) +#define SOC_RESET_CONTROL_I2S_MBOX_RST_MSB 19 +#define SOC_RESET_CONTROL_I2S_MBOX_RST_LSB 19 +#define SOC_RESET_CONTROL_I2S_MBOX_RST_MASK 0x00080000 +#define SOC_RESET_CONTROL_I2S_MBOX_RST_GET(x) (((x) & SOC_RESET_CONTROL_I2S_MBOX_RST_MASK) >> SOC_RESET_CONTROL_I2S_MBOX_RST_LSB) +#define SOC_RESET_CONTROL_I2S_MBOX_RST_SET(x) (((x) << SOC_RESET_CONTROL_I2S_MBOX_RST_LSB) & SOC_RESET_CONTROL_I2S_MBOX_RST_MASK) +/* TODO: */ +#define SOC_RESET_CONTROL_CHECKSUM_ACC_RST_MSB 18 +#define SOC_RESET_CONTROL_CHECKSUM_ACC_RST_LSB 18 +#define SOC_RESET_CONTROL_CHECKSUM_ACC_RST_MASK 0x00040000 +#define SOC_RESET_CONTROL_CHECKSUM_ACC_RST_GET(x) (((x) & SOC_RESET_CONTROL_CHECKSUM_ACC_RST_MASK) >> SOC_RESET_CONTROL_CHECKSUM_ACC_RST_LSB) +#define SOC_RESET_CONTROL_CHECKSUM_ACC_RST_SET(x) (((x) << SOC_RESET_CONTROL_CHECKSUM_ACC_RST_LSB) & SOC_RESET_CONTROL_CHECKSUM_ACC_RST_MASK) +#define SOC_RESET_CONTROL_CE_RST_MSB 18 +#define SOC_RESET_CONTROL_CE_RST_LSB 18 +#define SOC_RESET_CONTROL_CE_RST_MASK 0x00040000 +#define SOC_RESET_CONTROL_CE_RST_GET(x) (((x) & SOC_RESET_CONTROL_CE_RST_MASK) >> SOC_RESET_CONTROL_CE_RST_LSB) +#define SOC_RESET_CONTROL_CE_RST_SET(x) (((x) << SOC_RESET_CONTROL_CE_RST_LSB) & SOC_RESET_CONTROL_CE_RST_MASK) +#define SOC_RESET_CONTROL_UART2_RST_MSB 17 +#define SOC_RESET_CONTROL_UART2_RST_LSB 17 +#define SOC_RESET_CONTROL_UART2_RST_MASK 0x00020000 +#define SOC_RESET_CONTROL_UART2_RST_GET(x) (((x) & SOC_RESET_CONTROL_UART2_RST_MASK) >> SOC_RESET_CONTROL_UART2_RST_LSB) +#define SOC_RESET_CONTROL_UART2_RST_SET(x) (((x) << SOC_RESET_CONTROL_UART2_RST_LSB) & SOC_RESET_CONTROL_UART2_RST_MASK) +#define SOC_RESET_CONTROL_DEBUG_UART_RST_MSB 16 +#define SOC_RESET_CONTROL_DEBUG_UART_RST_LSB 16 +#define SOC_RESET_CONTROL_DEBUG_UART_RST_MASK 0x00010000 +#define SOC_RESET_CONTROL_DEBUG_UART_RST_GET(x) (((x) & SOC_RESET_CONTROL_DEBUG_UART_RST_MASK) >> SOC_RESET_CONTROL_DEBUG_UART_RST_LSB) +#define SOC_RESET_CONTROL_DEBUG_UART_RST_SET(x) (((x) << SOC_RESET_CONTROL_DEBUG_UART_RST_LSB) & SOC_RESET_CONTROL_DEBUG_UART_RST_MASK) +#define SOC_RESET_CONTROL_CPU_INIT_RESET_MSB 11 +#define SOC_RESET_CONTROL_CPU_INIT_RESET_LSB 11 +#define SOC_RESET_CONTROL_CPU_INIT_RESET_MASK 0x00000800 +#define SOC_RESET_CONTROL_CPU_INIT_RESET_GET(x) (((x) & SOC_RESET_CONTROL_CPU_INIT_RESET_MASK) >> SOC_RESET_CONTROL_CPU_INIT_RESET_LSB) +#define SOC_RESET_CONTROL_CPU_INIT_RESET_SET(x) (((x) << SOC_RESET_CONTROL_CPU_INIT_RESET_LSB) & SOC_RESET_CONTROL_CPU_INIT_RESET_MASK) +#define SOC_RESET_CONTROL_RST_OUT_MSB 9 +#define SOC_RESET_CONTROL_RST_OUT_LSB 9 +#define SOC_RESET_CONTROL_RST_OUT_MASK 0x00000200 +#define SOC_RESET_CONTROL_RST_OUT_GET(x) (((x) & SOC_RESET_CONTROL_RST_OUT_MASK) >> SOC_RESET_CONTROL_RST_OUT_LSB) +#define SOC_RESET_CONTROL_RST_OUT_SET(x) (((x) << SOC_RESET_CONTROL_RST_OUT_LSB) & SOC_RESET_CONTROL_RST_OUT_MASK) +#define SOC_RESET_CONTROL_COLD_RST_MSB 8 +#define SOC_RESET_CONTROL_COLD_RST_LSB 8 +#define SOC_RESET_CONTROL_COLD_RST_MASK 0x00000100 +#define SOC_RESET_CONTROL_COLD_RST_GET(x) (((x) & SOC_RESET_CONTROL_COLD_RST_MASK) >> SOC_RESET_CONTROL_COLD_RST_LSB) +#define SOC_RESET_CONTROL_COLD_RST_SET(x) (((x) << SOC_RESET_CONTROL_COLD_RST_LSB) & SOC_RESET_CONTROL_COLD_RST_MASK) +#define SOC_RESET_CONTROL_CPU_WARM_RST_MSB 6 +#define SOC_RESET_CONTROL_CPU_WARM_RST_LSB 6 +#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define SOC_RESET_CONTROL_CPU_WARM_RST_GET(x) (((x) & SOC_RESET_CONTROL_CPU_WARM_RST_MASK) >> SOC_RESET_CONTROL_CPU_WARM_RST_LSB) +#define SOC_RESET_CONTROL_CPU_WARM_RST_SET(x) (((x) << SOC_RESET_CONTROL_CPU_WARM_RST_LSB) & SOC_RESET_CONTROL_CPU_WARM_RST_MASK) +/* TODO: */ +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MSB 2 +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 2 +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000004 +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_GET(x) (((x) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) >> SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_SET(x) (((x) << SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) +#define SOC_RESET_CONTROL_MBOX_RST_MSB 2 +#define SOC_RESET_CONTROL_MBOX_RST_LSB 2 +#define SOC_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define SOC_RESET_CONTROL_MBOX_RST_GET(x) (((x) & SOC_RESET_CONTROL_MBOX_RST_MASK) >> SOC_RESET_CONTROL_MBOX_RST_LSB) +#define SOC_RESET_CONTROL_MBOX_RST_SET(x) (((x) << SOC_RESET_CONTROL_MBOX_RST_LSB) & SOC_RESET_CONTROL_MBOX_RST_MASK) +#define SOC_RESET_CONTROL_UART_RST_MSB 1 +#define SOC_RESET_CONTROL_UART_RST_LSB 1 +#define SOC_RESET_CONTROL_UART_RST_MASK 0x00000002 +#define SOC_RESET_CONTROL_UART_RST_GET(x) (((x) & SOC_RESET_CONTROL_UART_RST_MASK) >> SOC_RESET_CONTROL_UART_RST_LSB) +#define SOC_RESET_CONTROL_UART_RST_SET(x) (((x) << SOC_RESET_CONTROL_UART_RST_LSB) & SOC_RESET_CONTROL_UART_RST_MASK) +#define SOC_RESET_CONTROL_SI0_RST_MSB 0 +#define SOC_RESET_CONTROL_SI0_RST_LSB 0 +#define SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define SOC_RESET_CONTROL_SI0_RST_GET(x) (((x) & SOC_RESET_CONTROL_SI0_RST_MASK) >> SOC_RESET_CONTROL_SI0_RST_LSB) +#define SOC_RESET_CONTROL_SI0_RST_SET(x) (((x) << SOC_RESET_CONTROL_SI0_RST_LSB) & SOC_RESET_CONTROL_SI0_RST_MASK) + +#define SOC_TCXO_DETECT_ADDRESS 0x00000004 +#define SOC_TCXO_DETECT_OFFSET 0x00000004 +#define SOC_TCXO_DETECT_PRESENT_MSB 0 +#define SOC_TCXO_DETECT_PRESENT_LSB 0 +#define SOC_TCXO_DETECT_PRESENT_MASK 0x00000001 +#define SOC_TCXO_DETECT_PRESENT_GET(x) (((x) & SOC_TCXO_DETECT_PRESENT_MASK) >> SOC_TCXO_DETECT_PRESENT_LSB) +#define SOC_TCXO_DETECT_PRESENT_SET(x) (((x) << SOC_TCXO_DETECT_PRESENT_LSB) & SOC_TCXO_DETECT_PRESENT_MASK) + +#define SOC_XTAL_TEST_ADDRESS 0x00000008 +#define SOC_XTAL_TEST_OFFSET 0x00000008 +#define SOC_XTAL_TEST_NOTCXODET_MSB 0 +#define SOC_XTAL_TEST_NOTCXODET_LSB 0 +#define SOC_XTAL_TEST_NOTCXODET_MASK 0x00000001 +#define SOC_XTAL_TEST_NOTCXODET_GET(x) (((x) & SOC_XTAL_TEST_NOTCXODET_MASK) >> SOC_XTAL_TEST_NOTCXODET_LSB) +#define SOC_XTAL_TEST_NOTCXODET_SET(x) (((x) << SOC_XTAL_TEST_NOTCXODET_LSB) & SOC_XTAL_TEST_NOTCXODET_MASK) + +#define SOC_CPU_CLOCK_ADDRESS 0x00000020 +#define SOC_CPU_CLOCK_OFFSET 0x00000020 +#define SOC_CPU_CLOCK_STANDARD_MSB 1 +#define SOC_CPU_CLOCK_STANDARD_LSB 0 +#define SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define SOC_CPU_CLOCK_STANDARD_GET(x) (((x) & SOC_CPU_CLOCK_STANDARD_MASK) >> SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_SET(x) (((x) << SOC_CPU_CLOCK_STANDARD_LSB) & SOC_CPU_CLOCK_STANDARD_MASK) + +#define SOC_CLOCK_CONTROL_ADDRESS 0x00000028 +#define SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define SOC_CLOCK_CONTROL_USB_CLOCK_MSB 3 +#define SOC_CLOCK_CONTROL_USB_CLOCK_LSB 3 +#define SOC_CLOCK_CONTROL_USB_CLOCK_MASK 0x00000008 +#define SOC_CLOCK_CONTROL_USB_CLOCK_GET(x) (((x) & SOC_CLOCK_CONTROL_USB_CLOCK_MASK) >> SOC_CLOCK_CONTROL_USB_CLOCK_LSB) +#define SOC_CLOCK_CONTROL_USB_CLOCK_SET(x) (((x) << SOC_CLOCK_CONTROL_USB_CLOCK_LSB) & SOC_CLOCK_CONTROL_USB_CLOCK_MASK) +#define SOC_CLOCK_CONTROL_LF_CLK32_MSB 2 +#define SOC_CLOCK_CONTROL_LF_CLK32_LSB 2 +#define SOC_CLOCK_CONTROL_LF_CLK32_MASK 0x00000004 +#define SOC_CLOCK_CONTROL_LF_CLK32_GET(x) (((x) & SOC_CLOCK_CONTROL_LF_CLK32_MASK) >> SOC_CLOCK_CONTROL_LF_CLK32_LSB) +#define SOC_CLOCK_CONTROL_LF_CLK32_SET(x) (((x) << SOC_CLOCK_CONTROL_LF_CLK32_LSB) & SOC_CLOCK_CONTROL_LF_CLK32_MASK) +#define SOC_CLOCK_CONTROL_SI0_CLK_MSB 0 +#define SOC_CLOCK_CONTROL_SI0_CLK_LSB 0 +#define SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define SOC_CLOCK_CONTROL_SI0_CLK_GET(x) (((x) & SOC_CLOCK_CONTROL_SI0_CLK_MASK) >> SOC_CLOCK_CONTROL_SI0_CLK_LSB) +#define SOC_CLOCK_CONTROL_SI0_CLK_SET(x) (((x) << SOC_CLOCK_CONTROL_SI0_CLK_LSB) & SOC_CLOCK_CONTROL_SI0_CLK_MASK) + +#define SOC_WDT_CONTROL_ADDRESS 0x00000030 +#define SOC_WDT_CONTROL_OFFSET 0x00000030 +#define SOC_WDT_CONTROL_ACTION_MSB 2 +#define SOC_WDT_CONTROL_ACTION_LSB 0 +#define SOC_WDT_CONTROL_ACTION_MASK 0x00000007 +#define SOC_WDT_CONTROL_ACTION_GET(x) (((x) & SOC_WDT_CONTROL_ACTION_MASK) >> SOC_WDT_CONTROL_ACTION_LSB) +#define SOC_WDT_CONTROL_ACTION_SET(x) (((x) << SOC_WDT_CONTROL_ACTION_LSB) & SOC_WDT_CONTROL_ACTION_MASK) + +#define SOC_WDT_STATUS_ADDRESS 0x00000034 +#define SOC_WDT_STATUS_OFFSET 0x00000034 +#define SOC_WDT_STATUS_INTERRUPT_MSB 0 +#define SOC_WDT_STATUS_INTERRUPT_LSB 0 +#define SOC_WDT_STATUS_INTERRUPT_MASK 0x00000001 +#define SOC_WDT_STATUS_INTERRUPT_GET(x) (((x) & SOC_WDT_STATUS_INTERRUPT_MASK) >> SOC_WDT_STATUS_INTERRUPT_LSB) +#define SOC_WDT_STATUS_INTERRUPT_SET(x) (((x) << SOC_WDT_STATUS_INTERRUPT_LSB) & SOC_WDT_STATUS_INTERRUPT_MASK) + +#define SOC_WDT_ADDRESS 0x00000038 +#define SOC_WDT_OFFSET 0x00000038 +#define SOC_WDT_TARGET_MSB 21 +#define SOC_WDT_TARGET_LSB 0 +#define SOC_WDT_TARGET_MASK 0x003fffff +#define SOC_WDT_TARGET_GET(x) (((x) & SOC_WDT_TARGET_MASK) >> SOC_WDT_TARGET_LSB) +#define SOC_WDT_TARGET_SET(x) (((x) << SOC_WDT_TARGET_LSB) & SOC_WDT_TARGET_MASK) + +#define SOC_WDT_COUNT_ADDRESS 0x0000003c +#define SOC_WDT_COUNT_OFFSET 0x0000003c +#define SOC_WDT_COUNT_VALUE_MSB 21 +#define SOC_WDT_COUNT_VALUE_LSB 0 +#define SOC_WDT_COUNT_VALUE_MASK 0x003fffff +#define SOC_WDT_COUNT_VALUE_GET(x) (((x) & SOC_WDT_COUNT_VALUE_MASK) >> SOC_WDT_COUNT_VALUE_LSB) +#define SOC_WDT_COUNT_VALUE_SET(x) (((x) << SOC_WDT_COUNT_VALUE_LSB) & SOC_WDT_COUNT_VALUE_MASK) + +#define SOC_WDT_RESET_ADDRESS 0x00000040 +#define SOC_WDT_RESET_OFFSET 0x00000040 +#define SOC_WDT_RESET_VALUE_MSB 0 +#define SOC_WDT_RESET_VALUE_LSB 0 +#define SOC_WDT_RESET_VALUE_MASK 0x00000001 +#define SOC_WDT_RESET_VALUE_GET(x) (((x) & SOC_WDT_RESET_VALUE_MASK) >> SOC_WDT_RESET_VALUE_LSB) +#define SOC_WDT_RESET_VALUE_SET(x) (((x) << SOC_WDT_RESET_VALUE_LSB) & SOC_WDT_RESET_VALUE_MASK) + +#define SOC_INT_STATUS_ADDRESS 0x00000044 +#define SOC_INT_STATUS_OFFSET 0x00000044 +#define SOC_INT_STATUS_MAC_4_MSB 23 +#define SOC_INT_STATUS_MAC_4_LSB 23 +#define SOC_INT_STATUS_MAC_4_MASK 0x00800000 +#define SOC_INT_STATUS_MAC_4_GET(x) (((x) & SOC_INT_STATUS_MAC_4_MASK) >> SOC_INT_STATUS_MAC_4_LSB) +#define SOC_INT_STATUS_MAC_4_SET(x) (((x) << SOC_INT_STATUS_MAC_4_LSB) & SOC_INT_STATUS_MAC_4_MASK) +#define SOC_INT_STATUS_MAC_3_MSB 22 +#define SOC_INT_STATUS_MAC_3_LSB 22 +#define SOC_INT_STATUS_MAC_3_MASK 0x00400000 +#define SOC_INT_STATUS_MAC_3_GET(x) (((x) & SOC_INT_STATUS_MAC_3_MASK) >> SOC_INT_STATUS_MAC_3_LSB) +#define SOC_INT_STATUS_MAC_3_SET(x) (((x) << SOC_INT_STATUS_MAC_3_LSB) & SOC_INT_STATUS_MAC_3_MASK) +#define SOC_INT_STATUS_MAC_2_MSB 21 +#define SOC_INT_STATUS_MAC_2_LSB 21 +#define SOC_INT_STATUS_MAC_2_MASK 0x00200000 +#define SOC_INT_STATUS_MAC_2_GET(x) (((x) & SOC_INT_STATUS_MAC_2_MASK) >> SOC_INT_STATUS_MAC_2_LSB) +#define SOC_INT_STATUS_MAC_2_SET(x) (((x) << SOC_INT_STATUS_MAC_2_LSB) & SOC_INT_STATUS_MAC_2_MASK) +#define SOC_INT_STATUS_MAC_1_MSB 20 +#define SOC_INT_STATUS_MAC_1_LSB 20 +#define SOC_INT_STATUS_MAC_1_MASK 0x00100000 +#define SOC_INT_STATUS_MAC_1_GET(x) (((x) & SOC_INT_STATUS_MAC_1_MASK) >> SOC_INT_STATUS_MAC_1_LSB) +#define SOC_INT_STATUS_MAC_1_SET(x) (((x) << SOC_INT_STATUS_MAC_1_LSB) & SOC_INT_STATUS_MAC_1_MASK) +#define SOC_INT_STATUS_USBDMA_MSB 19 +#define SOC_INT_STATUS_USBDMA_LSB 19 +#define SOC_INT_STATUS_USBDMA_MASK 0x00080000 +#define SOC_INT_STATUS_USBDMA_GET(x) (((x) & SOC_INT_STATUS_USBDMA_MASK) >> SOC_INT_STATUS_USBDMA_LSB) +#define SOC_INT_STATUS_USBDMA_SET(x) (((x) << SOC_INT_STATUS_USBDMA_LSB) & SOC_INT_STATUS_USBDMA_MASK) +#define SOC_INT_STATUS_USBIP_MSB 18 +#define SOC_INT_STATUS_USBIP_LSB 18 +#define SOC_INT_STATUS_USBIP_MASK 0x00040000 +#define SOC_INT_STATUS_USBIP_GET(x) (((x) & SOC_INT_STATUS_USBIP_MASK) >> SOC_INT_STATUS_USBIP_LSB) +#define SOC_INT_STATUS_USBIP_SET(x) (((x) << SOC_INT_STATUS_USBIP_LSB) & SOC_INT_STATUS_USBIP_MASK) +#define SOC_INT_STATUS_THERM_MSB 17 +#define SOC_INT_STATUS_THERM_LSB 17 +#define SOC_INT_STATUS_THERM_MASK 0x00020000 +#define SOC_INT_STATUS_THERM_GET(x) (((x) & SOC_INT_STATUS_THERM_MASK) >> SOC_INT_STATUS_THERM_LSB) +#define SOC_INT_STATUS_THERM_SET(x) (((x) << SOC_INT_STATUS_THERM_LSB) & SOC_INT_STATUS_THERM_MASK) +#define SOC_INT_STATUS_EFUSE_OVERWRITE_MSB 16 +#define SOC_INT_STATUS_EFUSE_OVERWRITE_LSB 16 +#define SOC_INT_STATUS_EFUSE_OVERWRITE_MASK 0x00010000 +#define SOC_INT_STATUS_EFUSE_OVERWRITE_GET(x) (((x) & SOC_INT_STATUS_EFUSE_OVERWRITE_MASK) >> SOC_INT_STATUS_EFUSE_OVERWRITE_LSB) +#define SOC_INT_STATUS_EFUSE_OVERWRITE_SET(x) (((x) << SOC_INT_STATUS_EFUSE_OVERWRITE_LSB) & SOC_INT_STATUS_EFUSE_OVERWRITE_MASK) +#define SOC_INT_STATUS_RDMA_MSB 15 +#define SOC_INT_STATUS_RDMA_LSB 15 +#define SOC_INT_STATUS_RDMA_MASK 0x00008000 +#define SOC_INT_STATUS_RDMA_GET(x) (((x) & SOC_INT_STATUS_RDMA_MASK) >> SOC_INT_STATUS_RDMA_LSB) +#define SOC_INT_STATUS_RDMA_SET(x) (((x) << SOC_INT_STATUS_RDMA_LSB) & SOC_INT_STATUS_RDMA_MASK) +#define SOC_INT_STATUS_BTCOEX_MSB 14 +#define SOC_INT_STATUS_BTCOEX_LSB 14 +#define SOC_INT_STATUS_BTCOEX_MASK 0x00004000 +#define SOC_INT_STATUS_BTCOEX_GET(x) (((x) & SOC_INT_STATUS_BTCOEX_MASK) >> SOC_INT_STATUS_BTCOEX_LSB) +#define SOC_INT_STATUS_BTCOEX_SET(x) (((x) << SOC_INT_STATUS_BTCOEX_LSB) & SOC_INT_STATUS_BTCOEX_MASK) +#define SOC_INT_STATUS_RTC_POWER_MSB 13 +#define SOC_INT_STATUS_RTC_POWER_LSB 13 +#define SOC_INT_STATUS_RTC_POWER_MASK 0x00002000 +#define SOC_INT_STATUS_RTC_POWER_GET(x) (((x) & SOC_INT_STATUS_RTC_POWER_MASK) >> SOC_INT_STATUS_RTC_POWER_LSB) +#define SOC_INT_STATUS_RTC_POWER_SET(x) (((x) << SOC_INT_STATUS_RTC_POWER_LSB) & SOC_INT_STATUS_RTC_POWER_MASK) +#define SOC_INT_STATUS_MAC_MSB 12 +#define SOC_INT_STATUS_MAC_LSB 12 +#define SOC_INT_STATUS_MAC_MASK 0x00001000 +#define SOC_INT_STATUS_MAC_GET(x) (((x) & SOC_INT_STATUS_MAC_MASK) >> SOC_INT_STATUS_MAC_LSB) +#define SOC_INT_STATUS_MAC_SET(x) (((x) << SOC_INT_STATUS_MAC_LSB) & SOC_INT_STATUS_MAC_MASK) +#define SOC_INT_STATUS_MAILBOX_MSB 11 +#define SOC_INT_STATUS_MAILBOX_LSB 11 +#define SOC_INT_STATUS_MAILBOX_MASK 0x00000800 +#define SOC_INT_STATUS_MAILBOX_GET(x) (((x) & SOC_INT_STATUS_MAILBOX_MASK) >> SOC_INT_STATUS_MAILBOX_LSB) +#define SOC_INT_STATUS_MAILBOX_SET(x) (((x) << SOC_INT_STATUS_MAILBOX_LSB) & SOC_INT_STATUS_MAILBOX_MASK) +#define SOC_INT_STATUS_RTC_ALARM_MSB 10 +#define SOC_INT_STATUS_RTC_ALARM_LSB 10 +#define SOC_INT_STATUS_RTC_ALARM_MASK 0x00000400 +#define SOC_INT_STATUS_RTC_ALARM_GET(x) (((x) & SOC_INT_STATUS_RTC_ALARM_MASK) >> SOC_INT_STATUS_RTC_ALARM_LSB) +#define SOC_INT_STATUS_RTC_ALARM_SET(x) (((x) << SOC_INT_STATUS_RTC_ALARM_LSB) & SOC_INT_STATUS_RTC_ALARM_MASK) +#define SOC_INT_STATUS_HF_TIMER_MSB 9 +#define SOC_INT_STATUS_HF_TIMER_LSB 9 +#define SOC_INT_STATUS_HF_TIMER_MASK 0x00000200 +#define SOC_INT_STATUS_HF_TIMER_GET(x) (((x) & SOC_INT_STATUS_HF_TIMER_MASK) >> SOC_INT_STATUS_HF_TIMER_LSB) +#define SOC_INT_STATUS_HF_TIMER_SET(x) (((x) << SOC_INT_STATUS_HF_TIMER_LSB) & SOC_INT_STATUS_HF_TIMER_MASK) +#define SOC_INT_STATUS_LF_TIMER3_MSB 8 +#define SOC_INT_STATUS_LF_TIMER3_LSB 8 +#define SOC_INT_STATUS_LF_TIMER3_MASK 0x00000100 +#define SOC_INT_STATUS_LF_TIMER3_GET(x) (((x) & SOC_INT_STATUS_LF_TIMER3_MASK) >> SOC_INT_STATUS_LF_TIMER3_LSB) +#define SOC_INT_STATUS_LF_TIMER3_SET(x) (((x) << SOC_INT_STATUS_LF_TIMER3_LSB) & SOC_INT_STATUS_LF_TIMER3_MASK) +#define SOC_INT_STATUS_LF_TIMER2_MSB 7 +#define SOC_INT_STATUS_LF_TIMER2_LSB 7 +#define SOC_INT_STATUS_LF_TIMER2_MASK 0x00000080 +#define SOC_INT_STATUS_LF_TIMER2_GET(x) (((x) & SOC_INT_STATUS_LF_TIMER2_MASK) >> SOC_INT_STATUS_LF_TIMER2_LSB) +#define SOC_INT_STATUS_LF_TIMER2_SET(x) (((x) << SOC_INT_STATUS_LF_TIMER2_LSB) & SOC_INT_STATUS_LF_TIMER2_MASK) +#define SOC_INT_STATUS_LF_TIMER1_MSB 6 +#define SOC_INT_STATUS_LF_TIMER1_LSB 6 +#define SOC_INT_STATUS_LF_TIMER1_MASK 0x00000040 +#define SOC_INT_STATUS_LF_TIMER1_GET(x) (((x) & SOC_INT_STATUS_LF_TIMER1_MASK) >> SOC_INT_STATUS_LF_TIMER1_LSB) +#define SOC_INT_STATUS_LF_TIMER1_SET(x) (((x) << SOC_INT_STATUS_LF_TIMER1_LSB) & SOC_INT_STATUS_LF_TIMER1_MASK) +#define SOC_INT_STATUS_LF_TIMER0_MSB 5 +#define SOC_INT_STATUS_LF_TIMER0_LSB 5 +#define SOC_INT_STATUS_LF_TIMER0_MASK 0x00000020 +#define SOC_INT_STATUS_LF_TIMER0_GET(x) (((x) & SOC_INT_STATUS_LF_TIMER0_MASK) >> SOC_INT_STATUS_LF_TIMER0_LSB) +#define SOC_INT_STATUS_LF_TIMER0_SET(x) (((x) << SOC_INT_STATUS_LF_TIMER0_LSB) & SOC_INT_STATUS_LF_TIMER0_MASK) +#define SOC_INT_STATUS_SI_MSB 4 +#define SOC_INT_STATUS_SI_LSB 4 +#define SOC_INT_STATUS_SI_MASK 0x00000010 +#define SOC_INT_STATUS_SI_GET(x) (((x) & SOC_INT_STATUS_SI_MASK) >> SOC_INT_STATUS_SI_LSB) +#define SOC_INT_STATUS_SI_SET(x) (((x) << SOC_INT_STATUS_SI_LSB) & SOC_INT_STATUS_SI_MASK) +#define SOC_INT_STATUS_GPIO_MSB 3 +#define SOC_INT_STATUS_GPIO_LSB 3 +#define SOC_INT_STATUS_GPIO_MASK 0x00000008 +#define SOC_INT_STATUS_GPIO_GET(x) (((x) & SOC_INT_STATUS_GPIO_MASK) >> SOC_INT_STATUS_GPIO_LSB) +#define SOC_INT_STATUS_GPIO_SET(x) (((x) << SOC_INT_STATUS_GPIO_LSB) & SOC_INT_STATUS_GPIO_MASK) +#define SOC_INT_STATUS_DEBUG_UART_MSB 2 +#define SOC_INT_STATUS_DEBUG_UART_LSB 2 +#define SOC_INT_STATUS_DEBUG_UART_MASK 0x00000004 +#define SOC_INT_STATUS_DEBUG_UART_GET(x) (((x) & SOC_INT_STATUS_DEBUG_UART_MASK) >> SOC_INT_STATUS_DEBUG_UART_LSB) +#define SOC_INT_STATUS_DEBUG_UART_SET(x) (((x) << SOC_INT_STATUS_DEBUG_UART_LSB) & SOC_INT_STATUS_DEBUG_UART_MASK) +#define SOC_INT_STATUS_ERROR_MSB 1 +#define SOC_INT_STATUS_ERROR_LSB 1 +#define SOC_INT_STATUS_ERROR_MASK 0x00000002 +#define SOC_INT_STATUS_ERROR_GET(x) (((x) & SOC_INT_STATUS_ERROR_MASK) >> SOC_INT_STATUS_ERROR_LSB) +#define SOC_INT_STATUS_ERROR_SET(x) (((x) << SOC_INT_STATUS_ERROR_LSB) & SOC_INT_STATUS_ERROR_MASK) +#define SOC_INT_STATUS_WDT_INT_MSB 0 +#define SOC_INT_STATUS_WDT_INT_LSB 0 +#define SOC_INT_STATUS_WDT_INT_MASK 0x00000001 +#define SOC_INT_STATUS_WDT_INT_GET(x) (((x) & SOC_INT_STATUS_WDT_INT_MASK) >> SOC_INT_STATUS_WDT_INT_LSB) +#define SOC_INT_STATUS_WDT_INT_SET(x) (((x) << SOC_INT_STATUS_WDT_INT_LSB) & SOC_INT_STATUS_WDT_INT_MASK) + +#define SOC_LF_TIMER0_ADDRESS 0x00000048 +#define SOC_LF_TIMER0_OFFSET 0x00000048 +#define SOC_LF_TIMER0_TARGET_MSB 31 +#define SOC_LF_TIMER0_TARGET_LSB 0 +#define SOC_LF_TIMER0_TARGET_MASK 0xffffffff +#define SOC_LF_TIMER0_TARGET_GET(x) (((x) & SOC_LF_TIMER0_TARGET_MASK) >> SOC_LF_TIMER0_TARGET_LSB) +#define SOC_LF_TIMER0_TARGET_SET(x) (((x) << SOC_LF_TIMER0_TARGET_LSB) & SOC_LF_TIMER0_TARGET_MASK) + +#define SOC_LF_TIMER_COUNT0_ADDRESS 0x0000004c +#define SOC_LF_TIMER_COUNT0_OFFSET 0x0000004c +#define SOC_LF_TIMER_COUNT0_VALUE_MSB 31 +#define SOC_LF_TIMER_COUNT0_VALUE_LSB 0 +#define SOC_LF_TIMER_COUNT0_VALUE_MASK 0xffffffff +#define SOC_LF_TIMER_COUNT0_VALUE_GET(x) (((x) & SOC_LF_TIMER_COUNT0_VALUE_MASK) >> SOC_LF_TIMER_COUNT0_VALUE_LSB) +#define SOC_LF_TIMER_COUNT0_VALUE_SET(x) (((x) << SOC_LF_TIMER_COUNT0_VALUE_LSB) & SOC_LF_TIMER_COUNT0_VALUE_MASK) + +#define SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define SOC_LF_TIMER_CONTROL0_OFFSET 0x00000050 +#define SOC_LF_TIMER_CONTROL0_ENABLE_MSB 2 +#define SOC_LF_TIMER_CONTROL0_ENABLE_LSB 2 +#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define SOC_LF_TIMER_CONTROL0_ENABLE_GET(x) (((x) & SOC_LF_TIMER_CONTROL0_ENABLE_MASK) >> SOC_LF_TIMER_CONTROL0_ENABLE_LSB) +#define SOC_LF_TIMER_CONTROL0_ENABLE_SET(x) (((x) << SOC_LF_TIMER_CONTROL0_ENABLE_LSB) & SOC_LF_TIMER_CONTROL0_ENABLE_MASK) +#define SOC_LF_TIMER_CONTROL0_AUTO_RESTART_MSB 1 +#define SOC_LF_TIMER_CONTROL0_AUTO_RESTART_LSB 1 +#define SOC_LF_TIMER_CONTROL0_AUTO_RESTART_MASK 0x00000002 +#define SOC_LF_TIMER_CONTROL0_AUTO_RESTART_GET(x) (((x) & SOC_LF_TIMER_CONTROL0_AUTO_RESTART_MASK) >> SOC_LF_TIMER_CONTROL0_AUTO_RESTART_LSB) +#define SOC_LF_TIMER_CONTROL0_AUTO_RESTART_SET(x) (((x) << SOC_LF_TIMER_CONTROL0_AUTO_RESTART_LSB) & SOC_LF_TIMER_CONTROL0_AUTO_RESTART_MASK) +#define SOC_LF_TIMER_CONTROL0_RESET_MSB 0 +#define SOC_LF_TIMER_CONTROL0_RESET_LSB 0 +#define SOC_LF_TIMER_CONTROL0_RESET_MASK 0x00000001 +#define SOC_LF_TIMER_CONTROL0_RESET_GET(x) (((x) & SOC_LF_TIMER_CONTROL0_RESET_MASK) >> SOC_LF_TIMER_CONTROL0_RESET_LSB) +#define SOC_LF_TIMER_CONTROL0_RESET_SET(x) (((x) << SOC_LF_TIMER_CONTROL0_RESET_LSB) & SOC_LF_TIMER_CONTROL0_RESET_MASK) + +#define SOC_LF_TIMER_STATUS0_ADDRESS 0x00000054 +#define SOC_LF_TIMER_STATUS0_OFFSET 0x00000054 +#define SOC_LF_TIMER_STATUS0_INTERRUPT_MSB 0 +#define SOC_LF_TIMER_STATUS0_INTERRUPT_LSB 0 +#define SOC_LF_TIMER_STATUS0_INTERRUPT_MASK 0x00000001 +#define SOC_LF_TIMER_STATUS0_INTERRUPT_GET(x) (((x) & SOC_LF_TIMER_STATUS0_INTERRUPT_MASK) >> SOC_LF_TIMER_STATUS0_INTERRUPT_LSB) +#define SOC_LF_TIMER_STATUS0_INTERRUPT_SET(x) (((x) << SOC_LF_TIMER_STATUS0_INTERRUPT_LSB) & SOC_LF_TIMER_STATUS0_INTERRUPT_MASK) + +#define SOC_LF_TIMER1_ADDRESS 0x00000058 +#define SOC_LF_TIMER1_OFFSET 0x00000058 +#define SOC_LF_TIMER1_TARGET_MSB 31 +#define SOC_LF_TIMER1_TARGET_LSB 0 +#define SOC_LF_TIMER1_TARGET_MASK 0xffffffff +#define SOC_LF_TIMER1_TARGET_GET(x) (((x) & SOC_LF_TIMER1_TARGET_MASK) >> SOC_LF_TIMER1_TARGET_LSB) +#define SOC_LF_TIMER1_TARGET_SET(x) (((x) << SOC_LF_TIMER1_TARGET_LSB) & SOC_LF_TIMER1_TARGET_MASK) + +#define SOC_LF_TIMER_COUNT1_ADDRESS 0x0000005c +#define SOC_LF_TIMER_COUNT1_OFFSET 0x0000005c +#define SOC_LF_TIMER_COUNT1_VALUE_MSB 31 +#define SOC_LF_TIMER_COUNT1_VALUE_LSB 0 +#define SOC_LF_TIMER_COUNT1_VALUE_MASK 0xffffffff +#define SOC_LF_TIMER_COUNT1_VALUE_GET(x) (((x) & SOC_LF_TIMER_COUNT1_VALUE_MASK) >> SOC_LF_TIMER_COUNT1_VALUE_LSB) +#define SOC_LF_TIMER_COUNT1_VALUE_SET(x) (((x) << SOC_LF_TIMER_COUNT1_VALUE_LSB) & SOC_LF_TIMER_COUNT1_VALUE_MASK) + +#define SOC_LF_TIMER_CONTROL1_ADDRESS 0x00000060 +#define SOC_LF_TIMER_CONTROL1_OFFSET 0x00000060 +#define SOC_LF_TIMER_CONTROL1_ENABLE_MSB 2 +#define SOC_LF_TIMER_CONTROL1_ENABLE_LSB 2 +#define SOC_LF_TIMER_CONTROL1_ENABLE_MASK 0x00000004 +#define SOC_LF_TIMER_CONTROL1_ENABLE_GET(x) (((x) & SOC_LF_TIMER_CONTROL1_ENABLE_MASK) >> SOC_LF_TIMER_CONTROL1_ENABLE_LSB) +#define SOC_LF_TIMER_CONTROL1_ENABLE_SET(x) (((x) << SOC_LF_TIMER_CONTROL1_ENABLE_LSB) & SOC_LF_TIMER_CONTROL1_ENABLE_MASK) +#define SOC_LF_TIMER_CONTROL1_AUTO_RESTART_MSB 1 +#define SOC_LF_TIMER_CONTROL1_AUTO_RESTART_LSB 1 +#define SOC_LF_TIMER_CONTROL1_AUTO_RESTART_MASK 0x00000002 +#define SOC_LF_TIMER_CONTROL1_AUTO_RESTART_GET(x) (((x) & SOC_LF_TIMER_CONTROL1_AUTO_RESTART_MASK) >> SOC_LF_TIMER_CONTROL1_AUTO_RESTART_LSB) +#define SOC_LF_TIMER_CONTROL1_AUTO_RESTART_SET(x) (((x) << SOC_LF_TIMER_CONTROL1_AUTO_RESTART_LSB) & SOC_LF_TIMER_CONTROL1_AUTO_RESTART_MASK) +#define SOC_LF_TIMER_CONTROL1_RESET_MSB 0 +#define SOC_LF_TIMER_CONTROL1_RESET_LSB 0 +#define SOC_LF_TIMER_CONTROL1_RESET_MASK 0x00000001 +#define SOC_LF_TIMER_CONTROL1_RESET_GET(x) (((x) & SOC_LF_TIMER_CONTROL1_RESET_MASK) >> SOC_LF_TIMER_CONTROL1_RESET_LSB) +#define SOC_LF_TIMER_CONTROL1_RESET_SET(x) (((x) << SOC_LF_TIMER_CONTROL1_RESET_LSB) & SOC_LF_TIMER_CONTROL1_RESET_MASK) + +#define SOC_LF_TIMER_STATUS1_ADDRESS 0x00000064 +#define SOC_LF_TIMER_STATUS1_OFFSET 0x00000064 +#define SOC_LF_TIMER_STATUS1_INTERRUPT_MSB 0 +#define SOC_LF_TIMER_STATUS1_INTERRUPT_LSB 0 +#define SOC_LF_TIMER_STATUS1_INTERRUPT_MASK 0x00000001 +#define SOC_LF_TIMER_STATUS1_INTERRUPT_GET(x) (((x) & SOC_LF_TIMER_STATUS1_INTERRUPT_MASK) >> SOC_LF_TIMER_STATUS1_INTERRUPT_LSB) +#define SOC_LF_TIMER_STATUS1_INTERRUPT_SET(x) (((x) << SOC_LF_TIMER_STATUS1_INTERRUPT_LSB) & SOC_LF_TIMER_STATUS1_INTERRUPT_MASK) + +#define SOC_LF_TIMER2_ADDRESS 0x00000068 +#define SOC_LF_TIMER2_OFFSET 0x00000068 +#define SOC_LF_TIMER2_TARGET_MSB 31 +#define SOC_LF_TIMER2_TARGET_LSB 0 +#define SOC_LF_TIMER2_TARGET_MASK 0xffffffff +#define SOC_LF_TIMER2_TARGET_GET(x) (((x) & SOC_LF_TIMER2_TARGET_MASK) >> SOC_LF_TIMER2_TARGET_LSB) +#define SOC_LF_TIMER2_TARGET_SET(x) (((x) << SOC_LF_TIMER2_TARGET_LSB) & SOC_LF_TIMER2_TARGET_MASK) + +#define SOC_LF_TIMER_COUNT2_ADDRESS 0x0000006c +#define SOC_LF_TIMER_COUNT2_OFFSET 0x0000006c +#define SOC_LF_TIMER_COUNT2_VALUE_MSB 31 +#define SOC_LF_TIMER_COUNT2_VALUE_LSB 0 +#define SOC_LF_TIMER_COUNT2_VALUE_MASK 0xffffffff +#define SOC_LF_TIMER_COUNT2_VALUE_GET(x) (((x) & SOC_LF_TIMER_COUNT2_VALUE_MASK) >> SOC_LF_TIMER_COUNT2_VALUE_LSB) +#define SOC_LF_TIMER_COUNT2_VALUE_SET(x) (((x) << SOC_LF_TIMER_COUNT2_VALUE_LSB) & SOC_LF_TIMER_COUNT2_VALUE_MASK) + +#define SOC_LF_TIMER_CONTROL2_ADDRESS 0x00000070 +#define SOC_LF_TIMER_CONTROL2_OFFSET 0x00000070 +#define SOC_LF_TIMER_CONTROL2_ENABLE_MSB 2 +#define SOC_LF_TIMER_CONTROL2_ENABLE_LSB 2 +#define SOC_LF_TIMER_CONTROL2_ENABLE_MASK 0x00000004 +#define SOC_LF_TIMER_CONTROL2_ENABLE_GET(x) (((x) & SOC_LF_TIMER_CONTROL2_ENABLE_MASK) >> SOC_LF_TIMER_CONTROL2_ENABLE_LSB) +#define SOC_LF_TIMER_CONTROL2_ENABLE_SET(x) (((x) << SOC_LF_TIMER_CONTROL2_ENABLE_LSB) & SOC_LF_TIMER_CONTROL2_ENABLE_MASK) +#define SOC_LF_TIMER_CONTROL2_AUTO_RESTART_MSB 1 +#define SOC_LF_TIMER_CONTROL2_AUTO_RESTART_LSB 1 +#define SOC_LF_TIMER_CONTROL2_AUTO_RESTART_MASK 0x00000002 +#define SOC_LF_TIMER_CONTROL2_AUTO_RESTART_GET(x) (((x) & SOC_LF_TIMER_CONTROL2_AUTO_RESTART_MASK) >> SOC_LF_TIMER_CONTROL2_AUTO_RESTART_LSB) +#define SOC_LF_TIMER_CONTROL2_AUTO_RESTART_SET(x) (((x) << SOC_LF_TIMER_CONTROL2_AUTO_RESTART_LSB) & SOC_LF_TIMER_CONTROL2_AUTO_RESTART_MASK) +#define SOC_LF_TIMER_CONTROL2_RESET_MSB 0 +#define SOC_LF_TIMER_CONTROL2_RESET_LSB 0 +#define SOC_LF_TIMER_CONTROL2_RESET_MASK 0x00000001 +#define SOC_LF_TIMER_CONTROL2_RESET_GET(x) (((x) & SOC_LF_TIMER_CONTROL2_RESET_MASK) >> SOC_LF_TIMER_CONTROL2_RESET_LSB) +#define SOC_LF_TIMER_CONTROL2_RESET_SET(x) (((x) << SOC_LF_TIMER_CONTROL2_RESET_LSB) & SOC_LF_TIMER_CONTROL2_RESET_MASK) + +#define SOC_LF_TIMER_STATUS2_ADDRESS 0x00000074 +#define SOC_LF_TIMER_STATUS2_OFFSET 0x00000074 +#define SOC_LF_TIMER_STATUS2_INTERRUPT_MSB 0 +#define SOC_LF_TIMER_STATUS2_INTERRUPT_LSB 0 +#define SOC_LF_TIMER_STATUS2_INTERRUPT_MASK 0x00000001 +#define SOC_LF_TIMER_STATUS2_INTERRUPT_GET(x) (((x) & SOC_LF_TIMER_STATUS2_INTERRUPT_MASK) >> SOC_LF_TIMER_STATUS2_INTERRUPT_LSB) +#define SOC_LF_TIMER_STATUS2_INTERRUPT_SET(x) (((x) << SOC_LF_TIMER_STATUS2_INTERRUPT_LSB) & SOC_LF_TIMER_STATUS2_INTERRUPT_MASK) + +#define SOC_LF_TIMER3_ADDRESS 0x00000078 +#define SOC_LF_TIMER3_OFFSET 0x00000078 +#define SOC_LF_TIMER3_TARGET_MSB 31 +#define SOC_LF_TIMER3_TARGET_LSB 0 +#define SOC_LF_TIMER3_TARGET_MASK 0xffffffff +#define SOC_LF_TIMER3_TARGET_GET(x) (((x) & SOC_LF_TIMER3_TARGET_MASK) >> SOC_LF_TIMER3_TARGET_LSB) +#define SOC_LF_TIMER3_TARGET_SET(x) (((x) << SOC_LF_TIMER3_TARGET_LSB) & SOC_LF_TIMER3_TARGET_MASK) + +#define SOC_LF_TIMER_COUNT3_ADDRESS 0x0000007c +#define SOC_LF_TIMER_COUNT3_OFFSET 0x0000007c +#define SOC_LF_TIMER_COUNT3_VALUE_MSB 31 +#define SOC_LF_TIMER_COUNT3_VALUE_LSB 0 +#define SOC_LF_TIMER_COUNT3_VALUE_MASK 0xffffffff +#define SOC_LF_TIMER_COUNT3_VALUE_GET(x) (((x) & SOC_LF_TIMER_COUNT3_VALUE_MASK) >> SOC_LF_TIMER_COUNT3_VALUE_LSB) +#define SOC_LF_TIMER_COUNT3_VALUE_SET(x) (((x) << SOC_LF_TIMER_COUNT3_VALUE_LSB) & SOC_LF_TIMER_COUNT3_VALUE_MASK) + +#define SOC_LF_TIMER_CONTROL3_ADDRESS 0x00000080 +#define SOC_LF_TIMER_CONTROL3_OFFSET 0x00000080 +#define SOC_LF_TIMER_CONTROL3_ENABLE_MSB 2 +#define SOC_LF_TIMER_CONTROL3_ENABLE_LSB 2 +#define SOC_LF_TIMER_CONTROL3_ENABLE_MASK 0x00000004 +#define SOC_LF_TIMER_CONTROL3_ENABLE_GET(x) (((x) & SOC_LF_TIMER_CONTROL3_ENABLE_MASK) >> SOC_LF_TIMER_CONTROL3_ENABLE_LSB) +#define SOC_LF_TIMER_CONTROL3_ENABLE_SET(x) (((x) << SOC_LF_TIMER_CONTROL3_ENABLE_LSB) & SOC_LF_TIMER_CONTROL3_ENABLE_MASK) +#define SOC_LF_TIMER_CONTROL3_AUTO_RESTART_MSB 1 +#define SOC_LF_TIMER_CONTROL3_AUTO_RESTART_LSB 1 +#define SOC_LF_TIMER_CONTROL3_AUTO_RESTART_MASK 0x00000002 +#define SOC_LF_TIMER_CONTROL3_AUTO_RESTART_GET(x) (((x) & SOC_LF_TIMER_CONTROL3_AUTO_RESTART_MASK) >> SOC_LF_TIMER_CONTROL3_AUTO_RESTART_LSB) +#define SOC_LF_TIMER_CONTROL3_AUTO_RESTART_SET(x) (((x) << SOC_LF_TIMER_CONTROL3_AUTO_RESTART_LSB) & SOC_LF_TIMER_CONTROL3_AUTO_RESTART_MASK) +#define SOC_LF_TIMER_CONTROL3_RESET_MSB 0 +#define SOC_LF_TIMER_CONTROL3_RESET_LSB 0 +#define SOC_LF_TIMER_CONTROL3_RESET_MASK 0x00000001 +#define SOC_LF_TIMER_CONTROL3_RESET_GET(x) (((x) & SOC_LF_TIMER_CONTROL3_RESET_MASK) >> SOC_LF_TIMER_CONTROL3_RESET_LSB) +#define SOC_LF_TIMER_CONTROL3_RESET_SET(x) (((x) << SOC_LF_TIMER_CONTROL3_RESET_LSB) & SOC_LF_TIMER_CONTROL3_RESET_MASK) + +#define SOC_LF_TIMER_STATUS3_ADDRESS 0x00000084 +#define SOC_LF_TIMER_STATUS3_OFFSET 0x00000084 +#define SOC_LF_TIMER_STATUS3_INTERRUPT_MSB 0 +#define SOC_LF_TIMER_STATUS3_INTERRUPT_LSB 0 +#define SOC_LF_TIMER_STATUS3_INTERRUPT_MASK 0x00000001 +#define SOC_LF_TIMER_STATUS3_INTERRUPT_GET(x) (((x) & SOC_LF_TIMER_STATUS3_INTERRUPT_MASK) >> SOC_LF_TIMER_STATUS3_INTERRUPT_LSB) +#define SOC_LF_TIMER_STATUS3_INTERRUPT_SET(x) (((x) << SOC_LF_TIMER_STATUS3_INTERRUPT_LSB) & SOC_LF_TIMER_STATUS3_INTERRUPT_MASK) + +#define SOC_HF_TIMER_ADDRESS 0x00000088 +#define SOC_HF_TIMER_OFFSET 0x00000088 +#define SOC_HF_TIMER_TARGET_MSB 31 +#define SOC_HF_TIMER_TARGET_LSB 12 +#define SOC_HF_TIMER_TARGET_MASK 0xfffff000 +#define SOC_HF_TIMER_TARGET_GET(x) (((x) & SOC_HF_TIMER_TARGET_MASK) >> SOC_HF_TIMER_TARGET_LSB) +#define SOC_HF_TIMER_TARGET_SET(x) (((x) << SOC_HF_TIMER_TARGET_LSB) & SOC_HF_TIMER_TARGET_MASK) + +#define SOC_HF_TIMER_COUNT_ADDRESS 0x0000008c +#define SOC_HF_TIMER_COUNT_OFFSET 0x0000008c +#define SOC_HF_TIMER_COUNT_VALUE_MSB 31 +#define SOC_HF_TIMER_COUNT_VALUE_LSB 12 +#define SOC_HF_TIMER_COUNT_VALUE_MASK 0xfffff000 +#define SOC_HF_TIMER_COUNT_VALUE_GET(x) (((x) & SOC_HF_TIMER_COUNT_VALUE_MASK) >> SOC_HF_TIMER_COUNT_VALUE_LSB) +#define SOC_HF_TIMER_COUNT_VALUE_SET(x) (((x) << SOC_HF_TIMER_COUNT_VALUE_LSB) & SOC_HF_TIMER_COUNT_VALUE_MASK) + +#define SOC_HF_LF_COUNT_ADDRESS 0x00000090 +#define SOC_HF_LF_COUNT_OFFSET 0x00000090 +#define SOC_HF_LF_COUNT_VALUE_MSB 31 +#define SOC_HF_LF_COUNT_VALUE_LSB 0 +#define SOC_HF_LF_COUNT_VALUE_MASK 0xffffffff +#define SOC_HF_LF_COUNT_VALUE_GET(x) (((x) & SOC_HF_LF_COUNT_VALUE_MASK) >> SOC_HF_LF_COUNT_VALUE_LSB) +#define SOC_HF_LF_COUNT_VALUE_SET(x) (((x) << SOC_HF_LF_COUNT_VALUE_LSB) & SOC_HF_LF_COUNT_VALUE_MASK) + +#define SOC_HF_TIMER_CONTROL_ADDRESS 0x00000094 +#define SOC_HF_TIMER_CONTROL_OFFSET 0x00000094 +#define SOC_HF_TIMER_CONTROL_ENABLE_MSB 3 +#define SOC_HF_TIMER_CONTROL_ENABLE_LSB 3 +#define SOC_HF_TIMER_CONTROL_ENABLE_MASK 0x00000008 +#define SOC_HF_TIMER_CONTROL_ENABLE_GET(x) (((x) & SOC_HF_TIMER_CONTROL_ENABLE_MASK) >> SOC_HF_TIMER_CONTROL_ENABLE_LSB) +#define SOC_HF_TIMER_CONTROL_ENABLE_SET(x) (((x) << SOC_HF_TIMER_CONTROL_ENABLE_LSB) & SOC_HF_TIMER_CONTROL_ENABLE_MASK) +#define SOC_HF_TIMER_CONTROL_ON_MSB 2 +#define SOC_HF_TIMER_CONTROL_ON_LSB 2 +#define SOC_HF_TIMER_CONTROL_ON_MASK 0x00000004 +#define SOC_HF_TIMER_CONTROL_ON_GET(x) (((x) & SOC_HF_TIMER_CONTROL_ON_MASK) >> SOC_HF_TIMER_CONTROL_ON_LSB) +#define SOC_HF_TIMER_CONTROL_ON_SET(x) (((x) << SOC_HF_TIMER_CONTROL_ON_LSB) & SOC_HF_TIMER_CONTROL_ON_MASK) +#define SOC_HF_TIMER_CONTROL_AUTO_RESTART_MSB 1 +#define SOC_HF_TIMER_CONTROL_AUTO_RESTART_LSB 1 +#define SOC_HF_TIMER_CONTROL_AUTO_RESTART_MASK 0x00000002 +#define SOC_HF_TIMER_CONTROL_AUTO_RESTART_GET(x) (((x) & SOC_HF_TIMER_CONTROL_AUTO_RESTART_MASK) >> SOC_HF_TIMER_CONTROL_AUTO_RESTART_LSB) +#define SOC_HF_TIMER_CONTROL_AUTO_RESTART_SET(x) (((x) << SOC_HF_TIMER_CONTROL_AUTO_RESTART_LSB) & SOC_HF_TIMER_CONTROL_AUTO_RESTART_MASK) +#define SOC_HF_TIMER_CONTROL_RESET_MSB 0 +#define SOC_HF_TIMER_CONTROL_RESET_LSB 0 +#define SOC_HF_TIMER_CONTROL_RESET_MASK 0x00000001 +#define SOC_HF_TIMER_CONTROL_RESET_GET(x) (((x) & SOC_HF_TIMER_CONTROL_RESET_MASK) >> SOC_HF_TIMER_CONTROL_RESET_LSB) +#define SOC_HF_TIMER_CONTROL_RESET_SET(x) (((x) << SOC_HF_TIMER_CONTROL_RESET_LSB) & SOC_HF_TIMER_CONTROL_RESET_MASK) + +#define SOC_HF_TIMER_STATUS_ADDRESS 0x00000098 +#define SOC_HF_TIMER_STATUS_OFFSET 0x00000098 +#define SOC_HF_TIMER_STATUS_INTERRUPT_MSB 0 +#define SOC_HF_TIMER_STATUS_INTERRUPT_LSB 0 +#define SOC_HF_TIMER_STATUS_INTERRUPT_MASK 0x00000001 +#define SOC_HF_TIMER_STATUS_INTERRUPT_GET(x) (((x) & SOC_HF_TIMER_STATUS_INTERRUPT_MASK) >> SOC_HF_TIMER_STATUS_INTERRUPT_LSB) +#define SOC_HF_TIMER_STATUS_INTERRUPT_SET(x) (((x) << SOC_HF_TIMER_STATUS_INTERRUPT_LSB) & SOC_HF_TIMER_STATUS_INTERRUPT_MASK) + +#define SOC_RTC_CONTROL_ADDRESS 0x0000009c +#define SOC_RTC_CONTROL_OFFSET 0x0000009c +#define SOC_RTC_CONTROL_ENABLE_MSB 2 +#define SOC_RTC_CONTROL_ENABLE_LSB 2 +#define SOC_RTC_CONTROL_ENABLE_MASK 0x00000004 +#define SOC_RTC_CONTROL_ENABLE_GET(x) (((x) & SOC_RTC_CONTROL_ENABLE_MASK) >> SOC_RTC_CONTROL_ENABLE_LSB) +#define SOC_RTC_CONTROL_ENABLE_SET(x) (((x) << SOC_RTC_CONTROL_ENABLE_LSB) & SOC_RTC_CONTROL_ENABLE_MASK) +#define SOC_RTC_CONTROL_LOAD_RTC_MSB 1 +#define SOC_RTC_CONTROL_LOAD_RTC_LSB 1 +#define SOC_RTC_CONTROL_LOAD_RTC_MASK 0x00000002 +#define SOC_RTC_CONTROL_LOAD_RTC_GET(x) (((x) & SOC_RTC_CONTROL_LOAD_RTC_MASK) >> SOC_RTC_CONTROL_LOAD_RTC_LSB) +#define SOC_RTC_CONTROL_LOAD_RTC_SET(x) (((x) << SOC_RTC_CONTROL_LOAD_RTC_LSB) & SOC_RTC_CONTROL_LOAD_RTC_MASK) +#define SOC_RTC_CONTROL_LOAD_ALARM_MSB 0 +#define SOC_RTC_CONTROL_LOAD_ALARM_LSB 0 +#define SOC_RTC_CONTROL_LOAD_ALARM_MASK 0x00000001 +#define SOC_RTC_CONTROL_LOAD_ALARM_GET(x) (((x) & SOC_RTC_CONTROL_LOAD_ALARM_MASK) >> SOC_RTC_CONTROL_LOAD_ALARM_LSB) +#define SOC_RTC_CONTROL_LOAD_ALARM_SET(x) (((x) << SOC_RTC_CONTROL_LOAD_ALARM_LSB) & SOC_RTC_CONTROL_LOAD_ALARM_MASK) + +#define SOC_RTC_TIME_ADDRESS 0x000000a0 +#define SOC_RTC_TIME_OFFSET 0x000000a0 +#define SOC_RTC_TIME_WEEK_DAY_MSB 26 +#define SOC_RTC_TIME_WEEK_DAY_LSB 24 +#define SOC_RTC_TIME_WEEK_DAY_MASK 0x07000000 +#define SOC_RTC_TIME_WEEK_DAY_GET(x) (((x) & SOC_RTC_TIME_WEEK_DAY_MASK) >> SOC_RTC_TIME_WEEK_DAY_LSB) +#define SOC_RTC_TIME_WEEK_DAY_SET(x) (((x) << SOC_RTC_TIME_WEEK_DAY_LSB) & SOC_RTC_TIME_WEEK_DAY_MASK) +#define SOC_RTC_TIME_HOUR_MSB 21 +#define SOC_RTC_TIME_HOUR_LSB 16 +#define SOC_RTC_TIME_HOUR_MASK 0x003f0000 +#define SOC_RTC_TIME_HOUR_GET(x) (((x) & SOC_RTC_TIME_HOUR_MASK) >> SOC_RTC_TIME_HOUR_LSB) +#define SOC_RTC_TIME_HOUR_SET(x) (((x) << SOC_RTC_TIME_HOUR_LSB) & SOC_RTC_TIME_HOUR_MASK) +#define SOC_RTC_TIME_MINUTE_MSB 14 +#define SOC_RTC_TIME_MINUTE_LSB 8 +#define SOC_RTC_TIME_MINUTE_MASK 0x00007f00 +#define SOC_RTC_TIME_MINUTE_GET(x) (((x) & SOC_RTC_TIME_MINUTE_MASK) >> SOC_RTC_TIME_MINUTE_LSB) +#define SOC_RTC_TIME_MINUTE_SET(x) (((x) << SOC_RTC_TIME_MINUTE_LSB) & SOC_RTC_TIME_MINUTE_MASK) +#define SOC_RTC_TIME_SECOND_MSB 6 +#define SOC_RTC_TIME_SECOND_LSB 0 +#define SOC_RTC_TIME_SECOND_MASK 0x0000007f +#define SOC_RTC_TIME_SECOND_GET(x) (((x) & SOC_RTC_TIME_SECOND_MASK) >> SOC_RTC_TIME_SECOND_LSB) +#define SOC_RTC_TIME_SECOND_SET(x) (((x) << SOC_RTC_TIME_SECOND_LSB) & SOC_RTC_TIME_SECOND_MASK) + +#define SOC_RTC_DATE_ADDRESS 0x000000a4 +#define SOC_RTC_DATE_OFFSET 0x000000a4 +#define SOC_RTC_DATE_YEAR_MSB 23 +#define SOC_RTC_DATE_YEAR_LSB 16 +#define SOC_RTC_DATE_YEAR_MASK 0x00ff0000 +#define SOC_RTC_DATE_YEAR_GET(x) (((x) & SOC_RTC_DATE_YEAR_MASK) >> SOC_RTC_DATE_YEAR_LSB) +#define SOC_RTC_DATE_YEAR_SET(x) (((x) << SOC_RTC_DATE_YEAR_LSB) & SOC_RTC_DATE_YEAR_MASK) +#define SOC_RTC_DATE_MONTH_MSB 12 +#define SOC_RTC_DATE_MONTH_LSB 8 +#define SOC_RTC_DATE_MONTH_MASK 0x00001f00 +#define SOC_RTC_DATE_MONTH_GET(x) (((x) & SOC_RTC_DATE_MONTH_MASK) >> SOC_RTC_DATE_MONTH_LSB) +#define SOC_RTC_DATE_MONTH_SET(x) (((x) << SOC_RTC_DATE_MONTH_LSB) & SOC_RTC_DATE_MONTH_MASK) +#define SOC_RTC_DATE_MONTH_DAY_MSB 5 +#define SOC_RTC_DATE_MONTH_DAY_LSB 0 +#define SOC_RTC_DATE_MONTH_DAY_MASK 0x0000003f +#define SOC_RTC_DATE_MONTH_DAY_GET(x) (((x) & SOC_RTC_DATE_MONTH_DAY_MASK) >> SOC_RTC_DATE_MONTH_DAY_LSB) +#define SOC_RTC_DATE_MONTH_DAY_SET(x) (((x) << SOC_RTC_DATE_MONTH_DAY_LSB) & SOC_RTC_DATE_MONTH_DAY_MASK) + +#define SOC_RTC_SET_TIME_ADDRESS 0x000000a8 +#define SOC_RTC_SET_TIME_OFFSET 0x000000a8 +#define SOC_RTC_SET_TIME_WEEK_DAY_MSB 26 +#define SOC_RTC_SET_TIME_WEEK_DAY_LSB 24 +#define SOC_RTC_SET_TIME_WEEK_DAY_MASK 0x07000000 +#define SOC_RTC_SET_TIME_WEEK_DAY_GET(x) (((x) & SOC_RTC_SET_TIME_WEEK_DAY_MASK) >> SOC_RTC_SET_TIME_WEEK_DAY_LSB) +#define SOC_RTC_SET_TIME_WEEK_DAY_SET(x) (((x) << SOC_RTC_SET_TIME_WEEK_DAY_LSB) & SOC_RTC_SET_TIME_WEEK_DAY_MASK) +#define SOC_RTC_SET_TIME_HOUR_MSB 21 +#define SOC_RTC_SET_TIME_HOUR_LSB 16 +#define SOC_RTC_SET_TIME_HOUR_MASK 0x003f0000 +#define SOC_RTC_SET_TIME_HOUR_GET(x) (((x) & SOC_RTC_SET_TIME_HOUR_MASK) >> SOC_RTC_SET_TIME_HOUR_LSB) +#define SOC_RTC_SET_TIME_HOUR_SET(x) (((x) << SOC_RTC_SET_TIME_HOUR_LSB) & SOC_RTC_SET_TIME_HOUR_MASK) +#define SOC_RTC_SET_TIME_MINUTE_MSB 14 +#define SOC_RTC_SET_TIME_MINUTE_LSB 8 +#define SOC_RTC_SET_TIME_MINUTE_MASK 0x00007f00 +#define SOC_RTC_SET_TIME_MINUTE_GET(x) (((x) & SOC_RTC_SET_TIME_MINUTE_MASK) >> SOC_RTC_SET_TIME_MINUTE_LSB) +#define SOC_RTC_SET_TIME_MINUTE_SET(x) (((x) << SOC_RTC_SET_TIME_MINUTE_LSB) & SOC_RTC_SET_TIME_MINUTE_MASK) +#define SOC_RTC_SET_TIME_SECOND_MSB 6 +#define SOC_RTC_SET_TIME_SECOND_LSB 0 +#define SOC_RTC_SET_TIME_SECOND_MASK 0x0000007f +#define SOC_RTC_SET_TIME_SECOND_GET(x) (((x) & SOC_RTC_SET_TIME_SECOND_MASK) >> SOC_RTC_SET_TIME_SECOND_LSB) +#define SOC_RTC_SET_TIME_SECOND_SET(x) (((x) << SOC_RTC_SET_TIME_SECOND_LSB) & SOC_RTC_SET_TIME_SECOND_MASK) + +#define SOC_RTC_SET_DATE_ADDRESS 0x000000ac +#define SOC_RTC_SET_DATE_OFFSET 0x000000ac +#define SOC_RTC_SET_DATE_YEAR_MSB 23 +#define SOC_RTC_SET_DATE_YEAR_LSB 16 +#define SOC_RTC_SET_DATE_YEAR_MASK 0x00ff0000 +#define SOC_RTC_SET_DATE_YEAR_GET(x) (((x) & SOC_RTC_SET_DATE_YEAR_MASK) >> SOC_RTC_SET_DATE_YEAR_LSB) +#define SOC_RTC_SET_DATE_YEAR_SET(x) (((x) << SOC_RTC_SET_DATE_YEAR_LSB) & SOC_RTC_SET_DATE_YEAR_MASK) +#define SOC_RTC_SET_DATE_MONTH_MSB 12 +#define SOC_RTC_SET_DATE_MONTH_LSB 8 +#define SOC_RTC_SET_DATE_MONTH_MASK 0x00001f00 +#define SOC_RTC_SET_DATE_MONTH_GET(x) (((x) & SOC_RTC_SET_DATE_MONTH_MASK) >> SOC_RTC_SET_DATE_MONTH_LSB) +#define SOC_RTC_SET_DATE_MONTH_SET(x) (((x) << SOC_RTC_SET_DATE_MONTH_LSB) & SOC_RTC_SET_DATE_MONTH_MASK) +#define SOC_RTC_SET_DATE_MONTH_DAY_MSB 5 +#define SOC_RTC_SET_DATE_MONTH_DAY_LSB 0 +#define SOC_RTC_SET_DATE_MONTH_DAY_MASK 0x0000003f +#define SOC_RTC_SET_DATE_MONTH_DAY_GET(x) (((x) & SOC_RTC_SET_DATE_MONTH_DAY_MASK) >> SOC_RTC_SET_DATE_MONTH_DAY_LSB) +#define SOC_RTC_SET_DATE_MONTH_DAY_SET(x) (((x) << SOC_RTC_SET_DATE_MONTH_DAY_LSB) & SOC_RTC_SET_DATE_MONTH_DAY_MASK) + +#define SOC_RTC_SET_ALARM_ADDRESS 0x000000b0 +#define SOC_RTC_SET_ALARM_OFFSET 0x000000b0 +#define SOC_RTC_SET_ALARM_HOUR_MSB 21 +#define SOC_RTC_SET_ALARM_HOUR_LSB 16 +#define SOC_RTC_SET_ALARM_HOUR_MASK 0x003f0000 +#define SOC_RTC_SET_ALARM_HOUR_GET(x) (((x) & SOC_RTC_SET_ALARM_HOUR_MASK) >> SOC_RTC_SET_ALARM_HOUR_LSB) +#define SOC_RTC_SET_ALARM_HOUR_SET(x) (((x) << SOC_RTC_SET_ALARM_HOUR_LSB) & SOC_RTC_SET_ALARM_HOUR_MASK) +#define SOC_RTC_SET_ALARM_MINUTE_MSB 14 +#define SOC_RTC_SET_ALARM_MINUTE_LSB 8 +#define SOC_RTC_SET_ALARM_MINUTE_MASK 0x00007f00 +#define SOC_RTC_SET_ALARM_MINUTE_GET(x) (((x) & SOC_RTC_SET_ALARM_MINUTE_MASK) >> SOC_RTC_SET_ALARM_MINUTE_LSB) +#define SOC_RTC_SET_ALARM_MINUTE_SET(x) (((x) << SOC_RTC_SET_ALARM_MINUTE_LSB) & SOC_RTC_SET_ALARM_MINUTE_MASK) +#define SOC_RTC_SET_ALARM_SECOND_MSB 6 +#define SOC_RTC_SET_ALARM_SECOND_LSB 0 +#define SOC_RTC_SET_ALARM_SECOND_MASK 0x0000007f +#define SOC_RTC_SET_ALARM_SECOND_GET(x) (((x) & SOC_RTC_SET_ALARM_SECOND_MASK) >> SOC_RTC_SET_ALARM_SECOND_LSB) +#define SOC_RTC_SET_ALARM_SECOND_SET(x) (((x) << SOC_RTC_SET_ALARM_SECOND_LSB) & SOC_RTC_SET_ALARM_SECOND_MASK) + +#define SOC_RTC_CONFIG_ADDRESS 0x000000b4 +#define SOC_RTC_CONFIG_OFFSET 0x000000b4 +#define SOC_RTC_CONFIG_BCD_MSB 2 +#define SOC_RTC_CONFIG_BCD_LSB 2 +#define SOC_RTC_CONFIG_BCD_MASK 0x00000004 +#define SOC_RTC_CONFIG_BCD_GET(x) (((x) & SOC_RTC_CONFIG_BCD_MASK) >> SOC_RTC_CONFIG_BCD_LSB) +#define SOC_RTC_CONFIG_BCD_SET(x) (((x) << SOC_RTC_CONFIG_BCD_LSB) & SOC_RTC_CONFIG_BCD_MASK) +#define SOC_RTC_CONFIG_TWELVE_HOUR_MSB 1 +#define SOC_RTC_CONFIG_TWELVE_HOUR_LSB 1 +#define SOC_RTC_CONFIG_TWELVE_HOUR_MASK 0x00000002 +#define SOC_RTC_CONFIG_TWELVE_HOUR_GET(x) (((x) & SOC_RTC_CONFIG_TWELVE_HOUR_MASK) >> SOC_RTC_CONFIG_TWELVE_HOUR_LSB) +#define SOC_RTC_CONFIG_TWELVE_HOUR_SET(x) (((x) << SOC_RTC_CONFIG_TWELVE_HOUR_LSB) & SOC_RTC_CONFIG_TWELVE_HOUR_MASK) +#define SOC_RTC_CONFIG_DSE_MSB 0 +#define SOC_RTC_CONFIG_DSE_LSB 0 +#define SOC_RTC_CONFIG_DSE_MASK 0x00000001 +#define SOC_RTC_CONFIG_DSE_GET(x) (((x) & SOC_RTC_CONFIG_DSE_MASK) >> SOC_RTC_CONFIG_DSE_LSB) +#define SOC_RTC_CONFIG_DSE_SET(x) (((x) << SOC_RTC_CONFIG_DSE_LSB) & SOC_RTC_CONFIG_DSE_MASK) + +#define SOC_RTC_ALARM_STATUS_ADDRESS 0x000000b8 +#define SOC_RTC_ALARM_STATUS_OFFSET 0x000000b8 +#define SOC_RTC_ALARM_STATUS_ENABLE_MSB 1 +#define SOC_RTC_ALARM_STATUS_ENABLE_LSB 1 +#define SOC_RTC_ALARM_STATUS_ENABLE_MASK 0x00000002 +#define SOC_RTC_ALARM_STATUS_ENABLE_GET(x) (((x) & SOC_RTC_ALARM_STATUS_ENABLE_MASK) >> SOC_RTC_ALARM_STATUS_ENABLE_LSB) +#define SOC_RTC_ALARM_STATUS_ENABLE_SET(x) (((x) << SOC_RTC_ALARM_STATUS_ENABLE_LSB) & SOC_RTC_ALARM_STATUS_ENABLE_MASK) +#define SOC_RTC_ALARM_STATUS_INTERRUPT_MSB 0 +#define SOC_RTC_ALARM_STATUS_INTERRUPT_LSB 0 +#define SOC_RTC_ALARM_STATUS_INTERRUPT_MASK 0x00000001 +#define SOC_RTC_ALARM_STATUS_INTERRUPT_GET(x) (((x) & SOC_RTC_ALARM_STATUS_INTERRUPT_MASK) >> SOC_RTC_ALARM_STATUS_INTERRUPT_LSB) +#define SOC_RTC_ALARM_STATUS_INTERRUPT_SET(x) (((x) << SOC_RTC_ALARM_STATUS_INTERRUPT_LSB) & SOC_RTC_ALARM_STATUS_INTERRUPT_MASK) + +#define SOC_UART_WAKEUP_ADDRESS 0x000000bc +#define SOC_UART_WAKEUP_OFFSET 0x000000bc +#define SOC_UART_WAKEUP_ENABLE_MSB 0 +#define SOC_UART_WAKEUP_ENABLE_LSB 0 +#define SOC_UART_WAKEUP_ENABLE_MASK 0x00000001 +#define SOC_UART_WAKEUP_ENABLE_GET(x) (((x) & SOC_UART_WAKEUP_ENABLE_MASK) >> SOC_UART_WAKEUP_ENABLE_LSB) +#define SOC_UART_WAKEUP_ENABLE_SET(x) (((x) << SOC_UART_WAKEUP_ENABLE_LSB) & SOC_UART_WAKEUP_ENABLE_MASK) + +#define SOC_RESET_CAUSE_ADDRESS 0x000000c0 +#define SOC_RESET_CAUSE_OFFSET 0x000000c0 +#define SOC_RESET_CAUSE_LAST_MSB 2 +#define SOC_RESET_CAUSE_LAST_LSB 0 +#define SOC_RESET_CAUSE_LAST_MASK 0x00000007 +#define SOC_RESET_CAUSE_LAST_GET(x) (((x) & SOC_RESET_CAUSE_LAST_MASK) >> SOC_RESET_CAUSE_LAST_LSB) +#define SOC_RESET_CAUSE_LAST_SET(x) (((x) << SOC_RESET_CAUSE_LAST_LSB) & SOC_RESET_CAUSE_LAST_MASK) + +#define SOC_SYSTEM_SLEEP_ADDRESS 0x000000c4 +#define SOC_SYSTEM_SLEEP_OFFSET 0x000000c4 +#define SOC_SYSTEM_SLEEP_MCI_MSB 5 +#define SOC_SYSTEM_SLEEP_MCI_LSB 5 +#define SOC_SYSTEM_SLEEP_MCI_MASK 0x00000020 +#define SOC_SYSTEM_SLEEP_MCI_GET(x) (((x) & SOC_SYSTEM_SLEEP_MCI_MASK) >> SOC_SYSTEM_SLEEP_MCI_LSB) +#define SOC_SYSTEM_SLEEP_MCI_SET(x) (((x) << SOC_SYSTEM_SLEEP_MCI_LSB) & SOC_SYSTEM_SLEEP_MCI_MASK) +#define SOC_SYSTEM_SLEEP_HOST_IF_MSB 4 +#define SOC_SYSTEM_SLEEP_HOST_IF_LSB 4 +#define SOC_SYSTEM_SLEEP_HOST_IF_MASK 0x00000010 +#define SOC_SYSTEM_SLEEP_HOST_IF_GET(x) (((x) & SOC_SYSTEM_SLEEP_HOST_IF_MASK) >> SOC_SYSTEM_SLEEP_HOST_IF_LSB) +#define SOC_SYSTEM_SLEEP_HOST_IF_SET(x) (((x) << SOC_SYSTEM_SLEEP_HOST_IF_LSB) & SOC_SYSTEM_SLEEP_HOST_IF_MASK) +#define SOC_SYSTEM_SLEEP_MBOX_MSB 3 +#define SOC_SYSTEM_SLEEP_MBOX_LSB 3 +#define SOC_SYSTEM_SLEEP_MBOX_MASK 0x00000008 +#define SOC_SYSTEM_SLEEP_MBOX_GET(x) (((x) & SOC_SYSTEM_SLEEP_MBOX_MASK) >> SOC_SYSTEM_SLEEP_MBOX_LSB) +#define SOC_SYSTEM_SLEEP_MBOX_SET(x) (((x) << SOC_SYSTEM_SLEEP_MBOX_LSB) & SOC_SYSTEM_SLEEP_MBOX_MASK) +#define SOC_SYSTEM_SLEEP_MAC_IF_MSB 2 +#define SOC_SYSTEM_SLEEP_MAC_IF_LSB 2 +#define SOC_SYSTEM_SLEEP_MAC_IF_MASK 0x00000004 +#define SOC_SYSTEM_SLEEP_MAC_IF_GET(x) (((x) & SOC_SYSTEM_SLEEP_MAC_IF_MASK) >> SOC_SYSTEM_SLEEP_MAC_IF_LSB) +#define SOC_SYSTEM_SLEEP_MAC_IF_SET(x) (((x) << SOC_SYSTEM_SLEEP_MAC_IF_LSB) & SOC_SYSTEM_SLEEP_MAC_IF_MASK) +#define SOC_SYSTEM_SLEEP_LIGHT_MSB 1 +#define SOC_SYSTEM_SLEEP_LIGHT_LSB 1 +#define SOC_SYSTEM_SLEEP_LIGHT_MASK 0x00000002 +#define SOC_SYSTEM_SLEEP_LIGHT_GET(x) (((x) & SOC_SYSTEM_SLEEP_LIGHT_MASK) >> SOC_SYSTEM_SLEEP_LIGHT_LSB) +#define SOC_SYSTEM_SLEEP_LIGHT_SET(x) (((x) << SOC_SYSTEM_SLEEP_LIGHT_LSB) & SOC_SYSTEM_SLEEP_LIGHT_MASK) +#define SOC_SYSTEM_SLEEP_DISABLE_MSB 0 +#define SOC_SYSTEM_SLEEP_DISABLE_LSB 0 +#define SOC_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define SOC_SYSTEM_SLEEP_DISABLE_GET(x) (((x) & SOC_SYSTEM_SLEEP_DISABLE_MASK) >> SOC_SYSTEM_SLEEP_DISABLE_LSB) +#define SOC_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << SOC_SYSTEM_SLEEP_DISABLE_LSB) & SOC_SYSTEM_SLEEP_DISABLE_MASK) + +#define SOC_SDIO_WRAPPER_ADDRESS 0x000000c8 +#define SOC_SDIO_WRAPPER_OFFSET 0x000000c8 +#define SOC_SDIO_WRAPPER_SLEEP_MSB 3 +#define SOC_SDIO_WRAPPER_SLEEP_LSB 3 +#define SOC_SDIO_WRAPPER_SLEEP_MASK 0x00000008 +#define SOC_SDIO_WRAPPER_SLEEP_GET(x) (((x) & SOC_SDIO_WRAPPER_SLEEP_MASK) >> SOC_SDIO_WRAPPER_SLEEP_LSB) +#define SOC_SDIO_WRAPPER_SLEEP_SET(x) (((x) << SOC_SDIO_WRAPPER_SLEEP_LSB) & SOC_SDIO_WRAPPER_SLEEP_MASK) +#define SOC_SDIO_WRAPPER_WAKEUP_MSB 2 +#define SOC_SDIO_WRAPPER_WAKEUP_LSB 2 +#define SOC_SDIO_WRAPPER_WAKEUP_MASK 0x00000004 +#define SOC_SDIO_WRAPPER_WAKEUP_GET(x) (((x) & SOC_SDIO_WRAPPER_WAKEUP_MASK) >> SOC_SDIO_WRAPPER_WAKEUP_LSB) +#define SOC_SDIO_WRAPPER_WAKEUP_SET(x) (((x) << SOC_SDIO_WRAPPER_WAKEUP_LSB) & SOC_SDIO_WRAPPER_WAKEUP_MASK) +#define SOC_SDIO_WRAPPER_SOC_ON_MSB 1 +#define SOC_SDIO_WRAPPER_SOC_ON_LSB 1 +#define SOC_SDIO_WRAPPER_SOC_ON_MASK 0x00000002 +#define SOC_SDIO_WRAPPER_SOC_ON_GET(x) (((x) & SOC_SDIO_WRAPPER_SOC_ON_MASK) >> SOC_SDIO_WRAPPER_SOC_ON_LSB) +#define SOC_SDIO_WRAPPER_SOC_ON_SET(x) (((x) << SOC_SDIO_WRAPPER_SOC_ON_LSB) & SOC_SDIO_WRAPPER_SOC_ON_MASK) +#define SOC_SDIO_WRAPPER_ON_MSB 0 +#define SOC_SDIO_WRAPPER_ON_LSB 0 +#define SOC_SDIO_WRAPPER_ON_MASK 0x00000001 +#define SOC_SDIO_WRAPPER_ON_GET(x) (((x) & SOC_SDIO_WRAPPER_ON_MASK) >> SOC_SDIO_WRAPPER_ON_LSB) +#define SOC_SDIO_WRAPPER_ON_SET(x) (((x) << SOC_SDIO_WRAPPER_ON_LSB) & SOC_SDIO_WRAPPER_ON_MASK) + +#define SOC_INT_SLEEP_MASK_ADDRESS 0x000000cc +#define SOC_INT_SLEEP_MASK_OFFSET 0x000000cc +#define SOC_INT_SLEEP_MASK_BITMAP_MSB 31 +#define SOC_INT_SLEEP_MASK_BITMAP_LSB 0 +#define SOC_INT_SLEEP_MASK_BITMAP_MASK 0xffffffff +#define SOC_INT_SLEEP_MASK_BITMAP_GET(x) (((x) & SOC_INT_SLEEP_MASK_BITMAP_MASK) >> SOC_INT_SLEEP_MASK_BITMAP_LSB) +#define SOC_INT_SLEEP_MASK_BITMAP_SET(x) (((x) << SOC_INT_SLEEP_MASK_BITMAP_LSB) & SOC_INT_SLEEP_MASK_BITMAP_MASK) + +#define SOC_LPO_CAL_TIME_ADDRESS 0x000000d4 +#define SOC_LPO_CAL_TIME_OFFSET 0x000000d4 +#define SOC_LPO_CAL_TIME_LENGTH_MSB 13 +#define SOC_LPO_CAL_TIME_LENGTH_LSB 0 +#define SOC_LPO_CAL_TIME_LENGTH_MASK 0x00003fff +#define SOC_LPO_CAL_TIME_LENGTH_GET(x) (((x) & SOC_LPO_CAL_TIME_LENGTH_MASK) >> SOC_LPO_CAL_TIME_LENGTH_LSB) +#define SOC_LPO_CAL_TIME_LENGTH_SET(x) (((x) << SOC_LPO_CAL_TIME_LENGTH_LSB) & SOC_LPO_CAL_TIME_LENGTH_MASK) + +#define SOC_LPO_INIT_DIVIDEND_INT_ADDRESS 0x000000d8 +#define SOC_LPO_INIT_DIVIDEND_INT_OFFSET 0x000000d8 +#define SOC_LPO_INIT_DIVIDEND_INT_VALUE_MSB 23 +#define SOC_LPO_INIT_DIVIDEND_INT_VALUE_LSB 0 +#define SOC_LPO_INIT_DIVIDEND_INT_VALUE_MASK 0x00ffffff +#define SOC_LPO_INIT_DIVIDEND_INT_VALUE_GET(x) (((x) & SOC_LPO_INIT_DIVIDEND_INT_VALUE_MASK) >> SOC_LPO_INIT_DIVIDEND_INT_VALUE_LSB) +#define SOC_LPO_INIT_DIVIDEND_INT_VALUE_SET(x) (((x) << SOC_LPO_INIT_DIVIDEND_INT_VALUE_LSB) & SOC_LPO_INIT_DIVIDEND_INT_VALUE_MASK) + +#define SOC_LPO_INIT_DIVIDEND_FRACTION_ADDRESS 0x000000dc +#define SOC_LPO_INIT_DIVIDEND_FRACTION_OFFSET 0x000000dc +#define SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB 10 +#define SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB 0 +#define SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK 0x000007ff +#define SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x) (((x) & SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK) >> SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB) +#define SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x) (((x) << SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB) & SOC_LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK) + +#define SOC_LPO_CAL_ADDRESS 0x000000e0 +#define SOC_LPO_CAL_OFFSET 0x000000e0 +#define SOC_LPO_CAL_ENABLE_MSB 20 +#define SOC_LPO_CAL_ENABLE_LSB 20 +#define SOC_LPO_CAL_ENABLE_MASK 0x00100000 +#define SOC_LPO_CAL_ENABLE_GET(x) (((x) & SOC_LPO_CAL_ENABLE_MASK) >> SOC_LPO_CAL_ENABLE_LSB) +#define SOC_LPO_CAL_ENABLE_SET(x) (((x) << SOC_LPO_CAL_ENABLE_LSB) & SOC_LPO_CAL_ENABLE_MASK) +#define SOC_LPO_CAL_COUNT_MSB 19 +#define SOC_LPO_CAL_COUNT_LSB 0 +#define SOC_LPO_CAL_COUNT_MASK 0x000fffff +#define SOC_LPO_CAL_COUNT_GET(x) (((x) & SOC_LPO_CAL_COUNT_MASK) >> SOC_LPO_CAL_COUNT_LSB) +#define SOC_LPO_CAL_COUNT_SET(x) (((x) << SOC_LPO_CAL_COUNT_LSB) & SOC_LPO_CAL_COUNT_MASK) + +#define SOC_LPO_CAL_TEST_CONTROL_ADDRESS 0x000000e4 +#define SOC_LPO_CAL_TEST_CONTROL_OFFSET 0x000000e4 +#define SOC_LPO_CAL_TEST_CONTROL_ENABLE_MSB 16 +#define SOC_LPO_CAL_TEST_CONTROL_ENABLE_LSB 16 +#define SOC_LPO_CAL_TEST_CONTROL_ENABLE_MASK 0x00010000 +#define SOC_LPO_CAL_TEST_CONTROL_ENABLE_GET(x) (((x) & SOC_LPO_CAL_TEST_CONTROL_ENABLE_MASK) >> SOC_LPO_CAL_TEST_CONTROL_ENABLE_LSB) +#define SOC_LPO_CAL_TEST_CONTROL_ENABLE_SET(x) (((x) << SOC_LPO_CAL_TEST_CONTROL_ENABLE_LSB) & SOC_LPO_CAL_TEST_CONTROL_ENABLE_MASK) +#define SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_MSB 15 +#define SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_LSB 0 +#define SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_MASK 0x0000ffff +#define SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_GET(x) (((x) & SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_MASK) >> SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_LSB) +#define SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_SET(x) (((x) << SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_LSB) & SOC_LPO_CAL_TEST_CONTROL_RTC_CYCLES_MASK) + +#define SOC_LPO_CAL_TEST_STATUS_ADDRESS 0x000000e8 +#define SOC_LPO_CAL_TEST_STATUS_OFFSET 0x000000e8 +#define SOC_LPO_CAL_TEST_STATUS_READY_MSB 16 +#define SOC_LPO_CAL_TEST_STATUS_READY_LSB 16 +#define SOC_LPO_CAL_TEST_STATUS_READY_MASK 0x00010000 +#define SOC_LPO_CAL_TEST_STATUS_READY_GET(x) (((x) & SOC_LPO_CAL_TEST_STATUS_READY_MASK) >> SOC_LPO_CAL_TEST_STATUS_READY_LSB) +#define SOC_LPO_CAL_TEST_STATUS_READY_SET(x) (((x) << SOC_LPO_CAL_TEST_STATUS_READY_LSB) & SOC_LPO_CAL_TEST_STATUS_READY_MASK) +#define SOC_LPO_CAL_TEST_STATUS_COUNT_MSB 15 +#define SOC_LPO_CAL_TEST_STATUS_COUNT_LSB 0 +#define SOC_LPO_CAL_TEST_STATUS_COUNT_MASK 0x0000ffff +#define SOC_LPO_CAL_TEST_STATUS_COUNT_GET(x) (((x) & SOC_LPO_CAL_TEST_STATUS_COUNT_MASK) >> SOC_LPO_CAL_TEST_STATUS_COUNT_LSB) +#define SOC_LPO_CAL_TEST_STATUS_COUNT_SET(x) (((x) << SOC_LPO_CAL_TEST_STATUS_COUNT_LSB) & SOC_LPO_CAL_TEST_STATUS_COUNT_MASK) + +#define LEGACY_SOC_CHIP_ID_ADDRESS 0x000000ec +#define LEGACY_SOC_CHIP_ID_OFFSET 0x000000ec +#define LEGACY_SOC_CHIP_ID_DEVICE_ID_MSB 31 +#define LEGACY_SOC_CHIP_ID_DEVICE_ID_LSB 16 +#define LEGACY_SOC_CHIP_ID_DEVICE_ID_MASK 0xffff0000 +#define LEGACY_SOC_CHIP_ID_DEVICE_ID_GET(x) (((x) & LEGACY_SOC_CHIP_ID_DEVICE_ID_MASK) >> LEGACY_SOC_CHIP_ID_DEVICE_ID_LSB) +#define LEGACY_SOC_CHIP_ID_DEVICE_ID_SET(x) (((x) << LEGACY_SOC_CHIP_ID_DEVICE_ID_LSB) & LEGACY_SOC_CHIP_ID_DEVICE_ID_MASK) +#define LEGACY_SOC_CHIP_ID_CONFIG_ID_MSB 15 +#define LEGACY_SOC_CHIP_ID_CONFIG_ID_LSB 4 +#define LEGACY_SOC_CHIP_ID_CONFIG_ID_MASK 0x0000fff0 +#define LEGACY_SOC_CHIP_ID_CONFIG_ID_GET(x) (((x) & LEGACY_SOC_CHIP_ID_CONFIG_ID_MASK) >> LEGACY_SOC_CHIP_ID_CONFIG_ID_LSB) +#define LEGACY_SOC_CHIP_ID_CONFIG_ID_SET(x) (((x) << LEGACY_SOC_CHIP_ID_CONFIG_ID_LSB) & LEGACY_SOC_CHIP_ID_CONFIG_ID_MASK) +#define LEGACY_SOC_CHIP_ID_VERSION_ID_MSB 3 +#define LEGACY_SOC_CHIP_ID_VERSION_ID_LSB 0 +#define LEGACY_SOC_CHIP_ID_VERSION_ID_MASK 0x0000000f +#define LEGACY_SOC_CHIP_ID_VERSION_ID_GET(x) (((x) & LEGACY_SOC_CHIP_ID_VERSION_ID_MASK) >> LEGACY_SOC_CHIP_ID_VERSION_ID_LSB) +#define LEGACY_SOC_CHIP_ID_VERSION_ID_SET(x) (((x) << LEGACY_SOC_CHIP_ID_VERSION_ID_LSB) & LEGACY_SOC_CHIP_ID_VERSION_ID_MASK) + +#define SOC_CHIP_ID_ADDRESS 0x000000f0 +#define SOC_CHIP_ID_OFFSET 0x000000f0 +#define SOC_CHIP_ID_DEVICE_ID_MSB 31 +#define SOC_CHIP_ID_DEVICE_ID_LSB 16 +#define SOC_CHIP_ID_DEVICE_ID_MASK 0xffff0000 +#define SOC_CHIP_ID_DEVICE_ID_GET(x) (((x) & SOC_CHIP_ID_DEVICE_ID_MASK) >> SOC_CHIP_ID_DEVICE_ID_LSB) +#define SOC_CHIP_ID_DEVICE_ID_SET(x) (((x) << SOC_CHIP_ID_DEVICE_ID_LSB) & SOC_CHIP_ID_DEVICE_ID_MASK) +#define SOC_CHIP_ID_CONFIG_ID_MSB 15 +#define SOC_CHIP_ID_CONFIG_ID_LSB 4 +#define SOC_CHIP_ID_CONFIG_ID_MASK 0x0000fff0 +#define SOC_CHIP_ID_CONFIG_ID_GET(x) (((x) & SOC_CHIP_ID_CONFIG_ID_MASK) >> SOC_CHIP_ID_CONFIG_ID_LSB) +#define SOC_CHIP_ID_CONFIG_ID_SET(x) (((x) << SOC_CHIP_ID_CONFIG_ID_LSB) & SOC_CHIP_ID_CONFIG_ID_MASK) +#define SOC_CHIP_ID_VERSION_ID_MSB 3 +#define SOC_CHIP_ID_VERSION_ID_LSB 0 +#define SOC_CHIP_ID_VERSION_ID_MASK 0x0000000f +#define SOC_CHIP_ID_VERSION_ID_GET(x) (((x) & SOC_CHIP_ID_VERSION_ID_MASK) >> SOC_CHIP_ID_VERSION_ID_LSB) +#define SOC_CHIP_ID_VERSION_ID_SET(x) (((x) << SOC_CHIP_ID_VERSION_ID_LSB) & SOC_CHIP_ID_VERSION_ID_MASK) + +#define SOC_POWER_REG_ADDRESS 0x0000010c +#define SOC_POWER_REG_OFFSET 0x0000010c +#define SOC_POWER_REG_DISCON_MODE_EN_MSB 16 +#define SOC_POWER_REG_DISCON_MODE_EN_LSB 16 +#define SOC_POWER_REG_DISCON_MODE_EN_MASK 0x00010000 +#define SOC_POWER_REG_DISCON_MODE_EN_GET(x) (((x) & SOC_POWER_REG_DISCON_MODE_EN_MASK) >> SOC_POWER_REG_DISCON_MODE_EN_LSB) +#define SOC_POWER_REG_DISCON_MODE_EN_SET(x) (((x) << SOC_POWER_REG_DISCON_MODE_EN_LSB) & SOC_POWER_REG_DISCON_MODE_EN_MASK) +#define SOC_POWER_REG_DEEP_SLEEP_EN_MSB 15 +#define SOC_POWER_REG_DEEP_SLEEP_EN_LSB 15 +#define SOC_POWER_REG_DEEP_SLEEP_EN_MASK 0x00008000 +#define SOC_POWER_REG_DEEP_SLEEP_EN_GET(x) (((x) & SOC_POWER_REG_DEEP_SLEEP_EN_MASK) >> SOC_POWER_REG_DEEP_SLEEP_EN_LSB) +#define SOC_POWER_REG_DEEP_SLEEP_EN_SET(x) (((x) << SOC_POWER_REG_DEEP_SLEEP_EN_LSB) & SOC_POWER_REG_DEEP_SLEEP_EN_MASK) +#define SOC_POWER_REG_DEBUG_EN_MSB 14 +#define SOC_POWER_REG_DEBUG_EN_LSB 14 +#define SOC_POWER_REG_DEBUG_EN_MASK 0x00004000 +#define SOC_POWER_REG_DEBUG_EN_GET(x) (((x) & SOC_POWER_REG_DEBUG_EN_MASK) >> SOC_POWER_REG_DEBUG_EN_LSB) +#define SOC_POWER_REG_DEBUG_EN_SET(x) (((x) << SOC_POWER_REG_DEBUG_EN_LSB) & SOC_POWER_REG_DEBUG_EN_MASK) +#define SOC_POWER_REG_WLAN_BB_PWD_EN_MSB 13 +#define SOC_POWER_REG_WLAN_BB_PWD_EN_LSB 13 +#define SOC_POWER_REG_WLAN_BB_PWD_EN_MASK 0x00002000 +#define SOC_POWER_REG_WLAN_BB_PWD_EN_GET(x) (((x) & SOC_POWER_REG_WLAN_BB_PWD_EN_MASK) >> SOC_POWER_REG_WLAN_BB_PWD_EN_LSB) +#define SOC_POWER_REG_WLAN_BB_PWD_EN_SET(x) (((x) << SOC_POWER_REG_WLAN_BB_PWD_EN_LSB) & SOC_POWER_REG_WLAN_BB_PWD_EN_MASK) +#define SOC_POWER_REG_WLAN_MAC_PWD_EN_MSB 12 +#define SOC_POWER_REG_WLAN_MAC_PWD_EN_LSB 12 +#define SOC_POWER_REG_WLAN_MAC_PWD_EN_MASK 0x00001000 +#define SOC_POWER_REG_WLAN_MAC_PWD_EN_GET(x) (((x) & SOC_POWER_REG_WLAN_MAC_PWD_EN_MASK) >> SOC_POWER_REG_WLAN_MAC_PWD_EN_LSB) +#define SOC_POWER_REG_WLAN_MAC_PWD_EN_SET(x) (((x) << SOC_POWER_REG_WLAN_MAC_PWD_EN_LSB) & SOC_POWER_REG_WLAN_MAC_PWD_EN_MASK) +#define SOC_POWER_REG_CPU_INT_ENABLE_MSB 7 +#define SOC_POWER_REG_CPU_INT_ENABLE_LSB 7 +#define SOC_POWER_REG_CPU_INT_ENABLE_MASK 0x00000080 +#define SOC_POWER_REG_CPU_INT_ENABLE_GET(x) (((x) & SOC_POWER_REG_CPU_INT_ENABLE_MASK) >> SOC_POWER_REG_CPU_INT_ENABLE_LSB) +#define SOC_POWER_REG_CPU_INT_ENABLE_SET(x) (((x) << SOC_POWER_REG_CPU_INT_ENABLE_LSB) & SOC_POWER_REG_CPU_INT_ENABLE_MASK) +#define SOC_POWER_REG_WLAN_ISO_DIS_MSB 6 +#define SOC_POWER_REG_WLAN_ISO_DIS_LSB 6 +#define SOC_POWER_REG_WLAN_ISO_DIS_MASK 0x00000040 +#define SOC_POWER_REG_WLAN_ISO_DIS_GET(x) (((x) & SOC_POWER_REG_WLAN_ISO_DIS_MASK) >> SOC_POWER_REG_WLAN_ISO_DIS_LSB) +#define SOC_POWER_REG_WLAN_ISO_DIS_SET(x) (((x) << SOC_POWER_REG_WLAN_ISO_DIS_LSB) & SOC_POWER_REG_WLAN_ISO_DIS_MASK) +#define SOC_POWER_REG_WLAN_ISO_CNTL_MSB 5 +#define SOC_POWER_REG_WLAN_ISO_CNTL_LSB 5 +#define SOC_POWER_REG_WLAN_ISO_CNTL_MASK 0x00000020 +#define SOC_POWER_REG_WLAN_ISO_CNTL_GET(x) (((x) & SOC_POWER_REG_WLAN_ISO_CNTL_MASK) >> SOC_POWER_REG_WLAN_ISO_CNTL_LSB) +#define SOC_POWER_REG_WLAN_ISO_CNTL_SET(x) (((x) << SOC_POWER_REG_WLAN_ISO_CNTL_LSB) & SOC_POWER_REG_WLAN_ISO_CNTL_MASK) +#define SOC_POWER_REG_RADIO_PWD_EN_MSB 4 +#define SOC_POWER_REG_RADIO_PWD_EN_LSB 4 +#define SOC_POWER_REG_RADIO_PWD_EN_MASK 0x00000010 +#define SOC_POWER_REG_RADIO_PWD_EN_GET(x) (((x) & SOC_POWER_REG_RADIO_PWD_EN_MASK) >> SOC_POWER_REG_RADIO_PWD_EN_LSB) +#define SOC_POWER_REG_RADIO_PWD_EN_SET(x) (((x) << SOC_POWER_REG_RADIO_PWD_EN_LSB) & SOC_POWER_REG_RADIO_PWD_EN_MASK) +#define SOC_POWER_REG_SOC_ISO_EN_MSB 3 +#define SOC_POWER_REG_SOC_ISO_EN_LSB 3 +#define SOC_POWER_REG_SOC_ISO_EN_MASK 0x00000008 +#define SOC_POWER_REG_SOC_ISO_EN_GET(x) (((x) & SOC_POWER_REG_SOC_ISO_EN_MASK) >> SOC_POWER_REG_SOC_ISO_EN_LSB) +#define SOC_POWER_REG_SOC_ISO_EN_SET(x) (((x) << SOC_POWER_REG_SOC_ISO_EN_LSB) & SOC_POWER_REG_SOC_ISO_EN_MASK) +#define SOC_POWER_REG_WLAN_ISO_EN_MSB 2 +#define SOC_POWER_REG_WLAN_ISO_EN_LSB 2 +#define SOC_POWER_REG_WLAN_ISO_EN_MASK 0x00000004 +#define SOC_POWER_REG_WLAN_ISO_EN_GET(x) (((x) & SOC_POWER_REG_WLAN_ISO_EN_MASK) >> SOC_POWER_REG_WLAN_ISO_EN_LSB) +#define SOC_POWER_REG_WLAN_ISO_EN_SET(x) (((x) << SOC_POWER_REG_WLAN_ISO_EN_LSB) & SOC_POWER_REG_WLAN_ISO_EN_MASK) +#define SOC_POWER_REG_WLAN_PWD_EN_MSB 1 +#define SOC_POWER_REG_WLAN_PWD_EN_LSB 1 +#define SOC_POWER_REG_WLAN_PWD_EN_MASK 0x00000002 +#define SOC_POWER_REG_WLAN_PWD_EN_GET(x) (((x) & SOC_POWER_REG_WLAN_PWD_EN_MASK) >> SOC_POWER_REG_WLAN_PWD_EN_LSB) +#define SOC_POWER_REG_WLAN_PWD_EN_SET(x) (((x) << SOC_POWER_REG_WLAN_PWD_EN_LSB) & SOC_POWER_REG_WLAN_PWD_EN_MASK) +#define SOC_POWER_REG_POWER_EN_MSB 0 +#define SOC_POWER_REG_POWER_EN_LSB 0 +#define SOC_POWER_REG_POWER_EN_MASK 0x00000001 +#define SOC_POWER_REG_POWER_EN_GET(x) (((x) & SOC_POWER_REG_POWER_EN_MASK) >> SOC_POWER_REG_POWER_EN_LSB) +#define SOC_POWER_REG_POWER_EN_SET(x) (((x) << SOC_POWER_REG_POWER_EN_LSB) & SOC_POWER_REG_POWER_EN_MASK) + +#define SOC_CORE_CLK_CTRL_ADDRESS 0x00000110 +#define SOC_CORE_CLK_CTRL_OFFSET 0x00000110 +#define SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define SOC_CORE_CLK_CTRL_DIV_GET(x) (((x) & SOC_CORE_CLK_CTRL_DIV_MASK) >> SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_SET(x) (((x) << SOC_CORE_CLK_CTRL_DIV_LSB) & SOC_CORE_CLK_CTRL_DIV_MASK) + +#define SOC_GPIO_WAKEUP_CONTROL_ADDRESS 0x00000114 +#define SOC_GPIO_WAKEUP_CONTROL_OFFSET 0x00000114 +#define SOC_GPIO_WAKEUP_CONTROL_ENABLE_MSB 0 +#define SOC_GPIO_WAKEUP_CONTROL_ENABLE_LSB 0 +#define SOC_GPIO_WAKEUP_CONTROL_ENABLE_MASK 0x00000001 +#define SOC_GPIO_WAKEUP_CONTROL_ENABLE_GET(x) (((x) & SOC_GPIO_WAKEUP_CONTROL_ENABLE_MASK) >> SOC_GPIO_WAKEUP_CONTROL_ENABLE_LSB) +#define SOC_GPIO_WAKEUP_CONTROL_ENABLE_SET(x) (((x) << SOC_GPIO_WAKEUP_CONTROL_ENABLE_LSB) & SOC_GPIO_WAKEUP_CONTROL_ENABLE_MASK) + +#define SLEEP_RETENTION_ADDRESS 0x00000214 +#define SLEEP_RETENTION_OFFSET 0x00000214 +#define SLEEP_RETENTION_GREEN_SAVE_MSB 10 +#define SLEEP_RETENTION_GREEN_SAVE_LSB 10 +#define SLEEP_RETENTION_GREEN_SAVE_MASK 0x00000400 +#define SLEEP_RETENTION_GREEN_SAVE_GET(x) (((x) & SLEEP_RETENTION_GREEN_SAVE_MASK) >> SLEEP_RETENTION_GREEN_SAVE_LSB) +#define SLEEP_RETENTION_GREEN_SAVE_SET(x) (((x) << SLEEP_RETENTION_GREEN_SAVE_LSB) & SLEEP_RETENTION_GREEN_SAVE_MASK) +#define SLEEP_RETENTION_TIME_MSB 9 +#define SLEEP_RETENTION_TIME_LSB 2 +#define SLEEP_RETENTION_TIME_MASK 0x000003fc +#define SLEEP_RETENTION_TIME_GET(x) (((x) & SLEEP_RETENTION_TIME_MASK) >> SLEEP_RETENTION_TIME_LSB) +#define SLEEP_RETENTION_TIME_SET(x) (((x) << SLEEP_RETENTION_TIME_LSB) & SLEEP_RETENTION_TIME_MASK) +#define SLEEP_RETENTION_MODE_MSB 1 +#define SLEEP_RETENTION_MODE_LSB 1 +#define SLEEP_RETENTION_MODE_MASK 0x00000002 +#define SLEEP_RETENTION_MODE_GET(x) (((x) & SLEEP_RETENTION_MODE_MASK) >> SLEEP_RETENTION_MODE_LSB) +#define SLEEP_RETENTION_MODE_SET(x) (((x) << SLEEP_RETENTION_MODE_LSB) & SLEEP_RETENTION_MODE_MASK) +#define SLEEP_RETENTION_ENABLE_MSB 0 +#define SLEEP_RETENTION_ENABLE_LSB 0 +#define SLEEP_RETENTION_ENABLE_MASK 0x00000001 +#define SLEEP_RETENTION_ENABLE_GET(x) (((x) & SLEEP_RETENTION_ENABLE_MASK) >> SLEEP_RETENTION_ENABLE_LSB) +#define SLEEP_RETENTION_ENABLE_SET(x) (((x) << SLEEP_RETENTION_ENABLE_LSB) & SLEEP_RETENTION_ENABLE_MASK) + +#define LP_PERF_COUNTER_ADDRESS 0x00000284 +#define LP_PERF_COUNTER_OFFSET 0x00000284 +#define LP_PERF_COUNTER_EN_MSB 0 +#define LP_PERF_COUNTER_EN_LSB 0 +#define LP_PERF_COUNTER_EN_MASK 0x00000001 +#define LP_PERF_COUNTER_EN_GET(x) (((x) & LP_PERF_COUNTER_EN_MASK) >> LP_PERF_COUNTER_EN_LSB) +#define LP_PERF_COUNTER_EN_SET(x) (((x) << LP_PERF_COUNTER_EN_LSB) & LP_PERF_COUNTER_EN_MASK) + +#define LP_PERF_LIGHT_SLEEP_ADDRESS 0x00000288 +#define LP_PERF_LIGHT_SLEEP_OFFSET 0x00000288 +#define LP_PERF_LIGHT_SLEEP_CNT_MSB 31 +#define LP_PERF_LIGHT_SLEEP_CNT_LSB 0 +#define LP_PERF_LIGHT_SLEEP_CNT_MASK 0xffffffff +#define LP_PERF_LIGHT_SLEEP_CNT_GET(x) (((x) & LP_PERF_LIGHT_SLEEP_CNT_MASK) >> LP_PERF_LIGHT_SLEEP_CNT_LSB) +#define LP_PERF_LIGHT_SLEEP_CNT_SET(x) (((x) << LP_PERF_LIGHT_SLEEP_CNT_LSB) & LP_PERF_LIGHT_SLEEP_CNT_MASK) + +#define LP_PERF_DEEP_SLEEP_ADDRESS 0x0000028c +#define LP_PERF_DEEP_SLEEP_OFFSET 0x0000028c +#define LP_PERF_DEEP_SLEEP_CNT_MSB 31 +#define LP_PERF_DEEP_SLEEP_CNT_LSB 0 +#define LP_PERF_DEEP_SLEEP_CNT_MASK 0xffffffff +#define LP_PERF_DEEP_SLEEP_CNT_GET(x) (((x) & LP_PERF_DEEP_SLEEP_CNT_MASK) >> LP_PERF_DEEP_SLEEP_CNT_LSB) +#define LP_PERF_DEEP_SLEEP_CNT_SET(x) (((x) << LP_PERF_DEEP_SLEEP_CNT_LSB) & LP_PERF_DEEP_SLEEP_CNT_MASK) + +#define LP_PERF_ON_ADDRESS 0x00000290 +#define LP_PERF_ON_OFFSET 0x00000290 +#define LP_PERF_ON_CNT_MSB 31 +#define LP_PERF_ON_CNT_LSB 0 +#define LP_PERF_ON_CNT_MASK 0xffffffff +#define LP_PERF_ON_CNT_GET(x) (((x) & LP_PERF_ON_CNT_MASK) >> LP_PERF_ON_CNT_LSB) +#define LP_PERF_ON_CNT_SET(x) (((x) << LP_PERF_ON_CNT_LSB) & LP_PERF_ON_CNT_MASK) + +#define CHIP_MODE_ADDRESS 0x000002a8 +#define CHIP_MODE_OFFSET 0x000002a8 +#define CHIP_MODE_BIT_MSB 1 +#define CHIP_MODE_BIT_LSB 0 +#define CHIP_MODE_BIT_MASK 0x00000003 +#define CHIP_MODE_BIT_GET(x) (((x) & CHIP_MODE_BIT_MASK) >> CHIP_MODE_BIT_LSB) +#define CHIP_MODE_BIT_SET(x) (((x) << CHIP_MODE_BIT_LSB) & CHIP_MODE_BIT_MASK) + +#define CLK_REQ_FALL_EDGE_ADDRESS 0x000002ac +#define CLK_REQ_FALL_EDGE_OFFSET 0x000002ac +#define CLK_REQ_FALL_EDGE_EN_MSB 31 +#define CLK_REQ_FALL_EDGE_EN_LSB 31 +#define CLK_REQ_FALL_EDGE_EN_MASK 0x80000000 +#define CLK_REQ_FALL_EDGE_EN_GET(x) (((x) & CLK_REQ_FALL_EDGE_EN_MASK) >> CLK_REQ_FALL_EDGE_EN_LSB) +#define CLK_REQ_FALL_EDGE_EN_SET(x) (((x) << CLK_REQ_FALL_EDGE_EN_LSB) & CLK_REQ_FALL_EDGE_EN_MASK) +#define CLK_REQ_FALL_EDGE_DELAY_MSB 7 +#define CLK_REQ_FALL_EDGE_DELAY_LSB 0 +#define CLK_REQ_FALL_EDGE_DELAY_MASK 0x000000ff +#define CLK_REQ_FALL_EDGE_DELAY_GET(x) (((x) & CLK_REQ_FALL_EDGE_DELAY_MASK) >> CLK_REQ_FALL_EDGE_DELAY_LSB) +#define CLK_REQ_FALL_EDGE_DELAY_SET(x) (((x) << CLK_REQ_FALL_EDGE_DELAY_LSB) & CLK_REQ_FALL_EDGE_DELAY_MASK) + +#define OTP_ADDRESS 0x000002b0 +#define OTP_OFFSET 0x000002b0 +#define OTP_LDO25_EN_MSB 1 +#define OTP_LDO25_EN_LSB 1 +#define OTP_LDO25_EN_MASK 0x00000002 +#define OTP_LDO25_EN_GET(x) (((x) & OTP_LDO25_EN_MASK) >> OTP_LDO25_EN_LSB) +#define OTP_LDO25_EN_SET(x) (((x) << OTP_LDO25_EN_LSB) & OTP_LDO25_EN_MASK) +#define OTP_VDD12_EN_MSB 0 +#define OTP_VDD12_EN_LSB 0 +#define OTP_VDD12_EN_MASK 0x00000001 +#define OTP_VDD12_EN_GET(x) (((x) & OTP_VDD12_EN_MASK) >> OTP_VDD12_EN_LSB) +#define OTP_VDD12_EN_SET(x) (((x) << OTP_VDD12_EN_LSB) & OTP_VDD12_EN_MASK) + +#define OTP_STATUS_ADDRESS 0x000002b4 +#define OTP_STATUS_OFFSET 0x000002b4 +#define OTP_STATUS_LDO25_EN_READY_MSB 1 +#define OTP_STATUS_LDO25_EN_READY_LSB 1 +#define OTP_STATUS_LDO25_EN_READY_MASK 0x00000002 +#define OTP_STATUS_LDO25_EN_READY_GET(x) (((x) & OTP_STATUS_LDO25_EN_READY_MASK) >> OTP_STATUS_LDO25_EN_READY_LSB) +#define OTP_STATUS_LDO25_EN_READY_SET(x) (((x) << OTP_STATUS_LDO25_EN_READY_LSB) & OTP_STATUS_LDO25_EN_READY_MASK) +#define OTP_STATUS_VDD12_EN_READY_MSB 0 +#define OTP_STATUS_VDD12_EN_READY_LSB 0 +#define OTP_STATUS_VDD12_EN_READY_MASK 0x00000001 +#define OTP_STATUS_VDD12_EN_READY_GET(x) (((x) & OTP_STATUS_VDD12_EN_READY_MASK) >> OTP_STATUS_VDD12_EN_READY_LSB) +#define OTP_STATUS_VDD12_EN_READY_SET(x) (((x) << OTP_STATUS_VDD12_EN_READY_LSB) & OTP_STATUS_VDD12_EN_READY_MASK) + +#define PMU_ADDRESS 0x000002b8 +#define PMU_OFFSET 0x000002b8 +#define PMU_REG_WAKEUP_TIME_SEL_MSB 1 +#define PMU_REG_WAKEUP_TIME_SEL_LSB 0 +#define PMU_REG_WAKEUP_TIME_SEL_MASK 0x00000003 +#define PMU_REG_WAKEUP_TIME_SEL_GET(x) (((x) & PMU_REG_WAKEUP_TIME_SEL_MASK) >> PMU_REG_WAKEUP_TIME_SEL_LSB) +#define PMU_REG_WAKEUP_TIME_SEL_SET(x) (((x) << PMU_REG_WAKEUP_TIME_SEL_LSB) & PMU_REG_WAKEUP_TIME_SEL_MASK) + +#define PMU_CONFIG_ADDRESS 0x000002bc +#define PMU_CONFIG_OFFSET 0x000002bc +#define PMU_CONFIG_VALUE_MSB 4 +#define PMU_CONFIG_VALUE_LSB 0 +#define PMU_CONFIG_VALUE_MASK 0x0000001f +#define PMU_CONFIG_VALUE_GET(x) (((x) & PMU_CONFIG_VALUE_MASK) >> PMU_CONFIG_VALUE_LSB) +#define PMU_CONFIG_VALUE_SET(x) (((x) << PMU_CONFIG_VALUE_LSB) & PMU_CONFIG_VALUE_MASK) + +#define PMU_PAREG_ADDRESS 0x000002c0 +#define PMU_PAREG_OFFSET 0x000002c0 +#define PMU_PAREG_LVL_CTR_MSB 2 +#define PMU_PAREG_LVL_CTR_LSB 0 +#define PMU_PAREG_LVL_CTR_MASK 0x00000007 +#define PMU_PAREG_LVL_CTR_GET(x) (((x) & PMU_PAREG_LVL_CTR_MASK) >> PMU_PAREG_LVL_CTR_LSB) +#define PMU_PAREG_LVL_CTR_SET(x) (((x) << PMU_PAREG_LVL_CTR_LSB) & PMU_PAREG_LVL_CTR_MASK) + +#define PMU_BYPASS_ADDRESS 0x000002c4 +#define PMU_BYPASS_OFFSET 0x000002c4 +#define PMU_BYPASS_SWREG_MSB 2 +#define PMU_BYPASS_SWREG_LSB 2 +#define PMU_BYPASS_SWREG_MASK 0x00000004 +#define PMU_BYPASS_SWREG_GET(x) (((x) & PMU_BYPASS_SWREG_MASK) >> PMU_BYPASS_SWREG_LSB) +#define PMU_BYPASS_SWREG_SET(x) (((x) << PMU_BYPASS_SWREG_LSB) & PMU_BYPASS_SWREG_MASK) +#define PMU_BYPASS_DREG_MSB 1 +#define PMU_BYPASS_DREG_LSB 1 +#define PMU_BYPASS_DREG_MASK 0x00000002 +#define PMU_BYPASS_DREG_GET(x) (((x) & PMU_BYPASS_DREG_MASK) >> PMU_BYPASS_DREG_LSB) +#define PMU_BYPASS_DREG_SET(x) (((x) << PMU_BYPASS_DREG_LSB) & PMU_BYPASS_DREG_MASK) +#define PMU_BYPASS_PAREG_MSB 0 +#define PMU_BYPASS_PAREG_LSB 0 +#define PMU_BYPASS_PAREG_MASK 0x00000001 +#define PMU_BYPASS_PAREG_GET(x) (((x) & PMU_BYPASS_PAREG_MASK) >> PMU_BYPASS_PAREG_LSB) +#define PMU_BYPASS_PAREG_SET(x) (((x) << PMU_BYPASS_PAREG_LSB) & PMU_BYPASS_PAREG_MASK) + +#define THERM_CTRL1_ADDRESS 0x000002dc +#define THERM_CTRL1_OFFSET 0x000002dc +#define THERM_CTRL1_BYPASS_MSB 16 +#define THERM_CTRL1_BYPASS_LSB 16 +#define THERM_CTRL1_BYPASS_MASK 0x00010000 +#define THERM_CTRL1_BYPASS_GET(x) (((x) & THERM_CTRL1_BYPASS_MASK) >> THERM_CTRL1_BYPASS_LSB) +#define THERM_CTRL1_BYPASS_SET(x) (((x) << THERM_CTRL1_BYPASS_LSB) & THERM_CTRL1_BYPASS_MASK) +#define THERM_CTRL1_WIDTH_ARBITOR_MSB 15 +#define THERM_CTRL1_WIDTH_ARBITOR_LSB 12 +#define THERM_CTRL1_WIDTH_ARBITOR_MASK 0x0000f000 +#define THERM_CTRL1_WIDTH_ARBITOR_GET(x) (((x) & THERM_CTRL1_WIDTH_ARBITOR_MASK) >> THERM_CTRL1_WIDTH_ARBITOR_LSB) +#define THERM_CTRL1_WIDTH_ARBITOR_SET(x) (((x) << THERM_CTRL1_WIDTH_ARBITOR_LSB) & THERM_CTRL1_WIDTH_ARBITOR_MASK) +#define THERM_CTRL1_WIDTH_MSB 11 +#define THERM_CTRL1_WIDTH_LSB 5 +#define THERM_CTRL1_WIDTH_MASK 0x00000fe0 +#define THERM_CTRL1_WIDTH_GET(x) (((x) & THERM_CTRL1_WIDTH_MASK) >> THERM_CTRL1_WIDTH_LSB) +#define THERM_CTRL1_WIDTH_SET(x) (((x) << THERM_CTRL1_WIDTH_LSB) & THERM_CTRL1_WIDTH_MASK) +#define THERM_CTRL1_TYPE_MSB 4 +#define THERM_CTRL1_TYPE_LSB 3 +#define THERM_CTRL1_TYPE_MASK 0x00000018 +#define THERM_CTRL1_TYPE_GET(x) (((x) & THERM_CTRL1_TYPE_MASK) >> THERM_CTRL1_TYPE_LSB) +#define THERM_CTRL1_TYPE_SET(x) (((x) << THERM_CTRL1_TYPE_LSB) & THERM_CTRL1_TYPE_MASK) +#define THERM_CTRL1_MEASURE_MSB 2 +#define THERM_CTRL1_MEASURE_LSB 2 +#define THERM_CTRL1_MEASURE_MASK 0x00000004 +#define THERM_CTRL1_MEASURE_GET(x) (((x) & THERM_CTRL1_MEASURE_MASK) >> THERM_CTRL1_MEASURE_LSB) +#define THERM_CTRL1_MEASURE_SET(x) (((x) << THERM_CTRL1_MEASURE_LSB) & THERM_CTRL1_MEASURE_MASK) +#define THERM_CTRL1_INT_EN_MSB 1 +#define THERM_CTRL1_INT_EN_LSB 1 +#define THERM_CTRL1_INT_EN_MASK 0x00000002 +#define THERM_CTRL1_INT_EN_GET(x) (((x) & THERM_CTRL1_INT_EN_MASK) >> THERM_CTRL1_INT_EN_LSB) +#define THERM_CTRL1_INT_EN_SET(x) (((x) << THERM_CTRL1_INT_EN_LSB) & THERM_CTRL1_INT_EN_MASK) +#define THERM_CTRL1_INT_STATUS_MSB 0 +#define THERM_CTRL1_INT_STATUS_LSB 0 +#define THERM_CTRL1_INT_STATUS_MASK 0x00000001 +#define THERM_CTRL1_INT_STATUS_GET(x) (((x) & THERM_CTRL1_INT_STATUS_MASK) >> THERM_CTRL1_INT_STATUS_LSB) +#define THERM_CTRL1_INT_STATUS_SET(x) (((x) << THERM_CTRL1_INT_STATUS_LSB) & THERM_CTRL1_INT_STATUS_MASK) + +#define THERM_CTRL2_ADDRESS 0x000002e0 +#define THERM_CTRL2_OFFSET 0x000002e0 +#define THERM_CTRL2_ADC_OFF_MSB 25 +#define THERM_CTRL2_ADC_OFF_LSB 25 +#define THERM_CTRL2_ADC_OFF_MASK 0x02000000 +#define THERM_CTRL2_ADC_OFF_GET(x) (((x) & THERM_CTRL2_ADC_OFF_MASK) >> THERM_CTRL2_ADC_OFF_LSB) +#define THERM_CTRL2_ADC_OFF_SET(x) (((x) << THERM_CTRL2_ADC_OFF_LSB) & THERM_CTRL2_ADC_OFF_MASK) +#define THERM_CTRL2_ADC_ON_MSB 24 +#define THERM_CTRL2_ADC_ON_LSB 24 +#define THERM_CTRL2_ADC_ON_MASK 0x01000000 +#define THERM_CTRL2_ADC_ON_GET(x) (((x) & THERM_CTRL2_ADC_ON_MASK) >> THERM_CTRL2_ADC_ON_LSB) +#define THERM_CTRL2_ADC_ON_SET(x) (((x) << THERM_CTRL2_ADC_ON_LSB) & THERM_CTRL2_ADC_ON_MASK) +#define THERM_CTRL2_SAMPLE_MSB 23 +#define THERM_CTRL2_SAMPLE_LSB 16 +#define THERM_CTRL2_SAMPLE_MASK 0x00ff0000 +#define THERM_CTRL2_SAMPLE_GET(x) (((x) & THERM_CTRL2_SAMPLE_MASK) >> THERM_CTRL2_SAMPLE_LSB) +#define THERM_CTRL2_SAMPLE_SET(x) (((x) << THERM_CTRL2_SAMPLE_LSB) & THERM_CTRL2_SAMPLE_MASK) +#define THERM_CTRL2_HIGH_MSB 15 +#define THERM_CTRL2_HIGH_LSB 8 +#define THERM_CTRL2_HIGH_MASK 0x0000ff00 +#define THERM_CTRL2_HIGH_GET(x) (((x) & THERM_CTRL2_HIGH_MASK) >> THERM_CTRL2_HIGH_LSB) +#define THERM_CTRL2_HIGH_SET(x) (((x) << THERM_CTRL2_HIGH_LSB) & THERM_CTRL2_HIGH_MASK) +#define THERM_CTRL2_LOW_MSB 7 +#define THERM_CTRL2_LOW_LSB 0 +#define THERM_CTRL2_LOW_MASK 0x000000ff +#define THERM_CTRL2_LOW_GET(x) (((x) & THERM_CTRL2_LOW_MASK) >> THERM_CTRL2_LOW_LSB) +#define THERM_CTRL2_LOW_SET(x) (((x) << THERM_CTRL2_LOW_LSB) & THERM_CTRL2_LOW_MASK) + +#define THERM_CTRL3_ADDRESS 0x000002e4 +#define THERM_CTRL3_OFFSET 0x000002e4 +#define THERM_CTRL3_ADC_GAIN_MSB 16 +#define THERM_CTRL3_ADC_GAIN_LSB 8 +#define THERM_CTRL3_ADC_GAIN_MASK 0x0001ff00 +#define THERM_CTRL3_ADC_GAIN_GET(x) (((x) & THERM_CTRL3_ADC_GAIN_MASK) >> THERM_CTRL3_ADC_GAIN_LSB) +#define THERM_CTRL3_ADC_GAIN_SET(x) (((x) << THERM_CTRL3_ADC_GAIN_LSB) & THERM_CTRL3_ADC_GAIN_MASK) +#define THERM_CTRL3_ADC_OFFSET_MSB 7 +#define THERM_CTRL3_ADC_OFFSET_LSB 0 +#define THERM_CTRL3_ADC_OFFSET_MASK 0x000000ff +#define THERM_CTRL3_ADC_OFFSET_GET(x) (((x) & THERM_CTRL3_ADC_OFFSET_MASK) >> THERM_CTRL3_ADC_OFFSET_LSB) +#define THERM_CTRL3_ADC_OFFSET_SET(x) (((x) << THERM_CTRL3_ADC_OFFSET_LSB) & THERM_CTRL3_ADC_OFFSET_MASK) + +#define LISTEN_MODE1_ADDRESS 0x000002e8 +#define LISTEN_MODE1_OFFSET 0x000002e8 +#define LISTEN_MODE1_TIMER_CLEAR_MSB 19 +#define LISTEN_MODE1_TIMER_CLEAR_LSB 19 +#define LISTEN_MODE1_TIMER_CLEAR_MASK 0x00080000 +#define LISTEN_MODE1_TIMER_CLEAR_GET(x) (((x) & LISTEN_MODE1_TIMER_CLEAR_MASK) >> LISTEN_MODE1_TIMER_CLEAR_LSB) +#define LISTEN_MODE1_TIMER_CLEAR_SET(x) (((x) << LISTEN_MODE1_TIMER_CLEAR_LSB) & LISTEN_MODE1_TIMER_CLEAR_MASK) +#define LISTEN_MODE1_TIMER_THRESH_WAKE_MSB 18 +#define LISTEN_MODE1_TIMER_THRESH_WAKE_LSB 3 +#define LISTEN_MODE1_TIMER_THRESH_WAKE_MASK 0x0007fff8 +#define LISTEN_MODE1_TIMER_THRESH_WAKE_GET(x) (((x) & LISTEN_MODE1_TIMER_THRESH_WAKE_MASK) >> LISTEN_MODE1_TIMER_THRESH_WAKE_LSB) +#define LISTEN_MODE1_TIMER_THRESH_WAKE_SET(x) (((x) << LISTEN_MODE1_TIMER_THRESH_WAKE_LSB) & LISTEN_MODE1_TIMER_THRESH_WAKE_MASK) +#define LISTEN_MODE1_TIMER_OVERFLOW_WAKE_MSB 2 +#define LISTEN_MODE1_TIMER_OVERFLOW_WAKE_LSB 2 +#define LISTEN_MODE1_TIMER_OVERFLOW_WAKE_MASK 0x00000004 +#define LISTEN_MODE1_TIMER_OVERFLOW_WAKE_GET(x) (((x) & LISTEN_MODE1_TIMER_OVERFLOW_WAKE_MASK) >> LISTEN_MODE1_TIMER_OVERFLOW_WAKE_LSB) +#define LISTEN_MODE1_TIMER_OVERFLOW_WAKE_SET(x) (((x) << LISTEN_MODE1_TIMER_OVERFLOW_WAKE_LSB) & LISTEN_MODE1_TIMER_OVERFLOW_WAKE_MASK) +#define LISTEN_MODE1_CLOCK_GATE_MSB 1 +#define LISTEN_MODE1_CLOCK_GATE_LSB 1 +#define LISTEN_MODE1_CLOCK_GATE_MASK 0x00000002 +#define LISTEN_MODE1_CLOCK_GATE_GET(x) (((x) & LISTEN_MODE1_CLOCK_GATE_MASK) >> LISTEN_MODE1_CLOCK_GATE_LSB) +#define LISTEN_MODE1_CLOCK_GATE_SET(x) (((x) << LISTEN_MODE1_CLOCK_GATE_LSB) & LISTEN_MODE1_CLOCK_GATE_MASK) +#define LISTEN_MODE1_ENABLE_MSB 0 +#define LISTEN_MODE1_ENABLE_LSB 0 +#define LISTEN_MODE1_ENABLE_MASK 0x00000001 +#define LISTEN_MODE1_ENABLE_GET(x) (((x) & LISTEN_MODE1_ENABLE_MASK) >> LISTEN_MODE1_ENABLE_LSB) +#define LISTEN_MODE1_ENABLE_SET(x) (((x) << LISTEN_MODE1_ENABLE_LSB) & LISTEN_MODE1_ENABLE_MASK) + +#define LISTEN_MODE2_ADDRESS 0x000002ec +#define LISTEN_MODE2_OFFSET 0x000002ec +#define LISTEN_MODE2_TIMER_TRIGGER_WAKE_MSB 15 +#define LISTEN_MODE2_TIMER_TRIGGER_WAKE_LSB 0 +#define LISTEN_MODE2_TIMER_TRIGGER_WAKE_MASK 0x0000ffff +#define LISTEN_MODE2_TIMER_TRIGGER_WAKE_GET(x) (((x) & LISTEN_MODE2_TIMER_TRIGGER_WAKE_MASK) >> LISTEN_MODE2_TIMER_TRIGGER_WAKE_LSB) +#define LISTEN_MODE2_TIMER_TRIGGER_WAKE_SET(x) (((x) << LISTEN_MODE2_TIMER_TRIGGER_WAKE_LSB) & LISTEN_MODE2_TIMER_TRIGGER_WAKE_MASK) + +#define AUDIO_PLL_CONFIG_ADDRESS 0x000002f0 +#define AUDIO_PLL_CONFIG_OFFSET 0x000002f0 +#define AUDIO_PLL_CONFIG_UPDATING_MSB 31 +#define AUDIO_PLL_CONFIG_UPDATING_LSB 31 +#define AUDIO_PLL_CONFIG_UPDATING_MASK 0x80000000 +#define AUDIO_PLL_CONFIG_UPDATING_GET(x) (((x) & AUDIO_PLL_CONFIG_UPDATING_MASK) >> AUDIO_PLL_CONFIG_UPDATING_LSB) +#define AUDIO_PLL_CONFIG_UPDATING_SET(x) (((x) << AUDIO_PLL_CONFIG_UPDATING_LSB) & AUDIO_PLL_CONFIG_UPDATING_MASK) +#define AUDIO_PLL_CONFIG_EXT_DIV_MSB 14 +#define AUDIO_PLL_CONFIG_EXT_DIV_LSB 12 +#define AUDIO_PLL_CONFIG_EXT_DIV_MASK 0x00007000 +#define AUDIO_PLL_CONFIG_EXT_DIV_GET(x) (((x) & AUDIO_PLL_CONFIG_EXT_DIV_MASK) >> AUDIO_PLL_CONFIG_EXT_DIV_LSB) +#define AUDIO_PLL_CONFIG_EXT_DIV_SET(x) (((x) << AUDIO_PLL_CONFIG_EXT_DIV_LSB) & AUDIO_PLL_CONFIG_EXT_DIV_MASK) +#define AUDIO_PLL_CONFIG_POSTPLLDIV_MSB 9 +#define AUDIO_PLL_CONFIG_POSTPLLDIV_LSB 7 +#define AUDIO_PLL_CONFIG_POSTPLLDIV_MASK 0x00000380 +#define AUDIO_PLL_CONFIG_POSTPLLDIV_GET(x) (((x) & AUDIO_PLL_CONFIG_POSTPLLDIV_MASK) >> AUDIO_PLL_CONFIG_POSTPLLDIV_LSB) +#define AUDIO_PLL_CONFIG_POSTPLLDIV_SET(x) (((x) << AUDIO_PLL_CONFIG_POSTPLLDIV_LSB) & AUDIO_PLL_CONFIG_POSTPLLDIV_MASK) +#define AUDIO_PLL_CONFIG_PLLPWD_MSB 5 +#define AUDIO_PLL_CONFIG_PLLPWD_LSB 5 +#define AUDIO_PLL_CONFIG_PLLPWD_MASK 0x00000020 +#define AUDIO_PLL_CONFIG_PLLPWD_GET(x) (((x) & AUDIO_PLL_CONFIG_PLLPWD_MASK) >> AUDIO_PLL_CONFIG_PLLPWD_LSB) +#define AUDIO_PLL_CONFIG_PLLPWD_SET(x) (((x) << AUDIO_PLL_CONFIG_PLLPWD_LSB) & AUDIO_PLL_CONFIG_PLLPWD_MASK) +#define AUDIO_PLL_CONFIG_BYPASS_MSB 4 +#define AUDIO_PLL_CONFIG_BYPASS_LSB 4 +#define AUDIO_PLL_CONFIG_BYPASS_MASK 0x00000010 +#define AUDIO_PLL_CONFIG_BYPASS_GET(x) (((x) & AUDIO_PLL_CONFIG_BYPASS_MASK) >> AUDIO_PLL_CONFIG_BYPASS_LSB) +#define AUDIO_PLL_CONFIG_BYPASS_SET(x) (((x) << AUDIO_PLL_CONFIG_BYPASS_LSB) & AUDIO_PLL_CONFIG_BYPASS_MASK) +#define AUDIO_PLL_CONFIG_REFDIV_MSB 3 +#define AUDIO_PLL_CONFIG_REFDIV_LSB 0 +#define AUDIO_PLL_CONFIG_REFDIV_MASK 0x0000000f +#define AUDIO_PLL_CONFIG_REFDIV_GET(x) (((x) & AUDIO_PLL_CONFIG_REFDIV_MASK) >> AUDIO_PLL_CONFIG_REFDIV_LSB) +#define AUDIO_PLL_CONFIG_REFDIV_SET(x) (((x) << AUDIO_PLL_CONFIG_REFDIV_LSB) & AUDIO_PLL_CONFIG_REFDIV_MASK) + +#define AUDIO_PLL_MODULATION_ADDRESS 0x000002f4 +#define AUDIO_PLL_MODULATION_OFFSET 0x000002f4 +#define AUDIO_PLL_MODULATION_TGT_DIV_FRAC_MSB 28 +#define AUDIO_PLL_MODULATION_TGT_DIV_FRAC_LSB 11 +#define AUDIO_PLL_MODULATION_TGT_DIV_FRAC_MASK 0x1ffff800 +#define AUDIO_PLL_MODULATION_TGT_DIV_FRAC_GET(x) (((x) & AUDIO_PLL_MODULATION_TGT_DIV_FRAC_MASK) >> AUDIO_PLL_MODULATION_TGT_DIV_FRAC_LSB) +#define AUDIO_PLL_MODULATION_TGT_DIV_FRAC_SET(x) (((x) << AUDIO_PLL_MODULATION_TGT_DIV_FRAC_LSB) & AUDIO_PLL_MODULATION_TGT_DIV_FRAC_MASK) +#define AUDIO_PLL_MODULATION_TGT_DIV_INT_MSB 6 +#define AUDIO_PLL_MODULATION_TGT_DIV_INT_LSB 1 +#define AUDIO_PLL_MODULATION_TGT_DIV_INT_MASK 0x0000007e +#define AUDIO_PLL_MODULATION_TGT_DIV_INT_GET(x) (((x) & AUDIO_PLL_MODULATION_TGT_DIV_INT_MASK) >> AUDIO_PLL_MODULATION_TGT_DIV_INT_LSB) +#define AUDIO_PLL_MODULATION_TGT_DIV_INT_SET(x) (((x) << AUDIO_PLL_MODULATION_TGT_DIV_INT_LSB) & AUDIO_PLL_MODULATION_TGT_DIV_INT_MASK) +#define AUDIO_PLL_MODULATION_START_MSB 0 +#define AUDIO_PLL_MODULATION_START_LSB 0 +#define AUDIO_PLL_MODULATION_START_MASK 0x00000001 +#define AUDIO_PLL_MODULATION_START_GET(x) (((x) & AUDIO_PLL_MODULATION_START_MASK) >> AUDIO_PLL_MODULATION_START_LSB) +#define AUDIO_PLL_MODULATION_START_SET(x) (((x) << AUDIO_PLL_MODULATION_START_LSB) & AUDIO_PLL_MODULATION_START_MASK) + +#define AUDIO_PLL_MOD_STEP_ADDRESS 0x000002f8 +#define AUDIO_PLL_MOD_STEP_OFFSET 0x000002f8 +#define AUDIO_PLL_MOD_STEP_FRAC_MSB 31 +#define AUDIO_PLL_MOD_STEP_FRAC_LSB 14 +#define AUDIO_PLL_MOD_STEP_FRAC_MASK 0xffffc000 +#define AUDIO_PLL_MOD_STEP_FRAC_GET(x) (((x) & AUDIO_PLL_MOD_STEP_FRAC_MASK) >> AUDIO_PLL_MOD_STEP_FRAC_LSB) +#define AUDIO_PLL_MOD_STEP_FRAC_SET(x) (((x) << AUDIO_PLL_MOD_STEP_FRAC_LSB) & AUDIO_PLL_MOD_STEP_FRAC_MASK) +#define AUDIO_PLL_MOD_STEP_INT_MSB 13 +#define AUDIO_PLL_MOD_STEP_INT_LSB 4 +#define AUDIO_PLL_MOD_STEP_INT_MASK 0x00003ff0 +#define AUDIO_PLL_MOD_STEP_INT_GET(x) (((x) & AUDIO_PLL_MOD_STEP_INT_MASK) >> AUDIO_PLL_MOD_STEP_INT_LSB) +#define AUDIO_PLL_MOD_STEP_INT_SET(x) (((x) << AUDIO_PLL_MOD_STEP_INT_LSB) & AUDIO_PLL_MOD_STEP_INT_MASK) +#define AUDIO_PLL_MOD_STEP_UPDATE_CNT_MSB 3 +#define AUDIO_PLL_MOD_STEP_UPDATE_CNT_LSB 0 +#define AUDIO_PLL_MOD_STEP_UPDATE_CNT_MASK 0x0000000f +#define AUDIO_PLL_MOD_STEP_UPDATE_CNT_GET(x) (((x) & AUDIO_PLL_MOD_STEP_UPDATE_CNT_MASK) >> AUDIO_PLL_MOD_STEP_UPDATE_CNT_LSB) +#define AUDIO_PLL_MOD_STEP_UPDATE_CNT_SET(x) (((x) << AUDIO_PLL_MOD_STEP_UPDATE_CNT_LSB) & AUDIO_PLL_MOD_STEP_UPDATE_CNT_MASK) + +#define CURRENT_AUDIO_PLL_MODULATION_ADDRESS 0x000002fc +#define CURRENT_AUDIO_PLL_MODULATION_OFFSET 0x000002fc +#define CURRENT_AUDIO_PLL_MODULATION_FRAC_MSB 27 +#define CURRENT_AUDIO_PLL_MODULATION_FRAC_LSB 10 +#define CURRENT_AUDIO_PLL_MODULATION_FRAC_MASK 0x0ffffc00 +#define CURRENT_AUDIO_PLL_MODULATION_FRAC_GET(x) (((x) & CURRENT_AUDIO_PLL_MODULATION_FRAC_MASK) >> CURRENT_AUDIO_PLL_MODULATION_FRAC_LSB) +#define CURRENT_AUDIO_PLL_MODULATION_FRAC_SET(x) (((x) << CURRENT_AUDIO_PLL_MODULATION_FRAC_LSB) & CURRENT_AUDIO_PLL_MODULATION_FRAC_MASK) +#define CURRENT_AUDIO_PLL_MODULATION_INT_MSB 6 +#define CURRENT_AUDIO_PLL_MODULATION_INT_LSB 1 +#define CURRENT_AUDIO_PLL_MODULATION_INT_MASK 0x0000007e +#define CURRENT_AUDIO_PLL_MODULATION_INT_GET(x) (((x) & CURRENT_AUDIO_PLL_MODULATION_INT_MASK) >> CURRENT_AUDIO_PLL_MODULATION_INT_LSB) +#define CURRENT_AUDIO_PLL_MODULATION_INT_SET(x) (((x) << CURRENT_AUDIO_PLL_MODULATION_INT_LSB) & CURRENT_AUDIO_PLL_MODULATION_INT_MASK) + +#define ETH_PLL_CONFIG_ADDRESS 0x00000300 +#define ETH_PLL_CONFIG_OFFSET 0x00000300 +#define ETH_PLL_CONFIG_GE0_MASTER_MSB 30 +#define ETH_PLL_CONFIG_GE0_MASTER_LSB 30 +#define ETH_PLL_CONFIG_GE0_MASTER_MASK 0x40000000 +#define ETH_PLL_CONFIG_GE0_MASTER_GET(x) (((x) & ETH_PLL_CONFIG_GE0_MASTER_MASK) >> ETH_PLL_CONFIG_GE0_MASTER_LSB) +#define ETH_PLL_CONFIG_GE0_MASTER_SET(x) (((x) << ETH_PLL_CONFIG_GE0_MASTER_LSB) & ETH_PLL_CONFIG_GE0_MASTER_MASK) +#define ETH_PLL_CONFIG_GE0_MSB 29 +#define ETH_PLL_CONFIG_GE0_LSB 29 +#define ETH_PLL_CONFIG_GE0_MASK 0x20000000 +#define ETH_PLL_CONFIG_GE0_GET(x) (((x) & ETH_PLL_CONFIG_GE0_MASK) >> ETH_PLL_CONFIG_GE0_LSB) +#define ETH_PLL_CONFIG_GE0_SET(x) (((x) << ETH_PLL_CONFIG_GE0_LSB) & ETH_PLL_CONFIG_GE0_MASK) +#define ETH_PLL_CONFIG_RANGE_MSB 28 +#define ETH_PLL_CONFIG_RANGE_LSB 28 +#define ETH_PLL_CONFIG_RANGE_MASK 0x10000000 +#define ETH_PLL_CONFIG_RANGE_GET(x) (((x) & ETH_PLL_CONFIG_RANGE_MASK) >> ETH_PLL_CONFIG_RANGE_LSB) +#define ETH_PLL_CONFIG_RANGE_SET(x) (((x) << ETH_PLL_CONFIG_RANGE_LSB) & ETH_PLL_CONFIG_RANGE_MASK) +#define ETH_PLL_CONFIG_FRAC_MSB 27 +#define ETH_PLL_CONFIG_FRAC_LSB 18 +#define ETH_PLL_CONFIG_FRAC_MASK 0x0ffc0000 +#define ETH_PLL_CONFIG_FRAC_GET(x) (((x) & ETH_PLL_CONFIG_FRAC_MASK) >> ETH_PLL_CONFIG_FRAC_LSB) +#define ETH_PLL_CONFIG_FRAC_SET(x) (((x) << ETH_PLL_CONFIG_FRAC_LSB) & ETH_PLL_CONFIG_FRAC_MASK) +#define ETH_PLL_CONFIG_INT_MSB 17 +#define ETH_PLL_CONFIG_INT_LSB 12 +#define ETH_PLL_CONFIG_INT_MASK 0x0003f000 +#define ETH_PLL_CONFIG_INT_GET(x) (((x) & ETH_PLL_CONFIG_INT_MASK) >> ETH_PLL_CONFIG_INT_LSB) +#define ETH_PLL_CONFIG_INT_SET(x) (((x) << ETH_PLL_CONFIG_INT_LSB) & ETH_PLL_CONFIG_INT_MASK) +#define ETH_PLL_CONFIG_OUTDIV_MSB 9 +#define ETH_PLL_CONFIG_OUTDIV_LSB 7 +#define ETH_PLL_CONFIG_OUTDIV_MASK 0x00000380 +#define ETH_PLL_CONFIG_OUTDIV_GET(x) (((x) & ETH_PLL_CONFIG_OUTDIV_MASK) >> ETH_PLL_CONFIG_OUTDIV_LSB) +#define ETH_PLL_CONFIG_OUTDIV_SET(x) (((x) << ETH_PLL_CONFIG_OUTDIV_LSB) & ETH_PLL_CONFIG_OUTDIV_MASK) +#define ETH_PLL_CONFIG_PLLPWD_MSB 6 +#define ETH_PLL_CONFIG_PLLPWD_LSB 6 +#define ETH_PLL_CONFIG_PLLPWD_MASK 0x00000040 +#define ETH_PLL_CONFIG_PLLPWD_GET(x) (((x) & ETH_PLL_CONFIG_PLLPWD_MASK) >> ETH_PLL_CONFIG_PLLPWD_LSB) +#define ETH_PLL_CONFIG_PLLPWD_SET(x) (((x) << ETH_PLL_CONFIG_PLLPWD_LSB) & ETH_PLL_CONFIG_PLLPWD_MASK) +#define ETH_PLL_CONFIG_BYPASS_MSB 5 +#define ETH_PLL_CONFIG_BYPASS_LSB 5 +#define ETH_PLL_CONFIG_BYPASS_MASK 0x00000020 +#define ETH_PLL_CONFIG_BYPASS_GET(x) (((x) & ETH_PLL_CONFIG_BYPASS_MASK) >> ETH_PLL_CONFIG_BYPASS_LSB) +#define ETH_PLL_CONFIG_BYPASS_SET(x) (((x) << ETH_PLL_CONFIG_BYPASS_LSB) & ETH_PLL_CONFIG_BYPASS_MASK) +#define ETH_PLL_CONFIG_REFDIV_MSB 4 +#define ETH_PLL_CONFIG_REFDIV_LSB 0 +#define ETH_PLL_CONFIG_REFDIV_MASK 0x0000001f +#define ETH_PLL_CONFIG_REFDIV_GET(x) (((x) & ETH_PLL_CONFIG_REFDIV_MASK) >> ETH_PLL_CONFIG_REFDIV_LSB) +#define ETH_PLL_CONFIG_REFDIV_SET(x) (((x) << ETH_PLL_CONFIG_REFDIV_LSB) & ETH_PLL_CONFIG_REFDIV_MASK) + +#define CPU_PLL_CONFIG_ADDRESS 0x00000304 +#define CPU_PLL_CONFIG_OFFSET 0x00000304 +#define CPU_PLL_CONFIG_RANGE_MSB 28 +#define CPU_PLL_CONFIG_RANGE_LSB 28 +#define CPU_PLL_CONFIG_RANGE_MASK 0x10000000 +#define CPU_PLL_CONFIG_RANGE_GET(x) (((x) & CPU_PLL_CONFIG_RANGE_MASK) >> CPU_PLL_CONFIG_RANGE_LSB) +#define CPU_PLL_CONFIG_RANGE_SET(x) (((x) << CPU_PLL_CONFIG_RANGE_LSB) & CPU_PLL_CONFIG_RANGE_MASK) +#define CPU_PLL_CONFIG_FRAC_MSB 25 +#define CPU_PLL_CONFIG_FRAC_LSB 20 +#define CPU_PLL_CONFIG_FRAC_MASK 0x03f00000 +#define CPU_PLL_CONFIG_FRAC_GET(x) (((x) & CPU_PLL_CONFIG_FRAC_MASK) >> CPU_PLL_CONFIG_FRAC_LSB) +#define CPU_PLL_CONFIG_FRAC_SET(x) (((x) << CPU_PLL_CONFIG_FRAC_LSB) & CPU_PLL_CONFIG_FRAC_MASK) +#define CPU_PLL_CONFIG_INT_MSB 17 +#define CPU_PLL_CONFIG_INT_LSB 12 +#define CPU_PLL_CONFIG_INT_MASK 0x0003f000 +#define CPU_PLL_CONFIG_INT_GET(x) (((x) & CPU_PLL_CONFIG_INT_MASK) >> CPU_PLL_CONFIG_INT_LSB) +#define CPU_PLL_CONFIG_INT_SET(x) (((x) << CPU_PLL_CONFIG_INT_LSB) & CPU_PLL_CONFIG_INT_MASK) +#define CPU_PLL_CONFIG_OUTDIV_MSB 9 +#define CPU_PLL_CONFIG_OUTDIV_LSB 7 +#define CPU_PLL_CONFIG_OUTDIV_MASK 0x00000380 +#define CPU_PLL_CONFIG_OUTDIV_GET(x) (((x) & CPU_PLL_CONFIG_OUTDIV_MASK) >> CPU_PLL_CONFIG_OUTDIV_LSB) +#define CPU_PLL_CONFIG_OUTDIV_SET(x) (((x) << CPU_PLL_CONFIG_OUTDIV_LSB) & CPU_PLL_CONFIG_OUTDIV_MASK) +#define CPU_PLL_CONFIG_PLLPWD_MSB 6 +#define CPU_PLL_CONFIG_PLLPWD_LSB 6 +#define CPU_PLL_CONFIG_PLLPWD_MASK 0x00000040 +#define CPU_PLL_CONFIG_PLLPWD_GET(x) (((x) & CPU_PLL_CONFIG_PLLPWD_MASK) >> CPU_PLL_CONFIG_PLLPWD_LSB) +#define CPU_PLL_CONFIG_PLLPWD_SET(x) (((x) << CPU_PLL_CONFIG_PLLPWD_LSB) & CPU_PLL_CONFIG_PLLPWD_MASK) +#define CPU_PLL_CONFIG_REFDIV_MSB 4 +#define CPU_PLL_CONFIG_REFDIV_LSB 0 +#define CPU_PLL_CONFIG_REFDIV_MASK 0x0000001f +#define CPU_PLL_CONFIG_REFDIV_GET(x) (((x) & CPU_PLL_CONFIG_REFDIV_MASK) >> CPU_PLL_CONFIG_REFDIV_LSB) +#define CPU_PLL_CONFIG_REFDIV_SET(x) (((x) << CPU_PLL_CONFIG_REFDIV_LSB) & CPU_PLL_CONFIG_REFDIV_MASK) + +#define BB_PLL_CONFIG_ADDRESS 0x00000308 +#define BB_PLL_CONFIG_OFFSET 0x00000308 +#define BB_PLL_CONFIG_FRAC_MSB 17 +#define BB_PLL_CONFIG_FRAC_LSB 0 +#define BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define BB_PLL_CONFIG_FRAC_GET(x) (((x) & BB_PLL_CONFIG_FRAC_MASK) >> BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_SET(x) (((x) << BB_PLL_CONFIG_FRAC_LSB) & BB_PLL_CONFIG_FRAC_MASK) + +#define ETH_XMII_ADDRESS 0x0000030c +#define ETH_XMII_OFFSET 0x0000030c +#define ETH_XMII_TX_INVERT_MSB 31 +#define ETH_XMII_TX_INVERT_LSB 31 +#define ETH_XMII_TX_INVERT_MASK 0x80000000 +#define ETH_XMII_TX_INVERT_GET(x) (((x) & ETH_XMII_TX_INVERT_MASK) >> ETH_XMII_TX_INVERT_LSB) +#define ETH_XMII_TX_INVERT_SET(x) (((x) << ETH_XMII_TX_INVERT_LSB) & ETH_XMII_TX_INVERT_MASK) +#define ETH_XMII_GIGE_QUAD_MSB 30 +#define ETH_XMII_GIGE_QUAD_LSB 30 +#define ETH_XMII_GIGE_QUAD_MASK 0x40000000 +#define ETH_XMII_GIGE_QUAD_GET(x) (((x) & ETH_XMII_GIGE_QUAD_MASK) >> ETH_XMII_GIGE_QUAD_LSB) +#define ETH_XMII_GIGE_QUAD_SET(x) (((x) << ETH_XMII_GIGE_QUAD_LSB) & ETH_XMII_GIGE_QUAD_MASK) +#define ETH_XMII_RX_DELAY_MSB 29 +#define ETH_XMII_RX_DELAY_LSB 28 +#define ETH_XMII_RX_DELAY_MASK 0x30000000 +#define ETH_XMII_RX_DELAY_GET(x) (((x) & ETH_XMII_RX_DELAY_MASK) >> ETH_XMII_RX_DELAY_LSB) +#define ETH_XMII_RX_DELAY_SET(x) (((x) << ETH_XMII_RX_DELAY_LSB) & ETH_XMII_RX_DELAY_MASK) +#define ETH_XMII_TX_DELAY_MSB 27 +#define ETH_XMII_TX_DELAY_LSB 26 +#define ETH_XMII_TX_DELAY_MASK 0x0c000000 +#define ETH_XMII_TX_DELAY_GET(x) (((x) & ETH_XMII_TX_DELAY_MASK) >> ETH_XMII_TX_DELAY_LSB) +#define ETH_XMII_TX_DELAY_SET(x) (((x) << ETH_XMII_TX_DELAY_LSB) & ETH_XMII_TX_DELAY_MASK) +#define ETH_XMII_GIGE_MSB 25 +#define ETH_XMII_GIGE_LSB 25 +#define ETH_XMII_GIGE_MASK 0x02000000 +#define ETH_XMII_GIGE_GET(x) (((x) & ETH_XMII_GIGE_MASK) >> ETH_XMII_GIGE_LSB) +#define ETH_XMII_GIGE_SET(x) (((x) << ETH_XMII_GIGE_LSB) & ETH_XMII_GIGE_MASK) +#define ETH_XMII_OFFSET_PHASE_MSB 24 +#define ETH_XMII_OFFSET_PHASE_LSB 24 +#define ETH_XMII_OFFSET_PHASE_MASK 0x01000000 +#define ETH_XMII_OFFSET_PHASE_GET(x) (((x) & ETH_XMII_OFFSET_PHASE_MASK) >> ETH_XMII_OFFSET_PHASE_LSB) +#define ETH_XMII_OFFSET_PHASE_SET(x) (((x) << ETH_XMII_OFFSET_PHASE_LSB) & ETH_XMII_OFFSET_PHASE_MASK) +#define ETH_XMII_OFFSET_COUNT_MSB 23 +#define ETH_XMII_OFFSET_COUNT_LSB 16 +#define ETH_XMII_OFFSET_COUNT_MASK 0x00ff0000 +#define ETH_XMII_OFFSET_COUNT_GET(x) (((x) & ETH_XMII_OFFSET_COUNT_MASK) >> ETH_XMII_OFFSET_COUNT_LSB) +#define ETH_XMII_OFFSET_COUNT_SET(x) (((x) << ETH_XMII_OFFSET_COUNT_LSB) & ETH_XMII_OFFSET_COUNT_MASK) +#define ETH_XMII_PHASE1_COUNT_MSB 15 +#define ETH_XMII_PHASE1_COUNT_LSB 8 +#define ETH_XMII_PHASE1_COUNT_MASK 0x0000ff00 +#define ETH_XMII_PHASE1_COUNT_GET(x) (((x) & ETH_XMII_PHASE1_COUNT_MASK) >> ETH_XMII_PHASE1_COUNT_LSB) +#define ETH_XMII_PHASE1_COUNT_SET(x) (((x) << ETH_XMII_PHASE1_COUNT_LSB) & ETH_XMII_PHASE1_COUNT_MASK) +#define ETH_XMII_PHASE0_COUNT_MSB 7 +#define ETH_XMII_PHASE0_COUNT_LSB 0 +#define ETH_XMII_PHASE0_COUNT_MASK 0x000000ff +#define ETH_XMII_PHASE0_COUNT_GET(x) (((x) & ETH_XMII_PHASE0_COUNT_MASK) >> ETH_XMII_PHASE0_COUNT_LSB) +#define ETH_XMII_PHASE0_COUNT_SET(x) (((x) << ETH_XMII_PHASE0_COUNT_LSB) & ETH_XMII_PHASE0_COUNT_MASK) + +#define USB_PHY_CONFIG_ADDRESS 0x00000310 +#define USB_PHY_CONFIG_OFFSET 0x00000310 +#define USB_PHY_CONFIG_REFCLK_SEL_MSB 7 +#define USB_PHY_CONFIG_REFCLK_SEL_LSB 4 +#define USB_PHY_CONFIG_REFCLK_SEL_MASK 0x000000f0 +#define USB_PHY_CONFIG_REFCLK_SEL_GET(x) (((x) & USB_PHY_CONFIG_REFCLK_SEL_MASK) >> USB_PHY_CONFIG_REFCLK_SEL_LSB) +#define USB_PHY_CONFIG_REFCLK_SEL_SET(x) (((x) << USB_PHY_CONFIG_REFCLK_SEL_LSB) & USB_PHY_CONFIG_REFCLK_SEL_MASK) +#define USB_PHY_CONFIG_REFDIV_MSB 3 +#define USB_PHY_CONFIG_REFDIV_LSB 3 +#define USB_PHY_CONFIG_REFDIV_MASK 0x00000008 +#define USB_PHY_CONFIG_REFDIV_GET(x) (((x) & USB_PHY_CONFIG_REFDIV_MASK) >> USB_PHY_CONFIG_REFDIV_LSB) +#define USB_PHY_CONFIG_REFDIV_SET(x) (((x) << USB_PHY_CONFIG_REFDIV_LSB) & USB_PHY_CONFIG_REFDIV_MASK) +#define USB_PHY_CONFIG_TESTMODE_MSB 2 +#define USB_PHY_CONFIG_TESTMODE_LSB 2 +#define USB_PHY_CONFIG_TESTMODE_MASK 0x00000004 +#define USB_PHY_CONFIG_TESTMODE_GET(x) (((x) & USB_PHY_CONFIG_TESTMODE_MASK) >> USB_PHY_CONFIG_TESTMODE_LSB) +#define USB_PHY_CONFIG_TESTMODE_SET(x) (((x) << USB_PHY_CONFIG_TESTMODE_LSB) & USB_PHY_CONFIG_TESTMODE_MASK) +#define USB_PHY_CONFIG_PLL_PWD_MSB 1 +#define USB_PHY_CONFIG_PLL_PWD_LSB 1 +#define USB_PHY_CONFIG_PLL_PWD_MASK 0x00000002 +#define USB_PHY_CONFIG_PLL_PWD_GET(x) (((x) & USB_PHY_CONFIG_PLL_PWD_MASK) >> USB_PHY_CONFIG_PLL_PWD_LSB) +#define USB_PHY_CONFIG_PLL_PWD_SET(x) (((x) << USB_PHY_CONFIG_PLL_PWD_LSB) & USB_PHY_CONFIG_PLL_PWD_MASK) +#define USB_PHY_CONFIG_HOSTMODE_MSB 0 +#define USB_PHY_CONFIG_HOSTMODE_LSB 0 +#define USB_PHY_CONFIG_HOSTMODE_MASK 0x00000001 +#define USB_PHY_CONFIG_HOSTMODE_GET(x) (((x) & USB_PHY_CONFIG_HOSTMODE_MASK) >> USB_PHY_CONFIG_HOSTMODE_LSB) +#define USB_PHY_CONFIG_HOSTMODE_SET(x) (((x) << USB_PHY_CONFIG_HOSTMODE_LSB) & USB_PHY_CONFIG_HOSTMODE_MASK) + +#define USBCORE_CLK60M_ADDRESS 0x00000314 +#define USBCORE_CLK60M_OFFSET 0x00000314 +#define USBCORE_CLK60M_SEL_MSB 0 +#define USBCORE_CLK60M_SEL_LSB 0 +#define USBCORE_CLK60M_SEL_MASK 0x00000001 +#define USBCORE_CLK60M_SEL_GET(x) (((x) & USBCORE_CLK60M_SEL_MASK) >> USBCORE_CLK60M_SEL_LSB) +#define USBCORE_CLK60M_SEL_SET(x) (((x) << USBCORE_CLK60M_SEL_LSB) & USBCORE_CLK60M_SEL_MASK) + +#define USBPHY_UTMI_CLK_ADDRESS 0x00000318 +#define USBPHY_UTMI_CLK_OFFSET 0x00000318 +#define USBPHY_UTMI_CLK_EN_MSB 0 +#define USBPHY_UTMI_CLK_EN_LSB 0 +#define USBPHY_UTMI_CLK_EN_MASK 0x00000001 +#define USBPHY_UTMI_CLK_EN_GET(x) (((x) & USBPHY_UTMI_CLK_EN_MASK) >> USBPHY_UTMI_CLK_EN_LSB) +#define USBPHY_UTMI_CLK_EN_SET(x) (((x) << USBPHY_UTMI_CLK_EN_LSB) & USBPHY_UTMI_CLK_EN_MASK) + +#define USB_TXVALID_DLY_CONFIG_ADDRESS 0x0000031c +#define USB_TXVALID_DLY_CONFIG_OFFSET 0x0000031c +#define USB_TXVALID_DLY_CONFIG_UTMI16_MSB 7 +#define USB_TXVALID_DLY_CONFIG_UTMI16_LSB 4 +#define USB_TXVALID_DLY_CONFIG_UTMI16_MASK 0x000000f0 +#define USB_TXVALID_DLY_CONFIG_UTMI16_GET(x) (((x) & USB_TXVALID_DLY_CONFIG_UTMI16_MASK) >> USB_TXVALID_DLY_CONFIG_UTMI16_LSB) +#define USB_TXVALID_DLY_CONFIG_UTMI16_SET(x) (((x) << USB_TXVALID_DLY_CONFIG_UTMI16_LSB) & USB_TXVALID_DLY_CONFIG_UTMI16_MASK) +#define USB_TXVALID_DLY_CONFIG_UTMI8_MSB 3 +#define USB_TXVALID_DLY_CONFIG_UTMI8_LSB 0 +#define USB_TXVALID_DLY_CONFIG_UTMI8_MASK 0x0000000f +#define USB_TXVALID_DLY_CONFIG_UTMI8_GET(x) (((x) & USB_TXVALID_DLY_CONFIG_UTMI8_MASK) >> USB_TXVALID_DLY_CONFIG_UTMI8_LSB) +#define USB_TXVALID_DLY_CONFIG_UTMI8_SET(x) (((x) << USB_TXVALID_DLY_CONFIG_UTMI8_LSB) & USB_TXVALID_DLY_CONFIG_UTMI8_MASK) + +#define SECOND_HOST_INFT_ADDRESS 0x00000320 +#define SECOND_HOST_INFT_OFFSET 0x00000320 +#define SECOND_HOST_INFT_SDIO_MODE_MSB 0 +#define SECOND_HOST_INFT_SDIO_MODE_LSB 0 +#define SECOND_HOST_INFT_SDIO_MODE_MASK 0x00000001 +#define SECOND_HOST_INFT_SDIO_MODE_GET(x) (((x) & SECOND_HOST_INFT_SDIO_MODE_MASK) >> SECOND_HOST_INFT_SDIO_MODE_LSB) +#define SECOND_HOST_INFT_SDIO_MODE_SET(x) (((x) << SECOND_HOST_INFT_SDIO_MODE_LSB) & SECOND_HOST_INFT_SDIO_MODE_MASK) + +#define SDIO_HOST_ADDRESS 0x00000324 +#define SDIO_HOST_OFFSET 0x00000324 +#define SDIO_HOST_RESET_MSB 0 +#define SDIO_HOST_RESET_LSB 0 +#define SDIO_HOST_RESET_MASK 0x00000001 +#define SDIO_HOST_RESET_GET(x) (((x) & SDIO_HOST_RESET_MASK) >> SDIO_HOST_RESET_LSB) +#define SDIO_HOST_RESET_SET(x) (((x) << SDIO_HOST_RESET_LSB) & SDIO_HOST_RESET_MASK) + +#define ENTERPRISE_CONFIG_ADDRESS 0x00000328 +#define ENTERPRISE_CONFIG_OFFSET 0x00000328 +#define ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_MSB 12 +#define ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_LSB 12 +#define ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_MASK 0x00001000 +#define ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_GET(x) (((x) & ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_MASK) >> ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_LSB) +#define ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_SET(x) (((x) << ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_LSB) & ENTERPRISE_CONFIG_TPC_LOWER_PERFORMANCE_MASK) +#define ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_MSB 11 +#define ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_LSB 11 +#define ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_MASK 0x00000800 +#define ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_GET(x) (((x) & ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_MASK) >> ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_LSB) +#define ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_SET(x) (((x) << ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_LSB) & ENTERPRISE_CONFIG_SWCOM_IDLE_MODE_MASK) +#define ENTERPRISE_CONFIG_STBC_DISABLE_MSB 10 +#define ENTERPRISE_CONFIG_STBC_DISABLE_LSB 10 +#define ENTERPRISE_CONFIG_STBC_DISABLE_MASK 0x00000400 +#define ENTERPRISE_CONFIG_STBC_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_STBC_DISABLE_MASK) >> ENTERPRISE_CONFIG_STBC_DISABLE_LSB) +#define ENTERPRISE_CONFIG_STBC_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_STBC_DISABLE_LSB) & ENTERPRISE_CONFIG_STBC_DISABLE_MASK) +#define ENTERPRISE_CONFIG_LDPC_DISABLE_MSB 9 +#define ENTERPRISE_CONFIG_LDPC_DISABLE_LSB 9 +#define ENTERPRISE_CONFIG_LDPC_DISABLE_MASK 0x00000200 +#define ENTERPRISE_CONFIG_LDPC_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_LDPC_DISABLE_MASK) >> ENTERPRISE_CONFIG_LDPC_DISABLE_LSB) +#define ENTERPRISE_CONFIG_LDPC_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_LDPC_DISABLE_LSB) & ENTERPRISE_CONFIG_LDPC_DISABLE_MASK) +#define ENTERPRISE_CONFIG_GREEN_TX_DISABLE_MSB 8 +#define ENTERPRISE_CONFIG_GREEN_TX_DISABLE_LSB 8 +#define ENTERPRISE_CONFIG_GREEN_TX_DISABLE_MASK 0x00000100 +#define ENTERPRISE_CONFIG_GREEN_TX_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_GREEN_TX_DISABLE_MASK) >> ENTERPRISE_CONFIG_GREEN_TX_DISABLE_LSB) +#define ENTERPRISE_CONFIG_GREEN_TX_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_GREEN_TX_DISABLE_LSB) & ENTERPRISE_CONFIG_GREEN_TX_DISABLE_MASK) +#define ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_MSB 7 +#define ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_LSB 7 +#define ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_MASK 0x00000080 +#define ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_MASK) >> ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_LSB) +#define ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_LSB) & ENTERPRISE_CONFIG_DUAL_BAND_DISABLE_MASK) +#define ENTERPRISE_CONFIG_CHAIN1_DISABLE_MSB 6 +#define ENTERPRISE_CONFIG_CHAIN1_DISABLE_LSB 6 +#define ENTERPRISE_CONFIG_CHAIN1_DISABLE_MASK 0x00000040 +#define ENTERPRISE_CONFIG_CHAIN1_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_CHAIN1_DISABLE_MASK) >> ENTERPRISE_CONFIG_CHAIN1_DISABLE_LSB) +#define ENTERPRISE_CONFIG_CHAIN1_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_CHAIN1_DISABLE_LSB) & ENTERPRISE_CONFIG_CHAIN1_DISABLE_MASK) +#define ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_MSB 5 +#define ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_LSB 5 +#define ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_MASK 0x00000020 +#define ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_MASK) >> ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_LSB) +#define ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_LSB) & ENTERPRISE_CONFIG_CH_5MHZ_DISABLE_MASK) +#define ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_MSB 4 +#define ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_LSB 4 +#define ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_MASK 0x00000010 +#define ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_MASK) >> ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_LSB) +#define ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_LSB) & ENTERPRISE_CONFIG_CH_10MHZ_DISABLE_MASK) +#define ENTERPRISE_CONFIG_TXBF_DISABLE_MSB 3 +#define ENTERPRISE_CONFIG_TXBF_DISABLE_LSB 3 +#define ENTERPRISE_CONFIG_TXBF_DISABLE_MASK 0x00000008 +#define ENTERPRISE_CONFIG_TXBF_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_TXBF_DISABLE_MASK) >> ENTERPRISE_CONFIG_TXBF_DISABLE_LSB) +#define ENTERPRISE_CONFIG_TXBF_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_TXBF_DISABLE_LSB) & ENTERPRISE_CONFIG_TXBF_DISABLE_MASK) +#define ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_MSB 2 +#define ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_LSB 2 +#define ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_MASK 0x00000004 +#define ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_MASK) >> ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_LSB) +#define ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_LSB) & ENTERPRISE_CONFIG_MIN_PKT_SIZE_DISABLE_MASK) +#define ENTERPRISE_CONFIG_LOOPBACK_DISABLE_MSB 1 +#define ENTERPRISE_CONFIG_LOOPBACK_DISABLE_LSB 1 +#define ENTERPRISE_CONFIG_LOOPBACK_DISABLE_MASK 0x00000002 +#define ENTERPRISE_CONFIG_LOOPBACK_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_LOOPBACK_DISABLE_MASK) >> ENTERPRISE_CONFIG_LOOPBACK_DISABLE_LSB) +#define ENTERPRISE_CONFIG_LOOPBACK_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_LOOPBACK_DISABLE_LSB) & ENTERPRISE_CONFIG_LOOPBACK_DISABLE_MASK) +#define ENTERPRISE_CONFIG_LOCATION_DISABLE_MSB 0 +#define ENTERPRISE_CONFIG_LOCATION_DISABLE_LSB 0 +#define ENTERPRISE_CONFIG_LOCATION_DISABLE_MASK 0x00000001 +#define ENTERPRISE_CONFIG_LOCATION_DISABLE_GET(x) (((x) & ENTERPRISE_CONFIG_LOCATION_DISABLE_MASK) >> ENTERPRISE_CONFIG_LOCATION_DISABLE_LSB) +#define ENTERPRISE_CONFIG_LOCATION_DISABLE_SET(x) (((x) << ENTERPRISE_CONFIG_LOCATION_DISABLE_LSB) & ENTERPRISE_CONFIG_LOCATION_DISABLE_MASK) + +#define RTC_DEBUG_BUS_ADDRESS 0x0000032c +#define RTC_DEBUG_BUS_OFFSET 0x0000032c +#define RTC_DEBUG_BUS_SEL_MSB 0 +#define RTC_DEBUG_BUS_SEL_LSB 0 +#define RTC_DEBUG_BUS_SEL_MASK 0x00000001 +#define RTC_DEBUG_BUS_SEL_GET(x) (((x) & RTC_DEBUG_BUS_SEL_MASK) >> RTC_DEBUG_BUS_SEL_LSB) +#define RTC_DEBUG_BUS_SEL_SET(x) (((x) << RTC_DEBUG_BUS_SEL_LSB) & RTC_DEBUG_BUS_SEL_MASK) + +#define RTC_EXT_CLK_BUF_ADDRESS 0x00000330 +#define RTC_EXT_CLK_BUF_OFFSET 0x00000330 +#define RTC_EXT_CLK_BUF_EN_MSB 0 +#define RTC_EXT_CLK_BUF_EN_LSB 0 +#define RTC_EXT_CLK_BUF_EN_MASK 0x00000001 +#define RTC_EXT_CLK_BUF_EN_GET(x) (((x) & RTC_EXT_CLK_BUF_EN_MASK) >> RTC_EXT_CLK_BUF_EN_LSB) +#define RTC_EXT_CLK_BUF_EN_SET(x) (((x) << RTC_EXT_CLK_BUF_EN_LSB) & RTC_EXT_CLK_BUF_EN_MASK) + +#define WLAN_AHB_BRIDGE_TIMEOUT_ADDRESS 0x00000334 +#define WLAN_AHB_BRIDGE_TIMEOUT_OFFSET 0x00000334 +#define WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_MSB 13 +#define WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_LSB 0 +#define WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_MASK 0x00003fff +#define WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_GET(x) (((x) & WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_MASK) >> WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_LSB) +#define WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_SET(x) (((x) << WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_LSB) & WLAN_AHB_BRIDGE_TIMEOUT_CONFIG_MASK) + +#define WLAN_AHB_CONFIG_ADDRESS 0x00000338 +#define WLAN_AHB_CONFIG_OFFSET 0x00000338 +#define WLAN_AHB_CONFIG_MAX_BURST_16_MSB 2 +#define WLAN_AHB_CONFIG_MAX_BURST_16_LSB 2 +#define WLAN_AHB_CONFIG_MAX_BURST_16_MASK 0x00000004 +#define WLAN_AHB_CONFIG_MAX_BURST_16_GET(x) (((x) & WLAN_AHB_CONFIG_MAX_BURST_16_MASK) >> WLAN_AHB_CONFIG_MAX_BURST_16_LSB) +#define WLAN_AHB_CONFIG_MAX_BURST_16_SET(x) (((x) << WLAN_AHB_CONFIG_MAX_BURST_16_LSB) & WLAN_AHB_CONFIG_MAX_BURST_16_MASK) +#define WLAN_AHB_CONFIG_MAX_BURST_8_MSB 1 +#define WLAN_AHB_CONFIG_MAX_BURST_8_LSB 1 +#define WLAN_AHB_CONFIG_MAX_BURST_8_MASK 0x00000002 +#define WLAN_AHB_CONFIG_MAX_BURST_8_GET(x) (((x) & WLAN_AHB_CONFIG_MAX_BURST_8_MASK) >> WLAN_AHB_CONFIG_MAX_BURST_8_LSB) +#define WLAN_AHB_CONFIG_MAX_BURST_8_SET(x) (((x) << WLAN_AHB_CONFIG_MAX_BURST_8_LSB) & WLAN_AHB_CONFIG_MAX_BURST_8_MASK) +#define WLAN_AHB_CONFIG_MAX_BURST_4_MSB 0 +#define WLAN_AHB_CONFIG_MAX_BURST_4_LSB 0 +#define WLAN_AHB_CONFIG_MAX_BURST_4_MASK 0x00000001 +#define WLAN_AHB_CONFIG_MAX_BURST_4_GET(x) (((x) & WLAN_AHB_CONFIG_MAX_BURST_4_MASK) >> WLAN_AHB_CONFIG_MAX_BURST_4_LSB) +#define WLAN_AHB_CONFIG_MAX_BURST_4_SET(x) (((x) << WLAN_AHB_CONFIG_MAX_BURST_4_LSB) & WLAN_AHB_CONFIG_MAX_BURST_4_MASK) + +#define RTC_AXI_AHB_BRIDGE_ADDRESS 0x0000033c +#define RTC_AXI_AHB_BRIDGE_OFFSET 0x0000033c +#define RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_MSB 3 +#define RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_LSB 3 +#define RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_MASK 0x00000008 +#define RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_GET(x) (((x) & RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_MASK) >> RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_LSB) +#define RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_SET(x) (((x) << RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_LSB) & RTC_AXI_AHB_BRIDGE_BURST_WR_ALIGN_EN_MASK) +#define RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_MSB 2 +#define RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_LSB 2 +#define RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_MASK 0x00000004 +#define RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_GET(x) (((x) & RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_MASK) >> RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_LSB) +#define RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_SET(x) (((x) << RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_LSB) & RTC_AXI_AHB_BRIDGE_BURST_RD_ALIGN_EN_MASK) +#define RTC_AXI_AHB_BRIDGE_MAX_BEATS_MSB 1 +#define RTC_AXI_AHB_BRIDGE_MAX_BEATS_LSB 0 +#define RTC_AXI_AHB_BRIDGE_MAX_BEATS_MASK 0x00000003 +#define RTC_AXI_AHB_BRIDGE_MAX_BEATS_GET(x) (((x) & RTC_AXI_AHB_BRIDGE_MAX_BEATS_MASK) >> RTC_AXI_AHB_BRIDGE_MAX_BEATS_LSB) +#define RTC_AXI_AHB_BRIDGE_MAX_BEATS_SET(x) (((x) << RTC_AXI_AHB_BRIDGE_MAX_BEATS_LSB) & RTC_AXI_AHB_BRIDGE_MAX_BEATS_MASK) + +#define WLAN2BT_CPUCOM_INT_STS_ADDRESS 0x00000400 +#define WLAN2BT_CPUCOM_INT_STS_OFFSET 0x00000400 +#define WLAN2BT_CPUCOM_INT_STS_REG_MSB 31 +#define WLAN2BT_CPUCOM_INT_STS_REG_LSB 0 +#define WLAN2BT_CPUCOM_INT_STS_REG_MASK 0xffffffff +#define WLAN2BT_CPUCOM_INT_STS_REG_GET(x) (((x) & WLAN2BT_CPUCOM_INT_STS_REG_MASK) >> WLAN2BT_CPUCOM_INT_STS_REG_LSB) +#define WLAN2BT_CPUCOM_INT_STS_REG_SET(x) (((x) << WLAN2BT_CPUCOM_INT_STS_REG_LSB) & WLAN2BT_CPUCOM_INT_STS_REG_MASK) + +#define WLAN2BT_CPUCOM_INT_MASK_N_ADDRESS 0x00000404 +#define WLAN2BT_CPUCOM_INT_MASK_N_OFFSET 0x00000404 +#define WLAN2BT_CPUCOM_INT_MASK_N_REG_MSB 31 +#define WLAN2BT_CPUCOM_INT_MASK_N_REG_LSB 0 +#define WLAN2BT_CPUCOM_INT_MASK_N_REG_MASK 0xffffffff +#define WLAN2BT_CPUCOM_INT_MASK_N_REG_GET(x) (((x) & WLAN2BT_CPUCOM_INT_MASK_N_REG_MASK) >> WLAN2BT_CPUCOM_INT_MASK_N_REG_LSB) +#define WLAN2BT_CPUCOM_INT_MASK_N_REG_SET(x) (((x) << WLAN2BT_CPUCOM_INT_MASK_N_REG_LSB) & WLAN2BT_CPUCOM_INT_MASK_N_REG_MASK) + +#define WLAN2BT_CPUCOM_INT_EOI_ADDRESS 0x00000408 +#define WLAN2BT_CPUCOM_INT_EOI_OFFSET 0x00000408 +#define WLAN2BT_CPUCOM_INT_EOI_REG_MSB 31 +#define WLAN2BT_CPUCOM_INT_EOI_REG_LSB 0 +#define WLAN2BT_CPUCOM_INT_EOI_REG_MASK 0xffffffff +#define WLAN2BT_CPUCOM_INT_EOI_REG_GET(x) (((x) & WLAN2BT_CPUCOM_INT_EOI_REG_MASK) >> WLAN2BT_CPUCOM_INT_EOI_REG_LSB) +#define WLAN2BT_CPUCOM_INT_EOI_REG_SET(x) (((x) << WLAN2BT_CPUCOM_INT_EOI_REG_LSB) & WLAN2BT_CPUCOM_INT_EOI_REG_MASK) + +#define WLAN2BT_CPUCOM_INT_ACK_STS_ADDRESS 0x0000040c +#define WLAN2BT_CPUCOM_INT_ACK_STS_OFFSET 0x0000040c +#define WLAN2BT_CPUCOM_INT_ACK_STS_REG_MSB 31 +#define WLAN2BT_CPUCOM_INT_ACK_STS_REG_LSB 0 +#define WLAN2BT_CPUCOM_INT_ACK_STS_REG_MASK 0xffffffff +#define WLAN2BT_CPUCOM_INT_ACK_STS_REG_GET(x) (((x) & WLAN2BT_CPUCOM_INT_ACK_STS_REG_MASK) >> WLAN2BT_CPUCOM_INT_ACK_STS_REG_LSB) +#define WLAN2BT_CPUCOM_INT_ACK_STS_REG_SET(x) (((x) << WLAN2BT_CPUCOM_INT_ACK_STS_REG_LSB) & WLAN2BT_CPUCOM_INT_ACK_STS_REG_MASK) + +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_ADDRESS 0x00000410 +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_OFFSET 0x00000410 +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_MSB 31 +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_LSB 0 +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_MASK 0xffffffff +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_GET(x) (((x) & WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_MASK) >> WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_LSB) +#define WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_SET(x) (((x) << WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_LSB) & WLAN2BT_CPUCOM_INT_ACK_MASK_N_REG_MASK) + +#define WLAN_CPUCOM_CRD_CNT0_ADDRESS 0x00000414 +#define WLAN_CPUCOM_CRD_CNT0_OFFSET 0x00000414 +#define WLAN_CPUCOM_CRD_CNT0_REG_MSB 15 +#define WLAN_CPUCOM_CRD_CNT0_REG_LSB 0 +#define WLAN_CPUCOM_CRD_CNT0_REG_MASK 0x0000ffff +#define WLAN_CPUCOM_CRD_CNT0_REG_GET(x) (((x) & WLAN_CPUCOM_CRD_CNT0_REG_MASK) >> WLAN_CPUCOM_CRD_CNT0_REG_LSB) +#define WLAN_CPUCOM_CRD_CNT0_REG_SET(x) (((x) << WLAN_CPUCOM_CRD_CNT0_REG_LSB) & WLAN_CPUCOM_CRD_CNT0_REG_MASK) + +#define WLAN_CPUCOM_CRD_INC0_ADDRESS 0x00000418 +#define WLAN_CPUCOM_CRD_INC0_OFFSET 0x00000418 +#define WLAN_CPUCOM_CRD_INC0_REG_MSB 15 +#define WLAN_CPUCOM_CRD_INC0_REG_LSB 0 +#define WLAN_CPUCOM_CRD_INC0_REG_MASK 0x0000ffff +#define WLAN_CPUCOM_CRD_INC0_REG_GET(x) (((x) & WLAN_CPUCOM_CRD_INC0_REG_MASK) >> WLAN_CPUCOM_CRD_INC0_REG_LSB) +#define WLAN_CPUCOM_CRD_INC0_REG_SET(x) (((x) << WLAN_CPUCOM_CRD_INC0_REG_LSB) & WLAN_CPUCOM_CRD_INC0_REG_MASK) + +#define WLAN_CPUCOM_CRD_DEC0_ADDRESS 0x0000041c +#define WLAN_CPUCOM_CRD_DEC0_OFFSET 0x0000041c +#define WLAN_CPUCOM_CRD_DEC0_REG_MSB 15 +#define WLAN_CPUCOM_CRD_DEC0_REG_LSB 0 +#define WLAN_CPUCOM_CRD_DEC0_REG_MASK 0x0000ffff +#define WLAN_CPUCOM_CRD_DEC0_REG_GET(x) (((x) & WLAN_CPUCOM_CRD_DEC0_REG_MASK) >> WLAN_CPUCOM_CRD_DEC0_REG_LSB) +#define WLAN_CPUCOM_CRD_DEC0_REG_SET(x) (((x) << WLAN_CPUCOM_CRD_DEC0_REG_LSB) & WLAN_CPUCOM_CRD_DEC0_REG_MASK) + +#define WLAN_CPUCOM_CRD_CNT1_ADDRESS 0x00000420 +#define WLAN_CPUCOM_CRD_CNT1_OFFSET 0x00000420 +#define WLAN_CPUCOM_CRD_CNT1_REG_MSB 15 +#define WLAN_CPUCOM_CRD_CNT1_REG_LSB 0 +#define WLAN_CPUCOM_CRD_CNT1_REG_MASK 0x0000ffff +#define WLAN_CPUCOM_CRD_CNT1_REG_GET(x) (((x) & WLAN_CPUCOM_CRD_CNT1_REG_MASK) >> WLAN_CPUCOM_CRD_CNT1_REG_LSB) +#define WLAN_CPUCOM_CRD_CNT1_REG_SET(x) (((x) << WLAN_CPUCOM_CRD_CNT1_REG_LSB) & WLAN_CPUCOM_CRD_CNT1_REG_MASK) + +#define WLAN_CPUCOM_CRD_INC1_ADDRESS 0x00000424 +#define WLAN_CPUCOM_CRD_INC1_OFFSET 0x00000424 +#define WLAN_CPUCOM_CRD_INC1_REG_MSB 15 +#define WLAN_CPUCOM_CRD_INC1_REG_LSB 0 +#define WLAN_CPUCOM_CRD_INC1_REG_MASK 0x0000ffff +#define WLAN_CPUCOM_CRD_INC1_REG_GET(x) (((x) & WLAN_CPUCOM_CRD_INC1_REG_MASK) >> WLAN_CPUCOM_CRD_INC1_REG_LSB) +#define WLAN_CPUCOM_CRD_INC1_REG_SET(x) (((x) << WLAN_CPUCOM_CRD_INC1_REG_LSB) & WLAN_CPUCOM_CRD_INC1_REG_MASK) + +#define WLAN_CPUCOM_CRD_DEC1_ADDRESS 0x00000428 +#define WLAN_CPUCOM_CRD_DEC1_OFFSET 0x00000428 +#define WLAN_CPUCOM_CRD_DEC1_REG_MSB 15 +#define WLAN_CPUCOM_CRD_DEC1_REG_LSB 0 +#define WLAN_CPUCOM_CRD_DEC1_REG_MASK 0x0000ffff +#define WLAN_CPUCOM_CRD_DEC1_REG_GET(x) (((x) & WLAN_CPUCOM_CRD_DEC1_REG_MASK) >> WLAN_CPUCOM_CRD_DEC1_REG_LSB) +#define WLAN_CPUCOM_CRD_DEC1_REG_SET(x) (((x) << WLAN_CPUCOM_CRD_DEC1_REG_LSB) & WLAN_CPUCOM_CRD_DEC1_REG_MASK) + +#define WLAN_CPUCOM_SCRATCH0_ADDRESS 0x0000042c +#define WLAN_CPUCOM_SCRATCH0_OFFSET 0x0000042c +#define WLAN_CPUCOM_SCRATCH0_REG_MSB 31 +#define WLAN_CPUCOM_SCRATCH0_REG_LSB 0 +#define WLAN_CPUCOM_SCRATCH0_REG_MASK 0xffffffff +#define WLAN_CPUCOM_SCRATCH0_REG_GET(x) (((x) & WLAN_CPUCOM_SCRATCH0_REG_MASK) >> WLAN_CPUCOM_SCRATCH0_REG_LSB) +#define WLAN_CPUCOM_SCRATCH0_REG_SET(x) (((x) << WLAN_CPUCOM_SCRATCH0_REG_LSB) & WLAN_CPUCOM_SCRATCH0_REG_MASK) + +#define WLAN_CPUCOM_SCRATCH1_ADDRESS 0x00000430 +#define WLAN_CPUCOM_SCRATCH1_OFFSET 0x00000430 +#define WLAN_CPUCOM_SCRATCH1_REG_MSB 31 +#define WLAN_CPUCOM_SCRATCH1_REG_LSB 0 +#define WLAN_CPUCOM_SCRATCH1_REG_MASK 0xffffffff +#define WLAN_CPUCOM_SCRATCH1_REG_GET(x) (((x) & WLAN_CPUCOM_SCRATCH1_REG_MASK) >> WLAN_CPUCOM_SCRATCH1_REG_LSB) +#define WLAN_CPUCOM_SCRATCH1_REG_SET(x) (((x) << WLAN_CPUCOM_SCRATCH1_REG_LSB) & WLAN_CPUCOM_SCRATCH1_REG_MASK) + +#define WLAN_CPUCOM_SCRATCH2_ADDRESS 0x00000434 +#define WLAN_CPUCOM_SCRATCH2_OFFSET 0x00000434 +#define WLAN_CPUCOM_SCRATCH2_REG_MSB 31 +#define WLAN_CPUCOM_SCRATCH2_REG_LSB 0 +#define WLAN_CPUCOM_SCRATCH2_REG_MASK 0xffffffff +#define WLAN_CPUCOM_SCRATCH2_REG_GET(x) (((x) & WLAN_CPUCOM_SCRATCH2_REG_MASK) >> WLAN_CPUCOM_SCRATCH2_REG_LSB) +#define WLAN_CPUCOM_SCRATCH2_REG_SET(x) (((x) << WLAN_CPUCOM_SCRATCH2_REG_LSB) & WLAN_CPUCOM_SCRATCH2_REG_MASK) + +#define WLAN_CPUCOM_SCRATCH3_ADDRESS 0x00000438 +#define WLAN_CPUCOM_SCRATCH3_OFFSET 0x00000438 +#define WLAN_CPUCOM_SCRATCH3_REG_MSB 31 +#define WLAN_CPUCOM_SCRATCH3_REG_LSB 0 +#define WLAN_CPUCOM_SCRATCH3_REG_MASK 0xffffffff +#define WLAN_CPUCOM_SCRATCH3_REG_GET(x) (((x) & WLAN_CPUCOM_SCRATCH3_REG_MASK) >> WLAN_CPUCOM_SCRATCH3_REG_LSB) +#define WLAN_CPUCOM_SCRATCH3_REG_SET(x) (((x) << WLAN_CPUCOM_SCRATCH3_REG_LSB) & WLAN_CPUCOM_SCRATCH3_REG_MASK) + +#define WLAN_CPUCOM_DBG_ADDRESS 0x0000043c +#define WLAN_CPUCOM_DBG_OFFSET 0x0000043c +#define WLAN_CPUCOM_DBG_RESERVE_MSB 7 +#define WLAN_CPUCOM_DBG_RESERVE_LSB 4 +#define WLAN_CPUCOM_DBG_RESERVE_MASK 0x000000f0 +#define WLAN_CPUCOM_DBG_RESERVE_GET(x) (((x) & WLAN_CPUCOM_DBG_RESERVE_MASK) >> WLAN_CPUCOM_DBG_RESERVE_LSB) +#define WLAN_CPUCOM_DBG_RESERVE_SET(x) (((x) << WLAN_CPUCOM_DBG_RESERVE_LSB) & WLAN_CPUCOM_DBG_RESERVE_MASK) +#define WLAN_CPUCOM_DBG_CRD1_DEC_ERR_MSB 3 +#define WLAN_CPUCOM_DBG_CRD1_DEC_ERR_LSB 3 +#define WLAN_CPUCOM_DBG_CRD1_DEC_ERR_MASK 0x00000008 +#define WLAN_CPUCOM_DBG_CRD1_DEC_ERR_GET(x) (((x) & WLAN_CPUCOM_DBG_CRD1_DEC_ERR_MASK) >> WLAN_CPUCOM_DBG_CRD1_DEC_ERR_LSB) +#define WLAN_CPUCOM_DBG_CRD1_DEC_ERR_SET(x) (((x) << WLAN_CPUCOM_DBG_CRD1_DEC_ERR_LSB) & WLAN_CPUCOM_DBG_CRD1_DEC_ERR_MASK) +#define WLAN_CPUCOM_DBG_CRD1_INC_ERR_MSB 2 +#define WLAN_CPUCOM_DBG_CRD1_INC_ERR_LSB 2 +#define WLAN_CPUCOM_DBG_CRD1_INC_ERR_MASK 0x00000004 +#define WLAN_CPUCOM_DBG_CRD1_INC_ERR_GET(x) (((x) & WLAN_CPUCOM_DBG_CRD1_INC_ERR_MASK) >> WLAN_CPUCOM_DBG_CRD1_INC_ERR_LSB) +#define WLAN_CPUCOM_DBG_CRD1_INC_ERR_SET(x) (((x) << WLAN_CPUCOM_DBG_CRD1_INC_ERR_LSB) & WLAN_CPUCOM_DBG_CRD1_INC_ERR_MASK) +#define WLAN_CPUCOM_DBG_CRD0_DEC_ERR_MSB 1 +#define WLAN_CPUCOM_DBG_CRD0_DEC_ERR_LSB 1 +#define WLAN_CPUCOM_DBG_CRD0_DEC_ERR_MASK 0x00000002 +#define WLAN_CPUCOM_DBG_CRD0_DEC_ERR_GET(x) (((x) & WLAN_CPUCOM_DBG_CRD0_DEC_ERR_MASK) >> WLAN_CPUCOM_DBG_CRD0_DEC_ERR_LSB) +#define WLAN_CPUCOM_DBG_CRD0_DEC_ERR_SET(x) (((x) << WLAN_CPUCOM_DBG_CRD0_DEC_ERR_LSB) & WLAN_CPUCOM_DBG_CRD0_DEC_ERR_MASK) +#define WLAN_CPUCOM_DBG_CRD0_INC_ERR_MSB 0 +#define WLAN_CPUCOM_DBG_CRD0_INC_ERR_LSB 0 +#define WLAN_CPUCOM_DBG_CRD0_INC_ERR_MASK 0x00000001 +#define WLAN_CPUCOM_DBG_CRD0_INC_ERR_GET(x) (((x) & WLAN_CPUCOM_DBG_CRD0_INC_ERR_MASK) >> WLAN_CPUCOM_DBG_CRD0_INC_ERR_LSB) +#define WLAN_CPUCOM_DBG_CRD0_INC_ERR_SET(x) (((x) << WLAN_CPUCOM_DBG_CRD0_INC_ERR_LSB) & WLAN_CPUCOM_DBG_CRD0_INC_ERR_MASK) + +#define WLAN2BT_CPUCOM_INT_ACK_EN_ADDRESS 0x00000440 +#define WLAN2BT_CPUCOM_INT_ACK_EN_OFFSET 0x00000440 +#define WLAN2BT_CPUCOM_INT_ACK_EN_REG_MSB 0 +#define WLAN2BT_CPUCOM_INT_ACK_EN_REG_LSB 0 +#define WLAN2BT_CPUCOM_INT_ACK_EN_REG_MASK 0x00000001 +#define WLAN2BT_CPUCOM_INT_ACK_EN_REG_GET(x) (((x) & WLAN2BT_CPUCOM_INT_ACK_EN_REG_MASK) >> WLAN2BT_CPUCOM_INT_ACK_EN_REG_LSB) +#define WLAN2BT_CPUCOM_INT_ACK_EN_REG_SET(x) (((x) << WLAN2BT_CPUCOM_INT_ACK_EN_REG_LSB) & WLAN2BT_CPUCOM_INT_ACK_EN_REG_MASK) + +#define BT2WLAN_CPUCOM_INT_EN_ADDRESS 0x00000444 +#define BT2WLAN_CPUCOM_INT_EN_OFFSET 0x00000444 +#define BT2WLAN_CPUCOM_INT_EN_REG_MSB 0 +#define BT2WLAN_CPUCOM_INT_EN_REG_LSB 0 +#define BT2WLAN_CPUCOM_INT_EN_REG_MASK 0x00000001 +#define BT2WLAN_CPUCOM_INT_EN_REG_GET(x) (((x) & BT2WLAN_CPUCOM_INT_EN_REG_MASK) >> BT2WLAN_CPUCOM_INT_EN_REG_LSB) +#define BT2WLAN_CPUCOM_INT_EN_REG_SET(x) (((x) << BT2WLAN_CPUCOM_INT_EN_REG_LSB) & BT2WLAN_CPUCOM_INT_EN_REG_MASK) + +#ifndef __ASSEMBLER__ +typedef struct rtc_soc_reg_reg_s { + volatile unsigned int soc_reset_control; + volatile unsigned int soc_tcxo_detect; + volatile unsigned int soc_xtal_test; + unsigned char pad0[20]; /* pad to 0x20 */ + volatile unsigned int soc_cpu_clock; + unsigned char pad1[4]; /* pad to 0x28 */ + volatile unsigned int soc_clock_control; + unsigned char pad2[4]; /* pad to 0x30 */ + volatile unsigned int soc_wdt_control; + volatile unsigned int soc_wdt_status; + volatile unsigned int soc_wdt; + volatile unsigned int soc_wdt_count; + volatile unsigned int soc_wdt_reset; + volatile unsigned int soc_int_status; + volatile unsigned int soc_lf_timer0; + volatile unsigned int soc_lf_timer_count0; + volatile unsigned int soc_lf_timer_control0; + volatile unsigned int soc_lf_timer_status0; + volatile unsigned int soc_lf_timer1; + volatile unsigned int soc_lf_timer_count1; + volatile unsigned int soc_lf_timer_control1; + volatile unsigned int soc_lf_timer_status1; + volatile unsigned int soc_lf_timer2; + volatile unsigned int soc_lf_timer_count2; + volatile unsigned int soc_lf_timer_control2; + volatile unsigned int soc_lf_timer_status2; + volatile unsigned int soc_lf_timer3; + volatile unsigned int soc_lf_timer_count3; + volatile unsigned int soc_lf_timer_control3; + volatile unsigned int soc_lf_timer_status3; + volatile unsigned int soc_hf_timer; + volatile unsigned int soc_hf_timer_count; + volatile unsigned int soc_hf_lf_count; + volatile unsigned int soc_hf_timer_control; + volatile unsigned int soc_hf_timer_status; + volatile unsigned int soc_rtc_control; + volatile unsigned int soc_rtc_time; + volatile unsigned int soc_rtc_date; + volatile unsigned int soc_rtc_set_time; + volatile unsigned int soc_rtc_set_date; + volatile unsigned int soc_rtc_set_alarm; + volatile unsigned int soc_rtc_config; + volatile unsigned int soc_rtc_alarm_status; + volatile unsigned int soc_uart_wakeup; + volatile unsigned int soc_reset_cause; + volatile unsigned int soc_system_sleep; + volatile unsigned int soc_sdio_wrapper; + volatile unsigned int soc_int_sleep_mask; + unsigned char pad3[4]; /* pad to 0xd4 */ + volatile unsigned int soc_lpo_cal_time; + volatile unsigned int soc_lpo_init_dividend_int; + volatile unsigned int soc_lpo_init_dividend_fraction; + volatile unsigned int soc_lpo_cal; + volatile unsigned int soc_lpo_cal_test_control; + volatile unsigned int soc_lpo_cal_test_status; + volatile unsigned int legacy_soc_chip_id; + volatile unsigned int soc_chip_id; + unsigned char pad4[24]; /* pad to 0x10c */ + volatile unsigned int soc_power_reg; + volatile unsigned int soc_core_clk_ctrl; + volatile unsigned int soc_gpio_wakeup_control; + unsigned char pad5[252]; /* pad to 0x214 */ + volatile unsigned int sleep_retention; + unsigned char pad6[108]; /* pad to 0x284 */ + volatile unsigned int lp_perf_counter; + volatile unsigned int lp_perf_light_sleep; + volatile unsigned int lp_perf_deep_sleep; + volatile unsigned int lp_perf_on; + unsigned char pad7[20]; /* pad to 0x2a8 */ + volatile unsigned int chip_mode; + volatile unsigned int clk_req_fall_edge; + volatile unsigned int otp; + volatile unsigned int otp_status; + volatile unsigned int pmu; + volatile unsigned int pmu_config; + volatile unsigned int pmu_pareg; + volatile unsigned int pmu_bypass; + unsigned char pad8[20]; /* pad to 0x2dc */ + volatile unsigned int therm_ctrl1; + volatile unsigned int therm_ctrl2; + volatile unsigned int therm_ctrl3; + volatile unsigned int listen_mode1; + volatile unsigned int listen_mode2; + volatile unsigned int audio_pll_config; + volatile unsigned int audio_pll_modulation; + volatile unsigned int audio_pll_mod_step; + volatile unsigned int current_audio_pll_modulation; + volatile unsigned int eth_pll_config; + volatile unsigned int cpu_pll_config; + volatile unsigned int bb_pll_config; + volatile unsigned int eth_xmii; + volatile unsigned int usb_phy_config; + volatile unsigned int usbcore_clk60m; + volatile unsigned int usbphy_utmi_clk; + volatile unsigned int usb_txvalid_dly_config; + volatile unsigned int second_host_inft; + volatile unsigned int sdio_host; + volatile unsigned int enterprise_config; + volatile unsigned int rtc_debug_bus; + volatile unsigned int rtc_ext_clk_buf; + volatile unsigned int wlan_ahb_bridge_timeout; + volatile unsigned int wlan_ahb_config; + volatile unsigned int rtc_axi_ahb_bridge; + unsigned char pad9[192]; /* pad to 0x400 */ + volatile unsigned int wlan2bt_cpucom_int_sts; + volatile unsigned int wlan2bt_cpucom_int_mask_n; + volatile unsigned int wlan2bt_cpucom_int_eoi; + volatile unsigned int wlan2bt_cpucom_int_ack_sts; + volatile unsigned int wlan2bt_cpucom_int_ack_mask_n; + volatile unsigned int wlan_cpucom_crd_cnt0; + volatile unsigned int wlan_cpucom_crd_inc0[1]; + volatile unsigned int wlan_cpucom_crd_dec0[1]; + volatile unsigned int wlan_cpucom_crd_cnt1; + volatile unsigned int wlan_cpucom_crd_inc1[1]; + volatile unsigned int wlan_cpucom_crd_dec1[1]; + volatile unsigned int wlan_cpucom_scratch0; + volatile unsigned int wlan_cpucom_scratch1; + volatile unsigned int wlan_cpucom_scratch2; + volatile unsigned int wlan_cpucom_scratch3; + volatile unsigned int wlan_cpucom_dbg; + volatile unsigned int wlan2bt_cpucom_int_ack_en; + volatile unsigned int bt2wlan_cpucom_int_en; +} rtc_soc_reg_reg_t; +#endif /* __ASSEMBLER__ */ + +#endif /* _RTC_SOC_REG_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/sys/queue.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/sys/queue.h new file mode 100644 index 000000000000..a1b620721cea --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/sys/queue.h @@ -0,0 +1,576 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.58 2004/04/07 04:19:49 imp Exp $ + */ + +#if !defined(__NetBSD__) +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#define QUEUE_MACRO_DEBUG 0 +#if QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)NULL;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) do {(x) = (void *)0;} while (0) +#endif /* QUEUE_MACRO_DEBUG */ + +#ifdef ATHR_RNWF +/* NDIS contains a defn for SLIST_ENTRY and SINGLE_LIST_ENTRY */ +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SING_LIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ + } \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ +} while (0) + + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if (STAILQ_NEXT(elm, field)) { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + } \ +} while (0) + + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define ATH_LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#ifndef LIST_HEAD +#define LIST_HEAD ATH_LIST_HEAD +#endif + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define HEADNAME +#define COPY_HEADNAME(head) + +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + HEADNAME \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + COPY_HEADNAME(head); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (0) + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !(__GNUC__ || __INTEL_COMPILER) */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __GNUC__ || __INTEL_COMPILER */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ +#else /* !__NetBSD__ */ +#include_next +#endif /* __NetBSD__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targaddrs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targaddrs.h new file mode 100644 index 000000000000..d40192c8de62 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targaddrs.h @@ -0,0 +1,689 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __TARGADDRS_H__ +#define __TARGADDRS_H__ + +#if defined(ATH_TARGET) +#include "soc_addrs.h" +#endif + +#if !defined(ATH_TARGET) +#include "athstartpack.h" +#endif + +/* + * SOC option bits, to enable/disable various features. + * By default, all option bits are 0. + * AR6004: These bits can be set in LOCAL_SCRATCH register 0. + * AR9888: These bits can be set in soc_core register SCRATCH_0. + */ +#define SOC_OPTION_BMI_DISABLE 0x01 /* Disable BMI comm with Host */ +#define SOC_OPTION_SERIAL_ENABLE 0x02 /* Enable serial port msgs */ +#define SOC_OPTION_WDT_DISABLE 0x04 /* WatchDog Timer override */ +#define SOC_OPTION_SLEEP_DISABLE 0x08 /* Disable system sleep */ +#define SOC_OPTION_STOP_BOOT 0x10 /* Stop boot processes (for ATE) */ +#define SOC_OPTION_ENABLE_NOANI 0x20 /* Operate without ANI */ +#define SOC_OPTION_DSET_DISABLE 0x40 /* Ignore DataSets */ +#define SOC_OPTION_IGNORE_FLASH 0x80 /* Ignore flash during bootup */ + +/* + * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the + * host_interest structure. It must match the address of the _host_interest + * symbol (see linker script). + * + * Host Interest is shared between Host and Target in order to coordinate + * between the two, and is intended to remain constant (with additions only + * at the end) across software releases. + * + * All addresses are available here so that it's possible to + * write a single binary that works with all Target Types. + * May be used in assembler code as well as C. + */ +#define AR6002_HOST_INTEREST_ADDRESS 0x00500400 +#define AR6003_HOST_INTEREST_ADDRESS 0x00540600 +#define AR6004_HOST_INTEREST_ADDRESS 0x00400800 +#define AR9888_HOST_INTEREST_ADDRESS 0x00400800 +#define AR900B_HOST_INTEREST_ADDRESS 0x00400800 +#define AR6320_HOST_INTEREST_ADDRESS 0x00400800 +#define AR6004_SOC_RESET_ADDRESS 0X00004000 +#define AR6004_SOC_RESET_CPU_INIT_RESET_MASK 0X00000800 +#if defined(AR6006_MEMORY_NEW_ARCH) +#define AR6006_HOST_INTEREST_ADDRESS 0x00428800 +#else +#define AR6006_HOST_INTEREST_ADDRESS 0x00400800 +#endif +#define AR6006_SOC_RESET_ADDRESS 0X00004000 +#define AR6006_SOC_RESET_CPU_INIT_RESET_MASK 0X00000800 + + + +#define HOST_INTEREST_MAX_SIZE 0x200 + +#if !defined(__ASSEMBLER__) +struct register_dump_s; +struct dbglog_hdr_s; + +/* + * These are items that the Host may need to access + * via BMI or via the Diagnostic Window. The position + * of items in this structure must remain constant + * across firmware revisions! + * + * Types for each item must be fixed size across + * target and host platforms. + * + * More items may be added at the end. + */ +PREPACK64 struct host_interest_s { + /* + * Pointer to application-defined area, if any. + * Set by Target application during startup. + */ + A_UINT32 hi_app_host_interest; /* 0x00 */ + + /* Pointer to register dump area, valid after Target crash. */ + A_UINT32 hi_failure_state; /* 0x04 */ + + /* Pointer to debug logging header */ + A_UINT32 hi_dbglog_hdr; /* 0x08 */ + + /* Save SW ROM version */ + A_UINT32 hi_sw_rom_version; /* 0x0c */ + + /* + * General-purpose flag bits, similar to SOC_OPTION_* flags. + * Can be used by application rather than by OS. + */ + A_UINT32 hi_option_flag; /* 0x10 */ + + /* + * Boolean that determines whether or not to + * display messages on the serial port. + */ + A_UINT32 hi_serial_enable; /* 0x14 */ + + /* Start address of DataSet index, if any */ + A_UINT32 hi_dset_list_head; /* 0x18 */ + + /* Override Target application start address */ + A_UINT32 hi_app_start; /* 0x1c */ + + /* Clock and voltage tuning */ + A_UINT32 hi_skip_clock_init; /* 0x20 */ + A_UINT32 hi_core_clock_setting; /* 0x24 */ + A_UINT32 hi_cpu_clock_setting; /* 0x28 */ + A_UINT32 hi_system_sleep_setting; /* 0x2c */ + A_UINT32 hi_xtal_control_setting; /* 0x30 */ + A_UINT32 hi_pll_ctrl_setting_24ghz; /* 0x34 */ + A_UINT32 hi_pll_ctrl_setting_5ghz; /* 0x38 */ + A_UINT32 hi_ref_voltage_trim_setting; /* 0x3c */ + A_UINT32 hi_clock_info; /* 0x40 */ + + /* Host uses BE CPU or not */ + A_UINT32 hi_be; /* 0x44 */ + + A_UINT32 hi_stack; /* normal stack */ /* 0x48 */ + A_UINT32 hi_err_stack; /* error stack */ /* 0x4c */ + A_UINT32 hi_desired_cpu_speed_hz; /* 0x50 */ + + /* Pointer to Board Data */ + A_UINT32 hi_board_data; /* 0x54 */ + + /* + * Indication of Board Data state: + * 0: board data is not yet initialized. + * 1: board data is initialized; unknown size + * >1: number of bytes of initialized board data (varies with board type) + */ + A_UINT32 hi_board_data_initialized; /* 0x58 */ + + A_UINT32 hi_dset_RAM_index_table; /* 0x5c */ + + A_UINT32 hi_desired_baud_rate; /* 0x60 */ + A_UINT32 hi_dbglog_config; /* 0x64 */ + A_UINT32 hi_end_RAM_reserve_sz; /* 0x68 */ + A_UINT32 hi_mbox_io_block_sz; /* 0x6c */ + + A_UINT32 hi_num_bpatch_streams; /* 0x70 -- unused */ + A_UINT32 hi_mbox_isr_yield_limit; /* 0x74 */ + + A_UINT32 hi_refclk_hz; /* 0x78 */ + A_UINT32 hi_ext_clk_detected; /* 0x7c */ + A_UINT32 hi_dbg_uart_txpin; /* 0x80 */ + A_UINT32 hi_dbg_uart_rxpin; /* 0x84 */ + A_UINT32 hi_hci_uart_baud; /* 0x88 */ + A_UINT32 hi_hci_uart_pin_assignments; /* 0x8C */ + /* NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts pin */ + A_UINT32 hi_hci_uart_baud_scale_val; /* 0x90 */ + A_UINT32 hi_hci_uart_baud_step_val; /* 0x94 */ + + A_UINT32 hi_allocram_start; /* 0x98 */ + A_UINT32 hi_allocram_sz; /* 0x9c */ + A_UINT32 hi_hci_bridge_flags; /* 0xa0 */ + A_UINT32 hi_hci_uart_support_pins; /* 0xa4 */ + /* NOTE: byte [0] = RESET pin (bit 7 is polarity), bytes[1]..bytes[3] are for future use */ + A_UINT32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */ + /* 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high + * [31:16]: wakeup timeout in ms + */ + /* Pointer to extended board Data */ + A_UINT32 hi_board_ext_data; /* 0xac */ + A_UINT32 hi_board_ext_data_config; /* 0xb0 */ + /* + * Bit [0] : valid + * Bit[31:16: size + */ + /* + * hi_reset_flag is used to do some stuff when target reset. + * such as restore app_start after warm reset or + * preserve host Interest area, or preserve ROM data, literals etc. + */ + A_UINT32 hi_reset_flag; /* 0xb4 */ + /* indicate hi_reset_flag is valid */ + A_UINT32 hi_reset_flag_valid; /* 0xb8 */ + A_UINT32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */ + /* 0xbc - [31:0]: idle timeout in ms + */ + /* ACS flags */ + A_UINT32 hi_acs_flags; /* 0xc0 */ + A_UINT32 hi_console_flags; /* 0xc4 */ + A_UINT32 hi_nvram_state; /* 0xc8 */ + A_UINT32 hi_option_flag2; /* 0xcc */ + + /* If non-zero, override values sent to Host in WMI_READY event. */ + A_UINT32 hi_sw_version_override; /* 0xd0 */ + A_UINT32 hi_abi_version_override; /* 0xd4 */ + + /* Percentage of high priority RX traffic to total expected RX traffic - + * applicable only to ar6004 */ + A_UINT32 hi_hp_rx_traffic_ratio; /* 0xd8 */ + + /* test applications flags */ + A_UINT32 hi_test_apps_related ; /* 0xdc */ + /* location of test script */ + A_UINT32 hi_ota_testscript; /* 0xe0 */ + /* location of CAL data */ + A_UINT32 hi_cal_data; /* 0xe4 */ + + /* Number of packet log buffers */ + A_UINT32 hi_pktlog_num_buffers; /* 0xe8 */ + + /* wow extension configuration */ + A_UINT32 hi_wow_ext_config; /* 0xec */ + A_UINT32 hi_pwr_save_flags; /* 0xf0 */ + + /* Spatial Multiplexing Power Save (SMPS) options */ + A_UINT32 hi_smps_options; /* 0xf4 */ + + /* Interconnect-specific state */ + A_UINT32 hi_interconnect_state; /* 0xf8 */ + + /* Coex configuration flags */ + A_UINT32 hi_coex_config; /* 0xfc */ + + /* Early allocation support */ + A_UINT32 hi_early_alloc; /* 0x100 */ + + /* FW swap field */ + /* Bits of this 32bit word will be used to pass specific swap + instruction to FW */ + /* Bit 0 -- AP Nart descriptor no swap. When this bit is set + FW will not swap TX descriptor. Meaning packets are formed + on the target processor.*/ + /* Bit 1 -- TBD */ + + A_UINT32 hi_fw_swap; /* 0x104 */ + + /* global arenas pointer address, used by host driver debug */ + A_UINT32 hi_dynamic_mem_arenas_addr; /* 0x108 */ + + /* allocated bytes of DRAM use by allocated */ + A_UINT32 hi_dynamic_mem_allocated; /* 0x10C */ + + /* remaining bytes of DRAM */ + A_UINT32 hi_dynamic_mem_remaining; /* 0x110 */ + + /* memory track count, configured by host */ + A_UINT32 hi_dynamic_mem_track_max; /* 0x114 */ + + /* minidump buffer */ + A_UINT32 hi_minidump; /* 0x118 */ + + /* bdata's sig and key addr */ + A_UINT32 hi_bd_sig_key; /* 0x11c */ + +} POSTPACK64; + +/* bitmap for hi_test_apps_related */ +#define HI_TEST_APPS_TESTSCRIPT_LOADED 0x00000001 +#define HI_TEST_APPS_CAL_DATA_AVAIL 0x00000002 + +/* Bits defined in hi_option_flag */ +#define HI_OPTION_TIMER_WAR 0x01 /* Enable timer workaround */ +#define HI_OPTION_BMI_CRED_LIMIT 0x02 /* Limit BMI command credits */ +#define HI_OPTION_RELAY_DOT11_HDR 0x04 /* Relay Dot11 hdr to/from host */ +#define HI_OPTION_MAC_ADDR_METHOD 0x08 /* MAC addr method 0-locally administred 1-globally unique addrs */ +#define HI_OPTION_FW_BRIDGE 0x10 /* Firmware Bridging */ +#define HI_OPTION_ENABLE_PROFILE 0x20 /* Enable CPU profiling */ +#define HI_OPTION_DISABLE_DBGLOG 0x40 /* Disable debug logging */ +#define HI_OPTION_SKIP_ERA_TRACKING 0x80 /* Skip Era Tracking */ +#define HI_OPTION_PAPRD_DISABLE 0x100 /* Disable PAPRD (debug) */ +#define HI_OPTION_NUM_DEV_LSB 0x200 +#define HI_OPTION_NUM_DEV_MSB 0x800 +#define HI_OPTION_DEV_MODE_LSB 0x1000 +#define HI_OPTION_DEV_MODE_MSB 0x8000000 +#define HI_OPTION_NO_LFT_STBL 0x10000000 /* Disable LowFreq Timer Stabilization */ +#define HI_OPTION_SKIP_REG_SCAN 0x20000000 /* Skip regulatory scan */ +#define HI_OPTION_INIT_REG_SCAN 0x40000000 /* Do regulatory scan during init before + * sending WMI ready event to host */ +#define HI_OPTION_SKIP_MEMMAP 0x80000000 /* REV6: Do not adjust memory map */ + +#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3 + +/* 2 bits of hi_option_flag are used to represent 3 modes */ +#define HI_OPTION_FW_MODE_IBSS 0x0 /* IBSS Mode */ +#define HI_OPTION_FW_MODE_BSS_STA 0x1 /* STA Mode */ +#define HI_OPTION_FW_MODE_AP 0x2 /* AP Mode */ +#define HI_OPTION_FW_MODE_BT30AMP 0x3 /* BT30 AMP Mode */ + +/* 2 bits of hi_option flag are usedto represent 4 submodes */ +#define HI_OPTION_FW_SUBMODE_NONE 0x0 /* Normal mode */ +#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 /* p2p device mode */ +#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 /* p2p client mode */ +#define HI_OPTION_FW_SUBMODE_P2PGO 0x3 /* p2p go mode */ + +/* Num dev Mask */ +#define HI_OPTION_NUM_DEV_MASK 0x7 +#define HI_OPTION_NUM_DEV_SHIFT 0x9 + +/* firmware bridging */ +#define HI_OPTION_FW_BRIDGE_SHIFT 0x04 + +/* Fw Mode/SubMode Mask +|-------------------------------------------------------------------------------| +| SUB | SUB | SUB | SUB | | | | | +| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0] | +| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | +|-------------------------------------------------------------------------------| +*/ +#define HI_OPTION_FW_MODE_BITS 0x2 +#define HI_OPTION_FW_MODE_MASK 0x3 +#define HI_OPTION_FW_MODE_SHIFT 0xC +#define HI_OPTION_ALL_FW_MODE_MASK 0xFF + +#define HI_OPTION_FW_SUBMODE_BITS 0x2 +#define HI_OPTION_FW_SUBMODE_MASK 0x3 +#define HI_OPTION_FW_SUBMODE_SHIFT 0x14 +#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00 +#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8 + + +/* hi_option_flag2 options */ +#define HI_OPTION_OFFLOAD_AMSDU 0x01 +#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */ +#define HI_OPTION_ENABLE_RFKILL 0x04 /* RFKill Enable Feature*/ +#define HI_OPTION_RADIO_RETENTION_DISABLE 0x08 /* Disable radio retention */ +#define HI_OPTION_EARLY_CFG_DONE 0x10 /* Early configuration is complete */ + +#define HI_OPTION_RF_KILL_SHIFT 0x2 +#define HI_OPTION_RF_KILL_MASK 0x1 + +/* AR9888 1.0 only. Enable/disable CDC max perf support from host */ +#define HI_OPTION_DISABLE_CDC_MAX_PERF_WAR 0x20 +#define CDC_MAX_PERF_WAR_ENABLED() \ + (!(HOST_INTEREST->hi_option_flag2 & HI_OPTION_DISABLE_CDC_MAX_PERF_WAR)) + +#define HI_OPTION_USE_EXT_LDO 0x40 /* use LDO27 for 1.1V instead of PMU */ +#define HI_OPTION_DBUART_SUPPORT 0x80 /* Enable uart debug support */ +#define HT_OPTION_GPIO_WAKEUP_SUPPORT 0x200 /* GPIO wake up support */ + +#define GPIO_WAKEUP_ENABLED() \ + (HOST_INTEREST->hi_option_flag2 & HT_OPTION_GPIO_WAKEUP_SUPPORT) + +/* hi_reset_flag */ +#define HI_RESET_FLAG_PRESERVE_APP_START 0x01 /* preserve App Start address */ +#define HI_RESET_FLAG_PRESERVE_HOST_INTEREST 0x02 /* preserve host interest */ +#define HI_RESET_FLAG_PRESERVE_ROMDATA 0x04 /* preserve ROM data */ +#define HI_RESET_FLAG_PRESERVE_NVRAM_STATE 0x08 +#define HI_RESET_FLAG_PRESERVE_BOOT_INFO 0x10 +#define HI_RESET_FLAG_WARM_RESET 0x20 + +/* define hi_fw_swap bits */ +#define HI_DESC_IN_FW_BIT 0x01 + +#define HI_RESET_FLAG_IS_VALID 0x12345678 /* indicate the reset flag is valid */ + +#define ON_RESET_FLAGS_VALID() \ + (HOST_INTEREST->hi_reset_flag_valid == HI_RESET_FLAG_IS_VALID) + +#define RESET_FLAGS_VALIDATE() \ + (HOST_INTEREST->hi_reset_flag_valid = HI_RESET_FLAG_IS_VALID) + +#define RESET_FLAGS_INVALIDATE() \ + (HOST_INTEREST->hi_reset_flag_valid = 0) + +#define ON_RESET_PRESERVE_APP_START() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_APP_START) + +#define ON_RESET_PRESERVE_NVRAM_STATE() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_NVRAM_STATE) + +#define ON_RESET_PRESERVE_HOST_INTEREST() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_HOST_INTEREST) + +#define ON_RESET_PRESERVE_ROMDATA() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_ROMDATA) + +#define ON_RESET_PRESERVE_BOOT_INFO() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_BOOT_INFO) + +#define ON_RESET_WARM_RESET() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_WARM_RESET) + +/* host CPU endianness */ +#define HOST_ON_BE_CPU() \ + (HOST_INTEREST->hi_be) + +/* AP nart no swap descriptor flag. Decsriptors are created on the target processor. */ +#define DESC_IN_FW() \ + (HOST_INTEREST->hi_fw_swap & HI_DESC_IN_FW_BIT) + +#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET (1 << 0) +#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET (1 << 1) +#define HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE (1 << 2) + +#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK (1 << 16) +#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK (1 << 17) + +/* CONSOLE FLAGS + * + * Bit Range Meaning + * --------- -------------------------------- + * 2..0 UART ID (0 = Default) + * 3 Baud Select (0 = 9600, 1 = 115200) + * 30..4 Reserved + * 31 Enable Console + * + * */ + +#define HI_CONSOLE_FLAGS_ENABLE (1 << 31) +#define HI_CONSOLE_FLAGS_UART_MASK (0x7) +#define HI_CONSOLE_FLAGS_UART_SHIFT 0 +#define HI_CONSOLE_FLAGS_BAUD_SELECT (1 << 3) + +/* SM power save options */ +#define HI_SMPS_ALLOW_MASK (0x00000001) +#define HI_SMPS_MODE_MASK (0x00000002) +#define HI_SMPS_MODE_STATIC (0x00000000) +#define HI_SMPS_MODE_DYNAMIC (0x00000002) +#define HI_SMPS_DISABLE_AUTO_MODE (0x00000004) +#define HI_SMPS_DATA_THRESH_MASK (0x000007f8) +#define HI_SMPS_DATA_THRESH_SHIFT (3) +#define HI_SMPS_RSSI_THRESH_MASK (0x0007f800) +#define HI_SMPS_RSSI_THRESH_SHIFT (11) +#define HI_SMPS_LOWPWR_CM_MASK (0x00380000) +#define HI_SMPS_LOWPWR_CM_SHIFT (15) +#define HI_SMPS_HIPWR_CM_MASK (0x03c00000) +#define HI_SMPS_HIPWR_CM_SHIFT (19) + +#define HOST_INTEREST_SMPS_GET_MODE() (HOST_INTEREST->hi_smps_options & HI_SMPS_MODE_MASK) +#define HOST_INTEREST_SMPS_GET_DATA_THRESH() ((HOST_INTEREST->hi_smps_options & HI_SMPS_DATA_THRESH_MASK) >> HI_SMPS_DATA_THRESH_SHIFT) +#define HOST_INTEREST_SMPS_SET_DATA_THRESH(x) (((x) << HI_SMPS_DATA_THRESH_SHIFT) & HI_SMPS_DATA_THRESH_MASK) +#define HOST_INTEREST_SMPS_GET_RSSI_THRESH() ((HOST_INTEREST->hi_smps_options & HI_SMPS_RSSI_THRESH_MASK) >> HI_SMPS_RSSI_THRESH_SHIFT) +#define HOST_INTEREST_SMPS_SET_RSSI_THRESH(x) (((x) << HI_SMPS_RSSI_THRESH_SHIFT) & HI_SMPS_RSSI_THRESH_MASK) +#define HOST_INTEREST_SMPS_SET_LOWPWR_CM() ((HOST_INTEREST->hi_smps_options & HI_SMPS_LOWPWR_CM_MASK) >> HI_SMPS_LOWPWR_CM_SHIFT) +#define HOST_INTEREST_SMPS_SET_HIPWR_CM() ((HOST_INTEREST->hi_smps_options << HI_SMPS_HIPWR_CM_MASK) & HI_SMPS_HIPWR_CM_SHIFT) +#define HOST_INTEREST_SMPS_IS_AUTO_MODE_DISABLED() (HOST_INTEREST->hi_smps_options & HI_SMPS_DISABLE_AUTO_MODE) + + +/* WOW Extension configuration + * + * Bit Range Meaning + * --------- -------------------------------- + * 8..0 Size of each WOW pattern (max 511) + * 15..9 Number of patterns per list (max 127) + * 17..16 Number of lists (max 4) + * 30..18 Reserved + * 31 Enabled + * + * set values (except enable) to zeros for default settings + * + * */ + +#define HI_WOW_EXT_ENABLED_MASK (1 << 31) +#define HI_WOW_EXT_NUM_LIST_SHIFT 16 +#define HI_WOW_EXT_NUM_LIST_MASK (0x3 << HI_WOW_EXT_NUM_LIST_SHIFT) +#define HI_WOW_EXT_NUM_PATTERNS_SHIFT 9 +#define HI_WOW_EXT_NUM_PATTERNS_MASK (0x7F << HI_WOW_EXT_NUM_PATTERNS_SHIFT) +#define HI_WOW_EXT_PATTERN_SIZE_SHIFT 0 +#define HI_WOW_EXT_PATTERN_SIZE_MASK (0x1FF << HI_WOW_EXT_PATTERN_SIZE_SHIFT) + +#define HI_WOW_EXT_MAKE_CONFIG(num_lists,count,size) \ + ((((num_lists) << HI_WOW_EXT_NUM_LIST_SHIFT) & HI_WOW_EXT_NUM_LIST_MASK) | \ + (((count) << HI_WOW_EXT_NUM_PATTERNS_SHIFT) & HI_WOW_EXT_NUM_PATTERNS_MASK) | \ + (((size) << HI_WOW_EXT_PATTERN_SIZE_SHIFT) & HI_WOW_EXT_PATTERN_SIZE_MASK)) + +#define HI_WOW_EXT_GET_NUM_LISTS(config) \ + (((config) & HI_WOW_EXT_NUM_LIST_MASK) >> HI_WOW_EXT_NUM_LIST_SHIFT) +#define HI_WOW_EXT_GET_NUM_PATTERNS(config) \ + (((config) & HI_WOW_EXT_NUM_PATTERNS_MASK) >> HI_WOW_EXT_NUM_PATTERNS_SHIFT) +#define HI_WOW_EXT_GET_PATTERN_SIZE(config) \ + (((config) & HI_WOW_EXT_PATTERN_SIZE_MASK) >> HI_WOW_EXT_PATTERN_SIZE_SHIFT) + +/* + * Early allocation configuration + * Support RAM bank configuration before BMI done and this eases the memory + * allocation at very early stage + * Bit Range Meaning + * --------- ---------------------------------- + * [0:3] number of bank assigned to be IRAM + * [4:15] reserved + * [16:31] magic number + * + * Note: + * 1. target firmware would check magic number and if it's a match, firmware + * would consider the bits[0:15] are valid and base on that to calculate + * the end of DRAM. Early allocation would be located at that area and + * may be reclaimed when necesary + * 2. if no magic number is found, early allocation would happen at "_end" + * symbol of ROM which is located before the app-data and might NOT be + * re-claimable. If this is adopted, link script should keep this in + * mind to avoid data corruption. + */ +#define HI_EARLY_ALLOC_MAGIC 0x6d8a +#define HI_EARLY_ALLOC_MAGIC_MASK 0xffff0000 +#define HI_EARLY_ALLOC_MAGIC_SHIFT 16 +#define HI_EARLY_ALLOC_IRAM_BANKS_MASK 0x0000000f +#define HI_EARLY_ALLOC_IRAM_BANKS_SHIFT 0 + +#define HI_EARLY_ALLOC_VALID() \ + ((((HOST_INTEREST->hi_early_alloc) & HI_EARLY_ALLOC_MAGIC_MASK) >> HI_EARLY_ALLOC_MAGIC_SHIFT) \ + == (HI_EARLY_ALLOC_MAGIC)) +#define HI_EARLY_ALLOC_GET_IRAM_BANKS() \ + (((HOST_INTEREST->hi_early_alloc) & HI_EARLY_ALLOC_IRAM_BANKS_MASK) >> HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) + +/* + * Intended for use by Host software, this macro returns the Target RAM + * address of any item in the host_interest structure. + * Example: target_addr = AR6002_HOST_INTEREST_ITEM_ADDRESS(hi_board_data); + */ +#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item))) + +#define AR6003_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item))) + +#define AR6004_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR6004_HOST_INTEREST_ADDRESS))->item))) + +#define AR6006_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR6006_HOST_INTEREST_ADDRESS))->item))) + +#define AR9888_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR9888_HOST_INTEREST_ADDRESS))->item))) + +#define AR6320_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR6320_HOST_INTEREST_ADDRESS))->item))) + +#define AR900B_HOST_INTEREST_ITEM_ADDRESS(item) \ + (A_UINT32)((size_t)&((((struct host_interest_s *)(AR900B_HOST_INTEREST_ADDRESS))->item))) + +#define HOST_INTEREST_DBGLOG_IS_ENABLED() \ + (!((volatile A_UINT32)HOST_INTEREST->hi_option_flag & HI_OPTION_DISABLE_DBGLOG)) + +#define HOST_INTEREST_PKTLOG_IS_ENABLED() \ + (((volatile A_UINT32)HOST_INTEREST->hi_pktlog_num_buffers)) + +#define HOST_INTEREST_PROFILE_IS_ENABLED() \ + ((volatile A_UINT32)HOST_INTEREST->hi_option_flag & HI_OPTION_ENABLE_PROFILE) + +#define LF_TIMER_STABILIZATION_IS_ENABLED() \ + (!((volatile A_UINT32)HOST_INTEREST->hi_option_flag & HI_OPTION_NO_LFT_STBL)) + +#define IS_AMSDU_OFFLAOD_ENABLED() \ + (((volatile A_UINT32)HOST_INTEREST->hi_option_flag2 & HI_OPTION_OFFLOAD_AMSDU)) + +#define HOST_INTEREST_DFS_IS_ENABLED() \ + (((volatile A_UINT32)HOST_INTEREST->hi_option_flag2 & HI_OPTION_DFS_SUPPORT)) + +#define HOST_INTEREST_EARLY_CFG_DONE() \ + (((volatile A_UINT32)HOST_INTEREST->hi_option_flag2 & HI_OPTION_EARLY_CFG_DONE)) + +/*power save flag bit definitions*/ +#define HI_PWR_SAVE_LPL_ENABLED 0x1 +/*b1-b3 reserved*/ +/*b4-b5 : dev0 LPL type : 0 - none + 1- Reduce Pwr Search + 2- Reduce Pwr Listen*/ +/*b6-b7 : dev1 LPL type and so on for Max 8 devices*/ +#define HI_PWR_SAVE_LPL_DEV0_LSB 4 +#define HI_PWR_SAVE_LPL_DEV_MASK 0x3 +/*power save related utility macros*/ +#define HI_LPL_ENABLED() \ + ((HOST_INTEREST->hi_pwr_save_flags & HI_PWR_SAVE_LPL_ENABLED)) +#define HI_DEV_LPL_TYPE_GET(_devix) \ + (HOST_INTEREST->hi_pwr_save_flags & \ + ((HI_PWR_SAVE_LPL_DEV_MASK) << \ + (HI_PWR_SAVE_LPL_DEV0_LSB + \ + (_devix)*2))) + +#define HOST_INTEREST_SMPS_IS_ALLOWED() \ + ((HOST_INTEREST->hi_smps_options & HI_SMPS_ALLOW_MASK)) + +/* Convert a Target virtual address into a Target physical address */ +#define AR6002_VTOP(vaddr) ((vaddr) & 0x001fffff) +#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff) +#define AR6004_VTOP(vaddr) (vaddr) +#define AR6006_VTOP(vaddr) (vaddr) +#define AR9888_VTOP(vaddr) (vaddr) +#define AR6320_VTOP(vaddr) (vaddr) +#define AR900B_VTOP(vaddr) (vaddr) +#define TARG_VTOP(TargetType, vaddr) \ + (((TargetType) == TARGET_TYPE_AR6002) ? AR6002_VTOP(vaddr) : \ + (((TargetType) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \ + (((TargetType) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : \ + (((TargetType) == TARGET_TYPE_AR6006) ? AR6006_VTOP(vaddr) : \ + (((TargetType) == TARGET_TYPE_AR9888) ? AR9888_VTOP(vaddr) : \ + (((TargetType) == TARGET_TYPE_AR6320) ? AR6320_VTOP(vaddr) : \ + (((TargetType) == TARGET_TYPE_AR900B) ? AR900B_VTOP(vaddr) : \ + 0))))))) + +#define HOST_INTEREST_ITEM_ADDRESS(TargetType, item) \ + (((TargetType) == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR6004) ? AR6004_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR6006) ? AR6006_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR9888) ? AR9888_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR6320) ? AR6320_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR6320V2) ? AR6320_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((TargetType) == TARGET_TYPE_AR900B) ? AR900B_HOST_INTEREST_ITEM_ADDRESS(item) : \ + 0)))))))) + +#define AR6002_BOARD_DATA_SZ 768 +#define AR6002_BOARD_EXT_DATA_SZ 0 +#define AR6003_BOARD_DATA_SZ 1024 +/* Reserve 1024 bytes for extended board data */ +#if defined(AR6002_REV43) +#define AR6003_BOARD_EXT_DATA_SZ 1024 +#else +#define AR6003_BOARD_EXT_DATA_SZ 768 +#endif +#define AR6004_BOARD_DATA_SZ 7168 +#define AR6004_BOARD_EXT_DATA_SZ 0 +#define AR9888_BOARD_DATA_SZ 7168 +#define AR9888_BOARD_EXT_DATA_SZ 0 +#define AR6320_BOARD_DATA_SZ 8192 +#define AR6320_BOARD_EXT_DATA_SZ 0 +#define AR900B_BOARD_DATA_SZ 7168 +#define AR900B_BOARD_EXT_DATA_SZ 0 + +#define AR6003_REV3_APP_START_OVERRIDE 0x946100 +#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 +#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 +#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 +#define AR6003_REV3_RAM_RESERVE_SIZE 4096 + +#define AR6004_REV1_BOARD_DATA_ADDRESS 0x423900 +#define AR6004_REV1_RAM_RESERVE_SIZE 19456 +#define AR6004_REV1_DATASET_PATCH_ADDRESS 0x425294 + +#define AR6004_REV2_BOARD_DATA_ADDRESS 0x426400 +#define AR6004_REV2_RAM_RESERVE_SIZE 7168 +#define AR6004_REV2_DATASET_PATCH_ADDRESS 0x435294 + +#define AR6004_REV5_BOARD_DATA_ADDRESS 0x436400 +#define AR6004_REV5_RAM_RESERVE_SIZE 7168 +#define AR6004_REV5_DATASET_PATCH_ADDRESS 0x437860 + +/* Reserve 4K for OTA test script */ +#define AR6004_REV1_RAM_RESERVE_SIZE_FOR_TEST_SCRIPT 4096 +#define AR6004_REV1_TEST_SCRIPT_ADDRESS 0x422900 + +/* # of A_UINT32 entries in targregs, used by DIAG_FETCH_TARG_REGS */ +#define AR6003_FETCH_TARG_REGS_COUNT 64 +#define AR6004_FETCH_TARG_REGS_COUNT 64 +#define AR9888_FETCH_TARG_REGS_COUNT 64 +#define AR6320_FETCH_TARG_REGS_COUNT 64 +#define AR900B_FETCH_TARG_REGS_COUNT 64 + +#endif /* !__ASSEMBLER__ */ + +#ifndef ATH_TARGET +#include "athendpack.h" +#endif + +#endif /* __TARGADDRS_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targcfg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targcfg.h new file mode 100644 index 000000000000..f33a6e6dd593 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/targcfg.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __TARGCFG_H__ +#define __TARGCFG_H__ + +#if defined(ATH_TARGET) +#include /* A_UINT32 */ +#else +#include /* A_UINT32 */ +#endif + +typedef struct _targcfg_t { + A_UINT32 num_vdev; + A_UINT32 num_peers; + A_UINT32 num_peer_ast; + A_UINT32 num_peer_keys; + A_UINT32 num_peer_tid; + A_UINT32 num_mcast_keys; + A_UINT32 num_tx; + A_UINT32 num_rx; + A_UINT32 num_mgmt_tx; + A_UINT32 num_mgmt_rx; + A_UINT32 tx_chain_mask; + A_UINT32 rx_chain_mask; + A_UINT32 override; /* Override target with the values supplied above */ +} targcfg_t; + +#endif /* __TARGCFG_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/testmode.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/testmode.h new file mode 100644 index 000000000000..705884bc1207 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/testmode.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _TESTMODE_H_ +#define _TESTMODE_H_ + +#define AR6K_TM_DATA_MAX_LEN 5000 + +enum ar6k_testmode_attr { + __AR6K_TM_ATTR_INVALID = 0, + AR6K_TM_ATTR_CMD = 1, + AR6K_TM_ATTR_DATA = 2, + AR6K_TM_ATTR_STREAM_ID = 3, + + /* keep last */ + __AR6K_TM_ATTR_AFTER_LAST, + AR6K_TM_ATTR_MAX = __AR6K_TM_ATTR_AFTER_LAST - 1 +}; + +enum ar6k_testmode_cmd { + AR6K_TM_CMD_TCMD = 0, + AR6K_TM_CMD_WMI_CMD = 0xF000, +}; + +enum ar6k_tcmd_ep { + TCMD_EP_TCMD, + TCMD_EP_WMI, +}; + +struct ar6k_testmode_cmd_data { + void *data; + int len; +}; +#endif /* #ifndef _TESTMODE_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wal_rx_desc.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wal_rx_desc.h new file mode 100644 index 000000000000..44ee98e9de4b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wal_rx_desc.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WAL_RX_DESC__H_ +#define _WAL_RX_DESC__H_ + + +#if defined(ATH_TARGET) +#include /* A_UINT8 */ +#else +#include /* A_UINT8 */ +#endif + +/* + * As this header is used by host also, + * and host will access target registers by target reg tbl, + * so disable direct-reference here for host. + * + */ +#if !defined(ATH_PERF_PWR_OFFLOAD) +/* HW rx descriptor definitions */ +#include +#include +#include +#include +#include +#include +#include +#include +/* + * This struct defines the basic descriptor information, which is + * written by the 11ac HW MAC into the WAL's rx status descriptor + * ring. + */ +struct hw_rx_desc_base { + struct rx_attention attention; + struct rx_frag_info frag_info; + struct rx_mpdu_start mpdu_start; + struct rx_msdu_start msdu_start; + struct rx_msdu_end msdu_end; + struct rx_mpdu_end mpdu_end; + struct rx_ppdu_start ppdu_start; + struct rx_ppdu_end ppdu_end; +}; +#endif + +/* + * This struct defines the basic MSDU rx descriptor created by FW. + */ +struct fw_rx_desc_base { + union { + struct { + A_UINT8 discard : 1, + forward : 1, + any_err : 1, + dup_err : 1, + reserved : 1, + inspect : 1, + extension: 2; + }bits; + A_UINT8 val; + }u; +}; + +#define FW_RX_DESC_DISCARD_M 0x1 +#define FW_RX_DESC_DISCARD_S 0 +#define FW_RX_DESC_FORWARD_M 0x2 +#define FW_RX_DESC_FORWARD_S 1 +#define FW_RX_DESC_MIC_ERR_M 0x4 +#define FW_RX_DESC_MIC_ERR_S 2 +#define FW_RX_DESC_DUP_ERR_M 0x8 +#define FW_RX_DESC_DUP_ERR_S 3 +#define FW_RX_DESC_INSPECT_M 0x20 +#define FW_RX_DESC_INSPECT_S 5 +#define FW_RX_DESC_EXT_M 0xc0 +#define FW_RX_DESC_EXT_S 6 + +#define FW_RX_DESC_CNT_2_BYTES(_fw_desc_cnt) (_fw_desc_cnt) + +enum { + FW_RX_DESC_EXT_NONE = 0, + FW_RX_DESC_EXT_LRO_ONLY, + FW_RX_DESC_EXT_LRO_AND_OTHER, + FW_RX_DESC_EXT_OTHER +}; + +#define FW_RX_DESC_DISCARD_GET(_var) \ + (((_var) & FW_RX_DESC_DISCARD_M) >> FW_RX_DESC_DISCARD_S) +#define FW_RX_DESC_DISCARD_SET(_var, _val) \ + ((_var) |= ((_val) << FW_RX_DESC_DISCARD_S)) + +#define FW_RX_DESC_FORWARD_GET(_var) \ + (((_var) & FW_RX_DESC_FORWARD_M) >> FW_RX_DESC_FORWARD_S) +#define FW_RX_DESC_FORWARD_SET(_var, _val) \ + ((_var) |= ((_val) << FW_RX_DESC_FORWARD_S)) + +#define FW_RX_DESC_INSPECT_GET(_var) \ + (((_var) & FW_RX_DESC_INSPECT_M) >> FW_RX_DESC_INSPECT_S) +#define FW_RX_DESC_INSPECT_SET(_var, _val) \ + ((_var) |= ((_val) << FW_RX_DESC_INSPECT_S)) + +#define FW_RX_DESC_EXT_GET(_var) \ + (((_var) & FW_RX_DESC_EXT_M) >> FW_RX_DESC_EXT_S) +#define FW_RX_DESC_EXT_SET(_var, _val) \ + ((_var) |= ((_val) << FW_RX_DESC_EXT_S)) + + +#endif /* _WAL_RX_DESC__H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event.h new file mode 100644 index 000000000000..70ab930dd4dd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WDI_EVENT_H_ +#define _WDI_EVENT_H_ + +#include "athdefs.h" +#include "adf_nbuf.h" +#define WDI_EVENT_BASE 0x100 /* Event starting number */ + +enum WDI_EVENT { + WDI_EVENT_TX_STATUS = WDI_EVENT_BASE, + WDI_EVENT_RX_DESC, + WDI_EVENT_RX_DESC_REMOTE, + WDI_EVENT_RATE_FIND, + WDI_EVENT_RATE_UPDATE, + WDI_EVENT_RX_PEER_INVALID, + /* End of new event items */ + + WDI_EVENT_LAST +}; + +struct wdi_event_rx_peer_invalid_msg { + adf_nbuf_t msdu; + struct ieee80211_frame *wh; + u_int8_t vdev_id; +}; + +#define WDI_NUM_EVENTS (WDI_EVENT_LAST - WDI_EVENT_BASE) + +#define WDI_EVENT_NOTIFY_BASE 0x200 +enum WDI_EVENT_NOTIFY { + WDI_EVENT_SUB_DEALLOCATE = WDI_EVENT_NOTIFY_BASE, + /* End of new notification types */ + + WDI_EVENT_NOTIFY_LAST +}; + +/* Opaque event callback */ +typedef void (*wdi_event_cb)(void *pdev, enum WDI_EVENT event, void *data); + +/* Opaque event notify */ +typedef void (*wdi_event_notify)(enum WDI_EVENT_NOTIFY notify, + enum WDI_EVENT event); + +/** + * @typedef wdi_event_subscribe + * @brief Used by consumers to subscribe to WDI event notifications. + * @details + * The event_subscribe struct includes pointers to other event_subscribe + * objects. These pointers are simply to simplify the management of + * lists of event subscribers. These pointers are set during the + * event_sub() function, and shall not be modified except by the + * WDI event management SW, until after the object's event subscription + * is canceled by calling event_unsub(). + */ + +typedef struct wdi_event_subscribe_t { + wdi_event_cb callback; /* subscriber event callback structure head*/ + void *context; /* subscriber object that processes the event callback */ + struct { + /* private - the event subscriber SW shall not use this struct */ + struct wdi_event_subscribe_t *next; + struct wdi_event_subscribe_t *prev; + } priv; +} wdi_event_subscribe; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event_api.h new file mode 100644 index 000000000000..4ed3a424ea8a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_event_api.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WDI_EVENT_API_H_ +#define _WDI_EVENT_API_H_ + +#include "wdi_event.h" + +struct ol_txrx_pdev_t; + +/** + * @brief Subscribe to a specified WDI event. + * @details + * This function adds the provided wdi_event_subscribe object to a list of + * subscribers for the specified WDI event. + * When the event in question happens, each subscriber for the event will + * have their callback function invoked. + * The order in which callback functions from multiple subscribers are + * invoked is unspecified. + * + * @param pdev - the event physical device, that maintains the event lists + * @param event_cb_sub - the callback and context for the event subscriber + * @param event - which event's notifications are being subscribed to + * @return error code, or A_OK for success + */ +A_STATUS wdi_event_sub( + struct ol_txrx_pdev_t *txrx_pdev, + wdi_event_subscribe *event_cb_sub, + enum WDI_EVENT event); + +/** + * @brief Unsubscribe from a specified WDI event. + * @details + * This function removes the provided event subscription object from the + * list of subscribers for its event. + * This function shall only be called if there was a successful prior call + * to event_sub() on the same wdi_event_subscribe object. + * + * @param pdev - the event physical device with the list of event subscribers + * @param event_cb_sub - the event subscription object + * @param event - which event is being unsubscribed + * @return error code, or A_OK for success + */ +A_STATUS wdi_event_unsub( + struct ol_txrx_pdev_t *txrx_pdev, + wdi_event_subscribe *event_cb_sub, + enum WDI_EVENT event); + +#ifdef WDI_EVENT_ENABLE + +void wdi_event_handler(enum WDI_EVENT event, + struct ol_txrx_pdev_t *txrx_pdev, + void *data); +A_STATUS wdi_event_attach(struct ol_txrx_pdev_t *txrx_pdev); +A_STATUS wdi_event_detach(struct ol_txrx_pdev_t *txrx_pdev); + +#endif /* WDI_EVENT_ENABLE */ + +#endif /* _WDI_EVENT_API_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_in.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_in.h new file mode 100644 index 000000000000..b6d37f60c60d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_in.h @@ -0,0 +1,1280 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY */ +/** + * @addtogroup WDIAPI + *@{ + */ +/** + * @file wdi_in.h + * @brief Datapath functions called by SW outside the WDI boundary + */ +#ifndef _WDI_IN__H_ +#define _WDI_IN__H_ + +#include + +#ifdef WDI_API_AS_FUNCS + +#include /* A_STATUS */ +#include /* adf_nbuf_t */ +#include /* adf_os_device_t */ +#include /* HTC_HANDLE */ + +#include /* MAX_SPATIAL_STREAM */ + +/** + * @brief Set up the data SW subsystem. + * @details + * As part of the WLAN device attach, the data SW subsystem has + * to be attached as a component within the WLAN device. + * This attach allocates and initializes the physical device object + * used by the data SW. + * The data SW subsystem attach needs to happen after the target has + * be started, and host / target parameter negotiation has completed, + * since the host data SW uses some of these host/target negotiated + * parameters (e.g. peer ID range) during the initializations within + * its attach function. + * However, the host data SW is not allowed to send HTC messages to the + * target within this pdev_attach function call, since the HTC setup + * has not complete at this stage of initializations. Any messaging + * to the target has to be done in the separate pdev_attach_target call + * that is invoked after HTC setup is complete. + * + * @param ctrl_pdev - control SW's physical device handle, needed as an + * argument for dynamic configuration queries + * @param htc_pdev - the HTC physical device handle. This is not needed + * by the txrx module, but needs to be passed along to the HTT module. + * @param osdev - OS handle needed as an argument for some OS primitives + * @return the data physical device object + */ +ol_txrx_pdev_handle +wdi_in_pdev_attach( + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, + adf_os_device_t osdev); + +/** + * @brief Do final steps of data SW setup that send messages to the target. + * @details + * The majority of the data SW setup are done by the pdev_attach function, + * but this function completes the data SW setup by sending datapath + * configuration messages to the target. + * + * @param data_pdev - the physical device being initialized + */ +A_STATUS +wdi_in_pdev_attach_target(ol_txrx_pdev_handle data_pdev); + +/** + * @brief Wrapper for rate-control context initialization + * @details + * Enables the switch that controls the allocation of the + * rate-control contexts on the host. + * + * @param pdev - the physical device being initialized + * @param enable - 1: enabled 0: disabled + */ +void wdi_in_enable_host_ratectrl(ol_txrx_pdev_handle pdev, u_int32_t enable); + +/** + * @brief modes that a virtual device can operate as + * @details + * A virtual device can operate as an AP, an IBSS, a STA + * (client), in monitor mode or OCB mode + */ +enum wlan_op_mode { + wlan_op_mode_unknown, + wlan_op_mode_ap, + wlan_op_mode_ibss, + wlan_op_mode_sta, + wlan_op_mode_monitor, + wlan_op_mode_ocb, +}; + +/** + * @brief Allocate and initialize the data object for a new virtual device. + * @param data_pdev - the physical device the virtual device belongs to + * @param vdev_mac_addr - the MAC address of the virtual device + * @param vdev_id - the ID used to identify the virtual device to the target + * @param op_mode - whether this virtual device is operating as an AP, + * an IBSS, or a STA + * @return + * success: handle to new data vdev object, -OR- + * failure: NULL + */ +ol_txrx_vdev_handle +wdi_in_vdev_attach( + ol_txrx_pdev_handle data_pdev, + u_int8_t *vdev_mac_addr, + u_int8_t vdev_id, + enum wlan_op_mode op_mode); + +/** + * @brief Allocate and set up references for a data peer object. + * @details + * When an association with a peer starts, the host's control SW + * uses this function to inform the host data SW. + * The host data SW allocates its own peer object, and stores a + * reference to the control peer object within the data peer object. + * The host data SW also stores a reference to the virtual device + * that the peer is associated with. This virtual device handle is + * used when the data SW delivers rx data frames to the OS shim layer. + * The host data SW returns a handle to the new peer data object, + * so a reference within the control peer object can be set to the + * data peer object. + * + * @param data_pdev - data physical device object that will indirectly + * own the data_peer object + * @param data_vdev - data virtual device object that will directly + * own the data_peer object + * @param peer_mac_addr - MAC address of the new peer + * @return handle to new data peer object, or NULL if the attach fails + */ +ol_txrx_peer_handle +wdi_in_peer_attach( + ol_txrx_pdev_handle data_pdev, + ol_txrx_vdev_handle data_vdev, + u_int8_t *peer_mac_addr); + +/** + * @brief Template for passing ieee80211_node members to rate-control + * @details + * This structure is used in order to maintain the isolation between umac and + * ol while initializing the peer-level rate-control context with peer-specific + * parameters. + */ +struct peer_ratectrl_params_t { + u_int8_t ni_streams; + u_int8_t is_auth_wpa; + u_int8_t is_auth_wpa2; + u_int8_t is_auth_8021x; + u_int32_t ni_flags; + u_int32_t ni_chwidth; + u_int16_t ni_htcap; + u_int32_t ni_vhtcap; + u_int16_t ni_phymode; + u_int16_t ni_rx_vhtrates; + u_int8_t ht_rates[MAX_SPATIAL_STREAM * 8]; +}; + +/** +* @brief Parameter type to be input to wdi_in_peer_update +* @details +* This struct is union,to be used to specify various informations to update +* txrx peer object. +*/ +typedef union { + struct peer_ratectrl_params_t * ratectrl; + u_int8_t qos_capable; + u_int8_t uapsd_mask; + enum ol_sec_type sec_type; +}ol_txrx_peer_update_param_t; + +/** +* @brief Parameter type to be input to wdi_in_peer_update +* @details +* This enum is used to specify what exact information in ol_txrx_peer_update_param_t +* is used to update the txrx peer object. +*/ +typedef enum { + ol_txrx_peer_update_rate_ctrl = 0x1, + ol_txrx_peer_update_qos_capable, + ol_txrx_peer_update_uapsdMask, + ol_txrx_peer_update_peer_security, +} ol_txrx_peer_update_select_t; + +/** + * @brief Update the data peer object as some informaiton changed in node. + * @details + * Only a single prarameter can be changed for each call to this func. + * For the host-based implementation of rate-control (select == + * ol_txrx_peer_update_rate_ctrl), it updates the peer/node-related parameters + * within rate-control context of the peer at association. + * + * @param peer - pointer to the node's object + * @param param - new param to be upated in peer object. + * @param select - specify what's parameter needed to be update + * @return none + */ +void +wdi_in_peer_update(ol_txrx_vdev_handle data_vdev, u_int8_t *peer_mac, + ol_txrx_peer_update_param_t *param, + ol_txrx_peer_update_select_t select); + +/** + * @brief Notify tx data SW that a peer's transmissions are suspended. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * The HL host tx data SW is doing tx classification and tx download + * scheduling, and therefore also needs to actively participate in tx + * flow control. Specifically, the HL tx data SW needs to check whether a + * given peer is available to transmit to, or is paused. + * This function is used to tell the HL tx data SW when a peer is paused, + * so the host tx data SW can hold the tx frames for that SW. + * + * @param data_peer - which peer is being paused + */ +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_SUPPORT_INTEGRATED_SOC) +void +wdi_in_peer_pause(ol_txrx_peer_handle data_peer); +#else +#define wdi_in_peer_pause(data_peer) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Notify tx data SW that a peer-TID is ready to transmit to. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * If a peer-TID has tx paused, then the tx datapath will end up queuing + * any tx frames that arrive from the OS shim for that peer-TID. + * In a HL system, the host tx data SW itself will classify the tx frame, + * and determine that it needs to be queued rather than downloaded to the + * target for transmission. + * Once the peer-TID is ready to accept data, the host control SW will call + * this function to notify the host data SW that the queued frames can be + * enabled for transmission, or specifically to download the tx frames + * to the target to transmit. + * The TID parameter is an extended version of the QoS TID. Values 0-15 + * indicate a regular QoS TID, and the value 16 indicates either non-QoS + * data, multicast data, or broadcast data. + * + * @param data_peer - which peer is being unpaused + * @param tid - which TID within the peer is being unpaused, or -1 as a + * wildcard to unpause all TIDs within the peer + */ +#if defined(CONFIG_HL_SUPPORT) +void +wdi_in_peer_tid_unpause(ol_txrx_peer_handle data_peer, int tid); +#else +#define wdi_in_peer_tid_unpause(data_peer, tid) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Tell a paused peer to release a specified number of tx frames. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * Download up to a specified maximum number of tx frames from the tx + * queues of the specified TIDs within the specified paused peer, usually + * in response to a U-APSD trigger from the peer. + * It is up to the host data SW to determine how to choose frames from the + * tx queues of the specified TIDs. However, the host data SW does need to + * provide long-term fairness across the U-APSD enabled TIDs. + * The host data SW will notify the target data FW when it is done downloading + * the batch of U-APSD triggered tx frames, so the target data FW can + * differentiate between an in-progress download versus a case when there are + * fewer tx frames available than the specified limit. + * This function is relevant primarily to HL U-APSD, where the frames are + * held in the host. + * + * @param peer - which peer sent the U-APSD trigger + * @param tid_mask - bitmask of U-APSD enabled TIDs from whose tx queues + * tx frames can be released + * @param max_frms - limit on the number of tx frames to release from the + * specified TID's queues within the specified peer + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +wdi_in_tx_release( + ol_txrx_peer_handle peer, + u_int32_t tid_mask, + int max_frms); +#else +#define wdi_in_tx_release(peer, tid_mask, max_frms) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Suspend all tx data for the specified virtual device. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * As an example, this function could be used when a single-channel physical + * device supports multiple channels by jumping back and forth between the + * channels in a time-shared manner. As the device is switched from channel + * A to channel B, the virtual devices that operate on channel A will be + * paused. + * + * @param data_vdev - the virtual device being paused + * @param reason - the reason for which vdev queue is getting paused + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +wdi_in_vdev_pause(ol_txrx_vdev_handle data_vdev, u_int32_t reason); +#else +#define wdi_in_vdev_pause(data_vdev, reason) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Resume tx for the specified virtual device. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * + * @param data_vdev - the virtual device being unpaused + * @param reason - the reason for which vdev queue is getting unpaused + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +wdi_in_vdev_unpause(ol_txrx_vdev_handle data_vdev, u_int32_t reason); +#else +#define wdi_in_vdev_unpause(data_vdev, reason) /* no-op */ +#endif /* CONFIG_HL_SUPPORT */ + +/** + * @brief Suspend all tx data for the specified physical device. + * @details + * This function applies to HL systems - + * in LL systems, applies when txrx_vdev_pause_all is enabled. + * In some systems it is necessary to be able to temporarily + * suspend all WLAN traffic, e.g. to allow another device such as bluetooth + * to temporarily have exclusive access to shared RF chain resources. + * This function suspends tx traffic within the specified physical device. + * + * @param data_pdev - the physical device being paused + * @param reason - pause reason + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +wdi_in_pdev_pause(ol_txrx_pdev_handle data_pdev, u_int32_t reason); +#else +#define wdi_in_pdev_pause(data_pdev, reason) /* no-op */ +#endif + +/** + * @brief Resume tx for the specified physical device. + * @details + * This function applies to HL systems - + * in LL systems, applies when txrx_vdev_pause_all is enabled. + * + * @param data_pdev - the physical device being unpaused + * @param reason - pause reason + */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +void +wdi_in_pdev_unpause(ol_txrx_pdev_handle data_pdev, u_int32_t reason); +#else +#define wdi_in_pdev_unpause(data_pdev, reason) /* no-op */ +#endif + +/** + * @brief Synchronize the data-path tx with a control-path target download + * @dtails + * @param data_pdev - the data-path physical device object + * @param sync_cnt - after the host data-path SW downloads this sync request + * to the target data-path FW, the target tx data-path will hold itself + * in suspension until it is given an out-of-band sync counter value that + * is equal to or greater than this counter value + */ +void +wdi_in_tx_sync(ol_txrx_pdev_handle data_pdev, u_int8_t sync_cnt); + +/** + * @brief Delete a peer's data object. + * @details + * When the host's control SW disassociates a peer, it calls this + * function to delete the peer's data object. + * The reference stored in the control peer object to the data peer + * object (set up by a call to ol_peer_store()) is provided. + * + * @param data_peer - the object to delete + */ +void +wdi_in_peer_detach(ol_txrx_peer_handle data_peer); + +typedef void (*ol_txrx_vdev_delete_cb)(void *context); + +/** + * @brief Deallocate the specified data virtual device object. + * @details + * All peers associated with the virtual device need to be deleted + * (wdi_in_peer_detach) before the virtual device itself is deleted. + * However, for the peers to be fully deleted, the peer deletion has to + * percolate through the target data FW and back up to the host data SW. + * Thus, even though the host control SW may have issued a peer_detach + * call for each of the vdev's peers, the peer objects may still be + * allocated, pending removal of all references to them by the target FW. + * In this case, though the vdev_detach function call will still return + * immediately, the vdev itself won't actually be deleted, until the + * deletions of all its peers complete. + * The caller can provide a callback function pointer to be notified when + * the vdev deletion actually happens - whether it's directly within the + * vdev_detach call, or if it's deferred until all in-progress peer + * deletions have completed. + * + * @param data_vdev - data object for the virtual device in question + * @param callback - function to call (if non-NULL) once the vdev has + * been wholly deleted + * @param callback_context - context to provide in the callback + */ +void +wdi_in_vdev_detach( + ol_txrx_vdev_handle data_vdev, + ol_txrx_vdev_delete_cb callback, + void *callback_context); + +/** + * @brief Delete the data SW state. + * @details + * This function is used when the WLAN driver is being removed to + * remove the host data component within the driver. + * All virtual devices within the physical device need to be deleted + * (wdi_in_vdev_detach) before the physical device itself is deleted. + * + * @param data_pdev - the data physical device object being removed + * @param force - delete the pdev (and its vdevs and peers) even if there + * are outstanding references by the target to the vdevs and peers + * within the pdev + */ +void +wdi_in_pdev_detach(ol_txrx_pdev_handle data_pdev, int force); + +typedef void +(*ol_txrx_data_tx_cb)(void *ctxt, adf_nbuf_t tx_frm, int had_error); + +/** + * @brief Store a delivery notification callback for specific data frames. + * @details + * Through a non-std tx function, the txrx SW can be given tx data frames + * that are specially marked to not be unmapped and freed by the tx SW + * when transmission completes. Rather, these specially-marked frames + * are provided to the callback registered with this function. + * + * @param data_vdev - which vdev the callback is being registered with + * (Currently the callback is stored in the pdev rather than the vdev.) + * @param callback - the function to call when tx frames marked as "no free" + * are done being transmitted + * @param ctxt - the context argument provided to the callback function + */ +void +wdi_in_data_tx_cb_set( + ol_txrx_vdev_handle data_vdev, + ol_txrx_data_tx_cb callback, + void *ctxt); + +/** + * @brief Allow the control-path SW to send data frames. + * @details + * Generally, all tx data frames come from the OS shim into the txrx layer. + * However, there are rare cases such as TDLS messaging where the UMAC + * control-path SW creates tx data frames. + * This UMAC SW can call this function to provide the tx data frames to + * the txrx layer. + * The UMAC SW can request a callback for these data frames after their + * transmission completes, by using the wdi_in_data_tx_cb_set function + * to register a tx completion callback, and by specifying + * ol_tx_spec_no_free as the tx_spec arg when giving the frames to + * ol_tx_non_std. + * The MSDUs need to have the appropriate L2 header type (802.3 vs. 802.11), + * as specified by ol_cfg_frame_type(). + * + * @param data_vdev - which vdev should transmit the tx data frames + * @param tx_spec - what non-standard handling to apply to the tx data frames + * @param msdu_list - NULL-terminated list of tx MSDUs + */ +adf_nbuf_t +ol_tx_non_std( + ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, + adf_nbuf_t msdu_list); + +typedef void +(*ol_txrx_mgmt_tx_cb)(void *ctxt, adf_nbuf_t tx_mgmt_frm, int had_error); + +/** + * @brief Store a callback for delivery notifications for managements frames. + * @details + * When the txrx SW receives notifications from the target that a tx frame + * has been delivered to its recipient, it will check if the tx frame + * is a management frame. If so, the txrx SW will check the management + * frame type specified when the frame was submitted for transmission. + * If there is a callback function registered for the type of managment + * frame in question, the txrx code will invoke the callback to inform + * the management + control SW that the mgmt frame was delivered. + * This function is used by the control SW to store a callback pointer + * for a given type of management frame. + * + * @param pdev - the data physical device object + * @param type - the type of mgmt frame the callback is used for + * @param download_cb - the callback for delivery notification to target + * @param ota_ack_cb - the callback for delivery notification to peer + * @param ctxt - context to use with the callback + */ +void +wdi_in_mgmt_tx_cb_set( + ol_txrx_pdev_handle pdev, + u_int8_t type, + ol_txrx_mgmt_tx_cb download_cb, + ol_txrx_mgmt_tx_cb ota_ack_cb + void *ctxt); + +/** + * @brief Transmit a management frame. + * @details + * Send the specified management frame from the specified virtual device. + * The type is used for determining whether to invoke a callback to inform + * the sender that the tx mgmt frame was delivered, and if so, which + * callback to use. + * + * @param vdev - virtual device transmitting the frame + * @param tx_mgmt_frm - management frame to transmit + * @param type - the type of managment frame (determines what callback to use) + * @param use_6mbps - specify whether management frame to transmit should use 6 Mbps + * rather than 1 Mbps min rate(for 5GHz band or P2P) + * @return + * 0 -> the frame is accepted for transmission, -OR- + * 1 -> the frame was not accepted + */ +int +wdi_in_mgmt_send( + ol_txrx_vdev_handle vdev, + adf_nbuf_t tx_mgmt_frm, + u_int8_t type, + u_int8_t use_6mbps, + u_int16_t chanfreq); + +/** + * wdi_in_display_stats - display txrx stats + * @pdev: txrx pdev context + * @value: value + */ +void +wdi_in_display_stats(struct ol_txrx_pdev_t *pdev, uint16_t value); + + +/** + * wdi_in_clear_stats - clear txrx stats + * @pdev: txrx pdev context + * @value: value + */ +void +wdi_in_clear_stats(struct ol_txrx_pdev_t *pdev, uint16_t value); + +/** + * @brief Setup the monitor mode vap (vdev) for this pdev + * @details + * When a non-NULL vdev handle is registered as the monitor mode vdev, all + * packets received by the system are delivered to the OS stack on this + * interface in 802.11 MPDU format. Only a single monitor mode interface + * can be up at any timer. When the vdev handle is set to NULL the monitor + * mode delivery is stopped. This handle may either be a unique vdev + * object that only receives monitor mode packets OR a point to a a vdev + * object that also receives non-monitor traffic. In the second case the + * OS stack is responsible for delivering the two streams using approprate + * OS APIs + * + * @param pdev - the data physical device object + * @param vdev - the data virtual device object to deliver monitor mode + * packets on + * @return + * 0 -> the monitor mode vap was sucessfully setup + * -1 -> Unable to setup monitor mode + */ +int +wdi_in_set_monitor_mode_vap( + ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev); + +/** + * @brief Setup the current operating channel of the device + * @details + * Mainly used when populating monitor mode status that requires the + * current operating channel + * + * @param pdev - the data physical device object + * @param chan_mhz - the channel frequency (mhz) + * packets on + * @return - void + */ +void +wdi_in_set_curchan( + ol_txrx_pdev_handle pdev, + u_int32_t chan_mhz); + +/** + * @brief Get the number of pending transmit frames that are awaiting completion. + * @details + * Mainly used in clean up path to make sure all buffers have been free'ed + * + * @param pdev - the data physical device object + * @return - count of pending frames + */ +int +wdi_in_get_tx_pending( + ol_txrx_pdev_handle pdev); + +/** + * @brief Discard all tx frames that are pending in txrx. + * @details + * Mainly used in clean up path to make sure all pending tx packets + * held by txrx are returned back to OS shim immediately. + * + * @param pdev - the data physical device object + * @return - void + */ +void +wdi_in_discard_tx_pending( + ol_txrx_pdev_handle pdev); + +/** + * @brief set the safemode of the device + * @details + * This flag is used to bypass the encrypt and decrypt processes when send and + * receive packets. It works like open AUTH mode, HW will treate all packets + * as non-encrypt frames because no key installed. For rx fragmented frames, + * it bypasses all the rx defragmentaion. + * + * @param vdev - the data virtual device object + * @param val - the safemode state + * @return - void + */ +void +wdi_in_set_safemode( + ol_txrx_vdev_handle vdev, + u_int32_t val); + +/** + * @brief set the privacy filter + * @details + * Rx related. Set the privacy filters. When rx packets, check the ether type, filter type and + * packet type to decide whether discard these packets. + * + * @param vdev - the data virtual device object + * @param filter - filters to be set + * @param num - the number of filters + * @return - void + */ +void +wdi_in_set_privacy_filters( + ol_txrx_vdev_handle vdev, + void *filter, + u_int32_t num); + +/** + * @brief configure the drop unencrypted frame flag + * @details + * Rx related. When set this flag, all the unencrypted frames + * received over a secure connection will be discarded + * + * @param vdev - the data virtual device object + * @param val - flag + * @return - void + */ +void +wdi_in_set_drop_unenc( + ol_txrx_vdev_handle vdev, + u_int32_t val); + +enum ol_txrx_peer_state { + ol_txrx_peer_state_disc, /* initial state */ + ol_txrx_peer_state_conn, /* authentication in progress */ + ol_txrx_peer_state_auth, /* authentication completed successfully */ +}; + +/** + * @brief specify the peer's authentication state + * @details + * Specify the peer's authentication state (none, connected, authenticated) + * to allow the data SW to determine whether to filter out invalid data frames. + * (In the "connected" state, where security is enabled, but authentication + * has not completed, tx and rx data frames other than EAPOL or WAPI should + * be discarded.) + * This function is only relevant for systems in which the tx and rx filtering + * are done in the host rather than in the target. + * + * @param data_peer - which peer has changed its state + * @param state - the new state of the peer + */ +void +wdi_in_peer_state_update(ol_txrx_pdev_handle pdev, u_int8_t *peer_mac, + ol_txrx_peer_handle data_peer, + enum ol_txrx_peer_state state); + +void +wdi_in_peer_keyinstalled_state_update( + ol_txrx_peer_handle data_peer, + u_int8_t val); + +#define ol_tx_addba_conf(data_peer, tid, status) /* no-op */ + +/** + * @typedef ol_txrx_tx_fp + * @brief top-level transmit function + */ +typedef adf_nbuf_t (*ol_txrx_tx_fp)( + ol_txrx_vdev_handle data_vdev, adf_nbuf_t msdu_list); + +/** + * @enum ol_txrx_osif_tx_spec + * @brief indicate what non-standard transmission actions to apply + * @details + * Indicate one or more of the following: + * - The tx frame already has a complete 802.11 header. + * Thus, skip 802.3/native-WiFi to 802.11 header encapsulation and + * A-MSDU aggregation. + * - The tx frame should not be aggregated (A-MPDU or A-MSDU) + * - The tx frame is already encrypted - don't attempt encryption. + * - The tx frame is a segment of a TCP jumbo frame. + * More than one of these specification can apply, though typically + * only a single specification is applied to a tx frame. + * A compound specification can be created, as a bit-OR of these + * specifications. + */ +enum ol_txrx_osif_tx_spec { + ol_txrx_osif_tx_spec_std = 0x0, /* do regular processing */ + ol_txrx_osif_tx_spec_raw = 0x1, /* skip encap + A-MSDU aggr */ + ol_txrx_osif_tx_spec_no_aggr = 0x2, /* skip encap + all aggr */ + ol_txrx_osif_tx_spec_no_encrypt = 0x4, /* skip encap + encrypt */ + ol_txrx_osif_tx_spec_tso = 0x8, /* TCP segmented */ + ol_txrx_osif_tx_spect_nwifi_no_encrypt = 0x10, /* skip encrypt for nwifi */ +}; + +/** + * @typedef ol_txrx_tx_non_std_fp + * @brief top-level transmit function for non-standard tx frames + * @details + * This function pointer provides an alternative to the ol_txrx_tx_fp + * to support non-standard transmits. In particular, this function + * supports transmission of: + * 1. "Raw" frames + * These raw frames already have an 802.11 header; the usual + * 802.11 header encapsulation by the driver does not apply. + * 2. TSO segments + * During tx completion, the txrx layer needs to reclaim the buffer + * that holds the ethernet/IP/TCP header created for the TSO segment. + * Thus, these tx frames need to be marked as TSO, to show that they + * need this special handling during tx completion. + * + * @param data_vdev - which virtual device should transmit the frame + * @param tx_spec - what non-standard operations to apply to the tx frame + * @param msdu_list - tx frame(s), in a null-terminated list + */ +typedef adf_nbuf_t (*ol_txrx_tx_non_std_fp)( + ol_txrx_vdev_handle data_vdev, + enum ol_txrx_osif_tx_spec tx_spec, + adf_nbuf_t msdu_list); + +/** + * @typedef ol_txrx_rx_fp + * @brief receive function to hand batches of data frames from txrx to OS shim + */ +typedef void (*ol_txrx_rx_fp)(ol_osif_vdev_handle vdev, adf_nbuf_t msdus); + +/** + * @typedef ol_txrx_rx_mon_fp + * @brief OSIF monitor mode receive function for single MPDU (802.11 format) + */ +typedef void (*ol_txrx_rx_mon_fp)( + ol_osif_vdev_handle vdev, + adf_nbuf_t mpdu, + void *rx_status); + +struct ol_txrx_osif_ops { + /* tx function pointers - specified by txrx, stored by OS shim */ + struct { + ol_txrx_tx_fp std; + ol_txrx_tx_non_std_fp non_std; + } tx; + + /* rx function pointers - specified by OS shim, stored by txrx */ + struct { + ol_txrx_rx_fp std; + ol_txrx_rx_mon_fp mon; + } rx; +}; + +/** + * @brief Link a vdev's data object with the matching OS shim vdev object. + * @details + * The data object for a virtual device is created by the function + * ol_txrx_vdev_attach. However, rather than fully linking the + * data vdev object with the vdev objects from the other subsystems + * that the data vdev object interacts with, the txrx_vdev_attach + * function focuses primarily on creating the data vdev object. + * After the creation of both the data vdev object and the OS shim + * vdev object, this txrx_osif_vdev_attach function is used to connect + * the two vdev objects, so the data SW can use the OS shim vdev handle + * when passing rx data received by a vdev up to the OS shim. + * + * @param txrx_vdev - the virtual device's data object + * @param osif_vdev - the virtual device's OS shim object + * @param txrx_ops - (pointers to) the functions used for tx and rx data xfer + * There are two portions of these txrx operations. + * The rx portion is filled in by OSIF SW before calling + * wdi_in_osif_vdev_register; inside the wdi_in_osif_vdev_register + * the txrx SW stores a copy of these rx function pointers, to use + * as it delivers rx data frames to the OSIF SW. + * The tx portion is filled in by the txrx SW inside + * wdi_in_osif_vdev_register; when the function call returns, + * the OSIF SW stores a copy of these tx functions to use as it + * delivers tx data frames to the txrx SW. + * The rx function pointer inputs consist of the following: + * rx: the OS shim rx function to deliver rx data frames to. + * This can have different values for different virtual devices, + * e.g. so one virtual device's OS shim directly hands rx frames to + * the OS, but another virtual device's OS shim filters out P2P + * messages before sending the rx frames to the OS. + * The netbufs delivered to the osif_rx function are in the format + * specified by the OS to use for tx and rx frames (either 802.3 or + * native WiFi). + * rx_mon: the OS shim rx monitor function to deliver monitor data to + * Though in practice, it is probable that the same function will + * be used for delivering rx monitor data for all virtual devices, + * in theory each different virtual device can have a different + * OS shim function for accepting rx monitor data. + * The netbufs delivered to the osif_rx_mon function are in 802.11 + * format. Each netbuf holds a 802.11 MPDU, not an 802.11 MSDU. + * Depending on compile-time configuration, each netbuf may also + * have a monitor-mode encapsulation header such as a radiotap + * header added before the MPDU contents. + * The tx function pointer outputs consist of the following: + * tx: the tx function pointer for standard data frames + * This function pointer is set by the txrx SW to perform + * host-side transmit operations based on whether a HL or LL + * host/target interface is in use. + * tx_non_std: the tx function pointer for non-standard data frames, + * such as TSO frames, explicitly-prioritized frames, or "raw" + * frames which skip some of the tx operations, such as 802.11 + * MAC header encapsulation. + */ +void +wdi_in_osif_vdev_register( + ol_txrx_vdev_handle txrx_vdev, + void *osif_vdev, + struct ol_txrx_osif_ops *txrx_ops); + +/** + * @brief Divide a jumbo TCP frame into smaller segments. + * @details + * For efficiency, the protocol stack above the WLAN driver may operate + * on jumbo tx frames, which are larger than the 802.11 MTU. + * The OSIF SW uses this txrx API function to divide the jumbo tx TCP frame + * into a series of segment frames. + * The segments are created as clones of the input jumbo frame. + * The txrx SW generates a new encapsulation header (ethernet + IP + TCP) + * for each of the output segment frames. The exact format of this header, + * e.g. 802.3 vs. Ethernet II, and IPv4 vs. IPv6, is chosen to match the + * header format of the input jumbo frame. + * The input jumbo frame is not modified. + * After the wdi_in_osif_tso_segment returns, the OSIF SW needs to perform + * DMA mapping on each of the segment network buffers, and also needs to + * + * @param txrx_vdev - which virtual device will transmit the TSO segments + * @param max_seg_payload_bytes - the maximum size for the TCP payload of + * each segment frame. + * This does not include the ethernet + IP + TCP header sizes. + * @param jumbo_tcp_frame - jumbo frame which needs to be cloned+segmented + * @return + * NULL if the segmentation fails, - OR - + * a NULL-terminated list of segment network buffers + */ +adf_nbuf_t wdi_in_osif_tso_segment( + ol_txrx_vdev_handle txrx_vdev, + int max_seg_payload_bytes, + adf_nbuf_t jumbo_tcp_frame); + +#define WDI_EVENT_BASE 0x100 /* Event starting number */ + +enum WDI_EVENT { + WDI_EVENT_TX_STATUS = WDI_EVENT_BASE, + WDI_EVENT_RX_DESC, + WDI_EVENT_RX_DESC_REMOTE, + WDI_EVENT_RATE_FIND, + WDI_EVENT_RATE_UPDATE, + WDI_EVENT_RX_PEER_INVALID, + /* End of new event items */ + + WDI_EVENT_LAST +}; + +struct wdi_event_rx_peer_invalid_msg { + adf_nbuf_t msdu; + struct ieee80211_frame *wh; + u_int8_t vdev_id; +}; + +#define WDI_NUM_EVENTS WDI_EVENT_LAST - WDI_EVENT_BASE + +#define WDI_EVENT_NOTIFY_BASE 0x200 +enum WDI_EVENT_NOTIFY { + WDI_EVENT_SUB_DEALLOCATE = WDI_EVENT_NOTIFY_BASE, + /* End of new notification types */ + + WDI_EVENT_NOTIFY_LAST +}; + +/* Opaque event callback */ +typedef void (*wdi_event_cb)(void *pdev, enum WDI_EVENT event, void *data); + +/* Opaque event notify */ +typedef void (*wdi_event_notify)(enum WDI_EVENT_NOTIFY notify, + enum WDI_EVENT event); +/** + * @typedef wdi_event_subscribe + * @brief Used by consumers to subscribe to WDI event notifications. + * @details + * The event_subscribe struct includes pointers to other event_subscribe + * objects. These pointers are simply to simplify the management of + * lists of event subscribers. These pointers are set during the + * event_sub() function, and shall not be modified except by the + * WDI event management SW, until after the object's event subscription + * is canceled by calling event_unsub(). + */ + +typedef struct wdi_event_subscribe_t { + wdi_event_cb callback; /* subscriber event callback structure head*/ + void *context; /* subscriber object that processes the event callback */ + struct { + /* private - the event subscriber SW shall not use this struct */ + struct wdi_event_subscribe_t *next; + struct wdi_event_subscribe_t *prev; + } priv; +} wdi_event_subscribe; + +struct wdi_event_pdev_t; +typedef struct wdi_event_pdev_t *wdi_event_pdev_handle; + +/** + * @brief Subscribe to a specified WDI event. + * @details + * This function adds the provided wdi_event_subscribe object to a list of + * subscribers for the specified WDI event. + * When the event in question happens, each subscriber for the event will + * have their callback function invoked. + * The order in which callback functions from multiple subscribers are + * invoked is unspecified. + * + * @param pdev - the event physical device, that maintains the event lists + * @param event_cb_sub - the callback and context for the event subscriber + * @param event - which event's notifications are being subscribed to + * @return error code, or A_OK for success + */ +A_STATUS wdi_in_event_sub( + struct ol_txrx_pdev_t *txrx_pdev, + wdi_event_subscribe *event_cb_sub, + enum WDI_EVENT event); + +/** + * @brief Unsubscribe from a specified WDI event. + * @details + * This function removes the provided event subscription object from the + * list of subscribers for its event. + * This function shall only be called if there was a successful prior call + * to event_sub() on the same wdi_event_subscribe object. + * + * @param pdev - the event physical device with the list of event subscribers + * @param event_cb_sub - the event subscription object + * @param event - which event is being unsubscribed + * @return error code, or A_OK for success + */ +A_STATUS wdi_in_event_unsub( + struct ol_txrx_pdev_t *txrx_pdev, + wdi_event_subscribe *event_cb_sub, + enum WDI_EVENT event); + +#include /* adf_os_mutex_t */ +#include /* htt_dbg_stats_type */ +#include /* ol_txrx_stats */ + +typedef void (*ol_txrx_stats_callback)( + void *ctxt, + enum htt_dbg_stats_type type, + u_int8_t *buf, + int bytes); + +struct ol_txrx_stats_req { + u_int32_t stats_type_upload_mask; /* which stats to upload */ + u_int32_t stats_type_reset_mask; /* which stats to reset */ + + /* stats will be printed if either print element is set */ + struct { + int verbose; /* verbose stats printout */ + int concise; /* concise stats printout (takes precedence) */ + } print; /* print uploaded stats */ + + /* stats notify callback will be invoked if fp is non-NULL */ + struct { + ol_txrx_stats_callback fp; + void *ctxt; + } callback; + + /* stats will be copied into the specified buffer if buf is non-NULL */ + struct { + u_int8_t *buf; + int byte_limit; /* don't copy more than this */ + } copy; + + /* + * If blocking is true, the caller will take the specified semaphore + * to wait for the stats to be uploaded, and the driver will release + * the semaphore when the stats are done being uploaded. + */ + struct { + int blocking; + adf_os_mutex_t *sem_ptr; + } wait; +}; + +#ifdef ATH_PERF_PWR_OFFLOAD /*---------------------------------------------*/ + +#define wdi_in_debug(vdev, debug_specs) 0 +#define wdi_in_fw_stats_cfg(vdev, type, val) 0 +#define wdi_in_fw_stats_get(vdev, req) 0 +#define wdi_in_aggr_cfg(vdev, max_subfrms_ampdu, max_subfrms_amsdu) 0 + +#else /*---------------------------------------------------------------------*/ + +int wdi_in_debug(ol_txrx_vdev_handle vdev, int debug_specs); + +void wdi_in_fw_stats_cfg( + ol_txrx_vdev_handle vdev, + u_int8_t cfg_stats_type, + u_int32_t cfg_val); + +int wdi_in_fw_stats_get( + ol_txrx_vdev_handle vdev, + struct ol_txrx_stats_req *req); + +int wdi_in_aggr_cfg(ol_txrx_vdev_handle vdev, + int max_subfrms_ampdu, + int max_subfrms_amsdu); + +enum { + TXRX_DBG_MASK_OBJS = 0x01, + TXRX_DBG_MASK_STATS = 0x02, + TXRX_DBG_MASK_PROT_ANALYZE = 0x04, + TXRX_DBG_MASK_RX_REORDER_TRACE = 0x08, + TXRX_DBG_MASK_RX_PN_TRACE = 0x10 +}; + +/*--- txrx printouts ---*/ + +/* + * Uncomment this to enable txrx printouts with dynamically adjustable + * verbosity. These printouts should not impact performance. + */ +#define TXRX_PRINT_ENABLE 1 +/* uncomment this for verbose txrx printouts (may impact performance) */ +//#define TXRX_PRINT_VERBOSE_ENABLE 1 + +void wdi_in_print_level_set(unsigned level); + +/*--- txrx object (pdev, vdev, peer) display debug functions ---*/ + +#ifndef TXRX_DEBUG_LEVEL +#define TXRX_DEBUG_LEVEL 0 /* no debug info */ +#endif + +#if TXRX_DEBUG_LEVEL > 5 +void wdi_in_pdev_display(ol_txrx_pdev_handle pdev, int indent); +void wdi_in_vdev_display(ol_txrx_vdev_handle vdev, int indent); +void wdi_in_peer_display(ol_txrx_peer_handle peer, int indent); +#else +#define wdi_in_pdev_display(pdev, indent) +#define wdi_in_vdev_display(vdev, indent) +#define wdi_in_peer_display(peer, indent) +#endif + +/*--- txrx stats display debug functions ---*/ + +#if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF + +void wdi_in_stats_display(ol_txrx_pdev_handle pdev); + +int +wdi_in_stats_publish(ol_txrx_pdev_handle pdev, struct ol_txrx_stats *buf); + +#else +#define wdi_in_stats_display(pdev) +#define wdi_in_stats_publish(pdev, buf) TXRX_STATS_LEVEL_OFF +#endif /* TXRX_STATS_LEVEL */ + +/*--- txrx protocol analyzer debug feature ---*/ + +/* uncomment this to enable the protocol analzyer feature */ +//#define ENABLE_TXRX_PROT_ANALYZE 1 + +#if defined(ENABLE_TXRX_PROT_ANALYZE) + +void wdi_in_prot_ans_display(ol_txrx_pdev_handle pdev); + +#else + +#define wdi_in_prot_ans_display(pdev) + +#endif /* ENABLE_TXRX_PROT_ANALYZE */ + +/*--- txrx sequence number trace debug feature ---*/ + +/* uncomment this to enable the rx reorder trace feature */ +//#define ENABLE_RX_REORDER_TRACE 1 + +#define wdi_in_seq_num_trace_display(pdev) \ + ol_rx_reorder_trace_display(pdev, 0, 0) + +#if defined(ENABLE_RX_REORDER_TRACE) + +void +ol_rx_reorder_trace_display(ol_txrx_pdev_handle pdev, int just_once, int limit); + +#else + +#define ol_rx_reorder_trace_display(pdev, just_once, limit) + +#endif /* ENABLE_RX_REORDER_TRACE */ + +/*--- txrx packet number trace debug feature ---*/ + +/* uncomment this to enable the rx PN trace feature */ +//#define ENABLE_RX_PN_TRACE 1 + +#define wdi_in_pn_trace_display(pdev) ol_rx_pn_trace_display(pdev, 0) + +#if defined(ENABLE_RX_PN_TRACE) + +void +ol_rx_pn_trace_display(ol_txrx_pdev_handle pdev, int just_once); + +#else + +#define ol_rx_pn_trace_display(pdev, just_once) + +#endif /* ENABLE_RX_PN_TRACE */ + +/*--- tx queue log debug feature ---*/ +/* uncomment this to enable the tx queue log feature */ + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + +void +ol_tx_queue_log_display(ol_txrx_pdev_handle pdev); + +#else + +#define ol_tx_queue_log_display(pdev) + +#endif /* defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) */ + +#endif /* ATH_PERF_PWR_OFFLOAD */ /*----------------------------------------*/ + +#else +/* WDI_API_AS_MACROS */ + +#include + +#define wdi_in_pdev_cfg_attach ol_pdev_cfg_attach +#define wdi_in_pdev_attach ol_txrx_pdev_attach +#define wdi_in_pdev_attach_target ol_txrx_pdev_attach_target +#define wdi_in_enable_host_ratectrl ol_txrx_enable_host_ratectrl +#define wdi_in_vdev_attach ol_txrx_vdev_attach +#define wdi_in_peer_attach ol_txrx_peer_attach +#define wdi_in_peer_update ol_txrx_peer_update +#define wdi_in_peer_pause ol_txrx_peer_pause +#define wdi_in_peer_tid_unpause ol_txrx_peer_tid_unpause +#define wdi_in_tx_release ol_txrx_tx_release +#define wdi_in_vdev_pause ol_txrx_vdev_pause +#define wdi_in_vdev_unpause ol_txrx_vdev_unpause +#define wdi_in_pdev_pause ol_txrx_pdev_pause +#define wdi_in_pdev_unpause ol_txrx_pdev_unpause +#define wdi_in_tx_sync ol_txrx_tx_sync +#define wdi_in_peer_detach ol_txrx_peer_detach +#define wdi_in_vdev_detach ol_txrx_vdev_detach +#define wdi_in_pdev_detach ol_txrx_pdev_detach +#define wdi_in_data_tx_cb_set ol_txrx_data_tx_cb_set +#define wdi_in_mgmt_tx_cb_set ol_txrx_mgmt_tx_cb_set +#define wdi_in_mgmt_send ol_txrx_mgmt_send +#define wdi_in_display_stats ol_txrx_display_stats +#define wdi_in_clear_stats ol_txrx_clear_stats +#define wdi_in_set_monitor_mode_vap ol_txrx_set_monitor_mode_vap +#define wdi_in_set_curchan ol_txrx_set_curchan +#define wdi_in_get_tx_pending ol_txrx_get_tx_pending +#define wdi_in_discard_tx_pending ol_txrx_discard_tx_pending +#define wdi_in_set_safemode ol_txrx_set_safemode +#define wdi_in_set_privacy_filters ol_txrx_set_privacy_filters +#define wdi_in_set_drop_unenc ol_txrx_set_drop_unenc +#define wdi_in_peer_state_update ol_txrx_peer_state_update +#define wdi_in_peer_keyinstalled_state_update ol_txrx_peer_keyinstalled_state_update +#define wdi_in_vdev_rx_fwd_disabled ol_vdev_rx_set_intrabss_fwd +#ifdef QCA_LL_TX_FLOW_CT +#define wdi_in_get_tx_resource ol_txrx_get_tx_resource +#define wdi_in_ll_set_tx_pause_q_depth ol_txrx_ll_set_tx_pause_q_depth +#endif /* QCA_LL_TX_FLOW_CT */ +#define wdi_in_set_wmm_param ol_txrx_set_wmm_param + +#include + +#define wdi_in_debug ol_txrx_debug +#define wdi_in_fw_stats_cfg ol_txrx_fw_stats_cfg +#define wdi_in_fw_stats_get ol_txrx_fw_stats_get +#define wdi_in_aggr_cfg ol_txrx_aggr_cfg +#define wdi_in_debug ol_txrx_debug +#define wdi_in_fw_stats_cfg ol_txrx_fw_stats_cfg +#define wdi_in_fw_stats_get ol_txrx_fw_stats_get +#define wdi_in_aggr_cfg ol_txrx_aggr_cfg +#define wdi_in_aggr_cfg ol_txrx_aggr_cfg +#define wdi_in_print_level_set ol_txrx_print_level_set +#define wdi_in_pdev_display ol_txrx_pdev_display +#define wdi_in_vdev_display ol_txrx_vdev_display +#define wdi_in_peer_display ol_txrx_peer_display +#define wdi_in_pdev_display ol_txrx_pdev_display +#define wdi_in_vdev_display ol_txrx_vdev_display +#define wdi_in_peer_display ol_txrx_peer_display +#define wdi_in_stats_display ol_txrx_stats_display +#define wdi_in_stats_publish ol_txrx_stats_publish +#define wdi_in_stats_display ol_txrx_stats_display +#define wdi_in_stats_publish ol_txrx_stats_publish +#define wdi_in_prot_ans_display ol_txrx_prot_ans_display +#define wdi_in_prot_ans_display ol_txrx_prot_ans_display +#define wdi_in_seq_num_trace_display ol_txrx_seq_num_trace_display +#define wdi_in_pn_trace_display ol_txrx_pn_trace_display + +#ifdef IPA_UC_OFFLOAD +#define wdi_in_ipa_uc_get_resource ol_txrx_ipa_uc_get_resource +#define wdi_in_ipa_uc_set_doorbell_paddr ol_txrx_ipa_uc_set_doorbell_paddr +#define wdi_in_ipa_uc_set_active ol_txrx_ipa_uc_set_active +#define wdi_in_ipa_uc_register_op_cb ol_txrx_ipa_uc_register_op_cb +#endif /* IPA_UC_OFFLOAD */ + +#include + +#define wdi_in_osif_vdev_register ol_txrx_osif_vdev_register +#define wdi_in_osif_tso_segment ol_txrx_osif_tso_segment +#include + +#define wdi_in_event_sub wdi_event_sub +#define wdi_in_event_unsub wdi_event_unsub +#define wdi_in_set_cfg_rx_fwd_disabled ol_set_cfg_rx_fwd_disabled +#define wdi_in_set_cfg_pakcet_log_enabled ol_set_cfg_packet_log_enabled + +#endif /* WDI_API_AS_FUNCS / MACROS */ + +#endif /* _WDI_IN__H_ */ + +/**@}*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_out.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_out.h new file mode 100644 index 000000000000..dcfccd273fd1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_out.h @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY */ +/** + * @addtogroup WDIAPI + *@{ + */ +/** + * @file wdi_out.h + * @brief Functions outside the WDI boundary called by datapath functions + */ +#ifndef _WDI_OUT__H_ +#define _WDI_OUT__H_ + +#include + +#ifdef WDI_API_AS_FUNCS + +#include /* u_int32_t */ +#include /* ieee80211_qosframe_htc_addr4 */ +#include /* LLC_SNAP_HDR_LEN */ + +#if defined(CONFIG_HL_SUPPORT) +#include "wlan_tgt_def_config_hl.h" +#else +#include "wlan_tgt_def_config.h" +#endif + +/** + * @brief Specify whether the system is high-latency or low-latency. + * @details + * Indicate whether the system is operating in high-latency (message + * based, e.g. USB) mode or low-latency (memory-mapped, e.g. PCIe) mode. + * Some chips support just one type of host / target interface. + * Other chips support both LL and HL interfaces (e.g. PCIe and USB), + * so the selection will be made based on which bus HW is present, or + * which is preferred if both are present. + * + * @param pdev - handle to the physical device + * @return 1 -> high-latency -OR- 0 -> low-latency + */ +int wdi_out_cfg_is_high_latency(ol_pdev_handle pdev); + +/** + * @brief Specify the range of peer IDs. + * @details + * Specify the maximum peer ID. This is the maximum number of peers, + * minus one. + * This is used by the host to determine the size of arrays indexed by + * peer ID. + * + * @param pdev - handle to the physical device + * @return maximum peer ID + */ +int wdi_out_cfg_max_peer_id(ol_pdev_handle pdev); + +/** + * @brief Specify the max number of virtual devices within a physical device. + * @details + * Specify how many virtual devices may exist within a physical device. + * + * @param pdev - handle to the physical device + * @return maximum number of virtual devices + */ +int wdi_out_cfg_max_vdevs(ol_pdev_handle pdev); + +/** + * @brief Check whether host-side rx PN check is enabled or disabled. + * @details + * Choose whether to allocate rx PN state information and perform + * rx PN checks (if applicable, based on security type) on the host. + * If the rx PN check is specified to be done on the host, the host SW + * will determine which peers are using a security type (e.g. CCMP) that + * requires a PN check. + * + * @param pdev - handle to the physical device + * @return 1 -> host performs rx PN check -OR- 0 -> no host-side rx PN check + */ +int wdi_out_cfg_rx_pn_check(ol_pdev_handle pdev); + +/** + * @brief Check whether host-side rx forwarding is enabled or disabled. + * @details + * Choose whether to check whether to forward rx frames to tx on the host. + * For LL systems, this rx -> tx host-side forwarding check is typically + * enabled. + * For HL systems, the rx -> tx forwarding check is typically done on the + * target. However, even in HL systems, the host-side rx -> tx forwarding + * will typically be enabled, as a second-tier safety net in case the + * target doesn't have enough memory to store all rx -> tx forwarded frames. + * + * @param pdev - handle to the physical device + * @return 1 -> host does rx->tx forward -OR- 0 -> no host-side rx->tx forward + */ +int wdi_out_cfg_rx_fwd_check(ol_pdev_handle pdev); + +/** + * @brief Check whether to perform inter-BSS or intra-BSS rx->tx forwarding. + * @details + * Check whether data received by an AP on one virtual device destined + * to a STA associated with a different virtual device within the same + * physical device should be forwarded within the driver, or whether + * forwarding should only be done within a virtual device. + * + * @param pdev - handle to the physical device + * @return + * 1 -> forward both within and between vdevs + * -OR- + * 0 -> forward only within a vdev + */ +int wdi_out_cfg_rx_fwd_inter_bss(ol_pdev_handle pdev); + +/** + * @brief format of data frames delivered to/from the WLAN driver by/to the OS + */ +enum wlan_frm_fmt { + wlan_frm_fmt_unknown, + wlan_frm_fmt_raw, + wlan_frm_fmt_native_wifi, + wlan_frm_fmt_802_3, +}; + +/** + * @brief Specify data frame format used by the OS. + * @details + * Specify what type of frame (802.3 or native WiFi) the host data SW + * should expect from and provide to the OS shim. + * + * @param pdev - handle to the physical device + * @return enumerated data frame format + */ +enum wlan_frm_fmt wdi_out_cfg_frame_type(ol_pdev_handle pdev); + +/** + * @brief Specify the peak throughput. + * @details + * Specify the peak throughput that a system is expected to support. + * The data SW uses this configuration to help choose the size for its + * tx descriptor pool and rx buffer ring. + * The data SW assumes that the peak throughput applies to either rx or tx, + * rather than having separate specs of the rx max throughput vs. the tx + * max throughput. + * + * @param pdev - handle to the physical device + * @return maximum supported throughput in Mbps (not MBps) + */ +int wdi_out_cfg_max_thruput_mbps(ol_pdev_handle pdev); + +/** + * @brief Specify the maximum number of fragments per tx network buffer. + * @details + * Specify the maximum number of fragments that a tx frame provided to + * the WLAN driver by the OS may contain. + * In LL systems, the host data SW uses this maximum fragment count to + * determine how many elements to allocate in the fragmentation descriptor + * it creates to specify to the tx MAC DMA where to locate the tx frame's + * data. + * This maximum fragments count is only for regular frames, not TSO frames, + * since TSO frames are sent in segments with a limited number of fragments + * per segment. + * + * @param pdev - handle to the physical device + * @return maximum number of fragments that can occur in a regular tx frame + */ +int wdi_out_cfg_netbuf_frags_max(ol_pdev_handle pdev); + +/** + * @brief For HL systems, specify when to free tx frames. + * @details + * In LL systems, the host's tx frame is referenced by the MAC DMA, and + * thus cannot be freed until the target indicates that it is finished + * transmitting the frame. + * In HL systems, the entire tx frame is downloaded to the target. + * Consequently, the target has its own copy of the tx frame, and the + * host can free the tx frame as soon as the download completes. + * Alternatively, the HL host can keep the frame allocated until the + * target explicitly tells the HL host it is done transmitting the frame. + * This gives the target the option of discarding its copy of the tx + * frame, and then later getting a new copy from the host. + * This function tells the host whether it should retain its copy of the + * transmit frames until the target explicitly indicates it is finished + * transmitting them, or if it should free its copy as soon as the + * tx frame is downloaded to the target. + * + * @param pdev - handle to the physical device + * @return + * 0 -> retain the tx frame until the target indicates it is done + * transmitting the frame + * -OR- + * 1 -> free the tx frame as soon as the download completes + */ +int wdi_out_cfg_tx_free_at_download(ol_pdev_handle pdev); + +/** + * @brief Low water mark for target tx credit. + * Tx completion handler is invoked to reap the buffers when the target tx + * credit goes below Low Water Mark. + */ +#define OL_CFG_NUM_MSDU_REAP 512 +#define wdi_out_cfg_tx_credit_lwm(pdev) \ + ((CFG_TGT_NUM_MSDU_DESC > OL_CFG_NUM_MSDU_REAP) ? \ + (CFG_TGT_NUM_MSDU_DESC - OL_CFG_NUM_MSDU_REAP) : 0) + +/** + * @brief In a HL system, specify the target initial credit count. + * @details + * The HL host tx data SW includes a module for determining which tx frames + * to download to the target at a given time. + * To make this judgement, the HL tx download scheduler has to know + * how many buffers the HL target has available to hold tx frames. + * Due to the possibility that a single target buffer pool can be shared + * between rx and tx frames, the host may not be able to obtain a precise + * specification of the tx buffer space available in the target, but it + * uses the best estimate, as provided by this configuration function, + * to determine how best to schedule the tx frame downloads. + * + * @param pdev - handle to the physical device + * @return the number of tx buffers available in a HL target + */ +int wdi_out_cfg_target_tx_credit(ol_pdev_handle pdev); + +/** + * @brief Specify the LL tx MSDU header download size. + * @details + * In LL systems, determine how many bytes from a tx frame to download, + * in order to provide the target FW's Descriptor Engine with enough of + * the packet's payload to interpret what kind of traffic this is, + * and who it is for. + * This download size specification does not include the 802.3 / 802.11 + * frame encapsulation headers; it starts with the encapsulated IP packet + * (or whatever ethertype is carried within the ethernet-ish frame). + * The LL host data SW will determine how many bytes of the MSDU header to + * download by adding this download size specification to the size of the + * frame header format specified by the wdi_out_cfg_frame_type configuration + * function. + * + * @param pdev - handle to the physical device + * @return the number of bytes beyond the 802.3 or native WiFi header to + * download to the target for tx classification + */ +int wdi_out_cfg_tx_download_size(ol_pdev_handle pdev); + +/** + * brief Specify where defrag timeout and duplicate detection is handled + * @details + * non-aggregate duplicate detection and timing out stale fragments + * requires additional target memory. To reach max client + * configurations (128+), non-aggregate duplicate detection and the + * logic to time out stale fragments is moved to the host. + * + * @param pdev - handle to the physical device + * @return + * 0 -> target is responsible non-aggregate duplicate detection and + * timing out stale fragments. + * + * 1 -> host is responsible non-aggregate duplicate detection and + * timing out stale fragments. + */ +int wdi_out_cfg_rx_host_defrag_timeout_duplicate_check(ol_pdev_handle pdev); + +typedef enum { + wlan_frm_tran_cap_raw = 0x01, + wlan_frm_tran_cap_native_wifi = 0x02, + wlan_frm_tran_cap_8023 = 0x04, +} wlan_target_fmt_translation_caps; + +/** + * @brief Specify the maximum header size added by SW tx encapsulation + * @details + * This function returns the maximum size of the new L2 header, not the + * difference between the new and old L2 headers. + * Thus, this function returns the maximum 802.11 header size that the + * tx SW may need to add to tx data frames. + * + * @param pdev - handle to the physical device + */ +static inline int +wdi_out_cfg_sw_encap_hdr_max_size(ol_pdev_handle pdev) +{ + /* + * 24 byte basic 802.11 header + * + 6 byte 4th addr + * + 2 byte QoS control + * + 4 byte HT control + * + 8 byte LLC/SNAP + */ + return sizeof(struct ieee80211_qosframe_htc_addr4) + LLC_SNAP_HDR_LEN; +} + +static inline u_int8_t +wdi_out_cfg_tx_encap(ol_pdev_handle pdev) +{ + /* tx encap done in HW */ + return 0; +} + +static inline int +wdi_out_cfg_host_addba(ol_pdev_handle pdev) +{ + /* + * ADDBA negotiation is handled by the target FW for Peregrine + Rome. + */ + return 0; +} + +/** + * @brief If the host SW's ADDBA negotiation fails, should it be retried? + * + * @param pdev - handle to the physical device + */ +static inline int +wdi_out_cfg_addba_retry(ol_pdev_handle pdev) +{ + return 0; /* disabled for now */ +} + +/** + * @brief How many frames to hold in a paused vdev's tx queue in LL systems + */ +static inline int +wdi_out_tx_cfg_max_tx_queue_depth_ll(ol_pdev_handle pdev) +{ + /* + * Store up to 700 frames for a paused vdev. + * For example, if the vdev is sending 300 Mbps of traffic, and the + * PHY is capable of 600 Mbps, then it will take 56 ms for the PHY to + * drain both the 700 frames that are queued initially, plus the next + * 700 frames that come in while the PHY is catching up. + * So in this example scenario, the PHY will remain fully utilized + * in a MCC system that has a channel-switching period of 56 ms or less. + */ + return 700; +} + +//#include /* u_int8_t */ +#include /* u_int8_t */ +#include /* adf_nbuf_t */ + +enum ol_rx_err_type { + OL_RX_ERR_DEFRAG_MIC, + OL_RX_ERR_PN, + OL_RX_ERR_UNKNOWN_PEER, + OL_RX_ERR_MALFORMED, + OL_RX_ERR_TKIP_MIC, + OL_RX_ERR_DECRYPT, + OL_RX_ERR_MPDU_LENGTH, + OL_RX_ERR_ENCRYPT_REQUIRED, + OL_RX_ERR_DUP, + OL_RX_ERR_UNKNOWN, + OL_RX_ERR_FCS, + OL_RX_ERR_PRIVACY, + OL_RX_ERR_NONE_FRAG, + OL_RX_ERR_NONE = 0xFF +}; + +#ifdef SUPPORT_HOST_STATISTICS +/** * @brief Update tx statistics + * @details + * Update tx statistics after tx complete. + * + * @param pdev - ol_pdev_handle instance + * @param vdev_id - ID of the virtual device that tx frame + * @param had_error - whether there is error when tx + */ +void wdi_out_tx_statistics(ol_pdev_handle pdev, + u_int16_t vdev_id, + int had_error); +#else +#define wdi_out_tx_statistics(pdev, vdev_id, had_error) +#endif + +/** * @brief Count on received packets for invalid peer case + * + * @param pdev - txrx pdev handle + * @param wh - received frame + * @param err_type - what kind of error occurred + */ +void wdi_out_rx_err_inv_peer_statistics(ol_pdev_handle pdev, + struct ieee80211_frame *wh, + enum ol_rx_err_type err_type); + +/** + * @brief Count on received packets, both success and failed + * + * @param pdev - ol_pdev_handle handle + * @param vdev_id - ID of the virtual device received the erroneous rx frame + * @param err_type - what kind of error occurred + * @param sec_type - The cipher type the peer is using + * @param is_mcast - whether this is one multi cast frame + */ +void wdi_out_rx_err_statistics(ol_pdev_handle pdev, + u_int8_t vdev_id, + enum ol_rx_err_type err_type, + enum ol_sec_type sec_type, + int is_mcast); + +/** + * @brief Provide notification of failure during host rx processing + * @details + * Indicate an error during host rx data processing, including what + * kind of error happened, when it happened, which peer and TID the + * erroneous rx frame is from, and what the erroneous rx frame itself + * is. + * + * @param pdev - handle to the ctrl SW's physical device object + * @param vdev_id - ID of the virtual device received the erroneous rx frame + * @param peer_mac_addr - MAC address of the peer that sent the erroneous + * rx frame + * @param tid - which TID within the peer sent the erroneous rx frame + * @param tsf32 - the timstamp in TSF units of the erroneous rx frame, or + * one of the fragments that when reassembled, constitute the rx frame + * @param err_type - what kind of error occurred + * @param rx_frame - the rx frame that had an error + * @pn - Packet sequence number + * @key_id - Key index octet received in IV of the frame + */ +void +wdi_out_rx_err( + ol_pdev_handle pdev, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tid, + u_int32_t tsf32, + enum ol_rx_err_type err_type, + adf_nbuf_t rx_frame, + u_int64_t *pn, + u_int8_t key_id); + +enum ol_rx_notify_type { + OL_RX_NOTIFY_IPV4_IGMP, +}; + +/** + * @brief Provide notification of reception of data of special interest. + * @details + * Indicate when "special" data has been received. The nature of the + * data that results in it being considered special is specified in the + * notify_type argument. + * This function is currently used by the data-path SW to notify the + * control path SW when the following types of rx data are received: + * + IPv4 IGMP frames + * The control SW can use these to learn about multicast group + * membership, if it so chooses. + * + * @param pdev - handle to the ctrl SW's physical device object + * @param vdev_id - ID of the virtual device received the special data + * @param peer_mac_addr - MAC address of the peer that sent the special data + * @param tid - which TID within the peer sent the special data + * @param tsf32 - the timstamp in TSF units of the special data + * @param notify_type - what kind of special data was received + * @param rx_frame - the rx frame containing the special data + */ +void +wdi_out_rx_notify( + ol_pdev_handle pdev, + u_int8_t vdev_id, + u_int8_t *peer_mac_addr, + int tid, + u_int32_t tsf32, + enum ol_rx_notify_type notify_type, + adf_nbuf_t rx_frame); + +/** + * @brief Indicate when a paused STA has tx data available. + * @details + * Indicate to the control SW when a paused peer that previously + * has all its peer-TID queues empty gets a MSDU to transmit. + * Conversely, indicate when a paused peer that had data in one or more of + * its peer-TID queues has all queued data removed (e.g. due to a U-APSD + * triggered transmission), but is still paused. + * It is up to the control SW to determine whether the peer is paused due to + * being in power-save sleep, or some other reason, and thus whether it is + * necessary to set the TIM in beacons to notify a sleeping STA that it has + * data. + * The data SW will also issue this wdi_out_tx_paused_peer_data call when an + * unpaused peer that currently has tx data in one or more of its + * peer-TID queues becomes paused. + * The data SW will not issue this wdi_out_tx_paused_peer_data call when a + * peer with data in one or more of its peer-TID queues becomes unpaused. + * + * @param peer - the paused peer + * @param has_tx_data - + * 1 -> a paused peer that previously had no tx data now does, -OR- + * 0 -> a paused peer that previously had tx data now doesnt + */ +void +wdi_out_tx_paused_peer_data(ol_peer_handle peer, int has_tx_data); + + +#define wdi_out_ctrl_addba_req(pdev, peer_mac_addr, tid) ol_addba_req_reject +#define wdi_out_ctrl_rx_addba_complete(pdev, peer_mac_addr, tid, failed) /* no-op */ + + +#else +/* WDI_API_AS_MACROS */ + +#include + +#define wdi_out_cfg_is_high_latency ol_cfg_is_high_latency +#define wdi_out_cfg_max_peer_id ol_cfg_max_peer_id +#define wdi_out_cfg_max_vdevs ol_cfg_max_vdevs +#define wdi_out_cfg_rx_pn_check ol_cfg_rx_pn_check +#define wdi_out_cfg_rx_fwd_check ol_cfg_rx_fwd_check +#define wdi_out_cfg_rx_fwd_inter_bss ol_cfg_rx_fwd_inter_bss +#define wdi_out_cfg_frame_type ol_cfg_frame_type +#define wdi_out_cfg_max_thruput_mbps ol_cfg_max_thruput_mbps +#define wdi_out_cfg_netbuf_frags_max ol_cfg_netbuf_frags_max +#define wdi_out_cfg_tx_free_at_download ol_cfg_tx_free_at_download +#define wdi_out_cfg_tx_credit_lwm ol_cfg_tx_credit_lwm +#define wdi_out_cfg_target_tx_credit ol_cfg_target_tx_credit +#define wdi_out_cfg_tx_download_size ol_cfg_tx_download_size +#define wdi_out_cfg_rx_host_defrag_timeout_duplicate_check ol_cfg_rx_host_defrag_timeout_duplicate_check +#define wdi_out_cfg_sw_encap_hdr_max_size ol_cfg_sw_encap_hdr_max_size +#define wdi_out_cfg_tx_encap ol_cfg_tx_encap +#define wdi_out_cfg_host_addba ol_cfg_host_addba +#define wdi_out_cfg_addba_retry ol_cfg_addba_retry +#define wdi_out_tx_cfg_max_tx_queue_depth_ll ol_tx_cfg_max_tx_queue_depth_ll + +#include + +#define wdi_out_tx_statistics ol_tx_statistics +#define wdi_out_tx_statistics ol_tx_statistics +#define wdi_out_rx_err_inv_peer_statistics ol_rx_err_inv_peer_statistics +#define wdi_out_rx_err_statistics ol_rx_err_statistics +#define wdi_out_rx_err ol_rx_err +#define wdi_out_rx_notify ol_rx_notify +#define wdi_out_tx_paused_peer_data ol_tx_paused_peer_data +#define wdi_out_ctrl_addba_req ol_ctrl_addba_req +#define wdi_out_ctrl_rx_addba_complete ol_ctrl_rx_addba_complete +#define wdi_out_cfg_rx_fwd_disabled ol_cfg_rx_fwd_disabled + +#endif /* WDI_API_AS_FUNCS / MACROS */ + +#endif /* _WDI_OUT__H_ */ + +/**@}*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_types.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_types.h new file mode 100644 index 000000000000..e6e500769a6c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wdi_types.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY */ +/** + * @addtogroup WDIAPI + *@{ + */ +/** + * @file wdi_types.h + * @brief Data type definitions used within the WDI API + * @details + * The data type definitions shown below are purely for documentation + * reference. + * The actual data type definitions are obtained by including the individual + * API header files that define them. + */ +#ifndef _WDI_TYPES__H_ +#define _WDI_TYPES__H_ + +#ifdef WDI_TYPES_DIRECT_DEFS + +struct ol_pdev_t; +typedef struct ol_pdev_t* ol_pdev_handle; + +struct ol_vdev_t; +typedef struct ol_vdev_t* ol_vdev_handle; + +struct ol_peer_t; +typedef struct ol_peer_t* ol_peer_handle; + +/** + * @typedef ol_osif_vdev_handle + * @brief opaque handle for OS shim virtual device object + */ +struct ol_osif_vdev_t; +typedef struct ol_osif_vdev_t* ol_osif_vdev_handle; + +/** + * @typedef ol_txrx_pdev_handle + * @brief opaque handle for txrx physical device object + */ +struct ol_txrx_pdev_t; +typedef struct ol_txrx_pdev_t* ol_txrx_pdev_handle; + +/** + * @typedef ol_txrx_vdev_handle + * @brief opaque handle for txrx virtual device object + */ +struct ol_txrx_vdev_t; +typedef struct ol_txrx_vdev_t* ol_txrx_vdev_handle; + +/** + * @typedef ol_txrx_peer_handle + * @brief opaque handle for txrx peer object + */ +struct ol_txrx_peer_t; +typedef struct ol_txrx_peer_t* ol_txrx_peer_handle; + +/** + * @brief ADDBA negotiation status, used both during requests and confirmations + */ +enum ol_addba_status { + /* status: negotiation started or completed successfully */ + ol_addba_success, + + /* reject: aggregation is not applicable - don't try again */ + ol_addba_reject, + + /* busy: ADDBA negotiation couldn't be performed - try again later */ + ol_addba_busy, +}; + +enum ol_sec_type { + ol_sec_type_none, + ol_sec_type_wep128, + ol_sec_type_wep104, + ol_sec_type_wep40, + ol_sec_type_tkip, + ol_sec_type_tkip_nomic, + ol_sec_type_aes_ccmp, + ol_sec_type_wapi, + + /* keep this last! */ + ol_sec_type_types +}; + +#else + +/* obtain data type defs from individual API header files */ + +#include +#include +#include + +#endif /* WDI_TYPES_DIRECT_DEFS */ + +#endif /* _WDI_TYPES__H_ */ + +/**@}*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_defs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_defs.h new file mode 100644 index 000000000000..8d73cb2e6644 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_defs.h @@ -0,0 +1,798 @@ +/* + * Copyright (c) 2004-2010, 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLANDEFS_H__ +#define __WLANDEFS_H__ + +#include /* A_COMPILE_TIME_ASSERT */ +#include + +/* + * This file contains WLAN definitions that may be used across both + * Host and Target software. + */ + + +/* + * MAX_SPATIAL_STREAM should be defined in a fwconfig_xxx.h file, + * but for now provide a default value here in case it's not defined + * in the fwconfig_xxx.h file. + */ +#ifndef MAX_SPATIAL_STREAM +#define MAX_SPATIAL_STREAM 3 +#endif + +/* + * MAX_SPATIAL_STREAM_ANY - + * what is the largest number of spatial streams that any target supports + */ +#define MAX_SPATIAL_STREAM_ANY 4 + +#ifndef CONFIG_160MHZ_SUPPORT +#define CONFIG_160MHZ_SUPPORT 0 /* default: 160 MHz channels not supported */ +#endif + +typedef enum { + MODE_11A = 0, /* 11a Mode */ + MODE_11G = 1, /* 11b/g Mode */ + MODE_11B = 2, /* 11b Mode */ + MODE_11GONLY = 3, /* 11g only Mode */ + MODE_11NA_HT20 = 4, /* 11a HT20 mode */ + MODE_11NG_HT20 = 5, /* 11g HT20 mode */ + MODE_11NA_HT40 = 6, /* 11a HT40 mode */ + MODE_11NG_HT40 = 7, /* 11g HT40 mode */ + MODE_11AC_VHT20 = 8, + MODE_11AC_VHT40 = 9, + MODE_11AC_VHT80 = 10, + MODE_11AC_VHT20_2G = 11, + MODE_11AC_VHT40_2G = 12, + MODE_11AC_VHT80_2G = 13, +#if CONFIG_160MHZ_SUPPORT + MODE_11AC_VHT80_80 = 14, + MODE_11AC_VHT160 = 15, +#endif + + MODE_UNKNOWN, + MODE_UNKNOWN_NO_160MHZ_SUPPORT = 14, + MODE_UNKNOWN_160MHZ_SUPPORT = 16, + + MODE_MAX = MODE_UNKNOWN, + MODE_MAX_NO_160_MHZ_SUPPORT = MODE_UNKNOWN_NO_160MHZ_SUPPORT, + MODE_MAX_160_MHZ_SUPPORT = MODE_UNKNOWN_160MHZ_SUPPORT, + +} WLAN_PHY_MODE; + +#if CONFIG_160MHZ_SUPPORT == 0 +A_COMPILE_TIME_ASSERT( + mode_unknown_value_consistency_Check, + MODE_UNKNOWN == MODE_UNKNOWN_NO_160MHZ_SUPPORT); +#else +A_COMPILE_TIME_ASSERT( + mode_unknown_value_consistency_Check, + MODE_UNKNOWN == MODE_UNKNOWN_160MHZ_SUPPORT); +#endif + +typedef enum { + VHT_MODE_NONE = 0, /* NON VHT Mode, e.g., HT, DSSS, CCK */ + VHT_MODE_20M = 1, + VHT_MODE_40M = 2, + VHT_MODE_80M = 3, + VHT_MODE_160M = 4 +} VHT_OPER_MODE; + +typedef enum { + WLAN_11A_CAPABILITY = 1, + WLAN_11G_CAPABILITY = 2, + WLAN_11AG_CAPABILITY = 3, +}WLAN_CAPABILITY; + +#if defined(CONFIG_AR900B_SUPPORT) || defined(AR900B) +#define A_RATEMASK A_UINT64 +#else +#define A_RATEMASK A_UINT32 +#endif + +#define A_RATEMASK_NUM_OCTET (sizeof (A_RATEMASK)) +#define A_RATEMASK_NUM_BITS ((sizeof (A_RATEMASK)) << 3) + + +#if CONFIG_160MHZ_SUPPORT +#define IS_MODE_VHT(mode) (((mode) == MODE_11AC_VHT20) || \ + ((mode) == MODE_11AC_VHT40) || \ + ((mode) == MODE_11AC_VHT80) || \ + ((mode) == MODE_11AC_VHT80_80) || \ + ((mode) == MODE_11AC_VHT160)) +#else +#define IS_MODE_VHT(mode) (((mode) == MODE_11AC_VHT20) || \ + ((mode) == MODE_11AC_VHT40) || \ + ((mode) == MODE_11AC_VHT80)) +#endif + +#define IS_MODE_VHT_2G(mode) (((mode) == MODE_11AC_VHT20_2G) || \ + ((mode) == MODE_11AC_VHT40_2G) || \ + ((mode) == MODE_11AC_VHT80_2G)) + + +#define IS_MODE_11A(mode) (((mode) == MODE_11A) || \ + ((mode) == MODE_11NA_HT20) || \ + ((mode) == MODE_11NA_HT40) || \ + (IS_MODE_VHT(mode))) + +#define IS_MODE_11B(mode) ((mode) == MODE_11B) +#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \ + ((mode) == MODE_11GONLY) || \ + ((mode) == MODE_11NG_HT20) || \ + ((mode) == MODE_11NG_HT40) || \ + (IS_MODE_VHT_2G(mode))) +#define IS_MODE_11GN(mode) (((mode) == MODE_11NG_HT20) || \ + ((mode) == MODE_11NG_HT40)) +#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY) + + +enum { + REGDMN_MODE_11A = 0x00000001, /* 11a channels */ + REGDMN_MODE_TURBO = 0x00000002, /* 11a turbo-only channels */ + REGDMN_MODE_11B = 0x00000004, /* 11b channels */ + REGDMN_MODE_PUREG = 0x00000008, /* 11g channels (OFDM only) */ + REGDMN_MODE_11G = 0x00000008, /* XXX historical */ + REGDMN_MODE_108G = 0x00000020, /* 11g+Turbo channels */ + REGDMN_MODE_108A = 0x00000040, /* 11a+Turbo channels */ + REGDMN_MODE_XR = 0x00000100, /* XR channels */ + REGDMN_MODE_11A_HALF_RATE = 0x00000200, /* 11A half rate channels */ + REGDMN_MODE_11A_QUARTER_RATE = 0x00000400, /* 11A quarter rate channels */ + REGDMN_MODE_11NG_HT20 = 0x00000800, /* 11N-G HT20 channels */ + REGDMN_MODE_11NA_HT20 = 0x00001000, /* 11N-A HT20 channels */ + REGDMN_MODE_11NG_HT40PLUS = 0x00002000, /* 11N-G HT40 + channels */ + REGDMN_MODE_11NG_HT40MINUS = 0x00004000, /* 11N-G HT40 - channels */ + REGDMN_MODE_11NA_HT40PLUS = 0x00008000, /* 11N-A HT40 + channels */ + REGDMN_MODE_11NA_HT40MINUS = 0x00010000, /* 11N-A HT40 - channels */ + REGDMN_MODE_11AC_VHT20 = 0x00020000, /* 5Ghz, VHT20 */ + REGDMN_MODE_11AC_VHT40PLUS = 0x00040000, /* 5Ghz, VHT40 + channels */ + REGDMN_MODE_11AC_VHT40MINUS = 0x00080000, /* 5Ghz VHT40 - channels */ + REGDMN_MODE_11AC_VHT80 = 0x000100000, /* 5Ghz, VHT80 channels */ + REGDMN_MODE_11AC_VHT20_2G = 0x000200000, /* 2Ghz, VHT20 */ + REGDMN_MODE_11AC_VHT40_2G = 0x000400000, /* 2Ghz, VHT40 */ + REGDMN_MODE_11AC_VHT80_2G = 0x000800000, /* 2Ghz, VHT80 */ + REGDMN_MODE_11AC_VHT160 = 0x001000000, /* 5Ghz, VHT160 */ +}; + +#define REGDMN_MODE_ALL (0xFFFFFFFF) /* REGDMN_MODE_ALL is defined out of the enum + * to prevent the ARM compile "warning #66: + * enumeration value is out of int range" + * Anyway, this is a BIT-OR of all possible values. + */ + +#define REGDMN_CAP1_CHAN_HALF_RATE 0x00000001 +#define REGDMN_CAP1_CHAN_QUARTER_RATE 0x00000002 +#define REGDMN_CAP1_CHAN_HAL49GHZ 0x00000004 + + +/* regulatory capabilities */ +#define REGDMN_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMI_TLVTAG_STRUC_HAL_REG_CAPABILITIES */ + A_UINT32 eeprom_rd; //regdomain value specified in EEPROM + A_UINT32 eeprom_rd_ext; //regdomain + A_UINT32 regcap1; // CAP1 capabilities bit map. + A_UINT32 regcap2; // REGDMN EEPROM CAP. + A_UINT32 wireless_modes; // REGDMN MODE + A_UINT32 low_2ghz_chan; + A_UINT32 high_2ghz_chan; + A_UINT32 low_5ghz_chan; + A_UINT32 high_5ghz_chan; +} HAL_REG_CAPABILITIES; + +typedef enum { + WHAL_REG_EXT_FCC_MIDBAND = 0, + WHAL_REG_EXT_JAPAN_MIDBAND = 1, + WHAL_REG_EXT_FCC_DFS_HT40 = 2, + WHAL_REG_EXT_JAPAN_NONDFS_HT40 = 3, + WHAL_REG_EXT_JAPAN_DFS_HT40 = 4, + WHAL_REG_EXT_FCC_CH_144 = 5, +} WHAL_REG_EXT_BITMAP; + +/* + * Used to update rate-control logic with the status of the tx-completion. + * In host-based implementation of the rate-control feature, this struture is used to + * create the payload for HTT message/s from target to host. + */ + +typedef struct { + A_UINT8 rateCode; + A_UINT8 flags; +}RATE_CODE; + +typedef struct { + RATE_CODE ptx_rc; /* rate code, bw, chain mask sgi */ + A_UINT8 reserved[2]; + A_UINT32 flags; /* Encodes information such as excessive + retransmission, aggregate, some info + from .11 frame control, + STBC, LDPC, (SGI and Tx Chain Mask + are encoded in ptx_rc->flags field), + AMPDU truncation (BT/time based etc.), + RTS/CTS attempt */ + A_UINT32 num_enqued; /* # of MPDUs (for non-AMPDU 1) for this rate */ + A_UINT32 num_retries; /* Total # of transmission attempt for this rate */ + A_UINT32 num_failed; /* # of failed MPDUs in A-MPDU, 0 otherwise */ + A_UINT32 ack_rssi; /* ACK RSSI: b'7..b'0 avg RSSI across all chain */ + A_UINT32 time_stamp ; /* ACK timestamp (helps determine age) */ + A_UINT32 is_probe; /* Valid if probing. Else, 0 */ + A_UINT32 ba_win_size; /* b'7..b0, block Ack Window size, b'31..b8 Resvd */ + A_UINT32 failed_ba_bmap_0_31; /* failed BA bitmap 0..31 */ + A_UINT32 failed_ba_bmap_32_63; /* failed BA bitmap 32..63 */ + A_UINT32 bmap_tried_0_31; /* enqued bitmap 0..31 */ + A_UINT32 bmap_tried_32_63; /* enqued bitmap 32..63 */ +} RC_TX_DONE_PARAMS; + + +#define RC_SET_TX_DONE_INFO(_dst, _rc, _f, _nq, _nr, _nf, _rssi, _ts) \ + do { \ + (_dst).ptx_rc.rateCode = (_rc).rateCode; \ + (_dst).ptx_rc.flags = (_rc).flags; \ + (_dst).flags = (_f); \ + (_dst).num_enqued = (_nq); \ + (_dst).num_retries = (_nr); \ + (_dst).num_failed = (_nf); \ + (_dst).ack_rssi = (_rssi); \ + (_dst).time_stamp = (_ts); \ + } while (0) + +#define RC_SET_TXBF_DONE_INFO(_dst, _f) \ + do { \ + (_dst).flags |= (_f); \ + } while (0) + +/* NOTE: NUM_DYN_BW and NUM_SCHED_ENTRIES cannot be changed without breaking WMI Compatibility */ +#define NUM_SCHED_ENTRIES 2 +#define NUM_DYN_BW_MAX 4 + +/* Some products only use 20/40/80; some use 20/40/80/160 */ +#ifndef NUM_DYN_BW +#define NUM_DYN_BW 3 /* default: support up through 80 MHz */ +#endif + +#define NUM_DYN_BW_MASK 0x3 + +#define PROD_SCHED_BW_ENTRIES (NUM_SCHED_ENTRIES * NUM_DYN_BW) +typedef A_UINT8 A_RATE; + +#if NUM_DYN_BW > 4 +// Extend rate table module first +#error "Extend rate table module first" +#endif + +#define MAX_IBSS_PEERS 32 + +#if defined(CONFIG_AR900B_SUPPORT) || defined(AR900B) +typedef struct{ + A_UINT32 psdu_len [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_UINT16 flags[NUM_SCHED_ENTRIES][NUM_DYN_BW]; + A_RATE rix[NUM_SCHED_ENTRIES][NUM_DYN_BW]; + A_UINT8 tpc[NUM_SCHED_ENTRIES][NUM_DYN_BW]; + A_UINT32 antmask[NUM_SCHED_ENTRIES]; + A_UINT8 num_mpdus [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_UINT16 txbf_cv_len; + A_UINT32 txbf_cv_ptr; + A_UINT16 txbf_flags; + A_UINT16 txbf_cv_size; + A_UINT8 txbf_nc_idx; + A_UINT8 tries[NUM_SCHED_ENTRIES]; + A_UINT8 bw_mask[NUM_SCHED_ENTRIES]; + A_UINT8 max_bw[NUM_SCHED_ENTRIES]; + A_UINT8 num_sched_entries; + A_UINT8 paprd_mask; + A_UINT8 rts_rix; + A_UINT8 sh_pream; + A_UINT8 min_spacing_1_4_us; + A_UINT8 fixed_delims; + A_UINT8 bw_in_service; + A_RATE probe_rix; + A_UINT8 num_valid_rates; + A_UINT8 rtscts_tpc; +} RC_TX_RATE_SCHEDULE; + +#else +typedef struct{ + A_UINT32 psdu_len [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_UINT16 flags [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_RATE rix [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_UINT8 tpc [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_UINT8 num_mpdus [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_UINT32 antmask [NUM_SCHED_ENTRIES]; + A_UINT32 txbf_cv_ptr; + A_UINT16 txbf_cv_len; + A_UINT8 tries [NUM_SCHED_ENTRIES]; + A_UINT8 num_valid_rates; + A_UINT8 paprd_mask; + A_UINT8 rts_rix; + A_UINT8 sh_pream; + A_UINT8 min_spacing_1_4_us; + A_UINT8 fixed_delims; + A_UINT8 bw_in_service; + A_RATE probe_rix; +} RC_TX_RATE_SCHEDULE; +#endif + +typedef struct{ + A_UINT16 flags [NUM_DYN_BW * NUM_SCHED_ENTRIES]; + A_RATE rix [NUM_DYN_BW * NUM_SCHED_ENTRIES]; +#ifdef DYN_TPC_ENABLE + A_UINT8 tpc [NUM_DYN_BW * NUM_SCHED_ENTRIES]; +#endif +#ifdef SECTORED_ANTENNA + A_UINT32 antmask [NUM_SCHED_ENTRIES]; +#endif + A_UINT8 tries [NUM_SCHED_ENTRIES]; + A_UINT8 num_valid_rates; + A_UINT8 rts_rix; + A_UINT8 sh_pream; + A_UINT8 bw_in_service; + A_RATE probe_rix; + A_UINT8 dd_profile; +} RC_TX_RATE_INFO; + +/* + * Temporarily continue to provide the WHAL_RC_INIT_RC_MASKS def in wlan_defs.h + * for older targets. + * The WHAL_RX_INIT_RC_MASKS macro def needs to be moved into ratectrl_11ac.h + * for all targets, but until this is complete, the WHAL_RC_INIT_RC_MASKS def + * will be maintained here in its old location. + */ +#if CONFIG_160MHZ_SUPPORT == 0 +#define WHAL_RC_INIT_RC_MASKS(_rm) do { \ + _rm[WHAL_RC_MASK_IDX_NON_HT] = A_RATEMASK_OFDM_CCK; \ + _rm[WHAL_RC_MASK_IDX_HT_20] = A_RATEMASK_HT_20; \ + _rm[WHAL_RC_MASK_IDX_HT_40] = A_RATEMASK_HT_40; \ + _rm[WHAL_RC_MASK_IDX_VHT_20] = A_RATEMASK_VHT_20; \ + _rm[WHAL_RC_MASK_IDX_VHT_40] = A_RATEMASK_VHT_40; \ + _rm[WHAL_RC_MASK_IDX_VHT_80] = A_RATEMASK_VHT_80; \ + } while (0) +#endif + +/** + * strucutre describing host memory chunk. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wlan_host_memory_chunk */ + /** id of the request that is passed up in service ready */ + A_UINT32 req_id; + /** the physical address the memory chunk */ + A_UINT32 ptr; + /** size of the chunk */ + A_UINT32 size; +} wlan_host_memory_chunk; + +#define NUM_UNITS_IS_NUM_VDEVS 0x1 +#define NUM_UNITS_IS_NUM_PEERS 0x2 + +/** + * structure used by FW for requesting host memory + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMI_TLVTAG_STRUC_wlan_host_mem_req */ + + /** ID of the request */ + A_UINT32 req_id; + /** size of the of each unit */ + A_UINT32 unit_size; + /** + * flags to indicate that + * the number units is dependent + * on number of resources(num vdevs num peers .. etc) + */ + A_UINT32 num_unit_info; + /* + * actual number of units to allocate . if flags in the num_unit_info + * indicate that number of units is tied to number of a particular + * resource to allocate then num_units filed is set to 0 and host + * will derive the number units from number of the resources it is + * requesting. + */ + A_UINT32 num_units; +} wlan_host_mem_req; + +typedef enum { + IGNORE_DTIM = 0x01, + NORMAL_DTIM = 0x02, + STICK_DTIM = 0x03, + AUTO_DTIM = 0x04, +} BEACON_DTIM_POLICY; + +/* During test it is observed that 6 * 400 = 2400 can + * be alloced in addition to CFG_TGT_NUM_MSDU_DESC. + * If there is any change memory requirement, this number + * needs to be revisited. */ +#define TOTAL_VOW_ALLOCABLE 2400 +#define VOW_DESC_GRAB_MAX 800 + +#define VOW_GET_NUM_VI_STA(vow_config) (((vow_config) & 0xffff0000) >> 16) +#define VOW_GET_DESC_PER_VI_STA(vow_config) ((vow_config) & 0x0000ffff) + +/***TODO!!! Get these values dynamically in WMI_READY event and use it to calculate the mem req*/ +/* size in bytes required for msdu descriptor. If it changes, this should be updated. LARGE_AP + * case is not considered. LARGE_AP is disabled when VoW is enabled.*/ +#define MSDU_DESC_SIZE 20 + +/* size in bytes required to support a peer in target. + * This obtained by considering Two tids per peer. + * peer structure = 168 bytes + * tid = 96 bytes (per sta 2 means we need 192 bytes) + * peer_cb = 16 * 2 + * key = 52 * 2 + * AST = 12 * 2 + * rate, reorder.. = 384 + * smart antenna = 50 + */ +#define MEMORY_REQ_FOR_PEER 800 +/* + * NB: it is important to keep all the fields in the structure dword long + * so that it is easy to handle the statistics in BE host. + */ + +struct wlan_dbg_tx_stats { + /* Num HTT cookies queued to dispatch list */ + A_INT32 comp_queued; + /* Num HTT cookies dispatched */ + A_INT32 comp_delivered; + /* Num MSDU queued to WAL */ + A_INT32 msdu_enqued; + /* Num MPDU queue to WAL */ + A_INT32 mpdu_enqued; + /* Num MSDUs dropped by WMM limit */ + A_INT32 wmm_drop; + /* Num Local frames queued */ + A_INT32 local_enqued; + /* Num Local frames done */ + A_INT32 local_freed; + /* Num queued to HW */ + A_INT32 hw_queued; + /* Num PPDU reaped from HW */ + A_INT32 hw_reaped; + /* Num underruns */ + A_INT32 underrun; +#if defined(AR900B) + /* HW Paused. */ + A_UINT32 hw_paused; +#endif + /* Num PPDUs cleaned up in TX abort */ + A_INT32 tx_abort; + /* Num MPDUs requed by SW */ + A_INT32 mpdus_requed; + /* excessive retries */ + A_UINT32 tx_ko; +#if defined(AR900B) + A_UINT32 tx_xretry; +#endif + /* data hw rate code */ + A_UINT32 data_rc; + /* Scheduler self triggers */ + A_UINT32 self_triggers; + /* frames dropped due to excessive sw retries */ + A_UINT32 sw_retry_failure; + /* illegal rate phy errors */ + A_UINT32 illgl_rate_phy_err; + /* wal pdev continous xretry */ + A_UINT32 pdev_cont_xretry; + /* wal pdev continous xretry */ + A_UINT32 pdev_tx_timeout; + /* wal pdev resets */ + A_UINT32 pdev_resets; + /* frames dropped due to non-availability of stateless TIDs */ + A_UINT32 stateless_tid_alloc_failure; + /* PhY/BB underrun */ + A_UINT32 phy_underrun; + /* MPDU is more than txop limit */ + A_UINT32 txop_ovf; +#if defined(AR900B) + /* Number of Sequences posted */ + A_UINT32 seq_posted; + /* Number of Sequences failed queueing */ + A_UINT32 seq_failed_queueing; + /* Number of Sequences completed */ + A_UINT32 seq_completed; + /* Number of Sequences restarted */ + A_UINT32 seq_restarted; + /* Number of MU Sequences posted */ + A_UINT32 mu_seq_posted; + /* Num MPDUs flushed by SW, HWPAUSED, SW TXABORT (Reset,channel change) */ + A_INT32 mpdus_sw_flush; + /* Num MPDUs filtered by HW, all filter condition (TTL expired) */ + A_INT32 mpdus_hw_filter; + /* Num MPDUs truncated by PDG (TXOP, TBTT, PPDU_duration based on rate, dyn_bw) */ + A_INT32 mpdus_truncated; + /* Num MPDUs that was tried but didn't receive ACK or BA */ + A_INT32 mpdus_ack_failed; + /* Num MPDUs that was dropped du to expiry. */ + A_INT32 mpdus_expired; + /* Num mc drops */ + //A_UINT32 mc_drop; +#endif +}; + +struct wlan_dbg_rx_stats { + /* Cnts any change in ring routing mid-ppdu */ + A_INT32 mid_ppdu_route_change; + /* Total number of statuses processed */ + A_INT32 status_rcvd; + /* Extra frags on rings 0-3 */ + A_INT32 r0_frags; + A_INT32 r1_frags; + A_INT32 r2_frags; + A_INT32 r3_frags; + /* MSDUs / MPDUs delivered to HTT */ + A_INT32 htt_msdus; + A_INT32 htt_mpdus; + /* MSDUs / MPDUs delivered to local stack */ + A_INT32 loc_msdus; + A_INT32 loc_mpdus; + /* AMSDUs that have more MSDUs than the status ring size */ + A_INT32 oversize_amsdu; + /* Number of PHY errors */ + A_INT32 phy_errs; + /* Number of PHY errors drops */ + A_INT32 phy_err_drop; + /* Number of mpdu errors - FCS, MIC, ENC etc. */ + A_INT32 mpdu_errs; +#if defined(AR900B) + /* Number of rx overflow errors. */ + A_INT32 rx_ovfl_errs; +#endif +}; + + +struct wlan_dbg_mem_stats { + A_UINT32 iram_free_size; + A_UINT32 dram_free_size; +}; + +struct wlan_dbg_peer_stats { + + A_INT32 dummy; /* REMOVE THIS ONCE REAL PEER STAT COUNTERS ARE ADDED */ +}; + +typedef struct { + A_UINT32 mcs[10]; + A_UINT32 sgi[10]; + A_UINT32 nss[4]; + A_UINT32 nsts; + A_UINT32 stbc[10]; + A_UINT32 bw[3]; + A_UINT32 pream[6]; + A_UINT32 ldpc; + A_UINT32 txbf; + A_UINT32 mgmt_rssi; + A_UINT32 data_rssi; + A_UINT32 rssi_chain0; + A_UINT32 rssi_chain1; + A_UINT32 rssi_chain2; +/* + * TEMPORARY: leave rssi_chain3 in place for AR900B builds until code using + * rssi_chain3 has been converted to use wlan_dbg_rx_rate_info_v2_t. + * At that time, this rssi_chain3 field will be deleted. + */ +#if defined(AR900B) + A_UINT32 rssi_chain3; +#endif +} wlan_dbg_rx_rate_info_t ; + +typedef struct { + A_UINT32 mcs[10]; + A_UINT32 sgi[10]; +/* + * TEMPORARY: leave nss conditionally defined, until all code that + * requires nss[4] is converted to use wlan_dbg_tx_rate_info_v2_t. + * At that time, this nss array will be made length = 3 unconditionally. + */ +#if defined(CONFIG_AR900B_SUPPORT) || defined(AR900B) + A_UINT32 nss[4]; +#else + A_UINT32 nss[3]; +#endif + A_UINT32 stbc[10]; + A_UINT32 bw[3]; + A_UINT32 pream[4]; + A_UINT32 ldpc; + A_UINT32 rts_cnt; + A_UINT32 ack_rssi; +} wlan_dbg_tx_rate_info_t ; + +#define WLAN_MAX_MCS 10 + +typedef struct { + A_UINT32 mcs[WLAN_MAX_MCS]; + A_UINT32 sgi[WLAN_MAX_MCS]; + A_UINT32 nss[MAX_SPATIAL_STREAM_ANY]; + A_UINT32 nsts; + A_UINT32 stbc[WLAN_MAX_MCS]; + A_UINT32 bw[NUM_DYN_BW_MAX]; + A_UINT32 pream[6]; + A_UINT32 ldpc; + A_UINT32 txbf; + A_UINT32 mgmt_rssi; + A_UINT32 data_rssi; + A_UINT32 rssi_chain0; + A_UINT32 rssi_chain1; + A_UINT32 rssi_chain2; + A_UINT32 rssi_chain3; + A_UINT32 reserved[8]; +} wlan_dbg_rx_rate_info_v2_t ; + +typedef struct { + A_UINT32 mcs[WLAN_MAX_MCS]; + A_UINT32 sgi[WLAN_MAX_MCS]; + A_UINT32 nss[MAX_SPATIAL_STREAM_ANY]; + A_UINT32 stbc[WLAN_MAX_MCS]; + A_UINT32 bw[NUM_DYN_BW_MAX]; + A_UINT32 pream[4]; + A_UINT32 ldpc; + A_UINT32 rts_cnt; + A_UINT32 ack_rssi; + A_UINT32 reserved[8]; +} wlan_dbg_tx_rate_info_v2_t ; + +#define WHAL_DBG_PHY_ERR_MAXCNT 18 +#define WHAL_DBG_SIFS_STATUS_MAXCNT 8 +#define WHAL_DBG_SIFS_ERR_MAXCNT 8 +#define WHAL_DBG_CMD_RESULT_MAXCNT 10 +#define WHAL_DBG_CMD_STALL_ERR_MAXCNT 4 +#define WHAL_DBG_FLUSH_REASON_MAXCNT 40 + +typedef enum { + WIFI_URRN_STATS_FIRST_PKT, + WIFI_URRN_STATS_BETWEEN_MPDU, + WIFI_URRN_STATS_WITHIN_MPDU, + WHAL_MAX_URRN_STATS +} wifi_urrn_type_t; + +typedef struct wlan_dbg_txbf_snd_stats { + A_UINT32 cbf_20[4]; + A_UINT32 cbf_40[4]; + A_UINT32 cbf_80[4]; + A_UINT32 sounding[9]; +}wlan_dbg_txbf_snd_stats_t; + +typedef struct wlan_dbg_wifi2_error_stats { + A_UINT32 urrn_stats[WHAL_MAX_URRN_STATS]; + A_UINT32 flush_errs[WHAL_DBG_FLUSH_REASON_MAXCNT]; + A_UINT32 schd_stall_errs[WHAL_DBG_CMD_STALL_ERR_MAXCNT]; + A_UINT32 schd_cmd_result[WHAL_DBG_CMD_RESULT_MAXCNT]; + A_UINT32 sifs_status[WHAL_DBG_SIFS_STATUS_MAXCNT]; + A_UINT8 phy_errs[WHAL_DBG_PHY_ERR_MAXCNT]; + A_UINT32 rx_rate_inval; +}wlan_dbg_wifi2_error_stats_t; + +typedef struct wlan_dbg_wifi2_error2_stats { + A_UINT32 schd_errs[WHAL_DBG_CMD_STALL_ERR_MAXCNT]; + A_UINT32 sifs_errs[WHAL_DBG_SIFS_ERR_MAXCNT]; +}wlan_dbg_wifi2_error2_stats_t; + +#define WLAN_DBG_STATS_SIZE_TXBF_VHT 10 +#define WLAN_DBG_STATS_SIZE_TXBF_HT 8 +#define WLAN_DBG_STATS_SIZE_TXBF_OFDM 8 +#define WLAN_DBG_STATS_SIZE_TXBF_CCK 7 + +typedef struct wlan_dbg_txbf_data_stats { + A_UINT32 tx_txbf_vht[WLAN_DBG_STATS_SIZE_TXBF_VHT]; + A_UINT32 rx_txbf_vht[WLAN_DBG_STATS_SIZE_TXBF_VHT]; + A_UINT32 tx_txbf_ht[WLAN_DBG_STATS_SIZE_TXBF_HT]; + A_UINT32 tx_txbf_ofdm[WLAN_DBG_STATS_SIZE_TXBF_OFDM]; + A_UINT32 tx_txbf_cck[WLAN_DBG_STATS_SIZE_TXBF_CCK]; +} wlan_dbg_txbf_data_stats_t; + +struct wlan_dbg_tx_mu_stats { + A_UINT32 mu_sch_nusers_2; + A_UINT32 mu_sch_nusers_3; + A_UINT32 mu_mpdus_queued_usr[4]; + A_UINT32 mu_mpdus_tried_usr[4]; + A_UINT32 mu_mpdus_failed_usr[4]; + A_UINT32 mu_mpdus_requeued_usr[4]; + A_UINT32 mu_err_no_ba_usr[4]; + A_UINT32 mu_mpdu_underrun_usr[4]; + A_UINT32 mu_ampdu_underrun_usr[4]; +}; + +struct wlan_dbg_tx_selfgen_stats { + A_UINT32 su_ndpa; + A_UINT32 su_ndp; + A_UINT32 mu_ndpa; + A_UINT32 mu_ndp; + A_UINT32 mu_brpoll_1; + A_UINT32 mu_brpoll_2; + A_UINT32 mu_bar_1; + A_UINT32 mu_bar_2; + A_UINT32 cts_burst; + A_UINT32 su_ndp_err; + A_UINT32 su_ndpa_err; + A_UINT32 mu_ndp_err; + A_UINT32 mu_brp1_err; + A_UINT32 mu_brp2_err; +}; + +typedef struct wlan_dbg_sifs_resp_stats { + A_UINT32 ps_poll_trigger; /* num ps-poll trigger frames */ + A_UINT32 uapsd_trigger; /* num uapsd trigger frames */ + A_UINT32 qb_data_trigger[2]; /* num data trigger frames; idx 0: explicit and idx 1: implicit */ + A_UINT32 qb_bar_trigger[2]; /* num bar trigger frames; idx 0: explicit and idx 1: implicit */ + A_UINT32 sifs_resp_data; /* num ppdus transmitted at SIFS interval */ + A_UINT32 sifs_resp_err; /* num ppdus failed to meet SIFS resp timing */ +} wlan_dgb_sifs_resp_stats_t; + + + +/** wlan_dbg_wifi2_error_stats_t is not grouped with the + * following structure as it is allocated differently and only + * belongs to whal + */ +typedef struct wlan_dbg_stats_wifi2 { + wlan_dbg_txbf_snd_stats_t txbf_snd_info; + wlan_dbg_txbf_data_stats_t txbf_data_info; + struct wlan_dbg_tx_selfgen_stats tx_selfgen; + struct wlan_dbg_tx_mu_stats tx_mu; + wlan_dgb_sifs_resp_stats_t sifs_resp_info; +} wlan_dbg_wifi2_stats_t; + +typedef struct { + wlan_dbg_rx_rate_info_t rx_phy_info; + wlan_dbg_tx_rate_info_t tx_rate_info; +} wlan_dbg_rate_info_t; + +typedef struct { + wlan_dbg_rx_rate_info_v2_t rx_phy_info; + wlan_dbg_tx_rate_info_v2_t tx_rate_info; +} wlan_dbg_rate_info_v2_t; + +struct wlan_dbg_stats { + struct wlan_dbg_tx_stats tx; + struct wlan_dbg_rx_stats rx; +#if defined(AR900B) + struct wlan_dbg_mem_stats mem; +#endif + struct wlan_dbg_peer_stats peer; +}; + +#define DBG_STATS_MAX_HWQ_NUM 10 +#define DBG_STATS_MAX_TID_NUM 20 +#define DBG_STATS_MAX_CONG_NUM 16 +struct wlan_dbg_txq_stats { + A_UINT16 num_pkts_queued[DBG_STATS_MAX_HWQ_NUM]; + A_UINT16 tid_hw_qdepth[DBG_STATS_MAX_TID_NUM];//WAL_MAX_TID is 20 + A_UINT16 tid_sw_qdepth[DBG_STATS_MAX_TID_NUM];//WAL_MAX_TID is 20 +}; + +struct wlan_dbg_tidq_stats{ + A_UINT32 wlan_dbg_tid_txq_status; + struct wlan_dbg_txq_stats txq_st; +}; + +#endif /* __WLANDEFS_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_module_ids.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_module_ids.h new file mode 100644 index 000000000000..b9edddf121ce --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_module_ids.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _WLAN_MODULE_IDS_H_ +#define _WLAN_MODULE_IDS_H_ + +/* Wlan module ids , global across all the modules */ +typedef enum { + WLAN_MODULE_ID_MIN = 0, + WLAN_MODULE_INF = WLAN_MODULE_ID_MIN, /* 0x00 */ + WLAN_MODULE_WMI, + WLAN_MODULE_STA_PWRSAVE, + WLAN_MODULE_WHAL, + WLAN_MODULE_COEX, + WLAN_MODULE_ROAM, + WLAN_MODULE_RESMGR_CHAN_MANAGER, + WLAN_MODULE_RESMGR, + WLAN_MODULE_VDEV_MGR, + WLAN_MODULE_SCAN, + WLAN_MODULE_RATECTRL, + WLAN_MODULE_AP_PWRSAVE, + WLAN_MODULE_BLOCKACK, + WLAN_MODULE_MGMT_TXRX, + WLAN_MODULE_DATA_TXRX, + WLAN_MODULE_HTT, + WLAN_MODULE_HOST, /* 0x10 */ + WLAN_MODULE_BEACON, + WLAN_MODULE_OFFLOAD, + WLAN_MODULE_WAL, + WAL_MODULE_DE, + WLAN_MODULE_PCIELP, + WLAN_MODULE_RTT, + WLAN_MODULE_RESOURCE, + WLAN_MODULE_DCS, + WLAN_MODULE_CACHEMGR, + WLAN_MODULE_ANI, + WLAN_MODULE_P2P, + WLAN_MODULE_CSA, + WLAN_MODULE_NLO, + WLAN_MODULE_CHATTER, + WLAN_MODULE_WOW, + WLAN_MODULE_WAL_VDEV, /* 0x20 */ + WLAN_MODULE_WAL_PDEV, + WLAN_MODULE_TEST, + WLAN_MODULE_STA_SMPS, + WLAN_MODULE_SWBMISS, + WLAN_MODULE_WMMAC, + WLAN_MODULE_TDLS, + WLAN_MODULE_HB, + WLAN_MODULE_TXBF, + WLAN_MODULE_BATCH_SCAN, + WLAN_MODULE_THERMAL_MGR, + WLAN_MODULE_PHYERR_DFS, + WLAN_MODULE_RMC, + WLAN_MODULE_STATS, + WLAN_MODULE_NAN, + WLAN_MODULE_IBSS_PWRSAVE, + WLAN_MODULE_HIF_UART, /* 0x30 */ + WLAN_MODULE_LPI, + WLAN_MODULE_EXTSCAN, + WLAN_MODULE_UNIT_TEST, + WLAN_MODULE_MLME, + WLAN_MODULE_SUPPL, + WLAN_MODULE_ERE, + WLAN_MODULE_OCB, + WLAN_MODULE_RSSI_MONITOR, + WLAN_MODULE_WPM, + WLAN_MODULE_CSS, /* 0x3a */ + WLAN_MODULE_PPS, /* 0x3b */ + WLAN_MODULE_SCAN_CH_PREDICT, /* 0x3c */ + WLAN_MODULE_MAWC, + WLAN_MODULE_CMC_QMIC, /* 0x3e */ + WLAN_MODULE_EGAP, /* 0x3f */ + + WLAN_MODULE_ID_MAX, + WLAN_MODULE_ID_INVALID = WLAN_MODULE_ID_MAX, +} WLAN_MODULE_ID; + + +#endif /* _WLAN_MODULE_IDS_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_opts.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_opts.h new file mode 100644 index 000000000000..4fed4cdb7d67 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_opts.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WLAN_OPTS_H_ +#define _WLAN_OPTS_H_ + +/* ATH_DEBUG - + * Control whether debug features (printouts, assertions) are compiled + * into the driver. + */ +#ifndef ATH_DEBUG +#define ATH_DEBUG 1 /* default: include debug code */ +#endif + +#if ATH_DEBUG +#define DEBUG_VAR_DECL_INIT(_var,_type,_value) _type (_var)=_value +#else +#define DEBUG_VAR_DECL_INIT(_var,_type,_value) +#endif + +/* ATH_SUPPORT_WIRESHARK - + * Control whether code that adds a radiotap packet header for consumption + * by wireshark are compiled into the driver. + */ +#ifndef ATH_SUPPORT_WIRESHARK +#define ATH_SUPPORT_WIRESHARK 1 /* default: include radiotap/wireshark code */ +#endif + +#ifndef ATH_SUPPORT_ATHVAP_INFO +#define ATH_SUPPORT_ATHVAP_INFO 1 +#endif + +/* ATH_SUPPORT_IBSS - + * Control whether Adhoc support is compiled into the driver. + */ +#ifndef ATH_SUPPORT_IBSS +#define ATH_SUPPORT_IBSS 1 /* default: include radiotap/wireshark code */ +#endif + +/* ATH_SLOW_ANT_DIV - + * Control whether Slow Antenna Diversity support is compiled into the driver. + */ +#ifndef ATH_SLOW_ANT_DIV +#define ATH_SLOW_ANT_DIV 0 /* default: do not include Slow Antenna Diversity code */ +#endif + +#ifndef ATH_SUPPORT_CWM +#define ATH_SUPPORT_CWM 1 /* on unless explicitly disabled */ +#endif + +#ifndef ATH_SUPPORT_MULTIPLE_SCANS +#define ATH_SUPPORT_MULTIPLE_SCANS 0 /* default: do not include suport for multiple simultaneous scans, including Scan Scheduler code */ +#endif + +#ifndef ATH_BUILD_VISTA_ONLY +#define ATH_BUILD_VISTA_ONLY 0 /* default: build VISTA and WIN7 as the same binary */ +#endif + +#ifndef IEEE80211_DEBUG_REFCNT_SE +#define IEEE80211_DEBUG_REFCNT_SE 0 /*default: do not include scan_entry reference count debug info */ +#endif + +#ifndef ATH_OSPREY_UAPSDDEFERRED +#define ATH_OSPREY_UAPSDDEFERRED 0 /* default: handle Osprey UAPSD in ISR */ +#endif + +#ifndef ATH_SUPPORT_STATS_APONLY +#define ATH_SUPPORT_STATS_APONLY 0 /*default: update all stats*/ +#endif + +#ifndef ATH_RESET_SERIAL +#define ATH_RESET_SERIAL 0 /*default: do not run ath_reset always in passive_level */ +#endif + +#ifndef ATH_LOW_PRIORITY_CALIBRATE +#define ATH_LOW_PRIORITY_CALIBRATE 0 /*default: do not run ath_calibrate in workitem. */ +#endif + +#endif /* _WLAN_OPTS_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h new file mode 100644 index 000000000000..8989f03207e7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_TGT_DEF_CONFIG_H__ +#define __WLAN_TGT_DEF_CONFIG_H__ + +/* + * set of default target config , that can be over written by platform + */ + +/* + * default limit of 8 VAPs per device. + */ +/* Rome PRD support 3 vdevs */ +#define CFG_TGT_NUM_VDEV 3 + +/* + * We would need 1 AST entry per peer. Scale it by a factor of 2 to minimize hash collisions. + * TODO: This scaling factor would be taken care inside the WAL in the future. + */ +#define CFG_TGT_NUM_PEER_AST 2 + +/* # of WDS entries to support. + */ +#define CFG_TGT_WDS_ENTRIES 0 + +/* MAC DMA burst size. 0: 128B - default, 1: 256B, 2: 64B + */ +#define CFG_TGT_DEFAULT_DMA_BURST_SIZE 0 + +/* Fixed delimiters to be inserted after every MPDU + */ +#define CFG_TGT_DEFAULT_MAC_AGGR_DELIM 0 + +/* + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_AST_SKID_LIMIT 16 + +/* + * total number of peers per device. + */ +#define CFG_TGT_NUM_PEERS 14 + +/* + * In offload mode target supports features like WOW, chatter and other + * protocol offloads. In order to support them some functionalities like + * reorder buffering, PN checking need to be done in target. This determines + * maximum number of peers suported by target in offload mode + */ + +/* + * The current firmware implementation requires the number of offload peers + * should be (number of vdevs + 1). + + * The reason for this is the firmware clubbed the self peer and offload peer + * in the same pool. So if the firmware wanted to support n vdevs then the + * number of offload peer must be n+1 of which n buffers will be used for + * self peer and the remaining 1 is used for offload peer to support chatter + * mode for single STA. + + * Technically the macro should be 1 however the current firmware requires n+1. + + * TODO: This MACRO need to be modified in the future, if the firmware modified + * to allocate buffers for self peer and offload peer independently. + */ + +#define CFG_TGT_NUM_OFFLOAD_PEERS (CFG_TGT_NUM_VDEV+1) + +/* + * Number of reorder buffers used in offload mode + */ +#define CFG_TGT_NUM_OFFLOAD_REORDER_BUFFS 4 + +/* + * keys per peer node + */ +#define CFG_TGT_NUM_PEER_KEYS 2 +/* + * total number of data TX and RX TIDs + */ +#define CFG_TGT_NUM_TIDS (2 * (CFG_TGT_NUM_PEERS + CFG_TGT_NUM_VDEV + 2)) +/* + * set this to 0x7 (Peregrine = 3 chains). + * need to be set dynamically based on the HW capability. + */ +#define CFG_TGT_DEFAULT_TX_CHAIN_MASK 0x7 +/* + * set this to 0x7 (Peregrine = 3 chains). + * need to be set dynamically based on the HW capability. + */ +#define CFG_TGT_DEFAULT_RX_CHAIN_MASK 0x7 +/* 100 ms for video, best-effort, and background */ +#define CFG_TGT_RX_TIMEOUT_LO_PRI 100 +/* 40 ms for voice*/ +#define CFG_TGT_RX_TIMEOUT_HI_PRI 40 + +/* AR9888 unified is default in ethernet mode */ +#define CFG_TGT_RX_DECAP_MODE (0x2) +/* Decap to native Wifi header */ +#define CFG_TGT_RX_DECAP_MODE_NWIFI (0x1) + +/* maximum number of pending scan requests */ +#define CFG_TGT_DEFAULT_SCAN_MAX_REQS 0x4 + +/* maximum number of VDEV that could use BMISS offload */ +#define CFG_TGT_DEFAULT_BMISS_OFFLOAD_MAX_VDEV 0x2 + +/* maximum number of VDEV offload Roaming to support */ +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_VDEV 0x2 + +/* maximum number of AP profiles pushed to offload Roaming */ +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_PROFILES 0x8 + +/* maximum number of VDEV offload GTK to support */ +#define CFG_TGT_DEFAULT_GTK_OFFLOAD_MAX_VDEV 0x2 + +/* default: mcast->ucast disabled if ATH_SUPPORT_MCAST2UCAST not defined */ +#ifndef ATH_SUPPORT_MCAST2UCAST +#define CFG_TGT_DEFAULT_NUM_MCAST_GROUPS 0 +#define CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS 0 +#define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 0 /* disabled */ +#else +/* (for testing) small multicast group membership table enabled */ +#define CFG_TGT_DEFAULT_NUM_MCAST_GROUPS 4 +#define CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS 16 +#define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 2 +#endif + +#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 5 +/* + * Specify how much memory the target should allocate for a debug log of + * tx PPDU meta-information (how large the PPDU was, when it was sent, + * whether it was successful, etc.) + * The size of the log records is configurable, from a minimum of 28 bytes + * to a maximum of about 300 bytes. A typical configuration would result + * in each log record being about 124 bytes. + * Thus, 1KB of log space can hold about 30 small records, 3 large records, + * or about 8 typical-sized records. + */ +#define CFG_TGT_DEFAULT_TX_DBG_LOG_SIZE 1024 /* bytes */ + +/* target based fragment timeout and MPDU duplicate detection */ +#define CFG_TGT_DEFAULT_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 0 + +/* Default VoW configuration + */ +#define CFG_TGT_DEFAULT_VOW_CONFIG 0 + +/* + * total number of descriptors to use in the target + */ +#define CFG_TGT_NUM_MSDU_DESC (1024 + 32) + +/* + * Maximum number of frag table entries + */ +#define CFG_TGT_MAX_FRAG_TABLE_ENTRIES 10 + +/* + * Maximum number of VDEV that beacon tx offload will support + */ +#define CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV 2 + +/* + * number of vdevs that can support tdls + */ +#define CFG_TGT_NUM_TDLS_VDEVS 1 + +/* + * number of peers that each Tdls vdev can track + */ +#define CFG_TGT_NUM_TDLS_CONN_TABLE_ENTRIES 32 + +/* + * number of TDLS concurrent sleep STAs + */ +#define CFG_TGT_NUM_TDLS_CONC_SLEEP_STAS 1 + +/* + * number of TDLS concurrent buffer STAs + */ +#define CFG_TGT_NUM_TDLS_CONC_BUFFER_STAS 1 + +/* + * ht enable highest MCS by default + */ +#define CFG_TGT_DEFAULT_GTX_HT_MASK 0x8080 +/* + * vht enable highest MCS by default + */ +#define CFG_TGT_DEFAULT_GTX_VHT_MASK 0x80200 +/* + * resv for furture use, bit 30 is used for fix tpc, bit0-3 for Power save balance + */ +#define CFG_TGT_DEFAULT_GTX_USR_CFG 0xa +/* + * threshold to enable GTX + */ +#define CFG_TGT_DEFAULT_GTX_PER_THRESHOLD 3 +/* + * margin to move back when per > margin + threshold + */ +#define CFG_TGT_DEFAULT_GTX_PER_MARGIN 2 +/* + * step for every move + */ +#define CFG_TGT_DEFAULT_GTX_TPC_STEP 1 +/* + * lowest TPC + */ +#define CFG_TGT_DEFAULT_GTX_TPC_MIN 0 +/* + * enable all BW 20/40/80/160 + */ +#define CFG_TGT_DEFAULT_GTX_BW_MASK 0xf + +/* + * number of vdevs that can support OCB + */ +#define CFG_TGT_NUM_OCB_VDEVS 1 + +/* + * maximum number of channels that can do OCB + */ +#define CFG_TGT_NUM_OCB_CHANNELS 2 + +/* + * maximum number of channels in an OCB schedule + */ +#define CFG_TGT_NUM_OCB_SCHEDULES 2 + +#endif /*__WLAN_TGT_DEF_CONFIG_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h new file mode 100644 index 000000000000..f9e9654643c4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifndef __WLAN_TGT_DEF_CONFIG_H__ +#define __WLAN_TGT_DEF_CONFIG_H__ + +/* + * TODO: please help to consider if we need a seperate config file from LL case. + */ + +/* + * set of default target config , that can be over written by platform + */ + +#ifdef QCA_SUPPORT_INTEGRATED_SOC +#define CFG_TGT_NUM_VDEV 3 /*STA, P2P device, P2P GO/Cli*/ +#else +/* + * default limit of VAPs per device. + */ +#define CFG_TGT_NUM_VDEV 3 +#endif +/* + * We would need 1 AST entry per peer. Scale it by a factor of 2 to minimize + * hash collisions. + * TODO: This scaling factor would be taken care inside the WAL in the future. + */ +#define CFG_TGT_NUM_PEER_AST 2 + +/* # of WDS entries to support. + */ +#define CFG_TGT_WDS_ENTRIES 0 + +/* MAC DMA burst size. 0: 128B - default, 1: 256B, 2: 64B + */ +#define CFG_TGT_DEFAULT_DMA_BURST_SIZE 0 + +/* Fixed delimiters to be inserted after every MPDU + */ +#define CFG_TGT_DEFAULT_MAC_AGGR_DELIM 0 + +/* + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_AST_SKID_LIMIT 6 +/* + * total number of peers per device. + * currently set to 8 to bring up IP3.9 for memory size problem + */ +#define CFG_TGT_NUM_PEERS 8 +/* + * max number of peers per device. + */ +#define CFG_TGT_NUM_PEERS_MAX 8 +/* + * In offload mode target supports features like WOW, chatter and other + * protocol offloads. In order to support them some functionalities like + * reorder buffering, PN checking need to be done in target. This determines + * maximum number of peers suported by target in offload mode + */ +#define CFG_TGT_NUM_OFFLOAD_PEERS 0 +/* + * Number of reorder buffers used in offload mode + */ +#define CFG_TGT_NUM_OFFLOAD_REORDER_BUFFS 0 +/* + * keys per peer node + */ +#define CFG_TGT_NUM_PEER_KEYS 2 +/* + * total number of TX/RX data TIDs + */ +#define CFG_TGT_NUM_TIDS (2 * (CFG_TGT_NUM_PEERS + CFG_TGT_NUM_VDEV)) +/* + * max number of Tx TIDS + */ +#define CFG_TGT_NUM_TIDS_MAX (2 * (CFG_TGT_NUM_PEERS_MAX + CFG_TGT_NUM_VDEV)) +/* + * number of multicast keys. + */ +#define CFG_TGT_NUM_MCAST_KEYS 8 +/* + * A value of 3 would probably suffice - one for the control stack, one for + * the data stack, and one for debugging. + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_NUM_PDEV_HANDLERS 8 +/* + * A value of 3 would probably suffice - one for the control stack, one for + * the data stack, and one for debugging. + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_NUM_VDEV_HANDLERS 4 +/* + * set this to 8: + * one for WAL interals (connection pause) + * one for the control stack, + * one for the data stack + * and one for debugging + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_NUM_HANDLERS 14 +/* + * set this to 3: one for the control stack, one for + * the data stack, and one for debugging. + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_NUM_PEER_HANDLERS 32 +/* + * set this to 0x7 (Peregrine = 3 chains). + * need to be set dynamically based on the HW capability. + * this is rome + */ +#define CFG_TGT_DEFAULT_TX_CHAIN_MASK 0x3 +/* + * set this to 0x7 (Peregrine = 3 chains). + * need to be set dynamically based on the HW capability. + * this is rome + */ +#define CFG_TGT_DEFAULT_RX_CHAIN_MASK 0x3 +/* 100 ms for video, best-effort, and background */ +#define CFG_TGT_RX_TIMEOUT_LO_PRI 100 +/* 40 ms for voice*/ +#define CFG_TGT_RX_TIMEOUT_HI_PRI 40 + +/* AR9888 unified is default in ethernet mode */ +#define CFG_TGT_RX_DECAP_MODE (0x2) +/* Decap to native Wifi header */ +#define CFG_TGT_RX_DECAP_MODE_NWIFI (0x1) + +/* maximum number of pending scan requests */ +#define CFG_TGT_DEFAULT_SCAN_MAX_REQS 0x4 + +/* maximum number of scan event handlers */ +#define CFG_TGT_DEFAULT_SCAN_MAX_HANDLERS 0x4 + +/* maximum number of VDEV that could use BMISS offload */ +#define CFG_TGT_DEFAULT_BMISS_OFFLOAD_MAX_VDEV 0x2 + +/* maximum number of VDEV offload Roaming to support */ +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_VDEV 0x2 + +/* maximum number of AP profiles pushed to offload Roaming */ +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_PROFILES 0x8 + +/* maximum number of VDEV offload GTK to support */ +#define CFG_TGT_DEFAULT_GTK_OFFLOAD_MAX_VDEV 0x2 +/* default: mcast->ucast disabled */ +#if 1 +#define CFG_TGT_DEFAULT_NUM_MCAST_GROUPS 0 +#define CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS 0 +#define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 0 /* disabled */ +#else +/* (for testing) small multicast group membership table enabled */ +#define CFG_TGT_DEFAULT_NUM_MCAST_GROUPS 4 +#define CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS 16 +#define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 1 +#endif + +/* + * Specify how much memory the target should allocate for a debug log of + * tx PPDU meta-information (how large the PPDU was, when it was sent, + * whether it was successful, etc.) + * The size of the log records is configurable, from a minimum of 28 bytes + * to a maximum of about 300 bytes. A typical configuration would result + * in each log record being about 124 bytes. + * Thus, 1KB of log space can hold about 30 small records, 3 large records, + * or about 8 typical-sized records. + */ +#define CFG_TGT_DEFAULT_TX_DBG_LOG_SIZE 1024 /* bytes */ + +/* target based fragment timeout and MPDU duplicate detection */ +#define CFG_TGT_DEFAULT_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 0 +/* Default VoW configuration + */ +#define CFG_TGT_DEFAULT_VOW_CONFIG 0 + +/* + * total number of descriptors to use in the target + */ +#ifndef HIF_SDIO +#define CFG_TGT_NUM_MSDU_DESC (32) +#else +#define CFG_TGT_NUM_MSDU_DESC (0) +#endif +/* + * Maximum number of frag table entries + */ +#define CFG_TGT_MAX_FRAG_TABLE_ENTRIES 2 + +/* + * number of vdevs that can support tdls + */ +#define CFG_TGT_NUM_TDLS_VDEVS 1 + +/* + * number of peers that each Tdls vdev can track + */ +#define CFG_TGT_NUM_TDLS_CONN_TABLE_ENTRIES 32 +/* + * number of TDLS concurrent sleep STAs + */ +#define CFG_TGT_NUM_TDLS_CONC_SLEEP_STAS 1 + +/* + * number of TDLS concurrent buffer STAs + */ +#define CFG_TGT_NUM_TDLS_CONC_BUFFER_STAS 1 + +#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 5 +/* + * Maximum number of VDEV that beacon tx offload will support + */ +#ifdef HIF_SDIO +#define CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV 2 +#else +#define CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV 1 +#endif + +/* + * ht enable highest MCS by default + */ +#define CFG_TGT_DEFAULT_GTX_HT_MASK 0x8080 +/* + * vht enable highest MCS by default + */ +#define CFG_TGT_DEFAULT_GTX_VHT_MASK 0x80200 +/* + * resv for furture use, bit 30 is used for fix tpc, bit0-3 for Power save + * balance + */ +#define CFG_TGT_DEFAULT_GTX_USR_CFG 0xa +/* + * threshold to enable GTX + */ +#define CFG_TGT_DEFAULT_GTX_PER_THRESHOLD 3 +/* + * margin to move back when per > margin + threshold + */ +#define CFG_TGT_DEFAULT_GTX_PER_MARGIN 2 +/* + * step for every move + */ +#define CFG_TGT_DEFAULT_GTX_TPC_STEP 1 +/* + * lowest TPC + */ +#define CFG_TGT_DEFAULT_GTX_TPC_MIN 0 +/* + * enable all BW 20/40/80/160 + */ +#define CFG_TGT_DEFAULT_GTX_BW_MASK 0xf + +/* + * number of vdevs that can support OCB + */ +#define CFG_TGT_NUM_OCB_VDEVS 1 + +/* + * maximum number of channels that can do OCB + */ +#define CFG_TGT_NUM_OCB_CHANNELS 2 + +/* + * maximum number of channels in an OCB schedule + */ +#define CFG_TGT_NUM_OCB_SCHEDULES 2 + +#endif /*__WLAN_TGT_DEF_CONFIG_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_types.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_types.h new file mode 100644 index 000000000000..c1bc7166b4aa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_types.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + * + * @file: wlan_types.h + * + * @brief: This file defines the common types for wlan + * + * @author: Xiaochang Duan + * + * + *=========================================================================*/ + +#ifndef __WLAN_TYPES_H__ +#define __WLAN_TYPES_H__ + +/*------------------------------------------------------------------------- + Include Files +-------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +typedef uint32_t uint32; /* Unsigned 32 bit value */ + +typedef uint16_t uint16; /* Unsigned 16 bit value */ + +typedef uint8_t uint8; /* Unsigned 8 bit value */ + +typedef int32_t int32; /* Signed 32 bit value */ + +typedef int16_t int16; /* Signed 16 bit value */ + +typedef int8_t int8; /* Signed 8 bit value */ + +typedef int64_t int64; /* Signed 64 bit value */ + +typedef uint64_t uint64; /* Unsigned 64 bit value */ + +typedef uint8_t byte; /* byte type */ + +typedef uint8_t boolean; /* Boolean Type */ + +#endif //__WLAN_TYPES_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_api.h new file mode 100644 index 000000000000..4b748c04400d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_api.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wma.c + \brief Implementation of WMA + + ========================================================================*/ +/**========================================================================= + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- ----------------------------------------- + 12/03/2013 Ganesh Implementation of wma function for initialization + Kondabattini + ==========================================================================*/ +#ifndef WMA_API_H +#define WMA_API_H + +#include "osdep.h" +#include "vos_mq.h" +#include "aniGlobal.h" +#include "a_types.h" +#include "wmi_unified.h" +#include "wlan_hdd_tgt_cfg.h" +#ifdef NOT_YET +#include "htc_api.h" +#endif +#include "limGlobal.h" + +typedef v_VOID_t* WMA_HANDLE; + +typedef enum { + /* Set ampdu size */ + GEN_VDEV_PARAM_AMPDU = 0x1, + /* Set amsdu size */ + GEN_VDEV_PARAM_AMSDU, + GEN_PARAM_DUMP_AGC_START, + GEN_PARAM_DUMP_AGC, + GEN_PARAM_DUMP_CHANINFO_START, + GEN_PARAM_DUMP_CHANINFO, + GEN_PARAM_DUMP_WATCHDOG, + GEN_PARAM_CRASH_INJECT, +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + GEN_PARAM_DUMP_PCIE_ACCESS_LOG, +#endif + GEN_PARAM_MODULATED_DTIM, + GEN_PARAM_CAPTURE_TSF, + GEN_PARAM_RESET_TSF_GPIO, +} GEN_PARAM; + +#define VDEV_CMD 1 +#define PDEV_CMD 2 +#define GEN_CMD 3 +#define DBG_CMD 4 +#define PPS_CMD 5 +#define QPOWER_CMD 6 +#define GTX_CMD 7 + +VOS_STATUS wma_pre_start(v_VOID_t *vos_context); + +VOS_STATUS wma_mc_process_msg( v_VOID_t *vos_context, vos_msg_t *msg ); + +VOS_STATUS wma_start(v_VOID_t *vos_context); + +VOS_STATUS wma_stop(v_VOID_t *vos_context, tANI_U8 reason); + +VOS_STATUS wma_close(v_VOID_t *vos_context); + +VOS_STATUS wma_wmi_service_close(v_VOID_t *vos_context); + +VOS_STATUS wma_wmi_work_close(v_VOID_t *vos_context); + +v_VOID_t wma_rx_ready_event(WMA_HANDLE handle, v_VOID_t *ev); + +v_VOID_t wma_rx_service_ready_event(WMA_HANDLE handle, + v_VOID_t *ev); + +v_VOID_t wma_setneedshutdown(v_VOID_t *vos_context); + +v_BOOL_t wma_needshutdown(v_VOID_t *vos_context); + +VOS_STATUS wma_wait_for_ready_event(WMA_HANDLE handle); + +tANI_U8 wma_map_channel(tANI_U8 mapChannel); + +int wma_cli_get_command(void *wmapvosContext, int vdev_id, + int param_id, int vpdev); +eHalStatus wma_set_htconfig(tANI_U8 vdev_id, tANI_U16 ht_capab, int value); +eHalStatus WMA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, + tAniBool sendRegHint); + +VOS_STATUS WMA_GetWcnssSoftwareVersion(v_PVOID_t pvosGCtx, tANI_U8 *pVersion, + tANI_U32 versionBufferSize); +int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); +void wma_target_suspend_acknowledge(void *context); +int wma_resume_target(WMA_HANDLE handle, int); +int wma_disable_wow_in_fw(WMA_HANDLE handle, int); +int wma_is_wow_mode_selected(WMA_HANDLE handle); +int wma_enable_wow_in_fw(WMA_HANDLE handle, int); +bool wma_check_scan_in_progress(WMA_HANDLE handle); +#ifdef FEATURE_RUNTIME_PM +int wma_runtime_suspend_req(WMA_HANDLE handle); +int wma_runtime_resume_req(WMA_HANDLE handle); +#endif + +#ifdef FEATURE_WLAN_D0WOW +int wma_get_client_count(WMA_HANDLE handle); +#endif +int wma_set_peer_param(void *wma_ctx, u_int8_t *peer_addr, u_int32_t param_id, + u_int32_t param_value, u_int32_t vdev_id); +#ifdef NOT_YET +VOS_STATUS wma_update_channel_list(WMA_HANDLE handle, void *scan_chan_info); +#endif + +u_int8_t *wma_get_vdev_address_by_vdev_id(u_int8_t vdev_id); + +void *wma_get_beacon_buffer_by_vdev_id(u_int8_t vdev_id, + u_int32_t *buffer_size); + +int process_wma_set_command(int sessid, int paramid, + int sval, int vpdev); +tANI_U8 wma_getFwWlanFeatCaps(tANI_U8 featEnumValue); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_dfs_interface.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_dfs_interface.h new file mode 100644 index 000000000000..3aad4665b0d5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wma_dfs_interface.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "ath_dfs_structs.h" +#include "_ieee80211_common.h" +#include +#define IEEE80211_CHAN_MAX 255 + +/* channel attributes */ + +/* Turbo channel */ +#define IEEE80211_CHAN_TURBO 0x00000010 +/* CCK channel */ +#define IEEE80211_CHAN_CCK 0x00000020 +/* OFDM channel */ +#define IEEE80211_CHAN_OFDM 0x00000040 +/* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_2GHZ 0x00000080 +/* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_5GHZ 0x00000100 +/* Only passive scan allowed */ +#define IEEE80211_CHAN_PASSIVE 0x00000200 +/* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_DYN 0x00000400 +/* GFSK channel (FHSS PHY) */ +#define IEEE80211_CHAN_GFSK 0x00000800 +/* Radar found on channel */ +#define IEEE80211_CHAN_RADAR 0x00001000 +/* 11a static turbo channel only */ +#define IEEE80211_CHAN_STURBO 0x00002000 +/* Half rate channel */ +#define IEEE80211_CHAN_HALF 0x00004000 +/* Quarter rate channel */ +#define IEEE80211_CHAN_QUARTER 0x00008000 +/* HT 20 channel */ +#define IEEE80211_CHAN_HT20 0x00010000 +/* HT 40 with extension channel above */ +#define IEEE80211_CHAN_HT40PLUS 0x00020000 +/* HT 40 with extension channel below */ +#define IEEE80211_CHAN_HT40MINUS 0x00040000 +/* HT 40 Intolerant */ +#define IEEE80211_CHAN_HT40INTOL 0x00080000 +/* VHT 20 channel */ +#define IEEE80211_CHAN_VHT20 0x00100000 +/* VHT 40 with extension channel above */ +#define IEEE80211_CHAN_VHT40PLUS 0x00200000 +/* VHT 40 with extension channel below */ +#define IEEE80211_CHAN_VHT40MINUS 0x00400000 +/* VHT 80 channel */ +#define IEEE80211_CHAN_VHT80 0x00800000 + +/* token for ``any channel'' */ +#define IEEE80211_CHAN_ANY (-1) +#define IEEE80211_CHAN_ANYC \ + ((struct ieee80211_channel *) IEEE80211_CHAN_ANY) + + +#define IEEE80211_IS_CHAN_11N_HT40MINUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) != 0) +#define IEEE80211_IS_CHAN_11N_HT40PLUS(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) != 0) +#define IEEE80211_CHAN_11AC_VHT80 \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT80) + + +#define IEEE80211_IS_CHAN_11AC_VHT80(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == \ + IEEE80211_CHAN_11AC_VHT80) +#define CHANNEL_108G \ + (IEEE80211_CHAN_2GHZ|IEEE80211_CHAN_OFDM|IEEE80211_CHAN_TURBO) + +/* + * Software use: channel interference + * used for as AR as well as RADAR + * interference detection +*/ +#define CHANNEL_INTERFERENCE 0x01 +/* In case of VHT160, we can have 8 20Mhz channels */ +#define IEE80211_MAX_20M_SUB_CH 8 + +struct ieee80211_channel +{ + u_int32_t ic_freq; /* setting in Mhz */ + u_int32_t ic_flags; /* see below */ + u_int8_t ic_flagext; /* see below */ + u_int8_t ic_ieee; /* IEEE channel number */ + + /* maximum regulatory tx power in dBm */ + int8_t ic_maxregpower; + + int8_t ic_maxpower; /* maximum tx power in dBm */ + int8_t ic_minpower; /* minimum tx power in dBm */ + u_int8_t ic_regClassId; /* regClassId of this channel */ + u_int8_t ic_antennamax; /* antenna gain max from regulatory */ + u_int32_t ic_vhtop_ch_freq_seg1; /* Channel Center frequency */ + + /* Channel Center frequency applicable*/ + u_int32_t ic_vhtop_ch_freq_seg2; + + /* + * spectral separation between pri channel + * and the center frequency in MHz + */ + int ic_pri_freq_center_freq_mhz_separation; +}; + +struct ieee80211_channel_list +{ + int cl_nchans; + struct ieee80211_channel *cl_channels[IEE80211_MAX_20M_SUB_CH]; +}; + +struct ieee80211_dfs_state +{ + int nol_event[IEEE80211_CHAN_MAX]; + os_timer_t nol_timer; /* NOL list processing */ + os_timer_t cac_timer; /* CAC timer */ + int cureps; /* current events/second */ + const struct ieee80211_channel *lastchan; /* chan w/ last radar event */ + struct ieee80211_channel *newchan; /* chan selected next */ + /* overridden cac timeout */ + int cac_timeout_override; + u_int8_t enable:1, + cac_timer_running:1, + ignore_dfs:1, + ignore_cac:1; +}; + +typedef struct ieee80211com +{ + void (*ic_start_csa)(struct ieee80211com *ic,u_int8_t ieeeChan); + void (*ic_get_ext_chan_info)(struct ieee80211com *ic, + struct ieee80211_channel_list *chan); + enum ieee80211_opmode ic_opmode; /* operation mode */ + struct ieee80211_channel *(*ic_find_channel)(struct ieee80211com *ic, + int freq, u_int32_t flags); + u_int64_t (*ic_get_TSF64)(struct ieee80211com *ic); + unsigned int (*ic_ieee2mhz)(u_int chan, u_int flags); + struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1]; + /* Number of Channels according to the Regulatory domain channels */ + int ic_nchans; + struct ieee80211_channel *ic_curchan; /* current channel */ + u_int8_t ic_isdfsregdomain; /* operating in DFS domain ? */ + int (*ic_get_dfsdomain)(struct ieee80211com *); + u_int16_t (*ic_dfs_usenol)(struct ieee80211com *ic); + u_int16_t (*ic_dfs_isdfsregdomain)(struct ieee80211com *ic); + int (*ic_dfs_attached)(struct ieee80211com *ic); + void *ic_dfs; + struct ieee80211_dfs_state ic_dfs_state; + int (*ic_dfs_attach)(struct ieee80211com *ic, + void *pCap, void *radar_info); + int (*ic_dfs_detach)(struct ieee80211com *ic); + int (*ic_dfs_enable)(struct ieee80211com *ic, int *is_fastclk, void *); + int (*ic_dfs_disable)(struct ieee80211com *ic); + int (*ic_get_ext_busy)(struct ieee80211com *ic); + int (*ic_get_mib_cycle_counts_pct)(struct ieee80211com *ic, + u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt); + int (*ic_dfs_get_thresholds)(struct ieee80211com *ic,void *pe); + + int (*ic_dfs_debug)(struct ieee80211com *ic, int type, void *data); + /* + * Update the channel list with the current set of DFS + * NOL entries. + * + * + 'cmd' indicates what to do; for now it should just + * be DFS_NOL_CLIST_CMD_UPDATE which will update all + * channels, given the _entire_ NOL. (Rather than + * the earlier behaviour with clist_update, which + * was to either add or remove a set of channel + * entries.) + */ + void (*ic_dfs_clist_update)(struct ieee80211com *ic, int cmd, + struct dfs_nol_chan_entry *, int nentries); + void (*ic_dfs_notify_radar)(struct ieee80211com *ic, + struct ieee80211_channel *chan); + void (*ic_dfs_unmark_radar)(struct ieee80211com *ic, + struct ieee80211_channel *chan); + int (*ic_dfs_control)(struct ieee80211com *ic, + u_int id, void *indata, u_int32_t insize, + void *outdata, u_int32_t *outsize); + HAL_DFS_DOMAIN current_dfs_regdomain; + u_int8_t vdev_id; + u_int8_t last_radar_found_chan; + int32_t dfs_pri_multiplier; + adf_os_spinlock_t chan_lock; + bool disable_phy_err_processing; +} IEEE80211COM, *PIEEE80211COM; + +/* + * Convert channel to frequency value. + */ +static INLINE u_int +ieee80211_chan2freq(struct ieee80211com *ic, + const struct ieee80211_channel *c) +{ + if (c == NULL) + { + return 0; + } + return (c == IEEE80211_CHAN_ANYC ? IEEE80211_CHAN_ANY : c->ic_freq); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi.h new file mode 100644 index 000000000000..9cb7e30c351c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2004-2010 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010, 2013 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +/* + * This file contains the definitions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all the + * commands and events. Commands are messages from the host to the WM. + * Events and Replies are messages from the WM to the host. + * + * Ownership of correctness in regards to commands + * belongs to the host driver and the WMI is not required to validate + * parameters for value, proper range, or any other checking. + * + */ + +#ifndef _WMI_H_ +#define _WMI_H_ + +#include "wlan_defs.h" +#include "wmix.h" +#include "wmi_unified.h" +#include "wmi_tlv_helper.h" +#include "wmi_tlv_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HTC_PROTOCOL_VERSION 0x0002 + +#define WMI_PROTOCOL_VERSION 0x0002 + +#define WMI_MODE_MAX 8 +#define WMI_MAX_RATE_MASK 6 + + +PREPACK struct host_app_area_s { + A_UINT32 wmi_protocol_ver; +} POSTPACK; + + +#undef MS +#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) +#undef SM +#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) +#undef WO +#define WO(_f) ((_f##_OFFSET) >> 2) + +#undef GET_FIELD +#define GET_FIELD(_addr, _f) MS(*((A_UINT32 *)(_addr) + WO(_f)), _f) +#undef SET_FIELD +#define SET_FIELD(_addr, _f, _val) \ + (*((A_UINT32 *)(_addr) + WO(_f)) = \ + (*((A_UINT32 *)(_addr) + WO(_f)) & ~_f##_MASK) | SM(_val, _f)) + +#define WMI_GET_FIELD(_msg_buf, _msg_type, _f) \ + GET_FIELD(_msg_buf, _msg_type ## _ ## _f) + +#define WMI_SET_FIELD(_msg_buf, _msg_type, _f, _val) \ + SET_FIELD(_msg_buf, _msg_type ## _ ## _f, _val) + +#define WMI_EP_APASS 0x0 +#define WMI_EP_LPASS 0x1 +#define WMI_EP_SENSOR 0x2 + +/* + * Control Path + */ +typedef PREPACK struct { + A_UINT32 commandId : 24, + reserved : 2, /* used for WMI endpoint ID */ + plt_priv : 6; /* platform private */ +} POSTPACK WMI_CMD_HDR; /* used for commands and events */ + +#define WMI_CMD_HDR_COMMANDID_LSB 0 +#define WMI_CMD_HDR_COMMANDID_MASK 0x00ffffff +#define WMI_CMD_HDR_COMMANDID_OFFSET 0x00000000 +#define WMI_CMD_HDR_WMI_ENDPOINTID_MASK 0x03000000 +#define WMI_CMD_HDR_WMI_ENDPOINTID_OFFSET 24 +#define WMI_CMD_HDR_PLT_PRIV_LSB 24 +#define WMI_CMD_HDR_PLT_PRIV_MASK 0xff000000 +#define WMI_CMD_HDR_PLT_PRIV_OFFSET 0x00000000 + +/* + * List of Commnands + */ +typedef enum { + WMI_EXTENSION_CMDID, //used in wmi_svc.c /* Non-wireless extensions */ + WMI_IGNORE_CMDID, //used in wlan_wmi.c +} WMI_COMMAND_ID; + + +typedef enum { + NONE_CRYPT = 0x01, + WEP_CRYPT = 0x02, + TKIP_CRYPT = 0x04, + AES_CRYPT = 0x08, +#ifdef WAPI_ENABLE + WAPI_CRYPT = 0x10, +#endif /*WAPI_ENABLE*/ +} CRYPTO_TYPE; + +#define WMI_MAX_SSID_LEN 32 + +/* + * WMI_SET_PMK_CMDID + */ +#define WMI_PMK_LEN 32 + + +/* + * WMI_ADD_CIPHER_KEY_CMDID + */ +typedef enum { + PAIRWISE_USAGE = 0x00, + GROUP_USAGE = 0x01, + TX_USAGE = 0x02, /* default Tx Key - Static WEP only */ +} KEY_USAGE; + + +/* + * List of Events (target to host) + */ +typedef enum { + WMI_EXTENSION_EVENTID, //wmi_profhook.c and umac_wmi_events.c +} WMI_EVENT_ID; + +typedef enum { + WMI_11A_CAPABILITY = 1, + WMI_11G_CAPABILITY = 2, + WMI_11AG_CAPABILITY = 3, + WMI_11NA_CAPABILITY = 4, + WMI_11NG_CAPABILITY = 5, + WMI_11NAG_CAPABILITY = 6, + WMI_11AC_CAPABILITY = 7, + // END CAPABILITY + WMI_11N_CAPABILITY_OFFSET = (WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY), +} WMI_PHY_CAPABILITY; + + +/* Deprectated, need clean up */ +#define WMI_MAX_RX_META_SZ (12) + +typedef PREPACK struct { + A_INT8 rssi; + A_UINT8 info; /* usage of 'info' field(8-bit): + * b1:b0 - WMI_MSG_TYPE + * b4:b3:b2 - UP(tid) + * b5 - Used in AP mode. More-data in tx dir, PS in rx. + * b7:b6 - Dot3 header(0), + * Dot11 Header(1), + * ACL data(2) + */ + + A_UINT16 info2; /* usage of 'info2' field(16-bit): + * b11:b0 - seq_no + * b12 - A-MSDU? + * b15:b13 - META_DATA_VERSION 0 - 7 + */ + A_UINT16 info3; /* b3:b2:b1:b0 - device id + * b4 - Used in AP mode. uAPSD trigger in rx, EOSP in tx + * b7:b5 - unused? + * b15:b8 - pad before data start(irrespective of meta version) + */ +} POSTPACK WMI_DATA_HDR; + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_services.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_services.h new file mode 100644 index 000000000000..636330a827f7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_services.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * This file defines WMI services bitmap and the set of WMI services . + * defines macrso to set/clear/get different service bits from the bitmap. + * the service bitmap is sent up to the host via WMI_READY command. + * + */ + +#ifndef _WMI_SERVICES_H_ +#define _WMI_SERVICES_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef enum { + WMI_SERVICE_BEACON_OFFLOAD=0, /* beacon offload */ + WMI_SERVICE_SCAN_OFFLOAD, /* scan offload */ + WMI_SERVICE_ROAM_SCAN_OFFLOAD, /* roam scan offload */ + WMI_SERVICE_BCN_MISS_OFFLOAD, /* beacon miss offload */ + WMI_SERVICE_STA_PWRSAVE, /* fake sleep + basic power save */ + WMI_SERVICE_STA_ADVANCED_PWRSAVE, /* uapsd, pspoll, force sleep */ + WMI_SERVICE_AP_UAPSD, /* uapsd on AP */ + WMI_SERVICE_AP_DFS, /* DFS on AP */ + WMI_SERVICE_11AC, /* supports 11ac */ + WMI_SERVICE_BLOCKACK, /* Supports triggering ADDBA/DELBA from host*/ + WMI_SERVICE_PHYERR, /* PHY error */ + WMI_SERVICE_BCN_FILTER, /* Beacon filter support */ + WMI_SERVICE_RTT, /* RTT (round trip time) support */ + WMI_SERVICE_WOW, /* WOW Support */ + WMI_SERVICE_RATECTRL_CACHE, /* Rate-control caching */ + WMI_SERVICE_IRAM_TIDS, /* TIDs in IRAM */ + WMI_SERVICE_ARPNS_OFFLOAD, /* ARP NS Offload support for STA vdev */ + WMI_SERVICE_NLO, /* Network list offload service */ + WMI_SERVICE_GTK_OFFLOAD, /* GTK offload */ + WMI_SERVICE_SCAN_SCH, /* Scan Scheduler Service */ + WMI_SERVICE_CSA_OFFLOAD, /* CSA offload service */ + WMI_SERVICE_CHATTER, /* Chatter service */ + WMI_SERVICE_COEX_FREQAVOID, /* FW report freq range to avoid */ + WMI_SERVICE_PACKET_POWER_SAVE, /* packet power save service */ + WMI_SERVICE_FORCE_FW_HANG, /* Service to test the firmware recovery mechanism */ + WMI_SERVICE_GPIO, /* GPIO service */ + WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, /* Modulated DTIM support */ + WMI_STA_UAPSD_BASIC_AUTO_TRIG, /* Basic version of station UAPSD AC Trigger Generation Method with + * variable tigger periods (service, delay, and suspend intervals) */ + WMI_STA_UAPSD_VAR_AUTO_TRIG, /* Station UAPSD AC Trigger Generation Method with variable + * trigger periods (service, delay, and suspend intervals) */ + WMI_SERVICE_STA_KEEP_ALIVE, /* Serivce to support the STA KEEP ALIVE mechanism */ + WMI_SERVICE_TX_ENCAP, /* Packet type for TX encapsulation */ + WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC, /* detect out-of-sync sleeping stations */ + WMI_SERVICE_EARLY_RX, /* adaptive early-rx feature */ + WMI_SERVICE_STA_SMPS, /* STA MIMO-PS */ + WMI_SERVICE_FWTEST, /* Firmware test service */ + WMI_SERVICE_STA_WMMAC, /* STA WMMAC */ + WMI_SERVICE_TDLS, /* TDLS support */ + WMI_SERVICE_BURST, /* SIFS spaced burst support */ + WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE, /* Dynamic beaocn interval change for SAP/P2p GO in MCC scenario */ + WMI_SERVICE_ADAPTIVE_OCS, /* Service to support adaptive off-channel scheduler */ + WMI_SERVICE_BA_SSN_SUPPORT, /* target will provide Sequence number for the peer/tid combo */ + WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE, + WMI_SERVICE_WLAN_HB, /* wlan HB service */ + WMI_SERVICE_LTE_ANT_SHARE_SUPPORT, /* support LTE/WLAN antenna sharing */ + WMI_SERVICE_BATCH_SCAN, /*Service to support batch scan*/ + WMI_SERVICE_QPOWER, /* QPower service */ + WMI_SERVICE_PLMREQ, + WMI_SERVICE_THERMAL_MGMT, + WMI_SERVICE_RMC, /* RMC support */ + WMI_SERVICE_MHF_OFFLOAD, /* multi-hop forwarding offload */ + WMI_SERVICE_COEX_SAR, /* target support SAR tx limit from WMI_PDEV_PARAM_TXPOWER_LIMITxG */ + WMI_SERVICE_BCN_TXRATE_OVERRIDE, /* Will support the bcn/prb rsp rate override */ + WMI_SERVICE_NAN, /* Neighbor Awareness Network */ + WMI_SERVICE_L1SS_STAT, /* L1SS statistics counter report */ + WMI_SERVICE_ESTIMATE_LINKSPEED, /* Linkspeed Estimation per peer */ + WMI_SERVICE_OBSS_SCAN, /* Service to support OBSS scan */ + WMI_SERVICE_TDLS_OFFCHAN, /* TDLS off channel support */ + WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, /* TDLS UAPSD Buffer STA support */ + WMI_SERVICE_TDLS_UAPSD_SLEEP_STA, /* TDLS UAPSD Sleep STA support */ + WMI_SERVICE_IBSS_PWRSAVE, /* IBSS power save support */ + WMI_SERVICE_LPASS, /*Service to support LPASS*/ + WMI_SERVICE_EXTSCAN, /* Extended Scans */ + WMI_SERVICE_D0WOW, /* D0-WOW Support */ + WMI_SERVICE_HSOFFLOAD, /* Hotspot offload feature Support */ + WMI_SERVICE_ROAM_HO_OFFLOAD, /* roam handover offload */ + WMI_SERVICE_RX_FULL_REORDER, /* target-based Rx full reorder */ + WMI_SERVICE_DHCP_OFFLOAD, /* DHCP offload support */ + WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT, /* STA RX DATA offload to IPA support */ + WMI_SERVICE_MDNS_OFFLOAD, /* mDNS responder offload support */ + WMI_SERVICE_SAP_AUTH_OFFLOAD, /* softap auth offload */ + WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT, /* Dual Band Simultaneous support */ + WMI_SERVICE_OCB, /* OCB mode support */ + WMI_SERVICE_AP_ARPNS_OFFLOAD, /* arp offload support for ap mode vdev */ + WMI_SERVICE_PER_BAND_CHAINMASK_SUPPORT, /* Per band chainmask support */ + WMI_SERVICE_PACKET_FILTER_OFFLOAD, /* Per vdev packet filters */ + WMI_SERVICE_MGMT_TX_HTT, /* Mgmt Tx via HTT interface */ + WMI_SERVICE_MGMT_TX_WMI, /* Mgmt Tx via WMI interface */ + WMI_SERVICE_EXT_MSG, /* WMI_SERVICE_READY_EXT msg follows */ + WMI_SERVICE_MAWC, /* Motion Aided WiFi Connectivity (MAWC)*/ + WMI_SERVICE_PEER_ASSOC_CONF, /* target will send ASSOC_CONF after ASSOC_CMD is processed */ + WMI_SERVICE_EGAP, /* enhanced green ap support */ + WMI_SERVICE_STA_PMF_OFFLOAD, /* FW supports 11W PMF Offload for STA */ + WMI_SERVICE_UNIFIED_WOW_CAPABILITY, /* FW supports unified D0 and D3 wow */ + + WMI_MAX_SERVICE=128 /* max service */ +} WMI_SERVICE; + +#define WMI_SERVICE_BM_SIZE ((WMI_MAX_SERVICE + sizeof(A_UINT32)- 1)/sizeof(A_UINT32)) + +#define WMI_SERVICE_ROAM_OFFLOAD WMI_SERVICE_ROAM_SCAN_OFFLOAD /* depreciated the name WMI_SERVICE_ROAM_OFFLOAD, but here to help compiling with old host driver */ + +/* + * turn on the WMI service bit corresponding to the WMI service. + */ +#define WMI_SERVICE_ENABLE(pwmi_svc_bmap,svc_id) \ + ( (pwmi_svc_bmap)[(svc_id)/(sizeof(A_UINT32))] |= \ + (1 << ((svc_id)%(sizeof(A_UINT32)))) ) + +#define WMI_SERVICE_DISABLE(pwmi_svc_bmap,svc_id) \ + ( (pwmi_svc_bmap)[(svc_id)/(sizeof(A_UINT32))] &= \ + ( ~(1 << ((svc_id)%(sizeof(A_UINT32)))) ) ) + +#define WMI_SERVICE_IS_ENABLED(pwmi_svc_bmap,svc_id) \ + ( ((pwmi_svc_bmap)[(svc_id)/(sizeof(A_UINT32))] & \ + (1 << ((svc_id)%(sizeof(A_UINT32)))) ) != 0) + +#ifdef __cplusplus +} +#endif + +#endif /*_WMI_SERVICES_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_defs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_defs.h new file mode 100644 index 000000000000..adfae7047d48 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_defs.h @@ -0,0 +1,3041 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WMI_TLV_DEFS_H_ +#define _WMI_TLV_DEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define WMITLV_FIELD_BUF_IS_ALLOCATED(elem_name) \ + is_allocated_##elem_name + +#define WMITLV_FIELD_NUM_OF(elem_name) \ + num_##elem_name + +/* Define the structure typedef for the TLV parameters of each cmd/event */ +#define WMITLV_TYPEDEF_STRUCT_PARAMS_TLVS(wmi_cmd_event_id) \ + wmi_cmd_event_id##_param_tlvs + +/* + * The following macro WMITLV_OP_* are created by the macro WMITLV_ELEM(). + */ +/* macro to define the TLV name in the correct order. When (op==TAG_ORDER) */ +#define WMITLV_OP_TAG_ORDER_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + wmi_cmd_event_id##_tlv_order_##elem_name, + +/* macro to define the TLV name with the TLV Tag value. When (op==TAG_ID) */ +#define WMITLV_OP_TAG_ID_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + wmi_cmd_event_id##_tlv_tag_##elem_name = elem_tlv_tag, + +/* macro to define the TLV name with the TLV structure size. May not be accurate when variable length. When (op==TAG_SIZEOF) */ +#define WMITLV_OP_TAG_SIZEOF_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + wmi_cmd_event_id##_sizeof_##elem_name = sizeof(elem_struc_type), + +/* macro to define the TLV name with value indicating whether the TLV is variable length. When (op==TAG_VAR_SIZED) */ +#define WMITLV_OP_TAG_VAR_SIZED_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + wmi_cmd_event_id##_var_sized_##elem_name = var_len, + +/* macro to define the TLV name with value indicating the fixed array size. When (op==TAG_ARR_SIZE) */ +#define WMITLV_OP_TAG_ARR_SIZE_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + wmi_cmd_event_id##_arr_size_##elem_name = arr_size, + +/* + * macro to define afew fields associated to a TLV. For example, a structure pointer with the TLV name. + * This macro is expand from WMITLV_ELEM(op) when (op==STRUCT_FIELD). + * NOTE: If this macro is changed, then "mirror" structure wmitlv_cmd_param_info + * should be updated too. + */ +#define WMITLV_OP_STRUCT_FIELD_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + elem_struc_type *elem_name; \ + A_UINT32 WMITLV_FIELD_NUM_OF(elem_name); \ + A_UINT32 WMITLV_FIELD_BUF_IS_ALLOCATED(elem_name); + +/* + * A "mirror" structure that contains the fields that is created by the + * macro WMITLV_OP_STRUCT_FIELD_macro. + * NOTE: you should modify this structure and WMITLV_OP_STRUCT_FIELD_macro + * so that they both has the same kind of fields. + */ +typedef struct { + void *tlv_ptr; /* Pointer to the TLV Buffer. But the "real" one will have the right type instead of void. */ + A_UINT32 num_elements; /* Number of elements. For non-array, this is one. For array, this is the number of elements. */ + A_UINT32 buf_is_allocated;/* Boolean flag to indicate that a new buffer is allocated for this TLV. */ +} wmitlv_cmd_param_info; + +/* + * NOTE TRICKY MACRO: + * WMITLV_ELEM is re-defined to a "op" specific macro. + * Eg. WMITLV_OP_TAG_ORDER_macro is created for the op_type=TAG_ORDER. + */ +#define WMITLV_ELEM(wmi_cmd_event_id, op_type, param_ptr, param_len, elem_tlv_tag, elem_struc_type, elem_name, var_len) \ + WMITLV_OP_##op_type##_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, WMITLV_ARR_SIZE_INVALID) +/* + * WMITLV_FXAR (FiX ARray) is similar to WMITLV_ELEM except it has an extra parameter for the fixed number of elements. + * It is re-defined to a "op" specific macro. + * Eg. WMITLV_OP_TAG_ORDER_macro is created for the op_type=TAG_ORDER. + */ +#define WMITLV_FXAR(wmi_cmd_event_id, op_type, param_ptr, param_len, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + WMITLV_OP_##op_type##_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) + +#define WMITLV_TABLE(id,op,buf,len) WMITLV_TABLE_##id(id,op,buf,len) + +/* + * This macro will create various enumerations and structures to describe the TLVs for + * the given Command/Event ID. + * + * For example, the following is for WMI_SERVICE_READY_EVENTID: + * #define WMITLV_TABLE_WMI_SERVICE_READY_EVENTID(id,op,buf,len) \ + * WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_service_ready_event_fixed_param, wmi_service_ready_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + * WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_HAL_REG_CAPABILITIES, HAL_REG_CAPABILITIES, hal_reg_capabilities, WMITLV_SIZE_FIX) \ + * WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, wmi_service_bitmap, WMITLV_SIZE_FIX, WMI_SERVICE_BM_SIZE) \ + * WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wlan_host_mem_req, mem_reqs, WMITLV_SIZE_VAR) + * WMITLV_CREATE_PARAM_STRUC(WMI_SERVICE_READY_EVENTID); + * This macro will create the following text: + * + * typedef enum { + * WMI_SERVICE_READY_EVENTID_tlv_order_wmi_service_ready_event_fixed_param, + * WMI_SERVICE_READY_EVENTID_tlv_order_hal_reg_capabilities, + * WMI_SERVICE_READY_EVENTID_tlv_order_wmi_service_bitmap, + * WMI_SERVICE_READY_EVENTID_tlv_order_mem_reqs, + * WMI_TLV_HLPR_NUM_TLVS_FOR_WMI_SERVICE_READY_EVENTID + * } WMI_SERVICE_READY_EVENTID_TAG_ID_enum_type; + * //NOTE: WMI_TLV_HLPR_NUM_TLVS_FOR_WMI_SERVICE_READY_EVENTID is the number of TLVs. + * + * typedef enum { + * WMI_SERVICE_READY_EVENTID_tlv_tag_wmi_service_ready_event_fixed_param = WMITLV_TAG_STRUC_wmi_service_ready_event_fixed_param, + * WMI_SERVICE_READY_EVENTID_tlv_tag_hal_reg_capabilities = WMITLV_TAG_STRUC_HAL_REG_CAPABILITIES, + * WMI_SERVICE_READY_EVENTID_tlv_tag_wmi_service_bitmap = WMITLV_TAG_ARRAY_UINT32, + * WMI_SERVICE_READY_EVENTID_tlv_tag_mem_reqs = WMITLV_TAG_ARRAY_STRUC, + * } WMI_SERVICE_READY_EVENTID_TAG_ORDER_enum_type; + * + * typedef enum { + * WMI_SERVICE_READY_EVENTID_sizeof_wmi_service_ready_event_fixed_param = sizeof(wmi_service_ready_event_fixed_param), + * WMI_SERVICE_READY_EVENTID_sizeof_hal_reg_capabilities = sizeof(HAL_REG_CAPABILITIES), + * WMI_SERVICE_READY_EVENTID_sizeof_wmi_service_bitmap = sizeof(A_UINT32), + * WMI_SERVICE_READY_EVENTID_sizeof_mem_reqs = sizeof(wlan_host_mem_req), + * } WMI_SERVICE_READY_EVENTID_TAG_SIZEOF_enum_type; + * + * typedef enum { + * WMI_SERVICE_READY_EVENTID_var_sized_wmi_service_ready_event_fixed_param = WMITLV_SIZE_FIX, + * WMI_SERVICE_READY_EVENTID_var_sized_hal_reg_capabilities = WMITLV_SIZE_FIX, + * WMI_SERVICE_READY_EVENTID_var_sized_wmi_service_bitmap = WMITLV_SIZE_VAR, + * WMI_SERVICE_READY_EVENTID_var_sized_mem_reqs = WMITLV_SIZE_VAR, + * } WMI_SERVICE_READY_EVENTID_TAG_VAR_SIZED_enum_type; + * + * typedef enum { + * WMI_SERVICE_READY_EVENTID_arr_size_wmi_service_ready_event_fixed_param = WMITLV_ARR_SIZE_INVALID, + * WMI_SERVICE_READY_EVENTID_arr_size_hal_reg_capabilities = WMITLV_ARR_SIZE_INVALID, + * WMI_SERVICE_READY_EVENTID_arr_size_wmi_service_bitmap = WMI_SERVICE_BM_SIZE, + * WMI_SERVICE_READY_EVENTID_arr_size_mem_reqs = WMITLV_ARR_SIZE_INVALID, + * } WMI_SERVICE_READY_EVENTID_TAG_ARR_SIZE_enum_type; + * + * typedef struct { + * wmi_service_ready_event_fixed_param *fixed_param; + * A_UINT32 num_fixed_param; + * A_UINT32 is_allocated_fixed_param; + * HAL_REG_CAPABILITIES *hal_reg_capabilities; + * A_UINT32 num_hal_reg_capabilities; + * A_UINT32 is_allocated_hal_reg_capabilities; + * A_UINT32 *wmi_service_bitmap; + * A_UINT32 num_wmi_service_bitmap; + * A_UINT32 is_allocated_wmi_service_bitmap; + * wlan_host_mem_req *mem_reqs; + * A_UINT32 num_mem_reqs; + * A_UINT32 is_allocated_mem_reqs; + * + * } WMI_SERVICE_READY_EVENTID_param_tlvs; + * + */ + +#define WMITLV_CREATE_PARAM_STRUC(wmi_cmd_event_id) \ + typedef enum { \ + WMITLV_TABLE(wmi_cmd_event_id, TAG_ORDER, NULL, 0) \ + WMI_TLV_HLPR_NUM_TLVS_FOR_##wmi_cmd_event_id \ + } wmi_cmd_event_id##_TAG_ORDER_enum_type; \ + \ + typedef struct { \ + WMITLV_TABLE(wmi_cmd_event_id, STRUCT_FIELD, NULL, 0) \ + } WMITLV_TYPEDEF_STRUCT_PARAMS_TLVS(wmi_cmd_event_id); \ + +/** Enum list of TLV Tags for each parameter structure type. */ +typedef enum { + /* 0 to 15 is reserved */ + WMITLV_TAG_LAST_RESERVED = 15, + WMITLV_TAG_FIRST_ARRAY_ENUM, /* First entry of ARRAY type tags */ + WMITLV_TAG_ARRAY_UINT32 = WMITLV_TAG_FIRST_ARRAY_ENUM, + WMITLV_TAG_ARRAY_BYTE, + WMITLV_TAG_ARRAY_STRUC, + WMITLV_TAG_ARRAY_FIXED_STRUC, + WMITLV_TAG_LAST_ARRAY_ENUM = 31, /* Last entry of ARRAY type tags */ + WMITLV_TAG_STRUC_wmi_service_ready_event_fixed_param, + WMITLV_TAG_STRUC_HAL_REG_CAPABILITIES, + WMITLV_TAG_STRUC_wlan_host_mem_req, + WMITLV_TAG_STRUC_wmi_ready_event_fixed_param, + WMITLV_TAG_STRUC_wmi_scan_event_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_tpc_config_event_fixed_param, + WMITLV_TAG_STRUC_wmi_chan_info_event_fixed_param, + WMITLV_TAG_STRUC_wmi_comb_phyerr_rx_hdr, + WMITLV_TAG_STRUC_wmi_vdev_start_response_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_stopped_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_install_key_complete_event_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_sta_kickout_event_fixed_param, + WMITLV_TAG_STRUC_wmi_mgmt_rx_hdr, + WMITLV_TAG_STRUC_wmi_tbtt_offset_event_fixed_param, + WMITLV_TAG_STRUC_wmi_tx_delba_complete_event_fixed_param, + WMITLV_TAG_STRUC_wmi_tx_addba_complete_event_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_event_fixed_param, + WMITLV_TAG_STRUC_WOW_EVENT_INFO_fixed_param, + WMITLV_TAG_STRUC_WOW_EVENT_INFO_SECTION_BITMAP, + WMITLV_TAG_STRUC_wmi_rtt_event_header, + WMITLV_TAG_STRUC_wmi_rtt_error_report_event_fixed_param, + WMITLV_TAG_STRUC_wmi_rtt_meas_event_fixed_param, + WMITLV_TAG_STRUC_wmi_echo_event_fixed_param, + WMITLV_TAG_STRUC_wmi_ftm_intg_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_get_keepalive_event_fixed_param, + WMITLV_TAG_STRUC_wmi_gpio_input_event_fixed_param, + WMITLV_TAG_STRUC_wmi_csa_event_fixed_param, + WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param, + WMITLV_TAG_STRUC_wmi_igtk_info, + WMITLV_TAG_STRUC_wmi_dcs_interference_event_fixed_param, + WMITLV_TAG_STRUC_ath_dcs_cw_int, + WMITLV_TAG_STRUC_ath_dcs_wlan_int_stat, + WMITLV_TAG_STRUC_wmi_wlan_profile_ctx_t, + WMITLV_TAG_STRUC_wmi_wlan_profile_t, + WMITLV_TAG_STRUC_wmi_pdev_qvit_event_fixed_param, + WMITLV_TAG_STRUC_wmi_host_swba_event_fixed_param, + WMITLV_TAG_STRUC_wmi_tim_info, + WMITLV_TAG_STRUC_wmi_p2p_noa_info, + WMITLV_TAG_STRUC_wmi_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_avoid_freq_ranges_event_fixed_param, + WMITLV_TAG_STRUC_wmi_avoid_freq_range_desc, + WMITLV_TAG_STRUC_wmi_gtk_rekey_fail_event_fixed_param, + WMITLV_TAG_STRUC_wmi_init_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_resource_config, + WMITLV_TAG_STRUC_wlan_host_memory_chunk, + WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_scan_chan_list_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_wmm_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wmm_params, + WMITLV_TAG_STRUC_wmi_pdev_set_quiet_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_create_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_delete_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_start_request_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_p2p_noa_descriptor, + WMITLV_TAG_STRUC_wmi_p2p_go_set_beacon_ie_fixed_param, + WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_up_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_stop_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_down_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_set_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_install_key_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_create_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_delete_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_flush_tids_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_assoc_complete_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vht_rate_set, + WMITLV_TAG_STRUC_wmi_bcn_tmpl_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_prb_tmpl_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_bcn_prb_info, + WMITLV_TAG_STRUC_wmi_peer_tid_addba_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_tid_delba_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sta_powersave_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sta_dtim_ps_method_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_param, + WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE, + WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, + WMITLV_TAG_STRUC_wmi_ftm_intg_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_STA_KEEPALIVE_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_STA_KEEPALVE_ARP_RESPONSE, + WMITLV_TAG_STRUC_wmi_p2p_set_vendor_ie_data_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ap_ps_peer_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_rate_retry_sched_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_rtt_measreq_head, + WMITLV_TAG_STRUC_wmi_rtt_measreq_body, + WMITLV_TAG_STRUC_wmi_rtt_tsf_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_spectral_configure_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_spectral_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param, + WMITLV_TAG_STRUC_nlo_configured_parameters, + WMITLV_TAG_STRUC_wmi_csa_offload_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_csa_offload_chanswitch_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_chatter_set_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_echo_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_set_keepalive_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_get_keepalive_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_FORCE_FW_HANG_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_gpio_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_gpio_output_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_add_wds_entry_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_remove_wds_entry_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_bcn_tx_hdr, + WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mgmt_tx_hdr, + WMITLV_TAG_STRUC_wmi_addba_clear_resp_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_addba_send_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_delba_send_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_addba_setresponse_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_send_singleamsdu_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_dscp_tid_map_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_green_ap_ps_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_get_tpc_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_base_macaddr_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_mcast_group_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param, + WMITLV_TAG_STRUC_wmi_ap_profile, + WMITLV_TAG_STRUC_wmi_scan_sch_priority_table_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_dfs_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_dfs_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T, + WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T, + WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T, + WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD, + WMITLV_TAG_STRUC_WMI_scan_update_request_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_chatter_pkt_coalescing_filter, + WMITLV_TAG_STRUC_wmi_chatter_coalescing_add_filter_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_chatter_coalescing_delete_filter_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_chatter_coalescing_query_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_txbf_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_debug_log_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_nlo_event, + WMITLV_TAG_STRUC_wmi_chatter_query_reply_event_fixed_param, + WMITLV_TAG_STRUC_wmi_upload_h_hdr, + WMITLV_TAG_STRUC_wmi_capture_h_event_hdr, + WMITLV_TAG_STRUC_WMI_VDEV_WNM_SLEEPMODE_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_set_wmm_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_tdls_peer_event_fixed_param, + WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities, + WMITLV_TAG_STRUC_wmi_vdev_mcc_set_tbtt_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_mcc_bcn_intvl_change_event_fixed_param, + WMITLV_TAG_STRUC_wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_resmgr_set_chan_time_quota_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_resmgr_set_chan_latency_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ba_req_ssn_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ba_rsp_ssn_event_fixed_param, + WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_p2p_set_oppps_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_p2p_set_noa_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ba_req_ssn_cmd_sub_struct_param, + WMITLV_TAG_STRUC_wmi_ba_req_ssn_event_sub_struct_param, + WMITLV_TAG_STRUC_wmi_sta_smps_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_set_gtx_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mcc_sched_traffic_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mcc_sched_sta_traffic_stats, + WMITLV_TAG_STRUC_wmi_offload_bcn_tx_status_event_fixed_param, + WMITLV_TAG_STRUC_wmi_p2p_noa_event_fixed_param, + WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_hb_ind_event_fixed_param, + WMITLV_TAG_STRUC_wmi_tx_pause_event_fixed_param, + WMITLV_TAG_STRUC_wmi_rfkill_event_fixed_param, + WMITLV_TAG_STRUC_wmi_dfs_radar_event_fixed_param, + WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_ena_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_dis_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_batch_scan_result_scan_list, + WMITLV_TAG_STRUC_wmi_batch_scan_result_network_info, + WMITLV_TAG_STRUC_wmi_batch_scan_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_batch_scan_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_batch_scan_trigger_result_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_batch_scan_enabled_event_fixed_param, + WMITLV_TAG_STRUC_wmi_batch_scan_result_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_thermal_mgmt_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_thermal_mgmt_event_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_info_event_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_info, + WMITLV_TAG_STRUC_wmi_peer_tx_fail_cnt_thr_event_fixed_param, + WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_rmc_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mhf_offload_set_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mhf_offload_plumb_routing_table_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_nan_cmd_param, + WMITLV_TAG_STRUC_wmi_nan_event_hdr, + WMITLV_TAG_STRUC_wmi_pdev_l1ss_track_event_fixed_param, + WMITLV_TAG_STRUC_wmi_diag_data_container_event_fixed_param, + WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param, + WMITLV_TAG_STRUC_wmi_peer_get_estimated_linkspeed_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_estimated_linkspeed_event_fixed_param, + WMITLV_TAG_STRUC_wmi_aggr_state_trig_event_fixed_param, + WMITLV_TAG_STRUC_wmi_mhf_offload_routing_table_entry, + WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_req_stats_ext_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_stats_ext_event_fixed_param, + WMITLV_TAG_STRUC_wmi_obss_scan_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_obss_scan_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_offload_prb_rsp_tx_status_event_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_led_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_host_auto_shutdown_event_fixed_param, + WMITLV_TAG_STRUC_wmi_update_whal_mib_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param, + WMITLV_TAG_STRUC_WOW_IOAC_PKT_PATTERN_T, + WMITLV_TAG_STRUC_WOW_IOAC_TMR_PATTERN_T, + WMITLV_TAG_STRUC_WMI_WOW_IOAC_ADD_KEEPALIVE_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_IOAC_DEL_KEEPALIVE_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_IOAC_KEEPALIVE_T, + WMITLV_TAG_STRUC_WMI_WOW_IOAC_ADD_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_IOAC_DEL_PATTERN_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_start_link_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_clear_link_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_request_link_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_iface_link_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_radio_link_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_channel_stats, + WMITLV_TAG_STRUC_wmi_radio_link_stats, + WMITLV_TAG_STRUC_wmi_rate_stats, + WMITLV_TAG_STRUC_wmi_peer_link_stats, + WMITLV_TAG_STRUC_wmi_wmm_ac_stats, + WMITLV_TAG_STRUC_wmi_iface_link_stats, + WMITLV_TAG_STRUC_wmi_lpi_mgmt_snooping_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_lpi_start_scan_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_lpi_stop_scan_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_lpi_result_event_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_state_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_bucket_channel_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_wlan_change_bssid_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_get_wlan_change_results_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_set_capabilities_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_wlan_descriptor_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_rssi_info_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_wlan_change_result_bssid_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_cache_capabilities_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_wlan_change_monitor_capabilities_event_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_hotlist_monitor_capabilities_event_fixed_param, + WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_d0_wow_disable_ack_event_fixed_param, + WMITLV_TAG_STRUC_wmi_unit_test_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param, + WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param, + WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param, + WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param, + WMITLV_TAG_STRUC_wmi_roam_synch_event_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param, + WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_lpi_status_event_fixed_param, + WMITLV_TAG_STRUC_wmi_lpi_handoff_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_rate_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_rate_ht_info, + WMITLV_TAG_STRUC_wmi_ric_request_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_get_temperature_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_temperature_event_fixed_param, + WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_tpc_chainmask_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ric_tspec, + WMITLV_TAG_STRUC_wmi_tpc_chainmask_config, + WMITLV_TAG_STRUCT_wmi_ipa_offload_enable_disable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_scan_prob_req_oui_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_key_material, + WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mdns_offload_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mdns_set_fqdn_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mdns_set_resp_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mdns_get_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mdns_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_resume_event_fixed_param, + WMITLV_TAG_STRUC_wmi_pdev_set_antenna_diversity_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sap_ofl_enable_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_sap_ofl_add_sta_event_fixed_param, + WMITLV_TAG_STRUC_wmi_sap_ofl_del_sta_event_fixed_param, + WMITLV_TAG_STRUC_wmi_apfind_cmd_param, + WMITLV_TAG_STRUC_wmi_apfind_event_hdr, + WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param, //DEPRECATED + WMITLV_TAG_STRUC_wmi_ocb_set_sched_event_fixed_param, // DEPRECATED + WMITLV_TAG_STRUC_wmi_ocb_set_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_set_config_resp_event_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_set_utc_time_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_start_timing_advert_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_stop_timing_advert_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_resp_event_fixed_param, + WMITLV_TAG_STRUC_wmi_dcc_get_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_dcc_channel_stats_request, + WMITLV_TAG_STRUC_wmi_dcc_get_stats_resp_event_fixed_param, + WMITLV_TAG_STRUC_wmi_dcc_clear_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_dcc_update_ndl_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_dcc_update_ndl_resp_event_fixed_param, + WMITLV_TAG_STRUC_wmi_dcc_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_channel, + WMITLV_TAG_STRUC_wmi_ocb_schedule_element, + WMITLV_TAG_STRUC_wmi_dcc_ndl_stats_per_channel, + WMITLV_TAG_STRUC_wmi_dcc_ndl_chan, + WMITLV_TAG_STRUC_wmi_qos_parameter, + WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config, + WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param, + WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param, + WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_passpoint_event_hdr, + WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_tsf_report_event_fixed_param, + WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param, + WMITLV_TAG_STRUC_wmi_update_fw_mem_dump_fixed_param, + WMITLV_TAG_STRUC_wmi_fw_mem_dump_params, + WMITLV_TAG_STRUC_wmi_debug_mesg_flush_fixed_param, + WMITLV_TAG_STRUC_wmi_debug_mesg_flush_complete_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_set_rate_report_condition_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param, + WMITLV_TAG_STRUC_wmi_rssi_breach_event_fixed_param, + WMITLV_TAG_STRUC_WOW_EVENT_INITIAL_WAKEUP_fixed_param, + WMITLV_TAG_STRUC_wmi_soc_set_pcl_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_response_event_fixed_param, + WMITLV_TAG_STRUC_wmi_soc_hw_mode_transition_event_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_txrx_streams, + WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_response_vdev_mac_entry, + WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_response_event_fixed_param, + WMITLV_TAG_STRUC_WOW_IOAC_SOCK_PATTERN_T, + WMITLV_TAG_STRUC_wmi_wow_enable_icmpv6_na_flt_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_diag_event_log_config_fixed_param, + WMITLV_TAG_STRUC_wmi_diag_event_log_supported_event_fixed_params, + WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param, + WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param, + WMITLV_TAG_STRUC_wmi_sap_set_blacklist_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mgmt_tx_send_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mgmt_tx_compl_event_fixed_param, + WMITLV_TAG_STRUC_wmi_soc_set_antenna_mode_cmd_fixed_param, + WMITLV_TAG_STRUC_WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_lro_info_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param, + WMITLV_TAG_STRUC_wmi_service_ready_ext_event_fixed_param, + WMITLV_TAG_STRUC_wmi_mawc_sensor_report_ind_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_mawc_enable_sensor_event_fixed_param, + WMITLV_TAG_STRUC_wmi_roam_configure_mawc_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_nlo_configure_mawc_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_extscan_configure_mawc_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_assoc_conf_event_fixed_param, + WMITLV_TAG_STRUC_wmi_wow_hostwakeup_gpio_pin_pattern_config_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ap_ps_egap_param_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ap_ps_egap_info_event_fixed_param, + WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param, + WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_complete_event_fixed_param, + WMITLV_TAG_STRUC_wmi_scpc_event_fixed_param, + WMITLV_TAG_STRUC_wmi_ap_ps_egap_info_chainmask_list, + WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_complete_event_fixed_param, +} WMITLV_TAG_ID; + +/* + * IMPORTANT: Please add _ALL_ WMI Commands Here. + * Otherwise, these WMI TLV Functions will be process them. + */ +#define WMITLV_ALL_CMD_LIST(OP) \ + OP(WMI_INIT_CMDID) \ + OP(WMI_PEER_CREATE_CMDID) \ + OP(WMI_PEER_DELETE_CMDID) \ + OP(WMI_PEER_FLUSH_TIDS_CMDID) \ + OP(WMI_PEER_SET_PARAM_CMDID) \ + OP(WMI_STA_POWERSAVE_MODE_CMDID) \ + OP(WMI_STA_POWERSAVE_PARAM_CMDID) \ + OP(WMI_STA_DTIM_PS_METHOD_CMDID) \ + OP(WMI_PDEV_SET_REGDOMAIN_CMDID) \ + OP(WMI_PEER_TID_ADDBA_CMDID) \ + OP(WMI_PEER_TID_DELBA_CMDID) \ + OP(WMI_PDEV_FTM_INTG_CMDID) \ + OP(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID) \ + OP(WMI_WOW_ENABLE_CMDID) \ + OP(WMI_RMV_BCN_FILTER_CMDID) \ + OP(WMI_ROAM_SCAN_MODE) \ + OP(WMI_ROAM_SCAN_RSSI_THRESHOLD) \ + OP(WMI_ROAM_SCAN_PERIOD) \ + OP(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD) \ + OP(WMI_START_SCAN_CMDID) \ + OP(WMI_VDEV_PLMREQ_START_CMDID) \ + OP(WMI_VDEV_PLMREQ_STOP_CMDID) \ + OP(WMI_PDEV_SET_CHANNEL_CMDID) \ + OP(WMI_PDEV_SET_WMM_PARAMS_CMDID) \ + OP(WMI_VDEV_START_REQUEST_CMDID) \ + OP(WMI_VDEV_RESTART_REQUEST_CMDID) \ + OP(WMI_P2P_GO_SET_BEACON_IE) \ + OP(WMI_GTK_OFFLOAD_CMDID) \ + OP(WMI_SCAN_CHAN_LIST_CMDID) \ + OP(WMI_STA_UAPSD_AUTO_TRIG_CMDID) \ + OP(WMI_PRB_TMPL_CMDID) \ + OP(WMI_BCN_TMPL_CMDID) \ + OP(WMI_VDEV_INSTALL_KEY_CMDID) \ + OP(WMI_PEER_ASSOC_CMDID) \ + OP(WMI_ADD_BCN_FILTER_CMDID) \ + OP(WMI_STA_KEEPALIVE_CMDID) \ + OP(WMI_SET_ARP_NS_OFFLOAD_CMDID) \ + OP(WMI_P2P_SET_VENDOR_IE_DATA_CMDID) \ + OP(WMI_AP_PS_PEER_PARAM_CMDID) \ + OP(WMI_WLAN_PROFILE_TRIGGER_CMDID) \ + OP(WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID) \ + OP(WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID) \ + OP(WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID) \ + OP(WMI_WOW_DEL_WAKE_PATTERN_CMDID) \ + OP(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID) \ + OP(WMI_RTT_MEASREQ_CMDID) \ + OP(WMI_RTT_TSF_CMDID) \ + OP(WMI_OEM_REQ_CMDID) \ + OP(WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID) \ + OP(WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID) \ + OP(WMI_REQUEST_STATS_CMDID) \ + OP(WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID) \ + OP(WMI_CSA_OFFLOAD_ENABLE_CMDID) \ + OP(WMI_CSA_OFFLOAD_CHANSWITCH_CMDID) \ + OP(WMI_CHATTER_SET_MODE_CMDID) \ + OP(WMI_ECHO_CMDID) \ + OP(WMI_PDEV_UTF_CMDID) \ + OP(WMI_PDEV_QVIT_CMDID) \ + OP(WMI_VDEV_SET_KEEPALIVE_CMDID) \ + OP(WMI_VDEV_GET_KEEPALIVE_CMDID) \ + OP(WMI_FORCE_FW_HANG_CMDID) \ + OP(WMI_GPIO_CONFIG_CMDID) \ + OP(WMI_GPIO_OUTPUT_CMDID) \ + OP(WMI_PEER_ADD_WDS_ENTRY_CMDID) \ + OP(WMI_PEER_REMOVE_WDS_ENTRY_CMDID) \ + OP(WMI_BCN_TX_CMDID) \ + OP(WMI_PDEV_SEND_BCN_CMDID) \ + OP(WMI_MGMT_TX_CMDID) \ + OP(WMI_ADDBA_CLEAR_RESP_CMDID) \ + OP(WMI_ADDBA_SEND_CMDID) \ + OP(WMI_DELBA_SEND_CMDID) \ + OP(WMI_ADDBA_SET_RESP_CMDID) \ + OP(WMI_SEND_SINGLEAMSDU_CMDID) \ + OP(WMI_PDEV_PKTLOG_ENABLE_CMDID) \ + OP(WMI_PDEV_PKTLOG_DISABLE_CMDID) \ + OP(WMI_PDEV_SET_HT_CAP_IE_CMDID) \ + OP(WMI_PDEV_SET_VHT_CAP_IE_CMDID) \ + OP(WMI_PDEV_SET_DSCP_TID_MAP_CMDID) \ + OP(WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID) \ + OP(WMI_PDEV_GET_TPC_CONFIG_CMDID) \ + OP(WMI_PDEV_SET_BASE_MACADDR_CMDID) \ + OP(WMI_PEER_MCAST_GROUP_CMDID) \ + OP(WMI_ROAM_AP_PROFILE) \ + OP(WMI_SCAN_SCH_PRIO_TBL_CMDID) \ + OP(WMI_PDEV_DFS_ENABLE_CMDID) \ + OP(WMI_PDEV_DFS_DISABLE_CMDID) \ + OP(WMI_WOW_ADD_WAKE_PATTERN_CMDID) \ + OP(WMI_PDEV_SUSPEND_CMDID) \ + OP(WMI_PDEV_RESUME_CMDID) \ + OP(WMI_STOP_SCAN_CMDID) \ + OP(WMI_PDEV_SET_PARAM_CMDID) \ + OP(WMI_PDEV_SET_QUIET_MODE_CMDID) \ + OP(WMI_VDEV_CREATE_CMDID) \ + OP(WMI_VDEV_DELETE_CMDID) \ + OP(WMI_VDEV_UP_CMDID) \ + OP(WMI_VDEV_STOP_CMDID) \ + OP(WMI_VDEV_DOWN_CMDID) \ + OP(WMI_VDEV_SET_PARAM_CMDID) \ + OP(WMI_SCAN_UPDATE_REQUEST_CMDID) \ + OP(WMI_CHATTER_ADD_COALESCING_FILTER_CMDID) \ + OP(WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID) \ + OP(WMI_CHATTER_COALESCING_QUERY_CMDID) \ + OP(WMI_TXBF_CMDID) \ + OP(WMI_DBGLOG_CFG_CMDID) \ + OP(WMI_VDEV_WNM_SLEEPMODE_CMDID) \ + OP(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID) \ + OP(WMI_VDEV_WMM_ADDTS_CMDID) \ + OP(WMI_VDEV_WMM_DELTS_CMDID) \ + OP(WMI_VDEV_SET_WMM_PARAMS_CMDID) \ + OP(WMI_VDEV_SET_GTX_PARAMS_CMDID) \ + OP(WMI_TDLS_SET_STATE_CMDID) \ + OP(WMI_TDLS_PEER_UPDATE_CMDID) \ + OP(WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID) \ + OP(WMI_ROAM_CHAN_LIST) \ + OP(WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID)\ + OP(WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID) \ + OP(WMI_RESMGR_SET_CHAN_LATENCY_CMDID) \ + OP(WMI_BA_REQ_SSN_CMDID) \ + OP(WMI_STA_SMPS_FORCE_MODE_CMDID) \ + OP(WMI_SET_MCASTBCAST_FILTER_CMDID) \ + OP(WMI_P2P_SET_OPPPS_PARAM_CMDID) \ + OP(WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID) \ + OP(WMI_STA_SMPS_PARAM_CMDID) \ + OP(WMI_MCC_SCHED_TRAFFIC_STATS_CMDID) \ + OP(WMI_HB_SET_ENABLE_CMDID) \ + OP(WMI_HB_SET_TCP_PARAMS_CMDID) \ + OP(WMI_HB_SET_TCP_PKT_FILTER_CMDID) \ + OP(WMI_HB_SET_UDP_PARAMS_CMDID) \ + OP(WMI_HB_SET_UDP_PKT_FILTER_CMDID) \ + OP(WMI_PEER_INFO_REQ_CMDID) \ + OP(WMI_RMC_SET_MODE_CMDID) \ + OP(WMI_RMC_SET_ACTION_PERIOD_CMDID) \ + OP(WMI_RMC_CONFIG_CMDID) \ + OP(WMI_MHF_OFFLOAD_SET_MODE_CMDID) \ + OP(WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID) \ + OP(WMI_DFS_PHYERR_FILTER_ENA_CMDID) \ + OP(WMI_DFS_PHYERR_FILTER_DIS_CMDID) \ + OP(WMI_BATCH_SCAN_ENABLE_CMDID) \ + OP(WMI_BATCH_SCAN_DISABLE_CMDID) \ + OP(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID) \ + OP(WMI_THERMAL_MGMT_CMDID) \ + OP(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID) \ + OP(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID) \ + OP(WMI_NAN_CMDID) \ + OP(WMI_MODEM_POWER_STATE_CMDID) \ + OP(WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID) \ + OP(WMI_ROAM_SCAN_CMD)\ + OP(WMI_REQUEST_STATS_EXT_CMDID) \ + OP(WMI_OBSS_SCAN_ENABLE_CMDID) \ + OP(WMI_OBSS_SCAN_DISABLE_CMDID)\ + OP(WMI_PDEV_SET_LED_CONFIG_CMDID)\ + OP(WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID) \ + OP(WMI_TPC_CHAINMASK_CONFIG_CMDID) \ + OP(WMI_CHAN_AVOID_UPDATE_CMDID) \ + OP(WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID) \ + OP(WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID) \ + OP(WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID) \ + OP(WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID) \ + OP(WMI_REQUEST_LINK_STATS_CMDID) \ + OP(WMI_START_LINK_STATS_CMDID) \ + OP(WMI_CLEAR_LINK_STATS_CMDID) \ + OP(WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID) \ + OP(WMI_LPI_START_SCAN_CMDID) \ + OP(WMI_LPI_STOP_SCAN_CMDID) \ + OP(WMI_EXTSCAN_START_CMDID) \ + OP(WMI_EXTSCAN_STOP_CMDID) \ + OP(WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID) \ + OP(WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID) \ + OP(WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID) \ + OP(WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID) \ + OP(WMI_EXTSCAN_SET_CAPABILITIES_CMDID) \ + OP(WMI_EXTSCAN_GET_CAPABILITIES_CMDID) \ + OP(WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID) \ + OP(WMI_D0_WOW_ENABLE_DISABLE_CMDID) \ + OP(WMI_UNIT_TEST_CMDID) \ + OP(WMI_ROAM_SYNCH_COMPLETE) \ + OP(WMI_EXTWOW_ENABLE_CMDID) \ + OP(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID) \ + OP(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID) \ + OP(WMI_ROAM_SET_RIC_REQUEST_CMDID) \ + OP(WMI_PDEV_GET_TEMPERATURE_CMDID) \ + OP(WMI_SET_DHCP_SERVER_OFFLOAD_CMDID) \ + OP(WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID)\ + OP(WMI_SCAN_PROB_REQ_OUI_CMDID) \ + OP(WMI_TDLS_SET_OFFCHAN_MODE_CMDID)\ + OP(WMI_PDEV_SET_LED_FLASHING_CMDID) \ + OP(WMI_ROAM_INVOKE_CMDID) \ + OP(WMI_MDNS_OFFLOAD_ENABLE_CMDID) \ + OP(WMI_MDNS_SET_FQDN_CMDID) \ + OP(WMI_MDNS_SET_RESPONSE_CMDID) \ + OP(WMI_MDNS_GET_STATS_CMDID) \ + OP(WMI_SET_ANTENNA_DIVERSITY_CMDID) \ + OP(WMI_SAP_OFL_ENABLE_CMDID) \ + OP(WMI_APFIND_CMDID) \ + OP(WMI_OCB_SET_SCHED_CMDID) \ + OP(WMI_OCB_SET_CONFIG_CMDID) \ + OP(WMI_OCB_SET_UTC_TIME_CMDID) \ + OP(WMI_OCB_START_TIMING_ADVERT_CMDID) \ + OP(WMI_OCB_STOP_TIMING_ADVERT_CMDID) \ + OP(WMI_OCB_GET_TSF_TIMER_CMDID) \ + OP(WMI_DCC_GET_STATS_CMDID) \ + OP(WMI_DCC_CLEAR_STATS_CMDID) \ + OP(WMI_DCC_UPDATE_NDL_CMDID) \ + OP(WMI_ROAM_FILTER_CMDID) \ + OP(WMI_PASSPOINT_LIST_CONFIG_CMDID) \ + OP(WMI_VDEV_TSF_TSTAMP_ACTION_CMDID) \ + OP(WMI_GET_FW_MEM_DUMP_CMDID) \ + OP(WMI_DEBUG_MESG_FLUSH_CMDID) \ + OP(WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID) \ + OP(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID) \ + OP(WMI_VDEV_SET_IE_CMDID) \ + OP(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID) \ + OP(WMI_SOC_SET_PCL_CMDID) \ + OP(WMI_SOC_SET_HW_MODE_CMDID) \ + OP(WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID) \ + OP(WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID) \ + OP(WMI_DIAG_EVENT_LOG_CONFIG_CMDID) \ + OP(WMI_PACKET_FILTER_CONFIG_CMDID) \ + OP(WMI_PACKET_FILTER_ENABLE_CMDID) \ + OP(WMI_SAP_SET_BLACKLIST_PARAM_CMDID) \ + OP(WMI_MGMT_TX_SEND_CMDID) \ + OP(WMI_SOC_SET_ANTENNA_MODE_CMDID) \ + OP(WMI_WOW_UDP_SVC_OFLD_CMDID) \ + OP(WMI_LRO_CONFIG_CMDID) \ + OP(WMI_MAWC_SENSOR_REPORT_IND_CMDID) \ + OP(WMI_ROAM_CONFIGURE_MAWC_CMDID) \ + OP(WMI_NLO_CONFIGURE_MAWC_CMDID) \ + OP(WMI_EXTSCAN_CONFIGURE_MAWC_CMDID) \ + OP(WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID) \ + OP(WMI_AP_PS_EGAP_PARAM_CMDID) \ + OP(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID) \ + OP(WMI_TRANSFER_DATA_TO_FLASH_CMDID) \ + OP(WMI_OEM_REQUEST_CMDID) +/* + * IMPORTANT: Please add _ALL_ WMI Events Here. + * Otherwise, these WMI TLV Functions will be process them. + */ +#define WMITLV_ALL_EVT_LIST(OP) \ + OP(WMI_SERVICE_READY_EVENTID) \ + OP(WMI_SERVICE_READY_EXT_EVENTID) \ + OP(WMI_READY_EVENTID) \ + OP(WMI_SCAN_EVENTID) \ + OP(WMI_PDEV_TPC_CONFIG_EVENTID) \ + OP(WMI_CHAN_INFO_EVENTID) \ + OP(WMI_PHYERR_EVENTID) \ + OP(WMI_VDEV_START_RESP_EVENTID) \ + OP(WMI_VDEV_STOPPED_EVENTID) \ + OP(WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID) \ + OP(WMI_PEER_STA_KICKOUT_EVENTID) \ + OP(WMI_MGMT_RX_EVENTID) \ + OP(WMI_TBTTOFFSET_UPDATE_EVENTID) \ + OP(WMI_TX_DELBA_COMPLETE_EVENTID) \ + OP(WMI_TX_ADDBA_COMPLETE_EVENTID) \ + OP(WMI_ROAM_EVENTID) \ + OP(WMI_WOW_WAKEUP_HOST_EVENTID) \ + OP(WMI_RTT_ERROR_REPORT_EVENTID) \ + OP(WMI_OEM_MEASUREMENT_REPORT_EVENTID) \ + OP(WMI_OEM_ERROR_REPORT_EVENTID) \ + OP(WMI_OEM_CAPABILITY_EVENTID) \ + OP(WMI_ECHO_EVENTID) \ + OP(WMI_PDEV_FTM_INTG_EVENTID) \ + OP(WMI_VDEV_GET_KEEPALIVE_EVENTID) \ + OP(WMI_GPIO_INPUT_EVENTID) \ + OP(WMI_CSA_HANDLING_EVENTID) \ + OP(WMI_DEBUG_MESG_EVENTID) \ + OP(WMI_GTK_OFFLOAD_STATUS_EVENTID) \ + OP(WMI_DCS_INTERFERENCE_EVENTID) \ + OP(WMI_WLAN_PROFILE_DATA_EVENTID) \ + OP(WMI_PDEV_UTF_EVENTID) \ + OP(WMI_DEBUG_PRINT_EVENTID) \ + OP(WMI_RTT_MEASUREMENT_REPORT_EVENTID) \ + OP(WMI_HOST_SWBA_EVENTID) \ + OP(WMI_UPDATE_STATS_EVENTID) \ + OP(WMI_PDEV_QVIT_EVENTID) \ + OP(WMI_WLAN_FREQ_AVOID_EVENTID) \ + OP(WMI_GTK_REKEY_FAIL_EVENTID) \ + OP(WMI_NLO_MATCH_EVENTID) \ + OP(WMI_NLO_SCAN_COMPLETE_EVENTID) \ + OP(WMI_APFIND_EVENTID) \ + OP(WMI_CHATTER_PC_QUERY_EVENTID) \ + OP(WMI_UPLOADH_EVENTID) \ + OP(WMI_CAPTUREH_EVENTID) \ + OP(WMI_TDLS_PEER_EVENTID) \ + OP(WMI_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID) \ + OP(WMI_BA_RSP_SSN_EVENTID) \ + OP(WMI_OFFLOAD_BCN_TX_STATUS_EVENTID) \ + OP(WMI_P2P_NOA_EVENTID) \ + OP(WMI_TX_PAUSE_EVENTID) \ + OP(WMI_RFKILL_STATE_CHANGE_EVENTID) \ + OP(WMI_PEER_INFO_EVENTID) \ + OP(WMI_PEER_TX_FAIL_CNT_THR_EVENTID) \ + OP(WMI_DFS_RADAR_EVENTID) \ + OP(WMI_BATCH_SCAN_ENABLED_EVENTID) \ + OP(WMI_BATCH_SCAN_RESULT_EVENTID) \ + OP(WMI_THERMAL_MGMT_EVENTID) \ + OP(WMI_NAN_EVENTID) \ + OP(WMI_PDEV_L1SS_TRACK_EVENTID) \ + OP(WMI_DIAG_DATA_CONTAINER_EVENTID) \ + OP(WMI_PEER_ESTIMATED_LINKSPEED_EVENTID) \ + OP(WMI_AGGR_STATE_TRIG_EVENTID)\ + OP(WMI_STATS_EXT_EVENTID) \ + OP(WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID) \ + OP(WMI_HOST_AUTO_SHUTDOWN_EVENTID) \ + OP(WMI_UPDATE_WHAL_MIB_STATS_EVENTID) \ + OP(WMI_IFACE_LINK_STATS_EVENTID) \ + OP(WMI_PEER_LINK_STATS_EVENTID) \ + OP(WMI_RADIO_LINK_STATS_EVENTID) \ + OP(WMI_LPI_RESULT_EVENTID) \ + OP(WMI_PEER_STATE_EVENTID) \ + OP(WMI_EXTSCAN_START_STOP_EVENTID) \ + OP(WMI_EXTSCAN_OPERATION_EVENTID) \ + OP(WMI_EXTSCAN_TABLE_USAGE_EVENTID) \ + OP(WMI_EXTSCAN_CACHED_RESULTS_EVENTID) \ + OP(WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID) \ + OP(WMI_EXTSCAN_HOTLIST_MATCH_EVENTID) \ + OP(WMI_EXTSCAN_CAPABILITIES_EVENTID) \ + OP(WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID) \ + OP(WMI_D0_WOW_DISABLE_ACK_EVENTID) \ + OP(WMI_ROAM_SYNCH_EVENTID) \ + OP(WMI_LPI_STATUS_EVENTID) \ + OP(WMI_LPI_HANDOFF_EVENTID) \ + OP(WMI_UPDATE_VDEV_RATE_STATS_EVENTID) \ + OP(WMI_PDEV_TEMPERATURE_EVENTID) \ + OP(WMI_DIAG_EVENTID) \ + OP(WMI_MDNS_STATS_EVENTID) \ + OP(WMI_PDEV_RESUME_EVENTID) \ + OP(WMI_SAP_OFL_ADD_STA_EVENTID) \ + OP(WMI_SAP_OFL_DEL_STA_EVENTID) \ + OP(WMI_OCB_SET_SCHED_EVENTID) \ + OP(WMI_OCB_SET_CONFIG_RESP_EVENTID) \ + OP(WMI_OCB_GET_TSF_TIMER_RESP_EVENTID) \ + OP(WMI_DCC_GET_STATS_RESP_EVENTID) \ + OP(WMI_DCC_UPDATE_NDL_RESP_EVENTID) \ + OP(WMI_DCC_STATS_EVENTID) \ + OP(WMI_PASSPOINT_MATCH_EVENTID) \ + OP(WMI_VDEV_TSF_REPORT_EVENTID) \ + OP(WMI_UPDATE_FW_MEM_DUMP_EVENTID) \ + OP(WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID) \ + OP(WMI_RSSI_BREACH_EVENTID)\ + OP(WMI_WOW_INITIAL_WAKEUP_EVENTID) \ + OP(WMI_SOC_SET_HW_MODE_RESP_EVENTID) \ + OP(WMI_SOC_HW_MODE_TRANSITION_EVENTID) \ + OP(WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID) \ + OP(WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID) \ + OP(WMI_MGMT_TX_COMPLETION_EVENTID) \ + OP(WMI_MAWC_ENABLE_SENSOR_EVENTID) \ + OP(WMI_PEER_ASSOC_CONF_EVENTID) \ + OP(WMI_AP_PS_EGAP_INFO_EVENTID) \ + OP(WMI_TRANSFER_DATA_TO_FLASH_COMPLETE_EVENTID) \ + OP(WMI_OEM_RESPONSE_EVENTID) \ + OP(WMI_PDEV_UTF_SCPC_EVENTID) \ + OP(WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID) + +/* TLV definitions of WMI commands */ + +/* Init Cmd */ +#define WMITLV_TABLE_WMI_INIT_CMDID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_init_cmd_fixed_param, wmi_init_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_resource_config, wmi_resource_config, resource_config, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wlan_host_memory_chunk, host_mem_chunks, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_INIT_CMDID); + +/* Peer create Cmd */ +#define WMITLV_TABLE_WMI_PEER_CREATE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_create_cmd_fixed_param, wmi_peer_create_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_CREATE_CMDID); + +/* Peer delete Cmd */ +#define WMITLV_TABLE_WMI_PEER_DELETE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_delete_cmd_fixed_param, wmi_peer_delete_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_DELETE_CMDID); + +/* Peer flush Cmd*/ +#define WMITLV_TABLE_WMI_PEER_FLUSH_TIDS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_flush_tids_cmd_fixed_param, wmi_peer_flush_tids_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_FLUSH_TIDS_CMDID); + +/* Peer Set Param Cmd */ +#define WMITLV_TABLE_WMI_PEER_SET_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param, wmi_peer_set_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_SET_PARAM_CMDID); + +/* STA Powersave Mode Cmd */ +#define WMITLV_TABLE_WMI_STA_POWERSAVE_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_powersave_mode_cmd_fixed_param, wmi_sta_powersave_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_POWERSAVE_MODE_CMDID); + +/* STA Powersave Param Cmd */ +#define WMITLV_TABLE_WMI_STA_POWERSAVE_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param, wmi_sta_powersave_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_POWERSAVE_PARAM_CMDID); + +/* STA DTIM PS METHOD Cmd */ +#define WMITLV_TABLE_WMI_STA_DTIM_PS_METHOD_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_dtim_ps_method_cmd_fixed_param, wmi_sta_dtim_ps_method_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_DTIM_PS_METHOD_CMDID); + +/* Pdev Set Reg Domain Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_REGDOMAIN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param, wmi_pdev_set_regdomain_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_REGDOMAIN_CMDID); + + +/* Peer TID ADD BA Cmd */ +#define WMITLV_TABLE_WMI_PEER_TID_ADDBA_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_tid_addba_cmd_fixed_param, wmi_peer_tid_addba_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_TID_ADDBA_CMDID); + +/* Peer TID DEL BA Cmd */ +#define WMITLV_TABLE_WMI_PEER_TID_DELBA_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_tid_delba_cmd_fixed_param, wmi_peer_tid_delba_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_TID_DELBA_CMDID); +/* Peer Req Add BA Ssn for staId/tid pair Cmd */ +#define WMITLV_TABLE_WMI_BA_REQ_SSN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ba_req_ssn_cmd_fixed_param, wmi_ba_req_ssn_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len,WMITLV_TAG_ARRAY_STRUC, wmi_ba_req_ssn, ba_req_ssn_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_BA_REQ_SSN_CMDID); + +/* PDEV FTM integration Cmd */ +#define WMITLV_TABLE_WMI_PDEV_FTM_INTG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ftm_intg_cmd_fixed_param, wmi_ftm_intg_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_FTM_INTG_CMDID); + +/* WOW Wakeup from sleep Cmd */ +#define WMITLV_TABLE_WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param, wmi_wow_hostwakeup_from_sleep_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID); + +/* WOW Enable Cmd */ +#define WMITLV_TABLE_WMI_WOW_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param, wmi_wow_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_ENABLE_CMDID); + +/* WOW ICMPv6 NA filtering command */ +#define WMITLV_TABLE_WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wow_enable_icmpv6_na_flt_cmd_fixed_param, wmi_wow_enable_icmpv6_na_flt_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID); + +/* Remove Bcn Filter Cmd */ +#define WMITLV_TABLE_WMI_RMV_BCN_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param, wmi_rmv_bcn_filter_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_RMV_BCN_FILTER_CMDID); + +/** Service bit WMI_SERVICE_ROAM_OFFLOAD for Roaming feature */ +/* Roam scan mode Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SCAN_MODE(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param, wmi_roam_scan_mode_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, wmi_start_scan_cmd_fixed_param, scan_params, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_roam_offload_tlv_param, offload_param, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_roam_11i_offload_tlv_param, offload_11i_param, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_roam_11r_offload_tlv_param, offload_11r_param, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_roam_ese_offload_tlv_param, offload_ese_param, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SCAN_MODE); + +/* Roam scan Rssi Threshold Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SCAN_RSSI_THRESHOLD(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param, wmi_roam_scan_rssi_threshold_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_roam_scan_extended_threshold_param, extended_param, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_roam_earlystop_rssi_thres_param, earlystop_param, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SCAN_RSSI_THRESHOLD); + +/* Roam Scan Period Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SCAN_PERIOD(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param, wmi_roam_scan_period_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SCAN_PERIOD); + +/* Roam scan change Rssi Threshold Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param, wmi_roam_scan_rssi_change_threshold_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD); +/* Roam Scan Channel list Cmd */ +#define WMITLV_TABLE_WMI_ROAM_CHAN_LIST(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param, wmi_roam_chan_list_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_CHAN_LIST); + +/* Roam scan mode Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SCAN_CMD(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param, wmi_roam_scan_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SCAN_CMD); + + +#define WMITLV_TABLE_WMI_VDEV_PLMREQ_START_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param, wmi_vdev_plmreq_start_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_PLMREQ_START_CMDID); + +#define WMITLV_TABLE_WMI_VDEV_PLMREQ_STOP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param, wmi_vdev_plmreq_stop_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_PLMREQ_STOP_CMDID); + +/* Start scan Cmd */ +#define WMITLV_TABLE_WMI_START_SCAN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, wmi_start_scan_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_ssid, ssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, bssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_START_SCAN_CMDID); + +/* Start ExtScan Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_START_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param, wmi_extscan_start_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_ssid, ssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, bssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_data, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_bucket, bucket_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_bucket_channel, channel_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_START_CMDID); + +/* Stop ExtScan Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_STOP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param, wmi_extscan_stop_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_STOP_CMDID); + +/* Start ExtScan BSSID Monitoring Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param, wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_change_bssid_param, wlan_change_descriptor_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID); + +/* Start Hot List Monitoring Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param, wmi_extscan_configure_hotlist_monitor_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_hotlist_entry, hotlist, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID); + +/* Get ExtScan BSSID/RSSI list Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param, wmi_extscan_get_cached_results_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID); + +/* Get ExtScan BSSID monitor results Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_get_wlan_change_results_cmd_fixed_param, wmi_extscan_get_wlan_change_results_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID); + +/* Set ExtScan Capabilities Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_SET_CAPABILITIES_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_set_capabilities_cmd_fixed_param, wmi_extscan_set_capabilities_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_cache_capabilities, extscan_cache_capabilities, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_change_monitor_capabilities, wlan_change_capabilities, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_hotlist_monitor_capabilities, hotlist_capabilities, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_SET_CAPABILITIES_CMDID); + +/* Get ExtScan Capabilities Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_GET_CAPABILITIES_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param, wmi_extscan_get_capabilities_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_GET_CAPABILITIES_CMDID); + +/* Start SSID Hot List Monitoring Cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param, wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_hotlist_ssid_entry, hotlist_ssid, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID); + +/* P2P set vendor ID data Cmd */ +#define WMITLV_TABLE_WMI_P2P_SET_VENDOR_IE_DATA_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_p2p_set_vendor_ie_data_cmd_fixed_param, wmi_p2p_set_vendor_ie_data_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_P2P_SET_VENDOR_IE_DATA_CMDID); +/* P2P set OppPS parameters Cmd */ +#define WMITLV_TABLE_WMI_P2P_SET_OPPPS_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_p2p_set_oppps_cmd_fixed_param, wmi_p2p_set_oppps_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_P2P_SET_OPPPS_PARAM_CMDID); + +/* Pdev set channel Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_CHANNEL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_channel, wmi_channel, chan, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_CHANNEL_CMDID); + +/* Echo Cmd */ +#define WMITLV_TABLE_WMI_ECHO_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_echo_cmd_fixed_param, wmi_echo_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_ECHO_CMDID); + +/* Pdev set wmm params */ +#define WMITLV_TABLE_WMI_PDEV_SET_WMM_PARAMS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_wmm_params_cmd_fixed_param, wmi_pdev_set_wmm_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wmm_params, wmi_wmm_params, wmm_params_ac_be, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wmm_params, wmi_wmm_params, wmm_params_ac_bk, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wmm_params, wmi_wmm_params, wmm_params_ac_vi, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wmm_params, wmi_wmm_params, wmm_params_ac_vo, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_WMM_PARAMS_CMDID); + +/* Vdev start request Cmd */ +#define WMITLV_TABLE_WMI_VDEV_START_REQUEST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_start_request_cmd_fixed_param, wmi_vdev_start_request_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_channel, wmi_channel, chan, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_p2p_noa_descriptor, noa_descriptors, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_START_REQUEST_CMDID); + +/* Vdev restart request cmd */ +#define WMITLV_TABLE_WMI_VDEV_RESTART_REQUEST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_start_request_cmd_fixed_param, wmi_vdev_start_request_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_channel, wmi_channel, chan, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_p2p_noa_descriptor, noa_descriptors, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_RESTART_REQUEST_CMDID); + +/* P2P Go set beacon IE cmd */ +#define WMITLV_TABLE_WMI_P2P_GO_SET_BEACON_IE(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_p2p_go_set_beacon_ie_fixed_param, wmi_p2p_go_set_beacon_ie_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_P2P_GO_SET_BEACON_IE); + +/* GTK offload Cmd */ +#define WMITLV_TABLE_WMI_GTK_OFFLOAD_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param, WMI_GTK_OFFLOAD_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_GTK_OFFLOAD_CMDID); + +/* PMF 11w offload Set SA query cmd */ +#define WMITLV_TABLE_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param, WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID); + +/* Scan channel list Cmd */ +#define WMITLV_TABLE_WMI_SCAN_CHAN_LIST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_scan_chan_list_cmd_fixed_param, wmi_scan_chan_list_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_channel, chan_info, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_SCAN_CHAN_LIST_CMDID); + +/* STA UAPSD Auto trigger Cmd */ +#define WMITLV_TABLE_WMI_STA_UAPSD_AUTO_TRIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_cmd_fixed_param, wmi_sta_uapsd_auto_trig_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_sta_uapsd_auto_trig_param, ac_param, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_UAPSD_AUTO_TRIG_CMDID); + +/* Probe template Cmd */ +#define WMITLV_TABLE_WMI_PRB_TMPL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_prb_tmpl_cmd_fixed_param, wmi_prb_tmpl_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_bcn_prb_info, wmi_bcn_prb_info, bcn_prb_info, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_PRB_TMPL_CMDID); + +/* Beacon template Cmd */ +#define WMITLV_TABLE_WMI_BCN_TMPL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_bcn_tmpl_cmd_fixed_param, wmi_bcn_tmpl_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_bcn_prb_info, wmi_bcn_prb_info, bcn_prb_info, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_BCN_TMPL_CMDID); + +/* VDEV install key complete Cmd */ +#define WMITLV_TABLE_WMI_VDEV_INSTALL_KEY_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_install_key_cmd_fixed_param, wmi_vdev_install_key_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, key_data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_INSTALL_KEY_CMDID); +/* VDEV WNM SLEEP MODE Cmd */ +#define WMITLV_TABLE_WMI_VDEV_WNM_SLEEPMODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_VDEV_WNM_SLEEPMODE_CMD_fixed_param, WMI_VDEV_WNM_SLEEPMODE_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_WNM_SLEEPMODE_CMDID); + +#define WMITLV_TABLE_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param, WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID); + +/* Peer Assoc Cmd */ +#define WMITLV_TABLE_WMI_PEER_ASSOC_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_assoc_complete_cmd_fixed_param, wmi_peer_assoc_complete_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, peer_legacy_rates, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, peer_ht_rates, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vht_rate_set, wmi_vht_rate_set, peer_vht_rates, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_ASSOC_CMDID); + +/* Peer Set Rate Report Condition Cmd */ +#define WMITLV_TABLE_WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_set_rate_report_condition_fixed_param, wmi_peer_set_rate_report_condition_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID); + + +/* Add Beacon filter Cmd */ +#define WMITLV_TABLE_WMI_ADD_BCN_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param, wmi_add_bcn_filter_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, ie_map, WMITLV_SIZE_FIX, BCN_FLT_MAX_ELEMS_IE_LIST) + +WMITLV_CREATE_PARAM_STRUC(WMI_ADD_BCN_FILTER_CMDID); + +/* Sta keepalive cmd */ +#define WMITLV_TABLE_WMI_STA_KEEPALIVE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_STA_KEEPALIVE_CMD_fixed_param, WMI_STA_KEEPALIVE_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_STA_KEEPALVE_ARP_RESPONSE, WMI_STA_KEEPALVE_ARP_RESPONSE, arp_resp, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_KEEPALIVE_CMDID); + +/* ARP NS offload Cmd */ +#define WMITLV_TABLE_WMI_SET_ARP_NS_OFFLOAD_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param, WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_NS_OFFLOAD_TUPLE, ns_tuples, WMITLV_SIZE_FIX, WMI_MAX_NS_OFFLOADS) \ + WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_ARP_OFFLOAD_TUPLE, arp_tuples, WMITLV_SIZE_FIX, WMI_MAX_ARP_OFFLOADS) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_NS_OFFLOAD_TUPLE, ns_ext_tuples, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_SET_ARP_NS_OFFLOAD_CMDID); + +/* AP PS peer param Cmd */ +#define WMITLV_TABLE_WMI_AP_PS_PEER_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ap_ps_peer_cmd_fixed_param, wmi_ap_ps_peer_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_AP_PS_PEER_PARAM_CMDID); + +/* AP PS enhanced green ap param Cmd */ +#define WMITLV_TABLE_WMI_AP_PS_EGAP_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len,\ + WMITLV_TAG_STRUC_wmi_ap_ps_egap_param_cmd_fixed_param,\ + wmi_ap_ps_egap_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_AP_PS_EGAP_PARAM_CMDID); + +/* Profile Trigger Cmd */ +#define WMITLV_TABLE_WMI_WLAN_PROFILE_TRIGGER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param, wmi_wlan_profile_trigger_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_PROFILE_TRIGGER_CMDID); + +/* WLAN Profile set hist interval Cmd */ +#define WMITLV_TABLE_WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param, wmi_wlan_profile_set_hist_intvl_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID); + +/* WLAN Profile get profile data Cmd */ +#define WMITLV_TABLE_WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param, wmi_wlan_profile_get_prof_data_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID); + +/* WLAN Profile enable profile ID Cmd */ +#define WMITLV_TABLE_WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param, wmi_wlan_profile_enable_profile_id_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID); + +/* WOW Delete Wake Pattern Cmd */ +#define WMITLV_TABLE_WMI_WOW_DEL_WAKE_PATTERN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param, WMI_WOW_DEL_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_DEL_WAKE_PATTERN_CMDID); + +#define WMITLV_TABLE_WMI_WOW_UDP_SVC_OFLD_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param, WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, pattern, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, response, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_UDP_SVC_OFLD_CMDID); + +#define WMITLV_TABLE_WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len,\ + WMITLV_TAG_STRUC_wmi_wow_hostwakeup_gpio_pin_pattern_config_cmd_fixed_param,\ + WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMD_fixed_param, fixed_param,\ + WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID); + +/* Wow enable/disable wake up Cmd */ +#define WMITLV_TABLE_WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param, WMI_WOW_ADD_DEL_EVT_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID); + +/* RTT measurement request Cmd */ +#define WMITLV_TABLE_WMI_RTT_MEASREQ_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_RTT_MEASREQ_CMDID); + +/* RTT TSF Cmd */ +#define WMITLV_TABLE_WMI_RTT_TSF_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_RTT_TSF_CMDID); + +/*RTT OEM req Cmd - DEPRECATED */ +#define WMITLV_TABLE_WMI_OEM_REQ_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_OEM_REQ_CMDID); + +/* RTT OEM request Cmd */ +#define WMITLV_TABLE_WMI_OEM_REQUEST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_OEM_REQUEST_CMDID); + +/* Spectral scan configure Cmd */ +#define WMITLV_TABLE_WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_spectral_configure_cmd_fixed_param, wmi_vdev_spectral_configure_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID); + +/* Spectral scan enable Cmd */ +#define WMITLV_TABLE_WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_spectral_enable_cmd_fixed_param, wmi_vdev_spectral_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID); + +/* Request stats Cmd */ +#define WMITLV_TABLE_WMI_REQUEST_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, wmi_request_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_REQUEST_STATS_CMDID); + + +/* Request for memory dump stats Cmd */ +#define WMITLV_TABLE_WMI_GET_FW_MEM_DUMP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param, wmi_get_fw_mem_dump_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_fw_mem_dump, fw_mem_dump_params, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_GET_FW_MEM_DUMP_CMDID); + +/* flush debug messages */ +#define WMITLV_TABLE_WMI_DEBUG_MESG_FLUSH_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_debug_mesg_flush_fixed_param, wmi_debug_mesg_flush_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_DEBUG_MESG_FLUSH_CMDID); + +/* Request to config the DIAG Events and LOGs*/ +#define WMITLV_TABLE_WMI_DIAG_EVENT_LOG_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_diag_event_log_config_fixed_param, wmi_diag_event_log_config_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, diag_events_logs_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_DIAG_EVENT_LOG_CONFIG_CMDID); + +/* Set config params */ +#define WMITLV_TABLE_WMI_START_LINK_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_start_link_stats_cmd_fixed_param, wmi_start_link_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_START_LINK_STATS_CMDID); + +/* Request to clear link stats */ +#define WMITLV_TABLE_WMI_CLEAR_LINK_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_clear_link_stats_cmd_fixed_param, wmi_clear_link_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_CLEAR_LINK_STATS_CMDID); + +/* Request Link stats Cmd */ +#define WMITLV_TABLE_WMI_REQUEST_LINK_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_request_link_stats_cmd_fixed_param, wmi_request_link_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_REQUEST_LINK_STATS_CMDID); + +/* Network list offload config Cmd */ +#define WMITLV_TABLE_WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param, wmi_nlo_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, nlo_configured_parameters, nlo_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, nlo_channel_prediction_cfg, channel_prediction_param, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); + +/* Passpoint list offload config Cmd */ +#define WMITLV_TABLE_WMI_PASSPOINT_LIST_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param, wmi_passpoint_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PASSPOINT_LIST_CONFIG_CMDID); + +/* CSA offload enable Cmd */ +#define WMITLV_TABLE_WMI_CSA_OFFLOAD_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_csa_offload_enable_cmd_fixed_param, wmi_csa_offload_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_CSA_OFFLOAD_ENABLE_CMDID); + +/* CSA offload channel switch Cmd */ +#define WMITLV_TABLE_WMI_CSA_OFFLOAD_CHANSWITCH_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_csa_offload_chanswitch_cmd_fixed_param, wmi_csa_offload_chanswitch_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_channel, wmi_channel, chan, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_CSA_OFFLOAD_CHANSWITCH_CMDID); + +/* Chatter set mode Cmd */ +#define WMITLV_TABLE_WMI_CHATTER_SET_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_chatter_set_mode_cmd_fixed_param, wmi_chatter_set_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_CHATTER_SET_MODE_CMDID); + + +/* PDEV UTF Cmd */ +#define WMITLV_TABLE_WMI_PDEV_UTF_CMDID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_UTF_CMDID); + +/* PDEV QVIT Cmd */ +#define WMITLV_TABLE_WMI_PDEV_QVIT_CMDID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_QVIT_CMDID); + +/* Vdev Set keep alive Cmd */ +#define WMITLV_TABLE_WMI_VDEV_SET_KEEPALIVE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_set_keepalive_cmd_fixed_param, wmi_vdev_set_keepalive_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SET_KEEPALIVE_CMDID); + +/* Vdev Get keep alive Cmd */ +#define WMITLV_TABLE_WMI_VDEV_GET_KEEPALIVE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_get_keepalive_cmd_fixed_param, wmi_vdev_get_keepalive_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_GET_KEEPALIVE_CMDID); +/*FWTEST Set TBTT mode Cmd*/ +#define WMITLV_TABLE_WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_mcc_set_tbtt_mode_cmd_fixed_param, wmi_vdev_mcc_set_tbtt_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID); + +/* FWTEST set NoA parameters Cmd */ +#define WMITLV_TABLE_WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_p2p_set_noa_cmd_fixed_param, wmi_p2p_set_noa_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_p2p_noa_descriptor, noa_descriptor, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID); + +/* Unit test FW */ +#define WMITLV_TABLE_WMI_UNIT_TEST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_unit_test_cmd_fixed_param, wmi_unit_test_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, args, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_UNIT_TEST_CMDID); + +/* Force Fw Hang Cmd */ +#define WMITLV_TABLE_WMI_FORCE_FW_HANG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_FORCE_FW_HANG_CMD_fixed_param, WMI_FORCE_FW_HANG_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_FORCE_FW_HANG_CMDID); +/* Set Mcast address Cmd */ +#define WMITLV_TABLE_WMI_SET_MCASTBCAST_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param, WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SET_MCASTBCAST_FILTER_CMDID); + +/* GPIO config Cmd */ +#define WMITLV_TABLE_WMI_GPIO_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_gpio_config_cmd_fixed_param, wmi_gpio_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_GPIO_CONFIG_CMDID); + +/* GPIO output Cmd */ +#define WMITLV_TABLE_WMI_GPIO_OUTPUT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_gpio_output_cmd_fixed_param, wmi_gpio_output_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_GPIO_OUTPUT_CMDID); + +/* Peer add WDA entry Cmd */ +#define WMITLV_TABLE_WMI_PEER_ADD_WDS_ENTRY_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_add_wds_entry_cmd_fixed_param, wmi_peer_add_wds_entry_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_ADD_WDS_ENTRY_CMDID); + +/*Peer remove WDS entry Cmd */ +#define WMITLV_TABLE_WMI_PEER_REMOVE_WDS_ENTRY_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_remove_wds_entry_cmd_fixed_param, wmi_peer_remove_wds_entry_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_REMOVE_WDS_ENTRY_CMDID); + +/* Beacon tx Cmd */ +#define WMITLV_TABLE_WMI_BCN_TX_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_bcn_tx_hdr, wmi_bcn_tx_hdr, hdr, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_BCN_TX_CMDID); + +/* PDEV send Beacon Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SEND_BCN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param, wmi_bcn_send_from_host_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SEND_BCN_CMDID); + +/* Management tx Cmd */ +#define WMITLV_TABLE_WMI_MGMT_TX_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mgmt_tx_hdr, wmi_mgmt_tx_hdr, hdr, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_MGMT_TX_CMDID); + +/* Management tx send cmd */ +#define WMITLV_TABLE_WMI_MGMT_TX_SEND_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mgmt_tx_send_cmd_fixed_param, wmi_mgmt_tx_send_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_MGMT_TX_SEND_CMDID); + +/* ADD clear response Cmd */ +#define WMITLV_TABLE_WMI_ADDBA_CLEAR_RESP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_addba_clear_resp_cmd_fixed_param, wmi_addba_clear_resp_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ADDBA_CLEAR_RESP_CMDID); + +/* ADD BA send Cmd */ +#define WMITLV_TABLE_WMI_ADDBA_SEND_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_addba_send_cmd_fixed_param, wmi_addba_send_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ADDBA_SEND_CMDID); + +/* DEL BA send Cmd */ +#define WMITLV_TABLE_WMI_DELBA_SEND_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_delba_send_cmd_fixed_param, wmi_delba_send_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_DELBA_SEND_CMDID); + +/* ADD BA set response Cmd */ +#define WMITLV_TABLE_WMI_ADDBA_SET_RESP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_addba_setresponse_cmd_fixed_param, wmi_addba_setresponse_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ADDBA_SET_RESP_CMDID); + +/* Send single AMSDU Cmd */ +#define WMITLV_TABLE_WMI_SEND_SINGLEAMSDU_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_send_singleamsdu_cmd_fixed_param, wmi_send_singleamsdu_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_SEND_SINGLEAMSDU_CMDID); + +/* PDev Packet Log enable Cmd */ +#define WMITLV_TABLE_WMI_PDEV_PKTLOG_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param, wmi_pdev_pktlog_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_PKTLOG_ENABLE_CMDID); + +/* PDev Packet Log disable Cmd */ +#define WMITLV_TABLE_WMI_PDEV_PKTLOG_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param, wmi_pdev_pktlog_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_PKTLOG_DISABLE_CMDID); + +/* PDev set HT Cap IE Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_HT_CAP_IE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param, wmi_pdev_set_ht_ie_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_HT_CAP_IE_CMDID); + +/* PDev set VHT Cap IE Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_VHT_CAP_IE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param, wmi_pdev_set_vht_ie_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_VHT_CAP_IE_CMDID); + +/* PDev Set DSCP to TID map Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_DSCP_TID_MAP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_dscp_tid_map_cmd_fixed_param, wmi_pdev_set_dscp_tid_map_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_DSCP_TID_MAP_CMDID); + +/* PDev Green AP PS enable Cmd */ +#define WMITLV_TABLE_WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_green_ap_ps_enable_cmd_fixed_param, wmi_pdev_green_ap_ps_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID); + +/* PDEV Get TPC Config Cmd */ +#define WMITLV_TABLE_WMI_PDEV_GET_TPC_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_get_tpc_config_cmd_fixed_param, wmi_pdev_get_tpc_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_GET_TPC_CONFIG_CMDID); + +/* PDEV Set Base Mac Address Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_BASE_MACADDR_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_base_macaddr_cmd_fixed_param, wmi_pdev_set_base_macaddr_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_BASE_MACADDR_CMDID); + +/* Peer multicast group Cmd */ +#define WMITLV_TABLE_WMI_PEER_MCAST_GROUP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_mcast_group_cmd_fixed_param, wmi_peer_mcast_group_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_MCAST_GROUP_CMDID); + +/* Roam AP profile Cmd */ +#define WMITLV_TABLE_WMI_ROAM_AP_PROFILE(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param, wmi_roam_ap_profile_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ap_profile, wmi_ap_profile, ap_profile, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_AP_PROFILE); + +/* Roam sync complete Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SYNCH_COMPLETE(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param, wmi_roam_synch_complete_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SYNCH_COMPLETE); + +#define WMITLV_TABLE_WMI_ROAM_SET_RIC_REQUEST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ric_request_fixed_param, wmi_ric_request_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_ric_tspec, ric_tspec_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SET_RIC_REQUEST_CMDID); + +/* Scan scheduler priority Table Cmd */ +#define WMITLV_TABLE_WMI_SCAN_SCH_PRIO_TBL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_scan_sch_priority_table_cmd_fixed_param, wmi_scan_sch_priority_table_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, mapping_table, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_SCAN_SCH_PRIO_TBL_CMDID); + +/* PDEV DFS enable Cmd */ +#define WMITLV_TABLE_WMI_PDEV_DFS_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_dfs_enable_cmd_fixed_param, wmi_pdev_dfs_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_DFS_ENABLE_CMDID); + +/* PDEV DFS disable Cmd */ +#define WMITLV_TABLE_WMI_PDEV_DFS_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_dfs_disable_cmd_fixed_param, wmi_pdev_dfs_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_DFS_DISABLE_CMDID); + +/* DFS phyerr parse/filter offload enable Cmd */ +#define WMITLV_TABLE_WMI_DFS_PHYERR_FILTER_ENA_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_ena_cmd_fixed_param, wmi_dfs_phyerr_filter_ena_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_DFS_PHYERR_FILTER_ENA_CMDID); + +/* DFS phyerr parse/filter offload disable Cmd */ +#define WMITLV_TABLE_WMI_DFS_PHYERR_FILTER_DIS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_dis_cmd_fixed_param, wmi_dfs_phyerr_filter_dis_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_DFS_PHYERR_FILTER_DIS_CMDID); + +/* WOW Add Wake Pattern Cmd */ +#define WMITLV_TABLE_WMI_WOW_ADD_WAKE_PATTERN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param, WMI_WOW_ADD_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_BITMAP_PATTERN_T, pattern_info_bitmap, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_IPV4_SYNC_PATTERN_T, pattern_info_ipv4, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_IPV6_SYNC_PATTERN_T, pattern_info_ipv6, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_MAGIC_PATTERN_CMD, pattern_info_magic_pattern, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, pattern_info_timeout, WMITLV_SIZE_VAR) \ + WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, ra_ratelimit_interval, WMITLV_SIZE_FIX, 1) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_ADD_WAKE_PATTERN_CMDID); + +/* IOAC add keep alive cmd. */ +#define WMITLV_TABLE_WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_IOAC_ADD_KEEPALIVE_CMD_fixed_param, WMI_WOW_IOAC_ADD_KEEPALIVE_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_WOW_IOAC_KEEPALIVE_T, keepalive_set, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID); + +/* IOAC del keep alive cmd. */ +#define WMITLV_TABLE_WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_IOAC_DEL_KEEPALIVE_CMD_fixed_param, WMI_WOW_IOAC_DEL_KEEPALIVE_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID); + +/* WOW IOAC Add Wake Pattern Cmd */ +#define WMITLV_TABLE_WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_IOAC_ADD_PATTERN_CMD_fixed_param, WMI_WOW_IOAC_ADD_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_IOAC_PKT_PATTERN_T, pattern_info_pkt, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_IOAC_TMR_PATTERN_T, pattern_info_tmr, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_IOAC_SOCK_PATTERN_T, pattern_info_sock, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID); + +/* WOW IOAC Delete Wake Pattern Cmd */ +#define WMITLV_TABLE_WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_WOW_IOAC_DEL_PATTERN_CMD_fixed_param, WMI_WOW_IOAC_DEL_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID); + +/* extwow enable Cmd */ +#define WMITLV_TABLE_WMI_EXTWOW_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param, wmi_extwow_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTWOW_ENABLE_CMDID); + +/* extwow set wakeup params cmd for app type1 */ +#define WMITLV_TABLE_WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param, wmi_extwow_set_app_type1_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID); + +/* extwow set wakeup params cmd for app type2 */ +#define WMITLV_TABLE_WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param, wmi_extwow_set_app_type2_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID); + +/* Stop scan Cmd */ +#define WMITLV_TABLE_WMI_STOP_SCAN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param, wmi_stop_scan_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STOP_SCAN_CMDID); + +#define WMITLV_TABLE_WMI_PDEV_SET_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param, wmi_pdev_set_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_PARAM_CMDID); + +/* PDev set quiet Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_QUIET_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_quiet_cmd_fixed_param, wmi_pdev_set_quiet_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_QUIET_MODE_CMDID); + +/* Vdev create Cmd */ +#define WMITLV_TABLE_WMI_VDEV_CREATE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_create_cmd_fixed_param, wmi_vdev_create_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_vdev_txrx_streams, cfg_txrx_streams, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_CREATE_CMDID); + +/* Vdev delete Cmd */ +#define WMITLV_TABLE_WMI_VDEV_DELETE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_delete_cmd_fixed_param, wmi_vdev_delete_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_DELETE_CMDID); + +/* Vdev up Cmd */ +#define WMITLV_TABLE_WMI_VDEV_UP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_up_cmd_fixed_param, wmi_vdev_up_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_UP_CMDID); + +/* Vdev stop cmd */ +#define WMITLV_TABLE_WMI_VDEV_STOP_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_stop_cmd_fixed_param, wmi_vdev_stop_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_STOP_CMDID); + +/* Vdev down Cmd */ +#define WMITLV_TABLE_WMI_VDEV_DOWN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_down_cmd_fixed_param, wmi_vdev_down_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_DOWN_CMDID); + +/* Vdev set param Cmd */ +#define WMITLV_TABLE_WMI_VDEV_SET_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_set_param_cmd_fixed_param, wmi_vdev_set_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SET_PARAM_CMDID); + +/* Pdev suspend Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SUSPEND_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param, wmi_pdev_suspend_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SUSPEND_CMDID); + +/* Pdev Resume Cmd */ +#define WMITLV_TABLE_WMI_PDEV_RESUME_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param, wmi_pdev_resume_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_RESUME_CMDID); + +#define WMITLV_TABLE_WMI_SCAN_UPDATE_REQUEST_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_scan_update_request_cmd_fixed_param, wmi_scan_update_request_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_SCAN_UPDATE_REQUEST_CMDID); + +#define WMITLV_TABLE_WMI_SCAN_PROB_REQ_OUI_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_scan_prob_req_oui_cmd_fixed_param, wmi_scan_prob_req_oui_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_SCAN_PROB_REQ_OUI_CMDID); + +#define WMITLV_TABLE_WMI_CHATTER_ADD_COALESCING_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len,WMITLV_TAG_STRUC_wmi_chatter_coalescing_add_filter_cmd_fixed_param, wmi_chatter_coalescing_add_filter_cmd_fixed_param, fixed_param,WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, chatter_pkt_coalescing_filter, coalescing_filter, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_CHATTER_ADD_COALESCING_FILTER_CMDID); + +#define WMITLV_TABLE_WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_chatter_coalescing_delete_filter_cmd_fixed_param,wmi_chatter_coalescing_delete_filter_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + +WMITLV_CREATE_PARAM_STRUC(WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID); + +#define WMITLV_TABLE_WMI_CHATTER_COALESCING_QUERY_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_chatter_coalescing_query_cmd_fixed_param, wmi_chatter_coalescing_query_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + +WMITLV_CREATE_PARAM_STRUC(WMI_CHATTER_COALESCING_QUERY_CMDID); + +#define WMITLV_TABLE_WMI_TXBF_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len,WMITLV_TAG_STRUC_wmi_txbf_cmd_fixed_param, wmi_txbf_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + +WMITLV_CREATE_PARAM_STRUC(WMI_TXBF_CMDID); + +#define WMITLV_TABLE_WMI_DBGLOG_CFG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_debug_log_config_cmd_fixed_param, wmi_debug_log_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_FXAR(id,op,buf,len,WMITLV_TAG_ARRAY_UINT32, A_UINT32, module_id_bitmap, WMITLV_SIZE_FIX, MAX_MODULE_ID_BITMAP_WORDS) \ + +WMITLV_CREATE_PARAM_STRUC(WMI_DBGLOG_CFG_CMDID); + +#define WMITLV_TABLE_WMI_VDEV_WMM_ADDTS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param, wmi_vdev_wmm_addts_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_WMM_ADDTS_CMDID); + +#define WMITLV_TABLE_WMI_VDEV_WMM_DELTS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param, wmi_vdev_wmm_delts_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_WMM_DELTS_CMDID); + +#define WMITLV_TABLE_WMI_VDEV_SET_WMM_PARAMS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_set_wmm_params_cmd_fixed_param, wmi_vdev_set_wmm_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SET_WMM_PARAMS_CMDID); + +#define WMITLV_TABLE_WMI_VDEV_SET_GTX_PARAMS_CMDID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_set_gtx_params_cmd_fixed_param, wmi_vdev_set_gtx_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SET_GTX_PARAMS_CMDID); + +/* TDLS Enable/Disable Cmd */ +#define WMITLV_TABLE_WMI_TDLS_SET_STATE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param, \ + wmi_tdls_set_state_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_TDLS_SET_STATE_CMDID); + +/* TDLS Peer Update Cmd */ +#define WMITLV_TABLE_WMI_TDLS_PEER_UPDATE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param, wmi_tdls_peer_update_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities, wmi_tdls_peer_capabilities, peer_caps, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_channel, peer_chan_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_TDLS_PEER_UPDATE_CMDID); + +/* Enable/Disable TDLS Offchannel Cmd */ +#define WMITLV_TABLE_WMI_TDLS_SET_OFFCHAN_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param, \ + wmi_tdls_set_offchan_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_TDLS_SET_OFFCHAN_MODE_CMDID); + +/* Resmgr Enable/Disable Adaptive OCS CMD */ +#define WMITLV_TABLE_WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param, \ + wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID); + +/* Resmgr Set Channel Time Quota CMD */ +#define WMITLV_TABLE_WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_resmgr_set_chan_time_quota_cmd_fixed_param, \ + wmi_resmgr_set_chan_time_quota_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID); + +/* Resmgr Set Channel Latency CMD */ +#define WMITLV_TABLE_WMI_RESMGR_SET_CHAN_LATENCY_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_resmgr_set_chan_latency_cmd_fixed_param, \ + wmi_resmgr_set_chan_latency_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_RESMGR_SET_CHAN_LATENCY_CMDID); + +/* STA SMPS Force Mode CMD */ +#define WMITLV_TABLE_WMI_STA_SMPS_FORCE_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_cmd_fixed_param, \ + wmi_sta_smps_force_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_SMPS_FORCE_MODE_CMDID); + +/* wlan hb enable/disable CMD */ +#define WMITLV_TABLE_WMI_HB_SET_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param, \ + wmi_hb_set_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_HB_SET_ENABLE_CMDID); + +/* wlan hb set tcp params CMD */ +#define WMITLV_TABLE_WMI_HB_SET_TCP_PARAMS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param, \ + wmi_hb_set_tcp_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_HB_SET_TCP_PARAMS_CMDID); + +/* wlan hb set tcp pkt filter CMD */ +#define WMITLV_TABLE_WMI_HB_SET_TCP_PKT_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param, \ + wmi_hb_set_tcp_pkt_filter_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_HB_SET_TCP_PKT_FILTER_CMDID); + +/* wlan set udp params CMD */ +#define WMITLV_TABLE_WMI_HB_SET_UDP_PARAMS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param, \ + wmi_hb_set_udp_params_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_HB_SET_UDP_PARAMS_CMDID); + +/* wlan hb set udp pkt filter CMD */ +#define WMITLV_TABLE_WMI_HB_SET_UDP_PKT_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param, \ + wmi_hb_set_udp_pkt_filter_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_HB_SET_UDP_PKT_FILTER_CMDID); + +/* STA SMPS Param CMD */ +#define WMITLV_TABLE_WMI_STA_SMPS_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_smps_param_cmd_fixed_param, \ + wmi_sta_smps_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_STA_SMPS_PARAM_CMDID); + +/* MCC Adaptive Scheduler Traffic Stats */ +#define WMITLV_TABLE_WMI_MCC_SCHED_TRAFFIC_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mcc_sched_traffic_stats_cmd_fixed_param, wmi_mcc_sched_traffic_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_STRUC, wmi_mcc_sched_sta_traffic_stats, mcc_sched_sta_traffic_stats_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_MCC_SCHED_TRAFFIC_STATS_CMDID); + +#define WMITLV_TABLE_WMI_BATCH_SCAN_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_batch_scan_enable_cmd_fixed_param, wmi_batch_scan_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_BATCH_SCAN_ENABLE_CMDID); + +#define WMITLV_TABLE_WMI_PEER_INFO_REQ_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param, \ + wmi_peer_info_req_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_INFO_REQ_CMDID); + +#define WMITLV_TABLE_WMI_RMC_SET_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param, \ + wmi_rmc_set_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_RMC_SET_MODE_CMDID); + +#define WMITLV_TABLE_WMI_RMC_SET_ACTION_PERIOD_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param, \ + wmi_rmc_set_action_period_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_RMC_SET_ACTION_PERIOD_CMDID); + +#define WMITLV_TABLE_WMI_RMC_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_rmc_config_cmd_fixed_param, \ + wmi_rmc_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_RMC_CONFIG_CMDID); + +#define WMITLV_TABLE_WMI_MHF_OFFLOAD_SET_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mhf_offload_set_mode_cmd_fixed_param, \ + wmi_mhf_offload_set_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_MHF_OFFLOAD_SET_MODE_CMDID); + +#define WMITLV_TABLE_WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mhf_offload_plumb_routing_table_cmd_fixed_param, \ + wmi_mhf_offload_plumb_routing_table_cmd, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_mhf_offload_routing_table_entry, \ + routing_tbl_entries, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID) + +#define WMITLV_TABLE_WMI_BATCH_SCAN_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_batch_scan_disable_cmd_fixed_param, wmi_batch_scan_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_BATCH_SCAN_DISABLE_CMDID); + +#define WMITLV_TABLE_WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_batch_scan_trigger_result_cmd_fixed_param, wmi_batch_scan_trigger_result_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID); + +/* LPI mgmt snooping config Cmd */ +#define WMITLV_TABLE_WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lpi_mgmt_snooping_config_cmd_fixed_param, wmi_lpi_mgmt_snooping_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID); + +/* LPI start scan Cmd */ +#define WMITLV_TABLE_WMI_LPI_START_SCAN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lpi_start_scan_cmd_fixed_param, wmi_lpi_start_scan_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_ssid, ssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, bssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_data, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_LPI_START_SCAN_CMDID); + +/* LPI stop scan Cmd */ +#define WMITLV_TABLE_WMI_LPI_STOP_SCAN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lpi_stop_scan_cmd_fixed_param, wmi_lpi_stop_scan_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_LPI_STOP_SCAN_CMDID); + +#define WMITLV_TABLE_WMI_LPI_RESULT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lpi_result_event_fixed_param, wmi_lpi_result_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_LPI_RESULT_EVENTID); + +/* LPI Status Event */ +#define WMITLV_TABLE_WMI_LPI_STATUS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lpi_status_event_fixed_param, wmi_lpi_status_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_LPI_STATUS_EVENTID); + +/* LPI Handoff Event */ +#define WMITLV_TABLE_WMI_LPI_HANDOFF_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lpi_handoff_event_fixed_param, wmi_lpi_handoff_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_LPI_HANDOFF_EVENTID); + +/* Thermal Manager Params*/ +#define WMITLV_TABLE_WMI_THERMAL_MGMT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_thermal_mgmt_cmd_fixed_param, wmi_thermal_mgmt_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_THERMAL_MGMT_CMDID); + +#define WMITLV_TABLE_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, pattern, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID); + +#define WMITLV_TABLE_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID); + +/* NaN Request */ +#define WMITLV_TABLE_WMI_NAN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nan_cmd_param, wmi_nan_cmd_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_NAN_CMDID); + +/* Modem power state cmd */ +#define WMITLV_TABLE_WMI_MODEM_POWER_STATE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param, wmi_modem_power_state_cmd_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MODEM_POWER_STATE_CMDID); + +/* get estimated link speed cmd */ +#define WMITLV_TABLE_WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_get_estimated_linkspeed_cmd_fixed_param, wmi_peer_get_estimated_linkspeed_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID); + +/* ext stats Request */ +#define WMITLV_TABLE_WMI_REQUEST_STATS_EXT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_req_stats_ext_cmd_fixed_param, wmi_req_stats_ext_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_REQUEST_STATS_EXT_CMDID); + +/* 2.4Ghz HT40 OBSS scan enable */ +#define WMITLV_TABLE_WMI_OBSS_SCAN_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_obss_scan_enable_cmd_fixed_param, wmi_obss_scan_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, channels, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_field, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OBSS_SCAN_ENABLE_CMDID); + +/* 2.4Ghz HT40 OBSS scan disable */ +#define WMITLV_TABLE_WMI_OBSS_SCAN_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_obss_scan_disable_cmd_fixed_param, wmi_obss_scan_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OBSS_SCAN_DISABLE_CMDID); + +/* Pdev Set LED Config Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_LED_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_set_led_config_cmd_fixed_param, wmi_pdev_set_led_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_LED_CONFIG_CMDID); + +/* host auto shut down config cmd */ +#define WMITLV_TABLE_WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param, wmi_host_auto_shutdown_cfg_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID); + +/* tpc chainmask config cmd */ +#define WMITLV_TABLE_WMI_TPC_CHAINMASK_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tpc_chainmask_config_cmd_fixed_param, wmi_tpc_chainmask_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_tpc_chainmask_config, config_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_TPC_CHAINMASK_CONFIG_CMDID); + +/* Ch avoidance update cmd */ +#define WMITLV_TABLE_WMI_CHAN_AVOID_UPDATE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param, wmi_chan_avoid_update_cmd_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_CHAN_AVOID_UPDATE_CMDID); + +/* D0-WOW Enable Disable Cmd */ +#define WMITLV_TABLE_WMI_D0_WOW_ENABLE_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param, wmi_d0_wow_enable_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_D0_WOW_ENABLE_DISABLE_CMDID); + +/* Pdev get chip temperature Cmd */ +#define WMITLV_TABLE_WMI_PDEV_GET_TEMPERATURE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_get_temperature_cmd_fixed_param, wmi_pdev_get_temperature_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_GET_TEMPERATURE_CMDID); + +/* Set antenna diversity Cmd */ +#define WMITLV_TABLE_WMI_SET_ANTENNA_DIVERSITY_CMDID(id,op,buf,len) \ +WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_pdev_set_antenna_diversity_cmd_fixed_param, wmi_pdev_set_antenna_diversity_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SET_ANTENNA_DIVERSITY_CMDID); + +/* Set rssi monitoring config Cmd */ +#define WMITLV_TABLE_WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID(id,op,buf,len) \ +WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param, wmi_rssi_breach_monitor_config_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID); + +/* DHCP server offload param Cmd */ +#define WMITLV_TABLE_WMI_SET_DHCP_SERVER_OFFLOAD_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param, wmi_set_dhcp_server_offload_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SET_DHCP_SERVER_OFFLOAD_CMDID); + +/* IPA Offload Enable Disable Cmd */ +#define WMITLV_TABLE_WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUCT_wmi_ipa_offload_enable_disable_cmd_fixed_param, wmi_ipa_offload_enable_disable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID); + +/* Set LED flashing parameter Cmd */ +#define WMITLV_TABLE_WMI_PDEV_SET_LED_FLASHING_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param, wmi_set_led_flashing_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_SET_LED_FLASHING_CMDID); + +/* mDNS responder offload param Cmd */ +#define WMITLV_TABLE_WMI_MDNS_OFFLOAD_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mdns_offload_cmd_fixed_param, wmi_mdns_offload_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MDNS_OFFLOAD_ENABLE_CMDID); + +#define WMITLV_TABLE_WMI_MDNS_SET_FQDN_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mdns_set_fqdn_cmd_fixed_param, wmi_mdns_set_fqdn_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, fqdn_data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_MDNS_SET_FQDN_CMDID); + +#define WMITLV_TABLE_WMI_MDNS_SET_RESPONSE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mdns_set_resp_cmd_fixed_param, wmi_mdns_set_resp_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, resp_data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_MDNS_SET_RESPONSE_CMDID); + +#define WMITLV_TABLE_WMI_MDNS_GET_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mdns_get_stats_cmd_fixed_param, wmi_mdns_get_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MDNS_GET_STATS_CMDID); + +/* roam invoke Cmd */ +#define WMITLV_TABLE_WMI_ROAM_INVOKE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param, wmi_roam_invoke_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, bssid_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_INVOKE_CMDID); + +/* SAP Authentication offload param Cmd */ +#define WMITLV_TABLE_WMI_SAP_OFL_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sap_ofl_enable_cmd_fixed_param, wmi_sap_ofl_enable_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, psk, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_SAP_OFL_ENABLE_CMDID); + +/* SAP set blacklist param cmd */ +#define WMITLV_TABLE_WMI_SAP_SET_BLACKLIST_PARAM_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sap_set_blacklist_param_cmd_fixed_param, wmi_sap_set_blacklist_param_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SAP_SET_BLACKLIST_PARAM_CMDID); + +/* APFIND Request */ +#define WMITLV_TABLE_WMI_APFIND_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_apfind_cmd_param, wmi_apfind_cmd_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_APFIND_CMDID); + +/* Set OCB schedule cmd, DEPRECATED */ +#define WMITLV_TABLE_WMI_OCB_SET_SCHED_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param, wmi_ocb_set_sched_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_SCHED_CMDID); + +/* Set OCB configuration cmd */ +#define WMITLV_TABLE_WMI_OCB_SET_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_set_config_cmd_fixed_param, wmi_ocb_set_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_channel, chan_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_ocb_channel, ocb_chan_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_qos_parameter, qos_parameter_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_ndl_chan, chan_cfg, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_ndl_active_state_config, ndl_active_state_config_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_ocb_schedule_element, schedule_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_CONFIG_CMDID); + +/* Set UTC time cmd */ +#define WMITLV_TABLE_WMI_OCB_SET_UTC_TIME_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_set_utc_time_cmd_fixed_param, wmi_ocb_set_utc_time_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_UTC_TIME_CMDID); + +/* Start timing advertisement cmd */ +#define WMITLV_TABLE_WMI_OCB_START_TIMING_ADVERT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_start_timing_advert_cmd_fixed_param, wmi_ocb_start_timing_advert_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_START_TIMING_ADVERT_CMDID); + +/* Stop timing advertisement cmd */ +#define WMITLV_TABLE_WMI_OCB_STOP_TIMING_ADVERT_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_stop_timing_advert_cmd_fixed_param, wmi_ocb_stop_timing_advert_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_STOP_TIMING_ADVERT_CMDID); + +/* Get TSF timer cmd */ +#define WMITLV_TABLE_WMI_OCB_GET_TSF_TIMER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_cmd_fixed_param, wmi_ocb_get_tsf_timer_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_GET_TSF_TIMER_CMDID); + +/* Get DCC stats cmd */ +#define WMITLV_TABLE_WMI_DCC_GET_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcc_get_stats_cmd_fixed_param, wmi_dcc_get_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_channel_stats_request, channel_stats_request, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DCC_GET_STATS_CMDID); + +/* Clear DCC stats cmd */ +#define WMITLV_TABLE_WMI_DCC_CLEAR_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcc_clear_stats_cmd_fixed_param, wmi_dcc_clear_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_DCC_CLEAR_STATS_CMDID); + +/* Update DCC NDL cmd */ +#define WMITLV_TABLE_WMI_DCC_UPDATE_NDL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcc_update_ndl_cmd_fixed_param, wmi_dcc_update_ndl_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_ndl_chan, chan_ndl_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_ndl_active_state_config, ndl_active_state_config_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DCC_UPDATE_NDL_CMDID); + +/* Roam filter cmd */ +#define WMITLV_TABLE_WMI_ROAM_FILTER_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param, wmi_roam_filter_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, bssid_black_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_ssid, ssid_white_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, bssid_preferred_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, bssid_preferred_factor, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_FILTER_CMDID); + +/* TSF timestamp action cmd */ +#define WMITLV_TABLE_WMI_VDEV_TSF_TSTAMP_ACTION_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, wmi_vdev_tsf_tstamp_action_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); + +/* LFR subnet change config Cmd */ +#define WMITLV_TABLE_WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param, wmi_roam_subnet_change_config_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, skip_subnet_change_detection_bssid_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID); + +/* Set the SOC Preferred Channel List (PCL) Cmd */ +#define WMITLV_TABLE_WMI_SOC_SET_PCL_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_soc_set_pcl_cmd_fixed_param, wmi_soc_set_pcl_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, channel_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_SET_PCL_CMDID); + +/* Set the SOC Hardware Mode Cmd */ +#define WMITLV_TABLE_WMI_SOC_SET_HW_MODE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_cmd_fixed_param, wmi_soc_set_hw_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_SET_HW_MODE_CMDID); + +/* Set the SOC Dual MAC Config Cmd */ +#define WMITLV_TABLE_WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_cmd_fixed_param, wmi_soc_set_dual_mac_config_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID); + +/* Set the SOC Antenna Mode Cmd */ +#define WMITLV_TABLE_WMI_SOC_SET_ANTENNA_MODE_CMDID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_soc_set_antenna_mode_cmd_fixed_param, wmi_soc_set_antenna_mode_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_SET_ANTENNA_MODE_CMDID); + +#define WMITLV_TABLE_WMI_LRO_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_lro_info_cmd_fixed_param, wmi_lro_info_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_LRO_CONFIG_CMDID); + +#define WMITLV_TABLE_WMI_TRANSFER_DATA_TO_FLASH_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_cmd_fixed_param, wmi_transfer_data_to_flash_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_TRANSFER_DATA_TO_FLASH_CMDID); + +/* MAWC sensor report indication cmd */ +#define WMITLV_TABLE_WMI_MAWC_SENSOR_REPORT_IND_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mawc_sensor_report_ind_cmd_fixed_param, wmi_mawc_sensor_report_ind_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MAWC_SENSOR_REPORT_IND_CMDID); + +/* Roam configure MAWC cmd */ +#define WMITLV_TABLE_WMI_ROAM_CONFIGURE_MAWC_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_configure_mawc_cmd_fixed_param, wmi_roam_configure_mawc_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_CONFIGURE_MAWC_CMDID); + +/* NLO configure MAWC cmd */ +#define WMITLV_TABLE_WMI_NLO_CONFIGURE_MAWC_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nlo_configure_mawc_cmd_fixed_param, wmi_nlo_configure_mawc_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_NLO_CONFIGURE_MAWC_CMDID); + +/* Extscan configure MAWC cmd */ +#define WMITLV_TABLE_WMI_EXTSCAN_CONFIGURE_MAWC_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_configure_mawc_cmd_fixed_param, wmi_extscan_configure_mawc_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_CONFIGURE_MAWC_CMDID); + +/************************** TLV definitions of WMI events *******************************/ + +/* Service Ready event */ +#define WMITLV_TABLE_WMI_SERVICE_READY_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_service_ready_event_fixed_param, wmi_service_ready_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_HAL_REG_CAPABILITIES, HAL_REG_CAPABILITIES, hal_reg_capabilities, WMITLV_SIZE_FIX) \ + WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, wmi_service_bitmap, WMITLV_SIZE_FIX, WMI_SERVICE_BM_SIZE) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wlan_host_mem_req, mem_reqs, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, wlan_dbs_hw_mode_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_SERVICE_READY_EVENTID); + +/* Service Ready Extension event */ +#define WMITLV_TABLE_WMI_SERVICE_READY_EXT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_service_ready_ext_event_fixed_param, wmi_service_ready_ext_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SERVICE_READY_EXT_EVENTID); + +/* Ready event */ +#define WMITLV_TABLE_WMI_READY_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ready_event_fixed_param, wmi_ready_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_READY_EVENTID); + +/* Scan Event */ +#define WMITLV_TABLE_WMI_SCAN_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_scan_event_fixed_param, wmi_scan_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SCAN_EVENTID); + +/* ExtScan Start/Stop Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_START_STOP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param, wmi_extscan_start_stop_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_START_STOP_EVENTID); + +/* ExtScan Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_OPERATION_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param, wmi_extscan_operation_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, bucket_id, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_OPERATION_EVENTID); + +/* ExtScan Table Usage Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_TABLE_USAGE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param, wmi_extscan_table_usage_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_TABLE_USAGE_EVENTID); + +/* ExtScan Result Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_CACHED_RESULTS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param, wmi_extscan_cached_results_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_descriptor, bssid_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_rssi_info, rssi_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ie_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_CACHED_RESULTS_EVENTID); + +/* ExtScan Monitor RSSI List Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param, wmi_extscan_wlan_change_results_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_change_result_bssid, bssid_signal_descriptor_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, rssi_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID); + +/* ExtScan Hot List Match Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_HOTLIST_MATCH_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param, wmi_extscan_hotlist_match_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_descriptor, hotlist_match, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_HOTLIST_MATCH_EVENTID); + +/* ExtScan Hot List Match Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_CAPABILITIES_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param, wmi_extscan_capabilities_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_cache_capabilities, extscan_cache_capabilities, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_change_monitor_capabilities, wlan_change_capabilities, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_hotlist_monitor_capabilities, hotlist_capabilities, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_CAPABILITIES_EVENTID); + +/* ExtScan Hot List Match Event */ +#define WMITLV_TABLE_WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param, wmi_extscan_hotlist_ssid_match_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_extscan_wlan_descriptor, hotlist_ssid_match, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID); + +/* Update_whal_mib_stats Event */ +#define WMITLV_TABLE_WMI_UPDATE_WHAL_MIB_STATS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_update_whal_mib_stats_event_fixed_param, wmi_update_whal_mib_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_UPDATE_WHAL_MIB_STATS_EVENTID); + +/* PDEV TPC Config Event */ +#define WMITLV_TABLE_WMI_PDEV_TPC_CONFIG_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_tpc_config_event_fixed_param, wmi_pdev_tpc_config_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, ratesArray, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_TPC_CONFIG_EVENTID); + +/* Channel Info Event */ +#define WMITLV_TABLE_WMI_CHAN_INFO_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_chan_info_event_fixed_param, wmi_chan_info_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_CHAN_INFO_EVENTID); + +/* Phy Error Event */ +#define WMITLV_TABLE_WMI_PHYERR_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_comb_phyerr_rx_hdr, wmi_comb_phyerr_rx_hdr, hdr, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PHYERR_EVENTID); + +/* TX Pause/Unpause event */ +#define WMITLV_TABLE_WMI_TX_PAUSE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tx_pause_event_fixed_param, wmi_tx_pause_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_TX_PAUSE_EVENTID); + +/* Mgmt TX completion event */ +#define WMITLV_TABLE_WMI_MGMT_TX_COMPLETION_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mgmt_tx_compl_event_fixed_param, wmi_mgmt_tx_compl_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MGMT_TX_COMPLETION_EVENTID); + +/* VDEV Start response Event */ +#define WMITLV_TABLE_WMI_VDEV_START_RESP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_start_response_event_fixed_param, wmi_vdev_start_response_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_START_RESP_EVENTID); + +/* VDEV Stopped Event */ +#define WMITLV_TABLE_WMI_VDEV_STOPPED_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_stopped_event_fixed_param, wmi_vdev_stopped_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_STOPPED_EVENTID); + +/* VDEV Install Key Complete Event */ +#define WMITLV_TABLE_WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_install_key_complete_event_fixed_param, wmi_vdev_install_key_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID); + +/* Peer STA Kickout Event */ +#define WMITLV_TABLE_WMI_PEER_STA_KICKOUT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_sta_kickout_event_fixed_param, wmi_peer_sta_kickout_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_STA_KICKOUT_EVENTID); + +/* Management Rx Event */ +#define WMITLV_TABLE_WMI_MGMT_RX_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mgmt_rx_hdr, wmi_mgmt_rx_hdr, hdr, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_MGMT_RX_EVENTID); + +/* TBTT offset Event */ +#define WMITLV_TABLE_WMI_TBTTOFFSET_UPDATE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tbtt_offset_event_fixed_param, wmi_tbtt_offset_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_FXAR(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, tbttoffset_list, WMITLV_SIZE_FIX, WMI_MAX_AP_VDEV) +WMITLV_CREATE_PARAM_STRUC(WMI_TBTTOFFSET_UPDATE_EVENTID); + +/* TX DELBA Complete Event */ +#define WMITLV_TABLE_WMI_TX_DELBA_COMPLETE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tx_delba_complete_event_fixed_param, wmi_tx_delba_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_TX_DELBA_COMPLETE_EVENTID); + +/* Tx ADDBA Complete Event */ +#define WMITLV_TABLE_WMI_TX_ADDBA_COMPLETE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tx_addba_complete_event_fixed_param, wmi_tx_addba_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_TX_ADDBA_COMPLETE_EVENTID); + +/* ADD BA Req ssn Event */ +#define WMITLV_TABLE_WMI_BA_RSP_SSN_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ba_rsp_ssn_event_fixed_param, wmi_ba_rsp_ssn_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_STRUC, wmi_ba_event_ssn, ba_event_ssn_list, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_BA_RSP_SSN_EVENTID); + +/* Aggregation Request event */ +#define WMITLV_TABLE_WMI_AGGR_STATE_TRIG_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_aggr_state_trig_event_fixed_param, wmi_aggr_state_trig_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_AGGR_STATE_TRIG_EVENTID); + +/* Roam Event */ +#define WMITLV_TABLE_WMI_ROAM_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_event_fixed_param, wmi_roam_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_EVENTID); + +/* Roam Synch Event */ +#define WMITLV_TABLE_WMI_ROAM_SYNCH_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_roam_synch_event_fixed_param, wmi_roam_synch_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bcn_probe_rsp_frame, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, reassoc_rsp_frame, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_channel, wmi_channel, chan, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_key_material, key, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, status, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SYNCH_EVENTID); + +/* WOW Wakeup Host Event */ +/* NOTE: Make sure wow_bitmap_info can be zero or one elements only */ +#define WMITLV_TABLE_WMI_WOW_WAKEUP_HOST_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WOW_EVENT_INFO_fixed_param, WOW_EVENT_INFO_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WOW_EVENT_INFO_SECTION_BITMAP, wow_bitmap_info, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, wow_packet_buffer, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_hb_ind_event_fixed_param, hb_indevt, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param, wow_gtkigtk, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_WAKEUP_HOST_EVENTID); + +#define WMITLV_TABLE_WMI_WOW_INITIAL_WAKEUP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WOW_EVENT_INITIAL_WAKEUP_fixed_param, WOW_INITIAL_WAKEUP_EVENT_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_WOW_INITIAL_WAKEUP_EVENTID); + +/* RTT error report Event */ +#define WMITLV_TABLE_WMI_RTT_ERROR_REPORT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_RTT_ERROR_REPORT_EVENTID); + +/* Echo Event */ +#define WMITLV_TABLE_WMI_ECHO_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_echo_event_fixed_param, wmi_echo_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_ECHO_EVENTID); + +/* FTM Integration Event */ +#define WMITLV_TABLE_WMI_PDEV_FTM_INTG_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ftm_intg_event_fixed_param, wmi_ftm_intg_event_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_FTM_INTG_EVENTID); + +/* VDEV get Keepalive Event */ +#define WMITLV_TABLE_WMI_VDEV_GET_KEEPALIVE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_get_keepalive_event_fixed_param, wmi_vdev_get_keepalive_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_GET_KEEPALIVE_EVENTID); + +/* GPIO Input Event */ +#define WMITLV_TABLE_WMI_GPIO_INPUT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_gpio_input_event_fixed_param, wmi_gpio_input_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_GPIO_INPUT_EVENTID); + +/* CSA Handling Event */ +#define WMITLV_TABLE_WMI_CSA_HANDLING_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_csa_event_fixed_param, wmi_csa_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_CSA_HANDLING_EVENTID); + +/* Rfkill state change Event */ +#define WMITLV_TABLE_WMI_RFKILL_STATE_CHANGE_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_rfkill_event_fixed_param, wmi_rfkill_mode_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_RFKILL_STATE_CHANGE_EVENTID); + +/* Debug Message Event */ +#define WMITLV_TABLE_WMI_DEBUG_MESG_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DEBUG_MESG_EVENTID); + +#define WMITLV_TABLE_WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_debug_mesg_flush_complete_fixed_param, wmi_debug_mesg_flush_complete_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID); + +#define WMITLV_TABLE_WMI_RSSI_BREACH_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_rssi_breach_event_fixed_param, wmi_rssi_breach_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_RSSI_BREACH_EVENTID); + +#define WMITLV_TABLE_WMI_TRANSFER_DATA_TO_FLASH_COMPLETE_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_complete_event_fixed_param, wmi_transfer_data_to_flash_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_TRANSFER_DATA_TO_FLASH_COMPLETE_EVENTID); + +/* Diagnostics Event */ +#define WMITLV_TABLE_WMI_DIAG_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DIAG_EVENTID); + +/* IGTK Offload Event */ +#define WMITLV_TABLE_WMI_GTK_OFFLOAD_STATUS_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param, WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_GTK_OFFLOAD_STATUS_EVENTID); + +/* DCA interferance Event */ +#define WMITLV_TABLE_WMI_DCS_INTERFERENCE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcs_interference_event_fixed_param, wmi_dcs_interference_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, ath_dcs_cw_int, cw_int, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wlan_dcs_im_tgt_stats_t, wlan_stat, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DCS_INTERFERENCE_EVENTID); + +/* Profile data Event */ +#define WMITLV_TABLE_WMI_WLAN_PROFILE_DATA_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_wlan_profile_ctx_t, wmi_wlan_profile_ctx_t, profile_ctx, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_wlan_profile_t, profile_data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_PROFILE_DATA_EVENTID); + +/* PDEV UTF Event */ +#define WMITLV_TABLE_WMI_PDEV_UTF_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_UTF_EVENTID); + +/* Update SCPC calibrated data Event */ +#define WMITLV_TABLE_WMI_PDEV_UTF_SCPC_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_scpc_event_fixed_param, wmi_scpc_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_UTF_SCPC_EVENTID); + +/* Debug print Event */ +#define WMITLV_TABLE_WMI_DEBUG_PRINT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DEBUG_PRINT_EVENTID); + +/* RTT measurement report Event - DEPRECATED */ +#define WMITLV_TABLE_WMI_RTT_MEASUREMENT_REPORT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_RTT_MEASUREMENT_REPORT_EVENTID); + +/*oem measurement report Event - DEPRECATED */ +#define WMITLV_TABLE_WMI_OEM_MEASUREMENT_REPORT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OEM_MEASUREMENT_REPORT_EVENTID); + +/*oem error report event - DEPRECATED */ +#define WMITLV_TABLE_WMI_OEM_ERROR_REPORT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OEM_ERROR_REPORT_EVENTID); + +/*oem capability report event - DEPRECATED */ +#define WMITLV_TABLE_WMI_OEM_CAPABILITY_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OEM_CAPABILITY_EVENTID); + +/*oem response event*/ +#define WMITLV_TABLE_WMI_OEM_RESPONSE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_OEM_RESPONSE_EVENTID); + +/* HOST SWBA Event */ +#define WMITLV_TABLE_WMI_HOST_SWBA_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_host_swba_event_fixed_param, wmi_host_swba_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_tim_info, tim_info, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_p2p_noa_info, p2p_noa_info, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_HOST_SWBA_EVENTID); + + +/* Update stats Event */ +#define WMITLV_TABLE_WMI_UPDATE_STATS_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_stats_event_fixed_param, wmi_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_UPDATE_STATS_EVENTID); + +/* For vdev based ht/vht info upload*/ +#define WMITLV_TABLE_WMI_UPDATE_VDEV_RATE_STATS_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_rate_stats_event_fixed_param, wmi_vdev_rate_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_vdev_rate_ht_info, ht_info, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_UPDATE_VDEV_RATE_STATS_EVENTID); + + +/* Update memory dump complete Event */ +#define WMITLV_TABLE_WMI_UPDATE_FW_MEM_DUMP_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_update_fw_mem_dump_fixed_param, wmi_update_fw_mem_dump_fixed_param, fixed_param, WMITLV_SIZE_FIX) + +WMITLV_CREATE_PARAM_STRUC(WMI_UPDATE_FW_MEM_DUMP_EVENTID); + +/* Event indicating the DIAG LOGs/Events supported by FW */ +#define WMITLV_TABLE_WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_diag_event_log_supported_event_fixed_params, wmi_diag_event_log_supported_event_fixed_params, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, diag_events_logs_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID); + +/* Update iface link stats Event */ +#define WMITLV_TABLE_WMI_IFACE_LINK_STATS_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_iface_link_stats_event_fixed_param, wmi_iface_link_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_iface_link_stats, iface_link_stats, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_wmm_ac_stats, ac, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_IFACE_LINK_STATS_EVENTID); + +/* Update Peer link stats Event */ +#define WMITLV_TABLE_WMI_PEER_LINK_STATS_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_stats_event_fixed_param, wmi_peer_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_peer_link_stats, peer_stats, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_rate_stats, peer_rate_stats, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_LINK_STATS_EVENTID); + +/* Update radio stats Event */ +#define WMITLV_TABLE_WMI_RADIO_LINK_STATS_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_radio_link_stats_event_fixed_param, wmi_radio_link_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_radio_link_stats, radio_stats, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_channel_stats, channel_stats, WMITLV_SIZE_VAR) + +WMITLV_CREATE_PARAM_STRUC(WMI_RADIO_LINK_STATS_EVENTID); + +/* PDEV QVIT Event */ +#define WMITLV_TABLE_WMI_PDEV_QVIT_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_QVIT_EVENTID); + +/* WLAN Frequency avoid Event */ +#define WMITLV_TABLE_WMI_WLAN_FREQ_AVOID_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_avoid_freq_ranges_event_fixed_param, wmi_avoid_freq_ranges_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_avoid_freq_range_desc, avd_freq_range, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_FREQ_AVOID_EVENTID); + +/* GTK rekey fail Event */ +#define WMITLV_TABLE_WMI_GTK_REKEY_FAIL_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_gtk_rekey_fail_event_fixed_param, wmi_gtk_rekey_fail_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_GTK_REKEY_FAIL_EVENTID); + +/* NLO match event */ +#define WMITLV_TABLE_WMI_NLO_MATCH_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nlo_event, wmi_nlo_event, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_NLO_MATCH_EVENTID); + +/* NLO scan complete event */ +#define WMITLV_TABLE_WMI_NLO_SCAN_COMPLETE_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nlo_event, wmi_nlo_event, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_NLO_SCAN_COMPLETE_EVENTID); + +/* APFIND event */ +#define WMITLV_TABLE_WMI_APFIND_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_apfind_event_hdr, wmi_apfind_event_hdr, hdr, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + WMITLV_CREATE_PARAM_STRUC(WMI_APFIND_EVENTID); + +/* WMI_PASSPOINT_MATCH_EVENTID */ +#define WMITLV_TABLE_WMI_PASSPOINT_MATCH_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_passpoint_event_hdr, wmi_passpoint_event_hdr, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) + WMITLV_CREATE_PARAM_STRUC(WMI_PASSPOINT_MATCH_EVENTID); + +/* Chatter query reply event */ +#define WMITLV_TABLE_WMI_CHATTER_PC_QUERY_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_chatter_query_reply_event_fixed_param, wmi_chatter_query_reply_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_CHATTER_PC_QUERY_EVENTID); + +/* Upload H_CV info event */ +#define WMITLV_TABLE_WMI_UPLOADH_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_upload_h_hdr, wmi_upload_h_hdr, hdr, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) + WMITLV_CREATE_PARAM_STRUC(WMI_UPLOADH_EVENTID); + +/* Capture H info event */ +#define WMITLV_TABLE_WMI_CAPTUREH_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_capture_h_event_hdr, wmi_capture_h_event_hdr, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_CAPTUREH_EVENTID); + +/* TDLS Peer Update event */ +#define WMITLV_TABLE_WMI_TDLS_PEER_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_tdls_peer_event_fixed_param, wmi_tdls_peer_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_TDLS_PEER_EVENTID); + +/* VDEV MCC Beacon Interval Change Request Event */ +#define WMITLV_TABLE_WMI_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_mcc_bcn_intvl_change_event_fixed_param, wmi_vdev_mcc_bcn_intvl_change_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID); + +#define WMITLV_TABLE_WMI_BATCH_SCAN_ENABLED_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_batch_scan_enabled_event_fixed_param, wmi_batch_scan_enabled_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BATCH_SCAN_ENABLED_EVENTID); + +#define WMITLV_TABLE_WMI_BATCH_SCAN_RESULT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_batch_scan_result_event_fixed_param, wmi_batch_scan_result_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len,WMITLV_TAG_ARRAY_STRUC, wmi_batch_scan_result_scan_list, scan_list, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len,WMITLV_TAG_ARRAY_STRUC, wmi_batch_scan_result_network_info, network_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_BATCH_SCAN_RESULT_EVENTID); + +#define WMITLV_TABLE_WMI_OFFLOAD_BCN_TX_STATUS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_offload_bcn_tx_status_event_fixed_param, wmi_offload_bcn_tx_status_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OFFLOAD_BCN_TX_STATUS_EVENTID); + +/* NOA Event */ +#define WMITLV_TABLE_WMI_P2P_NOA_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_p2p_noa_event_fixed_param, wmi_p2p_noa_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_p2p_noa_info, wmi_p2p_noa_info, p2p_noa_info, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_P2P_NOA_EVENTID); + + /* AP PS enhanced green ap Event */ +#define WMITLV_TABLE_WMI_AP_PS_EGAP_INFO_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len,\ + WMITLV_TAG_STRUC_wmi_ap_ps_egap_info_event_fixed_param,\ + wmi_ap_ps_egap_info_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_STRUC,\ + wmi_ap_ps_egap_info_chainmask_list, chainmask_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_AP_PS_EGAP_INFO_EVENTID); + +#define WMITLV_TABLE_WMI_PEER_INFO_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_info_event_fixed_param, wmi_peer_info_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_peer_info, peer_info, WMITLV_SIZE_VAR) + WMITLV_CREATE_PARAM_STRUC(WMI_PEER_INFO_EVENTID); + +#define WMITLV_TABLE_WMI_PEER_TX_FAIL_CNT_THR_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_tx_fail_cnt_thr_event_fixed_param, wmi_peer_tx_fail_cnt_thr_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_PEER_TX_FAIL_CNT_THR_EVENTID); + +/* DFS radar Event */ +#define WMITLV_TABLE_WMI_DFS_RADAR_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dfs_radar_event_fixed_param, wmi_dfs_radar_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_DFS_RADAR_EVENTID); + +/* Thermal Event */ +#define WMITLV_TABLE_WMI_THERMAL_MGMT_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_thermal_mgmt_event_fixed_param, wmi_thermal_mgmt_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_THERMAL_MGMT_EVENTID); + +/* NAN Response/Indication Event */ +#define WMITLV_TABLE_WMI_NAN_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nan_event_hdr, wmi_nan_event_hdr, fixed_param, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) + WMITLV_CREATE_PARAM_STRUC(WMI_NAN_EVENTID); + +/* L1SS track Event */ +#define WMITLV_TABLE_WMI_PDEV_L1SS_TRACK_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_l1ss_track_event_fixed_param, wmi_pdev_l1ss_track_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_L1SS_TRACK_EVENTID); + +#define WMITLV_TABLE_WMI_DIAG_DATA_CONTAINER_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_diag_data_container_event_fixed_param, wmi_diag_data_container_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DIAG_DATA_CONTAINER_EVENTID); + +/* Estimated Link Speed Indication*/ +#define WMITLV_TABLE_WMI_PEER_ESTIMATED_LINKSPEED_EVENTID(id,op,buf,len)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_estimated_linkspeed_event_fixed_param, wmi_peer_estimated_linkspeed_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_ESTIMATED_LINKSPEED_EVENTID); + +#define WMITLV_TABLE_WMI_STATS_EXT_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_stats_ext_event_fixed_param, wmi_stats_ext_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_STATS_EXT_EVENTID); + +#define WMITLV_TABLE_WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_offload_prb_rsp_tx_status_event_fixed_param, wmi_offload_prb_rsp_tx_status_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID); + +/* host auto shut down event */ +#define WMITLV_TABLE_WMI_HOST_AUTO_SHUTDOWN_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_host_auto_shutdown_event_fixed_param, wmi_host_auto_shutdown_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_HOST_AUTO_SHUTDOWN_EVENTID); + +/* peer state Event */ +#define WMITLV_TABLE_WMI_PEER_STATE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_state_event_fixed_param, wmi_peer_state_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_STATE_EVENTID); + +/* peer assoc conf Event */ +#define WMITLV_TABLE_WMI_PEER_ASSOC_CONF_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_peer_assoc_conf_event_fixed_param, wmi_peer_assoc_conf_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_ASSOC_CONF_EVENTID); + +/* D0-WOW Disable Ack event */ +#define WMITLV_TABLE_WMI_D0_WOW_DISABLE_ACK_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_d0_wow_disable_ack_event_fixed_param, wmi_d0_wow_disable_ack_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_D0_WOW_DISABLE_ACK_EVENTID); + +/* Pdev get chip temperature event */ +#define WMITLV_TABLE_WMI_PDEV_TEMPERATURE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_temperature_event_fixed_param, wmi_pdev_temperature_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_TEMPERATURE_EVENTID); + +/* mDNS offload stats event */ +#define WMITLV_TABLE_WMI_MDNS_STATS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mdns_stats_event_fixed_param, wmi_mdns_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MDNS_STATS_EVENTID); + +/* pdev resume event */ +#define WMITLV_TABLE_WMI_PDEV_RESUME_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_pdev_resume_event_fixed_param, wmi_pdev_resume_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_RESUME_EVENTID); + +/* SAP Authentication offload event */ +#define WMITLV_TABLE_WMI_SAP_OFL_ADD_STA_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sap_ofl_add_sta_event_fixed_param, wmi_sap_ofl_add_sta_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_SAP_OFL_ADD_STA_EVENTID); + +#define WMITLV_TABLE_WMI_SAP_OFL_DEL_STA_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sap_ofl_del_sta_event_fixed_param, wmi_sap_ofl_del_sta_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SAP_OFL_DEL_STA_EVENTID); + +/* Set OCB schedule cmd, DEPRECATED */ +#define WMITLV_TABLE_WMI_OCB_SET_SCHED_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_ocb_set_sched_event_fixed_param, wmi_ocb_set_sched_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_SCHED_EVENTID); + +/* Set OCB configuration response event */ +#define WMITLV_TABLE_WMI_OCB_SET_CONFIG_RESP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_set_config_resp_event_fixed_param, wmi_ocb_set_config_resp_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_CONFIG_RESP_EVENTID); + +/* Get TSF timer response event */ +#define WMITLV_TABLE_WMI_OCB_GET_TSF_TIMER_RESP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_resp_event_fixed_param, wmi_ocb_get_tsf_timer_resp_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_GET_TSF_TIMER_RESP_EVENTID); + +/* Get DCC stats response event */ +#define WMITLV_TABLE_WMI_DCC_GET_STATS_RESP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcc_get_stats_resp_event_fixed_param, wmi_dcc_get_stats_resp_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_ndl_stats_per_channel, stats_per_channel_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DCC_GET_STATS_RESP_EVENTID); + +/* Update DCC NDL response event */ +#define WMITLV_TABLE_WMI_DCC_UPDATE_NDL_RESP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcc_update_ndl_resp_event_fixed_param, wmi_dcc_update_ndl_resp_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_DCC_UPDATE_NDL_RESP_EVENTID); + +/* DCC stats event */ +#define WMITLV_TABLE_WMI_DCC_STATS_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_dcc_stats_event_fixed_param, wmi_dcc_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_dcc_ndl_stats_per_channel, stats_per_channel_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_DCC_STATS_EVENTID); + +/* Read TSF timer response event */ +#define WMITLV_TABLE_WMI_VDEV_TSF_REPORT_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_tsf_report_event_fixed_param, wmi_vdev_tsf_report_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_TSF_REPORT_EVENTID); + +/* Vdev capabilities IE to be transmitted in mgmt frames */ +#define WMITLV_TABLE_WMI_VDEV_SET_IE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param, wmi_vdev_set_ie_cmd_fixed_param, vdev_ie, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, bufp, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_SET_IE_CMDID); + +/* SOC Set Hardware Mode Response event */ +#define WMITLV_TABLE_WMI_SOC_SET_HW_MODE_RESP_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_response_event_fixed_param, wmi_soc_set_hw_mode_response_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_soc_set_hw_mode_response_vdev_mac_entry, wmi_soc_set_hw_mode_response_vdev_mac_mapping, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_SET_HW_MODE_RESP_EVENTID); + +/* SOC Hardware Mode Transition event */ +#define WMITLV_TABLE_WMI_SOC_HW_MODE_TRANSITION_EVENTID(id,op,buf,len) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_soc_hw_mode_transition_event_fixed_param, wmi_soc_hw_mode_transition_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ +WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_soc_set_hw_mode_response_vdev_mac_entry, wmi_soc_set_hw_mode_response_vdev_mac_mapping, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_HW_MODE_TRANSITION_EVENTID); + +/* SOC Set Dual MAC Config Response event */ +#define WMITLV_TABLE_WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_response_event_fixed_param, wmi_soc_set_dual_mac_config_response_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID); + +/* Packet Filter configure command*/ +#define WMITLV_TABLE_WMI_PACKET_FILTER_CONFIG_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param, WMI_PACKET_FILTER_CONFIG_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PACKET_FILTER_CONFIG_CMDID); + +/* Packet Filter enable command*/ +#define WMITLV_TABLE_WMI_PACKET_FILTER_ENABLE_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param, WMI_PACKET_FILTER_ENABLE_CMD_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PACKET_FILTER_ENABLE_CMDID); + +/* MAWC enable/disable sensor event */ +#define WMITLV_TABLE_WMI_MAWC_ENABLE_SENSOR_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_mawc_enable_sensor_event_fixed_param, wmi_mawc_enable_sensor_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_MAWC_ENABLE_SENSOR_EVENTID); + +/* SMPS force mode complete Event */ +#define WMITLV_TABLE_WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_complete_event_fixed_param, wmi_sta_smps_force_mode_complete_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID); + +#ifdef __cplusplus +} +#endif + +#endif /*_WMI_TLV_DEFS_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_helper.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_helper.h new file mode 100644 index 000000000000..8064913f0eb9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_tlv_helper.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WMI_TLV_HELPER_H_ +#define _WMI_TLV_HELPER_H_ + +/* + * Every command or event parameter structure will need a TLV definition. + * The macro WMITLV_TABLE is used to help build this TLV definition. Inside this macro define, the + * individual TLV's are specified. The parameters for WMITLV_ELEM are: + * (1) the list of parameters that are passed unchanged from the WMITLV_TABLE. Currently, they are id,op,buf,len + * (2) The TLV Tag. You should create a new tag for each cmd/event in WMITLV_TAG_ID. The name of the + * tag is . There are special tags, + * e.g. WMI_TLVTAG_ARRAY_UINT32 and WMI_TLVTAG_ARRAY_STRUC. WMI_TLVTAG_ARRAY_UINT32 is for a + * variable size array of UINT32 elements. WMI_TLVTAG_ARRAY_STRUC is for a varialbe size array + * of structures. + * (3) type of the TLV. For WMI_TLVTAG_ARRAY_* tag, then it is the type of each element. + * (4) Name of this TLV. It must be unique in this TLV TABLE. + * (5) Either WMITLV_SIZE_FIX or WMITLV_SIZE_VAR to indicate if this TLV is variable size. + * + * Note: It is important that the last TLV_ELEM does not have the "\" character. +*/ + +/* Size of the TLV Header which is the Tag and Length fields */ +#define WMI_TLV_HDR_SIZE (1 * sizeof(A_UINT32)) + +/** TLV Helper macro to get the TLV Header given the pointer + * to the TLV buffer. */ +#define WMITLV_GET_HDR(tlv_buf) (((A_UINT32 *)(tlv_buf))[0]) + +/** TLV Helper macro to set the TLV Header given the pointer + * to the TLV buffer. */ +#define WMITLV_SET_HDR(tlv_buf, tag, len) (((A_UINT32 *)(tlv_buf))[0]) = ((tag << 16) | (len & 0x0000FFFF)) + +/** TLV Helper macro to get the TLV Tag given the TLV header. */ +#define WMITLV_GET_TLVTAG(tlv_header) ((A_UINT32)((tlv_header)>>16)) + +/** TLV Helper macro to get the TLV Buffer Length (minus TLV + * header size) given the TLV header. */ +#define WMITLV_GET_TLVLEN(tlv_header) ((A_UINT32)((tlv_header) & 0x0000FFFF)) + +/** TLV Helper macro to get the TLV length from TLV structure size by removing TLV header size */ +#define WMITLV_GET_STRUCT_TLVLEN(tlv_struct) ((A_UINT32)(sizeof(tlv_struct)-WMI_TLV_HDR_SIZE)) + +/* Indicates whether the TLV is fixed size or variable length */ +#define WMITLV_SIZE_FIX 0 +#define WMITLV_SIZE_VAR 1 + +typedef struct { + A_UINT32 tag_order; + A_UINT32 tag_id; + A_UINT32 tag_struct_size; + A_UINT32 tag_varied_size; + A_UINT32 tag_array_size; + A_UINT32 cmd_num_tlv; +} wmitlv_attributes_struc; + + +/* Template structure definition for a variable size array of UINT32 */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMI_TLVTAG_ARRAY_UINT32 */ + A_UINT32 uint32_array[1]; /* variable length Array of UINT32 */ +} wmitlv_array_uint32; + +/* Template structure definition for a variable size array of unknown structure */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMI_TLVTAG_ARRAY_STRUC */ + A_UINT32 struc_array[1]; /* variable length Array of structures */ +} wmitlv_array_struc; + +/* + * Used to fill in the "arr_size" parameter when it is not specified and hence, invalid. Can be used to + * indicate if the original TLV definition specify this fixed array size. + */ +#define WMITLV_ARR_SIZE_INVALID 0x1FE + +#define WMITLV_GET_TAG_NUM_TLV_ATTRIB(wmi_cmd_event_id) \ + WMI_TLV_HLPR_NUM_TLVS_FOR_##wmi_cmd_event_id + + +void +wmitlv_set_static_param_tlv_buf(void *param_tlv_buf, A_UINT32 max_tlvs_accomodated); + +void +wmitlv_free_allocated_command_tlvs( + A_UINT32 cmd_id, + void **wmi_cmd_struct_ptr); + +void +wmitlv_free_allocated_event_tlvs( + A_UINT32 event_id, + void **wmi_cmd_struct_ptr); + +int +wmitlv_check_command_tlv_params( + void *os_ctx, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id); + +int +wmitlv_check_event_tlv_params( + void *os_ctx, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id); + +int +wmitlv_check_and_pad_command_tlvs( + void *os_ctx, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id, void **wmi_cmd_struct_ptr); + +int +wmitlv_check_and_pad_event_tlvs( + void *os_ctx, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id, void **wmi_cmd_struct_ptr); + +/** This structure is the element for the Version WhiteList + * table. */ +typedef struct { + A_UINT32 major; + A_UINT32 minor; + A_UINT32 namespace_0; + A_UINT32 namespace_1; + A_UINT32 namespace_2; + A_UINT32 namespace_3; +} wmi_whitelist_version_info; + +struct _wmi_abi_version; /* Forward declaration to make the ARM compiler happy */ + +int +wmi_cmp_and_set_abi_version(int num_whitelist, wmi_whitelist_version_info *version_whitelist_table, + struct _wmi_abi_version *my_vers, + struct _wmi_abi_version *opp_vers, + struct _wmi_abi_version *out_vers); + +int +wmi_versions_are_compatible(struct _wmi_abi_version *vers1, struct _wmi_abi_version *vers2); + +#endif /*_WMI_TLV_HELPER_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h new file mode 100644 index 000000000000..3f469e342f70 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h @@ -0,0 +1,12074 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * @addtogroup WMIAPI + *@{ + */ + +/** @file + * This file specifies the WMI interface for the Software Architecture. + * + * It includes definitions of all the commands and events. Commands are messages + * from the host to the target. Events and Replies are messages from the target + * to the host. + * + * Ownership of correctness in regards to WMI commands + * belongs to the host driver and the target is not required to validate + * parameters for value, proper range, or any other checking. + * + * Guidelines for extending this interface are below. + * + * 1. Add new WMI commands ONLY within the specified range - 0x9000 - 0x9fff + * 2. Use ONLY A_UINT32 type for defining member variables within WMI command/event + * structures. Do not use A_UINT8, A_UINT16, A_BOOL or enum types within these structures. + * 3. DO NOT define bit fields within structures. Implement bit fields using masks + * if necessary. Do not use the programming language's bit field definition. + * 4. Define macros for encode/decode of A_UINT8, A_UINT16 fields within the A_UINT32 + * variables. Use these macros for set/get of these fields. Try to use this to + * optimize the structure without bloating it with A_UINT32 variables for every lower + * sized field. + * 5. Do not use PACK/UNPACK attributes for the structures as each member variable is + * already 4-byte aligned by virtue of being a A_UINT32 type. + * 6. Comment each parameter part of the WMI command/event structure by using the + * 2 stars at the begining of C comment instead of one star to enable HTML document + * generation using Doxygen. + * + */ + +#ifndef _WMI_UNIFIED_H_ +#define _WMI_UNIFIED_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define ATH_MAC_LEN 6 /**< length of MAC in bytes */ +#define WMI_EVENT_STATUS_SUCCESS 0 /* Success return status to host */ +#define WMI_EVENT_STATUS_FAILURE 1 /* Failure return status to host */ + +#define MAX_TX_RATE_VALUES 10 /*Max Tx Rates*/ +#define MAX_RSSI_VALUES 10 /*Max Rssi values*/ + +/* The WLAN_MAX_AC macro cannot be changed without breaking + WMI compatibility. */ +//The maximum value of access category +#define WLAN_MAX_AC 4 + +/* + * These don't necessarily belong here; but as the MS/SM macros require + * ar6000_internal.h to be included, it may not be defined as yet. + */ +#define WMI_F_MS(_v, _f) \ + ( ((_v) & (_f)) >> (_f##_S) ) + +/* + * This breaks the "good macro practice" of only referencing each + * macro field once (to avoid things like field++ from causing issues.) + */ +#define WMI_F_RMW(_var, _v, _f) \ + do { \ + (_var) &= ~(_f); \ + (_var) |= ( ((_v) << (_f##_S)) & (_f)); \ + } while (0) + +#define WMI_GET_BITS(_val,_index,_num_bits) \ + (((_val) >> (_index)) & ((1 << (_num_bits)) - 1)) + +#define WMI_SET_BITS(_var,_index,_num_bits,_val) do { \ + (_var) &= ~(((1 << (_num_bits)) - 1) << (_index)); \ + (_var) |= (((_val) & ((1 << (_num_bits)) - 1)) << (_index)); \ + } while(0) + +/** + * A packed array is an array where each entry in the array is less than + * or equal to 16 bits, and the entries are stuffed into an A_UINT32 array. + * For example, if each entry in the array is 11 bits, then you can stuff + * an array of 4 11-bit values into an array of 2 A_UINT32 values. + * The first 2 11-bit values will be stored in the first A_UINT32, + * and the last 2 11-bit values will be stored in the second A_UINT32. + */ +#define WMI_PACKED_ARR_SIZE(num_entries,bits_per_entry) \ + (((num_entries) / (32 / (bits_per_entry))) + \ + (((num_entries) % (32 / (bits_per_entry))) ? 1 : 0)) + +static INLINE A_UINT32 wmi_packed_arr_get_bits(A_UINT32 *arr, + A_UINT32 entry_index, A_UINT32 bits_per_entry) +{ + A_UINT32 entries_per_uint = (32 / bits_per_entry); + A_UINT32 uint_index = (entry_index / entries_per_uint); + A_UINT32 num_entries_in_prev_uints = (uint_index * entries_per_uint); + A_UINT32 index_in_uint = (entry_index - num_entries_in_prev_uints); + A_UINT32 start_bit_in_uint = (index_in_uint * bits_per_entry); + return ((arr[uint_index] >> start_bit_in_uint) & + (( 1 << bits_per_entry) - 1)); +} + +static INLINE void wmi_packed_arr_set_bits(A_UINT32 *arr, A_UINT32 entry_index, + A_UINT32 bits_per_entry, A_UINT32 val) +{ + A_UINT32 entries_per_uint = (32 / bits_per_entry); + A_UINT32 uint_index = (entry_index / entries_per_uint); + A_UINT32 num_entries_in_prev_uints = (uint_index * entries_per_uint); + A_UINT32 index_in_uint = (entry_index - num_entries_in_prev_uints); + A_UINT32 start_bit_in_uint = (index_in_uint * bits_per_entry); + + arr[uint_index] &= ~(((1 << bits_per_entry) - 1) << start_bit_in_uint); + arr[uint_index] |= + ((val & ((1 << bits_per_entry) - 1)) << start_bit_in_uint); +} + +/** 2 word representation of MAC addr */ +typedef struct { + /** upper 4 bytes of MAC address */ + A_UINT32 mac_addr31to0; + /** lower 2 bytes of MAC address */ + A_UINT32 mac_addr47to32; +} wmi_mac_addr; + +/** macro to convert MAC address from WMI word format to char array */ +#define WMI_MAC_ADDR_TO_CHAR_ARRAY(pwmi_mac_addr,c_macaddr) do { \ + (c_macaddr)[0] = ((pwmi_mac_addr)->mac_addr31to0) & 0xff; \ + (c_macaddr)[1] = ( ((pwmi_mac_addr)->mac_addr31to0) >> 8) & 0xff; \ + (c_macaddr)[2] = ( ((pwmi_mac_addr)->mac_addr31to0) >> 16) & 0xff; \ + (c_macaddr)[3] = ( ((pwmi_mac_addr)->mac_addr31to0) >> 24) & 0xff; \ + (c_macaddr)[4] = ((pwmi_mac_addr)->mac_addr47to32) & 0xff; \ + (c_macaddr)[5] = ( ((pwmi_mac_addr)->mac_addr47to32) >> 8) & 0xff; \ + } while(0) + +/** macro to convert MAC address from char array to WMI word format */ +#define WMI_CHAR_ARRAY_TO_MAC_ADDR(c_macaddr,pwmi_mac_addr) do { \ + (pwmi_mac_addr)->mac_addr31to0 = \ + ( (c_macaddr)[0] | ((c_macaddr)[1] << 8) \ + | ((c_macaddr)[2] << 16) | ((c_macaddr)[3] << 24) ); \ + (pwmi_mac_addr)->mac_addr47to32 = \ + ( (c_macaddr)[4] | ((c_macaddr)[5] << 8)); \ + } while(0) + + +/* + * wmi command groups. + */ +typedef enum { + /* 0 to 2 are reserved */ + WMI_GRP_START=0x3, + WMI_GRP_SCAN=WMI_GRP_START, + WMI_GRP_PDEV, + WMI_GRP_VDEV, + WMI_GRP_PEER, + WMI_GRP_MGMT, + WMI_GRP_BA_NEG, + WMI_GRP_STA_PS, + WMI_GRP_DFS, + WMI_GRP_ROAM, + WMI_GRP_OFL_SCAN, + WMI_GRP_P2P, + WMI_GRP_AP_PS, + WMI_GRP_RATE_CTRL, + WMI_GRP_PROFILE, + WMI_GRP_SUSPEND, + WMI_GRP_BCN_FILTER, + WMI_GRP_WOW, + WMI_GRP_RTT, + WMI_GRP_SPECTRAL, + WMI_GRP_STATS, + WMI_GRP_ARP_NS_OFL, + WMI_GRP_NLO_OFL, + WMI_GRP_GTK_OFL, + WMI_GRP_CSA_OFL, + WMI_GRP_CHATTER, + WMI_GRP_TID_ADDBA, + WMI_GRP_MISC, + WMI_GRP_GPIO, + WMI_GRP_FWTEST, + WMI_GRP_TDLS, + WMI_GRP_RESMGR, + WMI_GRP_STA_SMPS, + WMI_GRP_WLAN_HB, + WMI_GRP_RMC, + WMI_GRP_MHF_OFL, + WMI_GRP_LOCATION_SCAN, + WMI_GRP_OEM, + WMI_GRP_NAN, + WMI_GRP_COEX, + WMI_GRP_OBSS_OFL, + WMI_GRP_LPI, + WMI_GRP_EXTSCAN, + WMI_GRP_DHCP_OFL, + WMI_GRP_IPA, + WMI_GRP_MDNS_OFL, + WMI_GRP_SAP_OFL, + WMI_GRP_OCB, + WMI_GRP_SOC, + WMI_GRP_PKT_FILTER, + WMI_GRP_MAWC, + WMI_GRP_PMF_OFFLOAD, +} WMI_GRP_ID; + +#define WMI_CMD_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) +#define WMI_EVT_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) + +/** + * Command IDs and commange events + */ +typedef enum { + /** initialize the wlan sub system */ + WMI_INIT_CMDID=0x1, + + /* Scan specific commands */ + + /** start scan request to FW */ + WMI_START_SCAN_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_SCAN) , + /** stop scan request to FW */ + WMI_STOP_SCAN_CMDID, + /** full list of channels as defined by the regulatory that will be used by scanner */ + WMI_SCAN_CHAN_LIST_CMDID, + /** overwrite default priority table in scan scheduler */ + WMI_SCAN_SCH_PRIO_TBL_CMDID, + /** This command to adjust the priority and min.max_rest_time + * of an on ongoing scan request. + */ + WMI_SCAN_UPDATE_REQUEST_CMDID, + + /** set OUI to be used in probe request if enabled */ + WMI_SCAN_PROB_REQ_OUI_CMDID, + + /* PDEV(physical device) specific commands */ + /** set regulatorty ctl id used by FW to determine the exact ctl power limits */ + WMI_PDEV_SET_REGDOMAIN_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_PDEV), + /** set channel. mainly used for supporting monitor mode */ + WMI_PDEV_SET_CHANNEL_CMDID, + /** set pdev specific parameters */ + WMI_PDEV_SET_PARAM_CMDID, + /** enable packet log */ + WMI_PDEV_PKTLOG_ENABLE_CMDID, + /** disable packet log*/ + WMI_PDEV_PKTLOG_DISABLE_CMDID, + /** set wmm parameters */ + WMI_PDEV_SET_WMM_PARAMS_CMDID, + /** set HT cap ie that needs to be carried probe requests HT/VHT channels */ + WMI_PDEV_SET_HT_CAP_IE_CMDID, + /** set VHT cap ie that needs to be carried on probe requests on VHT channels */ + WMI_PDEV_SET_VHT_CAP_IE_CMDID, + + /** Command to send the DSCP-to-TID map to the target */ + WMI_PDEV_SET_DSCP_TID_MAP_CMDID, + /** set quiet ie parameters. primarily used in AP mode */ + WMI_PDEV_SET_QUIET_MODE_CMDID, + /** Enable/Disable Green AP Power Save */ + WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, + /** get TPC config for the current operating channel */ + WMI_PDEV_GET_TPC_CONFIG_CMDID, + + /** set the base MAC address for the physical device before a VDEV is created. + * For firmware that doesn't support this feature and this command, the pdev + * MAC address will not be changed. */ + WMI_PDEV_SET_BASE_MACADDR_CMDID, + + /* eeprom content dump , the same to bdboard data */ + WMI_PDEV_DUMP_CMDID, + /* set LED configuration */ + WMI_PDEV_SET_LED_CONFIG_CMDID, + /* Get Current temprature of chip in Celcius degree*/ + WMI_PDEV_GET_TEMPERATURE_CMDID, + /* Set LED flashing behavior */ + WMI_PDEV_SET_LED_FLASHING_CMDID, + + /* VDEV(virtual device) specific commands */ + /** vdev create */ + WMI_VDEV_CREATE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_VDEV), + /** vdev delete */ + WMI_VDEV_DELETE_CMDID, + /** vdev start request */ + WMI_VDEV_START_REQUEST_CMDID, + /** vdev restart request (RX only, NO TX, used for CAC period)*/ + WMI_VDEV_RESTART_REQUEST_CMDID, + /** vdev up request */ + WMI_VDEV_UP_CMDID, + /** vdev stop request */ + WMI_VDEV_STOP_CMDID, + /** vdev down request */ + WMI_VDEV_DOWN_CMDID, + /* set a vdev param */ + WMI_VDEV_SET_PARAM_CMDID, + /* set a key (used for setting per peer unicast and per vdev multicast) */ + WMI_VDEV_INSTALL_KEY_CMDID, + + /* wnm sleep mode command */ + WMI_VDEV_WNM_SLEEPMODE_CMDID, + WMI_VDEV_WMM_ADDTS_CMDID, + WMI_VDEV_WMM_DELTS_CMDID, + WMI_VDEV_SET_WMM_PARAMS_CMDID, + WMI_VDEV_SET_GTX_PARAMS_CMDID, + WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID, + + WMI_VDEV_PLMREQ_START_CMDID, + WMI_VDEV_PLMREQ_STOP_CMDID, + /* TSF timestamp action for specified vdev */ + WMI_VDEV_TSF_TSTAMP_ACTION_CMDID, + /** set the capabilties IE, e.g. for extended caps in probe requests, + * assoc req etc for frames FW locally generates */ + WMI_VDEV_SET_IE_CMDID, + + /* peer specific commands */ + + /** create a peer */ + WMI_PEER_CREATE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_PEER), + /** delete a peer */ + WMI_PEER_DELETE_CMDID, + /** flush specific tid queues of a peer */ + WMI_PEER_FLUSH_TIDS_CMDID, + /** set a parameter of a peer */ + WMI_PEER_SET_PARAM_CMDID, + /** set peer to associated state. will cary all parameters determined during assocication time */ + WMI_PEER_ASSOC_CMDID, + /**add a wds (4 address ) entry. used only for testing WDS feature on AP products */ + WMI_PEER_ADD_WDS_ENTRY_CMDID, + /**remove wds (4 address ) entry. used only for testing WDS feature on AP products */ + WMI_PEER_REMOVE_WDS_ENTRY_CMDID, + /** set up mcast group infor for multicast to unicast conversion */ + WMI_PEER_MCAST_GROUP_CMDID, + /** request peer info from FW. FW shall respond with PEER_INFO_EVENTID */ + WMI_PEER_INFO_REQ_CMDID, + + /** request the estimated link speed for the peer. FW shall respond with + * WMI_PEER_ESTIMATED_LINKSPEED_EVENTID. + */ + WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID, + /** Set the conditions to report peer justified rate to driver + * The justified rate means the the user-rate is justified by PER. + */ + WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID, + + /* beacon/management specific commands */ + + /** transmit beacon by reference . used for transmitting beacon on low latency interface like pcie */ + WMI_BCN_TX_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_MGMT), + /** transmit beacon by value */ + WMI_PDEV_SEND_BCN_CMDID, + /** set the beacon template. used in beacon offload mode to setup the + * the common beacon template with the FW to be used by FW to generate beacons */ + WMI_BCN_TMPL_CMDID, + /** set beacon filter with FW */ + WMI_BCN_FILTER_RX_CMDID, + /* enable/disable filtering of probe requests in the firmware */ + WMI_PRB_REQ_FILTER_RX_CMDID, + /** transmit management frame by value. will be deprecated */ + WMI_MGMT_TX_CMDID, + /** set the probe response template. used in beacon offload mode to setup the + * the common probe response template with the FW to be used by FW to generate + * probe responses */ + WMI_PRB_TMPL_CMDID, + + /** Transmit Mgmt frame by reference */ + WMI_MGMT_TX_SEND_CMDID, + + /** commands to directly control ba negotiation directly from host. only used in test mode */ + + /** turn off FW Auto addba mode and let host control addba */ + WMI_ADDBA_CLEAR_RESP_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_BA_NEG), + /** send add ba request */ + WMI_ADDBA_SEND_CMDID, + WMI_ADDBA_STATUS_CMDID, + /** send del ba */ + WMI_DELBA_SEND_CMDID, + /** set add ba response will be used by FW to generate addba response*/ + WMI_ADDBA_SET_RESP_CMDID, + /** send single VHT MPDU with AMSDU */ + WMI_SEND_SINGLEAMSDU_CMDID, + + /** Station power save specific config */ + /** enable/disable station powersave */ + WMI_STA_POWERSAVE_MODE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_STA_PS), + /** set station power save specific parameter */ + WMI_STA_POWERSAVE_PARAM_CMDID, + /** set station mimo powersave mode */ + WMI_STA_MIMO_PS_MODE_CMDID, + + + /** DFS-specific commands */ + /** enable DFS (radar detection)*/ + WMI_PDEV_DFS_ENABLE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_DFS), + /** disable DFS (radar detection)*/ + WMI_PDEV_DFS_DISABLE_CMDID, + /** enable DFS phyerr/parse filter offload */ + WMI_DFS_PHYERR_FILTER_ENA_CMDID, + /** enable DFS phyerr/parse filter offload */ + WMI_DFS_PHYERR_FILTER_DIS_CMDID, + + /* Roaming specific commands */ + /** set roam scan mode */ + WMI_ROAM_SCAN_MODE=WMI_CMD_GRP_START_ID(WMI_GRP_ROAM), + /** set roam scan rssi threshold below which roam scan is enabled */ + WMI_ROAM_SCAN_RSSI_THRESHOLD, + /** set roam scan period for periodic roam scan mode */ + WMI_ROAM_SCAN_PERIOD, + /** set roam scan trigger rssi change threshold */ + WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, + /** set roam AP profile */ + WMI_ROAM_AP_PROFILE, + /** set channel list for roam scans */ + WMI_ROAM_CHAN_LIST, + /** Stop scan command */ + WMI_ROAM_SCAN_CMD, + /** roaming sme offload sync complete */ + WMI_ROAM_SYNCH_COMPLETE, + /** set ric request element for 11r roaming */ + WMI_ROAM_SET_RIC_REQUEST_CMDID, + /** Invoke roaming forcefully */ + WMI_ROAM_INVOKE_CMDID, + /** roaming filter cmd to allow further filtering of roaming candidate */ + WMI_ROAM_FILTER_CMDID, + /** set gateway ip, mac and retries for subnet change detection */ + WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID, + /** configure thresholds for MAWC */ + WMI_ROAM_CONFIGURE_MAWC_CMDID, + + /** offload scan specific commands */ + /** set offload scan AP profile */ + WMI_OFL_SCAN_ADD_AP_PROFILE=WMI_CMD_GRP_START_ID(WMI_GRP_OFL_SCAN), + /** remove offload scan AP profile */ + WMI_OFL_SCAN_REMOVE_AP_PROFILE, + /** set offload scan period */ + WMI_OFL_SCAN_PERIOD, + + /* P2P specific commands */ + /**set P2P device info. FW will used by FW to create P2P IE to be carried in probe response + * generated during p2p listen and for p2p discoverability */ + WMI_P2P_DEV_SET_DEVICE_INFO=WMI_CMD_GRP_START_ID(WMI_GRP_P2P), + /** enable/disable p2p discoverability on STA/AP VDEVs */ + WMI_P2P_DEV_SET_DISCOVERABILITY, + /** set p2p ie to be carried in beacons generated by FW for GO */ + WMI_P2P_GO_SET_BEACON_IE, + /** set p2p ie to be carried in probe response frames generated by FW for GO */ + WMI_P2P_GO_SET_PROBE_RESP_IE, + /** set the vendor specific p2p ie data. FW will use this to parse the P2P NoA + * attribute in the beacons/probe responses received. + */ + WMI_P2P_SET_VENDOR_IE_DATA_CMDID, + /** set the configure of p2p find offload */ + WMI_P2P_DISC_OFFLOAD_CONFIG_CMDID, + /** set the vendor specific p2p ie data for p2p find offload using */ + WMI_P2P_DISC_OFFLOAD_APPIE_CMDID, + /** set the BSSID/device name pattern of p2p find offload */ + WMI_P2P_DISC_OFFLOAD_PATTERN_CMDID, + /** set OppPS related parameters **/ + WMI_P2P_SET_OPPPS_PARAM_CMDID, + + /** AP power save specific config */ + /** set AP power save specific param */ + WMI_AP_PS_PEER_PARAM_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_AP_PS), + /** set AP UAPSD coex pecific param */ + WMI_AP_PS_PEER_UAPSD_COEX_CMDID, + /** set Enhanced Green AP param */ + WMI_AP_PS_EGAP_PARAM_CMDID, + + + /** Rate-control specific commands */ + WMI_PEER_RATE_RETRY_SCHED_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_RATE_CTRL), + + /** WLAN Profiling commands. */ + WMI_WLAN_PROFILE_TRIGGER_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_PROFILE), + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, + + /** Suspend resume command Ids */ + WMI_PDEV_SUSPEND_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_SUSPEND), + WMI_PDEV_RESUME_CMDID, + + /* Beacon filter commands */ + /** add a beacon filter */ + WMI_ADD_BCN_FILTER_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_BCN_FILTER), + /** remove a beacon filter */ + WMI_RMV_BCN_FILTER_CMDID, + + /* WOW Specific WMI commands*/ + /** add pattern for awake */ + WMI_WOW_ADD_WAKE_PATTERN_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_WOW), + /** deleta a wake pattern */ + WMI_WOW_DEL_WAKE_PATTERN_CMDID, + /** enable/deisable wake event */ + WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, + /** enable WOW */ + WMI_WOW_ENABLE_CMDID, + /** host woke up from sleep event to FW. Generated in response to WOW Hardware event */ + WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, + /* IOAC add keep alive cmd. */ + WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID, + /* IOAC del keep alive cmd. */ + WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID, + /* IOAC add pattern for awake */ + WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID, + /* IOAC deleta a wake pattern */ + WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID, + /* D0-WOW enable or disable cmd */ + WMI_D0_WOW_ENABLE_DISABLE_CMDID, + /* enable extend WoW */ + WMI_EXTWOW_ENABLE_CMDID, + /* Extend WoW command to configure app type1 parameter */ + WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID, + /* Extend WoW command to configure app type2 parameter */ + WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID, + /* enable ICMPv6 Network advertisement filtering */ + WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID, + /* + * Set a pattern to match UDP packet in WOW mode. + * If match, construct a tx frame in a local buffer + * to send through the peer AP to the entity in the + * IP network that sent the UDP packet to this STA. + */ + WMI_WOW_UDP_SVC_OFLD_CMDID, + + /* configure WOW host wakeup PIN pattern */ + WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID, + + /* RTT measurement related cmd */ + /** request to make an RTT measurement */ + WMI_RTT_MEASREQ_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_RTT), + /** request to report a tsf measurement */ + WMI_RTT_TSF_CMDID, + + /** spectral scan command */ + /** configure spectral scan */ + WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_SPECTRAL), + /** enable/disable spectral scan and trigger */ + WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, + + /* F/W stats */ + /** one time request for stats */ + WMI_REQUEST_STATS_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_STATS), + /** Push MCC Adaptive Scheduler Stats to Firmware */ + WMI_MCC_SCHED_TRAFFIC_STATS_CMDID, + /** one time request for txrx stats */ + WMI_REQUEST_STATS_EXT_CMDID, + + /* Link Layer stats */ + /** Request for link layer stats */ + WMI_REQUEST_LINK_STATS_CMDID, + /** Request for setting params to link layer stats */ + WMI_START_LINK_STATS_CMDID, + /** Request to clear stats*/ + WMI_CLEAR_LINK_STATS_CMDID, + + /** Request for getting the Firmware Memory Dump */ + WMI_GET_FW_MEM_DUMP_CMDID, + + /** Request to flush of the buffered debug messages */ + WMI_DEBUG_MESG_FLUSH_CMDID, + + /** Cmd to configure the verbose level */ + WMI_DIAG_EVENT_LOG_CONFIG_CMDID, + + /** ARP OFFLOAD REQUEST*/ + WMI_SET_ARP_NS_OFFLOAD_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_ARP_NS_OFL), + + /** Proactive ARP Response Add Pattern Command*/ + WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID, + + /** Proactive ARP Response Del Pattern Command*/ + WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID, + + /** NS offload confid*/ + WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_NLO_OFL), + + /** APFIND Config */ + WMI_APFIND_CMDID, + + /** Passpoint list config */ + WMI_PASSPOINT_LIST_CONFIG_CMDID, + /** configure supprssing parameters for MAWC */ + WMI_NLO_CONFIGURE_MAWC_CMDID, + + /* GTK offload Specific WMI commands*/ + WMI_GTK_OFFLOAD_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_GTK_OFL), + + /* CSA offload Specific WMI commands*/ + /** csa offload enable */ + WMI_CSA_OFFLOAD_ENABLE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_CSA_OFL), + /** chan switch command */ + WMI_CSA_OFFLOAD_CHANSWITCH_CMDID, + + /* Chatter commands*/ + /* Change chatter mode of operation */ + WMI_CHATTER_SET_MODE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_CHATTER), + /** chatter add coalescing filter command */ + WMI_CHATTER_ADD_COALESCING_FILTER_CMDID, + /** chatter delete coalescing filter command */ + WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID, + /** chatter coalecing query command */ + WMI_CHATTER_COALESCING_QUERY_CMDID, + + /**addba specific commands */ + /** start the aggregation on this TID */ + WMI_PEER_TID_ADDBA_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_TID_ADDBA), + /** stop the aggregation on this TID */ + WMI_PEER_TID_DELBA_CMDID, + + /** set station mimo powersave method */ + WMI_STA_DTIM_PS_METHOD_CMDID, + /** Configure the Station UAPSD AC Auto Trigger Parameters */ + WMI_STA_UAPSD_AUTO_TRIG_CMDID, + /** Configure the Keep Alive Parameters */ + WMI_STA_KEEPALIVE_CMDID, + + /* Request ssn from target for a sta/tid pair */ + WMI_BA_REQ_SSN_CMDID, + /* misc command group */ + /** echo command mainly used for testing */ + WMI_ECHO_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_MISC), + + /* !!IMPORTANT!! + * If you need to add a new WMI command to the WMI_GRP_MISC sub-group, + * please make sure you add it BEHIND WMI_PDEV_UTF_CMDID, + * as we MUST have a fixed value here to maintain compatibility between + * UTF and the ART2 driver + */ + /** UTF WMI commands */ + WMI_PDEV_UTF_CMDID, + + /** set debug log config */ + WMI_DBGLOG_CFG_CMDID, + /* QVIT specific command id */ + WMI_PDEV_QVIT_CMDID, + /* Factory Testing Mode request command + * used for integrated chipsets */ + WMI_PDEV_FTM_INTG_CMDID, + /* set and get keepalive parameters command */ + WMI_VDEV_SET_KEEPALIVE_CMDID, + WMI_VDEV_GET_KEEPALIVE_CMDID, + /* For fw recovery test command */ + WMI_FORCE_FW_HANG_CMDID, + /* Set Mcast/Bdcast filter */ + WMI_SET_MCASTBCAST_FILTER_CMDID, + /** set thermal management params **/ + WMI_THERMAL_MGMT_CMDID, + /** set host auto shutdown params **/ + WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID, + /** set tpc chainmask config command */ + WMI_TPC_CHAINMASK_CONFIG_CMDID, + /** set Antenna diversity command */ + WMI_SET_ANTENNA_DIVERSITY_CMDID, + /** Set OCB Sched Request, deprecated */ + WMI_OCB_SET_SCHED_CMDID, + /** Set rssi monitoring config command */ + WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID, + /** Enable/disable Large Receive Offload processing; provide cfg params */ + WMI_LRO_CONFIG_CMDID, + /** transfer data from host to firmware to write flash */ + WMI_TRANSFER_DATA_TO_FLASH_CMDID, + /* GPIO Configuration */ + WMI_GPIO_CONFIG_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_GPIO), + WMI_GPIO_OUTPUT_CMDID, + + /* Txbf configuration command */ + WMI_TXBF_CMDID, + + /* FWTEST Commands */ + WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_FWTEST), + /** set NoA descs **/ + WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID, + /* UNIT Tests */ + WMI_UNIT_TEST_CMDID, + + /** TDLS Configuration */ + /** enable/disable TDLS */ + WMI_TDLS_SET_STATE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_TDLS), + /** set tdls peer state */ + WMI_TDLS_PEER_UPDATE_CMDID, + /** TDLS Offchannel control */ + WMI_TDLS_SET_OFFCHAN_MODE_CMDID, + + /** Resmgr Configuration */ + /** Adaptive OCS is enabled by default in the FW. This command is used to + * disable FW based adaptive OCS. + */ + WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_RESMGR), + /** set the requested channel time quota for the home channels */ + WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID, + /** set the requested latency for the home channels */ + WMI_RESMGR_SET_CHAN_LATENCY_CMDID, + + /** STA SMPS Configuration */ + /** force SMPS mode */ + WMI_STA_SMPS_FORCE_MODE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_STA_SMPS), + /** set SMPS parameters */ + WMI_STA_SMPS_PARAM_CMDID, + + /* Wlan HB commands*/ + /* enalbe/disable wlan HB */ + WMI_HB_SET_ENABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_WLAN_HB), + /* set tcp parameters for wlan HB */ + WMI_HB_SET_TCP_PARAMS_CMDID, + /* set tcp pkt filter for wlan HB */ + WMI_HB_SET_TCP_PKT_FILTER_CMDID, + /* set udp parameters for wlan HB */ + WMI_HB_SET_UDP_PARAMS_CMDID, + /* set udp pkt filter for wlan HB */ + WMI_HB_SET_UDP_PKT_FILTER_CMDID, + + /** Wlan RMC commands*/ + /** enable/disable RMC */ + WMI_RMC_SET_MODE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_RMC), + /** configure action frame period */ + WMI_RMC_SET_ACTION_PERIOD_CMDID, + /** For debug/future enhancement purposes only, + * configures/finetunes RMC algorithms */ + WMI_RMC_CONFIG_CMDID, + + /** WLAN MHF offload commands */ + /** enable/disable MHF offload */ + WMI_MHF_OFFLOAD_SET_MODE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_MHF_OFL), + /** Plumb routing table for MHF offload */ + WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID, + + /*location scan commands*/ + /*start batch scan*/ + WMI_BATCH_SCAN_ENABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_LOCATION_SCAN), + /*stop batch scan*/ + WMI_BATCH_SCAN_DISABLE_CMDID, + /*get batch scan result*/ + WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID, + /* OEM related cmd */ + WMI_OEM_REQ_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_OEM), /* DEPRECATED */ + WMI_OEM_REQUEST_CMDID, + + /** Nan Request */ + WMI_NAN_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_NAN), + + /** Modem power state command */ + WMI_MODEM_POWER_STATE_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_COEX), + WMI_CHAN_AVOID_UPDATE_CMDID, + + /** + * OBSS scan offload enable/disable commands + * OBSS scan enable CMD will send to FW after VDEV UP, if these conditions are true: + * 1. WMI_SERVICE_OBSS_SCAN is reported by FW in service ready, + * 2. STA connect to a 2.4Ghz ht20/ht40 AP, + * 3. AP enable 20/40 coexistence (OBSS_IE-74 can be found in beacon or association response) + * If OBSS parameters from beacon changed, also use enable CMD to update parameters. + * OBSS scan disable CMD will send to FW if have enabled when tearing down connection. + */ + WMI_OBSS_SCAN_ENABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_OBSS_OFL), + WMI_OBSS_SCAN_DISABLE_CMDID, + + /**LPI commands*/ + /**LPI mgmt snooping config command*/ + WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_LPI), + /**LPI scan start command*/ + WMI_LPI_START_SCAN_CMDID, + /**LPI scan stop command*/ + WMI_LPI_STOP_SCAN_CMDID, + + /** ExtScan commands */ + WMI_EXTSCAN_START_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_EXTSCAN), + WMI_EXTSCAN_STOP_CMDID, + WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID, + WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID, + WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID, + WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID, + WMI_EXTSCAN_SET_CAPABILITIES_CMDID, + WMI_EXTSCAN_GET_CAPABILITIES_CMDID, + WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID, + WMI_EXTSCAN_CONFIGURE_MAWC_CMDID, + + /** DHCP server offload commands */ + WMI_SET_DHCP_SERVER_OFFLOAD_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_DHCP_OFL), + + /** IPA Offload features related commands */ + WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_IPA), + + /** mDNS responder offload commands */ + WMI_MDNS_OFFLOAD_ENABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_MDNS_OFL), + WMI_MDNS_SET_FQDN_CMDID, + WMI_MDNS_SET_RESPONSE_CMDID, + WMI_MDNS_GET_STATS_CMDID, + + /* enable/disable AP Authentication offload */ + WMI_SAP_OFL_ENABLE_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_SAP_OFL), + WMI_SAP_SET_BLACKLIST_PARAM_CMDID, + + /** Out-of-context-of-BSS (OCB) commands */ + WMI_OCB_SET_CONFIG_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_OCB), + WMI_OCB_SET_UTC_TIME_CMDID, + WMI_OCB_START_TIMING_ADVERT_CMDID, + WMI_OCB_STOP_TIMING_ADVERT_CMDID, + WMI_OCB_GET_TSF_TIMER_CMDID, + WMI_DCC_GET_STATS_CMDID, + WMI_DCC_CLEAR_STATS_CMDID, + WMI_DCC_UPDATE_NDL_CMDID, + /* System-On-Chip commands */ + WMI_SOC_SET_PCL_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_SOC), + WMI_SOC_SET_HW_MODE_CMDID, + WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID, + WMI_SOC_SET_ANTENNA_MODE_CMDID, + + /* packet filter commands */ + WMI_PACKET_FILTER_CONFIG_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_PKT_FILTER), + WMI_PACKET_FILTER_ENABLE_CMDID, + + /** Motion Aided WiFi Connectivity (MAWC) commands */ + WMI_MAWC_SENSOR_REPORT_IND_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_MAWC), + + /** WMI commands related to PMF 11w Offload */ + WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_PMF_OFFLOAD), +} WMI_CMD_ID; + +typedef enum { + /** WMI service is ready; after this event WMI messages can be sent/received */ + WMI_SERVICE_READY_EVENTID=0x1, + /** WMI is ready; after this event the wlan subsystem is initialized and can process commands. */ + WMI_READY_EVENTID, + + /** Scan specific events */ + WMI_SCAN_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_SCAN) , + + /* PDEV specific events */ + /** TPC config for the current operating channel */ + WMI_PDEV_TPC_CONFIG_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_PDEV) , + /** Channel stats event */ + WMI_CHAN_INFO_EVENTID, + + /** PHY Error specific WMI event */ + WMI_PHYERR_EVENTID, + + /** eeprom dump event */ + WMI_PDEV_DUMP_EVENTID, + + /** traffic pause event */ + WMI_TX_PAUSE_EVENTID, + + /** DFS radar event */ + WMI_DFS_RADAR_EVENTID, + + /** track L1SS entry and residency event */ + WMI_PDEV_L1SS_TRACK_EVENTID, + + /** Report current temprature of the chip in Celcius degree */ + WMI_PDEV_TEMPERATURE_EVENTID, + + /** Extension of WMI_SERVICE_READY msg with extra target capability info */ + WMI_SERVICE_READY_EXT_EVENTID, + + /* VDEV specific events */ + /** VDEV started event in response to VDEV_START request */ + WMI_VDEV_START_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_VDEV), + /** vdev stopped event , generated in response to VDEV_STOP request */ + WMI_VDEV_STOPPED_EVENTID, + /* Indicate the set key (used for setting per + * peer unicast and per vdev multicast) + * operation has completed */ + WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID, + /* NOTE: WMI_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID would be deprecated. Please + don't use this for any new implementations */ + /* Firmware requests dynamic change to a specific beacon interval for a specific vdev ID in MCC scenario. + This request is valid only for vdevs operating in soft AP or P2P GO mode */ + WMI_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID, + + /* Return the TSF timestamp of specified vdev */ + WMI_VDEV_TSF_REPORT_EVENTID, + + /* peer specific events */ + /** FW reauet to kick out the station for reasons like inactivity,lack of response ..etc */ + WMI_PEER_STA_KICKOUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_PEER), + + /** Peer Info Event with data_rate, rssi, tx_fail_cnt etc */ + WMI_PEER_INFO_EVENTID, + + /** Event indicating that TX fail count reaching threshold */ + WMI_PEER_TX_FAIL_CNT_THR_EVENTID, + /** Return the estimate link speed for the Peer specified in the + * WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID command. + */ + WMI_PEER_ESTIMATED_LINKSPEED_EVENTID, + /* Return the peer state + * WMI_PEER_SET_PARAM_CMDID, WMI_PEER_AUTHORIZE + */ + WMI_PEER_STATE_EVENTID, + + /* Peer Assoc Conf event to confirm fw had received PEER_ASSOC_CMD. + * After that, host will send Mx message. + * Otherwise, host will pause any Mx(STA:M2/M4) message + */ + WMI_PEER_ASSOC_CONF_EVENTID, + + /* beacon/mgmt specific events */ + /** RX management frame. the entire frame is carried along with the event. */ + WMI_MGMT_RX_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MGMT), + /** software beacon alert event to Host requesting host to Queue a beacon for transmission + use only in host beacon mode */ + WMI_HOST_SWBA_EVENTID, + /** beacon tbtt offset event indicating the tsf offset of the tbtt from the theritical value. + tbtt offset is normally 0 and will be non zero if there are multiple VDEVs operating in + staggered beacon transmission mode */ + WMI_TBTTOFFSET_UPDATE_EVENTID, + + /** event after the first beacon is transmitted following + a change in the template.*/ + WMI_OFFLOAD_BCN_TX_STATUS_EVENTID, + /** event after the first probe response is transmitted following + a change in the template.*/ + WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID, + /** Event for Mgmt TX completion event */ + WMI_MGMT_TX_COMPLETION_EVENTID, + + /*ADDBA Related WMI Events*/ + /** Indication the completion of the prior + WMI_PEER_TID_DELBA_CMDID(initiator) */ + WMI_TX_DELBA_COMPLETE_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_BA_NEG), + /** Indication the completion of the prior + *WMI_PEER_TID_ADDBA_CMDID(initiator) */ + WMI_TX_ADDBA_COMPLETE_EVENTID, + + /* Seq num returned from hw for a sta/tid pair */ + WMI_BA_RSP_SSN_EVENTID, + + /* Aggregation state requested by BTC */ + WMI_AGGR_STATE_TRIG_EVENTID, + + /** Roam event to trigger roaming on host */ + WMI_ROAM_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_ROAM), + + /** matching AP found from list of profiles */ + WMI_PROFILE_MATCH, + /** roam synch event */ + WMI_ROAM_SYNCH_EVENTID, + + /** P2P disc found */ + WMI_P2P_DISC_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_P2P), + + /*send noa info to host when noa is changed for beacon tx offload enable*/ + WMI_P2P_NOA_EVENTID, + + /** Send EGAP Info to host */ + WMI_AP_PS_EGAP_INFO_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_AP_PS), + + /* send pdev resume event to host after pdev resume. */ + WMI_PDEV_RESUME_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_SUSPEND), + + /** WOW wake up host event.generated in response to WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID. + will cary wake reason */ + WMI_WOW_WAKEUP_HOST_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_WOW), + WMI_D0_WOW_DISABLE_ACK_EVENTID, + WMI_WOW_INITIAL_WAKEUP_EVENTID, + + /*RTT related event ID*/ + /** RTT measurement report */ + WMI_RTT_MEASUREMENT_REPORT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_RTT), + /** TSF measurement report */ + WMI_TSF_MEASUREMENT_REPORT_EVENTID, + /** RTT error report */ + WMI_RTT_ERROR_REPORT_EVENTID, + /*STATS specific events*/ + /** txrx stats event requested by host */ + WMI_STATS_EXT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_STATS), + /** FW iface link stats Event */ + WMI_IFACE_LINK_STATS_EVENTID, + /** FW iface peer link stats Event */ + WMI_PEER_LINK_STATS_EVENTID, + /** FW Update radio stats Event */ + WMI_RADIO_LINK_STATS_EVENTID, + + /** Firmware memory dump Complete event*/ + WMI_UPDATE_FW_MEM_DUMP_EVENTID, + + /** Event indicating the DIAG logs/events supported by FW */ + WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID, + + /* NLO specific events */ + /** NLO match event after the first match */ + WMI_NLO_MATCH_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_NLO_OFL), + + /** NLO scan complete event */ + WMI_NLO_SCAN_COMPLETE_EVENTID, + + /** APFIND specific events */ + WMI_APFIND_EVENTID, + + /** passpoint network match event */ + WMI_PASSPOINT_MATCH_EVENTID, + + /** GTK offload stautus event requested by host */ + WMI_GTK_OFFLOAD_STATUS_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GTK_OFL), + + /** GTK offload failed to rekey event */ + WMI_GTK_REKEY_FAIL_EVENTID, + /* CSA IE received event */ + WMI_CSA_HANDLING_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_CSA_OFL), + + /*chatter query reply event*/ + WMI_CHATTER_PC_QUERY_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_CHATTER), + + /** echo event in response to echo command */ + WMI_ECHO_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MISC), + + /* !!IMPORTANT!! + * If you need to add a new WMI event ID to the WMI_GRP_MISC sub-group, + * please make sure you add it BEHIND WMI_PDEV_UTF_EVENTID, + * as we MUST have a fixed value here to maintain compatibility between + * UTF and the ART2 driver + */ + /** UTF specific WMI event */ + WMI_PDEV_UTF_EVENTID, + + /** event carries buffered debug messages */ + WMI_DEBUG_MESG_EVENTID, + /** FW stats(periodic or on shot) */ + WMI_UPDATE_STATS_EVENTID, + /** debug print message used for tracing FW code while debugging */ + WMI_DEBUG_PRINT_EVENTID, + /** DCS wlan or non-wlan interference event + */ + WMI_DCS_INTERFERENCE_EVENTID, + /** VI spoecific event */ + WMI_PDEV_QVIT_EVENTID, + /** FW code profile data in response to profile request */ + WMI_WLAN_PROFILE_DATA_EVENTID, + /* Factory Testing Mode request event + * used for integrated chipsets */ + WMI_PDEV_FTM_INTG_EVENTID, + /* avoid list of frequencies . + */ + WMI_WLAN_FREQ_AVOID_EVENTID, + /* Indicate the keepalive parameters */ + WMI_VDEV_GET_KEEPALIVE_EVENTID, + /* Thermal Management event */ + WMI_THERMAL_MGMT_EVENTID, + + /* Container for QXDM/DIAG events */ + WMI_DIAG_DATA_CONTAINER_EVENTID, + + /* host auto shutdown event */ + WMI_HOST_AUTO_SHUTDOWN_EVENTID, + + /*update mib counters together with WMI_UPDATE_STATS_EVENTID*/ + WMI_UPDATE_WHAL_MIB_STATS_EVENTID, + + /*update ht/vht info based on vdev (rx and tx NSS and preamble)*/ + WMI_UPDATE_VDEV_RATE_STATS_EVENTID, + + WMI_DIAG_EVENTID, + + /** Set OCB Sched Response, deprecated */ + WMI_OCB_SET_SCHED_EVENTID, + + /** event to indicate the flush of the buffered debug messages is complete*/ + WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID, + + /** event to report mix/max RSSI breach events */ + WMI_RSSI_BREACH_EVENTID, + + /** event to report completion of data storage into flash memory */ + WMI_TRANSFER_DATA_TO_FLASH_COMPLETE_EVENTID, + + /** event to report SCPC calibrated data to host */ + WMI_PDEV_UTF_SCPC_EVENTID, + + /* GPIO Event */ + WMI_GPIO_INPUT_EVENTID=WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), + /** upload H_CV info WMI event + * to indicate uploaded H_CV info to host + */ + WMI_UPLOADH_EVENTID, + + /** capture H info WMI event + * to indicate captured H info to host + */ + WMI_CAPTUREH_EVENTID, + /* hw RFkill */ + WMI_RFKILL_STATE_CHANGE_EVENTID, + + /* TDLS Event */ + WMI_TDLS_PEER_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_TDLS), + + /** STA SMPS Event */ + /** force SMPS mode */ + WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_STA_SMPS), + + /*location scan event*/ + /*report the firmware's capability of batch scan*/ + WMI_BATCH_SCAN_ENABLED_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_LOCATION_SCAN), + /*batch scan result*/ + WMI_BATCH_SCAN_RESULT_EVENTID, + /* OEM Event */ + WMI_OEM_CAPABILITY_EVENTID=WMI_EVT_GRP_START_ID(WMI_GRP_OEM), /*DEPRECATED*/ + WMI_OEM_MEASUREMENT_REPORT_EVENTID, /* DEPRECATED */ + WMI_OEM_ERROR_REPORT_EVENTID, /* DEPRECATED */ + WMI_OEM_RESPONSE_EVENTID, + + /* NAN Event */ + WMI_NAN_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_NAN), + + /* LPI Event */ + WMI_LPI_RESULT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_LPI), + WMI_LPI_STATUS_EVENTID, + WMI_LPI_HANDOFF_EVENTID, + + /* ExtScan events */ + WMI_EXTSCAN_START_STOP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_EXTSCAN), + WMI_EXTSCAN_OPERATION_EVENTID, + WMI_EXTSCAN_TABLE_USAGE_EVENTID, + WMI_EXTSCAN_CACHED_RESULTS_EVENTID, + WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID, + WMI_EXTSCAN_HOTLIST_MATCH_EVENTID, + WMI_EXTSCAN_CAPABILITIES_EVENTID, + WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID, + + /* mDNS offload events */ + WMI_MDNS_STATS_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MDNS_OFL), + + /* SAP Authentication offload events */ + WMI_SAP_OFL_ADD_STA_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_SAP_OFL), + WMI_SAP_OFL_DEL_STA_EVENTID, + + + /** Out-of-context-of-bss (OCB) events */ + WMI_OCB_SET_CONFIG_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_OCB), + WMI_OCB_GET_TSF_TIMER_RESP_EVENTID, + WMI_DCC_GET_STATS_RESP_EVENTID, + WMI_DCC_UPDATE_NDL_RESP_EVENTID, + WMI_DCC_STATS_EVENTID, + + /* System-On-Chip events */ + WMI_SOC_SET_HW_MODE_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_SOC), + WMI_SOC_HW_MODE_TRANSITION_EVENTID, + WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID, + /** Motion Aided WiFi Connectivity (MAWC) events */ + WMI_MAWC_ENABLE_SENSOR_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MAWC), +} WMI_EVT_ID; + +/* defines for OEM message sub-types */ +#define WMI_OEM_CAPABILITY_REQ 0x01 +#define WMI_OEM_CAPABILITY_RSP 0x02 +#define WMI_OEM_MEASUREMENT_REQ 0x03 +#define WMI_OEM_MEASUREMENT_RSP 0x04 +#define WMI_OEM_ERROR_REPORT_RSP 0x05 +#define WMI_OEM_NAN_MEAS_REQ 0x06 +#define WMI_OEM_NAN_MEAS_RSP 0x07 +#define WMI_OEM_NAN_PEER_INFO 0x08 +#define WMI_OEM_CONFIGURE_LCR 0x09 +#define WMI_OEM_CONFIGURE_LCI 0x0A + + +/* below message subtype is internal to CLD. Target should + * never use internal response type + */ +#define WMI_OEM_INTERNAL_RSP 0xdeadbeef + +#define WMI_CHAN_LIST_TAG 0x1 +#define WMI_SSID_LIST_TAG 0x2 +#define WMI_BSSID_LIST_TAG 0x3 +#define WMI_IE_TAG 0x4 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_channel */ + /** primary 20 MHz channel frequency in mhz */ + A_UINT32 mhz; + /** Center frequency 1 in MHz*/ + A_UINT32 band_center_freq1; + /** Center frequency 2 in MHz - valid only for 11acvht 80plus80 mode*/ + A_UINT32 band_center_freq2; + /** channel info described below */ + A_UINT32 info; + /** contains min power, max power, reg power and reg class id. */ + A_UINT32 reg_info_1; + /** contains antennamax */ + A_UINT32 reg_info_2; +} wmi_channel; + +typedef enum{ +WMI_CHANNEL_CHANGE_CAUSE_NONE = 0, +WMI_CHANNEL_CHANGE_CAUSE_CSA, +}wmi_channel_change_cause; + +/** channel info consists of 6 bits of channel mode */ + +#define WMI_SET_CHANNEL_MODE(pwmi_channel,val) do { \ + (pwmi_channel)->info &= 0xffffffc0; \ + (pwmi_channel)->info |= (val); \ + } while(0) + +#define WMI_GET_CHANNEL_MODE(pwmi_channel) ((pwmi_channel)->info & 0x0000003f ) + +#define WMI_CHAN_FLAG_HT40_PLUS 6 +#define WMI_CHAN_FLAG_PASSIVE 7 +#define WMI_CHAN_ADHOC_ALLOWED 8 +#define WMI_CHAN_AP_DISABLED 9 +#define WMI_CHAN_FLAG_DFS 10 +#define WMI_CHAN_FLAG_ALLOW_HT 11 /* HT is allowed on this channel */ +#define WMI_CHAN_FLAG_ALLOW_VHT 12 /* VHT is allowed on this channel */ +#define WMI_CHANNEL_CHANGE_CAUSE_CSA 13 /*Indicate reason for channel switch */ +#define WMI_CHAN_FLAG_HALF_RATE 14 /* Indicates half rate channel */ +#define WMI_CHAN_FLAG_QUARTER_RATE 15 /* Indicates quarter rate channel */ + +#define WMI_SET_CHANNEL_FLAG(pwmi_channel,flag) do { \ + (pwmi_channel)->info |= (1 << flag); \ + } while(0) + +#define WMI_GET_CHANNEL_FLAG(pwmi_channel,flag) \ + (((pwmi_channel)->info & (1 << flag)) >> flag) + +#define WMI_SET_CHANNEL_MIN_POWER(pwmi_channel,val) do { \ + (pwmi_channel)->reg_info_1 &= 0xffffff00; \ + (pwmi_channel)->reg_info_1 |= (val&0xff); \ + } while(0) +#define WMI_GET_CHANNEL_MIN_POWER(pwmi_channel) ((pwmi_channel)->reg_info_1 & 0xff ) + +#define WMI_SET_CHANNEL_MAX_POWER(pwmi_channel,val) do { \ + (pwmi_channel)->reg_info_1 &= 0xffff00ff; \ + (pwmi_channel)->reg_info_1 |= ((val&0xff) << 8); \ + } while(0) +#define WMI_GET_CHANNEL_MAX_POWER(pwmi_channel) ( (((pwmi_channel)->reg_info_1) >> 8) & 0xff ) + +#define WMI_SET_CHANNEL_REG_POWER(pwmi_channel,val) do { \ + (pwmi_channel)->reg_info_1 &= 0xff00ffff; \ + (pwmi_channel)->reg_info_1 |= ((val&0xff) << 16); \ + } while(0) +#define WMI_GET_CHANNEL_REG_POWER(pwmi_channel) ( (((pwmi_channel)->reg_info_1) >> 16) & 0xff ) +#define WMI_SET_CHANNEL_REG_CLASSID(pwmi_channel,val) do { \ + (pwmi_channel)->reg_info_1 &= 0x00ffffff; \ + (pwmi_channel)->reg_info_1 |= ((val&0xff) << 24); \ + } while(0) +#define WMI_GET_CHANNEL_REG_CLASSID(pwmi_channel) ( (((pwmi_channel)->reg_info_1) >> 24) & 0xff ) + +#define WMI_SET_CHANNEL_ANTENNA_MAX(pwmi_channel,val) do { \ + (pwmi_channel)->reg_info_2 &= 0xffffff00; \ + (pwmi_channel)->reg_info_2 |= (val&0xff); \ + } while(0) +#define WMI_GET_CHANNEL_ANTENNA_MAX(pwmi_channel) ((pwmi_channel)->reg_info_2 & 0xff ) + +/* max tx power is in 1 dBm units */ +#define WMI_SET_CHANNEL_MAX_TX_POWER(pwmi_channel,val) do { \ + (pwmi_channel)->reg_info_2 &= 0xffff00ff; \ + (pwmi_channel)->reg_info_2 |= ((val&0xff)<<8); \ + } while(0) +#define WMI_GET_CHANNEL_MAX_TX_POWER(pwmi_channel) ( (((pwmi_channel)->reg_info_2)>>8) & 0xff ) + + +/** HT Capabilities*/ +#define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */ +#define WMI_HT_CAP_HT20_SGI 0x0002 /* Short Guard Interval with HT20 */ +#define WMI_HT_CAP_DYNAMIC_SMPS 0x0004 /* Dynamic MIMO powersave */ +#define WMI_HT_CAP_TX_STBC 0x0008 /* B3 TX STBC */ +#define WMI_HT_CAP_TX_STBC_MASK_SHIFT 3 +#define WMI_HT_CAP_RX_STBC 0x0030 /* B4-B5 RX STBC */ +#define WMI_HT_CAP_RX_STBC_MASK_SHIFT 4 +#define WMI_HT_CAP_LDPC 0x0040 /* LDPC supported */ +#define WMI_HT_CAP_L_SIG_TXOP_PROT 0x0080 /* L-SIG TXOP Protection */ +#define WMI_HT_CAP_MPDU_DENSITY 0x0700 /* MPDU Density */ +#define WMI_HT_CAP_MPDU_DENSITY_MASK_SHIFT 8 +#define WMI_HT_CAP_HT40_SGI 0x0800 + +/* These macros should be used when we wish to advertise STBC support for + * only 1SS or 2SS or 3SS. */ +#define WMI_HT_CAP_RX_STBC_1SS 0x0010 /* B4-B5 RX STBC */ +#define WMI_HT_CAP_RX_STBC_2SS 0x0020 /* B4-B5 RX STBC */ +#define WMI_HT_CAP_RX_STBC_3SS 0x0030 /* B4-B5 RX STBC */ + + +#define WMI_HT_CAP_DEFAULT_ALL (WMI_HT_CAP_ENABLED | \ + WMI_HT_CAP_HT20_SGI | \ + WMI_HT_CAP_HT40_SGI | \ + WMI_HT_CAP_TX_STBC | \ + WMI_HT_CAP_RX_STBC | \ + WMI_HT_CAP_LDPC) + +/* WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information + field. The fields not defined here are not supported, or reserved. + Do not change these masks and if you have to add new one follow the + bitmask as specified by 802.11ac draft. +*/ + +#define WMI_VHT_CAP_MAX_MPDU_LEN_7935 0x00000001 +#define WMI_VHT_CAP_MAX_MPDU_LEN_11454 0x00000002 +#define WMI_VHT_CAP_MAX_MPDU_LEN_MASK 0x00000003 +#define WMI_VHT_CAP_CH_WIDTH_160MHZ 0x00000004 +#define WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ 0x00000008 +#define WMI_VHT_CAP_RX_LDPC 0x00000010 +#define WMI_VHT_CAP_SGI_80MHZ 0x00000020 +#define WMI_VHT_CAP_SGI_160MHZ 0x00000040 +#define WMI_VHT_CAP_TX_STBC 0x00000080 +#define WMI_VHT_CAP_RX_STBC_MASK 0x00000300 +#define WMI_VHT_CAP_RX_STBC_MASK_SHIFT 8 +#define WMI_VHT_CAP_SU_BFORMER 0x00000800 +#define WMI_VHT_CAP_SU_BFORMEE 0x00001000 +#define WMI_VHT_CAP_MAX_CS_ANT_MASK 0x0000E000 +#define WMI_VHT_CAP_MAX_CS_ANT_MASK_SHIFT 13 +#define WMI_VHT_CAP_MAX_SND_DIM_MASK 0x00070000 +#define WMI_VHT_CAP_MAX_SND_DIM_MASK_SHIFT 16 +#define WMI_VHT_CAP_MU_BFORMER 0x00080000 +#define WMI_VHT_CAP_MU_BFORMEE 0x00100000 +#define WMI_VHT_CAP_TXOP_PS 0x00200000 +#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP 0x03800000 +#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT 23 +#define WMI_VHT_CAP_RX_FIXED_ANT 0x10000000 +#define WMI_VHT_CAP_TX_FIXED_ANT 0x20000000 + +/* TEMPORARY: + * Preserve the incorrect old name as an alias for the correct new name + * until all references to the old name have been removed from all hosts + * and targets. + */ +#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIT WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT + +/* These macros should be used when we wish to advertise STBC support for + * only 1SS or 2SS or 3SS. */ +#define WMI_VHT_CAP_RX_STBC_1SS 0x00000100 +#define WMI_VHT_CAP_RX_STBC_2SS 0x00000200 +#define WMI_VHT_CAP_RX_STBC_3SS 0x00000300 + +/* TEMPORARY: + * Preserve the incorrect old name as an alias for the correct new name + * until all references to the old name have been removed from all hosts + * and targets. + */ +#define WMI_vHT_CAP_RX_STBC_3SS WMI_VHT_CAP_RX_STBC_3SS + +#define WMI_VHT_CAP_DEFAULT_ALL (WMI_VHT_CAP_MAX_MPDU_LEN_11454 | \ + WMI_VHT_CAP_SGI_80MHZ | \ + WMI_VHT_CAP_TX_STBC | \ + WMI_VHT_CAP_RX_STBC_MASK | \ + WMI_VHT_CAP_RX_LDPC | \ + WMI_VHT_CAP_MAX_AMPDU_LEN_EXP | \ + WMI_VHT_CAP_RX_FIXED_ANT | \ + WMI_VHT_CAP_TX_FIXED_ANT) + +/* Interested readers refer to Rx/Tx MCS Map definition as defined in + 802.11ac +*/ +#define WMI_VHT_MAX_MCS_4_SS_MASK(r,ss) ((3 & (r)) << (((ss) - 1) << 1)) +#define WMI_VHT_MAX_SUPP_RATE_MASK 0x1fff0000 +#define WMI_VHT_MAX_SUPP_RATE_MASK_SHIFT 16 + +/* WMI_SYS_CAPS_* refer to the capabilities that system support +*/ +#define WMI_SYS_CAP_ENABLE 0x00000001 +#define WMI_SYS_CAP_TXPOWER 0x00000002 + +/* + * WMI Dual Band Simultaneous (DBS) hardware mode list bit-mask definitions. + * Bits 5:0 are reserved + */ +#define WMI_DBS_HW_MODE_MAC0_TX_STREAMS_BITPOS (28) +#define WMI_DBS_HW_MODE_MAC0_RX_STREAMS_BITPOS (24) +#define WMI_DBS_HW_MODE_MAC1_TX_STREAMS_BITPOS (20) +#define WMI_DBS_HW_MODE_MAC1_RX_STREAMS_BITPOS (16) +#define WMI_DBS_HW_MODE_MAC0_BANDWIDTH_BITPOS (12) +#define WMI_DBS_HW_MODE_MAC1_BANDWIDTH_BITPOS (8) +#define WMI_DBS_HW_MODE_DBS_MODE_BITPOS (7) +#define WMI_DBS_HW_MODE_AGILE_DFS_MODE_BITPOS (6) + +#define WMI_DBS_HW_MODE_MAC0_TX_STREAMS_MASK (0xf << WMI_DBS_HW_MODE_MAC0_TX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC0_RX_STREAMS_MASK (0xf << WMI_DBS_HW_MODE_MAC0_RX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC1_TX_STREAMS_MASK (0xf << WMI_DBS_HW_MODE_MAC1_TX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC1_RX_STREAMS_MASK (0xf << WMI_DBS_HW_MODE_MAC1_RX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC0_BANDWIDTH_MASK (0xf << WMI_DBS_HW_MODE_MAC0_BANDWIDTH_BITPOS) +#define WMI_DBS_HW_MODE_MAC1_BANDWIDTH_MASK (0xf << WMI_DBS_HW_MODE_MAC1_BANDWIDTH_BITPOS) +#define WMI_DBS_HW_MODE_DBS_MODE_MASK (0x1 << WMI_DBS_HW_MODE_DBS_MODE_BITPOS) +#define WMI_DBS_HW_MODE_AGILE_DFS_MODE_MASK (0x1 << WMI_DBS_HW_MODE_AGILE_DFS_MODE_BITPOS) + +#define WMI_DBS_HW_MODE_MAC0_TX_STREAMS_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_MAC0_TX_STREAMS_BITPOS, 4, value) +#define WMI_DBS_HW_MODE_MAC0_RX_STREAMS_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_MAC0_RX_STREAMS_BITPOS, 4, value) +#define WMI_DBS_HW_MODE_MAC1_TX_STREAMS_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_MAC1_TX_STREAMS_BITPOS, 4, value) +#define WMI_DBS_HW_MODE_MAC1_RX_STREAMS_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_MAC1_RX_STREAMS_BITPOS, 4, value) +#define WMI_DBS_HW_MODE_MAC0_BANDWIDTH_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_MAC0_BANDWIDTH_BITPOS, 4, value) +#define WMI_DBS_HW_MODE_MAC1_BANDWIDTH_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_MAC1_BANDWIDTH_BITPOS, 4, value) +#define WMI_DBS_HW_MODE_DBS_MODE_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_DBS_MODE_BITPOS, 1, value) +#define WMI_DBS_HW_MODE_AGILE_DFS_SET(hw_mode, value) \ + WMI_SET_BITS(hw_mode, WMI_DBS_HW_MODE_AGILE_DFS_MODE_BITPOS, 1, value) + +#define WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_MAC0_TX_STREAMS_MASK) >> WMI_DBS_HW_MODE_MAC0_TX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_MAC0_RX_STREAMS_MASK) >> WMI_DBS_HW_MODE_MAC0_RX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_MAC1_TX_STREAMS_MASK) >> WMI_DBS_HW_MODE_MAC1_TX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_MAC1_RX_STREAMS_MASK) >> WMI_DBS_HW_MODE_MAC1_RX_STREAMS_BITPOS) +#define WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_MAC0_BANDWIDTH_MASK) >> WMI_DBS_HW_MODE_MAC0_BANDWIDTH_BITPOS) +#define WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_MAC1_BANDWIDTH_MASK) >> WMI_DBS_HW_MODE_MAC1_BANDWIDTH_BITPOS) +#define WMI_DBS_HW_MODE_DBS_MODE_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_DBS_MODE_MASK) >> WMI_DBS_HW_MODE_DBS_MODE_BITPOS) +#define WMI_DBS_HW_MODE_AGILE_DFS_GET(hw_mode) \ + ((hw_mode & WMI_DBS_HW_MODE_AGILE_DFS_MODE_MASK) >> WMI_DBS_HW_MODE_AGILE_DFS_MODE_BITPOS) + +#define WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_BITPOS (31) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_BITPOS (30) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_BITPOS (29) + +#define WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_MASK (0x1 << WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_BITPOS) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_MASK (0x1 << WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_BITPOS) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_MASK (0x1 << WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_BITPOS) + +#define WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET(scan_cfg, value) \ + WMI_SET_BITS(scan_cfg, WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_BITPOS, 1, value) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET(scan_cfg, value) \ + WMI_SET_BITS(scan_cfg, WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_BITPOS, 1, value) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET(scan_cfg, value) \ + WMI_SET_BITS(scan_cfg, WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_BITPOS, 1, value) + +#define WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_cfg) \ + ((scan_cfg & WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_MASK) >> WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_BITPOS) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_cfg) \ + ((scan_cfg & WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_MASK) >> WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_BITPOS) +#define WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_cfg) \ + ((scan_cfg & WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_MASK) >> WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_BITPOS) + +#define WMI_DBS_FW_MODE_CFG_DBS_BITPOS (31) +#define WMI_DBS_FW_MODE_CFG_AGILE_DFS_BITPOS (30) + +#define WMI_DBS_FW_MODE_CFG_DBS_MASK (0x1 << WMI_DBS_FW_MODE_CFG_DBS_BITPOS) +#define WMI_DBS_FW_MODE_CFG_AGILE_DFS_MASK (0x1 << WMI_DBS_FW_MODE_CFG_AGILE_DFS_BITPOS) + +#define WMI_DBS_FW_MODE_CFG_DBS_SET(fw_mode, value) \ + WMI_SET_BITS(fw_mode, WMI_DBS_FW_MODE_CFG_DBS_BITPOS, 1, value) +#define WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET(fw_mode, value) \ + WMI_SET_BITS(fw_mode, WMI_DBS_FW_MODE_CFG_AGILE_DFS_BITPOS, 1, value) + +#define WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode) \ + ((fw_mode & WMI_DBS_FW_MODE_CFG_DBS_MASK) >> WMI_DBS_FW_MODE_CFG_DBS_BITPOS) +#define WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode) \ + ((fw_mode & WMI_DBS_FW_MODE_CFG_AGILE_DFS_MAS) >> WMI_DBS_FW_MODE_CFG_AGILE_DFS_BITPOS) + +/** NOTE: This structure cannot be extended in the future without breaking WMI compatibility */ +typedef struct _wmi_abi_version { + A_UINT32 abi_version_0; /** WMI Major and Minor versions */ + A_UINT32 abi_version_1; /** WMI change revision */ + A_UINT32 abi_version_ns_0; /** ABI version namespace first four dwords */ + A_UINT32 abi_version_ns_1; /** ABI version namespace second four dwords */ + A_UINT32 abi_version_ns_2; /** ABI version namespace third four dwords */ + A_UINT32 abi_version_ns_3; /** ABI version namespace fourth four dwords */ +} wmi_abi_version; + +/* +* maximum number of memroy requests allowed from FW. +*/ +#define WMI_MAX_MEM_REQS 16 + +/* !!NOTE!!: + * This HW_BD_INFO_SIZE cannot be changed without breaking compatibility. + * Please don't change it. + */ +#define HW_BD_INFO_SIZE 5 + +/** + * The following struct holds optional payload for + * wmi_service_ready_event_fixed_param,e.g., 11ac pass some of the + * device capability to the host. +*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_SERVICE_READY_EVENT */ + A_UINT32 fw_build_vers; /* firmware build number */ + wmi_abi_version fw_abi_vers; + A_UINT32 phy_capability; /* WMI_PHY_CAPABILITY */ + A_UINT32 max_frag_entry; /* Maximum number of frag table entries that SW will populate less 1 */ + A_UINT32 num_rf_chains; + /* The following field is only valid for service type WMI_SERVICE_11AC */ + A_UINT32 ht_cap_info; /* WMI HT Capability */ + A_UINT32 vht_cap_info; /* VHT capability info field of 802.11ac */ + A_UINT32 vht_supp_mcs; /* VHT Supported MCS Set field Rx/Tx same */ + A_UINT32 hw_min_tx_power; + A_UINT32 hw_max_tx_power; + A_UINT32 sys_cap_info; + A_UINT32 min_pkt_size_enable; /* Enterprise mode short pkt enable */ + /** Max beacon and Probe Response IE offload size (includes + * optional P2P IEs) */ + A_UINT32 max_bcn_ie_size; + /* + * request to host to allocate a chuck of memory and pss it down to FW via WM_INIT. + * FW uses this as FW extesnsion memory for saving its data structures. Only valid + * for low latency interfaces like PCIE where FW can access this memory directly (or) + * by DMA. + */ + A_UINT32 num_mem_reqs; + /* Max No. scan channels target can support + * If FW is too old and doesn't indicate this number, host side value will default to + * 0, and host will take the original compatible value (62) for future scan channel + * setup. + */ + A_UINT32 max_num_scan_channels; + + /* Hardware board specific ID. Values defined in enum WMI_HWBOARD_ID. + * Default 0 means tha hw_bd_info[] is invalid(legacy board). + */ + A_UINT32 hw_bd_id; + A_UINT32 hw_bd_info[HW_BD_INFO_SIZE]; /* Board specific information. Invalid if hw_hd_id is zero. */ + + /* + * Number of MACs supported, i.e. a DBS-capable device will return 2 + */ + A_UINT32 max_supported_macs; + + /* + * FW sub-feature capabilities to be used in concurrence with wmi_service_bitmap + */ + A_UINT32 wmi_fw_sub_feat_caps; //values from enum WMI_FW_SUB_FEAT_CAPS + + /* + * Number of Dual Band Simultaneous (DBS) hardware modes + */ + A_UINT32 num_dbs_hw_modes; + + /* + * txrx_chainmask + * [7:0] - 2G band tx chain mask + * [15:8] - 2G band rx chain mask + * [23:16] - 5G band tx chain mask + * [31:24] - 5G band rx chain mask + * + */ + A_UINT32 txrx_chainmask; + + /* + * default Dual Band Simultaneous (DBS) hardware mode + */ + A_UINT32 default_dbs_hw_mode_index; + + /* + * Number of msdu descriptors target would use + */ + A_UINT32 num_msdu_desc; + + /* The TLVs for hal_reg_capabilities, wmi_service_bitmap and mem_reqs[] will follow this TLV. + * HAL_REG_CAPABILITIES hal_reg_capabilities; + * A_UINT32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; + * wlan_host_mem_req mem_reqs[]; + * wlan_dbs_hw_mode_list[]; + */ +} wmi_service_ready_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_SERVICE_EXT_READY_EVENT */ + /* which WMI_DBS_CONC_SCAN_CFG setting the FW is initialized with */ + A_UINT32 default_conc_scan_config_bits; + /* which WMI_DBS_FW_MODE_CFG setting the FW is initialized with */ + A_UINT32 default_fw_config_bits; +} wmi_service_ready_ext_event_fixed_param; + +typedef enum { + WMI_FW_STA_RTT_INITR = 0x00000001, + WMI_FW_STA_RTT_RESPR = 0x00000002, + WMI_FW_P2P_CLI_RTT_INITR = 0x00000004, + WMI_FW_P2P_CLI_RTT_RESPR = 0x00000008, + WMI_FW_P2P_GO_RTT_INITR = 0x00000010, + WMI_FW_P2P_GO_RTT_RESPR = 0x00000020, + WMI_FW_AP_RTT_INITR = 0x00000040, + WMI_FW_AP_RTT_RESPR = 0x00000080, + WMI_FW_NAN_RTT_INITR = 0x00000100, + WMI_FW_NAN_RTT_RESPR = 0x00000200, + /* + * New fw sub feature capabilites before + * WMI_FW_MAX_SUB_FEAT_CAP + */ + WMI_FW_MAX_SUB_FEAT_CAP = 0x80000000, +} WMI_FW_SUB_FEAT_CAPS; + +typedef enum { + WMI_HWBD_NONE = 0, /* No hw board information is given */ + WMI_HWBD_QCA6174 = 1, /* Rome(AR6320) */ + WMI_HWBD_QCA2582 = 2, /* Killer 1525*/ +} WMI_HWBD_ID; + +#define ATH_BD_DATA_REV_MASK 0x000000FF +#define ATH_BD_DATA_REV_SHIFT 0 + +#define ATH_BD_DATA_PROJ_ID_MASK 0x0000FF00 +#define ATH_BD_DATA_PROJ_ID_SHIFT 8 + +#define ATH_BD_DATA_CUST_ID_MASK 0x00FF0000 +#define ATH_BD_DATA_CUST_ID_SHIFT 16 + +#define ATH_BD_DATA_REF_DESIGN_ID_MASK 0xFF000000 +#define ATH_BD_DATA_REF_DESIGN_ID_SHIFT 24 + +#define SET_BD_DATA_REV(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_REV_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_REV_SHIFT)) + +#define GET_BD_DATA_REV(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_REV_MASK) >> ATH_BD_DATA_REV_SHIFT) + +#define SET_BD_DATA_PROJ_ID(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_PROJ_ID_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_PROJ_ID_SHIFT)) + +#define GET_BD_DATA_PROJ_ID(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_PROJ_ID_MASK) >> ATH_BD_DATA_PROJ_ID_SHIFT) + +#define SET_BD_DATA_CUST_ID(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_CUST_ID_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_CUST_ID_SHIFT)) + +#define GET_BD_DATA_CUST_ID(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_CUST_ID_MASK) >> ATH_BD_DATA_CUST_ID_SHIFT) + +#define SET_BD_DATA_REF_DESIGN_ID(bd_data_ver, value) \ + ((bd_data_ver) &= ~ATH_BD_DATA_REF_DESIGN_ID_MASK, (bd_data_ver) |= ((value) << ATH_BD_DATA_REF_DESIGN_ID_SHIFT)) + +#define GET_BD_DATA_REF_DESIGN_ID(bd_data_ver) \ + (((bd_data_ver) & ATH_BD_DATA_REF_DESIGN_ID_MASK) >> ATH_BD_DATA_REF_DESIGN_ID_SHIFT) + +#ifdef ROME_LTE_COEX_FREQ_AVOID +typedef struct { + A_UINT32 start_freq; //start frequency, not channel center freq + A_UINT32 end_freq;//end frequency +}avoid_freq_range_desc; + +typedef struct { + //bad channel range count, multi range is allowed, 0 means all channel clear + A_UINT32 num_freq_ranges; + //multi range with num_freq_ranges, LTE advance multi carrier, CDMA,etc + avoid_freq_range_desc avd_freq_range[0]; +}wmi_wlan_avoid_freq_ranges_event; +#endif + +/** status consists of upper 16 bits fo A_STATUS status and lower 16 bits of module ID that retuned status */ +#define WLAN_INIT_STATUS_SUCCESS 0x0 +#define WLAN_INIT_STATUS_GEN_FAILED 0x1 +#define WLAN_GET_INIT_STATUS_REASON(status) ((status) & 0xffff) +#define WLAN_GET_INIT_STATUS_MODULE_ID(status) (((status) >> 16) & 0xffff) + +typedef A_UINT32 WLAN_INIT_STATUS; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ready_event_fixed_param */ + wmi_abi_version fw_abi_vers; + wmi_mac_addr mac_addr; + A_UINT32 status; +} wmi_ready_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_resource_config */ +/** + * @brief num_vdev - number of virtual devices (VAPs) to support + */ + A_UINT32 num_vdevs; +/** + * @brief num_peers - number of peer nodes to support + */ + A_UINT32 num_peers; +/* + * @brief In offload mode target supports features like WOW, chatter and other + * protocol offloads. In order to support them some functionalities like + * reorder buffering, PN checking need to be done in target. This determines + * maximum number of peers suported by target in offload mode + */ + A_UINT32 num_offload_peers; +/* @brief Number of reorder buffers available for doing target based reorder + * Rx reorder buffering + */ + A_UINT32 num_offload_reorder_buffs; +/** + * @brief num_peer_keys - number of keys per peer + */ + A_UINT32 num_peer_keys; +/** + * @brief num_peer_tids - number of TIDs to provide storage for per peer. + */ + A_UINT32 num_tids; +/** + * @brief ast_skid_limit - max skid for resolving hash collisions + * @details + * The address search table is sparse, so that if two MAC addresses + * result in the same hash value, the second of these conflicting + * entries can slide to the next index in the address search table, + * and use it, if it is unoccupied. This ast_skid_limit parameter + * specifies the upper bound on how many subsequent indices to search + * over to find an unoccupied space. + */ + A_UINT32 ast_skid_limit; +/** + * @brief tx_chain_mask - the nominal chain mask for transmit + * @details + * The chain mask may be modified dynamically, e.g. to operate AP tx with + * a reduced number of chains if no clients are associated. + * This configuration parameter specifies the nominal chain-mask that + * should be used when not operating with a reduced set of tx chains. + */ + A_UINT32 tx_chain_mask; +/** + * @brief rx_chain_mask - the nominal chain mask for receive + * @details + * The chain mask may be modified dynamically, e.g. for a client to use + * a reduced number of chains for receive if the traffic to the client + * is low enough that it doesn't require downlink MIMO or antenna + * diversity. + * This configuration parameter specifies the nominal chain-mask that + * should be used when not operating with a reduced set of rx chains. + */ + A_UINT32 rx_chain_mask; +/** + * @brief rx_timeout_pri - what rx reorder timeout (ms) to use for the AC + * @details + * Each WMM access class (voice, video, best-effort, background) will + * have its own timeout value to dictate how long to wait for missing + * rx MPDUs to arrive before flushing subsequent MPDUs that have already + * been received. + * This parameter specifies the timeout in milliseconds for each class . + * NOTE: the number of class (defined as 4) cannot be + * changed in the future without breaking WMI compatibility. + */ + A_UINT32 rx_timeout_pri[4]; +/** + * @brief rx_decap mode - what mode the rx should decap packets to + * @details + * MAC can decap to RAW (no decap), native wifi or Ethernet types + * THis setting also determines the default TX behavior, however TX + * behavior can be modified on a per VAP basis during VAP init + */ + A_UINT32 rx_decap_mode; + /** + * @brief scan_max_pending_req - what is the maximum scan requests than can be queued + */ + A_UINT32 scan_max_pending_req; + + /** + * @brief maximum VDEV that could use BMISS offload + */ + A_UINT32 bmiss_offload_max_vdev; + + /** + * @brief maximum VDEV that could use offload roaming + */ + A_UINT32 roam_offload_max_vdev; + + /** + * @brief maximum AP profiles that would push to offload roaming + */ + A_UINT32 roam_offload_max_ap_profiles; + +/** + * @brief num_mcast_groups - how many groups to use for mcast->ucast conversion + * @details + * The target's WAL maintains a table to hold information regarding which + * peers belong to a given multicast group, so that if multicast->unicast + * conversion is enabled, the target can convert multicast tx frames to a + * series of unicast tx frames, to each peer within the multicast group. + * This num_mcast_groups configuration parameter tells the target how + * many multicast groups to provide storage for within its multicast + * group membership table. + */ + A_UINT32 num_mcast_groups; + +/** + * @brief num_mcast_table_elems - size to alloc for the mcast membership table + * @details + * This num_mcast_table_elems configuration parameter tells the target + * how many peer elements it needs to provide storage for in its + * multicast group membership table. + * These multicast group membership table elements are shared by the + * multicast groups stored within the table. + */ + A_UINT32 num_mcast_table_elems; + +/** + * @brief mcast2ucast_mode - whether/how to do multicast->unicast conversion + * @details + * This configuration parameter specifies whether the target should + * perform multicast --> unicast conversion on transmit, and if so, + * what to do if it finds no entries in its multicast group membership + * table for the multicast IP address in the tx frame. + * Configuration value: + * 0 -> Do not perform multicast to unicast conversion. + * 1 -> Convert multicast frames to unicast, if the IP multicast address + * from the tx frame is found in the multicast group membership + * table. If the IP multicast address is not found, drop the frame. + * 2 -> Convert multicast frames to unicast, if the IP multicast address + * from the tx frame is found in the multicast group membership + * table. If the IP multicast address is not found, transmit the + * frame as multicast. + */ + A_UINT32 mcast2ucast_mode; + + + /** + * @brief tx_dbg_log_size - how much memory to allocate for a tx PPDU dbg log + * @details + * This parameter controls how much memory the target will allocate to + * store a log of tx PPDU meta-information (how large the PPDU was, + * when it was sent, whether it was successful, etc.) + */ + A_UINT32 tx_dbg_log_size; + + /** + * @brief num_wds_entries - how many AST entries to be allocated for WDS + */ + A_UINT32 num_wds_entries; + + /** + * @brief dma_burst_size - MAC DMA burst size, e.g., on Peregrine on PCI + * this limit can be 0 -default, 1 256B + */ + A_UINT32 dma_burst_size; + + /** + * @brief mac_aggr_delim - Fixed delimiters to be inserted after every MPDU + * to account for interface latency to avoid underrun. + */ + A_UINT32 mac_aggr_delim; + /** + * @brief rx_skip_defrag_timeout_dup_detection_check + * @details + * determine whether target is responsible for detecting duplicate + * non-aggregate MPDU and timing out stale fragments. + * + * A-MPDU reordering is always performed on the target. + * + * 0: target responsible for frag timeout and dup checking + * 1: host responsible for frag timeout and dup checking + */ + A_UINT32 rx_skip_defrag_timeout_dup_detection_check; + + /** + * @brief vow_config - Configuration for VoW : No of Video Nodes to be supported + * and Max no of descriptors for each Video link (node). + */ + A_UINT32 vow_config; + + /** + * @brief maximum VDEV that could use GTK offload + */ + A_UINT32 gtk_offload_max_vdev; + + /** + * @brief num_msdu_desc - Number of msdu descriptors target should use + */ + A_UINT32 num_msdu_desc; /* Number of msdu desc */ + /** + * @brief max_frag_entry - Max. number of Tx fragments per MSDU + * @details + * This parameter controls the max number of Tx fragments per MSDU. + * This is sent by the target as part of the WMI_SERVICE_READY event + * and is overriden by the OS shim as required. + */ + A_UINT32 max_frag_entries; + + /** + * @brief num_tdls_vdevs - Max. number of vdevs that can support TDLS + * @brief num_msdu_desc - Number of vdev that can support beacon offload + */ + + A_UINT32 num_tdls_vdevs; /* number of vdevs allowed to do tdls */ + + /** + * @brief num_tdls_conn_table_entries - Number of peers tracked by tdls vdev + * @details + * Each TDLS enabled vdev can track outgoing transmits/rssi/rates to/of + * peers in a connection tracking table for possible TDLS link creation + * or deletion. This controls the number of tracked peers per vdev. + */ + A_UINT32 num_tdls_conn_table_entries; /* number of peers to track per TDLS vdev */ + A_UINT32 beacon_tx_offload_max_vdev; + A_UINT32 num_multicast_filter_entries; + A_UINT32 num_wow_filters; /*host can configure the number of wow filters*/ + + /** + * @brief num_keep_alive_pattern - Num of keep alive patterns configured + * from host. + */ + A_UINT32 num_keep_alive_pattern; + /** + * @brief keep_alive_pattern_size - keep alive pattern size. + */ + A_UINT32 keep_alive_pattern_size; + + /** + * @brief max_tdls_concurrent_sleep_sta - Number of tdls sleep sta supported + * @details + * Each TDLS STA can become a sleep STA independently. This parameter + * mentions how many such sleep STAs can be supported concurrently. + */ + A_UINT32 max_tdls_concurrent_sleep_sta; + + /** + * @brief max_tdls_concurrent_buffer_sta - Number of tdls buffer sta supported + * @details + * Each TDLS STA can become a buffer STA independently. This parameter + * mentions how many such buffer STAs can be supported concurrently. + */ + A_UINT32 max_tdls_concurrent_buffer_sta; + + /** + * @brief wmi_send_separate - host configures fw to send the wmi separately + */ + A_UINT32 wmi_send_separate; + + /** + * @brief num_ocb_vdevs - Number of vdevs used for OCB support + */ + A_UINT32 num_ocb_vdevs; + + /** + * @brief num_ocb_channels - The supported number of simultaneous OCB channels + */ + A_UINT32 num_ocb_channels; + + /** + * @brief num_ocb_schedules - The supported number of OCB schedule segments + */ + A_UINT32 num_ocb_schedules; +} wmi_resource_config; + + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_init_cmd_fixed_param */ + + /** The following indicate the WMI versions to be supported by + * the host driver. Note that the host driver decide to + * "downgrade" its WMI version support and this may not be the + * native version of the host driver. */ + wmi_abi_version host_abi_vers; + + A_UINT32 num_host_mem_chunks; /** size of array host_mem_chunks[] */ + /* The TLVs for resource_config and host_mem_chunks[] will follow. + * wmi_resource_config resource_config; + * wlan_host_memory_chunk host_mem_chunks[]; + */ + +} wmi_init_cmd_fixed_param; + +/** + * TLV for channel list + */ +typedef struct { + /** WMI_CHAN_LIST_TAG */ + A_UINT32 tag; + /** # of channels to scan */ + A_UINT32 num_chan; + /** channels in Mhz */ + A_UINT32 channel_list[1]; +} wmi_chan_list; + +/** + * TLV for bssid list + */ +typedef struct { + /** WMI_BSSID_LIST_TAG */ + A_UINT32 tag; + /** number of bssids */ + A_UINT32 num_bssid; + /** bssid list */ + wmi_mac_addr bssid_list[1]; +} wmi_bssid_list; + +/** + * TLV for ie data. + */ +typedef struct { + /** WMI_IE_TAG */ + A_UINT32 tag; + /** number of bytes in ie data */ + A_UINT32 ie_len; + /** ie data array (ie_len adjusted to number of words (ie_len + 4)/4 ) */ + A_UINT32 ie_data[1]; +} wmi_ie_data; + + +typedef struct { + /** Len of the SSID */ + A_UINT32 ssid_len; + /** SSID */ + A_UINT32 ssid[8]; +} wmi_ssid; + +typedef struct { + /** WMI_SSID_LIST_TAG */ + A_UINT32 tag; + A_UINT32 num_ssids; + wmi_ssid ssids[1]; +} wmi_ssid_list; + +/* prefix used by scan requestor ids on the host */ +#define WMI_HOST_SCAN_REQUESTOR_ID_PREFIX 0xA000 +/* prefix used by scan request ids generated on the host */ +/* host cycles through the lower 12 bits to generate ids */ +#define WMI_HOST_SCAN_REQ_ID_PREFIX 0xA000 + +#define WLAN_SCAN_PARAMS_MAX_SSID 16 +#define WLAN_SCAN_PARAMS_MAX_BSSID 4 +#define WLAN_SCAN_PARAMS_MAX_IE_LEN 512 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param */ + /** Scan ID */ + A_UINT32 scan_id; + /** Scan requestor ID */ + A_UINT32 scan_req_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** Scan Priority, input to scan scheduler */ + A_UINT32 scan_priority; + /** Scan events subscription */ + A_UINT32 notify_scan_events; + /** dwell time in msec on active channels */ + A_UINT32 dwell_time_active; + /** dwell time in msec on passive channels */ + A_UINT32 dwell_time_passive; + /** min time in msec on the BSS channel,only valid if atleast one VDEV is active*/ + A_UINT32 min_rest_time; + /** max rest time in msec on the BSS channel,only valid if at least one VDEV is active*/ + /** the scanner will rest on the bss channel at least min_rest_time. after min_rest_time the scanner + * will start checking for tx/rx activity on all VDEVs. if there is no activity the scanner will + * switch to off channel. if there is activity the scanner will let the radio on the bss channel + * until max_rest_time expires.at max_rest_time scanner will switch to off channel + * irrespective of activity. activity is determined by the idle_time parameter. + */ + A_UINT32 max_rest_time; + /** time before sending next set of probe requests. + * The scanner keeps repeating probe requests transmission with period specified by repeat_probe_time. + * The number of probe requests specified depends on the ssid_list and bssid_list + */ + A_UINT32 repeat_probe_time; + /** time in msec between 2 consequetive probe requests with in a set. */ + A_UINT32 probe_spacing_time; + /** data inactivity time in msec on bss channel that will be used by scanner for measuring the inactivity */ + A_UINT32 idle_time; + /** maximum time in msec allowed for scan */ + A_UINT32 max_scan_time; + /** delay in msec before sending first probe request after switching to a channel */ + A_UINT32 probe_delay; + /** Scan control flags */ + A_UINT32 scan_ctrl_flags; + /** Burst duration time in msec*/ + A_UINT32 burst_duration; + + /** # if channels to scan. In the TLV channel_list[] */ + A_UINT32 num_chan; + /** number of bssids. In the TLV bssid_list[] */ + A_UINT32 num_bssid; + /** number of ssid. In the TLV ssid_list[] */ + A_UINT32 num_ssids; + /** number of bytes in ie data. In the TLV ie_data[]. Max len is defined by WLAN_SCAN_PARAMS_MAX_IE_LEN */ + A_UINT32 ie_len; + /** Max number of probes to be sent */ + A_UINT32 n_probes; + + + /** + * TLV (tag length value ) parameters follow the scan_cmd + * structure. The TLV's are: + * A_UINT32 channel_list[]; + * wmi_ssid ssid_list[]; + * wmi_mac_addr bssid_list[]; + * A_UINT8 ie_data[]; + */ +} wmi_start_scan_cmd_fixed_param; + +/** + * scan control flags. + */ + +/** passively scan all channels including active channels */ +#define WMI_SCAN_FLAG_PASSIVE 0x1 +/** add wild card ssid probe request even though ssid_list is specified. */ +#define WMI_SCAN_ADD_BCAST_PROBE_REQ 0x2 +/** add cck rates to rates/xrate ie for the generated probe request */ +#define WMI_SCAN_ADD_CCK_RATES 0x4 +/** add ofdm rates to rates/xrate ie for the generated probe request */ +#define WMI_SCAN_ADD_OFDM_RATES 0x8 +/** To enable indication of Chan load and Noise floor to host */ +#define WMI_SCAN_CHAN_STAT_EVENT 0x10 +/** Filter Probe request frames */ +#define WMI_SCAN_FILTER_PROBE_REQ 0x20 +/**When set, not to scan DFS channels*/ +#define WMI_SCAN_BYPASS_DFS_CHN 0x40 +/**When set, certain errors are ignored and scan continues. +* Different FW scan engine may use its own logic to decide what errors to ignore*/ +#define WMI_SCAN_CONTINUE_ON_ERROR 0x80 +/** Enable promiscous mode for ese */ +#define WMI_SCAN_FILTER_PROMISCOUS 0x100 +/** allow to send probe req on DFS channel */ +#define WMI_SCAN_FLAG_FORCE_ACTIVE_ON_DFS 0x200 +/** add TPC content in probe req frame */ +#define WMI_SCAN_ADD_TPC_IE_IN_PROBE_REQ 0x400 +/** add DS content in probe req frame */ +#define WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ 0x800 +/** use random mac address for TA for probe request frame and add + * oui specified by WMI_SCAN_PROB_REQ_OUI_CMDID to the probe req frame. + * if oui is not set by WMI_SCAN_PROB_REQ_OUI_CMDID then the flag is ignored*/ +#define WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ 0x1000 + +/** WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */ +#define WMI_SCAN_CLASS_MASK 0xFF000000 + +/* +* Masks identifying types/ID of scans +* Scan_Stop macros should be the same value as below defined in UMAC +* #define IEEE80211_SPECIFIC_SCAN 0x00000000 +* #define IEEE80211_VAP_SCAN 0x01000000 +* #define IEEE80211_ALL_SCANS 0x04000000 +*/ +#define WMI_SCAN_STOP_ONE 0x00000000 +#define WMI_SCN_STOP_VAP_ALL 0x01000000 +#define WMI_SCAN_STOP_ALL 0x04000000 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param */ + /** requestor requesting cancel */ + A_UINT32 requestor; + /** Scan ID */ + A_UINT32 scan_id; + /** + * Req Type + * req_type should be WMI_SCAN_STOP_ONE, WMI_SCN_STOP_VAP_ALL or WMI_SCAN_STOP_ALL + * WMI_SCAN_STOP_ONE indicates to stop a specific scan with scan_id + * WMI_SCN_STOP_VAP_ALL indicates to stop all scan requests on a specific vDev with vdev_id + * WMI_SCAN_STOP_ALL indicates to stop all scan requests in both Scheduler's queue and Scan Engine + */ + A_UINT32 req_type; + /** + * vDev ID + * used when req_type equals to WMI_SCN_STOP_VAP_ALL, it indexed the vDev on which to stop the scan + */ + A_UINT32 vdev_id; +} wmi_stop_scan_cmd_fixed_param; + +#define MAX_NUM_CHAN_PER_WMI_CMD 58 // each WMI cmd can hold 58 channel entries at most +#define APPEND_TO_EXISTING_CHAN_LIST 1 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_scan_chan_list_cmd_fixed_param */ + A_UINT32 num_scan_chans; /** no of elements in chan_info[] */ + A_UINT32 flags; /* Flags used to control the behavior of channel list update on target side */ + /** Followed by the variable length TLV chan_info: + * wmi_channel chan_info[] */ +} wmi_scan_chan_list_cmd_fixed_param; + +/* + * Priority numbers must be sequential, starting with 0. + */ + /* NOTE: WLAN SCAN_PRIORITY_COUNT can't be changed without breaking the compatibility */ +typedef enum { + WMI_SCAN_PRIORITY_VERY_LOW = 0, + WMI_SCAN_PRIORITY_LOW, + WMI_SCAN_PRIORITY_MEDIUM, + WMI_SCAN_PRIORITY_HIGH, + WMI_SCAN_PRIORITY_VERY_HIGH, + + WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */ +} wmi_scan_priority; + +/* Five Levels for Requested Priority */ +/* VERY_LOW LOW MEDIUM HIGH VERY_HIGH */ +typedef A_UINT32 WLAN_PRIORITY_MAPPING[WMI_SCAN_PRIORITY_COUNT]; + +/** +* to keep align with UMAC implementation, we pass only vdev_type but not vdev_subtype when we overwrite an entry for a specific vdev_subtype +* ex. if we need overwrite P2P Client prority entry, we will overwrite the whole table for WLAN_M_STA +* we will generate the new WLAN_M_STA table with modified P2P Client Entry but keep STA entry intact +*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_scan_sch_priority_table_cmd_fixed_param */ + /** + * used as an index to find the proper table for a specific vdev type in default_scan_priority_mapping_table + * vdev_type should be one of enum in WLAN_OPMODE which inculdes WLAN_M_IBSS, WLAN_M_STA, WLAN_M_AP and WLAN_M_MONITOR currently + */ + A_UINT32 vdev_type; + /** + * number of rows in mapping_table for a specific vdev + * for WLAN_M_STA type, there are 3 entries in the table (refer to default_scan_priority_mapping_table definition) + */ + A_UINT32 number_rows; + /** mapping_table for a specific vdev follows this TLV + * WLAN_PRIORITY_MAPPING mapping_table[]; */ +}wmi_scan_sch_priority_table_cmd_fixed_param; + +/** update flags */ +#define WMI_SCAN_UPDATE_SCAN_PRIORITY 0x1 +#define WMI_SCAN_UPDATE_SCAN_MIN_REST_TIME 0x2 +#define WMI_SCAN_UPDATE_SCAN_MAX_REST_TIME 0x4 + +typedef struct { + A_UINT32 tlv_header; + /** requestor requesting update scan request */ + A_UINT32 requestor; + /** Scan ID of the scan request that need to be update */ + A_UINT32 scan_id; + /** update flags, indicating which of the following fields are valid and need to be updated*/ + A_UINT32 scan_update_flags; + /** scan priority. Only valid if WMI_SCAN_UPDATE_SCAN_PRIORITY flag is set in scan_update_flag */ + A_UINT32 scan_priority; + /** min rest time. Only valid if WMI_SCAN_UPDATE_MIN_REST_TIME flag is set in scan_update_flag */ + A_UINT32 min_rest_time; + /** min rest time. Only valid if WMI_SCAN_UPDATE_MAX_REST_TIME flag is set in scan_update_flag */ + A_UINT32 max_rest_time; +} wmi_scan_update_request_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + /** oui to be used in probe request frame when random mac addresss is + * requested part of scan parameters. this is applied to both FW internal scans and + * host initated scans. host can request for random mac address with + * WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ flag. */ + A_UINT32 prob_req_oui; +} wmi_scan_prob_req_oui_cmd_fixed_param; + +enum wmi_scan_event_type { + WMI_SCAN_EVENT_STARTED=0x1, + WMI_SCAN_EVENT_COMPLETED=0x2, + WMI_SCAN_EVENT_BSS_CHANNEL=0x4, + WMI_SCAN_EVENT_FOREIGN_CHANNEL = 0x8, + WMI_SCAN_EVENT_DEQUEUED=0x10, /* scan request got dequeued */ + WMI_SCAN_EVENT_PREEMPTED=0x20, /* preempted by other high priority scan */ + WMI_SCAN_EVENT_START_FAILED=0x40, /* scan start failed */ + WMI_SCAN_EVENT_RESTARTED=0x80, /*scan restarted*/ + WMI_SCAN_EVENT_MAX=0x8000 +}; + +enum wmi_scan_completion_reason { + /** scan related events */ + WMI_SCAN_REASON_NONE = 0xFF, + WMI_SCAN_REASON_COMPLETED = 0, + WMI_SCAN_REASON_CANCELLED = 1, + WMI_SCAN_REASON_PREEMPTED = 2, + WMI_SCAN_REASON_TIMEDOUT = 3, + WMI_SCAN_REASON_INTERNAL_FAILURE = 4, /* This reason indication failures when performaing scan */ + WMI_SCAN_REASON_MAX, +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_scan_event_fixed_param */ + /** scan event (wmi_scan_event_type) */ + A_UINT32 event; + /** status of the scan completion event */ + A_UINT32 reason; + /** channel freq , only valid for FOREIGN channel event*/ + A_UINT32 channel_freq; + /**id of the requestor whose scan is in progress */ + A_UINT32 requestor; + /**id of the scan that is in progress */ + A_UINT32 scan_id; + /**id of VDEV that requested the scan */ + A_UINT32 vdev_id; +} wmi_scan_event_fixed_param; + +/* WMI Diag event */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag is WMITLV_TAG_STRUC_wmi_diag_event_fixed_param */ + A_UINT32 time_stamp; /* Reference timestamp. diag frame contains diff value */ + A_UINT32 count; /* Number of diag frames added to current event */ + A_UINT32 dropped; + /* followed by WMITLV_TAG_ARRAY_BYTE */ +} wmi_diag_event_fixed_param; + +/* +* If FW has multiple active channels due to MCC(multi channel concurrency), +* then these stats are combined stats for all the active channels. +*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_update_whal_mib_stats_event_fixed_param */ + /** ack count, it is an incremental number, not accumulated number */ + A_UINT32 ackRcvBad; + /** bad rts count, it is an incremental number, not accumulated number */ + A_UINT32 rtsBad; + /** good rts, it is an incremental number, not accumulated number */ + A_UINT32 rtsGood; + /** fcs count, it is an incremental number, not accumulated number */ + A_UINT32 fcsBad; + /** beacon count, it is an incremental number, not accumulated number */ + A_UINT32 noBeacons; +} wmi_update_whal_mib_stats_event_fixed_param; + +/* + * This defines how much headroom is kept in the + * receive frame between the descriptor and the + * payload, in order for the WMI PHY error and + * management handler to insert header contents. + * + * This is in bytes. + */ +#define WMI_MGMT_RX_HDR_HEADROOM sizeof(wmi_comb_phyerr_rx_hdr) + WMI_TLV_HDR_SIZE + sizeof(wmi_single_phyerr_rx_hdr) + +/** This event will be used for sending scan results + * as well as rx mgmt frames to the host. The rx buffer + * will be sent as part of this WMI event. It would be a + * good idea to pass all the fields in the RX status + * descriptor up to the host. + */ + /* ATH_MAX_ANTENNA value (4) can't be changed without breaking the compatibility */ +#define ATH_MAX_ANTENNA 4 /* To support beelinear, which is up to 4 chains */ + +/** flag indicating that the the mgmt frame (probe req/beacon) is received in the context of extscan performed by FW */ +#define WMI_MGMT_RX_HDR_EXTSCAN 0x01 + +/** flag indicating that the the mgmt frame (probe req/beacon) is received in the context of matched network by FW ENLO */ +#define WMI_MGMT_RX_HDR_ENLO 0x02 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mgmt_rx_hdr */ + /** channel on which this frame is received. */ + A_UINT32 channel; + /** snr information used to cal rssi */ + A_UINT32 snr; + /** Rate kbps */ + A_UINT32 rate; + /** rx phy mode WLAN_PHY_MODE */ + A_UINT32 phy_mode; + /** length of the frame */ + A_UINT32 buf_len; + /** rx status */ + A_UINT32 status; + /** RSSI of PRI 20MHz for each chain. */ + A_UINT32 rssi_ctl[ATH_MAX_ANTENNA]; + /** information about the management frame e.g. can give a scan source for a scan result mgmt frame */ + A_UINT32 flags; + /** combined RSSI, i.e. the sum of the snr + noise floor (dBm units) */ + A_INT32 rssi; + /** delta between local TSF(TSF timestamp when frame was RXd) + * and remote TSF(TSF timestamp in the IE for mgmt frame - + * beacon,proberesp for e.g). If remote TSF is not available, + * delta set to 0. + * Although tsf_delta is stored as A_UINT32, it can be negative, + * and thus would need to be sign-extended if added to a value + * larger than 32 bits. + */ + A_UINT32 tsf_delta; + + /* This TLV is followed by array of bytes: + * // management frame buffer + * A_UINT8 bufp[]; + */ +} wmi_mgmt_rx_hdr; + +/* WMI PHY Error RX */ + +typedef struct { + /** TSF timestamp */ + A_UINT32 tsf_timestamp; + + /** + * Current freq1, freq2 + * + * [7:0]: freq1[lo] + * [15:8] : freq1[hi] + * [23:16]: freq2[lo] + * [31:24]: freq2[hi] + */ + A_UINT32 freq_info_1; + + /** + * Combined RSSI over all chains and channel width for this PHY error + * + * [7:0]: RSSI combined + * [15:8]: Channel width (MHz) + * [23:16]: PHY error code + * [24:16]: reserved (future use) + */ + A_UINT32 freq_info_2; + + /** + * RSSI on chain 0 through 3 + * + * This is formatted the same as the PPDU_START RX descriptor + * field: + * + * [7:0]: pri20 + * [15:8]: sec20 + * [23:16]: sec40 + * [31:24]: sec80 + */ + A_UINT32 rssi_chain0; + A_UINT32 rssi_chain1; + A_UINT32 rssi_chain2; + A_UINT32 rssi_chain3; + + /** + * Last calibrated NF value for chain 0 through 3 + * + * nf_list_1: + * + * + [15:0] - chain 0 + * + [31:16] - chain 1 + * + * nf_list_2: + * + * + [15:0] - chain 2 + * + [31:16] - chain 3 + */ + A_UINT32 nf_list_1; + A_UINT32 nf_list_2; + + /** Length of the frame */ + A_UINT32 buf_len; +} wmi_single_phyerr_rx_hdr; + +#define WMI_UNIFIED_FREQINFO_1_LO 0x000000ff +#define WMI_UNIFIED_FREQINFO_1_LO_S 0 +#define WMI_UNIFIED_FREQINFO_1_HI 0x0000ff00 +#define WMI_UNIFIED_FREQINFO_1_HI_S 8 +#define WMI_UNIFIED_FREQINFO_2_LO 0x00ff0000 +#define WMI_UNIFIED_FREQINFO_2_LO_S 16 +#define WMI_UNIFIED_FREQINFO_2_HI 0xff000000 +#define WMI_UNIFIED_FREQINFO_2_HI_S 24 + +/* + * Please keep in mind that these _SET macros break macro side effect + * assumptions; don't be clever with them. + */ +#define WMI_UNIFIED_FREQ_INFO_GET(hdr, f) \ + ( WMI_F_MS( (hdr)->freq_info_1, \ + WMI_UNIFIED_FREQINFO_##f##_LO ) \ + | (WMI_F_MS( (hdr)->freq_info_1, \ + WMI_UNIFIED_FREQINFO_##f##_HI ) << 8) ) + +#define WMI_UNIFIED_FREQ_INFO_SET(hdr, f, v) \ + do { \ + WMI_F_RMW((hdr)->freq_info_1, (v) & 0xff, \ + WMI_UNIFIED_FREQINFO_##f##_LO); \ + WMI_F_RMW((hdr)->freq_info_1, ((v) >> 8) & 0xff, \ + WMI_UNIFIED_FREQINFO_##f##_HI); \ + } while (0) + +#define WMI_UNIFIED_FREQINFO_2_RSSI_COMB 0x000000ff +#define WMI_UNIFIED_FREQINFO_2_RSSI_COMB_S 0 +#define WMI_UNIFIED_FREQINFO_2_CHWIDTH 0x0000ff00 +#define WMI_UNIFIED_FREQINFO_2_CHWIDTH_S 8 +#define WMI_UNIFIED_FREQINFO_2_PHYERRCODE 0x00ff0000 +#define WMI_UNIFIED_FREQINFO_2_PHYERRCODE_S 16 + +#define WMI_UNIFIED_RSSI_COMB_GET(hdr) \ + ( (int8_t) (WMI_F_MS((hdr)->freq_info_2, \ + WMI_UNIFIED_FREQINFO_2_RSSI_COMB))) + +#define WMI_UNIFIED_RSSI_COMB_SET(hdr, v) \ + WMI_F_RMW((hdr)->freq_info_2, (v) & 0xff, \ + WMI_UNIFIED_FREQINFO_2_RSSI_COMB); + +#define WMI_UNIFIED_CHWIDTH_GET(hdr) \ + WMI_F_MS((hdr)->freq_info_2, WMI_UNIFIED_FREQINFO_2_CHWIDTH) + +#define WMI_UNIFIED_CHWIDTH_SET(hdr, v) \ + WMI_F_RMW((hdr)->freq_info_2, (v) & 0xff, \ + WMI_UNIFIED_FREQINFO_2_CHWIDTH); + +#define WMI_UNIFIED_PHYERRCODE_GET(hdr) \ + WMI_F_MS((hdr)->freq_info_2, WMI_UNIFIED_FREQINFO_2_PHYERRCODE) + +#define WMI_UNIFIED_PHYERRCODE_SET(hdr, v) \ + WMI_F_RMW((hdr)->freq_info_2, (v) & 0xff, \ + WMI_UNIFIED_FREQINFO_2_PHYERRCODE); + +#define WMI_UNIFIED_CHAIN_0 0x0000ffff +#define WMI_UNIFIED_CHAIN_0_S 0 +#define WMI_UNIFIED_CHAIN_1 0xffff0000 +#define WMI_UNIFIED_CHAIN_1_S 16 +#define WMI_UNIFIED_CHAIN_2 0x0000ffff +#define WMI_UNIFIED_CHAIN_2_S 0 +#define WMI_UNIFIED_CHAIN_3 0xffff0000 +#define WMI_UNIFIED_CHAIN_3_S 16 + +#define WMI_UNIFIED_CHAIN_0_FIELD nf_list_1 +#define WMI_UNIFIED_CHAIN_1_FIELD nf_list_1 +#define WMI_UNIFIED_CHAIN_2_FIELD nf_list_2 +#define WMI_UNIFIED_CHAIN_3_FIELD nf_list_2 + +#define WMI_UNIFIED_NF_CHAIN_GET(hdr, c) \ + ((int16_t) (WMI_F_MS((hdr)->WMI_UNIFIED_CHAIN_##c##_FIELD, \ + WMI_UNIFIED_CHAIN_##c))) + +#define WMI_UNIFIED_NF_CHAIN_SET(hdr, c, nf) \ + WMI_F_RMW((hdr)->WMI_UNIFIED_CHAIN_##c##_FIELD, (nf) & 0xffff, \ + WMI_UNIFIED_CHAIN_##c); + +/* + * For now, this matches what the underlying hardware is doing. + * Update ar6000ProcRxDesc() to use these macros when populating + * the rx descriptor and then we can just copy the field over + * to the WMI PHY notification without worrying about breaking + * things. + */ +#define WMI_UNIFIED_RSSI_CHAN_PRI20 0x000000ff +#define WMI_UNIFIED_RSSI_CHAN_PRI20_S 0 +#define WMI_UNIFIED_RSSI_CHAN_SEC20 0x0000ff00 +#define WMI_UNIFIED_RSSI_CHAN_SEC20_S 8 +#define WMI_UNIFIED_RSSI_CHAN_SEC40 0x00ff0000 +#define WMI_UNIFIED_RSSI_CHAN_SEC40_S 16 +#define WMI_UNIFIED_RSSI_CHAN_SEC80 0xff000000 +#define WMI_UNIFIED_RSSI_CHAN_SEC80_S 24 + +#define WMI_UNIFIED_RSSI_CHAN_SET(hdr, c, ch, rssi) \ + WMI_F_RMW((hdr)->rssi_chain##c, (rssi) & 0xff, \ + WMI_UNIFIED_RSSI_CHAN_##ch); + +#define WMI_UNIFIED_RSSI_CHAN_GET(hdr, c, ch) \ + ((int8_t) (WMI_F_MS((hdr)->rssi_chain##c, \ + WMI_UNIFIED_RSSI_CHAN_##ch))) + +typedef struct { + /** Phy error event header */ + wmi_single_phyerr_rx_hdr hdr; + /** frame buffer */ + A_UINT8 bufp[1]; +}wmi_single_phyerr_rx_event; + +/* PHY ERROR MASK 0 */ +/* bits 1:0 defined but not published */ +#define WMI_PHY_ERROR_MASK0_RADAR (1<<2 ) +/* bits 23:3 defined but not published */ +#define WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT (1<<24) +/* bits 25:24 defined but not published */ +#define WMI_PHY_ERROR_MASK0_SPECTRAL_SCAN (1<<26) +/* bits 31:27 defined but not published */ + +/* PHY ERROR MASK 1 */ +/* bits 13:0 defined but not published */ +/* bits 31:14 reserved */ + +/* PHY ERROR MASK 2 */ +/* bits 31:0 reserved */ + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_comb_phyerr_rx_hdr */ + /** Phy error phy error count */ + A_UINT32 num_phyerr_events; + A_UINT32 tsf_l32; + A_UINT32 tsf_u32; + A_UINT32 buf_len; + A_UINT32 pmac_id; + A_UINT32 rsPhyErrMask0; /* see WMI_PHY_ERROR_MASK0 */ + A_UINT32 rsPhyErrMask1; /* see WMI_PHY_ERROR_MASK1 */ + A_UINT32 rsPhyErrMask2; /* see WMI_PHY_ERROR_MASK2 */ + /* This TLV is followed by array of bytes: + * // frame buffer - contains multiple payloads in the order: + * // header - payload, header - payload... + * (The header is of type: wmi_single_phyerr_rx_hdr) + * A_UINT8 bufp[]; + */ +} wmi_comb_phyerr_rx_hdr; + +/* WMI MGMT TX */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mgmt_tx_hdr */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** xmit rate */ + A_UINT32 tx_rate; + /** xmit power */ + A_UINT32 tx_power; + /** Buffer length in bytes */ + A_UINT32 buf_len; + /* This TLV is followed by array of bytes: + * // management frame buffer + * A_UINT8 bufp[]; + */ +} wmi_mgmt_tx_hdr; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mgmt_tx_send_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 desc_id; /* echoed in tx_compl_event */ + A_UINT32 chanfreq; /* MHz units */ + A_UINT32 paddr_lo; + A_UINT32 paddr_hi; + A_UINT32 frame_len; + A_UINT32 buf_len; /** Buffer length in bytes */ +/* This TLV is followed by array of bytes: First 64 bytes of management frame + * A_UINT8 bufp[]; + */ +} wmi_mgmt_tx_send_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_echo_event_fixed_param */ + A_UINT32 value; +} wmi_echo_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_echo_cmd_fixed_param */ + A_UINT32 value; +}wmi_echo_cmd_fixed_param; + + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param */ + + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + /** reg domain code */ + A_UINT32 reg_domain; + A_UINT32 reg_domain_2G; + A_UINT32 reg_domain_5G; + A_UINT32 conformance_test_limit_2G; + A_UINT32 conformance_test_limit_5G; +} wmi_pdev_set_regdomain_cmd_fixed_param; + +typedef struct { + /** TRUE for scan start and flase for scan end */ + A_UINT32 scan_start; +} wmi_pdev_scan_cmd; + +/*Command to set/unset chip in quiet mode*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_quiet_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + A_UINT32 period; /*period in TUs*/ + A_UINT32 duration; /*duration in TUs*/ + A_UINT32 next_start; /*offset in TUs*/ + A_UINT32 enabled; /*enable/disable*/ +} wmi_pdev_set_quiet_cmd_fixed_param; + +/* + * Command to enable/disable Green AP Power Save. + * This helps conserve power during AP operation. When the AP has no + * stations associated with it, the host can enable Green AP Power Save + * to request the firmware to shut down all but one transmit and receive + * chains. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_green_ap_ps_enable_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + A_UINT32 enable; /*1:enable, 0:disable*/ +} wmi_pdev_green_ap_ps_enable_cmd_fixed_param; + + +#define MAX_HT_IE_LEN 32 +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + A_UINT32 ie_len; /*length of the ht ie in the TLV ie_data[] */ + A_UINT32 tx_streams; /* Tx streams supported for this HT IE */ + A_UINT32 rx_streams; /* Rx streams supported for this HT IE */ + /** The TLV for the HT IE follows: + * A_UINT32 ie_data[]; + */ +} wmi_pdev_set_ht_ie_cmd_fixed_param; + +#define MAX_VHT_IE_LEN 32 +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + A_UINT32 ie_len; /*length of the vht ie in the TLV ie_data[] */ + A_UINT32 tx_streams; /* Tx streams supported for this HT IE */ + A_UINT32 rx_streams; /* Rx streams supported for this HT IE */ + /** The TLV for the VHT IE follows: + * A_UINT32 ie_data[]; + */ +} wmi_pdev_set_vht_ie_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_base_macaddr_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + wmi_mac_addr base_macaddr; +} wmi_pdev_set_base_macaddr_cmd_fixed_param; + +/* + * For now, the spectral configuration is global rather than + * per-vdev. The vdev is a placeholder and will be ignored + * by the firmware. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_spectral_configure_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 spectral_scan_count; + A_UINT32 spectral_scan_period; + A_UINT32 spectral_scan_priority; + A_UINT32 spectral_scan_fft_size; + A_UINT32 spectral_scan_gc_ena; + A_UINT32 spectral_scan_restart_ena; + A_UINT32 spectral_scan_noise_floor_ref; + A_UINT32 spectral_scan_init_delay; + A_UINT32 spectral_scan_nb_tone_thr; + A_UINT32 spectral_scan_str_bin_thr; + A_UINT32 spectral_scan_wb_rpt_mode; + A_UINT32 spectral_scan_rssi_rpt_mode; + A_UINT32 spectral_scan_rssi_thr; + A_UINT32 spectral_scan_pwr_format; + A_UINT32 spectral_scan_rpt_mode; + A_UINT32 spectral_scan_bin_scale; + A_UINT32 spectral_scan_dBm_adj; + A_UINT32 spectral_scan_chn_mask; +} wmi_vdev_spectral_configure_cmd_fixed_param; + +/* + * Enabling, disabling and triggering the spectral scan + * is a per-vdev operation. That is, it will set channel + * flags per vdev rather than globally; so concurrent scan/run + * and multiple STA (eg p2p, tdls, multi-band STA) is possible. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_spectral_enable_cmd_fixed_param */ + A_UINT32 vdev_id; + /* 0 - ignore; 1 - trigger, 2 - clear trigger */ + A_UINT32 trigger_cmd; + /* 0 - ignore; 1 - enable, 2 - disable */ + A_UINT32 enable_cmd; +} wmi_vdev_spectral_enable_cmd_fixed_param; + +typedef enum { +WMI_CSA_IE_PRESENT = 0x00000001, +WMI_XCSA_IE_PRESENT = 0x00000002, +WMI_WBW_IE_PRESENT = 0x00000004, +WMI_CSWARP_IE_PRESENT = 0x00000008, +}WMI_CSA_EVENT_IES_PRESENT_FLAG; + +/* wmi CSA receive event from beacon frame */ +typedef struct{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_csa_event_fixed_param */ + A_UINT32 i_fc_dur; +// Bit 0-15: FC +// Bit 16-31: DUR + wmi_mac_addr i_addr1; + wmi_mac_addr i_addr2; + /* NOTE: size of array of csa_ie[], xcsa_ie[], and wb_ie[] cannot be + * changed in the future without breaking WMI compatibility */ + A_UINT32 csa_ie[2]; + A_UINT32 xcsa_ie[2]; + A_UINT32 wb_ie[2]; + A_UINT32 cswarp_ie; + A_UINT32 ies_present_flag; //WMI_CSA_EVENT_IES_PRESENT_FLAG +}wmi_csa_event_fixed_param; + +typedef enum { + /** TX chain mask */ + WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1, + /** RX chain mask */ + WMI_PDEV_PARAM_RX_CHAIN_MASK, + /** TX power limit for 2G Radio */ + WMI_PDEV_PARAM_TXPOWER_LIMIT2G, + /** TX power limit for 5G Radio */ + WMI_PDEV_PARAM_TXPOWER_LIMIT5G, + /** TX power scale */ + WMI_PDEV_PARAM_TXPOWER_SCALE, + /** Beacon generation mode . 0: host, 1: target */ + WMI_PDEV_PARAM_BEACON_GEN_MODE, + /** Beacon generation mode . 0: staggered 1: bursted */ + WMI_PDEV_PARAM_BEACON_TX_MODE, + /** Resource manager off chan mode . + * 0: turn off off chan mode. 1: turn on offchan mode + */ + WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE, + /** Protection mode 0: no protection 1:use CTS-to-self 2: use RTS/CTS */ + WMI_PDEV_PARAM_PROTECTION_MODE, + /** Dynamic bandwidth 0: disable 1: enable */ + WMI_PDEV_PARAM_DYNAMIC_BW, + /** Non aggregrate/ 11g sw retry threshold.0-disable */ + WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, + /** aggregrate sw retry threshold. 0-disable*/ + WMI_PDEV_PARAM_AGG_SW_RETRY_TH, + /** Station kickout threshold (non of consecutive failures).0-disable */ + WMI_PDEV_PARAM_STA_KICKOUT_TH, + /** Aggerate size scaling configuration per AC */ + WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING, + /** LTR enable */ + WMI_PDEV_PARAM_LTR_ENABLE, + /** LTR latency for BE, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_BE, + /** LTR latency for BK, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_BK, + /** LTR latency for VI, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_VI, + /** LTR latency for VO, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_VO, + /** LTR AC latency timeout, in ms */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, + /** LTR platform latency override, in us */ + WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE, + /** LTR-M override, in us */ + WMI_PDEV_PARAM_LTR_RX_OVERRIDE, + /** Tx activity timeout for LTR, in us */ + WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, + /** L1SS state machine enable */ + WMI_PDEV_PARAM_L1SS_ENABLE, + /** Deep sleep state machine enable */ + WMI_PDEV_PARAM_DSLEEP_ENABLE, + /** RX buffering flush enable */ + WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH, + /** RX buffering matermark */ + WMI_PDEV_PARAM_PCIELP_TXBUF_WATERMARK, + /** RX buffering timeout enable */ + WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, + /** RX buffering timeout value */ + WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, + /** pdev level stats update period in ms */ + WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, + /** vdev level stats update period in ms */ + WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, + /** peer level stats update period in ms */ + WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, + /** beacon filter status update period */ + WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, + /** QOS Mgmt frame protection MFP/PMF 0: disable, 1: enable */ + WMI_PDEV_PARAM_PMF_QOS, + /** Access category on which ARP frames are sent */ + WMI_PDEV_PARAM_ARP_AC_OVERRIDE, + /** DCS configuration */ + WMI_PDEV_PARAM_DCS, + /** Enable/Disable ANI on target */ + WMI_PDEV_PARAM_ANI_ENABLE, + /** configure the ANI polling period */ + WMI_PDEV_PARAM_ANI_POLL_PERIOD, + /** configure the ANI listening period */ + WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, + /** configure OFDM immunity level */ + WMI_PDEV_PARAM_ANI_OFDM_LEVEL, + /** configure CCK immunity level */ + WMI_PDEV_PARAM_ANI_CCK_LEVEL, + /** Enable/Disable CDD for 1x1 STAs in rate control module */ + WMI_PDEV_PARAM_DYNTXCHAIN, + /** Enable/Disable proxy STA */ + WMI_PDEV_PARAM_PROXY_STA, + /** Enable/Disable low power state when all VDEVs are inactive/idle. */ + WMI_PDEV_PARAM_IDLE_PS_CONFIG, + /** Enable/Disable power gating sleep */ + WMI_PDEV_PARAM_POWER_GATING_SLEEP, + /** Enable/Disable Rfkill */ + WMI_PDEV_PARAM_RFKILL_ENABLE, + /** Set Bursting DUR */ + WMI_PDEV_PARAM_BURST_DUR, + /** Set Bursting ENABLE */ + WMI_PDEV_PARAM_BURST_ENABLE, + /** HW rfkill config */ + WMI_PDEV_PARAM_HW_RFKILL_CONFIG, + /** Enable radio low power features */ + WMI_PDEV_PARAM_LOW_POWER_RF_ENABLE, + /** L1SS entry and residency time track */ + WMI_PDEV_PARAM_L1SS_TRACK, + /** set hyst at runtime, requirement from SS */ + WMI_PDEV_PARAM_HYST_EN, + /** Enable/ Disable POWER COLLAPSE */ + WMI_PDEV_PARAM_POWER_COLLAPSE_ENABLE, + /** configure LED system state */ + WMI_PDEV_PARAM_LED_SYS_STATE, + /** Enable/Disable LED */ + WMI_PDEV_PARAM_LED_ENABLE, + /** set DIRECT AUDIO time latency */ + WMI_PDEV_PARAM_AUDIO_OVER_WLAN_LATENCY, + /** set DIRECT AUDIO Feature ENABLE */ + WMI_PDEV_PARAM_AUDIO_OVER_WLAN_ENABLE, + /** pdev level whal mib stats update enable */ + WMI_PDEV_PARAM_WHAL_MIB_STATS_UPDATE_ENABLE, + /** ht/vht info based on vdev */ + WMI_PDEV_PARAM_VDEV_RATE_STATS_UPDATE_PERIOD, + /** Set CTS channel BW for dynamic BW adjustment feature */ + WMI_PDEV_PARAM_CTS_CBW, + /** Set GPIO pin info used by WNTS */ + WMI_PDEV_PARAM_WNTS_CONFIG, + /** Enable/Disable hardware adaptive early rx feature */ + WMI_PDEV_PARAM_ADAPTIVE_EARLY_RX_ENABLE, + /** The minimum early rx duration, to ensure early rx duration is non-zero */ + WMI_PDEV_PARAM_ADAPTIVE_EARLY_RX_MIN_SLEEP_SLOP, + /** Increasing/decreasing step used by hardware */ + WMI_PDEV_PARAM_ADAPTIVE_EARLY_RX_INC_DEC_STEP, + /** The fixed early rx duration when adaptive early rx is disabled */ + WMI_PDEV_PARAM_EARLY_RX_FIX_SLEEP_SLOP, + /** Enable/Disable bmiss based adaptive beacon timeout feature */ + WMI_PDEV_PARAM_BMISS_BASED_ADAPTIVE_BTO_ENABLE, + /** The minimum beacon timeout duration, to ensure beacon timeout duration is non-zero */ + WMI_PDEV_PARAM_BMISS_BTO_MIN_BCN_TIMEOUT, + /** Increasing/decreasing step used by hardware */ + WMI_PDEV_PARAM_BMISS_BTO_INC_DEC_STEP, + /** The fixed beacon timeout duration when bmiss based adaptive beacon timeout is disabled */ + WMI_PDEV_PARAM_BTO_FIX_BCN_TIMEOUT, + /** Enable/Disable Congestion Estimator based adaptive beacon timeout feature */ + WMI_PDEV_PARAM_CE_BASED_ADAPTIVE_BTO_ENABLE, + /** combo value of ce_id, ce_threshold, ce_time, refer to WMI_CE_BTO_CE_ID_MASK */ + WMI_PDEV_PARAM_CE_BTO_COMBO_CE_VALUE, + /** 2G TX chain mask */ + WMI_PDEV_PARAM_TX_CHAIN_MASK_2G, + /** 2G RX chain mask */ + WMI_PDEV_PARAM_RX_CHAIN_MASK_2G, + /** 5G TX chain mask */ + WMI_PDEV_PARAM_TX_CHAIN_MASK_5G, + /** 5G RX chain mask */ + WMI_PDEV_PARAM_RX_CHAIN_MASK_5G, + /* Set tx chain mask for CCK rates */ + WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK, + /* Set tx chain mask for 1SS stream */ + WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS, + /* Enable/Disable CTS2Self for P2P GO when Non-P2P Client is connected */ + WMI_PDEV_PARAM_CTS2SELF_FOR_P2P_GO_CONFIG, + /** TX power backoff in dB: tx power -= param value + * Host passes values(DB) to Halphy, Halphy reduces the power table by + * the values. Safety check will happen in Halphy + */ + WMI_PDEV_PARAM_TXPOWER_DECR_DB, +} WMI_PDEV_PARAM; + +typedef enum { + /** Set the loglevel */ + WMI_DBGLOG_LOG_LEVEL = 0x1, + /** Enable VAP level debug */ + WMI_DBGLOG_VAP_ENABLE, + /** Disable VAP level debug */ + WMI_DBGLOG_VAP_DISABLE, + /** Enable MODULE level debug */ + WMI_DBGLOG_MODULE_ENABLE, + /** Disable MODULE level debug */ + WMI_DBGLOG_MODULE_DISABLE, + /** Enable MODULE level debug */ + WMI_DBGLOG_MOD_LOG_LEVEL, + /** set type of the debug output */ + WMI_DBGLOG_TYPE, + /** Enable Disable debug */ + WMI_DBGLOG_REPORT_ENABLE +} WMI_DBG_PARAM; + +/* param_value for param_id WMI_PDEV_PARAM_CTS_CBW */ +typedef enum { + WMI_CTS_CBW_INVALID = 0, + WMI_CTS_CBW_20, + WMI_CTS_CBW_40, + WMI_CTS_CBW_80, + WMI_CTS_CBW_80_80, + WMI_CTS_CBW_160, +} WMI_CTS_CBW; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + /** parameter id */ + A_UINT32 param_id; + /** parametr value */ + A_UINT32 param_value; +} wmi_pdev_set_param_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_get_tpc_config_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + /** parameter */ + A_UINT32 param; +} wmi_pdev_get_tpc_config_cmd_fixed_param; + +#define WMI_FAST_DIVERSITY_BIT_OFFSET 0 +#define WMI_SLOW_DIVERSITY_BIT_OFFSET 1 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_antenna_diversity_cmd_fixed_param */ + A_UINT32 mac_id; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + /** parameter */ + A_UINT32 value; /** bit0 is for enable/disable FAST diversity, and bit1 is for enable/disable SLOW diversity, 0->disable, 1->enable */ +} wmi_pdev_set_antenna_diversity_cmd_fixed_param; + +#define WMI_MAX_RSSI_THRESHOLD_SUPPORTED 3 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_cmd_fixed_param */ + A_UINT32 vdev_id; /* vdev_id, where RSSI monitoring will take place */ + A_UINT32 request_id; /* host will configure request_id and firmware echo this id in RSSI_BREACH_EVENT */ + A_UINT32 enabled_bitmap; /* bit [0-2] = low_rssi_breach_enabled[0-2] enabled, bit [3-5] = hi_rssi_breach_enabled[0-2] */ + A_UINT32 low_rssi_breach_threshold[WMI_MAX_RSSI_THRESHOLD_SUPPORTED]; /* unit dBm. host driver to make sure [0] > [1] > [2] */ + A_UINT32 hi_rssi_breach_threshold[WMI_MAX_RSSI_THRESHOLD_SUPPORTED]; /* unit dBm. host driver to make sure [0] < [1] < [2] */ + A_UINT32 lo_rssi_reenable_hysteresis; /* unit dBm. once low rssi[] breached, same event bitmap will be generated only after signal gets better than this level. This value is adopted for all low_rssi_breach_threshold[3] */ + A_UINT32 hi_rssi_reenable_histeresis;/* unit dBm. once hi rssi[] breached, same event bitmap will be generated only after signal gets worse than this level. This value is adopted for all hi_rssi_breach_threshold[3] */ + A_UINT32 min_report_interval; /* After last event is generated, we wait until this interval to generate next event */ + A_UINT32 max_num_report; /* this is to suppress number of event to be generated */ +} wmi_rssi_breach_monitor_config_fixed_param; + +typedef struct { + /** parameter */ + A_UINT32 param; +} wmi_pdev_dump_cmd; + +typedef enum { + PAUSE_TYPE_CHOP = 0x1, /** for MCC (switch channel), only vdev_map is valid */ + PAUSE_TYPE_PS = 0x2, /** for peer station sleep in sap mode, only peer_id is valid */ + PAUSE_TYPE_UAPSD = 0x3, /** for uapsd, only peer_id and tid_map are valid. */ + PAUSE_TYPE_P2P_CLIENT_NOA = 0x4, /** only vdev_map is valid, actually only one vdev id is set at one time */ + PAUSE_TYPE_P2P_GO_PS = 0x5, /** only vdev_map is valid, actually only one vdev id is set at one time */ + PAUSE_TYPE_STA_ADD_BA = 0x6, /** only peer_id and tid_map are valid, actually only one tid is set at one time */ + PAUSE_TYPE_AP_PS = 0x7, /** for pausing AP vdev when all the connected clients are in PS. only vdev_map is valid */ + PAUSE_TYPE_IBSS_PS = 0x8, /** for pausing IBSS vdev when all the peers are in PS. only vdev_map is valid */ + PAUSE_TYPE_HOST = 0x15,/** host is requesting vdev pause */ +} wmi_tx_pause_type; + +typedef enum { + ACTION_PAUSE = 0x0, + ACTION_UNPAUSE = 0x1, +} wmi_tx_pause_action; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 pause_type; + A_UINT32 action; + A_UINT32 vdev_map; + A_UINT32 peer_id; + A_UINT32 tid_map; +} wmi_tx_pause_event_fixed_param; + +typedef enum { + WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK = 0, + WMI_MGMT_TX_COMP_TYPE_DISCARD, + WMI_MGMT_TX_COMP_TYPE_INSPECT, + WMI_MGMT_TX_COMP_TYPE_COMPLETE_NO_ACK, + WMI_MGMT_TX_COMP_TYPE_MAX, +} WMI_MGMT_TX_COMP_STATUS_TYPE; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 desc_id; /* from tx_send_cmd */ + A_UINT32 status; /* WMI_MGMT_TX_COMP_STATUS_TYPE */ +} wmi_mgmt_tx_compl_event_fixed_param; + +#define WMI_TPC_RATE_MAX 160 +/* WMI_TPC_TX_NUM_CHAIN macro can't be changed without breaking the WMI compatibility */ +#define WMI_TPC_TX_NUM_CHAIN 4 + +typedef enum { + WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD = 0x1, + WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC = 0x2, + WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF = 0x4, +} WMI_TPC_CONFIG_EVENT_FLAG; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_tpc_config_event_fixed_param */ + A_UINT32 regDomain; + A_UINT32 chanFreq; + A_UINT32 phyMode; + A_UINT32 twiceAntennaReduction; + A_UINT32 twiceMaxRDPower; + A_INT32 twiceAntennaGain; + A_UINT32 powerLimit; + A_UINT32 rateMax; + A_UINT32 numTxChain; + A_UINT32 ctl; + A_UINT32 flags; + /* WMI_TPC_TX_NUM_CHAIN macro can't be changed without breaking the WMI compatibility */ + A_INT8 maxRegAllowedPower[WMI_TPC_TX_NUM_CHAIN]; + A_INT8 maxRegAllowedPowerAGCDD[WMI_TPC_TX_NUM_CHAIN][WMI_TPC_TX_NUM_CHAIN]; + A_INT8 maxRegAllowedPowerAGSTBC[WMI_TPC_TX_NUM_CHAIN][WMI_TPC_TX_NUM_CHAIN]; + A_INT8 maxRegAllowedPowerAGTXBF[WMI_TPC_TX_NUM_CHAIN][WMI_TPC_TX_NUM_CHAIN]; + /* This TLV is followed by a byte array: + * A_UINT8 ratesArray[]; + */ +} wmi_pdev_tpc_config_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_l1ss_track_event_fixed_param */ + A_UINT32 periodCnt; + A_UINT32 L1Cnt; + A_UINT32 L11Cnt; + A_UINT32 L12Cnt; + A_UINT32 L1Entry; + A_UINT32 L11Entry; + A_UINT32 L12Entry; +} wmi_pdev_l1ss_track_event_fixed_param; + +typedef struct { + A_UINT32 len; + A_UINT32 msgref; + A_UINT32 segmentInfo; +} wmi_pdev_seg_hdr_info; + + +/* + * Transmit power scale factor. + * + */ +typedef enum { + WMI_TP_SCALE_MAX = 0, /* no scaling (default) */ + WMI_TP_SCALE_50 = 1, /* 50% of max (-3 dBm) */ + WMI_TP_SCALE_25 = 2, /* 25% of max (-6 dBm) */ + WMI_TP_SCALE_12 = 3, /* 12% of max (-9 dBm) */ + WMI_TP_SCALE_MIN = 4, /* min, but still on */ + WMI_TP_SCALE_SIZE = 5, /* max num of enum */ +} WMI_TP_SCALE; + +#define WMI_MAX_DEBUG_MESG (sizeof(A_UINT32) * 32) + +typedef struct { + /** message buffer, NULL terminated */ + char bufp[WMI_MAX_DEBUG_MESG]; +} wmi_debug_mesg_event; + +enum { + /** IBSS station */ + VDEV_TYPE_IBSS = 0, + /** infra STA */ + VDEV_TYPE_STA = 1, + /** infra AP */ + VDEV_TYPE_AP = 2, + /** Monitor */ + VDEV_TYPE_MONITOR =3, + /** OCB */ + VDEV_TYPE_OCB = 6, +}; + +enum { + /** P2P device */ + VDEV_SUBTYPE_P2PDEV=0, + /** P2P client */ + VDEV_SUBTYPE_P2PCLI, + /** P2P GO */ + VDEV_SUBTYPE_P2PGO, + /** BT3.0 HS */ + VDEV_SUBTYPE_BT, +}; + +typedef struct { + /** idnore power , only use flags , mode and freq */ + wmi_channel chan; +} wmi_pdev_set_channel_cmd; + +typedef enum { + WMI_PKTLOG_EVENT_RX = 0x1, + WMI_PKTLOG_EVENT_TX = 0x2, + WMI_PKTLOG_EVENT_RCF = 0x4, /* Rate Control Find */ + WMI_PKTLOG_EVENT_RCU = 0x8, /* Rate Control Update */ + /* 0x10 used by deprecated DBG_PRINT */ + WMI_PKTLOG_EVENT_SMART_ANTENNA = 0x20, /* To support Smart Antenna */ +} WMI_PKTLOG_EVENT; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + WMI_PKTLOG_EVENT evlist; +} wmi_pdev_pktlog_enable_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param */ + A_UINT32 reserved0; +} wmi_pdev_pktlog_disable_cmd_fixed_param; + +/** Customize the DSCP (bit) to TID (0-7) mapping for QOS. + * NOTE: This constant cannot be changed without breaking + * WMI Compatibility. */ + +#define WMI_DSCP_MAP_MAX (64) + /* + * @brief dscp_tid_map_cmdid - command to send the dscp to tid map to the target + * @details + * Create an API for sending the custom DSCP-to-TID map to the target + * If this is a request from the user space or from above the UMAC + * then the best place to implement this is in the umac_if_offload of the OL path. + * Provide a place holder for this API in the ieee80211com (ic). + * + * This API will be a function pointer in the ieee80211com (ic). Any user space calls for manually setting the DSCP-to-TID mapping + * in the target should be directed to the function pointer in the ic. + * + * Implementation details of the API to send the map to the target are as described- + * + * 1. The function will have 2 arguments- struct ieee80211com, DSCP-to-TID map. + * DSCP-to-TID map is a one dimensional u_int32_t array of length 64 to accomodate + * 64 TID values for 2^6 (64) DSCP ids. + * Example: + * A_UINT32 dscp_tid_map[WMI_DSCP_MAP_MAX] = { + * 0, 0, 0, 0, 0, 0, 0, 0, + * 1, 1, 1, 1, 1, 1, 1, 1, + * 2, 2, 2, 2, 2, 2, 2, 2, + * 3, 3, 3, 3, 3, 3, 3, 3, + * 4, 4, 4, 4, 4, 4, 4, 4, + * 5, 5, 5, 5, 5, 5, 5, 5, + * 6, 6, 6, 6, 6, 6, 6, 6, + * 7, 7, 7, 7, 7, 7, 7, 7, + * }; + * + * 2. Request for the WMI buffer of size equal to the size of the DSCP-to-TID map. + * + * 3. Copy the DSCP-to-TID map into the WMI buffer. + * + * 4. Invoke the wmi_unified_cmd_send to send the cmd buffer to the target with the + * WMI_PDEV_SET_DSCP_TID_MAP_CMDID. Arguments to the wmi send cmd API + * (wmi_unified_send_cmd) are wmi handle, cmd buffer, length of the cmd buffer and + * the WMI_PDEV_SET_DSCP_TID_MAP_CMDID id. + * + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_dscp_tid_map_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + /* map indicating DSCP to TID conversion */ + A_UINT32 dscp_to_tid_map[WMI_DSCP_MAP_MAX]; +} wmi_pdev_set_dscp_tid_map_cmd_fixed_param; + +/** Fixed rate (rate-code) for broadcast/ multicast data frames */ +/* @brief bcast_mcast_data_rate - set the rates for the bcast/ mcast frames + * @details + * Create an API for setting the custom rate for the MCAST and BCAST frames + * in the target. If this is a request from the user space or from above the UMAC + * then the best place to implement this is in the umac_if_offload of the OL path. + * Provide a place holder for this API in the ieee80211com (ic). + * + * Implementation details of the API to set custom rates for MCAST and BCAST in + * the target are as described- + * + * 1. The function will have 3 arguments- + * vap structure, + * MCAST/ BCAST identifier code, + * 8 bit rate code + * + * The rate-code is a 1-byte field in which:for given rate, nss and preamble + * b'7-b-6 indicate the preamble (0 OFDM, 1 CCK, 2, HT, 3 VHT) + * b'5-b'4 indicate the NSS (0 - 1x1, 1 - 2x2, 2 - 3x3) + * b'3-b'0 indicate the rate, which is indicated as follows: + * OFDM : 0: OFDM 48 Mbps + * 1: OFDM 24 Mbps + * 2: OFDM 12 Mbps + * 3: OFDM 6 Mbps + * 4: OFDM 54 Mbps + * 5: OFDM 36 Mbps + * 6: OFDM 18 Mbps + * 7: OFDM 9 Mbps + * CCK (pream == 1) + * 0: CCK 11 Mbps Long + * 1: CCK 5.5 Mbps Long + * 2: CCK 2 Mbps Long + * 3: CCK 1 Mbps Long + * 4: CCK 11 Mbps Short + * 5: CCK 5.5 Mbps Short + * 6: CCK 2 Mbps Short + * HT/VHT (pream == 2/3) + * 0..7: MCS0..MCS7 (HT) + * 0..9: MCS0..MCS9 (VHT) + * + * 2. Invoke the wmi_unified_vdev_set_param_send to send the rate value + * to the target. + * Arguments to the API are- + * wmi handle, + * VAP interface id (av_if_id) defined in ol_ath_vap_net80211, + * WMI_VDEV_PARAM_BCAST_DATA_RATE/ WMI_VDEV_PARAM_MCAST_DATA_RATE, + * rate value. + */ +typedef enum { + WMI_SET_MCAST_RATE, + WMI_SET_BCAST_RATE +} MCAST_BCAST_RATE_ID; + +typedef struct { + MCAST_BCAST_RATE_ID rate_id; + A_UINT32 rate; +} mcast_bcast_rate; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wmm_params */ + A_UINT32 cwmin; + A_UINT32 cwmax; + A_UINT32 aifs; + A_UINT32 txoplimit; + A_UINT32 acm; + A_UINT32 no_ack; +} wmi_wmm_params; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_wmm_params_cmd_fixed_param */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + A_UINT32 dg_type; + + /* The TLVs for the 4 AC follows: + * wmi_wmm_params wmm_params_ac_be; + * wmi_wmm_params wmm_params_ac_bk; + * wmi_wmm_params wmm_params_ac_vi; + * wmi_wmm_params wmm_params_ac_vo; + */ +} wmi_pdev_set_wmm_params_cmd_fixed_param; + +typedef enum { + WMI_REQUEST_PEER_STAT = 0x01, + WMI_REQUEST_AP_STAT = 0x02, + WMI_REQUEST_PDEV_STAT = 0x04, + WMI_REQUEST_VDEV_STAT = 0x08, + WMI_REQUEST_BCNFLT_STAT = 0x10, + WMI_REQUEST_VDEV_RATE_STAT = 0x20, +} wmi_stats_id; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param */ + wmi_stats_id stats_id; + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; +} wmi_request_stats_cmd_fixed_param; + +/* stats type bitmap */ +#define WMI_LINK_STATS_RADIO 0x00000001 +#define WMI_LINK_STATS_IFACE 0x00000002 +#define WMI_LINK_STATS_ALL_PEER 0x00000004 +#define WMI_LINK_STATS_PER_PEER 0x00000008 + + +/* wifi clear statistics bitmap */ +#define WIFI_STATS_RADIO 0x00000001 /** all radio statistics */ +#define WIFI_STATS_RADIO_CCA 0x00000002 /** cca_busy_time (within radio statistics) */ +#define WIFI_STATS_RADIO_CHANNELS 0x00000004 /** all channel statistics (within radio statistics) */ +#define WIFI_STATS_RADIO_SCAN 0x00000008 /** all scan statistics (within radio statistics) */ +#define WIFI_STATS_IFACE 0x00000010 /** all interface statistics */ +#define WIFI_STATS_IFACE_TXRATE 0x00000020 /** all tx rate statistics (within interface statistics) */ +#define WIFI_STATS_IFACE_AC 0x00000040 /** all ac statistics (within interface statistics) */ +#define WIFI_STATS_IFACE_CONTENTION 0x00000080 /** all contention (min, max, avg) statistics (within ac statisctics) */ +#define WMI_STATS_IFACE_ALL_PEER 0x00000100 /** All peer stats on this interface */ +#define WMI_STATS_IFACE_PER_PEER 0x00000200 /** Clear particular peer stats depending on the peer_mac */ + +/** Default value for stats if the stats collection has not started */ +#define WMI_STATS_VALUE_INVALID 0xffffffff + +#define WMI_DIAG_ID_GET(diag_events_logs) WMI_GET_BITS(diag_events_logs, 0, 16) +#define WMI_DIAG_ID_SET(diag_events_logs, value) WMI_SET_BITS(diag_events_logs, 0, 16, value) +#define WMI_DIAG_TYPE_GET(diag_events_logs) WMI_GET_BITS(diag_events_logs, 16, 1) +#define WMI_DIAG_TYPE_SET(diag_events_logs, value) WMI_SET_BITS(diag_events_logs, 16, 1, value) +#define WMI_DIAG_ID_ENABLED_DISABLED_GET(diag_events_logs) WMI_GET_BITS(diag_events_logs, 17, 1) +#define WMI_DIAG_ID_ENABLED_DISABLED_SET(diag_events_logs, value) WMI_SET_BITS(diag_events_logs, 17, 1, value) + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_diag_event_log_config_fixed_param */ + A_UINT32 num_of_diag_events_logs; +/* The TLVs will follow. + * A_UINT32 diag_events_logs_list[]; 0-15 Bits Diag EVENT/LOG ID, + * Bit 16 - DIAG type EVENT/LOG, 0 - Event, 1 - LOG + * Bit 17 Indicate if the DIAG type is Enabled/Disabled. + */ +} wmi_diag_event_log_config_fixed_param; + +#define WMI_DIAG_FREQUENCY_GET(diag_events_logs) WMI_GET_BITS(diag_events_logs, 17, 1) +#define WMI_DIAG_FREQUENCY_SET(diag_events_logs, value) WMI_SET_BITS(diag_events_logs, 17, 1, value) +#define WMI_DIAG_EXT_FEATURE_GET(diag_events_logs) WMI_GET_BITS(diag_events_logs, 18, 1) +#define WMI_DIAG_EXT_FEATURE_SET(diag_events_logs, value) WMI_SET_BITS(diag_events_logs, 18, 1, value) + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 num_of_diag_events_logs; +/* The TLVs will follow. + * A_UINT32 diag_events_logs_list[]; 0-15 Bits Diag EVENT/LOG ID, + * Bit 16 - DIAG type EVENT/LOG, 0 - Event, 1 - LOG + * Bit 17 - Frequncy of the DIAG EVENT/LOG High Frequency -1, Low Frequency - 0 + * Bit 18 - Set if the EVENTS/LOGs are used for EXT DEBUG Framework + */ +} wmi_diag_event_log_supported_event_fixed_params; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_debug_mesg_flush_fixed_param*/ + A_UINT32 reserved0; /** placeholder for future */ +} wmi_debug_mesg_flush_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_debug_mesg_flush_complete_fixed_param*/ + A_UINT32 reserved0; /** placeholder for future */ +} wmi_debug_mesg_flush_complete_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_rssi_breach_fixed_param */ + /* vdev_id, where RSSI breach event occurred */ + A_UINT32 vdev_id; + /* request id */ + A_UINT32 request_id; + /* bitmap[0-2] is corresponding to low_rssi[0-2]. bitmap[3-5] is corresponding to hi_rssi[0-2]*/ + A_UINT32 event_bitmap; + /* rssi at the time of RSSI breach. Unit dBm */ + A_UINT32 rssi; + /* bssid of the monitored AP's */ + wmi_mac_addr bssid; +} wmi_rssi_breach_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_fw_mem_dump */ + /** unique id identifying the segment */ + A_UINT32 seg_id; + /** Start address of the segment to be read */ + A_UINT32 seg_start_addr_lo; + A_UINT32 seg_start_addr_hi; + /** Length of the segment to be read */ + A_UINT32 seg_length; + /** Host bufeer address to which the segment will be read and dumped */ + A_UINT32 dest_addr_lo; + A_UINT32 dest_addr_hi; +} wmi_fw_mem_dump; + +/* Command to get firmware memory dump*/ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param */ + /** unique id identifying the request */ + A_UINT32 request_id; + /** number of memory dump segments */ + A_UINT32 num_fw_mem_dump_segs; +/** + * This TLV is followed by another TLV + * wmi_fw_mem_dump fw_mem_dump[]; + */ +} wmi_get_fw_mem_dump_fixed_param; + +/** Event to indicate the completion of fw mem dump */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_update_fw_mem_dump_fixed_param */ + /** unique id identifying the request, given in the request stats command */ + A_UINT32 request_id; + /*In case of Firmware memory dump */ + A_UINT32 fw_mem_dump_complete; +} wmi_update_fw_mem_dump_fixed_param; + +typedef enum { + WMI_ROAMING_IDLE = 0, + WMI_ROAMING_ACTIVE = 1, +} wmi_roam_state; + +/* access categories */ +typedef enum { + WMI_AC_VO = 0, + WMI_AC_VI = 1, + WMI_AC_BE = 2, + WMI_AC_BK = 3, + WMI_AC_MAX = 4, +} wmi_traffic_ac; + +typedef enum { + WMI_STA_STATS = 0, + WMI_SOFTAP_STATS = 1, + WMI_IBSS_STATS = 2, + WMI_P2P_CLIENT_STATS = 3, + WMI_P2P_GO_STATS = 4, + WMI_NAN_STATS = 5, + WMI_MESH_STATS = 6, +} wmi_link_iface_type; + +/* channel operating width */ +typedef enum { + WMI_CHAN_WIDTH_20 = 0, + WMI_CHAN_WIDTH_40 = 1, + WMI_CHAN_WIDTH_80 = 2, + WMI_CHAN_WIDTH_160 = 3, + WMI_CHAN_WIDTH_80P80 = 4, + WMI_CHAN_WIDTH_5 = 5, + WMI_CHAN_WIDTH_10 = 6, +} wmi_channel_width; + +/*Clear stats*/ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_clear_link_stats_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** stop_stats_collection_req = 1 will imply stop the statistics collection */ + A_UINT32 stop_stats_collection_req; + /** identifies what stats to be cleared */ + A_UINT32 stats_clear_req_mask; + /** identifies which peer stats to be cleared. Valid only while clearing PER_REER */ + wmi_mac_addr peer_macaddr; +} wmi_clear_link_stats_cmd_fixed_param; + +/* Link Stats configuration params. Trigger the link layer statistics collection*/ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_start_link_stats_cmd_fixed_param */ + /** threshold to classify the pkts as short or long */ + A_UINT32 mpdu_size_threshold; + /** set for field debug mode. Driver should collect all statistics regardless of performance impact.*/ + A_UINT32 aggressive_statistics_gathering; +} wmi_start_link_stats_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_request_link_stats_cmd_fixed_param */ + /** Type of stats required. This is a bitmask WMI_LINK_STATS_RADIO, WMI_LINK_STATS_IFACE */ + A_UINT32 stats_type; + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** unique id identifying the request, generated by the caller */ + A_UINT32 request_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; +} wmi_request_link_stats_cmd_fixed_param; + +/* channel statistics */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_channel_stats */ + /** Channel width (20, 40, 80, 80+80, 160) enum wmi_channel_width*/ + A_UINT32 channel_width; + /** Primary 20 MHz channel */ + A_UINT32 center_freq; + /** center frequency (MHz) first segment */ + A_UINT32 center_freq0; + /** center frequency (MHz) second segment */ + A_UINT32 center_freq1; + /** msecs the radio is awake (32 bits number accruing over time) */ + A_UINT32 radio_awake_time; + /** msecs the CCA register is busy (32 bits number accruing over time) */ + A_UINT32 cca_busy_time; +} wmi_channel_stats; + +/* radio statistics */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_radio_link_stats */ + /** Wifi radio (if multiple radio supported) */ + A_UINT32 radio_id; + /** msecs the radio is awake (32 bits number accruing over time) */ + A_UINT32 on_time; + /** msecs the radio is transmitting (32 bits number accruing over time) */ + A_UINT32 tx_time; + /** msecs the radio is in active receive (32 bits number accruing over time) */ + A_UINT32 rx_time; + /** msecs the radio is awake due to all scan (32 bits number accruing over time) */ + A_UINT32 on_time_scan; + /** msecs the radio is awake due to NAN (32 bits number accruing over time) */ + A_UINT32 on_time_nbd; + /** msecs the radio is awake due to G?scan (32 bits number accruing over time) */ + A_UINT32 on_time_gscan; + /** msecs the radio is awake due to roam?scan (32 bits number accruing over time) */ + A_UINT32 on_time_roam_scan; + /** msecs the radio is awake due to PNO scan (32 bits number accruing over time) */ + A_UINT32 on_time_pno_scan; + /** msecs the radio is awake due to HS2.0 scans and GAS exchange (32 bits number accruing over time) */ + A_UINT32 on_time_hs20; + /** number of channels */ + A_UINT32 num_channels; +} wmi_radio_link_stats; + +/** Radio statistics (once started) do not stop or get reset unless wifi_clear_link_stats is invoked */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_stats_event_fixed_param */ + /** unique id identifying the request, given in the request stats command */ + A_UINT32 request_id; + /** Number of radios*/ + A_UINT32 num_radio; + /** more_data will be set depending on the number of radios */ + A_UINT32 more_radio_events; +/* + * This TLV is followed by another TLV of array of bytes + * size of(struct wmi_radio_link_stats); + * + * This TLV is followed by another TLV of array of bytes + * num_channels * size of(struct wmi_channel_stats) + */ + +} wmi_radio_link_stats_event_fixed_param; + +/* per rate statistics */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_rate_stats */ + /** rate information + * The rate-code is a 1-byte field in which:for given rate, nss and preamble + * b'7-b-6 indicate the preamble (0 OFDM, 1 CCK, 2, HT, 3 VHT) + * b'5-b'4 indicate the NSS (0 - 1x1, 1 - 2x2, 2 - 3x3) + * b'3-b'0 indicate the rate, which is indicated as follows: + * OFDM : 0: OFDM 48 Mbps + * 1: OFDM 24 Mbps + * 2: OFDM 12 Mbps + * 3: OFDM 6 Mbps + * 4: OFDM 54 Mbps + * 5: OFDM 36 Mbps + * 6: OFDM 18 Mbps + * 7: OFDM 9 Mbps + * CCK (pream == 1) + * 0: CCK 11 Mbps Long + * 1: CCK 5.5 Mbps Long + * 2: CCK 2 Mbps Long + * 3: CCK 1 Mbps Long + * 4: CCK 11 Mbps Short + * 5: CCK 5.5 Mbps Short + * 6: CCK 2 Mbps Short + * HT/VHT (pream == 2/3) + * 0..7: MCS0..MCS7 (HT) + * 0..9: MCS0..MCS9 (VHT) + */ + A_UINT32 rate; + /** units of 100 Kbps */ + A_UINT32 bitrate; + /** number of successfully transmitted data pkts (ACK rcvd) */ + A_UINT32 tx_mpdu; + /** number of received data pkts */ + A_UINT32 rx_mpdu; + /** number of data packet losses (no ACK) */ + A_UINT32 mpdu_lost; + /** total number of data pkt retries */ + A_UINT32 retries; + /** number of short data pkt retries */ + A_UINT32 retries_short; + /** number of long data pkt retries */ + A_UINT32 retries_long; +} wmi_rate_stats; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_link_stats */ + /** peer type (AP, TDLS, GO etc.) enum wmi_peer_type*/ + A_UINT32 peer_type; + /** mac address */ + wmi_mac_addr peer_mac_address; + /** peer wmi_CAPABILITY_XXX */ + A_UINT32 capabilities; + /** number of rates */ + A_UINT32 num_rates; +} wmi_peer_link_stats; + +/** PEER statistics (once started) reset and start afresh after each connection */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_stats_event_fixed_param */ + /** unique id identifying the request, given in the request stats command */ + A_UINT32 request_id; + /** number of peers accomidated in this particular event */ + A_UINT32 num_peers; + /** Indicates the fragment number */ + A_UINT32 peer_event_number; + /** Indicates if there are more peers which will be sent as seperate peer_stats event */ + A_UINT32 more_data; + +/** + * This TLV is followed by another TLV + * num_peers * size of(struct wmi_peer_stats) + * num_rates * size of(struct wmi_rate_stats). num_rates is the sum of the rates of all the peers. + */ +} wmi_peer_stats_event_fixed_param; + +/* per access category statistics */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wmm_ac_stats */ + /** access category (VI, VO, BE, BK) enum wmi_traffic_ac*/ + A_UINT32 ac_type; + /** number of successfully transmitted unicast data pkts (ACK rcvd) */ + A_UINT32 tx_mpdu; + /** number of received unicast mpdus */ + A_UINT32 rx_mpdu; + /** number of succesfully transmitted multicast data packets */ + /** STA case: implies ACK received from AP for the unicast packet in which mcast pkt was sent */ + A_UINT32 tx_mcast; + /** number of received multicast data packets */ + A_UINT32 rx_mcast; + /** number of received unicast a-mpdus */ + A_UINT32 rx_ampdu; + /** number of transmitted unicast a-mpdus */ + A_UINT32 tx_ampdu; + /** number of data pkt losses (no ACK) */ + A_UINT32 mpdu_lost; + /** total number of data pkt retries */ + A_UINT32 retries; + /** number of short data pkt retries */ + A_UINT32 retries_short; + /** number of long data pkt retries */ + A_UINT32 retries_long; + /** data pkt min contention time (usecs) */ + A_UINT32 contention_time_min; + /** data pkt max contention time (usecs) */ + A_UINT32 contention_time_max; + /** data pkt avg contention time (usecs) */ + A_UINT32 contention_time_avg; + /** num of data pkts used for contention statistics */ + A_UINT32 contention_num_samples; +} wmi_wmm_ac_stats; + +/* interface statistics */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_iface_link_stats */ + /** access point beacon received count from connected AP */ + A_UINT32 beacon_rx; + /** access point mgmt frames received count from connected AP (including Beacon) */ + A_UINT32 mgmt_rx; + /** action frames received count */ + A_UINT32 mgmt_action_rx; + /** action frames transmit count */ + A_UINT32 mgmt_action_tx; + /** access Point Beacon and Management frames RSSI (averaged) */ + A_UINT32 rssi_mgmt; + /** access Point Data Frames RSSI (averaged) from connected AP */ + A_UINT32 rssi_data; + /** access Point ACK RSSI (averaged) from connected AP */ + A_UINT32 rssi_ack; + /** number of peers */ + A_UINT32 num_peers; + /** Indicates how many peer_stats events will be sent depending on the num_peers. */ + A_UINT32 num_peer_events; + /** number of ac */ + A_UINT32 num_ac; + /** Roaming Stat */ + A_UINT32 roam_state; + /** Average Beacon spread offset is the averaged time delay between TBTT and beacon TSF */ + /** Upper 32 bits of averaged 64 bit beacon spread offset */ + A_UINT32 avg_bcn_spread_offset_high; + /** Lower 32 bits of averaged 64 bit beacon spread offset */ + A_UINT32 avg_bcn_spread_offset_low; + /** Takes value of 1 if AP leaks packets after sending an ACK for PM=1 otherwise 0 */ + A_UINT32 is_leaky_ap; + /** Average number of frames received from AP after receiving the ACK for a frame with PM=1 */ + A_UINT32 avg_rx_frms_leaked; + /** Rx leak watch window currently in force to minimize data loss because of leaky AP. Rx leak window is the + time driver waits before shutting down the radio or switching the channel and after receiving an ACK for + a data frame with PM bit set) */ + A_UINT32 rx_leak_window; +} wmi_iface_link_stats; + +/** Interface statistics (once started) reset and start afresh after each connection */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_iface_link_stats_event_fixed_param */ + /** unique id identifying the request, given in the request stats command */ + A_UINT32 request_id; + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +/* + * This TLV is followed by another TLV + * wmi_iface_link_stats iface_link_stats; + * num_ac * size of(struct wmi_wmm_ac_stats) + */ +} wmi_iface_link_stats_event_fixed_param; + +/** Suspend option */ +enum { + WMI_PDEV_SUSPEND, /* suspend */ + WMI_PDEV_SUSPEND_AND_DISABLE_INTR, /* suspend and disable all interrupts */ +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param */ + /* suspend option sent to target */ + A_UINT32 reserved0; /** placeholder for pdev_id of future multiple MAC products. Init. to 0. */ + A_UINT32 suspend_opt; +} wmi_pdev_suspend_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param */ + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_pdev_resume_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_rate_stats_event_fixed_param, */ + A_UINT32 num_vdev_stats; /* number of vdevs */ +}wmi_vdev_rate_stats_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len, tag equals WMITLV_TAG_STRUC_wmi_vdev_rate_ht_info*/ + A_UINT32 vdevid; /* Id of the wlan vdev*/ + A_UINT32 tx_nss; /* Bit 28 of tx_rate_kbps has this info - based on last data packet transmitted*/ + A_UINT32 rx_nss; /* Bit 24 of rx_rate_kbps - same as above*/ + A_UINT32 tx_preamble; /* Bits 30-29 from tx_rate_kbps */ + A_UINT32 rx_preamble; /* Bits 26-25 from rx_rate_kbps */ +} wmi_vdev_rate_ht_info; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_stats_event_fixed_param */ + wmi_stats_id stats_id; + /** number of pdev stats event structures (wmi_pdev_stats) 0 or 1 */ + A_UINT32 num_pdev_stats; + /** number of vdev stats event structures (wmi_vdev_stats) 0 or max vdevs */ + A_UINT32 num_vdev_stats; + /** number of peer stats event structures (wmi_peer_stats) 0 or max peers */ + A_UINT32 num_peer_stats; + A_UINT32 num_bcnflt_stats; + /** number of chan stats event structures (wmi_chan_stats) 0 to MAX MCC CHANS */ + A_UINT32 num_chan_stats; + /* This TLV is followed by another TLV of array of bytes + * A_UINT8 data[]; + * This data array contains + * num_pdev_stats * size of(struct wmi_pdev_stats) + * num_vdev_stats * size of(struct wmi_vdev_stats) + * num_peer_stats * size of(struct wmi_peer_stats) + * num_bcnflt_stats * size_of() + * num_chan_stats * size of(struct wmi_chan_stats) + * + */ +} wmi_stats_event_fixed_param; + +/** + * PDEV statistics + * @todo + * add all PDEV stats here + */ +typedef struct { + /** Channel noise floor */ + A_INT32 chan_nf; + /** TX frame count */ + A_UINT32 tx_frame_count; + /** RX frame count */ + A_UINT32 rx_frame_count; + /** rx clear count */ + A_UINT32 rx_clear_count; + /** cycle count */ + A_UINT32 cycle_count; + /** Phy error count */ + A_UINT32 phy_err_count; + /** Channel Tx Power */ + A_UINT32 chan_tx_pwr; + /** WAL dbg stats */ + struct wlan_dbg_stats pdev_stats; + +} wmi_pdev_stats; + +/** + * VDEV statistics + * @todo + * add all VDEV stats here + */ + +typedef struct { + A_INT32 bcn_snr; + A_INT32 dat_snr; +} wmi_snr_info; + +typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + wmi_snr_info vdev_snr; + A_UINT32 tx_frm_cnt[WLAN_MAX_AC];/* Total number of packets(per AC) that were successfully transmitted(with and without retries, including multi-cast, broadcast) */ + A_UINT32 rx_frm_cnt;/* Total number of packets that were successfully received (after appropriate filter rules including multi-cast, broadcast)*/ + A_UINT32 multiple_retry_cnt[WLAN_MAX_AC];/*The number of MSDU packets and MMPDU frames per AC + that the 802.11 station successfully transmitted after more than one retransmission attempt*/ + A_UINT32 fail_cnt[WLAN_MAX_AC]; /*Total number packets(per AC) failed to transmit */ + A_UINT32 rts_fail_cnt;/*Total number of RTS/CTS sequence failures for transmission of a packet*/ + A_UINT32 rts_succ_cnt;/*Total number of RTS/CTS sequence success for transmission of a packet*/ + A_UINT32 rx_err_cnt;/*The receive error count. HAL will provide the RxP FCS error global */ + A_UINT32 rx_discard_cnt;/* The sum of the receive error count and dropped-receive-buffer error count. (FCS error)*/ + A_UINT32 ack_fail_cnt;/*Total number packets failed transmit because of no ACK from the remote entity*/ + A_UINT32 tx_rate_history[MAX_TX_RATE_VALUES];/*History of last ten transmit rate, in units of 500 kbit/sec*/ + A_UINT32 bcn_rssi_history[MAX_RSSI_VALUES];/*History of last ten Beacon rssi of the connected Bss*/ +} wmi_vdev_stats; + +/** + * peer statistics. + * + * @todo + * add more stats + * + */ +typedef struct { + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** rssi */ + A_UINT32 peer_rssi; + /** last tx data rate used for peer */ + A_UINT32 peer_tx_rate; + /** last rx data rate used for peer */ + A_UINT32 peer_rx_rate; +} wmi_peer_stats; + +typedef struct { + /** Primary channel freq of the channel for which stats are sent */ + A_UINT32 chan_mhz; + /** Time spent on the channel */ + A_UINT32 sampling_period_us; + /** Aggregate duration over a sampling period for which channel activity was observed */ + A_UINT32 rx_clear_count; + /** Accumalation of the TX PPDU duration over a sampling period */ + A_UINT32 tx_duration_us; + /** Accumalation of the RX PPDU duration over a sampling period */ + A_UINT32 rx_duration_us; +} wmi_chan_stats; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_create_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** VDEV type (AP,STA,IBSS,MONITOR) */ + A_UINT32 vdev_type; + /** VDEV subtype (P2PDEV, P2PCLI, P2PGO, BT3.0)*/ + A_UINT32 vdev_subtype; + /** VDEV MAC address */ + wmi_mac_addr vdev_macaddr; + /* Number of configured txrx streams */ + A_UINT32 num_cfg_txrx_streams; +/* This TLV is followed by another TLV of array of structures + * wmi_vdev_txrx_streams cfg_txrx_streams[]; + */ +} wmi_vdev_create_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_txrx_streams */ + /* band - Should take values from wmi_channel_band_mask */ + A_UINT32 band; + /* max supported tx streams per given band for this vdev */ + A_UINT32 supported_tx_streams; + /* max supported rx streams per given band for this vdev */ + A_UINT32 supported_rx_streams; +} wmi_vdev_txrx_streams; + +/* wmi_p2p_noa_descriptor structure can't be modified without breaking the compatibility for WMI_HOST_SWBA_EVENTID */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_noa_descriptor */ + A_UINT32 type_count; /** 255: continuous schedule, 0: reserved */ + A_UINT32 duration ; /** Absent period duration in micro seconds */ + A_UINT32 interval; /** Absent period interval in micro seconds */ + A_UINT32 start_time; /** 32 bit tsf time when in starts */ +} wmi_p2p_noa_descriptor; + +/** values for vdev_type */ +#define WMI_VDEV_TYPE_AP 0x1 +#define WMI_VDEV_TYPE_STA 0x2 +#define WMI_VDEV_TYPE_IBSS 0x3 +#define WMI_VDEV_TYPE_MONITOR 0x4 + +/** VDEV type is for social wifi interface.This VDEV is Currently mainly needed +* by FW to execute the NAN specific WMI commands and also implement NAN specific +* operations like Network discovery, service provisioning and service +* subscription ..etc. If FW needs NAN VDEV then Host should issue VDEV create +* WMI command to create this VDEV once during initialization and host is not +* expected to use any VDEV specific WMI commands on this VDEV. +**/ +#define WMI_VDEV_TYPE_NAN 0x5 + +#define WMI_VDEV_TYPE_OCB 0x6 + +/** values for vdev_subtype */ +#define WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE 0x1 +#define WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT 0x2 +#define WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO 0x3 + +/** values for vdev_start_request flags */ +/** Indicates that AP VDEV uses hidden ssid. only valid for + * AP/GO */ +#define WMI_UNIFIED_VDEV_START_HIDDEN_SSID (1<<0) +/** Indicates if robust management frame/management frame + * protection is enabled. For GO/AP vdevs, it indicates that + * it may support station/client associations with RMF enabled. + * For STA/client vdevs, it indicates that sta will + * associate with AP with RMF enabled. */ +#define WMI_UNIFIED_VDEV_START_PMF_ENABLED (1<<1) + +/* + * Host is sending bcn_tx_rate to override the beacon tx rates. + */ +#define WMI_UNIFIED_VDEV_START_BCN_TX_RATE_PRESENT (1<<2) + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_start_request_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** requestor id identifying the caller module */ + A_UINT32 requestor_id; + /** beacon interval from received beacon */ + A_UINT32 beacon_interval; + /** DTIM Period from the received beacon */ + A_UINT32 dtim_period; + /** Flags */ + A_UINT32 flags; + /** ssid field. Only valid for AP/GO/IBSS/BTAmp VDEV type. */ + wmi_ssid ssid; + /** beacon/probe reponse xmit rate. Applicable for SoftAP. */ + /** This field will be invalid and ignored unless the */ + /** flags field has the WMI_UNIFIED_VDEV_START_BCN_TX_RATE_PRESENT bit. */ + /** When valid, this field contains the fixed tx rate for the beacon */ + /** and probe response frames send by the GO or SoftAP */ + A_UINT32 bcn_tx_rate; + /** beacon/probe reponse xmit power. Applicable for SoftAP. */ + A_UINT32 bcn_txPower; + /** number of p2p NOA descriptor(s) from scan entry */ + A_UINT32 num_noa_descriptors; + /** Disable H/W ack. This used by WMI_VDEV_RESTART_REQUEST_CMDID. + During CAC, Our HW shouldn't ack ditected frames */ + A_UINT32 disable_hw_ack; + /** This field will be invalid unless the Dual Band Simultaneous (DBS) feature is enabled. */ + /** The DBS policy manager indicates the preferred number of transmit streams. */ + A_UINT32 preferred_tx_streams; + /** This field will be invalid unless the Dual Band Simultaneous (DBS) feature is enabled. */ + /** the DBS policy manager indicates the preferred number of receive streams. */ + A_UINT32 preferred_rx_streams; + + /* The TLVs follows this structure: + * wmi_channel chan; //WMI channel + * wmi_p2p_noa_descriptor noa_descriptors[]; //actual p2p NOA descriptor from scan entry + */ +} wmi_vdev_start_request_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_delete_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_delete_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_up_cmdid_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** aid (assoc id) received in association response for STA VDEV */ + A_UINT32 vdev_assoc_id; + /** bssid of the BSS the VDEV is joining */ + wmi_mac_addr vdev_bssid; +} wmi_vdev_up_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_stop_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_stop_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_down_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_down_cmd_fixed_param; + +typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_standby_response_cmd; + +typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_resume_response_cmd; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_set_param_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** parameter id */ + A_UINT32 param_id; + /** parameter value */ + A_UINT32 param_value; +} wmi_vdev_set_param_cmd_fixed_param; + +typedef struct { + A_UINT32 key_seq_counter_l; + A_UINT32 key_seq_counter_h; +} wmi_key_seq_counter; + +#define WMI_CIPHER_NONE 0x0 /* clear key */ +#define WMI_CIPHER_WEP 0x1 +#define WMI_CIPHER_TKIP 0x2 +#define WMI_CIPHER_AES_OCB 0x3 +#define WMI_CIPHER_AES_CCM 0x4 +#define WMI_CIPHER_WAPI 0x5 +#define WMI_CIPHER_CKIP 0x6 +#define WMI_CIPHER_AES_CMAC 0x7 +#define WMI_CIPHER_ANY 0x8 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_install_key_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** MAC address used for installing */ + wmi_mac_addr peer_macaddr; + /** key index */ + A_UINT32 key_ix; + /** key flags */ + A_UINT32 key_flags; + /** key cipher, defined above */ + A_UINT32 key_cipher; + /** key rsc counter */ + wmi_key_seq_counter key_rsc_counter; + /** global key rsc counter */ + wmi_key_seq_counter key_global_rsc_counter; + /** global key tsc counter */ + wmi_key_seq_counter key_tsc_counter; + /** WAPI key rsc counter */ + A_UINT8 wpi_key_rsc_counter[16]; + /** WAPI key tsc counter */ + A_UINT8 wpi_key_tsc_counter[16]; + /** key length */ + A_UINT32 key_len; + /** key tx mic length */ + A_UINT32 key_txmic_len; + /** key rx mic length */ + A_UINT32 key_rxmic_len; + /* + * Following this struct are this TLV. + * // actual key data + * A_UINT8 key_data[]; // contains key followed by tx mic followed by rx mic + */ +} wmi_vdev_install_key_cmd_fixed_param; + +/** Preamble types to be used with VDEV fixed rate configuration */ +typedef enum { + WMI_RATE_PREAMBLE_OFDM, + WMI_RATE_PREAMBLE_CCK, + WMI_RATE_PREAMBLE_HT, + WMI_RATE_PREAMBLE_VHT, +} WMI_RATE_PREAMBLE; + +/** Value to disable fixed rate setting */ +#define WMI_FIXED_RATE_NONE (0xff) + +/** the definition of different VDEV parameters */ +typedef enum { + /** RTS Threshold */ + WMI_VDEV_PARAM_RTS_THRESHOLD = 0x1, + /** Fragmentation threshold */ + WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, + /** beacon interval in TUs */ + WMI_VDEV_PARAM_BEACON_INTERVAL, + /** Listen interval in TUs */ + WMI_VDEV_PARAM_LISTEN_INTERVAL, + /** muticast rate in Mbps */ + WMI_VDEV_PARAM_MULTICAST_RATE, + /** management frame rate in Mbps */ + WMI_VDEV_PARAM_MGMT_TX_RATE, + /** slot time (long vs short) */ + WMI_VDEV_PARAM_SLOT_TIME, + /** preamble (long vs short) */ + WMI_VDEV_PARAM_PREAMBLE, + /** SWBA time (time before tbtt in msec) */ + WMI_VDEV_PARAM_SWBA_TIME, + /** time period for updating VDEV stats */ + WMI_VDEV_STATS_UPDATE_PERIOD, + /** age out time in msec for frames queued for station in power save*/ + WMI_VDEV_PWRSAVE_AGEOUT_TIME, + /** Host SWBA interval (time in msec before tbtt for SWBA event generation) */ + WMI_VDEV_HOST_SWBA_INTERVAL, + /** DTIM period (specified in units of num beacon intervals) */ + WMI_VDEV_PARAM_DTIM_PERIOD, + /** scheduler air time limit for this VDEV. used by off chan scheduler */ + WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, + /** enable/dsiable WDS for this VDEV */ + WMI_VDEV_PARAM_WDS, + /** ATIM Window */ + WMI_VDEV_PARAM_ATIM_WINDOW, + /** BMISS max */ + WMI_VDEV_PARAM_BMISS_COUNT_MAX, + /** BMISS first time */ + WMI_VDEV_PARAM_BMISS_FIRST_BCNT, + /** BMISS final time */ + WMI_VDEV_PARAM_BMISS_FINAL_BCNT, + /** WMM enables/disabled */ + WMI_VDEV_PARAM_FEATURE_WMM, + /** Channel width */ + WMI_VDEV_PARAM_CHWIDTH, + /** Channel Offset */ + WMI_VDEV_PARAM_CHEXTOFFSET, + /** Disable HT Protection */ + WMI_VDEV_PARAM_DISABLE_HTPROTECTION, + /** Quick STA Kickout */ + WMI_VDEV_PARAM_STA_QUICKKICKOUT, + /** Rate to be used with Management frames */ + WMI_VDEV_PARAM_MGMT_RATE, + /** Protection Mode */ + WMI_VDEV_PARAM_PROTECTION_MODE, + /** Fixed rate setting */ + WMI_VDEV_PARAM_FIXED_RATE, + /** Short GI Enable/Disable */ + WMI_VDEV_PARAM_SGI, + /** Enable LDPC */ + WMI_VDEV_PARAM_LDPC, + /** Enable Tx STBC */ + WMI_VDEV_PARAM_TX_STBC, + /** Enable Rx STBC */ + WMI_VDEV_PARAM_RX_STBC, + /** Intra BSS forwarding */ + WMI_VDEV_PARAM_INTRA_BSS_FWD, + /** Setting Default xmit key for Vdev */ + WMI_VDEV_PARAM_DEF_KEYID, + /** NSS width */ + WMI_VDEV_PARAM_NSS, + /** Set the custom rate for the broadcast data frames */ + WMI_VDEV_PARAM_BCAST_DATA_RATE, + /** Set the custom rate (rate-code) for multicast data frames */ + WMI_VDEV_PARAM_MCAST_DATA_RATE, + /** Tx multicast packet indicate Enable/Disable */ + WMI_VDEV_PARAM_MCAST_INDICATE, + /** Tx DHCP packet indicate Enable/Disable */ + WMI_VDEV_PARAM_DHCP_INDICATE, + /** Enable host inspection of Tx unicast packet to unknown destination */ + WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE, + + /* The minimum amount of time AP begins to consider STA inactive */ + WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, + + /* An associated STA is considered inactive when there is no recent TX/RX + * activity and no downlink frames are buffered for it. Once a STA exceeds + * the maximum idle inactive time, the AP will send an 802.11 data-null as + * a keep alive to verify the STA is still associated. If the STA does ACK + * the data-null, or if the data-null is buffered and the STA does not + * retrieve it, the STA will be considered unresponsive (see + * WMI_VDEV_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS). */ + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, + + /* An associated STA is considered unresponsive if there is no recent + * TX/RX activity and downlink frames are buffered for it. Once a STA + * exceeds the maximum unresponsive time, the AP will send a + * WMI_STA_KICKOUT event to the host so the STA can be deleted. */ + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, + + /* Enable NAWDS : MCAST INSPECT Enable, NAWDS Flag set */ + WMI_VDEV_PARAM_AP_ENABLE_NAWDS, + /** Enable/Disable RTS-CTS */ + WMI_VDEV_PARAM_ENABLE_RTSCTS, + /* Enable TXBFee/er */ + WMI_VDEV_PARAM_TXBF, + + /**Set packet power save */ + WMI_VDEV_PARAM_PACKET_POWERSAVE, + + /**Drops un-encrypted packets if any received in an encryted connection + * otherwise forwards to host + */ + WMI_VDEV_PARAM_DROP_UNENCRY, + + /* + * Set TX encap type. + * + * enum wmi_pkt_type is to be used as the parameter + * specifying the encap type. + */ + WMI_VDEV_PARAM_TX_ENCAP_TYPE, + + /* + * Try to detect stations that woke-up and exited power save but did not + * successfully transmit data-null with PM=0 to AP. When this happens, + * STA and AP power save state are out-of-sync. Use buffered but + * undelivered MSDU to the STA as a hint that the STA is really awake + * and expecting normal ASAP delivery, rather than retrieving BU with + * PS-Poll, U-APSD trigger, etc. + * + * 0 disables out-of-sync detection. Maximum time is 255 seconds. + */ + WMI_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, + + /* Enable/Disable early rx dynamic adjust feature. + * Early-rx dynamic adjust is a advance power save feature. + * Early-rx is a wakeup duration before exact TBTT,which is deemed necessary to provide a cushion for various + * timing discrepancies in the system. + * In current code branch, the duration is set to a very conservative fix value to make sure the drift impact is minimum. + * The fix early-tx will result in the unnessary power consume, so a dynamic early-rx adjust algorithm can be designed + * properly to minimum the power consume.*/ + WMI_VDEV_PARAM_EARLY_RX_ADJUST_ENABLE, + + /* set target bmiss number per sample cycle if bmiss adjust was chosen. + * In this adjust policy,early-rx is adjusted by comparing the current bmiss rate to target bmiss rate + * which can be set by user through WMI command. + */ + WMI_VDEV_PARAM_EARLY_RX_TGT_BMISS_NUM, + + /* set sample cycle(in the unit of beacon interval) if bmiss adjust was chosen */ + WMI_VDEV_PARAM_EARLY_RX_BMISS_SAMPLE_CYCLE, + + /* set slop_step */ + WMI_VDEV_PARAM_EARLY_RX_SLOP_STEP, + + /* set init slop */ + WMI_VDEV_PARAM_EARLY_RX_INIT_SLOP, + + /* pause adjust enable/disable */ + WMI_VDEV_PARAM_EARLY_RX_ADJUST_PAUSE, + + + /* Set channel pwr limit value of the vdev the minimal value of all + * vdevs operating on this channel will be set as channel tx power + * limit, which is used to configure ratearray + */ + WMI_VDEV_PARAM_TX_PWRLIMIT, + + /* set the count of snr value for calculation in snr monitor */ + WMI_VDEV_PARAM_SNR_NUM_FOR_CAL, + + /** Roaming offload */ + WMI_VDEV_PARAM_ROAM_FW_OFFLOAD, + + /** Enable Leader request RX functionality for RMC */ + WMI_VDEV_PARAM_ENABLE_RMC, + + /* IBSS does not have deauth/disassoc, vdev has to detect peer gone event + * by himself. If the beacon lost time exceed this threshold, the peer is + * thought to be gone. */ + WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS, + + /** max rate in kpbs, transmit rate can't go beyond it */ + WMI_VDEV_PARAM_MAX_RATE, + + /* enable/disable drift sample. 0: disable; 1: clk_drift; 2: ap_drift; 3 both clk and ap drift*/ + WMI_VDEV_PARAM_EARLY_RX_DRIFT_SAMPLE, + /* set Tx failure count threshold for the vdev */ + WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR, + + /* set ebt resync timeout value, in the unit of TU */ + WMI_VDEV_PARAM_EBT_RESYNC_TIMEOUT, + + /* Enable Aggregation State Trigger Event */ + WMI_VDEV_PARAM_AGGR_TRIG_EVENT_ENABLE, + + /* This parameter indicates whether IBSS station can enter into power save + * mode by sending Null frame (with PM=1). When not allowed, IBSS station has to stay + * awake all the time and should never set PM=1 in its transmitted frames. + * This parameter is meaningful/valid only when WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH + * is non-zero. */ + WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED, + + /* This parameter indicates if this station can enter into power collapse + * for the remaining beacon interval after the ATIM window. + * This parameter is meaningful/valid only when WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED + * is set to TRUE. */ + WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED, + + /* This parameter indicates whether IBSS station exit power save mode and + * enter power active state (by sending Null frame with PM=0 in the immediate ATIM Window) + * whenever there is a TX/RX activity. */ + WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED, + + /* If Awake on TX/RX activity is enabled, this parameter indicates + * the data inactivity time in number of beacon intervals after which + * IBSS station reenters power save by sending Null frame with PM=1. */ + WMI_VDEV_PARAM_INACTIVITY_CNT, + + /* Inactivity time in msec after which TX Service Period (SP) is + * terminated by sending a Qos Null frame with EOSP. + * If value is 0, TX SP is terminated with the last buffered packet itself + * instead of waiting for the inactivity timeout. */ + WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS, + + /** DTIM policy */ + WMI_VDEV_PARAM_DTIM_POLICY, + + /* When IBSS network is initialized, PS-supporting device + * does not enter protocol sleep state during first + * WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS seconds. */ + WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS, + + /* Enable/Disable 1 RX chain usage during the ATIM window */ + WMI_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE, + + /* RX Leak window is the time driver waits before shutting down + * the radio or switching the channel and after receiving an ACK + * for a data frame with PM bit set) */ + WMI_VDEV_PARAM_RX_LEAK_WINDOW, + + /** Averaging factor(16 bit value) is used in the calculations to + * perform averaging of different link level statistics like average + * beacon spread or average number of frames leaked */ + WMI_VDEV_PARAM_STATS_AVG_FACTOR, + + /** disconnect threshold, once the consecutive error for specific peer + * exceed this threhold, FW will send kickout event to host */ + WMI_VDEV_PARAM_DISCONNECT_TH, + + /** The rate_code of RTS_CTS changed by host. Now FW can support + * more non-HT rates rather than 1Mbps or 6Mbps */ + WMI_VDEV_PARAM_RTSCTS_RATE, + + /** This parameter indicates whether using a long duration RTS-CTS + * protection when a SAP goes off channel in MCC mode */ + WMI_VDEV_PARAM_MCC_RTSCTS_PROTECTION_ENABLE, + + /** This parameter indicates whether using a broadcast probe response + * to increase the detectability of SAP in MCC mode */ + WMI_VDEV_PARAM_MCC_BROADCAST_PROBE_ENABLE, + + /** This parameter indicates the power backoff in percentage + * currently supports 100%, 50%, 25%, 12.5%, and minimum + * Host passes 0, 1, 2, 3, 4 to Firmware + * 0 --> 100% --> no changes, 1 --> 50% --> -3dB, + * 2 --> 25% --> -6dB, 3 --> 12.5% --> -9dB, 4 --> minimum --> -32dB + */ + WMI_VDEV_PARAM_TXPOWER_SCALE, + + /** TX power backoff in dB: tx power -= param value + * Host passes values(DB) to Halphy, Halphy reduces the power table + * by the values. Safety check will happen in Halphy. + */ + WMI_VDEV_PARAM_TXPOWER_SCALE_DECR_DB, + +} WMI_VDEV_PARAM; + +/* Length of ATIM Window in TU */ +#define WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH WMI_VDEV_PARAM_ATIM_WINDOW + +enum wmi_pkt_type { + WMI_PKT_TYPE_RAW = 0, + WMI_PKT_TYPE_NATIVE_WIFI = 1, + WMI_PKT_TYPE_ETHERNET = 2, +}; + +typedef struct { + A_UINT8 sutxbfee : 1, + mutxbfee : 1, + sutxbfer : 1, + mutxbfer : 1, +#if defined(AR900B) + txb_sts_cap : 3, + implicit_bf:1; +#else + reserved : 4; +#endif +} wmi_vdev_txbf_en; + +/** Upto 8 bits are available for Roaming module to be sent along with +WMI_VDEV_PARAM_ROAM_FW_OFFLOAD WMI_VDEV_PARAM **/ +/* Enable Roaming FW offload LFR1.5/LFR2.0 implementation */ +#define WMI_ROAM_FW_OFFLOAD_ENABLE_FLAG 0x1 +/* Enable Roaming module in FW to do scan based on Final BMISS */ +#define WMI_ROAM_BMISS_FINAL_SCAN_ENABLE_FLAG 0x2 + + /** slot time long */ + #define WMI_VDEV_SLOT_TIME_LONG 0x1 + /** slot time short */ + #define WMI_VDEV_SLOT_TIME_SHORT 0x2 + /** preablbe long */ + #define WMI_VDEV_PREAMBLE_LONG 0x1 + /** preablbe short */ + #define WMI_VDEV_PREAMBLE_SHORT 0x2 + +/** the definition of different START/RESTART Event response */ +typedef enum { + /* Event respose of START CMD */ + WMI_VDEV_START_RESP_EVENT = 0, + /* Event respose of RESTART CMD */ + WMI_VDEV_RESTART_RESP_EVENT, +} WMI_START_EVENT_PARAM; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_start_response_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** requestor id that requested the VDEV start request */ + A_UINT32 requestor_id; + /* Respose of Event type START/RESTART */ + WMI_START_EVENT_PARAM resp_type; + /** status of the response */ + A_UINT32 status; + /** Vdev chain mask */ + A_UINT32 chain_mask; + /** Vdev mimo power save mode */ + A_UINT32 smps_mode; + /** mac_id field contains the MAC identifier that the VDEV is bound to. The valid range is 0 to (num_macs-1). */ + A_UINT32 mac_id; + /** Configured Transmit Streams **/ + A_UINT32 cfgd_tx_streams; + /** Configured Receive Streams **/ + A_UINT32 cfgd_rx_streams; +} wmi_vdev_start_response_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_stopped_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_stopped_event_fixed_param; + +/** common structure used for simple events (stopped, resume_req, standby response) */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag would be equivalent to actual event */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_simple_event_fixed_param; + + +/** VDEV start response status codes */ +#define WMI_VDEV_START_RESPONSE_STATUS_SUCCESS 0x0 /** VDEV succesfully started */ +#define WMI_VDEV_START_RESPONSE_INVALID_VDEVID 0x1 /** requested VDEV not found */ +#define WMI_VDEV_START_RESPONSE_NOT_SUPPORTED 0x2 /** unsupported VDEV combination */ + +/** Beacon processing related command and event structures */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_bcn_tx_hdr */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** xmit rate */ + A_UINT32 tx_rate; + /** xmit power */ + A_UINT32 txPower; + /** beacon buffer length in bytes */ + A_UINT32 buf_len; + /* This TLV is followed by array of bytes: + * // beacon frame buffer + * A_UINT8 bufp[]; + */ +} wmi_bcn_tx_hdr; + +/* Beacon filter */ +#define WMI_BCN_FILTER_ALL 0 /* Filter all beacons */ +#define WMI_BCN_FILTER_NONE 1 /* Pass all beacons */ +#define WMI_BCN_FILTER_RSSI 2 /* Pass Beacons RSSI >= RSSI threshold */ +#define WMI_BCN_FILTER_BSSID 3 /* Pass Beacons with matching BSSID */ +#define WMI_BCN_FILTER_SSID 4 /* Pass Beacons with matching SSID */ + +typedef struct { + /** Filter ID */ + A_UINT32 bcn_filter_id; + /** Filter type - wmi_bcn_filter */ + A_UINT32 bcn_filter; + /** Buffer len */ + A_UINT32 bcn_filter_len; + /** Filter info (threshold, BSSID, RSSI) */ + A_UINT8 *bcn_filter_buf; +} wmi_bcn_filter_rx_cmd; + +/** Capabilities and IEs to be passed to firmware */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_bcn_prb_info */ + /** Capabilities */ + A_UINT32 caps; + /** ERP info */ + A_UINT32 erp; + /** Advanced capabilities */ + /** HT capabilities */ + /** HT Info */ + /** ibss_dfs */ + /** wpa Info */ + /** rsn Info */ + /** rrm info */ + /** ath_ext */ + /** app IE */ +} wmi_bcn_prb_info; + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_bcn_tmpl_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** TIM IE offset from the beginning of the template. */ + A_UINT32 tim_ie_offset; + /** beacon buffer length. data is in TLV data[] */ + A_UINT32 buf_len; + /* + * The TLVs follows: + * wmi_bcn_prb_info bcn_prb_info; //beacon probe capabilities and IEs + * A_UINT8 data[]; //Variable length data + */ +} wmi_bcn_tmpl_cmd_fixed_param; + + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_prb_tmpl_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** beacon buffer length. data is in TLV data[] */ + A_UINT32 buf_len; + /* + * The TLVs follows: + * wmi_bcn_prb_info bcn_prb_info; //beacon probe capabilities and IEs + * A_UINT8 data[]; //Variable length data + */ + } wmi_prb_tmpl_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_offload_bcn_tx_status_event_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** bcn tx status, values defined in enum WMI_FRAME_TX_STATUS */ + A_UINT32 tx_status; +} wmi_offload_bcn_tx_status_event_fixed_param; + + enum wmi_sta_ps_mode { + /** enable power save for the given STA VDEV */ + WMI_STA_PS_MODE_DISABLED = 0, + /** disable power save for a given STA VDEV */ + WMI_STA_PS_MODE_ENABLED = 1, + }; + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_powersave_mode_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + + /** Power save mode + * + * (see enum wmi_sta_ps_mode) + */ + A_UINT32 sta_ps_mode; + } wmi_sta_powersave_mode_cmd_fixed_param; + + enum wmi_csa_offload_en{ + WMI_CSA_OFFLOAD_DISABLE = 0, + WMI_CSA_OFFLOAD_ENABLE = 1, + }; + + typedef struct{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_csa_offload_enable_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 csa_offload_enable; + } wmi_csa_offload_enable_cmd_fixed_param; + + typedef struct{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_csa_offload_chanswitch_cmd_fixed_param */ + A_UINT32 vdev_id; + /* + * The TLVs follows: + * wmi_channel chan; + */ + } wmi_csa_offload_chanswitch_cmd_fixed_param; + /** + * This parameter controls the policy for retrieving frames from AP while the + * STA is in sleep state. + * + * Only takes affect if the sta_ps_mode is enabled + */ + enum wmi_sta_ps_param_rx_wake_policy { + /* Wake up when ever there is an RX activity on the VDEV. In this mode + * the Power save SM(state machine) will come out of sleep by either + * sending null frame (or) a data frame (with PS==0) in response to TIM + * bit set in the received beacon frame from AP. + */ + WMI_STA_PS_RX_WAKE_POLICY_WAKE = 0, + + /* Here the power save state machine will not wakeup in response to TIM + * bit, instead it will send a PSPOLL (or) UASPD trigger based on UAPSD + * configuration setup by WMISET_PS_SET_UAPSD WMI command. When all + * access categories are delivery-enabled, the station will send a UAPSD + * trigger frame, otherwise it will send a PS-Poll. + */ + WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD = 1, + }; + + /** Number of tx frames/beacon that cause the power save SM to wake up. + * + * Value 1 causes the SM to wake up for every TX. Value 0 has a special + * meaning, It will cause the SM to never wake up. This is useful if you want + * to keep the system to sleep all the time for some kind of test mode . host + * can change this parameter any time. It will affect at the next tx frame. + */ + enum wmi_sta_ps_param_tx_wake_threshold { + WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER = 0, + WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS = 1, + + /* Values greater than one indicate that many TX attempts per beacon + * interval before the STA will wake up + */ + }; + + /** + * The maximum number of PS-Poll frames the FW will send in response to + * traffic advertised in TIM before waking up (by sending a null frame with PS + * = 0). Value 0 has a special meaning: there is no maximum count and the FW + * will send as many PS-Poll as are necessary to retrieve buffered BU. This + * parameter is used when the RX wake policy is + * WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD and ignored when the RX wake + * policy is WMI_STA_PS_RX_WAKE_POLICY_WAKE. + */ + enum wmi_sta_ps_param_pspoll_count { + WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0, + /* Values greater than 0 indicate the maximum numer of PS-Poll frames FW + * will send before waking up. + */ + }; + + /* + * This will include the delivery and trigger enabled state for every AC. + * This is the negotiated state with AP. The host MLME needs to set this based + * on AP capability and the state Set in the association request by the + * station MLME.Lower 8 bits of the value specify the UAPSD configuration. + */ + #define WMI_UAPSD_AC_TYPE_DELI 0 + #define WMI_UAPSD_AC_TYPE_TRIG 1 + + #define WMI_UAPSD_AC_BIT_MASK(ac,type) (type == WMI_UAPSD_AC_TYPE_DELI)?(1<<(ac<<1)):(1<<((ac<<1)+1)) + + enum wmi_sta_ps_param_uapsd { + WMI_STA_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0), + WMI_STA_PS_UAPSD_AC0_TRIGGER_EN = (1 << 1), + WMI_STA_PS_UAPSD_AC1_DELIVERY_EN = (1 << 2), + WMI_STA_PS_UAPSD_AC1_TRIGGER_EN = (1 << 3), + WMI_STA_PS_UAPSD_AC2_DELIVERY_EN = (1 << 4), + WMI_STA_PS_UAPSD_AC2_TRIGGER_EN = (1 << 5), + WMI_STA_PS_UAPSD_AC3_DELIVERY_EN = (1 << 6), + WMI_STA_PS_UAPSD_AC3_TRIGGER_EN = (1 << 7), + }; + + enum wmi_sta_powersave_param { + /** + * Controls how frames are retrievd from AP while STA is sleeping + * + * (see enum wmi_sta_ps_param_rx_wake_policy) + */ + WMI_STA_PS_PARAM_RX_WAKE_POLICY = 0, + + /** + * The STA will go active after this many TX + * + * (see enum wmi_sta_ps_param_tx_wake_threshold) + */ + WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD = 1, + + /** + * Number of PS-Poll to send before STA wakes up + * + * (see enum wmi_sta_ps_param_pspoll_count) + * + */ + WMI_STA_PS_PARAM_PSPOLL_COUNT = 2, + + /** + * TX/RX inactivity time in msec before going to sleep. + * + * The power save SM will monitor tx/rx activity on the VDEV, if no + * activity for the specified msec of the parameter the Power save SM will + * go to sleep. + */ + WMI_STA_PS_PARAM_INACTIVITY_TIME = 3, + + /** + * Set uapsd configuration. + * + * (see enum wmi_sta_ps_param_uapsd) + */ + WMI_STA_PS_PARAM_UAPSD = 4, + /** + * Number of PS-Poll to send before STA wakes up in QPower Mode + */ + WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT = 5, + + /** + * Enable QPower + */ + WMI_STA_PS_ENABLE_QPOWER = 6, + + /** + * Number of TX frames before the entering the Active state + */ + WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE = 7, + + /** + * QPower SPEC PSPOLL interval + */ + WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL = 8, + + /** + * Max SPEC PSPOLL to be sent when the PSPOLL response has + * no-data bit set + */ + WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL = 9, + }; + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** station power save parameter (see enum wmi_sta_powersave_param) */ + A_UINT32 param; + A_UINT32 value; + } wmi_sta_powersave_param_cmd_fixed_param; + + /** No MIMO power save */ + #define WMI_STA_MIMO_PS_MODE_DISABLE + /** mimo powersave mode static*/ + #define WMI_STA_MIMO_PS_MODE_STATIC + /** mimo powersave mode dynamic */ + #define WMI_STA_MIMO_PS_MODE_DYNAMI + + typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** mimo powersave mode as defined above */ + A_UINT32 mimo_pwrsave_mode; + } wmi_sta_mimo_ps_mode_cmd; + + + /** U-APSD configuration of peer station from (re)assoc request and TSPECs */ + enum wmi_ap_ps_param_uapsd { + WMI_AP_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0), + WMI_AP_PS_UAPSD_AC0_TRIGGER_EN = (1 << 1), + WMI_AP_PS_UAPSD_AC1_DELIVERY_EN = (1 << 2), + WMI_AP_PS_UAPSD_AC1_TRIGGER_EN = (1 << 3), + WMI_AP_PS_UAPSD_AC2_DELIVERY_EN = (1 << 4), + WMI_AP_PS_UAPSD_AC2_TRIGGER_EN = (1 << 5), + WMI_AP_PS_UAPSD_AC3_DELIVERY_EN = (1 << 6), + WMI_AP_PS_UAPSD_AC3_TRIGGER_EN = (1 << 7), + }; + + /** U-APSD maximum service period of peer station */ + enum wmi_ap_ps_peer_param_max_sp { + WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED = 0, + WMI_AP_PS_PEER_PARAM_MAX_SP_2 = 1, + WMI_AP_PS_PEER_PARAM_MAX_SP_4 = 2, + WMI_AP_PS_PEER_PARAM_MAX_SP_6 = 3, + + /* keep last! */ + MAX_WMI_AP_PS_PEER_PARAM_MAX_SP, + }; + + /** + * AP power save parameter + * Set a power save specific parameter for a peer station + */ + enum wmi_ap_ps_peer_param { + /** Set uapsd configuration for a given peer. + * + * This will include the delivery and trigger enabled state for every AC. + * The host MLME needs to set this based on AP capability and stations + * request Set in the association request received from the station. + * + * Lower 8 bits of the value specify the UAPSD configuration. + * + * (see enum wmi_ap_ps_param_uapsd) + * The default value is 0. + */ + WMI_AP_PS_PEER_PARAM_UAPSD = 0, + + /** + * Set the service period for a UAPSD capable station + * + * The service period from wme ie in the (re)assoc request frame. + * + * (see enum wmi_ap_ps_peer_param_max_sp) + */ + WMI_AP_PS_PEER_PARAM_MAX_SP = 1, + + /** Time in seconds for aging out buffered frames for STA in power save */ + WMI_AP_PS_PEER_PARAM_AGEOUT_TIME = 2, + }; + + typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ap_ps_peer_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** AP powersave param (see enum wmi_ap_ps_peer_param) */ + A_UINT32 param; + /** AP powersave param value */ + A_UINT32 value; + } wmi_ap_ps_peer_cmd_fixed_param; + + /** Configure peer station 11v U-APSD coexistance + * + * Two parameters from uaspd coexistence ie info (as specified in 11v) are + * sent down to FW along with this command. + * + * The semantics of these fields are described in the following text extracted + * from 802.11v. + * + * --- If the non-AP STA specified a non-zero TSF 0 Offset value in the + * U-APSD Coexistence element, the AP should not transmit frames to the + * non-AP STA outside of the U-APSD Coexistence Service Period, which + * begins when the AP receives the U-APSD trigger frame and ends after + * the transmission period specified by the result of the following + * calculation: + * + * End of transmission period = T + (Interval . ((T . TSF 0 Offset) mod Interval)) + * + * Where T is the time the U-APSD trigger frame was received at the AP + * Interval is the UAPSD Coexistence element Duration/Interval field + * value (see 7.3.2.91) or upon the successful transmission of a frame + * with EOSP bit set to 1, whichever is earlier. + * + * + * --- If the non-AP STA specified a zero TSF 0 Offset value in the U-APSD + * Coexistence element, the AP should not transmit frames to the non-AP + * STA outside of the U-APSD Coexistence Service Period, which begins + * when the AP receives a U-APSD trigger frame and ends after the + * transmission period specified by the result of the following + * calculation: End of transmission period = T + Duration + */ + typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Enable U-APSD coexistence support for this peer + * + * 0 -> disabled (default) + * 1 -> enabled + */ + A_UINT32 enabled; + /** Duration/Interval as defined by 11v U-ASPD coexistance */ + A_UINT32 duration_interval; + /** Upper 32 bits of 64-bit TSF offset */ + A_UINT32 tsf_offset_high; + /** Lower 32 bits of 64-bit TSF offset */ + A_UINT32 tsf_offset_low; + } wmi_ap_powersave_peer_uapsd_coex_cmd; + +typedef enum { + WMI_AP_PS_EGAP_F_ENABLE_PHYERR_DETECTION = 0x0001, + WMI_AP_PS_EGAP_F_ENABLE_PWRSAVE_BY_PS_STATE = 0x0002, + WMI_AP_PS_EGAP_F_ENABLE_PWRSAVE_BY_INACTIVITY = 0x0004, + + WMI_AP_PS_EGAP_FLAG_MAX = 0x8000 +} wmi_ap_ps_egap_flag_type; + +/** + * configure ehanced green ap parameters + */ +typedef struct { + /* + * TLV tag and len; tag equals + * wmi_ap_powersave_egap_param_cmd_fixed_param + */ + A_UINT32 tlv_header; + /** Enable enhanced green ap + * 0 -> disabled + * 1 -> enabled + */ + A_UINT32 enable; + /** The param indicates a duration that all STAs connected + * to S-AP have no traffic. + */ + A_UINT32 inactivity_time; /* in unit of milliseconds */ + /** The param indicates a duration that all STAs connected + * to S-AP have no traffic, after all STAs have entered powersave. + */ + A_UINT32 wait_time; /* in unit of milliseconds */ + /** The param is used to turn on/off some functions within E-GAP. + */ + A_UINT32 flags; /* wmi_ap_ps_egap_flag_type bitmap */ +} wmi_ap_ps_egap_param_cmd_fixed_param; + +typedef enum { + WMI_AP_PS_EGAP_STATUS_IDLE = 1, + WMI_AP_PS_EGAP_STATUS_PWRSAVE_OFF = 2, + WMI_AP_PS_EGAP_STATUS_PWRSAVE_ON = 3, + + WMI_AP_PS_EGAP_STATUS_MAX = 15 +} wmi_ap_ps_egap_status_type; + +/** + * send ehanced green ap status to host + */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ap_ps_egap_info_chainmask_list */ + A_UINT32 tlv_header; + /** The param indicates a mac under dual-mac */ + A_UINT32 mac_id; + /** The param indicates the current tx chainmask with the mac id. */ + A_UINT32 tx_chainmask; + /** The param indicates the current rx chainmask with the mac id. */ + A_UINT32 rx_chainmask; +} wmi_ap_ps_egap_info_chainmask_list; + +typedef struct { + /* + * TLV tag and len; tag equals + * wmi_ap_powersave_egap_param_cmd_fixed_param + */ + A_UINT32 tlv_header; + /** Enhanced green ap status (WMI_AP_PS_EGAP_STATUS). */ + A_UINT32 status; +/* This TLV is followed by + * wmi_ap_ps_egap_info_chainmask_list chainmask_list[]; + */ +} wmi_ap_ps_egap_info_event_fixed_param; + + /* 128 clients = 4 words */ + /* WMI_TIM_BITMAP_ARRAY_SIZE can't be modified without breaking the compatibility */ + #define WMI_TIM_BITMAP_ARRAY_SIZE 4 + + typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tim_info */ + /** TIM bitmap len (in bytes)*/ + A_UINT32 tim_len; + /** TIM Partial Virtual Bitmap */ + A_UINT32 tim_mcast; + A_UINT32 tim_bitmap[WMI_TIM_BITMAP_ARRAY_SIZE]; + A_UINT32 tim_changed; + A_UINT32 tim_num_ps_pending; + } wmi_tim_info; + + typedef struct { + /** Flag to enable quiet period IE support */ + A_UINT32 is_enabled; + /** Quiet start */ + A_UINT32 tbttcount; + /** Beacon intervals between quiets*/ + A_UINT32 period; + /** TUs of each quiet*/ + A_UINT32 duration; + /** TUs of from TBTT of quiet start*/ + A_UINT32 offset; + } wmi_quiet_info; + +/* WMI_P2P_MAX_NOA_DESCRIPTORS can't be modified without breaking the compatibility */ +#define WMI_P2P_MAX_NOA_DESCRIPTORS 4 /* Maximum number of NOA Descriptors supported */ + + typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_noa_info */ + /** Bit 0: Flag to indicate an update in NOA schedule + * Bits 7-1: Reserved + * Bits 15-8: Index (identifies the instance of NOA sub element) + * Bit 16: Opp PS state of the AP + * Bits 23-17: Ctwindow in TUs + * Bits 31-24: Number of NOA descriptors + */ + A_UINT32 noa_attributes; + wmi_p2p_noa_descriptor noa_descriptors[WMI_P2P_MAX_NOA_DESCRIPTORS]; + }wmi_p2p_noa_info; + +#define WMI_UNIFIED_NOA_ATTR_MODIFIED 0x1 +#define WMI_UNIFIED_NOA_ATTR_MODIFIED_S 0 + +#define WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(hdr) \ + WMI_F_MS((hdr)->noa_attributes, WMI_UNIFIED_NOA_ATTR_MODIFIED) + +#define WMI_UNIFIED_NOA_ATTR_MODIFIED_SET(hdr) \ + WMI_F_RMW((hdr)->noa_attributes, 0x1, \ + WMI_UNIFIED_NOA_ATTR_MODIFIED); + +#define WMI_UNIFIED_NOA_ATTR_INDEX 0xff00 +#define WMI_UNIFIED_NOA_ATTR_INDEX_S 8 + +#define WMI_UNIFIED_NOA_ATTR_INDEX_GET(hdr) \ + WMI_F_MS((hdr)->noa_attributes, WMI_UNIFIED_NOA_ATTR_INDEX) + +#define WMI_UNIFIED_NOA_ATTR_INDEX_SET(hdr, v) \ + WMI_F_RMW((hdr)->noa_attributes, (v) & 0xff, \ + WMI_UNIFIED_NOA_ATTR_INDEX); + +#define WMI_UNIFIED_NOA_ATTR_OPP_PS 0x10000 +#define WMI_UNIFIED_NOA_ATTR_OPP_PS_S 16 + +#define WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(hdr) \ + WMI_F_MS((hdr)->noa_attributes, WMI_UNIFIED_NOA_ATTR_OPP_PS) + +#define WMI_UNIFIED_NOA_ATTR_OPP_PS_SET(hdr) \ + WMI_F_RMW((hdr)->noa_attributes, 0x1, \ + WMI_UNIFIED_NOA_ATTR_OPP_PS); + +#define WMI_UNIFIED_NOA_ATTR_CTWIN 0xfe0000 +#define WMI_UNIFIED_NOA_ATTR_CTWIN_S 17 + +#define WMI_UNIFIED_NOA_ATTR_CTWIN_GET(hdr) \ + WMI_F_MS((hdr)->noa_attributes, WMI_UNIFIED_NOA_ATTR_CTWIN) + +#define WMI_UNIFIED_NOA_ATTR_CTWIN_SET(hdr, v) \ + WMI_F_RMW((hdr)->noa_attributes, (v) & 0x7f, \ + WMI_UNIFIED_NOA_ATTR_CTWIN); + +#define WMI_UNIFIED_NOA_ATTR_NUM_DESC 0xff000000 +#define WMI_UNIFIED_NOA_ATTR_NUM_DESC_S 24 + +#define WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(hdr) \ + WMI_F_MS((hdr)->noa_attributes, WMI_UNIFIED_NOA_ATTR_NUM_DESC) + +#define WMI_UNIFIED_NOA_ATTR_NUM_DESC_SET(hdr, v) \ + WMI_F_RMW((hdr)->noa_attributes, (v) & 0xff, \ + WMI_UNIFIED_NOA_ATTR_NUM_DESC); + + typedef struct { + /** TIM info */ + wmi_tim_info tim_info; + /** P2P NOA info */ + wmi_p2p_noa_info p2p_noa_info; + /* TBD: More info elements to be added later */ + } wmi_bcn_info; + + typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_host_swba_event_fixed_param */ + /** bitmap identifying the VDEVs, generated by the caller */ + A_UINT32 vdev_map; + /* This TLV is followed by tim_info and p2p_noa_info for each vdev in vdevmap : + * wmi_tim_info tim_info[]; + * wmi_p2p_noa_info p2p_noa_info[]; + * + */ + } wmi_host_swba_event_fixed_param; + + #define WMI_MAX_AP_VDEV 16 + + + typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tbtt_offset_event_fixed_param */ + /** bimtap of VDEVs that has tbtt offset updated */ + A_UINT32 vdev_map; + /* The TLVs for tbttoffset_list will follow this TLV. + * tbtt offset list in the order of the LSB to MSB in the vdev_map bitmap + * A_UINT32 tbttoffset_list[WMI_MAX_AP_VDEV]; + */ + } wmi_tbtt_offset_event_fixed_param; + + + /* Peer Specific commands and events */ + +typedef struct { + A_UINT32 percentage; /* in unit of 12.5% */ + A_UINT32 min_delta; /* in unit of Mbps */ +} rate_delta_t; + +#define PEER_RATE_REPORT_COND_FLAG_DELTA 0x01 +#define PEER_RATE_REPORT_COND_FLAG_THRESHOLD 0x02 +#define MAX_NUM_OF_RATE_THRESH 4 + +typedef struct { + A_UINT32 val_cond_flags; /* PEER_RATE_REPORT_COND_FLAG_DELTA, PEER_RATE_REPORT_COND_FLAG_THRESHOLD + Any of these two conditions or both of them can be set. */ + rate_delta_t rate_delta; + A_UINT32 rate_threshold[MAX_NUM_OF_RATE_THRESH]; /* In unit of Mbps. There are at most 4 thresholds. + If the threshold count is less than 4, set zero to + the one following the last threshold */ +} report_cond_per_phy_t; + + +enum peer_rate_report_cond_phy_type { + PEER_RATE_REPORT_COND_11B = 0, + PEER_RATE_REPORT_COND_11A_G, + PEER_RATE_REPORT_COND_11N, + PEER_RATE_REPORT_COND_11AC, + PEER_RATE_REPORT_COND_MAX_NUM +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_rate_report_condtion_fixed_param */ + A_UINT32 enable_rate_report; /* 1= enable, 0=disable */ + A_UINT32 report_backoff_time; /* in unit of msecond */ + A_UINT32 report_timer_period; /* in unit of msecond */ + /* In the following field, the array index means the phy type, + * please see enum peer_rate_report_cond_phy_type for detail */ + report_cond_per_phy_t cond_per_phy[PEER_RATE_REPORT_COND_MAX_NUM]; +} wmi_peer_set_rate_report_condition_fixed_param; + + /* Peer Type: + * NB: This can be left DEFAULT for the normal case, and f/w will determine BSS type based + * on address and vdev opmode. This is largely here to allow host to indicate that + * peer is explicitly a TDLS peer + */ + enum wmi_peer_type { + WMI_PEER_TYPE_DEFAULT = 0, /* Generic/Non-BSS/Self Peer */ + WMI_PEER_TYPE_BSS = 1, /* Peer is BSS Peer entry */ + WMI_PEER_TYPE_TDLS = 2, /* Peer is a TDLS Peer */ + WMI_PEER_TYPE_OCB = 3, /* Peer is a OCB Peer */ + WMI_PEER_TYPE_HOST_MAX = 127, /* Host <-> Target Peer type + * is assigned up to 127 */ + /* Reserved from 128 - 255 for + * target internal use.*/ + WMI_PEER_TYPE_ROAMOFFLOAD_TEMP = 128, /* Temporarily created during offload roam */ + }; + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_create_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** peer type: see enum values above */ + A_UINT32 peer_type; + } wmi_peer_create_cmd_fixed_param; + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_delete_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + } wmi_peer_delete_cmd_fixed_param; + + typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_flush_tids_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** tid bitmap identifying the tids to flush */ + A_UINT32 peer_tid_bitmap; + } wmi_peer_flush_tids_cmd_fixed_param; + + typedef struct { + /** rate mode . 0: disable fixed rate (auto rate) + * 1: legacy (non 11n) rate specified as ieee rate 2*Mbps + * 2: ht20 11n rate specified as mcs index + * 3: ht40 11n rate specified as mcs index + */ + A_UINT32 rate_mode; + /** 4 rate values for 4 rate series. series 0 is stored in byte 0 (LSB) + * and series 3 is stored at byte 3 (MSB) */ + A_UINT32 rate_series; + /** 4 retry counts for 4 rate series. retry count for rate 0 is stored in byte 0 (LSB) + * and retry count for rate 3 is stored at byte 3 (MSB) */ + A_UINT32 rate_retries; + } wmi_fixed_rate; + + typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** fixed rate */ + wmi_fixed_rate peer_fixed_rate; + } wmi_peer_fixed_rate_cmd; + + #define WMI_MGMT_TID 17 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_addba_clear_resp_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; +} wmi_addba_clear_resp_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_addba_send_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** Buffer/Window size*/ + A_UINT32 buffersize; +} wmi_addba_send_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_delba_send_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** Is Initiator */ + A_UINT32 initiator; + /** Reason code */ + A_UINT32 reasoncode; +} wmi_delba_send_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_addba_setresponse_cmd_fixed_param */ + /** unique id identifying the vdev, generated by the caller */ + A_UINT32 vdev_id; + /** peer mac address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** status code */ + A_UINT32 statuscode; +} wmi_addba_setresponse_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_send_singleamsdu_cmd_fixed_param */ + /** unique id identifying the vdev, generated by the caller */ + A_UINT32 vdev_id; + /** peer mac address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; +} wmi_send_singleamsdu_cmd_fixed_param; + +/* Type of Station DTIM Power Save method */ +enum { + /* For NORMAL DTIM, the parameter is the number of beacon intervals and + * also the same value as the listen interval. For this method, the + * station will wake up based on the listen interval. If this + * listen interval is not equal to DTIM, then the station may + * miss certain DTIM beacons. If this value is 1, then the + * station will wake up for every beacon. + */ + WMI_STA_DTIM_PS_NORMAL_DTIM = 0x01, + /* For MODULATED_DTIM, parameter is a multiple of DTIM beacons to skip. + * When this value is 1, then the station will wake at every DTIM beacon. + * If this value is >1, then the station will skip certain DTIM beacons. + * This value is the multiple of DTIM intervals that the station will + * wake up to receive the DTIM beacons. + */ + WMI_STA_DTIM_PS_MODULATED_DTIM = 0x02, +}; + +/* Parameter structure for the WMI_STA_DTIM_PS_METHOD_CMDID */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_dtim_ps_method_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** Station DTIM Power Save method as defined above */ + A_UINT32 dtim_pwrsave_method; + /** DTIM PS value. Contents depends on the method */ + A_UINT32 value; + /** Modulated DTIM value */ + A_UINT32 MaxLIModulatedDTIM; +} wmi_sta_dtim_ps_method_cmd_fixed_param; + + /* + * For Station UAPSD Auto Trigger feature, the Firmware monitors the + * uAPSD uplink and downlink traffic for each uAPSD enabled WMM ACs. + * If there is no uplink/download for the specified service interval (field service_interval), + * firmware will auto generate a QOS-NULL trigger for that WMM-AP with the TID value + * specified in the UP (field user_priority). + * Firmware also monitors the responses for these QOS-NULL triggers. + * If the peer does not have any delivery frames, it will respond with + * QOS-NULL (EOSP=1). This feature of only using service interval is assumed to be mandatory for all + * firmware implementation. For this basic implementation, the suspend_interval and delay_interval + * are unused and should be set to 0. + * When service_interval is 0, then the firmware will not send any trigger frames. This is for + * certain host-based implementations that don't want this firmware offload. + * Note that the per-AC intervals are required for some usage scenarios. This is why the intervals + * are given in the array of ac_param[]. For example, Voice service interval may defaults to 20 ms + * and rest of the AC default to 300 ms. + * + * The service bit, WMI_STA_UAPSD_VAR_AUTO_TRIG, will indicate that the more advanced feature + * of variable auto trigger is supported. The suspend_interval and delay_interval is used in + * the more advanced monitoring method. + * If the PEER does not have any delivery enabled data frames (non QOS-NULL) for the + * suspend interval (field suspend_interval), firmware will change its auto trigger interval + * to delay interval (field delay_interval). This way, when there is no traffic, the station + * will save more power by waking up less and sending less trigger frames. + * The (service_interval < suspend_interval) and (service_interval < delay_interval). + * If this variable auto trigger is not required, then the suspend_interval and delay_interval + * should be 0. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_param */ + /** WMM Access category from 0 to 3 */ + A_UINT32 wmm_ac; + /** User priority to use in trigger frames. It is the TID + * value. This field needs to be specified and may not be + * equivalent to AC since some implementation may use the TSPEC + * to enable UAPSD and negotiate a particular user priority. */ + A_UINT32 user_priority; + /** service interval in ms */ + A_UINT32 service_interval; + /** Suspend interval in ms */ + A_UINT32 suspend_interval; + /** delay interval in ms */ + A_UINT32 delay_interval; +} wmi_sta_uapsd_auto_trig_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer mac address */ + wmi_mac_addr peer_macaddr; + /** Number of AC to specify */ + A_UINT32 num_ac; + /* + * Following this struc is the TLV: + * wmi_sta_uapsd_auto_trig_param ac_param[]; //Variable number of AC parameters (defined by field num_ac) + */ + +} wmi_sta_uapsd_auto_trig_cmd_fixed_param; + +/** mimo powersave state */ +#define WMI_PEER_MIMO_PS_STATE 0x1 +/** enable/disable AMPDU . initial value (enabled) */ +#define WMI_PEER_AMPDU 0x2 +/** authorize/unauthorize peer. initial value is unauthorized (0) */ +#define WMI_PEER_AUTHORIZE 0x3 +/** peer channel bandwidth */ +#define WMI_PEER_CHWIDTH 0x4 +/** peer NSS */ +#define WMI_PEER_NSS 0x5 +/** USE 4 ADDR */ +#define WMI_PEER_USE_4ADDR 0x6 +/* set group membership status */ +#define WMI_PEER_MEMBERSHIP 0x7 +#define WMI_PEER_USERPOS 0x8 +/* + * A critical high-level protocol is being used with this peer. Target + * should take appropriate measures (if possible) to ensure more + * reliable link with minimal latency. This *may* include modifying the + * station power save policy, enabling more RX chains, increased + * priority of channel scheduling, etc. + * + * NOTE: This parameter should only be considered a hint as specific + * behavior will depend on many factors including current network load + * and vdev/peer configuration. + * + * For STA VDEV this peer corresponds to the AP's BSS peer. + * For AP VDEV this peer corresponds to the remote peer STA. + */ +#define WMI_PEER_CRIT_PROTO_HINT_ENABLED 0x9 +/* set Tx failure count threshold for the peer - Currently unused */ +#define WMI_PEER_TX_FAIL_CNT_THR 0xA +/* Enable H/W retry and Enable H/W Send CTS2S before Data */ +#define WMI_PEER_SET_HW_RETRY_CTS2S 0xB + +/* Set peer advertised IBSS atim window length */ +#define WMI_PEER_IBSS_ATIM_WINDOW_LENGTH 0xC + +/** peer phy mode */ +#define WMI_PEER_PHYMODE 0xD + +/** mimo ps values for the parameter WMI_PEER_MIMO_PS_STATE */ +#define WMI_PEER_MIMO_PS_NONE 0x0 +#define WMI_PEER_MIMO_PS_STATIC 0x1 +#define WMI_PEER_MIMO_PS_DYNAMIC 0x2 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** parameter id */ + A_UINT32 param_id; + /** parametr value */ + A_UINT32 param_value; +} wmi_peer_set_param_cmd_fixed_param; + +#define MAX_SUPPORTED_RATES 128 + +typedef struct { + /** total number of rates */ + A_UINT32 num_rates; + /** + * rates (each 8bit value) packed into a 32 bit word. + * the rates are filled from least significant byte to most + * significant byte. + */ + A_UINT32 rates[(MAX_SUPPORTED_RATES/4)+1]; +} wmi_rate_set; + +/* NOTE: It would bea good idea to represent the Tx MCS + * info in one word and Rx in another word. This is split + * into multiple words for convenience + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vht_rate_set */ + A_UINT32 rx_max_rate; /* Max Rx data rate */ + A_UINT32 rx_mcs_set; /* Negotiated RX VHT rates */ + A_UINT32 tx_max_rate; /* Max Tx data rate */ + A_UINT32 tx_mcs_set; /* Negotiated TX VHT rates */ +}wmi_vht_rate_set; + +/* + * IMPORTANT: Make sure the bit definitions here are consistent + * with the ni_flags definitions in wlan_peer.h + */ +#define WMI_PEER_AUTH 0x00000001 /* Authorized for data */ +#define WMI_PEER_QOS 0x00000002 /* QoS enabled */ +#define WMI_PEER_NEED_PTK_4_WAY 0x00000004 /* Needs PTK 4 way handshake for authorization */ +#define WMI_PEER_NEED_GTK_2_WAY 0x00000010 /* Needs GTK 2 way handshake after 4-way handshake */ +#define WMI_PEER_APSD 0x00000800 /* U-APSD power save enabled */ +#define WMI_PEER_HT 0x00001000 /* HT enabled */ +#define WMI_PEER_40MHZ 0x00002000 /* 40MHz enabld */ +#define WMI_PEER_STBC 0x00008000 /* STBC Enabled */ +#define WMI_PEER_LDPC 0x00010000 /* LDPC ENabled */ +#define WMI_PEER_DYN_MIMOPS 0x00020000 /* Dynamic MIMO PS Enabled */ +#define WMI_PEER_STATIC_MIMOPS 0x00040000 /* Static MIMO PS enabled */ +#define WMI_PEER_SPATIAL_MUX 0x00200000 /* SM Enabled */ +#define WMI_PEER_VHT 0x02000000 /* VHT Enabled */ +#define WMI_PEER_80MHZ 0x04000000 /* 80MHz enabld */ +#define WMI_PEER_PMF 0x08000000 /* Robust Management Frame Protection enabled */ +/** CAUTION TODO: Place holder for WLAN_PEER_F_PS_PRESEND_REQUIRED = 0x10000000. Need to be clean up */ +#define WMI_PEER_IS_P2P_CAPABLE 0x20000000 /* P2P capable peer */ +#define WMI_PEER_160MHZ 0x40000000 /* 160 MHz enabled */ +#define WMI_PEER_SAFEMODE_EN 0x80000000 /* Fips Mode Enabled */ + +/** + * Peer rate capabilities. + * + * This is of interest to the ratecontrol + * module which resides in the firmware. The bit definitions are + * consistent with that defined in if_athrate.c. + * + * @todo + * Move this to a common header file later so there is no need to + * duplicate the definitions or maintain consistency. + */ +#define WMI_RC_DS_FLAG 0x01 /* Dual stream flag */ +#define WMI_RC_CW40_FLAG 0x02 /* CW 40 */ +#define WMI_RC_SGI_FLAG 0x04 /* Short Guard Interval */ +#define WMI_RC_HT_FLAG 0x08 /* HT */ +#define WMI_RC_RTSCTS_FLAG 0x10 /* RTS-CTS */ +#define WMI_RC_TX_STBC_FLAG 0x20 /* TX STBC */ +#define WMI_RC_TX_STBC_FLAG_S 5 /* TX STBC */ +#define WMI_RC_RX_STBC_FLAG 0xC0 /* RX STBC ,2 bits */ +#define WMI_RC_RX_STBC_FLAG_S 6 /* RX STBC ,2 bits */ +#define WMI_RC_WEP_TKIP_FLAG 0x100 /* WEP/TKIP encryption */ +#define WMI_RC_TS_FLAG 0x200 /* Three stream flag */ +#define WMI_RC_UAPSD_FLAG 0x400 /* UAPSD Rate Control */ + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_assoc_complete_cmd_fixed_param */ + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** VDEV id */ + A_UINT32 vdev_id; + /** assoc = 1 reassoc = 0 */ + A_UINT32 peer_new_assoc; + /** peer associd (16 bits) */ + A_UINT32 peer_associd; + /** peer station flags: see definition above */ + A_UINT32 peer_flags; + /** negotiated capabilities (lower 16 bits)*/ + A_UINT32 peer_caps; + /** Listen interval */ + A_UINT32 peer_listen_intval; + /** HT capabilties of the peer */ + A_UINT32 peer_ht_caps; + /** maximum rx A-MPDU length */ + A_UINT32 peer_max_mpdu; + /** mpdu density of the peer in usec(0 to 16) */ + A_UINT32 peer_mpdu_density; + /** peer rate capabilties see flags above */ + A_UINT32 peer_rate_caps; + /** num spatial streams */ + A_UINT32 peer_nss; + /** VHT capabilties of the peer */ + A_UINT32 peer_vht_caps; + /** phy mode */ + A_UINT32 peer_phymode; + /** HT Operation Element of the peer. Five bytes packed in 2 + * INT32 array and filled from lsb to msb. + * Note that the size of array peer_ht_info[] cannotbe changed + * without breaking WMI Compatibility. */ + A_UINT32 peer_ht_info[2]; + /** total number of negotiated legacy rate set. Also the sizeof + * peer_legacy_rates[] */ + A_UINT32 num_peer_legacy_rates; + /** total number of negotiated ht rate set. Also the sizeof + * peer_ht_rates[] */ + A_UINT32 num_peer_ht_rates; + /* Following this struc are the TLV's: + * A_UINT8 peer_legacy_rates[]; + * A_UINT8 peer_ht_rates[]; + * wmi_vht_rate_set peer_vht_rates; //VHT capabilties of the peer + */ +} wmi_peer_assoc_complete_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_add_wds_entry_cmd_fixed_param */ + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** wds MAC addr */ + wmi_mac_addr wds_macaddr; +} wmi_peer_add_wds_entry_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_remove_wds_entry_cmd_fixed_param */ + /** wds MAC addr */ + wmi_mac_addr wds_macaddr; +} wmi_peer_remove_wds_entry_cmd_fixed_param; + + +typedef struct { + /** peer MAC address */ + wmi_mac_addr peer_macaddr; +} wmi_peer_q_empty_callback_event; + + + +/** + * Channel info WMI event + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chan_info_event_fixed_param */ + /** Error code */ + A_UINT32 err_code; + /** Channel freq */ + A_UINT32 freq; + /** Read flags */ + A_UINT32 cmd_flags; + /** Noise Floor value */ + A_UINT32 noise_floor; + /** rx clear count */ + A_UINT32 rx_clear_count; + /** cycle count */ + A_UINT32 cycle_count; +} wmi_chan_info_event_fixed_param; + +/** + * Non wlan interference event + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_ath_dcs_cw_int */ + A_UINT32 channel; /* either number or freq in mhz*/ +} ath_dcs_cw_int; + +/** + * wlan_dcs_im_tgt_stats + * + */ +typedef struct _wlan_dcs_im_tgt_stats { + /** current running TSF from the TSF-1 */ + A_UINT32 reg_tsf32; + + /** Known last frame rssi, in case of multiple stations, if + * and at different ranges, this would not gaurantee that + * this is the least rssi. + */ + A_UINT32 last_ack_rssi; + + /** Sum of all the failed durations in the last one second interval. + */ + A_UINT32 tx_waste_time; + /** count how many times the hal_rxerr_phy is marked, in this + * time period + */ + A_UINT32 rx_time; + A_UINT32 phyerr_cnt; + + /** + * WLAN IM stats from target to host + * + * Below statistics are sent from target to host periodically. + * These are collected at target as long as target is running + * and target chip is not in sleep. + * + */ + + /** listen time from ANI */ + A_INT32 listen_time; + + /** tx frame count, MAC_PCU_TX_FRAME_CNT_ADDRESS */ + A_UINT32 reg_tx_frame_cnt; + + /** rx frame count, MAC_PCU_RX_FRAME_CNT_ADDRESS */ + A_UINT32 reg_rx_frame_cnt; + + /** rx clear count, MAC_PCU_RX_CLEAR_CNT_ADDRESS */ + A_UINT32 reg_rxclr_cnt; + + /** total cycle counts MAC_PCU_CYCLE_CNT_ADDRESS */ + A_UINT32 reg_cycle_cnt; /* delta cycle count */ + + /** extenstion channel rx clear count */ + A_UINT32 reg_rxclr_ext_cnt; + + /** OFDM phy error counts, MAC_PCU_PHY_ERR_CNT_1_ADDRESS */ + A_UINT32 reg_ofdm_phyerr_cnt; + + /** CCK phy error count, MAC_PCU_PHY_ERR_CNT_2_ADDRESS */ + A_UINT32 reg_cck_phyerr_cnt; /* CCK err count since last reset, read from register */ + +} wlan_dcs_im_tgt_stats_t; + +/** + * wmi_dcs_interference_event_t + * + * Right now this is event and stats together. Partly this is + * because cw interference is handled in target now. This + * can be done at host itself, if we can carry the NF alone + * as a stats event. In future this would be done and this + * event would carry only stats. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_dcs_interference_event_fixed_param */ + /** + * Type of the event present, either the cw interference event, or the wlan_im stats + */ + A_UINT32 interference_type; /* type of interference, wlan or cw */ + /* + * Following this struct are these TLVs. Note that they are both array of structures + * but can have at most one element. Which TLV is empty or has one element depends + * on the field interference_type. This is to emulate an union with cw_int and wlan_stat + * elements (not arrays). union { ath_dcs_cw_int cw_int; wlan_dcs_im_tgt_stats_t wlan_stat; } int_event; + * + * //cw_interference event + * ath_dcs_cw_int cw_int[]; this element + * // wlan im interfernce stats + * wlan_dcs_im_tgt_stats_t wlan_stat[]; + */ +} wmi_dcs_interference_event_fixed_param; + +enum wmi_peer_mcast_group_action { + wmi_peer_mcast_group_action_add = 0, + wmi_peer_mcast_group_action_del = 1 +}; +#define WMI_PEER_MCAST_GROUP_FLAG_ACTION_M 0x1 +#define WMI_PEER_MCAST_GROUP_FLAG_ACTION_S 0 +#define WMI_PEER_MCAST_GROUP_FLAG_WILDCARD_M 0x2 +#define WMI_PEER_MCAST_GROUP_FLAG_WILDCARD_S 1 +/* multicast group membership commands */ +/* TODO: Converting this will be tricky since it uses an union. + Also, the mac_addr is not aligned. We will convert to the wmi_mac_addr */ +typedef struct{ + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_mcast_group_cmd_fixed_param */ + A_UINT32 flags; + wmi_mac_addr ucast_mac_addr; + A_UINT8 mcast_ip_addr[16]; /* in network byte order */ +} wmi_peer_mcast_group_cmd_fixed_param; + + +/** Offload Scan and Roaming related commands */ +/** The FW performs 2 different kinds of offload scans independent + * of host. One is Roam scan which is primarily performed on a + * station VDEV after association to look for a better AP that + * the station VDEV can roam to. The second scan is connect scan + * which is mainly performed when the station is not associated + * and to look for a matching AP profile from a list of + * configured profiles. */ + +/** + * WMI_ROAM_SCAN_MODE: Set Roam Scan mode + * the roam scan mode is one of the periodic, rssi change, both, none. + * None : Disable Roam scan. No Roam scan at all. + * Periodic : Scan periodically with a configurable period. + * Rssi change : Scan when ever rssi to current AP changes by the threshold value + * set by WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD command. + * Both : Both of the above (scan when either period expires or rss to current AP changes by X amount) + * + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param */ + A_UINT32 roam_scan_mode; + A_UINT32 vdev_id; +} wmi_roam_scan_mode_fixed_param; + +#define WMI_ROAM_SCAN_MODE_NONE 0x0 +#define WMI_ROAM_SCAN_MODE_PERIODIC 0x1 +#define WMI_ROAM_SCAN_MODE_RSSI_CHANGE 0x2 +#define WMI_ROAM_SCAN_MODE_BOTH 0x3 +/* Note: WMI_ROAM_SCAN_MODE_ROAMOFFLOAD is one bit not conflict with LFR2.0 SCAN_MODE. */ +#define WMI_ROAM_SCAN_MODE_ROAMOFFLOAD 0x4 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 command_arg; +} wmi_roam_scan_cmd_fixed_param; + +#define WMI_ROAM_SCAN_STOP_CMD 0x1 + +/** + * WMI_ROAM_SCAN_RSSI_THRESHOLD : set scan rssi thresold + * scan rssi threshold is the rssi threshold below which the FW will start running Roam scans. + * Applicable when WMI_ROAM_SCAN_MODE is not set to none. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** roam scan rssi threshold */ + A_UINT32 roam_scan_rssi_thresh; + /** When using Hw generated beacon RSSI interrupts */ + A_UINT32 roam_rssi_thresh_diff; + /** 5G scan max count */ + A_UINT32 hirssi_scan_max_count; + /** 5G scan rssi change threshold value */ + A_UINT32 hirssi_scan_delta; + /** 5G scan upper bound */ + A_UINT32 hirssi_upper_bound; + /* The TLVs will follow. + * wmi_roam_scan_extended_threshold_param extended_param; + * wmi_roam_earlystop_rssi_thres_param earlystop_param; + */ +} wmi_roam_scan_rssi_threshold_fixed_param; + +#define WMI_ROAM_5G_BOOST_PENALIZE_ALGO_FIXED 0x0 +#define WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR 0x1 +#define WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LOG 0x2 +#define WMI_ROAM_5G_BOOST_PENALIZE_ALGO_EXP 0x3 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param */ + A_UINT32 boost_threshold_5g; /** RSSI threshold above which 5GHz RSSI is favored */ + A_UINT32 penalty_threshold_5g; /** RSSI threshold below which 5GHz RSSI is penalized */ + A_UINT32 boost_algorithm_5g; /** 0 == fixed, 1 == linear, 2 == logarithm ..etc */ + A_UINT32 boost_factor_5g; /** factor by which 5GHz RSSI is boosted */ + A_UINT32 penalty_algorithm_5g; /** 0 == fixed, 1 == linear, 2 == logarithm ..etc */ + A_UINT32 penalty_factor_5g; /** factor by which 5GHz RSSI is penalized */ + A_UINT32 max_boost_5g; /** maximum boost that can be applied to a 5GHz RSSI */ + A_UINT32 max_penalty_5g; /** maximum penality that can be applied to a 5GHz RSSI */ + A_UINT32 good_rssi_threshold; /** RSSI below which roam is kicked in by background scan, although rssi is still good */ +} wmi_roam_scan_extended_threshold_param; + +/** + * WMI_ROAM_SCAN_PERIOD: period for roam scan. + * Applicable when the scan mode is Periodic or both. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** roam scan period value */ + A_UINT32 roam_scan_period; + /** Aging for Roam scans */ + A_UINT32 roam_scan_age; +} wmi_roam_scan_period_fixed_param; + +/** + * WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD : rssi delta to trigger the roam scan. + * Rssi change threshold used when mode is Rssi change (or) Both. + * The FW will run the roam scan when ever the rssi changes (up or down) by the value set by this parameter. + * Note scan is triggered based on the rssi threshold condition set by WMI_ROAM_SCAN_RSSI_THRESHOLD + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** roam scan rssi change threshold value */ + A_UINT32 roam_scan_rssi_change_thresh; + /** When using Hw generated beacon RSSI interrupts */ + A_UINT32 bcn_rssi_weight; + /** Minimum delay between two 5G scans */ + A_UINT32 hirssi_delay_btw_scans; +} wmi_roam_scan_rssi_change_threshold_fixed_param; + +#define WMI_ROAM_SCAN_CHAN_LIST_TYPE_NONE 0x1 +#define WMI_ROAM_SCAN_CHAN_LIST_TYPE_STATIC 0x2 +#define WMI_ROAM_SCAN_CHAN_LIST_TYPE_DYNAMIC 0x3 +/** + * TLV for roaming channel list + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** WMI_CHAN_LIST_TAG */ + A_UINT32 chan_list_type; + /** # if channels to scan */ + A_UINT32 num_chan; +/** + * TLV (tag length value ) parameters follow the wmi_roam_chan_list + * structure. The TLV's are: + * A_UINT32 channel_list[]; + **/ +} wmi_roam_chan_list_fixed_param; + +/** Authentication modes */ +enum { + WMI_AUTH_NONE , /* no upper level auth */ + WMI_AUTH_OPEN , /* open */ + WMI_AUTH_SHARED , /* shared-key */ + WMI_AUTH_8021X , /* 802.1x */ + WMI_AUTH_AUTO , /* Auto */ + WMI_AUTH_WPA , /* WPA */ + WMI_AUTH_RSNA , /* WPA2/RSNA */ + WMI_AUTH_CCKM , /* CCK */ + WMI_AUTH_WAPI ,/* WAPI */ + WMI_AUTH_AUTO_PSK, + WMI_AUTH_WPA_PSK, + WMI_AUTH_RSNA_PSK, + WMI_AUTH_WAPI_PSK, + WMI_AUTH_FT_RSNA, /* 11r FT */ + WMI_AUTH_FT_RSNA_PSK, + WMI_AUTH_RSNA_PSK_SHA256, + WMI_AUTH_RSNA_8021X_SHA256, +}; + +typedef struct { + /** authentication mode (defined above) */ + A_UINT32 rsn_authmode; + /** unicast cipher set */ + A_UINT32 rsn_ucastcipherset; + /** mcast/group cipher set */ + A_UINT32 rsn_mcastcipherset; + /** mcast/group management frames cipher set */ + A_UINT32 rsn_mcastmgmtcipherset; +} wmi_rsn_params; + +/** looking for a wps enabled AP */ +#define WMI_AP_PROFILE_FLAG_WPS 0x1 +/** looking for a secure AP */ +#define WMI_AP_PROFILE_FLAG_CRYPTO 0x2 +/** looking for a PMF enabled AP */ +#define WMI_AP_PROFILE_FLAG_PMF 0x4 + +/** To match an open AP, the rs_authmode should be set to WMI_AUTH_NONE + * and WMI_AP_PROFILE_FLAG_CRYPTO should be clear. + * To match a WEP enabled AP, the rs_authmode should be set to WMI_AUTH_NONE + * and WMI_AP_PROFILE_FLAG_CRYPTO should be set . + */ + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ap_profile */ + /** flags as defined above */ + A_UINT32 flags; + /** + * rssi thresold value: the value of the the candidate AP should + * higher by this threshold than the rssi of the currrently associated AP. + */ + A_UINT32 rssi_threshold; + /** + * ssid vlaue to be matched. + */ + wmi_ssid ssid; + + /** + * security params to be matched. + */ + /** authentication mode (defined above) */ + A_UINT32 rsn_authmode; + /** unicast cipher set */ + A_UINT32 rsn_ucastcipherset; + /** mcast/group cipher set */ + A_UINT32 rsn_mcastcipherset; + /** mcast/group management frames cipher set */ + A_UINT32 rsn_mcastmgmtcipherset; +} wmi_ap_profile; + +/** Support early stop roaming scanning when finding a strong candidate AP + * A 'strong' candidate is + * 1) Is eligible candidate + * (all conditions are met in existing candidate selection). + * 2) Its rssi is better than earlystop threshold. + * Earlystop threshold will be relaxed as each channel is scanned. + */ +typedef struct { + A_UINT32 tlv_header; + /* Minimum RSSI threshold value for early stop, unit is dB above NF. */ + A_UINT32 roam_earlystop_thres_min; + /* Maminum RSSI threshold value for early stop, unit is dB above NF. */ + A_UINT32 roam_earlystop_thres_max; +} wmi_roam_earlystop_rssi_thres_param; + +/** Beacon filter wmi command info */ + +#define BCN_FLT_MAX_SUPPORTED_IES 256 +#define BCN_FLT_MAX_ELEMS_IE_LIST BCN_FLT_MAX_SUPPORTED_IES/32 + +typedef struct bss_bcn_stats { + A_UINT32 vdev_id; + A_UINT32 bss_bcnsdropped; + A_UINT32 bss_bcnsdelivered; +}wmi_bss_bcn_stats_t; + +typedef struct bcn_filter_stats { + A_UINT32 bcns_dropped; + A_UINT32 bcns_delivered; + A_UINT32 activefilters; + wmi_bss_bcn_stats_t bss_stats; +}wmi_bcnfilter_stats_t; + +typedef struct wmi_add_bcn_filter_cmd { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param */ + A_UINT32 vdev_id; + /* + * Following this structure is the TLV: + * A_UINT32 ie_map[BCN_FLT_MAX_ELEMS_IE_LIST]; + */ +} wmi_add_bcn_filter_cmd_fixed_param; + +typedef struct wmi_rmv_bcn_filter_cmd { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param */ + A_UINT32 vdev_id; +}wmi_rmv_bcn_filter_cmd_fixed_param; + +#define WMI_BCN_SEND_DTIM_ZERO 1 +#define WMI_BCN_SEND_DTIM_BITCTL_SET 2 +typedef struct wmi_bcn_send_from_host { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 data_len; + A_UINT32 frag_ptr; /* Physical address of the frame */ + A_UINT32 frame_ctrl; /* farme ctrl to setup PPDU desc */ + A_UINT32 dtim_flag; /* to control CABQ traffic */ +}wmi_bcn_send_from_host_cmd_fixed_param; + +/* cmd to support bcn snd for all vaps at once */ +typedef struct wmi_pdev_send_bcn { + A_UINT32 num_vdevs; + wmi_bcn_send_from_host_cmd_fixed_param bcn_cmd[1]; +} wmi_pdev_send_bcn_cmd_t; + + /* + * WMI_ROAM_AP_PROFILE: AP profile of connected AP for roaming. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param */ + /** id of AP criteria */ + A_UINT32 id; + + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + + /* + * Following this structure is the TLV: + * wmi_ap_profile ap_profile; //AP profile info + */ +} wmi_roam_ap_profile_fixed_param; + +/** + * WMI_OFL_SCAN_ADD_AP_PROFILE: add an AP profile. + */ +typedef struct { + /** id of AP criteria */ + A_UINT32 id; + + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + + /** AP profile info */ + wmi_ap_profile ap_profile; + +} wmi_ofl_scan_add_ap_profile; + +/** + * WMI_OFL_SCAN_REMOVE_AP_CRITERIA: remove an ap profile. + */ +typedef struct { + /** id of AP criteria */ + A_UINT32 id; + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_ofl_scan_remove_ap_profile; + +/** + * WMI_OFL_SCAN_PERIOD: period in msec for offload scan. + * 0 will disable ofload scan and a very low value will perform a continous + * scan. + */ +typedef struct { + /** offload scan period value, used for scans used when not connected */ + A_UINT32 ofl_scan_period; +} wmi_ofl_scan_period; + +/* Do not modify XXX_BYTES or XXX_LEN below as it is fixed by standard */ +#define ROAM_OFFLOAD_PMK_BYTES (32) +#define ROAM_OFFLOAD_PSK_MSK_BYTES (32) +#define ROAM_OFFLOAD_KRK_BYTES (16) +#define ROAM_OFFLOAD_BTK_BYTES (32) +#define ROAM_OFFLOAD_R0KH_ID_MAX_LEN (48) +#define ROAM_OFFLOAD_NUM_MCS_SET (16) + +/* This TLV will be filled only in case roam offload + * for wpa2-psk/okc/ese/11r is enabled */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_offload_fixed_param */ + A_UINT32 rssi_cat_gap; /* gap for every category bucket */ + A_UINT32 prefer_5g; /* prefer select 5G candidate */ + A_UINT32 select_5g_margin; + A_UINT32 reassoc_failure_timeout; /* reassoc failure timeout */ + A_UINT32 capability; + A_UINT32 ht_caps_info; + A_UINT32 ampdu_param; + A_UINT32 ht_ext_cap; + A_UINT32 ht_txbf; + A_UINT32 asel_cap; + A_UINT32 qos_enabled; + A_UINT32 qos_caps; + A_UINT32 wmm_caps; + A_UINT32 mcsset[ROAM_OFFLOAD_NUM_MCS_SET>>2]; /* since this 4 byte aligned, + * we don't declare it as + * tlv array */ +} wmi_roam_offload_tlv_param; + +/* flags for 11i offload */ +#define WMI_ROAM_OFFLOAD_FLAG_OKC_ENABLED 0 /* okc is enabled */ +/* from bit 1 to bit 31 are reserved */ + +#define WMI_SET_ROAM_OFFLOAD_OKC_ENABLED(flag) do { \ + (flag) |= (1 << WMI_ROAM_OFFLOAD_FLAG_OKC_ENABLED); \ + } while(0) + +#define WMI_SET_ROAM_OFFLOAD_OKC_DISABLED(flag) do { \ + (flag) &= ~(1 << WMI_ROAM_OFFLOAD_FLAG_OKC_ENABLED); \ + } while(0) + +#define WMI_GET_ROAM_OFFLOAD_OKC_ENABLED(flag) \ + ((flag) & (1 << WMI_ROAM_OFFLOAD_FLAG_OKC_ENABLED)) + +/* This TLV will be filled only in case of wpa-psk/wpa2-psk */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_11i_offload_fixed_param */ + A_UINT32 flags; /** flags. see WMI_ROAM_OFFLOAD_FLAG_ above */ + A_UINT32 pmk[ROAM_OFFLOAD_PMK_BYTES>>2]; /* pmk offload. As this 4 byte aligned, we don't declare it as tlv array */ + A_UINT32 pmk_len; /**the length of pmk. in normal case it should be 32, but for LEAP, is should be 16*/ +} wmi_roam_11i_offload_tlv_param; + +/* This TLV will be filled only in case of 11R*/ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_11r_offload_fixed_param */ + A_UINT32 mdie_present; + A_UINT32 mdid; + A_UINT32 r0kh_id[ROAM_OFFLOAD_R0KH_ID_MAX_LEN>>2]; + A_UINT32 r0kh_id_len; + A_UINT32 psk_msk[ROAM_OFFLOAD_PSK_MSK_BYTES>>2]; /* psk/msk offload. As this 4 byte aligned, we don't declare it as tlv array */ + A_UINT32 psk_msk_len; /**length of psk_msk*/ +} wmi_roam_11r_offload_tlv_param; + +/* This TLV will be filled only in case of ESE */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_ese_offload_fixed_param */ + A_UINT32 krk[ROAM_OFFLOAD_KRK_BYTES>>2]; /* KRK offload. As this 4 byte aligned, we don't declare it as tlv array */ + A_UINT32 btk[ROAM_OFFLOAD_BTK_BYTES>>2]; /* BTK offload. As this 4 byte aligned, we don't declare it as tlv array */ +} wmi_roam_ese_offload_tlv_param; + + +/** WMI_ROAM_EVENT: roam event triggering the host roam logic. + * generated when ever a better AP is found in the recent roam scan (or) + * when beacon miss is detected (or) when a DEAUTH/DISASSOC is received + * from the current AP. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** reason for roam event */ + A_UINT32 reason; + /** associated AP's rssi calculated by FW when reason code is WMI_ROAM_REASON_LOW_RSSI*/ + A_UINT32 rssi; + +} wmi_roam_event_fixed_param; + +/* roam_reason: bits 0-3 */ +#define WMI_ROAM_REASON_BETTER_AP 0x1 /** found a better AP */ +#define WMI_ROAM_REASON_BMISS 0x2 /** beacon miss detected */ +#define WMI_ROAM_REASON_DEAUTH 0x2 /** deauth/disassoc received */ +#define WMI_ROAM_REASON_LOW_RSSI 0x3 /** connected AP's low rssi condition detected */ +#define WMI_ROAM_REASON_SUITABLE_AP 0x4 /** found another AP that matches + SSID and Security profile in + WMI_ROAM_AP_PROFILE, found during scan + triggered upon FINAL_BMISS **/ +#define WMI_ROAM_REASON_HO_FAILED 0x5 /** LFR3.0 roaming failed, indicate the disconnection to host */ +/* reserved up through 0xF */ + +/* subnet status: bits 4-5 */ +typedef enum { + WMI_ROAM_SUBNET_CHANGE_STATUS_UNKNOWN = 0, + WMI_ROAM_SUBNET_CHANGE_STATUS_UNCHANGED, + WMI_ROAM_SUBNET_CHANGE_STATUS_CHANGED, +} wmi_roam_subnet_change_status; + +#define WMI_ROAM_SUBNET_CHANGE_STATUS_MASK 0x30 +#define WMI_ROAM_SUBNET_CHANGE_STATUS_SHIFT 4 + +#define WMI_SET_ROAM_SUBNET_CHANGE_STATUS(roam_reason, status) \ + do { \ + (roam_reason) |= \ + (((status) << WMI_ROAM_SUBNET_CHANGE_STATUS_SHIFT) & \ + WMI_ROAM_SUBNET_CHANGE_STATUS_MASK); \ + } while (0) + +#define WMI_GET_ROAM_SUBNET_CHANGE_STATUS(roam_reason) \ + (((roam_reason) & WMI_ROAM_SUBNET_CHANGE_STATUS_MASK) >> \ + WMI_ROAM_SUBNET_CHANGE_STATUS_SHIFT) + +/**whenever RIC request information change, host driver should pass all ric related information to firmware (now only support tsepc) +* Once, 11r roaming happens, firmware can generate RIC request in reassoc request based on these informations +*/ +typedef struct +{ + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ric_request_fixed_param */ + A_UINT32 vdev_id; /**unique id identifying the VDEV, generated by the caller*/ + A_UINT32 num_ric_request; /**number of ric request ie send to firmware.(max value is 2 now)*/ + A_UINT32 is_add_ric; /**support add ric or delete ric*/ +}wmi_ric_request_fixed_param; + +/**tspec element: refer to 8.4.2.32 of 802.11 2012 spec +* these elements are used to construct tspec field in RIC request, which allow station to require specific TS when 11r roaming +*/ +typedef struct{ + A_UINT32 tlv_header; + A_UINT32 ts_info; /** bits value of TS Info field.*/ + A_UINT32 nominal_msdu_size; /**Nominal MSDU Size field*/ + A_UINT32 maximum_msdu_size; /**The Maximum MSDU Size field*/ + A_UINT32 min_service_interval; /**The Minimum Service Interval field*/ + A_UINT32 max_service_interval; /**The Maximum Service Interval field*/ + A_UINT32 inactivity_interval; /**The Inactivity Interval field*/ + A_UINT32 suspension_interval; /**The Suspension Interval field*/ + A_UINT32 svc_start_time; /**The Service Start Time field*/ + A_UINT32 min_data_rate; /**The Minimum Data Rate field*/ + A_UINT32 mean_data_rate; /**The Mean Data Rate field*/ + A_UINT32 peak_data_rate; /**The Peak Data Rate field*/ + A_UINT32 max_burst_size; /**The Burst Size field*/ + A_UINT32 delay_bound; /**The Delay Bound field*/ + A_UINT32 min_phy_rate; /**The Minimum PHY Rate field*/ + A_UINT32 surplus_bw_allowance; /**The Surplus Bandwidth Allowance field*/ + A_UINT32 medium_time; /**The Medium Time field,in units of 32 us/s.*/ +} wmi_ric_tspec; + +/* flags for roam_invoke_cmd */ +/* add this channel into roam cache channel list after this command is finished */ +#define WMI_ROAM_INVOKE_FLAG_ADD_CH_TO_CACHE 0 +/* from bit 1 to bit 31 are reserved */ + +#define WMI_SET_ROAM_INVOKE_ADD_CH_TO_CACHE(flag) do { \ + (flag) |= (1 << WMI_SET_ROAM_INVOKE_ADD_CH_TO_CACHE); \ + } while(0) + +#define WMI_CLEAR_ROAM_INVOKE_ADD_CH_TO_CACHE(flag) do { \ + (flag) &= ~(1 << WMI_SET_ROAM_INVOKE_ADD_CH_TO_CACHE); \ + } while(0) + +#define WMI_GET_ROAM_INVOKE_ADD_CH_TO_CACHE(flag) \ + ((flag) & (1 << WMI_SET_ROAM_INVOKE_ADD_CH_TO_CACHE)) + + +#define WMI_ROAM_INVOKE_SCAN_MODE_FIXED_CH 0 /* scan given channel only */ +#define WMI_ROAM_INVOKE_SCAN_MODE_CACHE_LIST 1 /* scan cached channel list */ +#define WMI_ROAM_INVOKE_SCAN_MODE_FULL_CH 2 /* scan full channel */ + +#define WMI_ROAM_INVOKE_AP_SEL_FIXED_BSSID 0 /* roam to given BSSID only */ +#define WMI_ROAM_INVOKE_AP_SEL_ANY_BSSID 1 /* roam to any BSSID */ + +/** WMI_ROAM_INVOKE_CMD: command to invoke roaming forcefully + * + * if is zero and is not given, roaming is not executed. + * if is zero and = 0 + * = 0 + * = 0 + * |= WMI_ROAM_INVOKE_FLAG_ADD_CH_TO_CACHE + * = do not fill (there will be no actual roaming because of ap_sel_mode is zero, but no BSSID is given) + * = channel list to be added + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_invoke_fixed_param */ + A_UINT32 vdev_id; /** Unique id identifying the VDEV on which roaming is invoked */ + A_UINT32 flags; /** flags. see WMI_ROAM_INVOKE_FLAG_ above */ + A_UINT32 roam_scan_mode; /** see WMI_ROAM_INVOKE_SCAN_ above */ + A_UINT32 roam_ap_sel_mode; /** see WMI_ROAM_INVOKE_AP_SEL_ above */ + A_UINT32 roam_delay; /** 0 = immediate roam, 1-2^32 = roam after this delay (msec) */ + A_UINT32 num_chan; /** # if channels to scan. In the TLV channel_list[] */ + A_UINT32 num_bssid; /** number of bssids. In the TLV bssid_list[] */ + /** + * TLV (tag length value ) parameters follows roam_invoke_req + * The TLV's are: + * A_UINT32 channel_list[]; + * wmi_mac_addr bssid_list[]; + */ +} wmi_roam_invoke_cmd_fixed_param; + +/* Definition for op_bitmap */ +enum { + ROAM_FILTER_OP_BITMAP_BLACK_LIST = 0x1, + ROAM_FILTER_OP_BITMAP_WHITE_LIST = 0x2, + ROAM_FILTER_OP_BITMAP_PREFER_BSSID = 0x4, +}; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_filter_list_fixed_param */ + A_UINT32 vdev_id; /** Unique id identifying the VDEV on which roaming filter is adopted */ + A_UINT32 flags; /** flags for filter */ + A_UINT32 op_bitmap; /** 32 bit bitmap to be set on. bit0 = first param, bit 1 = second param...etc. Can be or'ed */ + A_UINT32 num_bssid_black_list; /* number of blacklist in the TLV variable bssid_black_list */ + A_UINT32 num_ssid_white_list; /* number of whitelist in the TLV variable ssid_white_list */ + A_UINT32 num_bssid_preferred_list; /* only for lfr 3.0. number of preferred list & factor in the TLV */ + /** + * TLV (tag length value ) parameters follows roam_filter_list_cmd + * The TLV's are: + * wmi_mac_addr bssid_black_list[]; + * wmi_ssid ssid_white_list[]; + * wmi_mac_addr bssid_preferred_list[]; + * A_UINT32 bssid_preferred_factor[]; + */ +} wmi_roam_filter_fixed_param; + +typedef struct { + A_UINT8 address[4]; /* IPV4 address in Network Byte Order */ +} WMI_IPV4_ADDR; + +typedef struct _WMI_IPV6_ADDR { + A_UINT8 address[16]; /* IPV6 in Network Byte Order */ +} WMI_IPV6_ADDR; + +/* flags for subnet change detection */ +#define WMI_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED 0 +#define WMI_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED 1 +/* bit 2 to bit 31 are reserved */ + +/* set IPv4 enabled/disabled flag and get the flag */ +#define WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED(flag) do { \ + (flag) |= (1 << WMI_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED); \ +} while (0) + +#define WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP4_DISABLED(flag) do { \ + (flag) &= ~(1 << WMI_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED); \ +} while (0) + +#define WMI_GET_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED(flag) \ + ((flag) & (1 << WMI_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED)) + +/* set IPv6 enabled flag, disabled and get the flag */ +#define WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED(flag) do { \ + (flag) |= (1 << WMI_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED); \ +} while (0) + +#define WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP6_DISABLED(flag) do { \ + (flag) &= ~(1 << WMI_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED); \ +} while (0) + +#define WMI_GET_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED(flag) \ + ((flag) & (1 << WMI_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED)) + +/** + * WMI_ROAM_SUBNET_CHANGE_CONFIG : Pass the gateway IP and MAC addresses + * to FW. FW uses these parameters for subnet change detection. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals +WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** IPv4/IPv6 enabled/disabled */ + /** This flag sets the WMI_SET_ROAM_SUBNET_CHANGE_FLAG_xxx_ENABLED/ +DISABLED */ + A_UINT32 flag; + /** Gateway MAC address */ + wmi_mac_addr inet_gw_mac_addr; + /** IP addresses */ + WMI_IPV4_ADDR inet_gw_ip_v4_addr; + WMI_IPV6_ADDR inet_gw_ip_v6_addr; + /** Number of software retries for ARP/Neighbor solicitation request */ + A_UINT32 max_retries; + /** timeout in milliseconds for each ARP request*/ + A_UINT32 timeout; + /** number of skipped aps **/ + A_UINT32 num_skip_subnet_change_detection_bssid_list; +/** + * TLV (tag length value ) parameters follows roam_subnet_change_config_cmd + * structure. The TLV's are: + * wmi_mac_addr skip_subnet_change_detection_bssid_list []; + **/ +} wmi_roam_subnet_change_config_fixed_param; + +/** WMI_PROFILE_MATCH_EVENT: offload scan + * generated when ever atleast one of the matching profiles is found + * in recent NLO scan. no data is carried with the event. + */ + +/** P2P specific commands */ + +/** + * WMI_P2P_DEV_SET_DEVICE_INFO : p2p device info, which will be used by + * FW to generate P2P IE tobe carried in probe response frames. + * FW will respond to probe requests while in listen state. + */ +typedef struct { + /* number of secondary device types,supported */ + A_UINT32 num_secondary_dev_types; + /** + * followed by 8 bytes of primary device id and + * num_secondary_dev_types * 8 bytes of secondary device + * id. + */ +} wmi_p2p_dev_set_device_info; + +/** WMI_P2P_DEV_SET_DISCOVERABILITY: enable/disable discoverability + * state. if enabled, an active STA/AP will respond to P2P probe requests on + * the operating channel of the VDEV. + */ + +typedef struct { + /* 1:enable disoverability, 0:disable discoverability */ + A_UINT32 enable_discoverability; +} wmi_p2p_set_discoverability; + +/** WMI_P2P_GO_SET_BEACON_IE: P2P IE to be added to + * beacons generated by FW. used in FW beacon mode. + * the FW will add this IE to beacon in addition to the beacon + * template set by WMI_BCN_TMPL_CMDID command. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_go_set_beacon_ie_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* ie length */ + A_UINT32 ie_buf_len; + /* Following this structure is the TLV byte stream of ie data of length ie_buf_len: + * A_UINT8 ie_data[]; // length in byte given by field num_data. + */ + +} wmi_p2p_go_set_beacon_ie_fixed_param; + +/** WMI_P2P_GO_PROBE_RESP_IE: P2P IE to be added to + * probe response generated by FW. used in FW beacon mode. + * the FW will add this IE to probe response in addition to the probe response + * template set by WMI_PRB_TMPL_CMDID command. + */ +typedef struct { + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* ie length */ + A_UINT32 ie_buf_len; + /*followed by byte stream of ie data of length ie_buf_len */ +} wmi_p2p_go_set_probe_resp_ie; + +/** WMI_P2P_SET_VENDOR_IE_DATA_CMDID: Vendor specific P2P IE data, which will + * be used by the FW to parse the P2P NoA attribute in beacons, probe resposes + * and action frames received by the P2P Client. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_set_vendor_ie_data_cmd_fixed_param */ + /** OS specific P2P IE OUI (3 bytes) + OUI type (1 byte) */ + A_UINT32 p2p_ie_oui_type; + /** OS specific NoA Attribute ID */ + A_UINT32 p2p_noa_attribute; +} wmi_p2p_set_vendor_ie_data_cmd_fixed_param; + +/*----P2P disc offload definition ----*/ + +typedef struct { + A_UINT32 pattern_type; + /** + * TLV (tag length value ) paramerters follow the pattern structure. + * TLV can contain bssid list, ssid list and + * ie. the TLV tags are defined above; + */ +}wmi_p2p_disc_offload_pattern_cmd; + +typedef struct { + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* mgmt type of the ie*/ + A_UINT32 mgmt_type; + /* ie length */ + A_UINT32 ie_buf_len; + /*followed by byte stream of ie data of length ie_buf_len */ +}wmi_p2p_disc_offload_appie_cmd; + +typedef struct { + /* enable/disable p2p find offload*/ + A_UINT32 enable; + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* p2p find type */ + A_UINT32 disc_type; + /* p2p find perodic */ + A_UINT32 perodic; + /* p2p find listen channel */ + A_UINT32 listen_channel; + /* p2p find full channel number */ + A_UINT32 num_scan_chans; + /** + * TLV (tag length value ) paramerters follow the pattern structure. + * TLV contain channel list + */ +}wmi_p2p_disc_offload_config_cmd; + +/*----P2P OppPS definition ----*/ +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_set_oppps_cmd_fixed_param */ + A_UINT32 tlv_header; + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* OppPS attributes */ + /** Bit 0: Indicate enable/disable of OppPS + * Bits 7-1: Ctwindow in TUs + * Bits 31-8: Reserved + */ + A_UINT32 oppps_attr; +} wmi_p2p_set_oppps_cmd_fixed_param; + +#define WMI_UNIFIED_OPPPS_ATTR_ENALBED 0x1 +#define WMI_UNIFIED_OPPPS_ATTR_ENALBED_S 0 + +#define WMI_UNIFIED_OPPPS_ATTR_IS_ENABLED(hdr) \ + WMI_F_MS((hdr)->oppps_attr, WMI_UNIFIED_OPPPS_ATTR_ENALBED) + +#define WMI_UNIFIED_OPPPS_ATTR_ENABLED_SET(hdr) \ + WMI_F_RMW((hdr)->oppps_attr, 0x1, \ + WMI_UNIFIED_OPPPS_ATTR_ENALBED); + +#define WMI_UNIFIED_OPPPS_ATTR_CTWIN 0xfe +#define WMI_UNIFIED_OPPPS_ATTR_CTWIN_S 1 + +#define WMI_UNIFIED_OPPPS_ATTR_CTWIN_GET(hdr) \ + WMI_F_MS((hdr)->oppps_attr, WMI_UNIFIED_OPPPS_ATTR_CTWIN) + +#define WMI_UNIFIED_OPPPS_ATTR_CTWIN_SET(hdr, v) \ + WMI_F_RMW((hdr)->oppps_attr, (v) & 0x7f, \ + WMI_UNIFIED_OPPPS_ATTR_CTWIN); + +typedef struct { + A_UINT32 time32; //upper 32 bits of time stamp + A_UINT32 time0; //lower 32 bits of time stamp +} A_TIME64; + +typedef enum wmi_peer_sta_kickout_reason { + WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED = 0, /* default value to preserve legacy behavior */ + WMI_PEER_STA_KICKOUT_REASON_XRETRY = 1, + WMI_PEER_STA_KICKOUT_REASON_INACTIVITY = 2, + WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT = 3, + WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT = 4, /* TDLS peer has disappeared. All tx is failing */ + WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT = 5, +} PEER_KICKOUT_REASON; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_sta_kickout_event_fixed_param */ + /** peer mac address */ + wmi_mac_addr peer_macaddr; + /** Reason code, defined as above */ + A_UINT32 reason; + /** RSSI of the last bcn (averaged) in dB. 0 means Noise Floor value */ + A_UINT32 rssi; +} wmi_peer_sta_kickout_event_fixed_param; + +#define WMI_WLAN_PROFILE_MAX_HIST 3 +#define WMI_WLAN_PROFILE_MAX_BIN_CNT 32 + +typedef struct _wmi_wlan_profile_t { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wlan_profile_t */ + A_UINT32 id; + A_UINT32 cnt; + A_UINT32 tot; + A_UINT32 min; + A_UINT32 max; + A_UINT32 hist_intvl; + A_UINT32 hist[WMI_WLAN_PROFILE_MAX_HIST]; +} wmi_wlan_profile_t; + +typedef struct _wmi_wlan_profile_ctx_t { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wlan_profile_ctx_t */ + A_UINT32 tot; /* time in us */ + A_UINT32 tx_msdu_cnt; + A_UINT32 tx_mpdu_cnt; + A_UINT32 tx_ppdu_cnt; + A_UINT32 rx_msdu_cnt; + A_UINT32 rx_mpdu_cnt; + A_UINT32 bin_count; +} wmi_wlan_profile_ctx_t; + + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param */ + A_UINT32 enable; +} wmi_wlan_profile_trigger_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param */ + A_UINT32 value; +} wmi_wlan_profile_get_prof_data_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param */ + A_UINT32 profile_id; + A_UINT32 value; +} wmi_wlan_profile_set_hist_intvl_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param */ + A_UINT32 profile_id; + A_UINT32 enable; +} wmi_wlan_profile_enable_profile_id_cmd_fixed_param; + +/*Wifi header is upto 26, LLC is 8, with 14 byte duplicate in 802.3 header, that's 26+8-14=20. +146-128=18. So this means it is converted to non-QoS header. Riva FW take care of the QOS/non-QOS +when comparing wifi header.*/ +/* NOTE: WOW_DEFAULT_BITMAP_PATTERN_SIZE(_DWORD) and WOW_DEFAULT_BITMASK_SIZE(_DWORD) can't be changed without breaking the compatibility */ +#define WOW_DEFAULT_BITMAP_PATTERN_SIZE 146 +#define WOW_DEFAULT_BITMAP_PATTERN_SIZE_DWORD 37 //Convert WOW_DEFAULT_EVT_BUF_SIZE into Int32 size +#define WOW_DEFAULT_BITMASK_SIZE 146 +#define WOW_DEFAULT_BITMASK_SIZE_DWORD 37 +#define WOW_MAX_BITMAP_FILTERS 32 +#define WOW_DEFAULT_MAGIG_PATTERN_MATCH_CNT 16 +#define WOW_EXTEND_PATTERN_MATCH_CNT 16 +#define WOW_SHORT_PATTERN_MATCH_CNT 8 +#define WOW_DEFAULT_EVT_BUF_SIZE 148 /* Maximum 148 bytes of the data is copied starting from header incase if the match is found. + The 148 comes from (128 - 14 ) payload size + 8bytes LLC + 26bytes MAC header*/ +#define WOW_DEFAULT_IOAC_PATTERN_SIZE 6 +#define WOW_DEFAULT_IOAC_PATTERN_SIZE_DWORD 2 +#define WOW_DEFAULT_IOAC_RANDOM_SIZE 6 +#define WOW_DEFAULT_IOAC_RANDOM_SIZE_DWORD 2 +#define WOW_DEFAULT_IOAC_KEEP_ALIVE_PKT_SIZE 120 +#define WOW_DEFAULT_IOAC_KEEP_ALIVE_PKT_SIZE_DWORD 30 +#define WOW_DEFAULT_IOAC_SOCKET_PATTERN_SIZE 32 +#define WOW_DEFAULT_IOAC_SOCKET_PATTERN_SIZE_DWORD 8 +#define WOW_DEFAULT_IOAC_KEEP_ALIVE_PKT_REV_SIZE 32 +#define WOW_DEFAULT_IOAC_KEEP_ALIVE_PKT_REV_SIZE_DWORD 8 +#define WOW_DEFAULT_IOAC_SOCKET_PATTERN_ACKNAK_SIZE 128 +#define WOW_DEFAULT_IOAC_SOCKET_PATTERN_ACKNAK_SIZE_DWORD 32 + +typedef enum pattern_type_e { + WOW_PATTERN_MIN = 0, + WOW_BITMAP_PATTERN = WOW_PATTERN_MIN, + WOW_IPV4_SYNC_PATTERN, + WOW_IPV6_SYNC_PATTERN, + WOW_WILD_CARD_PATTERN, + WOW_TIMER_PATTERN, + WOW_MAGIC_PATTERN, + WOW_IPV6_RA_PATTERN, + WOW_IOAC_PKT_PATTERN, + WOW_IOAC_TMR_PATTERN, + WOW_IOAC_SOCK_PATTERN, + WOW_PATTERN_MAX +}WOW_PATTERN_TYPE; + +typedef enum event_type_e { + WOW_BMISS_EVENT = 0, + WOW_BETTER_AP_EVENT, + WOW_DEAUTH_RECVD_EVENT, + WOW_MAGIC_PKT_RECVD_EVENT, + WOW_GTK_ERR_EVENT, + WOW_FOURWAY_HSHAKE_EVENT, + WOW_EAPOL_RECVD_EVENT, + WOW_NLO_DETECTED_EVENT, + WOW_DISASSOC_RECVD_EVENT, + WOW_PATTERN_MATCH_EVENT, + WOW_CSA_IE_EVENT, + WOW_PROBE_REQ_WPS_IE_EVENT, + WOW_AUTH_REQ_EVENT, + WOW_ASSOC_REQ_EVENT, + WOW_HTT_EVENT, + WOW_RA_MATCH_EVENT, + WOW_HOST_AUTO_SHUTDOWN_EVENT, + WOW_IOAC_MAGIC_EVENT, + WOW_IOAC_SHORT_EVENT, + WOW_IOAC_EXTEND_EVENT, + WOW_IOAC_TIMER_EVENT, + WOW_DFS_PHYERR_RADAR_EVENT, + WOW_BEACON_EVENT, + WOW_CLIENT_KICKOUT_EVENT, + WOW_NAN_EVENT, + WOW_EXTSCAN_EVENT, + WOW_IOAC_REV_KA_FAIL_EVENT, + WOW_IOAC_SOCK_EVENT, + WOW_NLO_SCAN_COMPLETE_EVENT, +} WOW_WAKE_EVENT_TYPE; + +typedef enum wake_reason_e { + WOW_REASON_UNSPECIFIED =-1, + WOW_REASON_NLOD = 0, + WOW_REASON_AP_ASSOC_LOST, + WOW_REASON_LOW_RSSI, + WOW_REASON_DEAUTH_RECVD, + WOW_REASON_DISASSOC_RECVD, + WOW_REASON_GTK_HS_ERR, + WOW_REASON_EAP_REQ, + WOW_REASON_FOURWAY_HS_RECV, + WOW_REASON_TIMER_INTR_RECV, + WOW_REASON_PATTERN_MATCH_FOUND, + WOW_REASON_RECV_MAGIC_PATTERN, + WOW_REASON_P2P_DISC, + WOW_REASON_WLAN_HB, + WOW_REASON_CSA_EVENT, + WOW_REASON_PROBE_REQ_WPS_IE_RECV, + WOW_REASON_AUTH_REQ_RECV, + WOW_REASON_ASSOC_REQ_RECV, + WOW_REASON_HTT_EVENT, + WOW_REASON_RA_MATCH, + WOW_REASON_HOST_AUTO_SHUTDOWN, + WOW_REASON_IOAC_MAGIC_EVENT, + WOW_REASON_IOAC_SHORT_EVENT, + WOW_REASON_IOAC_EXTEND_EVENT, + WOW_REASON_IOAC_TIMER_EVENT, + WOW_REASON_ROAM_HO, + WOW_REASON_DFS_PHYERR_RADADR_EVENT, + WOW_REASON_BEACON_RECV, + WOW_REASON_CLIENT_KICKOUT_EVENT, + WOW_REASON_NAN_EVENT, + WOW_REASON_EXTSCAN, + WOW_REASON_RSSI_BREACH_EVENT, + WOW_REASON_IOAC_REV_KA_FAIL_EVENT, + WOW_REASON_IOAC_SOCK_EVENT, + WOW_REASON_NLO_SCAN_COMPLETE, + WOW_REASON_PACKET_FILTER_MATCH, + WOW_REASON_ASSOC_RES_RECV, + WOW_REASON_REASSOC_REQ_RECV, + WOW_REASON_REASSOC_RES_RECV, + WOW_REASON_ACTION_FRAME_RECV, + WOW_REASON_DEBUG_TEST = 0xFF, +} WOW_WAKE_REASON_TYPE; + +typedef enum { + WOW_IFACE_PAUSE_ENABLED, + WOW_IFACE_PAUSE_DISABLED +} WOW_IFACE_STATUS; + +enum { + /* some win10 platfrom will not assert pcie_reset for wow.*/ + WMI_WOW_FLAG_IGNORE_PCIE_RESET = 0x00000001, +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param */ + A_UINT32 enable; + A_UINT32 pause_iface_config; + A_UINT32 flags; /* WMI_WOW_FLAG enums */ +} wmi_wow_enable_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param */ + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_wow_hostwakeup_from_sleep_cmd_fixed_param; + +#define WOW_ICMPV6_NA_FILTER_DISABLE 0 +#define WOW_ICMPV6_NA_FILTER_ENABLE 1 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wow_enable_icmpv6_na_flt_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 enable; /* WOW_ICMPV6_NA_FILTER_ENABLE/DISABLE */ +} wmi_wow_enable_icmpv6_na_flt_cmd_fixed_param; + +typedef struct bitmap_pattern_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T */ + A_UINT32 patternbuf[WOW_DEFAULT_BITMAP_PATTERN_SIZE_DWORD]; + A_UINT32 bitmaskbuf[WOW_DEFAULT_BITMASK_SIZE_DWORD]; + A_UINT32 pattern_offset; + A_UINT32 pattern_len; + A_UINT32 bitmask_len; + A_UINT32 pattern_id; /* must be less than max_bitmap_filters */ +}WOW_BITMAP_PATTERN_T; + +typedef struct ipv4_sync_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T */ + A_UINT32 ipv4_src_addr; + A_UINT32 ipv4_dst_addr; + A_UINT32 tcp_src_prt; + A_UINT32 tcp_dst_prt; +}WOW_IPV4_SYNC_PATTERN_T; + +typedef struct ipv6_sync_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T */ + A_UINT32 ipv6_src_addr[4]; + A_UINT32 ipv6_dst_addr[4]; + A_UINT32 tcp_src_prt; + A_UINT32 tcp_dst_prt; +}WOW_IPV6_SYNC_PATTERN_T; + +typedef struct WOW_MAGIC_PATTERN_CMD +{ + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD */ + wmi_mac_addr macaddr; +}WOW_MAGIC_PATTERN_CMD; + +typedef enum wow_ioac_pattern_type { + WOW_IOAC_MAGIC_PATTERN = 1, + WOW_IOAC_SHORT_PATTERN, + WOW_IOAC_EXTEND_PATTERN, +} WOW_IOAC_PATTERN_TYPE; + +typedef struct ioac_sock_pattern_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_IOAC_SOCK_PATTERN_T */ + A_UINT32 id; + A_UINT32 local_ipv4; + A_UINT32 remote_ipv4; + A_UINT32 local_port; + A_UINT32 remote_port; + A_UINT32 pattern_len; /* units = bytes */ + A_UINT32 pattern[WOW_DEFAULT_IOAC_SOCKET_PATTERN_SIZE_DWORD]; + WMI_IPV6_ADDR local_ipv6; + WMI_IPV6_ADDR remote_ipv6; + A_UINT32 ack_nak_len; + A_UINT32 ackpkt[WOW_DEFAULT_IOAC_SOCKET_PATTERN_ACKNAK_SIZE_DWORD]; + A_UINT32 nakpkt[WOW_DEFAULT_IOAC_SOCKET_PATTERN_ACKNAK_SIZE_DWORD]; +} WOW_IOAC_SOCK_PATTERN_T; + +typedef struct ioac_pkt_pattern_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_IOAC_PKT_PATTERN_T */ + A_UINT32 pattern_type; + A_UINT32 pattern[WOW_DEFAULT_IOAC_PATTERN_SIZE_DWORD]; + A_UINT32 random[WOW_DEFAULT_IOAC_RANDOM_SIZE_DWORD]; + A_UINT32 pattern_len; + A_UINT32 random_len; +} WOW_IOAC_PKT_PATTERN_T; + +typedef struct ioac_tmr_pattern_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_IOAC_TMR_PATTERN_T */ + A_UINT32 wake_in_s; + A_UINT32 vdev_id; +} WOW_IOAC_TMR_PATTERN_T; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_IOAC_ADD_KEEPALIVE_CMD_fixed_param */ + A_UINT32 nID; +} WMI_WOW_IOAC_ADD_KEEPALIVE_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_IOAC_DEL_KEEPALIVE_CMD_fixed_param */ + A_UINT32 nID; +} WMI_WOW_IOAC_DEL_KEEPALIVE_CMD_fixed_param; + +typedef struct ioac_keepalive_s { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_IOAC_KEEPALIVE_T */ + A_UINT32 keepalive_pkt_buf[WOW_DEFAULT_IOAC_KEEP_ALIVE_PKT_SIZE_DWORD]; + A_UINT32 keepalive_pkt_len; + A_UINT32 period_in_ms; + A_UINT32 vdev_id; + A_UINT32 max_loss_cnt; + A_UINT32 local_ipv4; + A_UINT32 remote_ipv4; + A_UINT32 local_port; + A_UINT32 remote_port; + A_UINT32 recv_period_in_ms; + A_UINT32 rev_ka_size; + A_UINT32 rev_ka_data[WOW_DEFAULT_IOAC_KEEP_ALIVE_PKT_REV_SIZE_DWORD]; + WMI_IPV6_ADDR local_ipv6; + WMI_IPV6_ADDR remote_ipv6; +} WMI_WOW_IOAC_KEEPALIVE_T; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_IOAC_ADD_PATTERN_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 pattern_type; +/* + * Following this struct are these TLVs. Note that they are all array of structures + * but can have at most one element. Which TLV is empty or has one element depends + * on the field pattern_type. This is to emulate an union. + * WOW_IOAC_PKT_PATTERN_T pattern_info_pkt[]; + * WOW_IOAC_TMR_PATTERN_T pattern_info_tmr[]; + */ +} WMI_WOW_IOAC_ADD_PATTERN_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_IOAC_DEL_PATTERN_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 pattern_type; + A_UINT32 pattern_id; +} WMI_WOW_IOAC_DEL_PATTERN_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 pattern_id; + A_UINT32 pattern_type; + /* + * Following this struct are these TLVs. Note that they are all array of structures + * but can have at most one element. Which TLV is empty or has one element depends + * on the field pattern_type. This is to emulate an union. + * WOW_BITMAP_PATTERN_T pattern_info_bitmap[]; + * WOW_IPV4_SYNC_PATTERN_T pattern_info_ipv4[]; + * WOW_IPV6_SYNC_PATTERN_T pattern_info_ipv6[]; + * WOW_MAGIC_PATTERN_CMD pattern_info_magic_pattern[]; + * A_UINT32 pattern_info_timeout[]; + * A_UINT32 ra_ratelimit_interval; + */ +}WMI_WOW_ADD_PATTERN_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 pattern_id; + A_UINT32 pattern_type; +}WMI_WOW_DEL_PATTERN_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 is_add; + A_UINT32 event_bitmap; +}WMI_WOW_ADD_DEL_EVT_CMD_fixed_param; + +/* + * This structure is used to set the pattern to check UDP packet in WOW mode. + * If match, construct a tx frame in a local buffer to send through the peer + * AP to the entity in the IP network that sent the UDP packet to this STA. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 enable; /* 1: enable, 0: disable*/ + /* dest_port - + * bits 7:0 contain the LSB of the UDP dest port, + * bits 15:8 contain the MSB of the UDP dest port + */ + A_UINT32 dest_port; + A_UINT32 pattern_len; /* length in byte of pattern[] */ + A_UINT32 response_len; /* length in byte of response[] */ +/* Following this struct are the TLV's: + * A_UINT8 pattern[]; // payload of UDP packet to be checked, network byte order + * A_UINT8 response[]; // payload of UDP packet to be response, network byte order + */ +} WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param; + +/* + * This structure is used to set the pattern for WOW host wakeup pin pulse + * pattern confirguration. + */ +typedef struct { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_WMI_WOW_HOSTWAKEUP_PIN_PATTERN_CONFIG_CMD_fixed_param + */ + A_UINT32 tlv_header; + A_UINT32 enable; // 1: enable, 0: disable + A_UINT32 pin; // pin for host wakeup + A_UINT32 interval_low; // interval for keeping low voltage, unit: ms + A_UINT32 interval_high; // interval for keeping high voltage, unit: ms + A_UINT32 repeat_cnt;// repeat times for pulse (0xffffffff means forever) +} WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMD_fixed_param; + +typedef struct wow_event_info_s { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_EVENT_INFO_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 flag; /*This is current reserved.*/ + A_INT32 wake_reason; + A_UINT32 data_len; +}WOW_EVENT_INFO_fixed_param; + +typedef struct wow_initial_wakeup_event_s { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WOW_INITIAL_WAKEUP_EVENT_fixed_param */ + A_UINT32 vdev_id; +} WOW_INITIAL_WAKEUP_EVENT_fixed_param; + +typedef enum { + WOW_EVENT_INFO_TYPE_PACKET = 0x0001, + WOW_EVENT_INFO_TYPE_BITMAP, + WOW_EVENT_INFO_TYPE_GTKIGTK, +}WOW_EVENT_INFO_TYPE; + +typedef struct wow_event_info_section_s { + A_UINT32 data_type; + A_UINT32 data_len; +}WOW_EVENT_INFO_SECTION; + +typedef struct wow_event_info_section_packet_s { + A_UINT8 packet[WOW_DEFAULT_EVT_BUF_SIZE]; +}WOW_EVENT_INFO_SECTION_PACKET; + +typedef struct wow_event_info_section_bitmap_s { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WOW_EVENT_INFO_SECTION_BITMAP */ + A_UINT32 flag; /*This is current reserved.*/ + A_UINT32 value; /*This could be the pattern id for bitmap pattern.*/ + A_UINT32 org_len; /*The length of the orginal packet.*/ +}WOW_EVENT_INFO_SECTION_BITMAP; + +/** + * This command is sent from WLAN host driver to firmware to + * enable or disable D0-WOW. D0-WOW means APSS suspend with + * PCIe link and DDR being active. + * + * + * Entering D0-WOW Mode (based on kernel suspend request): + * host->target: WMI_DO_WOW_ENABLE_DISABLE_CMDID (enable = 1) + * target: Take action (e.g. dbglog suspend) + * target->host: HTC_ACK (HTC_MSG_SEND_SUSPEND_COMPLETE message) + * + * Exiting D0-WOW mode (based on kernel resume OR target->host message received) + * host->target: WMI_DO_WOW_ENABLE_DISABLE_CMDID (enable = 0) + * target: Take action (e.g. dbglog resume) + * target->host: WMI_D0_WOW_DISABLE_ACK_EVENTID + * + * This command is applicable only on the PCIE LL systems + * Host can enter either D0-WOW or WOW mode, but NOT both at same time + * Decision to enter D0-WOW or WOW is based on active interfaces + * + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param */ + A_UINT32 enable; /* 1 = enable, 0 = disable */ +} wmi_d0_wow_enable_disable_cmd_fixed_param; + +typedef enum extend_wow_type_e { + EXTWOW_TYPE_APP_TYPE1, /* extend wow type: only enable wakeup for app type1 */ + EXTWOW_TYPE_APP_TYPE2, /* extend wow type: only enable wakeup for app type2 */ + EXTWOW_TYPE_APP_TYPE1_2, /* extend wow type: enable wakeup for app type1&2 */ + EXTWOW_DISABLED = 255, +} EXTWOW_TYPE; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals wmi_extwow_enable_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 type; + A_UINT32 wakeup_pin_num; +} wmi_extwow_enable_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals wmi_extwow_set_app_type1_params_cmd_fixed_param */ + A_UINT32 vdev_id; + wmi_mac_addr wakee_mac; + A_UINT8 ident[8]; + A_UINT8 passwd[16]; + A_UINT32 ident_len; + A_UINT32 passwd_len; +} wmi_extwow_set_app_type1_params_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals wmi_extwow_set_app_type2_params_cmd_fixed_param */ + A_UINT32 vdev_id; + + A_UINT8 rc4_key[16]; + A_UINT32 rc4_key_len; + + /** ip header parameter */ + A_UINT32 ip_id; /* NC id */ + A_UINT32 ip_device_ip; /* NC IP address */ + A_UINT32 ip_server_ip; /* Push server IP address */ + + /** tcp header parameter */ + A_UINT16 tcp_src_port; /* NC TCP port */ + A_UINT16 tcp_dst_port; /* Push server TCP port */ + A_UINT32 tcp_seq; + A_UINT32 tcp_ack_seq; + + A_UINT32 keepalive_init; /* Initial ping interval */ + A_UINT32 keepalive_min; /* Minimum ping interval */ + A_UINT32 keepalive_max; /* Maximum ping interval */ + A_UINT32 keepalive_inc; /* Increment of ping interval */ + + wmi_mac_addr gateway_mac; + A_UINT32 tcp_tx_timeout_val; + A_UINT32 tcp_rx_timeout_val; + + /** add extra parameter for backward-compatible */ + /* + * For all byte arrays, natural order is used. E.g. + * rc4_write_sandbox[0] holds the 1st RC4 S-box byte, + * rc4_write_sandbox[1] holds the 2nd RC4 S-box byte, etc. + */ + + /* used to encrypt transmit packet such as keep-alive */ + A_UINT8 rc4_write_sandbox[256]; + A_UINT32 rc4_write_x; + A_UINT32 rc4_write_y; + + /* used to decrypt received packet such as wow data */ + A_UINT8 rc4_read_sandbox[256]; + A_UINT32 rc4_read_x; + A_UINT32 rc4_read_y; + + /* used to caculate HMAC hash for transmit packet such as keep-alive */ + A_UINT8 ssl_write_seq[8]; + A_UINT8 ssl_sha1_write_key[64]; + A_UINT32 ssl_sha1_write_key_len; + + /* used to calculate HAMC hash for receive packet such as wow data */ + A_UINT8 ssl_read_seq[8]; + A_UINT8 ssl_sha1_read_key[64]; + A_UINT32 ssl_sha1_read_key_len; + + /* optional element for specifying TCP options data to include in + * transmit packets such as keep-alive + */ + A_UINT32 tcp_options_len; + A_UINT8 tcp_options[40]; + + A_UINT32 async_id; /* keep-alive request id */ +} wmi_extwow_set_app_type2_params_cmd_fixed_param; + + + +#define WMI_RXERR_CRC 0x01 /* CRC error on frame */ +#define WMI_RXERR_DECRYPT 0x08 /* non-Michael decrypt error */ +#define WMI_RXERR_MIC 0x10 /* Michael MIC decrypt error */ +#define WMI_RXERR_KEY_CACHE_MISS 0x20 /* No/incorrect key matter in h/w */ + +typedef enum { + PKT_PWR_SAVE_PAID_MATCH = 0x0001, + PKT_PWR_SAVE_GID_MATCH = 0x0002, + PKT_PWR_SAVE_EARLY_TIM_CLEAR = 0x0004, + PKT_PWR_SAVE_EARLY_DTIM_CLEAR = 0x0008, + PKT_PWR_SAVE_EOF_PAD_DELIM = 0x0010, + PKT_PWR_SAVE_MACADDR_MISMATCH = 0x0020, + PKT_PWR_SAVE_DELIM_CRC_FAIL = 0x0040, + PKT_PWR_SAVE_GID_NSTS_ZERO = 0x0080, + PKT_PWR_SAVE_RSSI_CHECK = 0x0100, + PKT_PWR_SAVE_5G_EBT = 0x0200, + PKT_PWR_SAVE_2G_EBT = 0x0400, + WMI_PKT_PWR_SAVE_MAX = 0x0800, +} WMI_PKT_PWR_SAVE_TYPE; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ftm_intg_cmd_fixed_param */ + A_UINT32 num_data; /** length in byte of data[]. */ + /* This structure is used to send Factory Test Mode [FTM] command + * from host to firmware for integrated chips which are binary blobs. + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field num_data. + */ +}wmi_ftm_intg_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ftm_intg_event_fixed_param */ + A_UINT32 num_data; /** length in byte of data[]. */ + /* This structure is used to receive Factory Test Mode [FTM] event + * from firmware to host for integrated chips which are binary blobs. + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field num_data. + */ +}wmi_ftm_intg_event_fixed_param; + +#define WMI_MAX_NS_OFFLOADS 2 +#define WMI_MAX_ARP_OFFLOADS 2 + +#define WMI_ARPOFF_FLAGS_VALID (1 << 0) /* the tuple entry is valid */ +#define WMI_ARPOFF_FLAGS_MAC_VALID (1 << 1) /* the target mac address is valid */ +#define WMI_ARPOFF_FLAGS_REMOTE_IP_VALID (1 << 2) /* remote IP field is valid */ + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE */ + A_UINT32 flags; /* flags */ + A_UINT8 target_ipaddr[4]; /* IPV4 addresses of the local node*/ + A_UINT8 remote_ipaddr[4]; /* source address of the remote node requesting the ARP (qualifier) */ + wmi_mac_addr target_mac; /* mac address for this tuple, if not valid, the local MAC is used */ +} WMI_ARP_OFFLOAD_TUPLE; + +#define WMI_NSOFF_FLAGS_VALID (1 << 0) /* the tuple entry is valid */ +#define WMI_NSOFF_FLAGS_MAC_VALID (1 << 1) /* the target mac address is valid */ +#define WMI_NSOFF_FLAGS_REMOTE_IP_VALID (1 << 2) /* remote IP field is valid */ + +#define WMI_NSOFF_MAX_TARGET_IPS 2 + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE */ + A_UINT32 flags; /* flags */ + /* NOTE: This size of array target_ipaddr[] cannot be changed without breaking WMI compatibility. */ + WMI_IPV6_ADDR target_ipaddr[WMI_NSOFF_MAX_TARGET_IPS]; /* IPV6 target addresses of the local node */ + WMI_IPV6_ADDR solicitation_ipaddr; /* multi-cast source IP addresses for receiving solicitations */ + WMI_IPV6_ADDR remote_ipaddr; /* address of remote node requesting the solicitation (qualifier) */ + wmi_mac_addr target_mac; /* mac address for this tuple, if not valid, the local MAC is used */ +} WMI_NS_OFFLOAD_TUPLE; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param */ + A_UINT32 flags; + A_UINT32 vdev_id; + A_UINT32 num_ns_ext_tuples; + /* Following this structure are the TLVs: + * WMI_NS_OFFLOAD_TUPLE ns_tuples[WMI_MAX_NS_OFFLOADS]; + * WMI_ARP_OFFLOAD_TUPLE arp_tuples[WMI_MAX_ARP_OFFLOADS]; + * WMI_NS_OFFLOAD_TUPLE ns_ext_tuples[]; //size based on num_ns_ext_tuples + */ +} WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 pattern_id; + A_UINT32 timeout; + A_UINT32 length; + /* Following this would be the pattern + A_UINT8 pattern[] of length specifed by length + field in the structure. */ +} WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 pattern_id; +} WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_tid_addba_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** Initiator (1) or Responder (0) for this aggregation */ + A_UINT32 initiator; + /** size of the negotiated window */ + A_UINT32 window_size; + /** starting sequence number (only valid for initiator) */ + A_UINT32 ssn; + /** timeout field represents the time to wait for Block Ack in + * initiator case and the time to wait for BAR in responder + * case. 0 represents no timeout. */ + A_UINT32 timeout; + /* BA policy: immediate ACK (0) or delayed ACK (1) */ + A_UINT32 policy; +} wmi_peer_tid_addba_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_tid_delba_cmd */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** Initiator (1) or Responder (0) for this aggregation */ + A_UINT32 initiator; +} wmi_peer_tid_delba_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tx_addba_complete_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** Event status */ + A_UINT32 status; +} wmi_tx_addba_complete_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tx_delba_complete_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** Tid number */ + A_UINT32 tid; + /** Event status */ + A_UINT32 status; +} wmi_tx_delba_complete_event_fixed_param; +/* + * Structure to request sequence numbers for a given + * peer station on different TIDs. The TIDs are + * indicated in the tidBitMap, tid 0 would + * be represented by LSB bit 0. tid 1 would be + * represented by LSB bit 1 etc. + * The target will retrieve the current sequence + * numbers for the peer on all the TIDs requested + * and send back a response in a WMI event. + */ +typedef struct +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals + WMITLV_TAG_STRUC_wmi_ba_req_ssn_cmd_sub_struct_param */ + wmi_mac_addr peer_macaddr; + A_UINT32 tidBitmap; +} wmi_ba_req_ssn; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals + WMITLV_TAG_STRUC_wmi_ba_req_ssn_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** Number of requested SSN In the TLV wmi_ba_req_ssn[] */ + A_UINT32 num_ba_req_ssn; +/* Following this struc are the TLV's: + * wmi_ba_req_ssn ba_req_ssn_list; All peer and tidBitMap for which the ssn is requested + */ +} wmi_ba_req_ssn_cmd_fixed_param; + +/* + * Max transmit categories + * + * Note: In future if we need to increase WMI_MAX_TC definition + * It would break the compatibility for WMI_BA_RSP_SSN_EVENTID. + */ +#define WMI_MAX_TC 8 + +/* + * Structure to send response sequence numbers + * for a give peer and tidmap. + */ +typedef struct +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals + WMITLV_TAG_STRUC_wmi_ba_req_ssn_event_sub_struct_param */ + wmi_mac_addr peer_macaddr; + /* A boolean to indicate if ssn is present */ + A_UINT32 ssn_present_for_tid[WMI_MAX_TC]; + /* The ssn from target, valid only if + * ssn_present_for_tid[tidn] equals 1 + */ + A_UINT32 ssn_for_tid[WMI_MAX_TC]; +} wmi_ba_event_ssn; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals + WMITLV_TAG_STRUC_wmi_ba_rsp_ssn_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** Event status, success or failure of the overall operation */ + A_UINT32 status; + /** Number of requested SSN In the TLV wmi_ba_req_ssn[] */ + A_UINT32 num_ba_event_ssn; +/* Following this struc are the TLV's: + * wmi_ba_event_ssn ba_event_ssn_list; All peer and tidBitMap for which the ssn is requested + */ +} wmi_ba_rsp_ssn_event_fixed_param; + + +enum wmi_aggr_state_req_type { + WMI_DISABLE_AGGREGATION, + WMI_ENABLE_AGGREGATION +}; + +/* + * This event is generated by the COEX module + * when esco call is begins the coex module in fw genrated this event to host to + * disable the RX aggregation and after completion of the esco call fw will indicate to + * enable back the Rx aggregation . +*/ + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_aggr_state_trig_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** req_type contains values from enum + * wmi_aggr_state_req_type; 0 (disable) 1(enable) */ + A_UINT32 req_type; +}wmi_aggr_state_trig_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_install_key_complete_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** MAC address used for installing */ + wmi_mac_addr peer_macaddr; + /** key index */ + A_UINT32 key_ix; + /** key flags */ + A_UINT32 key_flags; + /** Event status */ + A_UINT32 status; +} wmi_vdev_install_key_complete_event_fixed_param; + +typedef enum _WMI_NLO_AUTH_ALGORITHM { + WMI_NLO_AUTH_ALGO_80211_OPEN = 1, + WMI_NLO_AUTH_ALGO_80211_SHARED_KEY = 2, + WMI_NLO_AUTH_ALGO_WPA = 3, + WMI_NLO_AUTH_ALGO_WPA_PSK = 4, + WMI_NLO_AUTH_ALGO_WPA_NONE = 5, + WMI_NLO_AUTH_ALGO_RSNA = 6, + WMI_NLO_AUTH_ALGO_RSNA_PSK = 7, +} WMI_NLO_AUTH_ALGORITHM; + +typedef enum _WMI_NLO_CIPHER_ALGORITHM { + WMI_NLO_CIPHER_ALGO_NONE = 0x00, + WMI_NLO_CIPHER_ALGO_WEP40 = 0x01, + WMI_NLO_CIPHER_ALGO_TKIP = 0x02, + WMI_NLO_CIPHER_ALGO_CCMP = 0x04, + WMI_NLO_CIPHER_ALGO_WEP104 = 0x05, + WMI_NLO_CIPHER_ALGO_BIP = 0x06, + WMI_NLO_CIPHER_ALGO_WPA_USE_GROUP = 0x100, + WMI_NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100, + WMI_NLO_CIPHER_ALGO_WEP = 0x101, +} WMI_NLO_CIPHER_ALGORITHM; + +/* SSID broadcast type passed in NLO params */ +typedef enum _WMI_NLO_SSID_BcastNwType +{ + WMI_NLO_BCAST_UNKNOWN = 0, + WMI_NLO_BCAST_NORMAL = 1, + WMI_NLO_BCAST_HIDDEN = 2, +} WMI_NLO_SSID_BcastNwType; + +#define WMI_NLO_MAX_SSIDS 16 +#define WMI_NLO_MAX_CHAN 48 + +#define WMI_NLO_CONFIG_STOP (0x1 << 0) +#define WMI_NLO_CONFIG_START (0x1 << 1) +#define WMI_NLO_CONFIG_RESET (0x1 << 2) +#define WMI_NLO_CONFIG_SLOW_SCAN (0x1 << 4) +#define WMI_NLO_CONFIG_FAST_SCAN (0x1 << 5) +#define WMI_NLO_CONFIG_SSID_HIDE_EN (0x1 << 6) +/* This bit is used to indicate if EPNO or supplicant PNO is enabled. Only one of them can be enabled at a given time */ +#define WMI_NLO_CONFIG_ENLO (0x1 << 7) +#define WMI_NLO_CONFIG_SCAN_PASSIVE (0x1 << 8) + +/* Whether directed scan needs to be performed (for hidden SSIDs) */ +#define WMI_ENLO_FLAG_DIRECTED_SCAN 1 +/* Whether PNO event shall be triggered if the network is found on A band */ +#define WMI_ENLO_FLAG_A_BAND 2 +/* Whether PNO event shall be triggered if the network is found on G band */ +#define WMI_ENLO_FLAG_G_BAND 4 +/* Whether strict matching is required (i.e. firmware shall not match on the entire SSID) */ +#define WMI_ENLO_FLAG_STRICT_MATCH 8 + +/* Code for matching the beacon AUTH IE - additional codes TBD */ +/* open */ +#define WMI_ENLO_AUTH_CODE_OPEN 1 +/* WPA_PSK or WPA2PSK */ +#define WMI_ENLO_AUTH_CODE_PSK 2 +/* any EAPOL */ +#define WMI_ENLO_AUTH_CODE_EAPOL 4 + +/* NOTE: wmi_nlo_ssid_param structure can't be changed without breaking the compatibility */ +typedef struct wmi_nlo_ssid_param +{ + A_UINT32 valid; + wmi_ssid ssid; +} wmi_nlo_ssid_param; + +/* NOTE: wmi_nlo_enc_param structure can't be changed without breaking the compatibility */ +typedef struct wmi_nlo_enc_param +{ + A_UINT32 valid; + A_UINT32 enc_type; +} wmi_nlo_enc_param; + +/* NOTE: wmi_nlo_auth_param structure can't be changed without breaking the compatibility */ +typedef struct wmi_nlo_auth_param +{ + A_UINT32 valid; + A_UINT32 auth_type; +} wmi_nlo_auth_param; + +/* NOTE: wmi_nlo_bcast_nw_param structure can't be changed without breaking the compatibility */ +typedef struct wmi_nlo_bcast_nw_param +{ + A_UINT32 valid; + /* If WMI_NLO_CONFIG_EPNO is not set. Supplicant PNO is enabled. The value should be true/false + Otherwise EPNO is enabled. bcast_nw_type would be used as a bit flag contains WMI_ENLO_FLAG_XXX */ + A_UINT32 bcast_nw_type; +} wmi_nlo_bcast_nw_param; + +/* NOTE: wmi_nlo_rssi_param structure can't be changed without breaking the compatibility */ +typedef struct wmi_nlo_rssi_param +{ + A_UINT32 valid; + A_INT32 rssi; +} wmi_nlo_rssi_param; + +typedef struct nlo_configured_parameters { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_nlo_configured_parameters */ + wmi_nlo_ssid_param ssid; + wmi_nlo_enc_param enc_type; + wmi_nlo_auth_param auth_type; + wmi_nlo_rssi_param rssi_cond; + wmi_nlo_bcast_nw_param bcast_nw_type; /* indicates if the SSID is hidden or not */ +} nlo_configured_parameters; + +/* Support channel prediction for PNO scan after scanning top_k_num channels + * if stationary_threshold is met. + */ +typedef struct nlo_channel_prediction_cfg { + A_UINT32 tlv_header; + /* Enable or disable this feature. */ + A_UINT32 enable; + /* Top K channels will be scanned before deciding whether to further scan + * or stop. Minimum value is 3 and maximum is 5. */ + A_UINT32 top_k_num; + /* Preconfigured stationary threshold. + * Lesser value means more conservative. Bigger value means more aggressive. + * Maximum is 100 and mininum is 0. */ + A_UINT32 stationary_threshold; + /* Periodic full channel scan in milliseconds unit. + * After full_scan_period_ms since last full scan, channel prediction + * scan is suppressed and will do full scan. + * This is to help detecting sudden AP power-on or -off. Value 0 means no + * full scan at all (not recommended). + */ + A_UINT32 full_scan_period_ms; +} nlo_channel_prediction_cfg; + +typedef struct wmi_nlo_config { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param */ + A_UINT32 flags; + A_UINT32 vdev_id; + A_UINT32 fast_scan_max_cycles; + A_UINT32 active_dwell_time; + A_UINT32 passive_dwell_time; /* PDT in msecs */ + A_UINT32 probe_bundle_size; + A_UINT32 rest_time; /* ART = IRT */ + A_UINT32 max_rest_time; /* Max value that can be reached after SBM */ + A_UINT32 scan_backoff_multiplier; /* SBM */ + A_UINT32 fast_scan_period; /* SCBM */ + A_UINT32 slow_scan_period; /* specific to windows */ + A_UINT32 no_of_ssids; + A_UINT32 num_of_channels; + A_UINT32 delay_start_time; /* NLO scan start delay time in milliseconds */ + /* The TLVs will follow. + * nlo_configured_parameters nlo_list[]; + * A_UINT32 channel_list[]; + * nlo_channel_prediction_cfg ch_prediction_cfg; + */ + +} wmi_nlo_config_cmd_fixed_param; + +typedef struct wmi_nlo_event +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_nlo_event */ + A_UINT32 vdev_id; +}wmi_nlo_event; + + +/* WMI_PASSPOINT_CONFIG_SET + * Sets a list for passpoint networks for PNO purposes; + * it should be matched against any passpoint networks found + * during regular PNO scan. + */ +#define WMI_PASSPOINT_CONFIG_SET (0x1 << 0) +/* WMI_PASSPOINT_CONFIG_RESET + * Reset passpoint network list - + * no Passpoint networks should be matched after this. + */ +#define WMI_PASSPOINT_CONFIG_RESET (0x1 << 1) + +#define PASSPOINT_REALM_LEN 256 +#define PASSPOINT_ROAMING_CONSORTIUM_ID_LEN 5 +#define PASSPOINT_ROAMING_CONSORTIUM_ID_NUM 16 +#define PASSPOINT_PLMN_ID_LEN 3 +#define PASSPOINT_PLMN_ID_ALLOC_LEN /* round up to A_UINT32 boundary */ \ + (((PASSPOINT_PLMN_ID_LEN + 3) >> 2) << 2) + +/* + * Confirm PASSPOINT_REALM_LEN is a multiple of 4, so the + * A_UINT8 realm[PASSPOINT_REALM_LEN] + * array will end on a 4-byte boundary. + * (This 4-byte alignment simplifies endianness-correction byte swapping.) + */ +A_COMPILE_TIME_ASSERT( + check_passpoint_realm_size, + (PASSPOINT_REALM_LEN % sizeof(A_UINT32)) == 0); + +/* + * Confirm the product of PASSPOINT_ROAMING_CONSORTIUM_ID_NUM and + * PASSPOINT_ROAMING_CONSORTIUM_ID_LEN is a multiple of 4, so the + * roaming_consortium_ids array below will end on a 4-byte boundary. + * (This 4-byte alignment simplifies endianness-correction byte swapping.) + */ +A_COMPILE_TIME_ASSERT( + check_passpoint_roaming_consortium_ids_size, + ((PASSPOINT_ROAMING_CONSORTIUM_ID_NUM*PASSPOINT_ROAMING_CONSORTIUM_ID_LEN) % sizeof(A_UINT32)) == 0); + +/* wildcard ID to allow an action (reset) to apply to all networks */ +#define WMI_PASSPOINT_NETWORK_ID_WILDCARD 0xFFFFFFFF +typedef struct wmi_passpoint_config { + A_UINT32 tlv_header; /* TLV tag and len; tag equals wmi_passpoint_config_cmd_fixed_param */ + /* (network) id + * identifier of the matched network, report this in event + * This id can be a wildcard (WMI_PASSPOINT_NETWORK_ID_WILDCARD) + * that indicates the action should be applied to all networks. + * Currently, the only action that is applied to all networks is "reset". + * If a non-wildcard ID is specified, that particular network is configured. + * If a wildcard ID is specified, all networks are reset. + */ + A_UINT32 id; + A_UINT32 req_id; + A_UINT8 realm[PASSPOINT_REALM_LEN]; /*null terminated UTF8 encoded realm, 0 if unspecified*/ + A_UINT8 roaming_consortium_ids[PASSPOINT_ROAMING_CONSORTIUM_ID_NUM][PASSPOINT_ROAMING_CONSORTIUM_ID_LEN]; /*roaming consortium ids to match, 0s if unspecified*/ + /*This would be bytes-stream as same as defition of realm id in 802.11 standard*/ + A_UINT8 plmn[PASSPOINT_PLMN_ID_ALLOC_LEN]; /*PLMN id mcc/mnc combination as per rules, 0s if unspecified */ +} wmi_passpoint_config_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals wmi_passpoint_event_hdr */ + A_UINT32 id; /* identifier of the matched network */ + A_UINT32 vdev_id; + A_UINT32 timestamp; /* time since boot (in microsecond) when the result was retrieved*/ + wmi_ssid ssid; + wmi_mac_addr bssid; /* bssid of the network */ + A_UINT32 channel_mhz; /* channel frequency in MHz */ + A_UINT32 rssi; /* rssi value */ + A_UINT32 rtt; /* timestamp in nanoseconds*/ + A_UINT32 rtt_sd; /* standard deviation in rtt */ + A_UINT32 beacon_period; /* beacon advertised in the beacon */ + A_UINT32 capability; /* capabilities advertised in the beacon */ + A_UINT32 ie_length; /* size of the ie_data blob */ + A_UINT32 anqp_length; /* length of ANQP blob */ +/* Following this structure is the byte stream of ie data of length ie_buf_len: + * A_UINT8 ie_data[]; // length in byte given by field ie_length, blob of ie data in beacon + * A_UINT8 anqp_ie[]; // length in byte given by field anqp_len, blob of anqp data of IE + * Implicitly, combing ie_data and anqp_ie into a single bufp, and the bytes stream of each ie should be same as BEACON/Action-frm by 802.11 spec. + */ +} wmi_passpoint_event_hdr; + + +#define GTK_OFFLOAD_OPCODE_MASK 0xFF000000 +/** Enable GTK offload, and provided parameters KEK,KCK and replay counter values */ +#define GTK_OFFLOAD_ENABLE_OPCODE 0x01000000 +/** Disable GTK offload */ +#define GTK_OFFLOAD_DISABLE_OPCODE 0x02000000 +/** Read GTK offload parameters, generates WMI_GTK_OFFLOAD_STATUS_EVENT */ +#define GTK_OFFLOAD_REQUEST_STATUS_OPCODE 0x04000000 +enum wmi_chatter_mode { + /* Chatter enter/exit happens + * automatically based on preset + * params + */ + WMI_CHATTER_MODE_AUTO, + /* Chatter enter is triggered + * manually by the user + */ + WMI_CHATTER_MODE_MANUAL_ENTER, + /* Chatter exit is triggered + * manually by the user + */ + WMI_CHATTER_MODE_MANUAL_EXIT, + /* Placeholder max value, always last*/ + WMI_CHATTER_MODE_MAX +}; + +enum wmi_chatter_query_type { + /*query coalescing filter match counter*/ + WMI_CHATTER_QUERY_FILTER_MATCH_CNT, + WMI_CHATTER_QUERY_MAX +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chatter_set_mode_cmd_fixed_param */ + A_UINT32 chatter_mode; +} wmi_chatter_set_mode_cmd_fixed_param; + +/** maximum number of filter supported*/ +#define CHATTER_MAX_COALESCING_RULES 11 +/** maximum number of field tests per filter*/ +#define CHATTER_MAX_FIELD_TEST 5 +/** maximum field length in number of DWORDS*/ +#define CHATTER_MAX_TEST_FIELD_LEN32 2 + +/** field test kinds*/ +#define CHATTER_COALESCING_TEST_EQUAL 1 +#define CHATTER_COALESCING_TEST_MASKED_EQUAL 2 +#define CHATTER_COALESCING_TEST_NOT_EQUAL 3 + +/** packet type*/ +#define CHATTER_COALESCING_PKT_TYPE_UNICAST (1 << 0) +#define CHATTER_COALESCING_PKT_TYPE_MULTICAST (1 << 1) +#define CHATTER_COALESCING_PKT_TYPE_BROADCAST (1 << 2) + +/** coalescing field test*/ +typedef struct _chatter_pkt_coalescing_hdr_test { + /** offset from start of mac header, for windows native wifi host driver + * should assume standard 802.11 frame format without QoS info and address4 + * FW would account for any non-stand fields for final offset value. + */ + A_UINT32 offset; + A_UINT32 length; /* length of test field*/ + A_UINT32 test; /*equal, not equal or masked equal*/ + A_UINT32 mask[CHATTER_MAX_TEST_FIELD_LEN32]; /*mask byte stream*/ + A_UINT32 value[CHATTER_MAX_TEST_FIELD_LEN32]; /*value byte stream*/ +} chatter_pkt_coalescing_hdr_test; + +/** packet coalescing filter*/ +typedef struct _chatter_pkt_coalescing_filter { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chatter_pkt_coalescing_filter */ + A_UINT32 filter_id; /*unique id assigned by OS*/ + A_UINT32 max_coalescing_delay; /*max miliseconds 1st pkt can be hold*/ + A_UINT32 pkt_type; /*unicast/multicast/broadcast*/ + A_UINT32 num_of_test_field; /*number of field test in table*/ + chatter_pkt_coalescing_hdr_test test_fields[CHATTER_MAX_FIELD_TEST]; /*field test tbl*/ +} chatter_pkt_coalescing_filter; + +/** packet coalescing filter add command*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chatter_coalescing_add_filter_cmd_fixed_param */ + A_UINT32 num_of_filters; + /* Following this tlv, there comes an array of structure of type chatter_pkt_coalescing_filter + chatter_pkt_coalescing_filter rx_filter[1];*/ +} wmi_chatter_coalescing_add_filter_cmd_fixed_param; +/** packet coalescing filter delete command*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chatter_coalescing_delete_filter_cmd_fixed_param */ + A_UINT32 filter_id; /*filter id which will be deleted*/ +} wmi_chatter_coalescing_delete_filter_cmd_fixed_param; +/** packet coalescing query command*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chatter_coalescing_query_cmd_fixed_param */ + A_UINT32 type; /*type of query*/ +} wmi_chatter_coalescing_query_cmd_fixed_param; +/** chatter query reply event*/ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_chatter_query_reply_event_fixed_param */ + A_UINT32 type; /*query type*/ + A_UINT32 filter_match_cnt; /*coalescing filter match counter*/ +} wmi_chatter_query_reply_event_fixed_param; + +/* NOTE: This constants GTK_OFFLOAD_KEK_BYTES, GTK_OFFLOAD_KCK_BYTES, and GTK_REPLAY_COUNTER_BYTES + * cannot be changed without breaking WMI compatibility. */ +#define GTK_OFFLOAD_KEK_BYTES 16 +#define GTK_OFFLOAD_KCK_BYTES 16 +/* NOTE: GTK_REPLAY_COUNTER_BYTES, WMI_MAX_KEY_LEN, IGTK_PN_SIZE cannot be changed in the future without breaking WMI compatibility */ +#define GTK_REPLAY_COUNTER_BYTES 8 +#define WMI_MAX_KEY_LEN 32 +#define IGTK_PN_SIZE 6 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param */ + A_UINT32 vdev_id; /** unique id identifying the VDEV */ + A_UINT32 flags; /* status flags */ + A_UINT32 refresh_cnt; /* number of successful GTK refresh exchanges since last SET operation */ + A_UINT8 replay_counter[GTK_REPLAY_COUNTER_BYTES]; /* current replay counter */ + A_UINT8 igtk_keyIndex; /* Use if IGTK_OFFLOAD is defined */ + A_UINT8 igtk_keyLength; /* Use if IGTK_OFFLOAD is defined */ + A_UINT8 igtk_keyRSC[IGTK_PN_SIZE]; /* key replay sequence counter */ /* Use if IGTK_OFFLOAD is defined */ + A_UINT8 igtk_key[WMI_MAX_KEY_LEN]; /* Use if IGTK_OFFLOAD is defined */ +} WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param */ + A_UINT32 vdev_id; /** unique id identifying the VDEV */ + A_UINT32 flags; /* control flags, GTK offload command use high byte */ + /* The size of following 3 arrays cannot be changed without breaking WMI compatibility. */ + A_UINT8 KEK[GTK_OFFLOAD_KEK_BYTES]; /* key encryption key */ + A_UINT8 KCK[GTK_OFFLOAD_KCK_BYTES]; /* key confirmation key */ + A_UINT8 replay_counter[GTK_REPLAY_COUNTER_BYTES]; /* replay counter for re-key */ +}WMI_GTK_OFFLOAD_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 sa_query_retry_interval; /* in msec */ + A_UINT32 sa_query_max_retry_count; +} WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param; + +typedef enum { + WMI_STA_KEEPALIVE_METHOD_NULL_FRAME = 1, /* 802.11 NULL frame */ + WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE = 2, /* ARP response */ + WMI_STA_KEEPALIVE_METHOD_ETHERNET_LOOPBACK = 3, /*ETHERNET LOOPBACK*/ + WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST = 4, /* gratuitous ARP req*/ +} WMI_STA_KEEPALIVE_METHOD; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_STA_KEEPALVE_ARP_RESPONSE */ + WMI_IPV4_ADDR sender_prot_addr; /* Sender protocol address */ + WMI_IPV4_ADDR target_prot_addr; /* Target protocol address */ + wmi_mac_addr dest_mac_addr; /* destination MAC address */ +} WMI_STA_KEEPALVE_ARP_RESPONSE; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_STA_KEEPALIVE_CMD_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 enable; /* 1 - Enable, 0 - disable */ + A_UINT32 method; /* keep alive method */ + A_UINT32 interval; /* time interval in seconds */ + /* + * NOTE: following this structure is the TLV for ARP Resonse: + * WMI_STA_KEEPALVE_ARP_RESPONSE arp_resp; // ARP response + */ +} WMI_STA_KEEPALIVE_CMD_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 action; +} WMI_VDEV_WNM_SLEEPMODE_CMD_fixed_param; +typedef WMI_VDEV_WNM_SLEEPMODE_CMD_fixed_param WMI_STA_WNMSLEEP_CMD; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_set_keepalive_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 keepaliveInterval; /* seconds */ + A_UINT32 keepaliveMethod; +} wmi_vdev_set_keepalive_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_get_keepalive_cmd_fixed_param */ + A_UINT32 vdev_id; +} wmi_vdev_get_keepalive_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_get_keepalive_event_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 keepaliveInterval; /* seconds */ + A_UINT32 keepaliveMethod; /* seconds */ +} wmi_vdev_get_keepalive_event_fixed_param; + +#define IPSEC_NATKEEPALIVE_FILTER_DISABLE 0 +#define IPSEC_NATKEEPALIVE_FILTER_ENABLE 1 + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 action; +} WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param; + +typedef WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 mcc_tbttmode; + wmi_mac_addr mcc_bssid; +} wmi_vdev_mcc_set_tbtt_mode_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; /* home vdev id */ + A_UINT32 meas_token; /* from measure request frame */ + A_UINT32 dialog_token; + A_UINT32 number_bursts; /* zero keep sending until cancel, bigger than 0 means times e.g. 1,2 */ + A_UINT32 burst_interval; /* unit in mill seconds, interval between consecutive burst*/ + A_UINT32 burst_cycle; /* times cycle through within one burst */ + A_UINT32 tx_power; /* for path frame */ + A_UINT32 off_duration; /* uint in mill seconds, channel off duraiton for path loss frame sending */ + wmi_mac_addr dest_mac; /* multicast DA, for path loss frame */ + A_UINT32 num_chans; +} wmi_vdev_plmreq_start_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 meas_token; /* same value from req*/ +} wmi_vdev_plmreq_stop_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_set_noa_cmd_fixed_param */ + A_UINT32 tlv_header; + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* enable/disable NoA */ + A_UINT32 enable; + /** number of NoA desc. In the TLV noa_descriptor[] */ + A_UINT32 num_noa; + /** + * TLV (tag length value ) paramerters follow the pattern structure. + * TLV contain NoA desc with num of num_noa + */ +} wmi_p2p_set_noa_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_unit_test_cmd_fixed_param */ + A_UINT32 tlv_header; + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* Identify the wlan module */ + A_UINT32 module_id; + /* Num of test arguments passed */ + A_UINT32 num_args; +/** + * TLV (tag length value ) parameters follow the wmi_roam_chan_list + * structure. The TLV's are: + * A_UINT32 args[]; + **/ +} wmi_unit_test_cmd_fixed_param; + +/** Roaming offload SYNCH_COMPLETE from host when host finished sync logic + * after it received WMI_ROAM_SYNCH_EVENTID. + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_roam_synch_complete_fixed_param; + + +typedef enum { + RECOVERY_SIM_ASSERT = 0x01, + RECOVERY_SIM_NO_DETECT = 0x02, + RECOVERY_SIM_CTR_EP_FULL = 0x03, + RECOVERY_SIM_EMPTY_POINT = 0x04, + RECOVERY_SIM_STACK_OV = 0x05, + RECOVERY_SIM_INFINITE_LOOP = 0x06, + RECOVERY_SIM_PCIE_LINKDOWN = 0x07, + RECOVERY_SIM_SELF_RECOVERY = 0x08, +} RECOVERY_SIM_TYPE; + +/* WMI_FORCE_FW_HANG_CMDID */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_WMI_FORCE_FW_HANG_CMD_fixed_param */ + A_UINT32 type; /*0:unused 1: ASSERT, 2: not respond detect command,3: simulate ep-full(),4:...*/ + A_UINT32 delay_time_ms; /*0xffffffff means the simulate will delay for random time (0 ~0xffffffff ms)*/ +}WMI_FORCE_FW_HANG_CMD_fixed_param; +#define WMI_MCAST_FILTER_SET 1 +#define WMI_MCAST_FILTER_DELETE 2 +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 index; + A_UINT32 action; + wmi_mac_addr mcastbdcastaddr; +} WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param; + +/* GPIO Command and Event data structures */ + +/* WMI_GPIO_CONFIG_CMDID */ +enum { + WMI_GPIO_PULL_NONE, + WMI_GPIO_PULL_UP, + WMI_GPIO_PULL_DOWN, +}; + +enum { + WMI_GPIO_INTTYPE_DISABLE, + WMI_GPIO_INTTYPE_RISING_EDGE, + WMI_GPIO_INTTYPE_FALLING_EDGE, + WMI_GPIO_INTTYPE_BOTH_EDGE, + WMI_GPIO_INTTYPE_LEVEL_LOW, + WMI_GPIO_INTTYPE_LEVEL_HIGH +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_gpio_config_cmd_fixed_param */ + A_UINT32 gpio_num; /* GPIO number to be setup */ + A_UINT32 input; /* 0 - Output/ 1 - Input */ + A_UINT32 pull_type; /* Pull type defined above */ + A_UINT32 intr_mode; /* Interrupt mode defined above (Input) */ +} wmi_gpio_config_cmd_fixed_param; + +/* WMI_GPIO_OUTPUT_CMDID */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_gpio_output_cmd_fixed_param */ + A_UINT32 gpio_num; /* GPIO number to be setup */ + A_UINT32 set; /* Set the GPIO pin*/ +} wmi_gpio_output_cmd_fixed_param; + +/* WMI_GPIO_INPUT_EVENTID */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_gpio_input_event_fixed_param */ + A_UINT32 gpio_num; /* GPIO number which changed state */ +} wmi_gpio_input_event_fixed_param; + +/* WMI_P2P_DISC_EVENTID */ +enum { + P2P_DISC_SEARCH_PROB_REQ_HIT = 0, /* prob req hit the p2p find pattern */ + P2P_DISC_SEARCH_PROB_RESP_HIT, /* prob resp hit the p2p find pattern */ +}; + +enum { + P2P_DISC_MODE_SEARCH = 0, /* do search when p2p find offload*/ + P2P_DISC_MODE_LISTEN, /* do listen when p2p find offload*/ + P2P_DISC_MODE_AUTO, /* do listen and search when p2p find offload*/ +}; + +enum { + P2P_DISC_PATTERN_TYPE_BSSID = 0, /* BSSID pattern */ + P2P_DISC_PATTERN_TYPE_DEV_NAME, /* device name pattern */ +}; + +typedef struct { + A_UINT32 vdev_id; + A_UINT32 reason; /* P2P DISC wake up reason*/ +} wmi_p2p_disc_event; + +typedef WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param WOW_EVENT_INFO_SECTION_GTKIGTK; + +typedef enum { + WMI_FAKE_TXBFER_SEND_NDPA, + WMI_FAKE_TXBFER_SEND_MU, + WMI_FAKE_TXBFER_NDPA_FBTYPE, + WMI_FAKE_TXBFER_NDPA_NCIDX, + WMI_FAKE_TXBFER_NDPA_POLL, + WMI_FAKE_TXBFER_NDPA_BW, + WMI_FAKE_TXBFER_NDPA_PREAMBLE, + WMI_FAKE_TXBFER_NDPA_RATE, + WMI_FAKE_TXBFER_NDP_BW, + WMI_FAKE_TXBFER_NDP_NSS, + WMI_TXBFEE_ENABLE_UPLOAD_H, + WMI_TXBFEE_ENABLE_CAPTURE_H, + WMI_TXBFEE_SET_CBF_TBL, + WMI_TXBFEE_CBF_TBL_LSIG, + WMI_TXBFEE_CBF_TBL_SIGA1, + WMI_TXBFEE_CBF_TBL_SIGA2, + WMI_TXBFEE_CBF_TBL_SIGB, + WMI_TXBFEE_CBF_TBL_PAD, + WMI_TXBFEE_CBF_TBL_DUR, + WMI_TXBFEE_SU_NCIDX, + WMI_TXBFEE_CBIDX, + WMI_TXBFEE_NGIDX, +} WMI_TXBF_PARAM_ID; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_txbf_cmd_fixed_param */ + /** parameter id */ + A_UINT32 param_id; + /** parameter value */ + A_UINT32 param_value; +} wmi_txbf_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_upload_h_hdr */ + A_UINT32 h_length; + A_UINT32 cv_length; + /* This TLV is followed by array of bytes: + * // h_cv info buffer + * A_UINT8 bufp[]; + */ +} wmi_upload_h_hdr; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_capture_h_event_hdr */ + A_UINT32 svd_num; + A_UINT32 tone_num; + A_UINT32 reserved; +} wmi_capture_h_event_hdr; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_avoid_freq_range_desc */ + A_UINT32 start_freq; //start frequency, not channel center freq + A_UINT32 end_freq; //end frequency +} wmi_avoid_freq_range_desc; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_avoid_freq_ranges_event_fixed_param */ + //bad channel range count, multi range is allowed, 0 means all channel clear + A_UINT32 num_freq_ranges; + + /* The TLVs will follow. + * multi range with num_freq_ranges, LTE advance multi carrier, CDMA,etc + * wmi_avoid_freq_range_desc avd_freq_range[]; // message buffer, NULL terminated + */ +} wmi_avoid_freq_ranges_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_gtk_rekey_fail_event_fixed_param */ + /** Reserved for future use */ + A_UINT32 reserved0; + A_UINT32 vdev_id; +} wmi_gtk_rekey_fail_event_fixed_param; + +enum wmm_ac_downgrade_policy { + WMM_AC_DOWNGRADE_DEPRIO, + WMM_AC_DOWNGRADE_DROP, + WMM_AC_DOWNGRADE_INVALID, +}; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 cwmin; + A_UINT32 cwmax; + A_UINT32 aifs; + A_UINT32 txoplimit; + A_UINT32 acm; + A_UINT32 no_ack; +} wmi_wmm_vparams; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + wmi_wmm_vparams wmm_params[4]; /* 0 be, 1 bk, 2 vi, 3 vo */ +} wmi_vdev_set_wmm_params_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 gtxRTMask[2]; /* for HT and VHT rate masks */ + A_UINT32 userGtxMask; /* host request for GTX mask */ + A_UINT32 gtxPERThreshold; /* default: 10% */ + A_UINT32 gtxPERMargin; /* default: 2% */ + A_UINT32 gtxTPCstep; /* default: 1 */ + A_UINT32 gtxTPCMin; /* default: 5 */ + A_UINT32 gtxBWMask; /* 20/40/80/160 Mhz */ +} wmi_vdev_set_gtx_params_cmd_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 ac; + A_UINT32 medium_time_us; /* per second unit, the Admitted time granted, unit in micro seconds */ + A_UINT32 downgrade_type; +} wmi_vdev_wmm_addts_cmd_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 ac; +} wmi_vdev_wmm_delts_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_dfs_enable_cmd_fixed_param */ + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_pdev_dfs_enable_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_dfs_disable_cmd_fixed_param */ + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_pdev_dfs_disable_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_ena_cmd_fixed_param + */ + A_UINT32 tlv_header; + + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_dfs_phyerr_filter_ena_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_dis_cmd_fixed_param + */ + A_UINT32 tlv_header; + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_dfs_phyerr_filter_dis_cmd_fixed_param; + +/** TDLS COMMANDS */ + +/* WMI_TDLS_SET_STATE_CMDID */ +/* TDLS State */ +enum wmi_tdls_state { + /** TDLS disable */ + WMI_TDLS_DISABLE, + /** TDLS enabled - no firmware connection tracking/notifications */ + WMI_TDLS_ENABLE_PASSIVE, + /** TDLS enabled - with firmware connection tracking/notifications */ + WMI_TDLS_ENABLE_ACTIVE, + /** TDLS enabled - firmware waits for peer mac for connection tracking */ + WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL, +}; + +/* TDLS Options */ +#define WMI_TDLS_OFFCHAN_EN (1 << 0) /** TDLS Off Channel support */ +#define WMI_TDLS_BUFFER_STA_EN (1 << 1) /** TDLS Buffer STA support */ +#define WMI_TDLS_SLEEP_STA_EN (1 << 2) /** TDLS Sleep STA support (not currently supported) */ + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** Enable/Disable TDLS (wmi_tdls_state) */ + A_UINT32 state; + /** Duration (in ms) over which to calculate tx/rx threshold to trigger TDLS Discovery */ + A_UINT32 notification_interval_ms; + /** number of packets OVER which notify/suggest TDLS Discovery: + * if current tx pps counter / notification interval >= threshold + * then a notification will be sent to host to advise TDLS Discovery */ + A_UINT32 tx_discovery_threshold; + /** number of packets UNDER which notify/suggest TDLS Teardown: + * if current tx pps counter / notification interval < threshold + * then a notification will be sent to host to advise TDLS Tear down */ + A_UINT32 tx_teardown_threshold; + /** Absolute RSSI value under which notify/suggest TDLS Teardown */ + A_INT32 rssi_teardown_threshold; + /** Peer RSSI < (AP RSSI + delta) will trigger a teardown */ + A_INT32 rssi_delta; + /** TDLS Option Control + * Off-Channel, Buffer STA, (later)Sleep STA support */ + A_UINT32 tdls_options; + /* Buffering time in number of beacon intervals */ + A_UINT32 tdls_peer_traffic_ind_window; + /* Wait time for PTR frame */ + A_UINT32 tdls_peer_traffic_response_timeout_ms; + /* Self PUAPSD mask */ + A_UINT32 tdls_puapsd_mask; + /* Inactivity timeout */ + A_UINT32 tdls_puapsd_inactivity_time_ms; + /* Max of rx frame during SP */ + A_UINT32 tdls_puapsd_rx_frame_threshold; + /**Duration (in ms) over which to check whether TDLS link needs to be torn down */ + A_UINT32 teardown_notification_ms; + /**STA kickout threshold for TDLS peer */ + A_UINT32 tdls_peer_kickout_threshold; +} wmi_tdls_set_state_cmd_fixed_param; + +/* WMI_TDLS_PEER_UPDATE_CMDID */ + +enum wmi_tdls_peer_state { + /** tx peer TDLS link setup now starting, traffic to DA should be + * paused (except TDLS frames) until state is moved to CONNECTED (or + * TEARDOWN on setup failure) */ + WMI_TDLS_PEER_STATE_PEERING, + /** tx peer TDLS link established, running (all traffic to DA unpaused) */ + WMI_TDLS_PEER_STATE_CONNECTED, + /** tx peer TDLS link tear down started (link paused, any frames + * queued for DA will be requeued back through the AP)*/ + WMI_TDLS_PEER_STATE_TEARDOWN, + /** Add peer mac into connection table */ + WMI_TDLS_PEER_ADD_MAC_ADDR, + /** Remove peer mac from connection table */ + WMI_TDLS_PEER_REMOVE_MAC_ADDR, +}; + +/* NB: These defines are fixed, and cannot be changed without breaking WMI compatibility */ +#define WMI_TDLS_MAX_SUPP_OPER_CLASSES 32 +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities */ + A_UINT32 tlv_header; + /* Peer's QoS Info - for U-APSD */ + /* AC FLAGS - accessed through macros below */ + /* Ack, SP, More Data Ack - accessed through macros below */ + A_UINT32 peer_qos; + /*TDLS Peer's U-APSD Buffer STA Support*/ + A_UINT32 buff_sta_support; + /*TDLS off channel related params */ + A_UINT32 off_chan_support; + A_UINT32 peer_curr_operclass; + A_UINT32 self_curr_operclass; + /* Number of channels available for off channel operation */ + A_UINT32 peer_chan_len; + A_UINT32 peer_operclass_len; + A_UINT8 peer_operclass[WMI_TDLS_MAX_SUPP_OPER_CLASSES]; + /* Is peer initiator or responder of TDLS setup request */ + A_UINT32 is_peer_responder; + /* Preferred off channel number as configured by user */ + A_UINT32 pref_offchan_num; + /* Preferred off channel bandwidth as configured by user */ + A_UINT32 pref_offchan_bw; + + /** Followed by the variable length TLV peer_chan_list: + * wmi_channel peer_chan_list[]. + * Array size would be peer_chan_len. + * This array is intersected channels which is supported by both peer + * and DUT. freq1 in chan_info shall be same as mhz, freq2 shall be 0. + * FW shall compute BW for an offchan based on peer's ht/vht cap + * received in peer_assoc cmd during change STA operation + */ +} wmi_tdls_peer_capabilities; + +#define WMI_TDLS_QOS_VO_FLAG 0 +#define WMI_TDLS_QOS_VI_FLAG 1 +#define WMI_TDLS_QOS_BK_FLAG 2 +#define WMI_TDLS_QOS_BE_FLAG 3 +#define WMI_TDLS_QOS_ACK_FLAG 4 +#define WMI_TDLS_QOS_SP_FLAG 5 +#define WMI_TDLS_QOS_MOREDATA_FLAG 7 + +#define WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps,flag) do { \ + (ppeer_caps)->peer_qos |= (1 << flag); \ + } while(0) +#define WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps,flag) \ + (((ppeer_caps)->peer_qos & (1 << flag)) >> flag) + +#define WMI_SET_TDLS_PEER_VO_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_VO_FLAG) +#define WMI_GET_TDLS_PEER_VO_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_VO_FLAG) +#define WMI_SET_TDLS_PEER_VI_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_VI_FLAG) +#define WMI_GET_TDLS_PEER_VI_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_VI_FLAG) +#define WMI_SET_TDLS_PEER_BK_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_BK_FLAG) +#define WMI_GET_TDLS_PEER_BK_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_BK_FLAG) +#define WMI_SET_TDLS_PEER_BE_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_BE_FLAG) +#define WMI_GET_TDLS_PEER_BE_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_BE_FLAG) +#define WMI_SET_TDLS_PEER_ACK_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_ACK_FLAG) +#define WMI_GET_TDLS_PEER_ACK_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_ACK_FLAG) +/* SP has 2 bits */ +#define WMI_SET_TDLS_PEER_SP_UAPSD(ppeer_caps,val) do { \ + (ppeer_caps)->peer_qos |= (((val)&0x3) << WMI_TDLS_QOS_SP_FLAG); \ + } while(0) +#define WMI_GET_TDLS_PEER_SP_UAPSD(ppeer_caps) \ + (((ppeer_caps)->peer_qos & (0x3 << WMI_TDLS_QOS_SP_FLAG)) >> WMI_TDLS_QOS_SP_FLAG) + +#define WMI_SET_TDLS_PEER_MORE_DATA_ACK_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_SET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_MOREDATA_FLAG) +#define WMI_GET_TDLS_PEER_MORE_DATA_ACK_UAPSD(ppeer_caps) \ + WMI_TDLS_PEER_GET_QOS_FLAG(ppeer_caps, WMI_TDLS_QOS_MOREDATA_FLAG) + + +#define WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd,flag) do { \ + (pset_cmd)->tdls_puapsd_mask |= (1 << flag); \ + } while(0) +#define WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd,flag) \ + (((pset_cmd)->tdls_puapsd_mask & (1 << flag)) >> flag) + +#define WMI_SET_TDLS_SELF_VO_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_VO_FLAG) +#define WMI_GET_TDLS_SELF_VO_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_VO_FLAG) +#define WMI_SET_TDLS_SELF_VI_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_VI_FLAG) +#define WMI_GET_TDLS_SELF_VI_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_VI_FLAG) +#define WMI_SET_TDLS_SELF_BK_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_BK_FLAG) +#define WMI_GET_TDLS_SELF__BK_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_BK_FLAG) +#define WMI_SET_TDLS_SELF_BE_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_BE_FLAG) +#define WMI_GET_TDLS_SELF_BE_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_BE_FLAG) +#define WMI_SET_TDLS_SELF_ACK_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_ACK_FLAG) +#define WMI_GET_TDLS_SELF_ACK_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_ACK_FLAG) +/* SP has 2 bits */ +#define WMI_SET_TDLS_SELF_SP_UAPSD(pset_cmd,val) do { \ + (pset_cmd)->tdls_puapsd_mask |= (((val)&0x3) << WMI_TDLS_QOS_SP_FLAG); \ + } while(0) +#define WMI_GET_TDLS_SELF_SP_UAPSD(pset_cmd) \ + (((pset_cmd)->tdls_puapsd_mask & (0x3 << WMI_TDLS_QOS_SP_FLAG)) >> WMI_TDLS_QOS_SP_FLAG) + +#define WMI_SET_TDLS_SELF_MORE_DATA_ACK_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_SET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_MOREDATA_FLAG) +#define WMI_GET_TDLS_SELF_MORE_DATA_ACK_UAPSD(pset_cmd) \ + WMI_TDLS_SELF_GET_QOS_FLAG(pset_cmd, WMI_TDLS_QOS_MOREDATA_FLAG) + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** new TDLS state for peer (wmi_tdls_peer_state) */ + A_UINT32 peer_state; + /* The TLV for wmi_tdls_peer_capabilities will follow. + * wmi_tdls_peer_capabilities peer_caps; + */ + /** Followed by the variable length TLV chan_info: + * wmi_channel chan_info[] */ +} wmi_tdls_peer_update_cmd_fixed_param; + +/* WMI_TDLS_SET_OFFCHAN_MODE_CMDID */ + + +/* bitmap 20, 40, 80 or 160 MHz wide channel */ +#define WMI_TDLS_OFFCHAN_20MHZ 0x1 /* 20 MHz wide channel */ +#define WMI_TDLS_OFFCHAN_40MHZ 0x2 /* 40 MHz wide channel */ +#define WMI_TDLS_OFFCHAN_80MHZ 0x4 /* 80 MHz wide channel */ +#define WMI_TDLS_OFFCHAN_160MHZ 0x8 /* 160 MHz wide channel */ + + +enum wmi_tdls_offchan_mode { + WMI_TDLS_ENABLE_OFFCHANNEL, + WMI_TDLS_DISABLE_OFFCHANNEL +}; + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** Enable/Disable TDLS offchannel */ + A_UINT32 offchan_mode; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /* Is peer initiator or responder of TDLS setup request */ + A_UINT32 is_peer_responder; + /* off channel number*/ + A_UINT32 offchan_num; + /* off channel bandwidth bitmap, e.g. WMI_OFFCHAN_20MHZ */ + A_UINT32 offchan_bw_bitmap; + /* operating class for offchan */ + A_UINT32 offchan_oper_class; +} wmi_tdls_set_offchan_mode_cmd_fixed_param; + +/** TDLS EVENTS */ +enum wmi_tdls_peer_notification { + /** tdls discovery recommended for peer (based + * on tx bytes per second > tx_discover threshold) */ + WMI_TDLS_SHOULD_DISCOVER, + /** tdls link tear down recommended for peer + * due to tx bytes per second below tx_teardown_threshold + * NB: this notification sent once */ + WMI_TDLS_SHOULD_TEARDOWN, + /** tx peer TDLS link tear down complete */ + WMI_TDLS_PEER_DISCONNECTED, +}; + +enum wmi_tdls_peer_reason { + /** tdls teardown recommended due to low transmits */ + WMI_TDLS_TEARDOWN_REASON_TX, + /** tdls link tear down recommended due to poor RSSI */ + WMI_TDLS_TEARDOWN_REASON_RSSI, + /** tdls link tear down recommended due to offchannel scan */ + WMI_TDLS_TEARDOWN_REASON_SCAN, + /** tdls peer disconnected due to peer deletion */ + WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE, + /** tdls peer disconnected due to PTR timeout */ + WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT, + /** tdls peer disconnected due wrong PTR format */ + WMI_TDLS_TEARDOWN_REASON_BAD_PTR, + /** tdls peer not responding */ + WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE, +}; + +/* WMI_TDLS_PEER_EVENTID */ +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_tdls_peer_event_fixed_param */ + A_UINT32 tlv_header; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** TDLS peer status (wmi_tdls_peer_notification)*/ + A_UINT32 peer_status; + /** TDLS peer reason (wmi_tdls_peer_reason) */ + A_UINT32 peer_reason; + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; +} wmi_tdls_peer_event_fixed_param; + +/* NOTE: wmi_vdev_mcc_bcn_intvl_change_event_fixed_param would be deprecated. Please + don't use this for any new implementations */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_mcc_bcn_intvl_change_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* New beacon interval to be used for the specified VDEV suggested by firmware */ + A_UINT32 new_bcn_intvl; +} wmi_vdev_mcc_bcn_intvl_change_event_fixed_param; + +/* WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID */ +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param */ + A_UINT32 tlv_header; + /** 1: enable fw based adaptive ocs, + * 0: disable fw based adaptive ocs + */ + A_UINT32 enable; + /** This field contains the MAC identifier in order to lookup the appropriate OCS instance. */ + /** The valid range is 0 to (num_macs-1). */ + A_UINT32 mac_id; +} wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param; + +/* WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID */ +typedef struct { + /* Frequency of the channel for which the quota is set */ + A_UINT32 chan_mhz; + /* Requested channel time quota expressed as percentage */ + A_UINT32 channel_time_quota; +} wmi_resmgr_chan_time_quota; + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_resmgr_set_chan_time_quota_cmd_fixed_param */ + A_UINT32 tlv_header; + /** number of channel time quota command structures + * (wmi_resmgr_chan_time_quota) 1 or 2 + */ + A_UINT32 num_chans; +/* This TLV is followed by another TLV of array of bytes + * A_UINT8 data[]; + * This data array contains + * num_chans * size of(struct wmi_resmgr_chan_time_quota) + */ +} wmi_resmgr_set_chan_time_quota_cmd_fixed_param; + +/* WMI_RESMGR_SET_CHAN_LATENCY_CMDID */ +typedef struct { + /* Frequency of the channel for which the latency is set */ + A_UINT32 chan_mhz; + /* Requested channel latency in milliseconds */ + A_UINT32 latency; +} wmi_resmgr_chan_latency; + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_resmgr_set_chan_latency_cmd_fixed_param */ + A_UINT32 tlv_header; + /** number of channel latency command structures + * (wmi_resmgr_chan_latency) 1 or 2 + */ + A_UINT32 num_chans; +/* This TLV is followed by another TLV of array of bytes + * A_UINT8 data[]; + * This data array contains + * num_chans * size of(struct wmi_resmgr_chan_latency) + */ +} wmi_resmgr_set_chan_latency_cmd_fixed_param; + +/* WMI_STA_SMPS_FORCE_MODE_CMDID */ + +/** STA SMPS Forced Mode */ +typedef enum { + WMI_SMPS_FORCED_MODE_NONE = 0, + WMI_SMPS_FORCED_MODE_DISABLED, + WMI_SMPS_FORCED_MODE_STATIC, + WMI_SMPS_FORCED_MODE_DYNAMIC +} wmi_sta_smps_forced_mode; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_cmd_fixed_param */ + A_UINT32 tlv_header; + /** Unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** The mode of SMPS that is to be forced in the FW. */ + A_UINT32 forced_mode; +} wmi_sta_smps_force_mode_cmd_fixed_param; + +/** wlan HB commands */ +#define WMI_WLAN_HB_ITEM_UDP 0x1 +#define WMI_WLAN_HB_ITEM_TCP 0x2 +#define WMI_WLAN_HB_MAX_FILTER_SIZE 32 /* should be equal to WLAN_HB_MAX_FILTER_SIZE, must be a multiple of 4 bytes */ + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 enable; + A_UINT32 item; + A_UINT32 session; +} wmi_hb_set_enable_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 srv_ip; + A_UINT32 dev_ip; + A_UINT32 seq; + A_UINT32 src_port; + A_UINT32 dst_port; + A_UINT32 interval; + A_UINT32 timeout; + A_UINT32 session; +wmi_mac_addr gateway_mac; +} wmi_hb_set_tcp_params_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 length; + A_UINT32 offset; + A_UINT32 session; + A_UINT8 filter[WMI_WLAN_HB_MAX_FILTER_SIZE]; +} wmi_hb_set_tcp_pkt_filter_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 srv_ip; + A_UINT32 dev_ip; + A_UINT32 src_port; + A_UINT32 dst_port; + A_UINT32 interval; + A_UINT32 timeout; + A_UINT32 session; + wmi_mac_addr gateway_mac; +} wmi_hb_set_udp_params_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 length; + A_UINT32 offset; + A_UINT32 session; + A_UINT8 filter[WMI_WLAN_HB_MAX_FILTER_SIZE]; +} wmi_hb_set_udp_pkt_filter_cmd_fixed_param; + +/** wlan HB events */ +typedef enum { + WMI_WLAN_HB_REASON_UNKNOWN = 0, + WMI_WLAN_HB_REASON_TCP_TIMEOUT = 1, + WMI_WLAN_HB_REASON_UDP_TIMEOUT = 2, +} WMI_HB_WAKEUP_REASON; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_hb_ind_event_fixed_param */ + A_UINT32 vdev_id; /* unique id identifying the VDEV */ + A_UINT32 session; /* Session ID from driver */ + A_UINT32 reason; /* wakeup reason */ +} wmi_hb_ind_event_fixed_param; + +/** WMI_STA_SMPS_PARAM_CMDID */ +typedef enum { + /** RSSI threshold to enter Dynamic SMPS mode from inactive mode */ + WMI_STA_SMPS_PARAM_UPPER_RSSI_THRESH = 0, + /** RSSI threshold to enter Stalled-D-SMPS mode from D-SMPS mode or + * to enter D-SMPS mode from Stalled-D-SMPS mode */ + WMI_STA_SMPS_PARAM_STALL_RSSI_THRESH = 1, + /** RSSI threshold to disable SMPS modes */ + WMI_STA_SMPS_PARAM_LOWER_RSSI_THRESH = 2, + /** Upper threshold for beacon-RSSI. Used to reduce RX chainmask. */ + WMI_STA_SMPS_PARAM_UPPER_BRSSI_THRESH = 3, + /** Lower threshold for beacon-RSSI. Used to increase RX chainmask. */ + WMI_STA_SMPS_PARAM_LOWER_BRSSI_THRESH = 4, + /** Enable/Disable DTIM 1chRx feature */ + WMI_STA_SMPS_PARAM_DTIM_1CHRX_ENABLE = 5 +} wmi_sta_smps_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_sta_smps_param_cmd_fixed_param */ + A_UINT32 tlv_header; + /** Unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** SMPS parameter (see wmi_sta_smps_param) */ + A_UINT32 param; + /** Value of SMPS parameter */ + A_UINT32 value; +} wmi_sta_smps_param_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mcc_sched_sta_traffic_stats */ + A_UINT32 tlv_header; + /* TX stats */ + A_UINT32 txBytesPushed; + A_UINT32 txPacketsPushed; + /* RX stats */ + A_UINT32 rxBytesRcvd; + A_UINT32 rxPacketsRcvd; + A_UINT32 rxTimeTotal; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; +} wmi_mcc_sched_sta_traffic_stats; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mcc_sched_traffic_stats_cmd_fixed_param */ + A_UINT32 tlv_header; + /** Duration over which the host stats were collected */ + A_UINT32 duration; + /** Number of stations filled in following stats array */ + A_UINT32 num_sta; + /* Following this struct are the TLVs: + * wmi_mcc_sched_sta_traffic_stats mcc_sched_sta_traffic_stats_list; + */ +} wmi_mcc_sched_traffic_stats_cmd_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_batch_scan_enable_cmd_fixed_param */ + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /*Batch scan enable command parameters*/ + A_UINT32 scanInterval; + A_UINT32 numScan2Batch; + A_UINT32 bestNetworks; + A_UINT32 rfBand; + A_UINT32 rtt; +} wmi_batch_scan_enable_cmd_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_batch_scan_enabled_event_fixed_param */ + A_UINT32 supportedMscan; +} wmi_batch_scan_enabled_event_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_batch_scan_disable_cmd_fixed_param */ +/* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + A_UINT32 param; +} wmi_batch_scan_disable_cmd_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_batch_scan_trigger_result_cmd_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + A_UINT32 param; +} wmi_batch_scan_trigger_result_cmd_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; + wmi_mac_addr bssid; /* BSSID */ + wmi_ssid ssid; /* SSID */ + A_UINT32 ch; /* Channel */ + A_UINT32 rssi; /* RSSI or Level */ + /* Timestamp when Network was found. Used to calculate age based on timestamp in GET_RSP msg header */ + A_UINT32 timestamp; +} wmi_batch_scan_result_network_info; + +typedef struct +{ + A_UINT32 tlv_header; + A_UINT32 scanId; /* Scan List ID. */ + /* No of AP in a Scan Result. Should be same as bestNetwork in SET_REQ msg */ + A_UINT32 numNetworksInScanList; + A_UINT32 netWorkStartIndex; /* indicate the start index of network info*/ +} wmi_batch_scan_result_scan_list; + +#define LPI_IE_BITMAP_BSSID 0x00000001 // if this bit is set, bssid of the scan response frame is sent as the first IE in the data buffer sent to LOWI LP. +#define LPI_IE_BITMAP_IS_PROBE 0x00000002 // send true or false based on scan response frame being a Probe Rsp or not +#define LPI_IE_BITMAP_SSID 0x00000004 // send ssid from received scan response frame +#define LPI_IE_BITMAP_RSSI 0x00000008 // send RSSI value reported by HW for the received scan response after adjusting with noise floor +#define LPI_IE_BITMAP_CHAN 0x00000010 // send channel number from the received scan response +#define LPI_IE_BITMAP_AP_TX_PWR 0x00000020 // send Tx power from TPC IE of scan rsp +#define LPI_IE_BITMAP_TX_RATE 0x00000040 // send rate of the received frame as reported by HW. +#define LPI_IE_BITMAP_80211_MC_SUPPORT 0x00000080 // send true or false based on the received scan rsp was from a 11mc supported AP or not. +#define LPI_IE_BITMAP_TSF_TIMER_VALUE 0x00000100 // send timestamp reported in the received scan rsp frame. +#define LPI_IE_BITMAP_AGE_OF_MEASUREMENT 0x00000200 // (current system time - received time) = duration of time scan rsp frame data is kept in the buffer before sending to LOWI LP. +/* + * TEMPORARY alias of incorrect old name the correct name. + * This alias will be removed once all references to the old name have been fixed. + */ +#define LPI_IE_BITMAP_AGE_OF_MESAUREMENT LPI_IE_BITMAP_AGE_OF_MEASUREMENT +#define LPI_IE_BITMAP_CONN_STATUS 0x00000400 // If an infra STA is active and connected to an AP, true value is sent else false. +#define LPI_IE_BITMAP_MSAP_IE 0x00000800 // info on the vendor specific proprietary IE MSAP +#define LPI_IE_BITMAP_SEC_STATUS 0x00001000 // we indicate true or false based on if the AP has WPA or RSN security enabled +#define LPI_IE_BITMAP_DEVICE_TYPE 0x00002000 // info about the beacons coming from an AP or P2P or NAN device. +#define LPI_IE_BITMAP_CHAN_IS_PASSIVE 0x00004000 // info on whether the scan rsp was received from a passive channel +#define LPI_IE_BITMAP_DWELL_TIME 0x00008000 // send the scan dwell time of the channel on which the current scan rsp frame was received. +#define LPI_IE_BITMAP_BAND_CENTER_FREQ1 0x00010000 // the center frequencies in case AP is supporting wider channels than 20 MHz +#define LPI_IE_BITMAP_BAND_CENTER_FREQ2 0x00020000 // same as above +#define LPI_IE_BITMAP_PHY_MODE 0x00040000 // PHY mode indicates a, b, ,g, ac and other combinations +#define LPI_IE_BITMAP_SCAN_MODULE_ID 0x00080000 // scan module id indicates the scan client who originated the scan +#define LPI_IE_BITMAP_SCAN_ID 0x00100000 // extscan inserts the scan cycle count for this value; other scan clients can insert the scan id of the scan, if needed. +#define LPI_IE_BITMAP_FLAGS 0x00200000 // reserved as a bitmap to indicate more scan information; one such use being to indicate if the on-going scan is interrupted or not +#define LPI_IE_BITMAP_CACHING_REQD 0x00400000 // extscan will use this field to indicate if this frame info needs to be cached in LOWI LP or not +#define LPI_IE_BITMAP_ALL 0xFFFFFFFF + +typedef struct { + A_UINT32 tlv_header; + /**A_BOOL indicates LPI mgmt snooping enable/disable*/ + A_UINT32 enable; + /**LPI snooping mode*/ + A_UINT32 snooping_mode; + /** LPI interested IEs in snooping context */ + A_UINT32 ie_bitmap; +} wmi_lpi_mgmt_snooping_config_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param */ + /** Scan ID */ + A_UINT32 scan_id; + /** Scan requestor ID */ + A_UINT32 scan_req_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** LPI interested IEs in scan context */ + A_UINT32 ie_bitmap; + /** Scan Priority, input to scan scheduler */ + A_UINT32 scan_priority; + /** dwell time in msec on active channels */ + A_UINT32 dwell_time_active; + /** dwell time in msec on passive channels */ + A_UINT32 dwell_time_passive; + /** min time in msec on the BSS channel,only valid if atleast one VDEV is active*/ + A_UINT32 min_rest_time; + /** max rest time in msec on the BSS channel,only valid if at least one VDEV is active*/ + /** the scanner will rest on the bss channel at least min_rest_time. after min_rest_time the scanner + * will start checking for tx/rx activity on all VDEVs. if there is no activity the scanner will + * switch to off channel. if there is activity the scanner will let the radio on the bss channel + * until max_rest_time expires.at max_rest_time scanner will switch to off channel + * irrespective of activity. activity is determined by the idle_time parameter. + */ + A_UINT32 max_rest_time; + /** time before sending next set of probe requests. + * The scanner keeps repeating probe requests transmission with period specified by repeat_probe_time. + * The number of probe requests specified depends on the ssid_list and bssid_list + */ + A_UINT32 repeat_probe_time; + /** time in msec between 2 consequetive probe requests with in a set. */ + A_UINT32 probe_spacing_time; + /** data inactivity time in msec on bss channel that will be used by scanner for measuring the inactivity */ + A_UINT32 idle_time; + /** maximum time in msec allowed for scan */ + A_UINT32 max_scan_time; + /** delay in msec before sending first probe request after switching to a channel */ + A_UINT32 probe_delay; + /** Scan control flags */ + A_UINT32 scan_ctrl_flags; + /** Burst duration time in msec*/ + A_UINT32 burst_duration; + + /** # if channels to scan. In the TLV channel_list[] */ + A_UINT32 num_chan; + /** number of bssids. In the TLV bssid_list[] */ + A_UINT32 num_bssid; + /** number of ssid. In the TLV ssid_list[] */ + A_UINT32 num_ssids; + /** number of bytes in ie data. In the TLV ie_data[] */ + A_UINT32 ie_len; + +/** + * TLV (tag length value ) parameters follow the scan_cmd + * structure. The TLV's are: + * A_UINT32 channel_list[]; + * wmi_ssid ssid_list[]; + * wmi_mac_addr bssid_list[]; + * A_UINT8 ie_data[]; + */ +} wmi_lpi_start_scan_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param */ + /** Scan requestor ID */ + A_UINT32 scan_req_id; + /** Scan ID */ + A_UINT32 scan_id; + /** + * Req Type + * req_type should be WMI_SCAN_STOP_ONE, WMI_SCN_STOP_VAP_ALL or WMI_SCAN_STOP_ALL + * WMI_SCAN_STOP_ONE indicates to stop a specific scan with scan_id + * WMI_SCN_STOP_VAP_ALL indicates to stop all scan requests on a specific vDev with vdev_id + * WMI_SCAN_STOP_ALL indicates to stop all scan requests in both Scheduler's queue and Scan Engine + */ + A_UINT32 req_type; + /** + * vDev ID + * used when req_type equals to WMI_SCN_STOP_VAP_ALL, it indexed the vDev on which to stop the scan + */ + A_UINT32 vdev_id; +} wmi_lpi_stop_scan_cmd_fixed_param; + +typedef enum { + WMI_LPI_DEVICE_TYPE_AP = 1, + WMI_LPI_DEVICE_TYPE_P2P = 2, + WMI_LPI_DEVICE_TYPE_NAN = 3, +}wmi_lpi_device_type; + +typedef struct +{ + A_UINT32 tlv_header; + /** Scan requestor ID */ + A_UINT32 scan_req_id; + A_UINT32 ie_bitmap; + A_UINT32 data_len; +} wmi_lpi_result_event_fixed_param; + +typedef enum { + /** User scan Request completed */ + WMI_LPI_STATUS_SCAN_REQ_COMPLED = 0, + /** User Request was never serviced */ + WMI_LPI_STATUS_DROPPED_REQ = 1, + /** Illegal channel Req */ + WMI_LPI_STATUS_ILLEGAL_CHAN_REQ = 2, + /** Illegal Operation Req */ + WMI_LPI_STATUS_ILLEGAL_OPER_REQ = 3, + /** Request Aborted */ + WMI_LPI_STATUS_REQ_ABORTED = 4, + /** Request Timed Out */ + WMI_LPI_STATUS_REQ_TIME_OUT = 5, + /** Medium Busy, already there + * is a scan is going on */ + WMI_LPI_STATUS_MEDIUM_BUSY = 6, + /** Extscan is the scan client whose scan complete event is triggered */ + WMI_LPI_STATUS_EXTSCAN_CYCLE_AND_SCAN_REQ_COMPLETED = 7, +}wmi_lpi_staus; + +typedef struct +{ + A_UINT32 tlv_header; + wmi_lpi_staus status; + /** Scan requestor ID */ + A_UINT32 scan_req_id; +} wmi_lpi_status_event_fixed_param; + + +typedef struct +{ + A_UINT32 tlv_header; + wmi_mac_addr bssid; + wmi_ssid ssid; + A_UINT32 freq; + A_UINT32 rssi; + A_UINT32 vdev_id; +} wmi_lpi_handoff_event_fixed_param; + +typedef struct +{ + A_UINT32 tlv_header; + A_UINT32 timestamp; /*timestamp of batch scan event*/ + A_UINT32 numScanLists; /*number of scan in this event*/ + A_UINT32 isLastResult; /*is this event a last event of the whole batch scan*/ +} wmi_batch_scan_result_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_p2p_noa_event_fixed_param */ + A_UINT32 vdev_id; + /* This TLV is followed by p2p_noa_info for vdev : + * wmi_p2p_noa_info p2p_noa_info; + */ +} wmi_p2p_noa_event_fixed_param; + +#define WMI_RFKILL_CFG_RADIO_LEVEL_OFFSET 6 +#define WMI_RFKILL_CFG_RADIO_LEVEL_MASK 0x1 + +#define WMI_RFKILL_CFG_GPIO_PIN_NUM_OFFSET 0 +#define WMI_RFKILL_CFG_GPIO_PIN_NUM_MASK 0x3f + +#define WMI_RFKILL_CFG_PIN_AS_GPIO_OFFSET 7 +#define WMI_RFKILL_CFG_PIN_AS_GPIO_MASK 0xf + +typedef struct { + /** TLV tag and len; tag equals + * */ + A_UINT32 tlv_header; + /** gpip pin number */ + A_UINT32 gpio_pin_num; + /** gpio interupt type */ + A_UINT32 int_type; + /** RF radio status */ + A_UINT32 radio_state; +} wmi_rfkill_mode_param; + +typedef enum { + WMI_SET_LED_SYS_POWEROFF, + WMI_SET_LED_SYS_S3_SUSPEND, + WMI_SET_LED_SYS_S4_S5, + WMI_SET_LED_SYS_DRIVER_DISABLE, + WMI_SET_LED_SYS_WAKEUP, + WMI_SET_LED_SYS_ALWAYS_ON, //just for test! + WMI_SET_LED_SYS_POWERON, +} wmi_led_sys_state_param; + +typedef enum { + WMI_CONFIG_LED_TO_VDD = 0, + WMI_CONFIG_LED_TO_GND = 1, +} wmi_config_led_connect_type; + +typedef enum { + WMI_CONFIG_LED_NOT_WITH_BT = 0, + WMI_CONFIG_LED_WITH_BT = 1, +} wmi_config_led_with_bt_flag; + +typedef enum { + WMI_CONFIG_LED_DISABLE = 0, + WMI_CONFIG_LED_ENABLE = 1, +} wmi_config_led_enable_flag; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param */ + A_UINT32 tlv_header; + /* Set GPIO pin */ + A_UINT32 led_gpio_pin; + /* Set connect type defined in wmi_config_led_connect_type */ + A_UINT32 connect_type; + /* Set flag defined in wmi_config_led_with_bt_flag*/ + A_UINT32 with_bt; + /* Set LED enablement defined in wmi_config_led_enable_flag */ + A_UINT32 led_enable; +} wmi_pdev_set_led_config_cmd_fixed_param; + +#define WMI_WNTS_CFG_GPIO_PIN_NUM_OFFSET 0 +#define WMI_WNTS_CFG_GPIO_PIN_NUM_MASK 0xff + +/** WMI_PEER_INFO_REQ_CMDID + * Request FW to provide peer info */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param */ + A_UINT32 tlv_header; + /** In order to get the peer info for a single peer, host shall + * issue the peer_mac_address of that peer. For getting the + * info all peers, the host shall issue 0xFFFFFFFF as the mac + * address. The firmware will return the peer info for all the + * peers on the specified vdev_id */ + wmi_mac_addr peer_mac_address; + /** vdev id */ + A_UINT32 vdev_id; +} wmi_peer_info_req_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_peer_info */ + A_UINT32 tlv_header; + /** mac addr of the peer */ + wmi_mac_addr peer_mac_address; + /** data_rate of the peer */ + A_UINT32 data_rate; + /** rssi of the peer */ + A_UINT32 rssi; + /** tx fail count */ + A_UINT32 tx_fail_cnt; +} wmi_peer_info; + +/** FW response with the peer info */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_peer_info_event_fixed_param */ + A_UINT32 tlv_header; + /** number of peers in peer_info */ + A_UINT32 num_peers; + /* This TLV is followed by another TLV of array of structs + * wmi_peer_info peer_info[]; + */ +} wmi_peer_info_event_fixed_param; + +/** FW response when tx failure count has reached threshold + * for a peer */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_peer_tx_fail_cnt_thr_event_fixed_param */ + A_UINT32 tlv_header; + /** vdev id*/ + A_UINT32 vdev_id; + /** mac address */ + wmi_mac_addr peer_mac_address; + /** tx failure count- will eventually be removed and not used * */ + A_UINT32 tx_fail_cnt; + /** seq number of the nth tx_fail_event */ + A_UINT32 seq_no; +} wmi_peer_tx_fail_cnt_thr_event_fixed_param; + +enum wmi_rmc_mode { + /** Disable RMC */ + WMI_RMC_MODE_DISABLED = 0, + /** Enable RMC */ + WMI_RMC_MODE_ENABLED = 1, +}; + +/** Enable RMC transmitter functionality. Upon + * receiving this, the FW shall mutlicast frames with + * reliablity. This is a vendor + * proprietary feature. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param */ + A_UINT32 tlv_header; + /** vdev id*/ + A_UINT32 vdev_id; + /** enable_rmc contains values from enum wmi_rmc_mode; + * Default value: 0 (disabled) */ + A_UINT32 enable_rmc; +} wmi_rmc_set_mode_cmd_fixed_param; + +/** Configure transmission periodicity of action frames in a + * RMC network for the multicast transmitter */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param */ + A_UINT32 tlv_header; + /** vdev id */ + A_UINT32 vdev_id; + /** time period in milliseconds. Default: 300 ms. + An action frame indicating the current leader is transmitted by the + RMC transmitter once every 'periodity_msec' */ + A_UINT32 periodicity_msec; +} wmi_rmc_set_action_period_cmd_fixed_param; + +/** Optimise Leader selection process in RMC functionality. For + * Enhancement/Debug purposes only */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_rmc_config_cmd_fixed_param */ + A_UINT32 tlv_header; + /** vdev id */ + A_UINT32 vdev_id; + /** flags :: + * 0x0001 - Enable beacon averaging + * 0x0002 - Force leader selection + * 0x0004 - Enable Timer based leader switch + * 0x0008 - Use qos/NULL based for multicast reliability */ + A_UINT32 flags; + /** control leader change timeperiod (in seconds) */ + A_UINT32 peridocity_leader_switch; + /** control activity timeout value for data rx (in seconds) */ + A_UINT32 data_activity_timeout; + /** mac address of leader */ + wmi_mac_addr forced_leader_mac_addr; +} wmi_rmc_config_cmd_fixed_param; + +/** MHF is generally implemented in + * the kernel. To decrease system power consumption, the + * driver can enable offloading this to the chipset. In + * order for the offload, the firmware needs the routing table. + * The host shall plumb the routing table into FW. The firmware + * shall perform an IP address lookup and forward the packet to + * the next hop using next hop's mac address. This is a vendor + * proprietary feature. */ +enum wmi_mhf_ofl_mode { + /** Disable MHF offload */ + WMI_MHF_OFL_MODE_DISABLED = 0, + /** Enable MHF offload */ + WMI_MHF_OFL_MODE_ENABLED = 1, +}; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mhf_offload_set_mode_cmd_fixed_param */ + A_UINT32 tlv_header; + /** vdev id*/ + A_UINT32 vdev_id; + /** enable_mhf_ofl contains values from enum + * wmi_mhf_ofl_mode; Default value: 0 (disabled) */ + A_UINT32 enable_mhf_ofl; +} wmi_mhf_offload_set_mode_cmd_fixed_param; + +enum wmi_mhf_ofl_table_action { + /** Create MHF offload table in FW */ + WMI_MHF_OFL_TBL_CREATE = 0, + /** Append to existing MHF offload table */ + WMI_MHF_OFL_TBL_APPEND = 1, + /** Flush entire MHF offload table in FW */ + WMI_MHF_OFL_TBL_FLUSH = 2, +}; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mhf_offload_plumb_routing_table_cmd_fixed_param */ + A_UINT32 tlv_header; + /** vdev id*/ + A_UINT32 vdev_id; + /** action corresponds to values from enum + * wmi_mhf_ofl_table_action */ + A_UINT32 action; + /** number of entries in the table */ + A_UINT32 num_entries; +/** Followed by the variable length TLV + * wmi_mhf_offload_routing_table_entry entries[] */ +}wmi_mhf_offload_plumb_routing_table_cmd; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mhf_offload_routing_table_entry */ + A_UINT32 tlv_header; + /** Destination node's IP address */ + WMI_IPV4_ADDR dest_ipv4_addr; + /** Next hop node's MAC address */ + wmi_mac_addr next_hop_mac_addr; +}wmi_mhf_offload_routing_table_entry; + +typedef struct { + /** tlv tag and len, tag equals + * WMITLV_TAG_STRUC_wmi_dfs_radar_event */ + A_UINT32 tlv_header; + + /** full 64 tsf timestamp get from MAC tsf timer indicates + * the time that the radar event uploading to host, split + * it to high 32 bit and lower 32 bit in fulltsf_high and + * full_tsf_low + */ + A_UINT32 upload_fullts_low; + A_UINT32 upload_fullts_high; + + /** timestamp indicates the time when DFS pulse is detected + * equal to ppdu_end_ts - radar_pusle_summary_ts_offset + */ + A_UINT32 pulse_detect_ts; + + /** the duaration of the pulse in us */ + A_UINT32 pulse_duration; + + /** the center frequency of the radar pulse detected, KHz */ + A_UINT32 pulse_center_freq; + + /** bandwidth of current DFS channel, MHz */ + A_UINT32 ch_bandwidth; + + /** center channel frequency1 of current DFS channel, MHz */ + A_UINT16 ch_center_freq1; + + /** center channel frequency2 of current DFS channel, MHz, + * reserved for 160 BW mode + */ + A_UINT16 ch_center_freq2; + + /** flag to indicate if this pulse is chirp */ + A_UINT8 pulse_is_chirp; + + /** RSSI recorded in the ppdu */ + A_UINT8 rssi; + + /** extened RSSI info */ + A_UINT8 rssi_ext; + + /** pmac_id for the radar event */ + A_UINT8 pmac_id; + + /** index of peak magnitude bin (signed) */ + A_INT32 peak_sidx; + +} wmi_dfs_radar_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_thermal_mgmt_cmd_fixed_param */ + + /*Thermal thresholds*/ + A_UINT32 lower_thresh_degreeC; /* in degree C*/ + A_UINT32 upper_thresh_degreeC; /* in degree C*/ + + /*Enable/Disable Thermal Monitoring for Mitigation*/ + A_UINT32 enable; +} wmi_thermal_mgmt_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_thermal_mgmt_event_fixed_param */ + + A_UINT32 temperature_degreeC;/* temperature in degree C*/ +} wmi_thermal_mgmt_event_fixed_param; + +/** + * This command is sent from WLAN host driver to firmware to + * request firmware to configure auto shutdown timer in fw + * 0 - Disable <1-19600>-Enabled and timer value is seconds (86400 seconds = 1 day maximum> + */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_param */ + A_UINT32 timer_value; /** timer value; 0=disable */ +} wmi_host_auto_shutdown_cfg_cmd_fixed_param; + +enum wmi_host_auto_shutdown_reason { + WMI_HOST_AUTO_SHUTDOWN_REASON_UNKNOWN = 0, + WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY = 1, + WMI_HOST_AUTO_SHUTDOWN_REASON_MAX, +}; + +/* WMI_HOST_AUTO_SHUTDOWN_EVENTID */ +typedef struct{ + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_host_auto_shutdown_event_fixed_param */ + A_UINT32 shutdown_reason; /* value: wmi_host_auto_shutdown_reason */ +} wmi_host_auto_shutdown_event_fixed_param; + + +/** New WMI command to support TPC CHAINMASK ADJUSTMENT ACCORDING TO a set of conditions specified in the command. + * fw will save c tpc offset/chainmask along with conditions and adjust tpc/chainmask when condition meet. + * This command is only used by some customer for verification test. It is not for end-user. + * + * array of wmi_tpc_chainmask_config structures are passed with the command to specify multiple conditions. + * + * The set of conditions include bt status, stbc status, band, phy_mode, 1stream/2streams, channel, rate. when all these conditions meet, + * the output(tpc_offset,chainmask) will be applied on per packet basis. ack_offset is applied based on channel condtion only. When multiple + * conditions has the same channel ,then the first ack_offset will be applied. It is better for host driver to make sure the + * pair is unique. + * + * the conditions (bt status, stbc status, band, phy_mode, 1steam/2streams, tpc_offset, ack_offset, chainmask) are combinedi into a single word + * called basic_config_info by bitmap + * to save memory. And channel & rate info will be tracked by 'channel' field and 'rate0', 'rate1' field because of its large combination. + * + * 'rate bit' or 'channel bit' field of basic_config_info indicate validity of the channel and rate fields.if rate bit is 0 then the rate field + * is ignored. + * disable will remove preious conditions from FW. + * conditions from the later command will over write conditions stored from a previous command. + * + */ + +#define WMI_TPC_CHAINMASK_CONFIG_BT_ON_OFF 0 /** dont' care the bt status */ +#define WMI_TPC_CHAINMASK_CONFIG_BT_ON 1 /** apply only when bt on */ +#define WMI_TPC_CHAINMASK_CONFIG_BT_OFF 2 /** apply only when bt off */ +#define WMI_TPC_CHAINMASK_CONFIG_BT_RESV1 3 /** reserved */ + +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_DONT_CARE 0 /** don't care the chainmask */ +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_CHAIN0 1 /** force to use Chain0 to send */ +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_CHAIN1 2 /** force to use Chain1 to send */ +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_CHAIN0_CHAIN1 3 /** force to use Chain0 & Chain1 to send */ + +#define WMI_TPC_CHAINMASK_CONFIG_STBC_ON_OFF 0 /** don't care about stbc */ +#define WMI_TPC_CHAINMASK_CONFIG_STBC_ON 1 /** apply only when stbc on */ +#define WMI_TPC_CHAINMASK_CONFIG_STBC_OFF 2 /** apply only when stbc off */ +#define WMI_TPC_CHAINMASK_CONFIG_STBC_RESV1 3 /** reserved */ + +#define WMI_TPC_CHAINMASK_CONFIG_BAND_2G 0 /** 2G */ +#define WMI_TPC_CHAINMASK_CONFIG_BAND_5G 1 /** 5G */ + +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11B_2G 0 /** 11b 2G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11G_2G 1 /** 11g 2G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11N_2G 2 /** 11n 2G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11N_11AC_2G 3 /** 11n + 11ac 2G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11A_5G 4 /** 11a 5G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11N_5G 5 /** 11n 5G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11AC_5G 6 /** 11ac 5G */ +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11N_11AC_5G 7 /** 11n + 11ac 5G */ + +#define WMI_TPC_CHAINMASK_CONFIG_STREAM_1 0 /** 1 stream */ +#define WMI_TPC_CHAINMASK_CONFIG_STREAM_2 1 /** 2 streams */ + +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL_OFF 0 /** channel field is ignored */ +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL_ON 1 /** channel field needs to be checked */ + +#define WMI_TPC_CHAINMASK_CONFIG_RATE_OFF 0 /** rate field is ignored */ +#define WMI_TPC_CHAINMASK_CONFIG_RATE_ON 1 /** rate field needs to be checked */ + +/** Bit map definition for basic_config_info starts */ +#define WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET_S 0 +#define WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET (0x1f << WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET_S) +#define WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET) +#define WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET_SET(x,z) WMI_F_RMW(x,(z) & 0x1f,WMI_TPC_CHAINMASK_CONFIG_TPC_OFFSET) + +#define WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET_S 5 +#define WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET (0x1f << WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET_S) +#define WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET) +#define WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET_SET(x,z) WMI_F_RMW(x, (z) & 0x1f, WMI_TPC_CHAINMASK_CONFIG_ACK_OFFSET) + +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_S 10 +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK (0x3 << WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_S) +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_CHAINMASK) +#define WMI_TPC_CHAINMASK_CONFIG_CHAINMASK_SET(x,z) WMI_F_RMW(x, (z)&0x3, WMI_TPC_CHAINMASK_CONFIG_CHAINMASK) + +#define WMI_TPC_CHAINMASK_CONFIG_BT_S 12 +#define WMI_TPC_CHAINMASK_CONFIG_BT (0x3 << WMI_TPC_CHAINMASK_CONFIG_BT_S) +#define WMI_TPC_CHAINMASK_CONFIG_BT_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_BT) +#define WMI_TPC_CHAINMASK_CONFIG_BT_SET(x,z) WMI_F_RMW(x, (z)&0x3, WMI_TPC_CHAINMASK_CONFIG_BT) + +#define WMI_TPC_CHAINMASK_CONFIG_STBC_S 14 +#define WMI_TPC_CHAINMASK_CONFIG_STBC (0x3 << WMI_TPC_CHAINMASK_CONFIG_STBC_S) +#define WMI_TPC_CHAINMASK_CONFIG_STBC_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_STBC) +#define WMI_TPC_CHAINMASK_CONFIG_STBC_SET(x,z) WMI_F_RMW(x, (z)& 0x3, WMI_TPC_CHAINMASK_CONFIG_STBC) + +#define WMI_TPC_CHAINMASK_CONFIG_BAND_S 16 +#define WMI_TPC_CHAINMASK_CONFIG_BAND (0x1 << WMI_TPC_CHAINMASK_CONFIG_BAND_S) +#define WMI_TPC_CHAINMASK_CONFIG_BAND_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_BAND) +#define WMI_TPC_CHAINMASK_CONFIG_BAND_SET(x,z) WMI_F_RMW(x, (z) &0x1, WMI_TPC_CHAINMASK_CONFIG_BAND) + +#define WMI_TPC_CHAINMASK_CONFIG_STREAM_S 17 +#define WMI_TPC_CHAINMASK_CONFIG_STREAM (0x1 << WMI_TPC_CHAINMASK_CONFIG_STREAM_S) +#define WMI_TPC_CHAINMASK_CONFIG_STREAM_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_STREAM) +#define WMI_TPC_CHAINMASK_CONFIG_STREAM_SET(x,z) WMI_F_RMW(x, (z)&0x1, WMI_TPC_CHAINMASK_CONFIG_STREAM) + +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_S 18 +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE (0x7 << WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_S) +#define WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_PHY_MODE) +#define WMI_TPC_CHAINAMSK_CONFIG_PHY_MODE_SET(x,z) WMI_F_RMW(x, (z)&0x7, WMI_TPC_CHAINMASK_CONFIG_PHY_MODE) + +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL_S 21 +/* + * The deprecated old name (WMI_TPC_CHAINMASK_CONFIG_CHANNEL_EXIST) + * is temporarily maintained as an alias for the correct name + * (WMI_TPC_CHAINMASK_CONFIG_CHANNEL) + */ +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL_EXIST WMI_TPC_CHAINMASK_CONFIG_CHANNEL +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL (0x1 << WMI_TPC_CHAINMASK_CONFIG_CHANNEL_S) +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL_GET(x) WMI_F_MS(x,WMI_TPC_CHAINMASK_CONFIG_CHANNEL) +#define WMI_TPC_CHAINMASK_CONFIG_CHANNEL_SET(x,z) WMI_F_RMW(x, (z)&0x1, WMI_TPC_CHAINMASK_CONFIG_CHANNEL) + +#define WMI_TPC_CHAINMASK_CONFIG_RATE_S 22 +/* + * The deprecated old name (WMI_TPC_CHAINMASK_CONFIG_RATE_EXIST) + * is temporarily maintained as an alias for the correct name + * (WMI_TPC_CHAINMASK_CONFIG_RATE) + */ +#define WMI_TPC_CHAINMASK_CONFIG_RATE_EXIST WMI_TPC_CHAINMASK_CONFIG_RATE +#define WMI_TPC_CHAINMASK_CONFIG_RATE (0x1 << WMI_TPC_CHAINMASK_CONFIG_RATE_S) +#define WMI_TPC_CHAINMASK_CONFIG_RATE_GET(x) WMI_F_MS(x, WMI_TPC_CHAINMASK_CONFIG_RATE) +#define WMI_TPC_CHAINMASK_CONFIG_RATE_SET(x,z) WMI_F_RMW(x, (z)&0x1, WMI_TPC_CHAINMASK_CONFIG_RATE) + +/** Bit map definition for basic_config_info ends */ + +typedef struct{ + A_UINT32 tlv_header; + /** Basic condition defined as bit map above, bitmap is chosen to save memory. + * Bit0 ~ Bit4: tpc offset which will be adjusted if condtion matches, the unit is 0.5dB. bit4 indicates signed + * Bit5 ~ Bit9: ack offset which will be adjusted if condtion matches, the unit is 0.5dB. bit9 indicates signed + * Bit10 ~ Bit11: chainmask b'00: don't care, b'01: force to use chain0, b'10: force to use chain1, b'11: force to use chain0&chain1 + * Bit12 ~ Bit13: bt condition b'00: don't care, b'01: apply only when bt on, b'10: apply only when bt off, b'11: reserved + * Bit14 ~ Bit15: stbc condition b'00: don't care, b'01: apply only when stbc on, b'10: apply only when stbc off, b'11: reserved + * Bit16 : band condition b'0: 2G, b'1: 5G + * Bit17 : stream condition: b'0: 1 stream, b'1: 2 streams + * Bit18 ~ Bit20: phy mode condition: b'000: 11b 2g, b'001: 11g 2g, b'010: 11n 2g, b'011: 11n+11ac 2g, b'100: 11a, b'101: 11n 5g, b'110: 11ac 5g, b'111: 11n+11ac 5g + * Bit21 : channel bit, if this bit is 0, then the following channel field is ignored + * Bit22 : rate bit, if this bit is 0, then the following rate0&rate1 is ignored. + * Bit23 ~ Bit31: reserved + */ + A_UINT32 basic_config_info; + + /** channel mapping bit rule: The lower bit corresponds with smaller channel. + * it depends on Bit14 of basic_config_info + * Total 24 channels for 5G + * 36 40 44 48 52 56 60 64 100 104 108 112 116 120 124 128 132 136 140 149 153 157 161 165 + * Total 14 channels for 2G + * 1 ~ 14 + */ + A_UINT32 channel; + + /** rate mapping bit rule: The lower bit corresponds with lower rate. + * it depends on Bit16 ~ Bit18 of basic_config_info, "phy mode condition" + * Legacy rates , 11b, 11g, 11A + * 11n one stream ( ht20, ht40 ) 8+8 + * 11n two streams ( ht20, ht40 ) 8+8 + * 11ac one stream ( vht20, vht40, vht80 ) 10+10+10 + * 11ac two streams (vht20, vht40, vht80 ) 10+10+10 + */ + A_UINT32 rate0; + /** For example, for 11b, when rate0 equals 0x3, it means if actual_rate in [ "1Mbps", "2Mbps"] connection, the rate condition is true. + * For example, for 11g/11a, when rate0 equals 0xf0,it means "54Mbps", "48Mbps", "36Mbps", "24Mb's" is selected, while "18Mbps", "12Mbps", "9Mbps", "6Mbps" is not selected + */ + + /** only used for "11n+11ac" combined phy_mode, (WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11N_11AC_2G , WMI_TPC_CHAINMASK_CONFIG_PHY_MODE_11N_11AC_5G) in this case, 11n rates begins on rate0, while 11ac rates begins on rate1 + */ + A_UINT32 rate1; +} wmi_tpc_chainmask_config; + +#define WMI_TPC_CHAINMASK_CONFIG_DISABLE 0 /** control the off for the tpc & chainmask*/ +#define WMI_TPC_CHAINMASK_CONFIG_ENABLE 1 /** control the on for the tpc & chainmask*/ + +typedef struct{ + A_UINT32 tlv_header; + A_UINT32 enable; /** enable to set tpc & chainmask when condtions meet, 0: disabled, 1: enabled. */ + A_UINT32 num_tpc_chainmask_configs; + /** following this structure is num_tpc_chainmask_configs number of wmi_tpc_chainmask_config */ +} wmi_tpc_chainmask_config_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_nan_cmd_param */ + A_UINT32 data_len; /** length in byte of data[]. */ + /* This structure is used to send REQ binary blobs + * from application/service to firmware where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_nan_cmd_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_nan_event_hdr */ + A_UINT32 data_len; /** length in byte of data[]. */ + /* This structure is used to send REQ binary blobs + * from firmware to application/service where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_nan_event_hdr; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 num_data; + /* followed by WMITLV_TAG_ARRAY_BYTE */ +} wmi_diag_data_container_event_fixed_param; + +enum { + WMI_PDEV_PARAM_TXPOWER_REASON_NONE = 0, + WMI_PDEV_PARAM_TXPOWER_REASON_SAR, + WMI_PDEV_PARAM_TXPOWER_REASON_MAX +}; + +#define PDEV_PARAM_TXPOWER_VALUE_MASK 0x000000FF +#define PDEV_PARAM_TXPOWER_VALUE_SHIFT 0 + +#define PDEV_PARAM_TXPOWER_REASON_MASK 0x0000FF00 +#define PDEV_PARAM_TXPOWER_REASON_SHIFT 8 + +#define SET_PDEV_PARAM_TXPOWER_VALUE(txpower_param, value) \ + ((txpower_param) &= ~PDEV_PARAM_TXPOWER_VALUE_MASK, (txpower_param) |= ((value) << PDEV_PARAM_TXPOWER_VALUE_SHIFT)) + +#define SET_PDEV_PARAM_TXPOWER_REASON(txpower_param, value) \ + ((txpower_param) &= ~PDEV_PARAM_TXPOWER_REASON_MASK, (txpower_param) |= ((value) << PDEV_PARAM_TXPOWER_REASON_SHIFT)) + +#define GET_PDEV_PARAM_TXPOWER_VALUE(txpower_param) \ + (((txpower_param) & PDEV_PARAM_TXPOWER_VALUE_MASK) >> PDEV_PARAM_TXPOWER_VALUE_SHIFT) + +#define GET_PDEV_PARAM_TXPOWER_REASON(txpower_param) \ + (((txpower_param) & PDEV_PARAM_TXPOWER_REASON_MASK) >> PDEV_PARAM_TXPOWER_REASON_SHIFT) + +/** + * This command is sent from WLAN host driver to firmware to + * notify the current modem power state. Host would receive a + * message from modem when modem is powered on. Host driver + * would then send this command to firmware. Firmware would then + * power on WCI-2 (UART) interface for LTE/MWS Coex. + * + * This command is only applicable for APQ platform which has + * modem on the platform. If firmware doesn't support MWS Coex, + * this command can be dropped by firmware. + * + * This is a requirement from modem team that WCN can't toggle + * UART before modem is powered on. + */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param */ + A_UINT32 tlv_header; + + /** Modem power state parameter */ + A_UINT32 modem_power_state; +} wmi_modem_power_state_cmd_param; + +enum { + WMI_MODEM_STATE_OFF = 0, + WMI_MODEM_STATE_ON +}; + +#define WMI_ROAM_AUTH_STATUS_CONNECTED 0x1 /** connected, but not authenticated */ +#define WMI_ROAM_AUTH_STATUS_AUTHENTICATED 0x2 /** connected and authenticated */ + +/** WMI_ROAM_SYNCH_EVENT: roam synch event triggering the host propagation logic + generated whenever firmware roamed to new AP silently and + (a) If the host is awake, FW sends the event to the host immediately . + (b) If host is in sleep then either + (1) FW waits until host sends WMI_PDEV_RESUME_CMDID or WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID + command to FW (part of host wake up sequence from low power mode) before sending the event host. + (2) data/mgmt frame is received from roamed AP, which needs to return to host +*/ + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_key_material */ + A_UINT32 tlv_header; + + A_UINT8 kck[GTK_OFFLOAD_KCK_BYTES]; /* EAPOL-Key Key Confirmation Key (KCK) */ + A_UINT8 kek[GTK_OFFLOAD_KEK_BYTES]; /* EAPOL-Key Key Encryption Key (KEK) */ + A_UINT8 replay_counter[GTK_REPLAY_COUNTER_BYTES]; +} wmi_key_material; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_synch_event_fixed_param */ + /** Unique id identifying the VDEV on which roaming is done by firmware */ + A_UINT32 vdev_id; + /** auth_status: connected or authorized */ + A_UINT32 auth_status; + /* + * roam_reason: + * bits 0-3 for roam reason see WMI_ROAM_REASON_XXX + * bits 4-5 for subnet status see WMI_ROAM_SUBNET_CHANGE_STATUS_XXX. + */ + A_UINT32 roam_reason; + /** associated AP's rssi calculated by FW when reason code is WMI_ROAM_REASON_LOW_RSSI. not valid if roam_reason is BMISS */ + A_UINT32 rssi; + /** MAC address of roamed AP */ + wmi_mac_addr bssid; /* BSSID */ + /** whether the frame is beacon or probe rsp */ + A_UINT32 is_beacon; + /** the length of beacon/probe rsp */ + A_UINT32 bcn_probe_rsp_len; + /** the length of reassoc rsp */ + A_UINT32 reassoc_rsp_len; + /** + * TLV (tag length value ) parameters follows roam_synch_event + * The TLV's are: + * A_UINT8 bcn_probe_rsp_frame[]; length identified by bcn_probe_rsp_len + * A_UINT8 reassoc_rsp_frame[]; length identified by reassoc_rsp_len + * wmi_channel chan; + * wmi_key_material key; + * A_UINT32 status; subnet changed status not being used + * currently. will pass the information using roam_status. + **/ +} wmi_roam_synch_event_fixed_param; + +#define WMI_PEER_ESTIMATED_LINKSPEED_INVALID 0xFFFFFFFF + +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_ wmi_peer_get_estimated_linkspeed_cmd_fixed_param */ + A_UINT32 tlv_header; + /** MAC address of the peer for which the estimated link speed is required. */ + wmi_mac_addr peer_macaddr; +} wmi_peer_get_estimated_linkspeed_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_ wmi_peer_estimated_linkspeed_event_fixed_param */ + A_UINT32 tlv_header; + /** MAC address of the peer for which the estimated link speed is required. + */ + wmi_mac_addr peer_macaddr; + /* Estimated link speed in kbps. + * When est_linkspeed_kbps is not valid, the value is set to WMI_PEER_ESTIMATED_LINKSPEED_INVALID. + */ + A_UINT32 est_linkspeed_kbps; +} wmi_peer_estimated_linkspeed_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals */ + /* vdev ID */ + A_UINT32 vdev_id; + A_UINT32 data_len; /** length in byte of data[]. */ + /* This structure is used to send REQ binary blobs + * from application/service to firmware where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_req_stats_ext_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_stats1_event_fix_param */ + A_UINT32 vdev_id; /** vdev ID */ + A_UINT32 data_len; /** length in byte of data[]. */ + /* This structure is used to send REQ binary blobs + * from firmware to application/service where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_stats_ext_event_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_ wmi_peer_state_event_fixed_param */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; /* vdev ID */ + /* MAC address of the peer for which the estimated link speed is required.*/ + wmi_mac_addr peer_macaddr; + A_UINT32 state; /* peer state */ +} wmi_peer_state_event_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_assoc_conf_event_fixed_param */ + A_UINT32 tlv_header; + /* unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* peer MAC address */ + wmi_mac_addr peer_macaddr; +} wmi_peer_assoc_conf_event_fixed_param; + +enum { + WMI_2G4_HT40_OBSS_SCAN_PASSIVE = 0, /** scan_type: passive */ + WMI_2G4_HT40_OBSS_SCAN_ACTIVE, /** scan_type: active */ +}; + +typedef struct { + /** + * TLV tag and len; + * tag equals WMITLV_TAG_STRUC_wmi_obss_scan_enalbe_cmd_fixed_param + */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + /** + * active or passive. if active all the channels are actively scanned. + * if passive then all the channels are passively scanned + */ + A_UINT32 scan_type; + /** + * FW can perform multiple scans with in a OBSS scan interval. + * For each scan, + * if the scan is passive then obss_scan_passive_dwell is minimum dwell to be used for each channel , + * if the scan is active then obss_scan_active_dwell is minimum dwell to be used for each channel . + * The unit for these 2 parameters is TUs. + */ + A_UINT32 obss_scan_passive_dwell; + A_UINT32 obss_scan_active_dwell; + /** + * OBSS scan interval . FW needs to perform one or more OBSS scans within this interval and fulfill the + * both min and total per channel dwell time requirement + */ + A_UINT32 bss_channel_width_trigger_scan_interval; + /** + * FW can perform multiple scans with in a OBSS scan interval. + * For each scan, + * the total per channel dwell time across all scans with in OBSS scan interval should be + * atleast obss_scan_passive_total_per channel for passive scas and obss_scan_active_total_per channel + * for active scans and , + * The unit for these 2 parameters is TUs. + */ + A_UINT32 obss_scan_passive_total_per_channel; + A_UINT32 obss_scan_active_total_per_channel; + A_UINT32 bss_width_channel_transition_delay_factor; /** parameter to check exemption from scan */ + A_UINT32 obss_scan_activity_threshold; /** parameter to check exemption from scan */ + /** following two parameters used by FW to fill IEs when sending 20/40 coexistence action frame to AP */ + A_UINT32 forty_mhz_intolerant; /** STA 40M bandwidth intolerant capability */ + A_UINT32 current_operating_class; /** STA current operating class */ + /** length of 2.4GHz channel list to scan at, channel list in tlv->channels[] */ + A_UINT32 channel_len; + /** length of optional ie data to append to probe reqest when active scan, ie data in tlv->ie_field[] */ + A_UINT32 ie_len; +} wmi_obss_scan_enable_cmd_fixed_param; + +typedef struct { + /** + * TLV tag and len; + * tag equals WMITLV_TAG_STRUC_wmi_obss_scan_disalbe_cmd_fixed_param + */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; +} wmi_obss_scan_disable_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_offload_prb_rsp_tx_status_event_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** prb rsp tx status, values defined in enum WMI_FRAME_TX_STATUS */ + A_UINT32 tx_status; +}wmi_offload_prb_rsp_tx_status_event_fixed_param; + +typedef enum { + WMI_FRAME_TX_OK, /* frame tx ok */ + WMI_FRAME_TX_XRETRY, /* excessivley retried */ + WMI_FRAME_TX_DROP, /* frame dropped by FW due to resources */ + WMI_FRAME_TX_FILTERED, /* frame filtered by hardware */ +} WMI_FRAME_TX_STATUS; + +/** + * This command is sent from WLAN host driver to firmware to + * request firmware to send the latest channel avoidance range + * to host. + * + * This command is only applicable for APQ platform which has + * modem on the platform. If firmware doesn't support MWS Coex, + * this command can be dropped by firmware. + * + * Host would send this command to firmware to request a channel + * avoidance information update. + */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param */ + A_UINT32 tlv_header; +} wmi_chan_avoid_update_cmd_param; + +/* ExtScan operation mode */ +typedef enum { + WMI_EXTSCAN_MODE_NONE = 0x0000, + WMI_EXTSCAN_MODE_START = 0x0001, // ExtScan/TableMonitoring operation started + WMI_EXTSCAN_MODE_STOP = 0x0002, // ExtScan/TableMonitoring operation stopped + WMI_EXTSCAN_MODE_IGNORED = 0x0003, // ExtScan command ignored due to error +} wmi_extscan_operation_mode; + +/* Channel Mask */ +typedef enum { + WMI_CHANNEL_BAND_UNSPECIFIED = 0x0000, + WMI_CHANNEL_BAND_24 = 0x0001, // 2.4 channel + WMI_CHANNEL_BAND_5_NON_DFS = 0x0002, // 5G Channels (No DFS channels) + WMI_CHANNEL_BAND_DFS = 0x0004, // DFS channels +} wmi_channel_band_mask; + +typedef enum { + WMI_EXTSCAN_CYCLE_STARTED_EVENT = 0x0001, + WMI_EXTSCAN_CYCLE_COMPLETED_EVENT = 0x0002, + WMI_EXTSCAN_BUCKET_STARTED_EVENT = 0x0004, + WMI_EXTSCAN_BUCKET_COMPLETED_EVENT = 0x0008, + WMI_EXTSCAN_BUCKET_FAILED_EVENT = 0x0010, + WMI_EXTSCAN_BUCKET_OVERRUN_EVENT = 0x0020, + + WMI_EXTSCAN_EVENT_MAX = 0x8000 +} wmi_extscan_event_type; + +#define WMI_EXTSCAN_CYCLE_EVENTS_MASK (WMI_EXTSCAN_CYCLE_STARTED_EVENT | \ + WMI_EXTSCAN_CYCLE_COMPLETED_EVENT) + +#define WMI_EXTSCAN_BUCKET_EVENTS_MASK (WMI_EXTSCAN_BUCKET_STARTED_EVENT | \ + WMI_EXTSCAN_BUCKET_COMPLETED_EVENT | \ + WMI_EXTSCAN_BUCKET_FAILED_EVENT | \ + WMI_EXTSCAN_BUCKET_OVERRUN_EVENT) + +typedef enum { + WMI_EXTSCAN_NO_FORWARDING = 0x0000, + WMI_EXTSCAN_FORWARD_FRAME_TO_HOST = 0x0001 +} wmi_extscan_forwarding_flags; + +typedef enum { + WMI_EXTSCAN_USE_MSD = 0x0001, // Use Motion Sensor Detection */ + WMI_EXTSCAN_EXTENDED_BATCHING_EN = 0x0002, // Extscan LPASS extended batching feature is supported and enabled +} wmi_extscan_configuration_flags; + +typedef enum { + WMI_EXTSCAN_BUCKET_CACHE_RESULTS = 0x0001, // Cache the results of bucket whose configuration flags has this bit set +} wmi_extscan_bucket_configuration_flags; + +typedef enum { + WMI_EXTSCAN_STATUS_OK = 0, + WMI_EXTSCAN_STATUS_ERROR = 0x80000000, + WMI_EXTSCAN_STATUS_INVALID_PARAMETERS, + WMI_EXTSCAN_STATUS_INTERNAL_ERROR +} wmi_extscan_start_stop_status; + +typedef struct { + /** Request ID - to identify command. Cannot be 0 */ + A_UINT32 request_id; + /** Requestor ID - client requesting ExtScan */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; +} wmi_extscan_command_id; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /** channel number */ + A_UINT32 channel; + + /** dwell time in msec - use defaults if 0 */ + A_UINT32 min_dwell_time; + A_UINT32 max_dwell_time; + /** passive/active channel and other flags */ + A_UINT32 control_flags; // 0 => active, 1 => passive scan; ignored for DFS +} wmi_extscan_bucket_channel; + +/* Scan Bucket specification */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /** Bucket ID - 0-based */ + A_UINT32 bucket_id; + /** ExtScan events subscription - events to be reported to client (see wmi_extscan_event_type) */ + A_UINT32 notify_extscan_events; + /** Options to forward scan results - see wmi_extscan_forwarding_flags */ + A_UINT32 forwarding_flags; + /** ExtScan configuration flags - wmi_extscan__bucket_configuration_flags */ + A_UINT32 configuration_flags; + /** DEPRECATED member: multiplier to be applied to the periodic scan's base period */ + A_UINT32 base_period_multiplier; + /** dwell time in msec on active channels - use defaults if 0 */ + A_UINT32 min_dwell_time_active; + A_UINT32 max_dwell_time_active; + /** dwell time in msec on passive channels - use defaults if 0 */ + A_UINT32 min_dwell_time_passive; + A_UINT32 max_dwell_time_passive; + /** see wmi_channel_band_mask; when equal to WMI_CHANNEL_UNSPECIFIED, use channel list */ + A_UINT32 channel_band; + /** number of channels (if channel_band is WMI_CHANNEL_UNSPECIFIED) */ + A_UINT32 num_channels; + /** scan period upon start or restart of the bucket - periodicity of the bucket to begin with */ + A_UINT32 min_period; + /** period above which exponent is not applied anymore */ + A_UINT32 max_period; + /** back off value to be applied to bucket's periodicity after exp_max_step_count scan cycles + * new_bucket_period = last_bucket_period + last_exponent_period * exp_backoff + */ + A_UINT32 exp_backoff; + /** number of scans performed at a given periodicity after which exponential back off value is + * applied to current periodicity to obtain a newer one + */ + A_UINT32 exp_max_step_count; +/** Followed by the variable length TLV chan_list: + * wmi_extscan_bucket_channel chan_list[] */ +} wmi_extscan_bucket; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param */ + /** Request ID - to identify command. Cannot be 0 */ + A_UINT32 request_id; + /** Requestor ID - client requesting ExtScan */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous requests */ + A_UINT32 table_id; + /** Base period (milliseconds) used by scan buckets to define periodicity of the scans */ + A_UINT32 base_period; + /** Maximum number of iterations to run - one iteration is the scanning of the least frequent bucket */ + A_UINT32 max_iterations; + /** Options to forward scan results - see wmi_extscan_forwarding_flags */ + A_UINT32 forwarding_flags; + /** ExtScan configuration flags - wmi_extscan_configuration_flags */ + A_UINT32 configuration_flags; + /** ExtScan events subscription - bitmask indicating which events should be send to client (see wmi_extscan_event_type) */ + A_UINT32 notify_extscan_events; + /** Scan Priority, input to scan scheduler */ + A_UINT32 scan_priority; + /** Maximum number of BSSIDs to cache on each scan cycle */ + A_UINT32 max_bssids_per_scan_cycle; + /** Minimum RSSI value to report */ + A_UINT32 min_rssi; + /** Maximum table usage in percentage */ + A_UINT32 max_table_usage; + /** default dwell time in msec on active channels */ + A_UINT32 min_dwell_time_active; + A_UINT32 max_dwell_time_active; + /** default dwell time in msec on passive channels */ + A_UINT32 min_dwell_time_passive; + A_UINT32 max_dwell_time_passive; + /** min time in msec on the BSS channel,only valid if atleast one VDEV is active*/ + A_UINT32 min_rest_time; + /** max rest time in msec on the BSS channel,only valid if at least one VDEV is active*/ + /** the scanner will rest on the bss channel at least min_rest_time. after min_rest_time the scanner + * will start checking for tx/rx activity on all VDEVs. if there is no activity the scanner will + * switch to off channel. if there is activity the scanner will let the radio on the bss channel + * until max_rest_time expires.at max_rest_time scanner will switch to off channel + * irrespective of activity. activity is determined by the idle_time parameter. + */ + A_UINT32 max_rest_time; + /** time before sending next set of probe requests. + * The scanner keeps repeating probe requests transmission with period specified by repeat_probe_time. + * The number of probe requests specified depends on the ssid_list and bssid_list + */ + /** Max number of probes to be sent */ + A_UINT32 n_probes; + /** time in msec between 2 sets of probe requests. */ + A_UINT32 repeat_probe_time; + /** time in msec between 2 consequetive probe requests with in a set. */ + A_UINT32 probe_spacing_time; + /** data inactivity time in msec on bss channel that will be used by scanner for measuring the inactivity */ + A_UINT32 idle_time; + /** maximum time in msec allowed for scan */ + A_UINT32 max_scan_time; + /** delay in msec before sending first probe request after switching to a channel */ + A_UINT32 probe_delay; + /** Scan control flags */ + A_UINT32 scan_ctrl_flags; + /** Burst duration time in msec*/ + A_UINT32 burst_duration; + + /** number of bssids in the TLV bssid_list[] */ + A_UINT32 num_bssid; + /** number of ssid in the TLV ssid_list[] */ + A_UINT32 num_ssids; + /** number of bytes in TLV ie_data[] */ + A_UINT32 ie_len; + /** number of buckets in the TLV bucket_list[] */ + A_UINT32 num_buckets; + /** in number of scans, send notifications to host after these many scans */ + A_UINT32 report_threshold_num_scans; + /** number of channels in channel_list[] determined by the + sum of wmi_extscan_bucket.num_channels in array */ + +/** + * TLV (tag length value ) parameters follow the extscan_cmd + * structure. The TLV's are: + * wmi_ssid ssid_list[]; + * wmi_mac_addr bssid_list[]; + * A_UINT8 ie_data[]; + * wmi_extscan_bucket bucket_list[]; + * wmi_extscan_bucket_channel channel_list[]; + */ +} wmi_extscan_start_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param */ + /** Request ID - to match running command. 0 matches any request */ + A_UINT32 request_id; + /** Requestor ID - client requesting stop */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous requests */ + A_UINT32 table_id; +} wmi_extscan_stop_cmd_fixed_param; + +enum wmi_extscan_get_cached_results_flags { + WMI_EXTSCAN_GET_CACHED_RESULTS_FLAG_NONE = 0x0000, + WMI_EXTSCAN_GET_CACHED_RESULTS_FLAG_FLUSH_TABLE = 0x0001 +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param */ + /** request ID - used to correlate command with events */ + A_UINT32 request_id; + /** Requestor ID - client that requested results */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous requests */ + A_UINT32 table_id; + /** maximum number of results to be returned */ + A_UINT32 max_results; + /** flush BSSID list - wmi_extscan_get_cached_results_flags */ + A_UINT32 control_flags; // enum wmi_extscan_get_cached_results_flags +} wmi_extscan_get_cached_results_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_get_wlan_change_results_cmd_fixed_param */ + /** request ID - used to correlate command with events */ + A_UINT32 request_id; + /** Requestor ID - client that requested results */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous requests */ + A_UINT32 table_id; +} wmi_extscan_get_wlan_change_results_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /**bssid */ + wmi_mac_addr bssid; + /**channel number */ + A_UINT32 channel; + /**upper RSSI limit */ + A_UINT32 upper_rssi_limit; + /**lower RSSI limit */ + A_UINT32 lower_rssi_limit; +} wmi_extscan_wlan_change_bssid_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param */ + /** Request ID - to identify command. Cannot be 0 */ + A_UINT32 request_id; + /** Requestor ID - client requesting wlan change monitoring */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /** operation mode: start/stop */ + A_UINT32 mode; // wmi_extscan_operation_mode + /** number of rssi samples to store */ + A_UINT32 max_rssi_samples; + /** number of samples to use to calculate RSSI average */ + A_UINT32 rssi_averaging_samples; + /** number of scans to confirm loss of contact with RSSI */ + A_UINT32 lost_ap_scan_count; + /** number of out-of-range BSSIDs necessary to send event */ + A_UINT32 max_out_of_range_count; + /** total number of bssid signal descriptors (in all pages) */ + A_UINT32 total_entries; + /** index of the first bssid entry found in the TLV wlan_change_descriptor_list*/ + A_UINT32 first_entry_index; + /** number of bssid signal descriptors in this page */ + A_UINT32 num_entries_in_page; + /* Following this structure is the TLV: + * wmi_extscan_wlan_change_bssid_param wlan_change_descriptor_list[]; // number of elements given by field num_page_entries. + */ +} wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /**bssid */ + wmi_mac_addr bssid; + /**RSSI min threshold for reporting */ + A_UINT32 min_rssi; + /**Deprecated entry - channel number */ + A_UINT32 channel; + /** RSSI max threshold for reporting */ + A_UINT32 max_rssi; +} wmi_extscan_hotlist_entry; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param */ + /** Request ID - to identify command. Cannot be 0 */ + A_UINT32 request_id; + /** Requestor ID - client requesting hotlist monitoring */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /** operation mode: start/stop */ + A_UINT32 mode; // wmi_extscan_operation_mode + /**total number of bssids (in all pages) */ + A_UINT32 total_entries; + /**index of the first bssid entry found in the TLV wmi_extscan_hotlist_entry*/ + A_UINT32 first_entry_index; + /**number of bssids in this page */ + A_UINT32 num_entries_in_page; + /** number of consecutive scans to confirm loss of contact with AP */ + A_UINT32 lost_ap_scan_count; + /* Following this structure is the TLV: + * wmi_extscan_hotlist_entry hotlist[]; // number of elements given by field num_page_entries. + */ +} wmi_extscan_configure_hotlist_monitor_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /**ssid */ + wmi_ssid ssid; + /**band */ + A_UINT32 band; + /**RSSI threshold for reporting */ + A_UINT32 min_rssi; + A_UINT32 max_rssi; +} wmi_extscan_hotlist_ssid_entry; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param */ + /** Request ID - to identify command. Cannot be 0 */ + A_UINT32 request_id; + /** Requestor ID - client requesting hotlist ssid monitoring */ + A_UINT32 requestor_id; + /** VDEV id(interface) that is requesting scan */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /** operation mode: start/stop */ + A_UINT32 mode; // wmi_extscan_operation_mode + /**total number of ssids (in all pages) */ + A_UINT32 total_entries; + /**index of the first ssid entry found in the TLV wmi_extscan_hotlist_ssid_entry*/ + A_UINT32 first_entry_index; + /**number of ssids in this page */ + A_UINT32 num_entries_in_page; + /** number of consecutive scans to confirm loss of an ssid **/ + A_UINT32 lost_ap_scan_count; + /* Following this structure is the TLV: + * wmi_extscan_hotlist_ssid_entry hotlist_ssid[]; // number of elements given by field num_page_entries. + */ +} wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param; + + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /** size in bytes of scan cache entry */ + A_UINT32 scan_cache_entry_size; + /** maximum number of scan cache entries */ + A_UINT32 max_scan_cache_entries; + /** maximum number of buckets per extscan request */ + A_UINT32 max_buckets; + /** maximum number of BSSIDs that will be stored in each scan (best n/w as per RSSI) */ + A_UINT32 max_bssid_per_scan; + /** table usage level at which indication must be sent to host */ + A_UINT32 max_table_usage_threshold; +} wmi_extscan_cache_capabilities; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /** size in bytes of wlan change entry */ + A_UINT32 wlan_change_entry_size; + /** maximum number of entries in wlan change table */ + A_UINT32 max_wlan_change_entries; + /** number of RSSI samples used for averaging RSSI */ + A_UINT32 max_rssi_averaging_samples; + /** number of BSSID/RSSI entries (BSSID pointer, RSSI, timestamp) that device can hold */ + A_UINT32 max_rssi_history_entries; +} wmi_extscan_wlan_change_monitor_capabilities; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /** size in bytes of hotlist entry */ + A_UINT32 wlan_hotlist_entry_size; + /** maximum number of entries in wlan change table */ + A_UINT32 max_hotlist_entries; +} wmi_extscan_hotlist_monitor_capabilities; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_set_capabilities_cmd_fixed_param */ + /** Request ID - matches request ID used to start hot list monitoring */ + A_UINT32 request_id; + /** Requestor ID - client requesting stop */ + A_UINT32 requestor_id; + /** number of extscan caches */ + A_UINT32 num_extscan_cache_tables; + /** number of wlan change lists */ + A_UINT32 num_wlan_change_monitor_tables; + /** number of hotlists */ + A_UINT32 num_hotlist_monitor_tables; + /** if one sided rtt data collection is supported */ + A_UINT32 rtt_one_sided_supported; + /** if 11v data collection is supported */ + A_UINT32 rtt_11v_supported; + /** if 11mc data collection is supported */ + A_UINT32 rtt_ftm_supported; + /** number of extscan cache capabilities (one per table) */ + A_UINT32 num_extscan_cache_capabilities; + /** number of wlan change capabilities (one per table) */ + A_UINT32 num_extscan_wlan_change_capabilities; + /** number of extscan hotlist capabilities (one per table) */ + A_UINT32 num_extscan_hotlist_capabilities; + /* Following this structure is the TLV: + * wmi_extscan_cache_capabilities extscan_cache_capabilities; // number of capabilities given by num_extscan_caches + * wmi_extscan_wlan_change_monitor_capabilities wlan_change_capabilities; // number of capabilities given by num_wlan_change_monitor_tables + * wmi_extscan_hotlist_monitor_capabilities hotlist_capabilities; // number of capabilities given by num_hotlist_monitor_tables + */ +} wmi_extscan_set_capabilities_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param */ + /** Request ID - matches request ID used to start hot list monitoring */ + A_UINT32 request_id; + /** Requestor ID - client requesting capabilities */ + A_UINT32 requestor_id; +} wmi_extscan_get_capabilities_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param */ + /** Request ID of the operation that was started/stopped */ + A_UINT32 request_id; + /** Requestor ID of the operation that was started/stopped */ + A_UINT32 requestor_id; + /** VDEV id(interface) of the operation that was started/stopped */ + A_UINT32 vdev_id; + /** extscan WMI command */ + A_UINT32 command; + /** operation mode: start/stop */ + A_UINT32 mode; // wmi_extscan_operation_mode + /**success/failure */ + A_UINT32 status; // enum wmi_extscan_start_stop_status + /** table ID - to allow support for multiple simultaneous requests */ + A_UINT32 table_id; +} wmi_extscan_start_stop_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param */ + /** Request ID of the extscan operation that is currently running */ + A_UINT32 request_id; + /** Requestor ID of the extscan operation that is currently running */ + A_UINT32 requestor_id; + /** VDEV id(interface) of the extscan operation that is currently running */ + A_UINT32 vdev_id; + /** scan event (wmi_scan_event_type) */ + A_UINT32 event; // wmi_extscan_event_type + /** table ID - to allow support for multiple simultaneous requests */ + A_UINT32 table_id; + /**number of buckets */ + A_UINT32 num_buckets; + /* Following this structure is the TLV: + * A_UINT32 bucket_id[]; // number of elements given by field num_buckets. + */ +} wmi_extscan_operation_event_fixed_param; + +/* Types of extscan tables */ +typedef enum { + EXTSCAN_TABLE_NONE = 0, + EXTSCAN_TABLE_BSSID = 1, + EXTSCAN_TABLE_RSSI = 2, +} wmi_extscan_table_type; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param */ + /** Request ID of the extscan operation that is currently running */ + A_UINT32 request_id; + /** Requestor ID of the extscan operation that is currently running */ + A_UINT32 requestor_id; + /** VDEV id(interface) of the extscan operation that is currently running */ + A_UINT32 vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /**see wmi_extscan_table_type for table reporting usage */ + A_UINT32 table_type; + /**number of entries in use */ + A_UINT32 entries_in_use; + /**maximum number of entries in table */ + A_UINT32 maximum_entries; +} wmi_extscan_table_usage_event_fixed_param; + +typedef enum { + WMI_SCAN_STATUS_INTERRUPTED = 1 /* Indicates scan got interrupted i.e. aborted or pre-empted for a long time (> 1sec) + this can be used to discard scan results */ +} wmi_scan_status_flags; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /**RSSI */ + A_UINT32 rssi; + /**time stamp in milliseconds */ + A_UINT32 tstamp; + /** Extscan cycle during which this entry was scanned */ + A_UINT32 scan_cycle_id; + /** flag to indicate if the given result was obtained as part of interrupted (aborted/large time gap preempted) scan */ + A_UINT32 flags; +} wmi_extscan_rssi_info; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /**bssid */ + wmi_mac_addr bssid; + /**ssid */ + wmi_ssid ssid; + /**channel number */ + A_UINT32 channel; + /* capabilities */ + A_UINT32 capabilities; + /* beacon interval in TUs */ + A_UINT32 beacon_interval; + /**time stamp in milliseconds - time last seen */ + A_UINT32 tstamp; + /**flags - _tExtScanEntryFlags */ + A_UINT32 flags; + /**RTT in ns */ + A_UINT32 rtt; + /**rtt standard deviation */ + A_UINT32 rtt_sd; + /* rssi information */ + A_UINT32 number_rssi_samples; + /** IE length */ + A_UINT32 ie_length; // length of IE data +} wmi_extscan_wlan_descriptor; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param */ + /** Request ID of the WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID */ + A_UINT32 request_id; + /** Requestor ID of the WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID */ + A_UINT32 requestor_id; + /** VDEV id(interface) of the WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID */ + A_UINT32 vdev_id; + /** Request ID of the extscan operation that is currently running */ + A_UINT32 extscan_request_id; + /** Requestor ID of the extscan operation that is currently running */ + A_UINT32 extscan_requestor_id; + /** VDEV id(interface) of the extscan operation that is currently running */ + A_UINT32 extscan_vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /**current time stamp in seconds. Used to provide a baseline for the relative timestamps returned for each block and entry */ + A_UINT32 current_tstamp; + /**total number of bssids (in all pages) */ + A_UINT32 total_entries; + /**index of the first bssid entry found in the TLV wmi_extscan_wlan_descriptor*/ + A_UINT32 first_entry_index; + /**number of bssids in this page */ + A_UINT32 num_entries_in_page; + /* Followed by the variable length TLVs + * wmi_extscan_wlan_descriptor bssid_list[] + * wmi_extscan_rssi_info rssi_list[] + * A_UINT8 ie_list[] + */ +} wmi_extscan_cached_results_event_fixed_param; + +typedef enum { + EXTSCAN_WLAN_CHANGE_FLAG_NONE = 0x00, + EXTSCAN_WLAN_CHANGE_FLAG_OUT_OF_RANGE = 0x01, + EXTSCAN_WLAN_CHANGE_FLAG_AP_LOST = 0x02, +} wmi_extscan_wlan_change_flags; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + /**bssid */ + wmi_mac_addr bssid; + /**time stamp in milliseconds */ + A_UINT32 tstamp; + /**upper RSSI limit */ + A_UINT32 upper_rssi_limit; + /**lower RSSI limit */ + A_UINT32 lower_rssi_limit; + /** channel */ + A_UINT32 channel; /* in MHz */ + /**current RSSI average */ + A_UINT32 rssi_average; + /**flags - wmi_extscan_wlan_change_flags */ + A_UINT32 flags; + /**legnth of RSSI history to follow (number of values) */ + A_UINT32 num_rssi_samples; +} wmi_extscan_wlan_change_result_bssid; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param */ + /** Request ID of the WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID command that requested the results */ + A_UINT32 request_id; + /** Requestor ID of the WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID command that requested the results */ + A_UINT32 requestor_id; + /** VDEV id(interface) of the WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID command that requested the results */ + A_UINT32 vdev_id; + /** Request ID of the WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID command that configured the table */ + A_UINT32 config_request_id; + /** Requestor ID of the WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID command that configured the table */ + A_UINT32 config_requestor_id; + /** VDEV id(interface) of the WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID command that configured the table */ + A_UINT32 config_vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /**number of entries with RSSI out of range or BSSID not detected */ + A_UINT32 change_count; + /**total number of bssid signal descriptors (in all pages) */ + A_UINT32 total_entries; + /**index of the first bssid signal descriptor entry found in the TLV wmi_extscan_wlan_descriptor*/ + A_UINT32 first_entry_index; + /**number of bssids signal descriptors in this page */ + A_UINT32 num_entries_in_page; + /* Following this structure is the TLV: + * wmi_extscan_wlan_change_result_bssid bssid_signal_descriptor_list[]; // number of descriptors given by field num_entries_in_page. + * Following this structure is the list of RSSI values (each is an A_UINT8): + * A_UINT8 rssi_list[]; // last N RSSI values. + */ +} wmi_extscan_wlan_change_results_event_fixed_param; + +enum _tExtScanEntryFlags +{ + WMI_HOTLIST_FLAG_NONE = 0x00, + WMI_HOTLIST_FLAG_PRESENCE = 0x01, + WMI_HOTLIST_FLAG_DUPLICATE_SSID = 0x80, +}; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param */ + /** Request ID of the WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID that configured the table */ + A_UINT32 config_request_id; + /** Requestor ID of the WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID that configured the table */ + A_UINT32 config_requestor_id; + /** VDEV id(interface) of the WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID that configured the table */ + A_UINT32 config_vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /**total number of bssids (in all pages) */ + A_UINT32 total_entries; + /**index of the first bssid entry found in the TLV wmi_extscan_wlan_descriptor*/ + A_UINT32 first_entry_index; + /**number of bssids in this page */ + A_UINT32 num_entries_in_page; + /* Following this structure is the TLV: + * wmi_extscan_wlan_descriptor hotlist_match[]; // number of descriptors given by field num_entries_in_page. + */ +} wmi_extscan_hotlist_match_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param */ + /** Request ID of the WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID that configured the table */ + A_UINT32 config_request_id; + /** Requestor ID of the WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID that configured the table */ + A_UINT32 config_requestor_id; + /** VDEV id(interface) of the WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID that configured the table */ + A_UINT32 config_vdev_id; + /** table ID - to allow support for multiple simultaneous tables */ + A_UINT32 table_id; + /**total number of ssids (in all pages) */ + A_UINT32 total_entries; + /**index of the first ssid entry found in the TLV wmi_extscan_wlan_descriptor*/ + A_UINT32 first_entry_index; + /**number of ssids in this page */ + A_UINT32 num_entries_in_page; + /* Following this structure is the TLV: + * wmi_extscan_wlan_descriptor hotlist_match[]; // number of descriptors given by field num_entries_in_page. + */ +} wmi_extscan_hotlist_ssid_match_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param */ + /** Request ID of the WMI_EXTSCAN_GET_CAPABILITIES_CMDID */ + A_UINT32 request_id; + /** Requestor ID of the WMI_EXTSCAN_GET_CAPABILITIES_CMDID */ + A_UINT32 requestor_id; + /** VDEV id(interface) of the WMI_EXTSCAN_GET_CAPABILITIES_CMDID */ + A_UINT32 vdev_id; + /** number of extscan caches */ + A_UINT32 num_extscan_cache_tables; + /** number of wlan change lists */ + A_UINT32 num_wlan_change_monitor_tables; + /** number of hotlists */ + A_UINT32 num_hotlist_monitor_tables; + /** if one sided rtt data collection is supported */ + A_UINT32 rtt_one_sided_supported; + /** if 11v data collection is supported */ + A_UINT32 rtt_11v_supported; + /** if 11mc data collection is supported */ + A_UINT32 rtt_ftm_supported; + /** number of extscan cache capabilities (one per table) */ + A_UINT32 num_extscan_cache_capabilities; + /** number of wlan change capabilities (one per table) */ + A_UINT32 num_extscan_wlan_change_capabilities; + /** number of extscan hotlist capabilities (one per table) */ + A_UINT32 num_extscan_hotlist_capabilities; + /* max number of roaming ssid whitelist firmware can support */ + A_UINT32 num_roam_ssid_whitelist; + /* max number of blacklist bssid firmware can support */ + A_UINT32 num_roam_bssid_blacklist; + /* max number of preferred list firmware can support */ + A_UINT32 num_roam_bssid_preferred_list; + /* max number of hotlist ssids firmware can support */ + A_UINT32 num_extscan_hotlist_ssid; + /* max number of epno networks firmware can support */ + A_UINT32 num_epno_networks; + + /* Following this structure are the TLVs describing the capabilities of of the various types of lists. The FW theoretically + * supports multiple lists of each type. + * + * wmi_extscan_cache_capabilities extscan_cache_capabilities[] // capabilities of extscan cache (BSSID/RSSI lists) + * wmi_extscan_wlan_change_monitor_capabilities wlan_change_capabilities[] // capabilities of wlan_change_monitor_tables + * wmi_extscan_hotlist_monitor_capabilities hotlist_capabilities[] // capabilities of hotlist_monitor_tables + */ +} wmi_extscan_capabilities_event_fixed_param; + +/* WMI_D0_WOW_DISABLE_ACK_EVENTID */ +typedef struct{ + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_d0_wow_disable_ack_event_fixed_param */ + A_UINT32 reserved0; /* for future need */ +} wmi_d0_wow_disable_ack_event_fixed_param; + +/** WMI_PDEV_RESUME_EVENTID : generated in response to WMI_PDEV_RESUME_CMDID */ +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_resume_event_fixed_param */ + A_UINT32 rsvd; /* for future need */ +} wmi_pdev_resume_event_fixed_param; + + +/** value representing all modules */ +#define WMI_DEBUG_LOG_MODULE_ALL 0xffff + +/* param definitions */ + +/** + * Log level for a given module. Value contains both module id and log level. + * here is the bitmap definition for value. + * module Id : 16 + * Flags : reserved + * Level : 8 + * if odule Id is WMI_DEBUG_LOG_MODULE_ALL then log level is applied to all modules (global). + * WMI_DEBUG_LOG_MIDULE_ALL will overwrites per module level setting. + */ +#define WMI_DEBUG_LOG_PARAM_LOG_LEVEL 0x1 + +#define WMI_DBGLOG_SET_LOG_LEVEL(val,lvl) do { \ + (val) |= (lvl & 0xff); \ + } while(0) + +#define WMI_DBGLOG_GET_LOG_LEVEL(val) ((val) & 0xff) + +#define WMI_DBGLOG_SET_MODULE_ID(val,mid) do { \ + (val) |= ((mid & 0xffff) << 16); \ + } while(0) + +#define WMI_DBGLOG_GET_MODULE_ID(val) (( (val) >> 16) & 0xffff) + +/** + * Enable the debug log for a given vdev. Value is vdev id + */ +#define WMI_DEBUG_LOG_PARAM_VDEV_ENABLE 0x2 + + +/** + * Disable the debug log for a given vdev. Value is vdev id + * All the log level for a given VDEV is disabled except the ERROR log messages + */ + +#define WMI_DEBUG_LOG_PARAM_VDEV_DISABLE 0x3 + +/** + * set vdev enable bitmap. value is the vden enable bitmap + */ +#define WMI_DEBUG_LOG_PARAM_VDEV_ENABLE_BITMAP 0x4 + +/** + * set a given log level to all the modules specified in the module bitmap. + * and set the log levle for all other modules to DBGLOG_ERR. + * value: log levelt to be set. + * module_id_bitmap : identifies the modules for which the log level should be set and + * modules for which the log level should be reset to DBGLOG_ERR. + */ +#define WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP 0x5 + +#define NUM_MODULES_PER_ENTRY ((sizeof(A_UINT32)) << 3) + +#define WMI_MODULE_ENABLE(pmid_bitmap,mod_id) \ + ( (pmid_bitmap)[(mod_id)/NUM_MODULES_PER_ENTRY] |= \ + (1 << ((mod_id)%NUM_MODULES_PER_ENTRY)) ) + +#define WMI_MODULE_DISABLE(pmid_bitmap,mod_id) \ + ( (pmid_bitmap)[(mod_id)/NUM_MODULES_PER_ENTRY] &= \ + ( ~(1 << ((mod_id)%NUM_MODULES_PER_ENTRY)) ) ) + +#define WMI_MODULE_IS_ENABLED(pmid_bitmap,mod_id) \ + ( ((pmid_bitmap)[(mod_id)/NUM_MODULES_PER_ENTRY ] & \ + (1 << ((mod_id)%NUM_MODULES_PER_ENTRY)) ) != 0) + +#define MAX_MODULE_ID_BITMAP_WORDS 16 /* 16*32=512 module ids. should be more than sufficient */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_debug_log_config_cmd_fixed_param */ + A_UINT32 dbg_log_param; /** param types are defined above */ + A_UINT32 value; + /* The below array will follow this tlv ->fixed length module_id_bitmap[] + A_UINT32 module_id_bitmap[MAX_MODULE_ID_BITMAP_WORDS]; + */ +} wmi_debug_log_config_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_get_temperature_cmd_fixed_param */ + A_UINT32 param; /* Reserved for future use */ +} wmi_pdev_get_temperature_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_temperature_event_fixed_param */ + A_INT32 value; /* temprature value in Celcius degree */ +} wmi_pdev_temperature_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 enable; + A_UINT32 srv_ipv4; /* server IP */ + A_UINT32 start_lsb; /* starting address assigned to client */ + A_UINT32 num_client; /* number of clients we support */ +} wmi_set_dhcp_server_offload_cmd_fixed_param; + +typedef enum { + AP_RX_DATA_OFFLOAD = 0x00, + STA_RX_DATA_OFFLOAD = 0x01, +} wmi_ipa_offload_types; + +/** + * This command is sent from WLAN host driver to firmware for + * enabling/disabling IPA data-path offload features. + * + * + * Enabling data path offload to IPA(based on host INI configuration), example: + * when STA interface comes up, + * host->target: WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMD, + * (enable = 1, vdev_id = STA vdev id, offload_type = STA_RX_DATA_OFFLOAD) + * + * Disabling data path offload to IPA, example: + * host->target: WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMD, + * (enable = 0, vdev_id = STA vdev id, offload_type = STA_RX_DATA_OFFLOAD) + * + * + * This command is applicable only on the PCIE LL systems + * + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ipa_offload_enable_disable_cmd_fixed_param */ + A_UINT32 offload_type; /* wmi_ipa_offload_types enum values */ + A_UINT32 vdev_id; + A_UINT32 enable; /* 1 == enable, 0 == disable */ +} wmi_ipa_offload_enable_disable_cmd_fixed_param; + +typedef enum { + WMI_LED_FLASHING_PATTERN_NOT_CONNECTED = 0, + WMI_LED_FLASHING_PATTERN_CONNECTED = 1, + WMI_LED_FLASHING_PATTERN_RESERVED = 2, +} wmi_set_led_flashing_type; + +/** +The state of the LED GPIO control is determined by two 32 bit values(X_0 and X_1) to produce a 64 bit value. +Each 32 bit value consists of 4 bytes, where each byte defines the number of 50ms intervals that the GPIO will +remain at a predetermined state. The 64 bit value provides 8 unique GPIO timing intervals. The pattern starts +with the MSB of X_0 and continues to the LSB of X_1. After executing the timer interval of the LSB of X_1, the +pattern returns to the MSB of X_0 and repeats. The GPIO state for each timing interval alternates from Low to +High and the first interval of the pattern represents the time when the GPIO is Low. When a timing interval of +Zero is reached, it is skipped and moves on to the next interval. +*/ +typedef struct{ + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param */ + A_UINT32 pattern_id; /* pattern identifier */ + A_UINT32 led_x0; /* led flashing parameter0 */ + A_UINT32 led_x1; /* led flashing parameter1 */ + A_UINT32 gpio_num; /* GPIO number */ +} wmi_set_led_flashing_cmd_fixed_param; + +/** + * 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. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mdns_offload_cmd_fixed_param */ + A_UINT32 vdev_id; + A_UINT32 enable; +} wmi_mdns_offload_cmd_fixed_param; + +#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 + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mdns_set_fqdn_cmd_fixed_param */ + A_UINT32 vdev_id; + /** type of fqdn, general or unique */ + A_UINT32 type; + /** length of fqdn */ + A_UINT32 fqdn_len; + /* Following this structure is the TLV byte stream of fqdn data of length fqdn_len + * A_UINT8 fqdn_data[]; // fully-qualified domain name to check if match with the received queries + */ +} wmi_mdns_set_fqdn_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mdns_set_resp_cmd_fixed_param */ + A_UINT32 vdev_id; + /** Answer Resource Record count */ + A_UINT32 AR_count; + /** length of response */ + A_UINT32 resp_len; + /* Following this structure is the TLV byte stream of resp data of length resp_len + * A_UINT8 resp_data[]; // responses consisits of Resource Records + */ +} wmi_mdns_set_resp_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mdns_get_stats_cmd_fixed_param */ + A_UINT32 vdev_id; +} wmi_mdns_get_stats_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_mdns_stats_event_fixed_param */ + A_UINT32 vdev_id; + /** curTimestamp in milliseconds */ + A_UINT32 curTimestamp; + /** last received Query in milliseconds */ + A_UINT32 lastQueryTimestamp; + /** last sent Response in milliseconds */ + A_UINT32 lastResponseTimestamp; + /** stats of received queries */ + A_UINT32 totalQueries; + /** stats of macth queries */ + A_UINT32 totalMatches; + /** stats of responses */ + A_UINT32 totalResponses; + /** indicate the current status of mDNS offload */ + A_UINT32 status; +} wmi_mdns_stats_event_fixed_param; + +/** + * The purpose of the SoftAP authenticator offload is to offload the association and 4-way handshake process + * down to the firmware. When this feature is enabled, firmware can process the association/disassociation + * request and create/remove connection even host is suspended. + * 3 major components are offloaded: + * 1. ap-mlme. Firmware will process auth/deauth, association/disassociation request and send out response. + * 2. 4-way handshake. Firmware will send out m1/m3 and receive m2/m4. + * 3. key installation. Firmware will generate PMK from the psk info which is sent from the host and install PMK/GTK. + * Current implementation only supports WPA2 CCMP. + */ + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sap_ofl_enable_cmd_fixed_param */ + /** VDEV id(interface) of the WMI_SAP_OFL_ENABLE_CMDID */ + A_UINT32 vdev_id; + /** enable/disable sap auth offload */ + A_UINT32 enable; + /** sap ssid */ + wmi_ssid ap_ssid; + /** authentication mode (defined above) */ + A_UINT32 rsn_authmode; + /** unicast cipher set */ + A_UINT32 rsn_ucastcipherset; + /** mcast/group cipher set */ + A_UINT32 rsn_mcastcipherset; + /** mcast/group management frames cipher set */ + A_UINT32 rsn_mcastmgmtcipherset; + /** sap channel */ + A_UINT32 channel; + /** length of psk */ + A_UINT32 psk_len; + /* Following this structure is the TLV byte stream of wpa passphrase data of length psk_len + * A_UINT8 psk[]; + */ +} wmi_sap_ofl_enable_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sap_ofl_add_sta_event_fixed_param */ + /** VDEV id(interface) of the WMI_SAP_OFL_ADD_STA_EVENTID */ + A_UINT32 vdev_id; + /** aid (association id) of this station */ + A_UINT32 assoc_id; + /** peer station's mac addr */ + wmi_mac_addr peer_macaddr; + /** length of association request frame */ + A_UINT32 data_len; + /* Following this structure is the TLV byte stream of a whole association request frame of length data_len + * A_UINT8 bufp[]; + */ +} wmi_sap_ofl_add_sta_event_fixed_param; + +typedef enum { + SAP_OFL_DEL_STA_FLAG_NONE = 0x00, + SAP_OFL_DEL_STA_FLAG_RECONNECT = 0x01, +} wmi_sap_ofl_del_sta_flags; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sap_ofl_del_sta_event_fixed_param */ + /** VDEV id(interface) of the WMI_SAP_OFL_DEL_STA_EVENTID */ + A_UINT32 vdev_id; + /** aid (association id) of this station */ + A_UINT32 assoc_id; + /** peer station's mac addr */ + wmi_mac_addr peer_macaddr; + /** disassociation reason */ + A_UINT32 reason; + /** flags - wmi_sap_ofl_del_sta_flags */ + A_UINT32 flags; +} wmi_sap_ofl_del_sta_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sap_set_blacklist_param_cmd_fixed_param */ + A_UINT32 vdev_id; + /* Number of client failure connection attempt */ + A_UINT32 num_retry; + /* Time in milliseconds to record the client's failure connection attempts */ + A_UINT32 retry_allow_time_ms; + /* Time in milliseconds to drop the connection request if client is blacklisted */ + A_UINT32 blackout_time_ms; +} wmi_sap_set_blacklist_param_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_apfind_cmd_param */ + A_UINT32 data_len; /** length in byte of data[]. */ + /** This structure is used to send REQ binary blobs + * from application/service to firmware where Host drv is pass through . + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_apfind_cmd_param; + +typedef enum apfind_event_type_e { + APFIND_MATCH_EVENT = 0, + APFIND_WAKEUP_EVENT, +} APFIND_EVENT_TYPE; + +typedef struct { + A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_apfind_event_hdr */ + A_UINT32 event_type; /** APFIND_EVENT_TYPE */ + A_UINT32 data_len; /** length in byte of data[]. */ + /** This structure is used to send event binary blobs + * from firmware to application/service and Host drv. + * Following this structure is the TLV: + * A_UINT8 data[]; // length in byte given by field data_len. + */ +} wmi_apfind_event_hdr; + + +/** + * OCB DCC types and structures. + */ + +/** + * DCC types as described in ETSI TS 102 687 + * Type Format stepSize referenceValue numBits + * ------------------------------------------------------------------------- + * ndlType_acPrio INTEGER (0...7) 1 number 3 + * ndlType_controlLoop INTEGER (0...7) 1 0 3 + * ndlType_arrivalRate INTEGER (0..8191) 0.01 /s 0 13 + * ndlType_channelLoad INTEGER (0..1000) 0.1 % 0 % 10 + * ndlType_channelUse INTEGER (0..8000) 0.0125 % 0 % 13 + * ndlType_datarate INTEGER (0..7) Table 8 3 + * ndlType_distance INTEGER (0..4095) 1 m 0 12 + * ndlType_numberElements INTEGER (0..63) number 6 + * ndlType_packetDuration INTEGER (0..2047) TSYM 0 11 + * ndlType_packetInterval INTEGER (0..1023) 10 ms 0 10 + * ndlType_pathloss INTEGER (0..31) 0.1 1.0 5 + * ndlType_rxPower INTEGER (0..127) -0.5 dB -40 dBm 7 + * ndlType_snr INTEGER (0..127) 0.5 dB -10 dB 7 + * ndlType_timing INTEGER (0..4095) 10 ms 0 12 + * ndlType_txPower INTEGER (0..127) 0.5 dB -20 dBm 7 + * ndlType_ratio INTEGER (0..100) 1 % 0 % 7 + * ndlType_exponent INTEGER (0..100) 0.1 0 7 + * ndlType_queueStatus Enumeration Table A.2 1 + * ndlType_dccMechanism Bitset Table A.2 6 + * + * NOTE: All of following size macros (SIZE_NDLTYPE_ACPRIO through SIZE_BYTE) + * cannot be changed without breaking WMI compatibility. + * + * NOTE: For each of the types, one additional bit is allocated. This + * leftmost bit is used to indicate that the value is invalid. */ +#define SIZE_NDLTYPE_ACPRIO (1 + 3 ) +#define SIZE_NDLTYPE_CONTROLLOOP (1 + 3 ) +#define SIZE_NDLTYPE_ARRIVALRATE (1 + 13) +#define SIZE_NDLTYPE_CHANNELLOAD (1 + 10) +#define SIZE_NDLTYPE_CHANNELUSE (1 + 13) +#define SIZE_NDLTYPE_DATARATE (1 + 3 ) +#define SIZE_NDLTYPE_DISTANCE (1 + 12) +#define SIZE_NDLTYPE_NUMBERELEMENTS (1 + 6 ) +#define SIZE_NDLTYPE_PACKETDURATION (1 + 11) +#define SIZE_NDLTYPE_PACKETINTERVAL (1 + 10) +#define SIZE_NDLTYPE_PATHLOSS (1 + 5 ) +#define SIZE_NDLTYPE_RXPOWER (1 + 7 ) +#define SIZE_NDLTYPE_SNR (1 + 7 ) +#define SIZE_NDLTYPE_TIMING (1 + 12) +#define SIZE_NDLTYPE_TXPOWER (1 + 7 ) +#define SIZE_NDLTYPE_RATIO (1 + 7 ) +#define SIZE_NDLTYPE_EXPONENT (1 + 7 ) +#define SIZE_NDLTYPE_QUEUESTATUS (1 + 1 ) +#define SIZE_NDLTYPE_DCCMECHANISM (1 + 6 ) +#define SIZE_BYTE (8) + +#define INVALID_ACPRIO ((1 << SIZE_NDLTYPE_ACPRIO) - 1) +#define INVALID_CONTROLLOOP ((1 << SIZE_NDLTYPE_CONTROLLOOP) - 1) +#define INVALID_ARRIVALRATE ((1 << SIZE_NDLTYPE_ARRIVALRATE) - 1) +#define INVALID_CHANNELLOAD ((1 << SIZE_NDLTYPE_CHANNELLOAD) - 1) +#define INVALID_CHANNELUSE ((1 << SIZE_NDLTYPE_CHANNELUSE) - 1) +#define INVALID_DATARATE ((1 << SIZE_NDLTYPE_DATARATE) - 1) +#define INVALID_DISTANCE ((1 << SIZE_NDLTYPE_DISTANCE) - 1) +#define INVALID_NUMBERELEMENTS ((1 << SIZE_NDLTYPE_NUMBERELEMENTS) - 1) +#define INVALID_PACKETDURATION ((1 << SIZE_NDLTYPE_PACKETDURATION) - 1) +#define INVALID_PACKETINTERVAL ((1 << SIZE_NDLTYPE_PACKETINTERVAL) - 1) +#define INVALID_PATHLOSS ((1 << SIZE_NDLTYPE_PATHLOSS) - 1) +#define INVALID_RXPOWER ((1 << SIZE_NDLTYPE_RXPOWER) - 1) +#define INVALID_SNR ((1 << SIZE_NDLTYPE_SNR) - 1) +#define INVALID_TIMING ((1 << SIZE_NDLTYPE_TIMING) - 1) +#define INVALID_TXPOWER ((1 << SIZE_NDLTYPE_TXPOWER) - 1) +#define INVALID_RATIO ((1 << SIZE_NDLTYPE_RATIO) - 1) +#define INVALID_EXPONENT ((1 << SIZE_NDLTYPE_EXPONENT) - 1) +#define INVALID_QUEUESTATS ((1 << SIZE_NDLTYPE_QUEUESTATUS) - 1) +#define INVALID_DCCMECHANISM ((1 << SIZE_NDLTYPE_DCCMECHANISM) - 1) + +/** The MCS_COUNT macro cannot be modified without breaking + * WMI compatibility. */ +#define MCS_COUNT (8) + +/** Flags for ndlType_dccMechanism. */ +typedef enum { + DCC_MECHANISM_TPC = 1, + DCC_MECHANISM_TRC = 2, + DCC_MECHANISM_TDC = 4, + DCC_MECHANISM_DSC = 8, + DCC_MECHANISM_TAC = 16, + DCC_MECHANISM_RESERVED = 32, + DCC_MECHANISM_ALL = 0x3f, +} wmi_dcc_ndl_type_dcc_mechanism; + +/** Values for ndlType_queueStatus. */ +typedef enum { + DCC_QUEUE_CLOSED = 0, + DCC_QUEUE_OPEN = 1, +} wmi_dcc_ndl_type_queue_status; + +/** For ndlType_acPrio, use the values in wmi_traffic_ac. */ + +/** Values for ndlType_datarate */ +typedef enum { + DCC_DATARATE_3_MBPS = 0, + DCC_DATARATE_4_5_MBPS = 1, + DCC_DATARATE_6_MBPS = 2, + DCC_DATARATE_9_MBPS = 3, + DCC_DATARATE_12_MBPS = 4, + DCC_DATARATE_18_MBPS = 5, + DCC_DATARATE_24_MBPS = 6, + DCC_DATARATE_27_MBPS = 7, +} wmi_dcc_ndl_type_datarate; + +/** Data structure for active state configuration. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config */ + A_UINT32 tlv_header; + /** + * NDL_asStateId, ndlType_numberElements, 1+6 bits. + * NDL_asChanLoad, ndlType_channelLoad, 1+10 bits. + */ + A_UINT32 state_info; + /** + * NDL_asDcc(AC_BK), ndlType_dccMechanism, 1+6 bits. + * NDL_asDcc(AC_BE), ndlType_dccMechanism, 1+6 bits. + * NDL_asDcc(AC_VI), ndlType_dccMechanism, 1+6 bits. + * NDL_asDcc(AC_VO), ndlType_dccMechanism, 1+6 bits. + */ + A_UINT32 as_dcc[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_DCCMECHANISM)]; + + /** + * NDL_asTxPower(AC_BK), ndlType_txPower, 1+7 bits. + * NDL_asTxPower(AC_BE), ndlType_txPower, 1+7 bits. + * NDL_asTxPower(AC_VI), ndlType_txPower, 1+7 bits. + * NDL_asTxPower(AC_VO), ndlType_txPower, 1+7 bits. + */ + A_UINT32 as_tx_power_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_TXPOWER)]; + /** + * NDL_asPacketInterval(AC_BK), ndlType_packetInterval, 1+10 bits. + * NDL_asPacketInterval(AC_BE), ndlType_packetInterval, 1+10 bits. + * NDL_asPacketInterval(AC_VI), ndlType_packetInterval, 1+10 bits. + * NDL_asPacketInterval(AC_VO), ndlType_packetInterval, 1+10 bits. + */ + A_UINT32 as_packet_interval_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_PACKETINTERVAL)]; + /** + * NDL_asDatarate(AC_BK), ndlType_datarate, 1+3 bits. + * NDL_asDatarate(AC_BE), ndlType_datarate, 1+3 bits. + * NDL_asDatarate(AC_VI), ndlType_datarate, 1+3 bits. + * NDL_asDatarate(AC_VO), ndlType_datarate, 1+3 bits. + */ + A_UINT32 as_datarate_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_DATARATE)]; + /** + * NDL_asCarrierSense(AC_BK), ndlType_rxPower, 1+7 bits. + * NDL_asCarrierSense(AC_BE), ndlType_rxPower, 1+7 bits. + * NDL_asCarrierSense(AC_VI), ndlType_rxPower, 1+7 bits. + * NDL_asCarrierSense(AC_VO), ndlType_rxPower, 1+7 bits. + */ + A_UINT32 as_carrier_sense_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_RXPOWER)]; +} wmi_dcc_ndl_active_state_config; + +#define WMI_NDL_AS_STATE_ID_GET(ptr) WMI_GET_BITS((ptr)->state_info, 0, 7) +#define WMI_NDL_AS_STATE_ID_SET(ptr,val) WMI_SET_BITS((ptr)->state_info, 0, 7, val) +#define WMI_NDL_AS_CHAN_LOAD_GET(ptr) WMI_GET_BITS((ptr)->state_info, 7, 11) +#define WMI_NDL_AS_CHAN_LOAD_SET(ptr,val) WMI_SET_BITS((ptr)->state_info, 7, 11, val) +#define WMI_NDL_AS_DCC_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->as_dcc, acprio, SIZE_NDLTYPE_DCCMECHANISM) +#define WMI_NDL_AS_DCC_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->as_dcc, acprio, SIZE_NDLTYPE_DCCMECHANISM, val) +#define WMI_NDL_AS_TX_POWER_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->as_tx_power_ac, acprio, SIZE_NDLTYPE_TXPOWER) +#define WMI_NDL_AS_TX_POWER_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->as_tx_power_ac, acprio, SIZE_NDLTYPE_TXPOWER, val) +#define WMI_NDL_AS_PACKET_INTERVAL_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->as_packet_interval_ac, acprio, SIZE_NDLTYPE_PACKETINTERVAL) +#define WMI_NDL_AS_PACKET_INTERVAL_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->as_packet_interval_ac, acprio, SIZE_NDLTYPE_PACKETINTERVAL, val) +#define WMI_NDL_AS_DATARATE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->as_datarate_ac, acprio, SIZE_NDLTYPE_DATARATE) +#define WMI_NDL_AS_DATARATE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->as_datarate_ac, acprio, SIZE_NDLTYPE_DATARATE, val) +#define WMI_NDL_AS_CARRIER_SENSE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->as_carrier_sense_ac, acprio, SIZE_NDLTYPE_RXPOWER) +#define WMI_NDL_AS_CARRIER_SENSE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->as_carrier_sense_ac, acprio, SIZE_NDLTYPE_RXPOWER, val) + +/** Data structure for EDCA/QOS parameters. */ +typedef struct +{ + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_qos_parameter */ + A_UINT32 tlv_header; + /** Arbitration Inter-Frame Spacing. Range: 2-15 */ + A_UINT32 aifsn; + /** Contention Window minimum. Range: 1 - 10 */ + A_UINT32 cwmin; + /** Contention Window maximum. Range: 1 - 10 */ + A_UINT32 cwmax; +} wmi_qos_parameter; + +/** Data structure for information specific to a channel. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_channel */ + A_UINT32 tlv_header; + A_UINT32 bandwidth; /* MHz units */ + wmi_mac_addr mac_address; +} wmi_ocb_channel; + +/** Data structure for an element of the schedule array. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_schedule_element */ + A_UINT32 tlv_header; + A_UINT32 channel_freq; /* MHz units */ + A_UINT32 total_duration; /* ms units */ + A_UINT32 guard_interval; /* ms units */ +} wmi_ocb_schedule_element; + +/** Data structure for OCB configuration. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_set_config_cmd_fixed_param */ + A_UINT32 tlv_header; + /** VDEV id(interface) that is being configured */ + A_UINT32 vdev_id; + A_UINT32 channel_count; + A_UINT32 schedule_size; + A_UINT32 flags; + + /** This is followed by a TLV array of wmi_channel. */ + /** This is followed by a TLV array of wmi_ocb_channel. */ + /** This is followed by a TLV array of wmi_qos_parameter. */ + /** This is followed by a TLV array of wmi_dcc_ndl_chan. */ + /** This is followed by a TLV array of wmi_dcc_ndl_active_state_config. */ + /** This is followed by a TLV array of wmi_ocb_schedule_element. */ +} wmi_ocb_set_config_cmd_fixed_param; + +#define EXPIRY_TIME_IN_TSF_TIMESTAMP_OFFSET 0 +#define EXPIRY_TIME_IN_TSF_TIMESTAMP_MASK 1 + +#define WMI_OCB_EXPIRY_TIME_IN_TSF(ptr) \ + (((ptr)->flags & EXPIRY_TIME_IN_TSF_TIMESTAMP_MASK) >> EXPIRY_TIME_IN_TSF_TIMESTAMP_OFFSET) + +/** Data structure for the response to the WMI_OCB_SET_CONFIG_CMDID command. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_set_config_resp_event_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + A_UINT32 status; +} wmi_ocb_set_config_resp_event_fixed_param; + +/* SIZE_UTC_TIME and SIZE_UTC_TIME_ERROR cannot be modified without breaking + WMI compatibility. */ +#define SIZE_UTC_TIME (10) // The size of the utc time in bytes. +#define SIZE_UTC_TIME_ERROR (5) // The size of the utc time error in bytes. + +/** Data structure to set the UTC time. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_set_utc_time_cmd_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + /** 10 bytes of the utc time. */ + A_UINT32 utc_time[WMI_PACKED_ARR_SIZE(SIZE_UTC_TIME,SIZE_BYTE)]; + /** 5 bytes of the time error. */ + A_UINT32 time_error[WMI_PACKED_ARR_SIZE(SIZE_UTC_TIME_ERROR,SIZE_BYTE)]; +} wmi_ocb_set_utc_time_cmd_fixed_param; + +#define WMI_UTC_TIME_GET(ptr,byte_index) wmi_packed_arr_get_bits((ptr)->utc_time, byte_index, SIZE_BYTE) +#define WMI_UTC_TIME_SET(ptr,byte_index,val) wmi_packed_arr_set_bits((ptr)->utc_time, byte_index, SIZE_BYTE, val) +#define WMI_TIME_ERROR_GET(ptr,byte_index) wmi_packed_arr_get_bits((ptr)->time_error, byte_index, SIZE_BYTE) +#define WMI_TIME_ERROR_SET(ptr,byte_index,val) wmi_packed_arr_set_bits((ptr)->time_error, byte_index, SIZE_BYTE, val) + +/** Data structure start the timing advertisement. The template for the + * timing advertisement frame follows this structure in the WMI command. + */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_start_timing_advert_cmd_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + /** Number of times the TA is sent every 5 seconds. */ + A_UINT32 repeat_rate; + /** The frequency on which to transmit. */ + A_UINT32 channel_freq; /* MHz units */ + /** The offset into the template of the timestamp. */ + A_UINT32 timestamp_offset; + /** The offset into the template of the time value. */ + A_UINT32 time_value_offset; + /** The length of the timing advertisement template. The + * template is in the TLV data. */ + A_UINT32 timing_advert_template_length; + + /** This is followed by a binary array containing the TA template. */ +} wmi_ocb_start_timing_advert_cmd_fixed_param; + +/** Data structure to stop the timing advertisement. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_stop_timing_advert_cmd_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + A_UINT32 channel_freq; /* MHz units */ +} wmi_ocb_stop_timing_advert_cmd_fixed_param; + +/** Data structure for the request for WMI_OCB_GET_TSF_TIMER_CMDID. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_cmd_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + A_UINT32 reserved; +} wmi_ocb_get_tsf_timer_cmd_fixed_param; + +/** Data structure for the response to WMI_OCB_GET_TSF_TIMER_CMDID. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_resp_event_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + A_UINT32 tsf_timer_high; + A_UINT32 tsf_timer_low; +} wmi_ocb_get_tsf_timer_resp_event_fixed_param; + +/** Data structure for DCC stats configuration per channel. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_ndl_stats_per_channel */ + A_UINT32 tlv_header; + + /** The channel for which this applies, 16 bits. */ + /** The dcc_stats_bitmap, 8 bits. */ + A_UINT32 chan_info; + + /** Demodulation model parameters. */ + /** + * NDL_snrBackoff(MCS0), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS1), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS2), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS3), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS4), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS5), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS6), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS7), ndlType_snr, 1+7 bits. + */ + A_UINT32 snr_backoff_mcs[WMI_PACKED_ARR_SIZE(MCS_COUNT,SIZE_NDLTYPE_SNR)]; + + /** Communication ranges. */ + /** + * tx_power, ndlType_txPower, 1+7 bits. + * datarate, ndlType_datarate, 1+3 bits. + */ + A_UINT32 tx_power_datarate; + /** + * NDL_carrierSenseRange, ndlType_distance, 1+12 bits. + * NDL_estCommRange, ndlType_distance, 1+12 bits. + */ + A_UINT32 carrier_sense_est_comm_range; + + /** Channel load measures. */ + /** + * dccSensitivity, ndlType_rxPower, 1+7 bits. + * carrierSense, ndlType_rxPower, 1+7 bits. + * NDL_channelLoad, ndlType_channelLoad, 1+10 bits. + */ + A_UINT32 dcc_stats; + /** + * NDL_packetArrivalRate, ndlType_arrivalRate, 1+13 bits. + * NDL_packetAvgDuration, ndlType_packetDuration, 1+11 bits. + */ + A_UINT32 packet_stats; + /** + * NDL_channelBusyTime, ndlType_channelLoad, 1+10 bits. + */ + A_UINT32 channel_busy_time; + + /** Transmit packet statistics. */ + /** + * NDL_txPacketArrivalRate(AC_BK), ndlType_arrivalRate, 1+13 bits. + * NDL_txPacketArrivalRate(AC_BE), ndlType_arrivalRate, 1+13 bits. + * NDL_txPacketArrivalRate(AC_VI), ndlType_arrivalRate, 1+13 bits. + * NDL_txPacketArrivalRate(AC_VO), ndlType_arrivalRate, 1+13 bits. + */ + A_UINT32 tx_packet_arrival_rate_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_ARRIVALRATE)]; + /** + * NDL_txPacketAvgDuration(AC_BK), ndlType_packetDuration, 1+11 bits. + * NDL_txPacketAvgDuration(AC_BE), ndlType_packetDuration, 1+11 bits. + * NDL_txPacketAvgDuration(AC_VI), ndlType_packetDuration, 1+11 bits. + * NDL_txPacketAvgDuration(AC_VO), ndlType_packetDuration, 1+11 bits. + */ + A_UINT32 tx_packet_avg_duration_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_PACKETDURATION)]; + /** + * NDL_txChannelUse(AC_BK), ndlType_channelUse, 1+13 bits. + * NDL_txChannelUse(AC_BE), ndlType_channelUse, 1+13 bits. + * NDL_txChannelUse(AC_VI), ndlType_channelUse, 1+13 bits. + * NDL_txChannelUse(AC_VO), ndlType_channelUse, 1+13 bits. + */ + A_UINT32 tx_channel_use_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_CHANNELUSE)]; + /** + * NDL_txSignalAvgPower(AC_BK), ndlType_txPower, 1+7 bits. + * NDL_txSignalAvgPower(AC_BE), ndlType_txPower, 1+7 bits. + * NDL_txSignalAvgPower(AC_VI), ndlType_txPower, 1+7 bits. + * NDL_txSignalAvgPower(AC_VO), ndlType_txPower, 1+7 bits. + */ + A_UINT32 tx_signal_avg_power_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_TXPOWER)]; +} wmi_dcc_ndl_stats_per_channel; + +#define WMI_NDL_STATS_SNR_BACKOFF_GET(ptr,mcs) wmi_packed_arr_get_bits((ptr)->snr_backoff_mcs, mcs, SIZE_NDLTYPE_SNR) +#define WMI_NDL_STATS_SNR_BACKOFF_SET(ptr,mcs,val) wmi_packed_arr_set_bits((ptr)->snr_backoff_mcs, mcs, SIZE_NDLTYPE_SNR, val) + +#define WMI_NDL_STATS_CHAN_FREQ_GET(ptr) WMI_GET_BITS((ptr)->chan_info, 0, 16) +#define WMI_NDL_STATS_CHAN_FREQ_SET(ptr,val) WMI_SET_BITS((ptr)->chan_info, 0, 16, val) +#define WMI_NDL_STATS_DCC_STATS_BITMAP_GET(ptr) WMI_GET_BITS((ptr)->chan_info, 16, 8) +#define WMI_NDL_STATS_DCC_STATS_BITMAP_SET(ptr,val) WMI_SET_BITS((ptr)->chan_info, 16, 8, val) + +#define WMI_NDL_STATS_SNR_BACKOFF_GET(ptr,mcs) wmi_packed_arr_get_bits((ptr)->snr_backoff_mcs, mcs, SIZE_NDLTYPE_SNR) +#define WMI_NDL_STATS_SNR_BACKOFF_SET(ptr,mcs,val) wmi_packed_arr_set_bits((ptr)->snr_backoff_mcs, mcs, SIZE_NDLTYPE_SNR, val) + +#define WMI_TX_POWER_GET(ptr) WMI_GET_BITS((ptr)->tx_power_datarate, 0, 8) +#define WMI_TX_POWER_SET(ptr,val) WMI_SET_BITS((ptr)->tx_power_datarate, 0, 8, val) +#define WMI_TX_DATARATE_GET(ptr) WMI_GET_BITS((ptr)->tx_power_datarate, 0, 4) +#define WMI_TX_DATARATE_SET(ptr,val) WMI_SET_BITS((ptr)->tx_power_datarate, 0, 4, val) +#define WMI_NDL_CARRIER_SENSE_RANGE_GET(ptr) WMI_GET_BITS((ptr)->carrier_sense_est_comm_range, 0, 13) +#define WMI_NDL_CARRIER_SENSE_RANGE_SET(ptr,val) WMI_SET_BITS((ptr)->carrier_sense_est_comm_range, 0, 13, val) +#define WMI_NDL_EST_COMM_RANGE_GET(ptr) WMI_GET_BITS((ptr)->carrier_sense_est_comm_range, 13, 13) +#define WMI_NDL_EST_COMM_RANGE_SET(ptr,val) WMI_SET_BITS((ptr)->carrier_sense_est_comm_range, 13, 13, val) + +#define WMI_DCC_SENSITIVITY_GET(ptr) WMI_GET_BITS((ptr)->dcc_stats, 0, 8) +#define WMI_DCC_SENSITIVITY_SET(ptr,val) WMI_SET_BITS((ptr)->dcc_stats, 0, 8, val) +#define WMI_CARRIER_SENSE_GET(ptr) WMI_GET_BITS((ptr)->dcc_stats, 8, 8) +#define WMI_CARRIER_SENSE_SET(ptr,val) WMI_SET_BITS((ptr)->dcc_stats, 8, 8, val) +#define WMI_NDL_CHANNEL_LOAD_GET(ptr) WMI_GET_BITS((ptr)->dcc_stats, 16, 11) +#define WMI_NDL_CHANNEL_LOAD_SET(ptr,val) WMI_SET_BITS((ptr)->dcc_stats, 16, 11, val) +#define WMI_NDL_PACKET_ARRIVAL_RATE_GET(ptr) WMI_GET_BITS((ptr)->packet_stats, 0, 14) +#define WMI_NDL_PACKET_ARRIVAL_RATE_SET(ptr,val) WMI_SET_BITS((ptr)->packet_stats, 0, 14, val) +#define WMI_NDL_PACKET_AVG_DURATION_GET(ptr) WMI_GET_BITS((ptr)->packet_stats, 14, 12) +#define WMI_NDL_PACKET_AVG_DURATION_SET(ptr,val) WMI_SET_BITS((ptr)->packet_stats, 14, 12, val) +#define WMI_NDL_CHANNEL_BUSY_TIME_GET(ptr) WMI_GET_BITS((ptr)->channel_busy_time, 0, 11) +#define WMI_NDL_CHANNEL_BUSY_TIME_SET(ptr,val) WMI_SET_BITS((ptr)->channel_busy_time, 0, 11, val) + +#define WMI_NDL_TX_PACKET_ARRIVAL_RATE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tx_packet_arrival_rate_ac, acprio, SIZE_NDLTYPE_ARRIVALRATE) +#define WMI_NDL_TX_PACKET_ARRIVAL_RATE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tx_packet_arrival_rate_ac, acprio, SIZE_NDLTYPE_ARRIVALRATE, val) +#define WMI_NDL_TX_PACKET_AVG_DURATION_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tx_packet_avg_duration_ac, acprio, SIZE_NDLTYPE_PACKETDURATION) +#define WMI_NDL_TX_PACKET_AVG_DURATION_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tx_packet_avg_duration_ac, acprio, SIZE_NDLTYPE_PACKETDURATION, val) +#define WMI_NDL_TX_CHANNEL_USE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tx_channel_use_ac, acprio, SIZE_NDLTYPE_CHANNELUSE) +#define WMI_NDL_TX_CHANNEL_USE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tx_channel_use_ac, acprio, SIZE_NDLTYPE_CHANNELUSE, val) +#define WMI_NDL_TX_SIGNAL_AVG_POWER_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tx_signal_avg_power_ac, acprio, SIZE_NDLTYPE_TXPOWER) +#define WMI_NDL_TX_SIGNAL_AVG_POWER_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tx_signal_avg_power_ac, acprio, SIZE_NDLTYPE_TXPOWER, val) + +/** Bitmap for DCC stats. */ +typedef enum { + DCC_STATS_DEMODULATION_MODEL = 1, + DCC_STATS_COMMUNICATION_RANGES = 2, + DCC_STATS_CHANNEL_LOAD_MEASURES = 4, + DCC_STATS_TRANSMIT_PACKET_STATS = 8, + DCC_STATS_TRANSMIT_MODEL_PARAMETER = 16, + DCC_STATS_ALL = 0xff, +} wmi_dcc_stats_bitmap; + +/** Data structure for getting the DCC stats. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_get_stats_cmd_fixed_param */ + A_UINT32 tlv_header; + + /* VDEV identifier */ + A_UINT32 vdev_id; + + /** The number of channels for which stats are being requested. */ + A_UINT32 num_channels; + + /** This is followed by a TLV array of wmi_dcc_channel_stats_request. */ +} wmi_dcc_get_stats_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_channel_stats_request */ + A_UINT32 tlv_header; + + /** The channel for which this applies. */ + A_UINT32 chan_freq; /* MHz units */ + + /** The DCC stats being requested. */ + A_UINT32 dcc_stats_bitmap; +} wmi_dcc_channel_stats_request; + +/** Data structure for the response with the DCC stats. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_get_stats_resp_event_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + /** Number of channels in the response. */ + A_UINT32 num_channels; + /** This is followed by a TLV array of wmi_dcc_ndl_stats_per_channel. */ +} wmi_dcc_get_stats_resp_event_fixed_param; + +/** Data structure for clearing the DCC stats. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_clear_stats_cmd_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + A_UINT32 dcc_stats_bitmap; +} wmi_dcc_clear_stats_cmd_fixed_param; + +/** Data structure for the pushed DCC stats */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_stats_event_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + /** The number of channels in the response. */ + A_UINT32 num_channels; + + /** This is followed by a TLV array of wmi_dcc_ndl_stats_per_channel. */ +} wmi_dcc_stats_event_fixed_param; + +/** Data structure for updating NDL per channel. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_ndl_chan */ + A_UINT32 tlv_header; + + /** + * Channel frequency, 16 bits + * NDL_numActiveState, ndlType_numberElements, 1+6 bits + */ + A_UINT32 chan_info; + + /** + * NDL_minDccSampling, 10 bits. + * Maximum time interval between subsequent checks of the DCC rules. + */ + A_UINT32 ndl_min_dcc_sampling; + + /** + * dcc_enable, 1 bit. + * dcc_stats_enable, 1 bit. + * dcc_stats_interval, 16 bits. + */ + A_UINT32 dcc_flags; + + /** General DCC configuration. */ + /** + * NDL_timeUp, ndlType_timing, 1+12 bits. + * NDL_timeDown, ndlType_timing, 1+12 bits. + */ + A_UINT32 general_config; + + /** Transmit power thresholds. */ + /** + * NDL_minTxPower, ndlType_txPower, 1+7 bits. + * NDL_maxTxPower, ndlType_txPower, 1+7 bits. + */ + A_UINT32 min_max_tx_power; /* see "ETSI TS 102 687" table above for units */ + /** + * NDL_defTxPower(AC_BK), ndlType_txPower, 1+7 bits. + * NDL_defTxPower(AC_BE), ndlType_txPower, 1+7 bits. + * NDL_defTxPower(AC_VI), ndlType_txPower, 1+7 bits. + * NDL_defTxPower(AC_VO), ndlType_txPower, 1+7 bits. + */ + /* see "ETSI TS 102 687" table above for units */ + A_UINT32 def_tx_power_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_TXPOWER)]; + + /** Packet timing thresholds. */ + /** + * NDL_maxPacketDuration(AC_BK), ndlType_packetDuration, 1+11 bits. + * NDL_maxPacketDuration(AC_BE), ndlType_packetDuration, 1+11 bits. + * NDL_maxPacketDuration(AC_VI), ndlType_packetDuration, 1+11 bits. + * NDL_maxPacketDuration(AC_VO), ndlType_packetDuration, 1+11 bits. + */ + A_UINT32 max_packet_duration_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_PACKETDURATION)]; + /** + * NDL_minPacketInterval, ndlType_packetInterval, 1+10 bits. + * NDL_maxPacketInterval, ndlType_packetInterval, 1+10 bits. + */ + A_UINT32 min_max_packet_interval; + /** + * NDL_defPacketInterval(AC_BK), ndlType_packetInterval, 1+10 bits. + * NDL_defPacketInterval(AC_BE), ndlType_packetInterval, 1+10 bits. + * NDL_defPacketInterval(AC_VI), ndlType_packetInterval, 1+10 bits. + * NDL_defPacketInterval(AC_VO), ndlType_packetInterval, 1+10 bits. + */ + A_UINT32 def_packet_interval_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_PACKETINTERVAL)]; + + /** Packet datarate thresholds. */ + /** + * NDL_minDatarate, ndlType_datarate, 1+3 bits. + * NDL_maxDatarate, ndlType_datarate, 1+3 bits. + */ + A_UINT32 min_max_datarate; + /** + * NDL_defDatarate(AC_BK), ndlType_datarate, 1+3 bits. + * NDL_defDatarate(AC_BE), ndlType_datarate, 1+3 bits. + * NDL_defDatarate(AC_VI), ndlType_datarate, 1+3 bits. + * NDL_defDatarate(AC_VO), ndlType_datarate, 1+3 bits. + */ + A_UINT32 def_datarate_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC,SIZE_NDLTYPE_DATARATE)]; + + /** Receive signal thresholds. */ + /** + * NDL_minCarrierSense, ndlType_rxPower, 1+7 bits. + * NDL_maxCarrierSense, ndlType_rxPower, 1+7 bits. + * NDL_defCarrierSense, ndlType_rxPower, 1+7 bits. + */ + A_UINT32 min_max_def_carrier_sense; + + /** Receive model parameter. */ + /** + * NDL_defDccSensitivity, ndlType_rxPower, 1+7 bits. + * NDL_maxCsRange, ndlType_distance, 1+12 bits. + * NDL_refPathLoss, ndlType_pathloss, 1+5 bits. + */ + A_UINT32 receive_model_parameter; + + /** + * NDL_minSNR, ndlType_snr, 1+7 bits. + */ + A_UINT32 receive_model_parameter_2; + + /** Demodulation model parameters. */ + /** + * NDL_snrBackoff(MCS0), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS1), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS2), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS3), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS4), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS5), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS6), ndlType_snr, 1+7 bits. + * NDL_snrBackoff(MCS7), ndlType_snr, 1+7 bits. + */ + A_UINT32 snr_backoff_mcs[WMI_PACKED_ARR_SIZE(MCS_COUNT,SIZE_NDLTYPE_SNR)]; + + /** Transmit model parameters. */ + /** + * NDL_tmPacketArrivalRate(AC_BK), ndlType_arrivalRate, 1+13 bits. + * NDL_tmPacketArrivalRate(AC_BE), ndlType_arrivalRate, 1+13 bits. + * NDL_tmPacketArrivalRate(AC_VI), ndlType_arrivalRate, 1+13 bits. + * NDL_tmPacketArrivalRate(AC_VO), ndlType_arrivalRate, 1+13 bits. + */ + A_UINT32 tm_packet_arrival_rate_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_ARRIVALRATE)]; + /** + * NDL_tmPacketAvgDuration(AC_BK), ndlType_packetDuration, 1+11 bits. + * NDL_tmPacketAvgDuration(AC_BE), ndlType_packetDuration, 1+11 bits. + * NDL_tmPacketAvgDuration(AC_VI), ndlType_packetDuration, 1+11 bits. + * NDL_tmPacketAvgDuration(AC_VO), ndlType_packetDuration, 1+11 bits. + */ + A_UINT32 tm_packet_avg_duration_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_PACKETDURATION)]; + /** + * NDL_tmSignalAvgPower(AC_BK), ndlType_txPower, 1+7 bits. + * NDL_tmSignalAvgPower(AC_BE), ndlType_txPower, 1+7 bits. + * NDL_tmSignalAvgPower(AC_VI), ndlType_txPower, 1+7 bits. + * NDL_tmSignalAvgPower(AC_VO), ndlType_txPower, 1+7 bits. + */ + A_UINT32 tm_signal_avg_power_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_TXPOWER)]; + /** + * NDL_tmMaxChannelUse, ndlType_channelUse, 1+13 bits. + */ + A_UINT32 tm_max_channel_use; + /** + * NDL_tmChannelUse(AC_BK), ndlType_channelUse, 1+13 bits. + * NDL_tmChannelUse(AC_BE), ndlType_channelUse, 1+13 bits. + * NDL_tmChannelUse(AC_VI), ndlType_channelUse, 1+13 bits. + * NDL_tmChannelUse(AC_VO), ndlType_channelUse, 1+13 bits. + */ + A_UINT32 tm_channel_use_ac[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_CHANNELUSE)]; + + /** Channel load thresholds. */ + /** + * NDL_minChannelLoad, ndlType_channelLoad, 1+10 bits. + * NDL_maxChannelLoad, ndlType_channelLoad, 1+10 bits. + */ + A_UINT32 min_max_channel_load; + + /** Transmit queue parameters. */ + /** + * NDL_numQueue, ndlType_acPrio, 1+3 bits. + * NDL_refQueueStatus(AC_BK), ndlType_queueStatus, 1+1 bit. + * NDL_refQueueStatus(AC_BE), ndlType_queueStatus, 1+1 bit. + * NDL_refQueueStatus(AC_VI), ndlType_queueStatus, 1+1 bit. + * NDL_refQueueStatus(AC_VO), ndlType_queueStatus, 1+1 bit. + */ + A_UINT32 transmit_queue_parameters; + + /** + * NDL_refQueueLen(AC_BK), ndlType_numberElements, 1+6 bits. + * NDL_refQueueLen(AC_BE), ndlType_numberElements, 1+6 bits. + * NDL_refQueueLen(AC_VI), ndlType_numberElements, 1+6 bits. + * NDL_refQueueLen(AC_VO), ndlType_numberElements, 1+6 bits. + */ + A_UINT32 numberElements[WMI_PACKED_ARR_SIZE(WLAN_MAX_AC, SIZE_NDLTYPE_NUMBERELEMENTS)]; + +} wmi_dcc_ndl_chan; + +#define WMI_CHAN_FREQ_GET(ptr) WMI_GET_BITS((ptr)->chan_info, 0, 16) +#define WMI_CHAN_FREQ_SET(ptr,val) WMI_SET_BITS((ptr)->chan_info, 0, 16, val) +#define WMI_NDL_NUM_ACTIVE_STATE_GET(ptr) WMI_GET_BITS((ptr)->chan_info, 16, 7) +#define WMI_NDL_NUM_ACTIVE_STATE_SET(ptr,val) WMI_SET_BITS((ptr)->chan_info, 16, 7, val) + +#define WMI_NDL_MIN_DCC_SAMPLING_GET(ptr) WMI_GET_BITS((ptr)->ndl_min_dcc_sampling, 0, 10) +#define WMI_NDL_MIN_DCC_SAMPLING_SET(ptr,val) WMI_SET_BITS((ptr)->ndl_min_dcc_sampling, 0, 10, val) +#define WMI_NDL_MEASURE_INTERVAL_GET(ptr) WMI_GET_BITS((ptr)->ndl_min_dcc_sampling, 10, 16) +#define WMI_NDL_MEASURE_INTERVAL_SET(ptr,val) WMI_SET_BITS((ptr)->ndl_min_dcc_sampling, 10, 16, val) + +#define WMI_NDL_DCC_ENABLE_GET(ptr) WMI_GET_BITS((ptr)->dcc_flags, 0, 1) +#define WMI_NDL_DCC_ENABLE_SET(ptr,val) WMI_SET_BITS((ptr)->dcc_flags, 0, 1, val) +#define WMI_NDL_DCC_STATS_ENABLE_GET(ptr) WMI_GET_BITS((ptr)->dcc_flags, 1, 1) +#define WMI_NDL_DCC_STATS_ENABLE_SET(ptr,val) WMI_SET_BITS((ptr)->dcc_flags, 1, 1, val) +#define WMI_NDL_DCC_STATS_INTERVAL_GET(ptr) WMI_GET_BITS((ptr)->dcc_flags, 2, 16) +#define WMI_NDL_DCC_STATS_INTERVAL_SET(ptr,val) WMI_SET_BITS((ptr)->dcc_flags, 2, 16, val) + +#define WMI_NDL_TIME_UP_GET(ptr) WMI_GET_BITS((ptr)->general_config, 0, 13) +#define WMI_NDL_TIME_UP_SET(ptr,val) WMI_SET_BITS((ptr)->general_config, 0, 13, val) +#define WMI_NDL_TIME_DOWN_GET(ptr) WMI_GET_BITS((ptr)->general_config, 13, 13) +#define WMI_NDL_TIME_DOWN_SET(ptr,val) WMI_SET_BITS((ptr)->general_config, 13, 13, val) + +#define WMI_NDL_MIN_TX_POWER_GET(ptr) WMI_GET_BITS((ptr)->min_max_tx_power, 0, 8) +#define WMI_NDL_MIN_TX_POWER_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_tx_power, 0, 8, val) +#define WMI_NDL_MAX_TX_POWER_GET(ptr) WMI_GET_BITS((ptr)->min_max_tx_power, 8, 8) +#define WMI_NDL_MAX_TX_POWER_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_tx_power, 8, 8, val) + +#define WMI_NDL_DEF_TX_POWER_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->def_tx_power_ac, acprio, SIZE_NDLTYPE_TXPOWER) +#define WMI_NDL_DEF_TX_POWER_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->def_tx_power_ac, acprio, SIZE_NDLTYPE_TXPOWER, val) + +#define WMI_NDL_MAX_PACKET_DURATION_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->max_packet_duration_ac, acprio, SIZE_NDLTYPE_PACKETDURATION) +#define WMI_NDL_MAX_PACKET_DURATION_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->max_packet_duration_ac, acprio, SIZE_NDLTYPE_PACKETDURATION, val) +#define WMI_NDL_MIN_PACKET_INTERVAL_GET(ptr) WMI_GET_BITS((ptr)->min_max_packet_interval, 0, 11) +#define WMI_NDL_MIN_PACKET_INTERVAL_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_packet_interval, 0, 11, val) +#define WMI_NDL_MAX_PACKET_INTERVAL_GET(ptr) WMI_GET_BITS((ptr)->min_max_packet_interval, 11, 11) +#define WMI_NDL_MAX_PACKET_INTERVAL_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_packet_interval, 11, 11, val) +#define WMI_NDL_DEF_PACKET_INTERVAL_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->def_packet_interval_ac, acprio, SIZE_NDLTYPE_PACKETINTERVAL) +#define WMI_NDL_DEF_PACKET_INTERVAL_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->def_packet_interval_ac, acprio, SIZE_NDLTYPE_PACKETINTERVAL, val) + +#define WMI_NDL_MIN_DATARATE_GET(ptr) WMI_GET_BITS((ptr)->min_max_datarate, 0, 4) +#define WMI_NDL_MIN_DATARATE_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_datarate, 0, 4, val) +#define WMI_NDL_MAX_DATARATE_GET(ptr) WMI_GET_BITS((ptr)->min_max_datarate, 4, 4) +#define WMI_NDL_MAX_DATARATE_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_datarate, 4, 4, val) +#define WMI_NDL_DEF_DATARATE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->def_datarate_ac, acprio, SIZE_NDLTYPE_DATARATE) +#define WMI_NDL_DEF_DATARATE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->def_datarate_ac, acprio, SIZE_NDLTYPE_DATARATE, val) + +#define WMI_NDL_MIN_CARRIER_SENSE_GET(ptr) WMI_GET_BITS((ptr)->min_max_def_carrier_sense, 0, 8) +#define WMI_NDL_MIN_CARRIER_SENSE_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_def_carrier_sense, 0, 8, val) +#define WMI_NDL_MAX_CARRIER_SENSE_GET(ptr) WMI_GET_BITS((ptr)->min_max_def_carrier_sense, 8, 8) +#define WMI_NDL_MAX_CARRIER_SENSE_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_def_carrier_sense, 8, 8, val) +#define WMI_NDL_DEF_CARRIER_SENSE_GET(ptr) WMI_GET_BITS((ptr)->min_max_def_carrier_sense, 16, 8) +#define WMI_NDL_DEF_CARRIER_SENSE_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_def_carrier_sense, 16, 8, val) + +#define WMI_NDL_DEF_DCC_SENSITIVITY_GET(ptr) WMI_GET_BITS((ptr)->receive_model_parameter, 0, 8) +#define WMI_NDL_DEF_DCC_SENSITIVITY_SET(ptr,val) WMI_SET_BITS((ptr)->receive_model_parameter, 0, 8, val) +#define WMI_NDL_MAX_CS_RANGE_GET(ptr) WMI_GET_BITS((ptr)->receive_model_parameter, 8, 13) +#define WMI_NDL_MAX_CS_RANGE_SET(ptr,val) WMI_SET_BITS((ptr)->receive_model_parameter, 8, 13, val) +#define WMI_NDL_REF_PATH_LOSS_GET(ptr) WMI_GET_BITS((ptr)->receive_model_parameter, 21, 6) +#define WMI_NDL_REF_PATH_LOSS_SET(ptr,val) WMI_SET_BITS((ptr)->receive_model_parameter, 21, 6, val) + +#define WMI_NDL_MIN_SNR_GET(ptr) WMI_GET_BITS((ptr)->receive_model_parameter_2, 0, 8) +#define WMI_NDL_MIN_SNR_SET(ptr,val) WMI_SET_BITS((ptr)->receive_model_parameter_2, 0, 8, val) + +#define WMI_NDL_SNR_BACKOFF_GET(ptr,mcs) wmi_packed_arr_get_bits((ptr)->snr_backoff_mcs, mcs, SIZE_NDLTYPE_SNR) +#define WMI_NDL_SNR_BACKOFF_SET(ptr,mcs,val) wmi_packed_arr_set_bits((ptr)->snr_backoff_mcs, mcs, SIZE_NDLTYPE_SNR, val) + +#define WMI_NDL_TM_PACKET_ARRIVAL_RATE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tm_packet_arrival_rate_ac, acprio, SIZE_NDLTYPE_ARRIVALRATE) +#define WMI_NDL_TM_PACKET_ARRIVAL_RATE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tm_packet_arrival_rate_ac, acprio, SIZE_NDLTYPE_ARRIVALRATE, val) +#define WMI_NDL_TM_PACKET_AVG_DURATION_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tm_packet_avg_duration_ac, acprio, SIZE_NDLTYPE_PACKETDURATION) +#define WMI_NDL_TM_PACKET_AVG_DURATION_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tm_packet_avg_duration_ac, acprio, SIZE_NDLTYPE_PACKETDURATION, val) +#define WMI_NDL_TM_SIGNAL_AVG_POWER_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tm_signal_avg_power_ac, acprio, SIZE_NDLTYPE_TXPOWER) +#define WMI_NDL_TM_SIGNAL_AVG_POWER_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tm_signal_avg_power_ac, acprio, SIZE_NDLTYPE_TXPOWER, val) +#define WMI_NDL_TM_MAX_CHANNEL_USE_GET(ptr) WMI_GET_BITS((ptr)->tm_max_channel_use, 0, 14) +#define WMI_NDL_TM_MAX_CHANNEL_USE_SET(ptr,val) WMI_SET_BITS((ptr)->tm_max_channel_use, 0, 14, val) +#define WMI_NDL_TM_CHANNEL_USE_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->tm_channel_use_ac, acprio, SIZE_NDLTYPE_CHANNELUSE) +#define WMI_NDL_TM_CHANNEL_USE_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->tm_channel_use_ac, acprio, SIZE_NDLTYPE_CHANNELUSE, val) + +#define WMI_NDL_MIN_CHANNEL_LOAD_GET(ptr) WMI_GET_BITS((ptr)->min_max_channel_load, 0, 11) +#define WMI_NDL_MIN_CHANNEL_LOAD_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_channel_load, 0, 11, val) +#define WMI_NDL_MAX_CHANNEL_LOAD_GET(ptr) WMI_GET_BITS((ptr)->min_max_channel_load, 11, 11) +#define WMI_NDL_MAX_CHANNEL_LOAD_SET(ptr,val) WMI_SET_BITS((ptr)->min_max_channel_load, 11, 11, val) + +#define WMI_NDL_NUM_QUEUE_GET(ptr) WMI_GET_BITS((ptr)->transmit_queue_parameters, 0, 4) +#define WMI_NDL_NUM_QUEUE_SET(ptr,val) WMI_SET_BITS((ptr)->transmit_queue_parameters, 0, 4, val) +#define WMI_NDL_REF_QUEUE_STATUS_GET(ptr,acprio) WMI_GET_BITS((ptr)->transmit_queue_parameters, (4 + (acprio * 2)), 2) +#define WMI_NDL_REF_QUEUE_STATUS_SET(ptr,acprio,val) WMI_SET_BITS((ptr)->transmit_queue_parameters, (4 + (acprio * 2)), 2, val) +#define WMI_NDL_REF_QUEUE_LEN_GET(ptr,acprio) wmi_packed_arr_get_bits((ptr)->numberElements, acprio, SIZE_NDLTYPE_NUMBERELEMENTS) +#define WMI_NDL_REF_QUEUE_LEN_SET(ptr,acprio,val) wmi_packed_arr_set_bits((ptr)->numberElements, acprio, SIZE_NDLTYPE_NUMBERELEMENTS, val) + +/** Data structure for updating the NDL. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_update_ndl_cmd_fixed_param */ + A_UINT32 tlv_header; + + /* VDEV identifier */ + A_UINT32 vdev_id; + + /** The number of channels in the request. */ + A_UINT32 num_channel; + + /** This is followed by a TLV array of wmi_dcc_ndl_chan. */ + /** This is followed by a TLV array of wmi_dcc_ndl_active_state_config. */ +} wmi_dcc_update_ndl_cmd_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_dcc_update_ndl_resp_event_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + A_UINT32 status; +} wmi_dcc_update_ndl_resp_event_fixed_param; + +/* Actions for TSF timestamp */ +typedef enum { + TSF_TSTAMP_CAPTURE_REQ = 1, + TSF_TSTAMP_CAPTURE_RESET = 2, + TSF_TSTAMP_READ_VALUE = 3, +} wmi_tsf_tstamp_action; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /* action type, refer to wmi_tsf_tstamp_action */ + A_UINT32 tsf_action; +} wmi_vdev_tsf_tstamp_action_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_vdev_tsf_report_event_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + /* low 32bit of tsf */ + A_UINT32 tsf_low; + /* high 32 bit of tsf */ + A_UINT32 tsf_high; +} wmi_vdev_tsf_report_event_fixed_param; + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param */ + A_UINT32 tlv_header; + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; + /** unique id to identify the ie_data as defined by ieee 802.11 spec */ + A_UINT32 ie_id; /** ie_len corresponds to num of bytes in ie_data[] */ + A_UINT32 ie_len; + /** + * Following this structure is the TLV byte stream of ie data of length ie_buf_len: + * A_UINT8 ie_data[]; */ +} wmi_vdev_set_ie_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_set_pcl_cmd_fixed_param */ + /** Set Preferred Channel List **/ + + /** # of channels to scan */ + A_UINT32 num_chan; +/** + * TLV (tag length value ) parameters follow the wmi_soc_set_pcl_cmd + * structure. The TLV's are: + * A_UINT32 channel_list[]; + **/ +} wmi_soc_set_pcl_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_cmd_fixed_param */ + /** Set Hardware Mode **/ + + /* Hardware Mode Index */ + A_UINT32 hw_mode_index; +} wmi_soc_set_hw_mode_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_cmd_fixed_param */ + /** Set Dual MAC Firmware Configuration **/ + + /* Concurrent scan configuration bits */ + A_UINT32 concurrent_scan_config_bits; + /* Firmware mode configuration bits */ + A_UINT32 fw_mode_config_bits; + +} wmi_soc_set_dual_mac_config_cmd_fixed_param; + +typedef struct { + A_UINT32 num_tx_chains; + A_UINT32 num_rx_chains; + A_UINT32 reserved[2]; +} soc_num_tx_rx_chains; + +typedef struct { + A_UINT32 num_tx_chains_2g; + A_UINT32 num_rx_chains_2g; + A_UINT32 num_tx_chains_5g; + A_UINT32 num_rx_chains_5g; +} band_num_tx_rx_chains; + +typedef union { + soc_num_tx_rx_chains soc_txrx_chain_setting; + band_num_tx_rx_chains band_txrx_chain_setting; +} antenna_num_tx_rx_chains; + +typedef enum { + ANTENNA_MODE_DISABLED = 0x0, + ANTENNA_MODE_LOW_POWER_LOCATION_SCAN = 0x01, + /* reserved */ +} antenna_mode_reason; + +typedef struct { + /* + * TLV tag and len; + * tag equals WMITLV_TAG_STRUC_wmi_soc_set_antenna_mode_cmd_fixed_param + */ + A_UINT32 tlv_header; + + /* the reason for setting antenna mode, refer antenna_mode_reason */ + A_UINT32 reason; + + /* + * The above reason parameter will select whether the following union + * is soc_num_tx_rx_chains or band_num_tx_rx_chains. + */ + antenna_num_tx_rx_chains num_txrx_chains_setting; +} wmi_soc_set_antenna_mode_cmd_fixed_param; + + +/** Data structure for information specific to a VDEV to MAC mapping. */ +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_response_vdev_mac_entry */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; /* VDEV ID */ + A_UINT32 mac_id; /* MAC ID */ +} wmi_soc_set_hw_mode_response_vdev_mac_entry; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_response_event_fixed_param */ + /** Set Hardware Mode Response Event **/ + + /* Status of set_hw_mode command */ + /* + * Values for Status: + * 0 - OK; command successful + * 1 - EINVAL; Requested invalid hw_mode + * 2 - ECANCELED; HW mode change canceled + * 3 - ENOTSUP; HW mode not supported + * 4 - EHARDWARE; HW mode change prevented by hardware + * 5 - EPENDING; HW mode change is pending + * 6 - ECOEX; HW mode change conflict with Coex + */ + A_UINT32 status; + /* Configured Hardware Mode */ + A_UINT32 cfgd_hw_mode_index; + /* Number of Vdev to Mac entries */ + A_UINT32 num_vdev_mac_entries; + +/** + * TLV (tag length value ) parameters follow the soc_set_hw_mode_response_event + * structure. The TLV's are: + * A_UINT32 wmi_soc_set_hw_mode_response_vdev_mac_entry[]; + */ +} wmi_soc_set_hw_mode_response_event_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_hw_mode_transition_event_fixed_param */ + /** Hardware Mode Transition Event **/ + + /* Original or old Hardware mode */ + A_UINT32 old_hw_mode_index; + /* New Hardware Mode */ + A_UINT32 new_hw_mode_index; + /* Number of Vdev to Mac entries */ + A_UINT32 num_vdev_mac_entries; + +/** + * TLV (tag length value ) parameters follow the soc_set_hw_mode_response_event + * structure. The TLV's are: + * A_UINT32 wmi_soc_set_hw_mode_response_vdev_mac_entry[]; + */ +} wmi_soc_hw_mode_transition_event_fixed_param; + + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_response_event_fixed_param */ + /** Set Dual MAC Config Response Event **/ + + /* Status for set_dual_mac_config command */ + /* + * Values for Status: + * 0 - OK; command successful + * 1 - EINVAL; Requested invalid hw_mode + * 3 - ENOTSUP; HW mode not supported + * 4 - EHARDWARE; HW mode change prevented by hardware + * 6 - ECOEX; HW mode change conflict with Coex + */ + A_UINT32 status; + +} wmi_soc_set_dual_mac_config_response_event_fixed_param; + +typedef enum { + MAWC_MOTION_STATE_UNKNOWN, + MAWC_MOTION_STATE_STATIONARY, + MAWC_MOTION_STATE_WALK, + MAWC_MOTION_STATE_TRANSIT, +} MAWC_MOTION_STATE; + +typedef enum { + MAWC_SENSOR_STATUS_OK, + MAWC_SENSOR_STATUS_FAILED_TO_ENABLE, + MAWC_SENSOR_STATUS_SHUTDOWN, +} MAWC_SENSOR_STATUS; + +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mawc_sensor_report_ind_cmd_fixed_param */ + A_UINT32 tlv_header; + /** new motion state, MAWC_MOTION_STATE */ + A_UINT32 motion_state; + /** status code of sensor, MAWC_SENSOR_STATUS */ + A_UINT32 sensor_status; +} wmi_mawc_sensor_report_ind_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_mawc_enable_sensor_event_fixed_param */ + A_UINT32 tlv_header; + /* enable(1) or disable(0) */ + A_UINT32 enable; +} wmi_mawc_enable_sensor_event_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_extscan_configure_mawc_cmd_fixed_param */ + A_UINT32 tlv_header; + /* Unique id identifying the VDEV */ + A_UINT32 vdev_id; + /* enable(1) or disable(0) MAWC */ + A_UINT32 enable; + /* ratio of skipping suppressing scan, skip one out of x */ + A_UINT32 suppress_ratio; +} wmi_extscan_configure_mawc_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_nlo_configure_mawc_cmd_fixed_param */ + A_UINT32 tlv_header; + /* Unique id identifying the VDEV */ + A_UINT32 vdev_id; + /* enable(1) or disable(0) MAWC */ + A_UINT32 enable; + /* ratio of exponential backoff, next = current + current*ratio/100 */ + A_UINT32 exp_backoff_ratio; + /* initial scan interval(msec) */ + A_UINT32 init_scan_interval; + /* max scan interval(msec) */ + A_UINT32 max_scan_interval; +} wmi_nlo_configure_mawc_cmd_fixed_param; + +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_roam_configure_mawc_cmd_fixed_param */ + A_UINT32 tlv_header; + /* Unique id identifying the VDEV */ + A_UINT32 vdev_id; + /* enable(1) or disable(0) MAWC */ + A_UINT32 enable; + /* data traffic load (kBps) to register CMC */ + A_UINT32 traffic_load_threshold; + /* RSSI threshold (dBm) to scan for Best AP */ + A_UINT32 best_ap_rssi_threshold; + /* high RSSI threshold adjustment in Stationary to suppress scan */ + A_UINT32 rssi_stationary_high_adjust; + /* low RSSI threshold adjustment in Stationary to suppress scan */ + A_UINT32 rssi_stationary_low_adjust; +} wmi_roam_configure_mawc_cmd_fixed_param; + +#define WMI_PACKET_FILTER_COMPARE_DATA_LEN_DWORD 2 +#define WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER 10 + +typedef enum { + PACKET_FILTER_TYPE_INVALID = 0, + PACKET_FILTER_TYPE_FILTER_PKT, + PACKET_FILTER_TYPE_RESERVE_PKT, // not used + PACKET_FILTER_TYPE_MAX_ENUM_SIZE +} WMI_PACKET_FILTER_FILTER_TYPE; + +typedef enum { + PACKET_FILTER_PROTO_TYPE_INVALID = 0, + + /* L2 header */ + PACKET_FILTER_PROTO_TYPE_MAC, + PACKET_FILTER_PROTO_TYPE_SNAP, + + /* L3 header (EtherType) */ + PACKET_FILTER_PROTO_TYPE_IPV4, + PACKET_FILTER_PROTO_TYPE_IPV6, + + /* L4 header (IP protocol) */ + PACKET_FILTER_PROTO_TYPE_UDP, + PACKET_FILTER_PROTO_TYPE_TCP, + PACKET_FILTER_PROTO_TYPE_ICMPV6, + + PACKET_FILTER_PROTO_TYPE_MAX +} WMI_PACKET_FILTER_PROTO_TYPE; + +typedef enum { + PACKET_FILTER_CMP_TYPE_INVALID = 0, + PACKET_FILTER_CMP_TYPE_EQUAL, + PACKET_FILTER_CMP_TYPE_MASK_EQUAL, + PACKET_FILTER_CMP_TYPE_NOT_EQUAL, + PACKET_FILTER_CMP_TYPE_MASK_NOT_EQUAL, + PACKET_FILTER_CMP_TYPE_ADDRTYPE, + PACKET_FILTER_CMP_TYPE_MAX +} WMI_PACKET_FILTER_CMP_TYPE; + +typedef enum { + PACKET_FILTER_SET_INACTIVE = 0, + PACKET_FILTER_SET_ACTIVE +} WMI_PACKET_FILTER_ACTION; + +typedef enum { + PACKET_FILTER_SET_DISABLE = 0, + PACKET_FILTER_SET_ENABLE +} WMI_PACKET_FILTER_RUNTIME_ENABLE; + +typedef struct { + A_UINT32 proto_type; + A_UINT32 cmp_type; + A_UINT32 data_length; /* Length of the data to compare (units = bytes) */ + A_UINT32 data_offset; /* from start of the respective frame header ( +units = bytes) */ + A_UINT32 compareData[WMI_PACKET_FILTER_COMPARE_DATA_LEN_DWORD]; /* Data to compare, little-endian order */ + A_UINT32 dataMask[WMI_PACKET_FILTER_COMPARE_DATA_LEN_DWORD]; /* Mask to be applied on rcvd packet data before compare, little-endian order */ +} WMI_PACKET_FILTER_PARAMS_TYPE; + +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 filter_id; + A_UINT32 filter_action; /* WMI_PACKET_FILTER_ACTION */ + A_UINT32 filter_type; + A_UINT32 num_params; /* how many entries in paramsData are valid */ + A_UINT32 coalesce_time; // not currently used - fill with 0x0 + WMI_PACKET_FILTER_PARAMS_TYPE paramsData[ +WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER]; +} WMI_PACKET_FILTER_CONFIG_CMD_fixed_param; + +/* enable / disable all filters within the specified vdev */ +typedef struct { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 enable; /* WMI_PACKET_FILTER_RUNTIME_ENABLE */ +} WMI_PACKET_FILTER_ENABLE_CMD_fixed_param; + +#define WMI_LRO_INFO_TCP_FLAG_VALS_BITPOS 0 +#define WMI_LRO_INFO_TCP_FLAG_VALS_NUMBITS 9 + +#define WMI_LRO_INFO_TCP_FLAG_VALS_SET(tcp_flag_u32, tcp_flag_values) \ + WMI_SET_BITS(tcp_flag_u32, \ + WMI_LRO_INFO_TCP_FLAG_VALS_BITPOS, \ + WMI_LRO_INFO_TCP_FLAG_VALS_NUMBITS, \ + tcp_flag_values) +#define WMI_LRO_INFO_TCP_FLAG_VALS_GET(tcp_flag_u32) \ + WMI_GET_BITS(tcp_flag_u32, \ + WMI_LRO_INFO_TCP_FLAG_VALS_BITPOS, \ + WMI_LRO_INFO_TCP_FLAG_VALS_NUMBITS) + +#define WMI_LRO_INFO_TCP_FLAGS_MASK_BITPOS 9 +#define WMI_LRO_INFO_TCP_FLAGS_MASK_NUMBITS 9 + +#define WMI_LRO_INFO_TCP_FLAGS_MASK_SET(tcp_flag_u32, tcp_flags_mask) \ + WMI_SET_BITS(tcp_flag_u32, \ + WMI_LRO_INFO_TCP_FLAGS_MASK_BITPOS, \ + WMI_LRO_INFO_TCP_FLAGS_MASK_NUMBITS, \ + tcp_flags_mask) +#define WMI_LRO_INFO_TCP_FLAGS_MASK_GET(tcp_flag_u32) \ + WMI_GET_BITS(tcp_flag_u32, \ + WMI_LRO_INFO_TCP_FLAGS_MASK_BITPOS, \ + WMI_LRO_INFO_TCP_FLAGS_MASK_NUMBITS) + +typedef struct { + A_UINT32 tlv_header; + /** + * @brief lro_enable - indicates whether lro is enabled + * [0] LRO Enable + */ + A_UINT32 lro_enable; + /** + * @brief tcp_flag_u32 - mask of which TCP flags to check and + * values to check for + * [8:0] TCP flag values - If the TCP flags from the packet do not match + * the values in this field after masking with TCP flags mask below, + * LRO eligible will not be set + * [17:9] TCP flags mask - Mask field for comparing the TCP values + * provided above with the TCP flags field in the received packet + * Use WMI_LRO_INFO_TCP_FLAG_VALS and WMI_LRO_INFO_TCP_FLAGS_MASK + * macros to isolate the mask field and values field that are packed + * into this u32 "word". + */ + A_UINT32 tcp_flag_u32; + /** + * @brief toeplitz_hash_ipv4 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv4 packets. Contains + * bytes 0 to 3 + * + * In this and all the below toeplitz_hash fields, the bytes are + * specified in little-endian order. For example: + * toeplitz_hash_ipv4_0_3 bits 7:0 holds seed byte 0 + * toeplitz_hash_ipv4_0_3 bits 15:8 holds seed byte 1 + * toeplitz_hash_ipv4_0_3 bits 23:16 holds seed byte 2 + * toeplitz_hash_ipv4_0_3 bits 31:24 holds seed byte 3 + */ + A_UINT32 toeplitz_hash_ipv4_0_3; + + /** + * @brief toeplitz_hash_ipv4 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv4 packets. Contains + * bytes 4 to 7 + */ + A_UINT32 toeplitz_hash_ipv4_4_7; + + /** + * @brief toeplitz_hash_ipv4 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv4 packets. Contains + * bytes 8 to 11 + */ + A_UINT32 toeplitz_hash_ipv4_8_11; + + /** + * @brief toeplitz_hash_ipv4 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv4 packets. Contains + * bytes 12 to 15 + */ + A_UINT32 toeplitz_hash_ipv4_12_15; + + /** + * @brief toeplitz_hash_ipv4 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv4 packets. Contains + * byte 16 + */ + A_UINT32 toeplitz_hash_ipv4_16; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 0 to 3 + */ + A_UINT32 toeplitz_hash_ipv6_0_3; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 4 to 7 + */ + A_UINT32 toeplitz_hash_ipv6_4_7; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 8 to 11 + */ + A_UINT32 toeplitz_hash_ipv6_8_11; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 12 to 15 + */ + A_UINT32 toeplitz_hash_ipv6_12_15; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 16 to 19 + */ + A_UINT32 toeplitz_hash_ipv6_16_19; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 20 to 22 + */ + A_UINT32 toeplitz_hash_ipv6_20_23; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 24 to 27 + */ + A_UINT32 toeplitz_hash_ipv6_24_27; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 28 to 31 + */ + A_UINT32 toeplitz_hash_ipv6_28_31; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 32 to 35 + */ + A_UINT32 toeplitz_hash_ipv6_32_35; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * bytes 36 to 39 + */ + A_UINT32 toeplitz_hash_ipv6_36_39; + + /** + * @brief toeplitz_hash_ipv6 - contains seed needed to compute + * the flow id 5-tuple toeplitz hash for IPv6 packets. Contains + * byte 40 + */ + A_UINT32 toeplitz_hash_ipv6_40; +} wmi_lro_info_cmd_fixed_param; + +/* + * This structure is used to set the pattern for WOW host wakeup pin pulse + * pattern confirguration. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_cmd_fixed_param */ + A_UINT32 offset; /* flash offset to write, starting from 0 */ + A_UINT32 length; /* vaild data length in buffer, unit: byte */ +} wmi_transfer_data_to_flash_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_complete_event_fixed_param */ + /** Return status. 0 for success, non-zero otherwise */ + A_UINT32 status; +} wmi_transfer_data_to_flash_complete_event_fixed_param; + +/* + * This structure is used to report SCPC calibrated data to host. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_scpc_event_fixed_param */ + /** number of BDF patches. Each patch contains offset, length and data */ + A_UINT32 num_patch; + /* This TLV is followed by another TLV of array of bytes + * A_UINT8 data[]; + * This data array contains, for example + * patch1 offset(byte3~0), patch1 data length(byte7~4), patch1 data(byte11~8) + * patch2 offset(byte15~12), patch2 data length(byte19~16), patch2 data(byte47~20) + * + */ +} wmi_scpc_event_fixed_param; + +/* + * This structure is used to report SMPS force mode set complete to host. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_complete_event_fixed_param */ + /* Unique id identifying the VDEV */ + A_UINT32 vdev_id; + /* Return status. 0 for success, non-zero otherwise */ + A_UINT32 status; +} wmi_sta_smps_force_mode_complete_event_fixed_param; + +/* ADD NEW DEFS HERE */ + +/***************************************************************************** + * The following structures are deprecated. DO NOT USE THEM! + */ + +/** Max number of channels in the schedule. */ +#define OCB_CHANNEL_MAX (5) + +/* NOTE: Make sure these data structures are identical to those 9235 +* defined in sirApi.h */ + +typedef struct +{ + /** Arbitration Inter-Frame Spacing. Range: 2-15 */ + A_UINT32 aifsn; + /** Contention Window minimum. Range: 1 - 10 */ + A_UINT32 cwmin; + /** Contention Window maximum. Range: 1 - 10 */ + A_UINT32 cwmax; +} wmi_qos_params_t; + +typedef struct +{ + /** Channel frequency in MHz */ + A_UINT32 chan_freq; + /** Channel duration in ms */ + A_UINT32 duration; + /** Start guard interval in ms */ + A_UINT32 start_guard_interval; + /** End guard interval in ms */ + A_UINT32 end_guard_interval; + /** Transmit power in dBm, range 0 - 23 */ + A_UINT32 tx_power; + /** Transmit datarate in Mbps */ + A_UINT32 tx_rate; + /** QoS parameters for each AC */ + wmi_qos_params_t qos_params[WLAN_MAX_AC]; + /** 1 to enable RX stats for this channel, 0 otherwise */ + A_UINT32 rx_stats; +} wmi_ocb_channel_t; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param */ + A_UINT32 tlv_header; + /* VDEV identifier */ + A_UINT32 vdev_id; + /** Number of valid channels in the channels array */ + A_UINT32 num_channels; + /** The array of channels */ + wmi_ocb_channel_t channels[OCB_CHANNEL_MAX]; + /** 1 to allow off-channel tx, 0 otherwise */ + A_UINT32 off_channel_tx; // Not supported +} wmi_ocb_set_sched_cmd_fixed_param; + +typedef struct { + /** Return status. 0 for success, non-zero otherwise */ + A_UINT32 status; +} wmi_ocb_set_sched_event_fixed_param; + +/***************************************************************************** + * END DEPRECATED + */ + +/* ADD NEW DEFS ABOVE THIS DEPRECATED SECTION */ + +#ifdef __cplusplus +} +#endif + +#endif /*_WMI_UNIFIED_H_*/ + +/**@}*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h new file mode 100644 index 000000000000..cd9f923beca8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +/* + * This file contains the API definitions for the Unified Wireless Module Interface (WMI). + */ + +#ifndef _WMI_UNIFIED_API_H_ +#define _WMI_UNIFIED_API_H_ + +#include +#include "a_types.h" +#include "ol_defines.h" +#include "wmi.h" +#include "htc_api.h" + +typedef adf_nbuf_t wmi_buf_t; +#define wmi_buf_free(_buf) adf_nbuf_free(_buf) +#define wmi_buf_data(_buf) adf_nbuf_data(_buf) + +/** + * attach for unified WMI + * + * @param scn_handle : handle to SCN. + * @return opaque handle. + */ +void * +wmi_unified_attach(void *scn_handle, void (*func) (void*)); +/** + * detach for unified WMI + * + * @param wmi_handle : handle to WMI. + * @return void. + */ +void +wmi_unified_detach(struct wmi_unified* wmi_handle); + +void +wmi_unified_remove_work(struct wmi_unified* wmi_handle); + +/** + * generic function to allocate WMI buffer + * + * @param wmi_handle : handle to WMI. + * @param len : length of the buffer + * @return wmi_buf_t. + */ +wmi_buf_t +wmi_buf_alloc(wmi_unified_t wmi_handle, u_int16_t len); + + +/** + * generic function to send unified WMI command + * + * @param wmi_handle : handle to WMI. + * @param buf : wmi command buffer + * @param buflen : wmi command buffer length + * @return 0 on success and -ve on failure. + */ +int +wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int buflen, WMI_CMD_ID cmd_id); + +/** + * WMI event handler register function + * + * @param wmi_handle : handle to WMI. + * @param event_id : WMI event ID + * @param handler_func : Event handler call back function + * @return 0 on success and -ve on failure. + */ +int +wmi_unified_register_event_handler(wmi_unified_t wmi_handle, WMI_EVT_ID event_id, + wmi_unified_event_handler handler_func); + +/** + * WMI event handler unregister function + * + * @param wmi_handle : handle to WMI. + * @param event_id : WMI event ID + * @return 0 on success and -ve on failure. + */ +int +wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle, WMI_EVT_ID event_id); + + +/** + * request wmi to connet its htc service. + * @param wmi_handle : handle to WMI. + * @return void + */ +int +wmi_unified_connect_htc_service(struct wmi_unified * wmi_handle, void *htc_handle); + +/* + * WMI API to verify the host has enough credits to suspend +*/ + +int +wmi_is_suspend_ready(wmi_unified_t wmi_handle); + +/** + WMI API to get updated host_credits +*/ + +int +wmi_get_host_credits(wmi_unified_t wmi_handle); + +/** + WMI API to get WMI Pending Commands in the HTC queue +*/ + +int +wmi_get_pending_cmds(wmi_unified_t wmi_handle); + +/** + WMI API to set target suspend state +*/ + +void +wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val); + +void wmi_set_tgt_assert(wmi_unified_t wmi_handle, A_BOOL val); + +#ifdef FEATURE_RUNTIME_PM +void +wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val); +bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle); +#else +static inline void +wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val) +{ + return; +} +static inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle) +{ + return false; +} +#endif + +#ifdef FEATURE_WLAN_D0WOW +/** + WMI API to set D0WOW flag +*/ +void +wmi_set_d0wow_flag(wmi_unified_t wmi_handle, A_BOOL flag); + +/** + WMI API to get D0WOW flag +*/ +A_BOOL +wmi_get_d0wow_flag(wmi_unified_t wmi_handle); +#endif + +/** + WMA Callback to get the Tx complete for WOW_ENABLE +*/ +typedef void (*wma_wow_tx_complete_cbk)(void *scn_handle); + +uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle); + +void wmi_tag_crash_inject(wmi_unified_t wmi_handle, A_BOOL flag); +#endif /* _WMI_UNIFIED_API_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h new file mode 100644 index 000000000000..56e34cd96530 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * IMPORTANT NOTE: For all change to WMI Interface, the ABI version number _must_ be updated. + */ +/** Major version number is incremented when there are significant changes to WMI Interface that break compatibility. */ +#define __WMI_VER_MAJOR_ 1 +/** Minor version number is incremented when there are changes + * (however minor) to WMI Interface that break + * compatibility. */ +#define __WMI_VER_MINOR_ 0 +/** WMI revision number has to be incremented when there is a + * change that may or may not break compatibility. */ +#define __WMI_REVISION_ 183 + +/** The Version Namespace should not be normally changed. Only + * host and firmware of the same WMI namespace will work + * together. + * For example, "QCA_ML" converts to 0x4C, 0x4D5F414351. + * where 'Q'=0x51, 'C'=0x43, 'A'=0x41, '_'=0x5F. 'M'=4D, 'L'=4C + */ +#define __NAMESPACE_0_ 0x5F414351 +#define __NAMESPACE_1_ 0x00004C4D +#define __NAMESPACE_2_ 0x00000000 +#define __NAMESPACE_3_ 0x00000000 + +/* Format of the version number. */ +#define WMI_VER_MAJOR_BIT_OFFSET 24 +#define WMI_VER_MINOR_BIT_OFFSET 0 + +#define WMI_VER_MAJOR_BIT_MASK 0xFF000000 +#define WMI_VER_MINOR_BIT_MASK 0x00FFFFFF + +/* Macros to extract the sw_version components. + */ +#define WMI_VER_GET_MAJOR(x) (((x) & WMI_VER_MAJOR_BIT_MASK)>>WMI_VER_MAJOR_BIT_OFFSET) +#define WMI_VER_GET_MINOR(x) (((x) & WMI_VER_MINOR_BIT_MASK)>>WMI_VER_MINOR_BIT_OFFSET) + +#define WMI_VER_GET_VERSION_0(major, minor) ( (( major << WMI_VER_MAJOR_BIT_OFFSET ) & WMI_VER_MAJOR_BIT_MASK) + (( minor << WMI_VER_MINOR_BIT_OFFSET ) & WMI_VER_MINOR_BIT_MASK) ) +/* + * The version has the following format: + * Bits 24-31: Major version + * Bits 0-23: Minor version + * Bits 0-31: Build number + * E.g. Build 1.1.7 would be represented as 0x01000001 for Major/Minor & 0x00000007 for buildnum. + * + * DO NOT split the following macro into multiple lines as this may confuse the build scripts. + */ +/* ABI Version. Reflects the version of binary interface exposed by Target firmware. */ +#define WMI_ABI_VERSION_0 WMI_VER_GET_VERSION_0(__WMI_VER_MAJOR_, __WMI_VER_MINOR_) +#define WMI_ABI_VERSION_1 __WMI_REVISION_ +#define WMI_ABI_VERSION_NS_0 __NAMESPACE_0_ +#define WMI_ABI_VERSION_NS_1 __NAMESPACE_1_ +#define WMI_ABI_VERSION_NS_2 __NAMESPACE_2_ +#define WMI_ABI_VERSION_NS_3 __NAMESPACE_3_ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version_whitelist.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version_whitelist.c new file mode 100644 index 000000000000..266b7620445f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version_whitelist.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * Every Product Line or chipset or team can have its own Whitelist table. + * The following is a list of versions that the present software can support + * even though its versions are incompatible. Any entry here means that the + * indicated version does not break WMI compatibility even though it has + * a minor version change. + */ +wmi_whitelist_version_info version_whitelist[] = +{ + {0, 0, 0x5F414351, 0x00004C4D, 0, 0}, //Placeholder: Major=0, Minor=0, Namespace="QCA_ML" (Dummy entry) +}; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmix.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmix.h new file mode 100644 index 000000000000..9a64f53b98fe --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmix.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// $ATH_LICENSE_HOSTSDK0_C$ +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +/* + * This file contains extensions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all + * extended commands and events. Extensions include useful commands + * that are not directly related to wireless activities. They may + * be hardware-specific, and they might not be supported on all + * implementations. + * + * Extended WMIX commands are encapsulated in a WMI message with + * cmd=WMI_EXTENSION_CMD. + */ + +#ifndef _WMIX_H_ +#define _WMIX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Extended WMI commands are those that are needed during wireless + * operation, but which are not really wireless commands. This allows, + * for instance, platform-specific commands. Extended WMI commands are + * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID. + * Extended WMI events are similarly embedded in a WMI event message with + * WMI_EVENT_ID=WMI_EXTENSION_EVENTID. + */ +typedef struct { + A_UINT32 commandId; +} POSTPACK WMIX_CMD_HDR; + +typedef enum { + WMIX_DSETOPEN_REPLY_CMDID = 0x2001, + WMIX_DSETDATA_REPLY_CMDID, + WMIX_HB_CHALLENGE_RESP_CMDID, + WMIX_DBGLOG_CFG_MODULE_CMDID, + WMIX_PROF_CFG_CMDID, /* 0x200a */ + WMIX_PROF_ADDR_SET_CMDID, + WMIX_PROF_START_CMDID, + WMIX_PROF_STOP_CMDID, + WMIX_PROF_COUNT_GET_CMDID, +} WMIX_COMMAND_ID; + +typedef enum { + WMIX_DSETOPENREQ_EVENTID = 0x3001, + WMIX_DSETCLOSE_EVENTID, + WMIX_DSETDATAREQ_EVENTID, + WMIX_HB_CHALLENGE_RESP_EVENTID, + WMIX_DBGLOG_EVENTID, + WMIX_PROF_COUNT_EVENTID, + WMIX_PKTLOG_EVENTID, +} WMIX_EVENT_ID; + +/* + * =============DataSet support================= + */ + +/* + * WMIX_DSETOPENREQ_EVENTID + * DataSet Open Request Event + */ +typedef struct { + A_UINT32 dset_id; + A_UINT32 targ_dset_handle; /* echo'ed, not used by Host, */ + A_UINT32 targ_reply_fn; /* echo'ed, not used by Host, */ + A_UINT32 targ_reply_arg; /* echo'ed, not used by Host, */ +} POSTPACK WMIX_DSETOPENREQ_EVENT; + +/* + * WMIX_DSETCLOSE_EVENTID + * DataSet Close Event + */ +typedef struct { + A_UINT32 access_cookie; +} POSTPACK WMIX_DSETCLOSE_EVENT; + +/* + * WMIX_DSETDATAREQ_EVENTID + * DataSet Data Request Event + */ +typedef struct { + A_UINT32 access_cookie; + A_UINT32 offset; + A_UINT32 length; + A_UINT32 targ_buf; /* echo'ed, not used by Host, */ + A_UINT32 targ_reply_fn; /* echo'ed, not used by Host, */ + A_UINT32 targ_reply_arg; /* echo'ed, not used by Host, */ +} WMIX_DSETDATAREQ_EVENT; + +typedef struct { + A_UINT32 status; + A_UINT32 targ_dset_handle; + A_UINT32 targ_reply_fn; + A_UINT32 targ_reply_arg; + A_UINT32 access_cookie; + A_UINT32 size; + A_UINT32 version; +} WMIX_DSETOPEN_REPLY_CMD; + +typedef struct { + A_UINT32 status; + A_UINT32 targ_buf; + A_UINT32 targ_reply_fn; + A_UINT32 targ_reply_arg; + A_UINT32 length; + A_UINT8 buf[1]; +} WMIX_DSETDATA_REPLY_CMD; + +/* + * =============Error Detection support================= + */ + +/* + * WMIX_HB_CHALLENGE_RESP_CMDID + * Heartbeat Challenge Response command + */ +typedef struct { + A_UINT32 cookie; + A_UINT32 source; +} WMIX_HB_CHALLENGE_RESP_CMD; + +/* + * WMIX_HB_CHALLENGE_RESP_EVENTID + * Heartbeat Challenge Response Event + */ +#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD + +/* + * =============Target Profiling support================= + */ + +typedef struct { + A_UINT32 period; /* Time (in 30.5us ticks) between samples */ + A_UINT32 nbins; +} WMIX_PROF_CFG_CMD; + +typedef struct { + A_UINT32 addr; +} WMIX_PROF_ADDR_SET_CMD; + +/* + * Target responds to Hosts's earlier WMIX_PROF_COUNT_GET_CMDID request + * using a WMIX_PROF_COUNT_EVENT with + * addr set to the next address + * count set to the corresponding count + */ +typedef struct { + A_UINT32 addr; + A_UINT32 count; +} WMIX_PROF_COUNT_EVENT; + + +#ifdef __cplusplus +} +#endif + +#endif /* _WMIX_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/ath_dfs_structs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/ath_dfs_structs.h new file mode 100644 index 000000000000..425d0d5f53ec --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/ath_dfs_structs.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + ath_dfs_structs.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + + +#ifndef _DFS__STRUCTS_H_ +#define _DFS__STRUCTS_H_ +#include + +#ifdef ANDROID +#include +#endif + +/* + * For the dfs_nol_clist_update() method - this is the + * update command. + */ +enum { + DFS_NOL_CLIST_CMD_NONE = 0x0, + DFS_NOL_CLIST_CMD_UPDATE = 0x1, +}; + +struct ath_dfs_caps { + u_int32_t + ath_dfs_ext_chan_ok:1, /* Can radar be detected on the extension chan? */ + ath_dfs_combined_rssi_ok:1, /* Can use combined radar RSSI? */ + /* the following flag is used to indicate if radar detection scheme */ + /* should use enhanced chirping detection algorithm. This flag also */ + /* determines if certain radar data should be discarded to minimize */ + /* false detection of radar. */ + ath_dfs_use_enhancement:1, + ath_strong_signal_diversiry:1, + ath_chip_is_bb_tlv:1; + + /* + * goes with ath_strong_signal_diversiry: + * If we have fast diversity capability, read off + * Strong Signal fast diversity count set in the ini + * file, and store so we can restore the value when + * radar is disabled + */ + u_int32_t ath_fastdiv_val; +}; + +/* + * These are defined in the HAL for now, and must be migrated outside + * of there in order to be used by the new partial offload data path. + */ + +struct dfs_pulse { + u_int32_t rp_numpulses; /* Num of pulses in radar burst */ + u_int32_t rp_pulsedur; /* Duration of each pulse in usecs */ + u_int32_t rp_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_patterntype; /* fixed or variable pattern type*/ + u_int32_t rp_pulsevar; /* Time variation of pulse duration for + matched filter (single-sided) in usecs */ + u_int32_t rp_threshold; /* Threshold for MF output to indicateC + radar match */ + u_int32_t rp_mindur; /* Min pulse duration to be considered for + this pulse type */ + u_int32_t rp_maxdur; /* Max pusle duration to be considered for + this pulse type */ + u_int32_t rp_rssithresh; /* Minimum rssi to be considered a radar pulse */ + u_int32_t rp_meanoffset; /* Offset for timing adjustment */ + int32_t rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm */ + /* lower than in non TURBO mode. This will be used to offset that diff.*/ + u_int32_t rp_ignore_pri_window; + u_int32_t rp_pulseid; /* Unique ID for identifying filter */ +}; + +struct dfs_staggered_pulse { + u_int32_t rp_numpulses; /* Num of pulses in radar burst */ + u_int32_t rp_pulsedur; /* Duration of each pulse in usecs */ + u_int32_t rp_min_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ + u_int32_t rp_patterntype; /* fixed or variable pattern type*/ + u_int32_t rp_pulsevar; /* Time variation of pulse duration for + matched filter (single-sided) in usecs */ + u_int32_t rp_threshold; /* Thershold for MF output to indicateC + radar match */ + u_int32_t rp_mindur; /* Min pulse duration to be considered for + this pulse type */ + u_int32_t rp_maxdur; /* Max pusle duration to be considered for + this pulse type */ + u_int32_t rp_rssithresh; /* Minimum rssi to be considered a radar pulse */ + u_int32_t rp_meanoffset; /* Offset for timing adjustment */ + int32_t rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm */ + /* lower than in non TURBO mode. This will be used to offset that diff.*/ + u_int32_t rp_pulseid; /* Unique ID for identifying filter */ +}; + +struct dfs_bin5pulse { + u_int32_t b5_threshold; /* Number of bin5 pulses to indicate detection */ + u_int32_t b5_mindur; /* Min duration for a bin5 pulse */ + u_int32_t b5_maxdur; /* Max duration for a bin5 pulse */ + u_int32_t b5_timewindow; /* Window over which to count bin5 pulses */ + u_int32_t b5_rssithresh; /* Min rssi to be considered a pulse */ + u_int32_t b5_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dB */ +}; + +/* + * DFS NOL representation. + * + * This is used to represent the DFS NOL information between the + * NOL code in lmac/dfs/dfs_nol.c and any driver layer wishing + * to use it. + */ +struct dfs_nol_chan_entry { + u_int32_t nol_chfreq; /* Centre frequency, MHz */ + u_int32_t nol_chwidth; /* Width, MHz */ + unsigned long nol_start_ticks; /* start ticks, OS specific */ + u_int32_t nol_timeout_ms; /* timeout, mS */ +}; + +//HAL_PHYERR_PARAM; + +/* + * This represents the general case of the radar PHY configuration, + * across all chips. + * + * It's then up to each chip layer to translate to/from this + * (eg to HAL_PHYERR_PARAM for the HAL case.) + */ + +#define ATH_DFS_PHYERR_PARAM_NOVAL 0xFFFF +#define ATH_DFS_PHYERR_PARAM_ENABLE 0x8000 + +struct ath_dfs_phyerr_param { + int32_t pe_firpwr; /* FIR pwr out threshold */ + int32_t pe_rrssi; /* Radar rssi thresh */ + int32_t pe_height; /* Pulse height thresh */ + int32_t pe_prssi; /* Pulse rssi thresh */ + int32_t pe_inband; /* Inband thresh */ + + /* The following params are only for AR5413 and later */ + /* + * Relative power threshold in 0.5dB steps + */ + u_int32_t pe_relpwr; + + /* + * Pulse Relative step threshold in 0.5dB steps + */ + u_int32_t pe_relstep; + + /* + * Max length of radar sign in 0.8us units + */ + u_int32_t pe_maxlen; + + /* + * Use the average in-band power measured over 128 cycles + */ + bool pe_usefir128; + + /* + * Enable to block radar check if pkt detect is done via OFDM + * weak signal detect or pkt is detected immediately after tx + * to rx transition + */ + bool pe_blockradar; + + /* + * Enable to use the max rssi instead of the last rssi during + * fine gain changes for radar detection + */ + bool pe_enmaxrssi; +}; + +static inline void ath_dfs_phyerr_param_copy(struct ath_dfs_phyerr_param *dst, + struct ath_dfs_phyerr_param *src) +{ + adf_os_mem_copy(dst, src, sizeof(*dst)); +} + +static inline void ath_dfs_phyerr_init_noval(struct ath_dfs_phyerr_param *pe) +{ + pe->pe_firpwr = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_rrssi = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_height = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_prssi = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_inband = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_relpwr = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_relstep = ATH_DFS_PHYERR_PARAM_NOVAL; + pe->pe_maxlen = ATH_DFS_PHYERR_PARAM_NOVAL; + + /* XXX what about usefir128, blockradar, enmaxrssi? */ +} + +struct ath_dfs_radar_tab_info { + u_int32_t dfsdomain; + int numradars; + struct dfs_pulse *dfs_radars; + int numb5radars; + struct dfs_bin5pulse *b5pulses; + struct ath_dfs_phyerr_param dfs_defaultparams; + int dfs_pri_multiplier; +}; +#endif /* _DFS__STRUCTS_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs.h new file mode 100644 index 000000000000..556de5b1a49f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs.h @@ -0,0 +1,808 @@ +/* + * Copyright (c) 2005-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#ifndef _DFS_H_ +#define _DFS_H_ + +/* +*TO DO DFS- Need to include this file later on +*#include "ath_internal.h" +*/ +/*DFS New Include Start*/ + +#include /* ADF_NBUF_EXEMPT_NO_EXEMPTION, etc. */ +#include /* adf_nbuf_t, etc. */ +#include /* adf_os_assert */ +#include /* adf_os_spinlock */ +#include /* TAILQ */ +#include +#include +#include +#include +/*DFS Utility Include END*/ + +/* From wlan_modules/include/ */ +#include "ath_dfs_structs.h" +/*DFS - Newly added File to interface cld UMAC and dfs data structures*/ +#include +/* +*TO DO DFS- Need to include this file later on +#include "ah.h" +*/ +//#include "ah_desc.h" +#include "dfs_ioctl.h" +#include "dfs_ioctl_private.h" +#include "dfs_interface.h" +#include "_ieee80211_common.h" +#include "vos_api.h" + +#define ATH_SUPPORT_DFS 1 +#define CHANNEL_TURBO 0x00010 +#define DFS_PRINTK(_fmt, ...) printk((_fmt), __VA_ARGS__) +#define DFS_DPRINTK(dfs, _m, _fmt, ...) do { \ + if (((dfs) == NULL) || \ + ((dfs) != NULL && \ + ((_m) & (dfs)->dfs_debug_mask))) { \ + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_DEBUG, _fmt, __VA_ARGS__);\ + } \ +} while (0) + +#define DFS_MIN(a,b) ((a)<(b)?(a):(b)) +#define DFS_MAX(a,b) ((a)>(b)?(a):(b)) +#define DFS_DIFF(a,b) (DFS_MAX(a,b) - DFS_MIN(a,b)) +/* + * Maximum number of radar events to be processed in a single iteration. + * Allows soft watchdog to run. + */ +#define MAX_EVENTS 100 + +#define DFS_STATUS_SUCCESS 0 +#define DFS_STATUS_FAIL 1 + +/* + * Constants to use for chirping detection. + * + * All are unconverted as HW reports them. + * + * XXX Are these constants with or without fast clock 5GHz operation? + * XXX Peregrine reports pulses in microseconds, not hardware clocks! + */ +#define MIN_BIN5_DUR 63 /* 50 * 1.25*/ +#define MIN_BIN5_DUR_MICROSEC 50 +#define MAYBE_BIN5_DUR 35 /* 28 * 1.25*/ +#define MAYBE_BIN5_DUR_MICROSEC 28 +//#define MAX_BIN5_DUR 131 /* 105 * 1.25*/ +#define MAX_BIN5_DUR 145 /* use 145 for osprey */ //conversion is already done using dfs->dur_multiplier// +#define MAX_BIN5_DUR_MICROSEC 105 + +#define DFS_MARGIN_EQUAL(a, b, margin) ((DFS_DIFF(a,b)) <= margin) +#define DFS_MAX_STAGGERED_BURSTS 3 + +/* All filter thresholds in the radar filter tables are effective at a 50% channel loading */ +#define DFS_CHAN_LOADING_THRESH 50 +#define DFS_EXT_CHAN_LOADING_THRESH 30 +#define DFS_DEFAULT_PRI_MARGIN 6 +#define DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN 4 +#define ATH_DFSQ_LOCK(_dfs) spin_lock_dpc((&(_dfs)->dfs_radarqlock)) +#define ATH_DFSQ_UNLOCK(_dfs) spin_unlock_dpc((&(_dfs)->dfs_radarqlock)) +#define ATH_DFSQ_LOCK_INIT(_dfs) adf_os_spinlock_init(&(_dfs)->dfs_radarqlock) + +#define ATH_ARQ_LOCK(_dfs) spin_lock_dpc((&(_dfs)->dfs_arqlock)) +#define ATH_ARQ_UNLOCK(_dfs) spin_unlock_dpc((&(_dfs)->dfs_arqlock)) +#define ATH_ARQ_LOCK_INIT(_dfs) adf_os_spinlock_init(&(_dfs)->dfs_arqlock) + +#define ATH_DFSEVENTQ_LOCK(_dfs) spin_lock_dpc((&(_dfs)->dfs_eventqlock)) +#define ATH_DFSEVENTQ_UNLOCK(_dfs) spin_unlock_dpc((&(_dfs)->dfs_eventqlock)) +#define ATH_DFSEVENTQ_LOCK_INIT(_dfs) adf_os_spinlock_init((&(_dfs)->dfs_eventqlock)); + + + + + +#define DFS_TSMASK 0xFFFFFFFF /* Mask for time stamp from descriptor */ +#define DFS_TSSHIFT 32 /* Shift for time stamp from descriptor */ +#define DFS_TSF_WRAP 0xFFFFFFFFFFFFFFFFULL /* 64 bit TSF wrap value */ +#define DFS_64BIT_TSFMASK 0x0000000000007FFFULL /* TS mask for 64 bit value */ + + +#define DFS_AR_RADAR_RSSI_THR 5 /* in dB */ +#define DFS_AR_RADAR_RESET_INT 1 /* in secs */ +#define DFS_AR_RADAR_MAX_HISTORY 500 +#define DFS_AR_REGION_WIDTH 128 +#define DFS_AR_RSSI_THRESH_STRONG_PKTS 17 /* in dB */ +#define DFS_AR_RSSI_DOUBLE_THRESHOLD 15 /* in dB */ +#define DFS_AR_MAX_NUM_ACK_REGIONS 9 +#define DFS_AR_ACK_DETECT_PAR_THRESH 20 +#define DFS_AR_PKT_COUNT_THRESH 20 + +#define DFS_MAX_DL_SIZE 64 +#define DFS_MAX_DL_MASK 0x3F + +#define DFS_NOL_TIME DFS_NOL_TIMEOUT_US + /* 30 minutes in usecs */ + +#define DFS_WAIT_TIME 60*1000000 /* 1 minute in usecs */ + +#define DFS_DISABLE_TIME 3*60*1000000 /* 3 minutes in usecs */ + +#define DFS_MAX_B5_SIZE 128 +#define DFS_MAX_B5_MASK 0x0000007F /* 128 */ + +#define DFS_MAX_RADAR_OVERLAP 16 /* Max number of overlapping filters */ + +#define DFS_MAX_EVENTS 1024 /* Max number of dfs events which can be q'd */ + +#define DFS_RADAR_EN 0x80000000 /* Radar detect is capable */ +#define DFS_AR_EN 0x40000000 /* AR detect is capable */ +#define DFS_MAX_RSSI_VALUE 0x7fffffff /* Max rssi value */ + +#define DFS_BIN_MAX_PULSES 60 /* max num of pulses in a burst */ +#define DFS_BIN5_PRI_LOWER_LIMIT 990 /* us */ + +/* to cover the single pusle burst case, change from 2010 us to 2010000 us */ + +/* + * this is reverted back to 2010 as larger value causes false + * bin5 detect (EV76432, EV76320) + */ +#define DFS_BIN5_PRI_HIGHER_LIMIT 2010 /* us */ + +#define DFS_BIN5_WIDTH_MARGIN 4 /* us */ +#define DFS_BIN5_RSSI_MARGIN 5 /* dBm */ +/*Following threshold is not specified but should be okay statistically*/ +#define DFS_BIN5_BRI_LOWER_LIMIT 300000 /* us */ +#define DFS_BIN5_BRI_UPPER_LIMIT 12000000 /* us */ + +#define DFS_MAX_PULSE_BUFFER_SIZE 1024 /* Max number of pulses kept in buffer */ +#define DFS_MAX_PULSE_BUFFER_MASK 0x3ff + +#define DFS_FAST_CLOCK_MULTIPLIER (800/11) +#define DFS_NO_FAST_CLOCK_MULTIPLIER (80) + +#define DFS_WAR_PLUS_30_MHZ_SEPARATION 30 +#define DFS_WAR_MINUS_30_MHZ_SEPARATION -30 +#define DFS_WAR_PEAK_INDEX_ZERO 0 +#define DFS_TYPE4_WAR_PULSE_DURATION_LOWER_LIMIT 11 +#define DFS_TYPE4_WAR_PULSE_DURATION_UPPER_LIMIT 33 +#define DFS_TYPE4_WAR_PRI_LOWER_LIMIT 200 +#define DFS_TYPE4_WAR_PRI_UPPER_LIMIT 500 +#define DFS_TYPE4_WAR_VALID_PULSE_DURATION 12 +#define DFS_ETSI_TYPE2_TYPE3_WAR_PULSE_DUR_LOWER_LIMIT 15 +#define DFS_ETSI_TYPE2_TYPE3_WAR_PULSE_DUR_UPPER_LIMIT 33 +#define DFS_ETSI_TYPE2_WAR_PRI_LOWER_LIMIT 625 +#define DFS_ETSI_TYPE2_WAR_PRI_UPPER_LIMIT 5000 +#define DFS_ETSI_TYPE3_WAR_PRI_LOWER_LIMIT 250 +#define DFS_ETSI_TYPE3_WAR_PRI_UPPER_LIMIT 435 +#define DFS_ETSI_WAR_VALID_PULSE_DURATION 15 + +typedef adf_os_spinlock_t dfsq_lock_t; + +#ifdef WIN32 +#pragma pack(push, dfs_pulseparams, 1) +#endif +struct dfs_pulseparams { + u_int64_t p_time; /* time for start of pulse in usecs*/ + u_int8_t p_dur; /* Duration of pulse in usecs*/ + u_int8_t p_rssi; /* Duration of pulse in usecs*/ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_pulseparams) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_pulseline, 1) +#endif +struct dfs_pulseline { + /* pl_elems - array of pulses in delay line */ + struct dfs_pulseparams pl_elems[DFS_MAX_PULSE_BUFFER_SIZE]; + u_int32_t pl_firstelem; /* Index of the first element */ + u_int32_t pl_lastelem; /* Index of the last element */ + u_int32_t pl_numelems; /* Number of elements in the delay line */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_pulseline) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_event, 1) +#endif + +#define DFS_EVENT_CHECKCHIRP 0x01 /* Whether to check the chirp flag */ +#define DFS_EVENT_HW_CHIRP 0x02 /* hardware chirp */ +#define DFS_EVENT_SW_CHIRP 0x04 /* software chirp */ + +/* + * Use this only if the event has CHECKCHIRP set. + */ +#define DFS_EVENT_ISCHIRP(e) \ + ((e)->re_flags & (DFS_EVENT_HW_CHIRP | DFS_EVENT_SW_CHIRP)) + +/* + * Check if the given event is to be rejected as not possibly + * a chirp. This means: + * (a) it's a hardware or software checked chirp, and + * (b) the HW/SW chirp bits are both 0. + */ +#define DFS_EVENT_NOTCHIRP(e) \ + (((e)->re_flags & (DFS_EVENT_CHECKCHIRP)) && \ + (! DFS_EVENT_ISCHIRP((e)))) + +struct dfs_event { + u_int64_t re_full_ts; /* 64-bit full timestamp from interrupt time */ + u_int32_t re_ts; /* Original 15 bit recv timestamp */ + u_int8_t re_rssi; /* rssi of radar event */ + u_int8_t re_dur; /* duration of radar pulse */ + u_int8_t re_chanindex; /* Channel of event */ + u_int8_t re_flags; /* Event flags */ + u_int32_t re_freq; /* Centre frequency of event, KHz */ + u_int32_t re_freq_lo; /* Lower bounds of frequency, KHz */ + u_int32_t re_freq_hi; /* Upper bounds of frequency, KHz */ + int sidx; /* Pulse Index as in radar summary report */ + STAILQ_ENTRY(dfs_event) re_list; /* List of radar events */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_event) +#endif + +#define DFS_AR_MAX_ACK_RADAR_DUR 511 +#define DFS_AR_MAX_NUM_PEAKS 3 +#define DFS_AR_ARQ_SIZE 2048 /* 8K AR events for buffer size */ +#define DFS_AR_ARQ_SEQSIZE 2049 /* Sequence counter wrap for AR */ + +#define DFS_RADARQ_SIZE 512 /* 1K radar events for buffer size */ +#define DFS_RADARQ_SEQSIZE 513 /* Sequence counter wrap for radar */ +#define DFS_NUM_RADAR_STATES 64 /* Number of radar channels we keep state for */ +#define DFS_MAX_NUM_RADAR_FILTERS 10 /* Max number radar filters for each type */ +#define DFS_MAX_RADAR_TYPES 32 /* Number of different radar types */ + +struct dfs_ar_state { + u_int32_t ar_prevwidth; + u_int32_t ar_phyerrcount[DFS_AR_MAX_ACK_RADAR_DUR]; + u_int32_t ar_acksum; + u_int32_t ar_packetthreshold; /* Thresh to determine traffic load */ + u_int32_t ar_parthreshold; /* Thresh to determine peak */ + u_int32_t ar_radarrssi; /* Rssi threshold for AR event */ + u_int16_t ar_prevtimestamp; + u_int16_t ar_peaklist[DFS_AR_MAX_NUM_PEAKS]; +}; + +#ifdef WIN32 +#pragma pack(push, dfs_delayelem, 1) +#endif +struct dfs_delayelem { + u_int32_t de_time; /* Current "filter" time for start of pulse in usecs*/ + u_int8_t de_dur; /* Duration of pulse in usecs*/ + u_int8_t de_rssi; /* rssi of pulse in dB*/ + u_int64_t de_ts; /* time stamp for this delay element */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_delayelem) +#endif + +/* NB: The first element in the circular buffer is the oldest element */ + +#ifdef WIN32 +#pragma pack(push, dfs_delayline, 1) +#endif +struct dfs_delayline { + struct dfs_delayelem dl_elems[DFS_MAX_DL_SIZE]; /* Array of pulses in delay line */ + u_int64_t dl_last_ts; /* Last timestamp the delay line was used (in usecs) */ + u_int32_t dl_firstelem; /* Index of the first element */ + u_int32_t dl_lastelem; /* Index of the last element */ + u_int32_t dl_numelems; /* Number of elements in the delay line */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_delayline) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_filter, 1) +#endif +struct dfs_filter { + struct dfs_delayline rf_dl; /* Delay line of pulses for this filter */ + u_int32_t rf_numpulses; /* Number of pulses in the filter */ + u_int32_t rf_minpri; /* min pri to be considered for this filter*/ + u_int32_t rf_maxpri; /* max pri to be considered for this filter*/ + u_int32_t rf_threshold; /* match filter output threshold for radar detect */ + u_int32_t rf_filterlen; /* Length (in usecs) of the filter */ + u_int32_t rf_patterntype; /* fixed or variable pattern type */ + u_int32_t rf_fixed_pri_radar_pulse; /* indicates if it is a fixed pri pulse */ + u_int32_t rf_mindur; /* Min duration for this radar filter */ + u_int32_t rf_maxdur; /* Max duration for this radar filter */ + u_int32_t rf_ignore_pri_window; + u_int32_t rf_pulseid; /* Unique ID corresponding to the original filter ID */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_filter) +#endif + +struct dfs_filtertype { + struct dfs_filter ft_filters[DFS_MAX_NUM_RADAR_FILTERS]; + u_int32_t ft_filterdur; /* Duration of pulse which specifies filter type*/ + u_int32_t ft_numfilters; /* Num filters of this type */ + u_int64_t ft_last_ts; /* Last timestamp this filtertype was used + * (in usecs) */ + u_int32_t ft_mindur; /* min pulse duration to be considered + * for this filter type */ + u_int32_t ft_maxdur; /* max pulse duration to be considered + * for this filter type */ + u_int32_t ft_rssithresh; /* min rssi to be considered + * for this filter type */ + u_int32_t ft_numpulses; /* Num pulses in each filter of this type */ + u_int32_t ft_patterntype; /* fixed or variable pattern type */ + u_int32_t ft_minpri; /* min pri to be considered for this type */ + u_int32_t ft_rssimargin; /* rssi threshold margin. In Turbo Mode HW + * reports rssi 3dB lower than in non TURBO + * mode. This will offset that diff. */ +}; + +struct dfs_state { + struct ieee80211_channel rs_chan; /* Channel info */ + u_int8_t rs_chanindex; /* Channel index in radar structure */ + u_int32_t rs_numradarevents; /* Number of radar events */ + + struct ath_dfs_phyerr_param rs_param; +}; + +#define DFS_NOL_TIMEOUT_S (30*60) /* 30 minutes in seconds */ +//#define DFS_NOL_TIMEOUT_S (5*60) /* 5 minutes in seconds - debugging */ +#define DFS_NOL_TIMEOUT_MS (DFS_NOL_TIMEOUT_S * 1000) +#define DFS_NOL_TIMEOUT_US (DFS_NOL_TIMEOUT_MS * 1000) + +#ifdef WIN32 +#pragma pack(push, dfs_nolelem, 1) +#endif +struct dfs_nolelem { + u_int32_t nol_freq; /* centre frequency */ + u_int32_t nol_chwidth; /* event width (MHz) */ + unsigned long nol_start_ticks; /* NOL start time in OS ticks */ + u_int32_t nol_timeout_ms; /* NOL timeout value in msec */ + os_timer_t nol_timer; /* per element NOL timer */ + struct dfs_nolelem *nol_next; /* next element pointer */ +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_nolelem) +#endif + +/* Pass structure to DFS NOL timer */ +struct dfs_nol_timer_arg { + struct ath_dfs *dfs; + u_int16_t delfreq; + u_int16_t delchwidth; +}; + +#ifdef WIN32 +#pragma pack(push, dfs_info, 1) +#endif +struct dfs_info { + int rn_use_nol; /* Use the NOL when radar found (default: TRUE) */ + u_int32_t rn_numradars; /* Number of different types of radars */ + u_int64_t rn_lastfull_ts; /* Last 64 bit timstamp from recv interrupt */ + u_int16_t rn_last_ts; /* last 15 bit ts from recv descriptor */ + u_int32_t rn_last_unique_ts; /* last unique 32 bit ts from recv descriptor */ + + u_int64_t rn_ts_prefix; /* Prefix to prepend to 15 bit recv ts */ + u_int32_t rn_numbin5radars; /* Number of bin5 radar pulses to search for */ + u_int32_t rn_fastdivGCval; /* Value of fast diversity gc limit from init file */ + int32_t rn_minrssithresh; /* Min rssi for all radar types */ + u_int32_t rn_maxpulsedur; /* Max pulse width in TSF ticks */ + + u_int8_t dfs_ext_chan_busy; + u_int64_t ext_chan_busy_ts; + + u_int64_t dfs_bin5_chirp_ts; + u_int8_t dfs_last_bin5_dur; +} adf_os_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_info) +#endif + +struct dfs_bin5elem { + u_int64_t be_ts; /* Timestamp for the bin5 element */ + u_int32_t be_rssi; /* Rssi for the bin5 element */ + u_int32_t be_dur; /* Duration of bin5 element */ +}; + +struct dfs_bin5radars { + struct dfs_bin5elem br_elems[DFS_MAX_B5_SIZE]; /* List of bin5 elems that fall + * within the time window */ + u_int32_t br_firstelem; /* Index of the first element */ + u_int32_t br_lastelem; /* Index of the last element */ + u_int32_t br_numelems; /* Number of elements in the delay line */ + struct dfs_bin5pulse br_pulse; /* Original info about bin5 pulse */ +}; + +struct dfs_stats { + u_int32_t num_radar_detects; /* total num. of radar detects */ + u_int32_t total_phy_errors; + u_int32_t owl_phy_errors; + u_int32_t pri_phy_errors; + u_int32_t ext_phy_errors; + u_int32_t dc_phy_errors; + u_int32_t early_ext_phy_errors; + u_int32_t bwinfo_errors; + u_int32_t datalen_discards; + u_int32_t rssi_discards; + u_int64_t last_reset_tstamp; +}; + +/* + * This is for debuggin DFS as console log interferes with (helps) + * radar detection +*/ + +#define DFS_EVENT_LOG_SIZE 256 +struct dfs_event_log { + u_int64_t ts; /* 64-bit full timestamp from interrupt time */ + u_int32_t diff_ts; /* diff timestamp */ + u_int8_t rssi; /* rssi of radar event */ + u_int8_t dur; /* duration of radar pulse */ +}; + + +#define ATH_DFS_RESET_TIME_S 7 +#define ATH_DFS_WAIT (60 + ATH_DFS_RESET_TIME_S) /* 60 seconds */ +#define ATH_DFS_WAIT_MS ((ATH_DFS_WAIT) * 1000) /*in MS*/ + +#define ATH_DFS_WEATHER_CHANNEL_WAIT_MIN 10 /*10 minutes*/ +#define ATH_DFS_WEATHER_CHANNEL_WAIT_S (ATH_DFS_WEATHER_CHANNEL_WAIT_MIN * 60) +#define ATH_DFS_WEATHER_CHANNEL_WAIT_MS ((ATH_DFS_WEATHER_CHANNEL_WAIT_S) * 1000) /*in MS*/ + +#define ATH_DFS_WAIT_POLL_PERIOD 2 /* 2 seconds */ +#define ATH_DFS_WAIT_POLL_PERIOD_MS ((ATH_DFS_WAIT_POLL_PERIOD) * 1000) /*in MS*/ +#define ATH_DFS_TEST_RETURN_PERIOD 2 /* 2 seconds */ +#define ATH_DFS_TEST_RETURN_PERIOD_MS ((ATH_DFS_TEST_RETURN_PERIOD) * 1000)/* n MS*/ +#define IS_CHANNEL_WEATHER_RADAR(chan) ((chan->ic_freq >= 5600) && (chan->ic_freq <= 5650)) + +#define DFS_DEBUG_TIMEOUT_S 30 // debug timeout is 30 seconds +#define DFS_DEBUG_TIMEOUT_MS (DFS_DEBUG_TIMEOUT_S * 1000) + + +#define RSSI_POSSIBLY_FALSE 50 +#define SEARCH_FFT_REPORT_PEAK_MAG_THRSH 40 + + + +#if 0 +struct ath_dfs_caps { + u_int32_t + ath_dfs_ext_chan_ok:1, /* Can radar be detected on the extension chan? */ + ath_dfs_combined_rssi_ok:1, /* Can use combined radar RSSI? */ + /* the following flag is used to indicate if radar detection scheme */ + /* should use enhanced chirping detection algorithm. This flag also */ + /* determines if certain radar data should be discarded to minimize */ + /* false detection of radar. */ + ath_dfs_use_enhancement:1, + ath_strong_signal_diversiry:1; + + /* + * goes with ath_strong_signal_diversiry: + * If we have fast diversity capability, read off + * Strong Signal fast diversity count set in the ini + * file, and store so we can restore the value when + * radar is disabled + */ + u_int32_t ath_fastdiv_val; +}; + +struct ath_dfs_radar_tab_info { + u_int32_t dfsdomain; + int numradars; + struct dfs_pulse *dfs_radars; + int numb5radars; + struct dfs_bin5pulse *b5pulses; + HAL_PHYERR_PARAM dfs_defaultparams; +}; +#endif +struct ath_dfs { + uint32_t dfs_debug_mask; /* current debug bitmask */ + int16_t dfs_curchan_radindex; /* cur. channel radar index */ + int16_t dfs_extchan_radindex; /* extension channel radar index */ + u_int32_t dfsdomain; /* cur. DFS domain */ + u_int32_t dfs_proc_phyerr; /* Flags for Phy Errs to process */ + struct ieee80211com *ic; + STAILQ_HEAD(,dfs_event) dfs_eventq; /* Q of free dfs event objects */ + dfsq_lock_t dfs_eventqlock; /* Lock for free dfs event list */ + STAILQ_HEAD(,dfs_event) dfs_radarq; /* Q of radar events */ + dfsq_lock_t dfs_radarqlock; /* Lock for dfs q */ + STAILQ_HEAD(,dfs_event) dfs_arq; /* Q of AR events */ + dfsq_lock_t dfs_arqlock; /* Lock for AR q */ + + struct dfs_ar_state dfs_ar_state; /* AR state */ + + /* dfs_radar - Per-Channel Radar detector state */ + struct dfs_state dfs_radar[DFS_NUM_RADAR_STATES]; + + /* dfs_radarf - One filter for each radar pulse type */ + struct dfs_filtertype *dfs_radarf[DFS_MAX_RADAR_TYPES]; + + struct dfs_info dfs_rinfo; /* State vars for radar processing */ + struct dfs_bin5radars *dfs_b5radars;/* array of bin5 radar events */ + int8_t **dfs_radartable; /* map of radar durs to filter types */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + struct dfs_nolelem *dfs_nol; /* Non occupancy list for radar */ + int dfs_nol_count; /* How many items? */ +#endif + + struct ath_dfs_phyerr_param dfs_defaultparams; /* Default phy params per radar state */ + struct dfs_stats ath_dfs_stats; /* DFS related stats */ + struct dfs_pulseline *pulses; /* pulse history */ + struct dfs_event *events; /* Events structure */ + + u_int32_t + ath_radar_tasksched:1, /* radar task is scheduled */ + ath_dfswait:1, /* waiting on channel for radar detect */ + ath_dfstest:1; /* Test timer in progress */ + struct ath_dfs_caps dfs_caps; + u_int8_t ath_dfstest_ieeechan; /* IEEE chan num to return to after + * a dfs mute test */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + u_int32_t ath_dfs_cac_time; /* CAC period */ + u_int32_t ath_dfstesttime; /* Time to stay off chan during dfs test */ + os_timer_t ath_dfswaittimer; /* dfs wait timer */ + os_timer_t ath_dfstesttimer; /* dfs mute test timer */ + os_timer_t ath_dfs_debug_timer; /* dfs debug timer */ + u_int8_t dfs_bangradar; +#endif + os_timer_t ath_dfs_task_timer; /* dfs wait timer */ + int dur_multiplier; + + u_int16_t ath_dfs_isdfsregdomain; /* true when we are DFS domain */ + int ath_dfs_false_rssi_thres; + int ath_dfs_peak_mag; + + struct dfs_event_log radar_log[DFS_EVENT_LOG_SIZE]; + int dfs_event_log_count; + int dfs_event_log_on; + int dfs_phyerr_count; /* same as number of PHY radar interrupts */ + int dfs_phyerr_reject_count; /* when TLV is supported, # of radar events ignored after TLV is parsed */ + int dfs_phyerr_queued_count; /* number of radar events queued for matching the filters */ + int dfs_phyerr_freq_min; + int dfs_phyerr_freq_max; + int dfs_phyerr_w53_counter; + int dfs_pri_multiplier; /* allow pulse if they are within multiple of PRI for the radar type */ + int ath_dfs_nol_timeout; + int dfs_pri_multiplier_ini; /* dfs pri configuration from ini */ + /* + * Flag to indicate if DFS test mode is enabled and + * channel switch is disabled. + */ + int8_t disable_dfs_ch_switch; +}; + +/* This should match the table from if_ath.c */ +enum { + ATH_DEBUG_DFS = 0x00000100, /* Minimal DFS debug */ + ATH_DEBUG_DFS1 = 0x00000200, /* Normal DFS debug */ + ATH_DEBUG_DFS2 = 0x00000400, /* Maximal DFS debug */ + ATH_DEBUG_DFS3 = 0x00000800, /* matched filterID display */ + + ATH_DEBUG_DFS_PHYERR = 0x00001000, /* phy error parsing */ + ATH_DEBUG_DFS_NOL = 0x00002000, /* NOL related entries */ + ATH_DEBUG_DFS_PHYERR_SUM = 0x00004000, /* PHY error summary */ + ATH_DEBUG_DFS_PHYERR_PKT = 0x00008000, /* PHY error payload */ + + ATH_DEBUG_DFS_BIN5 = 0x00010000, /* bin5 checks */ + ATH_DEBUG_DFS_BIN5_FFT = 0x00020000, /* bin5 FFT check */ + ATH_DEBUG_DFS_BIN5_PULSE = 0x00040000, /* bin5 pulse check */ +}; + +#define IS_CHAN_HT40(_c) IEEE80211_IS_CHAN_11N_HT40(_c) +#define IS_CHAN_HT40_PLUS(_c) IEEE80211_IS_CHAN_11N_HT40PLUS(_c) +#define IS_CHAN_HT40_MINUS(_c) IEEE80211_IS_CHAN_11N_HT40MINUS(_c) + +/* + * chirp notes! + * + * Pre-Sowl chips don't do FFT reports, so chirp pulses simply show up + * as long duration pulses. + * + * The bin5 checking code would simply look for a chirp pulse of the correct + * duration (within MIN_BIN5_DUR and MAX_BIN5_DUR) and add it to the "chirp" + * pattern. + * + * For Sowl and later, an FFT was done on longer duration frames. If those + * frames looked like a chirp, their duration was adjusted to fall within + * the chirp duration limits. If the pulse failed the chirp test (it had + * no FFT data or the FFT didn't meet the chirping requirements) then the + * pulse duration was adjusted to be greater than MAX_BIN5_DUR, so it + * would always fail chirp detection. + * + * This is pretty horrible. + * + * The eventual goal for chirp handling is thus: + * + * + In case someone ever wants to do chirp detection with this code on + * chips that don't support chirp detection, you can still do it based + * on pulse duration. That's your problem to solve. + * + * + For chips that do hardware chirp detection or FFT, the "do_check_chirp" + * bit should be set. + * + * + Then, either is_hw_chirp or is_sw_chirp is set, indicating that + * the hardware or software post-processing of the chirp event found + * that indeed it was a chirp. + * + * + Finally, the bin5 code should just check whether the chirp bits are + * set and behave appropriately, falling back onto the duration checks + * if someone wishes to use this on older hardware (or with disabled + * FFTs, for whatever reason.) + */ +/* + * XXX TODO: + * + * + add duration in uS and raw duration, so the PHY error parsing + * code is responsible for doing the duration calculation; + * + add ts in raw and corrected, so the PHY error parsing + * code is responsible for doing the offsetting, not the radar + * event code. + */ +struct dfs_phy_err { + u_int64_t fulltsf; /* 64-bit TSF as read from MAC */ + + uint32_t is_pri:1, /* detected on primary channel */ + is_ext:1, /* detected on extension channel */ + is_dc:1, /* detected at DC */ + is_early:1, /* early detect */ + do_check_chirp:1, /* whether to check hw_chirp/sw_chirp */ + is_hw_chirp:1, /* hardware-detected chirp */ + is_sw_chirp:1; /* software detected chirp */ + + u_int32_t rs_tstamp; /* 32 bit TSF from RX descriptor (event) */ + u_int32_t freq; /* Centre frequency of event - KHz */ + u_int32_t freq_lo; /* Lower bounds of frequency - KHz */ + u_int32_t freq_hi; /* Upper bounds of frequency - KHz */ + + u_int8_t rssi; /* pulse RSSI */ + u_int8_t dur; /* pulse duration, raw (not uS) */ + int sidx; /* Pulse Index as in radar summary report */ +}; + +/* Attach, detach, handle ioctl prototypes */ + +int dfs_get_thresholds(struct ieee80211com *ic, + struct ath_dfs_phyerr_param *param); +int dfs_set_thresholds(struct ieee80211com *ic, + const u_int32_t threshtype, const u_int32_t value); + +/* PHY error and radar event handling */ +int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan); + +/* Non occupancy (NOL) handling prototypes */ +void dfs_nol_addchan(struct ath_dfs *dfs, struct ieee80211_channel *chan, u_int32_t dfs_nol_timeout); +void dfs_get_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int *nchan); +void dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan); +void dfs_nol_update(struct ath_dfs *dfs); +void dfs_nol_timer_cleanup(struct ath_dfs *dfs); + +/* FCC Bin5 detection prototypes */ +int dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re, + struct dfs_bin5radars *br); +int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, + struct dfs_event *re, u_int64_t thists); +int dfs_bin5_check(struct ath_dfs *dfs); +int dfs_check_chirping(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, int is_ctl, + int is_ext, int *slope, int *is_dc); +u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, u_int32_t diff_ts, u_int8_t old_dur); +u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, u_int32_t diff_ts, u_int8_t old_dur); +int dfs_get_random_bin5_dur(struct ath_dfs *dfs, u_int64_t tstamp); + +/* Debug prototypes */ +void dfs_print_delayline(struct ath_dfs *dfs, struct dfs_delayline *dl); +void dfs_print_nol(struct ath_dfs *dfs); +void dfs_print_filters(struct ath_dfs *dfs); +void dfs_print_activity(struct ath_dfs *dfs); +OS_TIMER_FUNC(dfs_debug_timeout); +void dfs_print_filter(struct ath_dfs *dfs, struct dfs_filter *rf); + +/* Misc prototypes */ +u_int32_t dfs_round(int32_t val); +struct dfs_state* dfs_getchanstate(struct ath_dfs *dfs, u_int8_t *index, int ext_ch_flag); + +/* Reset and init data structures */ + +int dfs_init_radar_filters( struct ieee80211com *ic, struct ath_dfs_radar_tab_info *radar_info); +void dfs_reset_alldelaylines(struct ath_dfs *dfs); +void dfs_reset_delayline(struct dfs_delayline *dl); +void dfs_reset_filter_delaylines(struct dfs_filtertype *dft); +void dfs_reset_radarq(struct ath_dfs *dfs); + +/* Detection algorithm prototypes */ +void dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_event *re, u_int32_t deltaT, u_int64_t this_ts); + +int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t dur, int ext_chan_flag); +int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t deltaT, u_int32_t dur, int ext_chan_flag); + +int dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_delayline *dl, u_int32_t score, + u_int32_t refpri, u_int32_t refdur, int ext_chan_flag, int fundamentalpri); +int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t deltaT, u_int32_t width); +/* False detection reduction */ +int dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, + int is_fixed_pattern); +int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, + int is_extchan_detect); + +/* AR related prototypes */ + +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void dfs_process_ar_event(struct ath_dfs *dfs, struct ieee80211_channel *chan); + */ +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void ath_ar_disable(struct ath_dfs *dfs); + */ +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void ath_ar_enable(struct ath_dfs *dfs); + */ +void dfs_reset_ar(struct ath_dfs *dfs); +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * void dfs_reset_arq(struct ath_dfs *dfs); + */ + + +struct ieee80211_channel *ieee80211_get_extchan(struct ieee80211com *ic); + +#endif /* _DFS_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs_interface.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs_interface.h new file mode 100644 index 000000000000..546e513a831c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/dfs_interface.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_interface.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#ifndef _DFS__INTERFACE_H_ +#define _DFS__INTERFACE_H_ + +/* + * These are the only functions exported to the upper (device) layer. + */ + +/* + * EXPORT_SYMBOL(dfs_attach); + * EXPORT_SYMBOL(dfs_detach); + * EXPORT_SYMBOL(dfs_radar_enable); + * EXPORT_SYMBOL(dfs_process_phyerr); + * EXPORT_SYMBOL(dfs_control); + * EXPORT_SYMBOL(dfs_clear_stats); + * EXPORT_SYMBOL(dfs_usenol); + * EXPORT_SYMBOL(dfs_isdfsregdomain); + */ + +/* + * These are exported but not currently defined here; these should be + * evaluated. + * + * EXPORT_SYMBOL(dfs_process_ar_event); -- legacy adaptive radio processing + * EXPORT_SYMBOL(ath_ar_disable); + * EXPORT_SYMBOL(ath_ar_enable); + * EXPORT_SYMBOL(dfs_get_thresholds); + * EXPORT_SYMBOL(dfs_init_radar_filters); + * EXPORT_SYMBOL(dfs_getchanstate); + */ + + +u_int16_t dfs_isdfsregdomain(struct ieee80211com *ic); +int dfs_attach(struct ieee80211com *ic); +void dfs_detach(struct ieee80211com *ic); +int dfs_radar_enable(struct ieee80211com *ic, + struct ath_dfs_radar_tab_info *ri); +int dfs_radar_disable(struct ieee80211com *ic); +extern void dfs_process_phyerr(struct ieee80211com *ic, void *buf, + u_int16_t datalen, u_int8_t rssi, + u_int8_t ext_rssi, u_int32_t rs_tstamp, + u_int64_t fulltsf, bool enable_log); +int dfs_control(struct ieee80211com *ic, u_int id, void *indata, u_int32_t insize, + void *outdata, u_int32_t *outsize); +void dfs_clear_stats(struct ieee80211com *ic); +#if 0 +/* The following are for FCC Bin 1-4 pulses */ +struct dfs_pulse dfs_fcc_radars[] = { + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_pulse dfs_mkk4_radars[] = { + /* following two filters are specific to Japan/MKK4 */ +// {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 17}, // 1389 +/- 6 us +// {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 18}, // 4000 +/- 6 us +// {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 19}, // 3846 +/- 7 us + {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us + {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us + {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, // 3846 +/- 7 us + + /* following filters are common to both FCC and JAPAN */ + + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_bin5pulse dfs_fcc_bin5pulses[] = { + {4, 28, 105, 12, 22, 5}, +}; + +struct dfs_bin5pulse dfs_jpn_bin5pulses[] = { + {5, 28, 105, 12, 22, 5}, +}; +struct dfs_pulse dfs_etsi_radars[] = { + + /* TYPE staggered pulse */ + /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ + {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31}, /* Type 5*/ + /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */ + {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32}, /* Type 6 */ + + /* constant PRF based */ + /* 0.8-5us, 200 300 PRF, 10 pulses */ + {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ + {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ + {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ + {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ +// {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, + + /* 0.8-15us, 200-1600 PRF, 15 pulses */ + {15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34}, /* Type 2 */ + + /* 0.8-15us, 2300-4000 PRF, 25 pulses*/ + {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35}, /* Type 3 */ + + /* 20-30us, 2000-4000 PRF, 20 pulses*/ + {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ +}; +#endif +#endif /* _DFS__INTERFACE_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/radar_filters.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/radar_filters.h new file mode 100644 index 000000000000..73d3c785adb8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/inc/radar_filters.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + radar_filters.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + + + + +struct dfs_pulse dfs_fcc_radars[] = { + // FCC NEW TYPE 0 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 8, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 20, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 20, 0, 3, 0, 11}, + + /* + * FCC NEW TYPE 1 + * 518us to 938us pulses (min 56 pulses) + */ + {57, 1, 1066, 1930, 0, 6, 20, 0, 1, 22, 0, 3, 0, 21}, + + /* + * FCC NEW TYPE 1 + * 938us to 2000 pulses (min 26 pulses) + */ + {27, 1, 500, 1066, 0, 6, 13, 0, 1, 22, 0, 3, 0, 22}, + + /* + * FCC NEW TYPE 1 + * 2000 to 3067us pulses (min 17 pulses) + */ + {18, 1, 325, 500, 0, 6, 9, 0, 1, 22, 0, 3, 0, 23}, + +}; + +struct dfs_pulse dfs_mkk4_radars[] = { + /* following two filters are specific to Japan/MKK4 */ +// {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 17}, // 1389 +/- 6 us +// {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 18}, // 4000 +/- 6 us +// {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 19}, // 3846 +/- 7 us + {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us + {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us + {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, // 3846 +/- 7 us + + /* following filters are common to both FCC and JAPAN */ + + // FCC TYPE 1 + // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 + {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0}, + {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, + + // FCC TYPE 6 + // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us + {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1}, + + // FCC TYPE 2 + {23, 5, 4347, 6666, 0, 18, 8, 0, 7, 22, 0, 3, 0, 2}, + + // FCC TYPE 3 + {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5}, + + // FCC TYPE 4 + {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 22, 0, 3, 0, 11}, +}; + +struct dfs_bin5pulse dfs_fcc_bin5pulses[] = { + {4, 28, 105, 12, 17, 5}, +}; + +struct dfs_bin5pulse dfs_jpn_bin5pulses[] = { + {5, 28, 105, 12, 22, 5}, +}; +struct dfs_pulse dfs_etsi_radars[] = { + + /* TYPE staggered pulse */ + /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ + {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31}, /* Type 5*/ + /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */ + {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32}, /* Type 6 */ + + /* constant PRF based */ + /* 0.8-5us, 200 300 PRF, 10 pulses */ + {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ + {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ + {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ + {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ +// {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, + + /* 0.8-15us, 200-1600 PRF, 15 pulses */ + {15, 15, 200, 1600, 0, 24, 8, 0, 18, 22, 0, 0, 0, 34}, /* Type 2 */ + + /* 0.8-15us, 2300-4000 PRF, 25 pulses*/ + {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 22, 0, 0, 0, 35}, /* Type 3 */ + + /* 20-30us, 2000-4000 PRF, 20 pulses*/ + {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ +}; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/sources b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/sources new file mode 100644 index 000000000000..d27e9b807daf --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/sources @@ -0,0 +1,62 @@ +# +# sources file for DFS module +# +LMAC=.. +TOP=$(LMAC)\.. +INC=$(TOP)\include +HAL=$(TOP)\hal +ATH=$(LMAC)\ath_dev + +!IFDEF BUILD_UMAC +MP=$(TOP)\os\win_nwf +INC_MP=$(MP)\include +IF_ATH=$(TOP)\umac\if_lmac +!ELSE +MP=$(TOP)\winvista +INC_MP=$(INC)\winvista +IF_ATH=$(TOP)\if_ath_net80211 +!ENDIF + +!include $(INC_MP)\sources.inc + +TARGETNAME=ath_dfs +TARGETPATH=$(TOP)\lib +TARGETTYPE=LIBRARY + +!IFDEF BUILD_HTC +# Put htc include dirs at the head of the list. +# This ensures that the htc/adf header files will preempt any +# header files of the same names from the regular adf directories. +INCLUDES= $(INCLUDES) \ + $(TOP)\htc\inc; \ + $(TOP)\htc\adf\include; \ + $(TOP)\htc\adf\winvista\nbuf; \ + $(TOP)\htc\adf\winvista\include; +!ENDIF + +INCLUDES= $(INCLUDES) \ + $(TOP); \ + $(ATH); \ + $(ATH_DFS); \ + $(TOP)\ath\winvista; \ + $(TOP)\ath\winvista; \ + $(HAL); \ + $(HAL)\winvista; \ + $(IF_ATH); \ + $(INC); \ + $(INC_MP); \ + $(SDXROOT)\net\inc; \ + $(DDK_INC_PATH) + +SOURCES=$(SOURCES) \ + dfs_staggered.c \ + dfs_bindetects.c \ + dfs_misc.c \ + dfs_debug.c \ + dfs_process_radarevent.c \ + dfs_process_phyerr.c \ + dfs_nol.c \ + dfs_ar.c \ + dfs_fcc_bin5.c \ + dfs_init.c \ + dfs.c diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs.c new file mode 100644 index 000000000000..803e99ecc1d4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs.c @@ -0,0 +1,987 @@ +/* + * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include + +#ifndef ATH_SUPPORT_DFS +#define ATH_SUPPORT_DFS 1 +#include "sys/queue.h" + +//#include "if_athioctl.h" +//#include "if_athvar.h" +#include "dfs_ioctl.h" +#include "dfs.h" + +int domainoverride=DFS_UNINIT_DOMAIN; + +/* + ** channel switch announcement (CSA) + ** usenol=1 (default) make CSA and switch to a new channel on radar detect + ** usenol=0, make CSA with next channel same as current on radar detect + ** usenol=2, no CSA and stay on the same channel on radar detect + **/ + +int usenol=1; +u_int32_t dfs_debug_level=ATH_DEBUG_DFS; + +#if 0 /* the code to call this is curently commented-out below */ +/* + * Mark a channel as having interference detected upon it. + * + * This adds the interference marker to both the primary and + * extension channel. + * + * XXX TODO: make the NOL and channel interference logic a bit smarter + * so only the channel with the radar event is marked, rather than + * both the primary and extension. + */ +static void +dfs_channel_mark_radar(struct ath_dfs *dfs, struct ieee80211_channel *chan) +{ + struct ieee80211_channel_list chan_info; + int i; + + //chan->ic_flagext |= CHANNEL_INTERFERENCE; + + /* + * If radar is detected in 40MHz mode, add both the primary and the + * extension channels to the NOL. chan is the channel data we return + * to the ath_dev layer which passes it on to the 80211 layer. + * As we want the AP to change channels and send out a CSA, + * we always pass back the primary channel data to the ath_dev layer. + */ + if ((dfs->dfs_rinfo.rn_use_nol == 1) && + (dfs->ic->ic_opmode == IEEE80211_M_HOSTAP || + dfs->ic->ic_opmode == IEEE80211_M_IBSS)) { + chan_info.cl_nchans= 0; + dfs->ic->ic_get_ext_chan_info (dfs->ic, &chan_info); + + for (i = 0; i < chan_info.cl_nchans; i++) + { + if (chan_info.cl_channels[i] == NULL) { + DFS_PRINTK("%s: NULL channel\n", __func__); + } else { + chan_info.cl_channels[i]->ic_flagext |= CHANNEL_INTERFERENCE; + dfs_nol_addchan(dfs, chan_info.cl_channels[i], dfs->ath_dfs_nol_timeout); + } + } + + + /* + * Update the umac/driver channels with the new NOL information. + */ + dfs_nol_update(dfs); + } +} +#endif /* #if 0 */ + +static OS_TIMER_FUNC(dfs_task) +{ + struct ieee80211com *ic; + struct ath_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + dfs = (struct ath_dfs *)ic->ic_dfs; + /* + * XXX no locking?! + */ + if (dfs_process_radarevent(dfs, ic->ic_curchan)) { +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + + /* + * This marks the channel (and the extension channel, if HT40) as + * having seen a radar event. It marks CHAN_INTERFERENCE and + * will add it to the local NOL implementation. + * + * This is only done for 'usenol=1', as the other two modes + * don't do radar notification or CAC/CSA/NOL; it just notes + * there was a radar. + */ + + if (dfs->dfs_rinfo.rn_use_nol == 1) { + //dfs_channel_mark_radar(dfs, ic->ic_curchan); + } +#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ + + /* + * This calls into the umac DFS code, which sets the umac related + * radar flags and begins the channel change machinery. + * + * XXX TODO: the umac NOL code isn't used, but IEEE80211_CHAN_RADAR + * still gets set. Since the umac NOL code isn't used, that flag + * is never cleared. This needs to be fixed. See EV 105776. + */ + if (dfs->dfs_rinfo.rn_use_nol == 1) { + ic->ic_dfs_notify_radar(ic, ic->ic_curchan); + } else if (dfs->dfs_rinfo.rn_use_nol == 0) { + /* + * For the test mode, don't do a CSA here; but setup the + * test timer so we get a CSA _back_ to the original channel. + */ + OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); + dfs->ath_dfstest = 1; + adf_os_spin_lock_bh(&ic->chan_lock); + dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee; + adf_os_spin_unlock_bh(&ic->chan_lock); + dfs->ath_dfstesttime = 1; /* 1ms */ + OS_SET_TIMER(&dfs->ath_dfstesttimer, dfs->ath_dfstesttime); + } + } + dfs->ath_radar_tasksched = 0; +} + +static +OS_TIMER_FUNC(dfs_testtimer_task) +{ + struct ieee80211com *ic; + struct ath_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + dfs = (struct ath_dfs *)ic->ic_dfs; + + /* XXX no locking? */ + dfs->ath_dfstest = 0; + + /* + * Flip the channel back to the original channel. + * Make sure this is done properly with a CSA. + */ + DFS_PRINTK("%s: go back to channel %d\n", + __func__, + dfs->ath_dfstest_ieeechan); + + /* + * XXX The mere existence of this method indirection + * to a umac function means this code belongs in + * the driver, _not_ here. Please fix this! + */ + ic->ic_start_csa(ic, dfs->ath_dfstest_ieeechan); +} + + +static int dfs_get_debug_info(struct ieee80211com *ic, int type, void *data) +{ + struct ath_dfs *dfs=(struct ath_dfs *)ic->ic_dfs; + if (data) { + *(u_int32_t *)data = dfs->dfs_proc_phyerr; + } + return (int)dfs->dfs_proc_phyerr; +} + + +int +dfs_attach(struct ieee80211com *ic) +{ + int i, n; + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct ath_dfs_radar_tab_info radar_info; +#define N(a) (sizeof(a)/sizeof(a[0])) + + if (dfs != NULL) { + /*DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: ic_dfs was not NULL\n", + __func__); + */ + return 1; + } + + dfs = (struct ath_dfs *)OS_MALLOC(NULL, sizeof(struct ath_dfs), GFP_ATOMIC); + + + if (dfs == NULL) { + /*DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: ath_dfs allocation failed\n", __func__);*/ + return 1; + } + + OS_MEMZERO(dfs, sizeof (struct ath_dfs)); + + ic->ic_dfs = (void *)dfs; + + dfs->ic = ic; + + ic->ic_dfs_debug = dfs_get_debug_info; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->dfs_nol = NULL; +#endif + + /* + * Zero out radar_info. It's possible that the attach function won't + * fetch an initial regulatory configuration; you really do want to + * ensure that the contents indicates there aren't any filters. + */ + OS_MEMZERO(&radar_info, sizeof(radar_info)); + ic->ic_dfs_attach(ic, &dfs->dfs_caps, &radar_info); + dfs_clear_stats(ic); + dfs->dfs_event_log_on = 0; + OS_INIT_TIMER(NULL, &(dfs->ath_dfs_task_timer), dfs_task, (void *) (ic), + ADF_DEFERRABLE_TIMER); +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + OS_INIT_TIMER(NULL, &(dfs->ath_dfstesttimer), dfs_testtimer_task, + (void *) ic, ADF_DEFERRABLE_TIMER); + dfs->ath_dfs_cac_time = ATH_DFS_WAIT_MS; + dfs->ath_dfstesttime = ATH_DFS_TEST_RETURN_PERIOD_MS; +#endif + ATH_DFSQ_LOCK_INIT(dfs); + STAILQ_INIT(&dfs->dfs_radarq); + ATH_ARQ_LOCK_INIT(dfs); + STAILQ_INIT(&dfs->dfs_arq); + STAILQ_INIT(&(dfs->dfs_eventq)); + ATH_DFSEVENTQ_LOCK_INIT(dfs); + dfs->events = (struct dfs_event *)OS_MALLOC(NULL, + sizeof(struct dfs_event)*DFS_MAX_EVENTS, + GFP_ATOMIC); + if (dfs->events == NULL) { + OS_FREE(dfs); + ic->ic_dfs = NULL; + DFS_PRINTK("%s: events allocation failed\n", __func__); + return 1; + } + for (i = 0; i < DFS_MAX_EVENTS; i++) { + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], re_list); + } + + dfs->pulses = (struct dfs_pulseline *)OS_MALLOC(NULL, sizeof(struct dfs_pulseline), GFP_ATOMIC); + if (dfs->pulses == NULL) { + OS_FREE(dfs->events); + dfs->events = NULL; + OS_FREE(dfs); + ic->ic_dfs = NULL; + DFS_PRINTK("%s: pulse buffer allocation failed\n", __func__); + return 1; + } + + dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; + + /* Allocate memory for radar filters */ + for (n=0; ndfs_radarf[n] = (struct dfs_filtertype *)OS_MALLOC(NULL, sizeof(struct dfs_filtertype),GFP_ATOMIC); + if (dfs->dfs_radarf[n] == NULL) { + DFS_PRINTK("%s: cannot allocate memory for radar filter types\n", + __func__); + goto bad1; + } + OS_MEMZERO(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype)); + } + /* Allocate memory for radar table */ + dfs->dfs_radartable = (int8_t **)OS_MALLOC(NULL, 256*sizeof(int8_t *), GFP_ATOMIC); + if (dfs->dfs_radartable == NULL) { + DFS_PRINTK("%s: cannot allocate memory for radar table\n", + __func__); + goto bad1; + } + for (n=0; n<256; n++) { + dfs->dfs_radartable[n] = OS_MALLOC(NULL, DFS_MAX_RADAR_OVERLAP*sizeof(int8_t), + GFP_ATOMIC); + if (dfs->dfs_radartable[n] == NULL) { + DFS_PRINTK("%s: cannot allocate memory for radar table entry\n", + __func__); + goto bad2; + } + } + + if (usenol == 0) + DFS_PRINTK("%s: NOL disabled\n", __func__); + else if (usenol == 2) + DFS_PRINTK("%s: NOL disabled; no CSA\n", __func__); + + dfs->dfs_rinfo.rn_use_nol = usenol; + + /* Init the cached extension channel busy for false alarm reduction */ + dfs->dfs_rinfo.ext_chan_busy_ts = ic->ic_get_TSF64(ic); + dfs->dfs_rinfo.dfs_ext_chan_busy = 0; + /* Init the Bin5 chirping related data */ + dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; + dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; + dfs->dfs_b5radars = NULL; + + /* + * If dfs_init_radar_filters() fails, we can abort here and + * reconfigure when the first valid channel + radar config + * is available. + */ + if ( dfs_init_radar_filters( ic, &radar_info) ) { + DFS_PRINTK(" %s: Radar Filter Intialization Failed \n", + __func__); + return 1; + } + + dfs->ath_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; + dfs->ath_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_queued_count = 0; + dfs->dfs_phyerr_w53_counter = 0; + dfs->dfs_pri_multiplier = 2; + + dfs->ath_dfs_nol_timeout = DFS_NOL_TIMEOUT_S; + return 0; + +bad2: + OS_FREE(dfs->dfs_radartable); + dfs->dfs_radartable = NULL; +bad1: + for (n=0; ndfs_radarf[n] != NULL) { + OS_FREE(dfs->dfs_radarf[n]); + dfs->dfs_radarf[n] = NULL; + } + } + if (dfs->pulses) { + OS_FREE(dfs->pulses); + dfs->pulses = NULL; + } + if (dfs->events) { + OS_FREE(dfs->events); + dfs->events = NULL; + } + + if (ic->ic_dfs) { + OS_FREE(ic->ic_dfs); + ic->ic_dfs = NULL; + } + return 1; +#undef N +} + +void +dfs_detach(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + int n, empty; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: ic_dfs is NULL\n", __func__); + return; + } + + /* Bug 29099 make sure all outstanding timers are cancelled*/ + + if (dfs->ath_radar_tasksched) { + OS_CANCEL_TIMER(&dfs->ath_dfs_task_timer); + dfs->ath_radar_tasksched = 0; + } + + if (dfs->ath_dfstest) { + OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); + dfs->ath_dfstest = 0; + } + +#if 0 +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + if (dfs->ic_dfswait) { + OS_CANCEL_TIMER(&dfs->ic_dfswaittimer); + dfs->ath_dfswait = 0; + } + + OS_CANCEL_TIMER(&dfs->sc_dfs_war_timer); + if (dfs->dfs_nol != NULL) { + struct dfs_nolelem *nol, *next; + nol = dfs->dfs_nol; + /* Bug 29099 - each NOL element has its own timer, cancel it and + free the element*/ + while (nol != NULL) { + OS_CANCEL_TIMER(&nol->nol_timer); + next = nol->nol_next; + OS_FREE(nol); + nol = next; + } + dfs->dfs_nol = NULL; + } +#endif +#endif + /* Return radar events to free q*/ + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + + /* Free up pulse log*/ + if (dfs->pulses != NULL) { + OS_FREE(dfs->pulses); + dfs->pulses = NULL; + } + + for (n=0; ndfs_radarf[n] != NULL) { + OS_FREE(dfs->dfs_radarf[n]); + dfs->dfs_radarf[n] = NULL; + } + } + + + if (dfs->dfs_radartable != NULL) { + for (n=0; n<256; n++) { + if (dfs->dfs_radartable[n] != NULL) { + OS_FREE(dfs->dfs_radartable[n]); + dfs->dfs_radartable[n] = NULL; + } + } + OS_FREE(dfs->dfs_radartable); + dfs->dfs_radartable = NULL; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->ath_dfs_isdfsregdomain = 0; +#endif + } + + if (dfs->dfs_b5radars != NULL) { + OS_FREE(dfs->dfs_b5radars); + dfs->dfs_b5radars=NULL; + } + +/* Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * dfs_reset_ar(dfs); + */ + ATH_ARQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_arq)); + ATH_ARQ_UNLOCK(dfs); + if (!empty) { +/* + * Commenting out since all the ar functions are obsolete and + * the function definition has been removed as part of dfs_ar.c + * + * dfs_reset_arq(dfs); + */ + } + if (dfs->events != NULL) { + OS_FREE(dfs->events); + dfs->events = NULL; + } + dfs_nol_timer_cleanup(dfs); + OS_FREE(dfs); + + /* XXX? */ + ic->ic_dfs = NULL; +} +/* + * This is called each time a channel change occurs, to (potentially) enable + * the radar code. + */ +int dfs_radar_disable(struct ieee80211com *ic) +{ + struct ath_dfs *dfs=(struct ath_dfs *)ic->ic_dfs; +#ifdef ATH_ENABLE_AR + dfs->dfs_proc_phyerr &= ~DFS_AR_EN; +#endif + dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; + return 0; +} +/* + * This is called each time a channel change occurs, to (potentially) enable + * the radar code. + */ +int dfs_radar_enable(struct ieee80211com *ic, + struct ath_dfs_radar_tab_info *radar_info) +{ + int is_ext_ch; + int is_fastclk = 0; + int radar_filters_init_status = 0; + //u_int32_t rfilt; + struct ath_dfs *dfs; + struct dfs_state *rs_pri, *rs_ext; + struct ieee80211_channel *chan=ic->ic_curchan, *ext_ch = NULL; + is_ext_ch=IEEE80211_IS_CHAN_11N_HT40(ic->ic_curchan); + dfs=(struct ath_dfs *)ic->ic_dfs; + rs_pri = NULL; + rs_ext = NULL; +#if 0 + int i; +#endif + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: ic_dfs is NULL\n", + __func__); + + return -EIO; + } + ic->ic_dfs_disable(ic); + + /* + * Setting country code might change the DFS domain + * so initialize the DFS Radar filters + */ + radar_filters_init_status = dfs_init_radar_filters(ic, radar_info); + + /* + * dfs_init_radar_filters() returns 1 on failure and + * 0 on success. + */ + if ( DFS_STATUS_FAIL == radar_filters_init_status ) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: DFS Radar Filters Initialization Failed", + __func__, __LINE__); + return -EIO; + } + + if ((ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS)) { + + if (IEEE80211_IS_CHAN_DFS(chan)) { + + u_int8_t index_pri, index_ext; +#ifdef ATH_ENABLE_AR + dfs->dfs_proc_phyerr |= DFS_AR_EN; +#endif + dfs->dfs_proc_phyerr |= DFS_RADAR_EN; + + + + if (is_ext_ch) { + ext_ch = ieee80211_get_extchan(ic); + } + dfs_reset_alldelaylines(dfs); + + rs_pri = dfs_getchanstate(dfs, &index_pri, 0); + if (ext_ch) { + rs_ext = dfs_getchanstate(dfs, &index_ext, 1); + } + if (rs_pri != NULL && ((ext_ch==NULL)||(rs_ext != NULL))) { + struct ath_dfs_phyerr_param pe; + + OS_MEMSET(&pe, '\0', sizeof(pe)); + + if (index_pri != dfs->dfs_curchan_radindex) + dfs_reset_alldelaylines(dfs); + + dfs->dfs_curchan_radindex = (int16_t) index_pri; + dfs->dfs_pri_multiplier_ini = radar_info->dfs_pri_multiplier; + + if (rs_ext) + dfs->dfs_extchan_radindex = (int16_t) index_ext; + + ath_dfs_phyerr_param_copy(&pe, + &rs_pri->rs_param); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "%s: firpwr=%d, rssi=%d, height=%d, " + "prssi=%d, inband=%d, relpwr=%d, " + "relstep=%d, maxlen=%d\n", + __func__, + pe.pe_firpwr, + pe.pe_rrssi, + pe.pe_height, + pe.pe_prssi, + pe.pe_inband, + pe.pe_relpwr, + pe.pe_relstep, + pe.pe_maxlen + ); + + ic->ic_dfs_enable(ic, &is_fastclk, &pe); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "Enabled radar detection on channel %d\n", + chan->ic_freq); + dfs->dur_multiplier = + is_fastclk ? DFS_FAST_CLOCK_MULTIPLIER : DFS_NO_FAST_CLOCK_MULTIPLIER; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "%s: duration multiplier is %d\n", __func__, dfs->dur_multiplier); + } else + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: No more radar states left\n", + __func__); + } + } + + return DFS_STATUS_SUCCESS; +} + +int +dfs_control(struct ieee80211com *ic, u_int id, + void *indata, u_int32_t insize, + void *outdata, u_int32_t *outsize) +{ + int error = 0; + struct ath_dfs_phyerr_param peout; + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct dfs_ioctl_params *dfsparams; + u_int32_t val=0; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + struct dfsreq_nolinfo *nol; + u_int32_t *data = NULL; +#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ + int i; + + if (dfs == NULL) { + error = -EINVAL; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s DFS is null\n", __func__); + goto bad; + } + + + switch (id) { + case DFS_SET_THRESH: + if (insize < sizeof(struct dfs_ioctl_params) || !indata) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: insize=%d, expected=%zu bytes, indata=%p\n", + __func__, insize, sizeof(struct dfs_ioctl_params), + indata); + error = -EINVAL; + break; + } + dfsparams = (struct dfs_ioctl_params *) indata; + if (!dfs_set_thresholds(ic, DFS_PARAM_FIRPWR, dfsparams->dfs_firpwr)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_RRSSI, dfsparams->dfs_rrssi)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_HEIGHT, dfsparams->dfs_height)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_PRSSI, dfsparams->dfs_prssi)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_INBAND, dfsparams->dfs_inband)) + error = -EINVAL; + /* 5413 speicfic */ + if (!dfs_set_thresholds(ic, DFS_PARAM_RELPWR, dfsparams->dfs_relpwr)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_RELSTEP, dfsparams->dfs_relstep)) + error = -EINVAL; + if (!dfs_set_thresholds(ic, DFS_PARAM_MAXLEN, dfsparams->dfs_maxlen)) + error = -EINVAL; + break; + case DFS_GET_THRESH: + if (!outdata || !outsize || *outsize ath_dfs_stats.num_radar_detects; + break; + case DFS_DISABLE_DETECT: + dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; + dfs->ic->ic_dfs_state.ignore_dfs = 1; + DFS_PRINTK("%s enable detects, ignore_dfs %d\n", + __func__, + dfs->ic->ic_dfs_state.ignore_dfs); + break; + case DFS_ENABLE_DETECT: + dfs->dfs_proc_phyerr |= DFS_RADAR_EN; + dfs->ic->ic_dfs_state.ignore_dfs = 0; + DFS_PRINTK("%s enable detects, ignore_dfs %d\n", + __func__, + dfs->ic->ic_dfs_state.ignore_dfs); + break; + case DFS_DISABLE_FFT: + //UMACDFS: TODO: val = ath_hal_dfs_config_fft(sc->sc_ah, false); + DFS_PRINTK("%s TODO disable FFT val=0x%x \n", __func__, val); + break; + case DFS_ENABLE_FFT: + //UMACDFS TODO: val = ath_hal_dfs_config_fft(sc->sc_ah, true); + DFS_PRINTK("%s TODO enable FFT val=0x%x \n", __func__, val); + break; + case DFS_SET_DEBUG_LEVEL: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->dfs_debug_mask= *(u_int32_t *)indata; + DFS_PRINTK("%s debug level now = 0x%x \n", + __func__, + dfs->dfs_debug_mask); + if (dfs->dfs_debug_mask & ATH_DEBUG_DFS3) { + /* Enable debug Radar Event */ + dfs->dfs_event_log_on = 1; + } else { + dfs->dfs_event_log_on = 0; + } + break; + case DFS_SET_FALSE_RSSI_THRES: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->ath_dfs_false_rssi_thres= *(u_int32_t *)indata; + DFS_PRINTK("%s false RSSI threshold now = 0x%x \n", + __func__, + dfs->ath_dfs_false_rssi_thres); + break; + case DFS_SET_PEAK_MAG: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->ath_dfs_peak_mag= *(u_int32_t *)indata; + DFS_PRINTK("%s peak_mag now = 0x%x \n", + __func__, + dfs->ath_dfs_peak_mag); + break; + case DFS_IGNORE_CAC: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + if (*(u_int32_t *)indata) { + dfs->ic->ic_dfs_state.ignore_cac= 1; + } else { + dfs->ic->ic_dfs_state.ignore_cac= 0; + } + DFS_PRINTK("%s ignore cac = 0x%x \n", + __func__, + dfs->ic->ic_dfs_state.ignore_cac); + break; + case DFS_SET_NOL_TIMEOUT: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + if (*(int *)indata) { + dfs->ath_dfs_nol_timeout= *(int *)indata; + } else { + dfs->ath_dfs_nol_timeout= DFS_NOL_TIMEOUT_S; + } + DFS_PRINTK("%s nol timeout = %d sec \n", + __func__, + dfs->ath_dfs_nol_timeout); + break; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + case DFS_MUTE_TIME: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + data = (u_int32_t *) indata; + dfs->ath_dfstesttime = *data; + dfs->ath_dfstesttime *= (1000); //convert sec into ms + break; + case DFS_GET_USENOL: + if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) { + error = -EINVAL; + break; + } + *outsize = sizeof(u_int32_t); + *((u_int32_t *)outdata) = dfs->dfs_rinfo.rn_use_nol; + + + + for (i = 0; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count); i++) { + //DFS_DPRINTK(sc, ATH_DEBUG_DFS,"ts=%llu diff_ts=%u rssi=%u dur=%u\n", dfs->radar_log[i].ts, dfs->radar_log[i].diff_ts, dfs->radar_log[i].rssi, dfs->radar_log[i].dur); + + } + dfs->dfs_event_log_count = 0; + dfs->dfs_phyerr_count = 0; + dfs->dfs_phyerr_reject_count = 0; + dfs->dfs_phyerr_queued_count = 0; + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + break; + case DFS_SET_USENOL: + if (insize < sizeof(u_int32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->dfs_rinfo.rn_use_nol = *(u_int32_t *)indata; + /* iwpriv markdfs in linux can do the same thing... */ + break; + case DFS_GET_NOL: + if (!outdata || !outsize || *outsize < sizeof(struct dfsreq_nolinfo)) { + error = -EINVAL; + break; + } + *outsize = sizeof(struct dfsreq_nolinfo); + nol = (struct dfsreq_nolinfo *)outdata; + dfs_get_nol(dfs, (struct dfsreq_nolelem *)nol->dfs_nol, &nol->ic_nchans); + dfs_print_nol(dfs); + break; + case DFS_SET_NOL: + if (insize < sizeof(struct dfsreq_nolinfo) || !indata) { + error = -EINVAL; + break; + } + nol = (struct dfsreq_nolinfo *) indata; + dfs_set_nol(dfs, (struct dfsreq_nolelem *)nol->dfs_nol, nol->ic_nchans); + break; + + case DFS_SHOW_NOL: + dfs_print_nol(dfs); + break; + case DFS_BANGRADAR: + #if 0 //MERGE_TBD + if(sc->sc_nostabeacons) + { + printk("No radar detection Enabled \n"); + break; + } +#endif + dfs->dfs_bangradar = 1; + dfs->ath_radar_tasksched = 1; + OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0); + break; +#endif /* ATH_DFS_RADAR_DETECTION_ONLY */ + default: + error = -EINVAL; + } +bad: + return error; +} +int +dfs_set_thresholds(struct ieee80211com *ic, const u_int32_t threshtype, + const u_int32_t value) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + int16_t chanindex; + struct dfs_state *rs; + struct ath_dfs_phyerr_param pe; + int is_fastclk = 0; /* XXX throw-away */ + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: ic_dfs is NULL\n", + __func__); + return 0; + } + + chanindex = dfs->dfs_curchan_radindex; + if ((chanindex <0) || (chanindex >= DFS_NUM_RADAR_STATES)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: chanindex = %d, DFS_NUM_RADAR_STATES=%d\n", + __func__, + chanindex, + DFS_NUM_RADAR_STATES); + return 0; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: threshtype=%d, value=%d\n", __func__, threshtype, value); + + ath_dfs_phyerr_init_noval(&pe); + + rs = &(dfs->dfs_radar[chanindex]); + switch (threshtype) { + case DFS_PARAM_FIRPWR: + rs->rs_param.pe_firpwr = (int32_t) value; + pe.pe_firpwr = value; + break; + case DFS_PARAM_RRSSI: + rs->rs_param.pe_rrssi = value; + pe.pe_rrssi = value; + break; + case DFS_PARAM_HEIGHT: + rs->rs_param.pe_height = value; + pe.pe_height = value; + break; + case DFS_PARAM_PRSSI: + rs->rs_param.pe_prssi = value; + pe.pe_prssi = value; + break; + case DFS_PARAM_INBAND: + rs->rs_param.pe_inband = value; + pe.pe_inband = value; + break; + /* 5413 specific */ + case DFS_PARAM_RELPWR: + rs->rs_param.pe_relpwr = value; + pe.pe_relpwr = value; + break; + case DFS_PARAM_RELSTEP: + rs->rs_param.pe_relstep = value; + pe.pe_relstep = value; + break; + case DFS_PARAM_MAXLEN: + rs->rs_param.pe_maxlen = value; + pe.pe_maxlen = value; + break; + default: + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: unknown threshtype (%d)\n", + __func__, + threshtype); + break; + } + + /* + * The driver layer dfs_enable routine is tasked with translating + * values from the global format to the per-device (HAL, offload) + * format. + */ + ic->ic_dfs_enable(ic, &is_fastclk, &pe); + return 1; +} + +int +dfs_get_thresholds(struct ieee80211com *ic, struct ath_dfs_phyerr_param *param) +{ + //UMACDFS : TODO:ath_hal_getdfsthresh(sc->sc_ah, param); + + OS_MEMZERO(param, sizeof(*param)); + + (void) ic->ic_dfs_get_thresholds(ic, param); + + return 1; +} + +u_int16_t dfs_usenol(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + return dfs ? (u_int16_t) dfs->dfs_rinfo.rn_use_nol : 0; +} + +u_int16_t dfs_isdfsregdomain(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + return dfs ? dfs->dfsdomain : 0; +} + +#endif /* ATH_UPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_bindetects.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_bindetects.c new file mode 100644 index 000000000000..1c1b903e6e85 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_bindetects.c @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2002-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_bindetects.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/*TO DO DFS removing +#include +*/ +#ifdef ATH_SUPPORT_DFS + +int +dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, u_int32_t dur, int ext_chan_flag) +{ + struct dfs_pulseline *pl = dfs->pulses; + int i, n, refpri, primargin, numpulses=0; + u_int64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, window_start, window_end; + u_int32_t index, next_index, deltadur; + + /* For fixed pattern types, rf->rf_patterntype=1*/ + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype==1)); + + refpri = (rf->rf_minpri + rf->rf_maxpri)/2; + index = pl->pl_lastelem; + end_ts = pl->pl_elems[index].p_time; + start_ts = end_ts - (refpri*rf->rf_numpulses); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "lastelem ts=%llu start_ts=%llu, end_ts=%llu\n", + (unsigned long long) pl->pl_elems[index].p_time, + (unsigned long long) start_ts, + (unsigned long long) end_ts); + + /* find the index of first element in our window of interest */ + for(i=0;ipl_numelems;i++) { + index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; + if(pl->pl_elems[index].p_time >= start_ts ) + continue; + else { + index = (index) & DFS_MAX_PULSE_BUFFER_MASK; + break; + } + } + for (n=0;n<=rf->rf_numpulses; n++) { + window_start = (start_ts + (refpri*n))-(primargin+n); + window_end = window_start + 2*(primargin+n); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "window_start %u window_end %u \n", + (u_int32_t)window_start, (u_int32_t)window_end); + for(i=0;ipl_numelems;i++) { + prev_event_ts = pl->pl_elems[index].p_time; + index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; + event_ts = pl->pl_elems[index].p_time; + next_index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; + next_event_ts = pl->pl_elems[next_index].p_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "ts %u \n", (u_int32_t)event_ts); + if( (event_ts <= window_end) && (event_ts >= window_start)){ + deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur); + if( (pl->pl_elems[index].p_dur == 1) || + ((dur != 1) && (deltadur <= 2))) { + numpulses++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numpulses %u \n", numpulses); + break; + } + } + else if( event_ts > window_end) { + index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; + break; + } + else if( event_ts == prev_event_ts) { + if( ((next_event_ts - event_ts) > refpri) || + ((next_event_ts - event_ts) == 0)) { + deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur); + if( (pl->pl_elems[index].p_dur == 1) || + ((pl->pl_elems[index].p_dur != 1) && (deltadur <= 2))) { + numpulses++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "zero PRI: numpulses %u \n", numpulses); + break; + } + } + } + } + } + if (numpulses >= dfs_get_filter_threshold(dfs, rf, ext_chan_flag)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s FOUND filterID=%u numpulses=%d unadj thresh=%d\n", __func__, rf->rf_pulseid, numpulses, rf->rf_threshold); + return 1; + } + else + return 0; +} + +void +dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, + u_int32_t deltaT, u_int64_t this_ts) +{ + u_int32_t index,n, window; + struct dfs_delayline *dl; + + dl = &rf->rf_dl; + /* Circular buffer of size 2^n */ + index = (dl->dl_lastelem + 1) & DFS_MAX_DL_MASK; + //if ((dl->dl_numelems+1) == DFS_MAX_DL_SIZE) + if ((dl->dl_numelems) == DFS_MAX_DL_SIZE) + dl->dl_firstelem = (dl->dl_firstelem + 1) & DFS_MAX_DL_MASK; + else + dl->dl_numelems++; + dl->dl_lastelem = index; + dl->dl_elems[index].de_time = deltaT; + dl->dl_elems[index].de_ts = this_ts; + window = deltaT; + dl->dl_elems[index].de_dur = re->re_dur; + dl->dl_elems[index].de_rssi = re->re_rssi; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s: adding: filter id %d, dur=%d, rssi=%d, ts=%llu\n", + __func__, + rf->rf_pulseid, + re->re_dur, + re->re_rssi, + (unsigned long long int) this_ts); + + for (n=0;ndl_numelems-1; n++) { + index = (index-1) & DFS_MAX_DL_MASK; + /* + * calculate window based on full time stamp instead of deltaT + * deltaT (de_time) may result in incorrect window value + */ + window = (u_int32_t) (this_ts - dl->dl_elems[index].de_ts); + + if (window > rf->rf_filterlen) { + dl->dl_firstelem = (index+1) & DFS_MAX_DL_MASK; + dl->dl_numelems = n+1; + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "dl firstElem = %d lastElem = %d\n",dl->dl_firstelem, + dl->dl_lastelem); +} + + +int +dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, u_int32_t deltaT, + u_int32_t width, int ext_chan_flag) +{ + u_int32_t refpri, refdur, searchpri, deltapri,deltapri_2,deltapri_3, averagerefpri; + u_int32_t n, i, primargin, durmargin, highscore, highscoreindex; + int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0; + struct dfs_delayline *dl; + u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff; + int numpulses=0; + int lowprichk=3, pri_match=0; + + dl = &rf->rf_dl; + if( dl->dl_numelems < (rf->rf_threshold-1)) { + return 0; + } + if( deltaT > rf->rf_filterlen) + return 0; + + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype==1)); + + + if(rf->rf_maxdur < 10) { + durmargin = 4; + } + else { + durmargin = 6; + } + + if( rf->rf_patterntype == 1 ){ + found = dfs_bin_fixedpattern_check(dfs, rf, width, ext_chan_flag); + if(found) { + dl->dl_numelems = 0; + } + return found; + } + + OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE); + /* find out the lowest pri */ + for (n=0;ndl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) + continue; + else if(refpri < lowpri) { + lowpri = dl->dl_elems[delayindex].de_time; + lowpriindex = n; + } + } + /* find out the each delay element's pri score */ + for (n=0;ndl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) + continue; + if (refpri < rf->rf_maxpri) { // use only valid PRI range for high score + for (i=0;idl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + deltapri_2 = DFS_DIFF(searchpri, 2*refpri); + deltapri_3 = DFS_DIFF(searchpri, 3*refpri); + if (rf->rf_ignore_pri_window==2) { + pri_match = ((deltapri < primargin) || (deltapri_2 < primargin) || (deltapri_3 < primargin)); + } else { + pri_match = (deltapri < primargin); + } + + if (pri_match) + score[n]++; + } + } else { + score[n] = 0; + } + if( score[n] > rf->rf_threshold) { + /* we got the most possible candidate, + * no need to continue further */ + break; + } + } + /* find out the high scorer */ + highscore = 0; + highscoreindex = 0; + for (n=0;ndl_numelems; n++) { + if( score[n] > highscore) { + highscore = score[n]; + highscoreindex = n; + } + else if( score[n] == highscore ) { + /*more than one pri has highscore take the least pri */ + delayindex = (dl->dl_firstelem + highscoreindex) & DFS_MAX_DL_MASK; + dindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + if( dl->dl_elems[dindex].de_time <= + dl->dl_elems[delayindex].de_time ) { + highscoreindex = n; + } + } + } + /* find the average pri of pulses around the pri of highscore or + * the pulses around the lowest pri */ + if (rf->rf_ignore_pri_window > 0) { + lowprichk = (rf->rf_threshold >> 1)+1; + } else { + lowprichk = 3; + } + + if( highscore < lowprichk) { + scoreindex = lowpriindex; + } + else { + scoreindex = highscoreindex; + } + /* We got the possible pri, save its parameters as reference */ + delayindex = (dl->dl_firstelem + scoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + averagerefpri = 0; + + if (rf->rf_fixed_pri_radar_pulse) { + refpri = (rf->rf_minpri + rf->rf_maxpri)/2; + } + + numpulses = dfs_bin_pri_check(dfs, rf, dl, score[scoreindex], refpri, + refdur, ext_chan_flag, refpri); + if (numpulses >= dfs_get_filter_threshold(dfs, rf, ext_chan_flag)) { + found = 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "ext_flag=%d MATCH filter=%u numpulses=%u thresh=%u refdur=%d refpri=%d primargin=%d\n", ext_chan_flag, rf->rf_pulseid, numpulses,rf->rf_threshold, refdur, refpri, primargin); + dfs_print_delayline(dfs, &rf->rf_dl); + dfs_print_filter(dfs, rf); + } + return found; +} + +int +dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_delayline *dl, u_int32_t score, u_int32_t refpri, + u_int32_t refdur, int ext_chan_flag, int fundamentalpri) +{ + u_int32_t searchpri, searchdur, searchrssi, deltapri = 0,deltapri1 = 0, deltapri2 = 0, deltadur, averagerefpri=0,MatchCount = 0; + u_int32_t delta_ts_variance, delta_time_stamps, prev_good_timestamp=0; + int delayindex, dindex; + u_int32_t i, j=0, primargin, durmargin, highscore=score, highscoreindex=0; + int numpulses=1; //first pulse in the burst is most likely being filtered out based on maxfilterlen + int priscorechk=1,numpulsetochk=2,primatch=0; + + //Use the adjusted PRI margin to reduce false alarms + /* For non fixed pattern types, rf->rf_patterntype=0*/ + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype==1)); + + if ( (refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri) ) { + numpulses = 0; + return numpulses; + } + + + if(rf->rf_maxdur < 10) { + durmargin = 4; + } else { + durmargin = 6; + } + + if ((!rf->rf_fixed_pri_radar_pulse)) { + if (rf->rf_ignore_pri_window==1) { + priscorechk = (rf->rf_threshold >> 1); + } else { + priscorechk = 1; + } + + MatchCount = 0; + if( score > priscorechk) { + for (i=0;idl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + if( deltapri < primargin) { + averagerefpri += searchpri; + MatchCount++; + } + } + if (rf->rf_patterntype != 2) { + if (MatchCount > 0) + refpri = (averagerefpri/MatchCount); //average + } else { + refpri = (averagerefpri/score); + } + } + } + /* Note: Following primultiple calculation should be done once per filter + * during initialization stage (dfs_attach) and stored in its array + * atleast for fixed frequency types like FCC Bin1 to save some CPU cycles. + * multiplication, devide operators in the following code are left as it is + * for readability hoping the complier will use left/right shifts wherever possible + */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "refpri = %d high score = %d index = %d numpulses = %d\n", + refpri, highscore, highscoreindex, numpulses); + /* Count the other delay elements that have pri and dur with in the + * acceptable range from the reference one */ + for (i=0; idl_numelems; i++) { + delayindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[delayindex].de_time; + if( searchpri == 0) { + /* This events PRI is zero, take it as a + * valid pulse but decrement next event's PRI by refpri + */ + dindex = (delayindex+1)& DFS_MAX_DL_MASK; + dl->dl_elems[dindex].de_time -= refpri; + searchpri = refpri; + } + searchdur = dl->dl_elems[delayindex].de_dur; + searchrssi = dl->dl_elems[delayindex].de_rssi; + deltadur = DFS_DIFF(searchdur, refdur); + deltapri = DFS_DIFF(searchpri, refpri); + + //deltapri3 = DFS_DIFF(searchpri, 3 * refpri); + primatch=0; + + if ((rf->rf_ignore_pri_window>0) && (rf->rf_patterntype!=2)) { + for (j=0;jrf_numpulses;j++){ + deltapri1 = DFS_DIFF(searchpri, (j+1)*refpri); + if (deltapri1 < (2*primargin)) { + primatch = 1; + break; + } + } + } else { + if (( deltapri1 < primargin) || ( deltapri2 < primargin)) { + primatch = 1; + } + } + + if ( primatch && ( deltadur < durmargin) ) { + if ( (numpulses == 1) ) { + numpulses++; + } else { + delta_time_stamps = dl->dl_elems[delayindex].de_ts - prev_good_timestamp; + if ((rf->rf_ignore_pri_window>0)) { + numpulsetochk = rf->rf_numpulses; + + if ((rf->rf_patterntype==2) && (fundamentalprirf_ignore_pri_window>0) { + break; + } + } + } + } + prev_good_timestamp = dl->dl_elems[delayindex].de_ts; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "rf->minpri=%d rf->maxpri=%d searchpri = %d index = %d numpulses = %d deltapri=%d j=%d\n", + rf->rf_minpri, rf->rf_maxpri, searchpri, i, numpulses, deltapri, j); + } + + } + return numpulses; +} +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_debug.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_debug.c new file mode 100644 index 000000000000..2590f6eec10d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_debug.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_debug.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifdef ATH_SUPPORT_DFS + +void +dfs_print_delayline(struct ath_dfs *dfs, struct dfs_delayline *dl) +{ + int i=0,index; + struct dfs_delayelem *de; + + index = dl->dl_lastelem; + for (i=0; idl_numelems; i++) { + de = &dl->dl_elems[index]; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "Elem %d: ts = %u (0x%x) dur=%u\n",i, + de->de_time, de->de_time, de->de_dur); + index = (index - 1)& DFS_MAX_DL_MASK; + } +} +void +dfs_print_filter(struct ath_dfs *dfs, struct dfs_filter *rf) +{ + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "filterID[%d] rf_numpulses=%u; rf->rf_minpri=%u; " + "rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; " + "rf->rf_mindur=%u; rf->rf_maxdur=%u\n", + rf->rf_pulseid, + rf->rf_numpulses, + rf->rf_minpri, + rf->rf_maxpri, + rf->rf_threshold, + rf->rf_filterlen, + rf->rf_mindur, + rf->rf_maxdur); +} + +void +dfs_print_filters(struct ath_dfs *dfs) +{ + struct dfs_filtertype *ft = NULL; + struct dfs_filter *rf; + int i,j; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); + return; + } + for (i=0; idfs_radarf[i] != NULL) { + ft = dfs->dfs_radarf[i]; + if((ft->ft_numfilters > DFS_MAX_NUM_RADAR_FILTERS) || (!ft->ft_numfilters)) + continue; + DFS_PRINTK("===========ft->ft_numfilters=%u===========\n", ft->ft_numfilters); + for (j=0; jft_numfilters; j++) { + rf = &(ft->ft_filters[j]); + DFS_PRINTK("filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n",j, rf->rf_pulseid, + rf->rf_numpulses, rf->rf_minpri, rf->rf_maxpri, rf->rf_threshold, rf->rf_filterlen, rf->rf_mindur, rf->rf_maxdur); + } + } + } +} + +void dfs_print_activity(struct ath_dfs *dfs) +{ + int chan_busy=0, ext_chan_busy=0; + u_int32_t rxclear=0, rxframe=0, txframe=0, cycles=0; + + cycles = dfs->ic->ic_get_mib_cycle_counts_pct(dfs->ic, &rxclear, &rxframe, &txframe); + chan_busy = cycles; + + ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS,"cycles=%d rxclear=%d rxframe=%d" + " txframe=%d extchanbusy=%d\n", cycles, rxclear, + rxframe, txframe, ext_chan_busy); + return; +} + +/* + * XXX migrate this to use ath_dfs as the arg, not ieee80211com! + */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY +OS_TIMER_FUNC(dfs_debug_timeout) +{ + struct ieee80211com *ic; + struct ath_dfs* dfs; + + OS_GET_TIMER_ARG(ic, struct ieee80211com *); + + dfs = (struct ath_dfs *)ic->ic_dfs; + + dfs_print_activity(dfs); + + OS_SET_TIMER(&dfs->ath_dfs_debug_timer, DFS_DEBUG_TIMEOUT_MS); +} +#endif + +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c new file mode 100644 index 000000000000..5e9d2cbd5de2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_fcc_bin5.c @@ -0,0 +1,836 @@ +/* + * Copyright (c) 2002-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_fcc_bin5.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifdef ATH_SUPPORT_DFS + +/* + * Reject the pulse if: + * + It's outside the RSSI threshold; + * + It's outside the pulse duration; + * + It's been verified by HW/SW chirp checking + * and neither of those found a chirp. + */ +int +dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re, + struct dfs_bin5radars *br) +{ + int b5_rssithresh = br->br_pulse.b5_rssithresh; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_PULSE, + "%s: re_dur=%d, rssi=%d, check_chirp=%d, " + "hw_chirp=%d, sw_chirp=%d\n", + __func__, + (int) re->re_dur, + (int) re->re_rssi, + !! (re->re_flags & DFS_EVENT_CHECKCHIRP), + !! (re->re_flags & DFS_EVENT_HW_CHIRP), + !! (re->re_flags & DFS_EVENT_SW_CHIRP)); + + /* + * If the sw/hw chirp detection says to fail the pulse, + * do so. + */ + if (DFS_EVENT_NOTCHIRP(re)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s: rejecting chirp: ts=%llu, dur=%d, rssi=%d " + "checkchirp=%d, hwchirp=%d, swchirp=%d\n", + __func__, + (unsigned long long) re->re_full_ts, + (int) re->re_dur, + (int) re->re_rssi, + !! (re->re_flags & DFS_EVENT_CHECKCHIRP), + !! (re->re_flags & DFS_EVENT_HW_CHIRP), + !! (re->re_flags & DFS_EVENT_SW_CHIRP)); + return (0); + } + + /* Adjust the filter threshold for rssi in non TURBO mode */ + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if( ! (dfs->ic->ic_curchan->ic_flags & CHANNEL_TURBO)) + b5_rssithresh += br->br_pulse.b5_rssimargin; + + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + /* + * Check if the pulse is within duration and rssi + * thresholds. + */ + if ((re->re_dur >= br->br_pulse.b5_mindur) && + (re->re_dur <= br->br_pulse.b5_maxdur) && + (re->re_rssi >= b5_rssithresh)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s: dur=%d, rssi=%d - adding!\n", + __func__, (int) re->re_dur, (int) re->re_rssi); + return (1); + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s: too low to be Bin5 pulse tsf=%llu, dur=%d, rssi=%d\n", + __func__, + (unsigned long long) re->re_full_ts, + (int) re->re_dur, + (int) re->re_rssi); + + return (0); +} + + +int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, + struct dfs_event *re, u_int64_t thists) +{ + u_int32_t index,stop; + u_int64_t tsDelta; + + /* Check if this pulse is a valid pulse in terms of repetition, + * if not, return without adding it to the queue. + * PRI : Pulse Repitetion Interval + * BRI : Burst Repitetion Interval */ + if( br->br_numelems != 0){ + index = br->br_lastelem; + tsDelta = thists - br->br_elems[index].be_ts; + if( (tsDelta < DFS_BIN5_PRI_LOWER_LIMIT) || + ( (tsDelta > DFS_BIN5_PRI_HIGHER_LIMIT) && + (tsDelta < DFS_BIN5_BRI_LOWER_LIMIT))) { + return 0; + } + } + /* Circular buffer of size 2^n */ + index = (br->br_lastelem +1) & DFS_MAX_B5_MASK; + br->br_lastelem = index; + if (br->br_numelems == DFS_MAX_B5_SIZE) + br->br_firstelem = (br->br_firstelem+1)&DFS_MAX_B5_MASK; + else + br->br_numelems++; + br->br_elems[index].be_ts = thists; + br->br_elems[index].be_rssi = re->re_rssi; + br->br_elems[index].be_dur = re->re_dur; /* please note that this is in u-sec */ + stop = 0; + index = br->br_firstelem; + while ((!stop) && (br->br_numelems-1) > 0) { + if ((thists - br->br_elems[index].be_ts) > + ((u_int64_t) br->br_pulse.b5_timewindow)) { + br->br_numelems--; + br->br_firstelem = (br->br_firstelem +1) & DFS_MAX_B5_MASK; + index = br->br_firstelem; + } else + stop = 1; + } + return 1; +} + +/* + * If the dfs structure is NULL (which should be illegal if everyting is working + * properly, then signify that a bin5 radar was found + */ + +int +dfs_bin5_check(struct ath_dfs *dfs) +{ + struct dfs_bin5radars *br; + int index[DFS_MAX_B5_SIZE]; + u_int32_t n = 0, i = 0, i1 = 0, this = 0, prev = 0, rssi_diff = 0, width_diff = 0, bursts= 0; + u_int32_t total_diff=0, average_diff=0, total_width=0, average_width=0, numevents=0; + u_int64_t pri; + + + if (dfs == NULL) { + DFS_PRINTK("%s: ic_dfs is NULL\n", __func__); + return 1; + } + for (n=0;ndfs_rinfo.rn_numbin5radars; n++) { + br = &(dfs->dfs_b5radars[n]); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "Num elems = %d\n", br->br_numelems); + + /* find a valid bin 5 pulse and use it as reference */ + for(i1=0;i1 < br->br_numelems; i1++) { + this = ((br->br_firstelem +i1) & DFS_MAX_B5_MASK); + if ((br->br_elems[this].be_dur >= MIN_BIN5_DUR_MICROSEC) && + (br->br_elems[this].be_dur <= MAX_BIN5_DUR_MICROSEC)) { + break; + } + } + + prev = this; + for(i = i1 + 1; i < br->br_numelems; i++){ + this = ((br->br_firstelem +i) & DFS_MAX_B5_MASK); + + /* first make sure it is a bin 5 pulse by checking the duration */ + if ((br->br_elems[this].be_dur < MIN_BIN5_DUR_MICROSEC) || (br->br_elems[this].be_dur > MAX_BIN5_DUR_MICROSEC)) { + continue; + } + + /* Rule 1: 1000 <= PRI <= 2000 + some margin */ + if( br->br_elems[this].be_ts >= br->br_elems[prev].be_ts ) { + pri = br->br_elems[this].be_ts - br->br_elems[prev].be_ts; + } + else {//roll over case + //pri = (0xffffffffffffffff - br->br_elems[prev].be_ts) + br->br_elems[this].be_ts; + pri = br->br_elems[this].be_ts; + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + " pri=%llu this.ts=%llu this.dur=%d this.rssi=%d prev.ts=%llu\n", + (unsigned long long)pri, + (unsigned long long)br->br_elems[this].be_ts, + (int) br->br_elems[this].be_dur, + (int) br->br_elems[this].be_rssi, + (unsigned long long)br->br_elems[prev].be_ts); + if(( (pri >= DFS_BIN5_PRI_LOWER_LIMIT) && (pri <= DFS_BIN5_PRI_HIGHER_LIMIT))) { //pri: pulse repitition interval in us + /* Rule 2: pulse width of the pulses in the burst should be same (+/- margin) */ + if( br->br_elems[this].be_dur >= br->br_elems[prev].be_dur) { + width_diff = br->br_elems[this].be_dur - br->br_elems[prev].be_dur; + } + else { + width_diff = br->br_elems[prev].be_dur - br->br_elems[this].be_dur; + } + if( width_diff <= DFS_BIN5_WIDTH_MARGIN ) { + /* Rule 3: RSSI of the pulses in the burst should be same (+/- margin) */ + if( br->br_elems[this].be_rssi >= br->br_elems[prev].be_rssi) { + rssi_diff = br->br_elems[this].be_rssi - br->br_elems[prev].be_rssi; + } + else { + rssi_diff = br->br_elems[prev].be_rssi - br->br_elems[this].be_rssi; + } + if( rssi_diff <= DFS_BIN5_RSSI_MARGIN ) { + bursts++; + /* Save the indexes of this pair for later width variance check */ + if( numevents >= 2 ) { + /* make sure the event is not duplicated, + * possible in a 3 pulse burst */ + if( index[numevents-1] != prev) { + index[numevents++] = prev; + } + } + else { + index[numevents++] = prev; } + index[numevents++] = this; + } else { + DFS_DPRINTK(dfs, + ATH_DEBUG_DFS_BIN5, + "%s %d Bin5 rssi_diff=%d\n", + __func__, __LINE__, rssi_diff); + } + } else { + DFS_DPRINTK(dfs, + ATH_DEBUG_DFS_BIN5, + "%s %d Bin5 width_diff=%d\n", + __func__, __LINE__, + width_diff); + } + } else if ((pri >= DFS_BIN5_BRI_LOWER_LIMIT) && + (pri <= DFS_BIN5_BRI_UPPER_LIMIT)) { + // check pulse width to make sure it is in range of bin 5 + //if ((br->br_elems[this].be_dur >= MIN_BIN5_DUR_MICROSEC) && (br->br_elems[this].be_dur <= MAX_BIN5_DUR_MICROSEC)) { + bursts++; + //} + } else{ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s %d Bin5 PRI check fail pri=%llu\n", + __func__, __LINE__, (unsigned long long)pri); + } + prev = this; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "bursts=%u numevents=%u\n", bursts, numevents); + if ( bursts >= br->br_pulse.b5_threshold) { + if( (br->br_elems[br->br_lastelem].be_ts - br->br_elems[br->br_firstelem].be_ts) < 3000000 ) { + return 0; + } + else { + /* + * don't do this check since not all the cases have this kind of burst width variation. + * + for (i=0; ibr_elems[index[i]].be_dur; + } + average_width = total_width/bursts; + for (i=0; ibr_elems[index[i]].be_dur, average_width); + } + average_diff = total_diff/bursts; + if( average_diff > DFS_BIN5_WIDTH_MARGIN ) { + return 1; + } else { + + DFS_DPRINTK(ic, ATH_DEBUG_DFS_BIN5, "bursts=%u numevents=%u total_width=%d average_width=%d total_diff=%d average_diff=%d\n", bursts, numevents, total_width, average_width, total_diff, average_diff); + + } + */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "bursts=%u numevents=%u total_width=%d average_width=%d total_diff=%d average_diff=%d\n", bursts, numevents, total_width, average_width, total_diff, average_diff); + DFS_PRINTK("bin 5 radar detected, bursts=%d\n", bursts); + return 1; + } + } + } + + return 0; +} + + +/* Return TRUE if chirping pulse, FALSE if not. + Decision is made based on processing the FFT data included with the PHY error. + Calculate the slope using the maximum bin index reported in the FFT data. + Calculate slope between FFT packet 0 and packet n-1. Also calculate slope between + packet 1 and packet n. + If a pulse is chirping, a slope of 5 and greater is seen. + Non-chirping pulses have slopes of 0, 1, 2 or 3. +*/ + +/* + * Chirp detection for Sowl/Howl. + */ +static int +dfs_check_chirping_sowl(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, int is_ctl, int is_ext, int *slope, int *is_dc) +{ +#define FFT_LEN 70 +#define FFT_LOWER_BIN_MAX_INDEX_BYTE 66 +#define FFT_UPPER_BIN_MAX_INDEX_BYTE 69 +#define MIN_CHIRPING_SLOPE 4 + int is_chirp=0; + int p, num_fft_packets=0; + int ctl_slope=0, ext_slope=0; + int ctl_high0, ctl_low0, ctl_slope0=0, ext_high0, ext_low0, ext_slope0=0; + int ctl_high1, ctl_low1, ctl_slope1=0, ext_high1, ext_low1, ext_slope1=0; + u_int8_t *fft_data_ptr; + + *slope = 0; + *is_dc = 0; + + num_fft_packets = datalen / FFT_LEN; + fft_data_ptr = ((u_int8_t*)buf); + + /* DEBUG - Print relevant portions of the FFT data*/ + for (p=0; p < num_fft_packets; p++) { + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "fft_data_ptr=0x%p\t", fft_data_ptr); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "[66]=%d [69]=%d\n", + *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2, + *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2); + + fft_data_ptr += FFT_LEN; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "datalen=%d num_fft_packets=%d\n", datalen, num_fft_packets); + + /* There is not enough FFT data to figure out whether the pulse is chirping or not*/ + if (num_fft_packets < 4) { + return 0; + } + + fft_data_ptr = ((u_int8_t*)buf); + + if (is_ctl) { + + fft_data_ptr = ((u_int8_t*)buf); + ctl_low0 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + fft_data_ptr += FFT_LEN; + ctl_low1 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + + // last packet with first packet + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 1)); + ctl_high1 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + + // second last packet with 0th packet + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 2)); + ctl_high0 = *(fft_data_ptr+FFT_LOWER_BIN_MAX_INDEX_BYTE) >> 2; + + ctl_slope0 = ctl_high0 - ctl_low0; + if (ctl_slope0 < 0) ctl_slope0 *= (-1); + + ctl_slope1 = ctl_high1 - ctl_low1; + if (ctl_slope1 < 0) ctl_slope1 *= (-1); + + ctl_slope = ((ctl_slope0 > ctl_slope1) ? ctl_slope0: ctl_slope1); + *slope = ctl_slope; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "ctl_slope0=%d ctl_slope1=%d ctl_slope=%d\n", + ctl_slope0, ctl_slope1, ctl_slope); + + } else if (is_ext) { + + fft_data_ptr = ((u_int8_t*)buf); + ext_low0 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + + fft_data_ptr += FFT_LEN; + ext_low1 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 1)); + ext_high1 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + fft_data_ptr = ((u_int8_t*)buf) + (FFT_LEN*(num_fft_packets - 2)); + ext_high0 = *(fft_data_ptr+FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + + ext_slope0 = ext_high0 - ext_low0; + if (ext_slope0 < 0) ext_slope0 *= (-1); + + ext_slope1 = ext_high1 - ext_low1; + if (ext_slope1 < 0) ext_slope1 *= (-1); + + ext_slope = ((ext_slope0 > ext_slope1) ? ext_slope0: ext_slope1); + *slope = ext_slope; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT | ATH_DEBUG_DFS_BIN5, + "ext_slope0=%d ext_slope1=%d ext_slope=%d\n", + ext_slope0, ext_slope1, ext_slope); + } else + return 0; + + if ((ctl_slope >= MIN_CHIRPING_SLOPE) || (ext_slope >= MIN_CHIRPING_SLOPE)) { + is_chirp = 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5 | ATH_DEBUG_DFS_BIN5_FFT | + ATH_DEBUG_DFS_PHYERR_SUM, + "is_chirp=%d is_dc=%d\n", is_chirp, *is_dc); + } + return is_chirp; + +#undef FFT_LEN +#undef FFT_LOWER_BIN_MAX_INDEX_BYTE +#undef FFT_UPPER_BIN_MAX_INDEX_BYTE +#undef MIN_CHIRPING_SLOPE +} + +/* + * Merlin (and Osprey, etc) chirp radar chirp detection. + */ +static int +dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + int is_ctl, int is_ext, int *slope, int *is_dc) +{ +#define ABS_DIFF(_x, _y) ((int)_x > (int)_y ? (int)_x - (int)_y : (int)_y - (int)_x) +#define ABS(_x) ((int)_x > 0 ? (int)_x : - (int)_x) + +#define DELTA_STEP 1 /* This should be between 1 and 3. Default is 1. */ +#define NUM_DIFFS 3 /* Number of Diffs to compute. valid range is 2-4 */ +#define MAX_DIFF 2 /* Threshold for difference of delta peaks */ +#define BIN_COUNT_MAX 6 /* Max. number of strong bins for narrow band */ + + +/* + * Dynamic 20/40 mode FFT packet format related definition + */ + +#define NUM_FFT_BYTES_HT40 70 +#define NUM_BIN_BYTES_HT40 64 +#define NUM_SUBCHAN_BINS_HT40 64 +#define LOWER_INDEX_BYTE_HT40 66 +#define UPPER_INDEX_BYTE_HT40 69 +#define LOWER_WEIGHT_BYTE_HT40 64 +#define UPPER_WEIGHT_BYTE_HT40 67 +#define LOWER_MAG_BYTE_HT40 65 +#define UPPER_MAG_BYTE_HT40 68 + +/* + * Static 20 mode FFT packet format related definition + */ + +#define NUM_FFT_BYTES_HT20 31 +#define NUM_BIN_BYTES_HT20 28 +#define NUM_SUBCHAN_BINS_HT20 56 +#define LOWER_INDEX_BYTE_HT20 30 +#define UPPER_INDEX_BYTE_HT20 30 +#define LOWER_WEIGHT_BYTE_HT20 28 +#define UPPER_WEIGHT_BYTE_HT20 28 +#define LOWER_MAG_BYTE_HT20 29 +#define UPPER_MAG_BYTE_HT20 29 + + int num_fft_packets; /* number of FFT packets reported to software */ + int num_fft_bytes; + int num_bin_bytes; + int num_subchan_bins; + int lower_index_byte; + int upper_index_byte; + int lower_weight_byte; + int upper_weight_byte; + int lower_mag_byte; + int upper_mag_byte; + + int max_index_lower [DELTA_STEP + NUM_DIFFS]; + int max_index_upper [DELTA_STEP + NUM_DIFFS]; + int max_mag_lower [DELTA_STEP + NUM_DIFFS]; + int max_mag_upper [DELTA_STEP + NUM_DIFFS]; + int bin_wt_lower [DELTA_STEP + NUM_DIFFS]; + int bin_wt_upper [DELTA_STEP + NUM_DIFFS]; + int max_mag_sel [DELTA_STEP + NUM_DIFFS]; + int max_mag [DELTA_STEP + NUM_DIFFS]; + int max_index [DELTA_STEP + NUM_DIFFS]; + + + + int max_d[] = {10, 19, 28}; + int min_d[] = {1, 2, 3}; + + u_int8_t *ptr; /* pointer to FFT data */ + int i; + int fft_start; + int chirp_found; + int delta_peak[NUM_DIFFS]; + int j; + int bin_count; + int bw_mask; + int delta_diff; + int same_sign; + int temp; + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + num_fft_bytes = NUM_FFT_BYTES_HT40; + num_bin_bytes = NUM_BIN_BYTES_HT40; + num_subchan_bins = NUM_SUBCHAN_BINS_HT40; + lower_index_byte = LOWER_INDEX_BYTE_HT40; + upper_index_byte = UPPER_INDEX_BYTE_HT40; + lower_weight_byte = LOWER_WEIGHT_BYTE_HT40; + upper_weight_byte = UPPER_WEIGHT_BYTE_HT40; + lower_mag_byte = LOWER_MAG_BYTE_HT40; + upper_mag_byte = UPPER_MAG_BYTE_HT40; + + /* if we are in HT40MINUS then swap primary and extension */ + if (IS_CHAN_HT40_MINUS(dfs->ic->ic_curchan)) { + temp = is_ctl; + is_ctl = is_ext; + is_ext = temp; + } + + } else { + num_fft_bytes = NUM_FFT_BYTES_HT20; + num_bin_bytes = NUM_BIN_BYTES_HT20; + num_subchan_bins = NUM_SUBCHAN_BINS_HT20; + lower_index_byte = LOWER_INDEX_BYTE_HT20; + upper_index_byte = UPPER_INDEX_BYTE_HT20; + lower_weight_byte = LOWER_WEIGHT_BYTE_HT20; + upper_weight_byte = UPPER_WEIGHT_BYTE_HT20; + lower_mag_byte = LOWER_MAG_BYTE_HT20; + upper_mag_byte = UPPER_MAG_BYTE_HT20; + } + + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + + ptr = (u_int8_t*)buf; + /* + * sanity check for FFT buffer + */ + + if ((ptr == NULL) || (datalen == 0)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "%s: FFT buffer pointer is null or size is 0\n", __func__); + return 0; + } + + num_fft_packets = (datalen - 3) / num_fft_bytes; + if (num_fft_packets < (NUM_DIFFS + DELTA_STEP)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, "datalen = %d, num_fft_packets = %d, too few packets... (exiting)\n", datalen, num_fft_packets); + return 0; + } + + if ((((datalen - 3) % num_fft_bytes) == 2) && (datalen > num_fft_bytes)) { + // FIXME !!! + ptr += 2; + datalen -= 2; + } + + for (i = 0; i < (NUM_DIFFS + DELTA_STEP); i++) { + fft_start = i * num_fft_bytes; + bin_wt_lower[i] = ptr[fft_start + lower_weight_byte] & 0x3f; + bin_wt_upper[i] = ptr[fft_start + upper_weight_byte] & 0x3f; + + max_index_lower[i] = ptr[fft_start + lower_index_byte] >> 2; + max_index_upper[i] = (ptr[fft_start + upper_index_byte] >> 2) + num_subchan_bins; + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if (!IS_CHAN_HT40(dfs->ic->ic_curchan)) { + /* + * for HT20 mode indices are 6 bit signed number + */ + max_index_lower[i] ^= 0x20; + max_index_upper[i] = 0; + } + + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + /* + * Reconstruct the maximum magnitude for each sub-channel. Also select + * and flag the max overall magnitude between the two sub-channels. + */ + + max_mag_lower[i] = ((ptr[fft_start + lower_index_byte] & 0x03) << 8) + + ptr[fft_start + lower_mag_byte]; + max_mag_upper[i] = ((ptr[fft_start + upper_index_byte] & 0x03) << 8) + + ptr[fft_start + upper_mag_byte]; + bw_mask = ((bin_wt_lower[i] == 0) ? 0 : is_ctl) + + (((bin_wt_upper[i] == 0) ? 0 : is_ext) << 1); + + /* + * Limit the max bin based on channel bandwidth + * If the upper sub-channel max index is stuck at '1', the signal is dominated + * by residual DC (or carrier leak) and should be ignored. + */ + + if (bw_mask == 1) { + max_mag_sel[i] = 0; + max_mag[i] = max_mag_lower[i]; + max_index[i] = max_index_lower[i]; + } else if(bw_mask == 2) { + max_mag_sel[i] = 1; + max_mag[i] = max_mag_upper[i]; + max_index[i] = max_index_upper[i]; + } else if(max_index_upper[i] == num_subchan_bins) { + max_mag_sel[i] = 0; /* Ignore DC bin. */ + max_mag[i] = max_mag_lower[i]; + max_index[i] = max_index_lower[i]; + } else { + if (max_mag_upper[i] > max_mag_lower[i]) { + max_mag_sel[i] = 1; + max_mag[i] = max_mag_upper[i]; + max_index[i] = max_index_upper[i]; + } else { + max_mag_sel[i] = 0; + max_mag[i] = max_mag_lower[i]; + max_index[i] = max_index_lower[i]; + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "i=%d, max_index[i]=%d, max_index_lower[i]=%d, " + "max_index_upper[i]=%d\n", + i, max_index[i], max_index_lower[i], max_index_upper[i]); + } + + + + chirp_found = 1; + delta_diff = 0; + same_sign = 1; + + /* + delta_diff computation -- look for movement in peak. + make sure that the chirp direction (i.e. sign) is always the same, + i.e. sign of the two peaks should be same. + */ + for (i = 0; i < NUM_DIFFS; i++) { + delta_peak[i] = max_index[i + DELTA_STEP] - max_index[i]; + if (i > 0) { + delta_diff = delta_peak[i] - delta_peak[i-1]; + same_sign = !((delta_peak[i] & 0x80) ^ (delta_peak[i-1] & 0x80)); + } + chirp_found &= (ABS(delta_peak[i]) >= min_d[DELTA_STEP - 1]) && + (ABS(delta_peak[i]) <= max_d[DELTA_STEP - 1]) && + same_sign && + (ABS(delta_diff) <= MAX_DIFF); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "i=%d, delta_peak[i]=%d, delta_diff=%d\n", + i, delta_peak[i], delta_diff); + } + + + if (chirp_found) + { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "%s: CHIRPING_BEFORE_STRONGBIN_YES\n", __func__); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "%s: CHIRPING_BEFORE_STRONGBIN_NO\n", __func__); + } + + /* + Work around for potential hardware data corruption bug. Check for + wide band signal by counting strong bins indicated by bitmap flags. + This check is done if chirp_found is true. We do this as a final check + to weed out corrupt FFTs bytes. This looks expensive but in most cases it + will exit early. + */ + + for (i = 0; (i < (NUM_DIFFS + DELTA_STEP)) && (chirp_found == 1); i++) { + bin_count = 0; + /* point to the start of the 1st byte of the selected sub-channel. */ + fft_start = (i * num_fft_bytes) + (max_mag_sel[i] ? (num_subchan_bins >> 1) : 0); + for (j = 0; j < (num_subchan_bins >> 1); j++) + { + /* + * If either bin is flagged "strong", accumulate the bin_count. + * It's not accurate, but good enough... + */ + bin_count += (ptr[fft_start + j] & 0x88) ? 1 : 0; + } + chirp_found &= (bin_count > BIN_COUNT_MAX) ? 0 : 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT, + "i=%d, computed bin_count=%d\n", i, bin_count); + } + + if (chirp_found) + { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT | ATH_DEBUG_DFS_PHYERR_SUM, + "%s: CHIRPING_YES\n", __func__); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_FFT | ATH_DEBUG_DFS_PHYERR_SUM, + "%s: CHIRPING_NO\n", __func__); + } + return chirp_found; + +#undef ABS_DIFF +#undef ABS +#undef DELTA_STEP +#undef NUM_DIFFS +#undef MAX_DIFF +#undef BIN_COUNT_MAX + +#undef NUM_FFT_BYTES_HT40 +#undef NUM_BIN_BYTES_HT40 +#undef NUM_SUBCHAN_BINS_HT40 +#undef LOWER_INDEX_BYTE_HT40 +#undef UPPER_INDEX_BYTE_HT40 +#undef LOWER_WEIGHT_BYTE_HT40 +#undef UPPER_WEIGHT_BYTE_HT40 +#undef LOWER_MAG_BYTE_HT40 +#undef UPPER_MAG_BYTE_HT40 + +#undef NUM_FFT_BYTES_HT40 +#undef NUM_BIN_BYTES_HT40 +#undef NUM_SUBCHAN_BINS_HT40 +#undef LOWER_INDEX_BYTE_HT40 +#undef UPPER_INDEX_BYTE_HT40 +#undef LOWER_WEIGHT_BYTE_HT40 +#undef UPPER_WEIGHT_BYTE_HT40 +#undef LOWER_MAG_BYTE_HT40 +#undef UPPER_MAG_BYTE_HT40 +} + +int +dfs_check_chirping(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, int is_ctl, int is_ext, int *slope, int *is_dc) +{ + + if (dfs->dfs_caps.ath_dfs_use_enhancement) + return dfs_check_chirping_merlin(dfs, buf, datalen, is_ctl, + is_ext, slope, is_dc); + else + return dfs_check_chirping_sowl(dfs, buf, datalen, is_ctl, + is_ext, slope, is_dc); +} + +u_int8_t +dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, u_int32_t diff_ts, + u_int8_t old_dur) +{ + + /* + * Pulses may get split into 2 during chirping, this print is only + * to show that it happened, we do not handle this condition if we + * cannot detect the chirping. + */ + /* + * SPLIT pulses will have a time stamp difference of < 50 + */ + if (diff_ts < 50) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, + "%s SPLIT pulse diffTs=%u dur=%d (old_dur=%d)\n", + __func__, diff_ts, + dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur); + } + /* + * Check if this is the 2nd or 3rd pulse in the same burst, + * PRI will be between 1000 and 2000 us + */ + if (((diff_ts >= DFS_BIN5_PRI_LOWER_LIMIT) && + (diff_ts <= DFS_BIN5_PRI_HIGHER_LIMIT))) { + /* + * This pulse belongs to the same burst as the pulse before, + * so return the same random duration for it + */ + DFS_DPRINTK(dfs,ATH_DEBUG_DFS_BIN5, + "%s this pulse belongs to the same burst as before, give " + "it same dur=%d (old_dur=%d)\n", + __func__, dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur); + + return (dfs->dfs_rinfo.dfs_last_bin5_dur); + } + /* + * This pulse does not belong to this burst, return unchanged + * duration. + */ + return old_dur; +} + +/* + * Chirping pulses may get cut off at DC and report lower durations. + * + * This function will compute a suitable random duration for each pulse. + * Duration must be between 50 and 100 us, but remember that in + * ath_process_phyerr() which calls this function, we are dealing with the + * HW reported duration (unconverted). dfs_process_radarevent() will + * actually convert the duration into the correct value. + * + * XXX This function doesn't take into account whether the hardware + * is operating in 5GHz fast clock mode or not. + * + * XXX And this function doesn't take into account whether the hardware + * is peregrine or not. Grr. + */ +int +dfs_get_random_bin5_dur(struct ath_dfs *dfs, u_int64_t tstamp) +{ + u_int8_t new_dur=MIN_BIN5_DUR; + int range; + + get_random_bytes(&new_dur, sizeof(u_int8_t)); + + range = (MAX_BIN5_DUR - MIN_BIN5_DUR + 1); + + new_dur %= range; + + new_dur += MIN_BIN5_DUR; + + return new_dur; +} + +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_init.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_init.c new file mode 100644 index 000000000000..be4262fbc4aa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_init.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_init.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifdef ATH_SUPPORT_DFS + +extern int domainoverride; + +/* + * Clear all delay lines for all filter types + * + * This may be called before any radar pulses are configured + * (eg on a non-DFS channel, with radar PHY errors still showing up.) + * In that case, just drop out early. + */ +void dfs_reset_alldelaylines(struct ath_dfs *dfs) +{ + struct dfs_filtertype *ft = NULL; + struct dfs_filter *rf; + struct dfs_delayline *dl; + struct dfs_pulseline *pl; + int i,j; + + if (dfs == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: sc_dfs is NULL", __func__, __LINE__); + return; + } + pl = dfs->pulses; + + if (pl == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: pl==NULL, dfs=%p", __func__, __LINE__, dfs); + return; + } + + if (dfs->dfs_b5radars == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: pl==NULL, b5radars=%p", __func__, __LINE__, dfs->dfs_b5radars); + return; + } + + /* reset the pulse log */ + pl->pl_firstelem = pl->pl_numelems = 0; + pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; + + for (i=0; idfs_radarf[i] != NULL) { + ft = dfs->dfs_radarf[i]; + if (NULL != ft) { + for (j = 0; j < ft->ft_numfilters; j++) { + rf = &(ft->ft_filters[j]); + dl = &(rf->rf_dl); + if (dl != NULL) { + OS_MEMZERO(dl, sizeof(struct dfs_delayline)); + dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; + } + } + } + } + } + for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) { + OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]), sizeof(struct dfs_bin5elem)*DFS_MAX_B5_SIZE); + dfs->dfs_b5radars[i].br_firstelem = 0; + dfs->dfs_b5radars[i].br_numelems = 0; + dfs->dfs_b5radars[i].br_lastelem = (0xFFFFFFFF)&DFS_MAX_B5_MASK; + } +} +/* + * Clear only a single delay line + */ + +void dfs_reset_delayline(struct dfs_delayline *dl) +{ + OS_MEMZERO(&(dl->dl_elems[0]), sizeof(dl->dl_elems)); + dl->dl_lastelem = (0xFFFFFFFF)&DFS_MAX_DL_MASK; +} + +void dfs_reset_filter_delaylines(struct dfs_filtertype *dft) +{ + int i; + struct dfs_filter *df; + for (i=0; i< DFS_MAX_NUM_RADAR_FILTERS; i++) { + df = &dft->ft_filters[i]; + dfs_reset_delayline(&(df->rf_dl)); + } +} + +void +dfs_reset_radarq(struct ath_dfs *dfs) +{ + struct dfs_event *event; + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL", __func__); + return; + } + ATH_DFSQ_LOCK(dfs); + ATH_DFSEVENTQ_LOCK(dfs); + while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) { + event = STAILQ_FIRST(&(dfs->dfs_radarq)); + STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); + OS_MEMZERO(event, sizeof(struct dfs_event)); + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); + } + ATH_DFSEVENTQ_UNLOCK(dfs); + ATH_DFSQ_UNLOCK(dfs); +} + + +/* This function Initialize the radar filter tables + * if the ath dfs domain is uninitalized or + * ath dfs domain is different from hal dfs domain + */ +int dfs_init_radar_filters(struct ieee80211com *ic, + struct ath_dfs_radar_tab_info *radar_info) +{ + u_int32_t T, Tmax; + int numpulses,p,n, i; + int numradars = 0, numb5radars = 0; + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct dfs_filtertype *ft = NULL; + struct dfs_filter *rf=NULL; + struct dfs_pulse *dfs_radars; + struct dfs_bin5pulse *b5pulses=NULL; + int32_t min_rssithresh=DFS_MAX_RSSI_VALUE; + u_int32_t max_pulsedur=0; + + if (dfs == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: dfs is NULL", __func__, __LINE__); + return DFS_STATUS_FAIL; + } + /* clear up the dfs domain flag first */ +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->ath_dfs_isdfsregdomain = 0; +#endif + + /* + * If radar_info is NULL or dfsdomain is NULL, treat + * the rest of the radar configuration as suspect. + */ + if (radar_info == NULL || radar_info->dfsdomain == 0) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: Unknown dfs domain %d ", + __func__, __LINE__, dfs->dfsdomain); + /* Disable radar detection since we don't have a radar domain */ + dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; + /* Returning success though we are not completing init. A failure + * will fail dfs_attach also. + */ + return DFS_STATUS_SUCCESS; + } + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s[%d]:dfsdomain=%d, numradars=%d, numb5radars=%d", + __func__, __LINE__, radar_info->dfsdomain, + radar_info->numradars, radar_info->numb5radars); + dfs->dfsdomain = radar_info->dfsdomain; + dfs_radars = radar_info->dfs_radars; + numradars = radar_info->numradars; + b5pulses = radar_info->b5pulses; + numb5radars = radar_info->numb5radars; + + /* XXX this should be an explicit copy of some sort! */ + dfs->dfs_defaultparams = radar_info->dfs_defaultparams; + +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + dfs->ath_dfs_isdfsregdomain = 1; +#endif + + dfs->dfs_rinfo.rn_numradars = 0; + /* Clear filter type table */ + for (n = 0; n < 256; n++) { + for (i=0;idfs_radartable[n])[i] = -1; + } + /* Now, initialize the radar filters */ + for (p=0; pdfs_rinfo.rn_numradars; n++) { + if ((dfs_radars[p].rp_pulsedur == dfs->dfs_radarf[n]->ft_filterdur) && + (dfs_radars[p].rp_numpulses == dfs->dfs_radarf[n]->ft_numpulses) && + (dfs_radars[p].rp_mindur == dfs->dfs_radarf[n]->ft_mindur) && + (dfs_radars[p].rp_maxdur == dfs->dfs_radarf[n]->ft_maxdur)) { + ft = dfs->dfs_radarf[n]; + break; + } + } + if (ft == NULL) { + /* No filter of the appropriate dur was found */ + if ((dfs->dfs_rinfo.rn_numradars+1) >DFS_MAX_RADAR_TYPES) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Too many filter types", + __func__); + goto bad4; + } + ft = dfs->dfs_radarf[dfs->dfs_rinfo.rn_numradars]; + ft->ft_numfilters = 0; + ft->ft_numpulses = dfs_radars[p].rp_numpulses; + ft->ft_patterntype = dfs_radars[p].rp_patterntype; + ft->ft_mindur = dfs_radars[p].rp_mindur; + ft->ft_maxdur = dfs_radars[p].rp_maxdur; + ft->ft_filterdur = dfs_radars[p].rp_pulsedur; + ft->ft_rssithresh = dfs_radars[p].rp_rssithresh; + ft->ft_rssimargin = dfs_radars[p].rp_rssimargin; + ft->ft_minpri = 1000000; + + if (ft->ft_rssithresh < min_rssithresh) + min_rssithresh = ft->ft_rssithresh; + if (ft->ft_maxdur > max_pulsedur) + max_pulsedur = ft->ft_maxdur; + for (i=ft->ft_mindur; i<=ft->ft_maxdur; i++) { + u_int32_t stop=0,tableindex=0; + while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) { + if ((dfs->dfs_radartable[i])[tableindex] == -1) + stop = 1; + else + tableindex++; + } + if (stop) { + (dfs->dfs_radartable[i])[tableindex] = + (int8_t) (dfs->dfs_rinfo.rn_numradars); + } else { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: Too many overlapping radar filters", + __func__); + goto bad4; + } + } + dfs->dfs_rinfo.rn_numradars++; + } + rf = &(ft->ft_filters[ft->ft_numfilters++]); + dfs_reset_delayline(&rf->rf_dl); + numpulses = dfs_radars[p].rp_numpulses; + + rf->rf_numpulses = numpulses; + rf->rf_patterntype = dfs_radars[p].rp_patterntype; + rf->rf_pulseid = dfs_radars[p].rp_pulseid; + rf->rf_mindur = dfs_radars[p].rp_mindur; + rf->rf_maxdur = dfs_radars[p].rp_maxdur; + rf->rf_numpulses = dfs_radars[p].rp_numpulses; + rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window; + T = (100000000/dfs_radars[p].rp_max_pulsefreq) - + 100*(dfs_radars[p].rp_meanoffset); + rf->rf_minpri = + dfs_round((int32_t)T - (100*(dfs_radars[p].rp_pulsevar))); + Tmax = (100000000/dfs_radars[p].rp_pulsefreq) - + 100*(dfs_radars[p].rp_meanoffset); + rf->rf_maxpri = + dfs_round((int32_t)Tmax + (100*(dfs_radars[p].rp_pulsevar))); + + if( rf->rf_minpri < ft->ft_minpri ) + ft->ft_minpri = rf->rf_minpri; + + rf->rf_fixed_pri_radar_pulse = ( dfs_radars[p].rp_max_pulsefreq == dfs_radars[p].rp_pulsefreq ) ? 1 : 0; + rf->rf_threshold = dfs_radars[p].rp_threshold; + rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]: minprf = %d maxprf = %d pulsevar = %d thresh=%d", + __func__,__LINE__,dfs_radars[p].rp_pulsefreq, dfs_radars[p].rp_max_pulsefreq, + dfs_radars[p].rp_pulsevar, rf->rf_threshold); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:minpri = %d maxpri = %d filterlen = %d filterID = %d",__func__,__LINE__, + rf->rf_minpri, rf->rf_maxpri, rf->rf_filterlen, rf->rf_pulseid); + + } + +#ifdef DFS_DEBUG + dfs_print_filters(ic); +#endif + dfs->dfs_rinfo.rn_numbin5radars = numb5radars; + if (dfs->dfs_b5radars != NULL) + OS_FREE(dfs->dfs_b5radars); + + dfs->dfs_b5radars = (struct dfs_bin5radars *)OS_MALLOC(NULL, + numb5radars * sizeof(struct dfs_bin5radars), GFP_KERNEL); + if (dfs->dfs_b5radars == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: cannot allocate memory for bin5 radars", + __func__); + goto bad4; + } + for (n=0; ndfs_b5radars[n].br_pulse = b5pulses[n]; + dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000; + if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < min_rssithresh) + min_rssithresh = dfs->dfs_b5radars[n].br_pulse.b5_rssithresh; + if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur) + max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur; + } + dfs_reset_alldelaylines(dfs); + dfs_reset_radarq(dfs); + dfs->dfs_curchan_radindex = -1; + dfs->dfs_extchan_radindex = -1; + dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh; + /* Convert durations to TSF ticks */ + dfs->dfs_rinfo.rn_maxpulsedur = dfs_round((int32_t)((max_pulsedur*100/80)*100)); + /* relax the max pulse duration a little bit due to inaccuracy caused by chirping. */ + dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur +20; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s[%d]: DFS min filter rssiThresh = %d", + __func__, __LINE__, min_rssithresh); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s[%d]:DFS max pulse dur = %d ticks", + __func__ ,__LINE__, dfs->dfs_rinfo.rn_maxpulsedur); + return DFS_STATUS_SUCCESS; + + bad4: + return DFS_STATUS_FAIL; +} + +void +dfs_clear_stats(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + if (dfs == NULL) + return; + OS_MEMZERO(&dfs->ath_dfs_stats, sizeof (struct dfs_stats)); + dfs->ath_dfs_stats.last_reset_tstamp = ic->ic_get_TSF64(ic); +} + +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl.h new file mode 100644 index 000000000000..d6f6b225578e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2010-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_ioctl.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +/* + * ioctl defines + */ + +#ifndef _DFS_IOCTL_H_ +#define _DFS_IOCTL_H_ + +#define DFS_MUTE_TIME 1 +#define DFS_SET_THRESH 2 +#define DFS_GET_THRESH 3 +#define DFS_GET_USENOL 4 +#define DFS_SET_USENOL 5 +#define DFS_RADARDETECTS 6 +#define DFS_BANGRADAR 7 +#define DFS_SHOW_NOL 8 +#define DFS_DISABLE_DETECT 9 +#define DFS_ENABLE_DETECT 10 +#define DFS_DISABLE_FFT 11 +#define DFS_ENABLE_FFT 12 +#define DFS_SET_DEBUG_LEVEL 13 +#define DFS_GET_NOL 14 +#define DFS_SET_NOL 15 + +#define DFS_SET_FALSE_RSSI_THRES 16 +#define DFS_SET_PEAK_MAG 17 +#define DFS_IGNORE_CAC 18 +#define DFS_SET_NOL_TIMEOUT 19 +#define DFS_LAST_IOCTL 20 +#ifndef IEEE80211_CHAN_MAX +#define IEEE80211_CHAN_MAX 255 +#endif + +struct dfsreq_nolelem { + u_int16_t nol_freq; /* NOL channel frequency */ + u_int16_t nol_chwidth; + unsigned long nol_start_ticks; /* OS ticks when the NOL timer started */ + u_int32_t nol_timeout_ms; /* Nol timeout value in msec */ +}; + +struct dfsreq_nolinfo { + u_int32_t ic_nchans; + struct dfsreq_nolelem dfs_nol[IEEE80211_CHAN_MAX]; +}; + +/* + * ioctl parameter types + */ + +#define DFS_PARAM_FIRPWR 1 +#define DFS_PARAM_RRSSI 2 +#define DFS_PARAM_HEIGHT 3 +#define DFS_PARAM_PRSSI 4 +#define DFS_PARAM_INBAND 5 +//5413 specific parameters +#define DFS_PARAM_RELPWR 7 +#define DFS_PARAM_RELSTEP 8 +#define DFS_PARAM_MAXLEN 9 + +struct dfs_ioctl_params { + int32_t dfs_firpwr; /* FIR pwr out threshold */ + int32_t dfs_rrssi; /* Radar rssi thresh */ + int32_t dfs_height; /* Pulse height thresh */ + int32_t dfs_prssi; /* Pulse rssi thresh */ + int32_t dfs_inband; /* Inband thresh */ + int32_t dfs_relpwr; /* pulse relative pwr thresh */ + int32_t dfs_relstep; /* pulse relative step thresh */ + int32_t dfs_maxlen; /* pulse max duration */ +}; + +/* + * XXX keep these in sync with ath_dfs_phyerr_param! + */ +#define DFS_IOCTL_PARAM_NOVAL 65535 +#define DFS_IOCTL_PARAM_ENABLE 0x8000 + +#endif /* _DFS_IOCTL_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl_private.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl_private.h new file mode 100644 index 000000000000..02397973e949 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_ioctl_private.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_ioctl_private.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +/* + * ioctl defines + */ + +#ifndef _DFS_IOCTL_PRIVATE_H_ +#define _DFS_IOCTL_PRIVATE_H_ + +/* + * Assert that the NOVAL values match. + */ +#if (ATH_DFS_PHYERR_PARAM_NOVAL != DFS_IOCTL_PARAM_NOVAL) +#error "ATH_DFS_PHYERR_PARAM_NOVAL != DFS_IOCTL_PARAM_NOVAL" +#endif + +/* + * Assert that the ENABLE values match. + */ +#if (ATH_DFS_PHYERR_PARAM_ENABLE != DFS_IOCTL_PARAM_ENABLE) +#error "ATH_DFS_PHYERR_PARAM_ENABLE != DFS_IOCTL_PARAM_ENABLE" +#endif + +/* + * These two methods are used by the lmac glue to copy between + * the DFS and HAL PHY configuration. + * + * I'm "cheating" here and assuming that the ENABLE and NOVAL + * values match - see the above macros. + */ +static inline void +ath_dfs_ioctlparam_to_dfsparam(const struct dfs_ioctl_params *src, + struct ath_dfs_phyerr_param *dst) +{ + + dst->pe_firpwr = src->dfs_firpwr; + dst->pe_rrssi = src->dfs_rrssi; + dst->pe_height = src->dfs_height; + dst->pe_prssi = src->dfs_prssi; + dst->pe_inband = src->dfs_inband; + dst->pe_relpwr = src->dfs_relpwr; + dst->pe_relstep = src->dfs_relstep; + dst->pe_maxlen = src->dfs_maxlen; +} + +static inline void +ath_dfs_dfsparam_to_ioctlparam(struct ath_dfs_phyerr_param *src, + struct dfs_ioctl_params *dst) +{ + + dst->dfs_firpwr = src->pe_firpwr; + dst->dfs_rrssi = src->pe_rrssi; + dst->dfs_height = src->pe_height; + dst->dfs_prssi = src->pe_prssi; + dst->dfs_inband = src->pe_inband; + dst->dfs_relpwr = src->pe_relpwr; + dst->dfs_relstep = src->pe_relstep; + dst->dfs_maxlen = src->pe_maxlen; +} + +#endif /* _DFS_IOCTL_PRIVATE_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_misc.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_misc.c new file mode 100644 index 000000000000..e02ef6dfe901 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_misc.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2002-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_misc.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifndef UNINET +/* TO DO DFS +#include +*/ +#endif +#ifdef ATH_SUPPORT_DFS + +static int adjust_pri_per_chan_busy(int ext_chan_busy, int pri_margin) +{ + int adjust_pri=0; + + if(ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) { + + adjust_pri = (ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) * (pri_margin); + adjust_pri /= 100; + + } + return adjust_pri; +} + +static int adjust_thresh_per_chan_busy(int ext_chan_busy, int thresh) +{ + int adjust_thresh=0; + + if(ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) { + + adjust_thresh = (ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) * thresh; + adjust_thresh /= 100; + + } + return adjust_thresh; +} +/* For the extension channel, if legacy traffic is present, we see a lot of false alarms, +so make the PRI margin narrower depending on the busy % for the extension channel.*/ + +int +dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, + int is_fixed_pattern) +{ + + int adjust_pri=0, ext_chan_busy=0; + int pri_margin; + + if (is_fixed_pattern) + pri_margin = DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN; + else + pri_margin = DFS_DEFAULT_PRI_MARGIN; + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic); + if(ext_chan_busy >= 0) { + dfs->dfs_rinfo.ext_chan_busy_ts = dfs->ic->ic_get_TSF64(dfs->ic); + dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; + } else { + // Check to see if the cached value of ext_chan_busy can be used + ext_chan_busy = 0; + if (dfs->dfs_rinfo.dfs_ext_chan_busy) { + if (dfs->dfs_rinfo.rn_lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) { + ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + " PRI Use cached copy of ext_chan_busy extchanbusy=%d \n", ext_chan_busy); + } + } + } + adjust_pri = adjust_pri_per_chan_busy(ext_chan_busy, pri_margin); + + pri_margin -= adjust_pri; + } else { + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + } + + return pri_margin; +} + +/* For the extension channel, if legacy traffic is present, we see a lot of false alarms, +so make the thresholds higher depending on the busy % for the extension channel.*/ + +int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, + int is_extchan_detect) +{ + int ext_chan_busy=0; + int thresh, adjust_thresh=0; + + thresh = rf->rf_threshold; + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic); + if(ext_chan_busy >= 0) { + dfs->dfs_rinfo.ext_chan_busy_ts = dfs->ic->ic_get_TSF64(dfs->ic); + dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; + } else { + // Check to see if the cached value of ext_chan_busy can be used + ext_chan_busy = 0; + if (dfs->dfs_rinfo.dfs_ext_chan_busy) { + if (dfs->dfs_rinfo.rn_lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) { + ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + " THRESH Use cached copy of ext_chan_busy extchanbusy=%d rn_lastfull_ts=%llu ext_chan_busy_ts=%llu\n", + ext_chan_busy, + (unsigned long long)dfs->dfs_rinfo.rn_lastfull_ts, + (unsigned long long)dfs->dfs_rinfo.ext_chan_busy_ts); + } + } + } + + adjust_thresh = adjust_thresh_per_chan_busy(ext_chan_busy, thresh); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + " filterID=%d extchanbusy=%d adjust_thresh=%d\n", + rf->rf_pulseid, ext_chan_busy, adjust_thresh); + + thresh += adjust_thresh; + } else { + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + } + return thresh; +} + + +u_int32_t dfs_round(int32_t val) +{ + u_int32_t ival,rem; + + if (val < 0) + return 0; + ival = val/100; + rem = val-(ival*100); + if (rem <50) + return ival; + else + return(ival+1); +} + +struct ieee80211_channel * +ieee80211_get_extchan(struct ieee80211com *ic) +{ + int chan_offset = 0; + if (IEEE80211_IS_CHAN_HT40PLUS_CAPABLE(ic->ic_curchan)) { + chan_offset = 20; + } else if (IEEE80211_IS_CHAN_HT40MINUS_CAPABLE(ic->ic_curchan)) { + chan_offset = -20; + } else { + return NULL; + } + + return(ic->ic_find_channel(ic, ic->ic_curchan->ic_freq + chan_offset, IEEE80211_CHAN_11NA_HT20)); +} + +/* + * Finds the radar state entry that matches the current channel + */ +struct dfs_state * +dfs_getchanstate(struct ath_dfs *dfs, u_int8_t *index, int ext_chan_flag) +{ + struct dfs_state *rs=NULL; + int i; + struct ieee80211_channel *cmp_ch; + + if (dfs == NULL) { + printk("%s[%d]: sc_dfs is NULL\n",__func__,__LINE__); + // DFS_DPRINTK(dfs, ATH_DEBUG_DFS,"%s: sc_dfs is NULL\n",__func__); + return NULL; + } + + if (ext_chan_flag) { + cmp_ch = ieee80211_get_extchan(dfs->ic); + if (cmp_ch) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "Extension channel freq = %u flags=0x%x\n", cmp_ch->ic_freq, cmp_ch->ic_flagext); + } else { + return NULL; + } + + } else { + cmp_ch = dfs->ic->ic_curchan; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "Primary channel freq = %u flags=0x%x\n", cmp_ch->ic_freq, cmp_ch->ic_flagext); + } + for (i=0;idfs_radar[i].rs_chan.ic_freq== cmp_ch->ic_freq) && + (dfs->dfs_radar[i].rs_chan.ic_flags == cmp_ch->ic_flags)) { + if (index != NULL) + *index = (u_int8_t) i; + + return &(dfs->dfs_radar[i]); + } + } + /* No existing channel found, look for first free channel state entry */ + for (i=0; idfs_radar[i].rs_chan.ic_freq == 0) { + rs = &(dfs->dfs_radar[i]); + /* Found one, set channel info and default thresholds */ + rs->rs_chan = *cmp_ch; + + /* Copy the parameters from the default set */ + ath_dfs_phyerr_param_copy(&rs->rs_param, + &dfs->dfs_defaultparams); + + if (index != NULL) + *index = (u_int8_t) i; + return (rs); + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: No more radar states left.\n", __func__); + return(NULL); +} + + + +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_nol.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_nol.c new file mode 100644 index 000000000000..d907cecf02f9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_nol.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_nol.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifndef UNINET +/*TO DO DFS +#include +*/ +#endif +#if defined(ATH_SUPPORT_DFS) && !defined(ATH_DFS_RADAR_DETECTION_ONLY) +#include "dfs_ioctl.h" +#include "dfs_ioctl_private.h" +#include "adf_os_time.h" /* adf_os_time_t, adf_os_time_after */ + +static void +dfs_nol_delete(struct ath_dfs *dfs, u_int16_t delfreq, u_int16_t delchwidth); + +static +OS_TIMER_FUNC(dfs_remove_from_nol) +{ + struct dfs_nol_timer_arg *nol_arg; + struct ath_dfs *dfs; + struct ieee80211com *ic; + u_int16_t delfreq; + u_int16_t delchwidth; + + OS_GET_TIMER_ARG(nol_arg, struct dfs_nol_timer_arg *); + + dfs = nol_arg->dfs; + ic = dfs->ic; + delfreq = nol_arg->delfreq; + delchwidth = nol_arg->delchwidth; + + /* Only operate in HOSTAP/IBSS */ + if (ic->ic_opmode != IEEE80211_M_HOSTAP && + ic->ic_opmode != IEEE80211_M_IBSS) + goto done; + + /* Delete the given NOL entry */ + dfs_nol_delete(dfs, delfreq, delchwidth); + + /* Update the wireless stack with the new NOL */ + dfs_nol_update(dfs); + +done: + OS_FREE(nol_arg); + return; +} + +void +dfs_print_nol(struct ath_dfs *dfs) +{ + struct dfs_nolelem *nol; + uint32_t diff_ms, remaining_sec; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL", __func__); + return; + } + nol = dfs->dfs_nol; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: NOL", __func__); + while (nol != NULL) { + diff_ms = adf_os_ticks_to_msecs(adf_os_ticks() - nol->nol_start_ticks); + diff_ms = (nol->nol_timeout_ms - diff_ms); + remaining_sec = diff_ms / 1000; /* convert to seconds */ + nol = nol->nol_next; + } +} + + +void +dfs_get_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, + int *nchan) +{ + struct dfs_nolelem *nol; + + *nchan = 0; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL", __func__); + return; + } + + nol = dfs->dfs_nol; + while (nol != NULL) { + dfs_nol[*nchan].nol_freq = nol->nol_freq; + dfs_nol[*nchan].nol_chwidth = nol->nol_chwidth; + dfs_nol[*nchan].nol_start_ticks = nol->nol_start_ticks; + dfs_nol[*nchan].nol_timeout_ms = nol->nol_timeout_ms; + ++(*nchan); + nol = nol->nol_next; + } +} + + +void +dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) +{ +#define TIME_IN_MS 1000 + u_int32_t nol_time_left_ms; + struct ieee80211_channel chan; + int i; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL", __func__); + return; + } + + for (i = 0; i < nchan; i++) + { + nol_time_left_ms = adf_os_ticks_to_msecs(adf_os_ticks() - dfs_nol[i].nol_start_ticks); + if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) { + chan.ic_freq = dfs_nol[i].nol_freq; + chan.ic_flags= 0; + chan.ic_flagext = 0; + nol_time_left_ms = (dfs_nol[i].nol_timeout_ms - nol_time_left_ms); + dfs_nol_addchan(dfs, &chan, (nol_time_left_ms / TIME_IN_MS)); + } + } +#undef TIME_IN_MS + dfs_nol_update(dfs); +} + + +void +dfs_nol_addchan(struct ath_dfs *dfs, struct ieee80211_channel *chan, + u_int32_t dfs_nol_timeout) +{ +#define TIME_IN_MS 1000 +#define TIME_IN_US (TIME_IN_MS * 1000) + struct dfs_nolelem *nol, *elem, *prev; + struct dfs_nol_timer_arg *dfs_nol_arg; + /* XXX for now, assume all events are 20MHz wide */ + int ch_width = 20; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL", __func__); + return; + } + nol = dfs->dfs_nol; + prev = dfs->dfs_nol; + elem = NULL; + while (nol != NULL) { + if ((nol->nol_freq == chan->ic_freq) && + (nol->nol_chwidth == ch_width)) { + nol->nol_start_ticks = adf_os_ticks(); + nol->nol_timeout_ms = dfs_nol_timeout*TIME_IN_MS; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s: Update OS Ticks for NOL %d MHz / %d MHz", + __func__, nol->nol_freq, nol->nol_chwidth); + OS_CANCEL_TIMER(&nol->nol_timer); + OS_SET_TIMER(&nol->nol_timer, dfs_nol_timeout*TIME_IN_MS); + return; + } + prev = nol; + nol = nol->nol_next; + } + /* Add a new element to the NOL*/ + elem = (struct dfs_nolelem *)OS_MALLOC(NULL, sizeof(struct dfs_nolelem),GFP_ATOMIC); + if (elem == NULL) { + goto bad; + } + dfs_nol_arg = (struct dfs_nol_timer_arg *)OS_MALLOC(NULL, + sizeof(struct dfs_nol_timer_arg), GFP_ATOMIC); + if (dfs_nol_arg == NULL) { + OS_FREE(elem); + goto bad; + } + elem->nol_freq = chan->ic_freq; + elem->nol_chwidth = ch_width; + elem->nol_start_ticks = adf_os_ticks(); + elem->nol_timeout_ms = dfs_nol_timeout*TIME_IN_MS; + elem->nol_next = NULL; + if (prev) { + prev->nol_next = elem; + } else { + /* This is the first element in the NOL */ + dfs->dfs_nol = elem; + } + dfs_nol_arg->dfs = dfs; + dfs_nol_arg->delfreq = elem->nol_freq; + dfs_nol_arg->delchwidth = elem->nol_chwidth; + + OS_INIT_TIMER(NULL, &elem->nol_timer, dfs_remove_from_nol, + dfs_nol_arg, ADF_DEFERRABLE_TIMER); + OS_SET_TIMER(&elem->nol_timer, dfs_nol_timeout*TIME_IN_MS); + + /* Update the NOL counter */ + dfs->dfs_nol_count++; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s: new NOL channel %d MHz / %d MHz", + __func__, + elem->nol_freq, + elem->nol_chwidth); + return; + +bad: + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL | ATH_DEBUG_DFS, + "%s: failed to allocate memory for nol entry", __func__); + +#undef TIME_IN_MS +#undef TIME_IN_US +} + +/* + * Delete the given frequency/chwidth from the NOL. + */ +static void +dfs_nol_delete(struct ath_dfs *dfs, u_int16_t delfreq, u_int16_t delchwidth) +{ + struct dfs_nolelem *nol,**prev_next; + + if (dfs == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL", __func__); + return; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s: remove channel=%d/%d MHz from NOL", + __func__, + delfreq, delchwidth); + prev_next = &(dfs->dfs_nol); + nol = dfs->dfs_nol; + while (nol != NULL) { + if (nol->nol_freq == delfreq && nol->nol_chwidth == delchwidth) { + *prev_next = nol->nol_next; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, + "%s removing channel %d/%dMHz from NOL tstamp=%d", + __func__, nol->nol_freq, nol->nol_chwidth, + (adf_os_ticks_to_msecs(adf_os_ticks()) / 1000)); + OS_CANCEL_TIMER(&nol->nol_timer); + OS_FREE(nol); + nol = NULL; + nol = *prev_next; + + /* Update the NOL counter */ + dfs->dfs_nol_count--; + + /* Be paranoid! */ + if (dfs->dfs_nol_count < 0) { + DFS_PRINTK("%s: dfs_nol_count < 0; eek!", __func__); + dfs->dfs_nol_count = 0; + } + + } else { + prev_next = &(nol->nol_next); + nol = nol->nol_next; + } + } +} + +/* + * Notify the driver/umac that it should update the channel radar/NOL + * flags based on the current NOL list. + */ +void +dfs_nol_update(struct ath_dfs *dfs) +{ + struct ieee80211com *ic = dfs->ic; + struct dfs_nol_chan_entry *dfs_nol; + struct dfs_nolelem *nol; + int nlen; + + /* + * Allocate enough entries to store the NOL. + * + * At least on Linux (don't ask why), if you allocate a 0 entry + * array, the returned pointer is 0x10. Make sure you're + * aware of this when you start debugging. + */ + dfs_nol = (struct dfs_nol_chan_entry *)OS_MALLOC(NULL, + sizeof(struct dfs_nol_chan_entry) * dfs->dfs_nol_count, + GFP_ATOMIC); + + if (dfs_nol == NULL) { + /* + * XXX TODO: if this fails, just schedule a task to retry + * updating the NOL at a later stage. That way the NOL + * update _DOES_ happen - hopefully the failure was just + * temporary. + */ + DFS_PRINTK("%s: failed to allocate NOL update memory!", + __func__); + return; + } + + + /* populate the nol array */ + nlen = 0; + + nol = dfs->dfs_nol; + while (nol != NULL && nlen < dfs->dfs_nol_count) { + dfs_nol[nlen].nol_chfreq = nol->nol_freq; + dfs_nol[nlen].nol_chwidth = nol->nol_chwidth; + dfs_nol[nlen].nol_start_ticks = nol->nol_start_ticks; + dfs_nol[nlen].nol_timeout_ms = nol->nol_timeout_ms; + nlen++; + nol = nol->nol_next; + } + + /* Be suitably paranoid for now */ + if (nlen != dfs->dfs_nol_count) + DFS_PRINTK("%s: nlen (%d) != dfs->dfs_nol_count (%d)!", + __func__, nlen, dfs->dfs_nol_count); + + /* + * Call the driver layer to have it recalculate the NOL flags for + * each driver/umac channel. + * + * If the list is empty, pass NULL instead of dfs_nol. + * + * The operating system may have some special representation for + * "malloc a 0 byte memory region" - for example, + * Linux 2.6.38-13 (ubuntu) returns 0x10 rather than a valid + * allocation (and is likely not NULL so the pointer doesn't + * match NULL checks in any later code. + */ + ic->ic_dfs_clist_update(ic, DFS_NOL_CLIST_CMD_UPDATE, + (nlen > 0) ? dfs_nol : NULL, nlen); + + /* + * .. and we're done. + */ + OS_FREE(dfs_nol); +} + +void dfs_nol_timer_cleanup(struct ath_dfs *dfs) +{ + struct dfs_nolelem *nol = dfs->dfs_nol, *prev; + + /* First Cancel timer */ + while (nol) { + OS_CANCEL_TIMER(&nol->nol_timer); + nol = nol->nol_next; + } + /* Free NOL elem, don't mix this while loop with above loop */ + nol = dfs->dfs_nol; + while (nol) { + prev = nol; + nol = nol->nol_next; + OS_FREE(prev); + } + return; +} +#endif /* defined(ATH_SUPPORT_DFS) && !defined(ATH_DFS_RADAR_DETECTION_ONLY) */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr.h new file mode 100644 index 000000000000..43423f6de40d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_phyerr.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + +#ifndef __DFS_PHYERR_H__ +#define __DFS_PHYERR_H__ + +extern int +dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, + u_int64_t fulltsf, struct dfs_phy_err *e, + bool enable_log); + +#endif /* __DFS_PHYERR_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c new file mode 100644 index 000000000000..a637484dda71 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.c @@ -0,0 +1,745 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_phyerr_tlv.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include +*/ +/* TO DO DFS +#include +*/ +#include "dfs_phyerr.h" +#include "dfs_phyerr_tlv.h" + +/* + * Parsed radar status + */ +struct rx_radar_status { + uint32_t raw_tsf; + uint32_t tsf_offset; + int rssi; + int pulse_duration; + int is_chirp:1; + int delta_peak; + int delta_diff; + int sidx; + int freq_offset; /* in KHz */ +}; + + +struct rx_search_fft_report { + uint32_t total_gain_db; + uint32_t base_pwr_db; + int fft_chn_idx; + int peak_sidx; + int relpwr_db; + int avgpwr_db; + int peak_mag; + int num_str_bins_ib; +}; + + +/* + * XXX until "fastclk" is stored in the DFS configuration.. + */ +#define PERE_IS_OVERSAMPLING(_dfs) (1) + +/* + * XXX there _has_ to be a better way of doing this! + * -adrian + */ +static int32_t +sign_extend_32(uint32_t v, int nb) +{ + uint32_t m = 1U << (nb - 1); + + /* Chop off high bits, just in case */ + v &= v & ((1U << nb) - 1); + + /* Extend */ + return (v ^ m) - m; +} + +/* + * Calculate the frequency offset from the given signed bin index + * from the radar summary report. + * + * This takes the oversampling mode into account. + * + * For oversampling, each bin has resolution 44MHz/128. + * For non-oversampling, each bin has resolution 40MHz/128. + * + * It returns kHz - ie, 1000th's of MHz. + */ +static int +calc_freq_offset(int sindex, int is_oversampling) +{ + + if (is_oversampling) + return (sindex * (44000 / 128)); + else + return (sindex * (40000 / 128)); +} + +static void +radar_summary_print(struct ath_dfs *dfs, + struct rx_radar_status *rsu, + bool enable_log) +{ + if (!enable_log) + return; + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + " \n ############ Radar Summary ############ \n"); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - pulsedur = %d\n", + __func__, rsu->pulse_duration); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - rssi = %d\n", + __func__, rsu->rssi); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - ischirp = %d\n", + __func__, rsu->is_chirp); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - sidx = %d\n", + __func__, rsu->sidx); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - delta_peak = %d\n", + __func__, rsu->delta_peak); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - delta_diff = %d\n", + __func__, rsu->delta_diff); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - raw tsf = %d\n", + __func__, rsu->raw_tsf); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - tsf_offset = %d\n", + __func__, rsu->tsf_offset); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: Radar Summary - cooked tsf = %d \n", + __func__, (rsu->raw_tsf - rsu->tsf_offset)); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: frequency offset = %d.%d MHz (oversampling = %d) \n", + __func__, (int) (rsu->freq_offset / 1000), + (int) abs(rsu->freq_offset % 1000), PERE_IS_OVERSAMPLING(dfs)); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n ################################### \n"); +} + +/* + * Parse the radar summary frame. + * + * The frame contents _minus_ the TLV are passed in. + */ +static void +radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, + struct rx_radar_status *rsu) +{ + uint32_t rs[2]; + int freq_centre, freq; + + /* Drop out if we have < 2 DWORDs available */ + if (len < sizeof(rs)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | + ATH_DEBUG_DFS_PHYERR_SUM, + "%s: len (%zu) < expected (%zu)!", + __func__, + len, + sizeof(rs)); + } + + /* + * Since the TLVs may be unaligned for some reason + * we take a private copy into aligned memory. + * This enables us to use the HAL-like accessor macros + * into the DWORDs to access sub-DWORD fields. + */ + OS_MEMCPY(rs, buf, sizeof(rs)); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x", __func__, rs[0], rs[1]); +// DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):", __func__, buf); + + /* Populate the fields from the summary report */ + rsu->tsf_offset = + MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_TSF_OFFSET); + rsu->pulse_duration = + MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_DUR); + rsu->is_chirp = + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_IS_CHIRP); + rsu->sidx = sign_extend_32( + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_SIDX), + 10); + rsu->freq_offset = + calc_freq_offset(rsu->sidx, PERE_IS_OVERSAMPLING(dfs)); + + /* These are only relevant if the pulse is a chirp */ + rsu->delta_peak = sign_extend_32( + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_PEAK), + 6); + rsu->delta_diff = + MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_DIFF); + + /* WAR for FCC Type 4*/ + /* + * HW is giving longer pulse duration (in case of VHT80, with traffic) + * which fails to detect FCC type4 radar pulses. Added a work around to + * fix the pulse duration and duration delta. + * + * IF VHT80 + * && (primary_channel==30MHz || primary_channel== -30MHz) + * && -4 <= pulse_index <= 4 + * && !chirp + * && pulse duration > 20 us + * THEN + * Set pulse duration to 20 us + */ + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + freq = ieee80211_chan2freq(dfs->ic, dfs->ic->ic_curchan); + freq_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; + + if ((IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan) && + (abs(freq - freq_centre) == 30) && + !rsu->is_chirp && + abs(rsu->sidx) <= 4 && + rsu->pulse_duration > 20)){ + rsu->pulse_duration = 20; + } + + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); +} + +static void +radar_fft_search_report_parse(struct ath_dfs *dfs, const char *buf, size_t len, + struct rx_search_fft_report *rsfr) +{ + uint32_t rs[2]; + + /* Drop out if we have < 2 DWORDs available */ + if (len < sizeof(rs)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | + ATH_DEBUG_DFS_PHYERR_SUM, + "%s: len (%zu) < expected (%zu)!", + __func__, + len, + sizeof(rs)); + } + + /* + * Since the TLVs may be unaligned for some reason + * we take a private copy into aligned memory. + * This enables us to use the HAL-like accessor macros + * into the DWORDs to access sub-DWORD fields. + */ + OS_MEMCPY(rs, buf, sizeof(rs)); + rsfr->total_gain_db = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_TOTAL_GAIN_DB); + rsfr->base_pwr_db = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_BASE_PWR_DB); + rsfr->fft_chn_idx = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_FFT_CHN_IDX); + rsfr->peak_sidx = sign_extend_32(MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_PEAK_SIDX), 12); + rsfr->relpwr_db = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_RELPWR_DB); + rsfr->avgpwr_db = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_AVGPWR_DB); + rsfr->peak_mag = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_PEAK_MAG); + rsfr->num_str_bins_ib = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_NUM_STR_BINS_IB); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x", __func__, rs[0], rs[1]); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->total_gain_db = %d", __func__, rsfr->total_gain_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->base_pwr_db = %d", __func__, rsfr->base_pwr_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->fft_chn_idx = %d", __func__, rsfr->fft_chn_idx); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->peak_sidx = %d", __func__, rsfr->peak_sidx); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->relpwr_db = %d", __func__, rsfr->relpwr_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->avgpwr_db = %d", __func__, rsfr->avgpwr_db); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->peak_mag = %d", __func__, rsfr->peak_mag); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->num_str_bins_ib = %d", __func__, rsfr->num_str_bins_ib); +} + +/* + * Parse a Peregrine BB TLV frame. + * + * This routine parses each TLV, prints out what's going on and + * calls an appropriate sub-function. + * + * Since the TLV format doesn't _specify_ all TLV components are + * DWORD aligned, we must treat them as not and access the fields + * appropriately. + */ +static int +tlv_parse_frame(struct ath_dfs *dfs, struct rx_radar_status *rs, + struct rx_search_fft_report *rsfr, const char *buf, size_t len, u_int8_t rssi) +{ + int i = 0; + uint32_t tlv_hdr[1]; + bool first_tlv = true; + bool false_detect = false; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: total length = %zu bytes", __func__, len); + while ((i < len ) && (false_detect == false)) { + /* Ensure we at least have four bytes */ + if ((len - i) < sizeof(tlv_hdr)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | + ATH_DEBUG_DFS_PHYERR_SUM, + "%s: ran out of bytes, len=%zu, i=%d", + __func__, len, i); + return (0); + } + + /* + * Copy the offset into the header, + * so the DWORD style access macros + * can be used. + */ + OS_MEMCPY(&tlv_hdr, buf + i, sizeof(tlv_hdr)); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: HDR: TLV SIG=0x%x, TAG=0x%x, LEN=%d bytes", + __func__, + MS(tlv_hdr[TLV_REG], TLV_SIG), + MS(tlv_hdr[TLV_REG], TLV_TAG), + MS(tlv_hdr[TLV_REG], TLV_LEN)); + + /* + * Sanity check the length field is available in + * the remaining frame. Drop out if this isn't + * the case - we can't trust the rest of the TLV + * entries. + */ + if (MS(tlv_hdr[TLV_REG], TLV_LEN) + i >= len) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: TLV oversize: TLV LEN=%d, available=%zu, " + "i=%d", + __func__, + MS(tlv_hdr[TLV_REG], TLV_LEN), + len, + i); + break; + } + + /* Skip the TLV header - one DWORD */ + i += sizeof(tlv_hdr); + + /* Handle the payload */ + /* XXX TODO! */ + switch (MS(tlv_hdr[TLV_REG], TLV_SIG)) { + case TAG_ID_RADAR_PULSE_SUMMARY: /* Radar pulse summary */ + /* XXX TODO verify return value */ + /* XXX TODO validate only seeing one of these */ + radar_summary_parse(dfs, buf + i, + MS(tlv_hdr[TLV_REG], TLV_LEN), rs); + break; + case TAG_ID_SEARCH_FFT_REPORT: + radar_fft_search_report_parse(dfs, buf + i, + MS(tlv_hdr[TLV_REG], TLV_LEN), rsfr); + /* + we examine search FFT report and make the following assumption + as per algorithms group's input: + (1) There may be multiple TLV + (2) We make false detection decison solely based on the first TLV + (3) If the first TLV is a serch FFT report then we check the peak_mag value. + When RSSI is equal to dfs->ath_dfs_false_rssI_thres (default 50) + and peak_mag is less than 2 * dfs->ath_dfs_peak_mag (default 40) + we treat it as false detect. + Please note that 50 is not a true RSSI estimate, but value indicated + by HW for RF saturation event. + */ + + if ((first_tlv == true) && + (rssi == dfs->ath_dfs_false_rssi_thres) && + (rsfr->peak_mag < (2 * dfs->ath_dfs_peak_mag))) { + false_detect = true; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s: setting false_detect to TRUE", __func__); + } + + break; + default: + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: unknown entry, SIG=0x%02x", + __func__, + MS(tlv_hdr[TLV_REG], TLV_SIG)); + } + + /* Skip the payload */ + i += MS(tlv_hdr[TLV_REG], TLV_LEN); + first_tlv = false; + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s: done", __func__); + + return (false_detect? 0 : 1); +} + +/* + * Calculate the channel centre in MHz. + */ +static int +tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) +{ + uint32_t chan_centre; + uint32_t chan_width; + int chan_offset; + + /* + * For now, just handle up to VHT80 correctly. + */ + if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) { + DFS_PRINTK("%s: dfs->ic=%p, that or curchan is null?", + __func__, dfs->ic); + return (0); + } + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + /* + * For now, the only 11ac channel with freq1/freq2 setup is + * VHT80. + * + * XXX should have a flag macro to check this! + */ + if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { + /* 11AC, so cfreq1/cfreq2 are setup */ + + /* + * XXX if it's 80+80 this won't work - need to use seg + * appropriately! + */ + + chan_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; + } else { + /* HT20/HT40 */ + + /* + * XXX this is hard-coded - it should be 5 or 10 for + * half/quarter appropriately. + */ + chan_width = 20; + + /* Grab default channel centre */ + chan_centre = ieee80211_chan2freq(dfs->ic, + dfs->ic->ic_curchan); + + /* Calculate offset based on HT40U/HT40D and VHT40U/VHT40D */ + if (IEEE80211_IS_CHAN_11N_HT40PLUS(dfs->ic->ic_curchan) || + dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40PLUS) + chan_offset = chan_width; + else if (IEEE80211_IS_CHAN_11N_HT40MINUS(dfs->ic->ic_curchan) || + dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40MINUS) + chan_offset = -chan_width; + else + chan_offset = 0; + + /* Calculate new _real_ channel centre */ + chan_centre += (chan_offset / 2); + } + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + + /* + * XXX half/quarter rate support! + */ + + /* Return ev_chan_centre in MHz */ + return (chan_centre); +} + +/* + * Calculate the centre frequency and low/high range for a radar pulse event. + * + * XXX TODO: Handle half/quarter rates correctly! + * XXX TODO: handle VHT160 correctly! + * XXX TODO: handle VHT80+80 correctly! + */ +static int +tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, + uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) +{ + int chan_width; + int chan_centre; + + /* Fetch the channel centre frequency in MHz */ + chan_centre = tlv_calc_freq_info(dfs, rs); + + /* Convert to KHz */ + chan_centre *= 1000; + + /* + * XXX hard-code event width to be 2 * bin size for now; + * XXX this needs to take into account the core clock speed + * XXX for half/quarter rate mode. + */ + if (PERE_IS_OVERSAMPLING(dfs)) + chan_width = (44000 * 2 / 128); + else + chan_width = (40000 * 2 / 128); + + /* XXX adjust chan_width for half/quarter rate! */ + + /* + * Now we can do the math to figure out the correct channel range. + */ + (*freq_centre) = (uint32_t) (chan_centre + rs->freq_offset); + (*freq_lo) = (uint32_t) ((chan_centre + rs->freq_offset) + - chan_width); + (*freq_hi) = (uint32_t) ((chan_centre + rs->freq_offset) + + chan_width); + + return (1); +} + +/* + * The chirp bandwidth in KHz is defined as: + * + * totalBW(KHz) = delta_peak(mean) + * * [ (bin resolution in KHz) / (radar_fft_long_period in uS) ] + * * pulse_duration (us) + * + * The bin resolution depends upon oversampling. + * + * For now, we treat the radar_fft_long_period as a hard-coded 8uS. + */ +static int +tlv_calc_event_freq_chirp(struct ath_dfs *dfs, struct rx_radar_status *rs, + uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) +{ + int32_t bin_resolution; /* KHz * 100 */ + int32_t radar_fft_long_period = 8; /* microseconds */ + int32_t delta_peak; + int32_t pulse_duration; + int32_t total_bw; + int32_t chan_centre; + int32_t freq_1, freq_2; + + /* + * KHz isn't enough resolution here! + * So treat it as deci-hertz (10Hz) and convert back to KHz + * later. + */ + if (PERE_IS_OVERSAMPLING(dfs)) + bin_resolution = (44000 * 100) / 128; + else + bin_resolution = (40000 * 100) / 128; + + delta_peak = rs->delta_peak; + pulse_duration = rs->pulse_duration; + + total_bw = delta_peak * (bin_resolution / radar_fft_long_period) * + pulse_duration; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | ATH_DEBUG_DFS_PHYERR_SUM, + "%s: delta_peak=%d, pulse_duration=%d, bin_resolution=%d.%dKHz, " + "radar_fft_long_period=%d, total_bw=%d.%ldKHz", + __func__, + delta_peak, + pulse_duration, + bin_resolution / 1000, + bin_resolution % 1000, + radar_fft_long_period, + total_bw / 100, + abs(total_bw % 100)); + + total_bw /= 100; /* back to KHz */ + + /* Grab the channel centre frequency in MHz */ + chan_centre = tlv_calc_freq_info(dfs, rs); + + /* Early abort! */ + if (chan_centre == 0) { + (*freq_centre) = 0; + return (0); + } + + /* Convert to KHz */ + chan_centre *= 1000; + + /* + * sidx is the starting frequency; total_bw is a signed value and + * for negative chirps (ie, moving down in frequency rather than up) + * the end frequency may be less than the start frequency. + */ + if (total_bw > 0) { + freq_1 = chan_centre + rs->freq_offset; + freq_2 = chan_centre + rs->freq_offset + total_bw; + } else { + freq_1 = chan_centre + rs->freq_offset + total_bw; + freq_2 = chan_centre + rs->freq_offset; + } + + (*freq_lo) = (uint32_t)(freq_1); + (*freq_hi) = (uint32_t)(freq_2); + (*freq_centre) = (uint32_t) (freq_1 + (abs(total_bw) / 2)); + + return (1); +} + +/* + * Calculate the centre and band edge frequencies of the given radar + * event. + */ +static int +tlv_calc_event_freq(struct ath_dfs *dfs, struct rx_radar_status *rs, + uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) +{ + if (rs->is_chirp) + return tlv_calc_event_freq_chirp(dfs, rs, freq_centre, + freq_lo, freq_hi); + else + return tlv_calc_event_freq_pulse(dfs, rs, freq_centre, + freq_lo, freq_hi); +} + +/* + * This is the public facing function which parses the PHY error + * and populates the dfs_phy_err struct. + */ +int +dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, + u_int64_t fulltsf, struct dfs_phy_err *e, + bool enable_log) +{ + struct rx_radar_status rs; + struct rx_search_fft_report rsfr; + static int invalid_phyerr_count = 0; + + OS_MEMZERO(&rs, sizeof(rs)); + + /* + * Add the ppdu_start/ppdu_end fields given to us by the upper + * layers. The firmware gives us a summary set of parameters rather + * than the whole PPDU_START/PPDU_END descriptor contenst. + */ + rs.rssi = rssi; + rs.raw_tsf = rs_tstamp; + /* + * Try parsing the TLV set. + */ + if (! tlv_parse_frame(dfs, &rs, &rsfr, buf, datalen, rssi)){ + invalid_phyerr_count++; + /* + * Print only at every 2 power times + * to avoid flushing of the kernel + * logs, since the frequency of + * invalid phyerrors is very high + * in noisy environments. + */ + if ( !(invalid_phyerr_count & 0xFF) ) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_DEBUG, + "%s[%d]:DFS-tlv parse failed invalid phyerror count = %d", + __func__,__LINE__, invalid_phyerr_count); + } + return (0); + } + /* For debugging, print what we have parsed */ + radar_summary_print(dfs, &rs, enable_log); + + /* Populate dfs_phy_err from rs */ + OS_MEMSET(e, 0, sizeof(*e)); + e->rssi = rs.rssi; + e->dur = rs.pulse_duration; + e->sidx = rs.sidx; + e->is_pri = 1; /* XXX always PRI for now */ + e->is_ext = 0; + e->is_dc = 0; + e->is_early = 0; + /* + * XXX TODO: add a "chirp detection enabled" capability or config + * bit somewhere, in case for some reason the hardware chirp + * detection AND FFTs are disabled. + */ + /* For now, assume this hardware always does chirp detection */ + e->do_check_chirp = 1; + e->is_hw_chirp = !! (rs.is_chirp); + e->is_sw_chirp = 0; /* We don't yet do software chirp checking */ + + e->fulltsf = fulltsf; + e->rs_tstamp = rs.raw_tsf - rs.tsf_offset; + + /* XXX error check */ + (void) tlv_calc_event_freq(dfs, &rs, &e->freq, &e->freq_lo, + &e->freq_hi); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, + "%s: fbin=%d, freq=%d.%d MHz, raw tsf=%u, offset=%d, " + "cooked tsf=%u, rssi=%d, dur=%d, is_chirp=%d, fulltsf=%llu, " + "freq=%d.%d MHz, freq_lo=%d.%dMHz, freq_hi=%d.%d MHz", + __func__, + rs.sidx, + (int) (rs.freq_offset / 1000), + (int) abs(rs.freq_offset % 1000), + rs.raw_tsf, + rs.tsf_offset, + e->rs_tstamp, + rs.rssi, + rs.pulse_duration, + (int) rs.is_chirp, + (unsigned long long) fulltsf, + (int) e->freq / 1000, + (int) abs(e->freq) % 1000, + (int) e->freq_lo / 1000, + (int) abs(e->freq_lo) % 1000, + (int) e->freq_hi / 1000, + (int) abs(e->freq_hi) % 1000); + + return (1); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h new file mode 100644 index 000000000000..ca90fa5cc395 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_phyerr_tlv.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_phyerr_tlv.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ +#ifndef __DFS_PHYERR_PEREGRINE_H__ +#define __DFS_PHYERR_PEREGRINE_H__ + +/* + * Register manipulation macros that expect bit field defines + * to follow the convention that an _S suffix is appended for + * a shift count, while the field mask has no suffix. + */ +#define SM(_v, _f) (((_v) << _f##_S) & _f) +#define MS(_v, _f) (((_v) & _f) >> _f##_S) + +/* + * The TLV dword is at the beginning of each TLV section. + */ +#define TLV_REG 0x00 + +#define TLV_LEN 0x0000FFFF +#define TLV_LEN_S 0 + +#define TLV_SIG 0x00FF0000 +#define TLV_SIG_S 16 + +#define TLV_TAG 0xFF000000 +#define TLV_TAG_S 24 + +#define TAG_ID_SEARCH_FFT_REPORT 0xFB +#define TAG_ID_RADAR_PULSE_SUMMARY 0xF8 +/* + * Radar pulse summary + * + * + TYPE=0xF8 (Radar pulse summary reprot) + * + SIG=0xBB (baseband PHY generated TLV components) + */ + +#define RADAR_REPORT_PULSE_REG_1 0x00 + +#define RADAR_REPORT_PULSE_IS_CHIRP 0x80000000 +#define RADAR_REPORT_PULSE_IS_CHIRP_S 31 + +#define RADAR_REPORT_PULSE_IS_MAX_WIDTH 0x40000000 +#define RADAR_REPORT_PULSE_IS_MAX_WIDTH_S 30 + +#define RADAR_REPORT_AGC_TOTAL_GAIN 0x3FF00000 +#define RADAR_REPORT_AGC_TOTAL_GAIN_S 20 + +#define RADAR_REPORT_PULSE_DELTA_DIFF 0x000F0000 +#define RADAR_REPORT_PULSE_DELTA_DIFF_S 16 + +#define RADAR_REPORT_PULSE_DELTA_PEAK 0x0000FC00 +#define RADAR_REPORT_PULSE_DELTA_PEAK_S 10 + +#define RADAR_REPORT_PULSE_SIDX 0x000003FF +#define RADAR_REPORT_PULSE_SIDX_S 0x0 + +#define RADAR_REPORT_PULSE_REG_2 0x01 + +#define RADAR_REPORT_PULSE_SRCH_FFT_A_VALID 0x80000000 +#define RADAR_REPORT_PULSE_SRCH_FFT_A_VALID_S 31 + +#define RADAR_REPORT_PULSE_AGC_MB_GAIN 0x7F000000 +#define RADAR_REPORT_PULSE_AGC_MB_GAIN_S 24 + +#define RADAR_REPORT_PULSE_SUBCHAN_MASK 0x00FF0000 +#define RADAR_REPORT_PULSE_SUBCHAN_MASK_S 16 + +#define RADAR_REPORT_PULSE_TSF_OFFSET 0x0000FF00 +#define RADAR_REPORT_PULSE_TSF_OFFSET_S 8 + +#define RADAR_REPORT_PULSE_DUR 0x000000FF +#define RADAR_REPORT_PULSE_DUR_S 0 + +#define SEARCH_FFT_REPORT_REG_1 0x00 + + +#define SEARCH_FFT_REPORT_TOTAL_GAIN_DB 0xFF800000 +#define SEARCH_FFT_REPORT_TOTAL_GAIN_DB_S 23 + +#define SEARCH_FFT_REPORT_BASE_PWR_DB 0x007FC000 +#define SEARCH_FFT_REPORT_BASE_PWR_DB_S 14 + +#define SEARCH_FFT_REPORT_FFT_CHN_IDX 0x00003000 +#define SEARCH_FFT_REPORT_FFT_CHN_IDX_S 12 + +#define SEARCH_FFT_REPORT_PEAK_SIDX 0x00000FFF +#define SEARCH_FFT_REPORT_PEAK_SIDX_S 0 + +#define SEARCH_FFT_REPORT_REG_2 0x01 + +#define SEARCH_FFT_REPORT_RELPWR_DB 0xFC000000 +#define SEARCH_FFT_REPORT_RELPWR_DB_S 26 + +#define SEARCH_FFT_REPORT_AVGPWR_DB 0x03FC0000 +#define SEARCH_FFT_REPORT_AVGPWR_DB_S 18 + +#define SEARCH_FFT_REPORT_PEAK_MAG 0x0003FF00 +#define SEARCH_FFT_REPORT_PEAK_MAG_S 8 + +#define SEARCH_FFT_REPORT_NUM_STR_BINS_IB 0x000000FF +#define SEARCH_FFT_REPORT_NUM_STR_BINS_IB_S 0 + + + +/* + * Although this code is now not parsing the whole frame (descriptor + * and all), the relevant fields are still useful information + * for anyone who is working on the PHY error part of DFS pattern + * matching. + * + * However, to understand _where_ these descriptors start, you + * should do some digging into the peregrine descriptor format. + * The 30 second version: each RX ring has a bitmap listing which + * descriptors are to be included, and then a set of offsets + * into the RX buffer for where each descriptor will be written. + * It's not like the 802.11n generation hardware which has + * a fixed descriptor format. + */ + +/* + * RX_PPDU_START + */ +#define RX_PPDU_START_LEN (10*4) + +#define RX_PPDU_START_REG_4 0x0004 +#define RX_PPDU_START_RSSI_COMB 0x000000FF +#define RX_PPDU_START_RSSI_COMB_S 0 + +/* + * RX_PPDU_END + */ +#define RX_PPDU_END_LEN (21*4) + +#define RX_PPDU_END_REG_16 16 +#define RX_PPDU_END_TSF_TIMESTAMP 0xFFFFFFFF +#define RX_PPDU_END_TSF_TIMESTAMP_S 0 + +#define RX_PPDU_END_REG_18 18 +#define RX_PPDU_END_PHY_ERR_CODE 0x0000FF00 +#define RX_PPDU_END_PHY_ERR_CODE_S 8 +#define RX_PPDU_END_PHY_ERR 0x00010000 +#define RX_PPDU_END_PHY_ERR_S 16 + +/* + * The RSSI values can have "special meanings". + * + * If rssi=50, it means that the peak detector triggered. + */ +#define RSSI_PEAK_DETECTOR_SAT 50 + +/* + * + * If rssi=25, it means that the ADC was saturated, but that only is + * valid when there is one ADC gain change. For short pulses this + * is true - you won't have time to do a gain change before the pulse + * goes away. But for longer pulses, ADC gain changes can occur, so + * you'll get a more accurate RSSI figure. + * + * For short pulses (and the definition of "short" still isn't clear + * at the time of writing) there isn't any real time to do a gain change + * (or two, or three..) in order to get an accurate estimation of signal + * sizing. Thus, RSSI will not be very accurate for short duration pulses. + * All you can really say for certain is that yes, there's a pulse that + * met the requirements of the pulse detector. + * + * For more information, see the 802.11ac Microarchitecture guide. + * (TODO: add a twiki reference.) + */ + +#endif /* __DFS_PHYERR_PEREGRINE_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_phyerr.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_phyerr.c new file mode 100644 index 000000000000..a5cb6afec4a5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_phyerr.c @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_process_phyerr.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +#include "dfs_phyerr.h" /* For chip-specific phyerr function declarations */ +/* TO DO DFS +#include +*/ +#ifndef UNINET +/* TO DO DFS +#include +*/ +#endif +#ifdef ATH_SUPPORT_DFS + +/* + * Return the frequency width for the current operating channel. + * + * This isn't the channel width - it's how wide the reported event + * may be. For HT20 this is 20MHz. For HT40 on Howl and later it'll + * still be 20MHz - the hardware returns either pri or ext channel. + */ +static inline int +dfs_get_event_freqwidth(struct ath_dfs *dfs) +{ + + /* Handle edge cases during startup/transition, shouldn't happen! */ + if (dfs == NULL) + return (0); + if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) + return (0); + + /* + * XXX For now, assume 20MHz wide - but this is incorrect when + * operating in half/quarter mode! + */ + return (20); +} + +/* + * Return the centre frequency for the current operating channel and + * event. + * + * This is for post-Owl 11n chips which report pri/extension channel + * events. + */ +static inline uint16_t +dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc) +{ + struct ieee80211com *ic; + int chan_offset = 0, chan_width; + uint16_t freq; + + /* Handle edge cases during startup/transition, shouldn't happen! */ + if (dfs == NULL) + return (0); + if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) + return (0); + + ic = dfs->ic; + + /* + * + * For wide channels, DC and ext frequencies need a bit of hand-holding + * based on whether it's an upper or lower channel. + */ + chan_width = dfs_get_event_freqwidth(dfs); + + adf_os_spin_lock_bh(&ic->chan_lock); + if (IEEE80211_IS_CHAN_11N_HT40PLUS(ic->ic_curchan)) + chan_offset = chan_width; + else if (IEEE80211_IS_CHAN_11N_HT40MINUS(ic->ic_curchan)) + chan_offset = -chan_width; + else + chan_offset = 0; + adf_os_spin_unlock_bh(&ic->chan_lock); + + /* + * Check for DC events first - the sowl code may just set all + * the bits together.. + */ + if (is_dc) { + /* + * XXX TODO: Should DC events be considered 40MHz wide here? + */ + adf_os_spin_lock_bh(&ic->chan_lock); + freq = (ieee80211_chan2freq(ic, ic->ic_curchan) + + (chan_offset / 2)); + adf_os_spin_unlock_bh(&ic->chan_lock); + return freq; + } + + /* + * For non-wide channels, the centre frequency is just ic_freq. + * The centre frequency for pri events is still ic_freq. + */ + if (is_pri) { + adf_os_spin_lock_bh(&ic->chan_lock); + freq = (ieee80211_chan2freq(ic, ic->ic_curchan)); + adf_os_spin_unlock_bh(&ic->chan_lock); + return freq; + } + + if (is_ext) { + adf_os_spin_lock_bh(&ic->chan_lock); + freq = (ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width); + adf_os_spin_unlock_bh(&ic->chan_lock); + return freq; + } + + /* XXX shouldn't get here */ + adf_os_spin_lock_bh(&ic->chan_lock); + freq = (ieee80211_chan2freq(ic, ic->ic_curchan)); + adf_os_spin_unlock_bh(&ic->chan_lock); + + return freq; +} + +/* + * Process an Owl-style phy error. + * + * Return 1 on success or 0 on failure. + */ +int +dfs_process_phyerr_owl(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, u_int64_t fulltsf, + struct dfs_phy_err *e) +{ + const char *cbuf = (const char *) buf; + u_int8_t dur; + int event_width; + + /* XXX this shouldn't be kept count here */ + dfs->ath_dfs_stats.owl_phy_errors++; + + /* + * HW cannot detect extension channel radar so it only passes us + * primary channel radar data + */ + if (datalen == 0) + dur = 0; + else + dur = ((u_int8_t *) cbuf)[0]; + + /* + * This is a spurious event; toss. + */ + if (rssi == 0 && dur == 0) + dfs->ath_dfs_stats.datalen_discards++; + return (0); + + /* + * Fill out dfs_phy_err with the information we have + * at hand. + */ + OS_MEMSET(e, 0, sizeof(*e)); + e->rssi = rssi; + e->dur = dur; + e->is_pri = 1; + e->is_ext = 0; + e->is_dc = 0; + e->is_early = 1; + e->fulltsf = fulltsf; + e->rs_tstamp = rs_tstamp; + + /* + * Owl only ever reports events on the primary channel; + * it doesn't even see events on the secondary channel. + */ + event_width = dfs_get_event_freqwidth(dfs); + e->freq = dfs_get_event_freqcentre(dfs, 1, 0, 0) * 1000; + e->freq_lo = e->freq - (event_width / 2) * 1000; + e->freq_hi = e->freq + (event_width / 2) * 1000; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, + "%s: rssi=%u dur=%u, freq=%d MHz, freq_lo=%d MHz, " + "freq_hi=%d MHz\n", + __func__, + rssi, + dur, + e->freq / 1000, + e->freq_lo / 1000, + e->freq_hi / 1000); + + return (1); +} + +/* + * Process a Sowl/Howl style phy error. + */ +int +dfs_process_phyerr_sowl(struct ath_dfs *dfs, void *buf, u_int16_t datalen, + u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, u_int64_t fulltsf, + struct dfs_phy_err *e) +{ +#define EXT_CH_RADAR_FOUND 0x02 +#define PRI_CH_RADAR_FOUND 0x01 +#define EXT_CH_RADAR_EARLY_FOUND 0x04 + const char *cbuf = (const char *) buf; + u_int8_t dur = 0; + u_int8_t pulse_bw_info, pulse_length_ext, pulse_length_pri; + int pri_found = 0, ext_found = 0; + int early_ext = 0; + int event_width; + + /* + * If radar can be detected on the extension channel, datalen zero + * pulses are bogus, discard them. + */ + if (!datalen) { + dfs->ath_dfs_stats.datalen_discards++; + return (0); + } + + /* Ensure that we have at least three bytes of payload */ + if (datalen < 3) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: short error frame (%d bytes)\n", + __func__, datalen); + dfs->ath_dfs_stats.datalen_discards++; + return (0); + } + + /* + * Fetch the payload directly - the compiler will happily generate + * byte-read instructions with a const char * cbuf pointer. + */ + pulse_length_pri = cbuf[datalen - 3]; + pulse_length_ext = cbuf[datalen - 2]; + pulse_bw_info = cbuf[datalen - 1]; + + /* + * Only the last 3 bits of the BW info are relevant, they indicate + * which channel the radar was detected in. + */ + pulse_bw_info &= 0x07; + + /* + * If pulse on DC, both primary and extension flags will be set + */ + if (((pulse_bw_info & EXT_CH_RADAR_FOUND) && + (pulse_bw_info & PRI_CH_RADAR_FOUND))) { + /* + * Conducted testing, when pulse is on DC, both + * pri and ext durations are reported to be same. + * + * Radiated testing, when pulse is on DC, different + * pri and ext durations are reported, so take the + * larger of the two + */ + if (pulse_length_ext >= pulse_length_pri) { + dur = pulse_length_ext; + ext_found = 1; + } else { + dur = pulse_length_pri; + pri_found = 1; + } + dfs->ath_dfs_stats.dc_phy_errors++; + } else { + if (pulse_bw_info & EXT_CH_RADAR_FOUND) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + dfs->ath_dfs_stats.ext_phy_errors++; + } + if (pulse_bw_info & PRI_CH_RADAR_FOUND) { + dur = pulse_length_pri; + pri_found = 1; + ext_found = 0; + dfs->ath_dfs_stats.pri_phy_errors++; + } + if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) { + dur = pulse_length_ext; + pri_found = 0; + ext_found = 1; + early_ext = 1; + dfs->ath_dfs_stats.early_ext_phy_errors++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "EARLY ext channel dur=%u rssi=%u datalen=%d\n", + dur, rssi, datalen); + } + if (! pulse_bw_info) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "ERROR channel dur=%u rssi=%u pulse_bw_info=0x%x " + "datalen MOD 4 = %d\n", + dur, rssi, pulse_bw_info, + (datalen & 0x3)); + /* + * Bogus bandwidth info received in descriptor, + * so ignore this PHY error + */ + dfs->ath_dfs_stats.bwinfo_errors++; + return (0); + } + } + + /* + * Always use combined RSSI reported, unless RSSI reported on + * extension is stronger + */ + if ((ext_rssi > rssi) && (ext_rssi < 128)) { + rssi = ext_rssi; + } + + /* + * Fill out the rssi/duration fields from above. + */ + OS_MEMSET(e, 0, sizeof(*e)); + e->rssi = rssi; + e->dur = dur; + e->is_pri = pri_found; + e->is_ext = ext_found; + e->is_dc = !! (((pulse_bw_info & EXT_CH_RADAR_FOUND) && + (pulse_bw_info & PRI_CH_RADAR_FOUND))); + e->is_early = early_ext; + e->fulltsf = fulltsf; + e->rs_tstamp = rs_tstamp; + + /* + * Sowl and later can report pri/ext events. + */ + event_width = dfs_get_event_freqwidth(dfs); + e->freq = + dfs_get_event_freqcentre(dfs, e->is_pri, e->is_ext, e->is_dc) + * 1000; + e->freq_lo = e->freq - (event_width / 2) * 1000; + e->freq_hi = e->freq + (event_width / 2) * 1000; + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, + "%s: pulse_bw_info=0x%x pulse_length_ext=%u pulse_length_pri=%u " + "rssi=%u ext_rssi=%u, freq=%d MHz, freq_lo=%d MHz, " + "freq_hi=%d MHz\n", + __func__, + pulse_bw_info, + pulse_length_ext, + pulse_length_pri, + rssi, + ext_rssi, + e->freq / 1000, + e->freq_lo / 1000, + e->freq_hi / 1000); + + return (1); +} + +/* + * Process a Merlin/Osprey style phy error. + */ +int +dfs_process_phyerr_merlin(struct ath_dfs *dfs, void *buf, + u_int16_t datalen, u_int8_t rssi, u_int8_t ext_rssi, u_int32_t rs_tstamp, + u_int64_t fulltsf, struct dfs_phy_err *e) +{ + const char *cbuf = (const char *) buf; + u_int8_t pulse_bw_info = 0; + + /* + * Process using the sowl code + */ + if (! dfs_process_phyerr_sowl(dfs, buf, datalen, rssi, ext_rssi, + rs_tstamp, fulltsf, e)) { + return (0); + } + + /* + * For osprey (and Merlin) bw_info has implication for selecting + * RSSI value. So re-fetch the bw_info field so the RSSI values + * can be appropriately overridden. + */ + pulse_bw_info = cbuf[datalen - 1]; + + switch (pulse_bw_info & 0x03) { + case 0x00: + /* No radar in ctrl or ext channel */ + rssi = 0; + break; + case 0x01: + /* radar in ctrl channel */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "RAW RSSI: rssi=%u ext_rssi=%u\n", + rssi, ext_rssi); + if (ext_rssi >= (rssi + 3)) { + /* + * cannot use ctrl channel RSSI if + * extension channel is stronger + */ + rssi = 0; + } + break; + case 0x02: + /* radar in extension channel */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "RAW RSSI: rssi=%u ext_rssi=%u\n", + rssi, ext_rssi); + if (rssi >= (ext_rssi + 12)) { + /* + * cannot use extension channel RSSI if control channel + * is stronger + */ + rssi = 0; + } else { + rssi = ext_rssi; + } + break; + case 0x03: + /* when both are present use stronger one */ + if (rssi < ext_rssi) { + rssi = ext_rssi; + } + break; + } + + /* + * Override the rssi decision made by the sowl code. + * The rest of the fields (duration, timestamp, etc) + * are left untouched. + */ + e->rssi = rssi; + + return(1); +} + +static void +dump_phyerr_contents(const char *d, int len) +{ +#ifdef CONFIG_ENABLE_DUMP_PHYERR_CONTENTS + int i, n, bufsize = 64; + + /* + * This is statically sized for a 4-digit address + 16 * 2 digit + * data string. + * + * It's done so the printk() passed to the kernel is an entire + * line, so the kernel logging code will atomically print it. + * Otherwise we'll end up with interleaved lines with output + * from other kernel threads. + */ + char buf[64]; + + /* Initial conditions */ + buf[0] = '\n'; + n = 0; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) { + n += snprintf(buf + n, bufsize - n, + "%04x: ", i); + } + n += snprintf(buf + n, bufsize - n, "%02x ", d[i] & 0xff); + if (i % 16 == 15) { + n = 0; + buf[0] = '\0'; + } + } + + /* + * Print the final line if we didn't print it above. + */ + if (n != 0) + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s: %s\n", __func__, buf); +#endif /* def CONFIG_ENABLE_DUMP_PHYERR_CONTENTS */ +} + +void +dfs_process_phyerr(struct ieee80211com *ic, void *buf, u_int16_t datalen, + u_int8_t r_rssi, u_int8_t r_ext_rssi, u_int32_t r_rs_tstamp, + u_int64_t r_fulltsf, bool enable_log) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + struct ieee80211_channel *chan=ic->ic_curchan; + struct dfs_event *event; + struct dfs_phy_err e; + int empty; + + if (dfs == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: sc_dfs is NULL\n", __func__); + return; + } + + dfs->dfs_phyerr_count++; + dump_phyerr_contents(buf, datalen); + /* + * XXX The combined_rssi_ok support has been removed. + * This was only clear for Owl. + * + * XXX TODO: re-add this; it requires passing in the ctl/ext + * RSSI set from the RX status descriptor. + * + * XXX TODO TODO: this may be done for us from the legacy + * phy error path in ath_dev; please review that code. + */ + + /* + * At this time we have a radar pulse that we need to examine and + * queue. But if dfs_process_radarevent already detected radar and set + * CHANNEL_INTERFERENCE flag then do not queue any more radar data. + * When we are in a new channel this flag will be clear and we will + * start queueing data for new channel. (EV74162) + */ + if (dfs->dfs_debug_mask & ATH_DEBUG_DFS_PHYERR_PKT) + dump_phyerr_contents(buf, datalen); + + if (chan == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: chan is NULL\n", __func__); + return; + } + + adf_os_spin_lock_bh(&ic->chan_lock); + if (IEEE80211_IS_CHAN_RADAR(chan)) { + adf_os_spin_unlock_bh(&ic->chan_lock); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: Radar already found in the channel, " + " do not queue radar data\n", + __func__); + return; + } + + adf_os_spin_unlock_bh(&ic->chan_lock); + dfs->ath_dfs_stats.total_phy_errors++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s[%d] phyerr %d len %d\n", + __func__, __LINE__, + dfs->ath_dfs_stats.total_phy_errors, datalen); + + /* + * hardware stores this as 8 bit signed value. + * we will cap it at 0 if it is a negative number + */ + if (r_rssi & 0x80) + r_rssi = 0; + + if (r_ext_rssi & 0x80) + r_ext_rssi = 0; + + OS_MEMSET(&e, 0, sizeof(e)); + + /* + * This is a bit evil - instead of just passing in + * the chip version, the existing code uses a set + * of HAL capability bits to determine what is + * possible. + * + * The way I'm decoding it is thus: + * + * + DFS enhancement? Merlin or later + * + DFS extension channel? Sowl or later. (Howl?) + * + otherwise, Owl (and legacy.) + */ + if (dfs->dfs_caps.ath_chip_is_bb_tlv) { + if (dfs_process_phyerr_bb_tlv(dfs, buf, datalen, r_rssi, r_ext_rssi, + r_rs_tstamp, r_fulltsf, + &e, enable_log) == 0) { + dfs->dfs_phyerr_reject_count++; + return; + } else { + if (dfs->dfs_phyerr_freq_min > e.freq) + dfs->dfs_phyerr_freq_min = e. freq; + + if (dfs->dfs_phyerr_freq_max < e.freq) + dfs->dfs_phyerr_freq_max = e. freq; + } + } else if (dfs->dfs_caps.ath_dfs_use_enhancement) { + if (dfs_process_phyerr_merlin(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0){ + return; + } + } else if (dfs->dfs_caps.ath_dfs_ext_chan_ok) { + if (dfs_process_phyerr_sowl(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0){ + return; + } + } else { + if (dfs_process_phyerr_owl(dfs, buf, datalen, r_rssi, + r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0){ + return; + } + } + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n %s: Frequency at which the phyerror was injected = %d", + __func__, e.freq); + + /* + * If the hardware supports radar reporting on the extension channel + * it will supply FFT data for longer radar pulses. + * + * TLV chips don't go through this software check - the hardware + * check should be enough. If we want to do software checking + * later on then someone will have to craft an FFT parser + * suitable for the TLV FFT data format. + */ + if ((! dfs->dfs_caps.ath_chip_is_bb_tlv) && + dfs->dfs_caps.ath_dfs_ext_chan_ok) { + /* + * HW has a known issue with chirping pulses injected at or + * around DC in 40MHz mode. Such pulses are reported with + * much lower durations and SW then discards them because + * they do not fit the minimum bin5 pulse duration. + * + * To work around this issue, if a pulse is within a 10us + * range of the bin5 min duration, check if the pulse is + * chirping. If the pulse is chirping, bump up the duration + * to the minimum bin5 duration. + * + * This makes sure that a valid chirping pulse will not be + * discarded because of incorrect low duration. + * + * TBD - Is it possible to calculate the 'real' duration of + * the pulse using the slope of the FFT data? + * + * TBD - Use FFT data to differentiate between radar pulses + * and false PHY errors. + * This will let us reduce the number of false alarms seen. + * + * BIN 5 chirping pulses are only for FCC or Japan MMK4 domain + */ + if (((dfs->dfsdomain == DFS_FCC_DOMAIN) || + (dfs->dfsdomain == DFS_MKK4_DOMAIN)) && + (e.dur >= MAYBE_BIN5_DUR) && (e.dur < MAX_BIN5_DUR)) { + int add_dur; + int slope = 0, dc_found = 0; + + /* + * Set the event chirping flags; as we're doing + * an actual chirp check. + */ + e.do_check_chirp = 1; + e.is_hw_chirp = 0; + e.is_sw_chirp = 0; + + /* + * dfs_check_chirping() expects is_pri and is_ext + * to be '1' for true and '0' for false for now, + * as the function itself uses these values in + * constructing things rather than testing them + * for 'true' or 'false'. + */ + add_dur = dfs_check_chirping(dfs, buf, datalen, + (e.is_pri ? 1 : 0), + (e.is_ext ? 1 : 0), + &slope, &dc_found); + if (add_dur) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "old dur %d slope =%d\n", e.dur, slope); + e.is_sw_chirp = 1; + // bump up to a random bin5 pulse duration + if (e.dur < MIN_BIN5_DUR) { + e.dur = dfs_get_random_bin5_dur(dfs, + e.fulltsf); + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "new dur %d\n", e.dur); + } else { + /* set the duration so that it is rejected */ + e.is_sw_chirp = 0; + e.dur = MAX_BIN5_DUR + 100; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "is_chirping = %d dur=%d \n", + add_dur, e.dur); + } + } else { + /* + * We have a pulse that is either bigger than + * MAX_BIN5_DUR or * less than MAYBE_BIN5_DUR + */ + if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || + (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { + /* + * XXX Would this result in very large pulses + * wrapping around to become short pulses? + */ + if (e.dur >= MAX_BIN5_DUR) { + /* + * set the duration so that it is + * rejected + */ + e.dur = MAX_BIN5_DUR + 50; + } + } + } + } + + /* + * Add the parsed, checked and filtered entry to the radar pulse + * event list. This is then checked by dfs_radar_processevent(). + * + * XXX TODO: some filtering is still done below this point - fix + * XXX this! + */ + ATH_DFSEVENTQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_eventq)); + ATH_DFSEVENTQ_UNLOCK(dfs); + if (empty) { + return; + } + + /* + * If the channel is a turbo G channel, then the event is + * for the adaptive radio (AR) pattern matching rather than + * radar detection. + */ + adf_os_spin_lock_bh(&ic->chan_lock); + if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) { + adf_os_spin_unlock_bh(&ic->chan_lock); + if (!(dfs->dfs_proc_phyerr & DFS_AR_EN)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s: DFS_AR_EN not enabled\n", + __func__); + return; + } + ATH_DFSEVENTQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_eventq)); + if (event == NULL) { + ATH_DFSEVENTQ_UNLOCK(dfs); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: no more events space left\n", + __func__); + return; + } + STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + event->re_rssi = e.rssi; + event->re_dur = e.dur; + event->re_full_ts = e.fulltsf; + event->re_ts = (e.rs_tstamp) & DFS_TSMASK; + event->re_chanindex = dfs->dfs_curchan_radindex; + event->re_flags = 0; + event->sidx = e.sidx; + + /* + * Handle chirp flags. + */ + if (e.do_check_chirp) { + event->re_flags |= DFS_EVENT_CHECKCHIRP; + if (e.is_hw_chirp) + event->re_flags |= DFS_EVENT_HW_CHIRP; + if (e.is_sw_chirp) + event->re_flags |= DFS_EVENT_SW_CHIRP; + } + + ATH_ARQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_arq), event, re_list); + ATH_ARQ_UNLOCK(dfs); + } else { + if (IEEE80211_IS_CHAN_DFS(chan)) { + adf_os_spin_unlock_bh(&ic->chan_lock); + if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "%s: DFS_RADAR_EN not enabled\n", + __func__); + return; + } + /* + * rssi is not accurate for short pulses, so do + * not filter based on that for short duration pulses + * + * XXX do this filtering above? + */ + if (dfs->dfs_caps.ath_dfs_ext_chan_ok) { + if ((e.rssi < dfs->dfs_rinfo.rn_minrssithresh && + (e.dur > 4)) || + e.dur > (dfs->dfs_rinfo.rn_maxpulsedur) ) { + dfs->ath_dfs_stats.rssi_discards++; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "Extension channel pulse is " + "discarded: dur=%d, " + "maxpulsedur=%d, rssi=%d, " + "minrssi=%d\n", + e.dur, + dfs->dfs_rinfo.rn_maxpulsedur, + e.rssi, + dfs->dfs_rinfo.rn_minrssithresh); + return; + } + } else { + if (e.rssi < dfs->dfs_rinfo.rn_minrssithresh || + e.dur > dfs->dfs_rinfo.rn_maxpulsedur) { + /* XXX TODO add a debug statement? */ + dfs->ath_dfs_stats.rssi_discards++; + return; + } + } + + /* + * Add the event to the list, if there's space. + */ + ATH_DFSEVENTQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_eventq)); + if (event == NULL) { + ATH_DFSEVENTQ_UNLOCK(dfs); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: no more events space left\n", + __func__); + return; + } + STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + + dfs->dfs_phyerr_queued_count++; + dfs->dfs_phyerr_w53_counter++; + + event->re_dur = e.dur; + event->re_full_ts = e.fulltsf; + event->re_ts = (e.rs_tstamp) & DFS_TSMASK; + event->re_rssi = e.rssi; + event->sidx = e.sidx; + + /* + * Handle chirp flags. + */ + if (e.do_check_chirp) { + event->re_flags |= DFS_EVENT_CHECKCHIRP; + if (e.is_hw_chirp) + event->re_flags |= DFS_EVENT_HW_CHIRP; + if (e.is_sw_chirp) + event->re_flags |= DFS_EVENT_SW_CHIRP; + } + + /* + * Correctly set which channel is being reported on + */ + if (e.is_pri) { + event->re_chanindex = dfs->dfs_curchan_radindex; + } else { + if (dfs->dfs_extchan_radindex == -1) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s - phyerr on ext channel\n", __func__); + } + event->re_chanindex = dfs->dfs_extchan_radindex; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s New extension channel event is added " + "to queue\n",__func__); + } + ATH_DFSQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); + ATH_DFSQ_UNLOCK(dfs); + } else { + adf_os_spin_unlock_bh(&ic->chan_lock); + } + } + + /* + * Schedule the radar/AR task as appropriate. + * + * XXX isn't a lock needed for ath_radar_tasksched? + */ + +/* +* Commenting out the dfs_process_ar_event() since the function is never +* called at run time as dfs_arq will be empty and the function +* dfs_process_ar_event is obsolete and function definition is removed +* as part of dfs_ar.c file +* +* if (!STAILQ_EMPTY(&dfs->dfs_arq)) +* // XXX shouldn't this be a task/timer too? +* dfs_process_ar_event(dfs, ic->ic_curchan); +*/ + + if (!STAILQ_EMPTY(&dfs->dfs_radarq) && !dfs->ath_radar_tasksched) { + dfs->ath_radar_tasksched = 1; + OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0); + } +#undef EXT_CH_RADAR_FOUND +#undef PRI_CH_RADAR_FOUND +#undef EXT_CH_RADAR_EARLY_FOUND +} +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_radarevent.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_radarevent.c new file mode 100644 index 000000000000..23d66c257efc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_process_radarevent.c @@ -0,0 +1,696 @@ +/* + * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_radarevent.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifdef ATH_SUPPORT_DFS + +#define FREQ_5500_MHZ 5500 +#define FREQ_5500_MHZ 5500 + +#define DFS_MAX_FREQ_SPREAD 1375 * 1 + +static char debug_dup[33]; +static int debug_dup_cnt; + +/* + * Convert the hardware provided duration to TSF ticks (usecs) + * taking the clock (fast or normal) into account. + * + * Legacy (pre-11n, Owl, Sowl, Howl) operate 5GHz using a 40MHz + * clock. Later 11n chips (Merlin, Osprey, etc) operate 5GHz using + * a 44MHz clock, so the reported pulse durations are different. + * + * Peregrine reports the pulse duration in microseconds regardless + * of the operating mode. (XXX TODO: verify this, obviously.) + */ +static inline u_int8_t +dfs_process_pulse_dur(struct ath_dfs *dfs, u_int8_t re_dur) +{ + /* + * Short pulses are sometimes returned as having a duration of 0, + * so round those up to 1. + * + * XXX This holds true for BB TLV chips too, right? + */ + if (re_dur == 0) + return 1; + + /* + * For BB TLV chips, the hardware always returns microsecond + * pulse durations. + */ + if (dfs->dfs_caps.ath_chip_is_bb_tlv) + return re_dur; + + /* + * This is for 11n and legacy chips, which may or may not + * use the 5GHz fast clock mode. + */ + /* Convert 0.8us durations to TSF ticks (usecs) */ + return (u_int8_t)dfs_round((int32_t)((dfs->dur_multiplier)*re_dur)); +} + +/* + * Process a radar event. + * + * If a radar event is found, return 1. Otherwise, return 0. + * + * There is currently no way to specify that a radar event has occured on + * a specific channel, so the current methodology is to mark both the pri + * and ext channels as being unavailable. This should be fixed for 802.11ac + * or we'll quickly run out of valid channels to use. + */ +int +dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) +{ +//commenting for now to validate radar indication msg to SAP +//#if 0 + struct dfs_event re,*event; + struct dfs_state *rs=NULL; + struct dfs_filtertype *ft; + struct dfs_filter *rf; + int found, retval = 0, p, empty; + int events_processed = 0; + u_int32_t tabledepth, index; + u_int64_t deltafull_ts = 0, this_ts, deltaT; + struct ieee80211_channel *thischan; + struct dfs_pulseline *pl; + static u_int32_t test_ts = 0; + static u_int32_t diff_ts = 0; + int ext_chan_event_flag = 0; +#if 0 + int pri_multiplier = 2; +#endif + int i; + + if (dfs == NULL) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s[%d]: dfs is NULL", __func__, __LINE__); + return 0; + } + pl = dfs->pulses; + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if ( !(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: radar event on non-DFS chan", + __func__); + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + return 0; + } + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + /* TEST : Simulate radar bang, make sure we add the channel to NOL (bug 29968) */ + if (dfs->dfs_bangradar) { + /* bangradar will always simulate radar found on the primary channel */ + rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; + dfs->dfs_bangradar = 0; /* reset */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: bangradar", __func__); + retval = 1; + goto dfsfound; + } +#endif + + /* + The HW may miss some pulses especially with high channel loading. + This is true for Japan W53 where channel loaoding is 50%. Also + for ETSI where channel loading is 30% this can be an issue too. + To take care of missing pulses, we introduce pri_margin multiplie. + This is normally 2 but can be higher for W53. + */ + + if ((dfs->dfsdomain == DFS_MKK4_DOMAIN) && + (dfs->dfs_caps.ath_chip_is_bb_tlv) && + (chan->ic_freq < FREQ_5500_MHZ)) { + + dfs->dfs_pri_multiplier = dfs->dfs_pri_multiplier_ini; + + /* do not process W53 pulses, + unless we have a minimum number of them + */ + if (dfs->dfs_phyerr_w53_counter >= 5) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: w53_counter=%d, freq_max=%d, " + "freq_min=%d, pri_multiplier=%d", + __func__, + dfs->dfs_phyerr_w53_counter, + dfs->dfs_phyerr_freq_max, + dfs->dfs_phyerr_freq_min, + dfs->dfs_pri_multiplier); + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + } else { + return 0; + } + } + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: pri_multiplier=%d", + __func__, + dfs->dfs_pri_multiplier); + + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + + while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) { + ATH_DFSQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_radarq)); + if (event != NULL) + STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); + ATH_DFSQ_UNLOCK(dfs); + + if (event == NULL) { + empty = 1; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "%s[%d]: event is NULL ",__func__,__LINE__); + break; + } + events_processed++; + re = *event; + + OS_MEMZERO(event, sizeof(struct dfs_event)); + ATH_DFSEVENTQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + + found = 0; + + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if (dfs->ic->disable_phy_err_processing) { + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + continue; + } + + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + + if (re.re_chanindex < DFS_NUM_RADAR_STATES) + rs = &dfs->dfs_radar[re.re_chanindex]; + else { + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + if (rs->rs_chan.ic_flagext & CHANNEL_INTERFERENCE) { + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + + if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { + /* + * Either not started, or 64-bit rollover exactly to zero + * Just prepend zeros to the 15-bit ts + */ + dfs->dfs_rinfo.rn_ts_prefix = 0; + } else { + /* WAR 23031- patch duplicate ts on very short pulses */ + /* This pacth has two problems in linux environment. + * 1)The time stamp created and hence PRI depends entirely on the latency. + * If the latency is high, it possibly can split two consecutive + * pulses in the same burst so far away (the same amount of latency) + * that make them look like they are from differenct bursts. It is + * observed to happen too often. It sure makes the detection fail. + * 2)Even if the latency is not that bad, it simply shifts the duplicate + * timestamps to a new duplicate timestamp based on how they are processed. + * This is not worse but not good either. + * + * Take this pulse as a good one and create a probable PRI later + */ + if (re.re_dur == 0 && re.re_ts == dfs->dfs_rinfo.rn_last_unique_ts) { + debug_dup[debug_dup_cnt++] = '1'; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, " %s deltaT is 0 ", __func__); + } else { + dfs->dfs_rinfo.rn_last_unique_ts = re.re_ts; + debug_dup[debug_dup_cnt++] = '0'; + } + if (debug_dup_cnt >= 32){ + debug_dup_cnt = 0; + } + + + if (re.re_ts <= dfs->dfs_rinfo.rn_last_ts) { + dfs->dfs_rinfo.rn_ts_prefix += + (((u_int64_t) 1) << DFS_TSSHIFT); + /* Now, see if it's been more than 1 wrap */ + deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; + if (deltafull_ts > + ((u_int64_t)((DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts))) + deltafull_ts -= (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts; + deltafull_ts = deltafull_ts >> DFS_TSSHIFT; + if (deltafull_ts > 1) { + dfs->dfs_rinfo.rn_ts_prefix += + ((deltafull_ts - 1) << DFS_TSSHIFT); + } + } else { + deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; + if (deltafull_ts > (u_int64_t) DFS_TSMASK) { + deltafull_ts = deltafull_ts >> DFS_TSSHIFT; + dfs->dfs_rinfo.rn_ts_prefix += + ((deltafull_ts - 1) << DFS_TSSHIFT); + } + } + } + /* + * At this stage rn_ts_prefix has either been blanked or + * calculated, so it's safe to use. + */ + this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((u_int64_t) re.re_ts); + dfs->dfs_rinfo.rn_lastfull_ts = re.re_full_ts; + dfs->dfs_rinfo.rn_last_ts = re.re_ts; + + /* + * The hardware returns the duration in a variety of formats, + * so it's converted from the hardware format to TSF (usec) + * values here. + * + * XXX TODO: this should really be done when the PHY error + * is processed, rather than way out here.. + */ + re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur); + + /* + * Calculate the start of the radar pulse. + * + * The TSF is stamped by the MAC upon reception of the + * event, which is (typically?) at the end of the event. + * But the pattern matching code expects the event timestamps + * to be at the start of the event. So to fake it, we + * subtract the pulse duration from the given TSF. + * + * This is done after the 64-bit timestamp has been calculated + * so long pulses correctly under-wrap the counter. Ie, if + * this was done on the 32 (or 15!) bit TSF when the TSF + * value is closed to 0, it will underflow to 0xfffffXX, which + * would mess up the logical "OR" operation done above. + * + * This isn't valid for Peregrine as the hardware gives us + * the actual TSF offset of the radar event, not just the MAC + * TSF of the completed receive. + * + * XXX TODO: ensure that the TLV PHY error processing + * code will correctly calculate the TSF to be the start + * of the radar pulse. + * + * XXX TODO TODO: modify the TLV parsing code to subtract + * the duration from the TSF, based on the current fast clock + * value. + */ + if ((! dfs->dfs_caps.ath_chip_is_bb_tlv) && re.re_dur != 1) { + this_ts -= re.re_dur; + } + + /* Save the pulse parameters in the pulse buffer(pulse line) */ + index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; + if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) + pl->pl_firstelem = (pl->pl_firstelem+1) & DFS_MAX_PULSE_BUFFER_MASK; + else + pl->pl_numelems++; + pl->pl_lastelem = index; + pl->pl_elems[index].p_time = this_ts; + pl->pl_elems[index].p_dur = re.re_dur; + pl->pl_elems[index].p_rssi = re.re_rssi; + diff_ts = (u_int32_t)this_ts - test_ts; + test_ts = (u_int32_t)this_ts; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,"ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu",(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time); + if (dfs->dfs_event_log_on) { + i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE; + dfs->radar_log[i].ts = this_ts; + dfs->radar_log[i].diff_ts = diff_ts; + dfs->radar_log[i].rssi = re.re_rssi; + dfs->radar_log[i].dur = re.re_dur; + dfs->dfs_event_log_count++; + } + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:xxxxx ts =%u re.re_dur=%u re.re_rssi =%u diff =%u pl->pl_lastelem.p_time=%llu xxxxx",__func__,__LINE__,(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time); + + + + /* If diff_ts is very small, we might be getting false pulse detects + * due to heavy interference. We might be getting spectral splatter + * from adjacent channel. In order to prevent false alarms we + * clear the delay-lines. This might impact positive detections under + * harsh environments, but helps with false detects. */ + + if (diff_ts < 100) { + dfs_reset_alldelaylines(dfs); + dfs_reset_radarq(dfs); + } + + found = 0; + + /* + * Use this fix only when device is not in test mode, as + * it drops some valid phyerrors. + * In FCC or JAPAN domain,if the follwing signature matches + * its likely that this is a false radar pulse pattern + * so process the next pulse in the queue. + */ + if ((dfs->disable_dfs_ch_switch == VOS_FALSE) && + (DFS_FCC_DOMAIN == dfs->dfsdomain || + DFS_MKK4_DOMAIN == dfs->dfsdomain) && + (re.re_dur >= 11 && re.re_dur <= 20) && + (diff_ts > 500 || diff_ts <= 305) && + (re.sidx == -4)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s: Rejecting on Peak Index = %d,re.re_dur = %d,diff_ts = %d\n", + __func__,re.sidx, re.re_dur, diff_ts); + + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + + /* + * Modifying the pulse duration for FCC Type 4 + * or JAPAN W56 Type 6 radar pulses when the + * following condition is reported in radar + * summary report. + */ + if ((DFS_FCC_DOMAIN == dfs->dfsdomain || + DFS_MKK4_DOMAIN == dfs->dfsdomain) && + ((chan->ic_flags & IEEE80211_CHAN_VHT80) == + IEEE80211_CHAN_VHT80) && + (chan->ic_pri_freq_center_freq_mhz_separation == + DFS_WAR_PLUS_30_MHZ_SEPARATION || + chan->ic_pri_freq_center_freq_mhz_separation == + DFS_WAR_MINUS_30_MHZ_SEPARATION) && + (re.sidx == DFS_WAR_PEAK_INDEX_ZERO) && + (re.re_dur > DFS_TYPE4_WAR_PULSE_DURATION_LOWER_LIMIT && + re.re_dur < DFS_TYPE4_WAR_PULSE_DURATION_UPPER_LIMIT) && + (diff_ts > DFS_TYPE4_WAR_PRI_LOWER_LIMIT && + diff_ts < DFS_TYPE4_WAR_PRI_UPPER_LIMIT)) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s:chan->ic_flags=0x%x, Pri Chan MHz Separation=%d\n", + __func__, chan->ic_flags, + chan->ic_pri_freq_center_freq_mhz_separation); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s: Reported Peak Index = %d,re.re_dur = %d,diff_ts = %d\n", + __func__, re.sidx, re.re_dur, diff_ts); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s: Modifying the pulse duration to fit the valid range \n", + __func__); + + re.re_dur = DFS_TYPE4_WAR_VALID_PULSE_DURATION; + } + + /* + * Modifying the pulse duration for ETSI Type 2 + * and ETSI type 3 radar pulses when the following + * condition is reported in radar summary report. + */ + if ((DFS_ETSI_DOMAIN == dfs->dfsdomain) && + ((chan->ic_flags & IEEE80211_CHAN_VHT80) == + IEEE80211_CHAN_VHT80) && + (chan->ic_pri_freq_center_freq_mhz_separation == + DFS_WAR_PLUS_30_MHZ_SEPARATION || + chan->ic_pri_freq_center_freq_mhz_separation == + DFS_WAR_MINUS_30_MHZ_SEPARATION) && + (re.sidx == DFS_WAR_PEAK_INDEX_ZERO) && + (re.re_dur > DFS_ETSI_TYPE2_TYPE3_WAR_PULSE_DUR_LOWER_LIMIT && + re.re_dur < DFS_ETSI_TYPE2_TYPE3_WAR_PULSE_DUR_UPPER_LIMIT) && + ((diff_ts > DFS_ETSI_TYPE2_WAR_PRI_LOWER_LIMIT && + diff_ts < DFS_ETSI_TYPE2_WAR_PRI_UPPER_LIMIT) || + (diff_ts > DFS_ETSI_TYPE3_WAR_PRI_LOWER_LIMIT && + diff_ts < DFS_ETSI_TYPE3_WAR_PRI_UPPER_LIMIT ))) { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s:chan->ic_flags=0x%x, Pri Chan MHz Separation=%d\n", + __func__, chan->ic_flags, + chan->ic_pri_freq_center_freq_mhz_separation); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s: Reported Peak Index = %d,re.re_dur = %d,diff_ts = %d\n", + __func__, re.sidx, re.re_dur, diff_ts); + + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "\n%s: Modifying the ETSI pulse dur to fit the valid range \n", + __func__); + + re.re_dur = DFS_ETSI_WAR_VALID_PULSE_DURATION; + } + + /* BIN5 pulses are FCC and Japan specific */ + + if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { + for (p=0; (p < dfs->dfs_rinfo.rn_numbin5radars) && (!found); p++) { + struct dfs_bin5radars *br; + + br = &(dfs->dfs_b5radars[p]); + if (dfs_bin5_check_pulse(dfs, &re, br)) { + // This is a valid Bin5 pulse, check if it belongs to a burst + re.re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts, re.re_dur); + // Remember our computed duration for the next pulse in the burst (if needed) + dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts; + dfs->dfs_rinfo.dfs_last_bin5_dur = re.re_dur; + + if( dfs_bin5_addpulse(dfs, br, &re, this_ts) ) { + found |= dfs_bin5_check(dfs); + } + } else{ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5_PULSE, + "%s not a BIN5 pulse (dur=%d)", + __func__, re.re_dur); + } + } + } + + if (found) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Found bin5 radar", __func__); + retval |= found; + goto dfsfound; + } + + tabledepth = 0; + rf = NULL; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1," *** chan freq (%d): ts %llu dur %u rssi %u", + rs->rs_chan.ic_freq, (unsigned long long)this_ts, re.re_dur, re.re_rssi); + + while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && + ((dfs->dfs_radartable[re.re_dur])[tabledepth] != -1) && + (!retval)) { + ft = dfs->dfs_radarf[((dfs->dfs_radartable[re.re_dur])[tabledepth])]; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2," ** RD (%d): ts %x dur %u rssi %u", + rs->rs_chan.ic_freq, + re.re_ts, re.re_dur, re.re_rssi); + + if (re.re_rssi < ft->ft_rssithresh && re.re_dur > 4) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,"%s : Rejecting on rssi rssi=%u thresh=%u", __func__, re.re_rssi, ft->ft_rssithresh); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]: Rejecting on rssi rssi=%u thresh=%u",__func__,__LINE__,re.re_rssi, ft->ft_rssithresh); + tabledepth++; + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + continue; + } + deltaT = this_ts - ft->ft_last_ts; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,"deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)",(unsigned long long)deltaT, (unsigned long long)this_ts, (unsigned long long)ft->ft_last_ts); + if ((deltaT < ft->ft_minpri) && (deltaT !=0)){ + /* This check is for the whole filter type. Individual filters + will check this again. This is first line of filtering.*/ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: Rejecting on pri pri=%lld minpri=%u", __func__, (unsigned long long)deltaT, ft->ft_minpri); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:Rejecting on pri pri=%lld minpri=%u",__func__,__LINE__,(unsigned long long)deltaT,ft->ft_minpri); + tabledepth++; + continue; + } + for (p=0, found = 0; (pft_numfilters) && (!found); p++) { + rf = &(ft->ft_filters[p]); + if ((re.re_dur >= rf->rf_mindur) && (re.re_dur <= rf->rf_maxdur)) { + /* The above check is probably not necessary */ + deltaT = (this_ts < rf->rf_dl.dl_last_ts) ? + (int64_t) ((DFS_TSF_WRAP - rf->rf_dl.dl_last_ts) + this_ts + 1) : + this_ts - rf->rf_dl.dl_last_ts; + + if ((deltaT < rf->rf_minpri) && (deltaT != 0)) { + /* Second line of PRI filtering. */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u", + rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:filterID= %d::Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u",__func__,__LINE__,rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + continue; + } + + if (rf->rf_ignore_pri_window > 0) { + if (deltaT < rf->rf_minpri) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u", + rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:filterID= %d :: Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u",__func__,__LINE__,rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + /* But update the last time stamp */ + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + } else { + + /* + The HW may miss some pulses especially with high channel loading. + This is true for Japan W53 where channel loaoding is 50%. Also + for ETSI where channel loading is 30% this can be an issue too. + To take care of missing pulses, we introduce pri_margin multiplie. + This is normally 2 but can be higher for W53. + */ + + if ( (deltaT > (dfs->dfs_pri_multiplier * rf->rf_maxpri) ) || (deltaT < rf->rf_minpri) ) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u", + rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); +VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:filterID= %d :: Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u",__func__,__LINE__,rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri); + /* But update the last time stamp */ + rf->rf_dl.dl_last_ts = this_ts; + continue; + } + } + dfs_add_pulse(dfs, rf, &re, deltaT, this_ts); + + + /* If this is an extension channel event, flag it for false alarm reduction */ + if (re.re_chanindex == dfs->dfs_extchan_radindex) { + ext_chan_event_flag = 1; + } + if (rf->rf_patterntype == 2) { + found = dfs_staggered_check(dfs, rf, (u_int32_t) deltaT, re.re_dur); + } else { + found = dfs_bin_check(dfs, rf, (u_int32_t) deltaT, re.re_dur, ext_chan_event_flag); + } + if (dfs->dfs_debug_mask & ATH_DEBUG_DFS2) { + dfs_print_delayline(dfs, &rf->rf_dl); + } + rf->rf_dl.dl_last_ts = this_ts; + } + } + ft->ft_last_ts = this_ts; + retval |= found; + if (found) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, + "Found on channel minDur = %d, filterId = %d",ft->ft_mindur, + rf != NULL ? rf->rf_pulseid : -1); + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s[%d]:### Found on channel minDur = %d, filterId = %d ###", + __func__,__LINE__,ft->ft_mindur, + rf != NULL ? rf->rf_pulseid : -1); + } + tabledepth++; + } + ATH_DFSQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + ATH_DFSQ_UNLOCK(dfs); + } +dfsfound: + if (retval) { + /* Collect stats */ + dfs->ath_dfs_stats.num_radar_detects++; + thischan = &rs->rs_chan; + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "%s[%d]: ### RADAR FOUND ON CHANNEL %d (%d MHz) ###",__func__,__LINE__,thischan->ic_ieee, +thischan->ic_freq); + DFS_PRINTK("Radar found on channel %d (%d MHz)", + thischan->ic_ieee, + thischan->ic_freq); + +#if 0 //UMACDFS : TODO + /* Disable radar for now */ + rfilt = ath_hal_getrxfilter(ah); + rfilt &= ~HAL_RX_FILTER_PHYRADAR; + ath_hal_setrxfilter(ah, rfilt); +#endif + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + /* XXX Should we really enable again? Maybe not... */ +/* No reason to re-enable so far - Ajay*/ +#if 0 + pe.pe_firpwr = rs->rs_firpwr; + pe.pe_rrssi = rs->rs_radarrssi; + pe.pe_height = rs->rs_height; + pe.pe_prssi = rs->rs_pulserssi; + pe.pe_inband = rs->rs_inband; + /* 5413 specific */ + pe.pe_relpwr = rs->rs_relpwr; + pe.pe_relstep = rs->rs_relstep; + pe.pe_maxlen = rs->rs_maxlen; + + ath_hal_enabledfs(ah, &pe); + rfilt |= HAL_RX_FILTER_PHYRADAR; + ath_hal_setrxfilter(ah, rfilt); +#endif + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "Primary channel freq = %u flags=0x%x", + chan->ic_freq, chan->ic_flagext); + adf_os_spin_lock_bh(&dfs->ic->chan_lock); + if ((dfs->ic->ic_curchan->ic_freq!= thischan->ic_freq)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "Ext channel freq = %u flags=0x%x", + thischan->ic_freq, thischan->ic_flagext); + } + + adf_os_spin_unlock_bh(&dfs->ic->chan_lock); + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_w53_counter = 0; + } + //VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "IN FUNC %s[%d]: retval = %d ",__func__,__LINE__,retval); + return retval; +//#endif +// return 1; +} + +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_staggered.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_staggered.c new file mode 100644 index 000000000000..23d27c4a1b0b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/DFS/src/dfs_staggered.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + dfs_staggered.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + +#include "dfs.h" +/* TO DO DFS +#include +*/ +#ifdef ATH_SUPPORT_DFS + +static int is_pri_multiple(u_int32_t sample_pri, u_int32_t refpri) +{ +#define MAX_ALLOWED_MISSED 3 + int i; + + if (sample_pri < refpri || (!refpri)) + return 0; + + for (i=1; i<= MAX_ALLOWED_MISSED; i++) { + if((sample_pri%(i*refpri) <= 5)) { + //printk("sample_pri=%d is a multiple of refpri=%d\n", sample_pri, refpri); + return 1; + } + } + return 0; +#undef MAX_ALLOWED_MISSED +} + +static int is_unique_pri(u_int32_t highestpri , u_int32_t midpri, + u_int32_t lowestpri , u_int32_t refpri ) +{ +#define DFS_STAGGERED_PRI_MARGIN_MIN 20 +#define DFS_STAGGERED_PRI_MARGIN_MAX 400 + if ((DFS_DIFF(lowestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) && + (DFS_DIFF(midpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) && + (DFS_DIFF(highestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN)) { + return 1; + } else { + if ((is_pri_multiple(refpri, highestpri)) || (is_pri_multiple(refpri, lowestpri)) || + (is_pri_multiple(refpri, midpri))) + return 0; + } + return 0; +#undef DFS_STAGGERED_PRI_MARGIN_MIN +#undef DFS_STAGGERED_PRI_MARGIN_MAX +} + + +int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, + u_int32_t deltaT, u_int32_t width) +{ + u_int32_t refpri, refdur, searchpri=0, deltapri;//, averagerefpri; + u_int32_t n, i, primargin, durmargin; + int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0; + struct dfs_delayline *dl; + u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff; +#if 0 + int numpulses=0; +#endif + int higherthan, lowerthan, numscores; + int numpulseshigh=0, numpulsesmid=0, numpulsestemp=0; + u_int32_t lowestscore=0, lowestscoreindex=0, lowestpri=0; + u_int32_t midscore=0, midscoreindex=0, midpri=0; + u_int32_t highestscore=0, highestscoreindex=0, highestpri=0; + + dl = &rf->rf_dl; + if( dl->dl_numelems < (rf->rf_threshold-1)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numelems %d < threshold for filter %d\n", + dl->dl_numelems, rf->rf_pulseid); + return 0; + } + if( deltaT > rf->rf_filterlen) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numelems %d < threshold for filter %d\n", + dl->dl_numelems, rf->rf_pulseid); + return 0; + } + primargin = 6; + if(rf->rf_maxdur < 10) { + durmargin = 4; + } + else { + durmargin = 6; + } + + OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE); + /* find out the lowest pri */ + for (n=0;ndl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) + continue; + else if(refpri < lowpri) { + lowpri = dl->dl_elems[delayindex].de_time; + lowpriindex = n; + } + } + /* find out the each delay element's pri score */ + for (n=0;ndl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + if( refpri == 0) { + continue; + } + + if ( (refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri) ) { + score[n] = 0; + continue; + } + + for (i=0;idl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + if( deltapri < primargin) + score[n]++; + } + } + for (n=0;ndl_numelems; n++) { + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "score[%d]=%d pri=%d\n", n, score[n], refdur); + } + + /* find out the 2 or 3 highest scorers */ + scoreindex = 0; + highestscore=0; + highestscoreindex=0; + highestpri=0; numscores=0; lowestscore=0; + + for (n=0;ndl_numelems; n++) { + higherthan=0; + lowerthan=0; + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; + refpri = dl->dl_elems[delayindex].de_time; + + if ((score[n] >= highestscore) && + (is_unique_pri(highestpri, midpri, lowestpri, refpri))) { + lowestscore = midscore; + lowestpri = midpri; + lowestscoreindex = midscoreindex; + midscore = highestscore; + midpri = highestpri; + midscoreindex = highestscoreindex; + highestscore = score[n]; + highestpri = refpri; + highestscoreindex = n; + } else { + if ((score[n] >= midscore) && + (is_unique_pri(highestpri, midpri, lowestpri, refpri))) { + lowestscore = midscore; + lowestpri = midpri; + lowestscoreindex = midscoreindex; + midscore = score[n]; + midpri = refpri; + midscoreindex = n; + } else if ((score[n] >= lowestscore) && + (is_unique_pri(highestpri, midpri, lowestpri, refpri))) { + lowestscore = score[n]; + lowestpri = refpri; + lowestscoreindex = n; + } + } + + } + + if (midscore == 0) { + // This means we have only 1 pulse type. It can not be staggered! + return 0; + } + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "FINAL highestscore=%d highestscoreindex=%d highestpri=%d\n", + highestscore, highestscoreindex, highestpri); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "FINAL lowestscore=%d lowestscoreindex=%d lowpri=%d\n", + lowestscore, lowestscoreindex, lowestpri); + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "FINAL midscore=%d midscoreindex=%d midpri=%d\n", + midscore, midscoreindex, midpri); + + + delayindex = (dl->dl_firstelem + highestscoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "highscoreindex=%d refdur=%d refpri=%d\n", + highestscoreindex, refdur, refpri); + + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur,0, highestpri); + numpulseshigh = numpulsestemp; + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur,0, highestpri + midpri); + if (numpulsestemp > numpulseshigh) { + numpulseshigh = numpulsestemp; + } + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur,0, highestpri + midpri + lowestpri); + if (numpulsestemp > numpulseshigh) { + numpulseshigh = numpulsestemp; + } + + + delayindex = (dl->dl_firstelem + midscoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "midscoreindex=%d refdur=%d refpri=%d\n", + midscoreindex, refdur, refpri); + + //numpulsesmid = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, 1); + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, midpri); + numpulsesmid = numpulsestemp; + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, highestpri + midpri); + if (numpulsestemp > numpulsesmid) { + numpulsesmid = numpulsestemp; + } + numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, highestpri + midpri + lowestpri); + if (numpulsestemp > numpulsesmid) { + numpulsesmid = numpulsestemp; + } + + + /*delayindex = (dl->dl_firstelem + lowestscoreindex) & DFS_MAX_DL_MASK; + refdur = dl->dl_elems[delayindex].de_dur; + refpri = dl->dl_elems[delayindex].de_time; + DFS_DPRINTK(ic, ATH_DEBUG_DFS1, "lowestscoreindex=%d refdur=%d refpri=%d\n", lowestscoreindex, refdur, refpri); + + numpulseslow = dfs_bin_pri_check(dfs, rf, dl, lowestscore, refpri, refdur,0, 1); + */ + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "numpulseshigh=%d, numpulsesmid=%d\n", + numpulseshigh, numpulsesmid); +// printf("numpulseshigh=%d, numpulsesmid=%d, numpulseslow %d\n",numpulseshigh, numpulsesmid, numpulseslow); + + if ( (numpulseshigh >= rf->rf_threshold) && (numpulsesmid >= rf->rf_threshold) ) { + /*if (numpulses >= rf->rf_threshold) {*/ + found = 1; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "MATCH filter=%u numpulseshigh=%u numpulsesmid= %u thresh=%u\n", rf->rf_pulseid, numpulseshigh, numpulsesmid, rf->rf_threshold); + } + return found; + } + +#endif /* ATH_SUPPORT_DFS */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320def.h new file mode 100644 index 000000000000..7bbe74402f58 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320def.h @@ -0,0 +1,703 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320DEF_H_ +#define _AR6320DEF_H_ + +/* Base Addresses */ +#define AR6320_RTC_SOC_BASE_ADDRESS 0x00000000 +#define AR6320_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320_CE0_BASE_ADDRESS 0x00034400 +#define AR6320_CE1_BASE_ADDRESS 0x00034800 +#define AR6320_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320_CE3_BASE_ADDRESS 0x00035000 +#define AR6320_CE4_BASE_ADDRESS 0x00035400 +#define AR6320_CE5_BASE_ADDRESS 0x00035800 +#define AR6320_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320_CE7_BASE_ADDRESS 0x00036000 +#define AR6320_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320_SCRATCH_3_ADDRESS 0x0028 +#define AR6320_TARG_DRAM_START 0x00400000 +#define AR6320_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320_SI_CONFIG_I2C_LSB 16 +#define AR6320_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320_SI_CONFIG_OFFSET 0x00000000 +#define AR6320_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320_SI_CS_OFFSET 0x00000004 +#define AR6320_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320_SI_CS_START_LSB 8 +#define AR6320_SI_CS_START_MASK 0x00000100 +#define AR6320_SI_CS_RX_CNT_LSB 4 +#define AR6320_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320_SI_CS_TX_CNT_LSB 0 +#define AR6320_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320_CE_COUNT 8 +#define AR6320_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320_RX_MPDU_START_0_RETRY_LSB 14 +#define AR6320_RX_MPDU_START_0_RETRY_MASK 0x00004000 +#define AR6320_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320_RX_MPDU_START_2_TID_LSB 28 +#define AR6320_RX_MPDU_START_2_TID_MASK 0xf0000000 +#define AR6320_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320_RX_MSDU_END_1_KEY_ID_OCT_MASK 0x000000ff +#define AR6320_RX_MSDU_END_1_KEY_ID_OCT_LSB 0 +#define AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320_HOST_IS_ADDRESS 0x0030 +#define AR6320_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320_HOST_IE_ADDRESS 0x002c +#define AR6320_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320_SR_BA_ADDRESS 0x0000 +#define AR6320_SR_SIZE_ADDRESS 0x0004 +#define AR6320_CE_CTRL1_ADDRESS 0x0010 +#define AR6320_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320_DR_BA_ADDRESS 0x0008 +#define AR6320_DR_SIZE_ADDRESS 0x000c +#define AR6320_MISC_IE_ADDRESS 0x0034 +#define AR6320_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320_SRC_WATERMARK_LOW_LSB 16 +#define AR6320_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320_DST_WATERMARK_LOW_LSB 16 +#define AR6320_DST_WATERMARK_HIGH_LSB 0 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320_RTC_STATE_ADDRESS 0x0000 +#define AR6320_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320_RTC_STATE_V_MASK 0x00000007 +#define AR6320_RTC_STATE_V_LSB 0 +#define AR6320_RTC_STATE_V_ON 3 +#define AR6320_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320_FW_IND_EVENT_PENDING 1 +#define AR6320_FW_IND_INITIALIZED 2 +#define AR6320_FW_IND_HELPER 4 +#define AR6320_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320_CPU_INTR_ADDRESS 0x0010 +#define AR6320_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320_CORE_CTRL_ADDRESS 0x0000 +#define AR6320_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320_SOC_CHIP_ID_REVISION_LSB 8 +#define AR6320_SOC_POWER_REG_OFFSET 0x0000010c + +/* Copy Engine Debug */ +#define AR6320_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c +#define AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MSB 3 +#define AR6320_WLAN_DEBUG_INPUT_SEL_SRC_LSB 0 +#define AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MASK 0x0000000f +#define AR6320_WLAN_DEBUG_CONTROL_OFFSET 0x00000108 +#define AR6320_WLAN_DEBUG_CONTROL_ENABLE_MSB 0 +#define AR6320_WLAN_DEBUG_CONTROL_ENABLE_LSB 0 +#define AR6320_WLAN_DEBUG_CONTROL_ENABLE_MASK 0x00000001 +#define AR6320_WLAN_DEBUG_OUT_OFFSET 0x00000110 +#define AR6320_WLAN_DEBUG_OUT_DATA_MSB 19 +#define AR6320_WLAN_DEBUG_OUT_DATA_LSB 0 +#define AR6320_WLAN_DEBUG_OUT_DATA_MASK 0x000fffff +#define AR6320_AMBA_DEBUG_BUS_OFFSET 0x0000011c +#define AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB 13 +#define AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB 8 +#define AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK 0x00003f00 +#define AR6320_AMBA_DEBUG_BUS_SEL_MSB 4 +#define AR6320_AMBA_DEBUG_BUS_SEL_LSB 0 +#define AR6320_AMBA_DEBUG_BUS_SEL_MASK 0x0000001f +#define AR6320_CE_WRAPPER_DEBUG_OFFSET 0x0008 +#define AR6320_CE_WRAPPER_DEBUG_SEL_MSB 5 +#define AR6320_CE_WRAPPER_DEBUG_SEL_LSB 0 +#define AR6320_CE_WRAPPER_DEBUG_SEL_MASK 0x0000003f +#define AR6320_CE_DEBUG_OFFSET 0x0054 +#define AR6320_CE_DEBUG_SEL_MSB 5 +#define AR6320_CE_DEBUG_SEL_LSB 0 +#define AR6320_CE_DEBUG_SEL_MASK 0x0000003f +/* End */ + +/* PLL start */ +#define AR6320_EFUSE_OFFSET 0x0000032c +#define AR6320_EFUSE_XTAL_SEL_MSB 10 +#define AR6320_EFUSE_XTAL_SEL_LSB 8 +#define AR6320_EFUSE_XTAL_SEL_MASK 0x00000700 +#define AR6320_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define AR6320_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define AR6320_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define AR6320_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define AR6320_BB_PLL_CONFIG_FRAC_MSB 17 +#define AR6320_BB_PLL_CONFIG_FRAC_LSB 0 +#define AR6320_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define AR6320_WLAN_PLL_SETTLE_TIME_MSB 10 +#define AR6320_WLAN_PLL_SETTLE_TIME_LSB 0 +#define AR6320_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define AR6320_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define AR6320_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define AR6320_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define AR6320_WLAN_PLL_SETTLE_RESET 0x00000400 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define AR6320_WLAN_PLL_CONTROL_DIV_MSB 9 +#define AR6320_WLAN_PLL_CONTROL_DIV_LSB 0 +#define AR6320_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define AR6320_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define AR6320_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define AR6320_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define AR6320_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define AR6320_WLAN_PLL_CONTROL_RESET 0x00010011 +#define AR6320_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define AR6320_RTC_SYNC_STATUS_OFFSET 0x0244 +#define AR6320_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define AR6320_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define AR6320_PCIE_INTR_CE_MASK(n) (AR6320_PCIE_INTR_CE0_MASK << (n)) +#define AR6320_DRAM_BASE_ADDRESS AR6320_TARG_DRAM_START +#define AR6320_FW_INDICATOR_ADDRESS (AR6320_SOC_CORE_BASE_ADDRESS + AR6320_SCRATCH_3_ADDRESS) +#define AR6320_SYSTEM_SLEEP_OFFSET AR6320_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320_WLAN_RESET_CONTROL_OFFSET AR6320_SOC_RESET_CONTROL_OFFSET +#define AR6320_CLOCK_CONTROL_OFFSET AR6320_SOC_CLOCK_CONTROL_OFFSET +#define AR6320_CLOCK_CONTROL_SI0_CLK_MASK AR6320_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320_RESET_CONTROL_SI0_RST_MASK AR6320_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320_GPIO_BASE_ADDRESS AR6320_WLAN_GPIO_BASE_ADDRESS +#define AR6320_GPIO_PIN0_OFFSET AR6320_WLAN_GPIO_PIN0_ADDRESS +#define AR6320_GPIO_PIN1_OFFSET AR6320_WLAN_GPIO_PIN1_ADDRESS +#define AR6320_GPIO_PIN0_CONFIG_MASK AR6320_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320_GPIO_PIN1_CONFIG_MASK AR6320_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320_SI_BASE_ADDRESS 0x00050000 +#define AR6320_CPU_CLOCK_OFFSET AR6320_SOC_CPU_CLOCK_OFFSET +#define AR6320_LPO_CAL_OFFSET AR6320_SOC_LPO_CAL_OFFSET +#define AR6320_GPIO_PIN10_OFFSET AR6320_WLAN_GPIO_PIN10_ADDRESS +#define AR6320_GPIO_PIN11_OFFSET AR6320_WLAN_GPIO_PIN11_ADDRESS +#define AR6320_GPIO_PIN12_OFFSET AR6320_WLAN_GPIO_PIN12_ADDRESS +#define AR6320_GPIO_PIN13_OFFSET AR6320_WLAN_GPIO_PIN13_ADDRESS +#define AR6320_CPU_CLOCK_STANDARD_LSB AR6320_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320_CPU_CLOCK_STANDARD_MASK AR6320_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320_LPO_CAL_ENABLE_LSB AR6320_SOC_LPO_CAL_ENABLE_LSB +#define AR6320_LPO_CAL_ENABLE_MASK AR6320_SOC_LPO_CAL_ENABLE_MASK +#define AR6320_ANALOG_INTF_BASE_ADDRESS AR6320_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320_COUNT_DEC_ADDRESS 0x0840 +#define AR6320_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320_WINDOW_WRITE_ADDR_ADDRESS 0x0878 + +struct targetdef_s ar6320_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR6320_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_RETRY_LSB = AR6320_RX_MPDU_START_0_RETRY_LSB, + .d_RX_MPDU_START_0_RETRY_MASK = AR6320_RX_MPDU_START_0_RETRY_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MPDU_START_2_TID_LSB = AR6320_RX_MPDU_START_2_TID_LSB, + .d_RX_MPDU_START_2_TID_MASK = AR6320_RX_MPDU_START_2_TID_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_MASK = AR6320_RX_MSDU_END_1_KEY_ID_OCT_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_LSB = AR6320_RX_MSDU_END_1_KEY_ID_OCT_LSB, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_WLAN_DEBUG_INPUT_SEL_OFFSET = AR6320_WLAN_DEBUG_INPUT_SEL_OFFSET, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MSB = AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_LSB = AR6320_WLAN_DEBUG_INPUT_SEL_SRC_LSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MASK = AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MASK, + .d_WLAN_DEBUG_CONTROL_OFFSET = AR6320_WLAN_DEBUG_CONTROL_OFFSET, + .d_WLAN_DEBUG_CONTROL_ENABLE_MSB = AR6320_WLAN_DEBUG_CONTROL_ENABLE_MSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_LSB = AR6320_WLAN_DEBUG_CONTROL_ENABLE_LSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_MASK = AR6320_WLAN_DEBUG_CONTROL_ENABLE_MASK, + .d_WLAN_DEBUG_OUT_OFFSET = AR6320_WLAN_DEBUG_OUT_OFFSET, + .d_WLAN_DEBUG_OUT_DATA_MSB = AR6320_WLAN_DEBUG_OUT_DATA_MSB, + .d_WLAN_DEBUG_OUT_DATA_LSB = AR6320_WLAN_DEBUG_OUT_DATA_LSB, + .d_WLAN_DEBUG_OUT_DATA_MASK = AR6320_WLAN_DEBUG_OUT_DATA_MASK, + .d_AMBA_DEBUG_BUS_OFFSET = AR6320_AMBA_DEBUG_BUS_OFFSET, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB = AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB = AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK = AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK, + .d_AMBA_DEBUG_BUS_SEL_MSB = AR6320_AMBA_DEBUG_BUS_SEL_MSB, + .d_AMBA_DEBUG_BUS_SEL_LSB = AR6320_AMBA_DEBUG_BUS_SEL_LSB, + .d_AMBA_DEBUG_BUS_SEL_MASK = AR6320_AMBA_DEBUG_BUS_SEL_MASK, + .d_CE_WRAPPER_DEBUG_OFFSET = AR6320_CE_WRAPPER_DEBUG_OFFSET, + .d_CE_WRAPPER_DEBUG_SEL_MSB = AR6320_CE_WRAPPER_DEBUG_SEL_MSB, + .d_CE_WRAPPER_DEBUG_SEL_LSB = AR6320_CE_WRAPPER_DEBUG_SEL_LSB, + .d_CE_WRAPPER_DEBUG_SEL_MASK = AR6320_CE_WRAPPER_DEBUG_SEL_MASK, + .d_CE_DEBUG_OFFSET = AR6320_CE_DEBUG_OFFSET, + .d_CE_DEBUG_SEL_MSB = AR6320_CE_DEBUG_SEL_MSB, + .d_CE_DEBUG_SEL_LSB = AR6320_CE_DEBUG_SEL_LSB, + .d_CE_DEBUG_SEL_MASK = AR6320_CE_DEBUG_SEL_MASK, + /* PLL start */ + .d_EFUSE_OFFSET = AR6320_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = AR6320_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = AR6320_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = AR6320_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = AR6320_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = AR6320_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = AR6320_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = AR6320_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = AR6320_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = AR6320_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = AR6320_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = AR6320_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = AR6320_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = AR6320_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = AR6320_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = AR6320_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = AR6320_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = AR6320_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = AR6320_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = AR6320_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = AR6320_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = AR6320_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = AR6320_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = AR6320_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = AR6320_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = AR6320_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = AR6320_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = AR6320_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = AR6320_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = AR6320_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = AR6320_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = AR6320_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = AR6320_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = AR6320_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = AR6320_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = AR6320_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = AR6320_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = AR6320_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = AR6320_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = AR6320_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = AR6320_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = AR6320_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = AR6320_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = AR6320_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = AR6320_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = AR6320_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = AR6320_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = AR6320_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = AR6320_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = AR6320_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_SOC_POWER_REG_OFFSET = AR6320_SOC_POWER_REG_OFFSET, + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320_FW_IND_INITIALIZED, + .d_FW_IND_HELPER = AR6320_FW_IND_HELPER, + .d_RTC_STATE_V_ON = AR6320_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320v2def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320v2def.h new file mode 100644 index 000000000000..7900e2b97936 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar6320v2def.h @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320V2DEF_H_ +#define _AR6320V2DEF_H_ + +/* Base Addresses */ +#define AR6320V2_RTC_SOC_BASE_ADDRESS 0x00000800 +#define AR6320V2_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320V2_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320V2_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320V2_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320V2_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320V2_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320V2_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320V2_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320V2_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320V2_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320V2_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320V2_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320V2_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320V2_CE0_BASE_ADDRESS 0x00034400 +#define AR6320V2_CE1_BASE_ADDRESS 0x00034800 +#define AR6320V2_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320V2_CE3_BASE_ADDRESS 0x00035000 +#define AR6320V2_CE4_BASE_ADDRESS 0x00035400 +#define AR6320V2_CE5_BASE_ADDRESS 0x00035800 +#define AR6320V2_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320V2_CE7_BASE_ADDRESS 0x00036000 +#define AR6320V2_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320V2_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320V2_SCRATCH_3_ADDRESS 0x0028 +#define AR6320V2_TARG_DRAM_START 0x00400000 +#define AR6320V2_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320V2_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320V2_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320V2_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320V2_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320V2_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320V2_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320V2_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320V2_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320V2_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320V2_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320V2_SI_CONFIG_I2C_LSB 16 +#define AR6320V2_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320V2_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320V2_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320V2_SI_CONFIG_OFFSET 0x00000000 +#define AR6320V2_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320V2_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320V2_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320V2_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320V2_SI_CS_OFFSET 0x00000004 +#define AR6320V2_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320V2_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320V2_SI_CS_START_LSB 8 +#define AR6320V2_SI_CS_START_MASK 0x00000100 +#define AR6320V2_SI_CS_RX_CNT_LSB 4 +#define AR6320V2_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320V2_SI_CS_TX_CNT_LSB 0 +#define AR6320V2_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320V2_CE_COUNT 8 +#define AR6320V2_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320V2_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_RETRY_LSB 14 +#define AR6320V2_RX_MPDU_START_0_RETRY_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320V2_RX_MPDU_START_2_TID_LSB 28 +#define AR6320V2_RX_MPDU_START_2_TID_MASK 0xf0000000 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff + +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320V2_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320V2_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320V2_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320V2_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320V2_HOST_IS_ADDRESS 0x0030 +#define AR6320V2_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320V2_HOST_IE_ADDRESS 0x002c +#define AR6320V2_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_SR_BA_ADDRESS 0x0000 +#define AR6320V2_SR_SIZE_ADDRESS 0x0004 +#define AR6320V2_CE_CTRL1_ADDRESS 0x0010 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320V2_DR_BA_ADDRESS 0x0008 +#define AR6320V2_DR_SIZE_ADDRESS 0x000c +#define AR6320V2_MISC_IE_ADDRESS 0x0034 +#define AR6320V2_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320V2_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320V2_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320V2_SRC_WATERMARK_LOW_LSB 16 +#define AR6320V2_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320V2_DST_WATERMARK_LOW_LSB 16 +#define AR6320V2_DST_WATERMARK_HIGH_LSB 0 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320V2_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320V2_RTC_STATE_ADDRESS 0x0000 +#define AR6320V2_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320V2_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320V2_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320V2_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320V2_RTC_STATE_V_MASK 0x00000007 +#define AR6320V2_RTC_STATE_V_LSB 0 +#define AR6320V2_RTC_STATE_V_ON 3 +#define AR6320V2_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320V2_FW_IND_EVENT_PENDING 1 +#define AR6320V2_FW_IND_INITIALIZED 2 +#define AR6320V2_FW_IND_HELPER 4 +#define AR6320V2_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320V2_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320V2_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320V2_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320V2_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320V2_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320V2_CPU_INTR_ADDRESS 0x0010 +#define AR6320V2_FW_RAM_CONFIG_ADDRESS 0x0018 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320V2_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320V2_CORE_CTRL_ADDRESS 0x0000 +#define AR6320V2_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320V2_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320V2_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320V2_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320V2_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320V2_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320V2_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320V2_SOC_CHIP_ID_REVISION_LSB 8 +#define AR6320V2_SOC_POWER_REG_OFFSET 0x0000010c + +/* Copy Engine Debug */ +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MSB 3 +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_LSB 0 +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MASK 0x0000000f +#define AR6320V2_WLAN_DEBUG_CONTROL_OFFSET 0x00000108 +#define AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MSB 0 +#define AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_LSB 0 +#define AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MASK 0x00000001 +#define AR6320V2_WLAN_DEBUG_OUT_OFFSET 0x00000110 +#define AR6320V2_WLAN_DEBUG_OUT_DATA_MSB 19 +#define AR6320V2_WLAN_DEBUG_OUT_DATA_LSB 0 +#define AR6320V2_WLAN_DEBUG_OUT_DATA_MASK 0x000fffff +#define AR6320V2_AMBA_DEBUG_BUS_OFFSET 0x0000011c +#define AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB 13 +#define AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB 8 +#define AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK 0x00003f00 +#define AR6320V2_AMBA_DEBUG_BUS_SEL_MSB 4 +#define AR6320V2_AMBA_DEBUG_BUS_SEL_LSB 0 +#define AR6320V2_AMBA_DEBUG_BUS_SEL_MASK 0x0000001f +#define AR6320V2_CE_WRAPPER_DEBUG_OFFSET 0x0008 +#define AR6320V2_CE_WRAPPER_DEBUG_SEL_MSB 5 +#define AR6320V2_CE_WRAPPER_DEBUG_SEL_LSB 0 +#define AR6320V2_CE_WRAPPER_DEBUG_SEL_MASK 0x0000003f +#define AR6320V2_CE_DEBUG_OFFSET 0x0054 +#define AR6320V2_CE_DEBUG_SEL_MSB 5 +#define AR6320V2_CE_DEBUG_SEL_LSB 0 +#define AR6320V2_CE_DEBUG_SEL_MASK 0x0000003f +/* End */ + +/* PLL start */ +#define AR6320V2_EFUSE_OFFSET 0x0000032c +#define AR6320V2_EFUSE_XTAL_SEL_MSB 10 +#define AR6320V2_EFUSE_XTAL_SEL_LSB 8 +#define AR6320V2_EFUSE_XTAL_SEL_MASK 0x00000700 +#define AR6320V2_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define AR6320V2_BB_PLL_CONFIG_FRAC_MSB 17 +#define AR6320V2_BB_PLL_CONFIG_FRAC_LSB 0 +#define AR6320V2_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define AR6320V2_WLAN_PLL_SETTLE_TIME_MSB 10 +#define AR6320V2_WLAN_PLL_SETTLE_TIME_LSB 0 +#define AR6320V2_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define AR6320V2_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define AR6320V2_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define AR6320V2_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define AR6320V2_WLAN_PLL_SETTLE_RESET 0x00000400 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_MSB 9 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_LSB 0 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define AR6320V2_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define AR6320V2_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define AR6320V2_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define AR6320V2_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define AR6320V2_WLAN_PLL_CONTROL_RESET 0x00010011 +#define AR6320V2_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define AR6320V2_RTC_SYNC_STATUS_OFFSET 0x0244 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define AR6320V2_PCIE_INTR_CE_MASK(n) (AR6320V2_PCIE_INTR_CE0_MASK << (n)) +#define AR6320V2_DRAM_BASE_ADDRESS AR6320V2_TARG_DRAM_START +#define AR6320V2_FW_INDICATOR_ADDRESS (AR6320V2_SOC_CORE_BASE_ADDRESS + AR6320V2_SCRATCH_3_ADDRESS) +#define AR6320V2_SYSTEM_SLEEP_OFFSET AR6320V2_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320V2_WLAN_RESET_CONTROL_OFFSET AR6320V2_SOC_RESET_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_OFFSET AR6320V2_SOC_CLOCK_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320V2_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320V2_RESET_CONTROL_SI0_RST_MASK AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320V2_GPIO_BASE_ADDRESS AR6320V2_WLAN_GPIO_BASE_ADDRESS +#define AR6320V2_GPIO_PIN0_OFFSET AR6320V2_WLAN_GPIO_PIN0_ADDRESS +#define AR6320V2_GPIO_PIN1_OFFSET AR6320V2_WLAN_GPIO_PIN1_ADDRESS +#define AR6320V2_GPIO_PIN0_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320V2_GPIO_PIN1_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320V2_SI_BASE_ADDRESS 0x00050000 +#define AR6320V2_CPU_CLOCK_OFFSET AR6320V2_SOC_CPU_CLOCK_OFFSET +#define AR6320V2_LPO_CAL_OFFSET AR6320V2_SOC_LPO_CAL_OFFSET +#define AR6320V2_GPIO_PIN10_OFFSET AR6320V2_WLAN_GPIO_PIN10_ADDRESS +#define AR6320V2_GPIO_PIN11_OFFSET AR6320V2_WLAN_GPIO_PIN11_ADDRESS +#define AR6320V2_GPIO_PIN12_OFFSET AR6320V2_WLAN_GPIO_PIN12_ADDRESS +#define AR6320V2_GPIO_PIN13_OFFSET AR6320V2_WLAN_GPIO_PIN13_ADDRESS +#define AR6320V2_CPU_CLOCK_STANDARD_LSB AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320V2_CPU_CLOCK_STANDARD_MASK AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320V2_LPO_CAL_ENABLE_LSB AR6320V2_SOC_LPO_CAL_ENABLE_LSB +#define AR6320V2_LPO_CAL_ENABLE_MASK AR6320V2_SOC_LPO_CAL_ENABLE_MASK +#define AR6320V2_ANALOG_INTF_BASE_ADDRESS AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320V2_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320V2_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320V2_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320V2_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320V2_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320V2_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320V2_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320V2_COUNT_DEC_ADDRESS 0x0840 +#define AR6320V2_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320V2_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320V2_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320V2_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320V2_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320V2_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320V2_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320V2_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320V2_WINDOW_WRITE_ADDR_ADDRESS 0x0878 + +struct targetdef_s ar6320v2_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320V2_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320V2_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320V2_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320V2_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320V2_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320V2_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320V2_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320V2_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320V2_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320V2_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320V2_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320V2_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320V2_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320V2_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320V2_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320V2_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320V2_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320V2_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320V2_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320V2_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320V2_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320V2_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320V2_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320V2_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320V2_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320V2_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320V2_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320V2_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320V2_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320V2_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320V2_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320V2_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320V2_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320V2_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320V2_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320V2_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320V2_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320V2_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320V2_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320V2_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320V2_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320V2_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320V2_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320V2_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320V2_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320V2_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320V2_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320V2_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320V2_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320V2_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320V2_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320V2_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320V2_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320V2_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320V2_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320V2_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320V2_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320V2_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320V2_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320V2_CORE_CTRL_CPU_INTR_MASK, + .d_FW_RAM_CONFIG_ADDRESS = AR6320V2_FW_RAM_CONFIG_ADDRESS, + .d_SR_WR_INDEX_ADDRESS = AR6320V2_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320V2_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_RETRY_LSB = AR6320V2_RX_MPDU_START_0_RETRY_LSB, + .d_RX_MPDU_START_0_RETRY_MASK = AR6320V2_RX_MPDU_START_0_RETRY_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320V2_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320V2_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MPDU_START_2_TID_LSB = AR6320V2_RX_MPDU_START_2_TID_LSB, + .d_RX_MPDU_START_2_TID_MASK = AR6320V2_RX_MPDU_START_2_TID_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320V2_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320V2_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320V2_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320V2_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320V2_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320V2_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320V2_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320V2_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320V2_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320V2_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320V2_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320V2_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320V2_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320V2_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320V2_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320V2_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320V2_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320V2_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320V2_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320V2_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320V2_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320V2_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320V2_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320V2_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320V2_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320V2_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_WLAN_DEBUG_INPUT_SEL_OFFSET = AR6320V2_WLAN_DEBUG_INPUT_SEL_OFFSET, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MSB = AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_LSB = AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_LSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MASK = AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MASK, + .d_WLAN_DEBUG_CONTROL_OFFSET = AR6320V2_WLAN_DEBUG_CONTROL_OFFSET, + .d_WLAN_DEBUG_CONTROL_ENABLE_MSB = AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_LSB = AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_LSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_MASK = AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MASK, + .d_WLAN_DEBUG_OUT_OFFSET = AR6320V2_WLAN_DEBUG_OUT_OFFSET, + .d_WLAN_DEBUG_OUT_DATA_MSB = AR6320V2_WLAN_DEBUG_OUT_DATA_MSB, + .d_WLAN_DEBUG_OUT_DATA_LSB = AR6320V2_WLAN_DEBUG_OUT_DATA_LSB, + .d_WLAN_DEBUG_OUT_DATA_MASK = AR6320V2_WLAN_DEBUG_OUT_DATA_MASK, + .d_AMBA_DEBUG_BUS_OFFSET = AR6320V2_AMBA_DEBUG_BUS_OFFSET, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB = AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB = AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK = AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK, + .d_AMBA_DEBUG_BUS_SEL_MSB = AR6320V2_AMBA_DEBUG_BUS_SEL_MSB, + .d_AMBA_DEBUG_BUS_SEL_LSB = AR6320V2_AMBA_DEBUG_BUS_SEL_LSB, + .d_AMBA_DEBUG_BUS_SEL_MASK = AR6320V2_AMBA_DEBUG_BUS_SEL_MASK, + .d_CE_WRAPPER_DEBUG_OFFSET = AR6320V2_CE_WRAPPER_DEBUG_OFFSET, + .d_CE_WRAPPER_DEBUG_SEL_MSB = AR6320V2_CE_WRAPPER_DEBUG_SEL_MSB, + .d_CE_WRAPPER_DEBUG_SEL_LSB = AR6320V2_CE_WRAPPER_DEBUG_SEL_LSB, + .d_CE_WRAPPER_DEBUG_SEL_MASK = AR6320V2_CE_WRAPPER_DEBUG_SEL_MASK, + .d_CE_DEBUG_OFFSET = AR6320V2_CE_DEBUG_OFFSET, + .d_CE_DEBUG_SEL_MSB = AR6320V2_CE_DEBUG_SEL_MSB, + .d_CE_DEBUG_SEL_LSB = AR6320V2_CE_DEBUG_SEL_LSB, + .d_CE_DEBUG_SEL_MASK = AR6320V2_CE_DEBUG_SEL_MASK, + /* PLL start */ + .d_EFUSE_OFFSET = AR6320V2_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = AR6320V2_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = AR6320V2_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = AR6320V2_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = AR6320V2_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = AR6320V2_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = AR6320V2_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = AR6320V2_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = AR6320V2_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = AR6320V2_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = AR6320V2_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = AR6320V2_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = AR6320V2_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = AR6320V2_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = AR6320V2_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = AR6320V2_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = AR6320V2_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = AR6320V2_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = AR6320V2_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = AR6320V2_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = AR6320V2_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = AR6320V2_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = AR6320V2_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = AR6320V2_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = AR6320V2_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = AR6320V2_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = AR6320V2_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = AR6320V2_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = AR6320V2_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = AR6320V2_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = AR6320V2_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = AR6320V2_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = AR6320V2_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = AR6320V2_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = AR6320V2_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = AR6320V2_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = AR6320V2_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = AR6320V2_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = AR6320V2_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = AR6320V2_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = AR6320V2_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = AR6320V2_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = AR6320V2_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = AR6320V2_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_SOC_POWER_REG_OFFSET = AR6320V2_SOC_POWER_REG_OFFSET, + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320V2_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320V2_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320V2_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320V2_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320V2_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320V2_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320V2_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320V2_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320v2_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320V2_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320V2_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320V2_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320V2_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320V2_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320V2_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320V2_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320V2_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320V2_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320V2_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320V2_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320V2_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320V2_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320V2_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320V2_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320V2_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320V2_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320V2_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320V2_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320V2_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320V2_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320V2_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320V2_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320V2_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320V2_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320V2_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320V2_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320V2_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320V2_FW_IND_INITIALIZED, + .d_FW_IND_HELPER = AR6320V2_FW_IND_HELPER, + .d_RTC_STATE_V_ON = AR6320V2_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320V2_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320V2_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar9888def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar9888def.h new file mode 100644 index 000000000000..b26b1b74f528 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/ar9888def.h @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR9888DEF_H_ +#define AR9888__AR9888DEF_H_ + +/* Base Addresses */ +#define AR9888_RTC_SOC_BASE_ADDRESS 0x00004000 +#define AR9888_RTC_WMAC_BASE_ADDRESS 0x00005000 +#define AR9888_MAC_COEX_BASE_ADDRESS 0x00006000 +#define AR9888_BT_COEX_BASE_ADDRESS 0x00007000 +#define AR9888_SOC_PCIE_BASE_ADDRESS 0x00008000 +#define AR9888_SOC_CORE_BASE_ADDRESS 0x00009000 +#define AR9888_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR9888_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR9888_WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 +#define AR9888_WLAN_MAC_BASE_ADDRESS 0x00020000 +#define AR9888_EFUSE_BASE_ADDRESS 0x00030000 +#define AR9888_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR9888_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR9888_CE_WRAPPER_BASE_ADDRESS 0x00057000 +#define AR9888_CE0_BASE_ADDRESS 0x00057400 +#define AR9888_CE1_BASE_ADDRESS 0x00057800 +#define AR9888_CE2_BASE_ADDRESS 0x00057c00 +#define AR9888_CE3_BASE_ADDRESS 0x00058000 +#define AR9888_CE4_BASE_ADDRESS 0x00058400 +#define AR9888_CE5_BASE_ADDRESS 0x00058800 +#define AR9888_CE6_BASE_ADDRESS 0x00058c00 +#define AR9888_CE7_BASE_ADDRESS 0x00059000 +#define AR9888_DBI_BASE_ADDRESS 0x00060000 +#define AR9888_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 + +#define AR9888_SCRATCH_3_ADDRESS 0x0030 +#define AR9888_TARG_DRAM_START 0x00400000 +#define AR9888_SOC_SYSTEM_SLEEP_OFFSET 0x000000c4 +#define AR9888_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR9888_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR9888_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR9888_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define AR9888_WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define AR9888_WLAN_GPIO_PIN0_ADDRESS 0x00000028 +#define AR9888_WLAN_GPIO_PIN1_ADDRESS 0x0000002c +#define AR9888_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR9888_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR9888_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR9888_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR9888_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR9888_WLAN_GPIO_PIN10_ADDRESS 0x00000050 +#define AR9888_WLAN_GPIO_PIN11_ADDRESS 0x00000054 +#define AR9888_WLAN_GPIO_PIN12_ADDRESS 0x00000058 +#define AR9888_WLAN_GPIO_PIN13_ADDRESS 0x0000005c +#define AR9888_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR9888_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR9888_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR9888_SOC_LPO_CAL_ENABLE_MASK 0x00100000 +#define AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 + +#define AR9888_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR9888_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR9888_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR9888_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR9888_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR9888_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR9888_SI_CONFIG_I2C_LSB 16 +#define AR9888_SI_CONFIG_I2C_MASK 0x00010000 +#define AR9888_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR9888_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR9888_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR9888_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR9888_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR9888_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR9888_SI_CONFIG_DIVIDER_LSB 0 +#define AR9888_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR9888_SI_CONFIG_OFFSET 0x00000000 +#define AR9888_SI_TX_DATA0_OFFSET 0x00000008 +#define AR9888_SI_TX_DATA1_OFFSET 0x0000000c +#define AR9888_SI_RX_DATA0_OFFSET 0x00000010 +#define AR9888_SI_RX_DATA1_OFFSET 0x00000014 +#define AR9888_SI_CS_OFFSET 0x00000004 +#define AR9888_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR9888_SI_CS_DONE_INT_MASK 0x00000200 +#define AR9888_SI_CS_START_LSB 8 +#define AR9888_SI_CS_START_MASK 0x00000100 +#define AR9888_SI_CS_RX_CNT_LSB 4 +#define AR9888_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR9888_SI_CS_TX_CNT_LSB 0 +#define AR9888_SI_CS_TX_CNT_MASK 0x0000000f +#define AR9888_CE_COUNT 8 +#define AR9888_SR_WR_INDEX_ADDRESS 0x003c +#define AR9888_DST_WATERMARK_ADDRESS 0x0050 +#define AR9888_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR9888_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR9888_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR9888_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR9888_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR9888_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR9888_RX_MSDU_END_1_KEY_ID_OCT_MASK 0x000000ff +#define AR9888_RX_MSDU_END_1_KEY_ID_OCT_LSB 0 +#define AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR9888_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR9888_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR9888_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR9888_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR9888_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR9888_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR9888_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR9888_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR9888_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR9888_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR9888_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR9888_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR9888_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR9888_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR9888_DST_WR_INDEX_ADDRESS 0x0040 +#define AR9888_SRC_WATERMARK_ADDRESS 0x004c +#define AR9888_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR9888_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR9888_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR9888_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR9888_CURRENT_SRRI_ADDRESS 0x0044 +#define AR9888_CURRENT_DRRI_ADDRESS 0x0048 +#define AR9888_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR9888_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR9888_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR9888_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR9888_HOST_IS_ADDRESS 0x0030 +#define AR9888_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR9888_HOST_IE_ADDRESS 0x002c +#define AR9888_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR9888_SR_BA_ADDRESS 0x0000 +#define AR9888_SR_SIZE_ADDRESS 0x0004 +#define AR9888_CE_CTRL1_ADDRESS 0x0010 +#define AR9888_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR9888_DR_BA_ADDRESS 0x0008 +#define AR9888_DR_SIZE_ADDRESS 0x000c +#define AR9888_MISC_IE_ADDRESS 0x0034 +#define AR9888_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR9888_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR9888_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR9888_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR9888_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR9888_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR9888_SRC_WATERMARK_LOW_LSB 16 +#define AR9888_SRC_WATERMARK_HIGH_LSB 0 +#define AR9888_DST_WATERMARK_LOW_LSB 16 +#define AR9888_DST_WATERMARK_HIGH_LSB 0 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR9888_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000004 +#define AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 2 +#define AR9888_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR9888_RTC_STATE_ADDRESS 0x0000 +#define AR9888_RTC_STATE_COLD_RESET_MASK 0x00000400 +#define AR9888_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR9888_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR9888_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR9888_RTC_STATE_V_MASK 0x00000007 +#define AR9888_RTC_STATE_V_LSB 0 +#define AR9888_RTC_STATE_V_ON 3 +#define AR9888_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR9888_FW_IND_EVENT_PENDING 1 +#define AR9888_FW_IND_INITIALIZED 2 +#define AR9888_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR9888_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR9888_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR9888_PCIE_INTR_CE0_MASK 0x00000800 +#define AR9888_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR9888_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR9888_CPU_INTR_ADDRESS 0x0010 +#define AR9888_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR9888_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR9888_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR9888_SOC_RESET_CONTROL_CE_RST_MASK 0x00040000 +#define AR9888_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR9888_CORE_CTRL_ADDRESS 0x0000 +#define AR9888_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR9888_LOCAL_SCRATCH_OFFSET 0x18 +#define AR9888_CLOCK_GPIO_OFFSET 0xffffffff +#define AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 + +#define AR9888_PCIE_INTR_CE_MASK(n) (AR9888_PCIE_INTR_CE0_MASK << (n)) +#define AR9888_FW_EVENT_PENDING_ADDRESS (AR9888_SOC_CORE_BASE_ADDRESS + AR9888_SCRATCH_3_ADDRESS) +#define AR9888_DRAM_BASE_ADDRESS AR9888_TARG_DRAM_START +#define AR9888_FW_INDICATOR_ADDRESS (AR9888_SOC_CORE_BASE_ADDRESS + AR9888_SCRATCH_3_ADDRESS) +#define AR9888_SYSTEM_SLEEP_OFFSET AR9888_SOC_SYSTEM_SLEEP_OFFSET +#define AR9888_WLAN_SYSTEM_SLEEP_OFFSET AR9888_SOC_SYSTEM_SLEEP_OFFSET +#define AR9888_WLAN_RESET_CONTROL_OFFSET AR9888_SOC_RESET_CONTROL_OFFSET +#define AR9888_CLOCK_CONTROL_OFFSET AR9888_SOC_CLOCK_CONTROL_OFFSET +#define AR9888_CLOCK_CONTROL_SI0_CLK_MASK AR9888_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR9888_RESET_CONTROL_MBOX_RST_MASK MISSING +#define AR9888_RESET_CONTROL_SI0_RST_MASK AR9888_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR9888_GPIO_BASE_ADDRESS AR9888_WLAN_GPIO_BASE_ADDRESS +#define AR9888_GPIO_PIN0_OFFSET AR9888_WLAN_GPIO_PIN0_ADDRESS +#define AR9888_GPIO_PIN1_OFFSET AR9888_WLAN_GPIO_PIN1_ADDRESS +#define AR9888_GPIO_PIN0_CONFIG_MASK AR9888_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR9888_GPIO_PIN1_CONFIG_MASK AR9888_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR9888_SI_BASE_ADDRESS AR9888_WLAN_SI_BASE_ADDRESS +#define AR9888_SCRATCH_BASE_ADDRESS AR9888_SOC_CORE_BASE_ADDRESS +#define AR9888_CPU_CLOCK_OFFSET AR9888_SOC_CPU_CLOCK_OFFSET +#define AR9888_LPO_CAL_OFFSET AR9888_SOC_LPO_CAL_OFFSET +#define AR9888_GPIO_PIN10_OFFSET AR9888_WLAN_GPIO_PIN10_ADDRESS +#define AR9888_GPIO_PIN11_OFFSET AR9888_WLAN_GPIO_PIN11_ADDRESS +#define AR9888_GPIO_PIN12_OFFSET AR9888_WLAN_GPIO_PIN12_ADDRESS +#define AR9888_GPIO_PIN13_OFFSET AR9888_WLAN_GPIO_PIN13_ADDRESS +#define AR9888_CPU_CLOCK_STANDARD_LSB AR9888_SOC_CPU_CLOCK_STANDARD_LSB +#define AR9888_CPU_CLOCK_STANDARD_MASK AR9888_SOC_CPU_CLOCK_STANDARD_MASK +#define AR9888_LPO_CAL_ENABLE_LSB AR9888_SOC_LPO_CAL_ENABLE_LSB +#define AR9888_LPO_CAL_ENABLE_MASK AR9888_SOC_LPO_CAL_ENABLE_MASK +#define AR9888_ANALOG_INTF_BASE_ADDRESS AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR9888_MBOX_BASE_ADDRESS MISSING +#define AR9888_INT_STATUS_ENABLE_ERROR_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_ERROR_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_CPU_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_CPU_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define AR9888_COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define AR9888_COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_ADDRESS MISSING +#define AR9888_CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define AR9888_CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define AR9888_HOST_INT_STATUS_ADDRESS MISSING +#define AR9888_CPU_INT_STATUS_ADDRESS MISSING +#define AR9888_ERROR_INT_STATUS_ADDRESS MISSING +#define AR9888_ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define AR9888_ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define AR9888_ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define AR9888_ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define AR9888_COUNT_DEC_ADDRESS MISSING +#define AR9888_HOST_INT_STATUS_CPU_MASK MISSING +#define AR9888_HOST_INT_STATUS_CPU_LSB MISSING +#define AR9888_HOST_INT_STATUS_ERROR_MASK MISSING +#define AR9888_HOST_INT_STATUS_ERROR_LSB MISSING +#define AR9888_HOST_INT_STATUS_COUNTER_MASK MISSING +#define AR9888_HOST_INT_STATUS_COUNTER_LSB MISSING +#define AR9888_RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define AR9888_WINDOW_DATA_ADDRESS MISSING +#define AR9888_WINDOW_READ_ADDR_ADDRESS MISSING +#define AR9888_WINDOW_WRITE_ADDR_ADDRESS MISSING + +struct targetdef_s ar9888_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR9888_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR9888_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR9888_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR9888_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR9888_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR9888_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR9888_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR9888_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR9888_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR9888_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR9888_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR9888_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR9888_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR9888_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR9888_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR9888_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR9888_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR9888_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR9888_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR9888_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR9888_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR9888_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR9888_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR9888_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR9888_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR9888_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR9888_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR9888_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR9888_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR9888_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR9888_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR9888_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR9888_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR9888_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR9888_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR9888_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR9888_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR9888_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR9888_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR9888_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR9888_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR9888_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR9888_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR9888_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR9888_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR9888_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR9888_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR9888_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR9888_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR9888_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR9888_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR9888_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR9888_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR9888_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR9888_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR9888_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR9888_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR9888_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR9888_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR9888_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR9888_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR9888_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR9888_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR9888_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR9888_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR9888_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR9888_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR9888_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR9888_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR9888_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR9888_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR9888_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR9888_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR9888_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR9888_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR9888_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR9888_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR9888_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR9888_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR9888_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR9888_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR9888_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR9888_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_1_KEY_ID_OCT_MASK = AR9888_RX_MSDU_END_1_KEY_ID_OCT_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_LSB = AR9888_RX_MSDU_END_1_KEY_ID_OCT_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR9888_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR9888_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR9888_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR9888_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR9888_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR9888_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR9888_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR9888_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR9888_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR9888_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR9888_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR9888_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR9888_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR9888_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR9888_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR9888_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR9888_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR9888_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR9888_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR9888_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR9888_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR9888_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR9888_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR9888_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR9888_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR9888_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR9888_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR9888_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR9888_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR9888_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR9888_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR9888_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR9888_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR9888_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR9888_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR9888_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR9888_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR9888_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR9888_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR9888_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR9888_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR9888_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR9888_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR9888_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR9888_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR9888_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR9888_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR9888_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR9888_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR9888_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR9888_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR9888_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + + .d_PCIE_INTR_CAUSE_ADDRESS = AR9888_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR9888_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR9888_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR9888_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR9888_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR9888_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR9888_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, +}; + +struct hostdef_s ar9888_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR9888_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR9888_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR9888_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR9888_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR9888_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR9888_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR9888_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR9888_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR9888_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR9888_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR9888_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR9888_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR9888_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR9888_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR9888_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR9888_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR9888_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR9888_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR9888_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR9888_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR9888_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR9888_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR9888_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR9888_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR9888_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR9888_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR9888_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR9888_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR9888_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR9888_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR9888_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR9888_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR9888_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR9888_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR9888_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR9888_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR9888_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR9888_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR9888_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR9888_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR9888_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR9888_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR9888_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR9888_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR9888_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/cepci.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/cepci.h new file mode 100644 index 000000000000..f5ba19bde895 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/cepci.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __CEPCI_H__ +#define __CEPCI_H__ + +/* + * Support for Copy Engine over PCI. + * Structures shared between Host software and Target firmware. + */ + + +/* + * Total number of PCIe MSI interrupts requested for all interrupt sources. + * PCIe standard forces this to be a power of 2. + * Some Host OS's limit MSI requests that can be granted to 8 + * so for now we abide by this limit and avoid requesting more + * than that. + */ +#define MSI_NUM_REQUEST_LOG2 3 +#define MSI_NUM_REQUEST (1<hi_interconnect_state points + * here (and all members are 32-bit quantities in order to + * facilitate Host access). In particular, Host software is + * required to initialize pipe_cfg_addr and svc_to_pipe_map. + */ +struct pcie_state_s { + A_UINT32 pipe_cfg_addr; /* Pipe configuration Target address */ + /* NB: CE_pipe_config[CE_COUNT] */ + + A_UINT32 svc_to_pipe_map; /* Service to pipe map Target address */ + /* NB: service_to_pipe[PIPE_TO_CE_MAP_CN] */ + + A_UINT32 MSI_requested; /* number of MSI interrupts requested */ + A_UINT32 MSI_granted; /* number of MSI interrupts granted */ + A_UINT32 MSI_addr; /* Message Signalled Interrupt address */ + A_UINT32 MSI_data; /* Base data */ + A_UINT32 MSI_fw_intr_data; /* Data for firmware interrupt; + MSI data for other interrupts are + in various SoC registers */ + + A_UINT32 power_mgmt_method; /* PCIE_PWR_METHOD_* */ + A_UINT32 config_flags; /* PCIE_CONFIG_FLAG_* */ +}; + +/* + * PCIE_CONFIG_FLAG definitions + */ +#define PCIE_CONFIG_FLAG_ENABLE_L1 0x0000001 +#define PCIE_CONFIG_FLAG_CLK_SWITCH_WAIT 0x0000002 +#define PCIE_CONFIG_FLAG_AXI_CLK_GATE 0x0000004 + +#define PIPE_TO_CE_MAP_CNT 32 /* simple implementation constant */ + +/* + * Configuration information for a Copy Engine pipe. + * Passed from Host to Target during startup (one per CE). + */ +struct CE_pipe_config { + A_UINT32 pipenum; + A_UINT32 pipedir; + A_UINT32 nentries; + A_UINT32 nbytes_max; + A_UINT32 flags; + A_UINT32 reserved; +}; + +#endif /* __CEPCI_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine.c new file mode 100644 index 000000000000..c73a8537c52c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine.c @@ -0,0 +1,1678 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include +#include "a_types.h" +#include +#include "osapi_linux.h" +#include "hif_msg_based.h" +#include "if_pci.h" +#include "copy_engine_api.h" +#include "copy_engine_internal.h" +#include "adf_os_lock.h" +#include "hif_pci.h" +#include "regtable.h" +#include +#include "epping_main.h" + +#define CE_POLL_TIMEOUT 10 /* ms */ + +static int war1_allow_sleep; +extern int hif_pci_war1; + +/* + * Support for Copy Engine hardware, which is mainly used for + * communication between Host and Target over a PCIe interconnect. + */ + +/* + * A single CopyEngine (CE) comprises two "rings": + * a source ring + * a destination ring + * + * Each ring consists of a number of descriptors which specify + * an address, length, and meta-data. + * + * Typically, one side of the PCIe interconnect (Host or Target) + * controls one ring and the other side controls the other ring. + * The source side chooses when to initiate a transfer and it + * chooses what to send (buffer address, length). The destination + * side keeps a supply of "anonymous receive buffers" available and + * it handles incoming data as it arrives (when the destination + * recieves an interrupt). + * + * The sender may send a simple buffer (address/length) or it may + * send a small list of buffers. When a small list is sent, hardware + * "gathers" these and they end up in a single destination buffer + * with a single interrupt. + * + * There are several "contexts" managed by this layer -- more, it + * may seem -- than should be needed. These are provided mainly for + * maximum flexibility and especially to facilitate a simpler HIF + * implementation. There are per-CopyEngine recv, send, and watermark + * contexts. These are supplied by the caller when a recv, send, + * or watermark handler is established and they are echoed back to + * the caller when the respective callbacks are invoked. There is + * also a per-transfer context supplied by the caller when a buffer + * (or sendlist) is sent and when a buffer is enqueued for recv. + * These per-transfer contexts are echoed back to the caller when + * the buffer is sent/received. + */ + +/* + * Guts of CE_send, used by both CE_send and CE_sendlist_send. + * The caller takes responsibility for any needed locking. + */ +int +CE_completed_send_next_nolock(struct CE_state *CE_state, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx); + +void WAR_CE_SRC_RING_WRITE_IDX_SET(struct hif_pci_softc *sc, + void __iomem *targid, + u32 ctrl_addr, + unsigned int write_index) +{ + if (hif_pci_war1) { + void __iomem *indicator_addr; + + indicator_addr = targid + ctrl_addr + DST_WATERMARK_ADDRESS; + + if (!war1_allow_sleep && ctrl_addr == CE_BASE_ADDRESS(CDC_WAR_DATA_CE)) { + A_PCI_WRITE32(indicator_addr, + (CDC_WAR_MAGIC_STR | write_index)); + } else { + unsigned long irq_flags; + local_irq_save(irq_flags); + A_PCI_WRITE32(indicator_addr, 1); + + /* + * PCIE write waits for ACK in IPQ8K, there is no + * need to read back value. + */ + (void)A_PCI_READ32(indicator_addr); + (void)A_PCI_READ32(indicator_addr); /* conservative */ + + CE_SRC_RING_WRITE_IDX_SET(targid, + ctrl_addr, + write_index); + + A_PCI_WRITE32(indicator_addr, 0); + local_irq_restore(irq_flags); + } + } else + CE_SRC_RING_WRITE_IDX_SET(targid, ctrl_addr, write_index); +} + +int +CE_send_nolock(struct CE_handle *copyeng, + void *per_transfer_context, + CE_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags) +{ + int status; + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *src_ring = CE_state->src_ring; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + struct hif_pci_softc *sc = CE_state->sc; + A_target_id_t targid = TARGID(sc); + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int write_index = src_ring->write_index; + + A_TARGET_ACCESS_BEGIN_RET(targid); + if (unlikely(CE_RING_DELTA(nentries_mask, write_index, sw_index-1) <= 0)) { + OL_ATH_CE_PKT_ERROR_COUNT_INCR(sc,CE_RING_DELTA_FAIL); + status = A_ERROR; + A_TARGET_ACCESS_END_RET(targid); + return status; + } + { + struct CE_src_desc *src_ring_base = (struct CE_src_desc *)src_ring->base_addr_owner_space; + struct CE_src_desc *shadow_base = (struct CE_src_desc *)src_ring->shadow_base; + struct CE_src_desc *src_desc = CE_SRC_RING_TO_DESC(src_ring_base, write_index); + struct CE_src_desc *shadow_src_desc = CE_SRC_RING_TO_DESC(shadow_base, write_index); + + /* Update source descriptor */ + shadow_src_desc->src_ptr = buffer; + shadow_src_desc->meta_data = transfer_id; + + /* + * Set the swap bit if: + * typical sends on this CE are swapped (host is big-endian) and + * this send doesn't disable the swapping (data is not bytestream) + */ + shadow_src_desc->byte_swap = + (((CE_state->attr_flags & CE_ATTR_BYTE_SWAP_DATA) != 0) & + ((flags & CE_SEND_FLAG_SWAP_DISABLE) == 0)); + shadow_src_desc->gather = ((flags & CE_SEND_FLAG_GATHER) != 0); + shadow_src_desc->nbytes = nbytes; + + *src_desc = *shadow_src_desc; + + src_ring->per_transfer_context[write_index] = per_transfer_context; + + /* Update Source Ring Write Index */ + write_index = CE_RING_IDX_INCR(nentries_mask, write_index); + + /* WORKAROUND */ + if (!shadow_src_desc->gather) { + WAR_CE_SRC_RING_WRITE_IDX_SET(sc, targid, ctrl_addr, write_index); + } + + src_ring->write_index = write_index; + status = A_OK; + } + A_TARGET_ACCESS_END_RET(targid); + + return status; +} + +int +CE_send(struct CE_handle *copyeng, + void *per_transfer_context, + CE_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + int status; + + + adf_os_spin_lock_bh(&sc->target_lock); + status = CE_send_nolock(copyeng, per_transfer_context, buffer, nbytes, transfer_id, flags); + adf_os_spin_unlock_bh(&sc->target_lock); + + return status; +} + +unsigned int +CE_sendlist_sizeof(void) +{ + return sizeof(struct CE_sendlist); +} + +void +CE_sendlist_init(struct CE_sendlist *sendlist) +{ + struct CE_sendlist_s *sl = (struct CE_sendlist_s *)sendlist; + sl->num_items=0; +} + +int +CE_sendlist_buf_add(struct CE_sendlist *sendlist, + CE_addr_t buffer, + unsigned int nbytes, + u_int32_t flags) +{ + struct CE_sendlist_s *sl = (struct CE_sendlist_s *)sendlist; + unsigned int num_items = sl->num_items; + struct CE_sendlist_item *item; + + if (num_items >= CE_SENDLIST_ITEMS_MAX) { + A_ASSERT(num_items < CE_SENDLIST_ITEMS_MAX); + return A_NO_RESOURCE; + } + + item = &sl->item[num_items]; + item->send_type = CE_SIMPLE_BUFFER_TYPE; + item->data = buffer; + item->u.nbytes = nbytes; + item->flags = flags; + sl->num_items = num_items+1; + return A_OK; +} + +int +CE_sendlist_send(struct CE_handle *copyeng, + void *per_transfer_context, + struct CE_sendlist *sendlist, + unsigned int transfer_id) +{ + int status = -ENOMEM; + struct CE_sendlist_s *sl = (struct CE_sendlist_s *)sendlist; + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *src_ring = CE_state->src_ring; + struct hif_pci_softc *sc = CE_state->sc; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int num_items = sl->num_items; + unsigned int sw_index ; + unsigned int write_index ; + + A_ASSERT((num_items > 0) && (num_items < src_ring->nentries)); + + adf_os_spin_lock_bh(&sc->target_lock); + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + + if (CE_RING_DELTA(nentries_mask, write_index, sw_index-1) >= num_items) { + struct CE_sendlist_item *item; + int i; + + /* handle all but the last item uniformly */ + for (i = 0; i < num_items-1; i++) { + item = &sl->item[i]; + /* TBDXXX: Support extensible sendlist_types? */ + A_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE); + status = CE_send_nolock(copyeng, CE_SENDLIST_ITEM_CTXT, + (CE_addr_t)item->data, item->u.nbytes, + transfer_id, + item->flags | CE_SEND_FLAG_GATHER); + A_ASSERT(status == A_OK); + } + /* provide valid context pointer for final item */ + item = &sl->item[i]; + /* TBDXXX: Support extensible sendlist_types? */ + A_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE); + status = CE_send_nolock(copyeng, per_transfer_context, + (CE_addr_t)item->data, item->u.nbytes, + transfer_id, item->flags); + A_ASSERT(status == A_OK); + } else { + /* + * Probably not worth the additional complexity to support + * partial sends with continuation or notification. We expect + * to use large rings and small sendlists. If we can't handle + * the entire request at once, punt it back to the caller. + */ + } + adf_os_spin_unlock_bh(&sc->target_lock); + + return status; +} + +int +CE_recv_buf_enqueue(struct CE_handle *copyeng, + void *per_recv_context, + CE_addr_t buffer) +{ + int status; + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *dest_ring = CE_state->dest_ring; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + struct hif_pci_softc *sc = CE_state->sc; + A_target_id_t targid = TARGID(sc); + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int write_index ; + unsigned int sw_index; + int val = 0; + + adf_os_spin_lock_bh(&sc->target_lock); + write_index = dest_ring->write_index; + sw_index = dest_ring->sw_index; + + A_TARGET_ACCESS_BEGIN_RET_EXT(targid, val); + if (val == -1) { + adf_os_spin_unlock_bh(&sc->target_lock); + return val; + } + + if (CE_RING_DELTA(nentries_mask, write_index, sw_index-1) > 0) { + struct CE_dest_desc *dest_ring_base = (struct CE_dest_desc *)dest_ring->base_addr_owner_space; + struct CE_dest_desc *dest_desc = CE_DEST_RING_TO_DESC(dest_ring_base, write_index); + + /* Update destination descriptor */ + dest_desc->dest_ptr = buffer; + dest_desc->info.nbytes = 0; /* NB: Enable CE_completed_recv_next_nolock to + protect against race between DRRI update and + desc update */ + + dest_ring->per_transfer_context[write_index] = per_recv_context; + + /* Update Destination Ring Write Index */ + write_index = CE_RING_IDX_INCR(nentries_mask, write_index); + CE_DEST_RING_WRITE_IDX_SET(targid, ctrl_addr, write_index); + dest_ring->write_index = write_index; + status = A_OK; + } else { + status = A_ERROR; + } + A_TARGET_ACCESS_END_RET_EXT(targid, val); + if (val == -1) { + adf_os_spin_unlock_bh(&sc->target_lock); + return val; + } + + adf_os_spin_unlock_bh(&sc->target_lock); + + return status; +} + +void +CE_send_watermarks_set(struct CE_handle *copyeng, + unsigned int low_alert_nentries, + unsigned int high_alert_nentries) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + struct hif_pci_softc *sc = CE_state->sc; + A_target_id_t targid = TARGID(sc); + + adf_os_spin_lock(&sc->target_lock); + CE_SRC_RING_LOWMARK_SET(targid, ctrl_addr, low_alert_nentries); + CE_SRC_RING_HIGHMARK_SET(targid, ctrl_addr, high_alert_nentries); + adf_os_spin_unlock(&sc->target_lock); +} + +void +CE_recv_watermarks_set(struct CE_handle *copyeng, + unsigned int low_alert_nentries, + unsigned int high_alert_nentries) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + struct hif_pci_softc *sc = CE_state->sc; + A_target_id_t targid = TARGID(sc); + + adf_os_spin_lock(&sc->target_lock); + CE_DEST_RING_LOWMARK_SET(targid, ctrl_addr, low_alert_nentries); + CE_DEST_RING_HIGHMARK_SET(targid, ctrl_addr, high_alert_nentries); + adf_os_spin_unlock(&sc->target_lock); +} + +unsigned int +CE_send_entries_avail(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *src_ring = CE_state->src_ring; + struct hif_pci_softc *sc = CE_state->sc; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index; + unsigned int write_index; + + adf_os_spin_lock(&sc->target_lock); + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + adf_os_spin_unlock(&sc->target_lock); + + return CE_RING_DELTA(nentries_mask, write_index, sw_index-1); +} + +unsigned int +CE_recv_entries_avail(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *dest_ring = CE_state->dest_ring; + struct hif_pci_softc *sc = CE_state->sc; + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int sw_index; + unsigned int write_index; + + adf_os_spin_lock(&sc->target_lock); + sw_index = dest_ring->sw_index; + write_index = dest_ring->write_index; + adf_os_spin_unlock(&sc->target_lock); + + return CE_RING_DELTA(nentries_mask, write_index, sw_index-1); +} + +/* + * Guts of CE_send_entries_done. + * The caller takes responsibility for any necessary locking. + */ +unsigned int +CE_send_entries_done_nolock(struct hif_pci_softc *sc, struct CE_state *CE_state) +{ + struct CE_ring_state *src_ring = CE_state->src_ring; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + A_target_id_t targid = TARGID(sc); + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index; + unsigned int read_index; + + sw_index = src_ring->sw_index; + read_index = CE_SRC_RING_READ_IDX_GET(targid, ctrl_addr); + + return CE_RING_DELTA(nentries_mask, sw_index, read_index); +} + +unsigned int +CE_send_entries_done(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + unsigned int nentries; + + adf_os_spin_lock(&sc->target_lock); + nentries = CE_send_entries_done_nolock(sc, CE_state); + adf_os_spin_unlock(&sc->target_lock); + + return nentries; +} + +/* + * Guts of CE_recv_entries_done. + * The caller takes responsibility for any necessary locking. + */ +unsigned int +CE_recv_entries_done_nolock(struct hif_pci_softc *sc, struct CE_state *CE_state) +{ + struct CE_ring_state *dest_ring = CE_state->dest_ring; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + A_target_id_t targid = TARGID(sc); + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int sw_index; + unsigned int read_index; + + sw_index = dest_ring->sw_index; + read_index = CE_DEST_RING_READ_IDX_GET(targid, ctrl_addr); + + return CE_RING_DELTA(nentries_mask, sw_index, read_index); +} + +unsigned int +CE_recv_entries_done(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + unsigned int nentries; + + adf_os_spin_lock(&sc->target_lock); + nentries = CE_recv_entries_done_nolock(sc, CE_state); + adf_os_spin_unlock(&sc->target_lock); + + return nentries; +} + +/* Debug support */ +void *ce_debug_cmplrn_context; /* completed recv next context */ +void *ce_debug_cnclsn_context; /* cancel send next context */ +void *ce_debug_rvkrn_context; /* revoke receive next context */ +void *ce_debug_cmplsn_context; /* completed send next context */ + + +/* + * Guts of CE_completed_recv_next. + * The caller takes responsibility for any necessary locking. + */ +int +CE_completed_recv_next_nolock(struct CE_state *CE_state, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp) +{ + int status; + struct CE_ring_state *dest_ring = CE_state->dest_ring; + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int sw_index = dest_ring->sw_index; + + struct CE_dest_desc *dest_ring_base = (struct CE_dest_desc *)dest_ring->base_addr_owner_space; + struct CE_dest_desc *dest_desc = CE_DEST_RING_TO_DESC(dest_ring_base, sw_index); + int nbytes; + struct dest_desc_info dest_desc_info; + + /* + * By copying the dest_desc_info element to local memory, we could + * avoid extra memory read from non-cachable memory. + */ + dest_desc_info = dest_desc->info; + nbytes = dest_desc_info.nbytes; + if (nbytes == 0) { + /* + * This closes a relatively unusual race where the Host + * sees the updated DRRI before the update to the + * corresponding descriptor has completed. We treat this + * as a descriptor that is not yet done. + */ + status = A_ERROR; + goto done; + } + + dest_desc->info.nbytes = 0; + + /* Return data from completed destination descriptor */ + *bufferp = (CE_addr_t)(dest_desc->dest_ptr); + *nbytesp = nbytes; + *transfer_idp = dest_desc_info.meta_data; + *flagsp = (dest_desc_info.byte_swap) ? CE_RECV_FLAG_SWAPPED : 0; + + if (per_CE_contextp) { + *per_CE_contextp = CE_state->recv_context; + } + + ce_debug_cmplrn_context = dest_ring->per_transfer_context[sw_index]; + if (per_transfer_contextp) { + *per_transfer_contextp = ce_debug_cmplrn_context; + } + dest_ring->per_transfer_context[sw_index] = 0; /* sanity */ + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + dest_ring->sw_index = sw_index; + status = A_OK; + +done: + return status; +} + +int +CE_completed_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + int status; + + + adf_os_spin_lock_bh(&sc->target_lock); + status = CE_completed_recv_next_nolock(CE_state, per_CE_contextp, per_transfer_contextp, + bufferp, nbytesp, transfer_idp, flagsp); + adf_os_spin_unlock_bh(&sc->target_lock); + + return status; +} + +/* NB: Modeled after CE_completed_recv_next_nolock */ +A_STATUS +CE_revoke_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp) +{ + struct CE_state *CE_state; + struct CE_ring_state *dest_ring; + unsigned int nentries_mask; + unsigned int sw_index; + unsigned int write_index; + A_STATUS status; + struct hif_pci_softc *sc; + + CE_state = (struct CE_state *)copyeng; + dest_ring = CE_state->dest_ring; + if (!dest_ring) { + return A_ERROR; + } + + sc = CE_state->sc; + adf_os_spin_lock(&sc->target_lock); + nentries_mask = dest_ring->nentries_mask; + sw_index = dest_ring->sw_index; + write_index = dest_ring->write_index; + if (write_index != sw_index) { + struct CE_dest_desc *dest_ring_base = (struct CE_dest_desc *)dest_ring->base_addr_owner_space; + struct CE_dest_desc *dest_desc = CE_DEST_RING_TO_DESC(dest_ring_base, sw_index); + + /* Return data from completed destination descriptor */ + *bufferp = (CE_addr_t)(dest_desc->dest_ptr); + + if (per_CE_contextp) { + *per_CE_contextp = CE_state->recv_context; + } + + ce_debug_rvkrn_context = dest_ring->per_transfer_context[sw_index]; + if (per_transfer_contextp) { + *per_transfer_contextp = ce_debug_rvkrn_context; + } + dest_ring->per_transfer_context[sw_index] = 0; /* sanity */ + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + dest_ring->sw_index = sw_index; + status = A_OK; + } else { + status = A_ERROR; + } + adf_os_spin_unlock(&sc->target_lock); + + return status; +} + +/* + * Guts of CE_completed_send_next. + * The caller takes responsibility for any necessary locking. + */ +int +CE_completed_send_next_nolock(struct CE_state *CE_state, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx) +{ + int status = A_ERROR; + struct CE_ring_state *src_ring = CE_state->src_ring; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + struct hif_pci_softc *sc = CE_state->sc; + A_target_id_t targid = TARGID(sc); + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int read_index; + + + if (src_ring->hw_index == sw_index) { + /* + * The SW completion index has caught up with the cached + * version of the HW completion index. + * Update the cached HW completion index to see whether + * the SW has really caught up to the HW, or if the cached + * value of the HW index has become stale. + */ + A_TARGET_ACCESS_BEGIN_RET(targid); + src_ring->hw_index = CE_SRC_RING_READ_IDX_GET(targid, ctrl_addr); + A_TARGET_ACCESS_END_RET(targid); + } + read_index = src_ring->hw_index; + + if (sw_idx) + *sw_idx = sw_index; + + if (hw_idx) + *hw_idx = read_index; + + if ((read_index != sw_index) && (read_index != 0xffffffff)) { + struct CE_src_desc *shadow_base = (struct CE_src_desc *)src_ring->shadow_base; + struct CE_src_desc *shadow_src_desc = CE_SRC_RING_TO_DESC(shadow_base, sw_index); + + /* Return data from completed source descriptor */ + *bufferp = (CE_addr_t)(shadow_src_desc->src_ptr); + *nbytesp = shadow_src_desc->nbytes; + *transfer_idp = shadow_src_desc->meta_data; + + if (per_CE_contextp) { + *per_CE_contextp = CE_state->send_context; + } + + ce_debug_cmplsn_context = src_ring->per_transfer_context[sw_index]; + if (per_transfer_contextp) { + *per_transfer_contextp = ce_debug_cmplsn_context; + } + src_ring->per_transfer_context[sw_index] = 0; /* sanity */ + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + src_ring->sw_index = sw_index; + status = A_OK; + } + + return status; +} + +/* NB: Modeled after CE_completed_send_next */ +A_STATUS +CE_cancel_send_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp) +{ + struct CE_state *CE_state; + struct CE_ring_state *src_ring; + unsigned int nentries_mask; + unsigned int sw_index; + unsigned int write_index; + A_STATUS status; + struct hif_pci_softc *sc; + + CE_state = (struct CE_state *)copyeng; + src_ring = CE_state->src_ring; + if (!src_ring) { + return A_ERROR; + } + + sc = CE_state->sc; + adf_os_spin_lock(&sc->target_lock); + nentries_mask = src_ring->nentries_mask; + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + + if (write_index != sw_index) { + struct CE_src_desc *src_ring_base = (struct CE_src_desc *)src_ring->base_addr_owner_space; + struct CE_src_desc *src_desc = CE_SRC_RING_TO_DESC(src_ring_base, sw_index); + + /* Return data from completed source descriptor */ + *bufferp = (CE_addr_t)(src_desc->src_ptr); + *nbytesp = src_desc->nbytes; + *transfer_idp = src_desc->meta_data; + + if (per_CE_contextp) { + *per_CE_contextp = CE_state->send_context; + } + + ce_debug_cnclsn_context = src_ring->per_transfer_context[sw_index]; + if (per_transfer_contextp) { + *per_transfer_contextp = ce_debug_cnclsn_context; + } + src_ring->per_transfer_context[sw_index] = 0; /* sanity */ + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + src_ring->sw_index = sw_index; + status = A_OK; + } else { + status = A_ERROR; + } + adf_os_spin_unlock(&sc->target_lock); + + return status; +} + +/* Shift bits to convert IS_*_RING_*_WATERMARK_MASK to CE_WM_FLAG_*_* */ +#define CE_WM_SHFT 1 + + +int +CE_completed_send_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + int status; + + + adf_os_spin_lock_bh(&sc->target_lock); + status = CE_completed_send_next_nolock(CE_state, per_CE_contextp, per_transfer_contextp, + bufferp, nbytesp, transfer_idp, + sw_idx, hw_idx); + adf_os_spin_unlock_bh(&sc->target_lock); + + return status; +} + + +#ifdef ATH_11AC_TXCOMPACT +/* CE engine descriptor reap + Similar to CE_per_engine_service , Only difference is CE_per_engine_service + does recieve and reaping of completed descriptor , + This function only handles reaping of Tx complete descriptor. + The Function is called from threshold reap poll routine HIFSendCompleteCheck + So should not countain recieve functionality within it . + */ + +void +CE_per_engine_servicereap(struct hif_pci_softc *sc, unsigned int CE_id) +{ + struct CE_state *CE_state = sc->CE_id_to_state[CE_id]; + A_target_id_t targid = TARGID(sc); + void *CE_context; + void *transfer_context; + CE_addr_t buf; + unsigned int nbytes; + unsigned int id; + unsigned int sw_idx, hw_idx; + + A_TARGET_ACCESS_BEGIN(targid); + + /* Since this function is called from both user context and + * tasklet context the spinlock has to lock the bottom halves. + * This fix assumes that ATH_11AC_TXCOMPACT flag is always + * enabled in TX polling mode. If this is not the case, more + * bottom halve spin lock changes are needed. Due to data path + * performance concern, after internal discussion we've decided + * to make minimum change, i.e., only address the issue occurred + * in this function. The possible negative effect of this minimum + * change is that, in the future, if some other function will also + * be opened to let the user context to use, those cases need to be + * addressed by change spin_lock to spin_lock_bh also. */ + + adf_os_spin_lock_bh(&sc->target_lock); + + if (CE_state->send_cb) { + { + /* Pop completed send buffers and call the registered send callback for each */ + while (CE_completed_send_next_nolock(CE_state, &CE_context, &transfer_context, + &buf, &nbytes, &id, &sw_idx, &hw_idx) == A_OK) + { + if(CE_id != CE_HTT_H2T_MSG){ + adf_os_spin_unlock_bh(&sc->target_lock); + CE_state->send_cb((struct CE_handle *)CE_state, CE_context, transfer_context, buf, nbytes, id, + sw_idx, hw_idx); + adf_os_spin_lock_bh(&sc->target_lock); + }else{ + struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *)CE_context; + + adf_os_spin_lock_bh(&pipe_info->completion_freeq_lock); + pipe_info->num_sends_allowed++; + adf_os_spin_unlock_bh(&pipe_info->completion_freeq_lock); + } + } + } + } + + adf_os_spin_unlock_bh(&sc->target_lock); + A_TARGET_ACCESS_END(targid); +} + +#endif /*ATH_11AC_TXCOMPACT*/ + +/* + * Number of times to check for any pending tx/rx completion on + * a copy engine, this count should be big enough. Once we hit + * this threashold we'll not check for any Tx/Rx comlpetion in same + * interrupt handling. Note that this threashold is only used for + * Rx interrupt processing, this can be used tor Tx as well if we + * suspect any infinite loop in checking for pending Tx completion. + */ +#define CE_TXRX_COMP_CHECK_THRESHOLD 20 + +/* + * Guts of interrupt handler for per-engine interrupts on a particular CE. + * + * Invokes registered callbacks for recv_complete, + * send_complete, and watermarks. + */ +void +CE_per_engine_service(struct hif_pci_softc *sc, unsigned int CE_id) +{ + struct CE_state *CE_state = sc->CE_id_to_state[CE_id]; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + A_target_id_t targid = TARGID(sc); + void *CE_context; + void *transfer_context; + CE_addr_t buf; + unsigned int nbytes; + unsigned int id; + unsigned int flags; + u_int32_t CE_int_status; + unsigned int more_comp_cnt = 0; + unsigned int more_snd_comp_cnt = 0; + unsigned int sw_idx, hw_idx; + + A_TARGET_ACCESS_BEGIN(targid); + + adf_os_spin_lock(&sc->target_lock); + + /* Clear force_break flag and re-initialize receive_count to 0 */ + sc->receive_count = 0; + sc->force_break = 0; +more_completions: + if (CE_state->recv_cb) { + + /* Pop completed recv buffers and call the registered recv callback for each */ + while (CE_completed_recv_next_nolock(CE_state, &CE_context, &transfer_context, + &buf, &nbytes, &id, &flags) == A_OK) + { + adf_os_spin_unlock(&sc->target_lock); + CE_state->recv_cb((struct CE_handle *)CE_state, CE_context, transfer_context, + buf, nbytes, id, flags); + + /* + * EV #112693 - [Peregrine][ES1][WB342][Win8x86][Performance] BSoD_0x133 occurred in VHT80 UDP_DL + * Break out DPC by force if number of loops in HIF_PCI_CE_recv_data reaches MAX_NUM_OF_RECEIVES to avoid spending too long time in DPC for each interrupt handling. + * Schedule another DPC to avoid data loss if we had taken force-break action before + * Apply to Windows OS only currently, Linux/MAC os can expand to their platform if necessary + */ + + /* Break the receive processes by force if force_break set up */ + if (adf_os_unlikely(sc->force_break)) + { + adf_os_atomic_set(&CE_state->rx_pending, 1); + CE_ENGINE_INT_STATUS_CLEAR(targid, ctrl_addr, HOST_IS_COPY_COMPLETE_MASK); + A_TARGET_ACCESS_END(targid); + return; + } + adf_os_spin_lock(&sc->target_lock); + } + } + + /* + * Attention: We may experience potential infinite loop for below While Loop during Sending Stress test + * Resolve the same way as Receive Case (Refer to EV #112693) + */ + + if (CE_state->send_cb) { + /* Pop completed send buffers and call the registered send callback for each */ + +#ifdef ATH_11AC_TXCOMPACT + while (CE_completed_send_next_nolock(CE_state, &CE_context, &transfer_context, + &buf, &nbytes, &id, &sw_idx, &hw_idx) == A_OK){ + + if(CE_id != CE_HTT_H2T_MSG || + WLAN_IS_EPPING_ENABLED(vos_get_conparam())){ + adf_os_spin_unlock(&sc->target_lock); + CE_state->send_cb((struct CE_handle *)CE_state, CE_context, transfer_context, buf, nbytes, id, + sw_idx, hw_idx); + adf_os_spin_lock(&sc->target_lock); + }else{ + struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *)CE_context; + + adf_os_spin_lock(&pipe_info->completion_freeq_lock); + pipe_info->num_sends_allowed++; + adf_os_spin_unlock(&pipe_info->completion_freeq_lock); + } + } +#else /*ATH_11AC_TXCOMPACT*/ + while (CE_completed_send_next_nolock(CE_state, &CE_context, &transfer_context, + &buf, &nbytes, &id, &sw_idx, &hw_idx) == A_OK){ + adf_os_spin_unlock(&sc->target_lock); + CE_state->send_cb((struct CE_handle *)CE_state, CE_context, transfer_context, buf, nbytes, id, + sw_idx, hw_idx); + adf_os_spin_lock(&sc->target_lock); + } +#endif /*ATH_11AC_TXCOMPACT*/ + } + +more_watermarks: + if (CE_state->misc_cbs) { + CE_int_status = CE_ENGINE_INT_STATUS_GET(targid, ctrl_addr); + if (CE_int_status & CE_WATERMARK_MASK) { + if (CE_state->watermark_cb) { + + adf_os_spin_unlock(&sc->target_lock); + /* Convert HW IS bits to software flags */ + flags = (CE_int_status & CE_WATERMARK_MASK) >> CE_WM_SHFT; + + CE_state->watermark_cb((struct CE_handle *)CE_state, CE_state->wm_context, flags); + adf_os_spin_lock(&sc->target_lock); + } + } + } + + /* + * Clear the misc interrupts (watermark) that were handled above, + * and that will be checked again below. + * Clear and check for copy-complete interrupts again, just in case + * more copy completions happened while the misc interrupts were being + * handled. + */ + CE_ENGINE_INT_STATUS_CLEAR(targid, ctrl_addr, CE_WATERMARK_MASK | HOST_IS_COPY_COMPLETE_MASK); + + /* + * Now that per-engine interrupts are cleared, verify that + * no recv interrupts arrive while processing send interrupts, + * and no recv or send interrupts happened while processing + * misc interrupts.Go back and check again.Keep checking until + * we find no more events to process. + */ + if (CE_state->recv_cb && CE_recv_entries_done_nolock(sc, CE_state)) { + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam()) || + more_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) { + goto more_completions; + } else { + adf_os_print("%s:Potential infinite loop detected during Rx processing" + "nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x\n", + __func__, CE_state->dest_ring->nentries_mask, + CE_state->dest_ring->sw_index, + CE_DEST_RING_READ_IDX_GET(targid, CE_state->ctrl_addr)); + } + } + + if (CE_state->send_cb && CE_send_entries_done_nolock(sc, CE_state)) { + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam()) || + more_snd_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) { + goto more_completions; + } else { + adf_os_print("%s:Potential infinite loop detected during send completion" + "nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x\n", + __func__, CE_state->src_ring->nentries_mask, + CE_state->src_ring->sw_index, + CE_SRC_RING_READ_IDX_GET(targid, CE_state->ctrl_addr)); + } + } + + + if (CE_state->misc_cbs) { + CE_int_status = CE_ENGINE_INT_STATUS_GET(targid, ctrl_addr); + if (CE_int_status & CE_WATERMARK_MASK) { + if (CE_state->watermark_cb) { + goto more_watermarks; + } + } + } + + adf_os_spin_unlock(&sc->target_lock); + adf_os_atomic_set(&CE_state->rx_pending, 0); + A_TARGET_ACCESS_END(targid); +} + +static void +CE_poll_timeout(void *arg) +{ + struct CE_state *CE_state = (struct CE_state *) arg; + if (CE_state->timer_inited) { + CE_per_engine_service(CE_state->sc, CE_state->id); + adf_os_timer_mod(&CE_state->poll_timer, CE_POLL_TIMEOUT); + } +} + + +/* + * Handler for per-engine interrupts on ALL active CEs. + * This is used in cases where the system is sharing a + * single interrput for all CEs + */ + +void +CE_per_engine_service_any(int irq, void *arg) +{ + struct hif_pci_softc *sc = arg; + A_target_id_t targid = TARGID(sc); + int CE_id; + A_UINT32 intr_summary; + + A_TARGET_ACCESS_BEGIN(targid); + if (!adf_os_atomic_read(&sc->tasklet_from_intr)) { + for (CE_id=0; CE_id < sc->ce_count; CE_id++) { + struct CE_state *CE_state = sc->CE_id_to_state[CE_id]; + if (adf_os_atomic_read(&CE_state->rx_pending)) { + adf_os_atomic_set(&CE_state->rx_pending, 0); + CE_per_engine_service(sc, CE_id); + } + } + + A_TARGET_ACCESS_END(targid); + return; + } + + intr_summary = CE_INTERRUPT_SUMMARY(targid); + + for (CE_id=0; intr_summary && (CE_id < sc->ce_count); CE_id++) { + if (intr_summary & (1<ctrl_addr; + struct hif_pci_softc *sc = CE_state->sc; + A_target_id_t targid = TARGID(sc); + CE_state->disable_copy_compl_intr = disable_copy_compl_intr; + + A_TARGET_ACCESS_BEGIN(targid); + if ((!disable_copy_compl_intr) && + (CE_state->send_cb || CE_state->recv_cb)) + { + CE_COPY_COMPLETE_INTR_ENABLE(targid, ctrl_addr); + } else { + CE_COPY_COMPLETE_INTR_DISABLE(targid, ctrl_addr); + } + + if (CE_state->watermark_cb) { + CE_WATERMARK_INTR_ENABLE(targid, ctrl_addr); + } else { + CE_WATERMARK_INTR_DISABLE(targid, ctrl_addr); + } + A_TARGET_ACCESS_END(targid); + +} + +/*Iterate the CE_state list and disable the compl interrupt if it has been registered already.*/ +void CE_disable_any_copy_compl_intr_nolock(struct hif_pci_softc *sc) +{ + A_target_id_t targid = TARGID(sc); + int CE_id; + + A_TARGET_ACCESS_BEGIN(targid); + for (CE_id=0; CE_id < sc->ce_count; CE_id++) { + struct CE_state *CE_state = sc->CE_id_to_state[CE_id]; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + + /* if the interrupt is currently enabled, disable it */ + if (!CE_state->disable_copy_compl_intr && (CE_state->send_cb || CE_state->recv_cb)) { + CE_COPY_COMPLETE_INTR_DISABLE(targid, ctrl_addr); + } + + if (CE_state->watermark_cb) { + CE_WATERMARK_INTR_DISABLE(targid, ctrl_addr); + } + } + A_TARGET_ACCESS_END(targid); +} + +void CE_enable_any_copy_compl_intr_nolock(struct hif_pci_softc *sc) +{ + A_target_id_t targid = TARGID(sc); + int CE_id; + + A_TARGET_ACCESS_BEGIN(targid); + for (CE_id=0; CE_id < sc->ce_count; CE_id++) { + struct CE_state *CE_state = sc->CE_id_to_state[CE_id]; + u_int32_t ctrl_addr = CE_state->ctrl_addr; + + /* + * If the CE is supposed to have copy complete interrupts enabled + * (i.e. there a callback registered, and the "disable" flag is not set), + * then re-enable the interrupt. + */ + if (!CE_state->disable_copy_compl_intr && (CE_state->send_cb || CE_state->recv_cb)) { + CE_COPY_COMPLETE_INTR_ENABLE(targid, ctrl_addr); + } + + if (CE_state->watermark_cb) { + CE_WATERMARK_INTR_ENABLE(targid, ctrl_addr); + } + } + A_TARGET_ACCESS_END(targid); +} + +void +CE_disable_any_copy_compl_intr(struct hif_pci_softc *sc) +{ + adf_os_spin_lock(&sc->target_lock); + CE_disable_any_copy_compl_intr_nolock(sc); + adf_os_spin_unlock(&sc->target_lock); +} + +/*Re-enable the copy compl interrupt if it has not been disabled before.*/ +void +CE_enable_any_copy_compl_intr(struct hif_pci_softc *sc) +{ + adf_os_spin_lock(&sc->target_lock); + CE_enable_any_copy_compl_intr_nolock(sc); + adf_os_spin_unlock(&sc->target_lock); +} + +void +CE_send_cb_register(struct CE_handle *copyeng, + CE_send_cb fn_ptr, + void *CE_send_context, + int disable_interrupts) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + + adf_os_spin_lock(&sc->target_lock); + CE_state->send_cb = fn_ptr; + CE_state->send_context = CE_send_context; + CE_per_engine_handler_adjust(CE_state, disable_interrupts); + adf_os_spin_unlock(&sc->target_lock); +} + +void +CE_recv_cb_register(struct CE_handle *copyeng, + CE_recv_cb fn_ptr, + void *CE_recv_context, + int disable_interrupts) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + + adf_os_spin_lock(&sc->target_lock); + CE_state->recv_cb = fn_ptr; + CE_state->recv_context = CE_recv_context; + CE_per_engine_handler_adjust(CE_state, disable_interrupts); + adf_os_spin_unlock(&sc->target_lock); +} + +void +CE_watermark_cb_register(struct CE_handle *copyeng, + CE_watermark_cb fn_ptr, + void *CE_wm_context) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct hif_pci_softc *sc = CE_state->sc; + + adf_os_spin_lock(&sc->target_lock); + CE_state->watermark_cb = fn_ptr; + CE_state->wm_context = CE_wm_context; + CE_per_engine_handler_adjust(CE_state, 0); + if (fn_ptr) { + CE_state->misc_cbs = 1; + } + adf_os_spin_unlock(&sc->target_lock); +} + +static unsigned int +roundup_pwr2(unsigned int n) +{ + int i; + unsigned int test_pwr2; + + if (!(n & (n-1))) { + return n; /* already a power of 2 */ + } + + test_pwr2 = 4; + for (i=0; i<29; i++) { + if (test_pwr2 > n) { + return test_pwr2; + } + test_pwr2 = test_pwr2 << 1; + } + + A_ASSERT(0); /* n too large */ + return 0; +} + +bool CE_get_rx_pending(struct hif_pci_softc *sc) +{ + int CE_id; + + for (CE_id=0; CE_id < sc->ce_count; CE_id++) { + struct CE_state *CE_state = sc->CE_id_to_state[CE_id]; + if (adf_os_atomic_read(&CE_state->rx_pending)) + return true; + } + + return false; +} +/* + * Initialize a Copy Engine based on caller-supplied attributes. + * This may be called once to initialize both source and destination + * rings or it may be called twice for separate source and destination + * initialization. It may be that only one side or the other is + * initialized by software/firmware. + */ +struct CE_handle * +CE_init(struct hif_pci_softc *sc, + unsigned int CE_id, + struct CE_attr *attr) +{ + struct CE_state *CE_state; + u_int32_t ctrl_addr; + A_target_id_t targid; + unsigned int nentries; + adf_os_dma_addr_t base_addr; + struct ol_softc *scn = sc->ol_sc; + bool malloc_CE_state = false; + bool malloc_src_ring = false; + + A_ASSERT(CE_id < sc->ce_count); + ctrl_addr = CE_BASE_ADDRESS(CE_id); + adf_os_spin_lock(&sc->target_lock); + CE_state = sc->CE_id_to_state[CE_id]; + + + if (!CE_state) { + adf_os_spin_unlock(&sc->target_lock); + CE_state = (struct CE_state *)A_MALLOC(sizeof(*CE_state)); + if (!CE_state) { + dev_err(&sc->pdev->dev, "ath ERROR: CE_state has no mem\n"); + return NULL; + } else + malloc_CE_state = true; + A_MEMZERO(CE_state, sizeof(*CE_state)); + adf_os_spin_lock(&sc->target_lock); + if (!sc->CE_id_to_state[CE_id]) { /* re-check under lock */ + sc->CE_id_to_state[CE_id] = CE_state; + + CE_state->sc = sc; + CE_state->id = CE_id; + CE_state->ctrl_addr = ctrl_addr; + CE_state->state = CE_RUNNING; + CE_state->attr_flags = attr->flags; /* Save attribute flags */ + } else { + /* + * We released target_lock in order to allocate CE state, + * but someone else beat us to it. Continue, using that + * CE_state (and free the one we allocated). + */ + A_FREE(CE_state); + malloc_CE_state = false; + CE_state = sc->CE_id_to_state[CE_id]; + } + } + adf_os_spin_unlock(&sc->target_lock); + + adf_os_atomic_init(&CE_state->rx_pending); + if (attr == NULL) { + /* Already initialized; caller wants the handle */ + return (struct CE_handle *)CE_state; + } + + targid = TARGID(sc); + + if (CE_state->src_sz_max) { + A_ASSERT(CE_state->src_sz_max == attr->src_sz_max); + } else { + CE_state->src_sz_max = attr->src_sz_max; + } + + /* source ring setup */ + nentries = attr->src_nentries; + if (nentries) { + struct CE_ring_state *src_ring; + unsigned CE_nbytes; + char *ptr; + + nentries = roundup_pwr2(nentries); + if (CE_state->src_ring) { + A_ASSERT(CE_state->src_ring->nentries == nentries); + } else { + CE_nbytes = sizeof(struct CE_ring_state) + + (nentries * sizeof(void *)); /* per-send context */ + ptr = A_MALLOC(CE_nbytes); + if (!ptr) { + /* cannot allocate src ring. If the CE_state is allocated + * locally free CE_State and return error. */ + dev_err(&sc->pdev->dev, "ath ERROR: src ring has no mem\n"); + if (malloc_CE_state) { + /* allocated CE_state locally */ + adf_os_spin_lock(&sc->target_lock); + sc->CE_id_to_state[CE_id]= NULL; + adf_os_spin_unlock(&sc->target_lock); + A_FREE(CE_state); + malloc_CE_state = false; + } + return NULL; + } else { + /* we can allocate src ring. + * Mark that the src ring is allocated locally */ + malloc_src_ring = true; + } + A_MEMZERO(ptr, CE_nbytes); + + src_ring = CE_state->src_ring = (struct CE_ring_state *)ptr; + ptr += sizeof(struct CE_ring_state); + src_ring->nentries = nentries; + src_ring->nentries_mask = nentries-1; + A_TARGET_ACCESS_BEGIN_RET_PTR(targid); + src_ring->hw_index = + src_ring->sw_index = CE_SRC_RING_READ_IDX_GET(targid, ctrl_addr); + src_ring->write_index = CE_SRC_RING_WRITE_IDX_GET(targid, ctrl_addr); + A_TARGET_ACCESS_END_RET_PTR(targid); + src_ring->low_water_mark_nentries = 0; + src_ring->high_water_mark_nentries = nentries; + src_ring->per_transfer_context = (void **)ptr; + + /* Legacy platforms that do not support cache coherent DMA are unsupported */ + src_ring->base_addr_owner_space_unaligned = + pci_alloc_consistent(scn->sc_osdev->bdev, + (nentries * sizeof(struct CE_src_desc) + CE_DESC_RING_ALIGN), + &base_addr); + if (src_ring->base_addr_owner_space_unaligned == NULL) { + dev_err(&sc->pdev->dev, "ath ERROR: src ring has no DMA mem\n"); + goto error_no_dma_mem; + } + src_ring->base_addr_CE_space_unaligned = base_addr; + + + if (src_ring->base_addr_CE_space_unaligned & (CE_DESC_RING_ALIGN-1)) { + + src_ring->base_addr_CE_space = (src_ring->base_addr_CE_space_unaligned + + CE_DESC_RING_ALIGN-1) & ~(CE_DESC_RING_ALIGN-1); + + src_ring->base_addr_owner_space = (void *)(((size_t)src_ring->base_addr_owner_space_unaligned + + CE_DESC_RING_ALIGN-1) & ~(CE_DESC_RING_ALIGN-1)); + } else { + src_ring->base_addr_CE_space = src_ring->base_addr_CE_space_unaligned; + src_ring->base_addr_owner_space = src_ring->base_addr_owner_space_unaligned; + } + /* + * Also allocate a shadow src ring in regular mem to use for + * faster access. + */ + src_ring->shadow_base_unaligned = A_MALLOC( + nentries * sizeof(struct CE_src_desc) + CE_DESC_RING_ALIGN); + if (src_ring->shadow_base_unaligned == NULL) { + dev_err(&sc->pdev->dev, "ath ERROR: src ring has no shadow_base mem\n"); + goto error_no_dma_mem; + } + src_ring->shadow_base = (struct CE_src_desc *) + (((size_t) src_ring->shadow_base_unaligned + + CE_DESC_RING_ALIGN-1) & ~(CE_DESC_RING_ALIGN-1)); + + A_TARGET_ACCESS_BEGIN_RET_PTR(targid); + CE_SRC_RING_BASE_ADDR_SET(targid, ctrl_addr, src_ring->base_addr_CE_space); + CE_SRC_RING_SZ_SET(targid, ctrl_addr, nentries); + CE_SRC_RING_DMAX_SET(targid, ctrl_addr, attr->src_sz_max); +#ifdef BIG_ENDIAN_HOST + /* Enable source ring byte swap for big endian host */ + CE_SRC_RING_BYTE_SWAP_SET(targid, ctrl_addr, 1); +#endif + CE_SRC_RING_LOWMARK_SET(targid, ctrl_addr, 0); + CE_SRC_RING_HIGHMARK_SET(targid, ctrl_addr, nentries); + A_TARGET_ACCESS_END_RET_PTR(targid); + } + } + + /* destination ring setup */ + nentries = attr->dest_nentries; + if (nentries) { + struct CE_ring_state *dest_ring; + unsigned CE_nbytes; + char *ptr; + + nentries = roundup_pwr2(nentries); + if (CE_state->dest_ring) { + A_ASSERT(CE_state->dest_ring->nentries == nentries); + } else { + CE_nbytes = sizeof(struct CE_ring_state) + + (nentries * sizeof(void *)); /* per-recv context */ + ptr = A_MALLOC(CE_nbytes); + if (!ptr) { + /* cannot allocate dst ring. If the CE_state or src ring is allocated + * locally free CE_State and src ring and return error. */ + dev_err(&sc->pdev->dev, "ath ERROR: dest ring has no mem\n"); + if (malloc_src_ring) { + A_FREE(CE_state->src_ring); + CE_state->src_ring= NULL; + malloc_src_ring = false; + } + if (malloc_CE_state) { + /* allocated CE_state locally */ + adf_os_spin_lock(&sc->target_lock); + sc->CE_id_to_state[CE_id]= NULL; + adf_os_spin_unlock(&sc->target_lock); + A_FREE(CE_state); + malloc_CE_state = false; + } + return NULL; + } + A_MEMZERO(ptr, CE_nbytes); + + dest_ring = CE_state->dest_ring = (struct CE_ring_state *)ptr; + ptr += sizeof(struct CE_ring_state); + dest_ring->nentries = nentries; + dest_ring->nentries_mask = nentries-1; + A_TARGET_ACCESS_BEGIN_RET_PTR(targid); + dest_ring->sw_index = CE_DEST_RING_READ_IDX_GET(targid, ctrl_addr); + dest_ring->write_index = CE_DEST_RING_WRITE_IDX_GET(targid, ctrl_addr); + A_TARGET_ACCESS_END_RET_PTR(targid); + dest_ring->low_water_mark_nentries = 0; + dest_ring->high_water_mark_nentries = nentries; + dest_ring->per_transfer_context = (void **)ptr; + + /* Legacy platforms that do not support cache coherent DMA are unsupported */ + dest_ring->base_addr_owner_space_unaligned = + pci_alloc_consistent(scn->sc_osdev->bdev, + (nentries * sizeof(struct CE_dest_desc) + CE_DESC_RING_ALIGN), + &base_addr); + if (dest_ring->base_addr_owner_space_unaligned == NULL) { + dev_err(&sc->pdev->dev, "ath ERROR: dest ring has no DMA mem\n"); + goto error_no_dma_mem; + } + dest_ring->base_addr_CE_space_unaligned = base_addr; + + /* Correctly initialize memory to 0 to prevent garbage data + * crashing system when download firmware + */ + A_MEMZERO(dest_ring->base_addr_owner_space_unaligned, nentries * sizeof(struct CE_dest_desc) + CE_DESC_RING_ALIGN); + + if (dest_ring->base_addr_CE_space_unaligned & (CE_DESC_RING_ALIGN-1)) { + + dest_ring->base_addr_CE_space = (dest_ring->base_addr_CE_space_unaligned + + CE_DESC_RING_ALIGN-1) & ~(CE_DESC_RING_ALIGN-1); + + dest_ring->base_addr_owner_space = (void *)(((size_t)dest_ring->base_addr_owner_space_unaligned + + CE_DESC_RING_ALIGN-1) & ~(CE_DESC_RING_ALIGN-1)); + } else { + dest_ring->base_addr_CE_space = dest_ring->base_addr_CE_space_unaligned; + dest_ring->base_addr_owner_space = dest_ring->base_addr_owner_space_unaligned; + } + + A_TARGET_ACCESS_BEGIN_RET_PTR(targid); + CE_DEST_RING_BASE_ADDR_SET(targid, ctrl_addr, dest_ring->base_addr_CE_space); + CE_DEST_RING_SZ_SET(targid, ctrl_addr, nentries); +#ifdef BIG_ENDIAN_HOST + /* Enable Destination ring byte swap for big endian host */ + CE_DEST_RING_BYTE_SWAP_SET(targid, ctrl_addr, 1); +#endif + CE_DEST_RING_LOWMARK_SET(targid, ctrl_addr, 0); + CE_DEST_RING_HIGHMARK_SET(targid, ctrl_addr, nentries); + A_TARGET_ACCESS_END_RET_PTR(targid); + + /* epping */ + /* poll timer */ + if ((CE_state->attr_flags & CE_ATTR_ENABLE_POLL)) { + adf_os_timer_init(scn->adf_dev, &CE_state->poll_timer, + CE_poll_timeout, CE_state, ADF_DEFERRABLE_TIMER); + CE_state->timer_inited = true; + adf_os_timer_mod(&CE_state->poll_timer, CE_POLL_TIMEOUT); + } + } + } + + /* Enable CE error interrupts */ + A_TARGET_ACCESS_BEGIN_RET_PTR(targid); + CE_ERROR_INTR_ENABLE(targid, ctrl_addr); + A_TARGET_ACCESS_END_RET_PTR(targid); + + return (struct CE_handle *)CE_state; + +error_no_dma_mem: + CE_fini((struct CE_handle *)CE_state); + return NULL; +} + +void +CE_fini(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + unsigned int CE_id = CE_state->id; + struct hif_pci_softc *sc = CE_state->sc; + struct ol_softc *scn = sc->ol_sc; + + CE_state->state = CE_UNUSED; + CE_state->sc->CE_id_to_state[CE_id] = NULL; + if (CE_state->src_ring) { + if (CE_state->src_ring->shadow_base_unaligned) + A_FREE(CE_state->src_ring->shadow_base_unaligned); + if (CE_state->src_ring->base_addr_owner_space_unaligned) + pci_free_consistent(scn->sc_osdev->bdev, + (CE_state->src_ring->nentries * sizeof(struct CE_src_desc) + CE_DESC_RING_ALIGN), + CE_state->src_ring->base_addr_owner_space_unaligned, CE_state->src_ring->base_addr_CE_space); + A_FREE(CE_state->src_ring); + } + if (CE_state->dest_ring) { + if (CE_state->dest_ring->base_addr_owner_space_unaligned) + pci_free_consistent(scn->sc_osdev->bdev, + (CE_state->dest_ring->nentries * sizeof(struct CE_dest_desc) + CE_DESC_RING_ALIGN), + CE_state->dest_ring->base_addr_owner_space_unaligned, CE_state->dest_ring->base_addr_CE_space); + A_FREE(CE_state->dest_ring); + + /* epping */ + if (CE_state->timer_inited) { + CE_state->timer_inited = false; + adf_os_timer_free(&CE_state->poll_timer); + } + } + A_FREE(CE_state); +} + +#ifdef IPA_UC_OFFLOAD +/* + * Copy engine should release resource to micro controller + * Micro controller needs + - Copy engine source descriptor base address + - Copy engine source descriptor size + - PCI BAR address to access copy engine regiser + */ +void CE_ipaGetResource(struct CE_handle *ce, + a_uint32_t *ce_sr_base_paddr, + a_uint32_t *ce_sr_ring_size, + a_uint32_t *ce_reg_paddr) +{ + struct CE_state *CE_state = (struct CE_state *)ce; + a_uint32_t ring_loop; + struct CE_src_desc *ce_desc; + a_uint32_t bar_value; + struct hif_pci_softc *sc = CE_state->sc; + + if (CE_RUNNING != CE_state->state) + { + *ce_sr_base_paddr = 0; + *ce_sr_ring_size = 0; + return; + } + + /* Update default value for descriptor */ + for (ring_loop = 0; ring_loop < CE_state->src_ring->nentries; ring_loop++) + { + ce_desc = (struct CE_src_desc *) + ((char *)CE_state->src_ring->base_addr_owner_space + + ring_loop * (sizeof(struct CE_src_desc))); + /* Source pointer and ID, + * should be updated by uc dynamically + * ce_desc->src_ptr = buffer; + * ce_desc->meta_data = transfer_id; */ + /* No Byte SWAP */ + ce_desc->byte_swap = 0; + /* DL size + * pdev->download_len = + * sizeof(struct htt_host_tx_desc_t) + + * HTT_TX_HDR_SIZE_OUTER_HDR_MAX + + * HTT_TX_HDR_SIZE_802_1Q + + * HTT_TX_HDR_SIZE_LLC_SNAP + + * ol_cfg_tx_download_size(pdev->ctrl_pdev); */ + ce_desc->nbytes = 60; + /* Single fragment No gather */ + ce_desc->gather = 0; + } + + /* Get BAR address */ + hif_read_bar(CE_state->sc, &bar_value); + + *ce_sr_base_paddr = (a_uint32_t)CE_state->src_ring->base_addr_CE_space; + *ce_sr_ring_size = (a_uint32_t)CE_state->src_ring->nentries; + *ce_reg_paddr = bar_value + CE_BASE_ADDRESS(CE_state->id) + SR_WR_INDEX_ADDRESS; + return; +} +#endif /* IPA_UC_OFFLOAD */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_api.h new file mode 100644 index 000000000000..7e03a5f28574 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_api.h @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __COPY_ENGINE_API_H__ +#define __COPY_ENGINE_API_H__ + +#if defined(CONFIG_COPY_ENGINE_SUPPORT) + +/* TBDXXX: Use int return values for consistency with Target */ + +/* TBDXXX: Perhaps merge Host/Target-->common */ + +/* + * Copy Engine support: low-level Target-side Copy Engine API. + * This is a hardware access layer used by code that understands + * how to use copy engines. + */ + +/* + * A "struct CE_handle *" serves as an opaque pointer-sized + * handle to a specific copy engine. + */ +struct CE_handle; + +/* + * "Send Completion" callback type for Send Completion Notification. + * + * If a Send Completion callback is registered and one or more sends + * have completed, the callback is invoked. + * + * per_CE_send_context is a context supplied by the calling layer + * (via CE_send_cb_register). It is associated with a copy engine. + * + * per_transfer_send_context is context supplied by the calling layer + * (via the "send" call). It may be different for each invocation + * of send. + * + * The buffer parameter is the first byte sent of the first buffer + * sent (if more than one buffer). + * + * nbytes is the number of bytes of that buffer that were sent. + * + * transfer_id matches the value used when the buffer or + * buf_list was sent. + * + * Implementation note: Pops 1 completed send buffer from Source ring + */ +typedef void (* CE_send_cb)(struct CE_handle *copyeng, + void *per_CE_send_context, + void *per_transfer_send_context, + CE_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int sw_index, + unsigned int hw_index); + +/* + * "Buffer Received" callback type for Buffer Received Notification. + * + * Implementation note: Pops 1 completed recv buffer from Dest ring + */ +typedef void (* CE_recv_cb)(struct CE_handle *copyeng, + void *per_CE_recv_context, + void *per_transfer_recv_context, + CE_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags); + +/* + * Copy Engine Watermark callback type. + * + * Allows upper layers to be notified when watermarks are reached: + * space is available and/or running short in a source ring + * buffers are exhausted and/or abundant in a destination ring + * + * The flags parameter indicates which condition triggered this + * callback. See CE_WM_FLAG_*. + * + * Watermark APIs are provided to allow upper layers "batch" + * descriptor processing and to allow upper layers to + * throttle/unthrottle. + */ +typedef void (* CE_watermark_cb)(struct CE_handle *copyeng, + void *per_CE_wm_context, + unsigned int flags); + +#define CE_WM_FLAG_SEND_HIGH 1 +#define CE_WM_FLAG_SEND_LOW 2 +#define CE_WM_FLAG_RECV_HIGH 4 +#define CE_WM_FLAG_RECV_LOW 8 + +/* A list of buffers to be gathered and sent */ +struct CE_sendlist; + +/* Copy Engine settable attributes */ +struct CE_attr; + +/*==================Send======================================================*/ + + /* CE_send flags */ +/* disable ring's byte swap, even if the default policy is to swap */ +#define CE_SEND_FLAG_SWAP_DISABLE 1 + +/* + * Queue a source buffer to be sent to an anonymous destination buffer. + * copyeng - which copy engine to use + * buffer - address of buffer + * nbytes - number of bytes to send + * transfer_id - arbitrary ID; reflected to destination + * flags - CE_SEND_FLAG_* values + * Returns 0 on success; otherwise an error status. + * + * Note: If no flags are specified, use CE's default data swap mode. + * + * Implementation note: pushes 1 buffer to Source ring + */ +int CE_send(struct CE_handle *copyeng, + void *per_transfer_send_context, + CE_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, /* 14 bits */ + unsigned int flags); + + +/* + * Register a Send Callback function. + * This function is called as soon as the contents of a Send + * have reached the destination, unless disable_interrupts is + * requested. In this case, the callback is invoked when the + * send status is polled, shortly after the send completes. + */ +void CE_send_cb_register(struct CE_handle *copyeng, + CE_send_cb fn_ptr, + void *per_CE_send_context, + int disable_interrupts); + +/* + * Return the size of a SendList. This allows the caller to allocate + * a SendList while the SendList structure remains opaque. + */ +unsigned int CE_sendlist_sizeof(void); + +/* Initialize a sendlist */ +void CE_sendlist_init(struct CE_sendlist *sendlist); + +/* Append a simple buffer (address/length) to a sendlist. */ +int CE_sendlist_buf_add(struct CE_sendlist *sendlist, + CE_addr_t buffer, + unsigned int nbytes, + u_int32_t flags /* OR-ed with internal flags */); + +/* + * Queue a "sendlist" of buffers to be sent using gather to a single + * anonymous destination buffer + * copyeng - which copy engine to use + * sendlist - list of simple buffers to send using gather + * transfer_id - arbitrary ID; reflected to destination + * Returns 0 on success; otherwise an error status. + * + * Implemenation note: Pushes multiple buffers with Gather to Source ring. + */ +int CE_sendlist_send(struct CE_handle *copyeng, + void *per_transfer_send_context, + struct CE_sendlist *sendlist, + unsigned int transfer_id); /* 14 bits */ + +/*==================Recv======================================================*/ + +/* + * Make a buffer available to receive. The buffer must be at least of a + * minimal size appropriate for this copy engine (src_sz_max attribute). + * copyeng - which copy engine to use + * per_transfer_recv_context - context passed back to caller's recv_cb + * buffer - address of buffer in CE space + * Returns 0 on success; otherwise an error status. + * + * Implemenation note: Pushes a buffer to Dest ring. + */ +int CE_recv_buf_enqueue(struct CE_handle *copyeng, + void *per_transfer_recv_context, + CE_addr_t buffer); + +/* + * Register a Receive Callback function. + * This function is called as soon as data is received + * from the source. + */ +void CE_recv_cb_register(struct CE_handle *copyeng, + CE_recv_cb fn_ptr, + void *per_CE_recv_context, + int disable_interrupts); + +/*==================CE Watermark==============================================*/ + +/* + * Register a Watermark Callback function. + * This function is called as soon as a watermark level + * is crossed. A Watermark Callback function is free to + * handle received data "en masse"; but then some coordination + * is required with a registered Receive Callback function. + * [Suggestion: Either handle Receives in a Receive Callback + * or en masse in a Watermark Callback; but not both.] + */ +void CE_watermark_cb_register(struct CE_handle *copyeng, + CE_watermark_cb fn_ptr, + void *per_CE_wm_context); + +/* + * Set low/high watermarks for the send/source side of a copy engine. + * + * Typically, the destination side CPU manages watermarks for + * the receive side and the source side CPU manages watermarks + * for the send side. + * + * A low watermark of 0 is never hit (so the watermark function + * will never be called for a Low Watermark condition). + * + * A high watermark equal to nentries is never hit (so the + * watermark function will never be called for a High Watermark + * condition). + */ +void CE_send_watermarks_set(struct CE_handle *copyeng, + unsigned int low_alert_nentries, + unsigned int high_alert_nentries); + +/* Set low/high watermarks for the receive/destination side of a copy engine. */ +void CE_recv_watermarks_set(struct CE_handle *copyeng, + unsigned int low_alert_nentries, + unsigned int high_alert_nentries); + +/* + * Return the number of entries that can be queued + * to a ring at an instant in time. + * + * For source ring, does not imply that destination-side + * buffers are available; merely indicates descriptor space + * in the source ring. + * + * For destination ring, does not imply that previously + * received buffers have been processed; merely indicates + * descriptor space in destination ring. + * + * Mainly for use with CE Watermark callback. + */ +unsigned int CE_send_entries_avail(struct CE_handle *copyeng); +unsigned int CE_recv_entries_avail(struct CE_handle *copyeng); + +/* + * Return the number of entries in the ring that are ready + * to be processed by software. + * + * For source ring, the number of descriptors that have + * been completed and can now be overwritten with new send + * descriptors. + * + * For destination ring, the number of descriptors that + * are available to be processed (newly received buffers). + */ +unsigned int CE_send_entries_done(struct CE_handle *copyeng); +unsigned int CE_recv_entries_done(struct CE_handle *copyeng); + + /* recv flags */ +/* Data is byte-swapped */ +#define CE_RECV_FLAG_SWAPPED 1 + +/* + * Supply data for the next completed unprocessed receive descriptor. + * + * For use + * with CE Watermark callback, + * in a recv_cb function when processing buf_lists + * in a recv_cb function in order to mitigate recv_cb's. + * + * Implemenation note: Pops buffer from Dest ring. + */ +int CE_completed_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp); + +/* + * Supply data for the next completed unprocessed send descriptor. + * + * For use + * with CE Watermark callback + * in a send_cb function in order to mitigate send_cb's. + * + * Implementation note: Pops 1 completed send buffer from Source ring + */ +int CE_completed_send_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx); + + +/*==================CE Engine Initialization==================================*/ + +/* Initialize an instance of a CE */ +struct CE_handle *CE_init(struct hif_pci_softc *sc, + unsigned int CE_id, + struct CE_attr *attr); + + +/*==================CE Engine Shutdown========================================*/ +/* + * Support clean shutdown by allowing the caller to revoke + * receive buffers. Target DMA must be stopped before using + * this API. + */ +A_STATUS +CE_revoke_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp); + +/* + * Support clean shutdown by allowing the caller to cancel + * pending sends. Target DMA must be stopped before using + * this API. + */ +A_STATUS +CE_cancel_send_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + CE_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp); + +void CE_fini(struct CE_handle *copyeng); + +/*==================CE Interrupt Handlers=====================================*/ +void CE_per_engine_service_any(int irq, void *arg); +void CE_per_engine_service(struct hif_pci_softc *sc, unsigned int CE_id); +void CE_per_engine_servicereap(struct hif_pci_softc *sc, unsigned int CE_id); + +/*===================CE cmpl interrupt Enable/Disable ============================*/ +void CE_disable_any_copy_compl_intr(struct hif_pci_softc *sc); +void CE_enable_any_copy_compl_intr(struct hif_pci_softc *sc); +void CE_disable_any_copy_compl_intr_nolock(struct hif_pci_softc *sc); +void CE_enable_any_copy_compl_intr_nolock(struct hif_pci_softc *sc); + +/* API to check if any of the copy engine pipes has pending frames for prcoessing */ +bool CE_get_rx_pending(struct hif_pci_softc *sc); + +/* CE_attr.flags values */ +#define CE_ATTR_NO_SNOOP 0x01 /* Use NonSnooping PCIe accesses? */ +#define CE_ATTR_BYTE_SWAP_DATA 0x02 /* Byte swap data words */ +#define CE_ATTR_SWIZZLE_DESCRIPTORS 0x04 /* Swizzle descriptors? */ +#define CE_ATTR_DISABLE_INTR 0x08 /* no interrupt on copy completion */ +#define CE_ATTR_ENABLE_POLL 0x10 /* poll for residue descriptors */ + +/* Attributes of an instance of a Copy Engine */ +struct CE_attr { + unsigned int flags; /* CE_ATTR_* values */ + + unsigned int priority; /* TBD */ + + unsigned int src_nentries; /* #entries in source ring - + Must be a power of 2 */ + + unsigned int src_sz_max; /* Max source send size for this CE. + This is also the minimum size of + a destination buffer. */ + + unsigned int dest_nentries; /* #entries in destination ring - + Must be a power of 2 */ + + void *reserved; /* Future use */ +}; + +/* + * When using sendlist_send to transfer multiple buffer fragments, the + * transfer context of each fragment, except last one, will be filled + * with CE_SENDLIST_ITEM_CTXT. CE_completed_send will return success for + * each fragment done with send and the transfer context would be + * CE_SENDLIST_ITEM_CTXT. Upper layer could use this to identify the + * status of a send completion. + */ +#define CE_SENDLIST_ITEM_CTXT ((void *)0xcecebeef) + +/* + * This is an opaque type that is at least large enough to hold + * a sendlist. A sendlist can only be accessed through CE APIs, + * but this allows a sendlist to be allocated on the run-time + * stack. TBDXXX: un-opaque would be simpler... + */ +struct CE_sendlist { + unsigned int word[62]; +}; + +#define ATH_ISR_NOSCHED 0x0000 /* Do not schedule bottom half/DPC */ +#define ATH_ISR_SCHED 0x0001 /* Schedule the bottom half for execution */ +#define ATH_ISR_NOTMINE 0x0002 /* This was not my interrupt - for shared IRQ's */ + +#ifdef IPA_UC_OFFLOAD +/* + * Copy engine should release resource to micro controller + * Micro controller needs + - Copy engine source descriptor base address + - Copy engine source descriptor size + - PCI BAR address to access copy engine regiser + */ +void CE_ipaGetResource(struct CE_handle *ce, + a_uint32_t *ce_sr_base_paddr, + a_uint32_t *ce_sr_ring_size, + a_uint32_t *ce_reg_paddr); +#endif /* IPA_UC_OFFLOAD */ + +#endif /* CONFIG_COPY_ENGINE_SUPPORT */ +#endif /* __COPY_ENGINE_API_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h new file mode 100644 index 000000000000..27df748ea7f1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include /* A_TARGET_WRITE */ + +/* Copy Engine operational state */ +enum CE_op_state { + CE_UNUSED, + CE_PAUSED, + CE_RUNNING, +}; + +enum ol_ath_hif_ce_ecodes { + CE_RING_DELTA_FAIL=0 +}; + +struct CE_src_desc; + +/* Copy Engine Ring internal state */ +struct CE_ring_state { + + /* Number of entries in this ring; must be power of 2 */ + unsigned int nentries; + unsigned int nentries_mask; + + /* + * For dest ring, this is the next index to be processed + * by software after it was/is received into. + * + * For src ring, this is the last descriptor that was sent + * and completion processed by software. + * + * Regardless of src or dest ring, this is an invariant + * (modulo ring size): + * write index >= read index >= sw_index + */ + unsigned int sw_index; + unsigned int write_index; /* cached copy */ + /* + * For src ring, this is the next index not yet processed by HW. + * This is a cached copy of the real HW index (read index), used + * for avoiding reading the HW index register more often than + * necessary. + * This extends the invariant: + * write index >= read index >= hw_index >= sw_index + * + * For dest ring, this is currently unused. + */ + unsigned int hw_index; /* cached copy */ + + /* Start of DMA-coherent area reserved for descriptors */ + void *base_addr_owner_space_unaligned; /* Host address space */ + CE_addr_t base_addr_CE_space_unaligned; /* CE address space */ + + /* + * Actual start of descriptors. + * Aligned to descriptor-size boundary. + * Points into reserved DMA-coherent area, above. + */ + void *base_addr_owner_space; /* Host address space */ + CE_addr_t base_addr_CE_space; /* CE address space */ + /* + * Start of shadow copy of descriptors, within regular memory. + * Aligned to descriptor-size boundary. + */ + char *shadow_base_unaligned; + struct CE_src_desc *shadow_base; + + unsigned int low_water_mark_nentries; + unsigned int high_water_mark_nentries; + void **per_transfer_context; + OS_DMA_MEM_CONTEXT(ce_dmacontext) // OS Specific DMA context +}; + +/* Copy Engine internal state */ +struct CE_state { + struct hif_pci_softc *sc; /* back pointer to device's sc */ + unsigned int id; + unsigned int attr_flags; /* CE_ATTR_* */ + u_int32_t ctrl_addr; /* relative to BAR */ + enum CE_op_state state; + + CE_send_cb send_cb; + void *send_context; + + CE_recv_cb recv_cb; + void *recv_context; + + /* misc_cbs - are any callbacks besides send and recv enabled? */ + u_int8_t misc_cbs; + + CE_watermark_cb watermark_cb; + void *wm_context; + + /*Record the state of the copy compl interrupt*/ + int disable_copy_compl_intr; + + unsigned int src_sz_max; + struct CE_ring_state *src_ring; + struct CE_ring_state *dest_ring; + atomic_t rx_pending; + + /* epping */ + bool timer_inited; + adf_os_timer_t poll_timer; +}; + +/* Descriptor rings must be aligned to this boundary */ +#define CE_DESC_RING_ALIGN 8 + +struct CE_src_desc { + CE_addr_t src_ptr; +#if _BYTE_ORDER == _BIG_ENDIAN + u_int32_t meta_data:14, + byte_swap:1, + gather:1, + nbytes:16; +#else + + u_int32_t nbytes:16, + gather:1, + byte_swap:1, + meta_data:14; +#endif +}; + +struct dest_desc_info { +#if _BYTE_ORDER == _BIG_ENDIAN + u_int32_t meta_data:14, + byte_swap:1, + gather:1, + nbytes:16; +#else + u_int32_t nbytes:16, + gather:1, + byte_swap:1, + meta_data:14; +#endif +}; + +struct CE_dest_desc { + CE_addr_t dest_ptr; + struct dest_desc_info info; +}; + +#define CE_SENDLIST_ITEMS_MAX 12 + +enum CE_sendlist_type_e { + CE_SIMPLE_BUFFER_TYPE, + /* TBDXXX: CE_RX_DESC_LIST, */ +}; + +/* + * There's a public "CE_sendlist" and a private "CE_sendlist_s". + * The former is an opaque structure with sufficient space + * to hold the latter. The latter is the actual structure + * definition and it is only used internally. The opaque version + * of the structure allows callers to allocate an instance on the + * run-time stack without knowing any of the details of the + * structure layout. + */ +struct CE_sendlist_s { + unsigned int num_items; + struct CE_sendlist_item { + enum CE_sendlist_type_e send_type; + dma_addr_t data; /* e.g. buffer or desc list */ + union { + unsigned int nbytes; /* simple buffer */ + unsigned int ndesc; /* Rx descriptor list */ + } u; + /* flags: externally-specified flags; OR-ed with internal flags */ + u_int32_t flags; + } item[CE_SENDLIST_ITEMS_MAX]; +}; + + +/* which ring of a CE? */ +#define CE_RING_SRC 0 +#define CE_RING_DEST 1 + +#define CDC_WAR_MAGIC_STR 0xceef0000 +#define CDC_WAR_DATA_CE 4 + +/* Additional internal-only CE_send flags */ +#define CE_SEND_FLAG_GATHER 0x00010000 /* Use Gather */ + +#define CE_SRC_RING_WRITE_IDX_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+SR_WR_INDEX_ADDRESS, (n)) + +#define CE_SRC_RING_WRITE_IDX_GET(targid, CE_ctrl_addr) \ + A_TARGET_READ((targid), (CE_ctrl_addr)+SR_WR_INDEX_ADDRESS) + +#define CE_SRC_RING_READ_IDX_GET(targid, CE_ctrl_addr) \ + A_TARGET_READ((targid), (CE_ctrl_addr)+CURRENT_SRRI_ADDRESS) + +#define CE_SRC_RING_BASE_ADDR_SET(targid, CE_ctrl_addr, addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+SR_BA_ADDRESS, (addr)) + +#define CE_SRC_RING_SZ_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+SR_SIZE_ADDRESS, (n)) + +#define CE_SRC_RING_DMAX_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+CE_CTRL1_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+CE_CTRL1_ADDRESS) & ~CE_CTRL1_DMAX_LENGTH_MASK) | \ + CE_CTRL1_DMAX_LENGTH_SET(n)) +#define CE_SRC_RING_BYTE_SWAP_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+CE_CTRL1_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+CE_CTRL1_ADDRESS) & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK ) | \ + CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n)) + +#define CE_DEST_RING_BYTE_SWAP_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+CE_CTRL1_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+CE_CTRL1_ADDRESS) & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK ) | \ + CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n)) + +#define CE_DEST_RING_WRITE_IDX_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+DST_WR_INDEX_ADDRESS, (n)) + +#define CE_DEST_RING_WRITE_IDX_GET(targid, CE_ctrl_addr) \ + A_TARGET_READ((targid), (CE_ctrl_addr)+DST_WR_INDEX_ADDRESS) + +#define CE_DEST_RING_READ_IDX_GET(targid, CE_ctrl_addr) \ + A_TARGET_READ((targid), (CE_ctrl_addr)+CURRENT_DRRI_ADDRESS) + +#define CE_DEST_RING_BASE_ADDR_SET(targid, CE_ctrl_addr, addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+DR_BA_ADDRESS, (addr)) + +#define CE_DEST_RING_SZ_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+DR_SIZE_ADDRESS, (n)) + +#define CE_SRC_RING_HIGHMARK_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+SRC_WATERMARK_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+SRC_WATERMARK_ADDRESS) & ~SRC_WATERMARK_HIGH_MASK) | \ + SRC_WATERMARK_HIGH_SET(n)) + +#define CE_SRC_RING_LOWMARK_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+SRC_WATERMARK_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+SRC_WATERMARK_ADDRESS) & ~SRC_WATERMARK_LOW_MASK) | \ + SRC_WATERMARK_LOW_SET(n)) + +#define CE_DEST_RING_HIGHMARK_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+DST_WATERMARK_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+DST_WATERMARK_ADDRESS) & ~DST_WATERMARK_HIGH_MASK) | \ + DST_WATERMARK_HIGH_SET(n)) + +#define CE_DEST_RING_LOWMARK_SET(targid, CE_ctrl_addr, n) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+DST_WATERMARK_ADDRESS, \ + (A_TARGET_READ((targid), (CE_ctrl_addr)+DST_WATERMARK_ADDRESS) & ~DST_WATERMARK_LOW_MASK) | \ + DST_WATERMARK_LOW_SET(n)) + +#define CE_COPY_COMPLETE_INTR_ENABLE(targid, CE_ctrl_addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS, \ + A_TARGET_READ((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS) | HOST_IE_COPY_COMPLETE_MASK) + +#define CE_COPY_COMPLETE_INTR_DISABLE(targid, CE_ctrl_addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS, \ + A_TARGET_READ((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS) & ~HOST_IE_COPY_COMPLETE_MASK) + +#define CE_BASE_ADDRESS(CE_id) \ + CE0_BASE_ADDRESS + ((CE1_BASE_ADDRESS-CE0_BASE_ADDRESS)*(CE_id)) + +#define CE_WATERMARK_INTR_ENABLE(targid, CE_ctrl_addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS, \ + A_TARGET_READ((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS) | CE_WATERMARK_MASK) + +#define CE_WATERMARK_INTR_DISABLE(targid, CE_ctrl_addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS, \ + A_TARGET_READ((targid), (CE_ctrl_addr)+HOST_IE_ADDRESS) & ~CE_WATERMARK_MASK) + +#define CE_ERROR_INTR_ENABLE(targid, CE_ctrl_addr) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+MISC_IE_ADDRESS, \ + A_TARGET_READ((targid), (CE_ctrl_addr)+MISC_IE_ADDRESS) | CE_ERROR_MASK) + +#define CE_MISC_INT_STATUS_GET(targid, CE_ctrl_addr) \ + A_TARGET_READ((targid), (CE_ctrl_addr)+MISC_IS_ADDRESS) + +#define CE_ENGINE_INT_STATUS_GET(targid, CE_ctrl_addr) \ + A_TARGET_READ((targid), (CE_ctrl_addr)+HOST_IS_ADDRESS) + +#define CE_ENGINE_INT_STATUS_CLEAR(targid, CE_ctrl_addr, mask) \ + A_TARGET_WRITE((targid), (CE_ctrl_addr)+HOST_IS_ADDRESS, (mask)) + +#define CE_WATERMARK_MASK (HOST_IS_SRC_RING_LOW_WATERMARK_MASK | \ + HOST_IS_SRC_RING_HIGH_WATERMARK_MASK | \ + HOST_IS_DST_RING_LOW_WATERMARK_MASK | \ + HOST_IS_DST_RING_HIGH_WATERMARK_MASK) + +#define CE_ERROR_MASK (MISC_IS_AXI_ERR_MASK | \ + MISC_IS_DST_ADDR_ERR_MASK | \ + MISC_IS_SRC_LEN_ERR_MASK | \ + MISC_IS_DST_MAX_LEN_VIO_MASK | \ + MISC_IS_DST_RING_OVERFLOW_MASK | \ + MISC_IS_SRC_RING_OVERFLOW_MASK) + +#define CE_SRC_RING_TO_DESC(baddr, idx) &(((struct CE_src_desc *)baddr)[idx]) +#define CE_DEST_RING_TO_DESC(baddr, idx) &(((struct CE_dest_desc *)baddr)[idx]) + +/* Ring arithmetic (modulus number of entries in ring, which is a pwr of 2). */ +#define CE_RING_DELTA(nentries_mask, fromidx, toidx) \ + (((int)(toidx)-(int)(fromidx)) & (nentries_mask)) + +#define CE_RING_IDX_INCR(nentries_mask, idx) \ + (((idx) + 1) & (nentries_mask)) + +#define CE_INTERRUPT_SUMMARY(targid) \ + CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \ + A_TARGET_READ((targid), CE_WRAPPER_BASE_ADDRESS+CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) + +/*Macro to increment CE packet errors*/ +#define OL_ATH_CE_PKT_ERROR_COUNT_INCR(_sc,_ce_ecode);\ +{\ + if(_ce_ecode==CE_RING_DELTA_FAIL)(_sc->ol_sc->pkt_stats.ce_ring_delta_fail_count)+=1;\ +} + + +/* Given a Copy Engine's ID, determine the interrupt number for that copy engine's interrupts. */ +#define CE_ID_TO_INUM(id) (A_INUM_CE0_COPY_COMP_BASE + (id)) +#define CE_INUM_TO_ID(inum) ((inum) - A_INUM_CE0_COPY_COMP_BASE) diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c new file mode 100644 index 000000000000..ca2fe95043a4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c @@ -0,0 +1,3597 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * Implementation of the Host-side Host InterFace (HIF) API + * for a Host/Target interconnect using Copy Engines over PCIe. + */ + +//#include +#include +#include "a_types.h" +#include "athdefs.h" +#include "osapi_linux.h" +#include "targcfg.h" +#include "adf_os_lock.h" +#include /* adf_os_atomic_read */ + +#include +#include +#include +#include + +#include "hif_msg_based.h" + +#include "if_pci.h" +#include "copy_engine_api.h" +#include "regtable.h" + +#define ATH_MODULE_NAME hif +#include +#include "hif_pci.h" +#include "vos_trace.h" +#include "vos_api.h" +#if defined(CONFIG_CNSS) +#include +#endif +#include +#include "epping_main.h" +#ifdef CONFIG_PCI_MSM +#include +#endif + +/* use credit flow control over HTC */ +unsigned int htc_credit_flow = 1; +int hif_pci_war1 = 0; +static DEFINE_SPINLOCK(pciwar_lock); + + +OSDRV_CALLBACKS HIF_osDrvcallback; + +#define HIF_PCI_DEBUG ATH_DEBUG_MAKE_MODULE_MASK(0) +#ifdef IPA_UC_OFFLOAD +#define HIF_PCI_IPA_UC_ASSIGNED_CE 5 +#endif /* IPA_UC_OFFLOAD */ + +#if defined(DEBUG) +static ATH_DEBUG_MASK_DESCRIPTION g_HIFDebugDescription[] = { + {HIF_PCI_DEBUG,"hif_pci"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, + "hif", + "PCIe Host Interface", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO, /*or with HIF_PCI_DEBUG if verbose HIF debug is required*/ + ATH_DEBUG_DESCRIPTION_COUNT(g_HIFDebugDescription), + g_HIFDebugDescription); +#endif + + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +spinlock_t pcie_access_log_lock; +unsigned int pcie_access_log_seqnum = 0; +HIF_ACCESS_LOG pcie_access_log[PCIE_ACCESS_LOG_NUM]; +static void HIFTargetDumpAccessLog(void); +#endif + +/* Forward references */ +static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info); + +/* + * Host software's Copy Engine configuration. + * This table is derived from the CE_PCI TABLE, above. + */ +#ifdef BIG_ENDIAN_HOST +#define CE_ATTR_FLAGS CE_ATTR_BYTE_SWAP_DATA +#else +#define CE_ATTR_FLAGS 0 +#endif + +#define AGC_DUMP 1 +#define CHANINFO_DUMP 2 +#define BB_WATCHDOG_DUMP 3 +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +#define PCIE_ACCESS_DUMP 4 +#endif +/* + * Fix EV118783, poll to check whether a BMI response comes + * other than waiting for the interruption which may be lost. + */ +//#define BMI_RSP_POLLING +#define BMI_RSP_TO_MILLISEC 1000 + +/** + * enum ce_host_index: index into the host copy engine attribute + * table + * @CE_HOST_H2T_HTC_CTRL: host->target HTC control and raw streams + * @CE_HOST_T2H_HTT_HTC_CTRL: target->host HTT + HTC control + * @CE_HOST_T2H_WMI: target->host WMI + * @CE_HOST_H2T_WMI: host->target WMI + * @CE_HOST_H2T_HTT: host->target HTT + * @CE_HOST_IPA2T_HTC_CTRL: ipa_uc->target HTC control + * @CE_HOST_TARGET_HIF: Target autonomous HIF_memcpy + * @CE_HOST_DIAG: ce_diag, the Diagnostic Window + * Note: This enum is closely tied to the host_CE_config_wlan + * table below. Please update the enum if the table is updated + */ + +enum ce_host_index { + CE_HOST_H2T_HTC_CTRL = 0, + CE_HOST_T2H_HTT_HTC_CTRL = 1, + CE_HOST_T2H_WMI = 2, + CE_HOST_H2T_WMI = 3, + CE_HOST_H2T_HTT = 4, +#ifndef IPA_UC_OFFLOAD + CE_HOST_UNUSED = 5, +#else + CE_HOST_IPA2T_HTC_CTRL = 5, +#endif + CE_HOST_TARGET_HIF = 6, + CE_HOST_DIAG = 7, +}; + +/** + * Note: This structure is closely tied to the enum above. + * Please update the enum if the table is updated + */ +static struct CE_attr host_CE_config_wlan[] = +{ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL, }, /* host->target HTC control and raw streams */ + /* could be moved to share CE3 */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL, },/* target->host HTT + HTC control */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL, },/* target->host WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL, },/* host->target WMI */ + { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, CE_HTT_H2T_MSG_SRC_NENTRIES , 256, 0, NULL, }, /* host->target HTT */ +#ifndef IPA_UC_OFFLOAD + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* unused */ +#else + { /* CE5 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, 1024, 512, 0, NULL, }, /* ipa_uc->target HTC control */ +#endif /* IPA_UC_OFFLOAD */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL, }, /* ce_diag, the Diagnostic Window */ +}; + +static struct CE_attr *host_CE_config = host_CE_config_wlan; + +/* + * Target firmware's Copy Engine configuration. + * This table is derived from the CE_PCI TABLE, above. + * It is passed to the Target at startup for use by firmware. + */ +static struct CE_pipe_config target_CE_config_wlan[] = { + { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTC control and raw streams */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0, }, /* target->host HTT + HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0, }, /* target->host WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0, }, /* host->target WMI */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTT */ + /* NB: 50% of src nentries, since tx has 2 frags */ +#ifndef IPA_UC_OFFLOAD + { /* CE5 */ 5, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0, }, /* unused */ +#else + { /* CE5 */ 5, PIPEDIR_OUT, 1024, 64, CE_ATTR_FLAGS, 0, }, /* ipa_uc->target HTC control */ +#endif /* IPA_UC_OFFLOAD */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0, },/* Reserved for target autonomous HIF_memcpy */ + /* CE7 used only by Host */ +}; + +static struct CE_pipe_config *target_CE_config = target_CE_config_wlan; +static int target_CE_config_sz = sizeof(target_CE_config_wlan); + +/* + * CE config for endpoint-ping test + * EP-ping is used to verify HTC/HIF basic functionality and could be used to + * measure interface performance. Here comes some notes. + * 1. In theory, each CE could be used to test. However, due to the limitation + * of target memory EP-ping only focus on CE 1/2/3/4 which are used for + * WMI/HTT services + * 2. The EP-ping CE config does not share the same CE config with WLAN + * application since the max_size and entries requirement for EP-ping + * is different. + */ +#define EPPING_CE_FLAGS_POLL CE_ATTR_DISABLE_INTR|CE_ATTR_ENABLE_POLL|CE_ATTR_FLAGS +static struct CE_attr host_CE_config_wlan_epping_poll[] = +{ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL, }, /* host->target HTC control and raw streams */ + { /* CE1 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 128, NULL, }, /* target->host EP-ping */ + { /* CE2 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 128, NULL, }, /* target->host EP-ping */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL, }, /* host->target EP-ping */ + { /* CE4 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL, }, /* host->target EP-ping */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, }, /* EP-ping heartbeat */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* unused */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL, }, /* ce_diag, the Diagnostic Window */ +}; + +static struct CE_attr host_CE_config_wlan_epping_irq[] = +{ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL, }, /* host->target HTC control and raw streams */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, }, /* target->host EP-ping */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, }, /* target->host EP-ping */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL, }, /* host->target EP-ping */ + { /* CE4 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL, }, /* host->target EP-ping */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, }, /* EP-ping heartbeat */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* unused */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL, }, /* ce_diag, the Diagnostic Window */ +}; +/* + * EP-ping firmware's CE configuration + */ +static struct CE_pipe_config target_CE_config_wlan_epping[] = { + { /* CE0 */ 0, PIPEDIR_OUT, 16, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTC control and raw streams */ + { /* CE1 */ 1, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0, }, /* target->host EP-ping */ + { /* CE2 */ 2, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0, }, /* target->host EP-ping */ + { /* CE3 */ 3, PIPEDIR_OUT, 128, 2048, CE_ATTR_FLAGS, 0, }, /* host->target EP-ping */ + { /* CE4 */ 4, PIPEDIR_OUT, 128, 2048, CE_ATTR_FLAGS, 0, }, /* host->target EP-ping */ + { /* CE5 */ 5, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0, }, /* EP-ping heartbeat */ + { /* CE6 */ 6, PIPEDIR_INOUT, 0, 0, CE_ATTR_FLAGS, 0, }, /* unused */ + /* CE7 used only by Host */ +}; + +int hif_completion_thread(struct HIF_CE_state *hif_state); +static int hif_post_recv_buffers(HIF_DEVICE *hif_device); + +void +WAR_PCI_WRITE32(char *addr, u32 offset, u32 value) +{ + if (hif_pci_war1) { + unsigned long irq_flags; + + spin_lock_irqsave(&pciwar_lock, irq_flags); + + (void)ioread32((void __iomem *)(addr+offset+4)); /* 3rd read prior to write */ + (void)ioread32((void __iomem *)(addr+offset+4)); /* 2nd read prior to write */ + (void)ioread32((void __iomem *)(addr+offset+4)); /* 1st read prior to write */ + iowrite32((u32)(value), (void __iomem *)(addr+offset)); + + spin_unlock_irqrestore(&pciwar_lock, irq_flags); + } else { + iowrite32((u32)(value), (void __iomem *)(addr+offset)); + } +} + +int HIFInit(OSDRV_CALLBACKS *callbacks) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + + A_MEMZERO(&HIF_osDrvcallback,sizeof(HIF_osDrvcallback)); + + A_REGISTER_MODULE_DEBUG_INFO(hif); + + HIF_osDrvcallback.deviceInsertedHandler = callbacks->deviceInsertedHandler; + HIF_osDrvcallback.deviceRemovedHandler = callbacks->deviceRemovedHandler; + HIF_osDrvcallback.deviceSuspendHandler = callbacks->deviceSuspendHandler; + HIF_osDrvcallback.deviceResumeHandler = callbacks->deviceResumeHandler; + HIF_osDrvcallback.deviceWakeupHandler = callbacks->deviceWakeupHandler; + HIF_osDrvcallback.context = callbacks->context; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + return EOK; +} + +int +HIFAttachHTC(HIF_DEVICE *hif_device, HTC_CALLBACKS *callbacks) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + ASSERT(0); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return EOK; +} + +void +HIFDetachHTC(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + A_MEMZERO(&hif_state->msg_callbacks_pending, sizeof(hif_state->msg_callbacks_pending)); + A_MEMZERO(&hif_state->msg_callbacks_current, sizeof(hif_state->msg_callbacks_current)); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); +} + +/* Send the first nbytes bytes of the buffer */ +A_STATUS +HIFSend_head(HIF_DEVICE *hif_device, + a_uint8_t pipe, unsigned int transfer_id, unsigned int nbytes, adf_nbuf_t nbuf) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct HIF_CE_pipe_info *pipe_info = &(hif_state->pipe_info[pipe]); + struct CE_handle *ce_hdl = pipe_info->ce_hdl; + int bytes = nbytes, nfrags = 0; + struct CE_sendlist sendlist; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + A_ASSERT(nbytes <= adf_nbuf_len(nbuf)); + + /* + * The common case involves sending multiple fragments within a + * single download (the tx descriptor and the tx frame header). + * So, optimize for the case of multiple fragments by not even + * checking whether it's necessary to use a sendlist. + * The overhead of using a sendlist for a single buffer download + * is not a big deal, since it happens rarely (for WMI messages). + */ + CE_sendlist_init(&sendlist); + do { + a_uint32_t frag_paddr; + int frag_bytes; + + frag_paddr = adf_nbuf_get_frag_paddr_lo(nbuf, nfrags); + frag_bytes = adf_nbuf_get_frag_len(nbuf, nfrags); + status = CE_sendlist_buf_add( + &sendlist, frag_paddr, + frag_bytes > bytes ? bytes : frag_bytes, + adf_nbuf_get_frag_is_wordstream(nbuf, nfrags) ? + 0 : CE_SEND_FLAG_SWAP_DISABLE); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: error, frag_num %d larger than the given limit\n", + __func__, nfrags)); + return status; + } + bytes -= frag_bytes; + nfrags++; + } while (bytes > 0); + + /* Make sure we have resources to handle this request */ + adf_os_spin_lock_bh(&pipe_info->completion_freeq_lock); + if (pipe_info->num_sends_allowed < nfrags) { + adf_os_spin_unlock_bh(&pipe_info->completion_freeq_lock); + OL_ATH_HIF_PKT_ERROR_COUNT_INCR(hif_state, HIF_PIPE_NO_RESOURCE); + return A_NO_RESOURCE; + } + pipe_info->num_sends_allowed -= nfrags; + adf_os_spin_unlock_bh(&pipe_info->completion_freeq_lock); + + if(adf_os_unlikely(ce_hdl == NULL)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: error CE handle is null\n", __func__)); + return A_ERROR; + } + + status = CE_sendlist_send(ce_hdl, nbuf, &sendlist, transfer_id); + A_ASSERT(status == A_OK); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return status; +} + +/* Send the entire buffer */ +A_STATUS +HIFSend(HIF_DEVICE *hif_device, a_uint8_t pipe, adf_nbuf_t hdr_buf, adf_nbuf_t netbuf) +{ + return HIFSend_head(hif_device, pipe, 0, adf_nbuf_len(netbuf), netbuf); +} + +void +HIFSendCompleteCheck(HIF_DEVICE *hif_device, a_uint8_t pipe, int force) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + if (! force) { + int resources; + /* + * Decide whether to actually poll for completions, or just + * wait for a later chance. + * If there seem to be plenty of resources left, then just wait, + * since checking involves reading a CE register, which is a + * relatively expensive operation. + */ + resources = HIFGetFreeQueueNumber(hif_device, pipe); + /* + * If at least 50% of the total resources are still available, + * don't bother checking again yet. + */ + if (resources > (host_CE_config[pipe].src_nentries >> 1)) { + return; + } + } +#ifdef ATH_11AC_TXCOMPACT + CE_per_engine_servicereap(hif_state->sc, pipe); +#else + CE_per_engine_service(hif_state->sc, pipe); +#endif +} + +a_uint16_t +HIFGetFreeQueueNumber(HIF_DEVICE *hif_device, a_uint8_t pipe) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct HIF_CE_pipe_info *pipe_info = &(hif_state->pipe_info[pipe]); + a_uint16_t rv; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + adf_os_spin_lock_bh(&pipe_info->completion_freeq_lock); + rv = pipe_info->num_sends_allowed; + adf_os_spin_unlock_bh(&pipe_info->completion_freeq_lock); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + return rv; +} + +/* Called by lower (CE) layer when a send to Target completes. */ +void +HIF_PCI_CE_send_done(struct CE_handle *copyeng, void *ce_context, void *transfer_context, + CE_addr_t CE_data, unsigned int nbytes, unsigned int transfer_id, + unsigned int sw_index, unsigned int hw_index) +{ + struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *)ce_context; + struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state; + struct HIF_CE_completion_state *compl_state; + struct HIF_CE_completion_state *compl_queue_head, *compl_queue_tail; /* local queue */ + unsigned int sw_idx = sw_index, hw_idx = hw_index; + + compl_queue_head = compl_queue_tail = NULL; + do { + /* + * For the send completion of an item in sendlist, just increment + * num_sends_allowed. The upper layer callback will be triggered + * when last fragment is done with send. + */ + if (transfer_context == CE_SENDLIST_ITEM_CTXT) { + adf_os_spin_lock(&pipe_info->completion_freeq_lock); + pipe_info->num_sends_allowed++; /* NB: meaningful only for Sends */ + adf_os_spin_unlock(&pipe_info->completion_freeq_lock); + continue; + } + + adf_os_spin_lock(&pipe_info->completion_freeq_lock); + compl_state = pipe_info->completion_freeq_head; + if (!compl_state) { + adf_os_spin_unlock(&pipe_info->completion_freeq_lock); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Out of free buf in hif send completion list, potential hw_index corruption" + "pipe_num:%d num_send_allowed:%d pipe_info:0x%p sw_index:%d hw_index:%d nbytes:%d\n", + pipe_info->pipe_num, pipe_info->num_sends_allowed, + pipe_info, sw_idx, hw_idx, nbytes)); + ASSERT(0); + break; + } + pipe_info->completion_freeq_head = compl_state->next; + adf_os_spin_unlock(&pipe_info->completion_freeq_lock); + + compl_state->next = NULL; + compl_state->send_or_recv = HIF_CE_COMPLETE_SEND; + compl_state->copyeng = copyeng; + compl_state->ce_context = ce_context; + compl_state->transfer_context = transfer_context; + compl_state->data = CE_data; + compl_state->nbytes = nbytes; + compl_state->transfer_id = transfer_id; + compl_state->flags = 0; + + /* Enqueue at end of local queue */ + if (compl_queue_tail) { + compl_queue_tail->next = compl_state; + } else { + compl_queue_head = compl_state; + } + compl_queue_tail = compl_state; + } while (CE_completed_send_next(copyeng, &ce_context, &transfer_context, + &CE_data, &nbytes, &transfer_id, + &sw_idx, &hw_idx) == EOK); + + if (compl_queue_head == NULL) { + /* + * If only some of the items within a sendlist have completed, + * don't invoke completion processing until the entire sendlist + * has been sent. + */ + return; + } + + adf_os_spin_lock(&hif_state->completion_pendingq_lock); + + /* Enqueue the local completion queue on the per-device completion queue */ + if (hif_state->completion_pendingq_head) { + hif_state->completion_pendingq_tail->next = compl_queue_head; + hif_state->completion_pendingq_tail = compl_queue_tail; + adf_os_spin_unlock(&hif_state->completion_pendingq_lock); + } else { + hif_state->completion_pendingq_head = compl_queue_head; + hif_state->completion_pendingq_tail = compl_queue_tail; + adf_os_spin_unlock(&hif_state->completion_pendingq_lock); + + /* Alert the send completion service thread */ + hif_completion_thread(hif_state); + } +} + + +/* Called by lower (CE) layer when data is received from the Target. */ +void +HIF_PCI_CE_recv_data(struct CE_handle *copyeng, void *ce_context, void *transfer_context, + CE_addr_t CE_data, unsigned int nbytes, unsigned int transfer_id, unsigned int flags) +{ + struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *)ce_context; + struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state; + struct hif_pci_softc *sc = hif_state->sc; + struct ol_softc *scn = sc->ol_sc; + struct HIF_CE_completion_state *compl_state; + struct HIF_CE_completion_state *compl_queue_head, *compl_queue_tail; /* local queue */ + + compl_queue_head = compl_queue_tail = NULL; + do { + hif_pm_runtime_mark_last_busy(sc->dev); + adf_os_spin_lock(&pipe_info->completion_freeq_lock); + compl_state = pipe_info->completion_freeq_head; + ASSERT(compl_state != NULL); + pipe_info->completion_freeq_head = compl_state->next; + adf_os_spin_unlock(&pipe_info->completion_freeq_lock); + + compl_state->next = NULL; + compl_state->send_or_recv = HIF_CE_COMPLETE_RECV; + compl_state->copyeng = copyeng; + compl_state->ce_context = ce_context; + compl_state->transfer_context = transfer_context; + compl_state->data = CE_data; + compl_state->nbytes = nbytes; + compl_state->transfer_id = transfer_id; + compl_state->flags = flags; + + /* Enqueue at end of local queue */ + if (compl_queue_tail) { + compl_queue_tail->next = compl_state; + } else { + compl_queue_head = compl_state; + } + compl_queue_tail = compl_state; + +#ifdef HTC_CRP_DEBUG + if (CE_HOST_T2H_WMI == pipe_info->pipe_num) + adf_nbuf_unmap_single(scn->adf_dev, (adf_nbuf_t)transfer_context, + ADF_OS_DMA_BIDIRECTIONAL); + else +#endif + adf_nbuf_unmap_single(scn->adf_dev, (adf_nbuf_t)transfer_context, + ADF_OS_DMA_FROM_DEVICE); + + /* + * EV #112693 - [Peregrine][ES1][WB342][Win8x86][Performance] BSoD_0x133 occurred in VHT80 UDP_DL + * Break out DPC by force if number of loops in HIF_PCI_CE_recv_data reaches MAX_NUM_OF_RECEIVES to avoid spending too long time in DPC for each interrupt handling. + * Schedule another DPC to avoid data loss if we had taken force-break action before + * Apply to Windows OS only currently, Linux/MAC os can expand to their platform if necessary + */ + + /* Set up force_break flag if num of receices reaches MAX_NUM_OF_RECEIVES */ + sc->receive_count++; + if (adf_os_unlikely(hif_max_num_receives_reached(sc->receive_count))) + { + sc->force_break = 1; + break; + } + } while (CE_completed_recv_next(copyeng, &ce_context, &transfer_context, + &CE_data, &nbytes, &transfer_id, &flags) == EOK); + + adf_os_spin_lock(&hif_state->completion_pendingq_lock); + + /* Enqueue the local completion queue on the per-device completion queue */ + if (hif_state->completion_pendingq_head) { + hif_state->completion_pendingq_tail->next = compl_queue_head; + hif_state->completion_pendingq_tail = compl_queue_tail; + adf_os_spin_unlock(&hif_state->completion_pendingq_lock); + } else { + hif_state->completion_pendingq_head = compl_queue_head; + hif_state->completion_pendingq_tail = compl_queue_tail; + adf_os_spin_unlock(&hif_state->completion_pendingq_lock); + + /* Alert the recv completion service thread */ + hif_completion_thread(hif_state); + } +} + +/* TBDXXX: Set CE High Watermark; invoke txResourceAvailHandler in response */ + + +void +HIFPostInit(HIF_DEVICE *hif_device, void *unused, MSG_BASED_HIF_CALLBACKS *callbacks) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + spin_lock_init(&pcie_access_log_lock); +#endif + /* Save callbacks for later installation */ + A_MEMCPY(&hif_state->msg_callbacks_pending, callbacks, sizeof(hif_state->msg_callbacks_pending)); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); +} + +static void hif_pci_free_complete_state(struct HIF_CE_pipe_info *pipe_info) +{ + struct HIF_CE_completion_state_list *tmp_list; + + while (pipe_info->completion_space_list) { + tmp_list = pipe_info->completion_space_list; + pipe_info->completion_space_list = tmp_list->next; + vos_mem_free(tmp_list); + } +} +int +hif_completion_thread_startup(struct HIF_CE_state *hif_state) +{ + struct CE_handle *ce_diag = hif_state->ce_diag; + struct hif_pci_softc *sc = hif_state->sc; + A_target_id_t targid = hif_state->targid; + int pipe_num; + + //daemonize("hif_compl_thread"); + + adf_os_spinlock_init(&hif_state->completion_pendingq_lock); + hif_state->completion_pendingq_head = hif_state->completion_pendingq_tail = NULL; + + A_TARGET_ACCESS_LIKELY(targid); + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + struct CE_attr attr; + struct HIF_CE_pipe_info *pipe_info; + int completions_needed; + + pipe_info = &hif_state->pipe_info[pipe_num]; + if (pipe_info->ce_hdl == ce_diag) { + continue; /* Handle Diagnostic CE specially */ + } + attr = host_CE_config[pipe_num]; + completions_needed = 0; + if (attr.src_nentries) { /* pipe used to send to target */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("pipe_num:%d pipe_info:0x%p\n", + pipe_num, pipe_info)); + CE_send_cb_register(pipe_info->ce_hdl, HIF_PCI_CE_send_done, pipe_info, attr.flags & CE_ATTR_DISABLE_INTR); + completions_needed += attr.src_nentries; + pipe_info->num_sends_allowed = attr.src_nentries-1; + } + if (attr.dest_nentries) { /* pipe used to receive from target */ + CE_recv_cb_register(pipe_info->ce_hdl, HIF_PCI_CE_recv_data, pipe_info, attr.flags & CE_ATTR_DISABLE_INTR); + completions_needed += attr.dest_nentries; + } + + pipe_info->completion_freeq_head = pipe_info->completion_freeq_tail = NULL; + if (completions_needed > 0) { + struct HIF_CE_completion_state *compl_state; + struct HIF_CE_completion_state_list *tmp_list; + int i; + int idx; + int num_list; + int allocated_node; + int num_in_batch; + size_t len; + + allocated_node = 0; + num_list = (completions_needed + HIF_CE_COMPLETE_STATE_NUM -1); + num_list /= HIF_CE_COMPLETE_STATE_NUM; + + for (idx = 0; idx < num_list; idx++) { + if (completions_needed - allocated_node >= + HIF_CE_COMPLETE_STATE_NUM) + num_in_batch = HIF_CE_COMPLETE_STATE_NUM; + else + num_in_batch = completions_needed - allocated_node; + if (num_in_batch <= 0) + break; + len = num_in_batch * + sizeof(struct HIF_CE_completion_state) + + sizeof(struct HIF_CE_completion_state_list); + /* Allocate structures to track pending send/recv completions */ + tmp_list = + (struct HIF_CE_completion_state_list *)vos_mem_malloc(len); + if (!tmp_list) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("ath ERROR: compl_state has no mem\n")); + hif_pci_free_complete_state(pipe_info); + return -1; + } + compl_state = (struct HIF_CE_completion_state *) + ((uint8_t *)tmp_list + + sizeof(struct HIF_CE_completion_state_list)); + for (i = 0; i < num_in_batch; i++) { + compl_state->send_or_recv = HIF_CE_COMPLETE_FREE; + compl_state->next = NULL; + if (pipe_info->completion_freeq_head) + pipe_info->completion_freeq_tail->next = compl_state; + else + pipe_info->completion_freeq_head = compl_state; + pipe_info->completion_freeq_tail = compl_state; + compl_state++; + allocated_node++; + } + if (pipe_info->completion_space_list == NULL) { + pipe_info->completion_space_list = tmp_list; + tmp_list->next = NULL; + } else { + tmp_list->next = pipe_info->completion_space_list; + pipe_info->completion_space_list = tmp_list; + } + } + adf_os_spinlock_init(&pipe_info->completion_freeq_lock); + } + + } + A_TARGET_ACCESS_UNLIKELY(targid); + return 0; +} + +void +hif_completion_thread_shutdown(struct HIF_CE_state *hif_state) +{ + struct HIF_CE_completion_state *compl_state; + struct HIF_CE_pipe_info *pipe_info; + struct hif_pci_softc *sc = hif_state->sc; + int pipe_num; + + /* + * Drop pending completions. These have already been + * reported by the CE layer to us but we have not yet + * passed them upstack. + */ + while ((compl_state = hif_state->completion_pendingq_head) != NULL) { + adf_nbuf_t netbuf; + + netbuf = (adf_nbuf_t)compl_state->transfer_context; + adf_nbuf_free(netbuf); + + hif_state->completion_pendingq_head = compl_state->next; + + /* + * NB: Don't bother to place compl_state on pipe's free queue, + * because we'll free underlying memory for the free queues + * in a moment anyway. + */ + } + + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + pipe_info = &hif_state->pipe_info[pipe_num]; + hif_pci_free_complete_state(pipe_info); + adf_os_spinlock_destroy(&pipe_info->completion_freeq_lock); + } + + //hif_state->compl_thread = NULL; + //complete_and_exit(&hif_state->compl_thread_done, 0); +} + +/* + * This thread provides a context in which send/recv completions + * are handled. + * + * Note: HIF installs callback functions with the CE layer. + * Those functions are called directly (e.g. in interrupt context). + * Upper layers (e.g. HTC) have installed callbacks with HIF which + * expect to be called in a thread context. This is where that + * conversion occurs. + * + * TBDXXX: Currently we use just one thread for all pipes. + * This might be sufficient or we might need multiple threads. + */ +int +//hif_completion_thread(void *hif_dev) +hif_completion_thread(struct HIF_CE_state *hif_state) +{ + MSG_BASED_HIF_CALLBACKS *msg_callbacks = &hif_state->msg_callbacks_current; + struct HIF_CE_completion_state *compl_state; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + + /* Allow only one instance of the thread to execute at a time to + * prevent out of order processing of messages - this is bad for higher + * layer code + */ + if (!adf_os_atomic_dec_and_test(&hif_state->hif_thread_idle)) { + /* We were not the lucky one */ + adf_os_atomic_inc(&hif_state->hif_thread_idle); + return 0; + } + + /* Make sure that HTC registered call backs with the HIF are valid */ + if (!msg_callbacks->fwEventHandler + || !msg_callbacks->txCompletionHandler + || !msg_callbacks->rxCompletionHandler) { + return 0; + } + + while (atomic_read(&hif_state->fw_event_pending) > 0) { + /* + * Clear pending state before handling, in case there's + * another while we process the first. + */ + atomic_set(&hif_state->fw_event_pending, 0); + msg_callbacks->fwEventHandler(msg_callbacks->Context, A_ERROR); + } + + if (hif_state->sc->ol_sc->target_status == OL_TRGET_STATUS_RESET) + return 0; + + for (;;) { + struct HIF_CE_pipe_info *pipe_info; + int send_done = 0; + + adf_os_spin_lock(&hif_state->completion_pendingq_lock); + + if (!hif_state->completion_pendingq_head) { + /* We are atomically sure that there is no pending work */ + adf_os_atomic_inc(&hif_state->hif_thread_idle); + adf_os_spin_unlock(&hif_state->completion_pendingq_lock); + break; /* All pending completions are handled */ + } + + /* Dequeue the first unprocessed but completed transfer */ + compl_state = hif_state->completion_pendingq_head; + hif_state->completion_pendingq_head = compl_state->next; + adf_os_spin_unlock(&hif_state->completion_pendingq_lock); + + pipe_info = (struct HIF_CE_pipe_info *)compl_state->ce_context; + if (compl_state->send_or_recv == HIF_CE_COMPLETE_SEND) { + msg_callbacks->txCompletionHandler(msg_callbacks->Context, compl_state->transfer_context, compl_state->transfer_id); + send_done = 1; + } else { /* compl_state->send_or_recv == HIF_CE_COMPLETE_RECV */ + adf_nbuf_t netbuf; + unsigned int nbytes; + + atomic_inc(&pipe_info->recv_bufs_needed); + hif_post_recv_buffers((HIF_DEVICE *)hif_state); + + netbuf = (adf_nbuf_t)compl_state->transfer_context; + nbytes = compl_state->nbytes; + /* + To see the following debug output, enable the HIF_PCI_DEBUG flag in + the debug module declaration in this source file + */ + AR_DEBUG_PRINTF(HIF_PCI_DEBUG,("HIF_PCI_CE_recv_data netbuf=%p nbytes=%d\n", netbuf, nbytes)); + if (nbytes <= pipe_info->buf_sz) { + adf_nbuf_set_pktlen(netbuf, nbytes); + msg_callbacks->rxCompletionHandler(msg_callbacks->Context, + netbuf, pipe_info->pipe_num); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Rx message netbuf:%p nbytes:%d\n", + netbuf, nbytes)); + adf_nbuf_free(netbuf); + } + } + + /* Recycle completion state back to the pipe it came from. */ + compl_state->next = NULL; + compl_state->send_or_recv = HIF_CE_COMPLETE_FREE; + adf_os_spin_lock(&pipe_info->completion_freeq_lock); + if (pipe_info->completion_freeq_head) { + pipe_info->completion_freeq_tail->next = compl_state; + } else { + pipe_info->completion_freeq_head = compl_state; + } + pipe_info->completion_freeq_tail = compl_state; + pipe_info->num_sends_allowed += send_done; + adf_os_spin_unlock(&pipe_info->completion_freeq_lock); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return 0; +} + +/* + * Install pending msg callbacks. + * + * TBDXXX: This hack is needed because upper layers install msg callbacks + * for use with HTC before BMI is done; yet this HIF implementation + * needs to continue to use BMI msg callbacks. Really, upper layers + * should not register HTC callbacks until AFTER BMI phase. + */ +static void +hif_msg_callbacks_install(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + + A_MEMCPY(&hif_state->msg_callbacks_current, + &hif_state->msg_callbacks_pending, sizeof(hif_state->msg_callbacks_pending)); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); +} + +int +HIFConfigureDevice(HIF_DEVICE *hif_device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, u_int32_t configLen) +{ + int status = EOK; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + switch (opcode) { + case HIF_DEVICE_GET_OS_DEVICE: + { + HIF_DEVICE_OS_DEVICE_INFO *info = (HIF_DEVICE_OS_DEVICE_INFO *)config; + + info->pOSDevice = (void *)sc->dev; + } + break; + + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: + /* provide fake block sizes for mailboxes to satisfy upper layer software */ + ((u_int32_t *)config)[0] = 16; + ((u_int32_t *)config)[1] = 16; + ((u_int32_t *)config)[2] = 16; + ((u_int32_t *)config)[3] = 16; + break; + + case HIF_BMI_DONE: + { + printk("%s: BMI_DONE\n", __FUNCTION__); /* TBDXXX */ + break; + } + + default: + status = !EOK; + break; + + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return status; +} + +void +HIFClaimDevice(HIF_DEVICE *hif_device, void *claimedContext) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + hif_state->claimedContext = claimedContext; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); +} + +void +HIFReleaseDevice(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + hif_state->claimedContext = NULL; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); +} + +void +HIFGetDefaultPipe(HIF_DEVICE *hif_device, a_uint8_t *ULPipe, a_uint8_t *DLPipe) +{ + int ul_is_polled, dl_is_polled; + + (void)HIFMapServiceToPipe( + hif_device, HTC_CTRL_RSVD_SVC, + ULPipe, DLPipe, + &ul_is_polled, &dl_is_polled); +} + +/* TBDXXX - temporary mapping while we have too few CE's */ +int +HIFMapServiceToPipe(HIF_DEVICE *hif_device, a_uint16_t ServiceId, a_uint8_t *ULPipe, a_uint8_t *DLPipe, int *ul_is_polled, int *dl_is_polled) +{ + int status = EOK; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + *dl_is_polled = 0; /* polling for received messages not supported */ + switch (ServiceId) { + case HTT_DATA_MSG_SVC: + /* + * Host->target HTT gets its own pipe, so it can be polled + * while other pipes are interrupt driven. + */ + *ULPipe = 4; + /* + * Use the same target->host pipe for HTC ctrl, HTC raw streams, + * and HTT. + */ + *DLPipe = 1; + break; + + case HTC_CTRL_RSVD_SVC: + case HTC_RAW_STREAMS_SVC: + /* + * Note: HTC_RAW_STREAMS_SVC is currently unused, and + * HTC_CTRL_RSVD_SVC could share the same pipe as the + * WMI services. So, if another CE is needed, change + * this to *ULPipe = 3, which frees up CE 0. + */ + //*ULPipe = 3; + *ULPipe = 0; + *DLPipe = 1; + break; + + case WMI_DATA_BK_SVC: + /* + * To avoid some confusions, better to introduce new EP-ping + * service instead of using existed services. Until the main + * framework support this, keep this design. + */ + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { + *ULPipe = 4; + *DLPipe = 1; + break; + } + case WMI_DATA_BE_SVC: + case WMI_DATA_VI_SVC: + case WMI_DATA_VO_SVC: + + case WMI_CONTROL_SVC: + *ULPipe = 3; + *DLPipe = 2; + break; + +#ifdef IPA_UC_OFFLOAD + case WDI_IPA_TX_SVC: + *ULPipe = 5; + break; +#endif /* IPA_UC_OFFLOAD */ + + /* pipe 5 unused */ + /* pipe 6 reserved */ + /* pipe 7 reserved */ + + default: + status = !EOK; + break; + } + *ul_is_polled = (host_CE_config[*ULPipe].flags & CE_ATTR_DISABLE_INTR) != 0; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return status; +} + +void HIFDumpTargetMemory(HIF_DEVICE *hif_device, void *ramdump_base, + u_int32_t address, u_int32_t size) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + A_target_id_t targid; + u_int32_t loc = address; + u_int32_t val = 0; + u_int32_t j = 0; + u8 *temp = ramdump_base; + + hif_state = (struct HIF_CE_state *)hif_device; + sc = hif_state->sc; + targid = hif_state->targid; + + A_TARGET_ACCESS_BEGIN(targid); + while (j < size) { + val = A_PCI_READ32(sc->mem + loc + j); + OS_MEMCPY(temp, &val, 4); + j += 4; + temp += 4; + } + A_TARGET_ACCESS_END(targid); +} + +/* + * TBDXXX: Should be a function call specific to each Target-type. + * This convoluted macro converts from Target CPU Virtual Address Space to CE Address Space. + * As part of this process, we conservatively fetch the current PCIE_BAR. MOST of the time, + * this should match the upper bits of PCI space for this device; but that's not guaranteed. + */ +#define TARG_CPU_SPACE_TO_CE_SPACE(pci_addr, addr) \ + (((A_PCI_READ32((pci_addr)+(SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \ + | 0x100000 | ((addr) & 0xfffff)) + +/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ +#define DIAG_ACCESS_CE_TIMEOUT_MS 10 + +/* + * Diagnostic read/write access is provided for startup/config/debug usage. + * Caller must guarantee proper alignment, when applicable, and single user + * at any moment. + */ + +A_STATUS +HIFDiagReadMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + struct ol_softc *scn; + A_target_id_t targid; + A_STATUS status = EOK; + CE_addr_t buf; + unsigned int completed_nbytes, orig_nbytes, remaining_bytes; + unsigned int id; + unsigned int flags; + struct CE_handle *ce_diag; + CE_addr_t CE_data; /* Host buffer address in CE space */ + adf_os_dma_addr_t CE_data_base = 0; + void *data_buf = NULL; + int i; + hif_state = (struct HIF_CE_state *)hif_device; + sc = hif_state->sc; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" %s\n",__FUNCTION__)); + + + /* This code cannot handle reads to non-memory space. Redirect to the + * register read fn but preserve the multi word read capability of this fn + */ + if (address < DRAM_BASE_ADDRESS) { + + if ((address & 0x3) || ((uintptr_t)data & 0x3)) { + return (-EIO); + } + + while ((nbytes >= 4) && + (A_OK == (status = HIFDiagReadAccess(hif_device, address, + (A_UINT32*)data)))) { + + nbytes -= sizeof(A_UINT32); + address+= sizeof(A_UINT32); + data += sizeof(A_UINT32); + + } + + return status; + } + + + scn = sc->ol_sc; + targid = hif_state->targid; + ce_diag = hif_state->ce_diag; + + A_TARGET_ACCESS_LIKELY(targid); + + /* + * Allocate a temporary bounce buffer to hold caller's data + * to be DMA'ed from Target. This guarantees + * 1) 4-byte alignment + * 2) Buffer in DMA-able space + */ + orig_nbytes = nbytes; + data_buf = (A_UCHAR *)pci_alloc_consistent(scn->sc_osdev->bdev, + orig_nbytes, + &CE_data_base); + if (!data_buf) { + status = A_NO_MEMORY; + goto done; + } + adf_os_mem_set(data_buf, 0, orig_nbytes); + pci_dma_sync_single_for_device(scn->sc_osdev->bdev, CE_data_base, orig_nbytes, PCI_DMA_FROMDEVICE); + + remaining_bytes = orig_nbytes; + CE_data = CE_data_base; + while (remaining_bytes) { + nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT); + { + status = CE_recv_buf_enqueue(ce_diag, NULL, CE_data); + if (status != A_OK) { + goto done; + } + } + + { /* Request CE to send from Target(!) address to Host buffer */ + /* + * The address supplied by the caller is in the + * Target CPU virtual address space. + * + * In order to use this address with the diagnostic CE, + * convert it from + * Target CPU virtual address space + * to + * CE address space + */ + A_TARGET_ACCESS_BEGIN_RET(targid); + address = TARG_CPU_SPACE_TO_CE_SPACE(sc->mem, address); + A_TARGET_ACCESS_END_RET(targid); + + status = CE_send(ce_diag, NULL, (CE_addr_t)address, nbytes, 0, 0); + if (status != EOK) { + goto done; + } + } + + i=0; + while (CE_completed_send_next(ce_diag, NULL, NULL, &buf, + &completed_nbytes, &id, + NULL, NULL) != A_OK) { + A_MDELAY(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = A_EBUSY; + goto done; + } + } + if (nbytes != completed_nbytes) { + status = A_ERROR; + goto done; + } + if (buf != (CE_addr_t)address) { + status = A_ERROR; + goto done; + } + + i=0; + while (CE_completed_recv_next(ce_diag, NULL, NULL, &buf, &completed_nbytes, &id, &flags) != A_OK) { + A_MDELAY(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = A_EBUSY; + goto done; + } + } + if (nbytes != completed_nbytes) { + status = A_ERROR; + goto done; + } + if (buf != CE_data) { + status = A_ERROR; + goto done; + } + + remaining_bytes -= nbytes; + address += nbytes; + CE_data += nbytes; + } + +done: + A_TARGET_ACCESS_UNLIKELY(targid); + + if (status == A_OK) { + /* Copy data from allocated DMA buf to caller's buf */ + A_MEMCPY(data, data_buf, orig_nbytes); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s failure (0x%x)\n", __FUNCTION__, address)); + } + + if (data_buf) { + pci_free_consistent(scn->sc_osdev->bdev, orig_nbytes, + data_buf, CE_data_base); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return status; +} + +/* Read 4-byte aligned data from Target memory or register */ +A_STATUS +HIFDiagReadAccess(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT32 *data) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + + hif_state = (struct HIF_CE_state *)hif_device; + sc = hif_state->sc; + + if (address >= DRAM_BASE_ADDRESS) { /* Assume range doesn't cross this boundary */ + return HIFDiagReadMem(hif_device, address, (A_UINT8 *)data, sizeof(A_UINT32)); + } else { + A_target_id_t targid; + + targid = hif_state->targid; + + A_TARGET_ACCESS_BEGIN_RET(targid); + *data = A_TARGET_READ(targid, address); + A_TARGET_ACCESS_END_RET(targid); + + return A_OK; + } +} + +A_STATUS +HIFDiagWriteMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + struct ol_softc *scn; + A_target_id_t targid; + A_STATUS status = A_OK; + CE_addr_t buf; + unsigned int completed_nbytes, orig_nbytes, remaining_bytes; + unsigned int id; + unsigned int flags; + struct CE_handle *ce_diag; + void *data_buf = NULL; + CE_addr_t CE_data; /* Host buffer address in CE space */ + adf_os_dma_addr_t CE_data_base = 0; + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" %s\n",__FUNCTION__)); + + hif_state = (struct HIF_CE_state *)hif_device; + sc = hif_state->sc; + scn = sc->ol_sc; + targid = hif_state->targid; + ce_diag = hif_state->ce_diag; + + A_TARGET_ACCESS_LIKELY(targid); + + /* + * Allocate a temporary bounce buffer to hold caller's data + * to be DMA'ed to Target. This guarantees + * 1) 4-byte alignment + * 2) Buffer in DMA-able space + */ + orig_nbytes = nbytes; + data_buf = (A_UCHAR *)pci_alloc_consistent(scn->sc_osdev->bdev, + orig_nbytes, + &CE_data_base); + if (!data_buf) { + status = A_NO_MEMORY; + goto done; + } + + /* Copy caller's data to allocated DMA buf */ + A_MEMCPY(data_buf, data, orig_nbytes); + pci_dma_sync_single_for_device(scn->sc_osdev->bdev, CE_data_base, orig_nbytes, PCI_DMA_TODEVICE); + + /* + * The address supplied by the caller is in the + * Target CPU virtual address space. + * + * In order to use this address with the diagnostic CE, + * convert it from + * Target CPU virtual address space + * to + * CE address space + */ + A_TARGET_ACCESS_BEGIN_RET(targid); + address = TARG_CPU_SPACE_TO_CE_SPACE(sc->mem, address); + A_TARGET_ACCESS_END_RET(targid); + + remaining_bytes = orig_nbytes; + CE_data = CE_data_base; + while (remaining_bytes) { + nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT); + + { /* Set up to receive directly into Target(!) address */ + status = CE_recv_buf_enqueue(ce_diag, NULL, address); + if (status != A_OK) { + goto done; + } + } + + { + /* + * Request CE to send caller-supplied data that + * was copied to bounce buffer to Target(!) address. + */ + status = CE_send(ce_diag, NULL, (CE_addr_t)CE_data, nbytes, 0, 0); + if (status != A_OK) { + goto done; + } + } + + i=0; + while (CE_completed_send_next(ce_diag, NULL, NULL, &buf, + &completed_nbytes, &id, + NULL, NULL) != A_OK) { + A_MDELAY(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = A_EBUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + status = A_ERROR; + goto done; + } + + if (buf != CE_data) { + status = A_ERROR; + goto done; + } + + i=0; + while (CE_completed_recv_next(ce_diag, NULL, NULL, &buf, &completed_nbytes, &id, &flags) != A_OK) { + A_MDELAY(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = A_EBUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + status = A_ERROR; + goto done; + } + + if (buf != address) { + status = A_ERROR; + goto done; + } + + remaining_bytes -= nbytes; + address += nbytes; + CE_data += nbytes; + } + +done: + A_TARGET_ACCESS_UNLIKELY(targid); + + if (data_buf) { + pci_free_consistent(scn->sc_osdev->bdev, orig_nbytes, + data_buf, CE_data_base); + } + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s failure (0x%x)\n", __FUNCTION__, address)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return status; +} + +/* Write 4B data to Target memory or register */ +A_STATUS +HIFDiagWriteAccess(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT32 data) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + + hif_state = (struct HIF_CE_state *)hif_device; + sc = hif_state->sc; + if (address >= DRAM_BASE_ADDRESS) { /* Assume range doesn't cross this boundary */ + A_UINT32 data_buf = data; + + return HIFDiagWriteMem(hif_device, address, (A_UINT8 *)&data_buf, sizeof(A_UINT32)); + } else { + struct HIF_CE_state *hif_state; + A_target_id_t targid; + + hif_state = (struct HIF_CE_state *)hif_device; + targid = hif_state->targid; + + A_TARGET_ACCESS_BEGIN_RET(targid); + A_TARGET_WRITE(targid, address, data); + A_TARGET_ACCESS_END_RET(targid); + + return A_OK; + } +} + +/** + * hif_dump_pipe_debug_count() - Log error count + * @hif_device: HIF device pointer. + * + * Output the pipe error counts of each pipe to log file + * + * Return: N/A + */ +void hif_dump_pipe_debug_count(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + int pipe_num; + + if (hif_device == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s hif_device is NULL", __func__)); + return; + } + hif_state = (struct HIF_CE_state *)hif_device; + if (hif_state == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s hif_state is NULL", __func__)); + return; + } + sc = hif_state->sc; + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + struct HIF_CE_pipe_info *pipe_info; + + pipe_info = &hif_state->pipe_info[pipe_num]; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s pipe_id = %d, recv_bufs_needed = %d, nbuf_alloc_err_count = %u, nbuf_dma_err_count = %u, nbuf_ce_enqueue_err_count = %u", + __func__, pipe_info->pipe_num, + atomic_read(&pipe_info->recv_bufs_needed), + pipe_info->nbuf_alloc_err_count, + pipe_info->nbuf_dma_err_count, + pipe_info->nbuf_ce_enqueue_err_count)); + } +} + +static int +hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) +{ + struct CE_handle *ce_hdl; + adf_os_size_t buf_sz; + struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state; + struct hif_pci_softc *sc = hif_state->sc; + struct ol_softc *scn = sc->ol_sc; + a_status_t ret; + uint32_t bufs_posted = 0; + + buf_sz = pipe_info->buf_sz; + if (buf_sz == 0) { + /* Unused Copy Engine */ + return 0; + } + + ce_hdl = pipe_info->ce_hdl; + + adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + while (atomic_read(&pipe_info->recv_bufs_needed) > 0) { + CE_addr_t CE_data; /* CE space buffer address*/ + adf_nbuf_t nbuf; + int status; + + atomic_dec(&pipe_info->recv_bufs_needed); + adf_os_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + + nbuf = adf_nbuf_alloc(scn->adf_dev, buf_sz, 0, 4, FALSE); + if (!nbuf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s buf alloc error [%d] needed %d\n", + __func__, pipe_info->pipe_num, + atomic_read(&pipe_info->recv_bufs_needed))); + atomic_inc(&pipe_info->recv_bufs_needed); + adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + pipe_info->nbuf_alloc_err_count++; + adf_os_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + return 1; + } + +#ifdef HTC_CRP_DEBUG +#define HTC_DEBUG_PATTERN 0xF005BA11 + if (CE_HOST_T2H_WMI == pipe_info->pipe_num) { + uint32_t * data; + data = (uint32_t *)adf_nbuf_data(nbuf); + *data = HTC_DEBUG_PATTERN; + *(data + 1) = HTC_DEBUG_PATTERN; + *(data + 2) = HTC_DEBUG_PATTERN; + *(data + 3) = HTC_DEBUG_PATTERN; + } +#endif + /* + * adf_nbuf_peek_header(nbuf, &data, &unused); + * CE_data = dma_map_single(dev, data, buf_sz, DMA_FROM_DEVICE); + */ +#ifdef HTC_CRP_DEBUG + if (CE_HOST_T2H_WMI == pipe_info->pipe_num) + ret = adf_nbuf_map_single(scn->adf_dev, nbuf, + ADF_OS_DMA_BIDIRECTIONAL); + else +#endif + ret = adf_nbuf_map_single(scn->adf_dev, nbuf, ADF_OS_DMA_FROM_DEVICE); + + if (unlikely(ret != A_STATUS_OK)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s mapping error\n", __func__)); + adf_nbuf_free(nbuf); + atomic_inc(&pipe_info->recv_bufs_needed); + adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + pipe_info->nbuf_dma_err_count++; + adf_os_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + return 1; + } + + CE_data = adf_nbuf_get_frag_paddr_lo(nbuf, 0); + + pci_dma_sync_single_for_device(scn->sc_osdev->bdev, CE_data, + buf_sz, PCI_DMA_FROMDEVICE); + status = CE_recv_buf_enqueue(ce_hdl, (void *)nbuf, CE_data); + A_ASSERT(status == EOK); + if (status != EOK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s CE_recv_buf_enqueue error [%d] needed %d\n", + __func__, pipe_info->pipe_num, + atomic_read(&pipe_info->recv_bufs_needed))); + atomic_inc(&pipe_info->recv_bufs_needed); + adf_nbuf_free(nbuf); + adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + pipe_info->nbuf_ce_enqueue_err_count++; + adf_os_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + return 1; + } + + adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + bufs_posted++; + } + pipe_info->nbuf_alloc_err_count = + (pipe_info->nbuf_alloc_err_count > bufs_posted)? + pipe_info->nbuf_alloc_err_count - bufs_posted : 0; + pipe_info->nbuf_dma_err_count = + (pipe_info->nbuf_dma_err_count > bufs_posted)? + pipe_info->nbuf_dma_err_count - bufs_posted : 0; + pipe_info->nbuf_ce_enqueue_err_count = + (pipe_info->nbuf_ce_enqueue_err_count > bufs_posted)? + pipe_info->nbuf_ce_enqueue_err_count - bufs_posted : 0; + + adf_os_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + + return 0; +} + +/* + * Try to post all desired receive buffers for all pipes. + * Returns 0 if all desired buffers are posted, + * non-zero if were were unable to completely + * replenish receive buffers. + */ +static int +hif_post_recv_buffers(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + A_target_id_t targid = hif_state->targid; + int pipe_num, rv=0; + + A_TARGET_ACCESS_LIKELY(targid); + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + struct HIF_CE_pipe_info *pipe_info; + + pipe_info = &hif_state->pipe_info[pipe_num]; + if (hif_post_recv_buffers_for_pipe(pipe_info)) { + rv = 1; + goto done; + } + } + +done: + A_TARGET_ACCESS_UNLIKELY(targid); + + return rv; +} + +void HIFDump(HIF_DEVICE *hif_device, u_int8_t cmd_id, bool start) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + + switch (cmd_id) { + case AGC_DUMP: + if (start) + priv_start_agc(sc); + else + priv_dump_agc(sc); + break; + + case CHANINFO_DUMP: + if (start) + priv_start_cap_chaninfo(sc); + else + priv_dump_chaninfo(sc); + break; + + case BB_WATCHDOG_DUMP: + priv_dump_bbwatchdog(sc); + break; + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + case PCIE_ACCESS_DUMP: + HIFTargetDumpAccessLog(); + break; +#endif + default: + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Invalid htc dump command\n")); + break; + } +} + +A_STATUS +HIFStart(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + + if (hif_completion_thread_startup(hif_state)) + return A_ERROR; + + hif_msg_callbacks_install(hif_device); + + /* Post buffers once to start things off. */ + (void)hif_post_recv_buffers(hif_device); + + hif_state->started = TRUE; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return A_OK; +} + +void +HIFGrowBuffers(hif_handle_t hif_hdl) +{ + struct hif_pci_softc *sc = hif_hdl; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *) sc->hif_device; + struct HIF_CE_pipe_info *pipe_info; + struct CE_attr *attr; + int pipe_num; + + for (pipe_num = 0; pipe_num < sc->ce_count; pipe_num++) { + pipe_info = &hif_state->pipe_info[pipe_num]; + attr = &host_CE_config[pipe_num]; + if (attr->dest_nentries > 0) { + adf_os_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + atomic_set(&pipe_info->recv_bufs_needed, attr->dest_nentries-1 - initBufferCount(attr->dest_nentries -1)); + adf_os_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + if (hif_post_recv_buffers_for_pipe(pipe_info)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s failed to grow\n",__FUNCTION__)); + break; + } + } + } +} + +void +hif_recv_buffer_cleanup_on_pipe(struct HIF_CE_pipe_info *pipe_info) +{ + struct ol_softc *scn; + struct CE_handle *ce_hdl; + u_int32_t buf_sz; + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + adf_nbuf_t netbuf; + CE_addr_t CE_data; + void *per_CE_context; + + buf_sz = pipe_info->buf_sz; + if (buf_sz == 0) { + /* Unused Copy Engine */ + return; + } + + hif_state = pipe_info->HIF_CE_state; + if (!hif_state->started) { + return; + } + + sc = hif_state->sc; + scn = sc->ol_sc; + ce_hdl = pipe_info->ce_hdl; + + if (scn->adf_dev == NULL) { + return; + } + while (CE_revoke_recv_next(ce_hdl, &per_CE_context, (void **)&netbuf, &CE_data) == A_OK) + { +#ifdef HTC_CRP_DEBUG + if (CE_HOST_T2H_WMI == pipe_info->pipe_num) + adf_nbuf_unmap_single(scn->adf_dev, netbuf, + ADF_OS_DMA_BIDIRECTIONAL); + else +#endif + adf_nbuf_unmap_single(scn->adf_dev, netbuf, ADF_OS_DMA_FROM_DEVICE); + + adf_nbuf_free(netbuf); + } +} + +void +hif_send_buffer_cleanup_on_pipe(struct HIF_CE_pipe_info *pipe_info) +{ + struct CE_handle *ce_hdl; + struct HIF_CE_state *hif_state; + adf_nbuf_t netbuf; + void *per_CE_context; + CE_addr_t CE_data; + unsigned int nbytes; + unsigned int id; + u_int32_t buf_sz; + + buf_sz = pipe_info->buf_sz; + if (buf_sz == 0) { + /* Unused Copy Engine */ + return; + } + + hif_state = pipe_info->HIF_CE_state; + if (!hif_state->started) { + return; + } + + ce_hdl = pipe_info->ce_hdl; + + while (CE_cancel_send_next(ce_hdl, &per_CE_context, (void **)&netbuf, &CE_data, &nbytes, &id) == A_OK) + { + if (netbuf != CE_SENDLIST_ITEM_CTXT) + { + /* + * Packets enqueued by htt_h2t_ver_req_msg() and + * htt_h2t_rx_ring_cfg_msg_ll() have already been freed in + * htt_htc_misc_pkt_pool_free() in WLANTL_Close(), so do not + * free them here again by checking whether it's the EndPoint + * which they are queued in. + */ + if (id == hif_state->sc->htc_endpoint) { + return; + } + /* Indicate the completion to higer layer to free the buffer */ + hif_state->msg_callbacks_current.txCompletionHandler( + hif_state->msg_callbacks_current.Context, netbuf, id); + } + } +} + +/* + * Cleanup residual buffers for device shutdown: + * buffers that were enqueued for receive + * buffers that were to be sent + * Note: Buffers that had completed but which were + * not yet processed are on a completion queue. They + * are handled when the completion thread shuts down. + */ +void +hif_buffer_cleanup(struct HIF_CE_state *hif_state) +{ + struct hif_pci_softc *sc = hif_state->sc; + int pipe_num; + + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + struct HIF_CE_pipe_info *pipe_info; + + pipe_info = &hif_state->pipe_info[pipe_num]; + hif_recv_buffer_cleanup_on_pipe(pipe_info); + hif_send_buffer_cleanup_on_pipe(pipe_info); + } +} + +void +HIFFlushSurpriseRemove(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + hif_buffer_cleanup(hif_state); +} + +void +HIFStop(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + int pipe_num; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + + if (!hif_state->started && !sc->hif_init_done) { + return; /* already stopped or stopping */ + } + + if (sc->hdd_startup_reinit_flag == TRUE) + return; /* If still in wlan_hdd_startup or wlan_hdd_reinit nop. */ + + sc->hif_init_done = FALSE; + + if (hif_state->started) { + /* sync shutdown */ + hif_completion_thread_shutdown(hif_state); + hif_completion_thread(hif_state); + } else { + hif_completion_thread_shutdown(hif_state); + } + + /* + * At this point, asynchronous threads are stopped, + * The Target should not DMA nor interrupt, Host code may + * not initiate anything more. So we just need to clean + * up Host-side state. + */ + +#if defined(CONFIG_ATH_PROCFS_DIAG_SUPPORT) + athdiag_procfs_remove(); +#endif + + hif_buffer_cleanup(hif_state); + + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + struct HIF_CE_pipe_info *pipe_info; + + pipe_info = &hif_state->pipe_info[pipe_num]; + if (pipe_info->ce_hdl) { + CE_fini(pipe_info->ce_hdl); + pipe_info->ce_hdl = NULL; + pipe_info->buf_sz = 0; + } + } + + adf_os_timer_cancel(&hif_state->sleep_timer); + adf_os_timer_free(&hif_state->sleep_timer); + + hif_state->started = FALSE; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); +} + + +int +hifWaitForPendingRecv(HIF_DEVICE *device) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" %s\n",__FUNCTION__)); + /* Nothing needed -- CE layer will notify via recv completion */ + + return EOK; +} + +void +HIFShutDownDevice(HIF_DEVICE *hif_device) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+%s\n",__FUNCTION__)); + + if (hif_device) { + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + + HIFStop(hif_device); + A_FREE(hif_state); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-%s\n",__FUNCTION__)); +} + +/* Track a BMI transaction that is in progress */ +#ifndef BIT +#define BIT(n) (1 << (n)) +#endif + +typedef enum { + BMI_REQ_SEND_DONE = BIT(0), /* the bmi request is done(tx completion) */ + BMI_RESP_RECV_DONE = BIT(1), /* the bmi respond is received */ +} BMI_TRANSACTION_FLAGS; + +struct BMI_transaction { + struct HIF_CE_state *hif_state; + adf_os_mutex_t bmi_transaction_sem; + A_UINT8 *bmi_request_host; /* Request BMI message in Host address space */ + CE_addr_t bmi_request_CE; /* Request BMI message in CE address space */ + u_int32_t bmi_request_length; /* Length of BMI request */ + A_UINT8 *bmi_response_host; /* Response BMI message in Host address space */ + CE_addr_t bmi_response_CE; /* Response BMI message in CE address space */ + unsigned int bmi_response_length;/* Length of received response */ + unsigned int bmi_timeout_ms; + A_UINT32 bmi_transaction_flags; /* flags for the transcation in bmi stage */ +}; + +/* + * send/recv completion functions for BMI. + * NB: The "net_buf" parameter is actually just a straight buffer, not an sk_buff. + */ +static void +HIF_BMI_send_done(struct CE_handle *copyeng, void *ce_context, void *transfer_context, + CE_addr_t data, unsigned int nbytes, unsigned int transfer_id, + unsigned int sw_index, unsigned int hw_index) +{ + struct BMI_transaction *transaction = (struct BMI_transaction *)transfer_context; + struct hif_pci_softc *sc = transaction->hif_state->sc; + +#ifdef BMI_RSP_POLLING + /* + * Fix EV118783, Release a semaphore after sending + * no matter whether a response is been expecting now. + */ + adf_os_mutex_release(sc->ol_sc->adf_dev, &transaction->bmi_transaction_sem); +#else + /* + * If a response is anticipated, we'll complete the + * transaction if the response has been received. + * If no response is anticipated, complete the + * transaction now. + */ + transaction->bmi_transaction_flags |= BMI_REQ_SEND_DONE; + + /* resp is't needed or has already been received, never assume resp comes later then this */ + if (!transaction->bmi_response_CE || + (transaction->bmi_transaction_flags & BMI_RESP_RECV_DONE)) { + adf_os_mutex_release(sc->ol_sc->adf_dev, &transaction->bmi_transaction_sem); + } +#endif +} + +#ifndef BMI_RSP_POLLING +static void +HIF_BMI_recv_data(struct CE_handle *copyeng, void *ce_context, void *transfer_context, + CE_addr_t data, unsigned int nbytes, unsigned int transfer_id, unsigned int flags) +{ + struct BMI_transaction *transaction = (struct BMI_transaction *)transfer_context; + struct hif_pci_softc *sc = transaction->hif_state->sc; + + transaction->bmi_response_length = nbytes; + transaction->bmi_transaction_flags |= BMI_RESP_RECV_DONE; + + /* when both send/recv are done, the sem can be released */ + if (transaction->bmi_transaction_flags & BMI_REQ_SEND_DONE) { + adf_os_mutex_release(sc->ol_sc->adf_dev, &transaction->bmi_transaction_sem); + } +} +#endif + +int +HIFExchangeBMIMsg(HIF_DEVICE *hif_device, + A_UINT8 *bmi_request, + u_int32_t request_length, + A_UINT8 *bmi_response, + u_int32_t *bmi_response_lengthp, + u_int32_t TimeoutMS) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + struct ol_softc *scn = sc->ol_sc; + struct HIF_CE_pipe_info *send_pipe_info = &(hif_state->pipe_info[BMI_CE_NUM_TO_TARG]); + struct CE_handle *ce_send = send_pipe_info->ce_hdl; + CE_addr_t CE_request, CE_response = 0; + A_target_id_t targid = hif_state->targid; + struct BMI_transaction *transaction = NULL; + int status = EOK; + struct HIF_CE_pipe_info *recv_pipe_info = &(hif_state->pipe_info[BMI_CE_NUM_TO_HOST]); + struct CE_handle *ce_recv = recv_pipe_info->ce_hdl; + +#ifdef BMI_RSP_POLLING + CE_addr_t buf; + unsigned int completed_nbytes, id, flags; + int i; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" %s\n",__FUNCTION__)); + + transaction = (struct BMI_transaction *)A_MALLOC(sizeof(*transaction)); + if (unlikely(!transaction)) { + return -ENOMEM; + } + + A_TARGET_ACCESS_LIKELY(targid); + + /* Initialize bmi_transaction_sem to block */ + adf_os_init_mutex(&transaction->bmi_transaction_sem); + adf_os_mutex_acquire(scn->adf_dev, &transaction->bmi_transaction_sem); + + transaction->hif_state = hif_state; + transaction->bmi_request_host = bmi_request; + transaction->bmi_request_length = request_length; + transaction->bmi_response_length = 0; + transaction->bmi_timeout_ms = TimeoutMS; + transaction->bmi_transaction_flags = 0; + + /* + * CE_request = dma_map_single(dev, (void *)bmi_request, request_length, DMA_TO_DEVICE); + */ + CE_request = scn->BMICmd_pa; + transaction->bmi_request_CE = CE_request; + + if (bmi_response) { + + /* + * CE_response = dma_map_single(dev, bmi_response, BMI_DATASZ_MAX, DMA_FROM_DEVICE); + */ + CE_response = scn->BMIRsp_pa; + transaction->bmi_response_host = bmi_response; + transaction->bmi_response_CE = CE_response; + /* dma_cache_sync(dev, bmi_response, BMI_DATASZ_MAX, DMA_FROM_DEVICE); */ + pci_dma_sync_single_for_device(scn->sc_osdev->bdev, CE_response, BMI_DATASZ_MAX, PCI_DMA_FROMDEVICE); + CE_recv_buf_enqueue(ce_recv, transaction, transaction->bmi_response_CE); + /* NB: see HIF_BMI_recv_done */ + } else { + transaction->bmi_response_host = NULL; + transaction->bmi_response_CE = 0; + } + + /* dma_cache_sync(dev, bmi_request, request_length, DMA_TO_DEVICE); */ + pci_dma_sync_single_for_device(scn->sc_osdev->bdev, CE_request, request_length, PCI_DMA_TODEVICE); + + status = CE_send(ce_send, transaction, CE_request, request_length, -1, 0); + ASSERT(status == EOK); + /* NB: see HIF_BMI_send_done */ + + /* TBDXXX: handle timeout */ + + /* Wait for BMI request/response transaction to complete */ + /* Always just wait for BMI request here if BMI_RSP_POLLING is defined */ + while (adf_os_mutex_acquire(scn->adf_dev, &transaction->bmi_transaction_sem)) { + /*need some break out condition(time out?)*/ + } + + if (bmi_response) { +#ifdef BMI_RSP_POLLING + /* Fix EV118783, do not wait a semaphore for the BMI response + * since the relative interruption may be lost. + * poll the BMI response instead. + */ + i = 0; + while (CE_completed_recv_next(ce_recv, NULL, NULL, &buf, &completed_nbytes, &id, &flags) != A_OK) { + if (i++ > BMI_RSP_TO_MILLISEC) { + printk("%s:error, can't get bmi response\n", __func__); + status = A_EBUSY; + break; + } + OS_DELAY(1000); + } + + if ((status == EOK) && bmi_response_lengthp) { + *bmi_response_lengthp = completed_nbytes; + } +#else + if ((status == EOK) && bmi_response_lengthp) { + *bmi_response_lengthp = transaction->bmi_response_length; + } +#endif + + } + + /* dma_unmap_single(dev, transaction->bmi_request_CE, request_length, DMA_TO_DEVICE); */ + //bus_unmap_single(scn->sc_osdev, transaction->bmi_request_CE, request_length, BUS_DMA_TODEVICE); + + if (status != EOK) { + CE_addr_t unused_buffer; + unsigned int unused_nbytes; + unsigned int unused_id; + + CE_cancel_send_next(ce_send, NULL, NULL, &unused_buffer, &unused_nbytes, &unused_id); + } + + A_TARGET_ACCESS_UNLIKELY(targid); + A_FREE(transaction); + return status; +} + + +/* CE_PCI TABLE */ +/* + * NOTE: the table below is out of date, though still a useful reference. + * Refer to target_service_to_CE_map and HIFMapServiceToPipe for the actual + * mapping of HTC services to HIF pipes. + */ +/* + * This authoritative table defines Copy Engine configuration and the mapping + * of services/endpoints to CEs. A subset of this information is passed to + * the Target during startup as a prerequisite to entering BMI phase. + * See: + * target_service_to_CE_map - Target-side mapping + * HIFMapServiceToPipe - Host-side mapping + * target_CE_config - Target-side configuration + * host_CE_config - Host-side configuration +============================================================================= +Purpose | Service / Endpoint | CE | Dire | Xfer | Xfer + | | | ctio | Size | Frequency + | | | n | | +============================================================================= +tx | HTT_DATA (downlink) | CE 0 | h->t | medium - | very frequent +descriptor | | | | O(100B) | and regular +download | | | | | +----------------------------------------------------------------------------- +rx | HTT_DATA (uplink) | CE 1 | t->h | small - | frequent and +indication | | | | O(10B) | regular +upload | | | | | +----------------------------------------------------------------------------- +MSDU | DATA_BK (uplink) | CE 2 | t->h | large - | rare +upload | | | | O(1000B) | (frequent +e.g. noise | | | | | during IP1.0 +packets | | | | | testing) +----------------------------------------------------------------------------- +MSDU | DATA_BK (downlink) | CE 3 | h->t | large - | very rare +download | | | | O(1000B) | (frequent +e.g. | | | | | during IP1.0 +misdirecte | | | | | testing) +d EAPOL | | | | | +packets | | | | | +----------------------------------------------------------------------------- +n/a | DATA_BE, DATA_VI | CE 2 | t->h | | never(?) + | DATA_VO (uplink) | | | | +----------------------------------------------------------------------------- +n/a | DATA_BE, DATA_VI | CE 3 | h->t | | never(?) + | DATA_VO (downlink) | | | | +----------------------------------------------------------------------------- +WMI events | WMI_CONTROL (uplink) | CE 4 | t->h | medium - | infrequent + | | | | O(100B) | +----------------------------------------------------------------------------- +WMI | WMI_CONTROL | CE 5 | h->t | medium - | infrequent +messages | (downlink) | | | O(100B) | + | | | | | +----------------------------------------------------------------------------- +n/a | HTC_CTRL_RSVD, | CE 1 | t->h | | never(?) + | HTC_RAW_STREAMS | | | | + | (uplink) | | | | +----------------------------------------------------------------------------- +n/a | HTC_CTRL_RSVD, | CE 0 | h->t | | never(?) + | HTC_RAW_STREAMS | | | | + | (downlink) | | | | +----------------------------------------------------------------------------- +diag | none (raw CE) | CE 7 | t<>h | 4 | Diag Window + | | | | | infrequent +============================================================================= + */ + +/* + * Map from service/endpoint to Copy Engine. + * This table is derived from the CE_PCI TABLE, above. + * It is passed to the Target at startup for use by firmware. + */ +static struct service_to_pipe target_service_to_CE_map_wlan[] = { + { + WMI_DATA_VO_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_VO_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_BK_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_BK_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_BE_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_BE_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_VI_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_VI_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_CONTROL_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_CONTROL_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + HTC_CTRL_RSVD_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, /* could be moved to 3 (share with WMI) */ + }, + { + HTC_CTRL_RSVD_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + HTC_RAW_STREAMS_SVC, /* not currently used */ + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, + }, + { + HTC_RAW_STREAMS_SVC, /* not currently used */ + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 4, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, +#ifdef IPA_UC_OFFLOAD + { + WDI_IPA_TX_SVC, + PIPEDIR_OUT, /* in = DL = target -> host */ + 5, + }, +#endif /* IPA_UC_OFFLOAD */ + /* (Additions here) */ + + { /* Must be last */ + 0, + 0, + 0, + }, +}; + +static struct service_to_pipe *target_service_to_CE_map = target_service_to_CE_map_wlan; +static int target_service_to_CE_map_sz = sizeof(target_service_to_CE_map_wlan); + +static struct service_to_pipe target_service_to_CE_map_wlan_epping[] = { + { WMI_DATA_VO_SVC, PIPEDIR_OUT, 3, }, /* out = UL = host -> target */ + { WMI_DATA_VO_SVC, PIPEDIR_IN, 2, }, /* in = DL = target -> host */ + { WMI_DATA_BK_SVC, PIPEDIR_OUT, 4, }, /* out = UL = host -> target */ + { WMI_DATA_BK_SVC, PIPEDIR_IN, 1, }, /* in = DL = target -> host */ + { WMI_DATA_BE_SVC, PIPEDIR_OUT, 3, }, /* out = UL = host -> target */ + { WMI_DATA_BE_SVC, PIPEDIR_IN, 2, }, /* in = DL = target -> host */ + { WMI_DATA_VI_SVC, PIPEDIR_OUT, 3, }, /* out = UL = host -> target */ + { WMI_DATA_VI_SVC, PIPEDIR_IN, 2, }, /* in = DL = target -> host */ + { WMI_CONTROL_SVC, PIPEDIR_OUT, 3, }, /* out = UL = host -> target */ + { WMI_CONTROL_SVC, PIPEDIR_IN, 2, }, /* in = DL = target -> host */ + { HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0, }, /* out = UL = host -> target */ + { HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 1, }, /* in = DL = target -> host */ + { HTC_RAW_STREAMS_SVC, PIPEDIR_OUT, 0, }, /* out = UL = host -> target */ + { HTC_RAW_STREAMS_SVC, PIPEDIR_IN, 1, }, /* in = DL = target -> host */ + { HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4, }, /* out = UL = host -> target */ + { HTT_DATA_MSG_SVC, PIPEDIR_IN, 1, }, /* in = DL = target -> host */ + { 0, 0, 0, }, /* Must be last */ +}; + +/* + * Send an interrupt to the device to wake up the Target CPU + * so it has an opportunity to notice any changed state. + */ +void +HIF_wake_target_cpu(struct hif_pci_softc *sc) +{ + A_STATUS rv; + A_UINT32 core_ctrl; + + rv = HIFDiagReadAccess(sc->hif_device, SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS, &core_ctrl); + ASSERT(rv == A_OK); + + core_ctrl |= CORE_CTRL_CPU_INTR_MASK; /* A_INUM_FIRMWARE interrupt to Target CPU */ + + rv = HIFDiagWriteAccess(sc->hif_device, SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS, core_ctrl); + ASSERT(rv == A_OK); +} + +#define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 +#define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 +static void +HIF_sleep_entry(void *arg) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)arg; + A_target_id_t pci_addr = TARGID_TO_PCI_ADDR(hif_state->targid); + struct hif_pci_softc *sc = hif_state->sc; + u_int32_t idle_ms; + + if (vos_is_unload_in_progress()) + return; + + if (sc->recovery) + return; + + adf_os_spin_lock_irqsave(&hif_state->keep_awake_lock); + if (hif_state->verified_awake == FALSE) { + idle_ms = adf_os_ticks_to_msecs(adf_os_ticks() + - hif_state->sleep_ticks); + if (idle_ms >= HIF_MIN_SLEEP_INACTIVITY_TIME_MS) { + if (!adf_os_atomic_read(&sc->pci_link_suspended)) { + A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + hif_state->fake_sleep = FALSE; + } + } else { + adf_os_timer_cancel(&hif_state->sleep_timer); + adf_os_timer_start(&hif_state->sleep_timer, + HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } + } else { + adf_os_timer_cancel(&hif_state->sleep_timer); + adf_os_timer_start(&hif_state->sleep_timer, + HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } + adf_os_spin_unlock_irqrestore(&hif_state->keep_awake_lock); +} + +void +HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + A_target_id_t pci_addr = TARGID_TO_PCI_ADDR(hif_state->targid); + struct hif_pci_softc *sc = hif_state->sc; + + adf_os_spin_lock_irqsave(&hif_state->keep_awake_lock); + /* + * If the deferred sleep timer is running cancel it + * and put the soc into sleep. + */ + if (hif_state->fake_sleep == TRUE) { + adf_os_timer_cancel(&hif_state->sleep_timer); + if (hif_state->verified_awake == FALSE) { + A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + } + hif_state->fake_sleep = FALSE; + } + adf_os_spin_unlock_irqrestore(&hif_state->keep_awake_lock); +} + +/* + * Called from PCI layer whenever a new PCI device is probed. + * Initializes per-device HIF state and notifies the main + * driver that a new HIF device is present. + */ +int +HIF_PCIDeviceProbed(hif_handle_t hif_hdl) +{ + struct HIF_CE_state *hif_state; + struct HIF_CE_pipe_info *pipe_info; + int pipe_num; + A_STATUS rv; + struct hif_pci_softc *sc = hif_hdl; + struct ol_softc *scn = sc->ol_sc; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n",__FUNCTION__)); + + /* if epping is enabled we need to use the epping configuration. */ + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { + if (WLAN_IS_EPPING_IRQ(vos_get_conparam())) + host_CE_config = host_CE_config_wlan_epping_irq; + else + host_CE_config = host_CE_config_wlan_epping_poll; + target_CE_config = target_CE_config_wlan_epping; + target_CE_config_sz = sizeof(target_CE_config_wlan_epping); + target_service_to_CE_map = target_service_to_CE_map_wlan_epping; + target_service_to_CE_map_sz = sizeof(target_service_to_CE_map_wlan_epping); + } + + hif_state = (struct HIF_CE_state *)A_MALLOC(sizeof(*hif_state)); + if (!hif_state) { + return -ENOMEM; + } + + A_MEMZERO(hif_state, sizeof(*hif_state)); + + sc->hif_device = (HIF_DEVICE *)hif_state; + hif_state->sc = sc; + + adf_os_spinlock_init(&hif_state->keep_awake_lock); + + adf_os_spinlock_init(&hif_state->suspend_lock); + + adf_os_atomic_init(&hif_state->hif_thread_idle); + adf_os_atomic_inc(&hif_state->hif_thread_idle); + + hif_state->keep_awake_count = 0; + + hif_state->fake_sleep = FALSE; + hif_state->sleep_ticks = 0; + adf_os_timer_init(NULL, &hif_state->sleep_timer, + HIF_sleep_entry, (void *)hif_state, + ADF_NON_DEFERRABLE_TIMER); + + hif_state->fw_indicator_address = FW_INDICATOR_ADDRESS; + hif_state->targid = A_TARGET_ID(sc->hif_device); +#if CONFIG_ATH_PCIE_MAX_PERF || CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD + /* Force AWAKE forever/till the driver is loaded */ + if (HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE) < 0) + return -EACCES; +#endif + + A_TARGET_ACCESS_LIKELY(hif_state->targid); /* During CE initializtion */ + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + struct CE_attr *attr; + + pipe_info = &hif_state->pipe_info[pipe_num]; + pipe_info->pipe_num = pipe_num; + pipe_info->HIF_CE_state = hif_state; + attr = &host_CE_config[pipe_num]; + pipe_info->ce_hdl = CE_init(sc, pipe_num, attr); + ASSERT(pipe_info->ce_hdl != NULL); + + if (pipe_num == sc->ce_count-1) { + /* Reserve the ultimate CE for Diagnostic Window support */ + hif_state->ce_diag = hif_state->pipe_info[sc->ce_count-1].ce_hdl; + continue; + } + + pipe_info->buf_sz = (adf_os_size_t)(attr->src_sz_max); + adf_os_spinlock_init(&pipe_info->recv_bufs_needed_lock); + if (attr->dest_nentries > 0) { + atomic_set(&pipe_info->recv_bufs_needed, initBufferCount(attr->dest_nentries-1)); + } else { + atomic_set(&pipe_info->recv_bufs_needed, 0); + } + } + +#if defined(CONFIG_ATH_PROCFS_DIAG_SUPPORT) + if (athdiag_procfs_init(sc) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athdiag_procfs_init failed\n")); + return A_ERROR; + } +#endif + + /* + * Initially, establish CE completion handlers for use with BMI. + * These are overwritten with generic handlers after we exit BMI phase. + */ + pipe_info = &hif_state->pipe_info[BMI_CE_NUM_TO_TARG]; + CE_send_cb_register(pipe_info->ce_hdl, HIF_BMI_send_done, pipe_info, 0); +#ifndef BMI_RSP_POLLING + pipe_info = &hif_state->pipe_info[BMI_CE_NUM_TO_HOST]; + CE_recv_cb_register(pipe_info->ce_hdl, HIF_BMI_recv_data, pipe_info, 0); +#endif + + { /* Download to Target the CE Configuration and the service-to-CE map */ + A_UINT32 interconnect_targ_addr = host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_interconnect_state)); + A_UINT32 pcie_state_targ_addr = 0; + A_UINT32 pipe_cfg_targ_addr = 0; + A_UINT32 svc_to_pipe_map = 0; + A_UINT32 pcie_config_flags = 0; + + /* Supply Target-side CE configuration */ + rv = HIFDiagReadAccess(sc->hif_device, interconnect_targ_addr, &pcie_state_targ_addr); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get pcie state addr (%d)\n", rv)); + goto done; + } + if (pcie_state_targ_addr == 0) { + rv = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed pcie state addr is 0\n")); + goto done; + } + + rv = HIFDiagReadAccess(sc->hif_device, + pcie_state_targ_addr+offsetof(struct pcie_state_s, pipe_cfg_addr), + &pipe_cfg_targ_addr); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get pipe cfg addr (%d)\n", rv)); + goto done; + } + if (pipe_cfg_targ_addr == 0) { + rv = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed pipe cfg addr is 0\n")); + goto done; + } + + rv = HIFDiagWriteMem(sc->hif_device, pipe_cfg_targ_addr, (A_UINT8 *)target_CE_config, target_CE_config_sz); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed write pipe cfg (%d)\n", rv)); + goto done; + } + + rv = HIFDiagReadAccess(sc->hif_device, + pcie_state_targ_addr+offsetof(struct pcie_state_s, svc_to_pipe_map), + &svc_to_pipe_map); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get svc/pipe map (%d)\n", rv)); + goto done; + } + if (svc_to_pipe_map == 0) { + rv = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed svc_to_pipe map is 0\n")); + goto done; + } + + rv = HIFDiagWriteMem(sc->hif_device, + svc_to_pipe_map, + (A_UINT8 *)target_service_to_CE_map, + target_service_to_CE_map_sz); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed write svc/pipe map (%d)\n", rv)); + goto done; + } + + rv = HIFDiagReadAccess(sc->hif_device, + pcie_state_targ_addr+offsetof(struct pcie_state_s, config_flags), + &pcie_config_flags); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get pcie config_flags (%d)\n", rv)); + goto done; + } + +#if (CONFIG_PCIE_ENABLE_L1_CLOCK_GATE) + pcie_config_flags |= PCIE_CONFIG_FLAG_ENABLE_L1; +#else + pcie_config_flags &= ~PCIE_CONFIG_FLAG_ENABLE_L1; +#endif /* CONFIG_PCIE_ENABLE_L1_CLOCK_GATE */ + pcie_config_flags |= PCIE_CONFIG_FLAG_CLK_SWITCH_WAIT; +#if (CONFIG_PCIE_ENABLE_AXI_CLK_GATE) + pcie_config_flags |= PCIE_CONFIG_FLAG_AXI_CLK_GATE; +#endif + rv = HIFDiagWriteMem(sc->hif_device, + pcie_state_targ_addr+offsetof(struct pcie_state_s, config_flags), + (A_UINT8 *)&pcie_config_flags, + sizeof(pcie_config_flags)); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed write pcie config_flags (%d)\n", rv)); + goto done; + } + } + + { /* configure early allocation */ + A_UINT32 ealloc_value; + A_UINT32 ealloc_targ_addr = host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_early_alloc)); + + rv = HIFDiagReadAccess(sc->hif_device, ealloc_targ_addr, &ealloc_value); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get early alloc val (%d)\n", rv)); + goto done; + } + + /* 1 bank is switched to IRAM, except ROME 1.0 */ + ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & HI_EARLY_ALLOC_MAGIC_MASK); + { + A_UINT8 banks_switched = 1; + A_UINT32 chip_id; + rv = HIFDiagReadAccess(sc->hif_device, CHIP_ID_ADDRESS | RTC_SOC_BASE_ADDRESS, &chip_id); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get chip id val (%d)\n", rv)); + goto done; + } + if (CHIP_ID_VERSION_GET(chip_id) == 0xD) { + scn->target_revision = CHIP_ID_REVISION_GET(chip_id); + switch(CHIP_ID_REVISION_GET(chip_id)) { + case 0x2: /* ROME 1.3 */ + /* 2 banks are switched to IRAM */ + banks_switched = 2; + break; + case 0x4: /* ROME 2.1 */ + case 0x5: /* ROME 2.2 */ + banks_switched = 6; + break; + case 0x8: /* ROME 3.0 */ + case 0x9: /* ROME 3.1 */ + case 0xA: /* ROME 3.2 */ + banks_switched = 9; + break; + case 0x0: /* ROME 1.0 */ + case 0x1: /* ROME 1.1 */ + default: + /* 3 banks are switched to IRAM */ + banks_switched = 3; + break; + } + + } + ealloc_value |= ((banks_switched << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & HI_EARLY_ALLOC_IRAM_BANKS_MASK); + } + rv = HIFDiagWriteAccess(sc->hif_device, ealloc_targ_addr, ealloc_value); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed set early alloc val (%d)\n", rv)); + goto done; + } + } + + { /* Tell Target to proceed with initialization */ + A_UINT32 flag2_value; + A_UINT32 flag2_targ_addr = host_interest_item_address(scn->target_type, offsetof(struct host_interest_s, hi_option_flag2)); + + rv = HIFDiagReadAccess(sc->hif_device, flag2_targ_addr, &flag2_value); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed get option val (%d)\n", rv)); + goto done; + } + + flag2_value |= HI_OPTION_EARLY_CFG_DONE; + rv = HIFDiagWriteAccess(sc->hif_device, flag2_targ_addr, flag2_value); + if (rv != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("ath: HIF_PCIDeviceProbed set option val (%d)\n", rv)); + goto done; + } + + HIF_wake_target_cpu(sc); + } + +done: + A_TARGET_ACCESS_UNLIKELY(hif_state->targid); + + if (rv == A_OK) { + } else { + /* Failure, so clean up */ + for (pipe_num=0; pipe_num < sc->ce_count; pipe_num++) { + pipe_info = &hif_state->pipe_info[pipe_num]; + if (pipe_info->ce_hdl) { + CE_fini(pipe_info->ce_hdl); + pipe_info->ce_hdl = NULL; + pipe_info->buf_sz = 0; + } + } + + adf_os_timer_cancel(&hif_state->sleep_timer); + adf_os_timer_free(&hif_state->sleep_timer); + + A_FREE(hif_state); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n",__FUNCTION__)); + + return (rv != A_OK); +} + +/* + * The "ID" returned here is an opaque cookie used for + * A_TARGET_READ and A_TARGET_WRITE -- low-overhead APIs + * appropriate for PCIe. + */ +A_target_id_t +HIFGetTargetId(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + + return(TARGID(sc)); +} + +extern void HIFdebug(void); + +#ifdef CONFIG_PCI_MSM +static inline void hif_msm_pcie_debug_info(struct hif_pci_softc *sc) +{ + msm_pcie_debug_info(sc->pdev, 13, 1, 0, 0, 0); + msm_pcie_debug_info(sc->pdev, 13, 2, 0, 0, 0); +} +#else +static inline void hif_msm_pcie_debug_info(struct hif_pci_softc *sc) {}; +#endif +/* + * For now, we use simple on-demand sleep/wake. + * Some possible improvements: + * -Use the Host-destined A_INUM_PCIE_AWAKE interrupt rather than spin/delay + * (or perhaps spin/delay for a short while, then convert to sleep/interrupt) + * Careful, though, these functions may be used by interrupt handlers ("atomic") + * -Don't use host_reg_table for this code; instead use values directly + * -Use a separate timer to track activity and allow Target to sleep only + * if it hasn't done anything for a while; may even want to delay some + * processing for a short while in order to "batch" (e.g.) transmit + * requests with completion processing into "windows of up time". Costs + * some performance, but improves power utilization. + * -On some platforms, it might be possible to eliminate explicit + * sleep/wakeup. Instead, take a chance that each access works OK. If not, + * recover from the failure by forcing the Target awake. + * -Change keep_awake_count to an atomic_t in order to avoid spin lock + * overhead in some cases. Perhaps this makes more sense when + * CONFIG_ATH_PCIE_ACCESS_LIKELY is used and less sense when LIKELY is + * disabled. + * -It is possible to compile this code out and simply force the Target + * to remain awake. That would yield optimal performance at the cost of + * increased power. See CONFIG_ATH_PCIE_MAX_PERF. + * + * Note: parameter wait_for_it has meaning only when waking (when sleep_ok==0). + */ +int +HIFTargetSleepStateAdjust(A_target_id_t targid, + A_BOOL sleep_ok, + A_BOOL wait_for_it) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)TARGID_TO_HIF(targid); + A_target_id_t pci_addr = TARGID_TO_PCI_ADDR(targid); + static int max_delay; + static int debug = 0; + struct hif_pci_softc *sc = hif_state->sc; + + + if (sc->recovery) + return -EACCES; + + if (adf_os_atomic_read(&sc->pci_link_suspended)) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "invalid access, PCIe link is suspended"); + debug = 1; + VOS_ASSERT(0); + return -EACCES; + } + + if(debug) { + wait_for_it = TRUE; + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "doing debug for invalid access, PCIe link is suspended"); + VOS_ASSERT(0); + } + + if (sleep_ok) { + adf_os_spin_lock_irqsave(&hif_state->keep_awake_lock); + hif_state->keep_awake_count--; + if (hif_state->keep_awake_count == 0) { + /* Allow sleep */ + hif_state->verified_awake = FALSE; + hif_state->sleep_ticks = adf_os_ticks(); + } + if (hif_state->fake_sleep == FALSE) { + /* Set the Fake Sleep */ + hif_state->fake_sleep = TRUE; + + /* Start the Sleep Timer */ + adf_os_timer_cancel(&hif_state->sleep_timer); + adf_os_timer_start(&hif_state->sleep_timer, + HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } + adf_os_spin_unlock_irqrestore(&hif_state->keep_awake_lock); + } else { + adf_os_spin_lock_irqsave(&hif_state->keep_awake_lock); + + if (hif_state->fake_sleep) { + hif_state->verified_awake = TRUE; + } else { + if (hif_state->keep_awake_count == 0) { + /* Force AWAKE */ + A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + } + } + hif_state->keep_awake_count++; + adf_os_spin_unlock_irqrestore(&hif_state->keep_awake_lock); + + if (wait_for_it && !hif_state->verified_awake) { +#define PCIE_WAKE_TIMEOUT 8000 /* 8Ms */ + int tot_delay = 0; + int curr_delay = 5; + + for (;;) { + if (hif_pci_targ_is_awake(sc, pci_addr)) { + hif_state->verified_awake = TRUE; + break; + } else if (!hif_pci_targ_is_present(targid, pci_addr)) { + break; + } + + //ASSERT(tot_delay <= PCIE_WAKE_TIMEOUT); + if (tot_delay > PCIE_WAKE_TIMEOUT) + { + u_int16_t val; + u_int32_t bar; + + printk("%s: keep_awake_count = %d\n", __func__, + hif_state->keep_awake_count); + + pci_read_config_word(sc->pdev, PCI_VENDOR_ID, &val); + printk("%s: PCI Vendor ID = 0x%04x\n", __func__, val); + + pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &val); + printk("%s: PCI Device ID = 0x%04x\n", __func__, val); + + pci_read_config_word(sc->pdev, PCI_COMMAND, &val); + printk("%s: PCI Command = 0x%04x\n", __func__, val); + + pci_read_config_word(sc->pdev, PCI_STATUS, &val); + printk("%s: PCI Status = 0x%04x\n", __func__, val); + + pci_read_config_dword(sc->pdev, PCI_BASE_ADDRESS_0, &bar); + printk("%s: PCI BAR 0 = 0x%08x\n", __func__, bar); + + printk("%s: PCIE_SOC_WAKE_ADDRESS = 0x%08x, RTC_STATE_ADDRESS = 0x%08x\n", + __func__, + A_PCI_READ32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS), + A_PCI_READ32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS)); + + printk("%s:error, can't wakeup target\n", __func__); + hif_msm_pcie_debug_info(sc); + if (!sc->ol_sc->enable_self_recovery) + VOS_BUG(0); + sc->recovery = true; + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); +#ifdef CONFIG_CNSS + cnss_wlan_pci_link_down(); +#endif + return -EACCES; + } + + OS_DELAY(curr_delay); + tot_delay += curr_delay; + + if (curr_delay < 50) { + curr_delay += 5; + } + } + + /* + * NB: If Target has to come out of Deep Sleep, + * this may take a few Msecs. Typically, though + * this delay should be <30us. + */ + if (tot_delay > max_delay) { + max_delay = tot_delay; + } + } + } + + if(debug && hif_state->verified_awake) { + debug = 0; + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "%s: INTR_ENABLE_REG = 0x%08x, INTR_CAUSE_REG = 0x%08x, " + "CPU_INTR_REG = 0x%08x, INTR_CLR_REG = 0x%08x, " + "CE_INTERRUPT_SUMMARY_REG = 0x%08x", __func__, + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_ENABLE_ADDRESS), + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CAUSE_ADDRESS), + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + CPU_INTR_ADDRESS), + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CLR_ADDRESS), + A_PCI_READ32(sc->mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)); + } + + return EOK; +} + +void +HIFSetTargetSleep(HIF_DEVICE *hif_device, A_BOOL sleep_ok, A_BOOL wait_for_it) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + HIFTargetSleepStateAdjust(hif_state->targid, sleep_ok, wait_for_it); +} + +A_BOOL +HIFTargetForcedAwake(A_target_id_t targid) +{ + A_target_id_t pci_addr = TARGID_TO_PCI_ADDR(targid); + A_BOOL awake; + A_BOOL pcie_forced_awake; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)TARGID_TO_HIF(targid); + struct hif_pci_softc *sc = hif_state->sc; + + awake = hif_pci_targ_is_awake(sc, pci_addr); + + pcie_forced_awake = + !!(A_PCI_READ32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS) & PCIE_SOC_WAKE_V_MASK); + + return (awake && pcie_forced_awake); +} + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +A_UINT32 +HIFTargetReadChecked(A_target_id_t targid, A_UINT32 offset) +{ + A_UINT32 value; + void *addr; + + if (!A_TARGET_ACCESS_OK(targid)) { + HIFdebug(); + } + + addr = TARGID_TO_PCI_ADDR(targid)+offset; + value = A_PCI_READ32(addr); + + { + unsigned long irq_flags; + int idx = pcie_access_log_seqnum % PCIE_ACCESS_LOG_NUM; + + spin_lock_irqsave(&pcie_access_log_lock, irq_flags); + pcie_access_log[idx].seqnum = pcie_access_log_seqnum; + pcie_access_log[idx].is_write = FALSE; + pcie_access_log[idx].addr = addr; + pcie_access_log[idx].value = value; + pcie_access_log_seqnum++; + spin_unlock_irqrestore(&pcie_access_log_lock, irq_flags); + } + + return value; +} + +void +HIFTargetWriteChecked(A_target_id_t targid, A_UINT32 offset, A_UINT32 value) +{ + void *addr; + + if (!A_TARGET_ACCESS_OK(targid)) { + HIFdebug(); + } + + addr = TARGID_TO_PCI_ADDR(targid)+(offset); + A_PCI_WRITE32(addr, value); + + { + unsigned long irq_flags; + int idx = pcie_access_log_seqnum % PCIE_ACCESS_LOG_NUM; + + spin_lock_irqsave(&pcie_access_log_lock, irq_flags); + pcie_access_log[idx].seqnum = pcie_access_log_seqnum; + pcie_access_log[idx].is_write = TRUE; + pcie_access_log[idx].addr = addr; + pcie_access_log[idx].value = value; + pcie_access_log_seqnum++; + spin_unlock_irqrestore(&pcie_access_log_lock, irq_flags); + } +} + +void +HIFdebug(void) +{ + /* BUG_ON(1); */ +// BREAK(); +} + +void +HIFTargetDumpAccessLog(void) +{ + int idx, len, start_idx, cur_idx; + unsigned long irq_flags; + + spin_lock_irqsave(&pcie_access_log_lock, irq_flags); + if (pcie_access_log_seqnum > PCIE_ACCESS_LOG_NUM) + { + len = PCIE_ACCESS_LOG_NUM; + start_idx = pcie_access_log_seqnum % PCIE_ACCESS_LOG_NUM; + } + else + { + len = pcie_access_log_seqnum; + start_idx = 0; + } + + for(idx = 0; idx < len; idx++) + { + cur_idx = (start_idx + idx) % PCIE_ACCESS_LOG_NUM; + printk("idx:%d\t sn:%u wr:%d addr:%p val:%u.\n", + idx, + pcie_access_log[cur_idx].seqnum, + pcie_access_log[cur_idx].is_write, + pcie_access_log[cur_idx].addr, + pcie_access_log[cur_idx].value); + } + + pcie_access_log_seqnum = 0; + spin_unlock_irqrestore(&pcie_access_log_lock, irq_flags); +} +#endif + +/* + * Convert an opaque HIF device handle into the corresponding + * opaque (void *) operating system device handle. + */ +#if ! defined(A_SIMOS_DEVHOST) +void * +HIFDeviceToOsDevice(HIF_DEVICE *hif_device) +{ + return ((struct HIF_CE_state *) hif_device)->sc->dev; +} +#endif + +/* + * Typically called from either the PCI infrastructure when + * a firmware interrupt is pending OR from the the shared PCI + * interrupt handler when a firmware-generated interrupt + * to the Host might be pending. + */ +irqreturn_t +HIF_fw_interrupt_handler(int irq, void *arg) +{ + struct hif_pci_softc *sc = arg; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + A_target_id_t targid = hif_state->targid; + A_UINT32 fw_indicator_address, fw_indicator; + + A_TARGET_ACCESS_BEGIN_RET(targid); + + fw_indicator_address = hif_state->fw_indicator_address; + /* For sudden unplug this will return ~0 */ + fw_indicator = A_TARGET_READ(targid, fw_indicator_address); + + if ((fw_indicator != ~0) && (fw_indicator & FW_IND_EVENT_PENDING)) { + /* ACK: clear Target-side pending event */ + A_TARGET_WRITE(targid, fw_indicator_address, fw_indicator & ~FW_IND_EVENT_PENDING); + A_TARGET_ACCESS_END_RET(targid); + + if (hif_state->started) { + /* Alert the Host-side service thread */ + atomic_set(&hif_state->fw_event_pending, 1); + hif_completion_thread(hif_state); + } else { + /* + * Probable Target failure before we're prepared + * to handle it. Generally unexpected. + */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ath ERROR: Early firmware event indicated\n")); + } + } else { + A_TARGET_ACCESS_END_RET(targid); + } + + return ATH_ISR_SCHED; +} + +void *hif_get_targetdef(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + + return sc->targetdef; +} + +void HIFsuspendwow(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + adf_os_atomic_set(&sc->wow_done, 1); +} + +#ifdef IPA_UC_OFFLOAD +void HIFIpaGetCEResource(HIF_DEVICE *hif_device, + A_UINT32 *ce_sr_base_paddr, + A_UINT32 *ce_sr_ring_size, + A_UINT32 *ce_reg_paddr) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct HIF_CE_pipe_info *pipe_info = + &(hif_state->pipe_info[HIF_PCI_IPA_UC_ASSIGNED_CE]); + struct CE_handle *ce_hdl = pipe_info->ce_hdl; + + CE_ipaGetResource(ce_hdl, ce_sr_base_paddr, ce_sr_ring_size, ce_reg_paddr); + return; +} +#endif /* IPA_UC_OFFLOAD */ + + +#ifdef FEATURE_RUNTIME_PM +/** + * hif_pci_runtime_pm_warn() - Runtime PM Debugging API + * @sc: hif_pci_softc context + * @msg: log message + * + * Return: void + */ +void hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *msg) +{ + struct hif_pm_runtime_context *ctx; + static const char *rpm_status[] = {"RPM_ACTIVE", "RPM_RESUMING", + "RPM_SUSPENDED", "RPM_SUSPENDING"}; + + pr_warn("%s: usage_count: %d, pm_state: %d, prevent_suspend_cnt: %d\n", + msg, atomic_read(&sc->dev->power.usage_count), + atomic_read(&sc->pm_state), + sc->prevent_suspend_cnt); + + pr_warn("runtime_status: %s, runtime_error: %d, disable_depth : %d " + "autosuspend_delay: %d\n", + rpm_status[sc->dev->power.runtime_status], + sc->dev->power.runtime_error, + sc->dev->power.disable_depth, + sc->dev->power.autosuspend_delay); + + pr_warn("runtime_get: %u, runtime_put: %u, request_resume: %u\n", + sc->pm_stats.runtime_get, sc->pm_stats.runtime_put, + sc->pm_stats.request_resume); + + pr_warn("allow_suspend: %u, prevent_suspend: %u\n", + sc->pm_stats.allow_suspend, + sc->pm_stats.prevent_suspend); + + pr_warn("prevent_suspend_timeout: %u, allow_suspend_timeout: %u\n", + sc->pm_stats.prevent_suspend_timeout, + sc->pm_stats.allow_suspend_timeout); + + pr_warn("Suspended: %u, resumed: %u count\n", + sc->pm_stats.suspended, + sc->pm_stats.resumed); + + pr_warn("suspend_err: %u, runtime_get_err: %u\n", + sc->pm_stats.suspend_err, + sc->pm_stats.runtime_get_err); + + pr_warn("Active Wakeup Sources preventing Runtime Suspend: "); + + list_for_each_entry(ctx, &sc->prevent_suspend_list, list) { + pr_warn("%s", ctx->name); + if (ctx->timeout) + pr_warn("(%d ms)", ctx->timeout); + pr_warn(" "); + } + + pr_warn("\n"); + WARN_ON(1); +} + +int hif_pm_runtime_get(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + int ret = 0; + int pm_state = adf_os_atomic_read(&sc->pm_state); + + if (pm_state == HIF_PM_RUNTIME_STATE_ON || + pm_state == HIF_PM_RUNTIME_STATE_NONE) { + sc->pm_stats.runtime_get++; + ret = __hif_pm_runtime_get(sc->dev); + + /* Get can return 1 if the device is already active, just return + * success in that case + */ + if (ret > 0) + ret = 0; + + if (ret) + hif_pm_runtime_put(hif_device); + + if (ret && ret != -EINPROGRESS) { + sc->pm_stats.runtime_get_err++; + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "%s: Runtime Get PM Error in pm_state:%d" + " ret: %d\n", __func__, + adf_os_atomic_read(&sc->pm_state), ret); + } + + return ret; + } + + sc->pm_stats.request_resume++; + sc->pm_stats.last_resume_caller = (void *)_RET_IP_; + ret = hif_pm_request_resume(sc->dev); + + return -EAGAIN; +} + +int hif_pm_runtime_put(HIF_DEVICE *hif_device) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)hif_device; + struct hif_pci_softc *sc = hif_state->sc; + int ret = 0; + int pm_state, usage_count; + unsigned long flags; + + pm_state = adf_os_atomic_read(&sc->pm_state); + usage_count = atomic_read(&sc->dev->power.usage_count); + + /* + * During Driver unload, platform driver increments the usage + * count to prevent any runtime suspend getting called. + * So during driver load in HIF_PM_RUNTIME_STATE_NONE state the + * usage_count should be one. In all other states, whithout + * get calling put is FATAL, so handling that case here. + */ + + if ((pm_state == HIF_PM_RUNTIME_STATE_NONE && usage_count == 1) || + usage_count == 0) { + spin_lock_irqsave(&sc->runtime_lock, flags); + hif_pci_runtime_pm_warn(sc, "PUT Without a Get Operation"); + spin_unlock_irqrestore(&sc->runtime_lock, flags); + return -EINVAL; + } + + sc->pm_stats.runtime_put++; + + hif_pm_runtime_mark_last_busy(sc->dev); + ret = hif_pm_runtime_put_auto(sc->dev); + + return 0; +} + +static int __hif_pm_runtime_prevent_suspend(struct hif_pci_softc + *hif_sc, struct hif_pm_runtime_context *context) +{ + int ret = 0; + + /* + * We shouldn't be setting context->timeout to zero here when + * context is active as we will have a case where Timeout API's + * for the same context called back to back. + * eg: echo "1=T:10:T:20" > /d/cnss_runtime_pm + * Set context->timeout to zero in hif_pm_runtime_prevent_suspend + * API to ensure the timeout version is no more active and + * list entry of this context will be deleted during allow suspend. + */ + if (context->active) + return 0; + + ret = __hif_pm_runtime_get(hif_sc->dev); + + /** + * The ret can be -EINPROGRESS, if Runtime status is RPM_RESUMING or + * RPM_SUSPENDING. Any other negative value is an error. + * We shouldn't be do runtime_put here as in later point allow + * suspend gets called with the the context and there the usage count + * is decremented, so suspend will be prevented. + */ + + if (ret < 0 && ret != -EINPROGRESS) { + hif_sc->pm_stats.runtime_get_err++; + hif_pci_runtime_pm_warn(hif_sc, + "Prevent Suspend Runtime PM Error"); + } + + hif_sc->prevent_suspend_cnt++; + + context->active = true; + + list_add_tail(&context->list, &hif_sc->prevent_suspend_list); + + hif_sc->pm_stats.prevent_suspend++; + + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO, + "%s: in pm_state:%d ret: %d\n", __func__, + adf_os_atomic_read(&hif_sc->pm_state), ret); + + return ret; +} + +static int __hif_pm_runtime_allow_suspend(struct hif_pci_softc *hif_sc, + struct hif_pm_runtime_context *context) +{ + int ret = 0; + int usage_count; + + if (hif_sc->prevent_suspend_cnt == 0) + return ret; + + if (!context->active) + return ret; + + usage_count = atomic_read(&hif_sc->dev->power.usage_count); + + /* + * During Driver unload, platform driver increments the usage + * count to prevent any runtime suspend getting called. + * So during driver load in HIF_PM_RUNTIME_STATE_NONE state the + * usage_count should be one. Ideally this shouldn't happen as + * context->active should be active for allow suspend to happen + * Handling this case here to prevent any failures. + */ + if ((adf_os_atomic_read(&hif_sc->pm_state) == HIF_PM_RUNTIME_STATE_NONE + && usage_count == 1) || usage_count == 0) { + hif_pci_runtime_pm_warn(hif_sc, + "Allow without a prevent suspend"); + return -EINVAL; + } + + list_del(&context->list); + + hif_sc->prevent_suspend_cnt--; + + context->active = false; + context->timeout = 0; + + hif_pm_runtime_mark_last_busy(hif_sc->dev); + ret = hif_pm_runtime_put_auto(hif_sc->dev); + + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO, + "%s: in pm_state:%d ret: %d\n", __func__, + adf_os_atomic_read(&hif_sc->pm_state), ret); + + hif_sc->pm_stats.allow_suspend++; + return ret; +} + +void hif_pci_runtime_pm_timeout_fn(unsigned long data) +{ + struct hif_pci_softc *hif_sc = (struct hif_pci_softc *)data; + unsigned long flags; + unsigned long timer_expires; + struct hif_pm_runtime_context *context, *temp; + + spin_lock_irqsave(&hif_sc->runtime_lock, flags); + + timer_expires = hif_sc->runtime_timer_expires; + + /* Make sure we are not called too early, this should take care of + * following case + * + * CPU0 CPU1 (timeout function) + * ---- ---------------------- + * spin_lock_irq + * timeout function called + * + * mod_timer() + * + * spin_unlock_irq + * spin_lock_irq + */ + if (timer_expires > 0 && !time_after(timer_expires, jiffies)) { + hif_sc->runtime_timer_expires = 0; + list_for_each_entry_safe(context, temp, + &hif_sc->prevent_suspend_list, list) { + if (context->timeout) { + __hif_pm_runtime_allow_suspend(hif_sc, context); + hif_sc->pm_stats.allow_suspend_timeout++; + } + } + } + + spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); +} + +int hif_pm_runtime_prevent_suspend(void *ol_sc, void *data) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + struct hif_pm_runtime_context *context = data; + unsigned long flags; + + if (!sc->enable_runtime_pm) + return 0; + + if (!context) + return -EINVAL; + + spin_lock_irqsave(&hif_sc->runtime_lock, flags); + context->timeout = 0; + __hif_pm_runtime_prevent_suspend(hif_sc, context); + spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + + return 0; +} + +int hif_pm_runtime_allow_suspend(void *ol_sc, void *data) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + struct hif_pm_runtime_context *context = data; + + unsigned long flags; + + if (!sc->enable_runtime_pm) + return 0; + + if (!context) + return -EINVAL; + + spin_lock_irqsave(&hif_sc->runtime_lock, flags); + + __hif_pm_runtime_allow_suspend(hif_sc, context); + + /* The list can be empty as well in cases where + * we have one context in the list and the allow + * suspend came before the timer expires and we delete + * context above from the list. + * When list is empty prevent_suspend count will be zero. + */ + if (hif_sc->prevent_suspend_cnt == 0 && + hif_sc->runtime_timer_expires > 0) { + del_timer(&hif_sc->runtime_timer); + hif_sc->runtime_timer_expires = 0; + } + + spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + + return 0; +} + +/** + * hif_pm_runtime_prevent_suspend_timeout() - Prevent runtime suspend timeout + * @ol_sc: HIF context + * delay: Timeout in milliseconds + * + * Prevent runtime suspend with a timeout after which runtime suspend would be + * allowed. This API uses a single timer to allow the suspend and timer is + * modified if the timeout is changed before timer fires. + * If the timeout is less than autosuspend_delay then use mark_last_busy instead + * of starting the timer. + * + * It is wise to try not to use this API and correct the design if possible. + * + * Return: 0 on success and negative error code on failure + */ +int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, void *data, + unsigned int delay) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + int ret = 0; + unsigned long expires; + unsigned long flags; + struct hif_pm_runtime_context *context = data; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "%s: Load/unload in progress, ignore!", + __func__); + return -EINVAL; + } + + if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in progress, ignore!", __func__); + return -EINVAL; + } + + if (!sc->enable_runtime_pm) + return 0; + + if (!context) + return -EINVAL; + + /* + * Don't use internal timer if the timeout is less than auto suspend + * delay. + */ + if (delay <= hif_sc->dev->power.autosuspend_delay) { + hif_pm_request_resume(hif_sc->dev); + hif_pm_runtime_mark_last_busy(hif_sc->dev); + return ret; + } + + expires = jiffies + msecs_to_jiffies(delay); + expires += !expires; + + spin_lock_irqsave(&hif_sc->runtime_lock, flags); + + context->timeout = delay; + ret = __hif_pm_runtime_prevent_suspend(hif_sc, context); + hif_sc->pm_stats.prevent_suspend_timeout++; + + /* Modify the timer only if new timeout is after already configured + * timeout + */ + if (time_after(expires, hif_sc->runtime_timer_expires)) { + mod_timer(&hif_sc->runtime_timer, expires); + hif_sc->runtime_timer_expires = expires; + } + + spin_unlock_irqrestore(&hif_sc->runtime_lock, flags); + + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO, + "%s: pm_state: %d delay: %dms ret: %d\n", __func__, + adf_os_atomic_read(&hif_sc->pm_state), delay, ret); + + return ret; + +} + +/** + * hif_runtime_pm_prevent_suspend_init() - API to initialize Runtime PM context + * @name: Context name + * + * This API initalizes the Runtime PM context of the caller and + * return the pointer. + * + * Return: void * + */ +void *hif_runtime_pm_prevent_suspend_init(const char *name) +{ + struct hif_pm_runtime_context *context; + + context = adf_os_mem_alloc(NULL, sizeof(*context)); + if (!context) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "%s: No memory for Runtime PM wakelock context\n", + __func__); + return NULL; + } + + context->name = name ? name : "Default"; + return context; +} + +/** + * hif_runtime_pm_prevent_suspend_deinit() - This API frees the runtime pm ctx + * @data: Runtime PM context + * + * Return: void + */ +void hif_runtime_pm_prevent_suspend_deinit(void *data) +{ + unsigned long flags; + struct hif_pm_runtime_context *context = data; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + struct ol_softc *scn = vos_get_context(VOS_MODULE_ID_HIF, + vos_context); + struct hif_pci_softc *sc; + + if (!scn) + return; + + sc = scn->hif_sc; + + if (!sc) + return; + + if (!context) + return; + + /* + * Ensure to delete the context list entry and reduce the usage count + * before freeing the context if context is active. + */ + spin_lock_irqsave(&sc->runtime_lock, flags); + __hif_pm_runtime_allow_suspend(sc, context); + spin_unlock_irqrestore(&sc->runtime_lock, flags); + + adf_os_mem_free(context); +} + +/** + * hif_pm_ssr_runtime_allow_suspend() - Release Runtime Context during SSR + * @sc: hif_pci context + * @context: runtime context + * + * API is used to release runtime pm context from prevent suspend list and + * reduce the usage count taken by the context and set the context state to + * false. + * + * Return: void + */ +void hif_pm_ssr_runtime_allow_suspend(struct hif_pci_softc *sc, void *context) +{ + __hif_pm_runtime_allow_suspend(sc, context); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.h new file mode 100644 index 000000000000..437cadc283fd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * NB: Inappropriate references to "HTC" are used in this (and other) + * HIF implementations. HTC is typically the calling layer, but it + * theoretically could be some alternative. + */ + +/* + * This holds all state needed to process a pending send/recv interrupt. + * The information is saved here as soon as the interrupt occurs (thus + * allowing the underlying CE to re-use the ring descriptor). The + * information here is eventually processed by a completion processing + * thread. + */ + +#include /* adf_os_atomic_read */ +#include "vos_lock.h" +struct HIF_CE_completion_state { + struct HIF_CE_completion_state *next; + int send_or_recv; + struct CE_handle *copyeng; + void *ce_context; + void *transfer_context; + CE_addr_t data; + unsigned int nbytes; + unsigned int transfer_id; + unsigned int flags; +}; + +/* compl_state.send_or_recv */ +#define HIF_CE_COMPLETE_FREE 0 +#define HIF_CE_COMPLETE_SEND 1 +#define HIF_CE_COMPLETE_RECV 2 + +enum ol_ath_hif_pkt_ecodes { + HIF_PIPE_NO_RESOURCE=0 +}; + +struct HIF_CE_state ; + +#define HIF_CE_COMPLETE_STATE_NUM 18 /* 56 * 18 + 4/8 = 1012/1016 bytes */ +struct HIF_CE_completion_state_list { + struct HIF_CE_completion_state_list *next; +}; +/* Per-pipe state. */ +struct HIF_CE_pipe_info { + /* Handle of underlying Copy Engine */ + struct CE_handle *ce_hdl; + + /* Our pipe number; facilitiates use of pipe_info ptrs. */ + A_UINT8 pipe_num; + + /* Convenience back pointer to HIF_CE_state. */ + struct HIF_CE_state *HIF_CE_state; + + /* Instantaneous number of receive buffers that should be posted */ + atomic_t recv_bufs_needed; + adf_os_size_t buf_sz; + adf_os_spinlock_t recv_bufs_needed_lock; + + adf_os_spinlock_t completion_freeq_lock; + /* Limit the number of outstanding send requests. */ + int num_sends_allowed; + struct HIF_CE_completion_state_list *completion_space_list; + struct HIF_CE_completion_state *completion_freeq_head; + struct HIF_CE_completion_state *completion_freeq_tail; + /* adding three counts for debugging ring buffer errors */ + uint32_t nbuf_alloc_err_count; + uint32_t nbuf_dma_err_count; + uint32_t nbuf_ce_enqueue_err_count; +} ; + +struct HIF_CE_state { + struct hif_pci_softc *sc; + A_BOOL started; + + adf_os_spinlock_t keep_awake_lock; + adf_os_spinlock_t suspend_lock; + unsigned int keep_awake_count; + A_BOOL verified_awake; + A_BOOL fake_sleep; + adf_os_timer_t sleep_timer; + unsigned long sleep_ticks; + + //struct task_struct *pci_dev_inserted_thread; + //struct completion pci_dev_inserted_thread_done; + + //wait_queue_head_t replenish_recv_buf_waitq; + //atomic_t replenish_recv_buf_flag; + //struct task_struct *replenish_thread; + //struct completion post_recv_bufs_thread_done; + + adf_os_spinlock_t completion_pendingq_lock; + /* Queue of send/recv completions that need to be processed */ + struct HIF_CE_completion_state *completion_pendingq_head; + struct HIF_CE_completion_state *completion_pendingq_tail; + atomic_t fw_event_pending; + adf_os_atomic_t hif_thread_idle; + + //wait_queue_head_t service_waitq; + //struct task_struct *compl_thread; + //struct completion compl_thread_done; + + /* Per-pipe state. */ + struct HIF_CE_pipe_info pipe_info[CE_COUNT_MAX]; + + MSG_BASED_HIF_CALLBACKS msg_callbacks_pending; /* to be activated after BMI_DONE */ + MSG_BASED_HIF_CALLBACKS msg_callbacks_current; /* current msg callbacks in use */ + + void *claimedContext; + + /* Target address used to signal a pending firmware event */ + u_int32_t fw_indicator_address; + + /* Copy Engine used for Diagnostic Accesses */ + struct CE_handle *ce_diag; + + /* For use with A_TARGET_ API */ + A_target_id_t targid; +}; + +void priv_start_agc(struct hif_pci_softc *sc); +void priv_dump_agc(struct hif_pci_softc *sc); +void priv_start_cap_chaninfo(struct hif_pci_softc *sc); +void priv_dump_chaninfo(struct hif_pci_softc *sc); +void priv_dump_bbwatchdog(struct hif_pci_softc *sc); +void hif_dump_pipe_debug_count(HIF_DEVICE *hif_device); + +#ifdef FEATURE_RUNTIME_PM +#include +void hif_pci_runtime_pm_timeout_fn(unsigned long data); +void hif_pci_runtime_pm_warn(struct hif_pci_softc *, const char *); +void hif_pm_ssr_runtime_allow_suspend(struct hif_pci_softc *, void *); + +/** + * Runtime PM Context for wakelocks + */ +struct hif_pm_runtime_context { + struct list_head list; + bool active; + uint32_t timeout; + const char *name; +}; + +#ifdef WLAN_OPEN_SOURCE +static inline int hif_pm_request_resume(struct device *dev) +{ + return pm_request_resume(dev); +} +static inline int __hif_pm_runtime_get(struct device *dev) +{ + return pm_runtime_get(dev); +} + +static inline int hif_pm_runtime_put_auto(struct device *dev) +{ + return pm_runtime_put_autosuspend(dev); +} + +static inline void hif_pm_runtime_mark_last_busy(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); +} + +static inline int hif_pm_runtime_resume(struct device *dev) +{ + return pm_runtime_resume(dev); +} +#else +static inline int hif_pm_request_resume(struct device *dev) +{ + return cnss_pm_runtime_request(dev, CNSS_PM_REQUEST_RESUME); +} + +static inline int __hif_pm_runtime_get(struct device *dev) +{ + return cnss_pm_runtime_request(dev, CNSS_PM_RUNTIME_GET); +} + +static inline int hif_pm_runtime_put_auto(struct device *dev) +{ + return cnss_pm_runtime_request(dev, CNSS_PM_RUNTIME_PUT_AUTO); +} + +static inline void hif_pm_runtime_mark_last_busy(struct device *dev) +{ + cnss_pm_runtime_request(dev, CNSS_PM_RUNTIME_MARK_LAST_BUSY); +} +static inline int hif_pm_runtime_resume(struct device *dev) +{ + return cnss_pm_runtime_request(dev, CNSS_PM_RUNTIME_RESUME); +} +#endif /* WLAN_OPEN_SOURCE */ +#else /* FEATURE_RUNTIME_PM */ +static inline void +hif_pm_runtime_mark_last_busy(struct device *dev) { } +static inline void +hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *name) { } +static inline void +hif_pm_ssr_runtime_allow_suspend(struct hif_pci_softc *, void *) { } +#endif + +#define CE_HTT_T2H_MSG 1 +#define CE_HTT_H2T_MSG 4 diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c new file mode 100644 index 000000000000..079cef799978 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -0,0 +1,3016 @@ +/* + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +#include +#include +#include +#include +#include +#include "if_pci.h" +#include "hif_msg_based.h" +#include "hif_pci.h" +#include "copy_engine_api.h" +#include "copy_engine_internal.h" +#include "bmi_msg.h" /* TARGET_TYPE_ */ +#include "regtable.h" +#include "ol_fw.h" +#include +#include +#include +#include "vos_api.h" +#include "vos_sched.h" +#include "wma_api.h" +#include "adf_os_atomic.h" +#include "wlan_hdd_power.h" +#include "wlan_hdd_main.h" +#ifdef CONFIG_CNSS +#include +#endif +#include "epping_main.h" + +#ifndef REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "pktlog_ac_api.h" +#include "pktlog_ac.h" +#endif + +#define AR9888_DEVICE_ID (0x003c) +#define AR6320_DEVICE_ID (0x003e) +#define AR6320_FW_1_1 (0x11) +#define AR6320_FW_1_3 (0x13) +#define AR6320_FW_2_0 (0x20) +#define AR6320_FW_3_0 (0x30) +#define AR6320_FW_3_2 (0x32) + +#ifdef CONFIG_SLUB_DEBUG_ON +#define MAX_NUM_OF_RECEIVES 400 /* Maximum number of Rx buf to process before* + break out in SLUB debug builds */ +#else +#define MAX_NUM_OF_RECEIVES 1000 /* Maximum number of Rx buf to process before break out */ +#endif + +#define PCIE_WAKE_TIMEOUT 1000 /* Maximum ms timeout for host to wake up target */ +#define RAMDUMP_EVENT_TIMEOUT 2500 +#define MAX_REG_READ_RETRIES 10 + +unsigned int msienable = 0; +module_param(msienable, int, 0644); + +int hif_pci_configure(struct hif_pci_softc *sc, hif_handle_t *hif_hdl); +void hif_nointrs(struct hif_pci_softc *sc); +static int __hif_pci_suspend(struct pci_dev *, pm_message_t, bool); +static int __hif_pci_resume(struct pci_dev *, bool); + +static void print_config_soc_reg(struct hif_pci_softc *sc) +{ + A_UINT16 val; + A_UINT32 bar0; + + pci_read_config_word(sc->pdev, PCI_VENDOR_ID, &val); + pr_err("%s: PCI Vendor ID = 0x%04x\n", __func__, val); + + pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &val); + pr_err("%s: PCI Device ID = 0x%04x\n", __func__, val); + + pci_read_config_word(sc->pdev, PCI_COMMAND, &val); + pr_err("%s: PCI Command = 0x%04x\n", __func__, val); + + pci_read_config_word(sc->pdev, PCI_STATUS, &val); + pr_err("%s: PCI Status = 0x%04x\n", __func__, val); + + pci_read_config_dword(sc->pdev, PCI_BASE_ADDRESS_0, &bar0); + pr_err("%s: PCI BAR0 = 0x%08x\n", __func__, bar0); + + pr_err("%s: RTC_STATE_ADDRESS = 0x%08x, " + "PCIE_SOC_WAKE_ADDRESS = 0x%08x\n", __func__, + A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS), + A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS)); + + pr_err("%s: 0x80008 = 0x%08x, 0x8000c = 0x%08x, " + "0x80010 = 0x%08x,\n0x80014 = 0x%08x, 0x80018 = 0x%08x, " + "0x8001c = 0x%08x\n", __func__, + A_PCI_READ32(sc->mem + 0x80008), + A_PCI_READ32(sc->mem + 0x8000c), + A_PCI_READ32(sc->mem + 0x80010), + A_PCI_READ32(sc->mem + 0x80014), + A_PCI_READ32(sc->mem + 0x80018), + A_PCI_READ32(sc->mem + 0x8001c)); +}; + +static struct pci_device_id hif_pci_id_table[] = { + { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, + { 0 } +}; + +/* HIF IRQ History */ +typedef enum { + HIF_IRQ, + HIF_TASKLET, + HIF_CRASH, +} hif_irq_type; + +#ifdef CONFIG_SLUB_DEBUG_ON +typedef struct { + hif_irq_type type; + A_UINT64 time; + A_UINT32 irq_summary; + A_UINT32 fw_indicator; +} hif_irq_history; + +#define HIF_IRQ_HISTORY_MAX 1024 +A_UINT32 g_hif_irq_history_idx = 0; +hif_irq_history hif_irq_history_buffer[HIF_IRQ_HISTORY_MAX]; + +void hif_irq_record(hif_irq_type type, struct hif_pci_softc *sc) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + A_target_id_t targid = hif_state->targid; + + if (HIF_IRQ_HISTORY_MAX <= g_hif_irq_history_idx) + g_hif_irq_history_idx = 0; + + hif_irq_history_buffer[g_hif_irq_history_idx].type = type; + hif_irq_history_buffer[g_hif_irq_history_idx].time = adf_get_boottime(); + + HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE); + hif_irq_history_buffer[g_hif_irq_history_idx].irq_summary = + CE_INTERRUPT_SUMMARY(targid); + hif_irq_history_buffer[g_hif_irq_history_idx].fw_indicator = + A_TARGET_READ(targid, hif_state->fw_indicator_address); + HIFTargetSleepStateAdjust(hif_state->targid, TRUE, FALSE); + + g_hif_irq_history_idx++; +} +#else +void hif_irq_record(hif_irq_type type, struct hif_pci_softc *sc) {}; +#endif + +#ifndef REMOVE_PKT_LOG +struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs = NULL; +#endif + +/* Setting SOC_GLOBAL_RESET during driver unload causes intermittent PCIe data bus error + * As workaround for this issue - changing the reset sequence to use TargetCPU warm reset + * instead of SOC_GLOBAL_RESET + */ +#define CPU_WARM_RESET_WAR + +/* + * Top-level interrupt handler for all PCI interrupts from a Target. + * When a block of MSI interrupts is allocated, this top-level handler + * is not used; instead, we directly call the correct sub-handler. + */ +static irqreturn_t +hif_pci_interrupt_handler(int irq, void *arg) +{ + struct hif_pci_softc *sc = (struct hif_pci_softc *) arg; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + volatile int tmp; + + if (sc->hif_init_done == TRUE) { + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + } + + if (LEGACY_INTERRUPTS(sc)) { + + if (sc->hif_init_done == TRUE) { + if (Q_TARGET_ACCESS_BEGIN(hif_state->targid) < 0) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + return IRQ_HANDLED; + } + + hif_irq_record(HIF_IRQ, sc); + } + + /* Clear Legacy PCI line interrupts */ + /* IMPORTANT: INTR_CLR regiser has to be set after INTR_ENABLE is set to 0, */ + /* otherwise interrupt can not be really cleared */ + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), 0); + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_CLR_ADDRESS), PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + /* IMPORTANT: this extra read transaction is required to flush the posted write buffer */ + tmp = A_PCI_READ32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); + + if (tmp == 0xdeadbeef) { + pr_err("BUG(%s): SoC returns 0xdeadbeef!!\n", __func__); + print_config_soc_reg(sc); + VOS_BUG(0); + } + + if (sc->hif_init_done == TRUE) { + if (Q_TARGET_ACCESS_END(hif_state->targid) < 0) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + return IRQ_HANDLED; + } + } + } + /* TBDXXX: Add support for WMAC */ + + sc->irq_event = irq; + adf_os_atomic_set(&sc->tasklet_from_intr, 1); + tasklet_schedule(&sc->intr_tq); + + if (sc->hif_init_done == TRUE) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + } + return IRQ_HANDLED; +} + +static irqreturn_t +hif_pci_msi_fw_handler(int irq, void *arg) +{ + struct hif_pci_softc *sc = (struct hif_pci_softc *) arg; + + (irqreturn_t)HIF_fw_interrupt_handler(sc->irq_event, sc); + + return IRQ_HANDLED; +} + +bool +hif_pci_targ_is_awake(struct hif_pci_softc *sc, void *__iomem *mem) +{ + A_UINT32 val; + + if(sc->recovery) + return false; + + val = A_PCI_READ32(mem + PCIE_LOCAL_BASE_ADDRESS + RTC_STATE_ADDRESS); + return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON); +} + +bool hif_pci_targ_is_present(A_target_id_t targetid, void *__iomem *mem) +{ + return 1; /* FIX THIS */ +} + +bool hif_max_num_receives_reached(unsigned int count) +{ + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + return (count > 120); + else + return (count > MAX_NUM_OF_RECEIVES); +} + +int hif_init_adf_ctx(void *ol_sc) +{ + v_CONTEXT_t pVosContext = NULL; + adf_os_device_t adf_ctx; + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if(pVosContext == NULL) { + return -EFAULT; + } + adf_ctx = vos_mem_malloc(sizeof(*adf_ctx)); + if (!adf_ctx) { + return -ENOMEM; + } + vos_mem_zero(adf_ctx, sizeof(*adf_ctx)); + adf_ctx->drv = &hif_sc->aps_osdev; + adf_ctx->drv_hdl = hif_sc->aps_osdev.bdev; + adf_ctx->dev = hif_sc->aps_osdev.device; + sc->adf_dev = adf_ctx; + ((VosContextType*)(pVosContext))->adf_ctx = adf_ctx; + return 0; +} + +void hif_deinit_adf_ctx(void *ol_sc) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + + if (sc == NULL) + return; + if (sc->adf_dev) { + v_CONTEXT_t pVosContext = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + vos_mem_free(sc->adf_dev); + sc->adf_dev = NULL; + if (pVosContext) + ((VosContextType*)(pVosContext))->adf_ctx = NULL; + } +} + +#define A_PCIE_LOCAL_REG_READ(mem, addr) \ + A_PCI_READ32((char *)(mem) + PCIE_LOCAL_BASE_ADDRESS + (A_UINT32)(addr)) + +#define A_PCIE_LOCAL_REG_WRITE(mem, addr, val) \ + A_PCI_WRITE32(((char *)(mem) + PCIE_LOCAL_BASE_ADDRESS + (A_UINT32)(addr)), (val)) + +#define ATH_PCI_RESET_WAIT_MAX 10 /* Ms */ +static void +hif_pci_device_reset(struct hif_pci_softc *sc) +{ + void __iomem *mem = sc->mem; + int i; + u_int32_t val; + + if (!sc->hostdef) + return; + + /* NB: Don't check resetok here. This form of reset is integral to correct operation. */ + + if (!SOC_GLOBAL_RESET_ADDRESS) { + return; + } + + if (!mem) { + return; + } + + printk("Reset Device \n"); + + /* + * NB: If we try to write SOC_GLOBAL_RESET_ADDRESS without first + * writing WAKE_V, the Target may scribble over Host memory! + */ + A_PCIE_LOCAL_REG_WRITE(mem, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + for (i=0; imem; + int i; + u_int32_t val; + u_int32_t fw_indicator; + + /* NB: Don't check resetok here. This form of reset is integral to correct operation. */ + + if (!mem) { + return; + } + + printk("Target Warm Reset\n"); + + /* + * NB: If we try to write SOC_GLOBAL_RESET_ADDRESS without first + * writing WAKE_V, the Target may scribble over Host memory! + */ + A_PCIE_LOCAL_REG_WRITE(mem, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + for (i=0; ihif_device; + A_target_id_t targid = hif_state->targid; + void __iomem *mem = sc->mem; + uint32_t val; + + A_TARGET_ACCESS_BEGIN_RET(targid); + A_PCI_WRITE32(mem + SOC_CORE_BASE_ADDRESS + + FW_RAM_CONFIG_ADDRESS, config); + val = A_PCI_READ32(mem + SOC_CORE_BASE_ADDRESS + + FW_RAM_CONFIG_ADDRESS); + if (val != config) { + pr_err("%s: Failed to set RAM config reg from 0x%x to 0x%x\n", + __func__, val, config); + A_TARGET_ACCESS_END_RET(targid); + return -EACCES; + } + A_TARGET_ACCESS_END_RET(targid); + return 0; +} + +int hif_pci_check_fw_reg(struct hif_pci_softc *sc) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + A_target_id_t targid = hif_state->targid; + void __iomem *mem = sc->mem; + u_int32_t val; + + A_TARGET_ACCESS_BEGIN_RET(targid); + val = A_PCI_READ32(mem + FW_INDICATOR_ADDRESS); + A_TARGET_ACCESS_END_RET(targid); + + printk("%s: FW_INDICATOR register is 0x%x\n", __func__, val); + + if (val & FW_IND_HELPER) + return 0; + + return 1; +} + +int hif_pci_check_soc_status(struct hif_pci_softc *sc) +{ + u_int16_t device_id; + u_int32_t val; + u_int16_t timeout_count = 0; + + /* Check device ID from PCIe configuration space for link status */ + pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &device_id); + if(device_id != sc->devid) { + printk(KERN_ERR "PCIe link is down!\n"); + return -EACCES; + } + + /* Check PCIe local register for bar/memory access */ + val = A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS); + printk("RTC_STATE_ADDRESS is %08x\n", val); + + /* Try to wake up taget if it sleeps */ + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + printk("PCIE_SOC_WAKE_ADDRESS is %08x\n", + A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS)); + + /* Check if taget can be woken up */ + while(!hif_pci_targ_is_awake(sc, sc->mem)) { + if(timeout_count >= PCIE_WAKE_TIMEOUT) { + printk(KERN_ERR "Target cannot be woken up! " + "RTC_STATE_ADDRESS is %08x, PCIE_SOC_WAKE_ADDRESS is %08x\n", + A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS), A_PCI_READ32(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS)); + return -EACCES; + } + + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + + A_MDELAY(100); + timeout_count += 100; + } + + /* Check Power register for SoC internal bus issues */ + val = A_PCI_READ32(sc->mem + RTC_SOC_BASE_ADDRESS + SOC_POWER_REG_OFFSET); + printk("Power register is %08x\n", val); + + return EOK; +} + +void dump_CE_debug_register(struct hif_pci_softc *sc) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + A_target_id_t targid = hif_state->targid; + void __iomem *mem = sc->mem; + u_int32_t val, i, j; + u_int32_t wrapper_idx[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + u_int32_t ce_base; + + A_TARGET_ACCESS_BEGIN(targid); + + /* DEBUG_INPUT_SEL_SRC = 0x6 */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_INPUT_SEL_OFFSET); + val &= ~WLAN_DEBUG_INPUT_SEL_SRC_MASK; + val |= WLAN_DEBUG_INPUT_SEL_SRC_SET(0x6); + A_PCI_WRITE32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_INPUT_SEL_OFFSET, val); + + /* DEBUG_CONTROL_ENABLE = 0x1 */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_CONTROL_OFFSET); + val &= ~WLAN_DEBUG_CONTROL_ENABLE_MASK; + val |= WLAN_DEBUG_CONTROL_ENABLE_SET(0x1); + A_PCI_WRITE32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_CONTROL_OFFSET, val); + + printk("Debug: inputsel: %x dbgctrl: %x\n", + A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_INPUT_SEL_OFFSET), + A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_CONTROL_OFFSET)); + + printk("Debug CE: \n"); + /* Loop CE debug output */ + /* AMBA_DEBUG_BUS_SEL = 0xc */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET); + val &= ~AMBA_DEBUG_BUS_SEL_MASK; + val |= AMBA_DEBUG_BUS_SEL_SET(0xc); + A_PCI_WRITE32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET, val); + + for (i = 0; i < sizeof(wrapper_idx)/sizeof(A_UINT32); i++) { + /* For (i=1,2,3,4,8,9) write CE_WRAPPER_DEBUG_SEL = i */ + val = A_PCI_READ32(mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_DEBUG_OFFSET); + val &= ~CE_WRAPPER_DEBUG_SEL_MASK; + val |= CE_WRAPPER_DEBUG_SEL_SET(wrapper_idx[i]); + A_PCI_WRITE32(mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_DEBUG_OFFSET, val); + + printk("ce wrapper: %d amdbg: %x cewdbg: %x\n", wrapper_idx[i], + A_PCI_READ32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET), + A_PCI_READ32(mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_DEBUG_OFFSET)); + + if (wrapper_idx[i] <= 7) { + for (j = 0; j <= 5; j++) { + ce_base = CE_BASE_ADDRESS(wrapper_idx[i]); + /* For (j=0~5) write CE_DEBUG_SEL = j */ + val = A_PCI_READ32(mem + ce_base + CE_DEBUG_OFFSET); + val &= ~CE_DEBUG_SEL_MASK; + val |= CE_DEBUG_SEL_SET(j); + A_PCI_WRITE32(mem + ce_base + CE_DEBUG_OFFSET, val); + + /* read (@gpio_athr_wlan_reg) WLAN_DEBUG_OUT_DATA */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_OUT_OFFSET); + val = WLAN_DEBUG_OUT_DATA_GET(val); + + printk(" module%d: cedbg: %x out: %x\n", j, + A_PCI_READ32(mem + ce_base + CE_DEBUG_OFFSET), val); + } + } else { + /* read (@gpio_athr_wlan_reg) WLAN_DEBUG_OUT_DATA */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_OUT_OFFSET); + val = WLAN_DEBUG_OUT_DATA_GET(val); + + printk(" out: %x\n", val); + } + } + + printk("Debug PCIe: \n"); + /* Loop PCIe debug output */ + /* Write AMBA_DEBUG_BUS_SEL = 0x1c */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET); + val &= ~AMBA_DEBUG_BUS_SEL_MASK; + val |= AMBA_DEBUG_BUS_SEL_SET(0x1c); + A_PCI_WRITE32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET, val); + + for (i = 0; i <= 8; i++) { + /* For (i=1~8) write AMBA_DEBUG_BUS_PCIE_DEBUG_SEL = i */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET); + val &= ~AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK; + val |= AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_SET(i); + A_PCI_WRITE32(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET, val); + + /* read (@gpio_athr_wlan_reg) WLAN_DEBUG_OUT_DATA */ + val = A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_OUT_OFFSET); + val = WLAN_DEBUG_OUT_DATA_GET(val); + + printk("amdbg: %x out: %x %x\n", + A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_OUT_OFFSET), val, + A_PCI_READ32(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_OUT_OFFSET)); + } + + A_TARGET_ACCESS_END(targid); +} + +/* + * Handler for a per-engine interrupt on a PARTICULAR CE. + * This is used in cases where each CE has a private + * MSI interrupt. + */ +static irqreturn_t +CE_per_engine_handler(int irq, void *arg) +{ + struct hif_pci_softc *sc = (struct hif_pci_softc *) arg; + int CE_id = irq - MSI_ASSIGN_CE_INITIAL; + + /* + * NOTE: We are able to derive CE_id from irq because we + * use a one-to-one mapping for CE's 0..5. + * CE's 6 & 7 do not use interrupts at all. + * + * This mapping must be kept in sync with the mapping + * used by firmware. + */ + + CE_per_engine_service(sc, CE_id); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_SLUB_DEBUG_ON + +/* worker thread to schedule wlan_tasklet in SLUB debug build */ +static void reschedule_tasklet_work_handler(struct work_struct *recovery) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + struct ol_softc *scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + struct hif_pci_softc *sc; + + if (NULL == scn){ + printk(KERN_ERR "%s: tasklet scn is null\n", __func__); + return; + } + + sc = scn->hif_sc; + + if (sc->hif_init_done == FALSE) { + printk(KERN_ERR "%s: wlan driver is unloaded\n", __func__); + return; + } + + tasklet_schedule(&sc->intr_tq); + return; +} + +static DECLARE_WORK(reschedule_tasklet_work, reschedule_tasklet_work_handler); + +#endif + + +static void +wlan_tasklet(unsigned long data) +{ + struct hif_pci_softc *sc = (struct hif_pci_softc *) data; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + volatile int tmp; + bool hif_init_done = sc->hif_init_done; + + if (hif_init_done == FALSE) { + goto irq_handled; + } + +#ifdef FEATURE_WLAN_D0WOW + if (adf_os_atomic_read(&sc->wow_done) && !adf_os_atomic_read(&sc->in_d0wow)) +#else + if (adf_os_atomic_read(&sc->wow_done)) +#endif + goto irq_handled; + + hif_irq_record(HIF_TASKLET, sc); + + adf_os_atomic_set(&sc->ce_suspend, 0); + + (irqreturn_t)HIF_fw_interrupt_handler(sc->irq_event, sc); + if (sc->ol_sc->target_status == OL_TRGET_STATUS_RESET) + goto irq_handled; + + CE_per_engine_service_any(sc->irq_event, sc); + adf_os_atomic_set(&sc->tasklet_from_intr, 0); + if (CE_get_rx_pending(sc)) { + /* + * There are frames pending, schedule tasklet to process them. + * Enable the interrupt only when there is no pending frames in + * any of the Copy Engine pipes. + */ + adf_os_atomic_set(&sc->ce_suspend, 1); +#ifdef CONFIG_SLUB_DEBUG_ON + schedule_work(&reschedule_tasklet_work); +#else + tasklet_schedule(&sc->intr_tq); +#endif + return; + } +irq_handled: + /* use cached value for hif_init_done to prevent + * unlocking an unlocked spinlock if hif init finishes + * while this tasklet is running + */ + if (hif_init_done == TRUE) + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + + if (LEGACY_INTERRUPTS(sc) && (sc->ol_sc->target_status != + OL_TRGET_STATUS_RESET) && + (!adf_os_atomic_read(&sc->pci_link_suspended))) { + + if (hif_init_done == TRUE) { + if(HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE) < 0) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + return; + } + } + + /* Enable Legacy PCI line interrupts */ + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + /* IMPORTANT: this extra read transaction is required to flush the posted write buffer */ + tmp = A_PCI_READ32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); + + if (hif_init_done == TRUE) { + HIF_fw_interrupt_handler(sc->irq_event, sc); + if(HIFTargetSleepStateAdjust(hif_state->targid, TRUE, FALSE) < 0) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + return; + } + } + } + + if (hif_init_done == TRUE) + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + + adf_os_atomic_set(&sc->ce_suspend, 1); +} + +#define ATH_PCI_PROBE_RETRY_MAX 3 + +#ifdef FEATURE_RUNTIME_PM +static void hif_pci_pm_work(struct work_struct *work) +{ + struct hif_pci_softc *sc = container_of(work, struct hif_pci_softc, + pm_work); + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + MSG_BASED_HIF_CALLBACKS *msg_callbacks; + + pr_debug("%s: Resume HTT & WMI Service in runtime_pm state %d\n", + __func__, atomic_read(&sc->pm_state)); + + msg_callbacks = &hif_state->msg_callbacks_current; + + msg_callbacks->txResumeAllHandler(msg_callbacks->Context); +} + +static int hif_pci_autopm_debugfs_show(struct seq_file *s, void *data) +{ +#define HIF_PCI_AUTOPM_STATS(_s, _sc, _name) \ + seq_printf(_s, "%30s: %u\n", #_name, _sc->pm_stats._name) + struct hif_pci_softc *sc = s->private; + static const char *autopm_state[] = {"NONE", "ON", "INPROGRESS", + "SUSPENDED"}; + unsigned int msecs_age; + int pm_state = atomic_read(&sc->pm_state); + unsigned long timer_expires, flags; + struct hif_pm_runtime_context *ctx; + + seq_printf(s, "%30s: %s\n", "Runtime PM state", + autopm_state[pm_state]); + seq_printf(s, "%30s: %pf\n", "Last Resume Caller", + sc->pm_stats.last_resume_caller); + + if (pm_state == HIF_PM_RUNTIME_STATE_SUSPENDED) { + msecs_age = jiffies_to_msecs(jiffies - sc->pm_stats.suspend_jiffies); + seq_printf(s, "%30s: %d.%03ds\n", "Suspended Since", + msecs_age / 1000, msecs_age % 1000); + } + + seq_printf(s, "%30s: %d\n", "PM Usage count", + atomic_read(&sc->dev->power.usage_count)); + + seq_printf(s, "%30s: %u\n", "prevent_suspend_cnt", + sc->prevent_suspend_cnt); + + HIF_PCI_AUTOPM_STATS(s, sc, suspended); + HIF_PCI_AUTOPM_STATS(s, sc, suspend_err); + HIF_PCI_AUTOPM_STATS(s, sc, resumed); + HIF_PCI_AUTOPM_STATS(s, sc, runtime_get); + HIF_PCI_AUTOPM_STATS(s, sc, runtime_put); + HIF_PCI_AUTOPM_STATS(s, sc, request_resume); + HIF_PCI_AUTOPM_STATS(s, sc, prevent_suspend); + HIF_PCI_AUTOPM_STATS(s, sc, allow_suspend); + HIF_PCI_AUTOPM_STATS(s, sc, prevent_suspend_timeout); + HIF_PCI_AUTOPM_STATS(s, sc, allow_suspend_timeout); + HIF_PCI_AUTOPM_STATS(s, sc, runtime_get_err); + timer_expires = sc->runtime_timer_expires; + if (timer_expires > 0) { + msecs_age = jiffies_to_msecs(timer_expires - jiffies); + seq_printf(s, "%30s: %d.%03ds\n", "Prevent suspend timeout", + msecs_age / 1000, msecs_age % 1000); + } + + spin_lock_irqsave(&sc->runtime_lock, flags); + if (list_empty(&sc->prevent_suspend_list)) { + spin_unlock_irqrestore(&sc->runtime_lock, flags); + return 0; + } + + seq_printf(s, "%30s: ", "Active Wakeup_Sources"); + list_for_each_entry(ctx, &sc->prevent_suspend_list, list) { + seq_printf(s, "%s", ctx->name); + if (ctx->timeout) + seq_printf(s, "(%d ms)", ctx->timeout); + seq_puts(s, " "); + } + seq_puts(s, "\n"); + spin_unlock_irqrestore(&sc->runtime_lock, flags); + + return 0; +#undef HIF_PCI_AUTOPM_STATS +} + +static int hif_pci_autopm_open(struct inode *inode, struct file *file) +{ + return single_open(file, hif_pci_autopm_debugfs_show, inode->i_private); +} + +#ifdef FEATURE_RUNTIME_PM_UNIT_TEST +/* + * This is global runtime context just for unit test framework. + * This context should not be used for other purpose. + */ + +#define MAX_RUNTIME_DEBUG_CONTEXT 4 +static struct hif_pm_runtime_context rpm_data[MAX_RUNTIME_DEBUG_CONTEXT]; + +/** + * hif_pm_test() - Calls the API's per context + * @sc: ol_softc context + * @context: Runtime PM context + * @fn: function Tag + * @delay: delay to add before executing the runtime API + * + * This API's calls the runtime API's based on the passed + * function tag value and adds the dealy before calling them + * + * Return: void + */ +static void hif_pm_test(struct ol_softc *sc, + struct hif_pm_runtime_context *context, + const char *fn, uint32_t delay) +{ + char func = *fn; + + pr_info("%s func:%c delay:%d ctx:%s\n", __func__, + func, delay, context ? context->name : "NULL"); + + switch (func) { + case 'A': + msleep(delay * 1000); + hif_pm_runtime_allow_suspend(sc, context); + break; + case 'P': + msleep(delay * 1000); + hif_pm_runtime_prevent_suspend(sc, context); + break; + case 'T': + hif_pm_runtime_prevent_suspend_timeout(sc, context, + delay * 1000); + break; + default: + break; + } +} + +/** + * hif_get_context() - Returns the context for unit test framework + * @c: value to choose the gloabl context for testing the runtime API's + * + * Return: void + */ + +static void *hif_get_context(char *c) +{ + unsigned int val; + + if (kstrtou32(c, 0, &val)) + return NULL; + + switch (val) { + case 1: + rpm_data[0].name = "context_1"; + break; + case 2: + rpm_data[1].name = "context_2"; + break; + case 3: + rpm_data[2].name = "context_3"; + break; + case 4: + rpm_data[3].name = "context_4"; + break; + default: + return NULL; + } + return &rpm_data[val-1]; +} + +/** + * hif_runtime_test_init() - Initialize the test framework + * @sc: Global hif context + * Return: void + */ +void hif_runtime_test_init(struct hif_pci_softc *sc) +{ + int i; + struct hif_pm_runtime_context *ctx = NULL, *tmp; + unsigned long flags; + + for (i = 0; i < MAX_RUNTIME_DEBUG_CONTEXT; i++) { + ctx = &rpm_data[i]; + ctx->active = false; + ctx->name = NULL; + spin_lock_irqsave(&sc->runtime_lock, flags); + list_for_each_entry_safe(ctx, tmp, + &sc->prevent_suspend_list, list) { + list_del(&ctx->list); + } + spin_unlock_irqrestore(&sc->runtime_lock, flags); + } +} + +/** + * hif_pci_autopm_write() - Unit Test API to verify the Runtime PM API's + * + * Usage: "Context=API:Delay:....;Context=API:Delay;" + * Context Can be from 1 to 4. + * API can be one of the following + * T - Prevent Suspend Timeout Version + * P - Prevent_suspend + * A - Allow Suspend + * Delay in sec + * Delimiters: + * "=" - Seperates context from the API calls + * ":" - Seperates API's/Delay + * ";" - Seperates two context. + * + * eg: echo "1=T:5:A:2:P:1;2=T:5;1=A:1;2=A:0" > /d/cnss_runtime_pm + * In the above example: + * 1=T:4:A:2:P:1 --> This is sequence of calls with context 1 + * 2=T:5 --> Context 2 is used here + * 1=A:1 --> Context 1 can be used to allow the prevented suspend in context 1 + * 2=A:0 --> Relax the runtime suspend from context 2. + * + * Only to be used by developers to verify if any changes done in future. + */ + +static ssize_t hif_pci_autopm_write(struct file *fp, const char __user *buf, + size_t count, loff_t *off) +{ + struct hif_pci_softc *hif_sc; + struct ol_softc *sc; + char *fmtp, *pattern, *func, *ctxp, *ctx, *data; + uint32_t val; + struct hif_pm_runtime_context *context = NULL; + + hif_sc = ((struct seq_file *)fp->private_data)->private; + if (!hif_sc) + return -EINVAL; + + sc = hif_sc->ol_sc; + + pattern = adf_os_mem_alloc(NULL, count); + if (!pattern) + return -ENOMEM; + + if (copy_from_user(pattern, buf, count)) { + adf_os_mem_free(pattern); + return -EFAULT; + } + + hif_runtime_test_init(hif_sc); + + ctxp = pattern; + while (ctxp) { + ctx = strsep(&ctxp, ";"); + while (ctx) { + data = strsep(&ctx, "="); + context = hif_get_context(data); + fmtp = strsep(&ctx, "="); + while (fmtp) { + func = strsep(&fmtp, ":"); + if (kstrtou32(strsep(&fmtp, ":"), 0, &val)) { + adf_os_mem_free(pattern); + return -EFAULT; + } + hif_pm_test(sc, context, func, val); + } + } + } + adf_os_mem_free(pattern); + return count; +} +#endif + +static const struct file_operations hif_pci_autopm_fops = { + .owner = THIS_MODULE, + .open = hif_pci_autopm_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +#ifdef FEATURE_RUNTIME_PM_UNIT_TEST + .write = hif_pci_autopm_write, +#endif +}; + +static int __hif_pci_runtime_suspend(struct pci_dev *pdev) +{ + struct hif_pci_softc *sc = NULL; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + pm_message_t state = { .event = PM_EVENT_SUSPEND }; + v_VOID_t *temp_module; + ol_txrx_pdev_handle txrx_pdev; + int ret = -EBUSY, test = 0; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { + pr_err("%s: Load/Unload in Progress\n", __func__); + goto end; + } + + if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) { + pr_err("%s: LOGP in progress\n", __func__); + goto end; + } + + sc = pci_get_drvdata(pdev); + if (!sc) { + pr_err("%s: sc is NULL!\n", __func__); + goto end; + } + + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_INPROGRESS); + + txrx_pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_context); + if (!txrx_pdev) { + pr_err("%s: txrx_pdev is NULL\n", __func__); + goto out; + } + + if ((test = ol_txrx_get_tx_pending(txrx_pdev))) { + pr_err("%s: txrx pending(%d), get: %u, put: %u\n", __func__, + test, + sc->pm_stats.runtime_get, + sc->pm_stats.runtime_put); + goto out; + } + + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + if (!temp_module) { + pr_err("%s: WDA module is NULL\n", __func__); + goto out; + } + + if (wma_check_scan_in_progress(temp_module)) { + pr_err("%s: Scan in Progress. Aborting runtime suspend\n", + __func__); + goto out; + } + +#ifdef FEATURE_WLAN_D0WOW + if (wma_get_client_count(temp_module)) { + pr_err("%s: Runtime PM not supported when clients are connected\n", + __func__); + goto out; + } +#endif + + ret = wma_runtime_suspend_req(temp_module); + if (ret) { + pr_err("%s: Runtime Offloads configuration failed: %d\n", + __func__, ret); + goto out; + } + + ret = __hif_pci_suspend(pdev, state, true); + if (ret) { + pr_err("%s: pci_suspend failed: %d\n", __func__, ret); + goto suspend_fail; + } + + ret = cnss_auto_suspend(); + + if (ret) { + ret = -EAGAIN; + goto suspend_fail; + } + + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_SUSPENDED); + sc->pm_stats.suspended++; + sc->pm_stats.suspend_jiffies = jiffies; + + return 0; + +suspend_fail: + wma_runtime_resume_req(temp_module); +out: + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_ON); + sc->pm_stats.suspend_err++; + hif_pm_runtime_mark_last_busy(sc->dev); +end: + ASSERT(ret == -EAGAIN || ret == -EBUSY); + return ret; +} + +static int hif_pci_runtime_suspend(struct pci_dev *pdev) +{ + int ret = 0; + vos_ssr_protect(__func__); + ret = __hif_pci_runtime_suspend(pdev); + vos_ssr_unprotect(__func__); + + return ret; +} + +static int __hif_pci_runtime_resume(struct pci_dev *pdev) +{ + struct hif_pci_softc *sc = pci_get_drvdata(pdev); + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + int ret = 0; + v_VOID_t * temp_module; + + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_INPROGRESS); + + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + if (!temp_module) { + pr_err("%s: WDA module is NULL\n", __func__); + goto out; + } + +#ifdef FEATURE_WLAN_D0WOW + if (wma_get_client_count(temp_module)) { + pr_err("%s: Runtime PM not supported when clients are connected\n", + __func__); + ASSERT(0); + + ret = -EINVAL; + goto out; + } +#endif + ret = cnss_auto_resume(); + + if (ret) { + pr_err("%s: Failed to resume PCIe link: %d\n", __func__, ret); + goto out; + } + + ret = __hif_pci_resume(pdev, true); + + if (ret) + goto out; + + ret = wma_runtime_resume_req(temp_module); + if (ret) + goto out; + + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_ON); + hif_pm_runtime_mark_last_busy(sc->dev); + sc->pm_stats.resumed++; + + schedule_work(&sc->pm_work); + + return 0; +out: + /* In Resume we should never fail */ + ASSERT(0); + return ret; +} + +static int hif_pci_runtime_resume(struct pci_dev *pdev) +{ + int ret = 0; + + vos_ssr_protect(__func__); + ret = __hif_pci_runtime_resume(pdev); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* TODO: Change this to dev_pm_ops */ +struct cnss_wlan_runtime_ops runtime_pm_ops = { + .runtime_suspend = hif_pci_runtime_suspend, + .runtime_resume = hif_pci_runtime_resume, +}; + +#ifdef WLAN_OPEN_SOURCE +static inline void hif_pci_pm_debugfs(struct hif_pci_softc *sc, bool init) +{ + if (init) + sc->pm_dentry = debugfs_create_file("cnss_runtime_pm", + S_IRUSR, NULL, sc, + &hif_pci_autopm_fops); + else + debugfs_remove(sc->pm_dentry); +} +#else +static inline void hif_pci_pm_debugfs(struct hif_pci_softc *sc, bool init) +{ + +} +#endif + +static void hif_pci_pm_runtime_pre_init(struct hif_pci_softc *sc) +{ + spin_lock_init(&sc->runtime_lock); + setup_timer(&sc->runtime_timer, hif_pci_runtime_pm_timeout_fn, + (unsigned long)sc); + + adf_os_atomic_init(&sc->pm_state); + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_NONE); + INIT_LIST_HEAD(&sc->prevent_suspend_list); +} + +static void hif_pci_pm_runtime_init(struct hif_pci_softc *sc) +{ + struct ol_softc *ol_sc; + + ol_sc = sc->ol_sc; + + if (!ol_sc->enable_runtime_pm) { + pr_info("%s: RUNTIME PM is disabled in ini\n", __func__); + return; + } + + if (vos_get_conparam() == VOS_FTM_MODE || + WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { + pr_info("%s: RUNTIME PM is disabled for FTM/EPPING mode\n", + __func__); + return; + } + + pr_info("%s: Enabling RUNTIME PM, Delay: %d ms\n", __func__, + ol_sc->runtime_pm_delay); + + cnss_init_work(&sc->pm_work, hif_pci_pm_work); + cnss_runtime_init(sc->dev, ol_sc->runtime_pm_delay); + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_ON); + hif_pci_pm_debugfs(sc, true); +} + +static void hif_pci_pm_runtime_exit(struct hif_pci_softc *sc) +{ + struct ol_softc *ol_sc = sc->ol_sc; + + if (!ol_sc->enable_runtime_pm) + return; + + if (vos_get_conparam() == VOS_FTM_MODE || + WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + return; + + hif_pm_runtime_resume(sc->dev); + + cnss_runtime_exit(sc->dev); + adf_os_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_NONE); + + hif_pci_pm_debugfs(sc, false); + del_timer_sync(&sc->runtime_timer); + cnss_flush_work(&sc->pm_work); +} + +/** + * hif_pci_pm_runtime_post_exit() - API to check the sanity of Runtime PM + * @sc: hif_pci_softc context + * + * API is used to check if any mismatch in runtime usage count and + * to ensure we fix it before driver unload. + * Ideally the conditions in this API shouldn't hit + * This prevention is needed to ensure Runtime PM wont be disabled + * for ever with mismatch in usage count. + * + * Return: void + */ +static void hif_pci_pm_runtime_post_exit(struct hif_pci_softc *sc) +{ + unsigned long flags; + struct hif_pm_runtime_context *ctx, *tmp; + + /* + * The usage_count should be one at this state, as all the + * HTT/WMI pkts should get tx complete and driver should + * will increment the usage count to 1 to prevent any suspend + */ + if (atomic_read(&sc->dev->power.usage_count) != 1) { + spin_lock_irqsave(&sc->runtime_lock, flags); + hif_pci_runtime_pm_warn(sc, "Driver UnLoading"); + spin_unlock_irqrestore(&sc->runtime_lock, flags); + } else + return; + + spin_lock_irqsave(&sc->runtime_lock, flags); + list_for_each_entry_safe(ctx, tmp, &sc->prevent_suspend_list, list) { + spin_unlock_irqrestore(&sc->runtime_lock, flags); + hif_runtime_pm_prevent_suspend_deinit(ctx); + spin_lock_irqsave(&sc->runtime_lock, flags); + } + spin_unlock_irqrestore(&sc->runtime_lock, flags); + /* + * This is totally a preventive measure to ensure Runtime PM + * isn't disabled for life time. + * To debug such scenarios, we can set dev->power.disable_depth > 0 + * or set dev->power.runtime_error. So Runtime PM callbacks won't + * get called. + * When usage_count is negative, kernel Runtime PM framework continues + * to call runtime suspend, and we may see weird issues. + */ + if (atomic_read(&sc->dev->power.usage_count) <= 0) + atomic_set(&sc->dev->power.usage_count, 1); + + while (atomic_read(&sc->dev->power.usage_count) != 1) + pm_runtime_put_noidle(sc->dev); +} + +/** + * hif_pci_pm_runtime_ssr_post_exit() - Empty the prevent suspend list on SSR + * @sc: hif_pci context + * + * API is used to empty the runtime pm prevent suspend list. + * + * Return: void + */ +static void hif_pci_pm_runtime_ssr_post_exit(struct hif_pci_softc *sc) +{ + unsigned long flags; + struct hif_pm_runtime_context *ctx, *tmp; + + spin_lock_irqsave(&sc->runtime_lock, flags); + list_for_each_entry_safe(ctx, tmp, &sc->prevent_suspend_list, list) { + hif_pm_ssr_runtime_allow_suspend(sc, ctx); + } + spin_unlock_irqrestore(&sc->runtime_lock, flags); +} + +#else +static inline void hif_pci_pm_runtime_init(struct hif_pci_softc *sc) { } +static inline void hif_pci_pm_runtime_pre_init(struct hif_pci_softc *sc) { } +static inline void hif_pci_pm_runtime_exit(struct hif_pci_softc *sc) { } +static inline void hif_pci_pm_runtime_post_exit(struct hif_pci_softc *sc) { } +static inline void +hif_pci_pm_runtime_ssr_post_exit(struct hif_pci_softc *sc) { } +#endif + +int +hif_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + void __iomem *mem; + int ret = 0; + u_int32_t hif_type, target_type; + struct hif_pci_softc *sc; + struct ol_softc *ol_sc; + int probe_again = 0; + u_int16_t device_id; + u_int16_t revision_id; + u_int32_t lcr_val; + + printk(KERN_INFO "%s:, con_mode= 0x%x\n", __func__, vos_get_conparam()); + +again: + ret = 0; + +#define BAR_NUM 0 + /* + * Without any knowledge of the Host, the Target + * may have been reset or power cycled and its + * Config Space may no longer reflect the PCI + * address space that was assigned earlier + * by the PCI infrastructure. Refresh it now. + */ + /*WAR for EV#117307, if PCI link is down, return from probe() */ + pci_read_config_word(pdev,PCI_DEVICE_ID,&device_id); + printk("PCI device id is %04x :%04x\n",device_id,id->device); + if(device_id != id->device) { + printk(KERN_ERR "ath: PCI link is down.\n"); + /* pci link is down, so returing with error code */ + return -EIO; + } + + /* FIXME: temp. commenting out assign_resource + * call for dev_attach to work on 2.6.38 kernel + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) && !defined(__LINUX_ARM_ARCH__) + if (pci_assign_resource(pdev, BAR_NUM)) { + printk(KERN_ERR "ath: cannot assign PCI space\n"); + return -EIO; + } +#endif + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "ath: cannot enable PCI device\n"); + return -EIO; + } + +#define BAR_NUM 0 + /* Request MMIO resources */ + ret = pci_request_region(pdev, BAR_NUM, "ath"); + if (ret) { + dev_err(&pdev->dev, "ath: PCI MMIO reservation error\n"); + ret = -EIO; + goto err_region; + } +#ifdef CONFIG_ARM_LPAE + /* if CONFIG_ARM_LPAE is enabled, we have to set 64 bits mask + * for 32 bits device also. */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) { + printk(KERN_ERR "ath: Cannot enable 64-bit pci DMA\n"); + goto err_dma; + } + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) { + printk(KERN_ERR "ath: Cannot enable 64-bit consistent DMA\n"); + goto err_dma; + } +#else + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + printk(KERN_ERR "ath: Cannot enable 32-bit pci DMA\n"); + goto err_dma; + } + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + printk(KERN_ERR "%s: Cannot enable 32-bit consistent DMA!\n", + __func__); + goto err_dma; + } +#endif + +#ifdef DISABLE_L1SS_STATES + pci_read_config_dword(pdev, 0x188, &lcr_val); + pci_write_config_dword(pdev, 0x188, (lcr_val & ~0x0000000f)); +#endif + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + + /* Temporary FIX: disable ASPM on peregrine. Will be removed after the OTP is programmed */ + pci_read_config_dword(pdev, 0x80, &lcr_val); + pci_write_config_dword(pdev, 0x80, (lcr_val & 0xffffff00)); + + /* Arrange for access to Target SoC registers. */ + mem = pci_iomap(pdev, BAR_NUM, 0); + if (!mem) { + printk(KERN_ERR "ath: PCI iomap error\n") ; + ret = -EIO; + goto err_iomap; + } + + /* Disable asynchronous suspend */ + device_disable_async_suspend(&pdev->dev); + + sc = A_MALLOC(sizeof(*sc)); + if (!sc) { + ret = -ENOMEM; + goto err_alloc; + } + + OS_MEMZERO(sc, sizeof(*sc)); + sc->mem = mem; + sc->pdev = pdev; + sc->dev = &pdev->dev; + + sc->aps_osdev.bdev = pdev; + sc->aps_osdev.device = &pdev->dev; + sc->aps_osdev.bc.bc_handle = (void *)mem; + sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_PCI; + sc->devid = id->device; + + adf_os_spinlock_init(&sc->target_lock); + + sc->cacheline_sz = dma_get_cache_alignment(); + + pci_read_config_word(pdev, 0x08, &revision_id); + + switch (id->device) { + case AR9888_DEVICE_ID: + hif_type = HIF_TYPE_AR9888; + target_type = TARGET_TYPE_AR9888; + break; + + case AR6320_DEVICE_ID: + switch(revision_id) { + case AR6320_FW_1_1: + case AR6320_FW_1_3: + hif_type = HIF_TYPE_AR6320; + target_type = TARGET_TYPE_AR6320; + break; + + case AR6320_FW_2_0: + case AR6320_FW_3_0: + case AR6320_FW_3_2: + hif_type = HIF_TYPE_AR6320V2; + target_type = TARGET_TYPE_AR6320V2; + break; + + default: + printk(KERN_ERR "unsupported revision id %x\n", id->device); + ret = -ENODEV; + goto err_tgtstate; + } + break; + + default: + printk(KERN_ERR "unsupported device id\n"); + ret = -ENODEV; + goto err_tgtstate; + } + /* + * Attach Target register table. This is needed early on -- + * even before BMI -- since PCI and HIF initialization (and BMI init) + * directly access Target registers (e.g. CE registers). + */ + + hif_register_tbl_attach(sc, hif_type); + target_register_tbl_attach(sc, target_type); + { + A_UINT32 fw_indicator; +#if PCIE_BAR0_READY_CHECKING + int wait_limit = 200; +#endif + int targ_awake_limit = 500; + + /* + * Verify that the Target was started cleanly. + * + * The case where this is most likely is with an AUX-powered + * Target and a Host in WoW mode. If the Host crashes, + * loses power, or is restarted (without unloading the driver) + * then the Target is left (aux) powered and running. On a + * subsequent driver load, the Target is in an unexpected state. + * We try to catch that here in order to reset the Target and + * retry the probe. + */ + A_PCI_WRITE32(mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + while (!hif_pci_targ_is_awake(sc, mem)) { + if (0 == targ_awake_limit) { + printk(KERN_ERR "%s: target awake timeout\n", __func__); + ret = -EAGAIN; + goto err_tgtstate; + } + A_MDELAY(1); + targ_awake_limit--; + } + +#if PCIE_BAR0_READY_CHECKING + /* Synchronization point: wait the BAR0 is configured */ + while (wait_limit-- && + !(A_PCI_READ32(mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_RDY_STATUS_ADDRESS) \ + & PCIE_SOC_RDY_STATUS_BAR_MASK)) { + A_MDELAY(10); + } + if (wait_limit < 0) { + /* AR6320v1 doesn't support checking of BAR0 configuration, + takes one sec to wait BAR0 ready */ + printk(KERN_INFO "AR6320v1 waits two sec for BAR0 ready.\n"); + } +#endif + + fw_indicator = A_PCI_READ32(mem + FW_INDICATOR_ADDRESS); + A_PCI_WRITE32(mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + + if (fw_indicator & FW_IND_INITIALIZED) { + probe_again++; + printk(KERN_ERR "ath: Target is in an unknown state. Resetting (attempt %d).\n", probe_again); + /* hif_pci_device_reset, below, will reset the target */ + ret = -EIO; + goto err_tgtstate; + } + } + + ol_sc = A_MALLOC(sizeof(*ol_sc)); + if (!ol_sc) + goto err_attach; + OS_MEMZERO(ol_sc, sizeof(*ol_sc)); + ol_sc->sc_osdev = &sc->aps_osdev; + ol_sc->hif_sc = (void *)sc; + sc->ol_sc = ol_sc; + ol_sc->target_type = target_type; + + hif_pci_pm_runtime_pre_init(sc); + + if (hif_pci_configure(sc, &ol_sc->hif_hdl)) + goto err_config; + + ol_sc->enableuartprint = 0; + ol_sc->enablefwlog = 0; +#ifdef QCA_SINGLE_BINARY_SUPPORT + ol_sc->enablesinglebinary = TRUE; +#else + ol_sc->enablesinglebinary = FALSE; +#endif + ol_sc->max_no_of_peers = 1; + +#ifdef CONFIG_CNSS + /* Get RAM dump memory address and size */ + ol_sc->ramdump_base = cnss_get_virt_ramdump_mem(&ol_sc->ramdump_size); + + if (ol_sc->ramdump_base == NULL || !ol_sc->ramdump_size) { + pr_info("%s: Failed to get RAM dump memory address or size!\n", + __func__); + } +#endif + + adf_os_atomic_init(&sc->tasklet_from_intr); + adf_os_atomic_init(&sc->wow_done); +#ifdef FEATURE_WLAN_D0WOW + adf_os_atomic_init(&sc->in_d0wow); +#endif + adf_os_atomic_init(&sc->ce_suspend); + adf_os_atomic_init(&sc->pci_link_suspended); + init_waitqueue_head(&ol_sc->sc_osdev->event_queue); + + ret = hif_init_adf_ctx(ol_sc); + if (ret == 0) { + sc->hdd_startup_reinit_flag = true; + ret = hdd_wlan_startup(&pdev->dev, ol_sc); + sc->hdd_startup_reinit_flag = false; + } + + if (ret) { + hif_disable_isr(ol_sc); + HIFShutDownDevice(ol_sc->hif_hdl); + goto err_config; + } + + /* Re-enable ASPM after firmware/OTP download is complete */ + pci_write_config_dword(pdev, 0x80, lcr_val); + + hif_pci_pm_runtime_init(sc); + + return 0; + +err_config: + hif_deinit_adf_ctx(ol_sc); + A_FREE(ol_sc); +err_attach: + ret = -EIO; +err_tgtstate: + pci_set_drvdata(pdev, NULL); + hif_pci_device_reset(sc); + A_FREE(sc); +err_alloc: + /* call HIF PCI free here */ + printk("%s: HIF PCI Free needs to happen here \n", __func__); + pci_iounmap(pdev, mem); +err_iomap: + pci_clear_master(pdev); +err_dma: + pci_release_region(pdev, BAR_NUM); +err_region: + pci_disable_device(pdev); + + if (probe_again && (probe_again <= ATH_PCI_PROBE_RETRY_MAX)) { + int delay_time; + + /* + * We can get here after a Host crash or power fail when + * the Target has aux power. We just did a device_reset, + * so we need to delay a short while before we try to + * reinitialize. Typically only one retry with the smallest + * delay is needed. Target should never need more than a 100Ms + * delay; that would not conform to the PCIe std. + */ + + printk(KERN_INFO "pci reprobe.\n"); + delay_time = max(100, 10 * (probe_again * probe_again)); /* 10, 40, 90, 100, 100, ... */ + A_MDELAY(delay_time); + goto again; + } + return ret; +} + +/* This function will be called when SSR frame work wants to + * power up WLAN host driver when SSR happens. Most of this + * function is duplicated from hif_pci_probe(). + */ +#if defined(CONFIG_CNSS) +int hif_pci_reinit(struct pci_dev *pdev, const struct pci_device_id *id) +{ + void __iomem *mem; + struct hif_pci_softc *sc; + struct ol_softc *ol_sc; + int probe_again = 0; + int ret = 0; + u_int16_t device_id; + u_int32_t hif_type; + u_int32_t target_type; + u_int32_t lcr_val; + u_int16_t revision_id; + +again: + ret = 0; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { + printk("Load/unload in progress, ignore SSR reinit\n"); + return 0; + } + +#define BAR_NUM 0 + /* + * Without any knowledge of the Host, the Target + * may have been reset or power cycled and its + * Config Space may no longer reflect the PCI + * address space that was assigned earlier + * by the PCI infrastructure. Refresh it now. + */ + /* If PCI link is down, return from reinit() */ + pci_read_config_word(pdev,PCI_DEVICE_ID,&device_id); + printk("PCI device id is %04x :%04x\n", device_id, id->device); + if (device_id != id->device) { + printk(KERN_ERR "%s: PCI link is down!\n", __func__); + /* PCI link is down, so return with error code. */ + return -EIO; + } + + /* FIXME: Commenting out assign_resource + * call for dev_attach to work on 2.6.38 kernel + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) && !defined(__LINUX_ARM_ARCH__) + if (pci_assign_resource(pdev, BAR_NUM)) { + printk(KERN_ERR "%s: Cannot assign PCI space!\n", __func__); + return -EIO; + } +#endif + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "%s: Cannot enable PCI device!\n", __func__); + return -EIO; + } + + /* Request MMIO resources */ + ret = pci_request_region(pdev, BAR_NUM, "ath"); + if (ret) { + dev_err(&pdev->dev, "%s: PCI MMIO reservation error!\n", __func__); + ret = -EIO; + goto err_region; + } + +#ifdef CONFIG_ARM_LPAE + /* if CONFIG_ARM_LPAE is enabled, we have to set 64 bits mask + * for 32 bits device also. */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) { + printk(KERN_ERR "ath: Cannot enable 64-bit pci DMA\n"); + goto err_dma; + } + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) { + printk(KERN_ERR "ath: Cannot enable 64-bit consistent DMA\n"); + goto err_dma; + } +#else + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + printk(KERN_ERR "ath: Cannot enable 32-bit pci DMA\n"); + goto err_dma; + } + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + printk(KERN_ERR "%s: Cannot enable 32-bit consistent DMA!\n", + __func__); + goto err_dma; + } +#endif + +#ifdef DISABLE_L1SS_STATES + pci_read_config_dword(pdev, 0x188, &lcr_val); + pci_write_config_dword(pdev, 0x188, (lcr_val & ~0x0000000f)); +#endif + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + + /* Temporary FIX: disable ASPM. Will be removed after + the OTP is programmed. */ + pci_read_config_dword(pdev, 0x80, &lcr_val); + pci_write_config_dword(pdev, 0x80, (lcr_val & 0xffffff00)); + + /* Arrange for access to Target SoC registers */ + mem = pci_iomap(pdev, BAR_NUM, 0); + if (!mem) { + printk(KERN_ERR "%s: PCI iomap error!\n", __func__) ; + ret = -EIO; + goto err_iomap; + } + + /* Disable asynchronous suspend */ + device_disable_async_suspend(&pdev->dev); + + sc = A_MALLOC(sizeof(*sc)); + if (!sc) { + ret = -ENOMEM; + goto err_alloc; + } + + OS_MEMZERO(sc, sizeof(*sc)); + sc->mem = mem; + sc->pdev = pdev; + sc->dev = &pdev->dev; + sc->aps_osdev.bdev = pdev; + sc->aps_osdev.device = &pdev->dev; + sc->aps_osdev.bc.bc_handle = (void *)mem; + sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_PCI; + sc->devid = id->device; + + adf_os_spinlock_init(&sc->target_lock); + + sc->cacheline_sz = dma_get_cache_alignment(); + pci_read_config_word(pdev, 0x08, &revision_id); + + switch (id->device) { + case AR9888_DEVICE_ID: + hif_type = HIF_TYPE_AR9888; + target_type = TARGET_TYPE_AR9888; + break; + + case AR6320_DEVICE_ID: + switch(revision_id) { + case AR6320_FW_1_1: + case AR6320_FW_1_3: + hif_type = HIF_TYPE_AR6320; + target_type = TARGET_TYPE_AR6320; + break; + + case AR6320_FW_2_0: + case AR6320_FW_3_0: + case AR6320_FW_3_2: + hif_type = HIF_TYPE_AR6320V2; + target_type = TARGET_TYPE_AR6320V2; + break; + + default: + printk(KERN_ERR "unsupported revision id %x\n", id->device); + ret = -ENODEV; + goto err_tgtstate; + } + break; + + default: + printk(KERN_ERR "%s: Unsupported device ID!\n", __func__); + ret = -ENODEV; + goto err_tgtstate; + } + + /* + * Attach Target register table. This is needed early on -- + * even before BMI -- since PCI and HIF initialization (and BMI init) + * directly access Target registers (e.g. CE registers). + */ + + hif_register_tbl_attach(sc, hif_type); + target_register_tbl_attach(sc, target_type); + { + A_UINT32 fw_indicator; +#if PCIE_BAR0_READY_CHECKING + int wait_limit = 200; +#endif + + /* + * Verify that the Target was started cleanly. + * + * The case where this is most likely is with an AUX-powered + * Target and a Host in WoW mode. If the Host crashes, + * loses power, or is restarted (without unloading the driver) + * then the Target is left (aux) powered and running. On a + * subsequent driver load, the Target is in an unexpected state. + * We try to catch that here in order to reset the Target and + * retry the probe. + */ + A_PCI_WRITE32(mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_V_MASK); + while (!hif_pci_targ_is_awake(sc, mem)) { + ; + } + +#if PCIE_BAR0_READY_CHECKING + /* Synchronization point: wait the BAR0 is configured. */ + while (wait_limit-- && + !(A_PCI_READ32(mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_RDY_STATUS_ADDRESS) & PCIE_SOC_RDY_STATUS_BAR_MASK)) { + A_MDELAY(10); + } + if (wait_limit < 0) { + /* AR6320v1 doesn't support checking of BAR0 configuration, + takes one sec to wait BAR0 ready. */ + printk(KERN_INFO "AR6320v1 waits two sec for BAR0 ready.\n"); + } +#endif + + fw_indicator = A_PCI_READ32(mem + FW_INDICATOR_ADDRESS); + A_PCI_WRITE32(mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); + + if (fw_indicator & FW_IND_INITIALIZED) { + probe_again++; + printk(KERN_ERR "%s: Target is in an unknown state. " + "Resetting (attempt %d).\n", __func__, probe_again); + /* hif_pci_device_reset, below will reset the target. */ + ret = -EIO; + goto err_tgtstate; + } + } + + ol_sc = A_MALLOC(sizeof(*ol_sc)); + if (!ol_sc) + goto err_attach; + + OS_MEMZERO(ol_sc, sizeof(*ol_sc)); + ol_sc->sc_osdev = &sc->aps_osdev; + ol_sc->hif_sc = (void *)sc; + sc->ol_sc = ol_sc; + ol_sc->target_type = target_type; + + hif_pci_pm_runtime_pre_init(sc); + + if (hif_pci_configure(sc, &ol_sc->hif_hdl)) + goto err_config; + + ol_sc->enableuartprint = 0; + ol_sc->enablefwlog = 0; +#ifdef QCA_SINGLE_BINARY_SUPPORT + ol_sc->enablesinglebinary = TRUE; +#else + ol_sc->enablesinglebinary = FALSE; +#endif + ol_sc->max_no_of_peers = 1; + +#ifdef CONFIG_CNSS + /* Get RAM dump memory address and size */ + ol_sc->ramdump_base = cnss_get_virt_ramdump_mem(&ol_sc->ramdump_size); + + if (ol_sc->ramdump_base == NULL || !ol_sc->ramdump_size) { + pr_info("%s: Failed to get RAM dump memory address or size!\n", + __func__); + } +#endif + + adf_os_atomic_init(&sc->tasklet_from_intr); + adf_os_atomic_init(&sc->wow_done); +#ifdef FEATURE_WLAN_D0WOW + adf_os_atomic_init(&sc->in_d0wow); +#endif + adf_os_atomic_init(&sc->ce_suspend); + adf_os_atomic_init(&sc->pci_link_suspended); + + init_waitqueue_head(&ol_sc->sc_osdev->event_queue); + + ret = hif_init_adf_ctx(ol_sc); + if (ret == 0) { + sc->hdd_startup_reinit_flag = true; + if (VOS_STATUS_SUCCESS == hdd_wlan_re_init(ol_sc)) + ret = 0; + sc->hdd_startup_reinit_flag = false; + } + + /* Re-enable ASPM after firmware/OTP download is complete */ + pci_write_config_dword(pdev, 0x80, lcr_val); + + if (ret) { + hif_disable_isr(ol_sc); + HIFShutDownDevice(ol_sc->hif_hdl); + goto err_config; + } + + hif_pci_pm_runtime_init(sc); + + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE); + printk("%s: WLAN host driver reinitiation completed!\n", __func__); + return 0; + +err_config: + hif_deinit_adf_ctx(ol_sc); + A_FREE(ol_sc); +err_attach: + ret = -EIO; +err_tgtstate: + pci_set_drvdata(pdev, NULL); + hif_pci_device_reset(sc); + A_FREE(sc); +err_alloc: + /* Call HIF PCI free here */ + printk("%s: HIF PCI free needs to happen here.\n", __func__); + pci_iounmap(pdev, mem); +err_iomap: + pci_clear_master(pdev); +err_dma: + pci_release_region(pdev, BAR_NUM); +err_region: + pci_disable_device(pdev); + + if (probe_again && (probe_again <= ATH_PCI_PROBE_RETRY_MAX)) { + int delay_time; + + /* + * We can get here after a Host crash or power fail when + * the Target has aux power. We just did a device_reset, + * so we need to delay a short while before we try to + * reinitialize. Typically only one retry with the smallest + * delay is needed. Target should never need more than a 100Ms + * delay; that would not conform to the PCIe std. + */ + + printk(KERN_INFO "%s: PCI rereinit\n", __func__); + /* 10, 40, 90, 100, 100, ... */ + delay_time = max(100, 10 * (probe_again * probe_again)); + A_MDELAY(delay_time); + goto again; + } + + return ret; +} +#endif + +void hif_pci_notify_handler(struct pci_dev *pdev, int state) +{ + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { + int ret = 0; + ret = hdd_wlan_notify_modem_power_state(state); + if (ret < 0) + printk(KERN_ERR "%s: Fail to send notify\n", __func__); + } +} + +void +hif_nointrs(struct hif_pci_softc *sc) +{ + int i; + + if (sc->hdd_startup_reinit_flag) { + pr_err("%s: WARN: In HDD startup or reinit\n", __func__); + return; + } + + if (!sc->pdev) { + pr_err("%s: pdev is NULL\n", __func__); + return; + } + if (sc->num_msi_intrs > 0) { + /* MSI interrupt(s) */ + for (i = 0; i < sc->num_msi_intrs; i++) { + free_irq(sc->pdev->irq + i, sc); + } + sc->num_msi_intrs = 0; + } else { + /* Legacy PCI line interrupt */ + free_irq(sc->pdev->irq, sc); + } +} + +int +hif_pci_configure(struct hif_pci_softc *sc, hif_handle_t *hif_hdl) +{ + int ret = 0; + int num_msi_desired; + u_int32_t val; + + BUG_ON(pci_get_drvdata(sc->pdev) != NULL); + pci_set_drvdata(sc->pdev, sc); + + tasklet_init(&sc->intr_tq, wlan_tasklet, (unsigned long)sc); + + /* + * Interrupt Management is divided into these scenarios : + * A) We wish to use MSI and Multiple MSI is supported and we + * are able to obtain the number of MSI interrupts desired + * (best performance) + * B) We wish to use MSI and Single MSI is supported and we are + * able to obtain a single MSI interrupt + * C) We don't want to use MSI or MSI is not supported and we + * are able to obtain a legacy interrupt + * D) Failure + */ +#if defined(FORCE_LEGACY_PCI_INTERRUPTS) + num_msi_desired = 0; /* Use legacy PCI line interrupts rather than MSI */ +#else + num_msi_desired = MSI_NUM_REQUEST; /* Multiple MSI */ + if (!msienable) { + num_msi_desired = 0; + } +#endif + + printk("\n %s : num_desired MSI set to %d\n", __func__, num_msi_desired); + + if (num_msi_desired > 1) { + int i; + int rv; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS) + rv = pci_enable_msi_range(sc->pdev, MSI_NUM_REQUEST, MSI_NUM_REQUEST); +#else + rv = pci_enable_msi_block(sc->pdev, MSI_NUM_REQUEST); +#endif + + if (rv == 0) { /* successfully allocated all MSI interrupts */ + /* + * TBDXXX: This path not yet tested, + * since Linux x86 does not currently + * support "Multiple MSIs". + */ + sc->num_msi_intrs = MSI_NUM_REQUEST; + ret = request_irq(sc->pdev->irq+MSI_ASSIGN_FW, hif_pci_msi_fw_handler, + IRQF_SHARED, "wlan_pci", sc); + if(ret) { + dev_err(&sc->pdev->dev, "request_irq failed\n"); + goto err_intr; + } + for (i=MSI_ASSIGN_CE_INITIAL; i<=MSI_ASSIGN_CE_MAX; i++) { + ret = request_irq(sc->pdev->irq+i, CE_per_engine_handler, IRQF_SHARED, + "wlan_pci", sc); + if(ret) { + dev_err(&sc->pdev->dev, "request_irq failed\n"); + goto err_intr; + } + } + } else { + if (rv < 0) { + /* Can't get any MSI -- try for legacy line interrupts */ + num_msi_desired = 0; + } else { + /* Can't get enough MSI interrupts -- try for just 1 */ + printk("\n %s : Can't allocate requested number of MSI, just use 1\n", __func__); + num_msi_desired = 1; + } + } + } + + if (num_msi_desired == 1) { + /* + * We are here because either the platform only supports + * single MSI OR because we couldn't get all the MSI interrupts + * that we wanted so we fall back to a single MSI. + */ + if (pci_enable_msi(sc->pdev) < 0) { + printk(KERN_ERR "ath: single MSI interrupt allocation failed\n"); + /* Try for legacy PCI line interrupts */ + num_msi_desired = 0; + } else { + /* Use a single Host-side MSI interrupt handler for all interrupts */ + num_msi_desired = 1; + } + } + + if ( num_msi_desired <= 1) { + /* We are here because we want to multiplex a single host interrupt among all + * Target interrupt sources + */ + ret = request_irq(sc->pdev->irq, hif_pci_interrupt_handler, IRQF_SHARED, + "wlan_pci", sc); + if(ret) { + dev_err(&sc->pdev->dev, "request_irq failed\n"); + goto err_intr; + } + + } +#if CONFIG_PCIE_64BIT_MSI + { + struct ol_ath_softc_net80211 *scn = sc->scn; + u_int8_t MSI_flag; + u_int32_t reg; + +#define OL_ATH_PCI_MSI_POS 0x50 +#define MSI_MAGIC_RDY_MASK 0x00000001 +#define MSI_MAGIC_EN_MASK 0x80000000 + + pci_read_config_byte(sc->pdev, OL_ATH_PCI_MSI_POS + PCI_MSI_FLAGS, &MSI_flag); + if (MSI_flag & PCI_MSI_FLAGS_ENABLE) { + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + while (!ath_pci_targ_is_awake(sc->mem)) { + ; + } + scn->MSI_magic = OS_MALLOC_CONSISTENT(scn->sc_osdev, 4, &scn->MSI_magic_dma, \ + OS_GET_DMA_MEM_CONTEXT(scn, MSI_dmacontext), 0); + A_PCI_WRITE32(sc->mem + SOC_PCIE_BASE_ADDRESS + MSI_MAGIC_ADR_ADDRESS, + scn->MSI_magic_dma); + reg = A_PCI_READ32(sc->mem + SOC_PCIE_BASE_ADDRESS + MSI_MAGIC_ADDRESS); + A_PCI_WRITE32(sc->mem + SOC_PCIE_BASE_ADDRESS + MSI_MAGIC_ADDRESS, reg | MSI_MAGIC_RDY_MASK); + + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + } + } +#endif + + if(num_msi_desired == 0) { + printk("\n Using PCI Legacy Interrupt\n"); + + /* Make sure to wake the Target before enabling Legacy Interrupt */ + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_V_MASK); + while (!hif_pci_targ_is_awake(sc, sc->mem)) { + ; + } + /* Use Legacy PCI Interrupts */ + /* + * A potential race occurs here: The CORE_BASE write depends on + * target correctly decoding AXI address but host won't know + * when target writes BAR to CORE_CTRL. This write might get lost + * if target has NOT written BAR. For now, fix the race by repeating + * the write in below synchronization checking. + */ + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); + } + + sc->num_msi_intrs = num_msi_desired; + sc->ce_count = CE_COUNT; + + { /* Synchronization point: Wait for Target to finish initialization before we proceed. */ + int wait_limit = 1000; /* 10 sec */ + + /* Make sure to wake Target before accessing Target memory */ + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + while (!hif_pci_targ_is_awake(sc, sc->mem)) { + ; + } + while (wait_limit-- && !(A_PCI_READ32(sc->mem + FW_INDICATOR_ADDRESS) & FW_IND_INITIALIZED)) { + if (num_msi_desired == 0) { + /* Fix potential race by repeating CORE_BASE writes */ + A_PCI_WRITE32(sc->mem + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + } + A_MDELAY(10); + } + + if (wait_limit < 0) { + printk(KERN_ERR "ath: %s: TARGET STALLED: .\n", __FUNCTION__); + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + ret = -EIO; + goto err_stalled; + } + A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + } + + if (HIF_PCIDeviceProbed(sc)) { + printk(KERN_ERR "ath: %s: Target probe failed.\n", __FUNCTION__); + ret = -EIO; + goto err_stalled; + } + + *hif_hdl = sc->hif_device; + + /* + * Flag to avoid potential unallocated memory access from MSI + * interrupt handler which could get scheduled as soon as MSI + * is enabled, i.e to take care of the race due to the order + * in where MSI is enabled before the memory, that will be + * in interrupt handlers, is allocated. + */ + sc->hif_init_done = TRUE; + return 0; + +err_stalled: + /* Read Target CPU Intr Cause for debug */ + val = A_PCI_READ32(sc->mem + (SOC_CORE_BASE_ADDRESS | CPU_INTR_ADDRESS)); + printk("ERROR: Target Stalled : Target CPU Intr Cause 0x%x \n", val); + hif_nointrs(sc); +err_intr: + if (num_msi_desired) { + pci_disable_msi(sc->pdev); + } + pci_set_drvdata(sc->pdev, NULL); + + return ret; +} + +void +hif_pci_remove(struct pci_dev *pdev) +{ + struct hif_pci_softc *sc = pci_get_drvdata(pdev); + struct ol_softc *scn; + void __iomem *mem; + + /* Attach did not succeed, all resources have been + * freed in error handler + */ + if (!sc) + return; + + scn = sc->ol_sc; + +#ifndef REMOVE_PKT_LOG + if (vos_get_conparam() != VOS_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + pktlogmod_exit(scn); +#endif + + hif_pci_pm_runtime_exit(sc); + + __hdd_wlan_exit(); + + mem = (void __iomem *)sc->mem; + + pci_disable_msi(pdev); + + hif_dump_pipe_debug_count(sc->hif_device); + + hif_pci_pm_runtime_post_exit(sc); + hif_deinit_adf_ctx(scn); + A_FREE(scn); + A_FREE(sc->hif_device); + A_FREE(sc); + pci_set_drvdata(pdev, NULL); + pci_iounmap(pdev, mem); + pci_release_region(pdev, BAR_NUM); + pci_clear_master(pdev); + pci_disable_device(pdev); + printk(KERN_INFO "pci_remove\n"); +} + +/* This function will be called when SSR framework wants to + * shutdown WLAN host driver when SSR happens. Most of this + * function is duplicated from hif_pci_remove(). + */ +#if defined(CONFIG_CNSS) +void hif_pci_shutdown(struct pci_dev *pdev) +{ + void __iomem *mem; + struct hif_pci_softc *sc; + struct ol_softc *scn; + struct HIF_CE_state *hif_state; + + sc = pci_get_drvdata(pdev); + /* Attach did not succeed, all resources have been + * freed in error handler. + */ + if (!sc) + return; + + hif_state = (struct HIF_CE_state *)sc->hif_device; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { + printk("Load/unload in progress, ignore SSR shutdown\n"); + return; + } + /* this is for cases, where shutdown invoked from CNSS */ + vos_set_logp_in_progress(VOS_MODULE_ID_HIF, TRUE); + vos_set_shutdown_in_progress(VOS_MODULE_ID_HIF, TRUE); + + if (!vos_is_ssr_ready(__func__)) + pr_info("Host driver is not ready for SSR, attempting anyway\n"); + + scn = sc->ol_sc; + + hif_disable_isr(scn); + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + if (!adf_os_atomic_read(&sc->pci_link_suspended)) + hif_pci_device_reset(sc); + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + +#ifndef REMOVE_PKT_LOG + if (vos_get_conparam() != VOS_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + pktlogmod_exit(scn); +#endif + + hif_pci_pm_runtime_exit(sc); + + hif_dump_pipe_debug_count(sc->hif_device); + + if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + hdd_wlan_shutdown(); + + mem = (void __iomem *)sc->mem; + + pci_disable_msi(pdev); + + hif_pci_pm_runtime_ssr_post_exit(sc); + hif_deinit_adf_ctx(scn); + A_FREE(scn); + A_FREE(sc->hif_device); + A_FREE(sc); + pci_set_drvdata(pdev, NULL); + pci_iounmap(pdev, mem); + pci_release_region(pdev, BAR_NUM); + pci_clear_master(pdev); + pci_disable_device(pdev); + vos_set_shutdown_in_progress(VOS_MODULE_ID_HIF, FALSE); + + printk("%s: WLAN host driver shutting down completed!\n", __func__); +} + +void hif_pci_crash_shutdown(struct pci_dev *pdev) +{ +#ifdef TARGET_RAMDUMP_AFTER_KERNEL_PANIC + struct hif_pci_softc *sc; + struct ol_softc *scn; + struct HIF_CE_state *hif_state; + + sc = pci_get_drvdata(pdev); + if (!sc) + return; + + hif_state = (struct HIF_CE_state *)sc->hif_device; + if (!hif_state) + return; + + scn = sc->ol_sc; + if (!scn) + return; + + if (OL_TRGET_STATUS_RESET == scn->target_status) { + printk("%s: Target is already asserted, ignore!\n", __func__); + return; + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { + pr_info("%s: Load/unload is in progress, ignore!\n", __func__); + return; + } + + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + + hif_irq_record(HIF_CRASH, sc); + +#ifdef DEBUG + if (hif_pci_check_soc_status(scn->hif_sc) + || dump_CE_register(scn)) { + goto out; + } + + dump_CE_debug_register(scn->hif_sc); +#endif + + if (ol_copy_ramdump(scn)) { + goto out; + } + + printk("%s: RAM dump collecting completed!\n", __func__); + +out: + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + return; +#else + printk("%s: Collecting target RAM dump after kernel panic is disabled!\n", + __func__); + return; +#endif +} +#endif + +#define OL_ATH_PCI_PM_CONTROL 0x44 + +static int +__hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) +{ + struct hif_pci_softc *sc = pci_get_drvdata(pdev); + void *vos = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + ol_txrx_pdev_handle txrx_pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos); + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + A_target_id_t targid = hif_state->targid; + u32 tx_drain_wait_cnt = 0; + u32 val; + u32 ce_drain_wait_cnt = 0; + v_VOID_t * temp_module; + u32 tmp; + int ret = -EBUSY; + + if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) + return ret; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) + return ret; + + if (!txrx_pdev) { + printk("%s: txrx_pdev is NULL\n", __func__); + goto out; + } + /* Wait for pending tx completion */ + while (ol_txrx_get_tx_pending(txrx_pdev)) { + msleep(OL_ATH_TX_DRAIN_WAIT_DELAY); + if (++tx_drain_wait_cnt > OL_ATH_TX_DRAIN_WAIT_CNT) { + printk("%s: tx frames are pending\n", __func__); + ol_txrx_dump_tx_desc(txrx_pdev); + goto out; + } + } + + /* No need to send WMI_PDEV_SUSPEND_CMDID to FW if WOW is enabled */ + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos); + if (!temp_module) { + printk("%s: WDA module is NULL\n", __func__); + goto out; + } + + if (wma_check_scan_in_progress(temp_module)) { + printk("%s: Scan in progress. Aborting suspend%s\n", __func__, + runtime_pm ? " for runtime PM" : ""); + goto out; + } + + if (wma_is_wow_mode_selected(temp_module)) { + if(wma_enable_wow_in_fw(temp_module, runtime_pm)) + goto out; + } else { + if (wma_suspend_target(temp_module, 0)) + goto out; + } + + while (!adf_os_atomic_read(&sc->ce_suspend)) { + if (++ce_drain_wait_cnt > HIF_CE_DRAIN_WAIT_CNT) { + printk("%s: CE still not done with access: \n", __func__); + adf_os_atomic_set(&sc->wow_done, 0); + + if (!wma_is_wow_mode_selected(temp_module)) { + wma_resume_target(temp_module, runtime_pm); + goto out; + } + else { + wma_disable_wow_in_fw(temp_module, runtime_pm); + goto out; + } + } + pr_debug("%s: Waiting for CE to finish access: \n", __func__); + msleep(10); + } + +#ifdef FEATURE_WLAN_D0WOW + if (wma_get_client_count(temp_module)) { + if (enable_irq_wake(pdev->irq)) { + pr_err("%s: Fail to enable wake IRQ!\n", __func__); + ret = -EAGAIN; + goto out; + } + + pr_info("%s: Suspend completes (D0WOW)\n", __func__); + ret = 0; + goto out; + } +#endif + + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + + /*Disable PCIe interrupts*/ + if (HIFTargetSleepStateAdjust(targid, FALSE, TRUE) < 0) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + goto out; + } + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), 0); + A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_CLR_ADDRESS), + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + /* IMPORTANT: this extra read transaction is required to flush the posted write buffer */ + tmp = A_PCI_READ32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); + if (tmp == 0xffffffff) { + printk(KERN_ERR "%s: PCIe pcie link is down\n", __func__); + VOS_ASSERT(0); + } + + if (HIFTargetSleepStateAdjust(targid, TRUE, FALSE) < 0) { + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + goto out; + } + + /* Stop the HIF Sleep Timer */ + HIFCancelDeferredTargetSleep(sc->hif_device); + + adf_os_atomic_set(&sc->pci_link_suspended, 1); + + adf_os_spin_unlock_irqrestore( &hif_state->suspend_lock); + +#ifdef CONFIG_CNSS + /* Keep PCIe bus driver's shadow memory intact */ + cnss_pcie_shadow_control(pdev, FALSE); +#endif + + if (runtime_pm) + goto skip; + + pci_read_config_dword(pdev, OL_ATH_PCI_PM_CONTROL, &val); + if ((val & 0x000000ff) != 0x3) { + pci_save_state(pdev); + pci_disable_device(pdev); + pci_write_config_dword(pdev, OL_ATH_PCI_PM_CONTROL, (val & 0xffffff00) | 0x03); + } + +skip: + pr_info("%s: Suspend completes%s in%s mode event:%d device_state:%d\n", + __func__, runtime_pm ? " for runtime pm" : "", + wma_is_wow_mode_selected(temp_module) ? " wow" : " pdev", + state.event, val); + printk("%s: Suspend completes%s\n", __func__, + runtime_pm ? " for runtime pm" : ""); + + ret = 0; + +out: + return ret; +} + +static int hif_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int ret; + + vos_ssr_protect(__func__); + + ret = __hif_pci_suspend(pdev, state, false); + + vos_ssr_unprotect(__func__); + + return ret; +} + +static int +__hif_pci_resume(struct pci_dev *pdev, bool runtime_pm) +{ + struct hif_pci_softc *sc = pci_get_drvdata(pdev); + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + A_target_id_t targid = hif_state->targid; + u32 val; + int err = 0; + v_VOID_t * temp_module; + u32 tmp; + int retry = 0; + + if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) + return err; + + adf_os_atomic_set(&sc->pci_link_suspended, 0); + adf_os_atomic_set(&sc->wow_done, 0); + + /* Enable Legacy PCI line interrupts */ + if (HIFTargetSleepStateAdjust(targid, FALSE, TRUE) < 0) + goto out; + for (;;) { + A_PCI_WRITE32(sc->mem + + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); + /* + * IMPORTANT: this extra read transaction is required to + * flush the posted write buffer + */ + + tmp = A_PCI_READ32(sc->mem + + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); + + if (tmp != 0xffffffff) + break; + + if (retry > MAX_REG_READ_RETRIES) { + pr_err("%s: PCIe link is possible down!\n", __func__); + print_config_soc_reg(sc); + VOS_ASSERT(0); + break; + } + + A_MDELAY(1); + retry++; + } + if (HIFTargetSleepStateAdjust(targid, TRUE, FALSE) < 0) + goto out; + + if (runtime_pm) + goto skip; + + err = pci_enable_device(pdev); + if (err) + { + printk("\n%s %d : pci_enable_device returned failure %d\n", + __func__, __LINE__, err); + goto out; + } + + pci_read_config_dword(pdev, OL_ATH_PCI_PM_CONTROL, &val); + if ((val & 0x000000ff) != 0) { + pci_restore_state(pdev); + pci_write_config_dword(pdev, OL_ATH_PCI_PM_CONTROL, val & 0xffffff00); + + /* + * Suspend/Resume resets the PCI configuration space, so we have to + * re-disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state + * + */ + pci_read_config_dword(pdev, 0x40, &val); + + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + } + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + +skip: +#ifdef CONFIG_CNSS + /* Keep PCIe bus driver's shadow memory intact */ + cnss_pcie_shadow_control(pdev, TRUE); +#endif + +#ifdef DISABLE_L1SS_STATES + pci_read_config_dword(pdev, 0x188, &val); + pci_write_config_dword(pdev, 0x188, (val & ~0x0000000f)); +#endif + + /* No need to send WMI_PDEV_RESUME_CMDID to FW if WOW is enabled */ + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + if (!temp_module) { + printk("%s: WDA module is NULL\n", __func__); + goto out; + } + + if (!wma_is_wow_mode_selected(temp_module)) + err = wma_resume_target(temp_module, runtime_pm); + else + err = wma_disable_wow_in_fw(temp_module, runtime_pm); + +#ifdef FEATURE_WLAN_D0WOW + if (wma_get_client_count(temp_module)) { + if (disable_irq_wake(pdev->irq)) { + pr_err("%s: Fail to disable wake IRQ!\n", __func__); + err = -1; + goto out; + } + } +#endif + + pr_info("%s: Resume completes%s in%s mode\n", __func__, + runtime_pm ? " for runtime pm" : "", + wma_is_wow_mode_selected(temp_module) ? " wow" : " pdev"); +out: + if (err) { + pr_err("%s: resume failed err:%d\n", __func__, err); + return (-1); + } + + return (0); +} + +static int +hif_pci_resume(struct pci_dev *pdev) +{ + int ret; + + vos_ssr_protect(__func__); + + ret = __hif_pci_resume(pdev, false); + + vos_ssr_unprotect(__func__); + + return ret; +} + +/* routine to modify the initial buffer count to be allocated on an os + * platform basis. Platform owner will need to modify this as needed + */ +adf_os_size_t initBufferCount(adf_os_size_t maxSize) +{ + return maxSize; +} + +#ifdef CONFIG_CNSS +struct cnss_wlan_driver cnss_wlan_drv_id = { + .name = "hif_pci", + .id_table = hif_pci_id_table, + .probe = hif_pci_probe, + .remove = hif_pci_remove, + .reinit = hif_pci_reinit, + .shutdown = hif_pci_shutdown, + .crash_shutdown = hif_pci_crash_shutdown, + .modem_status = hif_pci_notify_handler, +#ifdef ATH_BUS_PM + .suspend = hif_pci_suspend, + .resume = hif_pci_resume, +#ifdef FEATURE_RUNTIME_PM + .runtime_ops = &runtime_pm_ops, +#endif +#endif +}; +#else +MODULE_DEVICE_TABLE(pci, hif_pci_id_table); +struct pci_driver hif_pci_drv_id = { + .name = "hif_pci", + .id_table = hif_pci_id_table, + .probe = hif_pci_probe, + .remove = hif_pci_remove, +#ifdef ATH_BUS_PM + .suspend = hif_pci_suspend, + .resume = hif_pci_resume, +#endif +}; +#endif + +int hif_register_driver(void) +{ +#ifdef CONFIG_CNSS + return cnss_wlan_register_driver(&cnss_wlan_drv_id); +#else + return pci_register_driver(&hif_pci_drv_id); +#endif +} + +void hif_unregister_driver(void) +{ +#ifdef CONFIG_CNSS + cnss_wlan_unregister_driver(&cnss_wlan_drv_id); +#else + pci_unregister_driver(&hif_pci_drv_id); +#endif +} + +/* Function to set the TXRX handle in the ol_sc context */ +void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + sc->pdev_txrx_handle = txrx_handle; +} + +void hif_disable_isr(void *ol_sc) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + struct ol_softc *scn; + if (hif_sc->hdd_startup_reinit_flag) { + pr_err("%s: WARN: in HDD starrtup or reinit function\n", + __func__); + return; + } + scn = hif_sc->ol_sc; + hif_nointrs(hif_sc); +#if CONFIG_PCIE_64BIT_MSI + OS_FREE_CONSISTENT(scn->sc_osdev, 4, scn->MSI_magic, scn->MSI_magic_dma, + OS_GET_DMA_MEM_CONTEXT(scn, MSI_dmacontext)); + scn->MSI_magic = NULL; + scn->MSI_magic_dma = 0; +#endif + /* Cancel the pending tasklet */ + tasklet_kill(&hif_sc->intr_tq); +} + +/* Function to reset SoC */ +void hif_reset_soc(void *ol_sc) +{ + struct ol_softc *scn = (struct ol_softc *)ol_sc; + struct hif_pci_softc *sc = scn->hif_sc; + +#if defined(CPU_WARM_RESET_WAR) + /* Currently CPU warm reset sequence is tested only for AR9888_REV2 + * Need to enable for AR9888_REV1 once CPU warm reset sequence is + * verified for AR9888_REV1 + */ + if (scn->target_version == AR9888_REV2_VERSION) { + hif_pci_device_warm_reset(sc); + } + else { + hif_pci_device_reset(sc); + } +#else + hif_pci_device_reset(sc); +#endif +} + +void hif_disable_aspm(void) +{ + u_int32_t lcr_val = 0; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + struct ol_softc *scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + struct hif_pci_softc *sc; + + if (NULL == scn) + { + printk(KERN_ERR "%s: Could not disable ASPM scn is null\n", __func__); + return; + } + + sc = scn->hif_sc; + + /* Disable ASPM when pkt log is enabled */ + pci_read_config_dword(sc->pdev, 0x80, &lcr_val); + pci_write_config_dword(sc->pdev, 0x80, (lcr_val & 0xffffff00)); +} + +void hif_pci_save_htc_htt_config_endpoint(int htc_endpoint) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + struct ol_softc *scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + + if (!scn || !scn->hif_sc) { + printk(KERN_ERR "%s: error: scn or scn->hif_sc is NULL!\n", __func__); + return; + } + + scn->hif_sc->htc_endpoint = htc_endpoint; +} + +void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision) +{ + *version = ((struct ol_softc *)ol_sc)->target_version; + *revision = ((struct ol_softc *)ol_sc)->target_revision; +} + +void hif_set_fw_info(void *ol_sc, u32 target_fw_version) +{ + ((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version; +} + +#ifdef IPA_UC_OFFLOAD +/* Micro controller needs PCI BAR address to access CE register */ +void hif_read_bar(struct hif_pci_softc *sc, u32 *bar_value) +{ + pci_read_config_dword(sc->pdev, 0x10, bar_value); + *bar_value = pci_resource_start(sc->pdev, 0); +} +#endif /* IPA_UC_OFFLOAD */ + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +void wlan_hif_pci_suspend(void) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + struct ol_softc *scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + pm_message_t state; + + if (!scn || !scn->hif_sc) { + printk(KERN_ERR "%s: error: scn or scn->hif_sc is NULL!\n", __func__); + return; + } + state.event = PM_EVENT_SUSPEND; + hif_pci_suspend(scn->hif_sc->pdev, state); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h new file mode 100644 index 000000000000..619278062439 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +#ifndef __ATH_PCI_H__ +#define __ATH_PCI_H__ + +#include +#include +#include + +#define CONFIG_COPY_ENGINE_SUPPORT /* TBDXXX: here for now */ +#define ATH_DBG_DEFAULT 0 +#include +#include +#include +#include "osapi_linux.h" +#include "hif.h" +#include "cepci.h" + +/* Maximum number of Copy Engine's supported */ +#define CE_COUNT_MAX 8 +#define CE_HTT_H2T_MSG_SRC_NENTRIES 2048 + +struct CE_state; +struct ol_softc; + +/* An address (e.g. of a buffer) in Copy Engine space. */ +typedef ath_dma_addr_t CE_addr_t; + +#ifdef FEATURE_RUNTIME_PM +/* Driver States for Runtime Power Management */ +enum hif_pm_runtime_state { + HIF_PM_RUNTIME_STATE_NONE, + HIF_PM_RUNTIME_STATE_ON, + HIF_PM_RUNTIME_STATE_INPROGRESS, + HIF_PM_RUNTIME_STATE_SUSPENDED, +}; + +/* Debugging stats for Runtime PM */ +struct hif_pci_pm_stats { + u32 suspended; + u32 suspend_err; + u32 resumed; + u32 runtime_get; + u32 runtime_put; + u32 request_resume; + u32 allow_suspend; + u32 prevent_suspend; + u32 prevent_suspend_timeout; + u32 allow_suspend_timeout; + u32 runtime_get_err; + void *last_resume_caller; + unsigned long suspend_jiffies; +}; +#endif +struct hif_pci_softc { + void __iomem *mem; /* PCI address. */ + /* For efficiency, should be first in struct */ + + struct device *dev; + struct pci_dev *pdev; + struct _NIC_DEV aps_osdev; + struct ol_softc *ol_sc; + int num_msi_intrs; /* number of MSI interrupts granted */ + /* 0 --> using legacy PCI line interrupts */ + struct tasklet_struct intr_tq; /* tasklet */ + + int irq; + int irq_event; + int cacheline_sz; + /* + * Guard changes to Target HW state and to software + * structures that track hardware state. + */ + adf_os_spinlock_t target_lock; + + unsigned int ce_count; /* Number of Copy Engines supported */ + struct CE_state *CE_id_to_state[CE_COUNT_MAX]; /* Map CE id to CE_state */ + HIF_DEVICE *hif_device; + + bool force_break; /* Flag to indicate whether to break out the DPC context */ + unsigned int receive_count; /* count Num Of Receive Buffers handled for one interrupt DPC routine */ + u16 devid; + struct targetdef_s *targetdef; + struct hostdef_s *hostdef; + atomic_t tasklet_from_intr; + atomic_t wow_done; +#ifdef FEATURE_WLAN_D0WOW + atomic_t in_d0wow; +#endif + atomic_t ce_suspend; + atomic_t pci_link_suspended; + bool hif_init_done; + bool recovery; + bool hdd_startup_reinit_flag; + int htc_endpoint; +#ifdef FEATURE_RUNTIME_PM + atomic_t pm_state; + uint32_t prevent_suspend_cnt; + struct hif_pci_pm_stats pm_stats; + struct work_struct pm_work; + struct spinlock runtime_lock; + struct timer_list runtime_timer; + struct list_head prevent_suspend_list; + unsigned long runtime_timer_expires; +#ifdef WLAN_OPEN_SOURCE + struct dentry *pm_dentry; +#endif +#endif +}; +#define TARGID(sc) ((A_target_id_t)(&(sc)->mem)) +#define TARGID_TO_HIF(targid) (((struct hif_pci_softc *)((char *)(targid) - (char *)&(((struct hif_pci_softc *)0)->mem)))->hif_device) + +int athdiag_procfs_init(void *scn); +void athdiag_procfs_remove(void); + +bool hif_pci_targ_is_awake(struct hif_pci_softc *sc, void *__iomem *mem); + +bool hif_pci_targ_is_present(A_target_id_t targetid, void *__iomem *mem); + +bool hif_max_num_receives_reached(unsigned int count); + +int HIF_PCIDeviceProbed(hif_handle_t hif_hdl); +irqreturn_t HIF_fw_interrupt_handler(int irq, void *arg); + +/* routine to modify the initial buffer count to be allocated on an os + * platform basis. Platform owner will need to modify this as needed + */ +adf_os_size_t initBufferCount(adf_os_size_t maxSize); + +/* Function to disable ASPM */ +void hif_disable_aspm(void); + +void hif_pci_save_htc_htt_config_endpoint(int htc_endpoint); + +int hif_pci_set_ram_config_reg(struct hif_pci_softc *sc, uint32_t config); +int hif_pci_check_fw_reg(struct hif_pci_softc *sc); +int hif_pci_check_soc_status(struct hif_pci_softc *sc); +void dump_CE_debug_register(struct hif_pci_softc *sc); + +/*These functions are exposed to HDD*/ +int hif_register_driver(void); +void hif_unregister_driver(void); +int hif_init_adf_ctx(void *ol_sc); +void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle); +void hif_disable_isr(void *ol_sc); +void hif_reset_soc(void *ol_sc); +void hif_deinit_adf_ctx(void *ol_sc); +void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision); +void hif_set_fw_info(void *ol_sc, u32 target_fw_version); + +#ifdef IPA_UC_OFFLOAD +/* + * Micro controller needs PCI BAR address to access CE register + * If Micro controller data path enabled, control path will + * try to get PCI BAR address and will send to IPA driver + */ +void hif_read_bar(struct hif_pci_softc *sc, u32 *bar_value); +#endif /* IPA_UC_OFFLOAD */ + +/* + * A firmware interrupt to the Host is indicated by the + * low bit of SCRATCH_3_ADDRESS being set. + */ +#define FW_EVENT_PENDING_REG_ADDRESS SCRATCH_3_ADDRESS + +/* + * Typically, MSI Interrupts are used with PCIe. To force use of legacy + * "ABCD" PCI line interrupts rather than MSI, define FORCE_LEGACY_PCI_INTERRUPTS. + * Even when NOT forced, the driver may attempt to use legacy PCI interrupts + * MSI allocation fails + */ +#define LEGACY_INTERRUPTS(sc) ((sc)->num_msi_intrs == 0) + +/* + * There may be some pending tx frames during platform suspend. + * Suspend operation should be delayed until those tx frames are + * transfered from the host to target. This macro specifies how + * long suspend thread has to sleep before checking pending tx + * frame count. + */ +#define OL_ATH_TX_DRAIN_WAIT_DELAY 50 /* ms */ + +#define HIF_CE_DRAIN_WAIT_DELAY 10 /* ms */ +/* + * Wait time (in unit of OL_ATH_TX_DRAIN_WAIT_DELAY) for pending + * tx frame completion before suspend. Refer: hif_pci_suspend() + */ +#define OL_ATH_TX_DRAIN_WAIT_CNT 10 + +#define HIF_CE_DRAIN_WAIT_CNT 20 +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +void wlan_hif_pci_suspend(void); +#endif +#endif /* __ATH_PCI_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/mp_dev.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/mp_dev.c new file mode 100644 index 000000000000..66de1d5890c3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/mp_dev.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "if_pci.h" + +/*chaninfo*/ +#define CHANINFOMEM_S2_READ_MASK 0x00000008 +#define CHANINFO_CTRL_CAPTURE_CHAN_INFO_MASK 0x00000001 +#define CHANINFO_CTRL_CHANINFOMEM_BW_MASK 0x00000030 +#define MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK 0x00000007 + +/*agc*/ +#define GAINS_MIN_OFFSETS_CF_AGC_HIST_ENABLE_MASK 0x00040000 +#define GAINS_MIN_OFFSETS_CF_AGC_HIST_GC_MASK 0x00080000 +#define GAINS_MIN_OFFSETS_CF_AGC_HIST_VOTING_MASK 0x00100000 +#define GAINS_MIN_OFFSETS_CF_AGC_HIST_PHY_ERR_MASK 0x00200000 +#define AGC_HISTORY_DUMP_MASK GAINS_MIN_OFFSETS_CF_AGC_HIST_ENABLE_MASK| \ + GAINS_MIN_OFFSETS_CF_AGC_HIST_GC_MASK| \ + GAINS_MIN_OFFSETS_CF_AGC_HIST_VOTING_MASK| \ + GAINS_MIN_OFFSETS_CF_AGC_HIST_PHY_ERR_MASK + +#define BB_chaninfo_ctrl 0x1a370 +#define BB_multichain_enable 0x1a2a0 +#define BB_chn_tables_intf_addr 0x19894 +#define BB_chn1_tables_intf_addr 0x1a894 +#define BB_chn_tables_intf_data 0x19898 +#define BB_chn1_tables_intf_data 0x1a898 +#define BB_gains_min_offsets 0x19e08 +#define BB_chaninfo_tab_b0 0x03200 +#define BB_chaninfo_tab_b1 0x03300 +#define BB_watchdog_status 0x1a7c0 +#define BB_watchdog_ctrl_1 0x1a7c4 +#define BB_watchdog_ctrl_2 0x1a7c8 +#define BB_watchdog_status_B 0x1a7e0 + +#define PHY_BB_CHN_TABLES_INTF_ADDR 0x19894 +#define PHY_BB_CHN_TABLES_INTF_DATA 0x19898 + +#define PHY_BB_CHN1_TABLES_INTF_ADDR 0x1a894 +#define PHY_BB_CHN1_TABLES_INTF_DATA 0x1a898 + + +struct priv_ctrl_ctx { + u_int32_t chaninfo_ctrl_orig; + u_int32_t gain_min_offsets_orig; + u_int32_t anyreg_start; + u_int32_t anyreg_len; +}; + +static struct priv_ctrl_ctx g_Priv_Dump_Ctx; + +static INLINE void set_target_reg_bits(struct hif_pci_softc* hif, u_int32_t reg, u_int32_t bitmask, u_int32_t val) +{ + u_int32_t value = A_PCI_READ32(hif->mem + (reg)); + u_int32_t shift = 0; + value &= ~(bitmask); + while (!((bitmask >> shift) & 0x01)) { + shift++; + } + value |= (((val)<mem + (reg), value); +} + +static INLINE u_int32_t get_target_reg_bits(struct hif_pci_softc* hif, u_int32_t reg, u_int32_t bitmask) +{ + u_int32_t value = A_PCI_READ32(hif->mem + (reg)); + u_int32_t shift = 0; + while (!((bitmask >> shift) & 0x01)) { + shift++; + } + return (value>>shift)&bitmask; +} + +void priv_start_cap_chaninfo(struct hif_pci_softc* hif_sc) +{ + set_target_reg_bits(hif_sc, BB_chaninfo_ctrl, CHANINFO_CTRL_CAPTURE_CHAN_INFO_MASK, 1); +} + +void priv_start_agc(struct hif_pci_softc* hif_sc) +{ + g_Priv_Dump_Ctx.gain_min_offsets_orig = A_PCI_READ32(hif_sc->mem + BB_gains_min_offsets); + set_target_reg_bits(hif_sc, BB_gains_min_offsets, AGC_HISTORY_DUMP_MASK, 0x0f); +} + +void priv_stop_agc(struct hif_pci_softc* hif_sc) +{ + set_target_reg_bits(hif_sc, BB_gains_min_offsets, AGC_HISTORY_DUMP_MASK, 0); +} + +void priv_dump_chaninfo(struct hif_pci_softc* hif_sc) +{ + u_int32_t bw, val; + u_int32_t len, i, tmp; + u_int32_t chain_mask; + u_int32_t chain0, chain1; + + chain_mask = get_target_reg_bits(hif_sc, BB_multichain_enable, MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK); + chain0 = chain_mask & 1; + chain1 = chain_mask & 2; + + printk("\nChannel info dump:\n"); + bw = get_target_reg_bits(hif_sc, BB_chaninfo_ctrl, CHANINFO_CTRL_CHANINFOMEM_BW_MASK); + + if (bw == 0) { + len = 53; + } else if (bw == 1) { + len = 57; + } else if (bw == 2) { + len = 59*2-1; + } else { + len = 60*2+61*2; + } + + /* + * each tone is 16 bit valid, write to 32bit buffer each. + * bw==0(legacy20): 53 tones. + * bw==1(ht/vht20): 57 tones. + * bw==2(ht/vht40): 59+58 tones. + * bw==3(vht80): 60*2+61*2 tones. + */ + + if (chain0) { + A_PCI_WRITE32(hif_sc->mem+BB_chn_tables_intf_addr, 0x80003200); + } + if (chain1) { + A_PCI_WRITE32(hif_sc->mem+BB_chn1_tables_intf_addr, 0x80003200); + } + + set_target_reg_bits(hif_sc, BB_chaninfo_ctrl, CHANINFOMEM_S2_READ_MASK, 0); + + if (chain0) { + if (bw < 2) { + len = (bw == 0) ? 53 : 57; + for (i=0; imem+BB_chn_tables_intf_data) & 0x0000ffff; + printk("0x%x\t",val); + if (i%4 == 0) + printk("\n"); + } + } else { + len = (bw == 2) ? 59 : 60; + for (i=0; imem+BB_chn_tables_intf_data); + printk("0x%x\t", ((tmp>>16) & 0x0000ffff)); + printk("0x%x\t", (tmp & 0x0000ffff)); + if (i%2 == 0) + printk("\n"); + } + if (bw > 2) { + //bw == 3 for vht80 + A_PCI_WRITE32(hif_sc->mem+BB_chn_tables_intf_addr, 0x80003300); + len = 61; + for (i=0; imem+BB_chn_tables_intf_data); + printk("0x%x\t", ((tmp>>16) & 0x0000ffff)); + printk("0x%x\t", (tmp & 0x0000ffff)); + if (i%2 == 0) + printk("\n"); + } + } + } + } + if (chain1) { + if (bw < 2) { + len = (bw == 0) ? 53 : 57; + for (i=0; imem+BB_chn1_tables_intf_data) & 0x0000ffff; + printk("0x%x\t",val); + if (i%4 == 0) + printk("\n"); + } + } else { + len = (bw == 2) ? 59 : 60; + for (i=0; imem+BB_chn1_tables_intf_data); + printk("0x%x\n", (tmp>>16) & 0x0000ffff); + printk("0x%x\n", tmp & 0x0000ffff); + if (i%2 == 0) + printk("\n"); + } + if (bw > 2) { + //bw == 3 for vht80 + A_PCI_WRITE32(hif_sc->mem+BB_chn1_tables_intf_addr, 0x80003300); + len = 61; + for (i=0; imem+BB_chn1_tables_intf_data); + printk("0x%x\t", ((tmp>>16) & 0x0000ffff)); + printk("0x%x\t", (tmp & 0x0000ffff)); + if (i%2 == 0) + printk("\n"); + } + } + } + } + printk("\nChannel info dump complete\n"); +} + +void priv_dump_agc(struct hif_pci_softc* hif_sc) +{ + int i, len = 30; //check this value for Rome and Peregrine + u_int32_t chain0, chain1, chain_mask, val; + A_target_id_t targid = TARGID(hif_sc); + + A_TARGET_ACCESS_BEGIN(targid); + + chain_mask = get_target_reg_bits(hif_sc, BB_multichain_enable, MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK); + chain0 = chain_mask & 1; + chain1 = chain_mask & 2; + + len = len<<1; //each agc item is 64bit, total*2 + priv_stop_agc(hif_sc); + + set_target_reg_bits(hif_sc, BB_chaninfo_ctrl, CHANINFOMEM_S2_READ_MASK, 0); + + printk("AGC history buffer dump:\n"); + if (chain0) { + for (i = 0; i < len; i++) { + A_PCI_WRITE32(hif_sc->mem + PHY_BB_CHN_TABLES_INTF_ADDR, + BB_chaninfo_tab_b0 + i*4); + val = A_PCI_READ32(hif_sc->mem + PHY_BB_CHN_TABLES_INTF_DATA); + printk("0x%x\t", val); + if (i%4 == 0) + printk("\n"); + } + } + if (chain1) { + for (i = 0; i < len; i++) { + A_PCI_WRITE32(hif_sc->mem + PHY_BB_CHN1_TABLES_INTF_ADDR, + BB_chaninfo_tab_b0 + i*4); + val = A_PCI_READ32(hif_sc->mem + PHY_BB_CHN1_TABLES_INTF_DATA); + printk("0x%x\t", val); + if (i%4 == 0) + printk("\n"); + } + } + printk("\nAGC history buffer dump complete\n"); + //restore original value + A_PCI_WRITE32(hif_sc->mem + BB_gains_min_offsets, g_Priv_Dump_Ctx.gain_min_offsets_orig); + + A_TARGET_ACCESS_END(targid); + + return; +} + +void priv_dump_bbwatchdog(struct hif_pci_softc* hif_sc) +{ + u_int32_t val; + + printk("BB watchdog dump\n"); + val = A_PCI_READ32(hif_sc->mem + BB_watchdog_status); + printk("0x%x\t",val); + val = A_PCI_READ32(hif_sc->mem + BB_watchdog_ctrl_1); + printk("0x%x\t",val); + val = A_PCI_READ32(hif_sc->mem + BB_watchdog_ctrl_2); + printk("0x%x\t",val); + val = A_PCI_READ32(hif_sc->mem + BB_watchdog_status_B); + printk("0x%x\n",val); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.c new file mode 100644 index 000000000000..14cb319a4384 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "bmi_msg.h" +#include "targaddrs.h" +#include "cepci.h" +#include "regtable.h" +#include "ar9888def.h" +#include "ar6320def.h" +#include "ar6320v2def.h" + +void target_register_tbl_attach(struct hif_pci_softc *sc, u32 target_type) +{ + switch (target_type) { + case TARGET_TYPE_AR9888: + sc->targetdef = &ar9888_targetdef; + break; + case TARGET_TYPE_AR6320: + sc->targetdef = &ar6320_targetdef; + break; + case TARGET_TYPE_AR6320V2: + sc->targetdef = &ar6320v2_targetdef; + break; + default: + break; + } +} + +void hif_register_tbl_attach(struct hif_pci_softc *sc, u32 hif_type) +{ + switch (hif_type) { + case HIF_TYPE_AR9888: + sc->hostdef = &ar9888_hostdef; + break; + case HIF_TYPE_AR6320: + sc->hostdef = &ar6320_hostdef; + break; + case HIF_TYPE_AR6320V2: + sc->hostdef = &ar6320v2_hostdef; + break; + default: + break; + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.h new file mode 100644 index 000000000000..aaf07115618b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/regtable.h @@ -0,0 +1,851 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _REGTABLE_H_ +#define _REGTABLE_H_ +#include "if_pci.h" + +#define MISSING 0 + +typedef struct targetdef_s { + u_int32_t d_RTC_SOC_BASE_ADDRESS; + u_int32_t d_RTC_WMAC_BASE_ADDRESS; + u_int32_t d_SYSTEM_SLEEP_OFFSET; + u_int32_t d_WLAN_SYSTEM_SLEEP_OFFSET; + u_int32_t d_WLAN_SYSTEM_SLEEP_DISABLE_LSB; + u_int32_t d_WLAN_SYSTEM_SLEEP_DISABLE_MASK; + u_int32_t d_CLOCK_CONTROL_OFFSET; + u_int32_t d_CLOCK_CONTROL_SI0_CLK_MASK; + u_int32_t d_RESET_CONTROL_OFFSET; + u_int32_t d_RESET_CONTROL_MBOX_RST_MASK; + u_int32_t d_RESET_CONTROL_SI0_RST_MASK; + u_int32_t d_WLAN_RESET_CONTROL_OFFSET; + u_int32_t d_WLAN_RESET_CONTROL_COLD_RST_MASK; + u_int32_t d_WLAN_RESET_CONTROL_WARM_RST_MASK; + u_int32_t d_GPIO_BASE_ADDRESS; + u_int32_t d_GPIO_PIN0_OFFSET; + u_int32_t d_GPIO_PIN1_OFFSET; + u_int32_t d_GPIO_PIN0_CONFIG_MASK; + u_int32_t d_GPIO_PIN1_CONFIG_MASK; + u_int32_t d_SI_CONFIG_BIDIR_OD_DATA_LSB; + u_int32_t d_SI_CONFIG_BIDIR_OD_DATA_MASK; + u_int32_t d_SI_CONFIG_I2C_LSB; + u_int32_t d_SI_CONFIG_I2C_MASK; + u_int32_t d_SI_CONFIG_POS_SAMPLE_LSB; + u_int32_t d_SI_CONFIG_POS_SAMPLE_MASK; + u_int32_t d_SI_CONFIG_INACTIVE_CLK_LSB; + u_int32_t d_SI_CONFIG_INACTIVE_CLK_MASK; + u_int32_t d_SI_CONFIG_INACTIVE_DATA_LSB; + u_int32_t d_SI_CONFIG_INACTIVE_DATA_MASK; + u_int32_t d_SI_CONFIG_DIVIDER_LSB; + u_int32_t d_SI_CONFIG_DIVIDER_MASK; + u_int32_t d_SI_BASE_ADDRESS; + u_int32_t d_SI_CONFIG_OFFSET; + u_int32_t d_SI_TX_DATA0_OFFSET; + u_int32_t d_SI_TX_DATA1_OFFSET; + u_int32_t d_SI_RX_DATA0_OFFSET; + u_int32_t d_SI_RX_DATA1_OFFSET; + u_int32_t d_SI_CS_OFFSET; + u_int32_t d_SI_CS_DONE_ERR_MASK; + u_int32_t d_SI_CS_DONE_INT_MASK; + u_int32_t d_SI_CS_START_LSB; + u_int32_t d_SI_CS_START_MASK; + u_int32_t d_SI_CS_RX_CNT_LSB; + u_int32_t d_SI_CS_RX_CNT_MASK; + u_int32_t d_SI_CS_TX_CNT_LSB; + u_int32_t d_SI_CS_TX_CNT_MASK; + u_int32_t d_BOARD_DATA_SZ; + u_int32_t d_BOARD_EXT_DATA_SZ; + u_int32_t d_MBOX_BASE_ADDRESS; + u_int32_t d_LOCAL_SCRATCH_OFFSET; + u_int32_t d_CPU_CLOCK_OFFSET; + u_int32_t d_LPO_CAL_OFFSET; + u_int32_t d_GPIO_PIN10_OFFSET; + u_int32_t d_GPIO_PIN11_OFFSET; + u_int32_t d_GPIO_PIN12_OFFSET; + u_int32_t d_GPIO_PIN13_OFFSET; + u_int32_t d_CLOCK_GPIO_OFFSET; + u_int32_t d_CPU_CLOCK_STANDARD_LSB; + u_int32_t d_CPU_CLOCK_STANDARD_MASK; + u_int32_t d_LPO_CAL_ENABLE_LSB; + u_int32_t d_LPO_CAL_ENABLE_MASK; + u_int32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB; + u_int32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK; + u_int32_t d_ANALOG_INTF_BASE_ADDRESS; + u_int32_t d_WLAN_MAC_BASE_ADDRESS; + u_int32_t d_CE0_BASE_ADDRESS; + u_int32_t d_CE1_BASE_ADDRESS; + u_int32_t d_FW_INDICATOR_ADDRESS; + u_int32_t d_DRAM_BASE_ADDRESS; + u_int32_t d_SOC_CORE_BASE_ADDRESS; + u_int32_t d_CORE_CTRL_ADDRESS; + u_int32_t d_CE_COUNT; + u_int32_t d_MSI_NUM_REQUEST; + u_int32_t d_MSI_ASSIGN_FW; + u_int32_t d_MSI_ASSIGN_CE_INITIAL; + u_int32_t d_PCIE_INTR_ENABLE_ADDRESS; + u_int32_t d_PCIE_INTR_CLR_ADDRESS; + u_int32_t d_PCIE_INTR_FIRMWARE_MASK; + u_int32_t d_PCIE_INTR_CE_MASK_ALL; + u_int32_t d_CORE_CTRL_CPU_INTR_MASK; + u_int32_t d_FW_RAM_CONFIG_ADDRESS; + u_int32_t d_SR_WR_INDEX_ADDRESS; + u_int32_t d_DST_WATERMARK_ADDRESS; + + /* htt_rx.c */ + u_int32_t d_RX_MSDU_END_4_FIRST_MSDU_MASK; + u_int32_t d_RX_MSDU_END_4_FIRST_MSDU_LSB; + u_int32_t d_RX_MPDU_START_0_RETRY_LSB; + u_int32_t d_RX_MPDU_START_0_RETRY_MASK; + u_int32_t d_RX_MPDU_START_0_SEQ_NUM_MASK; + u_int32_t d_RX_MPDU_START_0_SEQ_NUM_LSB; + u_int32_t d_RX_MPDU_START_2_PN_47_32_LSB; + u_int32_t d_RX_MPDU_START_2_PN_47_32_MASK; + u_int32_t d_RX_MPDU_START_2_TID_LSB; + u_int32_t d_RX_MPDU_START_2_TID_MASK; + u_int32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK; + u_int32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB; + u_int32_t d_RX_MSDU_END_1_KEY_ID_OCT_MASK; + u_int32_t d_RX_MSDU_END_1_KEY_ID_OCT_LSB; + u_int32_t d_RX_MSDU_END_4_LAST_MSDU_MASK; + u_int32_t d_RX_MSDU_END_4_LAST_MSDU_LSB; + u_int32_t d_RX_ATTENTION_0_MCAST_BCAST_MASK; + u_int32_t d_RX_ATTENTION_0_MCAST_BCAST_LSB; + u_int32_t d_RX_ATTENTION_0_FRAGMENT_MASK; + u_int32_t d_RX_ATTENTION_0_FRAGMENT_LSB; + u_int32_t d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK; + u_int32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK; + u_int32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB; + u_int32_t d_RX_MSDU_START_0_MSDU_LENGTH_MASK; + u_int32_t d_RX_MSDU_START_0_MSDU_LENGTH_LSB; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_MASK; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_LSB; + u_int32_t d_RX_MPDU_START_0_ENCRYPTED_MASK; + u_int32_t d_RX_MPDU_START_0_ENCRYPTED_LSB; + u_int32_t d_RX_ATTENTION_0_MORE_DATA_MASK; + u_int32_t d_RX_ATTENTION_0_MSDU_DONE_MASK; + u_int32_t d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK; + /* end */ + /* copy_engine.c */ + u_int32_t d_DST_WR_INDEX_ADDRESS; + u_int32_t d_SRC_WATERMARK_ADDRESS; + u_int32_t d_SRC_WATERMARK_LOW_MASK; + u_int32_t d_SRC_WATERMARK_HIGH_MASK; + u_int32_t d_DST_WATERMARK_LOW_MASK; + u_int32_t d_DST_WATERMARK_HIGH_MASK; + u_int32_t d_CURRENT_SRRI_ADDRESS; + u_int32_t d_CURRENT_DRRI_ADDRESS; + u_int32_t d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK; + u_int32_t d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK; + u_int32_t d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK; + u_int32_t d_HOST_IS_DST_RING_LOW_WATERMARK_MASK; + u_int32_t d_HOST_IS_ADDRESS; + u_int32_t d_HOST_IS_COPY_COMPLETE_MASK; + u_int32_t d_CE_WRAPPER_BASE_ADDRESS; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS; + u_int32_t d_HOST_IE_ADDRESS; + u_int32_t d_HOST_IE_COPY_COMPLETE_MASK; + u_int32_t d_SR_BA_ADDRESS; + u_int32_t d_SR_SIZE_ADDRESS; + u_int32_t d_CE_CTRL1_ADDRESS; + u_int32_t d_CE_CTRL1_DMAX_LENGTH_MASK; + u_int32_t d_DR_BA_ADDRESS; + u_int32_t d_DR_SIZE_ADDRESS; + u_int32_t d_MISC_IE_ADDRESS; + u_int32_t d_MISC_IS_AXI_ERR_MASK; + u_int32_t d_MISC_IS_DST_ADDR_ERR_MASK; + u_int32_t d_MISC_IS_SRC_LEN_ERR_MASK; + u_int32_t d_MISC_IS_DST_MAX_LEN_VIO_MASK; + u_int32_t d_MISC_IS_DST_RING_OVERFLOW_MASK; + u_int32_t d_MISC_IS_SRC_RING_OVERFLOW_MASK; + u_int32_t d_SRC_WATERMARK_LOW_LSB; + u_int32_t d_SRC_WATERMARK_HIGH_LSB; + u_int32_t d_DST_WATERMARK_LOW_LSB; + u_int32_t d_DST_WATERMARK_HIGH_LSB; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB; + u_int32_t d_CE_CTRL1_DMAX_LENGTH_LSB; + u_int32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK; + u_int32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK; + u_int32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB; + u_int32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_OFFSET; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_SRC_MSB; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_SRC_LSB; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_SRC_MASK; + u_int32_t d_WLAN_DEBUG_CONTROL_OFFSET; + u_int32_t d_WLAN_DEBUG_CONTROL_ENABLE_MSB; + u_int32_t d_WLAN_DEBUG_CONTROL_ENABLE_LSB; + u_int32_t d_WLAN_DEBUG_CONTROL_ENABLE_MASK; + u_int32_t d_WLAN_DEBUG_OUT_OFFSET; + u_int32_t d_WLAN_DEBUG_OUT_DATA_MSB; + u_int32_t d_WLAN_DEBUG_OUT_DATA_LSB; + u_int32_t d_WLAN_DEBUG_OUT_DATA_MASK; + u_int32_t d_AMBA_DEBUG_BUS_OFFSET; + u_int32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB; + u_int32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB; + u_int32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK; + u_int32_t d_AMBA_DEBUG_BUS_SEL_MSB; + u_int32_t d_AMBA_DEBUG_BUS_SEL_LSB; + u_int32_t d_AMBA_DEBUG_BUS_SEL_MASK; + u_int32_t d_CE_WRAPPER_DEBUG_OFFSET; + u_int32_t d_CE_WRAPPER_DEBUG_SEL_MSB; + u_int32_t d_CE_WRAPPER_DEBUG_SEL_LSB; + u_int32_t d_CE_WRAPPER_DEBUG_SEL_MASK; + u_int32_t d_CE_DEBUG_OFFSET; + u_int32_t d_CE_DEBUG_SEL_MSB; + u_int32_t d_CE_DEBUG_SEL_LSB; + u_int32_t d_CE_DEBUG_SEL_MASK; + /* end */ + /* PLL start */ + u_int32_t d_EFUSE_OFFSET; + u_int32_t d_EFUSE_XTAL_SEL_MSB; + u_int32_t d_EFUSE_XTAL_SEL_LSB; + u_int32_t d_EFUSE_XTAL_SEL_MASK; + u_int32_t d_BB_PLL_CONFIG_OFFSET; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_MSB; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_LSB; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_MASK; + u_int32_t d_BB_PLL_CONFIG_FRAC_MSB; + u_int32_t d_BB_PLL_CONFIG_FRAC_LSB; + u_int32_t d_BB_PLL_CONFIG_FRAC_MASK; + u_int32_t d_WLAN_PLL_SETTLE_TIME_MSB; + u_int32_t d_WLAN_PLL_SETTLE_TIME_LSB; + u_int32_t d_WLAN_PLL_SETTLE_TIME_MASK; + u_int32_t d_WLAN_PLL_SETTLE_OFFSET; + u_int32_t d_WLAN_PLL_SETTLE_SW_MASK; + u_int32_t d_WLAN_PLL_SETTLE_RSTMASK; + u_int32_t d_WLAN_PLL_SETTLE_RESET; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_MSB; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_LSB; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_MASK; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_MSB; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_LSB; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_MASK; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_RESET; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_MSB; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_LSB; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_MASK; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_RESET; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_MSB; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_LSB; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_MASK; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_RESET; + u_int32_t d_WLAN_PLL_CONTROL_DIV_MSB; + u_int32_t d_WLAN_PLL_CONTROL_DIV_LSB; + u_int32_t d_WLAN_PLL_CONTROL_DIV_MASK; + u_int32_t d_WLAN_PLL_CONTROL_DIV_RESET; + u_int32_t d_WLAN_PLL_CONTROL_OFFSET; + u_int32_t d_WLAN_PLL_CONTROL_SW_MASK; + u_int32_t d_WLAN_PLL_CONTROL_RSTMASK; + u_int32_t d_WLAN_PLL_CONTROL_RESET; + u_int32_t d_SOC_CORE_CLK_CTRL_OFFSET; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_MSB; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_LSB; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_MASK; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MSB; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_LSB; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MASK; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_RESET; + u_int32_t d_RTC_SYNC_STATUS_OFFSET; + u_int32_t d_SOC_CPU_CLOCK_OFFSET; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_MSB; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_LSB; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_MASK; + /* PLL end */ + u_int32_t d_SOC_POWER_REG_OFFSET; + u_int32_t d_PCIE_INTR_CAUSE_ADDRESS; + u_int32_t d_SOC_RESET_CONTROL_ADDRESS; + u_int32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK; + u_int32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB; + u_int32_t d_SOC_RESET_CONTROL_CE_RST_MASK; + u_int32_t d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK; + u_int32_t d_CPU_INTR_ADDRESS; + u_int32_t d_SOC_LF_TIMER_CONTROL0_ADDRESS; + u_int32_t d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK; + /* chip id start */ + u_int32_t d_SOC_CHIP_ID_ADDRESS; + u_int32_t d_SOC_CHIP_ID_VERSION_MASK; + u_int32_t d_SOC_CHIP_ID_VERSION_LSB; + u_int32_t d_SOC_CHIP_ID_REVISION_MASK; + u_int32_t d_SOC_CHIP_ID_REVISION_LSB; + /* chip id end */ +} TARGET_REGISTER_TABLE; + +#define RTC_SOC_BASE_ADDRESS (sc->targetdef->d_RTC_SOC_BASE_ADDRESS) +#define RTC_WMAC_BASE_ADDRESS (sc->targetdef->d_RTC_WMAC_BASE_ADDRESS) +#define SYSTEM_SLEEP_OFFSET (sc->targetdef->d_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_OFFSET (sc->targetdef->d_WLAN_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB (sc->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK (sc->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define CLOCK_CONTROL_OFFSET (sc->targetdef->d_CLOCK_CONTROL_OFFSET) +#define CLOCK_CONTROL_SI0_CLK_MASK (sc->targetdef->d_CLOCK_CONTROL_SI0_CLK_MASK) +#define RESET_CONTROL_OFFSET (sc->targetdef->d_RESET_CONTROL_OFFSET) +#define RESET_CONTROL_MBOX_RST_MASK (sc->targetdef->d_RESET_CONTROL_MBOX_RST_MASK) +#define RESET_CONTROL_SI0_RST_MASK (sc->targetdef->d_RESET_CONTROL_SI0_RST_MASK) +#define WLAN_RESET_CONTROL_OFFSET (sc->targetdef->d_WLAN_RESET_CONTROL_OFFSET) +#define WLAN_RESET_CONTROL_COLD_RST_MASK (sc->targetdef->d_WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MASK (sc->targetdef->d_WLAN_RESET_CONTROL_WARM_RST_MASK) +#define GPIO_BASE_ADDRESS (sc->targetdef->d_GPIO_BASE_ADDRESS) +#define GPIO_PIN0_OFFSET (sc->targetdef->d_GPIO_PIN0_OFFSET) +#define GPIO_PIN1_OFFSET (sc->targetdef->d_GPIO_PIN1_OFFSET) +#define GPIO_PIN0_CONFIG_MASK (sc->targetdef->d_GPIO_PIN0_CONFIG_MASK) +#define GPIO_PIN1_CONFIG_MASK (sc->targetdef->d_GPIO_PIN1_CONFIG_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_LSB (sc->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_LSB) +#define SI_CONFIG_BIDIR_OD_DATA_MASK (sc->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_LSB (sc->targetdef->d_SI_CONFIG_I2C_LSB) +#define SI_CONFIG_I2C_MASK (sc->targetdef->d_SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_LSB (sc->targetdef->d_SI_CONFIG_POS_SAMPLE_LSB) +#define SI_CONFIG_POS_SAMPLE_MASK (sc->targetdef->d_SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_LSB (sc->targetdef->d_SI_CONFIG_INACTIVE_CLK_LSB) +#define SI_CONFIG_INACTIVE_CLK_MASK (sc->targetdef->d_SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_LSB (sc->targetdef->d_SI_CONFIG_INACTIVE_DATA_LSB) +#define SI_CONFIG_INACTIVE_DATA_MASK (sc->targetdef->d_SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_LSB (sc->targetdef->d_SI_CONFIG_DIVIDER_LSB) +#define SI_CONFIG_DIVIDER_MASK (sc->targetdef->d_SI_CONFIG_DIVIDER_MASK) +#define SI_BASE_ADDRESS (sc->targetdef->d_SI_BASE_ADDRESS) +#define SI_CONFIG_OFFSET (sc->targetdef->d_SI_CONFIG_OFFSET) +#define SI_TX_DATA0_OFFSET (sc->targetdef->d_SI_TX_DATA0_OFFSET) +#define SI_TX_DATA1_OFFSET (sc->targetdef->d_SI_TX_DATA1_OFFSET) +#define SI_RX_DATA0_OFFSET (sc->targetdef->d_SI_RX_DATA0_OFFSET) +#define SI_RX_DATA1_OFFSET (sc->targetdef->d_SI_RX_DATA1_OFFSET) +#define SI_CS_OFFSET (sc->targetdef->d_SI_CS_OFFSET) +#define SI_CS_DONE_ERR_MASK (sc->targetdef->d_SI_CS_DONE_ERR_MASK) +#define SI_CS_DONE_INT_MASK (sc->targetdef->d_SI_CS_DONE_INT_MASK) +#define SI_CS_START_LSB (sc->targetdef->d_SI_CS_START_LSB) +#define SI_CS_START_MASK (sc->targetdef->d_SI_CS_START_MASK) +#define SI_CS_RX_CNT_LSB (sc->targetdef->d_SI_CS_RX_CNT_LSB) +#define SI_CS_RX_CNT_MASK (sc->targetdef->d_SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_LSB (sc->targetdef->d_SI_CS_TX_CNT_LSB) +#define SI_CS_TX_CNT_MASK (sc->targetdef->d_SI_CS_TX_CNT_MASK) +#define EEPROM_SZ (sc->targetdef->d_BOARD_DATA_SZ) +#define EEPROM_EXT_SZ (sc->targetdef->d_BOARD_EXT_DATA_SZ) +#define MBOX_BASE_ADDRESS (sc->targetdef->d_MBOX_BASE_ADDRESS) +#define LOCAL_SCRATCH_OFFSET (sc->targetdef->d_LOCAL_SCRATCH_OFFSET) +#define CPU_CLOCK_OFFSET (sc->targetdef->d_CPU_CLOCK_OFFSET) +#define LPO_CAL_OFFSET (sc->targetdef->d_LPO_CAL_OFFSET) +#define GPIO_PIN10_OFFSET (sc->targetdef->d_GPIO_PIN10_OFFSET) +#define GPIO_PIN11_OFFSET (sc->targetdef->d_GPIO_PIN11_OFFSET) +#define GPIO_PIN12_OFFSET (sc->targetdef->d_GPIO_PIN12_OFFSET) +#define GPIO_PIN13_OFFSET (sc->targetdef->d_GPIO_PIN13_OFFSET) +#define CLOCK_GPIO_OFFSET (sc->targetdef->d_CLOCK_GPIO_OFFSET) +#define CPU_CLOCK_STANDARD_LSB (sc->targetdef->d_CPU_CLOCK_STANDARD_LSB) +#define CPU_CLOCK_STANDARD_MASK (sc->targetdef->d_CPU_CLOCK_STANDARD_MASK) +#define LPO_CAL_ENABLE_LSB (sc->targetdef->d_LPO_CAL_ENABLE_LSB) +#define LPO_CAL_ENABLE_MASK (sc->targetdef->d_LPO_CAL_ENABLE_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB (sc->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB) +#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK (sc->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +#define ANALOG_INTF_BASE_ADDRESS (sc->targetdef->d_ANALOG_INTF_BASE_ADDRESS) +#define WLAN_MAC_BASE_ADDRESS (sc->targetdef->d_WLAN_MAC_BASE_ADDRESS) +#define CE0_BASE_ADDRESS (sc->targetdef->d_CE0_BASE_ADDRESS) +#define CE1_BASE_ADDRESS (sc->targetdef->d_CE1_BASE_ADDRESS) +#define FW_INDICATOR_ADDRESS (sc->targetdef->d_FW_INDICATOR_ADDRESS) +#define DRAM_BASE_ADDRESS (sc->targetdef->d_DRAM_BASE_ADDRESS) +#define SOC_CORE_BASE_ADDRESS (sc->targetdef->d_SOC_CORE_BASE_ADDRESS) +#define CORE_CTRL_ADDRESS (sc->targetdef->d_CORE_CTRL_ADDRESS) +#define CE_COUNT (sc->targetdef->d_CE_COUNT) +#define PCIE_INTR_ENABLE_ADDRESS (sc->targetdef->d_PCIE_INTR_ENABLE_ADDRESS) +#define PCIE_INTR_CLR_ADDRESS (sc->targetdef->d_PCIE_INTR_CLR_ADDRESS) +#define PCIE_INTR_FIRMWARE_MASK (sc->targetdef->d_PCIE_INTR_FIRMWARE_MASK) +#define PCIE_INTR_CE_MASK_ALL (sc->targetdef->d_PCIE_INTR_CE_MASK_ALL) +#define FW_RAM_CONFIG_ADDRESS (sc->targetdef->d_FW_RAM_CONFIG_ADDRESS) +#define CORE_CTRL_CPU_INTR_MASK (sc->targetdef->d_CORE_CTRL_CPU_INTR_MASK) +#define PCIE_INTR_CAUSE_ADDRESS (sc->targetdef->d_PCIE_INTR_CAUSE_ADDRESS) +#define SOC_RESET_CONTROL_ADDRESS (sc->targetdef->d_SOC_RESET_CONTROL_ADDRESS) +#define SOC_RESET_CONTROL_CE_RST_MASK (sc->targetdef->d_SOC_RESET_CONTROL_CE_RST_MASK) +#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK (sc->targetdef->d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK) +#define CPU_INTR_ADDRESS (sc->targetdef->d_CPU_INTR_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ADDRESS (sc->targetdef->d_SOC_LF_TIMER_CONTROL0_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK (sc->targetdef->d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB (sc->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK (sc->targetdef ->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_GET(x) (((x) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) >> SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_SET(x) (((x) << SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +/* hif_pci.c */ +#define CHIP_ID_ADDRESS (sc->targetdef->d_SOC_CHIP_ID_ADDRESS) +#define SOC_CHIP_ID_REVISION_MASK (sc->targetdef->d_SOC_CHIP_ID_REVISION_MASK) +#define SOC_CHIP_ID_REVISION_LSB (sc->targetdef->d_SOC_CHIP_ID_REVISION_LSB) +#define SOC_CHIP_ID_VERSION_MASK (sc->targetdef->d_SOC_CHIP_ID_VERSION_MASK) +#define SOC_CHIP_ID_VERSION_LSB (sc->targetdef->d_SOC_CHIP_ID_VERSION_LSB) +#define CHIP_ID_REVISION_GET(x) (((x) & SOC_CHIP_ID_REVISION_MASK) >> SOC_CHIP_ID_REVISION_LSB) +#define CHIP_ID_VERSION_GET(x) (((x) & SOC_CHIP_ID_VERSION_MASK) >> SOC_CHIP_ID_VERSION_LSB) +/* hif_pci.c end */ + +/* misc */ +#define SR_WR_INDEX_ADDRESS (sc->targetdef->d_SR_WR_INDEX_ADDRESS) +#define DST_WATERMARK_ADDRESS (sc->targetdef->d_DST_WATERMARK_ADDRESS) +#define SOC_POWER_REG_OFFSET (sc->targetdef->d_SOC_POWER_REG_OFFSET) +/* end */ + +/* htt_rx.c */ +#define RX_MSDU_END_4_FIRST_MSDU_MASK (pdev->targetdef->d_RX_MSDU_END_4_FIRST_MSDU_MASK) +#define RX_MSDU_END_4_FIRST_MSDU_LSB (pdev->targetdef->d_RX_MSDU_END_4_FIRST_MSDU_LSB) +#define RX_MPDU_START_0_RETRY_LSB (pdev->targetdef->d_RX_MPDU_START_0_RETRY_LSB) +#define RX_MPDU_START_0_RETRY_MASK (pdev->targetdef->d_RX_MPDU_START_0_RETRY_MASK) +#define RX_MPDU_START_0_SEQ_NUM_MASK (pdev->targetdef->d_RX_MPDU_START_0_SEQ_NUM_MASK) +#define RX_MPDU_START_0_SEQ_NUM_LSB (pdev->targetdef->d_RX_MPDU_START_0_SEQ_NUM_LSB) +#define RX_MPDU_START_2_PN_47_32_LSB (pdev->targetdef->d_RX_MPDU_START_2_PN_47_32_LSB) +#define RX_MPDU_START_2_PN_47_32_MASK (pdev->targetdef->d_RX_MPDU_START_2_PN_47_32_MASK) +#define RX_MPDU_START_2_TID_LSB (pdev->targetdef->d_RX_MPDU_START_2_TID_LSB) +#define RX_MPDU_START_2_TID_MASK (pdev->targetdef->d_RX_MPDU_START_2_TID_MASK) +#define RX_MSDU_END_1_KEY_ID_OCT_MASK (pdev->targetdef->d_RX_MSDU_END_1_KEY_ID_OCT_MASK) +#define RX_MSDU_END_1_KEY_ID_OCT_LSB (pdev->targetdef->d_RX_MSDU_END_1_KEY_ID_OCT_LSB) +#define RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK (pdev->targetdef->d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK) +#define RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB (pdev->targetdef->d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB) +#define RX_MSDU_END_4_LAST_MSDU_MASK (pdev->targetdef->d_RX_MSDU_END_4_LAST_MSDU_MASK) +#define RX_MSDU_END_4_LAST_MSDU_LSB (pdev->targetdef->d_RX_MSDU_END_4_LAST_MSDU_LSB) +#define RX_ATTENTION_0_MCAST_BCAST_MASK (pdev->targetdef->d_RX_ATTENTION_0_MCAST_BCAST_MASK) +#define RX_ATTENTION_0_MCAST_BCAST_LSB (pdev->targetdef->d_RX_ATTENTION_0_MCAST_BCAST_LSB) +#define RX_ATTENTION_0_FRAGMENT_MASK (pdev->targetdef->d_RX_ATTENTION_0_FRAGMENT_MASK) +#define RX_ATTENTION_0_FRAGMENT_LSB (pdev->targetdef->d_RX_ATTENTION_0_FRAGMENT_LSB) +#define RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK (pdev->targetdef->d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK) +#define RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK (pdev->targetdef->d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK) +#define RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB (pdev->targetdef->d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB) +#define RX_MSDU_START_0_MSDU_LENGTH_MASK (pdev->targetdef->d_RX_MSDU_START_0_MSDU_LENGTH_MASK) +#define RX_MSDU_START_0_MSDU_LENGTH_LSB (pdev->targetdef->d_RX_MSDU_START_0_MSDU_LENGTH_LSB) +#define RX_MSDU_START_2_DECAP_FORMAT_OFFSET (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET) +#define RX_MSDU_START_2_DECAP_FORMAT_MASK (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_MASK) +#define RX_MSDU_START_2_DECAP_FORMAT_LSB (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_LSB) +#define RX_MPDU_START_0_ENCRYPTED_MASK (pdev->targetdef->d_RX_MPDU_START_0_ENCRYPTED_MASK) +#define RX_MPDU_START_0_ENCRYPTED_LSB (pdev->targetdef->d_RX_MPDU_START_0_ENCRYPTED_LSB) +#define RX_ATTENTION_0_MORE_DATA_MASK (pdev->targetdef->d_RX_ATTENTION_0_MORE_DATA_MASK) +#define RX_ATTENTION_0_MSDU_DONE_MASK (pdev->targetdef->d_RX_ATTENTION_0_MSDU_DONE_MASK) +#define RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK (pdev->targetdef->d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK) +/* end */ + +/* copy_engine.c */ +#define DST_WR_INDEX_ADDRESS (sc->targetdef->d_DST_WR_INDEX_ADDRESS) +#define SRC_WATERMARK_ADDRESS (sc->targetdef->d_SRC_WATERMARK_ADDRESS) +#define SRC_WATERMARK_LOW_MASK (sc->targetdef->d_SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_MASK (sc->targetdef->d_SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_MASK (sc->targetdef->d_DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_MASK (sc->targetdef->d_DST_WATERMARK_HIGH_MASK) +#define CURRENT_SRRI_ADDRESS (sc->targetdef->d_CURRENT_SRRI_ADDRESS) +#define CURRENT_DRRI_ADDRESS (sc->targetdef->d_CURRENT_DRRI_ADDRESS) +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK (sc->targetdef->d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK (sc->targetdef->d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK) +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK (sc->targetdef->d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK (sc->targetdef->d_HOST_IS_DST_RING_LOW_WATERMARK_MASK) +#define HOST_IS_ADDRESS (sc->targetdef->d_HOST_IS_ADDRESS) +#define HOST_IS_COPY_COMPLETE_MASK (sc->targetdef->d_HOST_IS_COPY_COMPLETE_MASK) +#define CE_WRAPPER_BASE_ADDRESS (sc->targetdef->d_CE_WRAPPER_BASE_ADDRESS) +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS) +#define HOST_IE_ADDRESS (sc->targetdef->d_HOST_IE_ADDRESS) +#define HOST_IE_COPY_COMPLETE_MASK (sc->targetdef->d_HOST_IE_COPY_COMPLETE_MASK) +#define SR_BA_ADDRESS (sc->targetdef->d_SR_BA_ADDRESS) +#define SR_SIZE_ADDRESS (sc->targetdef->d_SR_SIZE_ADDRESS) +#define CE_CTRL1_ADDRESS (sc->targetdef->d_CE_CTRL1_ADDRESS) +#define CE_CTRL1_DMAX_LENGTH_MASK (sc->targetdef->d_CE_CTRL1_DMAX_LENGTH_MASK) +#define DR_BA_ADDRESS (sc->targetdef->d_DR_BA_ADDRESS) +#define DR_SIZE_ADDRESS (sc->targetdef->d_DR_SIZE_ADDRESS) +#define MISC_IE_ADDRESS (sc->targetdef->d_MISC_IE_ADDRESS) +#define MISC_IS_AXI_ERR_MASK (sc->targetdef->d_MISC_IS_AXI_ERR_MASK) +#define MISC_IS_DST_ADDR_ERR_MASK (sc->targetdef->d_MISC_IS_DST_ADDR_ERR_MASK) +#define MISC_IS_SRC_LEN_ERR_MASK (sc->targetdef->d_MISC_IS_SRC_LEN_ERR_MASK) +#define MISC_IS_DST_MAX_LEN_VIO_MASK (sc->targetdef->d_MISC_IS_DST_MAX_LEN_VIO_MASK) +#define MISC_IS_DST_RING_OVERFLOW_MASK (sc->targetdef->d_MISC_IS_DST_RING_OVERFLOW_MASK) +#define MISC_IS_SRC_RING_OVERFLOW_MASK (sc->targetdef->d_MISC_IS_SRC_RING_OVERFLOW_MASK) +#define SRC_WATERMARK_LOW_LSB (sc->targetdef->d_SRC_WATERMARK_LOW_LSB) +#define SRC_WATERMARK_HIGH_LSB (sc->targetdef->d_SRC_WATERMARK_HIGH_LSB) +#define DST_WATERMARK_LOW_LSB (sc->targetdef->d_DST_WATERMARK_LOW_LSB) +#define DST_WATERMARK_HIGH_LSB (sc->targetdef->d_DST_WATERMARK_HIGH_LSB) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_LSB (sc->targetdef->d_CE_CTRL1_DMAX_LENGTH_LSB) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK (sc->targetdef->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK (sc->targetdef->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB (sc->targetdef->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB (sc->targetdef->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) +#define WLAN_DEBUG_INPUT_SEL_OFFSET (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_OFFSET) +#define WLAN_DEBUG_INPUT_SEL_SRC_MSB (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_MSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_LSB (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_LSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_MASK (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_MASK) +#define WLAN_DEBUG_CONTROL_OFFSET (sc->targetdef->d_WLAN_DEBUG_CONTROL_OFFSET) +#define WLAN_DEBUG_CONTROL_ENABLE_MSB (sc->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_MSB) +#define WLAN_DEBUG_CONTROL_ENABLE_LSB (sc->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_LSB) +#define WLAN_DEBUG_CONTROL_ENABLE_MASK (sc->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_MASK) +#define WLAN_DEBUG_OUT_OFFSET (sc->targetdef->d_WLAN_DEBUG_OUT_OFFSET) +#define WLAN_DEBUG_OUT_DATA_MSB (sc->targetdef->d_WLAN_DEBUG_OUT_DATA_MSB) +#define WLAN_DEBUG_OUT_DATA_LSB (sc->targetdef->d_WLAN_DEBUG_OUT_DATA_LSB) +#define WLAN_DEBUG_OUT_DATA_MASK (sc->targetdef->d_WLAN_DEBUG_OUT_DATA_MASK) +#define AMBA_DEBUG_BUS_OFFSET (sc->targetdef->d_AMBA_DEBUG_BUS_OFFSET) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB (sc->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB (sc->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK (sc->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) +#define AMBA_DEBUG_BUS_SEL_MSB (sc->targetdef->d_AMBA_DEBUG_BUS_SEL_MSB) +#define AMBA_DEBUG_BUS_SEL_LSB (sc->targetdef->d_AMBA_DEBUG_BUS_SEL_LSB) +#define AMBA_DEBUG_BUS_SEL_MASK (sc->targetdef->d_AMBA_DEBUG_BUS_SEL_MASK) +#define CE_WRAPPER_DEBUG_OFFSET (sc->targetdef->d_CE_WRAPPER_DEBUG_OFFSET) +#define CE_WRAPPER_DEBUG_SEL_MSB (sc->targetdef->d_CE_WRAPPER_DEBUG_SEL_MSB) +#define CE_WRAPPER_DEBUG_SEL_LSB (sc->targetdef->d_CE_WRAPPER_DEBUG_SEL_LSB) +#define CE_WRAPPER_DEBUG_SEL_MASK (sc->targetdef->d_CE_WRAPPER_DEBUG_SEL_MASK) +#define CE_DEBUG_OFFSET (sc->targetdef->d_CE_DEBUG_OFFSET) +#define CE_DEBUG_SEL_MSB (sc->targetdef->d_CE_DEBUG_SEL_MSB) +#define CE_DEBUG_SEL_LSB (sc->targetdef->d_CE_DEBUG_SEL_LSB) +#define CE_DEBUG_SEL_MASK (sc->targetdef->d_CE_DEBUG_SEL_MASK) +/* end */ +/* PLL start */ +#define EFUSE_OFFSET (sc->targetdef->d_EFUSE_OFFSET) +#define EFUSE_XTAL_SEL_MSB (sc->targetdef->d_EFUSE_XTAL_SEL_MSB) +#define EFUSE_XTAL_SEL_LSB (sc->targetdef->d_EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_MASK (sc->targetdef->d_EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OFFSET (sc->targetdef->d_BB_PLL_CONFIG_OFFSET) +#define BB_PLL_CONFIG_OUTDIV_MSB (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_MSB) +#define BB_PLL_CONFIG_OUTDIV_LSB (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_MASK (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_MSB (sc->targetdef->d_BB_PLL_CONFIG_FRAC_MSB) +#define BB_PLL_CONFIG_FRAC_LSB (sc->targetdef->d_BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_MASK (sc->targetdef->d_BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_MSB (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_MSB) +#define WLAN_PLL_SETTLE_TIME_LSB (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_MASK (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_SETTLE_OFFSET (sc->targetdef->d_WLAN_PLL_SETTLE_OFFSET) +#define WLAN_PLL_SETTLE_SW_MASK (sc->targetdef->d_WLAN_PLL_SETTLE_SW_MASK) +#define WLAN_PLL_SETTLE_RSTMASK (sc->targetdef->d_WLAN_PLL_SETTLE_RSTMASK) +#define WLAN_PLL_SETTLE_RESET (sc->targetdef->d_WLAN_PLL_SETTLE_RESET) +#define WLAN_PLL_CONTROL_NOPWD_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MSB) +#define WLAN_PLL_CONTROL_NOPWD_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MSB) +#define WLAN_PLL_CONTROL_BYPASS_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_BYPASS_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_RESET) +#define WLAN_PLL_CONTROL_CLK_SEL_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MSB) +#define WLAN_PLL_CONTROL_CLK_SEL_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_RESET) +#define WLAN_PLL_CONTROL_REFDIV_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MSB) +#define WLAN_PLL_CONTROL_REFDIV_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_REFDIV_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_RESET) +#define WLAN_PLL_CONTROL_DIV_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_MSB) +#define WLAN_PLL_CONTROL_DIV_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_MASK) +#define WLAN_PLL_CONTROL_DIV_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_RESET) +#define WLAN_PLL_CONTROL_OFFSET (sc->targetdef->d_WLAN_PLL_CONTROL_OFFSET) +#define WLAN_PLL_CONTROL_SW_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_SW_MASK) +#define WLAN_PLL_CONTROL_RSTMASK (sc->targetdef->d_WLAN_PLL_CONTROL_RSTMASK) +#define WLAN_PLL_CONTROL_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_RESET) +#define SOC_CORE_CLK_CTRL_OFFSET (sc->targetdef->d_SOC_CORE_CLK_CTRL_OFFSET) +#define SOC_CORE_CLK_CTRL_DIV_MSB (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MSB) +#define SOC_CORE_CLK_CTRL_DIV_LSB (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_MASK (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_MSB (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_LSB (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_MASK (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_RESET (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_RESET) +#define RTC_SYNC_STATUS_OFFSET (sc->targetdef->d_RTC_SYNC_STATUS_OFFSET) +#define SOC_CPU_CLOCK_OFFSET (sc->targetdef->d_SOC_CPU_CLOCK_OFFSET) +#define SOC_CPU_CLOCK_STANDARD_MSB (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_MSB) +#define SOC_CPU_CLOCK_STANDARD_LSB (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_MASK (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +/* SET macros */ +#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_SET(x) (((x) << SI_CONFIG_BIDIR_OD_DATA_LSB) & SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_SET(x) (((x) << SI_CONFIG_I2C_LSB) & SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_SET(x) (((x) << SI_CONFIG_POS_SAMPLE_LSB) & SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_SET(x) (((x) << SI_CONFIG_INACTIVE_CLK_LSB) & SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_SET(x) (((x) << SI_CONFIG_INACTIVE_DATA_LSB) & SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_SET(x) (((x) << SI_CONFIG_DIVIDER_LSB) & SI_CONFIG_DIVIDER_MASK) +#define SI_CS_START_SET(x) (((x) << SI_CS_START_LSB) & SI_CS_START_MASK) +#define SI_CS_RX_CNT_SET(x) (((x) << SI_CS_RX_CNT_LSB) & SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_SET(x) (((x) << SI_CS_TX_CNT_LSB) & SI_CS_TX_CNT_MASK) +#define LPO_CAL_ENABLE_SET(x) (((x) << LPO_CAL_ENABLE_LSB) & LPO_CAL_ENABLE_MASK) +#define CPU_CLOCK_STANDARD_SET(x) (((x) << CPU_CLOCK_STANDARD_LSB) & CPU_CLOCK_STANDARD_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_SET(x) (((x) << CLOCK_GPIO_BT_CLK_OUT_EN_LSB) & CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +/* copy_engine.c */ +#define SRC_WATERMARK_LOW_SET(x) (((x) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_SET(x) (((x) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_SET(x) (((x) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_SET(x) (((x) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_SET(x) (((x) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) (((x) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) (((x) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +#define WLAN_DEBUG_INPUT_SEL_SRC_GET(x) (((x) & WLAN_DEBUG_INPUT_SEL_SRC_MASK) >> WLAN_DEBUG_INPUT_SEL_SRC_LSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_SET(x) (((x) << WLAN_DEBUG_INPUT_SEL_SRC_LSB) & WLAN_DEBUG_INPUT_SEL_SRC_MASK) +#define WLAN_DEBUG_CONTROL_ENABLE_GET(x) (((x) & WLAN_DEBUG_CONTROL_ENABLE_MASK) >> WLAN_DEBUG_CONTROL_ENABLE_LSB) +#define WLAN_DEBUG_CONTROL_ENABLE_SET(x) (((x) << WLAN_DEBUG_CONTROL_ENABLE_LSB) & WLAN_DEBUG_CONTROL_ENABLE_MASK) +#define WLAN_DEBUG_OUT_DATA_GET(x) (((x) & WLAN_DEBUG_OUT_DATA_MASK) >> WLAN_DEBUG_OUT_DATA_LSB) +#define WLAN_DEBUG_OUT_DATA_SET(x) (((x) << WLAN_DEBUG_OUT_DATA_LSB) & WLAN_DEBUG_OUT_DATA_MASK) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_GET(x) (((x) & AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) >> AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_SET(x) (((x) << AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) & AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) +#define AMBA_DEBUG_BUS_SEL_GET(x) (((x) & AMBA_DEBUG_BUS_SEL_MASK) >> AMBA_DEBUG_BUS_SEL_LSB) +#define AMBA_DEBUG_BUS_SEL_SET(x) (((x) << AMBA_DEBUG_BUS_SEL_LSB) & AMBA_DEBUG_BUS_SEL_MASK) +#define CE_WRAPPER_DEBUG_SEL_GET(x) (((x) & CE_WRAPPER_DEBUG_SEL_MASK) >> CE_WRAPPER_DEBUG_SEL_LSB) +#define CE_WRAPPER_DEBUG_SEL_SET(x) (((x) << CE_WRAPPER_DEBUG_SEL_LSB) & CE_WRAPPER_DEBUG_SEL_MASK) +#define CE_DEBUG_SEL_GET(x) (((x) & CE_DEBUG_SEL_MASK) >> CE_DEBUG_SEL_LSB) +#define CE_DEBUG_SEL_SET(x) (((x) << CE_DEBUG_SEL_LSB) & CE_DEBUG_SEL_MASK) +/* end */ +/* PLL start */ +#define EFUSE_XTAL_SEL_GET(x) (((x) & EFUSE_XTAL_SEL_MASK) >> EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_SET(x) (((x) << EFUSE_XTAL_SEL_LSB) & EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OUTDIV_GET(x) (((x) & BB_PLL_CONFIG_OUTDIV_MASK) >> BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_SET(x) (((x) << BB_PLL_CONFIG_OUTDIV_LSB) & BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_GET(x) (((x) & BB_PLL_CONFIG_FRAC_MASK) >> BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_SET(x) (((x) << BB_PLL_CONFIG_FRAC_LSB) & BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_GET(x) (((x) & WLAN_PLL_SETTLE_TIME_MASK) >> WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_SET(x) (((x) << WLAN_PLL_SETTLE_TIME_LSB) & WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_CONTROL_NOPWD_GET(x) (((x) & WLAN_PLL_CONTROL_NOPWD_MASK) >> WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_SET(x) (((x) << WLAN_PLL_CONTROL_NOPWD_LSB) & WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_GET(x) (((x) & WLAN_PLL_CONTROL_BYPASS_MASK) >> WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_SET(x) (((x) << WLAN_PLL_CONTROL_BYPASS_LSB) & WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_GET(x) (((x) & WLAN_PLL_CONTROL_CLK_SEL_MASK) >> WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_SET(x) (((x) << WLAN_PLL_CONTROL_CLK_SEL_LSB) & WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_REFDIV_GET(x) (((x) & WLAN_PLL_CONTROL_REFDIV_MASK) >> WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_SET(x) (((x) << WLAN_PLL_CONTROL_REFDIV_LSB) & WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_DIV_GET(x) (((x) & WLAN_PLL_CONTROL_DIV_MASK) >> WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_SET(x) (((x) << WLAN_PLL_CONTROL_DIV_LSB) & WLAN_PLL_CONTROL_DIV_MASK) +#define SOC_CORE_CLK_CTRL_DIV_GET(x) (((x) & SOC_CORE_CLK_CTRL_DIV_MASK) >> SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_SET(x) (((x) << SOC_CORE_CLK_CTRL_DIV_LSB) & SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_GET(x) (((x) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) >> RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_SET(x) (((x) << RTC_SYNC_STATUS_PLL_CHANGING_LSB) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define SOC_CPU_CLOCK_STANDARD_GET(x) (((x) & SOC_CPU_CLOCK_STANDARD_MASK) >> SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_SET(x) (((x) << SOC_CPU_CLOCK_STANDARD_LSB) & SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +typedef struct hostdef_s { + A_UINT32 d_INT_STATUS_ENABLE_ERROR_LSB; + A_UINT32 d_INT_STATUS_ENABLE_ERROR_MASK; + A_UINT32 d_INT_STATUS_ENABLE_CPU_LSB; + A_UINT32 d_INT_STATUS_ENABLE_CPU_MASK; + A_UINT32 d_INT_STATUS_ENABLE_COUNTER_LSB; + A_UINT32 d_INT_STATUS_ENABLE_COUNTER_MASK; + A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_LSB; + A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_MASK; + A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB; + A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK; + A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB; + A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK; + A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_LSB; + A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_MASK; + A_UINT32 d_INT_STATUS_ENABLE_ADDRESS; + A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_LSB; + A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_MASK; + A_UINT32 d_HOST_INT_STATUS_ADDRESS; + A_UINT32 d_CPU_INT_STATUS_ADDRESS; + A_UINT32 d_ERROR_INT_STATUS_ADDRESS; + A_UINT32 d_ERROR_INT_STATUS_WAKEUP_MASK; + A_UINT32 d_ERROR_INT_STATUS_WAKEUP_LSB; + A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK; + A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB; + A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_MASK; + A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_LSB; + A_UINT32 d_COUNT_DEC_ADDRESS; + A_UINT32 d_HOST_INT_STATUS_CPU_MASK; + A_UINT32 d_HOST_INT_STATUS_CPU_LSB; + A_UINT32 d_HOST_INT_STATUS_ERROR_MASK; + A_UINT32 d_HOST_INT_STATUS_ERROR_LSB; + A_UINT32 d_HOST_INT_STATUS_COUNTER_MASK; + A_UINT32 d_HOST_INT_STATUS_COUNTER_LSB; + A_UINT32 d_RX_LOOKAHEAD_VALID_ADDRESS; + A_UINT32 d_WINDOW_DATA_ADDRESS; + A_UINT32 d_WINDOW_READ_ADDR_ADDRESS; + A_UINT32 d_WINDOW_WRITE_ADDR_ADDRESS; + A_UINT32 d_SOC_GLOBAL_RESET_ADDRESS; + A_UINT32 d_RTC_STATE_ADDRESS; + A_UINT32 d_RTC_STATE_COLD_RESET_MASK; + A_UINT32 d_PCIE_LOCAL_BASE_ADDRESS; + A_UINT32 d_PCIE_SOC_WAKE_RESET; + A_UINT32 d_PCIE_SOC_WAKE_ADDRESS; + A_UINT32 d_PCIE_SOC_WAKE_V_MASK; + A_UINT32 d_RTC_STATE_V_MASK; + A_UINT32 d_RTC_STATE_V_LSB; + A_UINT32 d_FW_IND_EVENT_PENDING; + A_UINT32 d_FW_IND_INITIALIZED; + A_UINT32 d_FW_IND_HELPER; + A_UINT32 d_RTC_STATE_V_ON; +#if defined(SDIO_3_0) + A_UINT32 d_HOST_INT_STATUS_MBOX_DATA_MASK; + A_UINT32 d_HOST_INT_STATUS_MBOX_DATA_LSB; +#endif + A_UINT32 d_PCIE_SOC_RDY_STATUS_ADDRESS; + A_UINT32 d_PCIE_SOC_RDY_STATUS_BAR_MASK; + A_UINT32 d_SOC_PCIE_BASE_ADDRESS; + A_UINT32 d_MSI_MAGIC_ADR_ADDRESS; + A_UINT32 d_MSI_MAGIC_ADDRESS; +} HOST_REGISTER_TABLE; + +#define INT_STATUS_ENABLE_ERROR_LSB (sc->hostdef->d_INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_MASK (sc->hostdef->d_INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_LSB (sc->hostdef->d_INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_MASK (sc->hostdef->d_INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_LSB (sc->hostdef->d_INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_MASK (sc->hostdef->d_INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_LSB (sc->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_MASK (sc->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB (sc->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK (sc->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB (sc->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK (sc->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB (sc->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK (sc->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define INT_STATUS_ENABLE_ADDRESS (sc->hostdef->d_INT_STATUS_ENABLE_ADDRESS) +#define CPU_INT_STATUS_ENABLE_BIT_LSB (sc->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_MASK (sc->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_MASK) +#define HOST_INT_STATUS_ADDRESS (sc->hostdef->d_HOST_INT_STATUS_ADDRESS) +#define CPU_INT_STATUS_ADDRESS (sc->hostdef->d_CPU_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_ADDRESS (sc->hostdef->d_ERROR_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_WAKEUP_MASK (sc->hostdef->d_ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_WAKEUP_LSB (sc->hostdef->d_ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK (sc->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB (sc->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK (sc->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB (sc->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define COUNT_DEC_ADDRESS (sc->hostdef->d_COUNT_DEC_ADDRESS) +#define HOST_INT_STATUS_CPU_MASK (sc->hostdef->d_HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_CPU_LSB (sc->hostdef->d_HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_MASK (sc->hostdef->d_HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_ERROR_LSB (sc->hostdef->d_HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_MASK (sc->hostdef->d_HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_COUNTER_LSB (sc->hostdef->d_HOST_INT_STATUS_COUNTER_LSB) +#define RX_LOOKAHEAD_VALID_ADDRESS (sc->hostdef->d_RX_LOOKAHEAD_VALID_ADDRESS) +#define WINDOW_DATA_ADDRESS (sc->hostdef->d_WINDOW_DATA_ADDRESS) +#define WINDOW_READ_ADDR_ADDRESS (sc->hostdef->d_WINDOW_READ_ADDR_ADDRESS) +#define WINDOW_WRITE_ADDR_ADDRESS (sc->hostdef->d_WINDOW_WRITE_ADDR_ADDRESS) +#define SOC_GLOBAL_RESET_ADDRESS (sc->hostdef->d_SOC_GLOBAL_RESET_ADDRESS) +#define RTC_STATE_ADDRESS (sc->hostdef->d_RTC_STATE_ADDRESS) +#define RTC_STATE_COLD_RESET_MASK (sc->hostdef->d_RTC_STATE_COLD_RESET_MASK) +#define PCIE_LOCAL_BASE_ADDRESS (sc->hostdef->d_PCIE_LOCAL_BASE_ADDRESS) +#define PCIE_SOC_WAKE_RESET (sc->hostdef->d_PCIE_SOC_WAKE_RESET) +#define PCIE_SOC_WAKE_ADDRESS (sc->hostdef->d_PCIE_SOC_WAKE_ADDRESS) +#define PCIE_SOC_WAKE_V_MASK (sc->hostdef->d_PCIE_SOC_WAKE_V_MASK) +#define RTC_STATE_V_MASK (sc->hostdef->d_RTC_STATE_V_MASK) +#define RTC_STATE_V_LSB (sc->hostdef->d_RTC_STATE_V_LSB) +#define FW_IND_EVENT_PENDING (sc->hostdef->d_FW_IND_EVENT_PENDING) +#define FW_IND_INITIALIZED (sc->hostdef->d_FW_IND_INITIALIZED) +#define FW_IND_HELPER (sc->hostdef->d_FW_IND_HELPER) +#define RTC_STATE_V_ON (sc->hostdef->d_RTC_STATE_V_ON) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_MASK (sc->hostdef->d_HOST_INT_STATUS_MBOX_DATA_MASK) +#define HOST_INT_STATUS_MBOX_DATA_LSB (sc->hostdef->d_HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#if !defined(SOC_PCIE_BASE_ADDRESS) +#define SOC_PCIE_BASE_ADDRESS 0 +#endif + +#if !defined(PCIE_SOC_RDY_STATUS_ADDRESS) +#define PCIE_SOC_RDY_STATUS_ADDRESS 0 +#define PCIE_SOC_RDY_STATUS_BAR_MASK 0 +#endif + +#if !defined(MSI_MAGIC_ADR_ADDRESS) +#define MSI_MAGIC_ADR_ADDRESS 0 +#define MSI_MAGIC_ADDRESS 0 +#endif + + +/* SET/GET macros */ +#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) +#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_GET(x) (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#define INVALID_REG_LOC_DUMMY_DATA 0xAA + + +#define AR6320_CORE_CLK_DIV_ADDR 0x403fa8 +#define AR6320_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320_CPU_SPEED_ADDR 0x403fa4 +#define AR6320V2_CORE_CLK_DIV_ADDR 0x403fd8 +#define AR6320V2_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320V2_CPU_SPEED_ADDR 0x403fd4 +#define AR6320V3_CORE_CLK_DIV_ADDR 0x404028 +#define AR6320V3_CPU_PLL_INIT_DONE_ADDR 0x404020 +#define AR6320V3_CPU_SPEED_ADDR 0x404024 + +typedef enum { + SOC_REFCLK_UNKNOWN = -1, /* Unsupported ref clock -- use PLL Bypass */ + SOC_REFCLK_48_MHZ = 0, + SOC_REFCLK_19_2_MHZ = 1, + SOC_REFCLK_24_MHZ = 2, + SOC_REFCLK_26_MHZ = 3, + SOC_REFCLK_37_4_MHZ = 4, + SOC_REFCLK_38_4_MHZ = 5, + SOC_REFCLK_40_MHZ = 6, + SOC_REFCLK_52_MHZ = 7, +} A_refclk_speed_t; + +#define A_REFCLK_UNKNOWN SOC_REFCLK_UNKNOWN +#define A_REFCLK_48_MHZ SOC_REFCLK_48_MHZ +#define A_REFCLK_19_2_MHZ SOC_REFCLK_19_2_MHZ +#define A_REFCLK_24_MHZ SOC_REFCLK_24_MHZ +#define A_REFCLK_26_MHZ SOC_REFCLK_26_MHZ +#define A_REFCLK_37_4_MHZ SOC_REFCLK_37_4_MHZ +#define A_REFCLK_38_4_MHZ SOC_REFCLK_38_4_MHZ +#define A_REFCLK_40_MHZ SOC_REFCLK_40_MHZ +#define A_REFCLK_52_MHZ SOC_REFCLK_52_MHZ + +#define TARGET_CPU_FREQ 176000000 + +struct wlan_pll_s { + u_int32_t refdiv; + u_int32_t div; + u_int32_t rnfrac; + u_int32_t outdiv; +}; + +struct cmnos_clock_s { + A_refclk_speed_t refclk_speed; + u_int32_t refclk_hz; + u_int32_t pll_settling_time; /* 50us */ + struct wlan_pll_s wlan_pll; +}; + +typedef struct TGT_REG_SECTION { + u_int32_t start_addr; + u_int32_t end_addr; +} tgt_reg_section; + +typedef struct TGT_REG_TABLE { + tgt_reg_section *section; + u_int32_t section_size; +} tgt_reg_table; + +void target_register_tbl_attach(struct hif_pci_softc *sc, u32 target_type); +void hif_register_tbl_attach(struct hif_pci_softc *sc, u32 hif_type); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320def.h new file mode 100644 index 000000000000..28a23b13982c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320def.h @@ -0,0 +1,698 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320DEF_H_ +#define _AR6320DEF_H_ + +/* Base Addresses */ +#define AR6320_RTC_SOC_BASE_ADDRESS 0x00000000 +#define AR6320_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320_CE0_BASE_ADDRESS 0x00034400 +#define AR6320_CE1_BASE_ADDRESS 0x00034800 +#define AR6320_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320_CE3_BASE_ADDRESS 0x00035000 +#define AR6320_CE4_BASE_ADDRESS 0x00035400 +#define AR6320_CE5_BASE_ADDRESS 0x00035800 +#define AR6320_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320_CE7_BASE_ADDRESS 0x00036000 +#define AR6320_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320_SCRATCH_3_ADDRESS 0x0028 +#define AR6320_TARG_DRAM_START 0x00400000 +#define AR6320_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320_SI_CONFIG_I2C_LSB 16 +#define AR6320_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320_SI_CONFIG_OFFSET 0x00000000 +#define AR6320_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320_SI_CS_OFFSET 0x00000004 +#define AR6320_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320_SI_CS_START_LSB 8 +#define AR6320_SI_CS_START_MASK 0x00000100 +#define AR6320_SI_CS_RX_CNT_LSB 4 +#define AR6320_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320_SI_CS_TX_CNT_LSB 0 +#define AR6320_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320_CE_COUNT 8 +#define AR6320_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320_RX_MPDU_START_0_RETRY_LSB 14 +#define AR6320_RX_MPDU_START_0_RETRY_MASK 0x00004000 +#define AR6320_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320_RX_MPDU_START_2_TID_LSB 28 +#define AR6320_RX_MPDU_START_2_TID_MASK 0xf0000000 +#define AR6320_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320_RX_MSDU_END_1_KEY_ID_OCT_MASK 0x000000ff +#define AR6320_RX_MSDU_END_1_KEY_ID_OCT_LSB 0 +#define AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320_HOST_IS_ADDRESS 0x0030 +#define AR6320_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320_HOST_IE_ADDRESS 0x002c +#define AR6320_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320_SR_BA_ADDRESS 0x0000 +#define AR6320_SR_SIZE_ADDRESS 0x0004 +#define AR6320_CE_CTRL1_ADDRESS 0x0010 +#define AR6320_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320_DR_BA_ADDRESS 0x0008 +#define AR6320_DR_SIZE_ADDRESS 0x000c +#define AR6320_MISC_IE_ADDRESS 0x0034 +#define AR6320_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320_SRC_WATERMARK_LOW_LSB 16 +#define AR6320_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320_DST_WATERMARK_LOW_LSB 16 +#define AR6320_DST_WATERMARK_HIGH_LSB 0 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320_RTC_STATE_ADDRESS 0x0000 +#define AR6320_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320_RTC_STATE_V_MASK 0x00000007 +#define AR6320_RTC_STATE_V_LSB 0 +#define AR6320_RTC_STATE_V_ON 3 +#define AR6320_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320_FW_IND_EVENT_PENDING 1 +#define AR6320_FW_IND_INITIALIZED 2 +#define AR6320_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320_CPU_INTR_ADDRESS 0x0010 +#define AR6320_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320_CORE_CTRL_ADDRESS 0x0000 +#define AR6320_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320_SOC_CHIP_ID_REVISION_LSB 8 +#define AR6320_SOC_POWER_REG_OFFSET 0x0000010c + +/* Copy Engine Debug */ +#define AR6320_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c +#define AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MSB 3 +#define AR6320_WLAN_DEBUG_INPUT_SEL_SRC_LSB 0 +#define AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MASK 0x0000000f +#define AR6320_WLAN_DEBUG_CONTROL_OFFSET 0x00000108 +#define AR6320_WLAN_DEBUG_CONTROL_ENABLE_MSB 0 +#define AR6320_WLAN_DEBUG_CONTROL_ENABLE_LSB 0 +#define AR6320_WLAN_DEBUG_CONTROL_ENABLE_MASK 0x00000001 +#define AR6320_WLAN_DEBUG_OUT_OFFSET 0x00000110 +#define AR6320_WLAN_DEBUG_OUT_DATA_MSB 19 +#define AR6320_WLAN_DEBUG_OUT_DATA_LSB 0 +#define AR6320_WLAN_DEBUG_OUT_DATA_MASK 0x000fffff +#define AR6320_AMBA_DEBUG_BUS_OFFSET 0x0000011c +#define AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB 13 +#define AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB 8 +#define AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK 0x00003f00 +#define AR6320_AMBA_DEBUG_BUS_SEL_MSB 4 +#define AR6320_AMBA_DEBUG_BUS_SEL_LSB 0 +#define AR6320_AMBA_DEBUG_BUS_SEL_MASK 0x0000001f +#define AR6320_CE_WRAPPER_DEBUG_OFFSET 0x0008 +#define AR6320_CE_WRAPPER_DEBUG_SEL_MSB 5 +#define AR6320_CE_WRAPPER_DEBUG_SEL_LSB 0 +#define AR6320_CE_WRAPPER_DEBUG_SEL_MASK 0x0000003f +#define AR6320_CE_DEBUG_OFFSET 0x0054 +#define AR6320_CE_DEBUG_SEL_MSB 5 +#define AR6320_CE_DEBUG_SEL_LSB 0 +#define AR6320_CE_DEBUG_SEL_MASK 0x0000003f +/* End */ + +/* PLL start */ +#define AR6320_EFUSE_OFFSET 0x0000032c +#define AR6320_EFUSE_XTAL_SEL_MSB 10 +#define AR6320_EFUSE_XTAL_SEL_LSB 8 +#define AR6320_EFUSE_XTAL_SEL_MASK 0x00000700 +#define AR6320_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define AR6320_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define AR6320_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define AR6320_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define AR6320_BB_PLL_CONFIG_FRAC_MSB 17 +#define AR6320_BB_PLL_CONFIG_FRAC_LSB 0 +#define AR6320_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define AR6320_WLAN_PLL_SETTLE_TIME_MSB 10 +#define AR6320_WLAN_PLL_SETTLE_TIME_LSB 0 +#define AR6320_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define AR6320_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define AR6320_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define AR6320_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define AR6320_WLAN_PLL_SETTLE_RESET 0x00000400 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define AR6320_WLAN_PLL_CONTROL_DIV_MSB 9 +#define AR6320_WLAN_PLL_CONTROL_DIV_LSB 0 +#define AR6320_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define AR6320_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define AR6320_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define AR6320_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define AR6320_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define AR6320_WLAN_PLL_CONTROL_RESET 0x00010011 +#define AR6320_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define AR6320_RTC_SYNC_STATUS_OFFSET 0x0244 +#define AR6320_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define AR6320_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define AR6320_PCIE_INTR_CE_MASK(n) (AR6320_PCIE_INTR_CE0_MASK << (n)) +#define AR6320_DRAM_BASE_ADDRESS AR6320_TARG_DRAM_START +#define AR6320_FW_INDICATOR_ADDRESS (AR6320_SOC_CORE_BASE_ADDRESS + AR6320_SCRATCH_3_ADDRESS) +#define AR6320_SYSTEM_SLEEP_OFFSET AR6320_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320_WLAN_RESET_CONTROL_OFFSET AR6320_SOC_RESET_CONTROL_OFFSET +#define AR6320_CLOCK_CONTROL_OFFSET AR6320_SOC_CLOCK_CONTROL_OFFSET +#define AR6320_CLOCK_CONTROL_SI0_CLK_MASK AR6320_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320_RESET_CONTROL_SI0_RST_MASK AR6320_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320_GPIO_BASE_ADDRESS AR6320_WLAN_GPIO_BASE_ADDRESS +#define AR6320_GPIO_PIN0_OFFSET AR6320_WLAN_GPIO_PIN0_ADDRESS +#define AR6320_GPIO_PIN1_OFFSET AR6320_WLAN_GPIO_PIN1_ADDRESS +#define AR6320_GPIO_PIN0_CONFIG_MASK AR6320_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320_GPIO_PIN1_CONFIG_MASK AR6320_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320_SI_BASE_ADDRESS 0x00050000 +#define AR6320_CPU_CLOCK_OFFSET AR6320_SOC_CPU_CLOCK_OFFSET +#define AR6320_LPO_CAL_OFFSET AR6320_SOC_LPO_CAL_OFFSET +#define AR6320_GPIO_PIN10_OFFSET AR6320_WLAN_GPIO_PIN10_ADDRESS +#define AR6320_GPIO_PIN11_OFFSET AR6320_WLAN_GPIO_PIN11_ADDRESS +#define AR6320_GPIO_PIN12_OFFSET AR6320_WLAN_GPIO_PIN12_ADDRESS +#define AR6320_GPIO_PIN13_OFFSET AR6320_WLAN_GPIO_PIN13_ADDRESS +#define AR6320_CPU_CLOCK_STANDARD_LSB AR6320_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320_CPU_CLOCK_STANDARD_MASK AR6320_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320_LPO_CAL_ENABLE_LSB AR6320_SOC_LPO_CAL_ENABLE_LSB +#define AR6320_LPO_CAL_ENABLE_MASK AR6320_SOC_LPO_CAL_ENABLE_MASK +#define AR6320_ANALOG_INTF_BASE_ADDRESS AR6320_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320_COUNT_DEC_ADDRESS 0x0840 +#define AR6320_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320_WINDOW_WRITE_ADDR_ADDRESS 0x0878 + +struct targetdef_s ar6320_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320_CE_COUNT, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR6320_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_RETRY_LSB = AR6320_RX_MPDU_START_0_RETRY_LSB, + .d_RX_MPDU_START_0_RETRY_MASK = AR6320_RX_MPDU_START_0_RETRY_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MPDU_START_2_TID_LSB = AR6320_RX_MPDU_START_2_TID_LSB, + .d_RX_MPDU_START_2_TID_MASK = AR6320_RX_MPDU_START_2_TID_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_MASK = AR6320_RX_MSDU_END_1_KEY_ID_OCT_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_LSB = AR6320_RX_MSDU_END_1_KEY_ID_OCT_LSB, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_WLAN_DEBUG_INPUT_SEL_OFFSET = AR6320_WLAN_DEBUG_INPUT_SEL_OFFSET, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MSB = AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_LSB = AR6320_WLAN_DEBUG_INPUT_SEL_SRC_LSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MASK = AR6320_WLAN_DEBUG_INPUT_SEL_SRC_MASK, + .d_WLAN_DEBUG_CONTROL_OFFSET = AR6320_WLAN_DEBUG_CONTROL_OFFSET, + .d_WLAN_DEBUG_CONTROL_ENABLE_MSB = AR6320_WLAN_DEBUG_CONTROL_ENABLE_MSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_LSB = AR6320_WLAN_DEBUG_CONTROL_ENABLE_LSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_MASK = AR6320_WLAN_DEBUG_CONTROL_ENABLE_MASK, + .d_WLAN_DEBUG_OUT_OFFSET = AR6320_WLAN_DEBUG_OUT_OFFSET, + .d_WLAN_DEBUG_OUT_DATA_MSB = AR6320_WLAN_DEBUG_OUT_DATA_MSB, + .d_WLAN_DEBUG_OUT_DATA_LSB = AR6320_WLAN_DEBUG_OUT_DATA_LSB, + .d_WLAN_DEBUG_OUT_DATA_MASK = AR6320_WLAN_DEBUG_OUT_DATA_MASK, + .d_AMBA_DEBUG_BUS_OFFSET = AR6320_AMBA_DEBUG_BUS_OFFSET, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB = AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB = AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK = AR6320_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK, + .d_AMBA_DEBUG_BUS_SEL_MSB = AR6320_AMBA_DEBUG_BUS_SEL_MSB, + .d_AMBA_DEBUG_BUS_SEL_LSB = AR6320_AMBA_DEBUG_BUS_SEL_LSB, + .d_AMBA_DEBUG_BUS_SEL_MASK = AR6320_AMBA_DEBUG_BUS_SEL_MASK, + .d_CE_WRAPPER_DEBUG_OFFSET = AR6320_CE_WRAPPER_DEBUG_OFFSET, + .d_CE_WRAPPER_DEBUG_SEL_MSB = AR6320_CE_WRAPPER_DEBUG_SEL_MSB, + .d_CE_WRAPPER_DEBUG_SEL_LSB = AR6320_CE_WRAPPER_DEBUG_SEL_LSB, + .d_CE_WRAPPER_DEBUG_SEL_MASK = AR6320_CE_WRAPPER_DEBUG_SEL_MASK, + .d_CE_DEBUG_OFFSET = AR6320_CE_DEBUG_OFFSET, + .d_CE_DEBUG_SEL_MSB = AR6320_CE_DEBUG_SEL_MSB, + .d_CE_DEBUG_SEL_LSB = AR6320_CE_DEBUG_SEL_LSB, + .d_CE_DEBUG_SEL_MASK = AR6320_CE_DEBUG_SEL_MASK, + /* PLL start */ + .d_EFUSE_OFFSET = AR6320_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = AR6320_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = AR6320_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = AR6320_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = AR6320_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = AR6320_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = AR6320_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = AR6320_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = AR6320_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = AR6320_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = AR6320_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = AR6320_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = AR6320_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = AR6320_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = AR6320_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = AR6320_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = AR6320_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = AR6320_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = AR6320_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = AR6320_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = AR6320_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = AR6320_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = AR6320_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = AR6320_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = AR6320_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = AR6320_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = AR6320_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = AR6320_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = AR6320_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = AR6320_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = AR6320_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = AR6320_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = AR6320_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = AR6320_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = AR6320_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = AR6320_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = AR6320_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = AR6320_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = AR6320_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = AR6320_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = AR6320_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = AR6320_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = AR6320_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = AR6320_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = AR6320_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = AR6320_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = AR6320_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = AR6320_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = AR6320_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = AR6320_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_SOC_POWER_REG_OFFSET = AR6320_SOC_POWER_REG_OFFSET, + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR6320_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320v2def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320v2def.h new file mode 100644 index 000000000000..40ed743f2a69 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar6320v2def.h @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320V2DEF_H_ +#define _AR6320V2DEF_H_ + +/* Base Addresses */ +#define AR6320V2_RTC_SOC_BASE_ADDRESS 0x00000800 +#define AR6320V2_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320V2_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320V2_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320V2_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320V2_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320V2_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320V2_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320V2_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320V2_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320V2_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320V2_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320V2_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320V2_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320V2_CE0_BASE_ADDRESS 0x00034400 +#define AR6320V2_CE1_BASE_ADDRESS 0x00034800 +#define AR6320V2_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320V2_CE3_BASE_ADDRESS 0x00035000 +#define AR6320V2_CE4_BASE_ADDRESS 0x00035400 +#define AR6320V2_CE5_BASE_ADDRESS 0x00035800 +#define AR6320V2_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320V2_CE7_BASE_ADDRESS 0x00036000 +#define AR6320V2_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320V2_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320V2_SCRATCH_3_ADDRESS 0x0028 +#define AR6320V2_TARG_DRAM_START 0x00400000 +#define AR6320V2_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320V2_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320V2_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320V2_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320V2_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320V2_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320V2_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320V2_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320V2_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320V2_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320V2_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320V2_SI_CONFIG_I2C_LSB 16 +#define AR6320V2_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320V2_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320V2_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320V2_SI_CONFIG_OFFSET 0x00000000 +#define AR6320V2_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320V2_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320V2_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320V2_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320V2_SI_CS_OFFSET 0x00000004 +#define AR6320V2_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320V2_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320V2_SI_CS_START_LSB 8 +#define AR6320V2_SI_CS_START_MASK 0x00000100 +#define AR6320V2_SI_CS_RX_CNT_LSB 4 +#define AR6320V2_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320V2_SI_CS_TX_CNT_LSB 0 +#define AR6320V2_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320V2_CE_COUNT 8 +#define AR6320V2_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320V2_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_RETRY_LSB 14 +#define AR6320V2_RX_MPDU_START_0_RETRY_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320V2_RX_MPDU_START_2_TID_LSB 28 +#define AR6320V2_RX_MPDU_START_2_TID_MASK 0xf0000000 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff + +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320V2_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320V2_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320V2_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320V2_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320V2_HOST_IS_ADDRESS 0x0030 +#define AR6320V2_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320V2_HOST_IE_ADDRESS 0x002c +#define AR6320V2_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_SR_BA_ADDRESS 0x0000 +#define AR6320V2_SR_SIZE_ADDRESS 0x0004 +#define AR6320V2_CE_CTRL1_ADDRESS 0x0010 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320V2_DR_BA_ADDRESS 0x0008 +#define AR6320V2_DR_SIZE_ADDRESS 0x000c +#define AR6320V2_MISC_IE_ADDRESS 0x0034 +#define AR6320V2_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320V2_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320V2_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320V2_SRC_WATERMARK_LOW_LSB 16 +#define AR6320V2_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320V2_DST_WATERMARK_LOW_LSB 16 +#define AR6320V2_DST_WATERMARK_HIGH_LSB 0 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320V2_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320V2_RTC_STATE_ADDRESS 0x0000 +#define AR6320V2_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320V2_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320V2_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320V2_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320V2_RTC_STATE_V_MASK 0x00000007 +#define AR6320V2_RTC_STATE_V_LSB 0 +#define AR6320V2_RTC_STATE_V_ON 3 +#define AR6320V2_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320V2_FW_IND_EVENT_PENDING 1 +#define AR6320V2_FW_IND_INITIALIZED 2 +#define AR6320V2_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320V2_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320V2_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320V2_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320V2_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320V2_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320V2_CPU_INTR_ADDRESS 0x0010 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320V2_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320V2_CORE_CTRL_ADDRESS 0x0000 +#define AR6320V2_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320V2_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320V2_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320V2_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320V2_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320V2_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320V2_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320V2_SOC_CHIP_ID_REVISION_LSB 8 +#define AR6320V2_SOC_POWER_REG_OFFSET 0x0000010c + +/* Copy Engine Debug */ +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MSB 3 +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_LSB 0 +#define AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MASK 0x0000000f +#define AR6320V2_WLAN_DEBUG_CONTROL_OFFSET 0x00000108 +#define AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MSB 0 +#define AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_LSB 0 +#define AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MASK 0x00000001 +#define AR6320V2_WLAN_DEBUG_OUT_OFFSET 0x00000110 +#define AR6320V2_WLAN_DEBUG_OUT_DATA_MSB 19 +#define AR6320V2_WLAN_DEBUG_OUT_DATA_LSB 0 +#define AR6320V2_WLAN_DEBUG_OUT_DATA_MASK 0x000fffff +#define AR6320V2_AMBA_DEBUG_BUS_OFFSET 0x0000011c +#define AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB 13 +#define AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB 8 +#define AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK 0x00003f00 +#define AR6320V2_AMBA_DEBUG_BUS_SEL_MSB 4 +#define AR6320V2_AMBA_DEBUG_BUS_SEL_LSB 0 +#define AR6320V2_AMBA_DEBUG_BUS_SEL_MASK 0x0000001f +#define AR6320V2_CE_WRAPPER_DEBUG_OFFSET 0x0008 +#define AR6320V2_CE_WRAPPER_DEBUG_SEL_MSB 5 +#define AR6320V2_CE_WRAPPER_DEBUG_SEL_LSB 0 +#define AR6320V2_CE_WRAPPER_DEBUG_SEL_MASK 0x0000003f +#define AR6320V2_CE_DEBUG_OFFSET 0x0054 +#define AR6320V2_CE_DEBUG_SEL_MSB 5 +#define AR6320V2_CE_DEBUG_SEL_LSB 0 +#define AR6320V2_CE_DEBUG_SEL_MASK 0x0000003f +/* End */ + +/* PLL start */ +#define AR6320V2_EFUSE_OFFSET 0x0000032c +#define AR6320V2_EFUSE_XTAL_SEL_MSB 10 +#define AR6320V2_EFUSE_XTAL_SEL_LSB 8 +#define AR6320V2_EFUSE_XTAL_SEL_MASK 0x00000700 +#define AR6320V2_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define AR6320V2_BB_PLL_CONFIG_FRAC_MSB 17 +#define AR6320V2_BB_PLL_CONFIG_FRAC_LSB 0 +#define AR6320V2_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define AR6320V2_WLAN_PLL_SETTLE_TIME_MSB 10 +#define AR6320V2_WLAN_PLL_SETTLE_TIME_LSB 0 +#define AR6320V2_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define AR6320V2_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define AR6320V2_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define AR6320V2_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define AR6320V2_WLAN_PLL_SETTLE_RESET 0x00000400 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_MSB 9 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_LSB 0 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define AR6320V2_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define AR6320V2_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define AR6320V2_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define AR6320V2_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define AR6320V2_WLAN_PLL_CONTROL_RESET 0x00010011 +#define AR6320V2_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define AR6320V2_RTC_SYNC_STATUS_OFFSET 0x0244 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define AR6320V2_PCIE_INTR_CE_MASK(n) (AR6320V2_PCIE_INTR_CE0_MASK << (n)) +#define AR6320V2_DRAM_BASE_ADDRESS AR6320V2_TARG_DRAM_START +#define AR6320V2_FW_INDICATOR_ADDRESS (AR6320V2_SOC_CORE_BASE_ADDRESS + AR6320V2_SCRATCH_3_ADDRESS) +#define AR6320V2_SYSTEM_SLEEP_OFFSET AR6320V2_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320V2_WLAN_RESET_CONTROL_OFFSET AR6320V2_SOC_RESET_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_OFFSET AR6320V2_SOC_CLOCK_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320V2_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320V2_RESET_CONTROL_SI0_RST_MASK AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320V2_GPIO_BASE_ADDRESS AR6320V2_WLAN_GPIO_BASE_ADDRESS +#define AR6320V2_GPIO_PIN0_OFFSET AR6320V2_WLAN_GPIO_PIN0_ADDRESS +#define AR6320V2_GPIO_PIN1_OFFSET AR6320V2_WLAN_GPIO_PIN1_ADDRESS +#define AR6320V2_GPIO_PIN0_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320V2_GPIO_PIN1_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320V2_SI_BASE_ADDRESS 0x00050000 +#define AR6320V2_CPU_CLOCK_OFFSET AR6320V2_SOC_CPU_CLOCK_OFFSET +#define AR6320V2_LPO_CAL_OFFSET AR6320V2_SOC_LPO_CAL_OFFSET +#define AR6320V2_GPIO_PIN10_OFFSET AR6320V2_WLAN_GPIO_PIN10_ADDRESS +#define AR6320V2_GPIO_PIN11_OFFSET AR6320V2_WLAN_GPIO_PIN11_ADDRESS +#define AR6320V2_GPIO_PIN12_OFFSET AR6320V2_WLAN_GPIO_PIN12_ADDRESS +#define AR6320V2_GPIO_PIN13_OFFSET AR6320V2_WLAN_GPIO_PIN13_ADDRESS +#define AR6320V2_CPU_CLOCK_STANDARD_LSB AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320V2_CPU_CLOCK_STANDARD_MASK AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320V2_LPO_CAL_ENABLE_LSB AR6320V2_SOC_LPO_CAL_ENABLE_LSB +#define AR6320V2_LPO_CAL_ENABLE_MASK AR6320V2_SOC_LPO_CAL_ENABLE_MASK +#define AR6320V2_ANALOG_INTF_BASE_ADDRESS AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320V2_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320V2_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320V2_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320V2_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320V2_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320V2_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320V2_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320V2_COUNT_DEC_ADDRESS 0x0840 +#define AR6320V2_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320V2_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320V2_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320V2_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320V2_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320V2_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320V2_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320V2_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320V2_WINDOW_WRITE_ADDR_ADDRESS 0x0878 + +struct targetdef_s ar6320v2_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320V2_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320V2_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320V2_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320V2_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320V2_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320V2_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320V2_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320V2_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320V2_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320V2_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320V2_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320V2_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320V2_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320V2_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320V2_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320V2_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320V2_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320V2_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320V2_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320V2_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320V2_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320V2_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320V2_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320V2_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320V2_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320V2_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320V2_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320V2_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320V2_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320V2_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320V2_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320V2_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320V2_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320V2_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320V2_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320V2_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320V2_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320V2_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320V2_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320V2_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320V2_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320V2_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320V2_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320V2_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320V2_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320V2_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320V2_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320V2_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320V2_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320V2_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320V2_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320V2_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320V2_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320V2_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320V2_CE_COUNT, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320V2_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320V2_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320V2_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320V2_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320V2_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR6320V2_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320V2_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_RETRY_LSB = AR6320V2_RX_MPDU_START_0_RETRY_LSB, + .d_RX_MPDU_START_0_RETRY_MASK = AR6320V2_RX_MPDU_START_0_RETRY_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320V2_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320V2_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MPDU_START_2_TID_LSB = AR6320V2_RX_MPDU_START_2_TID_LSB, + .d_RX_MPDU_START_2_TID_MASK = AR6320V2_RX_MPDU_START_2_TID_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320V2_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320V2_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320V2_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320V2_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320V2_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320V2_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320V2_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320V2_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320V2_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320V2_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320V2_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320V2_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320V2_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320V2_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320V2_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320V2_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320V2_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320V2_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320V2_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320V2_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320V2_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320V2_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320V2_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320V2_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320V2_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320V2_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_WLAN_DEBUG_INPUT_SEL_OFFSET = AR6320V2_WLAN_DEBUG_INPUT_SEL_OFFSET, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MSB = AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_LSB = AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_LSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MASK = AR6320V2_WLAN_DEBUG_INPUT_SEL_SRC_MASK, + .d_WLAN_DEBUG_CONTROL_OFFSET = AR6320V2_WLAN_DEBUG_CONTROL_OFFSET, + .d_WLAN_DEBUG_CONTROL_ENABLE_MSB = AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_LSB = AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_LSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_MASK = AR6320V2_WLAN_DEBUG_CONTROL_ENABLE_MASK, + .d_WLAN_DEBUG_OUT_OFFSET = AR6320V2_WLAN_DEBUG_OUT_OFFSET, + .d_WLAN_DEBUG_OUT_DATA_MSB = AR6320V2_WLAN_DEBUG_OUT_DATA_MSB, + .d_WLAN_DEBUG_OUT_DATA_LSB = AR6320V2_WLAN_DEBUG_OUT_DATA_LSB, + .d_WLAN_DEBUG_OUT_DATA_MASK = AR6320V2_WLAN_DEBUG_OUT_DATA_MASK, + .d_AMBA_DEBUG_BUS_OFFSET = AR6320V2_AMBA_DEBUG_BUS_OFFSET, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB = AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB = AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK = AR6320V2_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK, + .d_AMBA_DEBUG_BUS_SEL_MSB = AR6320V2_AMBA_DEBUG_BUS_SEL_MSB, + .d_AMBA_DEBUG_BUS_SEL_LSB = AR6320V2_AMBA_DEBUG_BUS_SEL_LSB, + .d_AMBA_DEBUG_BUS_SEL_MASK = AR6320V2_AMBA_DEBUG_BUS_SEL_MASK, + .d_CE_WRAPPER_DEBUG_OFFSET = AR6320V2_CE_WRAPPER_DEBUG_OFFSET, + .d_CE_WRAPPER_DEBUG_SEL_MSB = AR6320V2_CE_WRAPPER_DEBUG_SEL_MSB, + .d_CE_WRAPPER_DEBUG_SEL_LSB = AR6320V2_CE_WRAPPER_DEBUG_SEL_LSB, + .d_CE_WRAPPER_DEBUG_SEL_MASK = AR6320V2_CE_WRAPPER_DEBUG_SEL_MASK, + .d_CE_DEBUG_OFFSET = AR6320V2_CE_DEBUG_OFFSET, + .d_CE_DEBUG_SEL_MSB = AR6320V2_CE_DEBUG_SEL_MSB, + .d_CE_DEBUG_SEL_LSB = AR6320V2_CE_DEBUG_SEL_LSB, + .d_CE_DEBUG_SEL_MASK = AR6320V2_CE_DEBUG_SEL_MASK, + /* PLL start */ + .d_EFUSE_OFFSET = AR6320V2_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = AR6320V2_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = AR6320V2_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = AR6320V2_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = AR6320V2_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = AR6320V2_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = AR6320V2_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = AR6320V2_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = AR6320V2_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = AR6320V2_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = AR6320V2_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = AR6320V2_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = AR6320V2_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = AR6320V2_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = AR6320V2_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = AR6320V2_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = AR6320V2_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = AR6320V2_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = AR6320V2_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = AR6320V2_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = AR6320V2_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = AR6320V2_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = AR6320V2_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = AR6320V2_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = AR6320V2_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = AR6320V2_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = AR6320V2_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = AR6320V2_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = AR6320V2_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = AR6320V2_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = AR6320V2_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = AR6320V2_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = AR6320V2_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = AR6320V2_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = AR6320V2_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = AR6320V2_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = AR6320V2_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = AR6320V2_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = AR6320V2_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = AR6320V2_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = AR6320V2_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = AR6320V2_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = AR6320V2_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = AR6320V2_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_SOC_POWER_REG_OFFSET = AR6320V2_SOC_POWER_REG_OFFSET, + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320V2_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320V2_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320V2_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320V2_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320V2_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320V2_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320V2_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320V2_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320v2_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320V2_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320V2_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320V2_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320V2_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320V2_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320V2_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320V2_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320V2_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320V2_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320V2_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320V2_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320V2_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320V2_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320V2_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320V2_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320V2_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320V2_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320V2_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320V2_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320V2_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320V2_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320V2_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320V2_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320V2_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320V2_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320V2_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320V2_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320V2_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320V2_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR6320V2_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320V2_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320V2_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar9888def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar9888def.h new file mode 100644 index 000000000000..3bf2ec2e308c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/ar9888def.h @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR9888DEF_H_ +#define AR9888__AR9888DEF_H_ + +/* Base Addresses */ +#define AR9888_RTC_SOC_BASE_ADDRESS 0x00004000 +#define AR9888_RTC_WMAC_BASE_ADDRESS 0x00005000 +#define AR9888_MAC_COEX_BASE_ADDRESS 0x00006000 +#define AR9888_BT_COEX_BASE_ADDRESS 0x00007000 +#define AR9888_SOC_PCIE_BASE_ADDRESS 0x00008000 +#define AR9888_SOC_CORE_BASE_ADDRESS 0x00009000 +#define AR9888_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR9888_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR9888_WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 +#define AR9888_WLAN_MAC_BASE_ADDRESS 0x00020000 +#define AR9888_EFUSE_BASE_ADDRESS 0x00030000 +#define AR9888_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR9888_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR9888_CE_WRAPPER_BASE_ADDRESS 0x00057000 +#define AR9888_CE0_BASE_ADDRESS 0x00057400 +#define AR9888_CE1_BASE_ADDRESS 0x00057800 +#define AR9888_CE2_BASE_ADDRESS 0x00057c00 +#define AR9888_CE3_BASE_ADDRESS 0x00058000 +#define AR9888_CE4_BASE_ADDRESS 0x00058400 +#define AR9888_CE5_BASE_ADDRESS 0x00058800 +#define AR9888_CE6_BASE_ADDRESS 0x00058c00 +#define AR9888_CE7_BASE_ADDRESS 0x00059000 +#define AR9888_DBI_BASE_ADDRESS 0x00060000 +#define AR9888_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 + +#define AR9888_SCRATCH_3_ADDRESS 0x0030 +#define AR9888_TARG_DRAM_START 0x00400000 +#define AR9888_SOC_SYSTEM_SLEEP_OFFSET 0x000000c4 +#define AR9888_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR9888_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR9888_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR9888_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define AR9888_WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define AR9888_WLAN_GPIO_PIN0_ADDRESS 0x00000028 +#define AR9888_WLAN_GPIO_PIN1_ADDRESS 0x0000002c +#define AR9888_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR9888_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR9888_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR9888_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR9888_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR9888_WLAN_GPIO_PIN10_ADDRESS 0x00000050 +#define AR9888_WLAN_GPIO_PIN11_ADDRESS 0x00000054 +#define AR9888_WLAN_GPIO_PIN12_ADDRESS 0x00000058 +#define AR9888_WLAN_GPIO_PIN13_ADDRESS 0x0000005c +#define AR9888_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR9888_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR9888_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR9888_SOC_LPO_CAL_ENABLE_MASK 0x00100000 +#define AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 + +#define AR9888_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR9888_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR9888_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR9888_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR9888_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR9888_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR9888_SI_CONFIG_I2C_LSB 16 +#define AR9888_SI_CONFIG_I2C_MASK 0x00010000 +#define AR9888_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR9888_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR9888_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR9888_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR9888_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR9888_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR9888_SI_CONFIG_DIVIDER_LSB 0 +#define AR9888_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR9888_SI_CONFIG_OFFSET 0x00000000 +#define AR9888_SI_TX_DATA0_OFFSET 0x00000008 +#define AR9888_SI_TX_DATA1_OFFSET 0x0000000c +#define AR9888_SI_RX_DATA0_OFFSET 0x00000010 +#define AR9888_SI_RX_DATA1_OFFSET 0x00000014 +#define AR9888_SI_CS_OFFSET 0x00000004 +#define AR9888_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR9888_SI_CS_DONE_INT_MASK 0x00000200 +#define AR9888_SI_CS_START_LSB 8 +#define AR9888_SI_CS_START_MASK 0x00000100 +#define AR9888_SI_CS_RX_CNT_LSB 4 +#define AR9888_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR9888_SI_CS_TX_CNT_LSB 0 +#define AR9888_SI_CS_TX_CNT_MASK 0x0000000f +#define AR9888_CE_COUNT 8 +#define AR9888_SR_WR_INDEX_ADDRESS 0x003c +#define AR9888_DST_WATERMARK_ADDRESS 0x0050 +#define AR9888_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR9888_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR9888_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR9888_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR9888_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR9888_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR9888_RX_MSDU_END_1_KEY_ID_OCT_MASK 0x000000ff +#define AR9888_RX_MSDU_END_1_KEY_ID_OCT_LSB 0 +#define AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR9888_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR9888_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR9888_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR9888_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR9888_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR9888_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR9888_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR9888_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR9888_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR9888_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR9888_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR9888_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR9888_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR9888_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR9888_DST_WR_INDEX_ADDRESS 0x0040 +#define AR9888_SRC_WATERMARK_ADDRESS 0x004c +#define AR9888_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR9888_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR9888_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR9888_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR9888_CURRENT_SRRI_ADDRESS 0x0044 +#define AR9888_CURRENT_DRRI_ADDRESS 0x0048 +#define AR9888_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR9888_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR9888_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR9888_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR9888_HOST_IS_ADDRESS 0x0030 +#define AR9888_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR9888_HOST_IE_ADDRESS 0x002c +#define AR9888_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR9888_SR_BA_ADDRESS 0x0000 +#define AR9888_SR_SIZE_ADDRESS 0x0004 +#define AR9888_CE_CTRL1_ADDRESS 0x0010 +#define AR9888_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR9888_DR_BA_ADDRESS 0x0008 +#define AR9888_DR_SIZE_ADDRESS 0x000c +#define AR9888_MISC_IE_ADDRESS 0x0034 +#define AR9888_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR9888_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR9888_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR9888_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR9888_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR9888_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR9888_SRC_WATERMARK_LOW_LSB 16 +#define AR9888_SRC_WATERMARK_HIGH_LSB 0 +#define AR9888_DST_WATERMARK_LOW_LSB 16 +#define AR9888_DST_WATERMARK_HIGH_LSB 0 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR9888_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000004 +#define AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 2 +#define AR9888_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR9888_RTC_STATE_ADDRESS 0x0000 +#define AR9888_RTC_STATE_COLD_RESET_MASK 0x00000400 +#define AR9888_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR9888_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR9888_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR9888_RTC_STATE_V_MASK 0x00000007 +#define AR9888_RTC_STATE_V_LSB 0 +#define AR9888_RTC_STATE_V_ON 3 +#define AR9888_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR9888_FW_IND_EVENT_PENDING 1 +#define AR9888_FW_IND_INITIALIZED 2 +#define AR9888_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR9888_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR9888_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR9888_PCIE_INTR_CE0_MASK 0x00000800 +#define AR9888_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR9888_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR9888_CPU_INTR_ADDRESS 0x0010 +#define AR9888_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR9888_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR9888_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR9888_SOC_RESET_CONTROL_CE_RST_MASK 0x00040000 +#define AR9888_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR9888_CORE_CTRL_ADDRESS 0x0000 +#define AR9888_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR9888_LOCAL_SCRATCH_OFFSET 0x18 +#define AR9888_CLOCK_GPIO_OFFSET 0xffffffff +#define AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 + +#define AR9888_PCIE_INTR_CE_MASK(n) (AR9888_PCIE_INTR_CE0_MASK << (n)) +#define AR9888_FW_EVENT_PENDING_ADDRESS (AR9888_SOC_CORE_BASE_ADDRESS + AR9888_SCRATCH_3_ADDRESS) +#define AR9888_DRAM_BASE_ADDRESS AR9888_TARG_DRAM_START +#define AR9888_FW_INDICATOR_ADDRESS (AR9888_SOC_CORE_BASE_ADDRESS + AR9888_SCRATCH_3_ADDRESS) +#define AR9888_SYSTEM_SLEEP_OFFSET AR9888_SOC_SYSTEM_SLEEP_OFFSET +#define AR9888_WLAN_SYSTEM_SLEEP_OFFSET AR9888_SOC_SYSTEM_SLEEP_OFFSET +#define AR9888_WLAN_RESET_CONTROL_OFFSET AR9888_SOC_RESET_CONTROL_OFFSET +#define AR9888_CLOCK_CONTROL_OFFSET AR9888_SOC_CLOCK_CONTROL_OFFSET +#define AR9888_CLOCK_CONTROL_SI0_CLK_MASK AR9888_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR9888_RESET_CONTROL_MBOX_RST_MASK MISSING +#define AR9888_RESET_CONTROL_SI0_RST_MASK AR9888_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR9888_GPIO_BASE_ADDRESS AR9888_WLAN_GPIO_BASE_ADDRESS +#define AR9888_GPIO_PIN0_OFFSET AR9888_WLAN_GPIO_PIN0_ADDRESS +#define AR9888_GPIO_PIN1_OFFSET AR9888_WLAN_GPIO_PIN1_ADDRESS +#define AR9888_GPIO_PIN0_CONFIG_MASK AR9888_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR9888_GPIO_PIN1_CONFIG_MASK AR9888_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR9888_SI_BASE_ADDRESS AR9888_WLAN_SI_BASE_ADDRESS +#define AR9888_SCRATCH_BASE_ADDRESS AR9888_SOC_CORE_BASE_ADDRESS +#define AR9888_CPU_CLOCK_OFFSET AR9888_SOC_CPU_CLOCK_OFFSET +#define AR9888_LPO_CAL_OFFSET AR9888_SOC_LPO_CAL_OFFSET +#define AR9888_GPIO_PIN10_OFFSET AR9888_WLAN_GPIO_PIN10_ADDRESS +#define AR9888_GPIO_PIN11_OFFSET AR9888_WLAN_GPIO_PIN11_ADDRESS +#define AR9888_GPIO_PIN12_OFFSET AR9888_WLAN_GPIO_PIN12_ADDRESS +#define AR9888_GPIO_PIN13_OFFSET AR9888_WLAN_GPIO_PIN13_ADDRESS +#define AR9888_CPU_CLOCK_STANDARD_LSB AR9888_SOC_CPU_CLOCK_STANDARD_LSB +#define AR9888_CPU_CLOCK_STANDARD_MASK AR9888_SOC_CPU_CLOCK_STANDARD_MASK +#define AR9888_LPO_CAL_ENABLE_LSB AR9888_SOC_LPO_CAL_ENABLE_LSB +#define AR9888_LPO_CAL_ENABLE_MASK AR9888_SOC_LPO_CAL_ENABLE_MASK +#define AR9888_ANALOG_INTF_BASE_ADDRESS AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR9888_MBOX_BASE_ADDRESS MISSING +#define AR9888_INT_STATUS_ENABLE_ERROR_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_ERROR_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_CPU_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_CPU_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define AR9888_COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define AR9888_COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_ADDRESS MISSING +#define AR9888_CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define AR9888_CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define AR9888_HOST_INT_STATUS_ADDRESS MISSING +#define AR9888_CPU_INT_STATUS_ADDRESS MISSING +#define AR9888_ERROR_INT_STATUS_ADDRESS MISSING +#define AR9888_ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define AR9888_ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define AR9888_ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define AR9888_ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define AR9888_COUNT_DEC_ADDRESS MISSING +#define AR9888_HOST_INT_STATUS_CPU_MASK MISSING +#define AR9888_HOST_INT_STATUS_CPU_LSB MISSING +#define AR9888_HOST_INT_STATUS_ERROR_MASK MISSING +#define AR9888_HOST_INT_STATUS_ERROR_LSB MISSING +#define AR9888_HOST_INT_STATUS_COUNTER_MASK MISSING +#define AR9888_HOST_INT_STATUS_COUNTER_LSB MISSING +#define AR9888_RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define AR9888_WINDOW_DATA_ADDRESS MISSING +#define AR9888_WINDOW_READ_ADDR_ADDRESS MISSING +#define AR9888_WINDOW_WRITE_ADDR_ADDRESS MISSING + +struct targetdef_s ar9888_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR9888_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR9888_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR9888_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR9888_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR9888_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR9888_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR9888_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR9888_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR9888_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR9888_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR9888_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR9888_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR9888_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR9888_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR9888_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR9888_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR9888_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR9888_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR9888_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR9888_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR9888_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR9888_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR9888_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR9888_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR9888_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR9888_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR9888_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR9888_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR9888_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR9888_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR9888_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR9888_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR9888_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR9888_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR9888_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR9888_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR9888_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR9888_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR9888_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR9888_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR9888_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR9888_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR9888_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR9888_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR9888_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR9888_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR9888_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR9888_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR9888_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR9888_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR9888_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR9888_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR9888_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR9888_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR9888_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR9888_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR9888_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR9888_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR9888_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR9888_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR9888_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR9888_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR9888_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR9888_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR9888_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR9888_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR9888_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR9888_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR9888_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR9888_CE_COUNT, + .d_PCIE_INTR_ENABLE_ADDRESS = AR9888_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR9888_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR9888_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR9888_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR9888_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR9888_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR9888_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR9888_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR9888_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR9888_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR9888_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR9888_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR9888_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_1_KEY_ID_OCT_MASK = AR9888_RX_MSDU_END_1_KEY_ID_OCT_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_LSB = AR9888_RX_MSDU_END_1_KEY_ID_OCT_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR9888_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR9888_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR9888_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR9888_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR9888_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR9888_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR9888_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR9888_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR9888_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR9888_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR9888_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR9888_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR9888_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR9888_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR9888_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR9888_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR9888_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR9888_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR9888_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR9888_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR9888_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR9888_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR9888_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR9888_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR9888_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR9888_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR9888_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR9888_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR9888_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR9888_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR9888_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR9888_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR9888_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR9888_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR9888_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR9888_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR9888_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR9888_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR9888_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR9888_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR9888_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR9888_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR9888_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR9888_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR9888_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR9888_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR9888_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR9888_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR9888_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR9888_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR9888_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR9888_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + + .d_PCIE_INTR_CAUSE_ADDRESS = AR9888_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR9888_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR9888_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR9888_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR9888_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR9888_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR9888_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, +}; + +struct hostdef_s ar9888_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR9888_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR9888_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR9888_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR9888_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR9888_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR9888_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR9888_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR9888_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR9888_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR9888_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR9888_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR9888_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR9888_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR9888_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR9888_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR9888_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR9888_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR9888_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR9888_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR9888_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR9888_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR9888_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR9888_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR9888_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR9888_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR9888_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR9888_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR9888_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR9888_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR9888_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR9888_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR9888_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR9888_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR9888_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR9888_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR9888_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR9888_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR9888_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR9888_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR9888_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR9888_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR9888_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR9888_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR9888_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR9888_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb.c new file mode 100644 index 000000000000..a3bf77d30e97 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb.c @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "adf_net_types.h" +#include +#include "a_types.h" +#include "athdefs.h" +#include "a_osapi.h" +#include +#include "hif_usb_internal.h" +#include +#include +#include +#include +#define ATH_MODULE_NAME hif +#include + +#define USB_HIF_USE_SINGLE_PIPE_FOR_DATA +#define USB_HIF_TARGET_CREDIT_SIZE 1664 +#ifdef DEBUG +static ATH_DEBUG_MASK_DESCRIPTION g_HIFDebugDescription[] = { + {USB_HIF_DEBUG_CTRL_TRANS, "Control Transfers"}, + {USB_HIF_DEBUG_BULK_IN, "BULK In Transfers"}, + {USB_HIF_DEBUG_BULK_OUT, "BULK Out Transfers"}, + {USB_HIF_DEBUG_DUMP_DATA, "Dump data"}, + {USB_HIF_DEBUG_ENUM, "Enumeration"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, + "hif", + "USB Host Interface", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | + USB_HIF_DEBUG_ENUM, + ATH_DEBUG_DESCRIPTION_COUNT + (g_HIFDebugDescription), + g_HIFDebugDescription); + +#endif + +/* use credit flow control over HTC */ +unsigned int htc_credit_flow; +module_param(htc_credit_flow, uint, 0644); + +#ifdef USB_ISOC_SUPPORT +unsigned int hif_usb_isoch_vo = 1; +#else +unsigned int hif_usb_isoch_vo; +#endif +module_param(hif_usb_isoch_vo, uint, 0644); +unsigned int hif_usb_disable_rxdata2 = 1; +module_param(hif_usb_disable_rxdata2, uint, 0644); + +unsigned int hif_usbaudioclass; +module_param(hif_usbaudioclass, uint, 0644); + +static void usb_hif_destroy(HIF_DEVICE_USB *device); +static HIF_DEVICE_USB *usb_hif_create(struct usb_interface *interface); + +OSDRV_CALLBACKS osDrvcallback; + +int notifyDeviceInsertedHandler(void *hHIF) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + osDrvcallback.deviceInsertedHandler(osDrvcallback.context, hHIF); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + complete_and_exit(NULL, 0); + return 0; +} + +int notifyDeviceSurprisedRemovedHandler(void *context) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) context; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + osDrvcallback.deviceRemovedHandler(device->claimed_context, device); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + complete_and_exit(NULL, 0); + return 0; +} + +int HIF_USBDeviceInserted(struct usb_interface *interface, hif_handle_t hif_hdl) +{ + HIF_DEVICE_USB *device = NULL; + int retval = -1; + struct hif_usb_softc *sc = hif_hdl; + struct usb_device *udev = interface_to_usbdev(interface); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("BCDDevice : %x\n", + udev->descriptor.bcdDevice)); + + do { + + device = usb_hif_create(interface); + if (NULL == device) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("device is NULL\n")); + break; + } + device->sc = sc; + sc->hif_device = (HIF_DEVICE *) device; + retval = 0; + + } while (FALSE); + + if ((device != NULL) && (retval < 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("abnormal condition\n")); + usb_hif_destroy(device); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + return retval; +} + +void HIF_USBDeviceDetached(struct usb_interface *interface, + a_uint8_t surprise_removed) +{ + HIF_DEVICE_USB *device; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + do { + + device = (HIF_DEVICE_USB *) usb_get_intfdata(interface); + if (NULL == device) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("device is NULL\n")); + break; + } + + device->surpriseRemoved = surprise_removed; + /* inform upper layer if it is still interested */ + if (surprise_removed + && (osDrvcallback.deviceRemovedHandler != NULL) + && (device->claimed_context != NULL)) { + osDrvcallback.deviceRemovedHandler(device-> + claimed_context, + device); + } + + usb_hif_destroy(device); + athdiag_procfs_remove(); + } while (FALSE); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + +} + +static void usb_hif_usb_transmit_complete(struct urb *urb) +{ + HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; + adf_nbuf_t buf; + HIF_USB_PIPE *pipe = urb_context->pipe; + struct HIFSendContext *pSendContext; + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, + ("+%s: pipe: %d, stat:%d, len:%d\n", __func__, + pipe->logical_pipe_num, urb->status, + urb->actual_length)); + + /* this urb is not pending anymore */ + usb_hif_remove_pending_transfer(urb_context); + + if (urb->status != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: pipe: %d, failed:%d\n", + __func__, + pipe->logical_pipe_num, + urb->status)); + } + + a_mem_trace(urb_context->buf); + buf = urb_context->buf; + pSendContext = urb_context->pSendContext; + + if (pSendContext->bNewAlloc) { + adf_os_mem_free((void *)pSendContext); + } else { + adf_nbuf_pull_head(buf, pSendContext->head_data_len); + } + + urb_context->buf = NULL; + usb_hif_cleanup_transmit_urb(urb_context); + +#if 0 + if (pipe->urbcnt >= pipe->urb_cnt_thresh) + /* TBD */ +#endif + + /* note: queue implements a lock */ + skb_queue_tail(&pipe->io_comp_queue, buf); +#ifdef HIF_USB_TASKLET + tasklet_schedule(&pipe->io_complete_tasklet); +#else + schedule_work(&pipe->io_complete_work); +#endif + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, ("-%s\n", __func__)); +} + +static A_STATUS HIFSend_internal(HIF_DEVICE *hifDevice, a_uint8_t PipeID, + adf_nbuf_t hdr_buf, adf_nbuf_t buf, unsigned int nbytes) +{ + A_STATUS status = A_OK; + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + HIF_USB_PIPE *pipe = &device->pipes[PipeID]; + HIF_URB_CONTEXT *urb_context; + A_UINT8 *data; + A_UINT32 len; + struct urb *urb; + int usb_status; + int i; + struct HIFSendContext *pSendContext; + int frag_count = 0, head_data_len, tmp_frag_count = 0; + unsigned char *pData; + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, ("+%s pipe : %d, buf:0x%p\n", + __func__, PipeID, buf)); + + a_mem_trace(buf); + + frag_count = adf_nbuf_get_num_frags(buf); + if (frag_count > 1) { /* means have extra fragment buf in skb */ + /* header data length should be total sending length substract + * internal data length of netbuf + * | HIFSendContext | fragments except internal buffer | + * netbuf->data + */ + head_data_len = sizeof(struct HIFSendContext); + while (tmp_frag_count < (frag_count - 1)) { + head_data_len = + head_data_len + adf_nbuf_get_frag_len(buf, + tmp_frag_count); + tmp_frag_count = tmp_frag_count + 1; + } + } else { + /* + * | HIFSendContext | netbuf->data + */ + head_data_len = sizeof(struct HIFSendContext); + } + + /* Check whether head room is enough to save extra head data */ + if (head_data_len <= adf_nbuf_headroom(buf)) { + pSendContext = (struct HIFSendContext *)adf_nbuf_push_head(buf, + head_data_len); + pSendContext->bNewAlloc = FALSE; + } else { + pSendContext = adf_os_mem_alloc(NULL, + sizeof + (struct + HIFSendContext) + + + head_data_len + + + nbytes); + pSendContext->bNewAlloc = TRUE; + } + pSendContext->netbuf = buf; + pSendContext->pDev = hifDevice; + pSendContext->transferID = PipeID; + pSendContext->head_data_len = head_data_len; + /* + * Copy data to head part of netbuf or head of allocated buffer. + * if buffer is new allocated, the last buffer should be copied also. + * It assume last fragment is internal buffer of netbuf + * sometime total length of fragments larger than nbytes + */ + pData = (unsigned char *)pSendContext + sizeof(struct HIFSendContext); + for (i = 0; i < (pSendContext->bNewAlloc ? frag_count : frag_count - 1); + i++) { + int frag_len = adf_nbuf_get_frag_len(buf, i); + unsigned char *frag_addr = adf_nbuf_get_frag_vaddr(buf, i); + memcpy(pData, frag_addr, frag_len); + pData += frag_len; + } + /* Reset pData pointer and send out */ + pData = (unsigned char *)pSendContext + sizeof(struct HIFSendContext); + + do { + urb_context = usb_hif_alloc_urb_from_pipe(pipe); + if (NULL == urb_context) { + /* TODO : note, it is possible to run out of urbs if 2 + * endpoints map to the same pipe ID + */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s pipe:%d no urbs left. URB Cnt : %d\n", + __func__, PipeID, pipe->urb_cnt)); + status = A_NO_RESOURCE; + break; + } + urb_context->pSendContext = pSendContext; + urb = urb_context->urb; + urb_context->buf = buf; + data = pData; + len = nbytes; + + usb_fill_bulk_urb(urb, + device->udev, + pipe->usb_pipe_handle, + data, + (len % pipe->max_packet_size) == + 0 ? (len + 1) : len, + usb_hif_usb_transmit_complete, urb_context); + + if ((len % pipe->max_packet_size) == 0) { + /* hit a max packet boundary on this pipe */ + /* urb->transfer_flags |= URB_ZERO_PACKET; */ + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, ( + "athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes\n", + pipe->logical_pipe_num, pipe->usb_pipe_handle, + pipe->ep_address, nbytes)); + + usb_hif_enqueue_pending_transfer(pipe, urb_context); + usb_status = usb_submit_urb(urb, GFP_ATOMIC); + if (usb_status) { + if (pSendContext->bNewAlloc) + adf_os_mem_free(pSendContext); + else + adf_nbuf_pull_head(buf, head_data_len); + urb_context->buf = NULL; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "athusb : usb bulk transmit failed %d\n", + usb_status)); + usb_hif_remove_pending_transfer(urb_context); + usb_hif_cleanup_transmit_urb(urb_context); + status = A_ECOMM; + break; + } + + } while (FALSE); + + if (A_FAILED(status) && (status != A_NO_RESOURCE)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb send failed %d\n", status)); + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, + ("-%s pipe : %d\n", __func__, PipeID)); + + return status; +} + +/* Send the entire buffer */ +A_STATUS HIFSend(HIF_DEVICE *hif_device, a_uint8_t pipe, adf_nbuf_t hdr_buf, + adf_nbuf_t netbuf) +{ + return HIFSend_head(hif_device, pipe, 0, adf_nbuf_len(netbuf), netbuf); +} + +A_STATUS +HIFSend_head(HIF_DEVICE *hif_device, + a_uint8_t pipe, unsigned int transfer_id, unsigned int nbytes, + adf_nbuf_t nbuf) +{ + A_STATUS status = EOK; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + status = HIFSend_internal(hif_device, pipe, NULL, nbuf, nbytes); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + + return status; +} + +a_uint16_t HIFGetFreeQueueNumber(HIF_DEVICE *hifDevice, a_uint8_t PipeID) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + return device->pipes[PipeID].urb_cnt; +} + +a_uint16_t HIFGetMaxQueueNumber(HIF_DEVICE *hifDevice, a_uint8_t PipeID) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + return device->pipes[PipeID].urb_alloc; +} + +void HIFPostInit(HIF_DEVICE *hifDevice, void *unused, + MSG_BASED_HIF_CALLBACKS *callbacks) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + + A_MEMCPY(&device->htcCallbacks.Context, callbacks, + sizeof(MSG_BASED_HIF_CALLBACKS)); +} + +void HIFDetachHTC(HIF_DEVICE *hifDevice) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + + usb_hif_flush_all(device); + + A_MEMZERO(&device->htcCallbacks, sizeof(MSG_BASED_HIF_CALLBACKS)); +} + +static void usb_hif_destroy(HIF_DEVICE_USB *device) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + usb_hif_flush_all(device); + + usb_hif_cleanup_pipe_resources(device); + + usb_set_intfdata(device->interface, NULL); + + if (device->diag_cmd_buffer != NULL) + adf_os_mem_free(device->diag_cmd_buffer); + + if (device->diag_resp_buffer != NULL) + adf_os_mem_free(device->diag_resp_buffer); + + adf_os_mem_free(device); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +static HIF_DEVICE_USB *usb_hif_create(struct usb_interface *interface) +{ + HIF_DEVICE_USB *device = NULL; + struct usb_device *dev = interface_to_usbdev(interface); + A_STATUS status = A_OK; + int i; + HIF_USB_PIPE *pipe; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + do { + + device = adf_os_mem_alloc(NULL, sizeof(*device)); + if (NULL == device) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("device is NULL\n")); + break; + } + + adf_os_mem_zero(device, sizeof(*device)); + usb_set_intfdata(interface, device); + spin_lock_init(&(device->cs_lock)); + spin_lock_init(&(device->rx_lock)); + spin_lock_init(&(device->tx_lock)); + device->udev = dev; + device->interface = interface; + + for (i = 0; i < HIF_USB_PIPE_MAX; i++) { + pipe = &device->pipes[i]; +#ifdef HIF_USB_TASKLET + tasklet_init(&pipe->io_complete_tasklet, usb_hif_io_comp_tasklet, + (long unsigned int)pipe); +#else + INIT_WORK(&pipe->io_complete_work, + usb_hif_io_comp_work); +#endif + skb_queue_head_init(&pipe->io_comp_queue); + } + + device->diag_cmd_buffer = adf_os_mem_alloc(NULL, + USB_CTRL_MAX_DIAG_CMD_SIZE); + if (NULL == device->diag_cmd_buffer) { + status = A_NO_MEMORY; + break; + } + device->diag_resp_buffer = adf_os_mem_alloc(NULL, + USB_CTRL_MAX_DIAG_RESP_SIZE); + if (NULL == device->diag_resp_buffer) { + status = A_NO_MEMORY; + break; + } + + status = usb_hif_setup_pipe_resources(device); + + } while (FALSE); + + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("abnormal condition\n")); + usb_hif_destroy(device); + device = NULL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + return device; +} + +A_STATUS HIFStart(HIF_DEVICE *hifDevice) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + usb_hif_prestart_recv_pipes(device); + + /* set the TX resource avail threshold for each TX pipe */ + for (i = HIF_TX_CTRL_PIPE; i <= HIF_TX_DATA_HP_PIPE; i++) { + device->pipes[i].urb_cnt_thresh = + device->pipes[i].urb_alloc / 2; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + return A_OK; +} + +void HIFStop(HIF_DEVICE *hifDevice) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hifDevice; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + usb_hif_flush_all(device); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +void HIFGetDefaultPipe(HIF_DEVICE *hifDevice, a_uint8_t *ULPipe, + a_uint8_t *DLPipe) +{ + *ULPipe = HIF_TX_CTRL_PIPE; + *DLPipe = HIF_RX_CTRL_PIPE; +} + +#if defined(USB_MULTI_IN_TEST) || defined(USB_ISOC_TEST) +int +HIFMapServiceToPipe(HIF_DEVICE *hif_device, a_uint16_t ServiceId, + a_uint8_t *ULPipe, a_uint8_t *DLPipe, int *ul_is_polled, + int *dl_is_polled) +{ + A_STATUS status = A_OK; + + switch (ServiceId) { + case HTC_CTRL_RSVD_SVC: + case WMI_CONTROL_SVC: + case HTC_RAW_STREAMS_SVC: + *ULPipe = HIF_TX_CTRL_PIPE; + *DLPipe = HIF_RX_DATA_PIPE; + break; + case WMI_DATA_BE_SVC: + *ULPipe = HIF_TX_DATA_LP_PIPE; + *DLPipe = HIF_RX_DATA_PIPE; + break; + case WMI_DATA_BK_SVC: + *ULPipe = HIF_TX_DATA_MP_PIPE; + *DLPipe = HIF_RX_DATA2_PIPE; + break; + case WMI_DATA_VI_SVC: + *ULPipe = HIF_TX_DATA_HP_PIPE; + *DLPipe = HIF_RX_DATA_PIPE; + break; + case WMI_DATA_VO_SVC: + *ULPipe = HIF_TX_DATA_LP_PIPE; + *DLPipe = HIF_RX_DATA_PIPE; + break; + default: + status = A_ENOTSUP; + break; + } + + return status; +} +#else +int +HIFMapServiceToPipe(HIF_DEVICE *hif_device, a_uint16_t ServiceId, + a_uint8_t *ULPipe, a_uint8_t *DLPipe, int *ul_is_polled, + int *dl_is_polled) +{ + A_STATUS status = A_OK; + + switch (ServiceId) { + case HTC_CTRL_RSVD_SVC: + case WMI_CONTROL_SVC: + *ULPipe = HIF_TX_CTRL_PIPE; + *DLPipe = HIF_RX_DATA_PIPE; + break; + case WMI_DATA_BE_SVC: + case WMI_DATA_BK_SVC: + *ULPipe = HIF_TX_DATA_LP_PIPE; + if (hif_usb_disable_rxdata2) + *DLPipe = HIF_RX_DATA_PIPE; + else + *DLPipe = HIF_RX_DATA2_PIPE; + break; + case WMI_DATA_VI_SVC: +#ifdef USB_HIF_USE_SINGLE_PIPE_FOR_DATA + *ULPipe = HIF_TX_DATA_LP_PIPE; +#else + *ULPipe = HIF_TX_DATA_MP_PIPE; +#endif + if (hif_usb_disable_rxdata2) + *DLPipe = HIF_RX_DATA_PIPE; + else + *DLPipe = HIF_RX_DATA2_PIPE; + break; + case WMI_DATA_VO_SVC: +#ifdef USB_HIF_USE_SINGLE_PIPE_FOR_DATA + *ULPipe = HIF_TX_DATA_LP_PIPE; +#else + *ULPipe = HIF_TX_DATA_HP_PIPE; +#endif + if (hif_usb_disable_rxdata2) + *DLPipe = HIF_RX_DATA_PIPE; + else + *DLPipe = HIF_RX_DATA2_PIPE; +#ifdef USB_HIF_TEST_INTERRUPT_IN + *DLPipe = HIF_RX_INT_PIPE; +#endif + break; + case HTC_RAW_STREAMS_SVC: + *ULPipe = HIF_TX_CTRL_PIPE; + *DLPipe = HIF_RX_DATA_PIPE; + break; + case HTT_DATA_MSG_SVC: + *ULPipe = HIF_TX_DATA_LP_PIPE; + if (hif_usb_disable_rxdata2) + *DLPipe = HIF_RX_DATA_PIPE; + else + *DLPipe = HIF_RX_DATA2_PIPE; + break; +#ifdef QCA_TX_HTT2_SUPPORT + case HTT_DATA2_MSG_SVC: + *ULPipe = HIF_TX_DATA_HP_PIPE; + if (hif_usb_disable_rxdata2) + *DLPipe = HIF_RX_DATA_PIPE; + else + *DLPipe = HIF_RX_DATA2_PIPE; + break; +#endif /* QCA_TX_HTT2_SUPPORT */ + default: + status = A_ENOTSUP; + break; + } + + return status; +} +#endif + +static A_STATUS HIFCtrlMsgExchange(HIF_DEVICE_USB *macp, + A_UINT8 SendReqVal, + A_UINT8 *pSendMessage, + A_UINT32 Length, + A_UINT8 ResponseReqVal, + A_UINT8 *pResponseMessage, + A_UINT32 *pResponseLength) +{ + A_STATUS status; + + do { + + /* send command */ + status = usb_hif_submit_ctrl_out(macp, SendReqVal, 0, 0, + pSendMessage, Length); + + if (A_FAILED(status)) + break; + + if (NULL == pResponseMessage) { + /* no expected response */ + break; + } + + /* get response */ + status = usb_hif_submit_ctrl_in(macp, ResponseReqVal, 0, 0, + pResponseMessage, + *pResponseLength); + + if (A_FAILED(status)) + break; + + } while (FALSE); + + return status; +} + +A_STATUS HIFExchangeBMIMsg(HIF_DEVICE *device, + A_UINT8 *pSendMessage, + A_UINT32 Length, + A_UINT8 *pResponseMessage, + A_UINT32 *pResponseLength, A_UINT32 TimeoutMS) +{ + HIF_DEVICE_USB *macp = (HIF_DEVICE_USB *) device; + + return HIFCtrlMsgExchange(macp, + USB_CONTROL_REQ_SEND_BMI_CMD, + pSendMessage, + Length, + USB_CONTROL_REQ_RECV_BMI_RESP, + pResponseMessage, pResponseLength); +} + +A_STATUS HIFConfigureDevice(HIF_DEVICE *hif, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, A_UINT32 configLen) +{ + A_STATUS status = A_OK; + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif; + + switch (opcode) { + + case HIF_DEVICE_GET_OS_DEVICE: + { + HIF_DEVICE_OS_DEVICE_INFO *info = config; + info->pOSDevice = &device->udev->dev; + } + break; + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: + /* provide fake block sizes for mailboxes to satisfy upper layer + * software + */ + ((A_UINT32 *) config)[0] = 16; + ((A_UINT32 *) config)[1] = 16; + ((A_UINT32 *) config)[2] = 16; + ((A_UINT32 *) config)[3] = 16; + break; + default: + status = A_ENOTSUP; + break; + + } + + return status; +} + +A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device) +{ + return A_OK; +} + +A_STATUS HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, + A_UINT32 *data) +{ + HIF_DEVICE_USB *macp = (HIF_DEVICE_USB *) hifDevice; + A_STATUS status; + USB_CTRL_DIAG_CMD_READ *cmd; + A_UINT32 respLength; + + cmd = (USB_CTRL_DIAG_CMD_READ *) macp->diag_cmd_buffer; + + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->Cmd = USB_CTRL_DIAG_CC_READ; + cmd->Address = address; + respLength = sizeof(USB_CTRL_DIAG_RESP_READ); + + status = HIFCtrlMsgExchange(macp, + USB_CONTROL_REQ_DIAG_CMD, + (A_UINT8 *) cmd, + sizeof(*cmd), + USB_CONTROL_REQ_DIAG_RESP, + macp->diag_resp_buffer, &respLength); + + if (A_SUCCESS(status)) { + USB_CTRL_DIAG_RESP_READ *pResp = + (USB_CTRL_DIAG_RESP_READ *) macp->diag_resp_buffer; + *data = pResp->ReadValue; + } + + return status; +} + +A_STATUS HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, + A_UINT32 data) +{ + HIF_DEVICE_USB *macp = (HIF_DEVICE_USB *) hifDevice; + USB_CTRL_DIAG_CMD_WRITE *cmd; + + cmd = (USB_CTRL_DIAG_CMD_WRITE *) macp->diag_cmd_buffer; + + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->Cmd = USB_CTRL_DIAG_CC_WRITE; + cmd->Address = address; + cmd->Value = data; + + return HIFCtrlMsgExchange(macp, + USB_CONTROL_REQ_DIAG_CMD, + (A_UINT8 *) cmd, + sizeof(*cmd), 0, NULL, 0); +} + +void HIFShutDownDevice(HIF_DEVICE *hif) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + if (NULL == hif) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("full shutdown\n")); + /* this is a full driver shutdown */ + } else { + /* perform any actions to shutdown specific device */ + usb_hif_flush_all(device); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +void HIFReleaseDevice(HIF_DEVICE *hif) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + device->claimed_context = NULL; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +void HIFClaimDevice(HIF_DEVICE *hif, void *claimedContext) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif; + device->claimed_context = claimedContext; +} + +A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HIFInit\n")); + + A_MEMZERO(&osDrvcallback, sizeof(osDrvcallback)); + + A_REGISTER_MODULE_DEBUG_INFO(hif); + + osDrvcallback.deviceInsertedHandler = callbacks->deviceInsertedHandler; + osDrvcallback.deviceRemovedHandler = callbacks->deviceRemovedHandler; + osDrvcallback.deviceSuspendHandler = callbacks->deviceSuspendHandler; + osDrvcallback.deviceResumeHandler = callbacks->deviceResumeHandler; + osDrvcallback.deviceWakeupHandler = callbacks->deviceWakeupHandler; + osDrvcallback.context = callbacks->context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HIFInit\n")); + return A_OK; +} + +#ifdef ATH_BUS_PM +void HIFDeviceSuspend(HIF_DEVICE *dev) +{ + HIF_DEVICE_USB *macp = (HIF_DEVICE_USB *) dev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + if (osDrvcallback.deviceSuspendHandler) + osDrvcallback.deviceSuspendHandler(macp->claimed_context); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +void HIFDeviceResume(HIF_DEVICE *dev) +{ + HIF_DEVICE_USB *macp = (HIF_DEVICE_USB *) dev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + if (osDrvcallback.deviceResumeHandler) + osDrvcallback.deviceResumeHandler(macp->claimed_context); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} +#endif + +void HIFDumpInfo(HIF_DEVICE *hif) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif; + HIF_USB_PIPE *pipe = NULL; + struct usb_host_interface *iface_desc = NULL; + struct usb_endpoint_descriptor *ep_desc; + A_UINT8 i = 0; + for (i = 0; i < HIF_USB_PIPE_MAX; i++) { + pipe = &device->pipes[i]; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "PipeIndex : %d URB Cnt : %d PipeHandle : %x\n", + i, pipe->urb_cnt, + pipe->usb_pipe_handle)); + if (usb_pipeisoc(pipe->usb_pipe_handle)) + pr_info("Pipe Type ISOC\n"); + else if (usb_pipebulk(pipe->usb_pipe_handle)) + pr_info("Pipe Type BULK\n"); + else if (usb_pipeint(pipe->usb_pipe_handle)) + pr_info("Pipe Type INT\n"); + else if (usb_pipecontrol(pipe->usb_pipe_handle)) + pr_info("Pipe Type control\n"); + } + + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + ep_desc = &iface_desc->endpoint[i].desc; + if (ep_desc) { + pr_info( + "ep_desc : %p Index : %d: DescType : %d Addr : %d Maxp : %d Atrrib : %d\n", + ep_desc, i, + ep_desc->bDescriptorType, + ep_desc->bEndpointAddress, ep_desc->wMaxPacketSize, + ep_desc->bmAttributes); + if ((ep_desc) + && (usb_endpoint_type(ep_desc) == + USB_ENDPOINT_XFER_ISOC)) { + pr_info("ISOC EP Detected\n"); + } + } + } + +} + +void HIFDump(HIF_DEVICE *hif_device, u_int8_t cmd_id, bool start) +{ +/* TO DO... */ +} + +void HIFFlushSurpriseRemove(HIF_DEVICE *hif_device) +{ +/* TO DO... */ +} + +A_STATUS +HIFDiagReadMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, + int nbytes) +{ + A_STATUS status = EOK; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + if ((address & 0x3) || ((uintptr_t)data & 0x3)) { + return (-EIO); + } + + while ((nbytes >= 4) && + (A_OK == (status = HIFDiagReadAccess(hif_device, address, + (A_UINT32*)data)))) { + + nbytes -= sizeof(A_UINT32); + address += sizeof(A_UINT32); + data += sizeof(A_UINT32); + + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + return status; +} + +A_STATUS +HIFDiagWriteMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes) +{ + A_STATUS status = EOK; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + if ((address & 0x3) || ((uintptr_t)data & 0x3)) { + return (-EIO); + } + + while ((nbytes >= 4) && + (A_OK == (status = HIFDiagWriteAccess(hif_device, address, + *((A_UINT32*)data))))) { + + nbytes -= sizeof(A_UINT32); + address += sizeof(A_UINT32); + data += sizeof(A_UINT32); + + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + return status; +} + +void *hif_get_targetdef(HIF_DEVICE *hif_device) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif_device; + struct hif_usb_softc *sc = device->sc; + + return sc->targetdef; +} + +void HIFSendCompleteCheck(HIF_DEVICE *hif_device, a_uint8_t pipe, int force) +{ +} + +void HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device) +{ +} + +/* diagnostic command defnitions */ +#define USB_CTRL_DIAG_CC_READ 0 +#define USB_CTRL_DIAG_CC_WRITE 1 +#define USB_CTRL_DIAG_CC_WARM_RESET 2 +A_STATUS HIFDiagWriteWARMRESET(struct usb_interface *interface, + A_UINT32 address, A_UINT32 data) +{ + HIF_DEVICE_USB *hHIF_DEV; + A_STATUS status = EOK; + USB_CTRL_DIAG_CMD_WRITE *cmd; + + hHIF_DEV = (HIF_DEVICE_USB *) usb_get_intfdata(interface); + cmd = (USB_CTRL_DIAG_CMD_WRITE *) hHIF_DEV->diag_cmd_buffer; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + A_MEMZERO(cmd, sizeof(USB_CTRL_DIAG_CMD_WRITE)); + cmd->Cmd = USB_CTRL_DIAG_CC_WARM_RESET; + cmd->Address = address; + cmd->Value = data; + + status = HIFCtrlMsgExchange(hHIF_DEV, + USB_CONTROL_REQ_DIAG_CMD, + (A_UINT8 *) cmd, + sizeof(USB_CTRL_DIAG_CMD_WRITE), + 0, NULL, 0); + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("-%s HIFCtrlMsgExchange fail\n", + __func__)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + return status; +} +void HIFsuspendwow(HIF_DEVICE *hif_device) +{ + printk(KERN_INFO "HIFsuspendwow TODO\n"); +} + +void HIFSetBundleMode(HIF_DEVICE *hif_device, bool enabled, int rx_bundle_cnt) +{ + HIF_DEVICE_USB *device = (HIF_DEVICE_USB *) hif_device; + + device->is_bundle_enabled = enabled; + device->rx_bundle_cnt = rx_bundle_cnt; + if (device->is_bundle_enabled && (device->rx_bundle_cnt == 0)) { + device->rx_bundle_cnt = 1; + } + device->rx_bundle_buf_len = device->rx_bundle_cnt * + HIF_USB_RX_BUNDLE_ONE_PKT_SIZE; + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, + ("athusb bundle %s cnt %d\n", + enabled ? "enabled" : "disabled", + rx_bundle_cnt)); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb_internal.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb_internal.h new file mode 100644 index 000000000000..fa9636184ee7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/hif_usb_internal.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#ifndef _HIF_USB_INTERNAL_H +#define _HIF_USB_INTERNAL_H + +#include +#include + +#include "a_types.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "hif_msg_based.h" +#include "a_usb_defs.h" +#include +#include + +#define TX_URB_COUNT 32 +#define RX_URB_COUNT 32 + +#define HIF_USB_RX_BUFFER_SIZE (1792 + 8) +#define HIF_USB_RX_BUNDLE_ONE_PKT_SIZE (1792 + 8) + +/* USB Endpoint definition */ +typedef enum { + HIF_TX_CTRL_PIPE = 0, + HIF_TX_DATA_LP_PIPE, + HIF_TX_DATA_MP_PIPE, + HIF_TX_DATA_HP_PIPE, + HIF_RX_CTRL_PIPE, + HIF_RX_DATA_PIPE, + HIF_RX_DATA2_PIPE, + HIF_RX_INT_PIPE, + HIF_USB_PIPE_MAX +} HIF_USB_PIPE_ID; + +#define HIF_USB_PIPE_INVALID HIF_USB_PIPE_MAX + +/* debug masks */ +#define USB_HIF_DEBUG_CTRL_TRANS ATH_DEBUG_MAKE_MODULE_MASK(0) +#define USB_HIF_DEBUG_BULK_IN ATH_DEBUG_MAKE_MODULE_MASK(1) +#define USB_HIF_DEBUG_BULK_OUT ATH_DEBUG_MAKE_MODULE_MASK(2) +#define USB_HIF_DEBUG_ENUM ATH_DEBUG_MAKE_MODULE_MASK(3) +#define USB_HIF_DEBUG_DUMP_DATA ATH_DEBUG_MAKE_MODULE_MASK(4) +#define USB_HIF_SUSPEND ATH_DEBUG_MAKE_MODULE_MASK(5) +#define USB_HIF_ISOC_SUPPORT ATH_DEBUG_MAKE_MODULE_MASK(6) +struct _HIF_DEVICE_USB; +struct _HIF_USB_PIPE; + +/* + * Data structure to record required sending context data + */ +struct HIFSendContext { + A_BOOL bNewAlloc; + HIF_DEVICE *pDev; + adf_nbuf_t netbuf; + unsigned int transferID; + unsigned int head_data_len; +}; + +typedef struct _HIF_URB_CONTEXT { + DL_LIST link; + struct _HIF_USB_PIPE *pipe; + adf_nbuf_t buf; + struct urb *urb; + struct HIFSendContext *pSendContext; +} HIF_URB_CONTEXT; + +#define HIF_USB_PIPE_FLAG_TX (1 << 0) + +typedef struct _HIF_USB_PIPE { + DL_LIST urb_list_head; + DL_LIST urb_pending_list; + A_INT32 urb_alloc; + A_INT32 urb_cnt; + A_INT32 urb_cnt_thresh; + unsigned int usb_pipe_handle; + A_UINT32 flags; + A_UINT8 ep_address; + A_UINT8 logical_pipe_num; + struct _HIF_DEVICE_USB *device; + A_UINT16 max_packet_size; +#ifdef HIF_USB_TASKLET + struct tasklet_struct io_complete_tasklet; +#else + struct work_struct io_complete_work; +#endif + struct sk_buff_head io_comp_queue; + struct usb_endpoint_descriptor *ep_desc; + A_INT32 urb_prestart_cnt; +} HIF_USB_PIPE; + +typedef struct _HIF_DEVICE_USB { + spinlock_t cs_lock; + spinlock_t tx_lock; + spinlock_t rx_lock; + MSG_BASED_HIF_CALLBACKS htcCallbacks; + struct usb_device *udev; + struct usb_interface *interface; + HIF_USB_PIPE pipes[HIF_USB_PIPE_MAX]; + a_uint8_t surpriseRemoved; + a_uint8_t *diag_cmd_buffer; + a_uint8_t *diag_resp_buffer; + void *claimed_context; + struct hif_usb_softc *sc; + A_BOOL is_bundle_enabled; + A_UINT16 rx_bundle_cnt; + A_UINT32 rx_bundle_buf_len; +} HIF_DEVICE_USB; +extern unsigned int hif_usb_disable_rxdata2; + +extern A_STATUS usb_hif_submit_ctrl_in(HIF_DEVICE_USB *macp, + a_uint8_t req, + a_uint16_t value, + a_uint16_t index, + void *data, a_uint32_t size); + +extern A_STATUS usb_hif_submit_ctrl_out(HIF_DEVICE_USB *macp, + a_uint8_t req, + a_uint16_t value, + a_uint16_t index, + void *data, a_uint32_t size); + +extern int HIF_USBDeviceInserted(struct usb_interface *interface, + hif_handle_t hif_hdl); +extern void HIF_USBDeviceDetached(struct usb_interface *interface, + a_uint8_t surprise_removed); +#ifdef ATH_BUS_PM +extern void HIFDeviceSuspend(HIF_DEVICE *dev); +extern void HIFDeviceResume(HIF_DEVICE *dev); +#endif +extern A_STATUS usb_hif_setup_pipe_resources(HIF_DEVICE_USB *device); +extern void usb_hif_cleanup_pipe_resources(HIF_DEVICE_USB *device); +extern void usb_hif_prestart_recv_pipes(HIF_DEVICE_USB *device); +extern void usb_hif_start_recv_pipes(HIF_DEVICE_USB *device); +extern void usb_hif_flush_all(HIF_DEVICE_USB *device); +extern void usb_hif_cleanup_transmit_urb(HIF_URB_CONTEXT *urb_context); +extern void usb_hif_enqueue_pending_transfer(HIF_USB_PIPE *pipe, + HIF_URB_CONTEXT *urb_context); +extern void usb_hif_remove_pending_transfer(HIF_URB_CONTEXT *urb_context); +extern HIF_URB_CONTEXT *usb_hif_alloc_urb_from_pipe(HIF_USB_PIPE *pipe); +#ifdef HIF_USB_TASKLET +extern void usb_hif_io_comp_tasklet(long unsigned int context); +#else +extern void usb_hif_io_comp_work(struct work_struct *work); +#endif +/* Support for USB Suspend / Resume */ +extern void usb_hif_suspend(struct usb_interface *interface); +extern void usb_hif_resume(struct usb_interface *interface); +A_STATUS HIFDiagWriteWARMRESET(struct usb_interface *interface, + A_UINT32 address, A_UINT32 data); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.c new file mode 100644 index 000000000000..6bc42a66f8ef --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.c @@ -0,0 +1,677 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#include +#include +#include +#include +#include +#include +#include "if_usb.h" +#include "hif_usb_internal.h" +#include "bmi_msg.h" /* TARGET_TYPE_ */ +#include "regtable.h" +#include "ol_fw.h" +#include +#include "vos_api.h" +#include "wma_api.h" +#include "wlan_hdd_main.h" +#include "epping_main.h" +#include "vos_sched.h" + +#ifndef REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "pktlog_ac_api.h" +#include "pktlog_ac.h" +#endif +#define VENDOR_ATHR 0x0CF3 +#define AR9888_DEVICE_ID (0x003c) +#define AR6320_DEVICE_ID (0x9378) +#define DELAY_FOR_TARGET_READY 200 /* 200ms */ +#define DELAY_INT_FOR_HDD_REMOVE 200 /* 200ms */ +#define HIFDiagWriteCOLDRESET(hifdevice) HIFDiagWriteAccess(sc->hif_device, \ + (ROME_USB_SOC_RESET_CONTROL_COLD_RST_LSB | \ + ROME_USB_RTC_SOC_BASE_ADDRESS), \ + SOC_RESET_CONTROL_COLD_RST_SET(1)) + +unsigned int msienable; +module_param(msienable, int, 0644); +#define HIF_USB_UNLOAD_TIMEOUT (2*HZ) +enum hif_usb_drv_unload_state { + HIF_USB_UNLOAD_STATE_NULL = 0, + HIF_USB_UNLOAD_STATE_DRV_DEREG, + HIF_USB_UNLOAD_STATE_TARGET_RESET, + HIF_USB_UNLOAD_STATE_DEV_DISCONNECTED, +}; + +static int hif_usb_unload_dev_num = -1; +static wait_queue_head_t hif_usb_unload_event_wq; +static atomic_t hif_usb_unload_state; +struct hif_usb_softc *usb_sc = NULL; +static int hif_usb_resume(struct usb_interface *interface); + +static int +hif_usb_configure(struct hif_usb_softc *sc, hif_handle_t *hif_hdl, + struct usb_interface *interface) +{ + int ret = 0; + struct usb_device *dev = interface_to_usbdev(interface); + + if (HIF_USBDeviceInserted(interface, sc)) { + pr_err("ath: %s: Target probe failed.\n", __func__); + ret = -EIO; + goto err_stalled; + } + + if (athdiag_procfs_init(sc) != 0) { + pr_err("athdiag_procfs_init failed\n"); + return A_ERROR; + } + hif_usb_unload_dev_num = dev->devnum; + *hif_hdl = sc->hif_device; + return 0; + +err_stalled: + + return ret; +} + +static void hif_nointrs(struct hif_usb_softc *sc) +{ +} + +static int hif_usb_reboot(struct notifier_block *nb, unsigned long val, + void *v) +{ + struct hif_usb_softc *sc; + sc = container_of(nb, struct hif_usb_softc, reboot_notifier); + /* do cold reset */ + HIFDiagWriteCOLDRESET(sc->hif_device); + return NOTIFY_DONE; +} + +/* + * Disable lpm feature of usb2.0. + */ +static int hif_usb_disable_lpm(struct usb_device *udev) +{ + struct usb_hcd *hcd; + int ret = -EPERM; + pr_info("Enter:%s,Line:%d\n", __func__, __LINE__); + if (!udev || !udev->bus) { + pr_err("Invalid input parameters\n"); + } else { + hcd = bus_to_hcd(udev->bus); + if (udev->usb2_hw_lpm_enabled) { + if (hcd->driver->set_usb2_hw_lpm) { + ret = hcd->driver->set_usb2_hw_lpm(hcd, + udev, FALSE); + if (!ret) { + udev->usb2_hw_lpm_enabled = FALSE; + udev->usb2_hw_lpm_capable = FALSE; + pr_info("%s: LPM is disabled\n", + __func__); + } else { + pr_info("%s: Fail to disable LPM\n", + __func__); + } + } else { + pr_info("%s: hcd doesn't support LPM\n", + __func__); + } + } else { + pr_info("%s: LPM isn't enabled\n", __func__); + } + } + + pr_info("Exit:%s,Line:%d\n", __func__, __LINE__); + return ret; +} + +static int +hif_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + int ret = 0; + struct hif_usb_softc *sc; + struct ol_softc *ol_sc; + struct usb_device *pdev = interface_to_usbdev(interface); + int vendor_id, product_id; + + pr_info("hif_usb_probe\n"); + usb_get_dev(pdev); + vendor_id = le16_to_cpu(pdev->descriptor.idVendor); + product_id = le16_to_cpu(pdev->descriptor.idProduct); + + ret = 0; + + sc = A_MALLOC(sizeof(*sc)); + if (!sc) { + ret = -ENOMEM; + goto err_alloc; + } + + OS_MEMZERO(sc, sizeof(*sc)); + sc->pdev = (void *)pdev; + sc->dev = &pdev->dev; + + sc->aps_osdev.bdev = pdev; + sc->aps_osdev.device = &pdev->dev; + sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_AHB; + sc->devid = id->idProduct; + + adf_os_spinlock_init(&sc->target_lock); + + ol_sc = A_MALLOC(sizeof(*ol_sc)); + if (!ol_sc) + goto err_attach; + OS_MEMZERO(ol_sc, sizeof(*ol_sc)); + ol_sc->sc_osdev = &sc->aps_osdev; + ol_sc->hif_sc = (void *)sc; + sc->ol_sc = ol_sc; + + if ((usb_control_msg(pdev, usb_sndctrlpipe(pdev, 0), + USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0, + HZ)) < 0) { + pr_info("%s[%d]\n\r", __func__, __LINE__); + } + usb_set_interface(pdev, 0, 0); + /* disable lpm to avoid usb2.0 probe timeout */ + hif_usb_disable_lpm(pdev); + + if (hif_usb_configure(sc, &ol_sc->hif_hdl, interface)) + goto err_config; + + ol_sc->enableuartprint = 1; + ol_sc->enablefwlog = 0; + ol_sc->enablesinglebinary = FALSE; + ol_sc->max_no_of_peers = 1; + + init_waitqueue_head(&ol_sc->sc_osdev->event_queue); + + ret = hif_init_adf_ctx(ol_sc); + if (ret == 0) + ret = hdd_wlan_startup(&pdev->dev, ol_sc); + if (ret) { + hif_nointrs(sc); + if (sc->hif_device != NULL) { + ((HIF_DEVICE_USB *)(sc->hif_device))->sc = NULL; + } + athdiag_procfs_remove(); + goto err_config; + } + atomic_set(&sc->hdd_removed, -1); + atomic_set(&sc->hdd_removed_processing, 0); + sc->hdd_removed_wait_cnt = 0; + + sc->interface = interface; + sc->reboot_notifier.notifier_call = hif_usb_reboot; + register_reboot_notifier(&sc->reboot_notifier); + + usb_sc = sc; + return 0; + +err_config: + hif_deinit_adf_ctx(ol_sc); + HIFDiagWriteCOLDRESET(sc->hif_device); + A_FREE(ol_sc); +err_attach: + ret = -EIO; + usb_sc = NULL; + A_FREE(sc); +err_alloc: + usb_put_dev(pdev); + + return ret; +} + +static void hif_usb_remove(struct usb_interface *interface) +{ + HIF_DEVICE_USB *device = usb_get_intfdata(interface); + struct usb_device *udev = interface_to_usbdev(interface); + struct hif_usb_softc *sc = device->sc; + struct ol_softc *scn; + + /* Attach did not succeed, all resources have been + * freed in error handler + */ + if (!sc) + return; + + pr_info("Try to remove hif_usb!\n"); + + /* wait __hdd_wlan_exit until finished and no more than 4 seconds*/ + while(atomic_read(&usb_sc->hdd_removed_processing) == 1 && + usb_sc->hdd_removed_wait_cnt < 20) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(DELAY_INT_FOR_HDD_REMOVE)); + set_current_state(TASK_RUNNING); + usb_sc->hdd_removed_wait_cnt ++; + } + atomic_set(&usb_sc->hdd_removed_processing, 1); + + /* disable lpm to avoid following cold reset will + *cause xHCI U1/U2 timeout + */ + usb_disable_lpm(udev); + + /* wait for disable lpm */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(DELAY_FOR_TARGET_READY)); + set_current_state(TASK_RUNNING); + + /* do cold reset */ + HIFDiagWriteCOLDRESET(sc->hif_device); + + if (usb_sc->suspend_state) { + hif_usb_resume(usb_sc->interface); + } + unregister_reboot_notifier(&sc->reboot_notifier); + usb_put_dev(interface_to_usbdev(interface)); + if (atomic_read(&hif_usb_unload_state) == + HIF_USB_UNLOAD_STATE_DRV_DEREG) + atomic_set(&hif_usb_unload_state, + HIF_USB_UNLOAD_STATE_TARGET_RESET); + scn = sc->ol_sc; + + /* The logp is set by target failure's ol_ramdump_handler. + * Coldreset occurs and do this disconnect cb, try to issue + * offline uevent to restart driver. + */ + if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + /* dispatch 'offline' uevent to restart module */ + kobject_uevent(&scn->adf_dev->dev->kobj, KOBJ_OFFLINE); + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE); + } + + if (atomic_inc_and_test(&usb_sc->hdd_removed)) { +#ifndef REMOVE_PKT_LOG + if (vos_get_conparam() != VOS_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + pktlogmod_exit(scn); +#endif + __hdd_wlan_exit(); + pr_info("Exit HDD wlan... done by %s\n", __func__); + } + + hif_nointrs(sc); + HIF_USBDeviceDetached(interface, 1); + atomic_set(&usb_sc->hdd_removed_processing, 0); + hif_deinit_adf_ctx(scn); + A_FREE(scn); + A_FREE(sc); + usb_sc = NULL; + pr_info("hif_usb_remove!!!!!!\n"); +} + +#ifdef WLAN_LINK_UMAC_SUSPEND_WITH_BUS_SUSPEND +void hdd_suspend_wlan(void (*callback) (void *callbackContext), + void *callbackContext); +#endif + +static int hif_usb_suspend(struct usb_interface *interface, pm_message_t state) +{ + HIF_DEVICE_USB *device = usb_get_intfdata(interface); + struct hif_usb_softc *sc = device->sc; + void *vos = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + v_VOID_t * temp_module; + + printk("Enter:%s,Line:%d\n", __func__,__LINE__); + + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos); + if (!temp_module) { + printk("%s: WDA module is NULL\n", __func__); + return (-1); + } + + if (wma_check_scan_in_progress(temp_module)) { + printk("%s: Scan in progress. Aborting suspend\n", __func__); + return (-1); + } + + /* No need to send WMI_PDEV_SUSPEND_CMDID to FW if WOW is enabled */ + if (wma_is_wow_mode_selected(temp_module)) { + if (wma_enable_wow_in_fw(temp_module, 0)) { + pr_warn("%s[%d]: fail\n", __func__, __LINE__); + return -1; + } + } else if ((PM_EVENT_FREEZE & state.event) == PM_EVENT_FREEZE || + (PM_EVENT_SUSPEND & state.event) == PM_EVENT_SUSPEND || + (PM_EVENT_HIBERNATE & state.event) == PM_EVENT_HIBERNATE) { + if (wma_suspend_target + (vos_get_context(VOS_MODULE_ID_WDA, vos), 0)) { + pr_warn("%s[%d]: fail\n", __func__, __LINE__); + return -1; + } + } + + sc->suspend_state = 1; + usb_hif_flush_all(device); + + printk("Exit:%s,Line:%d\n", __func__,__LINE__); + return 0; +} + +#ifdef WLAN_LINK_UMAC_SUSPEND_WITH_BUS_SUSPEND +void hdd_resume_wlan(void); +#endif + +static int hif_usb_resume(struct usb_interface *interface) +{ + HIF_DEVICE_USB *device = usb_get_intfdata(interface); + struct hif_usb_softc *sc = device->sc; + void *vos = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + v_VOID_t * temp_module; + + printk("Enter:%s,Line:%d\n", __func__,__LINE__); + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos); + if (!temp_module) { + printk("%s: WDA module is NULL\n", __func__); + return (-1); + } + + sc->suspend_state = 0; + usb_hif_start_recv_pipes(device); + +#ifdef USB_HIF_TEST_INTERRUPT_IN + usb_hif_post_recv_transfers(&device->pipes[HIF_RX_INT_PIPE], + HIF_USB_RX_BUFFER_SIZE); +#endif + /* No need to send WMI_PDEV_RESUME_CMDID to FW if WOW is enabled */ + if (!wma_is_wow_mode_selected(temp_module)) { + wma_resume_target(temp_module, 0); + } else if (wma_disable_wow_in_fw(temp_module, 0)) { + pr_warn("%s[%d]: fail\n", __func__, __LINE__); + return (-1); + } + printk("Exit:%s,Line:%d\n", __func__,__LINE__); + return 0; +} + +static int hif_usb_reset_resume(struct usb_interface *intf) +{ + HIF_DEVICE_USB *device = usb_get_intfdata(intf); + struct hif_usb_softc *sc = device->sc; + + printk("Enter:%s,Line:%d \n\r", __func__,__LINE__); + HIFDiagWriteCOLDRESET(sc->hif_device); + printk("Exit:%s,Line:%d \n\r", __func__,__LINE__); + return 0; +} + +static struct usb_device_id hif_usb_id_table[] = { + {USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ATHR, 0x9378, 0xFF, 0xFF, 0xFF)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, hif_usb_id_table); +struct usb_driver hif_usb_drv_id = { + + .name = "hif_usb", + .id_table = hif_usb_id_table, + .probe = hif_usb_probe, + .disconnect = hif_usb_remove, +#ifdef ATH_BUS_PM + .suspend = hif_usb_suspend, + .resume = hif_usb_resume, + .reset_resume = hif_usb_reset_resume, +#endif + .supports_autosuspend = true, +}; + +int hif_init_adf_ctx(void *ol_sc) +{ + adf_os_device_t adf_ctx; + v_CONTEXT_t pVosContext = NULL; + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_usb_softc *hif_sc = (struct hif_usb_softc *)sc->hif_sc; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if(pVosContext == NULL) + return -EFAULT; + + adf_ctx = vos_mem_malloc(sizeof(*adf_ctx)); + if (!adf_ctx) + return -ENOMEM; + vos_mem_zero(adf_ctx, sizeof(*adf_ctx)); + adf_ctx->drv = &hif_sc->aps_osdev; + adf_ctx->drv_hdl = hif_sc->aps_osdev.bdev; + adf_ctx->dev = hif_sc->aps_osdev.device; + sc->adf_dev = adf_ctx; + ((VosContextType*)(pVosContext))->adf_ctx = adf_ctx; + return 0; +} + +void hif_deinit_adf_ctx(void *ol_sc) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + + if (sc == NULL) + return; + if (sc->adf_dev) { + v_CONTEXT_t pVosContext = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + vos_mem_free(sc->adf_dev); + sc->adf_dev = NULL; + if (pVosContext) + ((VosContextType*)(pVosContext))->adf_ctx = NULL; + } +} + +static int hif_usb_dev_notify(struct notifier_block *nb, + unsigned long action, void *dev) +{ + struct usb_device *udev; + int ret = NOTIFY_DONE; + + if (action != USB_DEVICE_REMOVE) + goto done; + + udev = (struct usb_device *) dev; + if (hif_usb_unload_dev_num != udev->devnum) + goto done; + + if (atomic_read(&hif_usb_unload_state) == + HIF_USB_UNLOAD_STATE_TARGET_RESET) { + atomic_set(&hif_usb_unload_state, + HIF_USB_UNLOAD_STATE_DEV_DISCONNECTED); + wake_up(&hif_usb_unload_event_wq); + } + +done: + return ret; +} + +static struct notifier_block hif_usb_dev_nb = { + .notifier_call = hif_usb_dev_notify, +}; +static int is_usb_driver_register = 0; +int hif_register_driver(void) +{ + int status = 0; + int probe_wait_cnt = 0; + is_usb_driver_register = 1; + init_waitqueue_head(&hif_usb_unload_event_wq); + atomic_set(&hif_usb_unload_state, HIF_USB_UNLOAD_STATE_NULL); + usb_register_notify(&hif_usb_dev_nb); + status = usb_register(&hif_usb_drv_id); + + /* wait for usb probe done, 2s at most*/ + while(!usb_sc && probe_wait_cnt < 10) { + A_MSLEEP(200); + probe_wait_cnt++; + } + + if (usb_sc && status == 0) + return 0; + else + return -1; +} + +void hif_unregister_driver(void) +{ + if (is_usb_driver_register) { + long timeleft = 0; + pr_info("Try to unregister hif_driver\n"); + if (usb_sc != NULL) { + /* wait __hdd_wlan_exit until finished and no more than + * 4 seconds + */ + while(usb_sc && + atomic_read(&usb_sc->hdd_removed_processing) == 1 && + usb_sc->hdd_removed_wait_cnt < 20) { + usb_sc->hdd_removed_wait_cnt ++; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies( + DELAY_INT_FOR_HDD_REMOVE)); + set_current_state(TASK_RUNNING); + } + + /* usb_sc is freed by hif_usb_remove */ + if (!usb_sc) + goto deregister; + + atomic_set(&usb_sc->hdd_removed_processing, 1); + + if (usb_sc->suspend_state) { + hif_usb_resume(usb_sc->interface); + } + + if (atomic_inc_and_test(&usb_sc->hdd_removed)) { +#ifndef REMOVE_PKT_LOG + if (vos_get_conparam() != VOS_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) + pktlogmod_exit(usb_sc->ol_sc); +#endif + __hdd_wlan_exit(); + pr_info("Exit HDD wlan... done by %s\n", __func__); + } + atomic_set(&usb_sc->hdd_removed_processing, 0); + } + +deregister: + is_usb_driver_register = 0; + atomic_set(&hif_usb_unload_state, + HIF_USB_UNLOAD_STATE_DRV_DEREG); + usb_deregister(&hif_usb_drv_id); + if (atomic_read(&hif_usb_unload_state) != + HIF_USB_UNLOAD_STATE_TARGET_RESET) + goto finish; + timeleft = wait_event_interruptible_timeout( + hif_usb_unload_event_wq, + atomic_read(&hif_usb_unload_state) == + HIF_USB_UNLOAD_STATE_DEV_DISCONNECTED, + HIF_USB_UNLOAD_TIMEOUT); + if (timeleft <= 0) + pr_err("Fail to wait from DRV_DEREG to DISCONNECT," + "timeleft = %ld \n\r", + timeleft); +finish: + usb_unregister_notify(&hif_usb_dev_nb); + pr_info("hif_unregister_driver!!!!!!\n"); + } +} + +/* Function to set the TXRX handle in the ol_sc context */ +void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + sc->pdev_txrx_handle = txrx_handle; +} + +void hif_disable_isr(void *ol_sc) +{ + /* TODO */ +} + +/* Function to reset SoC */ +void hif_reset_soc(void *ol_sc) +{ + /* TODO */ +} + +void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision) +{ + u_int32_t hif_type, target_type; + A_STATUS rv; + A_INT32 ret = 0; + A_UINT32 chip_id; + struct hif_usb_softc *sc; + + sc = ((struct ol_softc *)ol_sc)->hif_sc; + if (sc->hostdef == NULL && sc->targetdef == NULL) { + switch (((struct ol_softc *)ol_sc)->target_type) + { + case TARGET_TYPE_AR6320: + switch(((struct ol_softc *)ol_sc)->target_version) { + case AR6320_REV1_VERSION: + case AR6320_REV1_1_VERSION: + case AR6320_REV1_3_VERSION: + hif_type = HIF_TYPE_AR6320; + target_type = TARGET_TYPE_AR6320; + break; + case AR6320_REV2_1_VERSION: + case AR6320_REV3_VERSION: + case AR6320_REV3_2_VERSION: + case QCA9377_REV1_1_VERSION: + hif_type = HIF_TYPE_AR6320V2; + target_type = TARGET_TYPE_AR6320V2; + break; + default: + ret = -1; + break; + } + break; + default: + ret = -1; + break; + } + + if (!ret) { + /* assign target register table if we find corresponding type */ + hif_register_tbl_attach(sc, hif_type); + target_register_tbl_attach(sc, target_type); + /* read the chip revision*/ + rv = HIFDiagReadAccess(sc->hif_device, (CHIP_ID_ADDRESS | RTC_SOC_BASE_ADDRESS), &chip_id); + if (rv != A_OK) { + pr_err("ath: HIF_PCIDeviceProbed get chip id val (%d)\n", rv); + } + ((struct ol_softc *)ol_sc)->target_revision = CHIP_ID_REVISION_GET(chip_id); + } + } + + /* we need to get chip revision here */ + *version = ((struct ol_softc *)ol_sc)->target_version; + /* Chip version should be supported, set to 0 for now */ + *revision = ((struct ol_softc *)ol_sc)->target_revision; +} + +void hif_set_fw_info(void *ol_sc, u32 target_fw_version) +{ + ((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version; +} + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.h new file mode 100644 index 000000000000..26c6aa3d3c98 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/if_usb.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#ifndef __ATH_USB_H__ +#define __ATH_USB_H__ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +#include +#else +#include +#endif +#include +#include + +/* + * There may be some pending tx frames during platform suspend. + * Suspend operation should be delayed until those tx frames are + * transfered from the host to target. This macro specifies how + * long suspend thread has to sleep before checking pending tx + * frame count. + */ +#define OL_ATH_TX_DRAIN_WAIT_DELAY 50 /* ms */ +/* + * Wait time (in unit of OL_ATH_TX_DRAIN_WAIT_DELAY) for pending + * tx frame completion before suspend. Refer: hif_pci_suspend() + */ +#define OL_ATH_TX_DRAIN_WAIT_CNT 10 + +#define CONFIG_COPY_ENGINE_SUPPORT /* TBDXXX: here for now */ +#define ATH_DBG_DEFAULT 0 +#include +#include +#include +#include "osapi_linux.h" +#include "hif.h" + +struct hif_usb_softc { + /* For efficiency, should be first in struct */ + struct device *dev; + struct usb_dev *pdev; + struct _NIC_DEV aps_osdev; + struct ol_softc *ol_sc; + /* + * Guard changes to Target HW state and to software + * structures that track hardware state. + */ + adf_os_spinlock_t target_lock; + + HIF_DEVICE *hif_device; + + u16 devid; + struct targetdef_s *targetdef; + struct hostdef_s *hostdef; + struct usb_interface *interface; + struct notifier_block reboot_notifier; /* default mode before reboot */ + u8 suspend_state; + atomic_t hdd_removed; + atomic_t hdd_removed_processing; + int hdd_removed_wait_cnt; + u8 *fw_data; + u32 fw_data_len; +}; +#if defined(CONFIG_ATH_PROCFS_DIAG_SUPPORT) +int athdiag_procfs_init(void *scn); +void athdiag_procfs_remove(void); +#else +static inline int athdiag_procfs_init(void *scn) { return 0; } +static inline void athdiag_procfs_remove(void) { return; } +#endif + +/*These functions are exposed to HDD*/ +int hif_register_driver(void); +void hif_unregister_driver(void); +int hif_init_adf_ctx(void *ol_sc); +void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle); +void hif_disable_isr(void *ol_sc); +void hif_reset_soc(void *ol_sc); +void hif_deinit_adf_ctx(void *ol_sc); + +void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision); +void hif_set_fw_info(void *ol_sc, u32 target_fw_version); +#endif /* __ATH_USB_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.c new file mode 100644 index 000000000000..2f2d5b0d0fef --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "bmi_msg.h" +#include "targaddrs.h" +#include "regtable.h" +#include "ar9888def.h" +#include "ar6320def.h" +#include "ar6320v2def.h" + +void target_register_tbl_attach(struct hif_usb_softc *sc, u32 target_type) +{ + switch (target_type) { + case TARGET_TYPE_AR9888: + sc->targetdef = &ar9888_targetdef; + break; + case TARGET_TYPE_AR6320: + sc->targetdef = &ar6320_targetdef; + break; + case TARGET_TYPE_AR6320V2: + sc->targetdef = &ar6320v2_targetdef; + break; + default: + break; + } +} + +void hif_register_tbl_attach(struct hif_usb_softc *sc, u32 hif_type) +{ + switch (hif_type) { + case HIF_TYPE_AR9888: + sc->hostdef = &ar9888_hostdef; + break; + case HIF_TYPE_AR6320: + sc->hostdef = &ar6320_hostdef; + break; + case HIF_TYPE_AR6320V2: + sc->hostdef = &ar6320v2_hostdef; + break; + default: + break; + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.h new file mode 100644 index 000000000000..7fc623b64d67 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/regtable.h @@ -0,0 +1,854 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#ifndef _REGTABLE_H_ +#define _REGTABLE_H_ +#include "if_usb.h" + +#define MISSING 0 + +typedef struct targetdef_s { + u_int32_t d_RTC_SOC_BASE_ADDRESS; + u_int32_t d_RTC_WMAC_BASE_ADDRESS; + u_int32_t d_SYSTEM_SLEEP_OFFSET; + u_int32_t d_WLAN_SYSTEM_SLEEP_OFFSET; + u_int32_t d_WLAN_SYSTEM_SLEEP_DISABLE_LSB; + u_int32_t d_WLAN_SYSTEM_SLEEP_DISABLE_MASK; + u_int32_t d_CLOCK_CONTROL_OFFSET; + u_int32_t d_CLOCK_CONTROL_SI0_CLK_MASK; + u_int32_t d_RESET_CONTROL_OFFSET; + u_int32_t d_RESET_CONTROL_MBOX_RST_MASK; + u_int32_t d_RESET_CONTROL_SI0_RST_MASK; + u_int32_t d_WLAN_RESET_CONTROL_OFFSET; + u_int32_t d_WLAN_RESET_CONTROL_COLD_RST_MASK; + u_int32_t d_WLAN_RESET_CONTROL_WARM_RST_MASK; + u_int32_t d_GPIO_BASE_ADDRESS; + u_int32_t d_GPIO_PIN0_OFFSET; + u_int32_t d_GPIO_PIN1_OFFSET; + u_int32_t d_GPIO_PIN0_CONFIG_MASK; + u_int32_t d_GPIO_PIN1_CONFIG_MASK; + u_int32_t d_SI_CONFIG_BIDIR_OD_DATA_LSB; + u_int32_t d_SI_CONFIG_BIDIR_OD_DATA_MASK; + u_int32_t d_SI_CONFIG_I2C_LSB; + u_int32_t d_SI_CONFIG_I2C_MASK; + u_int32_t d_SI_CONFIG_POS_SAMPLE_LSB; + u_int32_t d_SI_CONFIG_POS_SAMPLE_MASK; + u_int32_t d_SI_CONFIG_INACTIVE_CLK_LSB; + u_int32_t d_SI_CONFIG_INACTIVE_CLK_MASK; + u_int32_t d_SI_CONFIG_INACTIVE_DATA_LSB; + u_int32_t d_SI_CONFIG_INACTIVE_DATA_MASK; + u_int32_t d_SI_CONFIG_DIVIDER_LSB; + u_int32_t d_SI_CONFIG_DIVIDER_MASK; + u_int32_t d_SI_BASE_ADDRESS; + u_int32_t d_SI_CONFIG_OFFSET; + u_int32_t d_SI_TX_DATA0_OFFSET; + u_int32_t d_SI_TX_DATA1_OFFSET; + u_int32_t d_SI_RX_DATA0_OFFSET; + u_int32_t d_SI_RX_DATA1_OFFSET; + u_int32_t d_SI_CS_OFFSET; + u_int32_t d_SI_CS_DONE_ERR_MASK; + u_int32_t d_SI_CS_DONE_INT_MASK; + u_int32_t d_SI_CS_START_LSB; + u_int32_t d_SI_CS_START_MASK; + u_int32_t d_SI_CS_RX_CNT_LSB; + u_int32_t d_SI_CS_RX_CNT_MASK; + u_int32_t d_SI_CS_TX_CNT_LSB; + u_int32_t d_SI_CS_TX_CNT_MASK; + u_int32_t d_BOARD_DATA_SZ; + u_int32_t d_BOARD_EXT_DATA_SZ; + u_int32_t d_MBOX_BASE_ADDRESS; + u_int32_t d_LOCAL_SCRATCH_OFFSET; + u_int32_t d_CPU_CLOCK_OFFSET; + u_int32_t d_LPO_CAL_OFFSET; + u_int32_t d_GPIO_PIN10_OFFSET; + u_int32_t d_GPIO_PIN11_OFFSET; + u_int32_t d_GPIO_PIN12_OFFSET; + u_int32_t d_GPIO_PIN13_OFFSET; + u_int32_t d_CLOCK_GPIO_OFFSET; + u_int32_t d_CPU_CLOCK_STANDARD_LSB; + u_int32_t d_CPU_CLOCK_STANDARD_MASK; + u_int32_t d_LPO_CAL_ENABLE_LSB; + u_int32_t d_LPO_CAL_ENABLE_MASK; + u_int32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB; + u_int32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK; + u_int32_t d_ANALOG_INTF_BASE_ADDRESS; + u_int32_t d_WLAN_MAC_BASE_ADDRESS; + u_int32_t d_CE0_BASE_ADDRESS; + u_int32_t d_CE1_BASE_ADDRESS; + u_int32_t d_FW_INDICATOR_ADDRESS; + u_int32_t d_DRAM_BASE_ADDRESS; + u_int32_t d_SOC_CORE_BASE_ADDRESS; + u_int32_t d_CORE_CTRL_ADDRESS; + u_int32_t d_CE_COUNT; + u_int32_t d_MSI_NUM_REQUEST; + u_int32_t d_MSI_ASSIGN_FW; + u_int32_t d_MSI_ASSIGN_CE_INITIAL; + u_int32_t d_PCIE_INTR_ENABLE_ADDRESS; + u_int32_t d_PCIE_INTR_CLR_ADDRESS; + u_int32_t d_PCIE_INTR_FIRMWARE_MASK; + u_int32_t d_PCIE_INTR_CE_MASK_ALL; + u_int32_t d_CORE_CTRL_CPU_INTR_MASK; + u_int32_t d_SR_WR_INDEX_ADDRESS; + u_int32_t d_DST_WATERMARK_ADDRESS; + + /* htt_rx.c */ + u_int32_t d_RX_MSDU_END_4_FIRST_MSDU_MASK; + u_int32_t d_RX_MSDU_END_4_FIRST_MSDU_LSB; + u_int32_t d_RX_MPDU_START_0_RETRY_LSB; + u_int32_t d_RX_MPDU_START_0_RETRY_MASK; + u_int32_t d_RX_MPDU_START_0_SEQ_NUM_MASK; + u_int32_t d_RX_MPDU_START_0_SEQ_NUM_LSB; + u_int32_t d_RX_MPDU_START_2_PN_47_32_LSB; + u_int32_t d_RX_MPDU_START_2_PN_47_32_MASK; + u_int32_t d_RX_MPDU_START_2_TID_LSB; + u_int32_t d_RX_MPDU_START_2_TID_MASK; + u_int32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK; + u_int32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB; + u_int32_t d_RX_MSDU_END_1_KEY_ID_OCT_MASK; + u_int32_t d_RX_MSDU_END_1_KEY_ID_OCT_LSB; + u_int32_t d_RX_MSDU_END_4_LAST_MSDU_MASK; + u_int32_t d_RX_MSDU_END_4_LAST_MSDU_LSB; + u_int32_t d_RX_ATTENTION_0_MCAST_BCAST_MASK; + u_int32_t d_RX_ATTENTION_0_MCAST_BCAST_LSB; + u_int32_t d_RX_ATTENTION_0_FRAGMENT_MASK; + u_int32_t d_RX_ATTENTION_0_FRAGMENT_LSB; + u_int32_t d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK; + u_int32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK; + u_int32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB; + u_int32_t d_RX_MSDU_START_0_MSDU_LENGTH_MASK; + u_int32_t d_RX_MSDU_START_0_MSDU_LENGTH_LSB; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_MASK; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_LSB; + u_int32_t d_RX_MPDU_START_0_ENCRYPTED_MASK; + u_int32_t d_RX_MPDU_START_0_ENCRYPTED_LSB; + u_int32_t d_RX_ATTENTION_0_MORE_DATA_MASK; + u_int32_t d_RX_ATTENTION_0_MSDU_DONE_MASK; + u_int32_t d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK; + /* end */ + /* copy_engine.c */ + u_int32_t d_DST_WR_INDEX_ADDRESS; + u_int32_t d_SRC_WATERMARK_ADDRESS; + u_int32_t d_SRC_WATERMARK_LOW_MASK; + u_int32_t d_SRC_WATERMARK_HIGH_MASK; + u_int32_t d_DST_WATERMARK_LOW_MASK; + u_int32_t d_DST_WATERMARK_HIGH_MASK; + u_int32_t d_CURRENT_SRRI_ADDRESS; + u_int32_t d_CURRENT_DRRI_ADDRESS; + u_int32_t d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK; + u_int32_t d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK; + u_int32_t d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK; + u_int32_t d_HOST_IS_DST_RING_LOW_WATERMARK_MASK; + u_int32_t d_HOST_IS_ADDRESS; + u_int32_t d_HOST_IS_COPY_COMPLETE_MASK; + u_int32_t d_CE_WRAPPER_BASE_ADDRESS; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS; + u_int32_t d_HOST_IE_ADDRESS; + u_int32_t d_HOST_IE_COPY_COMPLETE_MASK; + u_int32_t d_SR_BA_ADDRESS; + u_int32_t d_SR_SIZE_ADDRESS; + u_int32_t d_CE_CTRL1_ADDRESS; + u_int32_t d_CE_CTRL1_DMAX_LENGTH_MASK; + u_int32_t d_DR_BA_ADDRESS; + u_int32_t d_DR_SIZE_ADDRESS; + u_int32_t d_MISC_IE_ADDRESS; + u_int32_t d_MISC_IS_AXI_ERR_MASK; + u_int32_t d_MISC_IS_DST_ADDR_ERR_MASK; + u_int32_t d_MISC_IS_SRC_LEN_ERR_MASK; + u_int32_t d_MISC_IS_DST_MAX_LEN_VIO_MASK; + u_int32_t d_MISC_IS_DST_RING_OVERFLOW_MASK; + u_int32_t d_MISC_IS_SRC_RING_OVERFLOW_MASK; + u_int32_t d_SRC_WATERMARK_LOW_LSB; + u_int32_t d_SRC_WATERMARK_HIGH_LSB; + u_int32_t d_DST_WATERMARK_LOW_LSB; + u_int32_t d_DST_WATERMARK_HIGH_LSB; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB; + u_int32_t d_CE_CTRL1_DMAX_LENGTH_LSB; + u_int32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK; + u_int32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK; + u_int32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB; + u_int32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_OFFSET; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_SRC_MSB; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_SRC_LSB; + u_int32_t d_WLAN_DEBUG_INPUT_SEL_SRC_MASK; + u_int32_t d_WLAN_DEBUG_CONTROL_OFFSET; + u_int32_t d_WLAN_DEBUG_CONTROL_ENABLE_MSB; + u_int32_t d_WLAN_DEBUG_CONTROL_ENABLE_LSB; + u_int32_t d_WLAN_DEBUG_CONTROL_ENABLE_MASK; + u_int32_t d_WLAN_DEBUG_OUT_OFFSET; + u_int32_t d_WLAN_DEBUG_OUT_DATA_MSB; + u_int32_t d_WLAN_DEBUG_OUT_DATA_LSB; + u_int32_t d_WLAN_DEBUG_OUT_DATA_MASK; + u_int32_t d_AMBA_DEBUG_BUS_OFFSET; + u_int32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB; + u_int32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB; + u_int32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK; + u_int32_t d_AMBA_DEBUG_BUS_SEL_MSB; + u_int32_t d_AMBA_DEBUG_BUS_SEL_LSB; + u_int32_t d_AMBA_DEBUG_BUS_SEL_MASK; + u_int32_t d_CE_WRAPPER_DEBUG_OFFSET; + u_int32_t d_CE_WRAPPER_DEBUG_SEL_MSB; + u_int32_t d_CE_WRAPPER_DEBUG_SEL_LSB; + u_int32_t d_CE_WRAPPER_DEBUG_SEL_MASK; + u_int32_t d_CE_DEBUG_OFFSET; + u_int32_t d_CE_DEBUG_SEL_MSB; + u_int32_t d_CE_DEBUG_SEL_LSB; + u_int32_t d_CE_DEBUG_SEL_MASK; + /* end */ + /* PLL start */ + u_int32_t d_EFUSE_OFFSET; + u_int32_t d_EFUSE_XTAL_SEL_MSB; + u_int32_t d_EFUSE_XTAL_SEL_LSB; + u_int32_t d_EFUSE_XTAL_SEL_MASK; + u_int32_t d_BB_PLL_CONFIG_OFFSET; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_MSB; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_LSB; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_MASK; + u_int32_t d_BB_PLL_CONFIG_FRAC_MSB; + u_int32_t d_BB_PLL_CONFIG_FRAC_LSB; + u_int32_t d_BB_PLL_CONFIG_FRAC_MASK; + u_int32_t d_WLAN_PLL_SETTLE_TIME_MSB; + u_int32_t d_WLAN_PLL_SETTLE_TIME_LSB; + u_int32_t d_WLAN_PLL_SETTLE_TIME_MASK; + u_int32_t d_WLAN_PLL_SETTLE_OFFSET; + u_int32_t d_WLAN_PLL_SETTLE_SW_MASK; + u_int32_t d_WLAN_PLL_SETTLE_RSTMASK; + u_int32_t d_WLAN_PLL_SETTLE_RESET; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_MSB; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_LSB; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_MASK; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_MSB; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_LSB; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_MASK; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_RESET; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_MSB; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_LSB; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_MASK; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_RESET; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_MSB; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_LSB; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_MASK; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_RESET; + u_int32_t d_WLAN_PLL_CONTROL_DIV_MSB; + u_int32_t d_WLAN_PLL_CONTROL_DIV_LSB; + u_int32_t d_WLAN_PLL_CONTROL_DIV_MASK; + u_int32_t d_WLAN_PLL_CONTROL_DIV_RESET; + u_int32_t d_WLAN_PLL_CONTROL_OFFSET; + u_int32_t d_WLAN_PLL_CONTROL_SW_MASK; + u_int32_t d_WLAN_PLL_CONTROL_RSTMASK; + u_int32_t d_WLAN_PLL_CONTROL_RESET; + u_int32_t d_SOC_CORE_CLK_CTRL_OFFSET; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_MSB; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_LSB; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_MASK; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MSB; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_LSB; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MASK; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_RESET; + u_int32_t d_RTC_SYNC_STATUS_OFFSET; + u_int32_t d_SOC_CPU_CLOCK_OFFSET; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_MSB; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_LSB; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_MASK; + /* PLL end */ + u_int32_t d_SOC_POWER_REG_OFFSET; + u_int32_t d_PCIE_INTR_CAUSE_ADDRESS; + u_int32_t d_SOC_RESET_CONTROL_ADDRESS; + u_int32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK; + u_int32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB; + u_int32_t d_SOC_RESET_CONTROL_CE_RST_MASK; + u_int32_t d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK; + u_int32_t d_CPU_INTR_ADDRESS; + u_int32_t d_SOC_LF_TIMER_CONTROL0_ADDRESS; + u_int32_t d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK; + /* chip id start */ + u_int32_t d_SOC_CHIP_ID_ADDRESS; + u_int32_t d_SOC_CHIP_ID_VERSION_MASK; + u_int32_t d_SOC_CHIP_ID_VERSION_LSB; + u_int32_t d_SOC_CHIP_ID_REVISION_MASK; + u_int32_t d_SOC_CHIP_ID_REVISION_LSB; + /* chip id end */ +} TARGET_REGISTER_TABLE; + +#define RTC_SOC_BASE_ADDRESS (sc->targetdef->d_RTC_SOC_BASE_ADDRESS) +#define RTC_WMAC_BASE_ADDRESS (sc->targetdef->d_RTC_WMAC_BASE_ADDRESS) +#define SYSTEM_SLEEP_OFFSET (sc->targetdef->d_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_OFFSET (sc->targetdef->d_WLAN_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB (sc->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK (sc->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define CLOCK_CONTROL_OFFSET (sc->targetdef->d_CLOCK_CONTROL_OFFSET) +#define CLOCK_CONTROL_SI0_CLK_MASK (sc->targetdef->d_CLOCK_CONTROL_SI0_CLK_MASK) +#define RESET_CONTROL_OFFSET (sc->targetdef->d_RESET_CONTROL_OFFSET) +#define RESET_CONTROL_MBOX_RST_MASK (sc->targetdef->d_RESET_CONTROL_MBOX_RST_MASK) +#define RESET_CONTROL_SI0_RST_MASK (sc->targetdef->d_RESET_CONTROL_SI0_RST_MASK) +#define WLAN_RESET_CONTROL_OFFSET (sc->targetdef->d_WLAN_RESET_CONTROL_OFFSET) +#define WLAN_RESET_CONTROL_COLD_RST_MASK (sc->targetdef->d_WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MASK (sc->targetdef->d_WLAN_RESET_CONTROL_WARM_RST_MASK) +#define GPIO_BASE_ADDRESS (sc->targetdef->d_GPIO_BASE_ADDRESS) +#define GPIO_PIN0_OFFSET (sc->targetdef->d_GPIO_PIN0_OFFSET) +#define GPIO_PIN1_OFFSET (sc->targetdef->d_GPIO_PIN1_OFFSET) +#define GPIO_PIN0_CONFIG_MASK (sc->targetdef->d_GPIO_PIN0_CONFIG_MASK) +#define GPIO_PIN1_CONFIG_MASK (sc->targetdef->d_GPIO_PIN1_CONFIG_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_LSB (sc->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_LSB) +#define SI_CONFIG_BIDIR_OD_DATA_MASK (sc->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_LSB (sc->targetdef->d_SI_CONFIG_I2C_LSB) +#define SI_CONFIG_I2C_MASK (sc->targetdef->d_SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_LSB (sc->targetdef->d_SI_CONFIG_POS_SAMPLE_LSB) +#define SI_CONFIG_POS_SAMPLE_MASK (sc->targetdef->d_SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_LSB (sc->targetdef->d_SI_CONFIG_INACTIVE_CLK_LSB) +#define SI_CONFIG_INACTIVE_CLK_MASK (sc->targetdef->d_SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_LSB (sc->targetdef->d_SI_CONFIG_INACTIVE_DATA_LSB) +#define SI_CONFIG_INACTIVE_DATA_MASK (sc->targetdef->d_SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_LSB (sc->targetdef->d_SI_CONFIG_DIVIDER_LSB) +#define SI_CONFIG_DIVIDER_MASK (sc->targetdef->d_SI_CONFIG_DIVIDER_MASK) +#define SI_BASE_ADDRESS (sc->targetdef->d_SI_BASE_ADDRESS) +#define SI_CONFIG_OFFSET (sc->targetdef->d_SI_CONFIG_OFFSET) +#define SI_TX_DATA0_OFFSET (sc->targetdef->d_SI_TX_DATA0_OFFSET) +#define SI_TX_DATA1_OFFSET (sc->targetdef->d_SI_TX_DATA1_OFFSET) +#define SI_RX_DATA0_OFFSET (sc->targetdef->d_SI_RX_DATA0_OFFSET) +#define SI_RX_DATA1_OFFSET (sc->targetdef->d_SI_RX_DATA1_OFFSET) +#define SI_CS_OFFSET (sc->targetdef->d_SI_CS_OFFSET) +#define SI_CS_DONE_ERR_MASK (sc->targetdef->d_SI_CS_DONE_ERR_MASK) +#define SI_CS_DONE_INT_MASK (sc->targetdef->d_SI_CS_DONE_INT_MASK) +#define SI_CS_START_LSB (sc->targetdef->d_SI_CS_START_LSB) +#define SI_CS_START_MASK (sc->targetdef->d_SI_CS_START_MASK) +#define SI_CS_RX_CNT_LSB (sc->targetdef->d_SI_CS_RX_CNT_LSB) +#define SI_CS_RX_CNT_MASK (sc->targetdef->d_SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_LSB (sc->targetdef->d_SI_CS_TX_CNT_LSB) +#define SI_CS_TX_CNT_MASK (sc->targetdef->d_SI_CS_TX_CNT_MASK) +#define EEPROM_SZ (sc->targetdef->d_BOARD_DATA_SZ) +#define EEPROM_EXT_SZ (sc->targetdef->d_BOARD_EXT_DATA_SZ) +#define MBOX_BASE_ADDRESS (sc->targetdef->d_MBOX_BASE_ADDRESS) +#define LOCAL_SCRATCH_OFFSET (sc->targetdef->d_LOCAL_SCRATCH_OFFSET) +#define CPU_CLOCK_OFFSET (sc->targetdef->d_CPU_CLOCK_OFFSET) +#define LPO_CAL_OFFSET (sc->targetdef->d_LPO_CAL_OFFSET) +#define GPIO_PIN10_OFFSET (sc->targetdef->d_GPIO_PIN10_OFFSET) +#define GPIO_PIN11_OFFSET (sc->targetdef->d_GPIO_PIN11_OFFSET) +#define GPIO_PIN12_OFFSET (sc->targetdef->d_GPIO_PIN12_OFFSET) +#define GPIO_PIN13_OFFSET (sc->targetdef->d_GPIO_PIN13_OFFSET) +#define CLOCK_GPIO_OFFSET (sc->targetdef->d_CLOCK_GPIO_OFFSET) +#define CPU_CLOCK_STANDARD_LSB (sc->targetdef->d_CPU_CLOCK_STANDARD_LSB) +#define CPU_CLOCK_STANDARD_MASK (sc->targetdef->d_CPU_CLOCK_STANDARD_MASK) +#define LPO_CAL_ENABLE_LSB (sc->targetdef->d_LPO_CAL_ENABLE_LSB) +#define LPO_CAL_ENABLE_MASK (sc->targetdef->d_LPO_CAL_ENABLE_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB (sc->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB) +#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK (sc->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +#define ANALOG_INTF_BASE_ADDRESS (sc->targetdef->d_ANALOG_INTF_BASE_ADDRESS) +#define WLAN_MAC_BASE_ADDRESS (sc->targetdef->d_WLAN_MAC_BASE_ADDRESS) +#define CE0_BASE_ADDRESS (sc->targetdef->d_CE0_BASE_ADDRESS) +#define CE1_BASE_ADDRESS (sc->targetdef->d_CE1_BASE_ADDRESS) +#define FW_INDICATOR_ADDRESS (sc->targetdef->d_FW_INDICATOR_ADDRESS) +#define DRAM_BASE_ADDRESS (sc->targetdef->d_DRAM_BASE_ADDRESS) +#define SOC_CORE_BASE_ADDRESS (sc->targetdef->d_SOC_CORE_BASE_ADDRESS) +#define CORE_CTRL_ADDRESS (sc->targetdef->d_CORE_CTRL_ADDRESS) +#define CE_COUNT (sc->targetdef->d_CE_COUNT) +#define PCIE_INTR_ENABLE_ADDRESS (sc->targetdef->d_PCIE_INTR_ENABLE_ADDRESS) +#define PCIE_INTR_CLR_ADDRESS (sc->targetdef->d_PCIE_INTR_CLR_ADDRESS) +#define PCIE_INTR_FIRMWARE_MASK (sc->targetdef->d_PCIE_INTR_FIRMWARE_MASK) +#define PCIE_INTR_CE_MASK_ALL (sc->targetdef->d_PCIE_INTR_CE_MASK_ALL) +#define CORE_CTRL_CPU_INTR_MASK (sc->targetdef->d_CORE_CTRL_CPU_INTR_MASK) +#define PCIE_INTR_CAUSE_ADDRESS (sc->targetdef->d_PCIE_INTR_CAUSE_ADDRESS) +#define SOC_RESET_CONTROL_ADDRESS (sc->targetdef->d_SOC_RESET_CONTROL_ADDRESS) +#define SOC_RESET_CONTROL_CE_RST_MASK (sc->targetdef->d_SOC_RESET_CONTROL_CE_RST_MASK) +#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK (sc->targetdef->d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK) +#define CPU_INTR_ADDRESS (sc->targetdef->d_CPU_INTR_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ADDRESS (sc->targetdef->d_SOC_LF_TIMER_CONTROL0_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK (sc->targetdef->d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB (sc->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK (sc->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_GET(x) (((x) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) >> SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_SET(x) (((x) << SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +/* hif_pci.c */ +#define CHIP_ID_ADDRESS (sc->targetdef->d_SOC_CHIP_ID_ADDRESS) +#define SOC_CHIP_ID_REVISION_MASK (sc->targetdef->d_SOC_CHIP_ID_REVISION_MASK) +#define SOC_CHIP_ID_REVISION_LSB (sc->targetdef->d_SOC_CHIP_ID_REVISION_LSB) +#define SOC_CHIP_ID_VERSION_MASK (sc->targetdef->d_SOC_CHIP_ID_VERSION_MASK) +#define SOC_CHIP_ID_VERSION_LSB (sc->targetdef->d_SOC_CHIP_ID_VERSION_LSB) +#define CHIP_ID_REVISION_GET(x) (((x) & SOC_CHIP_ID_REVISION_MASK) >> SOC_CHIP_ID_REVISION_LSB) +#define CHIP_ID_VERSION_GET(x) (((x) & SOC_CHIP_ID_VERSION_MASK) >> SOC_CHIP_ID_VERSION_LSB) +/* hif_pci.c end */ + +/* misc */ +#define SR_WR_INDEX_ADDRESS (sc->targetdef->d_SR_WR_INDEX_ADDRESS) +#define DST_WATERMARK_ADDRESS (sc->targetdef->d_DST_WATERMARK_ADDRESS) +#define SOC_POWER_REG_OFFSET (sc->targetdef->d_SOC_POWER_REG_OFFSET) +/* end */ + +/* htt_rx.c */ +#define RX_MSDU_END_4_FIRST_MSDU_MASK (pdev->targetdef->d_RX_MSDU_END_4_FIRST_MSDU_MASK) +#define RX_MSDU_END_4_FIRST_MSDU_LSB (pdev->targetdef->d_RX_MSDU_END_4_FIRST_MSDU_LSB) +#define RX_MPDU_START_0_RETRY_LSB (pdev->targetdef->d_RX_MPDU_START_0_RETRY_LSB) +#define RX_MPDU_START_0_RETRY_MASK (pdev->targetdef->d_RX_MPDU_START_0_RETRY_MASK) +#define RX_MPDU_START_0_SEQ_NUM_MASK (pdev->targetdef->d_RX_MPDU_START_0_SEQ_NUM_MASK) +#define RX_MPDU_START_0_SEQ_NUM_LSB (pdev->targetdef->d_RX_MPDU_START_0_SEQ_NUM_LSB) +#define RX_MPDU_START_2_PN_47_32_LSB (pdev->targetdef->d_RX_MPDU_START_2_PN_47_32_LSB) +#define RX_MPDU_START_2_PN_47_32_MASK (pdev->targetdef->d_RX_MPDU_START_2_PN_47_32_MASK) +#define RX_MPDU_START_2_TID_LSB (pdev->targetdef->d_RX_MPDU_START_2_TID_LSB) +#define RX_MPDU_START_2_TID_MASK (pdev->targetdef->d_RX_MPDU_START_2_TID_MASK) +#define RX_MSDU_END_1_KEY_ID_OCT_MASK (pdev->targetdef->d_RX_MSDU_END_1_KEY_ID_OCT_MASK) +#define RX_MSDU_END_1_KEY_ID_OCT_LSB (pdev->targetdef->d_RX_MSDU_END_1_KEY_ID_OCT_LSB) +#define RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK (pdev->targetdef->d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK) +#define RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB (pdev->targetdef->d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB) +#define RX_MSDU_END_4_LAST_MSDU_MASK (pdev->targetdef->d_RX_MSDU_END_4_LAST_MSDU_MASK) +#define RX_MSDU_END_4_LAST_MSDU_LSB (pdev->targetdef->d_RX_MSDU_END_4_LAST_MSDU_LSB) +#define RX_ATTENTION_0_MCAST_BCAST_MASK (pdev->targetdef->d_RX_ATTENTION_0_MCAST_BCAST_MASK) +#define RX_ATTENTION_0_MCAST_BCAST_LSB (pdev->targetdef->d_RX_ATTENTION_0_MCAST_BCAST_LSB) +#define RX_ATTENTION_0_FRAGMENT_MASK (pdev->targetdef->d_RX_ATTENTION_0_FRAGMENT_MASK) +#define RX_ATTENTION_0_FRAGMENT_LSB (pdev->targetdef->d_RX_ATTENTION_0_FRAGMENT_LSB) +#define RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK (pdev->targetdef->d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK) +#define RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK (pdev->targetdef->d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK) +#define RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB (pdev->targetdef->d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB) +#define RX_MSDU_START_0_MSDU_LENGTH_MASK (pdev->targetdef->d_RX_MSDU_START_0_MSDU_LENGTH_MASK) +#define RX_MSDU_START_0_MSDU_LENGTH_LSB (pdev->targetdef->d_RX_MSDU_START_0_MSDU_LENGTH_LSB) +#define RX_MSDU_START_2_DECAP_FORMAT_OFFSET (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET) +#define RX_MSDU_START_2_DECAP_FORMAT_MASK (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_MASK) +#define RX_MSDU_START_2_DECAP_FORMAT_LSB (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_LSB) +#define RX_MPDU_START_0_ENCRYPTED_MASK (pdev->targetdef->d_RX_MPDU_START_0_ENCRYPTED_MASK) +#define RX_MPDU_START_0_ENCRYPTED_LSB (pdev->targetdef->d_RX_MPDU_START_0_ENCRYPTED_LSB) +#define RX_ATTENTION_0_MORE_DATA_MASK (pdev->targetdef->d_RX_ATTENTION_0_MORE_DATA_MASK) +#define RX_ATTENTION_0_MSDU_DONE_MASK (pdev->targetdef->d_RX_ATTENTION_0_MSDU_DONE_MASK) +#define RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK (pdev->targetdef->d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK) +/* end */ + +/* copy_engine.c */ +#define DST_WR_INDEX_ADDRESS (sc->targetdef->d_DST_WR_INDEX_ADDRESS) +#define SRC_WATERMARK_ADDRESS (sc->targetdef->d_SRC_WATERMARK_ADDRESS) +#define SRC_WATERMARK_LOW_MASK (sc->targetdef->d_SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_MASK (sc->targetdef->d_SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_MASK (sc->targetdef->d_DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_MASK (sc->targetdef->d_DST_WATERMARK_HIGH_MASK) +#define CURRENT_SRRI_ADDRESS (sc->targetdef->d_CURRENT_SRRI_ADDRESS) +#define CURRENT_DRRI_ADDRESS (sc->targetdef->d_CURRENT_DRRI_ADDRESS) +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK (sc->targetdef->d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK (sc->targetdef->d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK) +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK (sc->targetdef->d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK (sc->targetdef->d_HOST_IS_DST_RING_LOW_WATERMARK_MASK) +#define HOST_IS_ADDRESS (sc->targetdef->d_HOST_IS_ADDRESS) +#define HOST_IS_COPY_COMPLETE_MASK (sc->targetdef->d_HOST_IS_COPY_COMPLETE_MASK) +#define CE_WRAPPER_BASE_ADDRESS (sc->targetdef->d_CE_WRAPPER_BASE_ADDRESS) +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS) +#define HOST_IE_ADDRESS (sc->targetdef->d_HOST_IE_ADDRESS) +#define HOST_IE_COPY_COMPLETE_MASK (sc->targetdef->d_HOST_IE_COPY_COMPLETE_MASK) +#define SR_BA_ADDRESS (sc->targetdef->d_SR_BA_ADDRESS) +#define SR_SIZE_ADDRESS (sc->targetdef->d_SR_SIZE_ADDRESS) +#define CE_CTRL1_ADDRESS (sc->targetdef->d_CE_CTRL1_ADDRESS) +#define CE_CTRL1_DMAX_LENGTH_MASK (sc->targetdef->d_CE_CTRL1_DMAX_LENGTH_MASK) +#define DR_BA_ADDRESS (sc->targetdef->d_DR_BA_ADDRESS) +#define DR_SIZE_ADDRESS (sc->targetdef->d_DR_SIZE_ADDRESS) +#define MISC_IE_ADDRESS (sc->targetdef->d_MISC_IE_ADDRESS) +#define MISC_IS_AXI_ERR_MASK (sc->targetdef->d_MISC_IS_AXI_ERR_MASK) +#define MISC_IS_DST_ADDR_ERR_MASK (sc->targetdef->d_MISC_IS_DST_ADDR_ERR_MASK) +#define MISC_IS_SRC_LEN_ERR_MASK (sc->targetdef->d_MISC_IS_SRC_LEN_ERR_MASK) +#define MISC_IS_DST_MAX_LEN_VIO_MASK (sc->targetdef->d_MISC_IS_DST_MAX_LEN_VIO_MASK) +#define MISC_IS_DST_RING_OVERFLOW_MASK (sc->targetdef->d_MISC_IS_DST_RING_OVERFLOW_MASK) +#define MISC_IS_SRC_RING_OVERFLOW_MASK (sc->targetdef->d_MISC_IS_SRC_RING_OVERFLOW_MASK) +#define SRC_WATERMARK_LOW_LSB (sc->targetdef->d_SRC_WATERMARK_LOW_LSB) +#define SRC_WATERMARK_HIGH_LSB (sc->targetdef->d_SRC_WATERMARK_HIGH_LSB) +#define DST_WATERMARK_LOW_LSB (sc->targetdef->d_DST_WATERMARK_LOW_LSB) +#define DST_WATERMARK_HIGH_LSB (sc->targetdef->d_DST_WATERMARK_HIGH_LSB) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_LSB (sc->targetdef->d_CE_CTRL1_DMAX_LENGTH_LSB) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK (sc->targetdef->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK (sc->targetdef->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB (sc->targetdef->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB (sc->targetdef->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) +#define WLAN_DEBUG_INPUT_SEL_OFFSET (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_OFFSET) +#define WLAN_DEBUG_INPUT_SEL_SRC_MSB (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_MSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_LSB (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_LSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_MASK (sc->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_MASK) +#define WLAN_DEBUG_CONTROL_OFFSET (sc->targetdef->d_WLAN_DEBUG_CONTROL_OFFSET) +#define WLAN_DEBUG_CONTROL_ENABLE_MSB (sc->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_MSB) +#define WLAN_DEBUG_CONTROL_ENABLE_LSB (sc->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_LSB) +#define WLAN_DEBUG_CONTROL_ENABLE_MASK (sc->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_MASK) +#define WLAN_DEBUG_OUT_OFFSET (sc->targetdef->d_WLAN_DEBUG_OUT_OFFSET) +#define WLAN_DEBUG_OUT_DATA_MSB (sc->targetdef->d_WLAN_DEBUG_OUT_DATA_MSB) +#define WLAN_DEBUG_OUT_DATA_LSB (sc->targetdef->d_WLAN_DEBUG_OUT_DATA_LSB) +#define WLAN_DEBUG_OUT_DATA_MASK (sc->targetdef->d_WLAN_DEBUG_OUT_DATA_MASK) +#define AMBA_DEBUG_BUS_OFFSET (sc->targetdef->d_AMBA_DEBUG_BUS_OFFSET) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB (sc->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB (sc->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK (sc->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) +#define AMBA_DEBUG_BUS_SEL_MSB (sc->targetdef->d_AMBA_DEBUG_BUS_SEL_MSB) +#define AMBA_DEBUG_BUS_SEL_LSB (sc->targetdef->d_AMBA_DEBUG_BUS_SEL_LSB) +#define AMBA_DEBUG_BUS_SEL_MASK (sc->targetdef->d_AMBA_DEBUG_BUS_SEL_MASK) +#define CE_WRAPPER_DEBUG_OFFSET (sc->targetdef->d_CE_WRAPPER_DEBUG_OFFSET) +#define CE_WRAPPER_DEBUG_SEL_MSB (sc->targetdef->d_CE_WRAPPER_DEBUG_SEL_MSB) +#define CE_WRAPPER_DEBUG_SEL_LSB (sc->targetdef->d_CE_WRAPPER_DEBUG_SEL_LSB) +#define CE_WRAPPER_DEBUG_SEL_MASK (sc->targetdef->d_CE_WRAPPER_DEBUG_SEL_MASK) +#define CE_DEBUG_OFFSET (sc->targetdef->d_CE_DEBUG_OFFSET) +#define CE_DEBUG_SEL_MSB (sc->targetdef->d_CE_DEBUG_SEL_MSB) +#define CE_DEBUG_SEL_LSB (sc->targetdef->d_CE_DEBUG_SEL_LSB) +#define CE_DEBUG_SEL_MASK (sc->targetdef->d_CE_DEBUG_SEL_MASK) +/* end */ +/* PLL start */ +#define EFUSE_OFFSET (sc->targetdef->d_EFUSE_OFFSET) +#define EFUSE_XTAL_SEL_MSB (sc->targetdef->d_EFUSE_XTAL_SEL_MSB) +#define EFUSE_XTAL_SEL_LSB (sc->targetdef->d_EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_MASK (sc->targetdef->d_EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OFFSET (sc->targetdef->d_BB_PLL_CONFIG_OFFSET) +#define BB_PLL_CONFIG_OUTDIV_MSB (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_MSB) +#define BB_PLL_CONFIG_OUTDIV_LSB (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_MASK (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_MSB (sc->targetdef->d_BB_PLL_CONFIG_FRAC_MSB) +#define BB_PLL_CONFIG_FRAC_LSB (sc->targetdef->d_BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_MASK (sc->targetdef->d_BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_MSB (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_MSB) +#define WLAN_PLL_SETTLE_TIME_LSB (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_MASK (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_SETTLE_OFFSET (sc->targetdef->d_WLAN_PLL_SETTLE_OFFSET) +#define WLAN_PLL_SETTLE_SW_MASK (sc->targetdef->d_WLAN_PLL_SETTLE_SW_MASK) +#define WLAN_PLL_SETTLE_RSTMASK (sc->targetdef->d_WLAN_PLL_SETTLE_RSTMASK) +#define WLAN_PLL_SETTLE_RESET (sc->targetdef->d_WLAN_PLL_SETTLE_RESET) +#define WLAN_PLL_CONTROL_NOPWD_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MSB) +#define WLAN_PLL_CONTROL_NOPWD_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MSB) +#define WLAN_PLL_CONTROL_BYPASS_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_BYPASS_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_RESET) +#define WLAN_PLL_CONTROL_CLK_SEL_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MSB) +#define WLAN_PLL_CONTROL_CLK_SEL_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_RESET) +#define WLAN_PLL_CONTROL_REFDIV_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MSB) +#define WLAN_PLL_CONTROL_REFDIV_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_REFDIV_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_RESET) +#define WLAN_PLL_CONTROL_DIV_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_MSB) +#define WLAN_PLL_CONTROL_DIV_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_MASK) +#define WLAN_PLL_CONTROL_DIV_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_RESET) +#define WLAN_PLL_CONTROL_OFFSET (sc->targetdef->d_WLAN_PLL_CONTROL_OFFSET) +#define WLAN_PLL_CONTROL_SW_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_SW_MASK) +#define WLAN_PLL_CONTROL_RSTMASK (sc->targetdef->d_WLAN_PLL_CONTROL_RSTMASK) +#define WLAN_PLL_CONTROL_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_RESET) +#define SOC_CORE_CLK_CTRL_OFFSET (sc->targetdef->d_SOC_CORE_CLK_CTRL_OFFSET) +#define SOC_CORE_CLK_CTRL_DIV_MSB (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MSB) +#define SOC_CORE_CLK_CTRL_DIV_LSB (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_MASK (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_MSB (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_LSB (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_MASK (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_RESET (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_RESET) +#define RTC_SYNC_STATUS_OFFSET (sc->targetdef->d_RTC_SYNC_STATUS_OFFSET) +#define SOC_CPU_CLOCK_OFFSET (sc->targetdef->d_SOC_CPU_CLOCK_OFFSET) +#define SOC_CPU_CLOCK_STANDARD_MSB (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_MSB) +#define SOC_CPU_CLOCK_STANDARD_LSB (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_MASK (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +/* SET macros */ +#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_SET(x) (((x) << SI_CONFIG_BIDIR_OD_DATA_LSB) & SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_SET(x) (((x) << SI_CONFIG_I2C_LSB) & SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_SET(x) (((x) << SI_CONFIG_POS_SAMPLE_LSB) & SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_SET(x) (((x) << SI_CONFIG_INACTIVE_CLK_LSB) & SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_SET(x) (((x) << SI_CONFIG_INACTIVE_DATA_LSB) & SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_SET(x) (((x) << SI_CONFIG_DIVIDER_LSB) & SI_CONFIG_DIVIDER_MASK) +#define SI_CS_START_SET(x) (((x) << SI_CS_START_LSB) & SI_CS_START_MASK) +#define SI_CS_RX_CNT_SET(x) (((x) << SI_CS_RX_CNT_LSB) & SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_SET(x) (((x) << SI_CS_TX_CNT_LSB) & SI_CS_TX_CNT_MASK) +#define LPO_CAL_ENABLE_SET(x) (((x) << LPO_CAL_ENABLE_LSB) & LPO_CAL_ENABLE_MASK) +#define CPU_CLOCK_STANDARD_SET(x) (((x) << CPU_CLOCK_STANDARD_LSB) & CPU_CLOCK_STANDARD_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_SET(x) (((x) << CLOCK_GPIO_BT_CLK_OUT_EN_LSB) & CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +/* copy_engine.c */ +#define SRC_WATERMARK_LOW_SET(x) (((x) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_SET(x) (((x) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_SET(x) (((x) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_SET(x) (((x) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_SET(x) (((x) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) (((x) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) (((x) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +#define WLAN_DEBUG_INPUT_SEL_SRC_GET(x) (((x) & WLAN_DEBUG_INPUT_SEL_SRC_MASK) >> WLAN_DEBUG_INPUT_SEL_SRC_LSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_SET(x) (((x) << WLAN_DEBUG_INPUT_SEL_SRC_LSB) & WLAN_DEBUG_INPUT_SEL_SRC_MASK) +#define WLAN_DEBUG_CONTROL_ENABLE_GET(x) (((x) & WLAN_DEBUG_CONTROL_ENABLE_MASK) >> WLAN_DEBUG_CONTROL_ENABLE_LSB) +#define WLAN_DEBUG_CONTROL_ENABLE_SET(x) (((x) << WLAN_DEBUG_CONTROL_ENABLE_LSB) & WLAN_DEBUG_CONTROL_ENABLE_MASK) +#define WLAN_DEBUG_OUT_DATA_GET(x) (((x) & WLAN_DEBUG_OUT_DATA_MASK) >> WLAN_DEBUG_OUT_DATA_LSB) +#define WLAN_DEBUG_OUT_DATA_SET(x) (((x) << WLAN_DEBUG_OUT_DATA_LSB) & WLAN_DEBUG_OUT_DATA_MASK) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_GET(x) (((x) & AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) >> AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_SET(x) (((x) << AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) & AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) +#define AMBA_DEBUG_BUS_SEL_GET(x) (((x) & AMBA_DEBUG_BUS_SEL_MASK) >> AMBA_DEBUG_BUS_SEL_LSB) +#define AMBA_DEBUG_BUS_SEL_SET(x) (((x) << AMBA_DEBUG_BUS_SEL_LSB) & AMBA_DEBUG_BUS_SEL_MASK) +#define CE_WRAPPER_DEBUG_SEL_GET(x) (((x) & CE_WRAPPER_DEBUG_SEL_MASK) >> CE_WRAPPER_DEBUG_SEL_LSB) +#define CE_WRAPPER_DEBUG_SEL_SET(x) (((x) << CE_WRAPPER_DEBUG_SEL_LSB) & CE_WRAPPER_DEBUG_SEL_MASK) +#define CE_DEBUG_SEL_GET(x) (((x) & CE_DEBUG_SEL_MASK) >> CE_DEBUG_SEL_LSB) +#define CE_DEBUG_SEL_SET(x) (((x) << CE_DEBUG_SEL_LSB) & CE_DEBUG_SEL_MASK) +/* end */ +/* PLL start */ +#define EFUSE_XTAL_SEL_GET(x) (((x) & EFUSE_XTAL_SEL_MASK) >> EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_SET(x) (((x) << EFUSE_XTAL_SEL_LSB) & EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OUTDIV_GET(x) (((x) & BB_PLL_CONFIG_OUTDIV_MASK) >> BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_SET(x) (((x) << BB_PLL_CONFIG_OUTDIV_LSB) & BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_GET(x) (((x) & BB_PLL_CONFIG_FRAC_MASK) >> BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_SET(x) (((x) << BB_PLL_CONFIG_FRAC_LSB) & BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_GET(x) (((x) & WLAN_PLL_SETTLE_TIME_MASK) >> WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_SET(x) (((x) << WLAN_PLL_SETTLE_TIME_LSB) & WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_CONTROL_NOPWD_GET(x) (((x) & WLAN_PLL_CONTROL_NOPWD_MASK) >> WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_SET(x) (((x) << WLAN_PLL_CONTROL_NOPWD_LSB) & WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_GET(x) (((x) & WLAN_PLL_CONTROL_BYPASS_MASK) >> WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_SET(x) (((x) << WLAN_PLL_CONTROL_BYPASS_LSB) & WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_GET(x) (((x) & WLAN_PLL_CONTROL_CLK_SEL_MASK) >> WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_SET(x) (((x) << WLAN_PLL_CONTROL_CLK_SEL_LSB) & WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_REFDIV_GET(x) (((x) & WLAN_PLL_CONTROL_REFDIV_MASK) >> WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_SET(x) (((x) << WLAN_PLL_CONTROL_REFDIV_LSB) & WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_DIV_GET(x) (((x) & WLAN_PLL_CONTROL_DIV_MASK) >> WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_SET(x) (((x) << WLAN_PLL_CONTROL_DIV_LSB) & WLAN_PLL_CONTROL_DIV_MASK) +#define SOC_CORE_CLK_CTRL_DIV_GET(x) (((x) & SOC_CORE_CLK_CTRL_DIV_MASK) >> SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_SET(x) (((x) << SOC_CORE_CLK_CTRL_DIV_LSB) & SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_GET(x) (((x) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) >> RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_SET(x) (((x) << RTC_SYNC_STATUS_PLL_CHANGING_LSB) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define SOC_CPU_CLOCK_STANDARD_GET(x) (((x) & SOC_CPU_CLOCK_STANDARD_MASK) >> SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_SET(x) (((x) << SOC_CPU_CLOCK_STANDARD_LSB) & SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +typedef struct hostdef_s { + A_UINT32 d_INT_STATUS_ENABLE_ERROR_LSB; + A_UINT32 d_INT_STATUS_ENABLE_ERROR_MASK; + A_UINT32 d_INT_STATUS_ENABLE_CPU_LSB; + A_UINT32 d_INT_STATUS_ENABLE_CPU_MASK; + A_UINT32 d_INT_STATUS_ENABLE_COUNTER_LSB; + A_UINT32 d_INT_STATUS_ENABLE_COUNTER_MASK; + A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_LSB; + A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_MASK; + A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB; + A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK; + A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB; + A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK; + A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_LSB; + A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_MASK; + A_UINT32 d_INT_STATUS_ENABLE_ADDRESS; + A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_LSB; + A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_MASK; + A_UINT32 d_HOST_INT_STATUS_ADDRESS; + A_UINT32 d_CPU_INT_STATUS_ADDRESS; + A_UINT32 d_ERROR_INT_STATUS_ADDRESS; + A_UINT32 d_ERROR_INT_STATUS_WAKEUP_MASK; + A_UINT32 d_ERROR_INT_STATUS_WAKEUP_LSB; + A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK; + A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB; + A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_MASK; + A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_LSB; + A_UINT32 d_COUNT_DEC_ADDRESS; + A_UINT32 d_HOST_INT_STATUS_CPU_MASK; + A_UINT32 d_HOST_INT_STATUS_CPU_LSB; + A_UINT32 d_HOST_INT_STATUS_ERROR_MASK; + A_UINT32 d_HOST_INT_STATUS_ERROR_LSB; + A_UINT32 d_HOST_INT_STATUS_COUNTER_MASK; + A_UINT32 d_HOST_INT_STATUS_COUNTER_LSB; + A_UINT32 d_RX_LOOKAHEAD_VALID_ADDRESS; + A_UINT32 d_WINDOW_DATA_ADDRESS; + A_UINT32 d_WINDOW_READ_ADDR_ADDRESS; + A_UINT32 d_WINDOW_WRITE_ADDR_ADDRESS; + A_UINT32 d_SOC_GLOBAL_RESET_ADDRESS; + A_UINT32 d_RTC_STATE_ADDRESS; + A_UINT32 d_RTC_STATE_COLD_RESET_MASK; + A_UINT32 d_PCIE_LOCAL_BASE_ADDRESS; + A_UINT32 d_PCIE_SOC_WAKE_RESET; + A_UINT32 d_PCIE_SOC_WAKE_ADDRESS; + A_UINT32 d_PCIE_SOC_WAKE_V_MASK; + A_UINT32 d_RTC_STATE_V_MASK; + A_UINT32 d_RTC_STATE_V_LSB; + A_UINT32 d_FW_IND_EVENT_PENDING; + A_UINT32 d_FW_IND_INITIALIZED; + A_UINT32 d_RTC_STATE_V_ON; +#if defined(SDIO_3_0) + A_UINT32 d_HOST_INT_STATUS_MBOX_DATA_MASK; + A_UINT32 d_HOST_INT_STATUS_MBOX_DATA_LSB; +#endif + A_UINT32 d_PCIE_SOC_RDY_STATUS_ADDRESS; + A_UINT32 d_PCIE_SOC_RDY_STATUS_BAR_MASK; + A_UINT32 d_SOC_PCIE_BASE_ADDRESS; + A_UINT32 d_MSI_MAGIC_ADR_ADDRESS; + A_UINT32 d_MSI_MAGIC_ADDRESS; +} HOST_REGISTER_TABLE; + +#define INT_STATUS_ENABLE_ERROR_LSB (sc->hostdef->d_INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_MASK (sc->hostdef->d_INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_LSB (sc->hostdef->d_INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_MASK (sc->hostdef->d_INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_LSB (sc->hostdef->d_INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_MASK (sc->hostdef->d_INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_LSB (sc->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_MASK (sc->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB (sc->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK (sc->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB (sc->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK (sc->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB (sc->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK (sc->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define INT_STATUS_ENABLE_ADDRESS (sc->hostdef->d_INT_STATUS_ENABLE_ADDRESS) +#define CPU_INT_STATUS_ENABLE_BIT_LSB (sc->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_MASK (sc->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_MASK) +#define HOST_INT_STATUS_ADDRESS (sc->hostdef->d_HOST_INT_STATUS_ADDRESS) +#define CPU_INT_STATUS_ADDRESS (sc->hostdef->d_CPU_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_ADDRESS (sc->hostdef->d_ERROR_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_WAKEUP_MASK (sc->hostdef->d_ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_WAKEUP_LSB (sc->hostdef->d_ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK (sc->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB (sc->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK (sc->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB (sc->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define COUNT_DEC_ADDRESS (sc->hostdef->d_COUNT_DEC_ADDRESS) +#define HOST_INT_STATUS_CPU_MASK (sc->hostdef->d_HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_CPU_LSB (sc->hostdef->d_HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_MASK (sc->hostdef->d_HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_ERROR_LSB (sc->hostdef->d_HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_MASK (sc->hostdef->d_HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_COUNTER_LSB (sc->hostdef->d_HOST_INT_STATUS_COUNTER_LSB) +#define RX_LOOKAHEAD_VALID_ADDRESS (sc->hostdef->d_RX_LOOKAHEAD_VALID_ADDRESS) +#define WINDOW_DATA_ADDRESS (sc->hostdef->d_WINDOW_DATA_ADDRESS) +#define WINDOW_READ_ADDR_ADDRESS (sc->hostdef->d_WINDOW_READ_ADDR_ADDRESS) +#define WINDOW_WRITE_ADDR_ADDRESS (sc->hostdef->d_WINDOW_WRITE_ADDR_ADDRESS) +#define SOC_GLOBAL_RESET_ADDRESS (sc->hostdef->d_SOC_GLOBAL_RESET_ADDRESS) +#define RTC_STATE_ADDRESS (sc->hostdef->d_RTC_STATE_ADDRESS) +#define RTC_STATE_COLD_RESET_MASK (sc->hostdef->d_RTC_STATE_COLD_RESET_MASK) +#define PCIE_LOCAL_BASE_ADDRESS (sc->hostdef->d_PCIE_LOCAL_BASE_ADDRESS) +#define PCIE_SOC_WAKE_RESET (sc->hostdef->d_PCIE_SOC_WAKE_RESET) +#define PCIE_SOC_WAKE_ADDRESS (sc->hostdef->d_PCIE_SOC_WAKE_ADDRESS) +#define PCIE_SOC_WAKE_V_MASK (sc->hostdef->d_PCIE_SOC_WAKE_V_MASK) +#define RTC_STATE_V_MASK (sc->hostdef->d_RTC_STATE_V_MASK) +#define RTC_STATE_V_LSB (sc->hostdef->d_RTC_STATE_V_LSB) +#define FW_IND_EVENT_PENDING (sc->hostdef->d_FW_IND_EVENT_PENDING) +#define FW_IND_INITIALIZED (sc->hostdef->d_FW_IND_INITIALIZED) +#define RTC_STATE_V_ON (sc->hostdef->d_RTC_STATE_V_ON) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_MASK (sc->hostdef->d_HOST_INT_STATUS_MBOX_DATA_MASK) +#define HOST_INT_STATUS_MBOX_DATA_LSB (sc->hostdef->d_HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#if !defined(SOC_PCIE_BASE_ADDRESS) +#define SOC_PCIE_BASE_ADDRESS 0 +#endif + +#if !defined(PCIE_SOC_RDY_STATUS_ADDRESS) +#define PCIE_SOC_RDY_STATUS_ADDRESS 0 +#define PCIE_SOC_RDY_STATUS_BAR_MASK 0 +#endif + +#if !defined(MSI_MAGIC_ADR_ADDRESS) +#define MSI_MAGIC_ADR_ADDRESS 0 +#define MSI_MAGIC_ADDRESS 0 +#endif + +/* SET/GET macros */ +#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) +#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_GET(x) (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#define INVALID_REG_LOC_DUMMY_DATA 0xAA + + + +#define ROME_USB_RTC_SOC_BASE_ADDRESS 0x00000800 +#define ROME_USB_SOC_RESET_CONTROL_COLD_RST_LSB 0x0 +#define SOC_RESET_CONTROL_COLD_RST_LSB 8 +#define SOC_RESET_CONTROL_COLD_RST_MASK 0x00000100 +#define SOC_RESET_CONTROL_COLD_RST_SET(x) \ + (((x) << SOC_RESET_CONTROL_COLD_RST_LSB) & \ + SOC_RESET_CONTROL_COLD_RST_MASK) + + +#define AR6320_CORE_CLK_DIV_ADDR 0x403fa8 +#define AR6320_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320_CPU_SPEED_ADDR 0x403fa4 +#define AR6320V2_CORE_CLK_DIV_ADDR 0x403fd8 +#define AR6320V2_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320V2_CPU_SPEED_ADDR 0x403fd4 +#define AR6320V3_CORE_CLK_DIV_ADDR 0x404028 +#define AR6320V3_CPU_PLL_INIT_DONE_ADDR 0x404020 +#define AR6320V3_CPU_SPEED_ADDR 0x404024 + +typedef enum { + SOC_REFCLK_UNKNOWN = -1, /* Unsupported ref clock -- use PLL Bypass */ + SOC_REFCLK_48_MHZ = 0, + SOC_REFCLK_19_2_MHZ = 1, + SOC_REFCLK_24_MHZ = 2, + SOC_REFCLK_26_MHZ = 3, + SOC_REFCLK_37_4_MHZ = 4, + SOC_REFCLK_38_4_MHZ = 5, + SOC_REFCLK_40_MHZ = 6, + SOC_REFCLK_52_MHZ = 7, +} A_refclk_speed_t; + +#define A_REFCLK_UNKNOWN SOC_REFCLK_UNKNOWN +#define A_REFCLK_48_MHZ SOC_REFCLK_48_MHZ +#define A_REFCLK_19_2_MHZ SOC_REFCLK_19_2_MHZ +#define A_REFCLK_24_MHZ SOC_REFCLK_24_MHZ +#define A_REFCLK_26_MHZ SOC_REFCLK_26_MHZ +#define A_REFCLK_37_4_MHZ SOC_REFCLK_37_4_MHZ +#define A_REFCLK_38_4_MHZ SOC_REFCLK_38_4_MHZ +#define A_REFCLK_40_MHZ SOC_REFCLK_40_MHZ +#define A_REFCLK_52_MHZ SOC_REFCLK_52_MHZ + +#define TARGET_CPU_FREQ 176000000 + +struct wlan_pll_s { + u_int32_t refdiv; + u_int32_t div; + u_int32_t rnfrac; + u_int32_t outdiv; +}; + +struct cmnos_clock_s { + A_refclk_speed_t refclk_speed; + u_int32_t refclk_hz; + u_int32_t pll_settling_time; /* 50us */ + struct wlan_pll_s wlan_pll; +}; + +typedef struct TGT_REG_SECTION { + u_int32_t start_addr; + u_int32_t end_addr; +} tgt_reg_section; + +typedef struct TGT_REG_TABLE { + tgt_reg_section *section; + u_int32_t section_size; +} tgt_reg_table; +void target_register_tbl_attach(struct hif_usb_softc *sc, u32 target_type); +void hif_register_tbl_attach(struct hif_usb_softc *sc, u32 hif_type); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/usbdrv.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/usbdrv.c new file mode 100644 index 000000000000..0d5a0ae7dbdd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/USB/usbdrv.c @@ -0,0 +1,1156 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#include +#include +#include +#include + +#include "hif_usb_internal.h" +#include +#include "a_types.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME hif +#include "a_debug.h" +#include "a_usb_defs.h" +#include "htc.h" +#include "htc_packet.h" +#include "qwlan_version.h" +#include "if_usb.h" +#include "vos_api.h" + +#define IS_BULK_EP(attr) (((attr) & 3) == 0x02) +#define IS_INT_EP(attr) (((attr) & 3) == 0x03) +#define IS_ISOC_EP(attr) (((attr) & 3) == 0x01) +#define IS_DIR_IN(addr) ((addr) & 0x80) + +#define IS_FW_CRASH_DUMP(x) ((x == FW_ASSERT_PATTERN) || \ + (x == FW_REG_PATTERN) || \ + ((x & FW_RAMDUMP_PATTERN_MASK) == FW_RAMDUMP_PATTERN))?1:0 + +static void usb_hif_post_recv_transfers(HIF_USB_PIPE *recv_pipe, + int buffer_length); +static void usb_hif_post_recv_bundle_transfers(HIF_USB_PIPE *recv_pipe, + int buffer_length); +static void usb_hif_cleanup_recv_urb(HIF_URB_CONTEXT *urb_context); +static void usb_hif_free_urb_to_pipe(HIF_USB_PIPE *pipe, + HIF_URB_CONTEXT *urb_context) +{ + unsigned long flags; + + spin_lock_irqsave(&pipe->device->cs_lock, flags); + pipe->urb_cnt++; + DL_ListAdd(&pipe->urb_list_head, &urb_context->link); + spin_unlock_irqrestore(&pipe->device->cs_lock, flags); +} + +HIF_URB_CONTEXT *usb_hif_alloc_urb_from_pipe(HIF_USB_PIPE *pipe) +{ + HIF_URB_CONTEXT *urb_context = NULL; + DL_LIST *item; + unsigned long flags; + + spin_lock_irqsave(&pipe->device->cs_lock, flags); + item = DL_ListRemoveItemFromHead(&pipe->urb_list_head); + if (item != NULL) { + urb_context = A_CONTAINING_STRUCT(item, HIF_URB_CONTEXT, link); + pipe->urb_cnt--; + } + spin_unlock_irqrestore(&pipe->device->cs_lock, flags); + + return urb_context; +} + +static HIF_URB_CONTEXT *usb_hif_dequeue_pending_transfer(HIF_USB_PIPE *pipe) +{ + HIF_URB_CONTEXT *urb_context = NULL; + DL_LIST *item; + unsigned long flags; + + spin_lock_irqsave(&pipe->device->cs_lock, flags); + item = DL_ListRemoveItemFromHead(&pipe->urb_pending_list); + if (item != NULL) + urb_context = A_CONTAINING_STRUCT(item, HIF_URB_CONTEXT, link); + spin_unlock_irqrestore(&pipe->device->cs_lock, flags); + + return urb_context; +} + +void usb_hif_enqueue_pending_transfer(HIF_USB_PIPE *pipe, + HIF_URB_CONTEXT *urb_context) +{ + unsigned long flags; + + spin_lock_irqsave(&pipe->device->cs_lock, flags); + DL_ListInsertTail(&pipe->urb_pending_list, &urb_context->link); + spin_unlock_irqrestore(&pipe->device->cs_lock, flags); +} + +void usb_hif_remove_pending_transfer(HIF_URB_CONTEXT *urb_context) +{ + unsigned long flags; + + spin_lock_irqsave(&urb_context->pipe->device->cs_lock, flags); + DL_ListRemove(&urb_context->link); + spin_unlock_irqrestore(&urb_context->pipe->device->cs_lock, flags); +} + +static A_STATUS usb_hif_alloc_pipe_resources(HIF_USB_PIPE *pipe, int urb_cnt) +{ + A_STATUS status = A_OK; + int i; + HIF_URB_CONTEXT *urb_context; + + DL_LIST_INIT(&pipe->urb_list_head); + DL_LIST_INIT(&pipe->urb_pending_list); + + for (i = 0; i < urb_cnt; i++) { + urb_context = adf_os_mem_alloc(NULL, sizeof(*urb_context)); + if (NULL == urb_context) { + status = A_NO_MEMORY; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("urb_context is null\n")); + break; + } + adf_os_mem_zero(urb_context, sizeof(HIF_URB_CONTEXT)); + urb_context->pipe = pipe; + urb_context->urb = usb_alloc_urb(0, GFP_KERNEL); + + if (NULL == urb_context->urb) { + status = A_NO_MEMORY; + adf_os_mem_free(urb_context); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("urb_context->urb is null\n")); + break; + } + + /* note we are only allocate the urb contexts here, the actual + * URB is + * allocated from the kernel as needed to do a transaction + */ + pipe->urb_alloc++; + + usb_hif_free_urb_to_pipe(pipe, urb_context); + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_ENUM, ( + "athusb: alloc resources lpipe:%d hpipe:0x%X urbs:%d\n", + pipe->logical_pipe_num, + pipe->usb_pipe_handle, + pipe->urb_alloc)); + return status; +} + +static void usb_hif_free_pipe_resources(HIF_USB_PIPE *pipe) +{ + HIF_URB_CONTEXT *urb_context; + + if (NULL == pipe->device) { + /* nothing allocated for this pipe */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("pipe->device is null\n")); + return; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ( + "athusb: free resources lpipe:%d hpipe:0x%X urbs:%d avail:%d\n", + pipe->logical_pipe_num, + pipe->usb_pipe_handle, pipe->urb_alloc, + pipe->urb_cnt)); + + if (pipe->urb_alloc != pipe->urb_cnt) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "athusb: urb leak! lpipe:%d hpipe:0x%X urbs:%d avail:%d\n", + pipe->logical_pipe_num, + pipe->usb_pipe_handle, pipe->urb_alloc, + pipe->urb_cnt)); + } + + while (TRUE) { + urb_context = usb_hif_alloc_urb_from_pipe(pipe); + if (NULL == urb_context) + break; + + if (urb_context->buf) { + adf_nbuf_free(urb_context->buf); + urb_context->buf = NULL; + } + + usb_free_urb(urb_context->urb); + urb_context->urb = NULL; + adf_os_mem_free(urb_context); + } + +} + +static A_UINT8 usb_hif_get_logical_pipe_num(HIF_DEVICE_USB *device, + A_UINT8 ep_address, int *urb_count) +{ + A_UINT8 pipe_num = HIF_USB_PIPE_INVALID; + + switch (ep_address) { + case USB_EP_ADDR_APP_CTRL_IN: + pipe_num = HIF_RX_CTRL_PIPE; + *urb_count = RX_URB_COUNT; + break; + case USB_EP_ADDR_APP_DATA_IN: + pipe_num = HIF_RX_DATA_PIPE; + *urb_count = RX_URB_COUNT; + break; + case USB_EP_ADDR_APP_INT_IN: + pipe_num = HIF_RX_INT_PIPE; + *urb_count = RX_URB_COUNT; + break; + case USB_EP_ADDR_APP_DATA2_IN: + pipe_num = HIF_RX_DATA2_PIPE; + *urb_count = RX_URB_COUNT; + break; + case USB_EP_ADDR_APP_CTRL_OUT: + pipe_num = HIF_TX_CTRL_PIPE; + *urb_count = TX_URB_COUNT; + break; + case USB_EP_ADDR_APP_DATA_LP_OUT: + pipe_num = HIF_TX_DATA_LP_PIPE; + *urb_count = TX_URB_COUNT; + break; + case USB_EP_ADDR_APP_DATA_MP_OUT: + pipe_num = HIF_TX_DATA_MP_PIPE; + *urb_count = TX_URB_COUNT; + break; + case USB_EP_ADDR_APP_DATA_HP_OUT: + pipe_num = HIF_TX_DATA_HP_PIPE; + *urb_count = TX_URB_COUNT; + break; + default: + /* note: there may be endpoints not currently used */ + break; + } + + return pipe_num; +} + +A_STATUS usb_hif_setup_pipe_resources(HIF_DEVICE_USB *device) +{ + struct usb_interface *interface = device->interface; + struct usb_host_interface *iface_desc = interface->cur_altsetting; + struct usb_endpoint_descriptor *endpoint; + int i; + int urbcount; + A_STATUS status = A_OK; + HIF_USB_PIPE *pipe; + A_UINT8 pipe_num; + + /* walk decriptors and setup pipes */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (IS_BULK_EP(endpoint->bmAttributes)) { + AR_DEBUG_PRINTF(USB_HIF_DEBUG_ENUM, ( + "%s Bulk Ep:0x%2.2X " "maxpktsz:%d\n", + IS_DIR_IN(endpoint->bEndpointAddress) ? + "RX" : "TX", + endpoint->bEndpointAddress, + le16_to_cpu + (endpoint->wMaxPacketSize))); + } else if (IS_INT_EP(endpoint->bmAttributes)) { + AR_DEBUG_PRINTF(USB_HIF_DEBUG_ENUM, ( + "%s Int Ep:0x%2.2X maxpktsz:%d interval:%d\n", + IS_DIR_IN(endpoint->bEndpointAddress) ? + "RX" : "TX", + endpoint->bEndpointAddress, + le16_to_cpu(endpoint->wMaxPacketSize), + endpoint->bInterval)); + } else if (IS_ISOC_EP(endpoint->bmAttributes)) { + /* TODO for ISO */ + AR_DEBUG_PRINTF(USB_HIF_DEBUG_ENUM, ( + "%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d\n", + IS_DIR_IN(endpoint->bEndpointAddress) ? + "RX" : "TX", + endpoint->bEndpointAddress, + le16_to_cpu(endpoint->wMaxPacketSize), + endpoint->bInterval)); + } + urbcount = 0; + + pipe_num = usb_hif_get_logical_pipe_num(device, + endpoint-> + bEndpointAddress, + &urbcount); + if (HIF_USB_PIPE_INVALID == pipe_num) + continue; + + pipe = &device->pipes[pipe_num]; + if (pipe->device != NULL) { + /* hmmm..pipe was already setup */ + continue; + } + + pipe->device = device; + pipe->logical_pipe_num = pipe_num; + pipe->ep_address = endpoint->bEndpointAddress; + pipe->max_packet_size = le16_to_cpu(endpoint->wMaxPacketSize); + + if (IS_BULK_EP(endpoint->bmAttributes)) { + if (IS_DIR_IN(pipe->ep_address)) { + pipe->usb_pipe_handle = + usb_rcvbulkpipe(device->udev, + pipe->ep_address); + } else { + pipe->usb_pipe_handle = + usb_sndbulkpipe(device->udev, + pipe->ep_address); + } + } else if (IS_INT_EP(endpoint->bmAttributes)) { + if (IS_DIR_IN(pipe->ep_address)) { + pipe->usb_pipe_handle = + usb_rcvintpipe(device->udev, + pipe->ep_address); + } else { + pipe->usb_pipe_handle = + usb_sndintpipe(device->udev, + pipe->ep_address); + } + } else if (IS_ISOC_EP(endpoint->bmAttributes)) { + /* TODO for ISO */ + if (IS_DIR_IN(pipe->ep_address)) { + pipe->usb_pipe_handle = + usb_rcvisocpipe(device->udev, + pipe->ep_address); + } else { + pipe->usb_pipe_handle = + usb_sndisocpipe(device->udev, + pipe->ep_address); + } + } + pipe->ep_desc = endpoint; + + if (!IS_DIR_IN(pipe->ep_address)) + pipe->flags |= HIF_USB_PIPE_FLAG_TX; + + status = usb_hif_alloc_pipe_resources(pipe, urbcount); + if (A_FAILED(status)) + break; + + } + + return status; +} + +void usb_hif_cleanup_pipe_resources(HIF_DEVICE_USB *device) +{ + int i; + + for (i = 0; i < HIF_USB_PIPE_MAX; i++) + usb_hif_free_pipe_resources(&device->pipes[i]); +} + +static void usb_hif_flush_pending_transfers(HIF_USB_PIPE *pipe) +{ + HIF_URB_CONTEXT *urb_context; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s pipe : %d\n", __func__, + pipe->logical_pipe_num)); + + while (1) { + urb_context = usb_hif_dequeue_pending_transfer(pipe); + if (NULL == urb_context) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("urb_context is NULL\n")); + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" pending urb ctxt: 0x%p\n", + urb_context)); + if (urb_context->urb != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + (" killing urb: 0x%p\n", + urb_context->urb)); + /* killing the URB will cause the completion routines to + * run + */ + usb_kill_urb(urb_context->urb); + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +void usb_hif_flush_all(HIF_DEVICE_USB *device) +{ + int i; + HIF_USB_PIPE *pipe; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + for (i = 0; i < HIF_USB_PIPE_MAX; i++) { + if (device->pipes[i].device != NULL) { + usb_hif_flush_pending_transfers(&device->pipes[i]); + pipe = &device->pipes[i]; +#ifndef HIF_USB_TASKLET + flush_work(&pipe->io_complete_work); +#endif + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +static void usb_hif_cleanup_recv_urb(HIF_URB_CONTEXT *urb_context) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + if (urb_context->buf != NULL) { + adf_nbuf_free(urb_context->buf); + urb_context->buf = NULL; + } + + usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +void usb_hif_cleanup_transmit_urb(HIF_URB_CONTEXT *urb_context) +{ + usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context); +} + +static void usb_hif_usb_recv_prestart_complete(struct urb *urb) +{ + HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; + A_STATUS status = A_OK; + adf_nbuf_t buf = NULL; + HIF_USB_PIPE *pipe = urb_context->pipe; + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( + "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", + __func__, + pipe->logical_pipe_num, + urb->status, urb->actual_length, + urb)); + + /* this urb is not pending anymore */ + usb_hif_remove_pending_transfer(urb_context); + + do { + if (urb->status != 0) { + status = A_ECOMM; + switch (urb->status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* NOTE: no need to spew these errors when + * device is removed + * or urb is killed due to driver shutdown + */ + status = A_ECANCELED; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", + __func__, + pipe->logical_pipe_num, + pipe->ep_address, + urb->status)); + break; + } + break; + } + + if (urb->actual_length == 0) + break; + + buf = urb_context->buf; + /* we are going to pass it up */ + urb_context->buf = NULL; + adf_nbuf_put_tail(buf, urb->actual_length); + if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) { + A_UINT8 *data; + A_UINT32 len; + adf_nbuf_peek_header(buf, &data, &len); + DebugDumpBytes(data, len, "hif recv data"); + } + + /* note: queue implements a lock */ + skb_queue_tail(&pipe->io_comp_queue, buf); +#ifdef HIF_USB_TASKLET + tasklet_schedule(&pipe->io_complete_tasklet); +#else + schedule_work(&pipe->io_complete_work); +#endif + } while (FALSE); + + usb_hif_cleanup_recv_urb(urb_context); + + /* Prestart URBs runs out and now start working receive pipe. */ + if (--pipe->urb_prestart_cnt == 0) { + usb_hif_start_recv_pipes(pipe->device); + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); +} + +static void usb_hif_usb_recv_complete(struct urb *urb) +{ + HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; + A_STATUS status = A_OK; + adf_nbuf_t buf = NULL; + HIF_USB_PIPE *pipe = urb_context->pipe; + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( + "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", + __func__, + pipe->logical_pipe_num, + urb->status, urb->actual_length, + urb)); + + /* this urb is not pending anymore */ + usb_hif_remove_pending_transfer(urb_context); + + do { + + if (urb->status != 0) { + status = A_ECOMM; + switch (urb->status) { +#ifdef RX_SG_SUPPORT + case -EOVERFLOW: + urb->actual_length = HIF_USB_RX_BUFFER_SIZE; + status = A_OK; + break; +#endif + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* NOTE: no need to spew these errors when + * device is removed + * or urb is killed due to driver shutdown + */ + status = A_ECANCELED; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", + __func__, + pipe->logical_pipe_num, + pipe->ep_address, + urb->status)); + break; + } + break; + } + + if (urb->actual_length == 0) + break; + + buf = urb_context->buf; + /* we are going to pass it up */ + urb_context->buf = NULL; + adf_nbuf_put_tail(buf, urb->actual_length); + if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) { + A_UINT8 *data; + A_UINT32 len; + adf_nbuf_peek_header(buf, &data, &len); + DebugDumpBytes(data, len, "hif recv data"); + } + + /* note: queue implements a lock */ + skb_queue_tail(&pipe->io_comp_queue, buf); +#ifdef HIF_USB_TASKLET + tasklet_schedule(&pipe->io_complete_tasklet); +#else + schedule_work(&pipe->io_complete_work); +#endif + } while (FALSE); + + usb_hif_cleanup_recv_urb(urb_context); + + /* Only re-submit URB when STATUS is success and HIF is not at the + suspend state. + */ + if (A_SUCCESS(status) && !pipe->device->sc->suspend_state) { + if (pipe->urb_cnt >= pipe->urb_cnt_thresh) { + /* our free urbs are piling up, post more transfers */ + usb_hif_post_recv_transfers(pipe, + HIF_USB_RX_BUFFER_SIZE); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: pipe: %d, fail to post URB: status(%d) suspend (%d)\n", + __func__, + pipe->logical_pipe_num, + urb->status, + pipe->device->sc->suspend_state)); + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); +} + +static void usb_hif_usb_recv_bundle_complete(struct urb *urb) +{ + HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; + A_STATUS status = A_OK; + adf_nbuf_t buf = NULL; + HIF_USB_PIPE *pipe = urb_context->pipe; + A_UINT8 *netdata, *netdata_new; + A_UINT32 netlen, netlen_new; + HTC_FRAME_HDR *HtcHdr; + A_UINT16 payloadLen; + adf_nbuf_t new_skb = NULL; + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( + "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", + __func__, + pipe->logical_pipe_num, + urb->status, urb->actual_length, + urb)); + + /* this urb is not pending anymore */ + usb_hif_remove_pending_transfer(urb_context); + + do { + + if (urb->status != 0) { + status = A_ECOMM; + switch (urb->status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* NOTE: no need to spew these errors when + * device is removed + * or urb is killed due to driver shutdown + */ + status = A_ECANCELED; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", + __func__, + pipe->logical_pipe_num, + pipe->ep_address, + urb->status)); + break; + } + break; + } + + if (urb->actual_length == 0) + break; + + buf = urb_context->buf; + + if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) { + A_UINT8 *data; + A_UINT32 len; + adf_nbuf_peek_header(buf, &data, &len); + DebugDumpBytes(data, len, "hif recv data"); + } + + adf_nbuf_peek_header(buf, &netdata, &netlen); + netlen = urb->actual_length; + + do { + A_UINT16 frame_len; + + if (IS_FW_CRASH_DUMP(*(A_UINT32 *) netdata)) + frame_len = netlen; + else { + /* Hack into HTC header for bundle processing */ + HtcHdr = (HTC_FRAME_HDR *) netdata; + if (HtcHdr->EndpointID >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb: Rx: invalid EndpointID=%d\n", + HtcHdr->EndpointID)); + break; + } + + payloadLen = HtcHdr->PayloadLen; + payloadLen = A_LE2CPU16(payloadLen); + + if (payloadLen > HIF_USB_RX_BUFFER_SIZE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb: payloadLen too long %u\n", + payloadLen)); + break; + } + frame_len = (HTC_HDR_LENGTH + payloadLen); + } + + if (netlen >= frame_len) { + /* allocate a new skb and copy */ + new_skb = + adf_nbuf_alloc(NULL, frame_len, 0, 4, + FALSE); + if (new_skb == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "athusb: allocate skb (len=%u) failed\n", + frame_len)); + break; + } + + adf_nbuf_peek_header(new_skb, &netdata_new, + &netlen_new); + adf_os_mem_copy(netdata_new, netdata, + frame_len); + adf_nbuf_put_tail(new_skb, frame_len); + skb_queue_tail(&pipe->io_comp_queue, new_skb); + new_skb = NULL; + + netdata += frame_len; + netlen -= frame_len; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "athusb: subframe length %d not fitted into bundle packet length %d\n" + , netlen, frame_len)); + break; + } + + } while (netlen); +#ifdef HIF_USB_TASKLET + tasklet_schedule(&pipe->io_complete_tasklet); +#else + schedule_work(&pipe->io_complete_work); +#endif + } while (FALSE); + + if (urb_context->buf == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb: buffer in urb_context is NULL\n")); + } + + /* reset urb_context->buf ==> seems not necessary */ + usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context); + + if (A_SUCCESS(status)) { + if (pipe->urb_cnt >= pipe->urb_cnt_thresh) { + /* our free urbs are piling up, post more transfers */ + usb_hif_post_recv_bundle_transfers(pipe, + pipe->device->rx_bundle_buf_len); + } + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); +} + +/* post prestart recv urbs for a given pipe */ +static void usb_hif_post_recv_prestart_transfers(HIF_USB_PIPE *recv_pipe, + int prestart_urb) +{ + HIF_URB_CONTEXT *urb_context; + a_uint8_t *data; + a_uint32_t len; + struct urb *urb; + int i, usb_status, buffer_length = HIF_USB_RX_BUFFER_SIZE; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + for (i = 0; i < prestart_urb; i++) { + urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe); + if (NULL == urb_context) + break; + + urb_context->buf = + adf_nbuf_alloc(NULL, buffer_length, 0, 4, FALSE); + if (NULL == urb_context->buf) { + usb_hif_cleanup_recv_urb(urb_context); + break; + } + + adf_nbuf_peek_header(urb_context->buf, &data, &len); + + urb = urb_context->urb; + + usb_fill_bulk_urb(urb, + recv_pipe->device->udev, + recv_pipe->usb_pipe_handle, + data, + buffer_length, + usb_hif_usb_recv_prestart_complete, + urb_context); + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( + "athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%p\n", + recv_pipe->logical_pipe_num, + recv_pipe->usb_pipe_handle, + recv_pipe->ep_address, buffer_length, + urb_context->buf)); + + usb_hif_enqueue_pending_transfer(recv_pipe, urb_context); + + usb_status = usb_submit_urb(urb, GFP_ATOMIC); + + if (usb_status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb : usb bulk recv failed %d\n", + usb_status)); + usb_hif_remove_pending_transfer(urb_context); + usb_hif_cleanup_recv_urb(urb_context); + break; + } else + recv_pipe->urb_prestart_cnt++; + + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); +} + +/* post recv urbs for a given pipe */ +static void usb_hif_post_recv_transfers(HIF_USB_PIPE *recv_pipe, + int buffer_length) +{ + HIF_URB_CONTEXT *urb_context; + a_uint8_t *data; + a_uint32_t len; + struct urb *urb; + int usb_status; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + while (1) { + + urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe); + if (NULL == urb_context) + break; + + urb_context->buf = + adf_nbuf_alloc(NULL, buffer_length, 0, 4, FALSE); + if (NULL == urb_context->buf) { + usb_hif_cleanup_recv_urb(urb_context); + break; + } + + adf_nbuf_peek_header(urb_context->buf, &data, &len); + + urb = urb_context->urb; + + usb_fill_bulk_urb(urb, + recv_pipe->device->udev, + recv_pipe->usb_pipe_handle, + data, + buffer_length, + usb_hif_usb_recv_complete, urb_context); + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( + "athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%p\n", + recv_pipe->logical_pipe_num, + recv_pipe->usb_pipe_handle, + recv_pipe->ep_address, buffer_length, + urb_context->buf)); + + usb_hif_enqueue_pending_transfer(recv_pipe, urb_context); + + usb_status = usb_submit_urb(urb, GFP_ATOMIC); + + if (usb_status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb : usb bulk recv failed %d\n", + usb_status)); + usb_hif_remove_pending_transfer(urb_context); + usb_hif_cleanup_recv_urb(urb_context); + break; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + +} + +/* post recv urbs for a given pipe */ +static void usb_hif_post_recv_bundle_transfers(HIF_USB_PIPE *recv_pipe, + int buffer_length) +{ + HIF_URB_CONTEXT *urb_context; + a_uint8_t *data; + a_uint32_t len; + struct urb *urb; + int usb_status; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + + while (1) { + + urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe); + if (NULL == urb_context) + break; + + if (NULL == urb_context->buf) { + urb_context->buf = + adf_nbuf_alloc(NULL, buffer_length, 0, 4, FALSE); + if (NULL == urb_context->buf) { + usb_hif_cleanup_recv_urb(urb_context); + break; + } + } + + adf_nbuf_peek_header(urb_context->buf, &data, &len); + + urb = urb_context->urb; + usb_fill_bulk_urb(urb, + recv_pipe->device->udev, + recv_pipe->usb_pipe_handle, + data, + buffer_length, + usb_hif_usb_recv_bundle_complete, + urb_context); + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( + "athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%p\n", + recv_pipe->logical_pipe_num, + recv_pipe->usb_pipe_handle, + recv_pipe->ep_address, buffer_length, + urb_context->buf)); + + usb_hif_enqueue_pending_transfer(recv_pipe, urb_context); + + usb_status = usb_submit_urb(urb, GFP_ATOMIC); + + if (usb_status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("athusb : usb bulk recv failed %d\n", + usb_status)); + usb_hif_remove_pending_transfer(urb_context); + usb_hif_free_urb_to_pipe(urb_context->pipe, + urb_context); + break; + } + + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + +} + +void usb_hif_prestart_recv_pipes(HIF_DEVICE_USB *device) +{ + HIF_USB_PIPE *pipe = &device->pipes[HIF_RX_DATA_PIPE]; + + /* + * USB driver learn to support bundle or not until the firmware + * download and ready. Only allocate some URBs for control message + * communication during the initial phase then start the final + * working pipe after all information understood. + */ + usb_hif_post_recv_prestart_transfers(pipe, 8); +} + +void usb_hif_start_recv_pipes(HIF_DEVICE_USB *device) +{ + HIF_USB_PIPE *pipe; + a_uint32_t buf_len; + + printk("Enter:%s,Line:%d \n", __func__,__LINE__); + + pipe = &device->pipes[HIF_RX_DATA_PIPE]; + pipe->urb_cnt_thresh = pipe->urb_alloc / 2; + + printk("Post URBs to RX_DATA_PIPE: %d\n", + device->pipes[HIF_RX_DATA_PIPE].urb_cnt); + if (device->is_bundle_enabled) { + usb_hif_post_recv_bundle_transfers(pipe, + pipe->device->rx_bundle_buf_len); + } else { + buf_len = HIF_USB_RX_BUFFER_SIZE; + usb_hif_post_recv_transfers(pipe, buf_len); + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, + ("athusb bulk recv len %d\n", + buf_len)); + + if (!hif_usb_disable_rxdata2) { + printk("Post URBs to RX_DATA2_PIPE: %d\n", + device->pipes[HIF_RX_DATA2_PIPE].urb_cnt); + + pipe = &device->pipes[HIF_RX_DATA2_PIPE]; + pipe->urb_cnt_thresh = pipe->urb_alloc / 2; + usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE); + } +#ifdef USB_HIF_TEST_INTERRUPT_IN + printk("Post URBs to RX_INT_PIPE: %d\n", + device->pipes[HIF_RX_INT_PIPE].urb_cnt); + + pipe = &device->pipes[HIF_RX_INT_PIPE]; + pipe->urb_cnt_thresh = pipe->urb_alloc / 2; + usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE); +#endif + + printk("Exit:%s,Line:%d \n", __func__,__LINE__); +} + +A_STATUS usb_hif_submit_ctrl_out(HIF_DEVICE_USB *device, + a_uint8_t req, + a_uint16_t value, + a_uint16_t index, void *data, a_uint32_t size) +{ + a_int32_t result = 0; + A_STATUS ret = A_OK; + a_uint8_t *buf = NULL; + + do { + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + if (NULL == buf) { + ret = A_NO_MEMORY; + break; + } + memcpy(buf, (a_uint8_t *) data, size); + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_CTRL_TRANS, ( + "ctrl-out req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d\n", + req, value, index, size)); + + result = usb_control_msg(device->udev, + usb_sndctrlpipe(device->udev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, + size, 2 * HZ); + + if (result < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( + "%s failed,result = %d\n", + __func__, result)); + ret = A_ERROR; + } + + } while (FALSE); + + if (buf != NULL) + kfree(buf); + + return ret; +} + +A_STATUS usb_hif_submit_ctrl_in(HIF_DEVICE_USB *device, + a_uint8_t req, + a_uint16_t value, + a_uint16_t index, void *data, a_uint32_t size) +{ + a_int32_t result = 0; + A_STATUS ret = A_OK; + a_uint8_t *buf = NULL; + + do { + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + if (NULL == buf) { + ret = A_NO_MEMORY; + break; + } + } + + AR_DEBUG_PRINTF(USB_HIF_DEBUG_CTRL_TRANS, ( + "ctrl-in req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d\n", + req, value, index, size)); + + result = usb_control_msg(device->udev, + usb_rcvctrlpipe(device->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, + size, 2 * HZ); + + if (result < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s failed,result = %d\n", + __func__, result)); + ret = A_ERROR; + break; + } + + memcpy((a_uint8_t *) data, buf, size); + + } while (FALSE); + + if (buf != NULL) + kfree(buf); + + return ret; +} + +#ifdef HIF_USB_TASKLET +void usb_hif_io_comp_tasklet(long unsigned int context) +#else +void usb_hif_io_comp_work(struct work_struct *work) +#endif +{ +#ifdef HIF_USB_TASKLET + HIF_USB_PIPE *pipe = (HIF_USB_PIPE *) context; +#else + HIF_USB_PIPE *pipe = container_of(work, HIF_USB_PIPE, io_complete_work); +#endif + adf_nbuf_t buf; + HIF_DEVICE_USB *device; + HTC_FRAME_HDR *HtcHdr; + struct hif_usb_softc *sc; + A_UINT8 *data; + A_UINT32 len; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + device = pipe->device; + sc = device->sc; + + while ((buf = skb_dequeue(&pipe->io_comp_queue))) { + a_mem_trace(buf); + if (pipe->flags & HIF_USB_PIPE_FLAG_TX) { + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, + ("+athusb xmit callback " "buf:0x%p\n", + buf)); + HtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(buf, 0); + +#ifdef ATH_11AC_TXCOMPACT +#error ATH_11AC_TXCOMPACT only support for High Latency mode +#else + device->htcCallbacks.txCompletionHandler(device-> + htcCallbacks. + Context, buf, + HtcHdr-> + EndpointID); +#endif + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT, + ("-athusb xmit callback\n")); + } else { + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, + ("+athusb recv callback buf:" "0x%p\n", + buf)); + adf_nbuf_peek_header(buf, &data, &len); + + if (IS_FW_CRASH_DUMP(*((A_UINT32 *) data))) { + sc->fw_data = data; + sc->fw_data_len = len; + device->htcCallbacks.fwEventHandler( + device->htcCallbacks.Context, A_USB_ERROR); + dev_kfree_skb(buf); + } else { + device->htcCallbacks.rxCompletionHandler( + device->htcCallbacks.Context, buf, + pipe->logical_pipe_num); + AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, + ("-athusb recv callback\n")); + } + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); + +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c new file mode 100644 index 000000000000..3600565c76fe --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if defined(CONFIG_ATH_PROCFS_DIAG_SUPPORT) +#include /* Specifically, a module */ +#include /* We're doing kernel work */ +#include /* We're doing kernel work */ +#include /* Necessary because we use the proc fs */ +#include /* for copy_from_user */ +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#elif defined(HIF_SDIO) +#include "if_ath_sdio.h" +#endif +#include "vos_api.h" +#include + +#define PROCFS_NAME "athdiagpfs" +#define PROCFS_DIR "cld" + +/** + * This structure hold information about the /proc file + * + */ +static struct proc_dir_entry *proc_file, *proc_dir; + +static void *get_hif_hdl_from_file(struct file *file) +{ +#if defined(HIF_PCI) + struct hif_pci_softc *scn; +#elif defined(HIF_USB) + struct hif_usb_softc *scn; +#elif defined(HIF_SDIO) + struct ath_hif_sdio_softc *scn; +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#if defined(HIF_PCI) + scn = (struct hif_pci_softc *)PDE_DATA(file_inode(file)); +#elif defined(HIF_USB) + scn = (struct hif_usb_softc *)PDE_DATA(file_inode(file)); +#elif defined(HIF_SDIO) + scn = (struct ath_hif_sdio_softc *)PDE_DATA(file_inode(file)); +#endif +#else +#if defined(HIF_PCI) + scn = (struct hif_pci_softc *)(PDE(file->f_path.dentry->d_inode)->data); +#elif defined(HIF_USB) + scn = (struct hif_usb_softc *)(PDE(file->f_path.dentry->d_inode)->data); +#elif defined(HIF_SDIO) + scn = (struct ath_hif_sdio_softc *)(PDE(file->f_path.dentry->d_inode)->data); +#endif +#endif + return (void*)scn->ol_sc->hif_hdl; +} + +static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + hif_handle_t hif_hdl; + int rv; + A_UINT8 *read_buffer = NULL; + + read_buffer = (A_UINT8 *)vos_mem_malloc(count); + if (NULL == read_buffer) { + pr_debug("%s: vos_mem_alloc failed\n", __func__); + return -EINVAL; + } + + hif_hdl = get_hif_hdl_from_file(file); + pr_debug("rd buff 0x%p cnt %zu offset 0x%x buf 0x%p\n", + read_buffer,count, + (int)*pos, buf); + + if ((count == 4) && ((((A_UINT32)(*pos)) & 3) == 0)) { + /* reading a word? */ + rv = HIFDiagReadAccess(hif_hdl, (A_UINT32)(*pos), + (A_UINT32 *)read_buffer); + } else { + rv = HIFDiagReadMem(hif_hdl, (A_UINT32)(*pos), + (A_UINT8 *)read_buffer, count); + } + + if(copy_to_user(buf, read_buffer, count)) { + vos_mem_free(read_buffer); + return -EFAULT; + } else + vos_mem_free(read_buffer); + + if (rv == 0) { + return count; + } else { + return -EIO; + } +} + +static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + hif_handle_t hif_hdl; + int rv; + A_UINT8 *write_buffer = NULL; + + write_buffer = (A_UINT8 *)vos_mem_malloc(count); + if (NULL == write_buffer) { + pr_debug("%s: vos_mem_alloc failed\n", __func__); + return -EINVAL; + } + if(copy_from_user(write_buffer, buf, count)) { + vos_mem_free(write_buffer); + return -EFAULT; + } + + hif_hdl = get_hif_hdl_from_file(file); + pr_debug("wr buff 0x%p buf 0x%p cnt %zu offset 0x%x value 0x%x\n", + write_buffer, buf, count, + (int)*pos, *((A_UINT32 *)write_buffer)); + + if ((count == 4) && ((((A_UINT32)(*pos)) & 3) == 0)) { + /* reading a word? */ + A_UINT32 value = *((A_UINT32 *)write_buffer); + rv = HIFDiagWriteAccess(hif_hdl, + (A_UINT32)(*pos), value); + } else { + rv = HIFDiagWriteMem(hif_hdl, (A_UINT32)(*pos), + (A_UINT8 *)write_buffer, count); + } + + vos_mem_free(write_buffer); + if (rv == 0) { + return count; + } else { + return -EIO; + } +} + +static const struct file_operations athdiag_fops = { + .read = ath_procfs_diag_read, + .write = ath_procfs_diag_write, +}; + +/** + *This function is called when the module is loaded + * + */ +int athdiag_procfs_init(void *scn) +{ + proc_dir = proc_mkdir(PROCFS_DIR, NULL); + if (proc_dir == NULL) { + remove_proc_entry(PROCFS_DIR, NULL); + pr_debug("Error: Could not initialize /proc/%s\n", + PROCFS_DIR); + return -ENOMEM; + } + + proc_file = proc_create_data(PROCFS_NAME, + S_IRUSR | S_IWUSR, proc_dir, + &athdiag_fops, (void *)scn); + if (proc_file == NULL) { + remove_proc_entry(PROCFS_NAME, proc_dir); + pr_debug("Error: Could not initialize /proc/%s\n", + PROCFS_NAME); + return -ENOMEM; + } + + pr_debug("/proc/%s/%s created\n", PROCFS_DIR, PROCFS_NAME); + return 0; /* everything is ok */ +} + +/** + *This function is called when the module is unloaded + * + */ +void athdiag_procfs_remove(void) +{ + if (proc_dir != NULL) { + remove_proc_entry(PROCFS_NAME, proc_dir); + pr_debug("/proc/%s/%s removed\n", PROCFS_DIR, PROCFS_NAME); + remove_proc_entry(PROCFS_DIR, NULL); + pr_debug("/proc/%s removed\n", PROCFS_DIR); + proc_dir = NULL; + } +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_bmi_reg_access.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_bmi_reg_access.c new file mode 100644 index 000000000000..7e6918d873c8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_bmi_reg_access.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + *Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "athdefs.h" +#include "a_types.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME bmi +#include "a_debug.h" +#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) +#include "hif.h" +#include "bmi.h" +#include "htc_api.h" +#include "if_ath_sdio.h" +#include "regtable.h" + +#define BMI_COMMUNICATION_TIMEOUT 100000 + +static A_BOOL pendingEventsFuncCheck = FALSE; +static A_UINT32 commandCredits = 0; +static A_UINT32 *pBMICmdCredits = &commandCredits; + +/* BMI Access routines */ +static A_STATUS +bmiBufferSend(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length) +{ + A_STATUS status; + A_UINT32 timeout; + A_UINT32 address; + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress[0], sizeof(mboxAddress)); + + *pBMICmdCredits = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + + while(timeout-- && !(*pBMICmdCredits)) { + /* Read the counter register to get the command credits */ + address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; + /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause + * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to + * make all HIF accesses 4-byte aligned */ + status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, 4, + HIF_RD_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n")); + return A_ERROR; + } + /* the counter is only 8=bits, ignore anything in the upper 3 bytes */ + (*pBMICmdCredits) &= 0xFF; + } + + if (*pBMICmdCredits) { + address = mboxAddress[ENDPOINT1]; + status = HIFReadWrite(device, address, buffer, length, + HIF_WR_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n")); + return A_ERROR; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n")); + return A_ERROR; + } + + return status; +} + +static A_STATUS +bmiBufferReceive(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length, + A_BOOL want_timeout) +{ + A_STATUS status; + A_UINT32 address; + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + HIF_PENDING_EVENTS_INFO hifPendingEvents; + static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL; + + if (!pendingEventsFuncCheck) { + /* see if the HIF layer implements an alternative function to get pending events + * do this only once! */ + HIFConfigureDevice(device, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + &getPendingEventsFunc, + sizeof(getPendingEventsFunc)); + pendingEventsFuncCheck = TRUE; + } + + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress[0], sizeof(mboxAddress)); + + /* + * During normal bootup, small reads may be required. + * Rather than issue an HIF Read and then wait as the Target + * adds successive bytes to the FIFO, we wait here until + * we know that response data is available. + * + * This allows us to cleanly timeout on an unexpected + * Target failure rather than risk problems at the HIF level. In + * particular, this avoids SDIO timeouts and possibly garbage + * data on some host controllers. And on an interconnect + * such as Compact Flash (as well as some SDIO masters) which + * does not provide any indication on data timeout, it avoids + * a potential hang or garbage response. + * + * Synchronization is more difficult for reads larger than the + * size of the MBOX FIFO (128B), because the Target is unable + * to push the 129th byte of data until AFTER the Host posts an + * HIF Read and removes some FIFO data. So for large reads the + * Host proceeds to post an HIF Read BEFORE all the data is + * actually available to read. Fortunately, large BMI reads do + * not occur in practice -- they're supported for debug/development. + * + * So Host/Target BMI synchronization is divided into these cases: + * CASE 1: length < 4 + * Should not happen + * + * CASE 2: 4 <= length <= 128 + * Wait for first 4 bytes to be in FIFO + * If CONSERVATIVE_BMI_READ is enabled, also wait for + * a BMI command credit, which indicates that the ENTIRE + * response is available in the the FIFO + * + * CASE 3: length > 128 + * Wait for the first 4 bytes to be in FIFO + * + * For most uses, a small timeout should be sufficient and we will + * usually see a response quickly; but there may be some unusual + * (debug) cases of BMI_EXECUTE where we want an larger timeout. + * For now, we use an unbounded busy loop while waiting for + * BMI_EXECUTE. + * + * If BMI_EXECUTE ever needs to support longer-latency execution, + * especially in production, this code needs to be enhanced to sleep + * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently + * a function of Host processor speed. + */ + if (length >= 4) { /* NB: Currently, always true */ + /* + * NB: word_available is declared static for esoteric reasons + * having to do with protection on some OSes. + */ + static A_UINT32 word_available; + A_UINT32 timeout; + + word_available = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + while((!want_timeout || timeout--) && !word_available) { + + if (getPendingEventsFunc != NULL) { + status = getPendingEventsFunc(device, + &hifPendingEvents, + NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n")); + break; + } + + if (hifPendingEvents.AvailableRecvBytes >= sizeof(A_UINT32)) { + word_available = 1; + } + continue; + } +#if defined(SDIO_3_0) + status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS, (A_UINT8 *)&word_available, sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read HOST_INT_STATUS_ADDRESS register\n")); + return A_ERROR; + } + +#else + status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (A_UINT8 *)&word_available, sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n")); + return A_ERROR; + } +#endif + /* We did a 4-byte read to the same register; all we really want is one bit */ +#if defined(SDIO_3_0) + word_available = (HOST_INT_STATUS_MBOX_DATA_GET(word_available) & ( 1 << ENDPOINT1)); +#else + word_available &= (1 << ENDPOINT1); +#endif + + } + + if (!word_available) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n")); + return A_ERROR; + } + } + +#define CONSERVATIVE_BMI_READ 0 +#if CONSERVATIVE_BMI_READ + /* + * This is an extra-conservative CREDIT check. It guarantees + * that ALL data is available in the FIFO before we start to + * read from the interconnect. + * + * This credit check is useless when firmware chooses to + * allow multiple outstanding BMI Command Credits, since the next + * credit will already be present. To restrict the Target to one + * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT. + * + * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set) + * we cannot wait for the next credit because the Target's FIFO + * will not hold the entire response. So we need the Host to + * start to empty the FIFO sooner. (And again, large reads are + * not used in practice; they are for debug/development only.) + * + * For a more conservative Host implementation (which would be + * safer for a Compact Flash interconnect): + * Set CONSERVATIVE_BMI_READ (above) to 1 + * Set HI_OPTION_BMI_CRED_LIMIT and + * reduce BMI_DATASZ_MAX to 32 or 64 + */ + if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */ + A_UINT32 timeout; + + *pBMICmdCredits = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + while((!want_timeout || timeout--) && !(*pBMICmdCredits) { + /* Read the counter register to get the command credits */ + address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1; + /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing, + * we can read this counter multiple times using a non-incrementing address mode. + * The rationale here is to make all HIF accesses a multiple of 4 bytes */ + status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, sizeof(*pBMICmdCredits), + HIF_RD_SYNC_BYTE_FIX, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n")); + return A_ERROR; + } + /* we did a 4-byte read to the same count register so mask off upper bytes */ + (*pBMICmdCredits) &= 0xFF; + } + + if (!(*pBMICmdCredits)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n")); + return A_ERROR; + } + } +#endif + + address = mboxAddress[ENDPOINT1]; + status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n")); + return A_ERROR; + } + + return A_OK; +} + + +A_STATUS HIFRegBasedGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info) +{ + A_STATUS status; + A_UINT32 cid; + + /* From scope, when first CMD53 send out, the core_clk is not ready. + * So wait 100 ms here to wait target ready to avoid -110 error + * when loading driver + */ + if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == + MANUFACTURER_ID_QCA9377_BASE) { + msleep(100); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device)); + cid = BMI_GET_TARGET_INFO; + + status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid)); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device, try again.\n")); + mdelay(100); + status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid)); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Still unable to write to the device!\n")); + return A_ERROR; + } + } + + status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver, + sizeof(targ_info->target_ver), TRUE); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n")); + return A_ERROR; + } + + if (targ_info->target_ver == TARGET_VERSION_SENTINAL) { + /* Determine how many bytes are in the Target's targ_info */ + status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count, + sizeof(targ_info->target_info_byte_count), TRUE); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n")); + return A_ERROR; + } + + /* + * The Target's targ_info doesn't match the Host's targ_info. + * We need to do some backwards compatibility work to make this OK. + */ + A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info)); + + /* Read the remainder of the targ_info */ + status = bmiBufferReceive(device, + ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count), + sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), TRUE); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n", + targ_info->target_info_byte_count)); + return A_ERROR; + } + } else { + /* + * Target must be an AR6001 whose firmware does not + * support BMI_GET_TARGET_INFO. Construct the data + * that it would have sent. + */ + targ_info->target_info_byte_count=sizeof(*targ_info); + targ_info->target_type=TARGET_TYPE_AR6001; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n", + targ_info->target_ver, targ_info->target_type)); + + return A_OK; +} + +A_STATUS HIFExchangeBMIMsg(HIF_DEVICE *device, + A_UINT8 *pSendMessage, + A_UINT32 Length, + A_UINT8 *pResponseMessage, + A_UINT32 *pResponseLength, + A_UINT32 TimeoutMS) +{ + A_STATUS status = A_OK; + + if (device == NULL ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Null device argument\n")); + return A_EINVAL; + } + + do { + + status = bmiBufferSend(device, pSendMessage, Length); + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI : Unable to Send Message to device \n")); + break; + } + + if (pResponseMessage != NULL) { + status = bmiBufferReceive(device, pResponseMessage, *pResponseLength, TimeoutMS ? TRUE : FALSE); + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI : Unable to read response from device \n")); + break; + } + } + + } while (FALSE); + + return status; +} + +/* TODO .. the following APIs are a relic of the old register based interface */ + +A_STATUS +BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length) +{ + return bmiBufferSend(device, buffer, length); +} + +A_STATUS +BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout) +{ + return bmiBufferReceive(device, buffer, length, want_timeout); +} +#ifdef BRINGUP_DEBUG +#define SDIO_SCRATCH_1_ADDRESS 0x864 +/*Functions used for debugging*/ +A_STATUS bmiWriteScratchRegister (HIF_DEVICE *device, u_int32_t buffer) +{ + A_STATUS status = A_OK; + + + status = HIFReadWrite(device, SDIO_SCRATCH_1_ADDRESS, (A_UINT8 *)&buffer, 4, HIF_WR_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Unable to write to 0x%x\n",__func__, SDIO_SCRATCH_1_ADDRESS)); + return A_ERROR; + } + else + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wrote 0x%x to 0x%x\n", __func__, buffer, SDIO_SCRATCH_1_ADDRESS)); + + return status; +} + + +A_STATUS bmiReadScratchRegister (HIF_DEVICE *device) +{ + A_STATUS status = A_OK; + u_int32_t buffer = 0; + + + status = HIFReadWrite(device, SDIO_SCRATCH_1_ADDRESS, (A_UINT8 *)&buffer, 4, HIF_RD_SYNC_BYTE_INC, NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Unable to read from 0x%x\n", __func__, SDIO_SCRATCH_1_ADDRESS)); + return A_ERROR; + } + else + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: read 0x%x from 0x%x\n", __func__, buffer, SDIO_SCRATCH_1_ADDRESS)); + + return status; +} +#endif + diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_diag_reg_access.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_diag_reg_access.c new file mode 100644 index 000000000000..d3c69a1aba65 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_diag_reg_access.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef WIN_MOBILE7 +#include +#endif + +#include "athdefs.h" +#include "a_types.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME hif +#include "a_debug.h" + +#include "targaddrs.h" +#include "hif.h" +#include "if_ath_sdio.h" +#include "regtable.h" + +#define CPU_DBG_SEL_ADDRESS 0x00000483 +#define CPU_DBG_ADDRESS 0x00000484 + +/* set the window address register (using 4-byte register access ). + * This mitigates host interconnect issues with non-4byte aligned bus requests, some + * interconnects use bus adapters that impose strict limitations. + * Since diag window access is not intended for performance critical operations, the 4byte mode should + * be satisfactory even though it generates 4X the bus activity. */ +static A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address) +{ + A_STATUS status; + static A_UINT32 address; + + address = Address; + +/*AR6320 use new window register access procedure,not need confuse operation as below*/ +#if 0 + for (i = 1; i <= 3; i++) { + /* fill the buffer with the address byte value we want to hit 4 times*/ + addrValue[0] = ((A_UINT8 *)&Address)[i]; + addrValue[1] = addrValue[0]; + addrValue[2] = addrValue[0]; + addrValue[3] = addrValue[0]; + + /* hit each byte of the register address with a 4-byte write operation to the same address, + * this is a harmless operation */ + status = HIFReadWrite(hifDevice, + RegisterAddr+i, + addrValue, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + if (status != A_OK) { + break; + } + } + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", + Address, RegisterAddr)); + return status; + } +#endif +/*AR6320,just write the 4-byte address to window register*/ + status = HIFReadWrite(hifDevice, + RegisterAddr, + (A_UCHAR *)(&address), + 4, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", + Address, RegisterAddr)); + return status; + } + + return A_OK; +} + + +/* + * Read from the AR6000 through its diagnostic window. + * No cooperation from the Target is required for this. + */ +A_STATUS +HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 *data) +{ + A_STATUS status; + static A_UINT32 readvalue; + + if(address&0x03) + { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("[%s]addr is not 4 bytes align.addr[0x%08x]\n",__func__, address)); + return A_BAD_ADDRESS; + } + + /* set window register to start read cycle */ + status = ar6000_SetAddressWindowRegister(hifDevice, + WINDOW_READ_ADDR_ADDRESS, + address); + + if (status != A_OK) { + return status; + } + + /* read the data */ + status = HIFReadWrite(hifDevice, + WINDOW_DATA_ADDRESS, + (A_UCHAR *)&readvalue, + sizeof(A_UINT32), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n")); + return status; + } + + *data = readvalue; + return status; +} + + +/* + * Write to the AR6000 through its diagnostic window. + * No cooperation from the Target is required for this. + */ +A_STATUS HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 data) +{ + A_STATUS status; + static A_UINT32 writeValue; + + if(address&0x03) + { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("[%s]addr is not 4 bytes align.addr[0x%08x]\n",__func__, address)); + return A_BAD_ADDRESS; + } + + writeValue = data; + + /* set write data */ + status = HIFReadWrite(hifDevice, + WINDOW_DATA_ADDRESS, + (A_UCHAR *)&writeValue, + sizeof(A_UINT32), + HIF_WR_SYNC_BYTE_INC, + NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", data)); + return status; + } + + /* set window register, which starts the write cycle */ + return ar6000_SetAddressWindowRegister(hifDevice, + WINDOW_WRITE_ADDR_ADDRESS, + address); +} + +/* + * Write a block data to the AR6000 through its diagnostic window. + * This function may take some time. + * No cooperation from the Target is required for this. + */ +A_STATUS +HIFDiagWriteMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes) +{ + A_STATUS status; + A_INT32 i; + A_UINT32 tmp_data; + + if((address&0x03) || (nbytes&0x03)) + { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("[%s]addr or length is not 4 bytes align.addr[0x%08x] len[0x%08x]\n",__func__, address, nbytes)); + return A_BAD_ADDRESS; + } + + for(i=0;i>8 & 0xff; + data[i+2] = tmp_data>>16 & 0xff; + data[i+3] = tmp_data>>24 & 0xff; + } + + return A_OK; +} + +/* TODO .. the following APIs are only available on register-based HIFs where the CPU_DBG_SEL_ADDRESS + * register is available */ + +A_STATUS +ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval) +{ + A_STATUS status; + A_UCHAR vals[4]; + A_UCHAR register_selection[4]; + + register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff); + status = HIFReadWrite(hifDevice, + CPU_DBG_SEL_ADDRESS, + register_selection, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel)); + return status; + } + + status = HIFReadWrite(hifDevice, + CPU_DBG_ADDRESS, + (A_UCHAR *)vals, + sizeof(vals), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n")); + return status; + } + + *regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24; + + return status; +} + +void +ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs) +{ + int i; + A_UINT32 val; + + for (i=0; i +#endif +#include "hif_trace.h" + +#ifndef HIF_SDIO_COMMON_H_ +#define HIF_SDIO_COMMON_H_ + +#ifndef INLINE +#ifdef __GNUC__ +#define INLINE __inline__ +#else +#define INLINE __inline +#endif +#endif + /* SDIO manufacturer ID and Codes */ +#define MANUFACTURER_ID_AR6002_BASE 0x200 +#define MANUFACTURER_ID_AR6003_BASE 0x300 +#define MANUFACTURER_ID_AR6004_BASE 0x400 +#define MANUFACTURER_ID_AR6320_BASE 0x500 /* AR6320_TBDXXX */ +#define MANUFACTURER_ID_QCA9377_BASE 0x700 /* QCA9377 */ +#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00 +#define MANUFACTURER_ID_AR6K_REV_MASK 0x00FF +#define FUNCTION_CLASS 0x0 +#define MANUFACTURER_CODE 0x271 /* Atheros */ + + /* Mailbox address in SDIO address space */ +#if defined(SDIO_3_0) +#define HIF_MBOX_BASE_ADDR 0x1000 +#define HIF_MBOX_DUMMY_WIDTH 0x800 +#else +#define HIF_MBOX_BASE_ADDR 0x800 +#define HIF_MBOX_DUMMY_WIDTH 0 +#endif + +#define HIF_MBOX_WIDTH 0x800 + +#define HIF_MBOX_START_ADDR(mbox) \ + ( HIF_MBOX_BASE_ADDR + mbox * (HIF_MBOX_WIDTH + HIF_MBOX_DUMMY_WIDTH) ) + +#define HIF_MBOX_END_ADDR(mbox) \ + (HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1) + + /* extended MBOX address for larger MBOX writes to MBOX 0*/ +#if defined(SDIO_3_0) +#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x5000 +#else +#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800 +#endif +#define HIF_MBOX0_EXTENDED_WIDTH_AR6002 (6*1024) +#define HIF_MBOX0_EXTENDED_WIDTH_AR6003 (18*1024) + + /* version 1 of the chip has only a 12K extended mbox range */ +#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1 0x4000 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1 (12*1024) + +#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004 0x2800 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6004 (18*1024) + + +#if defined(SDIO_3_0) +#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320 0x5000 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6320 (36*1024) +#define HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0 (56*1024) +#define HIF_MBOX1_EXTENDED_WIDTH_AR6320 (36*1024) +#define HIF_MBOX_DUMMY_SPACE_SIZE_AR6320 (2*1024) +#else +#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320 0x2800 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6320 (24*1024) +#define HIF_MBOX1_EXTENDED_WIDTH_AR6320 (24*1024) +#define HIF_MBOX_DUMMY_SPACE_SIZE_AR6320 0 +#endif + + + /* GMBOX addresses */ +#define HIF_GMBOX_BASE_ADDR 0x7000 +#define HIF_GMBOX_WIDTH 0x4000 + +/* for SDIO we recommend a 128-byte block size */ +#if defined(WITH_BACKPORTS) +#define HIF_DEFAULT_IO_BLOCK_SIZE 128 +#else +#define HIF_DEFAULT_IO_BLOCK_SIZE 256 +#endif + + /* set extended MBOX window information for SDIO interconnects */ +static INLINE void SetExtendedMboxWindowInfo(A_UINT16 Manfid, HIF_DEVICE_MBOX_INFO *pInfo) +{ + switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) { + case MANUFACTURER_ID_AR6002_BASE : + /* MBOX 0 has an extended range */ + + /**** FIXME .. AR6004 currently masquerades as an AR6002 device + * and thus it's actual extended window size will be incorrectly + * set. Temporarily force the location and size to match AR6004 ****/ + //pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR; + //pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002; + + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1; + + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1; + + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6004; + + break; + case MANUFACTURER_ID_AR6003_BASE : + /* MBOX 0 has an extended range */ + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1; + pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR; + pInfo->GMboxSize = HIF_GMBOX_WIDTH; + break; + case MANUFACTURER_ID_AR6004_BASE : + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6004; + pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR; + pInfo->GMboxSize = HIF_GMBOX_WIDTH; + break; + case MANUFACTURER_ID_AR6320_BASE :{ + A_UINT16 ManuRevID = Manfid & MANUFACTURER_ID_AR6K_REV_MASK; + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320; + if (ManuRevID < 4){ + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320; + } else { + /* from rome 2.0(0x504), the width has been extended to 56K */ +#if defined(SDIO_3_0) + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0; +#else + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320; +#endif + } +#if defined(SDIO_3_0) + pInfo->MboxProp[1].ExtendedAddress = pInfo->MboxProp[0].ExtendedAddress + + pInfo->MboxProp[0].ExtendedSize + HIF_MBOX_DUMMY_SPACE_SIZE_AR6320; + pInfo->MboxProp[1].ExtendedSize = HIF_MBOX1_EXTENDED_WIDTH_AR6320; +#endif + pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR; + pInfo->GMboxSize = HIF_GMBOX_WIDTH; + break; + } + case MANUFACTURER_ID_QCA9377_BASE : + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0; + pInfo->MboxProp[1].ExtendedAddress = pInfo->MboxProp[0].ExtendedAddress + + pInfo->MboxProp[0].ExtendedSize + HIF_MBOX_DUMMY_SPACE_SIZE_AR6320; + pInfo->MboxProp[1].ExtendedSize = HIF_MBOX1_EXTENDED_WIDTH_AR6320; + pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR; + pInfo->GMboxSize = HIF_GMBOX_WIDTH; + break; + default: + A_ASSERT(FALSE); + break; + } +} + +#define FIFO_TIMEOUT_AND_CHIP_CONTROL 0x00000868 +#define FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF +#define FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000 +/* + In SDIO 2.0, asynchronous interrupt is not in SPEC requirement, but AR6003 support it, so the register + is placed in vendor specific field 0xF0(bit0) + In SDIO 3.0, the register is defined in SPEC, and its address is 0x16(bit1) +*/ + +#define CCCR_SDIO_IRQ_MODE_REG_AR6003 0xF0 /* interrupt mode register of AR6003*/ +#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003 (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/ + +#define CCCR_SDIO_IRQ_MODE_REG_AR6320 0x16 /* interrupt mode register of AR6320*/ +#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320 (1 << 1) /* mode to enable special 4-bit interrupt assertion without clock*/ + + +#define CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS 0xF0 +#define CCCR_SDIO_ASYNC_INT_DELAY_LSB 0x06 +#define CCCR_SDIO_ASYNC_INT_DELAY_MASK 0xC0 + +/* Vendor Specific Driver Strength Settings */ +#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR 0xf2 +#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK 0x0e +#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A 0x02 +#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C 0x04 +#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D 0x08 + +#endif /*HIF_SDIO_COMMON_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_trace.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_trace.h new file mode 100644 index 000000000000..59af5a840780 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/common/hif_trace.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//============================================================================== +// HIF specific declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HIF_TRACE_H_ +#define _HIF_TRACE_H_ + +#include "vos_trace.h" +#ifdef ENTER +#undef ENTER +#endif +#define ENTER(fmt,...) VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO, "Enter: %s "fmt, __FUNCTION__,## __VA_ARGS__) + +#ifdef EXIT +#undef EXIT +#endif +#define EXIT(fmt,...) VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO, "Exit: %s "fmt, __FUNCTION__,## __VA_ARGS__) + +#endif //_HIF_TRACE_H_ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320def.h new file mode 100644 index 000000000000..95f5dcd6ffe6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320def.h @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320DEF_H_ +#define _AR6320DEF_H_ + +/* Base Addresses */ +#define AR6320_RTC_SOC_BASE_ADDRESS 0x00000000 +#define AR6320_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320_CE0_BASE_ADDRESS 0x00034400 +#define AR6320_CE1_BASE_ADDRESS 0x00034800 +#define AR6320_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320_CE3_BASE_ADDRESS 0x00035000 +#define AR6320_CE4_BASE_ADDRESS 0x00035400 +#define AR6320_CE5_BASE_ADDRESS 0x00035800 +#define AR6320_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320_CE7_BASE_ADDRESS 0x00036000 +#define AR6320_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320_SCRATCH_3_ADDRESS 0x0028 +#define AR6320_TARG_DRAM_START 0x00400000 +#define AR6320_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320_SI_CONFIG_I2C_LSB 16 +#define AR6320_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320_SI_CONFIG_OFFSET 0x00000000 +#define AR6320_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320_SI_CS_OFFSET 0x00000004 +#define AR6320_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320_SI_CS_START_LSB 8 +#define AR6320_SI_CS_START_MASK 0x00000100 +#define AR6320_SI_CS_RX_CNT_LSB 4 +#define AR6320_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320_SI_CS_TX_CNT_LSB 0 +#define AR6320_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320_CE_COUNT 8 +#define AR6320_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320_RX_MPDU_START_0_RETRY_LSB 14 +#define AR6320_RX_MPDU_START_0_RETRY_MASK 0x00004000 +#define AR6320_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320_RX_MPDU_START_2_TID_LSB 28 +#define AR6320_RX_MPDU_START_2_TID_MASK 0xf0000000 +#define AR6320_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320_RX_MSDU_END_1_KEY_ID_OCT_MASK 0x000000ff +#define AR6320_RX_MSDU_END_1_KEY_ID_OCT_LSB 0 +#define AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320_HOST_IS_ADDRESS 0x0030 +#define AR6320_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320_HOST_IE_ADDRESS 0x002c +#define AR6320_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320_SR_BA_ADDRESS 0x0000 +#define AR6320_SR_SIZE_ADDRESS 0x0004 +#define AR6320_CE_CTRL1_ADDRESS 0x0010 +#define AR6320_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320_DR_BA_ADDRESS 0x0008 +#define AR6320_DR_SIZE_ADDRESS 0x000c +#define AR6320_MISC_IE_ADDRESS 0x0034 +#define AR6320_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320_SRC_WATERMARK_LOW_LSB 16 +#define AR6320_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320_DST_WATERMARK_LOW_LSB 16 +#define AR6320_DST_WATERMARK_HIGH_LSB 0 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320_RTC_STATE_ADDRESS 0x0000 +#define AR6320_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320_RTC_STATE_V_MASK 0x00000007 +#define AR6320_RTC_STATE_V_LSB 0 +#define AR6320_RTC_STATE_V_ON 3 +#define AR6320_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320_FW_IND_EVENT_PENDING 1 +#define AR6320_FW_IND_INITIALIZED 2 +#define AR6320_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320_CPU_INTR_ADDRESS 0x0010 +#define AR6320_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320_CORE_CTRL_ADDRESS 0x0000 +#define AR6320_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320_SOC_CHIP_ID_REVISION_LSB 8 + +/* PLL start */ +#define AR6320_EFUSE_OFFSET 0x0000032c +#define AR6320_EFUSE_XTAL_SEL_MSB 10 +#define AR6320_EFUSE_XTAL_SEL_LSB 8 +#define AR6320_EFUSE_XTAL_SEL_MASK 0x00000700 +#define AR6320_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define AR6320_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define AR6320_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define AR6320_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define AR6320_BB_PLL_CONFIG_FRAC_MSB 17 +#define AR6320_BB_PLL_CONFIG_FRAC_LSB 0 +#define AR6320_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define AR6320_WLAN_PLL_SETTLE_TIME_MSB 10 +#define AR6320_WLAN_PLL_SETTLE_TIME_LSB 0 +#define AR6320_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define AR6320_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define AR6320_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define AR6320_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define AR6320_WLAN_PLL_SETTLE_RESET 0x00000400 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define AR6320_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define AR6320_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define AR6320_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define AR6320_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define AR6320_WLAN_PLL_CONTROL_DIV_MSB 9 +#define AR6320_WLAN_PLL_CONTROL_DIV_LSB 0 +#define AR6320_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define AR6320_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define AR6320_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define AR6320_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define AR6320_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define AR6320_WLAN_PLL_CONTROL_RESET 0x00010011 +#define AR6320_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define AR6320_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define AR6320_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define AR6320_RTC_SYNC_STATUS_OFFSET 0x0244 +#define AR6320_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define AR6320_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define AR6320_PCIE_INTR_CE_MASK(n) (AR6320_PCIE_INTR_CE0_MASK << (n)) +#define AR6320_DRAM_BASE_ADDRESS AR6320_TARG_DRAM_START +#define AR6320_FW_INDICATOR_ADDRESS (AR6320_SOC_CORE_BASE_ADDRESS + AR6320_SCRATCH_3_ADDRESS) +#define AR6320_SYSTEM_SLEEP_OFFSET AR6320_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320_WLAN_RESET_CONTROL_OFFSET AR6320_SOC_RESET_CONTROL_OFFSET +#define AR6320_CLOCK_CONTROL_OFFSET AR6320_SOC_CLOCK_CONTROL_OFFSET +#define AR6320_CLOCK_CONTROL_SI0_CLK_MASK AR6320_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320_RESET_CONTROL_SI0_RST_MASK AR6320_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320_GPIO_BASE_ADDRESS AR6320_WLAN_GPIO_BASE_ADDRESS +#define AR6320_GPIO_PIN0_OFFSET AR6320_WLAN_GPIO_PIN0_ADDRESS +#define AR6320_GPIO_PIN1_OFFSET AR6320_WLAN_GPIO_PIN1_ADDRESS +#define AR6320_GPIO_PIN0_CONFIG_MASK AR6320_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320_GPIO_PIN1_CONFIG_MASK AR6320_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320_SI_BASE_ADDRESS 0x00050000 +#define AR6320_CPU_CLOCK_OFFSET AR6320_SOC_CPU_CLOCK_OFFSET +#define AR6320_LPO_CAL_OFFSET AR6320_SOC_LPO_CAL_OFFSET +#define AR6320_GPIO_PIN10_OFFSET AR6320_WLAN_GPIO_PIN10_ADDRESS +#define AR6320_GPIO_PIN11_OFFSET AR6320_WLAN_GPIO_PIN11_ADDRESS +#define AR6320_GPIO_PIN12_OFFSET AR6320_WLAN_GPIO_PIN12_ADDRESS +#define AR6320_GPIO_PIN13_OFFSET AR6320_WLAN_GPIO_PIN13_ADDRESS +#define AR6320_CPU_CLOCK_STANDARD_LSB AR6320_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320_CPU_CLOCK_STANDARD_MASK AR6320_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320_LPO_CAL_ENABLE_LSB AR6320_SOC_LPO_CAL_ENABLE_LSB +#define AR6320_LPO_CAL_ENABLE_MASK AR6320_SOC_LPO_CAL_ENABLE_MASK +#define AR6320_ANALOG_INTF_BASE_ADDRESS AR6320_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320_COUNT_DEC_ADDRESS 0x0840 +#define AR6320_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320_WINDOW_WRITE_ADDR_ADDRESS 0x0878 +#define AR6320_HOST_INT_STATUS_MBOX_DATA_MASK 0x0f +#define AR6320_HOST_INT_STATUS_MBOX_DATA_LSB 0 + +struct targetdef_s ar6320_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR6320_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_RETRY_LSB = AR6320_RX_MPDU_START_0_RETRY_LSB, + .d_RX_MPDU_START_0_RETRY_MASK = AR6320_RX_MPDU_START_0_RETRY_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MPDU_START_2_TID_LSB = AR6320_RX_MPDU_START_2_TID_LSB, + .d_RX_MPDU_START_2_TID_MASK = AR6320_RX_MPDU_START_2_TID_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_MASK = AR6320_RX_MSDU_END_1_KEY_ID_OCT_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_LSB = AR6320_RX_MSDU_END_1_KEY_ID_OCT_LSB, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + /* PLL start */ + .d_EFUSE_OFFSET = AR6320_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = AR6320_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = AR6320_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = AR6320_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = AR6320_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = AR6320_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = AR6320_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = AR6320_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = AR6320_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = AR6320_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = AR6320_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = AR6320_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = AR6320_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = AR6320_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = AR6320_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = AR6320_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = AR6320_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = AR6320_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = AR6320_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = AR6320_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = AR6320_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = AR6320_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = AR6320_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = AR6320_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = AR6320_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = AR6320_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = AR6320_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = AR6320_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = AR6320_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = AR6320_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = AR6320_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = AR6320_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = AR6320_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = AR6320_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = AR6320_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = AR6320_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = AR6320_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = AR6320_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = AR6320_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = AR6320_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = AR6320_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = AR6320_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = AR6320_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = AR6320_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = AR6320_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = AR6320_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = AR6320_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = AR6320_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = AR6320_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = AR6320_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = AR6320_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR6320_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif +#ifdef HIF_PCI + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +#endif +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320v2def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320v2def.h new file mode 100644 index 000000000000..4a8c8bdf137c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar6320v2def.h @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR6320V2DEF_H_ +#define _AR6320V2DEF_H_ + +/* Base Addresses */ +#define AR6320V2_RTC_SOC_BASE_ADDRESS 0x00000800 +#define AR6320V2_RTC_WMAC_BASE_ADDRESS 0x00001000 +#define AR6320V2_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define AR6320V2_BT_COEX_BASE_ADDRESS 0x00002000 +#define AR6320V2_SOC_PCIE_BASE_ADDRESS 0x00038000 +#define AR6320V2_SOC_CORE_BASE_ADDRESS 0x0003a000 +#define AR6320V2_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR6320V2_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR6320V2_WLAN_GPIO_BASE_ADDRESS 0x00005000 +#define AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00006000 +#define AR6320V2_WLAN_MAC_BASE_ADDRESS 0x00010000 +#define AR6320V2_EFUSE_BASE_ADDRESS 0x00024000 +#define AR6320V2_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR6320V2_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR6320V2_CE_WRAPPER_BASE_ADDRESS 0x00034000 +#define AR6320V2_CE0_BASE_ADDRESS 0x00034400 +#define AR6320V2_CE1_BASE_ADDRESS 0x00034800 +#define AR6320V2_CE2_BASE_ADDRESS 0x00034c00 +#define AR6320V2_CE3_BASE_ADDRESS 0x00035000 +#define AR6320V2_CE4_BASE_ADDRESS 0x00035400 +#define AR6320V2_CE5_BASE_ADDRESS 0x00035800 +#define AR6320V2_CE6_BASE_ADDRESS 0x00035c00 +#define AR6320V2_CE7_BASE_ADDRESS 0x00036000 +#define AR6320V2_DBI_BASE_ADDRESS 0x0003c000 +#define AR6320V2_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 + +#define AR6320V2_SCRATCH_3_ADDRESS 0x0028 +#define AR6320V2_TARG_DRAM_START 0x00400000 +#define AR6320V2_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define AR6320V2_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR6320V2_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000000 +#define AR6320V2_WLAN_GPIO_PIN0_ADDRESS 0x00000068 +#define AR6320V2_WLAN_GPIO_PIN1_ADDRESS 0x0000006c +#define AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR6320V2_WLAN_GPIO_PIN10_ADDRESS 0x00000090 +#define AR6320V2_WLAN_GPIO_PIN11_ADDRESS 0x00000094 +#define AR6320V2_WLAN_GPIO_PIN12_ADDRESS 0x00000098 +#define AR6320V2_WLAN_GPIO_PIN13_ADDRESS 0x0000009c +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR6320V2_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR6320V2_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR6320V2_SI_CONFIG_I2C_LSB 16 +#define AR6320V2_SI_CONFIG_I2C_MASK 0x00010000 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR6320V2_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR6320V2_SI_CONFIG_DIVIDER_LSB 0 +#define AR6320V2_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR6320V2_SI_CONFIG_OFFSET 0x00000000 +#define AR6320V2_SI_TX_DATA0_OFFSET 0x00000008 +#define AR6320V2_SI_TX_DATA1_OFFSET 0x0000000c +#define AR6320V2_SI_RX_DATA0_OFFSET 0x00000010 +#define AR6320V2_SI_RX_DATA1_OFFSET 0x00000014 +#define AR6320V2_SI_CS_OFFSET 0x00000004 +#define AR6320V2_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR6320V2_SI_CS_DONE_INT_MASK 0x00000200 +#define AR6320V2_SI_CS_START_LSB 8 +#define AR6320V2_SI_CS_START_MASK 0x00000100 +#define AR6320V2_SI_CS_RX_CNT_LSB 4 +#define AR6320V2_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR6320V2_SI_CS_TX_CNT_LSB 0 +#define AR6320V2_SI_CS_TX_CNT_MASK 0x0000000f +#define AR6320V2_CE_COUNT 8 +#define AR6320V2_SR_WR_INDEX_ADDRESS 0x003c +#define AR6320V2_DST_WATERMARK_ADDRESS 0x0050 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_RETRY_LSB 14 +#define AR6320V2_RX_MPDU_START_0_RETRY_MASK 0x00004000 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR6320V2_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR6320V2_RX_MPDU_START_2_TID_LSB 28 +#define AR6320V2_RX_MPDU_START_2_TID_MASK 0xf0000000 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff + +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR6320V2_DST_WR_INDEX_ADDRESS 0x0040 +#define AR6320V2_SRC_WATERMARK_ADDRESS 0x004c +#define AR6320V2_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR6320V2_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR6320V2_CURRENT_SRRI_ADDRESS 0x0044 +#define AR6320V2_CURRENT_DRRI_ADDRESS 0x0048 +#define AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR6320V2_HOST_IS_ADDRESS 0x0030 +#define AR6320V2_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR6320V2_HOST_IE_ADDRESS 0x002c +#define AR6320V2_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR6320V2_SR_BA_ADDRESS 0x0000 +#define AR6320V2_SR_SIZE_ADDRESS 0x0004 +#define AR6320V2_CE_CTRL1_ADDRESS 0x0010 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR6320V2_DR_BA_ADDRESS 0x0008 +#define AR6320V2_DR_SIZE_ADDRESS 0x000c +#define AR6320V2_MISC_IE_ADDRESS 0x0034 +#define AR6320V2_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR6320V2_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR6320V2_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR6320V2_SRC_WATERMARK_LOW_LSB 16 +#define AR6320V2_SRC_WATERMARK_HIGH_LSB 0 +#define AR6320V2_DST_WATERMARK_LOW_LSB 16 +#define AR6320V2_DST_WATERMARK_HIGH_LSB 0 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000020 +#define AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 5 +#define AR6320V2_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR6320V2_RTC_STATE_ADDRESS 0x0000 +#define AR6320V2_RTC_STATE_COLD_RESET_MASK 0x00002000 +#define AR6320V2_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR6320V2_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR6320V2_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR6320V2_RTC_STATE_V_MASK 0x00000007 +#define AR6320V2_RTC_STATE_V_LSB 0 +#define AR6320V2_RTC_STATE_V_ON 3 +#define AR6320V2_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR6320V2_FW_IND_EVENT_PENDING 1 +#define AR6320V2_FW_IND_INITIALIZED 2 +#define AR6320V2_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR6320V2_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR6320V2_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR6320V2_PCIE_INTR_CE0_MASK 0x00000800 +#define AR6320V2_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR6320V2_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR6320V2_CPU_INTR_ADDRESS 0x0010 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR6320V2_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK 0x00000001 +#define AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR6320V2_CORE_CTRL_ADDRESS 0x0000 +#define AR6320V2_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR6320V2_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define AR6320V2_CLOCK_GPIO_OFFSET 0xffffffff +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define AR6320V2_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define AR6320V2_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define AR6320V2_SOC_CHIP_ID_VERSION_LSB 18 +#define AR6320V2_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define AR6320V2_SOC_CHIP_ID_REVISION_LSB 8 + +/* PLL start */ +#define AR6320V2_EFUSE_OFFSET 0x0000032c +#define AR6320V2_EFUSE_XTAL_SEL_MSB 10 +#define AR6320V2_EFUSE_XTAL_SEL_LSB 8 +#define AR6320V2_EFUSE_XTAL_SEL_MASK 0x00000700 +#define AR6320V2_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define AR6320V2_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define AR6320V2_BB_PLL_CONFIG_FRAC_MSB 17 +#define AR6320V2_BB_PLL_CONFIG_FRAC_LSB 0 +#define AR6320V2_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define AR6320V2_WLAN_PLL_SETTLE_TIME_MSB 10 +#define AR6320V2_WLAN_PLL_SETTLE_TIME_LSB 0 +#define AR6320V2_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define AR6320V2_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define AR6320V2_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define AR6320V2_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define AR6320V2_WLAN_PLL_SETTLE_RESET 0x00000400 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define AR6320V2_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define AR6320V2_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define AR6320V2_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_MSB 9 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_LSB 0 +#define AR6320V2_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define AR6320V2_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define AR6320V2_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define AR6320V2_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define AR6320V2_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define AR6320V2_WLAN_PLL_CONTROL_RESET 0x00010011 +#define AR6320V2_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define AR6320V2_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define AR6320V2_RTC_SYNC_STATUS_OFFSET 0x0244 +#define AR6320V2_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define AR6320V2_PCIE_INTR_CE_MASK(n) (AR6320V2_PCIE_INTR_CE0_MASK << (n)) +#define AR6320V2_DRAM_BASE_ADDRESS AR6320V2_TARG_DRAM_START +#define AR6320V2_FW_INDICATOR_ADDRESS (AR6320V2_SOC_CORE_BASE_ADDRESS + AR6320V2_SCRATCH_3_ADDRESS) +#define AR6320V2_SYSTEM_SLEEP_OFFSET AR6320V2_SOC_SYSTEM_SLEEP_OFFSET +#define AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET 0x002c +#define AR6320V2_WLAN_RESET_CONTROL_OFFSET AR6320V2_SOC_RESET_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_OFFSET AR6320V2_SOC_CLOCK_CONTROL_OFFSET +#define AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK AR6320V2_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR6320V2_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define AR6320V2_RESET_CONTROL_SI0_RST_MASK AR6320V2_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR6320V2_GPIO_BASE_ADDRESS AR6320V2_WLAN_GPIO_BASE_ADDRESS +#define AR6320V2_GPIO_PIN0_OFFSET AR6320V2_WLAN_GPIO_PIN0_ADDRESS +#define AR6320V2_GPIO_PIN1_OFFSET AR6320V2_WLAN_GPIO_PIN1_ADDRESS +#define AR6320V2_GPIO_PIN0_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR6320V2_GPIO_PIN1_CONFIG_MASK AR6320V2_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR6320V2_SI_BASE_ADDRESS 0x00050000 +#define AR6320V2_CPU_CLOCK_OFFSET AR6320V2_SOC_CPU_CLOCK_OFFSET +#define AR6320V2_LPO_CAL_OFFSET AR6320V2_SOC_LPO_CAL_OFFSET +#define AR6320V2_GPIO_PIN10_OFFSET AR6320V2_WLAN_GPIO_PIN10_ADDRESS +#define AR6320V2_GPIO_PIN11_OFFSET AR6320V2_WLAN_GPIO_PIN11_ADDRESS +#define AR6320V2_GPIO_PIN12_OFFSET AR6320V2_WLAN_GPIO_PIN12_ADDRESS +#define AR6320V2_GPIO_PIN13_OFFSET AR6320V2_WLAN_GPIO_PIN13_ADDRESS +#define AR6320V2_CPU_CLOCK_STANDARD_LSB AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB +#define AR6320V2_CPU_CLOCK_STANDARD_MASK AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK +#define AR6320V2_LPO_CAL_ENABLE_LSB AR6320V2_SOC_LPO_CAL_ENABLE_LSB +#define AR6320V2_LPO_CAL_ENABLE_MASK AR6320V2_SOC_LPO_CAL_ENABLE_MASK +#define AR6320V2_ANALOG_INTF_BASE_ADDRESS AR6320V2_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR6320V2_MBOX_BASE_ADDRESS 0x00008000 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_LSB 7 +#define AR6320V2_INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define AR6320V2_INT_STATUS_ENABLE_CPU_LSB 6 +#define AR6320V2_INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB 4 +#define AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 16 +#define AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB 24 +#define AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0xff000000 +#define AR6320V2_INT_STATUS_ENABLE_ADDRESS 0x0828 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB 8 +#define AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK 0x0000ff00 +#define AR6320V2_HOST_INT_STATUS_ADDRESS 0x0800 +#define AR6320V2_CPU_INT_STATUS_ADDRESS 0x0801 +#define AR6320V2_ERROR_INT_STATUS_ADDRESS 0x0802 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK 0x00040000 +#define AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB 18 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00020000 +#define AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 17 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00010000 +#define AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB 16 +#define AR6320V2_COUNT_DEC_ADDRESS 0x0840 +#define AR6320V2_HOST_INT_STATUS_CPU_MASK 0x00000040 +#define AR6320V2_HOST_INT_STATUS_CPU_LSB 6 +#define AR6320V2_HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define AR6320V2_HOST_INT_STATUS_ERROR_LSB 7 +#define AR6320V2_HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define AR6320V2_HOST_INT_STATUS_COUNTER_LSB 4 +#define AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS 0x0805 +#define AR6320V2_WINDOW_DATA_ADDRESS 0x0874 +#define AR6320V2_WINDOW_READ_ADDR_ADDRESS 0x087c +#define AR6320V2_WINDOW_WRITE_ADDR_ADDRESS 0x0878 +#define AR6320V2_HOST_INT_STATUS_MBOX_DATA_MASK 0x0f +#define AR6320V2_HOST_INT_STATUS_MBOX_DATA_LSB 0 + +struct targetdef_s ar6320v2_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR6320V2_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR6320V2_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR6320V2_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR6320V2_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR6320V2_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR6320V2_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR6320V2_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR6320V2_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR6320V2_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR6320V2_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR6320V2_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR6320V2_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR6320V2_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR6320V2_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR6320V2_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR6320V2_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR6320V2_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR6320V2_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR6320V2_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR6320V2_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR6320V2_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR6320V2_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR6320V2_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR6320V2_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR6320V2_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR6320V2_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR6320V2_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR6320V2_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR6320V2_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR6320V2_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR6320V2_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR6320V2_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR6320V2_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR6320V2_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR6320V2_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR6320V2_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR6320V2_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR6320V2_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR6320V2_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR6320V2_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR6320V2_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR6320V2_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR6320_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR6320_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR6320V2_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR6320V2_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR6320V2_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR6320V2_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR6320V2_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR6320V2_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR6320V2_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR6320V2_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR6320V2_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR6320V2_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR6320V2_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR6320V2_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR6320V2_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR6320V2_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR6320V2_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR6320V2_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR6320V2_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320V2_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR6320V2_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR6320V2_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR6320V2_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR6320V2_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR6320V2_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR6320V2_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR6320V2_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR6320V2_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR6320V2_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR6320V2_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR6320V2_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR6320V2_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_RETRY_LSB = AR6320V2_RX_MPDU_START_0_RETRY_LSB, + .d_RX_MPDU_START_0_RETRY_MASK = AR6320V2_RX_MPDU_START_0_RETRY_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR6320V2_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR6320V2_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR6320V2_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR6320V2_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MPDU_START_2_TID_LSB = AR6320V2_RX_MPDU_START_2_TID_LSB, + .d_RX_MPDU_START_2_TID_MASK = AR6320V2_RX_MPDU_START_2_TID_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR6320V2_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR6320V2_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR6320V2_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR6320V2_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR6320V2_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR6320V2_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR6320V2_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR6320V2_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR6320V2_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR6320V2_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR6320V2_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR6320V2_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR6320V2_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR6320V2_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR6320V2_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR6320V2_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR6320V2_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR6320V2_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR6320V2_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR6320V2_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR6320V2_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR6320V2_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR6320V2_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR6320V2_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR6320V2_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR6320V2_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR6320V2_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR6320V2_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR6320V2_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR6320V2_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR6320V2_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR6320V2_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR6320V2_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR6320V2_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR6320V2_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR6320V2_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR6320V2_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR6320V2_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR6320V2_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR6320V2_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR6320V2_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR6320V2_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR6320V2_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR6320V2_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR6320V2_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR6320V2_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + /* PLL start */ + .d_EFUSE_OFFSET = AR6320V2_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = AR6320V2_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = AR6320V2_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = AR6320V2_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = AR6320V2_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = AR6320V2_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = AR6320V2_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = AR6320V2_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = AR6320V2_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = AR6320V2_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = AR6320V2_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = AR6320V2_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = AR6320V2_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = AR6320V2_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = AR6320V2_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = AR6320V2_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = AR6320V2_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = AR6320V2_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = AR6320V2_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = AR6320V2_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = AR6320V2_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = AR6320V2_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = AR6320V2_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = AR6320V2_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = AR6320V2_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = AR6320V2_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = AR6320V2_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = AR6320V2_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = AR6320V2_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = AR6320V2_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = AR6320V2_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = AR6320V2_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = AR6320V2_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = AR6320V2_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = AR6320V2_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = AR6320V2_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = AR6320V2_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = AR6320V2_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = AR6320V2_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = AR6320V2_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = AR6320V2_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = AR6320V2_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = AR6320V2_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = AR6320V2_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = AR6320V2_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = AR6320V2_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = AR6320V2_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = AR6320V2_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_PCIE_INTR_CAUSE_ADDRESS = AR6320V2_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR6320V2_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR6320V2_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR6320V2_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR6320V2_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR6320V2_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR6320V2_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = AR6320V2_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = AR6320V2_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = AR6320V2_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = AR6320V2_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = AR6320V2_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ +}; + +struct hostdef_s ar6320v2_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR6320V2_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR6320V2_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR6320V2_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR6320V2_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR6320V2_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR6320V2_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR6320V2_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR6320V2_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR6320V2_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR6320V2_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR6320V2_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR6320V2_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR6320V2_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR6320V2_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR6320V2_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR6320V2_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR6320V2_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR6320V2_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR6320V2_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR6320V2_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR6320V2_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR6320V2_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR6320V2_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR6320V2_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR6320V2_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR6320V2_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR6320V2_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR6320V2_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR6320V2_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR6320V2_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR6320V2_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR6320V2_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR6320V2_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR6320V2_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR6320V2_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR6320V2_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR6320V2_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR6320V2_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR6320V2_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR6320V2_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320V2_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif +#ifdef HIF_PCI + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +#endif +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar9888def.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar9888def.h new file mode 100644 index 000000000000..7c0095bddbc8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/ar9888def.h @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _AR9888DEF_H_ +#define AR9888__AR9888DEF_H_ + +/* Base Addresses */ +#define AR9888_RTC_SOC_BASE_ADDRESS 0x00004000 +#define AR9888_RTC_WMAC_BASE_ADDRESS 0x00005000 +#define AR9888_MAC_COEX_BASE_ADDRESS 0x00006000 +#define AR9888_BT_COEX_BASE_ADDRESS 0x00007000 +#define AR9888_SOC_PCIE_BASE_ADDRESS 0x00008000 +#define AR9888_SOC_CORE_BASE_ADDRESS 0x00009000 +#define AR9888_WLAN_UART_BASE_ADDRESS 0x0000c000 +#define AR9888_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR9888_WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 +#define AR9888_WLAN_MAC_BASE_ADDRESS 0x00020000 +#define AR9888_EFUSE_BASE_ADDRESS 0x00030000 +#define AR9888_FPGA_REG_BASE_ADDRESS 0x00039000 +#define AR9888_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define AR9888_CE_WRAPPER_BASE_ADDRESS 0x00057000 +#define AR9888_CE0_BASE_ADDRESS 0x00057400 +#define AR9888_CE1_BASE_ADDRESS 0x00057800 +#define AR9888_CE2_BASE_ADDRESS 0x00057c00 +#define AR9888_CE3_BASE_ADDRESS 0x00058000 +#define AR9888_CE4_BASE_ADDRESS 0x00058400 +#define AR9888_CE5_BASE_ADDRESS 0x00058800 +#define AR9888_CE6_BASE_ADDRESS 0x00058c00 +#define AR9888_CE7_BASE_ADDRESS 0x00059000 +#define AR9888_DBI_BASE_ADDRESS 0x00060000 +#define AR9888_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 + +#define AR9888_SCRATCH_3_ADDRESS 0x0030 +#define AR9888_TARG_DRAM_START 0x00400000 +#define AR9888_SOC_SYSTEM_SLEEP_OFFSET 0x000000c4 +#define AR9888_SOC_RESET_CONTROL_OFFSET 0x00000000 +#define AR9888_SOC_CLOCK_CONTROL_OFFSET 0x00000028 +#define AR9888_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define AR9888_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define AR9888_WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define AR9888_WLAN_GPIO_PIN0_ADDRESS 0x00000028 +#define AR9888_WLAN_GPIO_PIN1_ADDRESS 0x0000002c +#define AR9888_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define AR9888_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define AR9888_WLAN_SI_BASE_ADDRESS 0x00010000 +#define AR9888_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define AR9888_SOC_LPO_CAL_OFFSET 0x000000e0 +#define AR9888_WLAN_GPIO_PIN10_ADDRESS 0x00000050 +#define AR9888_WLAN_GPIO_PIN11_ADDRESS 0x00000054 +#define AR9888_WLAN_GPIO_PIN12_ADDRESS 0x00000058 +#define AR9888_WLAN_GPIO_PIN13_ADDRESS 0x0000005c +#define AR9888_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define AR9888_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define AR9888_SOC_LPO_CAL_ENABLE_LSB 20 +#define AR9888_SOC_LPO_CAL_ENABLE_MASK 0x00100000 +#define AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 + +#define AR9888_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define AR9888_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define AR9888_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 +#define AR9888_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 +#define AR9888_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define AR9888_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define AR9888_SI_CONFIG_I2C_LSB 16 +#define AR9888_SI_CONFIG_I2C_MASK 0x00010000 +#define AR9888_SI_CONFIG_POS_SAMPLE_LSB 7 +#define AR9888_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define AR9888_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define AR9888_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define AR9888_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define AR9888_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define AR9888_SI_CONFIG_DIVIDER_LSB 0 +#define AR9888_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define AR9888_SI_CONFIG_OFFSET 0x00000000 +#define AR9888_SI_TX_DATA0_OFFSET 0x00000008 +#define AR9888_SI_TX_DATA1_OFFSET 0x0000000c +#define AR9888_SI_RX_DATA0_OFFSET 0x00000010 +#define AR9888_SI_RX_DATA1_OFFSET 0x00000014 +#define AR9888_SI_CS_OFFSET 0x00000004 +#define AR9888_SI_CS_DONE_ERR_MASK 0x00000400 +#define AR9888_SI_CS_DONE_INT_MASK 0x00000200 +#define AR9888_SI_CS_START_LSB 8 +#define AR9888_SI_CS_START_MASK 0x00000100 +#define AR9888_SI_CS_RX_CNT_LSB 4 +#define AR9888_SI_CS_RX_CNT_MASK 0x000000f0 +#define AR9888_SI_CS_TX_CNT_LSB 0 +#define AR9888_SI_CS_TX_CNT_MASK 0x0000000f +#define AR9888_CE_COUNT 8 +#define AR9888_SR_WR_INDEX_ADDRESS 0x003c +#define AR9888_DST_WATERMARK_ADDRESS 0x0050 +#define AR9888_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define AR9888_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define AR9888_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define AR9888_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define AR9888_RX_MPDU_START_2_PN_47_32_LSB 0 +#define AR9888_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define AR9888_RX_MSDU_END_1_KEY_ID_OCT_MASK 0x000000ff +#define AR9888_RX_MSDU_END_1_KEY_ID_OCT_LSB 0 +#define AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define AR9888_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define AR9888_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define AR9888_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define AR9888_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define AR9888_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define AR9888_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define AR9888_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define AR9888_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define AR9888_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define AR9888_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define AR9888_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define AR9888_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define AR9888_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define AR9888_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define AR9888_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define AR9888_DST_WR_INDEX_ADDRESS 0x0040 +#define AR9888_SRC_WATERMARK_ADDRESS 0x004c +#define AR9888_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define AR9888_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define AR9888_DST_WATERMARK_LOW_MASK 0xffff0000 +#define AR9888_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define AR9888_CURRENT_SRRI_ADDRESS 0x0044 +#define AR9888_CURRENT_DRRI_ADDRESS 0x0048 +#define AR9888_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define AR9888_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define AR9888_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define AR9888_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define AR9888_HOST_IS_ADDRESS 0x0030 +#define AR9888_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define AR9888_HOST_IE_ADDRESS 0x002c +#define AR9888_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define AR9888_SR_BA_ADDRESS 0x0000 +#define AR9888_SR_SIZE_ADDRESS 0x0004 +#define AR9888_CE_CTRL1_ADDRESS 0x0010 +#define AR9888_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define AR9888_DR_BA_ADDRESS 0x0008 +#define AR9888_DR_SIZE_ADDRESS 0x000c +#define AR9888_MISC_IE_ADDRESS 0x0034 +#define AR9888_MISC_IS_AXI_ERR_MASK 0x00000400 +#define AR9888_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define AR9888_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define AR9888_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define AR9888_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define AR9888_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define AR9888_SRC_WATERMARK_LOW_LSB 16 +#define AR9888_SRC_WATERMARK_HIGH_LSB 0 +#define AR9888_DST_WATERMARK_LOW_LSB 16 +#define AR9888_DST_WATERMARK_HIGH_LSB 0 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define AR9888_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x00000004 +#define AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 2 +#define AR9888_SOC_GLOBAL_RESET_ADDRESS 0x0008 +#define AR9888_RTC_STATE_ADDRESS 0x0000 +#define AR9888_RTC_STATE_COLD_RESET_MASK 0x00000400 +#define AR9888_PCIE_SOC_WAKE_RESET 0x00000000 +#define AR9888_PCIE_SOC_WAKE_ADDRESS 0x0004 +#define AR9888_PCIE_SOC_WAKE_V_MASK 0x00000001 +#define AR9888_RTC_STATE_V_MASK 0x00000007 +#define AR9888_RTC_STATE_V_LSB 0 +#define AR9888_RTC_STATE_V_ON 3 +#define AR9888_PCIE_LOCAL_BASE_ADDRESS 0x80000 +#define AR9888_FW_IND_EVENT_PENDING 1 +#define AR9888_FW_IND_INITIALIZED 2 +#define AR9888_PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define AR9888_PCIE_INTR_CLR_ADDRESS 0x0014 +#define AR9888_PCIE_INTR_FIRMWARE_MASK 0x00000400 +#define AR9888_PCIE_INTR_CE0_MASK 0x00000800 +#define AR9888_PCIE_INTR_CE_MASK_ALL 0x0007f800 /* All CEs */ +#define AR9888_PCIE_INTR_CAUSE_ADDRESS 0x000c +#define AR9888_CPU_INTR_ADDRESS 0x0010 +#define AR9888_SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 +#define AR9888_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 +#define AR9888_SOC_RESET_CONTROL_ADDRESS 0x00000000 +#define AR9888_SOC_RESET_CONTROL_CE_RST_MASK 0x00040000 +#define AR9888_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define AR9888_CORE_CTRL_ADDRESS 0x0000 +#define AR9888_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define AR9888_LOCAL_SCRATCH_OFFSET 0x18 +#define AR9888_CLOCK_GPIO_OFFSET 0xffffffff +#define AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 + +#define AR9888_PCIE_INTR_CE_MASK(n) (AR9888_PCIE_INTR_CE0_MASK << (n)) +#define AR9888_FW_EVENT_PENDING_ADDRESS (AR9888_SOC_CORE_BASE_ADDRESS + AR9888_SCRATCH_3_ADDRESS) +#define AR9888_DRAM_BASE_ADDRESS AR9888_TARG_DRAM_START +#define AR9888_FW_INDICATOR_ADDRESS (AR9888_SOC_CORE_BASE_ADDRESS + AR9888_SCRATCH_3_ADDRESS) +#define AR9888_SYSTEM_SLEEP_OFFSET AR9888_SOC_SYSTEM_SLEEP_OFFSET +#define AR9888_WLAN_SYSTEM_SLEEP_OFFSET AR9888_SOC_SYSTEM_SLEEP_OFFSET +#define AR9888_WLAN_RESET_CONTROL_OFFSET AR9888_SOC_RESET_CONTROL_OFFSET +#define AR9888_CLOCK_CONTROL_OFFSET AR9888_SOC_CLOCK_CONTROL_OFFSET +#define AR9888_CLOCK_CONTROL_SI0_CLK_MASK AR9888_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define AR9888_RESET_CONTROL_MBOX_RST_MASK MISSING +#define AR9888_RESET_CONTROL_SI0_RST_MASK AR9888_SOC_RESET_CONTROL_SI0_RST_MASK +#define AR9888_GPIO_BASE_ADDRESS AR9888_WLAN_GPIO_BASE_ADDRESS +#define AR9888_GPIO_PIN0_OFFSET AR9888_WLAN_GPIO_PIN0_ADDRESS +#define AR9888_GPIO_PIN1_OFFSET AR9888_WLAN_GPIO_PIN1_ADDRESS +#define AR9888_GPIO_PIN0_CONFIG_MASK AR9888_WLAN_GPIO_PIN0_CONFIG_MASK +#define AR9888_GPIO_PIN1_CONFIG_MASK AR9888_WLAN_GPIO_PIN1_CONFIG_MASK +#define AR9888_SI_BASE_ADDRESS AR9888_WLAN_SI_BASE_ADDRESS +#define AR9888_SCRATCH_BASE_ADDRESS AR9888_SOC_CORE_BASE_ADDRESS +#define AR9888_CPU_CLOCK_OFFSET AR9888_SOC_CPU_CLOCK_OFFSET +#define AR9888_LPO_CAL_OFFSET AR9888_SOC_LPO_CAL_OFFSET +#define AR9888_GPIO_PIN10_OFFSET AR9888_WLAN_GPIO_PIN10_ADDRESS +#define AR9888_GPIO_PIN11_OFFSET AR9888_WLAN_GPIO_PIN11_ADDRESS +#define AR9888_GPIO_PIN12_OFFSET AR9888_WLAN_GPIO_PIN12_ADDRESS +#define AR9888_GPIO_PIN13_OFFSET AR9888_WLAN_GPIO_PIN13_ADDRESS +#define AR9888_CPU_CLOCK_STANDARD_LSB AR9888_SOC_CPU_CLOCK_STANDARD_LSB +#define AR9888_CPU_CLOCK_STANDARD_MASK AR9888_SOC_CPU_CLOCK_STANDARD_MASK +#define AR9888_LPO_CAL_ENABLE_LSB AR9888_SOC_LPO_CAL_ENABLE_LSB +#define AR9888_LPO_CAL_ENABLE_MASK AR9888_SOC_LPO_CAL_ENABLE_MASK +#define AR9888_ANALOG_INTF_BASE_ADDRESS AR9888_WLAN_ANALOG_INTF_BASE_ADDRESS +#define AR9888_MBOX_BASE_ADDRESS MISSING +#define AR9888_INT_STATUS_ENABLE_ERROR_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_ERROR_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_CPU_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_CPU_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define AR9888_INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define AR9888_COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define AR9888_COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define AR9888_INT_STATUS_ENABLE_ADDRESS MISSING +#define AR9888_CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define AR9888_CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define AR9888_HOST_INT_STATUS_ADDRESS MISSING +#define AR9888_CPU_INT_STATUS_ADDRESS MISSING +#define AR9888_ERROR_INT_STATUS_ADDRESS MISSING +#define AR9888_ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define AR9888_ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define AR9888_ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define AR9888_ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define AR9888_COUNT_DEC_ADDRESS MISSING +#define AR9888_HOST_INT_STATUS_CPU_MASK MISSING +#define AR9888_HOST_INT_STATUS_CPU_LSB MISSING +#define AR9888_HOST_INT_STATUS_ERROR_MASK MISSING +#define AR9888_HOST_INT_STATUS_ERROR_LSB MISSING +#define AR9888_HOST_INT_STATUS_COUNTER_MASK MISSING +#define AR9888_HOST_INT_STATUS_COUNTER_LSB MISSING +#define AR9888_RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define AR9888_WINDOW_DATA_ADDRESS MISSING +#define AR9888_WINDOW_READ_ADDR_ADDRESS MISSING +#define AR9888_WINDOW_WRITE_ADDR_ADDRESS MISSING +#define AR9888_HOST_INT_STATUS_MBOX_DATA_MASK 0x0f +#define AR9888_HOST_INT_STATUS_MBOX_DATA_LSB 0 + +struct targetdef_s ar9888_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = AR9888_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = AR9888_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = AR9888_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = AR9888_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = AR9888_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = AR9888_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = AR9888_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = AR9888_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = AR9888_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = AR9888_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = AR9888_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = AR9888_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = AR9888_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = AR9888_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = AR9888_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = AR9888_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = AR9888_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = AR9888_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = AR9888_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = AR9888_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = AR9888_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = AR9888_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = AR9888_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = AR9888_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = AR9888_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = AR9888_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = AR9888_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = AR9888_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = AR9888_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = AR9888_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = AR9888_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = AR9888_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = AR9888_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = AR9888_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = AR9888_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = AR9888_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = AR9888_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = AR9888_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = AR9888_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = AR9888_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = AR9888_SI_CS_START_LSB, + .d_SI_CS_START_MASK = AR9888_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = AR9888_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = AR9888_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = AR9888_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = AR9888_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = AR9888_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = AR9888_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = AR9888_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = AR9888_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = AR9888_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = AR9888_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = AR9888_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = AR9888_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = AR9888_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = AR9888_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = AR9888_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = AR9888_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = AR9888_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = AR9888_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = AR9888_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = AR9888_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = AR9888_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = AR9888_WLAN_MAC_BASE_ADDRESS, + .d_CE0_BASE_ADDRESS = AR9888_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR9888_CE1_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = AR9888_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = AR9888_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = AR9888_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = AR9888_CORE_CTRL_ADDRESS, + .d_CE_COUNT = AR9888_CE_COUNT, + .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, + .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, + .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, + .d_PCIE_INTR_ENABLE_ADDRESS = AR9888_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = AR9888_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = AR9888_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = AR9888_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = AR9888_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = AR9888_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = AR9888_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = AR9888_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = AR9888_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = AR9888_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = AR9888_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = AR9888_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = AR9888_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = AR9888_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_1_KEY_ID_OCT_MASK = AR9888_RX_MSDU_END_1_KEY_ID_OCT_MASK, + .d_RX_MSDU_END_1_KEY_ID_OCT_LSB = AR9888_RX_MSDU_END_1_KEY_ID_OCT_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = AR9888_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = AR9888_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = AR9888_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = AR9888_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = AR9888_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = AR9888_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = AR9888_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = AR9888_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = AR9888_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = AR9888_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = AR9888_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = AR9888_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = AR9888_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = AR9888_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = AR9888_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = AR9888_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = AR9888_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR9888_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = AR9888_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = AR9888_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = AR9888_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = AR9888_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = AR9888_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = AR9888_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = AR9888_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = AR9888_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = AR9888_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = AR9888_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = AR9888_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = AR9888_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = AR9888_HOST_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = AR9888_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = AR9888_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_HOST_IE_ADDRESS = AR9888_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = AR9888_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = AR9888_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = AR9888_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = AR9888_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = AR9888_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = AR9888_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = AR9888_DR_SIZE_ADDRESS, + .d_MISC_IE_ADDRESS = AR9888_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = AR9888_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = AR9888_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = AR9888_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = AR9888_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = AR9888_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = AR9888_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = AR9888_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = AR9888_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = AR9888_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = AR9888_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = AR9888_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = AR9888_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = AR9888_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = AR9888_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + + .d_PCIE_INTR_CAUSE_ADDRESS = AR9888_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = AR9888_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = AR9888_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = AR9888_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = AR9888_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = AR9888_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = AR9888_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = AR9888_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, +}; + +struct hostdef_s ar9888_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = AR9888_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = AR9888_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = AR9888_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = AR9888_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = AR9888_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = AR9888_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = AR9888_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = AR9888_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = AR9888_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = AR9888_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = AR9888_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = AR9888_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = AR9888_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = AR9888_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = AR9888_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = AR9888_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = AR9888_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = AR9888_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = AR9888_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = AR9888_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = AR9888_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = AR9888_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = AR9888_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = AR9888_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = AR9888_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = AR9888_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = AR9888_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = AR9888_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = AR9888_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = AR9888_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = AR9888_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = AR9888_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = AR9888_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = AR9888_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = AR9888_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = AR9888_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = AR9888_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = AR9888_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = AR9888_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = AR9888_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = AR9888_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = AR9888_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = AR9888_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = AR9888_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = AR9888_FW_IND_INITIALIZED, + .d_RTC_STATE_V_ON = AR9888_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = AR9888_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR9888_HOST_INT_STATUS_MBOX_DATA_LSB, +#endif +#ifdef HIF_PCI + .d_PCIE_SOC_RDY_STATUS_ADDRESS = PCIE_SOC_RDY_STATUS_ADDRESS, + .d_PCIE_SOC_RDY_STATUS_BAR_MASK = PCIE_SOC_RDY_STATUS_BAR_MASK, + .d_SOC_PCIE_BASE_ADDRESS = SOC_PCIE_BASE_ADDRESS, + .d_MSI_MAGIC_ADR_ADDRESS = MSI_MAGIC_ADR_ADDRESS, + .d_MSI_MAGIC_ADDRESS = MSI_MAGIC_ADDRESS, +#endif +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/cepci.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/cepci.h new file mode 100644 index 000000000000..f5ba19bde895 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/cepci.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __CEPCI_H__ +#define __CEPCI_H__ + +/* + * Support for Copy Engine over PCI. + * Structures shared between Host software and Target firmware. + */ + + +/* + * Total number of PCIe MSI interrupts requested for all interrupt sources. + * PCIe standard forces this to be a power of 2. + * Some Host OS's limit MSI requests that can be granted to 8 + * so for now we abide by this limit and avoid requesting more + * than that. + */ +#define MSI_NUM_REQUEST_LOG2 3 +#define MSI_NUM_REQUEST (1<hi_interconnect_state points + * here (and all members are 32-bit quantities in order to + * facilitate Host access). In particular, Host software is + * required to initialize pipe_cfg_addr and svc_to_pipe_map. + */ +struct pcie_state_s { + A_UINT32 pipe_cfg_addr; /* Pipe configuration Target address */ + /* NB: CE_pipe_config[CE_COUNT] */ + + A_UINT32 svc_to_pipe_map; /* Service to pipe map Target address */ + /* NB: service_to_pipe[PIPE_TO_CE_MAP_CN] */ + + A_UINT32 MSI_requested; /* number of MSI interrupts requested */ + A_UINT32 MSI_granted; /* number of MSI interrupts granted */ + A_UINT32 MSI_addr; /* Message Signalled Interrupt address */ + A_UINT32 MSI_data; /* Base data */ + A_UINT32 MSI_fw_intr_data; /* Data for firmware interrupt; + MSI data for other interrupts are + in various SoC registers */ + + A_UINT32 power_mgmt_method; /* PCIE_PWR_METHOD_* */ + A_UINT32 config_flags; /* PCIE_CONFIG_FLAG_* */ +}; + +/* + * PCIE_CONFIG_FLAG definitions + */ +#define PCIE_CONFIG_FLAG_ENABLE_L1 0x0000001 +#define PCIE_CONFIG_FLAG_CLK_SWITCH_WAIT 0x0000002 +#define PCIE_CONFIG_FLAG_AXI_CLK_GATE 0x0000004 + +#define PIPE_TO_CE_MAP_CNT 32 /* simple implementation constant */ + +/* + * Configuration information for a Copy Engine pipe. + * Passed from Host to Target during startup (one per CE). + */ +struct CE_pipe_config { + A_UINT32 pipenum; + A_UINT32 pipedir; + A_UINT32 nentries; + A_UINT32 nbytes_max; + A_UINT32 flags; + A_UINT32 reserved; +}; + +#endif /* __CEPCI_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio.c new file mode 100644 index 000000000000..1e21f44c1c29 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "adf_net_types.h" +#include "a_types.h" +#include "athdefs.h" +#include "a_osapi.h" +#include +#include +#include +#include "hif_sdio_dev.h" +#include "if_ath_sdio.h" +#include "regtable.h" + +#define ATH_MODULE_NAME hif_sdio + +unsigned int htc_credit_flow = 1; + +A_STATUS HIFStart(HIF_DEVICE *hif_device) +{ + HIF_SDIO_DEVICE *htc_sdio_device = HIFDevFromHIF(hif_device); + ENTER(); + HIFDevEnableInterrupts(htc_sdio_device); + EXIT(); + return A_OK; +} + +void +HIFFlushSurpriseRemove(HIF_DEVICE *hif_device) +{ + +} + +void HIFStop(HIF_DEVICE *hif_device) +{ + HIF_SDIO_DEVICE *htc_sdio_device = HIFDevFromHIF(hif_device); + ENTER(); + if (htc_sdio_device != NULL) { + HIFDevDisableInterrupts(htc_sdio_device); + HIFDevDestroy(htc_sdio_device); + } + EXIT(); +} + +A_STATUS HIFSend_head(HIF_DEVICE *hif_device, a_uint8_t pipe, + unsigned int transferID, unsigned int nbytes, adf_nbuf_t buf) +{ + HIF_SDIO_DEVICE *htc_sdio_device = HIFDevFromHIF(hif_device); + return HIFDevSendBuffer(htc_sdio_device, transferID, pipe, nbytes, buf); + +} + +int HIFMapServiceToPipe(HIF_DEVICE *hif_device, a_uint16_t ServiceId, + a_uint8_t *ULPipe, a_uint8_t *DLPipe, int *ul_is_polled, + int *dl_is_polled) +{ + HIF_SDIO_DEVICE *htc_sdio_device = HIFDevFromHIF(hif_device); + + return HIFDevMapServiceToPipe(htc_sdio_device, + ServiceId, ULPipe, DLPipe, hif_device->swap_mailbox); +} + +void HIFGetDefaultPipe(HIF_DEVICE *hif_device, a_uint8_t *ULPipe, + a_uint8_t *DLPipe) +{ + HIFMapServiceToPipe(hif_device, + HTC_CTRL_RSVD_SVC, + ULPipe, + DLPipe, + NULL, + NULL); +} + +void HIFPostInit(HIF_DEVICE *hif_device, void *target, + MSG_BASED_HIF_CALLBACKS *callbacks) +{ + HIF_SDIO_DEVICE *htc_sdio_device = HIFDevFromHIF(hif_device); + if (htc_sdio_device == NULL) { + htc_sdio_device = HIFDevCreate(hif_device, callbacks, target); + } + + if (htc_sdio_device) + HIFDevSetup(htc_sdio_device); + + return; +} + + +/*SDIO uses credit based flow control at the HTC layer so transmit resource checks are +bypassed. This API is relevant to USB where there may be a limited number of USB request +blocks (URBs) in the HIF*/ +a_uint16_t HIFGetFreeQueueNumber(HIF_DEVICE *hif_device, a_uint8_t pipe) +{ + a_uint16_t rv; + rv = 1; + return rv; +} + +void HIFSendCompleteCheck(HIF_DEVICE *hif_device, a_uint8_t pipe, int force) +{ + +} + +void *hif_get_targetdef(HIF_DEVICE *hif_device) +{ + return (void*)sc->targetdef; +} + +void HIFDump(HIF_DEVICE *hif_device, u_int8_t cmd_id, bool start) { + ENTER("Dummy Function"); +} + +void HIFSetBundleMode(HIF_DEVICE *hif_device, bool enabled, int rx_bundle_cnt) +{ + +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c new file mode 100644 index 000000000000..1982c75ef8cf --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#define ATH_MODULE_NAME hif +#include "a_debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hif_sdio_internal.h" +#include "if_ath_sdio.h" +#include "regtable.h" + +/* under HL SDIO, with Interface Memory support, we have the following + * reasons to support 2 mboxs: a) we need place different buffers in different + * mempool, for example, data using Interface Memory, desc and other using + * DRAM, they need different SDIO mbox channels; b) currently, tx mempool in + * LL case is seperated from main mempool, the structure (descs at the beginning + * of every pool buffer) is different, because they only need store tx desc from host. + * To align with LL case, we also need 2 mbox support just as PCIe LL cases. + */ + +#define INVALID_MAILBOX_NUMBER 0xFF +A_UINT8 HIFDevMapPipeToMailBox(HIF_SDIO_DEVICE *pDev, A_UINT8 pipeid) +{ + // TODO: temp version, should not hardcoded here, will be updated after HIF design + if (2 == pipeid || 3 == pipeid) + return 1; + else if (0 == pipeid || 1 == pipeid) + return 0; + else { + printk("%s:--------------------pipeid=%d,should not happen\n",__func__,pipeid); + adf_os_assert(0); + return INVALID_MAILBOX_NUMBER; + } +} + +A_UINT8 HIFDevMapMailBoxToPipe(HIF_SDIO_DEVICE *pDev, A_UINT8 mboxIndex, + A_BOOL upload) +{ + // TODO: temp version, should not hardcoded here, will be updated after HIF design + if (mboxIndex == 0) { + return upload ? 1 : 0; + } else if (mboxIndex == 1) { + return upload ? 3 : 2; + } else { + printk("%s:--------------------mboxIndex=%d,upload=%d,should not happen\n",__func__,mboxIndex,upload); + adf_os_assert(0); + return 0xff; + } +} + +A_STATUS HIFDevMapServiceToPipe(HIF_SDIO_DEVICE *pDev, A_UINT16 ServiceId, + A_UINT8 *ULPipe, A_UINT8 *DLPipe, A_BOOL SwapMapping) +{ + A_STATUS status = EOK; + switch (ServiceId) { + case HTT_DATA_MSG_SVC: + if (SwapMapping) { + *ULPipe = 1; + *DLPipe = 0; + } else { + *ULPipe = 3; + *DLPipe = 2; + } + break; + + case HTC_CTRL_RSVD_SVC: + case HTC_RAW_STREAMS_SVC: + *ULPipe = 1; + *DLPipe = 0; + break; + + case WMI_DATA_BE_SVC: + case WMI_DATA_BK_SVC: + case WMI_DATA_VI_SVC: + case WMI_DATA_VO_SVC: + *ULPipe = 1; + *DLPipe = 0; + break; + + case WMI_CONTROL_SVC: + if (SwapMapping) { + *ULPipe = 3; + *DLPipe = 2; + } else { + *ULPipe = 1; + *DLPipe = 0; + } + break; + + default: + status = !EOK; + break; + } + return status; +} + +HTC_PACKET *HIFDevAllocRxBuffer(HIF_SDIO_DEVICE *pDev, size_t length) +{ + HTC_PACKET *pPacket; + adf_nbuf_t netbuf; + A_UINT32 bufsize = 0, headsize = 0; + + bufsize = length + HIF_SDIO_RX_DATA_OFFSET; + headsize = sizeof(HTC_PACKET); + netbuf = adf_nbuf_alloc(NULL, bufsize + headsize, 0, 4, FALSE); + if (netbuf == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("(%s)Allocate netbuf failed\n", __FUNCTION__)); + return NULL; + } + pPacket = (HTC_PACKET *) adf_nbuf_data(netbuf); + adf_nbuf_reserve(netbuf, headsize); + + SET_HTC_PACKET_INFO_RX_REFILL(pPacket, + pDev, + adf_nbuf_data(netbuf), + bufsize, + ENDPOINT_0); + SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); + return pPacket; +} + +HIF_SDIO_DEVICE* HIFDevCreate(HIF_DEVICE *hif_device, + MSG_BASED_HIF_CALLBACKS *callbacks, + void *target) +{ + + A_STATUS status; + HIF_SDIO_DEVICE *pDev; + + pDev = A_MALLOC(sizeof(HIF_SDIO_DEVICE)); + if (!pDev) { + A_ASSERT(FALSE); + return NULL; + } + + A_MEMZERO(pDev, sizeof(HIF_SDIO_DEVICE)); + A_MUTEX_INIT(&pDev->Lock); + A_MUTEX_INIT(&pDev->TxLock); + A_MUTEX_INIT(&pDev->RxLock); + + pDev->HIFDevice = hif_device; + pDev->pTarget = target; + status = HIFConfigureDevice(hif_device, + HIF_DEVICE_SET_HTC_CONTEXT, + (void*) pDev, + sizeof(pDev)); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("(%s)HIF_DEVICE_SET_HTC_CONTEXT failed!!!\n", __FUNCTION__)); + } + + A_MEMCPY(&pDev->hif_callbacks, callbacks, sizeof(*callbacks)); + + return pDev; +} + +void HIFDevDestroy(HIF_SDIO_DEVICE *pDev) +{ + A_STATUS status; + + status = HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_SET_HTC_CONTEXT, + (void*) NULL, + 0); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("(%s)HIF_DEVICE_SET_HTC_CONTEXT failed!!!\n", __FUNCTION__)); + } + A_FREE(pDev); +} + +HIF_SDIO_DEVICE *HIFDevFromHIF(HIF_DEVICE *hif_device) +{ + HIF_SDIO_DEVICE *pDev = NULL; + A_STATUS status; + status = HIFConfigureDevice(hif_device, + HIF_DEVICE_GET_HTC_CONTEXT, + (void**) &pDev, + sizeof(HIF_SDIO_DEVICE)); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("(%s)HTC_SDIO_CONTEXT is NULL!!!\n", __FUNCTION__)); + } + return pDev; +} + +A_STATUS HIFDevDisableInterrupts(HIF_SDIO_DEVICE *pDev) +{ + MBOX_IRQ_ENABLE_REGISTERS regs; + A_STATUS status = A_OK; + ENTER(); + + LOCK_HIF_DEV(pDev); + /* Disable all interrupts */ + pDev->IrqEnableRegisters.int_status_enable = 0; + pDev->IrqEnableRegisters.cpu_int_status_enable = 0; + pDev->IrqEnableRegisters.error_status_enable = 0; + pDev->IrqEnableRegisters.counter_int_status_enable = 0; + /* copy into our temp area */ + A_MEMCPY(®s, + &pDev->IrqEnableRegisters, + sizeof(pDev->IrqEnableRegisters)); + + UNLOCK_HIF_DEV(pDev); + + /* always synchronous */ + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + (A_UCHAR *)®s, + sizeof(MBOX_IRQ_ENABLE_REGISTERS), + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status != A_OK) { + /* Can't write it for some reason */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to update interrupt control registers err: %d", status)); + } + + /* mask the host controller interrupts */ + HIFMaskInterrupt(pDev->HIFDevice); + EXIT("status :%d",status); + return status; +} + +A_STATUS HIFDevEnableInterrupts(HIF_SDIO_DEVICE *pDev) +{ + A_STATUS status; + MBOX_IRQ_ENABLE_REGISTERS regs; + ENTER(); + + + /* for good measure, make sure interrupt are disabled before unmasking at the HIF + * layer. + * The rationale here is that between device insertion (where we clear the interrupts the first time) + * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets. + * The AR6K interrupt enables reset back to an "enabled" state when this happens. + * */ + HIFDevDisableInterrupts(pDev); + + /* Unmask the host controller interrupts */ + HIFUnMaskInterrupt(pDev->HIFDevice); + + LOCK_HIF_DEV(pDev); + + /* Enable all the interrupts except for the internal AR6000 CPU interrupt */ + pDev->IrqEnableRegisters.int_status_enable = + INT_STATUS_ENABLE_ERROR_SET(0x01) | INT_STATUS_ENABLE_CPU_SET(0x01) + | INT_STATUS_ENABLE_COUNTER_SET(0x01); + + pDev->IrqEnableRegisters.int_status_enable |= + INT_STATUS_ENABLE_MBOX_DATA_SET(0x01) | INT_STATUS_ENABLE_MBOX_DATA_SET(0x02); // enable 2 mboxs INT + + /* Set up the CPU Interrupt Status Register, enable CPU sourced interrupt #0, #1 + * #0 is used for report assertion from target + * #1 is used for inform host that credit arrived + * */ + pDev->IrqEnableRegisters.cpu_int_status_enable = 0x03; + + /* Set up the Error Interrupt Status Register */ + pDev->IrqEnableRegisters.error_status_enable = + (ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) + | ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01)) >> 16; + + /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */ + pDev->IrqEnableRegisters.counter_int_status_enable = + (COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK)) >> 24; + + /* copy into our temp area */ + A_MEMCPY(®s, + &pDev->IrqEnableRegisters, + sizeof(MBOX_IRQ_ENABLE_REGISTERS)); + + UNLOCK_HIF_DEV(pDev); + + + /* always synchronous */ + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + (A_UCHAR *)®s, + sizeof(MBOX_IRQ_ENABLE_REGISTERS), + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status != A_OK) { + /* Can't write it for some reason */ + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("Failed to update interrupt control registers err: %d\n", status)); + + } + EXIT(); + return status; +} + +A_STATUS HIFDevSetup(HIF_SDIO_DEVICE *pDev) +{ + A_STATUS status; + A_UINT32 blocksizes[MAILBOX_COUNT]; + HTC_CALLBACKS htcCallbacks; + HIF_DEVICE *hif_device = pDev->HIFDevice; + + ENTER(); + + status = HIFConfigureDevice(hif_device, + HIF_DEVICE_GET_MBOX_ADDR, + &pDev->MailBoxInfo, + sizeof(pDev->MailBoxInfo)); + + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("(%s)HIF_DEVICE_GET_MBOX_ADDR failed!!!\n", __FUNCTION__)); + A_ASSERT(FALSE); + } + + status = HIFConfigureDevice(hif_device, + HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, + sizeof(blocksizes)); + if (status != A_OK) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("(%s)HIF_DEVICE_GET_MBOX_BLOCK_SIZE failed!!!\n", __FUNCTION__)); + A_ASSERT(FALSE); + } + + pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE]; + pDev->BlockMask = pDev->BlockSize - 1; + A_ASSERT((pDev->BlockSize & pDev->BlockMask) == 0); + + /* assume we can process HIF interrupt events asynchronously */ + pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC; + + /* see if the HIF layer overrides this assumption */ + HIFConfigureDevice(hif_device, + HIF_DEVICE_GET_IRQ_PROC_MODE, + &pDev->HifIRQProcessingMode, + sizeof(pDev->HifIRQProcessingMode)); + + switch (pDev->HifIRQProcessingMode) { + case HIF_DEVICE_IRQ_SYNC_ONLY: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("HIF Interrupt processing is SYNC ONLY\n")); + /* see if HIF layer wants HTC to yield */ + HIFConfigureDevice(hif_device, + HIF_DEVICE_GET_IRQ_YIELD_PARAMS, + &pDev->HifIRQYieldParams, + sizeof(pDev->HifIRQYieldParams)); + + if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) { + AR_DEBUG_PRINTF( ATH_DEBUG_WARN, + ("HIF requests that DSR yield per %d RECV packets \n", pDev->HifIRQYieldParams.RecvPacketYieldCount)); + pDev->DSRCanYield = TRUE; + } + break; + case HIF_DEVICE_IRQ_ASYNC_SYNC: + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("HIF Interrupt processing is ASYNC and SYNC\n")); + break; + default: + A_ASSERT(FALSE); + break; + } + + pDev->HifMaskUmaskRecvEvent = NULL; + + /* see if the HIF layer implements the mask/unmask recv events function */ + HIFConfigureDevice(hif_device, + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, + &pDev->HifMaskUmaskRecvEvent, + sizeof(pDev->HifMaskUmaskRecvEvent)); + + status = HIFDevDisableInterrupts(pDev); + + A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS)); + /* the device layer handles these */ + htcCallbacks.rwCompletionHandler = HIFDevRWCompletionHandler; + htcCallbacks.dsrHandler = HIFDevDsrHandler; + htcCallbacks.context = pDev; + status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks); + + EXIT(); + return status; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.h new file mode 100644 index 000000000000..40154fad73d6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_dev.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef HIF_SDIO_DEV_H_ +#define HIF_SDIO_DEV_H_ + +#include "adf_net_types.h" +#include "a_types.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "hif_msg_based.h" +#include "athstartpack.h" + +typedef struct TAG_HIF_SDIO_DEVICE HIF_SDIO_DEVICE; + +HIF_SDIO_DEVICE* HIFDevFromHIF(HIF_DEVICE *hif_device); + +HIF_SDIO_DEVICE* HIFDevCreate(HIF_DEVICE *hif_device, + MSG_BASED_HIF_CALLBACKS *callbacks, + void *target); + +void HIFDevDestroy(HIF_SDIO_DEVICE *htc_sdio_device); + +A_STATUS HIFDevSetup(HIF_SDIO_DEVICE *htc_sdio_device); + +A_STATUS HIFDevEnableInterrupts(HIF_SDIO_DEVICE *htc_sdio_device); + +A_STATUS HIFDevDisableInterrupts(HIF_SDIO_DEVICE *htc_sdio_device); + +A_STATUS HIFDevSendBuffer(HIF_SDIO_DEVICE *htc_sdio_device, unsigned int transferID, a_uint8_t pipe, + unsigned int nbytes, adf_nbuf_t buf); + +A_STATUS HIFDevMapServiceToPipe(HIF_SDIO_DEVICE *pDev, A_UINT16 ServiceId, + A_UINT8 *ULPipe, A_UINT8 *DLPipe, A_BOOL SwapMapping); + +#endif /* HIF_SDIO_DEV_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h new file mode 100644 index 000000000000..30f1f06e24e9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_internal.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef HIF_SDIO_INTERNAL_H_ +#define HIF_SDIO_INTERNAL_H_ + +#include "a_debug.h" +#include "hif_sdio_dev.h" +#include "htc_packet.h" +#include "htc_api.h" + + +#define HIF_SDIO_RX_DATA_OFFSET 64 + +/* TODO: print output level and mask control */ +#define ATH_DEBUG_IRQ ATH_DEBUG_MAKE_MODULE_MASK(4) +#define ATH_DEBUG_XMIT ATH_DEBUG_MAKE_MODULE_MASK(5) +#define ATH_DEBUG_RECV ATH_DEBUG_MAKE_MODULE_MASK(6) + +#define ATH_DEBUG_MAX_MASK 32 + +#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ + INT_STATUS_ENABLE_CPU_MASK | \ + INT_STATUS_ENABLE_COUNTER_MASK) + +/* HTC operational parameters */ +#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ +#define HTC_TARGET_DEBUG_INTR_MASK 0x01 +#define HTC_TARGET_CREDIT_INTR_MASK 0xF0 + +#define MAILBOX_COUNT 4 +#define MAILBOX_FOR_BLOCK_SIZE 1 +#define MAILBOX_USED_COUNT 2 +#if defined(SDIO_3_0) +#define MAILBOX_LOOKAHEAD_SIZE_IN_WORD 2 +#else +#define MAILBOX_LOOKAHEAD_SIZE_IN_WORD 1 +#endif +#define AR6K_TARGET_DEBUG_INTR_MASK 0x01 + +typedef PREPACK struct _MBOX_IRQ_PROC_REGISTERS { + A_UINT8 host_int_status; + A_UINT8 cpu_int_status; + A_UINT8 error_int_status; + A_UINT8 counter_int_status; + A_UINT8 mbox_frame; + A_UINT8 rx_lookahead_valid; + A_UINT8 host_int_status2; + A_UINT8 gmbox_rx_avail; + A_UINT32 rx_lookahead[MAILBOX_LOOKAHEAD_SIZE_IN_WORD * MAILBOX_COUNT]; + A_UINT32 int_status_enable; +}POSTPACK MBOX_IRQ_PROC_REGISTERS; + +typedef PREPACK struct _MBOX_IRQ_ENABLE_REGISTERS { + A_UINT8 int_status_enable; + A_UINT8 cpu_int_status_enable; + A_UINT8 error_status_enable; + A_UINT8 counter_int_status_enable; +}POSTPACK MBOX_IRQ_ENABLE_REGISTERS; + +#define TOTAL_CREDIT_COUNTER_CNT 4 + +typedef PREPACK struct _MBOX_COUNTER_REGISTERS { + A_UINT32 counter[TOTAL_CREDIT_COUNTER_CNT]; +}POSTPACK MBOX_COUNTER_REGISTERS; + +#define SDIO_NUM_DATA_RX_BUFFERS 64 +#define SDIO_DATA_RX_SIZE 1664 + +struct TAG_HIF_SDIO_DEVICE { + HIF_DEVICE *HIFDevice; + A_MUTEX_T Lock; + A_MUTEX_T TxLock; + A_MUTEX_T RxLock; + MBOX_IRQ_PROC_REGISTERS IrqProcRegisters; + MBOX_IRQ_ENABLE_REGISTERS IrqEnableRegisters; + MBOX_COUNTER_REGISTERS MailBoxCounterRegisters; + MSG_BASED_HIF_CALLBACKS hif_callbacks; + HIF_DEVICE_MBOX_INFO MailBoxInfo; + A_UINT32 BlockSize; + A_UINT32 BlockMask; + HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode; + HIF_DEVICE_IRQ_YIELD_PARAMS HifIRQYieldParams; + A_BOOL DSRCanYield; + HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent; + int CurrentDSRRecvCount; + int RecheckIRQStatusCnt; + A_UINT32 RecvStateFlags; + void *pTarget; +}; + +#define LOCK_HIF_DEV(device) A_MUTEX_LOCK(&(device)->Lock); +#define UNLOCK_HIF_DEV(device) A_MUTEX_UNLOCK(&(device)->Lock); +#define LOCK_HIF_DEV_RX(t) A_MUTEX_LOCK(&(t)->RxLock); +#define UNLOCK_HIF_DEV_RX(t) A_MUTEX_UNLOCK(&(t)->RxLock); +#define LOCK_HIF_DEV_TX(t) A_MUTEX_LOCK(&(t)->TxLock); +#define UNLOCK_HIF_DEV_TX(t) A_MUTEX_UNLOCK(&(t)->TxLock); + +#define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask))) +#define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length) +#define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0) + +#define HTC_RECV_WAIT_BUFFERS (1 << 0) +#define HTC_OP_STATE_STOPPING (1 << 0) + +#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0) +#define HTC_RX_PKT_REFRESH_HDR (1 << 1) +#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2) +#define HTC_RX_PKT_NO_RECYCLE (1 << 3) +#define HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK (1 << 4) + +#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY) + +/* hif_sdio_dev.c */ +HTC_PACKET *HIFDevAllocRxBuffer(HIF_SDIO_DEVICE *pDev, size_t length); + +A_UINT8 HIFDevMapPipeToMailBox(HIF_SDIO_DEVICE *pDev, A_UINT8 pipeid); +A_UINT8 HIFDevMapMailBoxToPipe(HIF_SDIO_DEVICE *pDev, A_UINT8 mboxIndex, + A_BOOL upload); + +/* hif_sdio_recv.c */ +A_STATUS HIFDevRWCompletionHandler(void *context, A_STATUS status); +A_STATUS HIFDevDsrHandler(void *context); + +#endif /* HIF_SDIO_INTERNAL_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c new file mode 100644 index 000000000000..bde28f027689 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_recv.c @@ -0,0 +1,1323 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#define ATH_MODULE_NAME hif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hif_sdio_internal.h" +#include "../../HTC/htc_internal.h" +#include "regtable.h" +#include "if_ath_sdio.h" + + +static void HIFDevDumpRegisters(HIF_SDIO_DEVICE *pDev, + MBOX_IRQ_PROC_REGISTERS *pIrqProcRegs, + MBOX_IRQ_ENABLE_REGISTERS *pIrqEnableRegs, + MBOX_COUNTER_REGISTERS *pMailBoxCounterRegisters) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RegTable->")); + + if (pIrqProcRegs != NULL) { + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("HostIntStatus: 0x%x ",pIrqProcRegs->host_int_status)); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("CPUIntStatus: 0x%x ",pIrqProcRegs->cpu_int_status)); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("ErrorIntStatus: 0x%x ",pIrqProcRegs->error_int_status)); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("CounterIntStatus: 0x%x ",pIrqProcRegs->counter_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("MboxFrame: 0x%x ",pIrqProcRegs->mbox_frame)); + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\nRegTable->")); + + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("RxLKAValid: 0x%x ",pIrqProcRegs->rx_lookahead_valid)); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("RxLKA0: 0x%x",pIrqProcRegs->rx_lookahead[0])); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("RxLKA1: 0x%x ",pIrqProcRegs->rx_lookahead[1])); + + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("RxLKA2: 0x%x ",pIrqProcRegs->rx_lookahead[2])); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("RxLKA3: 0x%x",pIrqProcRegs->rx_lookahead[3])); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\nRegTable->")); + + if (pDev->MailBoxInfo.GMboxAddress != 0) { + /* if the target supports GMBOX hardware, dump some additional state */ + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("GMBOX-HostIntStatus2: 0x%x ",pIrqProcRegs->host_int_status2)); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("GMBOX-RX-Avail: 0x%x ",pIrqProcRegs->gmbox_rx_avail)); + } + } + + if (pIrqEnableRegs != NULL) { + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable)); + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable)); + } + + if (pMailBoxCounterRegisters != NULL){ + int i; + for (i = 0; i < 4; i ++){ + AR_DEBUG_PRINTF( ATH_DEBUG_ANY, + ("Counter[%d]: 0x%x\n", i, pMailBoxCounterRegisters->counter[i])); + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------->\n")); +} + +static A_STATUS HIFDevAllocAndPrepareRxPackets(HIF_SDIO_DEVICE *pDev, + A_UINT32 LookAheads[], int Messages, HTC_PACKET_QUEUE *pQueue) +{ + A_STATUS status = A_OK; + HTC_PACKET *pPacket; + HTC_FRAME_HDR *pHdr; + int i, j; + int numMessages; + int fullLength; + A_BOOL noRecycle; + + /* lock RX while we assemble the packet buffers */ + LOCK_HIF_DEV_RX(pDev); + + for (i = 0; i < Messages; i++) { + + pHdr = (HTC_FRAME_HDR *) &LookAheads[i]; + if (pHdr->EndpointID >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID)); + /* invalid endpoint */ + status = A_EPROTO; + break; + } + + if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("Payload length %d exceeds max HTC : %d !\n", pHdr->PayloadLen, (A_UINT32)HTC_MAX_PAYLOAD_LENGTH)); + status = A_EPROTO; + break; + } + + numMessages = GET_RECV_BUNDLE_COUNT(pHdr->Flags); + + if (!numMessages) + { + /* HTC header only indicates 1 message to fetch */ + numMessages = 1; + } + else + { + /* the count doesn't include the starter frame, just a count of + frames to follow */ + numMessages++; + //A_ASSERT(numMessages <= target->MaxMsgPerBundle); + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages)); + } + + fullLength = DEV_CALC_RECV_PADDED_LEN(pDev,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR)); + + /* + all but the last packet have a length of payloadLen + sizeof(HTC_FRAME_HDR) + The last packet in the bundle has an additional 16 byte lookahead information. + This is present only if bit 0 of the flags is set + */ + + /* get packet buffers for each message, if there was a bundle detected in the header, + * use pHdr as a template to fetch all packets in the bundle */ + for (j = 0; j < numMessages; j++) { + + /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup, + * they must be explicitly returned */ + noRecycle = FALSE; + + /*allocate memory for the last packet*/ + if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK)) + fullLength += HIF_MBOX_BLOCK_SIZE; + + pPacket = HIFDevAllocRxBuffer(pDev, fullLength); + + + if (pPacket == NULL) { + /* this is not an error, we simply need to mark that we are waiting for buffers.*/ + pDev->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS; + //pDev->EpWaitingForBuffers = pEndpoint->Id; + status = A_NO_RESOURCE; + break; + } + + //AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id); + /* clear flags */ + pPacket->PktInfo.AsRx.HTCRxFlags = 0; + pPacket->PktInfo.AsRx.IndicationFlags = 0; + pPacket->Status = A_OK; + + if (noRecycle) { + /* flag that these packets cannot be recycled, they have to be returned to the + * user */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_NO_RECYCLE; + } + /* add packet to queue (also incase we need to cleanup down below) */ + HTC_PACKET_ENQUEUE(pQueue, pPacket); + + /* + if (HTC_STOPPING(target)) { + status = A_ECANCELED; + break; + } + */ + + /* make sure this message can fit in the endpoint buffer */ + if ((A_UINT32) fullLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n", pHdr->PayloadLen, fullLength, pPacket->BufferLength)); + status = A_EPROTO; + break; + } + if (j > 0) { + /* for messages fetched in a bundle the expected lookahead is unknown since we + * are only using the lookahead of the first packet as a template of what to + * expect for lengths */ + /* flag that once we get the real HTC header we need to refesh the information */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_REFRESH_HDR; + /* set it to something invalid */ + pPacket->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF; + } else { + pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */ + } + /* set the amount of data to fetch */ + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; + if ((j == (numMessages-1)) && ((pHdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK)) + pPacket->PktInfo.AsRx.HTCRxFlags |= + HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK; + pPacket->Endpoint = pHdr->EndpointID; + pPacket->Completion = NULL; + } + + if (A_FAILED(status)) { + if (A_NO_RESOURCE == status) { + /* this is actually okay */ + status = A_OK; + } + break; + } + + } + + UNLOCK_HIF_DEV_RX(pDev); + + if (A_FAILED(status)) { + while (!HTC_QUEUE_EMPTY(pQueue)) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + } + } + return status; +} + +static INLINE A_STATUS HIFDevRecvPacket(HIF_SDIO_DEVICE *pDev, + HTC_PACKET *pPacket, + A_UINT32 RecvLength, + A_UINT8 mboxIndex) +{ + A_UINT32 paddedLength; + A_STATUS status; + A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength); + + if (paddedLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", paddedLength,RecvLength,pPacket->BufferLength)); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket, A_EINVAL); + return A_OK; + } + return A_EINVAL; + } + + /* mailbox index is saved in Endpoint member */ + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + ("HIFDevRecvPacket (0x%lX : hdr:0x%X) Len:%d, Padded Length: %d Mbox:0x%X\n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr, + RecvLength, + paddedLength, + pDev->MailBoxInfo.MboxAddresses[mboxIndex])); + +#ifdef HIF_SYNC_READ + status = HIFSyncRead(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[mboxIndex], + pPacket->pBuffer, + paddedLength, + (sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX), + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ +#else + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[mboxIndex], + pPacket->pBuffer, + paddedLength, + (sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX), + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ +#endif + + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, ("EP%d, Seq:%d\n", + ((HTC_FRAME_HDR*)pPacket->pBuffer)->EndpointID, + ((HTC_FRAME_HDR*)pPacket->pBuffer)->ControlBytes1)); + if (status != A_OK) { + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + ("HIFDevRecvPacket (0x%lX : hdr:0x%X) Failed\n", (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr)); + } + if (sync) { + pPacket->Status = status; + if (status == A_OK) { + HTC_FRAME_HDR *pHdr = (HTC_FRAME_HDR *) pPacket->pBuffer; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HIFDevRecvPacket " + "EP:%d,PayloadLen:%d,Flag:%d,CB:0x%02X,0x%02X\n", + pHdr->EndpointID, + pHdr->PayloadLen, + pHdr->Flags, + pHdr->ControlBytes0, + pHdr->ControlBytes1)); + } + } + + return status; +} + +static INLINE A_STATUS HIFDevProcessTrailer(HIF_SDIO_DEVICE *pDev, + A_UINT8 *pBuffer, int Length, A_UINT32 *pNextLookAheads, + int *pNumLookAheads, HTC_ENDPOINT_ID FromEndpoint) +{ + HTC_RECORD_HDR *pRecord; + A_UINT8 *pRecordBuf; + HTC_LOOKAHEAD_REPORT *pLookAhead; + A_UINT8 *pOrigBuffer; + int origLength; + A_STATUS status; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("+HTCProcessTrailer (length:%d) \n", Length)); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer"); + } + + pOrigBuffer = pBuffer; + origLength = Length; + status = A_OK; + + while (Length > 0) { + + if (Length < sizeof(HTC_RECORD_HDR)) { + status = A_EPROTO; + break; + } + /* these are byte aligned structs */ + pRecord = (HTC_RECORD_HDR *) pBuffer; + Length -= sizeof(HTC_RECORD_HDR); + pBuffer += sizeof(HTC_RECORD_HDR); + + if (pRecord->Length > Length) { + /* no room left in buffer for record */ + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + (" invalid record length: %d (id:%d) buffer has: %d bytes left \n", pRecord->Length, pRecord->RecordID, Length)); + status = A_EPROTO; + break; + } + /* start of record follows the header */ + pRecordBuf = pBuffer; + + switch (pRecord->RecordID) { + case HTC_RECORD_CREDITS: + /* Process in HTC, ignore here*/ + break; + case HTC_RECORD_LOOKAHEAD: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT)); + pLookAhead = (HTC_LOOKAHEAD_REPORT *) pRecordBuf; + if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) + && (pNextLookAheads != NULL)) { + + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) %d %d\n", + pLookAhead->PreValid, pLookAhead->PostValid, + FromEndpoint, + pLookAhead->LookAhead0 + )); + /* look ahead bytes are valid, copy them over */ + ((A_UINT8 *) (&pNextLookAheads[0]))[0] = pLookAhead->LookAhead0; + ((A_UINT8 *) (&pNextLookAheads[0]))[1] = pLookAhead->LookAhead1; + ((A_UINT8 *) (&pNextLookAheads[0]))[2] = pLookAhead->LookAhead2; + ((A_UINT8 *) (&pNextLookAheads[0]))[3] = pLookAhead->LookAhead3; + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes((A_UINT8 *) pNextLookAheads, + 4, + "Next Look Ahead"); + } + /* just one normal lookahead */ + if (pNumLookAheads != NULL) { + *pNumLookAheads = 1; + } + } + break; + case HTC_RECORD_LOOKAHEAD_BUNDLE: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)); + if (pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT) + && (pNextLookAheads != NULL)) { + HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt; + int i; + + pBundledLookAheadRpt = + (HTC_BUNDLED_LOOKAHEAD_REPORT *) pRecordBuf; + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes(pRecordBuf, + pRecord->Length, + "Bundle LookAhead"); + } + + if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) + > HTC_MAX_MSG_PER_BUNDLE_RX) { + /* this should never happen, the target restricts the number + * of messages per bundle configured by the host */ + A_ASSERT(FALSE); + status = A_EPROTO; + break; + } + for (i = 0; i< (int) (pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) { + ((A_UINT8 *) (&pNextLookAheads[i]))[0] = + pBundledLookAheadRpt->LookAhead0; + ((A_UINT8 *) (&pNextLookAheads[i]))[1] = + pBundledLookAheadRpt->LookAhead1; + ((A_UINT8 *) (&pNextLookAheads[i]))[2] = + pBundledLookAheadRpt->LookAhead2; + ((A_UINT8 *) (&pNextLookAheads[i]))[3] = + pBundledLookAheadRpt->LookAhead3; + pBundledLookAheadRpt++; + } + + if (pNumLookAheads != NULL) { + *pNumLookAheads = i; + } + } + break; + default: + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + (" HIF unhandled record: id:%d length:%d \n", pRecord->RecordID, pRecord->Length)); + break; + } + + if (A_FAILED(status)) { + break; + } + + /* advance buffer past this record for next time around */ + pBuffer += pRecord->Length; + Length -= pRecord->Length; + } + + if (A_FAILED(status)) { + DebugDumpBytes(pOrigBuffer, origLength, "BAD Recv Trailer"); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n")); + return status; + +} + + +/* process a received message (i.e. strip off header, process any trailer data) + * note : locks must be released when this function is called */ +static A_STATUS HIFDevProcessRecvHeader(HIF_SDIO_DEVICE *pDev, + HTC_PACKET *pPacket, A_UINT32 *pNextLookAheads, int *pNumLookAheads) +{ + A_UINT8 temp; + A_UINT8 *pBuf; + A_STATUS status = A_OK; + A_UINT16 payloadLen; + A_UINT32 lookAhead, ActualLength; + + pBuf = pPacket->pBuffer; + ActualLength = pPacket->ActualLength; + + if (pNumLookAheads != NULL) { + *pNumLookAheads = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n")); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT"); + } + + do { + /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to + * retrieve 16 bit fields */ + payloadLen = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, PAYLOADLEN); + + ((A_UINT8 *) &lookAhead)[0] = pBuf[0]; + ((A_UINT8 *) &lookAhead)[1] = pBuf[1]; + ((A_UINT8 *) &lookAhead)[2] = pBuf[2]; + ((A_UINT8 *) &lookAhead)[3] = pBuf[3]; + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) { + /* refresh expected hdr, since this was unknown at the time we grabbed the packets + * as part of a bundle */ + pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead; + /* refresh actual length since we now have the real header */ + pPacket->ActualLength = payloadLen + HTC_HDR_LENGTH; + + /* validate the actual header that was refreshed */ + if (pPacket->ActualLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("Refreshed HDR payload length (%d) in bundled RECV is invalid (hdr: 0x%X) \n", payloadLen, lookAhead)); + /* limit this to max buffer just to print out some of the buffer */ + pPacket->ActualLength = + min(pPacket->ActualLength, pPacket->BufferLength); + status = A_EPROTO; + break; + } + + if (pPacket->Endpoint + != HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, ENDPOINTID)) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n", HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, ENDPOINTID), pPacket->Endpoint)); + status = A_EPROTO; + break; + } + } + + if (lookAhead != pPacket->PktInfo.AsRx.ExpectedHdr) { + /* somehow the lookahead that gave us the full read length did not + * reflect the actual header in the pending message */ + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("HIFDevProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X), 0x%08X != 0x%08X\n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags, + lookAhead, pPacket->PktInfo.AsRx.ExpectedHdr)); +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes((A_UINT8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead"); + DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header"); +#ifdef HTC_CAPTURE_LAST_FRAME + DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header"); + if (target->LastTrailerLength != 0) { + DebugDumpBytes(target->LastTrailer, + target->LastTrailerLength, + "Last trailer"); + } +#endif +#endif + status = A_EPROTO; + break; + } + + /* get flags */ + temp = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, FLAGS); + + if (temp & HTC_FLAGS_RECV_TRAILER) { + /* this packet has a trailer */ + + /* extract the trailer length in control byte 0 */ + temp = HTC_GET_FIELD(pBuf, HTC_FRAME_HDR, CONTROLBYTES0); + + if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { + AR_DEBUG_PRINTF( ATH_DEBUG_ERR, + ("HIFDevProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", payloadLen, temp)); + status = A_EPROTO; + break; + } + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { + /* this packet was fetched as part of an HTC bundle, the embedded lookahead is + * not valid since the next packet may have already been fetched as part of the + * bundle */ + pNextLookAheads = NULL; + pNumLookAheads = NULL; + } + + /* process trailer data that follows HDR + application payload */ + status = HIFDevProcessTrailer(pDev, + (pBuf + HTC_HDR_LENGTH + payloadLen - temp), + temp, + pNextLookAheads, + pNumLookAheads, + pPacket->Endpoint); + + if (A_FAILED(status)) { + break; + } + } + }while (FALSE); + + if (A_FAILED(status)) { + /* dump the whole packet */ + DebugDumpBytes(pBuf, + pPacket->ActualLength, + "BAD HTC Recv PKT"); + } else { + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + if (pPacket->ActualLength > 0) { + AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg"); + } + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HIFDevProcessRecvHeader \n")); + return status; +} + +static A_STATUS HIFDevIssueRecvPacketBundle(HIF_SDIO_DEVICE *pDev, + HTC_PACKET_QUEUE *pRecvPktQueue, + HTC_PACKET_QUEUE *pSyncCompletionQueue, + A_UINT8 MailBoxIndex, + int *pNumPacketsFetched, + A_BOOL PartialBundle) +{ A_STATUS status = A_OK; + int i, totalLength = 0; + unsigned char *pBundleBuffer = NULL; + HTC_PACKET *pPacket, *pPacketRxBundle; + HTC_TARGET *target = NULL; + A_UINT32 paddedLength; + + int bundleSpaceRemaining = 0; + target = (HTC_TARGET *)pDev->pTarget; + + if((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - HTC_MAX_MSG_PER_BUNDLE_RX) > 0){ + PartialBundle = TRUE; + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("%s, partial bundle detected num: %d, %d \n", + __FUNCTION__, HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), HTC_MAX_MSG_PER_BUNDLE_RX)); + } + + bundleSpaceRemaining = HTC_MAX_MSG_PER_BUNDLE_RX * target->TargetCreditSize; + pPacketRxBundle = AllocateHTCBundleRxPacket(target); + if (!pPacketRxBundle) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: pPacketRxBundle is NULL \n", + __FUNCTION__)); + return A_NO_MEMORY; + } + pBundleBuffer = pPacketRxBundle->pBuffer; + + for(i = 0; !HTC_QUEUE_EMPTY(pRecvPktQueue) && i < HTC_MAX_MSG_PER_BUNDLE_RX; i++){ + pPacket = HTC_PACKET_DEQUEUE(pRecvPktQueue); + if (pPacket == NULL) + break; + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK) + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, pPacket->ActualLength) + + HIF_MBOX_BLOCK_SIZE; + else + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, pPacket->ActualLength); + + if((bundleSpaceRemaining - paddedLength) < 0){ + /* exceeds what we can transfer, put the packet back */ + HTC_PACKET_ENQUEUE_TO_HEAD(pRecvPktQueue, pPacket); + break; + } + bundleSpaceRemaining -= paddedLength; + + if(PartialBundle || HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) > 0){ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD; + } + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE; + + HTC_PACKET_ENQUEUE(pSyncCompletionQueue, pPacket); + + totalLength += paddedLength; + } +#if DEBUG_BUNDLE + adf_os_print("Recv bundle count %d, length %d.\n", + HTC_PACKET_QUEUE_DEPTH(pSyncCompletionQueue), totalLength); +#endif + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + if (HTC_PACKET_QUEUE_DEPTH(pSyncCompletionQueue) <= HTC_MAX_MSG_PER_BUNDLE_RX) + target->rx_bundle_stats[HTC_PACKET_QUEUE_DEPTH(pSyncCompletionQueue) - 1]++; +#endif + + +#ifdef HIF_SYNC_READ + status = HIFSyncRead(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[(int)MailBoxIndex], + pBundleBuffer, + totalLength, + HIF_RD_SYNC_BLOCK_FIX, + NULL); +#else + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[(int)MailBoxIndex], + pBundleBuffer, + totalLength, + HIF_RD_SYNC_BLOCK_FIX, + NULL); +#endif + + if(status != A_OK){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s, HIFSend Failed status:%d \n",__FUNCTION__, status)); + }else{ + unsigned char *pBuffer = pBundleBuffer; + *pNumPacketsFetched = i; + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pSyncCompletionQueue, pPacket){ + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, pPacket->ActualLength); + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK){ + paddedLength += HIF_MBOX_BLOCK_SIZE; + } + A_MEMCPY(pPacket->pBuffer, pBuffer, paddedLength); + pBuffer += paddedLength; + }HTC_PACKET_QUEUE_ITERATE_END; + } + /* free bundle space under Sync mode */ + FreeHTCBundleRxPacket(target, pPacketRxBundle); + return status; +} +A_STATUS HIFDevRecvMessagePendingHandler(HIF_SDIO_DEVICE *pDev, + A_UINT8 MailBoxIndex, + A_UINT32 MsgLookAheads[], + int NumLookAheads, + A_BOOL *pAsyncProc, + int *pNumPktsFetched) +{ + A_STATUS status = A_OK; + HTC_PACKET *pPacket; + A_BOOL asyncProc = FALSE; + A_UINT32 lookAheads[HTC_MAX_MSG_PER_BUNDLE_RX]; + int pktsFetched; + HTC_PACKET_QUEUE recvPktQueue, syncCompletedPktsQueue; + A_BOOL partialBundle; + HTC_ENDPOINT_ID id; + int totalFetched = 0; + + HTC_TARGET *target = NULL; + + AR_DEBUG_PRINTF( ATH_DEBUG_RECV, + ("+HTCRecvMessagePendingHandler NumLookAheads: %d \n", NumLookAheads)); + + if (pNumPktsFetched != NULL) { + *pNumPktsFetched = 0; + } + + if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev)) { + /* We use async mode to get the packets if the device layer supports it. + * The device layer interfaces with HIF in which HIF may have restrictions on + * how interrupts are processed */ + asyncProc = TRUE; + } + + if (pAsyncProc != NULL) { + /* indicate to caller how we decided to process this */ + *pAsyncProc = asyncProc; + } + if (NumLookAheads > HTC_MAX_MSG_PER_BUNDLE_RX) { + A_ASSERT(FALSE); + return A_EPROTO; + } + A_MEMCPY(lookAheads, MsgLookAheads, (sizeof(A_UINT32)) * NumLookAheads); + + target = (HTC_TARGET *)pDev->pTarget; + id = ((HTC_FRAME_HDR *) &lookAheads[0])->EndpointID; + +#ifdef HTC_EP_STAT_PROFILING + LOCK_HTC_RX(target); + INC_HTC_EP_STAT(&target->EndPoint[id],HIFDSRCount,1); + UNLOCK_HTC_RX(target); +#endif + + + + while (TRUE) { + + /* reset packets queues */ + INIT_HTC_PACKET_QUEUE(&recvPktQueue); + INIT_HTC_PACKET_QUEUE(&syncCompletedPktsQueue); + if (NumLookAheads > HTC_MAX_MSG_PER_BUNDLE_RX) { + status = A_EPROTO; + A_ASSERT(FALSE); + break; + } + + /* first lookahead sets the expected endpoint IDs for all packets in a bundle */ + id = ((HTC_FRAME_HDR *) &lookAheads[0])->EndpointID; + + if (id >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("MsgPend, Invalid Endpoint in look-ahead: %d \n",id)); + status = A_EPROTO; + break; + } + /* try to allocate as many HTC RX packets indicated by the lookaheads + * these packets are stored in the recvPkt queue */ + status = HIFDevAllocAndPrepareRxPackets(pDev, + lookAheads, + NumLookAheads, + &recvPktQueue); + if (A_FAILED(status)) { + break; + } + totalFetched += HTC_PACKET_QUEUE_DEPTH(&recvPktQueue); + + /* we've got packet buffers for all we can currently fetch, + * this count is not valid anymore */ + NumLookAheads = 0; + partialBundle = FALSE; + + /* now go fetch the list of HTC packets */ + while (!HTC_QUEUE_EMPTY(&recvPktQueue)) { + + pktsFetched = 0; + if ((HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) { + /* there are enough packets to attempt a bundle transfer and recv bundling is allowed */ + status = HIFDevIssueRecvPacketBundle(pDev, + &recvPktQueue, + asyncProc ? NULL : &syncCompletedPktsQueue, + MailBoxIndex, + &pktsFetched, + partialBundle); + if (A_FAILED(status)) { + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) { + /* we couldn't fetch all packets at one time, this creates a broken + * bundle */ + partialBundle = TRUE; + } + if (pktsFetched) + { + HTC_TARGET *target = NULL; + target = (HTC_TARGET *)pDev->pTarget; + +#ifdef HTC_EP_STAT_PROFILING + LOCK_HTC_RX(target); + INC_HTC_EP_STAT(&target->EndPoint[id],RxPacketsBundled,pktsFetched); + UNLOCK_HTC_RX(target); +#endif + } + + } + + /* see if the previous operation fetched any packets using bundling */ + if (0 == pktsFetched) { + /* dequeue one packet */ + pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue); + if (pPacket == NULL) + break; + pPacket->Completion = NULL; + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 0) { + /* lookaheads in all packets except the last one in the bundle must be ignored */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD; + } +#if DEBUG_BUNDLE + adf_os_print("Recv single packet, length %d.\n", pPacket->ActualLength); +#endif + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + target->rx_bundle_stats[0]++; +#endif + + /* go fetch the packet */ + status = HIFDevRecvPacket(pDev, pPacket, pPacket->ActualLength, MailBoxIndex); + if (A_FAILED(status)) { + break; + } + /* sent synchronously, queue this packet for synchronous completion */ + HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue, pPacket); + } + } + + /* synchronous handling */ + if (pDev->DSRCanYield) { + /* for the SYNC case, increment count that tracks when the DSR should yield */ + pDev->CurrentDSRRecvCount++; + } + + /* in the sync case, all packet buffers are now filled, + * we can process each packet, check lookaheads and then repeat */ + + /* unload sync completion queue */ + while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + A_UINT8 pipeid; + adf_nbuf_t netbuf; + + pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue); + if (pPacket == NULL) + break; + + NumLookAheads = 0; + status = HIFDevProcessRecvHeader(pDev, pPacket, lookAheads, + &NumLookAheads); + if (A_FAILED(status)) { + break; + } + + netbuf = (adf_nbuf_t) pPacket->pNetBufContext; + /* set data length */ + adf_nbuf_put_tail(netbuf, pPacket->ActualLength); + + if (pDev->hif_callbacks.rxCompletionHandler) { + pipeid = HIFDevMapMailBoxToPipe(pDev, MailBoxIndex, TRUE); + pDev->hif_callbacks.rxCompletionHandler(pDev->hif_callbacks.Context, + netbuf, + pipeid); + } + } + if (A_FAILED(status)) { + break; + } + + if (NumLookAheads == 0) { + /* no more look aheads */ + break; + } + /* check whether other OS contexts have queued any WMI command/data for WLAN. + * This check is needed only if WLAN Tx and Rx happens in same thread context */ + A_CHECK_DRV_TX(); + } + if (pNumPktsFetched != NULL) { + *pNumPktsFetched = totalFetched; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvMessagePendingHandler \n")); + return status; +} + +static A_STATUS HIFDevServiceCPUInterrupt(HIF_SDIO_DEVICE *pDev) +{ + A_STATUS status; + A_UINT8 cpu_int_status; + A_UINT8 regBuffer[4]; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n")); + if (pDev == NULL) + return A_ERROR; + + cpu_int_status = pDev->IrqProcRegisters.cpu_int_status + & pDev->IrqEnableRegisters.cpu_int_status_enable; + A_ASSERT(cpu_int_status); + AR_DEBUG_PRINTF( ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", cpu_int_status)); + + /* Clear the interrupt */ + pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */ + + /* set up the register transfer buffer to hit the register 4 times , this is done + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that + * restrict bus transfer lengths to be a multiple of 4-bytes */ + + /* set W1C value to clear the interrupt, this hits the register first */ + regBuffer[0] = cpu_int_status; + /* the remaining 4 values are set to zero which have no-effect */ + regBuffer[1] = 0; + regBuffer[2] = 0; + regBuffer[3] = 0; + + status = HIFReadWrite(pDev->HIFDevice, + CPU_INT_STATUS_ADDRESS, + regBuffer, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + A_ASSERT(status == A_OK); + + /* The Interrupt sent to the Host is generated via bit0 of CPU INT register*/ + if (cpu_int_status & 0x1){ + if (pDev && pDev->hif_callbacks.fwEventHandler) + /* It calls into HTC which propagates this to ol_target_failure() */ + pDev->hif_callbacks.fwEventHandler(pDev->hif_callbacks.Context, + A_ERROR); + } + else + AR_DEBUG_PRINTF( ATH_DEBUG_ERROR, + ("%s: Unable to call fwEventHandler, invalid input arguments\n",__func__)); + + return status; +} + +static A_STATUS HIFDevServiceErrorInterrupt(HIF_SDIO_DEVICE *pDev) +{ + A_STATUS status; + A_UINT8 error_int_status; + A_UINT8 regBuffer[4]; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n")); + error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F; + A_ASSERT(error_int_status); + AR_DEBUG_PRINTF( ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", error_int_status)); + + if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) { + /* Wakeup */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n")); + } + + if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) { + /* Rx Underflow */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n")); + } + + if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) { + /* Tx Overflow */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n")); + } + + /* Clear the interrupt */ + pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */ + + /* set up the register transfer buffer to hit the register 4 times , this is done + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that + * restrict bus transfer lengths to be a multiple of 4-bytes */ + + /* set W1C value to clear the interrupt, this hits the register first */ + regBuffer[0] = error_int_status; + /* the remaining 4 values are set to zero which have no-effect */ + regBuffer[1] = 0; + regBuffer[2] = 0; + regBuffer[3] = 0; + + status = HIFReadWrite(pDev->HIFDevice, + ERROR_INT_STATUS_ADDRESS, + regBuffer, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + A_ASSERT(status == A_OK); + return status; +} + +static A_STATUS HIFDevServiceDebugInterrupt(HIF_SDIO_DEVICE *pDev) +{ + A_UINT32 dummy; + A_STATUS status; + + /* Send a target failure event to the application */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); + + /* clear the interrupt , the debug error interrupt is + * counter 0 */ + /* read counter to clear interrupt */ + status = HIFReadWrite(pDev->HIFDevice, + COUNT_DEC_ADDRESS, + (A_UINT8 *) &dummy, + 4, + HIF_RD_SYNC_BYTE_INC, + NULL); + + A_ASSERT(status == A_OK); + return status; +} + +static A_STATUS HIFDevServiceCounterInterrupt(HIF_SDIO_DEVICE *pDev) +{ + A_UINT8 counter_int_status; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n")); + + counter_int_status = pDev->IrqProcRegisters.counter_int_status + & pDev->IrqEnableRegisters.counter_int_status_enable; + + AR_DEBUG_PRINTF( ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", counter_int_status)); + + /* Check if the debug interrupt is pending + * NOTE: other modules like GMBOX may use the counter interrupt for + * credit flow control on other counters, we only need to check for the debug assertion + * counter interrupt */ + if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { + return HIFDevServiceDebugInterrupt(pDev); + } + + return A_OK; +} + +/* process pending interrupts synchronously */ +static A_STATUS HIFDevProcessPendingIRQs(HIF_SDIO_DEVICE *pDev, A_BOOL *pDone, + A_BOOL *pASyncProcessing) +{ + A_STATUS status = A_OK; + A_UINT8 host_int_status = 0; + A_UINT32 lookAhead[MAILBOX_USED_COUNT]; + int i; + + A_MEMZERO(&lookAhead, sizeof(lookAhead)); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev)); + + /*** NOTE: the HIF implementation guarantees that the context of this call allows + * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that + * can block or switch thread/task ontexts. + * This is a fully schedulable context. + * */ + do { + + if (pDev->IrqEnableRegisters.int_status_enable == 0) { + /* interrupt enables have been cleared, do not try to process any pending interrupts that + * may result in more bus transactions. The target may be unresponsive at this + * point. */ + break; + } + + +#ifdef HIF_SYNC_READ + status = HIFSyncRead(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (A_UINT8 *) &pDev->IrqProcRegisters, + sizeof(pDev->IrqProcRegisters), + HIF_RD_SYNC_BYTE_INC, + NULL); +#else + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (A_UINT8 *) &pDev->IrqProcRegisters, + sizeof(pDev->IrqProcRegisters), + HIF_RD_SYNC_BYTE_INC, + NULL); +#endif + + if (A_FAILED(status)) { + break; + } + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) { + HIFDevDumpRegisters(pDev, + &pDev->IrqProcRegisters, + &pDev->IrqEnableRegisters, + &pDev->MailBoxCounterRegisters); + } + + /* Update only those registers that are enabled */ + host_int_status = pDev->IrqProcRegisters.host_int_status + & pDev->IrqEnableRegisters.int_status_enable; + + /* only look at mailbox status if the HIF layer did not provide this function, + * on some HIF interfaces reading the RX lookahead is not valid to do */ + for (i = 0; i < MAILBOX_USED_COUNT; i++) { + lookAhead[i] = 0; + if (host_int_status & (1 << i)) { + /* mask out pending mailbox value, we use "lookAhead" as the real flag for + * mailbox processing below */ + host_int_status &= ~(1 << i); + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << i)) { + /* mailbox has a message and the look ahead is valid */ + lookAhead[i] = pDev->IrqProcRegisters.rx_lookahead[MAILBOX_LOOKAHEAD_SIZE_IN_WORD*i]; + } + } + } /*end of for loop*/ + } while (FALSE); + + do { + A_BOOL bLookAheadValid = FALSE; + /* did the interrupt status fetches succeed? */ + if (A_FAILED(status)) { + break; + } + + for (i = 0; i < MAILBOX_USED_COUNT; i++) { + if (lookAhead[i] != 0) { + bLookAheadValid = TRUE; + break; + } + } + + if ((0 == host_int_status) && !bLookAheadValid) { + /* nothing to process, the caller can use this to break out of a loop */ + *pDone = TRUE; + break; + } + + if (bLookAheadValid) { + for (i = 0; i < MAILBOX_USED_COUNT; i++) { + int fetched = 0; + if (lookAhead[i] == 0) { + continue; + } + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Pending mailbox[%d] message, LookAhead: 0x%X\n", i, lookAhead[i])); + /* Mailbox Interrupt, the HTC layer may issue async requests to empty the + * mailbox... + * When emptying the recv mailbox we use the async handler above called from the + * completion routine of the callers read request. This can improve performance + * by reducing context switching when we rapidly pull packets */ + status = HIFDevRecvMessagePendingHandler(pDev, + i, + &lookAhead[i], + 1, + pASyncProcessing, + &fetched); + if (A_FAILED(status)) { + break; + } + + if (!fetched) { + /* HTC could not pull any messages out due to lack of resources */ + /* force DSR handler to ack the interrupt */ + *pASyncProcessing = FALSE; + pDev->RecheckIRQStatusCnt = 0; + } + } + } + + /* now handle the rest of them */ + AR_DEBUG_PRINTF( ATH_DEBUG_IRQ, + (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n", host_int_status)); + + if (HOST_INT_STATUS_CPU_GET(host_int_status)) { + /* CPU Interrupt */ + status = HIFDevServiceCPUInterrupt(pDev); + if (A_FAILED(status)) { + break; + } + } + + if (HOST_INT_STATUS_ERROR_GET(host_int_status)) { + /* Error Interrupt */ + status = HIFDevServiceErrorInterrupt(pDev); + if (A_FAILED(status)) { + break; + } + } + + if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) { + /* Counter Interrupt */ + status = HIFDevServiceCounterInterrupt(pDev); + if (A_FAILED(status)) { + break; + } + } + + } while (FALSE); + + /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake + * the target, if upper layers determine that we are in a low-throughput mode, we can + * rely on taking another interrupt rather than re-checking the status registers which can + * re-wake the target. + * + * NOTE : for host interfaces that use the special GetPendingEventsFunc, this optimization cannot + * be used due to possible side-effects. For example, SPI requires the host to drain all + * messages from the mailbox before exiting the ISR routine. */ + if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Bypassing IRQ Status re-check, forcing done \n")); + *pDone = TRUE; + } + + AR_DEBUG_PRINTF( ATH_DEBUG_IRQ, + ("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n", *pDone, *pASyncProcessing, status)); + + return status; +} + +#define DEV_CHECK_RECV_YIELD(pDev) \ + ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount) + +/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/ +A_STATUS HIFDevDsrHandler(void *context) +{ + HIF_SDIO_DEVICE *pDev = (HIF_SDIO_DEVICE *) context; + A_STATUS status = A_OK; + A_BOOL done = FALSE; + A_BOOL asyncProc = FALSE; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + /* reset the recv counter that tracks when we need to yield from the DSR */ + pDev->CurrentDSRRecvCount = 0; + /* reset counter used to flag a re-scan of IRQ status registers on the target */ + pDev->RecheckIRQStatusCnt = 0; + + while (!done) { + status = HIFDevProcessPendingIRQs(pDev, &done, &asyncProc); + if (A_FAILED(status)) { + break; + } + + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { + /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */ + asyncProc = FALSE; + /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers. + * this has a nice side effect of blocking us until all async read requests are completed. + * This behavior is required on some HIF implementations that do not allow ASYNC + * processing in interrupt handlers (like Windows CE) */ + + if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) { + /* ProcessPendingIRQs() pulled enough recv messages to satisfy the yield count, stop + * checking for more messages and return */ + break; + } + } + + if (asyncProc) { + /* the function performed some async I/O for performance, we + need to exit the ISR immediately, the check below will prevent the interrupt from being + Ack'd while we handle it asynchronously */ + break; + } + + } + + if (A_SUCCESS(status) && !asyncProc) { + /* Ack the interrupt only if : + * 1. we did not get any errors in processing interrupts + * 2. there are no outstanding async processing requests */ + if (pDev->DSRCanYield) { + /* if the DSR can yield do not ACK the interrupt, there could be more pending messages. + * The HIF layer must ACK the interrupt on behalf of HTC */ + AR_DEBUG_PRINTF( ATH_DEBUG_IRQ, + (" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" Acking interrupt from DevDsrHandler \n")); + HIFAckInterrupt(pDev->HIFDevice); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevDsrHandler \n")); + return status; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_send.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_send.c new file mode 100644 index 000000000000..53af5b83a5b9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/hif_sdio_send.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hif_sdio_internal.h" + +/* + * Data structure to record required sending context data + */ +struct HIFSendContext +{ + A_BOOL bNewAlloc; + HIF_SDIO_DEVICE *pDev; + adf_nbuf_t netbuf; + unsigned int transferID; + unsigned int head_data_len; +}; + +/* + * Completion routine for ALL HIF layer async I/O + */ +A_STATUS HIFDevRWCompletionHandler(void *context, A_STATUS status) +{ + struct HIFSendContext *pSendContext = (struct HIFSendContext *)context; + unsigned int transferID = pSendContext->transferID; + HIF_SDIO_DEVICE *pDev = pSendContext->pDev; + adf_nbuf_t buf = pSendContext->netbuf; + + if (pSendContext->bNewAlloc){ + adf_os_mem_free((void*)pSendContext); + } else { + adf_nbuf_pull_head(buf, pSendContext->head_data_len); + } + if (pDev->hif_callbacks.txCompletionHandler) { + pDev->hif_callbacks.txCompletionHandler(pDev->hif_callbacks.Context, + buf, + transferID); + } + return A_OK; +} + +A_STATUS HIFDevSendBuffer(HIF_SDIO_DEVICE *pDev, unsigned int transferID, a_uint8_t pipe, + unsigned int nbytes, adf_nbuf_t buf) +{ + A_STATUS status; + A_UINT32 paddedLength; + int frag_count = 0, i, head_data_len; + struct HIFSendContext *pSendContext; + unsigned char *pData; + A_UINT32 request = HIF_WR_ASYNC_BLOCK_INC; + A_UINT8 mboxIndex = HIFDevMapPipeToMailBox(pDev, pipe); + + paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, nbytes); +#ifdef ENABLE_MBOX_DUMMY_SPACE_FEATURE + A_ASSERT(paddedLength - nbytes < HIF_DUMMY_SPACE_MASK + 1); + /* + * two most significant bytes to save dummy data count + * data written into the dummy space will not put into the final mbox FIFO + * + */ + request |= ((paddedLength - nbytes) << 16); +#endif + + frag_count = adf_nbuf_get_num_frags(buf); + + if (frag_count > 1){ + /* header data length should be total sending length substract internal data length of netbuf */ + /* + * | HIFSendContext | fragments except internal buffer | netbuf->data + */ + head_data_len = sizeof(struct HIFSendContext) + + (nbytes - adf_nbuf_get_frag_len(buf, frag_count - 1)); + } else { + /* + * | HIFSendContext | netbuf->data + */ + head_data_len = sizeof(struct HIFSendContext); + } + + /* Check whether head room is enough to save extra head data */ + if ((head_data_len <= adf_nbuf_headroom(buf)) && + (adf_nbuf_tailroom(buf) >= (paddedLength - nbytes))){ + pSendContext = (struct HIFSendContext*)adf_nbuf_push_head(buf, head_data_len); + pSendContext->bNewAlloc = FALSE; + } else { + pSendContext = (struct HIFSendContext*)adf_os_mem_alloc(NULL, + sizeof(struct HIFSendContext) + paddedLength); + if (pSendContext == NULL) + return A_ERROR; + pSendContext->bNewAlloc = TRUE; + } + + pSendContext->netbuf = buf; + pSendContext->pDev = pDev; + pSendContext->transferID = transferID; + pSendContext->head_data_len = head_data_len; + /* + * Copy data to head part of netbuf or head of allocated buffer. + * if buffer is new allocated, the last buffer should be copied also. + * It assume last fragment is internal buffer of netbuf + * sometime total length of fragments larger than nbytes + */ + pData = (unsigned char *)pSendContext + sizeof(struct HIFSendContext); + for (i = 0; i < (pSendContext->bNewAlloc ? frag_count : frag_count - 1); i ++){ + int frag_len = adf_nbuf_get_frag_len(buf, i); + unsigned char *frag_addr = adf_nbuf_get_frag_vaddr(buf, i); + if (frag_len > nbytes){ + frag_len = nbytes; + } + memcpy(pData, frag_addr, frag_len); + pData += frag_len; + nbytes -= frag_len; + if (nbytes <= 0) { + break; + } + } + + /* Reset pData pointer and send out */ + pData = (unsigned char *)pSendContext + sizeof(struct HIFSendContext); + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxProp[mboxIndex].ExtendedAddress, + (char*) pData, + paddedLength, + request, + (void*)pSendContext); + + if (status == A_PENDING){ + /* + * it will return A_PENDING in native HIF implementation, + * which should be treated as successful result here. + */ + status = A_OK; + } + /* release buffer or move back data pointer when failed */ + if (status != A_OK){ + if (pSendContext->bNewAlloc){ + adf_os_mem_free(pSendContext); + } else { + adf_nbuf_pull_head(buf, head_data_len); + } + } + + return status; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c new file mode 100644 index 000000000000..b799c8368a86 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bmi_msg.h" /* TARGET_TYPE_ */ +#include "if_ath_sdio.h" +#include "vos_api.h" +#include "vos_sched.h" +#include "regtable.h" + +#ifndef REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "pktlog_ac_api.h" +#include "pktlog_ac.h" +#endif +#include "ol_fw.h" +#include "epping_main.h" + +#ifndef ATH_BUS_PM +#ifdef CONFIG_PM +#define ATH_BUS_PM +#endif /* CONFIG_PM */ +#endif /* ATH_BUS_PM */ + +#ifndef REMOVE_PKT_LOG +struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs = NULL; +#endif + +typedef void * hif_handle_t; +typedef void * hif_softc_t; + +extern int hdd_wlan_startup(struct device *dev, void *hif_sc); +extern void __hdd_wlan_exit(void); + +struct ath_hif_sdio_softc *sc = NULL; + +static A_STATUS +ath_hif_sdio_probe(void *context, void *hif_handle) +{ + int ret = 0; + struct ol_softc *ol_sc; + HIF_DEVICE_OS_DEVICE_INFO os_dev_info; + struct sdio_func *func = NULL; + const struct sdio_device_id *id; + u_int32_t target_type; + ENTER(); + + sc = (struct ath_hif_sdio_softc *) A_MALLOC(sizeof(*sc)); + if (!sc) { + ret = -ENOMEM; + goto err_alloc; + } + A_MEMZERO(sc,sizeof(*sc)); + + + sc->hif_handle = hif_handle; + HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE, &os_dev_info, sizeof(os_dev_info)); + + sc->aps_osdev.device = os_dev_info.pOSDevice; + sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_SDIO; + spin_lock_init(&sc->target_lock); + + { + /* + * Attach Target register table. This is needed early on -- + * even before BMI -- since PCI and HIF initialization (and BMI init) + * directly access Target registers (e.g. CE registers). + * + * TBDXXX: targetdef should not be global -- should be stored + * in per-device struct so that we can support multiple + * different Target types with a single Host driver. + * The whole notion of an "hif type" -- (not as in the hif + * module, but generic "Host Interface Type") is bizarre. + * At first, one one expect it to be things like SDIO, USB, PCI. + * But instead, it's an actual platform type. Inexplicably, the + * values used for HIF platform types are *different* from the + * values used for Target Types. + */ + +#if defined(CONFIG_AR9888_SUPPORT) + hif_register_tbl_attach(HIF_TYPE_AR9888); + target_register_tbl_attach(TARGET_TYPE_AR9888); + target_type = TARGET_TYPE_AR9888; +#elif defined(CONFIG_AR6320_SUPPORT) + id = ((HIF_DEVICE*)hif_handle)->id; + if ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == MANUFACTURER_ID_QCA9377_BASE) { + hif_register_tbl_attach(HIF_TYPE_AR6320V2); + target_register_tbl_attach(TARGET_TYPE_AR6320V2); + } else if ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == MANUFACTURER_ID_AR6320_BASE) { + int ar6kid = id->device & MANUFACTURER_ID_AR6K_REV_MASK; + if (ar6kid >= 1) { + /* v2 or higher silicon */ + hif_register_tbl_attach(HIF_TYPE_AR6320V2); + target_register_tbl_attach(TARGET_TYPE_AR6320V2); + } else { + /* legacy v1 silicon */ + hif_register_tbl_attach(HIF_TYPE_AR6320); + target_register_tbl_attach(TARGET_TYPE_AR6320); + } + } + target_type = TARGET_TYPE_AR6320; + +#endif + } + func = ((HIF_DEVICE*)hif_handle)->func; + + ol_sc = A_MALLOC(sizeof(*ol_sc)); + if (!ol_sc){ + ret = -ENOMEM; + goto err_attach; + } + OS_MEMZERO(ol_sc, sizeof(*ol_sc)); + ol_sc->sc_osdev = &sc->aps_osdev; + ol_sc->hif_sc = (void *)sc; + sc->ol_sc = ol_sc; + ol_sc->target_type = target_type; + ol_sc->enableuartprint = 1; + ol_sc->enablefwlog = 0; + ol_sc->enablesinglebinary = FALSE; + ol_sc->max_no_of_peers = 1; + + ol_sc->hif_hdl = hif_handle; + +#ifndef TARGET_DUMP_FOR_NON_QC_PLATFORM + ol_sc->ramdump_base = ioremap(RAMDUMP_ADDR, RAMDUMP_SIZE); + ol_sc->ramdump_size = RAMDUMP_SIZE; + if (ol_sc->ramdump_base == NULL) { + ol_sc->ramdump_base = 0; + ol_sc->ramdump_size = 0; + } +#endif + init_waitqueue_head(&ol_sc->sc_osdev->event_queue); + + if (athdiag_procfs_init(sc) != 0) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "%s athdiag_procfs_init failed",__func__); + ret = A_ERROR; + goto err_attach1; + } + ret = hif_init_adf_ctx(ol_sc); + if (ret == 0) + ret = hdd_wlan_startup(&(func->dev), ol_sc); + if ( ret ) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_FATAL," hdd_wlan_startup failed"); + goto err_attach2; + }else{ + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO," hdd_wlan_startup success!"); + } + + return 0; + +err_attach2: + athdiag_procfs_remove(); + hif_deinit_adf_ctx(ol_sc); +err_attach1: + A_FREE(ol_sc); +err_attach: + A_FREE(sc); + sc = NULL; +err_alloc: + return ret; +} + +int +ol_ath_sdio_configure(hif_softc_t hif_sc, struct net_device *dev, hif_handle_t *hif_hdl) +{ + struct ath_hif_sdio_softc *sc = (struct ath_hif_sdio_softc *) hif_sc; + int ret = 0; + + sc->aps_osdev.netdev = dev; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(dev); +#endif + + *hif_hdl = sc->hif_handle; + + return ret; +} + +static A_STATUS +ath_hif_sdio_remove(void *context, void *hif_handle) +{ + ENTER(); + + if (!sc) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "Global SDIO context is NULL"); + return A_ERROR; + } + + athdiag_procfs_remove(); + +#ifndef TARGET_DUMP_FOR_NON_QC_PLATFORM + if (sc && sc->ol_sc && sc->ol_sc->ramdump_base){ + iounmap(sc->ol_sc->ramdump_base); + } +#endif + +#ifndef REMOVE_PKT_LOG + if (vos_get_conparam() != VOS_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(vos_get_conparam())){ + if (sc && sc->ol_sc) + pktlogmod_exit(sc->ol_sc); + } +#endif + + //cleaning up the upper layers + __hdd_wlan_exit(); + + if (sc && sc->ol_sc){ + hif_deinit_adf_ctx(sc->ol_sc); + A_FREE(sc->ol_sc); + sc->ol_sc = NULL; + } + if (sc) { + A_FREE(sc); + sc = NULL; + } + + EXIT(); + return 0; +} + +static A_STATUS +ath_hif_sdio_suspend(void *context) +{ + printk(KERN_INFO "ol_ath_sdio_suspend TODO\n"); + return 0; +} + +static A_STATUS +ath_hif_sdio_resume(void *context) +{ + printk(KERN_INFO "ol_ath_sdio_resume ODO\n"); + return 0; +} + +static A_STATUS +ath_hif_sdio_power_change(void *context, A_UINT32 config) +{ + printk(KERN_INFO "ol_ath_sdio_power change TODO\n"); + return 0; +} + +/* + * Module glue. + */ +#include +static char *version = "HIF (Atheros/multi-bss)"; +static char *dev_info = "ath_hif_sdio"; + +static int init_ath_hif_sdio(void) +{ + A_STATUS status; + OSDRV_CALLBACKS osdrvCallbacks; + ENTER(); + + A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks)); + osdrvCallbacks.deviceInsertedHandler = ath_hif_sdio_probe; + osdrvCallbacks.deviceRemovedHandler = ath_hif_sdio_remove; +#ifdef CONFIG_PM + osdrvCallbacks.deviceSuspendHandler = ath_hif_sdio_suspend; + osdrvCallbacks.deviceResumeHandler = ath_hif_sdio_resume; + osdrvCallbacks.devicePowerChangeHandler = ath_hif_sdio_power_change; +#endif + + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_INFO,"%s %d",__func__,__LINE__); + status = HIFInit(&osdrvCallbacks); + if(status != A_OK){ + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_FATAL, "%s HIFInit failed!",__func__); + return -ENODEV; + } + + printk(KERN_INFO "%s: %s\n", dev_info, version); + + return 0; +} + +int hif_register_driver(void) +{ + int status = 0; + ENTER(); + status = init_ath_hif_sdio(); + EXIT("status = %d", status); + return status; + +} + +void hif_unregister_driver(void) +{ + ENTER(); + HIFShutDownDevice(NULL); + EXIT(); + return ; +} + +int hif_init_adf_ctx(void *ol_sc) +{ + adf_os_device_t adf_ctx; + v_CONTEXT_t pVosContext = NULL; + struct ol_softc *ol_sc_local = (struct ol_softc *)ol_sc; + struct ath_hif_sdio_softc *hif_sc = ol_sc_local->hif_sc; + ENTER(); + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if(pVosContext == NULL) + return -EFAULT; + adf_ctx = vos_mem_malloc(sizeof(*adf_ctx)); + if (!adf_ctx) + return -ENOMEM; + vos_mem_zero(adf_ctx, sizeof(*adf_ctx)); + adf_ctx->drv = &hif_sc->aps_osdev; + adf_ctx->dev = hif_sc->aps_osdev.device; + ol_sc_local->adf_dev = adf_ctx; + ((VosContextType*)(pVosContext))->adf_ctx = adf_ctx; + EXIT(); + return 0; +} + +void hif_deinit_adf_ctx(void *ol_sc) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + + if (sc == NULL) + return; + if (sc->adf_dev) { + v_CONTEXT_t pVosContext = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + vos_mem_free(sc->adf_dev); + sc->adf_dev = NULL; + if (pVosContext) + ((VosContextType*)(pVosContext))->adf_ctx = NULL; + } +} + +/* Function to set the TXRX handle in the ol_sc context */ +void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + ENTER(); + sc->pdev_txrx_handle = txrx_handle; +} + +void hif_disable_isr(void *ol_sc) +{ + ENTER("- dummy function!"); +} + +void +HIFSetTargetSleep(HIF_DEVICE *hif_device, A_BOOL sleep_ok, A_BOOL wait_for_it) +{ + ENTER("- dummy function!"); +} + +void +HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device) +{ + ENTER("- dummy function!"); + +} + +/* Function to reset SoC */ +void hif_reset_soc(void *ol_sc) +{ + ENTER("- dummy function!"); +} + +void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision) +{ + struct ol_softc *ol_sc_local = (struct ol_softc *)ol_sc; + A_UINT32 chip_id = 0; + A_STATUS rv; + rv = HIFDiagReadAccess(ol_sc_local->hif_hdl, + (CHIP_ID_ADDRESS | RTC_SOC_BASE_ADDRESS), &chip_id); + if (rv != A_OK) { + pr_warn("%s[%d]: get chip id fail\n", __func__, __LINE__); + ol_sc_local->target_revision = -1; + } else { + ol_sc_local->target_revision = + CHIP_ID_REVISION_GET(chip_id); + } + *version = ol_sc_local->target_version; + *revision = ol_sc_local->target_revision; +} + +void hif_set_fw_info(void *ol_sc, u32 target_fw_version) +{ + ((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h new file mode 100644 index 000000000000..cbd58ae1f969 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __IF_ATH_SDIO_H__ +#define __IF_ATH_SDIO_H__ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +#include +#else +#include +#endif +#include +#include +#include +#include +#include "a_osapi.h" +#include "hif_internal.h" +#include "hif_trace.h" + +#define AR6320_HEADERS_DEF + +#define ATH_DBG_DEFAULT 0 + +#ifdef TARGET_DUMP_FOR_9X15_PLATFORM +#define RAMDUMP_ADDR 0x46E00000 +#define RAMDUMP_SIZE 0x100000 +#else +#define RAMDUMP_ADDR 0x8F000000 +#define RAMDUMP_SIZE 0x700000 +#endif + +struct ath_hif_sdio_softc { + struct device *dev; + struct _NIC_DEV aps_osdev; + struct ol_softc *ol_sc; + struct tasklet_struct intr_tq; /* tasklet */ + + int irq; + /* + * Guard changes to Target HW state and to software + * structures that track hardware state. + */ + spinlock_t target_lock; + void *hif_handle; + struct targetdef_s *targetdef; + struct hostdef_s *hostdef; +}; + +#if defined(CONFIG_ATH_PROCFS_DIAG_SUPPORT) +int athdiag_procfs_init(void *scn); +void athdiag_procfs_remove(void); +#else +static inline int athdiag_procfs_init(void *scn) { return 0; } +static inline void athdiag_procfs_remove(void) { return; } +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define DMA_MAPPING_ERROR(dev, addr) dma_mapping_error((addr)) +#else +#define DMA_MAPPING_ERROR(dev, addr) dma_mapping_error((dev), (addr)) +#endif + +int ath_sdio_probe(void *context, void *hif_handle); +void ath_sdio_remove(void *context, void *hif_handle); +int ath_sdio_suspend(void *context); +int ath_sdio_resume(void *context); + +/*These functions are exposed to HDD*/ +int hif_register_driver(void); +void hif_unregister_driver(void); +int hif_init_adf_ctx(void *ol_sc); +void hif_deinit_adf_ctx(void *ol_sc); +void hif_disable_isr(void *ol_sc); +void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle); +void hif_reset_soc(void *ol_sc); + + +void hif_register_tbl_attach(u32 hif_type); +void target_register_tbl_attach(u32 target_type); + +void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision); +void hif_set_fw_info(void *ol_sc, u32 target_fw_version); + +#endif /* __IF_ATH_SDIO_H__*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h new file mode 100644 index 000000000000..382e38c1b92e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _HIF_INTERNAL_H_ +#define _HIF_INTERNAL_H_ + +#include "athdefs.h" +#include "a_types.h" +#include "a_osapi.h" +#include "adf_os_timer.h" +#include "adf_os_atomic.h" +#include "hif.h" +#include "hif_sdio_common.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#include +#define HIF_LINUX_MMC_SCATTER_SUPPORT +#endif + +#define BUS_REQUEST_MAX_NUM 64 + +#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000 +#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20 +#define FLAGS_CARD_ENAB 0x02 +#define FLAGS_CARD_IRQ_UNMSK 0x04 + +#define HIF_MBOX_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE +#define HIF_MBOX0_BLOCK_SIZE 1 +#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE +#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE +#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE + +struct _HIF_SCATTER_REQ_PRIV; + +typedef struct bus_request { + struct bus_request *next; /* link list of available requests */ + struct bus_request *inusenext; /* link list of in use requests */ + struct semaphore sem_req; + A_UINT32 address; /* request data */ + A_UCHAR *buffer; + A_UINT32 length; + A_UINT32 request; + void *context; + A_STATUS status; + struct _HIF_SCATTER_REQ_PRIV *pScatterReq; /* this request is a scatter request */ +} BUS_REQUEST; + +#ifdef HIF_MBOX_SLEEP_WAR +typedef enum { + HIF_MBOX_UNKNOWN_STATE, + HIF_MBOX_REQUEST_TO_SLEEP_STATE, + HIF_MBOX_SLEEP_STATE, + HIF_MBOX_AWAKE_STATE +} HIF_MBOX_STATE; +#endif + +struct hif_device { + struct sdio_func *func; + spinlock_t asynclock; + struct task_struct* async_task; /* task to handle async commands */ + struct semaphore sem_async; /* wake up for async task */ + int async_shutdown; /* stop the async task */ + struct completion async_completion; /* thread completion */ + BUS_REQUEST *asyncreq; /* request for async tasklet */ + BUS_REQUEST *taskreq; /* async tasklet data */ + spinlock_t lock; + BUS_REQUEST *s_busRequestFreeQueue; /* free list */ + BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */ + void *claimedContext; + HTC_CALLBACKS htcCallbacks; + A_UINT8 *dma_buffer; + DL_LIST ScatterReqHead; /* scatter request list head */ + A_BOOL scatter_enabled; /* scatter enabled flag */ + A_BOOL is_suspend; + A_BOOL is_disabled; + atomic_t irqHandling; + HIF_DEVICE_POWER_CHANGE_TYPE powerConfig; + HIF_DEVICE_STATE DeviceState; +#ifdef HIF_MBOX_SLEEP_WAR + adf_os_atomic_t mbox_state; + adf_os_timer_t sleep_timer; + unsigned long sleep_ticks; + A_UINT32 init_sleep; +#endif + const struct sdio_device_id *id; + struct mmc_host *host; + void *htcContext; + /* mailbox swapping for control and data svc*/ + A_BOOL swap_mailbox; +}; + +#define HIF_DMA_BUFFER_SIZE (4 * 1024) +#define CMD53_FIXED_ADDRESS 1 +#define CMD53_INCR_ADDRESS 2 + +BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device); +void hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest); +void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest); +void HIFDumpCCCR(HIF_DEVICE *hif_device); + +#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT + +#define MAX_SCATTER_REQUESTS 4 +#define MAX_SCATTER_ENTRIES_PER_REQ 16 +#define MAX_SCATTER_REQ_TRANSFER_SIZE 32*1024 + +typedef struct _HIF_SCATTER_REQ_PRIV { + HIF_SCATTER_REQ *pHifScatterReq; /* HIF scatter request with allocated entries */ + HIF_DEVICE *device; /* this device */ + BUS_REQUEST *busrequest; /* request associated with request */ + /* scatter list for linux */ + struct scatterlist sgentries[MAX_SCATTER_ENTRIES_PER_REQ]; +} HIF_SCATTER_REQ_PRIV; + +#define ATH_DEBUG_SCATTER ATH_DEBUG_MAKE_MODULE_MASK(0) + +A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo); +void CleanupHIFScatterResources(HIF_DEVICE *device); +A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest); + +#else // HIF_LINUX_MMC_SCATTER_SUPPORT + +static inline A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo) +{ + return A_ENOTSUP; +} + +static inline A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest) +{ + return A_ENOTSUP; +} + +#define CleanupHIFScatterResources(d) { } + +#endif // HIF_LINUX_MMC_SCATTER_SUPPORT + +#endif // _HIF_INTERNAL_H_ + diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c new file mode 100644 index 000000000000..2fce4023c268 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c @@ -0,0 +1,2345 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "if_ath_sdio.h" +#include "regtable.h" +#include "vos_api.h" +#include "wma_api.h" +#include "hif_internal.h" +#include "adf_os_time.h" +/* by default setup a bounce buffer for the data packets, if the underlying host controller driver + does not use DMA you may be able to skip this step and save the memory allocation and transfer time */ +#define HIF_USE_DMA_BOUNCE_BUFFER 1 +#define ATH_MODULE_NAME hif +#include "a_debug.h" + +#if HIF_USE_DMA_BOUNCE_BUFFER +/* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host controllers assume the + * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack). + * virt_addr_valid check fails on stack memory. + */ +#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer))) +#else +#define BUFFER_NEEDS_BOUNCE(buffer) (FALSE) +#endif + +#define MAX_HIF_DEVICES 2 + +#ifdef HIF_MBOX_SLEEP_WAR +#define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 +#define HIF_SLEEP_DISABLE_UPDATE_DELAY 1 +#define HIF_IS_WRITE_REQUEST_MBOX1_TO_3(request) \ + ((request->request & HIF_WRITE)&& \ + (request->address >= 0x1000 && request->address < 0x1FFFF)) +#endif +unsigned int mmcbuswidth = 0; +module_param(mmcbuswidth, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mmcbuswidth, "Set MMC driver Bus Width: 1-1Bit, 4-4Bit, 8-8Bit"); +EXPORT_SYMBOL(mmcbuswidth); + +unsigned int mmcclock = 0; +module_param(mmcclock, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mmcclock, "Set MMC driver Clock value"); +EXPORT_SYMBOL(mmcclock); + +unsigned int brokenirq = 0; +module_param(brokenirq, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(brokenirq, "Set as 1 to use polling method instead of interrupt mode"); + +unsigned int forcesleepmode = 0; +module_param(forcesleepmode, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(forcesleepmode, "Set sleep mode: 0-host capbility, 1-force WOW, 2-force DeepSleep, 3-force CutPower"); + +/* Some laptop with JMicron SDIO host has compitable + * issue with asyncintdelay value, + * change default value to 2 */ +unsigned int asyncintdelay = 2; +module_param(asyncintdelay, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(asyncintdelay, "Delay clock count for aysnc interrupt, 2 is default, vaild values are 1 and 2"); + +unsigned int forcecard = 0; +module_param(forcecard, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(forcecard, "Ignore card capabilities information to switch bus mode"); + +unsigned int debugcccr = 1; +module_param(debugcccr, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(debugcccr, "Output this cccr values"); + +unsigned int writecccr1 = 0; +module_param(writecccr1, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +unsigned int writecccr1value = 0; +module_param(writecccr1value, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +unsigned int writecccr2 = 0; +module_param(writecccr2, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +unsigned int writecccr2value = 0; +module_param(writecccr2value, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +unsigned int writecccr3 = 0; +module_param(writecccr3, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +unsigned int writecccr3value = 0; +module_param(writecccr3value, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +unsigned int writecccr4 = 0; +module_param(writecccr4, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +unsigned int writecccr4value = 0; +module_param(writecccr4value, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +unsigned int modstrength = 0; +module_param(modstrength, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(modstrength, "Adjust internal driver strength"); + +/* ATHENV */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) +#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) +static int hifDeviceSuspend(struct device *dev); +static int hifDeviceResume(struct device *dev); +#endif /* CONFIG_PM */ +static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id); +static void hifDeviceRemoved(struct sdio_func *func); +static HIF_DEVICE *addHifDevice(struct sdio_func *func); +static HIF_DEVICE *getHifDevice(struct sdio_func *func); +static void delHifDevice(HIF_DEVICE * device); +static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte); +static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte); + + +int reset_sdio_on_unload = 0; +module_param(reset_sdio_on_unload, int, 0644); + +A_UINT32 nohifscattersupport = 1; + +A_UINT32 forcedriverstrength = 1; /* force driver strength to type D */ + +/* ------ Static Variables ------ */ +static const struct sdio_device_id ar6k_id_table[] = { +#ifdef AR6002_HEADERS_DEF + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) }, +#endif +#ifdef AR6003_HEADERS_DEF + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) }, +#endif +#ifdef AR6004_HEADERS_DEF + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x1)) }, +#endif +#ifdef AR6320_HEADERS_DEF + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x1)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x2)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x3)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x4)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x5)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x6)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x7)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x8)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x9)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xA)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xB)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xC)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xD)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xE)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xF)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x1)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x2)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x3)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x4)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x5)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x6)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x7)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x8)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x9)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xA)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xB)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xC)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF)) }, + /* TODO: just for compatible with old image which ManufacturerID is 0, should delete later */ + { SDIO_DEVICE(MANUFACTURER_CODE, (0 | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (0 | 0x1)) }, +#endif + { /* null */ }, +}; +MODULE_DEVICE_TABLE(sdio, ar6k_id_table); + +static struct sdio_driver ar6k_driver = { + .name = "ar6k_wlan", + .id_table = ar6k_id_table, + .probe = hifDeviceInserted, + .remove = hifDeviceRemoved, +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) +/* New suspend/resume based on linux-2.6.32 + * Need to patch linux-2.6.32 with mmc2.6.32_suspend.patch + * Need to patch with msmsdcc2.6.29_suspend.patch for msm_sdcc host + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +static struct dev_pm_ops ar6k_device_pm_ops = { +#else +static struct pm_ops ar6k_device_pm_ops = { +#endif + .suspend = hifDeviceSuspend, + .resume = hifDeviceResume, +}; +#endif /* CONFIG_PM */ + +/* make sure we only unregister when registered. */ +static int registered = 0; + +OSDRV_CALLBACKS osdrvCallbacks; +extern A_UINT32 onebitmode; +extern A_UINT32 busspeedlow; +extern A_UINT32 debughif; + +static HIF_DEVICE *hif_devices[MAX_HIF_DEVICES]; + +static void ResetAllCards(void); +static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func); +static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func); + +#ifdef DEBUG + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, + "hif", + "(Linux MMC) Host Interconnect Framework", + ATH_DEBUG_MASK_DEFAULTS, + 0, + NULL); + +#endif + + +/* ------ Functions ------ */ +A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) +{ + int status; + + if (callbacks == NULL) + return A_ERROR; + + A_REGISTER_MODULE_DEBUG_INFO(hif); + + ENTER(); + /* store the callback handlers */ + osdrvCallbacks = *callbacks; + + /* Register with bus driver core */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n")); + registered = 1; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) + if (callbacks->deviceSuspendHandler && callbacks->deviceResumeHandler) { + ar6k_driver.drv.pm = &ar6k_device_pm_ops; + } +#endif /* CONFIG_PM */ + status = sdio_register_driver(&ar6k_driver); + AR_DEBUG_ASSERT(status==0); + + if (status != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("%s sdio_register_driver failed!",__func__)); + return A_ERROR; + } + else + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,("%s sdio_register_driver successful",__func__)); + + return A_OK; +} + +static A_STATUS +__HIFReadWrite(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + A_UINT32 request, + void *context) +{ + A_UINT8 opcode; + A_STATUS status = A_OK; + int ret; + A_UINT8 *tbuffer; + A_BOOL bounced = FALSE; + + if (device == NULL || device->func == NULL) + return A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("__HIFReadWrite, addr:0X%06X, len:%08d, %s, %s\n", + address, + length, + request & HIF_READ ? "Read " : "Write", + request & HIF_ASYNCHRONOUS ? "Async" : "Sync ")); + + do { + if (request & HIF_EXTENDED_IO) { + //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid command type: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (request & HIF_BLOCK_BASIS) { + /* round to whole block length size */ + length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Block mode (BlockLen: %d)\n", + length)); + } else if (request & HIF_BYTE_BASIS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Byte mode (BlockLen: %d)\n", + length)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid data mode: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + +#if 0 + /* useful for checking register accesses */ + if (length & 0x3) { + A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n", + request & HIF_WRITE ? "write":"read", address, length); + } +#endif + + if (request & HIF_WRITE) { + HIF_DEVICE_MBOX_INFO MailBoxInfo; + unsigned int mboxLength = 0; + HIFConfigureDevice(device, + HIF_DEVICE_GET_MBOX_ADDR, + &MailBoxInfo, + sizeof(MailBoxInfo)); + if (address >= 0x800 && address < 0xC00) { + /* Host control register and CIS Window */ + mboxLength = 0; + } else if (address == MailBoxInfo.MboxAddresses[0] + || address == MailBoxInfo.MboxAddresses[1] + || address == MailBoxInfo.MboxAddresses[2] + || address == MailBoxInfo.MboxAddresses[3]) { + mboxLength = HIF_MBOX_WIDTH; + } else if (address == MailBoxInfo.MboxProp[0].ExtendedAddress) { + mboxLength = MailBoxInfo.MboxProp[0].ExtendedSize; + } else if (address == MailBoxInfo.MboxProp[1].ExtendedAddress) { + mboxLength = MailBoxInfo.MboxProp[1].ExtendedSize; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid written address: 0x%08x\n", address)); + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("address:%08X, Length:0x%08X, Dummy:0x%04X, Final:0x%08X\n", address, length, (request & HIF_DUMMY_SPACE_MASK) >> 16, mboxLength == 0 ? address : address + (mboxLength - length))); + if (mboxLength != 0) { + if (length > mboxLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIFReadWrite: written length(0x%08X) " + "larger than mbox length(0x%08x)\n", length, mboxLength)); + break; + } + address += (mboxLength - length); +#ifdef ENABLE_MBOX_DUMMY_SPACE_FEATURE + /* + * plus dummy byte count + */ + address += ((request & HIF_DUMMY_SPACE_MASK) >> 16); +#endif + } + } + + if (request & HIF_FIXED_ADDRESS) { + opcode = CMD53_FIXED_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address)); + } else if (request & HIF_INCREMENTAL_ADDRESS) { + opcode = CMD53_INCR_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid address mode: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (request & HIF_WRITE) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer) && device->dma_buffer != NULL) { + tbuffer = device->dma_buffer; + /* copy the write data to the dma buffer */ + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + if (length > HIF_DMA_BUFFER_SIZE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid write length: %d\n", length)); + status = A_EINVAL; + break; + } + memcpy(tbuffer, buffer, length); + bounced = TRUE; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS && tbuffer != NULL) { + ret = sdio_writesb(device->func, address, tbuffer, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } else { + ret = sdio_memcpy_toio(device->func, address, tbuffer, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } + } else if (request & HIF_READ) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer) && device->dma_buffer != NULL) { + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + if (length > HIF_DMA_BUFFER_SIZE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid read length: %d\n", length)); + status = A_EINVAL; + break; + } + tbuffer = device->dma_buffer; + bounced = TRUE; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS && tbuffer != NULL) { + ret = sdio_readsb(device->func, tbuffer, address, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } else { + ret = sdio_memcpy_fromio(device->func, tbuffer, address, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } +#if HIF_USE_DMA_BOUNCE_BUFFER + if (bounced) { + /* copy the read data from the dma buffer */ + memcpy(buffer, tbuffer, length); + } +#endif + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid direction: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret)); + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("__HIFReadWrite, addr:0X%06X, len:%08d, %s, %s\n", + address, + length, + request & HIF_READ ? "Read " : "Write", + request & HIF_ASYNCHRONOUS ? "Async" : "Sync ")); + status = A_ERROR; + } + } while (FALSE); + + return status; +} + +void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest) +{ + unsigned long flags; + BUS_REQUEST *async; + BUS_REQUEST *active; + + spin_lock_irqsave(&device->asynclock, flags); + active = device->asyncreq; + if (active == NULL) { + device->asyncreq = busrequest; + device->asyncreq->inusenext = NULL; + } else { + for (async = device->asyncreq; + async != NULL; + async = async->inusenext) { + active = async; + } + active->inusenext = busrequest; + busrequest->inusenext = NULL; + } + spin_unlock_irqrestore(&device->asynclock, flags); +} + +A_STATUS +HIFSyncRead(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + A_UINT32 request, + void *context) +{ + A_STATUS status; + + if (device == NULL || device->func == NULL) + return A_ERROR; + + sdio_claim_host(device->func); + status = __HIFReadWrite(device, address, buffer, length, request & ~HIF_SYNCHRONOUS, NULL); + sdio_release_host(device->func); + return status; +} + +/* queue a read/write request */ +A_STATUS +HIFReadWrite(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + A_UINT32 request, + void *context) +{ + A_STATUS status = A_OK; + BUS_REQUEST *busrequest; + + + if (device == NULL || device->func == NULL) + return A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: device 0x%p addr 0x%X buffer 0x%p len %d req 0x%X context 0x%p", + device, address, buffer, length, request, context)); + + /*sdio r/w action is not needed when suspend with cut power,so just return*/ + if((device->is_suspend == TRUE)&&(device->powerConfig == HIF_DEVICE_POWER_CUT)){ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("skip io when suspending\n")); + return A_OK; + } + do { + if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){ + /* serialize all requests through the async thread */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n", + (request & HIF_ASYNCHRONOUS)?"Async":"Synch")); + busrequest = hifAllocateBusRequest(device); + if (busrequest == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n", + request & HIF_READ ? "READ":"WRITE", address, length)); + return A_ERROR; + } + busrequest->address = address; + busrequest->buffer = buffer; + busrequest->length = length; + busrequest->request = request; + busrequest->context = context; + + AddToAsyncList(device, busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%lX\n", (unsigned long)busrequest)); + + /* wait for completion */ + up(&device->sem_async); + if (down_interruptible(&busrequest->sem_req) != 0) { + /* interrupted, exit */ + return A_ERROR; + } else { + A_STATUS status = busrequest->status; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n", + (unsigned long)busrequest, busrequest->status)); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request)); + hifFreeBusRequest(device, busrequest); + return status; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%lX\n", (unsigned long)busrequest)); + up(&device->sem_async); + return A_PENDING; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request)); + status = A_EINVAL; + break; + } + } while(0); + + return status; +} +/* thread to serialize all requests, both sync and async */ +static int async_task(void *param) + { + HIF_DEVICE *device; + BUS_REQUEST *request; + A_STATUS status; + unsigned long flags; + + device = (HIF_DEVICE *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n")); + set_current_state(TASK_INTERRUPTIBLE); + while(!device->async_shutdown) { + /* wait for work */ + if (down_interruptible(&device->sem_async) != 0) { + /* interrupted, exit */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n")); + break; + } + if (device->async_shutdown) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n")); + break; + } +#ifdef HIF_MBOX_SLEEP_WAR + /* No write request, and device state is sleep enter into sleep mode */ + if ((device->asyncreq == NULL) && + (adf_os_atomic_read(&device->mbox_state) == HIF_MBOX_REQUEST_TO_SLEEP_STATE)) { + HIFSetMboxSleep(device, true, true, false); + continue; + } +#endif + /* we want to hold the host over multiple cmds if possible, but holding the host blocks card interrupts */ + sdio_claim_host(device->func); + spin_lock_irqsave(&device->asynclock, flags); + /* pull the request to work on */ + while (device->asyncreq != NULL) { + request = device->asyncreq; + if (request->inusenext != NULL) { + device->asyncreq = request->inusenext; + } else { + device->asyncreq = NULL; + } + spin_unlock_irqrestore(&device->asynclock, flags); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req: 0x%lX\n", (unsigned long)request)); +#ifdef HIF_MBOX_SLEEP_WAR + /* write request pending for mailbox(1-3), + * and the mbox state is sleep then awake the device */ + if (HIF_IS_WRITE_REQUEST_MBOX1_TO_3(request)) { + if (adf_os_atomic_read(&device->mbox_state) == HIF_MBOX_SLEEP_STATE) { + HIFSetMboxSleep(device, false, true, false); + adf_os_timer_cancel(&device->sleep_timer); + adf_os_timer_start(&device->sleep_timer, HIF_MIN_SLEEP_INACTIVITY_TIME_MS); + } + /* Update the write time stamp */ + device->sleep_ticks = adf_os_ticks(); + } +#endif + if (request->pScatterReq != NULL) { + A_ASSERT(device->scatter_enabled); + /* this is a queued scatter request, pass the request to scatter routine which + * executes it synchronously, note, no need to free the request since scatter requests + * are maintained on a separate list */ + status = DoHifReadWriteScatter(device,request); + } else { + /* call HIFReadWrite in sync mode to do the work */ + status = __HIFReadWrite(device, request->address, request->buffer, + request->length, request->request & ~HIF_SYNCHRONOUS, NULL); + if (request->request & HIF_ASYNCHRONOUS) { + void *context = request->context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing req: 0x%lX\n", (unsigned long)request)); + hifFreeBusRequest(device, request); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%lX\n", (unsigned long)request)); + device->htcCallbacks.rwCompletionHandler(context, status); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req: 0x%lX\n", (unsigned long)request)); + request->status = status; + up(&request->sem_req); + } + } + spin_lock_irqsave(&device->asynclock, flags); + } + spin_unlock_irqrestore(&device->asynclock, flags); + sdio_release_host(device->func); + } + + complete_and_exit(&device->async_completion, 0); + return 0; +} +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) +static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, A_UINT32 flags, A_UINT32 *resp) +{ + struct mmc_command cmd; + A_INT32 err; + struct mmc_host *host; + struct sdio_func *func; + + func = device->func; + host = func->card->host; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = opcode; + cmd.arg = arg; + cmd.flags = flags; + err = mmc_wait_for_cmd(host, &cmd, 3); + + if ((!err) && (resp)) { + *resp = cmd.resp[0]; + } + + return err; +} +#endif +A_STATUS ReinitSDIO(HIF_DEVICE *device) +{ + A_INT32 err = 0; + struct mmc_host *host; + struct mmc_card *card; + struct sdio_func *func; + A_UINT8 cmd52_resp; + A_UINT32 clock; + + func = device->func; + card = func->card; + host = card->host; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n")); + sdio_claim_host(func); + + do { + /* Enable high speed */ + if (card->host->caps & MMC_CAP_SD_HIGHSPEED) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n")); + err = Func0_CMD52ReadByte(card, SDIO_CCCR_SPEED, &cmd52_resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 read to CCCR speed register failed : %d \n",err)); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) + card->state &= ~MMC_STATE_HIGHSPEED; +#endif + /* no need to break */ + } else { + err = Func0_CMD52WriteByte(card, SDIO_CCCR_SPEED, (cmd52_resp | SDIO_SPEED_EHS)); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 write to CCCR speed register failed : %d \n",err)); + break; + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) + mmc_card_set_highspeed(card); +#endif + host->ios.timing = MMC_TIMING_SD_HS; + host->ops->set_ios(host, &host->ios); + } + } + + /* Set clock */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) + if (mmc_card_highspeed(card)) { +#else + if (mmc_card_hs(card)) { +#endif + clock = 50000000; + } else { + clock = card->cis.max_dtr; + } + + if (clock > host->f_max) { + clock = host->f_max; + } + /* + * In fpga mode the clk should be set to 12500000, or will result in scan channel setting timeout error. + * So in fpga mode, please set module parameter mmcclock to 12500000. + */ + if(mmcclock > 0) + clock = mmcclock; + host->ios.clock = clock; + host->ops->set_ios(host, &host->ios); + + + if (card->host->caps & MMC_CAP_4_BIT_DATA) { + /* CMD52: Set bus width & disable card detect resistor */ + err = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 to set bus mode failed : %d \n",err)); + break; + } + host->ios.bus_width = MMC_BUS_WIDTH_4; + host->ops->set_ios(host, &host->ios); + } + } while (0); + + sdio_release_host(func); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n")); + + return (err) ? A_ERROR : A_OK; +} + +#ifdef CONFIG_PM +/* + * Setup IRQ mode for deep sleep and WoW + * Switch back to 1 bits mode when we suspend for WoW in order to + * detect SDIO irq without clock. + * Re-enable async 4-bit irq mode for some host controllers after resume + */ +static int SdioEnable4bits(HIF_DEVICE *device, int enable) +{ + int ret = 0; + struct sdio_func *func = device->func; + struct mmc_card *card = func->card; + struct mmc_host *host = card->host; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) + unsigned char ctrl = 0; + unsigned int width; +#ifdef SDIO_BUS_WIDTH_8BIT + unsigned char wide_mask = (SDIO_BUS_WIDTH_4BIT|SDIO_BUS_WIDTH_8BIT); +#else + unsigned char wide_mask = (SDIO_BUS_WIDTH_4BIT); +#endif +#endif + + if (!(host->caps & (MMC_CAP_4_BIT_DATA))) + return 0; + + if (card->cccr.low_speed && !card->cccr.wide_bus) + return 0; + + sdio_claim_host(func); + do { + int setAsyncIRQ = 0; + __u16 manufacturer_id = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; + /* 2.6.34 will setup 1bits automatically. No need to setup */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) + ret = Func0_CMD52ReadByte(card, SDIO_CCCR_IF, &ctrl); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Fail to read CCCR_IF : %d \n", __func__, ret)); + break; + } + if (enable) { + width = MMC_BUS_WIDTH_4; + ctrl &= ~(SDIO_BUS_WIDTH_1BIT|wide_mask); + ctrl |= SDIO_BUS_WIDTH_4BIT; + } else { + width = MMC_BUS_WIDTH_1; + ctrl &= ~(wide_mask); + } + + ret = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, ctrl); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Fail to write CCCR_IF : %d \n", __func__, ret)); + break; + } + host->ios.bus_width = width; + host->ops->set_ios(host, &host->ios); +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) */ + + /* Re-enable 4-bit ASYNC interrupt on AR6003x after system resume for some host controller */ + if (manufacturer_id == MANUFACTURER_ID_AR6003_BASE) { + setAsyncIRQ = 1; + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG_AR6003, + enable ? SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003 : 0); + } else if (manufacturer_id == MANUFACTURER_ID_AR6320_BASE || manufacturer_id == MANUFACTURER_ID_QCA9377_BASE) { + unsigned char data = 0; + setAsyncIRQ = 1; + ret = Func0_CMD52ReadByte(func->card, CCCR_SDIO_IRQ_MODE_REG_AR6320, &data); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to read interrupt extension register %d \n",ret)); + sdio_release_host(func); + return ret; + } + if (enable) + data |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320; + else + data &= ~SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320; + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG_AR6320, data); + } + if (setAsyncIRQ){ + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to setup 4-bit ASYNC IRQ mode into %d err %d \n", enable, ret)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("AR6000: Setup 4-bit ASYNC IRQ mode into %d successfully\n", enable)); + } + } + } while (0); + sdio_release_host(func); + return ret; +} + +#endif /* CONFIG_PM */ +A_STATUS +PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config) +{ + A_STATUS status = A_OK; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) + struct sdio_func *func = device->func; + int old_reset_val; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +PowerStateChangeNotify %d\n", config)); + switch (config) { + case HIF_DEVICE_POWER_DOWN: +#ifdef HIF_MBOX_SLEEP_WAR + adf_os_timer_cancel(&device->sleep_timer); + HIFSetMboxSleep(device, true, true, false); +#endif + /* Disable 4bits in order to let SDIO bus detect DAT1 as interrupt source */ + SdioEnable4bits(device, 0); + break; + case HIF_DEVICE_POWER_CUT: + old_reset_val = reset_sdio_on_unload; + reset_sdio_on_unload = 1; + status = hifDisableFunc(device, func); + reset_sdio_on_unload = old_reset_val; + if (!device->is_suspend) { + device->powerConfig = config; + mmc_detect_change(device->host, HZ/3); + } + break; + case HIF_DEVICE_POWER_UP: + if (device->powerConfig == HIF_DEVICE_POWER_CUT) { + if (device->is_suspend) { + status = ReinitSDIO(device); + /* set powerConfig before EnableFunc to passthrough sdio r/w action when resuming from cut power */ + device->powerConfig = config; + if (status == A_OK) { + status = hifEnableFunc(device, func); + } + } else { + /* device->func is bad pointer at this time */ + mmc_detect_change(device->host, 0); + return A_PENDING; /* Don't change powerConfig status */ + } + } else if (device->powerConfig == HIF_DEVICE_POWER_DOWN) { + int ret = SdioEnable4bits(device, 1); + status = (ret==0) ? A_OK : A_ERROR; + } + break; + } + device->powerConfig = config; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -PowerStateChangeNotify\n")); +#endif + return status; +} + +A_STATUS +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, A_UINT32 configLen) +{ + A_UINT32 count; + A_STATUS status = A_OK; + + switch(opcode) { + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: + ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; + ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; + ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; + ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; + break; + + case HIF_DEVICE_GET_MBOX_ADDR: + for (count = 0; count < 4; count ++) { + ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); + } + + if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) { + SetExtendedMboxWindowInfo((A_UINT16)device->func->device, + (HIF_DEVICE_MBOX_INFO *)config); + } + + break; + case HIF_DEVICE_GET_PENDING_EVENTS_FUNC: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: configuration opcode %d is not used for Linux SDIO stack \n", opcode)); + status = A_ERROR; + break; + case HIF_DEVICE_GET_IRQ_PROC_MODE: + *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; + break; + case HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: configuration opcode %d is not used for Linux SDIO stack \n", opcode)); + status = A_ERROR; + break; + case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: + if (!device->scatter_enabled) { + return A_ENOTSUP; + } + status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config); + if (A_FAILED(status)) { + device->scatter_enabled = FALSE; + } + break; + case HIF_DEVICE_GET_OS_DEVICE: + /* pass back a pointer to the SDIO function's "dev" struct */ + ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev; + break; + case HIF_DEVICE_POWER_STATE_CHANGE: + status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config); + break; + case HIF_DEVICE_GET_IRQ_YIELD_PARAMS: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: configuration opcode %d is only used for RTOS systems, not Linux systems\n", opcode)); + status = A_ERROR; + break; + case HIF_DEVICE_SET_HTC_CONTEXT: + device->htcContext = config; + break; + case HIF_DEVICE_GET_HTC_CONTEXT: + if (config == NULL){ + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Argument of HIF_DEVICE_GET_HTC_CONTEXT is NULL\n")); + return A_ERROR; + } + *(void**)config = device->htcContext; + break; + case HIF_BMI_DONE: + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: BMI_DONE\n", __FUNCTION__)); /* TBDXXX */ + break; + } + default: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: Unsupported configuration opcode: %d\n", opcode)); + status = A_ERROR; + } + + return status; +} + +void +HIFShutDownDevice(HIF_DEVICE *device) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n")); + if (device != NULL) { + AR_DEBUG_ASSERT(device->powerConfig==HIF_DEVICE_POWER_CUT || device->func != NULL); + } else { + int i; + /* since we are unloading the driver anyways, reset all cards in case the SDIO card + * is externally powered and we are unloading the SDIO stack. This avoids the problem when + * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already + * enumerated */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n")); + ResetAllCards(); + + /* Unregister with bus driver core */ + if (registered) { + registered = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Unregistering with the bus driver\n")); + sdio_unregister_driver(&ar6k_driver); + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Unregistered!")); + } + + for (i=0; ifunc == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Remove pending hif_device %p\n", hif_devices[i])); + delHifDevice(hif_devices[i]); + hif_devices[i] = NULL; + } + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n")); +} + +static void +hifIRQHandler(struct sdio_func *func) +{ + A_STATUS status; + HIF_DEVICE *device; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n")); + + device = getHifDevice(func); + atomic_set(&device->irqHandling, 1); + /* release the host during ints so we can pick it back up when we process cmds */ + sdio_release_host(device->func); + status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context); + sdio_claim_host(device->func); + atomic_set(&device->irqHandling, 0); + AR_DEBUG_ASSERT(status == A_OK || status == A_ECANCELED); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n")); +} + +#ifdef HIF_MBOX_SLEEP_WAR +static void +HIF_sleep_entry(void *arg) +{ + HIF_DEVICE *device = (HIF_DEVICE *)arg; + A_UINT32 idle_ms; + + idle_ms = adf_os_ticks_to_msecs(adf_os_ticks() + - device->sleep_ticks); + if (idle_ms >= HIF_MIN_SLEEP_INACTIVITY_TIME_MS) { + adf_os_atomic_set(&device->mbox_state, HIF_MBOX_REQUEST_TO_SLEEP_STATE); + up(&device->sem_async); + } else { + adf_os_timer_cancel(&device->sleep_timer); + adf_os_timer_start(&device->sleep_timer, + HIF_MIN_SLEEP_INACTIVITY_TIME_MS); + } +} + +void +HIFSetMboxSleep(HIF_DEVICE *device, bool sleep, bool wait, bool cache) +{ + if (!device || !device->func|| !device->func->card) { + printk("HIFSetMboxSleep incorrect input arguments\n"); + return; + } + sdio_claim_host(device->func); + if (cache) { + __HIFReadWrite(device, FIFO_TIMEOUT_AND_CHIP_CONTROL, + (A_UCHAR*)(&device->init_sleep), 4, + HIF_RD_SYNC_BYTE_INC, NULL); + } + if (sleep) { + device->init_sleep &= FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF; + adf_os_atomic_set(&device->mbox_state, HIF_MBOX_SLEEP_STATE); + } else { + device->init_sleep |= FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON; + adf_os_atomic_set(&device->mbox_state, HIF_MBOX_AWAKE_STATE); + } + + __HIFReadWrite(device, FIFO_TIMEOUT_AND_CHIP_CONTROL, + (A_UCHAR*)&device->init_sleep, 4, + HIF_WR_SYNC_BYTE_INC, NULL); + sdio_release_host(device->func); + /*Wait for 1ms for the written value to take effect */ + if (wait) { + adf_os_mdelay(HIF_SLEEP_DISABLE_UPDATE_DELAY); + } + return; +} +#endif + +/* handle HTC startup via thread*/ +static int startup_task(void *param) +{ + HIF_DEVICE *device; + + device = (HIF_DEVICE *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n")); + /* start up inform DRV layer */ + if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); + } + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) +static int enable_task(void *param) +{ + HIF_DEVICE *device; + device = (HIF_DEVICE *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n")); + + /* start up inform DRV layer */ + if (device && + device->claimedContext && + osdrvCallbacks.devicePowerChangeHandler && + osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != A_OK) + { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); + } + + return 0; +} +#endif +static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id) +{ + int i; + int ret; + HIF_DEVICE * device = NULL; + int count; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X, Device ID: 0x%X, block size: 0x%X/0x%X\n", + func->num, func->vendor, id->device, func->max_blksize, func->cur_blksize)); + /* + dma_mask should not be NULL, otherwise dma_map_single will crash. + TODO: check why dma_mask is NULL here + */ + if (func->dev.dma_mask == NULL){ + static u64 dma_mask = 0xFFFFFFFF; + func->dev.dma_mask = &dma_mask; + } + for (i=0; ipowerConfig == HIF_DEVICE_POWER_CUT && + hifdevice->host == func->card->host) { + hifdevice->func = func; + hifdevice->powerConfig = HIF_DEVICE_POWER_UP; + sdio_set_drvdata(func, hifdevice); + device = getHifDevice(func); + + if (device->is_suspend) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,("AR6000: hifDeviceInserted, Resume from suspend, need to ReinitSDIO.\n")); + ret = ReinitSDIO(device); + } + break; + } + } + + if (device==NULL) { + if (addHifDevice(func) == NULL) { + return -1; + } + device = getHifDevice(func); + + for (i=0; iid = id; + device->host = func->card->host; + device->is_disabled = TRUE; +/* +TODO: MMC SDIO3.0 Setting should also be modified in ReInit() function when Power Manage work. +*/ + { + A_UINT32 clock, clock_set = 12500000; + + sdio_claim_host(func); + + /* force driver strength to type D */ + if (((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == + MANUFACTURER_ID_QCA9377_BASE && forcedriverstrength == 1)) { + unsigned int addr = SDIO_CCCR_DRIVE_STRENGTH; + unsigned char value = 0; + A_UINT32 err = Func0_CMD52ReadByte(func->card, addr, &value); + if (err) { + printk("Read CCCR 0x%02X failed: %d\n", + (unsigned int) addr, + (unsigned int) err); + } else { + value = (value & + (~(SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT))) | + SDIO_DTSx_SET_TYPE_D; + err = Func0_CMD52WriteByte(func->card, addr, value); + if (err) { + printk("Write CCCR 0x%02X to 0x%02X failed: %d\n", + (unsigned int) addr, + (unsigned int) value, + (unsigned int) err); + } else { + addr = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR; + value = 0; + err = Func0_CMD52ReadByte(func->card, addr, &value); + if (err) { + printk("Read CCCR 0x%02X failed: %d\n", + (unsigned int) addr, + (unsigned int) err); + } else { + value = (value & + (~CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK)) | + CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A | + CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C | + CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D; + err = Func0_CMD52WriteByte(func->card, addr, value); + if (err) { + printk("Write CCCR 0x%02X to 0x%02X failed: %d\n", + (unsigned int) addr, + (unsigned int) value, + (unsigned int) err); + } + } + } + } + } + + if (writecccr1) { + A_UINT32 err = Func0_CMD52WriteByte(func->card, + writecccr1, + writecccr1value); + if (err) { + printk("Write CCCR 0x%02X to 0x%02X failed: %d\n", + (unsigned int) writecccr1, + (unsigned int) writecccr1value, + (unsigned int) err); + } else { + printk("Write CCCR 0x%02X to 0x%02X OK\n", + (unsigned int) writecccr1, + (unsigned int) writecccr1value); + } + } + if (writecccr2) { + A_UINT32 err = Func0_CMD52WriteByte(func->card, + writecccr2, + writecccr2value); + if (err) { + printk("Write CCCR 0x%02X to 0x%02X failed: %d\n", + (unsigned int) writecccr2, + (unsigned int) writecccr2value, + (unsigned int) err); + } else { + printk("Write CCCR 0x%02X to 0x%02X OK\n", + (unsigned int) writecccr2, + (unsigned int) writecccr2value); + } + } + if (writecccr3) { + A_UINT32 err = Func0_CMD52WriteByte(func->card, + writecccr3, + writecccr3value); + if (err) { + printk("Write CCCR 0x%02X to 0x%02X failed: %d\n", + (unsigned int) writecccr3, + (unsigned int) writecccr3value, + (unsigned int) err); + } else { + printk("Write CCCR 0x%02X to 0x%02X OK\n", + (unsigned int) writecccr3, + (unsigned int) writecccr3value); + } + } + if (writecccr4) { + A_UINT32 err = Func0_CMD52WriteByte(func->card, + writecccr4, + writecccr4value); + if (err) { + printk("Write CCCR 0x%02X to 0x%02X failed: %d\n", + (unsigned int) writecccr4, + (unsigned int) writecccr4value, + (unsigned int) err); + } else { + printk("Write CCCR 0x%02X to 0x%02X OK\n", + (unsigned int) writecccr4, + (unsigned int) writecccr4value); + } + } + // Set MMC Clock + if (mmcclock > 0){ + clock_set = mmcclock; + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) + if (mmc_card_highspeed(func->card)){ +#else + if (mmc_card_hs(func->card)) { +#endif + clock = 50000000; + } else { + clock = func->card->cis.max_dtr; + } + if (clock > device->host->f_max){ + clock = device->host->f_max; + } + + printk(KERN_ERR "%s: Dumping clocks (%d,%d)\n", __func__, func->card->cis.max_dtr, device->host->f_max); + +/* +// We don't need to set the clock explicitly on 8064/ADP platforms. +// The clock chosen by the MMC stack will take affect. + + printk(KERN_ERR "Decrease host clock from %d to %d(%d,%d)\n", + clock, clock_set, func->card->cis.max_dtr, device->host->f_max); + device->host->ios.clock = clock_set; + device->host->ops->set_ios(device->host, &device->host->ios); +*/ + /* only when mmcclock module parameter is specified, + * set the clock explicitly + */ + if (mmcclock > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Decrease host clock from %d to %d(%d,%d)\n", + clock, clock_set, func->card->cis.max_dtr, device->host->f_max)); + device->host->ios.clock = clock_set; + device->host->ops->set_ios(device->host, &device->host->ios); + } + +// Set SDIO3.0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + // Set MMC Bus Width: 1-1Bit, 4-4Bit, 8-8Bit + if (mmcbuswidth > 0){ + if (mmcbuswidth == 1){ + ret = Func0_CMD52WriteByte(func->card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE|SDIO_BUS_WIDTH_1BIT); + if (ret){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: CMD52 to set bus width failed: %d \n", __func__, ret)); + return ret; + } + device->host->ios.bus_width = MMC_BUS_WIDTH_1; + device->host->ops->set_ios(device->host, &device->host->ios); + } else if (mmcbuswidth == 4 && (device->host->caps & MMC_CAP_4_BIT_DATA)){ + ret = Func0_CMD52WriteByte(func->card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE|SDIO_BUS_WIDTH_4BIT); + if (ret){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: CMD52 to set bus width failed: %d \n", __func__, ret)); + return ret; + } + device->host->ios.bus_width = MMC_BUS_WIDTH_4; + device->host->ops->set_ios(device->host, &device->host->ios); + } +#ifdef SDIO_BUS_WIDTH_8BIT + else if (mmcbuswidth == 8 && (device->host->caps & MMC_CAP_8_BIT_DATA)){ + ret = Func0_CMD52WriteByte(func->card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE|SDIO_BUS_WIDTH_8BIT); + if (ret){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: CMD52 to set bus width failed: %d \n", __func__, ret)); + return ret; + } + device->host->ios.bus_width = MMC_BUS_WIDTH_8; + device->host->ops->set_ios(device->host, &device->host->ios); + } +#endif /* SDIO_BUS_WIDTH_8BIT */ + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: MMC bus width %d is not supported. \n", __func__, mmcbuswidth)); + return ret = -1; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("%s: Set MMC bus width to %dBit. \n", __func__, mmcbuswidth)); + } + if (debugcccr) { + HIFDumpCCCR(device); + } + +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) */ + sdio_release_host(func); + } + + spin_lock_init(&device->lock); + + spin_lock_init(&device->asynclock); + + DL_LIST_INIT(&device->ScatterReqHead); + + if (!nohifscattersupport) { + /* try to allow scatter operation on all instances, + * unless globally overridden */ + device->scatter_enabled = TRUE; + } + else + device->scatter_enabled = FALSE; + + /* Initialize the bus requests to be used later */ + A_MEMZERO(device->busRequest, sizeof(device->busRequest)); + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { + sema_init(&device->busRequest[count].sem_req, 0); + hifFreeBusRequest(device, &device->busRequest[count]); + } + sema_init(&device->sem_async, 0); + } +#ifdef HIF_MBOX_SLEEP_WAR + adf_os_timer_init(NULL, &device->sleep_timer, + HIF_sleep_entry, (void *)device, + ADF_NON_DEFERRABLE_TIMER); + adf_os_atomic_set(&device->mbox_state, HIF_MBOX_UNKNOWN_STATE); +#endif + + ret = hifEnableFunc(device, func); + return (ret == A_OK || ret == A_PENDING) ? 0 : -1; +} + + +void +HIFAckInterrupt(HIF_DEVICE *device) +{ + AR_DEBUG_ASSERT(device != NULL); + + /* Acknowledge our function IRQ */ +} + +void +HIFUnMaskInterrupt(HIF_DEVICE *device) +{ + int ret;; + + if (device == NULL || device->func == NULL) + return; + + ENTER(); + /* + * On HP Elitebook 8460P, interrupt mode is not stable in high throughput, + * so polling method should be used instead of interrupt mode + */ + if (brokenirq){ + printk(KERN_ERR"AR6000:Using broken IRQ mode\n"); + /* disable IRQ support even the capability exists */ + device->func->card->host->caps &= ~MMC_CAP_SDIO_IRQ; + } + /* Register the IRQ Handler */ + sdio_claim_host(device->func); + ret = sdio_claim_irq(device->func, hifIRQHandler); + sdio_release_host(device->func); + AR_DEBUG_ASSERT(ret == 0); + EXIT(); +} + +void HIFMaskInterrupt(HIF_DEVICE *device) +{ + int ret; + + if (device == NULL || device->func == NULL) + return; + ENTER(); + + /* Mask our function IRQ */ + sdio_claim_host(device->func); + while (atomic_read(&device->irqHandling)) { + sdio_release_host(device->func); + schedule_timeout_interruptible(HZ/10); + sdio_claim_host(device->func); + } + ret = sdio_release_irq(device->func); + sdio_release_host(device->func); + if (ret) { + if (ret == -ETIMEDOUT) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: Timeout to mask interrupt. Card removed?\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Unable to mask interrupt %d\n", ret)); + AR_DEBUG_ASSERT(ret == 0); + } + } + EXIT(); +} + +BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device) +{ + BUS_REQUEST *busrequest; + unsigned long flag; + + /* Acquire lock */ + spin_lock_irqsave(&device->lock, flag); + + /* Remove first in list */ + if((busrequest = device->s_busRequestFreeQueue) != NULL) + { + device->s_busRequestFreeQueue = busrequest->next; + } + /* Release lock */ + spin_unlock_irqrestore(&device->lock, flag); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", busrequest)); + return busrequest; +} + +void +hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest) +{ + unsigned long flag; + + if (busrequest == NULL) + return; + //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busrequest)); + /* Acquire lock */ + spin_lock_irqsave(&device->lock, flag); + + + /* Insert first in list */ + busrequest->next = device->s_busRequestFreeQueue; + busrequest->inusenext = NULL; + device->s_busRequestFreeQueue = busrequest; + + /* Release lock */ + spin_unlock_irqrestore(&device->lock, flag); +} + +static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func) +{ + int ret; + A_STATUS status = A_OK; + + ENTER(); + device = getHifDevice(func); + if (device->async_task) { + init_completion(&device->async_completion); + device->async_shutdown = 1; + up(&device->sem_async); + wait_for_completion(&device->async_completion); + device->async_task = NULL; + sema_init(&device->sem_async, 0); + } +#ifdef HIF_MBOX_SLEEP_WAR + adf_os_timer_cancel(&device->sleep_timer); + HIFSetMboxSleep(device, true, true, false); +#endif + /* Disable the card */ + sdio_claim_host(device->func); + ret = sdio_disable_func(device->func); + if (ret) { + status = A_ERROR; + } + + if (reset_sdio_on_unload && status == A_OK) { + /* reset the SDIO interface. This is useful in automated testing where the card + * does not need to be removed at the end of the test. It is expected that the user will + * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */ + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n")); + + /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows access + * to undefined registers in the range of: 0xF0-0xFF */ + + ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3)); + if (ret) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret)); + } + } + + sdio_release_host(device->func); + + if (status == A_OK) { + device->is_disabled = TRUE; + } + CleanupHIFScatterResources(device); + + EXIT(); + return status; +} + +static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func) +{ + struct task_struct* pTask; + const char *taskName = NULL; + int (*taskFunc)(void *) = NULL; + int ret = A_OK; + + ENTER("sdio_func 0x%p", func); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n")); + device = getHifDevice(func); + + if (device->is_disabled) { + int setAsyncIRQ = 0; + __u16 manufacturer_id = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; + /* enable the SDIO function */ + sdio_claim_host(func); + /* enable 4-bit ASYNC interrupt on AR6003x or later devices */ + if (manufacturer_id == MANUFACTURER_ID_AR6003_BASE) { + setAsyncIRQ = 1; + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG_AR6003, + SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003); + } else if (manufacturer_id == MANUFACTURER_ID_AR6320_BASE || + manufacturer_id == MANUFACTURER_ID_QCA9377_BASE) { + unsigned char data = 0; + setAsyncIRQ = 1; + ret = Func0_CMD52ReadByte(func->card, CCCR_SDIO_IRQ_MODE_REG_AR6320, &data); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to read interrupt extension register %d \n",ret)); + sdio_release_host(func); + return A_ERROR; + } + data |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320; + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG_AR6320, data); + } + if (setAsyncIRQ){ + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret)); + sdio_release_host(func); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n")); + } + + /* set CCCR 0xF0[7:6] to increase async interrupt delay clock to fix interrupt missing issue on dell 8460p */ + if (asyncintdelay != 0){ + unsigned char data = 0; + ret = Func0_CMD52ReadByte(func->card, CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, &data); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to read CCCR %d, result is %d \n", + CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, ret)); + sdio_release_host(func); + return A_ERROR; + } + data = (data & ~CCCR_SDIO_ASYNC_INT_DELAY_MASK) | + ((asyncintdelay << CCCR_SDIO_ASYNC_INT_DELAY_LSB) & CCCR_SDIO_ASYNC_INT_DELAY_MASK); + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, data); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to write CCCR %d, result is %d \n", + CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, ret)); + sdio_release_host(func); + return A_ERROR; + } + printk(KERN_ERR"AR6000: Set async interrupt delay clock as %d.\n", asyncintdelay); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + /* give us some time to enable, in ms */ + func->enable_timeout = 100; +#endif + ret = sdio_enable_func(func); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n", + __FUNCTION__, ret)); + sdio_release_host(func); + return A_ERROR; + } + ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); + + if (modstrength){ + unsigned int address = WINDOW_DATA_ADDRESS; + unsigned int value = 0x0FFF; + ret = sdio_memcpy_toio(device->func, address, &value, 4); + if (ret) { + printk("memcpy_toio 0x%x 0x%x error:%d\n", address, value, ret); + } else { + printk("memcpy_toio, 0x%x 0x%x OK\n", address, value); + address = WINDOW_WRITE_ADDR_ADDRESS; + value = 0x50F8; + ret = sdio_memcpy_toio(device->func, address, &value, 4); + if (ret) { + printk("memcpy_toio 0x%x 0x%x error:%d\n", address, value, ret); + } else { + printk("memcpy_toio, 0x%x 0x%x OK\n", address, value); + } + } + }; + sdio_release_host(func); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n", + __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret)); + return A_ERROR; + } + device->is_disabled = FALSE; + /* create async I/O thread */ + if (!device->async_task) { + device->async_shutdown = 0; + device->async_task = kthread_create(async_task, + (void *)device, + "AR6K Async"); + if (IS_ERR(device->async_task)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__)); + device->async_task = NULL; + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); + wake_up_process(device->async_task ); + } + } + + if (!device->claimedContext) { + taskFunc = startup_task; + taskName = "AR6K startup"; + ret = A_OK; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) + } else { + taskFunc = enable_task; + taskName = "AR6K enable"; + ret = A_PENDING; +#endif /* CONFIG_PM */ + } + /* create resume thread */ + pTask = kthread_create(taskFunc, (void *)device, taskName); + if (IS_ERR(pTask)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__)); + return A_ERROR; + } + wake_up_process(pTask); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n")); + + /* task will call the enable func, indicate pending */ + EXIT(); + return ret; +} +#if 0 +//ToDO - This is a part of suspend/resume functionality +static int hifStopAllVap(struct ol_ath_softc_net80211 *scn) +{ + struct ieee80211com *ic; + struct ieee80211vap *vap; + struct ieee80211vap *vapnext; + osif_dev *osifp; + struct net_device *netdev; + A_STATUS status = A_OK; + + ic = &scn->sc_ic; + vap = TAILQ_FIRST(&ic->ic_vaps); + while (vap != NULL) { + vapnext = TAILQ_NEXT(vap, iv_next); + osifp = (osif_dev *)vap->iv_ifp; + if(osifp->is_up == 0){ + vap = vapnext; + continue; + } + + /* force target to sleep */ + wlan_pwrsave_force_sleep(vap,TRUE); + + netdev = osifp->netdev; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: %s()stopping interface %s\n", __FUNCTION__, netdev->name)); + status = osif_vap_stop(netdev); + if(status){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s()stop interface %s failed\n", __FUNCTION__, netdev->name)); + } + vap = vapnext; + } + + return A_OK; +} + +static int hifRestartAllVap(struct ol_ath_softc_net80211 *scn) +{ + struct ieee80211com *ic; + struct ieee80211vap *vap; + struct ieee80211vap *vapnext; + osif_dev *osifp; + struct net_device *netdev; + + ic = &scn->sc_ic;; + vap = TAILQ_FIRST(&ic->ic_vaps); + while (vap != NULL) { + vapnext = TAILQ_NEXT(vap, iv_next); + osifp = (osif_dev *)vap->iv_ifp; + netdev = osifp->netdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: %s()restarting interface %s\n", __FUNCTION__, netdev->name)); + netdev->flags |= IFF_RUNNING; /* we are ready to go */ + osifp->is_vap_pending = 1; + osif_vap_init(netdev, 0); + + /* restore power save state */ + wlan_pwrsave_force_sleep(vap,FALSE); + + vap = vapnext; + } + + return A_OK; +} +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) +static int hifDeviceSuspend(struct device *dev) +{ + struct sdio_func *func=dev_to_sdio_func(dev); + A_STATUS status = A_OK; + int ret = A_OK; +#if defined(MMC_PM_KEEP_POWER) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + mmc_pm_flag_t pm_flag = 0; + HIF_DEVICE_POWER_CHANGE_TYPE config; + struct mmc_host *host = NULL; +#endif + + HIF_DEVICE *device = getHifDevice(func); + void *vos = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + v_VOID_t *temp_module; + + if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: LOPG in progress\n", __func__)); + return (-1); + } + + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos); + if (!temp_module) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: WDA module is NULL\n", __func__)); + return (-1); + } + + if (wma_check_scan_in_progress(temp_module)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: Scan in progress. Aborting suspend\n", __func__)); + return (-1); + } + +#if defined(MMC_PM_KEEP_POWER) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + if (device && device->func) { + host = device->func->card->host; + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceSuspend\n")); + if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) { + device->is_suspend = TRUE; /* set true first for PowerStateChangeNotify(..) */ + status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext); + +#if defined(MMC_PM_KEEP_POWER) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + switch(forcesleepmode){ + case 0://depend on sdio host pm capbility + pm_flag = sdio_get_host_pm_caps(func); + break; + case 1://force WOW + pm_flag |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; + break; + case 2://force DeepSleep + pm_flag &= ~MMC_PM_WAKE_SDIO_IRQ; + pm_flag |= MMC_PM_KEEP_POWER; + break; + case 3://force CutPower + pm_flag &= ~(MMC_PM_WAKE_SDIO_IRQ | MMC_PM_WAKE_SDIO_IRQ); + break; + } + if(!(pm_flag & MMC_PM_KEEP_POWER)){ + /* cut power support */ + /*setting powerConfig before HIFConfigureDevice to skip sdio r/w action when suspending with cut power*/ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: cut power enter\n")); + config = HIF_DEVICE_POWER_CUT; + device->powerConfig = config; + if ((device->claimedContext != NULL)&&osdrvCallbacks.deviceRemovedHandler) { + status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device); + } + ret = HIFConfigureDevice(device, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + if(ret){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: HIFConfigureDevice failed: %d\n",ret)); + return ret; + } + + HIFMaskInterrupt(device); + device->DeviceState = HIF_DEVICE_STATE_CUTPOWER; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: cut power success\n")); + return ret; + } else { + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: set sdio pm flags MMC_PM_KEEP_POWER failed: %d\n",ret)); + return ret; + } + + if (wma_is_wow_mode_selected(temp_module)) { + if (wma_enable_wow_in_fw(temp_module, 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("wow mode failure\n")); + return -1; + } + } else { + if (wma_suspend_target(temp_module, 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("PDEV Suspend Failed\n")); + return -1; + } + } + + if (pm_flag & MMC_PM_WAKE_SDIO_IRQ){ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: wow enter\n")); + config = HIF_DEVICE_POWER_DOWN; + ret = HIFConfigureDevice(device, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + + if(ret){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: HIFConfigureDevice failed: %d\n",ret)); + return ret; + } + ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); + if (ret){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: set sdio pm flags MMC_PM_WAKE_SDIO_IRQ failed: %d\n",ret)); + return ret; + } + HIFMaskInterrupt(device); + device->DeviceState = HIF_DEVICE_STATE_WOW; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: wow success\n")); + return ret; + } + else{ + /* deep sleep support */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: deep sleep enter\n")); +// hifStopAllVap((struct ol_ath_softc_net80211 *)device->claimedContext); + + /* + * Wait for some async clean handler finished. + * These clean handlers are part of vdev disconnect flow. + * As these handlers are async,sleep wait is not a good method, some block kernel method may be a good choice. + * But before adding finishe callback function to these handler, sleep wait is a simple method. + */ + msleep(100); + HIFMaskInterrupt(device); + device->DeviceState = HIF_DEVICE_STATE_DEEPSLEEP; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: deep sleep success\n")); + return ret; + } + } +#endif + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceSuspend\n")); + + switch (status) { + case A_OK: +#if defined(MMC_PM_KEEP_POWER) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + if (host) { + host->pm_flags &= ~(MMC_PM_KEEP_POWER|MMC_PM_WAKE_SDIO_IRQ); + } +#endif + return 0; + case A_EBUSY: +#if defined(MMC_PM_KEEP_POWER) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) + if (host) { + /* Some controller need to WAKE_SDIO_IRQ in order to wake up by DAT1 */ + host->pm_flags |= (MMC_PM_KEEP_POWER|MMC_PM_WAKE_SDIO_IRQ); + host->pm_flags &= host->pm_caps; + } + return 0; +#else + return -EBUSY; /* Hack for kernel to support deep sleep and wow */ +#endif + default: + device->is_suspend = FALSE; + return -1; + } +} + +static int hifDeviceResume(struct device *dev) +{ + struct sdio_func *func=dev_to_sdio_func(dev); + A_STATUS status = A_OK; + HIF_DEVICE_POWER_CHANGE_TYPE config; + HIF_DEVICE *device; + void *vos = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + v_VOID_t * temp_module; + + if (vos == NULL) + return 0; + + temp_module = vos_get_context(VOS_MODULE_ID_WDA, vos); + if (!temp_module) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: WDA module is NULL\n", __func__)); + return (-1); + } + + device = getHifDevice(func); + if (device == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: device is NULL\n", __func__)); + return (-1); + } + + if(device->DeviceState == HIF_DEVICE_STATE_CUTPOWER){ + config = HIF_DEVICE_POWER_UP; + status = HIFConfigureDevice(device, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + if(status){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: HIFConfigureDevice failed\n")); + return status; + } + } + else if(device->DeviceState == HIF_DEVICE_STATE_DEEPSLEEP){ + HIFUnMaskInterrupt(device); +// hifRestartAllVap((struct ol_ath_softc_net80211 *)device->claimedContext); + } + else if(device->DeviceState == HIF_DEVICE_STATE_WOW){ + config = HIF_DEVICE_POWER_UP; + status = HIFConfigureDevice(device, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + if(status){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: HIFConfigureDevice failed status:%d\n", status)); + return status; + } + /*TODO:WOW support*/ + HIFUnMaskInterrupt(device); + } + + /* + * deviceResumeHandler do nothing now. + * If some operation should be added to this handler in power cut resume flow, + * do make sure those operation is not + * depent on what startup_task has done,or the resume flow will block. + */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceResume\n")); + if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) { + status = osdrvCallbacks.deviceResumeHandler(device->claimedContext); + device->is_suspend = FALSE; + } + + /* No need to send WMI_PDEV_RESUME_CMDID to FW if WOW is enabled */ + if (!wma_is_wow_mode_selected(temp_module)) { + wma_resume_target(temp_module, 0); + } else if (wma_disable_wow_in_fw(temp_module, 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%s: disable wow in fw failed\n", __func__)); + status = (-1); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceResume\n")); + device->DeviceState = HIF_DEVICE_STATE_ON; + + return A_SUCCESS(status) ? 0 : status; +} +#endif /* CONFIG_PM */ + +static void hifDeviceRemoved(struct sdio_func *func) +{ + A_STATUS status = A_OK; + HIF_DEVICE *device; + AR_DEBUG_ASSERT(func != NULL); + + ENTER(); + + device = getHifDevice(func); + + if (device->powerConfig == HIF_DEVICE_POWER_CUT) { + device->func = NULL; /* func will be free by mmc stack */ + return; /* Just return for cut-off mode */ + } else { + int i; + for (i=0; iclaimedContext != NULL) { + status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device); + } + + HIFMaskInterrupt(device); + + if (device->is_disabled) { + device->is_disabled = FALSE; + } else { + status = hifDisableFunc(device, func); + } + + delHifDevice(device); + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: Unable to disable sdio func. Card removed?\n")); + } + + EXIT(); +} + +/* + * This should be moved to AR6K HTC layer. + */ +A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device) +{ + A_INT32 cnt = 10; + A_UINT8 host_int_status; + A_STATUS status = A_OK; + + do { + while (atomic_read(&device->irqHandling)) { + /* wait until irq handler finished all the jobs */ + schedule_timeout_interruptible(HZ / 10); + } + /* check if there is any pending irq due to force done */ + host_int_status = 0; + status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS, + (A_UINT8 *)&host_int_status, sizeof(host_int_status), + HIF_RD_SYNC_BYTE_INC, NULL); + host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)) : 0; + if (host_int_status) { + /* wait until irq handler finishs its job */ + schedule_timeout_interruptible(1); + } + } while (host_int_status && --cnt > 0); + + if (host_int_status && cnt == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__)); + } + + return A_OK; +} + + +static HIF_DEVICE * +addHifDevice(struct sdio_func *func) +{ + HIF_DEVICE *hifdevice = NULL; +#if(LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && !defined(WITH_BACKPORTS) + int ret = 0; +#endif + ENTER(); + if (func == NULL) + return NULL; + + hifdevice = (HIF_DEVICE *)A_MALLOC(sizeof(HIF_DEVICE)); + if (hifdevice == NULL) + return NULL; + A_MEMZERO(hifdevice, sizeof(*hifdevice)); +#if HIF_USE_DMA_BOUNCE_BUFFER + hifdevice->dma_buffer = A_MALLOC(HIF_DMA_BUFFER_SIZE); + AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL); + if (hifdevice->dma_buffer == NULL) { + A_FREE(hifdevice); + return NULL; + } +#endif + hifdevice->func = func; + hifdevice->powerConfig = HIF_DEVICE_POWER_UP; + hifdevice->DeviceState = HIF_DEVICE_STATE_ON; +#if(LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && !defined(WITH_BACKPORTS) + ret = sdio_set_drvdata(func, hifdevice); + EXIT("status %d", ret); +#else + sdio_set_drvdata(func, hifdevice); + EXIT(); +#endif + return hifdevice; +} + +static HIF_DEVICE * +getHifDevice(struct sdio_func *func) +{ + AR_DEBUG_ASSERT(func != NULL); + return (HIF_DEVICE *)sdio_get_drvdata(func); +} + +static void +delHifDevice(HIF_DEVICE * device) +{ + if (device == NULL) + return; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device)); + if (device->dma_buffer != NULL) { + A_FREE(device->dma_buffer); + } + A_FREE(device); +} + +static void ResetAllCards(void) +{ +} + +void HIFClaimDevice(HIF_DEVICE *device, void *context) +{ + device->claimedContext = context; +} + +void HIFSetMailboxSwap(HIF_DEVICE *device) +{ + device->swap_mailbox = TRUE; +} + +void HIFReleaseDevice(HIF_DEVICE *device) +{ + device->claimedContext = NULL; +} + +A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks) +{ + if (device->htcCallbacks.context != NULL) { + /* already in use! */ + return A_ERROR; + } + device->htcCallbacks = *callbacks; + return A_OK; +} + +static void hif_flush_async_task(HIF_DEVICE *device) +{ + if (device->async_task) { + init_completion(&device->async_completion); + device->async_shutdown = 1; + up(&device->sem_async); + wait_for_completion(&device->async_completion); + device->async_task = NULL; + sema_init(&device->sem_async, 0); + } +} + +void HIFDetachHTC(HIF_DEVICE *device) +{ + hif_flush_async_task(device); + A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks)); +} + +#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \ + (arg) = (((rw) & 1) << 31) | \ + (((func) & 0x7) << 28) | \ + (((raw) & 1) << 27) | \ + (1 << 26) | \ + (((address) & 0x1FFFF) << 9) | \ + (1 << 8) | \ + ((writedata) & 0xFF) + +#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \ + SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00) +#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \ + SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value) + +static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte) +{ + struct mmc_command ioCmd; + unsigned long arg; + int status = 0; + + memset(&ioCmd,0,sizeof(ioCmd)); + SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte); + ioCmd.opcode = SD_IO_RW_DIRECT; + ioCmd.arg = arg; + ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + status = mmc_wait_for_cmd(card->host, &ioCmd, 0); + + if (status) AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s mmc_wait_for_cmd returned %d\n",__func__, status)); + + return status; +} + +static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte) +{ + struct mmc_command ioCmd; + unsigned long arg; + A_INT32 err; + + memset(&ioCmd,0,sizeof(ioCmd)); + SDIO_SET_CMD52_READ_ARG(arg,0,address); + ioCmd.opcode = SD_IO_RW_DIRECT; + ioCmd.arg = arg; + ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + + err = mmc_wait_for_cmd(card->host, &ioCmd, 0); + + if ((!err) && (byte)) { + *byte = ioCmd.resp[0] & 0xFF; + } + + if (err) AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s mmc_wait_for_cmd returned %d\n",__func__, err)); + + return err; +} + +void HIFDumpCCCR(HIF_DEVICE *hif_device) +{ + int i; + A_UINT8 cccr_val; + A_UINT32 err; + + if (!hif_device || !hif_device->func|| !hif_device->func->card) { + printk("HIFDumpCCCR incorrect input arguments\n"); + return; + } + + printk("HIFDumpCCCR "); + for (i = 0; i <= 0x16; i ++) { + err = Func0_CMD52ReadByte(hif_device->func->card, i, &cccr_val); + if (err) { + printk("Reading CCCR 0x%02X failed: %d\n", (unsigned int)i, (unsigned int)err); + } else { + printk("%X(%X) ", (unsigned int)i, (unsigned int)cccr_val); + } + } +/* + printk("\nHIFDumpCCCR "); + for (i = 0xF0; i <= 0xFF; i ++) { + err = Func0_CMD52ReadByte(hif_device->func->card, i, &cccr_val); + if (err) { + printk("Reading CCCR 0x%02X failed: %d\n", (unsigned int)i, (unsigned int)err); + } else { + printk("0x%02X(%02X)", (unsigned int)i, (unsigned int)cccr_val); + } + } +*/ + printk("\n"); +} + +void HIFsuspendwow(HIF_DEVICE *hif_device) +{ + printk(KERN_INFO "HIFsuspendwow TODO\n"); +} + +A_BOOL HIFIsMailBoxSwapped(HIF_DEVICE *hd) +{ + return ((struct hif_device *)hd)->swap_mailbox; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif_scatter.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif_scatter.c new file mode 100644 index 000000000000..978a8b6972f2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif_scatter.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include "hif_internal.h" +#include +#define ATH_MODULE_NAME hif +#include "a_debug.h" + +#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT + +#define _CMD53_ARG_READ 0 +#define _CMD53_ARG_WRITE 1 +#define _CMD53_ARG_BLOCK_BASIS 1 +#define _CMD53_ARG_FIXED_ADDRESS 0 +#define _CMD53_ARG_INCR_ADDRESS 1 + +#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \ + (arg) = (((rw) & 1) << 31) | \ + (((func) & 0x7) << 28) | \ + (((mode) & 1) << 27) | \ + (((opcode) & 1) << 26) | \ + (((address) & 0x1FFFF) << 9) | \ + ((bytes_blocks) & 0x1FF) + +static void FreeScatterReq(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq) +{ + unsigned long flag; + + spin_lock_irqsave(&device->lock, flag); + + DL_ListInsertTail(&device->ScatterReqHead, &pReq->ListLink); + + spin_unlock_irqrestore(&device->lock, flag); + +} + +static HIF_SCATTER_REQ *AllocScatterReq(HIF_DEVICE *device) +{ + DL_LIST *pItem; + unsigned long flag; + + spin_lock_irqsave(&device->lock, flag); + + pItem = DL_ListRemoveItemFromHead(&device->ScatterReqHead); + + spin_unlock_irqrestore(&device->lock, flag); + + if (pItem != NULL) { + return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink); + } + + return NULL; +} + + /* called by async task to perform the operation synchronously using direct MMC APIs */ +A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest) +{ + int i; + A_UINT8 rw; + A_UINT8 opcode; + struct mmc_request mmcreq; + struct mmc_command cmd; + struct mmc_data data; + HIF_SCATTER_REQ_PRIV *pReqPriv; + HIF_SCATTER_REQ *pReq; + A_STATUS status = A_OK; + struct scatterlist *pSg; + + ENTER(); + + pReqPriv = busrequest->pScatterReq; + + if (pReqPriv == NULL) + return A_ERROR; + + pReq = pReqPriv->pHifScatterReq; + + memset(&mmcreq, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + data.blksz = HIF_MBOX_BLOCK_SIZE; + data.blocks = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE; + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: (%s) Address: 0x%X, (BlockLen: %d, BlockCount: %d) , (tot:%d,sg:%d)\n", + (pReq->Request & HIF_WRITE) ? "WRITE":"READ", pReq->Address, data.blksz, data.blocks, + pReq->TotalLength,pReq->ValidScatterEntries)); + + if (pReq->Request & HIF_WRITE) { + rw = _CMD53_ARG_WRITE; + data.flags = MMC_DATA_WRITE; + } else { + rw = _CMD53_ARG_READ; + data.flags = MMC_DATA_READ; + } + + if (pReq->Request & HIF_FIXED_ADDRESS) { + opcode = _CMD53_ARG_FIXED_ADDRESS; + } else { + opcode = _CMD53_ARG_INCR_ADDRESS; + } + + /* fill SG entries */ + pSg = pReqPriv->sgentries; + sg_init_table(pSg, pReq->ValidScatterEntries); + + /* assemble SG list */ + for (i = 0 ; i < pReq->ValidScatterEntries ; i++, pSg++) { + /* setup each sg entry */ + if ((unsigned long)pReq->ScatterList[i].pBuffer & 0x3) { + /* note some scatter engines can handle unaligned buffers, print this + * as informational only */ + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, + ("HIF: (%s) Scatter Buffer is unaligned 0x%lx\n", + pReq->Request & HIF_WRITE ? "WRITE":"READ", + (unsigned long)pReq->ScatterList[i].pBuffer)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, (" %d: Addr:0x%lX, Len:%d \n", + i,(unsigned long)pReq->ScatterList[i].pBuffer,pReq->ScatterList[i].Length)); + + sg_set_buf(pSg, pReq->ScatterList[i].pBuffer, pReq->ScatterList[i].Length); + } + /* set scatter-gather table for request */ + data.sg = pReqPriv->sgentries; + data.sg_len = pReq->ValidScatterEntries; + /* set command argument */ + SDIO_SET_CMD53_ARG(cmd.arg, + rw, + device->func->num, + _CMD53_ARG_BLOCK_BASIS, + opcode, + pReq->Address, + data.blocks); + + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + mmcreq.cmd = &cmd; + mmcreq.data = &data; + + mmc_set_data_timeout(&data, device->func->card); + /* synchronous call to process request */ + mmc_wait_for_req(device->func->card->host, &mmcreq); + + if (cmd.error) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: cmd error: %d \n",cmd.error)); + } + + if (data.error) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error)); + } + + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n", + (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks)); + } + + /* set completion status, fail or success */ + pReq->CompletionStatus = status; + + if (pReq->Request & HIF_ASYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: async_task completion routine req: 0x%lX (%d)\n",(unsigned long)busrequest, status)); + /* complete the request */ + if (pReq->CompletionRoutine != NULL) + pReq->CompletionRoutine(pReq); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER async_task upping busrequest : 0x%lX (%d)\n", (unsigned long)busrequest,status)); + /* signal wait */ + up(&busrequest->sem_req); + } + EXIT(); + + return status; +} + + /* callback to issue a read-write scatter request */ +static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq) +{ + A_STATUS status = A_EINVAL; + A_UINT32 request = pReq->Request; + HIF_SCATTER_REQ_PRIV *pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0]; + + do { + + if (NULL == pReqPriv) { + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: total len: %d Scatter Entries: %d\n", + pReq->TotalLength, pReq->ValidScatterEntries)); + + if (!(request & HIF_EXTENDED_IO)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid command type: 0x%08x\n", request)); + break; + } + + if (!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid execution mode: 0x%08x\n", request)); + break; + } + + if (!(request & HIF_BLOCK_BASIS)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid data mode: 0x%08x\n", request)); + break; + } + + if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid length: %d \n", pReq->TotalLength)); + break; + } + + if (pReq->TotalLength == 0) { + A_ASSERT(FALSE); + break; + } + + /* add bus request to the async list for the async I/O thread to process */ + AddToAsyncList(device, pReqPriv->busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued sync req: 0x%lX\n", (unsigned long)pReqPriv->busrequest)); + /* signal thread and wait */ + up(&device->sem_async); + if (down_interruptible(&pReqPriv->busrequest->sem_req) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF-SCATTER: interrupted! \n")); + /* interrupted, exit */ + status = A_ERROR; + break; + } else { + status = pReq->CompletionStatus; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest)); + /* wake thread, it will process and then take care of the async callback */ + up(&device->sem_async); + status = A_OK; + } + + } while (FALSE); + + if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) { + pReq->CompletionStatus = status; + pReq->CompletionRoutine(pReq); + status = A_OK; + } + + return status; +} + + /* setup of HIF scatter resources */ +A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo) +{ + A_STATUS status = A_ERROR; + int i; + HIF_SCATTER_REQ_PRIV *pReqPriv; + BUS_REQUEST *busrequest; + + do { + /* check if host supports scatter requests and it meets our requirements */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + if (device->func->card->host->max_hw_segs < MAX_SCATTER_ENTRIES_PER_REQ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n", + device->func->card->host->max_hw_segs, MAX_SCATTER_ENTRIES_PER_REQ)); + status = A_ENOTSUP; + break; + } +#else + if (device->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n", + device->func->card->host->max_segs, MAX_SCATTER_ENTRIES_PER_REQ)); + status = A_ENOTSUP; + break; + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HIF-SCATTER Enabled: max scatter req : %d entries: %d \n", + MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ)); + + for (i = 0; i < MAX_SCATTER_REQUESTS; i++) { + /* allocate the private request blob */ + pReqPriv = (HIF_SCATTER_REQ_PRIV *)A_MALLOC(sizeof(HIF_SCATTER_REQ_PRIV)); + if (NULL == pReqPriv) { + break; + } + A_MEMZERO(pReqPriv, sizeof(HIF_SCATTER_REQ_PRIV)); + /* save the device instance*/ + pReqPriv->device = device; + /* allocate the scatter request */ + pReqPriv->pHifScatterReq = (HIF_SCATTER_REQ *)A_MALLOC(sizeof(HIF_SCATTER_REQ) + + (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM))); + + if (NULL == pReqPriv->pHifScatterReq) { + A_FREE(pReqPriv); + break; + } + /* just zero the main part of the scatter request */ + A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(HIF_SCATTER_REQ)); + /* back pointer to the private struct */ + pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv; + /* allocate a bus request for this scatter request */ + busrequest = hifAllocateBusRequest(device); + if (NULL == busrequest) { + A_FREE(pReqPriv->pHifScatterReq); + A_FREE(pReqPriv); + break; + } + /* assign the scatter request to this bus request */ + busrequest->pScatterReq = pReqPriv; + /* point back to the request */ + pReqPriv->busrequest = busrequest; + /* add it to the scatter pool */ + FreeScatterReq(device,pReqPriv->pHifScatterReq); + } + + if (i != MAX_SCATTER_REQUESTS) { + status = A_NO_MEMORY; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : failed to alloc scatter resources !\n")); + break; + } + + /* set scatter function pointers */ + pInfo->pAllocateReqFunc = AllocScatterReq; + pInfo->pFreeReqFunc = FreeScatterReq; + pInfo->pReadWriteScatterFunc = HifReadWriteScatter; + pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ; + pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE; + + status = A_OK; + + } while (FALSE); + + if (A_FAILED(status)) { + CleanupHIFScatterResources(device); + } + + return status; +} + + /* clean up scatter support */ +void CleanupHIFScatterResources(HIF_DEVICE *device) +{ + HIF_SCATTER_REQ_PRIV *pReqPriv; + HIF_SCATTER_REQ *pReq; + + /* empty the free list */ + + while (1) { + + pReq = AllocScatterReq(device); + if (NULL == pReq) { + break; + } + + pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0]; + if (NULL == pReqPriv) { + break; + } + + if (pReqPriv->busrequest != NULL) { + pReqPriv->busrequest->pScatterReq = NULL; + /* free bus request */ + hifFreeBusRequest(device, pReqPriv->busrequest); + pReqPriv->busrequest = NULL; + } + + if (pReqPriv->pHifScatterReq != NULL) { + A_FREE(pReqPriv->pHifScatterReq); + pReqPriv->pHifScatterReq = NULL; + } + + A_FREE(pReqPriv); + } +} + +#endif // HIF_LINUX_MMC_SCATTER_SUPPORT diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.c new file mode 100644 index 000000000000..34a3f333e9ae --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "bmi_msg.h" +#include "cepci.h" + +#define MISSING 0 +#include "regtable.h" +#include "targaddrs.h" +#include "if_ath_sdio.h" +#include "ar9888def.h" +#include "ar6320def.h" +#include "ar6320v2def.h" + + + +void target_register_tbl_attach(u32 target_type) +{ + ENTER("target_type %d", target_type); + + switch (target_type) { + case TARGET_TYPE_AR9888: + sc->targetdef = &ar9888_targetdef; + break; + case TARGET_TYPE_AR6320: + sc->targetdef = &ar6320_targetdef; + break; + case TARGET_TYPE_AR6320V2: + sc->targetdef = &ar6320v2_targetdef; + break; + default: + break; + } +} + +void hif_register_tbl_attach(u32 hif_type) +{ + ENTER("hif_type %d", hif_type); + + if (NULL == sc) { + VOS_TRACE( VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, "%s: sc is NULL", + __func__); + return; +} + + switch (hif_type) { + case HIF_TYPE_AR9888: + sc->hostdef = &ar9888_hostdef; + break; + case HIF_TYPE_AR6320: + sc->hostdef = &ar6320_hostdef; + break; + case HIF_TYPE_AR6320V2: + sc->hostdef = &ar6320v2_hostdef; + break; + default: + break; + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.h new file mode 100644 index 000000000000..6c6b4df3d172 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/regtable.h @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#ifndef _REGTABLE_H_ +#define _REGTABLE_H_ +//#include "if_usb.h" + +#define MISSING 0 +extern struct ath_hif_sdio_softc *sc; + +typedef struct targetdef_s { + u_int32_t d_RTC_SOC_BASE_ADDRESS; + u_int32_t d_RTC_WMAC_BASE_ADDRESS; + u_int32_t d_SYSTEM_SLEEP_OFFSET; + u_int32_t d_WLAN_SYSTEM_SLEEP_OFFSET; + u_int32_t d_WLAN_SYSTEM_SLEEP_DISABLE_LSB; + u_int32_t d_WLAN_SYSTEM_SLEEP_DISABLE_MASK; + u_int32_t d_CLOCK_CONTROL_OFFSET; + u_int32_t d_CLOCK_CONTROL_SI0_CLK_MASK; + u_int32_t d_RESET_CONTROL_OFFSET; + u_int32_t d_RESET_CONTROL_MBOX_RST_MASK; + u_int32_t d_RESET_CONTROL_SI0_RST_MASK; + u_int32_t d_WLAN_RESET_CONTROL_OFFSET; + u_int32_t d_WLAN_RESET_CONTROL_COLD_RST_MASK; + u_int32_t d_WLAN_RESET_CONTROL_WARM_RST_MASK; + u_int32_t d_GPIO_BASE_ADDRESS; + u_int32_t d_GPIO_PIN0_OFFSET; + u_int32_t d_GPIO_PIN1_OFFSET; + u_int32_t d_GPIO_PIN0_CONFIG_MASK; + u_int32_t d_GPIO_PIN1_CONFIG_MASK; + u_int32_t d_SI_CONFIG_BIDIR_OD_DATA_LSB; + u_int32_t d_SI_CONFIG_BIDIR_OD_DATA_MASK; + u_int32_t d_SI_CONFIG_I2C_LSB; + u_int32_t d_SI_CONFIG_I2C_MASK; + u_int32_t d_SI_CONFIG_POS_SAMPLE_LSB; + u_int32_t d_SI_CONFIG_POS_SAMPLE_MASK; + u_int32_t d_SI_CONFIG_INACTIVE_CLK_LSB; + u_int32_t d_SI_CONFIG_INACTIVE_CLK_MASK; + u_int32_t d_SI_CONFIG_INACTIVE_DATA_LSB; + u_int32_t d_SI_CONFIG_INACTIVE_DATA_MASK; + u_int32_t d_SI_CONFIG_DIVIDER_LSB; + u_int32_t d_SI_CONFIG_DIVIDER_MASK; + u_int32_t d_SI_BASE_ADDRESS; + u_int32_t d_SI_CONFIG_OFFSET; + u_int32_t d_SI_TX_DATA0_OFFSET; + u_int32_t d_SI_TX_DATA1_OFFSET; + u_int32_t d_SI_RX_DATA0_OFFSET; + u_int32_t d_SI_RX_DATA1_OFFSET; + u_int32_t d_SI_CS_OFFSET; + u_int32_t d_SI_CS_DONE_ERR_MASK; + u_int32_t d_SI_CS_DONE_INT_MASK; + u_int32_t d_SI_CS_START_LSB; + u_int32_t d_SI_CS_START_MASK; + u_int32_t d_SI_CS_RX_CNT_LSB; + u_int32_t d_SI_CS_RX_CNT_MASK; + u_int32_t d_SI_CS_TX_CNT_LSB; + u_int32_t d_SI_CS_TX_CNT_MASK; + u_int32_t d_BOARD_DATA_SZ; + u_int32_t d_BOARD_EXT_DATA_SZ; + u_int32_t d_MBOX_BASE_ADDRESS; + u_int32_t d_LOCAL_SCRATCH_OFFSET; + u_int32_t d_CPU_CLOCK_OFFSET; + u_int32_t d_LPO_CAL_OFFSET; + u_int32_t d_GPIO_PIN10_OFFSET; + u_int32_t d_GPIO_PIN11_OFFSET; + u_int32_t d_GPIO_PIN12_OFFSET; + u_int32_t d_GPIO_PIN13_OFFSET; + u_int32_t d_CLOCK_GPIO_OFFSET; + u_int32_t d_CPU_CLOCK_STANDARD_LSB; + u_int32_t d_CPU_CLOCK_STANDARD_MASK; + u_int32_t d_LPO_CAL_ENABLE_LSB; + u_int32_t d_LPO_CAL_ENABLE_MASK; + u_int32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB; + u_int32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK; + u_int32_t d_ANALOG_INTF_BASE_ADDRESS; + u_int32_t d_WLAN_MAC_BASE_ADDRESS; + u_int32_t d_CE0_BASE_ADDRESS; + u_int32_t d_CE1_BASE_ADDRESS; + u_int32_t d_FW_INDICATOR_ADDRESS; + u_int32_t d_DRAM_BASE_ADDRESS; + u_int32_t d_SOC_CORE_BASE_ADDRESS; + u_int32_t d_CORE_CTRL_ADDRESS; + u_int32_t d_CE_COUNT; + u_int32_t d_MSI_NUM_REQUEST; + u_int32_t d_MSI_ASSIGN_FW; + u_int32_t d_MSI_ASSIGN_CE_INITIAL; + u_int32_t d_PCIE_INTR_ENABLE_ADDRESS; + u_int32_t d_PCIE_INTR_CLR_ADDRESS; + u_int32_t d_PCIE_INTR_FIRMWARE_MASK; + u_int32_t d_PCIE_INTR_CE_MASK_ALL; + u_int32_t d_CORE_CTRL_CPU_INTR_MASK; + u_int32_t d_SR_WR_INDEX_ADDRESS; + u_int32_t d_DST_WATERMARK_ADDRESS; + + /* htt_rx.c */ + u_int32_t d_RX_MSDU_END_4_FIRST_MSDU_MASK; + u_int32_t d_RX_MSDU_END_4_FIRST_MSDU_LSB; + u_int32_t d_RX_MPDU_START_0_RETRY_LSB; + u_int32_t d_RX_MPDU_START_0_RETRY_MASK; + u_int32_t d_RX_MPDU_START_0_SEQ_NUM_MASK; + u_int32_t d_RX_MPDU_START_0_SEQ_NUM_LSB; + u_int32_t d_RX_MPDU_START_2_PN_47_32_LSB; + u_int32_t d_RX_MPDU_START_2_PN_47_32_MASK; + u_int32_t d_RX_MPDU_START_2_TID_LSB; + u_int32_t d_RX_MPDU_START_2_TID_MASK; + u_int32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK; + u_int32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB; + u_int32_t d_RX_MSDU_END_1_KEY_ID_OCT_MASK; + u_int32_t d_RX_MSDU_END_1_KEY_ID_OCT_LSB; + u_int32_t d_RX_MSDU_END_4_LAST_MSDU_MASK; + u_int32_t d_RX_MSDU_END_4_LAST_MSDU_LSB; + u_int32_t d_RX_ATTENTION_0_MCAST_BCAST_MASK; + u_int32_t d_RX_ATTENTION_0_MCAST_BCAST_LSB; + u_int32_t d_RX_ATTENTION_0_FRAGMENT_MASK; + u_int32_t d_RX_ATTENTION_0_FRAGMENT_LSB; + u_int32_t d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK; + u_int32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK; + u_int32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB; + u_int32_t d_RX_MSDU_START_0_MSDU_LENGTH_MASK; + u_int32_t d_RX_MSDU_START_0_MSDU_LENGTH_LSB; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_MASK; + u_int32_t d_RX_MSDU_START_2_DECAP_FORMAT_LSB; + u_int32_t d_RX_MPDU_START_0_ENCRYPTED_MASK; + u_int32_t d_RX_MPDU_START_0_ENCRYPTED_LSB; + u_int32_t d_RX_ATTENTION_0_MORE_DATA_MASK; + u_int32_t d_RX_ATTENTION_0_MSDU_DONE_MASK; + u_int32_t d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK; + /* end */ + /* copy_engine.c */ + u_int32_t d_DST_WR_INDEX_ADDRESS; + u_int32_t d_SRC_WATERMARK_ADDRESS; + u_int32_t d_SRC_WATERMARK_LOW_MASK; + u_int32_t d_SRC_WATERMARK_HIGH_MASK; + u_int32_t d_DST_WATERMARK_LOW_MASK; + u_int32_t d_DST_WATERMARK_HIGH_MASK; + u_int32_t d_CURRENT_SRRI_ADDRESS; + u_int32_t d_CURRENT_DRRI_ADDRESS; + u_int32_t d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK; + u_int32_t d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK; + u_int32_t d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK; + u_int32_t d_HOST_IS_DST_RING_LOW_WATERMARK_MASK; + u_int32_t d_HOST_IS_ADDRESS; + u_int32_t d_HOST_IS_COPY_COMPLETE_MASK; + u_int32_t d_CE_WRAPPER_BASE_ADDRESS; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS; + u_int32_t d_HOST_IE_ADDRESS; + u_int32_t d_HOST_IE_COPY_COMPLETE_MASK; + u_int32_t d_SR_BA_ADDRESS; + u_int32_t d_SR_SIZE_ADDRESS; + u_int32_t d_CE_CTRL1_ADDRESS; + u_int32_t d_CE_CTRL1_DMAX_LENGTH_MASK; + u_int32_t d_DR_BA_ADDRESS; + u_int32_t d_DR_SIZE_ADDRESS; + u_int32_t d_MISC_IE_ADDRESS; + u_int32_t d_MISC_IS_AXI_ERR_MASK; + u_int32_t d_MISC_IS_DST_ADDR_ERR_MASK; + u_int32_t d_MISC_IS_SRC_LEN_ERR_MASK; + u_int32_t d_MISC_IS_DST_MAX_LEN_VIO_MASK; + u_int32_t d_MISC_IS_DST_RING_OVERFLOW_MASK; + u_int32_t d_MISC_IS_SRC_RING_OVERFLOW_MASK; + u_int32_t d_SRC_WATERMARK_LOW_LSB; + u_int32_t d_SRC_WATERMARK_HIGH_LSB; + u_int32_t d_DST_WATERMARK_LOW_LSB; + u_int32_t d_DST_WATERMARK_HIGH_LSB; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK; + u_int32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB; + u_int32_t d_CE_CTRL1_DMAX_LENGTH_LSB; + u_int32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK; + u_int32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK; + u_int32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB; + u_int32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB; + /* end */ + /* PLL start */ + u_int32_t d_EFUSE_OFFSET; + u_int32_t d_EFUSE_XTAL_SEL_MSB; + u_int32_t d_EFUSE_XTAL_SEL_LSB; + u_int32_t d_EFUSE_XTAL_SEL_MASK; + u_int32_t d_BB_PLL_CONFIG_OFFSET; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_MSB; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_LSB; + u_int32_t d_BB_PLL_CONFIG_OUTDIV_MASK; + u_int32_t d_BB_PLL_CONFIG_FRAC_MSB; + u_int32_t d_BB_PLL_CONFIG_FRAC_LSB; + u_int32_t d_BB_PLL_CONFIG_FRAC_MASK; + u_int32_t d_WLAN_PLL_SETTLE_TIME_MSB; + u_int32_t d_WLAN_PLL_SETTLE_TIME_LSB; + u_int32_t d_WLAN_PLL_SETTLE_TIME_MASK; + u_int32_t d_WLAN_PLL_SETTLE_OFFSET; + u_int32_t d_WLAN_PLL_SETTLE_SW_MASK; + u_int32_t d_WLAN_PLL_SETTLE_RSTMASK; + u_int32_t d_WLAN_PLL_SETTLE_RESET; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_MSB; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_LSB; + u_int32_t d_WLAN_PLL_CONTROL_NOPWD_MASK; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_MSB; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_LSB; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_MASK; + u_int32_t d_WLAN_PLL_CONTROL_BYPASS_RESET; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_MSB; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_LSB; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_MASK; + u_int32_t d_WLAN_PLL_CONTROL_CLK_SEL_RESET; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_MSB; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_LSB; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_MASK; + u_int32_t d_WLAN_PLL_CONTROL_REFDIV_RESET; + u_int32_t d_WLAN_PLL_CONTROL_DIV_MSB; + u_int32_t d_WLAN_PLL_CONTROL_DIV_LSB; + u_int32_t d_WLAN_PLL_CONTROL_DIV_MASK; + u_int32_t d_WLAN_PLL_CONTROL_DIV_RESET; + u_int32_t d_WLAN_PLL_CONTROL_OFFSET; + u_int32_t d_WLAN_PLL_CONTROL_SW_MASK; + u_int32_t d_WLAN_PLL_CONTROL_RSTMASK; + u_int32_t d_WLAN_PLL_CONTROL_RESET; + u_int32_t d_SOC_CORE_CLK_CTRL_OFFSET; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_MSB; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_LSB; + u_int32_t d_SOC_CORE_CLK_CTRL_DIV_MASK; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MSB; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_LSB; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MASK; + u_int32_t d_RTC_SYNC_STATUS_PLL_CHANGING_RESET; + u_int32_t d_RTC_SYNC_STATUS_OFFSET; + u_int32_t d_SOC_CPU_CLOCK_OFFSET; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_MSB; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_LSB; + u_int32_t d_SOC_CPU_CLOCK_STANDARD_MASK; + /* PLL end */ + u_int32_t d_PCIE_INTR_CAUSE_ADDRESS; + u_int32_t d_SOC_RESET_CONTROL_ADDRESS; + u_int32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK; + u_int32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB; + u_int32_t d_SOC_RESET_CONTROL_CE_RST_MASK; + u_int32_t d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK; + u_int32_t d_CPU_INTR_ADDRESS; + u_int32_t d_SOC_LF_TIMER_CONTROL0_ADDRESS; + u_int32_t d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK; + /* chip id start */ + u_int32_t d_SOC_CHIP_ID_ADDRESS; + u_int32_t d_SOC_CHIP_ID_VERSION_MASK; + u_int32_t d_SOC_CHIP_ID_VERSION_LSB; + u_int32_t d_SOC_CHIP_ID_REVISION_MASK; + u_int32_t d_SOC_CHIP_ID_REVISION_LSB; + /* chip id end */ +} TARGET_REGISTER_TABLE; + +#define RTC_SOC_BASE_ADDRESS (sc->targetdef->d_RTC_SOC_BASE_ADDRESS) +#define RTC_WMAC_BASE_ADDRESS (sc->targetdef->d_RTC_WMAC_BASE_ADDRESS) +#define SYSTEM_SLEEP_OFFSET (sc->targetdef->d_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_OFFSET (sc->targetdef->d_WLAN_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB (sc->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK (sc->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define CLOCK_CONTROL_OFFSET (sc->targetdef->d_CLOCK_CONTROL_OFFSET) +#define CLOCK_CONTROL_SI0_CLK_MASK (sc->targetdef->d_CLOCK_CONTROL_SI0_CLK_MASK) +#define RESET_CONTROL_OFFSET (sc->targetdef->d_RESET_CONTROL_OFFSET) +#define RESET_CONTROL_MBOX_RST_MASK (sc->targetdef->d_RESET_CONTROL_MBOX_RST_MASK) +#define RESET_CONTROL_SI0_RST_MASK (sc->targetdef->d_RESET_CONTROL_SI0_RST_MASK) +#define WLAN_RESET_CONTROL_OFFSET (sc->targetdef->d_WLAN_RESET_CONTROL_OFFSET) +#define WLAN_RESET_CONTROL_COLD_RST_MASK (sc->targetdef->d_WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MASK (sc->targetdef->d_WLAN_RESET_CONTROL_WARM_RST_MASK) +#define GPIO_BASE_ADDRESS (sc->targetdef->d_GPIO_BASE_ADDRESS) +#define GPIO_PIN0_OFFSET (sc->targetdef->d_GPIO_PIN0_OFFSET) +#define GPIO_PIN1_OFFSET (sc->targetdef->d_GPIO_PIN1_OFFSET) +#define GPIO_PIN0_CONFIG_MASK (sc->targetdef->d_GPIO_PIN0_CONFIG_MASK) +#define GPIO_PIN1_CONFIG_MASK (sc->targetdef->d_GPIO_PIN1_CONFIG_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_LSB (sc->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_LSB) +#define SI_CONFIG_BIDIR_OD_DATA_MASK (sc->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_LSB (sc->targetdef->d_SI_CONFIG_I2C_LSB) +#define SI_CONFIG_I2C_MASK (sc->targetdef->d_SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_LSB (sc->targetdef->d_SI_CONFIG_POS_SAMPLE_LSB) +#define SI_CONFIG_POS_SAMPLE_MASK (sc->targetdef->d_SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_LSB (sc->targetdef->d_SI_CONFIG_INACTIVE_CLK_LSB) +#define SI_CONFIG_INACTIVE_CLK_MASK (sc->targetdef->d_SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_LSB (sc->targetdef->d_SI_CONFIG_INACTIVE_DATA_LSB) +#define SI_CONFIG_INACTIVE_DATA_MASK (sc->targetdef->d_SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_LSB (sc->targetdef->d_SI_CONFIG_DIVIDER_LSB) +#define SI_CONFIG_DIVIDER_MASK (sc->targetdef->d_SI_CONFIG_DIVIDER_MASK) +#define SI_BASE_ADDRESS (sc->targetdef->d_SI_BASE_ADDRESS) +#define SI_CONFIG_OFFSET (sc->targetdef->d_SI_CONFIG_OFFSET) +#define SI_TX_DATA0_OFFSET (sc->targetdef->d_SI_TX_DATA0_OFFSET) +#define SI_TX_DATA1_OFFSET (sc->targetdef->d_SI_TX_DATA1_OFFSET) +#define SI_RX_DATA0_OFFSET (sc->targetdef->d_SI_RX_DATA0_OFFSET) +#define SI_RX_DATA1_OFFSET (sc->targetdef->d_SI_RX_DATA1_OFFSET) +#define SI_CS_OFFSET (sc->targetdef->d_SI_CS_OFFSET) +#define SI_CS_DONE_ERR_MASK (sc->targetdef->d_SI_CS_DONE_ERR_MASK) +#define SI_CS_DONE_INT_MASK (sc->targetdef->d_SI_CS_DONE_INT_MASK) +#define SI_CS_START_LSB (sc->targetdef->d_SI_CS_START_LSB) +#define SI_CS_START_MASK (sc->targetdef->d_SI_CS_START_MASK) +#define SI_CS_RX_CNT_LSB (sc->targetdef->d_SI_CS_RX_CNT_LSB) +#define SI_CS_RX_CNT_MASK (sc->targetdef->d_SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_LSB (sc->targetdef->d_SI_CS_TX_CNT_LSB) +#define SI_CS_TX_CNT_MASK (sc->targetdef->d_SI_CS_TX_CNT_MASK) +#define EEPROM_SZ (sc->targetdef->d_BOARD_DATA_SZ) +#define EEPROM_EXT_SZ (sc->targetdef->d_BOARD_EXT_DATA_SZ) +#define MBOX_BASE_ADDRESS (sc->targetdef->d_MBOX_BASE_ADDRESS) +#define LOCAL_SCRATCH_OFFSET (sc->targetdef->d_LOCAL_SCRATCH_OFFSET) +#define CPU_CLOCK_OFFSET (sc->targetdef->d_CPU_CLOCK_OFFSET) +#define LPO_CAL_OFFSET (sc->targetdef->d_LPO_CAL_OFFSET) +#define GPIO_PIN10_OFFSET (sc->targetdef->d_GPIO_PIN10_OFFSET) +#define GPIO_PIN11_OFFSET (sc->targetdef->d_GPIO_PIN11_OFFSET) +#define GPIO_PIN12_OFFSET (sc->targetdef->d_GPIO_PIN12_OFFSET) +#define GPIO_PIN13_OFFSET (sc->targetdef->d_GPIO_PIN13_OFFSET) +#define CLOCK_GPIO_OFFSET (sc->targetdef->d_CLOCK_GPIO_OFFSET) +#define CPU_CLOCK_STANDARD_LSB (sc->targetdef->d_CPU_CLOCK_STANDARD_LSB) +#define CPU_CLOCK_STANDARD_MASK (sc->targetdef->d_CPU_CLOCK_STANDARD_MASK) +#define LPO_CAL_ENABLE_LSB (sc->targetdef->d_LPO_CAL_ENABLE_LSB) +#define LPO_CAL_ENABLE_MASK (sc->targetdef->d_LPO_CAL_ENABLE_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB (sc->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB) +#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK (sc->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +#define ANALOG_INTF_BASE_ADDRESS (sc->targetdef->d_ANALOG_INTF_BASE_ADDRESS) +#define WLAN_MAC_BASE_ADDRESS (sc->targetdef->d_WLAN_MAC_BASE_ADDRESS) +#define CE0_BASE_ADDRESS (sc->targetdef->d_CE0_BASE_ADDRESS) +#define CE1_BASE_ADDRESS (sc->targetdef->d_CE1_BASE_ADDRESS) +#define FW_INDICATOR_ADDRESS (sc->targetdef->d_FW_INDICATOR_ADDRESS) +#define DRAM_BASE_ADDRESS (sc->targetdef->d_DRAM_BASE_ADDRESS) +#define SOC_CORE_BASE_ADDRESS (sc->targetdef->d_SOC_CORE_BASE_ADDRESS) +#define CORE_CTRL_ADDRESS (sc->targetdef->d_CORE_CTRL_ADDRESS) +#define CE_COUNT (sc->targetdef->d_CE_COUNT) +#define PCIE_INTR_ENABLE_ADDRESS (sc->targetdef->d_PCIE_INTR_ENABLE_ADDRESS) +#define PCIE_INTR_CLR_ADDRESS (sc->targetdef->d_PCIE_INTR_CLR_ADDRESS) +#define PCIE_INTR_FIRMWARE_MASK (sc->targetdef->d_PCIE_INTR_FIRMWARE_MASK) +#define PCIE_INTR_CE_MASK_ALL (sc->targetdef->d_PCIE_INTR_CE_MASK_ALL) +#define CORE_CTRL_CPU_INTR_MASK (sc->targetdef->d_CORE_CTRL_CPU_INTR_MASK) +#define PCIE_INTR_CAUSE_ADDRESS (sc->targetdef->d_PCIE_INTR_CAUSE_ADDRESS) +#define SOC_RESET_CONTROL_ADDRESS (sc->targetdef->d_SOC_RESET_CONTROL_ADDRESS) +#define SOC_RESET_CONTROL_CE_RST_MASK (sc->targetdef->d_SOC_RESET_CONTROL_CE_RST_MASK) +#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK (sc->targetdef->d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK) +#define CPU_INTR_ADDRESS (sc->targetdef->d_CPU_INTR_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ADDRESS (sc->targetdef->d_SOC_LF_TIMER_CONTROL0_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK (sc->targetdef->d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB (sc->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK (sc->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_GET(x) (((x) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) >> SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_SET(x) (((x) << SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +/* hif_pci.c */ +#define CHIP_ID_ADDRESS (sc->targetdef->d_SOC_CHIP_ID_ADDRESS) +#define SOC_CHIP_ID_REVISION_MASK (sc->targetdef->d_SOC_CHIP_ID_REVISION_MASK) +#define SOC_CHIP_ID_REVISION_LSB (sc->targetdef->d_SOC_CHIP_ID_REVISION_LSB) +#define SOC_CHIP_ID_VERSION_MASK (sc->targetdef->d_SOC_CHIP_ID_VERSION_MASK) +#define SOC_CHIP_ID_VERSION_LSB (sc->targetdef->d_SOC_CHIP_ID_VERSION_LSB) +#define CHIP_ID_REVISION_GET(x) (((x) & SOC_CHIP_ID_REVISION_MASK) >> SOC_CHIP_ID_REVISION_LSB) +#define CHIP_ID_VERSION_GET(x) (((x) & SOC_CHIP_ID_VERSION_MASK) >> SOC_CHIP_ID_VERSION_LSB) +/* hif_pci.c end */ + +/* misc */ +#define SR_WR_INDEX_ADDRESS (sc->targetdef->d_SR_WR_INDEX_ADDRESS) +#define DST_WATERMARK_ADDRESS (sc->targetdef->d_DST_WATERMARK_ADDRESS) +/* end */ + +/* htt_rx.c */ +#define RX_MSDU_END_4_FIRST_MSDU_MASK (pdev->targetdef->d_RX_MSDU_END_4_FIRST_MSDU_MASK) +#define RX_MSDU_END_4_FIRST_MSDU_LSB (pdev->targetdef->d_RX_MSDU_END_4_FIRST_MSDU_LSB) +#define RX_MPDU_START_0_RETRY_LSB (pdev->targetdef->d_RX_MPDU_START_0_RETRY_LSB) +#define RX_MPDU_START_0_RETRY_MASK (pdev->targetdef->d_RX_MPDU_START_0_RETRY_MASK) +#define RX_MPDU_START_0_SEQ_NUM_MASK (pdev->targetdef->d_RX_MPDU_START_0_SEQ_NUM_MASK) +#define RX_MPDU_START_0_SEQ_NUM_LSB (pdev->targetdef->d_RX_MPDU_START_0_SEQ_NUM_LSB) +#define RX_MPDU_START_2_PN_47_32_LSB (pdev->targetdef->d_RX_MPDU_START_2_PN_47_32_LSB) +#define RX_MPDU_START_2_PN_47_32_MASK (pdev->targetdef->d_RX_MPDU_START_2_PN_47_32_MASK) +#define RX_MPDU_START_2_TID_LSB (pdev->targetdef->d_RX_MPDU_START_2_TID_LSB) +#define RX_MPDU_START_2_TID_MASK (pdev->targetdef->d_RX_MPDU_START_2_TID_MASK) +#define RX_MSDU_END_1_KEY_ID_OCT_MASK (pdev->targetdef->d_RX_MSDU_END_1_KEY_ID_OCT_MASK) +#define RX_MSDU_END_1_KEY_ID_OCT_LSB (pdev->targetdef->d_RX_MSDU_END_1_KEY_ID_OCT_LSB) +#define RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK (pdev->targetdef->d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK) +#define RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB (pdev->targetdef->d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB) +#define RX_MSDU_END_4_LAST_MSDU_MASK (pdev->targetdef->d_RX_MSDU_END_4_LAST_MSDU_MASK) +#define RX_MSDU_END_4_LAST_MSDU_LSB (pdev->targetdef->d_RX_MSDU_END_4_LAST_MSDU_LSB) +#define RX_ATTENTION_0_MCAST_BCAST_MASK (pdev->targetdef->d_RX_ATTENTION_0_MCAST_BCAST_MASK) +#define RX_ATTENTION_0_MCAST_BCAST_LSB (pdev->targetdef->d_RX_ATTENTION_0_MCAST_BCAST_LSB) +#define RX_ATTENTION_0_FRAGMENT_MASK (pdev->targetdef->d_RX_ATTENTION_0_FRAGMENT_MASK) +#define RX_ATTENTION_0_FRAGMENT_LSB (pdev->targetdef->d_RX_ATTENTION_0_FRAGMENT_LSB) +#define RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK (pdev->targetdef->d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK) +#define RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK (pdev->targetdef->d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK) +#define RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB (pdev->targetdef->d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB) +#define RX_MSDU_START_0_MSDU_LENGTH_MASK (pdev->targetdef->d_RX_MSDU_START_0_MSDU_LENGTH_MASK) +#define RX_MSDU_START_0_MSDU_LENGTH_LSB (pdev->targetdef->d_RX_MSDU_START_0_MSDU_LENGTH_LSB) +#define RX_MSDU_START_2_DECAP_FORMAT_OFFSET (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET) +#define RX_MSDU_START_2_DECAP_FORMAT_MASK (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_MASK) +#define RX_MSDU_START_2_DECAP_FORMAT_LSB (pdev->targetdef->d_RX_MSDU_START_2_DECAP_FORMAT_LSB) +#define RX_MPDU_START_0_ENCRYPTED_MASK (pdev->targetdef->d_RX_MPDU_START_0_ENCRYPTED_MASK) +#define RX_MPDU_START_0_ENCRYPTED_LSB (pdev->targetdef->d_RX_MPDU_START_0_ENCRYPTED_LSB) +#define RX_ATTENTION_0_MORE_DATA_MASK (pdev->targetdef->d_RX_ATTENTION_0_MORE_DATA_MASK) +#define RX_ATTENTION_0_MSDU_DONE_MASK (pdev->targetdef->d_RX_ATTENTION_0_MSDU_DONE_MASK) +#define RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK (pdev->targetdef->d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK) +/* end */ + +/* copy_engine.c */ +#define DST_WR_INDEX_ADDRESS (sc->targetdef->d_DST_WR_INDEX_ADDRESS) +#define SRC_WATERMARK_ADDRESS (sc->targetdef->d_SRC_WATERMARK_ADDRESS) +#define SRC_WATERMARK_LOW_MASK (sc->targetdef->d_SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_MASK (sc->targetdef->d_SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_MASK (sc->targetdef->d_DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_MASK (sc->targetdef->d_DST_WATERMARK_HIGH_MASK) +#define CURRENT_SRRI_ADDRESS (sc->targetdef->d_CURRENT_SRRI_ADDRESS) +#define CURRENT_DRRI_ADDRESS (sc->targetdef->d_CURRENT_DRRI_ADDRESS) +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK (sc->targetdef->d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK (sc->targetdef->d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK) +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK (sc->targetdef->d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK (sc->targetdef->d_HOST_IS_DST_RING_LOW_WATERMARK_MASK) +#define HOST_IS_ADDRESS (sc->targetdef->d_HOST_IS_ADDRESS) +#define HOST_IS_COPY_COMPLETE_MASK (sc->targetdef->d_HOST_IS_COPY_COMPLETE_MASK) +#define CE_WRAPPER_BASE_ADDRESS (sc->targetdef->d_CE_WRAPPER_BASE_ADDRESS) +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS) +#define HOST_IE_ADDRESS (sc->targetdef->d_HOST_IE_ADDRESS) +#define HOST_IE_COPY_COMPLETE_MASK (sc->targetdef->d_HOST_IE_COPY_COMPLETE_MASK) +#define SR_BA_ADDRESS (sc->targetdef->d_SR_BA_ADDRESS) +#define SR_SIZE_ADDRESS (sc->targetdef->d_SR_SIZE_ADDRESS) +#define CE_CTRL1_ADDRESS (sc->targetdef->d_CE_CTRL1_ADDRESS) +#define CE_CTRL1_DMAX_LENGTH_MASK (sc->targetdef->d_CE_CTRL1_DMAX_LENGTH_MASK) +#define DR_BA_ADDRESS (sc->targetdef->d_DR_BA_ADDRESS) +#define DR_SIZE_ADDRESS (sc->targetdef->d_DR_SIZE_ADDRESS) +#define MISC_IE_ADDRESS (sc->targetdef->d_MISC_IE_ADDRESS) +#define MISC_IS_AXI_ERR_MASK (sc->targetdef->d_MISC_IS_AXI_ERR_MASK) +#define MISC_IS_DST_ADDR_ERR_MASK (sc->targetdef->d_MISC_IS_DST_ADDR_ERR_MASK) +#define MISC_IS_SRC_LEN_ERR_MASK (sc->targetdef->d_MISC_IS_SRC_LEN_ERR_MASK) +#define MISC_IS_DST_MAX_LEN_VIO_MASK (sc->targetdef->d_MISC_IS_DST_MAX_LEN_VIO_MASK) +#define MISC_IS_DST_RING_OVERFLOW_MASK (sc->targetdef->d_MISC_IS_DST_RING_OVERFLOW_MASK) +#define MISC_IS_SRC_RING_OVERFLOW_MASK (sc->targetdef->d_MISC_IS_SRC_RING_OVERFLOW_MASK) +#define SRC_WATERMARK_LOW_LSB (sc->targetdef->d_SRC_WATERMARK_LOW_LSB) +#define SRC_WATERMARK_HIGH_LSB (sc->targetdef->d_SRC_WATERMARK_HIGH_LSB) +#define DST_WATERMARK_LOW_LSB (sc->targetdef->d_DST_WATERMARK_LOW_LSB) +#define DST_WATERMARK_HIGH_LSB (sc->targetdef->d_DST_WATERMARK_HIGH_LSB) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB (sc->targetdef->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_LSB (sc->targetdef->d_CE_CTRL1_DMAX_LENGTH_LSB) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK (sc->targetdef->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK (sc->targetdef->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB (sc->targetdef->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB (sc->targetdef->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) +/* end */ +/* PLL start */ +#define EFUSE_OFFSET (sc->targetdef->d_EFUSE_OFFSET) +#define EFUSE_XTAL_SEL_MSB (sc->targetdef->d_EFUSE_XTAL_SEL_MSB) +#define EFUSE_XTAL_SEL_LSB (sc->targetdef->d_EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_MASK (sc->targetdef->d_EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OFFSET (sc->targetdef->d_BB_PLL_CONFIG_OFFSET) +#define BB_PLL_CONFIG_OUTDIV_MSB (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_MSB) +#define BB_PLL_CONFIG_OUTDIV_LSB (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_MASK (sc->targetdef->d_BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_MSB (sc->targetdef->d_BB_PLL_CONFIG_FRAC_MSB) +#define BB_PLL_CONFIG_FRAC_LSB (sc->targetdef->d_BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_MASK (sc->targetdef->d_BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_MSB (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_MSB) +#define WLAN_PLL_SETTLE_TIME_LSB (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_MASK (sc->targetdef->d_WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_SETTLE_OFFSET (sc->targetdef->d_WLAN_PLL_SETTLE_OFFSET) +#define WLAN_PLL_SETTLE_SW_MASK (sc->targetdef->d_WLAN_PLL_SETTLE_SW_MASK) +#define WLAN_PLL_SETTLE_RSTMASK (sc->targetdef->d_WLAN_PLL_SETTLE_RSTMASK) +#define WLAN_PLL_SETTLE_RESET (sc->targetdef->d_WLAN_PLL_SETTLE_RESET) +#define WLAN_PLL_CONTROL_NOPWD_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MSB) +#define WLAN_PLL_CONTROL_NOPWD_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MSB) +#define WLAN_PLL_CONTROL_BYPASS_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_BYPASS_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_BYPASS_RESET) +#define WLAN_PLL_CONTROL_CLK_SEL_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MSB) +#define WLAN_PLL_CONTROL_CLK_SEL_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_RESET) +#define WLAN_PLL_CONTROL_REFDIV_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MSB) +#define WLAN_PLL_CONTROL_REFDIV_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_REFDIV_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_REFDIV_RESET) +#define WLAN_PLL_CONTROL_DIV_MSB (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_MSB) +#define WLAN_PLL_CONTROL_DIV_LSB (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_MASK) +#define WLAN_PLL_CONTROL_DIV_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_DIV_RESET) +#define WLAN_PLL_CONTROL_OFFSET (sc->targetdef->d_WLAN_PLL_CONTROL_OFFSET) +#define WLAN_PLL_CONTROL_SW_MASK (sc->targetdef->d_WLAN_PLL_CONTROL_SW_MASK) +#define WLAN_PLL_CONTROL_RSTMASK (sc->targetdef->d_WLAN_PLL_CONTROL_RSTMASK) +#define WLAN_PLL_CONTROL_RESET (sc->targetdef->d_WLAN_PLL_CONTROL_RESET) +#define SOC_CORE_CLK_CTRL_OFFSET (sc->targetdef->d_SOC_CORE_CLK_CTRL_OFFSET) +#define SOC_CORE_CLK_CTRL_DIV_MSB (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MSB) +#define SOC_CORE_CLK_CTRL_DIV_LSB (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_MASK (sc->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_MSB (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_LSB (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_MASK (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_RESET (sc->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_RESET) +#define RTC_SYNC_STATUS_OFFSET (sc->targetdef->d_RTC_SYNC_STATUS_OFFSET) +#define SOC_CPU_CLOCK_OFFSET (sc->targetdef->d_SOC_CPU_CLOCK_OFFSET) +#define SOC_CPU_CLOCK_STANDARD_MSB (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_MSB) +#define SOC_CPU_CLOCK_STANDARD_LSB (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_MASK (sc->targetdef->d_SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +/* SET macros */ +#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_SET(x) (((x) << SI_CONFIG_BIDIR_OD_DATA_LSB) & SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_SET(x) (((x) << SI_CONFIG_I2C_LSB) & SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_SET(x) (((x) << SI_CONFIG_POS_SAMPLE_LSB) & SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_SET(x) (((x) << SI_CONFIG_INACTIVE_CLK_LSB) & SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_SET(x) (((x) << SI_CONFIG_INACTIVE_DATA_LSB) & SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_SET(x) (((x) << SI_CONFIG_DIVIDER_LSB) & SI_CONFIG_DIVIDER_MASK) +#define SI_CS_START_SET(x) (((x) << SI_CS_START_LSB) & SI_CS_START_MASK) +#define SI_CS_RX_CNT_SET(x) (((x) << SI_CS_RX_CNT_LSB) & SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_SET(x) (((x) << SI_CS_TX_CNT_LSB) & SI_CS_TX_CNT_MASK) +#define LPO_CAL_ENABLE_SET(x) (((x) << LPO_CAL_ENABLE_LSB) & LPO_CAL_ENABLE_MASK) +#define CPU_CLOCK_STANDARD_SET(x) (((x) << CPU_CLOCK_STANDARD_LSB) & CPU_CLOCK_STANDARD_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_SET(x) (((x) << CLOCK_GPIO_BT_CLK_OUT_EN_LSB) & CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +/* copy_engine.c */ +#define SRC_WATERMARK_LOW_SET(x) (((x) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_SET(x) (((x) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_SET(x) (((x) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_SET(x) (((x) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_SET(x) (((x) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) (((x) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) (((x) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +/* end */ +/* PLL start */ +#define EFUSE_XTAL_SEL_GET(x) (((x) & EFUSE_XTAL_SEL_MASK) >> EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_SET(x) (((x) << EFUSE_XTAL_SEL_LSB) & EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OUTDIV_GET(x) (((x) & BB_PLL_CONFIG_OUTDIV_MASK) >> BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_SET(x) (((x) << BB_PLL_CONFIG_OUTDIV_LSB) & BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_GET(x) (((x) & BB_PLL_CONFIG_FRAC_MASK) >> BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_SET(x) (((x) << BB_PLL_CONFIG_FRAC_LSB) & BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_GET(x) (((x) & WLAN_PLL_SETTLE_TIME_MASK) >> WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_SET(x) (((x) << WLAN_PLL_SETTLE_TIME_LSB) & WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_CONTROL_NOPWD_GET(x) (((x) & WLAN_PLL_CONTROL_NOPWD_MASK) >> WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_SET(x) (((x) << WLAN_PLL_CONTROL_NOPWD_LSB) & WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_GET(x) (((x) & WLAN_PLL_CONTROL_BYPASS_MASK) >> WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_SET(x) (((x) << WLAN_PLL_CONTROL_BYPASS_LSB) & WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_GET(x) (((x) & WLAN_PLL_CONTROL_CLK_SEL_MASK) >> WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_SET(x) (((x) << WLAN_PLL_CONTROL_CLK_SEL_LSB) & WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_REFDIV_GET(x) (((x) & WLAN_PLL_CONTROL_REFDIV_MASK) >> WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_SET(x) (((x) << WLAN_PLL_CONTROL_REFDIV_LSB) & WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_DIV_GET(x) (((x) & WLAN_PLL_CONTROL_DIV_MASK) >> WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_SET(x) (((x) << WLAN_PLL_CONTROL_DIV_LSB) & WLAN_PLL_CONTROL_DIV_MASK) +#define SOC_CORE_CLK_CTRL_DIV_GET(x) (((x) & SOC_CORE_CLK_CTRL_DIV_MASK) >> SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_SET(x) (((x) << SOC_CORE_CLK_CTRL_DIV_LSB) & SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_GET(x) (((x) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) >> RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_SET(x) (((x) << RTC_SYNC_STATUS_PLL_CHANGING_LSB) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define SOC_CPU_CLOCK_STANDARD_GET(x) (((x) & SOC_CPU_CLOCK_STANDARD_MASK) >> SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_SET(x) (((x) << SOC_CPU_CLOCK_STANDARD_LSB) & SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +typedef struct hostdef_s { + A_UINT32 d_INT_STATUS_ENABLE_ERROR_LSB; + A_UINT32 d_INT_STATUS_ENABLE_ERROR_MASK; + A_UINT32 d_INT_STATUS_ENABLE_CPU_LSB; + A_UINT32 d_INT_STATUS_ENABLE_CPU_MASK; + A_UINT32 d_INT_STATUS_ENABLE_COUNTER_LSB; + A_UINT32 d_INT_STATUS_ENABLE_COUNTER_MASK; + A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_LSB; + A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_MASK; + A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB; + A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK; + A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB; + A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK; + A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_LSB; + A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_MASK; + A_UINT32 d_INT_STATUS_ENABLE_ADDRESS; + A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_LSB; + A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_MASK; + A_UINT32 d_HOST_INT_STATUS_ADDRESS; + A_UINT32 d_CPU_INT_STATUS_ADDRESS; + A_UINT32 d_ERROR_INT_STATUS_ADDRESS; + A_UINT32 d_ERROR_INT_STATUS_WAKEUP_MASK; + A_UINT32 d_ERROR_INT_STATUS_WAKEUP_LSB; + A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK; + A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB; + A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_MASK; + A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_LSB; + A_UINT32 d_COUNT_DEC_ADDRESS; + A_UINT32 d_HOST_INT_STATUS_CPU_MASK; + A_UINT32 d_HOST_INT_STATUS_CPU_LSB; + A_UINT32 d_HOST_INT_STATUS_ERROR_MASK; + A_UINT32 d_HOST_INT_STATUS_ERROR_LSB; + A_UINT32 d_HOST_INT_STATUS_COUNTER_MASK; + A_UINT32 d_HOST_INT_STATUS_COUNTER_LSB; + A_UINT32 d_RX_LOOKAHEAD_VALID_ADDRESS; + A_UINT32 d_WINDOW_DATA_ADDRESS; + A_UINT32 d_WINDOW_READ_ADDR_ADDRESS; + A_UINT32 d_WINDOW_WRITE_ADDR_ADDRESS; + A_UINT32 d_SOC_GLOBAL_RESET_ADDRESS; + A_UINT32 d_RTC_STATE_ADDRESS; + A_UINT32 d_RTC_STATE_COLD_RESET_MASK; + A_UINT32 d_PCIE_LOCAL_BASE_ADDRESS; + A_UINT32 d_PCIE_SOC_WAKE_RESET; + A_UINT32 d_PCIE_SOC_WAKE_ADDRESS; + A_UINT32 d_PCIE_SOC_WAKE_V_MASK; + A_UINT32 d_RTC_STATE_V_MASK; + A_UINT32 d_RTC_STATE_V_LSB; + A_UINT32 d_FW_IND_EVENT_PENDING; + A_UINT32 d_FW_IND_INITIALIZED; + A_UINT32 d_RTC_STATE_V_ON; +#if defined(SDIO_3_0) + A_UINT32 d_HOST_INT_STATUS_MBOX_DATA_MASK; + A_UINT32 d_HOST_INT_STATUS_MBOX_DATA_LSB; +#endif + A_UINT32 d_PCIE_SOC_RDY_STATUS_ADDRESS; + A_UINT32 d_PCIE_SOC_RDY_STATUS_BAR_MASK; + A_UINT32 d_SOC_PCIE_BASE_ADDRESS; + A_UINT32 d_MSI_MAGIC_ADR_ADDRESS; + A_UINT32 d_MSI_MAGIC_ADDRESS; +} HOST_REGISTER_TABLE; + +#define INT_STATUS_ENABLE_ERROR_LSB (sc->hostdef->d_INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_MASK (sc->hostdef->d_INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_LSB (sc->hostdef->d_INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_MASK (sc->hostdef->d_INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_LSB (sc->hostdef->d_INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_MASK (sc->hostdef->d_INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_LSB (sc->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_MASK (sc->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB (sc->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK (sc->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB (sc->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK (sc->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB (sc->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK (sc->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define INT_STATUS_ENABLE_ADDRESS (sc->hostdef->d_INT_STATUS_ENABLE_ADDRESS) +#define CPU_INT_STATUS_ENABLE_BIT_LSB (sc->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_MASK (sc->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_MASK) +#define HOST_INT_STATUS_ADDRESS (sc->hostdef->d_HOST_INT_STATUS_ADDRESS) +#define CPU_INT_STATUS_ADDRESS (sc->hostdef->d_CPU_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_ADDRESS (sc->hostdef->d_ERROR_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_WAKEUP_MASK (sc->hostdef->d_ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_WAKEUP_LSB (sc->hostdef->d_ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK (sc->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB (sc->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK (sc->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB (sc->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define COUNT_DEC_ADDRESS (sc->hostdef->d_COUNT_DEC_ADDRESS) +#define HOST_INT_STATUS_CPU_MASK (sc->hostdef->d_HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_CPU_LSB (sc->hostdef->d_HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_MASK (sc->hostdef->d_HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_ERROR_LSB (sc->hostdef->d_HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_MASK (sc->hostdef->d_HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_COUNTER_LSB (sc->hostdef->d_HOST_INT_STATUS_COUNTER_LSB) +#define RX_LOOKAHEAD_VALID_ADDRESS (sc->hostdef->d_RX_LOOKAHEAD_VALID_ADDRESS) +#define WINDOW_DATA_ADDRESS (sc->hostdef->d_WINDOW_DATA_ADDRESS) +#define WINDOW_READ_ADDR_ADDRESS (sc->hostdef->d_WINDOW_READ_ADDR_ADDRESS) +#define WINDOW_WRITE_ADDR_ADDRESS (sc->hostdef->d_WINDOW_WRITE_ADDR_ADDRESS) +#define SOC_GLOBAL_RESET_ADDRESS (sc->hostdef->d_SOC_GLOBAL_RESET_ADDRESS) +#define RTC_STATE_ADDRESS (sc->hostdef->d_RTC_STATE_ADDRESS) +#define RTC_STATE_COLD_RESET_MASK (sc->hostdef->d_RTC_STATE_COLD_RESET_MASK) +#define PCIE_LOCAL_BASE_ADDRESS (sc->hostdef->d_PCIE_LOCAL_BASE_ADDRESS) +#define PCIE_SOC_WAKE_RESET (sc->hostdef->d_PCIE_SOC_WAKE_RESET) +#define PCIE_SOC_WAKE_ADDRESS (sc->hostdef->d_PCIE_SOC_WAKE_ADDRESS) +#define PCIE_SOC_WAKE_V_MASK (sc->hostdef->d_PCIE_SOC_WAKE_V_MASK) +#define RTC_STATE_V_MASK (sc->hostdef->d_RTC_STATE_V_MASK) +#define RTC_STATE_V_LSB (sc->hostdef->d_RTC_STATE_V_LSB) +#define FW_IND_EVENT_PENDING (sc->hostdef->d_FW_IND_EVENT_PENDING) +#define FW_IND_INITIALIZED (sc->hostdef->d_FW_IND_INITIALIZED) +#define RTC_STATE_V_ON (sc->hostdef->d_RTC_STATE_V_ON) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_MASK (sc->hostdef->d_HOST_INT_STATUS_MBOX_DATA_MASK) +#define HOST_INT_STATUS_MBOX_DATA_LSB (sc->hostdef->d_HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#if !defined(SOC_PCIE_BASE_ADDRESS) +#define SOC_PCIE_BASE_ADDRESS 0 +#endif + +#if !defined(PCIE_SOC_RDY_STATUS_ADDRESS) +#define PCIE_SOC_RDY_STATUS_ADDRESS 0 +#define PCIE_SOC_RDY_STATUS_BAR_MASK 0 +#endif + +#if !defined(MSI_MAGIC_ADR_ADDRESS) +#define MSI_MAGIC_ADR_ADDRESS 0 +#define MSI_MAGIC_ADDRESS 0 +#endif + +/* SET/GET macros */ +#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) +#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_GET(x) (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#define INVALID_REG_LOC_DUMMY_DATA 0xAA + + +#define AR6320_CORE_CLK_DIV_ADDR 0x403fa8 +#define AR6320_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320_CPU_SPEED_ADDR 0x403fa4 +#define AR6320V2_CORE_CLK_DIV_ADDR 0x403fd8 +#define AR6320V2_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320V2_CPU_SPEED_ADDR 0x403fd4 +#define AR6320V3_CORE_CLK_DIV_ADDR 0x404028 +#define AR6320V3_CPU_PLL_INIT_DONE_ADDR 0x404020 +#define AR6320V3_CPU_SPEED_ADDR 0x404024 + +typedef enum { + SOC_REFCLK_UNKNOWN = -1, /* Unsupported ref clock -- use PLL Bypass */ + SOC_REFCLK_48_MHZ = 0, + SOC_REFCLK_19_2_MHZ = 1, + SOC_REFCLK_24_MHZ = 2, + SOC_REFCLK_26_MHZ = 3, + SOC_REFCLK_37_4_MHZ = 4, + SOC_REFCLK_38_4_MHZ = 5, + SOC_REFCLK_40_MHZ = 6, + SOC_REFCLK_52_MHZ = 7, +} A_refclk_speed_t; + +#define A_REFCLK_UNKNOWN SOC_REFCLK_UNKNOWN +#define A_REFCLK_48_MHZ SOC_REFCLK_48_MHZ +#define A_REFCLK_19_2_MHZ SOC_REFCLK_19_2_MHZ +#define A_REFCLK_24_MHZ SOC_REFCLK_24_MHZ +#define A_REFCLK_26_MHZ SOC_REFCLK_26_MHZ +#define A_REFCLK_37_4_MHZ SOC_REFCLK_37_4_MHZ +#define A_REFCLK_38_4_MHZ SOC_REFCLK_38_4_MHZ +#define A_REFCLK_40_MHZ SOC_REFCLK_40_MHZ +#define A_REFCLK_52_MHZ SOC_REFCLK_52_MHZ + +#define TARGET_CPU_FREQ 176000000 + +struct wlan_pll_s { + u_int32_t refdiv; + u_int32_t div; + u_int32_t rnfrac; + u_int32_t outdiv; +}; + +struct cmnos_clock_s { + A_refclk_speed_t refclk_speed; + u_int32_t refclk_hz; + u_int32_t pll_settling_time; /* 50us */ + struct wlan_pll_s wlan_pll; +}; + +typedef struct TGT_REG_SECTION { + u_int32_t start_addr; + u_int32_t end_addr; +} tgt_reg_section; + +typedef struct TGT_REG_TABLE { + tgt_reg_section *section; + u_int32_t section_size; +} tgt_reg_table; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc.c new file mode 100644 index 000000000000..b08b23133711 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc.c @@ -0,0 +1,1023 @@ +/* + * Copyright (c) 2013, 2014, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#include "ol_if_athvar.h" +#include "htc_debug.h" +#include "htc_internal.h" +#include /* adf_nbuf_t */ +#include /* adf_os_print */ +#include /* HIFFlushSurpriseRemove */ +#include +#include "epping_main.h" +#include "htc_api.h" + +#ifdef DEBUG +static ATH_DEBUG_MASK_DESCRIPTION g_HTCDebugDescription[] = { + { ATH_DEBUG_SEND , "Send"}, + { ATH_DEBUG_RECV , "Recv"}, + { ATH_DEBUG_SYNC , "Sync"}, + { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"}, + { ATH_DEBUG_SETUP, "Setup"}, +}; + + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc, + "htc", + "Host Target Communications", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | ATH_DEBUG_SETUP, + ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescription), + g_HTCDebugDescription); + +#endif + +extern unsigned int htc_credit_flow; + +static void ResetEndpointStates(HTC_TARGET *target); + +static void DestroyHTCTxCtrlPacket(HTC_PACKET *pPacket) +{ + adf_nbuf_t netbuf; + netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("free ctrl netbuf :0x%p \n", netbuf)); + if (netbuf != NULL) { + adf_nbuf_free(netbuf); + } + + A_FREE(pPacket); +} + + +static HTC_PACKET *BuildHTCTxCtrlPacket(adf_os_device_t osdev) +{ + HTC_PACKET *pPacket = NULL; + adf_nbuf_t netbuf; + + do { + pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET)); + if (NULL == pPacket) { + break; + } + A_MEMZERO(pPacket,sizeof(HTC_PACKET)); + netbuf = adf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE, 20, 4, TRUE); + if (NULL == netbuf) { + A_FREE(pPacket); + pPacket = NULL; + adf_os_print("%s: nbuf alloc failed\n",__func__); + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("alloc ctrl netbuf :0x%p \n", netbuf)); + SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); + } while (FALSE); + + return pPacket; +} + +void HTCFreeControlTxPacket(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + +#ifdef TODO_FIXME + LOCK_HTC(target); + HTC_PACKET_ENQUEUE(&target->ControlBufferTXFreeList,pPacket); + UNLOCK_HTC(target); + /* TODO_FIXME netbufs cannot be RESET! */ +#else + DestroyHTCTxCtrlPacket(pPacket); +#endif + +} + +HTC_PACKET *HTCAllocControlTxPacket(HTC_TARGET *target) +{ +#ifdef TODO_FIXME + HTC_PACKET *pPacket; + + LOCK_HTC(target); + pPacket = HTC_PACKET_DEQUEUE(&target->ControlBufferTXFreeList); + UNLOCK_HTC(target); + + return pPacket; +#else + return BuildHTCTxCtrlPacket(target->osdev); +#endif +} + +/* Set the target failure handling callback */ +void HTCSetTargetFailureCallback(HTC_HANDLE HTCHandle, HTC_TARGET_FAILURE Callback) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + target->HTCInitInfo.TargetFailure = Callback; +} + +void HTCDump(HTC_HANDLE HTCHandle, u_int8_t CmdId, bool start) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HIFDump(target->hif_dev, CmdId, start); +} + +/* cleanup the HTC instance */ +static void HTCCleanup(HTC_TARGET *target) +{ + HTC_PACKET *pPacket; + adf_nbuf_t netbuf; + + if (target->hif_dev != NULL) { + HIFDetachHTC(target->hif_dev); +#ifdef HIF_SDIO + HIFMaskInterrupt(target->hif_dev); +#endif + target->hif_dev = NULL; + } + + while (TRUE) { + pPacket = AllocateHTCPacketContainer(target); + if (NULL == pPacket) { + break; + } + A_FREE(pPacket); + } + + pPacket = target->pBundleFreeTxList; + while (pPacket) { + HTC_PACKET *pPacketTmp = (HTC_PACKET *)pPacket->ListLink.pNext; + if(pPacket->pContext != NULL) { + A_FREE(pPacket->pContext); + } + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + if(netbuf != NULL) + adf_nbuf_free(netbuf); + A_FREE(pPacket); + pPacket = pPacketTmp; + } + + pPacket = target->pBundleFreeRxList; + while (pPacket) { + HTC_PACKET *pPacketTmp = (HTC_PACKET *)pPacket->ListLink.pNext; + if (pPacket->pContext != NULL) { + A_FREE(pPacket->pContext); + } + netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + if (netbuf != NULL) { + adf_nbuf_free(netbuf); + } + A_FREE(pPacket); + pPacket = pPacketTmp; + } +#ifdef TODO_FIXME + while (TRUE) { + pPacket = HTCAllocControlTxPacket(target); + if (NULL == pPacket) { + break; + } + netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + if (netbuf != NULL) { + adf_nbuf_free(netbuf); + } + + A_FREE(pPacket); + } +#endif + + adf_os_spinlock_destroy(&target->HTCLock); + adf_os_spinlock_destroy(&target->HTCRxLock); + adf_os_spinlock_destroy(&target->HTCTxLock); + adf_os_spinlock_destroy(&target->HTCCreditLock); + + /* free our instance */ + A_FREE(target); +} + +/* registered target arrival callback from the HIF layer */ +HTC_HANDLE HTCCreate(void *ol_sc, HTC_INIT_INFO *pInfo, adf_os_device_t osdev) +{ + hif_handle_t hHIF = ((struct ol_softc *)ol_sc)->hif_hdl; + MSG_BASED_HIF_CALLBACKS htcCallbacks; + HTC_ENDPOINT *pEndpoint=NULL; + HTC_TARGET *target = NULL; + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("+HTCCreate .. HIF :%p \n",hHIF)); + + A_REGISTER_MODULE_DEBUG_INFO(htc); + + if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTC : Unable to allocate memory\n")); + return NULL; + } + + A_MEMZERO(target, sizeof(HTC_TARGET)); + + adf_os_spinlock_init(&target->HTCLock); + adf_os_spinlock_init(&target->HTCRxLock); + adf_os_spinlock_init(&target->HTCTxLock); + adf_os_spinlock_init(&target->HTCCreditLock); + + do { + A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO)); + target->host_handle = pInfo->pContext; + target->osdev = osdev; + + ResetEndpointStates(target); + + INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); + + for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) { + HTC_PACKET *pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET)); + if (pPacket != NULL) { + A_MEMZERO(pPacket,sizeof(HTC_PACKET)); + FreeHTCPacketContainer(target,pPacket); + } + } + +#ifdef TODO_FIXME + for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) { + pPacket = BuildHTCTxCtrlPacket(); + if (NULL == pPacket) { + break; + } + HTCFreeControlTxPacket(target,pPacket); + } +#endif + + /* setup HIF layer callbacks */ + A_MEMZERO(&htcCallbacks, sizeof(MSG_BASED_HIF_CALLBACKS)); + htcCallbacks.Context = target; + htcCallbacks.rxCompletionHandler = HTCRxCompletionHandler; + htcCallbacks.txCompletionHandler = HTCTxCompletionHandler; + htcCallbacks.txResourceAvailHandler = HTCTxResourceAvailHandler; + htcCallbacks.fwEventHandler = HTCFwEventHandler; + htcCallbacks.txResumeAllHandler = HTCTxResumeAllHandler; + target->hif_dev = hHIF; + + /* Get HIF default pipe for HTC message exchange */ + pEndpoint = &target->EndPoint[ENDPOINT_0]; + + HIFPostInit(hHIF, target, &htcCallbacks); + HIFGetDefaultPipe(hHIF, &pEndpoint->UL_PipeID, &pEndpoint->DL_PipeID); + + } while (FALSE); + + HTCRecvInit(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("-HTCCreate (0x%p) \n", target)); + + return (HTC_HANDLE)target; +} + +void HTCDestroy(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%p \n",target)); + HIFStop(HTCGetHifDevice(HTCHandle)); + HTCCleanup(target); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n")); +} + +/* get the low level HIF device for the caller , the caller may wish to do low level + * HIF requests */ +void *HTCGetHifDevice(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return target->hif_dev; +} + +void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket) +{ + HTC_TARGET *target = (HTC_TARGET *)Context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+-HTCControlTxComplete 0x%p (l:%d) \n",pPacket,pPacket->ActualLength)); + HTCFreeControlTxPacket(target,pPacket); +} + +/* TODO, this is just a temporary max packet size */ +#define MAX_MESSAGE_SIZE 1536 + +A_STATUS HTCSetupTargetBufferAssignments(HTC_TARGET *target) +{ + HTC_SERVICE_TX_CREDIT_ALLOCATION *pEntry; + A_STATUS status; + int credits; + int creditsPerMaxMsg; +#ifdef HIF_USB + unsigned int hif_usbaudioclass=0; +#else + unsigned int hif_usbaudioclass=0; +#endif + + creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize; + if (MAX_MESSAGE_SIZE % target->TargetCreditSize) { + creditsPerMaxMsg++; + } + + /* TODO, this should be configured by the caller! */ + + credits = target->TotalTransmitCredits; + pEntry = &target->ServiceTxAllocTable[0]; +#if !(defined(HIF_PCI) || defined(HIF_SIM) || defined(CONFIG_HL_SUPPORT) || (defined(HIF_USB))) + status = A_NO_RESOURCE; +#endif + +#if defined(HIF_PCI) || defined(HIF_SIM) || (defined(CONFIG_HL_SUPPORT) && !defined(AR6004_HW))/* TODO: maybe change to HIF_SDIO later */ + /* TODO: maybe check ROME service for USB service */ + /* + * for PCIE allocate all credists/HTC buffers to WMI. + * no buffers are used/required for data. data always + * remains on host. + */ + hif_usbaudioclass = 0; /* to keep compiler happy */ + /* for PCIE allocate all credits to wmi for now */ + status = A_OK; + pEntry++; + pEntry->ServiceID = WMI_CONTROL_SVC; + pEntry->CreditAllocation = credits; + + if (WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { + /* endpoint ping is a testing tool directly on top of HTC in + * both target and host sides. + * In target side, the endppint ping fw has no wlan stack and the + * FW mboxping app directly sits on HTC and it simply drops + * or loops back TX packets. For rx perf, FW mboxping app + * generates packets and passes packets to HTC to send to host. + * There is no WMI mesage exchanges between host and target + * in endpoint ping case. + * In host side, the endpoint ping driver is a Ethernet driver + * and it directly sits on HTC. Only HIF, HTC, VOSS, ADF are + * used by the endpoint ping driver. There is no wifi stack + * at all in host side also. For tx perf use case, + * the user space mboxping app sends the raw packets to endpoint + * ping driver and it directly forwards to HTC for transmission + * to stress the bus. For the rx perf, HTC passes the received + * packets to endpoint ping driver and it is passed to the user + * space through the Ethernet interface. + * For credit allocation, in SDIO bus case, only BE service is + * used for tx/rx perf testing so that all credits are given + * to BE service. In PCIe and USB bus case, endpoint ping uses both + * BE and BK services to stress the bus so that the total credits + * are equally distributed to BE and BK services. + */ +#if !defined(HIF_USB) + pEntry++; + pEntry->ServiceID = WMI_DATA_BE_SVC; + pEntry->CreditAllocation = credits; +#endif + #if defined(HIF_PCI) || defined(HIF_USB) + pEntry->ServiceID = WMI_DATA_BE_SVC; + pEntry->CreditAllocation = (credits >> 1); + + pEntry++; + pEntry->ServiceID = WMI_DATA_BK_SVC; + pEntry->CreditAllocation = (credits >> 1); + #endif + } + +#else + do { + + if(hif_usbaudioclass) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HTCSetupTargetBufferAssignments For USB Audio Class- Total:%d\n",credits)); + pEntry++; + pEntry++; + //Setup VO Service To have Max Credits + pEntry->ServiceID = WMI_DATA_VO_SVC; + pEntry->CreditAllocation = (credits -6); + if (pEntry->CreditAllocation == 0) { + pEntry->CreditAllocation++; + } + credits -= (int)pEntry->CreditAllocation; + if (credits <= 0) { + break; + } + pEntry++; + pEntry->ServiceID = WMI_CONTROL_SVC; + pEntry->CreditAllocation = creditsPerMaxMsg; + credits -= (int)pEntry->CreditAllocation; + if (credits <= 0) { + break; + } + /* + * HTT_DATA_MSG_SVG is unidirectional from target -> host, + * so no target buffers are needed. + */ + /* leftovers go to best effort */ + pEntry++; + pEntry++; + pEntry->ServiceID = WMI_DATA_BE_SVC; + pEntry->CreditAllocation = (A_UINT8)credits; + status = A_OK; + break; + } + + pEntry++; + pEntry->ServiceID = WMI_DATA_VI_SVC; + pEntry->CreditAllocation = credits / 4; + if (pEntry->CreditAllocation == 0) { + pEntry->CreditAllocation++; + } + credits -= (int)pEntry->CreditAllocation; + if (credits <= 0) { + break; + } + pEntry++; + pEntry->ServiceID = WMI_DATA_VO_SVC; + pEntry->CreditAllocation = credits / 4; + if (pEntry->CreditAllocation == 0) { + pEntry->CreditAllocation++; + } + credits -= (int)pEntry->CreditAllocation; + if (credits <= 0) { + break; + } + pEntry++; + pEntry->ServiceID = WMI_CONTROL_SVC; + pEntry->CreditAllocation = creditsPerMaxMsg; + credits -= (int)pEntry->CreditAllocation; + if (credits <= 0) { + break; + } + /* + * HTT_DATA_MSG_SVG is unidirectional from target -> host, + * so no target buffers are needed. + */ + pEntry++; + pEntry->ServiceID = WMI_DATA_BK_SVC; + pEntry->CreditAllocation = creditsPerMaxMsg; + credits -= (int)pEntry->CreditAllocation; + if (credits <= 0) { + break; + } + /* leftovers go to best effort */ + pEntry++; + pEntry->ServiceID = WMI_DATA_BE_SVC; + pEntry->CreditAllocation = (A_UINT8)credits; + status = A_OK; + + } while (FALSE); + +#endif + + if (A_SUCCESS(status)) { + int i; + for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { + if (target->ServiceTxAllocTable[i].ServiceID != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_INIT,("HTC Service Index : %d TX : 0x%2.2X : alloc:%d \n", + i, + target->ServiceTxAllocTable[i].ServiceID, + target->ServiceTxAllocTable[i].CreditAllocation)); + } + } + } + + return status; +} + +A_UINT8 HTCGetCreditAllocation(HTC_TARGET *target, A_UINT16 ServiceID) +{ + A_UINT8 allocation = 0; + int i; + + for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { + if (target->ServiceTxAllocTable[i].ServiceID == ServiceID) { + allocation = target->ServiceTxAllocTable[i].CreditAllocation; + } + } + + if (0 == allocation) { + AR_DEBUG_PRINTF(ATH_DEBUG_INIT,("HTC Service TX : 0x%2.2X : allocation is zero! \n",ServiceID)); + } + + return allocation; +} + + +A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle) +{ + A_STATUS status = A_OK; + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_READY_EX_MSG *pReadyMsg; + HTC_SERVICE_CONNECT_REQ connect; + HTC_SERVICE_CONNECT_RESP resp; + HTC_READY_MSG *rdy_msg; + A_UINT16 htc_rdy_msg_id; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%p) \n", HTCHandle)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n")); + + do { + + status = HIFStart(target->hif_dev); + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIFStart failed\n")); + break; + } + + status = HTCWaitRecvCtrlMessage(target); + + if (A_FAILED(status)) { + break; + } + + if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid HTC Ready Msg Len:%d! \n",target->CtrlResponseLength)); + status = A_ECOMM; + break; + } + + pReadyMsg = (HTC_READY_EX_MSG *)target->CtrlResponseBuffer; + + rdy_msg = &pReadyMsg->Version2_0_Info; + htc_rdy_msg_id = HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID); + if (htc_rdy_msg_id != HTC_MSG_READY_ID) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Invalid HTC Ready Msg : 0x%X ! \n",htc_rdy_msg_id)); + status = A_ECOMM; + break; + } + + target->TotalTransmitCredits = HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITCOUNT); + target->TargetCreditSize = (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE); + + target->MaxMsgsPerHTCBundle = (A_UINT8) HTC_GET_FIELD(pReadyMsg, HTC_READY_EX_MSG, MAXMSGSPERHTCBUNDLE); + target->AltDataCreditSize = (A_UINT16)HTC_GET_FIELD(pReadyMsg, HTC_READY_EX_MSG, ALTDATACREDITSIZE); + + /* for old fw this value is set to 0. But the minimum value should be 1, + * i.e., no bundling */ + if (target->MaxMsgsPerHTCBundle < 1) + target->MaxMsgsPerHTCBundle = 1; + + AR_DEBUG_PRINTF(ATH_DEBUG_INIT, + ("Target Ready! : transmit resources : %d size:%d, MaxMsgsPerHTCBundle = %d\n", + target->TotalTransmitCredits, target->TargetCreditSize, target->MaxMsgsPerHTCBundle)); + + if ((0 == target->TotalTransmitCredits) || (0 == target->TargetCreditSize)) { + status = A_ECOMM; + break; + } + /* done processing */ + target->CtrlResponseProcessing = FALSE; + + HTCSetupTargetBufferAssignments(target); + + /* setup our pseudo HTC control endpoint connection */ + A_MEMZERO(&connect,sizeof(connect)); + A_MEMZERO(&resp,sizeof(resp)); + connect.EpCallbacks.pContext = target; + connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; + connect.EpCallbacks.EpRecv = HTCControlRxComplete; + connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS; + connect.ServiceID = HTC_CTRL_RSVD_SVC; + + /* connect fake service */ + status = HTCConnectService((HTC_HANDLE)target, + &connect, + &resp); + + } while (FALSE); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit (%d)\n",status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("-HWT\n")); + return status; +} + +/* start HTC, this is called after all services are connected */ +static A_STATUS HTCConfigTargetHIFPipe(HTC_TARGET *target) +{ + + return A_OK; +} + +static void ResetEndpointStates(HTC_TARGET *target) +{ + HTC_ENDPOINT *pEndpoint; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + pEndpoint->ServiceID = 0; + pEndpoint->MaxMsgLength = 0; + pEndpoint->MaxTxQueueDepth = 0; + pEndpoint->Id = i; + INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue); + INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue); + INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue); + pEndpoint->target = target; + //pEndpoint->TxCreditFlowEnabled = (A_BOOL)htc_credit_flow; + pEndpoint->TxCreditFlowEnabled = (A_BOOL)1; + adf_os_atomic_init(&pEndpoint->TxProcessCount); + } +} + +A_STATUS HTCStart(HTC_HANDLE HTCHandle) +{ + adf_nbuf_t netbuf; + A_STATUS status = A_OK; + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_SETUP_COMPLETE_EX_MSG *pSetupComp; + HTC_PACKET *pSendPacket; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); + + do { + + HTCConfigTargetHIFPipe(target); + + /* allocate a buffer to send */ + pSendPacket = HTCAllocControlTxPacket(target); + if (NULL == pSendPacket) { + AR_DEBUG_ASSERT(FALSE); + adf_os_print("%s: allocControlTxPacket failed\n",__func__); + status = A_NO_MEMORY; + break; + } + + netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); + /* assemble setup complete message */ + adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); + pSetupComp = (HTC_SETUP_COMPLETE_EX_MSG *) adf_nbuf_data(netbuf); + A_MEMZERO(pSetupComp,sizeof(HTC_SETUP_COMPLETE_EX_MSG)); + + HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG, + MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID); + + if (!htc_credit_flow) { + AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC will not use TX credit flow control\n")); + pSetupComp->SetupFlags |= HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC using TX credit flow control\n")); + } + +#if defined(HIF_SDIO) || defined(HIF_USB) +#if ENABLE_BUNDLE_RX + if (HTC_ENABLE_BUNDLE(target)) { + pSetupComp->SetupFlags |= + HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; + + HIFSetBundleMode(target->hif_dev, true, HTC_MAX_MSG_PER_BUNDLE_RX); + } +#endif /* ENABLE_BUNDLE_RX */ +#endif + + pSetupComp->MaxMsgsPerBundledRecv = HTC_MAX_MSG_PER_BUNDLE_RX; + + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (A_UINT8 *)pSetupComp, + sizeof(HTC_SETUP_COMPLETE_EX_MSG), + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + + status = HTCSendPkt((HTC_HANDLE)target,pSendPacket); + if (A_FAILED(status)) { + break; + } + + } while (FALSE); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); + return status; +} + +/*flush all queued buffers for surpriseremove case*/ +void HTCFlushSurpriseRemove(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int i; + HTC_ENDPOINT *pEndpoint; +#ifdef RX_SG_SUPPORT + adf_nbuf_t netbuf; + adf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCFlushSurpriseRemove \n")); + + /* cleanup endpoints */ + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + HTCFlushRxHoldQueue(target,pEndpoint); + HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL); + } + + HIFFlushSurpriseRemove(target->hif_dev); + +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + while ((netbuf = adf_nbuf_queue_remove(rx_sg_queue)) != NULL) { + adf_nbuf_free(netbuf); + } + RESET_RX_SG_CONFIG(target); + UNLOCK_HTC_RX(target); +#endif + + ResetEndpointStates(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCFlushSurpriseRemove \n")); +} + +/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ +void HTCStop(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int i; + HTC_ENDPOINT *pEndpoint; +#ifdef RX_SG_SUPPORT + adf_nbuf_t netbuf; + adf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); + + /* cleanup endpoints */ + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + HTCFlushRxHoldQueue(target,pEndpoint); + HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL); + if(pEndpoint->ul_is_polled){ + adf_os_timer_cancel(&pEndpoint->ul_poll_timer); + adf_os_timer_free(&pEndpoint->ul_poll_timer); + } + } + + /* Note: HTCFlushEndpointTX for all endpoints should be called before + * HIFStop - otherwise HTCTxCompletionHandler called from + * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer, + * might queue the packet again to HIF Layer - which could cause tx + * buffer leak + */ + + HIFStop(target->hif_dev); + +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + while ((netbuf = adf_nbuf_queue_remove(rx_sg_queue)) != NULL) { + adf_nbuf_free(netbuf); + } + RESET_RX_SG_CONFIG(target); + UNLOCK_HTC_RX(target); +#endif + + ResetEndpointStates(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); +} + + + +void HTCDumpCreditStates(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + int i; + + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (0 == pEndpoint->ServiceID) { + continue; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n", + pEndpoint->Id, pEndpoint->ServiceID)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEndpoint->TxCredits)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEndpoint->TxCreditSize)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEndpoint->TxCreditsPerMaxMsg)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); + } +} + +void HTCEndpointDumpCreditStats(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) +{ +#ifdef HTC_EP_STAT_PROFILING + HTC_TARGET *target; + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+%s \n", __func__)); + + target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" ******* HTC Stats for EP %d ******* \n", Endpoint)); + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("HIFDSRCount=%d \t RxAllocThreshBytes=%d \t RxAllocThreshHit=%d \n" + "RxBundleIndFromHdr=%d \t RxBundleLookAheads=%d \t RxLookAheads=%d \n" + "RxPacketsBundled=%d \t RxReceived=%d \t TxBundles=%d \n" + "TxCreditLowIndications=%d \t TxCreditRpts=%d \t TxCreditRptsFromEp0=%d \n" + "TxCreditRptsFromOther=%d \t TxCreditRptsFromRx=%d \t TxCreditsConsummed=%d \n" + "TxCreditsFromEp0=%d \t TxCreditsFromOther=%d \t TxCreditsFromRx=%d \n" + "TxCreditsReturned=%d \t TxDropped=%d \t TxIssued=%d \n" + "TxPacketsBundled=%d \t TxPosted=%d \n", + target->EndPoint->EndPointStats.HIFDSRCount, + target->EndPoint->EndPointStats.RxAllocThreshBytes, + target->EndPoint->EndPointStats.RxAllocThreshHit, + target->EndPoint->EndPointStats.RxBundleIndFromHdr, + target->EndPoint->EndPointStats.RxBundleLookAheads, + target->EndPoint->EndPointStats.RxLookAheads, + target->EndPoint->EndPointStats.RxPacketsBundled, + target->EndPoint->EndPointStats.RxReceived, + target->EndPoint->EndPointStats.TxBundles, + target->EndPoint->EndPointStats.TxCreditLowIndications, + target->EndPoint->EndPointStats.TxCreditRpts, + target->EndPoint->EndPointStats.TxCreditRptsFromEp0, + target->EndPoint->EndPointStats.TxCreditRptsFromOther, + target->EndPoint->EndPointStats.TxCreditRptsFromRx, + target->EndPoint->EndPointStats.TxCreditsConsummed, + target->EndPoint->EndPointStats.TxCreditsFromEp0, + target->EndPoint->EndPointStats.TxCreditsFromOther, + target->EndPoint->EndPointStats.TxCreditsFromRx, + target->EndPoint->EndPointStats.TxCreditsReturned, + target->EndPoint->EndPointStats.TxDropped, + target->EndPoint->EndPointStats.TxIssued, + target->EndPoint->EndPointStats.TxPacketsBundled, + target->EndPoint->EndPointStats.TxPosted)); + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" ******* End Stats ******* \n")); +#else + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("%s not implemented\n", __func__)); +#endif +} + +A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + HTC_ENDPOINT_STATS *pStats) +{ +#ifdef HTC_EP_STAT_PROFILING + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + A_BOOL clearStats = FALSE; + A_BOOL sample = FALSE; + + switch (Action) { + case HTC_EP_STAT_SAMPLE : + sample = TRUE; + break; + case HTC_EP_STAT_SAMPLE_AND_CLEAR : + sample = TRUE; + clearStats = TRUE; + break; + case HTC_EP_STAT_CLEAR : + clearStats = TRUE; + break; + default: + break; + } + + A_ASSERT(Endpoint < ENDPOINT_MAX); + + /* lock out TX and RX while we sample and/or clear */ + LOCK_HTC_TX(target); + LOCK_HTC_RX(target); + + if (sample) { + A_ASSERT(pStats != NULL); + /* return the stats to the caller */ + A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS)); + } + + if (clearStats) { + /* reset stats */ + A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS)); + } + + UNLOCK_HTC_RX(target); + UNLOCK_HTC_TX(target); + + return TRUE; +#else + return FALSE; +#endif +} + +void *htc_get_targetdef(HTC_HANDLE htc_handle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + + return hif_get_targetdef(target->hif_dev); +} + +void HTCSetTargetToSleep(void *context) +{ +#ifdef HIF_PCI +#if CONFIG_ATH_PCIE_MAX_PERF == 0 +#if CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD + struct ol_softc *sc = (struct ol_softc *)context; + + HIFSetTargetSleep(sc->hif_hdl, true, false); +#endif +#endif +#endif +} + +void HTCCancelDeferredTargetSleep(void *context) +{ +#ifdef HIF_PCI +#if CONFIG_ATH_PCIE_MAX_PERF == 0 + struct ol_softc *sc = (struct ol_softc *)context; + HIFCancelDeferredTargetSleep(sc->hif_hdl); +#endif +#endif +} + +#ifdef IPA_UC_OFFLOAD +void HTCIpaGetCEResource(HTC_HANDLE htc_handle, + a_uint32_t *ce_sr_base_paddr, + a_uint32_t *ce_sr_ring_size, + a_uint32_t *ce_reg_paddr) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + + if (target->hif_dev != NULL) { + HIFIpaGetCEResource(target->hif_dev, + ce_sr_base_paddr, + ce_sr_ring_size, + ce_reg_paddr); + } +} +#endif /* IPA_UC_OFFLOAD */ + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + +void HTCDumpBundleStats(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int total, i; + + total = 0; + for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++) { + total += target->rx_bundle_stats[i]; + } + + if (total) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RX Bundle stats:\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("Total RX packets: %d\n", total)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,( + "Number of bundle: Number of packets\n")); + for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("%10d:%10d(%2d%s)\n",(i+1), target->rx_bundle_stats[i], + ((target->rx_bundle_stats[i]*100)/total), "%")); + } + } + + + total = 0; + for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++) { + total += target->tx_bundle_stats[i]; + } + + if (total) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("TX Bundle stats:\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("Total TX packets: %d\n", total)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Number of bundle: Number of packets\n")); + for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("%10d:%10d(%2d%s)\n",(i+1), target->tx_bundle_stats[i], + ((target->tx_bundle_stats[i]*100)/total), "%")); + } + } +} + +void HTCClearBundleStats (HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + adf_os_mem_zero(&target->rx_bundle_stats, sizeof(target->rx_bundle_stats)); + adf_os_mem_zero(&target->tx_bundle_stats, sizeof(target->tx_bundle_stats)); +} +#endif + +#ifdef FEATURE_RUNTIME_PM +int htc_pm_runtime_get(HTC_HANDLE htc_handle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("%s: %pS\n", __func__, (void *)_RET_IP_)); + return hif_pm_runtime_get(target->hif_dev); +} + +int htc_pm_runtime_put(HTC_HANDLE htc_handle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("%s: %pS\n", __func__, (void *)_RET_IP_)); + return hif_pm_runtime_put(target->hif_dev); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_debug.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_debug.h new file mode 100644 index 000000000000..d41fcee13ba1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_debug.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef HTC_DEBUG_H_ +#define HTC_DEBUG_H_ + +#define ATH_MODULE_NAME htc +#include "a_debug.h" + +/* ------- Debug related stuff ------- */ + +#define ATH_DEBUG_SEND ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_RECV ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_SYNC ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_DUMP ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_SETUP ATH_DEBUG_MAKE_MODULE_MASK(4) + + +#endif /*HTC_DEBUG_H_*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_internal.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_internal.h new file mode 100644 index 000000000000..7ac205193d1a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_internal.h @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _HTC_INTERNAL_H_ +#define _HTC_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +//#include +#include +#include + +#endif +#include +#include "a_types.h" +#include "osapi_linux.h" +#include +#include +#include +#include +#include +#include "hif_msg_based.h" +#include +#include "htc_api.h" +#include "htc_packet.h" + +/* HTC operational parameters */ +#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ +#define HTC_TARGET_DEBUG_INTR_MASK 0x01 +#define HTC_TARGET_CREDIT_INTR_MASK 0xF0 +#define HTC_MIN_MSG_PER_BUNDLE 2 +#if defined(HIF_USB) +#define HTC_MAX_MSG_PER_BUNDLE_RX 11 +#define HTC_MAX_MSG_PER_BUNDLE_TX 8 +#else +#define HTC_MAX_MSG_PER_BUNDLE_RX 64 +#define HTC_MAX_MSG_PER_BUNDLE_TX 32 +#endif +/* + * HTC_MAX_TX_BUNDLE_SEND_LIMIT - + * This value is in units of tx frame fragments. + * It needs to be at least as large as the maximum number of tx frames in a + * HTC download bundle times the average number of fragments in each such frame + * (In certain operating systems, such as Linux, we expect to only have + * a single fragment per frame anyway.) + */ +#define HTC_MAX_TX_BUNDLE_SEND_LIMIT 255 + +#define HTC_PACKET_CONTAINER_ALLOCATION 32 +#define NUM_CONTROL_TX_BUFFERS 2 +#define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH) +#define HTC_CONTROL_BUFFER_ALIGN 32 +#define HTC_TARGET_RESPONSE_POLL_MS 10 +#if !defined(A_SIMOS_DEVHOST) +#define HTC_TARGET_MAX_RESPONSE_POLL 200 /* actual HW */ +#else +#define HTC_TARGET_MAX_RESPONSE_POLL 600 /* host + target simulation */ +#endif + +#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL + +#define HTC_CREDIT_HISTORY_MAX 1024 + +typedef enum { + HTC_REQUEST_CREDIT, + HTC_PROCESS_CREDIT_REPORT, + HTC_SUSPEND_ACK, + HTC_SUSPEND_NACK, +} htc_credit_exchange_type; + +typedef struct { + htc_credit_exchange_type type; + A_UINT64 time; + A_UINT32 tx_credit; + A_UINT32 htc_tx_queue_depth; +} HTC_CREDIT_HISTORY; + +typedef struct _HTC_ENDPOINT { + HTC_ENDPOINT_ID Id; + HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to + non-zero value means this endpoint is in use */ + HTC_EP_CALLBACKS EpCallBacks; /* callbacks associated with this endpoint */ + HTC_PACKET_QUEUE TxQueue; /* HTC frame buffer TX queue */ + int MaxTxQueueDepth; /* max depth of the TX queue before we need to + call driver's full handler */ + int MaxMsgLength; /* max length of endpoint message */ + a_uint8_t UL_PipeID; + a_uint8_t DL_PipeID; + int ul_is_polled; /* Need to call HIF to get tx completion callbacks? */ + adf_os_timer_t ul_poll_timer; + int ul_poll_timer_active; + int ul_outstanding_cnt; + int dl_is_polled; /* Need to call HIF to fetch rx? (Not currently supported.) */ + #if 0 /* not currently supported */ + adf_os_timer_t dl_poll_timer; + #endif + + HTC_PACKET_QUEUE TxLookupQueue; /* lookup queue to match netbufs to htc packets */ + HTC_PACKET_QUEUE RxBufferHoldQueue; /* temporary hold queue for back compatibility */ + A_UINT8 SeqNo; /* TX seq no (helpful) for debugging */ + adf_os_atomic_t TxProcessCount; /* serialization */ + struct _HTC_TARGET *target; + int TxCredits; /* TX credits available on this endpoint */ + int TxCreditSize; /* size in bytes of each credit (set by HTC) */ + int TxCreditsPerMaxMsg; /* credits required per max message (precalculated) */ +#ifdef HTC_EP_STAT_PROFILING + HTC_ENDPOINT_STATS EndPointStats; /* endpoint statistics */ +#endif + A_BOOL TxCreditFlowEnabled; +} HTC_ENDPOINT; + +#ifdef HTC_EP_STAT_PROFILING +#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count); +#else +#define INC_HTC_EP_STAT(p,stat,count) +#endif + +typedef struct { + A_UINT16 ServiceID; + A_UINT8 CreditAllocation; +} HTC_SERVICE_TX_CREDIT_ALLOCATION; + +#define HTC_MAX_SERVICE_ALLOC_ENTRIES 8 + +/* Error codes for HTC layer packet stats*/ +enum ol_ath_htc_pkt_ecodes { + GET_HTC_PKT_Q_FAIL=0, /* error- get packet at head of HTC_PACKET_Q */ + HTC_PKT_Q_EMPTY, + HTC_SEND_Q_EMPTY +}; +/* our HTC target state */ +typedef struct _HTC_TARGET { + HIF_DEVICE *hif_dev; + HTC_ENDPOINT EndPoint[ENDPOINT_MAX]; + adf_os_spinlock_t HTCLock; + adf_os_spinlock_t HTCRxLock; + adf_os_spinlock_t HTCTxLock; + adf_os_spinlock_t HTCCreditLock; + A_UINT32 HTCStateFlags; + void *host_handle; + HTC_INIT_INFO HTCInitInfo; + HTC_PACKET *pHTCPacketStructPool; /* pool of HTC packets */ + HTC_PACKET_QUEUE ControlBufferTXFreeList; + A_UINT8 CtrlResponseBuffer[HTC_MAX_CONTROL_MESSAGE_LENGTH]; + int CtrlResponseLength; + adf_os_mutex_t CtrlResponseValid; + A_BOOL CtrlResponseProcessing; + int TotalTransmitCredits; + HTC_SERVICE_TX_CREDIT_ALLOCATION ServiceTxAllocTable[HTC_MAX_SERVICE_ALLOC_ENTRIES]; + int TargetCreditSize; +#ifdef RX_SG_SUPPORT + adf_nbuf_queue_t RxSgQueue; + A_BOOL IsRxSgInprogress; + A_UINT32 CurRxSgTotalLen; /* current total length */ + A_UINT32 ExpRxSgTotalLen; /* expected total length */ +#endif + adf_os_device_t osdev; + struct ol_ath_htc_stats htc_pkt_stats; + HTC_PACKET *pBundleFreeTxList; + HTC_PACKET *pBundleFreeRxList; + A_UINT32 CE_send_cnt; + A_UINT32 TX_comp_cnt; + A_UINT8 MaxMsgsPerHTCBundle; + A_UINT16 AltDataCreditSize; +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + A_UINT32 rx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_RX]; + A_UINT32 tx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_TX]; +#endif +} HTC_TARGET; + +#define HTC_ENABLE_BUNDLE(target) (target->MaxMsgsPerHTCBundle > 1) +#ifdef RX_SG_SUPPORT +#define RESET_RX_SG_CONFIG(_target) \ + _target->ExpRxSgTotalLen = 0; \ + _target->CurRxSgTotalLen = 0; \ + _target->IsRxSgInprogress = FALSE; +#endif + +#define HTC_STATE_STOPPING (1 << 0) +#define HTC_STOPPING(t) ((t)->HTCStateFlags & HTC_STATE_STOPPING) +#define LOCK_HTC(t) adf_os_spin_lock_bh(&(t)->HTCLock); +#define UNLOCK_HTC(t) adf_os_spin_unlock_bh(&(t)->HTCLock); +#define LOCK_HTC_RX(t) adf_os_spin_lock_bh(&(t)->HTCRxLock); +#define UNLOCK_HTC_RX(t) adf_os_spin_unlock_bh(&(t)->HTCRxLock); +#define LOCK_HTC_TX(t) adf_os_spin_lock_bh(&(t)->HTCTxLock); +#define UNLOCK_HTC_TX(t) adf_os_spin_unlock_bh(&(t)->HTCTxLock); +#define LOCK_HTC_CREDIT(t) adf_os_spin_lock_bh(&(t)->HTCCreditLock); +#define UNLOCK_HTC_CREDIT(t) adf_os_spin_unlock_bh(&(t)->HTCCreditLock); + +#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd)) + +#define IS_TX_CREDIT_FLOW_ENABLED(ep) ((ep)->TxCreditFlowEnabled) + +#define HTC_POLL_CLEANUP_PERIOD_MS 10 /* milliseconds */ + + +/* Macro to Increment the HTC_PACKET_ERRORS for Tx.*/ +#define OL_ATH_HTC_PKT_ERROR_COUNT_INCR(_target,_ecode)\ + do {\ + if(_ecode==GET_HTC_PKT_Q_FAIL)(_target->htc_pkt_stats.htc_get_pkt_q_fail_count)+=1;\ + if(_ecode==HTC_PKT_Q_EMPTY)(_target->htc_pkt_stats.htc_pkt_q_empty_count)+=1;\ + if(_ecode==HTC_SEND_Q_EMPTY)(_target->htc_pkt_stats.htc_send_q_empty_count)+=1;\ + } while(0); +/* internal HTC functions */ + +A_STATUS HTCRxCompletionHandler( + void *Context, adf_nbuf_t netbuf, a_uint8_t pipeID); +A_STATUS HTCTxCompletionHandler( + void *Context, adf_nbuf_t netbuf, unsigned int transferID); + +HTC_PACKET *AllocateHTCBundleRxPacket(HTC_TARGET *target); +HTC_PACKET *AllocateHTCBundleTxPacket(HTC_TARGET *target); + +void FreeHTCBundleRxPacket(HTC_TARGET *target, HTC_PACKET *pPacket); +void FreeHTCBundleTxPacket(HTC_TARGET *target, HTC_PACKET *pPacket); + +HTC_PACKET *AllocateHTCPacketContainer(HTC_TARGET *target); +void FreeHTCPacketContainer(HTC_TARGET *target, HTC_PACKET *pPacket); +void HTCFlushRxHoldQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint); +void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag); +void HTCRecvInit(HTC_TARGET *target); +A_STATUS HTCWaitRecvCtrlMessage(HTC_TARGET *target); +void HTCFreeControlTxPacket(HTC_TARGET *target, HTC_PACKET *pPacket); +HTC_PACKET *HTCAllocControlTxPacket(HTC_TARGET *target); +A_UINT8 HTCGetCreditAllocation(HTC_TARGET *target, A_UINT16 ServiceID); +void HTCTxResourceAvailHandler(void *context, A_UINT8 pipeID); +void HTCControlRxComplete(void *Context, HTC_PACKET *pPacket); +void HTCProcessCreditRpt(HTC_TARGET *target, + HTC_CREDIT_REPORT *pRpt, + int NumEntries, + HTC_ENDPOINT_ID FromEndpoint); +void HTCFwEventHandler(void *context, A_STATUS status); +void HTCSendCompleteCheckCleanup(void *context); +void HTCTxResumeAllHandler(void *context); + +void htc_credit_record(htc_credit_exchange_type type, A_UINT32 tx_credit, + A_UINT32 htc_tx_queue_depth); + +static inline void HTCSendCompletePollTimerStop(HTC_ENDPOINT *pEndpoint) +{ + LOCK_HTC_TX(pEndpoint->target); + if (pEndpoint->ul_poll_timer_active) { + //adf_os_timer_cancel(&pEndpoint->ul_poll_timer); + pEndpoint->ul_poll_timer_active = 0; + } + UNLOCK_HTC_TX(pEndpoint->target); +} + +static inline void HTCSendCompletePollTimerStart(HTC_ENDPOINT *pEndpoint) +{ + LOCK_HTC_TX(pEndpoint->target); + if (pEndpoint->ul_outstanding_cnt && ! pEndpoint->ul_poll_timer_active) { + /* + adf_os_timer_start( + &pEndpoint->ul_poll_timer, HTC_POLL_CLEANUP_PERIOD_MS); + */ + pEndpoint->ul_poll_timer_active = 1; + } + UNLOCK_HTC_TX(pEndpoint->target); +} + + +static inline void +HTCSendCompleteCheck(HTC_ENDPOINT *pEndpoint, int force) +{ + /* + * Stop the polling-cleanup timer that will result in a later call to + * this function. It may get started again below, if there are still + * outsending sends. + */ + HTCSendCompletePollTimerStop(pEndpoint); + /* + * Check whether HIF has any prior sends that have finished, + * have not had the post-processing done. + */ + HIFSendCompleteCheck( + pEndpoint->target->hif_dev, pEndpoint->UL_PipeID, force); + /* + * If there are still outstanding sends after polling, start a timer + * to check again a little later. + */ + HTCSendCompletePollTimerStart(pEndpoint); +} + + +#ifdef __cplusplus +} +#endif + +#ifndef DEBUG_BUNDLE +#define DEBUG_BUNDLE 0 +#endif + +#if defined(HIF_SDIO) || defined(HIF_USB) +#ifndef ENABLE_BUNDLE_TX +#define ENABLE_BUNDLE_TX 1 +#endif + +#ifndef ENABLE_BUNDLE_RX +#define ENABLE_BUNDLE_RX 1 +#endif +#endif +#endif /* !_HTC_HOST_INTERNAL_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_recv.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_recv.c new file mode 100644 index 000000000000..63f98257940b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_recv.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "htc_debug.h" +#include "htc_internal.h" +#include "vos_api.h" +#include /* adf_nbuf_t */ +#include +#include "epping_main.h" + +#ifdef DEBUG +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription) +{ + A_CHAR stream[60]; + A_CHAR byteOffsetStr[10]; + A_UINT32 i; + A_UINT16 offset, count, byteOffset; + + A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription); + + count = 0; + offset = 0; + byteOffset = 0; + for(i = 0; i < length; i++) { + A_SNPRINTF(stream + offset, (sizeof(stream) - offset), + "%02X ", buffer[i]); + count ++; + offset += 3; + + if(count == 16) { + count = 0; + offset = 0; + A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X",byteOffset); + A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); + A_MEMZERO(stream, 60); + byteOffset += 16; + } + } + + if(offset != 0) { + A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X",byteOffset); + A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); + } + + A_PRINTF("<------------------------------------------------->\n"); +} +#else +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription) +{} +#endif + +static A_STATUS HTCProcessTrailer(HTC_TARGET *target, + A_UINT8 *pBuffer, + int Length, + HTC_ENDPOINT_ID FromEndpoint); + +static void DoRecvCompletion(HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueueToIndicate) +{ + + do { + + if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { + /* nothing to indicate */ + break; + } + + if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d, recv multiple callback (%d pkts) \n", + pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); + /* a recv multiple handler is being used, pass the queue to the handler */ + pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint->EpCallBacks.pContext, + pQueueToIndicate); + INIT_HTC_PACKET_QUEUE(pQueueToIndicate); + } else { + HTC_PACKET *pPacket; + /* using legacy EpRecv */ + while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) { + pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + if (pEndpoint->EpCallBacks.EpRecv == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTC ep %d has NULL recv callback on packet %p\n", + pEndpoint->Id, pPacket)); + continue; + } + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTC calling ep %d recv callback on packet %p\n", + pEndpoint->Id, pPacket)); + pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket); + } + } + + } while (FALSE); + +} + +static void RecvPacketCompletion(HTC_TARGET *target,HTC_ENDPOINT *pEndpoint, HTC_PACKET *pPacket) +{ + HTC_PACKET_QUEUE container; + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + /* do completion */ + DoRecvCompletion(pEndpoint,&container); +} + + +void HTCControlRxComplete(void *Context, HTC_PACKET *pPacket) +{ + /* TODO, can't really receive HTC control messages yet.... */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid call to HTCControlRxComplete\n")); +} + +void HTCUnblockRecv(HTC_HANDLE HTCHandle) +{ + /* TODO find the Need in new model*/ +} + + +void HTCEnableRecv(HTC_HANDLE HTCHandle) +{ + + /* TODO find the Need in new model*/ +} + +void HTCDisableRecv(HTC_HANDLE HTCHandle) +{ + + /* TODO find the Need in new model*/ +} + +int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; + return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue); +} + +HTC_PACKET *AllocateHTCPacketContainer(HTC_TARGET *target) +{ + HTC_PACKET *pPacket; + + LOCK_HTC_RX(target); + + if (NULL == target->pHTCPacketStructPool) { + UNLOCK_HTC_RX(target); + return NULL; + } + + pPacket = target->pHTCPacketStructPool; + target->pHTCPacketStructPool = (HTC_PACKET *)pPacket->ListLink.pNext; + + UNLOCK_HTC_RX(target); + + pPacket->ListLink.pNext = NULL; + return pPacket; +} + +void FreeHTCPacketContainer(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + LOCK_HTC_RX(target); + + if (NULL == target->pHTCPacketStructPool) { + target->pHTCPacketStructPool = pPacket; + pPacket->ListLink.pNext = NULL; + } else { + pPacket->ListLink.pNext = (DL_LIST *)target->pHTCPacketStructPool; + target->pHTCPacketStructPool = pPacket; + } + + UNLOCK_HTC_RX(target); +} + +#ifdef RX_SG_SUPPORT +adf_nbuf_t RxSgToSingleNetbuf(HTC_TARGET *target) +{ + adf_nbuf_t skb; + a_uint8_t *anbdata; + a_uint8_t *anbdata_new; + a_uint32_t anblen; + adf_nbuf_t new_skb = NULL; + a_uint32_t sg_queue_len; + adf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; + + sg_queue_len = adf_nbuf_queue_len(rx_sg_queue); + + if (sg_queue_len <= 1) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("RxSgToSingleNetbuf: invalid sg queue len %u\n")); + goto _failed; + } + + new_skb = adf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, FALSE); + if (new_skb == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("RxSgToSingleNetbuf: can't allocate %u size netbuf\n", + target->ExpRxSgTotalLen)); + goto _failed; + } + + adf_nbuf_peek_header(new_skb, &anbdata_new, &anblen); + + skb = adf_nbuf_queue_remove(rx_sg_queue); + do { + adf_nbuf_peek_header(skb, &anbdata, &anblen); + adf_os_mem_copy(anbdata_new, anbdata, adf_nbuf_len(skb)); + adf_nbuf_put_tail(new_skb, adf_nbuf_len(skb)); + anbdata_new += adf_nbuf_len(skb); + adf_nbuf_free(skb); + skb = adf_nbuf_queue_remove(rx_sg_queue); + } while(skb != NULL); + + RESET_RX_SG_CONFIG(target); + return new_skb; + +_failed: + + while ((skb = adf_nbuf_queue_remove(rx_sg_queue)) != NULL) { + adf_nbuf_free(skb); + } + + RESET_RX_SG_CONFIG(target); + return NULL; +} +#endif + +static void HTCsuspendwow(HTC_TARGET *target) +{ + HIFsuspendwow(target->hif_dev); + return; +} + +A_STATUS HTCRxCompletionHandler( + void *Context, adf_nbuf_t netbuf, a_uint8_t pipeID) +{ + A_STATUS status = A_OK; + HTC_FRAME_HDR *HtcHdr; + HTC_TARGET *target = (HTC_TARGET *)Context; + a_uint8_t *netdata; + a_uint32_t netlen; + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pPacket; + A_UINT16 payloadLen; + a_uint32_t trailerlen = 0; + A_UINT8 htc_ep_id; + +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + if (target->IsRxSgInprogress) { + target->CurRxSgTotalLen += adf_nbuf_len(netbuf); + adf_nbuf_queue_add(&target->RxSgQueue, netbuf); + if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) { + netbuf = RxSgToSingleNetbuf(target); + if (netbuf == NULL) { + UNLOCK_HTC_RX(target); + goto _out; + } + } + else { + netbuf = NULL; + UNLOCK_HTC_RX(target); + goto _out; + } + } + UNLOCK_HTC_RX(target); +#endif + + netdata = adf_nbuf_data(netbuf); + netlen = adf_nbuf_len(netbuf); + + HtcHdr = (HTC_FRAME_HDR *)netdata; + + do { + + htc_ep_id = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, ENDPOINTID); + + if (htc_ep_id >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC Rx: invalid EndpointID=%d\n",htc_ep_id)); + DebugDumpBytes((A_UINT8 *)HtcHdr,sizeof(HTC_FRAME_HDR),"BAD HTC Header"); + status = A_ERROR; + VOS_BUG(0); + break; + } + + pEndpoint = &target->EndPoint[htc_ep_id]; + + /* + * If this endpoint that received a message from the target has + * a to-target HIF pipe whose send completions are polled rather + * than interrupt-driven, this is a good point to ask HIF to check + * whether it has any completed sends to handle. + */ + if (pEndpoint->ul_is_polled) { + HTCSendCompleteCheck(pEndpoint, 1); + } + + payloadLen = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, PAYLOADLEN); + + if (netlen < (payloadLen + HTC_HDR_LENGTH)) { +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + target->IsRxSgInprogress = TRUE; + adf_nbuf_queue_init(&target->RxSgQueue); + adf_nbuf_queue_add(&target->RxSgQueue, netbuf); + target->ExpRxSgTotalLen = (payloadLen + HTC_HDR_LENGTH); + target->CurRxSgTotalLen += netlen; + UNLOCK_HTC_RX(target); + netbuf = NULL; + break; +#else + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC Rx: insufficient length, got:%d expected =%zu\n", + netlen, payloadLen + HTC_HDR_LENGTH)); + DebugDumpBytes((A_UINT8 *)HtcHdr,sizeof(HTC_FRAME_HDR),"BAD RX packet length"); + status = A_ERROR; + VOS_BUG(0); + break; +#endif + } + +#ifdef HTC_EP_STAT_PROFILING + LOCK_HTC_RX(target); + INC_HTC_EP_STAT(pEndpoint,RxReceived,1); + UNLOCK_HTC_RX(target); +#endif + + //if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + { + A_UINT8 temp; + /* get flags to check for trailer */ + temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, FLAGS); + if (temp & HTC_FLAGS_RECV_TRAILER) { + /* extract the trailer length */ + temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, CONTROLBYTES0); + if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCRxCompletionHandler, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", + payloadLen, temp)); + status = A_EPROTO; + break; + } + + trailerlen = temp; + /* process trailer data that follows HDR + application payload */ + status = HTCProcessTrailer(target, + ((A_UINT8 *)HtcHdr + HTC_HDR_LENGTH + payloadLen - temp), + temp, htc_ep_id); + if (A_FAILED(status)) { + break; + } + + } + } + + if (((int)payloadLen - (int)trailerlen) <= 0) { + /* zero length packet with trailer data, just drop these */ + break; + } + + + if (htc_ep_id == ENDPOINT_0) { + A_UINT16 message_id; + HTC_UNKNOWN_MSG *htc_msg; + int wow_nack = 0; + + /* remove HTC header */ + adf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH); + netdata = adf_nbuf_data(netbuf); + netlen = adf_nbuf_len(netbuf); + + htc_msg = (HTC_UNKNOWN_MSG*)netdata; + message_id = HTC_GET_FIELD(htc_msg, HTC_UNKNOWN_MSG, MESSAGEID); + + switch (message_id) { + default: + /* handle HTC control message */ + if (target->CtrlResponseProcessing) { + /* this is a fatal error, target should not be sending unsolicited messages + * on the endpoint 0 */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC Rx Ctrl still processing\n")); + status = A_ERROR; + VOS_BUG(FALSE); + break; + } + + LOCK_HTC_RX(target); + target->CtrlResponseLength = min((int)netlen,HTC_MAX_CONTROL_MESSAGE_LENGTH); + A_MEMCPY(target->CtrlResponseBuffer,netdata,target->CtrlResponseLength); + + /* Requester will clear this flag */ + target->CtrlResponseProcessing = TRUE; + UNLOCK_HTC_RX(target); + + adf_os_mutex_release(target->osdev, &target->CtrlResponseValid); + break; + case HTC_MSG_SEND_SUSPEND_COMPLETE: + wow_nack = 0; + LOCK_HTC_CREDIT(target); + htc_credit_record(HTC_SUSPEND_ACK, pEndpoint->TxCredits, + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)); + UNLOCK_HTC_CREDIT(target); + target->HTCInitInfo.TargetSendSuspendComplete((void *)&wow_nack); + HTCsuspendwow(target); + break; + case HTC_MSG_NACK_SUSPEND: + wow_nack = 1; + LOCK_HTC_CREDIT(target); + htc_credit_record(HTC_SUSPEND_NACK, pEndpoint->TxCredits, + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)); + UNLOCK_HTC_CREDIT(target); + target->HTCInitInfo.TargetSendSuspendComplete((void *)&wow_nack); + break; + } + + adf_nbuf_free(netbuf); + netbuf = NULL; + break; + } + + /* the current message based HIF architecture allocates net bufs for recv packets + * since this layer bridges that HIF to upper layers , which expects HTC packets, + * we form the packets here + * TODO_FIXME */ + pPacket = AllocateHTCPacketContainer(target); + if (NULL == pPacket) { + status = A_NO_RESOURCE; + break; + } + pPacket->Status = A_OK; + pPacket->Endpoint = htc_ep_id; + pPacket->pPktContext = netbuf; + pPacket->pBuffer = adf_nbuf_data(netbuf) + HTC_HDR_LENGTH; + pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen; + + adf_nbuf_pull_head(netbuf, HTC_HEADER_LEN); + adf_nbuf_set_pktlen(netbuf, pPacket->ActualLength); + + RecvPacketCompletion(target,pEndpoint,pPacket); + /* recover the packet container */ + FreeHTCPacketContainer(target,pPacket); + netbuf = NULL; + + } while(FALSE); + +#ifdef RX_SG_SUPPORT +_out: +#endif + + if (netbuf != NULL) { + adf_nbuf_free(netbuf); + } + + return status; + +} + +A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pFirstPacket; + A_STATUS status = A_OK; + HTC_PACKET *pPacket; + + pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); + + if (NULL == pFirstPacket) { + A_ASSERT(FALSE); + return A_EINVAL; + } + + AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n", + pFirstPacket->Endpoint, + HTC_PACKET_QUEUE_DEPTH(pPktQueue), + pFirstPacket->BufferLength)); + + pEndpoint = &target->EndPoint[pFirstPacket->Endpoint]; + + LOCK_HTC_RX(target); + + do { + + if (HTC_STOPPING(target)) { + status = A_ERROR; + break; + } + + /* store receive packets */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue,pPktQueue); + + } while (FALSE); + + UNLOCK_HTC_RX(target); + + if (A_FAILED(status)) { + /* walk through queue and mark each one canceled */ + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + pPacket->Status = A_ECANCELED; + } HTC_PACKET_QUEUE_ITERATE_END; + + DoRecvCompletion(pEndpoint,pPktQueue); + } + + return status; +} + + +A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) +{ + HTC_PACKET_QUEUE queue; + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + return HTCAddReceivePktMultiple(HTCHandle, &queue); +} + +void HTCFlushRxHoldQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint) +{ + HTC_PACKET *pPacket; + HTC_PACKET_QUEUE container; + + LOCK_HTC_RX(target); + + while (1) { + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBufferHoldQueue); + if (NULL == pPacket) { + break; + } + UNLOCK_HTC_RX(target); + pPacket->Status = A_ECANCELED; + pPacket->ActualLength = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:%p, length:%d, ep:%d \n", + pPacket, pPacket->BufferLength, pPacket->Endpoint)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + /* give the packet back */ + DoRecvCompletion(pEndpoint,&container); + LOCK_HTC_RX(target); + } + + UNLOCK_HTC_RX(target); +} + +void HTCRecvInit(HTC_TARGET *target) +{ + /* Initialize CtrlResponseValid to block */ + adf_os_init_mutex(&target->CtrlResponseValid); + adf_os_mutex_acquire(target->osdev, &target->CtrlResponseValid); +} + + + /* polling routine to wait for a control packet to be received */ +A_STATUS HTCWaitRecvCtrlMessage(HTC_TARGET *target) +{ +// int count = HTC_TARGET_MAX_RESPONSE_POLL; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HTCWaitCtrlMessageRecv\n")); + + /* Wait for BMI request/response transaction to complete */ + while (adf_os_mutex_acquire(target->osdev, &target->CtrlResponseValid)) { + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HTCWaitCtrlMessageRecv success\n")); + return A_OK; +} + +static A_STATUS HTCProcessTrailer(HTC_TARGET *target, + A_UINT8 *pBuffer, + int Length, + HTC_ENDPOINT_ID FromEndpoint) +{ + HTC_RECORD_HDR *pRecord; + A_UINT8 htc_rec_id; + A_UINT8 htc_rec_len; + A_UINT8 *pRecordBuf; + A_UINT8 *pOrigBuffer; + int origLength; + A_STATUS status; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length)); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer"); + } + + pOrigBuffer = pBuffer; + origLength = Length; + status = A_OK; + + while (Length > 0) { + + if (Length < sizeof(HTC_RECORD_HDR)) { + status = A_EPROTO; + break; + } + /* these are byte aligned structs */ + pRecord = (HTC_RECORD_HDR *)pBuffer; + Length -= sizeof(HTC_RECORD_HDR); + pBuffer += sizeof(HTC_RECORD_HDR); + + htc_rec_len = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, LENGTH); + htc_rec_id = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, RECORDID); + + if (htc_rec_len > Length) { + /* no room left in buffer for record */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" invalid record length: %d (id:%d) buffer has: %d bytes left \n", + htc_rec_len, htc_rec_id, Length)); + status = A_EPROTO; + break; + } + /* start of record follows the header */ + pRecordBuf = pBuffer; + + switch (htc_rec_id) { + case HTC_RECORD_CREDITS: + AR_DEBUG_ASSERT(htc_rec_len >= sizeof(HTC_CREDIT_REPORT)); + HTCProcessCreditRpt(target, + (HTC_CREDIT_REPORT *)pRecordBuf, + htc_rec_len / (sizeof(HTC_CREDIT_REPORT)), + FromEndpoint); + break; + +#ifdef HIF_SDIO + case HTC_RECORD_LOOKAHEAD: + /* Process in HIF layer */ + break; + + case HTC_RECORD_LOOKAHEAD_BUNDLE: + /* Process in HIF layer */ + break; +#endif /* HIF_SDIO */ + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" HTC unhandled record: id:%d length:%d \n", + htc_rec_id, htc_rec_len)); + break; + } + + if (A_FAILED(status)) { + break; + } + + /* advance buffer past this record for next time around */ + pBuffer += htc_rec_len; + Length -= htc_rec_len; + } + + if (A_FAILED(status)) { + DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer"); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n")); + return status; + +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c new file mode 100644 index 000000000000..f343ff03d7e4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c @@ -0,0 +1,1844 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +#include "htc_debug.h" +#include "htc_internal.h" +#include /* adf_nbuf_t */ +#include /* adf_os_mem_alloc */ +#include +#include "epping_main.h" + +#define HTC_DATA_RESOURCE_THRS 256 +#define HTC_DATA_MINDESC_PERPACKET 2 + +typedef enum _HTC_SEND_QUEUE_RESULT { + HTC_SEND_QUEUE_OK = 0, /* packet was queued */ + HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */ +} HTC_SEND_QUEUE_RESULT; + +#ifndef DEBUG_CREDIT +#define DEBUG_CREDIT 0 +#endif + +#if DEBUG_CREDIT +/* bit mask to enable debug certain endpoint */ +static unsigned ep_debug_mask = (1 << ENDPOINT_0) | (1 << ENDPOINT_1) | (1 << ENDPOINT_2); +#endif + +/* HTC Control Path Credit History */ +A_UINT32 g_htc_credit_history_idx = 0; +HTC_CREDIT_HISTORY htc_credit_history_buffer[HTC_CREDIT_HISTORY_MAX]; + +void htc_credit_record(htc_credit_exchange_type type, A_UINT32 tx_credit, + A_UINT32 htc_tx_queue_depth) +{ + if (HTC_CREDIT_HISTORY_MAX <= g_htc_credit_history_idx) + g_htc_credit_history_idx = 0; + + htc_credit_history_buffer[g_htc_credit_history_idx].type = type; + htc_credit_history_buffer[g_htc_credit_history_idx].time = + adf_get_boottime(); + htc_credit_history_buffer[g_htc_credit_history_idx].tx_credit = tx_credit; + htc_credit_history_buffer[g_htc_credit_history_idx].htc_tx_queue_depth = + htc_tx_queue_depth; + g_htc_credit_history_idx++; +} + +void HTC_dump_counter_info(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("\n%s: CE_send_cnt = %d, TX_comp_cnt = %d\n", + __func__, target->CE_send_cnt, target->TX_comp_cnt)); +} + +void HTCGetControlEndpointTxHostCredits(HTC_HANDLE HTCHandle, int *credits) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + int i; + + if (!credits || !target) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: invalid args", __func__)); + return; + } + + *credits = 0; + LOCK_HTC_TX(target); + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { + *credits = pEndpoint->TxCredits; + break; + } + } + UNLOCK_HTC_TX(target); +} + +static INLINE void RestoreTxPacket(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + if (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) { + adf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + adf_nbuf_unmap(target->osdev, netbuf, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR)); + pPacket->PktInfo.AsTx.Flags &= ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF; + } + +} + +static void DoSendCompletion(HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueueToIndicate) +{ + do { + + if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { + /* nothing to indicate */ + break; + } + + if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n", + pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); + /* a multiple send complete handler is being used, pass the queue to the handler */ + pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.pContext, + pQueueToIndicate); + /* all packets are now owned by the callback, reset queue to be safe */ + INIT_HTC_PACKET_QUEUE(pQueueToIndicate); + } else { + HTC_PACKET *pPacket; + /* using legacy EpTxComplete */ + do { + pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send complete callback on packet %p \n", + pEndpoint->Id, pPacket)); + pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket); + } while (!HTC_QUEUE_EMPTY(pQueueToIndicate)); + } + + } while (FALSE); + +} + +static void SendPacketCompletion(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint]; + HTC_PACKET_QUEUE container; + + RestoreTxPacket(target, pPacket); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + + /* do completion */ + DoSendCompletion(pEndpoint,&container); +} + +void +HTCSendCompleteCheckCleanup(void *context) +{ + HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context; + HTCSendCompleteCheck(pEndpoint, 1); +} + + +HTC_PACKET *AllocateHTCBundleTxPacket(HTC_TARGET *target) +{ + HTC_PACKET *pPacket; + HTC_PACKET_QUEUE *pQueueSave; + adf_nbuf_t netbuf; + + LOCK_HTC_TX(target); + if (NULL == target->pBundleFreeTxList) { + UNLOCK_HTC_TX(target); + + /* for HTT packets, if AltDataCreditSize is non zero, we will have + allocated more space per packet (i.e., TargetCreditSize-AltDataCreditSize) + per bundle packet, but this should is required since we reuse the packet + for all services and all endpoints */ + + netbuf = adf_nbuf_alloc(NULL, + HTC_MAX_MSG_PER_BUNDLE_TX * target->TargetCreditSize, + 0, + 4, + FALSE); + AR_DEBUG_ASSERT(netbuf); + if (!netbuf) + { + return NULL; + } + pPacket = adf_os_mem_alloc(NULL, sizeof(HTC_PACKET)); + AR_DEBUG_ASSERT(pPacket); + if (!pPacket) + { + adf_nbuf_free(netbuf); + return NULL; + } + pQueueSave = adf_os_mem_alloc(NULL, sizeof(HTC_PACKET_QUEUE)); + AR_DEBUG_ASSERT(pQueueSave); + if (!pQueueSave) + { + adf_nbuf_free(netbuf); + adf_os_mem_free(pPacket); + return NULL; + } + INIT_HTC_PACKET_QUEUE(pQueueSave); + pPacket->pContext = pQueueSave; + SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); + pPacket->pBuffer = adf_nbuf_data(netbuf); + pPacket->BufferLength = adf_nbuf_len(netbuf); + + //store the original head room so that we can restore this when we "free" the packet + //free packet puts the packet back on the free list + pPacket->netbufOrigHeadRoom = adf_nbuf_headroom(netbuf); + return pPacket; + } + + //already done malloc - restore from free list + pPacket = target->pBundleFreeTxList; + AR_DEBUG_ASSERT(pPacket); + if (!pPacket) + { + UNLOCK_HTC_TX(target); + return NULL; + } + target->pBundleFreeTxList = (HTC_PACKET *)pPacket->ListLink.pNext; + UNLOCK_HTC_TX(target); + pPacket->ListLink.pNext = NULL; + + return pPacket; +} + +void FreeHTCBundleTxPacket(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + A_UINT32 curentHeadRoom; + adf_nbuf_t netbuf; + HTC_PACKET_QUEUE *pQueueSave; + + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + AR_DEBUG_ASSERT(netbuf); + if (!netbuf) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("\n%s: Invalid netbuf in HTC " + "Packet\n", __func__)); + return; + } + + // HIF adds data to the headroom section of the nbuf, restore the original + // size. If this is not done, headroom keeps shrinking with every HIF send + // and eventually HIF ends up doing another malloc big enough to store the + // data + its header + + curentHeadRoom = adf_nbuf_headroom(netbuf); + adf_nbuf_pull_head(netbuf, pPacket->netbufOrigHeadRoom - curentHeadRoom); + adf_nbuf_trim_tail(netbuf, adf_nbuf_len(netbuf)); + + //restore the pBuffer pointer. HIF changes this + pPacket->pBuffer = adf_nbuf_data(netbuf); + pPacket->BufferLength = adf_nbuf_len(netbuf); + + //restore queue + pQueueSave = (HTC_PACKET_QUEUE*)pPacket->pContext; + AR_DEBUG_ASSERT(pQueueSave); + + INIT_HTC_PACKET_QUEUE(pQueueSave); + + LOCK_HTC_TX(target); + if (target->pBundleFreeTxList == NULL) { + target->pBundleFreeTxList = pPacket; + pPacket->ListLink.pNext = NULL; + } else { + pPacket->ListLink.pNext = (DL_LIST *)target->pBundleFreeTxList; + target->pBundleFreeTxList = pPacket; + } + UNLOCK_HTC_TX(target); +} + +HTC_PACKET *AllocateHTCBundleRxPacket(HTC_TARGET *target) +{ + HTC_PACKET *pPacket; + HTC_PACKET_QUEUE *pQueueSave; + adf_nbuf_t netbuf; + LOCK_HTC_TX(target); + if (NULL == target->pBundleFreeRxList) { + UNLOCK_HTC_TX(target); + netbuf = adf_nbuf_alloc(NULL, + HTC_MAX_MSG_PER_BUNDLE_RX * target->TargetCreditSize, + 0, + 4, + FALSE); + AR_DEBUG_ASSERT(netbuf); + if (!netbuf) + { + return NULL; + } + pPacket = adf_os_mem_alloc(NULL, sizeof(HTC_PACKET)); + AR_DEBUG_ASSERT(pPacket); + if (!pPacket) + { + adf_nbuf_free(netbuf); + return NULL; + } + pQueueSave = adf_os_mem_alloc(NULL, sizeof(HTC_PACKET_QUEUE)); + AR_DEBUG_ASSERT(pQueueSave); + if (!pQueueSave) + { + adf_nbuf_free(netbuf); + adf_os_mem_free(pPacket); + return NULL; + } + INIT_HTC_PACKET_QUEUE(pQueueSave); + pPacket->pContext = pQueueSave; + SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); + pPacket->pBuffer = adf_nbuf_data(netbuf); + pPacket->BufferLength = adf_nbuf_len(netbuf); + + //store the original head room so that we can restore this when we "free" the packet + //free packet puts the packet back on the free list + pPacket->netbufOrigHeadRoom = adf_nbuf_headroom(netbuf); + return pPacket; + } + + //already done malloc - restore from free list + pPacket = target->pBundleFreeRxList; + AR_DEBUG_ASSERT(pPacket); + if (!pPacket) + { + UNLOCK_HTC_TX(target); + return NULL; + } + target->pBundleFreeRxList = (HTC_PACKET *)pPacket->ListLink.pNext; + UNLOCK_HTC_TX(target); + pPacket->ListLink.pNext = NULL; + + return pPacket; +} + +void FreeHTCBundleRxPacket(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + A_UINT32 curentHeadRoom; + adf_nbuf_t netbuf; + HTC_PACKET_QUEUE *pQueueSave; + + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + AR_DEBUG_ASSERT(netbuf); + if (!netbuf) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("\n%s: Invalid netbuf in HTC " + "Packet\n", __func__)); + return; + } + + // HIF adds data to the headroom section of the nbuf, restore the original + // size. If this is not done, headroom keeps shrinking with every HIF send + // and eventually HIF ends up doing another malloc big enough to store the + // data + its header + + curentHeadRoom = adf_nbuf_headroom(netbuf); + adf_nbuf_pull_head(netbuf, pPacket->netbufOrigHeadRoom - curentHeadRoom); + adf_nbuf_trim_tail(netbuf, adf_nbuf_len(netbuf)); + + //restore the pBuffer pointer. HIF changes this + pPacket->pBuffer = adf_nbuf_data(netbuf); + pPacket->BufferLength = adf_nbuf_len(netbuf); + + //restore queue + pQueueSave = (HTC_PACKET_QUEUE*)pPacket->pContext; + AR_DEBUG_ASSERT(pQueueSave); + + INIT_HTC_PACKET_QUEUE(pQueueSave); + + LOCK_HTC_TX(target); + if (target->pBundleFreeRxList == NULL) { + target->pBundleFreeRxList = pPacket; + pPacket->ListLink.pNext = NULL; + } else { + pPacket->ListLink.pNext = (DL_LIST *)target->pBundleFreeRxList; + target->pBundleFreeRxList = pPacket; + } + UNLOCK_HTC_TX(target); +} + + +#if defined(HIF_USB) || defined(HIF_SDIO) +#ifdef ENABLE_BUNDLE_TX +static A_STATUS HTCSendBundledNetbuf(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + unsigned char *pBundleBuffer, + HTC_PACKET *pPacketTx) +{ + adf_os_size_t data_len; + A_STATUS status; + adf_nbuf_t bundleBuf; + bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); + data_len = pBundleBuffer - adf_nbuf_data(bundleBuf); + adf_nbuf_put_tail(bundleBuf, data_len); + SET_HTC_PACKET_INFO_TX(pPacketTx, + target, + pBundleBuffer, + data_len, + pEndpoint->Id, + HTC_TX_PACKET_TAG_BUNDLED); + LOCK_HTC_TX(target); + HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacketTx); + UNLOCK_HTC_TX(target); +#if DEBUG_BUNDLE + adf_os_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.\n", + pEndpoint->Id, + pEndpoint->TxCreditSize, + data_len, + data_len / pEndpoint->TxCreditSize); +#endif + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + if ((data_len / pEndpoint->TxCreditSize) < HTC_MAX_MSG_PER_BUNDLE_TX) { + target->tx_bundle_stats[data_len / pEndpoint->TxCreditSize]++; + } +#endif + + status = HIFSend_head(target->hif_dev, + pEndpoint->UL_PipeID, + pEndpoint->Id, + data_len, + bundleBuf); + if (status != A_OK){ + adf_os_print("%s:HIFSend_head failed(len=%zu).\n", __FUNCTION__, + data_len); + } + return status; +} + +static void HTCIssuePacketsBundle(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pPktQueue) +{ + int i, frag_count, nbytes; + adf_nbuf_t netbuf, bundleBuf; + unsigned char *pBundleBuffer = NULL; + HTC_PACKET *pPacket = NULL, *pPacketTx = NULL; +#ifndef HIF_USB + HTC_FRAME_HDR *pHtcHdr; +#endif + int last_creditPad = 0; + int creditPad, creditRemainder,transferLength, bundlesSpaceRemaining = 0; + HTC_PACKET_QUEUE *pQueueSave = NULL; + + bundlesSpaceRemaining = HTC_MAX_MSG_PER_BUNDLE_TX * pEndpoint->TxCreditSize; + + pPacketTx = AllocateHTCBundleTxPacket(target); + if (!pPacketTx) + { + //good time to panic + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AllocateHTCBundleTxPacket failed \n")); + AR_DEBUG_ASSERT(FALSE); + return; + } + bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); + pBundleBuffer = adf_nbuf_data(bundleBuf); + pQueueSave = (HTC_PACKET_QUEUE*)pPacketTx->pContext; + while (1) { + pPacket = HTC_PACKET_DEQUEUE(pPktQueue); + if (pPacket == NULL){ + break; + } + creditPad = 0; + transferLength = pPacket->ActualLength + HTC_HDR_LENGTH; + creditRemainder = transferLength % pEndpoint->TxCreditSize; + if(creditRemainder != 0){ + if(transferLength < pEndpoint->TxCreditSize){ + creditPad = pEndpoint->TxCreditSize - transferLength; + } else { + creditPad = creditRemainder; + } + transferLength += creditPad; + } + + if (bundlesSpaceRemaining < transferLength){ + /* send out previous buffer */ + HTCSendBundledNetbuf(target, pEndpoint, + pBundleBuffer - last_creditPad, pPacketTx); + if (HTC_PACKET_QUEUE_DEPTH(pPktQueue) < HTC_MIN_MSG_PER_BUNDLE){ + return; + } + bundlesSpaceRemaining = HTC_MAX_MSG_PER_BUNDLE_TX * pEndpoint->TxCreditSize; + pPacketTx = AllocateHTCBundleTxPacket(target); + if (!pPacketTx) + { + //good time to panic + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AllocateHTCBundleTxPacket failed \n")); + AR_DEBUG_ASSERT(FALSE); + return; + } + bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); + pBundleBuffer = adf_nbuf_data(bundleBuf); + pQueueSave = (HTC_PACKET_QUEUE*)pPacketTx->pContext; + } + + bundlesSpaceRemaining -= transferLength; + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); +#ifndef HIF_USB + pHtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(netbuf, 0); + HTC_WRITE32(pHtcHdr, SM(pPacket->ActualLength, HTC_FRAME_HDR_PAYLOADLEN) | + SM(pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEND_BUNDLE, HTC_FRAME_HDR_FLAGS) | + SM(pPacket->Endpoint, HTC_FRAME_HDR_ENDPOINTID)); + HTC_WRITE32((A_UINT32 *)pHtcHdr + 1, + SM(pPacket->PktInfo.AsTx.SeqNo, HTC_FRAME_HDR_CONTROLBYTES1) | + SM(creditPad, HTC_FRAME_HDR_RESERVED)); + pHtcHdr->reserved = creditPad; +#endif + frag_count = adf_nbuf_get_num_frags(netbuf); + nbytes = pPacket->ActualLength + HTC_HDR_LENGTH; + for (i = 0; i < frag_count && nbytes > 0; i ++){ + int frag_len = adf_nbuf_get_frag_len(netbuf, i); + unsigned char *frag_addr = adf_nbuf_get_frag_vaddr(netbuf, i); + if (frag_len > nbytes){ + frag_len = nbytes; + } + A_MEMCPY(pBundleBuffer, frag_addr, frag_len); + nbytes -= frag_len; + pBundleBuffer += frag_len; + } + HTC_PACKET_ENQUEUE(pQueueSave, pPacket); + pBundleBuffer += creditPad; + +#ifdef HIF_USB + /* last one can't be packed. */ + last_creditPad = creditPad; +#endif + } + if (pBundleBuffer != adf_nbuf_data(bundleBuf)){ + /* send out remaining buffer */ + HTCSendBundledNetbuf(target, pEndpoint, + pBundleBuffer - last_creditPad, pPacketTx); + } else { + FreeHTCBundleTxPacket(target, pPacketTx); + } +} +#endif /* ENABLE_BUNDLE_TX */ +#endif + +static A_STATUS HTCIssuePackets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pPktQueue) +{ + A_STATUS status = A_OK; + adf_nbuf_t netbuf; + HTC_PACKET *pPacket = NULL; + u_int16_t payloadLen; + HTC_FRAME_HDR *pHtcHdr; + bool is_tx_runtime_put = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCIssuePackets: Queue: %p, Pkts %d \n", + pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue))); + while (TRUE) { +#if defined(HIF_USB) || defined(HIF_SDIO) +#ifdef ENABLE_BUNDLE_TX + if( +#ifndef HIF_USB + IS_TX_CREDIT_FLOW_ENABLED(pEndpoint) && +#endif + HTC_ENABLE_BUNDLE(target) && + HTC_PACKET_QUEUE_DEPTH(pPktQueue) >= HTC_MIN_MSG_PER_BUNDLE){ + HTCIssuePacketsBundle(target, pEndpoint, pPktQueue); + } +#endif +#endif + /* if not bundling or there was a packet that could not be placed in a bundle, + * and send it by normal way + */ + pPacket = HTC_PACKET_DEQUEUE(pPktQueue); + if(NULL == pPacket){ + /* local queue is fully drained */ + break; + } + + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + AR_DEBUG_ASSERT(netbuf); + /* Non-credit enabled endpoints have been mapped and setup by now, + * so no need to revisit the HTC headers + */ + if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + + payloadLen = pPacket->ActualLength; + /* setup HTC frame header */ + + pHtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(netbuf, 0); + AR_DEBUG_ASSERT(pHtcHdr); + + + HTC_WRITE32(pHtcHdr, SM(payloadLen, HTC_FRAME_HDR_PAYLOADLEN) | + SM(pPacket->PktInfo.AsTx.SendFlags, HTC_FRAME_HDR_FLAGS) | + SM(pPacket->Endpoint, HTC_FRAME_HDR_ENDPOINTID)); + HTC_WRITE32(((A_UINT32 *)pHtcHdr) + 1, + SM(pPacket->PktInfo.AsTx.SeqNo, HTC_FRAME_HDR_CONTROLBYTES1)); + + /* + * Now that the HTC frame header has been added, the netbuf can be + * mapped. This only applies to non-data frames, since data frames + * were already mapped as they entered into the driver. + * Check the "FIXUP_NETBUF" flag to see whether this is a data netbuf + * that is already mapped, or a non-data netbuf that needs to be + * mapped. + */ + if (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) { + adf_nbuf_map( + target->osdev, + GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), + ADF_OS_DMA_TO_DEVICE); + } + } + LOCK_HTC_TX(target); + /* store in look up queue to match completions */ +#ifdef ATH_11AC_TXCOMPACT + if (HTT_DATA_MSG_SVC != pEndpoint->ServiceID) +#endif /* ATH_11AC_TXCOMPACT */ + { + HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue,pPacket); + } + INC_HTC_EP_STAT(pEndpoint,TxIssued,1); + pEndpoint->ul_outstanding_cnt++; + UNLOCK_HTC_TX(target); + + if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT) + is_tx_runtime_put = true; + + status = HIFSend_head(target->hif_dev, + pEndpoint->UL_PipeID, pEndpoint->Id, + HTC_HDR_LENGTH + pPacket->ActualLength, + netbuf); +#if DEBUG_BUNDLE + adf_os_print(" Send single EP%d buffer size:0x%x, total:0x%x.\n", + pEndpoint->Id, + pEndpoint->TxCreditSize, + HTC_HDR_LENGTH + pPacket->ActualLength); +#endif + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + target->tx_bundle_stats[0]++; +#endif + + target->CE_send_cnt++; + + if (adf_os_unlikely(A_FAILED(status))) { + if (status != A_NO_RESOURCE) { + /* TODO : if more than 1 endpoint maps to the same PipeID it is possible + * to run out of resources in the HIF layer. Don't emit the error */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HIFSend Failed status:%d \n",status)); + } + LOCK_HTC_TX(target); + target->CE_send_cnt--; + pEndpoint->ul_outstanding_cnt--; + HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue,pPacket); + /* reclaim credits */ + pEndpoint->TxCredits += pPacket->PktInfo.AsTx.CreditsUsed; + /* put it back into the callers queue */ + HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue,pPacket); + UNLOCK_HTC_TX(target); + break; + } + + /* + * For HTT messages the Tx complete is disabled and for some HTT + * messages which doesn't have response from FW, runtime pm put + * is not happening. To address that the HTT packet which is tagged + * with HTC_TX_PACKET_TAG_RUNTIME_PUT releases the count after the + * packet sent is successful + */ + if (is_tx_runtime_put) { + is_tx_runtime_put = false; + hif_pm_runtime_put(target->hif_dev); + } + } + + if (adf_os_unlikely(A_FAILED(status))) { + while (!HTC_QUEUE_EMPTY(pPktQueue)) { + if (status != A_NO_RESOURCE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCIssuePackets, failed pkt:0x%p status:%d \n",pPacket,status)); + } + pPacket = HTC_PACKET_DEQUEUE(pPktQueue); + if (pPacket) { + pPacket->Status = status; + hif_pm_runtime_put(target->hif_dev); + SendPacketCompletion(target,pPacket); + } + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCIssuePackets \n")); + + return status; +} + +#ifdef FEATURE_RUNTIME_PM +static void GetHTCAutoPmSendPackets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue) +{ + HTC_PACKET *pPacket; + /* + * If the EP is not WMI EP then it is not required to go through + * the queue to find the tagged packkets. + */ + if (pEndpoint->ServiceID != WMI_CONTROL_SVC) + return; + + ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, + HTC_PACKET, ListLink) { + + if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM) + continue; + + HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket); + HTC_PACKET_ENQUEUE(pQueue, pPacket); + } ITERATE_END +} + +static void RequeueHTCAutoPmSendPackets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue) +{ + if (pEndpoint->ServiceID != WMI_CONTROL_SVC) + return; + + /* + * Go through remaining packets in the temporary queue and add them to + * head of the queue so that those would be sent at priority than other + * packets + */ + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, pQueue); +} +#else +static inline void GetHTCAutoPmSendPackets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue) +{ + return; +} +static inline void RequeueHTCAutoPmSendPackets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue) +{ + return; +} +#endif + + /* get HTC send packets from the TX queue on an endpoint, based on available credits */ +void GetHTCSendPacketsCreditBased(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue) +{ + int creditsRequired; + int remainder; + A_UINT8 sendFlags; + HTC_PACKET *pPacket; + unsigned int transferLength; + HTC_PACKET_QUEUE *pTxQueue; + HTC_PACKET_QUEUE tempQueue; + A_BOOL AutoPMQueue = FALSE; + + /****** NOTE : the TX lock is held when this function is called *****************/ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPacketsCreditBased \n")); + + INIT_HTC_PACKET_QUEUE(&tempQueue); + + GetHTCAutoPmSendPackets(target, pEndpoint, &tempQueue); + + if (!HTC_QUEUE_EMPTY(&tempQueue)) { + pTxQueue = &tempQueue; + AutoPMQueue = TRUE; + } else + pTxQueue = &pEndpoint->TxQueue; + + /* loop until we can grab as many packets out of the queue as we can */ + while (TRUE) { + + sendFlags = 0; + + if (!AutoPMQueue && hif_pm_runtime_get(target->hif_dev)) { + A_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0); + break; + } + + /* get packet at head, but don't remove it */ + pPacket = HTC_GET_PKT_AT_HEAD(pTxQueue); + if (pPacket == NULL) { + if (!AutoPMQueue) + hif_pm_runtime_put(target->hif_dev); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:%p , Queue Depth: %d\n", + pPacket, HTC_PACKET_QUEUE_DEPTH(pTxQueue))); + + transferLength = pPacket->ActualLength + HTC_HDR_LENGTH; + + if (transferLength <= pEndpoint->TxCreditSize) { + creditsRequired = 1; + } else { + /* figure out how many credits this message requires */ + creditsRequired = transferLength / pEndpoint->TxCreditSize; + remainder = transferLength % pEndpoint->TxCreditSize; + + if (remainder) { + creditsRequired++; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Credits Required:%d Got:%d\n", + creditsRequired, pEndpoint->TxCredits)); + + if (pEndpoint->Id == ENDPOINT_0) { + /* endpoint 0 is special, it always has a credit and does not require credit based + * flow control */ + creditsRequired = 0; + } else { + + if (pEndpoint->TxCredits < creditsRequired) { +#if DEBUG_CREDIT + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" EP%d, No Credit now. %d < %d\n", + pEndpoint->Id, pEndpoint->TxCredits, creditsRequired)); +#endif + if (!AutoPMQueue) + hif_pm_runtime_put(target->hif_dev); + break; + } + + pEndpoint->TxCredits -= creditsRequired; + INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired); + + /* check if we need credits back from the target */ + if (pEndpoint->TxCredits <= pEndpoint->TxCreditsPerMaxMsg) { + /* tell the target we need credits ASAP! */ + sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; + + if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { + LOCK_HTC_CREDIT(target); + htc_credit_record(HTC_REQUEST_CREDIT, pEndpoint->TxCredits, + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)); + UNLOCK_HTC_CREDIT(target); + } + + INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1); +#if DEBUG_CREDIT + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" EP%d Needs Credits\n", pEndpoint->Id)); +#endif + } + } + + /* now we can fully dequeue */ + pPacket = HTC_PACKET_DEQUEUE(pTxQueue); + if (pPacket) { + /* save the number of credits this packet consumed */ + pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired; + /* save send flags */ + pPacket->PktInfo.AsTx.SendFlags = sendFlags; + + /* queue this packet into the caller's queue */ + HTC_PACKET_ENQUEUE(pQueue,pPacket); + } + } + + if (AutoPMQueue) + RequeueHTCAutoPmSendPackets(target, pEndpoint, &tempQueue); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPacketsCreditBased \n")); +} + +void GetHTCSendPackets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue, + int Resources) +{ + + HTC_PACKET *pPacket; + HTC_PACKET_QUEUE *pTxQueue; + HTC_PACKET_QUEUE tempQueue; + A_BOOL AutoPMQueue = FALSE; + + /****** NOTE : the TX lock is held when this function is called *****************/ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets %d resources\n",Resources)); + + INIT_HTC_PACKET_QUEUE(&tempQueue); + + GetHTCAutoPmSendPackets(target, pEndpoint, &tempQueue); + + if (!HTC_QUEUE_EMPTY(&tempQueue)) { + pTxQueue = &tempQueue; + AutoPMQueue = TRUE; + } else + pTxQueue = &pEndpoint->TxQueue; + /* loop until we can grab as many packets out of the queue as we can */ + while (Resources > 0) { + int num_frags; + + if (!AutoPMQueue && hif_pm_runtime_get(target->hif_dev)) { + A_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0); + break; + } + + pPacket = HTC_PACKET_DEQUEUE(pTxQueue); + if (pPacket == NULL) { + if (!AutoPMQueue) + hif_pm_runtime_put(target->hif_dev); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got packet:%p , New Queue Depth: %d\n", + pPacket, HTC_PACKET_QUEUE_DEPTH(pTxQueue))); + /* For non-credit path the sequence number is already embedded + * in the constructed HTC header + */ +#if 0 + pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; + pEndpoint->SeqNo++; +#endif + pPacket->PktInfo.AsTx.SendFlags = 0; + pPacket->PktInfo.AsTx.CreditsUsed = 0; + /* queue this packet into the caller's queue */ + HTC_PACKET_ENQUEUE(pQueue,pPacket); + + /* + * FIX THIS: + * For now, avoid calling adf_nbuf_get_num_frags before calling + * adf_nbuf_map, because the MacOS version of adf_nbuf_t doesn't + * support adf_nbuf_get_num_frags until after adf_nbuf_map has + * been done. + * Assume that the non-data netbufs, i.e. the WMI message netbufs, + * consist of a single fragment. + */ + num_frags = + (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) ? + 1 /* WMI messages are in a single-fragment network buffer */ : + adf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)); + Resources -= num_frags; + } + + if (AutoPMQueue) + RequeueHTCAutoPmSendPackets(target, pEndpoint, &tempQueue); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n")); + +} + +static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pCallersSendQueue) +{ + HTC_PACKET_QUEUE sendQueue; /* temp queue to hold packets at various stages */ + HTC_PACKET *pPacket; + int tx_resources; + int overflow; + HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:%p Depth:%d)\n", + pCallersSendQueue, + (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue))); + + /* init the local send queue */ + INIT_HTC_PACKET_QUEUE(&sendQueue); + + do { + + if (NULL == pCallersSendQueue) { + /* caller didn't provide a queue, just wants us to check queues and send */ + break; + } + + if (HTC_QUEUE_EMPTY(pCallersSendQueue)) { + /* empty queue */ + OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,HTC_PKT_Q_EMPTY); + result = HTC_SEND_QUEUE_DROP; + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueueDepth) { + /* we've already overflowed */ + overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); + } else { + /* figure out how much we will overflow by */ + overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); + /* figure out how much we will overflow the TX queue by */ + overflow -= pEndpoint->MaxTxQueueDepth; + } + + /* if overflow is negative or zero, we are okay */ + if (overflow > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n", + pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue), pEndpoint->MaxTxQueueDepth)); + } + if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) { + /* all packets will fit or caller did not provide send full indication handler + * -- just move all of them to the local sendQueue object */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue); + } else { + int i; + int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - overflow; + + A_ASSERT(goodPkts >= 0); + /* we have overflowed, and a callback is provided */ + /* dequeue all non-overflow packets into the sendqueue */ + for (i = 0; i < goodPkts; i++) { + /* pop off caller's queue*/ + pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue); + A_ASSERT(pPacket != NULL); + /* insert into local queue */ + HTC_PACKET_ENQUEUE(&sendQueue,pPacket); + } + + /* the caller's queue has all the packets that won't fit*/ + /* walk through the caller's queue and indicate each one to the send full handler */ + ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, HTC_PACKET, ListLink) { + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: %p \n", + pPacket)); + /* + * Remove headroom reserved for HTC_FRAME_HDR before giving + * the packet back to the user via the EpSendFull callback. + */ + RestoreTxPacket(target, pPacket); + + if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext, + pPacket) == HTC_SEND_FULL_DROP) { + /* callback wants the packet dropped */ + INC_HTC_EP_STAT(pEndpoint, TxDropped, 1); + /* leave this one in the caller's queue for cleanup */ + } else { + /* callback wants to keep this packet, remove from caller's queue */ + HTC_PACKET_REMOVE(pCallersSendQueue, pPacket); + /* put it in the send queue */ + /* add HTC_FRAME_HDR space reservation again */ + adf_nbuf_push_head( + GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), + sizeof(HTC_FRAME_HDR)); + + HTC_PACKET_ENQUEUE(&sendQueue,pPacket); + } + + } ITERATE_END; + + if (HTC_QUEUE_EMPTY(&sendQueue)) { + /* no packets made it in, caller will cleanup */ + OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,HTC_SEND_Q_EMPTY); + result = HTC_SEND_QUEUE_DROP; + break; + } + } + + } while (FALSE); + + if (result != HTC_SEND_QUEUE_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); + return result; + } + + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + tx_resources = HIFGetFreeQueueNumber(target->hif_dev,pEndpoint->UL_PipeID); + } else { + tx_resources = 0; + } + + LOCK_HTC_TX(target); + + if (!HTC_QUEUE_EMPTY(&sendQueue)) { + /* transfer packets to tail */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue); + A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue)); + INIT_HTC_PACKET_QUEUE(&sendQueue); + } + + /* increment tx processing count on entry */ + adf_os_atomic_inc(&pEndpoint->TxProcessCount); + if (adf_os_atomic_read(&pEndpoint->TxProcessCount) > 1) { + /* another thread or task is draining the TX queues on this endpoint + * that thread will reset the tx processing count when the queue is drained */ + adf_os_atomic_dec(&pEndpoint->TxProcessCount); + UNLOCK_HTC_TX(target); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n")); + return HTC_SEND_QUEUE_OK; + } + + /***** beyond this point only 1 thread may enter ******/ + + /* now drain the endpoint TX queue for transmission as long as we have enough + * transmit resources */ + while (TRUE) { + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) { + break; + } + + if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { +#if DEBUG_CREDIT + int cred = pEndpoint->TxCredits; +#endif + /* credit based mechanism provides flow control based on target transmit resource availability, we + * assume that the HIF layer will always have bus resources greater than target transmit resources */ + GetHTCSendPacketsCreditBased(target,pEndpoint,&sendQueue); +#if DEBUG_CREDIT + if (ep_debug_mask & (1 << pEndpoint->Id)){ + if (cred - pEndpoint->TxCredits > 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Decrease EP%d %d - %d = %d credits.\n", + pEndpoint->Id, cred, cred - pEndpoint->TxCredits, pEndpoint->TxCredits)); + } + } +#endif + } else { +#ifdef HIF_USB +#ifdef ENABLE_BUNDLE_TX + /* + * Header and payload belongs to the different fragments and + * consume 2 resource for one HTC package but USB conbime into + * one transfer. + */ + if (HTC_ENABLE_BUNDLE(target) && tx_resources) { + tx_resources = (HTC_MAX_MSG_PER_BUNDLE_TX * 2); + } +#endif +#endif + /* get all the packets for this endpoint that we can for this pass */ + GetHTCSendPackets(target,pEndpoint,&sendQueue,tx_resources); + } + + if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) { + /* didn't get any packets due to a lack of resources or TX queue was drained */ + break; + } + + UNLOCK_HTC_TX(target); + + /* send what we can */ + HTCIssuePackets(target,pEndpoint,&sendQueue); + + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + tx_resources = HIFGetFreeQueueNumber(target->hif_dev,pEndpoint->UL_PipeID); + } + + LOCK_HTC_TX(target); + + } + + /* done with this endpoint, we can clear the count */ + adf_os_atomic_init(&pEndpoint->TxProcessCount); + UNLOCK_HTC_TX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); + + return HTC_SEND_QUEUE_OK; +} + +A_STATUS HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pPacket; + adf_nbuf_t netbuf; + HTC_FRAME_HDR *pHtcHdr; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: %p, Pkts %d \n", + pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue))); + + /* get packet at head to figure out which endpoint these packets will go into */ + pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); + if (NULL == pPacket) { + OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target,GET_HTC_PKT_Q_FAIL); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n")); + return A_EINVAL; + } + + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + + if (!pEndpoint->ServiceID) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s: ServiceID is invalid\n", + __func__)); + return A_EINVAL; + } + +#ifdef HTC_EP_STAT_PROFILING + LOCK_HTC_TX(target); + INC_HTC_EP_STAT(pEndpoint,TxPosted,HTC_PACKET_QUEUE_DEPTH(pPktQueue)); + UNLOCK_HTC_TX(target); +#endif + + /* provide room in each packet's netbuf for the HTC frame header */ + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + AR_DEBUG_ASSERT(netbuf); + + adf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); + /* setup HTC frame header */ + pHtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(netbuf, 0); + AR_DEBUG_ASSERT(pHtcHdr); + HTC_WRITE32(pHtcHdr, SM(pPacket->ActualLength, HTC_FRAME_HDR_PAYLOADLEN) | + SM(pPacket->Endpoint, HTC_FRAME_HDR_ENDPOINTID)); + + LOCK_HTC_TX(target); + + pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; + pEndpoint->SeqNo++; + + HTC_WRITE32(((A_UINT32 *)pHtcHdr) + 1, + SM(pPacket->PktInfo.AsTx.SeqNo, HTC_FRAME_HDR_CONTROLBYTES1)); + + UNLOCK_HTC_TX(target); + /* + * Now that the HTC frame header has been added, the netbuf can be + * mapped. This only applies to non-data frames, since data frames + * were already mapped as they entered into the driver. + */ + adf_nbuf_map( + target->osdev, + GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), + ADF_OS_DMA_TO_DEVICE); + + pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF; + } HTC_PACKET_QUEUE_ITERATE_END; + + HTCTrySend(target,pEndpoint,pPktQueue); + + /* do completion on any packets that couldn't get in */ + if (!HTC_QUEUE_EMPTY(pPktQueue)) { + + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + /* remove the headroom reserved for HTC_FRAME_HDR */ + RestoreTxPacket(target, pPacket); + + if (HTC_STOPPING(target)) { + pPacket->Status = A_ECANCELED; + } else { + pPacket->Status = A_NO_RESOURCE; + } + } HTC_PACKET_QUEUE_ITERATE_END; + + DoSendCompletion(pEndpoint,pPktQueue); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n")); + + return A_OK; +} + +/* HTC API - HTCSendPkt */ +A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) +{ + HTC_PACKET_QUEUE queue; + + if (HTCHandle == NULL || pPacket == NULL) { + return A_ERROR; + } + a_mem_trace(GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+-HTCSendPkt: Enter endPointId: %d, buffer: %p, length: %d \n", + pPacket->Endpoint, pPacket->pBuffer, pPacket->ActualLength)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + return HTCSendPktsMultiple(HTCHandle, &queue); +} + +#ifdef ATH_11AC_TXCOMPACT + +A_STATUS HTCSendDataPkt(HTC_HANDLE HTCHandle, adf_nbuf_t netbuf, int Epid, int ActualLength) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + HTC_FRAME_HDR *pHtcHdr; + A_STATUS status = A_OK; + int tx_resources; + + pEndpoint = &target->EndPoint[Epid]; + + tx_resources = HIFGetFreeQueueNumber(target->hif_dev, pEndpoint->UL_PipeID); + + if(tx_resources < HTC_DATA_RESOURCE_THRS){ + if (pEndpoint->ul_is_polled){ + HIFSendCompleteCheck( + pEndpoint->target->hif_dev, pEndpoint->UL_PipeID, 1); + tx_resources = HIFGetFreeQueueNumber(target->hif_dev, pEndpoint->UL_PipeID); + } + if(tx_resources < HTC_DATA_MINDESC_PERPACKET){ + return A_ERROR; + } + } + + if (hif_pm_runtime_get(target->hif_dev)) + return A_ERROR; + + pHtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(netbuf, 0); + AR_DEBUG_ASSERT(pHtcHdr); + + HTC_WRITE32(pHtcHdr, SM(ActualLength, HTC_FRAME_HDR_PAYLOADLEN) | + SM(Epid, HTC_FRAME_HDR_ENDPOINTID)); + /* + * If the HIF pipe for the data endpoint is polled rather than + * interrupt-driven, this is a good point to check whether any + * data previously sent through the HIF pipe have finished being + * sent. + * Since this may result in callbacks to HTCTxCompletionHandler, + * which can take the HTC tx lock, make the HIFSendCompleteCheck + * call before acquiring the HTC tx lock. + * Call HIFSendCompleteCheck directly, rather than calling + * HTCSendCompleteCheck, and call the PollTimerStart separately + * after calling HIFSend_head, so the timer will be started to + * check for completion of the new outstanding download (in the + * unexpected event that other polling calls don't catch it). + */ + + LOCK_HTC_TX(target); + + HTC_WRITE32(((A_UINT32 *)pHtcHdr) + 1, SM(pEndpoint->SeqNo, HTC_FRAME_HDR_CONTROLBYTES1)); + + pEndpoint->SeqNo++; + + status = HIFSend_head(target->hif_dev, + pEndpoint->UL_PipeID, + pEndpoint->Id, + ActualLength, + netbuf); + + + UNLOCK_HTC_TX(target); + return status ; +} +#else /*ATH_11AC_TXCOMPACT*/ + +A_STATUS HTCSendDataPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, + A_UINT8 more_data) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + HTC_FRAME_HDR *pHtcHdr; + HTC_PACKET_QUEUE sendQueue; + adf_nbuf_t netbuf; + int tx_resources; + A_STATUS status = A_OK; + if (pPacket){ + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + + /* add HTC_FRAME_HDR in the initial fragment */ + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + pHtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(netbuf, 0); + AR_DEBUG_ASSERT(pHtcHdr); + + if (pPacket->ActualLength > (pEndpoint->TxCreditSize - HTC_HDR_LENGTH)) { + pPacket->ActualLength = pEndpoint->TxCreditSize - HTC_HDR_LENGTH; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Packet Length %d exceeds endpoint credit size %d, set the packet length to credit size\n", + pPacket->ActualLength, pEndpoint->TxCreditSize)); + } + HTC_WRITE32(pHtcHdr, SM(pPacket->ActualLength, HTC_FRAME_HDR_PAYLOADLEN) | + SM(pPacket->PktInfo.AsTx.SendFlags, HTC_FRAME_HDR_FLAGS) | + SM(pPacket->Endpoint, HTC_FRAME_HDR_ENDPOINTID)); + /* + * If the HIF pipe for the data endpoint is polled rather than + * interrupt-driven, this is a good point to check whether any + * data previously sent through the HIF pipe have finished being + * sent. + * Since this may result in callbacks to HTCTxCompletionHandler, + * which can take the HTC tx lock, make the HIFSendCompleteCheck + * call before acquiring the HTC tx lock. + * Call HIFSendCompleteCheck directly, rather than calling + * HTCSendCompleteCheck, and call the PollTimerStart separately + * after calling HIFSend_head, so the timer will be started to + * check for completion of the new outstanding download (in the + * unexpected event that other polling calls don't catch it). + */ + if (pEndpoint->ul_is_polled) { + HTCSendCompletePollTimerStop(pEndpoint); + HIFSendCompleteCheck( + pEndpoint->target->hif_dev, pEndpoint->UL_PipeID, 0); + } + + LOCK_HTC_TX(target); + + pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; + pEndpoint->SeqNo++; + + + HTC_WRITE32(((A_UINT32 *)pHtcHdr) + 1, SM(pPacket->PktInfo.AsTx.SeqNo, HTC_FRAME_HDR_CONTROLBYTES1)); + + /* append new packet to pEndpoint->TxQueue */ + HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue, pPacket); +#ifdef ENABLE_BUNDLE_TX + if (HTC_ENABLE_BUNDLE(target) && (more_data)) { + UNLOCK_HTC_TX(target); + return A_OK; + } +#endif + } else { + LOCK_HTC_TX(target); + pEndpoint = &target->EndPoint[1]; + } + + /* increment tx processing count on entry */ + adf_os_atomic_inc(&pEndpoint->TxProcessCount); + if (adf_os_atomic_read(&pEndpoint->TxProcessCount) > 1) { + /* + * Another thread or task is draining the TX queues on this endpoint. + * That thread will reset the tx processing count when the queue is + * drained. + */ + adf_os_atomic_dec(&pEndpoint->TxProcessCount); + UNLOCK_HTC_TX(target); + return A_OK; + } + + /***** beyond this point only 1 thread may enter ******/ + + INIT_HTC_PACKET_QUEUE(&sendQueue); + if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { +#if DEBUG_CREDIT + int cred = pEndpoint->TxCredits; +#endif + GetHTCSendPacketsCreditBased(target, pEndpoint, &sendQueue); +#if DEBUG_CREDIT + if (ep_debug_mask & (1 << pEndpoint->Id)){ + if (cred - pEndpoint->TxCredits > 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Decrease EP%d %d - %d = %d credits.\n", + pEndpoint->Id, cred, cred - pEndpoint->TxCredits, pEndpoint->TxCredits)); + } + } +#endif + UNLOCK_HTC_TX(target); + } +#ifdef ENABLE_BUNDLE_TX + else if (HTC_ENABLE_BUNDLE(target)) { +#ifdef HIF_USB + if (HIFGetFreeQueueNumber(target->hif_dev, pEndpoint->UL_PipeID)) { + /* + * Header and payload belongs to the different fragments and + * consume 2 resource for one HTC package but USB conbime into + * one transfer. + */ + GetHTCSendPackets(target, pEndpoint, &sendQueue, + (HTC_MAX_MSG_PER_BUNDLE_TX * 2)); + } +#else + /* Dequeue max packets from endpoint tx queue */ + GetHTCSendPackets(target, pEndpoint, &sendQueue, + HTC_MAX_TX_BUNDLE_SEND_LIMIT); +#endif + UNLOCK_HTC_TX(target); + } +#endif + else { + /* + * Now drain the endpoint TX queue for transmission as long as we have + * enough transmit resources + */ + tx_resources = HIFGetFreeQueueNumber(target->hif_dev,pEndpoint->UL_PipeID); + GetHTCSendPackets(target, pEndpoint, &sendQueue, tx_resources); + UNLOCK_HTC_TX(target); + } + /* send what we can */ + while (TRUE) { +#if defined(HIF_USB) || defined(HIF_SDIO) +#ifdef ENABLE_BUNDLE_TX + if (HTC_ENABLE_BUNDLE(target) && + HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_MSG_PER_BUNDLE) { + HTCIssuePacketsBundle(target, pEndpoint, &sendQueue); + } +#endif +#endif + pPacket = HTC_PACKET_DEQUEUE(&sendQueue); + if (pPacket == NULL){ + break; + } + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + + LOCK_HTC_TX(target); + /* store in look up queue to match completions */ + HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue,pPacket); + INC_HTC_EP_STAT(pEndpoint,TxIssued,1); + pEndpoint->ul_outstanding_cnt++; + UNLOCK_HTC_TX(target); + + status = HIFSend_head(target->hif_dev, + pEndpoint->UL_PipeID, + pEndpoint->Id, + HTC_HDR_LENGTH + pPacket->ActualLength, + netbuf); +#if DEBUG_BUNDLE + adf_os_print(" Send single EP%d buffer size:0x%x, total:0x%x.\n", + pEndpoint->Id, + pEndpoint->TxCreditSize, + HTC_HDR_LENGTH + pPacket->ActualLength); +#endif + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) + target->tx_bundle_stats[0]++; +#endif + + if (adf_os_unlikely(A_FAILED(status))) { + LOCK_HTC_TX(target); + pEndpoint->ul_outstanding_cnt--; + /* remove this packet from the tx completion queue */ + HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue,pPacket); + + /* + * Don't bother reclaiming credits - HTC flow control + * is not applicable to tx data. + * In LL systems, there is no download flow control, + * since there's virtually no download delay. + * In HL systems, the txrx SW explicitly performs the + * tx flow control. + */ + //pEndpoint->TxCredits += pPacket->PktInfo.AsTx.CreditsUsed; + + /* put this frame back at the front of the sendQueue */ + HTC_PACKET_ENQUEUE_TO_HEAD(&sendQueue, pPacket); + + /* put the sendQueue back at the front of pEndpoint->TxQueue */ + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, &sendQueue); + UNLOCK_HTC_TX(target); + break; /* still need to reset TxProcessCount */ + } + } + /* done with this endpoint, we can clear the count */ + adf_os_atomic_init(&pEndpoint->TxProcessCount); + + if (pEndpoint->ul_is_polled) { + /* + * Start a cleanup timer to poll for download completion. + * The download completion should be noticed promptly from + * other polling calls, but the timer provides a safety net + * in case other polling calls don't occur as expected. + */ + HTCSendCompletePollTimerStart(pEndpoint); + } + + return status; +} +#endif /*ATH_11AC_TXCOMPACT*/ + +/* + * In the adapted HIF layer, adf_nbuf_t are passed between HIF and HTC, since upper layers expects + * HTC_PACKET containers we use the completed netbuf and lookup its corresponding HTC packet buffer + * from a lookup list. + * This is extra overhead that can be fixed by re-aligning HIF interfaces with HTC. + * + */ +static HTC_PACKET *HTCLookupTxPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, adf_nbuf_t netbuf) +{ + HTC_PACKET *pPacket = NULL; + HTC_PACKET *pFoundPacket = NULL; + HTC_PACKET_QUEUE lookupQueue; + + INIT_HTC_PACKET_QUEUE(&lookupQueue); + LOCK_HTC_TX(target); + + /* mark that HIF has indicated the send complete for another packet */ + pEndpoint->ul_outstanding_cnt--; + + /* Dequeue first packet directly because of in-order completion */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxLookupQueue); + if (adf_os_unlikely(!pPacket)) { + UNLOCK_HTC_TX(target); + return NULL; + } + if (netbuf == (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) { + UNLOCK_HTC_TX(target); + return pPacket; + } else { + HTC_PACKET_ENQUEUE(&lookupQueue, pPacket); + } + + /* + * Move TX lookup queue to temp queue because most of packets that are not index 0 + * are not top 10 packets. + */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&lookupQueue, &pEndpoint->TxLookupQueue); + UNLOCK_HTC_TX(target); + + ITERATE_OVER_LIST_ALLOW_REMOVE(&lookupQueue.QueueHead,pPacket,HTC_PACKET,ListLink) { + + if (NULL == pPacket){ + pFoundPacket = pPacket; + break; + } + /* check for removal */ + if (netbuf == (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) { + /* found it */ + HTC_PACKET_REMOVE(&lookupQueue, pPacket); + pFoundPacket = pPacket; + break; + } + + } ITERATE_END; + + LOCK_HTC_TX(target); + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue, &lookupQueue); + UNLOCK_HTC_TX(target); + + return pFoundPacket; +} + + +A_STATUS HTCTxCompletionHandler(void *Context, + adf_nbuf_t netbuf, + unsigned int EpID) +{ + HTC_TARGET *target = (HTC_TARGET *)Context; + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pPacket; + + pEndpoint = &target->EndPoint[EpID]; + target->TX_comp_cnt++; + + do { + pPacket = HTCLookupTxPacket(target, pEndpoint, netbuf); + if (NULL == pPacket) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC TX lookup failed!\n")); + /* may have already been flushed and freed */ + netbuf = NULL; + break; + } + a_mem_trace(netbuf); + + if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM) + hif_pm_runtime_put(target->hif_dev); + + if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED){ + HTC_PACKET *pPacketTemp; + HTC_PACKET_QUEUE *pQueueSave = (HTC_PACKET_QUEUE *)pPacket->pContext; + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQueueSave, pPacketTemp){ + pPacket->Status = A_OK; + SendPacketCompletion(target,pPacketTemp); + }HTC_PACKET_QUEUE_ITERATE_END; + FreeHTCBundleTxPacket(target, pPacket); + +#ifdef HIF_USB + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + HTCTrySend(target,pEndpoint,NULL); + } +#endif + return A_OK; + } + /* will be giving this buffer back to upper layers */ + netbuf = NULL; + pPacket->Status = A_OK; + SendPacketCompletion(target,pPacket); + + } while (FALSE); + + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + /* note: when using TX credit flow, the re-checking of queues happens + * when credits flow back from the target. + * in the non-TX credit case, we recheck after the packet completes */ + HTCTrySend(target,pEndpoint,NULL); + } + + return A_OK; +} + + /* callback when TX resources become available */ +void HTCTxResourceAvailHandler(void *context, A_UINT8 pipeID) +{ + int i; + HTC_TARGET *target = (HTC_TARGET *)context; + HTC_ENDPOINT *pEndpoint = NULL; + + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (pEndpoint->ServiceID != 0) { + if (pEndpoint->UL_PipeID == pipeID) { + break; + } + } + } + + if (i >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid pipe indicated for TX resource avail : %d!\n",pipeID)); + return; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HIF indicated more resources for pipe:%d \n",pipeID)); + + HTCTrySend(target,pEndpoint,NULL); +} + +void HTCTxResumeAllHandler(void *context) +{ + int i; + HTC_TARGET *target = (HTC_TARGET *)context; + HTC_ENDPOINT *pEndpoint = NULL; + + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + + if (pEndpoint->ServiceID == 0) + continue; + + if (pEndpoint->EpCallBacks.EpResumeTxQueue) + pEndpoint->EpCallBacks.EpResumeTxQueue + (pEndpoint->EpCallBacks.pContext); + + HTCTrySend(target, pEndpoint, NULL); + } +} + +/* flush endpoint TX queue */ +void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag) +{ + HTC_PACKET *pPacket; + + LOCK_HTC_TX(target); + while(HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)){ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue); + + if (pPacket) { + /* let the sender know the packet was not delivered */ + pPacket->Status = A_ECANCELED; + SendPacketCompletion(target, pPacket); + } + } + UNLOCK_HTC_TX(target); +} + +/* HTC API to flush an endpoint's TX queue*/ +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; + + if (pEndpoint->ServiceID == 0) { + AR_DEBUG_ASSERT(FALSE); + /* not in use.. */ + return; + } + + HTCFlushEndpointTX(target,pEndpoint,Tag); +} + +/* HTC API to indicate activity to the credit distribution function */ +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + A_BOOL Active) +{ + /* TODO */ +} + +A_BOOL HTCIsEndpointActive(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint) +{ + return TRUE; +} + +/* process credit reports and call distribution function */ +void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint) +{ + int i; + HTC_ENDPOINT *pEndpoint; + int totalCredits = 0; + A_UINT8 rpt_credits, rpt_ep_id; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries)); + + /* lock out TX while we update credits */ + LOCK_HTC_TX(target); + + + for (i = 0; i < NumEntries; i++, pRpt++) { + + rpt_ep_id = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, ENDPOINTID); + + if (rpt_ep_id >= ENDPOINT_MAX) { + AR_DEBUG_ASSERT(FALSE); + break; + } + + rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS); + + pEndpoint = &target->EndPoint[rpt_ep_id]; +#if DEBUG_CREDIT + if (ep_debug_mask & (1 << pEndpoint->Id)){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Increase EP%d %d + %d = %d credits\n", + rpt_ep_id, pEndpoint->TxCredits, rpt_credits, pEndpoint->TxCredits + rpt_credits)); + } +#endif + +#ifdef HTC_EP_STAT_PROFILING + + INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1); + INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, rpt_credits); + + if (FromEndpoint == rpt_ep_id) { + /* this credit report arrived on the same endpoint indicating it arrived in an RX + * packet */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, rpt_credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1); + } else if (FromEndpoint == ENDPOINT_0) { + /* this credit arrived on endpoint 0 as a NULL message */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, rpt_credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1); + } else { + /* arrived on another endpoint */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, rpt_credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1); + } + +#endif + pEndpoint->TxCredits += rpt_credits; + + if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { + LOCK_HTC_CREDIT(target); + htc_credit_record(HTC_PROCESS_CREDIT_REPORT, pEndpoint->TxCredits, + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)); + UNLOCK_HTC_CREDIT(target); + } + + if (pEndpoint->TxCredits && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { + UNLOCK_HTC_TX(target); +#ifdef ATH_11AC_TXCOMPACT + HTCTrySend(target,pEndpoint,NULL); +#else + if (pEndpoint->ServiceID == HTT_DATA_MSG_SVC){ + HTCSendDataPkt(target, NULL, 0); + } else { + HTCTrySend(target,pEndpoint,NULL); + } +#endif + LOCK_HTC_TX(target); + } + totalCredits += rpt_credits; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits)); + + UNLOCK_HTC_TX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n")); +} + +/* function to fetch stats from htc layer*/ +struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + return(&(target->htc_pkt_stats)); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_services.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_services.c new file mode 100644 index 000000000000..0ce50c4a5d83 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_services.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "htc_debug.h" +#include "htc_internal.h" +#include /* adf_nbuf_t */ +#if defined(HIF_PCI) +#include "if_pci.h" +#endif + +extern unsigned int htc_credit_flow; + +#ifndef DEBUG_CREDIT +#define DEBUG_CREDIT 0 +#endif + +A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, + HTC_SERVICE_CONNECT_REQ *pConnectReq, + HTC_SERVICE_CONNECT_RESP *pConnectResp) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + A_STATUS status = A_OK; + HTC_PACKET *pSendPacket = NULL; + HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; + HTC_CONNECT_SERVICE_MSG *pConnectMsg; + HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; + HTC_ENDPOINT *pEndpoint; + unsigned int maxMsgSize = 0; + adf_nbuf_t netbuf; + A_UINT8 txAlloc; + int length; + A_BOOL disableCreditFlowCtrl = FALSE; + A_UINT16 conn_flags; + A_UINT16 rsp_msg_id, rsp_msg_serv_id, rsp_msg_max_msg_size; + A_UINT8 rsp_msg_status, rsp_msg_end_id, rsp_msg_serv_meta_len; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:%p SvcID:0x%X \n", + target, pConnectReq->ServiceID)); + + do { + + AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); + + if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { + /* special case for pseudo control service */ + assignedEndpoint = ENDPOINT_0; + maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; + txAlloc = 0; + + } else { + + txAlloc = HTCGetCreditAllocation(target,pConnectReq->ServiceID); + if (!txAlloc) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Service %d does not allocate target credits!\n", + pConnectReq->ServiceID)); + } + + /* allocate a packet to send to the target */ + pSendPacket = HTCAllocControlTxPacket(target); + + if (NULL == pSendPacket) { + AR_DEBUG_ASSERT(FALSE); + status = A_NO_MEMORY; + break; + } + + netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); + length = sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectReq->MetaDataLength; + + /* assemble connect service message */ + adf_nbuf_put_tail(netbuf, length); + pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)adf_nbuf_data(netbuf); + + if (NULL == pConnectMsg) { + AR_DEBUG_ASSERT(0); + status = A_EFAULT; + break; + } + + A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); + + conn_flags = (pConnectReq->ConnectionFlags & ~HTC_SET_RECV_ALLOC_MASK) | + HTC_CONNECT_FLAGS_SET_RECV_ALLOCATION(txAlloc); + HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, MESSAGEID, + HTC_MSG_CONNECT_SERVICE_ID); + HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, SERVICE_ID, + pConnectReq->ServiceID); + HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, + CONNECTIONFLAGS, conn_flags); + + if (pConnectReq->ConnectionFlags & HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL) { + disableCreditFlowCtrl = TRUE; + } +#if defined(HIF_USB) + if (!htc_credit_flow) { + disableCreditFlowCtrl = TRUE; + } +#else + /* Only enable credit for WMI service */ + if (!htc_credit_flow && pConnectReq->ServiceID != WMI_CONTROL_SVC) { + disableCreditFlowCtrl = TRUE; + } +#endif + /* check caller if it wants to transfer meta data */ + if ((pConnectReq->pMetaData != NULL) && + (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { + /* copy meta data into message buffer (after header ) */ + A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), + pConnectReq->pMetaData, + pConnectReq->MetaDataLength); + + HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, + SERVICEMETALENGTH, pConnectReq->MetaDataLength); + } + + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (A_UINT8 *)pConnectMsg, + length, + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + + + status = HTCSendPkt((HTC_HANDLE)target,pSendPacket); + /* we don't own it anymore */ + pSendPacket = NULL; + if (A_FAILED(status)) { + break; + } + + /* wait for response */ + status = HTCWaitRecvCtrlMessage(target); + if (A_FAILED(status)) { + break; + } + /* we controlled the buffer creation so it has to be properly aligned */ + pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)target->CtrlResponseBuffer; + + rsp_msg_id = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, MESSAGEID); + rsp_msg_serv_id = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, SERVICEID); + rsp_msg_status = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, STATUS); + rsp_msg_end_id = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, ENDPOINTID); + rsp_msg_max_msg_size = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, MAXMSGSIZE); + rsp_msg_serv_meta_len = HTC_GET_FIELD(pResponseMsg, + HTC_CONNECT_SERVICE_RESPONSE_MSG, SERVICEMETALENGTH); + + + if ((rsp_msg_id != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || + (target->CtrlResponseLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { + /* this message is not valid */ + AR_DEBUG_ASSERT(FALSE); + status = A_EPROTO; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("HTCConnectService, service 0x%X connect response from target status:%d, assigned ep: %d\n", + rsp_msg_serv_id, rsp_msg_status, rsp_msg_end_id)); + + pConnectResp->ConnectRespCode = rsp_msg_status; + + /* check response status */ + if (rsp_msg_status != HTC_SERVICE_SUCCESS) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Target failed service 0x%X connect request (status:%d)\n", + rsp_msg_serv_id, rsp_msg_status)); + status = A_EPROTO; +#ifdef QCA_TX_HTT2_SUPPORT + /* Keep work and not to block the control message. */ + target->CtrlResponseProcessing = FALSE; +#endif /* QCA_TX_HTT2_SUPPORT */ + break; + } + + assignedEndpoint = (HTC_ENDPOINT_ID)rsp_msg_end_id; + maxMsgSize = rsp_msg_max_msg_size; + + if ((pConnectResp->pMetaData != NULL) && + (rsp_msg_serv_meta_len > 0) && + (rsp_msg_serv_meta_len <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { + /* caller supplied a buffer and the target responded with data */ + int copyLength = min((int)pConnectResp->BufferLength, (int)rsp_msg_serv_meta_len); + /* copy the meta data */ + A_MEMCPY(pConnectResp->pMetaData, + ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), + copyLength); + pConnectResp->ActualLength = copyLength; + } + /* done processing response buffer */ + target->CtrlResponseProcessing = FALSE; + } + + /* the rest of these are parameter checks so set the error status */ + status = A_EPROTO; + + if (assignedEndpoint >= ENDPOINT_MAX) { + AR_DEBUG_ASSERT(FALSE); + break; + } + + if (0 == maxMsgSize) { + AR_DEBUG_ASSERT(FALSE); + break; + } + + pEndpoint = &target->EndPoint[assignedEndpoint]; + pEndpoint->Id = assignedEndpoint; + if (pEndpoint->ServiceID != 0) { + /* endpoint already in use! */ + AR_DEBUG_ASSERT(FALSE); + break; + } + + /* return assigned endpoint to caller */ + pConnectResp->Endpoint = assignedEndpoint; + pConnectResp->MaxMsgLength = maxMsgSize; + + /* setup the endpoint */ + pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ + pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; + pEndpoint->MaxMsgLength = maxMsgSize; + pEndpoint->TxCredits = txAlloc; + pEndpoint->TxCreditSize = target->TargetCreditSize; + pEndpoint->TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; + if (maxMsgSize % target->TargetCreditSize) { + pEndpoint->TxCreditsPerMaxMsg++; + } +#if DEBUG_CREDIT + adf_os_print(" Endpoint%d initial credit:%d, size:%d.\n", + pEndpoint->Id, pEndpoint->TxCredits, pEndpoint->TxCreditSize); +#endif + + /* copy all the callbacks */ + pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; + + status = HIFMapServiceToPipe(target->hif_dev, + pEndpoint->ServiceID, + &pEndpoint->UL_PipeID, + &pEndpoint->DL_PipeID, + &pEndpoint->ul_is_polled, + &pEndpoint->dl_is_polled); + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("%s Failed to Map Service to Pipe\n", + __func__)); + break; + } + +#if defined(HIF_SDIO) + /* + When AltDataCreditSize is non zero, it indicates the credit size for + HTT and all other services on Mbox0. Mbox1 has WMI_CONTROL_SVC which + uses the default credit size. Use AltDataCreditSize only when mailbox + is swapped. Mailbox swap bit is set by bmi_target_ready at the end of + BMI phase. + + The Credit Size is a parameter associated with the mbox rather than a + service. Multiple services can run on this mbox. + + If AltDataCreditSize is 0, that means the firmware doesn't support + this feature. Default to the TargetCreditSize + */ + + if ((target->AltDataCreditSize) && HIFIsMailBoxSwapped(target->hif_dev) + && (pEndpoint->UL_PipeID == 1) && (pEndpoint->DL_PipeID == 0)) + pEndpoint->TxCreditSize = target->AltDataCreditSize; +#elif defined(HIF_USB) + /* + * Endpoing to pipe is one-to-one mapping in USB. + * If AltDataCreditSize is not zero, it indicates the credit size for + * HTT_DATA_MSG_SVC services use AltDataCrditSize. + */ + if ((target->AltDataCreditSize) && (pEndpoint->ServiceID == HTT_DATA_MSG_SVC)) + pEndpoint->TxCreditSize = target->AltDataCreditSize; +#endif + + adf_os_assert(!pEndpoint->dl_is_polled); /* not currently supported */ + + if (pEndpoint->ul_is_polled) { + adf_os_timer_init( + target->osdev, + &pEndpoint->ul_poll_timer, + HTCSendCompleteCheckCleanup, + pEndpoint, ADF_DEFERRABLE_TIMER); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SETUP, ("HTC Service:0x%4.4X, ULpipe:%d DLpipe:%d id:%d Ready\n", + pEndpoint->ServiceID,pEndpoint->UL_PipeID,pEndpoint->DL_PipeID,pEndpoint->Id)); + + if (disableCreditFlowCtrl && pEndpoint->TxCreditFlowEnabled) { + pEndpoint->TxCreditFlowEnabled = FALSE; + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HTC Service:0x%4.4X ep:%d TX flow control disabled\n", + pEndpoint->ServiceID, assignedEndpoint)); + } + + } while (FALSE); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); + + return status; +} + + +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, + void *pCreditDistContext, + HTC_CREDIT_DIST_CALLBACK CreditDistFunc, + HTC_CREDIT_INIT_CALLBACK CreditInitFunc, + HTC_SERVICE_ID ServicePriorityOrder[], + int ListLength) +{ + /* NOT Supported, this transport does not use a credit based flow control mechanism */ + +} + + +void HTCFwEventHandler(void *context, A_STATUS status) +{ + HTC_TARGET *target = (HTC_TARGET *)context; + HTC_INIT_INFO *initInfo = &target->HTCInitInfo; + + /* check if target failure handler exists and pass error code to it. */ + if (target->HTCInitInfo.TargetFailure != NULL) { + initInfo->TargetFailure(initInfo->pContext, status); + } +} + +/* Disable ASPM : disable PCIe low power */ +void htc_disable_aspm(void) +{ +#if defined(HIF_PCI) + hif_disable_aspm(); +#endif +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.c new file mode 100644 index 000000000000..d28bdbe6e3c6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.c @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2011,2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * Notifications and licenses are retained for attribution purposes only. + */ +/* + * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * Copyright (c) 2010, Atheros Communications Inc. + * + * Redistribution and use in source and binary forms are permitted + * provided that the following conditions are met: + * 1. The materials contained herein are unmodified and are used + * unmodified. + * 2. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following NO + * ''WARRANTY'' disclaimer below (''Disclaimer''), without + * modification. + * 3. Redistributions in binary form must reproduce at minimum a + * disclaimer similar to the Disclaimer below and any redistribution + * must be conditioned upon including a substantially similar + * Disclaimer requirement for further binary redistribution. + * 4. Neither the names of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote + * product derived from this software without specific prior written + * permission. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + * FOR 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 DAMAGES. + */ + +#include +#include "wma.h" +#include "regdomain.h" +#include "regdomain_common.h" + +#define N(a) (sizeof(a)/sizeof(a[0])) + +static regdm_supp_op_classes regdm_curr_supp_opp_classes = {0}; + +/* Global Operating Classes */ +regdm_op_class_map_t global_op_class[] = { + {81, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}, + {82, 25, BW20, {14}}, + {83, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7, 8, 9}}, + {84, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11, 12, 13}}, + {115, 20, BW20, {36, 40, 44, 48}}, + {116, 40, BW40_LOW_PRIMARY, {36, 44}}, + {117, 40, BW40_HIGH_PRIMARY, {40, 48}}, + {118, 20, BW20, {52, 56, 60, 64}}, + {119, 40, BW40_LOW_PRIMARY, {52, 60}}, + {120, 40, BW40_HIGH_PRIMARY, {56, 64}}, + {121, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}, + {122, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132}}, + {123, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136}}, + {125, 20, BW20, {149, 153, 157, 161, 165, 169}}, + {126, 40, BW40_LOW_PRIMARY, {149, 157}}, + {127, 40, BW40_HIGH_PRIMARY, {153, 161}}, + {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, + 112, 116, 120, 124, 128, 132, 136, 140, 144, + 149, 153, 157, 161}}, + {0, 0, 0, {0}}, +}; + +/* Operating Classes in US */ +regdm_op_class_map_t us_op_class[] = { + {1, 20, BW20, {36, 40, 44, 48}}, + {2, 20, BW20, {52, 56, 60, 64}}, + {4, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + 144}}, + {5, 20, BW20, {149, 153, 157, 161, 165}}, + {12, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, + {22, 40, BW40_LOW_PRIMARY, {36, 44}}, + {23, 40, BW40_LOW_PRIMARY, {52, 60}}, + {24, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132, 140}}, + {26, 40, BW40_LOW_PRIMARY, {149, 157}}, + {27, 40, BW40_HIGH_PRIMARY, {40, 48}}, + {28, 40, BW40_HIGH_PRIMARY, {56, 64}}, + {29, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136, 144}}, + {31, 40, BW40_HIGH_PRIMARY, {153, 161}}, + {32, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7}}, + {33, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11}}, + {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, + 112, 116, 120, 124, 128, 132, 136, 140, 144, + 149, 153, 157, 161}}, + {0, 0, 0, {0}}, +}; + +/* Operating Classes in Europe */ +regdm_op_class_map_t euro_op_class[] = { + {1, 20, BW20, {36, 40, 44, 48}}, + {2, 20, BW20, {52, 56, 60, 64}}, + {3, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}, + {4, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}, + {5, 40, BW40_LOW_PRIMARY, {36, 44}}, + {6, 40, BW40_LOW_PRIMARY, {52, 60}}, + {7, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132}}, + {8, 40, BW40_HIGH_PRIMARY, {40, 48}}, + {9, 40, BW40_HIGH_PRIMARY, {56, 64}}, + {10, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136}}, + {11, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7, 8, 9}}, + {12, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11, 12, 13}}, + {17, 20, BW20, {149, 153, 157, 161, 165, 169}}, + {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, + 116, 120, 124, 128}}, + {0, 0, 0, {0}}, +}; + +/* Operating Classes in Japan */ +regdm_op_class_map_t japan_op_class[] = { + {1, 20, BW20, {36, 40, 44, 48}}, + {30, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}, + {31, 25, BW20, {14}}, + {32, 20, BW20, {52, 56, 60, 64}}, + {34, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}, + {36, 40, BW40_LOW_PRIMARY, {36, 44}}, + {37, 40, BW40_LOW_PRIMARY, {52, 60}}, + {39, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132}}, + {41, 40, BW40_HIGH_PRIMARY, {40, 48}}, + {42, 40, BW40_HIGH_PRIMARY, {56, 64}}, + {44, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136}}, + {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, + 116, 120, 124, 128}}, + {0, 0, 0, {0}}, +}; + +/* + * By default, the regdomain tables reference the common tables + * from regdomain_common.h. These default tables can be replaced + * by calls to populate_regdomain_tables functions. + */ +HAL_REG_DMN_TABLES ol_regdmn_Rdt = { + ahCmnRegDomainPairs, /* regDomainPairs */ + ahCmnAllCountries, /* allCountries */ + ahCmnRegDomains, /* allRegDomains */ + N(ahCmnRegDomainPairs), /* regDomainPairsCt */ + N(ahCmnAllCountries), /* allCountriesCt */ + N(ahCmnRegDomains), /* allRegDomainCt */ +}; + +static u_int16_t get_eeprom_rd(u_int16_t rd) +{ + return rd & ~WORLDWIDE_ROAMING_FLAG; +} + +/* + * Return whether or not the regulatory domain/country in EEPROM + * is acceptable. + */ +static bool regdmn_is_eeprom_valid(u_int16_t rd) +{ + int32_t i; + + if (rd & COUNTRY_ERD_FLAG) { + u_int16_t cc = rd & ~COUNTRY_ERD_FLAG; + for (i = 0; i < ol_regdmn_Rdt.allCountriesCt; i++) + if (ol_regdmn_Rdt.allCountries[i].countryCode == cc) + return true; + } else { + for (i = 0; i < ol_regdmn_Rdt.regDomainPairsCt; i++) + if (ol_regdmn_Rdt.regDomainPairs[i].regDmnEnum == rd) + return true; + } + /* TODO: Bring it under debug level */ + adf_os_print("%s: invalid regulatory domain/country code 0x%x\n", + __func__, rd); + return false; +} + +/* + * Find the pointer to the country element in the country table + * corresponding to the country code + */ +static const COUNTRY_CODE_TO_ENUM_RD *find_country(u_int16_t country_code) +{ + int32_t i; + + for (i = 0; i < ol_regdmn_Rdt.allCountriesCt; i++) { + if (ol_regdmn_Rdt.allCountries[i].countryCode == country_code) + return &ol_regdmn_Rdt.allCountries[i]; + } + return NULL; /* Not found */ +} + +int32_t regdmn_find_ctry_by_name(u_int8_t *alpha2) +{ + int32_t i; + + for (i = 0; i < ol_regdmn_Rdt.allCountriesCt; i++) { + if (ol_regdmn_Rdt.allCountries[i].isoName[0] == alpha2[0] && + ol_regdmn_Rdt.allCountries[i].isoName[1] == alpha2[1]) + return ol_regdmn_Rdt.allCountries[i].countryCode; + } + return CTRY_DEFAULT; /* Not found */ +} + +static u_int16_t regdmn_get_default_country(u_int16_t rd) +{ + int32_t i; + + if (rd & COUNTRY_ERD_FLAG) { + const COUNTRY_CODE_TO_ENUM_RD *country = NULL; + u_int16_t cc = rd & ~COUNTRY_ERD_FLAG; + + country = find_country(cc); + if (country) + return cc; + } + + /* + * Check reg domains that have only one country + */ + for (i = 0; i < ol_regdmn_Rdt.regDomainPairsCt; i++) { + if (ol_regdmn_Rdt.regDomainPairs[i].regDmnEnum == rd) { + if (ol_regdmn_Rdt.regDomainPairs[i].singleCC != 0) + return ol_regdmn_Rdt.regDomainPairs[i].singleCC; + else + i = ol_regdmn_Rdt.regDomainPairsCt; + } + } + return CTRY_DEFAULT; +} + +static const REG_DMN_PAIR_MAPPING *get_regdmn_pair(u_int16_t reg_dmn) +{ + int32_t i; + + for (i = 0; i < ol_regdmn_Rdt.regDomainPairsCt; i++) { + if (ol_regdmn_Rdt.regDomainPairs[i].regDmnEnum == reg_dmn) + return &ol_regdmn_Rdt.regDomainPairs[i]; + } + return NULL; +} + +static const REG_DOMAIN *get_regdmn(u_int16_t reg_dmn) +{ + int32_t i; + + for (i = 0; i < ol_regdmn_Rdt.regDomainsCt; i++) { + if (ol_regdmn_Rdt.regDomains[i].regDmnEnum == reg_dmn) + return &ol_regdmn_Rdt.regDomains[i]; + } + return NULL; +} + +static const COUNTRY_CODE_TO_ENUM_RD *get_country_from_rd(u_int16_t regdmn) +{ + int32_t i; + + for (i = 0; i < ol_regdmn_Rdt.allCountriesCt; i++) { + if (ol_regdmn_Rdt.allCountries[i].regDmnEnum == regdmn) + return &ol_regdmn_Rdt.allCountries[i]; + } + return NULL; /* Not found */ +} + +/* + * Some users have reported their EEPROM programmed with + * 0x8000 set, this is not a supported regulatory domain + * but since we have more than one user with it we need + * a solution for them. We default to WOR0_WORLD + */ +static void regd_sanitize(struct regulatory *reg) +{ + if (reg->reg_domain != COUNTRY_ERD_FLAG) + return; + reg->reg_domain = WOR0_WORLD; +} + +/* + * Returns country string for the given regulatory domain. + */ +int32_t regdmn_get_country_alpha2(struct regulatory *reg) +{ + u_int16_t country_code; + u_int16_t regdmn, rd; + const COUNTRY_CODE_TO_ENUM_RD *country = NULL; + + regd_sanitize(reg); + rd = reg->reg_domain; + + if (!regdmn_is_eeprom_valid(rd)) + return -EINVAL; + + regdmn = get_eeprom_rd(rd); + + country_code = regdmn_get_default_country(regdmn); + if (country_code == CTRY_DEFAULT && regdmn == CTRY_DEFAULT) { + /* Set to CTRY_UNITED_STATES for testing */ + country_code = CTRY_UNITED_STATES; + } + + if (country_code != CTRY_DEFAULT) { + country = find_country(country_code); + if (!country) { + /* TODO: Bring it under debug level */ + adf_os_print(KERN_ERR "Not a valid country code\n"); + return -EINVAL; + } + regdmn = country->regDmnEnum; + } + + reg->regpair = get_regdmn_pair(regdmn); + if (!reg->regpair) { + /* TODO: Bring it under debug level */ + adf_os_print(KERN_ERR "No regpair is found, can not proceeed\n"); + return -EINVAL; + } + reg->country_code = country_code; + + if (!country) + country = get_country_from_rd(regdmn); + + if (country) { + reg->alpha2[0] = country->isoName[0]; + reg->alpha2[1] = country->isoName[1]; + } else { + reg->alpha2[0] = '0'; + reg->alpha2[1] = '0'; + } + + return 0; +} + +/* + * Returns regulatory domain for given country string + */ +int32_t regdmn_get_regdmn_for_country(u_int8_t *alpha2) +{ + u_int8_t i; + + for (i = 0; i < ol_regdmn_Rdt.allCountriesCt; i++) { + if ((ol_regdmn_Rdt.allCountries[i].isoName[0] == alpha2[0]) && + (ol_regdmn_Rdt.allCountries[i].isoName[1] == alpha2[1])) + return ol_regdmn_Rdt.allCountries[i].regDmnEnum; + } + return -1; +} + +/* + * Test to see if the bitmask array is all zeros + */ +static bool +isChanBitMaskZero(const u_int64_t *bitmask) +{ + int i; + + for (i = 0; i < BMLEN; i++) { + if (bitmask[i] != 0) + return false; + } + return true; +} + +/* + * Return the mask of available modes based on the hardware + * capabilities and the specified country code and reg domain. + */ +u_int32_t regdmn_getwmodesnreg(u_int32_t modesAvail, + const COUNTRY_CODE_TO_ENUM_RD *country, + const REG_DOMAIN *rd5GHz) +{ + + /* Check country regulations for allowed modes */ + if ((modesAvail & (REGDMN_MODE_11A_TURBO|REGDMN_MODE_TURBO)) && + (!country->allow11aTurbo)) + modesAvail &= ~(REGDMN_MODE_11A_TURBO | REGDMN_MODE_TURBO); + + if ((modesAvail & REGDMN_MODE_11G_TURBO) && + (!country->allow11gTurbo)) + modesAvail &= ~REGDMN_MODE_11G_TURBO; + + if ((modesAvail & REGDMN_MODE_11G) && + (!country->allow11g)) + modesAvail &= ~REGDMN_MODE_11G; + + if ((modesAvail & REGDMN_MODE_11A) && + (isChanBitMaskZero(rd5GHz->chan11a))) + modesAvail &= ~REGDMN_MODE_11A; + + if ((modesAvail & REGDMN_MODE_11NG_HT20) && + (!country->allow11ng20)) + modesAvail &= ~REGDMN_MODE_11NG_HT20; + + if ((modesAvail & REGDMN_MODE_11NA_HT20) && + (!country->allow11na20)) + modesAvail &= ~REGDMN_MODE_11NA_HT20; + + if ((modesAvail & REGDMN_MODE_11NG_HT40PLUS) && + (!country->allow11ng40)) + modesAvail &= ~REGDMN_MODE_11NG_HT40PLUS; + + if ((modesAvail & REGDMN_MODE_11NG_HT40MINUS) && + (!country->allow11ng40)) + modesAvail &= ~REGDMN_MODE_11NG_HT40MINUS; + + if ((modesAvail & REGDMN_MODE_11NA_HT40PLUS) && + (!country->allow11na40)) + modesAvail &= ~REGDMN_MODE_11NA_HT40PLUS; + + if ((modesAvail & REGDMN_MODE_11NA_HT40MINUS) && + (!country->allow11na40)) + modesAvail &= ~REGDMN_MODE_11NA_HT40MINUS; + + if ((modesAvail & REGDMN_MODE_11AC_VHT20) && + (!country->allow11na20)) + modesAvail &= ~REGDMN_MODE_11AC_VHT20; + + if ((modesAvail & REGDMN_MODE_11AC_VHT40PLUS) && + (!country->allow11na40)) + modesAvail &= ~REGDMN_MODE_11AC_VHT40PLUS; + + if ((modesAvail & REGDMN_MODE_11AC_VHT40MINUS) && + (!country->allow11na40)) + modesAvail &= ~REGDMN_MODE_11AC_VHT40MINUS; + + if ((modesAvail & REGDMN_MODE_11AC_VHT80) && + (!country->allow11na80)) + modesAvail &= ~REGDMN_MODE_11AC_VHT80; + + if ((modesAvail & REGDMN_MODE_11AC_VHT20_2G) && + (!country->allow11ng20)) + modesAvail &= ~REGDMN_MODE_11AC_VHT20_2G; + + return modesAvail; +} + +void regdmn_get_ctl_info(struct regulatory *reg, u_int32_t modesAvail, + u_int32_t modeSelect) +{ + const REG_DOMAIN *regdomain2G = NULL; + const REG_DOMAIN *regdomain5G = NULL; + int8_t ctl_2g, ctl_5g, ctl; + const REG_DOMAIN *rd = NULL; + const struct cmode *cm; + const COUNTRY_CODE_TO_ENUM_RD *country; + const REG_DMN_PAIR_MAPPING *regpair; + + regpair = reg->regpair; + regdomain2G = get_regdmn(regpair->regDmn2GHz); + if (!regdomain2G) { + adf_os_print(KERN_ERR "Failed to get regdmn 2G"); + return; + } + + regdomain5G = get_regdmn(regpair->regDmn5GHz); + if (!regdomain5G) { + adf_os_print(KERN_ERR "Failed to get regdmn 5G"); + return; + } + + /* find first nible of CTL */ + ctl_2g = regdomain2G->conformance_test_limit; + ctl_5g = regdomain5G->conformance_test_limit; + + /* find second nible of CTL */ + country = find_country(reg->country_code); + if (country != NULL) + modesAvail = regdmn_getwmodesnreg(modesAvail, country, regdomain5G); + + for (cm = modes; cm < &modes[N(modes)]; cm++) { + + if ((cm->mode & modeSelect) == 0) + continue; + + if ((cm->mode & modesAvail) == 0) + continue; + + switch (cm->mode) { + case REGDMN_MODE_TURBO: + rd = regdomain5G; + ctl = rd->conformance_test_limit | CTL_TURBO; + break; + case REGDMN_MODE_11A: + case REGDMN_MODE_11NA_HT20: + case REGDMN_MODE_11NA_HT40PLUS: + case REGDMN_MODE_11NA_HT40MINUS: + case REGDMN_MODE_11AC_VHT20: + case REGDMN_MODE_11AC_VHT40PLUS: + case REGDMN_MODE_11AC_VHT40MINUS: + case REGDMN_MODE_11AC_VHT80: + rd = regdomain5G; + ctl = rd->conformance_test_limit; + break; + case REGDMN_MODE_11B: + rd = regdomain2G; + ctl = rd->conformance_test_limit | CTL_11B; + break; + case REGDMN_MODE_11G: + case REGDMN_MODE_11NG_HT20: + case REGDMN_MODE_11NG_HT40PLUS: + case REGDMN_MODE_11NG_HT40MINUS: + case REGDMN_MODE_11AC_VHT20_2G: + case REGDMN_MODE_11AC_VHT40_2G: + case REGDMN_MODE_11AC_VHT80_2G: + rd = regdomain2G; + ctl = rd->conformance_test_limit | CTL_11G; + break; + case REGDMN_MODE_11G_TURBO: + rd = regdomain2G; + ctl = rd->conformance_test_limit | CTL_108G; + break; + case REGDMN_MODE_11A_TURBO: + rd = regdomain5G; + ctl = rd->conformance_test_limit | CTL_108G; + break; + default: + adf_os_print(KERN_ERR "%s: Unkonwn HAL mode 0x%x\n", + __func__, cm->mode); + continue; + } + + if (rd == regdomain2G) + ctl_2g = ctl; + + if (rd == regdomain5G) + ctl_5g = ctl; + } + + /* save the ctl information for future reference */ + reg->ctl_5g = ctl_5g; + reg->ctl_2g = ctl_2g; + + wma_send_regdomain_info(reg->reg_domain, regpair->regDmn2GHz, + regpair->regDmn5GHz, ctl_2g, ctl_5g); +} + +/* regdmn_set_dfs_region() - to set the dfs region to wma + * + * @reg: the regulatory handle + * + * Return: none + */ +void regdmn_set_dfs_region(struct regulatory *reg) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + + if (!wma) { + WMA_LOGE("%s: Unable to get WMA handle", __func__); + return; + } + + WMA_LOGE("%s: dfs_region: %d", __func__, reg->dfs_region); + wma_set_dfs_regdomain(wma, reg->dfs_region); +} + +void regdmn_set_regval(struct regulatory *reg) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + u_int32_t modeSelect = 0xFFFFFFFF; + + if (!wma) { + WMA_LOGE("%s: Unable to get WMA handle", __func__); + return; + } + + wma_get_modeselect(wma, &modeSelect); + + regdmn_get_ctl_info(reg, wma->reg_cap.wireless_modes, modeSelect); + return; +} + +/* get the ctl from regdomain */ +u_int8_t regdmn_get_ctl_for_regdmn(u_int32_t reg_dmn) +{ + u_int8_t i; + u_int8_t default_regdmn_ctl = FCC; + + if (reg_dmn == CTRY_DEFAULT) + { + return default_regdmn_ctl; + } + else + { + for (i = 0; i < ol_regdmn_Rdt.regDomainsCt; i++) + { + if (ol_regdmn_Rdt.regDomains[i].regDmnEnum == reg_dmn) + return ol_regdmn_Rdt.regDomains[i].conformance_test_limit; + } + } + return -1; +} + +/* + * Get the 5G reg domain value for reg doamin + */ +u_int16_t get_regdmn_5g(u_int32_t reg_dmn) +{ + u_int16_t i; + + for (i = 0; i < ol_regdmn_Rdt.regDomainPairsCt; i++) + { + if (ol_regdmn_Rdt.regDomainPairs[i].regDmnEnum == reg_dmn) + { + return ol_regdmn_Rdt.regDomainPairs[i].regDmn5GHz; + } + } + adf_os_print("%s: invalid regulatory domain/country code 0x%x\n", + __func__, reg_dmn); + return 0; +} + +/* + * Get operating class for a given channel + */ +u_int16_t regdm_get_opclass_from_channel(u_int8_t *country, u_int8_t channel, + u_int8_t offset) +{ + regdm_op_class_map_t *class = NULL; + u_int16_t i = 0; + + if (0 == adf_os_mem_cmp(country,"US", 2)) { + class = us_op_class; + } else if (0 == adf_os_mem_cmp(country,"EU", 2)) { + class = euro_op_class; + } else if (0 == adf_os_mem_cmp(country,"JP", 2)) { + class = japan_op_class; + } else { + class = global_op_class; + } + + while (class->op_class) { + if ((offset == class->offset) || (offset == BWALL)) { + for (i = 0; + (i < MAX_CHANNELS_PER_OPERATING_CLASS && + class->channels[i]); + i++) { + if (channel == class->channels[i]) + return class->op_class; + } + } + class++; + } + return 0; +} + +/* + * Set current operating classes per country, regdomain + */ +u_int16_t regdm_set_curr_opclasses(u_int8_t num_classes, u_int8_t *class) +{ + u_int8_t i; + + if (SIR_MAC_MAX_SUPP_OPER_CLASSES < num_classes) { + adf_os_print(KERN_ERR "%s: Invalid numClasses (%d)\n", + __func__, num_classes); + return -1; + } + + for (i = 0 ; i < num_classes; i++) { + regdm_curr_supp_opp_classes.classes[i] = class[i]; + } + regdm_curr_supp_opp_classes.num_classes = num_classes; + + return 0; +} + +/* + * Get current operating classes + */ +u_int16_t regdm_get_curr_opclasses(u_int8_t *num_classes, u_int8_t *class) +{ + u_int8_t i; + + if (!num_classes || !class) { + adf_os_print(KERN_ERR "%s: Either num_classes or class is null\n", + __func__); + return -1; + } + + for (i = 0 ; i < regdm_curr_supp_opp_classes.num_classes; i++) { + class[i] = regdm_curr_supp_opp_classes.classes[i]; + } + + *num_classes = regdm_curr_supp_opp_classes.num_classes; + + return 0; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.h new file mode 100644 index 000000000000..516a3afe2b46 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain.h @@ -0,0 +1,1103 @@ +/* + * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * Notifications and licenses are retained for attribution purposes only. + */ +/* + * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting + * Copyright (c) 2005-2006 Atheros Communications, Inc. + * Copyright (c) 2010, Atheros Communications Inc. + * + * Redistribution and use in source and binary forms are permitted + * provided that the following conditions are met: + * 1. The materials contained herein are unmodified and are used + * unmodified. + * 2. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following NO + * ''WARRANTY'' disclaimer below (''Disclaimer''), without + * modification. + * 3. Redistributions in binary form must reproduce at minimum a + * disclaimer similar to the Disclaimer below and any redistribution + * must be conditioned upon including a substantially similar + * Disclaimer requirement for further binary redistribution. + * 4. Neither the names of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote + * product derived from this software without specific prior written + * permission. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + * FOR 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 DAMAGES. + * + * This module contains the regulatory domain private structure definitions . + * + */ + +#ifndef REGULATORY_H +#define REGULATORY_H + +enum { + CTRY_DEBUG = 0x1ff, /* debug country code */ + CTRY_DEFAULT = 0 /* default country code */ +}; + +#define BMLEN 2 /* Use 2 64 bit uint for channel bitmask */ + +/* + * The following table is the master list for all different freqeuncy + * bands with the complete matrix of all possible flags and settings + * for each band if it is used in ANY reg domain. + */ + +#define DEF_REGDMN FCC3_FCCA +#define DEF_DMN_5 FCC1 +#define DEF_DMN_2 FCCA +#define COUNTRY_ERD_FLAG 0x8000 +#define WORLDWIDE_ROAMING_FLAG 0x4000 +#define SUPER_DOMAIN_MASK 0x0fff +#define COUNTRY_CODE_MASK 0x3fff +#define CF_INTERFERENCE (CHANNEL_CW_INT | CHANNEL_RADAR_INT) + +/* + * The following describe the bit masks for different passive scan + * capability/requirements per regdomain. + */ +#define NO_PSCAN 0x0ULL +#define PSCAN_FCC 0x0000000000000001ULL +#define PSCAN_FCC_T 0x0000000000000002ULL +#define PSCAN_ETSI 0x0000000000000004ULL +#define PSCAN_MKK1 0x0000000000000008ULL +#define PSCAN_MKK2 0x0000000000000010ULL +#define PSCAN_MKKA 0x0000000000000020ULL +#define PSCAN_MKKA_G 0x0000000000000040ULL +#define PSCAN_ETSIA 0x0000000000000080ULL +#define PSCAN_ETSIB 0x0000000000000100ULL +#define PSCAN_ETSIC 0x0000000000000200ULL +#define PSCAN_WWR 0x0000000000000400ULL +#define PSCAN_MKKA1 0x0000000000000800ULL +#define PSCAN_MKKA1_G 0x0000000000001000ULL +#define PSCAN_MKKA2 0x0000000000002000ULL +#define PSCAN_MKKA2_G 0x0000000000004000ULL +#define PSCAN_MKK3 0x0000000000008000ULL +#define PSCAN_EXT_CHAN 0x0000000000010000ULL +#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL +#define IS_ECM_CHAN 0x8000000000000000ULL + + +/* define in ah_eeprom.h */ +#define SD_NO_CTL 0xf0 +#define NO_CTL 0xff +#define CTL_MODE_M 0x0f +#define CTL_11A 0 +#define CTL_11B 1 +#define CTL_11G 2 +#define CTL_TURBO 3 +#define CTL_108G 4 +#define CTL_2GHT20 5 +#define CTL_5GHT20 6 +#define CTL_2GHT40 7 +#define CTL_5GHT40 8 +#define CTL_5GVHT80 9 + +#ifndef ATH_NO_5G_SUPPORT + #define REGDMN_MODE_11A_TURBO REGDMN_MODE_108A + #define CHAN_11A_BMZERO BMZERO, + #define CHAN_11A_BM(_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l) \ + BM(_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l), +#else + /* remove 11a channel info if 11a is not supported */ + #define CHAN_11A_BMZERO + #define CHAN_11A_BM(_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l) +#endif +#ifndef ATH_REMOVE_2G_TURBO_RD_TABLE + #define REGDMN_MODE_11G_TURBO REGDMN_MODE_108G + #define CHAN_TURBO_G_BMZERO BMZERO, + #define CHAN_TURBO_G_BM(_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l) \ + BM(_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l), +#else + /* remove turbo-g channel info if turbo-g is not supported */ + #define CHAN_TURBO_G(a, b) + #define CHAN_TURBO_G_BMZERO + #define CHAN_TURBO_G_BM(_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l) +#endif + +#define BMLEN 2 /* Use 2 64 bit uint for channel bitmask + NB: Must agree with macro below (BM) */ +#define BMZERO {(u_int64_t) 0, (u_int64_t) 0} /* BMLEN zeros */ + +#ifndef SUPPRESS_SHIFT_WARNING +#define SUPPRESS_SHIFT_WARNING +#endif + +/* Suppress MS warning "C4293: 'operator' : shift count negative or too big, + * undefined behavior" + * This is safe below because the the operand is properly range-checked, but + * the compiler can't reason that out before it spits the warning. + * Using suppress, so the warning can still be enabled globally to catch other + * incorrect uses. + */ +#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \ + SUPPRESS_SHIFT_WARNING \ + {((((_fa >= 0) && (_fa < 64)) ? (((u_int64_t) 1) << _fa) : (u_int64_t) 0) | \ + (((_fb >= 0) && (_fb < 64)) ? (((u_int64_t) 1) << _fb) : (u_int64_t) 0) | \ + (((_fc >= 0) && (_fc < 64)) ? (((u_int64_t) 1) << _fc) : (u_int64_t) 0) | \ + (((_fd >= 0) && (_fd < 64)) ? (((u_int64_t) 1) << _fd) : (u_int64_t) 0) | \ + (((_fe >= 0) && (_fe < 64)) ? (((u_int64_t) 1) << _fe) : (u_int64_t) 0) | \ + (((_ff >= 0) && (_ff < 64)) ? (((u_int64_t) 1) << _ff) : (u_int64_t) 0) | \ + (((_fg >= 0) && (_fg < 64)) ? (((u_int64_t) 1) << _fg) : (u_int64_t) 0) | \ + (((_fh >= 0) && (_fh < 64)) ? (((u_int64_t) 1) << _fh) : (u_int64_t) 0) | \ + (((_fi >= 0) && (_fi < 64)) ? (((u_int64_t) 1) << _fi) : (u_int64_t) 0) | \ + (((_fj >= 0) && (_fj < 64)) ? (((u_int64_t) 1) << _fj) : (u_int64_t) 0) | \ + (((_fk >= 0) && (_fk < 64)) ? (((u_int64_t) 1) << _fk) : (u_int64_t) 0) | \ + (((_fl >= 0) && (_fl < 64)) ? (((u_int64_t) 1) << _fl) : (u_int64_t) 0) ) \ + ,(((((_fa > 63) && (_fa < 128)) ? (((u_int64_t) 1) << (_fa - 64)) : (u_int64_t) 0) | \ + (((_fb > 63) && (_fb < 128)) ? (((u_int64_t) 1) << (_fb - 64)) : (u_int64_t) 0) | \ + (((_fc > 63) && (_fc < 128)) ? (((u_int64_t) 1) << (_fc - 64)) : (u_int64_t) 0) | \ + (((_fd > 63) && (_fd < 128)) ? (((u_int64_t) 1) << (_fd - 64)) : (u_int64_t) 0) | \ + (((_fe > 63) && (_fe < 128)) ? (((u_int64_t) 1) << (_fe - 64)) : (u_int64_t) 0) | \ + (((_ff > 63) && (_ff < 128)) ? (((u_int64_t) 1) << (_ff - 64)) : (u_int64_t) 0) | \ + (((_fg > 63) && (_fg < 128)) ? (((u_int64_t) 1) << (_fg - 64)) : (u_int64_t) 0) | \ + (((_fh > 63) && (_fh < 128)) ? (((u_int64_t) 1) << (_fh - 64)) : (u_int64_t) 0) | \ + (((_fi > 63) && (_fi < 128)) ? (((u_int64_t) 1) << (_fi - 64)) : (u_int64_t) 0) | \ + (((_fj > 63) && (_fj < 128)) ? (((u_int64_t) 1) << (_fj - 64)) : (u_int64_t) 0) | \ + (((_fk > 63) && (_fk < 128)) ? (((u_int64_t) 1) << (_fk - 64)) : (u_int64_t) 0) | \ + (((_fl > 63) && (_fl < 128)) ? (((u_int64_t) 1) << (_fl - 64)) : (u_int64_t) 0)))} + +/* + * THE following table is the mapping of regdomain pairs specified by + * an 8 bit regdomain value to the individual unitary reg domains + */ + +typedef struct reg_dmn_pair_mapping { + u_int16_t regDmnEnum; /* 16 bit reg domain pair */ + u_int16_t regDmn5GHz; /* 5GHz reg domain */ + u_int16_t regDmn2GHz; /* 2GHz reg domain */ + u_int32_t flags5GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + u_int32_t flags2GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + u_int64_t pscanMask; /* Passive Scan flags which + can override unitary domain + passive scan flags. This + value is used as a mask on + the unitary flags*/ + u_int16_t singleCC; /* Country code of single country if + a one-on-one mapping exists */ +} REG_DMN_PAIR_MAPPING; + +typedef struct { + u_int16_t countryCode; + u_int16_t regDmnEnum; + const char* isoName; + const char* name; + u_int16_t + allow11g : 1, + allow11aTurbo : 1, + allow11gTurbo : 1, + allow11ng20 : 1, /* HT-20 allowed in 2GHz? */ + allow11ng40 : 1, /* HT-40 allowed in 2GHz? */ + allow11na20 : 1, /* HT-20 allowed in 5GHz? */ + allow11na40 : 1, /* HT-40 VHT-40 allowed in 5GHz? */ + allow11na80 : 1; /* VHT-80 allowed in 5GHz */ + u_int16_t outdoorChanStart; +} COUNTRY_CODE_TO_ENUM_RD; + +typedef struct RegDmnFreqBand { + u_int16_t lowChannel; /* Low channel center in MHz */ + u_int16_t highChannel; /* High Channel center in MHz */ + u_int8_t powerDfs; /* Max power (dBm) for channel + range when using DFS */ + u_int8_t antennaMax; /* Max allowed antenna gain */ + u_int8_t channelBW; /* Bandwidth of the channel */ + u_int8_t channelSep; /* Channel separation within + the band */ + u_int64_t useDfs; /* Use DFS in the RegDomain + if corresponding bit is set */ + u_int64_t usePassScan; /* Use Passive Scan in the RegDomain + if corresponding bit is set */ + u_int8_t regClassId; /* Regulatory class id */ +} REG_DMN_FREQ_BAND; + +typedef struct reg_domain { + u_int16_t regDmnEnum; /* value from EnumRd table */ + u_int8_t conformance_test_limit; + u_int64_t dfsMask; /* DFS bitmask for 5Ghz tables */ + u_int64_t pscan; /* Bitmask for passive scan */ + u_int32_t flags; /* Requirement flags (AdHoc disallow, noise + floor cal needed, etc) */ + u_int64_t chan11a[BMLEN];/* 128 bit bitmask for channel/band selection */ + u_int64_t chan11a_turbo[BMLEN];/* 128 bit bitmask for channel/band select */ + u_int64_t chan11a_dyn_turbo[BMLEN]; /* 128 bit mask for chan/band select */ + + u_int64_t chan11b[BMLEN];/* 128 bit bitmask for channel/band selection */ + u_int64_t chan11g[BMLEN];/* 128 bit bitmask for channel/band selection */ + u_int64_t chan11g_turbo[BMLEN]; +} REG_DOMAIN; + +struct cmode { + u_int32_t mode; + u_int32_t flags; +}; + +#define YES true +#define NO false + +/* mapping of old skus to new skus for Japan */ +typedef struct { + u_int16_t domain; + u_int16_t newdomain_pre53; /* pre eeprom version 5.3 */ + u_int16_t newdomain_post53; /* post eeprom version 5.3 */ +} JAPAN_SKUMAP; + +/* mapping of countrycode to new skus for Japan */ +typedef struct { + u_int16_t ccode; + u_int16_t newdomain_pre53; /* pre eeprom version 5.3 */ + u_int16_t newdomain_post53; /* post eeprom version 5.3 */ +} JAPAN_COUNTRYMAP; + +/* check rd flags in eeprom for japan */ +typedef struct { + u_int16_t freqbandbit; + u_int32_t eepromflagtocheck; +} JAPAN_BANDCHECK; + +/* Common mode power table for 5Ghz */ +typedef struct { + u_int16_t lchan; + u_int16_t hchan; + u_int8_t pwrlvl; +} COMMON_MODE_POWER; + +typedef enum +{ + COUNTRY_CODE_SET_BY_CORE, + COUNTRY_CODE_SET_BY_DRIVER, + COUNTRY_CODE_SET_BY_USER +} COUNTRY_CODE_SOURCE; + +struct regulatory { + uint32_t reg_domain; + uint32_t eeprom_rd_ext; + uint16_t country_code; + uint8_t alpha2[3]; + uint8_t dfs_region; + uint8_t ctl_2g; + uint8_t ctl_5g; + const void *regpair; + COUNTRY_CODE_SOURCE cc_src; + uint32_t reg_flags; +}; +/* Multi-Device RegDomain Support */ +typedef struct ath_hal_reg_dmn_tables { + /* regDomainPairs: Map of 8-bit regdomain values to unitary reg domain */ + const REG_DMN_PAIR_MAPPING *regDomainPairs; + /* allCountries: Master list of freq. bands (flags, settings) */ + const COUNTRY_CODE_TO_ENUM_RD *allCountries; + /* regDomains: Array of supported reg domains */ + const REG_DOMAIN *regDomains; + + u_int16_t regDomainPairsCt; /* Num reg domain pair entries */ + u_int16_t allCountriesCt; /* Num country entries */ + u_int16_t regDomainsCt; /* Num reg domain entries */ +} HAL_REG_DMN_TABLES; + +/* + * Country/Region Codes from MS WINNLS.H + * Numbering from ISO 3166 + */ +/** @brief country code definitions + * - country definition: CTRY_DEBUG + * - country string: DB + * - country ID: 0 + * - country definition: CTRY_DEFAULT + * - country string: NA + * - country ID: 0 + * - country definition: CTRY_ALBANIA + * - country string: AL + * - country ID: 8 + * - country definition: CTRY_ALGERIA + * - country string: DZ + * - country ID: 12 + * - country definition: CTRY_ARGENTINA + * - country string: AR + * - country ID: 32 + * - country definition: CTRY_ARMENIA + * - country string: AM + * - country ID: 51 + * - country definition: CTRY_AUSTRALIA + * - country string: AU + * - country ID: 36 + * - country definition: CTRY_AUSTRALIA2 + * - country string: AU2 + * - country ID: 5000 + * - country definition: CTRY_AUSTRIA + * - country string: AT + * - country ID: 40 + * - country definition: CTRY_AZERBAIJAN + * - country string: AZ + * - country ID: 31 + * - country definition: CTRY_BAHAMAS + * - country string: BS + * - country ID: 44 + * - country definition: CTRY_BAHRAIN + * - country string: BH + * - country ID: 48 + * - country definition: CTRY_BELARUS + * - country string: BY + * - country ID: 112 + * - country definition: CTRY_BELGIUM + * - country string: BE + * - country ID: 56 + * - country definition: CTRY_BELIZE + * - country string: BZ + * - country ID: 84 + * - country definition: CTRY_BERMUDA + * - country string: BM + * - country ID: 60 + * - country definition: CTRY_BOLIVIA + * - country string: BO + * - country ID: 68 + * - country definition: CTRY_BOSNIA_HERZEGOWINA + * - country string: 70 + * - country ID: BA + * - country definition: CTRY_BRAZIL + * - country string: BR + * - country ID: 76 + * - country definition: CTRY_BRUNEI_DARUSSALAM + * - country string: BN + * - country ID: 96 + * - country definition: CTRY_BULGARIA + * - country string: BG + * - country ID: 100 + * - country definition: CTRY_CANADA + * - country string: CA + * - country ID: 124 + * - country definition: CTRY_CANADA2 + * - country string: CA2 + * - country ID: 5001 + * - country definition: CTRY_CHILE + * - country string: CL + * - country ID: 152 + * - country definition: CTRY_CHINA + * - country string: CN + * - country ID: 152 + * - country definition: CTRY_COLOMBIA + * - country string: CO + * - country ID: 170 + * - country definition: CTRY_COSTA_RICA + * - country string: CR + * - country ID: 191 + * - country definition: CTRY_CROATIA + * - country string: HR + * - country ID: 191 + * - country definition: CTRY_CYPRUS + * - country string: CY + * - country ID: 196 + * - country definition: CTRY_CZECH + * - country string: CZ + * - country ID: 203 + * - country definition: CTRY_DENMARK + * - country string: DK + * - country ID: 208 + * - country definition: CTRY_DOMINICAN_REPUBLIC + * - country string: DO + * - country ID: 214 + * - country definition: CTRY_ECUADOR + * - country string: EC + * - country ID: 218 + * - country definition: CTRY_EGYPT + * - country string: EG + * - country ID: 818 + * - country definition: CTRY_EL_SALVADOR + * - country string: SV + * - country ID: 222 + * - country definition: CTRY_ESTONIA + * - country string: EE + * - country ID: 233 + * - country definition: CTRY_FAEROE_ISLANDS + * - country string: FO + * - country ID: 234 + * - country definition: CTRY_FINLAND + * - country string: FI + * - country ID: 246 + * - country definition: CTRY_FRANCE + * - country string: FR + * - country ID: 250 + * - country definition: CTRY_FRANCE2 + * - country string: F2 + * - country ID: 255 + * - country definition: CTRY_GEORGIA + * - country string: GE + * - country ID: 268 + * - country definition: CTRY_GERMANY + * - country string: DE + * - country ID: 276 + * - country definition: CTRY_GREECE + * - country string: GR + * - country ID: 300 + * - country definition: CTRY_GUATEMALA + * - country string: GT + * - country ID: 320 + * - country definition: CTRY_HONDURAS + * - country string: HN + * - country ID: 340 + * - country definition: CTRY_HONG_KONG + * - country string: HK + * - country ID: 344 + * - country definition: CTRY_HUNGARY + * - country string: HU + * - country ID: 348 + * - country definition: CTRY_ICELAND + * - country string: IS + * - country ID: 352 + * - country definition: CTRY_INDIA + * - country string: IN + * - country ID: 356 + * - country definition: CTRY_INDONESIA + * - country string: ID + * - country ID: 360 + * - country definition: CTRY_IRAN + * - country string: IR + * - country ID: 364 + * - country definition: CTRY_IRAQ + * - country string: IQ + * - country ID: 368 + * - country definition: CTRY_IRELAND + * - country string: IE + * - country ID: 372 + * - country definition: CTRY_ISRAEL + * - country string: IL + * - country ID: 376 + * - country definition: CTRY_ITALY + * - country string: IT + * - country ID: 380 + * - country definition: CTRY_JAMAICA + * - country string: JM + * - country ID: 388 + * - country definition: CTRY_JAPAN + * - country string: JP + * - country ID: 392 + * - country definition: CTRY_JAPAN1 + * - country string: JP1 + * - country ID: 393 + * - country definition: CTRY_JAPAN2 + * - country string: JP2 + * - country ID: 394 + * - country definition: CTRY_JAPAN3 + * - country string: JP3 + * - country ID: 395 + * - country definition: CTRY_JAPAN4 + * - country string: JP4 + * - country ID: 396 + * - country definition: CTRY_JAPAN5 + * - country string: JP5 + * - country ID: 397 + * - country definition: CTRY_JAPAN6 + * - country string: JP6 + * - country ID: 399 + * - country definition: CTRY_JAPAN7 + * - country string: JP7 + * - country ID: 4007 + * - country definition: CTRY_JAPAN8 + * - country string: JP8 + * - country ID: 4008 + * - country definition: CTRY_JAPAN9 + * - country string: JP9 + * - country ID: 4009 + * - country definition: CTRY_JAPAN10 + * - country string: JP10 + * - country ID: 4010 + * - country definition: CTRY_JAPAN11 + * - country string: JP11 + * - country ID: 4011 + * - country definition: CTRY_JAPAN12 + * - country string: JP12 + * - country ID: 4012 + * - country definition: CTRY_JAPAN13 + * - country string: JP13 + * - country ID: 4013 + * - country definition: CTRY_JAPAN14 + * - country string: JP14 + * - country ID: 4014 + * - country definition: CTRY_JAPAN15 + * - country string: JP15 + * - country ID: 4015 + * - country definition: CTRY_JAPAN16 + * - country string: JP16 + * - country ID: 4016 + * - country definition: CTRY_JAPAN17 + * - country string: JP17 + * - country ID: 4017 + * - country definition: CTRY_JAPAN18 + * - country string: JP18 + * - country ID: 4018 + * - country definition: CTRY_JAPAN19 + * - country string: JP19 + * - country ID: 4019 + * - country definition: CTRY_JAPAN20 + * - country string: JP20 + * - country ID: 4020 + * - country definition: CTRY_JAPAN21 + * - country string: JP21 + * - country ID: 4021 + * - country definition: CTRY_JAPAN22 + * - country string: JP22 + * - country ID: 4022 + * - country definition: CTRY_JAPAN23 + * - country string: JP23 + * - country ID: 4023 + * - country definition: CTRY_JAPAN24 + * - country string: JP24 + * - country ID: 4024 + * - country definition: CTRY_JAPAN25 + * - country string: JP25 + * - country ID: 4025 + * - country definition: CTRY_JAPAN26 + * - country string: JP26 + * - country ID: 4026 + * - country definition: CTRY_JAPAN27 + * - country string: JP27 + * - country ID: 4027 + * - country definition: CTRY_JAPAN28 + * - country string: JP28 + * - country ID: 4028 + * - country definition: CTRY_JAPAN29 + * - country string: JP29 + * - country ID: 4029 + * - country definition: CTRY_JAPAN30 + * - country string: JP30 + * - country ID: 4030 + * - country definition: CTRY_JAPAN31 + * - country string: JP31 + * - country ID: 4031 + * - country definition: CTRY_JAPAN32 + * - country string: JP32 + * - country ID: 4032 + * - country definition: CTRY_JAPAN33 + * - country string: JP33 + * - country ID: 4033 + * - country definition: CTRY_JAPAN34 + * - country string: JP34 + * - country ID: 4034 + * - country definition: CTRY_JAPAN35 + * - country string: JP35 + * - country ID: 4035 + * - country definition: CTRY_JAPAN36 + * - country string: JP36 + * - country ID: 4036 + * - country definition: CTRY_JAPAN37 + * - country string: JP37 + * - country ID: 4037 + * - country definition: CTRY_JAPAN38 + * - country string: JP38 + * - country ID: 4038 + * - country definition: CTRY_JAPAN39 + * - country string: JP39 + * - country ID: 4039 + * - country definition: CTRY_JAPAN40 + * - country string: JP40 + * - country ID: 4040 + * - country definition: CTRY_JAPAN41 + * - country string: JP41 + * - country ID: 4041 + * - country definition: CTRY_JAPAN42 + * - country string: JP42 + * - country ID: 4042 + * - country definition: CTRY_JAPAN43 + * - country string: JP43 + * - country ID: 4043 + * - country definition: CTRY_JAPAN44 + * - country string: JP44 + * - country ID: 4044 + * - country definition: CTRY_JAPAN45 + * - country string: JP45 + * - country ID: 4045 + * - country definition: CTRY_JAPAN46 + * - country string: JP46 + * - country ID: 4046 + * - country definition: CTRY_JAPAN47 + * - country string: JP47 + * - country ID: 4047 + * - country definition: CTRY_JAPAN48 + * - country string: JP48 + * - country ID: 4048 + * - country definition: CTRY_JAPAN49 + * - country string: JP49 + * - country ID: 4049 + * - country definition: CTRY_JAPAN50 + * - country string: JP50 + * - country ID: 4050 + * - country definition: CTRY_JAPAN51 + * - country string: JP51 + * - country ID: 4051 + * - country definition: CTRY_JAPAN52 + * - country string: JP52 + * - country ID: 4052 + * - country definition: CTRY_JAPAN53 + * - country string: JP53 + * - country ID: 4053 + * - country definition: CTRY_JAPAN54 + * - country string: JP54 + * - country ID: 4054 + * - country definition: CTRY_JAPAN55 + * - country string: JP55 + * - country ID: 4055 + * - country definition: CTRY_JAPAN56 + * - country string: JP56 + * - country ID: 4056 + * - country definition: CTRY_JORDAN + * - country string: JO + * - country ID: 400 + * - country definition: CTRY_KAZAKHSTAN + * - country string: KZ + * - country ID: 398 + * - country definition: CTRY_KENYA + * - country string: KE + * - country ID: 404 + * - country definition: CTRY_KOREA_NORTH + * - country string: KP + * - country ID: 408 + * - country definition: CTRY_KOREA_ROC + * - country string: KR + * - country ID: 410 + * - country definition: CTRY_KOREA_ROC2 + * - country string: KR2 + * - country ID: 411 + * - country definition: CTRY_KOREA_ROC3 + * - country string: KR3 + * - country ID: 412 + * - country definition: CTRY_KUWAIT + * - country string: KW + * - country ID: 414 + * - country definition: CTRY_LATVIA + * - country string: LV + * - country ID: 428 + * - country definition: CTRY_LEBANON + * - country string: LB + * - country ID: 422 + * - country definition: CTRY_LIBYA + * - country string: LY + * - country ID: 434 + * - country definition: CTRY_LIECHTENSTEIN + * - country string: LI + * - country ID: 438 + * - country definition: CTRY_LITHUANIA + * - country string: LT + * - country ID: 440 + * - country definition: CTRY_LUXEMBOURG + * - country string: LU + * - country ID: 442 + * - country definition: CTRY_MACAU + * - country string: MO + * - country ID: 446 + * - country definition: CTRY_MACEDONIA + * - country string: MK + * - country ID: 807 + * - country definition: CTRY_MALAYSIA + * - country string: MY + * - country ID: 458 + * - country definition: CTRY_MALTA + * - country string: MT + * - country ID: 470 + * - country definition: CTRY_MAURITIUS + * - country string: MU + * - country ID: 480 + * - country definition: CTRY_MEXICO + * - country string: MX + * - country ID: 484 + * - country definition: CTRY_MONACO + * - country string: MC + * - country ID: 492 + * - country definition: CTRY_MOROCCO + * - country string: MA + * - country ID: 504 + * - country definition: CTRY_NETHERLANDS + * - country string: NL + * - country ID: 528 + * - country definition: CTRY_NEW_ZEALAND + * - country string: NZ + * - country ID: 554 + * - country definition: CTRY_NICARAGUA + * - country string: NI + * - country ID: 558 + * - country definition: CTRY_NORWAY + * - country string: NO + * - country ID: 578 + * - country definition: CTRY_OMAN + * - country string: OM + * - country ID: 512 + * - country definition: CTRY_PAKISTAN + * - country string: PK + * - country ID: 586 + * - country definition: CTRY_PANAMA + * - country string: PA + * - country ID: 591 + * - country definition: CTRY_PARAGUAY + * - country string: PY + * - country ID: 600 + * - country definition: CTRY_PERU + * - country string: PE + * - country ID: 604 + * - country definition: CTRY_PHILIPPINES + * - country string: PH + * - country ID: 608 + * - country definition: CTRY_POLAND + * - country string: PL + * - country ID: 616 + * - country definition: CTRY_PORTUGAL + * - country string: PT + * - country ID: 620 + * - country definition: CTRY_PUERTO_RICO + * - country string: PR + * - country ID: 630 + * - country definition: CTRY_QATAR + * - country string: QA + * - country ID: 634 + * - country definition: CTRY_ROMANIA + * - country string: RO + * - country ID: 642 + * - country definition: CTRY_RUSSIA + * - country string: RU + * - country ID: 643 + * - country definition: CTRY_SAUDI_ARABIA + * - country string: SA + * - country ID: 682 + * - country definition: CTRY_SERBIA + * - country string: RS + * - country ID: 688 + * - country definition: CTRY_MONTENEGRO + * - country string: ME + * - country ID: 499 + * - country definition: CTRY_SINGAPORE + * - country string: SG + * - country ID: 702 + * - country definition: CTRY_SLOVAKIA + * - country string: SK + * - country ID: 703 + * - country definition: CTRY_SLOVENIA + * - country string: SI + * - country ID: 705 + * - country definition: CTRY_SOUTH_AFRICA + * - country string: ZA + * - country ID: 710 + * - country definition: CTRY_SPAIN + * - country string: ES + * - country ID: 724 + * - country definition: CTRY_SRI_LANKA + * - country string: LK + * - country ID: 144 + * - country definition: CTRY_SWEDEN + * - country string: SE + * - country ID: 752 + * - country definition: CTRY_SWITZERLAND + * - country string: CH + * - country ID: 756 + * - country definition: CTRY_SYRIA + * - country string: SY + * - country ID: 760 + * - country definition: CTRY_TAIWAN + * - country string: TW + * - country ID: 158 + * - country definition: CTRY_TANZANIA + * - country string: TZ + * - country ID: 834 + * - country definition: CTRY_THAILAND + * - country string: TH + * - country ID: 764 + * - country definition: CTRY_TRINIDAD_Y_TOBAGO + * - country string: TT + * - country ID: 780 + * - country definition: CTRY_TUNISIA + * - country string: TN + * - country ID: 788 + * - country definition: CTRY_TURKEY + * - country string: TR + * - country ID: 792 + * - country definition: CTRY_UAE + * - country string: AE + * - country ID: 784 + * - country definition: CTRY_UKRAINE + * - country string: UA + * - country ID: 804 + * - country definition: CTRY_UNITED_KINGDOM + * - country string: GB + * - country ID: 826 + * - country definition: CTRY_UNITED_STATES + * - country string: US + * - country ID: 840 + * - country definition: CTRY_UNITED_STATES_FCC49 + * - country string: US + * - country ID: 842 + * - country definition: CTRY_URUGUAY + * - country string: UY + * - country ID: 858 + * - country definition: CTRY_UZBEKISTAN + * - country string: UZ + * - country ID: 860 + * - country definition: CTRY_VENEZUELA + * - country string: VE + * - country ID: 862 + * - country definition: CTRY_VIET_NAM + * - country string: VN + * - country ID: 704 + * - country definition: CTRY_YEMEN + * - country string: YE + * - country ID: 887 + * - country definition: CTRY_ZIMBABWE + * - country string: ZW + * - country ID: 716 + */ +enum CountryCode { + CTRY_ALBANIA = 8, /* Albania */ + CTRY_ALGERIA = 12, /* Algeria */ + CTRY_ARGENTINA = 32, /* Argentina */ + CTRY_ARMENIA = 51, /* Armenia */ + CTRY_AUSTRALIA = 36, /* Australia */ + CTRY_AUSTRIA = 40, /* Austria */ + CTRY_AZERBAIJAN = 31, /* Azerbaijan */ + CTRY_BAHAMAS = 44, /* Bahamas */ + CTRY_BAHRAIN = 48, /* Bahrain */ + CTRY_BANGLADESH = 50, /* Bangladesh */ + CTRY_BARBADOS = 52, /* Barbados */ + CTRY_BELARUS = 112, /* Belarus */ + CTRY_BELGIUM = 56, /* Belgium */ + CTRY_BELIZE = 84, /* Belize */ + CTRY_BERMUDA = 60, /* Berumuda */ + CTRY_BOLIVIA = 68, /* Bolivia */ + CTRY_BOSNIA_HERZ = 70, /* Bosnia and Herzegowina */ + CTRY_BRAZIL = 76, /* Brazil */ + CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ + CTRY_BULGARIA = 100, /* Bulgaria */ + CTRY_CAMBODIA = 116, /* Cambodia */ + CTRY_CANADA = 124, /* Canada */ + CTRY_CHILE = 152, /* Chile */ + CTRY_CHINA = 156, /* People's Republic of China */ + CTRY_COLOMBIA = 170, /* Colombia */ + CTRY_COSTA_RICA = 188, /* Costa Rica */ + CTRY_CROATIA = 191, /* Croatia */ + CTRY_CYPRUS = 196, + CTRY_CZECH = 203, /* Czech Republic */ + CTRY_DENMARK = 208, /* Denmark */ + CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ + CTRY_ECUADOR = 218, /* Ecuador */ + CTRY_EGYPT = 818, /* Egypt */ + CTRY_EL_SALVADOR = 222, /* El Salvador */ + CTRY_ESTONIA = 233, /* Estonia */ + CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ + CTRY_FINLAND = 246, /* Finland */ + CTRY_FRANCE = 250, /* France */ + CTRY_GEORGIA = 268, /* Georgia */ + CTRY_GERMANY = 276, /* Germany */ + CTRY_GREECE = 300, /* Greece */ + CTRY_GREENLAND = 304, /* Greenland */ + CTRY_GRENADA = 308, /* Grenada */ + CTRY_GUAM = 316, /* Guam */ + CTRY_GUATEMALA = 320, /* Guatemala */ + CTRY_HAITI = 332, /* Haiti */ + CTRY_HONDURAS = 340, /* Honduras */ + CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ + CTRY_HUNGARY = 348, /* Hungary */ + CTRY_ICELAND = 352, /* Iceland */ + CTRY_INDIA = 356, /* India */ + CTRY_INDONESIA = 360, /* Indonesia */ + CTRY_IRAN = 364, /* Iran */ + CTRY_IRAQ = 368, /* Iraq */ + CTRY_IRELAND = 372, /* Ireland */ + CTRY_ISRAEL = 376, /* Israel */ + CTRY_ITALY = 380, /* Italy */ + CTRY_JAMAICA = 388, /* Jamaica */ + CTRY_JAPAN = 392, /* Japan */ + CTRY_JORDAN = 400, /* Jordan */ + CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ + CTRY_KENYA = 404, /* Kenya */ + CTRY_KOREA_NORTH = 408, /* North Korea */ + CTRY_KOREA_ROC = 410, /* South Korea */ + CTRY_KOREA_ROC3 = 412, /* South Korea */ + CTRY_KUWAIT = 414, /* Kuwait */ + CTRY_LATVIA = 428, /* Latvia */ + CTRY_LEBANON = 422, /* Lebanon */ + CTRY_LIBYA = 434, /* Libya */ + CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ + CTRY_LITHUANIA = 440, /* Lithuania */ + CTRY_LUXEMBOURG = 442, /* Luxembourg */ + CTRY_MACAU = 446, /* Macau SAR */ + CTRY_MACEDONIA = 807, /* the Former Yugoslav Republic of Macedonia */ + CTRY_MALAYSIA = 458, /* Malaysia */ + CTRY_MALDIVES = 462, /* Maldives */ + CTRY_MALTA = 470, /* Malta */ + CTRY_MAURITIUS = 480, /* Mauritius */ + CTRY_MEXICO = 484, /* Mexico */ + CTRY_MONACO = 492, /* Principality of Monaco */ + CTRY_MOROCCO = 504, /* Morocco */ + CTRY_NEPAL = 524, /* Nepal */ + CTRY_NETHERLANDS = 528, /* Netherlands */ + CTRY_NETHERLANDS_ANTILLES = 530, /* Netherlands-Antilles */ + CTRY_ARUBA = 533, /* Aruba */ + CTRY_NEW_ZEALAND = 554, /* New Zealand */ + CTRY_NICARAGUA = 558, /* Nicaragua */ + CTRY_NORWAY = 578, /* Norway */ + CTRY_OMAN = 512, /* Oman */ + CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ + CTRY_PANAMA = 591, /* Panama */ + CTRY_PAPUA_NEW_GUINEA = 598, /* Papua New Guinea */ + CTRY_PARAGUAY = 600, /* Paraguay */ + CTRY_PERU = 604, /* Peru */ + CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ + CTRY_POLAND = 616, /* Poland */ + CTRY_PORTUGAL = 620, /* Portugal */ + CTRY_PUERTO_RICO = 630, /* Puerto Rico */ + CTRY_QATAR = 634, /* Qatar */ + CTRY_ROMANIA = 642, /* Romania */ + CTRY_RUSSIA = 643, /* Russia */ + CTRY_RWANDA = 646, /* Rwanda */ + CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ + CTRY_SERBIA = 688, /* Republic of Serbia */ + CTRY_MONTENEGRO = 499, /* Montenegro */ + CTRY_SINGAPORE = 702, /* Singapore */ + CTRY_SLOVAKIA = 703, /* Slovak Republic */ + CTRY_SLOVENIA = 705, /* Slovenia */ + CTRY_SOUTH_AFRICA = 710, /* South Africa */ + CTRY_SPAIN = 724, /* Spain */ + CTRY_SRI_LANKA = 144, /* Sri Lanka */ + CTRY_SWEDEN = 752, /* Sweden */ + CTRY_SWITZERLAND = 756, /* Switzerland */ + CTRY_SYRIA = 760, /* Syria */ + CTRY_TAIWAN = 158, /* Taiwan */ + CTRY_TANZANIA = 834, /* Tanzania */ + CTRY_THAILAND = 764, /* Thailand */ + CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ + CTRY_TUNISIA = 788, /* Tunisia */ + CTRY_TURKEY = 792, /* Turkey */ + CTRY_UAE = 784, /* U.A.E. */ + CTRY_UGANDA = 800, /* Uganda */ + CTRY_UKRAINE = 804, /* Ukraine */ + CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ + CTRY_UNITED_STATES = 840, /* United States */ + CTRY_UNITED_STATES2 = 841, /* United States for AP */ + CTRY_UNITED_STATES_FCC49 = 842, /* United States (Public Safety)*/ + CTRY_URUGUAY = 858, /* Uruguay */ + CTRY_UZBEKISTAN = 860, /* Uzbekistan */ + CTRY_VENEZUELA = 862, /* Venezuela */ + CTRY_VIET_NAM = 704, /* Viet Nam */ + CTRY_YEMEN = 887, /* Yemen */ + CTRY_ZIMBABWE = 716, /* Zimbabwe */ + + /* + ** Japan special codes. Boy, do they have a lot + */ + + CTRY_JAPAN1 = 393, /* Japan (JP1) */ + CTRY_JAPAN2 = 394, /* Japan (JP0) */ + CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ + CTRY_JAPAN4 = 396, /* Japan (JE1) */ + CTRY_JAPAN5 = 397, /* Japan (JE2) */ + CTRY_JAPAN6 = 4006, /* Japan (JP6) */ + CTRY_JAPAN7 = 4007, /* Japan (J7) */ + CTRY_JAPAN8 = 4008, /* Japan (J8) */ + CTRY_JAPAN9 = 4009, /* Japan (J9) */ + CTRY_JAPAN10 = 4010, /* Japan (J10) */ + CTRY_JAPAN11 = 4011, /* Japan (J11) */ + CTRY_JAPAN12 = 4012, /* Japan (J12) */ + CTRY_JAPAN13 = 4013, /* Japan (J13) */ + CTRY_JAPAN14 = 4014, /* Japan (J14) */ + CTRY_JAPAN15 = 4015, /* Japan (J15) */ + CTRY_JAPAN16 = 4016, /* Japan (J16) */ + CTRY_JAPAN17 = 4017, /* Japan (J17) */ + CTRY_JAPAN18 = 4018, /* Japan (J18) */ + CTRY_JAPAN19 = 4019, /* Japan (J19) */ + CTRY_JAPAN20 = 4020, /* Japan (J20) */ + CTRY_JAPAN21 = 4021, /* Japan (J21) */ + CTRY_JAPAN22 = 4022, /* Japan (J22) */ + CTRY_JAPAN23 = 4023, /* Japan (J23) */ + CTRY_JAPAN24 = 4024, /* Japan (J24) */ + CTRY_JAPAN25 = 4025, /* Japan (J25) */ + CTRY_JAPAN26 = 4026, /* Japan (J26) */ + CTRY_JAPAN27 = 4027, /* Japan (J27) */ + CTRY_JAPAN28 = 4028, /* Japan (J28) */ + CTRY_JAPAN29 = 4029, /* Japan (J29) */ + CTRY_JAPAN30 = 4030, /* Japan (J30) */ + CTRY_JAPAN31 = 4031, /* Japan (J31) */ + CTRY_JAPAN32 = 4032, /* Japan (J32) */ + CTRY_JAPAN33 = 4033, /* Japan (J33) */ + CTRY_JAPAN34 = 4034, /* Japan (J34) */ + CTRY_JAPAN35 = 4035, /* Japan (J35) */ + CTRY_JAPAN36 = 4036, /* Japan (J36) */ + CTRY_JAPAN37 = 4037, /* Japan (J37) */ + CTRY_JAPAN38 = 4038, /* Japan (J38) */ + CTRY_JAPAN39 = 4039, /* Japan (J39) */ + CTRY_JAPAN40 = 4040, /* Japan (J40) */ + CTRY_JAPAN41 = 4041, /* Japan (J41) */ + CTRY_JAPAN42 = 4042, /* Japan (J42) */ + CTRY_JAPAN43 = 4043, /* Japan (J43) */ + CTRY_JAPAN44 = 4044, /* Japan (J44) */ + CTRY_JAPAN45 = 4045, /* Japan (J45) */ + CTRY_JAPAN46 = 4046, /* Japan (J46) */ + CTRY_JAPAN47 = 4047, /* Japan (J47) */ + CTRY_JAPAN48 = 4048, /* Japan (J48) */ + CTRY_JAPAN49 = 4049, /* Japan (J49) */ + CTRY_JAPAN50 = 4050, /* Japan (J50) */ + CTRY_JAPAN51 = 4051, /* Japan (J51) */ + CTRY_JAPAN52 = 4052, /* Japan (J52) */ + CTRY_JAPAN53 = 4053, /* Japan (J53) */ + CTRY_JAPAN54 = 4054, /* Japan (J54) */ + CTRY_JAPAN55 = 4055, /* Japan (J55) */ + CTRY_JAPAN56 = 4056, /* Japan (J56) */ + CTRY_JAPAN57 = 4057, /* Japan (J57) */ + CTRY_JAPAN58 = 4058, /* Japan (J58) */ + CTRY_JAPAN59 = 4059, /* Japan (J59) */ + + /* + ** "Special" codes for multiply defined countries, with the exception + ** of Japan and US. + */ + + CTRY_AUSTRALIA2 = 5000, /* Australia for AP only */ + CTRY_CANADA2 = 5001, /* Canada for AP only */ + CTRY_BELGIUM2 = 5002 /* Belgium/Cisco implementation */ +}; + +int32_t regdmn_get_country_alpha2(struct regulatory *reg); +void regdmn_set_regval(struct regulatory *reg); + +int32_t regdmn_find_ctry_by_name(u_int8_t *alpha2); +void regdmn_set_dfs_region(struct regulatory *reg); + +#endif /* REGULATORY_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h new file mode 100644 index 000000000000..46daf2fac44c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h @@ -0,0 +1,1864 @@ +/* + * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* +* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting +* Copyright (c) 2005-2011 Atheros Communications, Inc. +* All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +* +* $FreeBSD: release/9.0.0/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h 224226 2011-07-20 12:46:58Z adrian $ +*/ + /* + * This module contains the common regulatory domain database tables: + * + * - reg domain enum constants + * - reg domain enum to reg domain pair mappings + * - country to regdomain mappings + * - channel tag enums and the frequency-to-frequency band mappings + * for all the modes + * + * "The country table and respective Regulatory Domain channel and power + * settings are based on available knowledge as of software release. The + * underlying global regulatory and spectrum rules change on a regular basis, + * therefore, no warranty is given that the channel and power information + * herein is complete, accurate or up to date. Developers are responsible + * for regulatory compliance of end-products developed using the enclosed + * data per all applicable national requirements. Furthermore, data in this + * table does not guarantee that spectrum is available and that regulatory + * approval is possible in every case. Knowldegable regulatory compliance + * or government contacts should be consulted by the manufacturer to ensure + * that the most current and accurate settings are used in each end-product. + * This table was designed so that developers are able to update the country + * table mappings as well as the Regulatory Domain definitions in order to + * incorporate the most current channel and power settings in the end-product." + * + */ + +/* Enumerated Regulatory Domain Information 8 bit values indicate that + * the regdomain is really a pair of unitary regdomains. 12 bit values + * are the real unitary regdomains and are the only ones which have the + * frequency bitmasks and flags set. + */ + +#include "_ieee80211_common.h" +#include +#include "wlan_defs.h" + +#define MAX_CHANNELS_PER_OPERATING_CLASS 25 + +enum EnumRd { + /* + * The following regulatory domain definitions are + * found in the EEPROM. Each regulatory domain + * can operate in either a 5GHz or 2.4GHz wireless mode or + * both 5GHz and 2.4GHz wireless modes. + * In general, the value holds no special + * meaning and is used to decode into either specific + * 2.4GHz or 5GHz wireless mode for that particular + * regulatory domain. + */ + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ + NULL1_ETSIB = 0x07, /* Israel */ + NULL1_ETSIC = 0x08, + FCC1_FCCA = 0x10, /* USA */ + FCC1_WORLD = 0x11, /* Hong Kong */ + FCC4_FCCA = 0x12, /* USA - Public Safety */ + FCC5_FCCA = 0x13, /* US with no DFS (UNII-1 + UNII-3 Only)*/ + FCC6_FCCA = 0x14, /* Canada for AP only*/ + + FCC2_FCCA = 0x20, /* Canada */ + FCC2_WORLD = 0x21, /* Australia & HK */ + FCC2_ETSIC = 0x22, + FCC6_WORLD = 0x23, /* Australia for AP only*/ + FRANCE_RES = 0x31, /* Legacy France for OEM */ + FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_ETSIC = 0x3F, /* New Zealand, DFS enabled */ + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, /* France (optional) */ + ETSI2_WORLD = 0x35, /* Hungary & others */ + ETSI3_WORLD = 0x36, /* France & others */ + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, /* Bulgaria */ + ETSI8_WORLD = 0x3D, /* Russia */ + ETSI9_WORLD = 0x3E, /* Ukraine */ + ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ + + MKK1_MKKA = 0x40, /* Japan (JP1) */ + MKK1_MKKB = 0x41, /* Japan (JP0) */ + APL4_WORLD = 0x42, /* Singapore and Morocco */ + MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ + APL_RESERVED = 0x44, /* Reserved (Do not used) */ + APL2_WORLD = 0x45, /* Korea */ + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, /* Japan (JP1-1) */ + APL2_APLD = 0x49, /* Korea with 2.3G channels */ + MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ + MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ + MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ + APL2_FCCA = 0x4D, /* Mobile customer */ + APL11_FCCA = 0x4F, /* Specific AP Customer 5GHz, For APs Only */ + + APL3_FCCA = 0x50, + APL12_WORLD = 0x51, + APL1_WORLD = 0x52, /* Latin America */ + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, /* Venezuela */ + APL5_WORLD = 0x58, /* Chile */ + APL13_WORLD = 0x5A, /* Algeria */ + APL6_WORLD = 0x5B, /* Singapore */ + APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ + APL8_WORLD = 0x5D, /* Malaysia 5GHz */ + APL9_MKKC = 0x5E, /* Korea 5GHz, Before 11/2007. Now used only by APs */ + APL10_MKKC = 0x5F, /* Korea 5GHz, After 11/2007. For STAs only */ + + /* + * World mode SKUs + */ + WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ + WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ + WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ + WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ + WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ + WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ + + WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ + WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ + EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ + + WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ + WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ + WORB_WORLD = 0x6B, /* WorldB (WOB SKU) */ + WORC_WORLD = 0x6C, /* WorldC (WOC SKU) */ + + MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ + MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ + MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ + + MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ + MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ + MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ + + MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + MKK5_FCCA = 0x9A, + + MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ + MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + MKK14_MKKA1 = 0x92, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz + MKKA1 */ + MKK15_MKKA1 = 0x93, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz + MKKA1 */ + + MKK10_FCCA = 0xD0, /* Japan UNI-1 even + UNI-2 + 4.9GHz + FCCA */ + MKK10_MKKA1 = 0xD1, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA1 */ + MKK10_MKKC = 0xD2, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKC */ + MKK10_MKKA2 = 0xD3, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA2 */ + + MKK11_MKKA = 0xD4, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK11_FCCA = 0xD5, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK11_MKKA1 = 0xD6, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK11_MKKC = 0xD7, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK11_MKKA2 = 0xD8, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK12_MKKA = 0xD9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK12_FCCA = 0xDA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK12_MKKA1 = 0xDB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK12_MKKC = 0xDC, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK12_MKKA2 = 0xDD, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK13_MKKB = 0xDE, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB + All passive + no adhoc */ + + /* Following definitions are used only by s/w to map old + * Japan SKUs. + */ + MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ + MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ + MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ + MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ + MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ + MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ + MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ + MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + MKK6_MKKA1 = 0xF8, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK6_FCCA = 0xF9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK7_MKKA1 = 0xFA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK7_FCCA = 0xFB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK9_FCCA = 0xFC, /* Japan UNI-1 even + 4.9GHz + FCCA */ + MKK9_MKKA1 = 0xFD, /* Japan UNI-1 even + 4.9GHz + MKKA1 */ + MKK9_MKKC = 0xFE, /* Japan UNI-1 even + 4.9GHz + MKKC */ + MKK9_MKKA2 = 0xFF, /* Japan UNI-1 even + 4.9GHz + MKKA2 */ + + /* + * Regulator domains ending in a number (e.g. APL1, + * MK1, ETSI4, etc) apply to 5GHz channel and power + * information. Regulator domains ending in a letter + * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and + * power information. + */ + APL1 = 0x0150, /* LAT & Asia */ + APL2 = 0x0250, /* LAT & Asia */ + APL3 = 0x0350, /* Taiwan */ + APL4 = 0x0450, /* Jordan */ + APL5 = 0x0550, /* Chile */ + APL6 = 0x0650, /* Singapore */ + APL7 = 0x0750, /* Taiwan, disable ch52 */ + APL8 = 0x0850, /* Malaysia */ + APL9 = 0x0950, /* Korea. Before 11/2007. Now used only by APs */ + APL10 = 0x1050, /* Korea. After 11/2007. For STAs only */ + APL11 = 0x1150, /* Specific AP Customer 5GHz, For APs Only */ + APL12 = 0x1160, /* Kenya */ + + ETSI1 = 0x0130, /* Europe & others */ + ETSI2 = 0x0230, /* Europe & others */ + ETSI3 = 0x0330, /* Europe & others */ + ETSI4 = 0x0430, /* Europe & others */ + ETSI5 = 0x0530, /* Europe & others */ + ETSI6 = 0x0630, /* Europe & others */ + ETSI8 = 0x0830, /* Russia */ + ETSI9 = 0x0930, /* Ukraine */ + ETSIA = 0x0A30, /* France */ + ETSIB = 0x0B30, /* Israel */ + ETSIC = 0x0C30, /* Latin America */ + + FCC1 = 0x0110, /* US & others */ + FCC2 = 0x0120, /* Canada, Australia & New Zealand */ + FCC3 = 0x0160, /* US w/new middle band & DFS */ + FCC4 = 0x0165, /* US Public Safety */ + FCC5 = 0x0510, + FCC6 = 0x0610, /* Canada & Australia */ + FCCA = 0x0A10, + + APLD = 0x0D50, /* South Korea */ + + MKK1 = 0x0140, /* Japan (UNI-1 odd)*/ + MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ + MKK3 = 0x0340, /* Japan (UNI-1 even) */ + MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ + MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ + MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ + MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ + MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK11 = 0x1140, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK12 = 0x1240, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK13 = 0x0C40, /* Same as MKK8 but all passive and no adhoc 11a */ + MKK14 = 0x1440, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz */ + MKK15 = 0x1540, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz */ + MKKA = 0x0A40, /* Japan */ + MKKC = 0x0A50, + + NULL1 = 0x0198, + WORLD = 0x0199, + DEBUG_REG_DMN = 0x01ff, +}; + +enum { /* conformance test limits */ + FCC = 0x10, + MKK = 0x40, + ETSI = 0x30, +}; +/* + * The following are flags for different requirements per reg domain. + * These requirements are either inhereted from the reg domain pair or + * from the unitary reg domain if the reg domain pair flags value is + * 0 + */ + +enum { + NO_REQ = 0x00000000, + DISALLOW_ADHOC_11A = 0x00000001, + DISALLOW_ADHOC_11A_TURB = 0x00000002, + NEED_NFC = 0x00000004, + + ADHOC_PER_11D = 0x00000008, /* Start Ad-Hoc mode */ + ADHOC_NO_11A = 0x00000010, + + PUBLIC_SAFETY_DOMAIN = 0x00000020, /* public safety domain */ + LIMIT_FRAME_4MS = 0x00000040, /* 4msec limit on the frame length */ + + NO_HOSTAP = 0x00000080, /* No HOSTAP mode opereation */ + + REQ_MASK = 0x000000FF, /* Requirements bit mask */ +}; + +static const REG_DMN_PAIR_MAPPING ahCmnRegDomainPairs[] = { + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC3_ETSIC, FCC3, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {FCC5_FCCA, FCC5, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC6_WORLD, FCC6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI3_WORLD, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI4_WORLD, ETSI4, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI5_WORLD, ETSI5, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI6_WORLD, ETSI6, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI8_WORLD, ETSI8, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {ETSI9_WORLD, ETSI9, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + + {ETSI3_ETSIA, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL2_FCCA, APL2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL7_FCCA, APL7, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL9_MKKC, APL9, MKKC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL10_MKKC, APL10, MKKC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + + {MKK1_MKKA, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN }, + {MKK1_MKKB, MKK1, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 }, + {MKK1_FCCA, MKK1, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 }, + {MKK1_MKKA1, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 }, + {MKK1_MKKA2, MKK1, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 }, + {MKK1_MKKC, MKK1, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 }, + + /* MKK2 */ + {MKK2_MKKA, MKK2, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 }, + + /* MKK3 */ + {MKK3_MKKA, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC , PSCAN_MKKA, CTRY_JAPAN25 }, + {MKK3_MKKB, MKK3, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 }, + {MKK3_MKKA1, MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN26 }, + {MKK3_MKKA2,MKK3, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 }, + {MKK3_MKKC, MKK3, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 }, + {MKK3_FCCA, MKK3, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN27 }, + + /* MKK4 */ + {MKK4_MKKA, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN36 }, + {MKK4_MKKB, MKK4, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 }, + {MKK4_MKKA1, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN28 }, + {MKK4_MKKA2, MKK4, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 }, + {MKK4_MKKC, MKK4, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 }, + {MKK4_FCCA, MKK4, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN29 }, + + /* MKK5 */ +/* {MKK5_MKKA, MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN56 },*/ + {MKK5_MKKB, MKK5, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 }, + {MKK5_MKKA2,MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 }, + {MKK5_MKKC, MKK5, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 }, + {MKK5_FCCA, MKK5, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN56 }, + + /* MKK6 */ + {MKK6_MKKB, MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 }, + {MKK6_MKKA1,MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30 }, + {MKK6_MKKA2, MKK6, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 }, + {MKK6_MKKC, MKK6, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 }, + {MKK6_FCCA, MKK6, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN31 }, + + /* MKK7 */ + {MKK7_MKKB, MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 }, + {MKK7_MKKA1,MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32 }, + {MKK7_MKKA2, MKK7, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 }, + {MKK7_MKKC, MKK7, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 }, + {MKK7_FCCA, MKK7, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN33 }, + + /* MKK8 */ + {MKK8_MKKB, MKK8, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 }, + {MKK8_MKKA2,MKK8, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 }, + {MKK8_MKKC, MKK8, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 }, + + {MKK9_MKKA, MKK9, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN34 }, + {MKK9_FCCA, MKK9, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN37 }, + {MKK9_MKKA1, MKK9, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38 }, + {MKK9_MKKA2, MKK9, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40 }, + {MKK9_MKKC, MKK9, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, NO_PSCAN, CTRY_JAPAN39 }, + + {MKK10_MKKA, MKK10, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN35 }, + {MKK10_FCCA, MKK10, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 , CTRY_JAPAN41 }, + {MKK10_MKKA1, MKK10, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42 }, + {MKK10_MKKA2, MKK10, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44 }, + {MKK10_MKKC, MKK10, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN43 }, + + {MKK11_MKKA, MKK11, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN45 }, + {MKK11_FCCA, MKK11, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN46 }, + {MKK11_MKKA1, MKK11, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47 }, + {MKK11_MKKA2, MKK11, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49 }, + {MKK11_MKKC, MKK11, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN48 }, + + {MKK12_MKKA, MKK12, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN50 }, + {MKK12_FCCA, MKK12, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN51 }, + {MKK12_MKKA1, MKK12, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN52 }, + {MKK12_MKKA2, MKK12, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN54 }, + {MKK12_MKKC, MKK12, MKKC, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN53 }, + + {MKK13_MKKB, MKK13, MKKA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN57 }, + + {MKK14_MKKA1, MKK14, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN58 }, + {MKK15_MKKA1, MKK15, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN59 }, + + /* These are super domains */ + {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WORB_WORLD, WORB_WORLD, WORB_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 }, + {WORC_WORLD, WORC_WORLD, WORC_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, +}; + +static const COUNTRY_CODE_TO_ENUM_RD ahCmnAllCountries[] = { + {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ARGENTINA, FCC3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_ARUBA, ETSI1_WORLD, "AW", "ARUBA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_AUSTRALIA, FCC3_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_AUSTRALIA2, FCC6_WORLD, "AU", "AUSTRALIA2", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BAHAMAS, FCC3_WORLD, "BS", "BAHAMAS", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_BANGLADESH, NULL1_WORLD, "BD", "BANGLADESH", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_BARBADOS, FCC2_WORLD, "BB", "BARBADOS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BELGIUM2, ETSI4_WORLD, "BE", "BELGIUM2", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BERMUDA, FCC3_FCCA, "BM", "BERMUDA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLIVIA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", "BOSNIA AND HERZEGOVINA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN", "BRUNEI DARUSSALAM", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_BULGARIA, ETSI1_WORLD, "BG", "BULGARIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CAMBODIA, ETSI1_WORLD, "KH", "CAMBODIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CANADA, FCC3_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CANADA2, FCC6_FCCA, "CA", "CANADA2", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_COLOMBIA, FCC3_WORLD, "CO", "COLOMBIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_CROATIA, ETSI1_WORLD, "HR", "CROATIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_CZECH, ETSI1_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO", "DOMINICAN REPUBLIC", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_GREENLAND, ETSI1_WORLD, "GL", "GREENLAND", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_GRENADA, FCC3_FCCA, "GD", "GRENADA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_GUAM, FCC1_FCCA, "GU", "GUAM", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_HAITI, ETSI1_WORLD, "HT", "HAITI", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_HONDURAS, FCC3_WORLD, "HN", "HONDURAS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_HONG_KONG, FCC3_WORLD, "HK", "HONG KONG", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_INDONESIA, APL2_WORLD, "ID", "INDONESIA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ISRAEL, ETSI3_WORLD, "IL", "ISRAEL", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_JAMAICA, FCC3_WORLD, "JM", "JAMAICA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_JAPAN, MKK5_MKKA2, "JP", "JAPAN", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, YES, YES, YES, NO, NO, 7000 }, + {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN25, MKK3_MKKA, "JP", "JAPAN25", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN26, MKK3_MKKA1, "JP", "JAPAN26", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN27, MKK3_FCCA, "JP", "JAPAN27", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN28, MKK4_MKKA1, "JP", "JAPAN28", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN29, MKK4_FCCA, "JP", "JAPAN29", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN30, MKK6_MKKA1, "JP", "JAPAN30", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN31, MKK6_FCCA, "JP", "JAPAN31", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN32, MKK7_MKKA1, "JP", "JAPAN32", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN33, MKK7_FCCA, "JP", "JAPAN33", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN34, MKK9_MKKA, "JP", "JAPAN34", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN35, MKK10_MKKA, "JP", "JAPAN35", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN36, MKK4_MKKA, "JP", "JAPAN36", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN37, MKK9_FCCA, "JP", "JAPAN37", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN38, MKK9_MKKA1, "JP", "JAPAN38", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN39, MKK9_MKKC, "JP", "JAPAN39", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN40, MKK9_MKKA2, "JP", "JAPAN40", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN41, MKK10_FCCA, "JP", "JAPAN41", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN42, MKK10_MKKA1, "JP", "JAPAN42", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN43, MKK10_MKKC, "JP", "JAPAN43", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN44, MKK10_MKKA2, "JP", "JAPAN44", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN45, MKK11_MKKA, "JP", "JAPAN45", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN46, MKK11_FCCA, "JP", "JAPAN46", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN47, MKK11_MKKA1, "JP", "JAPAN47", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN48, MKK11_MKKC, "JP", "JAPAN48", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN49, MKK11_MKKA2, "JP", "JAPAN49", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN50, MKK12_MKKA, "JP", "JAPAN50", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN51, MKK12_FCCA, "JP", "JAPAN51", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN52, MKK12_MKKA1, "JP", "JAPAN52", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN53, MKK12_MKKC, "JP", "JAPAN53", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN54, MKK12_MKKA2, "JP", "JAPAN54", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, +/* {CTRY_JAPAN55, MKK5_MKKA, "JP", "JAPAN55", YES, NO, NO, YES, YES, YES, YES, NO, 7000 },*/ + {CTRY_JAPAN56, MKK5_FCCA, "JP", "JAPAN56", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN57, MKK13_MKKB, "JP", "JAPAN57", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN58, MKK14_MKKA1, "JP", "JAPAN58", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN59, MKK15_MKKA1, "JP", "JAPAN59", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_KENYA, APL1_WORLD, "KE", "KENYA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_KOREA_NORTH, APL9_MKKC, "KP", "NORTH KOREA", YES, NO, NO, YES, NO, YES, NO, NO, 7000 }, + {CTRY_KOREA_ROC, APL10_MKKC, "KR", "KOREA REPUBLIC", YES, NO, NO, YES, YES, YES, YES, YES, 7000 }, + {CTRY_KOREA_ROC3, APL9_MKKC, "KR", "KOREA REPUBLIC3", YES, NO, NO, YES, NO, YES, NO, NO, 7000 }, + {CTRY_KUWAIT, ETSI3_WORLD, "KW", "KUWAIT", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_LEBANON, APL1_WORLD, "LB", "LEBANON", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU SAR", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MACEDONIA, ETSI1_WORLD, "MK", "MACEDONIA, FYRO", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MALAYSIA, FCC1_WORLD, "MY", "MALAYSIA", YES, NO, NO, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MAURITIUS, ETSI1_WORLD, "MU", "MAURITIUS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MEXICO, FCC1_WORLD, "MX", "MEXICO", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MOROCCO, APL4_WORLD, "MA", "MOROCCO", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_NEPAL, APL1_WORLD, "NP", "NEPAL", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN", "NETHERLANDS ANTILLES", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_NICARAGUA, FCC3_FCCA, "NI", "NICARAGUA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_OMAN, FCC3_WORLD, "OM", "OMAN", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PAKISTAN, APL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG", "PAPUA NEW GUINEA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PARAGUAY, FCC3_WORLD, "PY", "PARAGUAY", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PERU, FCC3_WORLD, "PE", "PERU", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PHILIPPINES, FCC3_WORLD, "PH", "PHILIPPINES", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_QATAR, APL1_WORLD, "QA", "QATAR", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_ROMANIA, ETSI1_WORLD, "RO", "ROMANIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_RUSSIA, ETSI8_WORLD, "RU", "RUSSIA", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_RWANDA, APL1_WORLD, "RW", "RWANDA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SAUDI_ARABIA, FCC2_WORLD, "SA", "SAUDI ARABIA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_SERBIA, ETSI1_WORLD, "RS", "REPUBLIC OF SERBIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_MONTENEGRO, ETSI1_WORLD, "ME", "MONTENEGRO", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SINGAPORE, FCC3_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAKIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SRI_LANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIAN ARAB REPUBLIC", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_TAIWAN, APL7_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_TANZANIA, APL1_WORLD, "TZ", "TANZANIA", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_THAILAND, FCC3_WORLD, "TH", "THAILAND", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT", "TRINIDAD AND TOBAGO", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, + {CTRY_UGANDA, FCC3_WORLD, "UG", "UGANDA", YES, NO, NO, YES, YES, YES, YES, YES, 7000 }, + {CTRY_UKRAINE, ETSI9_WORLD, "UA", "UKRAINE", YES, NO, NO, YES, YES, YES, YES, NO, 7000 }, + {CTRY_UAE, ETSI1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB", "UNITED KINGDOM", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES, YES, YES, YES, YES, YES, YES, 5825 }, + {CTRY_UNITED_STATES2, FCC6_FCCA, "US", "UNITED STATES2", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_URUGUAY, FCC3_WORLD, "UY", "URUGUAY", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_VENEZUELA, FCC1_WORLD, "VE", "VENEZUELA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_VIET_NAM, ETSI3_WORLD, "VN", "VIET NAM", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, + {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES, YES, NO, NO, NO, 7000 } +}; + + +/* Bit masks for DFS per regdomain */ + +enum { + NO_DFS = 0x0000000000000000ULL, + DFS_FCC3 = 0x0000000000000001ULL, + DFS_ETSI = 0x0000000000000002ULL, + DFS_MKK4 = 0x0000000000000004ULL, +}; + + +/* The table of frequency bands is indexed by a bitmask. The ordering + * must be consistent with the enum below. When adding a new + * frequency band, be sure to match the location in the enum with the + * comments + */ + +/* + * 5GHz 11A channel tags + */ +enum { + F1_4912_4947, + F1_4915_4925, + F2_4915_4925, + F1_4935_4945, + F2_4935_4945, + F1_4920_4980, + F2_4920_4980, + F1_4942_4987, + F1_4945_4985, + F1_4950_4980, + F1_5032_5057, + F1_5035_5040, + F2_5035_5040, + F1_5035_5045, + F1_5040_5040, + F1_5040_5080, + F2_5040_5080, + F1_5055_5055, + F2_5055_5055, + + F1_5120_5240, + + F1_5170_5230, + F2_5170_5230, + + F1_5180_5240, + F2_5180_5240, + F3_5180_5240, + F4_5180_5240, + F5_5180_5240, + F6_5180_5240, + F7_5180_5240, + F8_5180_5240, + F9_5180_5240, + F10_5180_5240, + + F1_5240_5280, + + F1_5260_5280, + + F1_5260_5320, + F2_5260_5320, + F3_5260_5320, + F4_5260_5320, + F5_5260_5320, + F6_5260_5320, + F7_5260_5320, + + F1_5260_5700, + + F1_5280_5320, + F2_5280_5320, + F1_5500_5560, + + F1_5500_5580, + F2_5500_5580, + + F1_5500_5620, + + F1_5500_5660, + + F1_5500_5720, + F2_5500_5700, + F3_5500_5700, + F4_5500_5700, + F5_5500_5700, + F6_5500_5700, + + F1_5660_5700, + F2_5660_5720, + F3_5660_5720, + + F1_5745_5765, + + F1_5745_5805, + F2_5745_5805, + F3_5745_5805, + F4_5745_5805, + + F1_5745_5825, + F2_5745_5825, + F3_5745_5825, + F4_5745_5825, + F5_5745_5825, + F6_5745_5825, + F7_5745_5825, + F8_5745_5825, + F9_5745_5825, + + F1_5845_5865, + + W1_4920_4980, + W1_5040_5080, + W1_5170_5230, + W1_5180_5240, + W1_5260_5320, + W1_5745_5825, + W1_5500_5700, + A_DEMO_ALL_CHANNELS +}; + +static const REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { + { 4915, 4925, 20, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, /* F1_4915_4925 */ + { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, /* F2_4915_4925 */ + { 4935, 4945, 20, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, /* F1_4935_4945 */ + { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16 }, /* F2_4935_4945 */ + { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 }, /* F1_4920_4980 */ + { 4920, 4980, 20, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7 }, /* F2_4920_4980 */ + { 4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0 }, /* F1_4942_4987 */ + { 4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0 }, /* F1_4945_4985 */ + { 4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0 }, /* F1_4950_4980 */ + { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F1_5035_5040 */ + { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F2_5035_5040 */ + { 5040, 5040, 20, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F1_5040_5040 */ + { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2 }, /* F1_5040_5080 */ + { 5040, 5080, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 6 }, /* F2_5040_5080 */ + { 5055, 5055, 20, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F1_5055_5055 */ + { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12 }, /* F2_5055_5055 */ + + { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F1_5120_5240 */ + + { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, /* F1_5170_5230 */ + { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1 }, /* F2_5170_5230 */ + + { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 1 }, /* F1_5180_5240 */ + { 5180, 5240, 17, 6, 20, 20, NO_DFS, NO_PSCAN, 1 }, /* F2_5180_5240 */ + { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 1 }, /* F3_5180_5240 */ + { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 1 }, /* F4_5180_5240 */ + { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 1 }, /* F5_5180_5240 */ + { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 1 }, /* F6_5180_5240 */ + { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK3, 0 }, /* F7_5180_5240 */ + { 5180, 5240, 23, 6, 20, 20, NO_DFS, NO_PSCAN, 1 }, /* F8_5180_5240 */ + { 5180, 5240, 20, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0 }, /* F9_5180_5240 */ + { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 1 }, /* F10_5180_5240 */ + + { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5240_5280 */ + + { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 2 }, /* F1_5260_5280 */ + + { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 2 }, /* F1_5260_5320 */ + + { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 , 0 }, + /* F2_5260_5320 */ + + { 5260, 5320, 24, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 2 },/* F3_5260_5320 */ + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, /* F4_5260_5320 */ + { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, /* F5_5260_5320 */ + { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 2 }, /* F6_5260_5320 */ + { 5260, 5320, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 , 0 }, + /* F7_5260_5320 */ + + { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0 }, /* F1_5260_5700 */ + + { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2 }, /* F1_5280_5320 */ + + { 5500, 5580, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 4}, /* F1_5500_5580 */ + { 5500, 5580, 30, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 4}, /* F2_5500_5580 */ + + { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 3 }, /* F1_5500_5620 */ + + { 5500, 5660, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0 }, /* F1_5500_5660 */ + + { 5500, 5720, 24, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4 }, /* F1_5500_5720 */ + { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 3 }, /* F2_5500_5700 */ + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 3 }, /* F3_5500_5700 */ + { 5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0 },/* F4_5500_5700 */ + { 5500, 5700, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0 }, /* F5_5500_5700 */ + { 5500, 5700, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0 },/* F6_5500_5700 */ + + { 5660, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 4}, /* F1_5660_5700 */ + { 5660, 5700, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 4}, /* F2_5660_5700 */ + { 5660, 5700, 30, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 4}, /* F3_5660_5700 */ + + { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 3 }, /* F1_5745_5805 */ + { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3 }, /* F2_5745_5805 */ + { 5745, 5805, 30, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0 }, /* F3_5745_5805 */ + { 5745, 5805, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F4_5745_5805 */ + + { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 5 }, /* F1_5745_5825 */ + { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 5 }, /* F2_5745_5825 */ + { 5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F3_5745_5825 */ + { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F4_5745_5825 */ + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 5 }, /* F5_5745_5825 */ + { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 5 }, /* F6_5745_5825 */ + { 5745, 5825, 30, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0 }, /* F7_5745_5825 */ + { 5745, 5825, 20, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0 }, /* F8_5745_5825 */ + + /* + * Below are the world roaming channels + * All WWR domains have no power limit, instead use the card's CTL + * or max power settings. + */ + { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_4920_4980 */ + { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5040_5080 */ + { 5170, 5230, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5170_5230 */ + { 5180, 5240, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5180_5240 */ + { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, /* W1_5260_5320 */ + { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5745_5825 */ + { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0 }, /* W1_5500_5700 */ + { 4920, 6100, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* A_DEMO_ALL_CHANNELS */ +}; + +/* + * 2GHz 11b channel tags + */ +enum { + F1_2312_2372, + F2_2312_2372, + + F1_2412_2472, + F2_2412_2472, + F3_2412_2472, + F4_2412_2472, + + F1_2412_2462, + F2_2412_2462, + + F1_2432_2442, + + F1_2457_2472, + + F1_2467_2472, + + F1_2484_2484, + F2_2484_2484, + + F1_2512_2732, + + W1_2312_2372, + W1_2412_2412, + W1_2417_2432, + W1_2437_2442, + W1_2447_2457, + W1_2462_2462, + W1_2467_2467, + W2_2467_2467, + W1_2472_2472, + W2_2472_2472, + W1_2484_2484, + W2_2484_2484, +}; + +static const REG_DMN_FREQ_BAND regDmn2GhzFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2312_2372 */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F2_2312_2372 */ + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2412_2472 */ + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 30},/* F2_2412_2472 */ + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 4}, /* F3_2412_2472 */ + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, /* F4_2412_2472 */ + + { 2412, 2462, 30, 6, 20, 5, NO_DFS, NO_PSCAN, 12}, /* F1_2412_2462 */ + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 30}, /* F2_2412_2462 */ + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 4}, /* F1_2432_2442 */ + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2457_2472 */ + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 30}, /* F1_2467_2472 */ + + { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2484_2484 */ + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 31}, /* F2_2484_2484 */ + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* F1_2512_2732 */ + + /* + * WWR have powers opened up to 20dBm. Limits should often come from CTL/Max powers + */ + + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2312_2372 */ + { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2412_2412 */ + { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2417_2432 */ + { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2437_2442 */ + { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2447_2457 */ + { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* W1_2462_2462 */ + { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* W1_2467_2467 */ + { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* W2_2467_2467 */ + { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* W1_2472_2472 */ + { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* W2_2472_2472 */ + { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, /* W1_2484_2484 */ + { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* W2_2484_2484 */ +}; + +/* + * 2GHz 11g channel tags + */ + +enum { + G1_2312_2372, + G2_2312_2372, + + G1_2412_2472, + G2_2412_2472, + G3_2412_2472, + G4_2412_2472, + + G1_2412_2462, + G2_2412_2462, + + G1_2432_2442, + + G1_2457_2472, + + G1_2512_2732, + + G1_2467_2472, + G2_2467_2472, + + G1_2484_2484, + + WG1_2312_2372, + WG1_2412_2462, + WG1_2412_2472, + WG2_2412_2472, + G_DEMO_ALMOST_ALL_CHANNELS, + G_DEMO_ALL_CHANNELS, +}; + +static const REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { + { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2312_2372 */ + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G2_2312_2372 */ + + { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2412_2472 */ + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G | PSCAN_MKKA2 | PSCAN_MKKA | PSCAN_EXT_CHAN, 30}, /* G2_2412_2472 */ + { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 4}, /* G3_2412_2472 */ + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G | PSCAN_MKKA2 | PSCAN_MKKA | PSCAN_EXT_CHAN, 0}, /* G4_2412_2472 */ + + { 2412, 2462, 30, 6, 20, 5, NO_DFS, NO_PSCAN, 12}, /* G1_2412_2462 */ + { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 30}, /* G2_2412_2462 */ + + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 4}, /* G1_2432_2442 */ + + { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2457_2472 */ + + { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2512_2732 */ + + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 30 }, /* G1_2467_2472 */ + { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G | PSCAN_MKKA2, 0 }, /* G2_2467_2472 */ + + { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G1_2484_2484 */ + /* + * WWR open up the power to 20dBm + */ + + { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2312_2372 */ + { 2412, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, /* WG1_2412_2462 */ + { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN | PSCAN_EXT_CHAN, 0}, /* WG1_2412_2472 */ + { 2412, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, /* WG2_2412_2472 */ + { 2312, 2532, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G_DEMO_ALMOST_ALL_CHANNELS */ + { 2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, /* G_DEMO_ALL_CHANNELS */ +}; + +/* regulatory capabilities */ +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 + +static const JAPAN_BANDCHECK j_bandcheck[] = { + {F1_5170_5230, REGDMN_EEPROM_EEREGCAP_EN_KK_U1_ODD}, + {F4_5180_5240, REGDMN_EEPROM_EEREGCAP_EN_KK_U1_EVEN}, + {F2_5260_5320, REGDMN_EEPROM_EEREGCAP_EN_KK_U2}, + {F4_5500_5700, REGDMN_EEPROM_EEREGCAP_EN_KK_MIDBAND} +}; + +static const COMMON_MODE_POWER common_mode_pwrtbl[] = { + { 4900, 5000, 17 }, + { 5000, 5100, 17 }, + { 5150, 5250, 17 }, /* ETSI & MKK */ + { 5250, 5350, 18 }, /* ETSI */ + { 5470, 5725, 20 }, /* ETSI */ + { 5725, 5825, 20 }, /* Singapore */ + { 5825, 5850, 23 } /* Korea */ +}; + +/* + * 5GHz Turbo (dynamic & static) tags + */ + +enum { + T1_5130_5650, + T1_5150_5670, + + T1_5200_5200, + T2_5200_5200, + T3_5200_5200, + T4_5200_5200, + T5_5200_5200, + T6_5200_5200, + T7_5200_5200, + T8_5200_5200, + + T1_5200_5280, + T2_5200_5280, + T3_5200_5280, + T4_5200_5280, + T5_5200_5280, + T6_5200_5280, + + T1_5200_5240, + T1_5210_5210, + T2_5210_5210, + T3_5210_5210, + T4_5210_5210, + T5_5210_5210, + T6_5210_5210, + T7_5210_5210, + T8_5210_5210, + T9_5210_5210, + T10_5210_5210, + T1_5240_5240, + + T1_5210_5250, + T1_5210_5290, + T2_5210_5290, + T3_5210_5290, + + T1_5280_5280, + T2_5280_5280, + T1_5290_5290, + T2_5290_5290, + T3_5290_5290, + T1_5250_5290, + T2_5250_5290, + T3_5250_5290, + T4_5250_5290, + + T1_5540_5660, + T2_5540_5660, + T3_5540_5660, + T1_5760_5800, + T2_5760_5800, + T3_5760_5800, + T4_5760_5800, + T5_5760_5800, + T6_5760_5800, + T7_5760_5800, + + T1_5765_5805, + T2_5765_5805, + T3_5765_5805, + T4_5765_5805, + T5_5765_5805, + T6_5765_5805, + T7_5765_5805, + T8_5765_5805, + T9_5765_5805, + + WT1_5210_5250, + WT1_5290_5290, + WT1_5540_5660, + WT1_5760_5800, +}; + +/* + * 2GHz Dynamic turbo tags + */ +#ifndef ATH_REMOVE_2G_TURBO_RD_TABLE +enum { + T1_2312_2372, + T1_2437_2437, + T2_2437_2437, + T3_2437_2437, + T1_2512_2732 +}; + +static const REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = { + { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_2312_2372 */ + { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_2437_2437 */ + { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T2_2437_2437 */ + { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0}, /* T3_2437_2437 */ + { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0}, /* T1_2512_2732 */ +}; +#endif /* ATH_REMOVE_2G_TURBO_RD_TABLE */ + +static const REG_DOMAIN ahCmnRegDomains[] = { + + {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ, + CHAN_11A_BM(A_DEMO_ALL_CHANNELS, F6_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(T1_5130_5650, T1_5150_5670, F6_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, + -1, -1, -1, -1, -1, -1, -1, -1) + BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, + -1, -1, -1, -1, -1, -1, -1, -1), + BM(G_DEMO_ALMOST_ALL_CHANNELS, + G1_2484_2484, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL3, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ, + BM(F1_5280_5320, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5290_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F5_5180_5240, F9_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5210, T3_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5200, T3_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC , NO_REQ, + BM(F9_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, T5_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL7, FCC, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI , NO_REQ, + BM(F2_5280_5320, F2_5500_5580, F3_5660_5720, F7_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL8, ETSI, NO_DFS, NO_PSCAN, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL9, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + BM(F9_5180_5240, F2_5260_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL10, ETSI, DFS_ETSI, PSCAN_ETSI , DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + BM(F9_5180_5240, F2_5260_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL11, ETSI, DFS_ETSI, PSCAN_ETSI , DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + BM(F9_5180_5240, F2_5260_5320, F5_5500_5700, F7_5745_5825, F1_5845_5865, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {APL12, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + BM(F5_5180_5240, F1_5500_5560, F1_5745_5765, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F2_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5250, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {ETSI8, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, F1_5660_5700, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO + }, + + {ETSI9, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, F1_5500_5660, F8_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO + }, + + {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5210_5210, T2_5250_5290, T6_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5240, T2_5280_5280, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, + BM(F2_5180_5240, F3_5260_5320, F1_5500_5720, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5200_5200, T8_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + /* + + Bug Fix: EV 98583 Public Safety channel + Exclude the following channel in FCC Public safety domain + Uni-1: 5180, 5200, 5220, 5240 + Uni-2: 5260, 5280, 5300, 5320 + Uni-3: 5745, 5765, 5785, 5805, 5825 + */ + {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, + BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T8_5210_5210, T4_5250_5290, T7_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5240, T1_5280_5280, T9_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T8_5200_5200, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ, + BM(F8_5180_5240, F5_5260_5320, F1_5500_5580, F2_5660_5720, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1), + BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {MKK1, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_5170_5230, F10_5180_5240, F7_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + {MKK2, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F2_4915_4925, F2_4935_4945, F1_4920_4980, F1_5035_5040, F2_5055_5055, F1_5040_5080, F1_5170_5230, F10_5180_5240, -1, -1, -1, -1), + BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 even */ + {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 even + UNI-2 */ + {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T10_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 even + UNI-2 + mid-band */ + {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 odd + even */ + {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 */ + {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F4_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 even + 4.9 GHZ */ + {MKK9, MKK, NO_DFS, PSCAN_MKK2 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4912_4947, F1_5032_5057, F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5035_5045, F1_5055_5055, F2_5040_5080, F4_5180_5240, -1, -1, -1), + BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 even + UNI-2 + 4.9 GHZ */ + {MKK10, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4912_4947, F1_5032_5057, F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5035_5045, F1_5055_5055, F2_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz */ + {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4912_4947, F1_5032_5057, F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5035_5045, F1_5055_5055, F2_5040_5080, F4_5180_5240, F2_5260_5320, F6_5500_5700, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz */ + {MKK12, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5040_5040, F1_5055_5055, F2_5040_5080, F2_5170_5230, F4_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {MKK13, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F7_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 odd + UNI-1 even + 4.9GHz */ + {MKK14, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, + BM(F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5040_5040, F2_5040_5080, F1_5055_5055, F2_5170_5230, F4_5180_5240, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /* UNI-1 odd + UNI-1 even + UNI-2 + 4.9GHz */ + {MKK15, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5040_5040, F2_5040_5080, F1_5055_5055, F2_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + + /*=== 2 GHz ===*/ + + /* Defined here to use when 2G channels are authorised for country K2 */ + {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F2_2312_2372, F4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G2_2312_2372,G4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BMZERO + }, + + {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {MKKA, MKK, NO_DFS, PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G | PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, + -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, + -1, -1, -1, -1, -1, -1, -1), + BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472, W1_2417_2432, + W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1), + BM(WG2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, + -1, -1, -1, -1, -1, -1, -1), + BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, + -1, -1, -1, -1, -1, -1, -1), + BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WORB_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {WORC_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + }, + + {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, +}; + +static const struct cmode modes[] = { + { REGDMN_MODE_TURBO, IEEE80211_CHAN_ST}, /* TURBO means 11a Static Turbo */ + { REGDMN_MODE_11A, IEEE80211_CHAN_A}, + { REGDMN_MODE_11B, IEEE80211_CHAN_B}, + { REGDMN_MODE_11G, IEEE80211_CHAN_PUREG}, + { REGDMN_MODE_11G_TURBO, IEEE80211_CHAN_108G}, + { REGDMN_MODE_11A_TURBO, IEEE80211_CHAN_108A}, + { REGDMN_MODE_11NG_HT20, IEEE80211_CHAN_11NG_HT20}, + { REGDMN_MODE_11NG_HT40PLUS, IEEE80211_CHAN_11NG_HT40PLUS}, + { REGDMN_MODE_11NG_HT40MINUS, IEEE80211_CHAN_11NG_HT40MINUS}, + { REGDMN_MODE_11NA_HT20, IEEE80211_CHAN_11NA_HT20}, + { REGDMN_MODE_11NA_HT40PLUS, IEEE80211_CHAN_11NA_HT40PLUS}, + { REGDMN_MODE_11NA_HT40MINUS, IEEE80211_CHAN_11NA_HT40MINUS}, + { REGDMN_MODE_11AC_VHT20, IEEE80211_CHAN_11AC_VHT20}, + { REGDMN_MODE_11AC_VHT40PLUS, IEEE80211_CHAN_11AC_VHT40PLUS}, + { REGDMN_MODE_11AC_VHT40MINUS, IEEE80211_CHAN_11AC_VHT40MINUS}, + { REGDMN_MODE_11AC_VHT80, IEEE80211_CHAN_11AC_VHT80}, + { REGDMN_MODE_11AC_VHT20_2G, IEEE80211_CHAN_11AC_VHT20_2G}, + { REGDMN_MODE_11AC_VHT40_2G, IEEE80211_CHAN_11AC_VHT40_2G}, + { REGDMN_MODE_11AC_VHT80_2G, IEEE80211_CHAN_11AC_VHT80_2G}, +}; + +typedef enum offset +{ + BW20 = 0, + BW40_LOW_PRIMARY = 1, + BW40_HIGH_PRIMARY = 3, + BW80, + BWALL +} offset_t; + +typedef struct _regdm_op_class_map +{ + u_int8_t op_class; + u_int8_t ch_spacing; + offset_t offset; + u_int8_t channels[MAX_CHANNELS_PER_OPERATING_CLASS]; +} regdm_op_class_map_t; + +typedef struct _regdm_supp_op_classes { + u_int8_t num_classes; + u_int8_t classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} regdm_supp_op_classes; + +u_int16_t regdm_get_opclass_from_channel(u_int8_t *country, u_int8_t channel, + u_int8_t offset); +u_int16_t regdm_set_curr_opclasses(u_int8_t num_classes, u_int8_t *class); +u_int16_t regdm_get_curr_opclasses(u_int8_t *num_classes, u_int8_t *class); + diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_nv.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_nv.c new file mode 100644 index 000000000000..14342c18cafb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_nv.c @@ -0,0 +1,5409 @@ +/* + * Copyright (c) "2012,2014" The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file wlan_nv.c + + \brief Contains collection of table default values to use in + case a table is not found in NV + + $Id$ + + ========================================================================== */ + +#ifndef WLAN_NV_C +#define WLAN_NV_C + +#include "palTypes.h" +#include "wlan_nv.h" + +const sHalNv nvDefaults = +{ + { + 0, // tANI_U16 productId; + 1, // tANI_U8 productBands; + 2, // tANI_U8 wlanNvRevId; //0: WCN1312, 1: WCN1314, 2: WCN3660 + 1, // tANI_U8 numOfTxChains; + 1, // tANI_U8 numOfRxChains; + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // tANI_U8 macAddr[NV_FIELD_MAC_ADDR_SIZE]; + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // tANI_U8 macAddr[NV_FIELD_MAC_ADDR_SIZE]; + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // tANI_U8 macAddr[NV_FIELD_MAC_ADDR_SIZE]; + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // tANI_U8 macAddr[NV_FIELD_MAC_ADDR_SIZE]; + { "\0" }, + 0, // tANI_U8 couplerType; + WLAN_NV_VERSION, // tANI_U8 nvVersion; + }, //fields + + { + // NV_TABLE_RATE_POWER_SETTINGS + { + // typedef tANI_S16 tPowerdBm; + //typedef tPowerdBm tRateGroupPwr[NUM_HAL_PHY_RATES]; + //tRateGroupPwr pwrOptimum[NUM_RF_SUBBANDS]; + //2.4G + { + //802.11b Rates + {1900}, // HAL_PHY_RATE_11B_LONG_1_MBPS, + {1900}, // HAL_PHY_RATE_11B_LONG_2_MBPS, + {1900}, // HAL_PHY_RATE_11B_LONG_5_5_MBPS, + {1900}, // HAL_PHY_RATE_11B_LONG_11_MBPS, + {1900}, // HAL_PHY_RATE_11B_SHORT_2_MBPS, + {1900}, // HAL_PHY_RATE_11B_SHORT_5_5_MBPS, + {1900}, // HAL_PHY_RATE_11B_SHORT_11_MBPS, + + //11A 20MHz Rates + {1700}, // HAL_PHY_RATE_11A_6_MBPS, + {1700}, // HAL_PHY_RATE_11A_9_MBPS, + {1700}, // HAL_PHY_RATE_11A_12_MBPS, + {1650}, // HAL_PHY_RATE_11A_18_MBPS, + {1600}, // HAL_PHY_RATE_11A_24_MBPS, + {1550}, // HAL_PHY_RATE_11A_36_MBPS, + {1550}, // HAL_PHY_RATE_11A_48_MBPS, + {1550}, // HAL_PHY_RATE_11A_54_MBPS, + + //DUP 11A 40MHz Rates + {1700}, // HAL_PHY_RATE_11A_DUP_6_MBPS, + {1700}, // HAL_PHY_RATE_11A_DUP_9_MBPS, + {1700}, // HAL_PHY_RATE_11A_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11A_DUP_18_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_24_MBPS, + {1550}, // HAL_PHY_RATE_11A_DUP_36_MBPS, + {1550}, // HAL_PHY_RATE_11A_DUP_48_MBPS, + {1500}, // HAL_PHY_RATE_11A_DUP_54_MBPS, + + //MCS Index #0-7(20/40MHz) + {1700}, // HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, + {1700}, // HAL_PHY_RATE_MCS_1NSS_13_MBPS, + {1650}, // HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_26_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_39_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_52_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_65_MBPS, + {1700}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, + {1700}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS, + {1650}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, + + //MCS Index #8-15(20/40MHz) + {1700}, // HAL_PHY_RATE_MCS_1NSS_CB_13_5_MBPS, + {1700}, // HAL_PHY_RATE_MCS_1NSS_CB_27_MBPS, + {1650}, // HAL_PHY_RATE_MCS_1NSS_CB_40_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_54_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_CB_81_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_CB_108_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_CB_121_5_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_CB_135_MBPS, + {1700}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_15_MBPS, + {1700}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_30_MBPS, + {1650}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_45_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_60_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_90_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_120_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_135_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_150_MBPS, + +#ifdef WLAN_FEATURE_11AC + //11AC rates + //11A duplicate 80MHz Rates + {1700}, // HAL_PHY_RATE_11AC_DUP_6_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_9_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11AC_DUP_18_MBPS, + {1600}, // HAL_PHY_RATE_11AC_DUP_24_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_36_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_48_MBPS, + {1500}, // HAL_PHY_RATE_11AC_DUP_54_MBPS, + + //11ac 20MHZ NG, SG + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_6_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_13_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_19_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_26_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_39_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_52_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_65_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_78_MBPS, +#ifdef WCN_PRONTO + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_86_5_MBPS, +#endif + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_7_2_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_14_4_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_21_6_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_28_8_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_43_3_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_57_7_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_72_2_MBPS, + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_86_6_MBPS, +#ifdef WCN_PRONTO + {0000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_96_1_MBPS, +#endif + + //11ac 40MHZ NG, SG + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_13_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_27_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_40_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_54_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_81_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_108_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_121_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_135_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_162_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_180_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_15_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_30_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_45_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_60_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_90_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_120_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_135_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_150_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_180_MBPS, + {0000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_200_MBPS, + + //11ac 80MHZ NG, SG + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_29_3_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_87_8_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_117_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_175_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_234_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_263_3_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_292_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_351_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_390_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_32_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_97_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_130_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_195_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_260_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_292_5_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_325_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_390_MBPS, + {0000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_433_3_MBPS, +#endif + }, // RF_SUBBAND_2_4_GHZ + // 5G Low + { + //802.11b Rates + {0}, // HAL_PHY_RATE_11B_LONG_1_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_2_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_11_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_2_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_11_MBPS, + + ///11A 20MHz Rates + {1600}, // HAL_PHY_RATE_11A_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_12_MBPS, + {1550}, // HAL_PHY_RATE_11A_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_54_MBPS, + + ///DUP 11A 40MHz Rates + {1600}, // HAL_PHY_RATE_11A_DUP_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11A_DUP_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_DUP_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_DUP_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_54_MBPS, + + ///MCS Index #0-7(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_13_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_26_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_39_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_52_MBPS, + {1350}, // HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_65_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, + + ///MCS Index #8-15(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_13_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_27_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_CB_40_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_CB_54_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_CB_81_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_CB_108_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_CB_121_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_CB_135_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_15_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_30_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_45_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_60_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_90_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_120_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_135_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_150_MBPS, + +#ifdef WLAN_FEATUURE_11AC + ///11AC rates + ///11A duplicate 80MHz Rates + {1700}, // HAL_PHY_RATE_11AC_DUP_6_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_9_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11AC_DUP_18_MBPS, + {1600}, // HAL_PHY_RATE_11AC_DUP_24_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_36_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_48_MBPS, + {1500}, // HAL_PHY_RATE_11AC_DUP_54_MBPS, + + ///11ac 20MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_6_5_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_13_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_19_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_26_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_39_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_52_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_65_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_78_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_86_5_MBPS, +#endif + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_7_2_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_14_4_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_21_6_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_28_8_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_43_3_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_57_7_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_72_2_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_86_6_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_96_1_MBPS, +#endif + //11ac 40MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_13_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_27_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_40_5_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_54_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_81_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_108_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_121_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_135_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_162_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_180_MBPS, + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_15_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_30_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_45_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_60_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_90_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_120_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_135_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_150_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_180_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_200_MBPS, + + + //11ac 80MHZ NG, SG + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_29_3_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_87_8_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_117_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_175_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_234_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_263_3_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_292_5_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_351_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_390_MBPS, + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_32_5_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_97_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_130_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_195_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_260_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_292_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_325_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_390_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_433_3_MBPS, +#endif + }, // RF_SUBBAND_5_LOW_GHZ + // 5G Mid + { + //802.11b Rates + {0}, // HAL_PHY_RATE_11B_LONG_1_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_2_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_11_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_2_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_11_MBPS, + + ///11A 20MHz Rates + {1600}, // HAL_PHY_RATE_11A_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_12_MBPS, + {1550}, // HAL_PHY_RATE_11A_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_54_MBPS, + + ///DU P 11A 40MHz Rates + {1600}, // HAL_PHY_RATE_11A_DUP_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11A_DUP_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_DUP_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_DUP_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_54_MBPS, + + ///MCSS Index #0-7(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_13_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_26_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_39_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_52_MBPS, + {1350}, // HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_65_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, + + ///MCSS Index #8-15(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_13_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_27_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_CB_40_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_CB_54_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_CB_81_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_CB_108_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_CB_121_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_CB_135_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_15_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_30_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_45_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_60_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_90_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_120_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_135_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_150_MBPS, + +#ifdef WLAN_FEATUURE_111AC + ///11CAC rates + ///11Ad duplicate 80MHz Rates + {1700}, // HAL_PHY_RATE_11AC_DUP_6_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_9_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11AC_DUP_18_MBPS, + {1600}, // HAL_PHY_RATE_11AC_DUP_24_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_36_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_48_MBPS, + {1500}, // HAL_PHY_RATE_11AC_DUP_54_MBPS, + + ///11a c 20MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_6_5_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_13_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_19_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_26_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_39_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_52_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_65_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_78_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_86_5_MBPS, +#endif + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_7_2_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_14_4_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_21_6_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_28_8_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_43_3_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_57_7_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_72_2_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_86_6_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_96_1_MBPS, +#endif + //11ac 40MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_13_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_27_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_40_5_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_54_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_81_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_108_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_121_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_135_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_162_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_180_MBPS, + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_15_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_30_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_45_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_60_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_90_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_120_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_135_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_150_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_180_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_200_MBPS, + + + ///11a c 80MHZ NG, SG + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_29_3_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_87_8_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_117_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_175_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_234_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_263_3_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_292_5_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_351_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_390_MBPS, + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_32_5_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_97_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_130_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_195_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_260_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_292_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_325_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_390_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_433_3_MBPS, +#endif + }, // // RF_SUBBAND_5_MID_GHZ + // 5G High + { + //802.11b Rates + {0}, // HAL_PHY_RATE_11B_LONG_1_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_2_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_11_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_2_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_11_MBPS, + + ///11A 20MHz Rates + {1600}, // HAL_PHY_RATE_11A_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_12_MBPS, + {1550}, // HAL_PHY_RATE_11A_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_54_MBPS, + + ///DU P 11A 40MHz Rates + {1600}, // HAL_PHY_RATE_11A_DUP_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11A_DUP_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_DUP_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_DUP_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_54_MBPS, + + ///MCSS Index #0-7(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_13_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_26_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_39_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_52_MBPS, + {1350}, // HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_65_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, + + ///MCSS Index #8-15(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_13_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_27_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_CB_40_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_CB_54_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_CB_81_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_CB_108_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_CB_121_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_CB_135_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_15_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_30_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_45_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_60_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_90_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_120_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_135_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_150_MBPS, + +#ifdef WLAN_FEATUURE_11AC + ///11CAC rates + ///11Ad duplicate 80MHz Rates + {1700}, // HAL_PHY_RATE_11AC_DUP_6_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_9_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11AC_DUP_18_MBPS, + {1600}, // HAL_PHY_RATE_11AC_DUP_24_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_36_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_48_MBPS, + {1500}, // HAL_PHY_RATE_11AC_DUP_54_MBPS, + + ///11a c 20MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_6_5_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_13_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_19_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_26_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_39_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_52_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_65_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_78_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_86_5_MBPS, +#endif + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_7_2_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_14_4_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_21_6_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_28_8_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_43_3_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_57_7_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_72_2_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_86_6_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_96_1_MBPS, +#endif + //11ac 40MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_13_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_27_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_40_5_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_54_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_81_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_108_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_121_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_135_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_162_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_180_MBPS, + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_15_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_30_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_45_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_60_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_90_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_120_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_135_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_150_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_180_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_200_MBPS, + + + ///11a c 80MHZ NG, SG + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_29_3_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_87_8_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_117_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_175_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_234_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_263_3_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_292_5_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_351_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_390_MBPS, + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_32_5_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_97_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_130_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_195_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_260_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_292_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_325_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_390_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_433_3_MBPS, +#endif + }, // RF_SUBBAND_5_HIGH_GHZ, + // 4.9G + + { + //802.11b Rates + {0}, // HAL_PHY_RATE_11B_LONG_1_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_2_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_LONG_11_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_2_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_5_5_MBPS, + {0}, // HAL_PHY_RATE_11B_SHORT_11_MBPS, + + ///11A 20MHz Rates + {1600}, // HAL_PHY_RATE_11A_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_12_MBPS, + {1550}, // HAL_PHY_RATE_11A_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_54_MBPS, + + ///DU P 11A 40MHz Rates + {1600}, // HAL_PHY_RATE_11A_DUP_6_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_9_MBPS, + {1600}, // HAL_PHY_RATE_11A_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11A_DUP_18_MBPS, + {1550}, // HAL_PHY_RATE_11A_DUP_24_MBPS, + {1450}, // HAL_PHY_RATE_11A_DUP_36_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_48_MBPS, + {1400}, // HAL_PHY_RATE_11A_DUP_54_MBPS, + + ///MCSS Index #0-7(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_13_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_26_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_39_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_52_MBPS, + {1350}, // HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_65_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, + + ///MCSS Index #8-15(20/40MHz) + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_13_5_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_CB_27_MBPS, + {1550}, // HAL_PHY_RATE_MCS_1NSS_CB_40_5_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_CB_54_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_CB_81_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_CB_108_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_CB_121_5_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_CB_135_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_15_MBPS, + {1600}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_30_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_45_MBPS, + {1500}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_60_MBPS, + {1450}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_90_MBPS, + {1400}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_120_MBPS, + {1300}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_135_MBPS, + {1200}, // HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_150_MBPS, + +#ifdef WLAN_FEATUURE_11AC + ///11CAC rates + ///11Ad duplicate 80MHz Rates + {1700}, // HAL_PHY_RATE_11AC_DUP_6_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_9_MBPS, + {1700}, // HAL_PHY_RATE_11AC_DUP_12_MBPS, + {1650}, // HAL_PHY_RATE_11AC_DUP_18_MBPS, + {1600}, // HAL_PHY_RATE_11AC_DUP_24_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_36_MBPS, + {1550}, // HAL_PHY_RATE_11AC_DUP_48_MBPS, + {1500,, // HAL_PHY_RATE_11AC_DUP_54_MBPS, + + ///11a c 20MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_6_5_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_13_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_19_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_26_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_39_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_52_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_65_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_NGI_78_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_86_5_MBPS, +#endif + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_7_2_MBPS, + {1400}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_14_4_MBPS, + {1350}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_21_6_MBPS, + {1300}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_28_8_MBPS, + {1250}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_43_3_MBPS, + {1200}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_57_7_MBPS, + {1100}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_72_2_MBPS, + { 900}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_CB_SGI_86_6_MBPS, +#ifdef WCN_PRONTO + { 800}, // HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_96_1_MBPS, +#endif + //11ac 40MHZ NG, SG + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_13_5_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_27_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_40_5_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_54_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_81_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_108_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_121_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_135_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_162_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_180_MBPS, + {1400}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_15_MBPS, + {1300}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_30_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_45_MBPS, + {1250}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_60_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_90_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_120_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_135_MBPS, + {1000}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_150_MBPS, + { 900}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_180_MBPS, + { 800}, // HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_200_MBPS, + + + ///11a c 80MHZ NG, SG + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_29_3_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_87_8_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_117_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_175_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_234_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_263_3_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_292_5_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_351_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_390_MBPS, + {1300}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_32_5_MBPS, + {1100}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_65_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_97_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_130_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_195_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_260_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_292_5_MBPS, + {1000}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_325_MBPS, + { 900}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_390_MBPS, + { 800}, // HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_433_3_MBPS, +#endif + }, // RF_SUBBAND_4_9_GHZ + }, + + // NV_TABLE_REGULATORY_DOMAINS + { + // typedef struct + // { + // tANI_BOOLEAN enabled; + // tPowerdBm pwrLimit; + // }sRegulatoryChannel; + + // typedef struct + // { + // sRegulatoryChannel channels[NUM_RF_CHANNELS]; + // uAbsPwrPrecision antennaGain[NUM_RF_SUBBANDS]; + // uAbsPwrPrecision bRatePowerOffset[NUM_2_4GHZ_CHANNELS]; + // }sRegulatoryDomains; + + //sRegulatoryDomains regDomains[NUM_REG_DOMAINS]; + + + { // REG_DOMAIN_FCC start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_11, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_12, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_52, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_56, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_60, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DFS, 22}, //RF_CHAN_100, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_104, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_108, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_112, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_116, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_120, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_124, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_128, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_132, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_136, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_165, + + // 802.11p + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_170, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_171, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_172, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_173, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_174, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_175, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_176, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_177, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_178, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_179, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_180, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_181, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_182, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_183, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_184, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_FCC end + + { // REG_DOMAIN_ETSI start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 19}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 19}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_48, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_52, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_56, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_60, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_100, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_104, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_108, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_112, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_116, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_120, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_124, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_128, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_132, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_136, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_149, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_153, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_157, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_161, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_165, + + // 802.11p + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_170, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_171, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_172, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_173, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_174, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_175, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_176, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_177, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_178, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_179, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_180, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_181, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_182, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_183, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_184, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 23}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_ETSI end + + { // REG_DOMAIN_JAPAN start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_13, + {NV_CHANNEL_ENABLE, 18}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_52, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_56, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_60, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DFS, 22}, //RF_CHAN_100, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_104, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_108, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_112, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_116, + {NV_CHANNEL_DFS, 0}, //RF_CHAN_120, + {NV_CHANNEL_DFS, 0}, //RF_CHAN_124, + {NV_CHANNEL_DFS, 0}, //RF_CHAN_128, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_132, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_136, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_165, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_JAPAN end + + { // REG_DOMAIN_WORLD start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_52, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_56, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_60, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DFS, 22}, //RF_CHAN_100, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_104, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_108, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_112, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_116, + {NV_CHANNEL_DFS, 0}, //RF_CHAN_120, + {NV_CHANNEL_DFS, 0}, //RF_CHAN_124, + {NV_CHANNEL_DFS, 0}, //RF_CHAN_128, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_132, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_136, + {NV_CHANNEL_DFS, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_165, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_WORLD end + + { // REG_DOMAIN_N_AMER_EXC_FCC start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_11, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_12, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_52, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_56, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_60, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DISABLE, 22}, //RF_CHAN_100, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_104, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_108, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_112, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_116, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_120, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_124, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_128, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_132, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_136, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_165, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_N_AMER_EXC_FCC end + + { // REG_DOMAIN_APAC start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 26}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 16}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_52, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_56, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_60, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DISABLE, 22}, //RF_CHAN_100, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_104, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_108, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_112, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_116, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_120, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_124, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_128, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_132, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_136, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_165, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_APAC end + + { // REG_DOMAIN_KOREA start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 15}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_52, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_56, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_60, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DISABLE, 22}, //RF_CHAN_100, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_104, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_108, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_112, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_116, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_120, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_124, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_128, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_132, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_136, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_165, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_KOREA end + + { // REG_DOMAIN_HI_5GHZ start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band, none CB + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 14}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_14, + + //4.9GHz Band, none CB + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_240, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_244, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_248, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_252, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_208, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_212, + {NV_CHANNEL_DISABLE, 23}, //RF_CHAN_216, + + //5GHz Low & Mid U-NII Band, none CB + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_36, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_40, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_44, + {NV_CHANNEL_ENABLE, 17}, //RF_CHAN_48, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_52, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_56, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_60, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_64, + + //5GHz Mid Band - ETSI, none CB + {NV_CHANNEL_DISABLE, 22}, //RF_CHAN_100, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_104, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_108, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_112, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_116, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_120, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_124, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_128, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_132, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_136, + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_140, + + //5GHz High U-NII Band, none CB + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_149, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_153, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_157, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_161, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_165, + + //2.4GHz Band, channel bonded channels + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_3, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_4, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_5, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_6, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_7, + {NV_CHANNEL_ENABLE, 30}, //RF_CHAN_BOND_8, + {NV_CHANNEL_ENABLE, 22}, //RF_CHAN_BOND_9, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_10, + {NV_CHANNEL_ENABLE, 0}, //RF_CHAN_BOND_11, + + // 4.9GHz Band, channel bonded channels + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_242, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_246, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_250, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_210, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_214, + + //5GHz Low & Mid U-NII Band, channel bonded channels + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_38, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_42, + {NV_CHANNEL_ENABLE, 20}, //RF_CHAN_BOND_46, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_50, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_54, + {NV_CHANNEL_ENABLE, 27}, //RF_CHAN_BOND_58, + {NV_CHANNEL_ENABLE, 25}, //RF_CHAN_BOND_62, + + //5GHz Mid Band - ETSI, channel bonded channels + {NV_CHANNEL_DISABLE, 24}, //RF_CHAN_BOND_102 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_106 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_110 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_114 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_118 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_122 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_126 + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_130 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_134 + {NV_CHANNEL_DISABLE, 27}, //RF_CHAN_BOND_138 + + //5GHz High U-NII Band, channel bonded channels + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_151, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_155, + {NV_CHANNEL_DISABLE, 30}, //RF_CHAN_BOND_159, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_BOND_163 + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + }, // REG_DOMAIN_HI_5GHZ end + + { // REG_DOMAIN_NO_5GHZ start + { //sRegulatoryChannel start + //enabled, pwrLimit + //2.4GHz Band + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_1, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_2, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_3, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_4, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_5, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_6, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_7, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_8, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_9, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_10, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_11, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_12, + {NV_CHANNEL_ENABLE, 12}, //RF_CHAN_13, + {NV_CHANNEL_DISABLE, 0}, //RF_CHAN_14, + }, //sRegulatoryChannel end + + { + { 0 }, // RF_SUBBAND_2_4_GHZ + {0}, // RF_SUBBAND_5_LOW_GHZ + {0}, // RF_SUBBAND_5_MID_GHZ + {0}, // RF_SUBBAND_5_HIGH_GHZ + {0} // RF_SUBBAND_4_9_GHZ + }, + + { // bRatePowerOffset start + //2.4GHz Band + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + }, // bRatePowerOffset end + + { // gnRatePowerOffset start + //apply to all 2.4 and 5G channels + { 0 }, //RF_CHAN_1, + { 0 }, //RF_CHAN_2, + { 0 }, //RF_CHAN_3, + { 0 }, //RF_CHAN_4, + { 0 }, //RF_CHAN_5, + { 0 }, //RF_CHAN_6, + { 0 }, //RF_CHAN_7, + { 0 }, //RF_CHAN_8, + { 0 }, //RF_CHAN_9, + { 0 }, //RF_CHAN_10, + { 0 }, //RF_CHAN_11, + { 0 }, //RF_CHAN_12, + { 0 }, //RF_CHAN_13, + { 0 }, //RF_CHAN_14, + } // gnRatePowerOffset end + } // REG_DOMAIN_NO_5GHZ end + }, + + // NV_TABLE_DEFAULT_COUNTRY + { + // typedef struct + // { + // tANI_U8 regDomain; //from eRegDomainId + // tANI_U8 countryCode[NV_FIELD_COUNTRY_CODE_SIZE]; // string identifier + // }sDefaultCountry; + + 0, // regDomain + { 'U', 'S', 'I' } // countryCode + }, + + //NV_TABLE_TPC_POWER_TABLE + { + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 53 , //7 + 55 , //8 + 56 , //9 + 58 , //10 + 59 , //11 + 60 , //12 + 62 , //13 + 63 , //14 + 64 , //15 + 65 , //16 + 67 , //17 + 68 , //18 + 69 , //19 + 70 , //20 + 71 , //21 + 72 , //22 + 73 , //23 + 74 , //24 + 75 , //25 + 75 , //26 + 76 , //27 + 77 , //28 + 78 , //29 + 78 , //30 + 79 , //31 + 80 , //32 + 81 , //33 + 82 , //34 + 82 , //35 + 83 , //36 + 83 , //37 + 84 , //38 + 85 , //39 + 86 , //40 + 86 , //41 + 87 , //42 + 88 , //43 + 89 , //44 + 89 , //45 + 90 , //46 + 91 , //47 + 91 , //48 + 92 , //49 + 92 , //50 + 93 , //51 + 93 , //52 + 94 , //53 + 94 , //54 + 95 , //55 + 95 , //56 + 95 , //57 + 96 , //58 + 96 , //59 + 97 , //60 + 97 , //61 + 98 , //62 + 98 , //63 + 98 , //64 + 99 , //65 + 99 , //66 + 99 , //67 + 100, //68 + 100, //69 + 100, //70 + 101, //71 + 101, //72 + 102, //73 + 102, //74 + 102, //75 + 102, //76 + 103, //77 + 103, //78 + 103, //79 + 103, //80 + 104, //81 + 104, //82 + 104, //83 + 104, //84 + 105, //85 + 105, //86 + 105, //87 + 105, //88 + 105, //89 + 106, //90 + 106, //91 + 106, //92 + 106, //93 + 106, //94 + 106, //95 + 106, //96 + 106, //97 + 106, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 106, //103 + 106, //104 + 106, //105 + 107, //106 + 107, //107 + 107, //108 + 107, //109 + 107, //110 + 107, //111 + 107, //112 + 107, //113 + 107, //114 + 107, //115 + 107, //116 + 107, //117 + 107, //118 + 107, //119 + 107, //120 + 107, //121 + 107, //122 + 107, //123 + 107, //124 + 107, //125 + 107, //126 + 107, //127 + 107, + } + }, //RF_CHAN_1 + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 52 , //7 + 54 , //8 + 56 , //9 + 57 , //10 + 59 , //11 + 60 , //12 + 61 , //13 + 62 , //14 + 64 , //15 + 65 , //16 + 66 , //17 + 67 , //18 + 68 , //19 + 69 , //20 + 70 , //21 + 71 , //22 + 72 , //23 + 73 , //24 + 74 , //25 + 75 , //26 + 75 , //27 + 76 , //28 + 77 , //29 + 78 , //30 + 79 , //31 + 79 , //32 + 80 , //33 + 81 , //34 + 82 , //35 + 82 , //36 + 83 , //37 + 84 , //38 + 85 , //39 + 85 , //40 + 86 , //41 + 87 , //42 + 88 , //43 + 88 , //44 + 89 , //45 + 89 , //46 + 90 , //47 + 91 , //48 + 91 , //49 + 92 , //50 + 92 , //51 + 93 , //52 + 93 , //53 + 94 , //54 + 94 , //55 + 95 , //56 + 95 , //57 + 96 , //58 + 96 , //59 + 96 , //60 + 97 , //61 + 97 , //62 + 98 , //63 + 98 , //64 + 98 , //65 + 99 , //66 + 99 , //67 + 99 , //68 + 100, //69 + 100, //70 + 101, //71 + 101, //72 + 101, //73 + 101, //74 + 102, //75 + 102, //76 + 102, //77 + 103, //78 + 103, //79 + 103, //80 + 104, //81 + 104, //82 + 104, //83 + 104, //84 + 105, //85 + 105, //86 + 105, //87 + 105, //88 + 105, //89 + 106, //90 + 106, //91 + 106, //92 + 106, //93 + 106, //94 + 106, //95 + 106, //96 + 106, //97 + 106, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 107, //103 + 107, //104 + 107, //105 + 107, //106 + 107, //107 + 107, //108 + 107, //109 + 107, //110 + 107, //111 + 107, //112 + 107, //113 + 107, //114 + 107, //115 + 107, //116 + 107, //117 + 107, //118 + 107, //119 + 107, //120 + 107, //121 + 107, //122 + 107, //123 + 107, //124 + 107, //125 + 107, //126 + 107, //127 + 107, + } + }, //RF_CHAN_2 + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 52 , //7 + 54 , //8 + 55 , //9 + 57 , //10 + 58 , //11 + 60 , //12 + 61 , //13 + 62 , //14 + 64 , //15 + 65 , //16 + 66 , //17 + 67 , //18 + 68 , //19 + 69 , //20 + 70 , //21 + 71 , //22 + 72 , //23 + 73 , //24 + 74 , //25 + 75 , //26 + 75 , //27 + 76 , //28 + 77 , //29 + 78 , //30 + 78 , //31 + 79 , //32 + 80 , //33 + 81 , //34 + 82 , //35 + 82 , //36 + 83 , //37 + 84 , //38 + 84 , //39 + 85 , //40 + 86 , //41 + 87 , //42 + 87 , //43 + 88 , //44 + 89 , //45 + 89 , //46 + 90 , //47 + 90 , //48 + 91 , //49 + 91 , //50 + 92 , //51 + 93 , //52 + 93 , //53 + 94 , //54 + 94 , //55 + 94 , //56 + 95 , //57 + 95 , //58 + 96 , //59 + 96 , //60 + 97 , //61 + 97 , //62 + 97 , //63 + 98 , //64 + 98 , //65 + 99 , //66 + 99 , //67 + 99 , //68 + 100, //69 + 100, //70 + 100, //71 + 101, //72 + 101, //73 + 101, //74 + 102, //75 + 102, //76 + 102, //77 + 103, //78 + 103, //79 + 103, //80 + 103, //81 + 104, //82 + 104, //83 + 104, //84 + 104, //85 + 104, //86 + 105, //87 + 105, //88 + 105, //89 + 105, //90 + 105, //91 + 105, //92 + 105, //93 + 105, //94 + 105, //95 + 105, //96 + 105, //97 + 105, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 106, //103 + 106, //104 + 106, //105 + 106, //106 + 106, //107 + 106, //108 + 106, //109 + 106, //110 + 106, //111 + 106, //112 + 106, //113 + 106, //114 + 106, //115 + 106, //116 + 106, //117 + 106, //118 + 106, //119 + 106, //120 + 106, //121 + 106, //122 + 106, //123 + 106, //124 + 106, //125 + 106, //126 + 106, //127 + 107, + } + }, //RF_CHAN_3 + { + { + 0 , //0 + 42 , //1 + 44 , //2 + 46 , //3 + 48 , //4 + 49 , //5 + 51 , //6 + 53 , //7 + 55 , //8 + 57 , //9 + 58 , //10 + 60 , //11 + 61 , //12 + 62 , //13 + 63 , //14 + 64 , //15 + 66 , //16 + 67 , //17 + 68 , //18 + 69 , //19 + 70 , //20 + 71 , //21 + 72 , //22 + 73 , //23 + 74 , //24 + 75 , //25 + 75 , //26 + 76 , //27 + 77 , //28 + 78 , //29 + 78 , //30 + 79 , //31 + 80 , //32 + 81 , //33 + 82 , //34 + 82 , //35 + 83 , //36 + 84 , //37 + 84 , //38 + 85 , //39 + 86 , //40 + 87 , //41 + 87 , //42 + 88 , //43 + 88 , //44 + 89 , //45 + 90 , //46 + 90 , //47 + 91 , //48 + 91 , //49 + 92 , //50 + 92 , //51 + 93 , //52 + 93 , //53 + 94 , //54 + 94 , //55 + 95 , //56 + 95 , //57 + 95 , //58 + 96 , //59 + 96 , //60 + 97 , //61 + 97 , //62 + 98 , //63 + 98 , //64 + 98 , //65 + 99 , //66 + 99 , //67 + 99 , //68 + 100, //69 + 100, //70 + 100, //71 + 101, //72 + 101, //73 + 101, //74 + 102, //75 + 102, //76 + 102, //77 + 103, //78 + 103, //79 + 103, //80 + 103, //81 + 104, //82 + 104, //83 + 104, //84 + 104, //85 + 104, //86 + 104, //87 + 104, //88 + 104, //89 + 105, //90 + 105, //91 + 105, //92 + 105, //93 + 105, //94 + 105, //95 + 105, //96 + 105, //97 + 105, //98 + 105, //99 + 105, //100 + 105, //101 + 105, //102 + 105, //103 + 105, //104 + 106, //105 + 106, //106 + 106, //107 + 106, //108 + 106, //109 + 106, //110 + 106, //111 + 106, //112 + 106, //113 + 106, //114 + 106, //115 + 106, //116 + 106, //117 + 106, //118 + 106, //119 + 106, //120 + 106, //121 + 106, //122 + 106, //123 + 106, //124 + 106, //125 + 106, //126 + 106, //127 + 106, + } + }, //RF_CHAN_4 + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 53 , //7 + 54 , //8 + 56 , //9 + 57 , //10 + 59 , //11 + 60 , //12 + 62 , //13 + 63 , //14 + 65 , //15 + 66 , //16 + 67 , //17 + 68 , //18 + 69 , //19 + 69 , //20 + 71 , //21 + 72 , //22 + 72 , //23 + 73 , //24 + 74 , //25 + 75 , //26 + 76 , //27 + 77 , //28 + 78 , //29 + 79 , //30 + 79 , //31 + 80 , //32 + 81 , //33 + 82 , //34 + 83 , //35 + 83 , //36 + 84 , //37 + 85 , //38 + 86 , //39 + 87 , //40 + 87 , //41 + 88 , //42 + 89 , //43 + 89 , //44 + 90 , //45 + 91 , //46 + 91 , //47 + 92 , //48 + 92 , //49 + 93 , //50 + 93 , //51 + 94 , //52 + 94 , //53 + 95 , //54 + 95 , //55 + 96 , //56 + 96 , //57 + 96 , //58 + 97 , //59 + 97 , //60 + 98 , //61 + 98 , //62 + 98 , //63 + 99 , //64 + 99 , //65 + 100, //66 + 100, //67 + 100, //68 + 101, //69 + 101, //70 + 101, //71 + 102, //72 + 102, //73 + 102, //74 + 103, //75 + 103, //76 + 103, //77 + 103, //78 + 104, //79 + 104, //80 + 104, //81 + 104, //82 + 105, //83 + 105, //84 + 105, //85 + 105, //86 + 105, //87 + 105, //88 + 105, //89 + 105, //90 + 105, //91 + 106, //92 + 106, //93 + 106, //94 + 106, //95 + 106, //96 + 106, //97 + 106, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 106, //103 + 106, //104 + 106, //105 + 106, //106 + 106, //107 + 106, //108 + 106, //109 + 106, //110 + 106, //111 + 106, //112 + 106, //113 + 106, //114 + 106, //115 + 106, //116 + 106, //117 + 106, //118 + 106, //119 + 106, //120 + 106, //121 + 106, //122 + 106, //123 + 106, //124 + 106, //125 + 106, //126 + 106, //127 + 106, + } + }, //RF_CHAN_5 + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 53 , //7 + 55 , //8 + 56 , //9 + 58 , //10 + 59 , //11 + 61 , //12 + 62 , //13 + 63 , //14 + 64 , //15 + 65 , //16 + 66 , //17 + 68 , //18 + 69 , //19 + 70 , //20 + 71 , //21 + 72 , //22 + 73 , //23 + 74 , //24 + 75 , //25 + 76 , //26 + 77 , //27 + 77 , //28 + 78 , //29 + 79 , //30 + 80 , //31 + 80 , //32 + 81 , //33 + 82 , //34 + 83 , //35 + 83 , //36 + 84 , //37 + 85 , //38 + 86 , //39 + 87 , //40 + 87 , //41 + 88 , //42 + 89 , //43 + 89 , //44 + 90 , //45 + 91 , //46 + 91 , //47 + 92 , //48 + 92 , //49 + 93 , //50 + 93 , //51 + 94 , //52 + 94 , //53 + 95 , //54 + 95 , //55 + 96 , //56 + 96 , //57 + 97 , //58 + 97 , //59 + 98 , //60 + 98 , //61 + 98 , //62 + 99 , //63 + 99 , //64 + 100, //65 + 100, //66 + 100, //67 + 101, //68 + 101, //69 + 101, //70 + 102, //71 + 102, //72 + 102, //73 + 103, //74 + 103, //75 + 103, //76 + 103, //77 + 104, //78 + 104, //79 + 104, //80 + 104, //81 + 104, //82 + 105, //83 + 105, //84 + 105, //85 + 105, //86 + 105, //87 + 105, //88 + 105, //89 + 106, //90 + 106, //91 + 106, //92 + 106, //93 + 106, //94 + 106, //95 + 106, //96 + 106, //97 + 106, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 106, //103 + 106, //104 + 106, //105 + 106, //106 + 106, //107 + 106, //108 + 106, //109 + 106, //110 + 107, //111 + 107, //112 + 107, //113 + 107, //114 + 107, //115 + 107, //116 + 107, //117 + 107, //118 + 107, //119 + 107, //120 + 107, //121 + 107, //122 + 107, //123 + 107, //124 + 107, //125 + 107, //126 + 107, //127 + 107, + } + }, //RF_CHAN_6 + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 53 , //7 + 55 , //8 + 56 , //9 + 58 , //10 + 60 , //11 + 61 , //12 + 62 , //13 + 63 , //14 + 64 , //15 + 66 , //16 + 67 , //17 + 68 , //18 + 69 , //19 + 70 , //20 + 71 , //21 + 72 , //22 + 73 , //23 + 74 , //24 + 75 , //25 + 76 , //26 + 77 , //27 + 77 , //28 + 78 , //29 + 79 , //30 + 80 , //31 + 80 , //32 + 81 , //33 + 82 , //34 + 83 , //35 + 84 , //36 + 84 , //37 + 85 , //38 + 86 , //39 + 87 , //40 + 87 , //41 + 88 , //42 + 88 , //43 + 89 , //44 + 90 , //45 + 90 , //46 + 91 , //47 + 91 , //48 + 92 , //49 + 92 , //50 + 93 , //51 + 93 , //52 + 94 , //53 + 94 , //54 + 95 , //55 + 95 , //56 + 96 , //57 + 96 , //58 + 97 , //59 + 97 , //60 + 97 , //61 + 98 , //62 + 98 , //63 + 99 , //64 + 99 , //65 + 99 , //66 + 100, //67 + 100, //68 + 100, //69 + 101, //70 + 101, //71 + 101, //72 + 102, //73 + 102, //74 + 102, //75 + 103, //76 + 103, //77 + 103, //78 + 103, //79 + 104, //80 + 104, //81 + 104, //82 + 104, //83 + 104, //84 + 104, //85 + 105, //86 + 105, //87 + 105, //88 + 105, //89 + 105, //90 + 105, //91 + 105, //92 + 105, //93 + 105, //94 + 105, //95 + 105, //96 + 105, //97 + 106, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 106, //103 + 106, //104 + 106, //105 + 106, //106 + 106, //107 + 106, //108 + 106, //109 + 106, //110 + 106, //111 + 106, //112 + 106, //113 + 106, //114 + 106, //115 + 106, //116 + 106, //117 + 106, //118 + 106, //119 + 106, //120 + 106, //121 + 106, //122 + 106, //123 + 106, //124 + 106, //125 + 106, //126 + 106, //127 + 106, + } + }, //RF_CHAN_7 + { + { + 0 , //0 + 40 , //1 + 42 , //2 + 45 , //3 + 47 , //4 + 49 , //5 + 51 , //6 + 52 , //7 + 54 , //8 + 56 , //9 + 58 , //10 + 59 , //11 + 61 , //12 + 62 , //13 + 63 , //14 + 65 , //15 + 66 , //16 + 67 , //17 + 68 , //18 + 69 , //19 + 70 , //20 + 71 , //21 + 72 , //22 + 73 , //23 + 74 , //24 + 75 , //25 + 76 , //26 + 77 , //27 + 77 , //28 + 78 , //29 + 79 , //30 + 80 , //31 + 81 , //32 + 81 , //33 + 82 , //34 + 83 , //35 + 84 , //36 + 85 , //37 + 86 , //38 + 86 , //39 + 87 , //40 + 88 , //41 + 89 , //42 + 89 , //43 + 90 , //44 + 91 , //45 + 91 , //46 + 92 , //47 + 92 , //48 + 93 , //49 + 93 , //50 + 94 , //51 + 94 , //52 + 95 , //53 + 95 , //54 + 96 , //55 + 96 , //56 + 97 , //57 + 97 , //58 + 97 , //59 + 98 , //60 + 98 , //61 + 99 , //62 + 99 , //63 + 99 , //64 + 100, //65 + 100, //66 + 100, //67 + 101, //68 + 101, //69 + 102, //70 + 102, //71 + 102, //72 + 103, //73 + 103, //74 + 103, //75 + 104, //76 + 104, //77 + 104, //78 + 104, //79 + 105, //80 + 105, //81 + 105, //82 + 105, //83 + 105, //84 + 105, //85 + 105, //86 + 105, //87 + 106, //88 + 106, //89 + 106, //90 + 106, //91 + 106, //92 + 106, //93 + 106, //94 + 106, //95 + 106, //96 + 106, //97 + 106, //98 + 106, //99 + 106, //100 + 106, //101 + 106, //102 + 106, //103 + 106, //104 + 107, //105 + 107, //106 + 107, //107 + 107, //108 + 107, //109 + 107, //110 + 107, //111 + 107, //112 + 107, //113 + 107, //114 + 107, //115 + 107, //116 + 107, //117 + 107, //118 + 107, //119 + 107, //120 + 107, //121 + 107, //122 + 107, //123 + 107, //124 + 107, //125 + 107, //126 + 107, //127 + 107, + } + }, //RF_CHAN_8 + { + { + 0 , //0 + 41 , //1 + 44 , //2 + 46 , //3 + 48 , //4 + 50 , //5 + 52 , //6 + 54 , //7 + 56 , //8 + 58 , //9 + 59 , //10 + 60 , //11 + 62 , //12 + 63 , //13 + 64 , //14 + 66 , //15 + 67 , //16 + 68 , //17 + 69 , //18 + 70 , //19 + 71 , //20 + 72 , //21 + 73 , //22 + 74 , //23 + 75 , //24 + 76 , //25 + 77 , //26 + 78 , //27 + 79 , //28 + 79 , //29 + 80 , //30 + 81 , //31 + 82 , //32 + 83 , //33 + 83 , //34 + 84 , //35 + 85 , //36 + 86 , //37 + 87 , //38 + 87 , //39 + 88 , //40 + 89 , //41 + 89 , //42 + 90 , //43 + 91 , //44 + 91 , //45 + 92 , //46 + 92 , //47 + 93 , //48 + 93 , //49 + 94 , //50 + 94 , //51 + 95 , //52 + 95 , //53 + 96 , //54 + 96 , //55 + 97 , //56 + 97 , //57 + 98 , //58 + 98 , //59 + 98 , //60 + 99 , //61 + 99 , //62 + 100, //63 + 100, //64 + 100, //65 + 101, //66 + 101, //67 + 101, //68 + 102, //69 + 102, //70 + 103, //71 + 103, //72 + 103, //73 + 104, //74 + 104, //75 + 104, //76 + 104, //77 + 105, //78 + 105, //79 + 105, //80 + 105, //81 + 105, //82 + 105, //83 + 106, //84 + 106, //85 + 106, //86 + 106, //87 + 106, //88 + 106, //89 + 106, //90 + 106, //91 + 106, //92 + 106, //93 + 106, //94 + 106, //95 + 106, //96 + 106, //97 + 106, //98 + 107, //99 + 107, //100 + 107, //101 + 107, //102 + 107, //103 + 107, //104 + 107, //105 + 107, //106 + 107, //107 + 107, //108 + 107, //109 + 107, //110 + 107, //111 + 107, //112 + 107, //113 + 107, //114 + 107, //115 + 107, //116 + 107, //117 + 107, //118 + 107, //119 + 107, //120 + 107, //121 + 107, //122 + 107, //123 + 107, //124 + 107, //125 + 107, //126 + 107, //127 + 107, + } + }, //RF_CHAN_9 + { + { + 0 , //0 + 41 , //1 + 43 , //2 + 47 , //3 + 48 , //4 + 50 , //5 + 52 , //6 + 53 , //7 + 55 , //8 + 57 , //9 + 58 , //10 + 60 , //11 + 62 , //12 + 63 , //13 + 64 , //14 + 65 , //15 + 67 , //16 + 68 , //17 + 69 , //18 + 70 , //19 + 71 , //20 + 72 , //21 + 73 , //22 + 74 , //23 + 75 , //24 + 76 , //25 + 77 , //26 + 77 , //27 + 78 , //28 + 79 , //29 + 80 , //30 + 81 , //31 + 82 , //32 + 83 , //33 + 84 , //34 + 85 , //35 + 85 , //36 + 86 , //37 + 87 , //38 + 88 , //39 + 89 , //40 + 89 , //41 + 90 , //42 + 90 , //43 + 91 , //44 + 92 , //45 + 92 , //46 + 93 , //47 + 94 , //48 + 94 , //49 + 95 , //50 + 95 , //51 + 96 , //52 + 96 , //53 + 96 , //54 + 97 , //55 + 97 , //56 + 98 , //57 + 98 , //58 + 99 , //59 + 99 , //60 + 99 , //61 + 100, //62 + 100, //63 + 101, //64 + 101, //65 + 102, //66 + 102, //67 + 102, //68 + 103, //69 + 103, //70 + 103, //71 + 104, //72 + 104, //73 + 104, //74 + 105, //75 + 105, //76 + 105, //77 + 105, //78 + 105, //79 + 106, //80 + 106, //81 + 106, //82 + 106, //83 + 106, //84 + 106, //85 + 106, //86 + 106, //87 + 106, //88 + 107, //89 + 107, //90 + 107, //91 + 107, //92 + 107, //93 + 107, //94 + 107, //95 + 107, //96 + 107, //97 + 107, //98 + 107, //99 + 107, //100 + 107, //101 + 107, //102 + 107, //103 + 107, //104 + 107, //105 + 107, //106 + 107, //107 + 107, //108 + 107, //109 + 107, //110 + 107, //111 + 107, //112 + 107, //113 + 107, //114 + 107, //115 + 107, //116 + 107, //117 + 107, //118 + 107, //119 + 107, //120 + 107, //121 + 107, //122 + 107, //123 + 107, //124 + 107, //125 + 107, //126 + 107, //127 + 107, + } + }, //RF_CHAN_10 + { + { + 0 , //0 + 42 , //1 + 44 , //2 + 47 , //3 + 49 , //4 + 51 , //5 + 52 , //6 + 54 , //7 + 55 , //8 + 57 , //9 + 58 , //10 + 60 , //11 + 61 , //12 + 63 , //13 + 64 , //14 + 65 , //15 + 66 , //16 + 67 , //17 + 69 , //18 + 70 , //19 + 71 , //20 + 72 , //21 + 73 , //22 + 74 , //23 + 75 , //24 + 76 , //25 + 77 , //26 + 77 , //27 + 78 , //28 + 79 , //29 + 80 , //30 + 81 , //31 + 82 , //32 + 82 , //33 + 83 , //34 + 84 , //35 + 85 , //36 + 86 , //37 + 86 , //38 + 87 , //39 + 88 , //40 + 89 , //41 + 90 , //42 + 90 , //43 + 91 , //44 + 91 , //45 + 92 , //46 + 92 , //47 + 93 , //48 + 93 , //49 + 94 , //50 + 94 , //51 + 95 , //52 + 96 , //53 + 96 , //54 + 97 , //55 + 97 , //56 + 97 , //57 + 98 , //58 + 98 , //59 + 99 , //60 + 99 , //61 + 100, //62 + 100, //63 + 100, //64 + 101, //65 + 101, //66 + 101, //67 + 102, //68 + 102, //69 + 102, //70 + 103, //71 + 103, //72 + 103, //73 + 103, //74 + 103, //75 + 103, //76 + 104, //77 + 104, //78 + 104, //79 + 104, //80 + 104, //81 + 104, //82 + 104, //83 + 104, //84 + 104, //85 + 104, //86 + 104, //87 + 105, //88 + 105, //89 + 105, //90 + 105, //91 + 105, //92 + 105, //93 + 105, //94 + 105, //95 + 105, //96 + 105, //97 + 105, //98 + 105, //99 + 105, //100 + 105, //101 + 105, //102 + 105, //103 + 105, //104 + 105, //105 + 105, //106 + 105, //107 + 105, //108 + 105, //109 + 105, //110 + 105, //111 + 105, //112 + 105, //113 + 105, //114 + 105, //115 + 105, //116 + 105, //117 + 105, //118 + 105, //119 + 105, //120 + 105, //121 + 105, //122 + 105, //123 + 105, //124 + 105, //125 + 105, //126 + 105, //127 + } + }, //RF_CHAN_11 + { + { + 0 , //0 + 41 , //1 + 44 , //2 + 46 , //3 + 48 , //4 + 50 , //5 + 52 , //6 + 54 , //7 + 56 , //8 + 57 , //9 + 59 , //10 + 60 , //11 + 61 , //12 + 63 , //13 + 64 , //14 + 65 , //15 + 66 , //16 + 67 , //17 + 69 , //18 + 70 , //19 + 71 , //20 + 72 , //21 + 73 , //22 + 74 , //23 + 75 , //24 + 76 , //25 + 77 , //26 + 77 , //27 + 78 , //28 + 79 , //29 + 80 , //30 + 80 , //31 + 81 , //32 + 82 , //33 + 83 , //34 + 83 , //35 + 84 , //36 + 85 , //37 + 86 , //38 + 86 , //39 + 87 , //40 + 88 , //41 + 88 , //42 + 89 , //43 + 90 , //44 + 90 , //45 + 91 , //46 + 92 , //47 + 92 , //48 + 93 , //49 + 93 , //50 + 94 , //51 + 94 , //52 + 95 , //53 + 95 , //54 + 96 , //55 + 96 , //56 + 96 , //57 + 97 , //58 + 97 , //59 + 98 , //60 + 98 , //61 + 99 , //62 + 99 , //63 + 99 , //64 + 100, //65 + 100, //66 + 100, //67 + 101, //68 + 101, //69 + 101, //70 + 102, //71 + 102, //72 + 102, //73 + 103, //74 + 103, //75 + 103, //76 + 103, //77 + 103, //78 + 103, //79 + 103, //80 + 104, //81 + 104, //82 + 104, //83 + 104, //84 + 104, //85 + 104, //86 + 104, //87 + 104, //88 + 104, //89 + 104, //90 + 104, //91 + 104, //92 + 104, //93 + 105, //94 + 105, //95 + 105, //96 + 105, //97 + 105, //98 + 105, //99 + 105, //100 + 105, //101 + 105, //102 + 105, //103 + 105, //104 + 105, //105 + 105, //106 + 105, //107 + 105, //108 + 105, //109 + 105, //110 + 105, //111 + 105, //112 + 105, //113 + 105, //114 + 105, //115 + 105, //116 + 105, //117 + 105, //118 + 105, //119 + 105, //120 + 105, //121 + 105, //122 + 105, //123 + 105, //124 + 105, //125 + 105, //126 + 105, //127 + 105, + } + }, //RF_CHAN_12 + { + { + 0 , //0 + 42 , //1 + 44 , //2 + 46 , //3 + 48 , //4 + 50 , //5 + 52 , //6 + 54 , //7 + 56 , //8 + 58 , //9 + 59 , //10 + 60 , //11 + 61 , //12 + 63 , //13 + 64 , //14 + 65 , //15 + 66 , //16 + 68 , //17 + 69 , //18 + 70 , //19 + 71 , //20 + 72 , //21 + 73 , //22 + 74 , //23 + 75 , //24 + 75 , //25 + 76 , //26 + 77 , //27 + 78 , //28 + 79 , //29 + 80 , //30 + 80 , //31 + 81 , //32 + 82 , //33 + 83 , //34 + 83 , //35 + 84 , //36 + 85 , //37 + 86 , //38 + 86 , //39 + 87 , //40 + 88 , //41 + 89 , //42 + 89 , //43 + 90 , //44 + 91 , //45 + 91 , //46 + 92 , //47 + 93 , //48 + 93 , //49 + 94 , //50 + 94 , //51 + 95 , //52 + 95 , //53 + 96 , //54 + 96 , //55 + 97 , //56 + 97 , //57 + 97 , //58 + 98 , //59 + 98 , //60 + 99 , //61 + 99 , //62 + 100, //63 + 100, //64 + 100, //65 + 101, //66 + 101, //67 + 101, //68 + 102, //69 + 102, //70 + 102, //71 + 103, //72 + 103, //73 + 103, //74 + 103, //75 + 103, //76 + 103, //77 + 104, //78 + 104, //79 + 104, //80 + 104, //81 + 104, //82 + 104, //83 + 104, //84 + 104, //85 + 104, //86 + 104, //87 + 104, //88 + 104, //89 + 105, //90 + 105, //91 + 105, //92 + 105, //93 + 105, //94 + 105, //95 + 105, //96 + 105, //97 + 105, //98 + 105, //99 + 105, //100 + 105, //101 + 105, //102 + 105, //103 + 105, //104 + 105, //105 + 105, //106 + 105, //107 + 105, //108 + 105, //109 + 105, //110 + 105, //111 + 105, //112 + 105, //113 + 105, //114 + 105, //115 + 105, //116 + 105, //117 + 105, //118 + 105, //119 + 105, //120 + 105, //121 + 105, //122 + 105, //123 + 105, //124 + 105, //125 + 105, //126 + 105, //127 + 105, + } + }, //RF_CHAN_13 + { + { + 0, //0 + 40, //1 + 43, //2 + 45, //3 + 47, //4 + 49, //5 + 50, //6 + 52, //7 + 54, //8 + 56, //9 + 57, //10 + 58, //11 + 59, //12 + 60, //13 + 62, //14 + 63, //15 + 64, //16 + 65, //17 + 66, //18 + 67, //19 + 68, //20 + 69, //21 + 70, //22 + 71, //23 + 72, //24 + 73, //25 + 74, //26 + 74, //27 + 75, //28 + 76, //29 + 77, //30 + 78, //31 + 78, //32 + 79, //33 + 80, //34 + 81, //35 + 82, //36 + 83, //37 + 83, //38 + 84, //39 + 85, //40 + 85, //41 + 86, //42 + 87, //43 + 87, //44 + 88, //45 + 89, //46 + 89, //47 + 90, //48 + 90, //49 + 91, //50 + 91, //51 + 92, //52 + 92, //53 + 93, //54 + 93, //55 + 94, //56 + 94, //57 + 95, //58 + 95, //59 + 96, //60 + 96, //61 + 96, //62 + 97, //63 + 97, //64 + 97, //65 + 98, //66 + 98, //67 + 98, //68 + 98, //69 + 99, //70 + 99, //71 + 99, //72 + 99, //73 + 99, //74 + 99, //75 + 99, //76 + 99, //77 + 99, //78 + 99, //79 + 100, //80 + 100, //81 + 100, //82 + 100, //83 + 100, //84 + 100, //85 + 100, //86 + 100, //87 + 100, //88 + 100, //89 + 100, //90 + 100, //91 + 100, //92 + 100, //93 + 100, //94 + 100, //95 + 100, //96 + 100, //97 + 100, //98 + 100, //99 + 100, //100 + 100, //101 + 100, //102 + 100, //103 + 100, //104 + 100, //105 + 100, //106 + 100, //107 + 100, //108 + 100, //109 + 100, //110 + 100, //111 + 100, //112 + 100, //113 + 100, //114 + 100, //115 + 100, //116 + 100, //117 + 100, //118 + 100, //119 + 100, //120 + 100, //121 + 100, //122 + 100, //123 + 100, //124 + 100, //125 + 100, //126 + 100, //127 + 100, + } + }, //RF_CHAN_14 + }, + + //NV_TABLE_TPC_PDADC_OFFSETS + { + 98, // RF_CHAN_1 + 101, // RF_CHAN_2 + 101, // RF_CHAN_3 + 100, // RF_CHAN_4 + 98, // RF_CHAN_5 + 97, // RF_CHAN_6 + 94, // RF_CHAN_7 + 94, // RF_CHAN_8 + 92, // RF_CHAN_9 + 90, // RF_CHAN_10 + 94, // RF_CHAN_11 + 95, // RF_CHAN_12 + 97, // RF_CHAN_13 + 104, // RF_CHAN_14 + 100, // RF_CHAN_240 + 100, // RF_CHAN_244 + 100, // RF_CHAN_248 + 100, // RF_CHAN_252 + 100, // RF_CHAN_208 + 100, // RF_CHAN_212 + 100, // RF_CHAN_216 + 100, // RF_CHAN_36 + 100, // RF_CHAN_40 + 100, // RF_CHAN_44 + 100, // RF_CHAN_48 + 100, // RF_CHAN_52 + 100, // RF_CHAN_56 + 100, // RF_CHAN_60 + 100, // RF_CHAN_64 + 100, // RF_CHAN_100 + 100, // RF_CHAN_104 + 100, // RF_CHAN_108 + 100, // RF_CHAN_112 + 100, // RF_CHAN_116 + 100, // RF_CHAN_120 + 100, // RF_CHAN_124 + 100, // RF_CHAN_128 + 100, // RF_CHAN_132 + 100, // RF_CHAN_136 + 100, // RF_CHAN_140 + 100, // RF_CHAN_149 + 100, // RF_CHAN_153 + 100, // RF_CHAN_157 + 100, // RF_CHAN_161 + 100, // RF_CHAN_165 + //CHANNEL BONDED CHANNELS + 100, // RF_CHAN_BOND_3 + 100, // RF_CHAN_BOND_4 + 100, // RF_CHAN_BOND_5 + 100, // RF_CHAN_BOND_6 + 100, // RF_CHAN_BOND_7 + 100, // RF_CHAN_BOND_8 + 100, // RF_CHAN_BOND_9 + 100, // RF_CHAN_BOND_10 + 100, // RF_CHAN_BOND_11 + 100, // RF_CHAN_BOND_242 + 100, // RF_CHAN_BOND_246 + 100, // RF_CHAN_BOND_250 + 100, // RF_CHAN_BOND_210 + 100, // RF_CHAN_BOND_214 + 100, // RF_CHAN_BOND_38 + 100, // RF_CHAN_BOND_42 + 100, // RF_CHAN_BOND_46 + 100, // RF_CHAN_BOND_50 + 100, // RF_CHAN_BOND_54 + 100, // RF_CHAN_BOND_58 + 100, // RF_CHAN_BOND_62 + 100, // RF_CHAN_BOND_102 + 100, // RF_CHAN_BOND_106 + 100, // RF_CHAN_BOND_110 + 100, // RF_CHAN_BOND_114 + 100, // RF_CHAN_BOND_118 + 100, // RF_CHAN_BOND_122 + 100, // RF_CHAN_BOND_126 + 100, // RF_CHAN_BOND_130 + 100, // RF_CHAN_BOND_134 + 100, // RF_CHAN_BOND_138 + 100, // RF_CHAN_BOND_151 + 100, // RF_CHAN_BOND_155 + 100, // RF_CHAN_BOND_159 + 100, // RF_CHAN_BOND_163 + }, + + //NV_TABLE_VIRTUAL_RATE + // typedef tANI_S16 tPowerdBm; + //typedef tPowerdBm tRateGroupPwr[NUM_HAL_PHY_RATES]; + //tRateGroupPwr pwrOptimum[NUM_RF_SUBBANDS]; + { + // 2.4G RF Subband + { + //802.11b Rates + {100}, // HAL_PHY_VRATE_11A_54_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_65_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_72_2_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_CB_135_MBPS + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_CB_150_MBPS, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + }, + // 5G Low RF Subband + { + //802.11b Rates + {100}, // HAL_PHY_VRATE_11A_54_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_65_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_72_2_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_CB_135_MBPS + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_CB_150_MBPS, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + }, + // 5G Middle RF Subband + { + //802.11b Rates + {100}, // HAL_PHY_VRATE_11A_54_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_65_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_72_2_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_CB_135_MBPS + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_CB_150_MBPS, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + }, + // 5G High RF Subband + { + //802.11b Rates + {100}, // HAL_PHY_VRATE_11A_54_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_65_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_72_2_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_CB_135_MBPS + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_CB_150_MBPS, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + }, + // 4.9G RF Subband + { + //802.11b Rates + {100}, // HAL_PHY_VRATE_11A_54_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_65_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_72_2_MBPS, + {100}, // HAL_PHY_VRATE_MCS_1NSS_CB_135_MBPS + {100}, // HAL_PHY_VRATE_MCS_1NSS_MM_SG_CB_150_MBPS, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + {100}, // RESERVED, + } + }, + +#if 0 //FIXME_PRIMA + //NV_TABLE_CAL_MEMORY + { + 0x7FFF, // tANI_U16 process_monitor; + 0x00, // tANI_U8 hdet_cal_code; + 0x00, // tANI_U8 rxfe_gm_2; + + 0x00, // tANI_U8 tx_bbf_rtune; + 0x00, // tANI_U8 pa_rtune_reg; + 0x00, // tANI_U8 rt_code; + 0x00, // tANI_U8 bias_rtune; + + 0x00, // tANI_U8 bb_bw1; + 0x00, // tANI_U8 bb_bw2; + { 0x00, 0x00 }, // tANI_U8 reserved[2]; + + 0x00, // tANI_U8 bb_bw3; + 0x00, // tANI_U8 bb_bw4; + 0x00, // tANI_U8 bb_bw5; + 0x00, // tANI_U8 bb_bw6; + + 0x7FFF, // tANI_U16 rcMeasured; + 0x00, // tANI_U8 tx_bbf_ct; + 0x00, // tANI_U8 tx_bbf_ctr; + + 0x00, // tANI_U8 csh_maxgain_reg; + 0x00, // tANI_U8 csh_0db_reg; + 0x00, // tANI_U8 csh_m3db_reg; + 0x00, // tANI_U8 csh_m6db_reg; + + 0x00, // tANI_U8 cff_0db_reg; + 0x00, // tANI_U8 cff_m3db_reg; + 0x00, // tANI_U8 cff_m6db_reg; + 0x00, // tANI_U8 rxfe_gpio_ctl_1; + + 0x00, // tANI_U8 mix_bal_cnt_2; + 0x00, // tANI_S8 rxfe_lna_highgain_bias_ctl_delta; + 0x00, // tANI_U8 rxfe_lna_load_ctune; + 0x00, // tANI_U8 rxfe_lna_ngm_rtune; + + 0x00, // tANI_U8 rx_im2_i_cfg0; + 0x00, // tANI_U8 rx_im2_i_cfg1; + 0x00, // tANI_U8 rx_im2_q_cfg0; + 0x00, // tANI_U8 rx_im2_q_cfg1; + + 0x00, // tANI_U8 pll_vfc_reg3_b0; + 0x00, // tANI_U8 pll_vfc_reg3_b1; + 0x00, // tANI_U8 pll_vfc_reg3_b2; + 0x00, // tANI_U8 pll_vfc_reg3_b3; + + 0x7FFF, // tANI_U16 tempStart; + 0x7FFF, // tANI_U16 tempFinish; + + { //txLoCorrections + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_1 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_2 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_3 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_4 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_5 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_6 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_7 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_8 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_9 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_10 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_11 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_12 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + }, //RF_CHAN_13 + { + { 0x00, 0x00 }, // TX_GAIN_STEP_0 + { 0x00, 0x00 }, // TX_GAIN_STEP_1 + { 0x00, 0x00 }, // TX_GAIN_STEP_2 + { 0x00, 0x00 }, // TX_GAIN_STEP_3 + { 0x00, 0x00 }, // TX_GAIN_STEP_4 + { 0x00, 0x00 }, // TX_GAIN_STEP_5 + { 0x00, 0x00 }, // TX_GAIN_STEP_6 + { 0x00, 0x00 }, // TX_GAIN_STEP_7 + { 0x00, 0x00 }, // TX_GAIN_STEP_8 + { 0x00, 0x00 }, // TX_GAIN_STEP_9 + { 0x00, 0x00 }, // TX_GAIN_STEP_10 + { 0x00, 0x00 }, // TX_GAIN_STEP_11 + { 0x00, 0x00 }, // TX_GAIN_STEP_12 + { 0x00, 0x00 }, // TX_GAIN_STEP_13 + { 0x00, 0x00 }, // TX_GAIN_STEP_14 + { 0x00, 0x00 } // TX_GAIN_STEP_15 + } //RF_CHAN_14 + }, // tTxLoCorrections txLoValues; + + { //sTxIQChannel + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_1 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_2 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_3 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_4 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_5 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_6 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_7 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_8 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_9 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_10 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_11 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_12 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + }, //RF_CHAN_13 + { + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // TX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // TX_GAIN_STEP_15 + } //RF_CHAN_14 + }, // sTxIQChannel txIqValues; + + { //sRxIQChannel + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_1 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_2 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_3 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_4 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_5 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_6 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_7 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_8 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_9 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_10 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_11 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_12 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + }, //RF_CHAN_13 + { + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_0 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_1 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_2 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_3 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_4 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_5 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_6 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_7 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_8 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_9 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_10 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_11 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_12 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_13 + { 0x0000, 0x0000, 0x0000 }, // RX_GAIN_STEP_14 + { 0x0000, 0x0000, 0x0000 } // RX_GAIN_STEP_15 + } //RF_CHAN_14 + }, // sRxIQChannel rxIqValues; + + { // tTpcConfig clpcData[MAX_TPC_CHANNELS] + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_1 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_2 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_3 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_4 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_5 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_6 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_7 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_8 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_9 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_10 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_11 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_12 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + }, // RF_CHAN_13 + { + { + { + { 0x00, 0x00 }, //CAL_POINT_0 + { 0x00, 0x00 }, //CAL_POINT_1 + { 0x00, 0x00 }, //CAL_POINT_2 + { 0x00, 0x00 }, //CAL_POINT_3 + { 0x00, 0x00 }, //CAL_POINT_4 + { 0x00, 0x00 }, //CAL_POINT_5 + { 0x00, 0x00 }, //CAL_POINT_6 + { 0x00, 0x00 } //CAL_POINT_7 + } // PHY_TX_CHAIN_0 + } // empirical + } // RF_CHAN_14 + }, // tTpcConfig clpcData[MAX_TPC_CHANNELS]; + + { + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_1: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_2: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_3: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_4: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_5: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_6: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_7: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_8: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_9: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_10: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_11: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_12: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } }, // RF_CHAN_13: pdadc_offset, reserved[2] + { 0x0000, { 0x00, 0x00 } } // RF_CHAN_14: pdadc_offset, reserved[2] + } // tTpcParams clpcParams[MAX_TPC_CHANNELS]; + + }, //NV_TABLE_CAL_MEMORY +#endif + //NV_TABLE_FW_CONFIG + { + 0, //skuID + 0, //tpcMode2G + 0, //tpcMode5G + 0, //reserved1 + + 0, //xPA2G + 0, //xPA5G; + 0, //paPolarityTx; + 0, //paPolarityRx; + + 0, //xLNA2G; + 0, //xLNA5G; + 0, //xCoupler2G; + 0, //xCoupler5G; + + 0, //xPdet2G; + 0, //xPdet5G; + 0, //enableDPD2G; + 1, //enableDPD5G; + + 1, //pdadcSelect2G; + 1, //pdadcSelect5GLow; + 1, //pdadcSelect5GMid; + 1, //pdadcSelect5GHigh; + + 0, //reserved2 + 0, //reserved3 + 0, //reserved4 + }, + + + //NV_TABLE_RSSI_CHANNEL_OFFSETS + { + //PHY_RX_CHAIN_0 + { + //bRssiOffset + {300}, // apply to all channles + + //gnRssiOffset + {300} // apply to all channles + }, + //rsvd + { + //bRssiOffset + {0}, // apply to all channles + + //gnRssiOffset + {0} // apply to all channles + } + }, + + //NV_TABLE_HW_CAL_VALUES + { + 0x0, //validBmap + { + 1400, //psSlpTimeOvrHd2G; + 1400, //psSlpTimeOvrHd5G; + + 1600, //psSlpTimeOvrHdxLNA5G; + 0, //nv_TxBBFSel9MHz + 0, //hwParam1 + 0, //hwParam2 + + 0x1B, //custom_tcxo_reg8 + 0xFF, //custom_tcxo_reg9 + + 0, //hwParam3; + 0, //hwParam4; + 0, //hwParam5; + 0, //hwParam6; + 0, //hwParam7; + 0, //hwParam8; + 0, //hwParam9; + 0, //hwParam10; + 0, //hwParam11; + } + }, + + + //NV_TABLE_ANTENNA_PATH_LOSS + { + 280, // RF_CHAN_1 + 270, // RF_CHAN_2 + 270, // RF_CHAN_3 + 270, // RF_CHAN_4 + 270, // RF_CHAN_5 + 270, // RF_CHAN_6 + 280, // RF_CHAN_7 + 280, // RF_CHAN_8 + 290, // RF_CHAN_9 + 300, // RF_CHAN_10 + 300, // RF_CHAN_11 + 310, // RF_CHAN_12 + 310, // RF_CHAN_13 + 310, // RF_CHAN_14 + 280, // RF_CHAN_240 + 280, // RF_CHAN_244 + 280, // RF_CHAN_248 + 280, // RF_CHAN_252 + 280, // RF_CHAN_208 + 280, // RF_CHAN_212 + 280, // RF_CHAN_216 + 280, // RF_CHAN_36 + 280, // RF_CHAN_40 + 280, // RF_CHAN_44 + 280, // RF_CHAN_48 + 280, // RF_CHAN_52 + 280, // RF_CHAN_56 + 280, // RF_CHAN_60 + 280, // RF_CHAN_64 + 280, // RF_CHAN_100 + 280, // RF_CHAN_104 + 280, // RF_CHAN_108 + 280, // RF_CHAN_112 + 280, // RF_CHAN_116 + 280, // RF_CHAN_120 + 280, // RF_CHAN_124 + 280, // RF_CHAN_128 + 280, // RF_CHAN_132 + 280, // RF_CHAN_136 + 280, // RF_CHAN_140 + 280, // RF_CHAN_149 + 280, // RF_CHAN_153 + 280, // RF_CHAN_157 + 280, // RF_CHAN_161 + 280, // RF_CHAN_165 + //CHANNEL BONDED CHANNELS + 280, // RF_CHAN_BOND_3 + 280, // RF_CHAN_BOND_4 + 280, // RF_CHAN_BOND_5 + 280, // RF_CHAN_BOND_6 + 280, // RF_CHAN_BOND_7 + 280, // RF_CHAN_BOND_8 + 280, // RF_CHAN_BOND_9 + 280, // RF_CHAN_BOND_10 + 280, // RF_CHAN_BOND_11 + 280, // RF_CHAN_BOND_242 + 280, // RF_CHAN_BOND_246 + 280, // RF_CHAN_BOND_250 + 280, // RF_CHAN_BOND_210 + 280, // RF_CHAN_BOND_214 + 280, // RF_CHAN_BOND_38 + 280, // RF_CHAN_BOND_42 + 280, // RF_CHAN_BOND_46 + 280, // RF_CHAN_BOND_50 + 280, // RF_CHAN_BOND_54 + 280, // RF_CHAN_BOND_58 + 280, // RF_CHAN_BOND_62 + 280, // RF_CHAN_BOND_102 + 280, // RF_CHAN_BOND_106 + 280, // RF_CHAN_BOND_110 + 280, // RF_CHAN_BOND_114 + 280, // RF_CHAN_BOND_118 + 280, // RF_CHAN_BOND_122 + 280, // RF_CHAN_BOND_126 + 280, // RF_CHAN_BOND_130 + 280, // RF_CHAN_BOND_134 + 280, // RF_CHAN_BOND_138 + 280, // RF_CHAN_BOND_151 + 280, // RF_CHAN_BOND_155 + 280, // RF_CHAN_BOND_159 + 280, // RF_CHAN_BOND_163 + }, + + //NV_TABLE_PACKET_TYPE_POWER_LIMITS + { + { 2150 }, // applied to all channels, MODE_802_11B + { 1850 }, // applied to all channels,MODE_802_11AG + { 1750 } // applied to all channels,MODE_802_11N + }, + + //NV_TABLE_OFDM_CMD_PWR_OFFSET + { + 0, 0 + }, + + //NV_TABLE_TX_BB_FILTER_MODE + { + 0 + } + + } // tables +}; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_qct_wma_legacy.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_qct_wma_legacy.c new file mode 100644 index 000000000000..06dc646b0784 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wlan_qct_wma_legacy.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + wlan_qct_WMA_legacy.c + + OVERVIEW: + + This software unit holds the implementation of the WLAN Device Adaptation + Layer for the legacy functionalities that were part of the old HAL. + + The functions externalized by this module are to be called ONLY by other + WLAN modules that properly register with the Transport Layer initially. + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/* Standard include files */ +/* Application Specific include files */ +#include "limApi.h" +#include "pmmApi.h" +#include "cfgApi.h" + +/* Locally used Defines */ + +#define HAL_MMH_MB_MSG_TYPE_MASK 0xFF00 +// ------------------------------------------------------------- +/** + * WMAPostCtrlMsg + * + * FUNCTION: + * Posts WMA messages to MC thread + * + * LOGIC: + * + * ASSUMPTIONS:pl + * + * + * NOTE: + * + * @param tpAniSirGlobal MAC parameters structure + * @param pMsg pointer with message + * @return Success or Failure + */ + +tSirRetStatus +wmaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_WMA, (vos_msg_t *) pMsg)) + return eSIR_FAILURE; + else + return eSIR_SUCCESS; +} // halPostMsg() + +/** + * WMAPostCfgMsg + * + * FUNCTION: + * Posts MNT messages to gSirMntMsgQ + * + * LOGIC: + * + * ASSUMPTIONS: + * + * + * NOTE: + * + * @param tpAniSirGlobal MAC parameters structure + * @param pMsg A pointer to the msg + * @return Success or Failure + */ + +tSirRetStatus +wmaPostCfgMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + tSirRetStatus rc = eSIR_SUCCESS; + + do + { + // For Windows based MAC, instead of posting message to different + // queues we will call the handler routines directly + + cfgProcessMbMsg(pMac, (tSirMbMsg*)pMsg->bodyptr); + rc = eSIR_SUCCESS; + } while (0); + + return rc; +} // halMntPostMsg() + +// ------------------------------------------------------------- +/** + * uMacPostCtrlMsg + * + * FUNCTION: + * Forwards the completely received message to the respective + * modules for further processing. + * + * LOGIC: + * + * ASSUMPTIONS: + * Freeing up of the message buffer is left to the destination module. + * + * NOTE: + * This function has been moved to the API file because for MAC running + * on Windows host, the host module will call this routine directly to + * send any mailbox messages. Making this function an API makes sure that + * outside world (any module outside MMH) only calls APIs to use MMH + * services and not an internal function. + * + * @param pMb A pointer to the maibox message + * @return NONE + */ + +tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pSirGlobal; + + + tSirMbMsg* pMbLocal; + msg.type = pMb->type; + msg.bodyval = 0; +//TODO:FIXME +// WMA_LOGD("msgType %d, msgLen %d\n" ,pMb->type, pMb->msgLen); + + // copy the message from host buffer to firmware buffer + // this will make sure that firmware allocates, uses and frees + // it's own buffers for mailbox message instead of working on + // host buffer + + // second parameter, 'wait option', to palAllocateMemory is ignored on Windows + if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMbLocal, pMb->msgLen)) + { +//TODO:FIXME +// WMA_LOGE("Buffer Allocation failed!\n"); + return eSIR_FAILURE; + } + + palCopyMemory(pMac, (void *)pMbLocal, (void *)pMb, pMb->msgLen); + msg.bodyptr = pMbLocal; + + switch (msg.type & HAL_MMH_MB_MSG_TYPE_MASK) + { + case WMA_MSG_TYPES_BEGIN: // Posts a message to the HAL MsgQ + wmaPostCtrlMsg(pMac, &msg); + break; + + case SIR_LIM_MSG_TYPES_BEGIN: // Posts a message to the LIM MsgQ + limPostMsgApi(pMac, &msg); + break; + + case SIR_CFG_MSG_TYPES_BEGIN: // Posts a message to the CFG MsgQ + wmaPostCfgMsg(pMac, &msg); + break; + + case SIR_PMM_MSG_TYPES_BEGIN: // Posts a message to the PMM MsgQ + pmmPostMessage(pMac, &msg); + break; + + case SIR_PTT_MSG_TYPES_BEGIN: + break; + + + default: +//TODO:FIXME +//WMA_LOGD("Unknown message type = 0x%X\n", msg.type); + + // Release the memory. + if (palFreeMemory( pMac->hHdd, (void*)(msg.bodyptr)) + != eHAL_STATUS_SUCCESS) + { +//TODO:FIXME +// WMA_LOGE("Buffer Allocation failed!\n"); + return eSIR_FAILURE; + } + break; + } + + return eSIR_SUCCESS; + +} // uMacPostCtrlMsg() + +//TODO: FIXME +#if 0 +/* --------------------------------------------------------- + * FUNCTION: WMAGetGlobalSystemRole() + * + * Get the global HAL system role. + * --------------------------------------------------------- + */ +tBssSystemRole WMAGetGlobalSystemRole(tpAniSirGlobal pMac) +{ + v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WMA, NULL); + t_wma_handle *wmaContext = + vos_get_context(VOS_MODULE_ID_WMA, pVosContext); + if(NULL == wmaContext) + { + VOS_TRACE( VOS_MODULE_ID_WMA, VOS_TRACE_LEVEL_ERROR, + "%s:WMA context is NULL", __func__); + VOS_ASSERT(0); + return eSYSTEM_UNKNOWN_ROLE; + } +#ifdef FEATURE_WLAN_INTEGRATED_SOC + WMA_LOGD(" returning %d role\n",wmaContext->wmaGlobalSystemRole); +#endif /* #ifdef FEATURE_WLAN_INTEGRATED_SOC */ + return wmaContext->wmaGlobalSystemRole; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c new file mode 100644 index 000000000000..38686d5bdd04 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c @@ -0,0 +1,33004 @@ +/* + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wma.c + \brief Implementation of WMA + + ========================================================================*/ +/**========================================================================= + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- ----------------------------------------- + 12/03/2013 Ganesh Implementation of WMA APIs. + Kondabattini + 27/03/2013 Ganesh Rx Management Support added + Babu + ==========================================================================*/ + +/* ################ Header files ################ */ +#include "wma.h" +#include "wma_api.h" +#include "vos_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wniApi.h" +#include "aniGlobal.h" +#include "wmi_unified.h" +#include "wniCfgAp.h" +#include "cfgApi.h" +#include "ol_txrx_ctrl_api.h" +#if defined(CONFIG_HL_SUPPORT) +#include "wlan_tgt_def_config_hl.h" +#else +#include "wlan_tgt_def_config.h" +#endif + +#if defined(QCA_IBSS_SUPPORT) +#include "wlan_hdd_assoc.h" +#endif + +#include "adf_nbuf.h" +#include "adf_os_types.h" +#include "ol_txrx_api.h" +#include "vos_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wlan_qct_wda.h" +#include "wlan_qct_wda_msg.h" +#include "limApi.h" +#include "limSessionUtils.h" + +#include "wdi_out.h" +#include "wdi_in.h" + +#include "vos_utils.h" +#include "tl_shim.h" +#if defined(QCA_WIFI_FTM) +#include "testmode.h" +#endif + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif + +#include "dbglog_host.h" +/* FIXME: Inclusion of .c looks odd but this is how it is in internal codebase */ +#include "wmi_version_whitelist.c" +#include "csrApi.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "radar_filters.h" +#include "regdomain_common.h" + +#include "wma_ocb.h" + +/* ################### defines ################### */ +/* + * TODO: Following constant should be shared by firwmare in + * wmi_unified.h. This will be done once wmi_unified.h is updated. + */ +#define WMI_PEER_STATE_AUTHORIZED 0x2 + +#define WMA_2_4_GHZ_MAX_FREQ 3000 +#define WOW_CSA_EVENT_OFFSET 12 + +#define WMA_DEFAULT_SCAN_REQUESTER_ID 1 +#define WMI_SCAN_FINISH_EVENTS (WMI_SCAN_EVENT_START_FAILED |\ + WMI_SCAN_EVENT_COMPLETED |\ + WMI_SCAN_EVENT_DEQUEUED) +/* default value */ +#define DEFAULT_INFRA_STA_KEEP_ALIVE_PERIOD 20 +/* pdev vdev and peer stats*/ +#define FW_PDEV_STATS_SET 0x1 +#define FW_VDEV_STATS_SET 0x2 +#define FW_PEER_STATS_SET 0x4 +#define FW_STATS_SET 0x7 +/*AR9888/AR6320 noise floor approx value + * similar to the mentioned the TLSHIM + */ +#define WMA_TGT_NOISE_FLOOR_DBM (-96) + +/* + * Make sure that link monitor and keep alive + * default values should be in sync with CFG. + */ +#define WMA_LINK_MONITOR_DEFAULT_TIME_SECS 10 +#define WMA_KEEP_ALIVE_DEFAULT_TIME_SECS 5 + +#define AGC_DUMP 1 +#define CHAN_DUMP 2 +#define WD_DUMP 3 +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +#define PCIE_DUMP 4 +#endif + +/* conformance test limits */ +#define FCC 0x10 +#define MKK 0x40 +#define ETSI 0x30 + +/* Maximum Buffer length allowed for DFS phyerrors */ +#define DFS_MAX_BUF_LENGHT 4096 + +#define WMI_DEFAULT_NOISE_FLOOR_DBM (-96) + +#define WMI_MCC_MIN_CHANNEL_QUOTA 20 +#define WMI_MCC_MAX_CHANNEL_QUOTA 80 +#define WMI_MCC_MIN_NON_ZERO_CHANNEL_LATENCY 30 + +/* The maximum number of patterns that can be transmitted by the firmware + * and maximum patterns size. + */ +#define WMA_MAXNUM_PERIODIC_TX_PTRNS 6 + +#define WMI_MAX_HOST_CREDITS 2 +#define WMI_WOW_REQUIRED_CREDITS 1 + +#ifdef FEATURE_WLAN_D0WOW +#define DISABLE_PCIE_POWER_COLLAPSE 1 +#define ENABLE_PCIE_POWER_COLLAPSE 0 +#endif + +#define MAX_HT_MCS_IDX 8 +#define MAX_VHT_MCS_IDX 10 +#define INVALID_MCS_IDX 255 + +#define LINK_STATUS_LEGACY 0 +#define LINK_STATUS_VHT 0x1 +#define LINK_STATUS_MIMO 0x2 +#define LINK_SUPPORT_VHT 0x4 +#define LINK_SUPPORT_MIMO 0x8 + +#define LINK_RATE_VHT 0x3 + +#define WMA_MCC_MIRACAST_REST_TIME 400 + +#define WMA_LOG_COMPLETION_TIMER 10000 /* 10 seconds */ + +#ifdef FEATURE_WLAN_SCAN_PNO +static int wma_nlo_scan_cmp_evt_handler(void *handle, u_int8_t *event, + u_int32_t len); +#endif + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * enum extscan_report_events_type - extscan report events type + * @EXTSCAN_REPORT_EVENTS_BUFFER_FULL: report only when scan history is % full + * @EXTSCAN_REPORT_EVENTS_EACH_SCAN: report a scan completion event after scan + * @EXTSCAN_REPORT_EVENTS_FULL_RESULTS: forward scan results + * (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events. + * Note: To keep backward compatibility, + * fire completion events regardless of REPORT_EVENTS_EACH_SCAN. + * @EXTSCAN_REPORT_EVENTS_NO_BATCH: controls batching, + * 0 => batching, 1 => no batching + */ +enum extscan_report_events_type { + EXTSCAN_REPORT_EVENTS_BUFFER_FULL = 0x00, + EXTSCAN_REPORT_EVENTS_EACH_SCAN = 0x01, + EXTSCAN_REPORT_EVENTS_FULL_RESULTS = 0x02, + EXTSCAN_REPORT_EVENTS_NO_BATCH = 0x04, +}; + +#define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ + +#endif + +/* Data rate 100KBPS based on IE Index */ +struct index_data_rate_type +{ + v_U8_t mcs_index; + v_U16_t ht20_rate[2]; + v_U16_t ht40_rate[2]; +}; + +#ifdef WLAN_FEATURE_11AC +struct index_vht_data_rate_type +{ + v_U8_t mcs_index; + v_U16_t ht20_rate[2]; + v_U16_t ht40_rate[2]; + v_U16_t ht80_rate[2]; +}; +#endif + +/* MCS Based rate table */ +/* HT MCS parameters with Nss = 1 */ +static struct index_data_rate_type mcs_nss1[] = +{ + /* MCS L20 S20 L40 S40 */ + {0, {65, 72}, {135, 150 }}, + {1, {130, 144}, {270, 300 }}, + {2, {195, 217}, {405, 450 }}, + {3, {260, 289}, {540, 600 }}, + {4, {390, 433}, {815, 900 }}, + {5, {520, 578}, {1080, 1200}}, + {6, {585, 650}, {1215, 1350}}, + {7, {650, 722}, {1350, 1500}} +}; +/* HT MCS parameters with Nss = 2 */ +static struct index_data_rate_type mcs_nss2[] = +{ + /* MCS L20 S20 L40 S40 */ + {0, {130, 144}, {270, 300 }}, + {1, {260, 289}, {540, 600 }}, + {2, {390, 433}, {810, 900 }}, + {3, {520, 578}, {1080, 1200}}, + {4, {780, 867}, {1620, 1800}}, + {5, {1040, 1156}, {2160, 2400}}, + {6, {1170, 1300}, {2430, 2700}}, + {7, {1300, 1440}, {2700, 3000}} +}; + +#ifdef WLAN_FEATURE_11AC +/* MCS Based VHT rate table */ +/* MCS parameters with Nss = 1*/ +static struct index_vht_data_rate_type vht_mcs_nss1[] = +{ + /* MCS L20 S20 L40 S40 L80 S80 */ + {0, {65, 72 }, {135, 150}, {293, 325} }, + {1, {130, 144}, {270, 300}, {585, 650} }, + {2, {195, 217}, {405, 450}, {878, 975} }, + {3, {260, 289}, {540, 600}, {1170, 1300}}, + {4, {390, 433}, {810, 900}, {1755, 1950}}, + {5, {520, 578}, {1080, 1200}, {2340, 2600}}, + {6, {585, 650}, {1215, 1350}, {2633, 2925}}, + {7, {650, 722}, {1350, 1500}, {2925, 3250}}, + {8, {780, 867}, {1620, 1800}, {3510, 3900}}, + {9, {865, 960}, {1800, 2000}, {3900, 4333}} +}; + +/*MCS parameters with Nss = 2*/ +static struct index_vht_data_rate_type vht_mcs_nss2[] = +{ + /* MCS L20 S20 L40 S40 L80 S80 */ + {0, {130, 144}, {270, 300}, { 585, 650}}, + {1, {260, 289}, {540, 600}, {1170, 1300}}, + {2, {390, 433}, {810, 900}, {1755, 1950}}, + {3, {520, 578}, {1080, 1200}, {2340, 2600}}, + {4, {780, 867}, {1620, 1800}, {3510, 3900}}, + {5, {1040, 1156}, {2160, 2400}, {4680, 5200}}, + {6, {1170, 1300}, {2430, 2700}, {5265, 5850}}, + {7, {1300, 1444}, {2700, 3000}, {5850, 6500}}, + {8, {1560, 1733}, {3240, 3600}, {7020, 7800}}, + {9, {1730, 1920}, {3600, 4000}, {7800, 8667}} +}; +#endif + +static void wma_send_msg(tp_wma_handle wma_handle, u_int16_t msg_type, + void *body_ptr, u_int32_t body_val); + +#ifdef QCA_IBSS_SUPPORT +static void wma_data_tx_ack_comp_hdlr(void *wma_context, + adf_nbuf_t netbuf, + int32_t status); +#endif +static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, + tpDelStaSelfParams pdel_sta_self_req_param, + u_int8_t generateRsp); +static int32_t wmi_unified_vdev_stop_send(wmi_unified_t wmi, u_int8_t vdev_id); + +static tANI_U32 gFwWlanFeatCaps; + +static eHalStatus wma_set_ppsconfig(tANI_U8 vdev_id, tANI_U16 pps_param, + int value); +static eHalStatus wma_set_mimops(tp_wma_handle wma_handle, + tANI_U8 vdev_id, int value); +#ifdef FEATURE_WLAN_TDLS +static int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams); +static int wma_update_tdls_peer_state(WMA_HANDLE handle, + tTdlsPeerStateParams *peerStateParams); +static int wma_set_tdls_offchan_mode(WMA_HANDLE wma_handle, + tTdlsChanSwitchParams *pChanSwitchParams); +#endif + +static eHalStatus wma_set_smps_params(tp_wma_handle wma_handle, + tANI_U8 vdev_id, int value); +#if defined(QCA_WIFI_FTM) +void wma_utf_attach(tp_wma_handle wma_handle); +void wma_utf_detach(tp_wma_handle wma_handle); +static VOS_STATUS +wma_process_ftm_command(tp_wma_handle wma_handle, + struct ar6k_testmode_cmd_data *msg_buffer); +#endif + +static VOS_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, u8 peer_addr[6], + u_int32_t peer_type, u_int8_t vdev_id, + v_BOOL_t roam_synch_in_progress); +static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, + tpAddStaSelfParams self_sta_req, + u_int8_t generateRsp); +static void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info); + +/*DFS Attach*/ +struct ieee80211com* wma_dfs_attach(struct ieee80211com *ic); +static void wma_dfs_detach(struct ieee80211com *ic); +static void wma_set_bss_rate_flags(struct wma_txrx_node *iface, + tpAddBssParams add_bss); +/*Configure DFS with radar tables and regulatory domain*/ +void wma_dfs_configure(struct ieee80211com *ic); + +/*Configure the current channel with the DFS*/ +struct ieee80211_channel * +wma_dfs_configure_channel(struct ieee80211com *dfs_ic, + wmi_channel *chan, + WLAN_PHY_MODE chanmode, + struct wma_vdev_start_req *req); + +/* VDEV UP */ +static int +wmi_unified_vdev_up_send(wmi_unified_t wmi, + u_int8_t vdev_id, u_int16_t aid, + u_int8_t bssid[IEEE80211_ADDR_LEN]); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void wma_process_roam_synch_complete(WMA_HANDLE handle, + tSirSmeRoamOffloadSynchCnf *synchcnf); +void wma_process_roam_synch_fail(WMA_HANDLE handle, + tSirRoamOffloadSynchFail *synchfail); +#endif + +static VOS_STATUS wma_set_thermal_mgmt(tp_wma_handle wma_handle, + t_thermal_cmd_params thermal_info); + +#ifdef FEATURE_WLAN_CH_AVOID +VOS_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle, + tSirChAvoidUpdateReq *ch_avoid_update_req); +#endif /* FEATURE_WLAN_CH_AVOID */ + +static void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info); + +static void wma_beacon_miss_handler(tp_wma_handle wma, u_int32_t vdev_id, + uint32_t rssi); +static void wma_set_suspend_dtim(tp_wma_handle wma); +static void wma_set_resume_dtim(tp_wma_handle wma); +static int wma_roam_event_callback(WMA_HANDLE handle, u_int8_t *event_buf, + u_int32_t len); +static VOS_STATUS wma_stop_scan(tp_wma_handle wma_handle, + tAbortScanParams *abort_scan_req); + +static void wma_set_sap_keepalive(tp_wma_handle wma, u_int8_t vdev_id); +static int wma_smps_force_mode_callback(WMA_HANDLE handle, uint8_t *event_buf, + uint32_t len); + +static void *wma_find_vdev_by_addr(tp_wma_handle wma, u_int8_t *addr, + u_int8_t *vdev_id) +{ + u_int8_t i; + + for (i = 0; i < wma->max_bssid; i++) { + if (vos_is_macaddr_equal( + (v_MACADDR_t *) wma->interfaces[i].addr, + (v_MACADDR_t *) addr) == VOS_TRUE) { + *vdev_id = i; + return wma->interfaces[i].handle; + } + } + return NULL; +} + +/* + * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": + * 0 for no restriction + * 1 for 1/4 us - Our lower layer calculations limit our precision to 1 msec + * 2 for 1/2 us - Our lower layer calculations limit our precision to 1 msec + * 3 for 1 us + * 4 for 2 us + * 5 for 4 us + * 6 for 8 us + * 7 for 16 us + */ +static const u_int8_t wma_mpdu_spacing[] = {0, 1, 1, 1, 2, 4, 8, 16}; + +static inline uint8_t wma_parse_mpdudensity(u_int8_t mpdudensity) +{ + if (mpdudensity < sizeof(wma_mpdu_spacing)) + return wma_mpdu_spacing[mpdudensity]; + else + return 0; +} + +/* Function : wma_find_vdev_by_id + * Description : Returns vdev handle for given vdev id. + * Args : @wma - wma handle, @vdev_id - vdev ID + * Returns : Returns vdev handle if given vdev id is valid. + * Otherwise returns NULL. + */ +static inline void *wma_find_vdev_by_id(tp_wma_handle wma, u_int8_t vdev_id) +{ + if (vdev_id > wma->max_bssid) + return NULL; + + return wma->interfaces[vdev_id].handle; +} + +/* Function : wma_get_vdev_count + * Discription : Returns number of active vdev. + * Args : @wma - wma handle + * Returns : Returns valid vdev count. + */ +static inline u_int8_t wma_get_vdev_count(tp_wma_handle wma) +{ + u_int8_t vdev_count = 0, i; + + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].handle) + vdev_count++; + } + return vdev_count; +} + +/* Function : wma_is_vdev_in_ap_mode + * Description : Helper function to know whether given vdev id + * is in AP mode or not. + * Args : @wma - wma handle, @ vdev_id - vdev ID. + * Returns : True - if given vdev id is in AP mode. + * False - if given vdev id is not in AP mode. + */ +static bool wma_is_vdev_in_ap_mode(tp_wma_handle wma, u_int8_t vdev_id) +{ + struct wma_txrx_node *intf = wma->interfaces; + + if (vdev_id > wma->max_bssid) { + WMA_LOGP("%s: Invalid vdev_id %hu", __func__, vdev_id); + VOS_ASSERT(0); + return false; + } + + if ((intf[vdev_id].type == WMI_VDEV_TYPE_AP) && + ((intf[vdev_id].sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO) || + (intf[vdev_id].sub_type == 0))) + return true; + + return false; +} + +#ifdef QCA_IBSS_SUPPORT +/* Function : wma_is_vdev_in_ibss_mode + s_vdev_in_ibss_mode* Description : Helper function to know whether given vdev id + * is in IBSS mode or not. + * Args : @wma - wma handle, @ vdev_id - vdev ID. + * Retruns : True - if given vdev id is in IBSS mode. + * False - if given vdev id is not in IBSS mode. + */ +static bool wma_is_vdev_in_ibss_mode(tp_wma_handle wma, u_int8_t vdev_id) +{ + struct wma_txrx_node *intf = wma->interfaces; + + if (vdev_id > wma->max_bssid) { + WMA_LOGP("%s: Invalid vdev_id %hu", __func__, vdev_id); + VOS_ASSERT(0); + return false; + } + + if (intf[vdev_id].type == WMI_VDEV_TYPE_IBSS) + return true; + + return false; +} +#endif + +/* + * Function : wma_find_bssid_by_vdev_id + * Description : Get the BSS ID corresponding to the vdev ID + * Args : @wma - wma handle, @vdev_id - vdev ID + * Returns : Returns pointer to bssid on success, + * otherwise returns NULL. + */ +static inline u_int8_t *wma_find_bssid_by_vdev_id(tp_wma_handle wma, + u_int8_t vdev_id) +{ + if (vdev_id >= wma->max_bssid) + return NULL; + + return wma->interfaces[vdev_id].bssid; +} + +/* + * Function : wma_find_vdev_by_bssid + * Description : Get the VDEV ID corresponding from BSS ID + * Args : @wma - wma handle, @vdev_id - vdev ID + * Returns : Returns pointer to bssid on success, + * otherwise returns NULL. + */ +static void *wma_find_vdev_by_bssid(tp_wma_handle wma, u_int8_t *bssid, + u_int8_t *vdev_id) +{ + int i; + + for (i = 0; i < wma->max_bssid; i++) { + if (vos_is_macaddr_equal( + (v_MACADDR_t *)wma->interfaces[i].bssid, + (v_MACADDR_t *)bssid) == VOS_TRUE) { + *vdev_id = i; + return wma->interfaces[i].handle; + } + } + + return NULL; +} + +#ifdef BIG_ENDIAN_HOST + +/* ############# function definitions ############ */ + +/* function : wma_swap_bytes + * Description : + * Args : + * Retruns : + */ +v_VOID_t wma_swap_bytes(v_VOID_t *pv, v_SIZE_t n) +{ + v_SINT_t no_words; + v_SINT_t i; + v_U32_t *word_ptr; + + no_words = n/sizeof(v_U32_t); + word_ptr = (v_U32_t *)pv; + for (i=0; ivdev_respq_lock); + list_for_each_entry_safe(req_msg, tmp, + &wma->vdev_resp_queue, node) { + if (req_msg->vdev_id != vdev_id) + continue; + if (req_msg->type != type) + continue; + + found = true; + list_del(&req_msg->node); + break; + } + adf_os_spin_unlock_bh(&wma->vdev_respq_lock); + if (!found) { + WMA_LOGP("%s: target request not found for vdev_id %d type %d", + __func__, vdev_id, type); + return NULL; + } + WMA_LOGD("%s: target request found for vdev id: %d type %d msg %d", + __func__, vdev_id, type, req_msg->msg_type); + return req_msg; +} + +/** + * wma_peek_vdev_req() - peek what request message is queued for response. + * the function does not delete the node after found + * @wma: WMA handle + * @vdev_id: vdev ID + * @type: request message type + * + * Return: the request message found + */ +static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma, + uint8_t vdev_id, + uint8_t type) +{ + struct wma_target_req *req_msg = NULL, *tmp; + bool found = false; + + adf_os_spin_lock_bh(&wma->vdev_respq_lock); + list_for_each_entry_safe(req_msg, tmp, &wma->vdev_resp_queue, node) { + if (req_msg->vdev_id != vdev_id) + continue; + if (req_msg->type != type) + continue; + + found = true; + break; + } + adf_os_spin_unlock_bh(&wma->vdev_respq_lock); + if (!found) { + WMA_LOGP("%s: target request not found for vdev_id %d type %d", + __func__, vdev_id, type); + return NULL; + } + WMA_LOGD("%s: target request found for vdev id: %d type %d msg %d", + __func__, vdev_id, type, req_msg->msg_type); + return req_msg; +} + +/** + * wma_lost_link_info_handler() - collect lost link information and inform SME + * when disconnection in STA mode. + * @wma: WMA handle + * @vdev_id: vdev ID + * @rssi: rssi at disconnection time + * + * Return: none + */ +static void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id, + int8_t rssi) +{ + struct sir_lost_link_info *lost_link_info; + VOS_STATUS vos_status; + vos_msg_t sme_msg = {0}; + + /* report lost link information only for STA mode */ + if (wma->interfaces[vdev_id].vdev_up && + (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) && + (0 == wma->interfaces[vdev_id].sub_type)) { + lost_link_info = vos_mem_malloc(sizeof(*lost_link_info)); + if (NULL == lost_link_info) { + WMA_LOGE("%s: failed to allocate memory", __func__); + return; + } + lost_link_info->vdev_id = vdev_id; + lost_link_info->rssi = rssi; + sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND; + sme_msg.bodyptr = lost_link_info; + sme_msg.bodyval = 0; + WMA_LOGI("%s: post msg to SME, bss_idx %d, rssi %d", + __func__, + lost_link_info->vdev_id, + lost_link_info->rssi); + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE("%s: fail to post msg to SME", + __func__); + vos_mem_free(lost_link_info); + } + } +} + +tSmpsModeValue host_map_smps_mode (A_UINT32 fw_smps_mode) +{ + tSmpsModeValue smps_mode = SMPS_MODE_DISABLED; + switch (fw_smps_mode) { + case WMI_SMPS_FORCED_MODE_STATIC: + smps_mode = STATIC_SMPS_MODE; + break; + case WMI_SMPS_FORCED_MODE_DYNAMIC: + smps_mode = DYNAMIC_SMPS_MODE; + break; + default: + smps_mode = SMPS_MODE_DISABLED; + } + + return smps_mode; +} + +/** + * wma_smps_mode_to_force_mode_param() - Map smps mode to force + * mode commmand param + * @smps_mode: SMPS mode according to the protocol + * + * Return: int > 0 for success else failure + */ +static int wma_smps_mode_to_force_mode_param(uint8_t smps_mode) +{ + int param = -EINVAL; + + switch (smps_mode) { + case STATIC_SMPS_MODE: + param = WMI_SMPS_FORCED_MODE_STATIC; + break; + case DYNAMIC_SMPS_MODE: + param = WMI_SMPS_FORCED_MODE_DYNAMIC; + break; + case SMPS_MODE_DISABLED: + param = WMI_SMPS_FORCED_MODE_DISABLED; + break; + default: + WMA_LOGE(FL("smps mode cannot be mapped :%d "), + smps_mode); + } + return param; +} + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +/* function : wma_post_auto_shutdown_msg + * Description : function to post auto shutdown event to sme + */ +static int wma_post_auto_shutdown_msg(void) +{ + tSirAutoShutdownEvtParams *auto_sh_evt; + VOS_STATUS vos_status; + vos_msg_t sme_msg = {0} ; + + auto_sh_evt = (tSirAutoShutdownEvtParams *) + vos_mem_malloc(sizeof(tSirAutoShutdownEvtParams)); + if (!auto_sh_evt) { + WMA_LOGE("%s: No Mem", __func__); + return -ENOMEM; + } + + auto_sh_evt->shutdown_reason = + WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY; + sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND; + sme_msg.bodyptr = auto_sh_evt; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if ( !VOS_IS_STATUS_SUCCESS(vos_status) ) { + WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME"); + vos_mem_free(auto_sh_evt); + return -EINVAL; + } + + return 0; +} + +/* function : wma_auto_shutdown_event_handler + * Description : function to process auto shutdown timer trigger + */ +static int wma_auto_shutdown_event_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt; + WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf = + (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *) + event; + + if (!param_buf || !param_buf->fixed_param) { + WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__, + __LINE__); + return -EINVAL; + } + + + wmi_auto_sh_evt = param_buf->fixed_param; + + if (wmi_auto_sh_evt->shutdown_reason + != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) { + WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__, + __LINE__); + return -EINVAL; + } + + WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__, + wmi_auto_sh_evt->shutdown_reason); + return(wma_post_auto_shutdown_msg()); +} + +/* function : wma_set_auto_shutdown_timer_req + * Description : function sets auto shutdown timer in firmware + * Args : wma handle, auto shutdown timer value + * Returns : status of wmi cmd + */ +static VOS_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle, + tSirAutoShutdownCmdParams *auto_sh_cmd) +{ + int status = 0; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_host_auto_shutdown_cfg_cmd_fixed_param *wmi_auto_sh_cmd; + int len = sizeof(wmi_host_auto_shutdown_cfg_cmd_fixed_param); + + if (auto_sh_cmd == NULL) { + WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("%s: Set WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID:TIMER_VAL=%d", + __func__, auto_sh_cmd->timer_val); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + wmi_auto_sh_cmd = (wmi_host_auto_shutdown_cfg_cmd_fixed_param *)buf_ptr; + wmi_auto_sh_cmd->timer_value = auto_sh_cmd->timer_val; + + WMITLV_SET_HDR(&wmi_auto_sh_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_host_auto_shutdown_cfg_cmd_fixed_param)); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID); + if (status != EOK) { + WMA_LOGE("%s: WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID Err %d", + __func__, status); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} +#endif + +static void wma_vdev_start_rsp(tp_wma_handle wma, + tpAddBssParams add_bss, + wmi_vdev_start_response_event_fixed_param *resp_event) +{ + struct beacon_info *bcn; + +#ifdef QCA_IBSS_SUPPORT + WMA_LOGD("%s: vdev start response received for %s mode", __func__, + add_bss->operMode == BSS_OPERATIONAL_MODE_IBSS ? "IBSS" : "non-IBSS"); +#endif + + if (resp_event->status) { + add_bss->status = VOS_STATUS_E_FAILURE; + goto send_fail_resp; + } + + if ((add_bss->operMode == BSS_OPERATIONAL_MODE_AP) +#ifdef QCA_IBSS_SUPPORT + || (add_bss->operMode == BSS_OPERATIONAL_MODE_IBSS) +#endif + ) { + wma->interfaces[resp_event->vdev_id].beacon = + vos_mem_malloc(sizeof(struct beacon_info)); + + bcn = wma->interfaces[resp_event->vdev_id].beacon; + if (!bcn) { + WMA_LOGE("%s: Failed alloc memory for beacon struct", + __func__); + add_bss->status = VOS_STATUS_E_FAILURE; + goto send_fail_resp; + } + vos_mem_zero(bcn, sizeof(*bcn)); + bcn->buf = adf_nbuf_alloc(NULL, WMA_BCN_BUF_MAX_SIZE, 0, + sizeof(u_int32_t), 0); + if (!bcn->buf) { + WMA_LOGE("%s: No memory allocated for beacon buffer", + __func__); + vos_mem_free(bcn); + add_bss->status = VOS_STATUS_E_FAILURE; + goto send_fail_resp; + } + bcn->seq_no = MIN_SW_SEQ; + adf_os_spinlock_init(&bcn->lock); + adf_os_atomic_set(&wma->interfaces[resp_event->vdev_id].bss_status, + WMA_BSS_STATUS_STARTED); + WMA_LOGD("%s: AP mode (type %d subtype %d) BSS is started", __func__, + wma->interfaces[resp_event->vdev_id].type, + wma->interfaces[resp_event->vdev_id].sub_type); + + WMA_LOGD("%s: Allocated beacon struct %p, template memory %p", + __func__, bcn, bcn->buf); + } + add_bss->status = VOS_STATUS_SUCCESS; + add_bss->bssIdx = resp_event->vdev_id; + add_bss->chainMask = resp_event->chain_mask; + add_bss->smpsMode = host_map_smps_mode(resp_event->smps_mode); +send_fail_resp: + WMA_LOGD("%s: Sending add bss rsp to umac(vdev %d status %d)", + __func__, resp_event->vdev_id, add_bss->status); + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)add_bss, 0); +} + +static int wma_vdev_start_resp_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_VDEV_START_RESP_EVENTID_param_tlvs *param_buf; + wmi_vdev_start_response_event_fixed_param *resp_event; + u_int8_t *buf; + vos_msg_t vos_msg = {0}; + tp_wma_handle wma = (tp_wma_handle) handle; + + WMA_LOGI("%s: Enter", __func__); + param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid start response event buffer"); + return -EINVAL; + } + + resp_event = param_buf->fixed_param; + buf = vos_mem_malloc(sizeof(wmi_vdev_start_response_event_fixed_param)); + if (!buf) { + WMA_LOGE("%s: Failed alloc memory for buf", __func__); + return -EINVAL; + } + + if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id)) { + adf_os_spin_lock_bh(&wma->dfs_ic->chan_lock); + wma->dfs_ic->disable_phy_err_processing = false; + adf_os_spin_unlock_bh(&wma->dfs_ic->chan_lock); + } + + vos_mem_zero(buf, sizeof(wmi_vdev_start_response_event_fixed_param)); + vos_mem_copy(buf, (u_int8_t *)resp_event, + sizeof(wmi_vdev_start_response_event_fixed_param)); + + vos_msg.type = WDA_VDEV_START_RSP_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_VDEV_START_RSP_IND msg", __func__); + vos_mem_free(buf); + return -1; + } + WMA_LOGD("WDA_VDEV_START_RSP_IND posted"); + return 0; +} + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * wma_find_mcc_ap() - finds if device is operating AP in MCC mode or not + * @wma: wma handle. + * @vdev_id: vdev ID of device for which MCC has to be checked + * @add: flag indicating if current device is added or deleted + * + * This function parses through all the interfaces in wma and finds if + * any of those devces are in MCC mode with AP. If such a vdev is found + * involved AP vdevs are sent WDA_UPDATE_Q2Q_IE_IND msg to update their + * beacon template to include Q2Q IE. + * + * Return: void + */ +void wma_find_mcc_ap(tp_wma_handle wma, + uint8_t vdev_id, + bool add) +{ + uint8_t i; + uint16_t prev_ch_freq = 0; + bool is_ap = false; + bool result = false; + uint8_t * ap_vdev_ids = NULL; + uint8_t num_ch = 0; + + ap_vdev_ids = vos_mem_malloc(wma->max_bssid); + if (!ap_vdev_ids) { + return; + } + + for(i = 0; i < wma->max_bssid; i++) { + ap_vdev_ids[i] = -1; + if( add == false && i == vdev_id) + continue; + + if( wma->interfaces[i].vdev_up || (i == vdev_id && add) ) { + + if(wma->interfaces[i].type == WMI_VDEV_TYPE_AP) { + is_ap = true; + ap_vdev_ids[i] = i; + } + + if(wma->interfaces[i].mhz != prev_ch_freq) { + num_ch++; + prev_ch_freq = wma->interfaces[i].mhz; + } + } + } + + if( is_ap && (num_ch > 1) ) + result = true; + else + result = false; + + wma_send_msg(wma, WDA_UPDATE_Q2Q_IE_IND, (void*)ap_vdev_ids, result); +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +static const wmi_channel_width mode_to_width[MODE_MAX] = +{ + [MODE_11A] = WMI_CHAN_WIDTH_20, + [MODE_11G] = WMI_CHAN_WIDTH_20, + [MODE_11B] = WMI_CHAN_WIDTH_20, + [MODE_11GONLY] = WMI_CHAN_WIDTH_20, + [MODE_11NA_HT20] = WMI_CHAN_WIDTH_20, + [MODE_11NG_HT20] = WMI_CHAN_WIDTH_20, + [MODE_11AC_VHT20] = WMI_CHAN_WIDTH_20, + [MODE_11AC_VHT20_2G] = WMI_CHAN_WIDTH_20, + [MODE_11NA_HT40] = WMI_CHAN_WIDTH_40, + [MODE_11NG_HT40] = WMI_CHAN_WIDTH_40, + [MODE_11AC_VHT40] = WMI_CHAN_WIDTH_40, + [MODE_11AC_VHT40_2G] = WMI_CHAN_WIDTH_40, + [MODE_11AC_VHT80] = WMI_CHAN_WIDTH_80, +#if CONFIG_160MHZ_SUPPORT + [MODE_11AC_VHT80_80] = WMI_CHAN_WIDTH_80P80, + [MODE_11AC_VHT160] = WMI_CHAN_WIDTH_160, +#endif +}; + +/** + * chanmode_to_chanwidth() - get channel width through channel mode + * @chanmode: channel phy mode + * + * Return: channel width + */ +static wmi_channel_width chanmode_to_chanwidth(WLAN_PHY_MODE chanmode) +{ + wmi_channel_width chan_width; + + if (chanmode >= MODE_11A && chanmode < MODE_MAX) + chan_width = mode_to_width[chanmode]; + else + chan_width = WMI_CHAN_WIDTH_20; + + return chan_width; +} + +static int wma_vdev_start_rsp_ind(tp_wma_handle wma, u_int8_t *buf) +{ + struct wma_target_req *req_msg; + struct wma_txrx_node *iface; + int err; + wmi_channel_width chanwidth; + + wmi_vdev_start_response_event_fixed_param *resp_event; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)vos_get_context( + VOS_MODULE_ID_PE, + wma->vos_context); + if (NULL == mac_ctx) { + WMA_LOGE("%s: Failed to get mac_ctx", __func__); + return -EINVAL; + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + resp_event = (wmi_vdev_start_response_event_fixed_param *)buf; + + if (!resp_event) { + WMA_LOGE("Invalid start response event buffer"); + return -EINVAL; + } + + if ((resp_event->vdev_id <= wma->max_bssid) && + (adf_os_atomic_read( + &wma->interfaces[resp_event->vdev_id].vdev_restart_params.hidden_ssid_restart_in_progress)) && + (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == true)) { + WMA_LOGE( + "%s: vdev restart event recevied for hidden ssid set using IOCTL", + __func__); + + if (wmi_unified_vdev_up_send(wma->wmi_handle, resp_event->vdev_id, 0, + wma->interfaces[resp_event->vdev_id].bssid) < 0) { + WMA_LOGE("%s : failed to send vdev up", __func__); + return -EEXIST; + } + adf_os_atomic_set( + &wma->interfaces[resp_event->vdev_id].vdev_restart_params.hidden_ssid_restart_in_progress, 0); + wma->interfaces[resp_event->vdev_id].vdev_up = TRUE; + } + + req_msg = wma_find_vdev_req(wma, resp_event->vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + + if (!req_msg) { + WMA_LOGE("%s: Failed to lookup request message for vdev %d", + __func__, resp_event->vdev_id); + return -EINVAL; + } + + vos_timer_stop(&req_msg->event_timeout); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if (resp_event->status == VOS_STATUS_SUCCESS + && mac_ctx->sap.sap_channel_avoidance) + wma_find_mcc_ap(wma, resp_event->vdev_id, true); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + iface = &wma->interfaces[resp_event->vdev_id]; + if (req_msg->msg_type == WDA_CHNL_SWITCH_REQ) { + tpSwitchChannelParams params = + (tpSwitchChannelParams) req_msg->user_data; + if(!params) { + WMA_LOGE("%s: channel switch params is NULL for vdev %d", + __func__, resp_event->vdev_id); + return -EINVAL; + } + + WMA_LOGD("%s: Send channel switch resp vdev %d status %d", + __func__, resp_event->vdev_id, resp_event->status); + params->chainMask = resp_event->chain_mask; + params->smpsMode = host_map_smps_mode(resp_event->smps_mode); + params->status = resp_event->status; + if (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT && + (iface->type == WMI_VDEV_TYPE_STA)) { + + err = wma_set_peer_param(wma, iface->bssid, + WMI_PEER_PHYMODE, iface->chanmode, + resp_event->vdev_id); + + WMA_LOGD("%s:vdev_id %d chanmode %d status %d", + __func__, resp_event->vdev_id, + iface->chanmode, err); + + chanwidth = chanmode_to_chanwidth(iface->chanmode); + err = wma_set_peer_param(wma, iface->bssid, + WMI_PEER_CHWIDTH, chanwidth, + resp_event->vdev_id); + + WMA_LOGD("%s:vdev_id %d chanwidth %d status %d", + __func__, resp_event->vdev_id, + chanwidth, err); + + if (wmi_unified_vdev_up_send(wma->wmi_handle, + resp_event->vdev_id, iface->aid, + iface->bssid)) { + WMA_LOGE("%s:vdev_up failed vdev_id %d", + __func__, resp_event->vdev_id); + wma->interfaces[resp_event->vdev_id].vdev_up = + FALSE; + } else { + wma->interfaces[resp_event->vdev_id].vdev_up = + TRUE; + } + } + + wma_send_msg(wma, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); + } else if (req_msg->msg_type == WDA_ADD_BSS_REQ) { + tpAddBssParams bssParams = (tpAddBssParams) req_msg->user_data; + vos_mem_copy(iface->bssid, bssParams->bssId, ETH_ALEN); + wma_vdev_start_rsp(wma, bssParams, resp_event); + } else if (req_msg->msg_type == WDA_OCB_SET_CONFIG_CMD) { + if (wmi_unified_vdev_up_send(wma->wmi_handle, + resp_event->vdev_id, iface->aid, + iface->bssid) < 0) { + WMA_LOGE(FL("failed to send vdev up")); + return -EEXIST; + } + iface->vdev_up = TRUE; + + wma_ocb_start_resp_ind_cont(wma); + } + + + if ((wma->interfaces[resp_event->vdev_id].type == WMI_VDEV_TYPE_AP) && + wma->interfaces[resp_event->vdev_id].vdev_up) + wma_set_sap_keepalive(wma, resp_event->vdev_id); + + vos_timer_destroy(&req_msg->event_timeout); + adf_os_mem_free(req_msg); + + return 0; +} + +/* function : wma_unified_debug_print_event_handler + * Description : + * Args : + * Returns : + */ +static int wma_unified_debug_print_event_handler(void *handle, u_int8_t *datap, + u_int32_t len) +{ + WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf; + u_int8_t *data; + u_int32_t datalen; + + param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *)datap; + if (!param_buf) { + WMA_LOGE("Get NULL point message from FW"); + return -ENOMEM; + } + data = param_buf->data; + datalen = param_buf->num_data; + +#ifdef BIG_ENDIAN_HOST + { + char dbgbuf[500] = {0}; + memcpy(dbgbuf, data, datalen); + SWAPME(dbgbuf, datalen); + WMA_LOGD("FIRMWARE:%s", dbgbuf); + return 0; + } +#else + WMA_LOGD("FIRMWARE:%s", data); + return 0; +#endif +} + +static int +wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, u_int32_t if_id, + u_int32_t param_id, u_int32_t param_value) +{ + int ret; + wmi_vdev_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_vdev_set_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_set_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_set_param_cmd_fixed_param)); + cmd->vdev_id = if_id; + cmd->param_id = param_id; + cmd->param_value = param_value; + WMA_LOGD("Setting vdev %d param = %x, value = %u", + if_id, param_id, param_value); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_VDEV_SET_PARAM_CMDID); + if (ret < 0) { + WMA_LOGE("Failed to send set param command ret = %d", ret); + wmi_buf_free(buf); + } + return ret; +} + +VOS_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle, + A_INT32 first_bcnt, + A_UINT32 final_bcnt, + u_int32_t vdev_id) +{ + int status = 0; + + WMA_LOGI("%s: first_bcnt=%d, final_bcnt=%d", __func__, + first_bcnt, final_bcnt); + + status = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + vdev_id, + WMI_VDEV_PARAM_BMISS_FIRST_BCNT, + first_bcnt); + if (status != EOK) { + WMA_LOGE("wmi_unified_vdev_set_param_send" + "WMI_VDEV_PARAM_BMISS_FIRST_BCNT returned Error %d",status); + return VOS_STATUS_E_FAILURE; + } + + status = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + vdev_id, + WMI_VDEV_PARAM_BMISS_FINAL_BCNT, + final_bcnt); + if (status != EOK) { + WMA_LOGE("wmi_unified_vdev_set_param_send" + "WMI_VDEV_PARAM_BMISS_FINAL_BCNT returned Error %d",status); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +static v_VOID_t wma_set_default_tgt_config(tp_wma_handle wma_handle) +{ + struct ol_softc *scn; + u_int8_t no_of_peers_supported; + wmi_resource_config tgt_cfg = { + 0, /* Filling zero for TLV Tag and Length fields */ + CFG_TGT_NUM_VDEV, + CFG_TGT_NUM_PEERS + CFG_TGT_NUM_VDEV + 2, + CFG_TGT_NUM_OFFLOAD_PEERS, + CFG_TGT_NUM_OFFLOAD_REORDER_BUFFS, + CFG_TGT_NUM_PEER_KEYS, + CFG_TGT_NUM_TIDS, + CFG_TGT_AST_SKID_LIMIT, + CFG_TGT_DEFAULT_TX_CHAIN_MASK, + CFG_TGT_DEFAULT_RX_CHAIN_MASK, + { CFG_TGT_RX_TIMEOUT_LO_PRI, CFG_TGT_RX_TIMEOUT_LO_PRI, CFG_TGT_RX_TIMEOUT_LO_PRI, CFG_TGT_RX_TIMEOUT_HI_PRI }, + CFG_TGT_RX_DECAP_MODE, + CFG_TGT_DEFAULT_SCAN_MAX_REQS, + CFG_TGT_DEFAULT_BMISS_OFFLOAD_MAX_VDEV, + CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_VDEV, + CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_PROFILES, + CFG_TGT_DEFAULT_NUM_MCAST_GROUPS, + CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS, + CFG_TGT_DEFAULT_MCAST2UCAST_MODE, + CFG_TGT_DEFAULT_TX_DBG_LOG_SIZE, + CFG_TGT_WDS_ENTRIES, + CFG_TGT_DEFAULT_DMA_BURST_SIZE, + CFG_TGT_DEFAULT_MAC_AGGR_DELIM, + CFG_TGT_DEFAULT_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK, + CFG_TGT_DEFAULT_VOW_CONFIG, + CFG_TGT_DEFAULT_GTK_OFFLOAD_MAX_VDEV, + CFG_TGT_NUM_MSDU_DESC, + CFG_TGT_MAX_FRAG_TABLE_ENTRIES, + CFG_TGT_NUM_TDLS_VDEVS, + CFG_TGT_NUM_TDLS_CONN_TABLE_ENTRIES, + CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV, + CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES, + 0, + 0, + 0, + CFG_TGT_NUM_TDLS_CONC_SLEEP_STAS, + CFG_TGT_NUM_TDLS_CONC_BUFFER_STAS, + 0, + CFG_TGT_NUM_OCB_VDEVS, + CFG_TGT_NUM_OCB_CHANNELS, + CFG_TGT_NUM_OCB_SCHEDULES, + }; + + /* Update the max number of peers */ + scn = vos_get_context(VOS_MODULE_ID_HIF, wma_handle->vos_context); + if (!scn) { + WMA_LOGE("%s: vos_context is NULL", __func__); + return; + } + no_of_peers_supported = ol_get_number_of_peers_supported(scn); + tgt_cfg.num_peers = no_of_peers_supported + CFG_TGT_NUM_VDEV + 2; + tgt_cfg.num_tids = (2 * (no_of_peers_supported + CFG_TGT_NUM_VDEV + 2)); + + WMITLV_SET_HDR(&tgt_cfg.tlv_header,WMITLV_TAG_STRUC_wmi_resource_config, + WMITLV_GET_STRUCT_TLVLEN(wmi_resource_config)); + /* reduce the peer/vdev if CFG_TGT_NUM_MSDU_DESC exceeds 1000 */ +#ifdef PERE_IP_HDR_ALIGNMENT_WAR + if (scn->host_80211_enable) { + /* + * To make the IP header begins at dword aligned address, + * we make the decapsulation mode as Native Wifi. + */ + tgt_cfg.rx_decap_mode = CFG_TGT_RX_DECAP_MODE_NWIFI; + } +#endif + wma_handle->wlan_resource_config = tgt_cfg; +} + +static int32_t wmi_unified_peer_delete_send(wmi_unified_t wmi, + u_int8_t peer_addr[IEEE80211_ADDR_LEN], + u_int8_t vdev_id) +{ + wmi_peer_delete_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_peer_delete_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_delete_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_peer_delete_cmd_fixed_param)); + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr); + cmd->vdev_id = vdev_id; + + if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_DELETE_CMDID)) { + WMA_LOGP("%s: Failed to send peer delete command", __func__); + adf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); + return 0; +} + +static int32_t wmi_unified_peer_flush_tids_send(wmi_unified_t wmi, + u_int8_t peer_addr + [IEEE80211_ADDR_LEN], + u_int32_t peer_tid_bitmap, + u_int8_t vdev_id) +{ + wmi_peer_flush_tids_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_peer_flush_tids_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_flush_tids_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_peer_flush_tids_cmd_fixed_param)); + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr); + cmd->peer_tid_bitmap = peer_tid_bitmap; + cmd->vdev_id = vdev_id; + + if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_FLUSH_TIDS_CMDID)) { + WMA_LOGP("%s: Failed to send flush tid command", __func__); + adf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); + return 0; +} + +static void wma_remove_peer(tp_wma_handle wma, u_int8_t *bssid, + u_int8_t vdev_id, ol_txrx_peer_handle peer, + v_BOOL_t roam_synch_in_progress) +{ +#define PEER_ALL_TID_BITMASK 0xffffffff + u_int32_t peer_tid_bitmap = PEER_ALL_TID_BITMASK; + u_int8_t *peer_addr = bssid; + if (!wma->interfaces[vdev_id].peer_count) + { + WMA_LOGE("%s: Can't remove peer with peer_addr %pM vdevid %d peer_count %d", + __func__, bssid, vdev_id, wma->interfaces[vdev_id].peer_count); + return; + } + if (peer) + ol_txrx_peer_detach(peer); + + wma->interfaces[vdev_id].peer_count--; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_synch_in_progress) { + WMA_LOGD("%s:LFR3:Removed peer with addr %pM vdevid %d peer_cnt %d", + __func__, bssid, vdev_id, wma->interfaces[vdev_id].peer_count); + return; + } else { + WMA_LOGE("%s: Removed peer with addr %pM vdevid %d peer_count %d", + __func__, bssid, vdev_id, wma->interfaces[vdev_id].peer_count); + } +#endif + /* Flush all TIDs except MGMT TID for this peer in Target */ + peer_tid_bitmap &= ~(0x1 << WMI_MGMT_TID); + wmi_unified_peer_flush_tids_send(wma->wmi_handle, bssid, + peer_tid_bitmap, vdev_id); + +#if defined(QCA_IBSS_SUPPORT) + if ((peer) && (wma_is_vdev_in_ibss_mode(wma, vdev_id))) { + WMA_LOGD("%s: bssid %pM peer->mac_addr %pM", __func__, + bssid, peer->mac_addr.raw); + peer_addr = peer->mac_addr.raw; + } +#endif + + wmi_unified_peer_delete_send(wma->wmi_handle, peer_addr, vdev_id); +#undef PEER_ALL_TID_BITMASK +} + +static int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *param_buf = NULL; + wmi_peer_sta_kickout_event_fixed_param *kickout_event = NULL; + u_int8_t vdev_id, peer_id, macaddr[IEEE80211_ADDR_LEN]; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + tpDeleteStaContext del_sta_ctx; + tpSirIbssPeerInactivityInd p_inactivity; + + WMA_LOGD("%s: Enter", __func__); + param_buf = (WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs *) event; + kickout_event = param_buf->fixed_param; + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (!pdev) { + WMA_LOGE("%s: pdev is NULL", __func__); + return -EINVAL; + } + WMI_MAC_ADDR_TO_CHAR_ARRAY(&kickout_event->peer_macaddr, macaddr); + peer = ol_txrx_find_peer_by_addr(pdev, macaddr, &peer_id); + if (!peer) { + WMA_LOGE("PEER [%pM] not found", macaddr); + return -EINVAL; + } + + if (tl_shim_get_vdevid(peer, &vdev_id) != VOS_STATUS_SUCCESS) { + WMA_LOGE("Not able to find BSSID for peer [%pM]", macaddr); + return -EINVAL; + } + + WMA_LOGA("%s: PEER:[%pM], ADDR:[%pN], INTERFACE:%d, peer_id:%d, reason:%d", + __func__, macaddr, + wma->interfaces[vdev_id].addr, vdev_id, + peer_id, kickout_event->reason); + + switch (kickout_event->reason) { + case WMI_PEER_STA_KICKOUT_REASON_IBSS_DISCONNECT: + p_inactivity = (tpSirIbssPeerInactivityInd) + vos_mem_malloc(sizeof(tSirIbssPeerInactivityInd)); + if (!p_inactivity) { + WMA_LOGE("VOS MEM Alloc Failed for tSirIbssPeerInactivity"); + return -EINVAL; + } + + p_inactivity->staIdx = peer_id; + vos_mem_copy(p_inactivity->peerAddr, macaddr, IEEE80211_ADDR_LEN); + wma_send_msg(wma, WDA_IBSS_PEER_INACTIVITY_IND, (void *)p_inactivity, 0); + goto exit_handler; + break; + +#ifdef FEATURE_WLAN_TDLS + case WMI_PEER_STA_KICKOUT_REASON_TDLS_DISCONNECT: + del_sta_ctx = + (tpDeleteStaContext)vos_mem_malloc(sizeof(tDeleteStaContext)); + if (!del_sta_ctx) { + WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM", + __func__, macaddr); + return -EINVAL; + } + + del_sta_ctx->is_tdls = true; + del_sta_ctx->vdev_id = vdev_id; + del_sta_ctx->staId = peer_id; + vos_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN); + vos_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].bssid, + IEEE80211_ADDR_LEN); + del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE; + wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx, + 0); + goto exit_handler; + break; +#endif /* FEATURE_WLAN_TDLS */ + + case WMI_PEER_STA_KICKOUT_REASON_XRETRY: + if(wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA && + (wma->interfaces[vdev_id].sub_type == 0 || + wma->interfaces[vdev_id].sub_type == + WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) && + vos_mem_compare(wma->interfaces[vdev_id].bssid, + macaddr, ETH_ALEN)) { + /* + * KICKOUT event is for current station-AP connection. + * Treat it like final beacon miss. Station may not have + * missed beacons but not able to transmit frames to AP + * for a long time. Must disconnect to get out of + * this sticky situation. + * In future implementation, roaming module will also + * handle this event and perform a scan. + */ + WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_XRETRY event for STA", + __func__); + wma_beacon_miss_handler(wma, vdev_id, kickout_event->rssi); + goto exit_handler; + } + break; + + case WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED: + /* + * Default legacy value used by original firmware implementation. + */ + if(wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA && + (wma->interfaces[vdev_id].sub_type == 0 || + wma->interfaces[vdev_id].sub_type == + WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) && + vos_mem_compare(wma->interfaces[vdev_id].bssid, + macaddr, ETH_ALEN)) { + /* + * KICKOUT event is for current station-AP connection. + * Treat it like final beacon miss. Station may not have + * missed beacons but not able to transmit frames to AP + * for a long time. Must disconnect to get out of + * this sticky situation. + * In future implementation, roaming module will also + * handle this event and perform a scan. + */ + WMA_LOGW("%s: WMI_PEER_STA_KICKOUT_REASON_UNSPECIFIED event for STA", + __func__); + wma_beacon_miss_handler(wma, vdev_id, kickout_event->rssi); + goto exit_handler; + } + break; + + case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY: + /* This could be for STA or SAP role */ + default: + break; + } + + /* + * default action is to send delete station context indication to LIM + */ + del_sta_ctx = (tpDeleteStaContext)vos_mem_malloc(sizeof(tDeleteStaContext)); + if (!del_sta_ctx) { + WMA_LOGE("VOS MEM Alloc Failed for tDeleteStaContext"); + return -EINVAL; + } + + del_sta_ctx->is_tdls = false; + del_sta_ctx->vdev_id = vdev_id; + del_sta_ctx->staId = peer_id; + vos_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN); + vos_mem_copy(del_sta_ctx->bssId, wma->interfaces[vdev_id].addr, + IEEE80211_ADDR_LEN); + del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE; + del_sta_ctx->rssi = kickout_event->rssi + WMA_TGT_NOISE_FLOOR_DBM; + wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx, 0); + wma_lost_link_info_handler(wma, vdev_id, kickout_event->rssi + + WMA_TGT_NOISE_FLOOR_DBM); + +exit_handler: + WMA_LOGD("%s: Exit", __func__); + return 0; +} + +static int wmi_unified_vdev_down_send(wmi_unified_t wmi, u_int8_t vdev_id) +{ + wmi_vdev_down_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s : wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_vdev_down_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_down_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_down_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_DOWN_CMDID)) { + WMA_LOGP("%s: Failed to send vdev down", __func__); + adf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: vdev_id %d", __func__, vdev_id); + return 0; +} + +#ifdef QCA_IBSS_SUPPORT +static void wma_delete_all_ibss_peers(tp_wma_handle wma, A_UINT32 vdev_id) +{ + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer, temp; + + if (!wma || vdev_id > wma->max_bssid) + return; + + vdev = wma->interfaces[vdev_id].handle; + if (!vdev) + return; + + /* remove all remote peers of IBSS */ + adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex); + + temp = NULL; + TAILQ_FOREACH_REVERSE(peer, &vdev->peer_list, peer_list_t, peer_list_elem) { + if (temp) { + adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); + if (adf_os_atomic_read(&temp->delete_in_progress) == 0){ + wma_remove_peer(wma, temp->mac_addr.raw, + vdev_id, temp, VOS_FALSE); + } + adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex); + } + /* self peer is deleted last */ + if (peer == TAILQ_FIRST(&vdev->peer_list)) { + WMA_LOGE("%s: self peer removed by caller ", __func__); + break; + } else + temp = peer; + } + adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); + + /* remove IBSS bss peer last */ + peer = TAILQ_FIRST(&vdev->peer_list); + wma_remove_peer(wma, wma->interfaces[vdev_id].bssid, vdev_id, peer, + VOS_FALSE); + +} +#endif //#ifdef QCA_IBSS_SUPPORT + +static void wma_delete_all_ap_remote_peers(tp_wma_handle wma, A_UINT32 vdev_id) +{ + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer, temp; + + if (!wma || vdev_id > wma->max_bssid) + return; + + vdev = wma->interfaces[vdev_id].handle; + if (!vdev) + return; + + WMA_LOGE("%s: vdev_id - %d", __func__, vdev_id); + /* remove all remote peers of SAP */ + adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex); + + temp = NULL; + TAILQ_FOREACH_REVERSE(peer, &vdev->peer_list, peer_list_t, peer_list_elem) { + if (temp) { + adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); + if (adf_os_atomic_read(&temp->delete_in_progress) == 0){ + wma_remove_peer(wma, temp->mac_addr.raw, + vdev_id, temp, VOS_FALSE); + } + adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex); + } + /* self peer is deleted by caller */ + if (peer == TAILQ_FIRST(&vdev->peer_list)){ + WMA_LOGE("%s: self peer removed by caller ", __func__); + break; + } else + temp = peer; + } + + adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); +} + +#ifdef QCA_IBSS_SUPPORT +static void wma_recreate_ibss_vdev_and_bss_peer(tp_wma_handle wma, u_int8_t vdev_id) +{ + ol_txrx_vdev_handle vdev; + tDelStaSelfParams del_sta_param; + tAddStaSelfParams add_sta_self_param; + VOS_STATUS status; + + if (!wma) { + WMA_LOGE("%s: Null wma handle", __func__); + return; + } + + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("%s: Can't find vdev with id %d", __func__, vdev_id); + return; + } + + vos_copy_macaddr((v_MACADDR_t *)&(add_sta_self_param.selfMacAddr), + (v_MACADDR_t *)&(vdev->mac_addr)); + add_sta_self_param.sessionId = vdev_id; + add_sta_self_param.type = WMI_VDEV_TYPE_IBSS; + add_sta_self_param.subType = 0; + add_sta_self_param.status = 0; + add_sta_self_param.nss_2g = wma->interfaces[vdev_id].nss_2g; + add_sta_self_param.nss_5g = wma->interfaces[vdev_id].nss_5g; + + /* delete old ibss vdev */ + del_sta_param.sessionId = vdev_id; + vos_mem_copy((void *)del_sta_param.selfMacAddr, + (void *)&(vdev->mac_addr), + VOS_MAC_ADDR_SIZE); + wma_vdev_detach(wma, &del_sta_param, 0); + + /* create new vdev for ibss */ + vdev = wma_vdev_attach(wma, &add_sta_self_param, 0); + if (!vdev) { + WMA_LOGE("%s: Failed to create vdev", __func__); + return; + } + + WLANTL_RegisterVdev(wma->vos_context, vdev); + /* Register with TxRx Module for Data Ack Complete Cb */ + wdi_in_data_tx_cb_set(vdev, wma_data_tx_ack_comp_hdlr, wma); + WMA_LOGA("new IBSS vdev created with mac %pM", add_sta_self_param.selfMacAddr); + + /* create ibss bss peer */ + status = wma_create_peer(wma, vdev->pdev, vdev, vdev->mac_addr.raw, + WMI_PEER_TYPE_DEFAULT, vdev_id, VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) + WMA_LOGE("%s: Failed to create IBSS bss peer", __func__); + else + WMA_LOGA("IBSS BSS peer created with mac %pM", vdev->mac_addr.raw); +} +#endif //#ifdef QCA_IBSS_SUPPORT + +static int wma_vdev_stop_resp_handler(void *handle, u_int8_t *cmd_param_info, + u32 len) +{ + WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf; + wmi_vdev_stopped_event_fixed_param *event; + u_int8_t *buf; + vos_msg_t vos_msg = {0}; + + WMA_LOGI("%s: Enter", __func__); + param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid event buffer"); + return -EINVAL; + } + event = param_buf->fixed_param; + buf = vos_mem_malloc(sizeof(wmi_vdev_stopped_event_fixed_param)); + if (!buf) { + WMA_LOGE("%s: Failed alloc memory for buf", __func__); + return -EINVAL; + } + vos_mem_zero(buf, sizeof(wmi_vdev_stopped_event_fixed_param)); + vos_mem_copy(buf, (u_int8_t *)event, + sizeof(wmi_vdev_stopped_event_fixed_param)); + + vos_msg.type = WDA_VDEV_STOP_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_VDEV_STOP_IND msg", __func__); + vos_mem_free(buf); + return -1; + } + WMA_LOGD("WDA_VDEV_STOP_IND posted"); + return 0; +} + +void wma_hidden_ssid_vdev_restart_on_vdev_stop(tp_wma_handle wma_handle, u_int8_t sessionId) +{ + wmi_vdev_start_request_cmd_fixed_param *cmd; + wmi_buf_t buf; + wmi_channel *chan; + int32_t len; + u_int8_t *buf_ptr; + struct wma_txrx_node *intr = wma_handle->interfaces; + int32_t ret=0; + + len = sizeof(*cmd) + sizeof(wmi_channel) + + WMI_TLV_HDR_SIZE; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + adf_os_atomic_set(&intr[sessionId].vdev_restart_params.hidden_ssid_restart_in_progress,0); + return; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_vdev_start_request_cmd_fixed_param *) buf_ptr; + chan = (wmi_channel *) (buf_ptr + sizeof(*cmd)); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_start_request_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_start_request_cmd_fixed_param)); + + WMITLV_SET_HDR(&chan->tlv_header, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + + cmd->vdev_id = sessionId; + cmd->ssid.ssid_len = intr[sessionId].vdev_restart_params.ssid.ssid_len; + vos_mem_copy(cmd->ssid.ssid, + intr[sessionId].vdev_restart_params.ssid.ssid, + cmd->ssid.ssid_len); + cmd->flags = intr[sessionId].vdev_restart_params.flags; + if (intr[sessionId].vdev_restart_params.ssidHidden) + cmd->flags |= WMI_UNIFIED_VDEV_START_HIDDEN_SSID; + else + cmd->flags &= (0xFFFFFFFE); + cmd->requestor_id = intr[sessionId].vdev_restart_params.requestor_id; + cmd->disable_hw_ack = intr[sessionId].vdev_restart_params.disable_hw_ack; + + chan->mhz = intr[sessionId].vdev_restart_params.chan.mhz; + chan->band_center_freq1 = intr[sessionId].vdev_restart_params.chan.band_center_freq1; + chan->band_center_freq2 = intr[sessionId].vdev_restart_params.chan.band_center_freq2; + chan->info = intr[sessionId].vdev_restart_params.chan.info; + chan->reg_info_1 = intr[sessionId].vdev_restart_params.chan.reg_info_1; + chan->reg_info_2 = intr[sessionId].vdev_restart_params.chan.reg_info_2; + + cmd->num_noa_descriptors = 0; + buf_ptr = (u_int8_t *)(((u_int8_t *) cmd) + sizeof(*cmd) + + sizeof(wmi_channel)); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + cmd->num_noa_descriptors * + sizeof(wmi_p2p_noa_descriptor)); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle,buf,len, + WMI_VDEV_RESTART_REQUEST_CMDID); + if (ret < 0) { + WMA_LOGE("%s: Failed to send vdev restart command", __func__); + adf_os_atomic_set(&intr[sessionId].vdev_restart_params.hidden_ssid_restart_in_progress,0); + adf_nbuf_free(buf); + } +} + +static int wma_vdev_stop_ind(tp_wma_handle wma, u_int8_t *buf) +{ + wmi_vdev_stopped_event_fixed_param *resp_event; + struct wma_target_req *req_msg; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + u_int8_t peer_id; + struct wma_txrx_node *iface; + int32_t status = 0; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)vos_get_context( + VOS_MODULE_ID_PE, + wma->vos_context); + if (NULL == mac_ctx) { + WMA_LOGE("%s: Failed to get mac_ctx", __func__); + return -EINVAL; + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + WMA_LOGI("%s: Enter", __func__); + if (!buf) { + WMA_LOGE("Invalid event buffer"); + return -EINVAL; + } + + resp_event = (wmi_vdev_stopped_event_fixed_param *)buf; + + if ((resp_event->vdev_id <= wma->max_bssid) && + (adf_os_atomic_read(&wma->interfaces[resp_event->vdev_id].vdev_restart_params.hidden_ssid_restart_in_progress)) && + ((wma->interfaces[resp_event->vdev_id].type == WMI_VDEV_TYPE_AP) && + (wma->interfaces[resp_event->vdev_id].sub_type == 0))) { + WMA_LOGE("%s: vdev stop event recevied for hidden ssid set using IOCTL ", __func__); + wma_hidden_ssid_vdev_restart_on_vdev_stop(wma, resp_event->vdev_id); + } + + req_msg = wma_find_vdev_req(wma, resp_event->vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_STOP); + if (!req_msg) { + WMA_LOGP("%s: Failed to lookup vdev request for vdev id %d", + __func__, resp_event->vdev_id); + return -EINVAL; + } + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (!pdev) { + WMA_LOGE("%s: pdev is NULL", __func__); + status = -EINVAL; + vos_timer_stop(&req_msg->event_timeout); + goto free_req_msg; + } + + vos_timer_stop(&req_msg->event_timeout); + if (req_msg->msg_type == WDA_DELETE_BSS_REQ) { + tpDeleteBssParams params = + (tpDeleteBssParams)req_msg->user_data; + struct beacon_info *bcn; + if (resp_event->vdev_id > wma->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %d", __func__, + resp_event->vdev_id); + status = -EINVAL; + goto free_req_msg; + } + + iface = &wma->interfaces[resp_event->vdev_id]; + if (iface->handle == NULL) { + WMA_LOGE("%s vdev id %d is already deleted", + __func__, resp_event->vdev_id); + status = -EINVAL; + goto free_req_msg; + } + +#ifdef QCA_IBSS_SUPPORT + if ( wma_is_vdev_in_ibss_mode(wma, resp_event->vdev_id)) + wma_delete_all_ibss_peers(wma, resp_event->vdev_id); + else +#endif + { + if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id)) + { + wma_delete_all_ap_remote_peers(wma, resp_event->vdev_id); + } + peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, + &peer_id); + if (!peer) + WMA_LOGD("%s Failed to find peer %pM", + __func__, params->bssid); + wma_remove_peer(wma, params->bssid, resp_event->vdev_id, + peer, VOS_FALSE); + } + + if (wmi_unified_vdev_down_send(wma->wmi_handle, resp_event->vdev_id) < 0) { + WMA_LOGE("Failed to send vdev down cmd: vdev %d", + resp_event->vdev_id); + } else { + wma->interfaces[resp_event->vdev_id].vdev_up = FALSE; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if (mac_ctx->sap.sap_channel_avoidance) + wma_find_mcc_ap(wma, + resp_event->vdev_id, + false); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + } + ol_txrx_vdev_flush(iface->handle); + WMA_LOGD("%s, vdev_id: %d, un-pausing tx_ll_queue for VDEV_STOP rsp", + __func__, resp_event->vdev_id); + wdi_in_vdev_unpause(iface->handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + iface->pause_bitmap &= ~(1 << PAUSE_TYPE_HOST); + adf_os_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STOPPED); + WMA_LOGD("%s: (type %d subtype %d) BSS is stopped", + __func__, iface->type, iface->sub_type); + bcn = wma->interfaces[resp_event->vdev_id].beacon; + + if (bcn) { + WMA_LOGD("%s: Freeing beacon struct %p, " + "template memory %p", __func__, + bcn, bcn->buf); + if (bcn->dma_mapped) + adf_nbuf_unmap_single(pdev->osdev, bcn->buf, + ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(bcn->buf); + vos_mem_free(bcn); + wma->interfaces[resp_event->vdev_id].beacon = NULL; + } + +#ifdef QCA_IBSS_SUPPORT + /* recreate ibss vdev and bss peer for scan purpose */ + if (wma_is_vdev_in_ibss_mode(wma, resp_event->vdev_id)) + wma_recreate_ibss_vdev_and_bss_peer(wma, resp_event->vdev_id); +#endif + /* Timeout status means its WMA generated DEL BSS REQ when ADD + BSS REQ was timed out to stop the VDEV in this case no need to + send response to UMAC */ + if (params->status == eHAL_STATUS_FW_MSG_TIMEDOUT){ + vos_mem_free(params); + WMA_LOGE("%s: DEL BSS from ADD BSS timeout do not send " + "resp to UMAC (vdev id %x)", + __func__, resp_event->vdev_id); + } else { + params->status = VOS_STATUS_SUCCESS; + wma_send_msg(wma, WDA_DELETE_BSS_RSP, (void *)params, 0); + } + + if (iface->del_staself_req) { + WMA_LOGA("scheduling defered deletion (vdev id %x)", + resp_event->vdev_id); + wma_vdev_detach(wma, iface->del_staself_req, 1); + } + } +free_req_msg: + vos_timer_destroy(&req_msg->event_timeout); + adf_os_mem_free(req_msg); + return status; +} + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +static void wma_send_status_of_ext_wow(tp_wma_handle wma, boolean status) +{ + tSirReadyToExtWoWInd *ready_to_extwow; + VOS_STATUS vstatus; + vos_msg_t vos_msg; + u_int8_t len; + + WMA_LOGD("Posting ready to suspend indication to umac"); + + len = sizeof(tSirReadyToExtWoWInd); + ready_to_extwow = (tSirReadyToExtWoWInd *) vos_mem_malloc(len); + + if (NULL == ready_to_extwow) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + + ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND; + ready_to_extwow->mesgLen = len; + ready_to_extwow->status= status; + + vos_msg.type = eWNI_SME_READY_TO_EXTWOW_IND; + vos_msg.bodyptr = (void *) ready_to_extwow; + vos_msg.bodyval = 0; + + vstatus = vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg); + if (vstatus != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to post ready to suspend"); + vos_mem_free(ready_to_extwow); + } +} + +static int wma_enable_ext_wow(tp_wma_handle wma, + tpSirExtWoWParams params) +{ + wmi_extwow_enable_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int ret; + + len = sizeof(wmi_extwow_enable_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extwow_enable_cmd_fixed_param)); + + cmd->vdev_id = params->vdev_id; + cmd->type = params->type; + cmd->wakeup_pin_num = params->wakeup_pin_num; + + WMA_LOGD("%s: vdev_id %d type %d Wakeup_pin_num %x", + __func__, cmd->vdev_id, + cmd->type, cmd->wakeup_pin_num); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_EXTWOW_ENABLE_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to set EXTWOW Enable", __func__); + wmi_buf_free(buf); + wma_send_status_of_ext_wow(wma, FALSE); + return VOS_STATUS_E_FAILURE; + } + + wma_send_status_of_ext_wow(wma, TRUE); + return VOS_STATUS_SUCCESS; + +} + +static int wma_set_app_type1_params_in_fw(tp_wma_handle wma, + tpSirAppType1Params appType1Params) +{ + wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int ret; + + len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *) + wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extwow_set_app_type1_params_cmd_fixed_param)); + + cmd->vdev_id = appType1Params->vdev_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(appType1Params->wakee_mac_addr, + &cmd->wakee_mac); + vos_mem_copy(cmd->ident, appType1Params->identification_id, 8); + cmd->ident_len = appType1Params->id_length; + vos_mem_copy(cmd->passwd, appType1Params->password, 16); + cmd->passwd_len = appType1Params->pass_length; + + WMA_LOGD("%s: vdev_id %d wakee_mac_addr %pM " + "identification_id %.8s id_length %u " + "password %.16s pass_length %u", + __func__, cmd->vdev_id, appType1Params->wakee_mac_addr, + cmd->ident, cmd->ident_len, + cmd->passwd, cmd->passwd_len); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +static int wma_set_app_type2_params_in_fw(tp_wma_handle wma, + tpSirAppType2Params appType2Params) +{ + wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int ret; + + len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *) + wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extwow_set_app_type2_params_cmd_fixed_param)); + + cmd->vdev_id = appType2Params->vdev_id; + + vos_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16); + cmd->rc4_key_len = appType2Params->rc4_key_len; + + cmd->ip_id = appType2Params->ip_id; + cmd->ip_device_ip = appType2Params->ip_device_ip; + cmd->ip_server_ip = appType2Params->ip_server_ip; + + cmd->tcp_src_port = appType2Params->tcp_src_port; + cmd->tcp_dst_port = appType2Params->tcp_dst_port; + cmd->tcp_seq = appType2Params->tcp_seq; + cmd->tcp_ack_seq = appType2Params->tcp_ack_seq; + + cmd->keepalive_init = appType2Params->keepalive_init; + cmd->keepalive_min = appType2Params->keepalive_min; + cmd->keepalive_max = appType2Params->keepalive_max; + cmd->keepalive_inc = appType2Params->keepalive_inc; + + WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac, + &cmd->gateway_mac); + cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val; + cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val; + + WMA_LOGD("%s: vdev_id %d gateway_mac %pM " + "rc4_key %.16s rc4_key_len %u " + "ip_id %x ip_device_ip %x ip_server_ip %x " + "tcp_src_port %u tcp_dst_port %u tcp_seq %u " + "tcp_ack_seq %u keepalive_init %u keepalive_min %u " + "keepalive_max %u keepalive_inc %u " + "tcp_tx_timeout_val %u tcp_rx_timeout_val %u", + __func__, cmd->vdev_id, appType2Params->gateway_mac, + cmd->rc4_key, cmd->rc4_key_len, + cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip, + cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq, + cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min, + cmd->keepalive_max, cmd->keepalive_inc, + cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val); + + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to set APP TYPE2 PARAMS", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; + +} +#endif +static void wma_update_pdev_stats(tp_wma_handle wma, + wmi_pdev_stats *pdev_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tANI_U32 temp_mask; + tANI_U8 *stats_buf; + tCsrGlobalClassAStatsInfo *classa_stats = NULL; + struct wma_txrx_node *node; + u_int8_t i; + + for (i = 0; i < wma->max_bssid; i++) { + node = &wma->interfaces[i]; + stats_rsp_params = node->stats_rsp; + if (stats_rsp_params) { + node->fw_stats_set |= FW_PDEV_STATS_SET; + WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", + i); + stats_buf = (tANI_U8 *) (stats_rsp_params + 1); + temp_mask = stats_rsp_params->statsMask; + if (temp_mask & (1 << eCsrSummaryStats)) + stats_buf += sizeof(tCsrSummaryStatsInfo); + + if (temp_mask & (1 << eCsrGlobalClassAStats)) { + classa_stats = + (tCsrGlobalClassAStatsInfo *) stats_buf; + classa_stats->max_pwr = pdev_stats->chan_tx_pwr; + } + } + } +} + +/** + * wma_vdev_stats_lost_link_helper() - helper function to extract + * lost link information from vdev statistics event while deleting BSS. + * @wma: WMA handle + * @vdev_stats: statistics information from firmware + * + * This is for informing HDD to collect lost link information while + * disconnection. Following conditions to check + * 1. vdev is up + * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to + * zero, hence add the check here to indicate the event comes during deleting + * BSS + * 3. DELETE_BSS is the request message queued. Put this condition check on the + * last one as it consumes more resource searching entries in the list + * + * Return: none + */ +static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma, + wmi_vdev_stats *vdev_stats) +{ + struct wma_txrx_node *node; + int8_t rssi; + struct wma_target_req *req_msg; + uint8_t zero_mac[ETH_ALEN] = {0}; + + node = &wma->interfaces[vdev_stats->vdev_id]; + if (node->vdev_up && + vos_mem_compare(node->bssid, zero_mac, ETH_ALEN)) { + req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_STOP); + if ((NULL == req_msg) || + (WDA_DELETE_BSS_REQ != req_msg->msg_type)) { + WMA_LOGD("%s: cannot find DELETE_BSS request message", + __func__); + return; + } + WMA_LOGD("%s: get vdev id %d, beancon snr %d, data snr %d", + __func__, vdev_stats->vdev_id, + vdev_stats->vdev_snr.bcn_snr, + vdev_stats->vdev_snr.dat_snr); + if (vdev_stats->vdev_snr.bcn_snr != WMA_TGT_INVALID_SNR) + rssi = vdev_stats->vdev_snr.bcn_snr; + else if (vdev_stats->vdev_snr.dat_snr != WMA_TGT_INVALID_SNR) + rssi = vdev_stats->vdev_snr.dat_snr; + else + rssi = WMA_TGT_INVALID_SNR; + + /* Get the absolute rssi value from the current rssi value */ + rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM; + wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi); + } +} + +static void wma_update_vdev_stats(tp_wma_handle wma, + wmi_vdev_stats *vdev_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tCsrSummaryStatsInfo *summary_stats = NULL; + tANI_U8 *stats_buf; + struct wma_txrx_node *node; + tANI_U8 i; + v_S7_t rssi = 0; + VOS_STATUS vos_status; + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)wma->pGetRssiReq; + vos_msg_t sme_msg = {0} ; + + node = &wma->interfaces[vdev_stats->vdev_id]; + stats_rsp_params = node->stats_rsp; + if (stats_rsp_params) { + stats_buf = (tANI_U8 *) (stats_rsp_params + 1); + node->fw_stats_set |= FW_VDEV_STATS_SET; + WMA_LOGD("<---FW VDEV STATS received for vdevId:%d", + vdev_stats->vdev_id); + if (stats_rsp_params->statsMask & + (1 << eCsrSummaryStats)) { + summary_stats = (tCsrSummaryStatsInfo *) stats_buf; + for (i=0 ; i < 4 ; i++) { + summary_stats->tx_frm_cnt[i] = + vdev_stats->tx_frm_cnt[i]; + summary_stats->fail_cnt[i] = + vdev_stats->fail_cnt[i]; + summary_stats->multiple_retry_cnt[i] = + vdev_stats->multiple_retry_cnt[i]; + } + + summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt; + summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt; + summary_stats->rx_discard_cnt = + vdev_stats->rx_discard_cnt; + summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt; + summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt; + summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt; + } + } + + WMA_LOGD("vdev id %d beancon snr %d data snr %d", + vdev_stats->vdev_id, + vdev_stats->vdev_snr.bcn_snr, + vdev_stats->vdev_snr.dat_snr); + + if (pGetRssiReq && + pGetRssiReq->sessionId == vdev_stats->vdev_id) { + if ((vdev_stats->vdev_snr.bcn_snr == WMA_TGT_INVALID_SNR) && + (vdev_stats->vdev_snr.dat_snr == WMA_TGT_INVALID_SNR)) { + /* + * Firmware sends invalid snr till it sees + * Beacon/Data after connection since after + * vdev up fw resets the snr to invalid. + * In this duartion Host will return the last know + * rssi during connection. + */ + rssi = wma->first_rssi; + } else { + if (vdev_stats->vdev_snr.bcn_snr != WMA_TGT_INVALID_SNR) { + rssi = vdev_stats->vdev_snr.bcn_snr; + } else if (vdev_stats->vdev_snr.dat_snr != WMA_TGT_INVALID_SNR) { + rssi = vdev_stats->vdev_snr.dat_snr; + } + + /* + * Get the absolute rssi value from the current rssi value + * the sinr value is hardcoded into 0 in the core stack + */ + rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM; + } + + WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi, + pGetRssiReq->sessionId); + + /* update the average rssi value to UMAC layer */ + if (NULL != pGetRssiReq->rssiCallback) { + ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(rssi,pGetRssiReq->staId, + pGetRssiReq->pDevContext); + } + + adf_os_mem_free(pGetRssiReq); + wma->pGetRssiReq = NULL; + } + + if (node->psnr_req) { + tAniGetSnrReq *p_snr_req = node->psnr_req; + + if (vdev_stats->vdev_snr.bcn_snr != WMA_TGT_INVALID_SNR) + p_snr_req->snr = vdev_stats->vdev_snr.bcn_snr; + else if (vdev_stats->vdev_snr.dat_snr != WMA_TGT_INVALID_SNR) + p_snr_req->snr = vdev_stats->vdev_snr.dat_snr; + else + p_snr_req->snr = WMA_TGT_INVALID_SNR; + + sme_msg.type = eWNI_SME_SNR_IND; + sme_msg.bodyptr = p_snr_req; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE("%s: Fail to post snr ind msg", __func__); + vos_mem_free(p_snr_req); + } + + node->psnr_req = NULL; + } + + wma_vdev_stats_lost_link_helper(wma, vdev_stats); +} + +static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node) +{ + tAniGetPEStatsRsp *stats_rsp_params; + + stats_rsp_params = node->stats_rsp; + /* send response to UMAC*/ + wma_send_msg(wma, WDA_GET_STATISTICS_RSP, (void *)stats_rsp_params, 0) ; + node->stats_rsp = NULL; + node->fw_stats_set = 0; +} + +static void wma_update_peer_stats(tp_wma_handle wma, wmi_peer_stats *peer_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tCsrGlobalClassAStatsInfo *classa_stats = NULL; + struct wma_txrx_node *node; + tANI_U8 *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags; + tANI_U32 temp_mask; + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]); + if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id)) + return; + + node = &wma->interfaces[vdev_id]; + if (node->stats_rsp) { + node->fw_stats_set |= FW_PEER_STATS_SET; + WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id); + stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp; + stats_buf = (tANI_U8 *) (stats_rsp_params + 1); + temp_mask = stats_rsp_params->statsMask; + if (temp_mask & (1 << eCsrSummaryStats)) + stats_buf += sizeof(tCsrSummaryStatsInfo); + + if (temp_mask & (1 << eCsrGlobalClassAStats)) { + classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf; + WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate); + /*The linkspeed returned by fw is in kbps so convert + *it in to units of 500kbps which is expected by UMAC*/ + if (peer_stats->peer_tx_rate) { + classa_stats->tx_rate = + peer_stats->peer_tx_rate/500; + } + + classa_stats->tx_rate_flags = node->rate_flags; + if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) { + classa_stats->mcs_index = + wma_get_mcs_idx((peer_stats->peer_tx_rate/100), + node->rate_flags, + node->nss, + &mcsRateFlags); + /* rx_frag_cnt and promiscuous_rx_frag_cnt + * parameter is currently not used. lets use the + * same parameter to hold the nss value and mcs + * rate flags */ + classa_stats->rx_frag_cnt = node->nss; + classa_stats->promiscuous_rx_frag_cnt = mcsRateFlags; + WMA_LOGD("Computed mcs_idx:%d mcs_rate_flags:%d", + classa_stats->mcs_index, + mcsRateFlags); + } + /* FW returns tx power in intervals of 0.5 dBm + Convert it back to intervals of 1 dBm */ + classa_stats->max_pwr = + roundup(classa_stats->max_pwr, 2) >> 1; + WMA_LOGD("peer tx rate flags:%d nss:%d max_txpwr:%d", + node->rate_flags, node->nss, + classa_stats->max_pwr); + } + + if (node->fw_stats_set & FW_STATS_SET) { + WMA_LOGD("<--STATS RSP VDEV_ID:%d", vdev_id); + wma_post_stats(wma, node); + } + } +} + +static void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus, + u_int8_t link_status) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + vos_msg_t sme_msg = {0} ; + + pGetLinkStatus->linkStatus = link_status; + sme_msg.type = eWNI_SME_LINK_STATUS_IND; + sme_msg.bodyptr = pGetLinkStatus; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE("%s: Fail to post link status ind msg", __func__); + vos_mem_free(pGetLinkStatus); + } +} + +#ifdef WLAN_FEATURE_MEMDUMP +/** + * wma_fw_mem_dump_rsp() - send fw mem dump response to SME + * + * @req_id - request id. + * @status - copy status from the firmware. + * + * This function is called by the memory dump response handler to + * indicate SME that firmware dump copy is complete + */ +static VOS_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status) +{ + struct fw_dump_rsp *dump_rsp; + vos_msg_t sme_msg = {0} ; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + dump_rsp = vos_mem_malloc(sizeof(*dump_rsp)); + + if (!dump_rsp) { + WMA_LOGE(FL("Memory allocation failed.")); + vos_status = VOS_STATUS_E_NOMEM; + return vos_status; + } + + WMA_LOGI(FL("FW memory dump copy complete status: %d for request: %d"), + status, req_id); + + dump_rsp->request_id = req_id; + dump_rsp->dump_complete = status; + + sme_msg.type = eWNI_SME_FW_DUMP_IND; + sme_msg.bodyptr = dump_rsp; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE(FL("Fail to post fw mem dump ind msg")); + vos_mem_free(dump_rsp); + } + + return vos_status; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +static int wma_link_status_rsp(tp_wma_handle wma, u_int8_t *buf) +{ + wmi_vdev_rate_stats_event_fixed_param *event; + wmi_vdev_rate_ht_info *ht_info; + struct wma_txrx_node *intr = wma->interfaces; + u_int8_t link_status = LINK_STATUS_LEGACY; + int i; + + event = (wmi_vdev_rate_stats_event_fixed_param *)buf; + ht_info = (wmi_vdev_rate_ht_info *)(buf + sizeof(*event)); + + WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats); + for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) { + WMA_LOGD( + "%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d", + __func__, + ht_info->vdevid, + ht_info->tx_nss, + ht_info->rx_nss, + ht_info->tx_preamble, + ht_info->rx_preamble); + if (ht_info->vdevid < wma->max_bssid && + intr[ht_info->vdevid].plink_status_req) { + if (ht_info->tx_nss || ht_info->rx_nss) + link_status = LINK_STATUS_MIMO; + + if ((ht_info->tx_preamble == LINK_RATE_VHT) || + (ht_info->rx_preamble == LINK_RATE_VHT)) + link_status |= LINK_STATUS_VHT; + + if (intr[ht_info->vdevid].nss == 2) + link_status |= LINK_SUPPORT_MIMO; + + if (intr[ht_info->vdevid].rate_flags & + (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 | + eHAL_TX_RATE_VHT80)) + link_status |= LINK_SUPPORT_VHT; + + wma_post_link_status(intr[ht_info->vdevid].plink_status_req, + link_status); + intr[ht_info->vdevid].plink_status_req = NULL; + link_status = LINK_STATUS_LEGACY; + } + + ht_info++; + } + + return 0; +} + +static int wma_link_status_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf; + wmi_vdev_rate_stats_event_fixed_param *event; + vos_msg_t vos_msg = {0}; + u_int32_t buf_size; + u_int8_t *buf; + + param_buf = + (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + + event = param_buf->fixed_param; + buf_size = sizeof(wmi_vdev_rate_stats_event_fixed_param) + + sizeof(wmi_vdev_rate_ht_info) * event->num_vdev_stats; + buf = vos_mem_malloc(buf_size); + if (!buf) { + WMA_LOGE("%s: Failed alloc memory for buf", __func__); + return -ENOMEM; + } + + vos_mem_zero(buf, buf_size); + vos_mem_copy(buf, param_buf->fixed_param, + sizeof(wmi_vdev_rate_stats_event_fixed_param)); + vos_mem_copy((buf + sizeof(wmi_vdev_rate_stats_event_fixed_param)), + param_buf->ht_info, + sizeof(wmi_vdev_rate_ht_info) * event->num_vdev_stats); + + vos_msg.type = WDA_GET_LINK_STATUS_RSP_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_GET_LINK_STATUS_RSP_IND msg", + __func__); + vos_mem_free(buf); + return -1; + } + WMA_LOGD("posted WDA_GET_LINK_STATUS_RSP_IND"); + + return 0; +} + +static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; + wmi_stats_event_fixed_param *event; + vos_msg_t vos_msg = {0}; + u_int32_t buf_size; + u_int8_t *buf; + + param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + buf_size = sizeof(*event) + + (event->num_pdev_stats * sizeof(wmi_pdev_stats)) + + (event->num_vdev_stats * sizeof(wmi_vdev_stats)) + + (event->num_peer_stats * sizeof(wmi_peer_stats)); + buf = vos_mem_malloc(buf_size); + if (!buf) { + WMA_LOGE("%s: Failed alloc memory for buf", __func__); + return -ENOMEM; + } + vos_mem_zero(buf, buf_size); + vos_mem_copy(buf, event, sizeof(*event)); + vos_mem_copy(buf + sizeof(*event), (u_int8_t *)param_buf->data, + (buf_size - sizeof(*event))); + vos_msg.type = WDA_FW_STATS_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_FW_STATS_IND msg", __func__); + vos_mem_free(buf); + return -1; + } + WMA_LOGD("WDA_FW_STATS_IND posted"); + return 0; +} + +static VOS_STATUS wma_send_link_speed(u_int32_t link_speed) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + vos_msg_t sme_msg = {0} ; + tSirLinkSpeedInfo *ls_ind = + (tSirLinkSpeedInfo *) vos_mem_malloc(sizeof(tSirLinkSpeedInfo)); + if (!ls_ind) { + WMA_LOGE("%s: Memory allocation failed.", __func__); + vos_status = VOS_STATUS_E_NOMEM; + } + else + { + ls_ind->estLinkSpeed = link_speed; + sme_msg.type = eWNI_SME_LINK_SPEED_IND; + sme_msg.bodyptr = ls_ind; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status) ) { + WMA_LOGE("%s: Fail to post linkspeed ind msg", __func__); + vos_mem_free(ls_ind); + } + } + return vos_status; +} + +static int wma_link_speed_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf; + wmi_peer_estimated_linkspeed_event_fixed_param *event; + VOS_STATUS vos_status; + + param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid linkspeed event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + vos_status = wma_send_link_speed(event->est_linkspeed_kbps); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + return -EINVAL; + } + return 0; +} + + +/** + * wma_handle_sta_rssi() - handle rssi information in + * peer stats + * @num_peer_stats: peer number + * @peer_stats: peer stats received from firmware + * @peer_macaddr: the specified mac address + * @sapaddr: sap mac address + * + * This function will send eWNI_SME_GET_RSSI_IND + * to sme with stations' rssi information + * + */ +static void wma_handle_sta_rssi(uint32_t num_peer_stats, + wmi_peer_stats *peer_stats, + v_MACADDR_t peer_macaddr, + uint8_t *sapaddr) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_mac_addr temp_addr; + struct sir_rssi_resp *sta_rssi; + vos_msg_t sme_msg = {0}; + uint32_t i = 0; + uint32_t j = 0; + + if (!vos_is_macaddr_broadcast(&peer_macaddr)) { + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr); + for (i = 0; i < num_peer_stats; i++) { + if ((((temp_addr.mac_addr47to32) & 0x0000ffff) == + ((peer_stats->peer_macaddr.mac_addr47to32) & + 0x0000ffff)) + &&(temp_addr.mac_addr31to0 == + peer_stats->peer_macaddr.mac_addr31to0)) { + + break; + } + peer_stats = peer_stats + 1; + } + sta_rssi = vos_mem_malloc(sizeof(*sta_rssi) + + sizeof(sta_rssi->info[0])); + if (NULL == sta_rssi) { + WMA_LOGE("%s: Memory allocation failed.", __func__); + return; + } + if (i < num_peer_stats) { + sta_rssi->count = 1; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr), + sta_rssi->info[0].peer_macaddr); + sta_rssi->info[0].rssi = + peer_stats->peer_rssi; + } else { + WMA_LOGE("%s: no match mac address", __func__); + sta_rssi->count = 0; + } + } else { + sta_rssi = vos_mem_malloc(sizeof(*sta_rssi) + + num_peer_stats * sizeof(sta_rssi->info[0])); + if (NULL == sta_rssi) { + WMA_LOGE("%s: Memory allocation failed.", __func__); + return; + } + sta_rssi->count = num_peer_stats; + + for (i = 0; i < num_peer_stats; i++) { + WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr), + sta_rssi->info[j].peer_macaddr); + sta_rssi->info[j].rssi = peer_stats->peer_rssi; + if (TRUE == vos_mem_compare( + sta_rssi->info[j].peer_macaddr, + sapaddr, VOS_MAC_ADDR_SIZE)) { + + sta_rssi->count = sta_rssi->count - 1; + } else { + j++; + } + peer_stats = peer_stats + 1; + } + WMA_LOGD("WDA send peer num %d", sta_rssi->count); + } + + sme_msg.type = eWNI_SME_GET_RSSI_IND; + sme_msg.bodyptr = sta_rssi; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status) ) { + WMA_LOGE("%s: Fail to post get rssi msg", __func__); + vos_mem_free(sta_rssi); + } + + return; +} + + + + +static void wma_fw_stats_ind(tp_wma_handle wma, u_int8_t *buf) +{ + wmi_stats_event_fixed_param *event = (wmi_stats_event_fixed_param *)buf; + wmi_pdev_stats *pdev_stats; + wmi_vdev_stats *vdev_stats; + wmi_peer_stats *peer_stats; + u_int8_t i, *temp; + + WMA_LOGI("%s: Enter", __func__); + + temp = buf + sizeof(*event); + WMA_LOGD("%s: num_stats: pdev: %u vdev: %u peer %u", + __func__, event->num_pdev_stats, event->num_vdev_stats, + event->num_peer_stats); + if (event->num_pdev_stats > 0) { + for (i = 0; i < event->num_pdev_stats; i++) { + pdev_stats = (wmi_pdev_stats*)temp; + wma_update_pdev_stats(wma, pdev_stats); + temp += sizeof(wmi_pdev_stats); + } + } + + if (event->num_vdev_stats > 0) { + for (i = 0; i < event->num_vdev_stats; i++) { + vdev_stats = (wmi_vdev_stats *)temp; + wma_update_vdev_stats(wma, vdev_stats); + temp += sizeof(wmi_vdev_stats); + } + } + + WMA_LOGD("WDA receive peer num %d", + event->num_peer_stats); + + if (event->num_peer_stats > 0) { + WMA_LOGD("update get rssi %d", + wma->get_sta_rssi); + if (wma->get_sta_rssi == TRUE) { + wma_handle_sta_rssi(event->num_peer_stats, + (wmi_peer_stats *)temp, + wma->peer_macaddr, + wma->myaddr); + } else { + for (i = 0; i < event->num_peer_stats; i++) { + peer_stats = (wmi_peer_stats *)temp; + wma_update_peer_stats(wma, peer_stats); + temp += sizeof(wmi_peer_stats); + } + } + } + + WMA_LOGI("%s: Exit", __func__); +} + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * wma_extscan_rsp_handler() - extscan rsp handler + * @wma: WMA global handle + * @buf: event fixed param buffer + * + * Return: 0 on success, error number otherwise + */ +static int wma_extscan_rsp_handler(tp_wma_handle wma, uint8_t *buf) +{ + wmi_extscan_start_stop_event_fixed_param *event; + struct sir_extscan_generic_response *extscan_ind; + uint16_t event_type; + uint8_t vdev_id; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + WMA_LOGI("%s: Enter", __func__); + if (!mac_ctx) { + WMA_LOGE("%s: Invalid mac_ctx", __func__); + return -EINVAL; + } + if (!mac_ctx->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + if (!buf) { + WMA_LOGE("Invalid event buffer"); + return -EINVAL; + } + + event = (wmi_extscan_start_stop_event_fixed_param *)buf; + vdev_id = event->vdev_id; + extscan_ind = vos_mem_malloc(sizeof(*extscan_ind)); + if (!extscan_ind) { + WMA_LOGE("%s: extscan memory allocation failed", __func__); + return -ENOMEM; + } + + switch (event->command) { + case WMI_EXTSCAN_START_CMDID: + event_type = eSIR_EXTSCAN_START_RSP; + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + + if (!extscan_ind->status) + wma->interfaces[vdev_id].extscan_in_progress = true; + + break; + case WMI_EXTSCAN_STOP_CMDID: + event_type = eSIR_EXTSCAN_STOP_RSP; + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + + if (!extscan_ind->status) + wma->interfaces[vdev_id].extscan_in_progress = false; + + break; + case WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID: + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + if (event->mode == WMI_EXTSCAN_MODE_STOP) { + event_type = + eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP; + } else { + event_type = + eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP; + } + break; + case WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID: + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + if (event->mode == WMI_EXTSCAN_MODE_STOP) { + event_type = + eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP; + } else { + event_type = + eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP; + } + break; + case WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID: + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + event_type = eSIR_EXTSCAN_CACHED_RESULTS_RSP; + break; + case WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID: + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + if (event->mode == WMI_EXTSCAN_MODE_STOP) { + event_type = + eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP; + } else { + event_type = + eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP; + } + break; + default: + WMA_LOGE("%s: Unknown event %d from target vdev_id %u", + __func__, event->status, vdev_id); + vos_mem_free(extscan_ind); + return -EINVAL; + } + mac_ctx->sme.pExtScanIndCb(mac_ctx->hHdd, + event_type, extscan_ind); + WMA_LOGD("%s: sending event to umac for requestid %u with status %d", + __func__, + extscan_ind->request_id, extscan_ind->status); + vos_mem_free(extscan_ind); + return 0; +} + +/** + * wma_extscan_start_stop_event_handler() - extscan event handler + * @handle: WMA global handle + * @cmd_param_info: command event data + * @len: Length of @cmd_param_info + * + * Return: 0 on success, error number otherwise + */ +static int wma_extscan_start_stop_event_handler(void *handle, + uint8_t *cmd_param_info, uint32_t len) +{ + WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *param_buf; + wmi_extscan_start_stop_event_fixed_param *event; + u_int8_t *buf; + int buf_len = sizeof(*event); + vos_msg_t vos_msg = {0}; + + WMA_LOGI("%s: Enter", __func__); + param_buf = (WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid extscan event", __func__); + return -EINVAL; + } + + event = param_buf->fixed_param; + buf = vos_mem_malloc(buf_len); + if (!buf) { + WMA_LOGE("%s: extscan memory allocation failed", __func__); + return -ENOMEM; + } + + vos_mem_zero(buf, buf_len); + vos_mem_copy(buf, (u_int8_t *)event, buf_len); + + vos_msg.type = WDA_EXTSCAN_STATUS_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_EXTSCAN_STATUS_IND msg", + __func__); + vos_mem_free(buf); + return -EINVAL; + } + WMA_LOGI("WDA_EXTSCAN_STATUS_IND posted"); + + return 0; +} + +/** + * wma_extscan_operations_ind_handler() - extscan operations handler + * @wma: WMA global handle + * @buf: command event data + * + * This function extracts the event data, fill in appropriate structures + * and invoke upper layer callback. + * + * Return: 0 on success, error number otherwise + */ +static int wma_extscan_operations_ind_handler(tp_wma_handle wma, uint8_t *buf) +{ + wmi_extscan_operation_event_fixed_param *event; + tSirExtScanOnScanEventIndParams *oprn_ind; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!mac_ctx) { + WMA_LOGE("%s: Invalid mac_ctx", __func__); + return -EINVAL; + } + if (!mac_ctx->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + if (!buf) { + WMA_LOGE("%s: Invalid event buffer", __func__); + return -EINVAL; + } + event = (wmi_extscan_operation_event_fixed_param *)buf; + oprn_ind = vos_mem_malloc(sizeof(*oprn_ind)); + if (!oprn_ind) { + WMA_LOGE("%s: extscan memory allocation failed", __func__); + vos_mem_free(oprn_ind); + return -EINVAL; + } + + oprn_ind->requestId = event->request_id; + + switch (event->event) { + case WMI_EXTSCAN_BUCKET_COMPLETED_EVENT: + oprn_ind->scanEventType = WIFI_SCAN_COMPLETE; + oprn_ind->status = 0; + break; + case WMI_EXTSCAN_CYCLE_STARTED_EVENT: + WMA_LOGD("%s: received WMI_EXTSCAN_CYCLE_STARTED_EVENT", + __func__); + vos_wake_lock_timeout_acquire(&wma->extscan_wake_lock, + WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN); + goto exit_handler; + case WMI_EXTSCAN_CYCLE_COMPLETED_EVENT: + WMA_LOGD("%s: received WMI_EXTSCAN_CYCLE_COMPLETED_EVENT", + __func__); + vos_wake_lock_release(&wma->extscan_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN); + goto exit_handler; + default: + WMA_LOGE("%s: Unknown event %d from target", + __func__, event->event); + vos_mem_free(oprn_ind); + return -EINVAL; + } + mac_ctx->sme.pExtScanIndCb(mac_ctx->hHdd, + eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, + oprn_ind); + WMA_LOGD("%s: sending scan progress event to hdd", __func__); + +exit_handler: + vos_mem_free(oprn_ind); + return 0; +} + +/** + * wma_extscan_operations_event_handler() - extscan operations event handler + * @handle: WMA global handle + * @cmd_param_info: command event data + * @len: Length of @cmd_param_info + * + * Return: 0 on success, error number otherwise + */ +static int wma_extscan_operations_event_handler(void *handle, + uint8_t *cmd_param_info, uint32_t len) +{ + WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *param_buf; + wmi_extscan_operation_event_fixed_param *event, *buf; + int buf_len = sizeof(*event); + vos_msg_t vos_msg = {0}; + + WMA_LOGI("%s: Enter", __func__); + param_buf = (WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid extscan event", __func__); + return -EINVAL; + } + + event = param_buf->fixed_param; + buf = vos_mem_malloc(buf_len); + if (!buf) { + WMA_LOGE("%s: extscan memory allocation failed", __func__); + return -ENOMEM; + } + + *buf = *event; + + vos_msg.type = WDA_EXTSCAN_OPERATION_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_EXTSCAN_OPERATION_IND msg", + __func__); + vos_mem_free(buf); + return -EINVAL; + } + WMA_LOGI("WDA_EXTSCAN_OPERATION_IND posted"); + + return 0; +} + + +static int wma_extscan_table_usage_event_handler (void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *param_buf; + wmi_extscan_table_usage_event_fixed_param *event; + tSirExtScanResultsAvailableIndParams *tbl_usg_ind; + tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!pMac) { + WMA_LOGE("%s: Invalid pMac", __func__); + return -EINVAL; + } + if (!pMac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid table usage event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + tbl_usg_ind = vos_mem_malloc(sizeof(*tbl_usg_ind)); + if (!tbl_usg_ind) { + WMA_LOGE("%s: table usage allocation failed", __func__); + return -EINVAL; + } + tbl_usg_ind->requestId = event->request_id; + tbl_usg_ind->numResultsAvailable = event->entries_in_use; + + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND, + tbl_usg_ind); + WMA_LOGD("%s: sending scan_res available event to hdd", __func__); + vos_mem_free(tbl_usg_ind); + return 0; +} + +static int wma_extscan_capabilities_event_handler (void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *param_buf; + wmi_extscan_capabilities_event_fixed_param *event; + wmi_extscan_cache_capabilities *src_cache; + wmi_extscan_hotlist_monitor_capabilities *src_hotlist; + wmi_extscan_wlan_change_monitor_capabilities *src_change; + + struct ext_scan_capabilities_response *dest_capab; + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!pMac) { + WMA_LOGE("%s: Invalid pMac", __func__); + return -EINVAL; + } + if (!pMac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid capabilities event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + src_cache = param_buf->extscan_cache_capabilities; + src_hotlist = param_buf->hotlist_capabilities; + src_change = param_buf->wlan_change_capabilities; + + if (!src_cache || !src_hotlist || !src_change) { + WMA_LOGE("%s: Invalid capabilities list", __func__); + return -EINVAL; + } + dest_capab = vos_mem_malloc(sizeof(*dest_capab)); + if (!dest_capab) { + WMA_LOGE("%s: Allocation failed for capabilities buffer", + __func__); + return -EINVAL; + } + dest_capab->requestId = event->request_id; + dest_capab->max_scan_buckets = src_cache->max_buckets; + dest_capab->max_scan_cache_size = src_cache->scan_cache_entry_size; + dest_capab->max_ap_cache_per_scan = src_cache->max_bssid_per_scan; + dest_capab->max_scan_reporting_threshold = + src_cache->max_table_usage_threshold; + + dest_capab->max_hotlist_bssids = src_hotlist->max_hotlist_entries; + dest_capab->max_rssi_sample_size = + src_change->max_rssi_averaging_samples; + dest_capab->max_bssid_history_entries = + src_change->max_rssi_history_entries; + dest_capab->max_significant_wifi_change_aps = + src_change->max_wlan_change_entries; + dest_capab->max_hotlist_ssids = + event->num_extscan_hotlist_ssid; + dest_capab->max_number_epno_networks = + event->num_epno_networks; + dest_capab->max_number_epno_networks_by_ssid = + event->num_epno_networks; + dest_capab->max_number_of_white_listed_ssid = + event->num_roam_ssid_whitelist; + dest_capab->status = 0; + + WMA_LOGD("%s: request_id: %u status: %d", + __func__, dest_capab->requestId, dest_capab->status); + + WMA_LOGD("%s: Capabilities: max_scan_buckets: %d," + "max_hotlist_bssids: %d, max_scan_cache_size: %d," + "max_ap_cache_per_scan: %d, max_scan_reporting_threshold: %d," + "max_rssi_sample_size: %d, max_bssid_history_entries: %d," + "max_significant_wifi_change_aps: %d", + __func__, dest_capab->max_scan_buckets, + dest_capab->max_hotlist_bssids, + dest_capab->max_scan_cache_size, + dest_capab->max_ap_cache_per_scan, + dest_capab->max_scan_reporting_threshold, + dest_capab->max_rssi_sample_size, + dest_capab->max_bssid_history_entries, + dest_capab->max_significant_wifi_change_aps); + WMA_LOGD("%s: Capabilities: max_hotlist_ssids: %d," + "max_number_epno_networks: %d, max_number_epno_networks_by_ssid: %d," + "max_number_of_white_listed_ssid: %d", + __func__, dest_capab->max_hotlist_ssids, + dest_capab->max_number_epno_networks, + dest_capab->max_number_epno_networks_by_ssid, + dest_capab->max_number_of_white_listed_ssid); + + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_GET_CAPABILITIES_IND, + dest_capab); + WMA_LOGD("%s: sending capabilities event to hdd", __func__); + vos_mem_free(dest_capab); + return 0; +} + +static int wma_extscan_hotlist_match_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *param_buf; + wmi_extscan_hotlist_match_event_fixed_param *event; + struct extscan_hotlist_match *dest_hotlist; + tSirWifiScanResult *dest_ap; + wmi_extscan_wlan_descriptor *src_hotlist; + int numap, j, ap_found = 0; + + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!pMac) { + WMA_LOGE("%s: Invalid pMac", __func__); + return -EINVAL; + } + if (!pMac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid hotlist match event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + src_hotlist = param_buf->hotlist_match; + numap = event->total_entries; + + if (!src_hotlist || !numap) { + WMA_LOGE("%s: Hotlist AP's list invalid", __func__); + return -EINVAL; + } + dest_hotlist = vos_mem_malloc(sizeof(*dest_hotlist) + + sizeof(*dest_ap) * numap); + if (!dest_hotlist) { + WMA_LOGE("%s: Allocation failed for hotlist buffer", __func__); + return -EINVAL; + } + dest_ap = &dest_hotlist->ap[0]; + dest_hotlist->numOfAps = event->total_entries; + dest_hotlist->requestId = event->config_request_id; + if (event->first_entry_index + + event->num_entries_in_page < event->total_entries) + dest_hotlist->moreData = 1; + else + dest_hotlist->moreData = 0; + + WMA_LOGD("%s: Hotlist match: requestId: %u," + "numOfAps: %d", __func__, + dest_hotlist->requestId, dest_hotlist->numOfAps); + + /* + * Currently firmware sends only one bss information in-case + * of both hotlist ap found and lost. + */ + for (j = 0; j < numap; j++) { + dest_ap->rssi = 0; + dest_ap->channel = src_hotlist->channel; + dest_ap->ts = src_hotlist->tstamp; + ap_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE; + dest_ap->rtt = src_hotlist->rtt; + dest_ap->rtt_sd = src_hotlist->rtt_sd; + dest_ap->beaconPeriod = src_hotlist->beacon_interval; + dest_ap->capability = src_hotlist->capabilities; + dest_ap->ieLength = src_hotlist-> ie_length; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid, + dest_ap->bssid); + vos_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid, + src_hotlist->ssid.ssid_len); + dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0'; + dest_ap++; + src_hotlist++; + } + dest_hotlist->ap_found = ap_found; + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_HOTLIST_MATCH_IND, + dest_hotlist); + WMA_LOGD("%s: sending hotlist match event to hdd", __func__); + vos_mem_free(dest_hotlist); + return 0; +} + +/** wma_extscan_find_unique_scan_ids() - find unique scan ids + * @cmd_param_info: event data. + * + * This utility function parses the input bss table of information + * and find the unique number of scan ids + * + * Return: 0 on success; error number otherwise + */ +static int wma_extscan_find_unique_scan_ids(const u_int8_t *cmd_param_info) +{ + WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; + wmi_extscan_cached_results_event_fixed_param *event; + wmi_extscan_wlan_descriptor *src_hotlist; + wmi_extscan_rssi_info *src_rssi; + int prev_scan_id, scan_ids_cnt, i; + + param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) + cmd_param_info; + event = param_buf->fixed_param; + src_hotlist = param_buf->bssid_list; + src_rssi = param_buf->rssi_list; + + /* Find the unique number of scan_id's for grouping */ + prev_scan_id = src_rssi->scan_cycle_id; + scan_ids_cnt = 1; + for (i = 1; i < event->num_entries_in_page; i++) { + src_rssi++; + + if (prev_scan_id != src_rssi->scan_cycle_id) { + scan_ids_cnt++; + prev_scan_id = src_rssi->scan_cycle_id; + } + } + + return scan_ids_cnt; +} + +/** wma_fill_num_results_per_scan_id() - fill number of bss per scan id + * @cmd_param_info: event data. + * @scan_id_group: pointer to scan id group. + * + * This utility function parses the input bss table of information + * and finds how many bss are there per unique scan id. + * + * Return: 0 on success; error number otherwise + */ +static int wma_fill_num_results_per_scan_id(const u_int8_t *cmd_param_info, + struct extscan_cached_scan_result *scan_id_group) +{ + WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; + wmi_extscan_cached_results_event_fixed_param *event; + wmi_extscan_wlan_descriptor *src_hotlist; + wmi_extscan_rssi_info *src_rssi; + struct extscan_cached_scan_result *t_scan_id_grp; + int i, prev_scan_id; + + param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) + cmd_param_info; + event = param_buf->fixed_param; + src_hotlist = param_buf->bssid_list; + src_rssi = param_buf->rssi_list; + t_scan_id_grp = scan_id_group; + + prev_scan_id = src_rssi->scan_cycle_id; + + t_scan_id_grp->scan_id = src_rssi->scan_cycle_id; + t_scan_id_grp->flags = src_rssi->flags; + t_scan_id_grp->num_results = 1; + for (i = 1; i < event->num_entries_in_page; i++) { + src_rssi++; + if (prev_scan_id == src_rssi->scan_cycle_id) { + t_scan_id_grp->num_results++; + } else { + t_scan_id_grp++; + prev_scan_id = t_scan_id_grp->scan_id = + src_rssi->scan_cycle_id; + t_scan_id_grp->flags = src_rssi->flags; + t_scan_id_grp->num_results = 1; + } + } + return 0; +} + +/** wma_group_num_bss_to_scan_id() - group bss to scan id table + * @cmd_param_info: event data. + * @cached_result: pointer to cached table. + * + * This function reads the bss information from the format + * ------------------------------------------------------------------------ + * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_1 | flags | + * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_2 | flags | + * ........................................................................ + * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_N | flags | + * ------------------------------------------------------------------------ + * + * and converts it into the below format and store it + * + * ------------------------------------------------------------------------ + * | scan id_1 | -> bss info_1 -> bss info_2 -> .... bss info_M1 + * | scan id_2 | -> bss info_1 -> bss info_2 -> .... bss info_M2 + * ...................... + * | scan id_N | -> bss info_1 -> bss info_2 -> .... bss info_Mn + * ------------------------------------------------------------------------ + * + * Return: 0 on success; error number otherwise + */ +static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info, + struct extscan_cached_scan_results *cached_result) +{ + WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; + wmi_extscan_cached_results_event_fixed_param *event; + wmi_extscan_wlan_descriptor *src_hotlist; + wmi_extscan_rssi_info *src_rssi; + struct extscan_cached_scan_results *t_cached_result; + struct extscan_cached_scan_result *t_scan_id_grp; + int i, j; + tSirWifiScanResult *ap; + + param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) + cmd_param_info; + event = param_buf->fixed_param; + src_hotlist = param_buf->bssid_list; + src_rssi = param_buf->rssi_list; + t_cached_result = cached_result; + t_scan_id_grp = &t_cached_result->result[0]; + + WMA_LOGD("%s: num_scan_ids:%d", __func__, + t_cached_result->num_scan_ids); + for (i = 0; i < t_cached_result->num_scan_ids; i++) { + WMA_LOGD("%s: num_results:%d", __func__, + t_scan_id_grp->num_results); + t_scan_id_grp->ap = vos_mem_malloc(t_scan_id_grp->num_results * + sizeof(*ap)); + if (!t_scan_id_grp->ap) { + WMA_LOGD("%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + ap = &t_scan_id_grp->ap[0]; + for (j = 0; j < t_scan_id_grp->num_results; j++) { + ap->channel = src_hotlist->channel; + ap->ts = WMA_MSEC_TO_USEC(src_rssi->tstamp); + ap->rtt = src_hotlist->rtt; + ap->rtt_sd = src_hotlist->rtt_sd; + ap->beaconPeriod = src_hotlist->beacon_interval; + ap->capability = src_hotlist->capabilities; + ap->ieLength = src_hotlist->ie_length; + + /* Firmware already applied noise floor adjustment and + * due to WMI interface "UINT32 rssi", host driver + * receives a positive value, hence convert to + * signed char to get the absolute rssi. + */ + ap->rssi = (signed char) src_rssi->rssi; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid, + ap->bssid); + + vos_mem_copy(ap->ssid, src_hotlist->ssid.ssid, + src_hotlist->ssid.ssid_len); + ap->ssid[src_hotlist->ssid.ssid_len] = '\0'; + ap++; + src_rssi++; + src_hotlist++; + } + t_scan_id_grp++; + } + return 0; +} + +static int wma_extscan_cached_results_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; + wmi_extscan_cached_results_event_fixed_param *event; + struct extscan_cached_scan_results *dest_cachelist; + struct extscan_cached_scan_result *dest_result; + struct extscan_cached_scan_results empty_cachelist; + wmi_extscan_wlan_descriptor *src_hotlist; + wmi_extscan_rssi_info *src_rssi; + int numap, i, moredata, scan_ids_cnt; + int buf_len; + + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!pMac) { + WMA_LOGE("%s: Invalid pMac", __func__); + return -EINVAL; + } + if (!pMac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid cached results event", __func__); + return -EINVAL; + } + + event = param_buf->fixed_param; + src_hotlist = param_buf->bssid_list; + src_rssi = param_buf->rssi_list; + numap = event->num_entries_in_page; + WMA_LOGI("Total_entries %u first_entry_index %u", event->total_entries, + event->first_entry_index); + WMA_LOGI("num_entries_in_page %d", numap); + if (!src_hotlist || !src_rssi || !numap) { + WMA_LOGW("%s: Cached results empty, send 0 results", __func__); + goto noresults; + } + + if (event->first_entry_index + + event->num_entries_in_page < event->total_entries) + moredata = 1; + else + moredata = 0; + + dest_cachelist = vos_mem_malloc(sizeof(*dest_cachelist)); + if (!dest_cachelist) { + WMA_LOGE("%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + vos_mem_zero(dest_cachelist, sizeof(*dest_cachelist)); + dest_cachelist->request_id = event->request_id; + dest_cachelist->more_data = moredata; + + scan_ids_cnt = wma_extscan_find_unique_scan_ids(cmd_param_info); + WMA_LOGI("scan_ids_cnt %d", scan_ids_cnt); + dest_cachelist->num_scan_ids = scan_ids_cnt; + + buf_len = sizeof(*dest_result) * scan_ids_cnt; + dest_cachelist->result = vos_mem_malloc(buf_len); + if (!dest_cachelist->result) { + WMA_LOGE("%s: vos_mem_malloc failed", __func__); + vos_mem_free(dest_cachelist); + return -ENOMEM; + } + + dest_result = dest_cachelist->result; + wma_fill_num_results_per_scan_id(cmd_param_info, dest_result); + wma_group_num_bss_to_scan_id(cmd_param_info, dest_cachelist); + + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_CACHED_RESULTS_IND, + dest_cachelist); + WMA_LOGI("%s: sending cached results event", __func__); + + dest_result = dest_cachelist->result; + for (i = 0; i < dest_cachelist->num_scan_ids; i++) { + vos_mem_free(dest_result->ap); + dest_result++; + } + vos_mem_free(dest_cachelist->result); + vos_mem_free(dest_cachelist); + return 0; + +noresults: + empty_cachelist.request_id = event->request_id; + empty_cachelist.more_data = 0; + empty_cachelist.num_scan_ids = 0; + + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_CACHED_RESULTS_IND, + &empty_cachelist); + WMA_LOGI("%s: sending cached results event", __func__); + return 0; +} + +static int wma_extscan_change_results_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *param_buf; + wmi_extscan_wlan_change_results_event_fixed_param *event; + tSirWifiSignificantChangeEvent *dest_chglist; + tSirWifiSignificantChange *dest_ap; + wmi_extscan_wlan_change_result_bssid *src_chglist; + + int numap; + int i, k; + u_int8_t *src_rssi; + int count = 0; + int moredata; + int rssi_num = 0; + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!pMac) { + WMA_LOGE("%s: Invalid pMac", __func__); + return -EINVAL; + } + if (!pMac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid change monitor event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + src_chglist = param_buf->bssid_signal_descriptor_list; + src_rssi = param_buf->rssi_list; + numap = event->num_entries_in_page; + + if (!src_chglist || !numap) { + WMA_LOGE("%s: Results invalid", __func__); + return -EINVAL; + } + for (i = 0; i < numap; i++) { + rssi_num += src_chglist->num_rssi_samples; + } + if (event->first_entry_index + + event->num_entries_in_page < event->total_entries) + moredata = 1; + else + moredata = 0; + + dest_chglist = vos_mem_malloc(sizeof(*dest_chglist) + + sizeof(*dest_ap) * numap + + sizeof(tANI_S32) * rssi_num); + if (!dest_chglist) { + WMA_LOGE("%s: vos_mem_malloc failed", __func__); + return -EINVAL; + } + dest_ap = &dest_chglist->ap[0]; + for (i = 0; i < numap; i++) { + dest_ap->channel = src_chglist->channel; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_chglist->bssid, + dest_ap->bssid); + dest_ap->numOfRssi = + src_chglist->num_rssi_samples; + if (dest_ap->numOfRssi) { + for (k = 0; k < dest_ap->numOfRssi; k++) { + dest_ap->rssi[k] = WMA_TGT_NOISE_FLOOR_DBM + + src_rssi[count++]; + } + } + dest_ap += dest_ap->numOfRssi * sizeof(tANI_S32); + src_chglist++; + } + dest_chglist->requestId = event->request_id; + dest_chglist->moreData = moredata; + dest_chglist->numResults = event->total_entries; + + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND, + dest_chglist); + WMA_LOGD("%s: sending change monitor results", __func__); + vos_mem_free(dest_chglist); + return 0; +} + +/** + * wma_passpoint_match_event_handler() - passpoint match found event handler + * @handle: WMA handle + * @cmd_param_info: event data + * @len: event data length + * + * This is the passpoint match found event handler; it reads event data from + * @cmd_param_info and fill in the destination buffer and sends indication + * up layer. + * + * Return: 0 on success; error number otherwise + */ +static int wma_passpoint_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *param_buf; + wmi_passpoint_event_hdr *event; + struct wifi_passpoint_match *dest_match; + tSirWifiScanResult *dest_ap; + uint8_t *buf_ptr; + + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!pMac) { + WMA_LOGE("%s: Invalid pMac", __func__); + return -EINVAL; + } + if (!pMac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid passpoint match event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + buf_ptr = (uint8_t *)param_buf->fixed_param; + + dest_match = vos_mem_malloc(sizeof(*dest_match) + + event->ie_length + event->anqp_length); + if (!dest_match) { + WMA_LOGE("%s: vos_mem_malloc failed", __func__); + return -EINVAL; + } + dest_ap = &dest_match->ap; + dest_match->request_id = 0; + dest_match->id = event->id; + dest_match->anqp_len = event->anqp_length; + WMA_LOGI("%s: passpoint match: id: %u anqp length %u", __func__, + dest_match->id, dest_match->anqp_len); + + dest_ap->channel = event->channel_mhz; + dest_ap->ts = event->timestamp; + dest_ap->rtt = event->rtt; + dest_ap->rssi = event->rssi; + dest_ap->rtt_sd = event->rtt_sd; + dest_ap->beaconPeriod = event->beacon_period; + dest_ap->capability = event->capability; + dest_ap->ieLength = event->ie_length; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, dest_ap->bssid); + vos_mem_copy(dest_ap->ssid, event->ssid.ssid, + event->ssid.ssid_len); + dest_ap->ssid[event->ssid.ssid_len] = '\0'; + vos_mem_copy(dest_ap->ieData, buf_ptr + sizeof(*event) + + WMI_TLV_HDR_SIZE, dest_ap->ieLength); + vos_mem_copy(dest_match->anqp, buf_ptr + sizeof(*event) + + WMI_TLV_HDR_SIZE + dest_ap->ieLength, + dest_match->anqp_len); + + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_PASSPOINT_NETWORK_FOUND_IND, + dest_match); + WMA_LOGD("%s: sending passpoint match event to hdd", __func__); + vos_mem_free(dest_match); + return 0; +} + +/** + * wma_extscan_hotlist_ssid_match_event_handler() - + * Handler for SSID hotlist match event from firmware + * @handle: WMA handle + * @cmd_param_info: WMI command buffer + * @len: length of @cmd_param_info + * + * Return: 0 on success, non-zero on failure + */ +static int +wma_extscan_hotlist_ssid_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *param_buf; + wmi_extscan_hotlist_ssid_match_event_fixed_param *event; + tSirWifiScanResultEvent *dest_hotlist; + tSirWifiScanResult *dest_ap; + wmi_extscan_wlan_descriptor *src_hotlist; + int numap, j; + bool ssid_found = false; + tpAniSirGlobal mac = + vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); + + if (!mac) { + WMA_LOGE("%s: Invalid mac", __func__); + return -EINVAL; + } + + if (!mac->sme.pExtScanIndCb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + + param_buf = (WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid hotlist match event", __func__); + return -EINVAL; + } + + event = param_buf->fixed_param; + src_hotlist = param_buf->hotlist_ssid_match; + numap = event->total_entries; + if (!src_hotlist || !numap) { + WMA_LOGE("%s: Hotlist AP's list invalid", __func__); + return -EINVAL; + } + + dest_hotlist = vos_mem_malloc(sizeof(*dest_hotlist) + + sizeof(*dest_ap) * numap); + if (!dest_hotlist) { + WMA_LOGE("%s: Allocation failed for hotlist buffer", __func__); + return -EINVAL; + } + + dest_ap = &dest_hotlist->ap[0]; + dest_hotlist->numOfAps = event->total_entries; + dest_hotlist->requestId = event->config_request_id; + + if (event->first_entry_index + + event->num_entries_in_page < event->total_entries) + dest_hotlist->moreData = 1; + else + dest_hotlist->moreData = 0; + + WMA_LOGD("%s: Hotlist match: requestId: %u, numOfAps: %d", __func__, + dest_hotlist->requestId, dest_hotlist->numOfAps); + + for (j = 0; j < numap; j++) { + dest_ap->channel = src_hotlist->channel; + dest_ap->ts = src_hotlist->tstamp; + ssid_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE; + dest_ap->rtt = src_hotlist->rtt; + dest_ap->rtt_sd = src_hotlist->rtt_sd; + dest_ap->beaconPeriod = src_hotlist->beacon_interval; + dest_ap->capability = src_hotlist->capabilities; + dest_ap->ieLength = src_hotlist-> ie_length; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid, + dest_ap->bssid); + vos_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid, + src_hotlist->ssid.ssid_len); + dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0'; + dest_ap++; + src_hotlist++; + } + + dest_hotlist->ap_found = ssid_found; + mac->sme.pExtScanIndCb(mac->hHdd, + eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND, + dest_hotlist); + WMA_LOGD("%s: sending hotlist ssid match event", __func__); + vos_mem_free(dest_hotlist); + return 0; +} +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +static int wma_unified_link_iface_stats_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs; + wmi_iface_link_stats_event_fixed_param *fixed_param; + wmi_iface_link_stats *link_stats; + wmi_wmm_ac_stats *ac_stats; + tSirLLStatsResults *link_stats_results; + u_int8_t *results, *t_link_stats, *t_ac_stats; + u_int32_t next_res_offset, next_ac_offset, count; + u_int32_t roaming_offset , roaming_size; + size_t link_stats_size, ac_stats_size, iface_info_size; + size_t link_stats_results_size; + + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + + if (!pMac) { + WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__); + return -EINVAL; + } + + if (!pMac->sme.pLinkLayerStatsIndCallback) { + WMA_LOGD("%s: HDD callback is null", __func__); + return -EINVAL; + } + + WMA_LOGD("%s: Posting Iface Stats event to HDD", __func__); + param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *)cmd_param_info; + if (!param_tlvs) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + + /* + * cmd_param_info contains + * wmi_iface_link_stats_event_fixed_param fixed_param; + * wmi_iface_link_stats iface_link_stats; + * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats) + */ + fixed_param = param_tlvs->fixed_param; + link_stats = param_tlvs->iface_link_stats; + ac_stats = param_tlvs->ac; + + if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats)) { + WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__); + return -EINVAL; + } + + link_stats_size = sizeof(tSirWifiIfaceStat); + iface_info_size = sizeof(tSirWifiInterfaceInfo); + ac_stats_size = sizeof(tSirWifiWmmAcStat); + link_stats_results_size = sizeof(*link_stats_results) + + link_stats_size; + + link_stats_results = vos_mem_malloc(link_stats_results_size); + if (!link_stats_results) { + WMA_LOGD("%s: could not allocate mem for stats results-len %zu", + __func__, link_stats_results_size); + return -ENOMEM; + } + + WMA_LOGD("Interface stats from FW event buf"); + WMA_LOGD("Fixed Param:"); + WMA_LOGD("request_id %u vdev_id %u", + fixed_param->request_id,fixed_param->vdev_id); + + WMA_LOGD("Iface Stats:"); + WMA_LOGD("beacon_rx %u mgmt_rx %u mgmt_action_rx %u mgmt_action_tx %u " + "rssi_mgmt %u rssi_data %u rssi_ack %u num_peers %u " + "num_peer_events %u num_ac %u roam_state %u" + " avg_bcn_spread_offset_high %u" + " avg_bcn_spread_offset_low %u" + " is leaky_ap %u" + " avg_rx_frames_leaked %u" + " rx_leak_window %u", + link_stats->beacon_rx, link_stats->mgmt_rx, + link_stats->mgmt_action_rx, link_stats->mgmt_action_tx, + link_stats->rssi_mgmt, link_stats->rssi_data, + link_stats->rssi_ack, link_stats->num_peers, + link_stats->num_peer_events, link_stats->num_ac, + link_stats->roam_state, + link_stats->avg_bcn_spread_offset_high, + link_stats->avg_bcn_spread_offset_low, + link_stats->is_leaky_ap, + link_stats->avg_rx_frms_leaked, + link_stats->rx_leak_window); + + vos_mem_zero(link_stats_results, link_stats_results_size); + + link_stats_results->paramId = WMI_LINK_STATS_IFACE; + link_stats_results->rspId = fixed_param->request_id; + link_stats_results->ifaceId = fixed_param->vdev_id; + link_stats_results->num_peers = link_stats->num_peers; + link_stats_results->peer_event_number = 0; + link_stats_results->moreResultToFollow = 0; + + results = (u_int8_t *)link_stats_results->results; + t_link_stats = (u_int8_t *)link_stats; + t_ac_stats = (u_int8_t *)ac_stats; + + /* Copy roaming state */ + roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming); + roaming_size = member_size(tSirWifiInterfaceInfo, roaming); + + vos_mem_copy(results + roaming_offset, &link_stats->roam_state, + roaming_size); + + vos_mem_copy(results + iface_info_size, + t_link_stats + WMI_TLV_HDR_SIZE, + link_stats_size - iface_info_size - WIFI_AC_MAX * ac_stats_size); + + next_res_offset = link_stats_size - WIFI_AC_MAX * ac_stats_size; + next_ac_offset = WMI_TLV_HDR_SIZE; + + WMA_LOGD("AC Stats:"); + for (count = 0; count < link_stats->num_ac; count++) { + WMA_LOGD("ac_type %u tx_mpdu %u rx_mpdu %u tx_mcast %u " + "rx_mcast %u rx_ampdu %u tx_ampdu %u mpdu_lost %u " + "retries %u retries_short %u retries_long %u " + "contention_time_min %u contention_time_max %u " + "contention_time_avg %u contention_num_samples %u", + ac_stats->ac_type, ac_stats->tx_mpdu, ac_stats->rx_mpdu, + ac_stats->tx_mcast, ac_stats->rx_mcast, + ac_stats->rx_ampdu,ac_stats->tx_ampdu, + ac_stats->mpdu_lost, ac_stats->retries, + ac_stats->retries_short, ac_stats->retries_long, + ac_stats->contention_time_min, + ac_stats->contention_time_max, + ac_stats->contention_time_avg, + ac_stats->contention_num_samples); + ac_stats++; + + vos_mem_copy(results + next_res_offset, + t_ac_stats + next_ac_offset, + ac_stats_size); + next_res_offset += ac_stats_size; + next_ac_offset += sizeof(*ac_stats); + } + + /* call hdd callback with Link Layer Statistics + * vdev_id/ifacId in link_stats_results will be + * used to retrieve the correct HDD context + */ + pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd, + WDA_LINK_LAYER_STATS_RESULTS_RSP, + link_stats_results); + WMA_LOGD("%s: Iface Stats event posted to HDD", __func__); + vos_mem_free(link_stats_results); + + return 0; +} + +static int wma_unified_link_peer_stats_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs; + wmi_peer_stats_event_fixed_param *fixed_param; + wmi_peer_link_stats *peer_stats, *temp_peer_stats; + wmi_rate_stats *rate_stats; + tSirLLStatsResults *link_stats_results; + u_int8_t *results, *t_peer_stats, *t_rate_stats; + u_int32_t count, num_rates=0; + u_int32_t next_res_offset, next_peer_offset, next_rate_offset; + size_t peer_info_size, peer_stats_size, rate_stats_size; + size_t link_stats_results_size; + + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + + if (!pMac) { + WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__); + return -EINVAL; + } + + if (!pMac->sme.pLinkLayerStatsIndCallback) { + WMA_LOGD("%s: HDD callback is null", __func__); + return -EINVAL; + } + + WMA_LOGD("%s: Posting Peer Stats event to HDD", __func__); + param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *)cmd_param_info; + if (!param_tlvs) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + /* + * cmd_param_info contains + * wmi_peer_stats_event_fixed_param fixed_param; + * num_peers * size of(struct wmi_peer_link_stats) + * num_rates * size of(struct wmi_rate_stats) + * num_rates is the sum of the rates of all the peers. + */ + fixed_param = param_tlvs->fixed_param; + peer_stats = param_tlvs->peer_stats; + rate_stats = param_tlvs->peer_rate_stats; + + if (!fixed_param || !peer_stats || + (peer_stats->num_rates && !rate_stats)) { + WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__); + return -EINVAL; + } + + /* + * num_rates - sum of the rates of all the peers + */ + temp_peer_stats = (wmi_peer_link_stats*)peer_stats; + for (count = 0; count < fixed_param->num_peers; count++) { + num_rates += temp_peer_stats->num_rates; + temp_peer_stats++; + } + + peer_stats_size = sizeof(tSirWifiPeerStat); + peer_info_size = sizeof(tSirWifiPeerInfo); + rate_stats_size = sizeof(tSirWifiRateStat); + link_stats_results_size = sizeof(*link_stats_results) + peer_stats_size + + (fixed_param->num_peers * peer_info_size) + + (num_rates * rate_stats_size); + + link_stats_results = vos_mem_malloc(link_stats_results_size); + if (NULL == link_stats_results ) { + WMA_LOGD("%s: could not allocate mem for stats results-len %zu", + __func__, link_stats_results_size); + return -ENOMEM; + } + + WMA_LOGD("Peer stats from FW event buf"); + WMA_LOGD("Fixed Param:"); + WMA_LOGD("request_id %u num_peers %u peer_event_number %u more_data %u", + fixed_param->request_id, fixed_param->num_peers, + fixed_param->peer_event_number, fixed_param->more_data); + + vos_mem_zero(link_stats_results, link_stats_results_size); + + link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER; + link_stats_results->rspId = fixed_param->request_id; + link_stats_results->ifaceId = 0; + link_stats_results->num_peers = fixed_param->num_peers; + link_stats_results->peer_event_number = fixed_param->peer_event_number; + link_stats_results->moreResultToFollow = fixed_param->more_data; + + vos_mem_copy(link_stats_results->results, + &fixed_param->num_peers, peer_stats_size); + + results = (u_int8_t *)link_stats_results->results; + t_peer_stats = (u_int8_t *)peer_stats; + t_rate_stats = (u_int8_t *)rate_stats; + next_res_offset = peer_stats_size; + next_peer_offset = WMI_TLV_HDR_SIZE; + next_rate_offset = WMI_TLV_HDR_SIZE; + for (count = 0; count < fixed_param->num_peers; count++) { + WMA_LOGD("Peer Info:"); + WMA_LOGD("peer_type %u capabilities %u num_rates %u", + peer_stats->peer_type, peer_stats->capabilities, + peer_stats->num_rates); + + vos_mem_copy(results + next_res_offset, + t_peer_stats + next_peer_offset, + peer_info_size); + next_res_offset += peer_info_size; + + /* Copy rate stats associated with this peer */ + for (count = 0; count < peer_stats->num_rates; count++) { + WMA_LOGD("Rate Stats Info:"); + WMA_LOGD("rate %u bitrate %u tx_mpdu %u rx_mpdu %u " + "mpdu_lost %u retries %u retries_short %u " + "retries_long %u", rate_stats->rate, + rate_stats->bitrate, rate_stats->tx_mpdu, + rate_stats->rx_mpdu, rate_stats->mpdu_lost, + rate_stats->retries, rate_stats->retries_short, + rate_stats->retries_long); + rate_stats++; + + vos_mem_copy(results + next_res_offset, + t_rate_stats + next_rate_offset, + rate_stats_size); + next_res_offset += rate_stats_size; + next_rate_offset += sizeof(*rate_stats); + } + next_peer_offset += sizeof(*peer_stats); + peer_stats++; + } + + /* call hdd callback with Link Layer Statistics + * vdev_id/ifacId in link_stats_results will be + * used to retrieve the correct HDD context + */ + pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd, + WDA_LINK_LAYER_STATS_RESULTS_RSP, + link_stats_results); + WMA_LOGD("%s: Peer Stats event posted to HDD", __func__); + vos_mem_free(link_stats_results); + + return 0; +} + +static int wma_unified_link_radio_stats_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs; + wmi_radio_link_stats_event_fixed_param *fixed_param; + wmi_radio_link_stats *radio_stats; + wmi_channel_stats *channel_stats; + tSirLLStatsResults *link_stats_results; + u_int8_t *results, *t_radio_stats, *t_channel_stats; + u_int32_t next_res_offset, next_chan_offset, count; + size_t radio_stats_size, chan_stats_size; + size_t link_stats_results_size; + + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + + if (!pMac) { + WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__); + return -EINVAL; + } + + if (!pMac->sme.pLinkLayerStatsIndCallback) { + WMA_LOGD("%s: HDD callback is null", __func__); + return -EINVAL; + } + + WMA_LOGD("%s: Posting Radio Stats event to HDD", __func__); + param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *)cmd_param_info; + if (!param_tlvs) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + + /* + * cmd_param_info contains + * wmi_radio_link_stats_event_fixed_param fixed_param; + * size of(struct wmi_radio_link_stats); + * num_channels * size of(struct wmi_channel_stats) + */ + fixed_param = param_tlvs->fixed_param; + radio_stats = param_tlvs->radio_stats; + channel_stats = param_tlvs->channel_stats; + + if (!fixed_param || !radio_stats || + (radio_stats->num_channels && !channel_stats)) { + WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__); + return -EINVAL; + } + + radio_stats_size = sizeof(tSirWifiRadioStat); + chan_stats_size = sizeof(tSirWifiChannelStats); + link_stats_results_size = sizeof(*link_stats_results) + + radio_stats_size + + (radio_stats->num_channels * chan_stats_size); + + link_stats_results = vos_mem_malloc(link_stats_results_size); + if (NULL == link_stats_results ) { + WMA_LOGD("%s: could not allocate mem for stats results-len %zu", + __func__, link_stats_results_size); + return -ENOMEM; + } + + WMA_LOGD("Radio stats from FW event buf"); + WMA_LOGD("Fixed Param:"); + WMA_LOGD("request_id %u num_radio %u more_radio_events %u", + fixed_param->request_id, fixed_param->num_radio, + fixed_param->more_radio_events); + + WMA_LOGD("Radio Info"); + WMA_LOGD("radio_id %u on_time %u tx_time %u rx_time %u on_time_scan %u " + "on_time_nbd %u on_time_gscan %u on_time_roam_scan %u " + "on_time_pno_scan %u on_time_hs20 %u num_channels %u", + radio_stats->radio_id, radio_stats->on_time, + radio_stats->tx_time, radio_stats->rx_time, + radio_stats->on_time_scan, radio_stats->on_time_nbd, + radio_stats->on_time_gscan, + radio_stats->on_time_roam_scan, + radio_stats->on_time_pno_scan, + radio_stats->on_time_hs20, + radio_stats->num_channels); + + vos_mem_zero(link_stats_results, link_stats_results_size); + + link_stats_results->paramId = WMI_LINK_STATS_RADIO; + link_stats_results->rspId = fixed_param->request_id; + link_stats_results->ifaceId = 0; + link_stats_results->num_radio = fixed_param->num_radio; + link_stats_results->peer_event_number = 0; + link_stats_results->moreResultToFollow = fixed_param->more_radio_events; + + results = (u_int8_t *)link_stats_results->results; + t_radio_stats = (u_int8_t *)radio_stats; + t_channel_stats = (u_int8_t *)channel_stats; + + vos_mem_copy(results, t_radio_stats + WMI_TLV_HDR_SIZE, + radio_stats_size); + + next_res_offset = radio_stats_size; + next_chan_offset = WMI_TLV_HDR_SIZE; + WMA_LOGD("Channel Stats Info"); + for (count = 0; count < radio_stats->num_channels; count++) { + WMA_LOGD("channel_width %u center_freq %u center_freq0 %u " + "center_freq1 %u radio_awake_time %u cca_busy_time %u", + channel_stats->channel_width, channel_stats->center_freq, + channel_stats->center_freq0, channel_stats->center_freq1, + channel_stats->radio_awake_time, + channel_stats->cca_busy_time); + channel_stats++; + + vos_mem_copy(results + next_res_offset, + t_channel_stats + next_chan_offset, + chan_stats_size); + next_res_offset += chan_stats_size; + next_chan_offset += sizeof(*channel_stats); + } + + /* call hdd callback with Link Layer Statistics + * vdev_id/ifacId in link_stats_results will be + * used to retrieve the correct HDD context + */ + pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd, + WDA_LINK_LAYER_STATS_RESULTS_RSP, + link_stats_results); + WMA_LOGD("%s: Radio Stats event posted to HDD", __func__); + vos_mem_free(link_stats_results); + + return 0; +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +/** + * wma_fw_mem_dump_event_handler() - handles fw memory dump event + * + * handle - pointer to wma handle. + * cmd_param_info - pointer to TLV info received in the event. + * len - length of data in @cmd_param_info + * + * This function is a handler for firmware memory dump event. + */ +#ifdef WLAN_FEATURE_MEMDUMP +static int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *param_buf; + wmi_update_fw_mem_dump_fixed_param *event; + VOS_STATUS status; + + param_buf = + (WMI_UPDATE_FW_MEM_DUMP_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGA("%s: Invalid stats event", __func__); + return -EINVAL; + } + + event = param_buf->fixed_param; + + status = wma_fw_mem_dump_rsp(event->request_id, + event->fw_mem_dump_complete); + if (VOS_STATUS_SUCCESS != status) { + return -EINVAL; + } + + WMA_LOGI("FW MEM DUMP RSP posted successfully"); + return 0; +} +#else +static int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + return 0; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +u_int8_t *wma_add_p2p_ie(u_int8_t *frm) +{ + u_int8_t wfa_oui[3] = WMA_P2P_WFA_OUI; + struct p2p_ie *p2p_ie=(struct p2p_ie *) frm; + + p2p_ie->p2p_id = WMA_P2P_IE_ID; + p2p_ie->p2p_oui[0] = wfa_oui[0]; + p2p_ie->p2p_oui[1] = wfa_oui[1]; + p2p_ie->p2p_oui[2] = wfa_oui[2]; + p2p_ie->p2p_oui_type = WMA_P2P_WFA_VER; + p2p_ie->p2p_len = 4; + return (frm + sizeof(struct p2p_ie)); +} + +static void wma_update_beacon_noa_ie( + struct beacon_info *bcn, + u_int16_t new_noa_sub_ie_len) +{ + struct p2p_ie *p2p_ie; + u_int8_t *buf; + + /* if there is nothing to add, just return */ + if (new_noa_sub_ie_len == 0) { + if (bcn->noa_sub_ie_len && bcn->noa_ie) { + WMA_LOGD("%s: NoA is present in previous beacon, " + "but not present in swba event, " + "So Reset the NoA", + __func__); + /* TODO: Assuming p2p noa ie is last ie in the beacon */ + vos_mem_zero(bcn->noa_ie, (bcn->noa_sub_ie_len + + sizeof(struct p2p_ie)) ); + bcn->len -= (bcn->noa_sub_ie_len + + sizeof(struct p2p_ie)); + bcn->noa_ie = NULL; + bcn->noa_sub_ie_len = 0; + } + WMA_LOGD("%s: No need to update NoA", __func__); + return; + } + + if (bcn->noa_sub_ie_len && bcn->noa_ie) { + /* NoA present in previous beacon, update it */ + WMA_LOGD("%s: NoA present in previous beacon, " + "update the NoA IE, bcn->len %u" + "bcn->noa_sub_ie_len %u", + __func__, bcn->len, bcn->noa_sub_ie_len); + bcn->len -= (bcn->noa_sub_ie_len + sizeof(struct p2p_ie)) ; + vos_mem_zero(bcn->noa_ie, + (bcn->noa_sub_ie_len + sizeof(struct p2p_ie))); + } else { /* NoA is not present in previous beacon */ + WMA_LOGD("%s: NoA not present in previous beacon, add it" + "bcn->len %u", __func__, bcn->len); + buf = adf_nbuf_data(bcn->buf); + bcn->noa_ie = buf + bcn->len; + } + + bcn->noa_sub_ie_len = new_noa_sub_ie_len; + wma_add_p2p_ie(bcn->noa_ie); + p2p_ie = (struct p2p_ie *) bcn->noa_ie; + p2p_ie->p2p_len += new_noa_sub_ie_len; + vos_mem_copy((bcn->noa_ie + sizeof(struct p2p_ie)), bcn->noa_sub_ie, + new_noa_sub_ie_len); + + bcn->len += (new_noa_sub_ie_len + sizeof(struct p2p_ie)); + WMA_LOGI("%s: Updated beacon length with NoA Ie is %u", + __func__, bcn->len); +} + +static void wma_p2p_create_sub_ie_noa( + u_int8_t *buf, + struct p2p_sub_element_noa *noa, + u_int16_t *new_noa_sub_ie_len) +{ + u_int8_t tmp_octet = 0; + int i; + u_int8_t *buf_start = buf; + + *buf++ = WMA_P2P_SUB_ELEMENT_NOA; /* sub-element id */ + ASSERT(noa->num_descriptors <= WMA_MAX_NOA_DESCRIPTORS); + + /* + * Length = (2 octets for Index and CTWin/Opp PS) and + * (13 octets for each NOA Descriptors) + */ + P2PIE_PUT_LE16(buf, WMA_NOA_IE_SIZE(noa->num_descriptors)); + buf += 2; + + *buf++ = noa->index; /* Instance Index */ + + tmp_octet = noa->ctwindow & WMA_P2P_NOA_IE_CTWIN_MASK; + if (noa->oppPS) { + tmp_octet |= WMA_P2P_NOA_IE_OPP_PS_SET; + } + *buf++ = tmp_octet; /* Opp Ps and CTWin capabilities */ + + for (i = 0; i < noa->num_descriptors; i++) { + ASSERT(noa->noa_descriptors[i].type_count != 0); + + *buf++ = noa->noa_descriptors[i].type_count; + + P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].duration); + buf += 4; + P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].interval); + buf += 4; + P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].start_time); + buf += 4; + } + *new_noa_sub_ie_len = (buf - buf_start); +} + +static void wma_update_noa(struct beacon_info *beacon, + struct p2p_sub_element_noa *noa_ie) +{ + u_int16_t new_noa_sub_ie_len; + + /* Call this function by holding the spinlock on beacon->lock */ + + if (noa_ie) { + if ((noa_ie->ctwindow == 0) && (noa_ie->oppPS == 0) && + (noa_ie->num_descriptors == 0)) { + /* NoA is not present */ + WMA_LOGD("%s: NoA is not present", __func__); + new_noa_sub_ie_len = 0; + } + else { + /* Create the binary blob containing NOA sub-IE */ + WMA_LOGD("%s: Create NOA sub ie", __func__); + wma_p2p_create_sub_ie_noa(&beacon->noa_sub_ie[0], + noa_ie, &new_noa_sub_ie_len); + } + } + else { + WMA_LOGD("%s: No need to add NOA", __func__); + new_noa_sub_ie_len = 0; /* no NOA IE sub-attributes */ + } + + wma_update_beacon_noa_ie(beacon, new_noa_sub_ie_len); +} + +static void wma_update_probe_resp_noa(tp_wma_handle wma_handle, + struct p2p_sub_element_noa *noa_ie) +{ + tSirP2PNoaAttr *noa_attr = (tSirP2PNoaAttr *) vos_mem_malloc(sizeof(tSirP2PNoaAttr)); + WMA_LOGD("Received update NoA event"); + if (!noa_attr) { + WMA_LOGE("Failed to allocate memory for tSirP2PNoaAttr"); + return; + } + + vos_mem_zero(noa_attr, sizeof(tSirP2PNoaAttr)); + + noa_attr->index = noa_ie->index; + noa_attr->oppPsFlag = noa_ie->oppPS; + noa_attr->ctWin = noa_ie->ctwindow; + if (!noa_ie->num_descriptors) { + WMA_LOGD("Zero NoA descriptors"); + } + else { + WMA_LOGD("%d NoA descriptors", noa_ie->num_descriptors); + noa_attr->uNoa1IntervalCnt = + noa_ie->noa_descriptors[0].type_count; + noa_attr->uNoa1Duration = + noa_ie->noa_descriptors[0].duration; + noa_attr->uNoa1Interval = + noa_ie->noa_descriptors[0].interval; + noa_attr->uNoa1StartTime = + noa_ie->noa_descriptors[0].start_time; + if (noa_ie->num_descriptors > 1) { + noa_attr->uNoa2IntervalCnt = + noa_ie->noa_descriptors[1].type_count; + noa_attr->uNoa2Duration = + noa_ie->noa_descriptors[1].duration; + noa_attr->uNoa2Interval = + noa_ie->noa_descriptors[1].interval; + noa_attr->uNoa2StartTime = + noa_ie->noa_descriptors[1].start_time; + } + } + WMA_LOGI("Sending SIR_HAL_P2P_NOA_ATTR_IND to LIM"); + wma_send_msg(wma_handle, SIR_HAL_P2P_NOA_ATTR_IND, (void *)noa_attr , + 0); +} + +static void wma_send_bcn_buf_ll(tp_wma_handle wma, + ol_txrx_pdev_handle pdev, + u_int8_t vdev_id, + WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf) +{ + wmi_bcn_send_from_host_cmd_fixed_param *cmd; + struct ieee80211_frame *wh; + struct beacon_info *bcn; + wmi_tim_info *tim_info = param_buf->tim_info; + u_int8_t *bcn_payload; + wmi_buf_t wmi_buf; + a_status_t ret; + struct beacon_tim_ie *tim_ie; + wmi_p2p_noa_info *p2p_noa_info = param_buf->p2p_noa_info; + struct p2p_sub_element_noa noa_ie; + u_int8_t i; + int status; + + bcn = wma->interfaces[vdev_id].beacon; + if (!bcn->buf) { + WMA_LOGE("%s: Invalid beacon buffer", __func__); + return; + } + + wmi_buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd)); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return; + } + + adf_os_spin_lock_bh(&bcn->lock); + + bcn_payload = adf_nbuf_data(bcn->buf); + + tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]); + + if(tim_info->tim_changed) { + if(tim_info->tim_num_ps_pending) + vos_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap, + WMA_TIM_SUPPORTED_PVB_LENGTH); + else + vos_mem_zero(&tim_ie->tim_bitmap, + WMA_TIM_SUPPORTED_PVB_LENGTH); + /* + * Currently we support fixed number of + * peers as limited by HAL_NUM_STA. + * tim offset is always 0 + */ + tim_ie->tim_bitctl = 0; + } + + /* Update DTIM Count */ + if (tim_ie->dtim_count == 0) + tim_ie->dtim_count = tim_ie->dtim_period - 1; + else + tim_ie->dtim_count--; + + /* + * DTIM count needs to be backedup so that + * when umac updates the beacon template + * current dtim count can be updated properly + */ + bcn->dtim_count = tim_ie->dtim_count; + + /* update state for buffered multicast frames on DTIM */ + if (tim_info->tim_mcast && (tim_ie->dtim_count == 0 || + tim_ie->dtim_period == 1)) + tim_ie->tim_bitctl |= 1; + else + tim_ie->tim_bitctl &= ~1; + + /* To avoid sw generated frame sequence the same as H/W generated frame, + * the value lower than min_sw_seq is reserved for HW generated frame */ + if ((bcn->seq_no & IEEE80211_SEQ_MASK) < MIN_SW_SEQ) + bcn->seq_no = MIN_SW_SEQ; + + wh = (struct ieee80211_frame *) bcn_payload; + *(u_int16_t *)&wh->i_seq[0] = htole16(bcn->seq_no + << IEEE80211_SEQ_SEQ_SHIFT); + bcn->seq_no++; + + if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) { + vos_mem_zero(&noa_ie, sizeof(noa_ie)); + + noa_ie.index = (u_int8_t)WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info); + noa_ie.oppPS = (u_int8_t)WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info); + noa_ie.ctwindow = (u_int8_t)WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info); + noa_ie.num_descriptors = (u_int8_t)WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET( + p2p_noa_info); + WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, " + "num_descriptors = %u", __func__, noa_ie.index, + noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors); + for(i = 0; i < noa_ie.num_descriptors; i++) { + noa_ie.noa_descriptors[i].type_count = + (u_int8_t)p2p_noa_info->noa_descriptors[i].type_count; + noa_ie.noa_descriptors[i].duration = + p2p_noa_info->noa_descriptors[i].duration; + noa_ie.noa_descriptors[i].interval = + p2p_noa_info->noa_descriptors[i].interval; + noa_ie.noa_descriptors[i].start_time = + p2p_noa_info->noa_descriptors[i].start_time; + WMA_LOGI("%s: NoA descriptor[%d] type_count %u, " + "duration %u, interval %u, start_time = %u", + __func__, i, + noa_ie.noa_descriptors[i].type_count, + noa_ie.noa_descriptors[i].duration, + noa_ie.noa_descriptors[i].interval, + noa_ie.noa_descriptors[i].start_time); + } + wma_update_noa(bcn, &noa_ie); + + /* Send a msg to LIM to update the NoA IE in probe response + * frames transmitted by the host */ + wma_update_probe_resp_noa(wma, &noa_ie); + } + + if (bcn->dma_mapped) { + adf_nbuf_unmap_single(pdev->osdev, bcn->buf, + ADF_OS_DMA_TO_DEVICE); + bcn->dma_mapped = 0; + } + ret = adf_nbuf_map_single(pdev->osdev, bcn->buf, + ADF_OS_DMA_TO_DEVICE); + if (ret != A_STATUS_OK) { + adf_nbuf_free(wmi_buf); + WMA_LOGE("%s: failed map beacon buf to DMA region", + __func__); + adf_os_spin_unlock_bh(&bcn->lock); + return; + } + + bcn->dma_mapped = 1; + cmd = (wmi_bcn_send_from_host_cmd_fixed_param *) wmi_buf_data(wmi_buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_bcn_send_from_host_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->data_len = bcn->len; + cmd->frame_ctrl = *((A_UINT16 *)wh->i_fc); + cmd->frag_ptr = adf_nbuf_get_frag_paddr_lo(bcn->buf, 0); + + /* Notify Firmware of DTM and mcast/bcast traffic */ + if (tim_ie->dtim_count == 0) { + cmd->dtim_flag |= WMI_BCN_SEND_DTIM_ZERO; + /* deliver mcast/bcast traffic in next DTIM beacon */ + if (tim_ie->tim_bitctl & 0x01) + cmd->dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET; + } + + status = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, sizeof(*cmd), + WMI_PDEV_SEND_BCN_CMDID); + + if (status != EOK) { + WMA_LOGE("Failed to send WMI_PDEV_SEND_BCN_CMDID command"); + wmi_buf_free(wmi_buf); + } + adf_os_spin_unlock_bh(&bcn->lock); +} + +static int wma_beacon_swba_handler(void *handle, u_int8_t *event, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_HOST_SWBA_EVENTID_param_tlvs *param_buf; + wmi_host_swba_event_fixed_param *swba_event; + u_int32_t vdev_map; + ol_txrx_pdev_handle pdev; + u_int8_t vdev_id = 0; + + param_buf = (WMI_HOST_SWBA_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("Invalid swba event buffer"); + return -EINVAL; + } + swba_event = param_buf->fixed_param; + vdev_map = swba_event->vdev_map; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (!pdev) { + WMA_LOGE("%s: pdev is NULL", __func__); + return -EINVAL; + } + + for ( ; vdev_map; vdev_id++, vdev_map >>= 1) { + if (!(vdev_map & 0x1)) + continue; + if (!wdi_out_cfg_is_high_latency(pdev->ctrl_pdev)) + wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf); + break; + } + return 0; +} + +static int wma_csa_offload_handler(void *handle, u_int8_t *event, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf; + wmi_csa_event_fixed_param *csa_event; + u_int8_t bssid[IEEE80211_ADDR_LEN]; + u_int8_t vdev_id = 0; + u_int8_t cur_chan = 0; + struct ieee80211_channelswitch_ie *csa_ie; + tpCSAOffloadParams csa_offload_event; + struct ieee80211_extendedchannelswitch_ie *xcsa_ie; + struct ieee80211_ie_wide_bw_switch *wb_ie; + struct wma_txrx_node *intr = wma->interfaces; + + param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event; + + WMA_LOGD("%s: Enter", __func__); + if (!param_buf) { + WMA_LOGE("Invalid csa event buffer"); + return -EINVAL; + } + csa_event = param_buf->fixed_param; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]); + + if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) { + WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__); + return -EINVAL; + } + + csa_offload_event = vos_mem_malloc(sizeof(*csa_offload_event)); + if (!csa_offload_event) { + WMA_LOGE("VOS MEM Alloc Failed for csa_offload_event"); + return -EINVAL; + } + + vos_mem_zero(csa_offload_event, sizeof(*csa_offload_event)); + vos_mem_copy(csa_offload_event->bssId, &bssid, ETH_ALEN); + + if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) { + csa_ie = (struct ieee80211_channelswitch_ie *)(&csa_event->csa_ie[0]); + csa_offload_event->channel = csa_ie->newchannel; + csa_offload_event->switchmode = csa_ie->switchmode; + } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) { + xcsa_ie = (struct ieee80211_extendedchannelswitch_ie*)(&csa_event->xcsa_ie[0]); + csa_offload_event->channel = xcsa_ie->newchannel; + csa_offload_event->switchmode = xcsa_ie->switchmode; + } else { + WMA_LOGE("CSA Event error: No CSA IE present"); + vos_mem_free(csa_offload_event); + return -EINVAL; + } + + if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) { + wb_ie = (struct ieee80211_ie_wide_bw_switch*)(&csa_event->wb_ie[0]); + csa_offload_event->new_ch_width = wb_ie->new_ch_width; + csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1; + csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2; + } + + csa_offload_event->ies_present_flag = csa_event->ies_present_flag; + + WMA_LOGD("CSA: New Channel = %d BSSID:%pM", + csa_offload_event->channel, + csa_offload_event->bssId); + + cur_chan = vos_freq_to_chan(intr[vdev_id].mhz); + /* + * basic sanity check: requested channel should not be 0 + * and equal to home channel + */ + if( (0 == csa_offload_event->channel) || + (cur_chan == csa_offload_event->channel) ) { + WMA_LOGE("CSA Event with channel %d. Ignore !!", + csa_offload_event->channel); + vos_mem_free(csa_offload_event); + return -EINVAL; + } + wma->interfaces[vdev_id].is_channel_switch = VOS_TRUE; + wma_send_msg(wma, WDA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0); + return 0; +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +static int wma_gtk_offload_status_event(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *status; + WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf; + tpSirGtkOffloadGetInfoRspParams resp; + vos_msg_t vos_msg; + u_int8_t *bssid; + + WMA_LOGD("%s Enter", __func__); + + param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *)event; + if (!param_buf) { + WMA_LOGE("param_buf is NULL"); + return -EINVAL; + } + + status = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *)param_buf->fixed_param; + + if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) { + WMA_LOGE("Invalid length for GTK status"); + return -EINVAL; + } + bssid = wma_find_bssid_by_vdev_id(wma, status->vdev_id); + if (!bssid) { + WMA_LOGE("invalid bssid for vdev id %d", status->vdev_id); + return -ENOENT; + } + + resp = vos_mem_malloc(sizeof(*resp)); + if (!resp) { + WMA_LOGE("%s: Failed to alloc response", __func__); + return -ENOMEM; + } + vos_mem_zero(resp, sizeof(*resp)); + resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP; + resp->mesgLen = sizeof(*resp); + resp->ulStatus = VOS_STATUS_SUCCESS; + resp->ulTotalRekeyCount = status->refresh_cnt; + /* TODO: Is the total rekey count and GTK rekey count same? */ + resp->ulGTKRekeyCount = status->refresh_cnt; + + vos_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter, + GTK_REPLAY_COUNTER_BYTES); + + vos_mem_copy(resp->bssId, bssid, ETH_ALEN); + +#ifdef IGTK_OFFLOAD + /* TODO: Is the refresh count same for GTK and IGTK? */ + resp->ulIGTKRekeyCount = status->refresh_cnt; +#endif + + vos_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP; + vos_msg.bodyptr = (void *)resp; + vos_msg.bodyval = 0; + + if (vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vos_msg) + != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to post GTK response to SME"); + vos_mem_free(resp); + return -EINVAL; + } + + WMA_LOGD("GTK: got target status with replay counter " + "%02x%02x%02x%02x%02x%02x%02x%02x. vdev %d " + "Refresh GTK %d times exchanges since last set operation", + status->replay_counter[0], + status->replay_counter[1], + status->replay_counter[2], + status->replay_counter[3], + status->replay_counter[4], + status->replay_counter[5], + status->replay_counter[6], + status->replay_counter[7], + status->vdev_id, status->refresh_cnt); + + WMA_LOGD("%s Exit", __func__); + + return 0; +} +#endif + +#ifdef FEATURE_OEM_DATA_SUPPORT +static int wma_oem_capability_event_callback(void *handle, + u_int8_t *datap, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf; + u_int8_t *data; + u_int32_t datalen; + u_int32_t *msg_subtype; + tStartOemDataRsp *pStartOemDataRsp; + + param_buf = (WMI_OEM_CAPABILITY_EVENTID_param_tlvs *)datap; + if (!param_buf) { + WMA_LOGE("%s: Received NULL buf ptr from FW", __func__); + return -ENOMEM; + } + + data = param_buf->data; + datalen = param_buf->num_data; + + if (!data) { + WMA_LOGE("%s: Received NULL data from FW", __func__); + return -EINVAL; + } + + /* wma puts 4 bytes prefix for msg subtype, so length + * of data received from target should be 4 bytes less + * then max allowed + */ + if (datalen > (OEM_DATA_RSP_SIZE - 4)) { + WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)", + __func__, datalen, (OEM_DATA_RSP_SIZE - 4)); + return -EINVAL; + } + + pStartOemDataRsp = vos_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__); + return -ENOMEM; + } + + vos_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (u_int32_t *)(&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_CAPABILITY_RSP; + vos_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); + + WMA_LOGI("%s: Sending WDA_START_OEM_DATA_RSP, data len (%d)", + __func__, datalen); + + wma_send_msg(wma, WDA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + return 0; +} + +static int wma_oem_measurement_report_event_callback(void *handle, + u_int8_t *datap, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf; + u_int8_t *data; + u_int32_t datalen; + u_int32_t *msg_subtype; + tStartOemDataRsp *pStartOemDataRsp; + + param_buf = (WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *)datap; + if (!param_buf) { + WMA_LOGE("%s: Received NULL buf ptr from FW", __func__); + return -ENOMEM; + } + + data = param_buf->data; + datalen = param_buf->num_data; + + if (!data) { + WMA_LOGE("%s: Received NULL data from FW", __func__); + return -EINVAL; + } + + /* wma puts 4 bytes prefix for msg subtype, so length + * of data received from target should be 4 bytes less + * then max allowed + */ + if (datalen > (OEM_DATA_RSP_SIZE - 4)) { + WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)", + __func__, datalen, (OEM_DATA_RSP_SIZE - 4)); + return -EINVAL; + } + + pStartOemDataRsp = vos_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__); + return -ENOMEM; + } + + vos_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (u_int32_t *)(&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_MEASUREMENT_RSP; + vos_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); + + WMA_LOGI("%s: Sending WDA_START_OEM_DATA_RSP, data len (%d)", + __func__, datalen); + + wma_send_msg(wma, WDA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + return 0; +} + +static int wma_oem_error_report_event_callback(void *handle, + u_int8_t *datap, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf; + u_int8_t *data; + u_int32_t datalen; + u_int32_t *msg_subtype; + tStartOemDataRsp *pStartOemDataRsp; + + param_buf = (WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *)datap; + if (!param_buf) { + WMA_LOGE("%s: Received NULL buf ptr from FW", __func__); + return -ENOMEM; + } + + data = param_buf->data; + datalen = param_buf->num_data; + + if (!data) { + WMA_LOGE("%s: Received NULL data from FW", __func__); + return -EINVAL; + } + + /* wma puts 4 bytes prefix for msg subtype, so length + * of data received from target should be 4 bytes less + * then max allowed + */ + if (datalen > (OEM_DATA_RSP_SIZE - 4)) { + WMA_LOGE("%s: Received data len (%d) exceeds max value (%d)", + __func__, datalen, (OEM_DATA_RSP_SIZE - 4)); + return -EINVAL; + } + + pStartOemDataRsp = vos_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__); + return -ENOMEM; + } + + vos_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (u_int32_t *)(&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_ERROR_REPORT_RSP; + vos_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); + + WMA_LOGI("%s: Sending WDA_START_OEM_DATA_RSP, data len (%d)", + __func__, datalen); + + wma_send_msg(wma, WDA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + return 0; +} +#endif /* FEATURE_OEM_DATA_SUPPORT */ + +static int wma_p2p_noa_event_handler(void *handle, u_int8_t *event, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_P2P_NOA_EVENTID_param_tlvs *param_buf; + wmi_p2p_noa_event_fixed_param *p2p_noa_event; + u_int8_t vdev_id, i; + wmi_p2p_noa_info *p2p_noa_info; + struct p2p_sub_element_noa noa_ie; + u_int8_t *buf_ptr; + u_int32_t descriptors; + + param_buf = (WMI_P2P_NOA_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("Invalid P2P NoA event buffer"); + return -EINVAL; + } + + p2p_noa_event = param_buf->fixed_param; + buf_ptr = (u_int8_t *) p2p_noa_event; + buf_ptr += sizeof(wmi_p2p_noa_event_fixed_param); + p2p_noa_info = (wmi_p2p_noa_info *) (buf_ptr); + vdev_id = p2p_noa_event->vdev_id; + + if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) { + + vos_mem_zero(&noa_ie, sizeof(noa_ie)); + noa_ie.index = (u_int8_t)WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info); + noa_ie.oppPS = (u_int8_t)WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info); + noa_ie.ctwindow = (u_int8_t)WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info); + descriptors = WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info); + noa_ie.num_descriptors = (u_int8_t)descriptors; + + WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, " + "num_descriptors = %u", __func__, noa_ie.index, + noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors); + for(i = 0; i < noa_ie.num_descriptors; i++) { + noa_ie.noa_descriptors[i].type_count = + (u_int8_t)p2p_noa_info->noa_descriptors[i].type_count; + noa_ie.noa_descriptors[i].duration = + p2p_noa_info->noa_descriptors[i].duration; + noa_ie.noa_descriptors[i].interval = + p2p_noa_info->noa_descriptors[i].interval; + noa_ie.noa_descriptors[i].start_time = + p2p_noa_info->noa_descriptors[i].start_time; + WMA_LOGI("%s: NoA descriptor[%d] type_count %u, " + "duration %u, interval %u, start_time = %u", + __func__, i, + noa_ie.noa_descriptors[i].type_count, + noa_ie.noa_descriptors[i].duration, + noa_ie.noa_descriptors[i].interval, + noa_ie.noa_descriptors[i].start_time); + } + + /* Send a msg to LIM to update the NoA IE in probe response + * frames transmitted by the host */ + wma_update_probe_resp_noa(wma, &noa_ie); + } + + return 0; +} + +#ifdef FEATURE_WLAN_TDLS +static int wma_tdls_event_handler(void *handle, u_int8_t *event, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf = NULL; + wmi_tdls_peer_event_fixed_param *peer_event = NULL; + tSirTdlsEventNotify *tdls_event; + + if (!event) { + WMA_LOGE("%s: event param null", __func__); + return -1; + } + + param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("%s: received null buf from target", __func__); + return -1; + } + + peer_event = param_buf->fixed_param; + if (!peer_event) { + WMA_LOGE("%s: received null event data from target", __func__); + return -1; + } + + tdls_event = (tSirTdlsEventNotify *) + vos_mem_malloc(sizeof(*tdls_event)); + if (!tdls_event) { + WMA_LOGE("%s: failed to allocate memory for tdls_event", __func__); + return -1; + } + + tdls_event->sessionId = peer_event->vdev_id; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr, tdls_event->peerMac); + + switch(peer_event->peer_status) { + case WMI_TDLS_SHOULD_DISCOVER: + tdls_event->messageType = WDA_TDLS_SHOULD_DISCOVER; + break; + case WMI_TDLS_SHOULD_TEARDOWN: + tdls_event->messageType = WDA_TDLS_SHOULD_TEARDOWN; + break; + case WMI_TDLS_PEER_DISCONNECTED: + tdls_event->messageType = WDA_TDLS_PEER_DISCONNECTED; + break; + default: + vos_mem_free(tdls_event); + WMA_LOGE("%s: Discarding unknown tdls event(%d) from target", + __func__, peer_event->peer_status); + return -1; + } + + switch (peer_event->peer_reason) { + case WMI_TDLS_TEARDOWN_REASON_TX: + tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_TX; + break; + case WMI_TDLS_TEARDOWN_REASON_RSSI: + tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_RSSI; + break; + case WMI_TDLS_TEARDOWN_REASON_SCAN: + tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_SCAN; + break; + case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE: + tdls_event->peer_reason = eWNI_TDLS_DISCONNECTED_REASON_PEER_DELETE; + break; + case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT: + tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT; + break; + case WMI_TDLS_TEARDOWN_REASON_BAD_PTR: + tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_BAD_PTR; + break; + case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE: + tdls_event->peer_reason = eWNI_TDLS_TEARDOWN_REASON_NO_RESPONSE; + break; + default: + vos_mem_free(tdls_event); + WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target", + __func__, peer_event->peer_reason, peer_event->peer_status); + return -1; + } + + WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, " + "for peer: %pM, reason: %d, smesessionId: %d", + __func__, tdls_event->messageType, tdls_event->peerMac, + tdls_event->peer_reason, tdls_event->sessionId); + + wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0); + return 0; +} +#endif /* FEATURE_WLAN_TDLS */ + +/* + * WMI Handler for WMI_PHYERR_EVENTID event from firmware. + * This handler is currently handling only DFS phy errors. + * This handler will be invoked only when the DFS phyerror + * filtering offload is disabled. + * Return- 1:Success, 0:Failure + */ +static int wma_unified_phyerr_rx_event_handler(void * handle, + u_int8_t *data, u_int32_t datalen) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PHYERR_EVENTID_param_tlvs *param_tlvs; + wmi_comb_phyerr_rx_hdr *pe_hdr; + u_int8_t *bufp; + wmi_single_phyerr_rx_event *ev; + struct ieee80211com *ic = wma->dfs_ic; + adf_os_size_t n; + A_UINT64 tsf64 = 0; + int phy_err_code = 0; + int error = 0; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + bool enable_log = false; + + if (NULL == mac_ctx) { + WMA_LOGE("%s: mac_ctx is NULL", __func__); + return 0; + } + + enable_log = mac_ctx->sap.enable_dfs_phy_error_logs; + param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *)data; + + if (!param_tlvs) + { + WMA_LOGE("%s: Received NULL data from FW", __func__); + return 0; + } + + pe_hdr = param_tlvs->hdr; + if (pe_hdr == NULL) + { + WMA_LOGE("%s: Received Data PE Header is NULL", __func__); + return 0; + } + + /* Ensure it's at least the size of the header */ + if (datalen < sizeof(*pe_hdr)) + { + WMA_LOGE("%s: Expected minimum size %zu, received %d", + __func__, sizeof(*pe_hdr), datalen); + return 0; + } + if (pe_hdr->buf_len > DFS_MAX_BUF_LENGHT) + { + WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d" + "Maximum allowed buf length = %d", + __func__, pe_hdr->buf_len, DFS_MAX_BUF_LENGHT); + + return 0; + } + + /* + * Reconstruct the 64 bit event TSF. This isn't from the MAC, it's + * at the time the event was sent to us, the TSF value will be + * in the future. + */ + tsf64 = pe_hdr->tsf_l32; + tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32); + + /* + * Loop over the bufp, extracting out phyerrors + * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer, + * which isn't correct here - what we have received here + * is an array of TLV-style PHY errors. + */ + n = 0;/* Start just after the header */ + bufp = param_tlvs->bufp; + while (n < pe_hdr->buf_len) + { + /* ensure there's at least space for the header */ + if ((pe_hdr->buf_len - n) < sizeof(ev->hdr)) + { + WMA_LOGE("%s: Not enough space.(datalen=%d, n=%zu, hdr=%zu bytes", + __func__,pe_hdr->buf_len,n,sizeof(ev->hdr)); + error = 1; + break; + } + /* + * Obtain a pointer to the beginning of the current event. + * data[0] is the beginning of the WMI payload. + */ + ev = (wmi_single_phyerr_rx_event *) &bufp[n]; + + /* + * Sanity check the buffer length of the event against + * what we currently have. + * Since buf_len is 32 bits, we check if it overflows + * a large 32 bit value. It's not 0x7fffffff because + * we increase n by (buf_len + sizeof(hdr)), which would + * in itself cause n to overflow. + * If "int" is 64 bits then this becomes a moot point. + */ + if (ev->hdr.buf_len > 0x7f000000) + { + WMA_LOGE("%s:buf_len is garbage (0x%x)",__func__, + ev->hdr.buf_len); + error = 1; + break; + } + if (n + ev->hdr.buf_len > pe_hdr->buf_len) + { + WMA_LOGE("%s: buf_len exceeds available space n=%zu," + "buf_len=%d, datalen=%d", + __func__,n,ev->hdr.buf_len,pe_hdr->buf_len); + error = 1; + break; + } + phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr); + + /* + * If the phyerror category matches, + * pass radar events to the dfs pattern matching code. + * Don't pass radar events with no buffer payload. + */ + if (phy_err_code == 0x5 || phy_err_code == 0x24) + { + if (ev->hdr.buf_len > 0) + { + /* Calling in to the DFS module to process the phyerr */ + dfs_process_phyerr(ic, &ev->bufp[0], ev->hdr.buf_len, + WMI_UNIFIED_RSSI_COMB_GET(&ev->hdr) & 0xff, + /* Extension RSSI */ + WMI_UNIFIED_RSSI_COMB_GET(&ev->hdr) & 0xff, + ev->hdr.tsf_timestamp, + tsf64, enable_log); + } + } + + /* + * Advance the buffer pointer to the next PHY error. + * buflen is the length of this payload, so we need to + * advance past the current header _AND_ the payload. + */ + n += sizeof(*ev) + ev->hdr.buf_len; + + }/*end while()*/ + if (error) + { + return (0); + } + else + { + return (1); + } +} + +#ifdef WLAN_FEATURE_NAN +/* function : wma_nan_rsp_event_handler + * Descriptin : Function is used to handle nan response + * Args : wma_handle, event buffer and its length + * Returns : SUCCESS or FAILURE + */ +static int wma_nan_rsp_event_handler(void *handle, u_int8_t *event_buf, + u_int32_t len) +{ + WMI_NAN_EVENTID_param_tlvs *param_buf; + tSirNanEvent *nan_rsp_event; + wmi_nan_event_hdr *nan_rsp_event_hdr; + VOS_STATUS status; + vos_msg_t vos_msg; + u_int8_t *buf_ptr; + u_int32_t alloc_len; + + /* + * This is how received event_buf looks like + * + * <-------------------- event_buf -----------------------------------> + * + * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data --------> + * + * +-----------+---------+-----------------------+--------------------+ + * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data | + * +-----------+---------+-----------------------+--------------------+ + */ + + WMA_LOGD("%s: Posting NaN response event to SME", __func__); + param_buf = (WMI_NAN_EVENTID_param_tlvs *)event_buf; + if (!param_buf) { + WMA_LOGE("%s: Invalid nan response event buf", __func__); + return -EINVAL; + } + nan_rsp_event_hdr = param_buf->fixed_param; + buf_ptr = (u_int8_t *)nan_rsp_event_hdr; + alloc_len = sizeof(tSirNanEvent); + alloc_len += nan_rsp_event_hdr->data_len; + nan_rsp_event = (tSirNanEvent *) vos_mem_malloc(alloc_len); + if (NULL == nan_rsp_event) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return -ENOMEM; + } + + nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len; + vos_mem_copy(nan_rsp_event->event_data, buf_ptr + + sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE, + nan_rsp_event->event_data_len); + vos_msg.type = eWNI_SME_NAN_EVENT; + vos_msg.bodyptr = (void *)nan_rsp_event; + vos_msg.bodyval = 0; + + status = vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post NaN response event to SME", __func__); + vos_mem_free(nan_rsp_event); + return -1; + } + WMA_LOGD("%s: NaN response event Posted to SME", __func__); + return 0; +} +#endif + +/* + * WMI handler for WMI_DFS_RADAR_EVENTID + * This handler is registered for handling + * filtered DFS Phyerror. This handler is + * will be invoked only when DFS Phyerr + * filtering offload is enabled. + * Return- 1:Success, 0:Failure + */ +static int wma_unified_dfs_radar_rx_event_handler(void *handle, + u_int8_t *data, u_int32_t datalen) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + struct ieee80211com *ic; + struct ath_dfs *dfs; + struct dfs_event *event; + struct ieee80211_channel *chan; + int empty; + int do_check_chirp = 0; + int is_hw_chirp = 0; + int is_sw_chirp = 0; + int is_pri = 0; + + WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs; + wmi_dfs_radar_event_fixed_param *radar_event; + + ic = wma->dfs_ic; + if (NULL == ic) { + WMA_LOGE("%s: dfs_ic is NULL ", __func__); + return 0; + } + + dfs = (struct ath_dfs *)ic->ic_dfs; + param_tlvs = (WMI_DFS_RADAR_EVENTID_param_tlvs *) data; + + if (NULL == dfs) { + WMA_LOGE("%s: dfs is NULL ", __func__); + return 0; + } + /* + * This parameter holds the number + * of phyerror interrupts to the host + * after the phyerrors have passed through + * false detect filters in the firmware. + */ + dfs->dfs_phyerr_count++; + + if (!param_tlvs) { + WMA_LOGE("%s: Received NULL data from FW", __func__); + return 0; + } + + radar_event = param_tlvs->fixed_param; + + adf_os_spin_lock_bh(&ic->chan_lock); + chan = ic->ic_curchan; + + if (ic->disable_phy_err_processing) { + WMA_LOGD("%s: radar indication done,drop phyerror event", + __func__); + adf_os_spin_unlock_bh(&ic->chan_lock); + return 0; + } + + if (NV_CHANNEL_DFS != vos_nv_getChannelEnabledState(chan->ic_ieee)) { + WMA_LOGE("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS", + __func__, chan->ic_ieee); + adf_os_spin_unlock_bh(&ic->chan_lock); + return 0; + } + + adf_os_spin_unlock_bh(&ic->chan_lock); + dfs->ath_dfs_stats.total_phy_errors++; + + if (dfs->dfs_caps.ath_chip_is_bb_tlv) { + do_check_chirp = 1; + is_pri = 1; + is_hw_chirp = radar_event->pulse_is_chirp; + + if ((u_int32_t)dfs->dfs_phyerr_freq_min > + radar_event->pulse_center_freq) { + dfs->dfs_phyerr_freq_min = + (int)radar_event->pulse_center_freq; + } + + if (dfs->dfs_phyerr_freq_max < + (int)radar_event->pulse_center_freq) { + dfs->dfs_phyerr_freq_max = + (int)radar_event->pulse_center_freq; + } + } + + /* + * Now, add the parsed, checked and filtered + * radar phyerror event radar pulse event list. + * This event will then be processed by + * dfs_radar_processevent() to see if the pattern + * of pulses in radar pulse list match any radar + * singnature in the current regulatory domain. + */ + + ATH_DFSEVENTQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_eventq)); + ATH_DFSEVENTQ_UNLOCK(dfs); + if (empty) { + return 0; + } + /* + * Add the event to the list, if there's space. + */ + ATH_DFSEVENTQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_eventq)); + if (event == NULL) { + ATH_DFSEVENTQ_UNLOCK(dfs); + WMA_LOGE("%s: No more space left for queuing DFS Phyerror events", + __func__); + return 0; + } + STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); + ATH_DFSEVENTQ_UNLOCK(dfs); + dfs->dfs_phyerr_queued_count++; + dfs->dfs_phyerr_w53_counter++; + event->re_dur = (u_int8_t)radar_event->pulse_duration; + event->re_rssi = radar_event->rssi; + event->re_ts = radar_event->pulse_detect_ts & DFS_TSMASK; + event->re_full_ts = (((uint64_t)radar_event->upload_fullts_high) << 32) + | radar_event->upload_fullts_low; + + /* Index of peak magnitude */ + event->sidx = radar_event->peak_sidx; + + /* + * Handle chirp flags. + */ + if (do_check_chirp) { + event->re_flags |= DFS_EVENT_CHECKCHIRP; + if (is_hw_chirp) { + event->re_flags |= DFS_EVENT_HW_CHIRP; + } + if (is_sw_chirp) { + event->re_flags |= DFS_EVENT_SW_CHIRP; + } + } + /* + * Correctly set which channel is being reported on + */ + if (is_pri) { + event->re_chanindex = (u_int8_t)dfs->dfs_curchan_radindex; + } else { + if (dfs->dfs_extchan_radindex == -1) { + WMA_LOGI("%s phyerr on ext channel", __func__); + } + event->re_chanindex = (u_int8_t)dfs->dfs_extchan_radindex; + WMA_LOGI("%s:New extension channel event is added to queue", + __func__); + } + + ATH_DFSQ_LOCK(dfs); + + STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); + + empty = STAILQ_EMPTY(&dfs->dfs_radarq); + + ATH_DFSQ_UNLOCK(dfs); + + if (!empty && !dfs->ath_radar_tasksched) { + dfs->ath_radar_tasksched = 1; + OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0); + } + + return 1; + +} + +/* + * Register appropriate dfs phyerror event handler + * based on phyerror filtering offload is enabled + * or disabled. + */ +static void +wma_register_dfs_event_handler(tp_wma_handle wma_handle) +{ + if (NULL == wma_handle) { + WMA_LOGE("%s:wma_handle is NULL", __func__); + return; + } + + if (VOS_FALSE == wma_handle->dfs_phyerr_filter_offload) { + /* + * Register the wma_unified_phyerr_rx_event_handler + * for filtering offload disabled case to handle + * the DFS phyerrors. + */ + WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini", + __func__); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PHYERR_EVENTID, wma_unified_phyerr_rx_event_handler); + WMA_LOGD("%s: WMI_PHYERR_EVENTID event handler registered", + __func__); + } else { + WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini", + __func__); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_DFS_RADAR_EVENTID, + wma_unified_dfs_radar_rx_event_handler); + WMA_LOGD("%s:WMI_DFS_RADAR_EVENTID event handler registered", + __func__); + } + + return; +} + +static int wma_peer_state_change_event_handler(void *handle, + u_int8_t *event_buff, + u_int32_t len) +{ + WMI_PEER_STATE_EVENTID_param_tlvs *param_buf; + wmi_peer_state_event_fixed_param *event; + ol_txrx_vdev_handle vdev; + tp_wma_handle wma_handle = (tp_wma_handle)handle; + + if (!event_buff) { + WMA_LOGE("%s: event param null", __func__); + return -EINVAL; + } + + param_buf = (WMI_PEER_STATE_EVENTID_param_tlvs *)event_buff; + if (!param_buf) { + WMA_LOGE("%s: Received NULL buf ptr from FW", __func__); + return -ENOMEM; + } + + event = param_buf->fixed_param; + vdev = wma_find_vdev_by_id( wma_handle, event->vdev_id); + if (NULL == vdev) { + WMA_LOGP("%s: Couldn't find vdev for vdev_id: %d", + __func__, event->vdev_id); + return -EINVAL; + } + + if (vdev->opmode == wlan_op_mode_sta + && event->state == WMI_PEER_STATE_AUTHORIZED) { + /* + * set event so that WLANTL_ChangeSTAState + * can procced and unpause tx queue + */ + tl_shim_set_peer_authorized_event(wma_handle->vos_context, + event->vdev_id); + } + + return 0; +} + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +/* + * Register all the Link Layer Stats related event + * handler + */ +static void +wma_register_ll_stats_event_handler(tp_wma_handle wma_handle) +{ + if (NULL == wma_handle) { + WMA_LOGE("%s: wma_handle is NULL", __func__); + return; + } + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_IFACE_LINK_STATS_EVENTID, + wma_unified_link_iface_stats_event_handler); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_LINK_STATS_EVENTID, + wma_unified_link_peer_stats_event_handler); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_RADIO_LINK_STATS_EVENTID, + wma_unified_link_radio_stats_event_handler); + + return; +} +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static int wma_roam_synch_event_handler(void *handle, u_int8_t *event, u_int32_t len) +{ + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL; + wmi_roam_synch_event_fixed_param *synch_event = NULL; + u_int8_t *bcn_probersp_ptr = NULL; + u_int8_t *reassoc_rsp_ptr = NULL; + tp_wma_handle wma = (tp_wma_handle)handle; + wmi_channel *chan = NULL; + wmi_key_material *key = NULL; + int size=0; + tSirRoamOffloadSynchInd *pRoamOffloadSynchInd; + + WMA_LOGD("LFR3:%s", __func__); + if (!event) { + WMA_LOGE("%s: event param null", __func__); + return -EINVAL; + } + + param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("%s: received null buf from target", __func__); + return -EINVAL; + } + + synch_event = param_buf->fixed_param; + if (!synch_event) { + WMA_LOGE("%s: received null event data from target", __func__); + return -EINVAL; + } + + if(wma->interfaces[synch_event->vdev_id].roam_synch_in_progress == + VOS_TRUE) { + WMA_LOGE("%s: Ignoring RSI since one is already in progress", + __func__); + return -EINVAL; + } + adf_os_spin_lock_bh(&wma->roam_synch_lock); + wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = VOS_TRUE; + adf_os_spin_unlock_bh(&wma->roam_synch_lock); + len = sizeof(tSirRoamOffloadSynchInd) + + synch_event->bcn_probe_rsp_len + + synch_event->reassoc_rsp_len; + pRoamOffloadSynchInd = (tSirRoamOffloadSynchInd *)vos_mem_malloc(len); + if (!pRoamOffloadSynchInd) { + WMA_LOGE("%s: failed to allocate memory for roam_synch_event", __func__); + return -ENOMEM; + } + /* abort existing scan if any */ + if (wma->interfaces[synch_event->vdev_id].scan_info.scan_id != 0) { + tAbortScanParams abortScan; + WMA_LOGD("LFR3: Aborting Scan with scan_id=%d\n", + wma->interfaces[synch_event->vdev_id].scan_info.scan_id); + abortScan.SessionId = synch_event->vdev_id; + wma_stop_scan(wma, &abortScan); + } + pRoamOffloadSynchInd->messageType = eWNI_SME_ROAM_OFFLOAD_SYNCH_IND; + pRoamOffloadSynchInd->length = size; + pRoamOffloadSynchInd->roamedVdevId = synch_event->vdev_id; + pRoamOffloadSynchInd->authStatus = synch_event->auth_status; + pRoamOffloadSynchInd->roamReason = synch_event->roam_reason; + pRoamOffloadSynchInd->rssi = synch_event->rssi; + pRoamOffloadSynchInd->isBeacon = synch_event->is_beacon; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, pRoamOffloadSynchInd->bssId); + pRoamOffloadSynchInd->beaconProbeRespOffset = sizeof(tSirRoamOffloadSynchInd); + bcn_probersp_ptr = (tANI_U8 *)pRoamOffloadSynchInd + + pRoamOffloadSynchInd->beaconProbeRespOffset; + pRoamOffloadSynchInd->beaconProbeRespLength = synch_event->bcn_probe_rsp_len; + vos_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, + pRoamOffloadSynchInd->beaconProbeRespLength); + pRoamOffloadSynchInd->reassocRespOffset = sizeof(tSirRoamOffloadSynchInd) + + pRoamOffloadSynchInd->beaconProbeRespLength; + pRoamOffloadSynchInd->reassocRespLength = synch_event->reassoc_rsp_len; + reassoc_rsp_ptr = (tANI_U8 *)pRoamOffloadSynchInd + + pRoamOffloadSynchInd->reassocRespOffset; + vos_mem_copy(reassoc_rsp_ptr, + param_buf->reassoc_rsp_frame, + pRoamOffloadSynchInd->reassocRespLength); + chan = (wmi_channel *) param_buf->chan; + pRoamOffloadSynchInd->chan_freq = chan->mhz; + key = (wmi_key_material *) param_buf->key; + if (key != NULL) + { + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, + key->replay_counter, + SIR_REPLAY_CTR_LEN); + vos_mem_copy(pRoamOffloadSynchInd->kck, key->kck, + SIR_KCK_KEY_LEN); + vos_mem_copy(pRoamOffloadSynchInd->kek, key->kek, + SIR_KEK_KEY_LEN); + vos_mem_copy(pRoamOffloadSynchInd->replay_ctr, key->replay_counter, + SIR_REPLAY_CTR_LEN); + } + wma_send_msg(wma, WDA_ROAM_OFFLOAD_SYNCH_IND, + (void *) pRoamOffloadSynchInd, 0); + return 0; +} +#endif + +/** + * wma_rssi_breached_event_handler() - rssi breached event handler + * @handle: wma handle + * @cmd_param_info: event handler data + * @len: length of @cmd_param_info + * + * Return: 0 on success; error number otherwise + */ +static int wma_rssi_breached_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_RSSI_BREACH_EVENTID_param_tlvs *param_buf; + wmi_rssi_breach_event_fixed_param *event; + struct rssi_breach_event rssi; + tpAniSirGlobal mac = (tpAniSirGlobal)vos_get_context( + VOS_MODULE_ID_PE, wma->vos_context); + if (!mac) { + WMA_LOGE("%s: Invalid mac context", __func__); + return -EINVAL; + } + if (!mac->sme.rssi_threshold_breached_cb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + param_buf = (WMI_RSSI_BREACH_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid rssi breached event", __func__); + return -EINVAL; + } + event = param_buf->fixed_param; + + rssi.request_id = event->request_id; + rssi.session_id = event->vdev_id; + rssi.curr_rssi = event->rssi + WMA_TGT_NOISE_FLOOR_DBM; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, rssi.curr_bssid.bytes); + + WMA_LOGD("%s: req_id: %u vdev_id: %d curr_rssi: %d", __func__, + rssi.request_id, rssi.session_id, rssi.curr_rssi); + WMA_LOGI("%s: curr_bssid: %pM", __func__, rssi.curr_bssid.bytes); + + mac->sme.rssi_threshold_breached_cb(mac->hHdd, &rssi); + WMA_LOGD("%s: Invoke HDD rssi breached callback", __func__); + return 0; +} + +/* + * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or + * WMI_DFS_PHYERR_FILTER_DIS_CMDID command + * to firmware based on phyerr filtering + * offload status. + */ +static int +wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle) +{ + wmi_dfs_phyerr_filter_ena_cmd_fixed_param* enable_phyerr_offload_cmd; + wmi_dfs_phyerr_filter_dis_cmd_fixed_param* disable_phyerr_offload_cmd; + wmi_buf_t buf; + u_int16_t len; + int ret; + + if (NULL == wma_handle) { + WMA_LOGE("%s:wma_handle is NULL", __func__); + return 0; + } + + if (VOS_FALSE == wma_handle->dfs_phyerr_filter_offload) { + WMA_LOGD("%s:Phyerror Filtering offload is Disabled in ini", + __func__); + len = sizeof(*disable_phyerr_offload_cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return 0; + } + disable_phyerr_offload_cmd = + (wmi_dfs_phyerr_filter_dis_cmd_fixed_param *) + wmi_buf_data(buf); + + WMITLV_SET_HDR(&disable_phyerr_offload_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_dis_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dfs_phyerr_filter_dis_cmd_fixed_param)); + + /* + * Send WMI_DFS_PHYERR_FILTER_DIS_CMDID + * to the firmware to disable the phyerror + * filtering offload. + */ + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_DFS_PHYERR_FILTER_DIS_CMDID); + if (ret < 0) { + WMA_LOGE("%s: Failed to send WMI_DFS_PHYERR_FILTER_DIS_CMDID ret=%d", + __func__, ret); + wmi_buf_free(buf); + return 0; + } + WMA_LOGD("%s: WMI_DFS_PHYERR_FILTER_DIS_CMDID Send Success", + __func__); + } else { + WMA_LOGD("%s:Phyerror Filtering offload is Enabled in ini", + __func__); + + len = sizeof(*enable_phyerr_offload_cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return 0; + } + + enable_phyerr_offload_cmd = + (wmi_dfs_phyerr_filter_ena_cmd_fixed_param *) + wmi_buf_data(buf); + + WMITLV_SET_HDR(&enable_phyerr_offload_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_dfs_phyerr_filter_ena_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dfs_phyerr_filter_ena_cmd_fixed_param)); + + /* + * Send a WMI_DFS_PHYERR_FILTER_ENA_CMDID + * to the firmware to enable the phyerror + * filtering offload. + */ + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_DFS_PHYERR_FILTER_ENA_CMDID); + + if (ret < 0) { + WMA_LOGE("%s: Failed to send WMI_DFS_PHYERR_FILTER_ENA_CMDID ret=%d", + __func__, ret); + wmi_buf_free(buf); + return 0; + } + WMA_LOGD("%s: WMI_DFS_PHYERR_FILTER_ENA_CMDID Send Success", + __func__); + } + + return 1; +} + +/* + * WMI Handler for WMI_OFFLOAD_BCN_TX_STATUS_EVENTID event from firmware. + * This event is generated by FW when the beacon transmission is offloaded + * and the host performs beacon template modification using WMI_BCN_TMPL_CMDID + * The FW generates this event when the first successful beacon transmission + * after template update + * Return- 1:Success, 0:Failure + */ +static int wma_unified_bcntx_status_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *param_buf; + wmi_offload_bcn_tx_status_event_fixed_param *resp_event; + tSirFirstBeaconTxCompleteInd *beacon_tx_complete_ind; + + param_buf = (WMI_OFFLOAD_BCN_TX_STATUS_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid bcn tx response event buffer"); + return -EINVAL; + } + + resp_event = param_buf->fixed_param; + + /* Check for valid handle to ensure session is not deleted in any race */ + if (!wma->interfaces[resp_event->vdev_id].handle) { + WMA_LOGE("%s: The session does not exist", __func__); + return -EINVAL; + } + + /* Beacon Tx Indication supports only AP mode. Ignore in other modes */ + if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) == false) { + WMA_LOGI("%s: Beacon Tx Indication does not support type %d and sub_type %d", + __func__, wma->interfaces[resp_event->vdev_id].type, + wma->interfaces[resp_event->vdev_id].sub_type); + return 0; + } + + beacon_tx_complete_ind = (tSirFirstBeaconTxCompleteInd *) + vos_mem_malloc(sizeof(tSirFirstBeaconTxCompleteInd)); + if (!beacon_tx_complete_ind) { + WMA_LOGE("%s: Failed to alloc beacon_tx_complete_ind", __func__); + return -ENOMEM; + } + + beacon_tx_complete_ind->messageType = WDA_DFS_BEACON_TX_SUCCESS_IND; + beacon_tx_complete_ind->length = sizeof(tSirFirstBeaconTxCompleteInd); + beacon_tx_complete_ind->bssIdx = resp_event->vdev_id; + + wma_send_msg(wma, WDA_DFS_BEACON_TX_SUCCESS_IND, (void *)beacon_tx_complete_ind, 0); + return 0; +} + +static int wma_vdev_install_key_complete_event_handler(void *handle, u_int8_t *event, u_int32_t len) +{ + WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *param_buf = NULL; + wmi_vdev_install_key_complete_event_fixed_param *key_fp = NULL; + + if (!event) { + WMA_LOGE("%s: event param null", __func__); + return -1; + } + + param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("%s: received null buf from target", __func__); + return -1; + } + + key_fp = param_buf->fixed_param; + if (!key_fp) { + WMA_LOGE("%s: received null event data from target", __func__); + return -1; + } + /* + * Do nothing for now. Completion of set key is already indicated to lim + */ + WMA_LOGI("%s: WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID", __func__); + return 0; +} + +#ifdef WLAN_FEATURE_STATS_EXT +static int wma_stats_ext_event_handler(void *handle, u_int8_t *event_buf, + u_int32_t len) +{ + WMI_STATS_EXT_EVENTID_param_tlvs *param_buf; + tSirStatsExtEvent *stats_ext_event; + wmi_stats_ext_event_fixed_param *stats_ext_info; + VOS_STATUS status; + vos_msg_t vos_msg; + u_int8_t *buf_ptr; + u_int32_t alloc_len; + + WMA_LOGD("%s: Posting stats ext event to SME", __func__); + + param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *)event_buf; + if (!param_buf) { + WMA_LOGE("%s: Invalid stats ext event buf", __func__); + return -EINVAL; + } + + stats_ext_info = param_buf->fixed_param; + buf_ptr = (u_int8_t *)stats_ext_info; + + alloc_len = sizeof(tSirStatsExtEvent); + alloc_len += stats_ext_info->data_len; + + stats_ext_event = (tSirStatsExtEvent *) vos_mem_malloc(alloc_len); + if (NULL == stats_ext_event) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return -ENOMEM; + } + + buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE ; + + stats_ext_event->vdev_id = stats_ext_info->vdev_id; + stats_ext_event->event_data_len = stats_ext_info->data_len; + vos_mem_copy(stats_ext_event->event_data, + buf_ptr, + stats_ext_event->event_data_len); + + vos_msg.type = eWNI_SME_STATS_EXT_EVENT; + vos_msg.bodyptr = (void *)stats_ext_event; + vos_msg.bodyval = 0; + + status = vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post stats ext event to SME", __func__); + vos_mem_free(stats_ext_event); + return -1; + } + + WMA_LOGD("%s: stats ext event Posted to SME", __func__); + return 0; +} +#endif + +static void +wma_register_extscan_event_handler(tp_wma_handle wma_handle) +{ + if (!wma_handle) { + WMA_LOGE("%s: extscan wma_handle is NULL", __func__); + return; + } + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_START_STOP_EVENTID, + wma_extscan_start_stop_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_CAPABILITIES_EVENTID, + wma_extscan_capabilities_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_HOTLIST_MATCH_EVENTID, + wma_extscan_hotlist_match_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID, + wma_extscan_change_results_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_OPERATION_EVENTID, + wma_extscan_operations_event_handler); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_TABLE_USAGE_EVENTID, + wma_extscan_table_usage_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_CACHED_RESULTS_EVENTID, + wma_extscan_cached_results_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PASSPOINT_MATCH_EVENTID, + wma_passpoint_match_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID, + wma_extscan_hotlist_ssid_match_event_handler); + + return; + +} + +void wma_wow_tx_complete(void *wma) +{ + tp_wma_handle wma_handle = (tp_wma_handle)wma; + WMA_LOGD("WOW_TX_COMPLETE DONE"); + vos_event_set(&wma_handle->wow_tx_complete); +} + +#ifdef WLAN_FEATURE_NAN +/** + * wma_set_nan_enable() - set nan enable flag in WMA handle + * @wma_handle: Pointer to wma handle + * @mac_param: Pointer to mac_param + * + * Return: none + */ +static void wma_set_nan_enable(tp_wma_handle wma_handle, + tMacOpenParameters *mac_param) +{ + wma_handle->is_nan_enabled = mac_param->is_nan_enabled; +} +#else +static void wma_set_nan_enable(tp_wma_handle wma_handle, + tMacOpenParameters *mac_param) +{ +} +#endif + +#ifdef FEATURE_RUNTIME_PM +/** + * wma_runtime_context_init() - API to init wma runtime contexts + * @handle: wma handle + * + * The API initializes the wma runtime contexts for beaconing interfaces + * and the context to synchronize runtime suspend/resume. + * + * Return: void + */ +static void wma_runtime_context_init(tp_wma_handle handle) +{ + tp_wma_handle wma_handle = handle; + struct wma_runtime_pm_context *runtime_context = + &wma_handle->runtime_context; + + runtime_context->ap = + vos_runtime_pm_prevent_suspend_init("wma_runtime_ap"); + runtime_context->resume = + vos_runtime_pm_prevent_suspend_init("wma_runtime_resume"); +} + +/** + * wma_runtime_context_deinit() - API to deinit wma runtime contexts + * @handle: wma handle + * + * The API deinitializes the wma runtime contexts for beaconing interfaces + * and the context to synchronize runtime suspend/resume. + * + * Return: void + */ +static void wma_runtime_context_deinit(tp_wma_handle handle) +{ + tp_wma_handle wma_handle = handle; + struct wma_runtime_pm_context *runtime_context = + &wma_handle->runtime_context; + + vos_runtime_pm_prevent_suspend_deinit(runtime_context->ap); + runtime_context->ap = NULL; + vos_runtime_pm_prevent_suspend_deinit( + runtime_context->resume); + runtime_context->resume = NULL; +} +#else +static void wma_runtime_context_init(tp_wma_handle handle) { } +static void wma_runtime_context_deinit(tp_wma_handle handle) { } +#endif + +/* + * Allocate and init wmi adaptation layer. + */ +VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, + wda_tgt_cfg_cb tgt_cfg_cb, + wda_dfs_radar_indication_cb radar_ind_cb, + tMacOpenParameters *mac_params) +{ + tp_wma_handle wma_handle; + HTC_HANDLE htc_handle; + adf_os_device_t adf_dev; + v_VOID_t *wmi_handle; + VOS_STATUS vos_status; + struct ol_softc *scn; + struct txrx_pdev_cfg_param_t olCfg = {0}; + + WMA_LOGD("%s: Enter", __func__); + + adf_dev = vos_get_context(VOS_MODULE_ID_ADF, vos_context); + htc_handle = vos_get_context(VOS_MODULE_ID_HTC, vos_context); + + if (!htc_handle) { + WMA_LOGP("%s: Invalid HTC handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* Alloc memory for WMA Context */ + vos_status = vos_alloc_context(vos_context, VOS_MODULE_ID_WDA, + (v_VOID_t **) &wma_handle, + sizeof (t_wma_handle)); + + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: Memory allocation failed for wma_handle", + __func__); + return vos_status; + } + + vos_mem_zero(wma_handle, sizeof (t_wma_handle)); + + if (vos_get_conparam() != VOS_FTM_MODE) { +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_init(&wma_handle->pno_wake_lock, "wlan_pno_wl"); +#endif +#ifdef FEATURE_WLAN_EXTSCAN + vos_wake_lock_init(&wma_handle->extscan_wake_lock, + "wlan_extscan_wl"); +#endif + vos_wake_lock_init(&wma_handle->wow_wake_lock, "wlan_wow_wl"); + } + + /* attach the wmi */ + wmi_handle = wmi_unified_attach(wma_handle, wma_wow_tx_complete); + if (!wmi_handle) { + WMA_LOGP("%s: failed to attach WMI", __func__); + vos_status = VOS_STATUS_E_NOMEM; + goto err_wma_handle; + } + + WMA_LOGA("WMA --> wmi_unified_attach - success"); + + /* Save the WMI & HTC handle */ + wma_handle->wmi_handle = wmi_handle; + wma_handle->htc_handle = htc_handle; + wma_handle->vos_context = vos_context; + wma_handle->adf_dev = adf_dev; + + wma_runtime_context_init(wma_handle); + + /* initialize default target config */ + wma_set_default_tgt_config(wma_handle); + +#ifdef IPA_UC_OFFLOAD + olCfg.is_uc_offload_enabled = mac_params->ucOffloadEnabled; + olCfg.uc_tx_buffer_count = mac_params->ucTxBufCount; + olCfg.uc_tx_buffer_size = mac_params->ucTxBufSize; + olCfg.uc_rx_indication_ring_count = mac_params->ucRxIndRingCount; + olCfg.uc_tx_partition_base = mac_params->ucTxPartitionBase; +#endif /* IPA_UC_OFFLOAD*/ + + wma_handle->tx_chain_mask_cck = mac_params->tx_chain_mask_cck; + wma_handle->self_gen_frm_pwr = mac_params->self_gen_frm_pwr; + wma_handle->max_mgmt_tx_fail_count = mac_params->max_mgmt_tx_fail_count; + /* Allocate cfg handle */ + + /* RX Full reorder should enable for PCIe, ROME3.X project only now + * MDM should enable later, schedule TBD + * HL also sdould be enabled, schedule TBD */ +#ifdef WLAN_FEATURE_RX_FULL_REORDER_OL + olCfg.is_full_reorder_offload = mac_params->reorderOffload; +#else + olCfg.is_full_reorder_offload = 0; +#endif + ((pVosContextType) vos_context)->cfg_ctx = + ol_pdev_cfg_attach(((pVosContextType) vos_context)->adf_ctx, olCfg); + if (!(((pVosContextType) vos_context)->cfg_ctx)) { + WMA_LOGP("%s: failed to init cfg handle", __func__); + vos_status = VOS_STATUS_E_NOMEM; + goto err_wmi_handle; + } + + /* adjust the cfg_ctx default value based on setting */ + wdi_in_set_cfg_rx_fwd_disabled((ol_pdev_handle)((pVosContextType)vos_context)->cfg_ctx, + (u_int8_t)mac_params->apDisableIntraBssFwd); + + /* adjust the packet log enable default value based on CFG INI setting */ + wdi_in_set_cfg_pakcet_log_enabled((ol_pdev_handle) + ((pVosContextType)vos_context)->cfg_ctx, (u_int8_t)vos_is_packet_log_enabled()); + + + /* Allocate dfs_ic and initialize DFS */ + wma_handle->dfs_ic = wma_dfs_attach(wma_handle->dfs_ic); + if(wma_handle->dfs_ic == NULL) { + WMA_LOGE("%s: Memory allocation failed for dfs_ic", __func__); + goto err_wmi_handle; + } + +#if defined(QCA_WIFI_FTM) + if (vos_get_conparam() == VOS_FTM_MODE) + wma_utf_attach(wma_handle); +#endif + + /*TODO: Recheck below parameters */ + scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + + if (NULL == scn) { + WMA_LOGE("%s: Failed to get scn",__func__); + vos_status = VOS_STATUS_E_NOMEM; + goto err_scn_context; + } + + mac_params->maxStation = ol_get_number_of_peers_supported(scn); + + mac_params->maxBssId = WMA_MAX_SUPPORTED_BSS; + mac_params->frameTransRequired = 0; + +#ifdef WLAN_FEATURE_LPSS + wma_handle->is_lpass_enabled = mac_params->is_lpass_enabled; +#endif + wma_set_nan_enable(wma_handle, mac_params); + + wma_handle->wlan_resource_config.num_wow_filters = mac_params->maxWoWFilters; + wma_handle->wlan_resource_config.num_keep_alive_pattern = WMA_MAXNUM_PERIODIC_TX_PTRNS; + + /* The current firmware implementation requires the number of offload peers + * should be (number of vdevs + 1). + */ + wma_handle->wlan_resource_config.num_offload_peers = + mac_params->apMaxOffloadPeers + 1; + + wma_handle->wlan_resource_config.num_offload_reorder_buffs = + mac_params->apMaxOffloadReorderBuffs + 1; + + wma_handle->ol_ini_info = mac_params->olIniInfo; + wma_handle->max_station = mac_params->maxStation; + wma_handle->max_bssid = mac_params->maxBssId; + wma_handle->frame_xln_reqd = mac_params->frameTransRequired; + wma_handle->driver_type = mac_params->driverType; + wma_handle->ssdp = mac_params->ssdp; + wma_handle->enable_bcst_ptrn = mac_params->enable_bcst_ptrn; +#ifdef FEATURE_WLAN_RA_FILTERING + wma_handle->IsRArateLimitEnabled = mac_params->IsRArateLimitEnabled; + wma_handle->RArateLimitInterval = mac_params->RArateLimitInterval; +#endif + /* + * Indicates if DFS Phyerr filtering offload + * is Enabled/Disabed from ini + */ + wma_handle->dfs_phyerr_filter_offload = + mac_params->dfsPhyerrFilterOffload; + wma_handle->dfs_pri_multiplier = + mac_params->dfsRadarPriMultiplier; + wma_handle->interfaces = vos_mem_malloc(sizeof(struct wma_txrx_node) * + wma_handle->max_bssid); + if (!wma_handle->interfaces) { + WMA_LOGP("%s: failed to allocate interface table", __func__); + vos_status = VOS_STATUS_E_NOMEM; + goto err_scn_context; + } + vos_mem_zero(wma_handle->interfaces, sizeof(struct wma_txrx_node) * + wma_handle->max_bssid); + /* Register the debug print event handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_DEBUG_PRINT_EVENTID, + wma_unified_debug_print_event_handler); + + wma_handle->tgt_cfg_update_cb = tgt_cfg_cb; + wma_handle->dfs_radar_indication_cb = radar_ind_cb; + + vos_status = vos_event_init(&wma_handle->wma_ready_event); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: wma_ready_event initialization failed", __func__); + goto err_event_init; + } + vos_status = vos_event_init(&wma_handle->target_suspend); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: target suspend event initialization failed", + __func__); + goto err_event_init; + } + + vos_status = vos_event_init(&wma_handle->wow_tx_complete); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: wow_tx_complete event initialization failed", + __func__); + goto err_event_init; + } + + /* Init Tx Frame Complete event */ + vos_status = vos_event_init(&wma_handle->tx_frm_download_comp_event); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGP("%s: failed to init tx_frm_download_comp_event", + __func__); + goto err_event_init; + } + + /* Init tx queue empty check event */ + vos_status = vos_event_init(&wma_handle->tx_queue_empty_event); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGP("%s: failed to init tx_queue_empty_event", + __func__); + goto err_event_init; + } + + vos_status = vos_event_init(&wma_handle->wma_resume_event); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: wma_resume_event initialization failed", __func__); + goto err_event_init; + } + + vos_status = vos_event_init(&wma_handle->runtime_suspend); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: runtime suspend event initialization failed", + __func__); + goto err_event_init; + } + + vos_status = vos_event_init(&wma_handle->recovery_event); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: recovery event initialization failed", __func__); + goto err_event_init; + } + + INIT_LIST_HEAD(&wma_handle->vdev_resp_queue); + adf_os_spinlock_init(&wma_handle->vdev_respq_lock); + adf_os_spinlock_init(&wma_handle->vdev_detach_lock); + adf_os_spinlock_init(&wma_handle->roam_preauth_lock); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + adf_os_spinlock_init(&wma_handle->roam_synch_lock); +#endif + adf_os_atomic_init(&wma_handle->is_wow_bus_suspended); + + /* Register vdev start response event handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_START_RESP_EVENTID, + wma_vdev_start_resp_handler); + + /* Register vdev stop response event handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_STOPPED_EVENTID, + wma_vdev_stop_resp_handler); + + /* register for STA kickout function */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_STA_KICKOUT_EVENTID, + wma_peer_sta_kickout_event_handler); + + /* register for stats response event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_UPDATE_STATS_EVENTID, + wma_stats_event_handler); + /* register for linkspeed response event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_ESTIMATED_LINKSPEED_EVENTID, + wma_link_speed_event_handler); + +#ifdef FEATURE_OEM_DATA_SUPPORT + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OEM_CAPABILITY_EVENTID, + wma_oem_capability_event_callback); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OEM_MEASUREMENT_REPORT_EVENTID, + wma_oem_measurement_report_event_callback); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OEM_ERROR_REPORT_EVENTID, + wma_oem_error_report_event_callback); +#endif + /* + * Register appropriate DFS phyerr event handler for + * Phyerror events. Handlers differ for phyerr filtering + * offload enable and disable cases. + */ + wma_register_dfs_event_handler(wma_handle); + + /* Register peer change event handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_STATE_EVENTID, + wma_peer_state_change_event_handler); + + + /* Register beacon tx complete event id. The event is required + * for sending channel switch announcement frames + */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OFFLOAD_BCN_TX_STATUS_EVENTID, + wma_unified_bcntx_status_event_handler); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_UPDATE_VDEV_RATE_STATS_EVENTID, + wma_link_status_event_handler); +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + /* Register event handler for processing Link Layer Stats + * response from the FW + */ + wma_register_ll_stats_event_handler(wma_handle); + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + /* Register event handler to receive firmware mem dump + * copy complete indication + */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_UPDATE_FW_MEM_DUMP_EVENTID, + wma_fw_mem_dump_event_handler); + + wmi_set_tgt_assert(wma_handle->wmi_handle, + mac_params->force_target_assert_enabled); + /* Firmware debug log */ + vos_status = dbglog_init(wma_handle->wmi_handle); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: Firmware Dbglog initialization failed", __func__); + goto err_dbglog_init; + } + + /* + * Update Powersave mode + * 1 - Legacy Powersave + Deepsleep Disabled + * 2 - QPower + Deepsleep Disabled + * 3 - Legacy Powersave + Deepsleep Enabled + * 4 - QPower + Deepsleep Enabled + */ + wma_handle->powersave_mode = mac_params->powersaveOffloadEnabled; + wma_handle->staMaxLIModDtim = mac_params->staMaxLIModDtim; + wma_handle->staModDtim = mac_params->staModDtim; + wma_handle->staDynamicDtim = mac_params->staDynamicDtim; + + /* + * Value of mac_params->wowEnable can be, + * 0 - Disable both magic pattern match and pattern byte match. + * 1 - Enable magic pattern match on all interfaces. + * 2 - Enable pattern byte match on all interfaces. + * 3 - Enable both magic patter and pattern byte match on + * all interfaces. + */ + wma_handle->wow.magic_ptrn_enable = + (mac_params->wowEnable & 0x01) ? TRUE : FALSE; + wma_handle->ptrn_match_enable_all_vdev = + (mac_params->wowEnable & 0x02) ? TRUE : FALSE; + +#ifdef FEATURE_WLAN_TDLS + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_TDLS_PEER_EVENTID, + wma_tdls_event_handler); +#endif /* FEATURE_WLAN_TDLS */ + + /* register for install key completion event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID, + wma_vdev_install_key_complete_event_handler); +#ifdef WLAN_FEATURE_NAN + /* register for nan response event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_NAN_EVENTID, + wma_nan_rsp_event_handler); +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + /* register for extended stats event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_STATS_EXT_EVENTID, + wma_stats_ext_event_handler); +#endif +#ifdef FEATURE_WLAN_EXTSCAN + wma_register_extscan_event_handler(wma_handle); +#endif + + WMA_LOGD("%s: Exit", __func__); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_ROAM_SYNCH_EVENTID, + wma_roam_synch_event_handler); +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_RSSI_BREACH_EVENTID, + wma_rssi_breached_event_handler); + return VOS_STATUS_SUCCESS; + +err_dbglog_init: + adf_os_spinlock_destroy(&wma_handle->vdev_respq_lock); + adf_os_spinlock_destroy(&wma_handle->vdev_detach_lock); + adf_os_spinlock_destroy(&wma_handle->roam_preauth_lock); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + adf_os_spinlock_destroy(&wma_handle->roam_synch_lock); +#endif +err_event_init: + wmi_unified_unregister_event_handler(wma_handle->wmi_handle, + WMI_DEBUG_PRINT_EVENTID); + vos_mem_free(wma_handle->interfaces); +err_scn_context: + wma_dfs_detach(wma_handle->dfs_ic); +#if defined(QCA_WIFI_FTM) + wma_utf_detach(wma_handle); +#endif +err_wmi_handle: + adf_os_mem_free(((pVosContextType) vos_context)->cfg_ctx); + OS_FREE(wmi_handle); + +err_wma_handle: + + if (vos_get_conparam() != VOS_FTM_MODE) { +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_destroy(&wma_handle->pno_wake_lock); +#endif +#ifdef FEATURE_WLAN_EXTSCAN + vos_wake_lock_destroy(&wma_handle->extscan_wake_lock); +#endif + vos_wake_lock_destroy(&wma_handle->wow_wake_lock); + } + + wma_runtime_context_deinit(wma_handle); + vos_free_context(vos_context, VOS_MODULE_ID_WDA, wma_handle); + + WMA_LOGD("%s: Exit", __func__); + + return vos_status; +} + +/* function : wma_pre_start + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_pre_start(v_VOID_t *vos_ctx) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + A_STATUS status = A_OK; + tp_wma_handle wma_handle; + vos_msg_t wma_msg = {0} ; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + /* Validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGP("%s: invalid argument", __func__); + vos_status = VOS_STATUS_E_INVAL; + goto end; + } + /* Open endpoint for ctrl path - WMI <--> HTC */ + status = wmi_unified_connect_htc_service( + wma_handle->wmi_handle, + wma_handle->htc_handle); + if (A_OK != status) { + WMA_LOGP("%s: wmi_unified_connect_htc_service", __func__); + vos_status = VOS_STATUS_E_FAULT; + goto end; + } + + WMA_LOGA("WMA --> wmi_unified_connect_htc_service - success"); + + /* Trigger the CFG DOWNLOAD */ + wma_msg.type = WNI_CFG_DNLD_REQ ; + wma_msg.bodyptr = NULL; + wma_msg.bodyval = 0; + + vos_status = vos_mq_post_message( VOS_MQ_ID_WDA, &wma_msg ); + if (VOS_STATUS_SUCCESS !=vos_status) { + WMA_LOGP("%s: Failed to post WNI_CFG_DNLD_REQ msg", __func__); + VOS_ASSERT(0); + vos_status = VOS_STATUS_E_FAILURE; + } +end: + WMA_LOGD("%s: Exit", __func__); + return vos_status; +} + +/* function : wma_send_msg + * Description : + * Args : + * Returns : + */ +static void wma_send_msg(tp_wma_handle wma_handle, u_int16_t msg_type, + void *body_ptr, u_int32_t body_val) +{ + tSirMsgQ msg = {0} ; + tANI_U32 status = VOS_STATUS_SUCCESS ; + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + msg.type = msg_type; + msg.bodyval = body_val; + msg.bodyptr = body_ptr; + status = limPostMsgApi(pMac, &msg); + if (VOS_STATUS_SUCCESS != status) { + if(NULL != body_ptr) + vos_mem_free(body_ptr); + VOS_ASSERT(0) ; + } + return ; +} + +/* function : wma_get_txrx_vdev_type + * Description : + * Args : + * Returns : + */ +enum wlan_op_mode wma_get_txrx_vdev_type(u_int32_t type) +{ + enum wlan_op_mode vdev_type = wlan_op_mode_unknown; + switch (type) { + case WMI_VDEV_TYPE_AP: + vdev_type = wlan_op_mode_ap; + break; + case WMI_VDEV_TYPE_STA: + vdev_type = wlan_op_mode_sta; + break; +#ifdef QCA_IBSS_SUPPORT + case WMI_VDEV_TYPE_IBSS: + vdev_type = wlan_op_mode_ibss; + break; +#endif + case WMI_VDEV_TYPE_OCB: + vdev_type = wlan_op_mode_ocb; + break; + case WMI_VDEV_TYPE_MONITOR: + default: + WMA_LOGE("Invalid vdev type %u", type); + vdev_type = wlan_op_mode_unknown; + } + + return vdev_type; +} + +/* function : wma_unified_vdev_create_send + * Description : + * Args : + * Returns : + */ +int wma_unified_vdev_create_send(wmi_unified_t wmi_handle, u_int8_t if_id, + u_int32_t type, u_int32_t subtype, + u_int8_t macaddr[IEEE80211_ADDR_LEN], + u_int8_t nss_2g, u_int8_t nss_5g) +{ + wmi_vdev_create_cmd_fixed_param* cmd; + wmi_buf_t buf; + int len = sizeof(*cmd); + int ret; + int num_bands = 2; + u_int8_t *buf_ptr; + wmi_vdev_txrx_streams *txrx_streams; + + len += (num_bands * sizeof(wmi_vdev_txrx_streams) + WMI_TLV_HDR_SIZE); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s:wmi_buf_alloc failed", __FUNCTION__); + return ENOMEM; + } + cmd = (wmi_vdev_create_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_create_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_create_cmd_fixed_param)); + cmd->vdev_id = if_id; + cmd->vdev_type = type; + cmd->vdev_subtype = subtype; + cmd->num_cfg_txrx_streams = num_bands; + WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->vdev_macaddr); + WMA_LOGE("%s: ID = %d VAP Addr = %02x:%02x:%02x:%02x:%02x:%02x", + __func__, if_id, + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + + buf_ptr = (u_int8_t *)cmd + sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + (num_bands * sizeof(wmi_vdev_txrx_streams))); + buf_ptr += WMI_TLV_HDR_SIZE; + + WMA_LOGD("%s: type %d, subtype %d, nss_2g %d, nss_5g %d", __func__, + type, subtype, nss_2g, nss_5g); + txrx_streams = (wmi_vdev_txrx_streams *)buf_ptr; + txrx_streams->band = WMI_TPC_CHAINMASK_CONFIG_BAND_2G; + txrx_streams->supported_tx_streams = nss_2g; + txrx_streams->supported_rx_streams = nss_2g; + WMITLV_SET_HDR(&txrx_streams->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_txrx_streams, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_txrx_streams)); + + buf_ptr += sizeof(wmi_vdev_txrx_streams); + txrx_streams = (wmi_vdev_txrx_streams *)buf_ptr; + txrx_streams->band = WMI_TPC_CHAINMASK_CONFIG_BAND_5G; + txrx_streams->supported_tx_streams = nss_5g; + txrx_streams->supported_rx_streams = nss_5g; + WMITLV_SET_HDR(&txrx_streams->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_txrx_streams, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_txrx_streams)); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_VDEV_CREATE_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send WMI_VDEV_CREATE_CMDID"); + wmi_buf_free(buf); + } + return ret; +} + +/* function : wma_unified_vdev_delete_send + * Description : + * Args : + * Returns : + */ +static int wma_unified_vdev_delete_send(wmi_unified_t wmi_handle, u_int8_t if_id) +{ + wmi_vdev_delete_cmd_fixed_param* cmd; + wmi_buf_t buf; + int ret; + + buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGP("%s:wmi_buf_alloc failed", __FUNCTION__); + return ENOMEM; + } + + cmd = (wmi_vdev_delete_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_delete_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_delete_cmd_fixed_param)); + cmd->vdev_id = if_id; + ret = wmi_unified_cmd_send(wmi_handle, buf, sizeof(wmi_vdev_delete_cmd_fixed_param), + WMI_VDEV_DELETE_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send WMI_VDEV_DELETE_CMDID"); + wmi_buf_free(buf); + } + return ret; +} + +void wma_vdev_detach_callback(void *ctx) +{ + tp_wma_handle wma; + struct wma_txrx_node *iface = (struct wma_txrx_node *)ctx; + tpDelStaSelfParams param; + struct wma_target_req *req_msg; + + wma = vos_get_context(VOS_MODULE_ID_WDA, + vos_get_global_context(VOS_MODULE_ID_WDA, NULL)); + + if (!wma || !iface->del_staself_req) { + WMA_LOGP("%s: wma %p iface %p", __func__, wma, + iface->del_staself_req); + return; + } + param = (tpDelStaSelfParams) iface->del_staself_req; + WMA_LOGD("%s: sending WDA_DEL_STA_SELF_RSP for vdev %d", + __func__, param->sessionId); + + req_msg = wma_find_vdev_req(wma, param->sessionId, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (req_msg) { + WMA_LOGD("%s: Found vdev request for vdev id %d", + __func__, param->sessionId); + vos_timer_stop(&req_msg->event_timeout); + vos_timer_destroy(&req_msg->event_timeout); + adf_os_mem_free(req_msg); + } + if(iface->addBssStaContext) + adf_os_mem_free(iface->addBssStaContext); + +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) + adf_os_mem_free(iface->staKeyParams); +#endif + vos_mem_zero(iface, sizeof(*iface)); + param->status = VOS_STATUS_SUCCESS; + + wma_send_msg(wma, WDA_DEL_STA_SELF_RSP, (void *)param, 0); +} + +/* function : wma_vdev_detach + * Description : + * Args : + * Returns : + */ +static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, + tpDelStaSelfParams pdel_sta_self_req_param, + u_int8_t generateRsp) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + u_int8_t peer_id; + u_int8_t vdev_id = pdel_sta_self_req_param->sessionId; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + struct wma_target_req *msg; + + if ((iface->type == WMI_VDEV_TYPE_AP) && + (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { + + WMA_LOGA("P2P Device: removing self peer %pM", + pdel_sta_self_req_param->selfMacAddr); + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, + wma_handle->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev",__func__); + return VOS_STATUS_E_FAULT; + } + + peer = ol_txrx_find_peer_by_addr(pdev, + pdel_sta_self_req_param->selfMacAddr, + &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + pdel_sta_self_req_param->selfMacAddr); + } + wma_remove_peer(wma_handle, + pdel_sta_self_req_param->selfMacAddr, + vdev_id, peer, VOS_FALSE); + } + if (adf_os_atomic_read(&iface->bss_status) == WMA_BSS_STATUS_STARTED) { + WMA_LOGA("BSS is not yet stopped. Defering vdev(vdev id %x) deletion", + vdev_id); + iface->del_staself_req = pdel_sta_self_req_param; + return status; + } + + adf_os_spin_lock_bh(&wma_handle->vdev_detach_lock); + if(!iface->handle) { + WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed", + vdev_id); + adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); + vos_mem_free(pdel_sta_self_req_param); + pdel_sta_self_req_param = NULL; + return status; + } + + /* Unregister vdev from TL shim before vdev delete + * Will protect from invalid vdev access */ + WLANTL_UnRegisterVdev(wma_handle->vos_context, vdev_id); + + /* remove the interface from ath_dev */ + if (wma_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id)) { + WMA_LOGE("Unable to remove an interface for ath_dev."); + status = VOS_STATUS_E_FAILURE; + adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); + goto out; + } + + + WMA_LOGD("vdev_id:%hu vdev_hdl:%p", vdev_id, iface->handle); + if (!generateRsp) { + WMA_LOGE("Call txrx detach w/o callback for vdev %d", vdev_id); + ol_txrx_vdev_detach(iface->handle, NULL, NULL); + adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); + goto out; + } + + iface->del_staself_req = pdel_sta_self_req_param; + msg = wma_fill_vdev_req(wma_handle, vdev_id, WDA_DEL_STA_SELF_REQ, + WMA_TARGET_REQ_TYPE_VDEV_DEL, iface, 2000); + if (!msg) { + WMA_LOGE("%s: Failed to fill vdev request for vdev_id %d", + __func__, vdev_id); + status = VOS_STATUS_E_NOMEM; + adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); + goto out; + } + WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id); + ol_txrx_vdev_detach(iface->handle, NULL, NULL); + wma_vdev_detach_callback(iface); + adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); + return status; +out: + if(iface->addBssStaContext) + adf_os_mem_free(iface->addBssStaContext); +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) + adf_os_mem_free(iface->staKeyParams); +#endif + vos_mem_zero(iface, sizeof(*iface)); + pdel_sta_self_req_param->status = status; + if (generateRsp) + wma_send_msg(wma_handle, WDA_DEL_STA_SELF_RSP, (void *)pdel_sta_self_req_param, 0); + + return status; +} + +static int wmi_unified_peer_create_send(wmi_unified_t wmi, + const u_int8_t *peer_addr, u_int32_t peer_type, + u_int32_t vdev_id) +{ + wmi_peer_create_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_peer_create_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_create_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_peer_create_cmd_fixed_param)); + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr); + cmd->peer_type = peer_type; + cmd->vdev_id = vdev_id; + + if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_CREATE_CMDID)) { + WMA_LOGP("%s: failed to send WMI_PEER_CREATE_CMDID", __func__); + adf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); + return 0; +} + +static VOS_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, u8 peer_addr[6], + u_int32_t peer_type, u_int8_t vdev_id, + v_BOOL_t roam_synch_in_progress) +{ + ol_txrx_peer_handle peer; + + if (++wma->interfaces[vdev_id].peer_count > wma->wlan_resource_config.num_peers) { + WMA_LOGP("%s, the peer count exceeds the limit %d", + __func__, wma->interfaces[vdev_id].peer_count - 1); + goto err; + } + peer = ol_txrx_peer_attach(pdev, vdev, peer_addr); + if (!peer) { + WMA_LOGE("%s : Unable to attach peer %pM", __func__, peer_addr); + goto err; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_synch_in_progress) { + + WMA_LOGD("%s: Created peer with peer_addr %pM vdev_id %d," + "peer_count - %d",__func__, peer_addr, vdev_id, + wma->interfaces[vdev_id].peer_count); + return VOS_STATUS_SUCCESS; + } +#endif + if (wmi_unified_peer_create_send(wma->wmi_handle, peer_addr, + peer_type, vdev_id) < 0) { + WMA_LOGP("%s : Unable to create peer in Target", __func__); + ol_txrx_peer_detach(peer); + goto err; + } + WMA_LOGE("%s: Created peer with peer_addr %pM vdev_id %d, peer_count - %d", + __func__, peer_addr, vdev_id, wma->interfaces[vdev_id].peer_count); + +#ifdef QCA_IBSS_SUPPORT + /* for each remote ibss peer, clear its keys */ + if (wma_is_vdev_in_ibss_mode(wma, vdev_id) + && !vos_mem_compare(peer_addr, vdev->mac_addr.raw, ETH_ALEN)) { + + tSetStaKeyParams key_info; + WMA_LOGD("%s: remote ibss peer %pM key clearing\n", __func__, + peer_addr); + vos_mem_set(&key_info, sizeof(key_info), 0); + key_info.smesessionId= vdev_id; + vos_mem_copy(key_info.peerMacAddr, peer_addr, ETH_ALEN); + key_info.sendRsp = FALSE; + + wma_set_stakey(wma, &key_info); + } +#endif + + return VOS_STATUS_SUCCESS; +err: + wma->interfaces[vdev_id].peer_count--; + return VOS_STATUS_E_FAILURE; +} + +static void wma_set_sta_keep_alive(tp_wma_handle wma, u_int8_t vdev_id, + v_U32_t method, v_U32_t timeperiod, + u_int8_t *hostv4addr, u_int8_t *destv4addr, + u_int8_t *destmac) +{ + wmi_buf_t buf; + WMI_STA_KEEPALIVE_CMD_fixed_param *cmd; + WMI_STA_KEEPALVE_ARP_RESPONSE *arp_rsp; + u_int8_t *buf_ptr; + int len; + + WMA_LOGD("%s: Enter", __func__); + + if (timeperiod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) { + WMA_LOGE("Invalid period %d Max limit %d", timeperiod, + WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX); + return; + } + + len = sizeof(*cmd) + sizeof(*arp_rsp); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("wmi_buf_alloc failed"); + return; + } + + cmd = (WMI_STA_KEEPALIVE_CMD_fixed_param *) wmi_buf_data(buf); + buf_ptr = (u_int8_t *)cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_STA_KEEPALIVE_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_STA_KEEPALIVE_CMD_fixed_param)); + cmd->interval = timeperiod; + cmd->enable = (timeperiod)? 1:0; + cmd->vdev_id = vdev_id; + WMA_LOGD("Keep Alive: vdev_id:%d interval:%u method:%d", vdev_id, + timeperiod, method); + arp_rsp = (WMI_STA_KEEPALVE_ARP_RESPONSE *)(buf_ptr + sizeof(*cmd)); + WMITLV_SET_HDR(&arp_rsp->tlv_header, + WMITLV_TAG_STRUC_WMI_STA_KEEPALVE_ARP_RESPONSE, + WMITLV_GET_STRUCT_TLVLEN(WMI_STA_KEEPALVE_ARP_RESPONSE)); + + if (method == SIR_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { + if ((NULL == hostv4addr) || + (NULL == destv4addr) || + (NULL == destmac)) { + WMA_LOGE("%s: received null pointer, hostv4addr:%p " + "destv4addr:%p destmac:%p ", __func__, + hostv4addr, destv4addr, destmac); + adf_nbuf_free(buf); + return; + } + + cmd->method = WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE; + vos_mem_copy(&arp_rsp->sender_prot_addr, hostv4addr, + SIR_IPV4_ADDR_LEN); + vos_mem_copy(&arp_rsp->target_prot_addr, destv4addr, + SIR_IPV4_ADDR_LEN); + WMI_CHAR_ARRAY_TO_MAC_ADDR(destmac,&arp_rsp->dest_mac_addr); + } else { + cmd->method = WMI_STA_KEEPALIVE_METHOD_NULL_FRAME; + } + + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_STA_KEEPALIVE_CMDID)) { + WMA_LOGE("Failed to set KeepAlive"); + adf_nbuf_free(buf); + } + + WMA_LOGD("%s: Exit", __func__); + return; +} + +static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac, + tANI_U32 sub_type, + tANI_U32 *max_inactive_time, + tANI_U32 *max_unresponsive_time) +{ + tANI_U32 keep_alive; + tANI_U16 lm_id, ka_id; + + switch (sub_type) { + case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO: + lm_id = WNI_CFG_GO_LINK_MONITOR_TIMEOUT; + ka_id = WNI_CFG_GO_KEEP_ALIVE_TIMEOUT; + break; + default: + /*For softAp the subtype value will be zero*/ + lm_id = WNI_CFG_AP_LINK_MONITOR_TIMEOUT; + ka_id = WNI_CFG_AP_KEEP_ALIVE_TIMEOUT; + } + + if(wlan_cfgGetInt(mac, lm_id, max_inactive_time) != eSIR_SUCCESS) { + WMA_LOGE("Failed to read link monitor for subtype %d", sub_type); + *max_inactive_time = WMA_LINK_MONITOR_DEFAULT_TIME_SECS; + } + + if(wlan_cfgGetInt(mac, ka_id, &keep_alive) != eSIR_SUCCESS) { + WMA_LOGE("Failed to read keep alive for subtype %d", sub_type); + keep_alive = WMA_KEEP_ALIVE_DEFAULT_TIME_SECS; + } + *max_unresponsive_time = *max_inactive_time + keep_alive; +} + +static void wma_set_sap_keepalive(tp_wma_handle wma, u_int8_t vdev_id) +{ + tANI_U32 min_inactive_time, max_inactive_time, max_unresponsive_time; + struct sAniSirGlobal *mac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + + if (NULL == mac) { + WMA_LOGE("%s: Failed to get mac", __func__); + return; + } + + wma_get_link_probe_timeout(mac, wma->interfaces[vdev_id].sub_type, + &max_inactive_time, &max_unresponsive_time); + + min_inactive_time = max_inactive_time / 2; + + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, + vdev_id, + WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, + min_inactive_time)) + WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME"); + + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, + vdev_id, + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, + max_inactive_time)) + WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME"); + + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, + vdev_id, + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, + max_unresponsive_time)) + WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME"); + + WMA_LOGD("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u" + " max_unresponsive_time: %u", __func__, vdev_id, + min_inactive_time, max_inactive_time, max_unresponsive_time); +} + +static VOS_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(tANI_U32 mcc_adaptive_scheduler) +{ + int ret = -1; + wmi_buf_t buf = 0; + wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param *cmd = NULL; + tp_wma_handle wma = NULL; + void *vos_context = NULL; + u_int16_t len = sizeof(wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param); + + vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + + if (NULL == wma) { + WMA_LOGE("%s : Failed to get wma", __func__); + return VOS_STATUS_E_FAULT; + } + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + cmd = (wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param *) wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param)); + cmd->enable = mcc_adaptive_scheduler; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID); + if (ret) { + WMA_LOGP("%s: Failed to send enable/disable MCC" + " adaptive scheduler command", __func__); + adf_nbuf_free(buf); + } + return VOS_STATUS_SUCCESS; +} + +/** + * Currently used to set time latency for an MCC vdev/adapter using operating + * channel of it and channel number. The info is provided run time using + * iwpriv command: iwpriv setMccLatency . + */ +static VOS_STATUS wma_set_mcc_channel_time_latency + ( + tp_wma_handle wma, + tANI_U32 mcc_channel, + tANI_U32 mcc_channel_time_latency + ) +{ + int ret = -1; + wmi_buf_t buf = 0; + wmi_resmgr_set_chan_latency_cmd_fixed_param *cmdTL = NULL; + u_int16_t len = 0; + u_int8_t *buf_ptr = NULL; + tANI_U32 cfg_val = 0; + wmi_resmgr_chan_latency chan_latency; + struct sAniSirGlobal *pMac = NULL; + /* Note: we only support MCC time latency for a single channel */ + u_int32_t num_channels = 1; + u_int32_t channel1 = mcc_channel; + u_int32_t chan1_freq = vos_chan_to_freq( channel1 ); + u_int32_t latency_chan1 = mcc_channel_time_latency; + + if (!wma) { + WMA_LOGE("%s:NULL wma ptr. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + pMac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + if (!pMac) { + WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* First step is to confirm if MCC is active */ + if (!limIsInMCC(pMac)) { + WMA_LOGE("%s: MCC is not active. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + /* Confirm MCC adaptive scheduler feature is disabled */ + if (wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, + &cfg_val) == eSIR_SUCCESS) { + if (cfg_val == WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX) { + WMA_LOGD("%s: Can't set channel latency while MCC " + "ADAPTIVE SCHED is enabled. Exit", __func__); + return VOS_STATUS_SUCCESS; + } + } else { + WMA_LOGE("%s: Failed to get value for MCC_ADAPTIVE_SCHED, " + "Exit w/o setting latency", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + /* If 0ms latency is provided, then FW will set to a default. + * Otherwise, latency must be at least 30ms. + */ + if ((latency_chan1 > 0) && + (latency_chan1 < WMI_MCC_MIN_NON_ZERO_CHANNEL_LATENCY)) { + WMA_LOGE("%s: Invalid time latency for Channel #1 = %dms " + "Minimum is 30ms (or 0 to use default value by " + "firmware)", __func__, latency_chan1); + return VOS_STATUS_E_INVAL; + } + + /* Set WMI CMD for channel time latency here */ + len = sizeof(wmi_resmgr_set_chan_latency_cmd_fixed_param) + + WMI_TLV_HDR_SIZE + /*Place holder for chan_time_latency array*/ + num_channels * sizeof(wmi_resmgr_chan_latency); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmdTL = (wmi_resmgr_set_chan_latency_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&cmdTL->tlv_header, + WMITLV_TAG_STRUC_wmi_resmgr_set_chan_latency_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_resmgr_set_chan_latency_cmd_fixed_param)); + cmdTL->num_chans = num_channels; + /* Update channel time latency information for home channel(s) */ + buf_ptr += sizeof(*cmdTL); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + num_channels * sizeof(wmi_resmgr_chan_latency)); + buf_ptr += WMI_TLV_HDR_SIZE; + chan_latency.chan_mhz = chan1_freq; + chan_latency.latency = latency_chan1; + vos_mem_copy(buf_ptr, &chan_latency, sizeof(chan_latency)); + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RESMGR_SET_CHAN_LATENCY_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send MCC Channel Time Latency command", + __func__); + adf_nbuf_free(buf); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/** + * Currently used to set time quota for 2 MCC vdevs/adapters using (operating + * channel, quota) for each mode . The info is provided run time using + * iwpriv command: iwpriv setMccQuota . + * Note: the quota provided in command is for the same mode in cmd. HDD + * checks if MCC mode is active, gets the second mode and its operating chan. + * Quota for the 2nd role is calculated as 100 - quota of first mode. + */ +static VOS_STATUS wma_set_mcc_channel_time_quota + ( + tp_wma_handle wma, + tANI_U32 adapter_1_chan_number, + tANI_U32 adapter_1_quota, + tANI_U32 adapter_2_chan_number + ) +{ + int ret = -1; + wmi_buf_t buf = 0; + u_int16_t len = 0; + u_int8_t *buf_ptr = NULL; + tANI_U32 cfg_val = 0; + struct sAniSirGlobal *pMac = NULL; + wmi_resmgr_set_chan_time_quota_cmd_fixed_param *cmdTQ = NULL; + wmi_resmgr_chan_time_quota chan_quota; + u_int32_t channel1 = adapter_1_chan_number; + u_int32_t channel2 = adapter_2_chan_number; + u_int32_t quota_chan1 = adapter_1_quota; + /* Knowing quota of 1st chan., derive quota for 2nd chan. */ + u_int32_t quota_chan2 = 100 - quota_chan1; + /* Note: setting time quota for MCC requires info for 2 channels */ + u_int32_t num_channels = 2; + u_int32_t chan1_freq = vos_chan_to_freq(adapter_1_chan_number); + u_int32_t chan2_freq = vos_chan_to_freq(adapter_2_chan_number); + + WMA_LOGD("%s: Channel1:%d, freq1:%dMHz, Quota1:%dms, " + "Channel2:%d, freq2:%dMHz, Quota2:%dms", __func__, + channel1, chan1_freq, quota_chan1, channel2, chan2_freq, + quota_chan2); + + if (!wma) { + WMA_LOGE("%s:NULL wma ptr. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + pMac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + if (!pMac) { + WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* First step is to confirm if MCC is active */ + if (!limIsInMCC(pMac)) { + WMA_LOGD("%s: MCC is not active. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* Confirm MCC adaptive scheduler feature is disabled */ + if (wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, + &cfg_val) == eSIR_SUCCESS) { + if (cfg_val == WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX) { + WMA_LOGD("%s: Can't set channel quota while " + "MCC_ADAPTIVE_SCHED is enabled. Exit", + __func__); + return VOS_STATUS_SUCCESS; + } + } else { + WMA_LOGE("%s: Failed to retrieve " + "WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED. Exit", + __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /** + * Perform sanity check on time quota values provided. + */ + if (quota_chan1 < WMI_MCC_MIN_CHANNEL_QUOTA || + quota_chan1 > WMI_MCC_MAX_CHANNEL_QUOTA) { + WMA_LOGE("%s: Invalid time quota for Channel #1=%dms. Minimum " + "is 20ms & maximum is 80ms", __func__, quota_chan1); + return VOS_STATUS_E_INVAL; + } + /* Set WMI CMD for channel time quota here */ + len = sizeof(wmi_resmgr_set_chan_time_quota_cmd_fixed_param) + + WMI_TLV_HDR_SIZE + /* Place holder for chan_time_quota array */ + num_channels * sizeof(wmi_resmgr_chan_time_quota); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmdTQ = (wmi_resmgr_set_chan_time_quota_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&cmdTQ->tlv_header, + WMITLV_TAG_STRUC_wmi_resmgr_set_chan_time_quota_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_resmgr_set_chan_time_quota_cmd_fixed_param)); + cmdTQ->num_chans = num_channels; + + /* Update channel time quota information for home channel(s) */ + buf_ptr += sizeof(*cmdTQ); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + num_channels * sizeof(wmi_resmgr_chan_time_quota)); + buf_ptr += WMI_TLV_HDR_SIZE; + chan_quota.chan_mhz = chan1_freq; + chan_quota.channel_time_quota = quota_chan1; + vos_mem_copy(buf_ptr, &chan_quota, sizeof(chan_quota)); + /* Construct channel and quota record for the 2nd MCC mode. */ + buf_ptr += sizeof(chan_quota); + chan_quota.chan_mhz = chan2_freq; + chan_quota.channel_time_quota = quota_chan2; + vos_mem_copy(buf_ptr, &chan_quota, sizeof(chan_quota)); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID); + if (ret) { + WMA_LOGE("Failed to send MCC Channel Time Quota command"); + adf_nbuf_free(buf); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/* function : wma_vdev_attach + * Description : + * Args : + * Returns : + */ +static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, + tpAddStaSelfParams self_sta_req, + u_int8_t generateRsp) +{ + ol_txrx_vdev_handle txrx_vdev_handle = NULL; + ol_txrx_pdev_handle txrx_pdev = vos_get_context(VOS_MODULE_ID_TXRX, + wma_handle->vos_context); + enum wlan_op_mode txrx_vdev_type; + VOS_STATUS status = VOS_STATUS_SUCCESS; + struct sAniSirGlobal *mac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + tANI_U32 cfg_val; + tANI_U16 val16; + int ret; + tSirMacHTCapabilityInfo *phtCapInfo; + + if (NULL == mac) { + WMA_LOGE("%s: Failed to get mac",__func__); + goto end; + } + + /* Create a vdev in target */ + if (wma_unified_vdev_create_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + self_sta_req->type, + self_sta_req->subType, + self_sta_req->selfMacAddr, + self_sta_req->nss_2g, + self_sta_req->nss_5g)) + { + WMA_LOGP("%s: Unable to add an interface for ath_dev", __func__); + status = VOS_STATUS_E_RESOURCES; + goto end; + } + + txrx_vdev_type = wma_get_txrx_vdev_type(self_sta_req->type); + + if (wlan_op_mode_unknown == txrx_vdev_type) { + WMA_LOGE("Failed to get txrx vdev type"); + wma_unified_vdev_delete_send(wma_handle->wmi_handle, + self_sta_req->sessionId); + goto end; + } + + txrx_vdev_handle = ol_txrx_vdev_attach(txrx_pdev, + self_sta_req->selfMacAddr, + self_sta_req->sessionId, + txrx_vdev_type); + wma_handle->interfaces[self_sta_req->sessionId].pause_bitmap = 0; + + WMA_LOGD("vdev_id %hu, txrx_vdev_handle = %p", self_sta_req->sessionId, + txrx_vdev_handle); + + if (NULL == txrx_vdev_handle) { + WMA_LOGP("%s: ol_txrx_vdev_attach failed", __func__); + status = VOS_STATUS_E_FAILURE; + wma_unified_vdev_delete_send(wma_handle->wmi_handle, + self_sta_req->sessionId); + goto end; + } + wma_handle->interfaces[self_sta_req->sessionId].handle = txrx_vdev_handle; + + wma_handle->interfaces[self_sta_req->sessionId].ptrn_match_enable = + wma_handle->ptrn_match_enable_all_vdev ? TRUE : FALSE; + + if (wlan_cfgGetInt(mac, WNI_CFG_WOWLAN_DEAUTH_ENABLE, &cfg_val) + != eSIR_SUCCESS) + wma_handle->wow.deauth_enable = TRUE; + else + wma_handle->wow.deauth_enable = cfg_val ? TRUE : FALSE; + + if (wlan_cfgGetInt(mac, WNI_CFG_WOWLAN_DISASSOC_ENABLE, &cfg_val) + != eSIR_SUCCESS) + wma_handle->wow.disassoc_enable = TRUE; + else + wma_handle->wow.disassoc_enable = cfg_val ? TRUE : FALSE; + + if (wlan_cfgGetInt(mac, WNI_CFG_WOWLAN_MAX_MISSED_BEACON, &cfg_val) + != eSIR_SUCCESS) + wma_handle->wow.bmiss_enable = TRUE; + else + wma_handle->wow.bmiss_enable = cfg_val ? TRUE : FALSE; + + vos_mem_copy(wma_handle->interfaces[self_sta_req->sessionId].addr, + self_sta_req->selfMacAddr, + sizeof(wma_handle->interfaces[self_sta_req->sessionId].addr)); + switch (self_sta_req->type) { + case WMI_VDEV_TYPE_STA: + if(wlan_cfgGetInt(mac, WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD, + &cfg_val ) != eSIR_SUCCESS) { + WMA_LOGE("Failed to get value for " + "WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD"); + cfg_val = DEFAULT_INFRA_STA_KEEP_ALIVE_PERIOD; + } + + wma_set_sta_keep_alive(wma_handle, + self_sta_req->sessionId, + SIR_KEEP_ALIVE_NULL_PKT, + cfg_val, + NULL, + NULL, + NULL); + break; + } + + wma_handle->interfaces[self_sta_req->sessionId].type = + self_sta_req->type; + wma_handle->interfaces[self_sta_req->sessionId].sub_type = + self_sta_req->subType; + wma_handle->interfaces[self_sta_req->sessionId].nss_2g = + self_sta_req->nss_2g; + wma_handle->interfaces[self_sta_req->sessionId].nss_5g = + self_sta_req->nss_5g; + adf_os_atomic_init(&wma_handle->interfaces + [self_sta_req->sessionId].bss_status); + + if (((self_sta_req->type == WMI_VDEV_TYPE_AP) && + (self_sta_req->subType == + WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) + || (self_sta_req->type == WMI_VDEV_TYPE_OCB)) { + WMA_LOGA("P2P Device: creating self peer %pM, vdev_id %hu", + self_sta_req->selfMacAddr, + self_sta_req->sessionId); + status = wma_create_peer(wma_handle, txrx_pdev, + txrx_vdev_handle, self_sta_req->selfMacAddr, + WMI_PEER_TYPE_DEFAULT,self_sta_req->sessionId, + VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to create peer", __func__); + status = VOS_STATUS_E_FAILURE; + wma_unified_vdev_delete_send(wma_handle->wmi_handle, + self_sta_req->sessionId); + } + } + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_DISCONNECT_TH, + self_sta_req->pkt_err_disconn_th); + if (ret) + WMA_LOGE("Failed to set WMI_VDEV_PARAM_DISCONNECT_TH"); + + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_MCC_RTSCTS_PROTECTION_ENABLE, + mac->roam.configParam.mcc_rts_cts_prot_enable); + if (ret) + WMA_LOGE("Failed to set WMI_VDEV_PARAM_MCC_RTSCTS_PROTECTION_ENABLE"); + + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_MCC_BROADCAST_PROBE_ENABLE, + mac->roam.configParam.mcc_bcast_prob_resp_enable); + if (ret) + WMA_LOGE("Failed to set WMI_VDEV_PARAM_MCC_BROADCAST_PROBE_ENABLE"); + + if (wlan_cfgGetInt(mac, WNI_CFG_RTS_THRESHOLD, + &cfg_val) == eSIR_SUCCESS) { + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_RTS_THRESHOLD, + cfg_val); + if (ret) + WMA_LOGE("Failed to set WMI_VDEV_PARAM_RTS_THRESHOLD"); + } else { + WMA_LOGE("Failed to get value for WNI_CFG_RTS_THRESHOLD, leaving unchanged"); + } + + if (wlan_cfgGetInt(mac, WNI_CFG_FRAGMENTATION_THRESHOLD, + &cfg_val) == eSIR_SUCCESS) { + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, + cfg_val); + if (ret) + WMA_LOGE("Failed to set WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD"); + } else { + WMA_LOGE("Failed to get value for WNI_CFG_FRAGMENTATION_THRESHOLD, leaving unchanged"); + } + + if (wlan_cfgGetInt(mac, WNI_CFG_HT_CAP_INFO, + &cfg_val) == eSIR_SUCCESS) { + val16 = (tANI_U16)cfg_val; + phtCapInfo = (tSirMacHTCapabilityInfo *)&cfg_val; + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_TX_STBC, + phtCapInfo->txSTBC); + if (ret) + WMA_LOGE("Failed to set WMI_VDEV_PARAM_TX_STBC"); + } else { + WMA_LOGE("Failed to get value of HT_CAP, TX STBC unchanged"); + } + /* Initialize roaming offload state */ + if ((self_sta_req->type == WMI_VDEV_TYPE_STA) && + (self_sta_req->subType == 0)) { + wma_handle->roam_offload_enabled = TRUE; + wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->sessionId, + WMI_VDEV_PARAM_ROAM_FW_OFFLOAD, + (WMI_ROAM_FW_OFFLOAD_ENABLE_FLAG | + WMI_ROAM_BMISS_FINAL_SCAN_ENABLE_FLAG)); + } + + /* Initialize BMISS parameters */ + if ((self_sta_req->type == WMI_VDEV_TYPE_STA) && + (self_sta_req->subType == 0)) { + wma_roam_scan_bmiss_cnt(wma_handle, + mac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt, + mac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt, + self_sta_req->sessionId); + } + + if (wlan_cfgGetInt(mac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, + &cfg_val) == eSIR_SUCCESS) { + WMA_LOGD("%s: setting ini value for WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED: %d", + __func__, cfg_val); + ret = wma_set_enable_disable_mcc_adaptive_scheduler(cfg_val); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED"); + } + } else { + WMA_LOGE("Failed to get value for WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, leaving unchanged"); + } + +end: + self_sta_req->status = status; + +#ifdef QCA_IBSS_SUPPORT + if (generateRsp) +#endif + wma_send_msg(wma_handle, WDA_ADD_STA_SELF_RSP, (void *)self_sta_req, 0); + + return txrx_vdev_handle; +} + +static VOS_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + v_VOID_t *mac = vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + + WMA_LOGD("%s: Enter", __func__); + + if (NULL == mac) { + WMA_LOGP("%s: Invalid context", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + processCfgDownloadReq(mac); + + WMA_LOGD("%s: Exit", __func__); + return vos_status; +} + +/* function : wma_set_scan_info + * Description : function to save current ongoing scan info + * Args : wma handle, scan id, scan requestor id, vdev id + * Returns : None + */ +static inline void wma_set_scan_info(tp_wma_handle wma_handle, + u_int32_t scan_id, + u_int32_t requestor, + u_int32_t vdev_id, + tSirP2pScanType p2p_scan_type) +{ + wma_handle->interfaces[vdev_id].scan_info.scan_id = scan_id; + wma_handle->interfaces[vdev_id].scan_info.scan_requestor_id = + requestor; + wma_handle->interfaces[vdev_id].scan_info.p2p_scan_type = p2p_scan_type; +} + +/* function : wma_reset_scan_info + * Description : function to reset the current ongoing scan info + * Args : wma handle, vdev_id + * Returns : None + */ +static inline void wma_reset_scan_info(tp_wma_handle wma_handle, + u_int8_t vdev_id) +{ + vos_mem_zero((void *) &(wma_handle->interfaces[vdev_id].scan_info), + sizeof(struct scan_param)); +} + +bool wma_check_scan_in_progress(WMA_HANDLE handle) +{ + tp_wma_handle wma_handle = handle; + int i; + + for (i = 0; i < wma_handle->max_bssid; i++){ + if (wma_handle->interfaces[i].scan_info.scan_id){ + + WMA_LOGE("%s: scan in progress on interface[%d],scanid = %d", + __func__, i, wma_handle->interfaces[i].scan_info.scan_id ); + return true; + } + } + return false; +} + +v_BOOL_t wma_is_SAP_active(tp_wma_handle wma_handle) +{ + int i; + + for (i = 0; i < wma_handle->max_bssid; i++) { + if (!wma_handle->interfaces[i].vdev_up) + continue; + if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP && + wma_handle->interfaces[i].sub_type == 0) + return TRUE; + } + return FALSE; +} + +v_BOOL_t wma_is_P2P_GO_active(tp_wma_handle wma_handle) +{ + int i; + + for (i = 0; i < wma_handle->max_bssid; i++) { + if (!wma_handle->interfaces[i].vdev_up) + continue; + if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP && + wma_handle->interfaces[i].sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO) + return TRUE; + } + return FALSE; +} + +v_BOOL_t wma_is_P2P_CLI_active(tp_wma_handle wma_handle) +{ + int i; + + for (i = 0; i < wma_handle->max_bssid; i++) { + if (!wma_handle->interfaces[i].vdev_up) + continue; + if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA && + wma_handle->interfaces[i].sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT) + return TRUE; + } + return FALSE; +} + +v_BOOL_t wma_is_STA_active(tp_wma_handle wma_handle) +{ + int i; + + for (i = 0; i < wma_handle->max_bssid; i++) { + if (!wma_handle->interfaces[i].vdev_up) + continue; + if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA && + wma_handle->interfaces[i].sub_type == 0) + return TRUE; + if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS) + return TRUE; + } + return FALSE; +} + +/** + * wma_is_mcc_24G() - Function to check MCC in 2.4GHz band + * @handle: WMA handle + * + * This function is used to check MCC in 2.4GHz band + * + * Return: True if WMA is in MCC in 2.4GHz band + * + */ +static bool wma_is_mcc_24G(WMA_HANDLE handle) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + int32_t prev_chan = 0; + int32_t i; + + if (NULL == wma_handle) { + WMA_LOGE("%s: wma_handle is NULL", __func__); + return false; + } + for (i = 0; i < wma_handle->max_bssid; i++) { + if (wma_handle->interfaces[i].handle && + wma_handle->interfaces[i].vdev_up) { + if ((prev_chan != 0 && + prev_chan != wma_handle->interfaces[i].mhz) && + (wma_handle->interfaces[i].mhz <= + VOS_CHAN_14_FREQ)) + return true; + else + prev_chan = wma_handle->interfaces[i].mhz; + } + } + return false; +} + +/* function : wma_get_buf_start_scan_cmd + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, + tSirScanOffloadReq *scan_req, + wmi_buf_t *buf, + int *buf_len) +{ + wmi_start_scan_cmd_fixed_param *cmd; + wmi_chan_list *chan_list = NULL; + wmi_mac_addr *bssid; + wmi_ssid *ssid = NULL; + u_int32_t *tmp_ptr, ie_len_with_pad; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + u_int8_t *buf_ptr; + u_int32_t dwell_time; + u_int8_t SSID_num; + int i; + int len = sizeof(*cmd); + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + + if (!pMac) { + WMA_LOGP("%s: pMac is NULL!", __func__); + return VOS_STATUS_E_FAILURE; + } + + len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of uint32 */ + /* calculate the length of buffer required */ + if (scan_req->channelList.numChannels) + len += scan_req->channelList.numChannels * sizeof(u_int32_t); + + len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of wmi_ssid structures */ + if (scan_req->numSsid) + len += scan_req->numSsid * sizeof(wmi_ssid); + + len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of wmi_mac_addr structures */ + len += sizeof(wmi_mac_addr); + + len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of bytes */ + if (scan_req->uIEFieldLen) + len += roundup(scan_req->uIEFieldLen, sizeof(u_int32_t)); + + /* Allocate the memory */ + *buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!*buf) { + WMA_LOGP("%s: failed to allocate memory for start scan cmd", + __func__); + return VOS_STATUS_E_FAILURE; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(*buf); + cmd = (wmi_start_scan_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_start_scan_cmd_fixed_param)); + + if (wma_handle->scan_id >= WMA_MAX_SCAN_ID) + wma_handle->scan_id = 0; + + cmd->vdev_id = scan_req->sessionId; + /* host cycles through the lower 12 bits of + wma_handle->scan_id to generate ids */ + cmd->scan_id = WMA_HOST_SCAN_REQID_PREFIX | ++wma_handle->scan_id; + cmd->scan_priority = WMI_SCAN_PRIORITY_LOW; + cmd->scan_req_id = WMA_HOST_SCAN_REQUESTOR_ID_PREFIX | + WMA_DEFAULT_SCAN_REQUESTER_ID; + + /* Set the scan events which the driver is intereseted to receive */ + /* TODO: handle all the other flags also */ + cmd->notify_scan_events = WMI_SCAN_EVENT_STARTED | + WMI_SCAN_EVENT_START_FAILED | + WMI_SCAN_EVENT_FOREIGN_CHANNEL | + WMI_SCAN_EVENT_COMPLETED | + WMI_SCAN_EVENT_DEQUEUED | + WMI_SCAN_EVENT_PREEMPTED | + WMI_SCAN_EVENT_RESTARTED; + + cmd->dwell_time_active = scan_req->maxChannelTime; + + if (scan_req->scanType == eSIR_ACTIVE_SCAN) { + /* In Active scan case, the firmware has to do passive scan on DFS channels + * So the passive scan duration should be updated properly so that the duration + * will be sufficient enough to receive the beacon from AP */ + + if (wlan_cfgGetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + &dwell_time) != eSIR_SUCCESS) { + WMA_LOGE("Failed to get passive max channel value" + "using default value"); + dwell_time = WMA_DWELL_TIME_PASSIVE_DEFAULT; + } + cmd->dwell_time_passive = dwell_time; + } + else + cmd->dwell_time_passive = scan_req->maxChannelTime; + + WMA_LOGI("Scan Type %x, Active dwell time %u, Passive dwell time %u", + scan_req->scanType, cmd->dwell_time_active, + cmd->dwell_time_passive); + + /* Ensure correct number of probes are sent on active channel */ + cmd->repeat_probe_time = cmd->dwell_time_active / WMA_SCAN_NPROBES_DEFAULT; + + /* CSR sends min_rest_Time, max_rest_time and idle_time + * for staying on home channel to continue data traffic. + * Rome fw has facility to monitor the traffic + * and move to next channel. Stay on the channel for min_rest_time + * and then leave if there is no traffic. + */ + cmd->min_rest_time = scan_req->min_rest_time; + cmd->max_rest_time = scan_req->restTime; + + /* Check for traffic at idle_time interval after min_rest_time. + * Default value is 25 ms to allow full use of max_rest_time + * when voice packets are running at 20 ms interval. + */ + cmd->idle_time = scan_req->idle_time; + + /* Large timeout value for full scan cycle, 30 seconds */ + cmd->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; + + /* add DS param IE in probe req frame */ + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ; + + /* do not add OFDM rates in 11B mode */ + if (scan_req->dot11mode != WNI_CFG_DOT11_MODE_11B) + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES; + else + WMA_LOGD("OFDM_RATES not included in 11B mode"); + + /* Do not combine multiple channels in a single burst. Come back + * to home channel for data traffic after every foreign channel. + * By default, prefer throughput performance over scan cycle time. + */ + cmd->burst_duration = 0; + + if (!scan_req->p2pScanType) { + WMA_LOGD("Normal Scan request"); + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES; + if (!scan_req->numSsid) + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_BCAST_PROBE_REQ; + if (scan_req->scanType == eSIR_PASSIVE_SCAN) + cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; + cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ; + /* + * Decide burst_duration and dwell_time_active based on + * what type of devices are active. + */ + do { + if (wma_is_SAP_active(wma_handle) && + wma_is_P2P_GO_active(wma_handle) && + wma_is_STA_active(wma_handle)) { + if (scan_req->maxChannelTime <= + WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION) + cmd->burst_duration = scan_req->maxChannelTime; + else + cmd->burst_duration = + WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION; + break; + } + if (wma_is_SAP_active(wma_handle)) { + /* Background scan while SoftAP is sending beacons. + * Max duration of CTS2self is 32 ms, which limits + * the dwell time. + */ + cmd->dwell_time_active = MIN(scan_req->maxChannelTime, + (WMA_CTS_DURATION_MS_MAX - WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME)); + cmd->dwell_time_passive = cmd->dwell_time_active; + cmd->burst_duration = 0; + break; + } + if (wma_handle->miracast_value && + wma_is_mcc_24G(wma_handle)) { + cmd->max_rest_time = + pMac->f_sta_miracast_mcc_rest_time_val; + } + if (wma_is_P2P_GO_active(wma_handle)) { + /* Background scan while GO is sending beacons. + * Every off-channel transition has overhead of 2 beacon + * intervals for NOA. Maximize number of channels in + * every transition by using burst scan. + */ + if (wma_handle->miracast_value) { + /* When miracast is running, burst duration + * needs to be minimum to avoid any stutter + * or glitch in miracast during station scan + */ + if (scan_req->maxChannelTime <= + WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION) + cmd->burst_duration = + scan_req->maxChannelTime; + else + cmd->burst_duration = + WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION; + } + else { + /* If miracast is not running, accomodate max + * stations to make the scans faster + */ + cmd->burst_duration = + WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS * + scan_req->maxChannelTime; + if (cmd->burst_duration > + WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION) { + u_int8_t channels = + WMA_P2P_SCAN_MAX_BURST_DURATION + / scan_req->maxChannelTime; + if (channels) + cmd->burst_duration = channels * + scan_req->maxChannelTime; + else + cmd->burst_duration = + WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION; + } + } + break; + } + if (wma_is_STA_active(wma_handle) || + wma_is_P2P_CLI_active(wma_handle)) { + /* Typical background scan. Disable burst scan for now. */ + cmd->burst_duration = 0; + break; + } + } while (0); + + } + else { + WMA_LOGD("P2P Scan"); + switch (scan_req->p2pScanType) { + case P2P_SCAN_TYPE_LISTEN: + WMA_LOGD("P2P_SCAN_TYPE_LISTEN"); + cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; + cmd->notify_scan_events |= + WMI_SCAN_EVENT_FOREIGN_CHANNEL; + cmd->repeat_probe_time = 0; + break; + case P2P_SCAN_TYPE_SEARCH: + WMA_LOGD("P2P_SCAN_TYPE_SEARCH"); + cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ; + /* Default P2P burst duration of 120 ms will cover + * 3 channels with default max dwell time 40 ms. + * Cap limit will be set by + * WMA_P2P_SCAN_MAX_BURST_DURATION. Burst duration + * should be such that no channel is scanned less + * than the dwell time in normal scenarios. + */ + if (scan_req->channelList.numChannels == P2P_SOCIAL_CHANNELS + && (!(wma_handle->miracast_value))) + cmd->repeat_probe_time = scan_req->maxChannelTime/5; + else + cmd->repeat_probe_time = scan_req->maxChannelTime/3; + + cmd->burst_duration = WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS * scan_req->maxChannelTime; + if (cmd->burst_duration > WMA_P2P_SCAN_MAX_BURST_DURATION) { + u_int8_t channels = WMA_P2P_SCAN_MAX_BURST_DURATION / scan_req->maxChannelTime; + if (channels) + cmd->burst_duration = channels * scan_req->maxChannelTime; + else + cmd->burst_duration = WMA_P2P_SCAN_MAX_BURST_DURATION; + } + break; + default: + WMA_LOGE("Invalid scan type"); + goto error; + } + } + + cmd->n_probes = (cmd->repeat_probe_time > 0) ? + cmd->dwell_time_active/cmd->repeat_probe_time : 0; + + buf_ptr += sizeof(*cmd); + tmp_ptr = (u_int32_t *) (buf_ptr + WMI_TLV_HDR_SIZE); + + if (scan_req->channelList.numChannels) { + chan_list = (wmi_chan_list *) tmp_ptr; + cmd->num_chan = scan_req->channelList.numChannels; + for (i = 0; i < scan_req->channelList.numChannels; ++i) { + tmp_ptr[i] = vos_chan_to_freq( + scan_req->channelList.channelNumber[i]); + } + } + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_UINT32, + (cmd->num_chan * sizeof(u_int32_t))); + buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_chan * sizeof(u_int32_t)); + if (scan_req->numSsid > SIR_SCAN_MAX_NUM_SSID) { + WMA_LOGE("Invalid value for numSsid"); + goto error; + } + cmd->num_ssids = scan_req->numSsid; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, + (cmd->num_ssids * sizeof(wmi_ssid))); + if (scan_req->numSsid) { + ssid = (wmi_ssid *) (buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < scan_req->numSsid; ++i) { + ssid->ssid_len = scan_req->ssId[i].length; + vos_mem_copy(ssid->ssid, scan_req->ssId[i].ssId, + scan_req->ssId[i].length); + ssid++; + } + } + buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_ssids * sizeof(wmi_ssid)); + + cmd->num_bssid = 1; + + if (!scan_req->p2pScanType) { + if (wma_is_SAP_active(wma_handle)) { + SSID_num = cmd->num_ssids * cmd->num_bssid; + cmd->repeat_probe_time = + probeTime_dwellTime_map[MIN(SSID_num, + WMA_DWELL_TIME_PROBE_TIME_MAP_SIZE - 1)]. + probe_time; + } + } + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, + (cmd->num_bssid * sizeof(wmi_mac_addr))); + bssid = (wmi_mac_addr *) (buf_ptr + WMI_TLV_HDR_SIZE); + WMI_CHAR_ARRAY_TO_MAC_ADDR(scan_req->bssId, bssid); + buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_bssid * sizeof(wmi_mac_addr)); + + cmd->ie_len = scan_req->uIEFieldLen; + ie_len_with_pad = roundup(scan_req->uIEFieldLen, sizeof(u_int32_t)); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_with_pad); + if (scan_req->uIEFieldLen) { + vos_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, + (u_int8_t *)scan_req + + (scan_req->uIEFieldOffset), + scan_req->uIEFieldLen); + } + buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad; + + *buf_len = len; + return VOS_STATUS_SUCCESS; +error: + vos_mem_free(*buf); + *buf = NULL; + return vos_status; +} + +/* function : wma_get_buf_stop_scan_cmd + * Description : function to fill the args for wmi_stop_scan_cmd + * Args : wma handle, wmi command buffer, buffer length, vdev_id + * Returns : failure or success + */ +VOS_STATUS wma_get_buf_stop_scan_cmd(tp_wma_handle wma_handle, + wmi_buf_t *buf, + int *buf_len, + tAbortScanParams *abort_scan_req) +{ + wmi_stop_scan_cmd_fixed_param *cmd; + VOS_STATUS vos_status; + int len = sizeof(*cmd); + + /* Allocate the memory */ + *buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!*buf) { + WMA_LOGP("%s: failed to allocate memory for stop scan cmd", + __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + cmd = (wmi_stop_scan_cmd_fixed_param *) wmi_buf_data(*buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_stop_scan_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_stop_scan_cmd_fixed_param)); + cmd->vdev_id = abort_scan_req->SessionId; + cmd->requestor = + wma_handle->interfaces[cmd->vdev_id].scan_info.scan_requestor_id; + cmd->scan_id = wma_handle->interfaces[cmd->vdev_id].scan_info.scan_id; + /* stop the scan with the corresponding scan_id */ + cmd->req_type = WMI_SCAN_STOP_ONE; + + *buf_len = len; + vos_status = VOS_STATUS_SUCCESS; +error: + return vos_status; + +} + +void wma_process_link_status_req(tp_wma_handle wma, + tAniGetLinkStatus *pGetLinkStatus) +{ + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + u_int8_t len = sizeof(wmi_request_stats_cmd_fixed_param); + struct wma_txrx_node *iface = &wma->interfaces[pGetLinkStatus->sessionId]; + + if (iface->plink_status_req) { + WMA_LOGE( + "%s:previous link status request is pending,deleting the new request", + __func__); + vos_mem_free(pGetLinkStatus); + return; + } + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + goto end; + } + + iface->plink_status_req = pGetLinkStatus; + cmd = (wmi_request_stats_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param)); + cmd->stats_id = WMI_REQUEST_VDEV_RATE_STAT; + cmd->vdev_id = pGetLinkStatus->sessionId; + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_REQUEST_STATS_CMDID)) { + WMA_LOGE("Failed to send WMI link status request to fw"); + wmi_buf_free(buf); + iface->plink_status_req = NULL; + goto end; + } + + return; + +end: + wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY); +} + +VOS_STATUS wma_send_snr_request(tp_wma_handle wma_handle, void *pGetRssiReq, + v_S7_t first_rssi) +{ + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + u_int8_t len = sizeof(wmi_request_stats_cmd_fixed_param); + tAniGetRssiReq *pRssiBkUp = NULL; + + /* command is in progess */ + if(NULL != wma_handle->pGetRssiReq) + return VOS_STATUS_SUCCESS; + + wma_handle->first_rssi = first_rssi; + + /* create a copy of csrRssiCallback to send rssi value + * after wmi event + */ + if(pGetRssiReq) { + pRssiBkUp = adf_os_mem_alloc(NULL, sizeof(tAniGetRssiReq)); + if(!pRssiBkUp) { + WMA_LOGE("Failed to allocate memory for tAniGetRssiReq"); + wma_handle->pGetRssiReq = NULL; + return VOS_STATUS_E_FAILURE; + } + adf_os_mem_set(pRssiBkUp, 0, sizeof(tAniGetRssiReq)); + pRssiBkUp->sessionId = ((tAniGetRssiReq*)pGetRssiReq)->sessionId; + pRssiBkUp->rssiCallback = ((tAniGetRssiReq*)pGetRssiReq)->rssiCallback; + pRssiBkUp->pDevContext = ((tAniGetRssiReq*)pGetRssiReq)->pDevContext; + wma_handle->pGetRssiReq = (void*)pRssiBkUp; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + adf_os_mem_free(pRssiBkUp); + wma_handle->pGetRssiReq = NULL; + return VOS_STATUS_E_FAILURE; + } + + cmd = (wmi_request_stats_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param)); + cmd->stats_id = WMI_REQUEST_VDEV_STAT; + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,WMI_REQUEST_STATS_CMDID)) { + WMA_LOGE("Failed to send host stats request to fw"); + wmi_buf_free(buf); + adf_os_mem_free(pRssiBkUp); + wma_handle->pGetRssiReq = NULL; + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS WDA_GetSnr(tAniGetSnrReq *psnr_req) +{ + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + tAniGetSnrReq *psnr_req_bkp; + u_int8_t len = sizeof(wmi_request_stats_cmd_fixed_param); + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma_handle = NULL; + struct wma_txrx_node *intr; + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + + if (NULL == wma_handle) { + WMA_LOGE("%s : Failed to get wma_handle", __func__); + return VOS_STATUS_E_FAULT; + } + + intr = &wma_handle->interfaces[psnr_req->sessionId]; + /* command is in progess */ + if(NULL != intr->psnr_req) { + WMA_LOGE("%s : previous snr request is pending", __func__); + return VOS_STATUS_SUCCESS; + } + + psnr_req_bkp = adf_os_mem_alloc(NULL, sizeof(tAniGetSnrReq)); + if (!psnr_req_bkp) { + WMA_LOGE("Failed to allocate memory for tAniGetSnrReq"); + return VOS_STATUS_E_FAILURE; + } + + adf_os_mem_set(psnr_req_bkp, 0, sizeof(tAniGetSnrReq)); + psnr_req_bkp->staId = psnr_req->staId; + psnr_req_bkp->pDevContext = psnr_req->pDevContext; + psnr_req_bkp->snrCallback = psnr_req->snrCallback; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + adf_os_mem_free(psnr_req_bkp); + return VOS_STATUS_E_FAILURE; + } + + cmd = (wmi_request_stats_cmd_fixed_param *)wmi_buf_data(buf); + cmd->vdev_id = psnr_req->sessionId; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param)); + cmd->stats_id = WMI_REQUEST_VDEV_STAT; + intr->psnr_req = (void *)psnr_req_bkp; + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_REQUEST_STATS_CMDID)) { + WMA_LOGE("Failed to send host stats request to fw"); + wmi_buf_free(buf); + adf_os_mem_free(psnr_req_bkp); + intr->psnr_req = NULL; + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_TSF +/** + * wma_capture_tsf() - send wmi to fw to capture tsf + * + * @wma_handle: wma handler + * @vdev_id: vdev id + * + * Return: wmi send state + */ +static VOS_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf; + wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; + int status; + int len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: failed to allocate memory for cap tsf cmd", + __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf); + cmd->vdev_id = vdev_id; + cmd->tsf_action = TSF_TSTAMP_CAPTURE_REQ; + + WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_REQ", + __func__, cmd->vdev_id); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send returned Error %d", status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + return VOS_STATUS_SUCCESS; + +error: + if (buf) + adf_nbuf_free(buf); + return vos_status; +} + +/** + * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO + * + * @wma_handle: wma handler + * @vdev_id: vdev id + * + * Return: wmi send state + */ +static VOS_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf; + wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; + int status; + int len = sizeof(*cmd); + uint8_t *buf_ptr; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: failed to allocate memory for reset tsf gpio", + __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr; + cmd->vdev_id = vdev_id; + cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET; + + WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", + __func__, cmd->vdev_id); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); + + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send returned Error %d", status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + return VOS_STATUS_SUCCESS; + +error: + if (buf) + adf_nbuf_free(buf); + return vos_status; +} +#else +static VOS_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id) +{ + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id) +{ + return VOS_STATUS_SUCCESS; +} +#endif + +/* function : wma_start_scan + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_start_scan(tp_wma_handle wma_handle, + tSirScanOffloadReq *scan_req, v_U16_t msg_type) +{ + uint32_t vdev_id, scan_id; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + wmi_start_scan_cmd_fixed_param *cmd; + int status = 0; + int len; + tSirScanOffloadEvent *scan_event; + + if (scan_req->sessionId > wma_handle->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %d, msg_type : 0x%x", __func__, + scan_req->sessionId, msg_type); + goto error1; + } + + /* Sanity check to find whether vdev id active or not */ + if (msg_type != WDA_START_SCAN_OFFLOAD_REQ && + !wma_handle->interfaces[scan_req->sessionId].handle) { + WMA_LOGA("vdev id [%d] is not active", scan_req->sessionId); + goto error1; + } + if (msg_type == WDA_START_SCAN_OFFLOAD_REQ) { + /* Start the timer for scan completion */ + vos_status = vos_timer_start(&wma_handle->wma_scan_comp_timer, + WMA_HW_DEF_SCAN_MAX_DURATION); + if (vos_status != VOS_STATUS_SUCCESS ) { + WMA_LOGE("Failed to start the scan completion timer"); + vos_status = VOS_STATUS_E_FAILURE; + goto error1; + } + } + /* Fill individual elements of wmi_start_scan_req and + * TLV for channel list, bssid, ssid etc ... */ + vos_status = wma_get_buf_start_scan_cmd(wma_handle, scan_req, + &buf, &len); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to get buffer for start scan cmd"); + goto error0; + } + + if (NULL == buf) { + WMA_LOGE("Failed to get buffer for saving current scan info"); + goto error0; + } + + /* Save current scan info */ + cmd = (wmi_start_scan_cmd_fixed_param *) wmi_buf_data(buf); + if (msg_type == WDA_CHNL_SWITCH_REQ) { + /* Adjust parameters for channel switch scan */ + cmd->min_rest_time = WMA_ROAM_PREAUTH_REST_TIME; + cmd->max_rest_time = WMA_ROAM_PREAUTH_REST_TIME; + cmd->max_scan_time = WMA_ROAM_PREAUTH_MAX_SCAN_TIME; + cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH; + adf_os_spin_lock_bh(&wma_handle->roam_preauth_lock); + cmd->scan_id = ( (cmd->scan_id & WMA_MAX_SCAN_ID) | + WMA_HOST_ROAM_SCAN_REQID_PREFIX); + wma_handle->roam_preauth_scan_id = cmd->scan_id; + adf_os_spin_unlock_bh(&wma_handle->roam_preauth_lock); + } + + wma_set_scan_info(wma_handle, cmd->scan_id, + cmd->scan_req_id, cmd->vdev_id, + scan_req->p2pScanType); + + WMA_LOGD("scan_id %x, vdev_id %x, scan type %x, msg_type %x", + cmd->scan_id, cmd->vdev_id, scan_req->p2pScanType, + msg_type); + + /* + * Cache vdev_id and scan_id because cmd is freed after calling + * wmi_unified_cmd_send cmd. WMI internally frees cmd buffer after + * getting TX complete from CE + */ + vdev_id = cmd->vdev_id; + scan_id = cmd->scan_id; + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_START_SCAN_CMDID); + /* Call the wmi api to request the scan */ + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("WMA --> WMI_START_SCAN_CMDID"); + + /* Update the scan parameters for handler */ + wma_handle->wma_scan_timer_info.vdev_id = vdev_id; + wma_handle->wma_scan_timer_info.scan_id = scan_id; + + return VOS_STATUS_SUCCESS; +error: + wma_reset_scan_info(wma_handle, cmd->vdev_id); + if (buf) + adf_nbuf_free(buf); +error0: + /* Stop the timer for scan completion */ + if (vos_timer_stop(&wma_handle->wma_scan_comp_timer) + != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to stop the scan completion timer"); + } +error1: + /* Send completion event for only for start scan request */ + if (msg_type == WDA_START_SCAN_OFFLOAD_REQ) { + scan_event = + (tSirScanOffloadEvent *) vos_mem_malloc(sizeof(tSirScanOffloadEvent)); + if (!scan_event) { + WMA_LOGP("%s: Failed to allocate memory for scan rsp", + __func__); + return VOS_STATUS_E_NOMEM; + } + memset(scan_event, 0x00, sizeof(*scan_event)); + scan_event->event = WMI_SCAN_EVENT_COMPLETED; + scan_event->reasonCode = eSIR_SME_SCAN_FAILED; + scan_event->p2pScanType = scan_req->p2pScanType; + scan_event->sessionId = scan_req->sessionId; + wma_send_msg(wma_handle, WDA_RX_SCAN_EVENT, (void *) scan_event, 0) ; + } + return vos_status; +} + +/* function : wma_stop_scan + * Description : function to send the stop scan command + * Args : wma_handle + * Returns : failure or success + */ +static VOS_STATUS wma_stop_scan(tp_wma_handle wma_handle, + tAbortScanParams *abort_scan_req) +{ + VOS_STATUS vos_status; + wmi_buf_t buf; + int status = 0; + int len; + + vos_status = wma_get_buf_stop_scan_cmd(wma_handle, &buf, &len, + abort_scan_req); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to get buffer for stop scan cmd"); + goto error1; + } + + if (NULL == buf) { + WMA_LOGE("Failed to get buffer for stop scan cmd"); + vos_status = VOS_STATUS_E_FAULT; + goto error1; + } + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_STOP_SCAN_CMDID); + /* Call the wmi api to request the scan */ + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_STOP_SCAN_CMDID returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("WMA --> WMI_STOP_SCAN_CMDID"); + + return VOS_STATUS_SUCCESS; +error: + if (buf) + adf_nbuf_free(buf); +error1: + return vos_status; +} + +/* function : wma_update_channel_list + * Description : Function is used to update the support channel list + * Args : wma_handle, list of supported channels and power + * Returns : SUCCESS or FAILURE + */ +VOS_STATUS wma_update_channel_list(WMA_HANDLE handle, + tSirUpdateChanList *chan_list) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_buf_t buf; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_scan_chan_list_cmd_fixed_param *cmd; + int status, i; + u_int8_t *buf_ptr; + wmi_channel *chan_info; + u_int16_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; + + len += sizeof(wmi_channel) * chan_list->numChan; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate memory"); + vos_status = VOS_STATUS_E_NOMEM; + goto end; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_scan_chan_list_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_scan_chan_list_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_scan_chan_list_cmd_fixed_param)); + + WMA_LOGD("no of channels = %d, len = %d", chan_list->numChan, len); + + cmd->num_scan_chans = chan_list->numChan; + WMITLV_SET_HDR((buf_ptr + sizeof(wmi_scan_chan_list_cmd_fixed_param)), + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_channel) * chan_list->numChan); + chan_info = (wmi_channel *) (buf_ptr + sizeof(*cmd) + WMI_TLV_HDR_SIZE); + + WMA_LOGD("ht %d, vht %d, vht_24 %d", chan_list->ht_en, + chan_list->vht_en, chan_list->vht_24_en); + for (i = 0; i < chan_list->numChan; ++i) { + WMITLV_SET_HDR(&chan_info->tlv_header, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + chan_info->mhz = + vos_chan_to_freq(chan_list->chanParam[i].chanId); + chan_info->band_center_freq1 = chan_info->mhz; + chan_info->band_center_freq2 = 0; + + WMA_LOGD("chan[%d] = %u", i, chan_info->mhz); + if (chan_list->chanParam[i].dfsSet) { + WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE); + WMA_LOGI("chan[%d] DFS[%d]\n", + chan_list->chanParam[i].chanId, + chan_list->chanParam[i].dfsSet); + } + + if (chan_list->chanParam[i].half_rate) { + WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_HALF_RATE); + } else if (chan_list->chanParam[i].quarter_rate) { + WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_QUARTER_RATE); + } + + if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) { + WMI_SET_CHANNEL_MODE(chan_info, MODE_11G); + if (chan_list->vht_en && chan_list->vht_24_en) + WMI_SET_CHANNEL_FLAG(chan_info, + WMI_CHAN_FLAG_ALLOW_VHT); + } else { + WMI_SET_CHANNEL_MODE(chan_info, MODE_11A); + if (chan_list->vht_en) + WMI_SET_CHANNEL_FLAG(chan_info, + WMI_CHAN_FLAG_ALLOW_VHT); + } + + if (chan_list->ht_en) + WMI_SET_CHANNEL_FLAG(chan_info, + WMI_CHAN_FLAG_ALLOW_HT); + + WMI_SET_CHANNEL_MAX_TX_POWER(chan_info, + chan_list->chanParam[i].pwr); + + WMI_SET_CHANNEL_REG_POWER(chan_info, + chan_list->chanParam[i].pwr); + WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz, + chan_list->chanParam[i].pwr); + /*TODO: Set WMI_SET_CHANNEL_MIN_POWER */ + /*TODO: Set WMI_SET_CHANNEL_ANTENNA_MAX */ + /*TODO: WMI_SET_CHANNEL_REG_CLASSID*/ + chan_info++; + } + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_SCAN_CHAN_LIST_CMDID); + + if (status != EOK) { + vos_status = VOS_STATUS_E_FAILURE; + WMA_LOGE("Failed to send WMI_SCAN_CHAN_LIST_CMDID"); + wmi_buf_free(buf); + } +end: + return vos_status; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +VOS_STATUS wma_roam_scan_fill_self_caps(tp_wma_handle wma_handle, + wmi_roam_offload_tlv_param *roam_offload_params, + tSirRoamOffloadScanReq *roam_req) +{ + struct sAniSirGlobal *pMac = NULL; + tSirMacCapabilityInfo selfCaps; + tANI_U32 val = 0; + tANI_U32 nCfgValue; + tANI_U16 *pCfgValue16; + tANI_U8 nCfgValue8, *pCfgValue8; + tSirMacQosInfoStation macQosInfoSta; + union { + tANI_U16 nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + tSirMacExtendedHTCapabilityInfo extHtCapInfo; + } uHTCapabilityInfo; + + vos_mem_set(&macQosInfoSta, 0, sizeof(tSirMacQosInfoStation)); + /* Roaming is done only for INFRA STA type. + * So, ess will be one and ibss will be Zero */ + pMac = (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + if (!pMac) { + WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != + eSIR_SUCCESS){ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_PRIVACY_ENABLED"); + return VOS_STATUS_E_FAILURE; + } + selfCaps.ess = 1; + selfCaps.ibss = 0; + if (val) + selfCaps.privacy = 1; + if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != + eSIR_SUCCESS){ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_SHORT_PREAMBLE"); + return VOS_STATUS_E_FAILURE; + } + if (val) + selfCaps.shortPreamble = 1; + + selfCaps.pbcc = 0; + selfCaps.channelAgility = 0; + if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, + &val) != eSIR_SUCCESS){ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED"); + return VOS_STATUS_E_FAILURE; + } + if (val) + selfCaps.shortSlotTime = 1; + if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_11H_ENABLED"); + return VOS_STATUS_E_FAILURE; + } + if (val) + selfCaps.spectrumMgt = 1; + if (wlan_cfgGetInt(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_QOS_ENABLED"); + return VOS_STATUS_E_FAILURE; + } + if (val) + selfCaps.qos = 1; + if (wlan_cfgGetInt(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_APSD_ENABLED"); + return VOS_STATUS_E_FAILURE; + } + if (val) + selfCaps.apsd = 1; + + selfCaps.rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; + + if (wlan_cfgGetInt(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BLOCK_ACK_ENABLED"); + return VOS_STATUS_E_FAILURE; + } + selfCaps.delayedBA = + (tANI_U16)((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); + selfCaps.immediateBA = + (tANI_U16)((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); + pCfgValue16 = (tANI_U16 *)&selfCaps; + roam_offload_params->capability = (*pCfgValue16) & 0xFFFF; + + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &nCfgValue) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_HT_CAP_INFO"); + return VOS_STATUS_E_FAILURE; + } + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + roam_offload_params->ht_caps_info = + uHTCapabilityInfo.nCfgValue16 & 0xFFFF; + if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &nCfgValue) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_HT_AMPDU_PARAMS"); + return VOS_STATUS_E_FAILURE; + } + /* tSirMacHTParametersInfo */ + nCfgValue8 = ( tANI_U8 ) nCfgValue; + roam_offload_params->ampdu_param = (nCfgValue8) & 0xFF; + + val = ROAM_OFFLOAD_NUM_MCS_SET; + if (wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET, + (tANI_U8*)roam_offload_params->mcsset, + &val) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_SUPPORTED_MCS_SET"); + return VOS_STATUS_E_FAILURE; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_EXT_HT_CAP_INFO, &nCfgValue) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_EXT_HT_CAP_INFO"); + return VOS_STATUS_E_FAILURE; + } + /* uHTCapabilityInfo.extHtCapInfo */ + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + roam_offload_params->ht_ext_cap = + uHTCapabilityInfo.nCfgValue16 & 0xFFFF; + + if (wlan_cfgGetInt(pMac, WNI_CFG_TX_BF_CAP, &nCfgValue) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_TX_BF_CAP"); + return VOS_STATUS_E_FAILURE; + } + /* tSirMacTxBFCapabilityInfo */ + nCfgValue8 = ( tANI_U8 ) nCfgValue; + roam_offload_params->ht_txbf = nCfgValue8 & 0xFF; + if (wlan_cfgGetInt(pMac, WNI_CFG_AS_CAP, &nCfgValue) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_AS_CAP"); + return VOS_STATUS_E_FAILURE; + } + /* tSirMacASCapabilityInfo */ + nCfgValue8 = ( tANI_U8 ) nCfgValue; + roam_offload_params->asel_cap = nCfgValue8 & 0xFF; + + /* QOS Info */ + if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &nCfgValue) != + eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_MAX_SP_LENGTH"); + return VOS_STATUS_E_FAILURE; + } + nCfgValue8 = ( tANI_U8 ) nCfgValue; + macQosInfoSta.maxSpLen = nCfgValue8; + macQosInfoSta.moreDataAck = 0; + macQosInfoSta.qack = 0; + macQosInfoSta.acbe_uapsd = roam_req->AcUapsd.acbe_uapsd; + macQosInfoSta.acbk_uapsd = roam_req->AcUapsd.acbk_uapsd; + macQosInfoSta.acvi_uapsd = roam_req->AcUapsd.acvi_uapsd; + macQosInfoSta.acvo_uapsd = roam_req->AcUapsd.acvo_uapsd; + pCfgValue8 = (tANI_U8 *)&macQosInfoSta; + /* macQosInfoSta Only queue_request is set.Refer to + * PopulateDot11fWMMCaps for more details + */ + roam_offload_params->qos_caps = (*pCfgValue8) & 0xFF; + roam_offload_params->wmm_caps = 0x4 & 0xFF; + return VOS_STATUS_SUCCESS; +} + +#endif +/* function : wma_roam_scan_offload_mode + * Description : send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback + * : of WMI_ROAM_SCAN_MODE. + * Args : scan_cmd_fp contains the scan parameters. + * : mode controls rssi based and periodic scans by roam engine. + * Returns : + */ +VOS_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle, + wmi_start_scan_cmd_fixed_param *scan_cmd_fp, + tSirRoamOffloadScanReq *roam_req, + u_int32_t mode, + u_int32_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + u_int8_t *buf_ptr; + wmi_roam_scan_mode_fixed_param *roam_scan_mode_fp; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + int auth_mode = WMI_AUTH_NONE; + wmi_roam_offload_tlv_param *roam_offload_params; + wmi_roam_11i_offload_tlv_param *roam_offload_11i; + wmi_roam_11r_offload_tlv_param *roam_offload_11r; + wmi_roam_ese_offload_tlv_param *roam_offload_ese; + if (roam_req) + auth_mode = eCsrAuthType_to_rsn_authmode + (roam_req->ConnectedNetwork.authentication, + roam_req->ConnectedNetwork.encryption); + WMA_LOGD("%s : auth mode = %d",__func__, auth_mode); +#endif + /* Need to create a buf with roam_scan command at + * front and piggyback with scan command */ + len = sizeof(wmi_roam_scan_mode_fixed_param) + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + (2 * WMI_TLV_HDR_SIZE) + +#endif + sizeof(wmi_start_scan_cmd_fixed_param); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_req && roam_req->RoamOffloadEnabled) { + len += sizeof(wmi_roam_offload_tlv_param); + len += WMI_TLV_HDR_SIZE; + if((auth_mode != WMI_AUTH_NONE) && + ((auth_mode != WMI_AUTH_OPEN) || + (auth_mode == WMI_AUTH_OPEN && + roam_req->MDID.mdiePresent) || roam_req->IsESEAssoc)){ + len += WMI_TLV_HDR_SIZE; + if(roam_req->IsESEAssoc) + len += sizeof(wmi_roam_ese_offload_tlv_param); + else if (auth_mode == WMI_AUTH_FT_RSNA || + auth_mode == WMI_AUTH_FT_RSNA_PSK || + (auth_mode == WMI_AUTH_OPEN && + roam_req->MDID.mdiePresent)) + len += sizeof(wmi_roam_11r_offload_tlv_param); + else + len += sizeof(wmi_roam_11i_offload_tlv_param); + } else { + len += WMI_TLV_HDR_SIZE; + } + } else { + if (roam_req) + WMA_LOGD("%s : roam offload = %d", + __func__, roam_req->RoamOffloadEnabled); + else + WMA_LOGD("%s : roam_req is NULL",__func__); + len += (2 * WMI_TLV_HDR_SIZE); + } + if (roam_req && roam_req->RoamOffloadEnabled) { + mode = mode | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD; + } +#endif + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + roam_scan_mode_fp = (wmi_roam_scan_mode_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&roam_scan_mode_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_mode_fixed_param)); + + roam_scan_mode_fp->roam_scan_mode = mode; + roam_scan_mode_fp->vdev_id = vdev_id; + /* Fill in scan parameters suitable for roaming scan */ + buf_ptr += sizeof(wmi_roam_scan_mode_fixed_param); + vos_mem_copy(buf_ptr, scan_cmd_fp, sizeof(wmi_start_scan_cmd_fixed_param)); + /* Ensure there is no additional IEs */ + scan_cmd_fp->ie_len = 0; + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_start_scan_cmd_fixed_param)); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param); + if (roam_req && roam_req->RoamOffloadEnabled) { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_params = (wmi_roam_offload_tlv_param *) buf_ptr; + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_offload_tlv_param)); + roam_offload_params->prefer_5g = roam_req->Prefer5GHz; + roam_offload_params->rssi_cat_gap = roam_req->RoamRssiCatGap; + roam_offload_params->select_5g_margin = roam_req->Select5GHzMargin; + roam_offload_params->reassoc_failure_timeout = + roam_req->ReassocFailureTimeout; + /* Fill the capabilities */ + wma_roam_scan_fill_self_caps(wma_handle, roam_offload_params, roam_req); + buf_ptr += sizeof(wmi_roam_offload_tlv_param); + /* The TLV's are in the order of 11i, 11R, ESE. Hence, + * they are filled in the same order.Depending on the + * authentication type, the other mode TLV's are nullified + * and only headers are filled.*/ + if ((auth_mode != WMI_AUTH_NONE) && + ((auth_mode != WMI_AUTH_OPEN) || + (auth_mode == WMI_AUTH_OPEN && roam_req->MDID.mdiePresent) || + (roam_req->IsESEAssoc))) { + if (roam_req->IsESEAssoc){ + WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_ese_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_ese = + (wmi_roam_ese_offload_tlv_param *) buf_ptr; + vos_mem_copy (roam_offload_ese->krk, roam_req->KRK, + sizeof(roam_req->KRK)); + vos_mem_copy (roam_offload_ese->btk, roam_req->BTK, + sizeof(roam_req->BTK)); + WMITLV_SET_HDR(&roam_offload_ese->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_ese_offload_tlv_param)); + buf_ptr += sizeof(wmi_roam_ese_offload_tlv_param); + } else if (auth_mode == WMI_AUTH_FT_RSNA || + auth_mode == WMI_AUTH_FT_RSNA_PSK || + (auth_mode == WMI_AUTH_OPEN && + roam_req->MDID.mdiePresent)){ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_11r_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_11r = + (wmi_roam_11r_offload_tlv_param *) buf_ptr; + roam_offload_11r->r0kh_id_len = roam_req->R0KH_ID_Length; + vos_mem_copy (roam_offload_11r->r0kh_id, roam_req->R0KH_ID, + roam_offload_11r->r0kh_id_len); + vos_mem_copy (roam_offload_11r->psk_msk, roam_req->PSK_PMK, + sizeof(roam_req->PSK_PMK)); + roam_offload_11r->psk_msk_len = roam_req->pmk_len; + roam_offload_11r->mdie_present = roam_req->MDID.mdiePresent; + roam_offload_11r->mdid = roam_req->MDID.mobilityDomain; + if(auth_mode == WMI_AUTH_OPEN) { + /* If FT-Open ensure pmk length + and r0khid len are zero */ + roam_offload_11r->r0kh_id_len = 0; + roam_offload_11r->psk_msk_len = 0; + } + WMITLV_SET_HDR(&roam_offload_11r->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_11r_offload_tlv_param)); + buf_ptr += sizeof(wmi_roam_11r_offload_tlv_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + } else { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_11i_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_11i = + (wmi_roam_11i_offload_tlv_param *) buf_ptr; + if (roam_req->RoamKeyMgmtOffloadEnabled) { + WMI_SET_ROAM_OFFLOAD_OKC_ENABLED( + roam_offload_11i->flags); + WMA_LOGE("LFR3:OKC Enabled"); + } else { + WMI_SET_ROAM_OFFLOAD_OKC_DISABLED( + roam_offload_11i->flags); + WMA_LOGE("LFR3:OKC Disabled"); + } + + + vos_mem_copy (roam_offload_11i->pmk, roam_req->PSK_PMK, + sizeof(roam_req->PSK_PMK)); + roam_offload_11i->pmk_len = roam_req->pmk_len; + WMITLV_SET_HDR(&roam_offload_11i->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_11i_offload_tlv_param) ); + buf_ptr += sizeof(wmi_roam_11i_offload_tlv_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,0); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,0); + buf_ptr += WMI_TLV_HDR_SIZE; + } + } else { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + } + } else { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + } +#endif + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_SCAN_MODE); + if (status != EOK) { + WMA_LOGE + ("wmi_unified_cmd_send WMI_ROAM_SCAN_MODE returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_MODE", __func__); + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return vos_status; +} + +/* function : wma_roam_scan_offload_rssi_threshold + * Description : Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware + * Args : + * Returns : + */ +VOS_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len, rssi_thresh, rssi_thresh_diff; + u_int8_t *buf_ptr; + wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp; + wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL; + struct roam_ext_params *roam_params; + uint32_t hirssi_scan_max_count; + uint32_t hirssi_scan_delta; + int32_t hirssi_upper_bound; + int32_t good_rssi_threshold; + + /* Send rssi threshold */ + roam_params = &roam_req->roam_params; + rssi_thresh = roam_req->LookupThreshold - WMA_NOISE_FLOOR_DBM_DEFAULT; + rssi_thresh_diff = roam_req->OpportunisticScanThresholdDiff; + hirssi_scan_max_count = roam_req->hi_rssi_scan_max_count; + hirssi_scan_delta = roam_req->hi_rssi_scan_rssi_delta; + hirssi_upper_bound = roam_req->hi_rssi_scan_rssi_ub - + WMA_NOISE_FLOOR_DBM_DEFAULT; + len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param); + len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/ + len += sizeof(wmi_roam_scan_extended_threshold_param); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + rssi_threshold_fp = (wmi_roam_scan_rssi_threshold_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&rssi_threshold_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_roam_scan_rssi_threshold_fixed_param)); + /* fill in threshold values */ + rssi_threshold_fp->vdev_id = roam_req->sessionId; + rssi_threshold_fp->roam_scan_rssi_thresh = rssi_thresh & 0x000000ff; + rssi_threshold_fp->roam_rssi_thresh_diff = rssi_thresh_diff & 0x000000ff; + rssi_threshold_fp->hirssi_scan_max_count = hirssi_scan_max_count; + rssi_threshold_fp->hirssi_scan_delta = hirssi_scan_delta; + rssi_threshold_fp->hirssi_upper_bound = hirssi_upper_bound & 0x00000ff; + + buf_ptr += sizeof(wmi_roam_scan_rssi_threshold_fixed_param); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_scan_extended_threshold_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + ext_thresholds = (wmi_roam_scan_extended_threshold_param *) buf_ptr; + /* The current Noise floor in firmware is -96dBm. Penalty/Boost threshold is + * applied on a weaker signal to make it even more weaker. So, there + * is a chance that the user may configure a very low Penalty/Boost + * threshold beyond the noise floor. If that is the case, then suppress + * the penalty/boost threshold to the noise floor. + */ + if (roam_params->raise_rssi_thresh_5g < WMA_NOISE_FLOOR_DBM_DEFAULT) + ext_thresholds->penalty_threshold_5g = 0; + else + ext_thresholds->boost_threshold_5g = + (roam_params->raise_rssi_thresh_5g - WMA_NOISE_FLOOR_DBM_DEFAULT) & + 0x000000ff; + if (roam_params->drop_rssi_thresh_5g < WMA_NOISE_FLOOR_DBM_DEFAULT) + ext_thresholds->penalty_threshold_5g = 0; + else + ext_thresholds->penalty_threshold_5g = + (roam_params->drop_rssi_thresh_5g - WMA_NOISE_FLOOR_DBM_DEFAULT) & + 0x000000ff; + ext_thresholds->boost_algorithm_5g = WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR; + ext_thresholds->boost_factor_5g = roam_params->raise_factor_5g; + ext_thresholds->penalty_algorithm_5g = + WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR; + ext_thresholds->penalty_factor_5g = roam_params->drop_factor_5g; + ext_thresholds->max_boost_5g = roam_params->max_raise_rssi_5g; + ext_thresholds->max_penalty_5g = roam_params->max_drop_rssi_5g; + if (roam_params->good_rssi_roam) + good_rssi_threshold = WMA_NOISE_FLOOR_DBM_DEFAULT; + else + good_rssi_threshold = 0; + ext_thresholds->good_rssi_threshold = + (good_rssi_threshold - WMA_NOISE_FLOOR_DBM_DEFAULT) & 0x000000ff; + WMA_LOGD("WMA --> good_rssi_threshold=%d", + ext_thresholds->good_rssi_threshold); + WMITLV_SET_HDR(&ext_thresholds->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_scan_extended_threshold_param)); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_SCAN_RSSI_THRESHOLD); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI( + "%s: WMA --> WMI_ROAM_SCAN_RSSI_THRESHOLD roam_scan_rssi_thresh=%d, roam_rssi_thresh_diff=%d", + __func__, rssi_thresh, rssi_thresh_diff); + WMA_LOGI( + "%s: WMA --> WMI_ROAM_SCAN_RSSI_THRESHOLD hirssi_scan max_count=%d, delta=%d", + __func__, hirssi_scan_max_count, hirssi_scan_delta); + WMA_LOGI( + "%s: WMA --> WMI_ROAM_SCAN_RSSI_THRESHOLD hirssi_upper_bound=%d", + __func__, hirssi_upper_bound); + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return vos_status; +} + +/* function : wma_roam_scan_offload_scan_period + * Description : Send WMI_ROAM_SCAN_PERIOD TLV to firmware + * Args : + * Returns : + */ +VOS_STATUS wma_roam_scan_offload_scan_period(tp_wma_handle wma_handle, + A_UINT32 scan_period, + A_UINT32 scan_age, + u_int32_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + u_int8_t *buf_ptr; + wmi_roam_scan_period_fixed_param *scan_period_fp; + + /* Send scan period values */ + len = sizeof(wmi_roam_scan_period_fixed_param); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + scan_period_fp = (wmi_roam_scan_period_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&scan_period_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_roam_scan_period_fixed_param)); + /* fill in scan period values */ + scan_period_fp->vdev_id = vdev_id; + scan_period_fp->roam_scan_period = scan_period; /* 20 seconds */ + scan_period_fp->roam_scan_age = scan_age; + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_SCAN_PERIOD); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_PERIOD returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_PERIOD roam_scan_period=%d, roam_scan_age=%d", + __func__, scan_period, scan_age); + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return vos_status; +} +/* function : wma_roam_scan_offload_rssi_change + * Description : Send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD TLV to firmware + * Args : + * Returns : + */ +VOS_STATUS wma_roam_scan_offload_rssi_change(tp_wma_handle wma_handle, + u_int32_t vdev_id, + A_INT32 rssi_change_thresh, + A_UINT32 bcn_rssi_weight, + A_UINT32 hirssi_delay_btw_scans) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + u_int8_t *buf_ptr; + wmi_roam_scan_rssi_change_threshold_fixed_param *rssi_change_fp; + + /* Send rssi change parameters */ + len = sizeof(wmi_roam_scan_rssi_change_threshold_fixed_param); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + rssi_change_fp = (wmi_roam_scan_rssi_change_threshold_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&rssi_change_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_roam_scan_rssi_change_threshold_fixed_param)); + /* fill in rssi change threshold (hysteresis) values */ + rssi_change_fp->vdev_id = vdev_id; + rssi_change_fp->roam_scan_rssi_change_thresh = rssi_change_thresh; + rssi_change_fp->bcn_rssi_weight = bcn_rssi_weight; + rssi_change_fp->hirssi_delay_btw_scans = hirssi_delay_btw_scans; + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_RSSI_CHANGE_THERSHOLD roam_scan_rssi_change_thresh=%d, bcn_rssi_weight=%d", + __func__, rssi_change_thresh, bcn_rssi_weight); + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_RSSI_CHANGE_THERSHOLD hirssi_delay_btw_scans=%d", + __func__, hirssi_delay_btw_scans); + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return vos_status; +} + +/* function : wma_roam_scan_offload_chan_list + * Description : Send WMI_ROAM_CHAN_LIST TLV to firmware + * Args : + * Returns : + */ +VOS_STATUS wma_roam_scan_offload_chan_list(tp_wma_handle wma_handle, + u_int8_t chan_count, + u_int8_t *chan_list, + u_int8_t list_type, + u_int32_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len, list_tlv_len; + int i; + u_int8_t *buf_ptr; + wmi_roam_chan_list_fixed_param *chan_list_fp; + A_UINT32 *roam_chan_list_array; + + if (chan_count == 0) + { + WMA_LOGD("%s : invalid number of channels %d", __func__, chan_count); + return VOS_STATUS_E_EMPTY; + } + /* Channel list is a table of 2 TLV's */ + list_tlv_len = WMI_TLV_HDR_SIZE + chan_count * sizeof(A_UINT32); + len = sizeof(wmi_roam_chan_list_fixed_param) + list_tlv_len; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + chan_list_fp = (wmi_roam_chan_list_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&chan_list_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_chan_list_fixed_param)); + chan_list_fp->vdev_id = vdev_id; + chan_list_fp->num_chan = chan_count; + if (chan_count > 0 && list_type == CHANNEL_LIST_STATIC) { + /* external app is controlling channel list */ + chan_list_fp->chan_list_type = WMI_ROAM_SCAN_CHAN_LIST_TYPE_STATIC; + } else { + /* umac supplied occupied channel list in LFR */ + chan_list_fp->chan_list_type = WMI_ROAM_SCAN_CHAN_LIST_TYPE_DYNAMIC; + } + + buf_ptr += sizeof(wmi_roam_chan_list_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (chan_list_fp->num_chan * sizeof(u_int32_t))); + roam_chan_list_array = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE); + WMA_LOGI("%s: %d channels = ", __func__, chan_list_fp->num_chan); + for (i = 0; ((i < chan_list_fp->num_chan) && + (i < SIR_ROAM_MAX_CHANNELS)); i++) { + roam_chan_list_array[i] = vos_chan_to_freq(chan_list[i]); + WMA_LOGI("%d,",roam_chan_list_array[i]); + } + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_CHAN_LIST); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_CHAN_LIST returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CHAN_LIST", __func__); + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return vos_status; +} + +/* function : eCsrAuthType_to_rsn_authmode + * Description : Map CSR's authentication type into RSN auth mode used by firmware + * Args : + * Returns : + */ + + +A_UINT32 eCsrAuthType_to_rsn_authmode (eCsrAuthType authtype, eCsrEncryptionType encr) { + switch(authtype) { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + return (WMI_AUTH_OPEN); + case eCSR_AUTH_TYPE_WPA: + return (WMI_AUTH_WPA); + case eCSR_AUTH_TYPE_WPA_PSK: + return (WMI_AUTH_WPA_PSK); + case eCSR_AUTH_TYPE_RSN: + return (WMI_AUTH_RSNA); + case eCSR_AUTH_TYPE_RSN_PSK: + return (WMI_AUTH_RSNA_PSK); +#if defined WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: + return (WMI_AUTH_FT_RSNA); + case eCSR_AUTH_TYPE_FT_RSN_PSK: + return (WMI_AUTH_FT_RSNA_PSK); +#endif +#ifdef FEATURE_WLAN_WAPI + case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE: + return (WMI_AUTH_WAPI); + case eCSR_AUTH_TYPE_WAPI_WAI_PSK: + return(WMI_AUTH_WAPI_PSK); +#endif +#ifdef FEATURE_WLAN_ESE + case eCSR_AUTH_TYPE_CCKM_WPA: + case eCSR_AUTH_TYPE_CCKM_RSN: + return (WMI_AUTH_CCKM); +#endif +#ifdef WLAN_FEATURE_11W + case eCSR_AUTH_TYPE_RSN_PSK_SHA256: + return (WMI_AUTH_RSNA_PSK_SHA256); + case eCSR_AUTH_TYPE_RSN_8021X_SHA256: + return (WMI_AUTH_RSNA_8021X_SHA256); +#endif + case eCSR_AUTH_TYPE_NONE: + case eCSR_AUTH_TYPE_AUTOSWITCH: + /* In case of WEP and other keys, NONE means OPEN auth */ + if (encr == eCSR_ENCRYPT_TYPE_WEP40_STATICKEY || + encr == eCSR_ENCRYPT_TYPE_WEP104_STATICKEY || + encr == eCSR_ENCRYPT_TYPE_WEP40 || + encr == eCSR_ENCRYPT_TYPE_WEP104 || + encr == eCSR_ENCRYPT_TYPE_TKIP || + encr == eCSR_ENCRYPT_TYPE_AES) { + return (WMI_AUTH_OPEN); + } + return(WMI_AUTH_NONE); + default: + return(WMI_AUTH_NONE); + } +} + +/* function : eCsrEncryptionType_to_rsn_cipherset + * Description : Map CSR's encryption type into RSN cipher types used by firmware + * Args : + * Returns : + */ + +A_UINT32 eCsrEncryptionType_to_rsn_cipherset (eCsrEncryptionType encr) { + + switch (encr) { + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP104: + return (WMI_CIPHER_WEP); + case eCSR_ENCRYPT_TYPE_TKIP: + return (WMI_CIPHER_TKIP); + case eCSR_ENCRYPT_TYPE_AES: + return (WMI_CIPHER_AES_CCM); +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + return (WMI_CIPHER_WAPI); +#endif /* FEATURE_WLAN_WAPI */ + case eCSR_ENCRYPT_TYPE_ANY: + return (WMI_CIPHER_ANY); + case eCSR_ENCRYPT_TYPE_NONE: + default: + return (WMI_CIPHER_NONE); + } +} + +/* function : wma_roam_scan_fill_ap_profile + * Description : Fill ap_profile structure from configured parameters + * Args : + * Returns : + */ +v_VOID_t wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle, tpAniSirGlobal pMac, + tSirRoamOffloadScanReq *roam_req, wmi_ap_profile *ap_profile_p) +{ + vos_mem_zero(ap_profile_p, sizeof(wmi_ap_profile)); + if (roam_req == NULL) { + ap_profile_p->ssid.ssid_len = 0; + ap_profile_p->ssid.ssid[0] = 0; + ap_profile_p->rsn_authmode = WMI_AUTH_NONE; + ap_profile_p->rsn_ucastcipherset = WMI_CIPHER_NONE; + ap_profile_p->rsn_mcastcipherset = WMI_CIPHER_NONE; + ap_profile_p->rsn_mcastmgmtcipherset = WMI_CIPHER_NONE; + ap_profile_p->rssi_threshold = WMA_ROAM_RSSI_DIFF_DEFAULT; + } else { + ap_profile_p->ssid.ssid_len = roam_req->ConnectedNetwork.ssId.length; + vos_mem_copy(ap_profile_p->ssid.ssid, roam_req->ConnectedNetwork.ssId.ssId, + ap_profile_p->ssid.ssid_len); + ap_profile_p->rsn_authmode = + eCsrAuthType_to_rsn_authmode(roam_req->ConnectedNetwork.authentication, + roam_req->ConnectedNetwork.encryption); + ap_profile_p->rsn_ucastcipherset = + eCsrEncryptionType_to_rsn_cipherset(roam_req->ConnectedNetwork.encryption); + ap_profile_p->rsn_mcastcipherset = + eCsrEncryptionType_to_rsn_cipherset(roam_req->ConnectedNetwork.mcencryption); + ap_profile_p->rsn_mcastmgmtcipherset = ap_profile_p->rsn_mcastcipherset; + ap_profile_p->rssi_threshold = roam_req->RoamRssiDiff; +#ifdef WLAN_FEATURE_11W + if (roam_req->ConnectedNetwork.MFPEnabled) + ap_profile_p->flags |= WMI_AP_PROFILE_FLAG_PMF; +#endif + } +} + +/* function : wma_roam_scan_scan_params + * Description : Fill scan_params structure from configured parameters + * Args : roam_req pointer = NULL if this routine is called before connect + * : It will be non-NULL if called after assoc. + * Returns : + */ +v_VOID_t wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle, + tpAniSirGlobal pMac, + tSirRoamOffloadScanReq *roam_req, + wmi_start_scan_cmd_fixed_param *scan_params) +{ + tANI_U8 channels_per_burst = 0; + tANI_U32 val = 0; + + if (NULL == pMac) { + WMA_LOGE("%s: pMac is NULL", __func__); + return; + } + + vos_mem_zero(scan_params, sizeof(wmi_start_scan_cmd_fixed_param)); + scan_params->scan_ctrl_flags = WMI_SCAN_ADD_CCK_RATES | + WMI_SCAN_ADD_OFDM_RATES | + WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ; + if (roam_req != NULL) { + /* Parameters updated after association is complete */ + WMA_LOGI("%s: Input parameters: NeighborScanChannelMinTime" + " = %d, NeighborScanChannelMaxTime = %d", + __func__, + roam_req->NeighborScanChannelMinTime, + roam_req->NeighborScanChannelMaxTime); + WMA_LOGI("%s: Input parameters: NeighborScanTimerPeriod =" + " %d, HomeAwayTime = %d, nProbes = %d", + __func__, + roam_req->NeighborScanTimerPeriod, + roam_req->HomeAwayTime, + roam_req->nProbes); + + /* + * roam_req->NeighborScanChannelMaxTime = SCAN_CHANNEL_TIME + * roam_req->HomeAwayTime = SCAN_HOME_AWAY_TIME + * roam_req->NeighborScanTimerPeriod = SCAN_HOME_TIME + * + * scan_params->dwell_time_active = time station stays on channel + * and sends probes; + * scan_params->dwell_time_passive = time station stays on channel + * and listens probes; + * scan_params->burst_duration = time station goes off channel + * to scan; + */ + + if (wlan_cfgGetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, &val) != eSIR_SUCCESS) + { + /* + * Could not get max channel value from CFG. Log error. + */ + WMA_LOGE("could not retrieve passive max channel value"); + + /* use a default value of 110ms */ + val = WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT; + } + + scan_params->dwell_time_passive = val; + /* + * Here is the formula, + * T(HomeAway) = N * T(dwell) + (N+1) * T(cs) + * where N is number of channels scanned in single burst + */ + scan_params->dwell_time_active = roam_req->NeighborScanChannelMaxTime; + if (roam_req->HomeAwayTime < 2*WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME) { + /* clearly we can't follow home away time. + * Make it a split scan. + */ + scan_params->burst_duration = 0; + } else { + channels_per_burst = + (roam_req->HomeAwayTime - WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME) + / ( scan_params->dwell_time_active + WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME); + + if (channels_per_burst < 1) { + // dwell time and home away time conflicts + // we will override dwell time + scan_params->dwell_time_active = + roam_req->HomeAwayTime - 2*WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME; + scan_params->burst_duration = scan_params->dwell_time_active; + } else { + scan_params->burst_duration = + channels_per_burst * scan_params->dwell_time_active; + } + } + if (roam_req->allowDFSChannelRoam == SIR_ROAMING_DFS_CHANNEL_ENABLED_NORMAL && + roam_req->HomeAwayTime > 0 && + roam_req->ChannelCacheType != CHANNEL_LIST_STATIC) { + /* Roaming on DFS channels is supported and it is not app channel list. + * It is ok to override homeAwayTime to accomodate DFS dwell time in burst + * duration. + */ + scan_params->burst_duration = MAX(scan_params->burst_duration, + scan_params->dwell_time_passive); + } + scan_params->min_rest_time = roam_req->NeighborScanTimerPeriod; + scan_params->max_rest_time = roam_req->NeighborScanTimerPeriod; + scan_params->repeat_probe_time = (roam_req->nProbes > 0) ? + VOS_MAX(scan_params->dwell_time_active / roam_req->nProbes, 1) : 0; + scan_params->probe_spacing_time = 0; + scan_params->probe_delay = 0; + scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; /* 30 seconds for full scan cycle */ + scan_params->idle_time = scan_params->min_rest_time; + scan_params->n_probes = roam_req->nProbes; + if (roam_req->allowDFSChannelRoam == SIR_ROAMING_DFS_CHANNEL_DISABLED) { + scan_params->scan_ctrl_flags |= WMI_SCAN_BYPASS_DFS_CHN; + } else { + /* Roaming scan on DFS channel is allowed. + * No need to change any flags for default allowDFSChannelRoam = 1. + * Special case where static channel list is given by application + * that contains DFS channels. Assume that the application + * has knowledge of matching APs being active and that + * probe request transmission is permitted on those channel. + * Force active scans on those channels. + */ + + if (roam_req->allowDFSChannelRoam == + SIR_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE && + roam_req->ChannelCacheType == CHANNEL_LIST_STATIC && + roam_req->ConnectedNetwork.ChannelCount > 0) { + scan_params->scan_ctrl_flags |= + WMI_SCAN_FLAG_FORCE_ACTIVE_ON_DFS; + } + } + } else { + /* roam_req = NULL during initial or pre-assoc invocation */ + scan_params->dwell_time_active = WMA_ROAM_DWELL_TIME_ACTIVE_DEFAULT; + scan_params->dwell_time_passive = WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT; + scan_params->min_rest_time = WMA_ROAM_MIN_REST_TIME_DEFAULT; + scan_params->max_rest_time = WMA_ROAM_MAX_REST_TIME_DEFAULT; + scan_params->repeat_probe_time = 0; + scan_params->probe_spacing_time = 0; + scan_params->probe_delay = 0; + scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; + scan_params->idle_time = scan_params->min_rest_time; + scan_params->burst_duration = 0; + scan_params->n_probes = 0; + } + + WMA_LOGI("%s: Rome roam scan parameters:" + " dwell_time_active = %d, dwell_time_passive = %d", + __func__, + scan_params->dwell_time_active, + scan_params->dwell_time_passive); + WMA_LOGI("%s: min_rest_time = %d, max_rest_time = %d," + " repeat_probe_time = %d n_probes = %d", + __func__, + scan_params->min_rest_time, + scan_params->max_rest_time, + scan_params->repeat_probe_time, + scan_params->n_probes); + WMA_LOGI("%s: max_scan_time = %d, idle_time = %d," + " burst_duration = %d, scan_ctrl_flags = 0x%x", + __func__, + scan_params->max_scan_time, + scan_params->idle_time, + scan_params->burst_duration, + scan_params->scan_ctrl_flags); +} + +/* function : wma_roam_scan_offload_ap_profile + * Description : Send WMI_ROAM_AP_PROFILE TLV to firmware + * Args : AP profile parameters are passed in as the structure used in TLV + * Returns : + */ +VOS_STATUS wma_roam_scan_offload_ap_profile(tp_wma_handle wma_handle, + wmi_ap_profile *ap_profile_p, + u_int32_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + u_int8_t *buf_ptr; + wmi_roam_ap_profile_fixed_param *roam_ap_profile_fp; + + len = sizeof(wmi_roam_ap_profile_fixed_param) + + sizeof(wmi_ap_profile); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + roam_ap_profile_fp = (wmi_roam_ap_profile_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&roam_ap_profile_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_roam_ap_profile_fixed_param)); + /* fill in threshold values */ + roam_ap_profile_fp->vdev_id = vdev_id; + roam_ap_profile_fp->id = 0; + buf_ptr += sizeof(wmi_roam_ap_profile_fixed_param); + + vos_mem_copy(buf_ptr, ap_profile_p, sizeof(wmi_ap_profile)); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_STRUC_wmi_ap_profile, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ap_profile)); + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_AP_PROFILE); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_AP_PROFILE returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("WMA --> WMI_ROAM_AP_PROFILE and other parameters"); + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return vos_status; +} + +VOS_STATUS wma_roam_scan_filter(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req) +{ + wmi_buf_t buf = NULL; + int status = 0, i; + uint32_t len, num_bssid_black_list = 0, num_ssid_white_list = 0, + num_bssid_preferred_list = 0; + uint32_t op_bitmap = 0; + uint8_t *buf_ptr; + wmi_roam_filter_fixed_param *roam_filter; + uint8_t *bssid_src_ptr = NULL; + wmi_mac_addr *bssid_dst_ptr = NULL; + wmi_ssid *ssid_ptr = NULL; + uint32_t *bssid_preferred_factor_ptr = NULL; + struct roam_ext_params *roam_params; + + roam_params = &roam_req->roam_params; + len = sizeof(wmi_roam_filter_fixed_param); + len += WMI_TLV_HDR_SIZE; + if (roam_req->Command != ROAM_SCAN_OFFLOAD_STOP) { + switch (roam_req->reason) { + case REASON_ROAM_SET_BLACKLIST_BSSID: + op_bitmap |= 0x1; + num_bssid_black_list = roam_params->num_bssid_avoid_list; + len += num_bssid_black_list * sizeof(wmi_mac_addr); + len += WMI_TLV_HDR_SIZE; + break; + case REASON_ROAM_SET_SSID_ALLOWED: + op_bitmap |= 0x2; + num_ssid_white_list = roam_params->num_ssid_allowed_list; + len += num_ssid_white_list * sizeof(wmi_ssid); + len += WMI_TLV_HDR_SIZE; + break; + case REASON_ROAM_SET_FAVORED_BSSID: + op_bitmap |= 0x4; + num_bssid_preferred_list = roam_params->num_bssid_favored; + len += num_bssid_preferred_list * sizeof(wmi_mac_addr); + len += WMI_TLV_HDR_SIZE; + len += num_bssid_preferred_list * sizeof(A_UINT32); + break; + default: + WMA_LOGD("%s : Roam Filter need not be sent", __func__); + return VOS_STATUS_SUCCESS; + break; + } + } else { + /* In case of STOP command, reset all the variables + * except for blacklist BSSID which should be retained + * across connections.*/ + op_bitmap = 0x2 | 0x4; + num_ssid_white_list = roam_params->num_ssid_allowed_list; + len += num_ssid_white_list * sizeof(wmi_ssid); + num_bssid_preferred_list = roam_params->num_bssid_favored; + len += num_bssid_preferred_list * sizeof(wmi_mac_addr); + len += num_bssid_preferred_list * sizeof(A_UINT32); + len += (2 * WMI_TLV_HDR_SIZE); + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + roam_filter = (wmi_roam_filter_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&roam_filter->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_filter_fixed_param)); + /* fill in fixed values */ + roam_filter->vdev_id = roam_req->sessionId; + roam_filter->flags = 0; + roam_filter->op_bitmap = op_bitmap; + roam_filter->num_bssid_black_list = num_bssid_black_list; + roam_filter->num_ssid_white_list = num_ssid_white_list; + roam_filter->num_bssid_preferred_list = num_bssid_preferred_list; + buf_ptr += sizeof(wmi_roam_filter_fixed_param); + + WMITLV_SET_HDR((buf_ptr), + WMITLV_TAG_ARRAY_FIXED_STRUC, + (num_bssid_black_list * sizeof(wmi_mac_addr))); + bssid_src_ptr = (uint8_t *)&roam_params->bssid_avoid_list; + bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); + for(i=0; issid, &roam_params->ssid_allowed_list[i].ssId, + roam_params->ssid_allowed_list[i].length); + ssid_ptr->ssid_len = roam_params->ssid_allowed_list[i].length; + WMA_LOGD("%s: Passing SSID of length=%d", __func__,ssid_ptr->ssid_len); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, + (uint8_t *)ssid_ptr->ssid, + ssid_ptr->ssid_len); + ssid_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid_white_list * sizeof(wmi_ssid)); + WMITLV_SET_HDR((buf_ptr), + WMITLV_TAG_ARRAY_FIXED_STRUC, + (num_bssid_preferred_list * sizeof(wmi_mac_addr))); + bssid_src_ptr = (uint8_t *)&roam_params->bssid_favored; + bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); + for(i=0; ibssid_favored_factor[i]; + bssid_preferred_factor_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + (num_bssid_preferred_list * sizeof(uint32_t)); + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_FILTER_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_FILTER_CMDID returned Error %d", + status); + goto error; + } + return VOS_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; +} + +VOS_STATUS wma_roam_scan_offload_command(tp_wma_handle wma_handle, + u_int32_t command, + u_int32_t vdev_id) +{ + VOS_STATUS vos_status; + wmi_roam_scan_cmd_fixed_param *cmd_fp; + wmi_buf_t buf = NULL; + int status = 0; + int len; + u_int8_t *buf_ptr; + + len = sizeof(wmi_roam_scan_cmd_fixed_param); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + + cmd_fp = (wmi_roam_scan_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_cmd_fixed_param)); + cmd_fp->vdev_id = vdev_id; + cmd_fp->command_arg = command; + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_ROAM_SCAN_CMD); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_ROAM_SCAN_CMD returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CMD", __func__); + return VOS_STATUS_SUCCESS; + +error: + wmi_buf_free(buf); + + return vos_status; +} + +/* function : wma_process_roam_scan_req + * Description : Main routine to handle ROAM commands coming from CSR module. + * Args : + * Returns : + */ +VOS_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_start_scan_cmd_fixed_param scan_params; + wmi_ap_profile ap_profile; + tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + u_int32_t mode = 0; + struct wma_txrx_node *intr = NULL; + + WMA_LOGI("%s: command 0x%x, reason %d", __func__, roam_req->Command, + roam_req->reason); + + if (NULL == pMac) + { + WMA_LOGE("%s: pMac is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (!wma_handle->roam_offload_enabled) { + /* roam scan offload is not enabled in firmware. + * Cannot initialize it in the middle of connection. + */ + vos_mem_free(roam_req); + return VOS_STATUS_E_PERM; + } + switch (roam_req->Command) { + case ROAM_SCAN_OFFLOAD_START: + intr = &wma_handle->interfaces[roam_req->sessionId]; + intr->delay_before_vdev_stop = roam_req->delay_before_vdev_stop; + /* + * Scan/Roam threshold parameters are translated from fields of tSirRoamOffloadScanReq + * to WMITLV values sent to Rome firmware. + * some of these parameters are configurable in qcom_cfg.ini file. + */ + + /* First parameter is positive rssi value to trigger rssi based scan. + * Opportunistic scan is started at 30 dB higher that trigger rssi. + */ + wma_handle->suitable_ap_hb_failure = FALSE; + + vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, + roam_req); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + vos_status = wma_roam_scan_bmiss_cnt(wma_handle, + roam_req->RoamBmissFirstBcnt, roam_req->RoamBmissFinalBcnt, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + /* Opportunistic scan runs on a timer, value set by EmptyRefreshScanPeriod. + * Age out the entries after 3 such cycles. + */ + if (roam_req->EmptyRefreshScanPeriod > 0) { + vos_status = wma_roam_scan_offload_scan_period(wma_handle, + roam_req->EmptyRefreshScanPeriod, + roam_req->EmptyRefreshScanPeriod * 3, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + mode = WMI_ROAM_SCAN_MODE_PERIODIC; + /* Don't use rssi triggered roam scans if external app + * is in control of channel list. + */ + if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC) { + mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE; + } + } else { + mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE; + } + + /* Start new rssi triggered scan only if it changes by RoamRssiDiff value. + * Beacon weight of 14 means average rssi is taken over 14 previous samples + + * 2 times the current beacon's rssi. + */ + vos_status = wma_roam_scan_offload_rssi_change(wma_handle, + roam_req->sessionId, + roam_req->RoamRescanRssiDiff, + roam_req->RoamBeaconRssiWeight, + roam_req->hi_rssi_scan_delay); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req, &ap_profile); + + vos_status = wma_roam_scan_offload_ap_profile(wma_handle, + &ap_profile, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + vos_status = wma_roam_scan_offload_chan_list(wma_handle, + roam_req->ConnectedNetwork.ChannelCount, + &roam_req->ConnectedNetwork.ChannelCache[0], + roam_req->ChannelCacheType, + roam_req->sessionId); + if ((vos_status != VOS_STATUS_SUCCESS) && + (vos_status != VOS_STATUS_E_EMPTY)) { + break; + } + + + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, &scan_params); + vos_status = wma_roam_scan_offload_mode(wma_handle, + &scan_params, + roam_req, + mode, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + vos_status = wma_roam_scan_filter(wma_handle, roam_req); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Sending start for roam scan filter failed"); + break; + } + break; + + case ROAM_SCAN_OFFLOAD_STOP: + wma_handle->suitable_ap_hb_failure = FALSE; + if (wma_handle->roam_offload_enabled) { + + wma_roam_scan_fill_scan_params(wma_handle, pMac, + NULL, &scan_params); + vos_status = wma_roam_scan_offload_mode(wma_handle, + &scan_params, + NULL, + WMI_ROAM_SCAN_MODE_NONE, + roam_req->sessionId); + } + /* + * If the STOP command is due to a disconnect, then + * send the filter command to clear all the filter + * entries. If it is roaming scenario, then do not + * send the cleared entries. + */ + if (!roam_req->middle_of_roaming) { + vos_status = wma_roam_scan_filter(wma_handle, roam_req); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Sending clear for roam scan filter failed"); + break; + } + } + + if (roam_req->reason == REASON_OS_REQUESTED_ROAMING_NOW) { + vos_msg_t vosMsg; + tSirRoamOffloadScanRsp *scan_offload_rsp; + scan_offload_rsp = vos_mem_malloc(sizeof(*scan_offload_rsp)); + if (!scan_offload_rsp) { + WMA_LOGE("%s: Alloc failed for scan_offload_rsp", __func__); + vos_mem_free(roam_req); + return VOS_STATUS_E_NOMEM; + } + vosMsg.type = eWNI_SME_ROAM_SCAN_OFFLOAD_RSP; + scan_offload_rsp->sessionId = roam_req->sessionId; + scan_offload_rsp->reason = roam_req->reason; + vosMsg.bodyptr = scan_offload_rsp; + /* + * Since REASSOC request is processed in Roam_Scan_Offload_Rsp + * post a dummy rsp msg back to SME with proper reason code. + */ + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, + (vos_msg_t*)&vosMsg)) + { + vos_mem_free(scan_offload_rsp); + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "%s: Failed to post Scan Offload Rsp to UMAC", + __func__); + } + } + break; + + case ROAM_SCAN_OFFLOAD_ABORT_SCAN: + /* If roam scan is running, stop that cycle. + * It will continue automatically on next trigger. + */ + vos_status = wma_roam_scan_offload_command(wma_handle, + WMI_ROAM_SCAN_STOP_CMD, + roam_req->sessionId); + break; + + case ROAM_SCAN_OFFLOAD_RESTART: + /* Rome offload engine does not stop after any scan. + * If this command is sent because all preauth attempts failed + * and WMI_ROAM_REASON_SUITABLE_AP event was received earlier, + * now it is time to call it heartbeat failure. + */ + if ((roam_req->reason == REASON_PREAUTH_FAILED_FOR_ALL) + && wma_handle->suitable_ap_hb_failure) { + WMA_LOGE("%s: Sending heartbeat failure after preauth failures", + __func__); + wma_beacon_miss_handler(wma_handle, roam_req->sessionId, + wma_handle->suitable_ap_hb_failure_rssi); + wma_handle->suitable_ap_hb_failure = FALSE; + } + break; + + case ROAM_SCAN_OFFLOAD_UPDATE_CFG: + wma_handle->suitable_ap_hb_failure = FALSE; + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, &scan_params); + vos_status = wma_roam_scan_offload_mode(wma_handle, + &scan_params, + roam_req, + WMI_ROAM_SCAN_MODE_NONE, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + if (roam_req->RoamScanOffloadEnabled == FALSE) { + break; + } + + vos_status = wma_roam_scan_bmiss_cnt(wma_handle, + roam_req->RoamBmissFirstBcnt, roam_req->RoamBmissFinalBcnt, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + vos_status = wma_roam_scan_filter(wma_handle, roam_req); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Sending update for roam scan filter failed"); + break; + } + + /* + * Runtime (after association) changes to rssi thresholds and other parameters. + */ + vos_status = wma_roam_scan_offload_chan_list(wma_handle, + roam_req->ConnectedNetwork.ChannelCount, + &roam_req->ConnectedNetwork.ChannelCache[0], + roam_req->ChannelCacheType, + roam_req->sessionId); + /* + * Even though the channel list is empty, we can + * still go ahead and start Roaming. + */ + if ((vos_status != VOS_STATUS_SUCCESS) && + (vos_status != VOS_STATUS_E_EMPTY)) { + break; + } + + vos_status = wma_roam_scan_offload_rssi_thresh(wma_handle, + roam_req); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + if (roam_req->EmptyRefreshScanPeriod > 0) { + vos_status = wma_roam_scan_offload_scan_period(wma_handle, + roam_req->EmptyRefreshScanPeriod, + roam_req->EmptyRefreshScanPeriod * 3, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + mode = WMI_ROAM_SCAN_MODE_PERIODIC; + /* Don't use rssi triggered roam scans if external app + * is in control of channel list. + */ + if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC) { + mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE; + } + } else { + mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE; + } + + vos_status = wma_roam_scan_offload_rssi_change(wma_handle, + roam_req->sessionId, + roam_req->RoamRescanRssiDiff, + roam_req->RoamBeaconRssiWeight, + roam_req->hi_rssi_scan_delay); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req, &ap_profile); + vos_status = wma_roam_scan_offload_ap_profile(wma_handle, + &ap_profile, + roam_req->sessionId); + if (vos_status != VOS_STATUS_SUCCESS) { + break; + } + + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, &scan_params); + vos_status = wma_roam_scan_offload_mode( + wma_handle, + &scan_params, + roam_req, + mode, + roam_req->sessionId); + + break; + + default: + break; + } + vos_mem_free(roam_req); + return vos_status; +} + +#ifdef FEATURE_WLAN_LPHB +/* function : wma_lphb_conf_hbenable + * Description : handles the enable command of LPHB configuration requests + * Args : wma_handle - WMA handle + * lphb_conf_req - configuration info + * by_user - whether this call is from user or cached resent + * Returns : + */ +VOS_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req, + v_BOOL_t by_user) + +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int status = 0; + tSirLPHBEnableStruct *ts_lphb_enable; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp; + int len = sizeof(wmi_hb_set_enable_cmd_fixed_param); + int i; + + if (lphb_conf_req == NULL) + { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + ts_lphb_enable = &(lphb_conf_req->params.lphbEnableReq); + WMA_LOGI("%s: WMA --> WMI_HB_SET_ENABLE enable=%d, item=%d, session=%d", + __func__, + ts_lphb_enable->enable, + ts_lphb_enable->item, + ts_lphb_enable->session); + + if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) { + WMA_LOGE("%s : LPHB configuration wrong item %d", + __func__, + ts_lphb_enable->item); + return VOS_STATUS_E_FAILURE; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&hb_enable_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_hb_set_enable_cmd_fixed_param)); + + /* fill in values */ + hb_enable_fp->vdev_id = ts_lphb_enable->session; + hb_enable_fp->enable= ts_lphb_enable->enable; + hb_enable_fp->item = ts_lphb_enable->item; + hb_enable_fp->session = ts_lphb_enable->session; + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_HB_SET_ENABLE_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_ENABLE returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + if (by_user) { + /* target already configured, now cache command status */ + if (ts_lphb_enable->enable) { + i = ts_lphb_enable->item-1; + wma_handle->wow.lphb_cache[i].cmd + = LPHB_SET_EN_PARAMS_INDID; + wma_handle->wow.lphb_cache[i].params.lphbEnableReq.enable + = ts_lphb_enable->enable; + wma_handle->wow.lphb_cache[i].params.lphbEnableReq.item + = ts_lphb_enable->item; + wma_handle->wow.lphb_cache[i].params.lphbEnableReq.session + = ts_lphb_enable->session; + + WMA_LOGI("%s: cached LPHB status in WMA context for item %d", + __func__, i); + } else { + vos_mem_zero((void *)&wma_handle->wow.lphb_cache, + sizeof(wma_handle->wow.lphb_cache)); + WMA_LOGI("%s: cleared all cached LPHB status in WMA context", + __func__); + } + } + + return VOS_STATUS_SUCCESS; +error: + return vos_status; +} + +/* function : wma_lphb_conf_tcp_params + * Description : handles the tcp params command of LPHB configuration requests + * Args : + * Returns : + */ +VOS_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int status = 0; + tSirLPHBTcpParamStruct *ts_lphb_tcp_param; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp; + int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param); + + if (lphb_conf_req == NULL) + { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + ts_lphb_tcp_param = &(lphb_conf_req->params.lphbTcpParamReq); + WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, dev_ip=%08x, src_port=%d, " + "dst_port=%d, timeout=%d, session=%d, gateway_mac=%02x:%02x:%02x:%02x:%02x:%02x, " + "timePeriodSec=%d, tcpSn=%d", + __func__, + ts_lphb_tcp_param->srv_ip, ts_lphb_tcp_param->dev_ip, + ts_lphb_tcp_param->src_port, ts_lphb_tcp_param->dst_port, + ts_lphb_tcp_param->timeout, ts_lphb_tcp_param->session, + ts_lphb_tcp_param->gateway_mac[0], + ts_lphb_tcp_param->gateway_mac[1], + ts_lphb_tcp_param->gateway_mac[2], + ts_lphb_tcp_param->gateway_mac[3], + ts_lphb_tcp_param->gateway_mac[4], + ts_lphb_tcp_param->gateway_mac[5], + ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_hb_set_tcp_params_cmd_fixed_param)); + + /* fill in values */ + hb_tcp_params_fp->vdev_id = ts_lphb_tcp_param->session; + hb_tcp_params_fp->srv_ip = ts_lphb_tcp_param->srv_ip; + hb_tcp_params_fp->dev_ip = ts_lphb_tcp_param->dev_ip; + hb_tcp_params_fp->seq = ts_lphb_tcp_param->tcpSn; + hb_tcp_params_fp->src_port = ts_lphb_tcp_param->src_port; + hb_tcp_params_fp->dst_port = ts_lphb_tcp_param->dst_port; + hb_tcp_params_fp->interval = ts_lphb_tcp_param->timePeriodSec; + hb_tcp_params_fp->timeout = ts_lphb_tcp_param->timeout; + hb_tcp_params_fp->session = ts_lphb_tcp_param->session; + WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac, &hb_tcp_params_fp->gateway_mac); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_HB_SET_TCP_PARAMS_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + return VOS_STATUS_SUCCESS; +error: + return vos_status; +} + +/* function : wma_lphb_conf_tcp_pkt_filter + * Description : handles the tcp packet filter command of LPHB configuration requests + * Args : + * Returns : + */ +VOS_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int status = 0; + tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp; + int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param); + + if (lphb_conf_req == NULL) + { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + ts_lphb_tcp_filter = &(lphb_conf_req->params.lphbTcpFilterReq); + WMA_LOGI("%s: WMA --> WMI_HB_SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, " + "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", + __func__, + ts_lphb_tcp_filter->length, + ts_lphb_tcp_filter->offset, + ts_lphb_tcp_filter->session, + ts_lphb_tcp_filter->filter[0], + ts_lphb_tcp_filter->filter[1], + ts_lphb_tcp_filter->filter[2], + ts_lphb_tcp_filter->filter[3], + ts_lphb_tcp_filter->filter[4], + ts_lphb_tcp_filter->filter[5]); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + hb_tcp_filter_fp = (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_hb_set_tcp_pkt_filter_cmd_fixed_param)); + + /* fill in values */ + hb_tcp_filter_fp->vdev_id = ts_lphb_tcp_filter->session; + hb_tcp_filter_fp->length = ts_lphb_tcp_filter->length; + hb_tcp_filter_fp->offset = ts_lphb_tcp_filter->offset; + hb_tcp_filter_fp->session = ts_lphb_tcp_filter->session; + memcpy((void *) &hb_tcp_filter_fp->filter, (void *) &ts_lphb_tcp_filter->filter, + WMI_WLAN_HB_MAX_FILTER_SIZE); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_HB_SET_TCP_PKT_FILTER_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + return VOS_STATUS_SUCCESS; +error: + return vos_status; +} + +/* function : wma_lphb_conf_udp_params + * Description : handles the udp params command of LPHB configuration requests + * Args : + * Returns : + */ +VOS_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int status = 0; + tSirLPHBUdpParamStruct *ts_lphb_udp_param; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp; + int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param); + + if (lphb_conf_req == NULL) + { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + ts_lphb_udp_param = &(lphb_conf_req->params.lphbUdpParamReq); + WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, " + "dst_port=%d, interval=%d, timeout=%d, session=%d, " + "gateway_mac=%2x:%2x:%2x:%2x:%2x:%2x", + __func__, + ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip, + ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port, + ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout, ts_lphb_udp_param->session, + ts_lphb_udp_param->gateway_mac[0], + ts_lphb_udp_param->gateway_mac[1], + ts_lphb_udp_param->gateway_mac[2], + ts_lphb_udp_param->gateway_mac[3], + ts_lphb_udp_param->gateway_mac[4], + ts_lphb_udp_param->gateway_mac[5]); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_hb_set_udp_params_cmd_fixed_param)); + + /* fill in values */ + hb_udp_params_fp->vdev_id = ts_lphb_udp_param->session; + hb_udp_params_fp->srv_ip = ts_lphb_udp_param->srv_ip; + hb_udp_params_fp->dev_ip = ts_lphb_udp_param->dev_ip; + hb_udp_params_fp->src_port = ts_lphb_udp_param->src_port; + hb_udp_params_fp->dst_port = ts_lphb_udp_param->dst_port; + hb_udp_params_fp->interval = ts_lphb_udp_param->interval; + hb_udp_params_fp->timeout = ts_lphb_udp_param->timeout; + hb_udp_params_fp->session = ts_lphb_udp_param->session; + WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac, &hb_udp_params_fp->gateway_mac); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_HB_SET_UDP_PARAMS_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + return VOS_STATUS_SUCCESS; +error: + return vos_status; +} + +/* function : wma_lphb_conf_udp_pkt_filter + * Description : handles the udp packet filter command of LPHB configuration requests + * Args : + * Returns : + */ +VOS_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int status = 0; + tSirLPHBUdpFilterStruct *ts_lphb_udp_filter; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp; + int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param); + + if (lphb_conf_req == NULL) + { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + ts_lphb_udp_filter = &(lphb_conf_req->params.lphbUdpFilterReq); + WMA_LOGI("%s: WMA --> WMI_HB_SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, " + "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", + __func__, + ts_lphb_udp_filter->length, + ts_lphb_udp_filter->offset, + ts_lphb_udp_filter->session, + ts_lphb_udp_filter->filter[0], + ts_lphb_udp_filter->filter[1], + ts_lphb_udp_filter->filter[2], + ts_lphb_udp_filter->filter[3], + ts_lphb_udp_filter->filter[4], + ts_lphb_udp_filter->filter[5]); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + hb_udp_filter_fp = (wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_hb_set_udp_pkt_filter_cmd_fixed_param)); + + /* fill in values */ + hb_udp_filter_fp->vdev_id = ts_lphb_udp_filter->session; + hb_udp_filter_fp->length = ts_lphb_udp_filter->length; + hb_udp_filter_fp->offset = ts_lphb_udp_filter->offset; + hb_udp_filter_fp->session = ts_lphb_udp_filter->session; + memcpy((void *) &hb_udp_filter_fp->filter, (void *) &ts_lphb_udp_filter->filter, + WMI_WLAN_HB_MAX_FILTER_SIZE); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_HB_SET_UDP_PKT_FILTER_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d", + status); + vos_status = VOS_STATUS_E_FAILURE; + goto error; + } + + return VOS_STATUS_SUCCESS; +error: + return vos_status; +} + +/* function : wma_process_lphb_conf_req + * Description : handles LPHB configuration requests + * Args : + * Returns : + */ +VOS_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + if (lphb_conf_req == NULL) + { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI("%s : LPHB configuration cmd id is %d", __func__, + lphb_conf_req->cmd); + switch (lphb_conf_req->cmd) { + case LPHB_SET_EN_PARAMS_INDID: + vos_status = wma_lphb_conf_hbenable(wma_handle, + lphb_conf_req, TRUE); + break; + + case LPHB_SET_TCP_PARAMS_INDID: + vos_status = wma_lphb_conf_tcp_params(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_TCP_PKT_FILTER_INDID: + vos_status = wma_lphb_conf_tcp_pkt_filter(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_UDP_PARAMS_INDID: + vos_status = wma_lphb_conf_udp_params(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_UDP_PKT_FILTER_INDID: + vos_status = wma_lphb_conf_udp_pkt_filter(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_NETWORK_INFO_INDID: + default: + break; + } + + vos_mem_free(lphb_conf_req); + return vos_status; +} +#endif + +VOS_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle, + tAniDHCPInd *ta_dhcp_ind) +{ + uint8_t vdev_id; + int status = 0; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_peer_set_param_cmd_fixed_param *peer_set_param_fp; + int len = sizeof(wmi_peer_set_param_cmd_fixed_param); + + if (!ta_dhcp_ind) + { + WMA_LOGE("%s : DHCP indication is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (!wma_find_vdev_by_addr(wma_handle, ta_dhcp_ind->adapterMacAddr, + &vdev_id)) + { + WMA_LOGE("%s: Failed to find vdev id for DHCP indication", + __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, " + "msgType=%s," + "device_mode=%d, macAddr=" MAC_ADDRESS_STR, + __func__, + ta_dhcp_ind->msgType==WDA_DHCP_START_IND? + "WDA_DHCP_START_IND":"WDA_DHCP_STOP_IND", + ta_dhcp_ind->device_mode, + MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr)); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + peer_set_param_fp = (wmi_peer_set_param_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&peer_set_param_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_peer_set_param_cmd_fixed_param)); + + /* fill in values */ + peer_set_param_fp->vdev_id = vdev_id; + peer_set_param_fp->param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED; + if (WDA_DHCP_START_IND == ta_dhcp_ind->msgType) + peer_set_param_fp->param_value = 1; + else + peer_set_param_fp->param_value = 0; + WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr, + &peer_set_param_fp->peer_macaddr); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_PEER_SET_PARAM_CMDID); + if (status != EOK) { + WMA_LOGE("%s: wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD" + " returned Error %d", + __func__, status); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +static WLAN_PHY_MODE wma_chan_to_mode(u8 chan, ePhyChanBondState chan_offset, + u8 vht_capable, u8 dot11_mode) +{ + WLAN_PHY_MODE phymode = MODE_UNKNOWN; + + /* 2.4 GHz band */ + if ((chan >= WMA_11G_CHANNEL_BEGIN) && (chan <= WMA_11G_CHANNEL_END)) { + switch (chan_offset) { + case PHY_SINGLE_CHANNEL_CENTERED: + /* In case of no channel bonding, use dot11_mode + * to set phy mode + */ + switch (dot11_mode) { + case WNI_CFG_DOT11_MODE_11A: + phymode = MODE_11A; + break; + case WNI_CFG_DOT11_MODE_11B: + phymode = MODE_11B; + break; + case WNI_CFG_DOT11_MODE_11G: + phymode = MODE_11G; + break; + case WNI_CFG_DOT11_MODE_11G_ONLY: + phymode = MODE_11GONLY; + break; + default: + /* Configure MODE_11NG_HT20 for + * self vdev(for vht too) + */ + phymode = MODE_11NG_HT20; + break; + } + break; + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + phymode = vht_capable ? MODE_11AC_VHT40_2G :MODE_11NG_HT40; + break; + + default: + break; + } + } + + /* 5 GHz band */ + if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) { + switch (chan_offset) { + case PHY_SINGLE_CHANNEL_CENTERED: + phymode = vht_capable ? MODE_11AC_VHT20 :MODE_11NA_HT20; + break; + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + phymode = vht_capable ? MODE_11AC_VHT40 :MODE_11NA_HT40; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + phymode = MODE_11AC_VHT80; + break; + + default: + break; + } + } + + /* 5.9 GHz Band */ + if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END)) { + /* Only Legacy Modulation Schemes are supported */ + phymode = MODE_11A; + } + + WMA_LOGD("%s: phymode %d channel %d offset %d vht_capable %d " + "dot11_mode %d", __func__, phymode, chan, + chan_offset, vht_capable, dot11_mode); + + return phymode; +} + +tANI_U8 wma_getCenterChannel(tANI_U8 chan, tANI_U8 chan_offset) +{ + tANI_U8 band_center_chan = 0; + + if ((chan_offset == PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED) || + (chan_offset == PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW)) + band_center_chan = chan + 2; + else if (chan_offset == PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW) + band_center_chan = chan + 6; + else if ((chan_offset == PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH) || + (chan_offset == PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED)) + band_center_chan = chan - 2; + else if (chan_offset == PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH) + band_center_chan = chan - 6; + + return band_center_chan; +} + +VOS_STATUS wma_vdev_start(tp_wma_handle wma, + struct wma_vdev_start_req *req, v_BOOL_t isRestart) +{ + wmi_vdev_start_request_cmd_fixed_param *cmd; + wmi_buf_t buf; + wmi_channel *chan; + int32_t len, ret; + WLAN_PHY_MODE chanmode; + u_int8_t *buf_ptr; + struct wma_txrx_node *intr = wma->interfaces; + tpAniSirGlobal pmac = NULL; + struct ath_dfs *dfs; + + pmac = (tpAniSirGlobal) + vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); + + if (pmac == NULL) { + WMA_LOGE("%s: vdev start failed as pmac is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + dfs = (struct ath_dfs *)wma->dfs_ic->ic_dfs; + + WMA_LOGD("%s: Enter isRestart=%d vdev=%d", __func__, isRestart,req->vdev_id); + len = sizeof(*cmd) + sizeof(wmi_channel) + + WMI_TLV_HDR_SIZE; + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_vdev_start_request_cmd_fixed_param *) buf_ptr; + chan = (wmi_channel *) (buf_ptr + sizeof(*cmd)); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_start_request_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_start_request_cmd_fixed_param)); + WMITLV_SET_HDR(&chan->tlv_header, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + cmd->vdev_id = req->vdev_id; + + /* Fill channel info */ + chan->mhz = vos_chan_to_freq(req->chan); + chanmode = wma_chan_to_mode(req->chan, req->chan_offset, + req->vht_capable, req->dot11_mode); + + intr[cmd->vdev_id].chanmode = chanmode; /* save channel mode */ + intr[cmd->vdev_id].ht_capable = req->ht_capable; + intr[cmd->vdev_id].vht_capable = req->vht_capable; + intr[cmd->vdev_id].config.gtx_info.gtxRTMask[0] = CFG_TGT_DEFAULT_GTX_HT_MASK; + intr[cmd->vdev_id].config.gtx_info.gtxRTMask[1] = CFG_TGT_DEFAULT_GTX_VHT_MASK; + intr[cmd->vdev_id].config.gtx_info.gtxUsrcfg = CFG_TGT_DEFAULT_GTX_USR_CFG; + intr[cmd->vdev_id].config.gtx_info.gtxPERThreshold = CFG_TGT_DEFAULT_GTX_PER_THRESHOLD; + intr[cmd->vdev_id].config.gtx_info.gtxPERMargin = CFG_TGT_DEFAULT_GTX_PER_MARGIN; + intr[cmd->vdev_id].config.gtx_info.gtxTPCstep = CFG_TGT_DEFAULT_GTX_TPC_STEP; + intr[cmd->vdev_id].config.gtx_info.gtxTPCMin = CFG_TGT_DEFAULT_GTX_TPC_MIN; + intr[cmd->vdev_id].config.gtx_info.gtxBWMask = CFG_TGT_DEFAULT_GTX_BW_MASK; + intr[cmd->vdev_id].mhz = chan->mhz; + + WMI_SET_CHANNEL_MODE(chan, chanmode); + chan->band_center_freq1 = chan->mhz; + + if (chanmode == MODE_11AC_VHT80) + chan->band_center_freq1 = vos_chan_to_freq(wma_getCenterChannel + (req->chan, req->chan_offset)); + + if ((chanmode == MODE_11NA_HT40) || (chanmode == MODE_11NG_HT40) || + (chanmode == MODE_11AC_VHT40) || + (chanmode == MODE_11AC_VHT40_2G)) { + if (req->chan_offset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + chan->band_center_freq1 += 10; + else + chan->band_center_freq1 -= 10; + } + chan->band_center_freq2 = 0; + + /* Set half or quarter rate WMI flags */ + if (req->is_half_rate) { + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_HALF_RATE); + } else if (req->is_quarter_rate) { + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_QUARTER_RATE); + } + + /* + * If the channel has DFS set, flip on radar reporting. + * + * It may be that this should only be done for IBSS/hostap operation + * as this flag may be interpreted (at some point in the future) + * by the firmware as "oh, and please do radar DETECTION." + * + * If that is ever the case we would insert the decision whether to + * enable the firmware flag here. + */ + + /* + * If the Channel is DFS, + * set the WMI_CHAN_FLAG_DFS flag + */ + if (req->is_dfs) { + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_DFS); + cmd->disable_hw_ack = VOS_TRUE; + + req->dfs_pri_multiplier = wma->dfs_pri_multiplier; + + /* + * Configure the current operating channel + * to DFS module only if the device operating + * mode is AP. + * Enable/Disable Phyerr filtering offload + * depending on dfs_phyerr_filter_offload + * flag status as set in ini for SAP mode. + * Currently, only AP supports DFS master + * mode operation on DFS channels, P2P-GO + * does not support operation on DFS Channels. + */ + if (wma_is_vdev_in_ap_mode(wma, cmd->vdev_id) == true) { + /* + * If DFS regulatory domain is invalid, + * then, DFS radar filters intialization + * will fail. So, do not configure the + * channel in to DFS modlue, do not + * indicate if phyerror filtering offload + * is enabled or not to the firmware, simply + * fail the VDEV start on the DFS channel + * early on, to protect the DFS module from + * processing phyerrors without being intialized. + */ + if (DFS_UNINIT_DOMAIN == wma->dfs_ic->current_dfs_regdomain) { + WMA_LOGE("%s[%d]:DFS Configured with Invalid regdomain" + " Failed to send VDEV START command", + __func__, __LINE__); + + adf_nbuf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + + adf_os_spin_lock_bh(&wma->dfs_ic->chan_lock); + if (isRestart) + wma->dfs_ic->disable_phy_err_processing = true; + /* provide the current channel to DFS */ + wma->dfs_ic->ic_curchan = + wma_dfs_configure_channel(wma->dfs_ic,chan,chanmode,req); + adf_os_spin_unlock_bh(&wma->dfs_ic->chan_lock); + + wma_unified_dfs_phyerr_filter_offload_enable(wma); + dfs->disable_dfs_ch_switch = + pmac->sap.SapDfsInfo.disable_dfs_ch_switch; + } + } + + cmd->beacon_interval = req->beacon_intval; + cmd->dtim_period = req->dtim_period; + /* FIXME: Find out min, max and regulatory power levels */ + WMI_SET_CHANNEL_REG_POWER(chan, req->max_txpow); + WMI_SET_CHANNEL_MAX_TX_POWER(chan, req->max_txpow); + + /* TODO: Handle regulatory class, max antenna */ + if (!isRestart) { + cmd->beacon_interval = req->beacon_intval; + cmd->dtim_period = req->dtim_period; + + /* Copy the SSID */ + if (req->ssid.length) { + if (req->ssid.length < sizeof(cmd->ssid.ssid)) + cmd->ssid.ssid_len = req->ssid.length; + else + cmd->ssid.ssid_len = sizeof(cmd->ssid.ssid); + vos_mem_copy(cmd->ssid.ssid, req->ssid.ssId, + cmd->ssid.ssid_len); + } + + if (req->hidden_ssid) + cmd->flags |= WMI_UNIFIED_VDEV_START_HIDDEN_SSID; + + if (req->pmf_enabled) + cmd->flags |= WMI_UNIFIED_VDEV_START_PMF_ENABLED; + } + + cmd->num_noa_descriptors = 0; + buf_ptr = (u_int8_t *)(((uintptr_t) cmd) + sizeof(*cmd) + + sizeof(wmi_channel)); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + cmd->num_noa_descriptors * + sizeof(wmi_p2p_noa_descriptor)); + WMA_LOGD("%s: vdev_id %d freq %d channel %d chanmode %d is_dfs %d " + "beacon interval %d dtim %d center_chan %d center_freq2 %d " + "reg_info_1: 0x%x reg_info_2: 0x%x, req->max_txpow: 0x%x", + __func__, req->vdev_id, chan->mhz, req->chan, chanmode, req->is_dfs, + req->beacon_intval, cmd->dtim_period, chan->band_center_freq1, + chan->band_center_freq2, chan->reg_info_1, chan->reg_info_2, + req->max_txpow); + + /* Store vdev params in SAP mode which can be used in vdev restart */ + if (intr[req->vdev_id].type == WMI_VDEV_TYPE_AP && + intr[req->vdev_id].sub_type == 0) { + intr[req->vdev_id].vdev_restart_params.vdev_id = req->vdev_id; + intr[req->vdev_id].vdev_restart_params.ssid.ssid_len = cmd->ssid.ssid_len; + vos_mem_copy(intr[req->vdev_id].vdev_restart_params.ssid.ssid, cmd->ssid.ssid, + cmd->ssid.ssid_len); + intr[req->vdev_id].vdev_restart_params.flags = cmd->flags; + intr[req->vdev_id].vdev_restart_params.requestor_id = cmd->requestor_id; + intr[req->vdev_id].vdev_restart_params.disable_hw_ack = cmd->disable_hw_ack; + intr[req->vdev_id].vdev_restart_params.chan.mhz = chan->mhz; + intr[req->vdev_id].vdev_restart_params.chan.band_center_freq1 = chan->band_center_freq1; + intr[req->vdev_id].vdev_restart_params.chan.band_center_freq2 = chan->band_center_freq1; + intr[req->vdev_id].vdev_restart_params.chan.info = chan->info; + intr[req->vdev_id].vdev_restart_params.chan.reg_info_1 = chan->reg_info_1; + intr[req->vdev_id].vdev_restart_params.chan.reg_info_2 = chan->reg_info_2; + } + + if (isRestart) { + /* + * Marking the VDEV UP STATUS to FALSE + * since, VDEV RESTART will do a VDEV DOWN + * in the firmware. + */ + intr[cmd->vdev_id].vdev_up = FALSE; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_RESTART_REQUEST_CMDID); + + } else { + WMA_LOGD("%s, vdev_id: %d, unpausing tx_ll_queue at VDEV_START", + __func__, cmd->vdev_id); + wdi_in_vdev_unpause(wma->interfaces[cmd->vdev_id].handle, + 0xffffffff); + wma->interfaces[cmd->vdev_id].pause_bitmap = 0; + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_START_REQUEST_CMDID); + } + + if (ret < 0) { + WMA_LOGP("%s: Failed to send vdev start command", __func__); + adf_nbuf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +void wma_vdev_resp_timer(void *data) +{ + tp_wma_handle wma; + struct wma_target_req *tgt_req = (struct wma_target_req *)data; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + u_int8_t peer_id; + struct wma_target_req *msg; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tpAniSirGlobal mac_ctx = NULL; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + wma = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, vos_context); + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + vos_timer_stop(&tgt_req->event_timeout); + goto free_tgt_req; + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + mac_ctx = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + if (NULL == mac_ctx) { + WMA_LOGE("%s: Failed to get mac_ctx", __func__); + vos_timer_stop(&tgt_req->event_timeout); + goto free_tgt_req; + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + WMA_LOGA("%s: request %d is timed out for vdev_id - %d", __func__, + tgt_req->msg_type, tgt_req->vdev_id); + msg = wma_find_vdev_req(wma, tgt_req->vdev_id, tgt_req->type); + + if (!msg) { + WMA_LOGE("%s: Failed to lookup request message - %d", + __func__, tgt_req->msg_type); + return; + } + + if (tgt_req->msg_type == WDA_CHNL_SWITCH_REQ) { + tpSwitchChannelParams params = + (tpSwitchChannelParams)tgt_req->user_data; + params->status = VOS_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WDA_SWITCH_CHANNEL_REQ timedout", __func__); + wma_send_msg(wma, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); + wma->roam_preauth_chan_context = NULL; + adf_os_spin_lock_bh(&wma->roam_preauth_lock); + wma->roam_preauth_scan_id = -1; + adf_os_spin_unlock_bh(&wma->roam_preauth_lock); + } else if (tgt_req->msg_type == WDA_DELETE_BSS_REQ) { + tpDeleteBssParams params = + (tpDeleteBssParams)tgt_req->user_data; + struct beacon_info *bcn; + struct wma_txrx_node *iface; + + if (tgt_req->vdev_id > wma->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %d", __func__, + tgt_req->vdev_id); + vos_timer_stop(&tgt_req->event_timeout); + goto free_tgt_req; + } + + iface = &wma->interfaces[tgt_req->vdev_id]; + if (iface->handle == NULL) { + WMA_LOGE("%s vdev id %d is already deleted", + __func__, tgt_req->vdev_id); + vos_timer_stop(&tgt_req->event_timeout); + goto free_tgt_req; + } + +#ifdef QCA_IBSS_SUPPORT + if (wma_is_vdev_in_ibss_mode(wma, tgt_req->vdev_id)) + wma_delete_all_ibss_peers(wma, tgt_req->vdev_id); + else +#endif + { + if (wma_is_vdev_in_ap_mode(wma, tgt_req->vdev_id)) + { + wma_delete_all_ap_remote_peers(wma, tgt_req->vdev_id); + } + peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, + &peer_id); + wma_remove_peer(wma, params->bssid, tgt_req->vdev_id, + peer, VOS_FALSE); + } + + if (wmi_unified_vdev_down_send(wma->wmi_handle, tgt_req->vdev_id) < 0) { + WMA_LOGE("Failed to send vdev down cmd: vdev %d", + tgt_req->vdev_id); + } else { + wma->interfaces[tgt_req->vdev_id].vdev_up = FALSE; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if (mac_ctx->sap.sap_channel_avoidance) + wma_find_mcc_ap(wma, tgt_req->vdev_id, false); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + } + ol_txrx_vdev_flush(iface->handle); + WMA_LOGD("%s, vdev_id: %d, un-pausing tx_ll_queue for WDA_DELETE_BSS_REQ timeout", + __func__, tgt_req->vdev_id); + wdi_in_vdev_unpause(iface->handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + iface->pause_bitmap &= ~(1 << PAUSE_TYPE_HOST); + adf_os_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STOPPED); + WMA_LOGD("%s: (type %d subtype %d) BSS is stopped", + __func__, iface->type, iface->sub_type); + + bcn = wma->interfaces[tgt_req->vdev_id].beacon; + + if (bcn) { + WMA_LOGD("%s: Freeing beacon struct %p, " + "template memory %p", __func__, + bcn, bcn->buf); + if (bcn->dma_mapped) + adf_nbuf_unmap_single(pdev->osdev, bcn->buf, + ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(bcn->buf); + vos_mem_free(bcn); + wma->interfaces[tgt_req->vdev_id].beacon = NULL; + } + +#ifdef QCA_IBSS_SUPPORT + /* recreate ibss vdev and bss peer for scan purpose */ + if (wma_is_vdev_in_ibss_mode(wma, tgt_req->vdev_id)) + wma_recreate_ibss_vdev_and_bss_peer(wma, tgt_req->vdev_id); +#endif + params->status = VOS_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WDA_DELETE_BSS_REQ timedout", __func__); + wma_send_msg(wma, WDA_DELETE_BSS_RSP, (void *)params, 0); + if (iface->del_staself_req) { + WMA_LOGA("scheduling defered deletion(vdev id %x)", + tgt_req->vdev_id); + wma_vdev_detach(wma, iface->del_staself_req, 1); + } + } else if (tgt_req->msg_type == WDA_DEL_STA_SELF_REQ) { + struct wma_txrx_node *iface = + (struct wma_txrx_node *)tgt_req->user_data; + tpDelStaSelfParams params = + (tpDelStaSelfParams)iface->del_staself_req; + + params->status = VOS_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WDA_DEL_STA_SELF_REQ timedout", __func__); + wma_send_msg(wma, WDA_DEL_STA_SELF_RSP, + (void *)iface->del_staself_req, 0); + if(iface->addBssStaContext) + adf_os_mem_free(iface->addBssStaContext); +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) + adf_os_mem_free(iface->staKeyParams); +#endif + vos_mem_zero(iface, sizeof(*iface)); + } else if (tgt_req->msg_type == WDA_ADD_BSS_REQ) { + tpAddBssParams params = (tpAddBssParams)tgt_req->user_data; + tDeleteBssParams *del_bss_params = + vos_mem_malloc(sizeof(tDeleteBssParams)); + if (NULL == del_bss_params) { + WMA_LOGE("Failed to allocate memory for del_bss_params"); + peer = ol_txrx_find_peer_by_addr(pdev, params->bssId, + &peer_id); + goto error0; + } + + del_bss_params->status = params->status = + eHAL_STATUS_FW_MSG_TIMEDOUT; + del_bss_params->sessionId = params->sessionId; + del_bss_params->bssIdx = params->bssIdx; + vos_mem_copy(del_bss_params->bssid, params->bssId, + sizeof(tSirMacAddr)); + + WMA_LOGA("%s: WDA_ADD_BSS_REQ timedout", __func__); + peer = ol_txrx_find_peer_by_addr(pdev, params->bssId, &peer_id); + if (!peer) { + WMA_LOGP("%s: Failed to find peer %pM", __func__, params->bssId); + } + msg = wma_fill_vdev_req(wma, tgt_req->vdev_id, WDA_DELETE_BSS_REQ, + WMA_TARGET_REQ_TYPE_VDEV_STOP, + del_bss_params, + WMA_VDEV_STOP_REQUEST_TIMEOUT); + if (!msg) { + WMA_LOGP("%s: Failed to fill vdev request for vdev_id %d", + __func__, tgt_req->vdev_id); + goto error0; + } + + WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP (WDA_ADD_BSS_REQ timedout)", + __func__, tgt_req->vdev_id); + wdi_in_vdev_pause(wma->interfaces[tgt_req->vdev_id].handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + wma->interfaces[tgt_req->vdev_id].pause_bitmap |= + (1 << PAUSE_TYPE_HOST); + if (wmi_unified_vdev_stop_send(wma->wmi_handle, tgt_req->vdev_id)) { + WMA_LOGP("%s: %d Failed to send vdev stop", __func__, __LINE__); + wma_remove_vdev_req(wma, tgt_req->vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_STOP); + goto error0; + } + WMA_LOGI("%s: bssid %pM vdev_id %d", __func__, params->bssId, + tgt_req->vdev_id); + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)params, 0); + goto free_tgt_req; +error0: + if (peer) + wma_remove_peer(wma, params->bssId, + tgt_req->vdev_id, peer, + VOS_FALSE); + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)params, 0); + } else if (tgt_req->msg_type == WDA_OCB_SET_CONFIG_CMD) { + struct wma_txrx_node *iface; + + WMA_LOGE(FL("Failed to send OCB set config cmd")); + iface = &wma->interfaces[tgt_req->vdev_id]; + iface->vdev_up = FALSE; + wma_ocb_set_config_resp(wma, VOS_STATUS_E_TIMEOUT); + } +free_tgt_req: + vos_timer_destroy(&tgt_req->event_timeout); + adf_os_mem_free(tgt_req); +} + +struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, u_int8_t vdev_id, + u_int32_t msg_type, u_int8_t type, + void *params, u_int32_t timeout) +{ + struct wma_target_req *req; + + req = adf_os_mem_alloc(NULL, sizeof(*req)); + if (!req) { + WMA_LOGP("%s: Failed to allocate memory for msg %d vdev %d", + __func__, msg_type, vdev_id); + return NULL; + } + + WMA_LOGD("%s: vdev_id %d msg %d", __func__, vdev_id, msg_type); + req->vdev_id = vdev_id; + req->msg_type = msg_type; + req->type = type; + req->user_data = params; + vos_timer_init(&req->event_timeout, VOS_TIMER_TYPE_SW, + wma_vdev_resp_timer, req); + vos_timer_start(&req->event_timeout, timeout); + adf_os_spin_lock_bh(&wma->vdev_respq_lock); + list_add_tail(&req->node, &wma->vdev_resp_queue); + adf_os_spin_unlock_bh(&wma->vdev_respq_lock); + return req; +} + +void wma_remove_vdev_req(tp_wma_handle wma, u_int8_t vdev_id, + u_int8_t type) +{ + struct wma_target_req *req_msg; + + req_msg = wma_find_vdev_req(wma, vdev_id, type); + if (!req_msg) + return; + + vos_timer_stop(&req_msg->event_timeout); + vos_timer_destroy(&req_msg->event_timeout); + adf_os_mem_free(req_msg); +} + +/* function : wma_roam_preauth_chan_set + * Description: Send a single channel passive scan request + * to handle set_channel operation for preauth + * Args: + * Returns : + */ +VOS_STATUS wma_roam_preauth_chan_set(tp_wma_handle wma_handle, + tpSwitchChannelParams params, u_int8_t vdev_id) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tSirScanOffloadReq scan_req; + u_int8_t bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + WMA_LOGI("%s: channel %d", __func__, params->channelNumber); + + /* Check for prior operation in progress */ + if (wma_handle->roam_preauth_chan_context != NULL) { + vos_status = VOS_STATUS_E_FAILURE; + WMA_LOGE("%s: Rejected request. Previous operation in progress", __func__); + goto send_resp; + } + wma_handle->roam_preauth_chan_context = params; + + /* Prepare a dummy scan request and get the + * wmi_start_scan_cmd_fixed_param structure filled properly + */ + vos_mem_zero(&scan_req, sizeof(scan_req)); + vos_copy_macaddr((v_MACADDR_t *) &scan_req.bssId, (v_MACADDR_t *)bssid); + vos_copy_macaddr((v_MACADDR_t *)&scan_req.selfMacAddr, (v_MACADDR_t *)¶ms->selfStaMacAddr); + scan_req.channelList.numChannels = 1; + scan_req.channelList.channelNumber[0] = params->channelNumber; + scan_req.numSsid = 0; + scan_req.minChannelTime = WMA_ROAM_PREAUTH_SCAN_TIME; + scan_req.maxChannelTime = WMA_ROAM_PREAUTH_SCAN_TIME; + scan_req.scanType = eSIR_PASSIVE_SCAN; + scan_req.p2pScanType = P2P_SCAN_TYPE_LISTEN; + scan_req.sessionId = vdev_id; + wma_handle->roam_preauth_chanfreq = vos_chan_to_freq(params->channelNumber); + + /* set the state in advance before calling wma_start_scan and be ready + * to handle scan events from firmware. Otherwise print statments + * in wma_start_can create a race condition. + */ + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_REQUESTED; + vos_status = wma_start_scan(wma_handle, &scan_req, WDA_CHNL_SWITCH_REQ); + + if (vos_status == VOS_STATUS_SUCCESS) + return vos_status; + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_NONE; + /* Failed operation. Safely clear context */ + wma_handle->roam_preauth_chan_context = NULL; + +send_resp: + WMA_LOGI("%s: sending WDA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, vos_status); + params->chainMask = wma_handle->pdevconfig.txchainmask; + params->smpsMode = SMPS_MODE_DISABLED; + params->status = vos_status; + wma_send_msg(wma_handle, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); + return vos_status; +} + +VOS_STATUS wma_roam_preauth_chan_cancel(tp_wma_handle wma_handle, + tpSwitchChannelParams params, u_int8_t vdev_id) +{ + tAbortScanParams abort_scan_req; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + WMA_LOGI("%s: channel %d", __func__, params->channelNumber); + /* Check for prior operation in progress */ + if (wma_handle->roam_preauth_chan_context != NULL) { + vos_status = VOS_STATUS_E_FAILURE; + WMA_LOGE("%s: Rejected request. Previous operation in progress", __func__); + goto send_resp; + } + wma_handle->roam_preauth_chan_context = params; + + abort_scan_req.SessionId = vdev_id; + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_CANCEL_REQUESTED; + vos_status = wma_stop_scan(wma_handle, &abort_scan_req); + if (vos_status == VOS_STATUS_SUCCESS) + return vos_status; + /* Failed operation. Safely clear context */ + wma_handle->roam_preauth_chan_context = NULL; + +send_resp: + WMA_LOGI("%s: sending WDA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, vos_status); + params->chainMask = wma_handle->pdevconfig.txchainmask; + params->smpsMode = SMPS_MODE_DISABLED; + params->status = vos_status; + wma_send_msg(wma_handle, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); + return vos_status; +} + +static void wma_roam_preauth_scan_event_handler(tp_wma_handle wma_handle, + u_int8_t vdev_id, wmi_scan_event_fixed_param *wmi_event) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tSwitchChannelParams *params; + + WMA_LOGI("%s: preauth_scan_state %d, event 0x%x, reason 0x%x", + __func__, wma_handle->roam_preauth_scan_state, + wmi_event->event, wmi_event->reason); + switch(wma_handle->roam_preauth_scan_state) { + case WMA_ROAM_PREAUTH_CHAN_REQUESTED: + if (wmi_event->event & WMI_SCAN_EVENT_FOREIGN_CHANNEL) { + /* complete set_chan request */ + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_ON_CHAN; + vos_status = VOS_STATUS_SUCCESS; + } else if (wmi_event->event & WMI_SCAN_FINISH_EVENTS){ + /* Failed to get preauth channel or finished (unlikely) */ + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_NONE; + vos_status = VOS_STATUS_E_FAILURE; + } else + return; + break; + case WMA_ROAM_PREAUTH_CHAN_CANCEL_REQUESTED: + /* Completed or cancelled, complete set_chan cancel request */ + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_NONE; + break; + + case WMA_ROAM_PREAUTH_ON_CHAN: + if ((wmi_event->event & WMI_SCAN_EVENT_BSS_CHANNEL) || + (wmi_event->event & WMI_SCAN_FINISH_EVENTS)) + wma_handle->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_COMPLETED; + + /* There is no WDA request to complete. Next set channel request will + * look at this state and complete it. + */ + break; + default: + WMA_LOGE("%s: unhandled event 0x%x, reason 0x%x", + __func__, wmi_event->event, wmi_event->reason); + return; + } + + if((params = (tpSwitchChannelParams) wma_handle->roam_preauth_chan_context)) { + WMA_LOGI("%s: sending WDA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, vos_status); + params->chainMask = wma_handle->pdevconfig.txchainmask; + params->smpsMode = SMPS_MODE_DISABLED; + params->status = vos_status; + wma_send_msg(wma_handle, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); + wma_handle->roam_preauth_chan_context = NULL; + } + +} + +void wma_roam_preauth_ind(tp_wma_handle wma_handle, u_int8_t *buf) { + wmi_scan_event_fixed_param *wmi_event = NULL; + u_int8_t vdev_id; + + wmi_event = (wmi_scan_event_fixed_param *)buf; + if (wmi_event == NULL) { + WMA_LOGE("%s: Invalid param wmi_event is null", __func__); + return; + } + + vdev_id = wmi_event->vdev_id; + if (vdev_id >= wma_handle->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %d wmi_event %p", __func__, + vdev_id, wmi_event); + return; + } + + wma_roam_preauth_scan_event_handler(wma_handle, vdev_id, wmi_event); + return; +} + +/* + * wma_set_channel + * If this request is called when station is connected, it should use + */ +static void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) +{ + struct wma_vdev_start_req req; + struct wma_target_req *msg; + VOS_STATUS status = VOS_STATUS_SUCCESS; + u_int8_t vdev_id, peer_id; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + struct wma_txrx_node *intr = wma->interfaces; + + WMA_LOGD("%s: Enter", __func__); + if (!wma_find_vdev_by_addr(wma, params->selfStaMacAddr, &vdev_id)) { + WMA_LOGP("%s: Failed to find vdev id for %pM", + __func__, params->selfStaMacAddr); + status = VOS_STATUS_E_FAILURE; + goto send_resp; + } + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + status = VOS_STATUS_E_FAILURE; + goto send_resp; + } + + peer = ol_txrx_find_peer_by_addr(pdev, intr[vdev_id].bssid, &peer_id); + + /* + * Roam offload feature is currently supported + * only in STA mode. Other modes still require + * to issue a Vdev Start/Vdev Restart for + * channel change. + */ + if (((wma->interfaces[vdev_id].type == WMI_VDEV_TYPE_STA) && + (wma->interfaces[vdev_id].sub_type == 0)) && + !wma->interfaces[vdev_id].is_channel_switch) { + + if (peer && (peer->state == ol_txrx_peer_state_conn || + peer->state == ol_txrx_peer_state_auth)) { + /* Trying to change channel while connected + * should not invoke VDEV_START. + * Instead, use start scan command in passive + * mode to park station on that channel + */ + WMA_LOGI("%s: calling set_scan, state 0x%x", + __func__, wma->roam_preauth_scan_state); + if (wma->roam_preauth_scan_state == + WMA_ROAM_PREAUTH_CHAN_NONE) { + /* Is channel change required? + */ + if(vos_chan_to_freq(params->channelNumber) != + wma->interfaces[vdev_id].mhz) + { + status = wma_roam_preauth_chan_set(wma, + params, vdev_id); + /* response will be asynchronous */ + return; + } + } else if (wma->roam_preauth_scan_state == + WMA_ROAM_PREAUTH_CHAN_REQUESTED || + wma->roam_preauth_scan_state == WMA_ROAM_PREAUTH_ON_CHAN) { + status = wma_roam_preauth_chan_cancel(wma, params, vdev_id); + /* response will be asynchronous */ + return; + } else if (wma->roam_preauth_scan_state == + WMA_ROAM_PREAUTH_CHAN_COMPLETED) { + /* Already back on home channel. Complete the request */ + wma->roam_preauth_scan_state = WMA_ROAM_PREAUTH_CHAN_NONE; + status = VOS_STATUS_SUCCESS; + } + goto send_resp; + } + } + vos_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + msg = wma_fill_vdev_req(wma, req.vdev_id, WDA_CHNL_SWITCH_REQ, + WMA_TARGET_REQ_TYPE_VDEV_START, params, + WMA_VDEV_START_REQUEST_TIMEOUT); + if (!msg) { + WMA_LOGP("%s: Failed to fill channel switch request for vdev %d", + __func__, req.vdev_id); + status = VOS_STATUS_E_NOMEM; + goto send_resp; + } + req.chan = params->channelNumber; + req.chan_offset = params->secondaryChannelOffset; + req.vht_capable = params->vhtCapable; + req.dot11_mode = params->dot11_mode; +#ifdef WLAN_FEATURE_VOWIFI + req.max_txpow = params->maxTxPower; +#else + req.max_txpow = params->localPowerConstraint; +#endif + req.beacon_intval = 100; + req.dtim_period = 1; + req.is_dfs = params->isDfsChannel; + + /* In case of AP mode, once radar is detected, we need to + * issuse VDEV RESTART, so we making is_channel_switch as + * TRUE + */ + if ((wma_is_vdev_in_ap_mode(wma, req.vdev_id) == true) || + params->restart_on_chan_switch == VOS_TRUE) + wma->interfaces[req.vdev_id].is_channel_switch = VOS_TRUE; + + status = wma_vdev_start(wma, &req, + wma->interfaces[req.vdev_id].is_channel_switch); + if (status != VOS_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, req.vdev_id, WMA_TARGET_REQ_TYPE_VDEV_START); + WMA_LOGP("%s: vdev start failed status = %d", __func__, status); + goto send_resp; + } + + if (wma->interfaces[req.vdev_id].is_channel_switch) + wma->interfaces[req.vdev_id].is_channel_switch = VOS_FALSE; + return; +send_resp: + WMA_LOGD("%s: channel %d offset %d txpower %d status %d", __func__, + params->channelNumber, params->secondaryChannelOffset, +#ifdef WLAN_FEATURE_VOWIFI + params->maxTxPower, +#else + params->localPowerConstraint, +#endif + status); + params->status = status; + WMA_LOGI("%s: sending WDA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, status); + wma_send_msg(wma, WDA_SWITCH_CHANNEL_RSP, (void *)params, 0); +} + +static WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, u_int8_t sta_type, + u_int8_t is_ht, u_int8_t is_cw40, u_int8_t is_vht, u_int8_t is_cw_vht) +{ + WLAN_PHY_MODE phymode = MODE_UNKNOWN; + + switch (nw_type) { + case eSIR_11B_NW_TYPE: + if (is_vht) { + if (is_cw_vht) + phymode = MODE_11AC_VHT80; + else + phymode = (is_cw40) ? + MODE_11AC_VHT40 : + MODE_11AC_VHT20; + } + else if (is_ht) { + phymode = (is_cw40) ? + MODE_11NG_HT40 : MODE_11NG_HT20; + } else + phymode = MODE_11B; + break; + case eSIR_11G_NW_TYPE: + if (is_vht) { + if (is_cw_vht) + phymode = MODE_11AC_VHT80; + else + phymode = (is_cw40) ? + MODE_11AC_VHT40 : + MODE_11AC_VHT20; + } + else if (is_ht) { + phymode = (is_cw40) ? + MODE_11NG_HT40 : + MODE_11NG_HT20; + } else + phymode = MODE_11G; + break; + case eSIR_11A_NW_TYPE: + if (is_vht) { + if (is_cw_vht) + phymode = MODE_11AC_VHT80; + else + phymode = (is_cw40) ? + MODE_11AC_VHT40 : + MODE_11AC_VHT20; + } + else if (is_ht) { + phymode = (is_cw40) ? + MODE_11NA_HT40 : + MODE_11NA_HT20; + } else + phymode = MODE_11A; + break; + default: + WMA_LOGP("%s: Invalid nw type %d", __func__, nw_type); + break; + } + WMA_LOGD("%s: nw_type %d is_ht %d is_cw40 %d is_vht %d is_cw_vht %d phymode %d", + __func__, nw_type, is_ht, is_cw40, is_vht, is_cw_vht, phymode); + + return phymode; +} + +static int32_t wmi_unified_send_txbf(tp_wma_handle wma, + tpAddStaParams params) +{ + wmi_vdev_txbf_en txbf_en; + + /* This is set when Other partner is Bformer + and we are capable bformee(enabled both in ini and fw) */ + txbf_en.sutxbfee = params->vhtTxBFCapable; + txbf_en.mutxbfee = params->vhtTxMUBformeeCapable; + txbf_en.sutxbfer = 0; + txbf_en.mutxbfer = 0; + + /* When MU TxBfee is set, SU TxBfee must be set by default */ + if (txbf_en.mutxbfee) + txbf_en.sutxbfee = txbf_en.mutxbfee; + + WMA_LOGD("txbf_en.sutxbfee %d txbf_en.mutxbfee %d", + txbf_en.sutxbfee, txbf_en.mutxbfee); + + return(wmi_unified_vdev_set_param_send(wma->wmi_handle, + params->smesessionId, WMI_VDEV_PARAM_TXBF, + *((A_UINT8 *)&txbf_en))); +} + +static void wma_update_txrx_chainmask(int num_rf_chains, int *cmd_value) +{ + if (*cmd_value > WMA_MAX_RF_CHAINS(num_rf_chains)) { + WMA_LOGE("%s: Chainmask value exceeds the maximum" + " supported range setting it to" + " maximum value. Requested value %d" + " Updated value %d", __func__, *cmd_value, + WMA_MAX_RF_CHAINS(num_rf_chains)); + *cmd_value = WMA_MAX_RF_CHAINS(num_rf_chains); + } else if (*cmd_value < WMA_MIN_RF_CHAINS) { + WMA_LOGE("%s: Chainmask value is less than the minimum" + " supported range setting it to" + " minimum value. Requested value %d" + " Updated value %d", __func__, *cmd_value, + WMA_MIN_RF_CHAINS); + *cmd_value = WMA_MIN_RF_CHAINS; + } +} + +static int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, + tSirNwType nw_type, + tpAddStaParams params) +{ + ol_txrx_pdev_handle pdev; + wmi_peer_assoc_complete_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int32_t ret, max_rates, i; + u_int8_t rx_stbc, tx_stbc; + u_int8_t *rate_pos, *buf_ptr; + wmi_rate_set peer_legacy_rates, peer_ht_rates; + wmi_vht_rate_set *mcs; + u_int32_t num_peer_legacy_rates; + u_int32_t num_peer_ht_rates; + u_int32_t num_peer_11b_rates=0; + u_int32_t num_peer_11a_rates=0; + u_int32_t phymode; + u_int32_t peer_nss=1; + struct wma_txrx_node *intr = NULL; + + if (NULL == params) { + WMA_LOGE("%s: params is NULL", __func__); + return -EINVAL; + } + intr = &wma->interfaces[params->smesessionId]; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return -EINVAL; + } + + vos_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set)); + vos_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set)); + + phymode = wma_peer_phymode(nw_type, params->staType, + params->htCapable, + params->txChannelWidthSet, + params->vhtCapable, + params->vhtTxChannelWidthSet); + + /* Legacy Rateset */ + rate_pos = (u_int8_t *) peer_legacy_rates.rates; + for (i = 0; i < SIR_NUM_11B_RATES; i++) { + if (!params->supportedRates.llbRates[i]) + continue; + rate_pos[peer_legacy_rates.num_rates++] = + params->supportedRates.llbRates[i]; + num_peer_11b_rates++; + } + for (i = 0; i < SIR_NUM_11A_RATES; i++) { + if (!params->supportedRates.llaRates[i]) + continue; + rate_pos[peer_legacy_rates.num_rates++] = + params->supportedRates.llaRates[i]; + num_peer_11a_rates++; + } + + if ((phymode == MODE_11A && num_peer_11a_rates == 0) || + (phymode == MODE_11B && num_peer_11b_rates == 0)) { + WMA_LOGW("%s: Invalid phy rates. phymode 0x%x, 11b_rates %d, 11a_rates %d", + __func__, phymode, num_peer_11b_rates, num_peer_11a_rates); + return -EINVAL; + } + /* Set the Legacy Rates to Word Aligned */ + num_peer_legacy_rates = roundup(peer_legacy_rates.num_rates, + sizeof(u_int32_t)); + + /* HT Rateset */ + max_rates = sizeof(peer_ht_rates.rates) / + sizeof(peer_ht_rates.rates[0]); + rate_pos = (u_int8_t *) peer_ht_rates.rates; + for (i = 0; i < MAX_SUPPORTED_RATES; i++) { + if (params->supportedRates.supportedMCSSet[i / 8] & + (1 << (i % 8))) { + rate_pos[peer_ht_rates.num_rates++] = i; + if (i >= 8) { + /* MCS8 or higher rate is present, must be 2x2 */ + peer_nss = 2; + } + } + if (peer_ht_rates.num_rates == max_rates) + break; + } + + if (params->htCapable && !peer_ht_rates.num_rates) { + u_int8_t temp_ni_rates[8] = {0x0, 0x1, 0x2, 0x3, + 0x4, 0x5, 0x6, 0x7}; + /* + * Workaround for EV 116382: The peer is marked HT but with + * supported rx mcs set is set to 0. 11n spec mandates MCS0-7 + * for a HT STA. So forcing the supported rx mcs rate to + * MCS 0-7. This workaround will be removed once we get + * clarification from WFA regarding this STA behavior. + */ + + /* TODO: Do we really need this? */ + WMA_LOGW("Peer is marked as HT capable but supported mcs rate is 0"); + peer_ht_rates.num_rates = sizeof(temp_ni_rates); + vos_mem_copy((u_int8_t *) peer_ht_rates.rates, temp_ni_rates, + peer_ht_rates.num_rates); + } + + /* Set the Peer HT Rates to Word Aligned */ + num_peer_ht_rates = roundup(peer_ht_rates.num_rates, + sizeof(u_int32_t)); + + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE + /* Place holder for peer legacy rate array */ + (num_peer_legacy_rates * sizeof(u_int8_t)) + /* peer legacy rate array size */ + WMI_TLV_HDR_SIZE + /* Place holder for peer Ht rate array */ + (num_peer_ht_rates * sizeof(u_int8_t)) + /* peer HT rate array size */ + sizeof(wmi_vht_rate_set); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_peer_assoc_complete_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_assoc_complete_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_peer_assoc_complete_cmd_fixed_param)); + + /* in ap/ibss mode and for tdls peer, use mac address of the peer in + * the other end as the new peer address; in sta mode, use bss id to + * be the new peer address + */ + if ((wma_is_vdev_in_ap_mode(wma, params->smesessionId)) +#ifdef QCA_IBSS_SUPPORT + || (wma_is_vdev_in_ibss_mode(wma, params->smesessionId)) +#endif +#ifdef FEATURE_WLAN_TDLS + || (STA_ENTRY_TDLS_PEER == params->staType) +#endif + ) + WMI_CHAR_ARRAY_TO_MAC_ADDR(params->staMac, &cmd->peer_macaddr); + else + WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssId, &cmd->peer_macaddr); + cmd->vdev_id = params->smesessionId; + cmd->peer_new_assoc = 1; + cmd->peer_associd = params->assocId; + + /* + * The target only needs a subset of the flags maintained in the host. + * Just populate those flags and send it down + */ + cmd->peer_flags = 0; + + if (params->wmmEnabled) + cmd->peer_flags |= WMI_PEER_QOS; + + if (params->uAPSD) { + cmd->peer_flags |= WMI_PEER_APSD; + WMA_LOGD("Set WMI_PEER_APSD: uapsd Mask %d", params->uAPSD); + } + + if (params->htCapable) { + cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS); + cmd->peer_rate_caps |= WMI_RC_HT_FLAG; + } + + if (params->txChannelWidthSet) { + cmd->peer_flags |= WMI_PEER_40MHZ; + cmd->peer_rate_caps |= WMI_RC_CW40_FLAG; + if (params->fShortGI40Mhz) + cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; + } else if (params->fShortGI20Mhz) + cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; + +#ifdef WLAN_FEATURE_11AC + if (params->vhtCapable) { + cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_VHT | WMI_PEER_QOS); + cmd->peer_rate_caps |= WMI_RC_HT_FLAG; + } + + if (params->vhtTxChannelWidthSet) + cmd->peer_flags |= WMI_PEER_80MHZ; + + cmd->peer_vht_caps = params->vht_caps; +#endif + + if (params->rmfEnabled) + cmd->peer_flags |= WMI_PEER_PMF; + + rx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_RXSTBC) >> + IEEE80211_HTCAP_C_RXSTBC_S; + if (rx_stbc) { + cmd->peer_flags |= WMI_PEER_STBC; + cmd->peer_rate_caps |= (rx_stbc << WMI_RC_RX_STBC_FLAG_S); + } + + tx_stbc = (params->ht_caps & IEEE80211_HTCAP_C_TXSTBC) >> + IEEE80211_HTCAP_C_TXSTBC_S; + if (tx_stbc) { + cmd->peer_flags |= WMI_PEER_STBC; + cmd->peer_rate_caps |= (tx_stbc << WMI_RC_TX_STBC_FLAG_S); + } + + if (params->htLdpcCapable || params->vhtLdpcCapable) + cmd->peer_flags |= WMI_PEER_LDPC; + + switch (params->mimoPS) { + case eSIR_HT_MIMO_PS_STATIC: + cmd->peer_flags |= WMI_PEER_STATIC_MIMOPS; + break; + case eSIR_HT_MIMO_PS_DYNAMIC: + cmd->peer_flags |= WMI_PEER_DYN_MIMOPS; + break; + case eSIR_HT_MIMO_PS_NO_LIMIT: + cmd->peer_flags |= WMI_PEER_SPATIAL_MUX; + break; + default: + break; + } + +#ifdef FEATURE_WLAN_TDLS + if (STA_ENTRY_TDLS_PEER == params->staType) + cmd->peer_flags |= WMI_PEER_AUTH; +#endif + + if (params->wpa_rsn +#ifdef FEATURE_WLAN_WAPI + || params->encryptType == eSIR_ED_WPI +#endif + ) + cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY; + if (params->wpa_rsn >> 1) + cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY; + + #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + if (STA_ENTRY_TDLS_PEER == params->staType) + ol_txrx_peer_state_update(pdev, params->staMac, ol_txrx_peer_state_auth); + else + ol_txrx_peer_state_update(pdev, params->bssId, ol_txrx_peer_state_auth); + #else + ol_txrx_peer_state_update(pdev, params->bssId, ol_txrx_peer_state_auth); + #endif + +#ifdef FEATURE_WLAN_WAPI + if (params->encryptType == eSIR_ED_WPI) { + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + params->smesessionId, + WMI_VDEV_PARAM_DROP_UNENCRY, + FALSE); + if (ret) { + WMA_LOGE("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n", ret); + adf_nbuf_free(buf); + return ret; + } + } +#endif + + cmd->peer_caps = params->capab_info; + cmd->peer_listen_intval = params->listenInterval; + cmd->peer_ht_caps = params->ht_caps; + cmd->peer_max_mpdu = (1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + + params->maxAmpduSize)) - 1; + cmd->peer_mpdu_density = wma_parse_mpdudensity(params->maxAmpduDensity); + + if (params->supportedRates.supportedMCSSet[1] && + params->supportedRates.supportedMCSSet[2]) + cmd->peer_rate_caps |= WMI_RC_TS_FLAG; + else if (params->supportedRates.supportedMCSSet[1]) + cmd->peer_rate_caps |= WMI_RC_DS_FLAG; + + /* Update peer legacy rate information */ + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + num_peer_legacy_rates); + buf_ptr += WMI_TLV_HDR_SIZE; + cmd->num_peer_legacy_rates = peer_legacy_rates.num_rates; + vos_mem_copy(buf_ptr, peer_legacy_rates.rates, + peer_legacy_rates.num_rates); + + /* Update peer HT rate information */ + buf_ptr += num_peer_legacy_rates; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + num_peer_ht_rates); + buf_ptr += WMI_TLV_HDR_SIZE; + cmd->num_peer_ht_rates = peer_ht_rates.num_rates; + vos_mem_copy(buf_ptr, peer_ht_rates.rates, + peer_ht_rates.num_rates); + + /* VHT Rates */ + buf_ptr += num_peer_ht_rates; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_STRUC_wmi_vht_rate_set, + WMITLV_GET_STRUCT_TLVLEN(wmi_vht_rate_set)); + + cmd->peer_nss = peer_nss; + + WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss, + peer_ht_rates.num_rates); + + mcs = (wmi_vht_rate_set *)buf_ptr; + if ( params->vhtCapable) { +#define VHT2x2MCSMASK 0xc + mcs->rx_max_rate = params->supportedRates.vhtRxHighestDataRate; + mcs->rx_mcs_set = params->supportedRates.vhtRxMCSMap; + mcs->tx_max_rate = params->supportedRates.vhtTxHighestDataRate; + mcs->tx_mcs_set = params->supportedRates.vhtTxMCSMap; + + if(params->vhtSupportedRxNss) { + cmd->peer_nss = params->vhtSupportedRxNss; + } else { + cmd->peer_nss = ((mcs->rx_mcs_set & VHT2x2MCSMASK) + == VHT2x2MCSMASK) ? 1 : 2; + } + } + + /* + * Limit nss to max number of rf chain supported by target + * Otherwise Fw will crash + */ + if (!wma->per_band_chainmask_supp) + wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss); + + intr->nss = cmd->peer_nss; + cmd->peer_phymode = phymode; + + WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x " + "peer_caps %x listen_intval %d ht_caps %x max_mpdu %d " + "nss %d phymode %d peer_mpdu_density %d encr_type %d " + "cmd->peer_vht_caps %x", __func__, + cmd->vdev_id, cmd->peer_associd, cmd->peer_flags, + cmd->peer_rate_caps, cmd->peer_caps, + cmd->peer_listen_intval, cmd->peer_ht_caps, + cmd->peer_max_mpdu, cmd->peer_nss, cmd->peer_phymode, + cmd->peer_mpdu_density, params->encryptType, + cmd->peer_vht_caps); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PEER_ASSOC_CMDID); + if (ret != EOK) { + WMA_LOGP("%s: Failed to send peer assoc command ret = %d", + __func__, ret); + adf_nbuf_free(buf); + } + return ret; +} + +static int +wmi_unified_modem_power_state(wmi_unified_t wmi_handle, u_int32_t param_value) +{ + int ret; + wmi_modem_power_state_cmd_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_modem_power_state_cmd_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_modem_power_state_cmd_param)); + cmd->modem_power_state = param_value; + WMA_LOGD("%s: Setting cmd->modem_power_state = %u", __func__, param_value); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_MODEM_POWER_STATE_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send notify cmd ret = %d", ret); + wmi_buf_free(buf); + } + return ret; +} + +VOS_STATUS wma_get_link_speed(WMA_HANDLE handle, + tSirLinkSpeedInfo *pLinkSpeed) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_peer_get_estimated_linkspeed_cmd_fixed_param* cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_ESTIMATE_LINKSPEED)) { + WMA_LOGE("%s: Linkspeed feature bit not enabled" + " Sending value 0 as link speed.", + __func__); + wma_send_link_speed(0); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(wmi_peer_get_estimated_linkspeed_cmd_fixed_param); + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (wmi_peer_get_estimated_linkspeed_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_get_estimated_linkspeed_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_peer_get_estimated_linkspeed_cmd_fixed_param)); + + /* Copy the peer macaddress to the wma buffer */ + WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr, &cmd->peer_macaddr); + + WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, " + "peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x", + __func__, pLinkSpeed->peer_macaddr, + cmd->peer_macaddr.mac_addr31to0, + cmd->peer_macaddr.mac_addr47to32); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID)) { + WMA_LOGE("%s: failed to send link speed command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + + +/** + * wma_get_rssi() - get station's rssi + * @handle: wma interface + * @prssi_req: get rssi request information + * + * This function will send WMI_REQUEST_STATS_CMDID + * to wmi + * + * Return: 0 on success, otherwise error value + */ +static VOS_STATUS wma_get_rssi(WMA_HANDLE handle, + struct sir_rssi_req *prssi_req) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + wmi_request_stats_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + uint8_t *buf_ptr; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue get rssi", + __func__); + return VOS_STATUS_E_INVAL; + } + + len = sizeof(wmi_request_stats_cmd_fixed_param); + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf); + + cmd = (wmi_request_stats_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param)); + + cmd->stats_id = WMI_REQUEST_PEER_STAT; + cmd->vdev_id = prssi_req->sessionId; + wma_handle->get_sta_rssi = TRUE; + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_REQUEST_STATS_CMDID)) { + WMA_LOGE("Failed to send host stats request to fw"); + wmi_buf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + + vos_mem_copy(&(wma_handle->peer_macaddr), + &(prssi_req->peer_macaddr), + VOS_MAC_ADDR_SIZE); + return VOS_STATUS_SUCCESS; +} + + + +static int +wmi_unified_pdev_set_param(wmi_unified_t wmi_handle, WMI_PDEV_PARAM param_id, + u_int32_t param_value) +{ + int ret; + wmi_pdev_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_pdev_set_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_set_param_cmd_fixed_param)); + cmd->reserved0 = 0; + cmd->param_id = param_id; + cmd->param_value = param_value; + WMA_LOGD("Setting pdev param = %x, value = %u", + param_id, param_value); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_PDEV_SET_PARAM_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send set param command ret = %d", ret); + wmi_buf_free(buf); + } + return ret; +} + +static int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle, + uint8_t vdev_id, u_int32_t value) +{ + struct ol_txrx_stats_req req; + ol_txrx_vdev_handle vdev; + + vdev = wma_find_vdev_by_id(wma_handle, vdev_id); + if (!vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + return -EINVAL; + } + vos_mem_zero(&req, sizeof(req)); + req.stats_type_reset_mask = value; + ol_txrx_fw_stats_get(vdev, &req); + + return 0; +} + +static int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle, + uint8_t vdev_id, u_int32_t value) +{ + struct ol_txrx_stats_req req; + ol_txrx_vdev_handle vdev; + + vdev = wma_find_vdev_by_id(wma_handle, vdev_id); + if (!vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + return -EINVAL; + } + vos_mem_zero(&req, sizeof(req)); + req.print.verbose = 1; + switch (value) { + case WMA_FW_PHY_STATS: + case WMA_FW_RX_REORDER_STATS: + case WMA_FW_RX_RC_STATS: + case WMA_FW_TX_PPDU_STATS: + req.stats_type_upload_mask = 1 << (value - 1); + break; + case WMA_FW_TX_CONCISE_STATS: + /* + * Stats request 5 is the same as stats request 4, + * but with only a concise printout. + */ + req.print.concise = 1; + req.stats_type_upload_mask = 1 << (WMA_FW_TX_PPDU_STATS - 1); + break; + case WMA_FW_TX_RC_STATS: + req.stats_type_upload_mask = 1 << (WMA_FW_TX_CONCISE_STATS - 1); + break; + case WMA_FW_RX_REM_RING_BUF: + /* + * This part of the code is a bit confusing. + * For the statistics command iwpriv wlan0 txrx_fw_stats , + * for all n <= 4, there is 1:1 mapping of WMA defined value (n) + * with f/w required stats_type_upload_mask. + * For n <= 4, stats_type_upload_mask = 1 << (n - 1) + * With the introduction of WMA_FW_TX_CONCISE_STATS, + * there is a need for special handling, where for n = 5, + * stats_type_upload_mask = 1 << (n - 2). + * However per current code, there is no way to set the value of + * stats_type_upload_mask for n > 5. + * In the mean-time for dumping Remote Ring Buffer information, + * f/w expects stats_type_upload_mask = 1 << 12. + * However going by CLI command arguments, n should be 7. + * There seems to be no apparent correlation between 7 & 12. + * To fix this properly, one needs to fix the WMA defines + * appropriately and always let n have a 1:1 + * correspondence with the bitmask expected by f/w. + * Do not want to disturb the existing code now, + * but extending this code, so that CLI argument "n" has + * 1:1 correspondence with f/w bitmask. + * With this approach, for remote ring information, + * the statistics command should be: + * iwpriv wlan0 txrx_fw_stats 12 + */ + /* FIXME : Fix all the values in the appropriate way. */ + req.stats_type_upload_mask = 1 << WMA_FW_RX_REM_RING_BUF; + break; + case WMA_FW_RX_TXBF_MUSU_NDPA: + req.stats_type_upload_mask = 1 << WMA_FW_RX_TXBF_MUSU_NDPA; + break; + default: + WMA_LOGE("Invalid txrx_fw_stats requested id:%d", + value); + return -EINVAL; + } + ol_txrx_fw_stats_get(vdev, &req); + + return 0; +} + +static int32_t wma_set_priv_cfg(tp_wma_handle wma_handle, + wda_cli_set_cmd_t *privcmd) +{ + int32_t ret = 0; + + switch (privcmd->param_id) { + case WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID: + ret = wma_set_txrx_fw_stats_level(wma_handle, + privcmd->param_vdev_id, + privcmd->param_value); + break; + case WMA_VDEV_TXRX_FWSTATS_RESET_CMDID: + ret = wma_txrx_fw_stats_reset(wma_handle, + privcmd->param_vdev_id, + privcmd->param_value); + break; + case WMI_STA_SMPS_FORCE_MODE_CMDID: + ret = wma_set_mimops(wma_handle, privcmd->param_vdev_id, + privcmd->param_value); + break; + case WMI_STA_SMPS_PARAM_CMDID: + wma_set_smps_params(wma_handle, privcmd->param_vdev_id, + privcmd->param_value); + break; + case WMA_VDEV_MCC_SET_TIME_LATENCY: + { + /* Extract first MCC adapter/vdev channel number and latency */ + tANI_U8 mcc_channel = privcmd->param_value & 0x000000FF; + tANI_U8 mcc_channel_latency = + (privcmd->param_value & 0x0000FF00) >> 8; + int ret = -1; + WMA_LOGD("%s: Parsed input: Channel #1:%d, latency:%dms", + __func__, mcc_channel, mcc_channel_latency); + ret = wma_set_mcc_channel_time_latency + ( + wma_handle, + mcc_channel, + mcc_channel_latency + ); + } + break; + case WMA_VDEV_MCC_SET_TIME_QUOTA: + { + /** Extract the MCC 2 adapters/vdevs channel numbers and time + * quota value for the first adapter only (which is specified + * in iwpriv command. + */ + tANI_U8 adapter_2_chan_number = + privcmd->param_value & 0x000000FF; + tANI_U8 adapter_1_chan_number = + (privcmd->param_value & 0x0000FF00) >> 8; + tANI_U8 adapter_1_quota = + (privcmd->param_value & 0x00FF0000) >> 16; + int ret = -1; + + WMA_LOGD("%s: Parsed input: Channel #1:%d, Channel #2:%d," + "quota 1:%dms", __func__, adapter_1_chan_number, + adapter_2_chan_number, adapter_1_quota); + ret = wma_set_mcc_channel_time_quota + ( + wma_handle, + adapter_1_chan_number, + adapter_1_quota, + adapter_2_chan_number + ); + } + break; + case WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE: + { + wma_handle->wma_ibss_power_save_params.atimWindowLength = + privcmd->param_value; + WMA_LOGD("%s: IBSS power save ATIM Window = %d", __func__, + wma_handle->wma_ibss_power_save_params.atimWindowLength); + } + break; + case WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED: + { + wma_handle->wma_ibss_power_save_params.isPowerSaveAllowed = + privcmd->param_value; + WMA_LOGD("%s: IBSS is Power Save Allowed = %d", __func__, + wma_handle->wma_ibss_power_save_params.isPowerSaveAllowed); + } + break; + case WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED: + { + wma_handle->wma_ibss_power_save_params.isPowerCollapseAllowed = + privcmd->param_value; + WMA_LOGD("%s: IBSS is Power Collapse Allowed = %d", __func__, + wma_handle->wma_ibss_power_save_params.isPowerCollapseAllowed); + } + break; + case WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX: + { + wma_handle->wma_ibss_power_save_params.isAwakeonTxRxEnabled = + privcmd->param_value; + WMA_LOGD("%s: IBSS Power Save Awake on Tx/Rx Enabled = %d", __func__, + wma_handle->wma_ibss_power_save_params.isAwakeonTxRxEnabled); + } + break; + case WMA_VDEV_IBSS_SET_INACTIVITY_TIME: + { + wma_handle->wma_ibss_power_save_params.inactivityCount = + privcmd->param_value; + WMA_LOGD("%s: IBSS Power Save Data Inactivity Count = %d", __func__, + wma_handle->wma_ibss_power_save_params.inactivityCount); + } + break; + case WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME: + { + wma_handle->wma_ibss_power_save_params.txSPEndInactivityTime = + privcmd->param_value; + WMA_LOGD("%s: IBSS Power Save Transmit EOSP inactivity time out = %d", + __func__, + wma_handle->wma_ibss_power_save_params.txSPEndInactivityTime); + } + break; + case WMA_VDEV_DFS_CONTROL_CMDID: + { + struct ieee80211com *dfs_ic = wma_handle->dfs_ic; + struct ath_dfs *dfs; + + if (!dfs_ic) { + ret = -ENOENT; + } else { + if (dfs_ic->ic_curchan) { + WMA_LOGD("%s: Debug cmd: %s received on ch: %d", + __func__, + "WMA_VDEV_DFS_CONTROL_CMDID", + dfs_ic->ic_curchan->ic_ieee); + + if (dfs_ic->ic_curchan->ic_flagext & + IEEE80211_CHAN_DFS) { + dfs = (struct ath_dfs *)dfs_ic->ic_dfs; + dfs->dfs_bangradar = 1; + dfs->ath_radar_tasksched = 1; + OS_SET_TIMER(&dfs->ath_dfs_task_timer, + 0); + } else { + ret = -ENOENT; + } + } else { + ret = -ENOENT; + } + } + + if ( ret == -ENOENT) { + WMA_LOGE("%s: Operating channel is not DFS capable, " + "ignoring %s", + __func__, + "WMA_VDEV_DFS_CONTROL_CMDID"); + } else if (ret) { + WMA_LOGE("%s: Sending command %s failed with %d\n", + __func__, + "WMA_VDEV_DFS_CONTROL_CMDID", + ret); + } + } + break; + case WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS: + { + wma_handle->wma_ibss_power_save_params.ibssPsWarmupTime = + privcmd->param_value; + WMA_LOGD("%s: IBSS Power Save Warm Up Time in Seconds = %d", + __func__, + wma_handle->wma_ibss_power_save_params.ibssPsWarmupTime); + } + break; + case WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW: + { + wma_handle->wma_ibss_power_save_params.ibssPs1RxChainInAtimEnable = + privcmd->param_value; + WMA_LOGD("%s: IBSS Power Save single RX Chain Enable In ATIM = %d", + __func__, + wma_handle->wma_ibss_power_save_params.ibssPs1RxChainInAtimEnable); + } + break; + +#ifdef IPA_UC_OFFLOAD + case WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID: + { + ol_txrx_pdev_handle pdev; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_WDA, NULL)) { + WMA_LOGE("%s: Driver load/unload in progress", __func__); + return -EINVAL; + } + pdev = vos_get_context(VOS_MODULE_ID_TXRX, + wma_handle->vos_context); + if (!pdev) { + WMA_LOGE("pdev NULL for uc stat"); + return -EINVAL; + } + ol_txrx_ipa_uc_get_stat(pdev); + } + break; +#endif /* IPA_UC_OFFLOAD */ + + default: + WMA_LOGE("Invalid wma config command id:%d", + privcmd->param_id); + ret = -EINVAL; + } + return ret; +} + +static int wmi_crash_inject(wmi_unified_t wmi_handle, u_int32_t type, + u_int32_t delay_time_ms) +{ + int ret = 0; + WMI_FORCE_FW_HANG_CMD_fixed_param *cmd; + u_int16_t len = sizeof(*cmd); + wmi_buf_t buf; + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed!", __func__); + return -ENOMEM; + } + + cmd = (WMI_FORCE_FW_HANG_CMD_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_FORCE_FW_HANG_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(WMI_FORCE_FW_HANG_CMD_fixed_param)); + cmd->type = type; + cmd->delay_time_ms = delay_time_ms; + + ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_FORCE_FW_HANG_CMDID); + if (ret < 0) { + WMA_LOGE("%s: Failed to send set param command, ret = %d", + __func__, ret); + wmi_buf_free(buf); + } + + return ret; +} + +/** + * wma_crash_inject() - sends command to FW to simulate crash + * @wma_handle: pointer of WMA context + * @type: subtype of the command + * @delay_time_ms: time in milliseconds for FW to delay the crash + * + * This function will send a command to FW in order to simulate different + * kinds of FW crashes. + * + * Return: 0 for success or reasons for failure + */ + +int wma_crash_inject(tp_wma_handle wma_handle, uint32_t type, + uint32_t delay_time_ms) +{ + return wmi_crash_inject(wma_handle->wmi_handle, type, delay_time_ms); +} + +static int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle, + u_int32_t vdev_id, u_int32_t param, u_int32_t value) +{ + wmi_sta_powersave_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + tp_wma_handle wma; + struct wma_txrx_node *iface; + wma = vos_get_context(VOS_MODULE_ID_WDA, + vos_get_global_context(VOS_MODULE_ID_WDA, NULL)); + if (NULL == wma) { + WMA_LOGE("%s: wma is NULL", __func__); + return -EIO; + } + iface = &wma->interfaces[vdev_id]; + + WMA_LOGD("Set Sta Ps param vdevId %d Param %d val %d", + vdev_id, param, value); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: Set Sta Ps param Mem Alloc Failed", __func__); + return -ENOMEM; + } + + cmd = (wmi_sta_powersave_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_powersave_param_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->param = param; + cmd->value = value; + + if (wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_STA_POWERSAVE_PARAM_CMDID)) { + WMA_LOGE("Set Sta Ps param Failed vdevId %d Param %d val %d", + vdev_id, param, value); + adf_nbuf_free(buf); + return -EIO; + } + /* Store the PS Status */ + iface->ps_enabled = value ? TRUE : FALSE; + return 0; +} + +#ifdef FEATURE_GREEN_AP +static int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, + u_int32_t value) +{ + wmi_pdev_green_ap_ps_enable_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + WMA_LOGD("Set Green AP PS val %d", value); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: Green AP PS Mem Alloc Failed", __func__); + return -ENOMEM; + } + + cmd = (wmi_pdev_green_ap_ps_enable_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_green_ap_ps_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_green_ap_ps_enable_cmd_fixed_param)); + cmd->reserved0 = 0; + cmd->enable = value; + + if (wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID)) { + WMA_LOGE("Set Green AP PS param Failed val %d", value); + + adf_nbuf_free(buf); + return -EIO; + } + return 0; +} +#endif /* FEATURE_GREEN_AP */ + +static int +wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle, u_int32_t if_id, + gtx_config_t *gtx_info) +{ + wmi_vdev_set_gtx_params_cmd_fixed_param *cmd; + wmi_buf_t buf; + int len = sizeof(wmi_vdev_set_gtx_params_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __FUNCTION__); + return -1; + } + cmd = (wmi_vdev_set_gtx_params_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_set_gtx_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_set_gtx_params_cmd_fixed_param)); + cmd->vdev_id = if_id; + + cmd->gtxRTMask[0] = gtx_info->gtxRTMask[0]; + cmd->gtxRTMask[1] = gtx_info->gtxRTMask[1]; + cmd->userGtxMask = gtx_info->gtxUsrcfg; + cmd->gtxPERThreshold = gtx_info->gtxPERThreshold; + cmd->gtxPERMargin = gtx_info->gtxPERMargin; + cmd->gtxTPCstep = gtx_info->gtxTPCstep; + cmd->gtxTPCMin = gtx_info->gtxTPCMin; + cmd->gtxBWMask = gtx_info->gtxBWMask; + + WMA_LOGD("Setting vdev%d GTX values:htmcs 0x%x, vhtmcs 0x%x, usermask 0x%x, gtxPERThreshold %d, gtxPERMargin %d, gtxTPCstep %d, gtxTPCMin %d, gtxBWMask 0x%x.", + if_id, cmd->gtxRTMask[0], cmd->gtxRTMask[1], + cmd->userGtxMask, cmd->gtxPERThreshold, cmd->gtxPERMargin, + cmd->gtxTPCstep, cmd->gtxTPCMin, cmd->gtxBWMask); + return wmi_unified_cmd_send(wmi_handle, buf, len, WMI_VDEV_SET_GTX_PARAMS_CMDID); +} + +/** + * wma_send_echo_request() - send echo request to firmware + * @wma: wma context + * + * Return: none + */ +static void wma_send_echo_request(tp_wma_handle wma) +{ + wmi_echo_cmd_fixed_param *cmd; + wmi_buf_t buf; + int len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __FUNCTION__); + return; + } + + cmd = (wmi_echo_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_echo_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_echo_cmd_fixed_param)); + cmd->value = true; + + WMA_LOGD("Sent Echo request to firmware!"); + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_ECHO_CMDID)) { + WMA_LOGE("Failed to send Echo cmd to firmware"); + adf_nbuf_free(buf); + } +} + +/** + * wma_set_modulated_dtim() - function to configure modulated dtim + * @wma: wma handle + * @privcmd: structure containing parameters + * + * This function configures the modulated dtim in firmware + * + * Return: none + */ +static void wma_set_modulated_dtim(tp_wma_handle wma, + wda_cli_set_cmd_t *privcmd) +{ + uint8_t vdev_id = privcmd->param_vdev_id; + struct wma_txrx_node *iface = + &wma->interfaces[vdev_id]; + bool prev_dtim_enabled; + uint32_t listen_interval; + int ret; + + iface->alt_modulated_dtim = privcmd->param_value; + + prev_dtim_enabled = iface->alt_modulated_dtim_enabled; + + if (1 != privcmd->param_value) + iface->alt_modulated_dtim_enabled = true; + else + iface->alt_modulated_dtim_enabled = false; + + if ((true == iface->alt_modulated_dtim_enabled) || + (true == prev_dtim_enabled)) { + + listen_interval = iface->alt_modulated_dtim + * iface->dtimPeriod; + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + privcmd->param_vdev_id, + WMI_VDEV_PARAM_LISTEN_INTERVAL, + listen_interval); + if (ret) + /* Even if it fails, continue */ + WMA_LOGW("Failed to set listen interval %d", + listen_interval); + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + privcmd->param_vdev_id, + WMI_VDEV_PARAM_DTIM_POLICY , + NORMAL_DTIM); + if (ret) + WMA_LOGE("Failed to Set to Normal DTIM policy"); + } +} + +static void wma_process_cli_set_cmd(tp_wma_handle wma, + wda_cli_set_cmd_t *privcmd) +{ + int ret = 0, vid = privcmd->param_vdev_id, pps_val = 0; + struct wma_txrx_node *intr = wma->interfaces; + tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + struct qpower_params *qparams = &intr[vid].config.qpower_params; + + WMA_LOGD("wmihandle %p", wma->wmi_handle); + + if (NULL == pMac) { + WMA_LOGE("%s: Failed to get pMac", __func__); + return; + } + + if (privcmd->param_id >= WMI_CMDID_MAX) { + /* + * This configuration setting is not done using any wmi + * command, call appropriate handler. + */ + if (wma_set_priv_cfg(wma, privcmd)) + WMA_LOGE("Failed to set wma priv congiuration"); + return; + } + + switch (privcmd->param_vp_dev) { + case VDEV_CMD: + WMA_LOGD("vdev id %d pid %d pval %d", privcmd->param_vdev_id, + privcmd->param_id, privcmd->param_value); + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + privcmd->param_vdev_id, + privcmd->param_id, + privcmd->param_value); + if (ret) { + WMA_LOGE("wmi_unified_vdev_set_param_send" + " failed ret %d", ret); + return; + } + break; + case PDEV_CMD: + WMA_LOGD("pdev pid %d pval %d", privcmd->param_id, + privcmd->param_value); + if ((privcmd->param_id == WMI_PDEV_PARAM_RX_CHAIN_MASK) || + (privcmd->param_id == WMI_PDEV_PARAM_TX_CHAIN_MASK)) { + wma_update_txrx_chainmask(wma->num_rf_chains, + &privcmd->param_value); + } + + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + privcmd->param_id, + privcmd->param_value); + if (ret) { + WMA_LOGE("wmi_unified_vdev_set_param_send" + " failed ret %d", ret); + return; + } + break; + case GEN_CMD: + { + ol_txrx_vdev_handle vdev = NULL; + struct wma_txrx_node *intr = wma->interfaces; + + vdev = wma_find_vdev_by_id(wma, privcmd->param_vdev_id); + if (!vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + return; + } + WMA_LOGD("gen pid %d pval %d", privcmd->param_id, + privcmd->param_value); + + switch (privcmd->param_id) { + case GEN_VDEV_PARAM_AMPDU: + ret = ol_txrx_aggr_cfg(vdev, privcmd->param_value, 0); + if (ret) + WMA_LOGE("ol_txrx_aggr_cfg set ampdu" + " failed ret %d", ret); + else + intr[privcmd->param_vdev_id].config.ampdu = privcmd->param_value; + break; + case GEN_VDEV_PARAM_AMSDU: + ret = ol_txrx_aggr_cfg(vdev, 0, privcmd->param_value); + if (ret) + WMA_LOGE("ol_txrx_aggr_cfg set amsdu" + " failed ret %d", ret); + else + intr[privcmd->param_vdev_id].config.amsdu = privcmd->param_value; + break; + case GEN_PARAM_DUMP_AGC_START: + HTCDump(wma->htc_handle, AGC_DUMP, true); + break; + case GEN_PARAM_DUMP_AGC: + HTCDump(wma->htc_handle, AGC_DUMP, false); + break; + case GEN_PARAM_DUMP_CHANINFO_START: + HTCDump(wma->htc_handle, CHAN_DUMP, true); + break; + case GEN_PARAM_DUMP_CHANINFO: + HTCDump(wma->htc_handle, CHAN_DUMP, false); + break; + case GEN_PARAM_DUMP_WATCHDOG: + HTCDump(wma->htc_handle, WD_DUMP, false); + break; + case GEN_PARAM_CRASH_INJECT: + ret = wmi_crash_inject(wma->wmi_handle, + privcmd->param_value, privcmd->param_sec_value); + break; + case GEN_PARAM_CAPTURE_TSF: + ret = wma_capture_tsf(wma, privcmd->param_value); + break; + case GEN_PARAM_RESET_TSF_GPIO: + ret = wma_reset_tsf_gpio(wma, privcmd->param_value); + break; +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + case GEN_PARAM_DUMP_PCIE_ACCESS_LOG: + HTCDump(wma->htc_handle, PCIE_DUMP, false); + break; +#endif + case GEN_PARAM_MODULATED_DTIM: + wma_set_modulated_dtim(wma, privcmd); + break; + default: + WMA_LOGE("Invalid param id 0x%x", privcmd->param_id); + break; + } + break; + } + case DBG_CMD: + WMA_LOGD("dbg pid %d pval %d", privcmd->param_id, + privcmd->param_value); + switch (privcmd->param_id) { + case WMI_DBGLOG_LOG_LEVEL: + ret = dbglog_set_log_lvl(wma->wmi_handle, privcmd->param_value); + if (ret) + WMA_LOGE("dbglog_set_log_lvl" + " failed ret %d", ret); + break; + case WMI_DBGLOG_VAP_ENABLE: + ret = dbglog_vap_log_enable(wma->wmi_handle, privcmd->param_value, TRUE); + if (ret) + WMA_LOGE("dbglog_vap_log_enable" + " failed ret %d", ret); + break; + case WMI_DBGLOG_VAP_DISABLE: + ret = dbglog_vap_log_enable(wma->wmi_handle, privcmd->param_value, FALSE); + if (ret) + WMA_LOGE("dbglog_vap_log_enable" + " failed ret %d", ret); + break; + case WMI_DBGLOG_MODULE_ENABLE: + ret = dbglog_module_log_enable(wma->wmi_handle, privcmd->param_value, TRUE); + if (ret) + WMA_LOGE("dbglog_module_log_enable" + " failed ret %d", ret); + break; + case WMI_DBGLOG_MODULE_DISABLE: + ret = dbglog_module_log_enable(wma->wmi_handle, privcmd->param_value, FALSE); + if (ret) + WMA_LOGE("dbglog_module_log_enable" + " failed ret %d", ret); + break; + case WMI_DBGLOG_MOD_LOG_LEVEL: + ret = dbglog_set_mod_log_lvl(wma->wmi_handle, privcmd->param_value); + if (ret) + WMA_LOGE("dbglog_module_log_enable" + " failed ret %d", ret); + break; + case WMI_DBGLOG_TYPE: + ret = dbglog_parser_type_init(wma->wmi_handle, privcmd->param_value); + if (ret) + WMA_LOGE("dbglog_parser_type_init" + " failed ret %d", ret); + break; + case WMI_DBGLOG_REPORT_ENABLE: + ret = dbglog_report_enable(wma->wmi_handle, privcmd->param_value); + if (ret) + WMA_LOGE("dbglog_report_enable" + " failed ret %d", ret); + break; +#ifdef FEATURE_GREEN_AP + case WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID: + /* Set the Green AP */ + ret = wmi_unified_pdev_green_ap_ps_enable_cmd(wma->wmi_handle, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set GreenAP Failed val %d", privcmd->param_value); + } + break; +#endif /* FEATURE_GREEN_AP */ + + default: + WMA_LOGE("Invalid param id 0x%x", privcmd->param_id); + break; + } + break; + case PPS_CMD: + WMA_LOGD("dbg pid %d pval %d", privcmd->param_id, + privcmd->param_value); + switch (privcmd->param_id) { + + case WMI_VDEV_PPS_PAID_MATCH: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_PAID_MATCH & 0xffff); + intr[vid].config.pps_params.paid_match_enable = privcmd->param_value; + break; + case WMI_VDEV_PPS_GID_MATCH: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_GID_MATCH & 0xffff); + intr[vid].config.pps_params.gid_match_enable = privcmd->param_value; + break; + case WMI_VDEV_PPS_EARLY_TIM_CLEAR: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EARLY_TIM_CLEAR & 0xffff); + intr[vid].config.pps_params.tim_clear = privcmd->param_value; + break; + case WMI_VDEV_PPS_EARLY_DTIM_CLEAR: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EARLY_DTIM_CLEAR & 0xffff); + intr[vid].config.pps_params.dtim_clear = privcmd->param_value; + break; + case WMI_VDEV_PPS_EOF_PAD_DELIM: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EOF_PAD_DELIM & 0xffff); + intr[vid].config.pps_params.eof_delim = privcmd->param_value; + break; + case WMI_VDEV_PPS_MACADDR_MISMATCH: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_MACADDR_MISMATCH & 0xffff); + intr[vid].config.pps_params.mac_match = privcmd->param_value; + break; + case WMI_VDEV_PPS_DELIM_CRC_FAIL: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_DELIM_CRC_FAIL & 0xffff); + intr[vid].config.pps_params.delim_fail = privcmd->param_value; + break; + case WMI_VDEV_PPS_GID_NSTS_ZERO: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_GID_NSTS_ZERO & 0xffff); + intr[vid].config.pps_params.nsts_zero = privcmd->param_value; + break; + case WMI_VDEV_PPS_RSSI_CHECK: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_RSSI_CHECK & 0xffff); + intr[vid].config.pps_params.rssi_chk = privcmd->param_value; + break; + case WMI_VDEV_PPS_5G_EBT: + pps_val = ((privcmd->param_value << 31) & 0xffff0000) | + (PKT_PWR_SAVE_5G_EBT & 0xffff); + intr[vid].config.pps_params.ebt_5g = privcmd->param_value; + break; + default: + WMA_LOGE("Invalid param id 0x%x", privcmd->param_id); + break; + } + break; + + case QPOWER_CMD: + WMA_LOGD("QPOWER CLI CMD pid %d pval %d", privcmd->param_id, + privcmd->param_value); + switch (privcmd->param_id) { + case WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT: + WMA_LOGD("QPOWER CLI CMD:Ps Poll Cnt val %d", + privcmd->param_value); + /* Set the QPower Ps Poll Count */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-PsPollCnt Failed vdevId %d val %d", + vid, privcmd->param_value); + } else { + qparams->max_ps_poll_cnt = + privcmd->param_value; + } + break; + case WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE: + WMA_LOGD("QPOWER CLI CMD:Max Tx Before wake val %d", + privcmd->param_value); + /* Set the QPower Max Tx Before Wake */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-MaxTxBefWake Failed vId %d val %d", + vid, privcmd->param_value); + } else { + qparams->max_tx_before_wake = + privcmd->param_value; + } + break; + case WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + WMA_LOGD("QPOWER CLI CMD:Ps Poll Wake Inv val %d", + privcmd->param_value); + /* Set the QPower Spec Ps Poll Wake Inv */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-PsPoll WakeIntv Failed vId %d val %d", + vid, privcmd->param_value); + } else { + qparams->spec_ps_poll_wake_interval = + privcmd->param_value; + } + break; + case WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + WMA_LOGD("QPOWER CLI CMD:Spec NoData Ps Poll val %d", + privcmd->param_value); + /* Set the QPower Spec NoData PsPoll */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vid, + WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + privcmd->param_value); + if (ret) { + WMA_LOGE("Set Q-SpecNoDataPsPoll Failed vId %d val %d", + vid, privcmd->param_value); + } else { + qparams->max_spec_nodata_ps_poll = + privcmd->param_value; + } + break; + + default: + WMA_LOGE("Invalid param id 0x%x", privcmd->param_id); + break; + } + break; + case GTX_CMD: + WMA_LOGD("vdev id %d pid %d pval %d", privcmd->param_vdev_id, + privcmd->param_id, privcmd->param_value); + switch (privcmd->param_id) { + case WMI_VDEV_PARAM_GTX_HT_MCS: + intr[vid].config.gtx_info.gtxRTMask[0] = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + case WMI_VDEV_PARAM_GTX_VHT_MCS: + intr[vid].config.gtx_info.gtxRTMask[1] = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + + case WMI_VDEV_PARAM_GTX_USR_CFG: + intr[vid].config.gtx_info.gtxUsrcfg = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + + case WMI_VDEV_PARAM_GTX_THRE: + intr[vid].config.gtx_info.gtxPERThreshold = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + + case WMI_VDEV_PARAM_GTX_MARGIN: + intr[vid].config.gtx_info.gtxPERMargin = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + + case WMI_VDEV_PARAM_GTX_STEP: + intr[vid].config.gtx_info.gtxTPCstep = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + + case WMI_VDEV_PARAM_GTX_MINTPC: + intr[vid].config.gtx_info.gtxTPCMin = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + break; + + case WMI_VDEV_PARAM_GTX_BW_MASK: + intr[vid].config.gtx_info.gtxBWMask = privcmd->param_value; + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, + privcmd->param_vdev_id, + &intr[vid].config.gtx_info); + if (ret) { + WMA_LOGE("wmi_unified_vdev_set_param_send" + " failed ret %d", ret); + return; + } + break; + default: + break; + } + break; + + default: + WMA_LOGE("Invalid vpdev command id"); + } + if (1 == privcmd->param_vp_dev) { + switch (privcmd->param_id) { + case WMI_VDEV_PARAM_NSS: + intr[vid].config.nss = privcmd->param_value; + break; + case WMI_VDEV_PARAM_LDPC: + intr[vid].config.ldpc = privcmd->param_value; + break; + case WMI_VDEV_PARAM_TX_STBC: + intr[vid].config.tx_stbc = privcmd->param_value; + break; + case WMI_VDEV_PARAM_RX_STBC: + intr[vid].config.rx_stbc = privcmd->param_value; + break; + case WMI_VDEV_PARAM_SGI: + intr[vid].config.shortgi = privcmd->param_value; + break; + case WMI_VDEV_PARAM_ENABLE_RTSCTS: + intr[vid].config.rtscts_en = privcmd->param_value; + break; + case WMI_VDEV_PARAM_CHWIDTH: + intr[vid].config.chwidth = privcmd->param_value; + break; + case WMI_VDEV_PARAM_FIXED_RATE: + intr[vid].config.tx_rate = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_ADJUST_ENABLE: + intr[vid].config.erx_adjust = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_TGT_BMISS_NUM: + intr[vid].config.erx_bmiss_num = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_BMISS_SAMPLE_CYCLE: + intr[vid].config.erx_bmiss_cycle = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_SLOP_STEP: + intr[vid].config.erx_slop_step = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_INIT_SLOP: + intr[vid].config.erx_init_slop = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_ADJUST_PAUSE: + intr[vid].config.erx_adj_pause = privcmd->param_value; + break; + case WMI_VDEV_PARAM_EARLY_RX_DRIFT_SAMPLE: + intr[vid].config.erx_dri_sample = privcmd->param_value; + break; + default: + WMA_LOGE("Invalid wda_cli_set vdev command/Not" + " yet implemented 0x%x", privcmd->param_id); + break; + } + } else if (2 == privcmd->param_vp_dev) { + switch (privcmd->param_id) { + case WMI_PDEV_PARAM_ANI_ENABLE: + wma->pdevconfig.ani_enable = privcmd->param_value; + break; + case WMI_PDEV_PARAM_ANI_POLL_PERIOD: + wma->pdevconfig.ani_poll_len = privcmd->param_value; + break; + case WMI_PDEV_PARAM_ANI_LISTEN_PERIOD: + wma->pdevconfig.ani_listen_len = privcmd->param_value; + break; + case WMI_PDEV_PARAM_ANI_OFDM_LEVEL: + wma->pdevconfig.ani_ofdm_level = privcmd->param_value; + break; + case WMI_PDEV_PARAM_ANI_CCK_LEVEL: + wma->pdevconfig.ani_cck_level = privcmd->param_value; + break; + case WMI_PDEV_PARAM_DYNAMIC_BW: + wma->pdevconfig.cwmenable = privcmd->param_value; + break; + case WMI_PDEV_PARAM_CTS_CBW: + wma->pdevconfig.cts_cbw = privcmd->param_value; + break; + case WMI_PDEV_PARAM_TX_CHAIN_MASK: + wma->pdevconfig.txchainmask = privcmd->param_value; + break; + case WMI_PDEV_PARAM_RX_CHAIN_MASK: + wma->pdevconfig.rxchainmask = privcmd->param_value; + break; + case WMI_PDEV_PARAM_TX_CHAIN_MASK_2G: + case WMI_PDEV_PARAM_RX_CHAIN_MASK_2G: + wma->pdevconfig.chainmask_2g = privcmd->param_value; + break; + case WMI_PDEV_PARAM_TX_CHAIN_MASK_5G: + case WMI_PDEV_PARAM_RX_CHAIN_MASK_5G: + wma->pdevconfig.chainmask_5g = privcmd->param_value; + break; + case WMI_PDEV_PARAM_BURST_ENABLE: + wma->pdevconfig.burst_enable = privcmd->param_value; + if ((wma->pdevconfig.burst_enable == 1) && + (wma->pdevconfig.burst_dur == 0)) + wma->pdevconfig.burst_dur = WMA_DEFAULT_SIFS_BURST_DURATION; + else if (wma->pdevconfig.burst_enable == 0) + wma->pdevconfig.burst_dur = 0; + break; + case WMI_PDEV_PARAM_BURST_DUR: + wma->pdevconfig.burst_dur = privcmd->param_value; + break; + case WMI_PDEV_PARAM_TXPOWER_LIMIT2G: + wma->pdevconfig.txpow2g = privcmd->param_value; + if ((pMac->roam.configParam.bandCapability == + eCSR_BAND_ALL) || + (pMac->roam.configParam.bandCapability == + eCSR_BAND_24)) { + if (cfgSetInt(pMac, + WNI_CFG_CURRENT_TX_POWER_LEVEL, + privcmd->param_value) != eSIR_SUCCESS) { + WMA_LOGE("could not set" + " WNI_CFG_CURRENT_TX_POWER_LEVEL"); + } + } + else + WMA_LOGE("Current band is not 2G"); + break; + case WMI_PDEV_PARAM_TXPOWER_LIMIT5G: + wma->pdevconfig.txpow5g = privcmd->param_value; + if ((pMac->roam.configParam.bandCapability == + eCSR_BAND_ALL) || + (pMac->roam.configParam.bandCapability == + eCSR_BAND_5G)) { + if (cfgSetInt(pMac, + WNI_CFG_CURRENT_TX_POWER_LEVEL, + privcmd->param_value) != eSIR_SUCCESS) { + WMA_LOGE("could not set" + " WNI_CFG_CURRENT_TX_POWER_LEVEL"); + } + } + else + WMA_LOGE("Current band is not 5G"); + break; + default: + WMA_LOGE("Invalid wda_cli_set pdev command/Not" + " yet implemented 0x%x", privcmd->param_id); + break; + } + } else if (5 == privcmd->param_vp_dev) { + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, privcmd->param_vdev_id, + WMI_VDEV_PARAM_PACKET_POWERSAVE, + pps_val); + if (ret) + WMA_LOGE("Failed to send wmi packet power save cmd"); + else + WMA_LOGD("Sent packet power save cmd %d value %x to target", + privcmd->param_id, pps_val); + } +} + +int wma_cli_get_command(void *wmapvosContext, int vdev_id, + int param_id, int vpdev) +{ + int ret = 0; + tp_wma_handle wma; + struct wma_txrx_node *intr = NULL; + + wma = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, + wmapvosContext); + + if (NULL == wma) + { + WMA_LOGE("%s: Invalid wma handle", __func__); + return -EINVAL; + } + + intr = wma->interfaces; + + if (VDEV_CMD == vpdev) { + switch (param_id) { + case WMI_VDEV_PARAM_NSS: + ret = intr[vdev_id].config.nss; + break; +#ifdef QCA_SUPPORT_GTX + case WMI_VDEV_PARAM_GTX_HT_MCS: + ret = intr[vdev_id].config.gtx_info.gtxRTMask[0]; + break; + case WMI_VDEV_PARAM_GTX_VHT_MCS: + ret = intr[vdev_id].config.gtx_info.gtxRTMask[1]; + break; + case WMI_VDEV_PARAM_GTX_USR_CFG: + ret = intr[vdev_id].config.gtx_info.gtxUsrcfg; + break; + case WMI_VDEV_PARAM_GTX_THRE: + ret = intr[vdev_id].config.gtx_info.gtxPERThreshold; + break; + case WMI_VDEV_PARAM_GTX_MARGIN: + ret = intr[vdev_id].config.gtx_info.gtxPERMargin; + break; + case WMI_VDEV_PARAM_GTX_STEP: + ret = intr[vdev_id].config.gtx_info.gtxTPCstep; + break; + case WMI_VDEV_PARAM_GTX_MINTPC: + ret = intr[vdev_id].config.gtx_info.gtxTPCMin; + break; + case WMI_VDEV_PARAM_GTX_BW_MASK: + ret = intr[vdev_id].config.gtx_info.gtxBWMask; + break; +#endif + case WMI_VDEV_PARAM_LDPC: + ret = intr[vdev_id].config.ldpc; + break; + case WMI_VDEV_PARAM_TX_STBC: + ret = intr[vdev_id].config.tx_stbc; + break; + case WMI_VDEV_PARAM_RX_STBC: + ret = intr[vdev_id].config.rx_stbc; + break; + case WMI_VDEV_PARAM_SGI: + ret = intr[vdev_id].config.shortgi; + break; + case WMI_VDEV_PARAM_ENABLE_RTSCTS: + ret = intr[vdev_id].config.rtscts_en; + break; + case WMI_VDEV_PARAM_CHWIDTH: + ret = intr[vdev_id].config.chwidth; + break; + case WMI_VDEV_PARAM_FIXED_RATE: + ret = intr[vdev_id].config.tx_rate; + break; + default: + WMA_LOGE("Invalid cli_get vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } else if (PDEV_CMD == vpdev) { + switch (param_id) { + case WMI_PDEV_PARAM_ANI_ENABLE: + ret = wma->pdevconfig.ani_enable; + break; + case WMI_PDEV_PARAM_ANI_POLL_PERIOD: + ret = wma->pdevconfig.ani_poll_len; + break; + case WMI_PDEV_PARAM_ANI_LISTEN_PERIOD: + ret = wma->pdevconfig.ani_listen_len; + break; + case WMI_PDEV_PARAM_ANI_OFDM_LEVEL: + ret = wma->pdevconfig.ani_ofdm_level; + break; + case WMI_PDEV_PARAM_ANI_CCK_LEVEL: + ret = wma->pdevconfig.ani_cck_level; + break; + case WMI_PDEV_PARAM_DYNAMIC_BW: + ret = wma->pdevconfig.cwmenable; + break; + case WMI_PDEV_PARAM_CTS_CBW: + ret = wma->pdevconfig.cts_cbw; + break; + case WMI_PDEV_PARAM_TX_CHAIN_MASK: + ret = wma->pdevconfig.txchainmask; + break; + case WMI_PDEV_PARAM_RX_CHAIN_MASK: + ret = wma->pdevconfig.rxchainmask; + break; + case WMI_PDEV_PARAM_TXPOWER_LIMIT2G: + ret = wma->pdevconfig.txpow2g; + break; + case WMI_PDEV_PARAM_TXPOWER_LIMIT5G: + ret = wma->pdevconfig.txpow5g; + break; + case WMI_PDEV_PARAM_BURST_ENABLE: + ret = wma->pdevconfig.burst_enable; + break; + case WMI_PDEV_PARAM_BURST_DUR: + ret = wma->pdevconfig.burst_dur; + break; + default: + WMA_LOGE("Invalid cli_get pdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } else if (GEN_CMD == vpdev) { + switch (param_id) { + case GEN_VDEV_PARAM_AMPDU: + ret = intr[vdev_id].config.ampdu; + break; + case GEN_VDEV_PARAM_AMSDU: + ret = intr[vdev_id].config.amsdu; + break; + default: + WMA_LOGE("Invalid generic vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } else if (PPS_CMD == vpdev) { + switch (param_id) { + case WMI_VDEV_PPS_PAID_MATCH: + ret = intr[vdev_id].config.pps_params.paid_match_enable; + break; + case WMI_VDEV_PPS_GID_MATCH: + ret = intr[vdev_id].config.pps_params.gid_match_enable; + break; + case WMI_VDEV_PPS_EARLY_TIM_CLEAR: + ret = intr[vdev_id].config.pps_params.tim_clear; + break; + case WMI_VDEV_PPS_EARLY_DTIM_CLEAR: + ret = intr[vdev_id].config.pps_params.dtim_clear; + break; + case WMI_VDEV_PPS_EOF_PAD_DELIM: + ret = intr[vdev_id].config.pps_params.eof_delim; + break; + case WMI_VDEV_PPS_MACADDR_MISMATCH: + ret = intr[vdev_id].config.pps_params.mac_match; + break; + case WMI_VDEV_PPS_DELIM_CRC_FAIL: + ret = intr[vdev_id].config.pps_params.delim_fail; + break; + case WMI_VDEV_PPS_GID_NSTS_ZERO: + ret = intr[vdev_id].config.pps_params.nsts_zero; + break; + case WMI_VDEV_PPS_RSSI_CHECK: + ret = intr[vdev_id].config.pps_params.rssi_chk; + break; + default: + WMA_LOGE("Invalid pps vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } else if (QPOWER_CMD == vpdev) { + switch (param_id) { + case WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT: + ret = intr[vdev_id].config.qpower_params.max_ps_poll_cnt; + break; + + case WMI_STA_PS_PARAM_QPOWER_MAX_TX_BEFORE_WAKE: + ret = intr[vdev_id].config.qpower_params.max_tx_before_wake; + break; + + case WMI_STA_PS_PARAM_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL: + ret = + intr[vdev_id].config.qpower_params.spec_ps_poll_wake_interval; + break; + + case WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL: + ret = intr[vdev_id].config.qpower_params.max_spec_nodata_ps_poll; + break; + + default: + WMA_LOGE("Invalid generic vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } else if (GTX_CMD == vpdev) { + switch (param_id) { + case WMI_VDEV_PARAM_GTX_HT_MCS: + ret = intr[vdev_id].config.gtx_info.gtxRTMask[0]; + break; + case WMI_VDEV_PARAM_GTX_VHT_MCS: + ret = intr[vdev_id].config.gtx_info.gtxRTMask[1]; + break; + case WMI_VDEV_PARAM_GTX_USR_CFG: + ret = intr[vdev_id].config.gtx_info.gtxUsrcfg; + break; + case WMI_VDEV_PARAM_GTX_THRE: + ret = intr[vdev_id].config.gtx_info.gtxPERThreshold; + break; + case WMI_VDEV_PARAM_GTX_MARGIN: + ret = intr[vdev_id].config.gtx_info.gtxPERMargin; + break; + case WMI_VDEV_PARAM_GTX_STEP: + ret = intr[vdev_id].config.gtx_info.gtxTPCstep; + break; + case WMI_VDEV_PARAM_GTX_MINTPC: + ret = intr[vdev_id].config.gtx_info.gtxTPCMin; + break; + case WMI_VDEV_PARAM_GTX_BW_MASK: + ret = intr[vdev_id].config.gtx_info.gtxBWMask; + break; + default: + WMA_LOGE("Invalid generic vdev command/Not" + " yet implemented 0x%x", param_id); + return -EINVAL; + } + } + return ret; +} + +/** + * wma_process_set_pdev_ht_ie_req() - sends HT IE data to FW + * + * @wma: Pointer to wma handle + * @ie_params: Pointer to IE data. + * @nss: Nss values to prepare the HT IE. + * + * Sends the WMI req to set the HT IE to FW. + * + * Return: None + */ +void wma_process_set_pdev_ht_ie_req(tp_wma_handle wma, + struct set_ie_param *ie_params) +{ + int ret; + wmi_pdev_set_ht_ie_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len; + u_int16_t ie_len_pad; + u_int8_t *buf_ptr; + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; + ie_len_pad = roundup(ie_params->ie_len, sizeof(u_int32_t)); + len += ie_len_pad; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return; + } + cmd = (wmi_pdev_set_ht_ie_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_set_ht_ie_cmd_fixed_param)); + cmd->reserved0 = 0; + cmd->ie_len = ie_params->ie_len; + cmd->tx_streams = ie_params->nss; + cmd->rx_streams = ie_params->nss; + WMA_LOGD("Setting pdev HT ie with Nss = %u", + ie_params->nss); + buf_ptr = (u_int8_t *)cmd + sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad); + if (ie_params->ie_len) { + vos_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, + (u_int8_t *)ie_params->ie_ptr, + ie_params->ie_len); + } + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PDEV_SET_HT_CAP_IE_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send set param command ret = %d", ret); + wmi_buf_free(buf); + } +} + +/** + * wma_process_set_pdev_vht_ie_req() - sends VHT IE data to FW + * + * @wma: Pointer to wma handle + * @ie_params: Pointer to IE data. + * @nss: Nss values to prepare the VHT IE. + * + * Sends the WMI req to set the VHT IE to FW. + * + * Return: None + */ +void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma, + struct set_ie_param *ie_params) +{ + int ret; + wmi_pdev_set_vht_ie_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len; + u_int16_t ie_len_pad; + u_int8_t *buf_ptr; + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; + ie_len_pad = roundup(ie_params->ie_len, sizeof(u_int32_t)); + len += ie_len_pad; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return; + } + cmd = (wmi_pdev_set_vht_ie_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_set_vht_ie_cmd_fixed_param)); + cmd->reserved0 = 0; + cmd->ie_len = ie_params->ie_len; + cmd->tx_streams = ie_params->nss; + cmd->rx_streams = ie_params->nss; + WMA_LOGD("Setting pdev VHT ie with Nss = %u", + ie_params->nss); + buf_ptr = (u_int8_t *)cmd + sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad); + if (ie_params->ie_len) { + vos_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, + (u_int8_t *)ie_params->ie_ptr, + ie_params->ie_len); + } + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PDEV_SET_VHT_CAP_IE_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send set param command ret = %d", ret); + wmi_buf_free(buf); + } +} + +/** + * wma_process_set_pdev_ie_req() - process the pdev set IE req + * + * @wma: Pointer to wma handle + * @ie_params: Pointer to IE data. + * + * Sends the WMI req to set the IE to FW. + * + * Return: None + */ +void wma_process_set_pdev_ie_req(tp_wma_handle wma, + struct set_ie_param *ie_params) +{ + if (ie_params->ie_type == DOT11_HT_IE) + wma_process_set_pdev_ht_ie_req(wma, ie_params); + if (ie_params->ie_type == DOT11_VHT_IE) + wma_process_set_pdev_vht_ie_req(wma, ie_params); + + vos_mem_free(ie_params->ie_ptr); +} + +static void +wma_update_protection_mode(tp_wma_handle wma, u_int8_t vdev_id, + u_int8_t llbcoexist) +{ + int ret; + enum ieee80211_protmode prot_mode; + + prot_mode = llbcoexist ? IEEE80211_PROT_CTSONLY : IEEE80211_PROT_NONE; + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_PROTECTION_MODE, + prot_mode); + + if (ret) + WMA_LOGE("Failed to send wmi protection mode cmd"); + else + WMA_LOGD("Updated protection mode %d to target", prot_mode); +} + +static void +wma_update_beacon_interval(tp_wma_handle wma, u_int8_t vdev_id, + u_int16_t beaconInterval) +{ + int ret; + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_BEACON_INTERVAL, + beaconInterval); + + if (ret) + WMA_LOGE("Failed to update beacon interval"); + else + WMA_LOGI("Updated beacon interval %d for vdev %d", beaconInterval, vdev_id); +} + + +/* + * Function : wma_process_update_beacon_params + * Description : update the beacon parameters to target + * Args : wma handle, beacon parameters + * Returns : None + */ +static void +wma_process_update_beacon_params(tp_wma_handle wma, + tUpdateBeaconParams *bcn_params) +{ + if (!bcn_params) { + WMA_LOGE("bcn_params NULL"); + return; + } + + if (bcn_params->smeSessionId >= wma->max_bssid) { + WMA_LOGE("Invalid vdev id %d", bcn_params->smeSessionId); + return; + } + + if (bcn_params->paramChangeBitmap & PARAM_BCN_INTERVAL_CHANGED) { + wma_update_beacon_interval(wma, bcn_params->smeSessionId, + bcn_params->beaconInterval); + } + + if (bcn_params->paramChangeBitmap & PARAM_llBCOEXIST_CHANGED) + wma_update_protection_mode(wma, bcn_params->smeSessionId, + bcn_params->llbCoexist); +} + +/* + * Function : wma_update_cfg_params + * Description : update the cfg parameters to target + * Args : wma handle, cfg parameter + * Returns : None + */ +static void +wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam) +{ + u_int8_t vdev_id; + u_int32_t param_id; + tANI_U32 cfg_val; + int ret; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *pmac; + + switch(cfgParam->bodyval) { + case WNI_CFG_RTS_THRESHOLD: + param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; + break; + case WNI_CFG_FRAGMENTATION_THRESHOLD: + param_id = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD; + break; + default: + WMA_LOGD("Unhandled cfg parameter %d", cfgParam->bodyval); + return; + } + + pmac = (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + + if (NULL == pmac) { + WMA_LOGE("%s: Failed to get pmac", __func__); + return; + } + + if (wlan_cfgGetInt(pmac, (tANI_U16) cfgParam->bodyval, + &cfg_val) != eSIR_SUCCESS) + { + WMA_LOGE("Failed to get value for CFG PARAMS %d. returning without updating", + cfgParam->bodyval); + return; + } + + for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { + if (wma->interfaces[vdev_id].handle != 0) { + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + vdev_id, param_id, cfg_val); + if (ret) + WMA_LOGE("Update cfg params failed for vdevId %d", vdev_id); + } + } +} + +/* BSS set params functions */ +static void +wma_vdev_set_bss_params(tp_wma_handle wma, int vdev_id, + tSirMacBeaconInterval beaconInterval, tANI_U8 dtimPeriod, + tANI_U8 shortSlotTimeSupported, tANI_U8 llbCoexist, + tPowerdBm maxTxPower) +{ + int ret; + uint32_t slot_time; + struct wma_txrx_node *intr = wma->interfaces; + + /* Beacon Interval setting */ + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_BEACON_INTERVAL, + beaconInterval); + + if (ret) + WMA_LOGE("failed to set WMI_VDEV_PARAM_BEACON_INTERVAL"); + + ret = wmi_unified_vdev_set_gtx_cfg_send(wma->wmi_handle, vdev_id, + &intr[vdev_id].config.gtx_info); + if (ret) + WMA_LOGE("failed to set WMI_VDEV_PARAM_DTIM_PERIOD"); + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_DTIM_PERIOD, + dtimPeriod); + if (ret) + WMA_LOGE("failed to set WMI_VDEV_PARAM_DTIM_PERIOD"); + + if (!maxTxPower) + { + WMA_LOGW("Setting Tx power limit to 0"); + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TX_PWRLIMIT, + maxTxPower); + if (ret) + WMA_LOGE("failed to set WMI_VDEV_PARAM_TX_PWRLIMIT"); + else + intr[vdev_id].max_tx_power = maxTxPower; + + /* Slot time */ + if (shortSlotTimeSupported) + slot_time = WMI_VDEV_SLOT_TIME_SHORT; + else + slot_time = WMI_VDEV_SLOT_TIME_LONG; + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_SLOT_TIME, + slot_time); + if (ret) + WMA_LOGE("failed to set WMI_VDEV_PARAM_SLOT_TIME"); + + /* Initialize protection mode in case of coexistence */ + wma_update_protection_mode(wma, vdev_id, llbCoexist); +} + +static void wma_add_bss_ap_mode(tp_wma_handle wma, tpAddBssParams add_bss) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + struct wma_vdev_start_req req; + ol_txrx_peer_handle peer; + struct wma_target_req *msg; + u_int8_t vdev_id, peer_id; + VOS_STATUS status; + tPowerdBm maxTxPower; +#ifdef WLAN_FEATURE_11W + int ret = 0; +#endif /* WLAN_FEATURE_11W */ + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + goto send_fail_resp; + } + + vdev = wma_find_vdev_by_addr(wma, add_bss->bssId, &vdev_id); + if (!vdev) { + WMA_LOGE("%s: Failed to get vdev handle", __func__); + goto send_fail_resp; + } + + wma->interfaces[vdev_id].wps_state = add_bss->wps_state; + wma_set_bss_rate_flags(&wma->interfaces[vdev_id], add_bss); + status = wma_create_peer(wma, pdev, vdev, add_bss->bssId, + WMI_PEER_TYPE_DEFAULT, vdev_id, + VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to create peer", __func__); + goto send_fail_resp; + } + + peer = ol_txrx_find_peer_by_addr(pdev, add_bss->bssId, &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + add_bss->bssId); + goto send_fail_resp; + } + msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, + WMA_TARGET_REQ_TYPE_VDEV_START, add_bss, + WMA_VDEV_START_REQUEST_TIMEOUT); + if (!msg) { + WMA_LOGP("%s Failed to allocate vdev request vdev_id %d", + __func__, vdev_id); + goto peer_cleanup; + } + + add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); + + vos_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + req.chan = add_bss->currentOperChannel; + req.chan_offset = add_bss->currentExtChannel; + req.vht_capable = add_bss->vhtCapable; +#if defined WLAN_FEATURE_VOWIFI + req.max_txpow = add_bss->maxTxPower; + maxTxPower = add_bss->maxTxPower; +#else + req.max_txpow = 0; + maxTxPower = 0; +#endif +#ifdef WLAN_FEATURE_11W + if (add_bss->rmfEnabled) { + /* + * when 802.11w PMF is enabled for hw encr/decr + * use hw MFP Qos bits 0x10 + */ + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_PMF_QOS, TRUE); + if(ret) { + WMA_LOGE("%s: Failed to set QOS MFP/PMF (%d)", + __func__, ret); + } else { + WMA_LOGI("%s: QOS MFP/PMF set to %d", + __func__, TRUE); + } + } +#endif /* WLAN_FEATURE_11W */ + + req.beacon_intval = add_bss->beaconInterval; + req.dtim_period = add_bss->dtimPeriod; + req.hidden_ssid = add_bss->bHiddenSSIDEn; + req.is_dfs = add_bss->bSpectrumMgtEnabled; + req.oper_mode = BSS_OPERATIONAL_MODE_AP; + req.ssid.length = add_bss->ssId.length; + if (req.ssid.length > 0) + vos_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, + add_bss->ssId.length); + + status = wma_vdev_start(wma, &req, VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + goto peer_cleanup; + } + + wma_vdev_set_bss_params(wma, vdev_id, + add_bss->beaconInterval, add_bss->dtimPeriod, + add_bss->shortSlotTimeSupported, add_bss->llbCoexist, + maxTxPower); + + return; + +peer_cleanup: + wma_remove_peer(wma, add_bss->bssId, vdev_id, peer, + VOS_FALSE); +send_fail_resp: + add_bss->status = VOS_STATUS_E_FAILURE; + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)add_bss, 0); +} + +#ifdef QCA_IBSS_SUPPORT +static VOS_STATUS +wma_set_ibss_pwrsave_params(tp_wma_handle wma, u_int8_t vdev_id) +{ + int ret; + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH, + wma->wma_ibss_power_save_params.atimWindowLength); + if (ret < 0) { + WMA_LOGE("Failed to set WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH ret = %d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED, + wma->wma_ibss_power_save_params.isPowerSaveAllowed); + if (ret < 0) { + WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED, + wma->wma_ibss_power_save_params.isPowerCollapseAllowed); + if (ret < 0) { + WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED, + wma->wma_ibss_power_save_params.isAwakeonTxRxEnabled); + if (ret < 0) { + WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_INACTIVITY_CNT, + wma->wma_ibss_power_save_params.inactivityCount); + if (ret < 0) { + WMA_LOGE("Failed, set WMI_VDEV_PARAM_INACTIVITY_CNT ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS, + wma->wma_ibss_power_save_params.txSPEndInactivityTime); + if (ret < 0) { + WMA_LOGE("Failed, set WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS, + wma->wma_ibss_power_save_params.ibssPsWarmupTime); + if (ret < 0) { + WMA_LOGE("Failed, set WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE, + wma->wma_ibss_power_save_params.ibssPs1RxChainInAtimEnable); + if (ret < 0) { + WMA_LOGE("Failed to set IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE ret=%d", + ret); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + struct wma_vdev_start_req req; + ol_txrx_peer_handle peer = NULL; + struct wma_target_req *msg; + u_int8_t vdev_id, peer_id; + VOS_STATUS status; + tDelStaSelfParams del_sta_param; + tAddStaSelfParams add_sta_self_param; + tSetBssKeyParams key_info; + u_int8_t nss_2g, nss_5g; + + WMA_LOGD("%s: add_bss->sessionId = %d", __func__, add_bss->sessionId); + vdev_id = add_bss->sessionId; + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + goto send_fail_resp; + } + + nss_2g = wma->interfaces[vdev_id].nss_2g; + nss_5g = wma->interfaces[vdev_id].nss_5g; + wma_set_bss_rate_flags(&wma->interfaces[vdev_id], add_bss); + + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("%s: vdev not found for vdev id %d.", + __func__, vdev_id); + goto send_fail_resp; + } + + /* only change vdev type to ibss during 1st time join_ibss handling */ + + if (FALSE == wma_is_vdev_in_ibss_mode(wma, vdev_id)) { + + WMA_LOGD("%s: vdev found for vdev id %d. deleting the vdev", + __func__, vdev_id); + + /* remove peers on the existing non-ibss vdev */ + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + WMA_LOGE("%s: peer found for vdev id %d. deleting the peer", + __func__, vdev_id); + wma_remove_peer(wma, (u_int8_t *)&vdev->mac_addr, + vdev_id, peer, VOS_FALSE); + } + + /* remove the non-ibss vdev */ + vos_copy_macaddr((v_MACADDR_t *)&(del_sta_param.selfMacAddr), + (v_MACADDR_t *)&(vdev->mac_addr)); + del_sta_param.sessionId = vdev_id; + del_sta_param.status = 0; + + wma_vdev_detach(wma, &del_sta_param, 0); + + /* create new vdev for ibss */ + vos_copy_macaddr((v_MACADDR_t *)&(add_sta_self_param.selfMacAddr), + (v_MACADDR_t *)&(add_bss->selfMacAddr)); + add_sta_self_param.sessionId = vdev_id; + add_sta_self_param.type = WMI_VDEV_TYPE_IBSS; + add_sta_self_param.subType = 0; + add_sta_self_param.status = 0; + add_sta_self_param.nss_2g = add_bss->nss_2g; + add_sta_self_param.nss_5g = add_bss->nss_5g; + + vdev = wma_vdev_attach(wma, &add_sta_self_param, 0); + if (!vdev) { + WMA_LOGE("%s: Failed to create vdev", __func__); + goto send_fail_resp; + } + + WLANTL_RegisterVdev(wma->vos_context, vdev); + /* Register with TxRx Module for Data Ack Complete Cb */ + wdi_in_data_tx_cb_set(vdev, wma_data_tx_ack_comp_hdlr, wma); + WMA_LOGA("new IBSS vdev created with mac %pM", add_bss->selfMacAddr); + + /* create ibss bss peer */ + status = wma_create_peer(wma, pdev, vdev, add_bss->selfMacAddr, + WMI_PEER_TYPE_DEFAULT, vdev_id, + VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to create peer", __func__); + goto send_fail_resp; + } + WMA_LOGA("IBSS BSS peer created with mac %pM", add_bss->selfMacAddr); + } + + peer = ol_txrx_find_peer_by_addr(pdev, add_bss->selfMacAddr, &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + add_bss->selfMacAddr); + goto send_fail_resp; + } + + /* clear leftover ibss keys on bss peer */ + + WMA_LOGD("%s: ibss bss key clearing", __func__); + vos_mem_set(&key_info, sizeof(key_info), 0); + key_info.smesessionId = vdev_id; + key_info.numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + vos_mem_copy(&wma->ibsskey_info, &key_info, sizeof(tSetBssKeyParams)); + + /* start ibss vdev */ + + add_bss->operMode = BSS_OPERATIONAL_MODE_IBSS; + + msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, + WMA_TARGET_REQ_TYPE_VDEV_START, add_bss, + WMA_VDEV_START_REQUEST_TIMEOUT); + if (!msg) { + WMA_LOGP("%s Failed to allocate vdev request vdev_id %d", + __func__, vdev_id); + goto peer_cleanup; + } + WMA_LOGD("%s: vdev start request for IBSS enqueued", __func__); + + add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); + + /* + * If IBSS Power Save is supported by firmware + * set the IBSS power save params to firmware. + */ + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_IBSS_PWRSAVE)) { + status = wma_set_ibss_pwrsave_params(wma, vdev_id); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to Set IBSS Power Save Params to firmware", + __func__); + goto peer_cleanup; + } + } + + + vos_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + req.chan = add_bss->currentOperChannel; + req.chan_offset = add_bss->currentExtChannel; + req.vht_capable = add_bss->vhtCapable; +#if defined WLAN_FEATURE_VOWIF + req.max_txpow = add_bss->maxTxPower; +#else + req.max_txpow = 0; +#endif + req.beacon_intval = add_bss->beaconInterval; + req.dtim_period = add_bss->dtimPeriod; + req.hidden_ssid = add_bss->bHiddenSSIDEn; + req.is_dfs = add_bss->bSpectrumMgtEnabled; + req.oper_mode = BSS_OPERATIONAL_MODE_IBSS; + req.ssid.length = add_bss->ssId.length; + if (req.ssid.length > 0) + vos_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, + add_bss->ssId.length); + + WMA_LOGD("%s: chan %d chan_offset %d", __func__, req.chan, req.chan_offset); + WMA_LOGD("%s: ssid = %s", __func__, req.ssid.ssId); + + status = wma_vdev_start(wma, &req, VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + goto peer_cleanup; + } + WMA_LOGD("%s: vdev start request for IBSS sent to target", __func__); + + /* Initialize protection mode to no protection */ + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_PROTECTION_MODE, + IEEE80211_PROT_NONE)) { + WMA_LOGE("Failed to initialize protection mode"); + } + + return; + +peer_cleanup: + if (peer) { + wma_remove_peer(wma, add_bss->bssId, vdev_id, peer, + VOS_FALSE); + } +send_fail_resp: + add_bss->status = VOS_STATUS_E_FAILURE; + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)add_bss, 0); +} +#endif + +static void wma_set_bss_rate_flags(struct wma_txrx_node *iface, + tpAddBssParams add_bss) +{ + iface->rate_flags = 0; + +#ifdef WLAN_FEATURE_11AC + if (add_bss->vhtCapable) { + if (add_bss->vhtTxChannelWidthSet) + iface->rate_flags |= eHAL_TX_RATE_VHT80; + else if (add_bss->txChannelWidthSet) + iface->rate_flags |= eHAL_TX_RATE_VHT40; + else + iface->rate_flags |= eHAL_TX_RATE_VHT20; + } + /* avoid to conflict with htCapable flag */ + else +#endif + if (add_bss->htCapable) { + if (add_bss->txChannelWidthSet) + iface->rate_flags |= eHAL_TX_RATE_HT40; + else + iface->rate_flags |= eHAL_TX_RATE_HT20; + } + + if (add_bss->staContext.fShortGI20Mhz || + add_bss->staContext.fShortGI40Mhz) + iface->rate_flags |= eHAL_TX_RATE_SGI; + + if (!add_bss->htCapable && !add_bss->vhtCapable) + iface->rate_flags = eHAL_TX_RATE_LEGACY; +} + +static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss) +{ + ol_txrx_pdev_handle pdev; + struct wma_vdev_start_req req; + struct wma_target_req *msg; + u_int8_t vdev_id, peer_id; + ol_txrx_peer_handle peer; + VOS_STATUS status; + struct wma_txrx_node *iface; + int ret = 0; + int pps_val = 0; + v_BOOL_t roam_synch_in_progress = VOS_FALSE; + tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + goto send_fail_resp; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s Failed to get pdev", __func__); + goto send_fail_resp; + } + + vdev_id = add_bss->staContext.smesessionId; + iface = &wma->interfaces[vdev_id]; + + wma_set_bss_rate_flags(iface, add_bss); + if (add_bss->operMode) { + // Save parameters later needed by WDA_ADD_STA_REQ + if (iface->addBssStaContext) { + adf_os_mem_free(iface->addBssStaContext); + } + iface->addBssStaContext = adf_os_mem_alloc(NULL, sizeof(tAddStaParams)); + if (!iface->addBssStaContext) { + WMA_LOGE("%s Failed to allocat memory", __func__); + goto send_fail_resp; + } + adf_os_mem_copy(iface->addBssStaContext, &add_bss->staContext, + sizeof(tAddStaParams)); + +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) { + adf_os_mem_free(iface->staKeyParams); + iface->staKeyParams = NULL; + } + if (add_bss->extSetStaKeyParamValid) { + iface->staKeyParams = adf_os_mem_alloc(NULL, sizeof(tSetStaKeyParams)); + if (!iface->staKeyParams) { + WMA_LOGE("%s Failed to allocat memory", __func__); + goto send_fail_resp; + } + adf_os_mem_copy(iface->staKeyParams, &add_bss->extSetStaKeyParam, + sizeof(tSetStaKeyParams)); + } +#endif + // Save parameters later needed by WDA_ADD_STA_REQ + iface->rmfEnabled = add_bss->rmfEnabled; + iface->beaconInterval = add_bss->beaconInterval; + iface->dtimPeriod = add_bss->dtimPeriod; + iface->llbCoexist = add_bss->llbCoexist; + iface->shortSlotTimeSupported = add_bss->shortSlotTimeSupported; + iface->nwType = add_bss->nwType; + if(add_bss->nonRoamReassoc) { + peer = ol_txrx_find_peer_by_addr(pdev, add_bss->bssId, &peer_id); + if(peer) { + add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); + goto send_bss_resp; + } + } + if (add_bss->reassocReq) { +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + ol_txrx_vdev_handle vdev; +#endif + // Called in preassoc state. BSSID peer is already added by set_linkstate + peer = ol_txrx_find_peer_by_addr(pdev, add_bss->bssId, &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + add_bss->bssId); + goto send_fail_resp; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(iface->roam_synch_in_progress) { + add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); + goto send_bss_resp; + } +#endif + msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, + WMA_TARGET_REQ_TYPE_VDEV_START, + add_bss, + WMA_VDEV_START_REQUEST_TIMEOUT); + if (!msg) { + WMA_LOGP("%s Failed to allocate vdev request vdev_id %d", + __func__, vdev_id); + goto peer_cleanup; + } + + add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); + + vos_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + req.chan = add_bss->currentOperChannel; + req.chan_offset = add_bss->currentExtChannel; +#if defined WLAN_FEATURE_VOWIFI + req.max_txpow = add_bss->maxTxPower; +#else + req.max_txpow = 0; +#endif + req.beacon_intval = add_bss->beaconInterval; + req.dtim_period = add_bss->dtimPeriod; + req.hidden_ssid = add_bss->bHiddenSSIDEn; + req.is_dfs = add_bss->bSpectrumMgtEnabled; + req.ssid.length = add_bss->ssId.length; + req.oper_mode = BSS_OPERATIONAL_MODE_STA; + if (req.ssid.length > 0) + vos_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, + add_bss->ssId.length); + + status = wma_vdev_start(wma, &req, VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + goto peer_cleanup; + } +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("%s Invalid txrx vdev", __func__); + goto peer_cleanup; + } + wdi_in_vdev_pause(vdev, + OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED); +#endif + // ADD_BSS_RESP will be deferred to completion of VDEV_START + + return; + } + if (!add_bss->updateBss) { + goto send_bss_resp; + + } + /* Update peer state */ + if (add_bss->staContext.encryptType == eSIR_ED_NONE) { + WMA_LOGD("%s: Update peer(%pM) state into auth", + __func__, add_bss->bssId); + ol_txrx_peer_state_update(pdev, add_bss->bssId, + ol_txrx_peer_state_auth); + } else { +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + ol_txrx_vdev_handle vdev; +#endif + WMA_LOGD("%s: Update peer(%pM) state into conn", + __func__, add_bss->bssId); + ol_txrx_peer_state_update(pdev, add_bss->bssId, + ol_txrx_peer_state_conn); +#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + peer = ol_txrx_find_peer_by_addr(pdev, add_bss->bssId, &peer_id); + if (!peer) { + WMA_LOGE("%s:%d Failed to find peer %pM", __func__, + __LINE__, add_bss->bssId); + goto send_fail_resp; + } + + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("%s Invalid txrx vdev", __func__); + goto peer_cleanup; + } + wdi_in_vdev_pause(vdev, + OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED); +#endif + } + + wmi_unified_send_txbf(wma, &add_bss->staContext); + + pps_val = ((pMac->enable5gEBT << 31) & 0xffff0000) | (PKT_PWR_SAVE_5G_EBT & 0xffff); + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_PACKET_POWERSAVE, + pps_val); + if (ret) + WMA_LOGE("Failed to send wmi packet power save cmd"); + else + WMA_LOGD("Sent PKT_PWR_SAVE_5G_EBT cmd to target, val = %x, ret = %d", + pps_val, ret); + + wmi_unified_send_peer_assoc(wma, add_bss->nwType, + &add_bss->staContext); +#ifdef WLAN_FEATURE_11W + if (add_bss->rmfEnabled) { + /* when 802.11w PMF is enabled for hw encr/decr + use hw MFP Qos bits 0x10 */ + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_PMF_QOS, TRUE); + if(ret) { + WMA_LOGE("%s: Failed to set QOS MFP/PMF (%d)", + __func__, ret); + } else { + WMA_LOGI("%s: QOS MFP/PMF set to %d", + __func__, TRUE); + } + } +#endif /* WLAN_FEATURE_11W */ + + wma_vdev_set_bss_params(wma, add_bss->staContext.smesessionId, + add_bss->beaconInterval, add_bss->dtimPeriod, + add_bss->shortSlotTimeSupported, add_bss->llbCoexist, + add_bss->maxTxPower); + + /* + * Store the bssid in interface table, bssid will + * be used during group key setting sta mode. + */ + vos_mem_copy(iface->bssid, add_bss->bssId, ETH_ALEN); + + } +send_bss_resp: + ol_txrx_find_peer_by_addr(pdev, add_bss->bssId, + &add_bss->staContext.staIdx); + add_bss->status = (add_bss->staContext.staIdx < 0) ? + VOS_STATUS_E_FAILURE : VOS_STATUS_SUCCESS; + add_bss->bssIdx = add_bss->staContext.smesessionId; + vos_mem_copy(add_bss->staContext.staMac, add_bss->bssId, + sizeof(add_bss->staContext.staMac)); + WMA_LOGD("%s: opermode %d update_bss %d nw_type %d bssid %pM" + " staIdx %d status %d", __func__, add_bss->operMode, + add_bss->updateBss, add_bss->nwType, add_bss->bssId, + add_bss->staContext.staIdx, add_bss->status); + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)add_bss, 0); + return; + +peer_cleanup: + wma_remove_peer(wma, add_bss->bssId, vdev_id, peer, + roam_synch_in_progress); +send_fail_resp: + add_bss->status = VOS_STATUS_E_FAILURE; + wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)add_bss, 0); +} + +static void wma_add_bss(tp_wma_handle wma, tpAddBssParams params) +{ + WMA_LOGD("%s: add_bss_param.halPersona = %d", + __func__, params->halPersona); + + switch(params->halPersona) { + + case VOS_STA_SAP_MODE: + /*If current bring up SAP channel matches the previous + *radar found channel then reset the last_radar_found_chan + *variable to avoid race conditions. + */ + if (params->currentOperChannel == + wma->dfs_ic->last_radar_found_chan) + wma->dfs_ic->last_radar_found_chan = 0; + case VOS_P2P_GO_MODE: + /*If current bring up P2P channel matches the previous + *radar found channel then reset the last_radar_found_chan + *variable to avoid race conditions. + */ + if (params->currentOperChannel == + wma->dfs_ic->last_radar_found_chan) + wma->dfs_ic->last_radar_found_chan = 0; + wma_add_bss_ap_mode(wma, params); + break; + +#ifdef QCA_IBSS_SUPPORT + case VOS_IBSS_MODE: + wma_add_bss_ibss_mode(wma, params); + break; +#endif + + default: + wma_add_bss_sta_mode(wma, params); + break; + } +} + +static int wmi_unified_vdev_up_send(wmi_unified_t wmi, + u_int8_t vdev_id, u_int16_t aid, + u_int8_t bssid[IEEE80211_ADDR_LEN]) +{ + wmi_vdev_up_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + WMA_LOGD("%s: VDEV_UP", __func__); + WMA_LOGD("%s: vdev_id %d aid %d bssid %pM", __func__, + vdev_id, aid, bssid); + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_vdev_up_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_up_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_up_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->vdev_assoc_id = aid; + WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid, &cmd->vdev_bssid); + if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_UP_CMDID)) { + WMA_LOGP("%s: Failed to send vdev up command", __func__); + adf_nbuf_free(buf); + return -EIO; + } + return 0; +} + +static int32_t wmi_unified_set_ap_ps_param(void *wma_ctx, u_int32_t vdev_id, + u_int8_t *peer_addr, u_int32_t param, u_int32_t value) +{ + tp_wma_handle wma_handle = (tp_wma_handle) wma_ctx; + wmi_ap_ps_peer_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_ap_ps_param cmd"); + return -ENOMEM; + } + cmd = (wmi_ap_ps_peer_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ap_ps_peer_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ap_ps_peer_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr); + cmd->param = param; + cmd->value = value; + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_AP_PS_PEER_PARAM_CMDID); + if (err) { + WMA_LOGE("Failed to send set_ap_ps_param cmd"); + adf_os_mem_free(buf); + return -EIO; + } + return 0; +} + +static int32_t wma_set_ap_peer_uapsd(tp_wma_handle wma, u_int32_t vdev_id, + u_int8_t *peer_addr, u_int8_t uapsd_value, u_int8_t max_sp) +{ + u_int32_t uapsd = 0; + u_int32_t max_sp_len = 0; + int32_t ret = 0; + + if (uapsd_value & UAPSD_VO_ENABLED) { + uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC3_TRIGGER_EN; + } + + if (uapsd_value & UAPSD_VI_ENABLED) { + uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC2_TRIGGER_EN; + } + + if (uapsd_value & UAPSD_BK_ENABLED) { + uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC1_TRIGGER_EN; + } + + if (uapsd_value & UAPSD_BE_ENABLED) { + uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC0_TRIGGER_EN; + } + + switch (max_sp) { + case UAPSD_MAX_SP_LEN_2: + max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_2; + break; + case UAPSD_MAX_SP_LEN_4: + max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_4; + break; + case UAPSD_MAX_SP_LEN_6: + max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_6; + break; + default: + max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED; + break; + } + + WMA_LOGD("Set WMI_AP_PS_PEER_PARAM_UAPSD 0x%x for %pM", + uapsd, peer_addr); + + ret = wmi_unified_set_ap_ps_param(wma, vdev_id, + peer_addr, + WMI_AP_PS_PEER_PARAM_UAPSD, + uapsd); + if (ret) { + WMA_LOGE("Failed to set WMI_AP_PS_PEER_PARAM_UAPSD for %pM", + peer_addr); + return ret; + } + + WMA_LOGD("Set WMI_AP_PS_PEER_PARAM_MAX_SP 0x%x for %pM", + max_sp_len, peer_addr); + + ret = wmi_unified_set_ap_ps_param(wma, vdev_id, + peer_addr, + WMI_AP_PS_PEER_PARAM_MAX_SP, + max_sp_len); + if (ret) { + WMA_LOGE("Failed to set WMI_AP_PS_PEER_PARAM_MAX_SP for %pM", + peer_addr); + return ret; + } + return 0; +} + +static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta) +{ + enum ol_txrx_peer_state state = ol_txrx_peer_state_conn; + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer; + u_int8_t peer_id; + VOS_STATUS status; + int32_t ret; + struct wma_txrx_node *iface = NULL; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + add_sta->status = VOS_STATUS_E_FAILURE; + goto send_rsp; + } + /* UMAC sends WDA_ADD_STA_REQ msg twice to WMA when the station + * associates. First WDA_ADD_STA_REQ will have staType as + * STA_ENTRY_PEER and second posting will have STA_ENTRY_SELF. + * Peer creation is done in first WDA_ADD_STA_REQ and second + * WDA_ADD_STA_REQ which has STA_ENTRY_SELF is ignored and + * send fake response with success to UMAC. Otherwise UMAC + * will get blocked. + */ + if (add_sta->staType != STA_ENTRY_PEER) { + add_sta->status = VOS_STATUS_SUCCESS; + goto send_rsp; + } + + vdev = wma_find_vdev_by_id(wma, add_sta->smesessionId); + if (!vdev) { + WMA_LOGE("%s: Failed to find vdev", __func__); + add_sta->status = VOS_STATUS_E_FAILURE; + goto send_rsp; + } + + iface = &wma->interfaces[vdev->vdev_id]; + peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, + vdev, + add_sta->staMac, + &peer_id); + if (peer) { + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, + peer, VOS_FALSE); + WMA_LOGE("%s: Peer already exists, Deleted peer with peer_addr %pM", + __func__, add_sta->staMac); + } + + status = wma_create_peer(wma, pdev, vdev, add_sta->staMac, + WMI_PEER_TYPE_DEFAULT, add_sta->smesessionId, + VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to create peer for %pM", + __func__, add_sta->staMac); + add_sta->status = status; + goto send_rsp; + } + + peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, + vdev, + add_sta->staMac, + &peer_id); + if (!peer) { + WMA_LOGE("%s: Failed to find peer handle using peer mac %pM", + __func__, add_sta->staMac); + add_sta->status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, + peer, VOS_FALSE); + goto send_rsp; + } + + wmi_unified_send_txbf(wma, add_sta); + + ret = wmi_unified_send_peer_assoc(wma, add_sta->nwType, add_sta); + if (ret) { + add_sta->status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, + peer, VOS_FALSE); + goto send_rsp; + } + +#ifdef QCA_IBSS_SUPPORT + /* + * In IBSS mode send the peer + * Atim Window length if IBSS + * power save is enabled by the + * firmware. + */ + if ( wma_is_vdev_in_ibss_mode(wma, add_sta->smesessionId) && + WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_IBSS_PWRSAVE) ) { + /* + * If ATIM Window is present in the peer + * beacon then send it to firmware else + * configure Zero ATIM Window length to + * firmware. + */ + if(add_sta->atimIePresent) { + wma_set_peer_param(wma, add_sta->staMac, + WMI_PEER_IBSS_ATIM_WINDOW_LENGTH, + add_sta->peerAtimWindowLength, + add_sta->smesessionId); + } + else { + wma_set_peer_param(wma, add_sta->staMac, + WMI_PEER_IBSS_ATIM_WINDOW_LENGTH, + 0, + add_sta->smesessionId); + } + } +#endif + +#ifdef WLAN_FEATURE_11W + if (add_sta->rmfEnabled) { + /* + * We have to store the state of PMF connection + * per STA for SAP case + * We will isolate the ifaces based on vdevid + */ + iface->rmfEnabled = add_sta->rmfEnabled; + /* + * when 802.11w PMF is enabled for hw encr/decr + * use hw MFP Qos bits 0x10 + */ + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_PMF_QOS, TRUE); + if(ret) { + WMA_LOGE("%s: Failed to set QOS MFP/PMF (%d)", + __func__, ret); + } + else { + WMA_LOGI("%s: QOS MFP/PMF set to %d", + __func__, TRUE); + } + } +#endif /* WLAN_FEATURE_11W */ + + if (add_sta->uAPSD) { + ret = wma_set_ap_peer_uapsd(wma, add_sta->smesessionId, + add_sta->staMac, + add_sta->uAPSD, + add_sta->maxSPLen); + if (ret) { + WMA_LOGE("Failed to set peer uapsd param for %pM", + add_sta->staMac); + add_sta->status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, + VOS_FALSE); + goto send_rsp; + } + } + + WMA_LOGD("%s: Moving peer %pM to state %d", + __func__, add_sta->staMac, state); + ol_txrx_peer_state_update(pdev, add_sta->staMac, state); + + add_sta->staIdx = ol_txrx_local_peer_id(peer); + add_sta->nss = iface->nss; + add_sta->status = VOS_STATUS_SUCCESS; +send_rsp: + WMA_LOGD("%s: Sending add sta rsp to umac (mac:%pM, status:%d)", + __func__, add_sta->staMac, add_sta->status); + wma_send_msg(wma, WDA_ADD_STA_RSP, (void *)add_sta, 0); +} + +static int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, + u_int8_t vdev_id) +{ + WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + WMA_LOGD("%s: vdev_id %d", __func__, vdev_id); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->action = IPSEC_NATKEEPALIVE_FILTER_ENABLE; + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID)) { + WMA_LOGP("%s: Failed to send NAT keepalive enable command", + __func__); + wmi_buf_free(buf); + return -EIO; + } + return 0; +} + +static int wmi_unified_csa_offload_enable(tp_wma_handle wma, + u_int8_t vdev_id) +{ + wmi_csa_offload_enable_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + WMA_LOGD("%s: vdev_id %d", __func__, vdev_id); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_csa_offload_enable_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_csa_offload_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_csa_offload_enable_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->csa_offload_enable = WMI_CSA_OFFLOAD_ENABLE; + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_CSA_OFFLOAD_ENABLE_CMDID)) { + WMA_LOGP("%s: Failed to send CSA offload enable command", + __func__); + wmi_buf_free(buf); + return -EIO; + } + return 0; +} + +#ifdef QCA_IBSS_SUPPORT + +static u_int16_t wma_calc_ibss_heart_beat_timer(int16_t peer_num) +{ + /* heart beat timer value look-up table */ + /* entry index : (the number of currently connected peers) - 1 + entry value : the heart time threshold value in seconds for + detecting ibss peer departure */ + static const u_int16_t heart_beat_timer[HDD_MAX_NUM_IBSS_STA] = { + 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 12, 12, 12, 12, + 16, 16, 16, 16, 16, 16, 16, 16}; + + if (peer_num < 1 || peer_num > HDD_MAX_NUM_IBSS_STA) + return 0; + + return heart_beat_timer[peer_num - 1]; + +} + +static void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma, + u_int8_t vdev_id, + int8_t peer_num_delta) +{ + ol_txrx_vdev_handle vdev; + int16_t new_peer_num; + u_int16_t new_timer_value_sec; + u_int32_t new_timer_value_ms; + + if (peer_num_delta != 1 && peer_num_delta != -1) { + WMA_LOGE("Invalid peer_num_delta value %d", peer_num_delta); + return; + } + + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("vdev not found : vdev_id %d", vdev_id); + return; + } + + new_peer_num = vdev->ibss_peer_num + peer_num_delta; + if (new_peer_num > HDD_MAX_NUM_IBSS_STA || new_peer_num < 0) { + WMA_LOGE("new peer num %d out of valid boundary", new_peer_num); + return; + } + + /* adjust peer numbers */ + vdev->ibss_peer_num = new_peer_num; + + /* reset timer value if all peers departed */ + if (new_peer_num == 0) { + vdev->ibss_peer_heart_beat_timer = 0; + return; + } + + /* calculate new timer value */ + new_timer_value_sec = wma_calc_ibss_heart_beat_timer(new_peer_num); + if (new_timer_value_sec == 0) { + WMA_LOGE("timer value %d is invalid for peer number %d", + new_timer_value_sec, new_peer_num); + return; + } + if (new_timer_value_sec == vdev->ibss_peer_heart_beat_timer) { + WMA_LOGD("timer value %d stays same, no need to notify target", + new_timer_value_sec); + return; + } + + /* send new timer value to target */ + vdev->ibss_peer_heart_beat_timer = new_timer_value_sec; + + new_timer_value_ms = ((u_int32_t)new_timer_value_sec) * 1000; + + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS, + new_timer_value_ms)) { + WMA_LOGE("Failed to set IBSS link monitoring timer value"); + return; + } + + WMA_LOGD("Set IBSS link monitor timer: peer_num = %d timer_value = %d", + new_peer_num, new_timer_value_ms); +} + +#endif /* QCA_IBSS_SUPPORT */ + +#ifdef FEATURE_WLAN_TDLS +static void wma_add_tdls_sta(tp_wma_handle wma, tpAddStaParams add_sta) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer; + u_int8_t peer_id; + VOS_STATUS status; + int32_t ret; + tTdlsPeerStateParams *peerStateParams; + + WMA_LOGD("%s: staType: %d, staIdx: %d, updateSta: %d, " + "bssId: %pM, staMac: %pM", + __func__, add_sta->staType, add_sta->staIdx, + add_sta->updateSta, add_sta->bssId, add_sta->staMac); + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + add_sta->status = VOS_STATUS_E_FAILURE; + goto send_rsp; + } + + vdev = wma_find_vdev_by_id(wma, add_sta->smesessionId); + if (!vdev) { + WMA_LOGE("%s: Failed to find vdev", __func__); + add_sta->status = VOS_STATUS_E_FAILURE; + goto send_rsp; + } + + if (0 == add_sta->updateSta) { + /* its a add sta request **/ +#if defined(CONFIG_HL_SUPPORT) + if (add_sta->bssId && vdev->last_real_peer && + (adf_os_mem_cmp((u8 *)add_sta->bssId, + vdev->last_real_peer->mac_addr.raw, + IEEE80211_ADDR_LEN) == 0)) { + adf_os_mem_copy(vdev->hl_tdls_ap_mac_addr.raw, + vdev->last_real_peer->mac_addr.raw, + OL_TXRX_MAC_ADDR_LEN); + } +#endif + WMA_LOGD("%s: addSta, calling wma_create_peer for %pM, vdev_id %hu", + __func__, add_sta->staMac, add_sta->smesessionId); + + status = wma_create_peer(wma, pdev, vdev, add_sta->staMac, + WMI_PEER_TYPE_TDLS, add_sta->smesessionId, + VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to create peer for %pM", + __func__, add_sta->staMac); + add_sta->status = status; + goto send_rsp; + } + + peer = ol_txrx_find_peer_by_addr(pdev, add_sta->staMac, &peer_id); + if (!peer) { + WMA_LOGE("%s: addSta, failed to find peer handle for mac %pM", + __func__, add_sta->staMac); + add_sta->status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, peer, + VOS_FALSE); +#if defined(CONFIG_HL_SUPPORT) + if (vdev->last_real_peer == NULL) { + peer = NULL; + peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); + if (peer && (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) + vdev->last_real_peer = peer; + } +#endif + goto send_rsp; + } + + add_sta->staIdx = ol_txrx_local_peer_id(peer); + WMA_LOGD("%s: addSta, after calling ol_txrx_local_peer_id, " + "staIdx: %d, staMac: %pM", + __func__, add_sta->staIdx, add_sta->staMac); + + peerStateParams = vos_mem_malloc(sizeof(tTdlsPeerStateParams)); + if (!peerStateParams) { + WMA_LOGE("%s: Failed to allocate memory for peerStateParams for %pM", + __func__, add_sta->staMac); + add_sta->status = VOS_STATUS_E_FAILURE; + goto send_rsp; + } + + vos_mem_zero(peerStateParams, sizeof(*peerStateParams)); + peerStateParams->peerState = WMI_TDLS_PEER_STATE_PEERING; + peerStateParams->vdevId = vdev->vdev_id; + vos_mem_copy(&peerStateParams->peerMacAddr, + &add_sta->staMac, + sizeof(tSirMacAddr)); + wma_update_tdls_peer_state(wma, peerStateParams); + } else { + /* its a change sta request **/ + peer = ol_txrx_find_peer_by_addr(pdev, add_sta->staMac, &peer_id); + if (!peer) { + WMA_LOGE("%s: changeSta,failed to find peer handle for mac %pM", + __func__, add_sta->staMac); + add_sta->status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, peer, + VOS_FALSE); +#if defined(CONFIG_HL_SUPPORT) + if (vdev->last_real_peer == NULL) { + peer = NULL; + peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); + if (peer && (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) + vdev->last_real_peer = peer; + } +#endif + goto send_rsp; + } + + WMA_LOGD("%s: changeSta, calling wmi_unified_send_peer_assoc", + __func__); + + ret = wmi_unified_send_peer_assoc(wma, add_sta->nwType, add_sta); + if (ret) { + add_sta->status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, peer, + VOS_FALSE); +#if defined(CONFIG_HL_SUPPORT) + if (vdev->last_real_peer == NULL) { + peer = NULL; + peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); + if (peer && (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) + vdev->last_real_peer = peer; + } +#endif + goto send_rsp; + } + } + +send_rsp: + WMA_LOGD("%s: Sending add sta rsp to umac (mac:%pM, status:%d), " + "staType: %d, staIdx: %d, updateSta: %d", + __func__, add_sta->staMac, add_sta->status, + add_sta->staType, add_sta->staIdx, add_sta->updateSta); + wma_send_msg(wma, WDA_ADD_STA_RSP, (void *)add_sta, 0); +} +#endif + +static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) +{ + ol_txrx_pdev_handle pdev; + VOS_STATUS status = VOS_STATUS_SUCCESS; + ol_txrx_peer_handle peer; + struct wma_txrx_node *iface = NULL; + tPowerdBm maxTxPower; + int ret = 0; + int smps_param; + +#ifdef FEATURE_WLAN_TDLS + if (STA_ENTRY_TDLS_PEER == params->staType) + { + wma_add_tdls_sta(wma, params); + return; + } +#endif + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Unable to get pdev", __func__); + goto out; + } + + iface = &wma->interfaces[params->smesessionId]; + if (params->staType != STA_ENTRY_SELF) { + WMA_LOGP("%s: unsupported station type %d", + __func__, params->staType); + goto out; + } + peer = ol_txrx_find_peer_by_addr(pdev, params->bssId, ¶ms->staIdx); + if(params->nonRoamReassoc) { + ol_txrx_peer_state_update(pdev, params->bssId, + ol_txrx_peer_state_auth); + adf_os_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STARTED); + iface->aid = params->assocId; + goto out; + } + if (wma->interfaces[params->smesessionId].vdev_up == true) { + WMA_LOGE("%s: vdev id %d is already UP for %pM", __func__, + params->smesessionId, params->bssId); + status = VOS_STATUS_E_FAILURE; + goto out; + } + if (peer != NULL && peer->state == ol_txrx_peer_state_disc) { + /* + * This is the case for reassociation. + * peer state update and peer_assoc is required since it + * was not done by WDA_ADD_BSS_REQ. + */ + + /* Update peer state */ + if (params->encryptType == eSIR_ED_NONE) { + WMA_LOGD("%s: Update peer(%pM) state into auth", + __func__, params->bssId); + ol_txrx_peer_state_update(pdev, params->bssId, + ol_txrx_peer_state_auth); + } else { + WMA_LOGD("%s: Update peer(%pM) state into conn", + __func__, params->bssId); + ol_txrx_peer_state_update(pdev, params->bssId, + ol_txrx_peer_state_conn); + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(iface->roam_synch_in_progress) + { + // iface->nss = params->nss; + /*In LFR2.0, the following operations are performed as + * part of wmi_unified_send_peer_assoc. As we are + * skipping this operation, we are just executing the + * following which are useful for LFR3.0.*/ + ol_txrx_peer_state_update(pdev, params->bssId, + ol_txrx_peer_state_auth); + adf_os_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STARTED); + iface->aid = params->assocId; + goto out; + } +#endif + wmi_unified_send_txbf(wma, params); + + ret = wmi_unified_send_peer_assoc(wma, + iface->nwType, + (tAddStaParams *)iface->addBssStaContext); + if (ret) { + status = VOS_STATUS_E_FAILURE; + wma_remove_peer(wma, params->bssId, + params->smesessionId, peer, VOS_FALSE); + goto out; + } + +#ifdef WLAN_FEATURE_11W + if (params->rmfEnabled) { + /* when 802.11w PMF is enabled for hw encr/decr + use hw MFP Qos bits 0x10 */ + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_PMF_QOS, TRUE); + if(ret) { + WMA_LOGE("%s: Failed to set QOS MFP/PMF (%d)", + __func__, ret); + } else { + WMA_LOGI("%s: QOS MFP/PMF set to %d", + __func__, TRUE); + } + } +#endif /* WLAN_FEATURE_11W */ +#if defined WLAN_FEATURE_VOWIFI_11R + /* + * Set the PTK in 11r mode because we already have it. + */ + if (iface->staKeyParams) { + wma_set_stakey(wma, (tpSetStaKeyParams) iface->staKeyParams); + } +#endif + } +#if defined WLAN_FEATURE_VOWIFI + maxTxPower = params->maxTxPower; +#else + maxTxPower = 0; +#endif + wma_vdev_set_bss_params(wma, params->smesessionId, iface->beaconInterval, + iface->dtimPeriod, iface->shortSlotTimeSupported, + iface->llbCoexist, maxTxPower); + + params->csaOffloadEnable = 0; + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_CSA_OFFLOAD)) { + params->csaOffloadEnable = 1; + if (wmi_unified_csa_offload_enable(wma, params->smesessionId) < 0) { + WMA_LOGE("Unable to enable CSA offload for vdev_id:%d", + params->smesessionId); + } + } + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE)) { + if (wmi_unified_nat_keepalive_enable(wma, params->smesessionId) < 0) { + WMA_LOGE("Unable to enable NAT keepalive for vdev_id:%d", + params->smesessionId); + } + } + + if (wmi_unified_vdev_up_send(wma->wmi_handle, params->smesessionId, + params->assocId, params->bssId) < 0) { + WMA_LOGP("%s: Failed to send vdev up cmd: vdev %d bssid %pM", + __func__, params->smesessionId, params->bssId); + status = VOS_STATUS_E_FAILURE; + } + else { + wma->interfaces[params->smesessionId].vdev_up = TRUE; + } + + adf_os_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STARTED); + WMA_LOGD("%s: STA mode (type %d subtype %d) BSS is started", + __func__, iface->type, iface->sub_type); + /* Sta is now associated, configure various params */ + + /* Send SMPS force command to FW to send the required + * action frame. The SM power save is also included + * in the assoc request if ht smps is enabled either + * from INI or as a result of dynamic antenna switch + */ + if (params->enableHtSmps) { + smps_param = wma_smps_mode_to_force_mode_param( + params->htSmpsconfig); + if (smps_param >= 0) { + WMA_LOGD("%s: Set MIMO power save smps mode %d", + __func__, params->htSmpsconfig); + wma_set_mimops(wma, params->smesessionId, + smps_param); + } + } + +#ifdef WLAN_FEATURE_11AC + /* Partial AID match power save, enable when SU bformee*/ + if (params->enableVhtpAid && params->vhtTxBFCapable) + wma_set_ppsconfig(params->smesessionId, + WMA_VHT_PPS_PAID_MATCH, 1); +#endif + + /* Enable AMPDU power save, if htCapable/vhtCapable */ + if (params->enableAmpduPs && + (params->htCapable || params->vhtCapable)) + wma_set_ppsconfig(params->smesessionId, + WMA_VHT_PPS_DELIM_CRC_FAIL, 1); + iface->aid = params->assocId; + params->nss = iface->nss; +out: + params->status = status; +/* change logging before release */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(iface && iface->roam_synch_in_progress) + WMA_LOGD("%s:statype %d vdevid %d aid %d bssid %pM staIdx %d status %d", + __func__, params->staType, params->smesessionId, + params->assocId, params->bssId, params->staIdx, status); + else + WMA_LOGE("%s:statype %d vdevid %d aid %d bssid %pM staIdx %d status %d", + __func__, params->staType, params->smesessionId, + params->assocId, params->bssId, params->staIdx, status); +#endif + wma_send_msg(wma, WDA_ADD_STA_RSP, (void *)params, 0); +} + +#ifdef FEATURE_WLAN_D0WOW +static void wma_add_pm_vote(tp_wma_handle wma) +{ + if (++wma->ap_client_cnt == 1) { + vos_runtime_pm_prevent_suspend(wma->runtime_context.ap); + vos_pm_control(DISABLE_PCIE_POWER_COLLAPSE); + } +} + +static void wma_del_pm_vote(tp_wma_handle wma) +{ + if (--wma->ap_client_cnt == 0) { + vos_runtime_pm_allow_suspend(wma->runtime_context.ap); + vos_pm_control(ENABLE_PCIE_POWER_COLLAPSE); + } +} + +int wma_get_client_count(WMA_HANDLE handle) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + return wma->ap_client_cnt; +} +#else +static void wma_prevent_suspend_check(tp_wma_handle wma) +{ + wma->ap_client_cnt++; + if (wma->ap_client_cnt == + wma->wlan_resource_config.num_offload_peers) { + vos_runtime_pm_prevent_suspend(wma->runtime_context.ap); + vos_wake_lock_acquire(&wma->wow_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_ADD_STA); + WMA_LOGW("%s: %d clients connected, prevent suspend", + __func__, wma->ap_client_cnt); + } +} + +static void wma_allow_suspend_check(tp_wma_handle wma) +{ + wma->ap_client_cnt--; + if (wma->ap_client_cnt == + wma->wlan_resource_config.num_offload_peers - 1) { + vos_wake_lock_release(&wma->wow_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_DEL_STA); + vos_runtime_pm_allow_suspend(wma->runtime_context.ap); + WMA_LOGW("%s: %d clients connected, allow suspend", + __func__, wma->ap_client_cnt); + } +} +#endif /* FEATURE_WLAN_D0WOW */ + +static void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta) +{ + tANI_U8 oper_mode = BSS_OPERATIONAL_MODE_STA; + + WMA_LOGD("%s: add_sta->sessionId = %d.", __func__, add_sta->smesessionId); + WMA_LOGD("%s: add_sta->bssId = %x:%x:%x:%x:%x:%x", __func__, + add_sta->bssId[0], add_sta->bssId[1], add_sta->bssId[2], + add_sta->bssId[3], add_sta->bssId[4], add_sta->bssId[5]); + + if (wma_is_vdev_in_ap_mode(wma, add_sta->smesessionId)) { +#ifdef FEATURE_WLAN_D0WOW + wma_add_pm_vote(wma); +#else + wma_prevent_suspend_check(wma); +#endif + oper_mode = BSS_OPERATIONAL_MODE_AP; + } +#ifdef QCA_IBSS_SUPPORT + else if (wma_is_vdev_in_ibss_mode(wma, add_sta->smesessionId)) { + oper_mode = BSS_OPERATIONAL_MODE_IBSS; +#ifdef FEATURE_WLAN_D0WOW + wma_add_pm_vote(wma); +#endif + } +#endif + + switch (oper_mode) { + case BSS_OPERATIONAL_MODE_STA: + wma_add_sta_req_sta_mode(wma, add_sta); + break; + +#ifdef QCA_IBSS_SUPPORT + case BSS_OPERATIONAL_MODE_IBSS: /* IBSS should share the same code as AP mode */ +#endif + case BSS_OPERATIONAL_MODE_AP: + wma_add_sta_req_ap_mode(wma, add_sta); + break; + } + +#ifdef QCA_IBSS_SUPPORT + /* adjust heart beat thresold timer value for detecting ibss peer departure */ + if (oper_mode == BSS_OPERATIONAL_MODE_IBSS) + wma_adjust_ibss_heart_beat_timer(wma, add_sta->smesessionId, 1); +#endif + +} + +/* + * This function reads WEP keys from cfg and fills + * up key_info. + */ +static void wma_read_cfg_wepkey(tp_wma_handle wma_handle, + tSirKeys *key_info, v_U32_t *def_key_idx, + u_int8_t *num_keys) +{ + tSirRetStatus status; + v_U32_t val = SIR_MAC_KEY_LENGTH; + u_int8_t i, j; + + WMA_LOGD("Reading WEP keys from cfg"); + /* NOTE:def_key_idx is initialized to 0 by the caller */ + status = wlan_cfgGetInt(wma_handle->mac_context, + WNI_CFG_WEP_DEFAULT_KEYID, def_key_idx); + if (status != eSIR_SUCCESS) + WMA_LOGE("Unable to read default id, defaulting to 0"); + + for (i = 0, j = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) { + status = wlan_cfgGetStr(wma_handle->mac_context, + (u_int16_t) WNI_CFG_WEP_DEFAULT_KEY_1 + i, + key_info[j].key, &val); + if (status != eSIR_SUCCESS) { + WMA_LOGE("WEP key is not configured at :%d", i); + } else { + key_info[j].keyId = i; + key_info[j].keyLength = (u_int16_t) val; + j++; + } + } + *num_keys = j; +} + +/* + * This function setsup wmi buffer from information + * passed in key_params. + */ +static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, + struct wma_set_key_params *key_params, + u_int32_t *len, u_int8_t mode) +{ + wmi_vdev_install_key_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int8_t *buf_ptr; + u_int8_t *key_data; +#ifdef WLAN_FEATURE_11W + struct wma_txrx_node *iface = NULL; +#endif /* WLAN_FEATURE_11W */ + if ((key_params->key_type == eSIR_ED_NONE && + key_params->key_len) || (key_params->key_type != eSIR_ED_NONE && + !key_params->key_len)) { + WMA_LOGE("%s:Invalid set key request", __func__); + return NULL; + } + + *len = sizeof(*cmd) + roundup(key_params->key_len, sizeof(u_int32_t)) + + WMI_TLV_HDR_SIZE; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, *len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set key cmd"); + return NULL; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_vdev_install_key_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_install_key_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_install_key_cmd_fixed_param)); + cmd->vdev_id = key_params->vdev_id; + cmd->key_ix = key_params->key_idx; + WMI_CHAR_ARRAY_TO_MAC_ADDR(key_params->peer_mac, + &cmd->peer_macaddr); + if (key_params->unicast) + cmd->key_flags |= PAIRWISE_USAGE; + else + cmd->key_flags |= GROUP_USAGE; + + switch (key_params->key_type) { + case eSIR_ED_NONE: + cmd->key_cipher = WMI_CIPHER_NONE; + break; + case eSIR_ED_WEP40: + case eSIR_ED_WEP104: + cmd->key_cipher = WMI_CIPHER_WEP; + if (key_params->unicast && + cmd->key_ix == key_params->def_key_idx) + cmd->key_flags |= TX_USAGE; + break; + case eSIR_ED_TKIP: + cmd->key_txmic_len = WMA_TXMIC_LEN; + cmd->key_rxmic_len = WMA_RXMIC_LEN; + cmd->key_cipher = WMI_CIPHER_TKIP; + break; +#ifdef FEATURE_WLAN_WAPI +#define WPI_IV_LEN 16 + case eSIR_ED_WPI: + { + /*initialize receive and transmit IV with default values*/ + /* **Note: tx_iv must be sent in reverse** */ + unsigned char tx_iv[16] = {0x36,0x5c,0x36,0x5c,0x36,0x5c,0x36, + 0x5c,0x36,0x5c,0x36,0x5c,0x36,0x5c, + 0x36,0x5c}; + unsigned char rx_iv[16] = {0x5c,0x36,0x5c,0x36,0x5c,0x36,0x5c, + 0x36,0x5c,0x36,0x5c,0x36,0x5c,0x36, + 0x5c,0x37}; + if (mode == wlan_op_mode_ap) { + /*Authenticator initializes the value of PN as + *0x5C365C365C365C365C365C365C365C36 for MCastkey Update + */ + if (key_params->unicast) + tx_iv[0] = 0x37; + + rx_iv[WPI_IV_LEN - 1] = 0x36; + } else { + if (!key_params->unicast) + rx_iv[WPI_IV_LEN - 1] = 0x36; + } + + cmd->key_txmic_len = WMA_TXMIC_LEN; + cmd->key_rxmic_len = WMA_RXMIC_LEN; + + vos_mem_copy(&cmd->wpi_key_rsc_counter, &rx_iv, WPI_IV_LEN); + vos_mem_copy(&cmd->wpi_key_tsc_counter, &tx_iv, WPI_IV_LEN); + cmd->key_cipher = WMI_CIPHER_WAPI; + break; + } +#endif + case eSIR_ED_CCMP: + cmd->key_cipher = WMI_CIPHER_AES_CCM; + break; +#ifdef WLAN_FEATURE_11W + case eSIR_ED_AES_128_CMAC: + cmd->key_cipher = WMI_CIPHER_AES_CMAC; + break; +#endif /* WLAN_FEATURE_11W */ + default: + /* TODO: MFP ? */ + WMA_LOGE("%s:Invalid encryption type:%d", __func__, key_params->key_type); + adf_nbuf_free(buf); + return NULL; + } + + buf_ptr += sizeof(wmi_vdev_install_key_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + roundup(key_params->key_len, sizeof(u_int32_t))); + key_data = (A_UINT8*)(buf_ptr + WMI_TLV_HDR_SIZE); +#ifdef BIG_ENDIAN_HOST + { + /* for big endian host, copy engine byte_swap is enabled + * But the key data content is in network byte order + * Need to byte swap the key data content - so when copy engine + * does byte_swap - target gets key_data content in the correct + * order. + */ + int8_t i; + u_int32_t *destp, *srcp; + + destp = (u_int32_t *) key_data; + srcp = (u_int32_t *) key_params->key_data; + for(i = 0; + i < roundup(key_params->key_len, sizeof(u_int32_t)) / 4; + i++) { + *destp = le32_to_cpu(*srcp); + destp++; + srcp++; + } + } +#else + vos_mem_copy((void *) key_data, + (const void *) key_params->key_data, + key_params->key_len); +#endif + cmd->key_len = key_params->key_len; + +#ifdef WLAN_FEATURE_11W + if (key_params->key_type == eSIR_ED_AES_128_CMAC) + { + iface = &wma_handle->interfaces[key_params->vdev_id]; + if (iface) { + iface->key.key_length = key_params->key_len; + vos_mem_copy (iface->key.key, + (const void *) key_params->key_data, + iface->key.key_length); + if ((cmd->key_ix == WMA_IGTK_KEY_INDEX_4) || + (cmd->key_ix == WMA_IGTK_KEY_INDEX_5)) + vos_mem_zero (iface->key.key_id[cmd->key_ix - WMA_IGTK_KEY_INDEX_4].ipn, + CMAC_IPN_LEN); + } + } +#endif /* WLAN_FEATURE_11W */ + + WMA_LOGD("Key setup : vdev_id %d key_idx %d key_type %d key_len %d" + " unicast %d peer_mac %pM def_key_idx %d", key_params->vdev_id, + key_params->key_idx, key_params->key_type, key_params->key_len, + key_params->unicast, key_params->peer_mac, + key_params->def_key_idx); + + return buf; +} + +static void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info) +{ + struct wma_set_key_params key_params; + wmi_buf_t buf; + int32_t status; + u_int32_t len = 0, i; + v_U32_t def_key_idx = 0; + ol_txrx_vdev_handle txrx_vdev; + + WMA_LOGD("BSS key setup"); + txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId); + if (!txrx_vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + key_info->status = eHAL_STATUS_FAILURE; + goto out; + } + + /* + ** For IBSS, WMI expects the BSS key to be set per peer key + ** So cache the BSS key in the wma_handle and re-use it when the STA key is been setup for a peer + */ + if (wlan_op_mode_ibss == txrx_vdev->opmode) { + key_info->status = eHAL_STATUS_SUCCESS; + if (wma_handle->ibss_started > 0) + goto out; + WMA_LOGD("Caching IBSS Key"); + vos_mem_copy(&wma_handle->ibsskey_info, key_info, sizeof(tSetBssKeyParams)); + } + + adf_os_mem_set(&key_params, 0, sizeof(key_params)); + key_params.vdev_id = key_info->smesessionId; + key_params.key_type = key_info->encType; + key_params.singl_tid_rc = key_info->singleTidRc; + key_params.unicast = FALSE; + if (txrx_vdev->opmode == wlan_op_mode_sta) { + vos_mem_copy(key_params.peer_mac, + wma_handle->interfaces[key_info->smesessionId].bssid, + ETH_ALEN); + } else { + /* vdev mac address will be passed for all other modes */ + vos_mem_copy(key_params.peer_mac, txrx_vdev->mac_addr.raw, + ETH_ALEN); + WMA_LOGA("BSS Key setup with vdev_mac %pM\n", + txrx_vdev->mac_addr.raw); + } + + if (key_info->numKeys == 0 && + (key_info->encType == eSIR_ED_WEP40 || + key_info->encType == eSIR_ED_WEP104)) { + wma_read_cfg_wepkey(wma_handle, key_info->key, + &def_key_idx, &key_info->numKeys); + } else if ((key_info->encType == eSIR_ED_WEP40) || + (key_info->encType == eSIR_ED_WEP104)) { + struct wma_txrx_node *intf = + &wma_handle->interfaces[key_info->smesessionId]; + key_params.def_key_idx = intf->wep_default_key_idx; + } + + for (i = 0; i < key_info->numKeys; i++) { + if (key_params.key_type != eSIR_ED_NONE && + !key_info->key[i].keyLength) + continue; + if (key_info->encType == eSIR_ED_WPI) { + key_params.key_idx = key_info->key[i].keyId; + key_params.def_key_idx = key_info->key[i].keyId; + } else + key_params.key_idx = key_info->key[i].keyId; + + key_params.key_len = key_info->key[i].keyLength; + if (key_info->encType == eSIR_ED_TKIP) { + vos_mem_copy(key_params.key_data, + key_info->key[i].key, 16); + vos_mem_copy(&key_params.key_data[16], + &key_info->key[i].key[24], 8); + vos_mem_copy(&key_params.key_data[24], + &key_info->key[i].key[16], 8); + } else + vos_mem_copy((v_VOID_t *) key_params.key_data, + (const v_VOID_t *) key_info->key[i].key, + key_info->key[i].keyLength); + + WMA_LOGD("%s: bss key[%d] length %d", __func__, i, + key_info->key[i].keyLength); + + buf = wma_setup_install_key_cmd(wma_handle, &key_params, &len, + txrx_vdev->opmode); + if (!buf) { + WMA_LOGE("%s:Failed to setup install key buf", __func__); + key_info->status = eHAL_STATUS_FAILED_ALLOC; + goto out; + } + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_INSTALL_KEY_CMDID); + if (status) { + adf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send install key command", __func__); + key_info->status = eHAL_STATUS_FAILURE; + goto out; + } + } + + wma_handle->ibss_started++; + /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */ + key_info->status = eHAL_STATUS_SUCCESS; + +out: + wma_send_msg(wma_handle, WDA_SET_BSSKEY_RSP, (void *)key_info, 0); +} + +static void wma_set_ibsskey_helper(tp_wma_handle wma_handle, tpSetBssKeyParams key_info, u_int8_t* peerMacAddr) +{ + struct wma_set_key_params key_params; + wmi_buf_t buf; + int32_t status; + u_int32_t len = 0, i; + v_U32_t def_key_idx = 0; + ol_txrx_vdev_handle txrx_vdev; + + WMA_LOGD("BSS key setup for peer"); + ASSERT( NULL != peerMacAddr); + txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId); + if (!txrx_vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + key_info->status = eHAL_STATUS_FAILURE; + return; + } + + adf_os_mem_set(&key_params, 0, sizeof(key_params)); + key_params.vdev_id = key_info->smesessionId; + key_params.key_type = key_info->encType; + key_params.singl_tid_rc = key_info->singleTidRc; + key_params.unicast = FALSE; + ASSERT(wlan_op_mode_ibss == txrx_vdev->opmode); + + vos_mem_copy(key_params.peer_mac, peerMacAddr, ETH_ALEN); + + if (key_info->numKeys == 0 && + (key_info->encType == eSIR_ED_WEP40 || + key_info->encType == eSIR_ED_WEP104)) { + wma_read_cfg_wepkey(wma_handle, key_info->key, + &def_key_idx, &key_info->numKeys); + } + + for (i = 0; i < key_info->numKeys; i++) { + if (key_params.key_type != eSIR_ED_NONE && + !key_info->key[i].keyLength) + continue; + key_params.key_idx = key_info->key[i].keyId; + key_params.key_len = key_info->key[i].keyLength; + if (key_info->encType == eSIR_ED_TKIP) { + vos_mem_copy(key_params.key_data, + key_info->key[i].key, 16); + vos_mem_copy(&key_params.key_data[16], + &key_info->key[i].key[24], 8); + vos_mem_copy(&key_params.key_data[24], + &key_info->key[i].key[16], 8); + } else + vos_mem_copy((v_VOID_t *) key_params.key_data, + (const v_VOID_t *) key_info->key[i].key, + key_info->key[i].keyLength); + + WMA_LOGD("%s: peer bcast key[%d] length %d", __func__, i, + key_info->key[i].keyLength); + + buf = wma_setup_install_key_cmd(wma_handle, &key_params, &len, + txrx_vdev->opmode); + if (!buf) { + WMA_LOGE("%s:Failed to setup install key buf", __func__); + return; + } + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_INSTALL_KEY_CMDID); + if (status) { + adf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send install key command", __func__); + } + } +} + +static void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info) +{ + wmi_buf_t buf; + int32_t status, i; + u_int32_t len = 0; + ol_txrx_pdev_handle txrx_pdev; + ol_txrx_vdev_handle txrx_vdev; + struct ol_txrx_peer_t *peer; + u_int8_t num_keys = 0, peer_id; + struct wma_set_key_params key_params; + v_U32_t def_key_idx = 0; + + WMA_LOGD("STA key setup"); + + /* Get the txRx Pdev handle */ + txrx_pdev = vos_get_context(VOS_MODULE_ID_TXRX, + wma_handle->vos_context); + if (!txrx_pdev) { + WMA_LOGE("%s:Invalid txrx pdev handle", __func__); + key_info->status = eHAL_STATUS_FAILURE; + goto out; + } + + peer = ol_txrx_find_peer_by_addr(txrx_pdev, key_info->peerMacAddr, + &peer_id); + if (!peer) { + WMA_LOGE("%s:Invalid peer for key setting", __func__); + key_info->status = eHAL_STATUS_FAILURE; + goto out; + } + + txrx_vdev = wma_find_vdev_by_id(wma_handle, key_info->smesessionId); + if(!txrx_vdev) { + WMA_LOGE("%s:TxRx Vdev Handle is NULL", __func__); + key_info->status = eHAL_STATUS_FAILURE; + goto out; + } + + if (key_info->defWEPIdx == WMA_INVALID_KEY_IDX && + (key_info->encType == eSIR_ED_WEP40 || + key_info->encType == eSIR_ED_WEP104) && + txrx_vdev->opmode != wlan_op_mode_ap) { + wma_read_cfg_wepkey(wma_handle, key_info->key, + &def_key_idx, &num_keys); + key_info->defWEPIdx = def_key_idx; + } else { + num_keys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + if (key_info->encType != eSIR_ED_NONE) { + for (i = 0; i < num_keys; i++) { + if (key_info->key[i].keyDirection == + eSIR_TX_DEFAULT) { + key_info->defWEPIdx = i; + break; + } + } + } + } + adf_os_mem_set(&key_params, 0, sizeof(key_params)); + key_params.vdev_id = key_info->smesessionId; + key_params.key_type = key_info->encType; + key_params.singl_tid_rc = key_info->singleTidRc; + key_params.unicast = TRUE; + key_params.def_key_idx = key_info->defWEPIdx; + vos_mem_copy((v_VOID_t *) key_params.peer_mac, + (const v_VOID_t *) key_info->peerMacAddr, ETH_ALEN); + for (i = 0; i < num_keys; i++) { + if (key_params.key_type != eSIR_ED_NONE && + !key_info->key[i].keyLength) + continue; + if (key_info->encType == eSIR_ED_TKIP) { + vos_mem_copy(key_params.key_data, + key_info->key[i].key, 16); + vos_mem_copy(&key_params.key_data[16], + &key_info->key[i].key[24], 8); + vos_mem_copy(&key_params.key_data[24], + &key_info->key[i].key[16], 8); + } else + vos_mem_copy(key_params.key_data, key_info->key[i].key, + key_info->key[i].keyLength); + if (key_info->encType == eSIR_ED_WPI) { + key_params.key_idx = key_info->key[i].keyId; + key_params.def_key_idx = key_info->key[i].keyId; + } else + key_params.key_idx = i; + + key_params.key_len = key_info->key[i].keyLength; + buf = wma_setup_install_key_cmd(wma_handle, &key_params, &len, + txrx_vdev->opmode); + if (!buf) { + WMA_LOGE("%s:Failed to setup install key buf", __func__); + key_info->status = eHAL_STATUS_FAILED_ALLOC; + goto out; + } + + WMA_LOGD("%s: peer unicast key[%d] %d ", __func__, i, + key_info->key[i].keyLength); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_INSTALL_KEY_CMDID); + if (status) { + adf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send install key command", __func__); + key_info->status = eHAL_STATUS_FAILURE; + goto out; + } + } + + /* In IBSS mode, set the BSS KEY for this peer + ** BSS key is supposed to be cache into wma_handle + */ + if (wlan_op_mode_ibss == txrx_vdev->opmode){ + wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info, key_info->peerMacAddr); + } + + /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */ + key_info->status = eHAL_STATUS_SUCCESS; +out: + if (key_info->sendRsp) + wma_send_msg(wma_handle, WDA_SET_STAKEY_RSP, (void *) key_info, 0); +} + +static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, + tpDeleteStaParams del_sta) +{ + ol_txrx_pdev_handle pdev; + struct ol_txrx_peer_t *peer; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + del_sta->status = VOS_STATUS_E_FAILURE; + goto send_del_rsp; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, del_sta->staIdx); + if (!peer) { + WMA_LOGE("%s: Failed to get peer handle using peer id %d", + __func__, del_sta->staIdx); + del_sta->status = VOS_STATUS_E_FAILURE; + goto send_del_rsp; + } + + wma_remove_peer(wma, peer->mac_addr.raw, del_sta->smesessionId, peer, + VOS_FALSE); + del_sta->status = VOS_STATUS_SUCCESS; + +send_del_rsp: + if (del_sta->respReqd) { + WMA_LOGD("%s: Sending del rsp to umac (status: %d)", + __func__, del_sta->status); + wma_send_msg(wma, WDA_DELETE_STA_RSP, (void *)del_sta, 0); + } +} + +#ifdef FEATURE_WLAN_TDLS +static void wma_del_tdls_sta(tp_wma_handle wma, + tpDeleteStaParams del_sta) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + struct ol_txrx_peer_t *peer; + tTdlsPeerStateParams *peerStateParams; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + del_sta->status = VOS_STATUS_E_FAILURE; + goto send_del_rsp; + } + + vdev = wma_find_vdev_by_id(wma, del_sta->smesessionId); + if (!vdev) { + WMA_LOGE("%s: Failed to find vdev", __func__); + del_sta->status = VOS_STATUS_E_FAILURE; + goto send_del_rsp; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, del_sta->staIdx); + if (!peer) { + WMA_LOGE("%s: Failed to get peer handle using peer id %d", + __func__, del_sta->staIdx); + del_sta->status = VOS_STATUS_E_FAILURE; + goto send_del_rsp; + } + + peerStateParams = vos_mem_malloc(sizeof(tTdlsPeerStateParams)); + if (!peerStateParams) { + WMA_LOGE("%s: Failed to allocate memory for peerStateParams for: %pM", + __func__, del_sta->staMac); + del_sta->status = VOS_STATUS_E_FAILURE; + goto send_del_rsp; + } + + vos_mem_zero(peerStateParams, sizeof(*peerStateParams)); + peerStateParams->peerState = WDA_TDLS_PEER_STATE_TEARDOWN; + peerStateParams->vdevId = vdev->vdev_id; + vos_mem_copy(&peerStateParams->peerMacAddr, + &del_sta->staMac, + sizeof(tSirMacAddr)); + + WMA_LOGD("%s: sending tdls_peer_state for peer mac: %pM, " + " peerState: %d", + __func__, peerStateParams->peerMacAddr, + peerStateParams->peerState); + + wma_update_tdls_peer_state(wma, peerStateParams); + + del_sta->status = VOS_STATUS_SUCCESS; + +send_del_rsp: + if (del_sta->respReqd) { + WMA_LOGD("%s: Sending del rsp to umac (status: %d)", + __func__, del_sta->status); + wma_send_msg(wma, WDA_DELETE_STA_RSP, (void *)del_sta, 0); + } +} +#endif + +static void wma_delete_sta_req_sta_mode(tp_wma_handle wma, + tpDeleteStaParams params) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + struct wma_txrx_node *iface; + iface = &wma->interfaces[params->smesessionId]; + iface->uapsd_cached_val = 0; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + /* In case of LFR3.0 we need not send any + * WMI commands to FW before SYNCH_CONFIRM */ +if(iface->roam_synch_in_progress) + goto send_del_sta_rsp; +#endif +#ifdef FEATURE_WLAN_TDLS + if (STA_ENTRY_TDLS_PEER == params->staType) + { + wma_del_tdls_sta(wma, params); + return; + } +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +send_del_sta_rsp: +#endif + params->status = status; + if (params->respReqd) { + WMA_LOGD("%s: vdev_id %d status %d", __func__, + params->smesessionId, status); + wma_send_msg(wma, WDA_DELETE_STA_RSP, (void *)params, 0); + } +} + +static void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta) +{ + tANI_U8 oper_mode = BSS_OPERATIONAL_MODE_STA; + u_int8_t smesession_id = del_sta->smesessionId; + bool rsp_requested = del_sta->respReqd; + + if (wma_is_vdev_in_ap_mode(wma, smesession_id)) { +#ifdef FEATURE_WLAN_D0WOW + wma_del_pm_vote(wma); +#else + wma_allow_suspend_check(wma); +#endif + oper_mode = BSS_OPERATIONAL_MODE_AP; + } +#ifdef QCA_IBSS_SUPPORT + if (wma_is_vdev_in_ibss_mode(wma, smesession_id)) { + oper_mode = BSS_OPERATIONAL_MODE_IBSS; +#ifdef FEATURE_WLAN_D0WOW + wma_del_pm_vote(wma); +#endif + WMA_LOGD("%s: to delete sta for IBSS mode", __func__); + } +#endif + + switch (oper_mode) { + case BSS_OPERATIONAL_MODE_STA: + wma_delete_sta_req_sta_mode(wma, del_sta); + break; + +#ifdef QCA_IBSS_SUPPORT + case BSS_OPERATIONAL_MODE_IBSS: /* IBSS shares AP code */ +#endif + case BSS_OPERATIONAL_MODE_AP: + wma_delete_sta_req_ap_mode(wma, del_sta); + break; + } + +#ifdef QCA_IBSS_SUPPORT + /* adjust heart beat thresold timer value for + * detecting ibss peer departure + */ + if (oper_mode == BSS_OPERATIONAL_MODE_IBSS) + wma_adjust_ibss_heart_beat_timer(wma, smesession_id, -1); +#endif + if (!rsp_requested) { + WMA_LOGD("%s: vdev_id %d status %d", __func__, + del_sta->smesessionId, del_sta->status); + vos_mem_free(del_sta); + } +} + +static int32_t wmi_unified_vdev_stop_send(wmi_unified_t wmi, u_int8_t vdev_id) +{ + wmi_vdev_stop_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi, len); + if (!buf) { + WMA_LOGP("%s : wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_vdev_stop_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_stop_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_stop_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_STOP_CMDID)) { + WMA_LOGP("%s: Failed to send vdev stop command", __func__); + adf_nbuf_free(buf); + return -EIO; + } + return 0; +} + +static void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_peer_handle peer = NULL; + struct wma_target_req *msg; + VOS_STATUS status = VOS_STATUS_SUCCESS; + u_int8_t peer_id; + u_int8_t max_wait_iterations = 0; + ol_txrx_vdev_handle txrx_vdev = NULL; + v_BOOL_t roam_synch_in_progress = VOS_FALSE; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s:Unable to get TXRX context", __func__); + goto out; + } + +#ifdef QCA_IBSS_SUPPORT + if (wma_is_vdev_in_ibss_mode(wma, params->smesessionId)) + /* in rome ibss case, self mac is used to create the bss peer */ + peer = ol_txrx_find_peer_by_addr(pdev, + wma->interfaces[params->smesessionId].addr, + &peer_id); + else +#endif + peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, + &peer_id); + + if (!peer) { + WMA_LOGP("%s: Failed to find peer %pM", __func__, + params->bssid); + status = VOS_STATUS_E_FAILURE; + goto out; + } + + vos_mem_zero(wma->interfaces[params->smesessionId].bssid, ETH_ALEN); + + txrx_vdev = wma_find_vdev_by_id(wma, params->smesessionId); + if (!txrx_vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + status = VOS_STATUS_E_FAILURE; + goto out; + } + + /*Free the allocated stats response buffer for the the session*/ + if (wma->interfaces[params->smesessionId].stats_rsp) { + vos_mem_free(wma->interfaces[params->smesessionId].stats_rsp); + wma->interfaces[params->smesessionId].stats_rsp = NULL; + } + + if (wma->interfaces[params->smesessionId].psnr_req) { + vos_mem_free(wma->interfaces[params->smesessionId].psnr_req); + wma->interfaces[params->smesessionId].psnr_req = NULL; + } + + if (wlan_op_mode_ibss == txrx_vdev->opmode) { + wma->ibss_started = 0; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(wma->interfaces[params->smesessionId].roam_synch_in_progress) + { + roam_synch_in_progress = VOS_TRUE; + goto detach_peer; + } +#endif + msg = wma_fill_vdev_req(wma, params->smesessionId, WDA_DELETE_BSS_REQ, + WMA_TARGET_REQ_TYPE_VDEV_STOP, params, + WMA_VDEV_STOP_REQUEST_TIMEOUT); + if (!msg) { + WMA_LOGP("%s: Failed to fill vdev request for vdev_id %d", + __func__, params->smesessionId); + status = VOS_STATUS_E_NOMEM; + goto detach_peer; + } + + WMA_LOGW(FL("Outstanding msdu packets: %d"), + ol_txrx_get_tx_pending(pdev)); + + max_wait_iterations = + wma->interfaces[params->smesessionId].delay_before_vdev_stop / + WMA_TX_Q_RECHECK_TIMER_WAIT; + + while ( ol_txrx_get_tx_pending(pdev) && max_wait_iterations ) + { + WMA_LOGW(FL("Waiting for outstanding packet to drain.")); + vos_wait_single_event(&wma->tx_queue_empty_event, + WMA_TX_Q_RECHECK_TIMER_WAIT); + max_wait_iterations--; + } + + if (ol_txrx_get_tx_pending(pdev)) + { + WMA_LOGW(FL("Outstanding msdu packets before VDEV_STOP : %d"), + ol_txrx_get_tx_pending(pdev)); + } + + WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP (del_bss)", + __func__, params->smesessionId); + wdi_in_vdev_pause(wma->interfaces[params->smesessionId].handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + wma->interfaces[params->smesessionId].pause_bitmap |= + (1 << PAUSE_TYPE_HOST); + + if (wmi_unified_vdev_stop_send(wma->wmi_handle, params->smesessionId)) { + WMA_LOGP("%s: %d Failed to send vdev stop", + __func__, __LINE__); + wma_remove_vdev_req(wma, params->smesessionId, + WMA_TARGET_REQ_TYPE_VDEV_STOP); + status = VOS_STATUS_E_FAILURE; + goto detach_peer; + } + WMA_LOGD("%s: bssid %pM vdev_id %d", + __func__, params->bssid, params->smesessionId); + return; +detach_peer: + wma_remove_peer(wma, params->bssid, params->smesessionId, peer, + roam_synch_in_progress); +out: + params->status = status; + wma_send_msg(wma, WDA_DELETE_BSS_RSP, (void *)params, 0); +} + +static void wma_set_linkstate(tp_wma_handle wma, tpLinkStateParams params) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer; + u_int8_t vdev_id, peer_id; + v_BOOL_t roam_synch_in_progress = VOS_FALSE; + VOS_STATUS status; + + params->status = VOS_TRUE; + WMA_LOGD("%s: state %d selfmac %pM", __func__, + params->state, params->selfMacAddr); + if ((params->state != eSIR_LINK_PREASSOC_STATE) && + (params->state != eSIR_LINK_DOWN_STATE)) { + WMA_LOGD("%s: unsupported link state %d", + __func__, params->state); + goto out; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Unable to get TXRX context", __func__); + goto out; + } + + vdev = wma_find_vdev_by_addr(wma, params->selfMacAddr, &vdev_id); + if (!vdev) { + WMA_LOGP("%s: vdev not found for addr: %pM", + __func__, params->selfMacAddr); + goto out; + } + + if (wma_is_vdev_in_ap_mode(wma, vdev_id)) { + WMA_LOGD("%s: Ignoring set link req in ap mode", __func__); + goto out; + } + + if (params->state == eSIR_LINK_PREASSOC_STATE) { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(wma->interfaces[vdev_id].roam_synch_in_progress){ + roam_synch_in_progress = VOS_TRUE; + } +#endif + status = wma_create_peer(wma, pdev, vdev, params->bssid, + WMI_PEER_TYPE_DEFAULT, vdev_id, + roam_synch_in_progress); + if (status != VOS_STATUS_SUCCESS) + params->status = VOS_FALSE; + } + else { + WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP", + __func__, vdev_id); + wdi_in_vdev_pause(wma->interfaces[vdev_id].handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + wma->interfaces[vdev_id].pause_bitmap |= (1 << PAUSE_TYPE_HOST); + if (wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id)) { + WMA_LOGP("%s: %d Failed to send vdev stop", + __func__, __LINE__); + } + peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, &peer_id); + if (peer) { + WMA_LOGP("%s: Deleting peer %pM vdev id %d", + __func__, params->bssid, vdev_id); + wma_remove_peer(wma, params->bssid, vdev_id, peer, + roam_synch_in_progress); + } + } +out: + wma_send_msg(wma, WDA_SET_LINK_STATE_RSP, (void *)params, 0); +} + +/* + * Function to update per ac EDCA parameters + */ +static void wma_update_edca_params_for_ac(tSirMacEdcaParamRecord *edca_param, + wmi_wmm_vparams *wmm_param, + int ac) +{ +#define WMA_WMM_EXPO_TO_VAL(val) ((1 << (val)) - 1) + wmm_param->cwmin = WMA_WMM_EXPO_TO_VAL(edca_param->cw.min); + wmm_param->cwmax = WMA_WMM_EXPO_TO_VAL(edca_param->cw.max); + wmm_param->aifs = edca_param->aci.aifsn; + wmm_param->txoplimit = edca_param->txoplimit; + wmm_param->acm = edca_param->aci.acm; + + /* TODO: No ack is not present in EdcaParamRecord */ + wmm_param->no_ack = 0; + + WMA_LOGI("WMM PARAMS AC[%d]: AIFS %d Min %d Max %d TXOP %d ACM %d NOACK %d", + ac, + wmm_param->aifs, + wmm_param->cwmin, + wmm_param->cwmax, + wmm_param->txoplimit, + wmm_param->acm, + wmm_param->no_ack); +} + +/* + * Set TX power limit through vdev param + */ +static void wma_set_tx_power(WMA_HANDLE handle, + tMaxTxPowerParams *tx_pwr_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + u_int8_t vdev_id; + int ret = -1; + void *pdev; + + if (tx_pwr_params->dev_mode == VOS_STA_SAP_MODE || + tx_pwr_params->dev_mode == VOS_P2P_GO_MODE) { + pdev = wma_find_vdev_by_addr(wma_handle, + tx_pwr_params->bssId, &vdev_id); + } else { + pdev = wma_find_vdev_by_bssid(wma_handle, + tx_pwr_params->bssId, &vdev_id); + } + if (!pdev) { + WMA_LOGE("vdev handle is invalid for %pM", tx_pwr_params->bssId); + vos_mem_free(tx_pwr_params); + return; + } + + if (!(wma_handle->interfaces[vdev_id].vdev_up)) { + WMA_LOGE("%s: vdev id %d is not up for %pM", __func__, vdev_id, + tx_pwr_params->bssId); + vos_mem_free(tx_pwr_params); + return; + } + + if (tx_pwr_params->power == 0) { + /* set to default. Since the app does not care the tx power + * we keep the previous setting */ + wma_handle->interfaces[vdev_id].tx_power = 0; + ret = 0; + goto end; + } + if (wma_handle->interfaces[vdev_id].max_tx_power != 0) { + /* make sure tx_power less than max_tx_power */ + if (tx_pwr_params->power > + wma_handle->interfaces[vdev_id].max_tx_power) { + tx_pwr_params->power = + wma_handle->interfaces[vdev_id].max_tx_power; + } + } + if (wma_handle->interfaces[vdev_id].tx_power != tx_pwr_params->power) { + + /* tx_power changed, Push the tx_power to FW */ + WMA_LOGW("%s: Set TX power limit [WMI_VDEV_PARAM_TX_PWRLIMIT] to %d", + __func__, tx_pwr_params->power); + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TX_PWRLIMIT, tx_pwr_params->power); + if (ret == 0) + wma_handle->interfaces[vdev_id].tx_power = tx_pwr_params->power; + } else { + /* no tx_power change */ + ret = 0; + } +end: + vos_mem_free(tx_pwr_params); + if (ret) + WMA_LOGE("Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT"); +} + +/* + * Set TX power limit through vdev param + */ +static void wma_set_max_tx_power(WMA_HANDLE handle, + tMaxTxPowerParams *tx_pwr_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + u_int8_t vdev_id; + int ret = -1; + void *pdev; + tPowerdBm prev_max_power; + + pdev = wma_find_vdev_by_addr(wma_handle, tx_pwr_params->bssId, &vdev_id); + if (pdev == NULL) { + /* not in SAP array. Try the station/p2p array */ + pdev = wma_find_vdev_by_bssid(wma_handle, + tx_pwr_params->bssId, &vdev_id); + } + if (!pdev) { + WMA_LOGE("vdev handle is invalid for %pM", tx_pwr_params->bssId); + vos_mem_free(tx_pwr_params); + return; + } + + if (! (wma_handle->interfaces[vdev_id].vdev_up)) { + WMA_LOGE("%s: vdev id %d is not up",__func__, vdev_id); + vos_mem_free(tx_pwr_params); + return; + } + + if (wma_handle->interfaces[vdev_id].max_tx_power == tx_pwr_params->power) { + ret = 0; + goto end; + } + prev_max_power = wma_handle->interfaces[vdev_id].max_tx_power; + wma_handle->interfaces[vdev_id].max_tx_power = tx_pwr_params->power; + if (wma_handle->interfaces[vdev_id].max_tx_power == 0) { + ret = 0; + goto end; + } + WMA_LOGW("Set MAX TX power limit [WMI_VDEV_PARAM_TX_PWRLIMIT] to %d", + wma_handle->interfaces[vdev_id].max_tx_power); + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TX_PWRLIMIT, + wma_handle->interfaces[vdev_id].max_tx_power); + if (ret == 0) + wma_handle->interfaces[vdev_id].tx_power = + wma_handle->interfaces[vdev_id].max_tx_power; + else + wma_handle->interfaces[vdev_id].max_tx_power = prev_max_power; +end: + vos_mem_free(tx_pwr_params); + if (ret) + WMA_LOGE("%s: Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT", __func__); +} + +/* + * Function to update the EDCA parameters to the target + */ +static VOS_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle, + tEdcaParams *edca_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + u_int8_t *buf_ptr; + wmi_buf_t buf; + wmi_vdev_set_wmm_params_cmd_fixed_param *cmd; + wmi_wmm_vparams *wmm_param; + tSirMacEdcaParamRecord *edca_record; + int ac; + int len = sizeof(*cmd); + ol_txrx_pdev_handle pdev; + struct ol_tx_wmm_param_t ol_tx_wmm_param; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_vdev_set_wmm_params_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_set_wmm_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_set_wmm_params_cmd_fixed_param)); + cmd->vdev_id = edca_params->bssIdx; + + for (ac = 0; ac < WME_NUM_AC; ac++) { + wmm_param = (wmi_wmm_vparams *)(&cmd->wmm_params[ac]); + WMITLV_SET_HDR(&wmm_param->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_set_wmm_params_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_wmm_vparams)); + switch (ac) { + case WME_AC_BE: + edca_record = &edca_params->acbe; + break; + case WME_AC_BK: + edca_record = &edca_params->acbk; + break; + case WME_AC_VI: + edca_record = &edca_params->acvi; + break; + case WME_AC_VO: + edca_record = &edca_params->acvo; + break; + default: + goto fail; + } + + wma_update_edca_params_for_ac(edca_record, wmm_param, ac); + + ol_tx_wmm_param.ac[ac].aifs = wmm_param->aifs; + ol_tx_wmm_param.ac[ac].cwmin = wmm_param->cwmin; + ol_tx_wmm_param.ac[ac].cwmax = wmm_param->cwmax; + } + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_SET_WMM_PARAMS_CMDID)) + goto fail; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma_handle->vos_context); + if (pdev) { + wdi_in_set_wmm_param(pdev, ol_tx_wmm_param); + } + return VOS_STATUS_SUCCESS; + +fail: + wmi_buf_free(buf); + WMA_LOGE("%s: Failed to set WMM Paremeters", __func__); + return VOS_STATUS_E_FAILURE; +} + +static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma, + u_int8_t vdev_id, + tpSendProbeRespParams probe_rsp_info) +{ + wmi_prb_tmpl_cmd_fixed_param *cmd; + wmi_bcn_prb_info *bcn_prb_info; + wmi_buf_t wmi_buf; + u_int32_t tmpl_len, tmpl_len_aligned, wmi_buf_len; + u_int8_t *frm, *buf_ptr; + int ret; + u_int64_t adjusted_tsf_le; + struct ieee80211_frame *wh; + + WMA_LOGD(FL("Send probe response template for vdev %d"), vdev_id); + + frm = probe_rsp_info->pProbeRespTemplate; + tmpl_len = probe_rsp_info->probeRespTemplateLen; + tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32)); + /* + * Make the TSF offset negative so probe response in the same + * staggered batch have the same TSF. + */ + adjusted_tsf_le = cpu_to_le64(0ULL - + wma->interfaces[vdev_id].tsfadjust); + /* Update the timstamp in the probe response buffer with adjusted TSF */ + wh = (struct ieee80211_frame *)frm; + A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le)); + + wmi_buf_len = sizeof(wmi_prb_tmpl_cmd_fixed_param) + + sizeof(wmi_bcn_prb_info) + WMI_TLV_HDR_SIZE + + tmpl_len_aligned; + + if (wmi_buf_len > BEACON_TX_BUFFER_SIZE) { + WMA_LOGE(FL("wmi_buf_len: %d > %d. Can't send wmi cmd"), + wmi_buf_len, BEACON_TX_BUFFER_SIZE); + return -EINVAL; + } + + wmi_buf = wmi_buf_alloc(wma->wmi_handle, wmi_buf_len); + if (!wmi_buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (wmi_prb_tmpl_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_prb_tmpl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_prb_tmpl_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->buf_len = tmpl_len; + buf_ptr += sizeof(wmi_prb_tmpl_cmd_fixed_param); + + bcn_prb_info = (wmi_bcn_prb_info *)buf_ptr; + WMITLV_SET_HDR(&bcn_prb_info->tlv_header, + WMITLV_TAG_STRUC_wmi_bcn_prb_info, + WMITLV_GET_STRUCT_TLVLEN(wmi_bcn_prb_info)); + bcn_prb_info->caps = 0; + bcn_prb_info->erp = 0; + buf_ptr += sizeof(wmi_bcn_prb_info); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, tmpl_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, frm, tmpl_len); + + ret = wmi_unified_cmd_send(wma->wmi_handle, + wmi_buf, wmi_buf_len, + WMI_PRB_TMPL_CMDID); + if (ret) { + WMA_LOGE(FL("Failed to send PRB RSP tmpl: %d"), ret); + wmi_buf_free(wmi_buf); + } + + return ret; +} + +static int wmi_unified_bcn_tmpl_send(tp_wma_handle wma, + u_int8_t vdev_id, + tpSendbeaconParams bcn_info, + u_int8_t bytes_to_strip) +{ + wmi_bcn_tmpl_cmd_fixed_param *cmd; + wmi_bcn_prb_info *bcn_prb_info; + wmi_buf_t wmi_buf; + u_int32_t tmpl_len, tmpl_len_aligned, wmi_buf_len; + u_int8_t *frm, *buf_ptr; + int ret; + u_int8_t *p2p_ie; + u_int16_t p2p_ie_len = 0; + u_int64_t adjusted_tsf_le; + struct ieee80211_frame *wh; + + + WMA_LOGD("Send beacon template for vdev %d", vdev_id); + + if (bcn_info->p2pIeOffset) { + p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset; + p2p_ie_len = (u_int16_t) p2p_ie[1] + 2; + } + + /* + * XXX: The first byte of beacon buffer contains beacon length + * only when UMAC in sending the beacon template. In othercases + * (ex: from tbtt update) beacon length is read from beacon + * information. + */ + if (bytes_to_strip) + tmpl_len = *(u_int32_t *)&bcn_info->beacon[0]; + else + tmpl_len = bcn_info->beaconLength; + if (p2p_ie_len) { + tmpl_len -= (u_int32_t) p2p_ie_len; + } + + frm = bcn_info->beacon + bytes_to_strip; + tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32)); + /* + * Make the TSF offset negative so beacons in the same + * staggered batch have the same TSF. + */ + adjusted_tsf_le = cpu_to_le64(0ULL - + wma->interfaces[vdev_id].tsfadjust); + /* Update the timstamp in the beacon buffer with adjusted TSF */ + wh = (struct ieee80211_frame *)frm; + A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le)); + + wmi_buf_len = sizeof(wmi_bcn_tmpl_cmd_fixed_param) + + sizeof(wmi_bcn_prb_info) + WMI_TLV_HDR_SIZE + + tmpl_len_aligned; + + wmi_buf = wmi_buf_alloc(wma->wmi_handle, wmi_buf_len); + if (!wmi_buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (wmi_bcn_tmpl_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_bcn_tmpl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_bcn_tmpl_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->tim_ie_offset = bcn_info->timIeOffset - bytes_to_strip; + cmd->buf_len = tmpl_len; + buf_ptr += sizeof(wmi_bcn_tmpl_cmd_fixed_param); + + bcn_prb_info = (wmi_bcn_prb_info *)buf_ptr; + WMITLV_SET_HDR(&bcn_prb_info->tlv_header, + WMITLV_TAG_STRUC_wmi_bcn_prb_info, + WMITLV_GET_STRUCT_TLVLEN(wmi_bcn_prb_info)); + bcn_prb_info->caps = 0; + bcn_prb_info->erp = 0; + buf_ptr += sizeof(wmi_bcn_prb_info); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, tmpl_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, frm, tmpl_len); + + ret = wmi_unified_cmd_send(wma->wmi_handle, + wmi_buf, wmi_buf_len, + WMI_BCN_TMPL_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send bcn tmpl: %d", __func__, ret); + wmi_buf_free(wmi_buf); + } + + return ret; +} + +VOS_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, u_int8_t vdev_id, + tpSendbeaconParams bcn_info) +{ + struct beacon_info *bcn; + u_int32_t len; + u_int8_t *bcn_payload; + struct beacon_tim_ie *tim_ie; + + bcn = wma->interfaces[vdev_id].beacon; + if (!bcn || !bcn->buf) { + WMA_LOGE("%s: Memory is not allocated to hold bcn template", + __func__); + return VOS_STATUS_E_INVAL; + } + + len = *(u32 *)&bcn_info->beacon[0]; + if (len > WMA_BCN_BUF_MAX_SIZE) { + WMA_LOGE("%s: Received beacon len %d exceeding max limit %d", + __func__, len, WMA_BCN_BUF_MAX_SIZE); + return VOS_STATUS_E_INVAL; + } + WMA_LOGD("%s: Storing received beacon template buf to local buffer", + __func__); + adf_os_spin_lock_bh(&bcn->lock); + + /* + * Copy received beacon template content in local buffer. + * this will be send to target on the reception of SWBA + * event from target. + */ + adf_nbuf_trim_tail(bcn->buf, adf_nbuf_len(bcn->buf)); + memcpy(adf_nbuf_data(bcn->buf), + bcn_info->beacon + 4 /* Exclude beacon length field */, + len); + if (bcn_info->timIeOffset > 3) + { + bcn->tim_ie_offset = bcn_info->timIeOffset - 4; + } + else + { + bcn->tim_ie_offset = bcn_info->timIeOffset; + } + + if (bcn_info->p2pIeOffset > 3) + { + bcn->p2p_ie_offset = bcn_info->p2pIeOffset - 4; + } + else + { + bcn->p2p_ie_offset = bcn_info->p2pIeOffset; + } + bcn_payload = adf_nbuf_data(bcn->buf); + if (bcn->tim_ie_offset) + { + tim_ie = (struct beacon_tim_ie *)(&bcn_payload[bcn->tim_ie_offset]); + /* + * Intial Value of bcn->dtim_count will be 0. + * But if the beacon gets updated then current dtim + * count will be restored + */ + tim_ie->dtim_count = bcn->dtim_count; + tim_ie->tim_bitctl = 0; + } + + adf_nbuf_put_tail(bcn->buf, len); + bcn->len = len; + + adf_os_spin_unlock_bh(&bcn->lock); + + return VOS_STATUS_SUCCESS; +} + + + +static int wma_tbtt_update_ind(tp_wma_handle wma, u_int8_t *buf) +{ + struct wma_txrx_node *intf; + struct beacon_info *bcn; + tSendbeaconParams bcn_info; + u_int32_t *adjusted_tsf = NULL; + u_int32_t if_id = 0, vdev_map; + u_int32_t num_tbttoffset_list; + wmi_tbtt_offset_event_fixed_param *tbtt_offset_event; + WMA_LOGI("%s: Enter", __func__); + if (!buf) { + WMA_LOGE("Invalid event buffer"); + return -EINVAL; + } + if (!wma) { + WMA_LOGE("Invalid wma handle"); + return -EINVAL; + } + intf = wma->interfaces; + tbtt_offset_event = (wmi_tbtt_offset_event_fixed_param *)buf; + vdev_map = tbtt_offset_event->vdev_map; + num_tbttoffset_list = *(u_int32_t *)(buf + sizeof(wmi_tbtt_offset_event_fixed_param)); + adjusted_tsf = (u_int32_t *) ((u_int8_t *)buf + + sizeof(wmi_tbtt_offset_event_fixed_param) + + sizeof (u_int32_t)); + if (!adjusted_tsf) { + WMA_LOGE("%s: Invalid adjusted_tsf", __func__); + return -EINVAL; + } + + for ( ;(vdev_map); vdev_map >>= 1, if_id++) { + if (!(vdev_map & 0x1) || (!(intf[if_id].handle))) + continue; + + bcn = intf[if_id].beacon; + if (!bcn) { + WMA_LOGE("%s: Invalid beacon", __func__); + return -EINVAL; + } + if (!bcn->buf) { + WMA_LOGE("%s: Invalid beacon buffer", __func__); + return -EINVAL; + } + /* Save the adjusted TSF */ + intf[if_id].tsfadjust = adjusted_tsf[if_id]; + + adf_os_spin_lock_bh(&bcn->lock); + vos_mem_zero(&bcn_info, sizeof(bcn_info)); + bcn_info.beacon = adf_nbuf_data(bcn->buf); + bcn_info.p2pIeOffset = bcn->p2p_ie_offset; + bcn_info.beaconLength = bcn->len; + bcn_info.timIeOffset = bcn->tim_ie_offset; + adf_os_spin_unlock_bh(&bcn->lock); + + /* Update beacon template in firmware */ + wmi_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0); + } + return 0; +} + +static int wma_tbttoffset_update_event_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf; + wmi_tbtt_offset_event_fixed_param *tbtt_offset_event; + u_int8_t *buf, *tempBuf; + vos_msg_t vos_msg = {0}; + + param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)event; + if(!param_buf) { + WMA_LOGE("Invalid tbtt update event buffer"); + return -EINVAL; + } + + tbtt_offset_event = param_buf->fixed_param; + buf = vos_mem_malloc(sizeof(wmi_tbtt_offset_event_fixed_param) + + sizeof (u_int32_t) + + (param_buf->num_tbttoffset_list * sizeof (u_int32_t))); + if (!buf) { + WMA_LOGE("%s: Failed alloc memory for buf", __func__); + return -EINVAL; + } + + tempBuf = buf; + vos_mem_zero(buf, (sizeof(wmi_tbtt_offset_event_fixed_param) + + sizeof (u_int32_t) + + (param_buf->num_tbttoffset_list * sizeof (u_int32_t)))); + vos_mem_copy(buf, (u_int8_t *)tbtt_offset_event, sizeof (wmi_tbtt_offset_event_fixed_param)); + buf += sizeof (wmi_tbtt_offset_event_fixed_param); + + vos_mem_copy(buf, (u_int8_t *) ¶m_buf->num_tbttoffset_list, sizeof (u_int32_t)); + buf += sizeof(u_int32_t); + + vos_mem_copy(buf, (u_int8_t *)param_buf->tbttoffset_list, (param_buf->num_tbttoffset_list * sizeof(u_int32_t))); + + vos_msg.type = WDA_TBTT_UPDATE_IND; + vos_msg.bodyptr = tempBuf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGP("%s: Failed to post WDA_TBTT_UPDATE_IND msg", __func__); + vos_mem_free(tempBuf); + return -1; + } + WMA_LOGD("WDA_TBTT_UPDATE_IND posted"); + return 0; +} + + +static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle, + A_UINT32 vdev_id, u_int8_t *p2pIe) +{ + int ret; + wmi_p2p_go_set_beacon_ie_fixed_param *cmd; + wmi_buf_t wmi_buf; + u_int32_t ie_len, ie_len_aligned, wmi_buf_len; + u_int8_t *buf_ptr; + + ie_len = (u_int32_t) (p2pIe[1] + 2); + + /* More than one P2P IE may be included in a single frame. + If multiple P2P IEs are present, the complete P2P attribute + data consists of the concatenation of the P2P Attribute + fields of the P2P IEs. The P2P Attributes field of each + P2P IE may be any length up to the maximum (251 octets). + In this case host sends one P2P IE to firmware so the length + should not exceed more than 251 bytes + */ + if (ie_len > 251) { + WMA_LOGE("%s : invalid p2p ie length %u", __func__, ie_len); + return -EINVAL; + } + + ie_len_aligned = roundup(ie_len, sizeof(A_UINT32)); + + wmi_buf_len = sizeof(wmi_p2p_go_set_beacon_ie_fixed_param) + ie_len_aligned + WMI_TLV_HDR_SIZE; + + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, wmi_buf_len); + if (!wmi_buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (wmi_p2p_go_set_beacon_ie_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_p2p_go_set_beacon_ie_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_p2p_go_set_beacon_ie_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->ie_buf_len = ie_len; + + buf_ptr += sizeof(wmi_p2p_go_set_beacon_ie_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, p2pIe, ie_len); + + WMA_LOGI("%s: Sending WMI_P2P_GO_SET_BEACON_IE", __func__); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, + wmi_buf, wmi_buf_len, + WMI_P2P_GO_SET_BEACON_IE + ); + if (ret) { + WMA_LOGE("Failed to send bcn tmpl: %d", ret); + wmi_buf_free(wmi_buf); + } + + WMA_LOGI("%s: Successfully sent WMI_P2P_GO_SET_BEACON_IE", __func__); + return ret; +} + +static void wma_send_probe_rsp_tmpl(tp_wma_handle wma, + tpSendProbeRespParams probe_rsp_info) +{ + ol_txrx_vdev_handle vdev; + u_int8_t vdev_id; + tpAniProbeRspStruct probe_rsp; + + if(!probe_rsp_info) { + WMA_LOGE(FL("probe_rsp_info is NULL")); + return; + } + + probe_rsp = (tpAniProbeRspStruct)(probe_rsp_info->pProbeRespTemplate); + if(!probe_rsp) { + WMA_LOGE(FL("probe_rsp is NULL")); + return; + } + + vdev = wma_find_vdev_by_addr(wma, probe_rsp->macHdr.sa, &vdev_id); + if (!vdev) { + WMA_LOGE(FL("failed to get vdev handle")); + return; + } + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BEACON_OFFLOAD)) { + WMA_LOGI("Beacon Offload Enabled Sending Unified command"); + if (wmi_unified_probe_rsp_tmpl_send(wma, vdev_id, + probe_rsp_info) < 0){ + WMA_LOGE(FL("wmi_unified_probe_rsp_tmpl_send Failed ")); + return; + } + } +} + +static void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) +{ + ol_txrx_vdev_handle vdev; + u_int8_t vdev_id; + VOS_STATUS status; + u_int8_t *p2p_ie; + tpAniBeaconStruct beacon; + + beacon = (tpAniBeaconStruct)(bcn_info->beacon); + vdev = wma_find_vdev_by_addr(wma, beacon->macHdr.sa, &vdev_id); + if (!vdev) { + WMA_LOGE("%s : failed to get vdev handle", __func__); + return; + } + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BEACON_OFFLOAD)) { + WMA_LOGI("Beacon Offload Enabled Sending Unified command"); + if (wmi_unified_bcn_tmpl_send(wma, vdev_id, bcn_info, 4) < 0){ + WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ", __func__); + return; + } + + if (bcn_info->p2pIeOffset) { + p2p_ie = bcn_info->beacon + bcn_info->p2pIeOffset; + WMA_LOGI(" %s: p2pIe is present - vdev_id %hu, p2p_ie = %p, p2p ie len = %hu", + __func__, vdev_id, p2p_ie, p2p_ie[1]); + if (wma_p2p_go_set_beacon_ie(wma, vdev_id, p2p_ie) < 0) { + WMA_LOGE("%s : wmi_unified_bcn_tmpl_send Failed ", __func__); + return; + } + } + } + status = wma_store_bcn_tmpl(wma, vdev_id, bcn_info); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__); + return; + } + if (!wma->interfaces[vdev_id].vdev_up) { + if (wmi_unified_vdev_up_send(wma->wmi_handle, vdev_id, 0, + bcn_info->bssId) < 0) { + WMA_LOGE("%s : failed to send vdev up", __func__); + return; + } + wma->interfaces[vdev_id].vdev_up = TRUE; + wma_set_sap_keepalive(wma, vdev_id); + } +} + +#if !defined(REMOVE_PKT_LOG) +static VOS_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle, + struct ath_pktlog_wmi_params *params) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_PKTLOG_EVENT PKTLOG_EVENT; + WMI_CMD_ID CMD_ID; + wmi_pdev_pktlog_enable_cmd_fixed_param *cmd; + wmi_pdev_pktlog_disable_cmd_fixed_param *disable_cmd; + int len = 0; + wmi_buf_t buf; + + /*Check if packet log is enabled in cfg.ini*/ + if (! vos_is_packet_log_enabled()) + { + WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__); + return VOS_STATUS_E_FAILURE; + } + + + PKTLOG_EVENT = params->pktlog_event; + CMD_ID = params->cmd_id; + + switch (CMD_ID) { + case WMI_PDEV_PKTLOG_ENABLE_CMDID: + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + cmd = + (wmi_pdev_pktlog_enable_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_pktlog_enable_cmd_fixed_param)); + cmd->evlist = PKTLOG_EVENT; + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_PDEV_PKTLOG_ENABLE_CMDID)) { + WMA_LOGE("failed to send pktlog enable cmdid"); + goto wmi_send_failed; + } + break; + case WMI_PDEV_PKTLOG_DISABLE_CMDID: + len = sizeof(*disable_cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + disable_cmd = (wmi_pdev_pktlog_disable_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&disable_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_pktlog_disable_cmd_fixed_param)); + disable_cmd->reserved0 = 0; + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_PDEV_PKTLOG_DISABLE_CMDID)) { + WMA_LOGE("failed to send pktlog disable cmdid"); + goto wmi_send_failed; + } + break; + default: + WMA_LOGD("%s: invalid PKTLOG command", __func__); + break; + } + + return VOS_STATUS_SUCCESS; + +wmi_send_failed: + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; +} +#endif + +static int32_t wmi_unified_set_sta_ps(wmi_unified_t wmi_handle, + u_int32_t vdev_id, u_int8_t val) +{ + wmi_sta_powersave_mode_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + WMA_LOGD("Set Sta Mode Ps vdevId %d val %d", vdev_id, val); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: Set Sta Mode Ps Mem Alloc Failed", __func__); + return -ENOMEM; + } + cmd = (wmi_sta_powersave_mode_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_powersave_mode_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_powersave_mode_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + if(val) + cmd->sta_ps_mode = WMI_STA_PS_MODE_ENABLED; + else + cmd->sta_ps_mode = WMI_STA_PS_MODE_DISABLED; + + if(wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_STA_POWERSAVE_MODE_CMDID)) + { + WMA_LOGE("Set Sta Mode Ps Failed vdevId %d val %d", + vdev_id, val); + adf_nbuf_free(buf); + return -EIO; + } + return 0; +} + +static inline u_int32_t wma_get_uapsd_mask(tpUapsd_Params uapsd_params) +{ + u_int32_t uapsd_val = 0; + + if(uapsd_params->beDeliveryEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC0_DELIVERY_EN; + + if(uapsd_params->beTriggerEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC0_TRIGGER_EN; + + if(uapsd_params->bkDeliveryEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC1_DELIVERY_EN; + + if(uapsd_params->bkTriggerEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC1_TRIGGER_EN; + + if(uapsd_params->viDeliveryEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC2_DELIVERY_EN; + + if(uapsd_params->viTriggerEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC2_TRIGGER_EN; + + if(uapsd_params->voDeliveryEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC3_DELIVERY_EN; + + if(uapsd_params->voTriggerEnabled) + uapsd_val |= WMI_STA_PS_UAPSD_AC3_TRIGGER_EN; + + return uapsd_val; +} + +static int32_t wma_set_force_sleep(tp_wma_handle wma, u_int32_t vdev_id, + u_int8_t enable, enum powersave_qpower_mode qpower_config) +{ + int32_t ret; + tANI_U32 cfg_data_val = 0; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *mac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + u_int32_t rx_wake_policy; + u_int32_t tx_wake_threshold; + u_int32_t pspoll_count; + u_int32_t inactivity_time; + u_int32_t psmode; + + WMA_LOGD("Set Force Sleep vdevId %d val %d", vdev_id, enable); + + if (NULL == mac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return -ENOMEM; + } + + /* Set Tx/Rx Data InActivity Timeout */ + if (wlan_cfgGetInt(mac, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + &cfg_data_val ) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT"); + cfg_data_val = POWERSAVE_DEFAULT_INACTIVITY_TIME; + } + inactivity_time = (u_int32_t)cfg_data_val; + + if (enable) { + /* override normal configuration and force station asleep */ + rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD; + tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER; + + if (wlan_cfgGetInt(mac, WNI_CFG_MAX_PS_POLL, + &cfg_data_val ) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_MAX_PS_POLL"); + } + if (cfg_data_val) + pspoll_count = (u_int32_t)cfg_data_val; + else + pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE; + + psmode = WMI_STA_PS_MODE_ENABLED; + } else { + /* Ps Poll Wake Policy */ + if (wlan_cfgGetInt(mac, WNI_CFG_MAX_PS_POLL, + &cfg_data_val ) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_MAX_PS_POLL"); + } + if (cfg_data_val) { + /* Ps Poll is enabled */ + rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD; + pspoll_count = (u_int32_t)cfg_data_val; + tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER; + } else { + rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_WAKE; + pspoll_count = WMI_STA_PS_PSPOLL_COUNT_NO_MAX; + tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS; + } + psmode = WMI_STA_PS_MODE_ENABLED; + } + + /* + * QPower is enabled by default in Firmware + * So Disable QPower explicitly + */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_ENABLE_QPOWER, qpower_config); + if (ret) { + WMA_LOGE("Disable QPower Failed vdevId %d", vdev_id); + return ret; + } + WMA_LOGD("QPower Disabled vdevId %d", vdev_id); + + /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD*/ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_RX_WAKE_POLICY, + rx_wake_policy); + + if (ret) { + WMA_LOGE("Setting wake policy Failed vdevId %d", vdev_id); + return ret; + } + WMA_LOGD("Setting wake policy to %d vdevId %d", + rx_wake_policy, vdev_id); + + /* Set the Tx Wake Threshold */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD, + tx_wake_threshold); + + if (ret) { + WMA_LOGE("Setting TxWake Threshold vdevId %d", vdev_id); + return ret; + } + WMA_LOGD("Setting TxWake Threshold to %d vdevId %d", + tx_wake_threshold, vdev_id); + + /* Set the Ps Poll Count */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_PSPOLL_COUNT, + pspoll_count); + + if (ret) { + WMA_LOGE("Set Ps Poll Count Failed vdevId %d ps poll cnt %d", + vdev_id, pspoll_count); + return ret; + } + WMA_LOGD("Set Ps Poll Count vdevId %d ps poll cnt %d", + vdev_id, pspoll_count); + + /* Set the Tx/Rx InActivity */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_INACTIVITY_TIME, + inactivity_time); + + if (ret) { + WMA_LOGE("Setting Tx/Rx InActivity Failed vdevId %d InAct %d", + vdev_id, inactivity_time); + return ret; + } + WMA_LOGD("Set Tx/Rx InActivity vdevId %d InAct %d", + vdev_id, inactivity_time); + + /* Enable Sta Mode Power save */ + ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true); + + if (ret) { + WMA_LOGE("Enable Sta Mode Ps Failed vdevId %d", vdev_id); + return ret; + } + + /* Set Listen Interval */ + if (wlan_cfgGetInt(mac, WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val ) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_LISTEN_INTERVAL"); + cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_LISTEN_INTERVAL, + cfg_data_val); + if (ret) { + /* Even it fails continue Fw will take default LI */ + WMA_LOGE("Failed to Set Listen Interval vdevId %d", + vdev_id); + } + WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, cfg_data_val); + return 0; +} + +int32_t wma_set_qpower_force_sleep(tp_wma_handle wma, u_int32_t vdev_id, + u_int8_t enable) +{ + int32_t ret; + tANI_U32 cfg_data_val = 0; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *mac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + u_int32_t pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE; + + WMA_LOGE("Set QPower Force(1)/Normal(0) Sleep vdevId %d val %d", + vdev_id, enable); + + if (NULL == mac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return -ENOMEM; + } + + /* Get Configured Ps Poll Count */ + if (wlan_cfgGetInt(mac, WNI_CFG_MAX_PS_POLL, + &cfg_data_val ) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_MAX_PS_POLL"); + } + if (cfg_data_val) { + pspoll_count = (u_int32_t)cfg_data_val; + } + + /* Enable QPower */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_ENABLE_QPOWER, 1); + + if (ret) { + WMA_LOGE("Enable QPower Failed vdevId %d", vdev_id); + return ret; + } + WMA_LOGD("QPower Enabled vdevId %d", vdev_id); + + /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD*/ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_RX_WAKE_POLICY, + WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD); + + if (ret) { + WMA_LOGE("Setting wake policy to pspoll/uapsd Failed vdevId %d", vdev_id); + return ret; + } + WMA_LOGD("Wake policy set to to pspoll/uapsd vdevId %d", + vdev_id); + + if (enable) { + /* Set the Tx Wake Threshold */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD, + WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER); + + if (ret) { + WMA_LOGE("Setting TxWake Threshold vdevId %d", vdev_id); + return ret; + } + WMA_LOGD("TxWake Threshold set to TX_WAKE_THRESHOLD_NEVER %d", vdev_id); + } + + /* Set the QPower Ps Poll Count */ + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT, + pspoll_count); + + if (ret) { + WMA_LOGE("Set QPower Ps Poll Count Failed vdevId %d ps poll cnt %d", + vdev_id, pspoll_count); + return ret; + } + WMA_LOGD("Set QPower Ps Poll Count vdevId %d ps poll cnt %d", + vdev_id, pspoll_count); + + /* Enable Sta Mode Power save */ + ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true); + + if (ret) { + WMA_LOGE("Enable Sta Mode Ps Failed vdevId %d", vdev_id); + return ret; + } + + /* Set Listen Interval */ + if (wlan_cfgGetInt(mac, WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val ) != eSIR_SUCCESS) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_LISTEN_INTERVAL"); + cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_LISTEN_INTERVAL, + cfg_data_val); + if (ret) { + /* Even it fails continue Fw will take default LI */ + WMA_LOGE("Failed to Set Listen Interval vdevId %d", + vdev_id); + } + WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, cfg_data_val); + return 0; +} + +/** + * wma_get_qpower_config() - get qpower configuration + * @wma: WMA handle + * + * Power Save Offload configuration: + * 0 -> Power save offload is disabled + * 1 -> Legacy Power save enabled + Deep sleep Disabled + * 2 -> QPower enabled + Deep sleep Disabled + * 3 -> Legacy Power save enabled + Deep sleep Enabled + * 4 -> QPower enabled + Deep sleep Enabled + * 5 -> Duty cycling QPower enabled + * + * Return: enum powersave_qpower_mode with below values + * QPOWER_DISABLED if QPOWER is disabled + * QPOWER_ENABLED if QPOWER is enabled + * QPOWER_DUTY_CYCLING if DUTY CYCLING QPOWER is enabled + */ +static enum powersave_qpower_mode wma_get_qpower_config(tp_wma_handle wma) +{ + switch (wma->powersave_mode) { + case PS_QPOWER_NODEEPSLEEP: + case PS_QPOWER_DEEPSLEEP: + WMA_LOGI("QPOWER is enabled in power save mode %d", + wma->powersave_mode); + return QPOWER_ENABLED; + case PS_DUTY_CYCLING_QPOWER: + WMA_LOGI("DUTY cycling QPOWER is enabled in power save mode %d", + wma->powersave_mode); + return QPOWER_DUTY_CYCLING; + + default: + WMA_LOGI("QPOWER is disabled in power save mode %d", + wma->powersave_mode); + return QPOWER_DISABLED; + } +} + +static void wma_enable_sta_ps_mode(tp_wma_handle wma, tpEnablePsParams ps_req) +{ + uint32_t vdev_id = ps_req->sessionid; + int32_t ret; + enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma); + struct wma_txrx_node *iface = &wma->interfaces[vdev_id]; + + if (eSIR_ADDON_NOTHING == ps_req->psSetting) { + WMA_LOGD("Enable Sta Mode Ps vdevId %d", vdev_id); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_UAPSD, 0); + if (ret) { + WMA_LOGE("Set Uapsd param 0 Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + ret = wma_set_force_sleep(wma, vdev_id, false, + qpower_config); + if (ret) { + WMA_LOGE("Enable Sta Ps Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + } else if (eSIR_ADDON_ENABLE_UAPSD == ps_req->psSetting) { + u_int32_t uapsd_val = 0; + uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams); + + if(uapsd_val != iface->uapsd_cached_val) { + WMA_LOGD("Enable Uapsd vdevId %d Mask %d", + vdev_id, uapsd_val); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vdev_id, WMI_STA_PS_PARAM_UAPSD, + uapsd_val); + if (ret) { + WMA_LOGE("Enable Uapsd Failed vdevId %d", + vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + /* Cache the Uapsd Mask */ + iface->uapsd_cached_val = uapsd_val; + } else { + WMA_LOGD("Already Uapsd Enabled vdevId %d Mask %d", + vdev_id, uapsd_val); + } + + WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id); + + ret = wma_set_force_sleep(wma, vdev_id, true, + qpower_config); + + if (ret) { + WMA_LOGE("Enable Forced Sleep Failed vdevId %d", + vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + } + ps_req->status = VOS_STATUS_SUCCESS; + iface->dtimPeriod = ps_req->bcnDtimPeriod; +resp: + wma_send_msg(wma, WDA_ENTER_BMPS_RSP, ps_req, 0); +} + +static void wma_disable_sta_ps_mode(tp_wma_handle wma, tpDisablePsParams ps_req) +{ + int32_t ret; + uint32_t vdev_id = ps_req->sessionid; + + WMA_LOGD("Disable Sta Mode Ps vdevId %d", vdev_id); + + /* Disable Sta Mode Power save */ + ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false); + if(ret) { + WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + /* Disable UAPSD incase if additional Req came */ + if (eSIR_ADDON_DISABLE_UAPSD == ps_req->psSetting) { + WMA_LOGD("Disable Uapsd vdevId %d", vdev_id); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_UAPSD, 0); + if (ret) { + WMA_LOGE("Disable Uapsd Failed vdevId %d", vdev_id); + /* + * Even this fails we can proceed as success + * since we disabled powersave + */ + } + } + + ps_req->status = VOS_STATUS_SUCCESS; +resp: + wma_send_msg(wma, WDA_EXIT_BMPS_RSP, ps_req, 0); +} + +static void wma_enable_uapsd_mode(tp_wma_handle wma, + tpEnableUapsdParams ps_req) +{ + int32_t ret; + u_int32_t vdev_id = ps_req->sessionid; + u_int32_t uapsd_val = 0; + enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma); + + /* Disable Sta Mode Power save */ + ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false); + if (ret) { + WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams); + + WMA_LOGD("Enable Uapsd vdevId %d Mask %d", vdev_id, uapsd_val); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_UAPSD, uapsd_val); + if (ret) { + WMA_LOGE("Enable Uapsd Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id); + + ret = wma_set_force_sleep(wma, vdev_id, true, + qpower_config); + if (ret) { + WMA_LOGE("Enable Forced Sleep Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + ps_req->status = VOS_STATUS_SUCCESS; +resp: + wma_send_msg(wma, WDA_ENTER_UAPSD_RSP, ps_req, 0); +} + +static void wma_disable_uapsd_mode(tp_wma_handle wma, + tpDisableUapsdParams ps_req) +{ + int32_t ret; + u_int32_t vdev_id = ps_req->sessionid; + enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma); + + WMA_LOGD("Disable Uapsd vdevId %d", vdev_id); + + /* Disable Sta Mode Power save */ + ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false); + if (ret) { + WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_UAPSD, 0); + if (ret) { + WMA_LOGE("Disable Uapsd Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + /* Re enable Sta Mode Powersave with proper configuration */ + ret = wma_set_force_sleep(wma, vdev_id, false, + qpower_config); + if (ret) { + WMA_LOGE("Disable Forced Sleep Failed vdevId %d", vdev_id); + ps_req->status = VOS_STATUS_E_FAILURE; + goto resp; + } + + ps_req->status = VOS_STATUS_SUCCESS; +resp: + wma_send_msg(wma, WDA_EXIT_UAPSD_RSP, ps_req, 0); +} + +static void wma_set_keepalive_req(tp_wma_handle wma, + tSirKeepAliveReq *keepalive) +{ + WMA_LOGD("KEEPALIVE:PacketType:%d", keepalive->packetType); + wma_set_sta_keep_alive(wma, keepalive->sessionId, + keepalive->packetType, + keepalive->timePeriod, + keepalive->hostIpv4Addr, + keepalive->destIpv4Addr, + keepalive->destMacAddr); + + vos_mem_free(keepalive); +} +/* + * This function sets the trigger uapsd + * params such as service interval, delay + * interval and suspend interval which + * will be used by the firmware to send + * trigger frames periodically when there + * is no traffic on the transmit side. + */ +int32_t +wmi_unified_set_sta_uapsd_auto_trig_cmd( + wmi_unified_t wmi_handle, + u_int32_t vdevid, + u_int8_t peer_addr[IEEE80211_ADDR_LEN], + u_int8_t *autoTriggerparam, + u_int32_t num_ac) +{ + wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd; + int32_t ret; + u_int32_t param_len = num_ac * + sizeof(wmi_sta_uapsd_auto_trig_param); + u_int32_t cmd_len = sizeof(*cmd) + param_len + WMI_TLV_HDR_SIZE; + u_int32_t i; + wmi_buf_t buf; + u_int8_t *buf_ptr; + + buf = wmi_buf_alloc(wmi_handle, cmd_len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_sta_uapsd_auto_trig_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_uapsd_auto_trig_cmd_fixed_param)); + cmd->vdev_id = vdevid; + cmd->num_ac = num_ac; + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr); + + /* TLV indicating array of structures to follow */ + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, param_len); + + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, autoTriggerparam, param_len); + + /* + * Update tag and length for uapsd auto trigger params (this will take + * care of updating tag and length if it is not pre-filled by caller). + */ + for (i = 0; i < num_ac; i++) { + WMITLV_SET_HDR((buf_ptr + + (i * sizeof(wmi_sta_uapsd_auto_trig_param))), + WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_uapsd_auto_trig_param)); + } + + ret = wmi_unified_cmd_send(wmi_handle, buf, cmd_len, + WMI_STA_UAPSD_AUTO_TRIG_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send set uapsd param ret = %d", ret); + wmi_buf_free(buf); + } + return ret; +} + +/* + * This function sets the trigger uapsd + * params such as service interval, delay + * interval and suspend interval which + * will be used by the firmware to send + * trigger frames periodically when there + * is no traffic on the transmit side. + */ +VOS_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, u_int32_t vdev_id, + tp_wma_trigger_uapsd_params trigger_uapsd_params) +{ + int32_t ret; + wmi_sta_uapsd_auto_trig_param uapsd_trigger_param; + + WMA_LOGD("Trigger uapsd params vdev id %d", vdev_id); + + WMA_LOGD("WMM AC %d User Priority %d SvcIntv %d DelIntv %d SusIntv %d", + trigger_uapsd_params->wmm_ac, + trigger_uapsd_params->user_priority, + trigger_uapsd_params->service_interval, + trigger_uapsd_params->delay_interval, + trigger_uapsd_params->suspend_interval); + + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_STA_UAPSD_BASIC_AUTO_TRIG) || + !WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_STA_UAPSD_VAR_AUTO_TRIG)) { + WMA_LOGD("Trigger uapsd is not supported vdev id %d", vdev_id); + return VOS_STATUS_SUCCESS; + } + + uapsd_trigger_param.wmm_ac = + trigger_uapsd_params->wmm_ac; + uapsd_trigger_param.user_priority = + trigger_uapsd_params->user_priority; + uapsd_trigger_param.service_interval = + trigger_uapsd_params->service_interval; + uapsd_trigger_param.suspend_interval = + trigger_uapsd_params->suspend_interval; + uapsd_trigger_param.delay_interval = + trigger_uapsd_params->delay_interval; + + ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle, vdev_id, + wma_handle->interfaces[vdev_id].bssid, + (u_int8_t*)(&uapsd_trigger_param), + 1); + if (ret) { + WMA_LOGE("Fail to send uapsd param cmd for vdevid %d ret = %d", + ret, vdev_id); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle, + u_int32_t vdev_id, + enum uapsd_ac ac) +{ + int32_t ret; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + wmi_sta_uapsd_auto_trig_param uapsd_trigger_param; + enum uapsd_up user_priority; + + WMA_LOGD("Disable Uapsd per ac vdevId %d ac %d", vdev_id, ac); + + switch (ac) { + case UAPSD_VO: + iface->uapsd_cached_val &= + ~(WMI_STA_PS_UAPSD_AC3_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC3_TRIGGER_EN); + user_priority = UAPSD_UP_VO; + break; + case UAPSD_VI: + iface->uapsd_cached_val &= + ~(WMI_STA_PS_UAPSD_AC2_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC2_TRIGGER_EN); + user_priority = UAPSD_UP_VI; + break; + case UAPSD_BK: + iface->uapsd_cached_val &= + ~(WMI_STA_PS_UAPSD_AC1_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC1_TRIGGER_EN); + user_priority = UAPSD_UP_BK; + break; + case UAPSD_BE: + iface->uapsd_cached_val &= + ~(WMI_STA_PS_UAPSD_AC0_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC0_TRIGGER_EN); + user_priority = UAPSD_UP_BE; + break; + default: + WMA_LOGE("Invalid AC vdevId %d ac %d", vdev_id, ac); + return VOS_STATUS_E_FAILURE; + } + + /* + * Disable Auto Trigger Functionality before + * disabling uapsd for a particular AC + */ + uapsd_trigger_param.wmm_ac = ac; + uapsd_trigger_param.user_priority = user_priority; + uapsd_trigger_param.service_interval = 0; + uapsd_trigger_param.suspend_interval = 0; + uapsd_trigger_param.delay_interval = 0; + + ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle, + vdev_id, + wma_handle->interfaces[vdev_id].bssid, + (u_int8_t*)(&uapsd_trigger_param), + 1); + if (ret) { + WMA_LOGE("Fail to send auto trig cmd for vdevid %d ret = %d", + ret, vdev_id); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_set_sta_ps_param(wma_handle->wmi_handle, vdev_id, + WMI_STA_PS_PARAM_UAPSD, iface->uapsd_cached_val); + if (ret) { + WMA_LOGE("Disable Uapsd per ac Failed vdevId %d ac %d", vdev_id, ac); + return VOS_STATUS_E_FAILURE; + } + WMA_LOGD("Disable Uapsd per ac vdevId %d val %d", vdev_id, + iface->uapsd_cached_val); + return VOS_STATUS_SUCCESS; +} + +#ifdef FEATURE_WLAN_SCAN_PNO + +/* Request FW to start PNO operation */ +static VOS_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) +{ + wmi_nlo_config_cmd_fixed_param *cmd; + nlo_configured_parameters *nlo_list; + u_int32_t *channel_list; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + u_int8_t i; + int ret; + + WMA_LOGD("PNO Start"); + + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE + /* TLV place holder for array of structures nlo_configured_parameters(nlo_list) */ + WMI_TLV_HDR_SIZE; /* TLV place holder for array of uint32 channel_list */ + + len += sizeof(u_int32_t) * MIN(pno->aNetworks[0].ucChannelCount, + WMI_NLO_MAX_CHAN); + len += sizeof(nlo_configured_parameters) * + MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (u_int8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_nlo_config_cmd_fixed_param)); + cmd->vdev_id = pno->sessionId; + cmd->flags = WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN; + + /* Current FW does not support min-max range for dwell time */ + cmd->active_dwell_time = pno->active_max_time; + cmd->passive_dwell_time = pno->passive_max_time; + + if (pno->do_passive_scan) + cmd->flags |= WMI_NLO_CONFIG_SCAN_PASSIVE; + /* Copy scan interval */ + cmd->fast_scan_period = pno->fast_scan_period; + cmd->slow_scan_period = pno->slow_scan_period; + cmd->fast_scan_max_cycles = pno->fast_scan_max_cycles; + WMA_LOGD("fast_scan_period: %d msec slow_scan_period: %d msec", + cmd->fast_scan_period, cmd->slow_scan_period); + WMA_LOGD("fast_scan_max_cycles: %d", cmd->fast_scan_max_cycles); + + buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param); + + cmd->no_of_ssids = MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS); + WMA_LOGD("SSID count : %d", cmd->no_of_ssids); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + cmd->no_of_ssids * sizeof(nlo_configured_parameters)); + buf_ptr += WMI_TLV_HDR_SIZE; + + nlo_list = (nlo_configured_parameters *) buf_ptr; + for (i = 0; i < cmd->no_of_ssids; i++) { + WMITLV_SET_HDR(&nlo_list[i].tlv_header, + WMITLV_TAG_ARRAY_BYTE, + WMITLV_GET_STRUCT_TLVLEN(nlo_configured_parameters)); + /* Copy ssid and it's length */ + nlo_list[i].ssid.valid = TRUE; + nlo_list[i].ssid.ssid.ssid_len = pno->aNetworks[i].ssId.length; + vos_mem_copy(nlo_list[i].ssid.ssid.ssid, + pno->aNetworks[i].ssId.ssId, + nlo_list[i].ssid.ssid.ssid_len); + WMA_LOGD("index: %d ssid: %.*s len: %d", i, + nlo_list[i].ssid.ssid.ssid_len, + (char *) nlo_list[i].ssid.ssid.ssid, + nlo_list[i].ssid.ssid.ssid_len); + + /* Copy rssi threshold */ + if (pno->aNetworks[i].rssiThreshold && + pno->aNetworks[i].rssiThreshold > WMA_RSSI_THOLD_DEFAULT) { + nlo_list[i].rssi_cond.valid = TRUE; + nlo_list[i].rssi_cond.rssi = + pno->aNetworks[i].rssiThreshold; + WMA_LOGD("RSSI threshold : %d dBm", + nlo_list[i].rssi_cond.rssi); + } + nlo_list[i].bcast_nw_type.valid = TRUE; + nlo_list[i].bcast_nw_type.bcast_nw_type = + pno->aNetworks[i].bcastNetwType; + WMA_LOGI("Broadcast NW type (%u)", + nlo_list[i].bcast_nw_type.bcast_nw_type); + } + buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters); + + /* Copy channel info */ + cmd->num_of_channels = MIN(pno->aNetworks[0].ucChannelCount, + WMI_NLO_MAX_CHAN); + WMA_LOGD("Channel count: %d", cmd->num_of_channels); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (cmd->num_of_channels * sizeof(u_int32_t))); + buf_ptr += WMI_TLV_HDR_SIZE; + + channel_list = (u_int32_t *) buf_ptr; + for (i = 0; i < cmd->num_of_channels; i++) { + channel_list[i] = pno->aNetworks[0].aChannels[i]; + + if (channel_list[i] < WMA_NLO_FREQ_THRESH) + channel_list[i] = vos_chan_to_freq(channel_list[i]); + + WMA_LOGD("Ch[%d]: %d MHz", i, channel_list[i]); + } + buf_ptr += cmd->num_of_channels * sizeof(u_int32_t); + + /* TODO: Discrete firmware doesn't have command/option to configure + * App IE which comes from wpa_supplicant as of part PNO start request. + */ + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + wma->interfaces[pno->sessionId].pno_in_progress = TRUE; + + WMA_LOGD("PNO start request sent successfully for vdev %d", + pno->sessionId); + + return VOS_STATUS_SUCCESS; +} + +/* Request FW to stop ongoing PNO operation */ +static VOS_STATUS wma_pno_stop(tp_wma_handle wma, u_int8_t vdev_id) +{ + wmi_nlo_config_cmd_fixed_param *cmd; + int32_t len = sizeof(*cmd); + wmi_buf_t buf; + u_int8_t *buf_ptr; + int ret; + + if (!wma->interfaces[vdev_id].pno_in_progress) { + WMA_LOGD("No active pno session found for vdev %d, skip pno stop request", + vdev_id); + return VOS_STATUS_SUCCESS; + } + + WMA_LOGD("PNO Stop"); + + len += WMI_TLV_HDR_SIZE + /* TLV place holder for array of structures nlo_configured_parameters(nlo_list) */ + WMI_TLV_HDR_SIZE; /* TLV place holder for array of uint32 channel_list */ + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf); + buf_ptr = (u_int8_t *) cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_nlo_config_cmd_fixed_param)); + + cmd->vdev_id = vdev_id; + cmd->flags = WMI_NLO_CONFIG_STOP; + buf_ptr += sizeof(*cmd); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + wma->interfaces[vdev_id].pno_in_progress = FALSE; + + WMA_LOGD("PNO stop request sent successfully for vdev %d", + vdev_id); + + return VOS_STATUS_SUCCESS; +} + +static void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno) +{ + VOS_STATUS ret; + + if (pno->enable) + ret = wma_pno_start(wma, pno); + else + ret = wma_pno_stop(wma, pno->sessionId); + + if (ret) + WMA_LOGE("%s: PNO %s failed %d", __func__, + pno->enable ? "start" : "stop", ret); + + /* SME expects WMA to free tpSirPNOScanReq memory after + * processing PNO request. */ + vos_mem_free(pno); +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +static VOS_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm) +{ + wmi_vdev_plmreq_start_cmd_fixed_param *cmd; + u_int32_t *channel_list; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + u_int8_t count; + int ret; + + if (NULL == plm || NULL == wma) { + WMA_LOGE("%s: input pointer is NULL ", __func__); + return VOS_STATUS_E_FAILURE; + } + WMA_LOGD("PLM Start"); + + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE; /* TLV place holder for channel_list */ + len += sizeof(u_int32_t) * plm->plmNumCh; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + cmd = (wmi_vdev_plmreq_start_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (u_int8_t *) cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_plmreq_start_cmd_fixed_param)); + + cmd->vdev_id = plm->sessionId; + + cmd->meas_token = plm->meas_token; + cmd->dialog_token = plm->diag_token; + cmd->number_bursts = plm->numBursts; + cmd->burst_interval = WMA_SEC_TO_MSEC(plm->burstInt); + cmd->off_duration = plm->measDuration; + cmd->burst_cycle = plm->burstLen; + cmd->tx_power = plm->desiredTxPwr; + WMI_CHAR_ARRAY_TO_MAC_ADDR(plm->macAddr, &cmd->dest_mac); + cmd->num_chans = plm->plmNumCh; + + buf_ptr += sizeof(wmi_vdev_plmreq_start_cmd_fixed_param); + + WMA_LOGD("vdev : %d measu token : %d", cmd->vdev_id, cmd->meas_token); + WMA_LOGD("dialog_token: %d", cmd->dialog_token); + WMA_LOGD("number_bursts: %d", cmd->number_bursts); + WMA_LOGD("burst_interval: %d", cmd->burst_interval); + WMA_LOGD("off_duration: %d", cmd->off_duration); + WMA_LOGD("burst_cycle: %d", cmd->burst_cycle); + WMA_LOGD("tx_power: %d", cmd->tx_power); + WMA_LOGD("Number of channels : %d", cmd->num_chans); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (cmd->num_chans * sizeof(u_int32_t))); + + buf_ptr += WMI_TLV_HDR_SIZE; + if (cmd->num_chans) + { + channel_list = (u_int32_t *) buf_ptr; + for (count = 0; count < cmd->num_chans; count++) { + channel_list[count] = plm->plmChList[count]; + if (channel_list[count] < WMA_NLO_FREQ_THRESH) + channel_list[count] = + vos_chan_to_freq(channel_list[count]); + WMA_LOGD("Ch[%d]: %d MHz", count, channel_list[count]); + } + buf_ptr += cmd->num_chans * sizeof(u_int32_t); + } + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_PLMREQ_START_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send plm start wmi cmd", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + wma->interfaces[plm->sessionId].plm_in_progress = TRUE; + + WMA_LOGD("Plm start request sent successfully for vdev %d", + plm->sessionId); + + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_plm_stop(tp_wma_handle wma, const tpSirPlmReq plm) +{ + wmi_vdev_plmreq_stop_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int ret; + + if (NULL == plm || NULL == wma) { + WMA_LOGE("%s: input pointer is NULL ", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (FALSE == wma->interfaces[plm->sessionId].plm_in_progress) { + WMA_LOGE("No active plm req found, skip plm stop req" ); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("PLM Stop"); + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_vdev_plmreq_stop_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (u_int8_t *) cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_plmreq_stop_cmd_fixed_param)); + + cmd->vdev_id = plm->sessionId; + + cmd->meas_token = plm->meas_token; + WMA_LOGD("vdev %d meas token %d", cmd->vdev_id, cmd->meas_token); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_PLMREQ_STOP_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send plm stop wmi cmd", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + wma->interfaces[plm->sessionId].plm_in_progress = FALSE; + + WMA_LOGD("Plm stop request sent successfully for vdev %d", + plm->sessionId); + + return VOS_STATUS_SUCCESS; +} +static void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm) +{ + VOS_STATUS ret = 0; + + if (NULL == plm || NULL == wma) + return; + + if (plm->enable) + ret = wma_plm_start(wma, plm); + else + ret = wma_plm_stop(wma, plm); + + if (ret) + WMA_LOGE("%s: PLM %s failed %d", __func__, + plm->enable ? "start" : "stop", ret); + + /* SME expects WMA to free tpSirPlmReq memory after + * processing PLM request. */ + vos_mem_free(plm); + plm = NULL; +} +#endif + +/* + * After pushing cached scan results (that are stored in LIM) to SME, + * PE will post WDA_SME_SCAN_CACHE_UPDATED message indication to + * wma and intern this function handles that message. This function will + * check for PNO completion (by checking NLO match event) and post PNO + * completion back to SME if PNO operation is completed successfully. + */ +void wma_scan_cache_updated_ind(tp_wma_handle wma, u_int8_t sessionId) +{ + tSirPrefNetworkFoundInd *nw_found_ind; + VOS_STATUS status; + vos_msg_t vos_msg; + u_int8_t len, i; + + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].nlo_match_evt_received) + break; + } + + if (i == wma->max_bssid) { + WMA_LOGD("PNO match event is not received in any vdev, skip scan cache update indication"); + return; + } + wma->interfaces[i].nlo_match_evt_received = FALSE; + + WMA_LOGD("Posting PNO completion to umac"); + + len = sizeof(tSirPrefNetworkFoundInd); + nw_found_ind = (tSirPrefNetworkFoundInd *) vos_mem_malloc(len); + + if (NULL == nw_found_ind) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + + nw_found_ind->mesgType = eWNI_SME_PREF_NETWORK_FOUND_IND; + nw_found_ind->mesgLen = len; + nw_found_ind->sessionId = sessionId; + + vos_msg.type = eWNI_SME_PREF_NETWORK_FOUND_IND; + vos_msg.bodyptr = (void *) nw_found_ind; + vos_msg.bodyval = 0; + + status = vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post PNO completion match event to SME", + __func__); + vos_mem_free(nw_found_ind); + } +} + +#endif + +static void wma_send_status_to_suspend_ind(tp_wma_handle wma, boolean suspended, + bool runtime_pm) +{ + tSirReadyToSuspendInd *ready_to_suspend; + VOS_STATUS status; + vos_msg_t vos_msg; + u_int8_t len; + + if (runtime_pm) { + WMA_LOGD("Runtime PM: Posting ready to suspend indication"); + vos_event_set(&wma->runtime_suspend); + return; + } + + WMA_LOGD("Posting ready to suspend indication to umac"); + + len = sizeof(tSirReadyToSuspendInd); + ready_to_suspend = (tSirReadyToSuspendInd *) vos_mem_malloc(len); + + if (NULL == ready_to_suspend) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + + ready_to_suspend->mesgType = eWNI_SME_READY_TO_SUSPEND_IND; + ready_to_suspend->mesgLen = len; + ready_to_suspend->suspended = suspended; + + vos_msg.type = eWNI_SME_READY_TO_SUSPEND_IND; + vos_msg.bodyptr = (void *) ready_to_suspend; + vos_msg.bodyval = 0; + + status = vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to post ready to suspend"); + vos_mem_free(ready_to_suspend); + } +} + +/* Frees memory associated to given pattern ID in wow pattern cache. */ +static inline void wma_free_wow_ptrn(tp_wma_handle wma, u_int8_t ptrn_id) +{ + if (wma->wow.no_of_ptrn_cached <= 0 || + !wma->wow.cache[ptrn_id]) + return; + + WMA_LOGD("Deleting wow pattern %d from cache which belongs to vdev id %d", + ptrn_id, wma->wow.cache[ptrn_id]->vdev_id); + + vos_mem_free(wma->wow.cache[ptrn_id]->ptrn); + vos_mem_free(wma->wow.cache[ptrn_id]->mask); + vos_mem_free(wma->wow.cache[ptrn_id]); + wma->wow.cache[ptrn_id] = NULL; + + wma->wow.no_of_ptrn_cached--; +} + +/* Converts wow wakeup reason code to text format */ +static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason, tp_wma_handle wma) +{ + switch (wake_reason) { + case WOW_REASON_UNSPECIFIED: + if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle)) + return "UNSPECIFIED"; + else + return "RUNTIME PM resume"; + case WOW_REASON_NLOD: + return "NLOD"; + case WOW_REASON_AP_ASSOC_LOST: + return "AP_ASSOC_LOST"; + case WOW_REASON_LOW_RSSI: + return "LOW_RSSI"; + case WOW_REASON_DEAUTH_RECVD: + return "DEAUTH_RECVD"; + case WOW_REASON_DISASSOC_RECVD: + return "DISASSOC_RECVD"; + case WOW_REASON_GTK_HS_ERR: + return "GTK_HS_ERR"; + case WOW_REASON_EAP_REQ: + return "EAP_REQ"; + case WOW_REASON_FOURWAY_HS_RECV: + return "FOURWAY_HS_RECV"; + case WOW_REASON_TIMER_INTR_RECV: + return "TIMER_INTR_RECV"; + case WOW_REASON_PATTERN_MATCH_FOUND: + return "PATTERN_MATCH_FOUND"; + case WOW_REASON_RECV_MAGIC_PATTERN: + return "RECV_MAGIC_PATTERN"; + case WOW_REASON_P2P_DISC: + return "P2P_DISC"; +#ifdef FEATURE_WLAN_LPHB + case WOW_REASON_WLAN_HB: + return "WLAN_HB"; +#endif /* FEATURE_WLAN_LPHB */ + + case WOW_REASON_CSA_EVENT: + return "CSA_EVENT"; + case WOW_REASON_PROBE_REQ_WPS_IE_RECV: + return "PROBE_REQ_RECV"; + case WOW_REASON_AUTH_REQ_RECV: + return "AUTH_REQ_RECV"; + case WOW_REASON_ASSOC_REQ_RECV: + return "ASSOC_REQ_RECV"; + case WOW_REASON_HTT_EVENT: + return "WOW_REASON_HTT_EVENT"; +#ifdef FEATURE_WLAN_RA_FILTERING + case WOW_REASON_RA_MATCH: + return "WOW_REASON_RA_MATCH"; +#endif + case WOW_REASON_BEACON_RECV: + return "WOW_REASON_IBSS_BEACON_RECV"; +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + case WOW_REASON_HOST_AUTO_SHUTDOWN: + return "WOW_REASON_HOST_AUTO_SHUTDOWN"; +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WOW_REASON_ROAM_HO: + return "WOW_REASON_ROAM_HO"; +#endif + case WOW_REASON_CLIENT_KICKOUT_EVENT: + return "WOW_REASON_CLIENT_KICKOUT_EVENT"; + +#ifdef FEATURE_WLAN_EXTSCAN + case WOW_REASON_EXTSCAN: + return "WOW_REASON_EXTSCAN"; +#endif + case WOW_REASON_RSSI_BREACH_EVENT: + return "WOW_REASON_RSSI_BREACH_EVENT"; + + case WOW_REASON_NLO_SCAN_COMPLETE: + return "WOW_REASON_NLO_SCAN_COMPLETE"; + } + return "unknown"; +} + +static void wma_beacon_miss_handler(tp_wma_handle wma, u_int32_t vdev_id, + uint32_t rssi) +{ + tSirSmeMissedBeaconInd *beacon_miss_ind; + + beacon_miss_ind = (tSirSmeMissedBeaconInd *) vos_mem_malloc + (sizeof(tSirSmeMissedBeaconInd)); + + if (NULL == beacon_miss_ind) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + beacon_miss_ind->messageType = WDA_MISSED_BEACON_IND; + beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd); + beacon_miss_ind->bssIdx = vdev_id; + + wma_send_msg(wma, WDA_MISSED_BEACON_IND, + (void *)beacon_miss_ind, 0); + + wma_lost_link_info_handler(wma, vdev_id, rssi + + WMA_TGT_NOISE_FLOOR_DBM); +} + +#ifdef FEATURE_WLAN_LPHB +static int wma_lphb_handler(tp_wma_handle wma, u_int8_t *event) +{ + wmi_hb_ind_event_fixed_param *hb_fp; + tSirLPHBInd *slphb_indication; + VOS_STATUS vos_status; + vos_msg_t sme_msg = {0} ; + + hb_fp = (wmi_hb_ind_event_fixed_param *)event; + if (!hb_fp) { + WMA_LOGE("Invalid wmi_hb_ind_event_fixed_param buffer"); + return -EINVAL; + } + + WMA_LOGD("lphb indication received with vdev_id=%d, session=%d, reason=%d", + hb_fp->vdev_id, hb_fp->session, hb_fp->reason); + + slphb_indication = (tSirLPHBInd *) vos_mem_malloc(sizeof(tSirLPHBInd)); + + if (!slphb_indication) { + WMA_LOGE("Invalid LPHB indication buffer"); + return -EINVAL; + } + + slphb_indication->sessionIdx = hb_fp->session; + slphb_indication->protocolType = hb_fp->reason; + slphb_indication->eventReason= hb_fp->reason; + + sme_msg.type = eWNI_SME_LPHB_IND; + sme_msg.bodyptr = slphb_indication; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if ( !VOS_IS_STATUS_SUCCESS(vos_status) ) + { + WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME"); + vos_mem_free(slphb_indication); + return -EINVAL; + } + + return 0; +} +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_D0WOW +/* + * Handler to catch D0-WOW disable ACK event. + */ +static int wma_d0_wow_disable_ack_event(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *param_buf; + wmi_d0_wow_disable_ack_event_fixed_param *resp_data; + + param_buf = (WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *)event; + if (!param_buf) { + WMA_LOGE("Invalid D0-WOW disable ACK event buffer!"); + return -EINVAL; + } + + resp_data = param_buf->fixed_param; + vos_event_set(&wma->wma_resume_event); + WMA_LOGD("Received D0-WOW disable ACK"); + return 0; +} +#endif + +/* function : wma_get_temperature + * Descriptin : Function is used to send get pdev temperature req + * Args : wma_handle, request data which will be non-null + * Returns : SUCCESS or FAILURE + */ +VOS_STATUS wma_get_temperature(tp_wma_handle wma_handle) +{ + wmi_pdev_get_temperature_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len = sizeof(wmi_pdev_get_temperature_cmd_fixed_param); + u_int8_t *buf_ptr; + + if (!wma_handle) { + WMA_LOGE(FL("WMA is closed, can not issue cmd")); + return VOS_STATUS_E_INVAL; + } + + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t*)wmi_buf_data(wmi_buf); + + cmd = (wmi_pdev_get_temperature_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_get_temperature_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_pdev_get_temperature_cmd_fixed_param)); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_PDEV_GET_TEMPERATURE_CMDID)) { + WMA_LOGE(FL("failed to send get temperature command")); + wmi_buf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/* function : wma_pdev_temperature_evt_handler + * Description : Handler for WMI_PDEV_TEMPERATURE_EVENTID event from firmware + * : This event reports the chip temperature + * Returns : + */ +static int wma_pdev_temperature_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + vos_msg_t sme_msg = {0}; + WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *param_buf; + wmi_pdev_temperature_event_fixed_param *wmi_event; + + param_buf = (WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *) event; + if (!param_buf) + { + WMA_LOGE("Invalid pdev_temperature event buffer"); + return -EINVAL; + } + + wmi_event = param_buf->fixed_param; + WMA_LOGI(FL("temperature: %d"), wmi_event->value); + + sme_msg.type = eWNI_SME_MSG_GET_TEMPERATURE_IND; + sme_msg.bodyptr = NULL; + sme_msg.bodyval = wmi_event->value; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status) ) + { + WMA_LOGE(FL("Fail to post get temperature ind msg")); + } + + return 0; +} + +/** + * wma_log_supported_evt_handler() - Enable/Disable FW diag/log events + * @handle: WMA handle + * @event: Event received from FW + * @len: Length of the event + * + * Enables the low frequency events and disables the high frequency + * events. Bit 17 indicates if the event if low/high frequency. + * 1 - high frequency, 0 - low frequency + * + * Return: 0 on successfully enabling/disabling the events + */ +static int wma_log_supported_evt_handler(void *handle, + u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + uint32_t num_of_diag_events_logs; + wmi_diag_event_log_config_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t *cmd_args, *evt_args; + uint32_t buf_len, i; + + WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID_param_tlvs *param_buf; + wmi_diag_event_log_supported_event_fixed_params *wmi_event; + + WMA_LOGI("Received WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID"); + + param_buf = (WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("Invalid log supported event buffer"); + return -EINVAL; + } + wmi_event = param_buf->fixed_param; + num_of_diag_events_logs = wmi_event->num_of_diag_events_logs; + evt_args = param_buf->diag_events_logs_list; + if (!evt_args) { + WMA_LOGE("%s: Event list is empty, num_of_diag_events_logs=%d", + __func__, num_of_diag_events_logs); + return -EINVAL; + } + + WMA_LOGD("%s: num_of_diag_events_logs=%d", + __func__, num_of_diag_events_logs); + + /* Free any previous allocation */ + if (wma->events_logs_list) + vos_mem_free(wma->events_logs_list); + + /* Store the event list for run time enable/disable */ + wma->events_logs_list = vos_mem_malloc(num_of_diag_events_logs * + sizeof(uint32_t)); + if (!wma->events_logs_list) { + WMA_LOGE("%s: event log list memory allocation failed", + __func__); + return -ENOMEM; + } + wma->num_of_diag_events_logs = num_of_diag_events_logs; + + /* Prepare the send buffer */ + buf_len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + + (num_of_diag_events_logs * sizeof(uint32_t)); + + buf = wmi_buf_alloc(wma->wmi_handle, buf_len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + vos_mem_free(wma->events_logs_list); + wma->events_logs_list = NULL; + return -ENOMEM; + } + + cmd = (wmi_diag_event_log_config_fixed_param *) wmi_buf_data(buf); + buf_ptr = (uint8_t *) cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_diag_event_log_config_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_diag_event_log_config_fixed_param)); + + cmd->num_of_diag_events_logs = num_of_diag_events_logs; + + buf_ptr += sizeof(wmi_diag_event_log_config_fixed_param); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (num_of_diag_events_logs * sizeof(uint32_t))); + + cmd_args = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE); + + /* Populate the events */ + for (i = 0; i < num_of_diag_events_logs; i++) { + /* Low freq (0) - Enable (1) the event + * High freq (1) - Disable (0) the event + */ + WMI_DIAG_ID_ENABLED_DISABLED_SET(cmd_args[i], + !(WMI_DIAG_FREQUENCY_GET(evt_args[i]))); + /* Set the event ID */ + WMI_DIAG_ID_SET(cmd_args[i], + WMI_DIAG_ID_GET(evt_args[i])); + /* Set the type */ + WMI_DIAG_TYPE_SET(cmd_args[i], + WMI_DIAG_TYPE_GET(evt_args[i])); + /* Storing the event/log list in WMA */ + wma->events_logs_list[i] = evt_args[i]; + } + + if (wmi_unified_cmd_send(wma->wmi_handle, buf, buf_len, + WMI_DIAG_EVENT_LOG_CONFIG_CMDID)) { + WMA_LOGE("%s: WMI_DIAG_EVENT_LOG_CONFIG_CMDID failed", + __func__); + wmi_buf_free(buf); + /* Not clearing events_logs_list, though wmi cmd failed. + * Host can still have this list + */ + return -EINVAL; + } + + return 0; +} + +/** + * wma_flush_complete_evt_handler() - FW log flush complete event handler + * @handle: WMI handle + * @event: Event recevied from FW + * @len: Length of the event + * + */ +static int wma_flush_complete_evt_handler(void *handle, + u_int8_t *event, + u_int32_t len) +{ + VOS_STATUS status; + tp_wma_handle wma = (tp_wma_handle) handle; + + WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID_param_tlvs *param_buf; + wmi_debug_mesg_flush_complete_fixed_param *wmi_event; + uint32_t reason_code; + + param_buf = (WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("Invalid log flush complete event buffer"); + return VOS_STATUS_E_FAILURE; + } + + wmi_event = param_buf->fixed_param; + reason_code = wmi_event->reserved0; + + /* + * reason_code = 0; Flush event in response to flush command + * reason_code = other value; Asynchronous flush event for fatal events + */ + if (!reason_code && (vos_is_log_report_in_progress() == false)) { + WMA_LOGE("Received WMI flush event without sending CMD"); + return -EINVAL; + } else if (!reason_code && vos_is_log_report_in_progress() == true) { + /* Flush event in response to flush command */ + WMA_LOGI("Received WMI flush event in response to flush CMD"); + status = vos_timer_stop(&wma->log_completion_timer); + if (status != VOS_STATUS_SUCCESS) + WMA_LOGE("Failed to stop the log completion timeout"); + vos_logging_set_fw_flush_complete(); + } else if (reason_code && vos_is_log_report_in_progress() == false) { + /* Asynchronous flush event for fatal events */ + WMA_LOGE("Received asynchronous WMI flush event: reason=%d", + reason_code); + status = vos_set_log_completion(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_FIRMWARE, + reason_code); + if (VOS_STATUS_SUCCESS != status) { + WMA_LOGE("%s: Failed to set log trigger params", + __func__); + return VOS_STATUS_E_FAILURE; + } + vos_logging_set_fw_flush_complete(); + return status; + } else { + /* Asynchronous flush event for fatal event, + * but, report in progress already + */ + WMA_LOGI("%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", + __func__, WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_FIRMWARE, reason_code); + return VOS_STATUS_E_FAILURE; + } + return 0; +} + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id + * @tag: WMI TLV tag + * + * Return: + * 0 if TLV tag is invalid + * else return corresponding WMI event id + */ +static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag) +{ + uint32_t event_id; + + switch (tag) { + case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param: + event_id = WMI_EXTSCAN_START_STOP_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param: + event_id = WMI_EXTSCAN_OPERATION_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param: + event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param: + event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param: + event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param: + event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param: + event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param: + event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID; + break; + + default: + event_id = 0; + WMA_LOGE("%s: Unknown tag: %d", __func__, tag); + break; + } + + WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id); + return event_id; +} + +/** + * wma_extscan_wow_event_callback() - extscan wow event callback + * @handle: WMA handle + * @event: event buffer + * @len: length of @event buffer + * + * In wow case, the wow event is followed by the payload of the event + * which generated the wow event. + * payload is 4 bytes of length followed by event buffer. the first 4 bytes + * of event buffer is common tlv header, which is a combination + * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to + * identify the event which triggered wow event. + * + * @Return: none + */ +static void wma_extscan_wow_event_callback(void *handle, void *event, + uint32_t len) +{ + uint32_t id; + int tlv_ok_status = 0; + void *wmi_cmd_struct_ptr = NULL; + uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event)); + + id = wma_extscan_get_eventid_from_tlvtag(tag); + if (!id) { + WMA_LOGE("%s: Invalid Tag: %d", __func__, tag); + return; + } + + tlv_ok_status = wmitlv_check_and_pad_event_tlvs( + handle, event, len, id, + &wmi_cmd_struct_ptr); + if (tlv_ok_status != 0) { + WMA_LOGE("%s: Invalid Tag: %d could not check and pad tlvs", + __func__, tag); + return; + } + + switch (tag) { + case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param: + wma_extscan_start_stop_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param: + wma_extscan_operations_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param: + wma_extscan_table_usage_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param: + wma_extscan_cached_results_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param: + wma_extscan_change_results_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param: + wma_extscan_hotlist_match_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param: + wma_extscan_capabilities_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param: + wma_extscan_hotlist_ssid_match_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + default: + WMA_LOGE("%s: Unknown tag: %d", __func__, tag); + break; + } + wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr); + + return; +} +#endif + +/** + * wma_wow_wake_up_stats_display() - display wow wake up stats + * @wma: Pointer to wma handle + * + * Return: none + */ +static void wma_wow_wake_up_stats_display(tp_wma_handle wma) +{ + WMA_LOGA("uc %d bc %d v4_mc %d v6_mc %d ra %d ns %d na %d pno_match %d pno_complete %d gscan %d low_rssi %d rssi_breach %d", + wma->wow_ucast_wake_up_count, + wma->wow_bcast_wake_up_count, + wma->wow_ipv4_mcast_wake_up_count, + wma->wow_ipv6_mcast_wake_up_count, + wma->wow_ipv6_mcast_ra_stats, + wma->wow_ipv6_mcast_ns_stats, + wma->wow_ipv6_mcast_na_stats, + wma->wow_pno_match_wake_up_count, + wma->wow_pno_complete_wake_up_count, + wma->wow_gscan_wake_up_count, + wma->wow_low_rssi_wake_up_count, + wma->wow_rssi_breach_wake_up_count); + + return; +} + +/** + * wma_wow_ipv6_mcast_stats() - ipv6 mcast wake up stats + * @wma: Pointer to wma handle + * @data: Pointer to pattern match data + * + * Return: none + */ +static void wma_wow_ipv6_mcast_stats(tp_wma_handle wma, uint8_t *data) +{ + static const uint8_t ipv6_mcast[] = {0x86, 0xDD}; + + if (!memcmp(ipv6_mcast, (data + WMA_ETHER_TYPE_OFFSET), + sizeof(ipv6_mcast))) { + if (WMA_ICMP_V6_HEADER_TYPE == + *(data + WMA_ICMP_V6_HEADER_OFFSET)) { + if (WMA_ICMP_V6_RA_TYPE == + *(data + WMA_ICMP_V6_TYPE_OFFSET)) + wma->wow_ipv6_mcast_ra_stats++; + else if (WMA_ICMP_V6_NS_TYPE == + *(data + WMA_ICMP_V6_TYPE_OFFSET)) + wma->wow_ipv6_mcast_ns_stats++; + else if (WMA_ICMP_V6_NA_TYPE == + *(data + WMA_ICMP_V6_TYPE_OFFSET)) + wma->wow_ipv6_mcast_na_stats++; + else + WMA_LOGA("ICMP V6 type : 0x%x", + *(data + WMA_ICMP_V6_TYPE_OFFSET)); + } else { + WMA_LOGA("ICMP_V6 header 0x%x", + *(data + WMA_ICMP_V6_HEADER_OFFSET)); + } + } else { + WMA_LOGA("Ethertype x%x:0x%x", + *(data + WMA_ETHER_TYPE_OFFSET), + *(data + WMA_ETHER_TYPE_OFFSET + 1)); + } + + return; +} + +/** + * wma_wow_wake_up_stats() - maintain wow pattern match wake up stats + * @wma: Pointer to wma handle + * @data: Pointer to pattern match data + * @len: Pattern match data length + * @event: Wake up event + * + * Return: none + */ +static void wma_wow_wake_up_stats(tp_wma_handle wma, uint8_t *data, + int32_t len, WOW_WAKE_REASON_TYPE event) +{ + /* Do not increment debug stats if resume is for runtime pm */ + if (wmi_get_runtime_pm_inprogress(wma->wmi_handle)) + return; + + switch(event) { + + case WOW_REASON_PATTERN_MATCH_FOUND: + if (WMA_BCAST_MAC_ADDR == *data) { + wma->wow_bcast_wake_up_count++; + } else if (WMA_MCAST_IPV4_MAC_ADDR == *data) { + wma->wow_ipv4_mcast_wake_up_count++; + } else if (WMA_MCAST_IPV6_MAC_ADDR == *data) { + wma->wow_ipv6_mcast_wake_up_count++; + if (len > WMA_ICMP_V6_TYPE_OFFSET) + wma_wow_ipv6_mcast_stats(wma, data); + else + WMA_LOGA("ICMP_V6 data len %d", len); + } else { + wma->wow_ucast_wake_up_count++; + } + break; + + case WOW_REASON_RA_MATCH: + wma->wow_ipv6_mcast_ra_stats++; + break; + + case WOW_REASON_NLOD: + wma->wow_pno_match_wake_up_count++; + break; + + case WOW_REASON_NLO_SCAN_COMPLETE: + wma->wow_pno_complete_wake_up_count++; + break; + + case WOW_REASON_LOW_RSSI: + wma->wow_low_rssi_wake_up_count++; + break; + + case WOW_REASON_EXTSCAN: + wma->wow_gscan_wake_up_count++; + break; + + case WOW_REASON_RSSI_BREACH_EVENT: + wma->wow_rssi_breach_wake_up_count++; + break; + + default: + WMA_LOGE("Unknown wake up reason"); + break; + } + + wma_wow_wake_up_stats_display(wma); + return; +} + + +/** + * wma_wow_ap_lost_helper() - helper function to handle WOW_REASON_AP_ASSOC_LOST + * reason code and retrieve RSSI from the event. + * @wma: Pointer to wma handle + * @param: WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs buffer pointer + * + * Return: none + */ +static void wma_wow_ap_lost_helper(tp_wma_handle wma, void *param) +{ + WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf; + WOW_EVENT_INFO_fixed_param *wake_info; + WMI_ROAM_EVENTID_param_tlvs event_param; + wmi_roam_event_fixed_param *roam_event; + u_int32_t wow_buf_pkt_len = 0; + + param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) param; + wake_info = param_buf->fixed_param; + WMA_LOGA("%s: Beacon miss indication on vdev %d", + __func__, wake_info->vdev_id); + + if (NULL == param_buf->wow_packet_buffer) { + WMA_LOGE("%s: invalid wow packet buffer", __func__); + goto exit_handler; + } + + vos_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + WMA_LOGD("wow_packet_buffer dump"); + vos_trace_hex_dump(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer, wow_buf_pkt_len); + if (wow_buf_pkt_len >= sizeof(event_param)) { + roam_event = (wmi_roam_event_fixed_param *) + (param_buf->wow_packet_buffer + 4); + wma_beacon_miss_handler(wma, wake_info->vdev_id, + roam_event->rssi); + return; + } + +exit_handler: + /* in the case that no RSSI is available from the event */ + WMA_LOGE("%s: rssi is not available from wow_packet_buffer", __func__); + wma_beacon_miss_handler(wma, wake_info->vdev_id, 0); +} + +/* + * Handler to catch wow wakeup host event. This event will have + * reason why the firmware has woken the host. + */ +static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf; + WOW_EVENT_INFO_fixed_param *wake_info; +#ifdef FEATURE_WLAN_SCAN_PNO + struct wma_txrx_node *node; +#endif + u_int32_t wake_lock_duration = 0; + u_int32_t wow_buf_pkt_len = 0; + + param_buf = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("Invalid wow wakeup host event buf"); + return -EINVAL; + } + + wake_info = param_buf->fixed_param; + + WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d", + wma_wow_wake_reason_str(wake_info->wake_reason, wma), + wake_info->wake_reason, + wake_info->vdev_id); + + vos_event_set(&wma->wma_resume_event); + + switch (wake_info->wake_reason) { + case WOW_REASON_AUTH_REQ_RECV: + wake_lock_duration = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT; + break; + + case WOW_REASON_ASSOC_REQ_RECV: + wake_lock_duration = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION; + break; + + case WOW_REASON_DEAUTH_RECVD: + wake_lock_duration = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION; + break; + + case WOW_REASON_DISASSOC_RECVD: + wake_lock_duration = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION; + break; + + case WOW_REASON_AP_ASSOC_LOST: + wake_lock_duration = WMA_BMISS_EVENT_WAKE_LOCK_DURATION; + wma_wow_ap_lost_helper(wma, param_buf); + break; +#ifdef FEATURE_WLAN_RA_FILTERING + case WOW_REASON_RA_MATCH: + wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_RA_MATCH); + break; +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + case WOW_REASON_HOST_AUTO_SHUTDOWN: + wake_lock_duration = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION; + WMA_LOGA("Received WOW Auto Shutdown trigger in suspend"); + if (wma_post_auto_shutdown_msg()) + return -EINVAL; + break; +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + case WOW_REASON_NLOD: + wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD); + node = &wma->interfaces[wake_info->vdev_id]; + if (node) { + WMA_LOGD("NLO match happened"); + node->nlo_match_evt_received = TRUE; + + vos_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_PNO); + } + break; + + case WOW_REASON_NLO_SCAN_COMPLETE: + { + WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param; + + wma_wow_wake_up_stats(wma, NULL, 0, + WOW_REASON_NLO_SCAN_COMPLETE); + WMA_LOGD("Host woken up due to pno scan complete reason"); + /* First 4-bytes of wow_packet_buffer is the length */ + if (param_buf->wow_packet_buffer) { + param.fixed_param = (wmi_nlo_event *) + (param_buf->wow_packet_buffer + 4); + wma_nlo_scan_cmp_evt_handler(handle, + (u_int8_t *)¶m, + sizeof(param)); + } else + WMA_LOGD("No wow_packet_buffer present"); + } + break; +#endif + + case WOW_REASON_CSA_EVENT: + { + WMI_CSA_HANDLING_EVENTID_param_tlvs param; + WMA_LOGD("Host woken up because of CSA IE"); + param.fixed_param = (wmi_csa_event_fixed_param *) + (((u_int8_t *) wake_info) + + sizeof(WOW_EVENT_INFO_fixed_param) + + WOW_CSA_EVENT_OFFSET); + wma_csa_offload_handler(handle, (u_int8_t *)¶m, + sizeof(param)); + } + break; + +#ifdef FEATURE_WLAN_LPHB + case WOW_REASON_WLAN_HB: + wma_lphb_handler(wma, (u_int8_t *)param_buf->hb_indevt); + break; +#endif + + case WOW_REASON_HTT_EVENT: + break; + case WOW_REASON_PATTERN_MATCH_FOUND: + WMA_LOGD("Wake up for Rx packet, dump starting from ethernet hdr"); + if (param_buf->wow_packet_buffer) { + /* First 4-bytes of wow_packet_buffer is the length */ + vos_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + wma_wow_wake_up_stats(wma, + param_buf->wow_packet_buffer + 4, wow_buf_pkt_len, + WOW_REASON_PATTERN_MATCH_FOUND); + vos_trace_hex_dump(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer + 4, + wow_buf_pkt_len); + } else { + WMA_LOGE("No wow packet buffer present"); + } + break; + + case WOW_REASON_LOW_RSSI: + { + /* WOW_REASON_LOW_RSSI is used for all roaming events. + * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS, + * WMI_ROAM_REASON_SUITABLE_AP will be handled by + * wma_roam_event_callback(). + */ + WMI_ROAM_EVENTID_param_tlvs param; + wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_LOW_RSSI); + if (param_buf->wow_packet_buffer) { + /* Roam event is embedded in wow_packet_buffer */ + WMA_LOGD("Host woken up because of roam event"); + vos_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + WMA_LOGD("wow_packet_buffer dump"); + vos_trace_hex_dump(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer, wow_buf_pkt_len); + if (wow_buf_pkt_len >= sizeof(param)) { + param.fixed_param = (wmi_roam_event_fixed_param *) + (param_buf->wow_packet_buffer +4); + wma_roam_event_callback(handle, (u_int8_t *)¶m, + sizeof(param)); + } else { + WMA_LOGE("Wrong length for roam event = %d bytes", + wow_buf_pkt_len); + } + } else { + /* No wow_packet_buffer means a better AP beacon + * will follow in a later event. + */ + WMA_LOGD("Host woken up because of better AP beacon"); + } + break; + } + case WOW_REASON_CLIENT_KICKOUT_EVENT: + { + WMI_PEER_STA_KICKOUT_EVENTID_param_tlvs param; + if (param_buf->wow_packet_buffer) { + /* station kickout event embedded in wow_packet_buffer */ + WMA_LOGD("Host woken up because of sta_kickout event"); + vos_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + WMA_LOGD("wow_packet_buffer dump"); + vos_trace_hex_dump(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer, wow_buf_pkt_len); + if (wow_buf_pkt_len >= sizeof(param)) { + param.fixed_param = (wmi_peer_sta_kickout_event_fixed_param *) + (param_buf->wow_packet_buffer + 4); + wma_peer_sta_kickout_event_handler(handle, + (u_int8_t *)¶m, sizeof(param)); + } else { + WMA_LOGE("Wrong length for sta_kickout event = %d bytes", + wow_buf_pkt_len); + } + } else { + WMA_LOGD("No wow_packet_buffer present"); + } + break; + } +#ifdef FEATURE_WLAN_EXTSCAN + case WOW_REASON_EXTSCAN: + WMA_LOGD("Host woken up because of extscan reason"); + wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_EXTSCAN); + if (param_buf->wow_packet_buffer) { + wow_buf_pkt_len = + *(uint32_t *)param_buf->wow_packet_buffer; + WMA_LOGD("wow_packet_buffer dump"); + vos_trace_hex_dump(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer, + wow_buf_pkt_len); + wma_extscan_wow_event_callback(handle, + (u_int8_t *)(param_buf->wow_packet_buffer + 4), + wow_buf_pkt_len); + } else + WMA_LOGE("wow_packet_buffer is empty"); + break; +#endif + case WOW_REASON_RSSI_BREACH_EVENT: + { + WMI_RSSI_BREACH_EVENTID_param_tlvs param; + + wma_wow_wake_up_stats(wma, NULL, 0, + WOW_REASON_RSSI_BREACH_EVENT); + WMA_LOGD("Host woken up because of rssi breach reason"); + /* rssi breach event is embedded in wow_packet_buffer */ + if (param_buf->wow_packet_buffer) { + vos_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + if (wow_buf_pkt_len >= sizeof(param)) { + param.fixed_param = + (wmi_rssi_breach_event_fixed_param *) + (param_buf->wow_packet_buffer + 4); + wma_rssi_breached_event_handler(handle, + (u_int8_t *)¶m, + sizeof(param)); + } else { + WMA_LOGE("%s: Wrong length: %d bytes", + __func__, wow_buf_pkt_len); + } + } else + WMA_LOGD("No wow_packet_buffer present"); + } + break; + + default: + break; + } + + if (wake_lock_duration) { + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, + wake_lock_duration, + WIFI_POWER_EVENT_WAKELOCK_WOW); + WMA_LOGA("Holding %d msec wake_lock", wake_lock_duration); + } + + return 0; +} + +static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val) { + + adf_os_atomic_set(&wma->is_wow_bus_suspended, val); +} + +static inline int wma_get_wow_bus_suspend(tp_wma_handle wma) { + + return adf_os_atomic_read(&wma->is_wow_bus_suspended); +} + +static const u8 *wma_wow_wakeup_event_str(WOW_WAKE_EVENT_TYPE event) +{ + switch (event) { + case WOW_BMISS_EVENT: + return "WOW_BMISS_EVENT"; + case WOW_BETTER_AP_EVENT: + return "WOW_BETTER_AP_EVENT"; + case WOW_DEAUTH_RECVD_EVENT: + return "WOW_DEAUTH_RECVD_EVENT"; + case WOW_MAGIC_PKT_RECVD_EVENT: + return "WOW_MAGIC_PKT_RECVD_EVENT"; + case WOW_GTK_ERR_EVENT: + return "WOW_GTK_ERR_EVENT"; + case WOW_FOURWAY_HSHAKE_EVENT: + return "WOW_GTK_ERR_EVENT"; + case WOW_EAPOL_RECVD_EVENT: + return "WOW_EAPOL_RECVD_EVENT"; + case WOW_NLO_DETECTED_EVENT: + return "WOW_NLO_DETECTED_EVENT"; + case WOW_DISASSOC_RECVD_EVENT: + return "WOW_DISASSOC_RECVD_EVENT"; + case WOW_PATTERN_MATCH_EVENT: + return "WOW_PATTERN_MATCH_EVENT"; + case WOW_CSA_IE_EVENT: + return "WOW_CSA_IE_EVENT"; + case WOW_PROBE_REQ_WPS_IE_EVENT: + return "WOW_PROBE_REQ_WPS_IE_EVENT"; + case WOW_AUTH_REQ_EVENT: + return "WOW_AUTH_REQ_EVENT"; + case WOW_ASSOC_REQ_EVENT: + return "WOW_ASSOC_REQ_EVENT"; + case WOW_HTT_EVENT: + return "WOW_HTT_EVENT"; + case WOW_RA_MATCH_EVENT: + return "WOW_RA_MATCH_EVENT"; + case WOW_HOST_AUTO_SHUTDOWN_EVENT: + return "WOW_HOST_AUTO_SHUTDOWN_EVENT"; + case WOW_IOAC_MAGIC_EVENT: + return "WOW_IOAC_MAGIC_EVENT"; + case WOW_IOAC_SHORT_EVENT: + return "WOW_IOAC_SHORT_EVENT"; + case WOW_IOAC_EXTEND_EVENT: + return "WOW_IOAC_EXTEND_EVENT"; + case WOW_IOAC_TIMER_EVENT: + return "WOW_IOAC_TIMER_EVENT"; + case WOW_DFS_PHYERR_RADAR_EVENT: + return "WOW_DFS_PHYERR_RADAR_EVENT"; + case WOW_BEACON_EVENT: + return "WOW_BEACON_EVENT"; + case WOW_CLIENT_KICKOUT_EVENT: + return "WOW_CLIENT_KICKOUT_EVENT"; + case WOW_NAN_EVENT: + return "WOW_NAN_EVENT"; + case WOW_EXTSCAN_EVENT: + return "WOW_EXTSCAN_EVENT"; + case WOW_IOAC_REV_KA_FAIL_EVENT: + return "WOW_IOAC_REV_KA_FAIL_EVENT"; + case WOW_IOAC_SOCK_EVENT: + return "WOW_IOAC_SOCK_EVENT"; + case WOW_NLO_SCAN_COMPLETE_EVENT: + return "WOW_NLO_SCAN_COMPLETE_EVENT"; + default: + return "UNSPECIFIED_EVENT"; + } +} + +/* Configures wow wakeup events. */ +static void wma_add_wow_wakeup_event(tp_wma_handle wma, + WOW_WAKE_EVENT_TYPE event, + v_BOOL_t enable) +{ + if (enable) { + wma->wow_wakeup_enable_mask |= 1 << event; + wma->wow_wakeup_disable_mask &= ~(1 << event); + } else { + wma->wow_wakeup_disable_mask |= 1 << event; + wma->wow_wakeup_enable_mask &= ~(1 << event); + } + + WMA_LOGD("%s %s event %s\n", __func__, + enable ? "enable" : "disable", + wma_wow_wakeup_event_str(event)); +} + +/** + * wma_send_wakeup_mask() - Enable/Disable the wakeup patterns + * @wma: WMA Handle + * @enable: boolean to enable/disable the pattern in FW + * + * The API configures the bitmap mask for WoW wakeup patterns. + * The Patterns are used to filter out packets in FW during APPS + * Power collapse + * + * Return: 0 on success; else failure + */ + +static VOS_STATUS wma_send_wakeup_mask(tp_wma_handle wma, bool enable) +{ + WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd; + u_int16_t len; + wmi_buf_t buf; + int ret; + + len = sizeof(WMI_WOW_ADD_DEL_EVT_CMD_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed to allocate buf for wow wakeup mask", + __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_WOW_ADD_DEL_EVT_CMD_fixed_param)); + cmd->vdev_id = 0; + cmd->is_add = enable; + + if (cmd->is_add) + cmd->event_bitmap = wma->wow_wakeup_enable_mask; + else + cmd->event_bitmap = wma->wow_wakeup_disable_mask; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID); + if (ret) { + WMA_LOGE("Failed to config wow wakeup event"); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("%s Wakeup pattern 0x%x %s in fw", __func__, + cmd->event_bitmap, enable ? "enabled":"disabled"); + + return VOS_STATUS_SUCCESS; +} + +/* Sends WOW patterns to FW. */ +static VOS_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma, + u_int8_t vdev_id, u_int8_t ptrn_id, + const u_int8_t *ptrn, const u_int8_t ptrn_len, + const u_int8_t ptrn_offset, const u_int8_t *mask, + u_int8_t mask_len) + +{ + WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd; + WOW_BITMAP_PATTERN_T *bitmap_pattern; + wmi_buf_t buf; + u_int8_t *buf_ptr; +#ifdef WMA_DUMP_WOW_PTRN + u_int8_t pos; + u_int8_t *tmp; +#endif + int32_t len; + int ret; + + len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) + + WMI_TLV_HDR_SIZE + + 1 * sizeof(WOW_BITMAP_PATTERN_T) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(A_UINT32) + + WMI_TLV_HDR_SIZE + + 1 * sizeof(A_UINT32); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *)wmi_buf_data(buf); + buf_ptr = (u_int8_t *)cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_WOW_ADD_PATTERN_CMD_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->pattern_id = ptrn_id; + cmd->pattern_type = WOW_BITMAP_PATTERN; + buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(WOW_BITMAP_PATTERN_T)); + buf_ptr += WMI_TLV_HDR_SIZE; + bitmap_pattern = (WOW_BITMAP_PATTERN_T *)buf_ptr; + + WMITLV_SET_HDR(&bitmap_pattern->tlv_header, + WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T, + WMITLV_GET_STRUCT_TLVLEN(WOW_BITMAP_PATTERN_T)); + + vos_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len); + vos_mem_copy(&bitmap_pattern->bitmaskbuf[0], mask, mask_len); + + bitmap_pattern->pattern_offset = ptrn_offset; + bitmap_pattern->pattern_len = ptrn_len; + + if(bitmap_pattern->pattern_len > WOW_DEFAULT_BITMAP_PATTERN_SIZE) + bitmap_pattern->pattern_len = WOW_DEFAULT_BITMAP_PATTERN_SIZE; + + if(bitmap_pattern->pattern_len > WOW_DEFAULT_BITMASK_SIZE) + bitmap_pattern->pattern_len = WOW_DEFAULT_BITMASK_SIZE; + + bitmap_pattern->bitmask_len = bitmap_pattern->pattern_len; + bitmap_pattern->pattern_id = ptrn_id; + + WMA_LOGD("vdev id : %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d", + cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len, + bitmap_pattern->pattern_offset); + +#ifdef WMA_DUMP_WOW_PTRN + printk("Pattern : "); + tmp = (u_int8_t *) &bitmap_pattern->patternbuf[0]; + for (pos = 0; pos < bitmap_pattern->pattern_len; pos++) + printk("%02X ", tmp[pos]); + + printk("\nMask : "); + tmp = (u_int8_t *) &bitmap_pattern->bitmaskbuf[0]; + for (pos = 0; pos < bitmap_pattern->pattern_len; pos++) + printk("%02X ", tmp[pos]); +#endif + + buf_ptr += sizeof(WOW_BITMAP_PATTERN_T); + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for pattern_info_timeout but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for ra_ratelimit_interval with dummy data as this fix elem*/ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1 * sizeof(A_UINT32)); + buf_ptr += WMI_TLV_HDR_SIZE; + *(A_UINT32 *)buf_ptr = 0; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_WOW_ADD_WAKE_PATTERN_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send wow ptrn to fw", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +/* Sends delete pattern request to FW for given pattern ID on particular vdev */ +static VOS_STATUS wma_del_wow_pattern_in_fw(tp_wma_handle wma, + u_int8_t ptrn_id) +{ + WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int ret; + + len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_WOW_DEL_PATTERN_CMD_fixed_param)); + cmd->vdev_id = 0; + cmd->pattern_id = ptrn_id; + cmd->pattern_type = WOW_BITMAP_PATTERN; + + WMA_LOGD("Deleting pattern id: %d in fw", cmd->pattern_id); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_WOW_DEL_WAKE_PATTERN_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to delete wow ptrn from fw", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +#ifdef FEATURE_WLAN_D0WOW +void wma_set_d0wow_flag(tp_wma_handle wma_handle, A_BOOL flag) +{ + atomic_set(&wma_handle->in_d0wow, flag); +} + +A_BOOL wma_read_d0wow_flag(tp_wma_handle wma_handle) +{ + return atomic_read(&wma_handle->in_d0wow); +} + +/* Enable D0-WOW in firmware. */ +VOS_STATUS wma_enable_d0wow_in_fw(tp_wma_handle wma) +{ + wmi_d0_wow_enable_disable_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int host_credits; + int wmi_pending_cmds; + int ret = 0; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed to allocate WMI buffer!", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_d0_wow_enable_disable_cmd_fixed_param)); + cmd->enable = 1; + + vos_event_reset(&wma->target_suspend); + wma->wow_nack = 0; + + host_credits = wmi_get_host_credits(wma->wmi_handle); + wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle); + if (host_credits < WMI_WOW_REQUIRED_CREDITS) { + WMA_LOGE("%s: Not enough credits to post " + "WMI_D0_WOW_ENABLE_DISABLE_CMDID, try anyway! " + "Credits: %d, pending_cmds: %d", __func__, + host_credits, wmi_pending_cmds); + } + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_D0_WOW_ENABLE_DISABLE_CMDID); + if (ret) { + WMA_LOGE("Failed to enable D0-WOW in FW!"); + goto error; + } + + vos_status = vos_wait_single_event(&wma->target_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT); + if (VOS_STATUS_SUCCESS != vos_status) { + WMA_LOGE("Failed to receive D0-WoW enable HTC ACK from FW! " + "Credits: %d, pending_cmds: %d", + wmi_get_host_credits(wma->wmi_handle), + wmi_get_pending_cmds(wma->wmi_handle)); + + if (vos_is_logp_in_progress(VOS_MODULE_ID_WDA, NULL)) { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } else { + VOS_BUG(0); + return VOS_STATUS_E_FAILURE; + } + } + + if (wma->wow_nack) { + WMA_LOGE("FW not ready for D0WOW."); + return VOS_STATUS_E_AGAIN; + } + + host_credits = wmi_get_host_credits(wma->wmi_handle); + wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle); + if (host_credits < WMI_WOW_REQUIRED_CREDITS) { + WMA_LOGE("%s: No credits after HTC ACK: %d, pending_cmds: %d, " + "cannot resume back!", __func__, host_credits, + wmi_pending_cmds); + HTC_dump_counter_info(wma->htc_handle); + } + + wma->wow.wow_enable_cmd_sent = TRUE; + wmi_set_d0wow_flag(wma->wmi_handle, TRUE); + wma_set_d0wow_flag(wma, TRUE); + WMA_LOGD("D0-WOW is enabled successfully in FW."); + return vos_status; + +error: + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; +} +#endif /* FEATURE_WLAN_D0WOW */ + +/* Enables WOW in firmware. */ +int wma_enable_wow_in_fw(WMA_HANDLE handle, int runtime_pm) +{ + tp_wma_handle wma = handle; + wmi_wow_enable_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int ret; + struct ol_softc *scn; + int host_credits; + int wmi_pending_cmds; +#ifdef CONFIG_CNSS + tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return VOS_STATUS_E_FAILURE; + } +#endif + +#ifdef FEATURE_WLAN_D0WOW + if (wma->ap_client_cnt > 0) { + WMA_LOGD("Entering D0-WOW since client count is %d.", + wma->ap_client_cnt); + return wma_enable_d0wow_in_fw(wma); +} +#endif + + len = sizeof(wmi_wow_enable_cmd_fixed_param); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_wow_enable_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_wow_enable_cmd_fixed_param)); + cmd->enable = TRUE; + + vos_event_reset(&wma->target_suspend); + vos_event_reset(&wma->wow_tx_complete); + wma->wow_nack = 0; + + host_credits = wmi_get_host_credits(wma->wmi_handle); + wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle); + + WMA_LOGD("Credits:%d; Pending_Cmds: %d", + host_credits, wmi_pending_cmds); + +#if !defined(HIF_SDIO) + if (!runtime_pm && host_credits < WMI_WOW_REQUIRED_CREDITS) { + WMA_LOGE("%s: Not enough credits but trying to send WoW enable" + " anyway! Credits:%d, pending_cmds:%d\n", __func__, + host_credits, wmi_pending_cmds); + } +#endif + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_WOW_ENABLE_CMDID); + if (ret) { + WMA_LOGE("Failed to enable wow in fw"); + goto error; + } + + wmi_set_target_suspend(wma->wmi_handle, TRUE); + + if (vos_wait_single_event(&wma->target_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) + != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to receive WoW Enable Ack from FW"); + WMA_LOGE("Credits:%d; Pending_Cmds: %d", + wmi_get_host_credits(wma->wmi_handle), + wmi_get_pending_cmds(wma->wmi_handle)); + if (!vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { +#ifdef CONFIG_CNSS + if (pMac->sme.enableSelfRecovery) { + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } +#else + VOS_BUG(0); +#endif + } else { + WMA_LOGE("%s: LOGP is in progress, ignore!", __func__); + } + + wmi_set_target_suspend(wma->wmi_handle, FALSE); + return VOS_STATUS_E_FAILURE; + } + + if (wma->wow_nack) { + WMA_LOGE("FW not ready to WOW"); + wmi_set_target_suspend(wma->wmi_handle, FALSE); + return VOS_STATUS_E_AGAIN; + } + + host_credits = wmi_get_host_credits(wma->wmi_handle); + wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle); + + if (host_credits < WMI_WOW_REQUIRED_CREDITS) { + WMA_LOGE("%s: No Credits after HTC ACK:%d, pending_cmds:%d, " + "cannot resume back", __func__, host_credits, wmi_pending_cmds); + HTC_dump_counter_info(wma->htc_handle); + if (!vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) + VOS_BUG(0); + else + WMA_LOGE("%s: SSR in progress, ignore no credit issue", __func__); + } + + + WMA_LOGD("WOW enabled successfully in fw: credits:%d" + "pending_cmds: %d", host_credits, wmi_pending_cmds); + + scn = vos_get_context(VOS_MODULE_ID_HIF, wma->vos_context); + + if (scn == NULL) { + WMA_LOGE("%s: Failed to get HIF context", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + HTCCancelDeferredTargetSleep(scn); + + wma->wow.wow_enable_cmd_sent = TRUE; + + return VOS_STATUS_SUCCESS; + +error: + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; +} + +/* Sends user configured WOW patterns to the firmware. */ +static VOS_STATUS wma_wow_usr(tp_wma_handle wma, u_int8_t vdev_id, + u_int8_t *enable_ptrn_match) +{ + struct wma_wow_ptrn_cache *cache; + VOS_STATUS ret = VOS_STATUS_SUCCESS; + u_int8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; + u_int8_t bit_to_check, ptrn_id, pos; + + WMA_LOGD("Configuring user wow patterns for vdev %d", vdev_id); + + for (ptrn_id = 0; ptrn_id < WOW_MAX_BITMAP_FILTERS; ptrn_id++) { + cache = wma->wow.cache[ptrn_id]; + if (!cache) + continue; + + if (cache->vdev_id != vdev_id) + continue; + /* + * Convert received pattern mask value from bit representaion + * to byte representation. + * + * For example, received value from umac, + * + * Mask value : A1 (equivalent binary is "1010 0001") + * Pattern value : 12:00:13:00:00:00:00:44 + * + * The value which goes to FW after the conversion from this + * function (1 in mask value will become FF and 0 will + * become 00), + * + * Mask value : FF:00:FF:00:0:00:00:FF + * Pattern value : 12:00:13:00:00:00:00:44 + */ + vos_mem_zero(new_mask, sizeof(new_mask)); + for (pos = 0; pos < cache->ptrn_len; pos++) { + bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) - + (pos % WMA_NUM_BITS_IN_BYTE); + bit_to_check = 0x1 << bit_to_check; + if (cache->mask[pos / WMA_NUM_BITS_IN_BYTE] & bit_to_check) + new_mask[pos] = WMA_WOW_PTRN_MASK_VALID; + } + + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, ptrn_id, + cache->ptrn, cache->ptrn_len, + cache->ptrn_offset, new_mask, + cache->ptrn_len); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to submit wow pattern to fw (ptrn_id %d)", + ptrn_id); + break; + } + } + + *enable_ptrn_match = 1 << vdev_id; + return ret; +} + +/* Configures default WOW pattern for the given vdev_id which is in AP mode. */ +static VOS_STATUS wma_wow_ap(tp_wma_handle wma, u_int8_t vdev_id, + u_int8_t *enable_ptrn_match) +{ + static const u_int8_t arp_ptrn[] = { 0x08, 0x06 }; + static const u_int8_t arp_mask[] = { 0xff, 0xff }; + static const u_int8_t arp_offset = 20; + VOS_STATUS ret; + + /* Setup all ARP pkt pattern. This is dummy pattern hence the lenght + is zero */ + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, + wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], + arp_ptrn, 0, arp_offset, + arp_mask, 0); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW ARP pattern"); + return ret; + } + + *enable_ptrn_match = 1 << vdev_id; + return ret; +} + +#ifdef FEATURE_WLAN_RA_FILTERING +static VOS_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, u_int8_t vdev_id) +{ + + WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int32_t len; + int ret; + + len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_BITMAP_PATTERN_T) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) + + WMI_TLV_HDR_SIZE + + 0 * sizeof(A_UINT32) + + WMI_TLV_HDR_SIZE + + 1 * sizeof(A_UINT32); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *)wmi_buf_data(buf); + buf_ptr = (u_int8_t *)cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_WOW_ADD_PATTERN_CMD_fixed_param)); + cmd->vdev_id = vdev_id; + cmd->pattern_id = 0; + cmd->pattern_type = WOW_IPV6_RA_PATTERN; + buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param); + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for pattern_info_timeout but no data. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Fill TLV for ra_ratelimit_interval. */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(A_UINT32)); + buf_ptr += WMI_TLV_HDR_SIZE; + + + *((A_UINT32 *)buf_ptr) = wma->RArateLimitInterval; + + WMA_LOGD("%s: send RA rate limit [%d] to fw vdev = %d", __func__, + wma->RArateLimitInterval, vdev_id); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_WOW_ADD_WAKE_PATTERN_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send RA rate limit to fw", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; + +} +#endif /* FEATURE_WLAN_RA_FILTERING */ + + +/* Configures default WOW pattern for the given vdev_id which is in STA mode. */ +static VOS_STATUS wma_wow_sta(tp_wma_handle wma, u_int8_t vdev_id, + u_int8_t *enable_ptrn_match, bool runtime_pm) +{ + static const u_int8_t discvr_ptrn[] = { 0xe0, 0x00, 0x00, 0xf8 }; + static const u_int8_t discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 }; + static const u_int8_t discvr_offset = 30; + u_int8_t mac_mask[ETH_ALEN], free_slot; + VOS_STATUS ret = VOS_STATUS_SUCCESS; + static const u_int8_t arp_ptrn[] = { 0x08, 0x06 }; + static const u_int8_t arp_mask[] = { 0xff, 0xff }; + static const u_int8_t arp_offset = 12; + static const u_int8_t ns_ptrn[] = {0x86, 0xDD}; + static const u_int8_t bcst_ptrn[] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + static const u_int8_t bcst_mask[] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + static const u_int8_t bcst_offset = 0; + + free_slot = wma->wow.total_free_ptrn_id - wma->wow.used_free_ptrn_id ; + + if (free_slot < WMA_STA_WOW_DEFAULT_PTRN_MAX) { + WMA_LOGD("Free slots are not enough, avail:%d, need: %d", + free_slot, WMA_STA_WOW_DEFAULT_PTRN_MAX); + WMA_LOGD("Ignoring default STA mode wow pattern for vdev : %d", + vdev_id); + return ret; + } + + WMA_LOGD("Configuring default STA mode wow pattern for vdev %d", + vdev_id); + + /* Setup unicast pkt pattern */ + vos_mem_set(&mac_mask, ETH_ALEN, 0xFF); + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, + wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], + wma->interfaces[vdev_id].addr, ETH_ALEN, 0, + mac_mask, ETH_ALEN); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW unicast pattern"); + return ret; + } + + /* + * Setup multicast pattern for mDNS 224.0.0.251, + * SSDP 239.255.255.250 and LLMNR 224.0.0.252 + */ + if (wma->ssdp) { + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, + wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], + discvr_ptrn, sizeof(discvr_ptrn), discvr_offset, + discvr_mask, sizeof(discvr_ptrn)); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW mDNS/SSDP/LLMNR pattern"); + return ret; + } + } + else + WMA_LOGD("mDNS, SSDP, LLMNR patterns are disabled from ini"); + + if (runtime_pm && wma->enable_bcst_ptrn) { + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, + wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], + bcst_ptrn, sizeof(bcst_ptrn), bcst_offset, + bcst_mask, sizeof(bcst_mask)); + if (ret != VOS_STATUS_SUCCESS) + WMA_LOGE("Failed to add BCAST wakeup pattern\n"); + } + + /* when arp offload or ns offloaded is disabled + * from ini file, configure broad cast arp pattern + * to fw, so that host can wake up + */ + if (runtime_pm || !(wma->ol_ini_info & 0x1)) { + /* Setup all ARP pkt pattern */ + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, + wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], + arp_ptrn, sizeof(arp_ptrn), arp_offset, + arp_mask, sizeof(arp_mask)); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW ARP pattern"); + return ret; + } + } + + /* for NS or NDP offload packets */ + if (runtime_pm || !(wma->ol_ini_info & 0x2)) { + /* Setup all NS pkt pattern */ + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, + wma->wow.free_ptrn_id[wma->wow.used_free_ptrn_id++], + ns_ptrn, sizeof(arp_ptrn), arp_offset, + arp_mask, sizeof(arp_mask)); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW NS pattern"); + return ret; + } + + } + + *enable_ptrn_match = 1 << vdev_id; + return ret; +} + +/* Finds out list of unused slots in wow pattern cache. Those free slots number + * can be used as pattern ID while configuring default wow pattern. */ +static void wma_update_free_wow_ptrn_id(tp_wma_handle wma) +{ + struct wma_wow_ptrn_cache *cache; + u_int8_t ptrn_id; + + vos_mem_zero(wma->wow.free_ptrn_id, sizeof(wma->wow.free_ptrn_id)); + wma->wow.total_free_ptrn_id = 0; + wma->wow.used_free_ptrn_id = 0; + + for (ptrn_id = 0; ptrn_id < wma->wlan_resource_config.num_wow_filters; + ptrn_id++) { + cache = wma->wow.cache[ptrn_id]; + if (!cache) { + wma->wow.free_ptrn_id[wma->wow.total_free_ptrn_id] = + ptrn_id; + wma->wow.total_free_ptrn_id += 1; + + } + } + + /* + * Clear the wakeup pattern mask to ensure, we configure the + * wakeup patterns properly to FW. + */ + + wma->wow_wakeup_enable_mask = 0; + wma->wow_wakeup_disable_mask = 0; + WMA_LOGD("Total free wow pattern id for default patterns: %d", + wma->wow.total_free_ptrn_id ); +} + +/* Returns true if the user configured any wow pattern for given vdev id */ +static bool wma_is_wow_prtn_cached(tp_wma_handle wma, u_int8_t vdev_id) +{ + struct wma_wow_ptrn_cache *cache; + u_int8_t ptrn_id; + + for (ptrn_id = 0; ptrn_id < WOW_MAX_BITMAP_FILTERS; ptrn_id++) { + cache = wma->wow.cache[ptrn_id]; + if (!cache) + continue; + + if (cache->vdev_id == vdev_id) + return true; + } + + return false; +} + +/* Unpause all the vdev after resume */ +static void wma_unpause_vdev(tp_wma_handle wma) { + int8_t vdev_id; + struct wma_txrx_node *iface; + + for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { + if (!wma->interfaces[vdev_id].handle) + continue; + + #ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL + /* When host resume, by default, unpause all active vdev */ + if (wma->interfaces[vdev_id].pause_bitmap) { + wdi_in_vdev_unpause(wma->interfaces[vdev_id].handle, + 0xffffffff); + wma->interfaces[vdev_id].pause_bitmap = 0; + } + #endif /* QCA_SUPPORT_TXRX_VDEV_PAUSE_LL */ + + iface = &wma->interfaces[vdev_id]; + iface->conn_state = FALSE; + } +} + +static VOS_STATUS wma_resume_req(tp_wma_handle wma, bool runtime_pm) +{ + VOS_STATUS ret = VOS_STATUS_E_AGAIN; + u_int8_t ptrn_id; + + if (runtime_pm) + goto skip_vdev_suspend; + + wma->no_of_resume_ind++; + + if (wma->no_of_resume_ind < wma_get_vdev_count(wma)) + return VOS_STATUS_SUCCESS; + + wma->no_of_resume_ind = 0; + +skip_vdev_suspend: + WMA_LOGD("Clearing already configured wow patterns in fw%s," + " wow_enable: %d, wow_enable_cmd_sent: %d", + runtime_pm ? " for runtime PM" : "", + wma->wow.wow_enable, wma->wow.wow_enable_cmd_sent); + + if (wma->wow.wow_enable_cmd_sent) { + WMA_LOGD("Firmware is still in WoW mode, don't delete WoW" + " patterns"); + VOS_ASSERT(0); + return ret; + } + + if (!wma->wow.wow_enable) { + WMA_LOGD("WoW pattern not configured in FW during suspend," + " skip delete!"); + ret = VOS_STATUS_SUCCESS; + goto pdev_resume; + } + + /* Clear existing wow patterns in FW. */ + for (ptrn_id = 0; ptrn_id < wma->wlan_resource_config.num_wow_filters; + ptrn_id++) { + ret = wma_del_wow_pattern_in_fw(wma, ptrn_id); + if (ret != VOS_STATUS_SUCCESS) + goto end; + } + +end: + wma->wow.wow_enable = FALSE; + /* Reset the DTIM Parameters */ + wma_set_resume_dtim(wma); +pdev_resume: + wmi_set_runtime_pm_inprogress(wma->wmi_handle, FALSE); + /* need to reset if hif_pci_suspend_fails */ + wma_set_wow_bus_suspend(wma, 0); + /* unpause the vdev if left paused and hif_pci_suspend fails */ + wma_unpause_vdev(wma); + + if (runtime_pm) + vos_runtime_pm_allow_suspend(wma->runtime_context.resume); + + return ret; +} + +/* + * Pushes wow patterns from local cache to FW and configures + * wakeup trigger events. + */ +static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma, + v_BOOL_t pno_in_progress, + bool extscan_in_progress, bool pno_matched, + bool runtime_pm) +{ + struct wma_txrx_node *iface; + VOS_STATUS ret = VOS_STATUS_SUCCESS; + u_int8_t vdev_id; + u_int8_t enable_ptrn_match = 0; + v_BOOL_t ap_vdev_available = FALSE; +#ifdef QCA_IBSS_SUPPORT + v_BOOL_t ibss_vdev_available = FALSE; +#endif + bool wps_enable = false; + + if (wma->wow.wow_enable) { + WMA_LOGD("Already%s Fatal Error!", + runtime_pm ? " runtime suspended" : " cfg suspended"); + VOS_BUG(0); + return VOS_STATUS_E_AGAIN; + } + + /* Gather list of free ptrn id. This is needed while configuring + * default wow patterns. + */ + wma_update_free_wow_ptrn_id(wma); + + for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { + iface = &wma->interfaces[vdev_id]; + + if (!iface->handle || + !iface->ptrn_match_enable || + (!(wma_is_vdev_in_ap_mode(wma, vdev_id) +#ifdef QCA_IBSS_SUPPORT + || wma_is_vdev_in_ibss_mode(wma, vdev_id) +#endif + ) && !iface->conn_state)) + continue; + + if (wma_is_vdev_in_ap_mode(wma, vdev_id) +#ifdef QCA_IBSS_SUPPORT + || wma_is_vdev_in_ibss_mode(wma, vdev_id) +#endif + ) { + ap_vdev_available = TRUE; + if (SAP_WPS_DISABLED != iface->wps_state) + wps_enable = true; + } + +#ifdef QCA_IBSS_SUPPORT + if (wma_is_vdev_in_ibss_mode(wma, vdev_id)) + ibss_vdev_available = TRUE; +#endif + + if (wma_is_wow_prtn_cached(wma, vdev_id)) { + /* Configure wow patterns provided by the user */ + ret = wma_wow_usr(wma, vdev_id, &enable_ptrn_match); + } else if (wma_is_vdev_in_ap_mode(wma, vdev_id) +#ifdef QCA_IBSS_SUPPORT + ||wma_is_vdev_in_ibss_mode(wma, vdev_id) +#endif + ) + { + /* Configure AP mode default wow patterns */ + ret = wma_wow_ap(wma, vdev_id, &enable_ptrn_match); + } + else + { + /* Configure STA mode default wow patterns */ + ret = wma_wow_sta(wma, vdev_id, &enable_ptrn_match, + runtime_pm); + } + +#ifdef FEATURE_WLAN_RA_FILTERING + if ((ap_vdev_available == FALSE) && (wma->IsRArateLimitEnabled)) + { + ret = wma_wow_sta_ra_filter(wma, vdev_id); + + } + +#endif + if (ret != VOS_STATUS_SUCCESS) + goto end; + } + + /* + * Configure csa ie wakeup event. + */ + wma_add_wow_wakeup_event(wma, WOW_CSA_IE_EVENT, TRUE); + + wma_add_wow_wakeup_event(wma, WOW_CLIENT_KICKOUT_EVENT, TRUE); + + /* + * Configure pattern match wakeup event. FW does pattern match + * only if pattern match event is enabled. + */ + wma_add_wow_wakeup_event(wma, WOW_PATTERN_MATCH_EVENT, + enable_ptrn_match ? TRUE : FALSE); + + /* Configure magic pattern wakeup event */ + wma_add_wow_wakeup_event(wma, WOW_MAGIC_PKT_RECVD_EVENT, + wma->wow.magic_ptrn_enable); + + /* Configure deauth based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_DEAUTH_RECVD_EVENT, + wma->wow.deauth_enable); + + /* Configure disassoc based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_DISASSOC_RECVD_EVENT, + wma->wow.disassoc_enable); + + /* Configure beacon miss based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_BMISS_EVENT, + wma->wow.bmiss_enable); + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + /* Configure GTK based wakeup. Passing vdev_id 0 because + wma_add_wow_wakeup_event always uses vdev 0 for wow wake event id*/ + wma_add_wow_wakeup_event(wma, WOW_GTK_ERR_EVENT, + wma->wow.gtk_pdev_enable); +#endif + /* Configure probe req based wakeup */ + if (ap_vdev_available) + wma_add_wow_wakeup_event(wma, WOW_PROBE_REQ_WPS_IE_EVENT, + wps_enable); + /* Configure auth req based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_AUTH_REQ_EVENT, + ap_vdev_available); + + /* Configure assoc req based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_ASSOC_REQ_EVENT, + ap_vdev_available); + +#ifdef FEATURE_WLAN_SCAN_PNO + /* Configure pno based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_NLO_DETECTED_EVENT, + pno_in_progress); + + /* Configure pno scan complete wakeup */ + wma_add_wow_wakeup_event(wma, + WOW_NLO_SCAN_COMPLETE_EVENT, pno_matched); +#endif + + /* Configure roaming scan better AP based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_BETTER_AP_EVENT, + TRUE); + + /* Configure ADDBA/DELBA wakeup */ + wma_add_wow_wakeup_event(wma, WOW_HTT_EVENT, TRUE); + +#ifdef FEATURE_WLAN_RA_FILTERING + /* Configure RA filter wakeup */ + if (wma->IsRArateLimitEnabled) + wma_add_wow_wakeup_event(wma, WOW_RA_MATCH_EVENT, TRUE); + else + WMA_LOGD("gRAFilterEnable is not set, RA filterning is disabled"); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wma_add_wow_wakeup_event(wma, WOW_HOST_AUTO_SHUTDOWN_EVENT, TRUE); +#endif + +#ifdef QCA_IBSS_SUPPORT + /* Configure beacon based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_BEACON_EVENT, ibss_vdev_available); +#endif + +#ifdef FEATURE_WLAN_EXTSCAN + wma_add_wow_wakeup_event(wma, WOW_EXTSCAN_EVENT, extscan_in_progress); +#endif + + /* Enable wow wakeup events in FW */ + ret = wma_send_wakeup_mask(wma, TRUE); + if (ret) { + WMA_LOGE("%s Failed to enable wow pattern mask\n", __func__); + goto end; + } + + /* Disable wow wakeup events in FW */ + ret = wma_send_wakeup_mask(wma, FALSE); + if (ret) { + WMA_LOGE("%s Failed to disable wow pattern mask\n", __func__); + goto end; + } + + /* WOW is enabled in pcie suspend callback */ + wma->wow.wow_enable = TRUE; + wma->wow.wow_enable_cmd_sent = FALSE; + +end: + return ret; +} + +/* Adds received wow patterns in local wow pattern cache. */ +static VOS_STATUS wma_wow_add_pattern(tp_wma_handle wma, + tpSirWowlAddBcastPtrn ptrn) +{ + struct wma_wow_ptrn_cache *cache; + + WMA_LOGD("wow add pattern"); + + /* Free if there are any pattern cached already in the same slot. */ + if (wma->wow.cache[ptrn->ucPatternId]) + wma_free_wow_ptrn(wma, ptrn->ucPatternId); + + wma->wow.cache[ptrn->ucPatternId] = (struct wma_wow_ptrn_cache *) + vos_mem_malloc(sizeof(*cache)); + + cache = wma->wow.cache[ptrn->ucPatternId]; + if (!cache) { + WMA_LOGE("Unable to alloc memory for wow"); + return VOS_STATUS_E_NOMEM; + } + + cache->ptrn = (u_int8_t *) vos_mem_malloc(ptrn->ucPatternSize); + if (!cache->ptrn) { + WMA_LOGE("Unable to alloce memory to cache wow pattern"); + vos_mem_free(cache); + wma->wow.cache[ptrn->ucPatternId] = NULL; + return VOS_STATUS_E_NOMEM; + } + + cache->mask = (u_int8_t *) vos_mem_malloc(ptrn->ucPatternMaskSize); + if (!cache->mask) { + WMA_LOGE("Unable to alloc memory to cache wow ptrn mask"); + vos_mem_free(cache->ptrn); + vos_mem_free(cache); + wma->wow.cache[ptrn->ucPatternId] = NULL; + return VOS_STATUS_E_NOMEM; + } + + /* Cache wow pattern info until platform goes to suspend. */ + + cache->vdev_id = ptrn->sessionId; + cache->ptrn_len = ptrn->ucPatternSize; + cache->ptrn_offset = ptrn->ucPatternByteOffset; + cache->mask_len = ptrn->ucPatternMaskSize; + + vos_mem_copy(cache->ptrn, ptrn->ucPattern, cache->ptrn_len); + vos_mem_copy(cache->mask, ptrn->ucPatternMask, cache->mask_len); + wma->wow.no_of_ptrn_cached++; + + WMA_LOGD("wow pattern stored in cache (slot_id: %d, vdev id: %d)", + ptrn->ucPatternId, cache->vdev_id); + return VOS_STATUS_SUCCESS; +} + +/* Deletes given pattern from local wow pattern cache. */ +static VOS_STATUS wma_wow_del_pattern(tp_wma_handle wma, + tpSirWowlDelBcastPtrn ptrn) +{ + WMA_LOGD("wow delete pattern"); + + if (!wma->wow.cache[ptrn->ucPatternId]) { + WMA_LOGE("wow pattern not found (pattern id: %d) in cache", + ptrn->ucPatternId); + return VOS_STATUS_E_INVAL; + } + + wma_free_wow_ptrn(wma, ptrn->ucPatternId); + + return VOS_STATUS_SUCCESS; +} + +/* + * Records pattern enable/disable status locally. This choice will + * take effect when the driver enter into suspend state. + */ +static VOS_STATUS wma_wow_enter(tp_wma_handle wma, + tpSirHalWowlEnterParams info) +{ + struct wma_txrx_node *iface; + + WMA_LOGD("wow enable req received for vdev id: %d", info->sessionId); + + if (info->sessionId > wma->max_bssid) { + WMA_LOGE("Invalid vdev id (%d)", info->sessionId); + vos_mem_free(info); + return VOS_STATUS_E_INVAL; + } + + iface = &wma->interfaces[info->sessionId]; + iface->ptrn_match_enable = info->ucPatternFilteringEnable ? + TRUE : FALSE; + wma->wow.magic_ptrn_enable = info->ucMagicPktEnable ? TRUE : FALSE; + wma->wow.deauth_enable = info->ucWowDeauthRcv ? TRUE : FALSE; + wma->wow.disassoc_enable = info->ucWowDeauthRcv ? TRUE : FALSE; + wma->wow.bmiss_enable = info->ucWowMaxMissedBeacons ? TRUE : FALSE; + + vos_mem_free(info); + + return VOS_STATUS_SUCCESS; +} + +/* Clears all wow states */ +static VOS_STATUS wma_wow_exit(tp_wma_handle wma, + tpSirHalWowlExitParams info) +{ + struct wma_txrx_node *iface; + + WMA_LOGD("wow disable req received for vdev id: %d", info->sessionId); + + if (info->sessionId > wma->max_bssid) { + WMA_LOGE("Invalid vdev id (%d)", info->sessionId); + vos_mem_free(info); + return VOS_STATUS_E_INVAL; + } + + iface = &wma->interfaces[info->sessionId]; + iface->ptrn_match_enable = FALSE; + wma->wow.magic_ptrn_enable = FALSE; + vos_mem_free(info); + + return VOS_STATUS_SUCCESS; +} + +/* Handles suspend indication request received from umac. */ +static VOS_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) +{ + v_BOOL_t pno_in_progress = FALSE; + VOS_STATUS ret; + u_int8_t i; + bool extscan_in_progress = false; + bool pno_matched = false; + struct wma_txrx_node *iface; + bool enable_wow = false; + + if (info == NULL) { + WMA_LOGD("runtime PM: Request to suspend all interfaces"); + wmi_set_runtime_pm_inprogress(wma->wmi_handle, TRUE); + goto suspend_all_iface; + } + + wma->no_of_suspend_ind++; + + if (info->sessionId > wma->max_bssid) { + WMA_LOGE("Invalid vdev id (%d)", info->sessionId); + vos_mem_free(info); + return VOS_STATUS_E_INVAL; + } + + iface = &wma->interfaces[info->sessionId]; + if (!iface) { + WMA_LOGD("vdev %d node is not found", info->sessionId); + vos_mem_free(info); + return VOS_STATUS_SUCCESS; + } + + if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) { + vos_mem_free(info); + + if (wma->no_of_suspend_ind == wma_get_vdev_count(wma)) { + WMA_LOGD("Both magic and pattern byte match are disabled"); + wma->no_of_suspend_ind = 0; + goto send_ready_to_suspend; + } + + return VOS_STATUS_SUCCESS; + } + + iface->conn_state = (info->connectedState) ? TRUE : FALSE; + + /* + * Once WOW is enabled in FW, host can't send anymore + * data to fw. umac sends suspend indication on each + * vdev during platform suspend. WMA has to wait until + * suspend indication received on last vdev before + * enabling wow in fw. + */ + if (wma->no_of_suspend_ind < wma_get_vdev_count(wma)) { + vos_mem_free(info); + return VOS_STATUS_SUCCESS; + } + + wma->no_of_suspend_ind = 0; + wma->wow.gtk_pdev_enable = 0; + +suspend_all_iface: + if (info == NULL) { + for (i = 0; i < wma->max_bssid; i++) { + wma->interfaces[i].conn_state = + !!(wma->interfaces[i].vdev_up && + !wma_is_vdev_in_ap_mode(wma, i)); + } + } + + /* + * Enable WOW if any one of the condition meets, + * 1) Is any one of vdev in beaconning mode (in AP mode) ? + * 2) Is any one of vdev in connected state (in STA mode) ? + * 3) Is PNO in progress in any one of vdev ? + * 4) Is Extscan in progress in any one of vdev ? + */ + for (i = 0; i < wma->max_bssid; i++) { + if ((wma_is_vdev_in_ap_mode(wma, i) +#ifdef QCA_IBSS_SUPPORT + || wma_is_vdev_in_ibss_mode(wma, i) +#endif + ) && wma->interfaces[i].vdev_up && + WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BEACON_OFFLOAD)) { + WMA_LOGD("vdev %d is in beaconning mode, enabling wow", + i); + enable_wow = true; + } + } + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].conn_state) + enable_wow = true; +#ifdef FEATURE_WLAN_SCAN_PNO + if (wma->interfaces[i].pno_in_progress) { + WMA_LOGD("PNO is in progress, enabling wow"); + pno_in_progress = TRUE; + if (wma->interfaces[i].nlo_match_evt_received) + pno_matched = true; + break; + } +#endif + } + +#ifdef FEATURE_WLAN_EXTSCAN + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].extscan_in_progress) { + WMA_LOGD("Extscan is in progress, enabling wow"); + enable_wow = true; + extscan_in_progress = true; + break; + } + } +#endif + + for (i = 0; i < wma->max_bssid; i++) { + wma->wow.gtk_pdev_enable |= wma->wow.gtk_err_enable[i]; + WMA_LOGD("VDEV_ID:%d, gtk_err_enable[%d]:%d, gtk_pdev_enable:%d", + i, i, wma->wow.gtk_err_enable[i], + wma->wow.gtk_pdev_enable); + } + + if (!enable_wow && !pno_in_progress && !extscan_in_progress) { + WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); + vos_mem_free(info); + goto send_ready_to_suspend; + } + + WMA_LOGD("%sWOW Suspend", info ? "" : "Runtime PM "); + + /* + * At this point, suspend indication is received on + * last vdev. It's the time to enable wow in fw. + */ +#ifdef FEATURE_WLAN_LPHB + /* LPHB cache, if any item was enabled, should be + * applied. + */ + WMA_LOGD("%s: checking LPHB cache", __func__); + for (i = 0; i < 2; i++) { + if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) { + WMA_LOGD("%s: LPHB cache for item %d is marked as enable", + __func__, i + 1); + wma_lphb_conf_hbenable( + wma, + &(wma->wow.lphb_cache[i]), + FALSE); + } + } +#endif + + ret = wma_feed_wow_config_to_fw(wma, pno_in_progress, + extscan_in_progress, pno_matched, + info == NULL); + if (ret != VOS_STATUS_SUCCESS) { + wma_send_status_to_suspend_ind(wma, FALSE, info == NULL); + vos_mem_free(info); + return ret; + } + vos_mem_free(info); + +send_ready_to_suspend: + /* Set the Suspend DTIM Parameters */ + wma_set_suspend_dtim(wma); + + /* to handle race between hif_pci_suspend and + * unpause/pause tx handler + */ + wma_set_wow_bus_suspend(wma, 1); + + wma_send_status_to_suspend_ind(wma, TRUE, info == NULL); + + return VOS_STATUS_SUCCESS; +} + +/* + * Sends host wakeup indication to FW. On receiving this indication, + * FW will come out of WOW. + */ +static VOS_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma) +{ + wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd; + wmi_buf_t buf; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int32_t len; + int ret; +#ifdef CONFIG_CNSS + tpAniSirGlobal pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return VOS_STATUS_E_FAILURE; + } +#endif + + len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_wow_hostwakeup_from_sleep_cmd_fixed_param)); + + vos_event_reset(&wma->wma_resume_event); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID); + if (ret) { + WMA_LOGE("Failed to send host wakeup indication to fw"); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Host wakeup indication sent to fw"); + + vos_status = vos_wait_single_event(&(wma->wma_resume_event), + WMA_RESUME_TIMEOUT); + if (VOS_STATUS_SUCCESS != vos_status) { + WMA_LOGP("%s: Timeout waiting for resume event from FW", __func__); + WMA_LOGP("%s: Pending commands %d credits %d", __func__, + wmi_get_pending_cmds(wma->wmi_handle), + wmi_get_host_credits(wma->wmi_handle)); + if (!vos_is_logp_in_progress(VOS_MODULE_ID_WDA, NULL)) { +#ifdef CONFIG_CNSS + if (pMac->sme.enableSelfRecovery) { + wmi_tag_crash_inject(wma->wmi_handle, true); + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } +#else + VOS_BUG(0); +#endif + } else { + WMA_LOGE("%s: SSR in progress, ignore resume timeout", __func__); + } + } else { + WMA_LOGD("Host wakeup received"); + } + + if (VOS_STATUS_SUCCESS == vos_status) + wmi_set_target_suspend(wma->wmi_handle, FALSE); + + return vos_status; +} + +#ifdef FEATURE_WLAN_D0WOW +/* Disable D0-WOW in firmware. */ +VOS_STATUS wma_disable_d0wow_in_fw(tp_wma_handle wma) +{ + wmi_d0_wow_enable_disable_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len; + int host_credits; + int wmi_pending_cmds; + int ret = 0; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; +#ifdef CONFIG_CNSS + tpAniSirGlobal pmac; + + pmac = vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); + if (!pmac) { + WMA_LOGE("%s: Unable to get PE context!", __func__); + return VOS_STATUS_E_FAILURE; + } +#endif + + len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed to allocate WMI buffer!", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_d0_wow_enable_disable_cmd_fixed_param)); + cmd->enable = 0; + + host_credits = wmi_get_host_credits(wma->wmi_handle); + wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle); + if (host_credits < WMI_WOW_REQUIRED_CREDITS) { + WMA_LOGE("%s: No Credits when resume: %d, pending_cmds: %d, " + "cannot resume back", __func__, host_credits, + wmi_pending_cmds); + HTC_dump_counter_info(wma->htc_handle); + if (vos_is_logp_in_progress(VOS_MODULE_ID_WDA, NULL)) { + VOS_ASSERT(0); + } else { +#ifdef CONFIG_CNSS + if (pmac->sme.enableSelfRecovery) { + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } +#endif + } + + return VOS_STATUS_E_FAILURE; + } + + vos_event_reset(&wma->wma_resume_event); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_D0_WOW_ENABLE_DISABLE_CMDID); + if (ret) { + WMA_LOGE("Failed to disable D0-WOW in FW!"); + goto error; + } + + vos_status = vos_wait_single_event(&(wma->wma_resume_event), + WMA_RESUME_TIMEOUT); + if (VOS_STATUS_SUCCESS != vos_status) { + WMA_LOGP("%s: Timeout waiting for resume event from FW!", + __func__); + WMA_LOGP("%s: Pending commands: %d credits: %d", __func__, + wmi_get_pending_cmds(wma->wmi_handle), + wmi_get_host_credits(wma->wmi_handle)); + if (vos_is_logp_in_progress(VOS_MODULE_ID_WDA, NULL)) { + VOS_ASSERT(0); + } else { +#ifdef CONFIG_CNSS + if (pmac->sme.enableSelfRecovery) { + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } +#endif + } + + return VOS_STATUS_E_FAILURE; + } + + wma->wow.wow_enable_cmd_sent = FALSE; + wmi_set_d0wow_flag(wma->wmi_handle, FALSE); + WMA_LOGD("D0-WOW is disabled successfully in FW."); + return vos_status; + +error: + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; +} +#endif /* FEATURE_WLAN_D0WOW */ + +/* Disable wow in PCIe resume context. */ +int wma_disable_wow_in_fw(WMA_HANDLE handle, int runtime_pm) +{ + tp_wma_handle wma = handle; + VOS_STATUS ret; + + if (!wma->wow.wow_enable_cmd_sent) { + return VOS_STATUS_SUCCESS; + } + + WMA_LOGD("WoW Resume in PCIe Context\n"); + +#ifdef FEATURE_WLAN_D0WOW + if (wma->ap_client_cnt > 0) { + WMA_LOGD("Exiting D0-WOW since client count is %d.", + wma->ap_client_cnt); + return wma_disable_d0wow_in_fw(wma); + } +#endif + + ret = wma_send_host_wakeup_ind_to_fw(wma); + + if (ret != VOS_STATUS_SUCCESS) + return ret; + + wma->wow.wow_enable_cmd_sent = FALSE; + + /* To allow the tx pause/unpause events */ + wma_set_wow_bus_suspend(wma, 0); + /* Unpause the vdev as we are resuming */ + wma_unpause_vdev(wma); + + return ret; +} + +#ifdef WLAN_FEATURE_LPSS +/** + * wma_is_lpass_enabled() - check if lpass is enabled + * @handle: Pointer to wma handle + * + * WoW is needed if LPASS or NaN feature is enabled in INI because + * target can't wake up itself if its put in PDEV suspend when LPASS + * or NaN features are supported + * + * Return: true if lpass is enabled else false + */ +bool static wma_is_lpass_enabled(tp_wma_handle wma) +{ + if (wma->is_lpass_enabled) + return true; + else + return false; +} +#else +bool static wma_is_lpass_enabled(tp_wma_handle wma) +{ + return false; +} +#endif + +#ifdef WLAN_FEATURE_NAN +/** + * wma_is_nan_enabled() - check if NaN is enabled + * @handle: Pointer to wma handle + * + * WoW is needed if LPASS or NaN feature is enabled in INI because + * target can't wake up itself if its put in PDEV suspend when LPASS + * or NaN features are supported + * + * Return: true if NaN is enabled else false + */ +bool static wma_is_nan_enabled(tp_wma_handle wma) +{ + if (wma->is_nan_enabled) + return true; + else + return false; +} +#else +bool static wma_is_nan_enabled(tp_wma_handle wma) +{ + return false; +} +#endif + +/** + * wma_is_wow_mode_selected() - check if wow needs to be enabled in fw + * @handle: Pointer to wma handle + * + * If lpass is enabled then always do wow else check wow_enable config + * + * Return: true is wow mode is needed else false + */ +int wma_is_wow_mode_selected(WMA_HANDLE handle) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + + if (wma_is_lpass_enabled(wma)) { + WMA_LOGD("LPASS is enabled select WoW"); + return true; + } else if (wma_is_nan_enabled(wma)) { + WMA_LOGD("NAN is enabled select WoW"); + return true; + } else { + WMA_LOGD("WoW enable %d", wma->wow.wow_enable); + return wma->wow.wow_enable; + } +} + +#ifdef WLAN_FEATURE_APFIND + +/** + * wma_apfind_set_cmd() - set APFIND configuration to firmware + * @wda_handle: pointer to wma handle. + * @apfind_req: pointer to apfind configuration request. + * + * This is called to send APFIND configuations to firmware via WMI command. + * + * Return: VOS_STATUS. + */ +static VOS_STATUS wma_apfind_set_cmd(void *wda_handle, + struct hal_apfind_request *apfind_req) +{ + int ret; + tp_wma_handle wma_handle = (tp_wma_handle)wda_handle; + wmi_apfind_cmd_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + u_int16_t apfind_data_len, apfind_data_len_aligned; + u_int8_t *buf_ptr; + + if (!apfind_req) { + WMA_LOGE("%s:apfind req is not valid", __func__); + return VOS_STATUS_E_FAILURE; + } + apfind_data_len = apfind_req->request_data_len; + apfind_data_len_aligned = roundup(apfind_req->request_data_len, + sizeof(u_int32_t)); + len += WMI_TLV_HDR_SIZE + apfind_data_len_aligned; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_apfind_cmd_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_apfind_cmd_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_apfind_cmd_param)); + cmd->data_len = apfind_req->request_data_len; + WMA_LOGD("%s: The data len value is %u", + __func__, apfind_req->request_data_len); + buf_ptr += sizeof(wmi_apfind_cmd_param); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, apfind_data_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, apfind_req->request_data, + cmd->data_len); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_APFIND_CMDID); + if (ret != EOK) { + WMA_LOGE("%s Failed to send set param command ret = %d", __func__, ret); + wmi_buf_free(buf); + } + return ret; +} +#endif /* WLAN_FEATURE_APFIND */ + +tAniGetPEStatsRsp * wma_get_stats_rsp_buf(tAniGetPEStatsReq *get_stats_param) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tANI_U32 len, temp_mask, counter = 0; + + len= sizeof(tAniGetPEStatsRsp); + temp_mask = get_stats_param->statsMask; + + while (temp_mask) { + if (temp_mask & 1) { + switch (counter) { + case eCsrSummaryStats: + len += sizeof(tCsrSummaryStatsInfo); + break; + case eCsrGlobalClassAStats: + len += sizeof(tCsrGlobalClassAStatsInfo); + break; + case eCsrGlobalClassBStats: + len += sizeof(tCsrGlobalClassBStatsInfo); + break; + case eCsrGlobalClassCStats: + len += sizeof(tCsrGlobalClassCStatsInfo); + break; + case eCsrGlobalClassDStats: + len += sizeof(tCsrGlobalClassDStatsInfo); + break; + case eCsrPerStaStats: + len += sizeof(tCsrPerStaStatsInfo); + break; + } + } + + counter++; + temp_mask >>= 1; + } + + stats_rsp_params = (tAniGetPEStatsRsp *)vos_mem_malloc(len); + if (!stats_rsp_params) { + WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp"); + VOS_ASSERT(0); + return NULL; + } + + vos_mem_zero(stats_rsp_params, len); + stats_rsp_params->staId = get_stats_param->staId; + stats_rsp_params->statsMask = get_stats_param->statsMask; + stats_rsp_params->msgType = WDA_GET_STATISTICS_RSP; + stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp); + stats_rsp_params->rc = eHAL_STATUS_SUCCESS; + return stats_rsp_params; +} + +/* function : wma_get_stats_req + * Description : return the statistics + * Args : wma handle, pointer to tAniGetPEStatsReq + * Returns : nothing + */ +static void wma_get_stats_req(WMA_HANDLE handle, + tAniGetPEStatsReq *get_stats_param) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + struct wma_txrx_node *node; + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + tAniGetPEStatsRsp *pGetPEStatsRspParams; + u_int8_t len = sizeof(wmi_request_stats_cmd_fixed_param); + + WMA_LOGD("%s: Enter", __func__); + node = &wma_handle->interfaces[get_stats_param->sessionId]; + if (node->stats_rsp) { + pGetPEStatsRspParams = node->stats_rsp; + if (pGetPEStatsRspParams->staId == get_stats_param->staId && + pGetPEStatsRspParams->statsMask == + get_stats_param->statsMask) { + WMA_LOGI("Stats for staId %d with stats mask %d " + "is pending.... ignore new request", + get_stats_param->staId, + get_stats_param->statsMask); + goto end; + } else { + vos_mem_free(node->stats_rsp); + node->stats_rsp = NULL; + node->fw_stats_set = 0; + } + } + + pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param); + if (!pGetPEStatsRspParams) + goto end; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed to allocate wmi buffer", __func__); + goto failed; + } + + node->fw_stats_set = 0; + node->stats_rsp = pGetPEStatsRspParams; + wma_handle->get_sta_rssi = FALSE; + cmd = (wmi_request_stats_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param)); + cmd->stats_id = WMI_REQUEST_PEER_STAT|WMI_REQUEST_PDEV_STAT| + WMI_REQUEST_VDEV_STAT; + cmd->vdev_id = get_stats_param->sessionId; + WMI_CHAR_ARRAY_TO_MAC_ADDR(node->bssid, &cmd->peer_macaddr); + WMA_LOGD("STATS REQ VDEV_ID:%d-->", cmd->vdev_id); + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_REQUEST_STATS_CMDID)) { + + WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID", + __func__); + wmi_buf_free(buf); + goto failed; + } + + goto end; +failed: + + pGetPEStatsRspParams->rc = eHAL_STATUS_FAILURE; + node->stats_rsp = NULL; + /* send response to UMAC*/ + wma_send_msg(wma_handle, WDA_GET_STATISTICS_RSP, pGetPEStatsRspParams, + 0) ; +end: + vos_mem_free(get_stats_param); + WMA_LOGD("%s: Exit", __func__); + return; +} + +static void wma_init_scan_req(tp_wma_handle wma_handle, + tInitScanParams *init_scan_param) +{ + WMA_LOGD("%s: Send dummy init scan response for legacy scan request", + __func__); + init_scan_param->status = eHAL_STATUS_SUCCESS; + /* send ini scan response message back to PE */ + wma_send_msg(wma_handle, WDA_INIT_SCAN_RSP, (void *)init_scan_param, + 0); +} + +static void wma_finish_scan_req(tp_wma_handle wma_handle, + tFinishScanParams *finish_scan_param) +{ + WMA_LOGD("%s: Send dummy finish scan response for legacy scan request", + __func__); + finish_scan_param->status = eHAL_STATUS_SUCCESS; + /* send finish scan response message back to PE */ + wma_send_msg(wma_handle, WDA_FINISH_SCAN_RSP, (void *)finish_scan_param, + 0); +} + +static void wma_process_update_opmode(tp_wma_handle wma_handle, + tUpdateVHTOpMode *update_vht_opmode) +{ + WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode); + + wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac, + WMI_PEER_CHWIDTH, update_vht_opmode->opMode, + update_vht_opmode->smesessionId); +} + +static void wma_process_update_rx_nss(tp_wma_handle wma_handle, + tUpdateRxNss *update_rx_nss) +{ + struct wma_txrx_node *intr = + &wma_handle->interfaces[update_rx_nss->smesessionId]; + int rxNss = update_rx_nss->rxNss; + + if (wma_handle->per_band_chainmask_supp) + wma_update_txrx_chainmask(intr->nss, &rxNss); + else + wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rxNss); + intr->nss = (tANI_U8) rxNss; + update_rx_nss->rxNss = (tANI_U32) rxNss; + + WMA_LOGD("%s: Rx Nss = %d", __func__, update_rx_nss->rxNss); + + wma_set_peer_param(wma_handle, update_rx_nss->peer_mac, + WMI_PEER_NSS, update_rx_nss->rxNss, + update_rx_nss->smesessionId); +} + +#ifdef FEATURE_OEM_DATA_SUPPORT +static void wma_start_oem_data_req(tp_wma_handle wma_handle, + tStartOemDataReq *startOemDataReq) +{ + wmi_buf_t buf; + u_int8_t *cmd; + int ret = 0; + u_int32_t *msg_subtype; + tStartOemDataRsp *pStartOemDataRsp; + + WMA_LOGD("%s: Send OEM Data Request to target", __func__); + + if (!startOemDataReq) { + WMA_LOGE("%s: startOemDataReq is null", __func__); + goto out; + } + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not send Oem data request cmd", __func__); + return; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, + (OEM_DATA_REQ_SIZE + WMI_TLV_HDR_SIZE)); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + goto out; + } + + cmd = (u_int8_t *)wmi_buf_data(buf); + + WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, + OEM_DATA_REQ_SIZE); + cmd += WMI_TLV_HDR_SIZE; + vos_mem_copy(cmd, &startOemDataReq->oemDataReq[0], OEM_DATA_REQ_SIZE); + + WMA_LOGI("%s: Sending OEM Data Request to target, data len (%d)", + __func__, OEM_DATA_REQ_SIZE); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + (OEM_DATA_REQ_SIZE + + WMI_TLV_HDR_SIZE), + WMI_OEM_REQ_CMDID); + + if (ret != EOK) { + WMA_LOGE("%s:wmi cmd send failed", __func__); + adf_nbuf_free(buf); + } + +out: + /* free oem data req buffer received from UMAC */ + if (startOemDataReq) + vos_mem_free(startOemDataReq); + + /* Now send data resp back to PE/SME with message sub-type of + * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears + * up pending active command. Later when desired oem response(s) + * comes as wmi event from target then those shall be passed + * to oem application + */ + pStartOemDataRsp = vos_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) + { + WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE", + __func__); + return; + } + vos_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (u_int32_t *)(&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_INTERNAL_RSP; + + WMA_LOGI("%s: Sending WDA_START_OEM_DATA_RSP to clear up PE/SME pending cmd", + __func__); + + wma_send_msg(wma_handle, WDA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + + return; +} +#endif /* FEATURE_OEM_DATA_SUPPORT */ + +#ifdef FEATURE_WLAN_ESE + +#define TSM_DELAY_HISTROGRAM_BINS 4 +/* + * @brief: A parallel function to WDA_ProcessTsmStatsReq for pronto. This + * function fetches stats from data path APIs and post + * WDA_TSM_STATS_RSP msg back to LIM. + * @param: wma_handler - handle to wma + * @param: pTsmStatsMsg - TSM stats struct that needs to be populated and + * passed in message. + */ +VOS_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, + void *pTsmStatsMsg) +{ + u_int8_t counter; + u_int32_t queue_delay_microsec = 0; + u_int32_t tx_delay_microsec = 0; + u_int16_t packet_count = 0; + u_int16_t packet_loss_count = 0; + tpAniTrafStrmMetrics pTsmMetric = NULL; +#ifdef FEATURE_WLAN_ESE_UPLOAD + tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq)pTsmStatsMsg; + tpAniGetTsmStatsRsp pTsmRspParams = NULL; +#else + tpTSMStats pStats = (tpTSMStats)pTsmStatsMsg; +#endif + int tid = pStats->tid; + /* + * The number of histrogram bin report by data path api are different + * than required by TSM, hence different (6) size array used + */ + u_int16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = {0,}; + + ol_txrx_pdev_handle pdev = vos_get_context(VOS_MODULE_ID_TXRX, + wma_handler->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + vos_mem_free(pTsmStatsMsg); + return VOS_STATUS_E_INVAL; + } + + /* get required values from data path APIs */ + ol_tx_delay(pdev, &queue_delay_microsec, &tx_delay_microsec, tid); + ol_tx_delay_hist(pdev, bin_values, tid); + ol_tx_packet_count(pdev, &packet_count, &packet_loss_count, tid ); + +#ifdef FEATURE_WLAN_ESE_UPLOAD + pTsmRspParams = + (tpAniGetTsmStatsRsp)vos_mem_malloc(sizeof(tAniGetTsmStatsRsp)); + if(NULL == pTsmRspParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(pTsmStatsMsg); + return VOS_STATUS_E_NOMEM; + } + pTsmRspParams->staId = pStats->staId; + pTsmRspParams->rc = eSIR_FAILURE; + pTsmRspParams->tsmStatsReq = pStats; + pTsmMetric = &pTsmRspParams->tsmMetrics; +#else + pTsmMetric = (tpAniTrafStrmMetrics)&pStats->tsmMetrics; +#endif + /* populate pTsmMetric */ + pTsmMetric->UplinkPktQueueDly = queue_delay_microsec; + /* store only required number of bin values */ + for ( counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) + { + pTsmMetric->UplinkPktQueueDlyHist[counter] = bin_values[counter]; + } + pTsmMetric->UplinkPktTxDly = tx_delay_microsec; + pTsmMetric->UplinkPktLoss = packet_loss_count; + pTsmMetric->UplinkPktCount = packet_count; + + /* + * No need to populate roaming delay and roaming count as they are + * being populated just before sending IAPP frame out + */ + /* post this message to LIM/PE */ +#ifdef FEATURE_WLAN_ESE_UPLOAD + wma_send_msg(wma_handler, WDA_TSM_STATS_RSP, (void *)pTsmRspParams , 0) ; +#else + wma_send_msg(wma_handler, WDA_TSM_STATS_RSP, (void *)pTsmStatsMsg , 0) ; +#endif + return VOS_STATUS_SUCCESS; +} + +#endif /* FEATURE_WLAN_ESE */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static void wma_set_ric_req(tp_wma_handle wma, void *msg, tANI_U8 is_add_ts) +{ + wmi_ric_request_fixed_param *cmd; + wmi_ric_tspec *tspec_param; + wmi_buf_t buf; + u_int8_t *buf_ptr; + tSirMacTspecIE *ptspecIE; + int32_t len = sizeof(wmi_ric_request_fixed_param)+ + WMI_TLV_HDR_SIZE + + sizeof(wmi_ric_tspec); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return; + } + + buf_ptr = (u_int8_t *)wmi_buf_data(buf); + + cmd = (wmi_ric_request_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ric_request_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_ric_request_fixed_param)); + if (is_add_ts) + cmd->vdev_id = ((tAddTsParams *)msg)->sessionId; + else + cmd->vdev_id = ((tDelTsParams *)msg)->sessionId; + cmd->num_ric_request = 1; /* Today we are sending only 1 ric at once */ + cmd->is_add_ric = is_add_ts; + + buf_ptr += sizeof(wmi_ric_request_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_ric_tspec)); + + buf_ptr += WMI_TLV_HDR_SIZE; + tspec_param = (wmi_ric_tspec *)buf_ptr; + WMITLV_SET_HDR(&tspec_param->tlv_header, + WMITLV_TAG_STRUC_wmi_ric_tspec, + WMITLV_GET_STRUCT_TLVLEN(wmi_ric_tspec)); + + if(is_add_ts) + ptspecIE = &(((tAddTsParams *)msg)->tspec); + else + ptspecIE = &(((tDelTsParams *)msg)->delTsInfo.tspec); + + /* Fill the tsinfo in the format expected by firmware */ +#ifndef ANI_LITTLE_BIT_ENDIAN + vos_mem_copy(((tANI_U8 *)&tspec_param->ts_info)+1, + ((tANI_U8 *)&ptspecIE->tsinfo)+1, 2); +#else + vos_mem_copy(((tANI_U8 *)&tspec_param->ts_info), + ((tANI_U8 *)&ptspecIE->tsinfo)+1, 2); +#endif + + tspec_param->nominal_msdu_size = ptspecIE->nomMsduSz; + tspec_param->maximum_msdu_size = ptspecIE->maxMsduSz; + tspec_param->min_service_interval = ptspecIE->minSvcInterval; + tspec_param->max_service_interval = ptspecIE->maxSvcInterval; + tspec_param->inactivity_interval = ptspecIE->inactInterval; + tspec_param->suspension_interval = ptspecIE->suspendInterval; + tspec_param->svc_start_time = ptspecIE->svcStartTime; + tspec_param->min_data_rate = ptspecIE->minDataRate; + tspec_param->mean_data_rate = ptspecIE->meanDataRate; + tspec_param->peak_data_rate = ptspecIE->peakDataRate; + tspec_param->max_burst_size = ptspecIE->maxBurstSz; + tspec_param->delay_bound = ptspecIE->delayBound; + tspec_param->min_phy_rate = ptspecIE->minPhyRate; + tspec_param->surplus_bw_allowance = ptspecIE->surplusBw; + tspec_param->medium_time = 0; + + WMA_LOGI("%s: Set RIC Req is_add_ts:%d", __func__, is_add_ts); + + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_ROAM_SET_RIC_REQUEST_CMDID)) { + WMA_LOGP("%s: Failed to send vdev Set RIC Req command", __func__); + if(is_add_ts) + ((tAddTsParams *)msg)->status = eHAL_STATUS_FAILURE; + adf_nbuf_free(buf); + } +} +#endif + +static void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg) +{ + wmi_vdev_wmm_delts_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + goto err; + } + cmd = (wmi_vdev_wmm_delts_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_wmm_delts_cmd_fixed_param)); + cmd->vdev_id = msg->sessionId; + cmd->ac = TID_TO_WME_AC(msg->userPrio); + + WMA_LOGD("Delts vdev:%d, ac:%d, %s:%d", + cmd->vdev_id, cmd->ac, __FUNCTION__, __LINE__); + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_WMM_DELTS_CMDID)) { + WMA_LOGP("%s: Failed to send vdev DELTS command", __func__); + adf_nbuf_free(buf); + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(msg->setRICparams == true) + wma_set_ric_req(wma, msg, false); +#endif + +err: + vos_mem_free(msg); +} + +/* + * @brief: A function to handle WDA_AGGR_QOS_REQ. This will send out + * ADD_TS requestes to firmware in loop for all the ACs with + * active flow. + * @param: wma_handler - handle to wma + * @param: pAggrQosRspMsg - combined struct for all ADD_TS requests. + */ +static void wma_aggr_qos_req(tp_wma_handle wma, tAggrAddTsParams *pAggrQosRspMsg) +{ + int i = 0; + wmi_vdev_wmm_addts_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + + for( i = 0; i < HAL_QOS_NUM_AC_MAX; i++ ) + { + // if flow in this AC is active + if ( ((1 << i) & pAggrQosRspMsg->tspecIdx) ) + { + /* + * as per implementation of wma_add_ts_req() we + * are not waiting any response from firmware so + * apart from sending ADDTS to firmware just send + * success to upper layers + */ + pAggrQosRspMsg->status[i] = eHAL_STATUS_SUCCESS; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + goto aggr_qos_exit; + } + cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_wmm_addts_cmd_fixed_param)); + cmd->vdev_id = pAggrQosRspMsg->sessionId; + cmd->ac = TID_TO_WME_AC(pAggrQosRspMsg->tspec[i].tsinfo.traffic.userPrio); + cmd->medium_time_us = pAggrQosRspMsg->tspec[i].mediumTime * 32; + cmd->downgrade_type = WMM_AC_DOWNGRADE_DEPRIO; + WMA_LOGD("%s:%d: Addts vdev:%d, ac:%d, mediumTime:%d downgrade_type:%d", + __func__, __LINE__, cmd->vdev_id, cmd->ac, + cmd->medium_time_us, cmd->downgrade_type); + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_WMM_ADDTS_CMDID)) { + WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__); + pAggrQosRspMsg->status[i] = eHAL_STATUS_FAILURE; + adf_nbuf_free(buf); + } + } + } + +aggr_qos_exit: + // send reponse to upper layers from here only. + wma_send_msg(wma, WDA_AGGR_QOS_RSP, pAggrQosRspMsg, 0); +} + +static void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg) +{ + wmi_vdev_wmm_addts_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t len = sizeof(*cmd); + +#ifdef FEATURE_WLAN_ESE + /* + * msmt_interval is in unit called TU (1 TU = 1024 us) + * max value of msmt_interval cannot make resulting + * interval_miliseconds overflow 32 bit + */ + tANI_U32 intervalMiliseconds; + ol_txrx_pdev_handle pdev = + vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + goto err; + } + + intervalMiliseconds = (msg->tsm_interval*1024)/1000; + + ol_tx_set_compute_interval(pdev, intervalMiliseconds); +#endif + msg->status = eHAL_STATUS_SUCCESS; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + goto err; + } + cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_wmm_addts_cmd_fixed_param)); + cmd->vdev_id = msg->sme_session_id; + cmd->ac = TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio); + cmd->medium_time_us = msg->tspec.mediumTime * 32; + cmd->downgrade_type = WMM_AC_DOWNGRADE_DROP; + WMA_LOGD("Addts vdev:%d, ac:%d, mediumTime:%d, downgrade_type:%d %s:%d", + cmd->vdev_id, cmd->ac, cmd->medium_time_us, + cmd->downgrade_type, __func__, __LINE__); + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_WMM_ADDTS_CMDID)) { + WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__); + msg->status = eHAL_STATUS_FAILURE; + adf_nbuf_free(buf); + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(msg->setRICparams == true) + wma_set_ric_req(wma, msg, true); +#endif + +err: + wma_send_msg(wma, WDA_ADD_TS_RSP, msg, 0); +} + +static int wma_process_receive_filter_set_filter_req(tp_wma_handle wma_handle, + tSirRcvPktFilterCfgType *rcv_filter_param) +{ + wmi_chatter_coalescing_add_filter_cmd_fixed_param *cmd; + chatter_pkt_coalescing_filter *cmd_filter; + u_int8_t *buf_ptr; + wmi_buf_t buf; + int num_rules = 1; /* Only one rule at a time */ + int len; + int err; + int i; + + /* allocate the memory */ + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + sizeof(*cmd_filter) * num_rules; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_param cmd"); + vos_mem_free(rcv_filter_param); + return -ENOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + + /* fill the fixed part */ + cmd = (wmi_chatter_coalescing_add_filter_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_chatter_coalescing_add_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_chatter_coalescing_add_filter_cmd_fixed_param)); + cmd->num_of_filters = num_rules; + + /* specify the type of data in the subsequent buffer */ + buf_ptr += sizeof(*cmd); + cmd_filter = (chatter_pkt_coalescing_filter *) buf_ptr; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + num_rules * sizeof(chatter_pkt_coalescing_filter)); + + /* fill the actual filter data */ + buf_ptr += WMI_TLV_HDR_SIZE; + cmd_filter = (chatter_pkt_coalescing_filter *) buf_ptr; + + WMITLV_SET_HDR(&cmd_filter->tlv_header, + WMITLV_TAG_STRUC_wmi_chatter_pkt_coalescing_filter, + WMITLV_GET_STRUCT_TLVLEN(chatter_pkt_coalescing_filter)); + + cmd_filter->filter_id = rcv_filter_param->filterId; + cmd_filter->max_coalescing_delay = rcv_filter_param->coalesceTime; + cmd_filter->pkt_type = CHATTER_COALESCING_PKT_TYPE_UNICAST | + CHATTER_COALESCING_PKT_TYPE_MULTICAST | + CHATTER_COALESCING_PKT_TYPE_BROADCAST; + cmd_filter->num_of_test_field = MIN(rcv_filter_param->numFieldParams, + CHATTER_MAX_FIELD_TEST); + + for (i = 0; i < cmd_filter->num_of_test_field; i++) { + cmd_filter->test_fields[i].offset = rcv_filter_param->paramsData[i].dataOffset; + cmd_filter->test_fields[i].length = MIN(rcv_filter_param->paramsData[i].dataLength, + CHATTER_MAX_TEST_FIELD_LEN32); + cmd_filter->test_fields[i].test = rcv_filter_param->paramsData[i].cmpFlag; + memcpy(&cmd_filter->test_fields[i].value, rcv_filter_param->paramsData[i].compareData, + cmd_filter->test_fields[i].length); + memcpy(&cmd_filter->test_fields[i].mask, rcv_filter_param->paramsData[i].dataMask, + cmd_filter->test_fields[i].length); + } + WMA_LOGD("Chatter packets, adding filter with id: %d, num_test_fields=%d",cmd_filter->filter_id, + cmd_filter->num_of_test_field); + /* send the command along with data */ + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_CHATTER_ADD_COALESCING_FILTER_CMDID); + if (err) { + WMA_LOGE("Failed to send set_param cmd"); + wmi_buf_free(buf); + vos_mem_free(rcv_filter_param); + return -EIO; + } + vos_mem_free(rcv_filter_param); + return 0; /* SUCCESS */ +} + +static int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma_handle, + tSirRcvFltPktClearParam *rcv_clear_param) +{ + wmi_chatter_coalescing_delete_filter_cmd_fixed_param *cmd; + wmi_buf_t buf; + int err; + + /* allocate the memory */ + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_param cmd"); + vos_mem_free(rcv_clear_param); + return -ENOMEM; + } + + /* fill the fixed part */ + cmd = (wmi_chatter_coalescing_delete_filter_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_chatter_coalescing_delete_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_chatter_coalescing_delete_filter_cmd_fixed_param)); + cmd->filter_id = rcv_clear_param->filterId; + WMA_LOGD("Chatter packets, clearing filter with id: %d",cmd->filter_id); + + /* send the command along with data */ + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID); + if (err) { + WMA_LOGE("Failed to send set_param cmd"); + wmi_buf_free(buf); + vos_mem_free(rcv_clear_param); + return -EIO; + } + vos_mem_free(rcv_clear_param); + return 0; /* SUCCESS */ +} + +static int wma_set_base_macaddr_indicate(tp_wma_handle wma_handle, + tSirMacAddr *customAddr) +{ + wmi_pdev_set_base_macaddr_cmd_fixed_param *cmd; + wmi_buf_t buf; + int err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_base_macaddr cmd"); + return -ENOMEM; + } + + cmd = (wmi_pdev_set_base_macaddr_cmd_fixed_param *) wmi_buf_data(buf); + vos_mem_zero(cmd, sizeof(*cmd)); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_set_base_macaddr_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_set_base_macaddr_cmd_fixed_param)); + WMI_CHAR_ARRAY_TO_MAC_ADDR(*customAddr, &cmd->base_macaddr); + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_PDEV_SET_BASE_MACADDR_CMDID); + if (err) { + WMA_LOGE("Failed to send set_base_macaddr cmd"); + adf_os_mem_free(buf); + return -EIO; + } + WMA_LOGD("Base MAC Addr: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY((*customAddr))); + + return 0; +} + +static void wma_data_tx_ack_work_handler(struct work_struct *ack_work) +{ + struct wma_tx_ack_work_ctx *work; + tp_wma_handle wma_handle; + pWDAAckFnTxComp ack_cb; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_WDA, NULL)) { + WMA_LOGE("%s: Driver load/unload in progress", __func__); + return; + } + + work = container_of(ack_work, struct wma_tx_ack_work_ctx, ack_cmp_work); + wma_handle = work->wma_handle; + ack_cb = wma_handle->umac_data_ota_ack_cb; + + if (work->status) + WMA_LOGE("Data Tx Ack Cb Status %d", work->status); + else + WMA_LOGD("Data Tx Ack Cb Status %d", work->status); + + /* Call the Ack Cb registered by UMAC */ + if (ack_cb) + ack_cb((tpAniSirGlobal)(wma_handle->mac_context), + work->status ? 0 : 1); + else + WMA_LOGE("Data Tx Ack Cb is NULL"); + + wma_handle->umac_data_ota_ack_cb = NULL; + wma_handle->last_umac_data_nbuf = NULL; + adf_os_mem_free(work); + wma_handle->ack_work_ctx = NULL; +} + +/** + * wma_data_tx_ack_comp_hdlr - handles tx data ack completion + * @context: context with which the handler is registered + * @netbuf: tx data nbuf + * @err: status of tx completion + * + * This is the cb registered with TxRx for + * Ack Complete + */ +static void +wma_data_tx_ack_comp_hdlr(void *wma_context, + adf_nbuf_t netbuf, int32_t status) +{ + ol_txrx_pdev_handle pdev; + tp_wma_handle wma_handle = (tp_wma_handle)wma_context; + + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid WMA Handle", __func__); + return; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma_handle->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return; + } + + /* + * if netBuf does not match with pending nbuf then just free the + * netbuf and do not call ack cb + */ + if (wma_handle->last_umac_data_nbuf != netbuf) { + if (wma_handle->umac_data_ota_ack_cb) { + WMA_LOGE("%s: nbuf does not match but umac_data_ota_ack_cb is not null", + __func__); + } else { + WMA_LOGE("%s: nbuf does not match and umac_data_ota_ack_cb is also null", + __func__); + } + goto free_nbuf; + } + + if(wma_handle && wma_handle->umac_data_ota_ack_cb) { + struct wma_tx_ack_work_ctx *ack_work; + + ack_work = + adf_os_mem_alloc(NULL, sizeof(struct wma_tx_ack_work_ctx)); + wma_handle->ack_work_ctx = ack_work; + if(ack_work) { +#ifdef CONFIG_CNSS + cnss_init_work(&ack_work->ack_cmp_work, + wma_data_tx_ack_work_handler); +#else + INIT_WORK(&ack_work->ack_cmp_work, + wma_data_tx_ack_work_handler); +#endif + ack_work->wma_handle = wma_handle; + ack_work->sub_type = 0; + ack_work->status = status; + + /* Schedue the Work */ + schedule_work(&ack_work->ack_cmp_work); + } + } + +free_nbuf: + /* unmap and freeing the tx buf as txrx is not taking care */ + adf_nbuf_unmap_single(pdev->osdev, netbuf, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(netbuf); +} + +static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id, + tSirMacAddr multicastAddr, bool clearList) +{ + WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd; + wmi_buf_t buf; + int err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_param cmd"); + return -ENOMEM; + } + + cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf); + vos_mem_zero(cmd, sizeof(*cmd)); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param)); + cmd->action = (clearList? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET); + cmd->vdev_id = vdev_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(multicastAddr, &cmd->mcastbdcastaddr); + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_SET_MCASTBCAST_FILTER_CMDID); + if (err) { + WMA_LOGE("Failed to send set_param cmd"); + adf_os_mem_free(buf); + return -EIO; + } + WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d\n", + cmd->action, vdev_id, clearList); + WMA_LOGD("MCBC MAC Addr: %0x:%0x:%0x:%0x:%0x:%0x\n", + multicastAddr[0], multicastAddr[1], multicastAddr[2], + multicastAddr[3], multicastAddr[4], multicastAddr[5]); + return 0; +} + +static VOS_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle, + tSirRcvFltMcAddrList *mcbc_param) +{ + uint8_t vdev_id = 0; + int i; + + if(mcbc_param->ulMulticastAddrCnt <= 0) { + WMA_LOGW("Number of multicast addresses is 0"); + return VOS_STATUS_E_FAILURE; + } + + if (!wma_find_vdev_by_addr(wma_handle, mcbc_param->selfMacAddr, &vdev_id)) { + WMA_LOGE("%s: Failed to find vdev id for %pM", + __func__, mcbc_param->bssId); + return VOS_STATUS_E_FAILURE; + } + /* set mcbc_param->action to clear MCList and reset + * to configure the MCList in FW + */ + + for (i = 0; i < mcbc_param->ulMulticastAddrCnt; i++) { + wma_add_clear_mcbc_filter(wma_handle, vdev_id, + mcbc_param->multicastAddr[i], + (mcbc_param->action == 0)); + } + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define GTK_OFFLOAD_ENABLE 0 +#define GTK_OFFLOAD_DISABLE 1 + +static VOS_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, u_int8_t vdev_id, + tpSirGtkOffloadParams params) +{ + int len; + wmi_buf_t buf; + WMI_GTK_OFFLOAD_CMD_fixed_param *cmd; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + WMA_LOGD("%s Enter", __func__); + + len = sizeof(*cmd); + + /* alloc wmi buffer */ + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD"); + status = VOS_STATUS_E_NOMEM; + goto out; + } + + cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_GTK_OFFLOAD_CMD_fixed_param)); + + cmd->vdev_id = vdev_id; + + /* Request target to enable GTK offload */ + if (params->ulFlags == GTK_OFFLOAD_ENABLE) { + cmd->flags = GTK_OFFLOAD_ENABLE_OPCODE; + wma->wow.gtk_err_enable[vdev_id] = TRUE; + + /* Copy the keys and replay counter */ + vos_mem_copy(cmd->KCK, params->aKCK, GTK_OFFLOAD_KCK_BYTES); + vos_mem_copy(cmd->KEK, params->aKEK, GTK_OFFLOAD_KEK_BYTES); + vos_mem_copy(cmd->replay_counter, ¶ms->ullKeyReplayCounter, + GTK_REPLAY_COUNTER_BYTES); + } else { + wma->wow.gtk_err_enable[vdev_id] = FALSE; + cmd->flags = GTK_OFFLOAD_DISABLE_OPCODE; + } + + /* send the wmi command */ + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_GTK_OFFLOAD_CMDID)) { + WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID"); + wmi_buf_free(buf); + status = VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags); +out: + WMA_LOGD("%s Exit", __func__); + return status; +} + +static VOS_STATUS wma_process_gtk_offload_req(tp_wma_handle wma, + tpSirGtkOffloadParams params) +{ + u_int8_t vdev_id; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + WMA_LOGD("%s Enter", __func__); + + /* Get the vdev id */ + if (!wma_find_vdev_by_bssid(wma, params->bssId, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", params->bssId); + status = VOS_STATUS_E_INVAL; + goto out; + } + + /* Validate vdev id */ + if (vdev_id >= wma->max_bssid){ + WMA_LOGE("invalid vdev_id %d for %pM", vdev_id, params->bssId); + status = VOS_STATUS_E_INVAL; + goto out; + } + + if ((params->ulFlags == GTK_OFFLOAD_ENABLE) && + (wma->wow.gtk_err_enable[vdev_id] == TRUE)) { + WMA_LOGE("%s GTK Offload already enabled. Disable it first " + "vdev_id %d", __func__, vdev_id); + params->ulFlags = GTK_OFFLOAD_DISABLE; + status = wma_send_gtk_offload_req(wma, vdev_id, params); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s Failed to disable GTK Offload", __func__); + goto out; + } + WMA_LOGD("%s Enable GTK Offload again with updated inputs", + __func__); + params->ulFlags = GTK_OFFLOAD_ENABLE; + } + status = wma_send_gtk_offload_req(wma, vdev_id, params); +out: + vos_mem_free(params); + WMA_LOGD("%s Exit", __func__); + return status; +} + +static VOS_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma, + tpSirGtkOffloadGetInfoRspParams params) +{ + u_int8_t vdev_id; + int len; + wmi_buf_t buf; + WMI_GTK_OFFLOAD_CMD_fixed_param *cmd; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + WMA_LOGD("%s Enter", __func__); + + /* Get the vdev id */ + if (!wma_find_vdev_by_bssid(wma, params->bssId, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", params->bssId); + status = VOS_STATUS_E_INVAL; + goto out; + } + + len = sizeof(*cmd); + + /* alloc wmi buffer */ + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("wmi_buf_alloc failed for WMI_GTK_OFFLOAD_CMD"); + status = VOS_STATUS_E_NOMEM; + goto out; + } + + cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_GTK_OFFLOAD_CMD_fixed_param)); + + /* Request for GTK offload status */ + cmd->flags = GTK_OFFLOAD_REQUEST_STATUS_OPCODE; + cmd->vdev_id = vdev_id; + + /* send the wmi command */ + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_GTK_OFFLOAD_CMDID)) { + WMA_LOGE("Failed to send WMI_GTK_OFFLOAD_CMDID for req info"); + wmi_buf_free(buf); + status = VOS_STATUS_E_FAILURE; + } +out: + vos_mem_free(params); + WMA_LOGD("%s Exit", __func__); + return status; +} +#endif + +/* + * Function : wma_enable_arp_ns_offload + * Description : To configure ARP NS off load data to firmware + * when target goes to wow mode. + * Args : @wma - wma handle, @tpSirHostOffloadReq - + * pHostOffloadParams,@bool bArpOnly + * Returns : Returns Failure or Success based on WMI cmd. + * Comments : Since firware expects ARP and NS to be configured + * at a time, Arp info is cached in wma and send along + * with NS info to make both work. + */ +static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, tpSirHostOffloadReq pHostOffloadParams, bool bArpOnly) +{ + int32_t i; + int32_t res; + WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd; + WMI_NS_OFFLOAD_TUPLE *ns_tuple; + WMI_ARP_OFFLOAD_TUPLE *arp_tuple; + A_UINT8* buf_ptr; + wmi_buf_t buf; + int32_t len; + u_int8_t vdev_id; + uint32_t count = 0, num_ns_ext_tuples = 0; + + /* Get the vdev id */ + if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssId, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", pHostOffloadParams->bssId); + vos_mem_free(pHostOffloadParams); + return VOS_STATUS_E_INVAL; + } + + if (!wma->interfaces[vdev_id].vdev_up) { + + WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id); + vos_mem_free(pHostOffloadParams); + return VOS_STATUS_E_FAILURE; + } + + if (!bArpOnly) + count = pHostOffloadParams->num_ns_offload_count; + + len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + + WMI_TLV_HDR_SIZE + // TLV place holder size for array of NS tuples + WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE) + + WMI_TLV_HDR_SIZE + // TLV place holder size for array of ARP tuples + WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE); + + /* + * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate + * extra length for extended NS offload tuples which follows ARP offload + * tuples. Host needs to fill this structure in following format: + * 2 NS ofload tuples + * 2 ARP offload tuples + * N numbers of extended NS offload tuples if HDD has given more than + * 2 NS offload addresses + */ + if (!bArpOnly && count > WMI_MAX_NS_OFFLOADS) { + num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS; + len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples * + sizeof(WMI_NS_OFFLOAD_TUPLE); + } + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + vos_mem_free(pHostOffloadParams); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (A_UINT8*)wmi_buf_data(buf); + cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param)); + cmd->flags = 0; + cmd->vdev_id = vdev_id; + if (!bArpOnly) + cmd->num_ns_ext_tuples = num_ns_ext_tuples; + + WMA_LOGD("ARP NS Offload vdev_id: %d",cmd->vdev_id); + + /* Have copy of arp info to send along with NS, Since FW expects + * both ARP and NS info in single cmd */ + if(bArpOnly) + vos_mem_copy(&wma->mArpInfo, pHostOffloadParams, sizeof(tSirHostOffloadReq)); + + buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param); + WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC,(WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE))); + buf_ptr += WMI_TLV_HDR_SIZE; + for(i = 0; i < WMI_MAX_NS_OFFLOADS; i++ ){ + ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr; + WMITLV_SET_HDR(&ns_tuple->tlv_header, + WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, + (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE)); + + /* Fill data only for NS offload in the first ARP tuple for LA */ + if (!bArpOnly && + ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; + +#ifdef WLAN_NS_OFFLOAD + /*Copy the target/solicitation/remote ip addr */ + if(pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i]) + A_MEMCPY(&ns_tuple->target_ipaddr[0], + &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i], sizeof(WMI_IPV6_ADDR)); + A_MEMCPY(&ns_tuple->solicitation_ipaddr, + &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR)); + WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i, + &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], + &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]); + + /* target MAC is optional, check if it is valid, if this is not valid, + * the target will use the known local MAC address rather than the tuple */ + WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr, + &ns_tuple->target_mac); +#endif + if ((ns_tuple->target_mac.mac_addr31to0 != 0) || + (ns_tuple->target_mac.mac_addr47to32 != 0)) + { + ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID; + } + } + buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE); + } + + WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC,(WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE))); + buf_ptr += WMI_TLV_HDR_SIZE; + for(i = 0; i < WMI_MAX_ARP_OFFLOADS; i++){ + arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)buf_ptr; + WMITLV_SET_HDR(&arp_tuple->tlv_header, + WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE, + WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE)); + + /* Fill data for ARP and NS in the first tupple for LA */ + if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE) && (i==0)) { + /*Copy the target ip addr and flags*/ + arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID; + A_MEMCPY(&arp_tuple->target_ipaddr,wma->mArpInfo.params.hostIpv4Addr, + SIR_IPV4_ADDR_LEN); + WMA_LOGD("ARPOffload IP4 address: %pI4", + wma->mArpInfo.params.hostIpv4Addr); + } + buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE); + } + + /* Populate extended NS offload tuples */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + (num_ns_ext_tuples*sizeof(WMI_NS_OFFLOAD_TUPLE))); + buf_ptr += WMI_TLV_HDR_SIZE; + + if (num_ns_ext_tuples) { + for(i = WMI_MAX_NS_OFFLOADS; i < count; i++ ){ + ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr; + WMITLV_SET_HDR(&ns_tuple->tlv_header, + WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, + (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE)); + + /* Fill data only for NS offload in the first ARP tuple for LA */ + if (!bArpOnly && + ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; +#ifdef WLAN_NS_OFFLOAD + /*Copy the target/solicitation/remote ip addr */ + if(pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i]) + A_MEMCPY(&ns_tuple->target_ipaddr[0], + &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i], + sizeof(WMI_IPV6_ADDR)); + A_MEMCPY(&ns_tuple->solicitation_ipaddr, + &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], + sizeof(WMI_IPV6_ADDR)); + WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i, + &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], + &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]); + + /* target MAC is optional, check if it is valid, if this is not valid, + * the target will use the known local MAC address rather than the tuple */ + WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr, + &ns_tuple->target_mac); +#endif + if ((ns_tuple->target_mac.mac_addr31to0 != 0) || + (ns_tuple->target_mac.mac_addr47to32 != 0)) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID; + } + } + buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE); + } + } + + res = wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_SET_ARP_NS_OFFLOAD_CMDID); + if(res) { + WMA_LOGE("Failed to enable ARP NDP/NSffload"); + wmi_buf_free(buf); + vos_mem_free(pHostOffloadParams); + return VOS_STATUS_E_FAILURE; + } + + vos_mem_free(pHostOffloadParams); + return VOS_STATUS_SUCCESS; +} + +typedef struct { + int32_t rate; + tANI_U8 flag; +} wma_search_rate_t; + +#define WMA_MAX_OFDM_CCK_RATE_TBL_SIZE 12 +/* In ofdm_cck_rate_tbl->flag, if bit 7 is 1 it's CCK, otherwise it ofdm. + * Lower bit carries the ofdm/cck index for encoding the rate */ +static wma_search_rate_t ofdm_cck_rate_tbl[WMA_MAX_OFDM_CCK_RATE_TBL_SIZE] = { + {540, 4}, /* 4: OFDM 54 Mbps */ + {480, 0}, /* 0: OFDM 48 Mbps */ + {360, 5}, /* 5: OFDM 36 Mbps */ + {240, 1}, /* 1: OFDM 24 Mbps */ + {180, 6}, /* 6: OFDM 18 Mbps */ + {120, 2}, /* 2: OFDM 12 Mbps */ + {110, (1 << 7)}, /* 0: CCK 11 Mbps Long */ + {90, 7}, /* 7: OFDM 9 Mbps */ + {60, 3}, /* 3: OFDM 6 Mbps */ + {55, ((1 << 7)|1)}, /* 1: CCK 5.5 Mbps Long */ + {20, ((1 << 7)|2)}, /* 2: CCK 2 Mbps Long */ + {10, ((1 << 7)|3)} /* 3: CCK 1 Mbps Long */ +}; + +#define WMA_MAX_VHT20_RATE_TBL_SIZE 9 +/* In vht20_400ns_rate_tbl flag carries the mcs index for encoding the rate */ +static wma_search_rate_t vht20_400ns_rate_tbl[WMA_MAX_VHT20_RATE_TBL_SIZE] = { + {867, 8}, /* MCS8 1SS short GI */ + {722, 7}, /* MCS7 1SS short GI */ + {650, 6}, /* MCS6 1SS short GI */ + {578, 5}, /* MCS5 1SS short GI */ + {433, 4}, /* MCS4 1SS short GI */ + {289, 3}, /* MCS3 1SS short GI */ + {217, 2}, /* MCS2 1SS short GI */ + {144, 1}, /* MCS1 1SS short GI */ + {72, 0} /* MCS0 1SS short GI */ +}; +/* In vht20_800ns_rate_tbl flag carries the mcs index for encoding the rate */ +static wma_search_rate_t vht20_800ns_rate_tbl[WMA_MAX_VHT20_RATE_TBL_SIZE] = { + {780, 8}, /* MCS8 1SS long GI */ + {650, 7}, /* MCS7 1SS long GI */ + {585, 6}, /* MCS6 1SS long GI */ + {520, 5}, /* MCS5 1SS long GI */ + {390, 4}, /* MCS4 1SS long GI */ + {260, 3}, /* MCS3 1SS long GI */ + {195, 2}, /* MCS2 1SS long GI */ + {130, 1}, /* MCS1 1SS long GI */ + {65, 0} /* MCS0 1SS long GI */ +}; + +#define WMA_MAX_VHT40_RATE_TBL_SIZE 10 +/* In vht40_400ns_rate_tbl flag carries the mcs index for encoding the rate */ +static wma_search_rate_t vht40_400ns_rate_tbl[WMA_MAX_VHT40_RATE_TBL_SIZE] = { + {2000, 9}, /* MCS9 1SS short GI */ + {1800, 8}, /* MCS8 1SS short GI */ + {1500, 7}, /* MCS7 1SS short GI */ + {1350, 6}, /* MCS6 1SS short GI */ + {1200, 5}, /* MCS5 1SS short GI */ + {900, 4}, /* MCS4 1SS short GI */ + {600, 3}, /* MCS3 1SS short GI */ + {450, 2}, /* MCS2 1SS short GI */ + {300, 1}, /* MCS1 1SS short GI */ + {150, 0}, /* MCS0 1SS short GI */ +}; +static wma_search_rate_t vht40_800ns_rate_tbl[WMA_MAX_VHT40_RATE_TBL_SIZE] = { + {1800, 9}, /* MCS9 1SS long GI */ + {1620, 8}, /* MCS8 1SS long GI */ + {1350, 7}, /* MCS7 1SS long GI */ + {1215, 6}, /* MCS6 1SS long GI */ + {1080, 5}, /* MCS5 1SS long GI */ + {810, 4}, /* MCS4 1SS long GI */ + {540, 3}, /* MCS3 1SS long GI */ + {405, 2}, /* MCS2 1SS long GI */ + {270, 1}, /* MCS1 1SS long GI */ + {135, 0} /* MCS0 1SS long GI */ +}; + +#define WMA_MAX_VHT80_RATE_TBL_SIZE 10 +static wma_search_rate_t vht80_400ns_rate_tbl[WMA_MAX_VHT80_RATE_TBL_SIZE] = { + {4333, 9}, /* MCS9 1SS short GI */ + {3900, 8}, /* MCS8 1SS short GI */ + {3250, 7}, /* MCS7 1SS short GI */ + {2925, 6}, /* MCS6 1SS short GI */ + {2600, 5}, /* MCS5 1SS short GI */ + {1950, 4}, /* MCS4 1SS short GI */ + {1300, 3}, /* MCS3 1SS short GI */ + {975, 2}, /* MCS2 1SS short GI */ + {650, 1}, /* MCS1 1SS short GI */ + {325, 0} /* MCS0 1SS short GI */ +}; +static wma_search_rate_t vht80_800ns_rate_tbl[WMA_MAX_VHT80_RATE_TBL_SIZE] = { + {3900, 9}, /* MCS9 1SS long GI */ + {3510, 8}, /* MCS8 1SS long GI */ + {2925, 7}, /* MCS7 1SS long GI */ + {2633, 6}, /* MCS6 1SS long GI */ + {2340, 5}, /* MCS5 1SS long GI */ + {1755, 4}, /* MCS4 1SS long GI */ + {1170, 3}, /* MCS3 1SS long GI */ + {878, 2}, /* MCS2 1SS long GI */ + {585, 1}, /* MCS1 1SS long GI */ + {293, 0} /* MCS0 1SS long GI */ +}; + +#define WMA_MAX_HT20_RATE_TBL_SIZE 8 +static wma_search_rate_t ht20_400ns_rate_tbl[WMA_MAX_HT20_RATE_TBL_SIZE] = { + {722, 7}, /* MCS7 1SS short GI */ + {650, 6}, /* MCS6 1SS short GI */ + {578, 5}, /* MCS5 1SS short GI */ + {433, 4}, /* MCS4 1SS short GI */ + {289, 3}, /* MCS3 1SS short GI */ + {217, 2}, /* MCS2 1SS short GI */ + {144, 1}, /* MCS1 1SS short GI */ + {72, 0} /* MCS0 1SS short GI */ +}; +static wma_search_rate_t ht20_800ns_rate_tbl[WMA_MAX_HT20_RATE_TBL_SIZE] = { + {650, 7}, /* MCS7 1SS long GI */ + {585, 6}, /* MCS6 1SS long GI */ + {520, 5}, /* MCS5 1SS long GI */ + {390, 4}, /* MCS4 1SS long GI */ + {260, 3}, /* MCS3 1SS long GI */ + {195, 2}, /* MCS2 1SS long GI */ + {130, 1}, /* MCS1 1SS long GI */ + {65, 0} /* MCS0 1SS long GI */ +}; + +#define WMA_MAX_HT40_RATE_TBL_SIZE 8 +static wma_search_rate_t ht40_400ns_rate_tbl[WMA_MAX_HT40_RATE_TBL_SIZE] = { + {1500, 7}, /* MCS7 1SS short GI */ + {1350, 6}, /* MCS6 1SS short GI */ + {1200, 5}, /* MCS5 1SS short GI */ + {900, 4}, /* MCS4 1SS short GI */ + {600, 3}, /* MCS3 1SS short GI */ + {450, 2}, /* MCS2 1SS short GI */ + {300, 1}, /* MCS1 1SS short GI */ + {150, 0} /* MCS0 1SS short GI */ +}; +static wma_search_rate_t ht40_800ns_rate_tbl[WMA_MAX_HT40_RATE_TBL_SIZE] = { + {1350, 7}, /* MCS7 1SS long GI */ + {1215, 6}, /* MCS6 1SS long GI */ + {1080, 5}, /* MCS5 1SS long GI */ + {810, 4}, /* MCS4 1SS long GI */ + {540, 3}, /* MCS3 1SS long GI */ + {405, 2}, /* MCS2 1SS long GI */ + {270, 1}, /* MCS1 1SS long GI */ + {135, 0} /* MCS0 1SS long GI */ +}; + +static void wma_bin_search_rate(wma_search_rate_t *tbl, int32_t tbl_size, + tANI_S32 *mbpsx10_rate, tANI_U8 *ret_flag) +{ + int32_t upper, lower, mid; + + /* the table is descenting. index holds the largest value and the + * bottom index holds the smallest value */ + + upper = 0; /* index 0 */ + lower = tbl_size -1; /* last index */ + + if (*mbpsx10_rate >= tbl[upper].rate) { + /* use the largest rate */ + *mbpsx10_rate = tbl[upper].rate; + *ret_flag = tbl[upper].flag; + return; + } else if (*mbpsx10_rate <= tbl[lower].rate) { + /* use the smallest rate */ + *mbpsx10_rate = tbl[lower].rate; + *ret_flag = tbl[lower].flag; + return; + } + /* now we do binery search to get the floor value */ + while (lower - upper > 1) { + mid = (upper + lower) >> 1; + if (*mbpsx10_rate == tbl[mid].rate) { + /* found the exact match */ + *mbpsx10_rate = tbl[mid].rate; + *ret_flag = tbl[mid].flag; + return; + } else { + /* not found. if mid's rate is larger than input move + * upper to mid. If mid's rate is larger than input + * move lower to mid. */ + if (*mbpsx10_rate > tbl[mid].rate) + lower = mid; + else + upper = mid; + } + } + /* after the bin search the index is the ceiling of rate */ + *mbpsx10_rate = tbl[upper].rate; + *ret_flag = tbl[upper].flag; + return; +} + +static VOS_STATUS wma_fill_ofdm_cck_mcast_rate(tANI_S32 mbpsx10_rate, + tANI_U8 nss, tANI_U8 *rate) +{ + tANI_U8 idx = 0; + wma_bin_search_rate(ofdm_cck_rate_tbl, WMA_MAX_OFDM_CCK_RATE_TBL_SIZE, + &mbpsx10_rate, &idx); + + /* if bit 7 is set it uses CCK */ + if (idx & 0x80) + *rate |= (1 << 6) | (idx & 0xF); /* set bit 6 to 1 for CCK */ + else + *rate |= (idx & 0xF); + return VOS_STATUS_SUCCESS; +} + +static void wma_set_ht_vht_mcast_rate(u_int32_t shortgi, tANI_S32 mbpsx10_rate, + tANI_U8 sgi_idx, tANI_S32 sgi_rate, tANI_U8 lgi_idx, tANI_S32 lgi_rate, + tANI_U8 premable, tANI_U8 *rate, tANI_S32 *streaming_rate) +{ + if (shortgi == 0) { + *rate |= (premable << 6) | (lgi_idx & 0xF); + *streaming_rate = lgi_rate; + } else { + *rate |= (premable << 6) | (sgi_idx & 0xF); + *streaming_rate = sgi_rate; + } +} + +static VOS_STATUS wma_fill_ht20_mcast_rate(u_int32_t shortgi, + tANI_S32 mbpsx10_rate, tANI_U8 nss, tANI_U8 *rate, + tANI_S32 *streaming_rate) +{ + tANI_U8 sgi_idx = 0, lgi_idx = 0; + tANI_S32 sgi_rate, lgi_rate; + if (nss == 1) + mbpsx10_rate= mbpsx10_rate >> 1; + + sgi_rate = mbpsx10_rate; + lgi_rate = mbpsx10_rate; + if (shortgi) + wma_bin_search_rate(ht20_400ns_rate_tbl, + WMA_MAX_HT20_RATE_TBL_SIZE, &sgi_rate, &sgi_idx); + else + wma_bin_search_rate(ht20_800ns_rate_tbl, + WMA_MAX_HT20_RATE_TBL_SIZE, &lgi_rate, &lgi_idx); + + wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate, + lgi_idx, lgi_rate, 2, rate, streaming_rate); + if (nss == 1) + *streaming_rate = *streaming_rate << 1; + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_fill_ht40_mcast_rate(u_int32_t shortgi, + tANI_S32 mbpsx10_rate, tANI_U8 nss, tANI_U8 *rate, + tANI_S32 *streaming_rate) +{ + tANI_U8 sgi_idx = 0, lgi_idx = 0; + tANI_S32 sgi_rate, lgi_rate; + + /* for 2x2 divide the rate by 2 */ + if (nss == 1) + mbpsx10_rate= mbpsx10_rate >> 1; + + sgi_rate = mbpsx10_rate; + lgi_rate = mbpsx10_rate; + if (shortgi) + wma_bin_search_rate(ht40_400ns_rate_tbl, + WMA_MAX_HT40_RATE_TBL_SIZE, &sgi_rate, &sgi_idx); + else + wma_bin_search_rate(ht40_800ns_rate_tbl, + WMA_MAX_HT40_RATE_TBL_SIZE, &lgi_rate, &lgi_idx); + + wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate, + lgi_idx, lgi_rate, 2, rate, streaming_rate); + + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_fill_vht20_mcast_rate(u_int32_t shortgi, + tANI_S32 mbpsx10_rate, tANI_U8 nss, tANI_U8 *rate, + tANI_S32 *streaming_rate) +{ + tANI_U8 sgi_idx = 0, lgi_idx = 0; + tANI_S32 sgi_rate, lgi_rate; + + /* for 2x2 divide the rate by 2 */ + if (nss == 1) + mbpsx10_rate= mbpsx10_rate >> 1; + + sgi_rate = mbpsx10_rate; + lgi_rate = mbpsx10_rate; + if (shortgi) + wma_bin_search_rate(vht20_400ns_rate_tbl, + WMA_MAX_VHT20_RATE_TBL_SIZE, &sgi_rate, &sgi_idx); + else + wma_bin_search_rate(vht20_800ns_rate_tbl, + WMA_MAX_VHT20_RATE_TBL_SIZE, &lgi_rate, &lgi_idx); + + wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate, + lgi_idx, lgi_rate, 3, rate, streaming_rate); + if (nss == 1) + *streaming_rate = *streaming_rate << 1; + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_fill_vht40_mcast_rate(u_int32_t shortgi, + tANI_S32 mbpsx10_rate, tANI_U8 nss, tANI_U8 *rate, + tANI_S32 *streaming_rate) +{ + tANI_U8 sgi_idx = 0, lgi_idx = 0; + tANI_S32 sgi_rate, lgi_rate; + + /* for 2x2 divide the rate by 2 */ + if (nss == 1) + mbpsx10_rate= mbpsx10_rate >> 1; + + sgi_rate = mbpsx10_rate; + lgi_rate = mbpsx10_rate; + if (shortgi) + wma_bin_search_rate(vht40_400ns_rate_tbl, + WMA_MAX_VHT40_RATE_TBL_SIZE, &sgi_rate, &sgi_idx); + else + wma_bin_search_rate(vht40_800ns_rate_tbl, + WMA_MAX_VHT40_RATE_TBL_SIZE, &lgi_rate, &lgi_idx); + + wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, + sgi_idx, sgi_rate, lgi_idx, lgi_rate, + 3, rate, streaming_rate); + if (nss == 1) + *streaming_rate = *streaming_rate << 1; + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_fill_vht80_mcast_rate(u_int32_t shortgi, + tANI_S32 mbpsx10_rate, tANI_U8 nss, tANI_U8 *rate, + tANI_S32 *streaming_rate) +{ + tANI_U8 sgi_idx = 0, lgi_idx = 0; + tANI_S32 sgi_rate, lgi_rate; + + /* for 2x2 divide the rate by 2 */ + if (nss == 1) + mbpsx10_rate= mbpsx10_rate >> 1; + + sgi_rate = mbpsx10_rate; + lgi_rate = mbpsx10_rate; + if (shortgi) + wma_bin_search_rate(vht80_400ns_rate_tbl, + WMA_MAX_VHT80_RATE_TBL_SIZE, &sgi_rate, &sgi_idx); + else + wma_bin_search_rate(vht80_800ns_rate_tbl, + WMA_MAX_VHT80_RATE_TBL_SIZE, &lgi_rate, &lgi_idx); + + wma_set_ht_vht_mcast_rate(shortgi, mbpsx10_rate, sgi_idx, sgi_rate, + lgi_idx, lgi_rate, 3, rate, streaming_rate); + if (nss == 1) + *streaming_rate = *streaming_rate << 1; + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_fill_ht_mcast_rate(u_int32_t shortgi, + u_int32_t chwidth, tANI_S32 mbpsx10_rate, tANI_U8 nss, + WLAN_PHY_MODE chanmode, tANI_U8 *rate, tANI_S32 *streaming_rate) +{ + int32_t ret = 0; + + *streaming_rate = 0; + if (chwidth== 0) + ret = wma_fill_ht20_mcast_rate(shortgi, mbpsx10_rate, + nss, rate, streaming_rate); + else if (chwidth == 1) + ret = wma_fill_ht40_mcast_rate(shortgi, mbpsx10_rate, + nss, rate, streaming_rate); + else + WMA_LOGE("%s: Error, Invalid chwidth enum %d", __func__, chwidth); + return (*streaming_rate != 0) ? VOS_STATUS_SUCCESS : VOS_STATUS_E_INVAL; +} + +static VOS_STATUS wma_fill_vht_mcast_rate(u_int32_t shortgi, + u_int32_t chwidth, tANI_S32 mbpsx10_rate, tANI_U8 nss, + WLAN_PHY_MODE chanmode, tANI_U8 *rate, tANI_S32 *streaming_rate) +{ + int32_t ret = 0; + + *streaming_rate = 0; + if (chwidth== 0) + ret = wma_fill_vht20_mcast_rate(shortgi, mbpsx10_rate, nss, + rate, streaming_rate); + else if (chwidth == 1) + ret = wma_fill_vht40_mcast_rate(shortgi, mbpsx10_rate, nss, + rate, streaming_rate); + else if (chwidth == 2) + ret = wma_fill_vht80_mcast_rate(shortgi, mbpsx10_rate, nss, + rate, streaming_rate); + else + WMA_LOGE("%s: chwidth enum %d not supported", + __func__, chwidth); + return (*streaming_rate != 0) ? VOS_STATUS_SUCCESS : VOS_STATUS_E_INVAL; +} + +#define WMA_MCAST_1X1_CUT_OFF_RATE 2000 +/* + * FUNCTION: wma_encode_mc_rate + * + */ +static VOS_STATUS wma_encode_mc_rate(u_int32_t shortgi, u_int32_t chwidth, + WLAN_PHY_MODE chanmode, A_UINT32 mhz, tANI_S32 mbpsx10_rate, + tANI_U8 nss, tANI_U8 *rate) +{ + int32_t ret = 0; + + /* nss input value: 0 - 1x1; 1 - 2x2; 2 - 3x3 + * the phymode selection is based on following assumption: + * (1) if the app specifically requested 1x1 or 2x2 we hornor it + * (2) if mbpsx10_rate <= 540: always use BG + * (3) 540 < mbpsx10_rate <= 2000: use 1x1 HT/VHT + * (4) 2000 < mbpsx10_rate: use 2x2 HT/VHT + */ + WMA_LOGE("%s: Input: nss = %d, chanmode = %d, " + "mbpsx10 = 0x%x, chwidth = %d, shortgi = %d", + __func__, nss, chanmode, mbpsx10_rate, chwidth, shortgi); + if ((mbpsx10_rate & 0x40000000) && nss > 0) { + /* bit 30 indicates user inputed nss, + * bit 28 and 29 used to encode nss */ + tANI_U8 user_nss = (mbpsx10_rate & 0x30000000) >> 28; + + nss = (user_nss < nss) ? user_nss : nss; + /* zero out bits 19 - 21 to recover the actual rate */ + mbpsx10_rate &= ~0x70000000; + } else if (mbpsx10_rate <= WMA_MCAST_1X1_CUT_OFF_RATE) { + /* if the input rate is less or equal to the + * 1x1 cutoff rate we use 1x1 only */ + nss = 0; + } + /* encode NSS bits (bit 4, bit 5) */ + *rate = (nss & 0x3) << 4; + /* if mcast input rate exceeds the ofdm/cck max rate 54mpbs + * we try to choose best ht/vht mcs rate */ + if (540 < mbpsx10_rate) { + /* cannot use ofdm/cck, choose closest ht/vht mcs rate */ + tANI_U8 rate_ht = *rate; + tANI_U8 rate_vht = *rate; + tANI_S32 stream_rate_ht = 0; + tANI_S32 stream_rate_vht = 0; + tANI_S32 stream_rate = 0; + + ret = wma_fill_ht_mcast_rate(shortgi, chwidth, mbpsx10_rate, + nss, chanmode, &rate_ht, &stream_rate_ht); + if (ret != VOS_STATUS_SUCCESS) { + stream_rate_ht = 0; + } + if (mhz < WMA_2_4_GHZ_MAX_FREQ) { + /* not in 5 GHZ frequency */ + *rate = rate_ht; + stream_rate = stream_rate_ht; + goto ht_vht_done; + } + /* capable doing 11AC mcast so that search vht tables */ + ret = wma_fill_vht_mcast_rate(shortgi, chwidth, mbpsx10_rate, + nss, chanmode, &rate_vht, &stream_rate_vht); + if (ret != VOS_STATUS_SUCCESS) { + if (stream_rate_ht != 0) + ret = VOS_STATUS_SUCCESS; + *rate = rate_ht; + stream_rate = stream_rate_ht; + goto ht_vht_done; + } + if (stream_rate_ht == 0) { + /* only vht rate available */ + *rate = rate_vht; + stream_rate = stream_rate_vht; + } else { + /* set ht as default first */ + *rate = rate_ht; + stream_rate = stream_rate_ht; + if (stream_rate < mbpsx10_rate) { + if (mbpsx10_rate <= stream_rate_vht || + stream_rate < stream_rate_vht) { + *rate = rate_vht; + stream_rate = stream_rate_vht; + } + } else { + if (stream_rate_vht >= mbpsx10_rate && + stream_rate_vht < stream_rate) { + *rate = rate_vht; + stream_rate = stream_rate_vht; + } + } + } +ht_vht_done: + WMA_LOGE("%s: NSS = %d, ucast_chanmode = %d, " + "freq = %d, input_rate = %d, chwidth = %d " + "rate = 0x%x, streaming_rate = %d", + __func__, nss, chanmode, mhz, + mbpsx10_rate, chwidth, *rate, stream_rate); + } else { + if (mbpsx10_rate > 0) + ret = wma_fill_ofdm_cck_mcast_rate(mbpsx10_rate, + nss, rate); + else + *rate = 0xFF; + WMA_LOGE("%s: NSS = %d, ucast_chanmode = %d, " + "input_rate = %d, rate = 0x%x", + __func__, nss, chanmode, mbpsx10_rate, *rate); + } + return ret; +} +/* + * FUNCTION: wma_process_rate_update_indate + * + */ +VOS_STATUS wma_process_rate_update_indicate(tp_wma_handle wma, + tSirRateUpdateInd *pRateUpdateParams) +{ + int32_t ret = 0; + u_int8_t vdev_id = 0; + void *pdev; + tANI_S32 mbpsx10_rate = -1; + tANI_U32 paramId; + tANI_U8 rate = 0; + u_int32_t short_gi; + struct wma_txrx_node *intr = wma->interfaces; + + /* Get the vdev id */ + pdev = wma_find_vdev_by_addr(wma, pRateUpdateParams->bssid, &vdev_id); + if (!pdev) { + WMA_LOGE("vdev handle is invalid for %pM", pRateUpdateParams->bssid); + vos_mem_free(pRateUpdateParams); + return VOS_STATUS_E_INVAL; + } + short_gi = intr[vdev_id].config.shortgi; + if (short_gi == 0) + short_gi = (intr[vdev_id].rate_flags & eHAL_TX_RATE_SGI) ? TRUE : FALSE; + /* first check if reliable TX mcast rate is used. If not check the bcast. + * Then is mcast. Mcast rate is saved in mcastDataRate24GHz */ + if (pRateUpdateParams->reliableMcastDataRateTxFlag > 0) { + mbpsx10_rate = pRateUpdateParams->reliableMcastDataRate; + paramId = WMI_VDEV_PARAM_MCAST_DATA_RATE; + if (pRateUpdateParams->reliableMcastDataRateTxFlag & eHAL_TX_RATE_SGI) + short_gi = 1; /* upper layer specified short GI */ + } else if (pRateUpdateParams->bcastDataRate > -1) { + mbpsx10_rate = pRateUpdateParams->bcastDataRate; + paramId = WMI_VDEV_PARAM_BCAST_DATA_RATE; + } else { + mbpsx10_rate = pRateUpdateParams->mcastDataRate24GHz; + paramId = WMI_VDEV_PARAM_MCAST_DATA_RATE; + if (pRateUpdateParams->mcastDataRate24GHzTxFlag & eHAL_TX_RATE_SGI) + short_gi = 1; /* upper layer specified short GI */ + } + WMA_LOGE("%s: dev_id = %d, dev_type = %d, dev_mode = %d, " + "mac = %pM, config.shortgi = %d, rate_flags = 0x%x", + __func__, vdev_id, intr[vdev_id].type, + pRateUpdateParams->dev_mode, pRateUpdateParams->bssid, + intr[vdev_id].config.shortgi, intr[vdev_id].rate_flags); + ret = wma_encode_mc_rate(short_gi, intr[vdev_id].config.chwidth, + intr[vdev_id].chanmode, intr[vdev_id].mhz, + mbpsx10_rate, pRateUpdateParams->nss, &rate); + if (ret != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Error, Invalid input rate value", __func__); + vos_mem_free(pRateUpdateParams); + return ret; + } + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_SGI, short_gi); + if (ret) { + WMA_LOGE("%s: Failed to Set WMI_VDEV_PARAM_SGI (%d), ret = %d", + __func__, short_gi, ret); + vos_mem_free(pRateUpdateParams); + return VOS_STATUS_E_FAILURE; + } + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + vdev_id, paramId, rate); + vos_mem_free(pRateUpdateParams); + if (ret) { + WMA_LOGE("%s: Failed to Set rate, ret = %d", __func__, ret); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_11AC +static void wma_process_update_membership(tp_wma_handle wma_handle, + tUpdateMembership *membership) +{ + WMA_LOGD("%s: membership = %x ", __func__, + membership->membership); + + wma_set_peer_param(wma_handle, membership->peer_mac, + WMI_PEER_MEMBERSHIP, membership->membership, + membership->smesessionId); +} + +static void wma_process_update_userpos(tp_wma_handle wma_handle, + tUpdateUserPos *userpos) +{ + WMA_LOGD("%s: userPos = %x ", __func__, userpos->userPos); + + wma_set_peer_param(wma_handle, userpos->peer_mac, + WMI_PEER_USERPOS, userpos->userPos, + userpos->smesessionId); + + /* Now that membership/userpos is updated in fw, + * enable GID PPS. + */ + wma_set_ppsconfig(userpos->smesessionId, + WMA_VHT_PPS_GID_MATCH, 1); + +} +#endif + +/* function : wma_process_init_thermal_info + * Description : This function initializes the thermal management table in WMA, + sends down the initial temperature thresholds to the firmware and + configures the throttle period in the tx rx module + * Args : + wma : Pointer to WMA handle + * pThermalParams : Pointer to thermal mitigation parameters + * Returns : + * VOS_STATUS_SUCCESS for success otherwise failure + */ +VOS_STATUS wma_process_init_thermal_info(tp_wma_handle wma, + t_thermal_mgmt *pThermalParams) +{ + t_thermal_cmd_params thermal_params; + ol_txrx_pdev_handle curr_pdev; + + if (NULL == wma || NULL == pThermalParams) { + WMA_LOGE("TM Invalid input"); + return VOS_STATUS_E_FAILURE; + } + + curr_pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == curr_pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("TM enable %d period %d", pThermalParams->thermalMgmtEnabled, + pThermalParams->throttlePeriod); + + wma->thermal_mgmt_info.thermalMgmtEnabled = + pThermalParams->thermalMgmtEnabled; + wma->thermal_mgmt_info.thermalLevels[0].minTempThreshold = + pThermalParams->thermalLevels[0].minTempThreshold; + wma->thermal_mgmt_info.thermalLevels[0].maxTempThreshold = + pThermalParams->thermalLevels[0].maxTempThreshold; + wma->thermal_mgmt_info.thermalLevels[1].minTempThreshold = + pThermalParams->thermalLevels[1].minTempThreshold; + wma->thermal_mgmt_info.thermalLevels[1].maxTempThreshold = + pThermalParams->thermalLevels[1].maxTempThreshold; + wma->thermal_mgmt_info.thermalLevels[2].minTempThreshold = + pThermalParams->thermalLevels[2].minTempThreshold; + wma->thermal_mgmt_info.thermalLevels[2].maxTempThreshold = + pThermalParams->thermalLevels[2].maxTempThreshold; + wma->thermal_mgmt_info.thermalLevels[3].minTempThreshold = + pThermalParams->thermalLevels[3].minTempThreshold; + wma->thermal_mgmt_info.thermalLevels[3].maxTempThreshold = + pThermalParams->thermalLevels[3].maxTempThreshold; + wma->thermal_mgmt_info.thermalCurrLevel = WLAN_WMA_THERMAL_LEVEL_0; + + WMA_LOGD("TM level min max:\n" + "0 %d %d\n" + "1 %d %d\n" + "2 %d %d\n" + "3 %d %d", + wma->thermal_mgmt_info.thermalLevels[0].minTempThreshold, + wma->thermal_mgmt_info.thermalLevels[0].maxTempThreshold, + wma->thermal_mgmt_info.thermalLevels[1].minTempThreshold, + wma->thermal_mgmt_info.thermalLevels[1].maxTempThreshold, + wma->thermal_mgmt_info.thermalLevels[2].minTempThreshold, + wma->thermal_mgmt_info.thermalLevels[2].maxTempThreshold, + wma->thermal_mgmt_info.thermalLevels[3].minTempThreshold, + wma->thermal_mgmt_info.thermalLevels[3].maxTempThreshold); + + if (wma->thermal_mgmt_info.thermalMgmtEnabled) + { + ol_tx_throttle_init_period(curr_pdev, pThermalParams->throttlePeriod); + + /* Get the temperature thresholds to set in firmware */ + thermal_params.minTemp = wma->thermal_mgmt_info. + thermalLevels[WLAN_WMA_THERMAL_LEVEL_0].minTempThreshold; + thermal_params.maxTemp = wma->thermal_mgmt_info. + thermalLevels[WLAN_WMA_THERMAL_LEVEL_0].maxTempThreshold; + thermal_params.thermalEnable = + wma->thermal_mgmt_info.thermalMgmtEnabled; + + WMA_LOGE("TM sending the following to firmware: min %d max %d enable %d", + thermal_params.minTemp, thermal_params.maxTemp, + thermal_params.thermalEnable); + + if(VOS_STATUS_SUCCESS != wma_set_thermal_mgmt(wma, thermal_params)) + { + WMA_LOGE("Could not send thermal mgmt command to the firmware!"); + } + } + return VOS_STATUS_SUCCESS; +} + + +static void wma_set_thermal_level_ind(u_int8_t level) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + vos_msg_t sme_msg = {0}; + + WMA_LOGI(FL("Thermal level: %d"), level); + + sme_msg.type = eWNI_SME_SET_THERMAL_LEVEL_IND; + sme_msg.bodyptr = NULL; + sme_msg.bodyval = level; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + WMA_LOGE(FL("Fail to post set temperaturml level ind msg")); +} + +/** + * wma_process_set_thermal_level() - Sets new thermal throttle level + * wma: Pointer to wma handle + * thermal_level: Thermal level to set + * + * This function sets new thermal throttle level in the txrx module and sends + * down the corresponding temperature thresholds to the firmware. + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure. + * + */ +VOS_STATUS wma_process_set_thermal_level(tp_wma_handle wma, + uint8_t thermal_level) +{ + ol_txrx_pdev_handle curr_pdev; + + + if (NULL == wma) { + WMA_LOGE("TM Invalid input"); + return VOS_STATUS_E_FAILURE; + } + + + curr_pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == curr_pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGE("TM set level %d", thermal_level); + + /* Check if thermal mitigation is enabled */ + if (!wma->thermal_mgmt_info.thermalMgmtEnabled) { + WMA_LOGE("Thermal mgmt is not enabled, ignoring set level cmd"); + return VOS_STATUS_E_FAILURE; + } + + if (thermal_level >= WLAN_WMA_MAX_THERMAL_LEVELS) { + WMA_LOGE("Invalid thermal level set %d", thermal_level); + return VOS_STATUS_E_FAILURE; + } + + if (thermal_level == wma->thermal_mgmt_info.thermalCurrLevel) { + WMA_LOGD("Current level %d is same as the set level, ignoring", + wma->thermal_mgmt_info.thermalCurrLevel); + return VOS_STATUS_SUCCESS; + } + + wma->thermal_mgmt_info.thermalCurrLevel = thermal_level; + + ol_tx_throttle_set_level(curr_pdev, thermal_level); + + /* Send SME SET_THERMAL_LEVEL_IND message */ + wma_set_thermal_level_ind(thermal_level); + + return VOS_STATUS_SUCCESS; +} + +/* function : wma_ProcessTxPowerLimits + * Description : This function sends the power limits for 2g/5g to firmware + * Args : + handle : Pointer to WMA handle + * ptxlim : Pointer to power limit values + * Returns : VOS_STATUS based on values sent to firmware + * + */ +VOS_STATUS wma_ProcessTxPowerLimits(WMA_HANDLE handle, + tSirTxPowerLimit *ptxlim) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + int32_t ret = 0; + u_int32_t txpower_params2g = 0; + u_int32_t txpower_params5g = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue tx power limit", + __func__); + return VOS_STATUS_E_INVAL; + } + /* Set value and reason code for 2g and 5g power limit */ + + SET_PDEV_PARAM_TXPOWER_REASON(txpower_params2g, + WMI_PDEV_PARAM_TXPOWER_REASON_SAR); + SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params2g, + ptxlim->txPower2g); + + SET_PDEV_PARAM_TXPOWER_REASON(txpower_params5g, + WMI_PDEV_PARAM_TXPOWER_REASON_SAR); + SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params5g, + ptxlim->txPower5g); + + WMA_LOGD("%s: txpower2g: %x txpower5g: %x", + __func__, txpower_params2g, txpower_params5g); + + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_TXPOWER_LIMIT2G, txpower_params2g); + if (ret) { + WMA_LOGE("%s: Failed to set txpower 2g (%d)", + __func__, ret); + return VOS_STATUS_E_FAILURE; + } + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_TXPOWER_LIMIT5G, txpower_params5g); + if (ret) { + WMA_LOGE("%s: Failed to set txpower 5g (%d)", + __func__, ret); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + +/** + * wma_set_peer_rate_report_condition - + * this function set peer rate report + * condition info to firmware. + * @handle: Handle of WMA + * @config: Bad peer configuration from SIR module + * + * It is a wrapper function to sent WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID + * to the firmare\target.If the command sent to firmware failed, free the + * buffer that allocated. + * + * Return: VOS_STATUS based on values sent to firmware + */ + +VOS_STATUS wma_set_peer_rate_report_condition(WMA_HANDLE handle, + struct t_bad_peer_txtcl_config *config) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + wmi_peer_set_rate_report_condition_fixed_param *cmd = NULL; + wmi_buf_t buf = NULL; + int status = 0; + u_int32_t len = 0; + u_int32_t i, j; + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to alloc buf to peer_set_condition cmd\n"); + return eHAL_STATUS_FAILURE; + } + + cmd = (wmi_peer_set_rate_report_condition_fixed_param *) + wmi_buf_data (buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_set_rate_report_condition_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_peer_set_rate_report_condition_fixed_param)); + + cmd->enable_rate_report = config->enable; + cmd->report_backoff_time = config->tgt_backoff; + cmd->report_timer_period = config->tgt_report_prd; + for (i = 0; i < PEER_RATE_REPORT_COND_MAX_NUM; i++) { + cmd->cond_per_phy[i].val_cond_flags = + config->threshold[i].cond; + cmd->cond_per_phy[i].rate_delta.min_delta = + config->threshold[i].delta; + cmd->cond_per_phy[i].rate_delta.percentage = + config->threshold[i].percentage; + for (j = 0; j < MAX_NUM_OF_RATE_THRESH; j++) { + cmd->cond_per_phy[i].rate_threshold[j] = + config->threshold[i].thresh[j]; + } + } + WMA_LOGE("%s enable %d backoff_time %d period %d\n", __func__, + cmd->enable_rate_report, + cmd->report_backoff_time, cmd->report_timer_period); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID); + if (status) { + adf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send peer_set_report_cond command", + __func__); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + +/** + * wma_process_init_bad_peer_tx_ctl_info - + * this function to initialize peer rate report config info. + * @handle: Handle of WMA + * @config: Bad peer configuration from SIR module + * + * This function initializes the bad peer tx control data structure in WMA, + * sends down the initial configuration to the firmware and configures + * the peer status update seeting in the tx_rx module. + * + * Return: VOS_STATUS based on procedure status + */ + +static VOS_STATUS wma_process_init_bad_peer_tx_ctl_info(tp_wma_handle wma, + struct t_bad_peer_txtcl_config *config) +{ + /* Parameter sanity check */ + ol_txrx_pdev_handle curr_pdev; + + if (NULL == wma || NULL == config) { + WMA_LOGE("%s Invalid input\n", __func__); + return VOS_STATUS_E_FAILURE; + } + + curr_pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == curr_pdev) { + WMA_LOGE("%s: Failed to get pdev\n", __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGE("%s enable %d period %d txq limit %d\n", __func__, + config->enable, + config->period, + config->txq_limit); + + /* Only need to initialize the setting + when the feature is enabled */ + if (config->enable) { + int i = 0; + + ol_txrx_bad_peer_txctl_set_setting(curr_pdev, + config->enable, + config->period, + config->txq_limit); + + for (i = 0; i < WLAN_WMA_IEEE80211_MAX_LEVEL; i++) { + u_int32_t threshold, limit; + threshold = + config->threshold[i].thresh[0]; + limit = config->threshold[i].txlimit; + ol_txrx_bad_peer_txctl_update_threshold(curr_pdev, i, + threshold, limit); + } + } + + return wma_set_peer_rate_report_condition(wma, config); +} +#else +static inline +VOS_STATUS wma_process_init_bad_peer_tx_ctl_info(tp_wma_handle wma, + struct t_bad_peer_txtcl_config *config) +{ + return eHAL_STATUS_SUCCESS; +} +#endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */ + +/* + * FUNCTION: wma_ProcessAddPeriodicTxPtrnInd + * WMI command sent to firmware to add patterns + * for the corresponding vdev id + */ +VOS_STATUS wma_ProcessAddPeriodicTxPtrnInd(WMA_HANDLE handle, + tSirAddPeriodicTxPtrn *pAddPeriodicTxPtrnParams) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param* cmd; + wmi_buf_t wmi_buf; + uint32_t len; + uint8_t vdev_id; + u_int8_t *buf_ptr; + u_int32_t ptrn_len, ptrn_len_aligned; + int j; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + ptrn_len = pAddPeriodicTxPtrnParams->ucPtrnSize; + ptrn_len_aligned = roundup(ptrn_len, sizeof(uint32_t)); + len = sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param) + + WMI_TLV_HDR_SIZE + ptrn_len_aligned; + + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + if (!wma_find_vdev_by_addr(wma_handle, + pAddPeriodicTxPtrnParams->macAddress, &vdev_id)) { + WMA_LOGE("%s: Failed to find vdev id for %pM",__func__, + pAddPeriodicTxPtrnParams->macAddress); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_INVAL; + } + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param)); + + /* Pass the pattern id to delete for the corresponding vdev id */ + cmd->vdev_id = vdev_id; + cmd->pattern_id = pAddPeriodicTxPtrnParams->ucPtrnId; + cmd->timeout = pAddPeriodicTxPtrnParams->usPtrnIntervalMs; + cmd->length = pAddPeriodicTxPtrnParams->ucPtrnSize; + + /* Pattern info */ + buf_ptr += sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ptrn_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, pAddPeriodicTxPtrnParams->ucPattern, + ptrn_len); + for (j = 0; j < pAddPeriodicTxPtrnParams->ucPtrnSize; j++) { + WMA_LOGD("%s: Add Ptrn: %02x", __func__, buf_ptr[j] & 0xff); + } + WMA_LOGD("%s: Add ptrn id: %d vdev_id: %d", + __func__, cmd->pattern_id, cmd->vdev_id); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID)) { + WMA_LOGE("%s: failed to add pattern set state command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/* + * FUNCTION: wma_ProcessDelPeriodicTxPtrnInd + * WMI command sent to firmware to del patterns + * for the corresponding vdev id + */ +VOS_STATUS wma_ProcessDelPeriodicTxPtrnInd(WMA_HANDLE handle, + tSirDelPeriodicTxPtrn *pDelPeriodicTxPtrnParams) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param* cmd; + wmi_buf_t wmi_buf; + uint8_t vdev_id; + u_int32_t len = sizeof(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param); + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + if (!wma_find_vdev_by_addr(wma_handle, + pDelPeriodicTxPtrnParams->macAddress, &vdev_id)) { + WMA_LOGE("%s: Failed to find vdev id for %pM",__func__, + pDelPeriodicTxPtrnParams->macAddress); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_INVAL; + } + cmd = (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)wmi_buf_data(wmi_buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param)); + + /* Pass the pattern id to delete for the corresponding vdev id */ + cmd->vdev_id = vdev_id; + cmd->pattern_id = pDelPeriodicTxPtrnParams->ucPtrnId; + WMA_LOGD("%s: Del ptrn id: %d vdev_id: %d", + __func__, cmd->pattern_id, cmd->vdev_id); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID)) { + WMA_LOGE("%s: failed to send del pattern command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +static void wma_set_p2pgo_noa_Req(tp_wma_handle wma, + tP2pPsParams *noa) +{ + wmi_p2p_set_noa_cmd_fixed_param *cmd; + wmi_p2p_noa_descriptor *noa_discriptor; + wmi_buf_t buf; + u_int8_t *buf_ptr; + u_int16_t len; + int32_t status; + u_int32_t duration; + + WMA_LOGD("%s: Enter", __func__); + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + sizeof(*noa_discriptor); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate memory"); + goto end; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_p2p_set_noa_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_p2p_set_noa_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_p2p_set_noa_cmd_fixed_param)); + duration = (noa->count == 1)? noa->single_noa_duration : noa->duration; + cmd->vdev_id = noa->sessionId; + cmd->enable = (duration)? true : false; + cmd->num_noa = 1; + + WMITLV_SET_HDR((buf_ptr + sizeof(wmi_p2p_set_noa_cmd_fixed_param)), + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_p2p_noa_descriptor)); + noa_discriptor = (wmi_p2p_noa_descriptor *) (buf_ptr + + sizeof(wmi_p2p_set_noa_cmd_fixed_param) + + WMI_TLV_HDR_SIZE); + WMITLV_SET_HDR(&noa_discriptor->tlv_header, + WMITLV_TAG_STRUC_wmi_p2p_noa_descriptor, + WMITLV_GET_STRUCT_TLVLEN(wmi_p2p_noa_descriptor)); + noa_discriptor->type_count = noa->count; + noa_discriptor->duration = duration; + noa_discriptor->interval = noa->interval; + noa_discriptor->start_time = 0; + + WMA_LOGI("SET P2P GO NOA:vdev_id:%d count:%d duration:%d interval:%d", + cmd->vdev_id, noa->count, noa_discriptor->duration, + noa->interval); + status = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID); + if (status != EOK) { + WMA_LOGE("Failed to send WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID"); + wmi_buf_free(buf); + } + +end: + WMA_LOGD("%s: Exit", __func__); +} + +static void wma_set_p2pgo_oppps_req(tp_wma_handle wma, + tP2pPsParams *oppps) +{ + wmi_p2p_set_oppps_cmd_fixed_param *cmd; + wmi_buf_t buf; + int32_t status; + + WMA_LOGD("%s: Enter", __func__); + buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate memory"); + goto end; + } + + cmd = (wmi_p2p_set_oppps_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_p2p_set_oppps_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_p2p_set_oppps_cmd_fixed_param)); + cmd->vdev_id = oppps->sessionId; + if (oppps->ctWindow) + WMI_UNIFIED_OPPPS_ATTR_ENABLED_SET(cmd); + + WMI_UNIFIED_OPPPS_ATTR_CTWIN_SET(cmd, oppps->ctWindow); + WMA_LOGI("SET P2P GO OPPPS:vdev_id:%d ctwindow:%d", + cmd->vdev_id, oppps->ctWindow); + status = wmi_unified_cmd_send(wma->wmi_handle, buf, sizeof(*cmd), + WMI_P2P_SET_OPPPS_PARAM_CMDID); + if (status != EOK) { + WMA_LOGE("Failed to send WMI_P2P_SET_OPPPS_PARAM_CMDID"); + wmi_buf_free(buf); + } + +end: + WMA_LOGD("%s: Exit", __func__); +} + +static void wma_process_set_p2pgo_noa_Req(tp_wma_handle wma, + tP2pPsParams *ps_params) +{ + WMA_LOGD("%s: Enter", __func__); + if (ps_params->opp_ps) { + wma_set_p2pgo_oppps_req(wma, ps_params); + } else { + wma_set_p2pgo_noa_Req(wma, ps_params); + } + + WMA_LOGD("%s: Exit", __func__); +} + +/* function : wma_process_set_mimops_req + * Description : Set the received MiMo PS state to firmware. + * Args : + wma_handle : Pointer to WMA handle + * tSetMIMOPS : Pointer to MiMo PS struct + * Returns : + */ +static void wma_process_set_mimops_req(tp_wma_handle wma_handle, + tSetMIMOPS *mimops) +{ + /* Translate to what firmware understands */ + if ( mimops->htMIMOPSState == eSIR_HT_MIMO_PS_DYNAMIC) + mimops->htMIMOPSState = WMI_PEER_MIMO_PS_DYNAMIC; + else if ( mimops->htMIMOPSState == eSIR_HT_MIMO_PS_STATIC) + mimops->htMIMOPSState = WMI_PEER_MIMO_PS_STATIC; + else if ( mimops->htMIMOPSState == eSIR_HT_MIMO_PS_NO_LIMIT) + mimops->htMIMOPSState = WMI_PEER_MIMO_PS_NONE; + + WMA_LOGD("%s: htMIMOPSState = %d, sessionId = %d peerMac <%02x:%02x:%02x:%02x:%02x:%02x>", + __func__, + mimops->htMIMOPSState, mimops->sessionId, mimops->peerMac[0], + mimops->peerMac[1], mimops->peerMac[2], mimops->peerMac[3], + mimops->peerMac[4], mimops->peerMac[5]); + + wma_set_peer_param(wma_handle, mimops->peerMac, + WMI_PEER_MIMO_PS_STATE, mimops->htMIMOPSState, + mimops->sessionId); +} + +/* function : wma_set_vdev_intrabss_fwd + * Description : Set intra_fwd value to wni_in. + * Args : + * wma_handle : Pointer to WMA handle + * pdis_intra_fwd : Pointer to DisableIntraBssFwd struct + * Returns : + */ +static void wma_set_vdev_intrabss_fwd(tp_wma_handle wma_handle, + tpDisableIntraBssFwd pdis_intra_fwd) +{ + ol_txrx_vdev_handle txrx_vdev; + WMA_LOGD("%s:intra_fwd:vdev(%d) intrabss_dis=%s", + __func__, pdis_intra_fwd->sessionId, + (pdis_intra_fwd->disableintrabssfwd ? "true" : "false")); + + txrx_vdev = wma_handle->interfaces[pdis_intra_fwd->sessionId].handle; + wdi_in_vdev_rx_fwd_disabled(txrx_vdev, pdis_intra_fwd->disableintrabssfwd); +} + +VOS_STATUS wma_notify_modem_power_state(void *wda_handle, + tSirModemPowerStateInd *pReq) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle)wda_handle; + + WMA_LOGD("%s: WMA Notify Modem Power State %d", __func__, pReq->param); + + ret = wmi_unified_modem_power_state(wma->wmi_handle, pReq->param); + if (ret) { + WMA_LOGE("%s: Fail to notify Modem Power State %d", + __func__, pReq->param); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Successfully notify Modem Power State %d", pReq->param); + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_TSF +/** + * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin + * + * @handle: wma handler + * @pin: GPIO pin id + * + * Return: VOS_STATUS + */ +static VOS_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, + uint32_t pin) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + int32_t ret; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not set gpio", + __func__); + return VOS_STATUS_E_INVAL; + } + + WMA_LOGD("%s: set tsf gpio pin: %d", + __func__, pin); + + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_WNTS_CONFIG, pin); + if (ret) { + WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", + __func__, ret); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} +#else +static inline VOS_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, + uint32_t pin) +{ + return VOS_STATUS_E_INVAL; +} +#endif + +#ifdef WLAN_FEATURE_STATS_EXT +VOS_STATUS wma_stats_ext_req(void *wda_handle, + tpStatsExtRequest preq) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle)wda_handle; + wmi_req_stats_ext_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len; + u_int8_t *buf_ptr; + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + + preq->request_data_len; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_req_stats_ext_cmd_fixed_param *)buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_req_stats_ext_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_req_stats_ext_cmd_fixed_param)); + cmd->vdev_id = preq->vdev_id; + cmd->data_len = preq->request_data_len; + + WMA_LOGD("%s: The data len value is %u and vdev id set is %u ", + __func__, preq->request_data_len, preq->vdev_id); + + buf_ptr += sizeof(wmi_req_stats_ext_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, cmd->data_len); + + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, preq->request_data, + cmd->data_len); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_REQUEST_STATS_EXT_CMDID); + if (ret != EOK) { + WMA_LOGE("%s: Failed to send notify cmd ret = %d", __func__, ret); + wmi_buf_free(buf); + } + + return ret; +} + +#endif + +void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle, + tHalHiddenSsidVdevRestart *pReq) +{ + struct wma_txrx_node *intr = wma_handle->interfaces; + + if ((pReq->sessionId != intr[pReq->sessionId].vdev_restart_params.vdev_id) || + !((intr[pReq->sessionId].type == WMI_VDEV_TYPE_AP) && + (intr[pReq->sessionId].sub_type == 0))) + { + WMA_LOGE("%s : invalid session id", __func__); + return; + } + + intr[pReq->sessionId].vdev_restart_params.ssidHidden = pReq->ssidHidden; + adf_os_atomic_set(&intr[pReq->sessionId].vdev_restart_params.hidden_ssid_restart_in_progress,1); + + /* vdev stop -> vdev restart -> vdev up */ + WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP", + __func__, pReq->sessionId); + wdi_in_vdev_pause(wma_handle->interfaces[pReq->sessionId].handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + wma_handle->interfaces[pReq->sessionId].pause_bitmap |= + (1 << PAUSE_TYPE_HOST); + if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) { + WMA_LOGE("%s: %d Failed to send vdev stop", + __func__, __LINE__); + adf_os_atomic_set(&intr[pReq->sessionId].vdev_restart_params.hidden_ssid_restart_in_progress,0); + return; + } +} + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +static VOS_STATUS wma_process_ll_stats_clearReq +( + tp_wma_handle wma, + const tpSirLLStatsClearReq clearReq +) +{ + wmi_clear_link_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int ret; + + if (!clearReq || !wma) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + cmd = (wmi_clear_link_stats_cmd_fixed_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_clear_link_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_clear_link_stats_cmd_fixed_param)); + + cmd->stop_stats_collection_req = clearReq->stopReq; + cmd->vdev_id = clearReq->staId; + cmd->stats_clear_req_mask = clearReq->statsClearReqMask; + + WMI_CHAR_ARRAY_TO_MAC_ADDR(wma->interfaces[clearReq->staId].addr, + &cmd->peer_macaddr); + + WMA_LOGD("LINK_LAYER_STATS - Clear Request Params"); + WMA_LOGD("StopReq : %d", cmd->stop_stats_collection_req); + WMA_LOGD("Vdev Id : %d", cmd->vdev_id); + WMA_LOGD("Clear Stat Mask : %d", cmd->stats_clear_req_mask); + WMA_LOGD("Peer MAC Addr : %pM", wma->interfaces[clearReq->staId].addr); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_CLEAR_LINK_STATS_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send clear link stats req", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Clear Link Layer Stats request sent successfully"); + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_process_ll_stats_setReq +( + tp_wma_handle wma, + const tpSirLLStatsSetReq setReq +) +{ + wmi_start_link_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int ret; + + if (!setReq || !wma) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + cmd = (wmi_start_link_stats_cmd_fixed_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_start_link_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_start_link_stats_cmd_fixed_param)); + + cmd->mpdu_size_threshold = setReq->mpduSizeThreshold; + cmd->aggressive_statistics_gathering = setReq->aggressiveStatisticsGathering; + + WMA_LOGD("LINK_LAYER_STATS - Start/Set Request Params"); + WMA_LOGD("MPDU Size Thresh : %d", cmd->mpdu_size_threshold); + WMA_LOGD("Aggressive Gather: %d", cmd->aggressive_statistics_gathering); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_START_LINK_STATS_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send set link stats request", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Set Link Layer Stats request sent successfully"); + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS wma_process_ll_stats_getReq +( + tp_wma_handle wma, + const tpSirLLStatsGetReq getReq +) +{ + wmi_request_link_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int ret; + + if (!getReq || !wma) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + cmd = (wmi_request_link_stats_cmd_fixed_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_request_link_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_request_link_stats_cmd_fixed_param)); + + cmd->request_id = getReq->reqId; + cmd->stats_type = getReq->paramIdMask; + cmd->vdev_id = getReq->staId; + + WMI_CHAR_ARRAY_TO_MAC_ADDR(wma->interfaces[getReq->staId].addr, + &cmd->peer_macaddr); + + WMA_LOGD("LINK_LAYER_STATS - Get Request Params"); + WMA_LOGD("Request ID : %d", cmd->request_id); + WMA_LOGD("Stats Type : %d", cmd->stats_type); + WMA_LOGD("Vdev ID : %d", cmd->vdev_id); + WMA_LOGD("Peer MAC Addr : %pM", wma->interfaces[getReq->staId].addr); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_REQUEST_LINK_STATS_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send get link stats request", __func__); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Get Link Layer Stats request sent successfully"); + return VOS_STATUS_SUCCESS; +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef FEATURE_WLAN_EXTSCAN + VOS_STATUS wma_get_buf_extscan_start_cmd(tp_wma_handle wma_handle, + tSirWifiScanCmdReqParams *pstart, + wmi_buf_t *buf, + int *buf_len) +{ + wmi_extscan_start_cmd_fixed_param *cmd; + wmi_extscan_bucket *dest_blist; + wmi_extscan_bucket_channel *dest_clist; + tSirWifiScanBucketSpec *src_bucket = pstart->buckets; + tSirWifiScanChannelSpec *src_channel = src_bucket->channels; + tSirWifiScanChannelSpec save_channel[WLAN_EXTSCAN_MAX_CHANNELS]; + + u_int8_t *buf_ptr; + int i, k, count = 0; + int len = sizeof(*cmd); + int nbuckets = pstart->numBuckets; + int nchannels = 0; + + /* These TLV's are are NULL by default */ + u_int32_t ie_len_with_pad = 0; + int num_ssid = 0; + int num_bssid = 0; + int ie_len = 0; + + uint32_t base_period = pstart->basePeriod; + + /* TLV placeholder for ssid_list (NULL) */ + len += WMI_TLV_HDR_SIZE; + len += num_ssid * sizeof(wmi_ssid); + + /* TLV placeholder for bssid_list (NULL) */ + len += WMI_TLV_HDR_SIZE; + len += num_bssid * sizeof(wmi_mac_addr); + + /* TLV placeholder for ie_data (NULL) */ + len += WMI_TLV_HDR_SIZE; + len += ie_len * sizeof(u_int32_t); + + /* TLV placeholder for bucket */ + len += WMI_TLV_HDR_SIZE; + len += nbuckets * sizeof(wmi_extscan_bucket); + + /* TLV channel placeholder */ + len += WMI_TLV_HDR_SIZE; + for (i = 0; i < nbuckets; i++) { + nchannels += src_bucket->numChannels; + src_bucket++; + } + WMA_LOGD("%s: Total buckets: %d total #of channels is %d", + __func__, nbuckets, nchannels); + len += nchannels * sizeof(wmi_extscan_bucket_channel); + /* Allocate the memory */ + *buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!*buf) { + WMA_LOGP("%s: failed to allocate memory" + " for start extscan cmd", + __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *)wmi_buf_data(*buf); + cmd = (wmi_extscan_start_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_start_cmd_fixed_param)); + + cmd->request_id = pstart->requestId; + cmd->vdev_id = pstart->sessionId; + cmd->base_period = pstart->basePeriod; + cmd->num_buckets = nbuckets; + cmd->configuration_flags = 0; + + if (pstart->configuration_flags & EXTSCAN_LP_EXTENDED_BATCHING) + cmd->configuration_flags |= WMI_EXTSCAN_EXTENDED_BATCHING_EN; + WMA_LOGI("%s: configuration_flags: 0x%x", __func__, + cmd->configuration_flags); + + cmd->min_rest_time = WMA_EXTSCAN_REST_TIME; + cmd->max_rest_time = WMA_EXTSCAN_REST_TIME; + cmd->max_bssids_per_scan_cycle = pstart->maxAPperScan; + + /* The max dwell time is retrieved from the first channel + * of the first bucket and kept common for all channels. + */ + cmd->min_dwell_time_active = pstart->min_dwell_time_active; + cmd->max_dwell_time_active = pstart->max_dwell_time_active; + cmd->min_dwell_time_passive = pstart->min_dwell_time_passive; + cmd->max_dwell_time_passive = pstart->max_dwell_time_passive; + cmd->max_bssids_per_scan_cycle = pstart->maxAPperScan; + cmd->max_table_usage = pstart->report_threshold_percent; + cmd->report_threshold_num_scans = pstart->report_threshold_num_scans; + + cmd->repeat_probe_time = cmd->max_dwell_time_active / + WMA_SCAN_NPROBES_DEFAULT; + cmd->max_scan_time = WMA_EXTSCAN_MAX_SCAN_TIME; + cmd->probe_delay = 0; + cmd->probe_spacing_time = 0; + cmd->idle_time = 0; + cmd->burst_duration = WMA_EXTSCAN_BURST_DURATION; + cmd->scan_ctrl_flags = WMI_SCAN_ADD_BCAST_PROBE_REQ | + WMI_SCAN_ADD_CCK_RATES | + WMI_SCAN_ADD_OFDM_RATES | + WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ | + WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ; + cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH; + cmd->num_ssids = 0; + cmd->num_bssid = 0; + cmd->ie_len = 0; + cmd->n_probes = (cmd->repeat_probe_time > 0) ? + cmd->max_dwell_time_active / cmd->repeat_probe_time : 0; + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_FIXED_STRUC, + num_ssid * sizeof(wmi_ssid)); + buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid * sizeof(wmi_ssid)); + + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_FIXED_STRUC, + num_bssid * sizeof(wmi_mac_addr)); + buf_ptr += WMI_TLV_HDR_SIZE + (num_bssid * sizeof(wmi_mac_addr)); + + ie_len_with_pad = 0; + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_BYTE, + ie_len_with_pad); + buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad; + + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + nbuckets * sizeof(wmi_extscan_bucket)); + dest_blist = (wmi_extscan_bucket *) + (buf_ptr + WMI_TLV_HDR_SIZE); + src_bucket = pstart->buckets; + + /* Retrieve scanning information from each bucket and + * channels and send it to the target + */ + for (i = 0; i < nbuckets; i++) { + WMITLV_SET_HDR(dest_blist, + WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_extscan_bucket)); + + dest_blist->bucket_id = src_bucket->bucket; + dest_blist->base_period_multiplier = + src_bucket->period / base_period; + dest_blist->min_period = src_bucket->period; + dest_blist->max_period = src_bucket->max_period; + dest_blist->exp_backoff = src_bucket->exponent; + dest_blist->exp_max_step_count = src_bucket->step_count; + dest_blist->channel_band = src_bucket->band; + dest_blist->num_channels = src_bucket->numChannels; + dest_blist->notify_extscan_events = 0; + + if (src_bucket->reportEvents & EXTSCAN_REPORT_EVENTS_EACH_SCAN) + dest_blist->notify_extscan_events = + WMI_EXTSCAN_BUCKET_COMPLETED_EVENT; + + if (src_bucket->reportEvents & + EXTSCAN_REPORT_EVENTS_FULL_RESULTS) { + dest_blist->forwarding_flags = + WMI_EXTSCAN_FORWARD_FRAME_TO_HOST; + dest_blist->notify_extscan_events |= + WMI_EXTSCAN_BUCKET_COMPLETED_EVENT | + WMI_EXTSCAN_CYCLE_STARTED_EVENT | + WMI_EXTSCAN_CYCLE_COMPLETED_EVENT; + } else { + dest_blist->forwarding_flags = + WMI_EXTSCAN_NO_FORWARDING; + } + + if (src_bucket->reportEvents & EXTSCAN_REPORT_EVENTS_NO_BATCH) + dest_blist->configuration_flags = 0; + else + dest_blist->configuration_flags = + WMI_EXTSCAN_BUCKET_CACHE_RESULTS; + + WMA_LOGI("%s: ntfy_extscan_events:%u cfg_flags:%u fwd_flags:%u", + __func__, dest_blist->notify_extscan_events, + dest_blist->configuration_flags, + dest_blist->forwarding_flags); + + dest_blist->min_dwell_time_active = src_bucket->min_dwell_time_active; + dest_blist->max_dwell_time_active = src_bucket->max_dwell_time_active; + dest_blist->min_dwell_time_passive = src_bucket->min_dwell_time_passive; + dest_blist->max_dwell_time_passive = src_bucket->max_dwell_time_passive; + src_channel = src_bucket->channels; + + /* save the channel info to later populate + * the channel TLV + */ + for (k = 0; k < src_bucket->numChannels; k++) { + save_channel[count++].channel = + src_channel->channel; + src_channel++; + } + dest_blist++; + src_bucket++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (nbuckets * sizeof(wmi_extscan_bucket)); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + nchannels * sizeof(wmi_extscan_bucket_channel)); + dest_clist = (wmi_extscan_bucket_channel *) + (buf_ptr + WMI_TLV_HDR_SIZE); + + /* Active or passive scan is based on the bucket dwell time + * and channel specific active,passive scans are not + * supported yet + */ + for (i = 0; i < nchannels; i++) { + WMITLV_SET_HDR(dest_clist, + WMITLV_TAG_STRUC_wmi_extscan_bucket_channel_event_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_bucket_channel)); + dest_clist->channel = save_channel[i].channel; + dest_clist++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (nchannels * sizeof(wmi_extscan_bucket_channel)); + *buf_len = len; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_start_extscan(tp_wma_handle wma, + tSirWifiScanCmdReqParams *pstart) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf; + int len; + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed,can not issue extscan cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan feature bit not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + /* Fill individual elements of extscan request and + * TLV for buckets, channel list. + */ + vos_status = wma_get_buf_extscan_start_cmd(wma, pstart, + &buf, &len); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to get buffer for ext scan cmd", + __func__); + return VOS_STATUS_E_FAILURE; + } + if (!buf) { + WMA_LOGE("%s:Failed to get buffer" + "for current extscan info", __func__); + return VOS_STATUS_E_FAILURE; + } + if (wmi_unified_cmd_send(wma->wmi_handle, buf, + len, WMI_EXTSCAN_START_CMDID)) { + WMA_LOGE("%s: failed to send command", __func__); + adf_nbuf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Extscan start request sent successfully for vdev %d", + pstart->sessionId); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_stop_extscan(tp_wma_handle wma, + tSirExtScanStopReqParams *pstopcmd) +{ + wmi_extscan_stop_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, cannot issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + cmd = (wmi_extscan_stop_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_stop_cmd_fixed_param)); + + cmd->request_id = pstopcmd->requestId; + cmd->vdev_id = pstopcmd->sessionId; + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_EXTSCAN_STOP_CMDID)) { + WMA_LOGE("%s: failed to command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Extscan stop request sent successfully for vdev %d", + pstopcmd->sessionId); + + return VOS_STATUS_SUCCESS; +} + +/** wma_get_hotlist_entries_per_page() - hotlist entries per page + * @cmd: size of command structure. + * @per_entry_size: per entry size. + * + * This utility function calculates how many hotlist entries can + * fit in one page. + * + * Return: number of entries + */ +static inline int wma_get_hotlist_entries_per_page(wmi_unified_t wmi_handle, + size_t cmd_size, + size_t per_entry_size) +{ + uint32_t avail_space = 0; + int num_entries = 0; + uint16_t max_msg_len = wmi_get_max_msg_len(wmi_handle); + + /* Calculate number of hotlist entries that can + * be passed in wma message request. + */ + avail_space = max_msg_len - cmd_size; + num_entries = avail_space / per_entry_size; + return num_entries; +} + +/** wma_get_buf_extscan_hotlist_cmd() - extscan hotlist command + * @wma_handle: pointer to WMA handle + * @photlist: pointer to input hotlist request message + * @buf_len: buffer len + * + * This function constructs the WMA set bssid hotlist command message + * and based on the maximum length of the WMA command buf, it issues + * multiple request. + * + * Return: VOS_STATUS enumeration. + */ +VOS_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle, + tSirExtScanSetBssidHotListReqParams *photlist, + int *buf_len) +{ + wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd; + wmi_extscan_hotlist_entry *dest_hotlist; + tSirAPThresholdParam *src_ap = photlist->ap; + wmi_buf_t buf; + u_int8_t *buf_ptr; + + int j, index = 0; + int cmd_len = 0; + int num_entries = 0; + int min_entries = 0; + int numap = photlist->numAp; + int len = sizeof(*cmd); + + len += WMI_TLV_HDR_SIZE; + cmd_len = len; + + /* setbssid hotlist expects the bssid list + * to be non zero value + */ + if (!numap) { + WMA_LOGE("%s: Invalid number of bssid's", __func__); + return VOS_STATUS_E_INVAL; + } + num_entries = wma_get_hotlist_entries_per_page(wma_handle->wmi_handle, + cmd_len, + sizeof(*dest_hotlist)); + + /* Split the hot list entry pages and send multiple command + * requests if the buffer reaches the maximum request size + */ + while (index < numap) { + min_entries = VOS_MIN(num_entries, numap); + len += min_entries * sizeof(wmi_extscan_hotlist_entry); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *)wmi_buf_data(buf); + cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *) + buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_configure_hotlist_monitor_cmd_fixed_param)); + + /* Multiple requests are sent until the num_entries_in_page + * matches the total_entries + */ + cmd->request_id = photlist->requestId; + cmd->vdev_id = photlist->sessionId; + cmd->total_entries = numap; + cmd->mode = 1; + cmd->num_entries_in_page = min_entries; + cmd->lost_ap_scan_count = photlist->lost_ap_sample_size; + cmd->first_entry_index = index; + + WMA_LOGD("%s: vdev id:%d total_entries: %d num_entries: %d lost_ap_sample_size: %d", + __func__, cmd->vdev_id, cmd->total_entries, + cmd->num_entries_in_page, + cmd->lost_ap_scan_count); + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + min_entries * sizeof(wmi_extscan_hotlist_entry)); + dest_hotlist = (wmi_extscan_hotlist_entry *) + (buf_ptr + WMI_TLV_HDR_SIZE); + + /* Populate bssid, channel info and rssi + * for the bssid's that are sent as hotlists. + */ + for (j = 0; j < min_entries; j++) { + WMITLV_SET_HDR(dest_hotlist, + WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_hotlist_entry)); + + dest_hotlist->min_rssi = src_ap->low; + WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid, + &dest_hotlist->bssid); + + WMA_LOGD("%s: min_rssi %d", __func__, + dest_hotlist->min_rssi); + WMA_LOGD("%s: bssid mac_addr31to0: 0x%x, mac_addr47to32: 0x%x", + __func__, dest_hotlist->bssid.mac_addr31to0, + dest_hotlist->bssid.mac_addr47to32); + dest_hotlist++; + src_ap++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (min_entries * sizeof(wmi_extscan_hotlist_entry)); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) { + WMA_LOGE("%s: failed to send command", __func__); + adf_nbuf_free(buf); + return VOS_STATUS_E_FAILURE; + } + index = index + min_entries; + num_entries = numap - min_entries; + len = cmd_len; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma, + tSirExtScanSetBssidHotListReqParams *photlist) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int len; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + /* Fill individual elements for hotlist request and + * TLV for bssid entries + */ + vos_status = wma_get_buf_extscan_hotlist_cmd(wma, photlist, + &len); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to get buffer for hotlist scan cmd", + __func__); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma, + tSirExtScanResetBssidHotlistReqParams *photlist_reset) +{ + wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + int hotlist_entries = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!photlist_reset) { + WMA_LOGE("%s: Invalid reset hotlist buffer", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(*cmd); + + /* reset bssid hotlist with tlv set to 0 */ + len += WMI_TLV_HDR_SIZE; + len += hotlist_entries * sizeof(wmi_extscan_hotlist_entry); + + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *) + buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_configure_hotlist_monitor_cmd_fixed_param)); + + cmd->request_id = photlist_reset->requestId; + cmd->vdev_id = photlist_reset->sessionId; + cmd->mode = 0; + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + hotlist_entries * sizeof(wmi_extscan_hotlist_entry)); + buf_ptr += WMI_TLV_HDR_SIZE + + (hotlist_entries * sizeof(wmi_extscan_hotlist_entry)); + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) { + WMA_LOGE("%s: failed to command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/** + * wma_set_ssid_hotlist() - Handle an SSID hotlist set request + * @wma: WMA handle + * @request: SSID hotlist set request from SME + * + * Return: VOS_STATUS + */ +static VOS_STATUS +wma_set_ssid_hotlist(tp_wma_handle wma, + struct sir_set_ssid_hotlist_request *request) +{ + wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + uint32_t array_size; + uint8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!request) { + WMA_LOGE("%s: Invalid request buffer", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + + /* length of fixed portion */ + len = sizeof(*cmd); + + /* length of variable portion */ + array_size = + request->ssid_count * sizeof(wmi_extscan_hotlist_ssid_entry); + len += WMI_TLV_HDR_SIZE + array_size; + + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf); + cmd = (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *) + buf_ptr; + WMITLV_SET_HDR + (&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param)); + + cmd->request_id = request->request_id; + cmd->requestor_id = 0; + cmd->vdev_id = request->session_id; + cmd->table_id = 0; + cmd->lost_ap_scan_count = request->lost_ssid_sample_size; + cmd->total_entries = request->ssid_count; + cmd->num_entries_in_page = request->ssid_count; + cmd->first_entry_index = 0; + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, array_size); + + if (request->ssid_count) { + wmi_extscan_hotlist_ssid_entry *entry; + int i; + + buf_ptr += WMI_TLV_HDR_SIZE; + entry = (wmi_extscan_hotlist_ssid_entry *)buf_ptr; + for (i = 0; i < request->ssid_count; i++) { + WMITLV_SET_HDR + (entry, + WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN + (wmi_extscan_hotlist_ssid_entry)); + entry->ssid.ssid_len = request->ssids[i].ssid.length; + vos_mem_copy(entry->ssid.ssid, + request->ssids[i].ssid.ssId, + request->ssids[i].ssid.length); + entry->band = request->ssids[i].band; + entry->min_rssi = request->ssids[i].rssi_low; + entry->max_rssi = request->ssids[i].rssi_high; + entry++; + } + cmd->mode = WMI_EXTSCAN_MODE_START; + } else { + cmd->mode = WMI_EXTSCAN_MODE_STOP; + } + + if (wmi_unified_cmd_send + (wma->wmi_handle, wmi_buf, len, + WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID)) { + WMA_LOGE("%s: failed to send command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle, + tSirExtScanSetSigChangeReqParams *psigchange, + wmi_buf_t *buf, int *buf_len) +{ + wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd; + wmi_extscan_wlan_change_bssid_param *dest_chglist; + u_int8_t *buf_ptr; + int j; + int len = sizeof(*cmd); + int numap = psigchange->numAp; + tSirAPThresholdParam *src_ap = psigchange->ap; + + if (!numap) { + WMA_LOGE("%s: Invalid number of bssid's", + __func__); + return VOS_STATUS_E_INVAL; + } + len += WMI_TLV_HDR_SIZE; + len += numap * sizeof(wmi_extscan_wlan_change_bssid_param); + + *buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!*buf) { + WMA_LOGP("%s: failed to allocate memory for change monitor cmd", + __func__); + return VOS_STATUS_E_FAILURE; + } + buf_ptr = (u_int8_t *) wmi_buf_data(*buf); + cmd = (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param)); + + cmd->request_id = psigchange->requestId; + cmd->vdev_id = psigchange->sessionId; + cmd->total_entries = numap; + cmd->mode = 1; + cmd->num_entries_in_page = numap; + cmd->lost_ap_scan_count = psigchange->lostApSampleSize; + cmd->max_rssi_samples = psigchange->rssiSampleSize; + cmd->rssi_averaging_samples = psigchange->rssiSampleSize; + cmd->max_out_of_range_count = psigchange->minBreaching; + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + numap * sizeof(wmi_extscan_wlan_change_bssid_param)); + dest_chglist = (wmi_extscan_wlan_change_bssid_param *) + (buf_ptr + WMI_TLV_HDR_SIZE); + + for (j = 0; j < numap; j++) { + WMITLV_SET_HDR(dest_chglist, + WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_wlan_change_bssid_param)); + + dest_chglist->lower_rssi_limit = src_ap->low; + dest_chglist->upper_rssi_limit = src_ap->high; + WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid, + &dest_chglist->bssid); + + WMA_LOGD("%s:min_rssi %d", __func__, + dest_chglist->lower_rssi_limit); + dest_chglist++; + src_ap++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (numap * sizeof(wmi_extscan_wlan_change_bssid_param)); + *buf_len = len; + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_extscan_start_change_monitor(tp_wma_handle wma, + tSirExtScanSetSigChangeReqParams *psigchange) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf; + int len; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed,can not issue extscan cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + /* Fill individual elements of change monitor and + * TLV info ... */ + + vos_status = wma_get_buf_extscan_change_monitor_cmd(wma, + psigchange, &buf, &len); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to get buffer for change monitor cmd", + __func__); + return VOS_STATUS_E_FAILURE; + } + if (!buf) { + WMA_LOGE("%s: Failed to get buffer", __func__); + return VOS_STATUS_E_FAILURE; + } + if (wmi_unified_cmd_send(wma->wmi_handle, buf, + len, WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) { + WMA_LOGE("%s: failed to send command", __func__); + adf_nbuf_free(buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma, + tSirExtScanResetSignificantChangeReqParams *pResetReq) +{ + wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + int change_list = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: ext scan not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(*cmd); + + /* reset significant change tlv is set to 0 */ + len += WMI_TLV_HDR_SIZE; + len += change_list * + sizeof(wmi_extscan_wlan_change_bssid_param); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param)); + + cmd->request_id = pResetReq->requestId; + cmd->vdev_id = pResetReq->sessionId; + cmd->mode = 0; + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + change_list * + sizeof(wmi_extscan_wlan_change_bssid_param)); + buf_ptr += WMI_TLV_HDR_SIZE + (change_list * + sizeof(wmi_extscan_wlan_change_bssid_param)); + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) { + WMA_LOGE("%s: failed to command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_extscan_get_cached_results(tp_wma_handle wma, + tSirExtScanGetCachedResultsReqParams *pcached_results) +{ + wmi_extscan_get_cached_results_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, cannot issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf); + + cmd = (wmi_extscan_get_cached_results_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_get_cached_results_cmd_fixed_param)); + + cmd->request_id = pcached_results->requestId; + cmd->vdev_id = pcached_results->sessionId; + cmd->control_flags = pcached_results->flush; + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID)) { + WMA_LOGE("%s: failed to command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS wma_extscan_get_capabilities(tp_wma_handle wma, + tSirGetExtScanCapabilitiesReqParams *pgetcapab) +{ + wmi_extscan_get_capabilities_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", + __func__); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf); + + cmd = (wmi_extscan_get_capabilities_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_extscan_get_capabilities_cmd_fixed_param)); + + cmd->request_id = pgetcapab->requestId; + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_EXTSCAN_GET_CAPABILITIES_CMDID)) { + WMA_LOGE("%s: failed to command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/** wma_set_epno_network_list() - set epno network list + * @wma: WMA handle + * @req: epno config params request structure + * + * This function reads the incoming epno config request structure + * and constructs the WMI message to the firmware. + * + * Returns: 0 on success, error number otherwise + */ +static int wma_set_epno_network_list(tp_wma_handle wma, + struct wifi_epno_params *req) +{ + wmi_nlo_config_cmd_fixed_param *cmd; + nlo_configured_parameters *nlo_list; + u_int8_t i, *buf_ptr; + wmi_buf_t buf; + uint32_t len; + int ret; + + WMA_LOGD("wma_set_epno_network_list"); + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return -EINVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return -EINVAL; + } + + /* TLV place holder for array of structures + * nlo_configured_parameters(nlo_list) */ + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; + len += sizeof(nlo_configured_parameters) * + MIN(req->num_networks, WMI_NLO_MAX_SSIDS); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return -ENOMEM; + } + + cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (u_int8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_nlo_config_cmd_fixed_param)); + cmd->vdev_id = req->session_id; + cmd->flags = WMI_NLO_CONFIG_ENLO; + + buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param); + + cmd->no_of_ssids = MIN(req->num_networks, WMI_NLO_MAX_SSIDS); + WMA_LOGD("SSID count: %d", cmd->no_of_ssids); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + cmd->no_of_ssids * sizeof(nlo_configured_parameters)); + buf_ptr += WMI_TLV_HDR_SIZE; + + nlo_list = (nlo_configured_parameters *) buf_ptr; + for (i = 0; i < cmd->no_of_ssids; i++) { + WMITLV_SET_HDR(&nlo_list[i].tlv_header, + WMITLV_TAG_ARRAY_BYTE, + WMITLV_GET_STRUCT_TLVLEN(nlo_configured_parameters)); + /* Copy ssid and it's length */ + nlo_list[i].ssid.valid = TRUE; + nlo_list[i].ssid.ssid.ssid_len = req->networks[i].ssid.length; + vos_mem_copy(nlo_list[i].ssid.ssid.ssid, + req->networks[i].ssid.ssId, + nlo_list[i].ssid.ssid.ssid_len); + WMA_LOGD("index: %d ssid: %.*s len: %d", i, + nlo_list[i].ssid.ssid.ssid_len, + (char *) nlo_list[i].ssid.ssid.ssid, + nlo_list[i].ssid.ssid.ssid_len); + + /* Copy rssi threshold */ + nlo_list[i].rssi_cond.valid = TRUE; + nlo_list[i].rssi_cond.rssi = + req->networks[i].rssi_threshold; + WMA_LOGD("RSSI threshold : %d dBm", + nlo_list[i].rssi_cond.rssi); + + /* Copy pno flags */ + nlo_list[i].bcast_nw_type.valid = TRUE; + nlo_list[i].bcast_nw_type.bcast_nw_type = + req->networks[i].flags; + WMA_LOGD("PNO flags (%u)", + nlo_list[i].bcast_nw_type.bcast_nw_type); + + /* Copy auth bit field */ + nlo_list[i].auth_type.valid = TRUE; + nlo_list[i].auth_type.auth_type = + req->networks[i].auth_bit_field; + WMA_LOGD("Auth bit field (%u)", + nlo_list[i].auth_type.auth_type); + } + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send nlo wmi cmd", __func__); + wmi_buf_free(buf); + return -EINVAL; + } + + WMA_LOGD("set ePNO list request sent successfully for vdev %d", + req->session_id); + + return 0; +} + +/** + * wma_set_passpoint_network_list() - set passpoint network list + * @handle: WMA handle + * @req: passpoint network request structure + * + * This function reads the incoming @req and fill in the destination + * WMI structure and send down the passpoint configs down to the firmware + * + * Return: 0 on success; error number otherwise + */ +static int wma_set_passpoint_network_list(tp_wma_handle wma, + struct wifi_passpoint_req *req) +{ + wmi_passpoint_config_cmd_fixed_param *cmd; + u_int8_t i, j, *bytes; + wmi_buf_t buf; + uint32_t len; + int ret; + + WMA_LOGD("wma_set_passpoint_network_list"); + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return -EINVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return -EINVAL; + } + + len = sizeof(*cmd); + for (i = 0; i < req->num_networks; i++) { + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return -ENOMEM; + } + + cmd = (wmi_passpoint_config_cmd_fixed_param *) + wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_passpoint_config_cmd_fixed_param)); + cmd->id = req->networks[i].id; + WMA_LOGD("%s: network id: %u", __func__, cmd->id); + vos_mem_copy(cmd->realm, req->networks[i].realm, + strlen(req->networks[i].realm) + 1); + WMA_LOGD("%s: realm: %s", __func__, cmd->realm); + for (j = 0; j < PASSPOINT_ROAMING_CONSORTIUM_ID_NUM; j++) { + bytes = (uint8_t *) &req->networks[i].roaming_consortium_ids[j]; + WMA_LOGD("index: %d rcids: %02x %02x %02x %02x %02x %02x %02x %02x", + j, bytes[0], bytes[1], bytes[2], bytes[3], + bytes[4], bytes[5], bytes[6], bytes[7]); + + vos_mem_copy(&cmd->roaming_consortium_ids[j], + &req->networks[i].roaming_consortium_ids[j], + PASSPOINT_ROAMING_CONSORTIUM_ID_LEN); + } + vos_mem_copy(cmd->plmn, req->networks[i].plmn, + PASSPOINT_PLMN_ID_LEN); + WMA_LOGD("%s: plmn: [%02x %02x %02x]", __func__, + cmd->plmn[0], cmd->plmn[1], cmd->plmn[2]); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PASSPOINT_LIST_CONFIG_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send set passpoint network list wmi cmd", + __func__); + wmi_buf_free(buf); + return -EINVAL; + } + } + + WMA_LOGD("Set passpoint network list request is sent successfully for vdev %d", + req->session_id); + + return 0; +} + +/** + * wma_reset_passpoint_network_list() - reset passpoint network list + * @handle: WMA handle + * @req: passpoint network request structure + * + * This function sends down WMI command with network id set to wildcard id. + * firmware shall clear all the config entries + * + * Return: 0 on success; error number otherwise + */ +static int wma_reset_passpoint_network_list(tp_wma_handle wma, + struct wifi_passpoint_req *req) +{ + wmi_passpoint_config_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint32_t len; + int ret; + + WMA_LOGD("wma_reset_passpoint_network_list"); + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return -EINVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return -EINVAL; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return -ENOMEM; + } + + cmd = (wmi_passpoint_config_cmd_fixed_param *) wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_passpoint_config_cmd_fixed_param)); + cmd->id = WMI_PASSPOINT_NETWORK_ID_WILDCARD; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PASSPOINT_LIST_CONFIG_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send reset passpoint network list wmi cmd", + __func__); + wmi_buf_free(buf); + return -EINVAL; + } + + WMA_LOGD("Reset passpoint network list request is sent successfully for vdev %d", + req->session_id); + + return 0; +} + +#endif + +VOS_STATUS wma_ipa_offload_enable_disable(tp_wma_handle wma, + struct sir_ipa_offload_enable_disable *ipa_offload) +{ + wmi_ipa_offload_enable_disable_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; +#ifdef INTRA_BSS_FWD_OFFLOAD + ol_txrx_vdev_handle vdev; + struct txrx_pdev_cfg_t *cfg; + int32_t intra_bss_fwd = 0; +#endif + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + ((ipa_offload->offload_type == AP_RX_DATA_OFFLOAD)? + WMI_SERVICE_HSOFFLOAD: + WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT))) { + WMA_LOGE("%s: %s not supported", __func__, + ((ipa_offload->offload_type == AP_RX_DATA_OFFLOAD)? + "WMI_SERVICE_HSOFFLOAD": + "WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT")); + return VOS_STATUS_E_FAILURE; + } + + if (ipa_offload->offload_type > STA_RX_DATA_OFFLOAD) { + return VOS_STATUS_E_INVAL; + } + + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed (len=%d)", __func__, len); + return VOS_STATUS_E_NOMEM; + } + + WMA_LOGE("%s: offload_type=%d, enable=%d", __func__, + ipa_offload->offload_type, ipa_offload->enable); + + buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf); + + cmd = (wmi_ipa_offload_enable_disable_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUCT_wmi_ipa_offload_enable_disable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ipa_offload_enable_disable_cmd_fixed_param)); + + cmd->offload_type = ipa_offload->offload_type; + cmd->vdev_id = ipa_offload->vdev_id; + cmd->enable = ipa_offload->enable; + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID)) { + WMA_LOGE("%s: failed to command", __func__); + wmi_buf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + +#ifdef INTRA_BSS_FWD_OFFLOAD + /* Check if VDEV is already deleted. If deleted, don't + * send INTRA BSS FWD WMI command + */ + vdev = wma_find_vdev_by_id(wma, ipa_offload->vdev_id); + if (!vdev) + return VOS_STATUS_SUCCESS; + + /* Disable Intra-BSS FWD offload when gDisableIntraBssFwd=1 in INI */ + cfg = (struct txrx_pdev_cfg_t *)vdev->pdev->ctrl_pdev; + if (!ipa_offload->enable || cfg->rx_fwd_disabled) { + WMA_LOGE("%s: ipa_offload->enable=%d, rx_fwd_disabled=%d", + __func__, ipa_offload->enable, cfg->rx_fwd_disabled); + intra_bss_fwd = 1; + } + + /* Disable/enable WMI_VDEV_PARAM_INTRA_BSS_FWD */ + if (wmi_unified_vdev_set_param_send(wma->wmi_handle, + ipa_offload->vdev_id, WMI_VDEV_PARAM_INTRA_BSS_FWD, + intra_bss_fwd)) { + WMA_LOGE("Failed to disable WMI_VDEV_PARAM_INTRA_BSS_FWD"); + return VOS_STATUS_E_FAILURE; + } +#endif + + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_NAN +/* function : wma_nan_req + * Descriptin : Function is used to send nan request down + * Args : wma_handle, request data which will be non-null + * Returns : SUCCESS or FAILURE + */ +static VOS_STATUS wma_nan_req(void *wda_handle, tpNanRequest nan_req) +{ + int ret; + tp_wma_handle wma_handle = (tp_wma_handle)wda_handle; + wmi_nan_cmd_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + u_int16_t nan_data_len, nan_data_len_aligned; + u_int8_t *buf_ptr; + + /* + * <----- cmd ------------><-- WMI_TLV_HDR_SIZE --><--- data ----> + * +------------+----------+-----------------------+--------------+ + * | tlv_header | data_len | WMITLV_TAG_ARRAY_BYTE | nan_req_data | + * +------------+----------+-----------------------+--------------+ + */ + if (!nan_req) { + WMA_LOGE("%s:nan req is not valid", __func__); + return VOS_STATUS_E_FAILURE; + } + nan_data_len = nan_req->request_data_len; + nan_data_len_aligned = roundup(nan_req->request_data_len, + sizeof(u_int32_t)); + len += WMI_TLV_HDR_SIZE + nan_data_len_aligned; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_nan_cmd_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_nan_cmd_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_nan_cmd_param)); + cmd->data_len = nan_req->request_data_len; + WMA_LOGD("%s: The data len value is %u", + __func__, nan_req->request_data_len); + buf_ptr += sizeof(wmi_nan_cmd_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, nan_data_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, nan_req->request_data, + cmd->data_len); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_NAN_CMDID); + if (ret != EOK) { + WMA_LOGE("%s Failed to send set param command ret = %d", __func__, ret); + wmi_buf_free(buf); + } + return ret; +} +#endif + +static void wma_process_unit_test_cmd(WMA_HANDLE handle, + t_wma_unit_test_cmd *wma_utest) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_unit_test_cmd_fixed_param* cmd; + wmi_buf_t wmi_buf; + u_int8_t *buf_ptr; + int i; + u_int16_t len, args_tlv_len; + A_UINT32 *unit_test_cmd_args; + + args_tlv_len = WMI_TLV_HDR_SIZE + wma_utest->num_args * sizeof(A_UINT32); + len = sizeof(wmi_unit_test_cmd_fixed_param) + args_tlv_len; + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue fw unit test cmd", + __func__); + return; + } + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmai_buf_alloc failed", __func__); + return; + } + + cmd = (wmi_unit_test_cmd_fixed_param *)wmi_buf_data(wmi_buf); + buf_ptr = (u_int8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_unit_test_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_unit_test_cmd_fixed_param)); + cmd->vdev_id = wma_utest->vdev_id; + cmd->module_id = wma_utest->module_id; + cmd->num_args = wma_utest->num_args; + buf_ptr += sizeof(wmi_unit_test_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (wma_utest->num_args * sizeof(u_int32_t))); + unit_test_cmd_args = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE); + WMA_LOGI("%s: %d num of args = ", __func__, wma_utest->num_args); + for (i = 0; (i < wma_utest->num_args && i < WMA_MAX_NUM_ARGS); i++) { + unit_test_cmd_args[i] = wma_utest->args[i]; + WMA_LOGI("%d,", wma_utest->args[i]); + } + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_UNIT_TEST_CMDID)) { + WMA_LOGP("%s: failed to send unit test command", __func__); + adf_nbuf_free(wmi_buf); + return; + } + return; +} + +VOS_STATUS wma_scan_probe_setoui(tp_wma_handle wma, + tSirScanMacOui *psetoui) +{ + wmi_scan_prob_req_oui_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + u_int32_t *oui_buf; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", + __func__); + return VOS_STATUS_E_INVAL; + } + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf); + cmd = (wmi_scan_prob_req_oui_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_scan_prob_req_oui_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_scan_prob_req_oui_cmd_fixed_param)); + + oui_buf = &cmd->prob_req_oui; + vos_mem_zero(oui_buf, sizeof(cmd->prob_req_oui)); + *oui_buf = psetoui->oui[0] << 16 | psetoui->oui[1] << 8 + | psetoui->oui[2]; + WMA_LOGD("%s: wma:oui received from hdd %08x", __func__, + cmd->prob_req_oui); + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_SCAN_PROB_REQ_OUI_CMDID)) { + WMA_LOGE("%s: failed to send command", __func__); + adf_nbuf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +#ifdef DHCP_SERVER_OFFLOAD +static int wma_process_dhcpserver_offload(tp_wma_handle wma_handle, + tSirDhcpSrvOffloadInfo *pDhcpSrvOffloadInfo) +{ + wmi_set_dhcp_server_offload_cmd_fixed_param *cmd; + wmi_buf_t buf; + int err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send " + "set_dhcp_server_offload cmd"); + return -ENOMEM; + } + + cmd = (wmi_set_dhcp_server_offload_cmd_fixed_param *)wmi_buf_data(buf); + vos_mem_zero(cmd, sizeof(*cmd)); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_set_dhcp_server_offload_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_set_dhcp_server_offload_cmd_fixed_param)); + cmd->vdev_id = pDhcpSrvOffloadInfo->vdev_id; + cmd->enable = pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled; + cmd->num_client = pDhcpSrvOffloadInfo->dhcpClientNum; + cmd->srv_ipv4 = pDhcpSrvOffloadInfo->dhcpSrvIP; + cmd->start_lsb = pDhcpSrvOffloadInfo->dhcp_client_start_ip; + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_SET_DHCP_SERVER_OFFLOAD_CMDID); + if (err) { + WMA_LOGE("Failed to send set_dhcp_server_offload cmd"); + wmi_buf_free(buf); + return -EIO; + } + WMA_LOGD("Set dhcp server offload to vdevId %d", + pDhcpSrvOffloadInfo->vdev_id); + return 0; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +VOS_STATUS wma_set_led_flashing(tp_wma_handle wma_handle, + tSirLedFlashingReq *flashing) +{ + wmi_set_led_flashing_cmd_fixed_param *cmd; + int status = 0; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int32_t len = sizeof(wmi_set_led_flashing_cmd_fixed_param); + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE(FL("WMA is closed, can not issue cmd")); + return VOS_STATUS_E_INVAL; + } + if (!flashing) { + WMA_LOGE(FL("invalid parameter: flashing")); + return VOS_STATUS_E_INVAL; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_set_led_flashing_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_set_led_flashing_cmd_fixed_param)); + cmd->pattern_id = flashing->pattern_id; + cmd->led_x0 = flashing->led_x0; + cmd->led_x1 = flashing->led_x1; + cmd->gpio_num = flashing->gpio_num; + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_PDEV_SET_LED_FLASHING_CMDID); + if (status != EOK) { + WMA_LOGE("%s: wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD" + " returned Error %d", + __func__, status); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static void wma_process_roam_invoke(WMA_HANDLE handle, + t_wma_roam_invoke_cmd *roaminvoke) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_roam_invoke_cmd_fixed_param* cmd; + wmi_buf_t wmi_buf; + u_int8_t *buf_ptr; + u_int16_t len, args_tlv_len; + A_UINT32 *channel_list; + wmi_mac_addr *bssid_list; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not send roam invoke", + __func__); + return; + } + /* Host sends only one channel and one bssid */ + args_tlv_len = 2 * WMI_TLV_HDR_SIZE + sizeof(A_UINT32) + + sizeof(wmi_mac_addr); + len = sizeof(wmi_roam_invoke_cmd_fixed_param) + args_tlv_len; + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmai_buf_alloc failed", __func__); + return; + } + + cmd = (wmi_roam_invoke_cmd_fixed_param *)wmi_buf_data(wmi_buf); + buf_ptr = (u_int8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_invoke_cmd_fixed_param)); + cmd->vdev_id = roaminvoke->vdev_id; + cmd->flags = 0; + cmd->roam_scan_mode = 0; + cmd->roam_ap_sel_mode = 0; + cmd->roam_delay = 0; + cmd->num_chan = 1; + cmd->num_bssid = 1; + buf_ptr += sizeof(wmi_roam_invoke_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (sizeof(u_int32_t))); + channel_list = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE); + *channel_list = (A_UINT32)vos_chan_to_freq(roaminvoke->channel); + buf_ptr += sizeof(A_UINT32) + WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, + (sizeof(wmi_mac_addr))); + bssid_list = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); + WMI_CHAR_ARRAY_TO_MAC_ADDR(roaminvoke->bssid, bssid_list); + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_ROAM_INVOKE_CMDID)) { + WMA_LOGP("%s: failed to send roam invoke command", __func__); + adf_nbuf_free(wmi_buf); + return; + } + return; +} +#endif + +#ifdef MDNS_OFFLOAD +static int wma_set_mdns_offload(tp_wma_handle wma_handle, + tSirMDNSOffloadInfo *pMDNSInfo) +{ + wmi_mdns_offload_cmd_fixed_param *cmd; + wmi_buf_t buf; + int err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send " + "set_mdns_offload cmd"); + return -ENOMEM; + } + + cmd = (wmi_mdns_offload_cmd_fixed_param *)wmi_buf_data(buf); + vos_mem_zero(cmd, sizeof(*cmd)); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_offload_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_mdns_offload_cmd_fixed_param)); + cmd->vdev_id = pMDNSInfo->vdev_id; + cmd->enable = pMDNSInfo->mDNSOffloadEnabled; + + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_MDNS_OFFLOAD_ENABLE_CMDID); + if (err) { + WMA_LOGE("Failed to send set_mdns_offload cmd"); + wmi_buf_free(buf); + return -EIO; + } + WMA_LOGD("Set mDNS offload to vdevId %d", + pMDNSInfo->vdev_id); + return 0; +} + +static int wma_set_mdns_fqdn(tp_wma_handle wma_handle, + tSirMDNSFqdnInfo *pMDNSFqdnInfo) +{ + wmi_mdns_set_fqdn_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int len, err; + int num; + int numPadding = 0; + + /* mdns fqdn is a table of 2 TLV's */ + len = WMI_TLV_HDR_SIZE + pMDNSFqdnInfo->fqdn_len; + len += sizeof(wmi_mdns_set_fqdn_cmd_fixed_param); + num = len % sizeof(A_UINT32); + if (num > 0) { + numPadding = sizeof(A_UINT32) - num; + len += numPadding; + } + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send " + "set_mdns_fqdn cmd"); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_mdns_set_fqdn_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_set_fqdn_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_mdns_set_fqdn_cmd_fixed_param)); + cmd->vdev_id = pMDNSFqdnInfo->vdev_id; + cmd->type = pMDNSFqdnInfo->fqdn_type; + cmd->fqdn_len = pMDNSFqdnInfo->fqdn_len; + + buf_ptr += sizeof(wmi_mdns_set_fqdn_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, (numPadding+cmd->fqdn_len)); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, pMDNSFqdnInfo->fqdn_data, cmd->fqdn_len); + if (numPadding > 0) { + buf_ptr += cmd->fqdn_len; + vos_mem_zero(buf_ptr, numPadding); + } + + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_MDNS_SET_FQDN_CMDID); + if (err) { + WMA_LOGE("Failed to send set_mdns_fqdn cmd"); + wmi_buf_free(buf); + return -EIO; + } + WMA_LOGD("Set mDNS fqdn to vdevId %d", + pMDNSFqdnInfo->vdev_id); + return 0; +} + +static int wma_set_mdns_response(tp_wma_handle wma_handle, + tSirMDNSResponseInfo *pMDNSRespInfo) +{ + wmi_mdns_set_resp_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int len, err; + int num; + int numPadding = 0; + + /* mdns response is a table of 2 TLV's */ + len = WMI_TLV_HDR_SIZE + pMDNSRespInfo->resp_len; + len += sizeof(wmi_mdns_set_resp_cmd_fixed_param); + num = len % sizeof(A_UINT32); + if (num > 0) { + numPadding = sizeof(A_UINT32) - num; + len += numPadding; + } + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send " + "set_mdns_response cmd"); + return -ENOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_mdns_set_resp_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_set_resp_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_mdns_set_resp_cmd_fixed_param)); + cmd->vdev_id = pMDNSRespInfo->vdev_id; + cmd->AR_count = pMDNSRespInfo->resourceRecord_count; + cmd->resp_len = pMDNSRespInfo->resp_len; + + buf_ptr += sizeof(wmi_mdns_set_resp_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, (numPadding+cmd->resp_len)); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, pMDNSRespInfo->resp_data, cmd->resp_len); + if (numPadding > 0) { + buf_ptr += cmd->resp_len; + vos_mem_zero(buf_ptr, numPadding); + } + + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_MDNS_SET_RESPONSE_CMDID); + if (err) { + WMA_LOGE("Failed to set_mdns_response cmd"); + wmi_buf_free(buf); + return -EIO; + } + WMA_LOGD("Set mDNS response to vdevId %d", + pMDNSRespInfo->vdev_id); + return 0; +} + +static int wma_get_mdns_status(tp_wma_handle wma_handle, A_UINT32 *pVdev_id) +{ + wmi_mdns_get_stats_cmd_fixed_param *cmd; + wmi_buf_t buf; + int err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send " + "get_mdns_status cmd"); + return -ENOMEM; + } + + cmd = (wmi_mdns_get_stats_cmd_fixed_param *)wmi_buf_data(buf); + vos_mem_zero(cmd, sizeof(*cmd)); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_stats_event_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_mdns_get_stats_cmd_fixed_param)); + cmd->vdev_id = *pVdev_id; + + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_MDNS_GET_STATS_CMDID); + if (err) { + WMA_LOGE("Failed to send get_mdns_status cmd"); + wmi_buf_free(buf); + return -EIO; + } + WMA_LOGD("Get mDNS STATS for vdevId %d", *pVdev_id); + return 0; +} +#endif /* MDNS_OFFLOAD */ + + +#ifdef SAP_AUTH_OFFLOAD +static int wma_process_sap_auth_offload(tp_wma_handle wma_handle, + struct tSirSapOffloadInfo *sap_auth_offload_info) +{ + wmi_sap_ofl_enable_cmd_fixed_param *cmd = NULL; + wmi_buf_t buf; + u_int8_t *buf_ptr; + u_int16_t len, psk_len, psk_len_padded; + int err; + + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SAP_AUTH_OFFLOAD)) { + WMA_LOGE("Firmware not support SAP auth offload feature"); + return -EIO; + } + + psk_len = sap_auth_offload_info->key_len; + psk_len_padded = roundup(psk_len, sizeof(uint32_t)); + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + psk_len_padded; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send " + "sap_auth_offload_enable cmd"); + return -ENOMEM; + } + + vos_mem_zero(cmd, len); + + buf_ptr = wmi_buf_data(buf); + cmd = (wmi_sap_ofl_enable_cmd_fixed_param *)buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sap_ofl_enable_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_sap_ofl_enable_cmd_fixed_param)); + + cmd->enable = sap_auth_offload_info->sap_auth_offload_enable; + cmd->vdev_id = sap_auth_offload_info->vdev_id; + cmd->psk_len = psk_len; + + /* SSID didn't assign here, left for Supplicant Profile Assign + * This field just keep for extendable + */ + switch (sap_auth_offload_info->sap_auth_offload_sec_type) { + case eSIR_OFFLOAD_WPA2PSK_CCMP: + cmd->rsn_authmode = WMI_AUTH_RSNA_PSK; + cmd->rsn_mcastcipherset = WMI_CIPHER_AES_CCM; + cmd->rsn_ucastcipherset = WMI_CIPHER_AES_CCM; + break; + case eSIR_OFFLOAD_NONE: + default: + WMA_LOGE("Set software AP Auth offload " + "with none support security type\n"); + break; + } + + buf_ptr += sizeof(wmi_sap_ofl_enable_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, psk_len_padded); + buf_ptr += WMI_TLV_HDR_SIZE; + vos_mem_copy(buf_ptr, sap_auth_offload_info->key, psk_len); + + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_SAP_OFL_ENABLE_CMDID); + if (err) { + WMA_LOGE("Failed to set software AP Auth offload enable cmd"); + wmi_buf_free(buf); + return -EIO; + } + WMA_LOGD("Set software AP Auth offload enable = %d to vdevId %d", + sap_auth_offload_info->sap_auth_offload_enable, + sap_auth_offload_info->vdev_id); + return 0; +} + +/** + * wma_process_client_block_info send wmi cmd of block info to fw. + * + * @wma_handle: wma handler + * @client_block_info: client block info struct pointer + * + * Return: Return VOS_STATUS + */ +static VOS_STATUS wma_process_client_block_info(tp_wma_handle wma_handle, + struct sblock_info *client_block_info) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_sap_set_blacklist_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + int ret; + + if (!client_block_info) + return VOS_STATUS_E_FAULT; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed to allocate buffer",__func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_sap_set_blacklist_param_cmd_fixed_param *)wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sap_set_blacklist_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sap_set_blacklist_param_cmd_fixed_param)); + + cmd->vdev_id = client_block_info->vdev_id; + cmd->num_retry = client_block_info->reconnect_cnt; + cmd->retry_allow_time_ms = client_block_info->con_fail_duration; + cmd->blackout_time_ms = client_block_info->block_duration; + + WMA_LOGD("Set Sap client block info vdev id=%u, reconnect_cnt=%u" + "con_fail_duration=%u, block_duration=%u", + cmd->vdev_id, cmd->num_retry, + cmd->retry_allow_time_ms, cmd->blackout_time_ms); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_SAP_SET_BLACKLIST_PARAM_CMDID); + if (ret != EOK) { + WMA_LOGE("fail to semd WMI_SAP_SET_BLACKLIST_PARAM_CMDID"); + wmi_buf_free(buf); + vos_status = VOS_STATUS_E_FAILURE; + } + + return vos_status; +} +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * wma_process_set_mas() - Function to enable/disable MAS + * @wma: Pointer to WMA handle + * @mas_val: 1-Enable MAS, 0-Disable MAS + * + * This function enables/disables the MAS value + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure + * + */ +VOS_STATUS wma_process_set_mas(tp_wma_handle wma, + uint32_t *mas_val) +{ + uint32_t val; + + if (NULL == wma || NULL == mas_val) { + WMA_LOGE("%s: Invalid input to enable/disable MAS", __func__); + return VOS_STATUS_E_FAILURE; + } + + val = (*mas_val); + + if (VOS_STATUS_SUCCESS != + wma_set_enable_disable_mcc_adaptive_scheduler(val)) { + WMA_LOGE("%s: Unable to enable/disable MAS", __func__); + return VOS_STATUS_E_FAILURE; + } else { + WMA_LOGE("%s: Value is %d", __func__, val); + } + + return VOS_STATUS_SUCCESS; +} + +/** + * wma_process_set_miracast() - Function to set miracast value in WMA + * @wma: Pointer to WMA handle + * @miracast_val: 0-Disabled,1-Source,2-Sink + * + * This function stores the miracast value in WMA + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure + * + */ +VOS_STATUS wma_process_set_miracast(tp_wma_handle wma, u_int32_t *miracast_val) +{ + if (NULL == wma || NULL == miracast_val) { + WMA_LOGE("%s: Invalid input to store miracast value", __func__); + return VOS_STATUS_E_FAILURE; + } + + wma->miracast_value = *miracast_val; + WMA_LOGE("%s: Miracast value is %d", __func__, wma->miracast_value); + + return VOS_STATUS_SUCCESS; +} + +/** + * wma_config_stats_factor() - Function to configure stats avg. factor + * @wma: pointer to WMA handle + * @avg_factor: stats. avg. factor passed down by userspace + * + * This function configures the avg. stats value in firmware + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure + * + */ +VOS_STATUS wma_config_stats_factor(tp_wma_handle wma, + struct sir_stats_avg_factor *avg_factor) +{ + int ret; + + if (NULL == wma || NULL == avg_factor) { + WMA_LOGE("%s: Invalid input of stats avg factor", __func__); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + avg_factor->vdev_id, + WMI_VDEV_PARAM_STATS_AVG_FACTOR, + avg_factor->stats_avg_factor); + if (ret) { + WMA_LOGE(" failed to set avg_factor for vdev_id %d", + avg_factor->vdev_id); + } + + WMA_LOGD("%s: Set stats_avg_factor %d for vdev_id %d", __func__, + avg_factor->stats_avg_factor, avg_factor->vdev_id); + + return ret; +} + +/** + * wma_config_guard_time() - Function to set guard time in firmware + * @wma: pointer to WMA handle + * @guard_time: guard time passed down by userspace + * + * This function configures the guard time in firmware + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure + * + */ +VOS_STATUS wma_config_guard_time(tp_wma_handle wma, + struct sir_guard_time_request *guard_time) +{ + int ret; + + if (NULL == wma || NULL == guard_time) { + WMA_LOGE("%s: Invalid input of guard time", __func__); + return VOS_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + guard_time->vdev_id, + WMI_VDEV_PARAM_RX_LEAK_WINDOW, + guard_time->guard_time); + if (ret) { + WMA_LOGE(" failed to set guard time for vdev_id %d", + guard_time->vdev_id); + } + + WMA_LOGD("Set guard time %d for vdev_id %d", + guard_time->guard_time, guard_time->vdev_id); + + return ret; +} + +#ifdef WLAN_FEATURE_MEMDUMP +/* + * wma_process_fw_mem_dump_req() - Function to request fw memory dump from + * firmware + * @wma: Pointer to WMA handle + * @mem_dump_req: Pointer for mem_dump_req + * + * This function sends memory dump request to firmware + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure + * + */ +static VOS_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma, + struct fw_dump_req* mem_dump_req) +{ + wmi_get_fw_mem_dump_fixed_param *cmd; + wmi_fw_mem_dump *dump_params; + struct fw_dump_seg_req *seg_req; + int32_t len; + wmi_buf_t buf; + u_int8_t *buf_ptr; + int ret, loop; + + if (!mem_dump_req || !wma) { + WMA_LOGE(FL("input pointer is NULL")); + return VOS_STATUS_E_FAILURE; + } + + /* + * len = sizeof(fixed param) that includes tlv header + + * tlv header for array of struc + + * sizeof (each struct) + */ + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; + len += mem_dump_req->num_seg * sizeof(wmi_fw_mem_dump); + buf = wmi_buf_alloc(wma->wmi_handle, len); + + if (!buf) { + WMA_LOGE(FL("Failed allocate wmi buffer")); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + cmd = (wmi_get_fw_mem_dump_fixed_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_get_fw_mem_dump_fixed_param)); + + cmd->request_id = mem_dump_req->request_id; + cmd->num_fw_mem_dump_segs = mem_dump_req->num_seg; + + /* TLV indicating array of structures to follow */ + buf_ptr += sizeof(wmi_get_fw_mem_dump_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_fw_mem_dump) * + cmd->num_fw_mem_dump_segs); + + buf_ptr += WMI_TLV_HDR_SIZE; + dump_params = (wmi_fw_mem_dump *) buf_ptr; + + WMA_LOGI(FL("request_id:%d num_seg:%d"), + mem_dump_req->request_id, mem_dump_req->num_seg); + for (loop = 0; loop < cmd->num_fw_mem_dump_segs; loop++) { + seg_req = (struct fw_dump_seg_req *) + ((uint8_t *)(mem_dump_req->segment) + + loop * sizeof(*seg_req)); + WMITLV_SET_HDR(&dump_params->tlv_header, + WMITLV_TAG_STRUC_wmi_fw_mem_dump_params, + WMITLV_GET_STRUCT_TLVLEN(wmi_fw_mem_dump)); + dump_params->seg_id = seg_req->seg_id; + dump_params->seg_start_addr_lo = seg_req-> seg_start_addr_lo; + dump_params->seg_start_addr_hi = seg_req->seg_start_addr_hi; + dump_params->seg_length = seg_req->seg_length; + dump_params->dest_addr_lo = seg_req->dst_addr_lo; + dump_params->dest_addr_hi = seg_req->dst_addr_hi; + WMA_LOGI(FL("seg_number:%d"), loop); + WMA_LOGI(FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"), + dump_params->seg_id, dump_params->seg_start_addr_lo, + dump_params->seg_start_addr_hi); + WMA_LOGI(FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"), + dump_params->seg_length, dump_params->dest_addr_lo, + dump_params->dest_addr_hi); + dump_params++; + } + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_GET_FW_MEM_DUMP_CMDID); + if (ret) { + WMA_LOGE(FL("Failed to send get firmware mem dump request")); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI(FL("Get firmware mem dump request sent successfully")); + return VOS_STATUS_SUCCESS; +} +#else +static VOS_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma, + void *mem_dump_req) +{ + return VOS_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +/* + * wma_process_set_ie_info() - Function to send IE info to firmware + * @wma: Pointer to WMA handle + * @ie_data: Pointer for ie data + * + * This function sends IE information to firmware + * + * Return: VOS_STATUS_SUCCESS for success otherwise failure + * + */ +static VOS_STATUS wma_process_set_ie_info(tp_wma_handle wma, + struct vdev_ie_info* ie_info) +{ + wmi_vdev_set_ie_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t len, ie_len_aligned; + int ret; + + if (!ie_info || !wma) { + WMA_LOGE(FL("input pointer is NULL")); + return VOS_STATUS_E_FAILURE; + } + + /* Validate the input */ + if (ie_info->length <= 0) { + WMA_LOGE(FL("Invalid IE length")); + return -EINVAL; + } + + ie_len_aligned = roundup(ie_info->length, sizeof(uint32_t)); + /* Allocate memory for the WMI command */ + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + ie_len_aligned; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + + /* Populate the WMI command */ + cmd = (wmi_vdev_set_ie_cmd_fixed_param *)buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_set_ie_cmd_fixed_param)); + cmd->vdev_id = ie_info->vdev_id; + cmd->ie_id = ie_info->ie_id; + cmd->ie_len = ie_info->length; + + WMA_LOGD(FL("IE:%d of size:%d sent for vdev:%d"), ie_info->ie_id, + ie_info->length, ie_info->vdev_id); + + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + + vos_mem_copy(buf_ptr, ie_info->data, cmd->ie_len); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_VDEV_SET_IE_CMDID); + if (ret != EOK) { + WMA_LOGE(FL("Failed to send set IE command ret = %d"), ret); + wmi_buf_free(buf); + } + + return ret; +} + +/** + * wma_enable_specific_fw_logs() - Start/Stop logging of diag event/log id + * @wma_handle: WMA handle + * @start_log: Start logging related parameters + * + * Send the command to the FW based on which specific logging of diag + * event/log id can be started/stopped + * + * Return: None + */ +void wma_enable_specific_fw_logs(tp_wma_handle wma_handle, + struct sir_wifi_start_log *start_log) +{ + wmi_diag_event_log_config_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t len, count, log_level, i; + uint32_t *cmd_args; + uint32_t total_len; + count = 0; + + if (!start_log) { + WMA_LOGE("%s: start_log pointer is NULL", __func__); + return; + } + if (!wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return; + } + + if (!((start_log->ring_id == RING_ID_CONNECTIVITY) || + (start_log->ring_id == RING_ID_FIRMWARE_DEBUG))) { + WMA_LOGD("%s: Not connectivity or fw debug ring: %d", + __func__, start_log->ring_id); + return; + } + + if (!wma_handle->events_logs_list) { + WMA_LOGE("%s: Not received event/log list from FW, yet", + __func__); + return; + } + + /* total_len stores the number of events where BITS 17 and 18 are set. + * i.e., events of high frequency (17) and for extended debugging (18) + */ + total_len = 0; + for (i = 0; i < wma_handle->num_of_diag_events_logs; i++) { + if ((WMI_DIAG_FREQUENCY_GET(wma_handle->events_logs_list[i])) && + (WMI_DIAG_EXT_FEATURE_GET(wma_handle->events_logs_list[i]))) + total_len++; + } + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + + (total_len * sizeof(uint32_t)); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return; + } + cmd = (wmi_diag_event_log_config_fixed_param *) wmi_buf_data(buf); + buf_ptr = (uint8_t *) cmd; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_diag_event_log_config_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_diag_event_log_config_fixed_param)); + + cmd->num_of_diag_events_logs = total_len; + + buf_ptr += sizeof(wmi_diag_event_log_config_fixed_param); + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (total_len * sizeof(uint32_t))); + + cmd_args = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE); + + if (start_log->verbose_level >= LOG_LEVEL_ACTIVE) + log_level = 1; + else + log_level = 0; + + WMA_LOGD("%s: Length:%d, Log_level:%d", __func__, total_len, log_level); + for (i = 0; i < wma_handle->num_of_diag_events_logs; i++) { + uint32_t val = wma_handle->events_logs_list[i]; + if ((WMI_DIAG_FREQUENCY_GET(val)) && + (WMI_DIAG_EXT_FEATURE_GET(val))) { + + WMI_DIAG_ID_SET(cmd_args[count], + WMI_DIAG_ID_GET(val)); + WMI_DIAG_TYPE_SET(cmd_args[count], + WMI_DIAG_TYPE_GET(val)); + WMI_DIAG_ID_ENABLED_DISABLED_SET(cmd_args[count], + log_level); + WMA_LOGD("%s: Idx:%d, val:%x", __func__, i, val); + count++; + } + } + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_DIAG_EVENT_LOG_CONFIG_CMDID)) { + WMA_LOGE("%s: WMI_DIAG_EVENT_LOG_CONFIG_CMDID failed", + __func__); + wmi_buf_free(buf); + } + return; +} + +#if !defined(REMOVE_PKT_LOG) +/** + * wma_set_wifi_start_packet_stats() - Start/stop packet stats + * @wma_handle: WMA handle + * @start_log: Struture containing the start wifi logger params + * + * This function is used to send the WMA commands to start/stop logging + * of per packet statistics + * + * Return: None + * + */ +void wma_set_wifi_start_packet_stats(void *wma_handle, + struct sir_wifi_start_log *start_log) +{ + void *vos_context; + struct ol_softc *scn; + uint32_t log_state; + + if (!start_log) { + WMA_LOGE("%s: start_log pointer is NULL", __func__); + return; + } + if (!wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return; + } + + /* No need to register for ring IDs other than packet stats */ + if (start_log->ring_id != RING_ID_PER_PACKET_STATS) { + WMA_LOGI("%s: Ring id is not for per packet stats: %d", + __func__, start_log->ring_id); + return; + } + + vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + + if (!scn) { + WMA_LOGE("%s: ol_softc context is NULL\n", __func__); + return; + } + + log_state = ATH_PKTLOG_ANI | ATH_PKTLOG_RCUPDATE | ATH_PKTLOG_RCFIND | + ATH_PKTLOG_RX | ATH_PKTLOG_TX | ATH_PKTLOG_TEXT; + + if (start_log->verbose_level == WLAN_LOG_LEVEL_ACTIVE) { + pktlog_enable(scn, log_state); + WMA_LOGI("%s: Enabling per packet stats", __func__); + } else { + pktlog_enable(scn, 0); + WMA_LOGI("%s: Disabling per packet stats", __func__); + } +} +#endif + +/** + * wma_send_flush_logs_to_fw() - Send log flush command to FW + * @wma_handle: WMI handle + * + * This function is used to send the flush command to the FW, + * that will flush the fw logs that are residue in the FW + * + * Return: None + */ +void wma_send_flush_logs_to_fw(tp_wma_handle wma_handle) +{ + VOS_STATUS status; + wmi_debug_mesg_flush_fixed_param *cmd; + wmi_buf_t buf; + int len = sizeof(*cmd); + int ret; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return; + } + + cmd = (wmi_debug_mesg_flush_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_debug_mesg_flush_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_debug_mesg_flush_fixed_param)); + cmd->reserved0 = 0; + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, + buf, + len, + WMI_DEBUG_MESG_FLUSH_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send WMI_DEBUG_MESG_FLUSH_CMDID"); + wmi_buf_free(buf); + return; + } + WMA_LOGI("Sent WMI_DEBUG_MESG_FLUSH_CMDID to FW"); + + status = vos_timer_start(&wma_handle->log_completion_timer, + WMA_LOG_COMPLETION_TIMER); + if (status != VOS_STATUS_SUCCESS) + WMA_LOGE("Failed to start the log completion timer"); +} + +/** + * wma_set_rssi_monitoring() - set rssi monitoring + * @handle: WMA handle + * @req: rssi monitoring request structure + * + * This function reads the incoming @req and fill in the destination + * WMI structure and send down the rssi monitoring configs down to the firmware + * + * Return: 0 on success; error number otherwise + */ +static VOS_STATUS wma_set_rssi_monitoring(tp_wma_handle wma, + struct rssi_monitor_req *req) +{ + wmi_rssi_breach_monitor_config_fixed_param *cmd; + wmi_buf_t buf; + int ret, len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + cmd = (wmi_rssi_breach_monitor_config_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_rssi_breach_monitor_config_fixed_param)); + + cmd->vdev_id = req->session_id; + cmd->request_id = req->request_id; + cmd->lo_rssi_reenable_hysteresis = 0; + cmd->hi_rssi_reenable_histeresis = 0; + cmd->min_report_interval = 0; + cmd->max_num_report = 1; + if (req->control) { + /* enable one threshold for each min/max */ + cmd->enabled_bitmap = 0x09; + cmd->low_rssi_breach_threshold[0] = req->min_rssi; + cmd->hi_rssi_breach_threshold[0] = req->max_rssi; + } else { + cmd->enabled_bitmap = 0; + cmd->low_rssi_breach_threshold[0] = 0; + cmd->hi_rssi_breach_threshold[0] = 0; + } + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID"); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI("Sent WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID to FW"); + return VOS_STATUS_SUCCESS; +} + + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD +/** +* wma_send_udp_resp_offload_cmd() - send wmi cmd of udp response offload +* infomation to fw. +* @wma_handle: wma handler +* @udp_response: udp_resp_offload struct pointer +* +* Return: Return VOS_STATUS +*/ +static VOS_STATUS wma_send_udp_resp_offload_cmd(tp_wma_handle wma_handle, + struct udp_resp_offload *udp_response) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_buf_t buf; + WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param *cmd; + u_int16_t len; + u_int16_t pattern_len = 0; + u_int16_t response_len = 0; + u_int16_t udp_len = 0; + u_int16_t resp_len = 0; + + WMA_LOGD("%s: Enter", __func__); + if (1 == udp_response->enable) { + pattern_len = strlen(udp_response->udp_payload_filter); + response_len = strlen(udp_response->udp_response_payload); + } + + udp_len = (pattern_len % 4) ? + (4 * ((pattern_len / 4) + 1)) : (pattern_len); + + resp_len = (response_len % 4) ? + (4 * ((response_len / 4) + 1)) : (response_len); + + + len = sizeof(*cmd) + udp_len + resp_len + 2 * WMI_TLV_HDR_SIZE; + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("wmi_buf_alloc failed"); + return VOS_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param *)wmi_buf_data(buf); + vos_mem_zero(cmd, len); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param)); + + cmd->vdev_id = udp_response->vdev_id; + cmd->enable = udp_response->enable; + cmd->dest_port = udp_response->dest_port; + cmd->pattern_len = pattern_len; + cmd->response_len = response_len; + + + WMITLV_SET_HDR((A_UINT32 *)(cmd + 1), + WMITLV_TAG_ARRAY_BYTE, + udp_len); + + vos_mem_copy((void *)(cmd + 1) + WMI_TLV_HDR_SIZE, + (void *)udp_response->udp_payload_filter, + cmd->pattern_len); + WMITLV_SET_HDR((A_UINT32 *)((void *)(cmd + 1) + + WMI_TLV_HDR_SIZE + udp_len), + WMITLV_TAG_ARRAY_BYTE, + resp_len); + + vos_mem_copy((void *)(cmd + 1) + WMI_TLV_HDR_SIZE + + udp_len + WMI_TLV_HDR_SIZE, + (void *)udp_response->udp_response_payload, + cmd->response_len); + + + + WMA_LOGD("wma_set_udp_resp_cmd: enable:%d vdev_id:%d dest_port:%u", + cmd->enable,cmd->vdev_id, cmd->dest_port); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_WOW_UDP_SVC_OFLD_CMDID)) { + WMA_LOGE("Failed to send set udp resp offload"); + wmi_buf_free(buf); + vos_status = VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("%s: Exit", __func__); + return vos_status; +} +#else +static inline VOS_STATUS wma_send_udp_resp_offload_cmd(tp_wma_handle wma_handle, + struct udp_resp_offload *udp_response) +{ + return VOS_STATUS_E_FAILURE; +} +#endif + +/* + * wma_update_wep_default_key - function to update default key id + * @wma: pointer to wma handler + * @update_def_key: pointer to wep_update_default_key_idx + * + * function makes a copy of default key index to txrx node + * + * return: Success + */ +static VOS_STATUS wma_update_wep_default_key(tp_wma_handle wma, + struct wep_update_default_key_idx *update_def_key) +{ + struct wma_txrx_node *iface = + &wma->interfaces[update_def_key->session_id]; + iface->wep_default_key_idx = update_def_key->default_idx; + + return VOS_STATUS_SUCCESS; +} + +/* + * function : wma_mc_process_msg + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tp_wma_handle wma_handle; + ol_txrx_vdev_handle txrx_vdev_handle = NULL; + extern tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ); + + WMA_LOGI("%s: Enter", __func__); + if(NULL == msg) { + WMA_LOGE("msg is NULL"); + VOS_ASSERT(0); + vos_status = VOS_STATUS_E_INVAL; + goto end; + } + + WMA_LOGD("msg->type = %x %s", msg->type, macTraceGetWdaMsgString(msg->type)); + + wma_handle = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, + vos_context); + + if (NULL == wma_handle) { + WMA_LOGP("%s: wma_handle is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(msg->bodyptr); + vos_status = VOS_STATUS_E_INVAL; + goto end; + } + + switch (msg->type) { +#ifdef FEATURE_WLAN_ESE + case WDA_TSM_STATS_REQ: + WMA_LOGA("McThread: WDA_TSM_STATS_REQ"); + wma_process_tsm_stats_req(wma_handle, (void*)msg->bodyptr); + break; +#endif + case WNI_CFG_DNLD_REQ: + WMA_LOGA("McThread: WNI_CFG_DNLD_REQ"); + vos_status = wma_wni_cfg_dnld(wma_handle); + if (VOS_IS_STATUS_SUCCESS(vos_status)) { + vos_WDAComplete_cback(vos_context); + } + else { + WMA_LOGD("config download failure"); + } + break ; + case WDA_ADD_STA_SELF_REQ: + txrx_vdev_handle = wma_vdev_attach(wma_handle, + (tAddStaSelfParams *)msg->bodyptr, 1); + if (!txrx_vdev_handle) { + WMA_LOGE("Failed to attach vdev"); + } else { + WLANTL_RegisterVdev(vos_context, + txrx_vdev_handle); + /* Register with TxRx Module for Data Ack Complete Cb */ + wdi_in_data_tx_cb_set(txrx_vdev_handle, + wma_data_tx_ack_comp_hdlr, wma_handle); + } + break; + case WDA_DEL_STA_SELF_REQ: + wma_vdev_detach(wma_handle, + (tDelStaSelfParams *)msg->bodyptr, 1); + break; + case WDA_START_SCAN_OFFLOAD_REQ: + wma_start_scan(wma_handle, msg->bodyptr, msg->type); + vos_mem_free(msg->bodyptr); + break; + case WDA_STOP_SCAN_OFFLOAD_REQ: + wma_stop_scan(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_UPDATE_CHAN_LIST_REQ: + wma_update_channel_list(wma_handle, + (tSirUpdateChanList *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_LINK_STATE: + wma_set_linkstate(wma_handle, + (tpLinkStateParams)msg->bodyptr); + break; + case WDA_CHNL_SWITCH_REQ: + wma_set_channel(wma_handle, + (tpSwitchChannelParams)msg->bodyptr); + break; + case WDA_ADD_BSS_REQ: + wma_add_bss(wma_handle, (tpAddBssParams)msg->bodyptr); + break; + case WDA_ADD_STA_REQ: + wma_add_sta(wma_handle, (tpAddStaParams)msg->bodyptr); + break; + case WDA_SET_BSSKEY_REQ: + wma_set_bsskey(wma_handle, + (tpSetBssKeyParams)msg->bodyptr); + break; + case WDA_SET_STAKEY_REQ: + wma_set_stakey(wma_handle, + (tpSetStaKeyParams)msg->bodyptr); + break; + case WDA_DELETE_STA_REQ: + wma_delete_sta(wma_handle, + (tpDeleteStaParams)msg->bodyptr); + break; + case WDA_DELETE_BSS_REQ: + wma_delete_bss(wma_handle, + (tpDeleteBssParams)msg->bodyptr); + break; + case WDA_UPDATE_EDCA_PROFILE_IND: + wma_process_update_edca_param_req( + wma_handle, + (tEdcaParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SEND_BEACON_REQ: + wma_send_beacon(wma_handle, + (tpSendbeaconParams)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SEND_PROBE_RSP_TMPL: + wma_send_probe_rsp_tmpl(wma_handle, + (tpSendProbeRespParams)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_CLI_SET_CMD: + wma_process_cli_set_cmd(wma_handle, + (wda_cli_set_cmd_t *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_PDEV_IE_REQ: + wma_process_set_pdev_ie_req(wma_handle, + (struct set_ie_param *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#if !defined(REMOVE_PKT_LOG) + case WDA_PKTLOG_ENABLE_REQ: + wma_pktlog_wmi_send_cmd(wma_handle, + (struct ath_pktlog_wmi_params *) + msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif +#if defined(QCA_WIFI_FTM) + case WDA_FTM_CMD_REQ: + wma_process_ftm_command(wma_handle, + (struct ar6k_testmode_cmd_data *)msg->bodyptr); + break; +#endif + case WDA_ENTER_BMPS_REQ: + wma_enable_sta_ps_mode(wma_handle, + (tpEnablePsParams)msg->bodyptr); + break; + case WDA_EXIT_BMPS_REQ: + wma_disable_sta_ps_mode(wma_handle, + (tpDisablePsParams)msg->bodyptr); + break; + case WDA_ENTER_UAPSD_REQ: + wma_enable_uapsd_mode(wma_handle, + (tpEnableUapsdParams)msg->bodyptr); + break; + case WDA_EXIT_UAPSD_REQ: + wma_disable_uapsd_mode(wma_handle, + (tpDisableUapsdParams)msg->bodyptr); + break; + case WDA_SET_TX_POWER_REQ: + wma_set_tx_power(wma_handle, + (tpMaxTxPowerParams)msg->bodyptr); + break; + case WDA_SET_MAX_TX_POWER_REQ: + wma_set_max_tx_power(wma_handle, + (tpMaxTxPowerParams)msg->bodyptr); + break; + case WDA_SET_KEEP_ALIVE: + wma_set_keepalive_req(wma_handle, + (tSirKeepAliveReq *)msg->bodyptr); + break; +#ifdef FEATURE_WLAN_SCAN_PNO + case WDA_SET_PNO_REQ: + wma_config_pno(wma_handle, + (tpSirPNOScanReq)msg->bodyptr); + break; + + case WDA_SME_SCAN_CACHE_UPDATED: + wma_scan_cache_updated_ind(wma_handle, msg->bodyval); + break; +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case WDA_SET_PLM_REQ: + wma_config_plm(wma_handle, + (tpSirPlmReq)msg->bodyptr); + break; +#endif + case WDA_GET_STATISTICS_REQ: + wma_get_stats_req(wma_handle, + (tAniGetPEStatsReq *) msg->bodyptr); + break; + + case WDA_CONFIG_PARAM_UPDATE_REQ: + wma_update_cfg_params(wma_handle, + (tSirMsgQ *)msg); + break; + + case WDA_INIT_SCAN_REQ: + wma_init_scan_req(wma_handle, + (tInitScanParams *)msg->bodyptr); + break; + + case WDA_FINISH_SCAN_REQ: + wma_finish_scan_req(wma_handle, + (tFinishScanParams *)msg->bodyptr); + break; + case WDA_UPDATE_OP_MODE: + wma_process_update_opmode(wma_handle, + (tUpdateVHTOpMode *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_UPDATE_RX_NSS: + wma_process_update_rx_nss(wma_handle, + (tUpdateRxNss *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_11AC + case WDA_UPDATE_MEMBERSHIP: + wma_process_update_membership(wma_handle, + (tUpdateMembership *)msg->bodyptr); + break; + case WDA_UPDATE_USERPOS: + wma_process_update_userpos(wma_handle, + (tUpdateUserPos *)msg->bodyptr); + break; +#endif + case WDA_UPDATE_BEACON_IND: + wma_process_update_beacon_params(wma_handle, + (tUpdateBeaconParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + + case WDA_ADD_TS_REQ: + wma_add_ts_req(wma_handle, (tAddTsParams *)msg->bodyptr); + break; + + case WDA_DEL_TS_REQ: + wma_del_ts_req(wma_handle, (tDelTsParams *)msg->bodyptr); + break; + + case WDA_AGGR_QOS_REQ: + wma_aggr_qos_req(wma_handle, (tAggrAddTsParams *)msg->bodyptr); + break; + + case WDA_RECEIVE_FILTER_SET_FILTER_REQ: + wma_process_receive_filter_set_filter_req(wma_handle, + (tSirRcvPktFilterCfgType *)msg->bodyptr); + break; + + case WDA_RECEIVE_FILTER_CLEAR_FILTER_REQ: + wma_process_receive_filter_clear_filter_req(wma_handle, + (tSirRcvFltPktClearParam *)msg->bodyptr); + break; + + case WDA_WOWL_ADD_BCAST_PTRN: + wma_wow_add_pattern(wma_handle, + (tpSirWowlAddBcastPtrn)msg->bodyptr); + break; + case WDA_WOWL_DEL_BCAST_PTRN: + wma_wow_del_pattern(wma_handle, + (tpSirWowlDelBcastPtrn)msg->bodyptr); + break; + case WDA_WOWL_ENTER_REQ: + wma_wow_enter(wma_handle, + (tpSirHalWowlEnterParams)msg->bodyptr); + break; + case WDA_WOWL_EXIT_REQ: + wma_wow_exit(wma_handle, + (tpSirHalWowlExitParams)msg->bodyptr); + break; + case WDA_WLAN_SUSPEND_IND: + wma_suspend_req(wma_handle, + (tpSirWlanSuspendParam)msg->bodyptr); + break; + case WDA_8023_MULTICAST_LIST_REQ: + wma_process_mcbc_set_filter_req(wma_handle, + (tpSirRcvFltMcAddrList)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_GTK_OFFLOAD + case WDA_GTK_OFFLOAD_REQ: + wma_process_gtk_offload_req( + wma_handle, + (tpSirGtkOffloadParams)msg->bodyptr); + break; + + case WDA_GTK_OFFLOAD_GETINFO_REQ: + wma_process_gtk_offload_getinfo_req( + wma_handle, + (tpSirGtkOffloadGetInfoRspParams)msg->bodyptr); + break; +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ +#ifdef FEATURE_OEM_DATA_SUPPORT + case WDA_START_OEM_DATA_REQ: + wma_start_oem_data_req(wma_handle, + (tStartOemDataReq *)msg->bodyptr); + break; +#endif /* FEATURE_OEM_DATA_SUPPORT */ + case WDA_SET_HOST_OFFLOAD: + wma_enable_arp_ns_offload(wma_handle, (tpSirHostOffloadReq)msg->bodyptr, true); + break; +#ifdef WLAN_NS_OFFLOAD + case WDA_SET_NS_OFFLOAD: + wma_enable_arp_ns_offload(wma_handle, (tpSirHostOffloadReq)msg->bodyptr, false); + break; +#endif /*WLAN_NS_OFFLOAD */ + case WDA_ROAM_SCAN_OFFLOAD_REQ: + /* + * Main entry point or roaming directives from CSR. + */ + wma_process_roam_scan_req(wma_handle, + (tSirRoamOffloadScanReq *)msg->bodyptr); + break; + + case WDA_RATE_UPDATE_IND: + wma_process_rate_update_indicate(wma_handle, (tSirRateUpdateInd *)msg->bodyptr); + break; + +#ifdef FEATURE_WLAN_TDLS + case WDA_UPDATE_FW_TDLS_STATE: + wma_update_fw_tdls_state(wma_handle, + (t_wma_tdls_params *)msg->bodyptr); + break; + case WDA_UPDATE_TDLS_PEER_STATE: + wma_update_tdls_peer_state(wma_handle, + (tTdlsPeerStateParams *)msg->bodyptr); + break; + case WDA_TDLS_SET_OFFCHAN_MODE: + wma_set_tdls_offchan_mode(wma_handle, + (tTdlsChanSwitchParams*)msg->bodyptr); + break; +#endif /* FEATURE_WLAN_TDLS */ + case WDA_ADD_PERIODIC_TX_PTRN_IND: + wma_ProcessAddPeriodicTxPtrnInd(wma_handle, + (tSirAddPeriodicTxPtrn *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_DEL_PERIODIC_TX_PTRN_IND: + wma_ProcessDelPeriodicTxPtrnInd(wma_handle, + (tSirDelPeriodicTxPtrn *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_TX_POWER_LIMIT: + wma_ProcessTxPowerLimits(wma_handle, + (tSirTxPowerLimit *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef FEATURE_WLAN_LPHB + case WDA_LPHB_CONF_REQ: + wma_process_lphb_conf_req(wma_handle, (tSirLPHBReq *)msg->bodyptr); + break; +#endif + +#ifdef FEATURE_WLAN_CH_AVOID + case WDA_CH_AVOID_UPDATE_REQ: + wma_process_ch_avoid_update_req(wma_handle, + (tSirChAvoidUpdateReq *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + case WDA_SET_AUTO_SHUTDOWN_TIMER_REQ: + wma_set_auto_shutdown_timer_req(wma_handle, + msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif + case WDA_DHCP_START_IND: + case WDA_DHCP_STOP_IND: + wma_process_dhcp_ind(wma_handle, + (tAniDHCPInd *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + + + case WDA_INIT_THERMAL_INFO_CMD: + wma_process_init_thermal_info(wma_handle, (t_thermal_mgmt *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + + case WDA_SET_THERMAL_LEVEL: + wma_process_set_thermal_level(wma_handle, msg->bodyval); + break; + + case WDA_INIT_BAD_PEER_TX_CTL_INFO_CMD: + wma_process_init_bad_peer_tx_ctl_info(wma_handle, + (struct t_bad_peer_txtcl_config *) msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + + case WDA_SET_P2P_GO_NOA_REQ: + wma_process_set_p2pgo_noa_Req(wma_handle, + (tP2pPsParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_MIMOPS_REQ: + wma_process_set_mimops_req(wma_handle, (tSetMIMOPS *) msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_SAP_INTRABSS_DIS: + wma_set_vdev_intrabss_fwd(wma_handle, (tDisableIntraBssFwd *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_FW_STATS_IND: + wma_fw_stats_ind(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_GET_LINK_SPEED: + wma_get_link_speed(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_GET_RSSI: + wma_get_rssi(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_MODEM_POWER_STATE_IND: + wma_notify_modem_power_state(wma_handle, + (tSirModemPowerStateInd *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_VDEV_STOP_IND: + wma_vdev_stop_ind(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_WLAN_RESUME_REQ: + wma_resume_req(wma_handle, false); + break; + +#ifdef WLAN_FEATURE_STATS_EXT + case WDA_STATS_EXT_REQUEST: + wma_stats_ext_req(wma_handle, + (tpStatsExtRequest)(msg->bodyptr)); + vos_mem_free(msg->bodyptr); + break; +#endif + case WDA_HIDDEN_SSID_VDEV_RESTART: + wma_hidden_ssid_vdev_restart(wma_handle, + (tHalHiddenSsidVdevRestart *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + case WDA_WLAN_EXT_WOW: + wma_enable_ext_wow(wma_handle, + (tSirExtWoWParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_WLAN_SET_APP_TYPE1_PARAMS: + wma_set_app_type1_params_in_fw(wma_handle, + (tSirAppType1Params *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_WLAN_SET_APP_TYPE2_PARAMS: + wma_set_app_type2_params_in_fw(wma_handle, + (tSirAppType2Params *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif + case WDA_VDEV_START_RSP_IND: + wma_vdev_start_rsp_ind(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_ROAM_PREAUTH_IND: + wma_roam_preauth_ind(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_TBTT_UPDATE_IND: + wma_tbtt_update_ind(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef FEATURE_WLAN_EXTSCAN + case WDA_EXTSCAN_START_REQ: + wma_start_extscan(wma_handle, + (tSirWifiScanCmdReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_STOP_REQ: + wma_stop_extscan(wma_handle, + (tSirExtScanStopReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_SET_BSSID_HOTLIST_REQ: + wma_extscan_start_hotlist_monitor(wma_handle, + (tSirExtScanSetBssidHotListReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_RESET_BSSID_HOTLIST_REQ: + wma_extscan_stop_hotlist_monitor(wma_handle, + (tSirExtScanResetBssidHotlistReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_SET_SSID_HOTLIST_REQ: + wma_set_ssid_hotlist(wma_handle, + (struct sir_set_ssid_hotlist_request *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_SET_SIGNF_CHANGE_REQ: + wma_extscan_start_change_monitor(wma_handle, + (tSirExtScanSetSigChangeReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_RESET_SIGNF_CHANGE_REQ: + wma_extscan_stop_change_monitor(wma_handle, + (tSirExtScanResetSignificantChangeReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_GET_CACHED_RESULTS_REQ: + wma_extscan_get_cached_results(wma_handle, + (tSirExtScanGetCachedResultsReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_GET_CAPABILITIES_REQ: + wma_extscan_get_capabilities(wma_handle, + (tSirGetExtScanCapabilitiesReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_EPNO_LIST_REQ: + wma_set_epno_network_list(wma_handle, + (struct wifi_epno_params *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_PASSPOINT_LIST_REQ: + /* Issue reset passpoint network list first and clear + * the entries */ + wma_reset_passpoint_network_list(wma_handle, + (struct wifi_passpoint_req *)msg->bodyptr); + + wma_set_passpoint_network_list(wma_handle, + (struct wifi_passpoint_req *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_RESET_PASSPOINT_LIST_REQ: + wma_reset_passpoint_network_list(wma_handle, + (struct wifi_passpoint_req *)msg->bodyptr); + break; + case WDA_EXTSCAN_STATUS_IND: + wma_extscan_rsp_handler(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_EXTSCAN_OPERATION_IND: + wma_extscan_operations_ind_handler(wma_handle, + msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif + case WDA_SET_SCAN_MAC_OUI_REQ: + wma_scan_probe_setoui(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + case WDA_LINK_LAYER_STATS_CLEAR_REQ: + wma_process_ll_stats_clearReq(wma_handle, + (tpSirLLStatsClearReq)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_LINK_LAYER_STATS_SET_REQ: + wma_process_ll_stats_setReq(wma_handle, + (tpSirLLStatsSetReq)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_LINK_LAYER_STATS_GET_REQ: + wma_process_ll_stats_getReq(wma_handle, + (tpSirLLStatsGetReq)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + case SIR_HAL_UNIT_TEST_CMD: + wma_process_unit_test_cmd(wma_handle, + (t_wma_unit_test_cmd *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WDA_ROAM_OFFLOAD_SYNCH_CNF: + wma_process_roam_synch_complete(wma_handle, + (tSirSmeRoamOffloadSynchCnf *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_ROAM_OFFLOAD_SYNCH_FAIL: + wma_process_roam_synch_fail(wma_handle, + (tSirRoamOffloadSynchFail *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case SIR_HAL_ROAM_INVOKE: + wma_process_roam_invoke(wma_handle, + (t_wma_roam_invoke_cmd *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif +#ifdef WLAN_FEATURE_NAN + case WDA_NAN_REQUEST: + wma_nan_req(wma_handle, + (tNanRequest *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif + case SIR_HAL_SET_BASE_MACADDR_IND: + wma_set_base_macaddr_indicate(wma_handle, + (tSirMacAddr *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_LINK_STATUS_GET_REQ: + wma_process_link_status_req(wma_handle, + (tAniGetLinkStatus *)msg->bodyptr); + break; + case WDA_GET_LINK_STATUS_RSP_IND: + wma_link_status_rsp(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_GET_TEMPERATURE_REQ: + wma_get_temperature(wma_handle); + vos_mem_free(msg->bodyptr); + break; +#ifdef DHCP_SERVER_OFFLOAD + case WDA_SET_DHCP_SERVER_OFFLOAD_CMD: + wma_process_dhcpserver_offload(wma_handle, + (tSirDhcpSrvOffloadInfo *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + case WDA_LED_FLASHING_REQ: + wma_set_led_flashing(wma_handle, + (tSirLedFlashingReq *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif + case WDA_IPA_OFFLOAD_ENABLE_DISABLE: + wma_ipa_offload_enable_disable(wma_handle, + (struct sir_ipa_offload_enable_disable *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef MDNS_OFFLOAD + case WDA_SET_MDNS_OFFLOAD_CMD: + wma_set_mdns_offload(wma_handle, + (tSirMDNSOffloadInfo *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_MDNS_FQDN_CMD: + wma_set_mdns_fqdn(wma_handle, + (tSirMDNSFqdnInfo *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_MDNS_RESPONSE_CMD: + wma_set_mdns_response(wma_handle, + (tSirMDNSResponseInfo *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_GET_MDNS_STATUS_CMD: + wma_get_mdns_status(wma_handle, (A_UINT32 *) msg->bodyptr); + break; +#endif /* MDNS_OFFLOAD */ +#ifdef SAP_AUTH_OFFLOAD + case WDA_SET_SAP_AUTH_OFL: + wma_process_sap_auth_offload(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_CLIENT_BLOCK_INFO: + wma_process_client_block_info(wma_handle, msg->bodyptr); + if (msg->bodyptr) + vos_mem_free(msg->bodyptr); + break; +#endif /* SAP_AUTH_OFFLOAD */ +#ifdef WLAN_FEATURE_APFIND + case WDA_APFIND_SET_CMD: + wma_apfind_set_cmd(wma_handle, + (struct hal_apfind_request *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_APFIND */ + case WDA_OCB_SET_CONFIG_CMD: + wma_ocb_set_config_req(wma_handle, + (struct sir_ocb_config *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_OCB_SET_UTC_TIME_CMD: + wma_ocb_set_utc_time(wma_handle, + (struct sir_ocb_utc *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_OCB_START_TIMING_ADVERT_CMD: + wma_ocb_start_timing_advert(wma_handle, + (struct sir_ocb_timing_advert *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_OCB_STOP_TIMING_ADVERT_CMD: + wma_ocb_stop_timing_advert(wma_handle, + (struct sir_ocb_timing_advert *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_DCC_CLEAR_STATS_CMD: + wma_dcc_clear_stats(wma_handle, + (struct sir_dcc_clear_stats *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_OCB_GET_TSF_TIMER_CMD: + wma_ocb_get_tsf_timer(wma_handle, + (struct sir_ocb_get_tsf_timer *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_DCC_GET_STATS_CMD: + wma_dcc_get_stats(wma_handle, + (struct sir_dcc_get_stats *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_DCC_UPDATE_NDL_CMD: + wma_dcc_update_ndl(wma_handle, + (struct sir_dcc_update_ndl *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +#ifdef FEATURE_RUNTIME_PM + case WDA_RUNTIME_PM_SUSPEND_IND: + wma_suspend_req(wma_handle, NULL); + break; + case WDA_RUNTIME_PM_RESUME_IND: + wma_resume_req(wma_handle, true); + break; +#endif + case SIR_HAL_SET_MAS: + wma_process_set_mas(wma_handle, + (u_int32_t *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case SIR_HAL_SET_MIRACAST: + wma_process_set_miracast(wma_handle, + (u_int32_t *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_GET_FW_STATUS_REQ: + wma_send_echo_request(wma_handle); + break; + case SIR_HAL_CONFIG_STATS_FACTOR: + wma_config_stats_factor(wma_handle, + (struct sir_stats_avg_factor *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case SIR_HAL_CONFIG_GUARD_TIME: + wma_config_guard_time(wma_handle, + (struct sir_guard_time_request *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_FW_MEM_DUMP_REQ: + wma_process_fw_mem_dump_req(wma_handle, + (struct fw_dump_req*)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case SIR_HAL_START_STOP_LOGGING: + wma_set_wifi_start_packet_stats(wma_handle, + (struct sir_wifi_start_log *)msg->bodyptr); + wma_enable_specific_fw_logs(wma_handle, + (struct sir_wifi_start_log *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_TSF_GPIO_PIN: + wma_set_tsf_gpio_pin(wma_handle, msg->bodyval); + break; + case SIR_HAL_FLUSH_LOG_TO_FW: + wma_send_flush_logs_to_fw(wma_handle); + /* Body ptr is NULL here */ + break; + case WDA_SET_IE_INFO: + wma_process_set_ie_info(wma_handle, + (struct vdev_ie_info *) msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_RSSI_MONITOR_REQ: + wma_set_rssi_monitoring(wma_handle, + (struct rssi_monitor_req *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_SET_UDP_RESP_OFFLOAD: + wma_send_udp_resp_offload_cmd(wma_handle, + (struct udp_resp_offload *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_UPDATE_WEP_DEFAULT_KEY: + wma_update_wep_default_key(wma_handle, + (struct wep_update_default_key_idx *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + default: + WMA_LOGD("unknow msg type %x", msg->type); + /* Do Nothing? MSG Body should be freed at here */ + if(NULL != msg->bodyptr) { + vos_mem_free(msg->bodyptr); + } + } +end: + WMA_LOGI("%s: Exit", __func__); + return vos_status ; +} + +static int wma_scan_event_callback(WMA_HANDLE handle, u_int8_t *data, + u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_SCAN_EVENTID_param_tlvs *param_buf = NULL; + wmi_scan_event_fixed_param *wmi_event = NULL; + tSirScanOffloadEvent *scan_event; + u_int8_t vdev_id; + v_U32_t scan_id; + u_int8_t *buf; + vos_msg_t vos_msg = {0}; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + param_buf = (WMI_SCAN_EVENTID_param_tlvs *) data; + wmi_event = param_buf->fixed_param; + vdev_id = wmi_event->vdev_id; + scan_id = wma_handle->interfaces[vdev_id].scan_info.scan_id; + + adf_os_spin_lock_bh(&wma_handle->roam_preauth_lock); + if (wma_handle->roam_preauth_scan_id == wmi_event->scan_id) { + /* This is the scan requested by roam preauth set_channel operation */ + adf_os_spin_unlock_bh(&wma_handle->roam_preauth_lock); + + if (wmi_event->event & WMI_SCAN_FINISH_EVENTS) { + WMA_LOGE(" roam scan complete - scan_id %x, vdev_id %x", + wmi_event->scan_id, vdev_id); + wma_reset_scan_info(wma_handle, vdev_id); + } + + buf = vos_mem_malloc(sizeof(wmi_scan_event_fixed_param)); + if (!buf) { + WMA_LOGE("%s: Memory alloc failed for roam preauth ind", + __func__); + return -ENOMEM; + } + vos_mem_zero(buf, sizeof(wmi_scan_event_fixed_param)); + vos_mem_copy(buf, (u_int8_t *)wmi_event, + sizeof(wmi_scan_event_fixed_param)); + + vos_msg.type = WDA_ROAM_PREAUTH_IND; + vos_msg.bodyptr = buf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg)) { + WMA_LOGE("%s: Failed to post WDA_ROAM_PREAUTH_IND msg", + __func__); + vos_mem_free(buf); + return -1; + } + WMA_LOGD("%s: WDA_ROAM_PREAUTH_IND posted", __func__); + return 0; + } + adf_os_spin_unlock_bh(&wma_handle->roam_preauth_lock); + + scan_event = (tSirScanOffloadEvent *) vos_mem_malloc + (sizeof(tSirScanOffloadEvent)); + if (!scan_event) { + WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent"); + return -ENOMEM; + } + + scan_event->event = wmi_event->event; + + WMA_LOGI("WMA <-- wmi_scan_event : event %u, scan_id %u, " + "freq %u, reason %u", + wmi_event->event, wmi_event->scan_id, + wmi_event->channel_freq, wmi_event->reason); + + scan_event->scanId = wmi_event->scan_id; + scan_event->chanFreq = wmi_event->channel_freq; + scan_event->p2pScanType = + wma_handle->interfaces[vdev_id].scan_info.p2p_scan_type; + scan_event->sessionId = vdev_id; + + if (wmi_event->reason == WMI_SCAN_REASON_COMPLETED || + wmi_event->reason == WMI_SCAN_REASON_TIMEDOUT) + scan_event->reasonCode = eSIR_SME_SUCCESS; + else + scan_event->reasonCode = eSIR_SME_SCAN_FAILED; + + switch (wmi_event->event) { + case WMI_SCAN_EVENT_COMPLETED: + case WMI_SCAN_EVENT_DEQUEUED: + /* + * return success always so that SME can pick whatever scan + * results is available in scan cache(due to partial or + * aborted scan) + */ + scan_event->event = WMI_SCAN_EVENT_COMPLETED; + scan_event->reasonCode = eSIR_SME_SUCCESS; + break; + case WMI_SCAN_EVENT_START_FAILED: + scan_event->event = WMI_SCAN_EVENT_COMPLETED; + scan_event->reasonCode = eSIR_SME_SCAN_FAILED; + break; + case WMI_SCAN_EVENT_PREEMPTED: + WMA_LOGW("%s: Unhandled Scan Event WMI_SCAN_EVENT_PREEMPTED", __func__); + break; + case WMI_SCAN_EVENT_RESTARTED: + WMA_LOGW("%s: Unhandled Scan Event WMI_SCAN_EVENT_RESTARTED", __func__); + break; + } + + /* Stop the scan completion timeout if the event is WMI_SCAN_EVENT_COMPLETED */ + if (scan_event->event == (tSirScanEventType)WMI_SCAN_EVENT_COMPLETED) { + WMA_LOGE(" scan complete - scan_id %x, vdev_id %x", + wmi_event->scan_id, vdev_id); + /* + * first stop the timer then reset scan info, else there is a + * race condition between, timeout handler in host and reset + * operation here. because of that, sometime timeout handler + * triggers and scan ID mismatch messages is printed. + */ + vos_status = vos_timer_stop(&wma_handle->wma_scan_comp_timer); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to stop the scan completion timeout"); + vos_mem_free(scan_event); + return -EPERM; + } + if (wmi_event->scan_id == scan_id) + wma_reset_scan_info(wma_handle, vdev_id); + else + WMA_LOGE("Scan id not matched for SCAN COMPLETE event"); + } + + wma_send_msg(wma_handle, WDA_RX_SCAN_EVENT, (void *) scan_event, 0) ; + return 0; +} + +static void wma_mgmt_tx_ack_work_handler(struct work_struct *ack_work) +{ + struct wma_tx_ack_work_ctx *work; + tp_wma_handle wma_handle; + pWDAAckFnTxComp ack_cb; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_WDA, NULL)) { + WMA_LOGE("%s: Driver load/unload in progress", __func__); + return; + } + + work = container_of(ack_work, struct wma_tx_ack_work_ctx, ack_cmp_work); + wma_handle = work->wma_handle; + ack_cb = wma_handle->umac_ota_ack_cb[work->sub_type]; + + WMA_LOGD("Tx Ack Cb SubType %d Status %d", + work->sub_type, work->status); + + /* Call the Ack Cb registered by UMAC */ + ack_cb((tpAniSirGlobal)(wma_handle->mac_context), + work->status ? 0 : 1); + + adf_os_mem_free(work); + wma_handle->ack_work_ctx = NULL; +} + +/* function : wma_mgmt_tx_comp_conf_ind + * Description : Post mgmt tx complete indication to PE. + * Args : + wma_handle : Pointer to WMA handle + * sub_type : Tx mgmt frame sub type + * status : Mgmt frame tx status + * Returns : + */ +static void +wma_mgmt_tx_comp_conf_ind(tp_wma_handle wma_handle, u_int8_t sub_type, + int32_t status) +{ + int32_t tx_comp_status; + + tx_comp_status = status ? 0 : 1; + if(sub_type == SIR_MAC_MGMT_DISASSOC) { + wma_send_msg(wma_handle, WDA_DISASSOC_TX_COMP, NULL, tx_comp_status); + } + else if(sub_type == SIR_MAC_MGMT_DEAUTH) { + wma_send_msg(wma_handle, WDA_DEAUTH_TX_COMP, NULL, tx_comp_status); + } +} + +/** + * wma_mgmt_tx_ack_comp_hdlr - handles tx ack mgmt completion + * @context: context with which the handler is registered + * @netbuf: tx mgmt nbuf + * @err: status of tx completion + * + * This is the cb registered with TxRx for + * Ack Complete + */ +static void +wma_mgmt_tx_ack_comp_hdlr(void *wma_context, + adf_nbuf_t netbuf, int32_t status) +{ + tpSirMacFrameCtl pFc = + (tpSirMacFrameCtl)(adf_nbuf_data(netbuf)); + tp_wma_handle wma_handle = (tp_wma_handle)wma_context; + + if(wma_handle && wma_handle->umac_ota_ack_cb[pFc->subType]) { + if((pFc->subType == SIR_MAC_MGMT_DISASSOC) || + (pFc->subType == SIR_MAC_MGMT_DEAUTH)) { + wma_mgmt_tx_comp_conf_ind(wma_handle, (u_int8_t)pFc->subType, + status); + } + else { + struct wma_tx_ack_work_ctx *ack_work; + + ack_work = + adf_os_mem_alloc(NULL, sizeof(struct wma_tx_ack_work_ctx)); + + if(ack_work) { +#ifdef CONFIG_CNSS + cnss_init_work(&ack_work->ack_cmp_work, + wma_mgmt_tx_ack_work_handler); +#else + INIT_WORK(&ack_work->ack_cmp_work, + wma_mgmt_tx_ack_work_handler); +#endif + ack_work->wma_handle = wma_handle; + ack_work->sub_type = pFc->subType; + ack_work->status = status; + + /* Schedue the Work */ + schedule_work(&ack_work->ack_cmp_work); + } + } + } +} + +/** + * wma_mgmt_tx_dload_comp_hldr - handles tx mgmt completion + * @context: context with which the handler is registered + * @netbuf: tx mgmt nbuf + * @err: status of tx completion + */ +static void +wma_mgmt_tx_dload_comp_hldr(void *wma_context, adf_nbuf_t netbuf, + int32_t status) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + tp_wma_handle wma_handle = (tp_wma_handle)wma_context; + void *mac_context = wma_handle->mac_context; + + WMA_LOGD("Tx Complete Status %d", status); + + if (!wma_handle->tx_frm_download_comp_cb) { + WMA_LOGE("Tx Complete Cb not registered by umac"); + return; + } + + /* Call Tx Mgmt Complete Callback registered by umac */ + wma_handle->tx_frm_download_comp_cb(mac_context, + netbuf, 0); + + /* Reset Callback */ + wma_handle->tx_frm_download_comp_cb = NULL; + + /* Set the Tx Mgmt Complete Event */ + vos_status = vos_event_set( + &wma_handle->tx_frm_download_comp_event); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + WMA_LOGP("%s: Event Set failed - tx_frm_comp_event", __func__); +} + +/** + * wma_tx_attach - attaches tx fn with underlying layer + * @pwmaCtx: wma context + */ +VOS_STATUS wma_tx_attach(tp_wma_handle wma_handle) +{ + /* Get the Vos Context */ + pVosContextType vos_handle = + (pVosContextType)(wma_handle->vos_context); + + /* Get the txRx Pdev handle */ + ol_txrx_pdev_handle txrx_pdev = + (ol_txrx_pdev_handle)(vos_handle->pdev_txrx_ctx); + + /* Register for Tx Management Frames */ + wdi_in_mgmt_tx_cb_set(txrx_pdev, GENERIC_NODOWLOAD_ACK_COMP_INDEX, + NULL, wma_mgmt_tx_ack_comp_hdlr,wma_handle); + + wdi_in_mgmt_tx_cb_set(txrx_pdev, GENERIC_DOWNLD_COMP_NOACK_COMP_INDEX, + wma_mgmt_tx_dload_comp_hldr, NULL, wma_handle); + + wdi_in_mgmt_tx_cb_set(txrx_pdev, GENERIC_DOWNLD_COMP_ACK_COMP_INDEX, + wma_mgmt_tx_dload_comp_hldr, + wma_mgmt_tx_ack_comp_hdlr,wma_handle); + + /* Store the Mac Context */ + wma_handle->mac_context = vos_handle->pMACContext; + + return VOS_STATUS_SUCCESS; +} + +/** + * wma_tx_detach - detaches mgmt fn with underlying layer + * Deregister with TxRx for Tx Mgmt Download and Ack completion. + * @tp_wma_handle: wma context + */ +static VOS_STATUS wma_tx_detach(tp_wma_handle wma_handle) +{ + u_int32_t frame_index = 0; + + /* Get the Vos Context */ + pVosContextType vos_handle = + (pVosContextType)(wma_handle->vos_context); + + /* Get the txRx Pdev handle */ + ol_txrx_pdev_handle txrx_pdev = + (ol_txrx_pdev_handle)(vos_handle->pdev_txrx_ctx); + + if (txrx_pdev) { + /* Deregister with TxRx for Tx Mgmt completion call back */ + for (frame_index = 0; frame_index < FRAME_INDEX_MAX; + frame_index++) { + wdi_in_mgmt_tx_cb_set(txrx_pdev, frame_index, NULL, NULL, + txrx_pdev); + } + } + /* Destroy Tx Frame Complete event */ + vos_event_destroy(&wma_handle->tx_frm_download_comp_event); + + /* Tx queue empty check event (dummy event) */ + vos_event_destroy(&wma_handle->tx_queue_empty_event); + + /* Reset Tx Frm Callbacks */ + wma_handle->tx_frm_download_comp_cb = NULL; + + /* Reset Tx Data Frame Ack Cb */ + wma_handle->umac_data_ota_ack_cb = NULL; + + /* Reset last Tx Data Frame nbuf ptr */ + wma_handle->last_umac_data_nbuf = NULL; + + return VOS_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static void wma_roam_ho_fail_handler(tp_wma_handle wma, u_int32_t vdev_id) +{ + tSirSmeHOFailureInd *ho_failure_ind; + vos_msg_t sme_msg = {0}; + VOS_STATUS vos_status; + + ho_failure_ind = vos_mem_malloc(sizeof(tSirSmeHOFailureInd)); + + if (NULL == ho_failure_ind) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + ho_failure_ind->sessionId = vdev_id; + sme_msg.type = eWNI_SME_HO_FAIL_IND; + sme_msg.bodyptr = ho_failure_ind; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE("Fail to post eWNI_SME_HO_FAIL_IND msg to SME"); + vos_mem_free(ho_failure_ind); + return; + } + return; +} +#endif + +/* function : wma_roam_better_ap_handler + * Description : Handler for WMI_ROAM_REASON_BETTER_AP event from roam firmware in Rome. + * : This event means roam algorithm in Rome has found a better matching + * : candidate AP. The indication is sent through tl_shim as by repeating + * : the last beacon. Hence this routine calls a tlshim routine. + * Args : + * Returns : + */ +static void wma_roam_better_ap_handler(tp_wma_handle wma, u_int32_t vdev_id) +{ + VOS_STATUS ret; + /* abort existing scans from GUI, but not roaming preauth scan */ + if (wma->interfaces[vdev_id].scan_info.scan_id != 0 && + (wma->interfaces[vdev_id].scan_info.scan_id & + WMA_HOST_ROAM_SCAN_REQID_PREFIX) != + WMA_HOST_ROAM_SCAN_REQID_PREFIX) { + tAbortScanParams abortScan; + abortScan.SessionId = vdev_id; + wma_stop_scan(wma, &abortScan); + } + ret = tlshim_mgmt_roam_event_ind(wma->vos_context, vdev_id); +} + +/* function : wma_roam_event_callback + * Description : Handler for all events from roam engine in firmware + * Args : + * Returns : + */ + +static int wma_roam_event_callback(WMA_HANDLE handle, u_int8_t *event_buf, + u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_ROAM_EVENTID_param_tlvs *param_buf; + wmi_roam_event_fixed_param *wmi_event; + + param_buf = (WMI_ROAM_EVENTID_param_tlvs *) event_buf; + if (!param_buf) { + WMA_LOGE("Invalid roam event buffer"); + return -EINVAL; + } + + wmi_event = param_buf->fixed_param; + WMA_LOGD("%s: Reason %x for vdevid %x, rssi %d", + __func__, wmi_event->reason, wmi_event->vdev_id, wmi_event->rssi); + + switch(wmi_event->reason) { + case WMI_ROAM_REASON_BMISS: + WMA_LOGD("Beacon Miss for vdevid %x", + wmi_event->vdev_id); + wma_beacon_miss_handler(wma_handle, wmi_event->vdev_id, + wmi_event->rssi); + break; + case WMI_ROAM_REASON_BETTER_AP: + WMA_LOGD("%s:Better AP found for vdevid %x, rssi %d", __func__, + wmi_event->vdev_id, wmi_event->rssi); + wma_handle->suitable_ap_hb_failure = FALSE; + wma_roam_better_ap_handler(wma_handle, wmi_event->vdev_id); + break; + case WMI_ROAM_REASON_SUITABLE_AP: + wma_handle->suitable_ap_hb_failure = TRUE; + wma_handle->suitable_ap_hb_failure_rssi = wmi_event->rssi; + WMA_LOGD("%s:Bmiss scan AP found for vdevid %x, rssi %d", __func__, + wmi_event->vdev_id, wmi_event->rssi); + wma_roam_better_ap_handler(wma_handle, wmi_event->vdev_id); + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WMI_ROAM_REASON_HO_FAILED: + WMA_LOGE("LFR3:Hand-Off Failed for vdevid %x", + wmi_event->vdev_id); + wma_roam_ho_fail_handler(wma_handle, wmi_event->vdev_id); + break; +#endif + default: + WMA_LOGD("%s:Unhandled Roam Event %x for vdevid %x", __func__, + wmi_event->reason, wmi_event->vdev_id); + break; + } + return 0; +} + +/** + * wma_smps_force_mode_callback() - SMPS force command event + * handler + * @handle: WMA handle + * @event_buf: event buffer + * @len: length of event data + * + * Return: 0 for success non-zero for failure + */ +static int wma_smps_force_mode_callback(WMA_HANDLE handle, + uint8_t *event_buf, + uint32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID_param_tlvs *param_buf; + wmi_sta_smps_force_mode_complete_event_fixed_param *wmi_event; + struct sir_smps_force_mode_event *smps_ind; + + param_buf = + (WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID_param_tlvs *) + event_buf; + if (!param_buf) { + WMA_LOGE("Invalid smps force mode event buffer"); + return -EINVAL; + } + + wmi_event = param_buf->fixed_param; + WMA_LOGD("%s: vdev id %x status %x", + __func__, wmi_event->vdev_id, wmi_event->status); + + smps_ind = vos_mem_malloc(sizeof(*smps_ind)); + + if (NULL == smps_ind) { + WMA_LOGE("%s: memory alloc failed for SMPS force mode event", + __func__); + return -ENOMEM; + } + smps_ind->message_type = WDA_SMPS_FORCE_MODE_IND; + smps_ind->length = sizeof(struct sir_smps_force_mode_event); + smps_ind->vdev_id = wmi_event->vdev_id; + smps_ind->status = wmi_event->status; + + wma_send_msg(wma_handle, WDA_SMPS_FORCE_MODE_IND, smps_ind, 0); + + return 0; +} + +#ifdef FEATURE_WLAN_SCAN_PNO + +/* Record NLO match event comes from FW. It's a indication that + * one of the profile is matched. + */ +static int wma_nlo_match_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + wmi_nlo_event *nlo_event; + WMI_NLO_MATCH_EVENTID_param_tlvs *param_buf = + (WMI_NLO_MATCH_EVENTID_param_tlvs *) event; + struct wma_txrx_node *node; + + if (!param_buf) { + WMA_LOGE("Invalid NLO match event buffer"); + return -EINVAL; + } + + nlo_event = param_buf->fixed_param; + WMA_LOGD("PNO match event received for vdev %d", + nlo_event->vdev_id); + + node = &wma->interfaces[nlo_event->vdev_id]; + if (node) + node->nlo_match_evt_received = TRUE; + + vos_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_PNO); + + return 0; +} + +/* Handles NLO scan completion event. */ +static int wma_nlo_scan_cmp_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + wmi_nlo_event *nlo_event; + WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs *param_buf = + (WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs *) event; + tSirScanOffloadEvent *scan_event; + struct wma_txrx_node *node; + + if (!param_buf) { + WMA_LOGE("Invalid NLO scan comp event buffer"); + return -EINVAL; + } + + nlo_event = param_buf->fixed_param; + WMA_LOGD("PNO scan completion event received for vdev %d", + nlo_event->vdev_id); + + node = &wma->interfaces[nlo_event->vdev_id]; + + /* Handle scan completion event only after NLO match event. */ + if (!node || !node->nlo_match_evt_received) { + + WMA_LOGD("NLO match not received skipping PNO complete ind for vdev %d", + nlo_event->vdev_id); + goto skip_pno_cmp_ind; + } + vos_wake_lock_release(&wma->pno_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_PNO); + + scan_event = (tSirScanOffloadEvent *) vos_mem_malloc( + sizeof(tSirScanOffloadEvent)); + if (scan_event) { + /* Posting scan completion msg would take scan cache result + * from LIM module and update in scan cache maintained in SME.*/ + WMA_LOGD("Posting Scan completion to umac"); + vos_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_PNO); + vos_mem_zero(scan_event, sizeof(tSirScanOffloadEvent)); + scan_event->reasonCode = eSIR_SME_SUCCESS; + scan_event->event = SCAN_EVENT_COMPLETED; + scan_event->sessionId = nlo_event->vdev_id; + wma_send_msg(wma, WDA_RX_SCAN_EVENT, + (void *) scan_event, 0); + } else { + WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent"); + } + +skip_pno_cmp_ind: + return 0; +} + +#endif +#ifdef WLAN_FEATURE_APFIND +/* Record APFIND event comes from FW. + */ +static int wma_apfind_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + wmi_apfind_event_hdr *apfind_event_hdr; + WMI_APFIND_EVENTID_param_tlvs *param_buf = + (WMI_APFIND_EVENTID_param_tlvs *) event; + u_int8_t *buf; + u_int8_t ssid_tmp[WMI_MAX_SSID_LEN + 1]; + + if (!param_buf) { + WMA_LOGE("Invalid APFIND event buffer"); + return -EINVAL; + } + + apfind_event_hdr = param_buf->hdr; + WMA_LOGD("APFIND event received, id=%d, data_length=%d", + apfind_event_hdr->event_type, apfind_event_hdr->data_len); + buf = param_buf->data; + A_MEMZERO(ssid_tmp, sizeof(ssid_tmp)); + A_MEMCPY(ssid_tmp, buf, sizeof(ssid_tmp)); + WMA_LOGD("%s, APFIND match, dump ssid=%s\n", __func__, ssid_tmp); + + buf = ¶m_buf->data[WMI_MAX_SSID_LEN]; + WMA_LOGD("%s, APFIND dump mac=0x%08X-0x%08X\n", + __func__, *(u_int32_t *)buf, *(u_int32_t *)(buf + sizeof(u_int32_t))); + return 0; +} +#endif /* WLAN_FEATURE_APFIND */ +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) +/* Handle TX pause event from FW */ +static int wma_mcc_vdev_tx_pause_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf; + wmi_tx_pause_event_fixed_param *wmi_event; + u_int8_t vdev_id; + A_UINT32 vdev_map; + + param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *) event; + if (!param_buf) + { + WMA_LOGE("Invalid roam event buffer"); + return -EINVAL; + } + + if (wma_get_wow_bus_suspend(wma)) { + WMA_LOGD(" Suspend is in progress: Pause/Unpause Tx is NoOp"); + return 0; + } + + wmi_event = param_buf->fixed_param; + vdev_map = wmi_event->vdev_map; + /* FW mapped vdev from ID + * vdev_map = (1 << vdev_id) + * So, host should unmap to ID */ + for (vdev_id = 0; vdev_map != 0; vdev_id++) + { + if (!(vdev_map & 0x1)) + { + /* No Vdev */ + } + else + { + if (!wma->interfaces[vdev_id].handle) + { + WMA_LOGE("%s: invalid vdev ID %d", __func__, vdev_id); + /* Test Next VDEV */ + vdev_map >>= 1; + continue; + } + + /* PAUSE action, add bitmap */ + if (ACTION_PAUSE == wmi_event->action) + { + /* + * Now only support per-dev pause so it is not necessary + * to pause a paused queue again. + */ + if (!wma->interfaces[vdev_id].pause_bitmap) + wdi_in_vdev_pause(wma->interfaces[vdev_id].handle, + OL_TXQ_PAUSE_REASON_FW); + wma->interfaces[vdev_id].pause_bitmap |= (1 << wmi_event->pause_type); + } + /* UNPAUSE action, clean bitmap */ + else if (ACTION_UNPAUSE == wmi_event->action) + { + /* Handle unpause only if already paused*/ + if(wma->interfaces[vdev_id].pause_bitmap) + { + wma->interfaces[vdev_id].pause_bitmap &= ~(1 << wmi_event->pause_type); + + if (!wma->interfaces[vdev_id].pause_bitmap) + { + /* PAUSE BIT MAP is cleared + * UNPAUSE VDEV */ + wdi_in_vdev_unpause(wma->interfaces[vdev_id].handle, + OL_TXQ_PAUSE_REASON_FW); + } + } + } + else + { + WMA_LOGE("Not Valid Action Type %d", wmi_event->action); + } + + WMA_LOGD("vdev_id %d, pause_map 0x%x, pause type %d, action %d", + vdev_id, wma->interfaces[vdev_id].pause_bitmap, + wmi_event->pause_type, wmi_event->action); + } + /* Test Next VDEV */ + vdev_map >>= 1; + } + + return 0; +} +#endif /* QCA_SUPPORT_TXRX_VDEV_PAUSE_LL */ + +/* function : wma_set_thermal_mgmt + * Description : This function sends the thermal management command to the firmware + * Args : + wma_handle : Pointer to WMA handle + * thermal_info : Thermal command information + * Returns : + * VOS_STATUS_SUCCESS for success otherwise failure + */ +static VOS_STATUS wma_set_thermal_mgmt(tp_wma_handle wma_handle, + t_thermal_cmd_params thermal_info) +{ + wmi_thermal_mgmt_cmd_fixed_param *cmd = NULL; + wmi_buf_t buf = NULL; + int status = 0; + u_int32_t len = 0; + + len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set key cmd"); + return eHAL_STATUS_FAILURE; + } + + cmd = (wmi_thermal_mgmt_cmd_fixed_param *) wmi_buf_data (buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_thermal_mgmt_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_thermal_mgmt_cmd_fixed_param)); + + cmd->lower_thresh_degreeC = thermal_info.minTemp; + cmd->upper_thresh_degreeC = thermal_info.maxTemp; + cmd->enable = thermal_info.thermalEnable; + + WMA_LOGE("TM Sending thermal mgmt cmd: low temp %d, upper temp %d, enabled %d", + cmd->lower_thresh_degreeC, cmd->upper_thresh_degreeC, cmd->enable); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_THERMAL_MGMT_CMDID); + if (status) { + adf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send thermal mgmt command", __func__); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* function : wma_thermal_mgmt_get_level + * Description : This function returns the thermal(throttle) level given the temperature + * Args : + handle : Pointer to WMA handle + * temp : temperature + * Returns : + * thermal (throttle) level + */ +u_int8_t wma_thermal_mgmt_get_level(void *handle, u_int32_t temp) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + int i; + u_int8_t level; + + level = i = wma->thermal_mgmt_info.thermalCurrLevel; + while (temp < wma->thermal_mgmt_info.thermalLevels[i].minTempThreshold && + i > 0) { + i--; + level = i; + } + + i = wma->thermal_mgmt_info.thermalCurrLevel; + while (temp > wma->thermal_mgmt_info.thermalLevels[i].maxTempThreshold && + i < (WLAN_WMA_MAX_THERMAL_LEVELS - 1)) { + i++; + level = i; + } + + WMA_LOGW("Change thermal level from %d -> %d\n", + wma->thermal_mgmt_info.thermalCurrLevel, level); + + return level; +} + +/* function : wma_thermal_mgmt_evt_handler + * Description : This function handles the thermal mgmt event from the firmware + * Args : + wma_handle : Pointer to WMA handle + * event : Thermal event information + * len : + * Returns : + * 0 for success otherwise failure + */ +static int wma_thermal_mgmt_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + tp_wma_handle wma; + wmi_thermal_mgmt_event_fixed_param *tm_event; + u_int8_t thermal_level; + t_thermal_cmd_params thermal_params; + WMI_THERMAL_MGMT_EVENTID_param_tlvs *param_buf; + ol_txrx_pdev_handle curr_pdev; + + if (NULL == event || NULL == handle) { + WMA_LOGE("Invalid thermal mitigation event buffer"); + return -EINVAL; + } + + wma = (tp_wma_handle) handle; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma handle", __func__); + return -EINVAL; + } + + param_buf = (WMI_THERMAL_MGMT_EVENTID_param_tlvs *) event; + + curr_pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == curr_pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return -EINVAL; + } + + /* Check if thermal mitigation is enabled */ + if (!wma->thermal_mgmt_info.thermalMgmtEnabled){ + WMA_LOGE("Thermal mgmt is not enabled, ignoring event"); + return -EINVAL; + } + + tm_event = param_buf->fixed_param; + WMA_LOGD("Thermal mgmt event received with temperature %d", + tm_event->temperature_degreeC); + + /* Get the thermal mitigation level for the reported temperature*/ + thermal_level = wma_thermal_mgmt_get_level(handle, tm_event->temperature_degreeC); + WMA_LOGD("Thermal mgmt level %d", thermal_level); + + if (thermal_level == wma->thermal_mgmt_info.thermalCurrLevel) { + WMA_LOGD("Current level %d is same as the set level, ignoring", + wma->thermal_mgmt_info.thermalCurrLevel); + return 0; + } + + wma->thermal_mgmt_info.thermalCurrLevel = thermal_level; + + /* Inform txrx */ + ol_tx_throttle_set_level(curr_pdev, thermal_level); + + /* Send SME SET_THERMAL_LEVEL_IND message */ + wma_set_thermal_level_ind(thermal_level); + + /* Get the temperature thresholds to set in firmware */ + thermal_params.minTemp = + wma->thermal_mgmt_info.thermalLevels[thermal_level].minTempThreshold; + thermal_params.maxTemp = + wma->thermal_mgmt_info.thermalLevels[thermal_level].maxTempThreshold; + thermal_params.thermalEnable = + wma->thermal_mgmt_info.thermalMgmtEnabled; + + if (VOS_STATUS_SUCCESS != wma_set_thermal_mgmt(wma, thermal_params)) { + WMA_LOGE("Could not send thermal mgmt command to the firmware!"); + return -EINVAL; + } + + return 0; +} + +#ifdef FEATURE_WLAN_CH_AVOID +/* Process channel to avoid event comes from FW. + */ +static int wma_channel_avoid_evt_handler(void *handle, u_int8_t *event, + u_int32_t len) +{ + wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param; + wmi_avoid_freq_range_desc *afr_desc; + u_int32_t num_freq_ranges, freq_range_idx; + tSirChAvoidIndType *sca_indication; + VOS_STATUS vos_status; + vos_msg_t sme_msg = {0} ; + WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *param_buf = + (WMI_WLAN_FREQ_AVOID_EVENTID_param_tlvs *) event; + + if (!param_buf) { + WMA_LOGE("Invalid channel avoid event buffer"); + return -EINVAL; + } + + afr_fixed_param = param_buf->fixed_param; + if (!afr_fixed_param) { + WMA_LOGE("Invalid channel avoid event fixed param buffer"); + return -EINVAL; + } + + num_freq_ranges = (afr_fixed_param->num_freq_ranges > SIR_CH_AVOID_MAX_RANGE)? + SIR_CH_AVOID_MAX_RANGE:afr_fixed_param->num_freq_ranges; + + WMA_LOGD("Channel avoid event received with %d ranges", num_freq_ranges); + for (freq_range_idx = 0; freq_range_idx < num_freq_ranges; freq_range_idx++) { + afr_desc = (wmi_avoid_freq_range_desc *) ((void *)param_buf->avd_freq_range + + freq_range_idx * sizeof(wmi_avoid_freq_range_desc)); + WMA_LOGD("range %d: tlv id = %u, start freq = %u, end freq = %u", + freq_range_idx, + afr_desc->tlv_header, + afr_desc->start_freq, + afr_desc->end_freq); + } + + sca_indication = (tSirChAvoidIndType *) + vos_mem_malloc(sizeof(tSirChAvoidIndType)); + if (!sca_indication) { + WMA_LOGE("Invalid channel avoid indication buffer"); + return -EINVAL; + } + + sca_indication->avoid_range_count = num_freq_ranges; + for (freq_range_idx = 0; freq_range_idx < num_freq_ranges; freq_range_idx++) { + afr_desc = (wmi_avoid_freq_range_desc *) ((void *)param_buf->avd_freq_range + + freq_range_idx * sizeof(wmi_avoid_freq_range_desc)); + sca_indication->avoid_freq_range[freq_range_idx].start_freq = + afr_desc->start_freq; + sca_indication->avoid_freq_range[freq_range_idx].end_freq = + afr_desc->end_freq; + } + + sme_msg.type = eWNI_SME_CH_AVOID_IND; + sme_msg.bodyptr = sca_indication; + sme_msg.bodyval = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if ( !VOS_IS_STATUS_SUCCESS(vos_status) ) + { + WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME"); + vos_mem_free(sca_indication); + return -EINVAL; + } + + return 0; +} + +/* function : wma_process_ch_avoid_update_req + * Description : handles channel avoid update request + * Args : + * Returns : + */ +VOS_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle, + tSirChAvoidUpdateReq *ch_avoid_update_req) +{ + int status = 0; + wmi_buf_t buf = NULL; + u_int8_t *buf_ptr; + wmi_chan_avoid_update_cmd_param *ch_avoid_update_fp; + int len = sizeof(wmi_chan_avoid_update_cmd_param); + + if (ch_avoid_update_req == NULL) + { + WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE", + __func__); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + ch_avoid_update_fp = (wmi_chan_avoid_update_cmd_param *) buf_ptr; + WMITLV_SET_HDR(&ch_avoid_update_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_chan_avoid_update_cmd_param)); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + len, WMI_CHAN_AVOID_UPDATE_CMDID); + if (status != EOK) { + WMA_LOGE("wmi_unified_cmd_send" + " WMITLV_TABLE_WMI_CHAN_AVOID_UPDATE" + " returned Error %d", + status); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI", + __func__); + return VOS_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_CH_AVOID */ + +/* function : wma_scan_completion_timeout + * Description : + * Args : + * Returns : + */ +void wma_scan_completion_timeout(void *data) +{ + tp_wma_handle wma_handle; + u_int8_t vdev_id; + + WMA_LOGE("%s: Timeout occured for scan command", __func__); + + wma_handle = (tp_wma_handle) data; + + vdev_id = wma_handle->wma_scan_timer_info.vdev_id; + + if (wma_handle->wma_scan_timer_info.scan_id != + wma_handle->interfaces[vdev_id].scan_info.scan_id) { + WMA_LOGE("%s: Scan ID mismatch", __func__); + return; + } + + /* + * To avoid race condition between scan timeout in host and in firmware + * here we should just send abort scan to firmware and do cleanup after + * receiving event from firmware. Since at this moment there will be no + * outstanding scans, aborting should not cause any problem in firmware. + */ + if (wma_handle->interfaces[vdev_id].scan_info.scan_id != 0) { + tAbortScanParams abortScan; + abortScan.SessionId = vdev_id; + WMA_LOGW("%s: Sending abort for timed out scan", __func__); + wma_stop_scan(wma_handle, &abortScan); + } + + return; +} + +/** + * wma_log_completion_timeout() - Log completion timeout + * @data: Timeout handler data + * + * This function is called when log completion timer expires + * + * Return: None + */ +void wma_log_completion_timeout(void *data) +{ + tp_wma_handle wma_handle; + + WMA_LOGE("%s: Timeout occured for log completion command", __func__); + + wma_handle = (tp_wma_handle) data; + if (!wma_handle) + WMA_LOGE("%s: Invalid WMA handle", __func__); + + /* Though we did not receive any event from FW, + * we can flush whatever logs we have with us */ + vos_logging_set_fw_flush_complete(); + + return; +} + +#ifdef SAP_AUTH_OFFLOAD +static int wma_sap_ofl_add_sta_handler(void *handle, u_int8_t *data, + u_int32_t data_len) +{ + tp_wma_handle wma = handle; + WMI_SAP_OFL_ADD_STA_EVENTID_param_tlvs *param_buf = NULL; + wmi_sap_ofl_add_sta_event_fixed_param *sta_add_event = NULL; + struct sap_offload_add_sta_req *add_sta_req = NULL; + u_int8_t *buf_ptr; + + param_buf = (WMI_SAP_OFL_ADD_STA_EVENTID_param_tlvs *)data; + sta_add_event = param_buf->fixed_param; + buf_ptr = (u_int8_t *)param_buf->bufp; + + add_sta_req = vos_mem_malloc(sizeof(*add_sta_req)); + if (!add_sta_req) { + WMA_LOGE("%s: Failed to alloc memory for sap_ofl_add_sta_event", + __func__); + return 0; + } + vos_mem_set(add_sta_req, sizeof(*add_sta_req), 0); + add_sta_req->assoc_id = sta_add_event->assoc_id; + add_sta_req->conn_req_len = sta_add_event->data_len; + vos_mem_copy(add_sta_req->conn_req, buf_ptr, + sta_add_event->data_len); + + wma_send_msg(wma, WDA_SAP_OFL_ADD_STA, add_sta_req, 0); + + return 1; +} + +static int wma_sap_ofl_del_sta_handler(void *handle, u_int8_t *data, + u_int32_t data_len) +{ + tp_wma_handle wma = handle; + WMI_SAP_OFL_DEL_STA_EVENTID_param_tlvs *param_buf = NULL; + wmi_sap_ofl_del_sta_event_fixed_param *sta_del_event = NULL; + struct sap_offload_del_sta_req *del_sta_req = NULL; + + param_buf = (WMI_SAP_OFL_DEL_STA_EVENTID_param_tlvs *)data; + sta_del_event = param_buf->fixed_param; + + del_sta_req = vos_mem_malloc(sizeof(*del_sta_req)); + if (!del_sta_req) { + WMA_LOGE("%s: Failed to alloc memory for sap_ofl_del_sta_event", + __func__); + return 0; + } + vos_mem_set(del_sta_req, sizeof(*del_sta_req), 0); + WMI_MAC_ADDR_TO_CHAR_ARRAY(&sta_del_event->peer_macaddr, + del_sta_req->sta_mac); + + del_sta_req->assoc_id = sta_del_event->assoc_id; + del_sta_req->reason_code = sta_del_event->reason; + del_sta_req->flags = sta_del_event->flags; + wma_send_msg(wma, WDA_SAP_OFL_DEL_STA, del_sta_req, 0); + return 1; +} +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * wma_vdev_tsf_handler() - handle tsf event indicated by FW + * + * @handle: wma context + * @data: event buffer + * @data len: length of event buffer + * + * Return: 0 on success + */ +static int wma_vdev_tsf_handler(void *handle, uint8_t *data, + uint32_t data_len) +{ + vos_msg_t vos_msg = {0}; + WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf; + wmi_vdev_tsf_report_event_fixed_param *tsf_event; + struct stsf *ptsf; + + if (data == NULL) { + WMA_LOGE("%s: invalid pointer", __func__); + return -EINVAL; + } + ptsf = vos_mem_malloc(sizeof(*ptsf)); + if (NULL == ptsf) { + WMA_LOGE("%s: failed to allocate sSirtsf memory", __func__); + return -ENOMEM; + } + + param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data; + tsf_event = param_buf->fixed_param; + + ptsf->vdev_id = tsf_event->vdev_id; + ptsf->tsf_low = tsf_event->tsf_low; + ptsf->tsf_high = tsf_event->tsf_high; + + WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__); + WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__, + ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high); + + vos_msg.type = eWNI_SME_TSF_EVENT; + vos_msg.bodyptr = ptsf; + vos_msg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg)) { + + WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__); + vos_mem_free(ptsf); + return -EINVAL; + } + return 0; +} + +/** + * wma_echo_event_handler() - received echo response event from firmware + * @handle: wma context + * @event_buf: event buffer + * @len: length of event buffer + * + * Return: 0 on success + */ +static int wma_echo_event_handler(void *handle, u_int8_t *event_buf, + u_int32_t len) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + vos_msg_t sme_msg = {0}; + + WMA_LOGD("Received Echo reply from firmware!"); + sme_msg.type = eWNI_SME_FW_STATUS_IND; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &sme_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE("%s: Fail to post firmware status ind msg", __func__); + } + + return 0; +} + +/* function : wma_start + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_start(v_VOID_t *vos_ctx) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tp_wma_handle wma_handle; + int status; + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid handle", __func__); + vos_status = VOS_STATUS_E_INVAL; + goto end; + } + + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_SCAN_EVENTID, + wma_scan_event_callback); + if (0 != status) { + WMA_LOGP("%s: Failed to register scan callback", __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_ROAM_EVENTID, + wma_roam_event_callback); + if (0 != status) { + WMA_LOGP("%s: Failed to register Roam callback", __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_WOW_WAKEUP_HOST_EVENTID, + wma_wow_wakeup_host_event); + if (status) { + WMA_LOGP("%s: Failed to register wow wakeup host event handler", + __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + +#ifdef FEATURE_WLAN_D0WOW + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_D0_WOW_DISABLE_ACK_EVENTID, + wma_d0_wow_disable_ack_event); + if (status) { + WMA_LOGE("%s: Failed to register D0-WOW disable event handler!", + __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_NLO)) { + + WMA_LOGD("FW supports pno offload, registering nlo match handler"); + + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_NLO_MATCH_EVENTID, + wma_nlo_match_evt_handler); + if (status) { + WMA_LOGE("Failed to register nlo match event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_NLO_SCAN_COMPLETE_EVENTID, + wma_nlo_scan_cmp_evt_handler); + if (status) { + WMA_LOGE("Failed to register nlo scan comp event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + } +#endif + +#ifdef WLAN_FEATURE_APFIND + WMA_LOGD("APFIND event handler register"); + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_APFIND_EVENTID, + wma_apfind_evt_handler); + if (status) { + WMA_LOGE("Failed to register APFIND event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } +#endif /* WLAN_FEATURE_APFIND*/ + +#if defined(CONFIG_HL_SUPPORT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) + WMA_LOGE("MCC TX Pause Event Handler register"); + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_TX_PAUSE_EVENTID, + wma_mcc_vdev_tx_pause_evt_handler); +#endif /* QCA_SUPPORT_TXRX_VDEV_PAUSE_LL */ + +#ifdef FEATURE_WLAN_CH_AVOID + WMA_LOGD("Registering channel to avoid handler"); + + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_WLAN_FREQ_AVOID_EVENTID, + wma_channel_avoid_evt_handler); + if (status) { + WMA_LOGE("Failed to register channel to avoid event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } +#endif /* FEATURE_WLAN_CH_AVOID */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + WMA_LOGD("Registering auto shutdown handler"); + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_HOST_AUTO_SHUTDOWN_EVENTID, wma_auto_shutdown_event_handler); + if (status) { + WMA_LOGE("Failed to register WMI Auto shutdown event handler"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } +#endif + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_THERMAL_MGMT_EVENTID, + wma_thermal_mgmt_evt_handler); + if (status) { + WMA_LOGE("Failed to register thermal mitigation event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + status = wma_ocb_register_event_handlers(wma_handle); + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_ECHO_EVENTID, + wma_echo_event_handler); + if (status) { + WMA_LOGE("Failed to register echo event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + vos_status = VOS_STATUS_SUCCESS; + +#ifdef QCA_WIFI_FTM + /* + * Tx mgmt attach requires TXRX context which is not created + * in FTM mode as WLANTL_Open will not be called in this mode. + * So skip the TX mgmt attach. + */ + if (vos_get_conparam() == VOS_FTM_MODE) + goto end; +#endif + + vos_status = wma_tx_attach(wma_handle); + if(vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: Failed to register tx management", __func__); + goto end; + } + + /* Initialize scan completion timeout */ + vos_status = vos_timer_init(&wma_handle->wma_scan_comp_timer, + VOS_TIMER_TYPE_SW, + wma_scan_completion_timeout, + wma_handle); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to initialize scan completion timeout"); + goto end; + } + + /* Initialize log completion timeout */ + vos_status = vos_timer_init(&wma_handle->log_completion_timer, + VOS_TIMER_TYPE_SW, + wma_log_completion_timeout, + wma_handle); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to initialize log completion timeout"); + goto end; + } + + /* Initialize the get temperature event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PDEV_TEMPERATURE_EVENTID, + wma_pdev_temperature_evt_handler); + if (status != VOS_STATUS_SUCCESS) + { + WMA_LOGE("Failed to register get_temperature event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + +#ifdef SAP_AUTH_OFFLOAD + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SAP_AUTH_OFFLOAD)) { + /* Initialize the station connect event handler for + * software AP authentication offload feature. + */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_SAP_OFL_ADD_STA_EVENTID, + wma_sap_ofl_add_sta_handler); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to register sap offload add_sta event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + /* Initialize the station disconnect event handler for + * software AP authentication offload feature. + */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_SAP_OFL_DEL_STA_EVENTID, + wma_sap_ofl_del_sta_handler); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to register sap offload del_sta event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + } +#endif /* SAP_AUTH_OFFLOAD */ + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_TSF_REPORT_EVENTID, + wma_vdev_tsf_handler); + if (0 != status) { + WMA_LOGP("%s: Failed to register tsf callback", __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + /* Initialize the log flush complete event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID, + wma_flush_complete_evt_handler); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to register log flush complete event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + /* Initialize the SMPS force mode command event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID, + wma_smps_force_mode_callback); + if (VOS_STATUS_SUCCESS != status) { + WMA_LOGP("%s: SMPS force mode event registration failed", + __func__); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + +end: + WMA_LOGD("%s: Exit", __func__); + return vos_status; +} + +/* function : wma_stop + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_stop(v_VOID_t *vos_ctx, tANI_U8 reason) +{ + tp_wma_handle wma_handle; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int i; + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + WMA_LOGD("%s: Enter", __func__); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid handle", __func__); + vos_status = VOS_STATUS_E_INVAL; + goto end; + } + +#ifdef QCA_WIFI_FTM + /* + * Tx mgmt detach requires TXRX context which is not created + * in FTM mode as WLANTL_Open will not be called in this mode. + * So skip the TX mgmt detach. + */ + if (vos_get_conparam() == VOS_FTM_MODE) { + vos_status = VOS_STATUS_SUCCESS; + goto end; + } +#endif + + if (wma_handle->ack_work_ctx) { + vos_flush_work(&wma_handle->ack_work_ctx->ack_cmp_work); + adf_os_mem_free(wma_handle->ack_work_ctx); + wma_handle->ack_work_ctx = NULL; + } + + /* Destroy the timer for scan completion */ + vos_status = vos_timer_destroy(&wma_handle->wma_scan_comp_timer); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to destroy the scan completion timer"); + } + + /* Destroy the timer for log completion */ + vos_status = vos_timer_destroy(&wma_handle->log_completion_timer); + if (vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to destroy the log completion timer"); + } + + /* There's no need suspend target which is already down during SSR. */ + if (!vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) { +#ifdef HIF_USB + /* Suspend the target and enable interrupt */ + if (wma_suspend_target(wma_handle, 0)) + WMA_LOGE("Failed to suspend target"); +#else + /* Suspend the target and disable interrupt */ + if (wma_suspend_target(wma_handle, 1)) + WMA_LOGE("Failed to suspend target"); +#endif + } + + /* clean up ll-queue for all vdev */ + for (i = 0; i < wma_handle->max_bssid; i++) { + if (wma_handle->interfaces[i].handle && + wma_handle->interfaces[i].vdev_up) { + ol_txrx_vdev_flush(wma_handle->interfaces[i].handle); + } + } + + vos_status = wma_tx_detach(wma_handle); + if(vos_status != VOS_STATUS_SUCCESS) { + WMA_LOGP("%s: Failed to deregister tx management", __func__); + goto end; + } + +end: + WMA_LOGD("%s: Exit", __func__); + return vos_status; +} + +static void wma_cleanup_vdev_resp(tp_wma_handle wma) +{ + struct wma_target_req *msg, *tmp; + + adf_os_spin_lock_bh(&wma->vdev_respq_lock); + list_for_each_entry_safe(msg, tmp, + &wma->vdev_resp_queue, node) { + list_del(&msg->node); + vos_timer_destroy(&msg->event_timeout); + adf_os_mem_free(msg); + } + adf_os_spin_unlock_bh(&wma->vdev_respq_lock); +} + +VOS_STATUS wma_wmi_service_close(v_VOID_t *vos_ctx) +{ + tp_wma_handle wma_handle; + struct beacon_info *bcn; + int i; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGE("%s: Invalid wmi handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* dettach the wmi serice */ + WMA_LOGD("calling wmi_unified_detach"); + wmi_unified_detach(wma_handle->wmi_handle); + wma_handle->wmi_handle = NULL; + + for (i = 0; i < wma_handle->max_bssid; i++) { + bcn = wma_handle->interfaces[i].beacon; + + if (bcn) { + if (bcn->dma_mapped) + adf_nbuf_unmap_single(wma_handle->adf_dev, + bcn->buf, ADF_OS_DMA_TO_DEVICE); + adf_nbuf_free(bcn->buf); + vos_mem_free(bcn); + wma_handle->interfaces[i].beacon = NULL; + } + + if (wma_handle->interfaces[i].handle) { + adf_os_mem_free(wma_handle->interfaces[i].handle); + wma_handle->interfaces[i].handle = NULL; + } + } + + vos_mem_free(wma_handle->interfaces); + /* free the wma_handle */ + vos_free_context(wma_handle->vos_context, VOS_MODULE_ID_WDA, wma_handle); + + adf_os_mem_free(((pVosContextType) vos_ctx)->cfg_ctx); + WMA_LOGD("%s: Exit", __func__); + return VOS_STATUS_SUCCESS; +} + +/** + * wma_wmi_work_close() - close the work queue items associated with WMI + * @vos_ctx: Pointer to vos context + * + * This function closes work queue items associated with WMI, but not fully + * closes WMI service. + * + * Return: VOS_STATUS_SUCCESS if work close is successful. Otherwise + * proper error codes. + */ +VOS_STATUS wma_wmi_work_close(v_VOID_t *vos_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGE("%s: Invalid wmi handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* remove the wmi work */ + WMA_LOGD("calling wmi_unified_remove_work"); + wmi_unified_remove_work(wma_handle->wmi_handle); + + return VOS_STATUS_SUCCESS; +} + +/* + * Detach DFS methods + */ +static void wma_dfs_detach(struct ieee80211com *dfs_ic) +{ + dfs_detach(dfs_ic); + + adf_os_spinlock_destroy(&dfs_ic->chan_lock); + if (NULL != dfs_ic->ic_curchan) { + OS_FREE(dfs_ic->ic_curchan); + dfs_ic->ic_curchan = NULL; + } + + OS_FREE(dfs_ic); +} + +/* function : wma_close + * Description : + * Args : + * Returns : + */ +VOS_STATUS wma_close(v_VOID_t *vos_ctx) +{ + tp_wma_handle wma_handle; + u_int32_t idx; + u_int8_t ptrn_id; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGP("%s: Invalid wmi handle", __func__); + return VOS_STATUS_E_INVAL; + } + + if (wma_handle->events_logs_list) { + vos_mem_free(wma_handle->events_logs_list); + wma_handle->events_logs_list = NULL; + WMA_LOGD("%s: Event log list freed", __func__); + } + + /* Free wow pattern cache */ + for (ptrn_id = 0; ptrn_id < wma_handle->wlan_resource_config.num_wow_filters; + ptrn_id++) + wma_free_wow_ptrn(wma_handle, ptrn_id); + + if (vos_get_conparam() != VOS_FTM_MODE) { +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_destroy(&wma_handle->pno_wake_lock); +#endif +#ifdef FEATURE_WLAN_EXTSCAN + vos_wake_lock_destroy(&wma_handle->extscan_wake_lock); +#endif + vos_wake_lock_destroy(&wma_handle->wow_wake_lock); + } + + wma_runtime_context_deinit(wma_handle); + + /* unregister Firmware debug log */ + vos_status = dbglog_deinit(wma_handle->wmi_handle); + if(vos_status != VOS_STATUS_SUCCESS) + WMA_LOGP("%s: dbglog_deinit failed", __func__); + + /* close the vos events */ + vos_event_destroy(&wma_handle->wma_ready_event); + vos_event_destroy(&wma_handle->target_suspend); + vos_event_destroy(&wma_handle->wma_resume_event); + vos_event_destroy(&wma_handle->wow_tx_complete); + vos_event_destroy(&wma_handle->runtime_suspend); + vos_event_destroy(&wma_handle->recovery_event); + wma_cleanup_vdev_resp(wma_handle); + for(idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { + adf_os_mem_free_consistent( + wma_handle->adf_dev, + wma_handle->mem_chunks[idx].len, + wma_handle->mem_chunks[idx].vaddr, + wma_handle->mem_chunks[idx].paddr, + adf_os_get_dma_mem_context( + (&(wma_handle->mem_chunks[idx])), + memctx)); + } + +#if defined(QCA_WIFI_FTM) + /* Detach UTF and unregister the handler */ + if (vos_get_conparam() == VOS_FTM_MODE) + wma_utf_detach(wma_handle); +#endif + + if (NULL != wma_handle->dfs_ic){ + wma_dfs_detach(wma_handle->dfs_ic); + wma_handle->dfs_ic = NULL; + } + + if (NULL != wma_handle->pGetRssiReq) { + adf_os_mem_free(wma_handle->pGetRssiReq); + wma_handle->pGetRssiReq = NULL; + } + + WMA_LOGD("%s: Exit", __func__); + return VOS_STATUS_SUCCESS; +} + +static v_VOID_t wma_update_fw_config(tp_wma_handle wma_handle, + struct wma_target_cap *tgt_cap) +{ + /* + * tgt_cap contains default target resource configuration + * which can be modified here, if required + */ + /* Override the no. of max fragments as per platform configuration */ + tgt_cap->wlan_resource_config.max_frag_entries = + MIN(QCA_OL_11AC_TX_MAX_FRAGS, wma_handle->max_frag_entry); + wma_handle->max_frag_entry = tgt_cap->wlan_resource_config.max_frag_entries; +} + +/** + * allocate a chunk of memory at the index indicated and + * if allocation fail allocate smallest size possiblr and + * return number of units allocated. + */ +static u_int32_t wma_alloc_host_mem_chunk(tp_wma_handle wma_handle, + u_int32_t req_id, u_int32_t idx, + u_int32_t num_units, + u_int32_t unit_len) +{ + adf_os_dma_addr_t paddr; + if (!num_units || !unit_len) { + return 0; + } + wma_handle->mem_chunks[idx].vaddr = NULL ; + /** reduce the requested allocation by half until allocation succeeds */ + while(wma_handle->mem_chunks[idx].vaddr == NULL && num_units ) { + wma_handle->mem_chunks[idx].vaddr = adf_os_mem_alloc_consistent( + wma_handle->adf_dev, num_units*unit_len, &paddr, + adf_os_get_dma_mem_context( + (&(wma_handle->mem_chunks[idx])), + memctx)); + if(wma_handle->mem_chunks[idx].vaddr == NULL) { + num_units = (num_units >> 1) ; /* reduce length by half */ + } else { + wma_handle->mem_chunks[idx].paddr = paddr; + wma_handle->mem_chunks[idx].len = num_units*unit_len; + wma_handle->mem_chunks[idx].req_id = req_id; + } + } + return num_units; +} + +#define HOST_MEM_SIZE_UNIT 4 +/* + * allocate amount of memory requested by FW. + */ +static void wma_alloc_host_mem(tp_wma_handle wma_handle, u_int32_t req_id, + u_int32_t num_units, u_int32_t unit_len) +{ + u_int32_t remaining_units,allocated_units, idx; + + /* adjust the length to nearest multiple of unit size */ + unit_len = (unit_len + (HOST_MEM_SIZE_UNIT - 1)) & + (~(HOST_MEM_SIZE_UNIT - 1)); + idx = wma_handle->num_mem_chunks ; + remaining_units = num_units; + while(remaining_units) { + allocated_units = wma_alloc_host_mem_chunk(wma_handle, req_id, + idx, remaining_units, + unit_len); + if (allocated_units == 0) { + WMA_LOGE("FAILED TO ALLOCATED memory unit len %d" + " units requested %d units allocated %d ", + unit_len, num_units, + (num_units - remaining_units)); + wma_handle->num_mem_chunks = idx; + break; + } + remaining_units -= allocated_units; + ++idx; + if (idx == MAX_MEM_CHUNKS ) { + WMA_LOGE("RWACHED MAX CHUNK LIMIT for memory units %d" + " unit len %d requested by FW," + " only allocated %d ", + num_units,unit_len, + (num_units - remaining_units)); + wma_handle->num_mem_chunks = idx; + break; + } + } + wma_handle->num_mem_chunks = idx; +} + +static inline void wma_update_target_services(tp_wma_handle wh, + struct hdd_tgt_services *cfg) +{ + /* STA power save */ + cfg->sta_power_save = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_STA_PWRSAVE); + + /* Enable UAPSD */ + cfg->uapsd = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_AP_UAPSD); + + /* Update AP DFS service */ + cfg->ap_dfs = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_AP_DFS); + + /* Enable 11AC */ + cfg->en_11ac = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_11AC); + if (cfg->en_11ac) + gFwWlanFeatCaps |= (1 << DOT11AC); + + /* Proactive ARP response */ + gFwWlanFeatCaps |= (1 << WLAN_PERIODIC_TX_PTRN); + + /* Enable WOW */ + gFwWlanFeatCaps |= (1 << WOW); + + /* ARP offload */ + cfg->arp_offload = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_ARPNS_OFFLOAD); + + /* Adaptive early-rx */ + cfg->early_rx = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_EARLY_RX); +#ifdef FEATURE_WLAN_SCAN_PNO + /* PNO offload */ + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_NLO)) + cfg->pno_offload = TRUE; +#endif + +#ifdef FEATURE_WLAN_EXTSCAN + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + gFwWlanFeatCaps |= (1 << EXTENDED_SCAN); + } +#endif + cfg->lte_coex_ant_share = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_LTE_ANT_SHARE_SUPPORT); + cfg->per_band_chainmask_supp = WMI_SERVICE_IS_ENABLED( + wh->wmi_service_bitmap, + WMI_SERVICE_PER_BAND_CHAINMASK_SUPPORT); + wh->per_band_chainmask_supp = cfg->per_band_chainmask_supp; +#ifdef FEATURE_WLAN_TDLS + /* Enable TDLS */ + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_TDLS)) { + cfg->en_tdls = 1; + gFwWlanFeatCaps |= (1 << TDLS); + } + /* Enable advanced TDLS features */ + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_TDLS_OFFCHAN)) { + cfg->en_tdls_offchan = 1; + gFwWlanFeatCaps |= (1 << TDLS_OFF_CHANNEL); + } + + cfg->en_tdls_uapsd_buf_sta = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_TDLS_UAPSD_BUFFER_STA); + cfg->en_tdls_uapsd_sleep_sta = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_TDLS_UAPSD_SLEEP_STA); +#endif + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD)) + cfg->beacon_offload = TRUE; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + /* Enable Roam Offload */ + cfg->en_roam_offload = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_ROAM_HO_OFFLOAD); +#endif +#ifdef WLAN_FEATURE_NAN + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_NAN)) + gFwWlanFeatCaps |= (1 << NAN); +#endif + + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_RTT)) + gFwWlanFeatCaps |= (1 << RTT); + +#ifdef SAP_AUTH_OFFLOAD + cfg->sap_auth_offload_service = + WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_SAP_AUTH_OFFLOAD); +#endif + cfg->chain_mask_2g = wh->txrx_chainmask & 0xFF; + cfg->chain_mask_5g = (wh->txrx_chainmask >> 16 ) & 0xFF; +} + +static inline void wma_update_target_ht_cap(tp_wma_handle wh, + struct hdd_tgt_ht_cap *cfg) +{ + /* RX STBC */ + cfg->ht_rx_stbc = !!(wh->ht_cap_info & WMI_HT_CAP_RX_STBC); + + /* TX STBC */ + cfg->ht_tx_stbc = !!(wh->ht_cap_info & WMI_HT_CAP_TX_STBC); + + /* MPDU density */ + cfg->mpdu_density = wh->ht_cap_info & WMI_HT_CAP_MPDU_DENSITY; + + /* HT RX LDPC */ + cfg->ht_rx_ldpc = !!(wh->ht_cap_info & WMI_HT_CAP_LDPC); + + /* HT SGI */ + cfg->ht_sgi_20 = !!(wh->ht_cap_info & WMI_HT_CAP_HT20_SGI); + + cfg->ht_sgi_40 = !!(wh->ht_cap_info & WMI_HT_CAP_HT40_SGI); + + /* RF chains */ + cfg->num_rf_chains = wh->num_rf_chains; + + WMA_LOGD("%s: ht_cap_info - %x ht_rx_stbc - %d, ht_tx_stbc - %d, mpdu_density - %d ht_rx_ldpc - %d ht_sgi_20 - %d, ht_sgi_40 - %d num_rf_chains - %d ", + __func__, + wh->ht_cap_info, cfg->ht_rx_stbc, cfg->ht_tx_stbc, + cfg->mpdu_density, cfg->ht_rx_ldpc, cfg->ht_sgi_20, + cfg->ht_sgi_40, cfg->num_rf_chains); + +} + +#ifdef WLAN_FEATURE_11AC +static inline void wma_update_target_vht_cap(tp_wma_handle wh, + struct hdd_tgt_vht_cap *cfg) +{ + /* Max MPDU length */ + if (wh->vht_cap_info & IEEE80211_VHTCAP_MAX_MPDU_LEN_3839) + cfg->vht_max_mpdu = 0; + else if (wh->vht_cap_info & IEEE80211_VHTCAP_MAX_MPDU_LEN_7935) + cfg->vht_max_mpdu = 1; + else if (wh->vht_cap_info & IEEE80211_VHTCAP_MAX_MPDU_LEN_11454) + cfg->vht_max_mpdu = 2; + else + cfg->vht_max_mpdu = 0; + + /* supported channel width */ + if (wh->vht_cap_info & IEEE80211_VHTCAP_SUP_CHAN_WIDTH_80) + cfg->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_80MHZ; + + else if (wh->vht_cap_info & IEEE80211_VHTCAP_SUP_CHAN_WIDTH_160) + cfg->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_160MHZ; + + else if (wh->vht_cap_info & IEEE80211_VHTCAP_SUP_CHAN_WIDTH_80_160) { + cfg->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_80MHZ; + cfg->supp_chan_width |= 1 << eHT_CHANNEL_WIDTH_160MHZ; + } + + else + cfg->supp_chan_width = 0; + + /* LDPC capability */ + cfg->vht_rx_ldpc = wh->vht_cap_info & IEEE80211_VHTCAP_RX_LDPC; + + /* Guard interval */ + cfg->vht_short_gi_80 = wh->vht_cap_info & IEEE80211_VHTCAP_SHORTGI_80; + cfg->vht_short_gi_160 = wh->vht_cap_info & IEEE80211_VHTCAP_SHORTGI_160; + + /* TX STBC capability */ + cfg->vht_tx_stbc = wh->vht_cap_info & IEEE80211_VHTCAP_TX_STBC; + + /* RX STBC capability */ + cfg->vht_rx_stbc = wh->vht_cap_info & IEEE80211_VHTCAP_RX_STBC; + + cfg->vht_max_ampdu_len_exp = (wh->vht_cap_info & + IEEE80211_VHTCAP_MAX_AMPDU_LEN_EXP) + >> IEEE80211_VHTCAP_MAX_AMPDU_LEN_EXP_S; + + /* SU beamformer cap */ + cfg->vht_su_bformer = wh->vht_cap_info & IEEE80211_VHTCAP_SU_BFORMER; + + /* SU beamformee cap */ + cfg->vht_su_bformee = wh->vht_cap_info & IEEE80211_VHTCAP_SU_BFORMEE; + + /* MU beamformer cap */ + cfg->vht_mu_bformer = wh->vht_cap_info & IEEE80211_VHTCAP_MU_BFORMER; + + /* MU beamformee cap */ + cfg->vht_mu_bformee = wh->vht_cap_info & IEEE80211_VHTCAP_MU_BFORMEE; + + /* VHT Max AMPDU Len exp */ + cfg->vht_max_ampdu_len_exp = wh->vht_cap_info & + IEEE80211_VHTCAP_MAX_AMPDU_LEN_EXP; + + /* VHT TXOP PS cap */ + cfg->vht_txop_ps = wh->vht_cap_info & IEEE80211_VHTCAP_TXOP_PS; + + WMA_LOGD("%s: max_mpdu %d supp_chan_width %x rx_ldpc %x short_gi_80 %x tx_stbc %x rx_stbc %x txop_ps %x su_bformee %x mu_bformee %x max_ampdu_len_exp %d", + __func__, cfg->vht_max_mpdu, cfg->supp_chan_width, + cfg->vht_rx_ldpc, cfg->vht_short_gi_80, cfg->vht_tx_stbc, + cfg->vht_rx_stbc, cfg->vht_txop_ps, cfg->vht_su_bformee, + cfg->vht_mu_bformee, cfg->vht_max_ampdu_len_exp); +} +#endif /* #ifdef WLAN_FEATURE_11AC */ + +static void wma_update_hdd_cfg(tp_wma_handle wma_handle) +{ + struct hdd_tgt_cfg hdd_tgt_cfg; + void *hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, + wma_handle->vos_context); + + hdd_tgt_cfg.reg_domain = wma_handle->reg_cap.eeprom_rd; + hdd_tgt_cfg.eeprom_rd_ext = wma_handle->reg_cap.eeprom_rd_ext; + + switch (wma_handle->phy_capability) { + case WMI_11G_CAPABILITY: + case WMI_11NG_CAPABILITY: + hdd_tgt_cfg.band_cap = eCSR_BAND_24; + break; + case WMI_11A_CAPABILITY: + case WMI_11NA_CAPABILITY: + case WMI_11AC_CAPABILITY: + hdd_tgt_cfg.band_cap = eCSR_BAND_5G; + break; + case WMI_11AG_CAPABILITY: + case WMI_11NAG_CAPABILITY: + default: + hdd_tgt_cfg.band_cap = eCSR_BAND_ALL; + } + + hdd_tgt_cfg.max_intf_count = wma_handle->wlan_resource_config.num_vdevs; + + adf_os_mem_copy(hdd_tgt_cfg.hw_macaddr.bytes, wma_handle->hwaddr, + ATH_MAC_LEN); + + wma_update_target_services(wma_handle, &hdd_tgt_cfg.services); + wma_update_target_ht_cap(wma_handle, &hdd_tgt_cfg.ht_cap); +#ifdef WLAN_FEATURE_11AC + wma_update_target_vht_cap(wma_handle, &hdd_tgt_cfg.vht_cap); +#endif /* #ifdef WLAN_FEATURE_11AC */ + + hdd_tgt_cfg.target_fw_version = wma_handle->target_fw_version; +#ifdef WLAN_FEATURE_LPSS + hdd_tgt_cfg.lpss_support = wma_handle->lpss_support; +#endif + hdd_tgt_cfg.ap_arpns_support = wma_handle->ap_arpns_support; + wma_handle->tgt_cfg_update_cb(hdd_ctx, &hdd_tgt_cfg); +} +static wmi_buf_t wma_setup_wmi_init_msg(tp_wma_handle wma_handle, + wmi_service_ready_event_fixed_param *ev, + WMI_SERVICE_READY_EVENTID_param_tlvs *param_buf, + v_SIZE_t *len) +{ + wmi_buf_t buf; + wmi_init_cmd_fixed_param *cmd; + wlan_host_mem_req *ev_mem_reqs; + wmi_abi_version my_vers; + int num_whitelist; + u_int8_t *buf_ptr; + wmi_resource_config *resource_cfg; + wlan_host_memory_chunk *host_mem_chunks; + u_int32_t mem_chunk_len = 0; + u_int16_t idx; + u_int32_t num_units; + + *len = sizeof(*cmd) + sizeof(wmi_resource_config) + WMI_TLV_HDR_SIZE; + mem_chunk_len = (sizeof(wlan_host_memory_chunk) * MAX_MEM_CHUNKS); + buf = wmi_buf_alloc(wma_handle->wmi_handle, *len + mem_chunk_len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return NULL; + } + + ev_mem_reqs = param_buf->mem_reqs; + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_init_cmd_fixed_param *) buf_ptr; + resource_cfg = (wmi_resource_config *) (buf_ptr + sizeof(*cmd)); + host_mem_chunks = (wlan_host_memory_chunk*) + (buf_ptr + sizeof(*cmd) + sizeof(wmi_resource_config) + + WMI_TLV_HDR_SIZE); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_init_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_init_cmd_fixed_param)); + + *resource_cfg = wma_handle->wlan_resource_config; + WMITLV_SET_HDR(&resource_cfg->tlv_header, + WMITLV_TAG_STRUC_wmi_resource_config, + WMITLV_GET_STRUCT_TLVLEN(wmi_resource_config)); + + /* allocate memory requested by FW */ + if (ev->num_mem_reqs > WMI_MAX_MEM_REQS) { + VOS_ASSERT(0); + adf_nbuf_free(buf); + return NULL; + } + + cmd->num_host_mem_chunks = 0; + for(idx = 0; idx < ev->num_mem_reqs; ++idx) { + num_units = ev_mem_reqs[idx].num_units; + if (ev_mem_reqs[idx].num_unit_info & NUM_UNITS_IS_NUM_PEERS) { + /* + * number of units to allocate is number + * of peers, 1 extra for self peer on + * target. this needs to be fied, host + * and target can get out of sync + */ + num_units = resource_cfg->num_peers + 1; + } + WMA_LOGD("idx %d req %d num_units %d num_unit_info %d unit size %d actual units %d ", + idx, ev_mem_reqs[idx].req_id, + ev_mem_reqs[idx].num_units, + ev_mem_reqs[idx].num_unit_info, + ev_mem_reqs[idx].unit_size, + num_units); + wma_alloc_host_mem(wma_handle, ev_mem_reqs[idx].req_id, + num_units, ev_mem_reqs[idx].unit_size); + } + for(idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { + WMITLV_SET_HDR(&(host_mem_chunks[idx].tlv_header), + WMITLV_TAG_STRUC_wlan_host_memory_chunk, + WMITLV_GET_STRUCT_TLVLEN(wlan_host_memory_chunk)); + host_mem_chunks[idx].ptr = wma_handle->mem_chunks[idx].paddr; + host_mem_chunks[idx].size = wma_handle->mem_chunks[idx].len; + host_mem_chunks[idx].req_id = + wma_handle->mem_chunks[idx].req_id; + WMA_LOGD("chunk %d len %d requested ,ptr 0x%x ", + idx, host_mem_chunks[idx].size, + host_mem_chunks[idx].ptr) ; + } + cmd->num_host_mem_chunks = wma_handle->num_mem_chunks; + len += (wma_handle->num_mem_chunks * sizeof(wlan_host_memory_chunk)); + WMITLV_SET_HDR((buf_ptr + sizeof(*cmd) + sizeof(wmi_resource_config)), + WMITLV_TAG_ARRAY_STRUC, + (sizeof(wlan_host_memory_chunk) * + wma_handle->num_mem_chunks)); + vos_mem_copy(&wma_handle->target_abi_vers, + ¶m_buf->fixed_param->fw_abi_vers, + sizeof(wmi_abi_version)); + num_whitelist = sizeof(version_whitelist) / + sizeof(wmi_whitelist_version_info); + my_vers.abi_version_0 = WMI_ABI_VERSION_0; + my_vers.abi_version_1 = WMI_ABI_VERSION_1; + my_vers.abi_version_ns_0 = WMI_ABI_VERSION_NS_0; + my_vers.abi_version_ns_1 = WMI_ABI_VERSION_NS_1; + my_vers.abi_version_ns_2 = WMI_ABI_VERSION_NS_2; + my_vers.abi_version_ns_3 = WMI_ABI_VERSION_NS_3; + + wmi_cmp_and_set_abi_version(num_whitelist, version_whitelist, + &my_vers, ¶m_buf->fixed_param->fw_abi_vers, + &cmd->host_abi_vers); + + WMA_LOGD("%s: INIT_CMD version: %d, %d, 0x%x, 0x%x, 0x%x, 0x%x", + __func__, WMI_VER_GET_MAJOR(cmd->host_abi_vers.abi_version_0), + WMI_VER_GET_MINOR(cmd->host_abi_vers.abi_version_0), + cmd->host_abi_vers.abi_version_ns_0, + cmd->host_abi_vers.abi_version_ns_1, + cmd->host_abi_vers.abi_version_ns_2, + cmd->host_abi_vers.abi_version_ns_3); + + vos_mem_copy(&wma_handle->final_abi_vers, &cmd->host_abi_vers, + sizeof(wmi_abi_version)); + return buf; +} + +/* Process service ready event and send wmi_init command */ +v_VOID_t wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) +{ + wmi_buf_t buf; + v_SIZE_t len; + tp_wma_handle wma_handle = (tp_wma_handle) handle; + struct wma_target_cap target_cap; + WMI_SERVICE_READY_EVENTID_param_tlvs *param_buf; + wmi_service_ready_event_fixed_param *ev; + int status; + + WMA_LOGD("%s: Enter", __func__); + + param_buf = (WMI_SERVICE_READY_EVENTID_param_tlvs *) cmd_param_info; + if (!(handle && param_buf)) { + WMA_LOGP("%s: Invalid arguments", __func__); + return; + } + + ev = param_buf->fixed_param; + if (!ev) { + WMA_LOGP("%s: Invalid buffer", __func__); + return; + } + + WMA_LOGA("WMA <-- WMI_SERVICE_READY_EVENTID"); + + wma_handle->phy_capability = ev->phy_capability; + wma_handle->max_frag_entry = ev->max_frag_entry; + wma_handle->num_rf_chains = ev->num_rf_chains; + vos_mem_copy(&wma_handle->reg_cap, param_buf->hal_reg_capabilities, + sizeof(HAL_REG_CAPABILITIES)); + wma_handle->ht_cap_info = ev->ht_cap_info; +#ifdef WLAN_FEATURE_11AC + wma_handle->vht_cap_info = ev->vht_cap_info; + wma_handle->vht_supp_mcs = ev->vht_supp_mcs; +#endif + wma_handle->txrx_chainmask = ev->txrx_chainmask; + + wma_handle->target_fw_version = ev->fw_build_vers; + + WMA_LOGE("%s: Firmware build version : %08x", + __func__, ev->fw_build_vers); + + if (ev->hw_bd_id) { + wma_handle->hw_bd_id = ev->hw_bd_id; + vos_mem_copy(wma_handle->hw_bd_info, + ev->hw_bd_info, sizeof(ev->hw_bd_info)); + + WMA_LOGE("%s: Board version: %x.%x", + __func__, + wma_handle->hw_bd_info[0], + wma_handle->hw_bd_info[1]); + } else { + wma_handle->hw_bd_id = 0; + vos_mem_zero(wma_handle->hw_bd_info, + sizeof(wma_handle->hw_bd_info)); + WMA_LOGE("%s: Board version is unknown!", __func__); + } + + /* TODO: Recheck below line to dump service ready event */ + /* dbg_print_wmi_service_11ac(ev); */ + + /* wmi service is ready */ + vos_mem_copy(wma_handle->wmi_service_bitmap, + param_buf->wmi_service_bitmap, + sizeof(wma_handle->wmi_service_bitmap)); + /* SWBA event handler for beacon transmission */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_HOST_SWBA_EVENTID, + wma_beacon_swba_handler); + if (status) { + WMA_LOGE("Failed to register swba beacon event cb"); + return; + } + +#ifdef WLAN_FEATURE_LPSS + wma_handle->lpss_support = + WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_LPASS); +#endif + /* + * This Service bit is added to check for ARP/NS offload + * support for LL or HL targets + */ + wma_handle->ap_arpns_support = + WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_AP_ARPNS_OFFLOAD); + + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_CSA_OFFLOAD)) { + WMA_LOGD("%s: FW support CSA offload capability", __func__); + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_CSA_HANDLING_EVENTID, + wma_csa_offload_handler); + if (status) { + WMA_LOGE("Failed to register CSA offload event cb"); + return; + } + } + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_GTK_OFFLOAD)) { + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_GTK_OFFLOAD_STATUS_EVENTID, + wma_gtk_offload_status_event); + if (status) { + WMA_LOGE("Failed to register GTK offload event cb"); + return; + } + } +#endif + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_P2P_NOA_EVENTID, + wma_p2p_noa_event_handler); + if (status) { + WMA_LOGE("Failed to register WMI_P2P_NOA_EVENTID callback"); + return; + } + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_TBTTOFFSET_UPDATE_EVENTID, + wma_tbttoffset_update_event_handler); + if (status) { + WMA_LOGE("Failed to register WMI_TBTTOFFSET_UPDATE_EVENTID callback"); + return; + } + + /* Initialize the log supported event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID, + wma_log_supported_evt_handler); + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to register log supported event cb"); + return; + } + + vos_mem_copy(target_cap.wmi_service_bitmap, + param_buf->wmi_service_bitmap, + sizeof(wma_handle->wmi_service_bitmap)); + target_cap.wlan_resource_config = wma_handle->wlan_resource_config; + wma_update_fw_config(wma_handle, &target_cap); + vos_mem_copy(wma_handle->wmi_service_bitmap, target_cap.wmi_service_bitmap, + sizeof(wma_handle->wmi_service_bitmap)); + wma_handle->wlan_resource_config = target_cap.wlan_resource_config; + + buf = wma_setup_wmi_init_msg(wma_handle, ev, param_buf, &len); + if (!buf) { + WMA_LOGE("Failed to setup buffer for wma init command"); + return; + } + + WMA_LOGA("WMA --> WMI_INIT_CMDID"); + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_INIT_CMDID); + if (status != EOK) { + WMA_LOGE("Failed to send WMI_INIT_CMDID command"); + wmi_buf_free(buf); + return; + } +} + +/* function : wma_rx_ready_event + * Description : + * Args : + * Retruns : + */ +v_VOID_t wma_rx_ready_event(WMA_HANDLE handle, void *cmd_param_info) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_READY_EVENTID_param_tlvs *param_buf = NULL; + wmi_ready_event_fixed_param *ev = NULL; + + WMA_LOGD("%s: Enter", __func__); + + param_buf = (WMI_READY_EVENTID_param_tlvs *) cmd_param_info; + if (!(wma_handle && param_buf)) { + WMA_LOGP("%s: Invalid arguments", __func__); + VOS_ASSERT(0); + return; + } + + WMA_LOGA("WMA <-- WMI_READY_EVENTID"); + + ev = param_buf->fixed_param; + /* Indicate to the waiting thread that the ready + * event was received */ + wma_handle->wmi_ready = TRUE; + wma_handle->wlan_init_status = ev->status; + + /* + * We need to check the WMI versions and make sure both + * host and fw are compatible. + */ + if (!wmi_versions_are_compatible(&wma_handle->final_abi_vers, + &ev->fw_abi_vers)) { + /* + * Error: Our host version and the given firmware version + * are incompatible. + */ + WMA_LOGE("%s: Error: Incompatible WMI version." + "Host: %d,%d,0x%x 0x%x 0x%x 0x%x, FW: %d,%d,0x%x 0x%x 0x%x 0x%x", + __func__, + WMI_VER_GET_MAJOR( + wma_handle->final_abi_vers.abi_version_0), + WMI_VER_GET_MINOR( + wma_handle->final_abi_vers.abi_version_0), + wma_handle->final_abi_vers.abi_version_ns_0, + wma_handle->final_abi_vers.abi_version_ns_1, + wma_handle->final_abi_vers.abi_version_ns_2, + wma_handle->final_abi_vers.abi_version_ns_3, + WMI_VER_GET_MAJOR(ev->fw_abi_vers.abi_version_0), + WMI_VER_GET_MINOR(ev->fw_abi_vers.abi_version_0), + ev->fw_abi_vers.abi_version_ns_0, + ev->fw_abi_vers.abi_version_ns_1, + ev->fw_abi_vers.abi_version_ns_2, + ev->fw_abi_vers.abi_version_ns_3); + if (wma_handle->wlan_init_status == WLAN_INIT_STATUS_SUCCESS) { + /* Failed this connection to FW */ + wma_handle->wlan_init_status = + WLAN_INIT_STATUS_GEN_FAILED; + } + } + vos_mem_copy(&wma_handle->final_abi_vers, &ev->fw_abi_vers, + sizeof(wmi_abi_version)); + vos_mem_copy(&wma_handle->target_abi_vers, &ev->fw_abi_vers, + sizeof(wmi_abi_version)); + + /* copy the mac addr */ + WMI_MAC_ADDR_TO_CHAR_ARRAY (&ev->mac_addr, wma_handle->myaddr); + WMI_MAC_ADDR_TO_CHAR_ARRAY (&ev->mac_addr, wma_handle->hwaddr); + + wma_update_hdd_cfg(wma_handle); + + vos_event_set(&wma_handle->wma_ready_event); + + WMA_LOGD("Exit"); +} + +int wma_set_peer_param(void *wma_ctx, u_int8_t *peer_addr, u_int32_t param_id, + u_int32_t param_value, u_int32_t vdev_id) +{ + tp_wma_handle wma_handle = (tp_wma_handle) wma_ctx; + wmi_peer_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + int err; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_param cmd"); + return -ENOMEM; + } + cmd = (wmi_peer_set_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_peer_set_param_cmd_fixed_param)); + cmd->vdev_id = vdev_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr); + cmd->param_id = param_id; + cmd->param_value = param_value; + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(wmi_peer_set_param_cmd_fixed_param), + WMI_PEER_SET_PARAM_CMDID); + if (err) { + WMA_LOGE("Failed to send set_param cmd"); + adf_os_mem_free(buf); + return -EIO; + } + + return 0; +} + +static void +wma_decap_to_8023 (adf_nbuf_t msdu, struct wma_decap_info_t *info) +{ + struct llc_snap_hdr_t *llc_hdr; + u_int16_t ether_type; + u_int16_t l2_hdr_space; + struct ieee80211_qosframe_addr4 *wh; + u_int8_t local_buf[ETHERNET_HDR_LEN]; + u_int8_t *buf; + struct ethernet_hdr_t *ethr_hdr; + + buf = (u_int8_t *)adf_nbuf_data(msdu); + llc_hdr = (struct llc_snap_hdr_t *)buf; + ether_type = (llc_hdr->ethertype[0] << 8)|llc_hdr->ethertype[1]; + /* do llc remove if needed */ + l2_hdr_space = 0; + if (IS_SNAP(llc_hdr)) { + if (IS_BTEP(llc_hdr)) { + /* remove llc*/ + l2_hdr_space += sizeof(struct llc_snap_hdr_t); + llc_hdr = NULL; + } else if (IS_RFC1042(llc_hdr)) { + if (!(ether_type == ETHERTYPE_AARP || + ether_type == ETHERTYPE_IPX)) { + /* remove llc*/ + l2_hdr_space += sizeof(struct llc_snap_hdr_t); + llc_hdr = NULL; + } + } + } + if (l2_hdr_space > ETHERNET_HDR_LEN) { + buf = adf_nbuf_pull_head(msdu, l2_hdr_space - ETHERNET_HDR_LEN); + } else if (l2_hdr_space < ETHERNET_HDR_LEN) { + buf = adf_nbuf_push_head(msdu, ETHERNET_HDR_LEN - l2_hdr_space); + } + + /* mpdu hdr should be present in info,re-create ethr_hdr based on mpdu hdr*/ + wh = (struct ieee80211_qosframe_addr4 *)info->hdr; + ethr_hdr = (struct ethernet_hdr_t *)local_buf; + switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, + ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr2, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr2, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, + ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr4, + ETHERNET_ADDR_LEN); + break; + } + + if (llc_hdr == NULL) { + ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; + ethr_hdr->ethertype[1] = (ether_type) & 0xff; + } else { + u_int32_t pktlen = adf_nbuf_len(msdu) - sizeof(ethr_hdr->ethertype); + ether_type = (u_int16_t)pktlen; + ether_type = adf_nbuf_len(msdu) - sizeof(struct ethernet_hdr_t); + ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; + ethr_hdr->ethertype[1] = (ether_type) & 0xff; + } + adf_os_mem_copy(buf, ethr_hdr, ETHERNET_HDR_LEN); +} + +static int32_t +wma_ieee80211_hdrsize(const void *data) +{ + const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data; + int32_t size = sizeof(struct ieee80211_frame); + + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) + size += IEEE80211_ADDR_LEN; + if (IEEE80211_QOS_HAS_SEQ(wh)) + size += sizeof(u_int16_t); + return size; +} + +/** + * WDA_TxPacket - Sends Tx Frame to TxRx + * This function sends the frame corresponding to the + * given vdev id. + * This is blocking call till the downloading of frame is complete. + */ +VOS_STATUS WDA_TxPacket(void *wma_context, void *tx_frame, u_int16_t frmLen, + eFrameType frmType, eFrameTxDir txDir, u_int8_t tid, + pWDATxRxCompFunc tx_frm_download_comp_cb, void *pData, + pWDAAckFnTxComp tx_frm_ota_comp_cb, u_int8_t tx_flag, + u_int8_t vdev_id, bool tdlsFlag) +{ + tp_wma_handle wma_handle = (tp_wma_handle)(wma_context); + int32_t status; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + int32_t is_high_latency; + ol_txrx_vdev_handle txrx_vdev; + ol_txrx_pdev_handle txrx_pdev; + pVosContextType vos_handle; + enum frame_index tx_frm_index = + GENERIC_NODOWNLD_NOACK_COMP_INDEX; + tpSirMacFrameCtl pFc = (tpSirMacFrameCtl)(adf_nbuf_data(tx_frame)); + u_int8_t use_6mbps = 0; + u_int8_t downld_comp_required = 0; + u_int16_t chanfreq; +#ifdef WLAN_FEATURE_11W + tANI_U8 *pFrame = NULL; + void *pPacket = NULL; + u_int16_t newFrmLen = 0; +#endif /* WLAN_FEATURE_11W */ + struct wma_txrx_node *iface; + tpAniSirGlobal pMac; +#ifdef QCA_PKT_PROTO_TRACE + v_U8_t proto_type = 0; +#endif + + if (NULL == wma_handle) + { + WMA_LOGE("wma_handle is NULL"); + return VOS_STATUS_E_FAILURE; + } + iface = &wma_handle->interfaces[vdev_id]; + pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, + wma_handle->vos_context); + /* Get the vdev handle from vdev id */ + txrx_vdev = wma_handle->interfaces[vdev_id].handle; + vos_handle = (pVosContextType)(wma_handle->vos_context); + /* Get the txRx Pdev handle */ + txrx_pdev = (ol_txrx_pdev_handle)(vos_handle->pdev_txrx_ctx); + + if(!txrx_vdev) { + WMA_LOGE("TxRx Vdev Handle is NULL"); + return VOS_STATUS_E_FAILURE; + } + +#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + txrx_vdev->hlTdlsFlag = false; +#endif + + if (frmType >= HAL_TXRX_FRM_MAX) { + WMA_LOGE("Invalid Frame Type Fail to send Frame"); + return VOS_STATUS_E_FAILURE; + } + + if(!pMac) { + WMA_LOGE("pMac Handle is NULL"); + return VOS_STATUS_E_FAILURE; + } + /* + * Currently only support to + * send 80211 Mgmt and 80211 Data are added. + */ + if (!((frmType == HAL_TXRX_FRM_802_11_MGMT) || + (frmType == HAL_TXRX_FRM_802_11_DATA))) { + WMA_LOGE("No Support to send other frames except 802.11 Mgmt/Data"); + return VOS_STATUS_E_FAILURE; + } +#ifdef WLAN_FEATURE_11W + if ((iface && iface->rmfEnabled) && + (frmType == HAL_TXRX_FRM_802_11_MGMT) && + (pFc->subType == SIR_MAC_MGMT_DISASSOC || + pFc->subType == SIR_MAC_MGMT_DEAUTH || + pFc->subType == SIR_MAC_MGMT_ACTION)) { + struct ieee80211_frame *wh = + (struct ieee80211_frame *)adf_nbuf_data(tx_frame); + if(!IEEE80211_IS_BROADCAST(wh->i_addr1) && + !IEEE80211_IS_MULTICAST(wh->i_addr1)) { + if (pFc->wep) { + /* Allocate extra bytes for privacy header and trailer */ + newFrmLen = frmLen + IEEE80211_CCMP_HEADERLEN + + IEEE80211_CCMP_MICLEN; + vos_status = palPktAlloc( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )newFrmLen, + ( void** ) &pFrame, + ( void** ) &pPacket ); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGP("%s: Failed to allocate %d bytes for RMF status " + "code (%x)", __func__, newFrmLen, vos_status); + /* Free the original packet memory */ + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + goto error; + } + + /* + * Initialize the frame with 0's and only fill + * MAC header and data, Keep the CCMP header and + * trailer as 0's, firmware shall fill this + */ + vos_mem_set( pFrame, newFrmLen , 0 ); + vos_mem_copy( pFrame, wh, sizeof(*wh)); + vos_mem_copy( pFrame + sizeof(*wh) + IEEE80211_CCMP_HEADERLEN, + pData + sizeof(*wh), frmLen - sizeof(*wh)); + + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + tx_frame = pPacket; + frmLen = newFrmLen; + } + } else { + /* Allocate extra bytes for MMIE */ + newFrmLen = frmLen + IEEE80211_MMIE_LEN; + vos_status = palPktAlloc( pMac->hHdd, + HAL_TXRX_FRM_802_11_MGMT, + ( tANI_U16 )newFrmLen, + ( void** ) &pFrame, + ( void** ) &pPacket ); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGP("%s: Failed to allocate %d bytes for RMF status " + "code (%x)", __func__, newFrmLen, vos_status); + /* Free the original packet memory */ + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + goto error; + } + /* + * Initialize the frame with 0's and only fill + * MAC header and data. MMIE field will be + * filled by vos_attach_mmie API + */ + vos_mem_set( pFrame, newFrmLen , 0 ); + vos_mem_copy( pFrame, wh, sizeof(*wh)); + vos_mem_copy( pFrame + sizeof(*wh), + pData + sizeof(*wh), frmLen - sizeof(*wh)); + if (!vos_attach_mmie(iface->key.key, + iface->key.key_id[0].ipn, + WMA_IGTK_KEY_INDEX_4, + pFrame, + pFrame+newFrmLen, newFrmLen)) { + WMA_LOGP("%s: Failed to attach MMIE at the end of " + "frame", __func__); + /* Free the original packet memory */ + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + goto error; + } + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, + ( void* ) pData, ( void* ) tx_frame ); + tx_frame = pPacket; + frmLen = newFrmLen; + } + } +#endif /* WLAN_FEATURE_11W */ + + if ((frmType == HAL_TXRX_FRM_802_11_MGMT) && + (pFc->subType == SIR_MAC_MGMT_PROBE_RSP)) { + u_int64_t adjusted_tsf_le; + struct ieee80211_frame *wh = + (struct ieee80211_frame *)adf_nbuf_data(tx_frame); + + /* Make the TSF offset negative to match TSF in beacons */ + adjusted_tsf_le = cpu_to_le64(0ULL - + wma_handle->interfaces[vdev_id].tsfadjust); + A_MEMCPY(&wh[1], &adjusted_tsf_le, sizeof(adjusted_tsf_le)); + } + if (frmType == HAL_TXRX_FRM_802_11_DATA) { + adf_nbuf_t ret; + adf_nbuf_t skb = (adf_nbuf_t)tx_frame; + ol_txrx_pdev_handle pdev = + vos_get_context(VOS_MODULE_ID_TXRX, wma_handle->vos_context); + + struct wma_decap_info_t decap_info; + struct ieee80211_frame *wh = + (struct ieee80211_frame *)adf_nbuf_data(skb); + v_TIME_t curr_timestamp = vos_timer_get_system_ticks(); + + if (pdev == NULL) { + WMA_LOGE("%s: pdev pointer is not available", __func__); + return VOS_STATUS_E_FAULT; + } + + /* + * 1) TxRx Module expects data input to be 802.3 format + * So Decapsulation has to be done. + * 2) Only one Outstanding Data pending for Ack is allowed + */ + if (tx_frm_ota_comp_cb) { + if (wma_handle->umac_data_ota_ack_cb) { + /* + * If last data frame was sent more than 5 seconds + * ago and still we did not receive ack/nack from + * fw then allow Tx of this data frame + */ + if (curr_timestamp >= + wma_handle->last_umac_data_ota_timestamp + 500) { + WMA_LOGE("%s: No Tx Ack for last data frame for more than 5 secs, allow Tx of current data frame", + __func__); + } else { + WMA_LOGE("%s: Already one Data pending for Ack, reject Tx of data frame", + __func__); + return VOS_STATUS_E_FAILURE; + } + } + } else { + /* + * Data Frames are sent through TxRx Non Standard Data Path + * so Ack Complete Cb is must + */ + WMA_LOGE("No Ack Complete Cb. Don't Allow"); + return VOS_STATUS_E_FAILURE; + } + + /* Take out 802.11 header from skb */ + decap_info.hdr_len = wma_ieee80211_hdrsize(wh); + adf_os_mem_copy(decap_info.hdr, wh, decap_info.hdr_len); + adf_nbuf_pull_head(skb, decap_info.hdr_len); + + /* Decapsulate to 802.3 format */ + wma_decap_to_8023(skb, &decap_info); + + /* Zero out skb's context buffer for the driver to use */ + adf_os_mem_set(skb->cb, 0, sizeof(skb->cb)); + + /* Do the DMA Mapping */ + adf_nbuf_map_single(pdev->osdev, skb, ADF_OS_DMA_TO_DEVICE); + + /* Terminate the (single-element) list of tx frames */ + skb->next = NULL; + + /* Store the Ack Complete Cb */ + wma_handle->umac_data_ota_ack_cb = tx_frm_ota_comp_cb; + + /* Store the timestamp and nbuf for this data Tx */ + wma_handle->last_umac_data_ota_timestamp = curr_timestamp; + wma_handle->last_umac_data_nbuf = skb; + + /* Send the Data frame to TxRx in Non Standard Path */ +#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + txrx_vdev->hlTdlsFlag = tdlsFlag; +#endif + ret = ol_tx_non_std(txrx_vdev, ol_tx_spec_no_free, skb); +#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) + txrx_vdev->hlTdlsFlag = false; +#endif + if (ret) { + WMA_LOGE("TxRx Rejected. Fail to do Tx"); + adf_nbuf_unmap_single(pdev->osdev, skb, ADF_OS_DMA_TO_DEVICE); + /* Call Download Cb so that umac can free the buffer */ + if (tx_frm_download_comp_cb) + tx_frm_download_comp_cb(wma_handle->mac_context, + tx_frame, + WMA_TX_FRAME_BUFFER_FREE); + wma_handle->umac_data_ota_ack_cb = NULL; + wma_handle->last_umac_data_nbuf = NULL; + return VOS_STATUS_E_FAILURE; + } + + /* Call Download Callback if passed */ + if (tx_frm_download_comp_cb) + tx_frm_download_comp_cb(wma_handle->mac_context, + tx_frame, + WMA_TX_FRAME_BUFFER_NO_FREE); + + return VOS_STATUS_SUCCESS; + } + + is_high_latency = wdi_out_cfg_is_high_latency( + txrx_vdev->pdev->ctrl_pdev); + + downld_comp_required = tx_frm_download_comp_cb && is_high_latency; + + /* Fill the frame index to send */ + if(pFc->type == SIR_MAC_MGMT_FRAME) { + if(tx_frm_ota_comp_cb) { + if(downld_comp_required) + tx_frm_index = + GENERIC_DOWNLD_COMP_ACK_COMP_INDEX; + else + tx_frm_index = + GENERIC_NODOWLOAD_ACK_COMP_INDEX; + + /* Store the Ack Cb sent by UMAC */ + if(pFc->subType < SIR_MAC_MGMT_RESERVED15) { + wma_handle->umac_ota_ack_cb[pFc->subType] = + tx_frm_ota_comp_cb; + } +#ifdef QCA_PKT_PROTO_TRACE + if (pFc->subType == SIR_MAC_MGMT_ACTION) + proto_type = vos_pkt_get_proto_type(tx_frame, + pMac->fEnableDebugLog, + NBUF_PKT_TRAC_TYPE_MGMT_ACTION); + if (proto_type & NBUF_PKT_TRAC_TYPE_MGMT_ACTION) + vos_pkt_trace_buf_update("WM:T:MACT"); + adf_nbuf_trace_set_proto_type(tx_frame, proto_type); +#endif /* QCA_PKT_PROTO_TRACE */ + } else { + if(downld_comp_required) + tx_frm_index = + GENERIC_DOWNLD_COMP_NOACK_COMP_INDEX; + else + tx_frm_index = + GENERIC_NODOWNLD_NOACK_COMP_INDEX; + } + } + + /* + * If Dowload Complete is required + * Wait for download complete + */ + if(downld_comp_required) { + /* Store Tx Comp Cb */ + wma_handle->tx_frm_download_comp_cb = tx_frm_download_comp_cb; + + /* Reset the Tx Frame Complete Event */ + vos_status = vos_event_reset( + &wma_handle->tx_frm_download_comp_event); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGP("%s: Event Reset failed tx comp event %x", + __func__, vos_status); + goto error; + } + } + + /* If the frame has to be sent at BD Rate2 inform TxRx */ + if(tx_flag & HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) + use_6mbps = 1; + + if (wma_handle->roam_preauth_scan_state == WMA_ROAM_PREAUTH_ON_CHAN) { + chanfreq = wma_handle->roam_preauth_chanfreq; + WMA_LOGI("%s: Preauth frame on channel %d", __func__, chanfreq); + } else if(pFc->subType == SIR_MAC_MGMT_PROBE_RSP){ + chanfreq = wma_handle->interfaces[vdev_id].mhz; + WMA_LOGI("%s: Probe response frame on channel %d", __func__, chanfreq); + WMA_LOGI("%s: Probe response frame on vdev id %d", __func__, vdev_id); + } else { + chanfreq = 0; + } + if (pMac->fEnableDebugLog & 0x1) { + if ((pFc->type == SIR_MAC_MGMT_FRAME) && + (pFc->subType != SIR_MAC_MGMT_PROBE_REQ) && + (pFc->subType != SIR_MAC_MGMT_PROBE_RSP)) { + WMA_LOGE("TX MGMT - Type %hu, SubType %hu", + pFc->type, pFc->subType); + } + } + /* Hand over the Tx Mgmt frame to TxRx */ + status = wdi_in_mgmt_send(txrx_vdev, tx_frame, tx_frm_index, use_6mbps, chanfreq); + + /* + * Failed to send Tx Mgmt Frame + */ + if (status) { + /* Call Download Cb so that umac can free the buffer */ + if (tx_frm_download_comp_cb) + tx_frm_download_comp_cb(wma_handle->mac_context, + tx_frame, + WMA_TX_FRAME_BUFFER_FREE); + WMA_LOGP("%s: Failed to send Mgmt Frame", __func__); + goto error; + } + + if (!tx_frm_download_comp_cb) + return VOS_STATUS_SUCCESS; + + /* + * Wait for Download Complete + * if required + */ + if (downld_comp_required) { + static uint8_t mgmt_downld_fail_count = 0; + /* + * Wait for Download Complete + * @ Integrated : Dxe Complete + * @ Discrete : Target Download Complete + */ + vos_status = vos_wait_single_event( + &wma_handle->tx_frm_download_comp_event, + WMA_TX_FRAME_COMPLETE_TIMEOUT); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + mgmt_downld_fail_count++; + WMA_LOGP("Wait Event failed txfrm_comp_event"); + /* + * @Integrated: Something Wrong with Dxe + * TODO: Some Debug Code + * Here We need to trigger SSR since + * since system went into a bad state where + * we didn't get Download Complete for almost + * WMA_TX_FRAME_COMPLETE_TIMEOUT (1 sec) + */ +#ifdef CONFIG_HL_SUPPORT + /* display scheduler stats */ + wdi_in_display_stats(txrx_pdev, WLAN_SCHEDULER_STATS); +#endif + WMA_LOGE("%s: download complete failure count:%d", + __func__, mgmt_downld_fail_count); + /* + * Inject crash only if max_mgmt_tx_fail_count is non + * zero value. + */ + if (wma_handle->max_mgmt_tx_fail_count && + mgmt_downld_fail_count == + wma_handle->max_mgmt_tx_fail_count) + wmi_crash_inject(wma_handle->wmi_handle, + RECOVERY_SIM_ASSERT, 0); + } else { + mgmt_downld_fail_count = 0; + } + } else { + /* + * For Low Latency Devices + * Call the download complete + * callback once the frame is successfully + * given to txrx module + */ + tx_frm_download_comp_cb(wma_handle->mac_context, tx_frame, + WMA_TX_FRAME_BUFFER_NO_FREE); + } + + return VOS_STATUS_SUCCESS; + +error: + wma_handle->tx_frm_download_comp_cb = NULL; + return VOS_STATUS_E_FAILURE; +} + +/* function :wma_setneedshutdown + * Description : + * Args : + * Returns : + */ +v_VOID_t wma_setneedshutdown(v_VOID_t *vos_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid arguments", __func__); + VOS_ASSERT(0); + return; + } + + wma_handle->needShutdown = TRUE; + WMA_LOGD("%s: Exit", __func__); +} + +/* function : wma_rx_ready_event + * Description : + * Args : + * Returns : + */ + v_BOOL_t wma_needshutdown(v_VOID_t *vos_ctx) + { + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid arguments", __func__); + VOS_ASSERT(0); + return 0; + } + + WMA_LOGD("%s: Exit", __func__); + return wma_handle->needShutdown; +} + +VOS_STATUS wma_wait_for_ready_event(WMA_HANDLE handle) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + VOS_STATUS vos_status; + + /* wait until WMI_READY_EVENTID received from FW */ + vos_status = vos_wait_single_event( &(wma_handle->wma_ready_event), + WMA_READY_EVENTID_TIMEOUT ); + + if (VOS_STATUS_SUCCESS != vos_status) { + WMA_LOGP("%s: Timeout waiting for ready event from FW", __func__); + vos_status = VOS_STATUS_E_FAILURE; + } + return vos_status; +} + +int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_pdev_suspend_cmd_fixed_param* cmd; + wmi_buf_t wmibuf; + u_int32_t len = sizeof(*cmd); + struct ol_softc *scn; +#ifdef CONFIG_CNSS + tpAniSirGlobal pmac; +#endif + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("WMA is closed. can not issue suspend cmd"); + return -EINVAL; + } + +#ifdef CONFIG_CNSS + pmac = vos_get_context(VOS_MODULE_ID_PE, wma_handle->vos_context); + if (!pmac) { + WMA_LOGE("%s: Unable to get PE context!", __func__); + return -EINVAL; + } +#endif + + /* + * send the comand to Target to ignore the + * PCIE reset so as to ensure that Host and target + * states are in sync + */ + wmibuf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (wmibuf == NULL) { + return -1; + } + + cmd = (wmi_pdev_suspend_cmd_fixed_param *) wmi_buf_data(wmibuf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_suspend_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_suspend_cmd_fixed_param)); + if (disable_target_intr) { + cmd->suspend_opt = WMI_PDEV_SUSPEND_AND_DISABLE_INTR; + } + else { + cmd->suspend_opt = WMI_PDEV_SUSPEND; + } + vos_event_reset(&wma_handle->target_suspend); + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len, + WMI_PDEV_SUSPEND_CMDID)) { + adf_nbuf_free(wmibuf); + return -1; + } + + + wmi_set_target_suspend(wma_handle->wmi_handle, TRUE); + + if (vos_wait_single_event(&wma_handle->target_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) + != VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to get ACK from firmware for pdev suspend"); + wmi_set_target_suspend(wma_handle->wmi_handle, FALSE); +#ifdef CONFIG_CNSS + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_WDA, NULL) || + vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + WMA_LOGE("%s: Unloading/Loading/LOGP is in progress, Ignore!", + __func__); + } else { + if (pmac->sme.enableSelfRecovery) { + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } + } +#endif + return -1; + } + + scn = vos_get_context(VOS_MODULE_ID_HIF,wma_handle->vos_context); + + if (scn == NULL) { + WMA_LOGE("%s: Failed to get HIF context", __func__); + VOS_ASSERT(0); + return -1; + } + + HTCCancelDeferredTargetSleep(scn); + + return 0; +} + +void wma_target_suspend_acknowledge(void *context) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + int wow_nack = *((int *)context); + + if (NULL == wma) { + WMA_LOGE("%s: wma is NULL", __func__); + return; + } + + wma->wow_nack = wow_nack; + vos_event_set(&wma->target_suspend); + if (wow_nack) + vos_wake_lock_timeout_acquire(&wma->wow_wake_lock, WMA_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_WOW); +} + +int wma_resume_target(WMA_HANDLE handle, int runtime_pm) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_buf_t wmibuf; + wmi_pdev_resume_cmd_fixed_param *cmd; + int ret; + int timeout = 0; + int wmi_pending_cmds; + + wmibuf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (wmibuf == NULL) { + return -1; + } + cmd = (wmi_pdev_resume_cmd_fixed_param *) wmi_buf_data(wmibuf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_resume_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_pdev_resume_cmd_fixed_param)); + cmd->reserved0 = 0; + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, sizeof(*cmd), + WMI_PDEV_RESUME_CMDID); + if(ret != EOK) { + WMA_LOGE("Failed to send WMI_PDEV_RESUME_CMDID command"); + wmi_buf_free(wmibuf); + } + + if (runtime_pm) + goto end; + + wmi_pending_cmds = wmi_get_pending_cmds(wma_handle->wmi_handle); + while (wmi_pending_cmds && timeout++ < WMA_MAX_RESUME_RETRY) { + msleep(10); + wmi_pending_cmds = wmi_get_pending_cmds(wma_handle->wmi_handle); + } + + if (wmi_pending_cmds) { + WMA_LOGE("Failed to deliver WMI_PDEV_RESUME_CMDID command %d\n", timeout); + ret = -1; + } + +end: + if (EOK == ret) + wmi_set_target_suspend(wma_handle->wmi_handle, FALSE); + + return ret; +} + +void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA) +{ +} +/* TODO: Below is stub should be removed later */ +void WDI_DS_ActivateTrafficStats(void) +{ +} +/* + * Function fills the rx packet meta info from the the vos packet + */ +VOS_STATUS WDA_DS_PeekRxPacketInfo(vos_pkt_t *pkt, v_PVOID_t *pkt_meta, + v_BOOL_t bSwap) +{ + /* Sanity Check */ + if(pkt == NULL) { + WMA_LOGE("wma:Invalid parameter sent on wma_peek_rx_pkt_info"); + return VOS_STATUS_E_FAULT; + } + + *pkt_meta = &(pkt->pkt_meta); + + return VOS_STATUS_SUCCESS; +} + +/* + * Function to lookup MAC address from vdev ID + */ +u_int8_t *wma_get_vdev_address_by_vdev_id(u_int8_t vdev_id) +{ + tp_wma_handle wma; + + wma = vos_get_context(VOS_MODULE_ID_WDA, + vos_get_global_context(VOS_MODULE_ID_WDA, NULL)); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return NULL; + } + + if (vdev_id >= wma->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id); + return NULL; + } + + return wma->interfaces[vdev_id].addr; +} + +/* + * Function to get the beacon buffer from vdev ID + * Note: The buffer returned must be freed explicitly by caller + */ +void *wma_get_beacon_buffer_by_vdev_id(u_int8_t vdev_id, u_int32_t *buffer_size) +{ + tp_wma_handle wma; + struct beacon_info *beacon; + u_int8_t *buf; + u_int32_t buf_size; + + wma = vos_get_context(VOS_MODULE_ID_WDA, + vos_get_global_context(VOS_MODULE_ID_WDA, NULL)); + + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return NULL; + } + + if (vdev_id >= wma->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id); + return NULL; + } + + if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) { + WMA_LOGE("%s: vdevid %d is not in AP mode", + __func__, vdev_id); + return NULL; + } + + beacon = wma->interfaces[vdev_id].beacon; + + if (!beacon) { + WMA_LOGE("%s: beacon invalid", __func__); + return NULL; + } + + adf_os_spin_lock_bh(&beacon->lock); + + buf_size = adf_nbuf_len(beacon->buf); + buf = adf_os_mem_alloc(NULL, buf_size); + + if (!buf) { + adf_os_spin_unlock_bh(&beacon->lock); + WMA_LOGE("%s: alloc failed for beacon buf", __func__); + return NULL; + } + + adf_os_mem_copy(buf, adf_nbuf_data(beacon->buf), buf_size); + + adf_os_spin_unlock_bh(&beacon->lock); + + if (buffer_size) + *buffer_size = buf_size; + + return buf; +} + +#if defined(QCA_WIFI_FTM) +int wma_utf_rsp(tp_wma_handle wma_handle, u_int8_t **payload, u_int32_t *len) +{ + int ret = -1; + u_int32_t payload_len; + + payload_len = wma_handle->utf_event_info.length; + if (payload_len) { + ret = 0; + + /* + * The first 4 bytes holds the payload size + * and the actual payload sits next to it + */ + *payload = (u_int8_t *)vos_mem_malloc((v_SIZE_t)payload_len + + sizeof(A_UINT32)); + *(A_UINT32*)&(*payload[0]) = wma_handle->utf_event_info.length; + memcpy(*payload + sizeof(A_UINT32), + wma_handle->utf_event_info.data, + payload_len); + wma_handle->utf_event_info.length = 0; + *len = payload_len; + } + + return ret; +} + +static void wma_post_ftm_response(tp_wma_handle wma_handle) +{ + int ret; + u_int8_t *payload; + u_int32_t data_len; + vos_msg_t msg = {0}; + VOS_STATUS status; + + ret = wma_utf_rsp(wma_handle, &payload, &data_len); + + if (ret) { + return; + } + + msg.type = SYS_MSG_ID_FTM_RSP; + msg.bodyptr = payload; + msg.bodyval = 0; + msg.reserved = SYS_MSG_COOKIE; + + status = vos_mq_post_message(VOS_MQ_ID_SYS, &msg); + + if (status != VOS_STATUS_SUCCESS) { + WMA_LOGE("failed to post ftm response to SYS"); + vos_mem_free(payload); + } +} + +static int +wma_process_utf_event(WMA_HANDLE handle, + u_int8_t *datap, u_int32_t dataplen) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + SEG_HDR_INFO_STRUCT segHdrInfo; + u_int8_t totalNumOfSegments,currentSeq; + WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf; + u_int8_t *data; + u_int32_t datalen; + + param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap; + if (!param_buf) { + WMA_LOGE("Get NULL point message from FW"); + return -EINVAL; + } + data = param_buf->data; + datalen = param_buf->num_data; + + + segHdrInfo = *(SEG_HDR_INFO_STRUCT *)&(data[0]); + + wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF); + + currentSeq = (segHdrInfo.segmentInfo & 0xF); + totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF; + + datalen = datalen - sizeof(segHdrInfo); + + if (currentSeq == 0) { + wma_handle->utf_event_info.expectedSeq = 0; + wma_handle->utf_event_info.offset = 0; + } else { + if (wma_handle->utf_event_info.expectedSeq != currentSeq) + WMA_LOGE("Mismatch in expecting seq expected" + " Seq %d got seq %d", + wma_handle->utf_event_info.expectedSeq, + currentSeq); + } + + memcpy(&wma_handle->utf_event_info.data[wma_handle->utf_event_info.offset], + &data[sizeof(segHdrInfo)], + datalen); + wma_handle->utf_event_info.offset = wma_handle->utf_event_info.offset + datalen; + wma_handle->utf_event_info.expectedSeq++; + + if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) { + if (wma_handle->utf_event_info.offset != segHdrInfo.len) + WMA_LOGE("All segs received total len mismatch.." + " len %zu total len %d", + wma_handle->utf_event_info.offset, + segHdrInfo.len); + + wma_handle->utf_event_info.length = wma_handle->utf_event_info.offset; + } + + wma_post_ftm_response(wma_handle); + + return 0; +} + +void wma_utf_detach(tp_wma_handle wma_handle) +{ + if (wma_handle->utf_event_info.data) { + vos_mem_free(wma_handle->utf_event_info.data); + wma_handle->utf_event_info.data = NULL; + wma_handle->utf_event_info.length = 0; + wmi_unified_unregister_event_handler(wma_handle->wmi_handle, + WMI_PDEV_UTF_EVENTID); + } +} + +void wma_utf_attach(tp_wma_handle wma_handle) +{ + int ret; + + wma_handle->utf_event_info.data = (unsigned char *) + vos_mem_malloc(MAX_UTF_EVENT_LENGTH); + wma_handle->utf_event_info.length = 0; + + ret = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PDEV_UTF_EVENTID, + wma_process_utf_event); + + if (ret) + WMA_LOGP("%s: Failed to register UTF event callback", __func__); +} + +static int +wmi_unified_pdev_utf_cmd(wmi_unified_t wmi_handle, u_int8_t *utf_payload, + u_int16_t len) +{ + wmi_buf_t buf; + u_int8_t *cmd; + int ret = 0; + static u_int8_t msgref = 1; + u_int8_t segNumber = 0, segInfo, numSegments; + u_int16_t chunk_len, total_bytes; + u_int8_t *bufpos; + SEG_HDR_INFO_STRUCT segHdrInfo; + + bufpos = utf_payload; + total_bytes = len; + ASSERT(total_bytes / MAX_WMI_UTF_LEN == + (u_int8_t)(total_bytes / MAX_WMI_UTF_LEN)); + numSegments = (u_int8_t)(total_bytes / MAX_WMI_UTF_LEN); + + if (len - (numSegments * MAX_WMI_UTF_LEN)) + numSegments++; + + while (len) { + if (len > MAX_WMI_UTF_LEN) + chunk_len = MAX_WMI_UTF_LEN; /* MAX messsage */ + else + chunk_len = len; + + buf = wmi_buf_alloc(wmi_handle, + (chunk_len + sizeof(segHdrInfo) + + WMI_TLV_HDR_SIZE)); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -1; + } + + cmd = (u_int8_t *)wmi_buf_data(buf); + + segHdrInfo.len = total_bytes; + segHdrInfo.msgref = msgref; + segInfo = ((numSegments << 4 ) & 0xF0) | (segNumber & 0xF); + segHdrInfo.segmentInfo = segInfo; + segHdrInfo.pad = 0; + + WMA_LOGD("%s:segHdrInfo.len = %d, segHdrInfo.msgref = %d," + " segHdrInfo.segmentInfo = %d", + __func__, segHdrInfo.len, segHdrInfo.msgref, + segHdrInfo.segmentInfo); + + WMA_LOGD("%s:total_bytes %d segNumber %d totalSegments %d" + "chunk len %d", __func__, total_bytes, segNumber, + numSegments, chunk_len); + + segNumber++; + + WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, + (chunk_len + sizeof(segHdrInfo))); + cmd += WMI_TLV_HDR_SIZE; + memcpy(cmd, &segHdrInfo, sizeof(segHdrInfo)); /* 4 bytes */ + memcpy(&cmd[sizeof(segHdrInfo)], bufpos, chunk_len); + + ret = wmi_unified_cmd_send(wmi_handle, buf, + (chunk_len + sizeof(segHdrInfo) + + WMI_TLV_HDR_SIZE), + WMI_PDEV_UTF_CMDID); + + if (ret != EOK) { + WMA_LOGE("Failed to send WMI_PDEV_UTF_CMDID command"); + wmi_buf_free(buf); + break; + } + + len -= chunk_len; + bufpos += chunk_len; + } + + msgref++; + + return ret; +} + +int wma_utf_cmd(tp_wma_handle wma_handle, u_int8_t *data, u_int16_t len) +{ + wma_handle->utf_event_info.length = 0; + return wmi_unified_pdev_utf_cmd(wma_handle->wmi_handle, data, len); +} + +static VOS_STATUS +wma_process_ftm_command(tp_wma_handle wma_handle, + struct ar6k_testmode_cmd_data *msg_buffer) +{ + u_int8_t *data = NULL; + u_int16_t len = 0; + int ret; + + if (!msg_buffer) + return VOS_STATUS_E_INVAL; + + if (vos_get_conparam() != VOS_FTM_MODE) { + WMA_LOGE("FTM command issued in non-FTM mode"); + vos_mem_free(msg_buffer->data); + vos_mem_free(msg_buffer); + return VOS_STATUS_E_NOSUPPORT; + } + + data = msg_buffer->data; + len = msg_buffer->len; + + ret = wma_utf_cmd(wma_handle, data, len); + + vos_mem_free(msg_buffer->data); + vos_mem_free(msg_buffer); + + if (ret) + return VOS_STATUS_E_FAILURE; + + return VOS_STATUS_SUCCESS; +} +#endif + +/* Function to enable/disble Low Power Support(Pdev Specific) */ +VOS_STATUS WDA_SetIdlePsConfig(void *wda_handle, tANI_U32 idle_ps) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle)wda_handle; + + WMA_LOGD("WMA Set Idle Ps Config [1:set 0:clear] val %d", idle_ps); + + /* Set Idle Mode Power Save Config */ + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_IDLE_PS_CONFIG, idle_ps); + if(ret) { + WMA_LOGE("Fail to Set Idle Ps Config %d", idle_ps); + return VOS_STATUS_E_FAILURE; + } + + WMA_LOGD("Successfully Set Idle Ps Config %d", idle_ps); + return VOS_STATUS_SUCCESS; +} + +eHalStatus wma_set_htconfig(tANI_U8 vdev_id, tANI_U16 ht_capab, int value) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + int ret = -EIO; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return eHAL_STATUS_INVALID_PARAMETER; + } + + switch (ht_capab) { + case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_LDPC, value); + break; + case WNI_CFG_HT_CAP_INFO_TX_STBC: + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TX_STBC, value); + break; + case WNI_CFG_HT_CAP_INFO_RX_STBC: + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_RX_STBC, value); + break; + case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: + case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: + WMA_LOGE("%s: ht_capab = %d, value = %d", __func__, ht_capab, value); + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_SGI, value); + if (ret == 0) + wma->interfaces[vdev_id].config.shortgi = value; + break; + default: + WMA_LOGE("%s:INVALID HT CONFIG", __func__); + } + + return (ret)? eHAL_STATUS_FAILURE : eHAL_STATUS_SUCCESS; +} + +eHalStatus WMA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, + tAniBool sendRegHint) +{ + if(VOS_STATUS_SUCCESS != vos_nv_setRegDomain(clientCtxt, regId, sendRegHint)) + return eHAL_STATUS_INVALID_PARAMETER; + + return eHAL_STATUS_SUCCESS; +} + +tANI_U8 wma_getFwWlanFeatCaps(tANI_U8 featEnumValue) +{ + return ((gFwWlanFeatCaps & (1 << featEnumValue)) ? TRUE : FALSE); +} + +void wma_send_regdomain_info(u_int32_t reg_dmn, u_int16_t regdmn2G, + u_int16_t regdmn5G, int8_t ctl2G, int8_t ctl5G) +{ + wmi_buf_t buf; + wmi_pdev_set_regdomain_cmd_fixed_param *cmd; + int32_t len = sizeof(*cmd); + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + int32_t cck_mask_val = 0; + int ret = 0; + + if (NULL == wma) { + WMA_LOGE("%s: wma context is NULL", __func__); + return; + } + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return; + } + + cmd = (wmi_pdev_set_regdomain_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_pdev_set_regdomain_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_set_regdomain_cmd_fixed_param)); + cmd->reg_domain = reg_dmn; + cmd->reg_domain_2G = regdmn2G; + cmd->reg_domain_5G = regdmn5G; + cmd->conformance_test_limit_2G = ctl2G; + cmd->conformance_test_limit_5G = ctl5G; + + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PDEV_SET_REGDOMAIN_CMDID)) { + WMA_LOGP("%s: Failed to send pdev set regdomain command", + __func__); + adf_nbuf_free(buf); + } + + if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) || + ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) && + (true == wma->tx_chain_mask_cck)) + cck_mask_val = 1; + + cck_mask_val |= (wma->self_gen_frm_pwr << 16); + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK, + cck_mask_val); + if (ret) { + WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d", + ret); + } + + return; +} + +void wma_get_modeselect(tp_wma_handle wma, u_int32_t *modeSelect) +{ + + switch (wma->phy_capability) { + case WMI_11G_CAPABILITY: + case WMI_11NG_CAPABILITY: + *modeSelect &= ~(REGDMN_MODE_11A | REGDMN_MODE_TURBO | + REGDMN_MODE_108A | REGDMN_MODE_11A_HALF_RATE | + REGDMN_MODE_11A_QUARTER_RATE | REGDMN_MODE_11NA_HT20 | + REGDMN_MODE_11NA_HT40PLUS | REGDMN_MODE_11NA_HT40MINUS | + REGDMN_MODE_11AC_VHT20 | REGDMN_MODE_11AC_VHT40PLUS | + REGDMN_MODE_11AC_VHT40MINUS | REGDMN_MODE_11AC_VHT80); + break; + case WMI_11A_CAPABILITY: + case WMI_11NA_CAPABILITY: + case WMI_11AC_CAPABILITY: + *modeSelect &= ~(REGDMN_MODE_11B | REGDMN_MODE_11G | + REGDMN_MODE_108G | REGDMN_MODE_11NG_HT20 | + REGDMN_MODE_11NG_HT40PLUS | REGDMN_MODE_11NG_HT40MINUS | + REGDMN_MODE_11AC_VHT20_2G | REGDMN_MODE_11AC_VHT40_2G | + REGDMN_MODE_11AC_VHT80_2G); + break; + } +} + +tANI_U8 wma_map_channel(tANI_U8 mapChannel) +{ + return mapChannel; +} + +static eHalStatus wma_set_mimops(tp_wma_handle wma, tANI_U8 vdev_id, int value) +{ + int ret = eHAL_STATUS_SUCCESS; + wmi_sta_smps_force_mode_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_sta_smps_force_mode_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_smps_force_mode_cmd_fixed_param)); + + cmd->vdev_id = vdev_id; + + /* WMI_SMPS_FORCED_MODE values do not directly map + * to SM power save values defined in the specification. + * Make sure to send the right mapping. + */ + switch(value) + { + case 0: + cmd->forced_mode = WMI_SMPS_FORCED_MODE_NONE; + break; + case 1: + cmd->forced_mode = WMI_SMPS_FORCED_MODE_DISABLED; + break; + case 2: + cmd->forced_mode = WMI_SMPS_FORCED_MODE_STATIC; + break; + case 3: + cmd->forced_mode = WMI_SMPS_FORCED_MODE_DYNAMIC; + break; + default: + WMA_LOGE("%s:INVALID Mimo PS CONFIG", __func__); + return eHAL_STATUS_FAILURE; + } + + WMA_LOGD("Setting vdev %d value = %u", vdev_id, value); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_STA_SMPS_FORCE_MODE_CMDID); + if (ret < 0) { + WMA_LOGE("Failed to send set Mimo PS ret = %d", ret); + wmi_buf_free(buf); + } + + return ret; +} + +static eHalStatus wma_set_ppsconfig(tANI_U8 vdev_id, tANI_U16 pps_param, int val) +{ + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context); + int ret = -EIO; + u_int32_t pps_val; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return eHAL_STATUS_INVALID_PARAMETER; + } + + switch (pps_param) { + case WMA_VHT_PPS_PAID_MATCH: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_PAID_MATCH & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_GID_MATCH: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_GID_MATCH & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_DELIM_CRC_FAIL: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_DELIM_CRC_FAIL & 0xffff); + goto pkt_pwr_save_config; + + /* Enable the code below as and when the functionality + * is supported/added in host. + */ +#ifdef NOT_YET + case WMA_VHT_PPS_EARLY_TIM_CLEAR: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EARLY_TIM_CLEAR & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_EARLY_DTIM_CLEAR: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EARLY_DTIM_CLEAR & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_EOF_PAD_DELIM: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_EOF_PAD_DELIM & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_MACADDR_MISMATCH: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_MACADDR_MISMATCH & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_GID_NSTS_ZERO: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_GID_NSTS_ZERO & 0xffff); + goto pkt_pwr_save_config; + case WMA_VHT_PPS_RSSI_CHECK: + pps_val = ((val << 31) & 0xffff0000) | + (PKT_PWR_SAVE_RSSI_CHECK & 0xffff); + goto pkt_pwr_save_config; +#endif +pkt_pwr_save_config: + WMA_LOGD("vdev_id:%d val:0x%x pps_val:0x%x", vdev_id, + val, pps_val); + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_PACKET_POWERSAVE, pps_val); + break; + default: + WMA_LOGE("%s:INVALID PPS CONFIG", __func__); + } + + return (ret)? eHAL_STATUS_FAILURE : eHAL_STATUS_SUCCESS; +} + +#ifdef FEATURE_WLAN_TDLS +static int wma_set_tdls_offchan_mode(WMA_HANDLE handle, + tTdlsChanSwitchParams* pChanSwitchParams) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_tdls_set_offchan_mode_cmd_fixed_param* cmd; + wmi_buf_t wmi_buf; + u_int16_t len = sizeof(wmi_tdls_set_offchan_mode_cmd_fixed_param); + int ret = 0; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue tdls off channel cmd", + __func__); + ret = -EINVAL; + goto end; + } + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmai_buf_alloc failed", __func__); + ret = -ENOMEM; + goto end; + } + cmd = (wmi_tdls_set_offchan_mode_cmd_fixed_param*)wmi_buf_data(wmi_buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_set_offchan_mode_cmd_fixed_param)); + + WMI_CHAR_ARRAY_TO_MAC_ADDR(pChanSwitchParams->peerMacAddr, + &cmd->peer_macaddr); + cmd->vdev_id = pChanSwitchParams->vdevId; + cmd->offchan_mode = pChanSwitchParams->tdlsSwMode; + cmd->is_peer_responder = pChanSwitchParams->is_responder; + cmd->offchan_num = pChanSwitchParams->tdlsOffCh; + cmd->offchan_bw_bitmap = pChanSwitchParams->tdlsOffChBwOffset; + cmd->offchan_oper_class = pChanSwitchParams->operClass; + + WMA_LOGD("%s: Peer MAC Addr mac_addr31to0: 0x%x, " + "mac_addr47to32: 0x%x", + __func__, cmd->peer_macaddr.mac_addr31to0, + cmd->peer_macaddr.mac_addr47to32); + + WMA_LOGD("%s: vdev_id: %d, " + "off channel mode: %d, " + "off channel Num: %d, " + "off channel offset: 0x%x, " + "is_peer_responder: %d, " + "operating class: %d, ", + __func__, cmd->vdev_id, + cmd->offchan_mode, + cmd->offchan_num, + cmd->offchan_bw_bitmap, + cmd->is_peer_responder, + cmd->offchan_oper_class); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_TDLS_SET_OFFCHAN_MODE_CMDID)) { + WMA_LOGP("%s: failed to send tdls off chan command", __func__); + adf_nbuf_free(wmi_buf); + ret = -EIO; + } + +end: + if (pChanSwitchParams) + vos_mem_free(pChanSwitchParams); + return ret; +} + +/* wmi tdls command sent to firmware to enable/disable tdls for a vdev */ +static int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_tdls_set_state_cmd_fixed_param* cmd; + wmi_buf_t wmi_buf; + t_wma_tdls_mode tdls_mode; + t_wma_tdls_params *wma_tdls = (t_wma_tdls_params *)pwmaTdlsparams; + u_int16_t len = sizeof(wmi_tdls_set_state_cmd_fixed_param); + int ret = 0; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue fw tdls state cmd", + __func__); + ret = -EINVAL; + goto end_fw_tdls_state; + } + + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmai_buf_alloc failed", __func__); + ret = ENOMEM; + goto end_fw_tdls_state; + } + tdls_mode = wma_tdls->tdls_state; + cmd = (wmi_tdls_set_state_cmd_fixed_param *)wmi_buf_data(wmi_buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_set_state_cmd_fixed_param)); + cmd->vdev_id = wma_tdls->vdev_id; + + if (WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode) { + cmd->state = WMI_TDLS_ENABLE_PASSIVE; + } else if (WMA_TDLS_SUPPORT_ENABLED == tdls_mode) { + cmd->state = WMI_TDLS_ENABLE_ACTIVE; + } else if (WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL == tdls_mode) { + cmd->state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL; + } else { + cmd->state = WMI_TDLS_DISABLE; + } + + cmd->notification_interval_ms = wma_tdls->notification_interval_ms; + cmd->tx_discovery_threshold = wma_tdls->tx_discovery_threshold; + cmd->tx_teardown_threshold = wma_tdls->tx_teardown_threshold; + cmd->rssi_teardown_threshold = wma_tdls->rssi_teardown_threshold; + cmd->rssi_delta = wma_tdls->rssi_delta; + cmd->tdls_options = wma_tdls->tdls_options; + cmd->tdls_peer_traffic_ind_window = + wma_tdls->peer_traffic_ind_window; + cmd->tdls_peer_traffic_response_timeout_ms = + wma_tdls->peer_traffic_response_timeout; + cmd->tdls_puapsd_mask = + wma_tdls->puapsd_mask; + cmd->tdls_puapsd_inactivity_time_ms = + wma_tdls->puapsd_inactivity_time; + cmd->tdls_puapsd_rx_frame_threshold = + wma_tdls->puapsd_rx_frame_threshold; + cmd->teardown_notification_ms = + wma_tdls->teardown_notification_ms; + cmd->tdls_peer_kickout_threshold = + wma_tdls->tdls_peer_kickout_threshold; + + + + WMA_LOGD("%s: tdls_mode: %d, state: %d, " + "notification_interval_ms: %d, " + "tx_discovery_threshold: %d, " + "tx_teardown_threshold: %d, " + "rssi_teardown_threshold: %d, " + "rssi_delta: %d, " + "tdls_options: 0x%x, " + "tdls_peer_traffic_ind_window: %d, " + "tdls_peer_traffic_response_timeout: %d, " + "tdls_puapsd_mask: 0x%x, " + "tdls_puapsd_inactivity_time: %d, " + "tdls_puapsd_rx_frame_threshold: %d, " + "teardown_notification_ms: %d, " + "tdls_peer_kickout_threshold: %d ", + __func__, tdls_mode, cmd->state, + cmd->notification_interval_ms, + cmd->tx_discovery_threshold, + cmd->tx_teardown_threshold, + cmd->rssi_teardown_threshold, + cmd->rssi_delta, + cmd->tdls_options, + cmd->tdls_peer_traffic_ind_window, + cmd->tdls_peer_traffic_response_timeout_ms, + cmd->tdls_puapsd_mask, + cmd->tdls_puapsd_inactivity_time_ms, + cmd->tdls_puapsd_rx_frame_threshold, + cmd->teardown_notification_ms, + cmd->tdls_peer_kickout_threshold); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_TDLS_SET_STATE_CMDID)) { + WMA_LOGP("%s: failed to send tdls set state command", __func__); + adf_nbuf_free(wmi_buf); + ret = -EIO; + goto end_fw_tdls_state; + } + WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id); + +end_fw_tdls_state: + if (pwmaTdlsparams) + vos_mem_free(pwmaTdlsparams); + return ret; +} + +static int wma_update_tdls_peer_state(WMA_HANDLE handle, + tTdlsPeerStateParams *peerStateParams) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_tdls_peer_update_cmd_fixed_param* cmd; + wmi_tdls_peer_capabilities *peer_cap; + wmi_channel *chan_info; + wmi_buf_t wmi_buf; + u_int8_t *buf_ptr; + u_int32_t i; + ol_txrx_pdev_handle pdev; + u_int8_t peer_id; + struct ol_txrx_peer_t *peer; + int32_t len = sizeof(wmi_tdls_peer_update_cmd_fixed_param) + + sizeof(wmi_tdls_peer_capabilities); + int ret = 0; +#if defined(CONFIG_HL_SUPPORT) + struct ol_txrx_vdev_t *vdev; + bool restore_last_peer = false; +#endif + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + ret = -EINVAL; + goto end_tdls_peer_state; + } + + /* peer capability info is valid only when peer state is connected */ + if (WDA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) { + vos_mem_zero(&peerStateParams->peerCap, sizeof(tTdlsPeerCapParams)); + } + + len += WMI_TLV_HDR_SIZE + + sizeof(wmi_channel) * peerStateParams->peerCap.peerChanLen; + + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + ret = ENOMEM; + goto end_tdls_peer_state; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + cmd = (wmi_tdls_peer_update_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_peer_update_cmd_fixed_param)); + + cmd->vdev_id = peerStateParams->vdevId; + WMI_CHAR_ARRAY_TO_MAC_ADDR(peerStateParams->peerMacAddr, &cmd->peer_macaddr); + + switch (peerStateParams->peerState) { + case WDA_TDLS_PEER_STATE_PEERING: + cmd->peer_state = WMI_TDLS_PEER_STATE_PEERING; + break; + case WDA_TDLS_PEER_STATE_CONNECTED: + cmd->peer_state = WMI_TDLS_PEER_STATE_CONNECTED; + break; + case WDA_TDLS_PEER_STATE_TEARDOWN: + cmd->peer_state = WMI_TDLS_PEER_STATE_TEARDOWN; + break; + case WDA_TDLS_PEER_ADD_MAC_ADDR: + cmd->peer_state = WMI_TDLS_PEER_ADD_MAC_ADDR; + break; + case WDA_TDLS_PEER_REMOVE_MAC_ADDR: + cmd->peer_state = WMI_TDLS_PEER_REMOVE_MAC_ADDR; + break; + + } + + WMA_LOGD("%s: vdev_id: %d, peerStateParams->peerMacAddr: %pM, " + "peer_macaddr.mac_addr31to0: 0x%x, " + "peer_macaddr.mac_addr47to32: 0x%x, peer_state: %d", + __func__, cmd->vdev_id, peerStateParams->peerMacAddr, + cmd->peer_macaddr.mac_addr31to0, + cmd->peer_macaddr.mac_addr47to32, cmd->peer_state); + + buf_ptr += sizeof(wmi_tdls_peer_update_cmd_fixed_param); + peer_cap = (wmi_tdls_peer_capabilities *) buf_ptr; + WMITLV_SET_HDR(&peer_cap->tlv_header, + WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities, + WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_peer_capabilities)); + + if ((peerStateParams->peerCap.peerUapsdQueue & 0x08) >> 3) + WMI_SET_TDLS_PEER_VO_UAPSD(peer_cap); + if ((peerStateParams->peerCap.peerUapsdQueue & 0x04) >> 2) + WMI_SET_TDLS_PEER_VI_UAPSD(peer_cap); + if ((peerStateParams->peerCap.peerUapsdQueue & 0x02) >> 1) + WMI_SET_TDLS_PEER_BK_UAPSD(peer_cap); + if (peerStateParams->peerCap.peerUapsdQueue & 0x01) + WMI_SET_TDLS_PEER_BE_UAPSD(peer_cap); + + /* Ack and More Data Ack are sent as 0, so no need to set + * but fill SP + */ + WMI_SET_TDLS_PEER_SP_UAPSD(peer_cap, peerStateParams->peerCap.peerMaxSp); + + peer_cap->buff_sta_support = + peerStateParams->peerCap.peerBuffStaSupport; + peer_cap->off_chan_support = + peerStateParams->peerCap.peerOffChanSupport; + peer_cap->peer_curr_operclass = + peerStateParams->peerCap.peerCurrOperClass; + /* self curr operclass is not being used and so pass op class for + * preferred off chan in it. + */ + peer_cap->self_curr_operclass = + peerStateParams->peerCap.opClassForPrefOffChan; + peer_cap->peer_chan_len = + peerStateParams->peerCap.peerChanLen; + peer_cap->peer_operclass_len = + peerStateParams->peerCap.peerOperClassLen; + + WMA_LOGD("%s: peer_operclass_len: %d", + __func__, peer_cap->peer_operclass_len); + for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++) { + peer_cap->peer_operclass[i] = + peerStateParams->peerCap.peerOperClass[i]; + WMA_LOGD("%s: peer_operclass[%d]: %d", + __func__, i, peer_cap->peer_operclass[i]); + } + + peer_cap->is_peer_responder = + peerStateParams->peerCap.isPeerResponder; + peer_cap->pref_offchan_num = + peerStateParams->peerCap.prefOffChanNum; + peer_cap->pref_offchan_bw = + peerStateParams->peerCap.prefOffChanBandwidth; + + WMA_LOGD("%s: peer_qos: 0x%x, buff_sta_support: %d, off_chan_support: %d, peer_curr_operclass: %d, self_curr_operclass: %d, peer_chan_len: %d, peer_operclass_len: %d, is_peer_responder: %d, pref_offchan_num: %d, pref_offchan_bw: %d", + __func__, peer_cap->peer_qos, peer_cap->buff_sta_support, + peer_cap->off_chan_support, peer_cap->peer_curr_operclass, + peer_cap->self_curr_operclass, peer_cap->peer_chan_len, + peer_cap->peer_operclass_len, peer_cap->is_peer_responder, + peer_cap->pref_offchan_num, peer_cap->pref_offchan_bw); + + /* next fill variable size array of peer chan info */ + buf_ptr += sizeof(wmi_tdls_peer_capabilities); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_channel) * peerStateParams->peerCap.peerChanLen); + chan_info = (wmi_channel *) (buf_ptr + WMI_TLV_HDR_SIZE); + + for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) { + WMITLV_SET_HDR(&chan_info->tlv_header, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + chan_info->mhz = + vos_chan_to_freq(peerStateParams->peerCap.peerChan[i].chanId); + chan_info->band_center_freq1 = chan_info->mhz; + chan_info->band_center_freq2 = 0; + + WMA_LOGD("%s: chan[%d] = %u", __func__, i, chan_info->mhz); + + if (peerStateParams->peerCap.peerChan[i].dfsSet) { + WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE); + WMA_LOGI("chan[%d] DFS[%d]\n", + peerStateParams->peerCap.peerChan[i].chanId, + peerStateParams->peerCap.peerChan[i].dfsSet); + } + + if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) { + WMI_SET_CHANNEL_MODE(chan_info, MODE_11G); + } else { + WMI_SET_CHANNEL_MODE(chan_info, MODE_11A); + } + + WMI_SET_CHANNEL_MAX_TX_POWER(chan_info, + peerStateParams->peerCap.peerChan[i].pwr); + + WMI_SET_CHANNEL_REG_POWER(chan_info, + peerStateParams->peerCap.peerChan[i].pwr); + WMA_LOGD("Channel TX power[%d] = %u: %d", i, chan_info->mhz, + peerStateParams->peerCap.peerChan[i].pwr); + + chan_info++; + } + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_TDLS_PEER_UPDATE_CMDID)) { + WMA_LOGE("%s: failed to send tdls peer update state command", + __func__); + adf_nbuf_free(wmi_buf); + ret = -EIO; + goto end_tdls_peer_state; + } + + /* in case of teardown, remove peer from fw */ + if (WDA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) { + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma_handle->vos_context); + if (!pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + ret = -EIO; + goto end_tdls_peer_state; + } + + peer = ol_txrx_find_peer_by_addr(pdev, peerStateParams->peerMacAddr, + &peer_id); + if (!peer) { + WMA_LOGE("%s: Failed to get peer handle using peer mac %pM", + __func__, peerStateParams->peerMacAddr); + ret = -EIO; + goto end_tdls_peer_state; + } + +#if defined(CONFIG_HL_SUPPORT) + vdev = peer->vdev; + if (vdev->last_real_peer && (vdev->last_real_peer == peer)) + restore_last_peer = true; +#endif + + WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR + " vdevId: %d", __func__, + MAC_ADDR_ARRAY(peer->mac_addr.raw), peerStateParams->vdevId); + wma_remove_peer(wma_handle, peer->mac_addr.raw, + peerStateParams->vdevId, peer, + VOS_FALSE); +#if defined(CONFIG_HL_SUPPORT) + if (restore_last_peer && (vdev->last_real_peer == NULL)) { + peer = NULL; + peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); + if (peer && (peer->peer_ids[0] != HTT_INVALID_PEER_ID)) + vdev->last_real_peer = peer; + } +#endif + } + +end_tdls_peer_state: + if (peerStateParams) + vos_mem_free(peerStateParams); + return ret; +} +#endif /* FEATURE_WLAN_TDLS */ + +/* + * Attach DFS methods to the umac state. + */ +struct ieee80211com* wma_dfs_attach(struct ieee80211com *dfs_ic) +{ + /*Allocate memory for dfs_ic before passing it up to dfs_attach()*/ + dfs_ic = (struct ieee80211com *) + OS_MALLOC(NULL, sizeof(struct ieee80211com), GFP_ATOMIC); + if (dfs_ic == NULL) + { + WMA_LOGE("%s:Allocation of dfs_ic failed %zu", + __func__, sizeof(struct ieee80211com)); + return NULL; + } + OS_MEMZERO(dfs_ic, sizeof (struct ieee80211com)); + /* DFS pattern matching hooks */ + dfs_ic->ic_dfs_attach = ol_if_dfs_attach; + dfs_ic->ic_dfs_disable = ol_if_dfs_disable; + dfs_ic->ic_find_channel = ieee80211_find_channel; + dfs_ic->ic_dfs_enable = ol_if_dfs_enable; + dfs_ic->ic_ieee2mhz = ieee80211_ieee2mhz; + + /* Hardware facing hooks */ + dfs_ic->ic_get_ext_busy = ol_if_dfs_get_ext_busy; + dfs_ic->ic_get_mib_cycle_counts_pct = + ol_if_dfs_get_mib_cycle_counts_pct; + dfs_ic->ic_get_TSF64 = ol_if_get_tsf64; + + /* NOL related hooks */ + dfs_ic->ic_dfs_usenol = ol_if_dfs_usenol; + /* + * Hooks from wma/dfs/ back + * into the PE/SME + * and shared DFS code + */ + dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs; + adf_os_spinlock_init(&dfs_ic->chan_lock); + /* Initializes DFS Data Structures and queues*/ + dfs_attach(dfs_ic); + + return dfs_ic; +} + +/* + * Configures Radar Filters during + * vdev start/channel change/regulatory domain + * change.This Configuration enables to program + * the DFS pattern matching module. + */ +void wma_dfs_configure(struct ieee80211com *ic) +{ + struct ath_dfs_radar_tab_info rinfo; + int dfsdomain; + int radar_enabled_status = 0; + if(ic == NULL) { + WMA_LOGE("%s: DFS ic is Invalid",__func__); + return; + } + + dfsdomain = ic->current_dfs_regdomain; + + /* Fetch current radar patterns from the lmac */ + OS_MEMZERO(&rinfo, sizeof(rinfo)); + + /* + * Look up the current DFS + * regulatory domain and decide + * which radar pulses to use. + */ + switch (dfsdomain) + { + case DFS_FCC_DOMAIN: + WMA_LOGI("%s: DFS-FCC domain",__func__); + rinfo.dfsdomain = DFS_FCC_DOMAIN; + rinfo.dfs_radars = dfs_fcc_radars; + rinfo.numradars = ARRAY_LENGTH(dfs_fcc_radars); + rinfo.b5pulses = dfs_fcc_bin5pulses; + rinfo.numb5radars = ARRAY_LENGTH(dfs_fcc_bin5pulses); + break; + case DFS_ETSI_DOMAIN: + WMA_LOGI("%s: DFS-ETSI domain",__func__); + rinfo.dfsdomain = DFS_ETSI_DOMAIN; + rinfo.dfs_radars = dfs_etsi_radars; + rinfo.numradars = ARRAY_LENGTH(dfs_etsi_radars); + rinfo.b5pulses = NULL; + rinfo.numb5radars = 0; + break; + case DFS_MKK4_DOMAIN: + WMA_LOGI("%s: DFS-MKK4 domain",__func__); + rinfo.dfsdomain = DFS_MKK4_DOMAIN; + rinfo.dfs_radars = dfs_mkk4_radars; + rinfo.numradars = ARRAY_LENGTH(dfs_mkk4_radars); + rinfo.b5pulses = dfs_jpn_bin5pulses; + rinfo.numb5radars = ARRAY_LENGTH(dfs_jpn_bin5pulses); + break; + default: + WMA_LOGI("%s: DFS-UNINT domain",__func__); + rinfo.dfsdomain = DFS_UNINIT_DOMAIN; + rinfo.dfs_radars = NULL; + rinfo.numradars = 0; + rinfo.b5pulses = NULL; + rinfo.numb5radars = 0; + break; + } + + rinfo.dfs_pri_multiplier = ic->dfs_pri_multiplier; + + + /* + * Set the regulatory domain, + * radar pulse table and enable + * radar events if required. + * dfs_radar_enable() returns + * 0 on success and non-zero + * failure. + */ + radar_enabled_status = dfs_radar_enable(ic, &rinfo); + if (radar_enabled_status != DFS_STATUS_SUCCESS) { + WMA_LOGE("%s[%d]: DFS- Radar Detection Enabling Failed", + __func__, __LINE__); + } +} + +/* + * Set the Channel parameters in to DFS module + * Also,configure the DFS radar filters for + * matching the DFS phyerrors. + */ +struct ieee80211_channel * +wma_dfs_configure_channel(struct ieee80211com *dfs_ic, + wmi_channel *chan, + WLAN_PHY_MODE chanmode, + struct wma_vdev_start_req *req) +{ + if(dfs_ic == NULL) + { + WMA_LOGE("%s: DFS ic is Invalid",__func__); + return NULL; + } + + + if (!dfs_ic->ic_curchan) { + dfs_ic->ic_curchan = (struct ieee80211_channel *) OS_MALLOC(NULL, + sizeof(struct ieee80211_channel), + GFP_ATOMIC); + if (dfs_ic->ic_curchan == NULL) { + WMA_LOGE("%s: allocation of dfs_ic->ic_curchan failed %zu", + __func__, sizeof(struct ieee80211_channel)); + return NULL; + } + } + + OS_MEMZERO(dfs_ic->ic_curchan, sizeof (struct ieee80211_channel)); + + dfs_ic->ic_curchan->ic_ieee = req->chan; + dfs_ic->ic_curchan->ic_freq = chan->mhz; + dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1 = chan->band_center_freq1; + dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg2 = chan->band_center_freq2; + dfs_ic->ic_curchan->ic_pri_freq_center_freq_mhz_separation = + dfs_ic->ic_curchan->ic_freq - + dfs_ic->ic_curchan->ic_vhtop_ch_freq_seg1; + + if ( (dfs_ic->ic_curchan->ic_ieee >= WMA_11A_CHANNEL_BEGIN) && + (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END) ) + { + dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ; + } + if(chanmode == MODE_11AC_VHT80) + { + dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80; + } + if (req->chan_offset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + { + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? + IEEE80211_CHAN_VHT40PLUS : IEEE80211_CHAN_HT40PLUS); + } + else if (req->chan_offset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + { + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? + IEEE80211_CHAN_VHT40MINUS : IEEE80211_CHAN_HT40MINUS); + } + else if (req->chan_offset == PHY_SINGLE_CHANNEL_CENTERED) + { + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? IEEE80211_CHAN_VHT20 : IEEE80211_CHAN_HT20); + } + dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS; + + if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) + { + dfs_ic->ic_opmode = IEEE80211_M_HOSTAP; + dfs_ic->vdev_id = req->vdev_id; + } + + dfs_ic->dfs_pri_multiplier = req->dfs_pri_multiplier; + + /* + * Configuring the DFS with current channel and the radar filters + */ + wma_dfs_configure(dfs_ic); + WMA_LOGI("%s: DFS- CHANNEL CONFIGURED",__func__); + return dfs_ic->ic_curchan; +} +/* + * Configure the regulatory domain for DFS radar filter initialization + */ +void wma_set_dfs_regdomain(tp_wma_handle wma, uint8_t dfs_region) +{ + /* dfs information is passed */ + if (dfs_region > DFS_MKK4_DOMAIN || dfs_region == DFS_UNINIT_DOMAIN) + /* assign DFS_FCC_DOMAIN as default domain*/ + wma->dfs_ic->current_dfs_regdomain = DFS_FCC_DOMAIN; + else + wma->dfs_ic->current_dfs_regdomain = dfs_region; + + WMA_LOGI("%s: DFS Region Domain: %d", __func__, + wma->dfs_ic->current_dfs_regdomain); +} + +int wma_get_channels(struct ieee80211_channel *ichan, + struct wma_dfs_radar_channel_list *chan_list) +{ + uint8_t center_chan = vos_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1); + + chan_list->nchannels = 0; + + if (IEEE80211_IS_CHAN_11AC_VHT80(ichan)) + { + chan_list->nchannels= 4; + chan_list->channels[0] = center_chan - 6; + chan_list->channels[1] = center_chan - 2; + chan_list->channels[2] = center_chan + 2; + chan_list->channels[3] = center_chan + 6; + } + else if(IEEE80211_IS_CHAN_11N_HT40(ichan) || + IEEE80211_IS_CHAN_11AC_VHT40(ichan)) + { + chan_list->nchannels = 2; + chan_list->channels[0] = center_chan - 2; + chan_list->channels[1] = center_chan + 2; + } + else + { + chan_list->nchannels = 1; + chan_list->channels[0] = center_chan; + } + + return chan_list->nchannels; +} + + +/* + * Indicate Radar to SAP/HDD + */ +int wma_dfs_indicate_radar(struct ieee80211com *ic, + struct ieee80211_channel *ichan) +{ + tp_wma_handle wma; + void *hdd_ctx; + struct wma_dfs_radar_indication *radar_event; + struct hdd_dfs_radar_ind hdd_radar_event; + void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tpAniSirGlobal pmac = NULL; + bool indication_status; + + wma = (tp_wma_handle) vos_get_context(VOS_MODULE_ID_WDA, vos_context); + + if (wma == NULL) + { + WMA_LOGE("%s: DFS- Invalid wma", __func__); + return -ENOENT; + } + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD,wma->vos_context); + pmac = (tpAniSirGlobal) + vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); + if (!pmac) { + WMA_LOGE("%s:Invalid MAC handle", __func__); + return -ENOENT; + } + + if (wma->dfs_ic != ic) + { + WMA_LOGE("%s:DFS- Invalid WMA handle", __func__); + return -ENOENT; + } + radar_event = (struct wma_dfs_radar_indication *) + vos_mem_malloc(sizeof(struct wma_dfs_radar_indication)); + if (radar_event == NULL) + { + WMA_LOGE("%s:DFS- Invalid radar_event", __func__); + return -ENOENT; + } + + /* + * Do not post multiple Radar events on the same channel. + * But, when DFS test mode is enabled, allow multiple dfs + * radar events to be posted on the same channel. + */ + + adf_os_spin_lock_bh(&ic->chan_lock); + if (!pmac->sap.SapDfsInfo.disable_dfs_ch_switch) + wma->dfs_ic->disable_phy_err_processing = true; + + if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) || + ( pmac->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_TRUE) ) + { + /* Indicate the radar event to HDD to stop the netif Tx queues*/ + hdd_radar_event.ieee_chan_number = ichan->ic_ieee; + hdd_radar_event.chan_freq = ichan->ic_freq; + hdd_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND; + indication_status = + wma->dfs_radar_indication_cb(hdd_ctx,&hdd_radar_event); + if (indication_status == false) + { + WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP", + __func__); + adf_os_spin_unlock_bh(&ic->chan_lock); + return 0; + } + else + WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD",__func__); + + wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee; + /* + * Indicate to the radar event to SAP to + * select a new channel and set CSA IE + */ + radar_event->vdev_id = ic->vdev_id; + wma_get_channels(ichan, &radar_event->chan_list); + radar_event->dfs_radar_status = WMA_DFS_RADAR_FOUND; + radar_event->use_nol = ic->ic_dfs_usenol(ic); + wma_send_msg(wma, WDA_DFS_RADAR_IND, (void *)radar_event, 0); + WMA_LOGE("%s:DFS- WDA_DFS_RADAR_IND Message Posted",__func__); + } + + adf_os_spin_unlock_bh(&ic->chan_lock); + return 0; +} + +static eHalStatus wma_set_smps_params(tp_wma_handle wma, tANI_U8 vdev_id, int value) +{ + int ret = eHAL_STATUS_SUCCESS; + wmi_sta_smps_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + u_int16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return -ENOMEM; + } + cmd = (wmi_sta_smps_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_sta_smps_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_sta_smps_param_cmd_fixed_param)); + + cmd->vdev_id = vdev_id; + cmd->value = value & WMA_SMPS_MASK_LOWER_16BITS; + cmd->param = (value >> WMA_SMPS_PARAM_VALUE_S) & WMA_SMPS_MASK_UPPER_3BITS; + + WMA_LOGD("Setting vdev %d value = %x param %x", vdev_id, cmd->value, cmd->param); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_STA_SMPS_PARAM_CMDID); + if (ret < 0) { + WMA_LOGE("Failed to send set Mimo PS ret = %d", ret); + wmi_buf_free(buf); + } + + return ret; +} + +VOS_STATUS WMA_GetWcnssSoftwareVersion(v_PVOID_t pvosGCtx, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize) +{ + + tp_wma_handle wma_handle; + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, pvosGCtx); + + if (NULL == wma_handle) { + WMA_LOGE("%s: Failed to get wma", __func__); + return VOS_STATUS_E_FAULT; + } + + snprintf(pVersion, versionBufferSize, "%x", (unsigned int)wma_handle->target_fw_version); + return VOS_STATUS_SUCCESS; +} + +void ol_rx_err(ol_pdev_handle pdev, u_int8_t vdev_id, + u_int8_t *peer_mac_addr, int tid, u_int32_t tsf32, + enum ol_rx_err_type err_type, adf_nbuf_t rx_frame, + u_int64_t *pn, u_int8_t key_id) +{ + void *g_vos_ctx = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, g_vos_ctx); + tpSirSmeMicFailureInd mic_err_ind; + struct ether_header *eth_hdr; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return; + } + + if (err_type != OL_RX_ERR_TKIP_MIC) + return; + + if (adf_nbuf_len(rx_frame) < sizeof(*eth_hdr)) + return; + eth_hdr = (struct ether_header *) adf_nbuf_data(rx_frame); + mic_err_ind = vos_mem_malloc(sizeof(*mic_err_ind)); + if (!mic_err_ind) { + WMA_LOGE("%s: Failed to allocate memory for MIC indication message", __func__); + return; + } + adf_os_mem_set((void *) mic_err_ind, 0, sizeof(*mic_err_ind)); + + mic_err_ind->messageType = eWNI_SME_MIC_FAILURE_IND; + mic_err_ind->length = sizeof(*mic_err_ind); + adf_os_mem_copy(mic_err_ind->bssId, + (v_MACADDR_t *) wma->interfaces[vdev_id].bssid, + sizeof(tSirMacAddr)); + adf_os_mem_copy(mic_err_ind->info.taMacAddr, + (v_MACADDR_t *) peer_mac_addr, sizeof(tSirMacAddr)); + adf_os_mem_copy(mic_err_ind->info.srcMacAddr, + (v_MACADDR_t *) eth_hdr->ether_shost, sizeof(tSirMacAddr)); + adf_os_mem_copy(mic_err_ind->info.dstMacAddr, + (v_MACADDR_t *) eth_hdr->ether_dhost, sizeof(tSirMacAddr)); + mic_err_ind->info.keyId = key_id; + mic_err_ind->info.multicast = IEEE80211_IS_MULTICAST(eth_hdr->ether_dhost); + adf_os_mem_copy(mic_err_ind->info.TSC, pn, SIR_CIPHER_SEQ_CTR_SIZE); + wma_send_msg(wma, SIR_HAL_MIC_FAILURE_IND, (void *) mic_err_ind, 0); +} + +void +ol_indicate_err( + enum ol_rx_err_type err_type, + struct ol_error_info * err_info) +{ + switch (err_type) { + case OL_RX_ERR_TKIP_MIC: + { + void *g_vos_ctx = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, g_vos_ctx); + tpSirSmeMicFailureInd mic_err_ind; + + if (!wma) { + WMA_LOGE("%s: MIC error: Null wma handle", + __func__); + return; + } + + mic_err_ind = vos_mem_malloc(sizeof(*mic_err_ind)); + if (!mic_err_ind) { + WMA_LOGE("%s: Failed to allocate memory for MIC indication message", __func__); + return; + } + adf_os_mem_set((void *) mic_err_ind, 0, sizeof(*mic_err_ind)); + mic_err_ind->messageType = eWNI_SME_MIC_FAILURE_IND; + mic_err_ind->length = sizeof(*mic_err_ind); + adf_os_mem_copy(mic_err_ind->bssId, + (v_MACADDR_t *) wma->interfaces[err_info->u.mic_err.vdev_id].bssid, + sizeof(tSirMacAddr)); + WMA_LOGE("MIC error: BSSID:%02x:%02x:%02x:%02x:%02x:%02x\n", + mic_err_ind->bssId[0], mic_err_ind->bssId[1], + mic_err_ind->bssId[2], mic_err_ind->bssId[3], + mic_err_ind->bssId[4], mic_err_ind->bssId[5]); + adf_os_mem_copy(mic_err_ind->info.taMacAddr, + (v_MACADDR_t *) err_info->u.mic_err.ta, sizeof(tSirMacAddr)); + adf_os_mem_copy(mic_err_ind->info.srcMacAddr, + (v_MACADDR_t *) err_info->u.mic_err.sa, sizeof(tSirMacAddr)); + adf_os_mem_copy(mic_err_ind->info.dstMacAddr, + (v_MACADDR_t *) err_info->u.mic_err.da, sizeof(tSirMacAddr)); + mic_err_ind->info.keyId = err_info->u.mic_err.key_id; + mic_err_ind->info.multicast = + IEEE80211_IS_MULTICAST(err_info->u.mic_err.da); + adf_os_mem_copy(mic_err_ind->info.TSC, (void*)&err_info-> + u.mic_err.pn, SIR_CIPHER_SEQ_CTR_SIZE); + wma_send_msg(wma, SIR_HAL_MIC_FAILURE_IND, (void *) mic_err_ind, 0); + break; + } + default: + { + WMA_LOGE("%s: unhandled ol error type %d", __func__, err_type); + break; + } + } +} + +void WDA_TxAbort(v_U8_t vdev_id) +{ +#define PEER_ALL_TID_BITMASK 0xffffffff + tp_wma_handle wma; + u_int32_t peer_tid_bitmap = PEER_ALL_TID_BITMASK; + struct wma_txrx_node *iface; + + wma = vos_get_context(VOS_MODULE_ID_WDA, + vos_get_global_context(VOS_MODULE_ID_WDA, NULL)); + if (NULL == wma) { + WMA_LOGE("%s: wma is NULL", __func__); + return; + } + + iface = &wma->interfaces[vdev_id]; + if (!iface->handle) { + WMA_LOGE("%s: Failed to get iface handle: %p", + __func__, iface->handle); + return; + } + WMA_LOGA("%s: vdevid %d bssid %pM", __func__, vdev_id, iface->bssid); + iface->pause_bitmap |= (1 << PAUSE_TYPE_HOST); + wdi_in_vdev_pause(iface->handle, OL_TXQ_PAUSE_REASON_TX_ABORT); + + /* Flush all TIDs except MGMT TID for this peer in Target */ + peer_tid_bitmap &= ~(0x1 << WMI_MGMT_TID); + wmi_unified_peer_flush_tids_send(wma->wmi_handle, iface->bssid, + peer_tid_bitmap, vdev_id); +} + +static void wma_set_vdev_suspend_dtim(tp_wma_handle wma, v_U8_t vdev_id) +{ + struct wma_txrx_node *iface = &wma->interfaces[vdev_id]; + enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma); + + if ((iface->type == WMI_VDEV_TYPE_STA) && + (iface->ps_enabled == TRUE) && + (iface->dtimPeriod != 0)) { + int32_t ret; + u_int32_t listen_interval; + u_int32_t max_mod_dtim; + + if (wma->staDynamicDtim) { + listen_interval = wma->staDynamicDtim; + } else if ((wma->staModDtim) && + (wma->staMaxLIModDtim)) { + /* + * When the system is in suspend + * (maximum beacon will be at 1s == 10) + * If maxModulatedDTIM ((MAX_LI_VAL = 10) / AP_DTIM) + * equal or larger than MDTIM (configured in WCNSS_qcom_cfg.ini) + * Set LI to MDTIM * AP_DTIM + * If Dtim = 2 and Mdtim = 2 then LI is 4 + * Else + * Set LI to maxModulatedDTIM * AP_DTIM + */ + max_mod_dtim = wma->staMaxLIModDtim/iface->dtimPeriod; + if (max_mod_dtim >= wma->staModDtim) { + listen_interval = + (wma->staModDtim * iface->dtimPeriod); + } else { + listen_interval = + (max_mod_dtim * iface->dtimPeriod); + } + } else { + return; + } + + WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, listen_interval); + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_LISTEN_INTERVAL, + listen_interval); + if (ret) { + /* Even it fails continue Fw will take default LI */ + WMA_LOGE("Failed to Set Listen Interval vdevId %d", + vdev_id); + } + + if (qpower_config) { + WMA_LOGD("disable Qpower in suspend mode!"); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vdev_id, + WMI_STA_PS_ENABLE_QPOWER, + 0); + if (ret) + WMA_LOGE("Failed to disable Qpower in suspend mode!"); + + iface->ps_enabled = TRUE; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_DTIM_POLICY , + NORMAL_DTIM); + if (ret) { + /* Set it to Normal DTIM */ + WMA_LOGE("Failed to Set to Normal DTIM vdevId %d", + vdev_id); + } + iface->dtim_policy = NORMAL_DTIM; + WMA_LOGD("Set DTIM Policy to Normal Dtim vdevId %d", vdev_id); + } +} + +static void wma_set_suspend_dtim(tp_wma_handle wma) +{ + u_int8_t i; + + if (NULL == wma) { + WMA_LOGE("%s: wma is NULL", __func__); + return; + } + + for (i = 0; i < wma->max_bssid; i++) { + if ((wma->interfaces[i].handle) && + (false == wma->interfaces[i].alt_modulated_dtim_enabled)) { + wma_set_vdev_suspend_dtim(wma, i); + } + } +} + +static void wma_set_vdev_resume_dtim(tp_wma_handle wma, v_U8_t vdev_id) +{ + struct wma_txrx_node *iface = &wma->interfaces[vdev_id]; + enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma); + + if ((iface->type == WMI_VDEV_TYPE_STA) && + (iface->ps_enabled == TRUE) && + (iface->dtim_policy == NORMAL_DTIM)) { + int32_t ret; + tANI_U32 cfg_data_val = 0; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *mac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + /* Set Listen Interval */ + if ((NULL == mac) || (wlan_cfgGetInt(mac, + WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val ) != eSIR_SUCCESS)) { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for listen interval"); + cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL; + } + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_LISTEN_INTERVAL, + cfg_data_val); + if (ret) { + /* Even it fails continue Fw will take default LI */ + WMA_LOGE("Failed to Set Listen Interval vdevId %d", + vdev_id); + } + + WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, cfg_data_val); + + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_DTIM_POLICY , + STICK_DTIM); + if (ret) { + /* Set it back to Stick DTIM */ + WMA_LOGE("Failed to Set to Stick DTIM vdevId %d", + vdev_id); + } + iface->dtim_policy = STICK_DTIM; + WMA_LOGD("Set DTIM Policy to Stick Dtim vdevId %d", vdev_id); + + if (qpower_config) { + WMA_LOGD("enable Qpower in resume mode!"); + ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, + vdev_id, + WMI_STA_PS_ENABLE_QPOWER, + 1); + if (ret) + WMA_LOGE("Failed to enable Qpower in resume mode!"); + } + } +} + +static void wma_set_resume_dtim(tp_wma_handle wma) +{ + u_int8_t i; + + if (NULL == wma) { + WMA_LOGE("%s: wma is NULL", __func__); + return; + } + + for (i = 0; i < wma->max_bssid; i++) { + if ((wma->interfaces[i].handle) && + (false == wma->interfaces[i].alt_modulated_dtim_enabled)) { + wma_set_vdev_resume_dtim(wma, i); + } + } +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void wma_process_roam_synch_complete(WMA_HANDLE handle, + tSirSmeRoamOffloadSynchCnf *synchcnf) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_roam_synch_complete_fixed_param* cmd; + wmi_buf_t wmi_buf; + u_int8_t *buf_ptr; + u_int16_t len; + v_BOOL_t roam_synch_in_progress; + len = sizeof(wmi_roam_synch_complete_fixed_param); + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue roam synch cnf", + __func__); + return; + } + roam_synch_in_progress = + wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress; + if (roam_synch_in_progress == VOS_FALSE) { + WMA_LOGE("%s: Dont send the roam synch complete since Roam Synch" + "Propagation is not in Progress", __func__); + return; + } else { + adf_os_spin_lock_bh(&wma_handle->roam_synch_lock); + wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress = + VOS_FALSE; + adf_os_spin_unlock_bh(&wma_handle->roam_synch_lock); + } + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return; + } + cmd = (wmi_roam_synch_complete_fixed_param *)wmi_buf_data(wmi_buf); + buf_ptr = (u_int8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_synch_complete_fixed_param)); + cmd->vdev_id = synchcnf->sessionId; + if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, + WMI_ROAM_SYNCH_COMPLETE)) { + WMA_LOGP("%s: failed to send roam synch confirmation", __func__); + adf_nbuf_free(wmi_buf); + return; + } + return; +} +void wma_process_roam_synch_fail(WMA_HANDLE handle, + tSirRoamOffloadSynchFail *synchfail) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not clean-up roam synch", + __func__); + return; + } + /* Hand Off Failure could happen as an exception, when a roam synch + * indication is posted to Host, but a roam synch complete is not + * posted to the firmware.So, clear the roam synch in progress + * flag before disconnecting the session through this event.*/ + adf_os_spin_lock_bh(&wma_handle->roam_synch_lock); + wma_handle->interfaces[synchfail->sessionId].roam_synch_in_progress = + VOS_FALSE; + adf_os_spin_unlock_bh(&wma_handle->roam_synch_lock); +} +#endif + +#ifdef FEATURE_RUNTIME_PM +int wma_runtime_suspend_req(WMA_HANDLE handle) +{ + vos_msg_t vosMessage; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + int ret = 0; + tp_wma_handle wma = (tp_wma_handle) handle; + + vos_event_reset(&wma->runtime_suspend); + + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_RUNTIME_PM_SUSPEND_IND; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage ); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + ret = -EAGAIN; + return ret; + } + + if (vos_wait_single_event(&wma->runtime_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) != + VOS_STATUS_SUCCESS) { + WMA_LOGE("Failed to get runtime suspend event"); + ret = -EAGAIN; + goto out; + } + + /* Check if suspend completed, if not return failure */ + if (!wma_get_wow_bus_suspend(wma)) { + WMA_LOGE("Runtime Suspend Failed: %d", + wma_get_wow_bus_suspend(wma)); + ret = -EAGAIN; + } +out: + if (ret) + wma_runtime_resume_req(wma); + + return ret; +} + +int wma_runtime_resume_req(WMA_HANDLE handle) +{ + vos_msg_t vosMessage; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + int ret = 0; + tp_wma_handle wma = (tp_wma_handle) handle; + struct wma_runtime_pm_context *runtime_context = &wma->runtime_context; + + vos_runtime_pm_prevent_suspend(runtime_context->resume); + + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_RUNTIME_PM_RESUME_IND; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage ); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + WMA_LOGE("Failed to post Runtime PM Resume IND to VOS"); + ret = -EAGAIN; + vos_runtime_pm_allow_suspend(runtime_context->resume); + } + + return ret; +} + +#endif + +/** + * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID + * @vdev_id: vdev id + * + * Return: entry from vdev table + */ +struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id) +{ + tp_wma_handle wma; + void *vos_ctx; + + vos_ctx = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + wma = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return NULL; + } + + if (vdev_id >= wma->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id); + return NULL; + } + + return &wma->interfaces[vdev_id]; +} + +/** + * wma_is_vdev_up() - return whether a vdev is up + * @vdev_id: vdev id + * + * Return: true if the vdev is up, false otherwise + */ +bool wma_is_vdev_up(uint8_t vdev_id) +{ + struct wma_txrx_node *vdev = wma_get_interface_by_vdev_id(vdev_id); + if (vdev) + return vdev->vdev_up; + else + return false; +} + +/** + * wma_get_vht_ch_width - return vht channel width + * + * Return: return vht channel width + */ +uint32_t wma_get_vht_ch_width(void) +{ + uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + v_CONTEXT_t v_ctx = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + tp_wma_handle wm_hdl = (tp_wma_handle)vos_get_context(VOS_MODULE_ID_WDA, + v_ctx); + if (NULL == wm_hdl) { + WMA_LOGE("%s: Failed to get wm_hdl", __func__); + return -EINVAL; + } + if (wm_hdl->vht_cap_info & IEEE80211_VHTCAP_SUP_CHAN_WIDTH_160) + fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + else if (wm_hdl->vht_cap_info & IEEE80211_VHTCAP_SUP_CHAN_WIDTH_80_160) + fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; + + return fw_ch_wd; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h new file mode 100644 index 000000000000..04abb6401340 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h @@ -0,0 +1,1681 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**======================================================================== + + \file wma.h + \brief Implementation of WMA + + ========================================================================*/ +/**========================================================================= + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- ----------------------------------------- + 12/03/2013 Ganesh Created module for WMA + Kondabattini + 27/03/2013 Ganesh Rx Mgmt Related added + Babu + ==========================================================================*/ +#ifndef WMA_H +#define WMA_H + +#include "a_types.h" +#include "vos_types.h" +#include "osapi_linux.h" +#include "htc_packet.h" +#include "i_vos_event.h" +#include "wmi_services.h" +#include "wmi_unified.h" +#include "wmi_version.h" +#include "halTypes.h" +#include "cfgApi.h" +#include "vos_status.h" +#include "vos_sched.h" +#include "wlan_hdd_tgt_cfg.h" +#include "ol_txrx_api.h" +#include "sirMacProtDef.h" +#include "wlan_qct_wda.h" +#include "ol_txrx_types.h" +#include "wlan_qct_wda.h" +#include + +/* Platform specific configuration for max. no. of fragments */ +#define QCA_OL_11AC_TX_MAX_FRAGS 2 + +/** Private **/ +#define WMA_CFG_NV_DNLD_TIMEOUT 500 +#define WMA_READY_EVENTID_TIMEOUT 2000 +#define WMA_TGT_SUSPEND_COMPLETE_TIMEOUT 6000 +#define WMA_WAKE_LOCK_TIMEOUT 1000 +#define WMA_MAX_RESUME_RETRY 100 +#define WMA_RESUME_TIMEOUT 6000 +#define WMA_TGT_WOW_TX_COMPLETE_TIMEOUT 2000 +#define MAX_MEM_CHUNKS 32 +#define WMA_CRASH_INJECT_TIMEOUT 5000 + +/* + In prima 12 HW stations are supported including BCAST STA(staId 0) + and SELF STA(staId 1) so total ASSOC stations which can connect to Prima + SoftAP = 12 - 1(Self STa) - 1(Bcast Sta) = 10 Stations. */ + +#ifdef WLAN_SOFTAP_VSTA_FEATURE +#define WMA_MAX_SUPPORTED_STAS 38 +#else +#define WMA_MAX_SUPPORTED_STAS 12 +#endif +#define WMA_MAX_SUPPORTED_BSS 5 + +#define FRAGMENT_SIZE 3072 + +#define WMA_INVALID_VDEV_ID 0xFF +#define MAX_MEM_CHUNKS 32 +#define WMA_MAX_VDEV_SIZE 20 +#define WMA_VDEV_TBL_ENTRY_ADD 1 +#define WMA_VDEV_TBL_ENTRY_DEL 0 + + +/* 11A/G channel boundary */ +#define WMA_11A_CHANNEL_BEGIN 34 +#define WMA_11A_CHANNEL_END 165 +#define WMA_11G_CHANNEL_BEGIN 1 +#define WMA_11G_CHANNEL_END 14 + +#define WMA_11P_CHANNEL_BEGIN (170) +#define WMA_11P_CHANNEL_END (184) + +#define WMA_LOGD(args...) \ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, ## args) +#define WMA_LOGI(args...) \ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, ## args) +#define WMA_LOGW(args...) \ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_WARN, ## args) +#define WMA_LOGE(args...) \ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, ## args) +#define WMA_LOGP(args...) \ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_FATAL, ## args) + +#define WMA_DEBUG_ALWAYS + +#ifdef WMA_DEBUG_ALWAYS +#define WMA_LOGA(args...) \ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_FATAL, ## args) +#else +#define WMA_LOGA(args...) +#endif + +#define ALIGNED_WORD_SIZE 4 +#define WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE 0x7FFF + +/* Prefix used by scan req ids generated on the host */ +#define WMA_HOST_SCAN_REQID_PREFIX 0xA000 +/* Prefix used by roam scan req ids generated on the host */ +#define WMA_HOST_ROAM_SCAN_REQID_PREFIX 0xA800 +/* Prefix used by scan requestor id on host */ +#define WMA_HOST_SCAN_REQUESTOR_ID_PREFIX 0xA000 +#define WMA_HW_DEF_SCAN_MAX_DURATION 30000 /* 30 secs */ + +/* Max offchannel duration */ +#define WMA_BURST_SCAN_MAX_NUM_OFFCHANNELS (3) +#define WMA_SCAN_NPROBES_DEFAULT (2) +#define WMA_SCAN_IDLE_TIME_DEFAULT (25) +#define WMA_P2P_SCAN_MAX_BURST_DURATION (180) +#define WMA_CTS_DURATION_MS_MAX (32) +#define WMA_GO_MIN_ACTIVE_SCAN_BURST_DURATION (40) +#define WMA_GO_MAX_ACTIVE_SCAN_BURST_DURATION (120) +#define WMA_DWELL_TIME_PASSIVE_DEFAULT (110) +#define WMA_DWELL_TIME_PROBE_TIME_MAP_SIZE (11) +#define WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION (25) + +#define WMA_SEC_TO_USEC (1000000) + +#define BEACON_TX_BUFFER_SIZE (512) + +/* WMA_ETHER_TYPE_OFFSET = sa(6) + da(6) */ +#define WMA_ETHER_TYPE_OFFSET (6 + 6) +/* WMA_ICMP_V6_HEADER_OFFSET = sa(6) + da(6) + eth_type(2) + icmp_v6_hdr(6)*/ +#define WMA_ICMP_V6_HEADER_OFFSET (6 + 6 + 2 + 6) +/* WMA_ICMP_V6_TYPE_OFFSET = sa(6) + da(6) + eth_type(2) + 40 */ +#define WMA_ICMP_V6_TYPE_OFFSET (6 + 6 + 2 + 40) + +#define WMA_ICMP_V6_HEADER_TYPE (0x3A) +#define WMA_ICMP_V6_RA_TYPE (0x86) +#define WMA_ICMP_V6_NS_TYPE (0x87) +#define WMA_ICMP_V6_NA_TYPE (0x88) +#define WMA_BCAST_MAC_ADDR (0xFF) +#define WMA_MCAST_IPV4_MAC_ADDR (0x01) +#define WMA_MCAST_IPV6_MAC_ADDR (0x33) + +typedef struct probeTime_dwellTime { + u_int8_t dwell_time; + u_int8_t probe_time; +} t_probeTime_dwellTime; + +static const t_probeTime_dwellTime + probeTime_dwellTime_map[WMA_DWELL_TIME_PROBE_TIME_MAP_SIZE] = { + {28, 0}, /* 0 SSID */ + {28, 20}, /* 1 SSID */ + {28, 20}, /* 2 SSID */ + {28, 20}, /* 3 SSID */ + {28, 20}, /* 4 SSID */ + {28, 20}, /* 5 SSID */ + {28, 20}, /* 6 SSID */ + {28, 11}, /* 7 SSID */ + {28, 11}, /* 8 SSID */ + {28, 11}, /* 9 SSID */ + {28, 8} /* 10 SSID */ +}; + +/* Roaming default values + * All time and period values are in milliseconds. + * All rssi values are in dB except for WMA_NOISE_FLOOR_DBM_DEFAULT. + */ + +#define WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME (4) +#define WMA_NOISE_FLOOR_DBM_DEFAULT (-96) +#define WMA_ROAM_RSSI_DIFF_DEFAULT (5) +#define WMA_ROAM_DWELL_TIME_ACTIVE_DEFAULT (100) +#define WMA_ROAM_DWELL_TIME_PASSIVE_DEFAULT (110) +#define WMA_ROAM_MIN_REST_TIME_DEFAULT (50) +#define WMA_ROAM_MAX_REST_TIME_DEFAULT (500) +#define WMA_ROAM_LOW_RSSI_TRIGGER_DEFAULT (20) +#define WMA_ROAM_LOW_RSSI_TRIGGER_VERYLOW (10) +#define WMA_ROAM_BEACON_WEIGHT_DEFAULT (14) +#define WMA_ROAM_OPP_SCAN_PERIOD_DEFAULT (120000) +#define WMA_ROAM_OPP_SCAN_AGING_PERIOD_DEFAULT (WMA_ROAM_OPP_SCAN_PERIOD_DEFAULT * 5) +#define WMA_ROAM_PREAUTH_SCAN_TIME (50) +#define WMA_ROAM_PREAUTH_REST_TIME (0) +#define WMA_ROAM_PREAUTH_MAX_SCAN_TIME (10000) +#define WMA_ROAM_BMISS_FIRST_BCNT_DEFAULT (10) +#define WMA_ROAM_BMISS_FINAL_BCNT_DEFAULT (10) +#define WMA_ROAM_BMISS_FIRST_BCNT_DEFAULT_P2P (15) +#define WMA_ROAM_BMISS_FINAL_BCNT_DEFAULT_P2P (45) + +#define WMA_INVALID_KEY_IDX 0xff +#define WMA_DFS_RADAR_FOUND 1 + +#define WMA_MAX_RF_CHAINS(x) ((1 << x) - 1) +#define WMA_MIN_RF_CHAINS (1) + +#ifdef FEATURE_WLAN_EXTSCAN +#define WMA_MAX_EXTSCAN_MSG_SIZE 1536 +#define WMA_EXTSCAN_REST_TIME 100 +#define WMA_EXTSCAN_MAX_SCAN_TIME 50000 +#define WMA_EXTSCAN_BURST_DURATION 150 +#endif + +typedef void (*txFailIndCallback)(u_int8_t *peer_mac, u_int8_t seqNo); + +typedef struct { + HTC_ENDPOINT_ID endpoint_id; +}t_cfg_nv_param; + +typedef enum +{ + WMA_DRIVER_TYPE_PRODUCTION = 0, + WMA_DRIVER_TYPE_MFG = 1, + WMA_DRIVER_TYPE_DVT = 2, + WMA_DRIVER_TYPE_INVALID = 0x7FFFFFFF +}t_wma_drv_type; + +typedef enum { + WMA_STATE_OPEN, + WMA_STATE_START, + WMA_STATE_STOP, + WMA_STATE_CLOSE +}t_wma_state; + +#ifdef FEATURE_WLAN_TDLS +typedef enum { + WMA_TDLS_SUPPORT_NOT_ENABLED = 0, + WMA_TDLS_SUPPORT_DISABLED, /* suppress implicit trigger and not respond to the peer */ + WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY, /* suppress implicit trigger, but respond to the peer */ + WMA_TDLS_SUPPORT_ENABLED, /* implicit trigger */ + /* External control means implicit trigger + * but only to a peer mac configured by user space. + */ + WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL, +}t_wma_tdls_mode; + +/** TDLS EVENTS */ +enum wma_tdls_peer_notification { + /** tdls discovery recommended for peer (always based + * on tx bytes per second > tx_discover threshold + * NB: notification will be re-sent after + * discovery_request_interval_ms */ + WMA_TDLS_SHOULD_DISCOVER, + /** tdls link tear down recommended for peer + * due to tx bytes per second below tx_teardown_threshold + * NB: this notification sent once */ + WMA_TDLS_SHOULD_TEARDOWN, + /** tx peer TDLS link tear down complete */ + WMA_TDLS_PEER_DISCONNECTED, +}; + +enum wma_tdls_peer_reason { + /** tdls teardown recommended due to low transmits */ + WMA_TDLS_TEARDOWN_REASON_TX, + /** tdls tear down recommended due to packet rates < AP rates */ + WMA_TDLS_TEARDOWN_REASON_RATE, + /** tdls link tear down recommended due to poor RSSI */ + WMA_TDLS_TEARDOWN_REASON_RSSI, + /** tdls link tear down recommended due to offchannel scan */ + WMA_TDLS_TEARDOWN_REASON_SCAN, + /** tdls peer disconnected due to peer deletion */ + WMA_TDLS_DISCONNECTED_REASON_PEER_DELETE, +}; +#endif /* FEATURE_WLAN_TDLS */ + +typedef enum { + /* Roaming preauth channel state */ + WMA_ROAM_PREAUTH_CHAN_NONE, + WMA_ROAM_PREAUTH_CHAN_REQUESTED, + WMA_ROAM_PREAUTH_ON_CHAN, + WMA_ROAM_PREAUTH_CHAN_CANCEL_REQUESTED, + WMA_ROAM_PREAUTH_CHAN_COMPLETED +} t_wma_roam_preauth_chan_state_t; +/* + * memory chunck allocated by Host to be managed by FW + * used only for low latency interfaces like pcie + */ +struct wma_mem_chunk { + u_int32_t *vaddr; + u_int32_t paddr; + adf_os_dma_mem_context(memctx); + u_int32_t len; + u_int32_t req_id; +}; + +typedef struct s_vdev_tbl { + u_int8_t vdev_id; + u_int8_t sta_mac[ETH_ALEN]; + ol_txrx_vdev_handle tx_rx_vdev_handle; + u_int32_t vdev_type; + bool used; +}t_vdev_tbl; + +struct scan_param{ + u_int32_t scan_id; + u_int32_t scan_requestor_id; + tSirP2pScanType p2p_scan_type; +}; + + +#define WMA_BCN_BUF_MAX_SIZE 2500 +#define WMA_NOA_IE_SIZE(num_desc) (2 + (13 * (num_desc))) +#define WMA_MAX_NOA_DESCRIPTORS 4 +struct beacon_info { + adf_nbuf_t buf; + u_int32_t len; + u_int8_t dma_mapped; + u_int32_t tim_ie_offset; + u_int8_t dtim_count; + u_int16_t seq_no; + u_int8_t noa_sub_ie[2 + WMA_NOA_IE_SIZE(WMA_MAX_NOA_DESCRIPTORS)]; + u_int16_t noa_sub_ie_len; + u_int8_t *noa_ie; + u_int16_t p2p_ie_offset; + adf_os_spinlock_t lock; +}; + +struct beacon_tim_ie { + u_int8_t tim_ie; + u_int8_t tim_len; + u_int8_t dtim_count; + u_int8_t dtim_period; + u_int8_t tim_bitctl; + u_int8_t tim_bitmap[1]; +} __ATTRIB_PACK; + +#define WMA_TIM_SUPPORTED_PVB_LENGTH (HAL_NUM_STA / 8) + 1 + + +struct pps { + v_BOOL_t paid_match_enable; + v_BOOL_t gid_match_enable; + v_BOOL_t tim_clear; + v_BOOL_t dtim_clear; + v_BOOL_t eof_delim; + v_BOOL_t mac_match; + v_BOOL_t delim_fail; + v_BOOL_t nsts_zero; + v_BOOL_t rssi_chk; + v_BOOL_t ebt_5g; +}; + +struct qpower_params { + u_int32_t max_ps_poll_cnt; + u_int32_t max_tx_before_wake; + u_int32_t spec_ps_poll_wake_interval; + u_int32_t max_spec_nodata_ps_poll; +}; + +typedef struct { + u_int32_t gtxRTMask[2]; /* for HT and VHT rate masks */ + u_int32_t gtxUsrcfg; /* host request for GTX mask */ + u_int32_t gtxPERThreshold; /* default: 10% */ + u_int32_t gtxPERMargin; /* default: 2% */ + u_int32_t gtxTPCstep; /* default: 1 */ + u_int32_t gtxTPCMin; /* default: 5 */ + u_int32_t gtxBWMask; /* 20/40/80/160 Mhz */ +}gtx_config_t; + +typedef struct { + u_int32_t ani_enable; + u_int32_t ani_poll_len; + u_int32_t ani_listen_len; + u_int32_t ani_ofdm_level; + u_int32_t ani_cck_level; + u_int32_t cwmenable; + u_int32_t cts_cbw; + u_int32_t txchainmask; + u_int32_t rxchainmask; + u_int32_t txpow2g; + u_int32_t txpow5g; + u_int32_t burst_enable; + u_int32_t burst_dur; + u_int32_t chainmask_2g; + u_int32_t chainmask_5g; +} pdev_cli_config_t; + +typedef struct { + u_int32_t nss; + u_int32_t ldpc; + u_int32_t tx_stbc; + u_int32_t rx_stbc; + u_int32_t shortgi; + u_int32_t rtscts_en; + u_int32_t chwidth; + u_int32_t tx_rate; + u_int32_t ampdu; + u_int32_t amsdu; + u_int32_t erx_adjust; + u_int32_t erx_bmiss_num; + u_int32_t erx_bmiss_cycle; + u_int32_t erx_slop_step; + u_int32_t erx_init_slop; + u_int32_t erx_adj_pause; + u_int32_t erx_dri_sample; + struct pps pps_params; + struct qpower_params qpower_params; + gtx_config_t gtx_info; +} vdev_cli_config_t; + +#define WMA_WOW_PTRN_MASK_VALID 0xFF +#define WMA_NUM_BITS_IN_BYTE 8 + +#define WMA_AP_WOW_DEFAULT_PTRN_MAX 4 +#define WMA_STA_WOW_DEFAULT_PTRN_MAX 4 + +struct wma_wow_ptrn_cache { + u_int8_t vdev_id; + u_int8_t *ptrn; + u_int8_t ptrn_len; + u_int8_t ptrn_offset; + u_int8_t *mask; + u_int8_t mask_len; +}; + +struct wma_wow { + struct wma_wow_ptrn_cache *cache[WOW_MAX_BITMAP_FILTERS]; + u_int8_t no_of_ptrn_cached; + + u_int8_t free_ptrn_id[WOW_MAX_BITMAP_FILTERS]; + u_int8_t total_free_ptrn_id; + u_int8_t used_free_ptrn_id; + + v_BOOL_t magic_ptrn_enable; + v_BOOL_t wow_enable; + v_BOOL_t wow_enable_cmd_sent; + v_BOOL_t deauth_enable; + v_BOOL_t disassoc_enable; + v_BOOL_t bmiss_enable; + v_BOOL_t gtk_pdev_enable; + v_BOOL_t gtk_err_enable[WMA_MAX_SUPPORTED_BSS]; +#ifdef FEATURE_WLAN_LPHB + /* currently supports only vdev 0. + * cache has two entries: one for TCP and one for UDP. + */ + tSirLPHBReq lphb_cache[2]; +#endif +}; +#ifdef WLAN_FEATURE_11W +#define CMAC_IPN_LEN (6) +#define WMA_IGTK_KEY_INDEX_4 (4) +#define WMA_IGTK_KEY_INDEX_5 (5) + +typedef struct { + u_int8_t ipn[CMAC_IPN_LEN]; +} wma_igtk_ipn_t; + +typedef struct { + u_int16_t key_length; + u_int8_t key[CSR_AES_KEY_LEN]; + + /* IPN is maintained per iGTK keyID + * 0th index for iGTK keyID = 4; + * 1st index for iGTK KeyID = 5 + */ + wma_igtk_ipn_t key_id[2]; +} wma_igtk_key_t; +#endif + +#define WMA_BSS_STATUS_STARTED 0x1 +#define WMA_BSS_STATUS_STOPPED 0x2 + +typedef struct { + A_UINT32 vdev_id; + wmi_ssid ssid; + A_UINT32 flags; + A_UINT32 requestor_id; + A_UINT32 disable_hw_ack; + wmi_channel chan; + adf_os_atomic_t hidden_ssid_restart_in_progress; + tANI_U8 ssidHidden; +} vdev_restart_params_t; + +struct wma_txrx_node { + u_int8_t addr[ETH_ALEN]; + u_int8_t bssid[ETH_ALEN]; + void *handle; + struct beacon_info *beacon; + vdev_restart_params_t vdev_restart_params; + vdev_cli_config_t config; + struct scan_param scan_info; + u_int32_t type; + u_int32_t sub_type; +#ifdef FEATURE_WLAN_SCAN_PNO + v_BOOL_t nlo_match_evt_received; + v_BOOL_t pno_in_progress; +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + v_BOOL_t plm_in_progress; +#endif + v_BOOL_t ptrn_match_enable; + v_BOOL_t conn_state; + /* BSS parameters cached for use in WDA_ADD_STA */ + tSirMacBeaconInterval beaconInterval; + tANI_U8 llbCoexist; + tANI_U8 shortSlotTimeSupported; + tANI_U8 dtimPeriod; + WLAN_PHY_MODE chanmode; + tANI_U8 vht_capable; + tANI_U8 ht_capable; + A_UINT32 mhz; /* channel frequency in KHZ */ + v_BOOL_t vdev_up; + u_int64_t tsfadjust; + void *addBssStaContext; + tANI_U8 aid; + /* Robust Management Frame (RMF) enabled/disabled */ + tANI_U8 rmfEnabled; +#ifdef WLAN_FEATURE_11W + wma_igtk_key_t key; +#endif /* WLAN_FEATURE_11W */ + u_int32_t uapsd_cached_val; + tAniGetPEStatsRsp *stats_rsp; + tANI_U8 fw_stats_set; + void *del_staself_req; + adf_os_atomic_t bss_status; + tANI_U8 rate_flags; + tANI_U8 nss; + v_BOOL_t is_channel_switch; + u_int16_t pause_bitmap; + tPowerdBm tx_power; /* TX power in dBm */ + tPowerdBm max_tx_power; /* max Tx power in dBm */ + u_int32_t nwType; +#if defined WLAN_FEATURE_VOWIFI_11R + void *staKeyParams; +#endif + v_BOOL_t ps_enabled; + u_int32_t dtim_policy; + u_int32_t peer_count; + v_BOOL_t roam_synch_in_progress; + void *plink_status_req; + void *psnr_req; + u_int8_t delay_before_vdev_stop; +#ifdef FEATURE_WLAN_EXTSCAN + bool extscan_in_progress; +#endif + uint32_t alt_modulated_dtim; + bool alt_modulated_dtim_enabled; + uint8_t wps_state; + uint8_t nss_2g; + uint8_t nss_5g; + + uint8_t wep_default_key_idx; +}; + +#if defined(QCA_WIFI_FTM) +#define MAX_UTF_EVENT_LENGTH 2048 +#define MAX_WMI_UTF_LEN 252 +#define SYS_MSG_COOKIE (0xFACE) + +typedef struct { + A_UINT32 len; + A_UINT32 msgref; + A_UINT32 segmentInfo; + A_UINT32 pad; +} SEG_HDR_INFO_STRUCT; + +struct utf_event_info { + u_int8_t *data; + u_int32_t length; + adf_os_size_t offset; + u_int8_t currentSeq; + u_int8_t expectedSeq; +}; +#endif + +typedef struct { + u_int8_t vdev_id; + u_int32_t scan_id; +}scan_timer_info; + +typedef struct { + u_int32_t atimWindowLength; + u_int32_t isPowerSaveAllowed; + u_int32_t isPowerCollapseAllowed; + u_int32_t isAwakeonTxRxEnabled; + u_int32_t inactivityCount; + u_int32_t txSPEndInactivityTime; + u_int32_t ibssPsWarmupTime; + u_int32_t ibssPs1RxChainInAtimEnable; +}ibss_power_save_params; + +#define MAX_REQUEST_HANDLERS 20 + +struct wma_handle; +typedef VOS_STATUS (*wma_request_handler)(struct wma_handle *wma_handle, + void *request, void **response); + +typedef struct request_handler_entry { + int request_type; + wma_request_handler handler; +} request_handler_entry_t; + +struct wma_runtime_pm_context { + void *ap; + void *resume; +}; + +typedef struct wma_handle { + void *wmi_handle; + void *htc_handle; + void *vos_context; + void *mac_context; + + vos_event_t wma_ready_event; + vos_event_t wma_resume_event; + vos_event_t target_suspend; + vos_event_t wow_tx_complete; + vos_event_t runtime_suspend; + vos_event_t recovery_event; + + t_cfg_nv_param cfg_nv; + + v_U16_t max_station; + v_U16_t max_bssid; + v_U32_t frame_xln_reqd; + t_wma_drv_type driver_type; + + /* TODO: Check below 2 parameters are required for ROME/PRONTO ? */ + u_int8_t myaddr[ETH_ALEN]; /* current mac address */ + u_int8_t hwaddr[ETH_ALEN]; /* mac address from EEPROM */ + + wmi_abi_version target_abi_vers; /* The target firmware version */ + /* The final negotiated ABI version to be used for communicating */ + wmi_abi_version final_abi_vers; + v_U32_t target_fw_version; /* Target f/w build version */ +#ifdef WLAN_FEATURE_LPSS + v_U8_t lpss_support; /* LPSS feature is supported in target or not */ +#endif + uint8_t ap_arpns_support; + bool wmi_ready; + u_int32_t wlan_init_status; + adf_os_device_t adf_dev; + u_int32_t phy_capability; /* PHY Capability from Target*/ + u_int32_t max_frag_entry; /* Max number of Fragment entry */ + u_int32_t wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; /* wmi services bitmap received from Target */ + wmi_resource_config wlan_resource_config; + u_int32_t frameTransRequired; + tBssSystemRole wmaGlobalSystemRole; + + /* Tx Frame Compl Cb registered by umac */ + pWDATxRxCompFunc tx_frm_download_comp_cb; + + /* Event to wait for tx download completion */ + vos_event_t tx_frm_download_comp_event; + + /* + * Dummy event to wait for draining MSDUs left in hardware tx + * queue and before requesting VDEV_STOP. Nobody will set this + * and wait will timeout, and code will poll the pending tx + * descriptors number to be zero. + */ + vos_event_t tx_queue_empty_event; + + /* Ack Complete Callback registered by umac */ + pWDAAckFnTxComp umac_ota_ack_cb[SIR_MAC_MGMT_RESERVED15]; + pWDAAckFnTxComp umac_data_ota_ack_cb; + + /* timestamp when OTA of last umac data was done */ + v_TIME_t last_umac_data_ota_timestamp; + /* cache nbuf ptr for the last umac data buf */ + adf_nbuf_t last_umac_data_nbuf; + + v_BOOL_t needShutdown; + u_int32_t num_mem_chunks; + struct wma_mem_chunk mem_chunks[MAX_MEM_CHUNKS]; + wda_tgt_cfg_cb tgt_cfg_update_cb; + /*Callback to indicate radar to HDD*/ + wda_dfs_radar_indication_cb dfs_radar_indication_cb; + HAL_REG_CAPABILITIES reg_cap; + u_int32_t scan_id; + struct wma_txrx_node *interfaces; + pdev_cli_config_t pdevconfig; + struct list_head vdev_resp_queue; + adf_os_spinlock_t vdev_respq_lock; + adf_os_spinlock_t vdev_detach_lock; + u_int32_t ht_cap_info; +#ifdef WLAN_FEATURE_11AC + u_int32_t vht_cap_info; + u_int32_t vht_supp_mcs; +#endif + u_int32_t num_rf_chains; + +#if defined(QCA_WIFI_FTM) + /* UTF event information */ + struct utf_event_info utf_event_info; +#endif + u_int8_t is_fw_assert; + struct wma_wow wow; + u_int8_t no_of_suspend_ind; + u_int8_t no_of_resume_ind; + + /* Have a back up of arp info to send along + * with ns info suppose if ns also enabled + */ + tSirHostOffloadReq mArpInfo; + struct wma_tx_ack_work_ctx *ack_work_ctx; + u_int8_t powersave_mode; + v_BOOL_t ptrn_match_enable_all_vdev; + void* pGetRssiReq; + v_S7_t first_rssi; + bool get_sta_rssi; + v_MACADDR_t peer_macaddr; + t_thermal_mgmt thermal_mgmt_info; + v_BOOL_t roam_offload_enabled; + t_wma_roam_preauth_chan_state_t roam_preauth_scan_state; + u_int32_t roam_preauth_scan_id; + u_int16_t roam_preauth_chanfreq; + void *roam_preauth_chan_context; + adf_os_spinlock_t roam_preauth_lock; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + adf_os_spinlock_t roam_synch_lock; +#endif + /* Here ol_ini_info is used to store ini + * status of arp offload, ns offload + * and others. Currently 1st bit is used + * for arp off load and 2nd bit for ns + * offload currently, rest bits are unused + */ + u_int8_t ol_ini_info; + v_BOOL_t ssdp; + bool enable_bcst_ptrn; +#ifdef FEATURE_RUNTIME_PM + v_BOOL_t runtime_pm; + u_int32_t auto_time; +#endif + u_int8_t ibss_started; + tSetBssKeyParams ibsskey_info; + + /*DFS umac interface information*/ + struct ieee80211com *dfs_ic; +#ifdef FEATURE_WLAN_SCAN_PNO + vos_wake_lock_t pno_wake_lock; +#endif +#ifdef FEATURE_WLAN_EXTSCAN + vos_wake_lock_t extscan_wake_lock; +#endif + vos_wake_lock_t wow_wake_lock; + int wow_nack; + u_int32_t ap_client_cnt; + adf_os_atomic_t is_wow_bus_suspended; + + vos_timer_t wma_scan_comp_timer; + scan_timer_info wma_scan_timer_info; + + u_int8_t dfs_phyerr_filter_offload; + v_BOOL_t suitable_ap_hb_failure; + /* record the RSSI when suitable_ap_hb_failure for later usage to + * report RSSI at beacon miss scenario + */ + uint32_t suitable_ap_hb_failure_rssi; + + /* IBSS Power Save config Parameters */ + ibss_power_save_params wma_ibss_power_save_params; +#ifdef FEATURE_WLAN_RA_FILTERING + v_BOOL_t IsRArateLimitEnabled; + u_int16_t RArateLimitInterval; +#endif +#ifdef WLAN_FEATURE_LPSS + bool is_lpass_enabled; +#endif + +#ifdef WLAN_FEATURE_NAN + bool is_nan_enabled; +#endif + + /* Powersave Configuration Parameters */ + u_int8_t staMaxLIModDtim; + u_int8_t staModDtim; + u_int8_t staDynamicDtim; + + int32_t dfs_pri_multiplier; + + u_int32_t hw_bd_id; + u_int32_t hw_bd_info[HW_BD_INFO_SIZE]; + +#ifdef FEATURE_WLAN_D0WOW + atomic_t in_d0wow; +#endif + + /* OCB request contexts */ + struct sir_ocb_config *ocb_config_req; + + uint32_t miracast_value; + vos_timer_t log_completion_timer; + uint32_t txrx_chainmask; + uint8_t per_band_chainmask_supp; + uint16_t self_gen_frm_pwr; + bool tx_chain_mask_cck; + + uint32_t num_of_diag_events_logs; + uint32_t *events_logs_list; + + uint32_t wow_pno_match_wake_up_count; + uint32_t wow_pno_complete_wake_up_count; + uint32_t wow_gscan_wake_up_count; + uint32_t wow_low_rssi_wake_up_count; + uint32_t wow_rssi_breach_wake_up_count; + uint32_t wow_ucast_wake_up_count; + uint32_t wow_bcast_wake_up_count; + uint32_t wow_ipv4_mcast_wake_up_count; + uint32_t wow_ipv6_mcast_wake_up_count; + uint32_t wow_ipv6_mcast_ra_stats; + uint32_t wow_ipv6_mcast_ns_stats; + uint32_t wow_ipv6_mcast_na_stats; + uint32_t wow_wakeup_enable_mask; + uint32_t wow_wakeup_disable_mask; + uint16_t max_mgmt_tx_fail_count; + + struct wma_runtime_pm_context runtime_context; +}t_wma_handle, *tp_wma_handle; + +struct wma_target_cap { + u_int32_t wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; /* wmi services bitmap received from Target */ + wmi_resource_config wlan_resource_config; /* default resource config,the os shim can overwrite it */ +}; + +/********** The following structures are referenced from legacy prima code *********/ +typedef enum { + QWLAN_ISOC_START_CMDID = 0x4000, + QWLAN_ISOC_END_CMDID = 0x4FFF, + + FW_CFG_DOWNLOAD_REQ = QWLAN_ISOC_START_CMDID, + FW_NV_DOWNLOAD_REQ, + FW_WLAN_HAL_STOP_REQ, + /* Add additional commands here */ + + QWLAN_ISOC_MAX_CMDID = QWLAN_ISOC_END_CMDID - 1 +}QWLAN_CMD_ID; +/* The shared memory between WDI and HAL is 4K so maximum data can be transferred +from WDI to HAL is 4K.This 4K should also include the Message header so sending 4K +of NV fragment is nt possbile.The next multiple of 1Kb is 3K */ + +typedef struct +{ + v_VOID_t *pConfigBuffer; + + /*Length of the config buffer above*/ + v_U16_t usConfigBufferLen; + + /*Production or FTM driver*/ + t_wma_drv_type driver_type; + + /*The user data passed in by UMAC, it will be sent back when the above + function pointer will be called */ + v_VOID_t *pUserData; + + /*The user data passed in by UMAC, it will be sent back when the indication + function pointer will be called */ + v_VOID_t *pIndUserData; +}t_wma_start_req; + +/* Message types for messages exchanged between WDI and HAL */ +typedef enum +{ + //Init/De-Init + WLAN_HAL_START_REQ = 0, + WLAN_HAL_START_RSP = 1, + WLAN_HAL_STOP_REQ = 2, + WLAN_HAL_STOP_RSP = 3, + + //Scan + WLAN_HAL_INIT_SCAN_REQ = 4, + WLAN_HAL_INIT_SCAN_RSP = 5, + WLAN_HAL_START_SCAN_REQ = 6, + WLAN_HAL_START_SCAN_RSP = 7 , + WLAN_HAL_END_SCAN_REQ = 8, + WLAN_HAL_END_SCAN_RSP = 9, + WLAN_HAL_FINISH_SCAN_REQ = 10, + WLAN_HAL_FINISH_SCAN_RSP = 11, + + // HW STA configuration/deconfiguration + WLAN_HAL_CONFIG_STA_REQ = 12, + WLAN_HAL_CONFIG_STA_RSP = 13, + WLAN_HAL_DELETE_STA_REQ = 14, + WLAN_HAL_DELETE_STA_RSP = 15, + WLAN_HAL_CONFIG_BSS_REQ = 16, + WLAN_HAL_CONFIG_BSS_RSP = 17, + WLAN_HAL_DELETE_BSS_REQ = 18, + WLAN_HAL_DELETE_BSS_RSP = 19, + + //Infra STA asscoiation + WLAN_HAL_JOIN_REQ = 20, + WLAN_HAL_JOIN_RSP = 21, + WLAN_HAL_POST_ASSOC_REQ = 22, + WLAN_HAL_POST_ASSOC_RSP = 23, + + //Security + WLAN_HAL_SET_BSSKEY_REQ = 24, + WLAN_HAL_SET_BSSKEY_RSP = 25, + WLAN_HAL_SET_STAKEY_REQ = 26, + WLAN_HAL_SET_STAKEY_RSP = 27, + WLAN_HAL_RMV_BSSKEY_REQ = 28, + WLAN_HAL_RMV_BSSKEY_RSP = 29, + WLAN_HAL_RMV_STAKEY_REQ = 30, + WLAN_HAL_RMV_STAKEY_RSP = 31, + + //Qos Related + WLAN_HAL_ADD_TS_REQ = 32, + WLAN_HAL_ADD_TS_RSP = 33, + WLAN_HAL_DEL_TS_REQ = 34, + WLAN_HAL_DEL_TS_RSP = 35, + WLAN_HAL_UPD_EDCA_PARAMS_REQ = 36, + WLAN_HAL_UPD_EDCA_PARAMS_RSP = 37, + WLAN_HAL_ADD_BA_REQ = 38, + WLAN_HAL_ADD_BA_RSP = 39, + WLAN_HAL_DEL_BA_REQ = 40, + WLAN_HAL_DEL_BA_RSP = 41, + + WLAN_HAL_CH_SWITCH_REQ = 42, + WLAN_HAL_CH_SWITCH_RSP = 43, + WLAN_HAL_SET_LINK_ST_REQ = 44, + WLAN_HAL_SET_LINK_ST_RSP = 45, + WLAN_HAL_GET_STATS_REQ = 46, + WLAN_HAL_GET_STATS_RSP = 47, + WLAN_HAL_UPDATE_CFG_REQ = 48, + WLAN_HAL_UPDATE_CFG_RSP = 49, + + WLAN_HAL_MISSED_BEACON_IND = 50, + WLAN_HAL_UNKNOWN_ADDR2_FRAME_RX_IND = 51, + WLAN_HAL_MIC_FAILURE_IND = 52, + WLAN_HAL_FATAL_ERROR_IND = 53, + WLAN_HAL_SET_KEYDONE_MSG = 54, + + //NV Interface + WLAN_HAL_DOWNLOAD_NV_REQ = 55, + WLAN_HAL_DOWNLOAD_NV_RSP = 56, + + WLAN_HAL_ADD_BA_SESSION_REQ = 57, + WLAN_HAL_ADD_BA_SESSION_RSP = 58, + WLAN_HAL_TRIGGER_BA_REQ = 59, + WLAN_HAL_TRIGGER_BA_RSP = 60, + WLAN_HAL_UPDATE_BEACON_REQ = 61, + WLAN_HAL_UPDATE_BEACON_RSP = 62, + WLAN_HAL_SEND_BEACON_REQ = 63, + WLAN_HAL_SEND_BEACON_RSP = 64, + + WLAN_HAL_SET_BCASTKEY_REQ = 65, + WLAN_HAL_SET_BCASTKEY_RSP = 66, + WLAN_HAL_DELETE_STA_CONTEXT_IND = 67, + WLAN_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ = 68, + WLAN_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP = 69, + + // PTT interface support + WLAN_HAL_PROCESS_PTT_REQ = 70, + WLAN_HAL_PROCESS_PTT_RSP = 71, + + WLAN_HAL_TL_HAL_FLUSH_AC_REQ = 74, + WLAN_HAL_TL_HAL_FLUSH_AC_RSP = 75, + + WLAN_HAL_ENTER_IMPS_REQ = 76, + WLAN_HAL_EXIT_IMPS_REQ = 77, + WLAN_HAL_ENTER_BMPS_REQ = 78, + WLAN_HAL_EXIT_BMPS_REQ = 79, + WLAN_HAL_ENTER_UAPSD_REQ = 80, + WLAN_HAL_EXIT_UAPSD_REQ = 81, + WLAN_HAL_UPDATE_UAPSD_PARAM_REQ = 82, + WLAN_HAL_CONFIGURE_RXP_FILTER_REQ = 83, + WLAN_HAL_ADD_BCN_FILTER_REQ = 84, + WLAN_HAL_REM_BCN_FILTER_REQ = 85, + WLAN_HAL_ADD_WOWL_BCAST_PTRN = 86, + WLAN_HAL_DEL_WOWL_BCAST_PTRN = 87, + WLAN_HAL_ENTER_WOWL_REQ = 88, + WLAN_HAL_EXIT_WOWL_REQ = 89, + WLAN_HAL_HOST_OFFLOAD_REQ = 90, + WLAN_HAL_SET_RSSI_THRESH_REQ = 91, + WLAN_HAL_GET_RSSI_REQ = 92, + WLAN_HAL_SET_UAPSD_AC_PARAMS_REQ = 93, + WLAN_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ = 94, + + WLAN_HAL_ENTER_IMPS_RSP = 95, + WLAN_HAL_EXIT_IMPS_RSP = 96, + WLAN_HAL_ENTER_BMPS_RSP = 97, + WLAN_HAL_EXIT_BMPS_RSP = 98, + WLAN_HAL_ENTER_UAPSD_RSP = 99, + WLAN_HAL_EXIT_UAPSD_RSP = 100, + WLAN_HAL_SET_UAPSD_AC_PARAMS_RSP = 101, + WLAN_HAL_UPDATE_UAPSD_PARAM_RSP = 102, + WLAN_HAL_CONFIGURE_RXP_FILTER_RSP = 103, + WLAN_HAL_ADD_BCN_FILTER_RSP = 104, + WLAN_HAL_REM_BCN_FILTER_RSP = 105, + WLAN_HAL_SET_RSSI_THRESH_RSP = 106, + WLAN_HAL_HOST_OFFLOAD_RSP = 107, + WLAN_HAL_ADD_WOWL_BCAST_PTRN_RSP = 108, + WLAN_HAL_DEL_WOWL_BCAST_PTRN_RSP = 109, + WLAN_HAL_ENTER_WOWL_RSP = 110, + WLAN_HAL_EXIT_WOWL_RSP = 111, + WLAN_HAL_RSSI_NOTIFICATION_IND = 112, + WLAN_HAL_GET_RSSI_RSP = 113, + WLAN_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_RSP = 114, + + //11k related events + WLAN_HAL_SET_MAX_TX_POWER_REQ = 115, + WLAN_HAL_SET_MAX_TX_POWER_RSP = 116, + + //11R related msgs + WLAN_HAL_AGGR_ADD_TS_REQ = 117, + WLAN_HAL_AGGR_ADD_TS_RSP = 118, + + //P2P WLAN_FEATURE_P2P + WLAN_HAL_SET_P2P_GONOA_REQ = 119, + WLAN_HAL_SET_P2P_GONOA_RSP = 120, + + //WLAN Dump commands + WLAN_HAL_DUMP_COMMAND_REQ = 121, + WLAN_HAL_DUMP_COMMAND_RSP = 122, + + //OEM_DATA FEATURE SUPPORT + WLAN_HAL_START_OEM_DATA_REQ = 123, + WLAN_HAL_START_OEM_DATA_RSP = 124, + + //ADD SELF STA REQ and RSP + WLAN_HAL_ADD_STA_SELF_REQ = 125, + WLAN_HAL_ADD_STA_SELF_RSP = 126, + + //DEL SELF STA SUPPORT + WLAN_HAL_DEL_STA_SELF_REQ = 127, + WLAN_HAL_DEL_STA_SELF_RSP = 128, + + // Coex Indication + WLAN_HAL_COEX_IND = 129, + + // Tx Complete Indication + WLAN_HAL_OTA_TX_COMPL_IND = 130, + + //Host Suspend/resume messages + WLAN_HAL_HOST_SUSPEND_IND = 131, + WLAN_HAL_HOST_RESUME_REQ = 132, + WLAN_HAL_HOST_RESUME_RSP = 133, + + WLAN_HAL_SET_TX_POWER_REQ = 134, + WLAN_HAL_SET_TX_POWER_RSP = 135, + WLAN_HAL_GET_TX_POWER_REQ = 136, + WLAN_HAL_GET_TX_POWER_RSP = 137, + + WLAN_HAL_P2P_NOA_ATTR_IND = 138, + + WLAN_HAL_ENABLE_RADAR_DETECT_REQ = 139, + WLAN_HAL_ENABLE_RADAR_DETECT_RSP = 140, + WLAN_HAL_GET_TPC_REPORT_REQ = 141, + WLAN_HAL_GET_TPC_REPORT_RSP = 142, + WLAN_HAL_RADAR_DETECT_IND = 143, + WLAN_HAL_RADAR_DETECT_INTR_IND = 144, + WLAN_HAL_KEEP_ALIVE_REQ = 145, + WLAN_HAL_KEEP_ALIVE_RSP = 146, + + /*PNO messages*/ + WLAN_HAL_SET_PREF_NETWORK_REQ = 147, + WLAN_HAL_SET_PREF_NETWORK_RSP = 148, + WLAN_HAL_SET_RSSI_FILTER_REQ = 149, + WLAN_HAL_SET_RSSI_FILTER_RSP = 150, + WLAN_HAL_UPDATE_SCAN_PARAM_REQ = 151, + WLAN_HAL_UPDATE_SCAN_PARAM_RSP = 152, + WLAN_HAL_PREF_NETW_FOUND_IND = 153, + + WLAN_HAL_SET_TX_PER_TRACKING_REQ = 154, + WLAN_HAL_SET_TX_PER_TRACKING_RSP = 155, + WLAN_HAL_TX_PER_HIT_IND = 156, + + WLAN_HAL_8023_MULTICAST_LIST_REQ = 157, + WLAN_HAL_8023_MULTICAST_LIST_RSP = 158, + + WLAN_HAL_SET_PACKET_FILTER_REQ = 159, + WLAN_HAL_SET_PACKET_FILTER_RSP = 160, + WLAN_HAL_PACKET_FILTER_MATCH_COUNT_REQ = 161, + WLAN_HAL_PACKET_FILTER_MATCH_COUNT_RSP = 162, + WLAN_HAL_CLEAR_PACKET_FILTER_REQ = 163, + WLAN_HAL_CLEAR_PACKET_FILTER_RSP = 164, + /*This is temp fix. Should be removed once + * Host and Riva code is in sync*/ + WLAN_HAL_INIT_SCAN_CON_REQ = 165, + + WLAN_HAL_SET_POWER_PARAMS_REQ = 166, + WLAN_HAL_SET_POWER_PARAMS_RSP = 167, + + WLAN_HAL_TSM_STATS_REQ = 168, + WLAN_HAL_TSM_STATS_RSP = 169, + + // wake reason indication (WOW) + WLAN_HAL_WAKE_REASON_IND = 170, + // GTK offload support + WLAN_HAL_GTK_OFFLOAD_REQ = 171, + WLAN_HAL_GTK_OFFLOAD_RSP = 172, + WLAN_HAL_GTK_OFFLOAD_GETINFO_REQ = 173, + WLAN_HAL_GTK_OFFLOAD_GETINFO_RSP = 174, + + WLAN_HAL_FEATURE_CAPS_EXCHANGE_REQ = 175, + WLAN_HAL_FEATURE_CAPS_EXCHANGE_RSP = 176, + WLAN_HAL_EXCLUDE_UNENCRYPTED_IND = 177, + + WLAN_HAL_SET_THERMAL_MITIGATION_REQ = 178, + WLAN_HAL_SET_THERMAL_MITIGATION_RSP = 179, + + WLAN_HAL_UPDATE_VHT_OP_MODE_REQ = 182, + WLAN_HAL_UPDATE_VHT_OP_MODE_RSP = 183, + + WLAN_HAL_P2P_NOA_START_IND = 184, + + WLAN_HAL_CLASS_B_STATS_IND = 187, + WLAN_HAL_DEL_BA_IND = 188, + WLAN_HAL_DHCP_START_IND = 189, + WLAN_HAL_DHCP_STOP_IND = 190, + + WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE +}tHalHostMsgType; + +/* Enumeration for Version */ +typedef enum +{ + WLAN_HAL_MSG_VERSION0 = 0, + WLAN_HAL_MSG_VERSION1 = 1, + WLAN_HAL_MSG_WCNSS_CTRL_VERSION = 0x7FFF, /*define as 2 bytes data*/ + WLAN_HAL_MSG_VERSION_MAX_FIELD = WLAN_HAL_MSG_WCNSS_CTRL_VERSION +} tHalHostMsgVersion; + +/* 4-byte control message header used by HAL*/ +typedef PACKED_PRE struct PACKED_POST +{ + tHalHostMsgType msgType:16; + tHalHostMsgVersion msgVersion:16; + tANI_U32 msgLen; +} tHalMsgHeader, *tpHalMsgHeader; + +/*--------------------------------------------------------------------------- + WLAN_HAL_START_REQ + ---------------------------------------------------------------------------*/ + +typedef PACKED_PRE struct PACKED_POST sHalMacStartParameter +{ + /* Drive Type - Production or FTM etc */ + tDriverType driverType; + + /*Length of the config buffer*/ + tANI_U32 uConfigBufferLen; + + /* Following this there is a TLV formatted buffer of length + * "uConfigBufferLen" bytes containing all config values. + * The TLV is expected to be formatted like this: + * 0 15 31 31+CFG_LEN-1 length-1 + * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| + */ +} tHalMacStartParameter, *tpHalMacStartParameter; + +typedef PACKED_PRE struct PACKED_POST +{ + /* Note: The length specified in tHalMacStartReqMsg messages should be + * header.msgLen = sizeof(tHalMacStartReqMsg) + uConfigBufferLen */ + tHalMsgHeader header; + tHalMacStartParameter startReqParams; +} tHalMacStartReqMsg, *tpHalMacStartReqMsg; + +extern v_BOOL_t sys_validateStaConfig(void *pImage, unsigned long cbFile, + void **ppStaConfig, v_SIZE_t *pcbStaConfig); +extern void vos_WDAComplete_cback(v_PVOID_t pVosContext); +extern void wma_send_regdomain_info(u_int32_t reg_dmn, u_int16_t regdmn2G, + u_int16_t regdmn5G, int8_t ctl2G, + int8_t ctl5G); + +void wma_get_modeselect(tp_wma_handle wma, u_int32_t *modeSelect); + +void wma_set_dfs_regdomain(tp_wma_handle wma, uint8_t dfs_region); + +/** + * Frame index + */ +enum frame_index { + GENERIC_NODOWNLD_NOACK_COMP_INDEX, + GENERIC_DOWNLD_COMP_NOACK_COMP_INDEX, + GENERIC_DOWNLD_COMP_ACK_COMP_INDEX, + GENERIC_NODOWLOAD_ACK_COMP_INDEX, + FRAME_INDEX_MAX +}; + +VOS_STATUS wma_update_vdev_tbl(tp_wma_handle wma_handle, u_int8_t vdev_id, + ol_txrx_vdev_handle tx_rx_vdev_handle, u_int8_t *mac, + u_int32_t vdev_type, bool add_del); + +int32_t regdmn_get_regdmn_for_country(u_int8_t *alpha2); +void regdmn_get_ctl_info(struct regulatory *reg, u_int32_t modesAvail, + u_int32_t modeSelect); + +/*get the ctl from regdomain*/ +u_int8_t regdmn_get_ctl_for_regdmn(u_int32_t reg_dmn); +u_int16_t get_regdmn_5g(u_int32_t reg_dmn); + +#define WMA_FW_PHY_STATS 0x1 +#define WMA_FW_RX_REORDER_STATS 0x2 +#define WMA_FW_RX_RC_STATS 0x3 +#define WMA_FW_TX_PPDU_STATS 0x4 +#define WMA_FW_TX_CONCISE_STATS 0x5 +#define WMA_FW_TX_RC_STATS 0x6 +#define WMA_FW_RX_REM_RING_BUF 0xc +#define WMA_FW_RX_TXBF_MUSU_NDPA 0xf +#define WMA_FW_TXRX_FWSTATS_RESET 0x1f + +/* + * Setting the Tx Comp Timeout to 1 secs. + * TODO: Need to Revist the Timing + */ +#define WMA_TX_FRAME_COMPLETE_TIMEOUT 1000 +#define WMA_TX_FRAME_BUFFER_NO_FREE 0 +#define WMA_TX_FRAME_BUFFER_FREE 1 + +struct wma_tx_ack_work_ctx { + tp_wma_handle wma_handle; + u_int16_t sub_type; + int32_t status; + struct work_struct ack_cmp_work; +}; + +#define WMA_TARGET_REQ_TYPE_VDEV_START 0x1 +#define WMA_TARGET_REQ_TYPE_VDEV_STOP 0x2 +#define WMA_TARGET_REQ_TYPE_VDEV_DEL 0x3 + +#define WMA_VDEV_START_REQUEST_TIMEOUT (3000) /* 3 seconds */ +#define WMA_VDEV_STOP_REQUEST_TIMEOUT (3000) /* 3 seconds */ + +struct wma_target_req { + vos_timer_t event_timeout; + struct list_head node; + void *user_data; + u_int32_t msg_type; + u_int8_t vdev_id; + u_int8_t type; +}; + +struct wma_vdev_start_req { + u_int32_t beacon_intval; + u_int32_t dtim_period; + int32_t max_txpow; + ePhyChanBondState chan_offset; + bool is_dfs; + u_int8_t vdev_id; + u_int8_t chan; + u_int8_t oper_mode; + tSirMacSSid ssid; + u_int8_t hidden_ssid; + u_int8_t pmf_enabled; + u_int8_t vht_capable; + u_int8_t ht_capable; + int32_t dfs_pri_multiplier; + u_int8_t dot11_mode; + bool is_half_rate; + bool is_quarter_rate; +}; + +struct wma_set_key_params { + u_int8_t vdev_id; + /* def_key_idx can be used to see if we have to read the key from cfg */ + u_int32_t def_key_idx; + u_int16_t key_len; + u_int8_t peer_mac[ETH_ALEN]; + u_int8_t singl_tid_rc; + enum eAniEdType key_type; + u_int32_t key_idx; + bool unicast; + u_int8_t key_data[SIR_MAC_MAX_KEY_LENGTH]; +}; + +typedef struct { + u_int16_t minTemp; + u_int16_t maxTemp; + u_int8_t thermalEnable; +} t_thermal_cmd_params, *tp_thermal_cmd_params; + +/* Powersave Related */ +/* Default InActivity Time is 200 ms */ +#define POWERSAVE_DEFAULT_INACTIVITY_TIME 200 + +/* Default Listen Interval */ +#define POWERSAVE_DEFAULT_LISTEN_INTERVAL 1 + +/* + * TODO: Add WMI_CMD_ID_MAX as part of WMI_CMD_ID + * instead of assigning it to the last valid wmi + * cmd+1 to avoid updating this when a command is + * added/deleted. + */ +#define WMI_CMDID_MAX (WMI_TXBF_CMDID + 1) + +/* + * wma cmd ids for configuration request which + * does not involve sending a wmi command. + */ +enum wma_cfg_cmd_id { + WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID = WMI_CMDID_MAX, + WMA_VDEV_TXRX_FWSTATS_RESET_CMDID, + /* Set time latency and time quota for MCC home channels */ + WMA_VDEV_MCC_SET_TIME_LATENCY, + WMA_VDEV_MCC_SET_TIME_QUOTA, + + /* IBSS Power Save Parameters */ + WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE, + WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED, + WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED, + WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX, + WMA_VDEV_IBSS_SET_INACTIVITY_TIME, + WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME, + WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS, + WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW, + + /* dfs control interface */ + WMA_VDEV_DFS_CONTROL_CMDID, + WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID, + + /* Add any new command before this */ + WMA_CMD_ID_MAX +}; + +typedef struct wma_trigger_uapsd_params +{ + u_int32_t wmm_ac; + u_int32_t user_priority; + u_int32_t service_interval; + u_int32_t suspend_interval; + u_int32_t delay_interval; +}t_wma_trigger_uapsd_params, *tp_wma_trigger_uapsd_params; + +VOS_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, u_int32_t vdev_id, + tp_wma_trigger_uapsd_params trigger_uapsd_params); + +/* added to get average snr for both data and beacon */ +VOS_STATUS wma_send_snr_request(tp_wma_handle wma_handle, void *pGetRssiReq, + v_S7_t first_rssi); + + +#define WMA_NLO_FREQ_THRESH 1000 /* in MHz */ +#define WMA_SEC_TO_MSEC(sec) (sec * 1000) /* sec to msec */ +#define WMA_MSEC_TO_USEC(msec) (msec * 1000) /* msec to usec */ + +/* Default rssi threshold defined in CFG80211 */ +#define WMA_RSSI_THOLD_DEFAULT -300 + +#ifdef FEATURE_WLAN_SCAN_PNO +#define WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT (5 * 1000) /* in msec */ +#define WMA_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT (2 * 1000) /* in msec */ +#endif +#define WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT (5 * 1000) /* in msec */ +#define WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ +#define WMA_DEAUTH_RECV_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ +#define WMA_DISASSOC_RECV_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +#define WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ +#endif +#define WMA_BMISS_EVENT_WAKE_LOCK_DURATION (4 * 1000) /* in msec */ + +/* U-APSD maximum service period of peer station */ +enum uapsd_peer_param_max_sp { + UAPSD_MAX_SP_LEN_UNLIMITED = 0, + UAPSD_MAX_SP_LEN_2 = 2, + UAPSD_MAX_SP_LEN_4 = 4, + UAPSD_MAX_SP_LEN_6 = 6 +}; + +/* U-APSD Enabled AC's of peer station */ +enum uapsd_peer_param_enabled_ac { + UAPSD_VO_ENABLED = 0x01, + UAPSD_VI_ENABLED = 0x02, + UAPSD_BK_ENABLED = 0x04, + UAPSD_BE_ENABLED = 0x08 +}; + +#define WMA_TXMIC_LEN 8 +#define WMA_RXMIC_LEN 8 + +/* + * Length = (2 octets for Index and CTWin/Opp PS) and + * (13 octets for each NOA Descriptors) + */ + +#define WMA_P2P_NOA_IE_OPP_PS_SET (0x80) +#define WMA_P2P_NOA_IE_CTWIN_MASK (0x7F) + +#define WMA_P2P_IE_ID 0xdd +#define WMA_P2P_WFA_OUI { 0x50,0x6f,0x9a } +#define WMA_P2P_WFA_VER 0x09 /* ver 1.0 */ +#define WMA_WSC_OUI { 0x00,0x50,0xF2 } /* Microsoft WSC OUI byte */ + +/* P2P Sub element defintions (according to table 5 of Wifi's P2P spec) */ +#define WMA_P2P_SUB_ELEMENT_STATUS 0 +#define WMA_P2P_SUB_ELEMENT_MINOR_REASON 1 +#define WMA_P2P_SUB_ELEMENT_CAPABILITY 2 +#define WMA_P2P_SUB_ELEMENT_DEVICE_ID 3 +#define WMA_P2P_SUB_ELEMENT_GO_INTENT 4 +#define WMA_P2P_SUB_ELEMENT_CONFIGURATION_TIMEOUT 5 +#define WMA_P2P_SUB_ELEMENT_LISTEN_CHANNEL 6 +#define WMA_P2P_SUB_ELEMENT_GROUP_BSSID 7 +#define WMA_P2P_SUB_ELEMENT_EXTENDED_LISTEN_TIMING 8 +#define WMA_P2P_SUB_ELEMENT_INTENDED_INTERFACE_ADDR 9 +#define WMA_P2P_SUB_ELEMENT_MANAGEABILITY 10 +#define WMA_P2P_SUB_ELEMENT_CHANNEL_LIST 11 +#define WMA_P2P_SUB_ELEMENT_NOA 12 +#define WMA_P2P_SUB_ELEMENT_DEVICE_INFO 13 +#define WMA_P2P_SUB_ELEMENT_GROUP_INFO 14 +#define WMA_P2P_SUB_ELEMENT_GROUP_ID 15 +#define WMA_P2P_SUB_ELEMENT_INTERFACE 16 +#define WMA_P2P_SUB_ELEMENT_OP_CHANNEL 17 +#define WMA_P2P_SUB_ELEMENT_INVITATION_FLAGS 18 +#define WMA_P2P_SUB_ELEMENT_VENDOR 221 + +/* Macros for handling unaligned memory accesses */ +#define P2PIE_PUT_LE16(a, val) \ + do { \ + (a)[1] = ((u16) (val)) >> 8; \ + (a)[0] = ((u16) (val)) & 0xff; \ + } while (0) + +#define P2PIE_PUT_LE32(a, val) \ + do { \ + (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ + (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[0] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +/* + * P2P IE structural definition. + */ +struct p2p_ie { + u_int8_t p2p_id; + u_int8_t p2p_len; + u_int8_t p2p_oui[3]; + u_int8_t p2p_oui_type; +} __packed; + +struct p2p_noa_descriptor { + u_int8_t type_count; /* 255: continuous schedule, 0: reserved */ + u_int32_t duration ; /* Absent period duration in micro seconds */ + u_int32_t interval; /* Absent period interval in micro seconds */ + u_int32_t start_time; /* 32 bit tsf time when in starts */ +} __packed; + +struct p2p_sub_element_noa { + u_int8_t p2p_sub_id; + u_int8_t p2p_sub_len; + u_int8_t index; /* identifies instance of NOA su element */ + u_int8_t oppPS:1, /* oppPS state of the AP */ + ctwindow:7; /* ctwindow in TUs */ + u_int8_t num_descriptors; /* number of NOA descriptors */ + struct p2p_noa_descriptor noa_descriptors[WMA_MAX_NOA_DESCRIPTORS]; +}; + +struct wma_decap_info_t { + u_int8_t hdr[sizeof(struct ieee80211_qosframe_addr4)]; + int32_t hdr_len; +}; + + +#define WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE 1 + +typedef enum { + /* set packet power save */ + WMI_VDEV_PPS_PAID_MATCH = 0, + WMI_VDEV_PPS_GID_MATCH = 1, + WMI_VDEV_PPS_EARLY_TIM_CLEAR = 2, + WMI_VDEV_PPS_EARLY_DTIM_CLEAR = 3, + WMI_VDEV_PPS_EOF_PAD_DELIM = 4, + WMI_VDEV_PPS_MACADDR_MISMATCH = 5, + WMI_VDEV_PPS_DELIM_CRC_FAIL = 6, + WMI_VDEV_PPS_GID_NSTS_ZERO = 7, + WMI_VDEV_PPS_RSSI_CHECK = 8, + WMI_VDEV_VHT_SET_GID_MGMT = 9, + WMI_VDEV_PPS_5G_EBT = 10 +} packet_power_save; + +typedef enum { + WMI_VDEV_PARAM_GTX_HT_MCS, + WMI_VDEV_PARAM_GTX_VHT_MCS, + WMI_VDEV_PARAM_GTX_USR_CFG, + WMI_VDEV_PARAM_GTX_THRE, + WMI_VDEV_PARAM_GTX_MARGIN, + WMI_VDEV_PARAM_GTX_STEP, + WMI_VDEV_PARAM_GTX_MINTPC, + WMI_VDEV_PARAM_GTX_BW_MASK, +}green_tx_param; + +#define WMA_DEFAULT_QPOWER_MAX_PSPOLL_BEFORE_WAKE 1 +#define WMA_DEFAULT_QPOWER_TX_WAKE_THRESHOLD 2 +#define WMA_DEFAULT_SIFS_BURST_DURATION 8160 + +#define WMA_VHT_PPS_PAID_MATCH 1 +#define WMA_VHT_PPS_GID_MATCH 2 +#define WMA_VHT_PPS_DELIM_CRC_FAIL 3 + +#ifdef FEATURE_WLAN_TDLS +typedef struct wma_tdls_params +{ + tANI_U32 vdev_id; + tANI_U32 tdls_state; + tANI_U32 notification_interval_ms; + tANI_U32 tx_discovery_threshold; + tANI_U32 tx_teardown_threshold; + tANI_S32 rssi_teardown_threshold; + tANI_S32 rssi_delta; + tANI_U32 tdls_options; + tANI_U32 peer_traffic_ind_window; + tANI_U32 peer_traffic_response_timeout; + tANI_U32 puapsd_mask; + tANI_U32 puapsd_inactivity_time; + tANI_U32 puapsd_rx_frame_threshold; + uint32_t teardown_notification_ms; + uint32_t tdls_peer_kickout_threshold; +} t_wma_tdls_params; + +typedef struct { + /** unique id identifying the VDEV */ + A_UINT32 vdev_id; + /** peer MAC address */ + wmi_mac_addr peer_macaddr; + /** TDLS peer status (wma_tdls_peer_notification)*/ + A_UINT32 peer_status; + /** TDLS peer reason (wma_tdls_peer_reason) */ + A_UINT32 peer_reason; +} wma_tdls_peer_event; + +#endif /* FEATURE_WLAN_TDLS */ + +#define WMA_DFS_MAX_20M_SUB_CH 8 + +struct wma_dfs_radar_channel_list { + A_UINT32 nchannels; + /*Channel number including bonded channels on which the RADAR is present */ + u_int8_t channels[WMA_DFS_MAX_20M_SUB_CH]; +}; + +/* + * Structure to indicate RADAR + */ + +struct wma_dfs_radar_indication { + /* unique id identifying the VDEV */ + A_UINT32 vdev_id; + /* Channel list on which RADAR is detected */ + struct wma_dfs_radar_channel_list chan_list; + /* Flag to Indicate RADAR presence on the + * current operating channel + */ + u_int32_t dfs_radar_status; + /* Flag to indicate use NOL */ + int use_nol; +}; + +/* + * WMA-DFS Hooks + */ +int ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info); +u_int64_t ol_if_get_tsf64(struct ieee80211com *ic); +int ol_if_dfs_disable(struct ieee80211com *ic); +struct ieee80211_channel * ieee80211_find_channel(struct ieee80211com *ic, + int freq, u_int32_t flags); +int ol_if_dfs_enable(struct ieee80211com *ic, int *is_fastclk, void *pe); +u_int32_t ieee80211_ieee2mhz(u_int32_t chan, u_int32_t flags); +int ol_if_dfs_get_ext_busy(struct ieee80211com *ic); +int ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, + u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt); +u_int16_t ol_if_dfs_usenol(struct ieee80211com *ic); +void ieee80211_mark_dfs(struct ieee80211com *ic, + struct ieee80211_channel *ichan); +int wma_dfs_indicate_radar(struct ieee80211com *ic, + struct ieee80211_channel *ichan); +u_int16_t dfs_usenol(struct ieee80211com *ic); + +#define WMA_SMPS_MASK_LOWER_16BITS 0xFF +#define WMA_SMPS_MASK_UPPER_3BITS 0x7 +#define WMA_SMPS_PARAM_VALUE_S 29 + +#define WMA_MAX_SCAN_ID 0x00FF + +/* U-APSD Access Categories */ +enum uapsd_ac { + UAPSD_BE, + UAPSD_BK, + UAPSD_VI, + UAPSD_VO +}; + +VOS_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle, + u_int32_t vdev_id, + enum uapsd_ac ac); + +/* U-APSD User Priorities */ +enum uapsd_up { + UAPSD_UP_BE, + UAPSD_UP_BK, + UAPSD_UP_RESV, + UAPSD_UP_EE, + UAPSD_UP_CL, + UAPSD_UP_VI, + UAPSD_UP_VO, + UAPSD_UP_NC, + UAPSD_UP_MAX +}; + +#ifdef FEATURE_WLAN_D0WOW +void wma_set_d0wow_flag(tp_wma_handle wma_handle, A_BOOL flag); +A_BOOL wma_read_d0wow_flag(tp_wma_handle wma_handle); +#endif + +A_UINT32 eCsrAuthType_to_rsn_authmode (eCsrAuthType authtype, + eCsrEncryptionType encr); +A_UINT32 eCsrEncryptionType_to_rsn_cipherset (eCsrEncryptionType encr); + +#define WMA_TGT_INVALID_SNR (-1) + +#define WMA_TX_Q_RECHECK_TIMER_WAIT 2 // 2 ms +#define WMA_TX_Q_RECHECK_TIMER_MAX_WAIT 20 // 20 ms +#define WMA_MAX_NUM_ARGS 8 +typedef struct wma_unit_test_cmd +{ + v_UINT_t vdev_id; + WLAN_MODULE_ID module_id; + v_U32_t num_args; + v_U32_t args[WMA_MAX_NUM_ARGS]; +}t_wma_unit_test_cmd; + +typedef struct wma_roam_invoke_cmd +{ + v_UINT_t vdev_id; + u_int8_t bssid[6]; + v_U32_t channel; +}t_wma_roam_invoke_cmd; + +struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, u_int8_t vdev_id, + u_int32_t msg_type, u_int8_t type, void *params, u_int32_t timeout); + +VOS_STATUS wma_vdev_start(tp_wma_handle wma, struct wma_vdev_start_req *req, + v_BOOL_t isRestart); + +void wma_remove_vdev_req(tp_wma_handle wma, u_int8_t vdev_id, u_int8_t type); + +#ifdef REMOVE_PKT_LOG +static inline void wma_set_wifi_start_packet_stats(void *wma_handle, + struct sir_wifi_start_log *start_log) +{ + return; +} +#endif + +void wma_send_flush_logs_to_fw(tp_wma_handle wma_handle); +struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id); +bool wma_is_vdev_up(uint8_t vdev_id); + +int wma_crash_inject(tp_wma_handle wma_handle, uint32_t type, + uint32_t delay_time_ms); + +uint32_t wma_get_vht_ch_width(void); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_dfs_interface.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_dfs_interface.c new file mode 100644 index 000000000000..edd5a80cc7fd --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_dfs_interface.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + wma_dfs_interface.c + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- + +===========================================================================*/ + + + +#include "wma.h" +#include "ath_dfs_structs.h" +#include "wma_dfs_interface.h" + +#ifndef ATH_SUPPORT_DFS +#define ATH_SUPPORT_DFS 1 +#endif + +int +ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info) +{ + struct ath_dfs_caps *pCap = (struct ath_dfs_caps *) ptr; + + adf_os_print("%s: called; ptr=%p, radar_info=%p\n", + __func__, ptr, radar_info); + + pCap->ath_chip_is_bb_tlv = 1; + pCap->ath_dfs_combined_rssi_ok = 0; + pCap->ath_dfs_ext_chan_ok = 0; + pCap->ath_dfs_use_enhancement = 0; + pCap->ath_strong_signal_diversiry = 0; + pCap->ath_fastdiv_val = 0; + + return(0); +} + +/* + * Place Holder API + * We get the tsf from Firmware. + */ +u_int64_t +ol_if_get_tsf64(struct ieee80211com *ic) +{ + return (0); +} + +/* + * ic_dfs_disable is just a place holder + * function since firmware takes care of + * disabling the dfs phyerrors disabling. + */ +int +ol_if_dfs_disable(struct ieee80211com *ic) +{ + return (0); +} + + +/* + * Locate a channel given a frequency+flags. We cache + * the previous lookup to optimize swithing between two + * channels--as happens with dynamic turbo. + * This verifies that found channels have not been excluded because of 11d. + */ +struct ieee80211_channel * +ieee80211_find_channel(struct ieee80211com *ic, int freq, u_int32_t flags) +{ + struct ieee80211_channel *c; + int i; + + flags &= IEEE80211_CHAN_ALLTURBO; + /* brute force search */ + for (i = 0; i < ic->ic_nchans; i++) + { + c = &ic->ic_channels[i]; + + if ((! IEEE80211_IS_CHAN_11D_EXCLUDED(c)) && + (c->ic_freq == freq) && + ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)) + { + return c; + } + } + + return NULL; +} + + +/* + * ic_dfs_enable - enable DFS + * For offload solutions, radar PHY errors will be enabled by the target + * firmware when DFS is requested for the current channel. + */ +int ol_if_dfs_enable(struct ieee80211com *ic, int *is_fastclk, void *pe) +{ + /* + * For peregrine, treat fastclk as the "oversampling" mode. + * It's on by default. This may change at some point, so + * we should really query the firmware to find out what + * the current configuration is. + */ + (* is_fastclk) = 1; + + return (0); +} + +/* + * Convert IEEE channel number to MHz frequency. + */ +u_int32_t +ieee80211_ieee2mhz(u_int32_t chan, u_int32_t flags) +{ + if (flags & IEEE80211_CHAN_2GHZ) + { + /* 2GHz band */ + if (chan == 14) + return 2484; + if (chan < 14) + return 2407 + chan*5; + else + return 2512 + ((chan-15)*20); + } + else if (flags & IEEE80211_CHAN_5GHZ) + { + /* 5Ghz band */ + return 5000 + (chan*5); + } + else + { + /* either, guess */ + if (chan == 14) + return 2484; + if (chan < 14) /* 0-13 */ + return 2407 + chan*5; + if (chan < 27) /* 15-26 */ + return 2512 + ((chan-15)*20); + return 5000 + (chan*5); + } +} + +/* + * Place holder function ic_get_ext_busy + */ +int +ol_if_dfs_get_ext_busy(struct ieee80211com *ic) +{ + return (0); +} + +/* + * ic_get_mib_cycle_counts_pct + */ +int +ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, + u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt) +{ + return (0); +} + +u_int16_t +ol_if_dfs_usenol(struct ieee80211com *ic) +{ +#if ATH_SUPPORT_DFS + return(dfs_usenol(ic)); +#else + return (0); +#endif /* ATH_SUPPORT_DFS */ + return 0; +} + +/* + * Function to indicate Radar on the current + * SAP operating channel.This indication will + * be posted to SAP to select a new channel + * randomly and issue a vdev restart to + * operate on the new channel. + */ +void +ieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan) +{ + int status; + status = wma_dfs_indicate_radar(ic, ichan); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c new file mode 100644 index 000000000000..2abed4d61464 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c @@ -0,0 +1,1122 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * DOC: wma_ocb.c + * + * WLAN Host Device Driver 802.11p OCB implementation + */ + +#include "wma_ocb.h" +#include "wmi_unified_api.h" +#include "vos_utils.h" + +/** + * wma_ocb_resp() - send the OCB set config response via callback + * @wma_handle: pointer to the WMA handle + * @status: status of the set config command + */ +int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status) +{ + VOS_STATUS vos_status; + struct sir_ocb_set_config_response *resp; + vos_msg_t msg = {0}; + struct sir_ocb_config *req = wma_handle->ocb_config_req; + ol_txrx_vdev_handle vdev = (req ? + wma_handle->interfaces[req->session_id].handle : 0); + + /* + * If the command was successful, save the channel information in the + * vdev. + */ + if (status == VOS_STATUS_SUCCESS) { + if (vdev && req) { + if (vdev->ocb_channel_info) + vos_mem_free(vdev->ocb_channel_info); + vdev->ocb_channel_count = + req->channel_count; + if (req->channel_count) { + int i; + int buf_size = sizeof(*vdev->ocb_channel_info) * + req->channel_count; + vdev->ocb_channel_info = + vos_mem_malloc(buf_size); + if (!vdev->ocb_channel_info) + return -ENOMEM; + vos_mem_zero(vdev->ocb_channel_info, buf_size); + for (i = 0; i < req->channel_count; i++) { + vdev->ocb_channel_info[i].chan_freq = + req->channels[i].chan_freq; + if (req->channels[i].flags & + OCB_CHANNEL_FLAG_DISABLE_RX_STATS_HDR) + vdev->ocb_channel_info[i]. + disable_rx_stats_hdr = 1; + } + } else { + vdev->ocb_channel_info = 0; + } + } + } + + /* Free the configuration that was saved in wma_ocb_set_config. */ + vos_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = 0; + + resp = vos_mem_malloc(sizeof(*resp)); + if (!resp) + return -ENOMEM; + + resp->status = status; + + msg.type = eWNI_SME_OCB_SET_CONFIG_RSP; + msg.bodyptr = resp; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE(FL("Fail to post msg to SME")); + vos_mem_free(resp); + return -EINVAL; + } + + return 0; +} + +/** + * copy_sir_ocb_config() - deep copy of an OCB config struct + * @src: pointer to the source struct + * + * Return: pointer to the copied struct + */ +static struct sir_ocb_config *copy_sir_ocb_config(struct sir_ocb_config *src) +{ + struct sir_ocb_config *dst; + uint32_t length; + void *cursor; + + length = sizeof(*src) + + src->channel_count * sizeof(*src->channels) + + src->schedule_size * sizeof(*src->schedule) + + src->dcc_ndl_chan_list_len + + src->dcc_ndl_active_state_list_len; + + dst = vos_mem_malloc(length); + if (!dst) + return NULL; + + *dst = *src; + + cursor = dst; + cursor += sizeof(*dst); + dst->channels = cursor; + cursor += src->channel_count * sizeof(*dst->channels); + vos_mem_copy(dst->channels, src->channels, + src->channel_count * sizeof(*dst->channels)); + dst->schedule = cursor; + cursor += src->schedule_size * sizeof(*dst->schedule); + vos_mem_copy(dst->schedule, src->schedule, + src->schedule_size * sizeof(*dst->schedule)); + dst->dcc_ndl_chan_list = cursor; + cursor += src->dcc_ndl_chan_list_len; + vos_mem_copy(dst->dcc_ndl_chan_list, src->dcc_ndl_chan_list, + src->dcc_ndl_chan_list_len); + dst->dcc_ndl_active_state_list = cursor; + cursor += src->dcc_ndl_active_state_list_len; + vos_mem_copy(dst->dcc_ndl_active_state_list, + src->dcc_ndl_active_state_list, + src->dcc_ndl_active_state_list_len); + return dst; +} + +/** + * wma_ocb_set_config_req() - send the OCB config request + * @wma_handle: pointer to the WMA handle + * @config_req: the configuration to be set. + */ +int wma_ocb_set_config_req(tp_wma_handle wma_handle, + struct sir_ocb_config *config_req) +{ + struct wma_target_req *msg; + struct wma_vdev_start_req req; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + /* if vdev is not yet up, send vdev start request and wait for response. + * OCB set_config request should be sent on receiving + * vdev start response message + */ + if (!wma_handle->interfaces[config_req->session_id].vdev_up) { + vos_mem_zero(&req, sizeof(req)); + /* Enqueue OCB Set Schedule request message */ + msg = wma_fill_vdev_req(wma_handle, config_req->session_id, + WDA_OCB_SET_CONFIG_CMD, + WMA_TARGET_REQ_TYPE_VDEV_START, + (void *)config_req, 1000); + if (!msg) { + WMA_LOGE(FL("Failed to fill vdev req %d"), req.vdev_id); + status = VOS_STATUS_E_NOMEM; + return status; + } + req.chan = vos_freq_to_chan(config_req->channels[0].chan_freq); + req.vdev_id = msg->vdev_id; + if (vos_chan_to_band(req.chan) == VOS_BAND_2GHZ) + req.dot11_mode = WNI_CFG_DOT11_MODE_11G; + else + req.dot11_mode = WNI_CFG_DOT11_MODE_11A; + + if (wma_handle->ocb_config_req) + vos_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = copy_sir_ocb_config(config_req); + + status = wma_vdev_start(wma_handle, &req, VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + wma_remove_vdev_req(wma_handle, req.vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + WMA_LOGE(FL("vdev_start failed, status = %d"), status); + } + return 0; + } else { + return wma_ocb_set_config(wma_handle, config_req); + } +} + +int wma_ocb_start_resp_ind_cont(tp_wma_handle wma_handle) +{ + VOS_STATUS vos_status = 0; + + if (!wma_handle->ocb_config_req) { + WMA_LOGE(FL("The request could not be found")); + return VOS_STATUS_E_EMPTY; + } + + vos_status = wma_ocb_set_config(wma_handle, wma_handle->ocb_config_req); + return vos_status; +} + +static WLAN_PHY_MODE wma_ocb_freq_to_mode(uint32_t freq) +{ + if (vos_chan_to_band(vos_freq_to_chan(freq)) == VOS_BAND_2GHZ) + return MODE_11G; + else + return MODE_11A; +} + +/** + * wma_send_ocb_set_config() - send the OCB config to the FW + * @wma_handle: pointer to the WMA handle + * @config: the OCB configuration + * + * Return: 0 on success + */ +int wma_ocb_set_config(tp_wma_handle wma_handle, struct sir_ocb_config *config) +{ + int32_t ret; + wmi_ocb_set_config_cmd_fixed_param *cmd; + wmi_channel *chan; + wmi_ocb_channel *ocb_chan; + wmi_qos_parameter *qos_param; + wmi_dcc_ndl_chan *ndl_chan; + wmi_dcc_ndl_active_state_config *ndl_active_config; + wmi_ocb_schedule_element *sched_elem; + uint8_t *buf_ptr; + wmi_buf_t buf; + int32_t len; + int32_t i, j, active_state_count; + + /* + * Validate the dcc_ndl_chan_list_len and count the number of active + * states. Validate dcc_ndl_active_state_list_len. + */ + active_state_count = 0; + if (config->dcc_ndl_chan_list_len) { + if (!config->dcc_ndl_chan_list || + config->dcc_ndl_chan_list_len != + config->channel_count * sizeof(wmi_dcc_ndl_chan)) { + WMA_LOGE(FL("NDL channel is invalid. List len: %d"), + config->dcc_ndl_chan_list_len); + return -EINVAL; + } + + for (i = 0, ndl_chan = config->dcc_ndl_chan_list; + i < config->channel_count; ++i, ++ndl_chan) + active_state_count += + WMI_NDL_NUM_ACTIVE_STATE_GET(ndl_chan); + + if (active_state_count) { + if (!config->dcc_ndl_active_state_list || + config->dcc_ndl_active_state_list_len != + active_state_count * + sizeof(wmi_dcc_ndl_active_state_config)) { + WMA_LOGE(FL("NDL active state is invalid.")); + return -EINVAL; + } + } + } + + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE + config->channel_count * + sizeof(wmi_channel) + + WMI_TLV_HDR_SIZE + config->channel_count * + sizeof(wmi_ocb_channel) + + WMI_TLV_HDR_SIZE + config->channel_count * + sizeof(wmi_qos_parameter) * WLAN_MAX_AC + + WMI_TLV_HDR_SIZE + config->dcc_ndl_chan_list_len + + WMI_TLV_HDR_SIZE + active_state_count * + sizeof(wmi_dcc_ndl_active_state_config) + + WMI_TLV_HDR_SIZE + config->schedule_size * + sizeof(wmi_ocb_schedule_element); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = (uint8_t *)wmi_buf_data(buf); + cmd = (wmi_ocb_set_config_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_set_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_config_cmd_fixed_param)); + cmd->vdev_id = config->session_id; + cmd->channel_count = config->channel_count; + cmd->schedule_size = config->schedule_size; + cmd->flags = config->flags; + buf_ptr += sizeof(*cmd); + + /* Add the wmi_channel info */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + config->channel_count*sizeof(wmi_channel)); + buf_ptr += WMI_TLV_HDR_SIZE; + for (i = 0; i < config->channel_count; i++) { + chan = (wmi_channel *)buf_ptr; + WMITLV_SET_HDR(&chan->tlv_header, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + + chan->mhz = config->channels[i].chan_freq; + chan->band_center_freq1 = config->channels[i].chan_freq; + chan->band_center_freq2 = 0; + chan->info = 0; + + WMI_SET_CHANNEL_MODE(chan, wma_ocb_freq_to_mode(chan->mhz)); + WMI_SET_CHANNEL_MAX_POWER(chan, config->channels[i].max_pwr); + WMI_SET_CHANNEL_MIN_POWER(chan, config->channels[i].min_pwr); + WMI_SET_CHANNEL_MAX_TX_POWER(chan, config->channels[i].max_pwr); + WMI_SET_CHANNEL_REG_POWER(chan, config->channels[i].reg_pwr); + WMI_SET_CHANNEL_ANTENNA_MAX(chan, + config->channels[i].antenna_max); + + if (config->channels[i].bandwidth < 10) + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_QUARTER_RATE); + else if (config->channels[i].bandwidth < 20) + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_HALF_RATE); + buf_ptr += sizeof(*chan); + } + + /* Add the wmi_ocb_channel info */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + config->channel_count*sizeof(wmi_ocb_channel)); + buf_ptr += WMI_TLV_HDR_SIZE; + for (i = 0; i < config->channel_count; i++) { + ocb_chan = (wmi_ocb_channel *)buf_ptr; + WMITLV_SET_HDR(&ocb_chan->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_channel)); + ocb_chan->bandwidth = config->channels[i].bandwidth; + WMI_CHAR_ARRAY_TO_MAC_ADDR(config->channels[i].mac_address, + &ocb_chan->mac_address); + buf_ptr += sizeof(*ocb_chan); + } + + /* Add the wmi_qos_parameter info */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + config->channel_count * sizeof(wmi_qos_parameter)*WLAN_MAX_AC); + buf_ptr += WMI_TLV_HDR_SIZE; + /* WLAN_MAX_AC parameters for each channel */ + for (i = 0; i < config->channel_count; i++) { + for (j = 0; j < WLAN_MAX_AC; j++) { + qos_param = (wmi_qos_parameter *)buf_ptr; + WMITLV_SET_HDR(&qos_param->tlv_header, + WMITLV_TAG_STRUC_wmi_qos_parameter, + WMITLV_GET_STRUCT_TLVLEN(wmi_qos_parameter)); + qos_param->aifsn = + config->channels[i].qos_params[j].aifsn; + qos_param->cwmin = + config->channels[i].qos_params[j].cwmin; + qos_param->cwmax = + config->channels[i].qos_params[j].cwmax; + buf_ptr += sizeof(*qos_param); + } + } + + /* Add the wmi_dcc_ndl_chan (per channel) */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + config->dcc_ndl_chan_list_len); + buf_ptr += WMI_TLV_HDR_SIZE; + if (config->dcc_ndl_chan_list_len) { + ndl_chan = (wmi_dcc_ndl_chan *)buf_ptr; + vos_mem_copy(ndl_chan, config->dcc_ndl_chan_list, + config->dcc_ndl_chan_list_len); + for (i = 0; i < config->channel_count; i++) + WMITLV_SET_HDR(&(ndl_chan[i].tlv_header), + WMITLV_TAG_STRUC_wmi_dcc_ndl_chan, + WMITLV_GET_STRUCT_TLVLEN(wmi_dcc_ndl_chan)); + buf_ptr += config->dcc_ndl_chan_list_len; + } + + /* Add the wmi_dcc_ndl_active_state_config */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, active_state_count * + sizeof(wmi_dcc_ndl_active_state_config)); + buf_ptr += WMI_TLV_HDR_SIZE; + if (active_state_count) { + ndl_active_config = (wmi_dcc_ndl_active_state_config *)buf_ptr; + vos_mem_copy(ndl_active_config, + config->dcc_ndl_active_state_list, + active_state_count * sizeof(*ndl_active_config)); + for (i = 0; i < active_state_count; ++i) + WMITLV_SET_HDR(&(ndl_active_config[i].tlv_header), + WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_ndl_active_state_config)); + buf_ptr += active_state_count * + sizeof(*ndl_active_config); + } + + /* Add the wmi_ocb_schedule_element info */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + config->schedule_size * sizeof(wmi_ocb_schedule_element)); + buf_ptr += WMI_TLV_HDR_SIZE; + for (i = 0; i < config->schedule_size; i++) { + sched_elem = (wmi_ocb_schedule_element *)buf_ptr; + WMITLV_SET_HDR(&sched_elem->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_schedule_element, + WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_schedule_element)); + sched_elem->channel_freq = config->schedule[i].chan_freq; + sched_elem->total_duration = config->schedule[i].total_duration; + sched_elem->guard_interval = config->schedule[i].guard_interval; + buf_ptr += sizeof(*sched_elem); + } + + /* + * Save the configuration so that it can be used in + * wma_ocb_set_config_event_handler. + */ + if (wma_handle->ocb_config_req != config) { + if (wma_handle->ocb_config_req) + vos_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = copy_sir_ocb_config(config); + } + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_OCB_SET_CONFIG_CMDID); + if (ret != EOK) { + if (wma_handle->ocb_config_req) { + vos_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = 0; + } + + WMA_LOGE("Failed to set OCB config"); + wmi_buf_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_ocb_set_config_event_handler() - Response event for the set config cmd + * @handle: the WMA handle + * @event_buf: buffer with the event parameters + * @len: length of the buffer + * + * Return: 0 on success + */ +int wma_ocb_set_config_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + WMI_OCB_SET_CONFIG_RESP_EVENTID_param_tlvs *param_tlvs; + wmi_ocb_set_config_resp_event_fixed_param *fix_param; + param_tlvs = (WMI_OCB_SET_CONFIG_RESP_EVENTID_param_tlvs *)event_buf; + fix_param = param_tlvs->fixed_param; + return wma_ocb_set_config_resp(handle, fix_param->status); +}; + +/** + * wma_ocb_set_utc_time() - send the UTC time to the firmware + * @wma_handle: pointer to the WMA handle + * @utc: pointer to the UTC time struct + * + * Return: 0 on succes + */ +int wma_ocb_set_utc_time(tp_wma_handle wma_handle, struct sir_ocb_utc *utc) +{ + int32_t ret; + wmi_ocb_set_utc_time_cmd_fixed_param *cmd; + uint8_t *buf_ptr; + uint32_t len, i; + wmi_buf_t buf; + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = (uint8_t *)wmi_buf_data(buf); + cmd = (wmi_ocb_set_utc_time_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_set_utc_time_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_utc_time_cmd_fixed_param)); + cmd->vdev_id = utc->vdev_id; + + for (i = 0; i < SIZE_UTC_TIME; i++) + WMI_UTC_TIME_SET(cmd, i, utc->utc_time[i]); + + for (i = 0; i < SIZE_UTC_TIME_ERROR; i++) + WMI_TIME_ERROR_SET(cmd, i, utc->time_error[i]); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_OCB_SET_UTC_TIME_CMDID); + if (ret != EOK) { + WMA_LOGE(FL("Failed to set OCB UTC time")); + wmi_buf_free(buf); + return -EIO; + } + + return 0; +} + +/** + * wma_ocb_start_timing_advert() - start sending the timing advertisement + * frames on a channel + * @wma_handle: pointer to the WMA handle + * @timing_advert: pointer to the timing advertisement struct + * + * Return: 0 on succes + */ +int wma_ocb_start_timing_advert(tp_wma_handle wma_handle, + struct sir_ocb_timing_advert *timing_advert) +{ + int32_t ret; + wmi_ocb_start_timing_advert_cmd_fixed_param *cmd; + uint8_t *buf_ptr; + uint32_t len, len_template; + wmi_buf_t buf; + + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE; + + len_template = timing_advert->template_length; + /* Add padding to the template if needed */ + if (len_template % 4 != 0) + len_template += 4 - (len_template % 4); + len += len_template; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = (uint8_t *)wmi_buf_data(buf); + cmd = (wmi_ocb_start_timing_advert_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_start_timing_advert_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ocb_start_timing_advert_cmd_fixed_param)); + cmd->vdev_id = timing_advert->vdev_id; + cmd->repeat_rate = timing_advert->repeat_rate; + cmd->channel_freq = timing_advert->chan_freq; + cmd->timestamp_offset = timing_advert->timestamp_offset; + cmd->time_value_offset = timing_advert->time_value_offset; + cmd->timing_advert_template_length = timing_advert->template_length; + buf_ptr += sizeof(*cmd); + + /* Add the timing advert template */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + len_template); + vos_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, + (uint8_t *)timing_advert->template_value, + timing_advert->template_length); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_OCB_START_TIMING_ADVERT_CMDID); + if (ret != EOK) { + WMA_LOGE(FL("Failed to start OCB timing advert")); + wmi_buf_free(buf); + return -EIO; + } + + return 0; +} + +/** + * wma_ocb_stop_timing_advert() - stop sending the timing advertisement frames + * on a channel + * @wma_handle: pointer to the WMA handle + * @timing_advert: pointer to the timing advertisement struct + * + * Return: 0 on succes + */ +int wma_ocb_stop_timing_advert(tp_wma_handle wma_handle, + struct sir_ocb_timing_advert *timing_advert) +{ + int32_t ret; + wmi_ocb_stop_timing_advert_cmd_fixed_param *cmd; + uint8_t *buf_ptr; + uint32_t len; + wmi_buf_t buf; + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = (uint8_t *)wmi_buf_data(buf); + cmd = (wmi_ocb_stop_timing_advert_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_stop_timing_advert_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ocb_stop_timing_advert_cmd_fixed_param)); + cmd->vdev_id = timing_advert->vdev_id; + cmd->channel_freq = timing_advert->chan_freq; + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_OCB_STOP_TIMING_ADVERT_CMDID); + if (ret != EOK) { + WMA_LOGE(FL("Failed to stop OCB timing advert")); + wmi_buf_free(buf); + return -EIO; + } + + return 0; +} + +/** + * wma_ocb_get_tsf_timer() - stop sending the timing advertisement frames on a + * channel + * @wma_handle: pointer to the WMA handle + * @request: pointer to the request + * + * Return: 0 on succes + */ +int wma_ocb_get_tsf_timer(tp_wma_handle wma_handle, + struct sir_ocb_get_tsf_timer *request) +{ + VOS_STATUS ret; + wmi_ocb_get_tsf_timer_cmd_fixed_param *cmd; + uint8_t *buf_ptr; + wmi_buf_t buf; + int32_t len; + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + buf_ptr = (uint8_t *)wmi_buf_data(buf); + + cmd = (wmi_ocb_get_tsf_timer_cmd_fixed_param *)buf_ptr; + vos_mem_zero(cmd, len); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ocb_get_tsf_timer_cmd_fixed_param)); + cmd->vdev_id = request->vdev_id; + + /* Send the WMI command */ + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_OCB_GET_TSF_TIMER_CMDID); + /* If there is an error, set the completion event */ + if (ret != EOK) { + WMA_LOGE(FL("Failed to send WMI message: %d"), ret); + wmi_buf_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_ocb_get_tsf_timer_resp_event_handler() - Event for the get TSF timer cmd + * @handle: the WMA handle + * @event_buf: buffer with the event parameters + * @len: length of the buffer + * + * Return: 0 on success + */ +int wma_ocb_get_tsf_timer_resp_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + VOS_STATUS vos_status; + struct sir_ocb_get_tsf_timer_response *response; + WMI_OCB_GET_TSF_TIMER_RESP_EVENTID_param_tlvs *param_tlvs; + wmi_ocb_get_tsf_timer_resp_event_fixed_param *fix_param; + vos_msg_t msg = {0}; + + param_tlvs = (WMI_OCB_GET_TSF_TIMER_RESP_EVENTID_param_tlvs *)event_buf; + fix_param = param_tlvs->fixed_param; + + /* Allocate and populate the response */ + response = vos_mem_malloc(sizeof(*response)); + if (response == NULL) + return -ENOMEM; + response->vdev_id = fix_param->vdev_id; + response->timer_high = fix_param->tsf_timer_high; + response->timer_low = fix_param->tsf_timer_low; + + msg.type = eWNI_SME_OCB_GET_TSF_TIMER_RSP; + msg.bodyptr = response; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + vos_mem_free(response); + return -EINVAL; + } + + return 0; +} + +/** + * wma_dcc_get_stats() - get the DCC channel stats + * @wma_handle: pointer to the WMA handle + * @get_stats_param: pointer to the dcc stats + * + * Return: 0 on succes + */ +int wma_dcc_get_stats(tp_wma_handle wma_handle, + struct sir_dcc_get_stats *get_stats_param) +{ + int32_t ret; + wmi_dcc_get_stats_cmd_fixed_param *cmd; + wmi_dcc_channel_stats_request *channel_stats_array; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t len; + uint32_t i; + + /* Validate the input */ + if (get_stats_param->request_array_len != + get_stats_param->channel_count * sizeof(*channel_stats_array)) { + WMA_LOGE(FL("Invalid parameter")); + return -EINVAL; + } + + /* Allocate memory for the WMI command */ + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + + get_stats_param->request_array_len; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return VOS_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + + /* Populate the WMI command */ + cmd = (wmi_dcc_get_stats_cmd_fixed_param *)buf_ptr; + buf_ptr += sizeof(*cmd); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_dcc_get_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_get_stats_cmd_fixed_param)); + cmd->vdev_id = get_stats_param->vdev_id; + cmd->num_channels = get_stats_param->channel_count; + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + get_stats_param->request_array_len); + buf_ptr += WMI_TLV_HDR_SIZE; + + channel_stats_array = (wmi_dcc_channel_stats_request *)buf_ptr; + vos_mem_copy(channel_stats_array, get_stats_param->request_array, + get_stats_param->request_array_len); + for (i = 0; i < cmd->num_channels; i++) + WMITLV_SET_HDR(&channel_stats_array[i].tlv_header, + WMITLV_TAG_STRUC_wmi_dcc_channel_stats_request, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_channel_stats_request)); + + /* Send the WMI command */ + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_DCC_GET_STATS_CMDID); + + if (ret != EOK) { + WMA_LOGE(FL("Failed to send WMI message: %d"), ret); + wmi_buf_free(buf); + return -EIO; + } + + return 0; +} + +/** + * wma_dcc_get_stats_resp_event_handler() - Response event for the get stats cmd + * @handle: the WMA handle + * @event_buf: buffer with the event parameters + * @len: length of the buffer + * + * Return: 0 on success + */ +int wma_dcc_get_stats_resp_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + VOS_STATUS vos_status; + struct sir_dcc_get_stats_response *response; + WMI_DCC_GET_STATS_RESP_EVENTID_param_tlvs *param_tlvs; + wmi_dcc_get_stats_resp_event_fixed_param *fix_param; + vos_msg_t msg = {0}; + + param_tlvs = (WMI_DCC_GET_STATS_RESP_EVENTID_param_tlvs *)event_buf; + fix_param = param_tlvs->fixed_param; + + /* Allocate and populate the response */ + response = vos_mem_malloc(sizeof(*response) + fix_param->num_channels * + sizeof(wmi_dcc_ndl_stats_per_channel)); + if (response == NULL) + return -ENOMEM; + + response->vdev_id = fix_param->vdev_id; + response->num_channels = fix_param->num_channels; + response->channel_stats_array_len = + fix_param->num_channels * sizeof(wmi_dcc_ndl_stats_per_channel); + response->channel_stats_array = ((void *)response) + sizeof(*response); + vos_mem_copy(response->channel_stats_array, + param_tlvs->stats_per_channel_list, + response->channel_stats_array_len); + + msg.type = eWNI_SME_DCC_GET_STATS_RSP; + msg.bodyptr = response; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + vos_mem_free(response); + return -EINVAL; + } + + return 0; +} + +/** + * wma_dcc_clear_stats() - command to clear the DCC stats + * @wma_handle: pointer to the WMA handle + * @clear_stats_param: parameters to the command + * + * Return: 0 on succes + */ +int wma_dcc_clear_stats(tp_wma_handle wma_handle, + struct sir_dcc_clear_stats *clear_stats_param) +{ + int32_t ret; + wmi_dcc_clear_stats_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t len; + + /* Allocate memory for the WMI command */ + len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + + /* Populate the WMI command */ + cmd = (wmi_dcc_clear_stats_cmd_fixed_param *)buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_dcc_clear_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_clear_stats_cmd_fixed_param)); + cmd->vdev_id = clear_stats_param->vdev_id; + cmd->dcc_stats_bitmap = clear_stats_param->dcc_stats_bitmap; + + /* Send the WMI command */ + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_DCC_CLEAR_STATS_CMDID); + if (ret != EOK) { + WMA_LOGE(FL("Failed to send the WMI command")); + wmi_buf_free(buf); + return -EIO; + } + + return 0; +} + +/** + * wma_dcc_update_ndl() - command to update the NDL data + * @wma_handle: pointer to the WMA handle + * @update_ndl_param: pointer to the request parameters + * + * Return: 0 on success + */ +int wma_dcc_update_ndl(tp_wma_handle wma_handle, + struct sir_dcc_update_ndl *update_ndl_param) +{ + VOS_STATUS vos_status; + wmi_dcc_update_ndl_cmd_fixed_param *cmd; + wmi_dcc_ndl_chan *ndl_chan_array; + wmi_dcc_ndl_active_state_config *ndl_active_state_array; + uint32_t active_state_count; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t len; + uint32_t i; + + /* validate the input */ + if (update_ndl_param->dcc_ndl_chan_list_len != + update_ndl_param->channel_count * sizeof(*ndl_chan_array)) { + WMA_LOGE(FL("Invalid parameter")); + return VOS_STATUS_E_INVAL; + } + active_state_count = 0; + ndl_chan_array = update_ndl_param->dcc_ndl_chan_list; + for (i = 0; i < update_ndl_param->channel_count; i++) + active_state_count += + WMI_NDL_NUM_ACTIVE_STATE_GET(&ndl_chan_array[i]); + if (update_ndl_param->dcc_ndl_active_state_list_len != + active_state_count * sizeof(*ndl_active_state_array)) { + WMA_LOGE(FL("Invalid parameter")); + return VOS_STATUS_E_INVAL; + } + + /* Allocate memory for the WMI command */ + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE + update_ndl_param->dcc_ndl_chan_list_len + + WMI_TLV_HDR_SIZE + + update_ndl_param->dcc_ndl_active_state_list_len; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return -ENOMEM; + } + + buf_ptr = wmi_buf_data(buf); + vos_mem_zero(buf_ptr, len); + + /* Populate the WMI command */ + cmd = (wmi_dcc_update_ndl_cmd_fixed_param *)buf_ptr; + buf_ptr += sizeof(*cmd); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_dcc_update_ndl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_update_ndl_cmd_fixed_param)); + cmd->vdev_id = update_ndl_param->vdev_id; + cmd->num_channel = update_ndl_param->channel_count; + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + update_ndl_param->dcc_ndl_chan_list_len); + buf_ptr += WMI_TLV_HDR_SIZE; + + ndl_chan_array = (wmi_dcc_ndl_chan *)buf_ptr; + vos_mem_copy(ndl_chan_array, update_ndl_param->dcc_ndl_chan_list, + update_ndl_param->dcc_ndl_chan_list_len); + for (i = 0; i < cmd->num_channel; i++) + WMITLV_SET_HDR(&ndl_chan_array[i].tlv_header, + WMITLV_TAG_STRUC_wmi_dcc_ndl_chan, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_ndl_chan)); + buf_ptr += update_ndl_param->dcc_ndl_chan_list_len; + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + update_ndl_param->dcc_ndl_active_state_list_len); + buf_ptr += WMI_TLV_HDR_SIZE; + + ndl_active_state_array = (wmi_dcc_ndl_active_state_config *) buf_ptr; + vos_mem_copy(ndl_active_state_array, + update_ndl_param->dcc_ndl_active_state_list, + update_ndl_param->dcc_ndl_active_state_list_len); + for (i = 0; i < active_state_count; i++) { + WMITLV_SET_HDR(&ndl_active_state_array[i].tlv_header, + WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config, + WMITLV_GET_STRUCT_TLVLEN( + wmi_dcc_ndl_active_state_config)); + } + buf_ptr += update_ndl_param->dcc_ndl_active_state_list_len; + + /* Send the WMI command */ + vos_status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_DCC_UPDATE_NDL_CMDID); + /* If there is an error, set the completion event */ + if (vos_status) { + WMA_LOGE(FL("Failed to send WMI message: %d"), vos_status); + wmi_buf_free(buf); + return -EIO; + } + + return 0; +} + +/** + * wma_dcc_update_ndl_resp_event_handler() - Response event for the update NDL + * command + * @handle: the WMA handle + * @event_buf: buffer with the event parameters + * @len: length of the buffer + * + * Return: 0 on success + */ +int wma_dcc_update_ndl_resp_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + VOS_STATUS vos_status; + struct sir_dcc_update_ndl_response *resp; + WMI_DCC_UPDATE_NDL_RESP_EVENTID_param_tlvs *param_tlvs; + wmi_dcc_update_ndl_resp_event_fixed_param *fix_param; + vos_msg_t msg = {0}; + + param_tlvs = (WMI_DCC_UPDATE_NDL_RESP_EVENTID_param_tlvs *)event_buf; + fix_param = param_tlvs->fixed_param; + /* Allocate and populate the response */ + resp = vos_mem_malloc(sizeof(*resp)); + if (!resp) { + WMA_LOGE(FL("Error allocating memory for the response.")); + return -ENOMEM; + } + resp->vdev_id = fix_param->vdev_id; + resp->status = fix_param->status; + + msg.type = eWNI_SME_DCC_UPDATE_NDL_RSP; + msg.bodyptr = resp; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + vos_mem_free(resp); + return -EINVAL; + } + + return 0; +} + +/** + * wma_dcc_stats_event_handler() - Response event for the get stats cmd + * @handle: the WMA handle + * @event_buf: buffer with the event parameters + * @len: length of the buffer + * + * Return: 0 on success + */ +int wma_dcc_stats_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + VOS_STATUS vos_status; + struct sir_dcc_get_stats_response *response; + WMI_DCC_STATS_EVENTID_param_tlvs *param_tlvs; + wmi_dcc_stats_event_fixed_param *fix_param; + vos_msg_t msg = {0}; + + param_tlvs = (WMI_DCC_STATS_EVENTID_param_tlvs *)event_buf; + fix_param = param_tlvs->fixed_param; + /* Allocate and populate the response */ + response = vos_mem_malloc(sizeof(*response) + + fix_param->num_channels * sizeof(wmi_dcc_ndl_stats_per_channel)); + if (response == NULL) + return -ENOMEM; + response->vdev_id = fix_param->vdev_id; + response->num_channels = fix_param->num_channels; + response->channel_stats_array_len = + fix_param->num_channels * sizeof(wmi_dcc_ndl_stats_per_channel); + response->channel_stats_array = ((void *)response) + sizeof(*response); + vos_mem_copy(response->channel_stats_array, + param_tlvs->stats_per_channel_list, + response->channel_stats_array_len); + + msg.type = eWNI_SME_DCC_STATS_EVENT; + msg.bodyptr = response; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_SME, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + vos_mem_free(response); + return -EINVAL; + } + + return 0; +} + +/** + * wma_ocb_register_event_handlers() - register handlers for the OCB WMI + * events + * @wma_handle: pointer to the WMA handle + * + * Return: 0 on success, non-zero on failure + */ +int wma_ocb_register_event_handlers(tp_wma_handle wma_handle) +{ + int status; + + if (!wma_handle) { + WMA_LOGE(FL("wma_handle is NULL")); + return -EINVAL; + } + + /* Initialize the members in WMA used by wma_ocb */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OCB_SET_CONFIG_RESP_EVENTID, + wma_ocb_set_config_event_handler); + if (status) + return status; + + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_OCB_GET_TSF_TIMER_RESP_EVENTID, + wma_ocb_get_tsf_timer_resp_event_handler); + if (status) + return status; + + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_DCC_GET_STATS_RESP_EVENTID, + wma_dcc_get_stats_resp_event_handler); + if (status) + return status; + + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_DCC_UPDATE_NDL_RESP_EVENTID, + wma_dcc_update_ndl_resp_event_handler); + if (status) + return status; + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_DCC_STATS_EVENTID, + wma_dcc_stats_event_handler); + if (status) + return status; + + return VOS_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.h new file mode 100644 index 000000000000..dec331cb2f31 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.h @@ -0,0 +1,67 @@ +/*copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WMA_OCB_H +#define __WMA_OCB_H + +#include "wma.h" +#include "sirApi.h" + +int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status); + +int wma_ocb_set_config_req(tp_wma_handle handle, + struct sir_ocb_config *config_req); + +int wma_ocb_set_config_event_handler(void *handle, uint8_t *event_buf, + uint32_t len); + +int wma_ocb_start_resp_ind_cont(tp_wma_handle wma_handle); + +int wma_ocb_set_config(tp_wma_handle wma_handle, struct sir_ocb_config *config); + +int wma_ocb_set_utc_time(tp_wma_handle wma_handle, struct sir_ocb_utc *utc); + +int wma_ocb_start_timing_advert(tp_wma_handle wma_handle, + struct sir_ocb_timing_advert *timing_advert); + +int wma_ocb_stop_timing_advert(tp_wma_handle wma_handle, + struct sir_ocb_timing_advert *timing_advert); + +int wma_ocb_get_tsf_timer(tp_wma_handle wma_handle, + struct sir_ocb_get_tsf_timer *request); + +int wma_dcc_get_stats(tp_wma_handle wma_handle, + struct sir_dcc_get_stats *get_stats_param); + +int wma_dcc_clear_stats(tp_wma_handle wma_handle, + struct sir_dcc_clear_stats *clear_stats_param); + +int wma_dcc_update_ndl(tp_wma_handle wma_handle, + struct sir_dcc_update_ndl *update_ndl_param); + +int wma_ocb_register_event_handlers(tp_wma_handle wma_handle); + +#endif /* __WMA_OCB_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_stub.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_stub.h new file mode 100644 index 000000000000..5a9a68fc1620 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_stub.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WMA_STUB +#define WMA_STUB + +#include "vos_api.h" +#include "vos_packet.h" +#include "vos_types.h" + +static inline VOS_STATUS wma_shutdown(v_PVOID_t pVosContext, v_BOOL_t closeTransport) +{ + return VOS_STATUS_SUCCESS; +} + +static inline void WMA_TimerTrafficStatsInd(void *pWMA) { + return; +} + +static inline VOS_STATUS WMA_GetWcnssHardwareVersion(v_PVOID_t pvosGCtx, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize) +{ + return VOS_STATUS_SUCCESS; +} + +static inline VOS_STATUS WMA_GetWcnssWlanCompiledVersion(v_PVOID_t pvosGCtx, + tSirVersionType *pVersion) +{ + return VOS_STATUS_SUCCESS; +} + +static inline tANI_U8 WMA_getFwWlanFeatCaps(tANI_U8 featEnumValue) +{ + return featEnumValue; +} + +static inline void WMA_disableCapablityFeature(tANI_U8 feature_index) { + return; +} + +static inline VOS_STATUS WMA_HALDumpCmdReq(tpAniSirGlobal pMac, tANI_U32 cmd, + tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, + tANI_U32 arg4, tANI_U8 *pBuffer) { + return VOS_STATUS_SUCCESS; +} + +static inline void WMA_TrafficStatsTimerActivate(v_BOOL_t activate) +{ + return; +} + +static inline VOS_STATUS WMA_GetWcnssWlanReportedVersion(v_PVOID_t pvosGCtx, + tSirVersionType *pVersion) +{ + return VOS_STATUS_SUCCESS; +} + +static inline void WMA_featureCapsExchange(v_PVOID_t pVosContext) { + return; +} + +static inline void WMA_UpdateRssiBmps(v_PVOID_t pvosGCtx, + v_U8_t staId, v_S7_t rssi) +{ +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_helper.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_helper.c new file mode 100644 index 000000000000..1edd553fbbad --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_helper.c @@ -0,0 +1,998 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* wmi_tlv_platform.c file will be different for different components like Pronto firmware, Pronto windows host driver, + Pronto LA host driver because their memory management functions are different */ +#include "wmi_tlv_platform.c" +#include "wmi_tlv_defs.h" +#include "wmi_version.h" + +#define WMITLV_GET_ATTRIB_NUM_TLVS 0xFFFFFFFF + +#define WMITLV_GET_CMDID(val) (val & 0x00FFFFFF) +#define WMITLV_GET_NUM_TLVS(val) ((val >> 24) & 0xFF) + +#define WMITLV_GET_TAGID(val) (val & 0x00000FFF) +#define WMITLV_GET_TAG_STRUCT_SIZE(val) ((val >> 12) & 0x000001FF) +#define WMITLV_GET_TAG_ARRAY_SIZE(val) ((val >> 21) & 0x000001FF) +#define WMITLV_GET_TAG_VARIED(val) ((val >> 30) & 0x00000001) + +#define WMITLV_SET_ATTRB0(id) ((WMITLV_GET_TAG_NUM_TLV_ATTRIB(id) << 24) | (id & 0x00FFFFFF)) +#define WMITLV_SET_ATTRB1(tagID, tagStructSize, tagArraySize, tagVaried) (((tagVaried&0x1)<<30) | ((tagArraySize&0x1FF)<<21) | ((tagStructSize&0x1FF)<<12) | (tagID&0xFFF)) + +#define WMITLV_OP_SET_TLV_ATTRIB_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + WMITLV_SET_ATTRB1(elem_tlv_tag, sizeof(elem_struc_type), arr_size, var_len), + +#define WMITLV_GET_CMD_EVT_ATTRB_LIST(id) \ + WMITLV_SET_ATTRB0(id), \ + WMITLV_TABLE(id,SET_TLV_ATTRIB,NULL,0) + +A_UINT32 cmdAttrList[] = + { + WMITLV_ALL_CMD_LIST(WMITLV_GET_CMD_EVT_ATTRB_LIST) + }; + +A_UINT32 evtAttrList[] = + { + WMITLV_ALL_EVT_LIST(WMITLV_GET_CMD_EVT_ATTRB_LIST) + }; + + +#ifdef NO_DYNAMIC_MEM_ALLOC +static wmitlv_cmd_param_info *g_WmiStaticCmdParamInfoBuf = NULL; +A_UINT32 g_WmiStaticMaxCmdParamTlvs=0; +#endif + +/* TLV helper routines */ + +/* + * WMI TLV Helper function to set the static cmd_param_tlv structure and number of TLVs that can be + * accomodated in the structure. This function should be used when dynamic memory allocation is not + * supported. + * + * When dynamic memory allocation is not supported by any component then NO_DYNAMIC_MEMALLOC + * macro has to be defined in respective tlv_platform.c file. And respective component has to allocate + * cmd_param_tlv structure buffer to accomodate whatever number of TLV's. Both the buffer address + * and number of TLV's that can be accomodated in the buffer should be sent as arguments to this function. + * + * Return None + */ +void +wmitlv_set_static_param_tlv_buf(void *param_tlv_buf, A_UINT32 max_tlvs_accomodated) +{ +#ifdef NO_DYNAMIC_MEM_ALLOC + g_WmiStaticCmdParamInfoBuf = param_tlv_buf; + g_WmiStaticMaxCmdParamTlvs = max_tlvs_accomodated; +#endif +} + +/* + * WMI TLV Helper functions to find the attributes of the Command/Event TLVs. + * Return 0 if success. Return >=1 if failure. + */ +A_UINT32 wmitlv_get_attributes(A_UINT32 is_cmd_id, A_UINT32 cmd_event_id, A_UINT32 curr_tlv_order, wmitlv_attributes_struc* tlv_attr_ptr) +{ + A_UINT32 i, base_index, num_tlvs, num_entries; + A_UINT32 *pAttrArrayList; + + if (is_cmd_id) + { + pAttrArrayList = &cmdAttrList[0]; + num_entries = (sizeof(cmdAttrList)/sizeof(A_UINT32)); + } + else + { + pAttrArrayList = &evtAttrList[0]; + num_entries = (sizeof(evtAttrList)/sizeof(A_UINT32)); + } + + for (i = 0; i < num_entries; i++) + { + num_tlvs = WMITLV_GET_NUM_TLVS(pAttrArrayList[i]); + if (WMITLV_GET_CMDID(cmd_event_id) == WMITLV_GET_CMDID(pAttrArrayList[i])) + { + tlv_attr_ptr->cmd_num_tlv = num_tlvs; + /* Return success from here when only number of TLVS for this command/event is required */ + if (curr_tlv_order == WMITLV_GET_ATTRIB_NUM_TLVS) + { + wmi_tlv_print_verbose("%s: WMI TLV attribute definitions for %s:0x%x found; num_of_tlvs:%d\n", + __func__, (is_cmd_id ? "Cmd" : "Evt"), cmd_event_id, num_tlvs); + return 0; + } + + /* Return failure if tlv_order is more than the expected number of TLVs */ + if (curr_tlv_order >= num_tlvs) + { + wmi_tlv_print_error("%s: ERROR: TLV order %d greater than num_of_tlvs:%d for %s:0x%x\n", + __func__, curr_tlv_order, num_tlvs, (is_cmd_id ? "Cmd" : "Evt"), cmd_event_id); + return 1; + } + + base_index = i + 1; // index to first TLV attributes + wmi_tlv_print_verbose("%s: WMI TLV attributes for %s:0x%x tlv[%d]:0x%x\n", + __func__, (is_cmd_id ? "Cmd" : "Evt"), cmd_event_id, curr_tlv_order, pAttrArrayList[(base_index+curr_tlv_order)]); + tlv_attr_ptr->tag_order = curr_tlv_order; + tlv_attr_ptr->tag_id = WMITLV_GET_TAGID(pAttrArrayList[(base_index+curr_tlv_order)]); + tlv_attr_ptr->tag_struct_size = WMITLV_GET_TAG_STRUCT_SIZE(pAttrArrayList[(base_index+curr_tlv_order)]); + tlv_attr_ptr->tag_varied_size = WMITLV_GET_TAG_VARIED(pAttrArrayList[(base_index+curr_tlv_order)]); + tlv_attr_ptr->tag_array_size = WMITLV_GET_TAG_ARRAY_SIZE(pAttrArrayList[(base_index+curr_tlv_order)]); + return 0; + } + i += num_tlvs; + } + + wmi_tlv_print_error("%s: ERROR: Didn't found WMI TLV attribute definitions for %s:0x%x\n", + __func__, (is_cmd_id ? "Cmd" : "Evt"), cmd_event_id); + return 1; +} + +/* + * Helper Function to vaidate the prepared TLV's for an WMI event/command to be sent + * Return 0 if success. + * <0 if failure. + */ +static int +wmitlv_check_tlv_params( + void *os_handle, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 is_cmd_id, A_UINT32 wmi_cmd_event_id) +{ + wmitlv_attributes_struc attr_struct_ptr; + A_UINT32 buf_idx = 0; + A_UINT32 tlv_index = 0; + A_UINT8 *buf_ptr = (unsigned char *)param_struc_ptr; + A_UINT32 expected_num_tlvs, expected_tlv_len; + + /* Get the number of TLVs for this command/event */ + if (wmitlv_get_attributes(is_cmd_id, wmi_cmd_event_id, WMITLV_GET_ATTRIB_NUM_TLVS, &attr_struct_ptr) != 0) + { + wmi_tlv_print_error("%s: ERROR: Couldn't get expected number of TLVs for Cmd=%d\n", + __func__, wmi_cmd_event_id); + goto Error_wmitlv_check_tlv_params; + } + + /* NOTE: the returned number of TLVs is in "attr_struct_ptr.cmd_num_tlv" */ + + expected_num_tlvs = attr_struct_ptr.cmd_num_tlv; + + while ((buf_idx + WMI_TLV_HDR_SIZE) <= param_buf_len) + { + A_UINT32 curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr)); + A_UINT32 curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); + + if ((buf_idx + WMI_TLV_HDR_SIZE + curr_tlv_len) > param_buf_len) + { + wmi_tlv_print_error("%s: ERROR: Invalid TLV length for Cmd=%d Tag_order=%d buf_idx=%d Tag:%d Len:%d TotalLen:%d\n", + __func__, wmi_cmd_event_id, tlv_index, buf_idx, curr_tlv_tag, curr_tlv_len, param_buf_len); + goto Error_wmitlv_check_tlv_params; + } + + + /* Get the attributes of the TLV with the given order in "tlv_index" */ + wmi_tlv_OS_MEMZERO(&attr_struct_ptr,sizeof(wmitlv_attributes_struc)); + if (wmitlv_get_attributes(is_cmd_id, wmi_cmd_event_id, tlv_index, &attr_struct_ptr) != 0) + { + wmi_tlv_print_error("%s: ERROR: No TLV attributes found for Cmd=%d Tag_order=%d\n", + __func__, wmi_cmd_event_id, tlv_index); + goto Error_wmitlv_check_tlv_params; + } + + /* Found the TLV that we wanted */ + wmi_tlv_print_verbose("%s: [tlv %d]: tag=%d, len=%d\n", __func__, tlv_index, curr_tlv_tag, curr_tlv_len); + + /* Validating Tag ID order */ + if (curr_tlv_tag != attr_struct_ptr.tag_id) { + wmi_tlv_print_error("%s: ERROR: TLV has wrong tag in order for Cmd=0x%x. Given=%d, Expected=%d.\n", + __func__, wmi_cmd_event_id,curr_tlv_tag, attr_struct_ptr.tag_id); + goto Error_wmitlv_check_tlv_params; + } + + /* Validate Tag length */ + /* Array TLVs length checking needs special handling */ + if ((curr_tlv_tag >= WMITLV_TAG_FIRST_ARRAY_ENUM) && (curr_tlv_tag <= WMITLV_TAG_LAST_ARRAY_ENUM)) + { + if (attr_struct_ptr.tag_varied_size == WMITLV_SIZE_FIX) + { + /* Array size can't be invalid for fixed size Array TLV */ + if (WMITLV_ARR_SIZE_INVALID == attr_struct_ptr.tag_array_size){ + wmi_tlv_print_error("%s: ERROR: array_size can't be invalid for Array TLV Cmd=0x%x Tag=%d\n", + __func__, wmi_cmd_event_id, curr_tlv_tag); + goto Error_wmitlv_check_tlv_params; + } + + expected_tlv_len = attr_struct_ptr.tag_array_size * attr_struct_ptr.tag_struct_size; + /* Paddding is only required for Byte array Tlvs all other array tlv's should be aligned to 4 bytes during their definition */ + if (WMITLV_TAG_ARRAY_BYTE == attr_struct_ptr.tag_id) + { + expected_tlv_len = roundup(expected_tlv_len, sizeof(A_UINT32)); + } + + if (curr_tlv_len != expected_tlv_len){ + wmi_tlv_print_error("%s: ERROR: TLV has wrong length for Cmd=0x%x. Tag_order=%d Tag=%d, Given_Len:%d Expected_Len=%d.\n", + __func__, wmi_cmd_event_id, tlv_index, curr_tlv_tag, curr_tlv_len, expected_tlv_len); + goto Error_wmitlv_check_tlv_params; + } + } + else + { + /* Array size should be invalid for variable size Array TLV */ + if (WMITLV_ARR_SIZE_INVALID != attr_struct_ptr.tag_array_size){ + wmi_tlv_print_error("%s: ERROR: array_size should be invalid for Array TLV Cmd=0x%x Tag=%d\n", + __func__, wmi_cmd_event_id, curr_tlv_tag); + goto Error_wmitlv_check_tlv_params; + } + + /* Incase of variable length TLV's, there is no expectation on the length field so do whatever checking + you can depending on the TLV tag if TLV length is non-zero */ + if (curr_tlv_len != 0) + { + /* Verify TLV length is aligned to the size of structure */ + if ((curr_tlv_len%attr_struct_ptr.tag_struct_size)!=0) + { + wmi_tlv_print_error("%s: ERROR: TLV length %d for Cmd=0x%x is not aligned to size of structure(%d bytes)\n", + __func__, curr_tlv_len, wmi_cmd_event_id, attr_struct_ptr.tag_struct_size); + goto Error_wmitlv_check_tlv_params; + } + + if (curr_tlv_tag == WMITLV_TAG_ARRAY_STRUC) + { + A_UINT8 *tlv_buf_ptr = NULL; + A_UINT32 in_tlv_len; + A_UINT32 idx; + A_UINT32 num_of_elems; + + /* Verify length of inner TLVs */ + + num_of_elems = curr_tlv_len/attr_struct_ptr.tag_struct_size; + /* Set tlv_buf_ptr to the first inner TLV address */ + tlv_buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE; + for(idx=0; idx g_WmiStaticMaxCmdParamTlvs) + { + /* Error: Expecting more TLVs that accomodated for static structure */ + wmi_tlv_print_error("%s: Error: Expecting more TLVs that accomodated for static structure. Expected:%d Accomodated:%d\n", + __func__, attr_struct_ptr.cmd_num_tlv, g_WmiStaticMaxCmdParamTlvs); + return -1; + } +#endif + if (*wmi_cmd_struct_ptr == NULL) { + /* Error: unable to alloc memory */ + wmi_tlv_print_error("%s: Error: unable to alloc memory (size=%d) for TLV\n", + __func__, len_wmi_cmd_struct_buf); + return -1; + } + + + cmd_param_tlvs_ptr = (wmitlv_cmd_param_info *)*wmi_cmd_struct_ptr; + wmi_tlv_OS_MEMZERO(cmd_param_tlvs_ptr, len_wmi_cmd_struct_buf); + remaining_expected_tlvs = attr_struct_ptr.cmd_num_tlv; + + while (((buf_idx + WMI_TLV_HDR_SIZE) <= param_buf_len)&&(remaining_expected_tlvs)) + { + A_UINT32 curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr)); + A_UINT32 curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); + int num_padding_bytes = 0; + + /* Get the attributes of the TLV with the given order in "tlv_index" */ + wmi_tlv_OS_MEMZERO(&attr_struct_ptr,sizeof(wmitlv_attributes_struc)); + if (wmitlv_get_attributes(is_cmd_id, wmi_cmd_event_id, tlv_index, &attr_struct_ptr) != 0) + { + wmi_tlv_print_error("%s: ERROR: No TLV attributes found for Cmd=%d Tag_order=%d\n", + __func__, wmi_cmd_event_id, tlv_index); + goto Error_wmitlv_check_and_pad_tlvs; + } + + /* Found the TLV that we wanted */ + wmi_tlv_print_verbose("%s: [tlv %d]: tag=%d, len=%d\n", __func__, tlv_index, curr_tlv_tag, curr_tlv_len); + + /* Validating Tag order */ + if (curr_tlv_tag != attr_struct_ptr.tag_id) { + wmi_tlv_print_error("%s: ERROR: TLV has wrong tag in order for Cmd=0x%x. Given=%d, Expected=%d.\n", + __func__, wmi_cmd_event_id,curr_tlv_tag, attr_struct_ptr.tag_id); + goto Error_wmitlv_check_and_pad_tlvs; + } + + if ((curr_tlv_tag >= WMITLV_TAG_FIRST_ARRAY_ENUM) && (curr_tlv_tag <= WMITLV_TAG_LAST_ARRAY_ENUM)) + { + /* Current Tag is an array of some kind. */ + /* Skip the TLV header of this array */ + buf_ptr += WMI_TLV_HDR_SIZE; + buf_idx += WMI_TLV_HDR_SIZE; + } + else + { + /* Non-array TLV. */ + curr_tlv_len += WMI_TLV_HDR_SIZE; + } + + if (attr_struct_ptr.tag_varied_size == WMITLV_SIZE_FIX) + { + /* This TLV is fixed length */ + if (WMITLV_ARR_SIZE_INVALID == attr_struct_ptr.tag_array_size) + { + tlv_size_diff = curr_tlv_len - attr_struct_ptr.tag_struct_size; + num_of_elems = (curr_tlv_len>WMI_TLV_HDR_SIZE)?1:0; + } + else + { + tlv_size_diff = curr_tlv_len - (attr_struct_ptr.tag_struct_size*attr_struct_ptr.tag_array_size); + num_of_elems = attr_struct_ptr.tag_array_size; + } + } + else + { + /* This TLV has a variable number of elements */ + if (WMITLV_TAG_ARRAY_STRUC == attr_struct_ptr.tag_id) + { + A_UINT32 in_tlv_len = 0; + + if (curr_tlv_len != 0) + { + in_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)); + in_tlv_len += WMI_TLV_HDR_SIZE; + tlv_size_diff = in_tlv_len - attr_struct_ptr.tag_struct_size; + num_of_elems = curr_tlv_len/in_tlv_len; + wmi_tlv_print_verbose("%s: WARN: TLV array of structures in_tlv_len=%d struct_size:%d diff:%d num_of_elems=%d \n", + __func__, in_tlv_len, attr_struct_ptr.tag_struct_size, tlv_size_diff, num_of_elems); + } + else + { + tlv_size_diff = 0; + num_of_elems = 0; + } + } + else if ((WMITLV_TAG_ARRAY_UINT32 == attr_struct_ptr.tag_id) || + (WMITLV_TAG_ARRAY_BYTE == attr_struct_ptr.tag_id) || + (WMITLV_TAG_ARRAY_FIXED_STRUC == attr_struct_ptr.tag_id)) + { + tlv_size_diff = 0; + num_of_elems = curr_tlv_len/attr_struct_ptr.tag_struct_size; + } + else + { + wmi_tlv_print_error("%s ERROR Need to handle this tag ID for variable length %d\n",__func__,attr_struct_ptr.tag_id); + goto Error_wmitlv_check_and_pad_tlvs; + } + } + + if ((WMITLV_TAG_ARRAY_STRUC == attr_struct_ptr.tag_id) && + (tlv_size_diff!=0)) + { + void *new_tlv_buf = NULL; + A_UINT8 *tlv_buf_ptr = NULL; + A_UINT32 in_tlv_len; + A_UINT32 i; + + if (attr_struct_ptr.tag_varied_size == WMITLV_SIZE_FIX) + { + /* This is not allowed. The tag WMITLV_TAG_ARRAY_STRUC can only be used with variable-length structure array + should not have a fixed number of elements (contradicting). Use WMITLV_TAG_ARRAY_FIXED_STRUC tag for + fixed size structure array(where structure never change without breaking compatibility) */ + wmi_tlv_print_error("%s: ERROR: TLV (tag=%d) should be variable-length and not fixed length\n", + __func__, curr_tlv_tag); + goto Error_wmitlv_check_and_pad_tlvs; + } + + /* Warning: Needs to allocate a larger structure and pad with zeros */ + wmi_tlv_print_error("%s: WARN: TLV array of structures needs padding. tlv_size_diff=%d\n", + __func__, tlv_size_diff); + + /* incoming structure length */ + in_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr)) + WMI_TLV_HDR_SIZE; +#ifndef NO_DYNAMIC_MEM_ALLOC + wmi_tlv_os_mem_alloc(os_handle, new_tlv_buf, (num_of_elems * attr_struct_ptr.tag_struct_size)); + if (new_tlv_buf == NULL) { + /* Error: unable to alloc memory */ + wmi_tlv_print_error("%s: Error: unable to alloc memory (size=%d) for padding the TLV array %d\n", + __func__, (num_of_elems * attr_struct_ptr.tag_struct_size), curr_tlv_tag); + goto Error_wmitlv_check_and_pad_tlvs; + } + + wmi_tlv_OS_MEMZERO(new_tlv_buf, (num_of_elems * attr_struct_ptr.tag_struct_size)); + tlv_buf_ptr = (A_UINT8 *)new_tlv_buf; + for(i=0; i0) + { + /* Incoming structure size is greater than expected structure size. + so copy the number of bytes equal to expected structure size */ + wmi_tlv_OS_MEMCPY(tlv_buf_ptr, (void*)(buf_ptr+i*in_tlv_len), attr_struct_ptr.tag_struct_size); + } + else + { + /* Incoming structure size is smaller than expected structure size. + so copy the number of bytes equal to incoming structure size + (other bytes would be zeroes) */ + wmi_tlv_OS_MEMCPY(tlv_buf_ptr, (void*)(buf_ptr+i*in_tlv_len), in_tlv_len); + } + tlv_buf_ptr += attr_struct_ptr.tag_struct_size; + } +#else + { + A_UINT8 *src_addr; + A_UINT8 *dst_addr; + A_UINT32 buf_mov_len; + + if (tlv_size_diff < 0) + { + /* Incoming structure size is smaller than expected size then this needs padding for each element in the array */ + + /* Find amount of bytes to be padded for one element */ + num_padding_bytes = tlv_size_diff * -1; + + /* Move subsequent TLVs by number of bytes to be padded for all elements */ + if (param_buf_len > (buf_idx + curr_tlv_len)) + { + src_addr = buf_ptr + curr_tlv_len; + dst_addr = buf_ptr + curr_tlv_len + (num_padding_bytes * num_of_elems); + buf_mov_len = param_buf_len - (buf_idx + curr_tlv_len); + + wmi_tlv_OS_MEMMOVE(dst_addr, src_addr, buf_mov_len); + } + + /* Move subsequent elements of array down by number of bytes to be padded for one element and alse set padding bytes to zero */ + tlv_buf_ptr = buf_ptr; + for(i=0; i (buf_idx + curr_tlv_len)) + { + src_addr = buf_ptr + curr_tlv_len; + dst_addr = buf_ptr + curr_tlv_len + (num_padding_bytes * num_of_elems); + buf_mov_len = param_buf_len - (buf_idx + curr_tlv_len); + + wmi_tlv_OS_MEMMOVE(dst_addr, src_addr, buf_mov_len); + } + + /* Update the number of padding bytes to total number of bytes shrinked for all elements in the array */ + num_padding_bytes = num_padding_bytes * num_of_elems; + + new_tlv_buf = buf_ptr; + } + } +#endif + cmd_param_tlvs_ptr[tlv_index].tlv_ptr = new_tlv_buf; + cmd_param_tlvs_ptr[tlv_index].num_elements = num_of_elems; + cmd_param_tlvs_ptr[tlv_index].buf_is_allocated = 1; // Indicates that buffer is allocated + + } + else if (tlv_size_diff>=0) + { + /* Warning: some parameter truncation */ + if (tlv_size_diff > 0) + { + wmi_tlv_print_verbose("%s: WARN: TLV truncated. tlv_size_diff=%d, curr_tlv_len=%d\n", + __func__, tlv_size_diff, curr_tlv_len); + } + /* TODO: this next line needs more comments and explanation */ + cmd_param_tlvs_ptr[tlv_index].tlv_ptr = (attr_struct_ptr.tag_varied_size && !curr_tlv_len)?NULL:(void *)buf_ptr; + cmd_param_tlvs_ptr[tlv_index].num_elements = num_of_elems; + cmd_param_tlvs_ptr[tlv_index].buf_is_allocated = 0; // Indicates that buffer is not allocated + } + else + { + void *new_tlv_buf = NULL; + + /* Warning: Needs to allocate a larger structure and pad with zeros */ + wmi_tlv_print_verbose("%s: WARN: TLV needs padding. tlv_size_diff=%d\n", + __func__, tlv_size_diff); +#ifndef NO_DYNAMIC_MEM_ALLOC + /* Dynamic memory allocation is supported */ + wmi_tlv_os_mem_alloc(os_handle, new_tlv_buf, (curr_tlv_len-tlv_size_diff)); + if (new_tlv_buf == NULL) { + /* Error: unable to alloc memory */ + wmi_tlv_print_error("%s: Error: unable to alloc memory (size=%d) for padding the TLV %d\n", + __func__, (curr_tlv_len-tlv_size_diff), curr_tlv_tag); + goto Error_wmitlv_check_and_pad_tlvs; + } + + wmi_tlv_OS_MEMZERO(new_tlv_buf, (curr_tlv_len-tlv_size_diff)); + wmi_tlv_OS_MEMCPY(new_tlv_buf, (void*)buf_ptr, curr_tlv_len); +#else + /* Dynamic memory allocation is not supported. Padding has to be done with in the existing buffer assuming we have enough space + to grow */ + { + /* Note: tlv_size_diff is a value less than zero */ + /* Move the Subsequent TLVs by amount of bytes needs to be padded */ + A_UINT8 *src_addr; + A_UINT8 *dst_addr; + A_UINT32 src_len; + + num_padding_bytes = (tlv_size_diff * -1); + + src_addr = buf_ptr + curr_tlv_len; + dst_addr = buf_ptr + curr_tlv_len + num_padding_bytes; + src_len = param_buf_len - (buf_idx + curr_tlv_len); + + wmi_tlv_OS_MEMMOVE(dst_addr, src_addr, src_len); + + /* Set the padding bytes to zeroes */ + wmi_tlv_OS_MEMZERO(src_addr, num_padding_bytes); + + new_tlv_buf = buf_ptr; + } +#endif + cmd_param_tlvs_ptr[tlv_index].tlv_ptr = new_tlv_buf; + cmd_param_tlvs_ptr[tlv_index].num_elements = num_of_elems; + cmd_param_tlvs_ptr[tlv_index].buf_is_allocated = 1; // Indicates that buffer is allocated + } + + tlv_index++; + remaining_expected_tlvs--; + buf_ptr += curr_tlv_len + num_padding_bytes; + buf_idx += curr_tlv_len + num_padding_bytes; + } + + return(0); +Error_wmitlv_check_and_pad_tlvs: + if (is_cmd_id) { + wmitlv_free_allocated_command_tlvs(wmi_cmd_event_id, wmi_cmd_struct_ptr); + } + else { + wmitlv_free_allocated_event_tlvs(wmi_cmd_event_id, wmi_cmd_struct_ptr); + } + *wmi_cmd_struct_ptr = NULL; + return(-1); +} + +/* + * Helper Function to validate and pad(if necessary) for incoming WMI Event TLVs + * Return 0 if success. + <0 if failure. + */ +int +wmitlv_check_and_pad_event_tlvs( + void *os_handle, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id, void **wmi_cmd_struct_ptr) +{ + A_UINT32 is_cmd_id = 0; + return(wmitlv_check_and_pad_tlvs(os_handle,param_struc_ptr,param_buf_len,is_cmd_id,wmi_cmd_event_id,wmi_cmd_struct_ptr)); +} + +/* + * Helper Function to validate and pad(if necessary) for incoming WMI Command TLVs + * Return 0 if success. + <0 if failure. + */ +int +wmitlv_check_and_pad_command_tlvs( + void *os_handle, void *param_struc_ptr, A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id, void **wmi_cmd_struct_ptr) +{ + A_UINT32 is_cmd_id = 1; + return(wmitlv_check_and_pad_tlvs(os_handle,param_struc_ptr,param_buf_len,is_cmd_id,wmi_cmd_event_id,wmi_cmd_struct_ptr)); +} + +/* + * Helper Function to free any allocated buffers for WMI Event/Command TLV processing + * Return None + */ +static void wmitlv_free_allocated_tlvs(A_UINT32 is_cmd_id, A_UINT32 cmd_event_id, void **wmi_cmd_struct_ptr) +{ + void *ptr = *wmi_cmd_struct_ptr; + + if(!ptr) + { + wmi_tlv_print_error("%s: Nothing to free for CMD/Event 0x%x\n",__func__,cmd_event_id); + return; + } + +#ifndef NO_DYNAMIC_MEM_ALLOC + +/* macro to free that previously allocated memory for this TLV. When (op==FREE_TLV_ELEM). */ +#define WMITLV_OP_FREE_TLV_ELEM_macro(param_ptr, param_len, wmi_cmd_event_id, elem_tlv_tag, elem_struc_type, elem_name, var_len, arr_size) \ + if ((((WMITLV_TYPEDEF_STRUCT_PARAMS_TLVS(wmi_cmd_event_id)*)ptr)->WMITLV_FIELD_BUF_IS_ALLOCATED(elem_name)) && \ + (((WMITLV_TYPEDEF_STRUCT_PARAMS_TLVS(wmi_cmd_event_id)*)ptr)->elem_name != NULL)) \ + { \ + wmi_tlv_os_mem_free(((WMITLV_TYPEDEF_STRUCT_PARAMS_TLVS(wmi_cmd_event_id)*)ptr)->elem_name);\ + } + + +#define WMITLV_FREE_TLV_ELEMS(id) \ + case id:\ + {\ + WMITLV_TABLE(id, FREE_TLV_ELEM, NULL, 0) \ + } \ + break; + + if (is_cmd_id) { + switch(cmd_event_id) + { + WMITLV_ALL_CMD_LIST(WMITLV_FREE_TLV_ELEMS); + default: + wmi_tlv_print_error("%s: ERROR: Cannot find the TLVs attributes for Cmd=0x%x, %d\n", + __func__, cmd_event_id, cmd_event_id); + } + } + else { + switch(cmd_event_id) + { + WMITLV_ALL_EVT_LIST(WMITLV_FREE_TLV_ELEMS); + default: + wmi_tlv_print_error("%s: ERROR: Cannot find the TLVs attributes for Cmd=0x%x, %d\n", + __func__, cmd_event_id, cmd_event_id); + } + } + + wmi_tlv_os_mem_free(*wmi_cmd_struct_ptr); + *wmi_cmd_struct_ptr = NULL; +#endif + + return; +} + +/* + * Helper Function to free any allocated buffers for WMI Command TLV processing + * Return None + */ +void wmitlv_free_allocated_command_tlvs(A_UINT32 cmd_event_id, void **wmi_cmd_struct_ptr) +{ + wmitlv_free_allocated_tlvs(1, cmd_event_id, wmi_cmd_struct_ptr); +} + +/* + * Helper Function to free any allocated buffers for WMI Event TLV processing + * Return None + */ +void wmitlv_free_allocated_event_tlvs(A_UINT32 cmd_event_id, void **wmi_cmd_struct_ptr) +{ + wmitlv_free_allocated_tlvs(0, cmd_event_id, wmi_cmd_struct_ptr); +} + +/* + * Returns 1 if the two given versions are compatible. + * Else return 0 if Incompatible. + */ +int +wmi_versions_are_compatible(wmi_abi_version *vers1, wmi_abi_version *vers2) +{ + if ((vers1->abi_version_ns_0 != vers2->abi_version_ns_0) || + (vers1->abi_version_ns_1 != vers2->abi_version_ns_1) || + (vers1->abi_version_ns_2 != vers2->abi_version_ns_2) || + (vers1->abi_version_ns_3 != vers2->abi_version_ns_3)) + { + /* The namespaces are different. Incompatible. */ + return 0; + } + + if (vers1->abi_version_0 != vers2->abi_version_0) { + /* The major or minor versions are different. Incompatible */ + return 0; + } + /* We ignore the build version */ + return 1; +} + +/* + * Returns 1 if the two given versions are compatible. + * Else return 0 if Incompatible. + */ +int +wmi_versions_can_downgrade(int num_whitelist, wmi_whitelist_version_info *version_whitelist_table, + wmi_abi_version *my_vers, wmi_abi_version *opp_vers, wmi_abi_version *out_vers) +{ + A_UINT8 can_try_to_downgrade; + A_UINT32 my_major_vers = WMI_VER_GET_MAJOR(my_vers->abi_version_0); + A_UINT32 my_minor_vers = WMI_VER_GET_MINOR(my_vers->abi_version_0); + A_UINT32 opp_major_vers = WMI_VER_GET_MAJOR(opp_vers->abi_version_0); + A_UINT32 opp_minor_vers = WMI_VER_GET_MINOR(opp_vers->abi_version_0); + A_UINT32 downgraded_minor_vers; + + if ((my_vers->abi_version_ns_0 != opp_vers->abi_version_ns_0) || + (my_vers->abi_version_ns_1 != opp_vers->abi_version_ns_1) || + (my_vers->abi_version_ns_2 != opp_vers->abi_version_ns_2) || + (my_vers->abi_version_ns_3 != opp_vers->abi_version_ns_3)) + { + /* The namespaces are different. Incompatible. */ + can_try_to_downgrade = FALSE; + } + else if (my_major_vers != opp_major_vers) { + /* Major version is different. Incompatible and cannot downgrade. */ + can_try_to_downgrade = FALSE; + } + else { + /* Same major version. */ + + if (my_minor_vers < opp_minor_vers) { + /* Opposite party is newer. Incompatible and cannot downgrade. */ + can_try_to_downgrade = FALSE; + } + else if (my_minor_vers > opp_minor_vers) { + /* Opposite party is older. Check whitelist if we can downgrade */ + can_try_to_downgrade = TRUE; + } + else { + /* Same version */ + wmi_tlv_OS_MEMCPY(out_vers, my_vers, sizeof(wmi_abi_version)); + return 1; + } + } + + if (!can_try_to_downgrade) { + wmi_tlv_print_error("%s: Warning: incompatible WMI version.\n", __func__); + wmi_tlv_OS_MEMCPY(out_vers, my_vers, sizeof(wmi_abi_version)); + return 0; + } + /* Try to see we can downgrade the supported version */ + downgraded_minor_vers = my_minor_vers; + while (downgraded_minor_vers > opp_minor_vers) + { + A_UINT8 downgraded = FALSE; + int i; + + for (i=0; iabi_version_ns_0) || + (version_whitelist_table[i].namespace_1 != my_vers->abi_version_ns_1) || + (version_whitelist_table[i].namespace_2 != my_vers->abi_version_ns_2) || + (version_whitelist_table[i].namespace_3 != my_vers->abi_version_ns_3)) + { + continue; /* skip */ + } + if (version_whitelist_table[i].minor == downgraded_minor_vers) { + /* Found the next version that I can downgrade */ + wmi_tlv_print_error("%s: Note: found a whitelist entry to downgrade. wh. list ver: %d,%d,0x%x 0x%x 0x%x 0x%x\n", + __func__, version_whitelist_table[i].major, version_whitelist_table[i].minor, + version_whitelist_table[i].namespace_0, version_whitelist_table[i].namespace_1, + version_whitelist_table[i].namespace_2, version_whitelist_table[i].namespace_3); + downgraded_minor_vers--; + downgraded = TRUE; + break; + } + } + if (!downgraded) { + break; /* Done since we did not find any whitelist to downgrade version */ + } + } + wmi_tlv_OS_MEMCPY(out_vers, my_vers, sizeof(wmi_abi_version)); + out_vers->abi_version_0 = WMI_VER_GET_VERSION_0(my_major_vers, downgraded_minor_vers); + if (downgraded_minor_vers != opp_minor_vers) { + wmi_tlv_print_error("%s: Warning: incompatible WMI version and cannot downgrade.\n", __func__); + return 0; /* Incompatible */ + } + else { + return 1; /* Compatible */ + } +} + +/* + * This routine will compare and set the WMI ABI version. + * First, compare my version with the opposite side's version. + * If incompatible, then check the whitelist to see if our side can downgrade. + * Finally, fill in the final ABI version into the output, out_vers. + * Return 0 if the output version is compatible . + * Else return 1 if the output version is incompatible. . + */ +int +wmi_cmp_and_set_abi_version(int num_whitelist, wmi_whitelist_version_info *version_whitelist_table, + struct _wmi_abi_version *my_vers, + struct _wmi_abi_version *opp_vers, + struct _wmi_abi_version *out_vers) +{ + wmi_tlv_print_verbose("%s: Our WMI Version: Mj=%d, Mn=%d, bd=%d, ns0=0x%x ns1:0x%x ns2:0x%x ns3:0x%x\n", __func__, + WMI_VER_GET_MAJOR(my_vers->abi_version_0), WMI_VER_GET_MINOR(my_vers->abi_version_0), my_vers->abi_version_1, + my_vers->abi_version_ns_0, my_vers->abi_version_ns_1, my_vers->abi_version_ns_2, my_vers->abi_version_ns_3); + + wmi_tlv_print_verbose("%s: Opposite side WMI Version: Mj=%d, Mn=%d, bd=%d, ns0=0x%x ns1:0x%x ns2:0x%x ns3:0x%x\n", __func__, + WMI_VER_GET_MAJOR(opp_vers->abi_version_0), WMI_VER_GET_MINOR(opp_vers->abi_version_0), opp_vers->abi_version_1, + opp_vers->abi_version_ns_0, opp_vers->abi_version_ns_1, opp_vers->abi_version_ns_2, opp_vers->abi_version_ns_3); + + /* By default, the output version is our version. */ + wmi_tlv_OS_MEMCPY(out_vers, my_vers, sizeof(wmi_abi_version)); + if (!wmi_versions_are_compatible(my_vers, opp_vers)) + { + /* Our host version and the given firmware version are incompatible. */ + if (wmi_versions_can_downgrade(num_whitelist, version_whitelist_table, my_vers, opp_vers, out_vers)) + { + /* We can downgrade our host versions to match firmware. */ + wmi_tlv_print_error("%s: Host downgraded WMI Versions to match fw. Ret version: Mj=%d, Mn=%d, bd=%d, ns0=0x%x ns1:0x%x ns2:0x%x ns3:0x%x\n", __func__, + WMI_VER_GET_MAJOR(out_vers->abi_version_0), WMI_VER_GET_MINOR(out_vers->abi_version_0), out_vers->abi_version_1, + out_vers->abi_version_ns_0, out_vers->abi_version_ns_1, out_vers->abi_version_ns_2, out_vers->abi_version_ns_3); + return 0; /* Compatible */ + } + else { + /* Warn: We cannot downgrade our host versions to match firmware. */ + wmi_tlv_print_error("%s: WARN: Host WMI Versions mismatch with fw. Ret version: Mj=%d, Mn=%d, bd=%d, ns0=0x%x ns1:0x%x ns2:0x%x ns3:0x%x\n", __func__, + WMI_VER_GET_MAJOR(out_vers->abi_version_0), WMI_VER_GET_MINOR(out_vers->abi_version_0), out_vers->abi_version_1, + out_vers->abi_version_ns_0, out_vers->abi_version_ns_1, out_vers->abi_version_ns_2, out_vers->abi_version_ns_3); + + return 1; /* Incompatible */ + } + } + else { + /* We are compatible. Our host version is the output version */ + wmi_tlv_print_verbose("%s: Host and FW Compatible WMI Versions. Ret version: Mj=%d, Mn=%d, bd=%d, ns0=0x%x ns1:0x%x ns2:0x%x ns3:0x%x\n", __func__, + WMI_VER_GET_MAJOR(out_vers->abi_version_0), WMI_VER_GET_MINOR(out_vers->abi_version_0), out_vers->abi_version_1, + out_vers->abi_version_ns_0, out_vers->abi_version_ns_1, out_vers->abi_version_ns_2, out_vers->abi_version_ns_3); + return 0; /* Compatible */ + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_platform.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_platform.c new file mode 100644 index 000000000000..09091b589bc1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_tlv_platform.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * LMAC offload interface functions for WMI TLV Interface + */ + +#include "ol_if_athvar.h" +#include /* adf_os_mem_alloc,free, etc. */ +#include +#include "htc_api.h" +#include "wmi.h" +#include "wma.h" + +// QCA Main host has dynamic memory allocation and should not define NO_DYNAMIC_MEM_ALLOC +//#define NO_DYNAMIC_MEM_ALLOC + +/* Following macro definitions use OS or platform specific functions */ +/* Following macro definitions use QCA MAIN windows host driver(applicable for Perigrene and its future platforms, + Pronto and its future platforms) specific APIs */ + #define dummy_print(fmt, ...) {} + #define wmi_tlv_print_verbose dummy_print + #define wmi_tlv_print_error adf_os_print + #define wmi_tlv_OS_MEMCPY OS_MEMCPY + #define wmi_tlv_OS_MEMZERO OS_MEMZERO + #define wmi_tlv_OS_MEMMOVE OS_MEMMOVE + +#ifndef NO_DYNAMIC_MEM_ALLOC + #define wmi_tlv_os_mem_alloc(scn, ptr, numBytes) \ + { \ + (ptr) = OS_MALLOC(NULL, (numBytes), GFP_ATOMIC); \ + } + #define wmi_tlv_os_mem_free adf_os_mem_free +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c new file mode 100644 index 000000000000..7bbd217a47b4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c @@ -0,0 +1,1264 @@ +/* + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * Host WMI unified implementation + */ +#include "athdefs.h" +#include "osapi_linux.h" +#include "a_types.h" +#include "a_debug.h" +#include "ol_if_athvar.h" +#include "ol_defines.h" +#include "ol_fw.h" +#include "htc_api.h" +#include "htc_api.h" +#include "dbglog_host.h" +#include "wmi.h" +#include "wmi_unified_priv.h" +#include "wma_api.h" +#include "wma.h" +#include "macTrace.h" +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#endif + +#define WMI_MIN_HEAD_ROOM 64 + +#ifdef WMI_INTERFACE_EVENT_LOGGING +/* WMI commands */ +u_int32_t g_wmi_command_buf_idx = 0; +struct wmi_command_debug wmi_command_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; + +/* WMI commands TX completed */ +u_int32_t g_wmi_command_tx_cmp_buf_idx = 0; +struct wmi_command_debug wmi_command_tx_cmp_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; + +/* WMI events when processed */ +u_int32_t g_wmi_event_buf_idx = 0; +struct wmi_event_debug wmi_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; + +/* WMI events when queued */ +u_int32_t g_wmi_rx_event_buf_idx = 0; +struct wmi_event_debug wmi_rx_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; + +#define WMI_COMMAND_RECORD(a, b) { \ + if (WMI_EVENT_DEBUG_MAX_ENTRY <= g_wmi_command_buf_idx) \ + g_wmi_command_buf_idx = 0; \ + wmi_command_log_buffer[g_wmi_command_buf_idx].command = a; \ + adf_os_mem_copy(wmi_command_log_buffer[g_wmi_command_buf_idx].data, b, 16);\ + wmi_command_log_buffer[g_wmi_command_buf_idx].time = \ + adf_get_boottime(); \ + g_wmi_command_buf_idx++; \ +} + +#define WMI_COMMAND_TX_CMP_RECORD(a, b) { \ + if (WMI_EVENT_DEBUG_MAX_ENTRY <= g_wmi_command_tx_cmp_buf_idx) \ + g_wmi_command_tx_cmp_buf_idx = 0; \ + wmi_command_tx_cmp_log_buffer[g_wmi_command_tx_cmp_buf_idx].command = a;\ + adf_os_mem_copy(wmi_command_tx_cmp_log_buffer \ + [g_wmi_command_tx_cmp_buf_idx].data, b, 16); \ + wmi_command_tx_cmp_log_buffer[g_wmi_command_tx_cmp_buf_idx].time =\ + adf_get_boottime(); \ + g_wmi_command_tx_cmp_buf_idx++; \ +} + +#define WMI_EVENT_RECORD(a, b) { \ + if (WMI_EVENT_DEBUG_MAX_ENTRY <= g_wmi_event_buf_idx) \ + g_wmi_event_buf_idx = 0; \ + wmi_event_log_buffer[g_wmi_event_buf_idx].event = a; \ + adf_os_mem_copy(wmi_event_log_buffer[g_wmi_event_buf_idx].data, b, 16);\ + wmi_event_log_buffer[g_wmi_event_buf_idx].time = \ + adf_get_boottime(); \ + g_wmi_event_buf_idx++; \ +} + +#define WMI_RX_EVENT_RECORD(a,b) { \ + if (WMI_EVENT_DEBUG_MAX_ENTRY <= g_wmi_rx_event_buf_idx) \ + g_wmi_rx_event_buf_idx = 0; \ + wmi_rx_event_log_buffer[g_wmi_rx_event_buf_idx].event = a; \ + adf_os_mem_copy(wmi_rx_event_log_buffer[g_wmi_rx_event_buf_idx].data, b, 16);\ + wmi_rx_event_log_buffer[g_wmi_rx_event_buf_idx].time = \ + adf_get_boottime(); \ + g_wmi_rx_event_buf_idx++; \ +} + +#endif /*WMI_INTERFACE_EVENT_LOGGING*/ + + +static void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf); +int wmi_get_host_credits(wmi_unified_t wmi_handle); +/* WMI buffer APIs */ + +/** + * wmi_get_max_msg_len() - get maximum WMI message length + * @wmi_handle: WMI handle. + * + * This function returns the maximum WMI message length + * + * Return: maximum WMI message length + */ +uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle) +{ + return wmi_handle->max_msg_len - WMI_MIN_HEAD_ROOM; +} + +wmi_buf_t +wmi_buf_alloc(wmi_unified_t wmi_handle, u_int16_t len) +{ + wmi_buf_t wmi_buf; + + if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > + wmi_handle->max_msg_len) { + VOS_ASSERT(0); + return NULL; + } + wmi_buf = adf_nbuf_alloc(NULL, roundup(len + WMI_MIN_HEAD_ROOM, 4), + WMI_MIN_HEAD_ROOM, 4, FALSE); + if (!wmi_buf) + return NULL; + + /* Clear the wmi buffer */ + OS_MEMZERO(adf_nbuf_data(wmi_buf), len); + + /* + * Set the length of the buffer to match the allocation size. + */ + adf_nbuf_set_pktlen(wmi_buf, len); + return wmi_buf; +} + +static u_int8_t* get_wmi_cmd_string(WMI_CMD_ID wmi_command) +{ + switch(wmi_command) + { + /** initialize the wlan sub system */ + CASE_RETURN_STRING(WMI_INIT_CMDID); + + /* Scan specific commands */ + + /** start scan request to FW */ + CASE_RETURN_STRING(WMI_START_SCAN_CMDID); + /** stop scan request to FW */ + CASE_RETURN_STRING(WMI_STOP_SCAN_CMDID); + /** full list of channels as defined by the regulatory that will be used by scanner */ + CASE_RETURN_STRING(WMI_SCAN_CHAN_LIST_CMDID); + /** overwrite default priority table in scan scheduler */ + CASE_RETURN_STRING(WMI_SCAN_SCH_PRIO_TBL_CMDID); + /** This command to adjust the priority and min.max_rest_time + * of an on ongoing scan request. + */ + CASE_RETURN_STRING(WMI_SCAN_UPDATE_REQUEST_CMDID); + + /* PDEV(physical device) specific commands */ + /** set regulatorty ctl id used by FW to determine the exact ctl power limits */ + CASE_RETURN_STRING(WMI_PDEV_SET_REGDOMAIN_CMDID); + /** set channel. mainly used for supporting monitor mode */ + CASE_RETURN_STRING(WMI_PDEV_SET_CHANNEL_CMDID); + /** set pdev specific parameters */ + CASE_RETURN_STRING(WMI_PDEV_SET_PARAM_CMDID); + /** enable packet log */ + CASE_RETURN_STRING(WMI_PDEV_PKTLOG_ENABLE_CMDID); + /** disable packet log*/ + CASE_RETURN_STRING(WMI_PDEV_PKTLOG_DISABLE_CMDID); + /** set wmm parameters */ + CASE_RETURN_STRING(WMI_PDEV_SET_WMM_PARAMS_CMDID); + /** set HT cap ie that needs to be carried probe requests HT/VHT channels */ + CASE_RETURN_STRING(WMI_PDEV_SET_HT_CAP_IE_CMDID); + /** set VHT cap ie that needs to be carried on probe requests on VHT channels */ + CASE_RETURN_STRING(WMI_PDEV_SET_VHT_CAP_IE_CMDID); + + /** Command to send the DSCP-to-TID map to the target */ + CASE_RETURN_STRING(WMI_PDEV_SET_DSCP_TID_MAP_CMDID); + /** set quiet ie parameters. primarily used in AP mode */ + CASE_RETURN_STRING(WMI_PDEV_SET_QUIET_MODE_CMDID); + /** Enable/Disable Green AP Power Save */ + CASE_RETURN_STRING(WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID); + /** get TPC config for the current operating channel */ + CASE_RETURN_STRING(WMI_PDEV_GET_TPC_CONFIG_CMDID); + + /** set the base MAC address for the physical device before a VDEV is created. + * For firmware that doesn�t support this feature and this command, the pdev + * MAC address will not be changed. */ + CASE_RETURN_STRING(WMI_PDEV_SET_BASE_MACADDR_CMDID); + + /* eeprom content dump , the same to bdboard data */ + CASE_RETURN_STRING(WMI_PDEV_DUMP_CMDID); + + /* VDEV(virtual device) specific commands */ + /** vdev create */ + CASE_RETURN_STRING(WMI_VDEV_CREATE_CMDID); + /** vdev delete */ + CASE_RETURN_STRING(WMI_VDEV_DELETE_CMDID); + /** vdev start request */ + CASE_RETURN_STRING(WMI_VDEV_START_REQUEST_CMDID); + /** vdev restart request (RX only, NO TX, used for CAC period)*/ + CASE_RETURN_STRING(WMI_VDEV_RESTART_REQUEST_CMDID); + /** vdev up request */ + CASE_RETURN_STRING(WMI_VDEV_UP_CMDID); + /** vdev stop request */ + CASE_RETURN_STRING(WMI_VDEV_STOP_CMDID); + /** vdev down request */ + CASE_RETURN_STRING(WMI_VDEV_DOWN_CMDID); + /* set a vdev param */ + CASE_RETURN_STRING(WMI_VDEV_SET_PARAM_CMDID); + /* set a key (used for setting per peer unicast and per vdev multicast) */ + CASE_RETURN_STRING(WMI_VDEV_INSTALL_KEY_CMDID); + + /* wnm sleep mode command */ + CASE_RETURN_STRING(WMI_VDEV_WNM_SLEEPMODE_CMDID); + CASE_RETURN_STRING(WMI_VDEV_WMM_ADDTS_CMDID); + CASE_RETURN_STRING(WMI_VDEV_WMM_DELTS_CMDID); + CASE_RETURN_STRING(WMI_VDEV_SET_WMM_PARAMS_CMDID); + CASE_RETURN_STRING(WMI_VDEV_SET_GTX_PARAMS_CMDID); + CASE_RETURN_STRING(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID); + + CASE_RETURN_STRING(WMI_VDEV_PLMREQ_START_CMDID); + CASE_RETURN_STRING(WMI_VDEV_PLMREQ_STOP_CMDID); + CASE_RETURN_STRING(WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); + CASE_RETURN_STRING(WMI_VDEV_SET_IE_CMDID); + /* peer specific commands */ + + /** create a peer */ + CASE_RETURN_STRING(WMI_PEER_CREATE_CMDID); + /** delete a peer */ + CASE_RETURN_STRING(WMI_PEER_DELETE_CMDID); + /** flush specific tid queues of a peer */ + CASE_RETURN_STRING(WMI_PEER_FLUSH_TIDS_CMDID); + /** set a parameter of a peer */ + CASE_RETURN_STRING(WMI_PEER_SET_PARAM_CMDID); + /** set peer to associated state. will cary all parameters determined during assocication time */ + CASE_RETURN_STRING(WMI_PEER_ASSOC_CMDID); + /**add a wds (4 address ) entry. used only for testing WDS feature on AP products */ + CASE_RETURN_STRING(WMI_PEER_ADD_WDS_ENTRY_CMDID); + /**remove wds (4 address ) entry. used only for testing WDS feature on AP products */ + CASE_RETURN_STRING(WMI_PEER_REMOVE_WDS_ENTRY_CMDID); + /** set up mcast group infor for multicast to unicast conversion */ + CASE_RETURN_STRING(WMI_PEER_MCAST_GROUP_CMDID); + /** request peer info from FW. FW shall respond with PEER_INFO_EVENTID */ + CASE_RETURN_STRING(WMI_PEER_INFO_REQ_CMDID); + + /* beacon/management specific commands */ + + /** transmit beacon by reference . used for transmitting beacon on low latency interface like pcie */ + CASE_RETURN_STRING(WMI_BCN_TX_CMDID); + /** transmit beacon by value */ + CASE_RETURN_STRING(WMI_PDEV_SEND_BCN_CMDID); + /** set the beacon template. used in beacon offload mode to setup the + * the common beacon template with the FW to be used by FW to generate beacons */ + CASE_RETURN_STRING(WMI_BCN_TMPL_CMDID); + /** set beacon filter with FW */ + CASE_RETURN_STRING(WMI_BCN_FILTER_RX_CMDID); + /* enable/disable filtering of probe requests in the firmware */ + CASE_RETURN_STRING(WMI_PRB_REQ_FILTER_RX_CMDID); + /** transmit management frame by value. will be deprecated */ + CASE_RETURN_STRING(WMI_MGMT_TX_CMDID); + /** set the probe response template. used in beacon offload mode to setup the + * the common probe response template with the FW to be used by FW to generate + * probe responses */ + CASE_RETURN_STRING(WMI_PRB_TMPL_CMDID); + + /** commands to directly control ba negotiation directly from host. only used in test mode */ + + /** turn off FW Auto addba mode and let host control addba */ + CASE_RETURN_STRING(WMI_ADDBA_CLEAR_RESP_CMDID); + /** send add ba request */ + CASE_RETURN_STRING(WMI_ADDBA_SEND_CMDID); + CASE_RETURN_STRING(WMI_ADDBA_STATUS_CMDID); + /** send del ba */ + CASE_RETURN_STRING(WMI_DELBA_SEND_CMDID); + /** set add ba response will be used by FW to generate addba response*/ + CASE_RETURN_STRING(WMI_ADDBA_SET_RESP_CMDID); + /** send single VHT MPDU with AMSDU */ + CASE_RETURN_STRING(WMI_SEND_SINGLEAMSDU_CMDID); + + /** Station power save specific config */ + /** enable/disable station powersave */ + CASE_RETURN_STRING(WMI_STA_POWERSAVE_MODE_CMDID); + /** set station power save specific parameter */ + CASE_RETURN_STRING(WMI_STA_POWERSAVE_PARAM_CMDID); + /** set station mimo powersave mode */ + CASE_RETURN_STRING(WMI_STA_MIMO_PS_MODE_CMDID); + + + /** DFS-specific commands */ + /** enable DFS (radar detection)*/ + CASE_RETURN_STRING(WMI_PDEV_DFS_ENABLE_CMDID); + /** disable DFS (radar detection)*/ + CASE_RETURN_STRING(WMI_PDEV_DFS_DISABLE_CMDID); + /** enable DFS phyerr/parse filter offload */ + CASE_RETURN_STRING(WMI_DFS_PHYERR_FILTER_ENA_CMDID); + /** enable DFS phyerr/parse filter offload */ + CASE_RETURN_STRING(WMI_DFS_PHYERR_FILTER_DIS_CMDID); + + /* Roaming specific commands */ + /** set roam scan mode */ + CASE_RETURN_STRING(WMI_ROAM_SCAN_MODE); + /** set roam scan rssi threshold below which roam scan is enabled */ + CASE_RETURN_STRING(WMI_ROAM_SCAN_RSSI_THRESHOLD); + /** set roam scan period for periodic roam scan mode */ + CASE_RETURN_STRING(WMI_ROAM_SCAN_PERIOD); + /** set roam scan trigger rssi change threshold */ + CASE_RETURN_STRING(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD); + /** set roam AP profile */ + CASE_RETURN_STRING(WMI_ROAM_AP_PROFILE); + /** set channel list for roam scans */ + CASE_RETURN_STRING(WMI_ROAM_CHAN_LIST); + /** offload scan specific commands */ + /** set offload scan AP profile */ + CASE_RETURN_STRING(WMI_OFL_SCAN_ADD_AP_PROFILE); + /** remove offload scan AP profile */ + CASE_RETURN_STRING(WMI_OFL_SCAN_REMOVE_AP_PROFILE); + /** set offload scan period */ + CASE_RETURN_STRING(WMI_OFL_SCAN_PERIOD); + + /* P2P specific commands */ + /**set P2P device info. FW will used by FW to create P2P IE to be carried in probe response + * generated during p2p listen and for p2p discoverability */ + CASE_RETURN_STRING(WMI_P2P_DEV_SET_DEVICE_INFO); + /** enable/disable p2p discoverability on STA/AP VDEVs */ + CASE_RETURN_STRING(WMI_P2P_DEV_SET_DISCOVERABILITY); + /** set p2p ie to be carried in beacons generated by FW for GO */ + CASE_RETURN_STRING(WMI_P2P_GO_SET_BEACON_IE); + /** set p2p ie to be carried in probe response frames generated by FW for GO */ + CASE_RETURN_STRING(WMI_P2P_GO_SET_PROBE_RESP_IE); + /** set the vendor specific p2p ie data. FW will use this to parse the P2P NoA + * attribute in the beacons/probe responses received. + */ + CASE_RETURN_STRING(WMI_P2P_SET_VENDOR_IE_DATA_CMDID); + /** set the configure of p2p find offload */ + CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_CONFIG_CMDID); + /** set the vendor specific p2p ie data for p2p find offload using */ + CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_APPIE_CMDID); + /** set the BSSID/device name pattern of p2p find offload */ + CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_PATTERN_CMDID); + /** set OppPS related parameters **/ + CASE_RETURN_STRING(WMI_P2P_SET_OPPPS_PARAM_CMDID); + + /** AP power save specific config */ + /** set AP power save specific param */ + CASE_RETURN_STRING(WMI_AP_PS_PEER_PARAM_CMDID); + /** set AP UAPSD coex pecific param */ + CASE_RETURN_STRING(WMI_AP_PS_PEER_UAPSD_COEX_CMDID); + + + /** Rate-control specific commands */ + CASE_RETURN_STRING(WMI_PEER_RATE_RETRY_SCHED_CMDID); + + /** WLAN Profiling commands. */ + CASE_RETURN_STRING(WMI_WLAN_PROFILE_TRIGGER_CMDID); + CASE_RETURN_STRING(WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID); + CASE_RETURN_STRING(WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID); + CASE_RETURN_STRING(WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID); + CASE_RETURN_STRING(WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID); + + /** Suspend resume command Ids */ + CASE_RETURN_STRING(WMI_PDEV_SUSPEND_CMDID); + CASE_RETURN_STRING(WMI_PDEV_RESUME_CMDID); + + /* Beacon filter commands */ + /** add a beacon filter */ + CASE_RETURN_STRING(WMI_ADD_BCN_FILTER_CMDID); + /** remove a beacon filter */ + CASE_RETURN_STRING(WMI_RMV_BCN_FILTER_CMDID); + + /* WOW Specific WMI commands*/ + /** add pattern for awake */ + CASE_RETURN_STRING(WMI_WOW_ADD_WAKE_PATTERN_CMDID); + /** deleta a wake pattern */ + CASE_RETURN_STRING(WMI_WOW_DEL_WAKE_PATTERN_CMDID); + /** enable/deisable wake event */ + CASE_RETURN_STRING(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID); + /** enable WOW */ + CASE_RETURN_STRING(WMI_WOW_ENABLE_CMDID); + /** host woke up from sleep event to FW. Generated in response to WOW Hardware event */ + CASE_RETURN_STRING(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID); + + /* RTT measurement related cmd */ + /** reques to make an RTT measurement */ + CASE_RETURN_STRING(WMI_RTT_MEASREQ_CMDID); + /** reques to report a tsf measurement */ + CASE_RETURN_STRING(WMI_RTT_TSF_CMDID); + + /** spectral scan command */ + /** configure spectral scan */ + CASE_RETURN_STRING(WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID); + /** enable/disable spectral scan and trigger */ + CASE_RETURN_STRING(WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID); + + /* F/W stats */ + /** one time request for stats */ + CASE_RETURN_STRING(WMI_REQUEST_STATS_CMDID); + /** Push MCC Adaptive Scheduler Stats to Firmware */ + CASE_RETURN_STRING(WMI_MCC_SCHED_TRAFFIC_STATS_CMDID); + + /** ARP OFFLOAD REQUEST*/ + CASE_RETURN_STRING(WMI_SET_ARP_NS_OFFLOAD_CMDID); + + /** Proactive ARP Response Add Pattern Command*/ + CASE_RETURN_STRING(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID); + + /** Proactive ARP Response Del Pattern Command*/ + CASE_RETURN_STRING(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID); + + /** NS offload confid*/ + CASE_RETURN_STRING(WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); + + /* GTK offload Specific WMI commands*/ + CASE_RETURN_STRING(WMI_GTK_OFFLOAD_CMDID); + + /* CSA offload Specific WMI commands*/ + /** csa offload enable */ + CASE_RETURN_STRING(WMI_CSA_OFFLOAD_ENABLE_CMDID); + /** chan switch command */ + CASE_RETURN_STRING(WMI_CSA_OFFLOAD_CHANSWITCH_CMDID); + + /* Chatter commands*/ + /* Change chatter mode of operation */ + CASE_RETURN_STRING(WMI_CHATTER_SET_MODE_CMDID); + /** chatter add coalescing filter command */ + CASE_RETURN_STRING(WMI_CHATTER_ADD_COALESCING_FILTER_CMDID); + /** chatter delete coalescing filter command */ + CASE_RETURN_STRING(WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID); + /** chatter coalecing query command */ + CASE_RETURN_STRING(WMI_CHATTER_COALESCING_QUERY_CMDID); + + /**addba specific commands */ + /** start the aggregation on this TID */ + CASE_RETURN_STRING(WMI_PEER_TID_ADDBA_CMDID); + /** stop the aggregation on this TID */ + CASE_RETURN_STRING(WMI_PEER_TID_DELBA_CMDID); + + /** set station mimo powersave method */ + CASE_RETURN_STRING(WMI_STA_DTIM_PS_METHOD_CMDID); + /** Configure the Station UAPSD AC Auto Trigger Parameters */ + CASE_RETURN_STRING(WMI_STA_UAPSD_AUTO_TRIG_CMDID); + /** Configure the Keep Alive Parameters */ + CASE_RETURN_STRING(WMI_STA_KEEPALIVE_CMDID); + + /* Request ssn from target for a sta/tid pair */ + CASE_RETURN_STRING(WMI_BA_REQ_SSN_CMDID); + /* misc command group */ + /** echo command mainly used for testing */ + CASE_RETURN_STRING(WMI_ECHO_CMDID); + + /* !!IMPORTANT!! + * If you need to add a new WMI command to the CASE_RETURN_STRING(WMI_GRP_MISC sub-group, + * please make sure you add it BEHIND CASE_RETURN_STRING(WMI_PDEV_UTF_CMDID); + * as we MUST have a fixed value here to maintain compatibility between + * UTF and the ART2 driver + */ + /** UTF WMI commands */ + CASE_RETURN_STRING(WMI_PDEV_UTF_CMDID); + + /** set debug log config */ + CASE_RETURN_STRING(WMI_DBGLOG_CFG_CMDID); + /* QVIT specific command id */ + CASE_RETURN_STRING(WMI_PDEV_QVIT_CMDID); + /* Factory Testing Mode request command + * used for integrated chipsets */ + CASE_RETURN_STRING(WMI_PDEV_FTM_INTG_CMDID); + /* set and get keepalive parameters command */ + CASE_RETURN_STRING(WMI_VDEV_SET_KEEPALIVE_CMDID); + CASE_RETURN_STRING(WMI_VDEV_GET_KEEPALIVE_CMDID); + /* For fw recovery test command */ + CASE_RETURN_STRING(WMI_FORCE_FW_HANG_CMDID); + /* Set Mcast/Bdcast filter */ + CASE_RETURN_STRING(WMI_SET_MCASTBCAST_FILTER_CMDID); + /** set thermal management params **/ + CASE_RETURN_STRING(WMI_THERMAL_MGMT_CMDID); + CASE_RETURN_STRING(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_LRO_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_TRANSFER_DATA_TO_FLASH_CMDID); + CASE_RETURN_STRING(WMI_MAWC_SENSOR_REPORT_IND_CMDID); + CASE_RETURN_STRING(WMI_ROAM_CONFIGURE_MAWC_CMDID); + CASE_RETURN_STRING(WMI_NLO_CONFIGURE_MAWC_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_MAWC_CMDID); + /* GPIO Configuration */ + CASE_RETURN_STRING(WMI_GPIO_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_GPIO_OUTPUT_CMDID); + + /* Txbf configuration command */ + CASE_RETURN_STRING(WMI_TXBF_CMDID); + + /* FWTEST Commands */ + CASE_RETURN_STRING(WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID); + /** set NoA descs **/ + CASE_RETURN_STRING(WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID); + + /** TDLS Configuration */ + /** enable/disable TDLS */ + CASE_RETURN_STRING(WMI_TDLS_SET_STATE_CMDID); + /** set tdls peer state */ + CASE_RETURN_STRING(WMI_TDLS_PEER_UPDATE_CMDID); + + /** Resmgr Configuration */ + /** Adaptive OCS is enabled by default in the FW. This command is used to + * disable FW based adaptive OCS. + */ + CASE_RETURN_STRING(WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID); + /** set the requested channel time quota for the home channels */ + CASE_RETURN_STRING(WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID); + /** set the requested latency for the home channels */ + CASE_RETURN_STRING(WMI_RESMGR_SET_CHAN_LATENCY_CMDID); + + /** STA SMPS Configuration */ + /** force SMPS mode */ + CASE_RETURN_STRING(WMI_STA_SMPS_FORCE_MODE_CMDID); + /** set SMPS parameters */ + CASE_RETURN_STRING(WMI_STA_SMPS_PARAM_CMDID); + + /* Wlan HB commands*/ + /* enalbe/disable wlan HB */ + CASE_RETURN_STRING(WMI_HB_SET_ENABLE_CMDID); + /* set tcp parameters for wlan HB */ + CASE_RETURN_STRING(WMI_HB_SET_TCP_PARAMS_CMDID); + /* set tcp pkt filter for wlan HB */ + CASE_RETURN_STRING(WMI_HB_SET_TCP_PKT_FILTER_CMDID); + /* set udp parameters for wlan HB */ + CASE_RETURN_STRING(WMI_HB_SET_UDP_PARAMS_CMDID); + /* set udp pkt filter for wlan HB */ + CASE_RETURN_STRING(WMI_HB_SET_UDP_PKT_FILTER_CMDID); + + /** Wlan RMC commands*/ + /** enable/disable RMC */ + CASE_RETURN_STRING(WMI_RMC_SET_MODE_CMDID); + /** configure action frame period */ + CASE_RETURN_STRING(WMI_RMC_SET_ACTION_PERIOD_CMDID); + /** For debug/future enhancement purposes only, + * configures/finetunes RMC algorithms */ + CASE_RETURN_STRING(WMI_RMC_CONFIG_CMDID); + + /** WLAN MHF offload commands */ + /** enable/disable MHF offload */ + CASE_RETURN_STRING(WMI_MHF_OFFLOAD_SET_MODE_CMDID); + /** Plumb routing table for MHF offload */ + CASE_RETURN_STRING(WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID); + + /*location scan commands*/ + /*start batch scan*/ + CASE_RETURN_STRING(WMI_BATCH_SCAN_ENABLE_CMDID); + /*stop batch scan*/ + CASE_RETURN_STRING(WMI_BATCH_SCAN_DISABLE_CMDID); + /*get batch scan result*/ + CASE_RETURN_STRING(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID); + /* OEM related cmd */ + CASE_RETURN_STRING(WMI_OEM_REQ_CMDID); + CASE_RETURN_STRING(WMI_OEM_REQUEST_CMDID); + /* NAN request cmd */ + CASE_RETURN_STRING(WMI_NAN_CMDID); + /* Modem power state cmd */ + CASE_RETURN_STRING(WMI_MODEM_POWER_STATE_CMDID); + CASE_RETURN_STRING(WMI_REQUEST_STATS_EXT_CMDID); + CASE_RETURN_STRING(WMI_OBSS_SCAN_ENABLE_CMDID); + CASE_RETURN_STRING(WMI_OBSS_SCAN_DISABLE_CMDID); + CASE_RETURN_STRING(WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID); + CASE_RETURN_STRING(WMI_ROAM_SCAN_CMD); + CASE_RETURN_STRING(WMI_PDEV_SET_LED_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID); + CASE_RETURN_STRING(WMI_CHAN_AVOID_UPDATE_CMDID); + CASE_RETURN_STRING(WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID); + CASE_RETURN_STRING(WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID); + CASE_RETURN_STRING(WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID); + CASE_RETURN_STRING(WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID); + CASE_RETURN_STRING(WMI_REQUEST_LINK_STATS_CMDID); + CASE_RETURN_STRING(WMI_START_LINK_STATS_CMDID); + CASE_RETURN_STRING(WMI_CLEAR_LINK_STATS_CMDID); + CASE_RETURN_STRING(WMI_GET_FW_MEM_DUMP_CMDID); + CASE_RETURN_STRING(WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_LPI_START_SCAN_CMDID); + CASE_RETURN_STRING(WMI_LPI_STOP_SCAN_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_START_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_STOP_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_SET_CAPABILITIES_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_GET_CAPABILITIES_CMDID); + CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID); + CASE_RETURN_STRING(WMI_ROAM_SYNCH_COMPLETE); + CASE_RETURN_STRING(WMI_D0_WOW_ENABLE_DISABLE_CMDID); + CASE_RETURN_STRING(WMI_EXTWOW_ENABLE_CMDID); + CASE_RETURN_STRING(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID); + CASE_RETURN_STRING(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID); + CASE_RETURN_STRING(WMI_UNIT_TEST_CMDID); + CASE_RETURN_STRING(WMI_ROAM_SET_RIC_REQUEST_CMDID); + CASE_RETURN_STRING(WMI_PDEV_GET_TEMPERATURE_CMDID); + CASE_RETURN_STRING(WMI_SET_DHCP_SERVER_OFFLOAD_CMDID); + CASE_RETURN_STRING(WMI_TPC_CHAINMASK_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID); + CASE_RETURN_STRING(WMI_SCAN_PROB_REQ_OUI_CMDID); + CASE_RETURN_STRING(WMI_TDLS_SET_OFFCHAN_MODE_CMDID); + CASE_RETURN_STRING(WMI_PDEV_SET_LED_FLASHING_CMDID); + CASE_RETURN_STRING(WMI_MDNS_OFFLOAD_ENABLE_CMDID); + CASE_RETURN_STRING(WMI_MDNS_SET_FQDN_CMDID); + CASE_RETURN_STRING(WMI_MDNS_SET_RESPONSE_CMDID); + CASE_RETURN_STRING(WMI_MDNS_GET_STATS_CMDID); + CASE_RETURN_STRING(WMI_ROAM_INVOKE_CMDID); + CASE_RETURN_STRING(WMI_SET_ANTENNA_DIVERSITY_CMDID); + CASE_RETURN_STRING(WMI_SAP_OFL_ENABLE_CMDID); + CASE_RETURN_STRING(WMI_APFIND_CMDID); + CASE_RETURN_STRING(WMI_PASSPOINT_LIST_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_OCB_SET_SCHED_CMDID); + CASE_RETURN_STRING(WMI_OCB_SET_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_OCB_SET_UTC_TIME_CMDID); + CASE_RETURN_STRING(WMI_OCB_START_TIMING_ADVERT_CMDID); + CASE_RETURN_STRING(WMI_OCB_STOP_TIMING_ADVERT_CMDID); + CASE_RETURN_STRING(WMI_OCB_GET_TSF_TIMER_CMDID); + CASE_RETURN_STRING(WMI_DCC_GET_STATS_CMDID); + CASE_RETURN_STRING(WMI_DCC_CLEAR_STATS_CMDID); + CASE_RETURN_STRING(WMI_DCC_UPDATE_NDL_CMDID); + CASE_RETURN_STRING(WMI_ROAM_FILTER_CMDID); + CASE_RETURN_STRING(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_DEBUG_MESG_FLUSH_CMDID); + CASE_RETURN_STRING(WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID); + CASE_RETURN_STRING(WMI_SOC_SET_PCL_CMDID); + CASE_RETURN_STRING(WMI_SOC_SET_HW_MODE_CMDID); + CASE_RETURN_STRING(WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID); + CASE_RETURN_STRING(WMI_DIAG_EVENT_LOG_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_PACKET_FILTER_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_PACKET_FILTER_ENABLE_CMDID); + CASE_RETURN_STRING(WMI_SAP_SET_BLACKLIST_PARAM_CMDID); + CASE_RETURN_STRING(WMI_WOW_UDP_SVC_OFLD_CMDID); + CASE_RETURN_STRING(WMI_MGMT_TX_SEND_CMDID); + CASE_RETURN_STRING(WMI_SOC_SET_ANTENNA_MODE_CMDID); + CASE_RETURN_STRING(WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_AP_PS_EGAP_PARAM_CMDID); + CASE_RETURN_STRING(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID); + } + return "Invalid WMI cmd"; +} + +#ifdef FEATURE_RUNTIME_PM +inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle) +{ + return adf_os_atomic_read(&wmi_handle->runtime_pm_inprogress); +} +#endif + +/* WMI command API */ +int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, + WMI_CMD_ID cmd_id) +{ + HTC_PACKET *pkt; + A_STATUS status; + void *vos_context; + struct ol_softc *scn; + A_UINT16 htc_tag = 0; + + if (vos_is_shutdown_in_progress(VOS_MODULE_ID_WDA, NULL)) { + adf_os_print("\nERROR: %s: shutdown is in progress so could not send WMI command: %d\n", + __func__, cmd_id); + return -EBUSY; + } + + if (wmi_get_runtime_pm_inprogress(wmi_handle)) + goto skip_suspend_check; + + if (adf_os_atomic_read(&wmi_handle->is_target_suspended) && + ( (WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) && + (WMI_PDEV_RESUME_CMDID != cmd_id)) ) { + adf_os_print("\nERROR: %s: Target is suspended could not send WMI command: %d\n", + __func__, cmd_id); + VOS_ASSERT(0); + return -EBUSY; + } else + goto dont_tag; + +skip_suspend_check: + switch(cmd_id) { + case WMI_WOW_ENABLE_CMDID: + case WMI_PDEV_SUSPEND_CMDID: + case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID: + case WMI_WOW_ADD_WAKE_PATTERN_CMDID: + case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID: + case WMI_PDEV_RESUME_CMDID: + case WMI_WOW_DEL_WAKE_PATTERN_CMDID: +#ifdef FEATURE_WLAN_D0WOW + case WMI_D0_WOW_ENABLE_DISABLE_CMDID: +#endif + htc_tag = HTC_TX_PACKET_TAG_AUTO_PM; + case WMI_FORCE_FW_HANG_CMDID: + if (wmi_handle->tag_crash_inject) { + htc_tag = HTC_TX_PACKET_TAG_AUTO_PM; + wmi_handle->tag_crash_inject = false; + } + default: + break; + } + +dont_tag: + /* Do sanity check on the TLV parameter structure */ + { + void *buf_ptr = (void *) adf_nbuf_data(buf); + + if (wmitlv_check_command_tlv_params(NULL, buf_ptr, len, cmd_id) != 0) + { + adf_os_print("\nERROR: %s: Invalid WMI Parameter Buffer for Cmd:%d\n", + __func__, cmd_id); + return -1; + } + } + + if (adf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) { + pr_err("%s, Failed to send cmd %x, no memory\n", + __func__, cmd_id); + return -ENOMEM; + } + + WMI_SET_FIELD(adf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id); + + adf_os_atomic_inc(&wmi_handle->pending_cmds); + if (adf_os_atomic_read(&wmi_handle->pending_cmds) >= WMI_MAX_CMDS) { + vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); + scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); + pr_err("\n%s: hostcredits = %d\n", __func__, + wmi_get_host_credits(wmi_handle)); + HTC_dump_counter_info(wmi_handle->htc_handle); + //dump_CE_register(scn); + //dump_CE_debug_register(scn->hif_sc); + adf_os_atomic_dec(&wmi_handle->pending_cmds); + pr_err("%s: MAX 1024 WMI Pending cmds reached.\n", __func__); + VOS_BUG(0); + return -EBUSY; + } + + pkt = adf_os_mem_alloc(NULL, sizeof(*pkt)); + if (!pkt) { + adf_os_atomic_dec(&wmi_handle->pending_cmds); + pr_err("%s, Failed to alloc htc packet %x, no memory\n", + __func__, cmd_id); + return -ENOMEM; + } + + SET_HTC_PACKET_INFO_TX(pkt, + NULL, + adf_nbuf_data(buf), + len + sizeof(WMI_CMD_HDR), + /* htt_host_data_dl_len(buf)+20 */ + wmi_handle->wmi_endpoint_id, + htc_tag); + + SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf); + + WMA_LOGD("Send WMI command:%s command_id:%d", + get_wmi_cmd_string(cmd_id), cmd_id); + +#ifdef WMI_INTERFACE_EVENT_LOGGING + adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock); + /*Record 16 bytes of WMI cmd data - exclude TLV and WMI headers*/ + WMI_COMMAND_RECORD(cmd_id ,((u_int32_t *)adf_nbuf_data(buf) + 2)); + adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock); +#endif + + status = HTCSendPkt(wmi_handle->htc_handle, pkt); + + if (A_OK != status) { + adf_os_atomic_dec(&wmi_handle->pending_cmds); + pr_err("%s %d, HTCSendPkt failed\n", __func__, __LINE__); + } + + + return ((status == A_OK) ? EOK : -1); +} + + +/* WMI Event handler register API */ +int wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle, + WMI_EVT_ID event_id) +{ + u_int32_t idx = 0; + for (idx = 0; (idx < wmi_handle->max_event_idx && + idx < WMI_UNIFIED_MAX_EVENT); ++idx) { + if (wmi_handle->event_id[idx] == event_id && + wmi_handle->event_handler[idx] != NULL ) { + return idx; + } + } + return -1; +} + +int wmi_unified_register_event_handler(wmi_unified_t wmi_handle, + WMI_EVT_ID event_id, + wmi_unified_event_handler handler_func) +{ + u_int32_t idx=0; + + if ( wmi_unified_get_event_handler_ix( wmi_handle, event_id) != -1) { + printk("%s : event handler already registered 0x%x \n", + __func__, event_id); + return -1; + } + if ( wmi_handle->max_event_idx == WMI_UNIFIED_MAX_EVENT ) { + printk("%s : no more event handlers 0x%x \n", + __func__, event_id); + return -1; + } + idx=wmi_handle->max_event_idx; + wmi_handle->event_handler[idx] = handler_func; + wmi_handle->event_id[idx] = event_id; + wmi_handle->max_event_idx++; + + return 0; +} + +int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle, + WMI_EVT_ID event_id) +{ + u_int32_t idx=0; + if ( (idx = wmi_unified_get_event_handler_ix( wmi_handle, event_id)) == -1) { + printk("%s : event handler is not registered: event id 0x%x \n", + __func__, event_id); + return -1; + } + wmi_handle->event_handler[idx] = NULL; + wmi_handle->event_id[idx] = 0; + --wmi_handle->max_event_idx; + wmi_handle->event_handler[idx] = wmi_handle->event_handler[wmi_handle->max_event_idx]; + wmi_handle->event_id[idx] = wmi_handle->event_id[wmi_handle->max_event_idx] ; + return 0; +} + +#if 0 /* currently not used */ +static int wmi_unified_event_rx(struct wmi_unified *wmi_handle, + wmi_buf_t evt_buf) +{ + u_int32_t id; + u_int8_t *event; + u_int16_t len; + int status = -1; + u_int32_t idx = 0; + + ASSERT(evt_buf != NULL); + + id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + + if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL) + goto end; + + idx = wmi_unified_get_event_handler_ix(wmi_handle, id); + if (idx == -1) { + pr_err("%s : event handler is not registered: event id: 0x%x\n", + __func__, id); + goto end; + } + + event = adf_nbuf_data(evt_buf); + len = adf_nbuf_len(evt_buf); + + /* Call the WMI registered event handler */ + status = wmi_handle->event_handler[idx](wmi_handle->scn_handle, + event, len); + +end: + adf_nbuf_free(evt_buf); + return status; +} +#endif /* 0 */ + +/* + * Temporarily added to support older WMI events. We should move all events to unified + * when the target is ready to support it. + */ +void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet) +{ + struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx; + wmi_buf_t evt_buf; + u_int32_t len; + void *wmi_cmd_struct_ptr = NULL; + u_int32_t idx = 0; + int tlv_ok_status = 0; + +#if defined(WMI_INTERFACE_EVENT_LOGGING) || !defined(QCA_CONFIG_SMP) + u_int32_t id; + u_int8_t *data; +#endif + + evt_buf = (wmi_buf_t) htc_packet->pPktContext; + id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + /* TX_PAUSE EVENT should be handled with tasklet context */ + if ((WMI_TX_PAUSE_EVENTID == id) || + (WMI_WOW_WAKEUP_HOST_EVENTID == id) || + (WMI_D0_WOW_DISABLE_ACK_EVENTID == id)) { + if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL) + return; + + data = adf_nbuf_data(evt_buf); + len = adf_nbuf_len(evt_buf); + tlv_ok_status = wmitlv_check_and_pad_event_tlvs( + wmi_handle->scn_handle, + data, len, id, + &wmi_cmd_struct_ptr); + if (tlv_ok_status != 0) { + WMA_LOGE("Error: id=0x%x, wmitlv_check_and_pad_tlvs ret=%d", + id, tlv_ok_status); + return; + } + + idx = wmi_unified_get_event_handler_ix(wmi_handle, id); + if (idx == -1) { + wmitlv_free_allocated_event_tlvs(id, + &wmi_cmd_struct_ptr); + adf_nbuf_free(evt_buf); + return; + } + wmi_handle->event_handler[idx](wmi_handle->scn_handle, + wmi_cmd_struct_ptr, len); + wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr); + adf_nbuf_free(evt_buf); + return; + } + +#ifdef WMI_INTERFACE_EVENT_LOGGING + id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + data = adf_nbuf_data(evt_buf); + + adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock); + /* Exclude 4 bytes of TLV header */ + WMI_RX_EVENT_RECORD(id, ((u_int8_t *)data + 4)); + adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock); +#endif + adf_os_spin_lock_bh(&wmi_handle->eventq_lock); + adf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf); + adf_os_spin_unlock_bh(&wmi_handle->eventq_lock); + schedule_work(&wmi_handle->rx_event_work); +} + +void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) +{ + u_int32_t id; + u_int8_t *data; + u_int32_t len; + void *wmi_cmd_struct_ptr = NULL; + int tlv_ok_status = 0; + + id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + + if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL) + goto end; + + data = adf_nbuf_data(evt_buf); + len = adf_nbuf_len(evt_buf); + + /* Validate and pad(if necessary) the TLVs */ + tlv_ok_status = wmitlv_check_and_pad_event_tlvs(wmi_handle->scn_handle, + data, len, id, + &wmi_cmd_struct_ptr); + if (tlv_ok_status != 0) { + pr_err("%s: Error: id=0x%d, wmitlv_check_and_pad_tlvs ret=%d\n", + __func__, id, tlv_ok_status); + goto end; + } + +#ifdef FEATURE_WLAN_D0WOW + if (wmi_get_d0wow_flag(wmi_handle)) + pr_debug("%s: WMI event ID is 0x%x\n", __func__, id); +#endif + + if (id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) { + u_int32_t idx = 0; + + idx = wmi_unified_get_event_handler_ix(wmi_handle, id) ; + if (idx == -1) { + pr_err("%s : event handler is not registered: event id 0x%x\n", + __func__, id); + goto end; + } + +#ifdef WMI_INTERFACE_EVENT_LOGGING + adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock); + /* Exclude 4 bytes of TLV header */ + WMI_EVENT_RECORD(id, ((u_int8_t *)data + 4)); + adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock); +#endif + /* Call the WMI registered event handler */ + wmi_handle->event_handler[idx](wmi_handle->scn_handle, + wmi_cmd_struct_ptr, len); + goto end; + } + + switch (id) { + default: + pr_info("%s: Unhandled WMI event %d\n", __func__, id); + break; + case WMI_SERVICE_READY_EVENTID: + pr_info("%s: WMI UNIFIED SERVICE READY event\n", __func__); + wma_rx_service_ready_event(wmi_handle->scn_handle, + wmi_cmd_struct_ptr); + break; + case WMI_READY_EVENTID: + pr_info("%s: WMI UNIFIED READY event\n", __func__); + wma_rx_ready_event(wmi_handle->scn_handle, wmi_cmd_struct_ptr); + break; + } +end: + wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr); + adf_nbuf_free(evt_buf); +} + +void __wmi_rx_event_work(struct work_struct *work) +{ + struct wmi_unified *wmi = container_of(work, struct wmi_unified, + rx_event_work); + wmi_buf_t buf; + + adf_os_spin_lock_bh(&wmi->eventq_lock); + buf = adf_nbuf_queue_remove(&wmi->event_queue); + adf_os_spin_unlock_bh(&wmi->eventq_lock); + while (buf) { + __wmi_control_rx(wmi, buf); + adf_os_spin_lock_bh(&wmi->eventq_lock); + buf = adf_nbuf_queue_remove(&wmi->event_queue); + adf_os_spin_unlock_bh(&wmi->eventq_lock); + } +} + +void wmi_rx_event_work(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __wmi_rx_event_work(work); + vos_ssr_unprotect(__func__); +} + +/* WMI Initialization functions */ + +void * +wmi_unified_attach(ol_scn_t scn_handle, wma_wow_tx_complete_cbk func) +{ + struct wmi_unified *wmi_handle; + wmi_handle = (struct wmi_unified *)OS_MALLOC(NULL, sizeof(struct wmi_unified), GFP_ATOMIC); + if (wmi_handle == NULL) { + printk("allocation of wmi handle failed %zu \n", sizeof(struct wmi_unified)); + return NULL; + } + OS_MEMZERO(wmi_handle, sizeof(struct wmi_unified)); + wmi_handle->scn_handle = scn_handle; + adf_os_atomic_init(&wmi_handle->pending_cmds); + adf_os_atomic_init(&wmi_handle->is_target_suspended); +#ifdef FEATURE_RUNTIME_PM + adf_os_atomic_init(&wmi_handle->runtime_pm_inprogress); +#endif + adf_os_spinlock_init(&wmi_handle->eventq_lock); + adf_nbuf_queue_init(&wmi_handle->event_queue); +#ifdef CONFIG_CNSS + cnss_init_work(&wmi_handle->rx_event_work, wmi_rx_event_work); +#else + INIT_WORK(&wmi_handle->rx_event_work, wmi_rx_event_work); +#endif +#ifdef WMI_INTERFACE_EVENT_LOGGING + adf_os_spinlock_init(&wmi_handle->wmi_record_lock); +#endif + wmi_handle->wma_wow_tx_complete_cbk = func; + return wmi_handle; +} + +void +wmi_unified_detach(struct wmi_unified* wmi_handle) +{ + wmi_buf_t buf; + + vos_flush_work(&wmi_handle->rx_event_work); + adf_os_spin_lock_bh(&wmi_handle->eventq_lock); + buf = adf_nbuf_queue_remove(&wmi_handle->event_queue); + while (buf) { + adf_nbuf_free(buf); + buf = adf_nbuf_queue_remove(&wmi_handle->event_queue); + } + adf_os_spin_unlock_bh(&wmi_handle->eventq_lock); + if (wmi_handle != NULL) { + OS_FREE(wmi_handle); + wmi_handle = NULL; + } +} + +/** + * wmi_unified_remove_work() - detach for WMI work + * @wmi_handle: handle to WMI + * + * A function that does not fully detach WMI, but just remove work + * queue items associated with it. This is used to make sure that + * before any other processing code that may destroy related contexts + * (HTC, etc), work queue processing on WMI has already been stopped. + * + * Return: void. + */ +void +wmi_unified_remove_work(struct wmi_unified* wmi_handle) +{ + wmi_buf_t buf; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "Enter: %s", __func__); + vos_flush_work(&wmi_handle->rx_event_work); + adf_os_spin_lock_bh(&wmi_handle->eventq_lock); + buf = adf_nbuf_queue_remove(&wmi_handle->event_queue); + while (buf) { + adf_nbuf_free(buf); + buf = adf_nbuf_queue_remove(&wmi_handle->event_queue); + } + adf_os_spin_unlock_bh(&wmi_handle->eventq_lock); + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "Done: %s", __func__); +} + +void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt) +{ + struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx; + wmi_buf_t wmi_cmd_buf = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt); +#ifdef WMI_INTERFACE_EVENT_LOGGING + u_int32_t cmd_id; +#endif + + ASSERT(wmi_cmd_buf); +#ifdef WMI_INTERFACE_EVENT_LOGGING + cmd_id = WMI_GET_FIELD(adf_nbuf_data(wmi_cmd_buf), + WMI_CMD_HDR, COMMANDID); + adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock); + /* Record 16 bytes of WMI cmd tx complete data + - exclude TLV and WMI headers */ + WMI_COMMAND_TX_CMP_RECORD(cmd_id, + ((u_int32_t *)adf_nbuf_data(wmi_cmd_buf) + 2)); + adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock); +#endif + adf_nbuf_free(wmi_cmd_buf); + adf_os_mem_free(htc_pkt); + adf_os_atomic_dec(&wmi_handle->pending_cmds); +} + +int +wmi_unified_connect_htc_service(struct wmi_unified * wmi_handle, void *htc_handle) +{ + + int status; + HTC_SERVICE_CONNECT_RESP response; + HTC_SERVICE_CONNECT_REQ connect; + + OS_MEMZERO(&connect, sizeof(connect)); + OS_MEMZERO(&response, sizeof(response)); + + /* meta data is unused for now */ + connect.pMetaData = NULL; + connect.MetaDataLength = 0; + /* these fields are the same for all service endpoints */ + connect.EpCallbacks.pContext = wmi_handle; + connect.EpCallbacks.EpTxCompleteMultiple = NULL /* Control path completion ar6000_tx_complete */; + connect.EpCallbacks.EpRecv = wmi_control_rx /* Control path rx */; + connect.EpCallbacks.EpRecvRefill = NULL /* ar6000_rx_refill */; + connect.EpCallbacks.EpSendFull = NULL /* ar6000_tx_queue_full */; + connect.EpCallbacks.EpTxComplete = wmi_htc_tx_complete /* ar6000_tx_queue_full */; + + /* connect to control service */ + connect.ServiceID = WMI_CONTROL_SVC; + + if ((status = HTCConnectService(htc_handle, &connect, &response)) != EOK) + { + printk(" Failed to connect to WMI CONTROL service status:%d \n", status); + return -1;; + } + wmi_handle->wmi_endpoint_id = response.Endpoint; + wmi_handle->htc_handle = htc_handle; + wmi_handle->max_msg_len = response.MaxMsgLength; + + return EOK; +} + +int wmi_get_host_credits(wmi_unified_t wmi_handle) +{ + int host_credits; + + HTCGetControlEndpointTxHostCredits(wmi_handle->htc_handle, + &host_credits); + return host_credits; +} + +int wmi_get_pending_cmds(wmi_unified_t wmi_handle) +{ + return adf_os_atomic_read(&wmi_handle->pending_cmds); +} + +void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val) +{ + adf_os_atomic_set(&wmi_handle->is_target_suspended, val); +} + +/** + * wmi_set_tgt_assert() - set target assert configuration + * @wmi_handle: Pointer to WMI handle + * @val: Target assert config value + * + * Return: none + */ +void wmi_set_tgt_assert(wmi_unified_t wmi_handle, bool val) +{ + wmi_handle->tgt_force_assert_enable = val; +} + +#ifdef FEATURE_RUNTIME_PM +void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val) +{ + adf_os_atomic_set(&wmi_handle->runtime_pm_inprogress, val); +} +#endif + +#ifdef FEATURE_WLAN_D0WOW +void wmi_set_d0wow_flag(wmi_unified_t wmi_handle, A_BOOL flag) +{ + tp_wma_handle wma = wmi_handle->scn_handle; + struct ol_softc *scn = + vos_get_context(VOS_MODULE_ID_HIF, wma->vos_context); + + if (NULL == scn) { + WMA_LOGE("%s: Failed to get HIF context", __func__); + return; + } + adf_os_atomic_set(&scn->hif_sc->in_d0wow, flag); +} + +A_BOOL wmi_get_d0wow_flag(wmi_unified_t wmi_handle) +{ + tp_wma_handle wma = wmi_handle->scn_handle; + struct ol_softc *scn = + vos_get_context(VOS_MODULE_ID_HIF, wma->vos_context); + + if (NULL == scn) { + WMA_LOGE("%s: Failed to get HIF context", __func__); + return -EINVAL; + } + + return adf_os_atomic_read(&scn->hif_sc->in_d0wow); +} +#endif + +void wmi_tag_crash_inject(wmi_unified_t wmi_handle, A_BOOL flag) +{ + wmi_handle->tag_crash_inject = flag; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h new file mode 100644 index 000000000000..955e1d528a69 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * This file contains the API definitions for the Unified Wireless Module Interface (WMI). + */ +#ifndef _WMI_UNIFIED_PRIV_H_ +#define _WMI_UNIFIED_PRIV_H_ +#include +#include "a_types.h" +#include "wmi.h" +#include "wmi_unified.h" +#include "adf_os_atomic.h" + +#define WMI_UNIFIED_MAX_EVENT 0x100 +#define WMI_MAX_CMDS 1024 + +typedef adf_nbuf_t wmi_buf_t; + +#ifdef WMI_INTERFACE_EVENT_LOGGING + +#define WMI_EVENT_DEBUG_MAX_ENTRY (1024) + +struct wmi_command_debug{ + u_int32_t command; + u_int32_t data[4]; /*16 bytes of WMI cmd excluding TLV and WMI headers*/ + u_int64_t time; +}; + +struct wmi_event_debug{ + u_int32_t event; + u_int32_t data[4]; /*16 bytes of WMI event data excluding TLV header*/ + u_int64_t time; +}; + +#endif /*WMI_INTERFACE_EVENT_LOGGING*/ + + +#ifdef WLAN_OPEN_SOURCE +struct fwdebug { + struct sk_buff_head fwlog_queue; + struct completion fwlog_completion; + A_BOOL fwlog_open; +}; +#endif /* WLAN_OPEN_SOURCE */ + +struct wmi_unified { + ol_scn_t scn_handle; /* handle to device */ + adf_os_atomic_t pending_cmds; + HTC_ENDPOINT_ID wmi_endpoint_id; + uint16_t max_msg_len; + WMI_EVT_ID event_id[WMI_UNIFIED_MAX_EVENT]; + wmi_unified_event_handler event_handler[WMI_UNIFIED_MAX_EVENT]; + u_int32_t max_event_idx; + void *htc_handle; + adf_os_spinlock_t eventq_lock; + adf_nbuf_queue_t event_queue; + struct work_struct rx_event_work; +#ifdef WLAN_OPEN_SOURCE + struct fwdebug dbglog; + struct dentry *debugfs_phy; +#endif /* WLAN_OPEN_SOURCE */ + +#ifdef WMI_INTERFACE_EVENT_LOGGING + adf_os_spinlock_t wmi_record_lock; +#endif /*WMI_INTERFACE_EVENT_LOGGING*/ + + adf_os_atomic_t is_target_suspended; +#ifdef FEATURE_RUNTIME_PM + adf_os_atomic_t runtime_pm_inprogress; +#endif + bool tgt_force_assert_enable; + A_BOOL tag_crash_inject; + void (*wma_wow_tx_complete_cbk)(ol_scn_t scn_handle); +}; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/btcApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/btcApi.h new file mode 100644 index 000000000000..9a06f7c715a1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/btcApi.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: btcApi.h +* +* Description: BTC Events Layer API definitions. +* + +* +******************************************************************************/ + +#ifndef __BTC_API_H__ +#define __BTC_API_H__ + +#include "vos_types.h" +#include "vos_timer.h" +#include "vos_nvitem.h" + +#define BT_INVALID_CONN_HANDLE (0xFFFF) /**< Invalid connection handle */ + +/* ACL and Sync connection attempt results */ +#define BT_CONN_STATUS_FAIL (0) /**< Connection failed */ +#define BT_CONN_STATUS_SUCCESS (1) /**< Connection successful */ +#define BT_CONN_STATUS_MAX (2) /**< This and beyond are invalid values */ + +/** ACL and Sync link types + These must match the Bluetooth Spec! +*/ +#define BT_SCO (0) /**< SCO Link */ +#define BT_ACL (1) /**< ACL Link */ +#define BT_eSCO (2) /**< eSCO Link */ +#define BT_LINK_TYPE_MAX (3) /**< This value and higher are invalid */ + +/** ACL link modes + These must match the Bluetooth Spec! +*/ +#define BT_ACL_ACTIVE (0) /**< Active mode */ +#define BT_ACL_HOLD (1) /**< Hold mode */ +#define BT_ACL_SNIFF (2) /**< Sniff mode */ +#define BT_ACL_PARK (3) /**< Park mode */ +#define BT_ACL_MODE_MAX (4) /**< This value and higher are invalid */ + +/** + * A2DP BTC max no of BT sub intervals + * + * **/ +#define BTC_MAX_NUM_ACL_BT_SUB_INTS (7) + +/** BTC Executions Modes allowed to be set by user +*/ +#define BTC_SMART_COEXISTENCE (0) /** BTC Mapping Layer decides whats best */ +#define BTC_WLAN_ONLY (1) /** WLAN takes all mode */ +#define BTC_PTA_ONLY (2) /** Allow only 3 wire protocol in H/W */ +#define BTC_SMART_MAX_WLAN (3) /** BTC Mapping Layer decides whats best, WLAN weighted */ +#define BTC_SMART_MAX_BT (4) /** BTC Mapping Layer decides whats best, BT weighted */ +#define BTC_SMART_BT_A2DP (5) /** BTC Mapping Layer decides whats best, balanced + BT A2DP weight */ +#define BT_EXEC_MODE_MAX (6) /** This and beyond are invalid values */ + +/** Bitmaps used for maintaining various BT events that requires + enough time to complete such that it might require disbling of + heartbeat monitoring to avoid WLAN link loss with the AP +*/ +#define BT_INQUIRY_STARTED (1<<0) +#define BT_PAGE_STARTED (1<<1) +#define BT_CREATE_ACL_CONNECTION_STARTED (1<<2) +#define BT_CREATE_SYNC_CONNECTION_STARTED (1<<3) + +/** Maximum time duration in milliseconds between a specific BT start event and its + respective stop event, before it can be declared timed out on receiving the stop event. +*/ +#define BT_MAX_EVENT_DONE_TIMEOUT 45000 + + +/* + To suppurt multiple SCO connections for BT+UAPSD work +*/ +#define BT_MAX_SCO_SUPPORT 3 +#define BT_MAX_ACL_SUPPORT 3 +#define BT_MAX_DISCONN_SUPPORT (BT_MAX_SCO_SUPPORT+BT_MAX_ACL_SUPPORT) +#define BT_MAX_NUM_EVENT_ACL_DEFERRED 4 //We may need to defer these many BT events for ACL +#define BT_MAX_NUM_EVENT_SCO_DEFERRED 4 //We may need to defer these many BT events for SYNC + +/* + * Number of mws coex configurations + */ +#define MWS_COEX_MAX_CONFIG 6 + +/** Enumeration of all the different kinds of BT events +*/ +typedef enum eSmeBtEventType +{ + BT_EVENT_DEVICE_SWITCHED_ON, + BT_EVENT_DEVICE_SWITCHED_OFF, + BT_EVENT_INQUIRY_STARTED, + BT_EVENT_INQUIRY_STOPPED, + BT_EVENT_INQUIRY_SCAN_STARTED, + BT_EVENT_INQUIRY_SCAN_STOPPED, + BT_EVENT_PAGE_STARTED, + BT_EVENT_PAGE_STOPPED, + BT_EVENT_PAGE_SCAN_STARTED, + BT_EVENT_PAGE_SCAN_STOPPED, + BT_EVENT_CREATE_ACL_CONNECTION, + BT_EVENT_ACL_CONNECTION_COMPLETE, + BT_EVENT_CREATE_SYNC_CONNECTION, + BT_EVENT_SYNC_CONNECTION_COMPLETE, + BT_EVENT_SYNC_CONNECTION_UPDATED, + BT_EVENT_DISCONNECTION_COMPLETE, + BT_EVENT_MODE_CHANGED, + BT_EVENT_A2DP_STREAM_START, + BT_EVENT_A2DP_STREAM_STOP, + BT_EVENT_TYPE_MAX, //This and beyond are invalid values +} tSmeBtEventType; + +/**Data structure that specifies the needed event parameters for + BT_EVENT_CREATE_ACL_CONNECTION and BT_EVENT_ACL_CONNECTION_COMPLETE +*/ +typedef struct sSmeBtAclConnectionParam +{ + v_U8_t bdAddr[6]; + v_U16_t connectionHandle; + v_U8_t status; +} tSmeBtAclConnectionParam, *tpSmeBtAclConnectionParam; + +/** Data structure that specifies the needed event parameters for + BT_EVENT_CREATE_SYNC_CONNECTION, BT_EVENT_SYNC_CONNECTION_COMPLETE + and BT_EVENT_SYNC_CONNECTION_UPDATED +*/ +typedef struct sSmeBtSyncConnectionParam +{ + v_U8_t bdAddr[6]; + v_U16_t connectionHandle; + v_U8_t status; + v_U8_t linkType; + v_U8_t scoInterval; //units in number of 625us slots + v_U8_t scoWindow; //units in number of 625us slots + v_U8_t retransmisisonWindow; //units in number of 625us slots +} tSmeBtSyncConnectionParam, *tpSmeBtSyncConnectionParam; + +typedef struct sSmeBtSyncUpdateHist +{ + tSmeBtSyncConnectionParam btSyncConnection; + v_BOOL_t fValid; +} tSmeBtSyncUpdateHist, *tpSmeBtSyncUpdateHist; + +/**Data structure that specifies the needed event parameters for + BT_EVENT_MODE_CHANGED +*/ +typedef struct sSmeBtAclModeChangeParam +{ + v_U16_t connectionHandle; + v_U8_t mode; +} tSmeBtAclModeChangeParam, *tpSmeBtAclModeChangeParam; + +/*Data structure that specifies the needed event parameters for + BT_EVENT_DISCONNECTION_COMPLETE +*/ +typedef struct sSmeBtDisconnectParam +{ + v_U16_t connectionHandle; +} tSmeBtDisconnectParam, *tpSmeBtDisconnectParam; + +/*Data structure that specifies the needed event parameters for + BT_EVENT_A2DP_STREAM_START + BT_EVENT_A2DP_STREAM_STOP +*/ +typedef struct sSmeBtA2DPParam +{ + v_U8_t bdAddr[6]; +} tSmeBtA2DPParam, *tpSmeBtA2DPParam; + + +/** Generic Bluetooth Event structure for BTC +*/ +typedef struct sSmeBtcBtEvent +{ + tSmeBtEventType btEventType; + union + { + v_U8_t bdAddr[6]; /**< For events with only a BT Addr in event_data */ + tSmeBtAclConnectionParam btAclConnection; + tSmeBtSyncConnectionParam btSyncConnection; + tSmeBtDisconnectParam btDisconnect; + tSmeBtAclModeChangeParam btAclModeChange; + }uEventParam; +} tSmeBtEvent, *tpSmeBtEvent; + + +/** Data structure that specifies the BTC Configuration parameters +*/ +typedef struct sSmeBtcConfig +{ + v_U8_t btcExecutionMode; + v_U32_t mwsCoexConfig[MWS_COEX_MAX_CONFIG]; +} tSmeBtcConfig, *tpSmeBtcConfig; + + +typedef struct sSmeBtAclModeChangeEventHist +{ + tSmeBtAclModeChangeParam btAclModeChange; + v_BOOL_t fValid; +} tSmeBtAclModeChangeEventHist, *tpSmeBtAclModeChangeEventHist; + +typedef struct sSmeBtAclEventHist +{ + //At most, cached events are COMPLETION, DISCONNECT, CREATION, COMPLETION + tSmeBtEventType btEventType[BT_MAX_NUM_EVENT_ACL_DEFERRED]; + tSmeBtAclConnectionParam btAclConnection[BT_MAX_NUM_EVENT_ACL_DEFERRED]; + //bNextEventIdx == 0 meaning no event cached here + tANI_U8 bNextEventIdx; +} tSmeBtAclEventHist, *tpSmeBtAclEventHist; + +typedef struct sSmeBtSyncEventHist +{ + //At most, cached events are COMPLETION, DISCONNECT, CREATION, COMPLETION + tSmeBtEventType btEventType[BT_MAX_NUM_EVENT_SCO_DEFERRED]; + tSmeBtSyncConnectionParam btSyncConnection[BT_MAX_NUM_EVENT_SCO_DEFERRED]; + //bNextEventIdx == 0 meaning no event cached here + tANI_U8 bNextEventIdx; +} tSmeBtSyncEventHist, *tpSmeBtSyncEventHist; + +typedef struct sSmeBtDisconnectEventHist +{ + tSmeBtDisconnectParam btDisconnect; + v_BOOL_t fValid; +} tSmeBtDisconnectEventHist, *tpSmeBtDisconnectEventHist; + + +/* + Data structure for the history of BT events +*/ +typedef struct sSmeBtcEventHist +{ + tSmeBtSyncEventHist btSyncConnectionEvent[BT_MAX_SCO_SUPPORT]; + tSmeBtAclEventHist btAclConnectionEvent[BT_MAX_ACL_SUPPORT]; + tSmeBtAclModeChangeEventHist btAclModeChangeEvent[BT_MAX_ACL_SUPPORT]; + tSmeBtDisconnectEventHist btDisconnectEvent[BT_MAX_DISCONN_SUPPORT]; + tSmeBtSyncUpdateHist btSyncUpdateEvent[BT_MAX_SCO_SUPPORT]; + int nInquiryEvent; //>0 for # of outstanding inquiriy starts + //<0 for # of outstanding inquiry stops + //0 == no inquiry event + int nPageEvent; //>0 for # of outstanding page starts + //<0 for # of outstanding page stops + //0 == no page event + v_BOOL_t fA2DPStarted; + v_BOOL_t fA2DPStopped; +} tSmeBtcEventHist, *tpSmeBtcEventHist; + +typedef struct sSmeBtcEventReplay +{ + tSmeBtcEventHist btcEventHist; + v_BOOL_t fBTSwitchOn; + v_BOOL_t fBTSwitchOff; + //This is not directly tied to BT event so leave it alone when processing BT events + v_BOOL_t fRestoreHBMonitor; +} tSmeBtcEventReplay, *tpSmeBtcEventReplay; + +typedef struct sSmeBtcInfo +{ + tSmeBtcConfig btcConfig; + v_BOOL_t btcReady; + v_U8_t btcEventState; + v_U8_t btcHBActive; /* Is HB currently active */ + v_U8_t btcHBCount; /* default HB count */ + vos_timer_t restoreHBTimer; /* Timer to restore heart beat */ + tSmeBtcEventReplay btcEventReplay; + v_BOOL_t fReplayBTEvents; + v_BOOL_t btcUapsdOk; /* Indicate whether BTC is ok with UAPSD */ + v_BOOL_t fA2DPTrafStop;/*flag to check A2DP_STOP event has come before MODE_CHANGED*/ + v_U16_t btcScoHandles[BT_MAX_SCO_SUPPORT]; /* Handles for SCO, if any*/ + v_BOOL_t fA2DPUp; /*remember whether A2DP is in session*/ + v_BOOL_t btcScanCompromise; + v_U8_t btcBssfordisableaggr[VOS_MAC_ADDRESS_LEN]; +} tSmeBtcInfo, *tpSmeBtcInfo; + + +/** Routine definitions +*/ + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT +VOS_STATUS btcOpen (tHalHandle hHal); +VOS_STATUS btcClose (tHalHandle hHal); +VOS_STATUS btcReady (tHalHandle hHal); +VOS_STATUS btcSendCfgMsg(tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig); +VOS_STATUS btcSignalBTEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent); +VOS_STATUS btcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig); +VOS_STATUS btcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig); +/* + Caller can check whether BTC's current event allows UAPSD. This doesn't affect + BMPS. + return: VOS_TRUE -- BTC is ready for UAPSD + VOS_FALSE -- certain BT event is active, cannot enter UAPSD +*/ +v_BOOL_t btcIsReadyForUapsd( tHalHandle hHal ); +eHalStatus btcHandleCoexInd(tHalHandle hHal, void* pMsg); +#endif /* End of WLAN_MDM_CODE_REDUCTION_OPT */ + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/ccmApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/ccmApi.h new file mode 100644 index 000000000000..ddffaf0de083 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/ccmApi.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file ccmApi.h + + \brief Exports and types for the Common Config Module (CCM) + + $Id$This file contains all the interfaces for thge Platform Abstration Layer + functions. It is intended to be included in all modules that are using + the PAL interfaces. + + ========================================================================== */ +#ifndef CCMAPI_H__ +#define CCMAPI_H__ + +#include "wniCfgSta.h" +#include "halTypes.h" + +#define CCM_IS_RESULT_SUCCESS(result) (WNI_CFG_SUCCESS == (result) ||\ + WNI_CFG_NEED_RESTART == (result) || \ + WNI_CFG_NEED_RELOAD == (result)) + +#define CCM_INTEGER_TYPE 0 +#define CCM_STRING_TYPE 1 + +typedef void (*tCcmCfgSetCallback)(tHalHandle hHal, tANI_S32 result) ; + +typedef enum { + eCCM_STOPPED, + eCCM_STARTED, + eCCM_REQ_SENT, + eCCM_REQ_QUEUED, + eCCM_REQ_DONE, +} eCcmState ; + +/* We do not use Linux's list facility */ +typedef struct cfgreq { + struct cfgreq *next ; + tANI_U16 cfgId ; + tANI_U8 type ; + tANI_U8 state : 7 ; + tANI_U8 toBeSaved : 1 ; + tANI_S32 length ; + void *ccmPtr; + tANI_U32 ccmValue; + tCcmCfgSetCallback callback; + void *done ; +} tCfgReq ; + +typedef struct { + tANI_U16 started : 1 ; + tANI_U16 in_progress : 1 ; + tANI_U16 reserved : 14 ; + tANI_S16 nr_param ; + tANI_U32 result ; + tCcmCfgSetCallback callback ; + void *done ; +} tCfgReplay ; + +struct ccmlink { + tCfgReq *head; + tCfgReq *tail; +} ; + +typedef struct { + struct ccmlink reqQ ; + eCcmState state ; + tCfgReq * comp[CFG_PARAM_MAX_NUM] ; + tCfgReplay replay ; + void *lock; +} tCcm ; + +void ccmCfgCnfMsgHandler(tHalHandle hHal, void *msg) ; +eHalStatus ccmOpen(tHalHandle hHal) ; +eHalStatus ccmClose(tHalHandle hHal) ; +void ccmStart(tHalHandle hHal) ; +void ccmStop(tHalHandle hHal) ; +//If callback is NULL, the API is not serialized for the CFGs +eHalStatus ccmCfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) ; +//If callback is NULL, the API is not serialized for the CFGs +eHalStatus ccmCfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr, tANI_U32 length, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) ; +eHalStatus ccmCfgUpdate(tHalHandle hHal, tCcmCfgSetCallback callback) ; +eHalStatus ccmCfgGetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 *pValue) ; +eHalStatus ccmCfgGetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pBuf, tANI_U32 *pLength) ; + +void ccmDumpInit(tHalHandle hHal); + +#endif /*CCMAPI_H__*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h new file mode 100644 index 000000000000..86635069c0f6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h @@ -0,0 +1,1864 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csrApi.h + + Exports and types for the Common Scan and Roaming Module interfaces. +========================================================================== */ +#ifndef CSRAPI_H__ +#define CSRAPI_H__ + +#include "sirApi.h" +#include "sirMacProtDef.h" +#include "csrLinkList.h" + +typedef enum +{ + eCSR_AUTH_TYPE_NONE, //never used + // MAC layer authentication types + eCSR_AUTH_TYPE_OPEN_SYSTEM, + eCSR_AUTH_TYPE_SHARED_KEY, + eCSR_AUTH_TYPE_AUTOSWITCH, + + // Upper layer authentication types + eCSR_AUTH_TYPE_WPA, + eCSR_AUTH_TYPE_WPA_PSK, + eCSR_AUTH_TYPE_WPA_NONE, + + eCSR_AUTH_TYPE_RSN, + eCSR_AUTH_TYPE_RSN_PSK, +#if defined WLAN_FEATURE_VOWIFI_11R + eCSR_AUTH_TYPE_FT_RSN, + eCSR_AUTH_TYPE_FT_RSN_PSK, +#endif +#ifdef FEATURE_WLAN_WAPI + eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE, + eCSR_AUTH_TYPE_WAPI_WAI_PSK, +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_ESE + eCSR_AUTH_TYPE_CCKM_WPA, + eCSR_AUTH_TYPE_CCKM_RSN, +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_11W + eCSR_AUTH_TYPE_RSN_PSK_SHA256, + eCSR_AUTH_TYPE_RSN_8021X_SHA256, +#endif + eCSR_NUM_OF_SUPPORT_AUTH_TYPE, + eCSR_AUTH_TYPE_FAILED = 0xff, + eCSR_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED, + +}eCsrAuthType; + + +typedef enum +{ + eCSR_ENCRYPT_TYPE_NONE, + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY, + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY, + + eCSR_ENCRYPT_TYPE_WEP40, + eCSR_ENCRYPT_TYPE_WEP104, + eCSR_ENCRYPT_TYPE_TKIP, + eCSR_ENCRYPT_TYPE_AES, +#ifdef FEATURE_WLAN_WAPI + eCSR_ENCRYPT_TYPE_WPI, //WAPI +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_ESE + eCSR_ENCRYPT_TYPE_KRK, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + eCSR_ENCRYPT_TYPE_BTK, +#endif +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_11W + //11w BIP + eCSR_ENCRYPT_TYPE_AES_CMAC, +#endif + eCSR_ENCRYPT_TYPE_ANY, + eCSR_NUM_OF_ENCRYPT_TYPE = eCSR_ENCRYPT_TYPE_ANY, + + eCSR_ENCRYPT_TYPE_FAILED = 0xff, + eCSR_ENCRYPT_TYPE_UNKNOWN = eCSR_ENCRYPT_TYPE_FAILED, + +}eCsrEncryptionType; + +/*--------------------------------------------------------------------------- + Enumeration of the various Security types +---------------------------------------------------------------------------*/ +typedef enum +{ + eCSR_SECURITY_TYPE_WPA, + eCSR_SECURITY_TYPE_RSN, +#ifdef FEATURE_WLAN_WAPI + eCSR_SECURITY_TYPE_WAPI, +#endif /* FEATURE_WLAN_WAPI */ + eCSR_SECURITY_TYPE_UNKNOWN, + +}eCsrSecurityType; + +typedef enum { + eCSR_DOT11_MODE_abg = 0x0001, /* 11a/b/g only, no HT, no proprietary */ + eCSR_DOT11_MODE_11a = 0x0002, + eCSR_DOT11_MODE_11b = 0x0004, + eCSR_DOT11_MODE_11g = 0x0008, + eCSR_DOT11_MODE_11n = 0x0010, + eCSR_DOT11_MODE_11g_ONLY = 0x0020, + eCSR_DOT11_MODE_11n_ONLY = 0x0040, + eCSR_DOT11_MODE_11b_ONLY = 0x0080, +#ifdef WLAN_FEATURE_11AC + eCSR_DOT11_MODE_11ac = 0x0100, + eCSR_DOT11_MODE_11ac_ONLY = 0x0200, +#endif + /* + * This is for WIFI test. It is same as eWNIAPI_MAC_PROTOCOL_ALL + * except when it starts IBSS in 11B of 2.4GHz + * It is for CSR internal use + */ + eCSR_DOT11_MODE_AUTO = 0x0400, + + eCSR_NUM_PHY_MODE = 16, /* specify the number of maximum bits for phyMode */ + +} eCsrPhyMode; + +typedef tANI_U8 tCsrBssid[VOS_MAC_ADDR_SIZE]; + +typedef enum +{ + eCSR_BSS_TYPE_NONE, + eCSR_BSS_TYPE_INFRASTRUCTURE, + eCSR_BSS_TYPE_INFRA_AP, // SoftAP AP + eCSR_BSS_TYPE_IBSS, // an IBSS network we will NOT start + eCSR_BSS_TYPE_START_IBSS, // an IBSS network we will start if no partners detected. + eCSR_BSS_TYPE_WDS_AP, // BT-AMP AP + eCSR_BSS_TYPE_WDS_STA, // BT-AMP station + eCSR_BSS_TYPE_ANY, // any BSS type (IBSS or Infrastructure). +}eCsrRoamBssType; + + + +typedef enum { + eCSR_SCAN_REQUEST_11D_SCAN = 1, + eCSR_SCAN_REQUEST_FULL_SCAN, + eCSR_SCAN_IDLE_MODE_SCAN, + eCSR_SCAN_HO_BG_SCAN, // bg scan request in NRT & RT Handoff sub-states + eCSR_SCAN_HO_PROBE_SCAN, // directed probe on an entry from the candidate list + eCSR_SCAN_HO_NT_BG_SCAN, // bg scan request in NT sub-state + eCSR_SCAN_P2P_DISCOVERY, + + eCSR_SCAN_SOFTAP_CHANNEL_RANGE, + eCSR_SCAN_P2P_FIND_PEER, +}eCsrRequestType; + +typedef enum { + eCSR_SCAN_RESULT_GET = 0, + eCSR_SCAN_RESULT_FLUSH = 1, //to delete all cached scan results +}eCsrScanResultCmd; + +typedef enum +{ + eCSR_SCAN_SUCCESS, + eCSR_SCAN_FAILURE, + eCSR_SCAN_ABORT, + eCSR_SCAN_FOUND_PEER, +}eCsrScanStatus; + +/* Reason to abort the scan + * The reason can used later to decide whether to update the scan results + * to upper layer or not + */ +typedef enum +{ + eCSR_SCAN_ABORT_DEFAULT, + eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE, //Scan aborted due to band change +}eCsrAbortReason; + +typedef enum +{ + eCSR_BW_20MHz_VAL = 20, + eCSR_BW_40MHz_VAL = 40, + eCSR_BW_80MHz_VAL = 80, + eCSR_BW_160MHz_VAL = 160 +}eCSR_BW_Val; + +typedef enum +{ + eCSR_INI_SINGLE_CHANNEL_CENTERED = 0, + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY, + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY, +#ifdef WLAN_FEATURE_11AC + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED, + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED, + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED, + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW, + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW, + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH, + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH, +#endif + eCSR_INI_CHANNEL_BONDING_STATE_MAX +}eIniChanBondState; + + +#define CSR_RSN_PMKID_SIZE 16 +#define CSR_MAX_PMKID_ALLOWED 32 +#define CSR_WEP40_KEY_LEN 5 +#define CSR_WEP104_KEY_LEN 13 +#define CSR_TKIP_KEY_LEN 32 +#define CSR_AES_KEY_LEN 16 +#define CSR_MAX_TX_POWER ( WNI_CFG_CURRENT_TX_POWER_LEVEL_STAMAX ) +#define CSR_MAX_RSC_LEN 16 +#ifdef FEATURE_WLAN_WAPI +#define CSR_WAPI_BKID_SIZE 16 +#define CSR_MAX_BKID_ALLOWED 16 +#define CSR_WAPI_KEY_LEN 32 +#define CSR_MAX_KEY_LEN ( CSR_WAPI_KEY_LEN ) //longest one is for WAPI +#else +#define CSR_MAX_KEY_LEN ( CSR_TKIP_KEY_LEN ) //longest one is for TKIP +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_ESE +#define CSR_KRK_KEY_LEN 16 +#endif + + +typedef struct tagCsrChannelInfo +{ + tANI_U8 numOfChannels; + tANI_U8 *ChannelList; //it will be an array of channels +}tCsrChannelInfo, *tpCsrChannelInfo; + +typedef struct tagCsrSSIDInfo +{ + tSirMacSSid SSID; + tANI_BOOLEAN handoffPermitted; + tANI_BOOLEAN ssidHidden; +}tCsrSSIDInfo; + +typedef struct tagCsrSSIDs +{ + tANI_U32 numOfSSIDs; + tCsrSSIDInfo *SSIDList; //To be allocated for array of SSIDs +}tCsrSSIDs; + +typedef struct tagCsrBSSIDs +{ + tANI_U32 numOfBSSIDs; + tCsrBssid *bssid; +}tCsrBSSIDs; + +typedef struct tagCsrStaParams +{ + tANI_U16 capability; + tANI_U8 extn_capability[SIR_MAC_MAX_EXTN_CAP]; + tANI_U8 supported_rates_len; + tANI_U8 supported_rates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; + tSirHTCap HTCap; + tANI_U8 vhtcap_present; + tSirVHTCap VHTCap; + tANI_U8 uapsd_queues; + tANI_U8 max_sp; + tANI_U8 supported_channels_len; + tANI_U8 supported_channels[SIR_MAC_MAX_SUPP_CHANNELS]; + tANI_U8 supported_oper_classes_len; + tANI_U8 supported_oper_classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +}tCsrStaParams; + +typedef struct tagCsrScanRequest +{ + tSirScanType scanType; + tCsrBssid bssid; + eCsrRoamBssType BSSType; + tCsrSSIDs SSIDs; + tCsrChannelInfo ChannelInfo; + tANI_U32 minChnTime; //in units of milliseconds + tANI_U32 maxChnTime; //in units of milliseconds + tANI_U32 minChnTimeBtc; //in units of milliseconds + tANI_U32 maxChnTimeBtc; //in units of milliseconds + /* In units of milliseconds, ignored when not connected */ + uint32_t restTime; + /* In units of milliseconds, ignored when not connected */ + uint32_t min_rest_time; + /* In units of milliseconds, ignored when not connected */ + uint32_t idle_time; + + tANI_U32 uIEFieldLen; + tANI_U8 *pIEField; + eCsrRequestType requestType; //11d scan or full scan + tANI_BOOLEAN p2pSearch; + tANI_BOOLEAN skipDfsChnlInP2pSearch; +}tCsrScanRequest; + +typedef struct tagCsrBGScanRequest +{ + tSirScanType scanType; + tSirMacSSid SSID; + tCsrChannelInfo ChannelInfo; + tANI_U32 scanInterval; //in units of milliseconds + tANI_U32 minChnTime; //in units of milliseconds + tANI_U32 maxChnTime; //in units of milliseconds + tANI_U32 minChnTimeBtc; //in units of milliseconds + tANI_U32 maxChnTimeBtc; //in units of milliseconds + /* In units of milliseconds, ignored when not connected */ + uint32_t restTime; + /* In units of milliseconds, ignored when not connected */ + uint32_t min_rest_time; + /* In units of milliseconds, ignored when not connected */ + uint32_t idle_time; + tANI_U32 throughputImpact; //specify whether BG scan cares about impacting throughput //ignored when not connected + tCsrBssid bssid; //how to use it?? Apple +}tCsrBGScanRequest, *tpCsrBGScanRequest; + + +typedef struct tagCsrScanResultInfo +{ + //Carry the IEs for the current BSSDescription. A pointer to tDot11fBeaconIEs. Maybe NULL for start BSS. + void *pvIes; + tAniSSID ssId; + v_TIME_t timer; // timer is variable which is used for hidden SSID's timer value + //This member must be the last in the structure because the end of tSirBssDescription is an + // array with nonknown size at this time + tSirBssDescription BssDescriptor; +}tCsrScanResultInfo; + +typedef struct tagCsrEncryptionList +{ + + tANI_U32 numEntries; + eCsrEncryptionType encryptionType[eCSR_NUM_OF_ENCRYPT_TYPE]; + +}tCsrEncryptionList, *tpCsrEncryptionList; + +typedef struct tagCsrAuthList +{ + tANI_U32 numEntries; + eCsrAuthType authType[eCSR_NUM_OF_SUPPORT_AUTH_TYPE]; +}tCsrAuthList, *tpCsrAuthList; + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct tagCsrMobilityDomainInfo +{ + tANI_U8 mdiePresent; + tANI_U16 mobilityDomain; +} tCsrMobilityDomainInfo; +#endif + +#ifdef FEATURE_WLAN_ESE +typedef struct tagCsrEseCckmInfo +{ + tANI_U32 reassoc_req_num; + tANI_BOOLEAN krk_plumbed; + tANI_U8 krk[SIR_KRK_KEY_LEN]; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U8 btk[SIR_BTK_KEY_LEN]; +#endif +} tCsrEseCckmInfo; +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define CSR_DOT11F_IE_RSN_MAX_LEN (114) /*TODO: duplicate one in dot11f.h */ +typedef struct tagCsrEseCckmIe +{ + tANI_U8 cckmIe[CSR_DOT11F_IE_RSN_MAX_LEN]; + tANI_U8 cckmIeLen; +} tCsrEseCckmIe; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +typedef struct tagCsrScanResultFilter +{ + tCsrBSSIDs BSSIDs; //each bssid has a length of VOS_MAC_ADDR_SIZE (6) + tCsrSSIDs SSIDs; + tCsrChannelInfo ChannelInfo; + tCsrAuthList authType; + tCsrEncryptionList EncryptionType; + //eCSR_ENCRYPT_TYPE_ANY cannot be set in multicast encryption type. If caller doesn't case, + //put all supported encryption types in here + tCsrEncryptionList mcEncryptionType; + eCsrRoamBssType BSSType; + //this is a bit mask of all the needed phy mode defined in eCsrPhyMode + tANI_U32 phyMode; + //If countryCode[0] is not 0, countryCode is checked independent of fCheckUnknownCountryCode + tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN]; + tANI_U8 uapsd_mask; + /*For WPS filtering if true => auth and ecryption should be ignored*/ + tANI_BOOLEAN bWPSAssociation; + tANI_BOOLEAN bOSENAssociation; +#if defined WLAN_FEATURE_VOWIFI + /*For measurement reports --> if set, only SSID, BSSID and channel is considered for filtering.*/ + tANI_BOOLEAN fMeasurement; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsrMobilityDomainInfo MDID; +#endif + tANI_BOOLEAN p2pResult; +#ifdef WLAN_FEATURE_11W + // Management Frame Protection + tANI_BOOLEAN MFPEnabled; + tANI_U8 MFPRequired; + tANI_U8 MFPCapable; +#endif + /* The following flag is used to distinguish the + * roaming case while building the scan filter and + * applying it on to the scan results. This is mainly + * used to support whitelist ssid feature. + */ + uint8_t scan_filter_for_roam; +}tCsrScanResultFilter; + + +typedef struct sCsrChnPower_ +{ + tANI_U8 firstChannel; + tANI_U8 numChannels; + tANI_U8 maxtxPower; +}sCsrChnPower; + + +typedef struct sCsrChannel_ +{ + tANI_U8 numChannels; + tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +}sCsrChannel; + + +typedef struct tagCsr11dinfo +{ + sCsrChannel Channels; + tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN+1]; + //max power channel list + sCsrChnPower ChnPower[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +}tCsr11dinfo; + + +typedef enum +{ + eCSR_ROAM_CANCELLED = 1, + //this mean error happens before association_start or roaming_start is called. + eCSR_ROAM_FAILED, + //a CSR trigger roaming operation starts, callback may get a pointer to tCsrConnectedProfile + eCSR_ROAM_ROAMING_START, + //a CSR trigger roaming operation is completed + eCSR_ROAM_ROAMING_COMPLETION, + //Connection completed status. + eCSR_ROAM_CONNECT_COMPLETION, + //an association or start_IBSS operation starts, + //callback may get a pointer to tCsrRoamProfile and a pointer to tSirBssDescription + eCSR_ROAM_ASSOCIATION_START, + //a roaming operation is finish, see eCsrRoamResult for + //possible data passed back + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_DISASSOCIATED, + eCSR_ROAM_ASSOCIATION_FAILURE, + //when callback with this flag. callback gets a pointer to the BSS desc. + eCSR_ROAM_SHOULD_ROAM, + //A new candidate for PMKID is found + eCSR_ROAM_SCAN_FOUND_NEW_BSS, + //CSR is done lostlink roaming and still cannot reconnect + eCSR_ROAM_LOSTLINK, + //a link lost is detected. CSR starts roaming. + eCSR_ROAM_LOSTLINK_DETECTED, + //TKIP MIC error detected, callback gets a pointer to tpSirSmeMicFailureInd + eCSR_ROAM_MIC_ERROR_IND, + eCSR_ROAM_IBSS_IND, //IBSS indications. + //Update the connection status, useful for IBSS: new peer added, network is active etc. + eCSR_ROAM_CONNECT_STATUS_UPDATE, + eCSR_ROAM_GEN_INFO, + eCSR_ROAM_SET_KEY_COMPLETE, + eCSR_ROAM_REMOVE_KEY_COMPLETE, + eCSR_ROAM_IBSS_LEAVE, //IBSS indications. + //BSS in WDS mode status indication + eCSR_ROAM_WDS_IND, + //BSS in SoftAP mode status indication + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_WPS_PBC_PROBE_REQ_IND, +#ifdef WLAN_FEATURE_VOWIFI_11R + eCSR_ROAM_FT_RESPONSE, +#endif + eCSR_ROAM_FT_START, + eCSR_ROAM_INDICATE_MGMT_FRAME, + eCSR_ROAM_REMAIN_CHAN_READY, + eCSR_ROAM_SEND_ACTION_CNF, + //this mean error happens before association_start or roaming_start is called. + eCSR_ROAM_SESSION_OPENED, + eCSR_ROAM_FT_REASSOC_FAILED, +#ifdef FEATURE_WLAN_LFR + eCSR_ROAM_PMK_NOTIFY, +#endif +#ifdef FEATURE_WLAN_LFR_METRICS + eCSR_ROAM_PREAUTH_INIT_NOTIFY, + eCSR_ROAM_PREAUTH_STATUS_SUCCESS, + eCSR_ROAM_PREAUTH_STATUS_FAILURE, + eCSR_ROAM_HANDOVER_SUCCESS, +#endif +#ifdef FEATURE_WLAN_TDLS + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND, +#endif + eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, //Disaconnect all the clients + eCSR_ROAM_SEND_P2P_STOP_BSS, //Stopbss triggered from SME due to different + // beacon interval +#ifdef WLAN_FEATURE_11W + eCSR_ROAM_UNPROT_MGMT_FRAME_IND, +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + eCSR_ROAM_TSM_IE_IND, + eCSR_ROAM_CCKM_PREAUTH_NOTIFY, + eCSR_ROAM_ESE_ADJ_AP_REPORT_IND, + eCSR_ROAM_ESE_BCN_REPORT_IND, +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + + // Radar indication from lower layers + eCSR_ROAM_DFS_RADAR_IND, + eCSR_ROAM_SET_CHANNEL_RSP, + + // Channel sw update notification + eCSR_ROAM_DFS_CHAN_SW_NOTIFY, + eCSR_ROAM_EXT_CHG_CHNL_IND, +}eRoamCmdStatus; + + +//comment inside indicates what roaming callback gets +typedef enum +{ + eCSR_ROAM_RESULT_NONE, + //this means no more action in CSR + //If roamStatus is eCSR_ROAM_ASSOCIATION_COMPLETION, tCsrRoamInfo's pBssDesc may pass back + eCSR_ROAM_RESULT_FAILURE, + //Pass back pointer to tCsrRoamInfo + eCSR_ROAM_RESULT_ASSOCIATED, + eCSR_ROAM_RESULT_NOT_ASSOCIATED, + eCSR_ROAM_RESULT_MIC_FAILURE, + eCSR_ROAM_RESULT_FORCED, + eCSR_ROAM_RESULT_DISASSOC_IND, + eCSR_ROAM_RESULT_DEAUTH_IND, + eCSR_ROAM_RESULT_CAP_CHANGED, + //This means we starts an IBSS + //tCsrRoamInfo's pBssDesc may pass back + eCSR_ROAM_RESULT_IBSS_STARTED, + //START_BSS failed + //tCsrRoamInfo's pBssDesc may pass back + eCSR_ROAM_RESULT_IBSS_START_FAILED, + eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS, + eCSR_ROAM_RESULT_IBSS_JOIN_FAILED, + eCSR_ROAM_RESULT_IBSS_CONNECT, + eCSR_ROAM_RESULT_IBSS_INACTIVE, + //If roamStatus is eCSR_ROAM_ASSOCIATION_COMPLETION + //tCsrRoamInfo's pBssDesc may pass back. and the peer's MAC address in peerMacOrBssid + //If roamStatus is eCSR_ROAM_IBSS_IND, + //the peer's MAC address in peerMacOrBssid and a beacon frame of the IBSS in pbFrames + eCSR_ROAM_RESULT_IBSS_NEW_PEER, + //Peer departed from IBSS, Callback may get a pointer tSmeIbssPeerInd in pIbssPeerInd + eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED, + //Coalescing in the IBSS network (joined an IBSS network) + //Callback pass a BSSID in peerMacOrBssid + eCSR_ROAM_RESULT_IBSS_COALESCED, + //If roamStatus is eCSR_ROAM_ROAMING_START, callback may get a pointer to tCsrConnectedProfile used to connect. + eCSR_ROAM_RESULT_IBSS_STOP, + eCSR_ROAM_RESULT_LOSTLINK, + eCSR_ROAM_RESULT_MIC_ERROR_UNICAST, + eCSR_ROAM_RESULT_MIC_ERROR_GROUP, + eCSR_ROAM_RESULT_AUTHENTICATED, + eCSR_ROAM_RESULT_NEW_RSN_BSS, +#ifdef FEATURE_WLAN_WAPI + eCSR_ROAM_RESULT_NEW_WAPI_BSS, +#endif /* FEATURE_WLAN_WAPI */ + // WDS started successfully + eCSR_ROAM_RESULT_WDS_STARTED, + // WDS start failed + eCSR_ROAM_RESULT_WDS_START_FAILED, + // WDS stopped + eCSR_ROAM_RESULT_WDS_STOPPED, + // WDS joined successfully in STA mode + eCSR_ROAM_RESULT_WDS_ASSOCIATED, + // A station joined WDS AP + eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND, + // WDS join failed in STA mode + eCSR_ROAM_RESULT_WDS_NOT_ASSOCIATED, + // WDS disassociated + eCSR_ROAM_RESULT_WDS_DISASSOCIATED, + // INFRA started successfully + eCSR_ROAM_RESULT_INFRA_STARTED, + // INFRA start failed + eCSR_ROAM_RESULT_INFRA_START_FAILED, + // INFRA stopped + eCSR_ROAM_RESULT_INFRA_STOPPED, + // A station joining INFRA AP + eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND, + // A station joined INFRA AP + eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF, + // INFRA disassociated + eCSR_ROAM_RESULT_INFRA_DISASSOCIATED, + eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND, + eCSR_ROAM_RESULT_SEND_ACTION_FAIL, + // peer rejected assoc because max assoc limit reached. callback gets pointer to peer + eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED, + //Assoc rejected due to concurrent session running on a different channel + eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL, +#ifdef FEATURE_WLAN_TDLS + eCSR_ROAM_RESULT_ADD_TDLS_PEER, + eCSR_ROAM_RESULT_UPDATE_TDLS_PEER, + eCSR_ROAM_RESULT_DELETE_TDLS_PEER, + eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND, + eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND, + eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP, + eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER, + eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN, + eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED, +#endif + + eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND, + eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS, + eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE, + eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS, + eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE, + eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND, +}eCsrRoamResult; + + + +/*---------------------------------------------------------------------------- + List of link quality indications HDD can receive from SME +-----------------------------------------------------------------------------*/ +typedef enum +{ + eCSR_ROAM_LINK_QUAL_MIN_IND = -1, + + eCSR_ROAM_LINK_QUAL_POOR_IND = 0, /* bad link */ + eCSR_ROAM_LINK_QUAL_GOOD_IND = 1, /* acceptable for voice */ + eCSR_ROAM_LINK_QUAL_VERY_GOOD_IND = 2, /* suitable for voice */ + eCSR_ROAM_LINK_QUAL_EXCELLENT_IND = 3, /* suitable for voice */ + + eCSR_ROAM_LINK_QUAL_MAX_IND /* invalid value */ + +} eCsrRoamLinkQualityInd; + +typedef enum +{ + eCSR_DISCONNECT_REASON_UNSPECIFIED = 0, + eCSR_DISCONNECT_REASON_MIC_ERROR, + eCSR_DISCONNECT_REASON_DISASSOC, + eCSR_DISCONNECT_REASON_DEAUTH, + eCSR_DISCONNECT_REASON_HANDOFF, + eCSR_DISCONNECT_REASON_IBSS_JOIN_FAILURE, + eCSR_DISCONNECT_REASON_IBSS_LEAVE, + eCSR_DISCONNECT_REASON_STA_HAS_LEFT, +}eCsrRoamDisconnectReason; + +typedef enum +{ + // Not associated in Infra or participating in an IBSS / Ad-hoc network. + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED, + // Associated in an Infrastructure network. + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED, + // Participating in an IBSS network though disconnected (no partner stations + // in the IBSS). + eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED, + // Participating in an IBSS network with partner stations also present + eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED, + // Participating in a WDS network in AP or STA mode but not connected yet + eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED, + // Participating in a WDS network and connected peer to peer + eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED, + // Participating in a Infra network in AP not yet in connected state + 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; + + +// This parameter is no longer supported in the Profile. Need to set this in the global properties +// for the adapter. +typedef enum eCSR_MEDIUM_ACCESS +{ + eCSR_MEDIUM_ACCESS_AUTO = 0, + eCSR_MEDIUM_ACCESS_DCF, + eCSR_MEDIUM_ACCESS_eDCF, + eCSR_MEDIUM_ACCESS_HCF, + + eCSR_MEDIUM_ACCESS_WMM_eDCF_802dot1p, + eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP, + eCSR_MEDIUM_ACCESS_WMM_eDCF_NoClassify, + eCSR_MEDIUM_ACCESS_11e_eDCF = eCSR_MEDIUM_ACCESS_eDCF, + eCSR_MEDIUM_ACCESS_11e_HCF = eCSR_MEDIUM_ACCESS_HCF, +}eCsrMediaAccessType; + +typedef enum +{ + eCSR_TX_RATE_AUTO = 0, // use rate adaption to determine Tx rate. + + eCSR_TX_RATE_1Mbps = 0x00000001, + eCSR_TX_RATE_2Mbps = 0x00000002, + eCSR_TX_RATE_5_5Mbps = 0x00000004, + eCSR_TX_RATE_6Mbps = 0x00000008, + eCSR_TX_RATE_9Mbps = 0x00000010, + eCSR_TX_RATE_11Mbps = 0x00000020, + eCSR_TX_RATE_12Mbps = 0x00000040, + eCSR_TX_RATE_18Mbps = 0x00000080, + eCSR_TX_RATE_24Mbps = 0x00000100, + eCSR_TX_RATE_36Mbps = 0x00000200, + eCSR_TX_RATE_42Mbps = 0x00000400, + eCSR_TX_RATE_48Mbps = 0x00000800, + eCSR_TX_RATE_54Mbps = 0x00001000, + eCSR_TX_RATE_72Mbps = 0x00002000, + eCSR_TX_RATE_84Mbps = 0x00004000, + eCSR_TX_RATE_96Mbps = 0x00008000, + eCSR_TX_RATE_108Mbps = 0x00010000, + eCSR_TX_RATE_126Mbps = 0x00020000, + eCSR_TX_RATE_144Mbps = 0x00040000, + eCSR_TX_RATE_168Mbps = 0x00080000, + eCSR_TX_RATE_192Mbps = 0x00100000, + eCSR_TX_RATE_216Mbps = 0x00200000, + eCSR_TX_RATE_240Mbps = 0x00400000, + +}eCsrExposedTxRate; + +typedef enum +{ + eCSR_OPERATING_CHANNEL_ALL = 0, + eCSR_OPERATING_CHANNEL_AUTO = eCSR_OPERATING_CHANNEL_ALL, + eCSR_OPERATING_CHANNEL_ANY = eCSR_OPERATING_CHANNEL_ALL, +}eOperationChannel; + +typedef enum +{ + eCSR_DOT11_FRAG_THRESH_AUTO = -1, + eCSR_DOT11_FRAG_THRESH_MIN = 256, + eCSR_DOT11_FRAG_THRESH_MAX = 2346, + eCSR_DOT11_FRAG_THRESH_DEFAULT = 2000 +}eCsrDot11FragThresh; + + +//for channel bonding for ibss +typedef enum +{ + eCSR_CB_OFF = 0, + eCSR_CB_AUTO = 1, + eCSR_CB_DOWN = 2, + eCSR_CB_UP = 3, +}eCsrCBChoice; + +//For channel bonding, the channel number gap is 4, either up or down. For both 11a and 11g mode. +#define CSR_CB_CHANNEL_GAP 4 +#define CSR_CB_CENTER_CHANNEL_OFFSET 2 +#define CSR_MAX_24GHz_CHANNEL_NUMBER ( SIR_11B_CHANNEL_END ) +#define CSR_MIN_5GHz_CHANNEL_NUMBER ( SIR_11A_CHANNEL_BEGIN ) +#define CSR_MAX_5GHz_CHANNEL_NUMBER ( SIR_11P_CHANNEL_END ) + +// WEP keysize (in bits)... +typedef enum +{ + eCSR_SECURITY_WEP_KEYSIZE_40 = 40, // 40 bit key + 24bit IV = 64bit WEP + eCSR_SECURITY_WEP_KEYSIZE_104 = 104, // 104bit key + 24bit IV = 128bit WEP + + eCSR_SECURITY_WEP_KEYSIZE_MIN = eCSR_SECURITY_WEP_KEYSIZE_40, + eCSR_SECURITY_WEP_KEYSIZE_MAX = eCSR_SECURITY_WEP_KEYSIZE_104, + eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES = ( eCSR_SECURITY_WEP_KEYSIZE_MAX / 8 ), +}eCsrWEPKeySize; + + +// Possible values for the WEP static key ID... +typedef enum +{ + + eCSR_SECURITY_WEP_STATIC_KEY_ID_MIN = 0, + eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX = 3, + eCSR_SECURITY_WEP_STATIC_KEY_ID_DEFAULT = 0, + + eCSR_SECURITY_WEP_STATIC_KEY_ID_INVALID = -1, + +}eCsrWEPStaticKeyID; + +// Two extra key indicies are used for the IGTK (which is used by BIP) +#define CSR_MAX_NUM_KEY (eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX + 2 + 1) + +typedef enum +{ + eCSR_SECURITY_SET_KEY_ACTION_NO_CHANGE, + eCSR_SECURITY_SET_KEY_ACTION_SET_KEY, + eCSR_SECURITY_SET_KEY_ACTION_DELETE_KEY, +}eCsrSetKeyAction; + +typedef enum +{ + eCSR_BAND_ALL, + eCSR_BAND_24, + eCSR_BAND_5G, + eCSR_BAND_MAX, +}eCsrBand; + + +typedef enum +{ + // Roaming because HDD requested for reassoc by changing one of the fields in + // tCsrRoamModifyProfileFields. OR + // Roaming because SME requested for reassoc by changing one of the fields in + // tCsrRoamModifyProfileFields. + eCsrRoamReasonStaCapabilityChanged, + // Roaming because SME requested for reassoc to a different AP, as part of + // inter AP handoff. + eCsrRoamReasonBetterAP, + // Roaming because SME requested it as the link is lost - placeholder, will + // clean it up once handoff code gets in + eCsrRoamReasonSmeIssuedForLostLink, + +}eCsrRoamReasonCodes; + +typedef enum +{ + eCsrRoamWmmAuto = 0, + eCsrRoamWmmQbssOnly = 1, + eCsrRoamWmmNoQos = 2, + +} eCsrRoamWmmUserModeType; + +typedef enum +{ + eCSR_REQUESTER_MIN = 0, + eCSR_DIAG, + eCSR_UMA_GAN, + eCSR_HDD +} eCsrStatsRequesterType; + +/** + * enum csr_hi_rssi_scan_id - Parameter ids for hi rssi scan feature + * + * eCSR_HI_RSSI_SCAN_MAXCOUNT_ID: how many times scan can be performed + * eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID: rssi difference to trigger scan + * eCSR_HI_RSSI_SCAN_DELAY_ID: delay in millseconds between scans + * eCSR_HI_RSSI_SCAN_RSSI_UB_ID: rssi upper bound for scan trigger + */ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +enum csr_hi_rssi_scan_id { + eCSR_HI_RSSI_SCAN_MAXCOUNT_ID, + eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID, + eCSR_HI_RSSI_SCAN_DELAY_ID, + eCSR_HI_RSSI_SCAN_RSSI_UB_ID +}; +#endif + +typedef struct tagPmkidCandidateInfo +{ + tCsrBssid BSSID; + tANI_BOOLEAN preAuthSupported; +}tPmkidCandidateInfo; + +typedef struct tagPmkidCacheInfo +{ + tCsrBssid BSSID; + tANI_U8 PMKID[CSR_RSN_PMKID_SIZE]; +}tPmkidCacheInfo; + +#ifdef FEATURE_WLAN_WAPI +typedef struct tagBkidCandidateInfo +{ + tCsrBssid BSSID; + tANI_BOOLEAN preAuthSupported; +}tBkidCandidateInfo; + +typedef struct tagBkidCacheInfo +{ + tCsrBssid BSSID; + tANI_U8 BKID[CSR_WAPI_BKID_SIZE]; +}tBkidCacheInfo; +#endif /* FEATURE_WLAN_WAPI */ + +typedef struct tagCsrKeys +{ + tANI_U8 KeyLength[ CSR_MAX_NUM_KEY ]; //Also use to indicate whether the key index is set + tANI_U8 KeyMaterial[ CSR_MAX_NUM_KEY ][ CSR_MAX_KEY_LEN ]; + tANI_U8 defaultIndex; +}tCsrKeys; + +/* Following are fields which are part of tCsrRoamConnectedProfile might need + modification dynamically once STA is up & running and this could trigger + reassoc */ +typedef struct tagCsrRoamModifyProfileFields +{ + // during connect this specifies ACs U-APSD is to be setup + // for (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored). + // During assoc response this COULD carry confirmation of what ACs U-APSD + // got setup for. Later if an APP looking for APSD, SME-QoS might need to + // modify this field + tANI_U8 uapsd_mask; + // HDD might ask to modify this field + tANI_U16 listen_interval; +}tCsrRoamModifyProfileFields; + +typedef struct tagCsrRoamProfile +{ + //For eCSR_BSS_TYPE_WDS_AP. There must be one SSID in SSIDs. + //For eCSR_BSS_TYPE_WDS_STA. There must be two SSIDs. Index 0 is the SSID of the WDS-AP + //that we need to join. Index 1 is the SSID for self BSS. + tCsrSSIDs SSIDs; + tCsrBSSIDs BSSIDs; + /* this is a bit mask of all the needed phy mode defined in eCsrPhyMode */ + eCsrPhyMode phyMode; + eCsrRoamBssType BSSType; + + tCsrAuthList AuthType; + eCsrAuthType negotiatedAuthType; + + tCsrEncryptionList EncryptionType; + //This field is for output only, not for input + eCsrEncryptionType negotiatedUCEncryptionType; + + //eCSR_ENCRYPT_TYPE_ANY cannot be set in multicast encryption type. If caller doesn't case, + //put all supported encryption types in here + tCsrEncryptionList mcEncryptionType; + //This field is for output only, not for input + eCsrEncryptionType negotiatedMCEncryptionType; + +#ifdef WLAN_FEATURE_11W + // Management Frame Protection + tANI_BOOLEAN MFPEnabled; + tANI_U8 MFPRequired; + tANI_U8 MFPCapable; +#endif + + tCsrKeys Keys; + eCsrCBChoice CBMode; //up, down or auto + tCsrChannelInfo ChannelInfo; + tANI_U8 operationChannel; + tANI_U32 vht_channel_width; + tANI_U16 beaconInterval; //If this is 0, SME will fill in for caller. + // during connect this specifies ACs U-APSD is to be setup + // for (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored). + // During assoc response this COULD carry confirmation of what ACs U-APSD got setup for + tANI_U8 uapsd_mask; + tANI_U32 nWPAReqIELength; //The byte count in the pWPAReqIE + tANI_U8 *pWPAReqIE; //If not null, it has the IE byte stream for WPA + tANI_U32 nRSNReqIELength; //The byte count in the pRSNReqIE + tANI_U8 *pRSNReqIE; //If not null, it has the IE byte stream for RSN +#ifdef FEATURE_WLAN_WAPI + tANI_U32 nWAPIReqIELength; //The byte count in the pWAPIReqIE + tANI_U8 *pWAPIReqIE; //If not null, it has the IE byte stream for WAPI +#endif /* FEATURE_WLAN_WAPI */ + + tANI_U32 nAddIEScanLength; //The byte count in the pAddIE for scan (at the time of join) + tANI_U8 *pAddIEScan; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE + tANI_U32 nAddIEAssocLength; //The byte count in the pAddIE for assoc + tANI_U8 *pAddIEAssoc; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE + + tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN]; //it is ignored if [0] is 0. + /*WPS Association if true => auth and ecryption should be ignored*/ + tANI_BOOLEAN bWPSAssociation; + tANI_BOOLEAN bOSENAssociation; + tANI_U32 nWSCReqIELength; //The byte count in the pWSCReqIE + tANI_U8 *pWSCReqIE; //If not null, it has the IE byte stream for WSC + + tANI_U8 ieee80211d; + tANI_U8 privacy; + tANI_BOOLEAN fwdWPSPBCProbeReq; + tAniAuthType csr80211AuthType; + tANI_U32 dtimPeriod; + tANI_BOOLEAN ApUapsdEnable; + tANI_BOOLEAN protEnabled; + tANI_BOOLEAN obssProtEnabled; + tANI_U16 cfg_protection; + tANI_U8 wps_state; + +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsrMobilityDomainInfo MDID; +#endif + tVOS_CON_MODE csrPersona; + + tANI_U8 disableDFSChSwitch; + /* addIe params */ + tSirAddIeParams addIeParams; + uint8_t sap_dot11mc; +}tCsrRoamProfile; + + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +typedef struct tagCsrRoamHTProfile +{ + eCsrPhyMode phymode; + tANI_U8 htCapability; + tANI_U8 htSupportedChannelWidthSet; + tANI_U8 htRecommendedTxWidthSet; + ePhyChanBondState htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtCapability; + tANI_U8 vhtTxChannelWidthSet; + tANI_U8 apCenterChan; + tANI_U8 apChanWidth; +#endif +}tCsrRoamHTProfile; +#endif +typedef struct tagCsrRoamConnectedProfile +{ + tSirMacSSid SSID; + tANI_BOOLEAN handoffPermitted; + tANI_BOOLEAN ssidHidden; + tCsrBssid bssid; + eCsrRoamBssType BSSType; + eCsrAuthType AuthType; + tCsrAuthList AuthInfo; + eCsrEncryptionType EncryptionType; + tCsrEncryptionList EncryptionInfo; + eCsrEncryptionType mcEncryptionType; + tCsrEncryptionList mcEncryptionInfo; + eCsrCBChoice CBMode; //up, down or auto + tANI_U8 operationChannel; + tANI_U32 vht_channel_width; + tANI_U16 beaconInterval; + tCsrKeys Keys; + // meaningless on connect. It's an OUT param from CSR's point of view + // During assoc response carries the ACM bit-mask i.e. what + // ACs have ACM=1 (if any), + // (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored) + tANI_U8 acm_mask; + tCsrRoamModifyProfileFields modifyProfileFields; + tANI_U32 nAddIEAssocLength; //The byte count in the pAddIE for assoc + tANI_U8 *pAddIEAssoc; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE + + tSirBssDescription *pBssDesc; + tANI_BOOLEAN qap; //AP supports QoS + tANI_BOOLEAN qosConnection; //A connection is QoS enabled +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsrMobilityDomainInfo MDID; +#endif + +#ifdef FEATURE_WLAN_ESE + tCsrEseCckmInfo eseCckmInfo; + tANI_BOOLEAN isESEAssoc; +#endif + tANI_U32 dot11Mode; + tANI_U8 proxyARPService; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tCsrRoamHTProfile HTProfile; +#endif +#ifdef WLAN_FEATURE_11W + /* Management Frame Protection */ + tANI_BOOLEAN MFPEnabled; + tANI_U8 MFPRequired; + tANI_U8 MFPCapable; +#endif +}tCsrRoamConnectedProfile; + + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct tagCsr11rConfigParams +{ + tANI_BOOLEAN IsFTResourceReqSupported; +} tCsr11rConfigParams; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +typedef struct tagCsrNeighborRoamConfigParams +{ + + tANI_U32 nNeighborScanTimerPeriod; + tANI_U8 nNeighborLookupRssiThreshold; + tANI_U8 nNeighborReassocRssiThreshold; + tANI_U16 nNeighborScanMinChanTime; + tANI_U16 nNeighborScanMaxChanTime; + sCsrChannel neighborScanChanList; + tANI_U8 nMaxNeighborRetries; + tANI_U16 nNeighborResultsRefreshPeriod; + tANI_U16 nEmptyScanRefreshPeriod; + tANI_U8 nOpportunisticThresholdDiff; + tANI_U8 nRoamRescanRssiDiff; + tANI_U8 nRoamBmissFirstBcnt; + tANI_U8 nRoamBmissFinalBcnt; + tANI_U8 nRoamBeaconRssiWeight; + tANI_U8 delay_before_vdev_stop; + uint32_t nhi_rssi_scan_max_count; + uint32_t nhi_rssi_scan_rssi_delta; + uint32_t nhi_rssi_scan_delay; + int32_t nhi_rssi_scan_rssi_ub; +}tCsrNeighborRoamConfigParams; +#endif + +typedef struct tagCsrConfigParam +{ + tANI_U32 FragmentationThreshold; + tANI_U32 channelBondingMode24GHz; // keep this tANI_U32. This gets converted to ePhyChannelBondState + tANI_U32 channelBondingMode5GHz; // in csrChangeDefaultConfigParam using convertCBIniValueToPhyCBState + uint32_t stacbmode; + eCsrPhyMode phyMode; + eCsrBand eBand; + tANI_U32 RTSThreshold; + tANI_U32 HeartbeatThresh50; + tANI_U32 HeartbeatThresh24; + eCsrCBChoice cbChoice; + eCsrBand bandCapability; //indicate hw capability + tANI_U32 bgScanInterval; + tANI_U16 TxRate; + eCsrRoamWmmUserModeType WMMSupportMode; + tANI_BOOLEAN Is11eSupportEnabled; + tANI_BOOLEAN Is11dSupportEnabled; + tANI_BOOLEAN Is11dSupportEnabledOriginal; + tANI_BOOLEAN Is11hSupportEnabled; + tANI_BOOLEAN shortSlotTime; + tANI_BOOLEAN ProprietaryRatesEnabled; + tANI_U8 AdHocChannel24; + tANI_U8 AdHocChannel5G; + tANI_U32 impsSleepTime; //in units of seconds + tANI_U32 nScanResultAgeCount; //this number minus one is the number of times a scan doesn't find it before it is removed + tANI_U32 scanAgeTimeNCNPS; //scan result aging time threshold when Not-Connect-No-Power-Save, in seconds + tANI_U32 scanAgeTimeNCPS; //scan result aging time threshold when Not-Connect-Power-Save, in seconds + tANI_U32 scanAgeTimeCNPS; //scan result aging time threshold when Connect-No-Power-Save, in seconds, + tANI_U32 scanAgeTimeCPS; //scan result aging time threshold when Connect-Power-Savein seconds + tANI_U32 nRoamingTime; //In seconds, CSR will try this long before gives up. 0 means no roaming + tANI_U8 bCatRssiOffset; //to set the RSSI difference for each category + tANI_U8 fEnableMCCMode; //to set MCC Enable/Disable mode + bool mcc_rts_cts_prot_enable; + bool mcc_bcast_prob_resp_enable; + tANI_U8 fAllowMCCGODiffBI; //to allow MCC GO different B.I than STA's. NOTE: make sure if RIVA firmware can handle this combination before enabling this + //at the moment, this flag is provided only to pass Wi-Fi Cert. 5.1.12 + tCsr11dinfo Csr11dinfo; + //Whether to limit the channels to the ones set in Csr11dInfo. If true, the opertaional + //channels are limited to the default channel list. It is an "AND" operation between the + //default channels and the channels in the 802.11d IE. + tANI_BOOLEAN fEnforce11dChannels; + //Country Code Priority + //0 = 802.11D > Country IOCTL > NV + //1 = Country IOCTL > 802.11D > NV + tANI_BOOLEAN fSupplicantCountryCodeHasPriority; + //When true, AP with unknown country code won't be see. + //"Unknown country code" means either Ap doesn't have 11d IE or we cannot + //find a domain for the country code in its 11d IE. + tANI_BOOLEAN fEnforceCountryCodeMatch; + //When true, only APs in the default domain can be seen. If the Ap has "unknown country + //code", or the domain of the country code doesn't match the default domain, the Ap is + //not acceptable. + tANI_BOOLEAN fEnforceDefaultDomain; + + tANI_U16 vccRssiThreshold; + tANI_U32 vccUlMacLossThreshold; + + tANI_U32 nPassiveMinChnTime; //in units of milliseconds + tANI_U32 nPassiveMaxChnTime; //in units of milliseconds + tANI_U32 nActiveMinChnTime; //in units of milliseconds + tANI_U32 nActiveMaxChnTime; //in units of milliseconds + + tANI_U32 nInitialDwellTime; //in units of milliseconds + bool initial_scan_no_dfs_chnl; + + tANI_U32 nActiveMinChnTimeBtc; //in units of milliseconds + tANI_U32 nActiveMaxChnTimeBtc; //in units of milliseconds + tANI_U32 disableAggWithBtc; +#ifdef WLAN_AP_STA_CONCURRENCY + tANI_U32 nPassiveMinChnTimeConc; //in units of milliseconds + tANI_U32 nPassiveMaxChnTimeConc; //in units of milliseconds + tANI_U32 nActiveMinChnTimeConc; //in units of milliseconds + tANI_U32 nActiveMaxChnTimeConc; //in units of milliseconds + tANI_U32 nRestTimeConc; //in units of milliseconds + tANI_U8 nNumStaChanCombinedConc; //number of channels combined for + //STA in each split scan operation + tANI_U8 nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation +#endif + /*In units of milliseconds*/ + uint32_t min_rest_time_conc; + /*In units of milliseconds*/ + uint32_t idle_time_conc; + + tANI_BOOLEAN IsIdleScanEnabled; + //in dBm, the maximum TX power + //The actual TX power is the lesser of this value and 11d. + //If 11d is disable, the lesser of this and default setting. + tANI_U8 nTxPowerCap; + tANI_U32 statsReqPeriodicity; //stats request frequency from PE while in full power + tANI_U32 statsReqPeriodicityInPS;//stats request frequency from PE while in power save +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsr11rConfigParams csr11rConfig; +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U8 isEseIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_LFR + tANI_U8 isFastRoamIniFeatureEnabled; + tANI_U8 MAWCEnabled; +#endif + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_U8 nImmediateRoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + tCsrNeighborRoamConfigParams neighborRoamConfig; +#endif + + /* Instead of Reassoc, send ADDTS/DELTS even when ACM is off for that AC + * This is mandated by WMM-AC certification */ + tANI_BOOLEAN addTSWhenACMIsOff; + + + /*channelPowerInfoList24 has been seen corrupted. Set this flag to true trying to + * detect when it happens. Adding this into code because we can't reproduce it easily. + * We don't know when it happens. */ + tANI_BOOLEAN fValidateList; + + /*Customer wants to start with an active scan based on the default country code. + * This optimization will minimize the driver load to association time. + * Based on this flag we will bypass the initial passive scan needed for 11d + * to determine the country code & domain */ + tANI_BOOLEAN fEnableBypass11d; + + /*Customer wants to optimize the scan time. Avoiding scans(passive) on DFS + * channels while swipping through both bands can save some time + * (apprx 1.3 sec) */ + tANI_U8 fEnableDFSChnlScan; + + //To enable/disable scanning 2.4Ghz channels twice on a single scan request from HDD + tANI_BOOLEAN fScanTwice; +#ifdef WLAN_FEATURE_11AC + tANI_U32 nVhtChannelWidth; + tANI_U8 enableTxBF; + tANI_U8 txBFCsnValue; + tANI_U8 enable2x2; + tANI_BOOLEAN enableVhtFor24GHz; + tANI_U8 enableMuBformee; + tANI_U8 enableVhtpAid; + tANI_U8 enableVhtGid; +#endif + tANI_U8 enableAmpduPs; + tANI_U8 enableHtSmps; + tANI_U8 htSmps; + + /* + * To enable/disable scanning only 2.4Ghz channels on first scan + */ + tANI_BOOLEAN fFirstScanOnly2GChnl; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tANI_BOOLEAN nRoamPrefer5GHz; + tANI_BOOLEAN nRoamIntraBand; + tANI_U8 nProbes; + tANI_U16 nRoamScanHomeAwayTime; + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tANI_BOOLEAN isRoamOffloadScanEnabled; + tANI_BOOLEAN bFastRoamInConIniFeatureEnabled; +#endif +#endif + + tANI_BOOLEAN ignorePeerErpInfo; + tANI_U8 scanCfgAgingTime; + + tANI_U8 enableTxLdpc; + + tANI_U8 max_amsdu_num; + tANI_U8 nSelect5GHzMargin; + + tANI_U8 isCoalesingInIBSSAllowed; + + eCsrBand scanBandPreference; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tANI_U8 cc_switch_mode; +#endif + tANI_U8 allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_BOOLEAN isRoamOffloadEnabled; +#endif + + tANI_BOOLEAN obssEnabled; + v_U8_t conc_custom_rule1; + v_U8_t conc_custom_rule2; + v_U8_t is_sta_connection_in_5gz_enabled; + + /* 802.11p enable */ + bool enable_dot11p; + tANI_BOOLEAN sendDeauthBeforeCon; + v_U16_t pkt_err_disconn_th; + int8_t first_scan_bucket_threshold; +}tCsrConfigParam; + +//Tush +typedef struct tagCsrUpdateConfigParam +{ + tCsr11dinfo Csr11dinfo; +}tCsrUpdateConfigParam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define csrRoamIsRoamOffloadEnabled(pMac)\ + (pMac->roam.configParam.isRoamOffloadEnabled) + +#define DEFAULT_REASSOC_FAILURE_TIMEOUT 1000 +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define CSR_ROAM_AUTH_STATUS_CONNECTED 0x1 /** connected, + but not authenticated */ +#define CSR_ROAM_AUTH_STATUS_AUTHENTICATED 0x2 /** connected + and authenticated */ +#endif + +typedef struct tagCsrRoamInfo +{ + tCsrRoamProfile *pProfile; //may be NULL + tSirBssDescription *pBssDesc; //May be NULL + tANI_U32 nBeaconLength; //the length, in bytes, of the beacon frame, can be 0 + tANI_U32 nAssocReqLength; //the length, in bytes, of the assoc req frame, can be 0 + tANI_U32 nAssocRspLength; //The length, in bytes, of the assoc rsp frame, can be 0 + tANI_U32 nFrameLength; + tANI_U8 frameType; + tANI_U8 *pbFrames; //Point to a buffer contain the beacon, assoc req, assoc rsp frame, in that order + //user needs to use nBeaconLength, nAssocReqLength, nAssocRspLength to desice where + //each frame starts and ends. + tANI_BOOLEAN fReassocReq; //set to true if for re-association + tANI_BOOLEAN fReassocRsp; //set to true if for re-association + tCsrBssid bssid; + //Only valid in IBSS + //this is the peers MAC address for eCSR_ROAM_RESULT_IBSS_NEW_PEER or PEER_DEPARTED + tCsrBssid peerMac; + tSirResultCodes statusCode; + tANI_U32 reasonCode; //this could be our own defined or sent from the other BSS(per 802.11 spec) + tANI_U8 staId; // Peer stationId when connected + /*The DPU signatures will be sent eventually to TL to help it determine the + association to which a packet belongs to*/ + /*Unicast DPU signature*/ + tANI_U8 ucastSig; + + /*Broadcast DPU signature*/ + tANI_U8 bcastSig; + + tANI_BOOLEAN fAuthRequired; //FALSE means auth needed from supplicant. TRUE means authenticated(static WEP, open) + tANI_U8 sessionId; + tANI_U8 rsnIELen; + tANI_U8 *prsnIE; + tANI_U8 wapiIELen; + tANI_U8 *pwapiIE; + + tANI_U8 addIELen; + tANI_U8 *paddIE; + + union + { + tSirMicFailureInfo *pMICFailureInfo; + tCsrRoamConnectedProfile *pConnectedProfile; + tSirWPSPBCProbeReq *pWPSPBCProbeReq; + } u; + + tANI_BOOLEAN wmmEnabledSta; //set to true if WMM enabled STA + tANI_U32 dtimPeriod; + +#ifdef FEATURE_WLAN_ESE + tANI_BOOLEAN isESEAssoc; +#ifdef FEATURE_WLAN_ESE_UPLOAD + tSirTsmIE tsmIe; + tANI_U32 timestamp[2]; + tANI_U16 tsmRoamDelay; + tSirEseBcnReportRsp *pEseBcnReportRsp; +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_BOOLEAN is11rAssoc; +#endif + void* pRemainCtx; + tANI_U32 rxChan; + +#ifdef FEATURE_WLAN_TDLS + tANI_U8 staType; + bool tdls_prohibited; /* per ExtCap in Assoc/Reassoc resp */ + bool tdls_chan_swit_prohibited; /* per ExtCap in Assoc/Reassoc resp */ +#endif + + // Required for indicating the frames to upper layer + tANI_U32 beaconLength; + tANI_U8* beaconPtr; + tANI_U32 assocReqLength; + tANI_U8* assocReqPtr; + + tANI_S8 rxRssi; + tSirSmeDfsEventInd dfs_event; + tSirChanChangeResponse *channelChangeRespEvent; + /* Timing and fine Timing measurement capability clubbed together */ + tANI_U8 timingMeasCap; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U8 roamSynchInProgress; + tANI_U8 synchAuthStatus; + tANI_U8 kck[SIR_KCK_KEY_LEN]; + tANI_U8 kek[SIR_KEK_KEY_LEN]; + tANI_U8 replay_ctr[SIR_REPLAY_CTR_LEN]; +#endif + tSirSmeChanInfo chan_info; + uint8_t target_channel; +}tCsrRoamInfo; + + +typedef struct tagCsrFreqScanInfo +{ + tANI_U32 nStartFreq; //in unit of MHz + tANI_U32 nEndFreq; //in unit of MHz + tSirScanType scanType; +}tCsrFreqScanInfo; + + +typedef struct sSirSmeAssocIndToUpperLayerCnf +{ + tANI_U16 messageType; // eWNI_SME_ASSOC_CNF + tANI_U16 length; + tANI_U8 sessionId; + tSirResultCodes statusCode; + tSirMacAddr bssId; // Self BSSID + tSirMacAddr peerMacAddr; + tANI_U16 aid; + tSirMacAddr alternateBssId; + tANI_U8 alternateChannelId; + tANI_U8 wmmEnabledSta; //set to true if WMM enabled STA + tSirRSNie rsnIE; // RSN IE received from peer + tSirWAPIie wapiIE; // WAPI IE received from peer + tSirAddie addIE; // Additional IE received from peer, which can be WSC and/or P2P IE + tANI_U8 reassocReq; //set to true if reassoc + /* Timing and fine Timing measurement capability clubbed together */ + tANI_U8 timingMeasCap; + tSirSmeChanInfo chan_info; +} tSirSmeAssocIndToUpperLayerCnf, *tpSirSmeAssocIndToUpperLayerCnf; + +typedef struct tagCsrSummaryStatsInfo +{ + tANI_U32 retry_cnt[4]; + tANI_U32 multiple_retry_cnt[4]; + tANI_U32 tx_frm_cnt[4]; + //tANI_U32 num_rx_frm_crc_err; same as rx_error_cnt + //tANI_U32 num_rx_frm_crc_ok; same as rx_frm_cnt + tANI_U32 rx_frm_cnt; + tANI_U32 frm_dup_cnt; + tANI_U32 fail_cnt[4]; + tANI_U32 rts_fail_cnt; + tANI_U32 ack_fail_cnt; + tANI_U32 rts_succ_cnt; + tANI_U32 rx_discard_cnt; + tANI_U32 rx_error_cnt; + tANI_U32 tx_byte_cnt; + +}tCsrSummaryStatsInfo; + +typedef struct tagCsrGlobalClassAStatsInfo +{ + tANI_U32 rx_frag_cnt; + tANI_U32 promiscuous_rx_frag_cnt; + //tANI_U32 rx_fcs_err; + tANI_U32 rx_input_sensitivity; + tANI_U32 max_pwr; + //tANI_U32 default_pwr; + tANI_U32 sync_fail_cnt; + tANI_U32 tx_rate; + //mcs index for HT20 and HT40 rates + tANI_U32 mcs_index; + //to defferentiate between HT20 and HT40 rates;short and long guard interval + tANI_U32 tx_rate_flags; + +}tCsrGlobalClassAStatsInfo; + +typedef struct tagCsrGlobalClassBStatsInfo +{ + tANI_U32 uc_rx_wep_unencrypted_frm_cnt; + tANI_U32 uc_rx_mic_fail_cnt; + tANI_U32 uc_tkip_icv_err; + tANI_U32 uc_aes_ccmp_format_err; + tANI_U32 uc_aes_ccmp_replay_cnt; + tANI_U32 uc_aes_ccmp_decrpt_err; + tANI_U32 uc_wep_undecryptable_cnt; + tANI_U32 uc_wep_icv_err; + tANI_U32 uc_rx_decrypt_succ_cnt; + tANI_U32 uc_rx_decrypt_fail_cnt; + tANI_U32 mcbc_rx_wep_unencrypted_frm_cnt; + tANI_U32 mcbc_rx_mic_fail_cnt; + tANI_U32 mcbc_tkip_icv_err; + tANI_U32 mcbc_aes_ccmp_format_err; + tANI_U32 mcbc_aes_ccmp_replay_cnt; + tANI_U32 mcbc_aes_ccmp_decrpt_err; + tANI_U32 mcbc_wep_undecryptable_cnt; + tANI_U32 mcbc_wep_icv_err; + tANI_U32 mcbc_rx_decrypt_succ_cnt; + tANI_U32 mcbc_rx_decrypt_fail_cnt; + +}tCsrGlobalClassBStatsInfo; + +typedef struct tagCsrGlobalClassCStatsInfo +{ + tANI_U32 rx_amsdu_cnt; + tANI_U32 rx_ampdu_cnt; + tANI_U32 tx_20_frm_cnt; + tANI_U32 rx_20_frm_cnt; + tANI_U32 rx_mpdu_in_ampdu_cnt; + tANI_U32 ampdu_delimiter_crc_err; + +}tCsrGlobalClassCStatsInfo; + +typedef struct tagCsrGlobalClassDStatsInfo +{ + tANI_U32 tx_uc_frm_cnt; + tANI_U32 tx_mc_frm_cnt; + tANI_U32 tx_bc_frm_cnt; + tANI_U32 rx_uc_frm_cnt; + tANI_U32 rx_mc_frm_cnt; + tANI_U32 rx_bc_frm_cnt; + tANI_U32 tx_uc_byte_cnt[4]; + tANI_U32 tx_mc_byte_cnt; + tANI_U32 tx_bc_byte_cnt; + tANI_U32 rx_uc_byte_cnt[4]; + tANI_U32 rx_mc_byte_cnt; + tANI_U32 rx_bc_byte_cnt; + tANI_U32 rx_byte_cnt; + tANI_U32 num_rx_bytes_crc_ok; + tANI_U32 rx_rate; + +}tCsrGlobalClassDStatsInfo; + +typedef struct tagCsrPerStaStatsInfo +{ + tANI_U32 tx_frag_cnt[4]; + tANI_U32 tx_ampdu_cnt; + tANI_U32 tx_mpdu_in_ampdu_cnt; +} tCsrPerStaStatsInfo; + +typedef struct tagCsrRoamSetKey +{ + eCsrEncryptionType encType; + tAniKeyDirection keyDirection; //Tx, Rx or Tx-and-Rx + tCsrBssid peerMac; //Peers MAC address. ALL 1's for group key + tANI_U8 paeRole; //0 for supplicant + tANI_U8 keyId; // Kye index + tANI_U16 keyLength; //Number of bytes containing the key in pKey + tANI_U8 Key[CSR_MAX_KEY_LEN]; + tANI_U8 keyRsc[CSR_MAX_RSC_LEN]; +} tCsrRoamSetKey; + +typedef struct tagCsrRoamRemoveKey +{ + eCsrEncryptionType encType; + tCsrBssid peerMac; //Peers MAC address. ALL 1's for group key + tANI_U8 keyId; //key index +} tCsrRoamRemoveKey; + +#ifdef FEATURE_WLAN_TDLS + +typedef struct tagCsrLinkEstablishParams +{ + tSirMacAddr peerMac; + tANI_U8 uapsdQueues; + tANI_U8 maxSp; + tANI_U8 isBufSta; + tANI_U8 isOffChannelSupported; + tANI_U8 isResponder; + tANI_U8 supportedChannelsLen; + tANI_U8 supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; + tANI_U8 supportedOperClassesLen; + tANI_U8 supportedOperClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +}tCsrTdlsLinkEstablishParams; + +typedef struct tagCsrTdlsSendMgmt +{ + tSirMacAddr peerMac; + tANI_U8 frameType; + tANI_U8 dialog; + tANI_U16 statusCode; + tANI_U8 responder; + tANI_U32 peerCapability; + tANI_U8 *buf; + tANI_U8 len; + +}tCsrTdlsSendMgmt; + +#endif + +typedef void * tScanResultHandle; + +#define CSR_INVALID_SCANRESULT_HANDLE (NULL) + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +typedef enum +{ + REASSOC = 0, + FASTREASSOC = 1 +}handoff_src; + +typedef struct tagCsrHandoffRequest +{ + tCsrBssid bssid; + tANI_U8 channel; + tANI_U8 src; /* To check if its a REASSOC or a FASTREASSOC IOCTL */ +}tCsrHandoffRequest; +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +typedef struct tagCsrEseBeaconReqParams +{ + tANI_U16 measurementToken; + tANI_U8 channel; + tANI_U8 scanMode; + tANI_U16 measurementDuration; +} tCsrEseBeaconReqParams, *tpCsrEseBeaconReqParams; + +typedef struct tagCsrEseBeaconReq +{ + tANI_U8 numBcnReqIe; + tCsrEseBeaconReqParams bcnReq[SIR_ESE_MAX_MEAS_IE_REQS]; +} tCsrEseBeaconReq, *tpCsrEseBeaconReq; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +struct tagCsrDelStaParams +{ + tCsrBssid peerMacAddr; + u16 reason_code; + u8 subtype; +}; + +/** + * struct wep_update_default_key_idx: wep default key index structure + * + * @session_id: session ID for the connection session + * @default_idx: default key index for wep + * + * structure includes sesssion id for connection and default key + * index used for wep + */ +struct wep_update_default_key_idx { + uint8_t session_id; + uint8_t default_idx; +}; + +////////////////////////////////////////////Common SCAN starts + +//void *p2 -- the second context pass in for the caller +//***what if callback is called before requester gets the scanId?? +typedef eHalStatus (*csrScanCompleteCallback)(tHalHandle, void *p2, + tANI_U8 sessionId, + tANI_U32 scanID, + eCsrScanStatus status); + + + +///////////////////////////////////////////Common Roam starts + +//pContext is the pContext passed in with the roam request +//pParam is a pointer to a tCsrRoamInfo, see definition of eRoamCmdStatus and +// eRoamCmdResult for detail valid members. It may be NULL +//roamId is to identify the callback related roam request. 0 means unsolicit +//roamStatus is a flag indicating the status of the callback +//roamResult is the result +typedef eHalStatus (*csrRoamCompleteCallback)(void *pContext, tCsrRoamInfo *pParam, tANI_U32 roamId, + eRoamCmdStatus roamStatus, eCsrRoamResult roamResult); + +typedef eHalStatus (*csrRoamSessionCloseCallback)(void *pContext); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetNumPMKIDCache + \brief return number of PMKID cache entries + \return tANI_U32 - the number of PMKID cache entries + -------------------------------------------------------------------------------*/ +//tANI_U32 csrRoamGetNumPMKIDCache(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetPMKIDCache + \brief return PMKID cache from CSR + \param pNum - caller allocated memory that has the space of the number of pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the + needed or actually number in tPmkidCacheInfo. + \param pPmkidCache - Caller allocated memory that contains PMKID cache, if any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +//eHalStatus csrRoamGetPMKIDCache(tHalHandle hHal, tANI_U32 *pNum, tPmkidCacheInfo *pPmkidCache); + +//pProfile - pointer to tCsrRoamProfile +#define CSR_IS_START_IBSS(pProfile) (eCSR_BSS_TYPE_START_IBSS == (pProfile)->BSSType) +#define CSR_IS_JOIN_TO_IBSS(pProfile) (eCSR_BSS_TYPE_IBSS == (pProfile)->BSSType) +#define CSR_IS_IBSS(pProfile) ( CSR_IS_START_IBSS(pProfile) || CSR_IS_JOIN_TO_IBSS(pProfile) ) +#define CSR_IS_INFRASTRUCTURE(pProfile) (eCSR_BSS_TYPE_INFRASTRUCTURE == (pProfile)->BSSType) +#define CSR_IS_ANY_BSS_TYPE(pProfile) (eCSR_BSS_TYPE_ANY == (pProfile)->BSSType) +#define CSR_IS_WDS_AP( pProfile ) ( eCSR_BSS_TYPE_WDS_AP == (pProfile)->BSSType ) +#define CSR_IS_WDS_STA( pProfile ) ( eCSR_BSS_TYPE_WDS_STA == (pProfile)->BSSType ) +#define CSR_IS_WDS( pProfile ) ( CSR_IS_WDS_AP( pProfile ) || CSR_IS_WDS_STA( pProfile ) ) +#define CSR_IS_INFRA_AP( pProfile ) ( eCSR_BSS_TYPE_INFRA_AP == (pProfile)->BSSType ) + +//pProfile - pointer to tCsrRoamConnectedProfile +#define CSR_IS_CONN_INFRA_AP( pProfile ) ( eCSR_BSS_TYPE_INFRA_AP == (pProfile)->BSSType ) +#define CSR_IS_CONN_WDS_AP( pProfile ) ( eCSR_BSS_TYPE_WDS_AP == (pProfile)->BSSType ) +#define CSR_IS_CONN_WDS_STA( pProfile ) ( eCSR_BSS_TYPE_WDS_STA == (pProfile)->BSSType ) +#define CSR_IS_CONN_WDS( pProfile ) ( CSR_IS_WDS_AP( pProfile ) || CSR_IS_WDS_STA( pProfile ) ) + + + +///////////////////////////////////////////Common Roam ends + + + +/* --------------------------------------------------------------------------- + \fn csrSetChannels + \brief HDD calls this function to change some global settings. + caller must set the all fields or call csrGetConfigParam to prefill the fields. + \param pParam - caller allocated memory + \return eHalStatus + -------------------------------------------------------------------------------*/ + +eHalStatus csrSetChannels(tHalHandle hHal, tCsrConfigParam *pParam ); + +eHalStatus csrSetRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode); + + +//enum to string conversion for debug output +const char * get_eRoamCmdStatus_str(eRoamCmdStatus val); +const char * get_eCsrRoamResult_str(eCsrRoamResult val); +/* --------------------------------------------------------------------------- + \fn csrSetPhyMode + \brief HDD calls this function to set the phyMode. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + CSR. + \param phyMode - indicate the phyMode needs to set to. The value has to be either 0, or some bits set. + See eCsrPhyMode for definition + \param eBand - specify the operational band (2.4, 5 or both) + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrSetPhyMode(tHalHandle hHal, tANI_U32 phyMode, eCsrBand eBand, tANI_BOOLEAN *pfRestartNeeded); + +void csrDumpInit(tHalHandle hHal); + + +/*--------------------------------------------------------------------------- + This is the type for a link quality callback to be registered with SME + for indications + Once the link quality has been indicated, subsequently, link indications are + posted each time there is a CHANGE in link quality. + *** If there is no change in link, there will be no indication *** + + The indications may be based on one or more criteria internal to SME + such as RSSI and PER. + + \param ind - Indication being posted + \param pContext - any user data given at callback registration. + \return None + +---------------------------------------------------------------------------*/ +typedef void (* csrRoamLinkQualityIndCallback) + (eCsrRoamLinkQualityInd ind, void *pContext); + + +/*--------------------------------------------------------------------------- + This is the type for a statistics callback to be registered with SME + for stats reporting + + Since the client requesting for the stats already know which class/type of + stats it asked for, the callback will carry them in the rsp buffer + (void * stats) whose size will be same as the size of requested stats & + will be exactly in the same order requested in the stats mask from LSB to MSB + + \param stats - stats rsp buffer sent back with the report + \param pContext - any user data given at callback registration. + \return None + +---------------------------------------------------------------------------*/ +typedef void ( *tCsrStatsCallback) (void * stats, void *pContext); + +/*--------------------------------------------------------------------------- + This is the type for a rssi callback to be registered with SME + for getting rssi + + \param rssi - rssi + \param pContext - any user data given at callback registration. + \return None + +---------------------------------------------------------------------------*/ + +typedef void ( *tCsrRssiCallback) (v_S7_t rssi, tANI_U32 staId, void *pContext); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/*--------------------------------------------------------------------------- + This is the type for a tsm stats callback to be registered with SME + for getting tsm stats + \param tsmMetrics - tsmMetrics + \param pContext - any user data given at callback registration. + \return None +---------------------------------------------------------------------------*/ +typedef void ( *tCsrTsmStatsCallback) (tAniTrafStrmMetrics tsmMetrics, + tANI_U32 staId, + void *pContext); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/*--------------------------------------------------------------------------- + This is the type for a snr callback to be registered with SME + for getting snr + + \param snr + \param pContext - any user data given at callback registration. + \return None + +---------------------------------------------------------------------------*/ +typedef void (*tCsrSnrCallback) (v_S7_t snr, tANI_U32 staId, void *pContext); + +#ifdef WLAN_FEATURE_VOWIFI_11R +eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tpSirBssDescription pBssDescription); +#endif + +/*--------------------------------------------------------------------------- + This is the function to change the Band configuraiton (ALL/2.4 GHZ/5 GHZ) + + \param hHal - handle to Hal context + \param eBand - band value + \param sessionId - Session Identifier + \return eHalStatus + +---------------------------------------------------------------------------*/ +eHalStatus csrSetBand(tHalHandle hHal, tANI_U8 sessionId, eCsrBand eBand); + +/*--------------------------------------------------------------------------- + This is the function to get the current operating band value + \param hHal - handl to Hal context + \return eCsrband - band value + +---------------------------------------------------------------------------*/ +eCsrBand csrGetCurrentBand (tHalHandle hHal); + +typedef void (*csrReadyToSuspendCallback)(void *pContext, boolean suspended); + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +typedef void (*csrReadyToExtWoWCallback)(void *pContext, boolean status); +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus csrRoamIssueFTRoamOffloadSynch(tHalHandle hHal, tANI_U32 sessionId, + tSirBssDescription *pBssDescription); +#endif + +/*--------------------------------------------------------------------------- + Callback to be registered with SME for getting link status + \param status - link stats req result status + \param pContext - any user data given at callback registration. + \return None + +---------------------------------------------------------------------------*/ +typedef void (*tCsrLinkStatusCallback)(v_U8_t status, void *pContext); +/** + * tcsr_fw_state_callback() -HDD callback registered with SME for getting + * firmware state + * @context: HDD callback context + * + * Return: void + */ +typedef void (*tcsr_fw_state_callback)(void *context); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrInternal.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrInternal.h new file mode 100644 index 000000000000..5db0db3c1b2e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrInternal.h @@ -0,0 +1,1586 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrInternal.h + + Define internal data structure for MAC. +========================================================================== */ +#ifndef CSRINTERNAL_H__ +#define CSRINTERNAL_H__ + +#include "vos_status.h" +#include "vos_lock.h" + +#include "vos_timer.h" +#include "csrSupport.h" +#include "vos_nvitem.h" +#include "wlan_qct_tl.h" + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "csrNeighborRoam.h" +#endif + +#define CSR_MAX_STA (HAL_NUM_STA) + +//define scan return criteria. LIM should use these define as well +#define CSR_SCAN_RETURN_AFTER_ALL_CHANNELS ( 0 ) +#define CSR_SCAN_RETURN_AFTER_FIRST_MATCH ( 0x01 ) +#define CSR_SCAN_RETURN_AFTER_5_BAND_11d_FOUND ( 0x80 ) +#define CSR_SCAN_RETURN_AFTER_24_BAND_11d_FOUND ( 0x40 ) +#define CSR_SCAN_RETURN_AFTER_EITHER_BAND_11d_FOUND ( CSR_SCAN_RETURN_AFTER_5_BAND_11d_FOUND | CSR_SCAN_RETURN_AFTER_24_BAND_11d_FOUND ) +#define CSR_NUM_RSSI_CAT 15 +#define CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME 3 + +//Support for multiple session +#define CSR_SESSION_ID_INVALID 0xFF // session ID invalid +#define CSR_ROAM_SESSION_MAX 5 // No of sessions to be supported, and a + // session is for Infra, IBSS or BT-AMP +#define CSR_SESSION_ID_ANY 50 + +#define CSR_IS_SESSION_VALID( pMac, sessionId ) ( ( (sessionId) < CSR_ROAM_SESSION_MAX ) \ + && ( (pMac)->roam.roamSession[(sessionId)].sessionActive ) ) +#define CSR_GET_SESSION( pMac, sessionId ) \ +( \ + (sessionId < CSR_ROAM_SESSION_MAX) ? \ + (&(pMac)->roam.roamSession[(sessionId)]) :\ + NULL \ +) + +#define CSR_IS_SESSION_ANY(sessionId) (sessionId == CSR_SESSION_ID_ANY) +#define CSR_MAX_NUM_COUNTRY_CODE 100 +#define CSR_IS_SELECT_5GHZ_MARGIN( pMac ) \ +( \ + (((pMac)->roam.configParam.nSelect5GHzMargin)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) +#define CSR_IS_SELECT_5G_PREFERRED(pMac) \ +( \ + (((pMac)->roam.configParam.roam_params.is_5g_pref_enabled)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +#define CSR_IS_ROAM_PREFER_5GHZ( pMac ) \ +( \ + (((pMac)->roam.configParam.nRoamPrefer5GHz)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) +#define CSR_IS_ROAM_INTRA_BAND_ENABLED( pMac ) \ +( \ + (((pMac)->roam.configParam.nRoamIntraBand)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CSR_IS_ROAM_SCAN_OFFLOAD_ENABLED( pMac ) \ +( \ + (((pMac)->roam.configParam.isRoamOffloadScanEnabled)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) + +#define CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED( pMac ) \ +( \ + (((pMac)->roam.configParam.bFastRoamInConIniFeatureEnabled)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) +#endif + +//Support for "Fast roaming" (i.e., ESE, LFR, or 802.11r.) +#define CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15 + +typedef enum +{ + eCSR_CFG_DOT11_MODE_ABG, + eCSR_CFG_DOT11_MODE_11A, + eCSR_CFG_DOT11_MODE_11B, + eCSR_CFG_DOT11_MODE_11G, + eCSR_CFG_DOT11_MODE_11N, +#ifdef WLAN_FEATURE_11AC + eCSR_CFG_DOT11_MODE_11AC, +#endif + eCSR_CFG_DOT11_MODE_11G_ONLY, + eCSR_CFG_DOT11_MODE_11N_ONLY, +#ifdef WLAN_FEATURE_11AC + eCSR_CFG_DOT11_MODE_11AC_ONLY, +#endif + //This value can never set to CFG. It is for CSR's internal use + eCSR_CFG_DOT11_MODE_AUTO, +}eCsrCfgDot11Mode; //Used to determine what to set to the WNI_CFG_DOT11_MODE + +typedef enum etCsrRoamCommands +{ + eCsrRoamNoCommand, + eCsrRoamCommandScan, + eCsrRoamCommandRoam, + eCsrRoamCommandWmStatusChange, + eCsrRoamCommandSetKey, + eCsrRoamCommandRemoveKey, + +} eCsrRoamCommands; + +typedef enum +{ + eCsrScanOther = 1, + eCsrScanLostLink1, + eCsrScanLostLink2, + eCsrScanLostLink3, + eCsrScanLostLink4, + eCsrScan11d1, //First 11d scan + eCsrScan11d2, //First 11d scan has failed + eCsrScan11dDone, //11d scan succeeded, try the rest of the channel + eCsrScanUserRequest, + eCsrScanGetResult, + eCsrScanSetBGScanParam, //used for HO too - bg scan request in NT Handoff sub-state + eCsrScanForSsid, + eCsrScanForCapsChange, + eCsrScanBGScanAbort, + eCsrScanBGScanEnable, + eCsrScanIdleScan, + eCsrScanGetScanChnInfo, //To get the list of channels scanned + + eCsrScanBgScan, // bg scan request in NRT & RT Handoff sub-states + eCsrScanProbeBss, // directed probe on an entry from the candidate list - HO + eCsrScanAbortBgScan, //aborting a BG scan (meaning the scan is triggered by LIM timer) + eCsrScanAbortNormalScan, //aborting a normal scan (the scan is trigger by eWNI_SME_SCAN_REQ) + eCsrScanP2PFindPeer, + eCsrScanGetLfrResult, // get the LFR candidates from PE scan cache +}eCsrScanReason; + +typedef enum +{ + eCsrNoConnection, // Roaming because we have not established the initial connection. + eCsrCapsChange, // roaming because LIM reported a Capability change in the associated AP. + eCsrForcedDisassoc, // roaming becuase someone asked us to Disassoc and stay disassociated. + eCsrHddIssued, // roaming because an 802.11 request was issued to the driver. + eCsrLostLink1, // roaming because we lost link to an associated AP + eCsrLostLink2, + eCsrLostLink3, + eCsrForcedDisassocMICFailure, // roaming because we need to force a Disassoc due to MIC failure + eCsrHddIssuedReassocToSameAP, + eCsrSmeIssuedReassocToSameAP, + eCsrSmeIssuedReassocToDiffAP, + eCsrForcedDeauth, // roaming becuase someone asked us to deauth and stay disassociated. + eCsrSmeIssuedDisassocForHandoff, // will be issued by Handoff logic to disconect from current AP + eCsrSmeIssuedAssocToSimilarAP, // will be issued by Handoff logic to join a new AP with same profile + eCsrSmeIssuedIbssJoinFailure, // ibss join timer fired before any perr showed up, so shut down the network + eCsrForcedIbssLeave, + eCsrStopBss, + eCsrSmeIssuedFTReassoc, + eCsrForcedDisassocSta, + eCsrForcedDeauthSta, + eCsrPerformPreauth, + eCsrLostLink1Abort, + eCsrLostLink2Abort, + eCsrLostLink3Abort, +}eCsrRoamReason; + +typedef enum +{ + eCSR_ROAM_SUBSTATE_NONE = 0, + eCSR_ROAM_SUBSTATE_START_BSS_REQ, + eCSR_ROAM_SUBSTATE_JOIN_REQ, + eCSR_ROAM_SUBSTATE_REASSOC_REQ, + eCSR_ROAM_SUBSTATE_DISASSOC_REQ, + eCSR_ROAM_SUBSTATE_STOP_BSS_REQ, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, //Continue the current roam command after disconnect + eCSR_ROAM_SUBSTATE_AUTH_REQ, + eCSR_ROAM_SUBSTATE_CONFIG, + eCSR_ROAM_SUBSTATE_DEAUTH_REQ, + eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN, + eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, + eCSR_ROAM_SUBSTATE_DISASSOC_FORCED, + eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, + eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF, + eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC, + eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC, + eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC, + eCSR_ROAM_SUBSTATE_DISASSOC_STA_HAS_LEFT, +// max is 15 unless the bitfield is expanded... +} eCsrRoamSubState; + + +typedef enum +{ + eCSR_ROAMING_STATE_STOP = 0, + eCSR_ROAMING_STATE_IDLE, + eCSR_ROAMING_STATE_SCANNING, + eCSR_ROAMING_STATE_JOINING, + eCSR_ROAMING_STATE_JOINED, +}eCsrRoamState; + + +typedef enum +{ + eCsrContinueRoaming, + eCsrStopRoaming, + eCsrStartIbss, + eCsrStartIbssSameIbss, + eCsrReassocToSelfNoCapChange, + eCsrStopRoamingDueToConcurrency, + +}eCsrJoinState; + +typedef enum +{ + eCsrNotRoaming, + eCsrLostlinkRoamingDisassoc, + eCsrLostlinkRoamingDeauth, + eCsrDynamicRoaming, + eCsrReassocRoaming, +}eCsrRoamingReason; + +typedef enum +{ + eCsrDisassociated, + eCsrDeauthenticated + +}eCsrRoamWmStatusChangeTypes; + +typedef enum +{ + eCsrSummaryStats = 0, + eCsrGlobalClassAStats, + eCsrGlobalClassBStats, + eCsrGlobalClassCStats, + eCsrGlobalClassDStats, + eCsrPerStaStats, + eCsrMaxStats +}eCsrRoamStatsClassTypes; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +typedef enum +{ + eCSR_WLAN_STATUS_CONNECT =0, + eCSR_WLAN_STATUS_DISCONNECT + +}eCsrDiagWlanStatusEventSubtype; + +typedef enum +{ + eCSR_REASON_UNSPECIFIED = 0, + eCSR_REASON_USER_REQUESTED, + eCSR_REASON_MIC_ERROR, + eCSR_REASON_DISASSOC, + eCSR_REASON_DEAUTH, + eCSR_REASON_HANDOFF, + +}eCsrDiagWlanStatusEventReason; + +typedef enum +{ + eCSR_EVENT_TYPE_INVALID = 0, + eCSR_EVENT_SCAN_COMPLETE = 72, + eCSR_EVENT_SCAN_RES_FOUND = 73, +} eCSR_WLAN_DIAG_EVENT_TYPE; + +#endif //FEATURE_WLAN_DIAG_SUPPORT + +typedef struct tagCsrChannel +{ + tANI_U8 numChannels; + tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +}tCsrChannel; + +typedef struct tagScanProfile +{ + tANI_U32 minChnTime; + tANI_U32 maxChnTime; + /* In units of milliseconds, ignored when not connected */ + tANI_U32 restTime; //This is ignored if not associated + /* In units of milliseconds, ignored when not connected */ + tANI_U32 min_rest_time; + /* In units of milliseconds, ignored when not connected */ + tANI_U32 idle_time; + tANI_U32 numOfChannels; + tANI_U8 *pChannelList; + tSirScanType scanType; //active or passive + eCsrRoamBssType bssType; //BSS or IBSS + tANI_U8 ssid[WNI_CFG_SSID_LEN]; + tANI_U8 bReturnAfter1stMatch; + tANI_U8 fUniqueResult; + tANI_U8 freshScan; + tCsrBssid bssid; +}tScanProfile; + +typedef struct tagBssConfigParam +{ + eCsrMediaAccessType qosType; + tSirMacSSid SSID; + tANI_U32 uRTSThresh; + tANI_U32 uDeferThresh; // + eCsrCfgDot11Mode uCfgDot11Mode; + eCsrBand eBand; + tANI_U8 standardRate[CSR_DOT11_SUPPORTED_RATES_MAX]; + tANI_U8 extendedRate[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX]; + eCsrExposedTxRate txRate; + tAniAuthType authType; + eCsrEncryptionType encType; + tANI_U32 uShortSlotTime; + tANI_U32 uHTSupport; //High throughput + tANI_U32 uPowerLimit; + tANI_U32 uHeartBeatThresh; + tANI_U32 uJoinTimeOut; + tSirMacCapabilityInfo BssCap; + tANI_BOOLEAN f11hSupport; + ePhyChanBondState cbMode; +}tBssConfigParam; + + +typedef struct tagCsrRoamStartBssParams +{ + tSirMacSSid ssId; + tCsrBssid bssid; //this is the BSSID for the party we want to join (only use for IBSS or WDS) + tSirNwType sirNwType; + ePhyChanBondState cbMode; + tSirMacRateSet operationalRateSet; + tSirMacRateSet extendedRateSet; + tANI_U8 operationChn; + tANI_U8 vht_channel_width; + eCsrCfgDot11Mode uCfgDot11Mode; + tANI_U8 privacy; + tANI_BOOLEAN fwdWPSPBCProbeReq; + tANI_BOOLEAN protEnabled; + tANI_BOOLEAN obssProtEnabled; + tAniAuthType authType; + tANI_U16 beaconInterval; //If this is 0, SME will fill in for caller. + tANI_U16 ht_protection; + tANI_U32 dtimPeriod; + tANI_U8 ApUapsdEnable; + tANI_U8 ssidHidden; + tANI_U8 wps_state; + tVOS_CON_MODE bssPersona; + tANI_U16 nRSNIELength; //The byte count in the pRSNIE, if 0, pRSNIE is ignored. + tANI_U8 *pRSNIE; //If not null, it has the IE byte stream for RSN + tANI_BOOLEAN updatebeaconInterval; //Flag used to indicate update + // beaconInterval +#ifdef WLAN_FEATURE_11W + tANI_BOOLEAN mfpCapable; + tANI_BOOLEAN mfpRequired; +#endif + + tSirAddIeParams addIeParams; + uint8_t sap_dot11mc; + +}tCsrRoamStartBssParams; + + +typedef struct tagScanCmd +{ + tANI_U32 scanID; + csrScanCompleteCallback callback; + void *pContext; + eCsrScanReason reason; + eCsrRoamState lastRoamState[CSR_ROAM_SESSION_MAX]; + tCsrRoamProfile *pToRoamProfile; + tANI_U32 roamId; //this is the ID related to the pToRoamProfile + union + { + tCsrScanRequest scanRequest; + tCsrBGScanRequest bgScanRequest; + }u; + //This flag will be set while aborting the scan due to band change + tANI_BOOLEAN abortScanDueToBandChange; +}tScanCmd; + +typedef struct tagRoamCmd +{ + tANI_U32 roamId; + eCsrRoamReason roamReason; + tCsrRoamProfile roamProfile; + tScanResultHandle hBSSList; //BSS list fits the profile + tListElem *pRoamBssEntry; //point to the current BSS in the list that is roaming. It starts from head to tail + tSirBssDescription *pLastRoamBss; //the last BSS we try and failed + tANI_BOOLEAN fReleaseBssList; //whether to free hBSSList + tANI_BOOLEAN fReleaseProfile; //whether to free roamProfile + tANI_BOOLEAN fReassoc; //whether this command is for reassociation + tANI_BOOLEAN fUpdateCurRoamProfile; //whether pMac->roam.pCurRoamProfile needs to be updated + //this is for CSR internal used only. And it should not be assigned when creating the command + //This causes the roam command not to do anything. + tANI_BOOLEAN fReassocToSelfNoCapChange; + + tANI_BOOLEAN fStopWds; + tSirMacAddr peerMac; + tSirMacReasonCodes reason; +}tRoamCmd; + +typedef struct tagSetKeyCmd +{ + tANI_U32 roamId; + eCsrEncryptionType encType; + eCsrAuthType authType; + tAniKeyDirection keyDirection; //Tx, Rx or Tx-and-Rx + tSirMacAddr peerMac; //Peer's MAC address. ALL 1's for group key + tANI_U8 paeRole; //0 for supplicant + tANI_U8 keyId; // Kye index + tANI_U8 keyLength; //Number of bytes containing the key in pKey + tANI_U8 Key[CSR_MAX_KEY_LEN]; + tANI_U8 keyRsc[CSR_MAX_RSC_LEN]; +} tSetKeyCmd; + +typedef struct tahRemoveKeyCmd +{ + tANI_U32 roamId; + eCsrEncryptionType encType; + eCsrAuthType authType; + tSirMacAddr peerMac; //Peer's MAC address. ALL 1's for group key + tANI_U8 keyId; //key index +} tRemoveKeyCmd; + +typedef struct tagWmStatusChangeCmd +{ + eCsrRoamWmStatusChangeTypes Type; + union + { + tSirSmeDeauthInd DeauthIndMsg; + tSirSmeDisassocInd DisassocIndMsg; + }u; + +}tWmStatusChangeCmd; + + +typedef struct tagAddStaForSessionCmd +{ + //Session self mac addr + tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; + tANI_U32 type; + tANI_U32 subType; + tANI_U8 sessionId; +}tAddStaForSessionCmd; + +typedef struct tagDelStaForSessionCmd +{ + //Session self mac addr + tSirMacAddr selfMacAddr; + csrRoamSessionCloseCallback callback; + void *pContext; +}tDelStaForSessionCmd; + +//This structure represents one scan request +typedef struct tagCsrCmd +{ + tListElem Link; + eCsrRoamCommands command; + tANI_U8 sessionId; // Session ID for this command + union + { + tScanCmd scanCmd; + tRoamCmd roamCmd; + tWmStatusChangeCmd wmStatusChangeCmd; + tSetKeyCmd setKeyCmd; + tRemoveKeyCmd removeKeyCmd; + tAddStaForSessionCmd addStaSessionCmd; + tDelStaForSessionCmd delStaSessionCmd; + }u; +}tCsrCmd; + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct tagCsr11rConfig +{ + tANI_BOOLEAN IsFTResourceReqSupported; +} tCsr11rConfig; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +typedef struct tagCsrNeighborRoamConfig +{ + tANI_U32 nNeighborScanTimerPeriod; + tANI_U8 nNeighborLookupRssiThreshold; + tANI_U8 nNeighborReassocRssiThreshold; + tANI_U16 nNeighborScanMinChanTime; + tANI_U16 nNeighborScanMaxChanTime; + sCsrChannel neighborScanChanList; + tANI_U8 nMaxNeighborRetries; + tANI_U16 nNeighborResultsRefreshPeriod; + tANI_U16 nEmptyScanRefreshPeriod; + tANI_U8 nOpportunisticThresholdDiff; + tANI_U8 nRoamRescanRssiDiff; + tANI_U8 nRoamBmissFirstBcnt; + tANI_U8 nRoamBmissFinalBcnt; + tANI_U8 nRoamBeaconRssiWeight; + tANI_U8 delay_before_vdev_stop; + uint32_t nhi_rssi_scan_max_count; + uint32_t nhi_rssi_scan_rssi_delta; + uint32_t nhi_rssi_scan_delay; + int32_t nhi_rssi_scan_rssi_ub; +}tCsrNeighborRoamConfig; +#endif + +typedef struct tagCsrConfig +{ + tANI_U32 agingCount; + tANI_U32 FragmentationThreshold; + tANI_U32 channelBondingMode24GHz; + tANI_U32 channelBondingMode5GHz; + uint32_t stacbmode; + tANI_U32 RTSThreshold; + eCsrPhyMode phyMode; + eCsrCfgDot11Mode uCfgDot11Mode; + eCsrBand eBand; + tANI_U32 HeartbeatThresh50; + tANI_U32 HeartbeatThresh24; + tANI_U32 bgScanInterval; + eCsrCBChoice cbChoice; + eCsrBand bandCapability; //indicate hw capability + eCsrRoamWmmUserModeType WMMSupportMode; + tANI_BOOLEAN Is11eSupportEnabled; + tANI_BOOLEAN Is11dSupportEnabled; + tANI_BOOLEAN Is11dSupportEnabledOriginal; + tANI_BOOLEAN Is11hSupportEnabled; + tANI_BOOLEAN shortSlotTime; + tANI_BOOLEAN ProprietaryRatesEnabled; + tANI_BOOLEAN fenableMCCMode; + bool mcc_rts_cts_prot_enable; + bool mcc_bcast_prob_resp_enable; + tANI_U16 TxRate; + tANI_U8 fAllowMCCGODiffBI; + tANI_U8 AdHocChannel24; + tANI_U8 AdHocChannel5G; + tANI_U32 impsSleepTime; //in units of microseconds + tANI_U32 scanAgeTimeNCNPS; //scan result aging time threshold when Not-Connect-No-Power-Save, in seconds + tANI_U32 scanAgeTimeNCPS; //scan result aging time threshold when Not-Connect-Power-Save, in seconds + tANI_U32 scanAgeTimeCNPS; //scan result aging time threshold when Connect-No-Power-Save, in seconds, + tANI_U32 scanAgeTimeCPS; //scan result aging time threshold when Connect-Power-Savein seconds + tANI_U32 BssPreferValue[CSR_NUM_RSSI_CAT]; //each RSSI category has one value + int RSSICat[CSR_NUM_RSSI_CAT]; + tANI_U8 bCatRssiOffset; //to set the RSSI difference for each category + tANI_U32 nRoamingTime; //In seconds, CSR will try this long before gives up, 0 means no roaming + //Whether to limit the channels to the ones set in Csr11dInfo. If true, the opertaional + //channels are limited to the default channel list. It is an "AND" operation between the + //default channels and the channels in the 802.11d IE. + tANI_BOOLEAN fEnforce11dChannels; + //Country Code Priority + //0 = 802.11D > Configured Country > NV + //1 = Configured Country > 802.11D > NV + tANI_BOOLEAN fSupplicantCountryCodeHasPriority; + //When true, AP with unknown country code won't be see. + //"Unknown country code" means either Ap doesn't have 11d IE or we cannot + //find a domain for the country code in its 11d IE. + tANI_BOOLEAN fEnforceCountryCodeMatch; + //When true, only APs in the default domain can be seen. If the Ap has "unknown country + //code", or the doamin of the country code doesn't match the default domain, the Ap is + //not acceptable. + tANI_BOOLEAN fEnforceDefaultDomain; + + tANI_U16 vccRssiThreshold; + tANI_U32 vccUlMacLossThreshold; + + tANI_U32 nPassiveMinChnTime; //in units of milliseconds + tANI_U32 nPassiveMaxChnTime; //in units of milliseconds + tANI_U32 nActiveMinChnTime; //in units of milliseconds + tANI_U32 nActiveMaxChnTime; //in units of milliseconds + + tANI_U32 nInitialDwellTime; //in units of milliseconds + bool initial_scan_no_dfs_chnl; + + tANI_U32 nActiveMinChnTimeBtc; //in units of milliseconds + tANI_U32 nActiveMaxChnTimeBtc; //in units of milliseconds + tANI_U8 disableAggWithBtc; +#ifdef WLAN_AP_STA_CONCURRENCY + tANI_U32 nPassiveMinChnTimeConc; //in units of milliseconds + tANI_U32 nPassiveMaxChnTimeConc; //in units of milliseconds + tANI_U32 nActiveMinChnTimeConc; //in units of milliseconds + tANI_U32 nActiveMaxChnTimeConc; //in units of milliseconds + /* In units of milliseconds */ + tANI_U32 nRestTimeConc; + /* In units of milliseconds */ + tANI_U32 min_rest_time_conc; + /* In units of milliseconds */ + tANI_U32 idle_time_conc; + + tANI_U8 nNumStaChanCombinedConc; //number of channels combined for + //Sta in each split scan operation + tANI_U8 nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation +#endif + + tANI_BOOLEAN IsIdleScanEnabled; + //in dBm, the maximum TX power + //The actual TX power is the lesser of this value and 11d. + //If 11d is disable, the lesser of this and default setting. + tANI_U8 nTxPowerCap; + tANI_U32 statsReqPeriodicity; //stats request frequency from PE while in full power + tANI_U32 statsReqPeriodicityInPS;//stats request frequency from PE while in power save + tANI_U32 dtimPeriod; + tANI_BOOLEAN ssidHidden; + +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsr11rConfig csr11rConfig; +#endif + +#ifdef FEATURE_WLAN_LFR + tANI_U8 isFastRoamIniFeatureEnabled; + tANI_U8 MAWCEnabled; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tANI_U8 isRoamOffloadScanEnabled; + tANI_BOOLEAN bFastRoamInConIniFeatureEnabled; +#endif +#endif + +#ifdef FEATURE_WLAN_ESE + tANI_U8 isEseIniFeatureEnabled; +#endif + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_U8 nImmediateRoamRssiDiff; + tANI_BOOLEAN nRoamPrefer5GHz; + tANI_BOOLEAN nRoamIntraBand; + tANI_BOOLEAN isWESModeEnabled; + tANI_BOOLEAN nRoamScanControl; + tANI_U8 nProbes; + tANI_U16 nRoamScanHomeAwayTime; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + tCsrNeighborRoamConfig neighborRoamConfig; +#endif + + /* Instead of Reassoc, send ADDTS/DELTS even when ACM is off for that AC + * This is mandated by WMM-AC certification */ + tANI_BOOLEAN addTSWhenACMIsOff; + + tANI_BOOLEAN fValidateList; + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + tANI_BOOLEAN doBMPSWorkaround; + + //To enable/disable scanning 2.4Ghz channels twice on a single scan request from HDD + tANI_BOOLEAN fScanTwice; +#ifdef WLAN_FEATURE_11AC + tANI_U32 nVhtChannelWidth; + tANI_U8 txBFEnable; + tANI_U8 txBFCsnValue; + tANI_U8 enable2x2; + tANI_BOOLEAN enableVhtFor24GHz; + tANI_U8 txMuBformee; + tANI_U8 enableVhtpAid; + tANI_U8 enableVhtGid; +#endif + tANI_U8 enableAmpduPs; + tANI_U8 enableHtSmps; + tANI_U8 htSmps; + tANI_U8 txLdpcEnable; + + /* + * Enable/Disable heartbeat offload + */ + tANI_BOOLEAN enableHeartBeatOffload; + tANI_U8 max_amsdu_num; + tANI_U8 nSelect5GHzMargin; + tANI_U8 isCoalesingInIBSSAllowed; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tANI_U8 cc_switch_mode; +#endif + tANI_U8 allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_BOOLEAN isRoamOffloadEnabled; +#endif + tANI_BOOLEAN obssEnabled; + v_U8_t conc_custom_rule1; + v_U8_t conc_custom_rule2; + v_U8_t is_sta_connection_in_5gz_enabled; + struct roam_ext_params roam_params; + tANI_BOOLEAN sendDeauthBeforeCon; + tANI_BOOLEAN ignorePeerErpInfo; + v_U16_t pkt_err_disconn_th; +}tCsrConfig; + +typedef struct tagCsrChannelPowerInfo +{ + tListElem link; + tANI_U8 firstChannel; + tANI_U8 numChannels; + tANI_U8 txPower; + tANI_U8 interChannelOffset; +}tCsrChannelPowerInfo; + +typedef struct tagRoamJoinStatus +{ + tSirResultCodes statusCode; + //this is set to unspecified if statusCode indicates timeout. Or it is the failed reason from the other BSS(per 802.11 spec) + tANI_U32 reasonCode; + tSirMacAddr bssId; +}tCsrRoamJoinStatus; + +typedef struct tagCsrOsChannelMask +{ + tANI_U8 numChannels; + tANI_BOOLEAN scanEnabled[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +}tCsrOsChannelMask; + +typedef struct tagCsrVotes11d +{ + tANI_U8 votes; + tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN]; +}tCsrVotes11d; + +typedef struct tagCsrScanStruct +{ + tScanProfile scanProfile; + tANI_U32 nextScanID; + tDblLinkList scanResultList; + tDblLinkList tempScanResults; + tANI_BOOLEAN fScanEnable; + tANI_BOOLEAN fFullScanIssued; + vos_timer_t hTimerGetResult; +#ifdef WLAN_AP_STA_CONCURRENCY + vos_timer_t hTimerStaApConcTimer; +#endif + vos_timer_t hTimerIdleScan; + vos_timer_t hTimerResultCfgAging; + //changes on every scan, it is used as a flag for whether 11d info is found on every scan + tANI_U8 channelOf11dInfo; + tANI_U8 scanResultCfgAgingTime; + //changes on every scan, a flag to tell whether conflict 11d info found on each BSS + tANI_BOOLEAN fAmbiguous11dInfoFound; + //changes on every scan, a flag to tell whether the applied 11d info present in one of the scan results + tANI_BOOLEAN fCurrent11dInfoMatch; + tANI_BOOLEAN f11dInfoReset; //to indicate whether the 11d info in CFG is reset to default + tSirScanType curScanType; + tCsrChannel baseChannels; //This are all the supported channels AND(&) to the current eBand + tCsrChannel channels11d; + tChannelListWithPower defaultPowerTable[WNI_CFG_VALID_CHANNEL_LIST_LEN]; //From NV + tChannelListWithPower defaultPowerTable40MHz[WNI_CFG_VALID_CHANNEL_LIST_LEN]; //From NV + tANI_U32 numChannelsDefault; //total channels of NV + tCsrChannel base20MHzChannels; //The channel base to work on + tCsrChannel base40MHzChannels; //center channels for 40MHz channels + tDblLinkList channelPowerInfoList24; + tDblLinkList channelPowerInfoList5G; + tANI_U32 nLastAgeTimeOut; + tANI_U32 nAgingCountDown; + tANI_U8 countryCodeDefault[WNI_CFG_COUNTRY_CODE_LEN]; //The country code from NV + tANI_U8 countryCodeCurrent[WNI_CFG_COUNTRY_CODE_LEN]; + tANI_U8 countryCode11d[WNI_CFG_COUNTRY_CODE_LEN]; + v_REGDOMAIN_t domainIdDefault; //default regulatory domain + v_REGDOMAIN_t domainIdCurrent; //current regulatory domain + tCsrBssid currentCountryBssid; // Bssid for current country code + tANI_S8 currentCountryRSSI; // RSSI for current country code + tANI_BOOLEAN f11dInfoApplied; + tANI_BOOLEAN fCancelIdleScan; + tANI_U8 countryCodeCount; + tCsrVotes11d votes11d[CSR_MAX_NUM_COUNTRY_CODE]; //counts for various advertized country codes + //in 11d IE from probe rsp or beacons of neighboring APs; + //will use the most popular one (max count) + tANI_U8 countryCodeElected[WNI_CFG_COUNTRY_CODE_LEN]; + + tANI_U8 numBGScanChannel; //number of valid channels in the bgScanChannelList + tANI_U8 bgScanChannelList[WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN]; + //the ChannelInfo member is not used in this structure. + //numBGScanChannel and bgScanChannelList are used for the BG scan channel info + tCsrBGScanRequest bgScanParams; + tANI_BOOLEAN fRestartIdleScan; + tANI_U32 nIdleScanTimeGap; //the time since last trying to trigger idle scan + tCsrOsChannelMask osScanChannelMask;//keep a track of channels to be scnned while in traffic condition + tANI_U16 nBssLimit; //the maximum number of BSS in scan cache + /*channelPowerInfoList24 has been seen corrupted. Set this flag to true trying to + * detect when it happens. Adding this into code because we can't reproduce it easily. + * We don't know when it happens. */ + tANI_BOOLEAN fValidateList; + /*Customer wants to start with an active scan based on the default country code. + * This optimization will minimize the driver load to association time. + * Based on this flag we will bypass the initial passive scan needed for 11d + * to determine the country code & domain */ + tANI_BOOLEAN fEnableBypass11d; + + /*Customer wants to optimize the scan time. Avoiding scans(passive) on DFS + * channels while swipping through both bands can save some time + * (apprx 1.3 sec) */ + tANI_U8 fEnableDFSChnlScan; + + /* + * To enable/disable scanning only 2.4Ghz channels on first scan + */ + tANI_BOOLEAN fFirstScanOnly2GChnl; + + tANI_BOOLEAN fDropScanCmd; //true means we don't accept scan commands + +#ifdef WLAN_AP_STA_CONCURRENCY + tDblLinkList scanCmdPendingList; +#endif + /* This includes all channels on which candidate APs are found */ + tCsrChannel occupiedChannels[CSR_ROAM_SESSION_MAX]; + tANI_S8 inScanResultBestAPRssi; + eCsrBand scanBandPreference; //This defines the band perference for scan + csrScanCompleteCallback callback11dScanDone; + bool fcc_constraint; +}tCsrScanStruct; + +//Save the connected information. This structure + connectedProfile +//should contain all information about the connection +typedef struct tagRoamCsrConnectedInfo +{ + tANI_U32 nBeaconLength; //the length, in bytes, of the beacon frame, can be 0 + tANI_U32 nAssocReqLength; //the length, in bytes, of the assoc req frame, can be 0 + tANI_U32 nAssocRspLength; //The length, in bytes, of the assoc rsp frame, can be 0 +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_U32 nRICRspLength; //Length of the parsed RIC response IEs received in reassoc response +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U32 nTspecIeLength; +#endif + tANI_U8 *pbFrames; //Point to a buffer contain the beacon, assoc req, assoc rsp frame, in that order + //user needs to use nBeaconLength, nAssocReqLength, nAssocRspLength to desice where + //each frame starts and ends. + tANI_U8 staId; +}tCsrRoamConnectedInfo; + + +typedef struct tagCsrLinkQualityIndInfo +{ + csrRoamLinkQualityIndCallback callback; + void *context; +}tCsrLinkQualityIndInfo; + +typedef struct tagCsrPeStatsReqInfo +{ + tListElem link; /* list links */ + tANI_U32 statsMask; + tANI_U32 periodicity; + tANI_BOOLEAN rspPending; + vos_timer_t hPeStatsTimer; + tANI_BOOLEAN timerRunning; + tANI_U8 staId; + tANI_U8 numClient; + tpAniSirGlobal pMac; + /* To remember if the peStats timer is stopped successfully or not */ + tANI_BOOLEAN timerStopFailed; + tANI_U8 sessionId; + +}tCsrPeStatsReqInfo; + +typedef struct tagCsrStatsClientReqInfo +{ + tListElem link; /* list links */ + eCsrStatsRequesterType requesterId; + tCsrStatsCallback callback; + tANI_U32 periodicity; + void *pContext; + tANI_U32 statsMask; + tCsrPeStatsReqInfo *pPeStaEntry; + tANI_U8 staId; + vos_timer_t timer; + tANI_BOOLEAN timerExpired; + tpAniSirGlobal pMac; // TODO: Confirm this change BTAMP + tANI_U8 sessionId; +}tCsrStatsClientReqInfo; + +typedef struct tagCsrTlStatsReqInfo +{ + tANI_U32 periodicity; + tANI_BOOLEAN timerRunning; + vos_timer_t hTlStatsTimer; + tANI_U8 numClient; +}tCsrTlStatsReqInfo; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +typedef enum +{ + + /* reassociation is done but couldn't finish security handshake */ + eSIR_ROAM_AUTH_STATUS_CONNECTED = 1, + + /* roam successfully completed by firmware */ + eSIR_ROAM_AUTH_STATUS_AUTHENTICATED = 2, + + /* unknown error */ + eSIR_ROAM_AUTH_STATUS_UNKNOWN = 0xff + +} tCsrRoamOffloadAuthStatus; +typedef struct tagCsrRoamOffloadSynchStruct +{ + tANI_U8 roamedVdevId; /* vdevId after roaming */ + tANI_S8 txMgmtPower; /* HAL fills in the tx power used for */ + tANI_U8 rssi; /* RSSI */ + tANI_U8 roamReason; /* Roam reason */ + tANI_U8 nss; /* no of spatial streams */ + tANI_U16 chainMask; /* chainmask */ + tANI_U16 smpsMode; /* smps.mode */ + tSirMacAddr bssid; /* MAC address of roamed AP */ + tANI_BOOLEAN bRoamSynchInProgress; /* a roam offload synch*/ + tCsrRoamOffloadAuthStatus authStatus; /* authentication + status */ + tANI_U8 kck[SIR_KCK_KEY_LEN]; + tANI_U8 kek[SIR_KEK_KEY_LEN]; + tANI_U8 replay_ctr[SIR_REPLAY_CTR_LEN]; + tpSirBssDescription pbssDescription; /*BSS descriptor*/ +} tCsrRoamOffloadSynchStruct; +#endif + +typedef struct tagCsrRoamStoredProfile +{ + tANI_U32 session_id; + tCsrRoamProfile profile; + tScanResultHandle bsslist_handle; + eCsrRoamReason reason; + tANI_U32 roam_id; + tANI_BOOLEAN imediate_flag; + tANI_BOOLEAN clear_flag; +} tCsrRoamStoredProfile; + +typedef struct tagCsrRoamSession +{ + tANI_U8 sessionId; // Session ID + tANI_BOOLEAN sessionActive; // TRUE if it is used + tCsrBssid selfMacAddr; // For BT-AMP station, this serve as BSSID for self-BSS. + csrRoamCompleteCallback callback; + void *pContext; + eCsrConnectState connectState; + tCsrRoamConnectedProfile connectedProfile; + tCsrRoamConnectedInfo connectedInfo; + tCsrRoamProfile *pCurRoamProfile; + tSirBssDescription *pConnectBssDesc; + tANI_U16 NumPmkidCache; /* valid no. of pmkid in the cache */ + uint16_t curr_cache_idx; /* the index in pmkidcache to write next to */ + tPmkidCacheInfo PmkidCacheInfo[CSR_MAX_PMKID_ALLOWED]; + tANI_U8 cJoinAttemps; + //This may or may not have the up-to-date valid channel list + //It is used to get WNI_CFG_VALID_CHANNEL_LIST and not allocate memory all the time + tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_S32 sPendingCommands; //0 means CSR is ok to low power +#ifdef FEATURE_WLAN_WAPI + tANI_U16 NumBkidCache; + tBkidCacheInfo BkidCacheInfo[CSR_MAX_BKID_ALLOWED]; +#endif /* FEATURE_WLAN_WAPI */ + tANI_BOOLEAN fRoaming; //indicate whether CSR is roaming (either via lostlink or dynamic roaming) + //to remember some parameters needed for START_BSS. + //All member must be set every time we try to join or start an IBSS or BT-AMP + tCsrRoamStartBssParams bssParams; + tANI_U32 nWpaRsnReqIeLength; //the byte count of pWpaRsnIE; + tANI_U8 *pWpaRsnReqIE; //this contain the WPA/RSN IE in assoc request or the one sent in beacon (IBSS) + tANI_U32 nWpaRsnRspIeLength; //the byte count for pWpaRsnRspIE + tANI_U8 *pWpaRsnRspIE; //this contain the WPA/RSN IE in beacon/probe rsp +#ifdef FEATURE_WLAN_WAPI + tANI_U32 nWapiReqIeLength; //the byte count of pWapiReqIE; + tANI_U8 *pWapiReqIE; //this contain the WAPI IE in assoc request or the one sent in beacon (IBSS) + tANI_U32 nWapiRspIeLength; //the byte count for pWapiRspIE + tANI_U8 *pWapiRspIE; //this contain the WAPI IE in beacon/probe rsp +#endif /* FEATURE_WLAN_WAPI */ + tANI_U32 nAddIEScanLength; //the byte count of pAddIeScanIE; + tANI_U8 *pAddIEScan; //this contains the additional IE in (unicast) probe request at the time of join + tANI_U32 nAddIEAssocLength; //the byte count for pAddIeAssocIE + tANI_U8 *pAddIEAssoc; //this contains the additional IE in (re) assoc request + + tANI_TIMESTAMP roamingStartTime; //in units of 10ms + tCsrTimerInfo roamingTimerInfo; + eCsrRoamingReason roamingReason; + tANI_BOOLEAN fCancelRoaming; + vos_timer_t hTimerRoaming; + eCsrRoamResult roamResult; //the roamResult that is used when the roaming timer fires + tCsrRoamJoinStatus joinFailStatusCode; //This is the reason code for join(assoc) failure + //The status code returned from PE for deauth or disassoc (in case of lostlink), or our own dynamic roaming + tANI_U32 roamingStatusCode; + tANI_U16 NumPmkidCandidate; + tPmkidCandidateInfo PmkidCandidateInfo[CSR_MAX_PMKID_ALLOWED]; + #ifdef FEATURE_WLAN_WAPI + tANI_U16 NumBkidCandidate; + tBkidCandidateInfo BkidCandidateInfo[CSR_MAX_BKID_ALLOWED]; +#endif + tANI_BOOLEAN fWMMConnection; + tANI_BOOLEAN fQOSConnection; + +#ifdef FEATURE_WLAN_ESE + tCsrEseCckmInfo eseCckmInfo; + tANI_BOOLEAN isPrevApInfoValid; + tSirMacSSid prevApSSID; + tCsrBssid prevApBssid; + tANI_U8 prevOpChannel; + tANI_U16 clientDissSecs; + tANI_U32 roamTS1; +#if defined(FEATURE_WLAN_ESE_UPLOAD) + tCsrEseCckmIe suppCckmIeInfo; +#endif +#endif + tANI_U8 bRefAssocStartCnt; //Tracking assoc start indication + //ht config + tSirHTConfig htConfig; +#ifdef FEATURE_WLAN_SCAN_PNO + tANI_BOOLEAN pnoStarted; +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tCsrRoamOffloadSynchStruct roamOffloadSynchParams; + tANI_U8 psk_pmk[SIR_ROAM_SCAN_PSK_SIZE]; + size_t pmk_len; + tANI_U8 RoamKeyMgmtOffloadEnabled; +#endif + + /* SME FT Context */ +#if defined WLAN_FEATURE_VOWIFI_11R + tftSMEContext ftSmeContext; +#endif + uint8_t join_bssid_count; /* This count represents the number of + * bssid's we are trying to join. + */ + tCsrRoamStoredProfile stored_roam_profile; + bool ch_switch_in_progress; + bool supported_nss_1x1; + bool disable_hi_rssi; +} tCsrRoamSession; + +typedef struct tagCsrRoamStruct +{ + tANI_U32 nextRoamId; + tDblLinkList roamCmdPendingList; + tDblLinkList channelList5G; + tDblLinkList channelList24; + tCsrConfig configParam; + tANI_U32 numChannelsEeprom; //total channels of eeprom + tCsrChannel base20MHzChannels; //The channel base to work on + tCsrChannel base40MHzChannels; //center channels for 40MHz channels + eCsrRoamState curState[CSR_ROAM_SESSION_MAX]; + eCsrRoamSubState curSubState[CSR_ROAM_SESSION_MAX]; + //This may or may not have the up-to-date valid channel list + //It is used to get WNI_CFG_VALID_CHANNEL_LIST and not allocate memory all the time + tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_U32 numValidChannels; //total number of channels in CFG + + tANI_S32 sPendingCommands; + vos_timer_t hTimerWaitForKey; //To support timeout for WaitForKey state + tCsrSummaryStatsInfo summaryStatsInfo; + tCsrGlobalClassAStatsInfo classAStatsInfo; + tCsrGlobalClassBStatsInfo classBStatsInfo; + tCsrGlobalClassCStatsInfo classCStatsInfo; + tCsrGlobalClassDStatsInfo classDStatsInfo; + tCsrPerStaStatsInfo perStaStatsInfo[CSR_MAX_STA]; + tDblLinkList statsClientReqList; + tDblLinkList peStatsReqList; + tCsrTlStatsReqInfo tlStatsReqInfo; + eCsrRoamLinkQualityInd vccLinkQuality; + tCsrLinkQualityIndInfo linkQualityIndInfo; + v_CONTEXT_t gVosContext; //used for interaction with TL + /* TODO : Upto here */ + tCsrTimerInfo WaitForKeyTimerInfo; + tCsrRoamSession *roamSession; + tANI_U32 transactionId; // Current transaction ID for internal use. +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + tCsrNeighborRoamControlInfo neighborRoamInfo[CSR_ROAM_SESSION_MAX]; +#endif +#ifdef FEATURE_WLAN_LFR + tANI_U8 isFastRoamIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + tANI_U8 isEseIniFeatureEnabled; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tANI_U8 RoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; +#endif + tANI_U32 deauthRspStatus; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U8 *pReassocResp; /* reassociation response from new AP */ + tANI_U16 reassocRespLen; /* length of reassociation response */ +#endif +}tCsrRoamStruct; + + +#define GET_NEXT_ROAM_ID(pRoamStruct) (((pRoamStruct)->nextRoamId + 1 == 0) ? 1 : (pRoamStruct)->nextRoamId) +#define CSR_IS_ROAM_STATE(pMac, state, sessionId) ( (state) == (pMac)->roam.curState[sessionId] ) + +#define CSR_IS_ROAM_STOP(pMac, sessionId) CSR_IS_ROAM_STATE( (pMac), eCSR_ROAMING_STATE_STOP, sessionId ) +#define CSR_IS_ROAM_INIT(pMac, sessionId) CSR_IS_ROAM_STATE( (pMac), eCSR_ROAMING_STATE_INIT, sessionId ) +#define CSR_IS_ROAM_SCANNING(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_SCANNING, sessionId ) +#define CSR_IS_ROAM_JOINING(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_JOINING, sessionId ) +#define CSR_IS_ROAM_IDLE(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_IDLE, sessionId ) +#define CSR_IS_ROAM_JOINED(pMac, sessionId) CSR_IS_ROAM_STATE( pMac, eCSR_ROAMING_STATE_JOINED, sessionId ) + +#define CSR_IS_ROAM_SUBSTATE(pMac, subState, sessionId) ((subState) == (pMac)->roam.curSubState[sessionId]) +#define CSR_IS_ROAM_SUBSTATE_JOIN_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_AUTH_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_AUTH_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_REASSOC_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_REASSOC_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN, sessionId) +#define CSR_IS_ROAM_SUBSTATE_REASSOC_FAIL(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, sessionId) +#define CSR_IS_ROAM_SUBSTATE_DISASSOC_FORCED(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_FORCED, sessionId) +#define CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DEAUTH_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_START_BSS_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_START_BSS_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_STOP_BSS_REQ, sessionId) +#define CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, sessionId) +#define CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_CONFIG, sessionId) +#define CSR_IS_ROAM_SUBSTATE_WAITFORKEY(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, sessionId) +#define CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF, sessionId) +#define CSR_IS_ROAM_SUBSTATE_HO_NT(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC, sessionId) +#define CSR_IS_ROAM_SUBSTATE_HO_NRT(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC, sessionId) +#define CSR_IS_ROAM_SUBSTATE_HO_RT(pMac, sessionId) CSR_IS_ROAM_SUBSTATE((pMac), eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC, sessionId) + +#define CSR_IS_PHY_MODE_B_ONLY(pMac) \ + ((eCSR_DOT11_MODE_11b == (pMac)->roam.configParam.phyMode) ||\ + (eCSR_DOT11_MODE_11b_ONLY == (pMac)->roam.configParam.phyMode)) + +#define CSR_IS_PHY_MODE_G_ONLY(pMac) \ + (eCSR_DOT11_MODE_11g == (pMac)->roam.configParam.phyMode || eCSR_DOT11_MODE_11g_ONLY == (pMac)->roam.configParam.phyMode) + +#define CSR_IS_PHY_MODE_A_ONLY(pMac) \ + (eCSR_DOT11_MODE_11a == (pMac)->roam.configParam.phyMode) + +#ifdef WLAN_FEATURE_11AC +#define CSR_IS_PHY_MODE_DUAL_BAND(phyMode) \ + ((eCSR_DOT11_MODE_abg & (phyMode)) || (eCSR_DOT11_MODE_11n & (phyMode)) || \ + (eCSR_DOT11_MODE_11ac & (phyMode)) || \ + (eCSR_DOT11_MODE_AUTO & (phyMode))) +#else +#define CSR_IS_PHY_MODE_DUAL_BAND(phyMode) \ + ((eCSR_DOT11_MODE_abg & (phyMode)) || (eCSR_DOT11_MODE_11n & (phyMode)) || \ + (eCSR_DOT11_MODE_AUTO & (phyMode))) +#endif + + +// this function returns TRUE if the NIC is operating exclusively in the 2.4 GHz band, meaning +// it is NOT operating in the 5.0 GHz band. +#define CSR_IS_24_BAND_ONLY(pMac) \ + (eCSR_BAND_24 == (pMac)->roam.configParam.eBand) + +#define CSR_IS_5G_BAND_ONLY(pMac) \ + (eCSR_BAND_5G == (pMac)->roam.configParam.eBand) + +#define CSR_IS_RADIO_DUAL_BAND(pMac) \ + (eCSR_BAND_ALL == (pMac)->roam.configParam.bandCapability) + +#define CSR_IS_RADIO_BG_ONLY(pMac) \ + (eCSR_BAND_24 == (pMac)->roam.configParam.bandCapability) + +// this function returns TRUE if the NIC is operating exclusively in the 5.0 GHz band, meaning +// it is NOT operating in the 2.4 GHz band +#define CSR_IS_RADIO_A_ONLY(pMac) \ + (eCSR_BAND_5G == (pMac)->roam.configParam.bandCapability) + +// this function returns TRUE if the NIC is operating in both bands. +#define CSR_IS_OPEARTING_DUAL_BAND(pMac) \ + ((eCSR_BAND_ALL == (pMac)->roam.configParam.bandCapability) && (eCSR_BAND_ALL == (pMac)->roam.configParam.eBand)) + +// this function returns TRUE if the NIC can operate in the 5.0 GHz band (could operate in the +// 2.4 GHz band also). +#define CSR_IS_OPERATING_A_BAND(pMac) \ + (CSR_IS_OPEARTING_DUAL_BAND((pMac)) || CSR_IS_RADIO_A_ONLY((pMac)) || CSR_IS_5G_BAND_ONLY((pMac))) + +// this function returns TRUE if the NIC can operate in the 2.4 GHz band (could operate in the +// 5.0 GHz band also). +#define CSR_IS_OPERATING_BG_BAND(pMac) \ + (CSR_IS_OPEARTING_DUAL_BAND((pMac)) || CSR_IS_RADIO_BG_ONLY((pMac)) || CSR_IS_24_BAND_ONLY((pMac))) + +#define CSR_IS_CHANNEL_5GHZ(chnNum) \ + (((chnNum) >= CSR_MIN_5GHz_CHANNEL_NUMBER) && ((chnNum) <= CSR_MAX_5GHz_CHANNEL_NUMBER)) + +#define CSR_IS_CHANNEL_DFS(chnNum) \ + (NV_CHANNEL_ENABLE != vos_nv_getChannelEnabledState(chnNum)) + +#define CSR_IS_CHANNEL_24GHZ(chnNum) \ + (((chnNum) > 0) && ((chnNum) <= CSR_MAX_24GHz_CHANNEL_NUMBER)) + +#define CSR_IS_SAME_BAND_CHANNELS(ch1, ch2) (CSR_IS_CHANNEL_5GHZ(ch1) == CSR_IS_CHANNEL_5GHZ(ch2)) + + +#define CSR_IS_11D_INFO_FOUND(pMac) \ + (0 != (pMac)->scan.channelOf11dInfo) +// DEAUTHIND +#define CSR_IS_ROAMING(pSession) ((CSR_IS_LOSTLINK_ROAMING((pSession)->roamingReason)) || \ + (eCsrDynamicRoaming == (pSession)->roamingReason) || \ + (eCsrReassocRoaming == (pSession)->roamingReason)) + + +#define CSR_IS_SET_KEY_COMMAND( pCommand ) ( eSmeCommandSetKey == (pCommand)->command ) + +#define CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) (pMac->roam.configParam.addTSWhenACMIsOff) +// DEAUTHIND +#define CSR_IS_LOSTLINK_ROAMING(reason) ((eCsrLostlinkRoamingDisassoc == (reason)) || (eCsrLostlinkRoamingDeauth == (reason))) + +#define CSR_IS_ROAMING_COMMAND(pCommand) ((eCsrLostLink1 == (pCommand)->u.roamCmd.roamReason) ||\ + (eCsrLostLink2 == (pCommand)->u.roamCmd.roamReason) ||\ + (eCsrLostLink3 == (pCommand)->u.roamCmd.roamReason) ) + + +//Stop CSR from asking for IMPS, This function doesn't disable IMPS from CSR +void csrScanSuspendIMPS( tpAniSirGlobal pMac ); +//Start CSR from asking for IMPS. This function doesn't trigger CSR to request entering IMPS +//because IMPS maybe disabled. +void csrScanResumeIMPS( tpAniSirGlobal pMac ); + +eHalStatus csrInitGetChannels(tpAniSirGlobal pMac); +eHalStatus csrScanFilter11dResult(tpAniSirGlobal pMac); + +eHalStatus csrScanFilterResults(tpAniSirGlobal pMac); + +eHalStatus csrSetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamModifyProfileFields *pModifyProfileFields); +/* --------------------------------------------------------------------------- + \fn csrGetModifyProfileFields + \brief HDD or SME - QOS calls this function to get the current values of + connected profile fields changing which can cause reassoc. + This function must be called after CFG is downloaded and STA is in connected + state. + \param pModifyProfileFields - pointer to the connected profile fields + changing which can cause reassoc + + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrGetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamModifyProfileFields * pModifyProfileFields); +void csrSetGlobalCfgs( tpAniSirGlobal pMac ); +void csrSetDefaultDot11Mode( tpAniSirGlobal pMac ); +void csrScanSetChannelMask(tpAniSirGlobal pMac, tCsrChannelInfo *pChannelInfo); +tANI_BOOLEAN csrIsConnStateDisconnected(tpAniSirGlobal pMac, tANI_U32 sessionId); +tANI_BOOLEAN csrIsConnStateConnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateDisconnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateConnectedInfra( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateConnected( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateInfra( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateIbss( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateWds( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateConnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsConnStateDisconnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId ); +tANI_BOOLEAN csrIsAnySessionInConnectState( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsAllSessionDisconnected( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsStaSessionConnected( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsP2pSessionConnected( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsAnySessionConnected( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsInfraConnected( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsConcurrentInfraConnected( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsConcurrentSessionRunning( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsInfraApStarted( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsIBSSStarted( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsBTAMPStarted( tpAniSirGlobal pMac ); +tANI_BOOLEAN csrIsBTAMP( tpAniSirGlobal pMac, tANI_U32 sessionId ); +eHalStatus csrIsBTAMPAllowed( tpAniSirGlobal pMac, tANI_U32 chnId ); +tANI_BOOLEAN csrIsValidMcConcurrentSession(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirBssDescription *pBssDesc); +tANI_BOOLEAN csrIsConnStateConnectedInfraAp( tpAniSirGlobal pMac, tANI_U32 sessionId ); +/*---------------------------------------------------------------------------- + \fn csrRoamRegisterLinkQualityIndCallback + + \brief + a CSR function to allow HDD to register a callback handler with CSR for + link quality indications. + + Only one callback may be registered at any time. + In order to deregister the callback, a NULL cback may be provided. + + Registration happens in the task context of the caller. + + \param callback - Call back being registered + \param pContext - user data + + DEPENDENCIES: After CSR open + + \return eHalStatus +-----------------------------------------------------------------------------*/ +eHalStatus csrRoamRegisterLinkQualityIndCallback(tpAniSirGlobal pMac, + csrRoamLinkQualityIndCallback callback, + void *pContext); +/* --------------------------------------------------------------------------- + \fn csrGetStatistics + \brief csr function that client calls to register a callback to get + different PHY level statistics from CSR. + + \param requesterId - different client requesting for statistics, HDD, UMA/GAN etc + \param statsMask - The different category/categories of stats requester is looking for + \param callback - SME sends back the requested stats using the callback + \param periodicity - If requester needs periodic update, 0 means it's an one + time request + \param cache - If requester is happy with cached stats + \param staId - The station ID for which the stats is requested for + \param pContext - user context to be passed back along with the callback + \param sessionId - sme session Id. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requesterId, + tANI_U32 statsMask, + tCsrStatsCallback callback, + tANI_U32 periodicity, tANI_BOOLEAN cache, + tANI_U8 staId, void *pContext, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn csrGetTLSTAState + \helper function to get the TL STA State whenever the function is called. + + \param staId - The staID to be passed to the TL + to get the relevant TL STA State + \return the state as tANI_U16 + ---------------------------------------------------------------------------*/ +tANI_U16 csrGetTLSTAState(tpAniSirGlobal pMac, tANI_U8 staId); + +/* --------------------------------------------------------------------------- + \fn csrGetRssi + \ creates SME req packet for getRSSI and post to Self + + \param pMac - global MAC context + \param callback - hdd callback function to be called once FW returns the + RSSI value + \param staId - The staID to be passed to the TL to get the relevant + TL STA State + \param bssID - bssid for which RSSI is requested + \param lastRSSI - RSSI value at time of request. In case request cannot + be sent to firmware, do not hold up but return this value. + \param pContext - user context to be passed back along with the callback + \param pVosContext - vos conext + \return the state as tANI_U16 + ---------------------------------------------------------------------------*/ +eHalStatus csrGetRssi(tpAniSirGlobal pMac,tCsrRssiCallback callback, + tANI_U8 staId, tCsrBssid bssId, tANI_S8 lastRSSI, + void * pContext,void * pVosContext); + +/* --------------------------------------------------------------------------- + \fn csrGetSnr + \brief csr function that client calls to register a callback to get + SNR stored in TL + + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param bssid - The bssid for the connected session + \param pContext - user context to be passed back along with the callback + + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrGetSnr(tpAniSirGlobal pMac, tCsrSnrCallback callback, + tANI_U8 staId, tCsrBssid bssId, void *pContext); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +eHalStatus csrGetTsmStats(tpAniSirGlobal pMac, + tCsrTsmStatsCallback callback, + tANI_U8 staId, + tCsrBssid bssId, + void *pContext, + void* pVosContext, + tANI_U8 tid); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/* --------------------------------------------------------------------------- + \fn csrGetConfigParam + \brief HDD calls this function to get the global settings currently maintained by CSR. + \param pParam - caller allocated memory + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam); + +/* --------------------------------------------------------------------------- + \fn csrMsgProcessor + \brief HDD calls this function to change some global settings. + caller must set the all fields or call csrGetConfigParam to prefill the fields. + \param pParam - caller allocated memory + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam); + + +/* --------------------------------------------------------------------------- + \fn csrMsgProcessor + \brief HDD calls this function for the messages that are handled by CSR. + \param pMsgBuf - a pointer to a buffer that maps to various structures base on the message type. + The beginning of the buffer can always map to tSirSmeRsp. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ); + +/* --------------------------------------------------------------------------- + \fn csrOpen + \brief This function must be called before any API call to CSR. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrOpen(tpAniSirGlobal pMac); +/* --------------------------------------------------------------------------- + \fn csr_init_chan_list + \brief This function needs to called to initialize channel information, + which, for discrete, will come from targer fw. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csr_init_chan_list(tpAniSirGlobal mac, v_U8_t *alpha2); + +/* --------------------------------------------------------------------------- + \fn csrClose + \brief To close down CSR module. There should not be any API call into CSR after calling this function. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrClose(tpAniSirGlobal pMac); +/* --------------------------------------------------------------------------- + \fn csrStart + \brief To start CSR. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrStart(tpAniSirGlobal pMac); +/* --------------------------------------------------------------------------- + \fn csrStop + \brief To stop CSR. CSR still keeps its current setting. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrStop(tpAniSirGlobal pMac, tHalStopType stopType); +/* --------------------------------------------------------------------------- + \fn csrReady + \brief To let CSR is ready to operate + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrReady(tpAniSirGlobal pMac); + +#ifdef FEATURE_WLAN_WAPI + +eHalStatus csrScanGetBKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId, + tBkidCandidateInfo *pBkidList, tANI_U32 *pNumItems ); +/* --------------------------------------------------------------------------- + \fn csrRoamGetWapiReqIE + \brief return the WAPI IE CSR passes to PE to JOIN request or START_BSS request + \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the + needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetWapiReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetWapiRspIE + \brief return the WAPI IE from the beacon or probe rsp if connected + \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the + needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetWapiRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf); +tANI_U8 csrConstructWapiIe( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe ); +#endif /* FEATURE_WLAN_WAPI */ + +eHalStatus csrRoamUpdateAPWPSIE( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirAPWPSIEs *pAPWPSIES ); +eHalStatus csrRoamUpdateWPARSNIEs( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirRSNie * pAPSirRSNie); +void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOLEAN fPrivacy ); +tANI_S8 csrGetInfraSessionId( tpAniSirGlobal pMac ); +tANI_U8 csrGetInfraOperationChannel( tpAniSirGlobal pMac, tANI_U8 sessionId); +tANI_BOOLEAN csrIsSessionClientAndConnected(tpAniSirGlobal pMac, tANI_U8 sessionId); +tANI_U8 csrGetConcurrentOperationChannel( tpAniSirGlobal pMac ); + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +v_U16_t csrCheckConcurrentChannelOverlap(tpAniSirGlobal pMac, v_U16_t sap_ch, + eCsrPhyMode sap_phymode, v_U8_t cc_switch_mode ); +#endif +eHalStatus csrRoamCopyConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamConnectedProfile *pProfile); +tANI_BOOLEAN csrIsSetKeyAllowed(tpAniSirGlobal pMac, tANI_U32 sessionId); + +void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac ); +void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pChannelSetList, + tANI_U8 *pChannelList, tANI_U8 bSize, tANI_U8 *pNumChannels ); +#ifdef FEATURE_WLAN_SCAN_PNO +eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd); +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R +//Returns whether the current association is a 11r assoc or not +tANI_BOOLEAN csrRoamIs11rAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId); +#endif + +#ifdef FEATURE_WLAN_ESE +//Returns whether the current association is a ESE assoc or not +tANI_BOOLEAN csrRoamIsESEAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId); +tANI_BOOLEAN csrRoamIsEseIniFeatureEnabled(tpAniSirGlobal pMac); +tANI_BOOLEAN csrNeighborRoamIsESEAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId); +#endif + +//Remove this code once SLM_Sessionization is supported +//BMPS_WORKAROUND_NOT_NEEDED +void csrDisconnectAllActiveSessions(tpAniSirGlobal pMac); + +#ifdef FEATURE_WLAN_LFR +//Returns whether "Legacy Fast Roaming" is enabled...or not +tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac); +#endif +tANI_BOOLEAN csrIsChannelPresentInList( tANI_U8 *pChannelList, int numChannels, tANI_U8 channel ); +VOS_STATUS csrAddToChannelListFront( tANI_U8 *pChannelList, int numChannels, tANI_U8 channel ); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, + csrScanCompleteCallback callback, void *pContext); +eHalStatus csrRoamOffloadScanRspHdlr(tpAniSirGlobal pMac, + tpSirRoamOffloadScanRsp scanOffloadRsp); +eHalStatus csrHandoffRequest(tpAniSirGlobal pMac, tANI_U8 sessionId, + tCsrHandoffRequest *pHandoffInfo); +#endif +tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId); +#endif + +/* Post Channel Change Indication */ +eHalStatus csrRoamChannelChangeReq(tpAniSirGlobal pMac, tCsrBssid bssid, + tANI_U8 cbMode, tCsrRoamProfile *pprofile); + +/* Post Beacon Tx Start Indication */ +eHalStatus csrRoamStartBeaconReq( tpAniSirGlobal pMac, + tCsrBssid bssid, tANI_U8 dfsCacWaitStatus); + +eHalStatus +csrRoamSendChanSwIERequest(tpAniSirGlobal pMac, tCsrBssid bssid, + tANI_U8 targetChannel, tANI_U8 csaIeReqd, + u_int8_t ch_bandwidth); + +/*---------------------------------------------------------------------------- + \fn csrRoamModifyAddIEs + \brief This function sends msg to modify the additional IE buffers in PE + \param pMac - pMac global structure + \param pModifyIE - pointer to tSirModifyIE structure + \param updateType - Type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus +csrRoamModifyAddIEs(tpAniSirGlobal pMac, + tSirModifyIE *pModifyIE, + eUpdateIEsType updateType); + + +/*---------------------------------------------------------------------------- + \fn csrRoamUpdateAddIEs + \brief This function sends msg to updates the additional IE buffers in PE + \param pMac - pMac global structure + \param pUpdateIE - pointer to tSirUpdateIE structure + \param updateType, - type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus +csrRoamUpdateAddIEs(tpAniSirGlobal pMac, + tSirUpdateIE *pUpdateIE, + eUpdateIEsType updateType); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void csrProcessRoamOffloadSynchInd(tHalHandle hHal, + tpSirRoamOffloadSynchInd pSmeRoamOffloadSynchInd); +eHalStatus csrScanSaveRoamOffloadApToScanCache(tpAniSirGlobal pMac, + tSirRoamOffloadSynchInd *pRoamOffloadSynchInd); +void csrProcessHOFailInd(tpAniSirGlobal pMac, void *pMsgBuf); +#endif +bool csr_store_joinreq_param(tpAniSirGlobal mac_ctx, + tCsrRoamProfile *profile, + tScanResultHandle scan_cache, + uint32_t *roam_id, + uint32_t session_id); +bool csr_clear_joinreq_param(tpAniSirGlobal mac_ctx, + tANI_U32 session_id); +eHalStatus csr_issue_stored_joinreq(tpAniSirGlobal mac_ctx, + uint32_t *roam_id, + uint32_t session_id); +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void csr_diag_event_report(tpAniSirGlobal pmac, uint16_t event_type, + uint16_t status, uint16_t reasoncode); +#endif +#endif + diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrLinkList.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrLinkList.h new file mode 100644 index 000000000000..ed647bbc39d4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrLinkList.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csrLinkList.h + + Exports and types for the Common link list interfaces. +========================================================================== */ +#ifndef CSR_LINK_LIST_H__ +#define CSR_LINK_LIST_H__ + +#include "vos_lock.h" + + +#define LL_ACCESS_LOCK eANI_BOOLEAN_TRUE +#define LL_ACCESS_NOLOCK eANI_BOOLEAN_FALSE + +typedef struct tagListElem +{ + struct tagListElem *last; + struct tagListElem *next; +}tListElem; + +typedef enum +{ + LIST_FLAG_CLOSE = 0, + LIST_FLAG_OPEN = 0xa1b2c4d7, +}tListFlag; + +//This is a circular double link list +typedef struct tagDblLinkList +{ + tListElem ListHead; + vos_lock_t Lock; + tANI_U32 Count; + tHddHandle hHdd; + tListFlag Flag; + + /*command debugging */ + tANI_U32 cmdTimeoutDuration; /* command timeout duration */ + vos_timer_t *cmdTimeoutTimer; /*command timeout Timer */ +}tDblLinkList; + +//To get the address of an object of (type) base on the (address) of one of its (field) +#define GET_BASE_ADDR(address, type, field) ((type *)( \ + (tANI_U8 *)(address) - \ + (tANI_U8 *)(&((type *)0)->field))) + +//To get the offset of (field) inside structure (type) +#define GET_FIELD_OFFSET(type, field) ((uintptr_t)(&(((type *)0)->field))) + +#define GET_ROUND_UP( _Field, _Boundary ) (((_Field) + ((_Boundary) - 1)) & ~((_Boundary) - 1)) +#define BITS_ON( _Field, _Bitmask ) ( (_Field) |= (_Bitmask) ) +#define BITS_OFF( _Field, _Bitmask ) ( (_Field) &= ~(_Bitmask) ) + +#define CSR_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define CSR_MIN(a, b) ((a) < (b) ? (a) : (b)) + + +#define csrIsListEmpty(pHead) ((pHead)->next == (pHead)) + +tANI_U32 csrLLCount( tDblLinkList *pList ); + +eHalStatus csrLLOpen( tHddHandle hHdd, tDblLinkList *pList ); +void csrLLClose( tDblLinkList *pList ); + +void csrLLLock( tDblLinkList *pList ); +void csrLLUnlock( tDblLinkList *pList ); + +tANI_BOOLEAN csrLLIsListEmpty( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ); + +void csrLLInsertHead( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ); +void csrLLInsertTail( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ); +//This function put pNewEntry before pEntry. Caller should have found pEntry +void csrLLInsertEntry( tDblLinkList *pList, tListElem *pEntry, tListElem *pNewEntry, tANI_BOOLEAN fInterlocked ); + +tListElem *csrLLPeekHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ); +tListElem *csrLLPeekTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ); + +tListElem *csrLLRemoveHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ); +tListElem *csrLLRemoveTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ); +tANI_BOOLEAN csrLLRemoveEntry( tDblLinkList *pList, tListElem *pEntryToRemove, tANI_BOOLEAN fInterlocked ); +void csrLLPurge( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ); + +//csrLLNext return NULL if reaching the end or list is empty +tListElem *csrLLNext( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ); + +tListElem *csrLLPrevious( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ); + +tANI_BOOLEAN csrLLFindEntry( tDblLinkList *pList, tListElem *pEntryToFind ); + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrNeighborRoam.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrNeighborRoam.h new file mode 100644 index 000000000000..c674c200c526 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrNeighborRoam.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrNeighborRoam.h + + Exports and types for the neighbor roaming algorithm which is sepcifically + designed for Android. +========================================================================== */ +#ifndef CSR_NEIGHBOR_ROAM_H +#define CSR_NEIGHBOR_ROAM_H + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "sme_Api.h" + +#define ROAM_AP_AGE_LIMIT_MS 10000 + +/* Enumeration of various states in neighbor roam algorithm */ +typedef enum +{ + eCSR_NEIGHBOR_ROAM_STATE_CLOSED, + eCSR_NEIGHBOR_ROAM_STATE_INIT, + eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN, + eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING, +#ifdef WLAN_FEATURE_VOWIFI_11R + eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY, + eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN, + eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING, + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE, +#endif /* WLAN_FEATURE_VOWIFI_11R */ + eNEIGHBOR_STATE_MAX +} eCsrNeighborRoamState; + +/* Parameters that are obtained from CFG */ +typedef struct sCsrNeighborRoamCfgParams +{ + tANI_U8 maxNeighborRetries; + tANI_U32 neighborScanPeriod; + tCsrChannelInfo channelInfo; + tANI_U8 neighborLookupThreshold; + tANI_U8 neighborReassocThreshold; + tANI_U32 minChannelScanTime; + tANI_U32 maxChannelScanTime; + tANI_U16 neighborResultsRefreshPeriod; + tANI_U16 emptyScanRefreshPeriod; + tANI_U8 nOpportunisticThresholdDiff; + tANI_U8 nRoamRescanRssiDiff; + tANI_U8 nRoamBmissFirstBcnt; + tANI_U8 nRoamBmissFinalBcnt; + tANI_U8 nRoamBeaconRssiWeight; + tANI_U8 delay_before_vdev_stop; + uint32_t hi_rssi_scan_max_count; + uint32_t hi_rssi_scan_rssi_delta; + uint32_t hi_rssi_scan_delay; + int32_t hi_rssi_scan_rssi_ub; +} tCsrNeighborRoamCfgParams, *tpCsrNeighborRoamCfgParams; + +#define CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX 255 +typedef struct sCsrNeighborRoamChannelInfo +{ + tANI_BOOLEAN IAPPNeighborListReceived; // Flag to mark reception of IAPP Neighbor list + tANI_BOOLEAN chanListScanInProgress; + tANI_U8 currentChanIndex; //Current channel index that is being scanned + tCsrChannelInfo currentChannelListInfo; //Max number of channels in channel list and the list of channels +} tCsrNeighborRoamChannelInfo, *tpCsrNeighborRoamChannelInfo; + +typedef struct sCsrNeighborRoamBSSInfo +{ + tListElem List; + tANI_U8 apPreferenceVal; +// tCsrScanResultInfo *scanResultInfo; + tpSirBssDescription pBssDescription; +} tCsrNeighborRoamBSSInfo, *tpCsrNeighborRoamBSSInfo; + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define CSR_NEIGHBOR_ROAM_REPORT_QUERY_TIMEOUT 1000 //in milliseconds +#define CSR_NEIGHBOR_ROAM_PREAUTH_RSP_WAIT_MULTIPLIER 10 //in milliseconds +#define MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS 10 //Max number of MAC addresses with which the pre-auth was failed +#define MAX_BSS_IN_NEIGHBOR_RPT 15 +#define CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES 3 + +/* Black listed APs. List of MAC Addresses with which the Preauthentication was failed. */ +typedef struct sCsrPreauthFailListInfo +{ + tANI_U8 numMACAddress; + tSirMacAddr macAddress[MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS]; +} tCsrPreauthFailListInfo, *tpCsrPreauthFailListInfo; + +typedef struct sCsrNeighborReportBssInfo +{ + tANI_U8 channelNum; + tANI_U8 neighborScore; + tSirMacAddr neighborBssId; +} tCsrNeighborReportBssInfo, *tpCsrNeighborReportBssInfo; + +typedef struct sCsr11rAssocNeighborInfo +{ + tANI_BOOLEAN preauthRspPending; + tANI_BOOLEAN neighborRptPending; + tANI_U8 currentNeighborRptRetryNum; + tCsrPreauthFailListInfo preAuthFailList; + tANI_U32 neighborReportTimeout; + tANI_U32 PEPreauthRespTimeout; + tANI_U8 numPreAuthRetries; + tDblLinkList preAuthDoneList; /* Linked list which consists or preauthenticated nodes */ + tANI_U8 numBssFromNeighborReport; + tCsrNeighborReportBssInfo neighboReportBssInfo[MAX_BSS_IN_NEIGHBOR_RPT]; //Contains info needed during REPORT_SCAN State +} tCsr11rAssocNeighborInfo, *tpCsr11rAssocNeighborInfo; +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* + * Set lookup UP threshold 5 dB higher than the configured + * lookup DOWN threshold to minimize thrashing between + * DOWN and UP events. + */ +#define NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD \ + (pNeighborRoamInfo->cfgParams.neighborLookupThreshold-5) +#ifdef FEATURE_WLAN_LFR +typedef enum +{ + eFirstEmptyScan=1, + eSecondEmptyScan, + eThirdEmptyScan, + eFourthEmptyScan, + eFifthEmptyScan, + eMaxEmptyScan=eFifthEmptyScan, +} eNeighborRoamEmptyScanCount; + +typedef enum +{ + DEFAULT_SCAN=0, + SPLIT_SCAN_OCCUPIED_LIST=1, +} eNeighborRoamScanMode; +#endif + +/* Complete control information for neighbor roam algorithm */ +typedef struct sCsrNeighborRoamControlInfo +{ + eCsrNeighborRoamState neighborRoamState; + eCsrNeighborRoamState prevNeighborRoamState; + tCsrNeighborRoamCfgParams cfgParams; + tCsrBssid currAPbssid; // current assoc AP + tANI_U8 currAPoperationChannel; // current assoc AP + vos_timer_t neighborScanTimer; + vos_timer_t neighborResultsRefreshTimer; + vos_timer_t emptyScanRefreshTimer; + tCsrTimerInfo neighborScanTimerInfo; + tCsrNeighborRoamChannelInfo roamChannelInfo; + tANI_U8 currentNeighborLookupThreshold; + tANI_U8 currentOpportunisticThresholdDiff; + tANI_U8 currentRoamRescanRssiDiff; + tANI_BOOLEAN scanRspPending; + tANI_TIMESTAMP scanRequestTimeStamp; + tDblLinkList roamableAPList; // List of current FT candidates + tCsrRoamProfile csrNeighborRoamProfile; +#ifdef WLAN_FEATURE_VOWIFI_11R + tANI_BOOLEAN is11rAssoc; + tCsr11rAssocNeighborInfo FTRoamInfo; +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef FEATURE_WLAN_ESE + tANI_BOOLEAN isESEAssoc; + tANI_BOOLEAN isVOAdmitted; + tANI_U32 MinQBssLoadRequired; +#endif +#ifdef FEATURE_WLAN_LFR + tANI_U8 uEmptyScanCount; /* Consecutive number of times scan + yielded no results. */ + tCsrRoamConnectedProfile prevConnProfile; /* Previous connected profile. If the + new profile does not match previous + we re-initialize occupied channel list */ + tANI_S8 lookupDOWNRssi; + tANI_U8 uScanMode; + tANI_U8 uOsRequestedHandoff; /* upper layer requested + a reassoc */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tCsrHandoffRequest handoffReqInfo; /* handoff related info came + with upper layer's req for + reassoc */ +#endif +#endif + tSmeFastRoamTrigger cfgRoamEn; + tSirMacAddr cfgRoambssId; + tANI_U8 currentRoamBmissFirstBcnt; + tANI_U8 currentRoamBmissFinalBcnt; + tANI_U8 currentRoamBeaconRssiWeight; + tANI_U8 lastSentCmd; +} tCsrNeighborRoamControlInfo, *tpCsrNeighborRoamControlInfo; + +/* All the necessary Function declarations are here */ +eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, + tANI_U8 sessionId, VOS_STATUS status); +eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, + tANI_U8 sessionId); +tANI_BOOLEAN csrNeighborRoamIsHandoffInProgress(tpAniSirGlobal pMac, + tANI_U8 sessionId); +void csrNeighborRoamRequestHandoff(tpAniSirGlobal pMac, tANI_U8 sessionId); +eHalStatus csrNeighborRoamInit(tpAniSirGlobal pMac, tANI_U8 sessionId); +void csrNeighborRoamClose(tpAniSirGlobal pMac, tANI_U8 sessionId); +void csrNeighborRoamPurgePreauthFailedList(tpAniSirGlobal pMac); +VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac, + tANI_U8 sessionId); +VOS_STATUS csrNeighborRoamTransitionToPreauthDone(tpAniSirGlobal pMac); +eHalStatus csrNeighborRoamPrepareScanProfileFilter(tpAniSirGlobal pMac, + tCsrScanResultFilter *pScanFilter, + tANI_U8 sessionId); +bool csrNeighborRoamGetHandoffAPInfo(tpAniSirGlobal pMac, + tpCsrNeighborRoamBSSInfo pHandoffNode, + tANI_U8 sessionId); +eHalStatus csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tSirRetStatus limStatus); +#ifdef WLAN_FEATURE_VOWIFI_11R +tANI_BOOLEAN csrNeighborRoamIs11rAssoc(tpAniSirGlobal pMac, + tANI_U8 sessionId); +#endif +VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac, + tANI_U8 sessionId); +void csrNeighborRoamTranistionPreauthDoneToDisconnected(tpAniSirGlobal pMac, + tANI_U8 sessionId); +tANI_BOOLEAN csrNeighborRoamStatePreauthDone(tpAniSirGlobal pMac, + tANI_U8 sessionId); +tANI_BOOLEAN csrNeighborRoamScanRspPending(tHalHandle hHal, + tANI_U8 sessionId); +tANI_BOOLEAN csrNeighborMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId); +VOS_STATUS csrNeighborRoamSetLookupRssiThreshold(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t neighborLookupRssiThreshold); +VOS_STATUS +csrNeighborRoamSetOpportunisticScanThresholdDiff(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nOpportunisticThresholdDiff); +VOS_STATUS +csrNeighborRoamSetRoamRescanRssiDiff(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamRescanRssiDiff); +VOS_STATUS +csrNeighborRoamSetRoamBmissFirstBcnt(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamBmissFirstBcnt); +VOS_STATUS +csrNeighborRoamSetRoamBmissFinalBcnt(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamBmissFinalBcnt); +VOS_STATUS +csrNeighborRoamSetRoamBeaconRssiWeight(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamBeaconRssiWeight); +VOS_STATUS csrNeighborRoamUpdateFastRoamingEnabled(tpAniSirGlobal pMac, + tANI_U8 sessionId, + const v_BOOL_t fastRoamEnabled); +VOS_STATUS csrNeighborRoamUpdateEseModeEnabled(tpAniSirGlobal pMac, + tANI_U8 sessionId, + const v_BOOL_t eseMode); +VOS_STATUS csrNeighborRoamChannelsFilterByCurrentBand( + tpAniSirGlobal pMac, + tANI_U8 sessionId, + tANI_U8* pInputChannelList, + tANI_U8 inputNumOfChannels, + tANI_U8* pOutputChannelList, + tANI_U8* pMergedOutputNumOfChannels + ); +VOS_STATUS csrNeighborRoamReassocIndCallback(v_PVOID_t pAdapter, + v_U8_t trafficStatus, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi); +VOS_STATUS csrNeighborRoamMergeChannelLists(tpAniSirGlobal pMac, + tANI_U8 *pInputChannelList, + tANI_U8 inputNumOfChannels, + tANI_U8 *pOutputChannelList, + tANI_U8 outputNumOfChannels, + tANI_U8 *pMergedOutputNumOfChannels); +void csr_roam_reset_roam_params(tpAniSirGlobal mac_ptr); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define ROAM_SCAN_OFFLOAD_START 1 +#define ROAM_SCAN_OFFLOAD_STOP 2 +#define ROAM_SCAN_OFFLOAD_RESTART 3 +#define ROAM_SCAN_OFFLOAD_UPDATE_CFG 4 +#define ROAM_SCAN_OFFLOAD_ABORT_SCAN 5 + +#define REASON_CONNECT 1 +#define REASON_CHANNEL_LIST_CHANGED 2 +#define REASON_LOOKUP_THRESH_CHANGED 3 +#define REASON_DISCONNECTED 4 +#define REASON_RSSI_DIFF_CHANGED 5 +#define REASON_ESE_INI_CFG_CHANGED 6 +#define REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED 7 +#define REASON_VALID_CHANNEL_LIST_CHANGED 8 +#define REASON_FLUSH_CHANNEL_LIST 9 +#define REASON_EMPTY_SCAN_REF_PERIOD_CHANGED 10 +#define REASON_PREAUTH_FAILED_FOR_ALL 11 +#define REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW 12 +#define REASON_NPROBES_CHANGED 13 +#define REASON_HOME_AWAY_TIME_CHANGED 14 +#define REASON_OS_REQUESTED_ROAMING_NOW 15 +#define REASON_SCAN_CH_TIME_CHANGED 16 +#define REASON_SCAN_HOME_TIME_CHANGED 17 +#define REASON_OPPORTUNISTIC_THRESH_DIFF_CHANGED 18 +#define REASON_ROAM_RESCAN_RSSI_DIFF_CHANGED 19 +#define REASON_ROAM_BMISS_FIRST_BCNT_CHANGED 20 +#define REASON_ROAM_BMISS_FINAL_BCNT_CHANGED 21 +#define REASON_ROAM_BEACON_RSSI_WEIGHT_CHANGED 22 +#define REASON_ROAM_DFS_SCAN_MODE_CHANGED 23 +#define REASON_ROAM_ABORT_ROAM_SCAN 24 +#define REASON_ROAM_EXT_SCAN_PARAMS_CHANGED 25 +#define REASON_ROAM_SET_SSID_ALLOWED 26 +#define REASON_ROAM_SET_FAVORED_BSSID 27 +#define REASON_ROAM_GOOD_RSSI_CHANGED 28 +#define REASON_ROAM_SET_BLACKLIST_BSSID 29 +#define REASON_ROAM_SCAN_HI_RSSI_MAXCOUNT_CHANGED 30 +#define REASON_ROAM_SCAN_HI_RSSI_DELTA_CHANGED 31 +#define REASON_ROAM_SCAN_HI_RSSI_DELAY_CHANGED 32 +#define REASON_ROAM_SCAN_HI_RSSI_UB_CHANGED 33 + +eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 sessionId, + tANI_U8 command, tANI_U8 reason); +eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, + void* pMsg); +eHalStatus csrNeighborRoamHandoffReqHdlr(tpAniSirGlobal pMac, void* pMsg); +eHalStatus csrNeighborRoamProceedWithHandoffReq(tpAniSirGlobal pMac, + tANI_U8 sessionId); +eHalStatus csrNeighborRoamSssidScanDone(tpAniSirGlobal pMac, + tANI_U8 sessionId, + eHalStatus status); +eHalStatus csrNeighborRoamStartLfrScan(tpAniSirGlobal pMac, tANI_U8 sessionId); +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +VOS_STATUS csrSetCCKMIe(tpAniSirGlobal pMac, const tANI_U8 sessionId, + const tANI_U8 *pCckmIe, + const tANI_U8 ccKmIeLen); +VOS_STATUS csrRoamReadTSF(tpAniSirGlobal pMac, tANI_U8 *pTimestamp, + const tANI_U8 sessionId); +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus csrRoamOffloadSendSynchCnf(tpAniSirGlobal pMac, tANI_U8 sessionId); +eHalStatus +csrNeighborRoamOffloadUpdatePreauthList(tpAniSirGlobal pMac, + tpSirRoamOffloadSynchInd pSmeRoamOffloadSynchInd, + tANI_U8 sessionId); +#endif +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ + +#endif /* CSR_NEIGHBOR_ROAM_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrSupport.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrSupport.h new file mode 100644 index 000000000000..9244090baf56 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrSupport.h @@ -0,0 +1,816 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrSupport.h + + Exports and types for the Common Scan and Roaming supporting interfaces. +========================================================================== */ +#ifndef CSR_SUPPORT_H__ +#define CSR_SUPPORT_H__ + +#include "csrLinkList.h" +#include "csrApi.h" +#include "vos_nvitem.h" + +#ifdef FEATURE_WLAN_WAPI +#define CSR_WAPI_OUI_SIZE ( 4 ) +#define CSR_WAPI_VERSION_SUPPORTED ( 1 ) +#define CSR_WAPI_MAX_AUTH_SUITES ( 2 ) +#define CSR_WAPI_MAX_CYPHERS ( 5 ) +#define CSR_WAPI_MAX_UNICAST_CYPHERS ( 5 ) +#define CSR_WAPI_MAX_MULTICAST_CYPHERS ( 1 ) +#endif /* FEATURE_WLAN_WAPI */ + +#define CSR_RSN_OUI_SIZE ( 4 ) +#define CSR_RSN_VERSION_SUPPORTED ( 1 ) +#define CSR_RSN_MAX_AUTH_SUITES ( 4 ) +#define CSR_RSN_MAX_CYPHERS ( 5 ) +#define CSR_RSN_MAX_UNICAST_CYPHERS ( 5 ) +#define CSR_RSN_MAX_MULTICAST_CYPHERS ( 1 ) + +#define CSR_WPA_OUI_SIZE ( 4 ) +#define CSR_WPA_VERSION_SUPPORTED ( 1 ) +#define CSR_WME_OUI_SIZE ( 4 ) +#define CSR_WPA_MAX_AUTH_SUITES ( 2 ) +#define CSR_WPA_MAX_CYPHERS ( 5 ) +#define CSR_WPA_MAX_UNICAST_CYPHERS ( 5 ) +#define CSR_WPA_MAX_MULTICAST_CYPHERS ( 1 ) +#define CSR_WPA_IE_MIN_SIZE ( 6 ) // minimum size of the IE->length is the size of the Oui + Version. +#define CSR_WPA_IE_MIN_SIZE_W_MULTICAST ( HDD_WPA_IE_MIN_SIZE + HDD_WPA_OUI_SIZE ) +#define CSR_WPA_IE_MIN_SIZE_W_UNICAST ( HDD_WPA_IE_MIN_SIZE + HDD_WPA_OUI_SIZE + sizeof( pWpaIe->cUnicastCyphers ) ) + +#define CSR_DOT11_SUPPORTED_RATES_MAX ( 12 ) +#define CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ( 8 ) + +#define CSR_DOT11_BASIC_RATE_MASK ( 0x80 ) + +#define CSR_OUI_USE_GROUP_CIPHER_INDEX 0x00 +#define CSR_OUI_WEP40_OR_1X_INDEX 0x01 +#define CSR_OUI_TKIP_OR_PSK_INDEX 0x02 +#define CSR_OUI_RESERVED_INDEX 0x03 +#define CSR_OUI_AES_INDEX 0x04 +#define CSR_OUI_WEP104_INDEX 0x05 + +#ifdef FEATURE_WLAN_WAPI +#define CSR_OUI_WAPI_RESERVED_INDEX 0x00 +#define CSR_OUI_WAPI_WAI_CERT_OR_SMS4_INDEX 0x01 +#define CSR_OUI_WAPI_WAI_PSK_INDEX 0x02 +#define CSR_OUI_WAPI_WAI_MAX_INDEX 0x03 // max index, should be last & highest +#endif /* FEATURE_WLAN_WAPI */ + + +typedef enum +{ + // 11b rates + eCsrSuppRate_1Mbps = 1 * 2, + eCsrSuppRate_2Mbps = 2 * 2, + eCsrSuppRate_5_5Mbps = 11, // 5.5 * 2 + eCsrSuppRate_11Mbps = 11 * 2, + + // 11a / 11g rates + eCsrSuppRate_6Mbps = 6 * 2, + eCsrSuppRate_9Mbps = 9 * 2, + eCsrSuppRate_12Mbps = 12 * 2, + eCsrSuppRate_18Mbps = 18 * 2, + eCsrSuppRate_24Mbps = 24 * 2, + eCsrSuppRate_36Mbps = 36 * 2, + eCsrSuppRate_48Mbps = 48 * 2, + eCsrSuppRate_54Mbps = 54 * 2, + + // airgo proprietary rates + eCsrSuppRate_10Mbps = 10 * 2, + eCsrSuppRate_10_5Mbps= 21, // 10.5 * 2 + eCsrSuppRate_20Mbps = 20 * 2, + eCsrSuppRate_21Mbps = 21 * 2, + eCsrSuppRate_40Mbps = 40 * 2, + eCsrSuppRate_42Mbps = 42 * 2, + eCsrSuppRate_60Mbps = 60 * 2, + eCsrSuppRate_63Mbps = 63 * 2, + eCsrSuppRate_72Mbps = 72 * 2, + eCsrSuppRate_80Mbps = 80 * 2, + eCsrSuppRate_84Mbps = 84 * 2, + eCsrSuppRate_96Mbps = 96 * 2, + eCsrSuppRate_108Mbps = 108 * 2, + eCsrSuppRate_120Mbps = 120 * 2, + eCsrSuppRate_126Mbps = 126 * 2, + eCsrSuppRate_144Mbps = 144 * 2, + eCsrSuppRate_160Mbps = 160 * 2, + eCsrSuppRate_168Mbps = 168 * 2, + eCsrSuppRate_192Mbps = 192 * 2, + eCsrSuppRate_216Mbps = 216 * 2, + eCsrSuppRate_240Mbps = 240 * 2 +}eCsrSupportedRates; + +typedef enum +{ + eCsrPassiveScanNot, //can be scanned actively on the whole 5GHz band + eCsrPassiveScanCat1, //always passive scan from 5250 to 5350MHz + eCsrPassiveScanCat2, //always passive scan from 5250 to 5350MHz, and from 5470 to 5725MHz + eCsrPassiveScanCat3, //always passive scan from 5250 to 5350MHz, from 5470 to 5725MHz, and from 5500 to 5560MHz +}eCsrPassiveScanCat; + + +//Please donot insert in the middle of the enum here because they tie to the indiex +typedef enum +{ + eCSR_COUNTRY_INDEX_US = 0, //Always set US as index 0 + eCSR_COUNTRY_INDEX_ANDORRA, + eCSR_COUNTRY_INDEX_UAE, //United Arab Emirates + eCSR_COUNTRY_INDEX_AFGHANISTAN, + eCSR_COUNTRY_INDEX_ANTIGUA_AND_BARBUDA, + eCSR_COUNTRY_INDEX_ANGUILLA, + eCSR_COUNTRY_INDEX_ALBANIA, + eCSR_COUNTRY_INDEX_ARMENIA, + eCSR_COUNTRY_INDEX_NETHERLANDS_ANTILLES, + eCSR_COUNTRY_INDEX_ANGOLA, + eCSR_COUNTRY_INDEX_ANTARCTICA, + eCSR_COUNTRY_INDEX_ARGENTINA, + eCSR_COUNTRY_INDEX_AMERICAN_SAMOA, + eCSR_COUNTRY_INDEX_AUSTRIA, + eCSR_COUNTRY_INDEX_AUSTRALIA, + eCSR_COUNTRY_INDEX_ARUBA, + eCSR_COUNTRY_INDEX_ALAND_ISLANDS, + eCSR_COUNTRY_INDEX_AZERBAIJAN, + eCSR_COUNTRY_INDEX_BOSNIA_AND_HERZEGOVINA, + eCSR_COUNTRY_INDEX_BARBADOS, + eCSR_COUNTRY_INDEX_BANGLADESH, + eCSR_COUNTRY_INDEX_BELGIUM, + eCSR_COUNTRY_INDEX_BURKINA_FASO, + eCSR_COUNTRY_INDEX_BULGARIA, + eCSR_COUNTRY_INDEX_BAHRAIN, + eCSR_COUNTRY_INDEX_BURUNDI, + eCSR_COUNTRY_INDEX_BENIN, + eCSR_COUNTRY_INDEX_SAINT_BARTHELEMY, + eCSR_COUNTRY_INDEX_BERMUDA, + eCSR_COUNTRY_INDEX_BRUNEI_DARUSSALAM, + eCSR_COUNTRY_INDEX_BOLVIA, + eCSR_COUNTRY_INDEX_BRAZIL, + eCSR_COUNTRY_INDEX_BAHAMAS, + eCSR_COUNTRY_INDEX_BHUTAN, + eCSR_COUNTRY_INDEX_BOUVET_ISLAND, + eCSR_COUNTRY_INDEX_BOTSWANA, + eCSR_COUNTRY_INDEX_BELARUS, + eCSR_COUNTRY_INDEX_BELIZE, + eCSR_COUNTRY_INDEX_CANADA, + eCSR_COUNTRY_INDEX_COCOS_KEELING_ISLANDS, + eCSR_COUNTRY_INDEX_CONGO_REP, + eCSR_COUNTRY_INDEX_CENTRAL_AFRICAN, + eCSR_COUNTRY_INDEX_CONGO, + eCSR_COUNTRY_INDEX_SWITZERLAND, + eCSR_COUNTRY_INDEX_COTE_DIVOIRE, + eCSR_COUNTRY_INDEX_COOK_ISLANDS, + eCSR_COUNTRY_INDEX_CHILE, + eCSR_COUNTRY_INDEX_CAMEROON, + eCSR_COUNTRY_INDEX_CHINA, + eCSR_COUNTRY_INDEX_COLUMBIA, + eCSR_COUNTRY_INDEX_COSTA_RICA, + eCSR_COUNTRY_INDEX_CUBA, + eCSR_COUNTRY_INDEX_CAPE_VERDE, + eCSR_COUNTRY_INDEX_CHRISTMAS_ISLAND, + eCSR_COUNTRY_INDEX_CYPRUS, + eCSR_COUNTRY_INDEX_CZECH, + eCSR_COUNTRY_INDEX_GERMANY, + eCSR_COUNTRY_INDEX_DJIBOUTI, + eCSR_COUNTRY_INDEX_DENMARK, + eCSR_COUNTRY_INDEX_DOMINICA, + eCSR_COUNTRY_INDEX_DOMINICAN_REP, + eCSR_COUNTRY_INDEX_ALGERIA, + eCSR_COUNTRY_INDEX_ECUADOR, + eCSR_COUNTRY_INDEX_ESTONIA, + eCSR_COUNTRY_INDEX_EGYPT, + eCSR_COUNTRY_INDEX_WESTERN_SAHARA, + eCSR_COUNTRY_INDEX_ERITREA, + eCSR_COUNTRY_INDEX_SPAIN, + eCSR_COUNTRY_INDEX_ETHIOPIA, + eCSR_COUNTRY_INDEX_FINLAND, + eCSR_COUNTRY_INDEX_FIJI, + eCSR_COUNTRY_INDEX_FALKLAND_ISLANDS, + eCSR_COUNTRY_INDEX_MICRONESIA, + eCSR_COUNTRY_INDEX_FAROE_ISLANDS, + eCSR_COUNTRY_INDEX_FRANCE, + eCSR_COUNTRY_INDEX_GABON, + eCSR_COUNTRY_INDEX_UNITED_KINGDOM, + eCSR_COUNTRY_INDEX_GRENADA, + eCSR_COUNTRY_INDEX_GEORGIA, + eCSR_COUNTRY_INDEX_FRENCH_GUIANA, + eCSR_COUNTRY_INDEX_GUERNSEY, + eCSR_COUNTRY_INDEX_GHANA, + eCSR_COUNTRY_INDEX_GIBRALTAR, + eCSR_COUNTRY_INDEX_GREENLAND, + eCSR_COUNTRY_INDEX_GAMBIA, + eCSR_COUNTRY_INDEX_GUINEA, + eCSR_COUNTRY_INDEX_GUADELOUPE, + eCSR_COUNTRY_INDEX_EQUATORIAL_GUINEA, + eCSR_COUNTRY_INDEX_GREECE, + eCSR_COUNTRY_INDEX_SOUTH_GEORGIA, + eCSR_COUNTRY_INDEX_GUATEMALA, + eCSR_COUNTRY_INDEX_GUAM, + eCSR_COUNTRY_INDEX_GUINEA_BISSAU, + eCSR_COUNTRY_INDEX_GUYANA, + eCSR_COUNTRY_INDEX_HONGKONG, + eCSR_COUNTRY_INDEX_HEARD_ISLAND, + eCSR_COUNTRY_INDEX_HONDURAS, + eCSR_COUNTRY_INDEX_CROATIA, + eCSR_COUNTRY_INDEX_HAITI, + eCSR_COUNTRY_INDEX_HUNGARY, + eCSR_COUNTRY_INDEX_INDONESIA, + eCSR_COUNTRY_INDEX_IRELAND, + eCSR_COUNTRY_INDEX_ISRAEL, + eCSR_COUNTRY_INDEX_ISLE_OF_MAN, + eCSR_COUNTRY_INDEX_INDIA, + eCSR_COUNTRY_INDEX_BRITISH_INDIAN, + eCSR_COUNTRY_INDEX_IRAQ, + eCSR_COUNTRY_INDEX_IRAN, + eCSR_COUNTRY_INDEX_ICELAND, + eCSR_COUNTRY_INDEX_ITALY, + eCSR_COUNTRY_INDEX_JERSEY, + eCSR_COUNTRY_INDEX_JAMAICA, + eCSR_COUNTRY_INDEX_JORDAN, + eCSR_COUNTRY_INDEX_JAPAN, + eCSR_COUNTRY_INDEX_KENYA, + eCSR_COUNTRY_INDEX_KYRGYZSTAN, + eCSR_COUNTRY_INDEX_CAMBODIA, + eCSR_COUNTRY_INDEX_KIRIBATI, + eCSR_COUNTRY_INDEX_COMOROS, + eCSR_COUNTRY_INDEX_SAINT_KITTS_AND_NEVIS, + eCSR_COUNTRY_INDEX_KOREA_NORTH, + eCSR_COUNTRY_INDEX_KOREA_SOUTH, + eCSR_COUNTRY_INDEX_KUWAIT, + eCSR_COUNTRY_INDEX_CAYMAN_ISLANDS, + eCSR_COUNTRY_INDEX_KAZAKHSTAN, + eCSR_COUNTRY_INDEX_LAO, + eCSR_COUNTRY_INDEX_LEBANON, + eCSR_COUNTRY_INDEX_SAINT_LUCIA, + eCSR_COUNTRY_INDEX_LIECHTENSTEIN, + eCSR_COUNTRY_INDEX_SRI_LANKA, + eCSR_COUNTRY_INDEX_LIBERIA, + eCSR_COUNTRY_INDEX_LESOTHO, + eCSR_COUNTRY_INDEX_LITHUANIA, + eCSR_COUNTRY_INDEX_LUXEMBOURG, + eCSR_COUNTRY_INDEX_LATVIA, + eCSR_COUNTRY_INDEX_LIBYAN_ARAB_JAMAHIRIYA, + eCSR_COUNTRY_INDEX_MOROCCO, + eCSR_COUNTRY_INDEX_MONACO, + eCSR_COUNTRY_INDEX_MOLDOVA, + eCSR_COUNTRY_INDEX_MONTENEGRO, + eCSR_COUNTRY_INDEX_MADAGASCAR, + eCSR_COUNTRY_INDEX_MARSHALL_ISLANDS, + eCSR_COUNTRY_INDEX_MACEDONIA, + eCSR_COUNTRY_INDEX_MALI, + eCSR_COUNTRY_INDEX_MYANMAR, + eCSR_COUNTRY_INDEX_MONGOLIA, + eCSR_COUNTRY_INDEX_MACAO, + eCSR_COUNTRY_INDEX_NORTHERN_MARIANA_ISLANDS, + eCSR_COUNTRY_INDEX_MARTINIQUE, + eCSR_COUNTRY_INDEX_MAURITANIA, + eCSR_COUNTRY_INDEX_MONTSERRAT, + eCSR_COUNTRY_INDEX_MALTA, + eCSR_COUNTRY_INDEX_MAURITIUS, + eCSR_COUNTRY_INDEX_MALDIVES, + eCSR_COUNTRY_INDEX_MALAWI, + eCSR_COUNTRY_INDEX_MEXICO, + eCSR_COUNTRY_INDEX_MALAYSIA, + eCSR_COUNTRY_INDEX_MOZAMBIQUE, + eCSR_COUNTRY_INDEX_NAMIBIA, + eCSR_COUNTRY_INDEX_NEW_CALENDONIA, + eCSR_COUNTRY_INDEX_NIGER, + eCSR_COUNTRY_INDEX_NORFOLK_ISLAND, + eCSR_COUNTRY_INDEX_NIGERIA, + eCSR_COUNTRY_INDEX_NICARAGUA, + eCSR_COUNTRY_INDEX_NETHERLANDS, + eCSR_COUNTRY_INDEX_NORWAY, + eCSR_COUNTRY_INDEX_NEPAL, + eCSR_COUNTRY_INDEX_NAURU, + eCSR_COUNTRY_INDEX_NIUE, + eCSR_COUNTRY_INDEX_NEW_ZEALAND, + eCSR_COUNTRY_INDEX_OMAN, + eCSR_COUNTRY_INDEX_PANAMA, + eCSR_COUNTRY_INDEX_PERU, + eCSR_COUNTRY_INDEX_FRENCH_POLYNESIA, + eCSR_COUNTRY_INDEX_PAPUA_NEW_HUINEA, + eCSR_COUNTRY_INDEX_PHILIPPINES, + eCSR_COUNTRY_INDEX_PAKISTAN, + eCSR_COUNTRY_INDEX_POLAND, + eCSR_COUNTRY_INDEX_SAINT_PIERRE_AND_MIQUELON, + eCSR_COUNTRY_INDEX_PITCAIRN, + eCSR_COUNTRY_INDEX_PUERTO_RICO, + eCSR_COUNTRY_INDEX_PALESTINIAN_TERRITOTY_OCCUPIED, + eCSR_COUNTRY_INDEX_PORTUGAL, + eCSR_COUNTRY_INDEX_PALAU, + eCSR_COUNTRY_INDEX_PARAGUAY, + eCSR_COUNTRY_INDEX_QATAR, + eCSR_COUNTRY_INDEX_REUNION, + eCSR_COUNTRY_INDEX_ROMANIA, + eCSR_COUNTRY_INDEX_SERBIA, + eCSR_COUNTRY_INDEX_RUSSIAN, + eCSR_COUNTRY_INDEX_RWANDA, + eCSR_COUNTRY_INDEX_SAUDI_ARABIA, + eCSR_COUNTRY_INDEX_SOLOMON_ISLANDS, + eCSR_COUNTRY_INDEX_SEYCHELLES, + eCSR_COUNTRY_INDEX_SUDAN, + eCSR_COUNTRY_INDEX_SWEDEN, + eCSR_COUNTRY_INDEX_SINGAPORE, + eCSR_COUNTRY_INDEX_SAINT_HELENA, + eCSR_COUNTRY_INDEX_SLOVENIA, + eCSR_COUNTRY_INDEX_SVALBARD_AND_JAN_MAYEN, + eCSR_COUNTRY_INDEX_SLOVAKIA, + eCSR_COUNTRY_INDEX_SIERRA_LEONE, + eCSR_COUNTRY_INDEX_SAN_MARINO, + eCSR_COUNTRY_INDEX_SENEGAL, + eCSR_COUNTRY_INDEX_SOMOLIA, + eCSR_COUNTRY_INDEX_SURINAME, + eCSR_COUNTRY_INDEX_SAO_TOME_AND_PRINCIPE, + eCSR_COUNTRY_INDEX_EL_SALVADOR, + eCSR_COUNTRY_INDEX_SYRIAN_REP, + eCSR_COUNTRY_INDEX_SWAZILAND, + eCSR_COUNTRY_INDEX_TURKS_AND_CAICOS_ISLANDS, + eCSR_COUNTRY_INDEX_CHAD, + eCSR_COUNTRY_INDEX_FRENCH_SOUTHERN_TERRRTORY, + eCSR_COUNTRY_INDEX_TOGO, + eCSR_COUNTRY_INDEX_THAILAND, + eCSR_COUNTRY_INDEX_TAJIKSTAN, + eCSR_COUNTRY_INDEX_TOKELAU, + eCSR_COUNTRY_INDEX_TIMOR_LESTE, + eCSR_COUNTRY_INDEX_TURKMENISTAN, + eCSR_COUNTRY_INDEX_TUNISIA, + eCSR_COUNTRY_INDEX_TONGA, + eCSR_COUNTRY_INDEX_TURKEY, + eCSR_COUNTRY_INDEX_TRINIDAD_AND_TOBAGO, + eCSR_COUNTRY_INDEX_TUVALU, + eCSR_COUNTRY_INDEX_TAIWAN, + eCSR_COUNTRY_INDEX_TANZANIA, + eCSR_COUNTRY_INDEX_UKRAINE, + eCSR_COUNTRY_INDEX_UGANDA, + eCSR_COUNTRY_INDEX_US_MINOR_OUTLYING_ISLANDS, + eCSR_COUNTRY_INDEX_URUGUAY, + eCSR_COUNTRY_INDEX_UZBEKISTAN, + eCSR_COUNTRY_INDEX_HOLY_SEE, + eCSR_COUNTRY_INDEX_SAINT_VINCENT_AND_THE_GRENADINES, + eCSR_COUNTRY_INDEX_VENESUELA, + eCSR_COUNTRY_INDEX_VIRGIN_ISLANDS_BRITISH, + eCSR_COUNTRY_INDEX_VIRGIN_ISLANDS_US, + eCSR_COUNTRY_INDEX_VIET_NAM, + eCSR_COUNTRY_INDEX_VANUATU, + eCSR_COUNTRY_INDEX_WALLIS_AND_FUTUNA, + eCSR_COUNTRY_INDEX_SAMOA, + eCSR_COUNTRY_INDEX_YEMEN, + eCSR_COUNTRY_INDEX_MAYOTTE, + eCSR_COUNTRY_INDEX_SOTHER_AFRICA, + eCSR_COUNTRY_INDEX_ZAMBIA, + eCSR_COUNTRY_INDEX_ZIMBABWE, + + eCSR_COUNTRY_INDEX_KOREA_1, + eCSR_COUNTRY_INDEX_KOREA_2, + eCSR_COUNTRY_INDEX_KOREA_3, + eCSR_COUNTRY_INDEX_KOREA_4, + + eCSR_NUM_COUNTRY_INDEX, +}eCsrCountryIndex; +//Please donot insert in the middle of the enum above because they tie to the indiex + + +typedef struct tagCsrSirMBMsgHdr +{ + tANI_U16 type; + tANI_U16 msgLen; + +}tCsrSirMBMsgHdr; + +typedef struct tagCsrCfgMsgTlvHdr +{ + tANI_U32 type; + tANI_U32 length; + +}tCsrCfgMsgTlvHdr; + + + +typedef struct tagCsrCfgMsgTlv +{ + tCsrCfgMsgTlvHdr Hdr; + tANI_U32 variable[ 1 ]; // placeholder for the data + +}tCsrCfgMsgTlv; + +typedef struct tagCsrCfgGetRsp +{ + tCsrSirMBMsgHdr hdr; + tANI_U32 respStatus; + tANI_U32 paramId; + tANI_U32 attribLen; + tANI_U32 attribVal[1]; +}tCsrCfgGetRsp; + +typedef struct tagCsrCfgSetRsp +{ + + tCsrSirMBMsgHdr hdr; + tANI_U32 respStatus; + tANI_U32 paramId; +}tCsrCfgSetRsp; + + +typedef struct tagCsrDomainChnScanInfo +{ + tANI_U8 chnId; + tSirScanType scanType; //whether this channel must be scan passively +}tCsrDomainChnScanInfo; + + +#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK) +#pragma pack( push ) +#pragma pack( 1 ) +#elif defined(__ANI_COMPILER_PRAGMA_PACK) +#pragma pack( 1 ) +#endif + +// Generic Information Element Structure +typedef __ani_attr_pre_packed struct sDot11IEHeader +{ + tANI_U8 ElementID; + tANI_U8 Length; +}__ani_attr_packed tDot11IEHeader; + +typedef __ani_attr_pre_packed struct tagCsrWmeInfoIe +{ + tDot11IEHeader IeHeader; + tANI_U8 Oui[ CSR_WME_OUI_SIZE ]; // includes the 3 byte OUI + 1 byte Type + tANI_U8 Subtype; + tANI_U8 Version; + tANI_U8 QoSInfo; + +} __ani_attr_packed tCsrWmeInfoIe; + +typedef __ani_attr_pre_packed struct tagCsrWmeAcParms +{ + tANI_U8 AciAifsn; + tANI_U8 EcwMinEcwMax; + tANI_U16 TxOpLimit; + +} __ani_attr_packed tCsrWmeAcParms; + +typedef __ani_attr_pre_packed struct tagCsrWmeParmIe +{ + tDot11IEHeader IeHeader; + tANI_U8 Oui[ CSR_WME_OUI_SIZE ]; // includes the 3 byte OUI + 1 byte Type + tANI_U8 Subtype; + tANI_U8 Version; + tANI_U8 QoSInfo; + tANI_U8 Reserved; + tCsrWmeAcParms BestEffort; + tCsrWmeAcParms Background; + tCsrWmeAcParms Video; + tCsrWmeAcParms Voice; + +} __ani_attr_packed tCsrWmeParmIe; + +typedef __ani_attr_pre_packed struct tagCsrWpaIe +{ + tDot11IEHeader IeHeader; + tANI_U8 Oui[ CSR_WPA_OUI_SIZE ]; + tANI_U16 Version; + tANI_U8 MulticastOui[ CSR_WPA_OUI_SIZE ]; + tANI_U16 cUnicastCyphers; + + __ani_attr_pre_packed struct { + + tANI_U8 Oui[ CSR_WPA_OUI_SIZE ]; + + } __ani_attr_packed UnicastOui[ 1 ]; + +} __ani_attr_packed tCsrWpaIe; + +typedef __ani_attr_pre_packed struct tagCsrWpaAuthIe +{ + + tANI_U16 cAuthenticationSuites; + + __ani_attr_pre_packed struct { + + tANI_U8 Oui[ CSR_WPA_OUI_SIZE ]; + + } __ani_attr_packed AuthOui[ 1 ]; + +} __ani_attr_packed tCsrWpaAuthIe; + + +typedef __ani_attr_pre_packed struct tagCsrRSNIe +{ + tDot11IEHeader IeHeader; + tANI_U16 Version; + tANI_U8 MulticastOui[ CSR_RSN_OUI_SIZE ]; + tANI_U16 cUnicastCyphers; + + __ani_attr_pre_packed struct { + + tANI_U8 Oui[ CSR_RSN_OUI_SIZE ]; + + } __ani_attr_packed UnicastOui[ 1 ]; + +} __ani_attr_packed tCsrRSNIe; + +typedef __ani_attr_pre_packed struct tagCsrRSNAuthIe +{ + tANI_U16 cAuthenticationSuites; + __ani_attr_pre_packed struct { + + tANI_U8 Oui[ CSR_RSN_OUI_SIZE ]; + + } __ani_attr_packed AuthOui[ 1 ]; + +} __ani_attr_packed tCsrRSNAuthIe; + +typedef __ani_attr_pre_packed struct tagCsrRSNCapabilities +{ + tANI_U16 PreAuthSupported:1; + tANI_U16 NoPairwise:1; + tANI_U16 PTKSAReplayCounter:2; + tANI_U16 GTKSAReplayCounter:2; + tANI_U16 MFPRequired:1; + tANI_U16 MFPCapable:1; + tANI_U16 Reserved:8; +} __ani_attr_packed tCsrRSNCapabilities; + +typedef __ani_attr_pre_packed struct tagCsrRSNPMKIe +{ + tANI_U16 cPMKIDs; + + __ani_attr_pre_packed struct { + + tANI_U8 PMKID[ CSR_RSN_PMKID_SIZE ]; + + } __ani_attr_packed PMKIDList[ 1 ]; + + +} __ani_attr_packed tCsrRSNPMKIe; + +typedef __ani_attr_pre_packed struct tCsrIELenInfo +{ + tANI_U8 min; + tANI_U8 max; +} __ani_attr_packed tCsrIELenInfo; + +#ifdef FEATURE_WLAN_WAPI +typedef __ani_attr_pre_packed struct tagCsrWapiIe +{ + tDot11IEHeader IeHeader; + tANI_U16 Version; + + tANI_U16 cAuthenticationSuites; + __ani_attr_pre_packed struct { + + tANI_U8 Oui[ CSR_WAPI_OUI_SIZE ]; + + } __ani_attr_packed AuthOui[ 1 ]; + + tANI_U16 cUnicastCyphers; + __ani_attr_pre_packed struct { + + tANI_U8 Oui[ CSR_WAPI_OUI_SIZE ]; + + } __ani_attr_packed UnicastOui[ 1 ]; + + tANI_U8 MulticastOui[ CSR_WAPI_OUI_SIZE ]; + + __ani_attr_pre_packed struct { + tANI_U16 PreAuthSupported:1; + tANI_U16 Reserved:15; + } __ani_attr_packed tCsrWapiCapabilities; + + +} __ani_attr_packed tCsrWapiIe; + +typedef __ani_attr_pre_packed struct tagCsrWAPIBKIe +{ + tANI_U16 cBKIDs; + __ani_attr_pre_packed struct { + + tANI_U8 BKID[ CSR_WAPI_BKID_SIZE ]; + + } __ani_attr_packed BKIDList[ 1 ]; + + +} __ani_attr_packed tCsrWAPIBKIe; +#endif /* FEATURE_WLAN_WAPI */ + +#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK) +#pragma pack( pop ) +#endif + +// Structure used to describe a group of continuous channels and hook it into the +// corresponding channel list +typedef struct tagCsrChannelSet +{ + tListElem channelListLink; + tANI_U8 firstChannel; + tANI_U8 interChannelOffset; + tANI_U8 numChannels; + tANI_U8 txPower; +}tCsrChannelSet; + + +typedef struct sDot11InfoIBSSParmSet +{ + tDot11IEHeader dot11IEHeader; + tANI_U8 ATIMWindow; +}tDot11InfoIBSSParmSet; + + +typedef struct sDot11IECountry +{ + tDot11IEHeader dot11IEHeader; + tANI_U8 countryString[3]; + tSirMacChanInfo chanInfo[1]; +}tDot11IECountry; + + +typedef struct sDot11IEExtenedSupportedRates +{ + tDot11IEHeader dot11IEHeader; + tANI_U8 ExtendedSupportedRates[ CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ]; +}tDot11IEExtenedSupportedRates; + +#define CSR_DOT11_AP_NAME_MAX_LENGTH ( 32 ) + +typedef struct tagDot11IEAPName +{ + tDot11IEHeader dot11IEHeader; + tANI_U8 ApName[ CSR_DOT11_AP_NAME_MAX_LENGTH ]; +}tDot11IEAPName; + +typedef struct tagDot11IE11HLocalPowerConstraint +{ + tDot11IEHeader dot11IEHeader; + tANI_U8 localPowerConstraint; + +}tDot11IE11HLocalPowerConstraint; + +typedef struct tagRoamingTimerInfo +{ + tpAniSirGlobal pMac; + tANI_U8 sessionId; +} tCsrTimerInfo; + + +#define CSR_IS_11A_BSS(pBssDesc) ( eSIR_11A_NW_TYPE == (pBssDesc)->nwType ) +#define CSR_IS_BASIC_RATE(rate) ((rate) & CSR_DOT11_BASIC_RATE_MASK) +#define CSR_IS_QOS_BSS(pIes) ( (pIes)->WMMParams.present || (pIes)->WMMInfoAp.present ) + +#define CSR_IS_UAPSD_BSS(pIes) \ + ( ((pIes)->WMMParams.present && ((pIes)->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD)) || \ + ((pIes)->WMMInfoAp.present && (pIes)->WMMInfoAp.uapsd) ) + +//This macro returns the total length needed of Tlv with with len bytes of data +#define GET_TLV_MSG_LEN(len) GET_ROUND_UP((sizeof(tCsrCfgMsgTlvHdr) + (len)), sizeof(tANI_U32)) + +tANI_BOOLEAN csrGetBssIdBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc, tCsrBssid *pBssId ); +tANI_BOOLEAN csrIsBssIdEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 ); + +eCsrMediaAccessType csrGetQoSFromBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes); +tANI_BOOLEAN csrIsNULLSSID( tANI_U8 *pBssSsid, tANI_U8 len ); +tANI_BOOLEAN csrIsInfraBssDesc( tSirBssDescription *pSirBssDesc ); +tANI_BOOLEAN csrIsIbssBssDesc( tSirBssDescription *pSirBssDesc ); +tANI_BOOLEAN csrIsPrivacy( tSirBssDescription *pSirBssDesc ); +tSirResultCodes csrGetDisassocRspStatusCode( tSirSmeDisassocRsp *pSmeDisassocRsp ); +tSirResultCodes csrGetDeAuthRspStatusCode( tSirSmeDeauthRsp *pSmeRsp ); +tANI_U32 csrGetFragThresh( tHalHandle hHal ); +tANI_U32 csrGetRTSThresh( tHalHandle hHal ); +eCsrPhyMode csrGetPhyModeFromBssDesc( tSirBssDescription *pSirBssDesc ); +tANI_U32 csrGet11hPowerConstraint( tHalHandle hHal, tDot11fIEPowerConstraints *pPowerConstraint ); +tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrRSNIe *pRSNIe ); +tANI_U8 csrConstructWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe ); +#ifdef FEATURE_WLAN_WAPI + +tANI_BOOLEAN csrIsProfileWapi( tCsrRoamProfile *pProfile ); +#endif /* FEATURE_WLAN_WAPI */ +//If a WPAIE exists in the profile, just use it. Or else construct one from the BSS +//Caller allocated memory for pWpaIe and guarrantee it can contain a max length WPA IE +tANI_U8 csrRetrieveWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe ); +tANI_BOOLEAN csrIsSsidEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2 ); +//Null ssid means match +tANI_BOOLEAN csrIsSsidInList( tHalHandle hHal, tSirMacSSid *pSsid, tCsrSSIDs *pSsidList ); +tANI_BOOLEAN csrIsProfileWpa( tCsrRoamProfile *pProfile ); +tANI_BOOLEAN csrIsProfileRSN( tCsrRoamProfile *pProfile ); +//This function returns the raw byte array of WPA and/or RSN IE +tANI_BOOLEAN csrGetWpaRsnIe( tHalHandle hHal, tANI_U8 *pIes, tANI_U32 len, + tANI_U8 *pWpaIe, tANI_U8 *pcbWpaIe, tANI_U8 *pRSNIe, tANI_U8 *pcbRSNIe); +//If a RSNIE exists in the profile, just use it. Or else construct one from the BSS +//Caller allocated memory for pWpaIe and guarrantee it can contain a max length WPA IE +tANI_U8 csrRetrieveRsnIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrRSNIe *pRsnIe ); +#ifdef FEATURE_WLAN_WAPI +//If a WAPI IE exists in the profile, just use it. Or else construct one from the BSS +//Caller allocated memory for pWapiIe and guarrantee it can contain a max length WAPI IE +tANI_U8 csrRetrieveWapiIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe ); +#endif /* FEATURE_WLAN_WAPI */ +tANI_BOOLEAN csrSearchChannelListForTxPower(tHalHandle hHal, tSirBssDescription *pBssDescription, tCsrChannelSet *returnChannelGroup); +tANI_BOOLEAN csrRatesIsDot11Rate11bSupportedRate( tANI_U8 dot11Rate ); +tANI_BOOLEAN csrRatesIsDot11Rate11aSupportedRate( tANI_U8 dot11Rate ); +tAniEdType csrTranslateEncryptTypeToEdType( eCsrEncryptionType EncryptType ); +//pIes shall contain IEs from pSirBssDesc. It shall be returned from function csrGetParsedBssDescriptionIEs +tANI_BOOLEAN csrIsSecurityMatch( tHalHandle hHal, tCsrAuthList *authType, + tCsrEncryptionList *pUCEncryptionType, + tCsrEncryptionList *pMCEncryptionType, + tANI_BOOLEAN *pMFPEnabled, + tANI_U8 *pMFPRequired, + tANI_U8 *pMFPCapable, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, + eCsrAuthType *negotiatedAuthtype, eCsrEncryptionType *negotiatedUCCipher, eCsrEncryptionType *negotiatedMCCipher ); +tANI_BOOLEAN csrIsBSSTypeMatch(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2); +tANI_BOOLEAN csrIsBssTypeIBSS(eCsrRoamBssType bssType); +tANI_BOOLEAN csrIsBssTypeWDS(eCsrRoamBssType bssType); +//ppIes can be NULL. If caller want to get the *ppIes allocated by this function, pass in *ppIes = NULL +//Caller needs to free the memory in this case +tANI_BOOLEAN csrMatchBSS( tHalHandle hHal, tSirBssDescription *pBssDesc, tCsrScanResultFilter *pFilter, + eCsrAuthType *pNegAuth, eCsrEncryptionType *pNegUc, eCsrEncryptionType *pNegMc, + tDot11fBeaconIEs **ppIes); + +tANI_BOOLEAN csrIsBssidMatch( tHalHandle hHal, tCsrBssid *pProfBssid, tCsrBssid *BssBssid ); +tANI_BOOLEAN csrMatchBSSToConnectProfile( tHalHandle hHal, tCsrRoamConnectedProfile *pProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes ); + +void csrAddRateBitmap(tANI_U8 rate, tANI_U16 *pRateBitmap); +tANI_BOOLEAN csrCheckRateBitmap(tANI_U8 rate, tANI_U16 RateBitmap); + +tANI_BOOLEAN csrRatesIsDot11RateSupported( tHalHandle hHal, tANI_U8 rate ); +tANI_U16 csrRatesFindBestRate( tSirMacRateSet *pSuppRates, tSirMacRateSet *pExtRates, tSirMacPropRateSet *pPropRates ); +tSirBssType csrTranslateBsstypeToMacType(eCsrRoamBssType csrtype); + +//Caller allocates memory for pIEStruct +eHalStatus csrParseBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIEStruct); +//This function will allocate memory for the parsed IEs to the caller. Caller must free the memory +//after it is done with the data only if this function succeeds +eHalStatus csrGetParsedBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs **ppIEStruct); + +tANI_BOOLEAN csrValidateCountryString( tHalHandle hHal, tANI_U8 *pCountryString ); +tSirScanType csrGetScanType(tpAniSirGlobal pMac, tANI_U8 chnId); + +tANI_U8 csrToUpper( tANI_U8 ch ); +eHalStatus csrGetPhyModeFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBSSDescription, + eCsrPhyMode *pPhyMode, tDot11fBeaconIEs *pIes); + +//fForce -- force reassoc regardless of whether there is any change +//The reason is that for UAPSD-bypass, the code underneath this call determine whether +//to allow UAPSD. The information in pModProfileFields reflects what the user wants. +//There may be discrepency in it. UAPSD-bypass logic should decide if it needs to reassoc +eHalStatus csrReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamModifyProfileFields *pModProfileFields, + tANI_U32 *pRoamId, v_BOOL_t fForce); + +eHalStatus +csrIsconcurrentsessionValid(tpAniSirGlobal pMac,tANI_U32 cursessionId, + tVOS_CON_MODE currBssPersona); + +//Update beaconInterval for P2P-GO case if it is different +eHalStatus csrUpdatep2pBeaconInterval(tpAniSirGlobal pMac); + +//BeaconInterval validation for MCC support +eHalStatus csrValidateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U8 channelId, + tANI_U16 *beaconInterval, tANI_U32 cursessionId, + tVOS_CON_MODE currBssPersona); + +#ifdef WLAN_FEATURE_VOWIFI_11R +tANI_BOOLEAN csrIsProfile11r( tCsrRoamProfile *pProfile ); +tANI_BOOLEAN csrIsAuthType11r( eCsrAuthType AuthType, tANI_U8 mdiePresent); +#endif + +#ifdef FEATURE_WLAN_ESE +tANI_BOOLEAN csrIsAuthTypeESE( eCsrAuthType AuthType ); +tANI_BOOLEAN csrIsProfileESE( tCsrRoamProfile *pProfile ); +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/nan_Api.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/nan_Api.h new file mode 100644 index 000000000000..14097c8f3821 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/nan_Api.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: nan_Api.h +* +* Description: NAN FSM defines. +* +******************************************************************************/ + +#ifndef __NAN_API_H__ +#define __NAN_API_H__ + +#include "vos_types.h" +#include "halTypes.h" + +typedef struct sNanRequestReq { + tANI_U16 request_data_len; + const tANI_U8* request_data; +} tNanRequestReq, *tpNanRequestReq; + +/****************************************************************************** + * Function: Pointer NanCallback + * + * Description: + * this function pointer is used hold nan response callback. When ever we + * receive nan response, we will use this callback. + * + * Args: + * first argument to pass hHal pointer and second argument + * to pass the nan response data. + * + * Returns: + * void +******************************************************************************/ +typedef void (*NanCallback)(void*, tSirNanEvent*); + +/****************************************************************************** + * Function: sme_NanRegisterCallback + * + * Description: + * This function gets called when HDD wants register nan rsp callback with + * sme layer. + * + * Args: + * hHal and callback which needs to be registered. + * + * Returns: + * void +******************************************************************************/ +void sme_NanRegisterCallback(tHalHandle hHal, NanCallback callback); + +/****************************************************************************** + * Function: sme_NanRequest + * + * Description: + * This function gets called when HDD receives NAN vendor command + * from userspace + * + * Args: + * Nan Request structure ptr + * + * Returns: + * VOS_STATUS +******************************************************************************/ +VOS_STATUS sme_NanRequest(tpNanRequestReq input); + + +#endif /* __NAN_API_H__ */ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h new file mode 100644 index 000000000000..80c7af56f884 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file oemDataApi.h + + Exports and types for the Common OEM DATA REQ/RSP Module interfaces. +========================================================================== */ + +#ifndef __OEM_DATA_API_H__ +#define __OEM_DATA_API_H__ +#include "sirApi.h" +#include "sirMacProtDef.h" +#include "csrLinkList.h" + +#ifndef OEM_DATA_REQ_SIZE +#define OEM_DATA_REQ_SIZE 280 +#endif + +#ifndef OEM_DATA_RSP_SIZE +#define OEM_DATA_RSP_SIZE 1724 +#endif + +/* message subtype for internal purpose */ +#define OEM_MESSAGE_SUBTYPE_INTERNAL 0xdeadbeef + +/************************************************************************************************************* + OEM DATA REQ/RSP - DATA STRUCTURES +*************************************************************************************************************/ + +/* Structure for defining req sent to the PE */ +typedef struct tagOemDataReq +{ + tANI_U8 sessionId; + tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; +} tOemDataReq, tOemDataReqConfig; + +/************************************************************************************************************* + OEM DATA RESPONSE - DATA STRUCTURES +*************************************************************************************************************/ +typedef struct tagOemDataRsp +{ + tANI_U8 oemDataRsp[OEM_DATA_RSP_SIZE]; +} tOemDataRsp; + +/*************************************************************************************************************/ + +typedef enum +{ + eOEM_DATA_REQ_SUCCESS=1, + eOEM_DATA_REQ_FAILURE, + eOEM_DATA_REQ_INVALID_MODE, +} eOemDataReqStatus; + +/* --------------------------------------------------------------------------- + \fn oemData_OemDataReqOpen + \brief This function must be called before any API call to MEAS (OEM DATA REQ/RSP module) + \return eHalStatus + -------------------------------------------------------------------------------*/ + +eHalStatus oemData_OemDataReqOpen(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn oemData_OemDataReqClose + \brief This function must be called before closing the csr module + \return eHalStatus + -------------------------------------------------------------------------------*/ + +eHalStatus oemData_OemDataReqClose(tHalHandle hHal); + +/* HDD Callback function for the sme to callback when the oem data rsp is available */ +typedef eHalStatus (*oemData_OemDataReqCompleteCallback)( + tHalHandle, + void* p2, + tANI_U32 oemDataReqID, + eOemDataReqStatus status); + +/* --------------------------------------------------------------------------- + \fn oemData_OemDataReq + \brief Request an OEM DATA RSP + \param sessionId - Id of session to be used + \param pOemDataReqID - pointer to an object to get back the request ID + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus oemData_OemDataReq(tHalHandle, tANI_U8, tOemDataReqConfig *, tANI_U32 *pOemDataReqID); + +/* --------------------------------------------------------------------------- + \fn sme_HandleOemDataRsp + \brief This function processes the oem data response obtained from the PE + \param pMsg - Pointer to the pSirSmeOemDataRsp + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_HandleOemDataRsp(tHalHandle hHal, tANI_U8*); + +/* --------------------------------------------------------------------------- + \fn oemData_IsOemDataReqAllowed + \brief This function checks if oem data req/rsp can be performed in the + current driver state + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus oemData_IsOemDataReqAllowed(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn send_oem_data_rsp_msg + \brief This function sends oem data response message to registered + application + \return None + --------------------------------------------------------------------------*/ +void send_oem_data_rsp_msg(int length, tANI_U8 *oemDataRsp); + +#endif //_OEM_DATA_API_H__ + +#endif //FEATURE_OEM_DATA_SUPPORT diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataInternal.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataInternal.h new file mode 100644 index 000000000000..ba5612edc183 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataInternal.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file oemDataInternal.h + + Exports and types for the Common OEM DATA REQ/RSP Module interfaces. +========================================================================== */ + + +#ifndef __OEM_DATA_INTERNAL_H__ +#define __OEM_DATA_INTERNAL_H__ + +#include "csrSupport.h" +#include "vos_nvitem.h" +#include "wlan_qct_tl.h" + +#include "oemDataApi.h" + +typedef struct tagOemDataStruct +{ + tANI_U32 nextOemReqId; //a global req id + tANI_BOOLEAN oemDataReqActive; //indicates that currently a request has been posted and + //waiting for the response + tANI_U32 oemDataReqID; //original request ID + tOemDataReqConfig oemDataReqConfig; //current oem data request + tANI_U8 sessionId; //Session on which oem data req is active +} tOemDataStruct; + +typedef struct tagOemDataCmd +{ + tANI_U32 oemDataReqID; + tOemDataReq oemDataReq; +} tOemDataCmd; + +#endif //__OEM_DATA_INTERNAL_H__ + +#endif //FEATURE_OEM_DATA_SUPPORT diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/p2p_Api.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/p2p_Api.h new file mode 100644 index 000000000000..4a04c84997fa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/p2p_Api.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: p2p_Api.h +* +* Description: P2P FSM defines. +* + +* +******************************************************************************/ + +#ifndef __P2P_API_H__ +#define __P2P_API_H__ + +#include "vos_types.h" +#include "halTypes.h" +#include "vos_timer.h" +#include "vos_lock.h" + +typedef struct sP2pPsConfig{ + tANI_U8 opp_ps; + tANI_U32 ctWindow; + tANI_U8 count; + tANI_U32 duration; + tANI_U32 interval; + tANI_U32 single_noa_duration; + tANI_U8 psSelection; + tANI_U8 sessionid; +}tP2pPsConfig,*tpP2pPsConfig; + +typedef eHalStatus (*remainOnChanCallback)( tHalHandle, void* context, + eHalStatus status ); + +typedef struct sRemainOnChn{ + tANI_U8 chn; + tANI_U32 duration; + remainOnChanCallback callback; + void *pCBContext; +}tRemainOnChn, tpRemainOnChn; + +#define SIZE_OF_NOA_DESCRIPTOR 13 +#define MAX_NOA_PERIOD_IN_MICROSECS 3000000 + +#define P2P_CLEAR_POWERSAVE 0 +#define P2P_OPPORTUNISTIC_PS 1 +#define P2P_PERIODIC_NOA 2 +#define P2P_SINGLE_NOA 4 + + +typedef struct sp2pContext +{ + v_CONTEXT_t vosContext; + tHalHandle hHal; + tANI_U8 sessionId; //Session id corresponding to P2P. On windows it is same as HDD sessionid not sme sessionid. + tANI_U8 SMEsessionId; + tANI_U8 probeReqForwarding; + tANI_U8 *probeRspIe; + tANI_U32 probeRspIeLength; +} tp2pContext, *tPp2pContext; + +eHalStatus sme_RemainOnChannel( tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 channel, tANI_U32 duration, + remainOnChanCallback callback, + void *pContext, + tANI_U8 isP2PProbeReqAllowed); +eHalStatus sme_ReportProbeReq( tHalHandle hHal, tANI_U8 flag ); +eHalStatus sme_updateP2pIe( tHalHandle hHal, void *p2pIe, + tANI_U32 p2pIeLength ); +eHalStatus sme_sendAction( tHalHandle hHal, tANI_U8 sessionId, + const tANI_U8 *pBuf, tANI_U32 len, + tANI_U16 wait, tANI_BOOLEAN noack); +eHalStatus sme_CancelRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId ); +eHalStatus sme_p2pOpen( tHalHandle hHal ); +eHalStatus p2pStop( tHalHandle hHal ); +eHalStatus sme_p2pClose( tHalHandle hHal ); +eHalStatus sme_p2pSetPs( tHalHandle hHal, tP2pPsConfig * data ); +eHalStatus p2pRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 channel, tANI_U32 duration, + remainOnChanCallback callback, + void *pContext, + tANI_U8 isP2PProbeReqAllowed); +eHalStatus p2pSendAction( tHalHandle hHal, tANI_U8 sessionId, + const tANI_U8 *pBuf, tANI_U32 len, + tANI_U16 wait, tANI_BOOLEAN noack); +eHalStatus p2pCancelRemainOnChannel( tHalHandle hHal, tANI_U8 sessionId ); +eHalStatus p2pSetPs( tHalHandle hHal, tP2pPsConfig *pNoA ); +tSirRFBand GetRFBand(tANI_U8 channel); +#endif //__P2P_API_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/pmc.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/pmc.h new file mode 100644 index 000000000000..be81d8beee54 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/pmc.h @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: pmc.h +* +* Description: Power Management Control (PMC) internal definitions. +* + +* +******************************************************************************/ + +#ifndef __PMC_H__ +#define __PMC_H__ + + +#include "csrLinkList.h" +#include "pmcApi.h" +#include "smeInternal.h" + + +//Change PMC_ABORT to no-op for now. We need to define it as VOS_ASSERT(0) once we +//cleanup the usage. +#define PMC_ABORT + +#define PMC_SESSION_MAX 5 + +/* Auto Ps Entry Timer Default value - 1000 ms */ +#define AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE 1000 + +/* Auto Deferred Ps Entry Timer value - 5000 ms */ +#define AUTO_DEFERRED_PS_ENTRY_TIMER_DEFAULT_VALUE 5000 + + +/* Host power sources. */ +typedef enum ePowerSource +{ + AC_POWER, /* host is operating from AC power */ + BATTERY_POWER /* host is operating from battery power */ +} tPowerSource; + + +/* Power save check routine list entry. */ +typedef struct sPowerSaveCheckEntry +{ + tListElem link; /* list links */ + tANI_BOOLEAN (*checkRoutine) (void *checkContext); /* power save check routine */ + void *checkContext; /* value to be passed as parameter to routine specified above */ +} tPowerSaveCheckEntry, *tpPowerSaveCheckEntry; + + +/* Device Power State update indication list entry. */ +typedef struct sDeviceStateUpdateIndEntry +{ + tListElem link; /* list links */ + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState); /* Callback routine to be invoked when pmc changes device state */ + void *callbackContext; /* value to be passed as parameter to routine specified above */ +} tDeviceStateUpdateIndEntry, *tpDeviceStateUpdateIndEntry; + +/* Request full power callback routine list entry. */ +typedef struct sRequestFullPowerEntry +{ + tListElem link; /* list links */ + void (*callbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call when full power is restored */ + void *callbackContext; /* value to be passed as parameter to routine specified above */ +} tRequestFullPowerEntry, *tpRequestFullPowerEntry; + + +/* Request BMPS callback routine list entry. */ +typedef struct sRequestBmpsEntry +{ + tListElem link; /* list links */ + + /* routine to call when BMPS request succeeded/failed */ + void (*callbackRoutine) (void *callbackContext, eHalStatus status); + + /* value to be passed as parameter to routine specified above */ + void *callbackContext; + +} tRequestBmpsEntry, *tpRequestBmpsEntry; + + +/* Start U-APSD callback routine list entry. */ +typedef struct sStartUapsdEntry +{ + tListElem link; /* list links */ + + /* routine to call when Uapsd Start succeeded/failed*/ + void (*callbackRoutine) (void *callbackContext, eHalStatus status); + + /* value to be passed as parameter to routine specified above */ + void *callbackContext; + +} tStartUapsdEntry, *tpStartUapsdEntry; + +typedef struct sPmcDeferredMsg +{ + tListElem link; + tpAniSirGlobal pMac; + tANI_U16 messageType; + tANI_U16 size; //number of bytes in u.data + union + { + tSirPowerSaveCfg powerSaveConfig; + tSirWowlAddBcastPtrn wowlAddPattern; + tSirWowlDelBcastPtrn wowlDelPattern; + tANI_U8 data[1]; //a place holder + }u; +} tPmcDeferredMsg; + + + +/* Current PMC information for a particular device. */ +typedef struct sPmcInfo +{ + tPowerSource powerSource; /* host power source */ + tPmcSwitchState hwWlanSwitchState; /* Hardware WLAN Switch state */ + tPmcSwitchState swWlanSwitchState; /* Software WLAN Switch state */ + tPmcState pmcState; /* PMC state */ + tANI_BOOLEAN requestFullPowerPending; /* TRUE if a request for full power is pending */ + tRequestFullPowerReason requestFullPowerReason; /* reason for requesting full power */ + tPmcImpsConfigParams impsConfig; /* IMPS configuration */ + tPmcBmpsConfigParams bmpsConfig; /* BMPS configuration */ + tPmcSmpsConfigParams smpsConfig; /* SMPS configuration */ + tANI_BOOLEAN impsEnabled; /* TRUE if IMPS is enabled */ + tANI_BOOLEAN bmpsEnabled; /* TRUE if BMPS is enabled */ + tANI_BOOLEAN autoBmpsEntryEnabled; /* TRUE if auto BMPS entry is enabled. If set to TRUE, PMC will + attempt to put the device into BMPS on entry into full Power */ + tANI_BOOLEAN bmpsRequestedByHdd; /*TRUE if BMPS mode has been requested by HDD */ + tANI_BOOLEAN bmpsRequestQueued; /*If a enter BMPS request is queued*/ + tANI_BOOLEAN smpsEnabled; /* TRUE if SMPS is enabled */ + tANI_BOOLEAN remainInPowerActiveTillDHCP; /* Remain in Power active till DHCP completes */ + tANI_U32 remainInPowerActiveThreshold; /*Remain in Power active till DHCP threshold*/ + tANI_U32 impsPeriod; /* amount of time to remain in IMPS */ + void (*impsCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call when IMPS period + has finished */ + void *impsCallbackContext; /* value to be passed as parameter to routine specified above */ + vos_timer_t hImpsTimer; /* timer to use with IMPS */ + vos_timer_t hTrafficTimer; /* timer to measure traffic for BMPS */ + vos_timer_t hExitPowerSaveTimer; /* timer for deferred exiting of power save mode */ + tDblLinkList powerSaveCheckList; /* power save check routine list */ + tDblLinkList requestFullPowerList; /* request full power callback routine list */ + tANI_U32 cLastTxUnicastFrames; /* transmit unicast frame count at last BMPS traffic timer expiration */ + tANI_U32 cLastRxUnicastFrames; /* receive unicast frame count at last BMPS traffic timer expiration */ + + + tANI_BOOLEAN uapsdEnabled; /* TRUE if UAPSD is enabled */ + tANI_BOOLEAN uapsdSessionRequired; /* TRUE if device should go to UAPSD on entering BMPS*/ + tDblLinkList requestBmpsList; /* request Bmps callback routine list */ + tDblLinkList requestStartUapsdList; /* request start Uapsd callback routine list */ + tANI_BOOLEAN standbyEnabled; /* TRUE if Standby is enabled */ + void (*standbyCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call for standby request */ + void *standbyCallbackContext;/* value to be passed as parameter to routine specified above */ + tDblLinkList deviceStateUpdateIndList; /*update device state indication list */ + tANI_BOOLEAN pmcReady; /*whether eWNI_SME_SYS_READY_IND has been sent to PE or not */ + tANI_BOOLEAN wowlEnabled; /* TRUE if WoWL is enabled */ + tANI_BOOLEAN wowlModeRequired; /* TRUE if device should go to WOWL on entering BMPS */ + 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 */ + tDblLinkList deferredMsgList; //The message in here are deferred and DONOT expect response from PE +#ifdef FEATURE_WLAN_SCAN_PNO + preferredNetworkFoundIndCallback prefNetwFoundCB; /* routine to call for Preferred Network Found Indication */ + void *preferredNetworkFoundIndCallbackContext;/* value to be passed as parameter to routine specified above */ +#endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_PACKET_FILTERING + FilterMatchCountCallback FilterMatchCountCB; /* routine to call for Packet Coalescing Filter Match Count */ + void *FilterMatchCountCBContext;/* value to be passed as parameter to routine specified above */ +#endif // WLAN_FEATURE_PACKET_FILTERING +#ifdef WLAN_FEATURE_GTK_OFFLOAD + GTKOffloadGetInfoCallback GtkOffloadGetInfoCB; /* routine to call for GTK Offload Information */ + void *GtkOffloadGetInfoCBContext; /* value to be passed as parameter to routine specified above */ +#endif // WLAN_FEATURE_GTK_OFFLOAD + +#ifdef WLAN_WAKEUP_EVENTS + void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd); /* routine to call for Wake Reason Indication */ + void *wakeReasonIndCBContext; /* value to be passed as parameter to routine specified above */ +#endif // WLAN_WAKEUP_EVENTS + +/* + * If TRUE driver will go to BMPS only if host operating system + * asks to enter BMPS. For android wlan_hdd_cfg80211_set_power_mgmt API will + * be used to set host power save + */ + v_BOOL_t isHostPsEn; + v_BOOL_t ImpsReqFailed; + v_BOOL_t ImpsReqTimerFailed; + tANI_U8 ImpsReqFailCnt; + tANI_U8 ImpsReqTimerfailCnt; + +} tPmcInfo, *tpPmcInfo; + + +//MACRO +#define PMC_IS_READY(pMac) ( ((pMac)->pmc.pmcReady) && (STOPPED != (pMac)->pmc.pmcState) ) + + +/* Routine definitions. */ +extern eHalStatus pmcEnterLowPowerState (tHalHandle hHal); +extern eHalStatus pmcExitLowPowerState (tHalHandle hHal); +extern eHalStatus pmcEnterFullPowerState (tHalHandle hHal); +extern eHalStatus pmcEnterRequestFullPowerState (tHalHandle hHal, tRequestFullPowerReason fullPowerReason); +extern eHalStatus pmcEnterRequestImpsState (tHalHandle hHal); +extern eHalStatus pmcEnterImpsState (tHalHandle hHal); +extern eHalStatus pmcEnterRequestBmpsState (tHalHandle hHal); +extern eHalStatus pmcEnterBmpsState (tHalHandle hHal); +extern eHalStatus pmcEnterRequestStartUapsdState (tHalHandle hHal); +extern eHalStatus pmcEnterUapsdState (tHalHandle hHal); +extern eHalStatus pmcEnterRequestStopUapsdState (tHalHandle hHal); +extern eHalStatus pmcEnterRequestStandbyState (tHalHandle hHal); +extern eHalStatus pmcEnterStandbyState (tHalHandle hHal); +extern tANI_BOOLEAN pmcPowerSaveCheck (tHalHandle hHal); +extern eHalStatus pmcSendPowerSaveConfigMessage (tHalHandle hHal); +extern eHalStatus pmcSendMessage (tpAniSirGlobal pMac, tANI_U16 messageType, void *pMessageData, tANI_U32 messageSize); +extern void pmcDoCallbacks (tHalHandle hHal, eHalStatus callbackStatus); +extern void pmcDoBmpsCallbacks (tHalHandle hHal, eHalStatus callbackStatus); +extern void pmcDoStartUapsdCallbacks (tHalHandle hHal, eHalStatus callbackStatus); +extern void pmcDoStandbyCallbacks (tHalHandle hHal, eHalStatus callbackStatus); +extern eHalStatus pmcStartTrafficTimer (tHalHandle hHal, tANI_U32 expirationTime); +extern void pmcStopTrafficTimer (tHalHandle hHal); +extern void pmcImpsTimerExpired (tHalHandle hHal); +extern void pmcTrafficTimerExpired (tHalHandle hHal); + +extern void pmcExitPowerSaveTimerExpired (tHalHandle hHal); +extern tPmcState pmcGetPmcState (tHalHandle hHal); +extern const char* pmcGetPmcStateStr(tPmcState state); +extern void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state); +extern eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams); +extern eHalStatus pmcEnterWowlState (tHalHandle hHal); +extern eHalStatus pmcRequestExitWowlState(tHalHandle hHal, + tpSirSmeWowlExitParams wowlExitParams); +extern void pmcDoEnterWowlCallbacks (tHalHandle hHal, eHalStatus callbackStatus); +//The function will request for full power as well in addition to defer the message +extern eHalStatus pmcDeferMsg( tpAniSirGlobal pMac, tANI_U16 messageType, + void *pData, tANI_U32 size); +extern eHalStatus pmcIssueCommand(tpAniSirGlobal pMac, tANI_U32 sessionId, + eSmeCommandType cmdType, void *pvParam, + tANI_U32 size, tANI_BOOLEAN fPutToListHead); +extern eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac ); +extern eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac ); +extern tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac ); + +/* Power Save Offload Changes */ +/* Per SME Session PMC Offload Structure */ +typedef struct sPsOffloadPerSessionInfo +{ + tpAniSirGlobal pMac; + + tANI_U32 sessionId; + + /* TRUE if Sta Mode Ps is Enabled */ + tANI_BOOLEAN configStaPsEnabled; + + /* TRUE if deferred Sta Mode Ps is Enabled */ + tANI_BOOLEAN configDefStaPsEnabled; + + /* + * Indicates current uapsd status + * Enabled/Disabled/Required + */ + tUapsdStatus uapsdStatus; + + tANI_BOOLEAN uapsdSessionRequired; + + /* Current Power Save State */ + tPmcState pmcState; + + /* + * Auto Sta Ps Enable Timer + * Upon expiration of this timer + * Power Save Offload module will + * try to enable sta mode ps + */ + vos_timer_t autoPsEnableTimer; + + /* Auto Sta Ps Entry Timer Period */ + tANI_U32 autoPsEntryTimerPeriod; + + /* Full Power Request Pending */ + tANI_BOOLEAN fullPowerReqPend; + + /* + * List contains functions registered by different modules + * PsOffload Module will call this to check whether + * the particular module is ok to enable station mode power save + */ + tDblLinkList pwrsaveCheckList; + + /* + * List contains cbs passed by different modules + * to indicate power state change + */ + tDblLinkList deviceStateUpdateIndList; + + /* + * List contains cbs passed by different modules + * upon requesting full power + */ + tDblLinkList fullPowerCbList; + + /* + * List contains cbs passed by different modules + * upon requesting uapsd + */ + tDblLinkList uapsdCbList; + + /* + * Whether TDLS session allows power save or not + */ +#ifdef FEATURE_WLAN_TDLS + v_BOOL_t isTdlsPowerSaveProhibited; +#endif + tANI_BOOLEAN UapsdEnabled; +}tPsOffloadPerSessionInfo,*tpPsOffloadPerSessionInfo; + +typedef struct sPmcOffloadInfo +{ + /* Based on Whether BMPS is enabled or not in ini */ + tANI_BOOLEAN staPsEnabled; + + tPsOffloadPerSessionInfo pmc[PMC_SESSION_MAX]; + +}tPmcOffloadInfo,*tpPmcOffloadInfo; + +/* Power save check routine list entry. */ +typedef struct sPmcOffloadPsCheckEntry +{ + /* list links */ + tListElem link; + + /* power save check routine */ + PwrSaveCheckRoutine pwrsaveCheckCb; + + /* value to be passed as parameter to routine specified above */ + void *checkContext; + + /* Session Id */ + tANI_U32 sessionId; +} tPmcOffloadPsCheckEntry,*tpPmcOffloadPsCheckEntry; + + +/* Device Power State update indication list entry. */ +typedef struct sPmcOffloadDevStateUpdIndEntry +{ + /* list links */ + tListElem link; + + /* Callback routine to be invoked when pmc changes device state */ + PwrSaveStateChangeIndCb stateChangeCb; + + /* value to be passed as parameter to routine specified above */ + void *callbackContext; + + /* Session Id */ + tANI_U32 sessionId; +} tPmcOffloadDevStateUpdIndEntry,*tpPmcOffloadDevStateUpdIndEntry; + +/* Request full power callback routine list entry. */ +typedef struct sPmcOffloadReqFullPowerEntry +{ + /* list links */ + tListElem link; + + /* routine to call when full power is restored */ + FullPowerReqCb fullPwrCb; + + /* value to be passed as parameter to routine specified above */ + void *callbackContext; + + /* SessionId */ + tANI_U32 sessionId; +}tPmcOffloadReqFullPowerEntry,*tpPmcOffloadReqFullPowerEntry; + +/* Start U-APSD callback routine list entry. */ +typedef struct sPmcOffloadStartUapsdEntry +{ + tListElem link; /* list links */ + + /* routine to call when Uapsd Start succeeded/failed*/ + UapsdStartIndCb uapsdStartInd; + + /* value to be passed as parameter to routine specified above */ + void *callbackContext; + + /* SessionId */ + tANI_U32 sessionId; +} tPmcOffloadStartUapsdEntry,*tpPmcOffloadStartUapsdEntry; + +eHalStatus pmcOffloadOpenPerSession(tHalHandle hHal, tANI_U32 sessionId); +eHalStatus pmcOffloadClosePerSession(tHalHandle hHal, tANI_U32 sessionId); +eHalStatus pmcOffloadStartPerSession(tHalHandle hHal, tANI_U32 sessionId); +eHalStatus pmcOffloadStopPerSession(tHalHandle hHal, tANI_U32 sessionId); + +eHalStatus pmcOffloadStartAutoStaPsTimer (tpAniSirGlobal pMac, + tANI_U32 sessionId, + tANI_U32 timerValue); + +void pmcOffloadStopAutoStaPsTimer(tpAniSirGlobal pMac, tANI_U32 sessionId); + +eHalStatus pmcOffloadQueueRequestFullPower (tpAniSirGlobal pMac, + tANI_U32 sessionId, tRequestFullPowerReason fullPowerReason); + +eHalStatus pmcOffloadEnableStaPsHandler(tpAniSirGlobal pMac, + tANI_U32 sessionId); + +void pmcOffloadProcessResponse(tpAniSirGlobal pMac, tSirSmeRsp *pMsg); +void pmcOffloadAutoPsEntryTimerExpired(void *pmcInfo); +void pmcOffloadDoFullPowerCallbacks (tpAniSirGlobal pMac, tANI_U32 sessionId, + eHalStatus status); +void pmcOffloadDoDeviceStateUpdateCallbacks (tpAniSirGlobal pMac, + tANI_U32 sessionId, tPmcState state); +void pmcOffloadDoStartUapsdCallbacks (tpAniSirGlobal pMac, tANI_U32 sessionId, + eHalStatus status); +eHalStatus pmcOffloadDisableStaPsHandler(tpAniSirGlobal pMac, + tANI_U8 sessionId); +eHalStatus pmcOffloadEnableStaPsCheck(tpAniSirGlobal pMac, + tANI_U32 sessionId); +eHalStatus pmcOffloadExitPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId); + +eHalStatus pmcOffloadEnterPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId); +void pmcOffloadExitBmpsIndHandler(tpAniSirGlobal pMac, tSirSmeRsp *pMsg); + +eHalStatus pmcOffloadQueueStartUapsdRequest(tpAniSirGlobal pMac, tANI_U32 sessionId); +eHalStatus pmcOffloadQueueStopUapsdRequest(tpAniSirGlobal pMac, tANI_U32 sessionId); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/pmcApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/pmcApi.h new file mode 100644 index 000000000000..6052b3f79f23 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/pmcApi.h @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + +* + +* Name: pmcApi.h + +* + +* Description: Power Management Control (PMC) API definitions. + +* + +******************************************************************************/ + + +#ifndef __PMC_API_H__ + +#define __PMC_API_H__ + +/* + * This timer value determines the default periodicity at which BMPS retries + * will happen; this default value is overwritten typically by OS specific + * registry/INI values. + */ +#define BMPS_TRAFFIC_TIMER_DEFAULT 5000 //unit = ms +#define DHCP_REMAIN_POWER_ACTIVE_THRESHOLD 12 // (12 * 5) sec = 60 seconds = 1 min + +//This timer value is used when starting the timer right after association. This value +//should be large enough to allow the auth, DHCP handshake to complete +#define BMPS_TRAFFIC_TIMER_ALLOW_SECURITY_DHCP 8000 //unit = ms + +#define PMC_IS_CHIP_ACCESSIBLE(pmcState) ( (IMPS != (pmcState)) && (REQUEST_IMPS != (pmcState)) && \ + (STANDBY != (pmcState)) && (REQUEST_STANDBY != (pmcState)) ) + + + +/* Power events that are signaled to PMC. */ + +typedef enum ePmcPowerEvent + +{ + + ePMC_SYSTEM_HIBERNATE, /* host is entering hibernation */ + + ePMC_SYSTEM_RESUME, /* host is resuming after hibernation */ + + ePMC_HW_WLAN_SWITCH_OFF, /* Hardware WLAN Switch has been turned off */ + + ePMC_HW_WLAN_SWITCH_ON, /* Hardware WLAN Switch has been turned on */ + + ePMC_SW_WLAN_SWITCH_OFF, /* Software WLAN Switch has been turned off */ + + ePMC_SW_WLAN_SWITCH_ON, /* Software WLAN Switch has been turned on */ + + ePMC_BATTERY_OPERATION, /* host is now operating on battery power */ + + ePMC_AC_OPERATION /* host is now operating on AC power */ + +} tPmcPowerEvent; + + + + +/* Power saving modes. */ + +typedef enum ePmcPowerSavingMode + +{ + + ePMC_IDLE_MODE_POWER_SAVE, /* Idle Mode Power Save (IMPS) */ + + ePMC_BEACON_MODE_POWER_SAVE, /* Beacon Mode Power Save (BMPS) */ + + ePMC_SPATIAL_MULTIPLEX_POWER_SAVE, /* Spatial Multiplexing Power Save (SMPS) */ + + ePMC_UAPSD_MODE_POWER_SAVE, /* Unscheduled Automatic Power Save Delivery Mode */ + + ePMC_STANDBY_MODE_POWER_SAVE, /* Standby Power Save Mode */ + + ePMC_WOWL_MODE_POWER_SAVE /* Wake-on-Wireless LAN Power Save Mode */ + +} tPmcPowerSavingMode; + + + + +/* Switch states. */ + +typedef enum ePmcSwitchState + +{ + + ePMC_SWITCH_OFF, /* switch off */ + + ePMC_SWITCH_ON /* switch on */ + +} tPmcSwitchState; + + + + +/* Device power states. */ + +typedef enum ePmcPowerState + +{ + + ePMC_FULL_POWER, /* full power */ + + ePMC_LOW_POWER, /* low power */ + +} tPmcPowerState; + + + +/* PMC states. */ + +typedef enum ePmcState + +{ + + STOPPED, /* PMC is stopped */ + + FULL_POWER, /* full power */ + + LOW_POWER, /* low power */ + + REQUEST_IMPS, /* requesting IMPS */ + + IMPS, /* in IMPS */ + + REQUEST_BMPS, /* requesting BMPS */ + + BMPS, /* in BMPS */ + + REQUEST_FULL_POWER, /* requesting full power */ + + REQUEST_START_UAPSD, /* requesting Start UAPSD */ + + REQUEST_STOP_UAPSD, /* requesting Stop UAPSD */ + + UAPSD, /* in UAPSD */ + + REQUEST_STANDBY, /* requesting standby mode */ + + STANDBY, /* in standby mode */ + + REQUEST_ENTER_WOWL, /* requesting enter WOWL */ + + REQUEST_EXIT_WOWL, /* requesting exit WOWL */ + + WOWL /* Chip in WOWL mode */ + +} tPmcState; + + +/* Which beacons should be forwarded to the host. */ + +typedef enum ePmcBeaconsToForward + +{ + + ePMC_NO_BEACONS, /* none */ + + ePMC_BEACONS_WITH_TIM_SET, /* with TIM set */ + + ePMC_BEACONS_WITH_DTIM_SET, /* with DTIM set */ + + ePMC_NTH_BEACON, /* every Nth beacon */ + + ePMC_ALL_BEACONS /* all beacons */ + +} tPmcBeaconsToForward; + + + + +/* The Spatial Multiplexing Power Save modes. */ + +typedef enum ePmcSmpsMode + +{ + + ePMC_DYNAMIC_SMPS, /* dynamic SMPS */ + + ePMC_STATIC_SMPS /* static SMPS */ + +} tPmcSmpsMode; + + + + +/* Configuration parameters for Idle Mode Power Save (IMPS). */ + +typedef struct sPmcImpsConfigParams + +{ + + tANI_BOOLEAN enterOnAc; /* FALSE if device should enter IMPS only when host operating + + on battery power, TRUE if device should enter always */ + +} tPmcImpsConfigParams, *tpPmcImpsConfigParams; + + + + +/* Configuration parameters for Beacon Mode Power Save (BMPS). */ + +typedef struct sPmcBmpsConfigParams + +{ + + tANI_BOOLEAN enterOnAc; /* FALSE if device should enter BMPS only when host operating on + + battery power, TRUE if device should enter always */ + + tANI_U32 txThreshold; /* transmit rate under which BMPS should be entered (frames / traffic measurement period) */ + + tANI_U32 rxThreshold; /* receive rate under which BMPS should be entered (frames / traffic measurement period) */ + + tANI_U32 trafficMeasurePeriod; /* period for BMPS traffic measurement (milliseconds) */ + + tANI_U32 bmpsPeriod; /* amount of time in low power (beacon intervals) */ + + tPmcBeaconsToForward forwardBeacons; /* which beacons should be forwarded to the host */ + + tANI_U32 valueOfN; /* the value of N when forwardBeacons is set to ePMC_NTH_BEACON */ + + tANI_BOOLEAN usePsPoll; /* TRUE if PS-POLL should be used to retrieve frames from AP, FALSE if a + + null data frame with the PM bit reset should be used */ + + tANI_BOOLEAN setPmOnLastFrame; /* TRUE to keep device in BMPS as much as possible, FALSE otherwise, TRUE means: + + 1) PM bit should be set on last pending transmit data frame + + 2) null frame with PM bit set should be transmitted after last pending receive + + frame has been processed */ + + tANI_BOOLEAN enableBeaconEarlyTermination; /* if TRUE, BET feature in RIVA + will be enabled, FALSE otherwise, TRUE means: + RXP will read the beacon header for the + TIM bit & discard the rest if set to 0, + while in BMPS */ + tANI_U8 bcnEarlyTermWakeInterval; /* This specifies how often in terms + of LI we will disable BET in order to sync + up TSF*/ + +} tPmcBmpsConfigParams, *tpPmcBmpsConfigParams; + + + + +/* Configuration parameters for Spatial Multiplexing Power Save (SMPS). */ + +typedef struct sPmcSmpsConfigParams + +{ + + tPmcSmpsMode mode; /* mode to use */ + + tANI_BOOLEAN enterOnAc; /* FALSE if device should enter SMPS only when host operating on + + battery power, TRUE if device should enter always */ + +} tPmcSmpsConfigParams, *tpPmcSmpsConfigParams; + + +/* Routine definitions. */ + +extern eHalStatus pmcOpen (tHalHandle hHal); + +extern eHalStatus pmcStart (tHalHandle hHal); + +extern eHalStatus pmcStop (tHalHandle hHal); + +extern eHalStatus pmcClose (tHalHandle hHal ); + +extern eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams); + +extern eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams); + +extern eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode); + +extern eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal); + +extern eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal); + +extern eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode); + +extern eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState, tPmcSwitchState *pHwWlanSwitchState, + + tPmcSwitchState *pSwWlanSwitchState); + +extern tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode); + +extern eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, eHalStatus status), + + void *callbackContext, tRequestFullPowerReason fullPowerReason); + +extern eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod, + + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + + void *callbackContext); + +extern eHalStatus pmcRegisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext), + + void *checkContext); + +extern eHalStatus pmcDeregisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext)); + +extern void pmcMessageProcessor (tHalHandle hHal, tSirSmeRsp *pMsg); +extern void pmcResetImpsFailStatus (tHalHandle hHal); +extern v_BOOL_t IsPmcImpsReqFailed (tHalHandle hHal); + +extern eHalStatus pmcRequestBmps ( + + tHalHandle hHal, + + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + + void *callbackContext); + + +extern eHalStatus pmcStartUapsd ( + + tHalHandle hHal, + + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + + void *callbackContext); + + +extern eHalStatus pmcStopUapsd (tHalHandle hHal); + + +extern eHalStatus pmcRequestStandby ( + + tHalHandle hHal, + + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + + void *callbackContext); + + +extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, + + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState), + + void *callbackContext); + + +extern eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, + + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState)); + + +extern eHalStatus pmcReady(tHalHandle hHal); + + +void pmcDumpInit(tHalHandle hHal); + + +extern eHalStatus pmcWowlAddBcastPattern ( + tHalHandle hHal, + tpSirWowlAddBcastPtrn pattern, + tANI_U8 sessionId); + + +extern eHalStatus pmcWowlDelBcastPattern ( + tHalHandle hHal, + tpSirWowlDelBcastPtrn pattern, + tANI_U8 sessionId); + + +extern eHalStatus pmcEnterWowl ( + + tHalHandle hHal, + + void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status), + + void *enterWowlCallbackContext, +#ifdef WLAN_WAKEUP_EVENTS + void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd), + + void *wakeReasonIndCBContext, +#endif // WLAN_WAKEUP_EVENTS + tpSirSmeWowlEnterParams wowlEnterParams, tANI_U8 sessionId); + +extern eHalStatus pmcExitWowl (tHalHandle hHal, + tpSirSmeWowlExitParams wowlExitParams); + +extern eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn pmcSetKeepAlive + \brief Set the Keep Alive feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the Keep Alive. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the keep alive. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +extern eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 sessionId); + +extern tANI_BOOLEAN pmcValidateConnectState( tHalHandle hHal ); + +extern tANI_BOOLEAN pmcAllowImps( tHalHandle hHal ); + + +#ifdef FEATURE_WLAN_SCAN_PNO +/*Pref netw found Cb declaration*/ +typedef void(*preferredNetworkFoundIndCallback)(void *callbackContext, tpSirPrefNetworkFoundInd pPrefNetworkFoundInd); + +extern eHalStatus pmcSetPreferredNetworkList(tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext); +#endif // FEATURE_WLAN_SCAN_PNO + +#ifdef WLAN_FEATURE_PACKET_FILTERING +// Packet Coalescing Filter Match Count Callback declaration +typedef void(*FilterMatchCountCallback)(void *callbackContext, + tpSirRcvFltPktMatchRsp pRcvFltPktMatchRsp); +extern eHalStatus pmcGetFilterMatchCount(tHalHandle hHal, FilterMatchCountCallback callbackRoutine, + void *callbackContext, tANI_U8 sessionId); +#endif // WLAN_FEATURE_PACKET_FILTERING + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +// GTK Offload Information Callback declaration +typedef void(*GTKOffloadGetInfoCallback)(void *callbackContext, tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp); + +/* --------------------------------------------------------------------------- + \fn pmcSetGTKOffload + \brief Set GTK offload feature. + \param hHal - The handle returned by macOpen. + \param pGtkOffload - Pointer to the GTK offload request. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +extern eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn pmcGetGTKOffload + \brief Get GTK offload information. + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +extern eHalStatus pmcGetGTKOffload(tHalHandle hHal, + GTKOffloadGetInfoCallback callbackRoutine, + void *callbackContext, tANI_U8 sessionId); +#endif // WLAN_FEATURE_GTK_OFFLOAD + +/* Power Save Offload Changes */ +typedef enum eUapsdStatus +{ + PMC_UAPSD_DISABLED, + PMC_UAPSD_ENABLED, + PMC_UAPSD_DISABLE_PENDING, + PMC_UAPSD_ENABLE_PENDING +}tUapsdStatus; + +/* Power save Check Routine */ +typedef tANI_BOOLEAN (*PwrSaveCheckRoutine)(void *checkContext, + tANI_U32 sessionId); + +/* Power State Change Indication */ +typedef void (*PwrSaveStateChangeIndCb)(void *callbackContext, + tANI_U32 sessionId, + tPmcState pmcState); + +/* Full Power Req Callback */ +typedef void (*FullPowerReqCb)(void *callbackContext, + tANI_U32 sessionId, + eHalStatus status); + +/* Full Power Req Callback */ +typedef void (*UapsdStartIndCb)(void *callbackContext, + tANI_U32 sessionId, + eHalStatus status); + +eHalStatus pmcOffloadOpen(tHalHandle hHal); + +eHalStatus pmcOffloadStart(tHalHandle hHal); + +eHalStatus pmcOffloadStop(tHalHandle hHal); + +eHalStatus pmcOffloadClose(tHalHandle hHal); + +eHalStatus pmcOffloadCleanup(tHalHandle hHal, tANI_U32 sessionId); + +eHalStatus pmcOffloadConfigEnablePowerSave(tHalHandle hHal, + tPmcPowerSavingMode psMode); + +eHalStatus pmcOffloadConfigDisablePowerSave(tHalHandle hHal, + tPmcPowerSavingMode psMode); + +tPmcState pmcOffloadGetPmcState(tHalHandle hHal, tANI_U32 sessionId); + +void pmcOffloadMessageProcessor(tHalHandle hHal, tSirSmeRsp *pMsg); + +eHalStatus pmcOffloadRegisterPowerSaveCheck(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveCheckRoutine checkRoutine, + void *checkContext); + +eHalStatus pmcOffloadDeregisterPowerSaveCheck(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveCheckRoutine checkRoutine); + +eHalStatus pmcOffloadRegisterDeviceStateUpdateInd(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveStateChangeIndCb stateChangeCb, + void *callbackContext); + +eHalStatus pmcOffloadDeregisterDeviceStateUpdateInd(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveStateChangeIndCb stateChangeCb); + +eHalStatus PmcOffloadEnableStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId); + +eHalStatus PmcOffloadDisableStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId); + +eHalStatus pmcOffloadRequestFullPower(tHalHandle hHal, tANI_U32 sessionId, + FullPowerReqCb fullpwrReqCb,void *callbackContext, + tRequestFullPowerReason fullPowerReason); + +eHalStatus pmcOffloadStartUapsd(tHalHandle hHal, tANI_U32 sessionId, + UapsdStartIndCb uapsdStartIndCb, + void *callbackContext); + +eHalStatus pmcOffloadStopUapsd(tHalHandle hHal, tANI_U32 sessionId); + +#ifdef FEATURE_WLAN_TDLS +eHalStatus pmcOffloadSetTdlsProhibitBmpsStatus(tHalHandle hHal, + tANI_U32 sessionId, + v_BOOL_t val); +#endif + +tANI_BOOLEAN pmcOffloadIsPowerSaveEnabled (tHalHandle hHal, tANI_U32 sessionId, + tPmcPowerSavingMode psMode); + +eHalStatus PmcOffloadEnableDeferredStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId, + tANI_BOOLEAN isReassoc); + +eHalStatus PmcOffloadDisableDeferredStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInside.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInside.h new file mode 100644 index 000000000000..90ddd71b549f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInside.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __SMEINSIDE_H ) +#define __SMEINSIDE_H + + +/**========================================================================= + + \file smeInside.h + + \brief prototype for SME structures and APIs used inside SME + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_status.h" +#include "vos_lock.h" +#include "vos_trace.h" +#include "vos_memory.h" +#include "vos_types.h" +#include "sirApi.h" +#include "csrInternal.h" +#include "sme_QosApi.h" +#include "smeQosInternal.h" + + +#ifdef FEATURE_OEM_DATA_SUPPORT +#include "oemDataInternal.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI +#include "sme_RrmApi.h" +#endif +ePhyChanBondState csrConvertCBIniValueToPhyCBState(v_U32_t cbIniValue); + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/* + * In case MAX num of STA are connected to SAP, switching off SAP causes + * two SME cmd to be enqueued for each STA. Keeping SME total cmds as following + * to make sure we have space for these cmds + some additional cmds. + */ +#define SME_TOTAL_COMMAND (HAL_NUM_STA * 3) + + +typedef struct sGenericPmcCmd +{ + tANI_U32 size; //sizeof the data in the union, if any + tANI_U32 sessionId; + tRequestFullPowerReason fullPowerReason; + + /* If TRUE, the command shall not put back to the queue, + free the memory instead */ + tANI_BOOLEAN fReleaseWhenDone; + union + { + tExitBmpsInfo exitBmpsInfo; + tSirSmeWowlEnterParams enterWowlInfo; + tSirSmeWowlExitParams exitWowlInfo; + }u; +} tGenericPmcCmd; + + +typedef struct sGenericQosCmd +{ + sme_QosWmmTspecInfo tspecInfo; + sme_QosEdcaAcType ac; + v_U8_t tspec_mask; +} tGenericQosCmd; + +typedef struct sRemainChlCmd +{ + tANI_U8 chn; + tANI_U8 phyMode; + tANI_U32 duration; + tANI_U8 isP2PProbeReqAllowed; + void* callback; + void* callbackCtx; +}tRemainChlCmd; + +typedef struct sNoACmd +{ + tP2pPsConfig NoA; +} tNoACmd; +#ifdef FEATURE_WLAN_TDLS +typedef struct TdlsSendMgmtInfo +{ + tSirMacAddr peerMac; + tANI_U8 frameType; + tANI_U8 dialog; + tANI_U16 statusCode; + tANI_U8 responder; + tANI_U32 peerCapability; + tANI_U8 *buf; + tANI_U8 len; +} tTdlsSendMgmtCmdInfo; + +typedef struct TdlsLinkEstablishInfo +{ + tSirMacAddr peerMac; + tANI_U8 uapsdQueues; + tANI_U8 maxSp; + tANI_U8 isBufSta; + tANI_U8 isOffChannelSupported; + tANI_U8 isResponder; + tANI_U8 supportedChannelsLen; + tANI_U8 supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; + tANI_U8 supportedOperClassesLen; + tANI_U8 supportedOperClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} tTdlsLinkEstablishCmdInfo; + +typedef struct TdlsAddStaInfo +{ + eTdlsAddOper tdlsAddOper; + tSirMacAddr peerMac; + tANI_U16 capability; + tANI_U8 extnCapability[SIR_MAC_MAX_EXTN_CAP]; + tANI_U8 supportedRatesLen; + tANI_U8 supportedRates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; + tSirHTCap HTCap; + tANI_U8 vhtcap_present; + tSirVHTCap VHTCap; + tANI_U8 uapsdQueues; + tANI_U8 maxSp; +} tTdlsAddStaCmdInfo; + +typedef struct TdlsDelStaInfo +{ + tSirMacAddr peerMac; +} tTdlsDelStaCmdInfo; +/* + * TDLS cmd info, CMD from SME to PE. + */ +typedef struct s_tdls_cmd +{ + tANI_U32 size; + union + { + tTdlsLinkEstablishCmdInfo tdlsLinkEstablishCmdInfo; + tTdlsSendMgmtCmdInfo tdlsSendMgmtCmdInfo; + tTdlsAddStaCmdInfo tdlsAddStaCmdInfo; + tTdlsDelStaCmdInfo tdlsDelStaCmdInfo; + }u; +} tTdlsCmd; +#endif /* FEATURE_WLAN_TDLS */ + +/** + * struct s_ani_set_tx_max_pwr - Req params to set max tx power + * @bssid: bssid to set the power cap for + * @self_mac_addr:self mac address + * @power: power to set in dB + */ +struct s_ani_set_tx_max_pwr +{ + tSirMacAddr bssid; + tSirMacAddr self_sta_mac_addr; + tPowerdBm power; +}; + +typedef struct tagSmeCmd +{ + tListElem Link; + eSmeCommandType command; + tANI_U32 sessionId; + union + { + tScanCmd scanCmd; + tRoamCmd roamCmd; + tWmStatusChangeCmd wmStatusChangeCmd; + tSetKeyCmd setKeyCmd; + tRemoveKeyCmd removeKeyCmd; + tGenericPmcCmd pmcCmd; + tGenericQosCmd qosCmd; +#ifdef FEATURE_OEM_DATA_SUPPORT + tOemDataCmd oemDataCmd; +#endif + tRemainChlCmd remainChlCmd; + tNoACmd NoACmd; + tAddStaForSessionCmd addStaSessionCmd; + tDelStaForSessionCmd delStaSessionCmd; +#ifdef FEATURE_WLAN_TDLS + tTdlsCmd tdlsCmd; +#endif + struct s_ani_set_tx_max_pwr set_tx_max_pwr; + }u; +}tSmeCmd; + + + +/*-------------------------------------------------------------------------- + Internal to SME + ------------------------------------------------------------------------*/ + +//To get a command buffer +//Return: NULL if there no more command buffer left +tSmeCmd *smeGetCommandBuffer( tpAniSirGlobal pMac ); +void smePushCommand( tpAniSirGlobal pMac, tSmeCmd *pCmd, tANI_BOOLEAN fHighPriority ); +void smeProcessPendingQueue( tpAniSirGlobal pMac ); +void smeReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCmd); +void purgeSmeSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId, + tDblLinkList *pList); +tANI_BOOLEAN smeCommandPending(tpAniSirGlobal pMac); +tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +tANI_BOOLEAN pmcOffloadProcessCommand(tpAniSirGlobal pMac,tSmeCmd *pCommand); +tANI_BOOLEAN pmcOffloadIsStaInPowerSave(tpAniSirGlobal pMac, tANI_U32 sessionId); + +//this function is used to abort a command where the normal processing of the command +//is terminated without going through the normal path. it is here to take care of callbacks for +//the command, if applicable. +void pmcAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping ); +void pmcOffloadAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, + tANI_BOOLEAN fStopping ); + +tANI_BOOLEAN qosProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); + +eHalStatus csrProcessScanCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +void csrRoamProcessWmStatusChangeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +void csrReinitRoamCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrReinitWmStatusChangeCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrReinitSetKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrReinitRemoveKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +eHalStatus csrRoamProcessSetKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +eHalStatus csrRoamProcessRemoveKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +void csrReleaseCommandSetKey(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrReleaseCommandRemoveKey(tpAniSirGlobal pMac, tSmeCmd *pCommand); +//eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 roamId ); +eHalStatus csrRoamIssueRemoveKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamRemoveKey *pRemoveKey, tANI_U32 roamId ); +eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand, tRequestFullPowerReason *pReason, + tANI_BOOLEAN *pfNeedPower); +void csrAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping ); + +VOS_STATUS csrIsValidChannel(tpAniSirGlobal pMac, tANI_U8 chnNum); +tANI_BOOLEAN csrRoamIsValid40MhzChannel(tpAniSirGlobal pMac, tANI_U8 chnNum); + +eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme); +eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme); + +#ifdef FEATURE_OEM_DATA_SUPPORT +eHalStatus oemData_ProcessOemDataReqCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand); +#endif + +eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +eHalStatus csrProcessAddStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg); +eHalStatus csrProcessDelStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +eHalStatus csrProcessDelStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg); + +#ifdef WLAN_NS_OFFLOAD +/* --------------------------------------------------------------------------- + \fn pmcSetNSOffload + \brief Set the host offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the offload request. + \param sessionId . Session index of the session + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 sessionId); +#endif //WLAN_NS_OFFLOAD + +#ifdef FEATURE_WLAN_SCAN_PNO +eHalStatus pmcSetPreferredNetworkList(tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext); +eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChannel *pChannelList, tANI_U8 b11dResolved); +#endif // FEATURE_WLAN_SCAN_PNO +eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams, tANI_BOOLEAN forced); + +tANI_BOOLEAN csrRoamGetConcurrencyConnectStatusForBmps(tpAniSirGlobal pMac); +#ifdef FEATURE_WLAN_TDLS +eHalStatus csrTdlsSendMgmtReq(tHalHandle hHal, tANI_U8 sessionId, tCsrTdlsSendMgmt *tdlsSendMgmt); +VOS_STATUS csrTdlsSendLinkEstablishParams(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams *tdlsLinkEstablishParams); +eHalStatus csrTdlsAddPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac); +eHalStatus csrTdlsChangePeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams); +eHalStatus csrTdlsDelPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac); +eHalStatus csrTdlsProcessCmd(tpAniSirGlobal pMac,tSmeCmd *pCommand ); +eHalStatus csrTdlsProcessLinkEstablish( tpAniSirGlobal pMac, tSmeCmd *cmd ); +eHalStatus tdlsMsgProcessor(tpAniSirGlobal pMac,v_U16_t msg_type, + void *pMsgBuf); +#endif /* FEATURE_WLAN_TDLS */ + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +eHalStatus csrFlushCfgBgScanRoamChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId); +eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + const tANI_U8 *pChannelList, + const tANI_U8 numChannels); +eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + eCsrBand eBand); +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +eHalStatus csrCreateRoamScanChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tANI_U8 *pChannelList, + tANI_U8 numChannels, + const eCsrBand eBand); +#endif + +ePhyChanBondState csrConvertCBIniValueToPhyCBState(v_U32_t cbIniValue); + +eHalStatus csrPsOffloadIsFullPowerNeeded(tpAniSirGlobal pMac, + tSmeCmd *pCommand, + tRequestFullPowerReason *pReason, + tANI_BOOLEAN *pfNeedPower); + +void activeListCmdTimeoutHandle(void *userData); + +#endif //#if !defined( __SMEINSIDE_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h new file mode 100644 index 000000000000..ab4b59137900 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __SMEINTERNAL_H ) +#define __SMEINTERNAL_H + + +/**========================================================================= + + \file smeInternal.h + + \brief prototype for SME internal structures and APIs used for SME and MAC + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_status.h" +#include "vos_lock.h" +#include "vos_trace.h" +#include "vos_memory.h" +#include "vos_types.h" +#include "vos_diag_core_event.h" +#include "csrLinkList.h" + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +// Mask can be only have one bit set +typedef enum eSmeCommandType +{ + eSmeNoCommand = 0, + eSmeDropCommand, + //CSR + eSmeCsrCommandMask = 0x10000, //this is not a command, it is to identify this is a CSR command + eSmeCommandScan, + eSmeCommandRoam, + eSmeCommandWmStatusChange, + eSmeCommandSetKey, + eSmeCommandRemoveKey, + eSmeCommandAddStaSession, + eSmeCommandDelStaSession, + eSmeCommandSetMaxTxPower, +#ifdef FEATURE_WLAN_TDLS + //eSmeTdlsCommandMask = 0x80000, //To identify TDLS commands + //These can be considered as csr commands. + eSmeCommandTdlsSendMgmt, + eSmeCommandTdlsAddPeer, + eSmeCommandTdlsDelPeer, + eSmeCommandTdlsLinkEstablish, +#endif + //PMC + eSmePmcCommandMask = 0x20000, //To identify PMC commands + eSmeCommandEnterImps, + eSmeCommandExitImps, + eSmeCommandEnterBmps, + eSmeCommandExitBmps, + eSmeCommandEnterUapsd, + eSmeCommandExitUapsd, + eSmeCommandEnterWowl, + eSmeCommandExitWowl, + eSmeCommandEnterStandby, + //QOS + eSmeQosCommandMask = 0x40000, //To identify Qos commands + eSmeCommandAddTs, + eSmeCommandDelTs, +#ifdef FEATURE_OEM_DATA_SUPPORT + eSmeCommandOemDataReq = 0x80000, //To identify the oem data commands +#endif + eSmeCommandRemainOnChannel, + eSmeCommandNoAUpdate, +} eSmeCommandType; + + +typedef enum eSmeState +{ + SME_STATE_STOP, + SME_STATE_START, + SME_STATE_READY, +} eSmeState; + +#define SME_IS_START(pMac) (SME_STATE_STOP != (pMac)->sme.state) +#define SME_IS_READY(pMac) (SME_STATE_READY == (pMac)->sme.state) + +typedef struct sStatsExtEvent { + tANI_U32 vdev_id; + tANI_U32 event_data_len; + tANI_U8 event_data[]; +} tStatsExtEvent, *tpStatsExtEvent; + +#define MAX_ACTIVE_CMD_STATS 16 + +typedef struct sActiveCmdStats { + eSmeCommandType command; + tANI_U32 reason; + tANI_U32 sessionId; + v_U64_t timestamp; +} tActiveCmdStats; + +typedef struct sSelfRecoveryStats { + tActiveCmdStats activeCmdStats[MAX_ACTIVE_CMD_STATS]; + tANI_U8 cmdStatsIndx; +} tSelfRecoveryStats; + +typedef void (*ocb_callback)(void *context, void *response); + +typedef struct tagSmeStruct +{ + eSmeState state; + vos_lock_t lkSmeGlobalLock; + tANI_U32 totalSmeCmd; + /* following pointer contains array of pointers for tSmeCmd* */ + void **pSmeCmdBufAddr; + tDblLinkList smeCmdActiveList; + tDblLinkList smeCmdPendingList; + tDblLinkList smeCmdFreeList; //preallocated roam cmd list + void (*pTxPerHitCallback) (void *pCallbackContext); /* callback for Tx PER hit to HDD */ + void *pTxPerHitCbContext; + tVOS_CON_MODE currDeviceMode; +#ifdef FEATURE_WLAN_LPHB + void (*pLphbIndCb) (void *pHddCtx, tSirLPHBInd *indParam); +#endif /* FEATURE_WLAN_LPHB */ + //pending scan command list + tDblLinkList smeScanCmdPendingList; + //active scan command list + tDblLinkList smeScanCmdActiveList; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + vos_event_wlan_status_payload_type eventPayload; +#endif +#ifdef FEATURE_WLAN_CH_AVOID + void (*pChAvoidNotificationCb) (void *hdd_context, void *indi_param); +#endif /* FEATURE_WLAN_CH_AVOID */ +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + void(*pLinkLayerStatsIndCallback)(void *callbackContext, + int indType, void *pRsp); +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + void (*pAutoShutdownNotificationCb) (void); +#endif + /* Maximum interfaces allowed by the host */ + tANI_U8 max_intf_count; + void (* StatsExtCallback) (void *, tStatsExtEvent *); + /* link speed callback */ + void (*pLinkSpeedIndCb) (tSirLinkSpeedInfo *indParam, void *pDevContext); + void *pLinkSpeedCbContext; + /* get rssi callback */ + void (*pget_rssi_ind_cb) (struct sir_rssi_resp *param, void *pcontext); + void *pget_rssi_cb_context; +#ifdef FEATURE_WLAN_EXTSCAN + void (*pExtScanIndCb) (void *, const tANI_U16, void *); +#endif /* FEATURE_WLAN_EXTSCAN */ +#ifdef WLAN_FEATURE_NAN + void (*nanCallback) (void*, tSirNanEvent*); +#endif + + int (*get_tsf_cb)(void *pcb_cxt, struct stsf *ptsf); + void *get_tsf_cxt; + + v_BOOL_t enableSelfRecovery; + tCsrLinkStatusCallback linkStatusCallback; + void *linkStatusContext; + tcsr_fw_state_callback fw_state_callback; + void *fw_state_context; + /* get temperature event context and callback */ + void *pTemperatureCbContext; + void (*pGetTemperatureCb)(int temperature, void *context); + uint8_t miracast_value; + + /* OCB callbacks */ + void *ocb_set_config_context; + ocb_callback ocb_set_config_callback; + void *ocb_get_tsf_timer_context; + ocb_callback ocb_get_tsf_timer_callback; + void *dcc_get_stats_context; + ocb_callback dcc_get_stats_callback; + void *dcc_update_ndl_context; + ocb_callback dcc_update_ndl_callback; + void *dcc_stats_event_context; + ocb_callback dcc_stats_event_callback; +#ifdef WLAN_FEATURE_MEMDUMP + void (*fw_dump_callback)(void *context, struct fw_dump_rsp *rsp); +#endif + void (*set_thermal_level_cb)(void *hdd_context, uint8_t level); + + void (*rssi_threshold_breached_cb)(void *, struct rssi_breach_event *); + void (*lost_link_info_cb)(void *context, + struct sir_lost_link_info *lost_link_info); + void (*smps_force_mode_cb)(void *context, + struct sir_smps_force_mode_event *smps_force_mode_info); +} tSmeStruct, *tpSmeStruct; + + +#endif //#if !defined( __SMEINTERNAL_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/smeQosInternal.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeQosInternal.h new file mode 100644 index 000000000000..2f45a6e5bf60 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeQosInternal.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __SMEQOSINTERNAL_H ) +#define __SMEQOSINTERNAL_H + + +/**========================================================================= + + \file smeQosInternal.h + + \brief prototype for SME QoS APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_lock.h" +#include "vos_trace.h" +#include "vos_memory.h" +#include "vos_types.h" +#include "aniGlobal.h" +#include "sirApi.h" +#include "sme_QosApi.h" +#include "smeInternal.h" + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +#define SME_QOS_AP_SUPPORTS_APSD 0x80 + +/*--------------------------------------------------------------------------- + Enumeration of the various EDCA Access Categories: + Based on AC to ACI mapping in 802.11e spec (identical to WMM) +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_EDCA_AC_BE = 0, /* Best effort access category */ + SME_QOS_EDCA_AC_BK = 1, /* Background access category */ + SME_QOS_EDCA_AC_VI = 2, /* Video access category */ + SME_QOS_EDCA_AC_VO = 3, /* Voice access category */ + + SME_QOS_EDCA_AC_MAX +} sme_QosEdcaAcType; + + +/*--------------------------------------------------------------------------- + Enumeration of the various CSR event indication types that would be reported + by CSR +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_CSR_JOIN_REQ = 0, + SME_QOS_CSR_ASSOC_COMPLETE, + SME_QOS_CSR_REASSOC_REQ, + SME_QOS_CSR_REASSOC_COMPLETE, + SME_QOS_CSR_REASSOC_FAILURE, + SME_QOS_CSR_DISCONNECT_REQ, + SME_QOS_CSR_DISCONNECT_IND, + SME_QOS_CSR_HANDOFF_ASSOC_REQ, + SME_QOS_CSR_HANDOFF_COMPLETE, + SME_QOS_CSR_HANDOFF_FAILURE, +#ifdef WLAN_FEATURE_VOWIFI_11R + SME_QOS_CSR_PREAUTH_SUCCESS_IND, + SME_QOS_CSR_SET_KEY_SUCCESS_IND, +#endif +}sme_QosCsrEventIndType; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +typedef enum +{ + SME_QOS_DIAG_ADDTS_REQ = 0, + SME_QOS_DIAG_ADDTS_RSP, + SME_QOS_DIAG_DELTS + +}sme_QosDiagQosEventSubtype; + +typedef enum +{ + SME_QOS_DIAG_ADDTS_ADMISSION_ACCEPTED = 0, + SME_QOS_DIAG_ADDTS_INVALID_PARAMS, + SME_QOS_DIAG_ADDTS_RESERVED, + SME_QOS_DIAG_ADDTS_REFUSED, + SME_QOS_DIAG_USER_REQUESTED, + SME_QOS_DIAG_DELTS_IND_FROM_AP, + +}sme_QosDiagQosEventReasonCode; + +#endif //FEATURE_WLAN_DIAG_SUPPORT +/*--------------------------------------------------------------------------- + The association information structure to be passed by CSR after assoc or + reassoc is done +---------------------------------------------------------------------------*/ +typedef struct +{ + tSirBssDescription *pBssDesc; + tCsrRoamProfile *pProfile; +} sme_QosAssocInfo; + +/*-------------------------------------------------------------------------- + External APIs for CSR - Internal to SME + ------------------------------------------------------------------------*/ + +/* -------------------------------------------------------------------------- + \brief sme_QosOpen() - This function must be called before any API call to + SME QoS module. + + \param pMac - Pointer to the global MAC parameter structure. + + \return eHalStatus +----------------------------------------------------------------------------*/ +eHalStatus sme_QosOpen(tpAniSirGlobal pMac); + +/* -------------------------------------------------------------------------- + \brief sme_QosClose() - To close down SME QoS module. There should not be + any API call into this module after calling this function until another + call of sme_QosOpen. + + \param pMac - Pointer to the global MAC parameter structure. + + \return eHalStatus +----------------------------------------------------------------------------*/ +eHalStatus sme_QosClose(tpAniSirGlobal pMac); + +/*-------------------------------------------------------------------------- + \brief sme_QosSetParams() - This function is used by HDD to provide the + default TSPEC params to SME. + + \param pMac - Pointer to the global MAC parameter structure. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info per AC as defined above, provided by HDD + + \return eHAL_STATUS_SUCCESS - Setparam is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosSetParams(tpAniSirGlobal pMac, sme_QosWmmTspecInfo * pQoSInfo); + +/*-------------------------------------------------------------------------- + \brief sme_QosMsgProcessor() - sme_ProcessMsg() calls this function for the + messages that are handled by SME QoS module. + + \param pMac - Pointer to the global MAC parameter structure. + \param msg_type - the type of msg passed by PE as defined in wniApi.h + \param pMsgBuf - a pointer to a buffer that maps to various structures base + on the message type. + The beginning of the buffer can always map to tSirSmeRsp. + + \return eHalStatus. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type, + void *pMsgBuf); + +/*-------------------------------------------------------------------------- + Internal APIs for CSR + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + \brief sme_QosValidateParams() - The SME QoS API exposed to CSR to validate AP + capabilities regarding QoS support & any other QoS parameter validation. + + \param pMac - Pointer to the global MAC parameter structure. + \param pBssDesc - Pointer to the BSS Descriptor information passed down by + CSR to PE while issuing the Join request + + \return eHAL_STATUS_SUCCESS - Validation is successful + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosValidateParams(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc); + +/*-------------------------------------------------------------------------- + \brief sme_QosCsrEventInd() - The QoS sub-module in SME expects notifications + from CSR when certain events occur as mentioned in sme_QosCsrEventIndType. + + \param pMac - Pointer to the global MAC parameter structure. + \param ind - The event occurred of type sme_QosCsrEventIndType. + \param pEvent_info - Information related to the event + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosCsrEventInd(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosCsrEventIndType ind, + void *pEvent_info); + +/*-------------------------------------------------------------------------- + \brief sme_QosGetACMMask() - The QoS sub-module API to find out on which ACs + AP mandates Admission Control (ACM = 1) + + \param pMac - Pointer to the global MAC parameter structure. + \param pSirBssDesc - The event occurred of type sme_QosCsrEventIndType. + \param pIes - the parsed IE for pSirBssDesc. This can be NULL. + + + \return a bit mask indicating for which ACs AP has ACM set to 1 + + \sa + + --------------------------------------------------------------------------*/ +v_U8_t sme_QosGetACMMask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes); + +/* + sme_QosTriggerUapsdChange + It trigger a change on UAPSD (either disable/enable UAPSD) on current QoS flows +*/ +sme_QosStatusType sme_QosTriggerUapsdChange( tpAniSirGlobal pMac ); + +#ifdef FEATURE_WLAN_ESE +v_U8_t sme_QosEseRetrieveTspecInfo(tpAniSirGlobal pMac, v_U8_t sessionId, tTspecInfo *pTspecInfo); + +#endif + +#endif //#if !defined( __SMEQOSINTERNAL_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/smeRrmInternal.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeRrmInternal.h new file mode 100644 index 000000000000..86f397ec5d84 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeRrmInternal.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2011-2012, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __SMERRMINTERNAL_H ) +#define __SMERRMINTERNAL_H + + +/**========================================================================= + + \file smeRrmInternal.h + + \brief prototype for SME RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_lock.h" +#include "vos_trace.h" +#include "vos_memory.h" +#include "vos_types.h" +#include "rrmGlobal.h" + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +typedef struct sRrmNeighborReportDesc +{ + tListElem List; + tSirNeighborBssDescription *pNeighborBssDescription; + tANI_U32 roamScore; + tANI_U8 sessionId; +} tRrmNeighborReportDesc, *tpRrmNeighborReportDesc; + + +typedef void (*NeighborReportRspCallback) (void *context, VOS_STATUS vosStatus); + +typedef struct sRrmNeighborRspCallbackInfo +{ + tANI_U32 timeout; //in ms.. min value is 10 (10ms) + NeighborReportRspCallback neighborRspCallback; + void *neighborRspCallbackContext; +} tRrmNeighborRspCallbackInfo, *tpRrmNeighborRspCallbackInfo; + +typedef struct sRrmNeighborRequestControlInfo +{ + tANI_BOOLEAN isNeighborRspPending; //To check whether a neighbor req is already sent and response pending + vos_timer_t neighborRspWaitTimer; + tRrmNeighborRspCallbackInfo neighborRspCallbackInfo; +} tRrmNeighborRequestControlInfo, *tpRrmNeighborRequestControlInfo; + +typedef struct sRrmSMEContext +{ + tANI_U16 token; + tCsrBssid sessionBssId; + tANI_U8 regClass; + tCsrChannelInfo channelList; //list of all channels to be measured. + tANI_U8 currentIndex; + tAniSSID ssId; //SSID used in the measuring beacon report. + tSirMacAddr bssId; //bssid used for beacon report measurement. + tANI_U16 randnIntvl; //Randomization interval to be used in subsequent measurements. + tANI_U16 duration[SIR_ESE_MAX_MEAS_IE_REQS]; + tANI_U8 measMode[SIR_ESE_MAX_MEAS_IE_REQS]; + struct rrm_config_param rrmConfig; + vos_timer_t IterMeasTimer; + tDblLinkList neighborReportCache; + tRrmNeighborRequestControlInfo neighborReqControlInfo; + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + tCsrEseBeaconReq eseBcnReqInfo; + tANI_BOOLEAN eseBcnReqInProgress; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + tRrmMsgReqSource msgSource; +}tRrmSMEContext, *tpRrmSMEContext; + +typedef struct sRrmNeighborReq +{ + tANI_U8 no_ssid; + tSirMacSSid ssid; +}tRrmNeighborReq, *tpRrmNeighborReq; + +#endif //#if !defined( __SMERRMINTERNAL_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h new file mode 100644 index 000000000000..cd46e0e7de23 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h @@ -0,0 +1,4406 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __SME_API_H ) +#define __SME_API_H + + +/**========================================================================= + + \file smeApi.h + + \brief prototype for SME APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "ccmApi.h" +#include "csrApi.h" +#include "pmcApi.h" +#include "vos_mq.h" +#include "vos_lock.h" +#include "halTypes.h" +#include "sirApi.h" +#include "btcApi.h" +#include "vos_nvitem.h" +#include "p2p_Api.h" +#include "smeInternal.h" +#include "regdomain.h" + +#ifdef FEATURE_OEM_DATA_SUPPORT +#include "oemDataApi.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI +#include "smeRrmInternal.h" +#endif + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#define SME_SUMMARY_STATS 1 +#define SME_GLOBAL_CLASSA_STATS 2 +#define SME_GLOBAL_CLASSB_STATS 4 +#define SME_GLOBAL_CLASSC_STATS 8 +#define SME_GLOBAL_CLASSD_STATS 16 +#define SME_PER_STA_STATS 32 + +#define SME_INVALID_COUNTRY_CODE "XX" + +#define SME_2_4_GHZ_MAX_FREQ 3000 + +#define SME_SET_CHANNEL_REG_POWER(reg_info_1, val) do { \ + reg_info_1 &= 0xff00ffff; \ + reg_info_1 |= ((val & 0xff) << 16); \ +} while(0) + +#define SME_SET_CHANNEL_MAX_TX_POWER(reg_info_2, val) do { \ + reg_info_2 &= 0xffff00ff; \ + reg_info_2 |= ((val & 0xff) << 8); \ +} while(0) + +#define NUM_OF_BANDS 2 +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +typedef struct _smeConfigParams +{ + tCsrConfigParam csrConfig; +#if defined WLAN_FEATURE_VOWIFI + struct rrm_config_param rrmConfig; +#endif +#if defined FEATURE_WLAN_LFR + tANI_U8 isFastRoamIniFeatureEnabled; + tANI_U8 MAWCEnabled; +#endif +#if defined FEATURE_WLAN_ESE + tANI_U8 isEseIniFeatureEnabled; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; +#endif + tANI_BOOLEAN fScanOffload; + tANI_U8 max_amsdu_num; + tANI_BOOLEAN fP2pListenOffload; + tANI_BOOLEAN pnoOffload; + tANI_U8 fEnableDebugLog; + tANI_U8 max_intf_count; + tANI_BOOLEAN enable5gEBT; + tANI_BOOLEAN enableSelfRecovery; + uint32_t f_sta_miracast_mcc_rest_time_val; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + bool sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + uint8_t f_prefer_non_dfs_on_radar; + uint32_t fine_time_meas_cap; + int8_t first_scan_bucket_threshold; +} tSmeConfigParams, *tpSmeConfigParams; + +typedef enum +{ + eSME_ROAM_TRIGGER_NONE = 0, + eSME_ROAM_TRIGGER_SCAN = 1, + eSME_ROAM_TRIGGER_FAST_ROAM = 2, + eSME_ROAM_TRIGGER_MAX +} tSmeFastRoamTrigger; + +#ifdef FEATURE_WLAN_TDLS + +#define SME_TDLS_MAX_SUPP_CHANNELS 128 +#define SME_TDLS_MAX_SUPP_OPER_CLASSES 32 + +typedef struct _smeTdlsPeerCapParams { + tANI_U8 isPeerResponder; + tANI_U8 peerUapsdQueue; + tANI_U8 peerMaxSp; + tANI_U8 peerBuffStaSupport; + tANI_U8 peerOffChanSupport; + tANI_U8 peerCurrOperClass; + tANI_U8 selfCurrOperClass; + tANI_U8 peerChanLen; + tANI_U8 peerChan[SME_TDLS_MAX_SUPP_CHANNELS]; + tANI_U8 peerOperClassLen; + tANI_U8 peerOperClass[SME_TDLS_MAX_SUPP_OPER_CLASSES]; + tANI_U8 prefOffChanNum; + tANI_U8 prefOffChanBandwidth; + tANI_U8 opClassForPrefOffChan; +} tSmeTdlsPeerCapParams; + +typedef enum +{ + eSME_TDLS_PEER_STATE_PEERING, + eSME_TDLS_PEER_STATE_CONNECTED, + eSME_TDLS_PEER_STATE_TEARDOWN, + /* Add peer mac into connection table */ + eSME_TDLS_PEER_ADD_MAC_ADDR, + /* Remove peer mac from connection table */ + eSME_TDLS_PEER_REMOVE_MAC_ADDR, +} eSmeTdlsPeerState; + +typedef struct _smeTdlsPeerStateParams +{ + tANI_U32 vdevId; + tSirMacAddr peerMacAddr; + tANI_U32 peerState; + tSmeTdlsPeerCapParams peerCap; +} tSmeTdlsPeerStateParams; + +#define ENABLE_CHANSWITCH 1 +#define DISABLE_CHANSWITCH 2 +#define BW_20_OFFSET_BIT 0 +#define BW_40_OFFSET_BIT 1 +#define BW_80_OFFSET_BIT 2 +#define BW_160_OFFSET_BIT 3 + +typedef struct _smeTdlsChanSwitchParams +{ + tANI_U32 vdev_id; + tSirMacAddr peer_mac_addr; + tANI_U16 tdls_off_ch_bw_offset;/* Target Off Channel Bandwidth offset */ + tANI_U8 tdls_off_channel; /* Target Off Channel */ + tANI_U8 tdls_off_ch_mode; /* TDLS Off Channel Mode */ + tANI_U8 is_responder; /* is peer responder or initiator */ + uint8_t opclass; /* tdls operating class */ +} tSmeTdlsChanSwitchParams; +#endif /* FEATURE_WLAN_TDLS */ + +/* Thermal Mitigation*/ + +typedef struct { + u_int16_t smeMinTempThreshold; + u_int16_t smeMaxTempThreshold; +} tSmeThermalLevelInfo; + + +enum sme_max_bad_peer_thresh_levels { + IEEE80211_B_LEVEL = 0, + IEEE80211_AG_LEVEL, + IEEE80211_N_LEVEL, + IEEE80211_AC_LEVEL, + IEEE80211_MAX_LEVEL, +}; + +struct sme_bad_peer_thresh{ + uint32_t cond; + uint32_t delta; + uint32_t percentage; + uint32_t thresh; + uint32_t limit; +}; + +struct sme_bad_peer_txctl_param{ + /* Array of thermal levels */ + struct sme_bad_peer_thresh thresh[IEEE80211_MAX_LEVEL]; + uint32_t enabled; + uint32_t period; + uint32_t txq_limit; + uint32_t tgt_backoff; + uint32_t tgt_report_prd; +}; + + +#define SME_MAX_THERMAL_LEVELS (4) + +typedef struct { + /* Array of thermal levels */ + tSmeThermalLevelInfo smeThermalLevels[SME_MAX_THERMAL_LEVELS]; + u_int8_t smeThermalMgmtEnabled; + u_int32_t smeThrottlePeriod; +} tSmeThermalParams; + +#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 + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + + \brief sme_Open() - Initialize all SME modules and put them at idle state + + The function initializes each module inside SME, PMC, CCM, CSR, etc. . Upon + successfully return, all modules are at idle state ready to start. + + smeOpen must be called before any other SME APIs can be involved. + smeOpen must be called after macOpen. + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME is successfully initialized. + + Other status means SME is failed to be initialized + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Open(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + + \brief sme_init_chan_list() - Initialize sme channel info + + This function initializes sme channel information which can + be known only after getting the regulatory information which, for discrete, + will come from target after the fw got downloaded. For ISOC, this information + will be available in nv. + + \param hal - The handle returned by macOpen. + + \param alpha2 - Country code passed by the hdd context. + + \param cc_src - Country code source passed by the hdd context. + + \return eHAL_STATUS_SUCCESS - SME is successfully initialized. + + Other status means SME is failed to be initialized + \sa + +---------------------------------------------------------------------------*/ +eHalStatus sme_init_chan_list(tHalHandle hal, v_U8_t *alpha2, + COUNTRY_CODE_SOURCE cc_src); + +/*-------------------------------------------------------------------------- + + \brief sme_Close() - Release all SME modules and their resources. + + The function release each module in SME, PMC, CCM, CSR, etc. . Upon + return, all modules are at closed state. + + No SME APIs can be involved after sme_Close except sme_Open. + sme_Close must be called before macClose. + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME is successfully close. + + Other status means SME is failed to be closed but caller still cannot + call any other SME functions except smeOpen. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Close(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + + \brief sme_Start() - Put all SME modules at ready state. + + The function starts each module in SME, PMC, CCM, CSR, etc. . Upon + successfully return, all modules are ready to run. + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME is ready. + + Other status means SME is failed to start. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Start(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + + \brief sme_Stop() - Stop all SME modules and put them at idle state + + The function stops each module in SME, PMC, CCM, CSR, etc. . Upon + return, all modules are at idle state ready to start. + + + \param hHal - The handle returned by macOpen. + + \param tHalStopType - reason for stopping + + \return eHAL_STATUS_SUCCESS - SME is stopped. + + Other status means SME is failed to stop but caller should still consider + SME is stopped. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Stop(tHalHandle hHal, tHalStopType stopType); + + +/*-------------------------------------------------------------------------- + + \brief sme_OpenSession() - Open a session for scan/roam operation. + + This is a synchronous API. + + + \param hHal - The handle returned by macOpen. + \param callback - A pointer to the function caller specifies for roam/connect status indication + \param pContext - The context passed with callback + \param pSelfMacAddr - Caller allocated memory filled with self MAC address (6 bytes) + \param pbSessionId - pointer to a caller allocated buffer for returned session ID + + \return eHAL_STATUS_SUCCESS - session is opened. sessionId returned. + + Other status means SME is failed to open the session. + eHAL_STATUS_RESOURCES - no more session available. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, + void *pContext, tANI_U8 *pSelfMacAddr, + tANI_U8 *pbSessionId, tANI_U32 type, + tANI_U32 subType); + +/*-------------------------------------------------------------------------- + + \brief sme_SetCurrDeviceMode() - Sets the current operating device mode. + \param hHal - The handle returned by macOpen. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ + +void sme_SetCurrDeviceMode (tHalHandle hHal, tVOS_CON_MODE currDeviceMode); + +/*-------------------------------------------------------------------------- + + \brief sme_CloseSession() - Open a session for scan/roam operation. + + This is a synchronous API. + + + \param hHal - The handle returned by macOpen. + + \param sessionId - A previous opened session's ID. + + \return eHAL_STATUS_SUCCESS - session is closed. + + Other status means SME is failed to open the session. + eHAL_STATUS_INVALID_PARAMETER - session is not opened. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_CloseSession(tHalHandle hHal, tANI_U8 sessionId, + csrRoamSessionCloseCallback callback, void *pContext); + +eHalStatus sme_update_roam_params(tHalHandle hHal, uint8_t session_id, + struct roam_ext_params roam_params_src, int update_param); + +/*-------------------------------------------------------------------------- + + \brief sme_UpdateConfig() - Change configurations for all SME modules + + The function updates some configuration for modules in SME, CCM, CSR, etc + during SMEs close -> open sequence. + + Modules inside SME apply the new configuration at the next transaction. + + + \param hHal - The handle returned by macOpen. + \Param pSmeConfigParams - a pointer to a caller allocated object of + typedef struct _smeConfigParams. + + \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully. + + Other status means SME is failed to update the config parameters. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateConfig(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams); + +#ifdef FEATURE_WLAN_SCAN_PNO +/*-------------------------------------------------------------------------- + + \brief sme_UpdateChannelConfig() - Update channel configuration in RIVA. + + It is used at driver start up to inform RIVA of the default channel + configuration. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME update the channel config successfully. + + Other status means SME is failed to update the channel config. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateChannelConfig(tHalHandle hHal); + +#endif // FEATURE_WLAN_SCAN_PNLO + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/*-------------------------------------------------------------------------- + + \brief sme_SetPlmRequest() - send PLM request to firmware + + It is used to initiate PLM request + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME could successfully sent PLM command + + Other status means SME is failed to send plm command + + --------------------------------------------------------------------------*/ +eHalStatus sme_SetPlmRequest(tHalHandle hHal, tpSirPlmReq pPlm); + +#endif + +/*-------------------------------------------------------------------------- + + \brief sme_set11dinfo() - Set the 11d information about valid channels + and there power using information from nvRAM + This function is called only for AP. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + \Param pSmeConfigParams - a pointer to a caller allocated object of + typedef struct _smeConfigParams. + + \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully. + + Other status means SME is failed to update the config parameters. + \sa +--------------------------------------------------------------------------*/ + +eHalStatus sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams); + +/*-------------------------------------------------------------------------- + + \brief sme_getSoftApDomain() - Get the current regulatory domain of softAp. + + This is a synchronous call + + \param hHal - The handle returned by HostapdAdapter. + \Param v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp. + + \return eHAL_STATUS_SUCCESS - SME successfully completed the request. + + Other status means, failed to get the current regulatory domain. + \sa +--------------------------------------------------------------------------*/ + +eHalStatus sme_getSoftApDomain(tHalHandle hHal, v_REGDOMAIN_t *domainIdSoftAp); + +eHalStatus sme_setRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode); + + +/* --------------------------------------------------------------------------- + \fn sme_ChangeConfigParams + \brief The SME API exposed for HDD to provide config params to SME during + SMEs stop -> start sequence. + + If HDD changed the domain that will cause a reset. This function will + provide the new set of 11d information for the new domain. Currrently this + API provides info regarding 11d only at reset but we can extend this for + other params (PMC, QoS) which needs to be initialized again at reset. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + + \Param + pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that + currently provides 11d related information like Country code, + Regulatory domain, valid channel list, Tx power per channel, a + list with active/passive scan allowed per valid channel. + + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ChangeConfigParams(tHalHandle hHal, + tCsrUpdateConfigParam *pUpdateConfigParam); + +/*-------------------------------------------------------------------------- + + \brief sme_HDDReadyInd() - SME sends eWNI_SME_SYS_READY_IND to PE to inform that the NIC + is ready tio run. + + The function is called by HDD at the end of initialization stage so PE/HAL can enable the NIC + to running state. + + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE successfully. + + Other status means SME failed to send the message to PE. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_HDDReadyInd(tHalHandle hHal); + + +/*-------------------------------------------------------------------------- + + \brief sme_ProcessMsg() - The main message processor for SME. + + The function is called by a message dispatcher when to process a message + targeted for SME. + + + \param hHal - The handle returned by macOpen. + \param pMsg - A pointer to a caller allocated object of tSirMsgQ. + + \return eHAL_STATUS_SUCCESS - SME successfully process the message. + + Other status means SME failed to process the message. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg); + +v_VOID_t sme_FreeMsg( tHalHandle hHal, vos_msg_t* pMsg ); + +/* --------------------------------------------------------------------------- + \fn sme_ScanRequest + \brief a wrapper function to Request a 11d or full scan from CSR. + \param pScanRequestID - pointer to an object to get back the request ID + \param callback - a callback function that scan calls upon finish, will not + be called if csrScanRequest returns error + \param pContext - a pointer passed in for the callback + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanRequest(tHalHandle hHal, tANI_U8 sessionId, tCsrScanRequest *, + tANI_U32 *pScanRequestID, + csrScanCompleteCallback callback, void *pContext); + + +/* --------------------------------------------------------------------------- + \fn sme_ScanSetBGScanparams + \brief a wrapper function to request CSR to set BG scan params in PE + \param pScanReq - BG scan request structure + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanSetBGScanparams(tHalHandle hHal, tANI_U8 sessionId, tCsrBGScanRequest *pScanReq); + + +/* --------------------------------------------------------------------------- + \fn sme_ScanGetResult + \brief a wrapper function to request scan results from CSR. + \param pFilter - If pFilter is NULL, all cached results are returned + \param phResult - an object for the result. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanGetResult(tHalHandle hHal, tANI_U8 sessionId, tCsrScanResultFilter *pFilter, + tScanResultHandle *phResult); + +VOS_STATUS sme_get_ap_channel_from_scan_cache(tHalHandle hHal, + tCsrRoamProfile *profile, + tScanResultHandle *scan_cache, + tANI_U8 *ap_chnl_id); +bool sme_store_joinreq_param(tHalHandle hal_handle, + tCsrRoamProfile *profile, + tScanResultHandle scan_cache, + uint32_t *roam_id, + uint32_t session_id); +bool sme_clear_joinreq_param(tHalHandle hal_handle, + uint32_t session_id); +VOS_STATUS sme_issue_stored_joinreq(tHalHandle hal_handle, + uint32_t *roam_id, + uint32_t session_id); + +/* --------------------------------------------------------------------------- + \fn sme_ScanFlushResult + \brief a wrapper function to request CSR to clear scan results. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanFlushResult(tHalHandle hHal, tANI_U8 sessionId); + +/* + * --------------------------------------------------------------------------- + * \fn sme_FilterScanResults + * \brief a wrapper function to request CSR to filter the scan results based + * on valid channel list. + * \param hHal - The handle returned by macOpen. + * \param sessionId - the sessionId returned by sme_OpenSession. + * \return eHalStatus + *--------------------------------------------------------------------------- + */ +eHalStatus sme_FilterScanResults(tHalHandle hHal, tANI_U8 sessionId); + +eHalStatus sme_ScanFlushP2PResult(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_ScanResultGetFirst + \brief a wrapper function to request CSR to returns the first element of + scan result. + \param hScanResult - returned from csrScanGetResult + \return tCsrScanResultInfo * - NULL if no result + ---------------------------------------------------------------------------*/ +tCsrScanResultInfo *sme_ScanResultGetFirst(tHalHandle, + tScanResultHandle hScanResult); + +/* --------------------------------------------------------------------------- + \fn sme_ScanResultGetNext + \brief a wrapper function to request CSR to returns the next element of + scan result. It can be called without calling csrScanResultGetFirst + first + \param hScanResult - returned from csrScanGetResult + \return Null if no result or reach the end + ---------------------------------------------------------------------------*/ +tCsrScanResultInfo *sme_ScanResultGetNext(tHalHandle, + tScanResultHandle hScanResult); + +/* --------------------------------------------------------------------------- + \fn sme_ScanResultPurge + \brief a wrapper function to request CSR to remove all items(tCsrScanResult) + in the list and free memory for each item + \param hScanResult - returned from csrScanGetResult. hScanResult is + considered gone by + calling this function and even before this function returns. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanResultPurge(tHalHandle hHal, tScanResultHandle hScanResult); + +/* --------------------------------------------------------------------------- + \fn sme_ScanGetPMKIDCandidateList + \brief a wrapper function to return the PMKID candidate list + \param pPmkidList - caller allocated buffer point to an array of + tPmkidCandidateInfo + \param pNumItems - pointer to a variable that has the number of + tPmkidCandidateInfo allocated when returning, this is + either the number needed or number of items put into + pPmkidList + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough and pNumItems + has the number of tPmkidCandidateInfo. + \Note: pNumItems is a number of tPmkidCandidateInfo, + not sizeof(tPmkidCandidateInfo) * something + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanGetPMKIDCandidateList(tHalHandle hHal, tANI_U8 sessionId, + tPmkidCandidateInfo *pPmkidList, + tANI_U32 *pNumItems ); + + +/*---------------------------------------------------------------------------- + \fn sme_RoamRegisterLinkQualityIndCallback + + \brief + a wrapper function to allow HDD to register a callback handler with CSR for + link quality indications. + + Only one callback may be registered at any time. + In order to deregister the callback, a NULL cback may be provided. + + Registration happens in the task context of the caller. + + \param callback - Call back being registered + \param pContext - user data + + DEPENDENCIES: After CSR open + + \return eHalStatus +-----------------------------------------------------------------------------*/ +eHalStatus sme_RoamRegisterLinkQualityIndCallback(tHalHandle hHal, tANI_U8 sessionId, + csrRoamLinkQualityIndCallback callback, + void *pContext); + + +/* --------------------------------------------------------------------------- + \fn sme_RoamConnect + \brief a wrapper function to request CSR to initiate an association + \param sessionId - the sessionId returned by sme_OpenSession. + \param pProfile - can be NULL to join to any open ones + \param pRoamId - to get back the request ID + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamConnect(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile, + tANI_U32 *pRoamId); + +/* --------------------------------------------------------------------------- + \fn sme_RoamReassoc + \brief a wrapper function to request CSR to initiate a re-association + \param pProfile - can be NULL to join the currently connected AP. In that + case modProfileFields should carry the modified field(s) which could trigger + reassoc + \param modProfileFields - fields which are part of tCsrRoamConnectedProfile + that might need modification dynamically once STA is up & running and this + could trigger a reassoc + \param pRoamId - to get back the request ID + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamReassoc(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + tANI_U32 *pRoamId, v_BOOL_t fForce); + +/* --------------------------------------------------------------------------- + \fn sme_RoamConnectToLastProfile + \brief a wrapper function to request CSR to disconnect and reconnect with + the same profile + \return eHalStatus. It returns fail if currently connected + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamConnectToLastProfile(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_RoamDisconnect + \brief a wrapper function to request CSR to disconnect from a network + \param reason -- To indicate the reason for disconnecting. Currently, only + eCSR_DISCONNECT_REASON_MIC_ERROR is meaningful. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamDisconnect(tHalHandle hHal, tANI_U8 sessionId, eCsrRoamDisconnectReason reason); + +/* --------------------------------------------------------------------------- + \fn sme_RoamStopBss + \brief a wrapper function to request CSR to stop bss + \param sessionId - sessionId of SoftAP + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamStopBss(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetAssociatedStas + \brief To probe the list of associated stations from various modules of CORE stack. + \This is an asynchronous API. + \param sessionId - sessionId of SoftAP + \param modId - Module from whom list of associated stations is to be + probed. + If an invalid module is passed then by default VOS_MODULE_ID_PE will be probed + \param pUsrContext - Opaque HDD context + \param pfnSapEventCallback - Sap event callback in HDD + \param pAssocBuf - Caller allocated memory to be filled with associated + stations info + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetAssociatedStas(tHalHandle hHal, tANI_U8 sessionId, + VOS_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf); + +/* --------------------------------------------------------------------------- + \fn sme_RoamDisconnectSta + \brief To disassociate a station. This is an asynchronous API. + \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes) + \return eHalStatus SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamDisconnectSta(tHalHandle hHal, tANI_U8 sessionId, + struct tagCsrDelStaParams *pDelStaParams); + +/* --------------------------------------------------------------------------- + \fn sme_RoamDeauthSta + \brief To disassociate a station. This is an asynchronous API. + \param hHal - Global structure + \param sessionId - sessionId of SoftAP + \param pDelStaParams- Pointer to parameters of the station to deauthenticate + \return eHalStatus SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamDeauthSta(tHalHandle hHal, tANI_U8 sessionId, + struct tagCsrDelStaParams *pDelStaParams); + +/* --------------------------------------------------------------------------- + \fn sme_RoamTKIPCounterMeasures + \brief To start or stop TKIP counter measures. This is an asynchronous API. + \param sessionId - sessionId of SoftAP + \param bEnable - Flag to start/stop TKIP countermeasures + \return eHalStatus SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamTKIPCounterMeasures(tHalHandle hHal, tANI_U8 sessionId, tANI_BOOLEAN bEnable); + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetWpsSessionOverlap + \brief To get the WPS PBC session overlap information. + \This is an asynchronous API. + \param sessionId - sessionId of SoftAP + \param pUsrContext - Opaque HDD context + \param pfnSapEventCallback - Sap event callback in HDD + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetWpsSessionOverlap(tHalHandle hHal, tANI_U8 sessionId, + void *pUsrContext, void *pfnSapEventCallback, + v_MACADDR_t pRemoveMac); + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetConnectState + \brief a wrapper function to request CSR to return the current connect state + of Roaming + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetConnectState(tHalHandle hHal, tANI_U8 sessionId, eCsrConnectState *pState); + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetConnectProfile + \brief a wrapper function to request CSR to return the current connect + profile. Caller must call csrRoamFreeConnectProfile after it is done + and before reuse for another csrRoamGetConnectProfile call. + \param pProfile - pointer to a caller allocated structure + tCsrRoamConnectedProfile + \return eHalStatus. Failure if not connected + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetConnectProfile(tHalHandle hHal, tANI_U8 sessionId, + tCsrRoamConnectedProfile *pProfile); + +/* --------------------------------------------------------------------------- + \fn sme_RoamFreeConnectProfile + \brief a wrapper function to request CSR to free and reinitialize the + profile returned previously by csrRoamGetConnectProfile. + \param pProfile - pointer to a caller allocated structure + tCsrRoamConnectedProfile + \return eHalStatus. + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamFreeConnectProfile(tHalHandle hHal, + tCsrRoamConnectedProfile *pProfile); + +/* --------------------------------------------------------------------------- + \fn sme_RoamSetPMKIDCache + \brief a wrapper function to request CSR to return the PMKID candidate list + \param pPMKIDCache - caller allocated buffer point to an array of + tPmkidCacheInfo + \param numItems - a variable that has the number of tPmkidCacheInfo + allocated when returning, this is either the number needed + or number of items put into pPMKIDCache + \param update_entire_cache - if TRUE, then it overwrites the entire cache + with pPMKIDCache, else it updates entry by + entry without deleting the old entries. + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough and pNumItems has the number of + tPmkidCacheInfo. + \Note: pNumItems is a number of tPmkidCacheInfo, + not sizeof(tPmkidCacheInfo) * something + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamSetPMKIDCache( tHalHandle hHal, tANI_U8 sessionId, + tPmkidCacheInfo *pPMKIDCache, + tANI_U32 numItems, + tANI_BOOLEAN update_entire_cache ); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* --------------------------------------------------------------------------- + * \fn sme_RoamSetPSK_PMK + * \brief a wrapper function to request CSR to save PSK/PMK + * This is a synchronous call. + * \param hHal - Global structure + * \param sessionId - SME sessionId + * \param pPSK_PMK - pointer to an array of Psk[]/Pmk[] + * \param pmk_len - Length could be only 16 bytes in case if LEAP + * connections. Need to pass this information to + * firmware. + *\return eHalStatus -status whether PSK/PMK is set or not + * ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamSetPSK_PMK (tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 *pPSK_PMK, size_t pmk_len); +#endif +/* --------------------------------------------------------------------------- + \fn sme_RoamGetSecurityReqIE + \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE CSR + passes to PE to JOIN request or START_BSS request + This is a synchronous call. + \param sessionId - returned by sme_OpenSession. + \param pLen - caller allocated memory that has the length of pBuf as input. + Upon returned, *pLen has the needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, + upon return + \param secType - Specifies whether looking for WPA/WPA2/WAPI IE + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetSecurityReqIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen, + tANI_U8 *pBuf, eCsrSecurityType secType); + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetSecurityRspIE + \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE from + the beacon or probe rsp if connected + \param sessionId - returned by sme_OpenSession. + \param pLen - caller allocated memory that has the length of pBuf as input. + Upon returned, *pLen has the needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, + upon return + \param secType - Specifies whether looking for WPA/WPA2/WAPI IE + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetSecurityRspIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen, + tANI_U8 *pBuf, eCsrSecurityType secType); + + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetNumPMKIDCache + \brief a wrapper function to request CSR to return number of PMKID cache + entries + \return tANI_U32 - the number of PMKID cache entries + ---------------------------------------------------------------------------*/ +tANI_U32 sme_RoamGetNumPMKIDCache(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetPMKIDCache + \brief a wrapper function to request CSR to return PMKID cache from CSR + \param pNum - caller allocated memory that has the space of the number of + pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the + needed or actually number in tPmkidCacheInfo. + \param pPmkidCache - Caller allocated memory that contains PMKID cache, if + any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetPMKIDCache(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pNum, + tPmkidCacheInfo *pPmkidCache); + +/* --------------------------------------------------------------------------- + \fn sme_GetConfigParam + \brief a wrapper function that HDD calls to get the global settings + currently maintained by CSR. + \param pParam - caller allocated memory + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetConfigParam(tHalHandle hHal, tSmeConfigParams *pParam); + +/* --------------------------------------------------------------------------- + \fn sme_GetStatistics + \brief a wrapper function that client calls to register a callback to get + different PHY level statistics from CSR. + + \param requesterId - different client requesting for statistics, HDD, UMA/GAN etc + \param statsMask - The different category/categories of stats requester is looking for + The order in which you set the bits in the statsMask for requesting + different type of stats is: + + eCsrSummaryStats = bit 0 + eCsrGlobalClassAStats = bit 1 + eCsrGlobalClassBStats = bit 2 + eCsrGlobalClassCStats = bit 3 + eCsrGlobalClassDStats = bit 4 + eCsrPerStaStats = bit 5 + + \param callback - SME sends back the requested stats using the callback + \param periodicity - If requester needs periodic update, 0 means it's an one + time request + \param cache - If requester is happy with cached stats + \param staId - The station ID for which the stats is requested for + \param pContext - user context to be passed back along with the callback + \param sessionId - sme session interface + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId, + tANI_U32 statsMask, + tCsrStatsCallback callback, + tANI_U32 periodicity, tANI_BOOLEAN cache, + tANI_U8 staId, void *pContext, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn smeGetTLSTAState + \helper function to get the TL STA State whenever the function is called. + + \param staId - The staID to be passed to the TL + to get the relevant TL STA State + \return the state as tANI_U16 + ---------------------------------------------------------------------------*/ +tANI_U16 smeGetTLSTAState(tHalHandle hHal, tANI_U8 staId); + +/* --------------------------------------------------------------------------- + \fn sme_GetRssi + \brief a wrapper function that client calls to register a callback to get + RSSI + + \param hHal - HAL handle for device + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param bssid - The bssid of the connected session + \param lastRSSI - RSSI value at time of request. In case fw cannot provide + RSSI, do not hold up but return this value. + \param pContext - user context to be passed back along with the callback + \param pVosContext - vos context + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetRssi(tHalHandle hHal, + tCsrRssiCallback callback, + tANI_U8 staId, tCsrBssid bssId, tANI_S8 lastRSSI, + void *pContext, void* pVosContext); + +/* --------------------------------------------------------------------------- + \fn sme_GetSnr + \brief a wrapper function that client calls to register a callback to get + SNR from FW + + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param bssid - The bssid of the connected session + \param pContext - user context to be passed back along with the callback + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetSnr(tHalHandle hHal, + tCsrSnrCallback callback, + tANI_U8 staId, tCsrBssid bssId, + void *pContext); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* --------------------------------------------------------------------------- + \fn sme_GetTsmStats + \brief a wrapper function that client calls to register a callback to get + TSM Stats + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param pContext - user context to be passed back along with the callback + \param pVosContext - vos context + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetTsmStats(tHalHandle hHal, + tCsrTsmStatsCallback callback, + tANI_U8 staId, tCsrBssid bssId, + void *pContext, void* pVosContext, tANI_U8 tid); +/* --------------------------------------------------------------------------- + \fn sme_SetCCKMIe + \brief function to store the CCKM IE passed from supplicant and use it + while packing reassociation request + \param hHal - HAL handle for device + \param pCckmIe - pointer to CCKM IE data + \param pCckmIeLen - length of the CCKM IE + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_SetCCKMIe(tHalHandle hHal, + tANI_U8 sessionId, + tANI_U8 *pCckmIe, + tANI_U8 cckmIeLen); +/* --------------------------------------------------------------------------- + \fn sme_SetEseBeaconRequest + \brief function to set ESE beacon request parameters + \param hHal - HAL handle for device + \param pEseBcnReq - pointer to ESE beacon request + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_SetEseBeaconRequest(tHalHandle hHal, const tANI_U8 sessionId, + const tCsrEseBeaconReq* pEseBcnReq); + +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/* --------------------------------------------------------------------------- + \fn sme_CfgSetInt + \brief a wrapper function that HDD calls to set parameters in CFG. + \param cfgId - Configuration Parameter ID (type) for STA. + \param ccmValue - The information related to Configuration Parameter ID + which needs to be saved in CFG + \param callback - To be registered by CSR with CCM. Once the CFG done with + saving the information in the database, it notifies CCM & + then the callback will be invoked to notify. + \param toBeSaved - To save the request for future reference + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_CfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue, + tCcmCfgSetCallback callback, eAniBoolean toBeSaved) ; + +/* --------------------------------------------------------------------------- + \fn sme_CfgSetStr + \brief a wrapper function that HDD calls to set parameters in CFG. + \param cfgId - Configuration Parameter ID (type) for STA. + \param pStr - Pointer to the byte array which carries the information needs + to be saved in CFG + \param length - Length of the data to be saved + \param callback - To be registered by CSR with CCM. Once the CFG done with + saving the information in the database, it notifies CCM & + then the callback will be invoked to notify. + \param toBeSaved - To save the request for future reference + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_CfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr, + tANI_U32 length, tCcmCfgSetCallback callback, + eAniBoolean toBeSaved) ; + + +/* --------------------------------------------------------------------------- + \fn sme_GetModifyProfileFields + \brief HDD or SME - QOS calls this function to get the current values of + connected profile fields, changing which can cause reassoc. + This function must be called after CFG is downloaded and STA is in connected + state. Also, make sure to call this function to get the current profile + fields before calling the reassoc. So that pModifyProfileFields will have + all the latest values plus the one(s) has been updated as part of reassoc + request. + \param pModifyProfileFields - pointer to the connected profile fields + changing which can cause reassoc + + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetModifyProfileFields(tHalHandle hHal, tANI_U8 sessionId, + tCsrRoamModifyProfileFields * pModifyProfileFields); + + +/*-------------------------------------------------------------------------- + \fn sme_SetConfigPowerSave + \brief Wrapper fn to change power save configuration in SME (PMC) module. + For BMPS related configuration, this function also updates the CFG + and sends a message to FW to pick up the new values. Note: Calling + this function only updates the configuration and does not enable + the specified power save mode. + \param hHal - The handle returned by macOpen. + \param psMode - Power Saving mode being modified + \param pConfigParams - a pointer to a caller allocated object of type + tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams + \return eHalStatus + --------------------------------------------------------------------------*/ +eHalStatus sme_SetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode, + void *pConfigParams); + +/*-------------------------------------------------------------------------- + \fn sme_GetConfigPowerSave + \brief Wrapper fn to retrieve power save configuration in SME (PMC) module + \param hHal - The handle returned by macOpen. + \param psMode - Power Saving mode + \param pConfigParams - a pointer to a caller allocated object of type + tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams + \return eHalStatus + --------------------------------------------------------------------------*/ +eHalStatus sme_GetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode, + void *pConfigParams); + +/* --------------------------------------------------------------------------- + \fn sme_EnablePowerSave + \brief Enables one of the power saving modes. This API does not cause a + device state change. This is purely a configuration API. + \param hHal - The handle returned by macOpen. + \param psMode - The power saving mode to enable. + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_EnablePowerSave ( + tHalHandle hHal, + tPmcPowerSavingMode psMode); + +/* --------------------------------------------------------------------------- + \fn sme_DisablePowerSave + \brief Disables one of the power saving modes.Disabling does not imply + that device will be brought out of the current PS mode. This is + purely a configuration API. + \param hHal - The handle returned by macOpen. + \param psMode - The power saving mode to disable. + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_DisablePowerSave ( + tHalHandle hHal, + tPmcPowerSavingMode psMode); + + /* --------------------------------------------------------------------------- + \fn sme_SetHostPowerSave + \brief The BMPS logic is controlled by the User level Apps + \param hHal - The handle returned by macOpen. + \param psMode - The power saving mode to enable. + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_SetHostPowerSave ( + tHalHandle hHal, + v_BOOL_t psMode); + +/* --------------------------------------------------------------------------- + \fn sme_StartAutoBmpsTimer + \brief Starts a timer that periodically polls all the registered + module for entry into Bmps mode. This timer is started only if BMPS is + enabled and whenever the device is in full power. + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_StartAutoBmpsTimer ( tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_StopAutoBmpsTimer + \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer + Stopping the timer does not cause a device state change. Only the timer + is stopped. If "Full Power" is desired, use the sme_RequestFullPower API + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_StopAutoBmpsTimer ( tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_QueryPowerState + \brief Returns the current power state of the device. + \param hHal - The handle returned by macOpen. + \param pPowerState - pointer to location to return power state + \param pSwWlanSwitchState - ptr to location to return SW WLAN Switch state + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_QueryPowerState ( + tHalHandle hHal, + tPmcPowerState *pPowerState, + tPmcSwitchState *pSwWlanSwitchState); + +/* --------------------------------------------------------------------------- + \fn sme_IsPowerSaveEnabled + \brief Checks if the device is able to enter a particular power save mode + This does not imply that the device is in a particular PS mode + \param hHal - The handle returned by macOpen. + \param sessionId - sme sessionid + \param psMode - the power saving mode + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern tANI_BOOLEAN sme_IsPowerSaveEnabled ( + tHalHandle hHal, + tANI_U32 sessionId, + tPmcPowerSavingMode psMode); + +/* --------------------------------------------------------------------------- + \fn sme_RequestFullPower + \brief Request that the device be brought to full power state. + Note 1: If "fullPowerReason" specified in this API is set to + eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" requests + and also clear any "buffered BMPS requests by HDD". Assumption is that since + HDD is requesting full power, we need to undo any previous HDD requests for + BMPS (using sme_RequestBmps) or WoWL (using sme_EnterWoWL). If the reason is + specified anything other than above, the buffered requests for BMPS and WoWL + will not be cleared. + Note 2: Requesting full power (no matter what the fullPowerReason is) doesn't + disable the "auto bmps timer" (if it is enabled) or clear any "buffered uapsd + request". + Note 3: When the device finally enters Full Power PMC will start a timer + if any of the following holds true: + - Auto BMPS mode is enabled + - Uapsd request is pending + - HDD's request for BMPS is pending + - HDD's request for WoWL is pending + On timer expiry PMC will attempt to put the device in BMPS mode if following + (in addition to those listed above) holds true: + - Polling of all modules through the Power Save Check routine passes + - STA is associated to an access point + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \param - callbackContext - Cookie to be passed back during callback + \param - fullPowerReason - Reason why this API is being invoked. SME needs to + distinguish between BAP and HDD requests + \return eHalStatus - status + eHAL_STATUS_SUCCESS - device brought to full power state + eHAL_STATUS_FAILURE - device cannot be brought to full power state + eHAL_STATUS_PMC_PENDING - device is being brought to full power state, + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_RequestFullPower ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext, + tRequestFullPowerReason fullPowerReason); + +/* --------------------------------------------------------------------------- + \fn sme_RequestBmps + \brief Request that the device be put in BMPS state. Request will be + accepted only if BMPS mode is enabled and power save check routine + passes. Only HDD should invoke this API. + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \param - callbackContext - Cookie to be passed back during callback + \return eHalStatus + eHAL_STATUS_SUCCESS - device is in BMPS state + eHAL_STATUS_FAILURE - device cannot be brought to BMPS state + eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_RequestBmps ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext); + +/* --------------------------------------------------------------------------- + \fn sme_SetDHCPTillPowerActiveFlag + \brief Sets/Clears DHCP related flag in PMC to disable/enable auto BMPS + entry by PMC + \param hHal - The handle returned by macOpen. + ---------------------------------------------------------------------------*/ +void sme_SetDHCPTillPowerActiveFlag(tHalHandle hHal, tANI_U8 flag); + + +/* --------------------------------------------------------------------------- + \fn sme_StartUapsd + \brief Request that the device be put in UAPSD state. If the device is in + Full Power it will be put in BMPS mode first and then into UAPSD + mode. + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \param - callbackContext - Cookie to be passed back during callback + eHAL_STATUS_SUCCESS - device is in UAPSD state + eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state + eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state + eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_StartUapsd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext); + +/* --------------------------------------------------------------------------- + \fn sme_StopUapsd + \brief Request that the device be put out of UAPSD state. Device will be + put in in BMPS state after stop UAPSD completes. Buffered requests for + UAPSD will be cleared after this. + \param hHal - The handle returned by macOpen. + \return eHalStatus + eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state + eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_StopUapsd (tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_RequestStandby + \brief Request that the device be put in standby. It is HDD's responsibility + to bring the chip to full power and do a disconnect before calling + this API. Request for standby will be rejected if STA is associated + to an AP. + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \param - callbackContext - Cookie to be passed back during callback + \return eHalStatus + eHAL_STATUS_SUCCESS - device is in Standby mode + eHAL_STATUS_FAILURE - device cannot be put in standby mode + eHAL_STATUS_PMC_PENDING - device is being put in standby mode + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_RequestStandby ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext); + +/* --------------------------------------------------------------------------- + \fn sme_RegisterPowerSaveCheck + \brief Register a power save check routine that is called whenever + the device is about to enter one of the power save modes. + \param hHal - The handle returned by macOpen. + \param checkRoutine - Power save check routine to be registered + \param callbackContext - Cookie to be passed back during callback + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully registered + eHAL_STATUS_FAILURE - not successfully registered + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_RegisterPowerSaveCheck ( + tHalHandle hHal, + tANI_BOOLEAN (*checkRoutine) (void *checkContext), void *checkContext); + +/* --------------------------------------------------------------------------- + \fn sme_Register11dScanDoneCallback + \brief Register a routine of type csrScanCompleteCallback which is + called whenever an 11d scan is done + \param hHal - The handle returned by macOpen. + \param callback - 11d scan complete routine to be registered + \return eHalStatus + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_Register11dScanDoneCallback ( + tHalHandle hHal, + csrScanCompleteCallback); + +/* --------------------------------------------------------------------------- + \fn sme_DeregisterPowerSaveCheck + \brief Deregister a power save check routine + \param hHal - The handle returned by macOpen. + \param checkRoutine - Power save check routine to be deregistered + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_DeregisterPowerSaveCheck ( + tHalHandle hHal, + tANI_BOOLEAN (*checkRoutine) (void *checkContext)); + +/* --------------------------------------------------------------------------- + \fn sme_RegisterDeviceStateUpdateInd + \brief Register a callback routine that is called whenever + the device enters a new device state (Full Power, BMPS, UAPSD) + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine to be registered + \param callbackContext - Cookie to be passed back during callback + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully registered + eHAL_STATUS_FAILURE - not successfully registered + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_RegisterDeviceStateUpdateInd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState), + void *callbackContext); + +/* --------------------------------------------------------------------------- + \fn sme_DeregisterDeviceStateUpdateInd + \brief Deregister a routine that was registered for device state changes + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine to be deregistered + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_DeregisterDeviceStateUpdateInd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState)); + +/* --------------------------------------------------------------------------- + \fn sme_WowlAddBcastPattern + \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will + do a pattern match on these patterns when Wowl is enabled during BMPS + mode. + \param hHal - The handle returned by macOpen. + \param pattern - Pattern to be added + \return eHalStatus + eHAL_STATUS_FAILURE Cannot add pattern + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_WowlAddBcastPattern ( + tHalHandle hHal, + tpSirWowlAddBcastPtrn pattern, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_WowlDelBcastPattern + \brief Delete a pattern that was added for Pattern Byte Matching. + \param hHal - The handle returned by macOpen. + \param pattern - Pattern to be deleted + \return eHalStatus + eHAL_STATUS_FAILURE Cannot delete pattern + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_WowlDelBcastPattern ( + tHalHandle hHal, + tpSirWowlDelBcastPtrn pattern, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_EnterWowl + \brief This is the API to request entry into WOWL mode. + WoWLAN works on top of BMPS mode. If the device is not in BMPS mode, + SME will will cache the information that WOWL has been requested and + attempt to put the device in BMPS first. On entry into BMPS, SME will + enter the WOWL mode. + Note 1: After WoWL request is accepted, If module other than HDD requests + full power BEFORE WoWL request is completed, PMC will buffer the WoWL request + and attempt to put the chip into BMPS+WOWL based on a timer. + Note 2: Buffered request for WoWL will be cleared immediately AFTER + "enter Wowl" completes or if HDD requests full power or + if sme_ExitWoWL API is invoked. + Note 3: Both UAPSD and WOWL work on top of BMPS. On entry into BMPS, SME + will give priority to UAPSD and enable only UAPSD if both UAPSD and WOWL + are required. Currently there is no requirement or use case to support UAPSD + and WOWL at the same time. + Note 4. Request for WoWL is rejected if there is a pending UAPSD request. + Note 5. Request for WoWL is rejected if BMPS is disabled. + + \param hHal - The handle returned by macOpen. + \param enterWowlCallbackRoutine - Callback routine provided by HDD. + Used for success/failure notification by SME + \param enterWowlCallbackContext - A cookie passed by HDD, that is passed back to HDD + at the time of callback. + \param wakeReasonIndCB - Callback routine provided by HDD. + Used for Wake Reason Indication by SME + \param wakeReasonIndCBContext - A cookie passed by HDD, that is passed back to HDD + at the time of callback. + \return eHalStatus + eHAL_STATUS_SUCCESS Device is already in WoWLAN mode + eHAL_STATUS_FAILURE Device cannot enter WoWLAN mode. + eHAL_STATUS_PMC_PENDING Request accepted. SME will enable WOWL when BMPS + mode is entered. + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_EnterWowl ( + tHalHandle hHal, + void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status), + void *enterWowlCallbackContext, +#ifdef WLAN_WAKEUP_EVENTS + void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd), + void *wakeReasonIndCBContext, +#endif // WLAN_WAKEUP_EVENTS + tpSirSmeWowlEnterParams wowlEnterParams, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_ExitWowl + \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. + SME will initiate exit from WoWLAN mode and device will be put in BMPS + mode. Any Buffered request for WoWL will be cleared after this API. + \param hHal - The handle returned by macOpen. + \param wowlExitParams - Carries info on which smesession wowl exit + is requested. + \return eHalStatus + eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode. This can happen + only if the previous "Enter WOWL" transaction has + not even completed. + eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. + ---------------------------------------------------------------------------*/ +extern eHalStatus sme_ExitWowl (tHalHandle hHal, tpSirSmeWowlExitParams wowlExitParams); + +/* --------------------------------------------------------------------------- + + \fn sme_RoamSetKey + + \brief To set encryption key. This function should be called only when connected + This is an asynchronous API. + + \param pSetKeyInfo - pointer to a caller allocated object of tCsrSetContextInfo + + \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback + + \return eHalStatus SUCCESS Roam callback will be called indicate actually results + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamSetKey(tHalHandle, tANI_U8 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 *pRoamId); + +/* --------------------------------------------------------------------------- + + \fn sme_RoamRemoveKey + + \brief To set encryption key. This is an asynchronous API. + + \param pRemoveKey - pointer to a caller allocated object of tCsrRoamRemoveKey + + \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback + + \return eHalStatus SUCCESS Roam callback will be called indicate actually results + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamRemoveKey(tHalHandle, tANI_U8 sessionId, tCsrRoamRemoveKey *pRemoveKey, tANI_U32 *pRoamId); + + +/* --------------------------------------------------------------------------- + + \fn sme_GetCountryCode + + \brief To return the current country code. If no country code is applied, default country code is + used to fill the buffer. + If 11d supported is turned off, an error is return and the last applied/default country code is used. + This is a synchronous API. + + \param pBuf - pointer to a caller allocated buffer for returned country code. + + \param pbLen For input, this parameter indicates how big is the buffer. + Upon return, this parameter has the number of bytes for country. If pBuf + doesn't have enough space, this function returns + fail status and this parameter contains the number that is needed. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U8 *pbLen); + +/* --------------------------------------------------------------------------- + + \fn sme_SetCountryCode + + \brief To change the current/default country code. + If 11d supported is turned off, an error is return. + This is a synchronous API. + + \param pCountry - pointer to a caller allocated buffer for the country code. + + \param pfRestartNeeded A pointer to caller allocated memory, upon successful return, it indicates + whether a reset is required. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetCountryCode(tHalHandle hHal, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded); + +/* --------------------------------------------------------------------------- + \fn sme_ResetCountryCodeInformation + \brief this function is to reset the country code current being used back to EEPROM default + this includes channel list and power setting. This is a synchronous API. + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_ResetCountryCodeInformation(tHalHandle hHal, tANI_BOOLEAN *pfRestartNeeded); + +/* --------------------------------------------------------------------------- + \fn sme_GetSupportedCountryCode + \brief this function is to get a list of the country code current being supported + \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return, + this has the country code list. 3 bytes for each country code. This may be NULL if + caller wants to know the needed byte count. + \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return, + this contains the length of the data in pBuf. If pbuf is NULL, as input, *pbLen should be 0. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetSupportedCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U32 *pbLen); + +/* --------------------------------------------------------------------------- + \fn sme_GetCurrentRegulatoryDomain + \brief this function is to get the current regulatory domain. This is a synchronous API. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + SME. The function fails if 11d support is turned off. + \param pDomain - Caller allocated buffer to return the current domain. + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetCurrentRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t *pDomain); + +/* --------------------------------------------------------------------------- + \fn sme_SetRegulatoryDomain + \brief this function is to set the current regulatory domain. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + SME. This is a synchronous API. + \param domainId - indicate the domain (defined in the driver) needs to set to. + See v_REGDOMAIN_t for definition + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded); + +/* --------------------------------------------------------------------------- + + \fn sme_GetRegulatoryDomainForCountry + + \brief To return a regulatory domain base on a country code. This is a synchronous API. + + \param pCountry - pointer to a caller allocated buffer for input country code. + + \param pDomainId Upon successful return, it is the domain that country belongs to. + If it is NULL, returning success means that the country code is known. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetRegulatoryDomainForCountry(tHalHandle hHal, tANI_U8 *pCountry, v_REGDOMAIN_t *pDomainId); + + + +/* --------------------------------------------------------------------------- + + \fn sme_GetSupportedRegulatoryDomains + + \brief To return a list of supported regulatory domains. This is a synchronous API. + + \param pDomains - pointer to a caller allocated buffer for returned regulatory domains. + + \param pNumDomains For input, this parameter indicates how many domains + pDomains can hold. Upon return, this parameter has the + number for supported domains. If pDomains doesn't have + enough space for all the supported domains, this + function returns fail status and this parameter + contains the number that is needed. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetSupportedRegulatoryDomains(tHalHandle hHal, v_REGDOMAIN_t *pDomains, tANI_U32 *pNumDomains); + +//some support functions +tANI_BOOLEAN sme_Is11dSupported(tHalHandle hHal); +tANI_BOOLEAN sme_Is11hSupported(tHalHandle hHal); +tANI_BOOLEAN sme_IsWmmSupported(tHalHandle hHal); +//Upper layer to get the list of the base channels to scan for passively 11d info from csr +eHalStatus sme_ScanGetBaseChannels( tHalHandle hHal, tCsrChannelInfo * pChannelInfo ); + +typedef void ( *tSmeChangeCountryCallback)(void *pContext); +/* --------------------------------------------------------------------------- + + \fn sme_ChangeCountryCode + + \brief Change Country code from upper layer during WLAN driver operation. + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + + \param pCountry New Country Code String + + \param sendRegHint If we want to send reg hint to nl80211 + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_ChangeCountryCode( tHalHandle hHal, + tSmeChangeCountryCallback callback, + tANI_U8 *pCountry, + void *pContext, + void* pVosContext, + tAniBool countryFromUserSpace, + tAniBool sendRegHint); + +/* --------------------------------------------------------------------------- + + \fn sme_GenericChangeCountryCode + + \brief Generic API to change country code + + \param hHal - The handle returned by macOpen. + + \param pCountry New Country Code String + + \param reg_domain Regulatory domain for the new country code + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GenericChangeCountryCode( tHalHandle hHal, + tANI_U8 *pCountry, + v_REGDOMAIN_t reg_domain); + +/* --------------------------------------------------------------------------- + + \fn sme_DHCPStartInd + + \brief Indicate FW about DHCP start event. + + \param hHal - The handle returned by macOpen. + + \param device_mode the mode of the device + + \param macAddr the MAC address of the adapter + + \param sessionId session ID + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ + +eHalStatus sme_DHCPStartInd( tHalHandle hHal, + tANI_U8 device_mode, + tANI_U8 *macAddr, + tANI_U8 sessionId ); + +/* --------------------------------------------------------------------------- + + \fn sme_DHCPStopInd + + \brief Indicate FW about DHCP stop event. + + \param hHal - The handle returned by macOpen. + + \param device_mode the mode of the device + + \param macAddr the MAC address of the adapter + + \param sessionId session ID + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_DHCPStopInd( tHalHandle hHal, + tANI_U8 device_mode, + tANI_U8 *macAddr, + tANI_U8 sessionId ); + +/* --------------------------------------------------------------------------- + \fn sme_BtcSignalBtEvent + \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the + BT event type and the current operating mode of Libra (full power, + BMPS, UAPSD etc), appropriate Bluetooth Coexistence (BTC) strategy + would be employed. + \param hHal - The handle returned by macOpen. + \param pBtcBtEvent - Pointer to a caller allocated object of type tSmeBtEvent + Caller owns the memory and is responsible for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE BT Event not passed to HAL. This can happen + if driver has not yet been initialized or if BTC + Events Layer has been disabled. + VOS_STATUS_SUCCESS BT Event passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_BtcSignalBtEvent (tHalHandle hHal, tpSmeBtEvent pBtcBtEvent); + +/* --------------------------------------------------------------------------- + \fn sme_BtcSetConfig + \brief API to change the current Bluetooth Coexistence (BTC) configuration + This function should be invoked only after CFG download has completed. + Calling it after sme_HDDReadyInd is recommended. + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtcConfig. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE Config not passed to HAL. + VOS_STATUS_SUCCESS Config passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_BtcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig); + +/* --------------------------------------------------------------------------- + \fn sme_BtcGetConfig + \brief API to retrieve the current Bluetooth Coexistence (BTC) configuration + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type tSmeBtcConfig. + Caller owns the memory and is responsible for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_BtcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig); + +/* --------------------------------------------------------------------------- + \fn sme_SetCfgPrivacy + \brief API to set configure privacy parameters + \param hHal - The handle returned by macOpen. + \param pProfile - Pointer CSR Roam profile. + \param fPrivacy - This parameter indicates status of privacy + + \return void + ---------------------------------------------------------------------------*/ +void sme_SetCfgPrivacy(tHalHandle hHal, tCsrRoamProfile *pProfile, tANI_BOOLEAN fPrivacy); + +/* --------------------------------------------------------------------------- + \fn sme_getRecoveryStats + \brief API to get recovery stats for SME stuck cmds. + \param hHal - The handle returned by macOpen. + + \return void + ---------------------------------------------------------------------------*/ +void sme_getRecoveryStats(tHalHandle hHal); + +#if defined WLAN_FEATURE_VOWIFI +/* --------------------------------------------------------------------------- + \fn sme_NeighborReportRequest + \brief API to request neighbor report. + \param hHal - The handle returned by macOpen. + \param pRrmNeighborReq - Pointer to a caller allocated object of type + tRrmNeighborReq. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_NeighborReportRequest (tHalHandle hHal, tANI_U8 sessionId, + tpRrmNeighborReq pRrmNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo); +#endif + +VOS_STATUS sme_GetWcnssWlanCompiledVersion(tHalHandle hHal, + tSirVersionType *pVersion); +VOS_STATUS sme_GetWcnssWlanReportedVersion(tHalHandle hHal, + tSirVersionType *pVersion); +VOS_STATUS sme_GetWcnssSoftwareVersion(tHalHandle hHal, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize); +VOS_STATUS sme_GetWcnssHardwareVersion(tHalHandle hHal, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize); + +#ifdef FEATURE_WLAN_WAPI +/* --------------------------------------------------------------------------- + \fn sme_ScanGetBKIDCandidateList + \brief a wrapper function to return the BKID candidate list + \param pBkidList - caller allocated buffer point to an array of + tBkidCandidateInfo + \param pNumItems - pointer to a variable that has the number of + tBkidCandidateInfo allocated when returning, this is + either the number needed or number of items put into + pPmkidList + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough and pNumItems + has the number of tBkidCandidateInfo. + \Note: pNumItems is a number of tBkidCandidateInfo, + not sizeof(tBkidCandidateInfo) * something + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanGetBKIDCandidateList(tHalHandle hHal, tANI_U32 sessionId, + tBkidCandidateInfo *pBkidList, + tANI_U32 *pNumItems ); +#endif /* FEATURE_WLAN_WAPI */ + +#ifdef FEATURE_OEM_DATA_SUPPORT +/******************************************************************************************** + Oem data related modifications +*********************************************************************************************/ +/* --------------------------------------------------------------------------- + \fn sme_OemDataReq + \param sessionId - session id of session to be used for oem data req. + \param pOemDataReqID - pointer to an object to get back the request ID + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_OemDataReq(tHalHandle hHal, + tANI_U8 sessionId, + tOemDataReqConfig *, + tANI_U32 *pOemDataReqID); + +#endif /*FEATURE_OEM_DATA_SUPPORT*/ + + + +/* --------------------------------------------------------------------------- + + \fn sme_RoamUpdateAPWPSIE + + \brief To update AP's WPS IE. This function should be called after SME AP session is created + This is an asynchronous API. + + \param pAPWPSIES - pointer to a caller allocated object of tCsrRoamAPWPSIES + + \return eHalStatus SUCCESS Roam callback will be called indicate actually results + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ + +eHalStatus sme_RoamUpdateAPWPSIE(tHalHandle, tANI_U8 sessionId, tSirAPWPSIEs *pAPWPSIES); +/* --------------------------------------------------------------------------- + + \fn sme_RoamUpdateAPWPARSNIEs + + \brief To update AP's WPA/RSN IEs. This function should be called after SME AP session is created + This is an asynchronous API. + + \param pAPSirRSNie - pointer to a caller allocated object of tSirRSNie with WPS/RSN IEs + + \return eHalStatus SUCCESS + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamUpdateAPWPARSNIEs(tHalHandle hHal, tANI_U8 sessionId, tSirRSNie * pAPSirRSNie); + +/* --------------------------------------------------------------------------- + + sme_ChangeMCCBeaconInterval + + \brief To update P2P-GO's beacon Interval. + + \return eHalStatus SUCCESS + FAILURE or RESOURCES + The API finished and failed. + -------------------------------------------------------------------------------*/ +eHalStatus sme_ChangeMCCBeaconInterval(tHalHandle hHal, tANI_U8 sessionId); + + +/* --------------------------------------------------------------------------- + \fn sme_SetHostOffload + \brief API to set the host offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetHostOffload (tHalHandle hHal, tANI_U8 sessionId, + tpSirHostOffloadReq pRequest); + +/* --------------------------------------------------------------------------- + \fn sme_SetKeepAlive + \brief API to set the Keep Alive feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the Keep Alive request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetKeepAlive (tHalHandle hHal, tANI_U8 sessionId, + tpSirKeepAliveReq pRequest); + +/* ---------------------------------------------------------------------------- + \fn sme_GetOperationChannel + \brief API to get current channel on which STA is parked + this function gives channel information only of infra station or IBSS station. + \param hHal, pointer to memory location and sessionId + \returns eHAL_STATUS_SUCCESS + eHAL_STATUS_FAILURE +-------------------------------------------------------------------------------*/ +eHalStatus sme_GetOperationChannel(tHalHandle hHal, tANI_U32 *pChannel, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + + \fn sme_RegisterMgtFrame + + \brief To register management frame of specified type and subtype. + \param frameType - type of the frame that needs to be passed to HDD. + \param matchData - data which needs to be matched before passing frame + to HDD. + \param matchDataLen - Length of matched data. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RegisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId, + tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen); + +/* --------------------------------------------------------------------------- + + \fn sme_DeregisterMgtFrame + + \brief To De-register management frame of specified type and subtype. + \param frameType - type of the frame that needs to be passed to HDD. + \param matchData - data which needs to be matched before passing frame + to HDD. + \param matchDataLen - Length of matched data. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_DeregisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId, + tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen); + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureRxpFilter + + \brief + SME will pass this request to lower mac to set/reset the filter on RXP for + multicast & broadcast traffic. + + \param + + hHal - The handle returned by macOpen. + + filterMask- Currently the API takes a 1 or 0 (set or reset) as filter. + Basically to enable/disable the filter (to filter "all" mcbc traffic) based + on this param. In future we can use this as a mask to set various types of + filters as suggested below: + FILTER_ALL_MULTICAST: + FILTER_ALL_BROADCAST: + FILTER_ALL_MULTICAST_BROADCAST: + + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureRxpFilter( tHalHandle hHal, + tpSirWlanSetRxpFilters wlanRxpFilterParam); + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureAppsCpuWakeupState + + \brief + SME will pass this request to lower mac to dynamically adjusts the listen + interval based on the WLAN/MSM activity. This feature is named as + Telescopic Beacon wakeup feature. + + \param + + hHal - The handle returned by macOpen. + + isAppsAwake- Depicts the state of the Apps CPU + + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureAppsCpuWakeupState( tHalHandle hHal, tANI_BOOLEAN isAppsAwake); + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureSuspendInd + + \brief + SME will pass this request to lower mac to Indicate that the wlan needs to + be suspended + + \param + + hHal - The handle returned by macOpen. + + wlanSuspendParam- Depicts the wlan suspend params + + csrReadyToSuspendCallback - Callback to be called when ready to suspend + event is received. + callbackContext - Context associated with csrReadyToSuspendCallback. + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureSuspendInd( tHalHandle hHal, + tpSirWlanSuspendParam wlanSuspendParam, + csrReadyToSuspendCallback, + void *callbackContext); + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureResumeReq + + \brief + SME will pass this request to lower mac to Indicate that the wlan needs to + be Resumed + + \param + + hHal - The handle returned by macOpen. + + wlanResumeParam- Depicts the wlan resume params + + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureResumeReq( tHalHandle hHal, + tpSirWlanResumeParam wlanResumeParam); + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureExtWoW + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by macOpen. + + wlanExtParams- Depicts the wlan Ext params + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureExtWoW( tHalHandle hHal, + tpSirExtWoWParams wlanExtParams, + csrReadyToSuspendCallback callback, + void *callbackContext); + + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureAppType1Params + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by macOpen. + + wlanAppType1Params- Depicts the wlan Indoor params + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureAppType1Params( tHalHandle hHal, + tpSirAppType1Params wlanAppType1Params); + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureAppType2Params + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by macOpen. + + wlanAppType2Params- Depicts the wlan Indoor params + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureAppType2Params( tHalHandle hHal, + tpSirAppType2Params wlanAppType2Params); +#endif + +/* --------------------------------------------------------------------------- + + \fn sme_GetInfraSessionId + + \brief To get the session ID for infra session, if connected + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + + \return sessionid, -1 if infra session is not connected + + -------------------------------------------------------------------------------*/ +tANI_S8 sme_GetInfraSessionId(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + + \fn sme_GetInfraOperationChannel + + \brief To get the operating channel for infra session, if connected + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + \param sessionId - the sessionId returned by sme_OpenSession. + + \return operating channel, 0 if infra session is not connected + + -------------------------------------------------------------------------------*/ +tANI_U8 sme_GetInfraOperationChannel( tHalHandle hHal, tANI_U8 sessionId); +/* --------------------------------------------------------------------------- + + \fn sme_GetConcurrentOperationChannel + + \brief To get the operating channel for other concurrent sessions, if connected + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + \param currentPersona - persona that is trying to come up. + + \return operating channel, 0 if infra session is not connected + + -------------------------------------------------------------------------------*/ +tANI_U8 sme_GetConcurrentOperationChannel( tHalHandle hHal ); + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +v_U16_t sme_CheckConcurrentChannelOverlap( tHalHandle hHal, v_U16_t sap_ch, + eCsrPhyMode sapPhyMode, v_U8_t cc_switch_mode); +#endif +/* --------------------------------------------------------------------------- + \fn sme_AbortMacScan + \brief API to cancel MAC scan. + \param hHal - The handle returned by macOpen. + \param sessionId - sessionId for interface + \param reason - Reason to abort the scan + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +eHalStatus sme_AbortMacScan(tHalHandle hHal, tANI_U8 sessionId, + eCsrAbortReason reason); + +/* --------------------------------------------------------------------------- + \fn sme_GetCfgValidChannels + \brief API to get valid channel list + \param hHal - The handle returned by macOpen. + \param aValidChannels - Pointer to the valid channel list + \param len - valid channel list length + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetCfgValidChannels(tHalHandle hHal, tANI_U8 *aValidChannels, tANI_U32 *len); + +#ifdef FEATURE_WLAN_SCAN_PNO + +/* --------------------------------------------------------------------------- + \fn sme_SetPreferredNetworkList + \brief API to set the Preferred Network List Offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetPreferredNetworkList (tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext ); + +/****************************************************************************** +* +* Name: sme_PreferredNetworkFoundInd +* +* Description: +* Invoke Preferred Network Found Indication +* +* Parameters: +* hHal - HAL handle for device +* pMsg - found network description +* +* Returns: eHalStatus +* +******************************************************************************/ +eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg); +#endif // FEATURE_WLAN_SCAN_PNO + +/* --------------------------------------------------------------------------- + \fn sme_SetPowerParams + \brief API to set Power Parameters + \param hHal - The handle returned by macOpen. + \param pwParams - Pointer to the power parameters requested. + \param forced - if true, not to be dropped silently in host, it must reach + FW; It is added to avoid a race condition scenario where LIM hasn't deleted + the session yet before power params gets sent to PMC + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams, tANI_BOOLEAN forced); + +/* --------------------------------------------------------------------------- + \fn sme_SetTxPerTracking + \brief Set Tx PER tracking configuration parameters + \param hHal - The handle returned by macOpen. + \param pTxPerTrackingParam - Tx PER configuration parameters + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTxPerTracking ( + tHalHandle hHal, + void (*pCallbackfn) (void *pCallbackContext), + void *pCallbackContext, + tpSirTxPerTrackingParam pTxPerTrackingParam); + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/* --------------------------------------------------------------------------- + \fn sme_ReceiveFilterSetFilter + \brief API to set 8023 Multicast Address List + \param hHal - The handle returned by macOpen. + \param pMulticastAddrs - Pointer to the Multicast Address List + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_8023MulticastList(tHalHandle hHal, tANI_U8 sessionId, tpSirRcvFltMcAddrList pMulticastAddrs); + +/* --------------------------------------------------------------------------- + \fn sme_ReceiveFilterSetFilter + \brief API to set Receive Packet Filter + \param hHal - The handle returned by macOpen. + \param pRcvPktFilterCfg - Receive Packet Filter parameter + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ReceiveFilterSetFilter(tHalHandle hHal, tpSirRcvPktFilterCfgType pRcvPktFilterCfg, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_GetFilterMatchCount + \brief API to get D0 PC Filter Match Count + \param hHal - The handle returned by macOpen + \param callbackRoutine - Callback routine invoked to receive Packet Coalescing Filter Match Count + \param callbackContext - Cookie to be passed back during callback + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetFilterMatchCount(tHalHandle hHal, + FilterMatchCountCallback callbackRoutine, + void *callbackContext, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_ReceiveFilterClearFilter + \brief API to clear Receive Packet Filter + \param hHal - The handle returned by macOpen. + \param pRcvFltPktClearParam - Receive Packet Filter Clear parameter + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ReceiveFilterClearFilter(tHalHandle hHal, + tpSirRcvFltPktClearParam pRcvFltPktClearParam, + tANI_U8 sessionId); +#endif // WLAN_FEATURE_PACKET_FILTERING +/* --------------------------------------------------------------------------- + + \fn sme_IsChannelValid + \brief To check if the channel is valid for currently established domain + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + \param channel - channel to verify + + \return TRUE/FALSE, TRUE if channel is valid + + -------------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_IsChannelValid(tHalHandle hHal, tANI_U8 channel); + +/* --------------------------------------------------------------------------- + \fn sme_SetFreqBand + \brief Used to set frequency band. + \param hHal + \sessionId Session identifier + \eBand band value to be configured + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetFreqBand(tHalHandle hHal, tANI_U8 sessionId, eCsrBand eBand); + +/* --------------------------------------------------------------------------- + \fn sme_GetFreqBand + \brief Used to get the current band settings. + \param hHal + \pBand pointer to hold the current band value + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetFreqBand(tHalHandle hHal, eCsrBand *pBand); + +/* --------------------------------------------------------------------------- + + \fn sme_SetTxPerTracking + \brief Set Tx PER tracking configuration parameters + \param hHal - The handle returned by macOpen. + \param pTxPerTrackingParam - Tx PER configuration parameters + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTxPerTracking ( + tHalHandle hHal, + void (*pCallbackfn) (void *pCallbackContext), + void *pCallbackContext, + tpSirTxPerTrackingParam pTxPerTrackingParam); + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_SetGTKOffload + \brief API to set GTK offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the GTK offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pRequest, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_GetGTKOffload + \brief API to get GTK offload information. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the GTK offload response. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetGTKOffload (tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, + void *callbackContext, tANI_U8 sessionId); +#endif // WLAN_FEATURE_GTK_OFFLOAD + +#ifdef WLAN_WAKEUP_EVENTS +eHalStatus sme_WakeReasonIndCallback (tHalHandle hHal, void* pMsg); +#endif // WLAN_WAKEUP_EVENTS + +/* --------------------------------------------------------------------------- + \fn sme_SetTxPerTracking + \brief Set Tx PER tracking configuration parameters + \param hHal - The handle returned by macOpen. + \param pTxPerTrackingParam - Tx PER configuration parameters + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTxPerTracking ( + tHalHandle hHal, + void (*pCallbackfn) (void *pCallbackContext), + void *pCallbackContext, + tpSirTxPerTrackingParam pTxPerTrackingParam); + + +//return frequency for a particular channel +tANI_U16 sme_ChnToFreq(tANI_U8 chanNum); + +tANI_BOOLEAN sme_IsChannelValid(tHalHandle hHal, tANI_U8 channel); + +/* --------------------------------------------------------------------------- + \fn sme_SetMaxTxPower + \brief Used to set the Maximum Transmit Power dynamically. Note: this + setting will not persist over reboots + \param hHal + \param pBssid BSSID to set the power cap for + \param pBssid pSelfMacAddress self MAC Address + \param pBssid power to set in dB + \- return eHalStatus + -------------------------------------------------------------------------*/ +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); + +/* --------------------------------------------------------------------------- + \fn sme_SetTxPower + \brief Set Transmit Power dynamically. + \param hHal + \param sessionId Target Session ID + \param pBSSId BSSId + \param dev_mode device mode + \param power power to set in dBm + \- return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTxPower(tHalHandle hHal, v_U8_t sessionId, + tSirMacAddr pBSSId, + tVOS_CON_MODE dev_mode, int power); + + +/* --------------------------------------------------------------------------- + + \fn sme_SetCustomMacAddr + + \brief Set the customer Mac Address. + + \param customMacAddr customer MAC Address + \- return eHalStatus + + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetCustomMacAddr(tSirMacAddr customMacAddr); + +/* --------------------------------------------------------------------------- + + \fn sme_HideSSID + + \brief Enable/Disables hidden SSID dynamically. Note: this setting will + not persist over reboots. + + \param hHal + \param sessionId + \param ssidHidden 0 - Broadcast SSID, 1 - Disable broadcast SSID + \- return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_HideSSID(tHalHandle hHal, v_U8_t sessionId, v_U8_t ssidHidden); + +/* --------------------------------------------------------------------------- + + \fn sme_SetTmLevel + \brief Set Thermal Mitigation Level to RIVA + \param hHal - The handle returned by macOpen. + \param newTMLevel - new Thermal Mitigation Level + \param tmMode - Thermal Mitigation handle mode, default 0 + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTmLevel(tHalHandle hHal, v_U16_t newTMLevel, v_U16_t tmMode); + +/*--------------------------------------------------------------------------- + + \brief sme_featureCapsExchange() - SME interface to exchange capabilities between + Host and FW. + + \param hHal - HAL handle for device + + \return NONE + +---------------------------------------------------------------------------*/ +void sme_featureCapsExchange(tHalHandle hHal); + +/*--------------------------------------------------------------------------- + + \brief sme_disableActiveModeOffload() - SME interface to disable Active + mode Offload capability between Host and FW. + + \param hHal - HAL handle for device + + \return NONE + +---------------------------------------------------------------------------*/ +void sme_disableFeatureCapablity(tANI_U8 feature_index); + +/*--------------------------------------------------------------------------- + + \brief sme_GetDefaultCountryCodeFrmNv() - SME interface to get the default + country code + Host and FW. + + \param hHal - HAL handle for device + \param pCountry - pointer to country code + + \return Success or failure + + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetDefaultCountryCodeFrmNv(tHalHandle hHal, tANI_U8 *pCountry); + +/*--------------------------------------------------------------------------- + + \brief sme_GetCurrentCountryCode() - SME interface to get the current operating + country code. + + \param hHal - HAL handle for device + \param pCountry - pointer to country code + + \return Success or failure + + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetCurrentCountryCode(tHalHandle hHal, tANI_U8 *pCountry); + +/* --------------------------------------------------------------------------- + \fn sme_transportDebug + \brief Dynamically monitoring Transport channels + Private IOCTL will query transport channel status if driver loaded + \param hHal Upper MAC context + \param displaySnapshot Display transport channel snapshot option + \param toggleStallDetect Enable stall detect feature + This feature will take effect to data performance + Not integrate till fully verification + \- return NONE + -------------------------------------------------------------------------*/ +void sme_transportDebug(tHalHandle hHal, v_BOOL_t displaySnapshot, v_BOOL_t toggleStallDetect); + +/* --------------------------------------------------------------------------- + \fn sme_ResetPowerValuesFor5G + \brief Reset the power values for 5G band with NV power values. + \param hHal - HAL handle for device + \- return NONE + -------------------------------------------------------------------------*/ +void sme_ResetPowerValuesFor5G (tHalHandle hHal); + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamPrefer5GHz + \brief enable/disable Roam prefer 5G runtime option + This function is called through dynamic setConfig callback function + to configure the Roam prefer 5G runtime option + \param hHal - HAL handle for device + \param nRoamPrefer5GHz Enable/Disable Roam prefer 5G runtime option + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamPrefer5GHz(tHalHandle hHal, v_BOOL_t nRoamPrefer5GHz); + +/* --------------------------------------------------------------------------- + \fn sme_setRoamIntraBand + \brief enable/disable Intra band roaming + This function is called through dynamic setConfig callback function + to configure the intra band roaming + \param hHal - HAL handle for device + \param nRoamIntraBand Enable/Disable Intra band roaming + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanNProbes + \brief function to update roam scan N probes + This function is called through dynamic setConfig callback function + to update roam scan N probes + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nProbes number of probe requests to be sent out + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanNProbes(tHalHandle hHal, tANI_U8 sessionId, + const v_U8_t nProbes); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanHomeAwayTime + \brief function to update roam scan Home away time + This function is called through dynamic setConfig callback function + to update roam scan home away time + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nRoamScanAwayTime Scan home away time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanHomeAwayTime(tHalHandle hHal, tANI_U8 sessionId, + const v_U16_t nRoamScanHomeAwayTime, + const eAniBoolean bSendOffloadCmd); + +/* --------------------------------------------------------------------------- + \fn sme_getRoamIntraBand + \brief get Intra band roaming + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_BOOL_t sme_getRoamIntraBand(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanNProbes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U8_t sme_getRoamScanNProbes(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanHomeAwayTime + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U16_t sme_getRoamScanHomeAwayTime(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateImmediateRoamRssiDiff + \brief Update nImmediateRoamRssiDiff + This function is called through dynamic setConfig callback function + to configure nImmediateRoamRssiDiff + Usage: adb shell iwpriv wlan0 setConfig gImmediateRoamRssiDiff=[0 .. 125] + \param hHal - HAL handle for device + \param nImmediateRoamRssiDiff - minimum rssi difference between potential + candidate and current AP. + \param sessionId - Session identifier + \- return Success or failure + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateImmediateRoamRssiDiff(tHalHandle hHal, + v_U8_t nImmediateRoamRssiDiff, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamRssiDiff + \brief Update RoamRssiDiff + This function is called through dynamic setConfig callback function + to configure RoamRssiDiff + Usage: adb shell iwpriv wlan0 setConfig RoamRssiDiff=[0 .. 125] + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param RoamRssiDiff - minimum rssi difference between potential + candidate and current AP. + \- return Success or failure + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamRssiDiff(tHalHandle hHal, tANI_U8 sessionId, + v_U8_t RoamRssiDiff); + +/*-------------------------------------------------------------------------- + \brief sme_UpdateFastTransitionEnabled() - enable/disable Fast Transition support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isFastTransitionEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update isFastTransitionEnabled config successfully. + Other status means SME is failed to update isFastTransitionEnabled. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateFastTransitionEnabled(tHalHandle hHal, + v_BOOL_t isFastTransitionEnabled); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateWESMode + \brief Update WESMode + This function is called through dynamic setConfig callback function + to configure isWESModeEnabled + \param hHal - HAL handle for device + \param isWESModeEnabled - Enable/Disable WES Mode + \param sessionId - Session identifier + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateWESMode(tHalHandle hHal, v_BOOL_t isWESModeEnabled, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamScanControl + \brief Set roam scan control + This function is called to set roam scan control + if roam scan control is set to 0, roaming scan cache is cleared + any value other than 0 is treated as invalid value + \param hHal - HAL handle for device + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamScanControl(tHalHandle hHal, tANI_U8 sessionId, + v_BOOL_t roamScanControl); +#endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_ESE) || (FEATURE_WLAN_LFR) */ + +#ifdef FEATURE_WLAN_LFR +/*-------------------------------------------------------------------------- + \brief sme_UpdateIsFastRoamIniFeatureEnabled() - enable/disable LFR support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isFastRoamIniFeatureEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update isFastRoamIniFeatureEnabled config successfully. + Other status means SME is failed to update isFastRoamIniFeatureEnabled. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateIsFastRoamIniFeatureEnabled(tHalHandle hHal, + tANI_U8 sessionId, + const v_BOOL_t isFastRoamIniFeatureEnabled); + +/*-------------------------------------------------------------------------- + \brief sme_UpdateIsMAWCIniFeatureEnabled() - + Enable/disable LFR MAWC support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isMAWCIniFeatureEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update MAWCEnabled config successfully. + Other status means SME is failed to update MAWCEnabled. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateIsMAWCIniFeatureEnabled(tHalHandle hHal, + const v_BOOL_t MAWCEnabled); + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_stopRoaming() - Stop roaming for a given sessionId + This is a synchronous call + \param hHal - The handle returned by macOpen + \param sessionId - sessionId + \param reason - reason + \return eHAL_STATUS_SUCCESS on success + Other status on failure + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_stopRoaming(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 reason); + +/*-------------------------------------------------------------------------- + \brief sme_startRoaming() - Start roaming for a given sessionId + This is a synchronous call + \param hHal - The handle returned by macOpen + \param sessionId - sessionId + \param reason - reason + \return eHAL_STATUS_SUCCESS on success + Other status on failure + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_startRoaming(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 reason); + +/*-------------------------------------------------------------------------- + \brief sme_UpdateEnableFastRoamInConcurrency() - enable/disable LFR if + Concurrent session exists + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS + Other status means SME is failed + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateEnableFastRoamInConcurrency(tHalHandle hHal, + v_BOOL_t bFastRoamInConIniFeatureEnabled); +#endif +#endif /* FEATURE_WLAN_LFR */ + +#ifdef FEATURE_WLAN_ESE +/*-------------------------------------------------------------------------- + \brief sme_UpdateIsEseFeatureEnabled() - enable/disable ESE support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isEseIniFeatureEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update isEseIniFeatureEnabled config successfully. + Other status means SME is failed to update isEseIniFeatureEnabled. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateIsEseFeatureEnabled(tHalHandle hHal, tANI_U8 sessionId, + const v_BOOL_t isEseIniFeatureEnabled); + +#endif /* FEATURE_WLAN_ESE */ + +/*-------------------------------------------------------------------------- + \brief sme_UpdateConfigFwRssiMonitoring() - enable/disable firmware + RSSI Monitoring at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + fEnableFwRssiMonitoring. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update fEnableFwRssiMonitoring config successfully. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateConfigFwRssiMonitoring(tHalHandle hHal, + v_BOOL_t fEnableFwRssiMonitoring); + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +/* --------------------------------------------------------------------------- + \fn sme_SetRoamRescanRssiDiff + \brief Update Roam Rescan RSSI diff + This function is called through dynamic setConfig callback function + to configure nRoamRescanRssiDiff + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nRoamRescanRssiDiff - Roam Rescan Rssi Diff + \return eHAL_STATUS_SUCCESS - SME update nRoamRescanRssiDiff config + successfully. + else SME is failed to update nRoamRescanRssiDiff + -------------------------------------------------------------------------*/ + +eHalStatus sme_SetRoamRescanRssiDiff(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nRoamRescanRssiDiff); + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamRescanRssiDiff + \brief gets Roam Rescan RSSI diff + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nRoamRescanRssiDiff + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamRescanRssiDiff(tHalHandle hHal); + + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamOpportunisticScanThresholdDiff + \brief Update Opportunistic Scan threshold diff + This function is called through dynamic setConfig callback function + to configure nOpportunisticThresholdDiff + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nOpportunisticThresholdDiff - Opportunistic Scan threshold diff + \return eHAL_STATUS_SUCCESS - SME update nOpportunisticThresholdDiff config + successfully. + else SME is failed to update nOpportunisticThresholdDiff. + -------------------------------------------------------------------------*/ + +eHalStatus sme_SetRoamOpportunisticScanThresholdDiff(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nOpportunisticThresholdDiff); + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamOpportunisticScanThresholdDiff() + \brief gets Opportunistic Scan threshold diff + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nOpportunisticThresholdDiff + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamOpportunisticScanThresholdDiff(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_setNeighborLookupRssiThreshold() - update neighbor lookup rssi threshold + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborLookupRssiThreshold(tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t neighborLookupRssiThreshold); + +/*-------------------------------------------------------------------------- + \brief sme_set_delay_before_vdev_stop() - update delay before vdev stop + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_set_delay_before_vdev_stop(tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t delay_before_vdev_stop); + +/*-------------------------------------------------------------------------- + \brief sme_setNeighborReassocRssiThreshold() - update neighbor reassoc rssi threshold + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborReassocRssiThreshold(tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t neighborReassocRssiThreshold); + +/*-------------------------------------------------------------------------- + \brief sme_getNeighborLookupRssiThreshold() - get neighbor lookup rssi threshold + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_getNeighborLookupRssiThreshold(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_setNeighborScanRefreshPeriod() - set neighbor scan results refresh period + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanRefreshPeriod(tHalHandle hHal, + tANI_U8 sessionId, + v_U16_t neighborScanResultsRefreshPeriod); + +/*-------------------------------------------------------------------------- + \brief sme_getNeighborScanRefreshPeriod() - get neighbor scan results refresh period + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanRefreshPeriod(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_getEmptyScanRefreshPeriod() - get empty scan refresh period + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +v_U16_t sme_getEmptyScanRefreshPeriod(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateEmptyScanRefreshPeriod + \brief Update nEmptyScanRefreshPeriod + This function is called through dynamic setConfig callback function + to configure nEmptyScanRefreshPeriod + Usage: adb shell iwpriv wlan0 setConfig nEmptyScanRefreshPeriod=[0 .. 60] + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nEmptyScanRefreshPeriod - scan period following empty scan results. + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateEmptyScanRefreshPeriod(tHalHandle hHal,tANI_U8 sessionId, + v_U16_t nEmptyScanRefreshPeriod); + +/* --------------------------------------------------------------------------- + \fn sme_setNeighborScanMinChanTime + \brief Update nNeighborScanMinChanTime + This function is called through dynamic setConfig callback function + to configure gNeighborScanChannelMinTime + Usage: adb shell iwpriv wlan0 setConfig gNeighborScanChannelMinTime=[0 .. 60] + \param hHal - HAL handle for device + \param nNeighborScanMinChanTime - Channel minimum dwell time + \param sessionId - Session identifier + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanMinChanTime(tHalHandle hHal, + const v_U16_t nNeighborScanMinChanTime, + tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_setNeighborScanMaxChanTime + \brief Update nNeighborScanMaxChanTime + This function is called through dynamic setConfig callback function + to configure gNeighborScanChannelMaxTime + Usage: adb shell iwpriv wlan0 setConfig gNeighborScanChannelMaxTime=[0 .. 60] + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nNeighborScanMinChanTime - Channel maximum dwell time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanMaxChanTime(tHalHandle hHal, tANI_U8 sessionId, + const v_U16_t nNeighborScanMaxChanTime); + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborScanMinChanTime + \brief get neighbor scan min channel time + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return v_U16_t - channel min time value + -------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanMinChanTime(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborRoamState + \brief get neighbor roam state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - neighbor roam state + -------------------------------------------------------------------------*/ +v_U32_t sme_getNeighborRoamState(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getCurrentRoamState + \brief get current roam state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - current roam state + -------------------------------------------------------------------------*/ +v_U32_t sme_getCurrentRoamState(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getCurrentRoamSubState + \brief get neighbor roam sub state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - current roam sub state + -------------------------------------------------------------------------*/ +v_U32_t sme_getCurrentRoamSubState(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getLimSmeState + \brief get Lim Sme state + \param hHal - The handle returned by macOpen. + \return v_U32_t - Lim Sme state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimSmeState(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_getLimMlmState + \brief get Lim Mlm state + \param hHal - The handle returned by macOpen. + \return v_U32_t - Lim Mlm state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimMlmState(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_IsLimSessionValid + \brief is Lim session valid + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_BOOL_t - true or false + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsLimSessionValid(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getLimSmeSessionState + \brief get Lim Sme session state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - Lim Sme session state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimSmeSessionState(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getLimMlmSessionState + \brief get Lim Mlm session state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - Lim Mlm session state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimMlmSessionState(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborScanMaxChanTime + \brief get neighbor scan max channel time + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return v_U16_t - channel max time value + -------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanMaxChanTime(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_setNeighborScanPeriod + \brief Update nNeighborScanPeriod + This function is called through dynamic setConfig callback function + to configure nNeighborScanPeriod + Usage: adb shell iwpriv wlan0 setConfig nNeighborScanPeriod=[0 .. 60] + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nNeighborScanPeriod - neighbor scan period + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanPeriod(tHalHandle hHal, tANI_U8 sessionId, + const v_U16_t nNeighborScanPeriod); + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborScanPeriod + \brief get neighbor scan period + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return v_U16_t - neighbor scan period + -------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanPeriod(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamBmissFirstBcnt + \brief Update Roam count for first beacon miss + This function is called through dynamic setConfig callback function + to configure nRoamBmissFirstBcnt + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nRoamBmissFirstBcnt - Roam first bmiss count + \return eHAL_STATUS_SUCCESS - SME update nRoamBmissFirstBcnt + successfully. + else SME is failed to update nRoamBmissFirstBcnt + -------------------------------------------------------------------------*/ + +eHalStatus sme_SetRoamBmissFirstBcnt(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nRoamBmissFirstBcnt); + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamBmissFirstBcnt + \brief gets Roam count for first beacon miss + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nRoamBmissFirstBcnt + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamBmissFirstBcnt(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamBmissFinalBcnt + \brief Update Roam count for final beacon miss + This function is called through dynamic setConfig callback function + to configure nRoamBmissFinalBcnt + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nRoamBmissFinalBcnt - Roam final bmiss count + \return eHAL_STATUS_SUCCESS - SME update nRoamBmissFinalBcnt + successfully. + else SME is failed to update nRoamBmissFinalBcnt + -------------------------------------------------------------------------*/ + +eHalStatus sme_SetRoamBmissFinalBcnt(tHalHandle hHal, tANI_U8 sessionId, + const v_U8_t nRoamBmissFinalBcnt); + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamBmissFinalBcnt + \brief gets Roam count for final beacon miss + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nRoamBmissFinalBcnt + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamBmissFinalBcnt(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamBeaconRssiWeight + \brief Update Roam beacon rssi weight + This function is called through dynamic setConfig callback function + to configure nRoamBeaconRssiWeight + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param nRoamBeaconRssiWeight - Roam beacon rssi weight + \return eHAL_STATUS_SUCCESS - SME update nRoamBeaconRssiWeight config + successfully. + else SME is failed to update nRoamBeaconRssiWeight + -------------------------------------------------------------------------*/ + +eHalStatus sme_SetRoamBeaconRssiWeight(tHalHandle hHal, tANI_U8 sessionId, + const v_U8_t nRoamBeaconRssiWeight); + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamBeaconRssiWeight + \brief gets Roam beacon rssi weight + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nRoamBeaconRssiWeight + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamBeaconRssiWeight(tHalHandle hHal); +#endif + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/*-------------------------------------------------------------------------- + \brief sme_getRoamRssiDiff() - get Roam rssi diff + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_getRoamRssiDiff(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_ChangeRoamScanChannelList() - Change roam scan channel list + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 *pChannelList, + tANI_U8 numChannels); + +#ifdef FEATURE_WLAN_ESE_UPLOAD +/*-------------------------------------------------------------------------- + \brief sme_SetEseRoamScanChannelList() - set ese roam scan channel list + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_SetEseRoamScanChannelList(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 *pChannelList, + tANI_U8 numChannels); +#endif + +/*-------------------------------------------------------------------------- + \brief sme_getRoamScanChannelList() - get roam scan channel list + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param pChannelList - Output channel list + \param pNumChannels - Output number of channels + \param sessionId - Session identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, + tANI_U8 *pNumChannels, tANI_U8 sessionId); + +/*-------------------------------------------------------------------------- + \brief sme_getIsEseFeatureEnabled() - get ESE feature enabled or not + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return TRUE (1) - if the ESE feature is enabled + FALSE (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_getIsEseFeatureEnabled(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_getWESMode() - getWES Mode + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_U8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetWESMode(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_GetRoamScanControl() - get scan control + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_BOOL_t - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetRoamScanControl(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateEmptyScanRefreshPeriod + \brief Update nnEmptyScanRefreshPeriod + This function is called through dynamic setConfig callback function + to configure nnEmptyScanRefreshPeriod + Usage: adb shell iwpriv wlan0 setConfig nEmptyScanRefreshPeriod=[0 .. 60] + \param hHal - HAL handle for device + \param nEmptyScanRefreshPeriod - scan period following empty scan results. + \- return Success or failure + -------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + \brief sme_getIsLfrFeatureEnabled() - get LFR feature enabled or not + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return TRUE (1) - if the feature is enabled + FALSE (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_getIsLfrFeatureEnabled(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_getIsFtFeatureEnabled() - get FT feature enabled or not + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return TRUE (1) - if the feature is enabled + FALSE (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_getIsFtFeatureEnabled(tHalHandle hHal); + +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload + feature + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, v_BOOL_t nRoamScanOffloadEnabled); +#endif + + +/* --------------------------------------------------------------------------- + \fn sme_IsFeatureSupportedByFW + \brief Check if an feature is enabled by FW + + \param feattEnumValue - Enumeration value of the feature to be checked. + A value from enum placeHolderInCapBitmap + + \- return 1/0 (TRUE/FALSE) + -------------------------------------------------------------------------*/ +tANI_U8 sme_IsFeatureSupportedByFW(tANI_U8 featEnumValue); +#ifdef FEATURE_WLAN_TDLS + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsLinkEstablishParams + \brief API to send TDLS Link Establishment Parameters. + + \param peerMac - peer's Mac Address. + \param tdlsLinkEstablishParams - TDLS Peer Link Establishment Parameters + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ + +VOS_STATUS sme_SendTdlsLinkEstablishParams(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams *tdlsLinkEstablishParams); + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsMgmtFrame + \brief API to send TDLS management frames. + + \param peerMac - peer's Mac Address. + \param frame_type - Type of TDLS mgmt frame to be sent. + \param dialog - dialog token used in the frame. + \param status - status to be included in the frame. + \param peerCapability - peerCapability to be included in the frame. + \param buf - additional IEs to be included + \param len - length of additional Ies + \param responder - Tdls request type + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_SendTdlsMgmtFrame(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac, tANI_U8 frame_type, + tANI_U8 dialog, tANI_U16 status, + tANI_U32 peerCapability, tANI_U8 *buf, + tANI_U8 len, tANI_U8 responder); +/* --------------------------------------------------------------------------- + \fn sme_ChangeTdlsPeerSta + \brief API to Update TDLS peer sta parameters. + + \param peerMac - peer's Mac Address. + \param staParams - Peer Station Parameters. + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_ChangeTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams); +/* --------------------------------------------------------------------------- + \fn sme_AddTdlsPeerSta + \brief API to Add TDLS peer sta entry. + + \param peerMac - peer's Mac Address. + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_AddTdlsPeerSta(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac); +/* --------------------------------------------------------------------------- + \fn sme_DeleteTdlsPeerSta + \brief API to Delete TDLS peer sta entry. + + \param peerMac - peer's Mac Address. + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac); +/* --------------------------------------------------------------------------- + \fn sme_SetTdlsPowerSaveProhibited + \API to set/reset the isTdlsPowerSaveProhibited. + + \- return void + -------------------------------------------------------------------------*/ +void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, tANI_U32 sessionId, + v_BOOL_t val); + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsChanSwitchReq + \API to set tdls channel switch parameters. + + \- return void + -------------------------------------------------------------------------*/ +eHalStatus sme_SendTdlsChanSwitchReq(tHalHandle hHal, + tSmeTdlsChanSwitchParams *chSwitchParams); +#endif +/* --------------------------------------------------------------------------- + \fn sme_IsPmcBmps + \brief API to Check if PMC state is BMPS. + + \- return v_BOOL_t + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); + +eHalStatus sme_UpdateDfsSetting(tHalHandle hHal, tANI_U8 fUpdateEnableDFSChnlScan); + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_UpdateEnableSSR(tHalHandle hHal, tANI_BOOLEAN enableSSR); + +/* --------------------------------------------------------------------------- + + \fn sme_SetPhyMode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by macOpen. + + \param phyMode new phyMode which is to set + + \return eHalStatus SUCCESS. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetPhyMode(tHalHandle hHal, eCsrPhyMode phyMode); + +/* --------------------------------------------------------------------------- + + \fn sme_GetPhyMode + + \brief gets current PhyMode. + + \param hHal - The handle returned by macOpen. + + \return eHalStatus PhyMode + + -------------------------------------------------------------------------------*/ +eCsrPhyMode sme_GetPhyMode(tHalHandle hHal); + +/* + * SME API to determine the channel bonding mode + */ +eIniChanBondState sme_SelectCBMode(tHalHandle hHal, eCsrPhyMode eCsrPhyMode, + uint8_t channel, uint8_t ht_sec_dh, + uint16_t *vht_channel_width, + uint16_t ch_width_orig); + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_HandoffRequest() - a wrapper function to Request a handoff + from CSR. + This is a synchronous call + \param hHal - The handle returned by macOpen + \param sessionId - Session identifier + \param pHandoffInfo - info provided by HDD with the handoff request (namely: + BSSID, channel etc.) + \return eHAL_STATUS_SUCCESS - SME passed the request to CSR successfully. + Other status means SME is failed to send the request. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_HandoffRequest(tHalHandle hHal, tANI_U8 sessionId, + tCsrHandoffRequest *pHandoffInfo); +#endif +/*-------------------------------------------------------------------------- + \brief sme_isSta_p2p_clientConnected() - a wrapper function to check if there + is any connected session . + This is a synchronous call + \param hHal - The handle returned by macOpen + \return VOS_STATUS - SME passed the request to CSR successfully. + Other status means SME is failed to send the request. + \sa + --------------------------------------------------------------------------*/ +VOS_STATUS sme_isSta_p2p_clientConnected(tHalHandle hHal); + +#ifdef FEATURE_WLAN_LPHB +/* --------------------------------------------------------------------------- + \fn sme_LPHBConfigReq + \API to make configuration LPHB within FW. + \param hHal - The handle returned by macOpen + \param lphdReq - LPHB request argument by client + \param pCallbackfn - LPHB timeout notification callback function pointer + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +eHalStatus sme_LPHBConfigReq( + tHalHandle hHal, + tSirLPHBReq *lphdReq, + void (*pCallbackfn)(void *pHddCtx, tSirLPHBInd *indParam)); +#endif /* FEATURE_WLAN_LPHB */ + +/* --------------------------------------------------------------------------- + \fn sme_AddPeriodicTxPtrn + \brief API to Periodic TX Pattern Offload feature + \param hHal - The handle returned by macOpen + \param addPeriodicTxPtrnParams - Pointer to the add pattern structure + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_AddPeriodicTxPtrn(tHalHandle hHal, tSirAddPeriodicTxPtrn + *addPeriodicTxPtrnParams); + +/* --------------------------------------------------------------------------- + \fn sme_DelPeriodicTxPtrn + \brief API to Periodic TX Pattern Offload feature + \param hHal - The handle returned by macOpen + \param delPeriodicTxPtrnParams - Pointer to the deleting pattern structure + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_DelPeriodicTxPtrn(tHalHandle hHal, tSirDelPeriodicTxPtrn + *delPeriodicTxPtrnParams); +/*-------------------------------------------------------------------------- + \brief sme_enable_disable_split_scan() - a wrapper function to set the split + scan parameter. + This is a synchronous call + \param hHal - The handle returned by macOpen + \return None. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, + tANI_U8 nNumP2PChan); + +/* --------------------------------------------------------------------------- + \fn sme_SendRateUpdateInd + \brief API to Update rate + \param hHal - The handle returned by macOpen + \param rateUpdateParams - Pointer to rate update params + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SendRateUpdateInd(tHalHandle hHal, tSirRateUpdateInd *rateUpdateParams); + +/* + * sme API to trigger fast BSS roam to a given BSSID independent of RSSI + * triggers + * return status +*/ +eHalStatus smeIssueFastRoamNeighborAPEvent (tHalHandle hHal, + tANI_U8 *bssid, + tSmeFastRoamTrigger fastRoamTrig, + tANI_U8 sessionId); + +eHalStatus sme_RoamDelPMKIDfromCache(tHalHandle hHal, + tANI_U8 sessionId, + const tANI_U8 *pBSSId, + tANI_BOOLEAN flush_cache); + +void smeGetCommandQStatus( tHalHandle hHal ); + +/* + * SME API to enable/disable idle mode power save + * This should be called only if power save offload + * is enabled + */ +VOS_STATUS sme_SetIdlePowersaveConfig(v_PVOID_t vosContext, tANI_U32 value); +VOS_STATUS sme_notify_modem_power_state(tHalHandle hHal, tANI_U32 value); + +eHalStatus sme_ConfigEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode); +eHalStatus sme_ConfigDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode); +eHalStatus sme_PsOffloadEnablePowerSave (tHalHandle hHal, tANI_U32 sessionId); +eHalStatus sme_PsOffloadDisablePowerSave (tHalHandle hHal, tANI_U32 sessionId); +eHalStatus sme_PsOffloadEnableDeferredPowerSave (tHalHandle hHal, + tANI_U32 sessionId, + tANI_BOOLEAN isReassoc); +eHalStatus sme_PsOffloadDisableDeferredPowerSave (tHalHandle hHal, + tANI_U32 sessionId); + + +/*SME API to convert convert the ini value to the ENUM used in csr and MAC*/ +ePhyChanBondState sme_GetCBPhyStateFromCBIniValue(tANI_U32 cb_ini_value); + +int sme_UpdateHTConfig(tHalHandle hHal, tANI_U8 sessionId, tANI_U16 htCapab, + int value); +tANI_S16 sme_GetHTConfig(tHalHandle hHal, tANI_U8 session_id, tANI_U16 ht_capab); + +#ifdef QCA_HT_2040_COEX +VOS_STATUS sme_notify_ht2040_mode(tHalHandle hHal, tANI_U16 staId, + v_MACADDR_t macAddrSTA, v_U8_t sessionId, tANI_U8 channel_type); +eHalStatus sme_SetHT2040Mode(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 channel_type, tANI_BOOLEAN obssEnabled); +#endif + +eHalStatus sme_getRegInfo(tHalHandle hHal, tANI_U8 chanId, + tANI_U32 *regInfo1, tANI_U32 *regInfo2); + +#ifdef FEATURE_WLAN_TDLS +eHalStatus sme_UpdateFwTdlsState(tHalHandle hHal, void *psmeTdlsParams, + tANI_BOOLEAN useSmeLock); +eHalStatus sme_UpdateTdlsPeerState(tHalHandle hHal, + tSmeTdlsPeerStateParams *pPeerStateParams); +#endif /* FEATURE_WLAN_TDLS */ + +#ifdef FEATURE_WLAN_CH_AVOID +/* --------------------------------------------------------------------------- + \fn sme_AddChAvoidCallback + \brief Used to plug in callback function + Which notify channel may not be used with SAP or P2PGO mode. + Notification come from FW. + \param hHal + \param pCallbackfn : callback function pointer should be plugged in + \- return eHalStatus +-------------------------------------------------------------------------*/ +eHalStatus sme_AddChAvoidCallback +( + tHalHandle hHal, + void (*pCallbackfn)(void *hdd_context, void *indi_param) +); + +/* --------------------------------------------------------------------------- + \fn sme_ChAvoidUpdateReq + \API to request channel avoidance update from FW. + \param hHal - The handle returned by macOpen + \param update_type - The udpate_type parameter of this request call + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +eHalStatus sme_ChAvoidUpdateReq +( + tHalHandle hHal +); +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +/* --------------------------------------------------------------------------- + \fn sme_auto_shutdown_cb + \brief Used to plug in callback function for receiving auto shutdown evt + \param hHal + \param pCallbackfn : callback function pointer should be plugged in + \- return eHalStatus +-------------------------------------------------------------------------*/ +eHalStatus sme_set_auto_shutdown_cb(tHalHandle hHal, + void (*pCallbackfn)(void)); + +/* --------------------------------------------------------------------------- + \fn sme_set_auto_shutdown_timer + \API to set auto shutdown timer value in FW. + \param hHal - The handle returned by macOpen + \param timer_val - The auto shutdown timer value to be set + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +eHalStatus sme_set_auto_shutdown_timer(tHalHandle hHal, tANI_U32 timer_value); +#endif + +eHalStatus sme_RoamChannelChangeReq(tHalHandle hHal, tCsrBssid bssid, + tANI_U32 cbMode, tCsrRoamProfile *pprofile); + +eHalStatus sme_RoamStartBeaconReq( tHalHandle hHal, + tCsrBssid bssid, tANI_U8 dfsCacWaitStatus); +/* ------------------------------------------------------------------------- + \fn sme_RoamCsaIeRequest + \brief API to request CSA IE transmission from PE + \param hHal - The handle returned by macOpen + \param pDfsCsaReq - CSA IE request + \param bssid - SAP bssid + \param ch_bandwidth - Channel offset + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamCsaIeRequest(tHalHandle hHal, tCsrBssid bssid, + tANI_U8 targetChannel, tANI_U8 csaIeReqd, + u_int8_t ch_bandwidth); + +/* --------------------------------------------------------------------------- + \fn sme_InitThermalInfo + \brief SME API to initialize the thermal mitigation parameters + \param hHal + \param thermalParam : thermal mitigation parameters + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_InitThermalInfo( tHalHandle hHal, tSmeThermalParams thermalParam ); +/* --------------------------------------------------------------------------- + \fn sme_InitThermalInfo + \brief SME API to set the thermal mitigation level + \param hHal + \param level : thermal mitigation level + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetThermalLevel( tHalHandle hHal, tANI_U8 level ); +/* --------------------------------------------------------------------------- + \fn sme_TxpowerLimit + \brief SME API to set txpower limits + \param hHal + \param psmetx : power limits for 2g/5g + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_TxpowerLimit( tHalHandle hHal, tSirTxPowerLimit *psmetx); +/* --------------------------------------------------------------------------- + \fn sme_GetLinkSpeed + \brief SME API to get the link speed for peermac + \param hHal + \param lsReq: peermac address to retrieve link speed + \param plsContext: callback context + \param pCallbackfn: callback fn with response (link speed) + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetLinkSpeed(tHalHandle hHal,tSirLinkSpeedInfo *lsReq,void *plsContext, + void (*pCallbackfn)(tSirLinkSpeedInfo *indParam, void *pContext) ); + +eHalStatus sme_get_rssi(tHalHandle hal, struct sir_rssi_req req, + void *context, + void (*callbackfn)(struct sir_rssi_resp *param, + void *pcontext)); + +/*---------------------------------------------------------------------------- + \fn sme_ModifyAddIE + \brief This function sends msg to updates the additional IE buffers in PE + \param hHal - global structure + \param pModifyIE - pointer to tSirModifyIE structure + \param updateType - type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus sme_ModifyAddIE(tHalHandle hHal, + tSirModifyIE *pModifyIE, + eUpdateIEsType updateType); + +/*---------------------------------------------------------------------------- + \fn sme_UpdateAddIE + \brief This function sends msg to updates the additional IE buffers in PE + \param hHal - global structure + \param pUpdateIE - pointer to structure tSirUpdateIE + \param updateType - Type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus sme_UpdateAddIE(tHalHandle hHal, + tSirUpdateIE *pUpdateIE, + eUpdateIEsType updateType); + +eHalStatus sme_UpdateConnectDebug(tHalHandle hHal, tANI_U32 set_value); +const char * sme_requestTypetoString(const v_U8_t requestType); +const char * sme_PmcStatetoString(const v_U8_t pmcState); +eHalStatus sme_ApDisableIntraBssFwd(tHalHandle hHal, tANI_U8 sessionId, + tANI_BOOLEAN disablefwd); +tANI_U32 sme_GetChannelBondingMode5G(tHalHandle hHal); +tANI_U32 sme_GetChannelBondingMode24G(tHalHandle hHal); + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) + +eHalStatus sme_init_bad_peer_txctl_info(tHalHandle hHal, + struct sme_bad_peer_txctl_param param ); +#else +static inline eHalStatus sme_init_bad_peer_txctl_info(tHalHandle hHal, + struct sme_bad_peer_txctl_param param ) +{ + /* no-op */ + return eHAL_STATUS_SUCCESS; +} +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + +typedef struct sStatsExtRequestReq { + tANI_U32 request_data_len; + tANI_U8* request_data; +} tStatsExtRequestReq, *tpStatsExtRequestReq; + +typedef void (* StatsExtCallback)(void *, tStatsExtEvent *); + +void sme_StatsExtRegisterCallback(tHalHandle hHal, StatsExtCallback callback); + +eHalStatus sme_StatsExtRequest(tANI_U8 session_id, tpStatsExtRequestReq input); + +eHalStatus sme_StatsExtEvent (tHalHandle hHal, void* pMsg); + +#endif + +/* ------------------------------------------------------------------------- + \fn sme_set_dot11p_config + \brief API to Set 802.11p config + \param hal - The handle returned by macOpen + \param enable_dot11p - 802.11p config param + \return eHalStatus +---------------------------------------------------------------------------*/ +void sme_set_dot11p_config(tHalHandle hal, bool enable_dot11p); + +eHalStatus sme_ocb_set_config(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_config *config); + +eHalStatus sme_ocb_set_utc_time(struct sir_ocb_utc *utc); + +eHalStatus sme_ocb_start_timing_advert(struct sir_ocb_timing_advert + *timing_advert); + +eHalStatus sme_ocb_stop_timing_advert(struct sir_ocb_timing_advert + *timing_advert); + +eHalStatus sme_ocb_get_tsf_timer(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_get_tsf_timer *request); + +eHalStatus sme_dcc_get_stats(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_get_stats *request); + +eHalStatus sme_dcc_clear_stats(uint32_t vdev_id, uint32_t dcc_stats_bitmap); + +eHalStatus sme_dcc_update_ndl(tHalHandle hHal, void* context, + ocb_callback callback, + struct sir_dcc_update_ndl *request); + +eHalStatus sme_register_for_dcc_stats_event(tHalHandle hHal, void* context, + ocb_callback callback); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateDFSScanMode + \brief Update DFS roam scan mode + This function is called through dynamic setConfig callback function + to configure allowDFSChannelRoam. + \param hHal - HAL handle for device + \param sessionId - Session identifier + \param allowDFSChannelRoam - DFS roaming scan mode 0 (disable), + 1 (passive), 2 (active) + \return eHAL_STATUS_SUCCESS - SME update DFS roaming scan config + successfully. + Other status means SME failed to update DFS roaming scan config. + \sa + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateDFSScanMode(tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t allowDFSChannelRoam); + +/*-------------------------------------------------------------------------- + \brief sme_GetDFSScanMode() - get DFS roam scan mode + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return DFS roaming mode 0 (disabled), 1 (passive), 2 (active) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetDFSScanMode(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_staInMiddleOfRoaming + \brief This function returns TRUE if STA is in the middle of roaming state + \param hHal - HAL handle for device + \param sessionId - Session identifier + \- return TRUE or FALSE + -------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_staInMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_PsOffloadIsStaInPowerSave + \brief This function returns TRUE if STA is in power save + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \- return TRUE or FALSE + -------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_PsOffloadIsStaInPowerSave(tHalHandle hHal, tANI_U8 sessionId); + +#ifdef FEATURE_WLAN_EXTSCAN +/* --------------------------------------------------------------------------- + \fn sme_GetValidChannelsByBand + \brief SME API to fetch all valid channel filtered by band + \param hHal + \param wifiBand: RF band information + \param aValidChannels: Array to store channel info + \param len: number of channels + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetValidChannelsByBand (tHalHandle hHal, tANI_U8 wifiBand, + tANI_U32 *aValidChannels, tANI_U8 *pNumChannels); + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanGetCapabilities + \brief SME API to fetch extscan capabilities + \param hHal + \param pReq: extscan capabilities structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanGetCapabilities (tHalHandle hHal, + tSirGetExtScanCapabilitiesReqParams *pReq); + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanStart + \brief SME API to issue extscan start + \param hHal + \param pStartCmd: extscan start structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanStart (tHalHandle hHal, + tSirWifiScanCmdReqParams *pStartCmd); + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanStop + \brief SME API to issue extscan stop + \param hHal + \param pStopReq: extscan stop structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanStop(tHalHandle hHal, + tSirExtScanStopReqParams *pStopReq); + +/* --------------------------------------------------------------------------- + \fn sme_SetBssHotlist + \brief SME API to set BSSID hotlist + \param hHal + \param pSetHotListReq: extscan set hotlist structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetBssHotlist (tHalHandle hHal, + tSirExtScanSetBssidHotListReqParams *pSetHotListReq); + +/* --------------------------------------------------------------------------- + \fn sme_ResetBssHotlist + \brief SME API to reset BSSID hotlist + \param hHal + \param pSetHotListReq: extscan set hotlist structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ResetBssHotlist (tHalHandle hHal, + tSirExtScanResetBssidHotlistReqParams *pResetReq); + +eHalStatus +sme_set_ssid_hotlist(tHalHandle hal, + struct sir_set_ssid_hotlist_request *request); + +/* --------------------------------------------------------------------------- + \fn sme_SetSignificantChange + \brief SME API to set significant change + \param hHal + \param pSetSignificantChangeReq: extscan set significant change structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetSignificantChange (tHalHandle hHal, + tSirExtScanSetSigChangeReqParams* pSetSignificantChangeReq); + +/* --------------------------------------------------------------------------- + \fn sme_ResetSignificantChange + \brief SME API to reset significant change + \param hHal + \param pResetReq: extscan reset significant change structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ResetSignificantChange (tHalHandle hHal, + tSirExtScanResetSignificantChangeReqParams *pResetReq); + +/* --------------------------------------------------------------------------- + \fn sme_getCachedResults + \brief SME API to get cached results + \param hHal + \param pCachedResultsReq: extscan get cached results structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_getCachedResults (tHalHandle hHal, + tSirExtScanGetCachedResultsReqParams *pCachedResultsReq); + +eHalStatus sme_set_epno_list(tHalHandle hal, + struct wifi_epno_params *req_msg); +eHalStatus sme_set_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *req_msg); +eHalStatus sme_reset_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *req_msg); + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanRegisterCallback + \brief SME API to register extscan notification callback + \param pExtScanIndCb + \- return void + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanRegisterCallback (tHalHandle hHal, + void (*pExtScanIndCb)(void *, const tANI_U16, void *)); + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_abortRoamScan + \brief API to abort current roam scan cycle by roam scan offload module. + \param hHal - The handle returned by macOpen. + \param sessionId - Session identifier + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_abortRoamScan(tHalHandle hHal, tANI_U8 sessionId); +#endif //#if WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +/* --------------------------------------------------------------------------- + \fn sme_LLStatsClearReq + \brief SME API to clear Link Layer Statistics + \param hHal + \param pclearStatsReq: Link Layer clear stats request params structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_LLStatsClearReq (tHalHandle hHal, + tSirLLStatsClearReq *pclearStatsReq); + +/* --------------------------------------------------------------------------- + \fn sme_LLStatsSetReq + \brief SME API to set the Link Layer Statistics + \param hHal + \param psetStatsReq: Link Layer set stats request params structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_LLStatsSetReq (tHalHandle hHal, + tSirLLStatsSetReq *psetStatsReq); + +/* --------------------------------------------------------------------------- + \fn sme_LLStatsGetReq + \brief SME API to get the Link Layer Statistics + \param hHal + \param pgetStatsReq: Link Layer get stats request params structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_LLStatsGetReq (tHalHandle hHal, + tSirLLStatsGetReq *pgetStatsReq); + +/* --------------------------------------------------------------------------- + \fn sme_SetLinkLayerStatsIndCB + \brief SME API to trigger the stats are available after get request + \param hHal + \param callbackRoutine - HDD callback which needs to be invoked after + getting status notification from FW + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetLinkLayerStatsIndCB +( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackCtx, int indType, void *pRsp) +); + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +eHalStatus sme_fw_mem_dump(tHalHandle hHal, void *recvd_req); +eHalStatus sme_fw_mem_dump_register_cb(tHalHandle hHal, + void (*callback_routine)(void *cb_context, struct fw_dump_rsp *rsp)); +eHalStatus sme_fw_mem_dump_unregister_cb(tHalHandle hHal); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamOffloadEnabled() - enable/disable roam offload feature + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param nRoamOffloadEnabled - The boolean to update with + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamOffloadEnabled(tHalHandle hHal, + v_BOOL_t nRoamOffloadEnabled); + +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamKeyMgmtOffloadEnabled() - enable/disable key mgmt offload + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param nRoamKeyMgmtOffloadEnabled - The boolean to update with + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamKeyMgmtOffloadEnabled(tHalHandle hHal, + tANI_U8 sessionId, + v_BOOL_t nRoamKeyMgmtOffloadEnabled); + +#endif + +#ifdef WLAN_FEATURE_NAN +/****************************************************************************** + \fn sme_NanEvent + + \brief + a callback function called when SME received eWNI_SME_NAN_EVENT + event from WDA + + \param hHal - HAL handle for device + \param pMsg - Message body passed from WDA; includes NAN header + + \return VOS_STATUS +******************************************************************************/ +VOS_STATUS sme_NanEvent(tHalHandle hHal, void* pMsg); +#endif /* WLAN_FEATURE_NAN */ + +/*-------------------------------------------------------------------------- + \brief sme_getLinkStatus() - api to get the link status + \param hHal - The handle returned by macOpen. + \param callback - callback function for link status result from FW + \param pContext - The context passed with callback + \param sessionId - SME sessionId + \return eHalStatus + --------------------------------------------------------------------------*/ +eHalStatus sme_getLinkStatus(tHalHandle hHal, + tCsrLinkStatusCallback callback, + void *pContext, + tANI_U8 sessionId); + +eHalStatus sme_get_fw_state(tHalHandle hHal, + tcsr_fw_state_callback callback, + void *context); + +/* --------------------------------------------------------------------------- + \fn sme_GetTemperature + \brief SME API to get the pdev temperature + \param hHal + \param temperature context + \param pCallbackfn: callback fn with response (temperature) + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetTemperature(tHalHandle hHal, + void *tempContext, + void (*pCallbackfn)(int temperature, void *pContext)); + +/* --------------------------------------------------------------------------- + \fn sme_SetScanningMacOui + \brief SME API to set scanning mac oui + \param hHal + \param pScanMacOui: Scanning Mac Oui (input 3 bytes) + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetScanningMacOui(tHalHandle hHal, tSirScanMacOui *pScanMacOui); + +#ifdef IPA_UC_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_ipa_offload_enable_disable + \brief API to enable/disable IPA offload + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param pRequest - Pointer to the offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ipa_offload_enable_disable(tHalHandle hal, tANI_U8 session_id, + struct sir_ipa_offload_enable_disable *request); +#endif + +#ifdef DHCP_SERVER_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_setDhcpSrvOffload + \brief SME API to set DHCP server offload info + \param hHal + \param pDhcpSrvInfo : DHCP server offload info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setDhcpSrvOffload(tHalHandle hHal, + tSirDhcpSrvOffloadInfo *pDhcpSrvInfo); +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +/* --------------------------------------------------------------------------- + \fn sme_SetLedFlashing + \brief API to set the LED flashing feature. + \param hHal - The handle returned by macOpen. + \param x0, x1 - led flashing parameters + \param gpio_num - GPIO number + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetLedFlashing (tHalHandle hHal, tANI_U8 type, + tANI_U32 x0, tANI_U32 x1, tANI_U32 gpio_num); +#endif +/* --------------------------------------------------------------------------- + \fn sme_handle_dfS_chan_scan + \brief SME API to enable/disable DFS channel scan + \param hHal + \param dfs_flag: whether dfs needs to be enabled or disabled + \return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_handle_dfs_chan_scan(tHalHandle hHal, tANI_U8 dfs_flag); +eHalStatus sme_ext_change_channel(tHalHandle hHal, uint32_t channel, + uint8_t session_id); + +#ifdef MDNS_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_setMDNSOffload + \brief SME API to set mDNS offload info + \param hHal + \param pMDNSInfo : mDNS offload info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setMDNSOffload(tHalHandle hHal, + tSirMDNSOffloadInfo *pMDNSInfo); + +/* --------------------------------------------------------------------------- + \fn sme_setMDNSFqdn + \brief SME API to set mDNS Fqdn info + \param hHal + \param pMDNSFqdnInfo : mDNS Fqdn info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setMDNSFqdn(tHalHandle hHal, + tSirMDNSFqdnInfo *pMDNSFqdnInfo); + +/* --------------------------------------------------------------------------- + \fn sme_setMDNSResponse + \brief SME API to set mDNS response info + \param hHal + \param pMDNSRespInfo : mDNS response info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setMDNSResponse(tHalHandle hHal, + tSirMDNSResponseInfo *pMDNSRespInfo); +#endif /* MDNS_OFFLOAD */ + +#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); + +eHalStatus sme_set_client_block_info(tHalHandle hHal, + struct sblock_info *client_block_info); + +#else + +static inline eHalStatus sme_set_client_block_info(tHalHandle hHal, + struct sblock_info *client_block_info) +{ + return eHAL_STATUS_FAILURE; +} + +#endif /* SAP_AUTH_OFFLOAD */ + +eHalStatus sme_set_tsfcb(tHalHandle hHal, + int (*pcallbackfn)(void *pcallbackcontext, struct stsf *ptsf), + void *pcallbackcontext); + +#ifdef WLAN_FEATURE_APFIND +VOS_STATUS sme_apfind_set_cmd(struct sme_ap_find_request_req *input); +#endif /* WLAN_FEATURE_APFIND */ + +/** + * sme_enable_disable_mas() - Function to set MAS value to UMAC + * @val: 1-Enable, 0-Disable + * + * This function passes down the value of MAS to the UMAC. A + * value of 1 will enable MAS and a value of 0 will disable MAS + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +eHalStatus sme_set_mas(tANI_U32 val); + +/** + * sme_set_miracast() - Function to set miracast value to UMAC + * @hal: Handle returned by macOpen + * @filter_type: 0-Disabled, 1-Source, 2-sink + * + * This function passes down the value of miracast set by + * framework to UMAC + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +eHalStatus sme_set_miracast(tHalHandle hal, uint8_t filter_type); +bool sme_validate_sap_channel_switch(tHalHandle hal, + uint16_t sap_ch, + eCsrPhyMode sap_phy_mode, + uint8_t cc_switch_mode, + uint32_t session_id); + +eHalStatus sme_configure_modulated_dtim(tHalHandle hHal, tANI_U8 session_id, + tANI_U32 modulated_dtim); + +eHalStatus sme_configure_stats_avg_factor(tHalHandle hHal, tANI_U8 session_id, + tANI_U16 stats_avg_factor); + +eHalStatus sme_configure_guard_time(tHalHandle hHal, tANI_U8 session_id, + tANI_U32 guard_time); +eHalStatus sme_update_roam_scan_hi_rssi_scan_params(tHalHandle hal_handle, + uint8_t session_id, + uint32_t notify_id, + int32_t val); + +eHalStatus sme_wifi_start_logger(tHalHandle hal, + struct sir_wifi_start_log start_log); + +#ifdef WLAN_FEATURE_TSF +eHalStatus sme_set_tsf_gpio(tHalHandle hHal, uint32_t pinvalue); +#else +static inline eHalStatus +sme_set_tsf_gpio(tHalHandle hHal, uint32_t pinvalue) +{ + return eHAL_STATUS_FAILURE; +} +#endif + +bool smeNeighborMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId); + +eHalStatus sme_update_nss(tHalHandle h_hal, uint8_t nss); +void sme_enable_phy_error_logs(tHalHandle hal, bool enable_log); + +uint8_t sme_is_any_session_in_connected_state(tHalHandle h_hal); + +typedef void ( *tSmeSetThermalLevelCallback)(void *pContext, u_int8_t level); +void sme_add_set_thermal_level_callback(tHalHandle hHal, + tSmeSetThermalLevelCallback callback); + +eHalStatus sme_disable_non_fcc_channel(tHalHandle hHal, + bool fcc_constraint); + +eHalStatus sme_set_rssi_monitoring(tHalHandle hal, + struct rssi_monitor_req *input); +eHalStatus sme_set_rssi_threshold_breached_cb(tHalHandle hal, + void (*cb)(void *, struct rssi_breach_event *)); +void sme_set_pdev_ht_vht_ies(tHalHandle hHal, bool enable2x2); + +void sme_update_vdev_type_nss(tHalHandle hal, uint8_t max_supp_nss, + uint32_t vdev_type_nss, eCsrBand band); +void sme_update_user_configured_nss(tHalHandle hal, uint8_t nss); +void sme_set_vdev_nss(tHalHandle hal, bool enable2x2); +void sme_set_per_band_chainmask_supp(tHalHandle hal, bool val); +void sme_set_lte_coex_supp(tHalHandle hal, bool val); +void sme_set_bcon_offload_supp(tHalHandle hal, bool val); +void sme_SetDefDot11Mode(tHalHandle hal); + +#ifdef FEATURE_WLAN_TDLS +void sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset, + uint8_t *opclass); +#else +static inline void +sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset, + uint8_t *opclass) +{ +} +#endif + + + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD +VOS_STATUS sme_set_udp_resp_offload(struct udp_resp_offload *pudp_resp_cmd); +#else +static inline VOS_STATUS sme_set_udp_resp_offload(struct udp_resp_offload + *pudp_resp_cmd) +{ + return VOS_STATUS_E_FAILURE; +} +#endif + + +eHalStatus sme_set_lost_link_info_cb(tHalHandle hal, + void (*cb)(void *, + struct sir_lost_link_info *)); + +eHalStatus sme_roam_set_default_key_index(tHalHandle hal, uint8_t session_id, + uint8_t default_idx); + +eHalStatus sme_set_smps_force_mode_cb(tHalHandle hal, + void (*cb)(void *, struct sir_smps_force_mode_event *)); + +eHalStatus sme_update_mimo_power_save(tHalHandle hHal, + uint8_t is_ht_smps_enabled, + uint8_t ht_smps_mode); + +bool sme_is_sta_smps_allowed(tHalHandle hHal, uint8_t session_id); + +#endif //#if !defined( __SME_API_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_FTApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_FTApi.h new file mode 100644 index 000000000000..b963843db6a3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_FTApi.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#if defined(WLAN_FEATURE_VOWIFI_11R) + +#if !defined( __SME_FTAPI_H ) +#define __SME_FTAPI_H + +#include + +/**========================================================================= + + \brief macros and prototype for SME APIs + + ========================================================================*/ +typedef enum eFTIEState +{ + eFT_START_READY, // Start before and after 11r assoc + eFT_AUTH_REQ_READY, // When we have recvd the 1st or nth auth req + eFT_WAIT_AUTH2, // Sent auth1 and waiting auth2 + eFT_AUTH_COMPLETE, // We are now ready for FT phase, send auth1, recd auth2 + eFT_REASSOC_REQ_WAIT, // Now we have sent Auth Rsp to the supplicant and waiting + // Reassoc Req from the supplicant. + eFT_SET_KEY_WAIT, // We have received the Reassoc request from + // supplicant. Waiting for the keys. +} tFTIEStates; + +/* FT neighbor roam callback user context */ +typedef struct sFTRoamCallbackUsrCtx +{ + tpAniSirGlobal pMac; + tANI_U8 sessionId; +} tFTRoamCallbackUsrCtx, *tpFTRoamCallbackUsrCtx; + +typedef struct sFTSMEContext +{ + /* Received and processed during pre-auth */ + tANI_U8 *auth_ft_ies; + tANI_U32 auth_ft_ies_length; + + /* Received and processed during re-assoc */ + tANI_U8 *reassoc_ft_ies; + tANI_U16 reassoc_ft_ies_length; + + /* Pre-Auth info */ + tFTIEStates FTState; // The state of FT in the current 11rAssoc + tSirMacAddr preAuthbssId; // BSSID to preauth to + tANI_U32 smeSessionId; + + /* Saved pFTPreAuthRsp */ + tpSirFTPreAuthRsp psavedFTPreAuthRsp; + v_BOOL_t setFTPreAuthState; + v_BOOL_t setFTPTKState; + + /* Time to trigger reassoc once pre-auth is successful */ + vos_timer_t preAuthReassocIntvlTimer; + + v_BOOL_t addMDIE; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U32 r0kh_id_len; + tANI_U8 r0kh_id[SIR_ROAM_R0KH_ID_MAX_LEN]; +#endif + + /* User context for the timer callback */ + tpFTRoamCallbackUsrCtx pUsrCtx; +} tftSMEContext, *tpftSMEContext; + +/*-------------------------------------------------------------------------- + Prototype functions + ------------------------------------------------------------------------*/ +void sme_FTOpen(tHalHandle hHal, tANI_U32 sessionId); +void sme_FTClose(tHalHandle hHal, tANI_U32 sessionId); +void sme_FTReset(tHalHandle hHal, tANI_U32 sessionId); +void sme_SetFTIEs( tHalHandle hHal, tANI_U32 sessionId, const tANI_U8 *ft_ies, tANI_U16 ft_ies_length ); +eHalStatus sme_FTUpdateKey( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamSetKey * pFTKeyInfo ); +void sme_GetFTPreAuthResponse(tHalHandle hHal, tANI_U32 sessionId, tANI_U8 *ft_ies, + tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length ); +void sme_GetRICIEs(tHalHandle hHal, tANI_U32 sessionId, tANI_U8 *ric_ies, + tANI_U32 ric_ies_ip_len, tANI_U32 *ric_ies_length ); +void sme_PreauthReassocIntvlTimerCallback(void *context); +void sme_SetFTPreAuthState(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t state); +v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal, tANI_U32 sessionId); +v_BOOL_t sme_GetFTPTKState(tHalHandle hHal, tANI_U32 sessionId); +void sme_SetFTPTKState(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t state); +#endif + +#endif //#if !defined( __SME_FTAPI_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_QosApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_QosApi.h new file mode 100644 index 000000000000..1497b57a20bc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_QosApi.h @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __SME_QOSAPI_H ) +#define __SME_QOSAPI_H + + +/**========================================================================= + + \file sme_QosApi.h + + \brief prototype for SME QoS APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_lock.h" +#include "vos_trace.h" +#include "vos_memory.h" +#include "vos_types.h" +#include "aniGlobal.h" +#include "sirApi.h" + +/*-------------------------------------------------------------------------- + Pre-processor Definitions + ------------------------------------------------------------------------*/ +#define SME_QOS_UAPSD_VO 0x01 +#define SME_QOS_UAPSD_VI 0x02 +#define SME_QOS_UAPSD_BE 0x08 +#define SME_QOS_UAPSD_BK 0x04 + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Enumeration of the various QoS status types that would be reported to HDD +---------------------------------------------------------------------------*/ +typedef enum +{ + //async: once PE notifies successful TSPEC negotiation, or CSR notifies for + //successful reassoc, notifies HDD with current QoS Params + SME_QOS_STATUS_SETUP_SUCCESS_IND = 0, + //sync: only when App asked for APSD & it's already set with ACM = 0 + SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY, + //both: sync or async: in case of async notifies HDD with current QoS Params + SME_QOS_STATUS_SETUP_FAILURE_RSP, + //sync + SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP, + //sync: AP doesn't support QoS (WMM) + SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP, + //sync: either req has been sent down to PE or just buffered in SME + SME_QOS_STATUS_SETUP_REQ_PENDING_RSP, + //async: in case of flow aggregation, if the new TSPEC negotiation is + //successful, OR, + //notify existing flows that TSPEC is modified with current QoS Params + SME_QOS_STATUS_SETUP_MODIFIED_IND, + //sync: no APSD asked for & ACM = 0 + SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP, + //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or + //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't + //put the module in UAPSD mode right away (eHAL_STATUS_PMC_PENDING) + SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING, + //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or + //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't + //put the module in UAPSD mode at all (eHAL_STATUS_FAILURE) + SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED, + + //sync: req has been sent down to PE in case of delts or addts for remain + // flows, OR if the AC doesn't have APSD or ACM + //async: once the downgrade req for QoS params is successful + SME_QOS_STATUS_RELEASE_SUCCESS_RSP = 100, + //both: sync or async: in case of async notifies HDD with current QoS Params + SME_QOS_STATUS_RELEASE_FAILURE_RSP, + //async: AP sent DELTS indication + SME_QOS_STATUS_RELEASE_QOS_LOST_IND, + //sync: an addts req has been sent down to PE to downgrade the QoS params or + // just buffered in SME + SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP, + //sync + SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP, + + //async: for QoS modify request if modification is successful, notifies HDD + // with current QoS Params + SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND = 200, + //sync: only when App asked for APSD & it's already set with ACM = 0 + SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY, + //both: sync or async: in case of async notifies HDD with current QoS Params + SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP, + //sync: either req has been sent down to PE or just buffered in SME + SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP, + //sync: no APSD asked for & ACM = 0 + SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP, + //sync + SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP, + //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or + //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't + //put the module in UAPSD mode right away (eHAL_STATUS_PMC_PENDING) + SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_PENDING, + //async: In case of UAPSD, once PE notifies successful TSPEC negotiation, or + //CSR notifies for successful reassoc to SME-QoS, notify HDD if PMC can't + //put the module in UAPSD mode at all (eHAL_STATUS_FAILURE) + SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED, + //sync: STA is handing off to a new AP + SME_QOS_STATUS_HANDING_OFF = 300, + /* async:power save mode changed by PMC from UAPSD to Full power */ + SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND = 400, + /* async:power save mode changed by PMC from Full power to UAPSD */ + SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND, + +}sme_QosStatusType; + +/*--------------------------------------------------------------------------- + Enumeration of the various User priority (UP) types + + From 802.1D/802.11e/WMM specifications (all refer to same table) +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_WMM_UP_BE = 0, + SME_QOS_WMM_UP_BK = 1, + SME_QOS_WMM_UP_RESV = 2, /* Reserved */ + SME_QOS_WMM_UP_EE = 3, + SME_QOS_WMM_UP_CL = 4, + SME_QOS_WMM_UP_VI = 5, + SME_QOS_WMM_UP_VO = 6, + SME_QOS_WMM_UP_NC = 7, + + SME_QOS_WMM_UP_MAX + +}sme_QosWmmUpType; + +/*--------------------------------------------------------------------------- + Enumeration of the various TSPEC directions + + From 802.11e/WMM specifications +---------------------------------------------------------------------------*/ + +typedef enum +{ + SME_QOS_WMM_TS_DIR_UPLINK = 0, + SME_QOS_WMM_TS_DIR_DOWNLINK = 1, + SME_QOS_WMM_TS_DIR_RESV = 2, /* Reserved */ + SME_QOS_WMM_TS_DIR_BOTH = 3, + +}sme_QosWmmDirType; + +/*--------------------------------------------------------------------------- + Enumeration of the various TSPEC ack policies. + + From 802.11 WMM specification +---------------------------------------------------------------------------*/ + +typedef enum +{ + SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK = 0, + SME_QOS_WMM_TS_ACK_POLICY_RESV1 = 1, + SME_QOS_WMM_TS_ACK_POLICY_RESV2 = 2, /* Reserved */ + SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK = 3, + +}sme_QosWmmAckPolicyType; + +/*--------------------------------------------------------------------------- + TS Info field in the WMM TSPEC + + See suggestive values above +---------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t burst_size_defn; + sme_QosWmmAckPolicyType ack_policy; + sme_QosWmmUpType up; /* User priority */ + v_U8_t psb; /* power-save bit */ + sme_QosWmmDirType direction; /* Direction */ + v_U8_t tid; /* TID : To be filled up by SME-QoS */ +} sme_QosWmmTsInfoType; + +/*--------------------------------------------------------------------------- + The WMM TSPEC Element (from the WMM spec) +---------------------------------------------------------------------------*/ +typedef struct +{ + sme_QosWmmTsInfoType ts_info; + v_U16_t nominal_msdu_size; + v_U16_t maximum_msdu_size; + v_U32_t min_service_interval; + v_U32_t max_service_interval; + v_U32_t inactivity_interval; + v_U32_t suspension_interval; + v_U32_t svc_start_time; + v_U32_t min_data_rate; + v_U32_t mean_data_rate; + v_U32_t peak_data_rate; + v_U32_t max_burst_size; + v_U32_t delay_bound; + v_U32_t min_phy_rate; + v_U16_t surplus_bw_allowance; + v_U16_t medium_time; +} sme_QosWmmTspecInfo; + + +/*-------------------------------------------------------------------------- + External APIs + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + \brief sme_QosCallback() - This is a callback function which is registered + per flow while HDD is requesting for QoS. Used for any notification for the + flow (i.e. setup success/failure/release) which needs to be sent to HDD. HDD + will notify the application in turn, if needed. + + \param hHal - The handle returned by macOpen. + \param HDDcontext - A cookie passed by HDD during QoS setup, to be used by SME + during any QoS notification (through the callback) to HDD + \param pCurrentQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM + TSPEC related info as defined above, fed back to HDD + \param status - The status of the flow running on an AC. It could be of + sme_QosStatusType + + \return eHAL_STATUS_SUCCESS - Callback invoke successful. + + + \sa + + --------------------------------------------------------------------------*/ +typedef eHalStatus (*sme_QosCallback)(tHalHandle hHal, void * HDDcontext, + sme_QosWmmTspecInfo * pCurrentQoSInfo, + sme_QosStatusType status, + v_U32_t QosFlowID); + +/*-------------------------------------------------------------------------- + \brief sme_QosSetupReq() - The SME QoS API exposed to HDD to request for QoS + on a particular AC. This function should be called after a link has been + established, i.e. STA is associated with an AP etc. If the request involves + admission control on the requested AC, HDD needs to provide the necessary + Traffic Specification (TSPEC) parameters otherwise SME is going to use the + default params. + + \param hHal - The handle returned by macOpen. + \param sessionId - sessionId returned by sme_OpenSession. Current QOS code doesn't + support multiple session. This function returns failure when different + sessionId is passed in before calling sme_QosReleaseReq. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info as defined above, provided by HDD + \param QoSCallback - The callback which is registered per flow while + requesting for QoS. Used for any notification for the + flow (i.e. setup success/failure/release) which needs to + be sent to HDD + \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS + notification (through the callback) to HDD + \param UPType - Useful only if HDD or any other upper layer module (BAP etc.) + looking for implicit QoS setup, in that + case, the pQoSInfo will be NULL & SME will know about the AC + (from the UP provided in this param) QoS is requested on + \param pQosFlowID - Identification per flow running on each AC generated by + SME. + It is only meaningful if the QoS setup for the flow is + successful + + \return SME_QOS_STATUS_SETUP_SUCCESS - Setup request processed successfully. + + Other status means Setup request failed + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosSetupReq(tHalHandle hHal, tANI_U32 sessionId, + sme_QosWmmTspecInfo * pQoSInfo, + sme_QosCallback QoSCallback, void * HDDcontext, + sme_QosWmmUpType UPType, v_U32_t * pQosFlowID); + +/*-------------------------------------------------------------------------- + \brief sme_QosModifyReq() - The SME QoS API exposed to HDD to request for + modification of certain QoS params on a flow running on a particular AC. + This function should be called after a link has been established, i.e. STA is + associated with an AP etc. & a QoS setup has been successful for that flow. + If the request involves admission control on the requested AC, HDD needs to + provide the necessary Traffic Specification (TSPEC) parameters & SME might + start the renegotiation process through ADDTS. + + \param hHal - The handle returned by macOpen. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info as defined above, provided by HDD + \param QosFlowID - Identification per flow running on each AC generated by + SME. + It is only meaningful if the QoS setup for the flow has + been successful already + + \return SME_QOS_STATUS_SETUP_SUCCESS - Modification request processed + successfully. + + Other status means request failed + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosModifyReq(tHalHandle hHal, + sme_QosWmmTspecInfo * pQoSInfo, + v_U32_t QosFlowID); + +/*-------------------------------------------------------------------------- + \brief sme_QosReleaseReq() - The SME QoS API exposed to HDD to request for + releasing a QoS flow running on a particular AC. This function should be + called only if a QoS is set up with a valid FlowID. HDD should invoke this + API only if an explicit request for QoS release has come from Application + + \param hHal - The handle returned by macOpen. + \param QosFlowID - Identification per flow running on each AC generated by SME + It is only meaningful if the QoS setup for the flow is + successful + + \return SME_QOS_STATUS_RELEASE_SUCCESS - Release request processed + successfully. + + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosReleaseReq(tHalHandle hHal, v_U32_t QosFlowID); + +/*-------------------------------------------------------------------------- + \brief sme_QosIsTSInfoAckPolicyValid() - The SME QoS API exposed to HDD to + check if TS info ack policy field can be set to "HT-immediate block + acknowledgment" + + \param pMac - The handle returned by macOpen. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info, provided by HDD + \param sessionId - sessionId returned by sme_OpenSession. + + \return VOS_TRUE - Current Association is HT association and so TS info ack policy + can be set to "HT-immediate block acknowledgment" + + \sa + + --------------------------------------------------------------------------*/ +v_BOOL_t sme_QosIsTSInfoAckPolicyValid(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo * pQoSInfo, + v_U8_t sessionId); + + +/*-------------------------------------------------------------------------- + \brief sme_QosUpdateHandOff() - Function which can be called to update + Hand-off state of SME QoS Session + \param sessionId - session id + \param updateHandOff - value True/False to update the handoff flag + + \sa + +-------------------------------------------------------------------------*/ +void sme_QosUpdateHandOff(v_U8_t sessionId, + v_BOOL_t updateHandOff); + + +/*-------------------------------------------------------------------------- + \brief sme_UpdateDSCPtoUPMapping() - Function which can be called to update + qos mapping table maintained in HDD + \param hHal - The handle returned by macOpen. + \param dscpmapping - pointer to the qos mapping structure in HDD + \param sessionId - session id + + \sa +-------------------------------------------------------------------------*/ +VOS_STATUS sme_UpdateDSCPtoUPMapping(tHalHandle hHal, + sme_QosWmmUpType* dscpmapping, v_U8_t sessionId); + +#endif //#if !defined( __SME_QOSAPI_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_RrmApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_RrmApi.h new file mode 100644 index 000000000000..a1264c58dcd3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_RrmApi.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __SMERRMAPI_H ) +#define __SMERRMAPI_H + + +/**========================================================================= + + \file sme_RrmApi.h + + \brief prototype for SME RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_lock.h" +#include "vos_trace.h" +#include "vos_memory.h" +#include "vos_types.h" +#include "aniGlobal.h" +#include "sirApi.h" +#include "smeInternal.h" +#include "smeRrmInternal.h" + + +//APIs +eHalStatus sme_RrmMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type, + void *pMsgBuf); + +VOS_STATUS rrmClose (tpAniSirGlobal pMac); +VOS_STATUS rrmReady (tpAniSirGlobal pMac); +VOS_STATUS rrmOpen (tpAniSirGlobal pMac); +VOS_STATUS rrmChangeDefaultConfigParam(tpAniSirGlobal pMac, + struct rrm_config_param *rrm_config); +VOS_STATUS sme_RrmNeighborReportRequest(tpAniSirGlobal pMac, tANI_U8 sessionId, tpRrmNeighborReq pNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo); + +tRrmNeighborReportDesc* smeRrmGetFirstBssEntryFromNeighborCache( tpAniSirGlobal pMac); +tRrmNeighborReportDesc* smeRrmGetNextBssEntryFromNeighborCache( tpAniSirGlobal pMac, tpRrmNeighborReportDesc pBssEntry); +eHalStatus sme_RrmProcessBeaconReportReqInd(tpAniSirGlobal pMac, void *pMsgBuf); + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Trace.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Trace.h new file mode 100644 index 000000000000..1eac30491b0e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Trace.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*********************************************************************** + sme_Trace.h + + \brief definition for trace related APIs + + \author Kiran Kumar Reddy CH L V + + ========================================================================*/ + +#ifndef __SME_TRACE_H__ +#define __SME_TRACE_H__ + + +#include "macTrace.h" + +#define NO_SESSION 0xFF +#define TRACE_CODE_SME_COMMAND 0xFF +enum { + TRACE_CODE_SME_RX_HDD_MSG_SCAN_REQ, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_GET_RESULTS, + TRACE_CODE_SME_RX_HDD_MSG_CONNECT, + TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO, + TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN, + TRACE_CODE_SME_RX_HDD_MSG_SET_REGINFO, + TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CHANNEL_CONFIG, + TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG, + TRACE_CODE_SME_RX_HDD_MSG_HDDREADYIND, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_P2PRESULTS, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETFIRST, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETNEXT, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_PURGE, + TRACE_CODE_SME_RX_HDD_ROAM_REASSOC, + TRACE_CODE_SME_RX_HDD_ROAM_DISCONNECT, + TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, + TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE, + TRACE_CODE_SME_RX_HDD_ROAM_SET_PMKIDCACHE, + TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE, + TRACE_CODE_SME_RX_HDD_ROAM_GET_PMKIDCACHE, + TRACE_CODE_SME_RX_HDD_GET_CONFIGPARAM, + TRACE_CODE_SME_RX_HDD_GET_MODPROFFIELDS, + TRACE_CODE_SME_RX_HDD_SET_CONFIG_PWRSAVE, + TRACE_CODE_SME_RX_HDD_GET_CONFIG_PWRSAVE, + TRACE_CODE_SME_RX_HDD_ENABLE_PWRSAVE, + TRACE_CODE_SME_RX_HDD_DISABLE_PWRSAVE, + TRACE_CODE_SME_RX_HDD_SIGNAL_POWER_EVENT, + TRACE_CODE_SME_RX_HDD_START_AUTO_BMPSTIMER, + TRACE_CODE_SME_RX_HDD_STOP_AUTO_BMPSTIMER, + TRACE_CODE_SME_RX_HDD_IS_PWRSAVE_ENABLED, + TRACE_CODE_SME_RX_HDD_REQUEST_FULLPOWER, + TRACE_CODE_SME_RX_HDD_REQUEST_BMPS, + TRACE_CODE_SME_RX_HDD_SET_DHCP_FLAG, + TRACE_CODE_SME_RX_HDD_REQUEST_STANDBY, + TRACE_CODE_SME_RX_HDD_WOWL_ADDBCAST_PATTERN, + TRACE_CODE_SME_RX_HDD_WOWL_DELBCAST_PATTERN, + TRACE_CODE_SME_RX_HDD_ENTER_WOWL, + TRACE_CODE_SME_RX_HDD_EXIT_WOWL, + TRACE_CODE_SME_RX_HDD_SET_KEY, + TRACE_CODE_SME_RX_HDD_REMOVE_KEY, + TRACE_CODE_SME_RX_HDD_GET_STATS, + TRACE_CODE_SME_RX_HDD_GET_RSSI, + TRACE_CODE_SME_RX_HDD_GET_CNTRYCODE, + TRACE_CODE_SME_RX_HDD_SET_CNTRYCODE, + TRACE_CODE_SME_RX_HDD_CHANGE_CNTRYCODE, + TRACE_CODE_SME_RX_HDD_BTC_SIGNALEVENT, + TRACE_CODE_SME_RX_HDD_BTC_SETCONFIG, + TRACE_CODE_SME_RX_HDD_BTC_GETCONFIG, + TRACE_CODE_SME_RX_HDD_SET_CFGPRIVACY, + TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ, + TRACE_CODE_SME_RX_HDD_DBG_READREG, + TRACE_CODE_SME_RX_HDD_DBG_WRITEREG, + TRACE_CODE_SME_RX_HDD_DBG_READMEM, + TRACE_CODE_SME_RX_HDD_DBG_WRITEMEM, + TRACE_CODE_SME_RX_HDD_OPEN_SESSION, + TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, + TRACE_CODE_SME_RX_HDD_SET_HOSTOFFLOAD, + TRACE_CODE_SME_RX_HDD_SET_GTKOFFLOAD, + TRACE_CODE_SME_RX_HDD_GET_GTKOFFLOAD, + TRACE_CODE_SME_RX_HDD_SET_POWERPARAMS, + TRACE_CODE_SME_RX_HDD_ABORT_MACSCAN, + TRACE_CODE_SME_RX_HDD_REGISTER_MGMTFR, + TRACE_CODE_SME_RX_HDD_DEREGISTER_MGMTFR, + TRACE_CODE_SME_RX_HDD_REMAIN_ONCHAN, + TRACE_CODE_SME_RX_HDD_SEND_ACTION, + TRACE_CODE_SME_RX_HDD_CANCEL_REMAIN_ONCHAN, + TRACE_CODE_SME_RX_HDD_CONFIG_RXPFIL, + TRACE_CODE_SME_RX_HDD_CONFIG_SUSPENDIND, + TRACE_CODE_SME_RX_HDD_CONFIG_RESUMEREQ, +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + TRACE_CODE_SME_RX_HDD_CONFIG_EXTWOW, + TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE1, + TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE2, +#endif + TRACE_CODE_SME_RX_HDD_SET_MAXTXPOW, + TRACE_CODE_SME_RX_HDD_SET_TXPOW, + TRACE_CODE_SME_RX_HDD_SET_TMLEVEL, + TRACE_CODE_SME_RX_HDD_CAPS_EXCH, + TRACE_CODE_SME_RX_HDD_DISABLE_CAP, + TRACE_CODE_SME_RX_HDD_GET_DEFCCNV, + TRACE_CODE_SME_RX_HDD_GET_CURCC, + TRACE_CODE_SME_RX_HDD_RESET_PW5G, + TRACE_CODE_SME_RX_HDD_UPDATE_RP5G, + TRACE_CODE_SME_RX_HDD_SET_ROAMIBAND, + TRACE_CODE_SME_RX_HDD_GET_ROAMIBAND, + TRACE_CODE_SME_RX_HDD_UPDATE_RSSIDIFF, + TRACE_CODE_SME_RX_HDD_UPDATE_IMMRSSIDIFF, + TRACE_CODE_SME_RX_HDD_UPDATE_FTENABLED, + TRACE_CODE_SME_RX_HDD_UPDATE_WESMODE, + TRACE_CODE_SME_RX_HDD_SET_SCANCTRL, + TRACE_CODE_SME_RX_HDD_UPDATE_P2P_IE, + TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_N_PROBES, + TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_HOME_AWAY_TIME, + TRACE_CODE_SME_RX_HDD_STORE_JOIN_REQ, + TRACE_CODE_SME_RX_HDD_CLEAR_JOIN_REQ, + TRACE_CODE_SME_RX_HDD_ISSUE_JOIN_REQ, + TRACE_CODE_SME_RX_HDD_MSG_DEAUTH_STA, +#ifdef FEATURE_WLAN_TDLS + TRACE_CODE_SME_RX_HDD_TDLS_LINK_ESTABLISH_PARAM, + TRACE_CODE_SME_RX_HDD_TDLS_CHAN_SWITCH_REQ, + TRACE_CODE_SME_RX_HDD_TDLS_SEND_MGMT_FRAME, + TRACE_CODE_SME_RX_HDD_TDLS_CHANGE_PEER_STA, + TRACE_CODE_SME_RX_HDD_TDLS_ADD_PEER_STA, + TRACE_CODE_SME_RX_HDD_TDLS_DEL_PEER_STA, +#endif + TRACE_CODE_SME_RX_HDD_PREF_NET_LIST, +#ifdef FEATURE_WLAN_LPHB + TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ, +#endif /* FEATURE_WLAN_LPHB */ +}; + +void smeTraceInit(tpAniSirGlobal pMac); +#endif //__SME_TRACE_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/smsDebug.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/smsDebug.h new file mode 100644 index 000000000000..c773d92221d3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smsDebug.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011,2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file cssDebug.h + + Define debug log interface for SMS. +========================================================================== */ + +#ifndef SMS_DEBUG_H__ +#define SMS_DEBUG_H__ + +#include "utilsApi.h" +#include "sirDebug.h" + +#if !defined(__printf) +#define __printf(a,b) +#endif + +void __printf(3,4) +smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...); + +void __printf(3,4) +pmcLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...); + +#endif // __SMS_DEBUG_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/wlan_ps_wow_diag.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/wlan_ps_wow_diag.h new file mode 100644 index 000000000000..71ec44cdd1d2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/wlan_ps_wow_diag.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WLAN_PS_WOW_DIAG_H_ +#define _WLAN_PS_WOW_DIAG_H_ + + +#include "vos_diag_core_event.h" +#include "vos_diag_core_log.h" + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + +typedef enum +{ + WLAN_BMPS_ENTER_REQ =0, + WLAN_UAPSD_START_REQ =1, + WLAN_UAPSD_STOP_REQ =2, + WLAN_ENTER_STANDBY_REQ =3, + WLAN_ENTER_DEEP_SLEEP_REQ =4, + WLAN_START_BMPS_AUTO_TIMER_REQ =5, + WLAN_STOP_BMPS_AUTO_TIMER_REQ =6, + WLAN_IMPS_ENTER_REQ =7, + WLAN_ENTER_FULL_POWER_REQ =8, + WLAN_PMC_CURRENT_STATE =9, + WLAN_PS_MODE_ENABLE_REQ =10, + WLAN_PS_MODE_DISABLE_REQ =11, + WLAN_WINMOB_D_POWER_STATE =12, + WLAN_BMPS_DTIM_PERIOD =13, + WLAN_BMPS_FINAL_LI =14, + WLAN_BMPS_SET_CONFIG =15, + +} wlan_ps_evt_subtype_t; + +// maps directly to eRequestFullPowerReason +typedef enum +{ + WLAN_MISSED_BEACON_IND_RCVD, /* PE received a MAX_MISSED_BEACON_IND */ + WLAN_BMPS_STATUS_IND_RCVD, /* PE received a SIR_HAL_BMPS_STATUS_IND */ + WLAN_BMPS_MODE_DISABLED, /* BMPS mode was disabled by HDD in SME */ + WLAN_LINK_DISCONNECTED_BY_HDD, /* Link has been disconnected requested by HDD */ + + /* Disconnect due to link lost or requested by peer */ + WLAN_LINK_DISCONNECTED_BY_OTHER, + + WLAN_FULL_PWR_NEEDED_BY_HDD, /* HDD request full power for some reason */ + WLAN_FULL_PWR_NEEDED_BY_BAP, /* BAP request full power for BT_AMP */ + WLAN_FULL_PWR_NEEDED_BY_CSR, /* CSR requests full power */ + WLAN_FULL_PWR_NEEDED_BY_QOS, /* QOS requests full power */ + WLAN_REASON_OTHER /* No specific reason. General reason code */ + +} wlan_ps_full_power_request_reason_t; + +// maps directly to ePmcState +typedef enum +{ + WLAN_PMC_STOPPED, /* PMC is stopped */ + WLAN_PMC_FULL_POWER, /* full power */ + WLAN_PMC_LOW_POWER, /* low power */ + WLAN_PMC_REQUEST_IMPS, /* requesting IMPS */ + WLAN_PMC_IMPS, /* in IMPS */ + WLAN_PMC_REQUEST_BMPS, /* requesting BMPS */ + WLAN_PMC_BMPS, /* in BMPS */ + WLAN_PMC_REQUEST_FULL_POWER, /* requesting full power */ + WLAN_PMC_REQUEST_START_UAPSD, /* requesting Start UAPSD */ + WLAN_PMC_REQUEST_STOP_UAPSD, /* requesting Stop UAPSD */ + WLAN_PMC_UAPSD, /* in UAPSD */ + WLAN_PMC_REQUEST_STANDBY, /* requesting standby mode */ + WLAN_PMC_STANDBY, /* in standby mode */ + WLAN_PMC_REQUEST_ENTER_WOWL, /* requesting enter WOWL */ + WLAN_PMC_REQUEST_EXIT_WOWL, /* requesting exit WOWL */ + WLAN_PMC_WOWL /* Chip in WOWL mode */ + +} wlan_ps_pmc_current_state_t; + +// maps directly to ePmcPowerSavingMode +typedef enum +{ + WLAN_IDLE_MODE_POWER_SAVE, /* Idle Mode Power Save (IMPS) */ + WLAN_BEACON_MODE_POWER_SAVE, /* Beacon Mode Power Save (BMPS) */ + WLAN_SPATIAL_MULTIPLEX_POWER_SAVE, /* Spatial Multiplexing Power Save (SMPS) */ + WLAN_UAPSD_MODE_POWER_SAVE, /* Unscheduled Automatic Power Save Delivery Mode */ + WLAN_STANDBY_MODE_POWER_SAVE, /* Standby Power Save Mode */ + WLAN_WOWL_MODE_POWER_SAVE /* Wake-on-Wireless LAN Power Save Mode */ + +} wlan_ps_enable_disable_ps_mode_t; + +typedef enum +{ + WLAN_D0, + WLAN_D1, + WLAN_D2, + WLAN_D3, + WLAN_D4 + +} wlan_ps_winmob_d_power_state_t; + +typedef enum +{ + WLAN_WOW_ENTER_REQ =0, + WLAN_WOW_EXIT_REQ =1, + WLAN_WOW_DEL_PTRN_REQ =2, + WLAN_WOW_WAKEUP = 3 + +} wlan_ps_wow_evt_subtype_t; + +typedef enum +{ + WLAN_WOW_TYPE_NONE, + WLAN_WOW_TYPE_MAGIC_PKT_ONLY, + WLAN_WOW_TYPE_PTRN_BYTE_MATCH_ONLY, + WLAN_WOW_TYPE_MAGIC_PKT_PTRN_BYTE_MATCH, + +} wlan_ps_wow_type_t; + +typedef enum +{ + WLAN_WOW_MAGIC_PKT_MATCH, + WLAN_WOW_PTRN_BYTE_MATCH + +} wlan_ps_wos_wakeup_cause_t; + +#endif // FEATURE_WLAN_DIAG_SUPPORT + +#endif // _WLAN_PS_WOW_DIAG_H_ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/QoS/sme_Qos.c b/drivers/staging/qcacld-2.0/CORE/SME/src/QoS/sme_Qos.c new file mode 100644 index 000000000000..63e1ecf9463d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/QoS/sme_Qos.c @@ -0,0 +1,8648 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file sme_Qos.c + + \brief implementation for SME QoS APIs + + ========================================================================*/ +/* $Header$ */ +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + + +#include "aniGlobal.h" + +#include "smeInside.h" +#include "vos_diag_core_event.h" +#include "vos_diag_core_log.h" + +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "smsDebug.h" +#include "utilsParser.h" +#endif +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include +#endif + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT +/* TODO : 6Mbps as Cisco APs seem to like only this value; analysis req. */ +#define SME_QOS_MIN_PHY_RATE 0x5B8D80 +#define SME_QOS_SURPLUS_BW_ALLOWANCE 0x2000 /* Ratio of 1.0 */ +/*--------------------------------------------------------------------------- + Max values to bound tspec params against and avoid rollover +---------------------------------------------------------------------------*/ +#define SME_QOS_32BIT_MAX 0xFFFFFFFF +#define SME_QOS_16BIT_MAX 0xFFFF +#define SME_QOS_16BIT_MSB 0x8000 +/*--------------------------------------------------------------------------- + Adds y to x, but saturates at 32-bit max to avoid rollover +---------------------------------------------------------------------------*/ +#define SME_QOS_BOUNDED_U32_ADD_Y_TO_X( _x, _y ) \ + do \ + { \ + (_x) = ( (SME_QOS_32BIT_MAX-(_x))<(_y) ) ? \ + (SME_QOS_32BIT_MAX) : (_x)+(_y); \ + } while(0) +/*--------------------------------------------------------------------------- + As per WMM spec there could be max 2 TSPEC running on the same AC with + different direction. We will refer each TSPEC with an index +---------------------------------------------------------------------------*/ +#define SME_QOS_TSPEC_INDEX_0 0 +#define SME_QOS_TSPEC_INDEX_1 1 +#define SME_QOS_TSPEC_INDEX_MAX 2 +#define SME_QOS_TSPEC_MASK_BIT_1_SET 1 +#define SME_QOS_TSPEC_MASK_BIT_2_SET 2 +#define SME_QOS_TSPEC_MASK_BIT_1_2_SET 3 +#define SME_QOS_TSPEC_MASK_CLEAR 0 + +/* Which key to search on, in the flow list (1 = flowID, 2 = AC, 4 = reason) */ +#define SME_QOS_SEARCH_KEY_INDEX_1 1 +#define SME_QOS_SEARCH_KEY_INDEX_2 2 +#define SME_QOS_SEARCH_KEY_INDEX_3 4 +#define SME_QOS_SEARCH_KEY_INDEX_4 8 // ac + direction +#define SME_QOS_SEARCH_KEY_INDEX_5 0x10 // ac + tspec_mask +//special value for searching any Session Id +#define SME_QOS_SEARCH_SESSION_ID_ANY CSR_ROAM_SESSION_MAX +#define SME_QOS_ACCESS_POLICY_EDCA 1 +#define SME_QOS_MAX_TID 255 +#define SME_QOS_TSPEC_IE_LENGTH 61 +#define SME_QOS_TSPEC_IE_TYPE 2 +#define SME_QOS_MIN_FLOW_ID 1 +#define SME_QOS_MAX_FLOW_ID 0xFFFFFFFE +#define SME_QOS_INVALID_FLOW_ID 0xFFFFFFFF +// per the WMM Specification v1.2 Section 2.2.10 +// The Dialog Token field shall be set [...] to a non-zero value +#define SME_QOS_MIN_DIALOG_TOKEN 1 +#define SME_QOS_MAX_DIALOG_TOKEN 0xFF +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------- + Enumeration of the various states in the QoS state m/c +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_CLOSED = 0, + SME_QOS_INIT, + SME_QOS_LINK_UP, + SME_QOS_REQUESTED, + SME_QOS_QOS_ON, + SME_QOS_HANDOFF, + +}sme_QosStates; +/*--------------------------------------------------------------------------- + Enumeration of the various Release QoS trigger +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_RELEASE_DEFAULT = 0, + SME_QOS_RELEASE_BY_AP, +}sme_QosRelTriggers; +/*--------------------------------------------------------------------------- + Enumeration of the various QoS cmds +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_SETUP_REQ = 0, + SME_QOS_RELEASE_REQ, + SME_QOS_MODIFY_REQ, + SME_QOS_RESEND_REQ, + SME_QOS_CMD_MAX +}sme_QosCmdType; +/*--------------------------------------------------------------------------- + Enumeration of the various QoS reason codes to be used in the Flow list +---------------------------------------------------------------------------*/ +typedef enum +{ + SME_QOS_REASON_SETUP = 0, + SME_QOS_REASON_RELEASE, + SME_QOS_REASON_MODIFY, + SME_QOS_REASON_MODIFY_PENDING, + SME_QOS_REASON_REQ_SUCCESS, + SME_QOS_REASON_MAX +}sme_QosReasonType; + +/*--------------------------------------------------------------------------- + Table to map user priority passed in as an argument to appropriate Access + Category as specified in 802.11e/WMM +---------------------------------------------------------------------------*/ +sme_QosEdcaAcType sme_QosUPtoACMap[SME_QOS_WMM_UP_MAX] = +{ + SME_QOS_EDCA_AC_BE, /* User Priority 0 */ + SME_QOS_EDCA_AC_BK, /* User Priority 1 */ + SME_QOS_EDCA_AC_BK, /* User Priority 2 */ + SME_QOS_EDCA_AC_BE, /* User Priority 3 */ + SME_QOS_EDCA_AC_VI, /* User Priority 4 */ + SME_QOS_EDCA_AC_VI, /* User Priority 5 */ + SME_QOS_EDCA_AC_VO, /* User Priority 6 */ + SME_QOS_EDCA_AC_VO /* User Priority 7 */ +}; + +/*--------------------------------------------------------------------------- + Table to map access category (AC) to appropriate user priority as specified + in 802.11e/WMM + Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs + Mapping is done for consistency +---------------------------------------------------------------------------*/ +sme_QosWmmUpType sme_QosACtoUPMap[SME_QOS_EDCA_AC_MAX] = +{ + SME_QOS_WMM_UP_BE, /* AC BE */ + SME_QOS_WMM_UP_BK, /* AC BK */ + SME_QOS_WMM_UP_VI, /* AC VI */ + SME_QOS_WMM_UP_VO /* AC VO */ +}; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's FLOW Link List structure. This list can hold information per + flow/request, like TSPEC params requested, which AC it is running on +---------------------------------------------------------------------------*/ +typedef struct sme_QosFlowInfoEntry_s +{ + tListElem link; /* list links */ + v_U8_t sessionId; + v_U8_t tspec_mask; + sme_QosReasonType reason; + v_U32_t QosFlowID; + sme_QosEdcaAcType ac_type; + sme_QosWmmTspecInfo QoSInfo; + void * HDDcontext; + sme_QosCallback QoSCallback; + + /* + * Set to TRUE while re-negotiating flows after + * handoff, will set to FALSE once done with the process. Helps SME to + * decide if at all to notify HDD/LIS for flow renewal after HO + */ + v_BOOL_t hoRenewal; +} sme_QosFlowInfoEntry; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's setup request cmd related information structure. +---------------------------------------------------------------------------*/ +typedef struct sme_QosSetupCmdInfo_s +{ + v_U32_t QosFlowID; + sme_QosWmmTspecInfo QoSInfo; + void *HDDcontext; + sme_QosCallback QoSCallback; + sme_QosWmmUpType UPType; + + /* + * Set to TRUE while re-negotiating flows after + * handoff, will set to FALSE once done with the process. Helps SME to + * decide if at all to notify HDD/LIS for flow renewal after HO + */ + v_BOOL_t hoRenewal; +} sme_QosSetupCmdInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's modify cmd related information structure. +---------------------------------------------------------------------------*/ +typedef struct sme_QosModifyCmdInfo_s +{ + v_U32_t QosFlowID; + sme_QosEdcaAcType ac; + sme_QosWmmTspecInfo QoSInfo; +} sme_QosModifyCmdInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's resend cmd related information structure. +---------------------------------------------------------------------------*/ +typedef struct sme_QosResendCmdInfo_s +{ + v_U8_t tspecMask; + sme_QosEdcaAcType ac; + sme_QosWmmTspecInfo QoSInfo; +} sme_QosResendCmdInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's release cmd related information structure. +---------------------------------------------------------------------------*/ +typedef struct sme_QosReleaseCmdInfo_s +{ + v_U32_t QosFlowID; +} sme_QosReleaseCmdInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's buffered cmd related information structure. +---------------------------------------------------------------------------*/ +typedef struct sme_QosCmdInfo_s +{ + sme_QosCmdType command; + tpAniSirGlobal pMac; + v_U8_t sessionId; + union + { + sme_QosSetupCmdInfo setupCmdInfo; + sme_QosModifyCmdInfo modifyCmdInfo; + sme_QosResendCmdInfo resendCmdInfo; + sme_QosReleaseCmdInfo releaseCmdInfo; + }u; +} sme_QosCmdInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's buffered cmd List structure. This list can hold information + related to any pending cmd from HDD +---------------------------------------------------------------------------*/ +typedef struct sme_QosCmdInfoEntry_s +{ + tListElem link; /* list links */ + sme_QosCmdInfo cmdInfo; +} sme_QosCmdInfoEntry; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's Per AC information structure. This can hold information on + how many flows running on the AC, the current, previous states the AC is in +---------------------------------------------------------------------------*/ +typedef struct sme_QosACInfo_s +{ + v_U8_t num_flows[SME_QOS_TSPEC_INDEX_MAX]; + sme_QosStates curr_state; + sme_QosStates prev_state; + sme_QosWmmTspecInfo curr_QoSInfo[SME_QOS_TSPEC_INDEX_MAX]; + sme_QosWmmTspecInfo requested_QoSInfo[SME_QOS_TSPEC_INDEX_MAX]; + v_BOOL_t reassoc_pending;//reassoc requested for APSD + //As per WMM spec there could be max 2 TSPEC running on the same AC with + //different direction. We will refer each TSPEC with an index + v_U8_t tspec_mask_status; //status showing if both the indices are in use + v_U8_t tspec_pending;//tspec negotiation going on for which index + + /* + * Set to TRUE while re-negotiating flows after + * handoff, will set to FALSE once done with the process. Helps SME to + * decide if at all to notify HDD/LIS for flow renewal after HO + */ + v_BOOL_t hoRenewal; +#ifdef WLAN_FEATURE_VOWIFI_11R + v_U8_t ricIdentifier[SME_QOS_TSPEC_INDEX_MAX]; + /* stores the ADD TS response for each AC. The ADD TS response is formed by + parsing the RIC received in the the reassoc response */ + tSirAddtsRsp addTsRsp[SME_QOS_TSPEC_INDEX_MAX]; +#endif + sme_QosRelTriggers relTrig; + +} sme_QosACInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's Per session information structure. This can hold information + on the state of the session +---------------------------------------------------------------------------*/ +typedef struct sme_QosSessionInfo_s +{ + // what is this entry's session id + v_U8_t sessionId; + // is the session currently active + v_BOOL_t sessionActive; + // All AC info for this session + sme_QosACInfo ac_info[SME_QOS_EDCA_AC_MAX]; + // Bitmask of the ACs with APSD on + // Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored + v_U8_t apsdMask; + // association information for this session + sme_QosAssocInfo assocInfo; + // ID assigned to our reassoc request + v_U32_t roamID; + + /* + * Maintaining a power save status in QoS module, to be fed back to PMC at + * times through the sme_QosPmcCheckRoutine + */ + v_BOOL_t readyForPowerSave; + + // are we in the process of handing off to a different AP + v_BOOL_t handoffRequested; + // following reassoc or AddTS has UAPSD already been requested from PMC + v_BOOL_t uapsdAlreadyRequested; + // commands that are being buffered for this session + tDblLinkList bufferedCommandList; + +#ifdef WLAN_FEATURE_VOWIFI_11R + v_BOOL_t ftHandoffInProgress; +#endif + +} sme_QosSessionInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + Search key union. We can use the flowID, ac type, or reason to find an entry + in the flow list +---------------------------------------------------------------------------*/ +typedef union sme_QosSearchKey_s +{ + v_U32_t QosFlowID; + sme_QosEdcaAcType ac_type; + sme_QosReasonType reason; +}sme_QosSearchKey; +/*--------------------------------------------------------------------------- +DESCRIPTION + We can either use the flowID or the ac type to find an entry in the flow list. + The index is a bitmap telling us which key to use. Starting from LSB, + bit 0 - Flow ID + bit 1 - AC type +---------------------------------------------------------------------------*/ +typedef struct sme_QosSearchInfo_s +{ + v_U8_t sessionId; + v_U8_t index; + sme_QosSearchKey key; + sme_QosWmmDirType direction; + v_U8_t tspec_mask; +}sme_QosSearchInfo; +/*--------------------------------------------------------------------------- +DESCRIPTION + SME QoS module's internal control block. +---------------------------------------------------------------------------*/ +struct sme_QosCb_s +{ + //global Mac pointer + tpAniSirGlobal pMac; + //All Session Info + sme_QosSessionInfo sessionInfo[CSR_ROAM_SESSION_MAX]; + //All FLOW info + tDblLinkList flow_list; + //default TSPEC params + sme_QosWmmTspecInfo def_QoSInfo[SME_QOS_EDCA_AC_MAX]; + //counter for assigning Flow IDs + v_U32_t nextFlowId; + //counter for assigning Dialog Tokens + v_U8_t nextDialogToken; +}sme_QosCb; +typedef eHalStatus (*sme_QosProcessSearchEntry)(tpAniSirGlobal pMac, tListElem *pEntry); +/*-------------------------------------------------------------------------- + Internal function declarations + ------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosInternalSetupReq(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo * pQoSInfo, + sme_QosCallback QoSCallback, + void * HDDcontext, + sme_QosWmmUpType UPType, + v_U32_t QosFlowID, + v_BOOL_t buffered_cmd, + v_BOOL_t hoRenewal); +sme_QosStatusType sme_QosInternalModifyReq(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo * pQoSInfo, + v_U32_t QosFlowID, + v_BOOL_t buffered_cmd); +sme_QosStatusType sme_QosInternalReleaseReq(tpAniSirGlobal pMac, + v_U32_t QosFlowID, + v_BOOL_t buffered_cmd); +sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo *pTspec_Info, + sme_QosEdcaAcType ac); +eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo * pTspec_Info, + sme_QosEdcaAcType ac); +eHalStatus sme_QosDelTsReq(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosEdcaAcType ac, + v_U8_t tspec_mask); +eHalStatus sme_QosProcessAddTsRsp(tpAniSirGlobal pMac, void *pMsgBuf); +eHalStatus sme_QosProcessDelTsInd(tpAniSirGlobal pMac, void *pMsgBuf); +eHalStatus sme_QosProcessDelTsRsp(tpAniSirGlobal pMac, void *pMsgBuf); +eHalStatus sme_QosProcessAssocCompleteEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessReassocFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessDisconnectEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessJoinReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessHandoffAssocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessHandoffSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessHandoffFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +#ifdef WLAN_FEATURE_VOWIFI_11R +eHalStatus sme_QosProcessPreauthSuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessSetKeySuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info); +eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf); +eHalStatus sme_QosFTAggrQosReq( tpAniSirGlobal pMac, v_U8_t sessionId ); +#endif +eHalStatus sme_QosProcessAddTsSuccessRsp(tpAniSirGlobal pMac, + v_U8_t sessionId, + tSirAddtsRspInfo * pRsp); +eHalStatus sme_QosProcessAddTsFailureRsp(tpAniSirGlobal pMac, + v_U8_t sessionId, + tSirAddtsRspInfo * pRsp); +eHalStatus sme_QosAggregateParams( + sme_QosWmmTspecInfo * pInput_Tspec_Info, + sme_QosWmmTspecInfo * pCurrent_Tspec_Info, + sme_QosWmmTspecInfo * pUpdated_Tspec_Info); +static eHalStatus sme_QosUpdateParams(v_U8_t sessionId, + sme_QosEdcaAcType ac, + v_U8_t tspec_mask, + sme_QosWmmTspecInfo * pTspec_Info); +sme_QosWmmUpType sme_QosAcToUp(sme_QosEdcaAcType ac); +sme_QosEdcaAcType sme_QosUpToAc(sme_QosWmmUpType up); +v_BOOL_t sme_QosIsACM(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes); +tListElem *sme_QosFindInFlowList(sme_QosSearchInfo search_key); +eHalStatus sme_QosFindAllInFlowList(tpAniSirGlobal pMac, + sme_QosSearchInfo search_key, + sme_QosProcessSearchEntry fnp); +static void sme_QosStateTransition(v_U8_t sessionId, + sme_QosEdcaAcType ac, + sme_QosStates new_state); +eHalStatus sme_QosBufferCmd(sme_QosCmdInfo *pcmd, v_BOOL_t insert_head); +static eHalStatus sme_QosProcessBufferedCmd(v_U8_t sessionId); +eHalStatus sme_QosSaveAssocInfo(sme_QosSessionInfo *pSession, sme_QosAssocInfo *pAssoc_info); +eHalStatus sme_QosSetupFnp(tpAniSirGlobal pMac, tListElem *pEntry); +eHalStatus sme_QosModificationNotifyFnp(tpAniSirGlobal pMac, tListElem *pEntry); +eHalStatus sme_QosModifyFnp(tpAniSirGlobal pMac, tListElem *pEntry); +eHalStatus sme_QosDelTsIndFnp(tpAniSirGlobal pMac, tListElem *pEntry); +eHalStatus sme_QosReassocSuccessEvFnp(tpAniSirGlobal pMac, tListElem *pEntry); +eHalStatus sme_QosAddTsFailureFnp(tpAniSirGlobal pMac, tListElem *pEntry); +eHalStatus sme_QosAddTsSuccessFnp(tpAniSirGlobal pMac, tListElem *pEntry); +static v_BOOL_t sme_QosIsRspPending(v_U8_t sessionId, sme_QosEdcaAcType ac); +static v_BOOL_t sme_QosIsUapsdActive(void); +void sme_QosPmcFullPowerCallback(void *callbackContext, eHalStatus status); +void sme_QosPmcOffloadFullPowerCallback(void *callbackContext, tANI_U32 sessionId, + eHalStatus status); + +void sme_QosPmcStartUapsdCallback(void *callbackContext, eHalStatus status); +void sme_QosPmcOffloadStartUapsdCallback(void *callbackContext, + tANI_U32 sessionId, eHalStatus status); +v_BOOL_t sme_QosPmcCheckRoutine(void *callbackContext); +v_BOOL_t sme_QosPmcOffloadCheckRoutine(void *callbackContext, tANI_U32 sessionId); + +void sme_QosPmcDeviceStateUpdateInd(void *callbackContext, tPmcState pmcState); +void sme_OffloadQosPmcDeviceStateUpdateInd(void *callbackContext, + tANI_U32 sessionId, tPmcState pmcState); + +eHalStatus sme_QosProcessOutOfUapsdMode(tpAniSirGlobal pMac); +eHalStatus sme_OffloadQosProcessOutOfUapsdMode(tpAniSirGlobal pMac, + tANI_U32 sessionId); +eHalStatus sme_QosProcessIntoUapsdMode(tpAniSirGlobal pMac); +eHalStatus sme_OffloadQosProcessIntoUapsdMode(tpAniSirGlobal pMac, + tANI_U32 sessionId); +static eHalStatus sme_QosBufferExistingFlows(tpAniSirGlobal pMac, + v_U8_t sessionId); +static eHalStatus sme_QosDeleteExistingFlows(tpAniSirGlobal pMac, + v_U8_t sessionId); +static void sme_QosCleanupCtrlBlkForHandoff(tpAniSirGlobal pMac, + v_U8_t sessionId); +static eHalStatus sme_QosDeleteBufferedRequests(tpAniSirGlobal pMac, + v_U8_t sessionId); +v_BOOL_t sme_QosValidateRequestedParams(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo * pQoSInfo, + v_U8_t sessionId); + +extern eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme); +extern eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme); +static eHalStatus qosIssueCommand( tpAniSirGlobal pMac, v_U8_t sessionId, + eSmeCommandType cmdType, sme_QosWmmTspecInfo * pQoSInfo, + sme_QosEdcaAcType ac, v_U8_t tspec_mask ); +/* + sme_QosReRequestAddTS to re-send AddTS for the combined QoS request +*/ +static sme_QosStatusType sme_QosReRequestAddTS(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo * pQoSInfo, + sme_QosEdcaAcType ac, + v_U8_t tspecMask); +static void sme_QosInitACs(tpAniSirGlobal pMac, v_U8_t sessionId); +static eHalStatus sme_QosRequestReassoc(tpAniSirGlobal pMac, tANI_U8 sessionId, + tCsrRoamModifyProfileFields *pModFields, + v_BOOL_t fForce ); +static v_U32_t sme_QosAssignFlowId(void); +static v_U8_t sme_QosAssignDialogToken(void); +static eHalStatus sme_QosUpdateTspecMask(v_U8_t sessionId, + sme_QosSearchInfo search_key, + v_U8_t new_tspec_mask); +/*-------------------------------------------------------------------------- + External APIs definitions + ------------------------------------------------------------------------*/ +/* -------------------------------------------------------------------------- + \brief sme_QosOpen() - This function must be called before any API call to + SME QoS module. + \param pMac - Pointer to the global MAC parameter structure. + + \return eHalStatus +----------------------------------------------------------------------------*/ +eHalStatus sme_QosOpen(tpAniSirGlobal pMac) +{ + sme_QosSessionInfo *pSession; + v_U8_t sessionId; + eHalStatus status; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: initializing SME-QoS module", + __func__, __LINE__); + //init the control block + //(note that this will make all sessions invalid) + vos_mem_zero(&sme_QosCb, sizeof(sme_QosCb)); + sme_QosCb.pMac = pMac; + sme_QosCb.nextFlowId = SME_QOS_MIN_FLOW_ID; + sme_QosCb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN; + //init flow list + status = csrLLOpen(pMac->hHdd, &sme_QosCb.flow_list); + if (!HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot initialize Flow List", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) + { + pSession = &sme_QosCb.sessionInfo[sessionId]; + pSession->sessionId = sessionId; + // initialize the session's per-AC information + sme_QosInitACs(pMac, sessionId); + // initialize the session's buffered command list + status = csrLLOpen(pMac->hHdd, &pSession->bufferedCommandList); + if (!HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot initialize cmd list for session %d", + __func__, __LINE__, + sessionId); + return eHAL_STATUS_FAILURE; + } + pSession->readyForPowerSave = VOS_TRUE; + + if(pMac->psOffloadEnabled) + { + if(eHAL_STATUS_SUCCESS != pmcOffloadRegisterPowerSaveCheck(pMac, + sessionId, sme_QosPmcOffloadCheckRoutine, pMac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot register with pmcOffloadRegisterPowerSaveCheck()", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + + if(eHAL_STATUS_SUCCESS != pmcOffloadRegisterDeviceStateUpdateInd(pMac, + sessionId, sme_OffloadQosPmcDeviceStateUpdateInd, pMac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot register with pmcOffloadRegisterPowerSaveCheck()", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + } + } + + if(!pMac->psOffloadEnabled) + { + /* + * The routine registered here gets called by PMC whenever the device + * is about to enter one of the power save modes. PMC runs a poll with all + * the registered modules if device can enter power save mode or + * remain full power. + */ + if(!HAL_STATUS_SUCCESS( + pmcRegisterPowerSaveCheck(pMac, sme_QosPmcCheckRoutine, pMac))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot register with pmcRegisterPowerSaveCheck()", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + //the routine registered here gets called by PMC + //whenever there is a device + // state change. PMC might go to full power + //because of many reasons and this + // is the way for PMC to inform all the other + //registered modules so that + // everyone is in sync. + if(!HAL_STATUS_SUCCESS( + pmcRegisterDeviceStateUpdateInd(pMac, + sme_QosPmcDeviceStateUpdateInd, pMac))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot register with pmcRegisterDeviceStateUpdateInd()", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: done initializing SME-QoS module", + __func__, __LINE__); + return eHAL_STATUS_SUCCESS; +} +/* -------------------------------------------------------------------------- + \brief sme_QosClose() - To close down SME QoS module. There should not be + any API call into this module after calling this function until another + call of sme_QosOpen. + \param pMac - Pointer to the global MAC parameter structure. + + \return eHalStatus +----------------------------------------------------------------------------*/ +eHalStatus sme_QosClose(tpAniSirGlobal pMac) +{ + sme_QosSessionInfo *pSession; + sme_QosEdcaAcType ac; + v_U8_t sessionId; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: closing down SME-QoS", + __func__, __LINE__); + if(!pMac->psOffloadEnabled) + { + // deregister with PMC + if(!HAL_STATUS_SUCCESS( + pmcDeregisterDeviceStateUpdateInd(pMac, + sme_QosPmcDeviceStateUpdateInd))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot deregister pmcDeregisterDeviceStateUpdateInd()", + __func__, __LINE__); + } + if(!HAL_STATUS_SUCCESS( + pmcDeregisterPowerSaveCheck(pMac, sme_QosPmcCheckRoutine))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot deregister with pmcDeregisterPowerSaveCheck()", + __func__, __LINE__); + } + } + else + { + for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) + { + /* deregister with PMC */ + if(!HAL_STATUS_SUCCESS( + pmcOffloadDeregisterDeviceStateUpdateInd(pMac, sessionId, + sme_OffloadQosPmcDeviceStateUpdateInd))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot deregister DeviceStateUpdateInd()", + __func__, __LINE__); + } + if(!HAL_STATUS_SUCCESS( + pmcOffloadDeregisterPowerSaveCheck(pMac, sessionId, + sme_QosPmcOffloadCheckRoutine))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot deregister with PowerSaveCheck()", + __func__, __LINE__); + } + } + } + + //cleanup control block + //close the flow list + csrLLClose(&sme_QosCb.flow_list); + // shut down all of the sessions + for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) + { + pSession = &sme_QosCb.sessionInfo[sessionId]; + if (pSession == NULL) + continue; + + sme_QosInitACs(pMac, sessionId); + // this session doesn't require UAPSD + pSession->apsdMask = 0; + + pSession->uapsdAlreadyRequested = VOS_FALSE; + pSession->handoffRequested = VOS_FALSE; + pSession->readyForPowerSave = VOS_TRUE; + pSession->roamID = 0; + //need to clean up buffered req + sme_QosDeleteBufferedRequests(pMac, sessionId); + //need to clean up flows + sme_QosDeleteExistingFlows(pMac, sessionId); + + // Clean up the assoc info if already allocated + if (pSession->assocInfo.pBssDesc) { + vos_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + + // close the session's buffered command list + csrLLClose(&pSession->bufferedCommandList); + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + sme_QosStateTransition(sessionId, ac, SME_QOS_CLOSED); + } + pSession->sessionActive = VOS_FALSE; + pSession->readyForPowerSave = VOS_TRUE; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: closed down QoS", + __func__, __LINE__); + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosSetupReq() - The SME QoS API exposed to HDD to request for QoS + on a particular AC. This function should be called after a link has been + established, i.e. STA is associated with an AP etc. If the request involves + admission control on the requested AC, HDD needs to provide the necessary + Traffic Specification (TSPEC) parameters otherwise SME is going to use the + default params. + + \param hHal - The handle returned by macOpen. + \param sessionId - sessionId returned by sme_OpenSession. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info as defined above, provided by HDD + \param QoSCallback - The callback which is registered per flow while + requesting for QoS. Used for any notification for the + flow (i.e. setup success/failure/release) which needs to + be sent to HDD + \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS + notification (through the callback) to HDD + \param UPType - Useful only if HDD or any other upper layer module (BAP etc.) + looking for implicit QoS setup, in that + case, the pQoSInfo will be NULL & SME will know about the AC + (from the UP provided in this param) QoS is requested on + \param pQosFlowID - Identification per flow running on each AC generated by + SME. + It is only meaningful if the QoS setup for the flow is + successful + + \return eHAL_STATUS_SUCCESS - Setup is successful. + + Other status means Setup request failed + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosSetupReq(tHalHandle hHal, tANI_U32 sessionId, + sme_QosWmmTspecInfo * pQoSInfo, + sme_QosCallback QoSCallback, + void * HDDcontext, + sme_QosWmmUpType UPType, v_U32_t * pQosFlowID) +{ + sme_QosSessionInfo *pSession; + eHalStatus lock_status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + sme_QosStatusType status; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Setup requested by client on session %d", + __func__, __LINE__, + sessionId); + lock_status = sme_AcquireGlobalLock( &pMac->sme ); + if ( !HAL_STATUS_SUCCESS( lock_status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Unable to obtain lock", + __func__, __LINE__); + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + //Make sure the session is valid + if (!CSR_IS_SESSION_VALID( pMac, sessionId )) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Supplied Session ID %d is invalid", + __func__, __LINE__, + sessionId); + status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + else + { + //Make sure the session is active + pSession = &sme_QosCb.sessionInfo[sessionId]; + if (!pSession->sessionActive) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Supplied Session ID %d is inactive", + __func__, __LINE__, + sessionId); + status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + else + { + //Assign a Flow ID + *pQosFlowID = sme_QosAssignFlowId(); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS request on session %d assigned Flow ID %d", + __func__, __LINE__, + sessionId, *pQosFlowID); + //Call the internal function for QoS setup, + // adding a layer of abstraction + status = sme_QosInternalSetupReq(pMac, (v_U8_t)sessionId, pQoSInfo, + QoSCallback, HDDcontext, UPType, + *pQosFlowID, VOS_FALSE, VOS_FALSE); + } + } + sme_ReleaseGlobalLock( &pMac->sme ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS setup return status on session %d is %d", + __func__, __LINE__, + sessionId, status); + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosModifyReq() - The SME QoS API exposed to HDD to request for + modification of certain QoS params on a flow running on a particular AC. + This function should be called after a link has been established, i.e. STA is + associated with an AP etc. & a QoS setup has been successful for that flow. + If the request involves admission control on the requested AC, HDD needs to + provide the necessary Traffic Specification (TSPEC) parameters & SME might + start the renegotiation process through ADDTS. + + \param hHal - The handle returned by macOpen. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info as defined above, provided by HDD + \param QosFlowID - Identification per flow running on each AC generated by + SME. + It is only meaningful if the QoS setup for the flow has + been successful already + + \return SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful. + + Other status means request failed + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosModifyReq(tHalHandle hHal, + sme_QosWmmTspecInfo * pQoSInfo, + v_U32_t QosFlowID) +{ + eHalStatus lock_status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + sme_QosStatusType status; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Modify requested by client for Flow %d", + __func__, __LINE__, + QosFlowID); + lock_status = sme_AcquireGlobalLock( &pMac->sme ); + if ( !HAL_STATUS_SUCCESS( lock_status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Unable to obtain lock", + __func__, __LINE__); + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + //Call the internal function for QoS modify, adding a layer of abstraction + status = sme_QosInternalModifyReq(pMac, pQoSInfo, QosFlowID, VOS_FALSE); + sme_ReleaseGlobalLock( &pMac->sme ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Modify return status on Flow %d is %d", + __func__, __LINE__, + QosFlowID, status); + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosReleaseReq() - The SME QoS API exposed to HDD to request for + releasing a QoS flow running on a particular AC. This function should be + called only if a QoS is set up with a valid FlowID. HDD should invoke this + API only if an explicit request for QoS release has come from Application + + \param hHal - The handle returned by macOpen. + \param QosFlowID - Identification per flow running on each AC generated by SME + It is only meaningful if the QoS setup for the flow is + successful + + \return eHAL_STATUS_SUCCESS - Release is successful. + + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosReleaseReq(tHalHandle hHal, v_U32_t QosFlowID) +{ + eHalStatus lock_status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + sme_QosStatusType status; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Release requested by client for Flow %d", + __func__, __LINE__, + QosFlowID); + lock_status = sme_AcquireGlobalLock( &pMac->sme ); + if ( !HAL_STATUS_SUCCESS( lock_status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Unable to obtain lock", + __func__, __LINE__); + return SME_QOS_STATUS_RELEASE_FAILURE_RSP; + } + //Call the internal function for QoS release, adding a layer of abstraction + status = sme_QosInternalReleaseReq(pMac, QosFlowID, VOS_FALSE); + sme_ReleaseGlobalLock( &pMac->sme ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Release return status on Flow %d is %d", + __func__, __LINE__, + QosFlowID, status); + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosSetParams() - This function is used by HDD to provide the + default TSPEC params to SME. + + \param pMac - Pointer to the global MAC parameter structure. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info per AC as defined above, provided by HDD + + \return eHAL_STATUS_SUCCESS - Setparam is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosSetParams(tpAniSirGlobal pMac, sme_QosWmmTspecInfo * pQoSInfo) +{ + sme_QosEdcaAcType ac; + // find the AC + ac = sme_QosUpToAc(pQoSInfo->ts_info.up); + if(SME_QOS_EDCA_AC_MAX == ac) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Invalid AC %d (via UP %d)", + __func__, __LINE__, + ac, pQoSInfo->ts_info.up ); + return eHAL_STATUS_FAILURE; + } + //copy over the default params for this AC + sme_QosCb.def_QoSInfo[ac] = *pQoSInfo; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS default params set for AC %d (via UP %d)", + __func__, __LINE__, + ac, pQoSInfo->ts_info.up ); + return eHAL_STATUS_SUCCESS; +} + +void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + vos_mem_zero( &pCommand->u.qosCmd, sizeof( tGenericQosCmd ) ); + smeReleaseCommand( pMac, pCommand ); +} + +/*-------------------------------------------------------------------------- + \brief sme_QosMsgProcessor() - sme_ProcessMsg() calls this function for the + messages that are handled by SME QoS module. + + \param pMac - Pointer to the global MAC parameter structure. + \param msg_type - the type of msg passed by PE as defined in wniApi.h + \param pMsgBuf - a pointer to a buffer that maps to various structures base + on the message type. + The beginning of the buffer can always map to tSirSmeRsp. + + \return eHAL_STATUS_SUCCESS - Validation is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type, + void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tListElem *pEntry; + tSmeCmd *pCommand; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: msg = %d for QoS", + __func__, __LINE__, msg_type); + //switch on the msg type & make the state transition accordingly + switch(msg_type) + { + case eWNI_SME_ADDTS_RSP: + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if( pEntry ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( eSmeCommandAddTs == pCommand->command ) + { + status = sme_QosProcessAddTsRsp(pMac, pMsgBuf); + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + qosReleaseCommand( pMac, pCommand ); + } + smeProcessPendingQueue( pMac ); + } + } + break; + case eWNI_SME_DELTS_RSP: + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if( pEntry ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( eSmeCommandDelTs == pCommand->command ) + { + status = sme_QosProcessDelTsRsp(pMac, pMsgBuf); + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + qosReleaseCommand( pMac, pCommand ); + } + smeProcessPendingQueue( pMac ); + } + } + break; + case eWNI_SME_DELTS_IND: + status = sme_QosProcessDelTsInd(pMac, pMsgBuf); + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_AGGR_QOS_RSP: + status = sme_QosProcessAggrQosRsp(pMac, pMsgBuf); + break; +#endif + + default: + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: unknown msg type = %d", + __func__, __LINE__, msg_type); + break; + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosValidateParams() - The SME QoS API exposed to CSR to validate AP + capabilities regarding QoS support & any other QoS parameter validation. + + \param pMac - Pointer to the global MAC parameter structure. + \param pBssDesc - Pointer to the BSS Descriptor information passed down by + CSR to PE while issuing the Join request + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosValidateParams(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc) +{ + tDot11fBeaconIEs *pIes = NULL; + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: validation for QAP & APSD", + __func__, __LINE__); + do + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes))) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: csrGetParsedBssDescriptionIEs() failed", + __func__, __LINE__); + break; + } + //check if the AP is QAP & it supports APSD + if( !CSR_IS_QOS_BSS(pIes) ) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: AP doesn't support QoS", + __func__, __LINE__); + + break; + } + if(!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) && + !(pIes->WMMInfoAp.uapsd)) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: AP doesn't support APSD", + __func__, __LINE__); + break; + } + status = eHAL_STATUS_SUCCESS; + }while(0); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: validated with status = %d", + __func__, __LINE__, status); + if(pIes) + { + vos_mem_free(pIes); + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosCsrEventInd() - The QoS sub-module in SME expects notifications + from CSR when certain events occur as mentioned in sme_QosCsrEventIndType. + \param pMac - Pointer to the global MAC parameter structure. + \param ind - The event occurred of type sme_QosCsrEventIndType. + \param pEvent_info - Information related to the event + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosCsrEventInd(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosCsrEventIndType ind, + void *pEvent_info) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On Session %d Event %d received from CSR", + __func__, __LINE__, + sessionId, ind ); + switch(ind) + { + case SME_QOS_CSR_ASSOC_COMPLETE: + //expecting assoc info in pEvent_info + status = sme_QosProcessAssocCompleteEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_REASSOC_REQ: + //nothing expected in pEvent_info + status = sme_QosProcessReassocReqEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_REASSOC_COMPLETE: + //expecting assoc info in pEvent_info + status = sme_QosProcessReassocSuccessEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_REASSOC_FAILURE: + //nothing expected in pEvent_info + status = sme_QosProcessReassocFailureEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_DISCONNECT_REQ: + case SME_QOS_CSR_DISCONNECT_IND: + //nothing expected in pEvent_info + status = sme_QosProcessDisconnectEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_JOIN_REQ: + //nothing expected in pEvent_info + status = sme_QosProcessJoinReqEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_HANDOFF_ASSOC_REQ: + //nothing expected in pEvent_info + status = sme_QosProcessHandoffAssocReqEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_HANDOFF_COMPLETE: + //nothing expected in pEvent_info + status = sme_QosProcessHandoffSuccessEv(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_HANDOFF_FAILURE: + //nothing expected in pEvent_info + status = sme_QosProcessHandoffFailureEv(pMac, sessionId, pEvent_info); + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case SME_QOS_CSR_PREAUTH_SUCCESS_IND: + status = sme_QosProcessPreauthSuccessInd(pMac, sessionId, pEvent_info); + break; +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + case SME_QOS_CSR_SET_KEY_SUCCESS_IND: + status = sme_QosProcessSetKeySuccessInd(pMac, sessionId, pEvent_info); + break; +#endif +#endif + default: + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On Session %d Unknown Event %d received from CSR", + __func__, __LINE__, + sessionId, ind ); + break; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On Session %d processed Event %d with status %d", + __func__, __LINE__, + sessionId, ind, status ); + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosGetACMMask() - The QoS sub-module API to find out on which ACs + AP mandates Admission Control (ACM = 1) + (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored) + \param pMac - Pointer to the global MAC parameter structure. + \param pSirBssDesc - The event occurred of type sme_QosCsrEventIndType. + + \return a bit mask indicating for which ACs AP has ACM set to 1 + + \sa + + --------------------------------------------------------------------------*/ +v_U8_t sme_QosGetACMMask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes) +{ + sme_QosEdcaAcType ac; + v_U8_t acm_mask = 0; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked", + __func__, __LINE__); + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + if(sme_QosIsACM(pMac, pSirBssDesc, ac, pIes)) + { + acm_mask = acm_mask | (1 << (SME_QOS_EDCA_AC_VO - ac)); + } + + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: mask is %d", + __func__, __LINE__, acm_mask); + return acm_mask; +} +/*-------------------------------------------------------------------------- + Internal function definitions + ------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------- + \brief sme_QosInternalSetupReq() - The SME QoS internal setup request handling + function. + If the request involves admission control on the requested AC, HDD needs to + provide the necessary Traffic Specification (TSPEC) parameters otherwise SME + is going to use the default params. + + \param pMac - Pointer to the global MAC parameter structure. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info as defined above, provided by HDD + \param QoSCallback - The callback which is registered per flow while + requesting for QoS. Used for any notification for the + flow (i.e. setup success/failure/release) which needs to + be sent to HDD + \param HDDcontext - A cookie passed by HDD to be used by SME during any QoS + notification (through the callback) to HDD + \param UPType - Useful only if HDD or any other upper layer module (BAP etc.) + looking for implicit QoS setup, in that + case, the pQoSInfo will be NULL & SME will know about the AC + (from the UP provided in this param) QoS is requested on + \param QosFlowID - Identification per flow running on each AC generated by + SME. + It is only meaningful if the QoS setup for the flow is + successful + \param buffered_cmd - tells us if the cmd was a buffered one or fresh from + client + + \return eHAL_STATUS_SUCCESS - Setup is successful. + + Other status means Setup request failed + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosInternalSetupReq(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo * pQoSInfo, + sme_QosCallback QoSCallback, + void * HDDcontext, + sme_QosWmmUpType UPType, + v_U32_t QosFlowID, + v_BOOL_t buffered_cmd, + v_BOOL_t hoRenewal) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + sme_QosWmmTspecInfo Tspec_Info; + sme_QosStates new_state = SME_QOS_CLOSED; + sme_QosFlowInfoEntry *pentry = NULL; + sme_QosCmdInfo cmd; + sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + v_U8_t tmask = 0; + v_U8_t new_tmask = 0; + sme_QosSearchInfo search_key; + v_BOOL_t bufferCommand; + eHalStatus hstatus; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for flow %d", + __func__, __LINE__, + sessionId, QosFlowID); + pSession = &sme_QosCb.sessionInfo[sessionId]; + // if caller sent an empty TSPEC, fill up with the default one + if(!pQoSInfo) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: %d: caller sent an empty QoS param list, using defaults", + __func__, __LINE__); + // find the AC with UPType passed in + ac = sme_QosUpToAc(UPType); + if(SME_QOS_EDCA_AC_MAX == ac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, + ac, UPType); + + return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP; + } + Tspec_Info = sme_QosCb.def_QoSInfo[ac]; + } + else + { + // find the AC + ac = sme_QosUpToAc(pQoSInfo->ts_info.up); + if(SME_QOS_EDCA_AC_MAX == ac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, + ac, pQoSInfo->ts_info.up); + + return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP; + } + //validate QoS params + if(!sme_QosValidateRequestedParams(pMac, pQoSInfo, sessionId)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid params", + __func__, __LINE__); + return SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP; + } + Tspec_Info = *pQoSInfo; + } + pACInfo = &pSession->ac_info[ac]; + /* Need to vote off power save for the duration of this request */ + pSession->readyForPowerSave = VOS_FALSE; + // assume we won't have to (re)buffer the command + bufferCommand = VOS_FALSE; + + /* + * Check to consider the following flowing scenario Addts request is pending + * on one AC, while APSD requested on another which needs a reassoc. + * Will buffer a request if Addts is pending on any AC, which will safeguard + * the above scenario, & also won't confuse PE with back to back Addts or + * Addts followed by Reassoc. + */ + if(sme_QosIsRspPending(sessionId, ac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: buffering the setup request for flow %d in state %d " + "since another request is pending", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + bufferCommand = VOS_TRUE; + } + else + { + // make sure we are in full power so that we can issue + // an AddTS or reassoc if necessary + if(!pMac->psOffloadEnabled) + { + hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback, + pSession, eSME_REASON_OTHER); + } + else + { + hstatus = pmcOffloadRequestFullPower(pMac, sessionId, + sme_QosPmcOffloadFullPowerCallback, + pSession, eSME_REASON_OTHER); + } + + if( eHAL_STATUS_PMC_PENDING == hstatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: buffering the setup request for flow %d in state %d, " + "waiting for full power", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + bufferCommand = VOS_TRUE; + } + } + if (bufferCommand) + { + // we need to buffer the command + cmd.command = SME_QOS_SETUP_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.setupCmdInfo.HDDcontext = HDDcontext; + cmd.u.setupCmdInfo.QoSInfo = Tspec_Info; + cmd.u.setupCmdInfo.QoSCallback = QoSCallback; + cmd.u.setupCmdInfo.UPType = UPType; + cmd.u.setupCmdInfo.hoRenewal = hoRenewal; + cmd.u.setupCmdInfo.QosFlowID = QosFlowID; + hstatus = sme_QosBufferCmd(&cmd, buffered_cmd); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the setup request in state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to buffer the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Buffered setup request for flow = %d", + __func__, __LINE__, + QosFlowID); + return SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + } + + //get into the state m/c to see if the request can be granted + switch(pACInfo->curr_state) + { + case SME_QOS_LINK_UP: + //call the internal qos setup logic to decide on if the + // request is NOP, or need reassoc for APSD and/or need to send out ADDTS + status = sme_QosSetup(pMac, sessionId, &Tspec_Info, ac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_LINK_UP " + "sme_QosSetup returned with status %d", + __func__, __LINE__, + sessionId, ac, status); + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) + { + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + if((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)|| + (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + // we received an expected "good" status + //create an entry in the flow list + pentry = vos_mem_malloc(sizeof(*pentry)); + if (!pentry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the new " + "entry in the Flow List", + __func__, __LINE__); + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + pentry->ac_type = ac; + pentry->HDDcontext = HDDcontext; + pentry->QoSCallback = QoSCallback; + pentry->hoRenewal = hoRenewal; + pentry->QosFlowID = QosFlowID; + pentry->sessionId = sessionId; + // since we are in state SME_QOS_LINK_UP this must be the + // first TSPEC on this AC, so use index 0 (mask bit 1) + pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0] = Tspec_Info; + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) + { + if(pACInfo->tspec_mask_status && + !pACInfo->reassoc_pending) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d with AC %d in state " + "SME_QOS_LINK_UP tspec_mask_status is %d " + "but should not be set yet", + __func__, __LINE__, + sessionId, ac, pACInfo->tspec_mask_status); + VOS_ASSERT(0); + vos_mem_free(pentry); + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET; + if(!pACInfo->reassoc_pending) + { + // we didn't request for reassoc, it must be a tspec negotiation + pACInfo->tspec_pending = 1; + } + + pentry->reason = SME_QOS_REASON_SETUP; + new_state = SME_QOS_REQUESTED; + } + else + { + // SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP or + // SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY + pentry->reason = SME_QOS_REASON_REQ_SUCCESS; + new_state = SME_QOS_QOS_ON; + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET; + pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] = Tspec_Info; + if(buffered_cmd && !pentry->hoRenewal) + { + QoSCallback(pMac, HDDcontext, + &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + status, + pentry->QosFlowID); + } + pentry->hoRenewal = VOS_FALSE; + } + pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]++; + + //indicate on which index the flow entry belongs to & add it to the + //Flow List at the end + pentry->tspec_mask = pACInfo->tspec_mask_status; + pentry->QoSInfo = Tspec_Info; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Creating entry on session %d at %p with flowID %d", + __func__, __LINE__, + sessionId, pentry, QosFlowID); + csrLLInsertTail(&sme_QosCb.flow_list, &pentry->link, VOS_TRUE); + } + else + { + // unexpected status returned by sme_QosSetup() + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_QosSetup", + __func__, __LINE__, + sessionId, status); + new_state = pACInfo->curr_state; + if(buffered_cmd && hoRenewal) + { + QoSCallback(pMac, HDDcontext, + &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + SME_QOS_STATUS_RELEASE_QOS_LOST_IND, + QosFlowID); + } + } + break; + case SME_QOS_HANDOFF: + case SME_QOS_REQUESTED: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: Buffering setup request for flow %d in state = %d", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + //buffer cmd + cmd.command = SME_QOS_SETUP_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.setupCmdInfo.HDDcontext = HDDcontext; + cmd.u.setupCmdInfo.QoSInfo = Tspec_Info; + cmd.u.setupCmdInfo.QoSCallback = QoSCallback; + cmd.u.setupCmdInfo.UPType = UPType; + cmd.u.setupCmdInfo.hoRenewal = hoRenewal; + cmd.u.setupCmdInfo.QosFlowID = QosFlowID; + hstatus = sme_QosBufferCmd(&cmd, buffered_cmd); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d couldn't buffer the setup " + "request for flow %d in state = %d", + __func__, __LINE__, + sessionId, QosFlowID, pACInfo->curr_state ); + /* Unable to buffer the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + new_state = pACInfo->curr_state; + break; + case SME_QOS_QOS_ON: + + //check if multiple flows running on the ac + if((pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] > 0)|| + (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0)) + { + //do we need to care about the case where APSD needed on ACM = 0 below? + if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) || + sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: tspec_mask_status = %d for AC = %d", + __func__, __LINE__, + pACInfo->tspec_mask_status, ac); + if(!pACInfo->tspec_mask_status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: tspec_mask_status can't be 0 for ac = %d in " + "state = %d", + __func__, __LINE__, + ac, pACInfo->curr_state); + VOS_ASSERT(0); + /* Unable to buffer the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return status; + } + /* Flow aggregation */ + if ( ((pACInfo->tspec_mask_status > 0) && + (pACInfo->tspec_mask_status <= SME_QOS_TSPEC_INDEX_MAX)) ) + { + /* + * Either of upstream, downstream or bidirectional + * flows are present. If either of new stream or current stream is + * for bidirectional, aggregate the new stream with the current + * streams present and send out aggregated Tspec. + */ + if((Tspec_Info.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) || + (pACInfo->curr_QoSInfo[pACInfo->tspec_mask_status - 1]. + ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH)) + { + // Aggregate the new stream with the current stream(s). + tmask = pACInfo->tspec_mask_status; + } + /* None of new stream or current (aggregated) streams are for bidirectional. + * Check if the new stream direction matches the current stream direction. */ + else if(pACInfo->curr_QoSInfo[pACInfo->tspec_mask_status - 1]. + ts_info.direction == Tspec_Info.ts_info.direction) + { + // Aggregate the new stream with the current stream(s). + tmask = pACInfo->tspec_mask_status; + } + /* New stream is in different direction. */ + else + { + // No Aggregation. Mark the 2nd tpsec index also as active. + tmask = SME_QOS_TSPEC_MASK_CLEAR; + new_tmask = SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~pACInfo->tspec_mask_status; + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_2_SET; + } + } + else if(SME_QOS_TSPEC_MASK_BIT_1_2_SET == pACInfo->tspec_mask_status) + { + /* Both uplink and downlink streams are present. */ + /* If new stream is bidirectional, aggregate new stream with all existing + * upstreams and downstreams. Send out new aggregated tpsec. */ + if(Tspec_Info.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) + { + // Only one tspec index (0) will be in use after this aggregation. + tmask = SME_QOS_TSPEC_MASK_BIT_1_2_SET; + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_SET; + } + /* New stream is also uni-directional + * Find out the tsepc index with which it needs to be aggregated */ + else if(pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.direction != + Tspec_Info.ts_info.direction) + { + // Aggregate with 2nd tspec index + tmask = SME_QOS_TSPEC_MASK_BIT_2_SET; + } + else + { + // Aggregate with 1st tspec index + tmask = SME_QOS_TSPEC_MASK_BIT_1_SET; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: wrong tmask = %d", __func__, __LINE__, + pACInfo->tspec_mask_status ); + } + } + else + { + //ACM = 0 + // We won't be sending a TSPEC to the AP but we still need + // to aggregate to calculate trigger frame parameters + tmask = SME_QOS_TSPEC_MASK_BIT_1_SET; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: tmask = %d, new_tmask = %d in state = %d", + __func__, __LINE__, + tmask, new_tmask, pACInfo->curr_state ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: tspec_mask_status = %d for AC = %d", + __func__, __LINE__, + pACInfo->tspec_mask_status, ac); + if(tmask) + { + // create the aggregate TSPEC + if(tmask != SME_QOS_TSPEC_MASK_BIT_1_2_SET) + { + hstatus = sme_QosAggregateParams(&Tspec_Info, + &pACInfo->curr_QoSInfo[tmask - 1], + &pACInfo->requested_QoSInfo[tmask - 1]); + } + else + { + /* Aggregate the new bidirectional stream with the existing upstreams and + * downstreams in tspec indices 0 and 1. */ + tmask = SME_QOS_TSPEC_MASK_BIT_1_SET; + + if((hstatus = sme_QosAggregateParams(&Tspec_Info, + &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + &pACInfo->requested_QoSInfo[tmask - 1])) + == eHAL_STATUS_SUCCESS) + { + hstatus = sme_QosAggregateParams(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1], + &pACInfo->requested_QoSInfo[tmask - 1], + NULL); + } + } + + if(!HAL_STATUS_SUCCESS(hstatus)) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: failed to aggregate params", + __func__, __LINE__); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + } + else + { + if (!(new_tmask > 0 && new_tmask <= SME_QOS_TSPEC_INDEX_MAX)) + { + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + tmask = new_tmask; + pACInfo->requested_QoSInfo[tmask-1] = Tspec_Info; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no flows running for ac = %d while in state = %d", + __func__, __LINE__, + ac, pACInfo->curr_state ); + VOS_ASSERT(0); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return status; + } + //although aggregating, make sure to request on the correct UP,TID,PSB and direction + pACInfo->requested_QoSInfo[tmask - 1].ts_info.up = Tspec_Info.ts_info.up; + pACInfo->requested_QoSInfo[tmask - 1].ts_info.tid = Tspec_Info.ts_info.tid; + pACInfo->requested_QoSInfo[tmask - 1].ts_info.direction = Tspec_Info.ts_info.direction; + pACInfo->requested_QoSInfo[tmask - 1].ts_info.psb = Tspec_Info.ts_info.psb; + status = sme_QosSetup(pMac, sessionId, + &pACInfo->requested_QoSInfo[tmask - 1], ac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON " + "sme_QosSetup returned with status %d", + __func__, __LINE__, + sessionId, ac, status); + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) + { + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + if((SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status)|| + (SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + // we received an expected "good" status + //create an entry in the flow list + pentry = (sme_QosFlowInfoEntry *) vos_mem_malloc(sizeof(*pentry)); + if (!pentry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the new " + "entry in the Flow List", + __func__, __LINE__); + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + pentry->ac_type = ac; + pentry->HDDcontext = HDDcontext; + pentry->QoSCallback = QoSCallback; + pentry->hoRenewal = hoRenewal; + pentry->QosFlowID = QosFlowID; + pentry->sessionId = sessionId; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Creating flow %d", + __func__, __LINE__, + QosFlowID); + if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status)|| + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + new_state = pACInfo->curr_state; + pentry->reason = SME_QOS_REASON_REQ_SUCCESS; + pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] = + pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0]; + if(buffered_cmd && !pentry->hoRenewal) + { + QoSCallback(pMac, HDDcontext, + &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + status, + pentry->QosFlowID); + } + if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) + { + // if we are not in handoff, then notify all flows on + // this AC that the aggregate TSPEC may have changed + if(!pentry->hoRenewal) + { + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + hstatus = sme_QosFindAllInFlowList(pMac, search_key, + sme_QosSetupFnp); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't notify other " + "entries on this AC =%d", + __func__, __LINE__, ac); + } + } + } + pentry->hoRenewal = VOS_FALSE; + } + else + { + // SME_QOS_STATUS_SETUP_REQ_PENDING_RSP + new_state = SME_QOS_REQUESTED; + pentry->reason = SME_QOS_REASON_SETUP; + //Need this info when addts comes back from PE to know on + //which index of the AC the request was from + pACInfo->tspec_pending = tmask; + } + pACInfo->num_flows[tmask - 1]++; + //indicate on which index the flow entry belongs to & add it to the + //Flow List at the end + pentry->tspec_mask = tmask; + pentry->QoSInfo = Tspec_Info; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d creating entry at %p with flowID %d", + __func__, __LINE__, + sessionId, pentry, QosFlowID); + csrLLInsertTail(&sme_QosCb.flow_list, &pentry->link, VOS_TRUE); + } + else + { + // unexpected status returned by sme_QosSetup() + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_QosSetup", + __func__, __LINE__, + sessionId, status); + new_state = pACInfo->curr_state; + } + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: setup requested in unexpected state = %d", + __func__, __LINE__, + pACInfo->curr_state); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + VOS_ASSERT(0); + new_state = pACInfo->curr_state; + } + + /* + * if current state is same as previous no need for transition, + * if we are doing reassoc & we are already in handoff state, no need to + * move to requested state. But make sure to set the previous state as + * requested state + */ + if((new_state != pACInfo->curr_state)&& + (!(pACInfo->reassoc_pending && + (SME_QOS_HANDOFF == pACInfo->curr_state)))) + { + sme_QosStateTransition(sessionId, ac, new_state); + } + + if(pACInfo->reassoc_pending && + (SME_QOS_HANDOFF == pACInfo->curr_state)) + { + pACInfo->prev_state = SME_QOS_REQUESTED; + } + if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + (void)sme_QosProcessBufferedCmd(sessionId); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosInternalModifyReq() - The SME QoS internal function to request + for modification of certain QoS params on a flow running on a particular AC. + If the request involves admission control on the requested AC, HDD needs to + provide the necessary Traffic Specification (TSPEC) parameters & SME might + start the renegotiation process through ADDTS. + + \param pMac - Pointer to the global MAC parameter structure. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info as defined above, provided by HDD + \param QosFlowID - Identification per flow running on each AC generated by + SME. + It is only meaningful if the QoS setup for the flow has + been successful already + + \return SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful. + + Other status means request failed + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosInternalModifyReq(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo * pQoSInfo, + v_U32_t QosFlowID, + v_BOOL_t buffered_cmd) +{ + tListElem *pEntry= NULL; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *pNewEntry= NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosEdcaAcType ac; + sme_QosStates new_state = SME_QOS_CLOSED; + sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + sme_QosWmmTspecInfo Aggr_Tspec_Info; + sme_QosSearchInfo search_key; + sme_QosCmdInfo cmd; + v_U8_t sessionId; + v_BOOL_t bufferCommand; + eHalStatus hstatus; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked for flow %d", + __func__, __LINE__, + QosFlowID); + + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.QosFlowID = QosFlowID; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_1; + search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY; + //go through the link list to find out the details on the flow + pEntry = sme_QosFindInFlowList(search_key); + if(!pEntry) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no match found for flowID = %d", + __func__, __LINE__, + QosFlowID); + return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP; + } + // find the AC + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + + sessionId = flow_info->sessionId; + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + + //validate QoS params + if(!sme_QosValidateRequestedParams(pMac, pQoSInfo, sessionId)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid params", + __func__, __LINE__); + return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP; + } + // For modify, make sure that direction, TID and UP are not being altered + if((pQoSInfo->ts_info.direction != flow_info->QoSInfo.ts_info.direction) || + (pQoSInfo->ts_info.up != flow_info->QoSInfo.ts_info.up) || + (pQoSInfo->ts_info.tid != flow_info->QoSInfo.ts_info.tid)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Modification of direction/tid/up is not allowed", + __func__, __LINE__); + + return SME_QOS_STATUS_MODIFY_SETUP_INVALID_PARAMS_RSP; + } + + //should not be same as previous ioctl parameters + if ((pQoSInfo->nominal_msdu_size == flow_info->QoSInfo.nominal_msdu_size) && + (pQoSInfo->maximum_msdu_size == flow_info->QoSInfo.maximum_msdu_size) && + (pQoSInfo->min_data_rate == flow_info->QoSInfo.min_data_rate) && + (pQoSInfo->mean_data_rate == flow_info->QoSInfo.mean_data_rate) && + (pQoSInfo->peak_data_rate == flow_info->QoSInfo.peak_data_rate) && + (pQoSInfo->min_service_interval == + flow_info->QoSInfo.min_service_interval) && + (pQoSInfo->max_service_interval == + flow_info->QoSInfo.max_service_interval) && + (pQoSInfo->inactivity_interval == + flow_info->QoSInfo.inactivity_interval) && + (pQoSInfo->suspension_interval == + flow_info->QoSInfo.suspension_interval) && + (pQoSInfo->surplus_bw_allowance == + flow_info->QoSInfo.surplus_bw_allowance)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: the addts parameters are same as last request," + "dropping the current request", + __func__, __LINE__); + + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + + /* Need to vote off power save for the duration of this request */ + pSession->readyForPowerSave = VOS_FALSE; + // assume we won't have to (re)buffer the command + bufferCommand = VOS_FALSE; + /* + * Check to consider the following flowing scenario Addts request is pending + * on one AC, while APSD requested on another which needs a reassoc. Will + * buffer a request if Addts is pending on any AC, which will safeguard the + * above scenario, & also won't confuse PE with back to back Addts or + * Addts followed by Reassoc. + */ + if(sme_QosIsRspPending(sessionId, ac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: buffering the modify request for flow %d in state %d " + "since another request is pending", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + bufferCommand = VOS_TRUE; + } + else + { + // make sure we are in full power so that we can issue + // an AddTS or reassoc if necessary + if(!pMac->psOffloadEnabled) + { + hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback, + pSession, eSME_REASON_OTHER); + } + else + { + hstatus = pmcOffloadRequestFullPower(pMac, sessionId, + sme_QosPmcOffloadFullPowerCallback, + pSession, eSME_REASON_OTHER); + } + + if( eHAL_STATUS_PMC_PENDING == hstatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: buffering the modify request for flow %d in state %d, " + "waiting for full power", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + bufferCommand = VOS_TRUE; + } + } + if (bufferCommand) + { + // we need to buffer the command + cmd.command = SME_QOS_MODIFY_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.modifyCmdInfo.QosFlowID = QosFlowID; + cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo; + hstatus = sme_QosBufferCmd(&cmd, buffered_cmd); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the modify request in state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to buffer the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Buffered modify request for flow = %d", + __func__, __LINE__, + QosFlowID); + return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + } + //get into the stat m/c to see if the request can be granted + switch(pACInfo->curr_state) + { + case SME_QOS_QOS_ON: + //save the new params adding a new (duplicate) entry in the Flow List + //Once we have decided on OTA exchange needed or not we can delete the + //original one from the List + pNewEntry = (sme_QosFlowInfoEntry *) vos_mem_malloc(sizeof(*pNewEntry)); + if (!pNewEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the new " + "entry in the Flow List", + __func__, __LINE__); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + pNewEntry->ac_type = ac; + pNewEntry->sessionId = sessionId; + pNewEntry->HDDcontext = flow_info->HDDcontext; + pNewEntry->QoSCallback = flow_info->QoSCallback; + pNewEntry->QosFlowID = flow_info->QosFlowID; + pNewEntry->reason = SME_QOS_REASON_MODIFY_PENDING; + //since it is a modify request, use the same index on which the flow + //entry originally was running & add it to the Flow List at the end + pNewEntry->tspec_mask = flow_info->tspec_mask; + pNewEntry->QoSInfo = *pQoSInfo; + //update the entry from Flow List which needed to be modified + flow_info->reason = SME_QOS_REASON_MODIFY; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d creating modified " + "entry at %p with flowID %d", + __func__, __LINE__, + sessionId, pNewEntry, pNewEntry->QosFlowID); + //add the new entry under construction to the Flow List + csrLLInsertTail(&sme_QosCb.flow_list, &pNewEntry->link, VOS_TRUE); + //update TSPEC with the new param set + hstatus = sme_QosUpdateParams(sessionId, + ac, pNewEntry->tspec_mask, + &Aggr_Tspec_Info); + if(HAL_STATUS_SUCCESS(hstatus)) + { + pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1] = Aggr_Tspec_Info; + //if ACM, send out a new ADDTS + status = sme_QosSetup(pMac, sessionId, + &pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1], + ac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON " + "sme_QosSetup returned with status %d", + __func__, __LINE__, + sessionId, ac, status); + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) + { + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) + { + new_state = SME_QOS_REQUESTED; + status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + pACInfo->tspec_pending = pNewEntry->tspec_mask; + } + else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + new_state = SME_QOS_QOS_ON; + + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //delete the original entry in FLOW list which got modified + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + hstatus = sme_QosFindAllInFlowList(pMac, search_key, + sme_QosModifyFnp); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP != status) + { + pACInfo->curr_QoSInfo[pNewEntry->tspec_mask -1] = + pACInfo->requested_QoSInfo[pNewEntry->tspec_mask -1]; + if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) + { + status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY; + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + hstatus = sme_QosFindAllInFlowList(pMac, search_key, + sme_QosModificationNotifyFnp); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't notify other " + "entries on this AC =%d", + __func__, __LINE__, ac); + } + } + else if(SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) + { + status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP; + } + } + if(buffered_cmd) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[pNewEntry->tspec_mask -1], + status, + flow_info->QosFlowID); + } + + } + else + { + // unexpected status returned by sme_QosSetup() + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_QosSetup", + __func__, __LINE__, + sessionId, status); + new_state = SME_QOS_QOS_ON; + } + } + else + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosUpdateParams() failed", + __func__, __LINE__); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + new_state = SME_QOS_LINK_UP; + } + /* if we are doing reassoc & we are already in handoff state, no need + to move to requested state. But make sure to set the previous state + as requested state + */ + if(!(pACInfo->reassoc_pending && + (SME_QOS_HANDOFF == pACInfo->curr_state))) + { + sme_QosStateTransition(sessionId, ac, new_state); + } + else + { + pACInfo->prev_state = SME_QOS_REQUESTED; + } + break; + case SME_QOS_HANDOFF: + case SME_QOS_REQUESTED: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: Buffering modify request for flow %d in state = %d", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + //buffer cmd + cmd.command = SME_QOS_MODIFY_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.modifyCmdInfo.QosFlowID = QosFlowID; + cmd.u.modifyCmdInfo.QoSInfo = *pQoSInfo; + hstatus = sme_QosBufferCmd(&cmd, buffered_cmd); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the modify request in state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + case SME_QOS_LINK_UP: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: modify requested in unexpected state = %d", + __func__, __LINE__, + pACInfo->curr_state); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + break; + } + if((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + (void)sme_QosProcessBufferedCmd(sessionId); + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosInternalReleaseReq() - The SME QoS internal function to request + for releasing a QoS flow running on a particular AC. + + \param pMac - Pointer to the global MAC parameter structure. + \param QosFlowID - Identification per flow running on each AC generated by SME + It is only meaningful if the QoS setup for the flow is + successful + + \return eHAL_STATUS_SUCCESS - Release is successful. + + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosInternalReleaseReq(tpAniSirGlobal pMac, + v_U32_t QosFlowID, + v_BOOL_t buffered_cmd) +{ + tListElem *pEntry= NULL; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosFlowInfoEntry *pDeletedFlow = NULL; + sme_QosEdcaAcType ac; + sme_QosStates new_state = SME_QOS_CLOSED; + sme_QosStatusType status = SME_QOS_STATUS_RELEASE_FAILURE_RSP; + sme_QosWmmTspecInfo Aggr_Tspec_Info; + sme_QosSearchInfo search_key; + sme_QosCmdInfo cmd; + tCsrRoamModifyProfileFields modifyProfileFields; + v_BOOL_t deltsIssued = VOS_FALSE; + v_U8_t sessionId; + v_BOOL_t bufferCommand; + eHalStatus hstatus; + v_BOOL_t biDirectionalFlowsPresent = VOS_FALSE; + v_BOOL_t uplinkFlowsPresent = VOS_FALSE; + v_BOOL_t downlinkFlowsPresent = VOS_FALSE; + tListElem *pResult= NULL; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked for flow %d", + __func__, __LINE__, + QosFlowID); + + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.QosFlowID = QosFlowID; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_1; + search_key.sessionId = SME_QOS_SEARCH_SESSION_ID_ANY; + //go through the link list to find out the details on the flow + pEntry = sme_QosFindInFlowList(search_key); + + if(!pEntry) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no match found for flowID = %d", + __func__, __LINE__, + QosFlowID); + return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP; + } + // find the AC + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + sessionId = flow_info->sessionId; + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + /* Need to vote off power save for the duration of this request */ + pSession->readyForPowerSave = VOS_FALSE; + // assume we won't have to (re)buffer the command + bufferCommand = VOS_FALSE; + /* + * Check to consider the following flowing scenario Addts request is pending + * on one AC, while APSD requested on another which needs a reassoc. + * Will buffer a request if Addts is pending on any AC, which will safeguard + * the above scenario, & also won't confuse PE with back to back Addts or + * Addts followed by Reassoc. + */ + if(sme_QosIsRspPending(sessionId, ac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: buffering the release request for flow %d in state %d " + "since another request is pending", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + bufferCommand = VOS_TRUE; + } + else + { + // make sure we are in full power so that we can issue + // a DelTS or reassoc if necessary + if(!pMac->psOffloadEnabled) + { + hstatus = pmcRequestFullPower(pMac, sme_QosPmcFullPowerCallback, + pSession, eSME_REASON_OTHER); + } + else + { + hstatus = pmcOffloadRequestFullPower(pMac, sessionId, + sme_QosPmcOffloadFullPowerCallback, + pSession, eSME_REASON_OTHER); + } + + if( eHAL_STATUS_PMC_PENDING == hstatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: buffering the release request for flow %d in state %d, " + "waiting for full power", + __func__, __LINE__, + QosFlowID, pACInfo->curr_state ); + bufferCommand = VOS_TRUE; + } + } + if (bufferCommand) + { + // we need to buffer the command + cmd.command = SME_QOS_RELEASE_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.releaseCmdInfo.QosFlowID = QosFlowID; + hstatus = sme_QosBufferCmd(&cmd, buffered_cmd); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the release request in state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_RELEASE_FAILURE_RSP; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Buffered release request for flow = %d", + __func__, __LINE__, + QosFlowID); + return SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP; + } + //get into the stat m/c to see if the request can be granted + switch(pACInfo->curr_state) + { + case SME_QOS_QOS_ON: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: tspec_mask_status = %d for AC = %d with " + "entry tspec_mask = %d", + __func__, __LINE__, + pACInfo->tspec_mask_status, ac, flow_info->tspec_mask); + + //check if multiple flows running on the ac + if(pACInfo->num_flows[flow_info->tspec_mask - 1] > 1) + { + //don't want to include the flow in the new TSPEC on which release + //is requested + flow_info->reason = SME_QOS_REASON_RELEASE; + + /* + * Check if the flow being released is for bi-directional. + * Following flows may present in the system. + * a) bi-directional flows + * b) uplink flows + * c) downlink flows. + * If the flow being released is for bidirectional, splitting of + * existing streams into two tspec indices is required in case ff (b), + * (c) are present and not (a). + * In case if split occurs, all upstreams are aggregated into tspec + * index 0, downstreams are aggregated into tspec index 1 and two + * tspec requests for (aggregated) upstream(s) followed by + * (aggregated) downstream(s) is sent to AP. + */ + if(flow_info->QoSInfo.ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) + { + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_4; + search_key.sessionId = sessionId; + search_key.direction = SME_QOS_WMM_TS_DIR_BOTH; + pResult = sme_QosFindInFlowList(search_key); + if(pResult) + biDirectionalFlowsPresent = VOS_TRUE; + + if(!biDirectionalFlowsPresent) + { + // The only existing bidirectional flow is being released + + // Check if uplink flows exist + search_key.direction = SME_QOS_WMM_TS_DIR_UPLINK; + pResult = sme_QosFindInFlowList(search_key); + if(pResult) + uplinkFlowsPresent = VOS_TRUE; + + // Check if downlink flows exist + search_key.direction = SME_QOS_WMM_TS_DIR_DOWNLINK; + pResult = sme_QosFindInFlowList(search_key); + if(pResult) + downlinkFlowsPresent = VOS_TRUE; + + if(uplinkFlowsPresent && downlinkFlowsPresent) + { + // Need to split the uni-directional flows into SME_QOS_TSPEC_INDEX_0 and SME_QOS_TSPEC_INDEX_1 + + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + // Mark all downstream flows as using tspec index 1 + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_4; + search_key.sessionId = sessionId; + search_key.direction = SME_QOS_WMM_TS_DIR_DOWNLINK; + sme_QosUpdateTspecMask(sessionId, search_key, SME_QOS_TSPEC_MASK_BIT_2_SET); + + // Aggregate all downstream flows + hstatus = sme_QosUpdateParams(sessionId, + ac, SME_QOS_TSPEC_MASK_BIT_2_SET, + &Aggr_Tspec_Info); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d buffering the AddTS request " + "for AC %d in state %d as Addts is pending " + "on other Tspec index of this AC", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + + /* + * Buffer the (aggregated) tspec request for downstream flows. + * Please note that the (aggregated) tspec for upstream flows is + * sent out by the subsequent logic. + */ + cmd.command = SME_QOS_RESEND_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.resendCmdInfo.ac = ac; + cmd.u.resendCmdInfo.tspecMask = SME_QOS_TSPEC_MASK_BIT_2_SET; + cmd.u.resendCmdInfo.QoSInfo = Aggr_Tspec_Info; + pACInfo->requested_QoSInfo[SME_QOS_TSPEC_MASK_BIT_2_SET - 1] = Aggr_Tspec_Info; + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unable to buffer the AddTS " + "request for AC %d TSPEC %d in state %d", + __func__, __LINE__, + sessionId, ac, SME_QOS_TSPEC_MASK_BIT_2_SET, pACInfo->curr_state); + + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_BIT_1_2_SET; + + } + } + } + + /* In case of splitting of existing streams, + * tspec_mask will be pointing to tspec index 0 and + * aggregated tspec for upstream(s) is sent out here. */ + hstatus = sme_QosUpdateParams(sessionId, + ac, flow_info->tspec_mask, + &Aggr_Tspec_Info); + if(HAL_STATUS_SUCCESS(hstatus)) + { + pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1] = Aggr_Tspec_Info; + //if ACM, send out a new ADDTS + status = sme_QosSetup(pMac, sessionId, + &pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1], ac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON " + "sme_QosSetup returned with status %d", + __func__, __LINE__, + sessionId, ac, status); + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) + { + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) + { + new_state = SME_QOS_REQUESTED; + status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP; + pACInfo->tspec_pending = flow_info->tspec_mask; + } + else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + new_state = SME_QOS_QOS_ON; + pACInfo->num_flows[flow_info->tspec_mask - 1]--; + pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1] = + pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1]; + //delete the entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, + flow_info, QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + pDeletedFlow = flow_info; + if(SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) + { + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + hstatus = sme_QosFindAllInFlowList(pMac, search_key, + sme_QosSetupFnp); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't notify other " + "entries on this AC =%d", + __func__, __LINE__, ac); + } + } + status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP; + if(buffered_cmd) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + status, + flow_info->QosFlowID); + } + } + else + { + // unexpected status returned by sme_QosSetup() + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_QosSetup", + __func__, __LINE__, + sessionId, status); + new_state = SME_QOS_LINK_UP; + pACInfo->num_flows[flow_info->tspec_mask - 1]--; + pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1] = + pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1]; + //delete the entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d deleting entry at " + "%p with flowID %d", + __func__, __LINE__, + sessionId, flow_info, QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + pDeletedFlow = flow_info; + if(buffered_cmd) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + status, + flow_info->QosFlowID); + } + } + } + else + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosUpdateParams() failed", + __func__, __LINE__); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + new_state = SME_QOS_LINK_UP; + if(buffered_cmd) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + status, + flow_info->QosFlowID); + } + } + } + else + { + // this is the only flow aggregated in this TSPEC + status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP; +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + if (ac == SME_QOS_EDCA_AC_VO) + { + // Indicate to neighbor roam logic of the new required VO + // ac bandwidth requirement. + csrNeighborRoamIndicateVoiceBW( pMac, pACInfo->curr_QoSInfo[0].peak_data_rate, FALSE ); + } +#endif + //check if delts needs to be sent + if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) || + sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL)) + { + //check if other TSPEC for this AC is also in use + if(SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status) + { + // this is the only TSPEC active on this AC + // so indicate that we no longer require APSD + pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + //Also update modifyProfileFields.uapsd_mask in CSR for consistency + csrGetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields); + modifyProfileFields.uapsd_mask = pSession->apsdMask; + csrSetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields); + if(!pSession->apsdMask) + { + // this session no longer needs UAPSD + // do any sessions still require UAPSD? + if (!sme_QosIsUapsdActive()) + { + // No sessions require UAPSD so turn it off + // (really don't care when PMC stops it) + if(!pMac->psOffloadEnabled) + { + (void)pmcStopUapsd(pMac); + } + else + { + (void)pmcOffloadStopUapsd(pMac, sessionId); + } + } + } + } + if (SME_QOS_RELEASE_DEFAULT == pACInfo->relTrig) + { + //send delts + hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandDelTs, + NULL, ac, flow_info->tspec_mask); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosDelTsReq() failed", + __func__, __LINE__); + status = SME_QOS_STATUS_RELEASE_FAILURE_RSP; + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + else + { + pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET & + (~flow_info->tspec_mask); + deltsIssued = VOS_TRUE; + } + } + else + { + pSession->readyForPowerSave = VOS_TRUE; + pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET & + (~flow_info->tspec_mask); + deltsIssued = VOS_TRUE; + } + } + else if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac))) + { + //reassoc logic + csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields); + modifyProfileFields.uapsd_mask |= pSession->apsdMask; + modifyProfileFields.uapsd_mask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + if(!pSession->apsdMask) + { + // this session no longer needs UAPSD + // do any sessions still require UAPSD? + if (!sme_QosIsUapsdActive()) + { + // No sessions require UAPSD so turn it off + // (really don't care when PMC stops it) + if(!pMac->psOffloadEnabled) + { + (void)pmcStopUapsd(pMac); + } + else + { + (void)pmcOffloadStopUapsd(pMac, sessionId); + } + } + } + hstatus = sme_QosRequestReassoc(pMac, sessionId, + &modifyProfileFields, VOS_FALSE); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Reassoc failed", + __func__, __LINE__); + status = SME_QOS_STATUS_RELEASE_FAILURE_RSP; + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + else + { + pACInfo->reassoc_pending = VOS_FALSE;//no need to wait + pACInfo->prev_state = SME_QOS_LINK_UP; + pACInfo->tspec_pending = 0; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: nothing to do for AC = %d", + __func__, __LINE__, ac); + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + + if (SME_QOS_RELEASE_BY_AP == pACInfo->relTrig) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + SME_QOS_STATUS_RELEASE_QOS_LOST_IND, + flow_info->QosFlowID); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + } + else if(buffered_cmd) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + NULL, + status, + flow_info->QosFlowID); + } + + if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == status) + { + break; + } + + if(((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->tspec_mask) > 0) && + ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~flow_info->tspec_mask) <= + SME_QOS_TSPEC_INDEX_MAX)) + { + if(pACInfo->num_flows[(SME_QOS_TSPEC_MASK_BIT_1_2_SET & + ~flow_info->tspec_mask) - 1] > 0) + { + new_state = SME_QOS_QOS_ON; + } + else + { + new_state = SME_QOS_LINK_UP; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Exceeded the array bounds of pACInfo->num_flows", + __func__, __LINE__); + VOS_ASSERT (0); + return SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP; + } + + if(VOS_FALSE == deltsIssued) + { + vos_mem_zero(&pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + sizeof(sme_QosWmmTspecInfo)); + } + vos_mem_zero(&pACInfo->requested_QoSInfo[flow_info->tspec_mask - 1], + sizeof(sme_QosWmmTspecInfo)); + pACInfo->num_flows[flow_info->tspec_mask - 1]--; + //delete the entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d deleting entry at %p with flowID %d", + __func__, __LINE__, + sessionId, flow_info, QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + pDeletedFlow = flow_info; + pACInfo->relTrig = SME_QOS_RELEASE_DEFAULT; + } + /* if we are doing reassoc & we are already in handoff state, no need + to move to requested state. But make sure to set the previous state + as requested state + */ + if(SME_QOS_HANDOFF != pACInfo->curr_state) + { + sme_QosStateTransition(sessionId, ac, new_state); + } + if(pACInfo->reassoc_pending) + { + pACInfo->prev_state = SME_QOS_REQUESTED; + } + break; + case SME_QOS_HANDOFF: + case SME_QOS_REQUESTED: + //buffer cmd + cmd.command = SME_QOS_RELEASE_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.releaseCmdInfo.QosFlowID = QosFlowID; + hstatus = sme_QosBufferCmd(&cmd, buffered_cmd); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the release request in state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_RELEASE_FAILURE_RSP; + } + status = SME_QOS_STATUS_RELEASE_REQ_PENDING_RSP; + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + case SME_QOS_LINK_UP: + default: + //print error msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: release request in unexpected state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + VOS_ASSERT(0); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + break; + } + // if we deleted a flow, reclaim the memory + if (pDeletedFlow) + { + vos_mem_free(pDeletedFlow); + } + if((SME_QOS_STATUS_RELEASE_SUCCESS_RSP == status)) + { + (void)sme_QosProcessBufferedCmd(sessionId); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosSetup() - The internal qos setup function which has the + intelligence if the request is NOP, or for APSD and/or need to send out ADDTS. + It also does the sanity check for QAP, AP supports APSD etc. + \param pMac - Pointer to the global MAC parameter structure. + \param sessionId - Session upon which setup is being performed + \param pTspec_Info - Pointer to sme_QosWmmTspecInfo which contains the WMM + TSPEC related info as defined above + \param ac - Enumeration of the various EDCA Access Categories. + + \return SME_QOS_STATUS_SETUP_SUCCESS_RSP if the setup is successful + The logic used in the code might be confusing. Trying to cover all the cases + here. + AP supports App wants ACM = 1 Already set APSD Result + | 0 | 0 | 0 | 0 | NO ACM NO APSD + | 0 | 0 | 0 | 1 | NO ACM NO APSD/INVALID + | 0 | 0 | 1 | 0 | ADDTS + | 0 | 0 | 1 | 1 | ADDTS + | 0 | 1 | 0 | 0 | FAILURE + | 0 | 1 | 0 | 1 | INVALID + | 0 | 1 | 1 | 0 | ADDTS + | 0 | 1 | 1 | 1 | ADDTS + | 1 | 0 | 0 | 0 | NO ACM NO APSD + | 1 | 0 | 0 | 1 | NO ACM NO APSD + | 1 | 0 | 1 | 0 | ADDTS + | 1 | 0 | 1 | 1 | ADDTS + | 1 | 1 | 0 | 0 | REASSOC + | 1 | 1 | 0 | 1 | NOP: APSD SET ALREADY + | 1 | 1 | 1 | 0 | ADDTS + | 1 | 1 | 1 | 1 | ADDTS + + \sa + + --------------------------------------------------------------------------*/ +sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo *pTspec_Info, + sme_QosEdcaAcType ac) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosStatusType status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + tDot11fBeaconIEs *pIes = NULL; + tCsrRoamModifyProfileFields modifyProfileFields; + eHalStatus hstatus; + if( !CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Session Id %d is invalid", + __func__, __LINE__, + sessionId); + return status; + } + pSession = &sme_QosCb.sessionInfo[sessionId]; + if( !pSession->sessionActive ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Session %d is inactive", + __func__, __LINE__, + sessionId); + return status; + } + if(!pSession->assocInfo.pBssDesc) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Session %d has an Invalid BSS Descriptor", + __func__, __LINE__, + sessionId); + return status; + } + hstatus = csrGetParsedBssDescriptionIEs(pMac, + pSession->assocInfo.pBssDesc, + &pIes); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unable to parse BSS IEs", + __func__, __LINE__, + sessionId); + return status; + } + + /* success so pIes was allocated */ + + if( !CSR_IS_QOS_BSS(pIes) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AP doesn't support QoS", + __func__, __LINE__, + sessionId); + vos_mem_free(pIes); + //notify HDD through the synchronous status msg + return SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: %d: UAPSD/PSB set %d: ", __func__, __LINE__, + pTspec_Info->ts_info.psb); + + pACInfo = &pSession->ac_info[ac]; + do + { + // is ACM enabled for this AC? + if(CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) || + sme_QosIsACM(pMac, pSession->assocInfo.pBssDesc, ac, NULL)) + { + // ACM is enabled for this AC so we must send an AddTS + if(pTspec_Info->ts_info.psb && + !(pMac->psOffloadEnabled && pMac->pmcOffloadInfo.pmc[sessionId].UapsdEnabled) + && (!pMac->pmc.uapsdEnabled )) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Request is looking for APSD but PMC doesn't " + "have support for APSD", + __func__, __LINE__); + break; + } + + if (pTspec_Info->ts_info.psb && + !(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) && + !(pIes->WMMInfoAp.uapsd)) + { + // application is looking for APSD but AP doesn't support it + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AP doesn't support APSD", + __func__, __LINE__, + sessionId); + break; + } + + if(SME_QOS_MAX_TID == pTspec_Info->ts_info.tid) + { + //App didn't set TID, generate one + pTspec_Info->ts_info.tid = + (v_U8_t)(SME_QOS_WMM_UP_NC - pTspec_Info->ts_info.up); + } + //addts logic + hstatus = qosIssueCommand(pMac, sessionId, eSmeCommandAddTs, + pTspec_Info, ac, 0); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosAddTsReq() failed", + __func__, __LINE__); + break; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AddTS on AC %d is pending", + __func__, __LINE__, + sessionId, ac); + status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + break; + } + // ACM is not enabled for this AC + // Is the application looking for APSD? + if(0 == pTspec_Info->ts_info.psb) + { + //no, we don't need APSD + //but check the case, if the setup is called as a result of a release + // or modify which boils down to the fact that APSD was set on this AC + // but no longer needed - so we need a reassoc for the above case to + // let the AP know + if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac))) + { + // APSD was formerly enabled on this AC but is no longer required + // so we must reassociate + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d reassoc needed " + "to disable APSD on AC %d", + __func__, __LINE__, + sessionId, ac); + csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields); + modifyProfileFields.uapsd_mask |= pSession->apsdMask; + modifyProfileFields.uapsd_mask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + hstatus = sme_QosRequestReassoc(pMac, sessionId, + &modifyProfileFields, VOS_FALSE); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Unable to request reassociation", + __func__, __LINE__); + break; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d reassociation to enable " + "APSD on AC %d is pending", + __func__, __LINE__, + sessionId, ac); + status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + pACInfo->reassoc_pending = VOS_TRUE; + } + } + else + { + // we don't need APSD on this AC + // and we don't currently have APSD on this AC + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Request is not looking for APSD & Admission " + "Control isn't mandatory for the AC", + __func__, __LINE__); + //return success right away + status = SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP; + } + break; + } + else if(!(pIes->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD) && + !(pIes->WMMInfoAp.uapsd)) + { + // application is looking for APSD but AP doesn't support it + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AP doesn't support APSD", + __func__, __LINE__, + sessionId); + break; + } + else if(pSession->apsdMask & (1 << (SME_QOS_EDCA_AC_VO - ac))) + { + // application is looking for APSD + // and it is already enabled on this AC + status = SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Request is looking for APSD and it is already " + "set for the AC", + __func__, __LINE__); + break; + } + else + { + // application is looking for APSD + // but it is not enabled on this AC + // so we need to reassociate + if(pMac->pmc.uapsdEnabled || (pMac->psOffloadEnabled + && pMac->pmcOffloadInfo.pmc[sessionId].UapsdEnabled)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d reassoc needed " + "to enable APSD on AC %d", + __func__, __LINE__, + sessionId, ac); + //reassoc logic + // update the UAPSD mask to include the new + // AC on which APSD is requested + csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields); + modifyProfileFields.uapsd_mask |= pSession->apsdMask; + modifyProfileFields.uapsd_mask |= 1 << (SME_QOS_EDCA_AC_VO - ac); + hstatus = sme_QosRequestReassoc(pMac, sessionId, + &modifyProfileFields, VOS_FALSE); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Unable to request reassociation", + __func__, __LINE__); + break; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d reassociation to enable " + "APSD on AC %d is pending", + __func__, __LINE__, + sessionId, ac); + status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + pACInfo->reassoc_pending = VOS_TRUE; + } + } + else + { + //err msg: no support for APSD from PMC + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no support for APSD or BMPS from PMC", + __func__, __LINE__); + } + } + }while(0); + + vos_mem_free(pIes); + return status; +} + +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/* This is a dummy function now. But the purpose of me adding this was to + * delay the TSPEC processing till SET_KEY completes. This function can be + * used to do any SME_QOS processing after the SET_KEY. As of now, it is + * not required as we are ok with tspec getting programmed before set_key + * as the roam timings are measured without tspec in reassoc! + */ +eHalStatus sme_QosProcessSetKeySuccessInd(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "########### Set Key Complete #############"); + (void)sme_QosProcessBufferedCmd(sessionId); + return eHAL_STATUS_SUCCESS; +} +#endif + +#ifdef FEATURE_WLAN_ESE +/*-------------------------------------------------------------------------- + \brief sme_QosESESaveTspecResponse() - This function saves the TSPEC + parameters that came along in the TSPEC IE in the reassoc response + + \param pMac - Pointer to the global MAC parameter structure. + \param sessionId - SME session ID + \param pTspec - Pointer to the TSPEC IE from the reassoc rsp + \param ac - Access Category for which this TSPEC rsp is received + \param tspecIndex - flow/direction + + \return eHAL_STATUS_SUCCESS - Release is successful. + --------------------------------------------------------------------------*/ +eHalStatus sme_QosESESaveTspecResponse(tpAniSirGlobal pMac, v_U8_t sessionId, tDot11fIEWMMTSPEC *pTspec, v_U8_t ac, v_U8_t tspecIndex) +{ + tpSirAddtsRsp pAddtsRsp = &sme_QosCb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex]; + + ac = sme_QosUPtoACMap[pTspec->user_priority]; + + vos_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp)); + + pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP; + pAddtsRsp->length = sizeof(tSirAddtsRsp); + pAddtsRsp->rc = eSIR_SUCCESS; + pAddtsRsp->sessionId = sessionId; + pAddtsRsp->rsp.dialogToken = 0; + pAddtsRsp->rsp.status = eSIR_SUCCESS; + pAddtsRsp->rsp.wmeTspecPresent = pTspec->present; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Copy Tspec to local data structure ac=%d, tspecIdx=%d", + __func__, ac, tspecIndex); + + if (pAddtsRsp->rsp.wmeTspecPresent) + { + //Copy TSPEC params received in assoc response to addts response + ConvertWMMTSPEC(pMac, &pAddtsRsp->rsp.tspec, pTspec); + } + + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosESEProcessReassocTspecRsp() - This function processes the + WMM TSPEC IE in the reassoc response. Reassoc triggered as part of + ESE roaming to another ESE capable AP. If the TSPEC was added before + reassoc, as part of Call Admission Control, the reassoc req from the + STA would carry the TSPEC parameters which were already negotiated + with the older AP. + + \param pMac - Pointer to the global MAC parameter structure. + \param sessionId - SME session ID + \param pEven_info - Pointer to the smeJoinRsp structure + + \return eHAL_STATUS_SUCCESS - Release is successful. + --------------------------------------------------------------------------*/ +eHalStatus sme_QosESEProcessReassocTspecRsp(tpAniSirGlobal pMac, v_U8_t sessionId, void* pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + tDot11fIEWMMTSPEC *pTspecIE = NULL; + tCsrRoamSession *pCsrSession = NULL; + tCsrRoamConnectedInfo *pCsrConnectedInfo = NULL; + eHalStatus status = eHAL_STATUS_FAILURE; + v_U8_t ac, numTspec, cnt; + v_U8_t tspec_flow_index, tspec_mask_status; + v_U32_t tspecIeLen; + + pCsrSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pCsrSession) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } + + pCsrConnectedInfo = &pCsrSession->connectedInfo; + pSession = &sme_QosCb.sessionInfo[sessionId]; + + // Get the TSPEC IEs which came along with the reassoc response + // from the pbFrames pointer + pTspecIE = (tDot11fIEWMMTSPEC *)(pCsrConnectedInfo->pbFrames + pCsrConnectedInfo->nBeaconLength + + pCsrConnectedInfo->nAssocReqLength + pCsrConnectedInfo->nAssocRspLength + pCsrConnectedInfo->nRICRspLength); + + /* Get the number of tspecs Ies in the frame, the min length + should be at-least equal to the one TSPEC IE */ + tspecIeLen = pCsrConnectedInfo->nTspecIeLength; + if (tspecIeLen < sizeof(tDot11fIEWMMTSPEC)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("ESE Tspec IE len %d less than min %zu"), + tspecIeLen, sizeof(tDot11fIEWMMTSPEC)); + return eHAL_STATUS_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "TspecLen = %d, pbFrames = %p, pTspecIE = %p", + tspecIeLen, pCsrConnectedInfo->pbFrames, pTspecIE); + + numTspec = (tspecIeLen)/sizeof(tDot11fIEWMMTSPEC); + for(cnt=0; cntuser_priority); + if (ac >= SME_QOS_EDCA_AC_MAX) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("ac %d more than it`s max value"), ac); + return eHAL_STATUS_FAILURE; + } + pACInfo = &pSession->ac_info[ac]; + tspec_mask_status = pACInfo->tspec_mask_status; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("UP=%d, ac=%d, tspec_mask_status=%x"), + pTspecIE->user_priority, ac, tspec_mask_status ); + + for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++) { + if (tspec_mask_status & (1 << tspec_flow_index)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("Found Tspec entry flow = %d AC = %d"),tspec_flow_index, ac); + sme_QosESESaveTspecResponse(pMac, sessionId, pTspecIE, ac, tspec_flow_index); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("Not found Tspec entry flow = %d AC = %d"),tspec_flow_index, ac); + } + } + // Increment the pointer to point it to the next TSPEC IE + pTspecIE++; + } + + /* Send the Aggregated QoS request to HAL */ + status = sme_QosFTAggrQosReq(pMac,sessionId); + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosCopyTspecInfo() - This function copies the existing TSPEC + parameters from the source structure to the destination structure. + + \param pMac - Pointer to the global MAC parameter structure. + \param pTspec_Info - source structure + \param pTspec - destination structure + + \return void + --------------------------------------------------------------------------*/ +static void sme_QosCopyTspecInfo(tpAniSirGlobal pMac, sme_QosWmmTspecInfo *pTspec_Info, tSirMacTspecIE* pTspec) +{ + /* As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service + * Interval, Service Start Time, Suspension Interval and Delay Bound are + * all intended for HCCA operation and therefore must be set to zero*/ + pTspec->delayBound = pTspec_Info->delay_bound; + pTspec->inactInterval = pTspec_Info->inactivity_interval; + pTspec->length = SME_QOS_TSPEC_IE_LENGTH; + pTspec->maxBurstSz = pTspec_Info->max_burst_size; + pTspec->maxMsduSz = pTspec_Info->maximum_msdu_size; + pTspec->maxSvcInterval = pTspec_Info->max_service_interval; + pTspec->meanDataRate = pTspec_Info->mean_data_rate; + pTspec->mediumTime = pTspec_Info->medium_time; + pTspec->minDataRate = pTspec_Info->min_data_rate; + pTspec->minPhyRate = pTspec_Info->min_phy_rate; + pTspec->minSvcInterval = pTspec_Info->min_service_interval; + pTspec->nomMsduSz = pTspec_Info->nominal_msdu_size; + pTspec->peakDataRate = pTspec_Info->peak_data_rate; + pTspec->surplusBw = pTspec_Info->surplus_bw_allowance; + pTspec->suspendInterval = pTspec_Info->suspension_interval; + pTspec->svcStartTime = pTspec_Info->svc_start_time; + pTspec->tsinfo.traffic.direction = pTspec_Info->ts_info.direction; + + //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup + if (pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac)) { + pTspec->tsinfo.traffic.psb = pTspec_Info->ts_info.psb; + } else { + pTspec->tsinfo.traffic.psb = 0; + pTspec_Info->ts_info.psb = 0; + } + pTspec->tsinfo.traffic.tsid = pTspec_Info->ts_info.tid; + pTspec->tsinfo.traffic.userPrio = pTspec_Info->ts_info.up; + pTspec->tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA; + pTspec->tsinfo.traffic.burstSizeDefn = pTspec_Info->ts_info.burst_size_defn; + pTspec->tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy; + pTspec->type = SME_QOS_TSPEC_IE_TYPE; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: up = %d, tid = %d", + __func__, __LINE__, + pTspec_Info->ts_info.up, + pTspec_Info->ts_info.tid); +} + +/*-------------------------------------------------------------------------- + \brief sme_QosEseRetrieveTspecInfo() - This function is called by CSR + when try to create reassoc request message to PE - csrSendSmeReassocReqMsg + This functions get the existing tspec parameters to be included + in the reassoc request. + + \param pMac - Pointer to the global MAC parameter structure. + \param sessionId - SME session ID + \param pTspecInfo - Pointer to the structure to carry back the TSPEC parameters + + \return v_U8_t - number of existing negotiated TSPECs + --------------------------------------------------------------------------*/ +v_U8_t sme_QosEseRetrieveTspecInfo(tpAniSirGlobal pMac, v_U8_t sessionId, tTspecInfo *pTspecInfo) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t tspec_mask_status = 0; + v_U8_t tspec_pending_status = 0; + v_U8_t ac, numTspecs = 0; + tTspecInfo *pDstTspec = pTspecInfo; + + //TODO: Check if TSPEC has already been established, if not return + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + volatile v_U8_t tspec_index = 0; + + pACInfo = &pSession->ac_info[ac]; + tspec_pending_status = pACInfo->tspec_pending; + tspec_mask_status = pACInfo->tspec_mask_status; + + do { + if (tspec_mask_status & SME_QOS_TSPEC_MASK_BIT_1_SET) { + /* If a tspec status is pending, take requested_QoSInfo for RIC request, else use curr_QoSInfo + for the RIC request */ + if (tspec_pending_status & SME_QOS_TSPEC_MASK_BIT_1_SET) { + sme_QosCopyTspecInfo(pMac, &pACInfo->requested_QoSInfo[tspec_index], &pDstTspec->tspec); + } else { + sme_QosCopyTspecInfo(pMac, &pACInfo->curr_QoSInfo[tspec_index], &pDstTspec->tspec); + } + pDstTspec->valid = TRUE; + numTspecs++; + pDstTspec++; + } + tspec_mask_status >>= 1; + tspec_pending_status >>= 1; + tspec_index++; + } while (tspec_mask_status); + } + + return numTspecs; +} + +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + +eHalStatus sme_QosCreateTspecRICIE(tpAniSirGlobal pMac, sme_QosWmmTspecInfo *pTspec_Info, + v_U8_t *pRICBuffer, v_U32_t *pRICLength, v_U8_t *pRICIdentifier) +{ + tDot11fIERICDataDesc ricIE; + tANI_U32 nStatus; + + if (pRICBuffer == NULL || pRICIdentifier == NULL || pRICLength == NULL) + { + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(&ricIE, sizeof(tDot11fIERICDataDesc)); + + ricIE.present = 1; + ricIE.RICData.present = 1; + ricIE.RICData.resourceDescCount = 1; + ricIE.RICData.statusCode = 0; + ricIE.RICData.Identifier = sme_QosAssignDialogToken(); +#ifndef USE_80211_WMMTSPEC_FOR_RIC + ricIE.TSPEC.present = 1; + ricIE.TSPEC.delay_bound = pTspec_Info->delay_bound; + ricIE.TSPEC.inactivity_int = pTspec_Info->inactivity_interval; + ricIE.TSPEC.burst_size = pTspec_Info->max_burst_size; + ricIE.TSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size; + ricIE.TSPEC.max_service_int = pTspec_Info->max_service_interval; + ricIE.TSPEC.mean_data_rate = pTspec_Info->mean_data_rate; + ricIE.TSPEC.medium_time = 0; + ricIE.TSPEC.min_data_rate = pTspec_Info->min_data_rate; + ricIE.TSPEC.min_phy_rate = pTspec_Info->min_phy_rate; + ricIE.TSPEC.min_service_int = pTspec_Info->min_service_interval; + ricIE.TSPEC.size = pTspec_Info->nominal_msdu_size; + ricIE.TSPEC.peak_data_rate = pTspec_Info->peak_data_rate; + ricIE.TSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance; + ricIE.TSPEC.suspension_int = pTspec_Info->suspension_interval; + ricIE.TSPEC.service_start_time = pTspec_Info->svc_start_time; + ricIE.TSPEC.direction = pTspec_Info->ts_info.direction; + //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup + if( pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac) ) + { + ricIE.TSPEC.psb = pTspec_Info->ts_info.psb; + } + else + { + ricIE.TSPEC.psb = 0; + } + ricIE.TSPEC.tsid = pTspec_Info->ts_info.tid; + ricIE.TSPEC.user_priority = pTspec_Info->ts_info.up; + ricIE.TSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA; + + *pRICIdentifier = ricIE.RICData.Identifier; + + nStatus = dot11fPackIeRICDataDesc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), pRICLength); + if (DOT11F_FAILED(nStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Packing of RIC Data of length %d failed with status %d"), + *pRICLength, nStatus); + } +#else // WMM TSPEC + /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service + Interval, Service Start Time, Suspension Interval and Delay Bound are + all intended for HCCA operation and therefore must be set to zero*/ + ricIE.WMMTSPEC.present = 1; + ricIE.WMMTSPEC.version = 1; + ricIE.WMMTSPEC.delay_bound = pTspec_Info->delay_bound; + ricIE.WMMTSPEC.inactivity_int = pTspec_Info->inactivity_interval; + ricIE.WMMTSPEC.burst_size = pTspec_Info->max_burst_size; + ricIE.WMMTSPEC.max_msdu_size = pTspec_Info->maximum_msdu_size; + ricIE.WMMTSPEC.max_service_int = pTspec_Info->max_service_interval; + ricIE.WMMTSPEC.mean_data_rate = pTspec_Info->mean_data_rate; + ricIE.WMMTSPEC.medium_time = 0; + ricIE.WMMTSPEC.min_data_rate = pTspec_Info->min_data_rate; + ricIE.WMMTSPEC.min_phy_rate = pTspec_Info->min_phy_rate; + ricIE.WMMTSPEC.min_service_int = pTspec_Info->min_service_interval; + ricIE.WMMTSPEC.size = pTspec_Info->nominal_msdu_size; + ricIE.WMMTSPEC.peak_data_rate = pTspec_Info->peak_data_rate; + ricIE.WMMTSPEC.surplus_bw_allowance = pTspec_Info->surplus_bw_allowance; + ricIE.WMMTSPEC.suspension_int = pTspec_Info->suspension_interval; + ricIE.WMMTSPEC.service_start_time = pTspec_Info->svc_start_time; + ricIE.WMMTSPEC.direction = pTspec_Info->ts_info.direction; + //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup + if( pTspec_Info->ts_info.psb && btcIsReadyForUapsd(pMac) ) + { + ricIE.WMMTSPEC.psb = pTspec_Info->ts_info.psb; + } + else + { + ricIE.WMMTSPEC.psb = 0; + } + ricIE.WMMTSPEC.tsid = pTspec_Info->ts_info.tid; + ricIE.WMMTSPEC.user_priority = pTspec_Info->ts_info.up; + ricIE.WMMTSPEC.access_policy = SME_QOS_ACCESS_POLICY_EDCA; + + + nStatus = dot11fPackIeRICDataDesc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), pRICLength); + if (DOT11F_FAILED(nStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Packing of RIC Data of length %d failed with status %d"), + *pRICLength, nStatus); + } +#endif /* 80211_TSPEC */ + *pRICIdentifier = ricIE.RICData.Identifier; + return nStatus; +} + +eHalStatus sme_QosProcessFTReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t ac, qos_requested = FALSE; + v_U8_t tspec_flow_index; + sme_QosFlowInfoEntry *flow_info = NULL; + tListElem *pEntry= NULL; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + FL("Invoked on session %d"), sessionId); + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + qos_requested = FALSE; + + for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++) + { + /* Only in the below case, copy the AC's curr QoS Info to requested QoS info */ + if ((pACInfo->ricIdentifier[tspec_flow_index] && !pACInfo->tspec_pending) || + (pACInfo->tspec_mask_status & (1<requested_QoSInfo[tspec_flow_index] = pACInfo->curr_QoSInfo[tspec_flow_index]; + vos_mem_zero(&pACInfo->curr_QoSInfo[tspec_flow_index], sizeof(sme_QosWmmTspecInfo)); + qos_requested = TRUE; + } + } + + // Only if the tspec is required, transition the state to + // SME_QOS_REQUESTED for this AC + if (qos_requested) + { + switch(pACInfo->curr_state) + { + case SME_QOS_HANDOFF: + sme_QosStateTransition(sessionId, ac, SME_QOS_REQUESTED); + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("FT Reassoc req event in unexpected state %d"), pACInfo->curr_state); + VOS_ASSERT(0); + } + } + + } + + /* At this point of time, we are disconnected from the old AP, so it is safe + * to reset all these session variables */ + pSession->apsdMask = 0; + pSession->uapsdAlreadyRequested = 0; + pSession->readyForPowerSave = 0; + + /* Now change reason and HO renewal of all the flow in this session only */ + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: %d: Flow List empty, nothing to update", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + + do + { + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if(sessionId == flow_info->sessionId) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Changing FlowID %d reason to SETUP and HO renewal to FALSE", + __func__, __LINE__, + flow_info->QosFlowID); + flow_info->reason = SME_QOS_REASON_SETUP; + flow_info->hoRenewal = eANI_BOOLEAN_TRUE; + } + pEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + } while( pEntry ); + + return eHAL_STATUS_SUCCESS; +} + + +eHalStatus sme_QosFTAggrQosReq( tpAniSirGlobal pMac, v_U8_t sessionId ) +{ + tSirAggrQosReq *pMsg = NULL; + sme_QosSessionInfo *pSession; + eHalStatus status = eHAL_STATUS_FAILURE; + int i, j = 0; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", __func__, __LINE__, + sessionId); + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + pMsg = (tSirAggrQosReq *)vos_mem_malloc(sizeof(tSirAggrQosReq)); + + if (!pMsg) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the msg buffer", + __func__, __LINE__); + + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(pMsg, sizeof(tSirAggrQosReq)); + + pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_FT_AGGR_QOS_REQ); + pMsg->length = sizeof(tSirAggrQosReq); + pMsg->sessionId = sessionId; + pMsg->timeout = 0; + pMsg->rspReqd = VOS_TRUE; + vos_mem_copy( &pMsg->bssId[ 0 ], + &pSession->assocInfo.pBssDesc->bssId[ 0 ], + sizeof(tCsrBssid) ); + + for( i = 0; i < SME_QOS_EDCA_AC_MAX; i++ ) + { + for( j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++ ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("ac=%d, tspec_mask_staus=%x, tspec_index=%d"), + i, pSession->ac_info[i].tspec_mask_status, j); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("direction = %d"), pSession->ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.direction); + // Check if any flow is active on this AC + if ((pSession->ac_info[i].tspec_mask_status) & (1 << j)) + { + tANI_U8 direction = pSession->ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic.direction; + if ((direction == SME_QOS_WMM_TS_DIR_UPLINK) || + (direction == SME_QOS_WMM_TS_DIR_BOTH)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("Found tspec entry AC=%d, flow=%d, direction = %d"), i, j, direction); + pMsg->aggrInfo.aggrAddTsInfo[i].dialogToken = + sme_QosAssignDialogToken(); + pMsg->aggrInfo.aggrAddTsInfo[i].lleTspecPresent = + pSession->ac_info[i].addTsRsp[j].rsp.lleTspecPresent; + pMsg->aggrInfo.aggrAddTsInfo[i].numTclas = + pSession->ac_info[i].addTsRsp[j].rsp.numTclas; + vos_mem_copy( pMsg->aggrInfo.aggrAddTsInfo[i].tclasInfo, + pSession->ac_info[i].addTsRsp[j].rsp.tclasInfo, + SIR_MAC_TCLASIE_MAXNUM ); + pMsg->aggrInfo.aggrAddTsInfo[i].tclasProc = + pSession->ac_info[i].addTsRsp[j].rsp.tclasProc; + pMsg->aggrInfo.aggrAddTsInfo[i].tclasProcPresent = + pSession->ac_info[i].addTsRsp[j].rsp.tclasProcPresent; + pMsg->aggrInfo.aggrAddTsInfo[i].tspec = + pSession->ac_info[i].addTsRsp[j].rsp.tspec; + pMsg->aggrInfo.aggrAddTsInfo[i].wmeTspecPresent = + pSession->ac_info[i].addTsRsp[j].rsp.wmeTspecPresent; + pMsg->aggrInfo.aggrAddTsInfo[i].wsmTspecPresent = + pSession->ac_info[i].addTsRsp[j].rsp.wsmTspecPresent; + pMsg->aggrInfo.tspecIdx |= ( 1 << i ); + + // Mark the index for this AC as pending for response, which would be + // used to validate the AddTS response from HAL->PE->SME + pSession->ac_info[i].tspec_pending = (1<aggrInfo.tspecIdx); + + if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg))) + { + status = eHAL_STATUS_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: sent down a AGGR QoS req to PE", + __func__, __LINE__); + } + + return status; +} + +eHalStatus sme_QosProcessFTRICResponse(tpAniSirGlobal pMac, v_U8_t sessionId, tDot11fIERICDataDesc *pRicDataDesc, v_U8_t ac, v_U8_t tspecIndex) +{ + tANI_U8 i = 0; + tpSirAddtsRsp pAddtsRsp + = &sme_QosCb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex]; + + vos_mem_zero(pAddtsRsp, sizeof(tSirAddtsRsp)); + + pAddtsRsp->messageType = eWNI_SME_ADDTS_RSP; + pAddtsRsp->length = sizeof(tSirAddtsRsp); + pAddtsRsp->rc = pRicDataDesc->RICData.statusCode; + pAddtsRsp->sessionId = sessionId; + pAddtsRsp->rsp.dialogToken = pRicDataDesc->RICData.Identifier; + pAddtsRsp->rsp.status = pRicDataDesc->RICData.statusCode; + pAddtsRsp->rsp.wmeTspecPresent = pRicDataDesc->TSPEC.present; + if (pAddtsRsp->rsp.wmeTspecPresent) + { + //Copy TSPEC params received in RIC response to addts response + ConvertTSPEC(pMac, &pAddtsRsp->rsp.tspec, &pRicDataDesc->TSPEC); + } + + pAddtsRsp->rsp.numTclas = pRicDataDesc->num_TCLAS; + if (pAddtsRsp->rsp.numTclas) + { + for (i = 0; i < pAddtsRsp->rsp.numTclas; i++) + { + //Copy TCLAS info per index to the addts response + ConvertTCLAS(pMac, &pAddtsRsp->rsp.tclasInfo[i], &pRicDataDesc->TCLAS[i]); + } + } + + pAddtsRsp->rsp.tclasProcPresent = pRicDataDesc->TCLASSPROC.present; + if (pAddtsRsp->rsp.tclasProcPresent) + pAddtsRsp->rsp.tclasProc = pRicDataDesc->TCLASSPROC.processing; + + + pAddtsRsp->rsp.schedulePresent = pRicDataDesc->Schedule.present; + if (pAddtsRsp->rsp.schedulePresent) + { + //Copy Schedule IE params to addts response + ConvertSchedule(pMac, &pAddtsRsp->rsp.schedule, &pRicDataDesc->Schedule); + } + + //Need to check the below portion is a part of WMM TSPEC + //Process Delay element + if (pRicDataDesc->TSDelay.present) + ConvertTSDelay(pMac, &pAddtsRsp->rsp.delay, &pRicDataDesc->TSDelay); + + //Need to call for WMMTSPEC + if (pRicDataDesc->WMMTSPEC.present) + { + ConvertWMMTSPEC(pMac, &pAddtsRsp->rsp.tspec, &pRicDataDesc->WMMTSPEC); + } + //return sme_QosProcessAddTsRsp(pMac, &addtsRsp); + return eHAL_STATUS_SUCCESS; +} +eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirAggrQosRsp pAggrRsp = (tpSirAggrQosRsp)pMsgBuf; + tSirAddtsRsp addtsRsp; + eHalStatus status = eHAL_STATUS_SUCCESS; + int i, j = 0; + tANI_U8 sessionId = pAggrRsp->sessionId; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Received AGGR_QOS resp from LIM")); + + /* Copy over the updated response information for TSPEC of all the ACs */ + for( i = 0; i < SIR_QOS_NUM_AC_MAX; i++ ) + { + tANI_U8 tspec_mask_status = sme_QosCb.sessionInfo[sessionId].ac_info[i].tspec_mask_status; + for( j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++ ) + { + tANI_U8 direction = sme_QosCb.sessionInfo[sessionId].ac_info[i]. + addTsRsp[j].rsp.tspec.tsinfo.traffic.direction; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Addts rsp from LIM AC=%d, flow=%d dir=%d, tspecIdx=%x"), + i, j, direction, pAggrRsp->aggrInfo.tspecIdx); + // Check if the direction is Uplink or bi-directional + if( ((1<aggrInfo.tspecIdx) && + ((tspec_mask_status) & (1<aggrInfo.aggrRsp[i].status; + addtsRsp.rsp.status = pAggrRsp->aggrInfo.aggrRsp[i].status; + addtsRsp.rsp.tspec = pAggrRsp->aggrInfo.aggrRsp[i].tspec; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Processing Addts rsp from LIM AC=%d, flow=%d"), i, j); + /* post ADD TS response for each */ + if (sme_QosProcessAddTsRsp(pMac, &addtsRsp) != eHAL_STATUS_SUCCESS) + { + status = eHAL_STATUS_FAILURE; + } + } + } + } + return status; +} + + +eHalStatus sme_QosProcessFTReassocRspEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t ac; + v_U8_t tspec_flow_index; + tDot11fIERICDataDesc *pRicDataDesc = NULL; + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId ); + tCsrRoamConnectedInfo *pCsrConnectedInfo = NULL; + tANI_U32 ricRspLen; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tDot11fIERICDataDesc *pRicData = NULL; + tANI_U32 ricLen; + v_BOOL_t Found = false; + sme_QosWmmDirType direction; + v_U8_t ac1; +#endif + + if (NULL == pCsrSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("The Session pointer is NULL")); + return eHAL_STATUS_FAILURE; + } + pCsrConnectedInfo = &pCsrSession->connectedInfo; + + ricRspLen = pCsrConnectedInfo->nRICRspLength; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + pRicDataDesc = (tDot11fIERICDataDesc *)((pCsrConnectedInfo->pbFrames) + + (pCsrConnectedInfo->nBeaconLength + pCsrConnectedInfo->nAssocReqLength + + pCsrConnectedInfo->nAssocRspLength)); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if(!pCsrSession->roamOffloadSynchParams.bRoamSynchInProgress) + { +#endif + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + + for (tspec_flow_index = 0; tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; tspec_flow_index++) + { + /* Only in the below case, copy the AC's curr QoS Info to requested QoS info */ + if (pACInfo->ricIdentifier[tspec_flow_index]) + { + + if (!ricRspLen) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("RIC Response not received for AC %d on TSPEC Index %d, RIC Req Identifier = %d"), + ac, tspec_flow_index, pACInfo->ricIdentifier[tspec_flow_index]); + VOS_ASSERT(0); + } + else + { + /* Now we got response for this identifier. Process it. */ + if (pRicDataDesc->present) + { + if (pRicDataDesc->RICData.present) + { + if (pRicDataDesc->RICData.Identifier != pACInfo->ricIdentifier[tspec_flow_index]) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("RIC response order not same as request sent. Request ID = %d, Response ID = %d"), + pACInfo->ricIdentifier[tspec_flow_index], pRicDataDesc->RICData.Identifier); + VOS_ASSERT(0); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Processing RIC Response for AC %d, TSPEC Flow index %d with RIC ID %d "), + ac, tspec_flow_index, pRicDataDesc->RICData.Identifier); + status = sme_QosProcessFTRICResponse(pMac, sessionId, pRicDataDesc, ac, tspec_flow_index); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Failed with status %d for AC %d in TSPEC Flow index = %d"), + status, ac, tspec_flow_index); + } + } + pRicDataDesc++; + ricRspLen -= sizeof(tDot11fIERICDataDesc); + } + } + } + } + + } + } + + if (ricRspLen) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("RIC Response still follows despite traversing through all ACs. Remaining len = %d"), ricRspLen); + VOS_ASSERT(0); + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } + else + { + /* It means LFR3.0 roaming with RIC, + * currently we have support for WMM TSPEC alone + * In LFR3.0 11r since we do not have a RIC identifier + * maintained in host so identify the tspec from the AC + * and direction info */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("LFR3-11r Compare RIC in Reassoc Resp to find" + " matching tspec in host.")); + + pRicData = pRicDataDesc; + ricLen = ricRspLen; + + if (ricRspLen && pRicDataDesc->present && + pRicDataDesc->WMMTSPEC.present) { + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + for (tspec_flow_index = 0; + tspec_flow_index < SME_QOS_TSPEC_INDEX_MAX; + tspec_flow_index++) { + if((pSession->ac_info[ac].tspec_mask_status) + & (1 << tspec_flow_index)) { + do { + ac1 = sme_QosUpToAc(pRicData->WMMTSPEC.user_priority); + if (ac == SME_QOS_EDCA_AC_MAX) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Invalid AC %d UP %d"), ac, + pRicData->WMMTSPEC.user_priority); + break; + } + direction = pRicData->WMMTSPEC.direction; + + if (ac == ac1 && + direction == pACInfo->requested_QoSInfo[tspec_flow_index].ts_info.direction) + { + /* It means we found a matching tspec */ + Found = true; + status = sme_QosProcessFTRICResponse(pMac, + sessionId, + pRicData, + ac, + tspec_flow_index); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Failed with status %d for AC %d in TSPEC Flow index = %d"), + status, ac, tspec_flow_index); + } + break; + } + pRicData++; + ricLen -= sizeof(tDot11fIERICDataDesc); + }while(ricLen); + } + pRicData = pRicDataDesc; + ricLen = ricRspLen; + Found = false; + } + } + }else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("LFR3-11r ricRspLen is zero or pRicDataDesc is not" + " present or wmmtspec is not present")); + } + } +#endif + + /* Send the Aggregated QoS request to HAL */ + status = sme_QosFTAggrQosReq(pMac,sessionId); + + return status; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + + +/*-------------------------------------------------------------------------- + \brief sme_QosAddTsReq() - To send down the ADDTS request with TSPEC params + to PE + + + \param pMac - Pointer to the global MAC parameter structure. + \param sessionId - Session upon which the TSPEC should be added + \param pTspec_Info - Pointer to sme_QosWmmTspecInfo which contains the WMM + TSPEC related info as defined above + \param ac - Enumeration of the various EDCA Access Categories. + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo * pTspec_Info, + sme_QosEdcaAcType ac) +{ + tSirAddtsReq *pMsg = NULL; + sme_QosSessionInfo *pSession; + eHalStatus status = eHAL_STATUS_FAILURE; +#ifdef FEATURE_WLAN_ESE + tCsrRoamSession *pCsrSession = CSR_GET_SESSION( pMac, sessionId ); +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type); +#endif + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for AC %d", + __func__, __LINE__, + sessionId, ac); + if (sessionId >= CSR_ROAM_SESSION_MAX) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sessionId(%d) is invalid", + __func__, __LINE__, sessionId); + return eHAL_STATUS_FAILURE; + } + + pSession = &sme_QosCb.sessionInfo[sessionId]; + pMsg = (tSirAddtsReq *)vos_mem_malloc(sizeof(tSirAddtsReq)); + if (!pMsg) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the msg buffer", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(pMsg, sizeof(tSirAddtsReq)); + pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_ADDTS_REQ); + pMsg->length = sizeof(tSirAddtsReq); + pMsg->sessionId = sessionId; + pMsg->timeout = 0; + pMsg->rspReqd = VOS_TRUE; + pMsg->req.dialogToken = sme_QosAssignDialogToken(); + /*As per WMM_AC_testplan_v0.39 Minimum Service Interval, Maximum Service + Interval, Service Start Time, Suspension Interval and Delay Bound are + all intended for HCCA operation and therefore must be set to zero*/ + pMsg->req.tspec.delayBound = 0; + pMsg->req.tspec.inactInterval = pTspec_Info->inactivity_interval; + pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH; + pMsg->req.tspec.maxBurstSz = pTspec_Info->max_burst_size; + pMsg->req.tspec.maxMsduSz = pTspec_Info->maximum_msdu_size; + pMsg->req.tspec.maxSvcInterval = pTspec_Info->max_service_interval; + pMsg->req.tspec.meanDataRate = pTspec_Info->mean_data_rate; + pMsg->req.tspec.mediumTime = pTspec_Info->medium_time; + pMsg->req.tspec.minDataRate = pTspec_Info->min_data_rate; + pMsg->req.tspec.minPhyRate = pTspec_Info->min_phy_rate; + pMsg->req.tspec.minSvcInterval = pTspec_Info->min_service_interval; + pMsg->req.tspec.nomMsduSz = pTspec_Info->nominal_msdu_size; + pMsg->req.tspec.peakDataRate = pTspec_Info->peak_data_rate; + pMsg->req.tspec.surplusBw = pTspec_Info->surplus_bw_allowance; + pMsg->req.tspec.suspendInterval = pTspec_Info->suspension_interval; + pMsg->req.tspec.svcStartTime = 0; + pMsg->req.tspec.tsinfo.traffic.direction = pTspec_Info->ts_info.direction; + //Make sure UAPSD is allowed. BTC may want to disable UAPSD while keep QoS setup + if( pTspec_Info->ts_info.psb + && btcIsReadyForUapsd(pMac) + ) + { + pMsg->req.tspec.tsinfo.traffic.psb = pTspec_Info->ts_info.psb; + } + else + { + pMsg->req.tspec.tsinfo.traffic.psb = 0; + pTspec_Info->ts_info.psb = 0; + } + pMsg->req.tspec.tsinfo.traffic.tsid = pTspec_Info->ts_info.tid; + pMsg->req.tspec.tsinfo.traffic.userPrio = pTspec_Info->ts_info.up; + pMsg->req.tspec.tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA; + pMsg->req.tspec.tsinfo.traffic.burstSizeDefn = pTspec_Info->ts_info.burst_size_defn; + pMsg->req.tspec.tsinfo.traffic.ackPolicy = pTspec_Info->ts_info.ack_policy; + pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE; + /*Fill the BSSID pMsg->req.bssId*/ + if (NULL == pSession->assocInfo.pBssDesc) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: BSS descriptor is NULL so we don't send request to PE", + __func__, __LINE__); + vos_mem_free(pMsg); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy( &pMsg->bssId[ 0 ], + &pSession->assocInfo.pBssDesc->bssId[ 0 ], + sizeof(tCsrBssid) ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: up = %d, tid = %d", + __func__, __LINE__, + pTspec_Info->ts_info.up, + pTspec_Info->ts_info.tid); +#ifdef FEATURE_WLAN_ESE + if(pCsrSession->connectedProfile.isESEAssoc) + { + pMsg->req.tsrsIE.tsid = pTspec_Info->ts_info.up; + pMsg->req.tsrsPresent = 1; + } +#endif + if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg))) + { + status = eHAL_STATUS_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: sent down a ADDTS req to PE", + __func__, __LINE__); + //event: EVENT_WLAN_QOS +#ifdef FEATURE_WLAN_DIAG_SUPPORT + qos.eventId = SME_QOS_DIAG_ADDTS_REQ; + qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED; + WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif //FEATURE_WLAN_DIAG_SUPPORT + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosDelTsReq() - To send down the DELTS request with TSPEC params + to PE + + + \param pMac - Pointer to the global MAC parameter structure. + \param sessionId - Session from which the TSPEC should be deleted + \param ac - Enumeration of the various EDCA Access Categories. + \param tspec_mask - on which tspec per AC, the delts is requested + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosDelTsReq(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosEdcaAcType ac, + v_U8_t tspec_mask) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + tSirDeltsReq *pMsg; + sme_QosWmmTspecInfo *pTspecInfo; + eHalStatus status = eHAL_STATUS_FAILURE; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type); +#endif + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for AC %d", + __func__, __LINE__, + sessionId, ac); + pMsg = (tSirDeltsReq *)vos_mem_malloc(sizeof(tSirDeltsReq)); + if (!pMsg) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the msg buffer", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(pMsg, sizeof(tSirDeltsReq)); + // get pointer to the TSPEC being deleted + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + pTspecInfo = &pACInfo->curr_QoSInfo[tspec_mask - 1]; + pMsg->messageType = pal_cpu_to_be16((v_U16_t)eWNI_SME_DELTS_REQ); + pMsg->length = sizeof(tSirDeltsReq); + pMsg->sessionId = sessionId; + pMsg->rspReqd = VOS_TRUE; + pMsg->req.tspec.delayBound = pTspecInfo->delay_bound; + pMsg->req.tspec.inactInterval = pTspecInfo->inactivity_interval; + pMsg->req.tspec.length = SME_QOS_TSPEC_IE_LENGTH; + pMsg->req.tspec.maxBurstSz = pTspecInfo->max_burst_size; + pMsg->req.tspec.maxMsduSz = pTspecInfo->maximum_msdu_size; + pMsg->req.tspec.maxSvcInterval = pTspecInfo->max_service_interval; + pMsg->req.tspec.meanDataRate = pTspecInfo->mean_data_rate; + pMsg->req.tspec.mediumTime = pTspecInfo->medium_time; + pMsg->req.tspec.minDataRate = pTspecInfo->min_data_rate; + pMsg->req.tspec.minPhyRate = pTspecInfo->min_phy_rate; + pMsg->req.tspec.minSvcInterval = pTspecInfo->min_service_interval; + pMsg->req.tspec.nomMsduSz = pTspecInfo->nominal_msdu_size; + pMsg->req.tspec.peakDataRate = pTspecInfo->peak_data_rate; + pMsg->req.tspec.surplusBw = pTspecInfo->surplus_bw_allowance; + pMsg->req.tspec.suspendInterval = pTspecInfo->suspension_interval; + pMsg->req.tspec.svcStartTime = pTspecInfo->svc_start_time; + pMsg->req.tspec.tsinfo.traffic.direction = pTspecInfo->ts_info.direction; + pMsg->req.tspec.tsinfo.traffic.psb = pTspecInfo->ts_info.psb; + pMsg->req.tspec.tsinfo.traffic.tsid = pTspecInfo->ts_info.tid; + pMsg->req.tspec.tsinfo.traffic.userPrio = pTspecInfo->ts_info.up; + pMsg->req.tspec.tsinfo.traffic.accessPolicy = SME_QOS_ACCESS_POLICY_EDCA; + pMsg->req.tspec.tsinfo.traffic.burstSizeDefn = pTspecInfo->ts_info.burst_size_defn; + pMsg->req.tspec.tsinfo.traffic.ackPolicy = pTspecInfo->ts_info.ack_policy; + pMsg->req.tspec.type = SME_QOS_TSPEC_IE_TYPE; + /*Fill the BSSID pMsg->req.bssId*/ + if (NULL == pSession->assocInfo.pBssDesc) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: BSS descriptor is NULL so we don't send request to PE", + __func__, __LINE__); + vos_mem_free(pMsg); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy( &pMsg->bssId[ 0 ], + &pSession->assocInfo.pBssDesc->bssId[ 0 ], + sizeof(tCsrBssid) ); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: up = %d, tid = %d", + __func__, __LINE__, + pTspecInfo->ts_info.up, + pTspecInfo->ts_info.tid); + vos_mem_zero(&pACInfo->curr_QoSInfo[tspec_mask - 1], + sizeof(sme_QosWmmTspecInfo)); + if(HAL_STATUS_SUCCESS(palSendMBMessage(pMac->hHdd, pMsg))) + { + status = eHAL_STATUS_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: sme_QosDelTsReq:Test: sent down a DELTS req to PE", + __func__, __LINE__); + //event: EVENT_WLAN_QOS +#ifdef FEATURE_WLAN_DIAG_SUPPORT + qos.eventId = SME_QOS_DIAG_DELTS; + qos.reasonCode = SME_QOS_DIAG_USER_REQUESTED; + WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif //FEATURE_WLAN_DIAG_SUPPORT + } + + return status; +} + + +/*-------------------------------------------------------------------------- + \brief sme_QosProcessAddTsRsp() - Function to process the + eWNI_SME_ADDTS_RSP came from PE + + \param pMac - Pointer to the global MAC parameter structure. + \param pMsgBuf - Pointer to the msg buffer came from PE. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessAddTsRsp(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirAddtsRsp paddts_rsp = (tpSirAddtsRsp)pMsgBuf; + sme_QosSessionInfo *pSession; + v_U8_t sessionId = paddts_rsp->sessionId; + eHalStatus status = eHAL_STATUS_FAILURE; +#ifdef WLAN_FEATURE_VOWIFI_11R + sme_QosWmmUpType up = (sme_QosWmmUpType)paddts_rsp->rsp.tspec.tsinfo.traffic.userPrio; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type); +#endif + + pSession = &sme_QosCb.sessionInfo[sessionId]; + +#ifdef WLAN_FEATURE_VOWIFI_11R + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for UP %d", + __func__, __LINE__, + sessionId, up); + + ac = sme_QosUpToAc(up); + if(SME_QOS_EDCA_AC_MAX == ac) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + + return eHAL_STATUS_FAILURE; + } + pACInfo = &pSession->ac_info[ac]; + if (SME_QOS_HANDOFF == pACInfo->curr_state) + { + smsLog(pMac, LOG1, FL("ADDTS Response received for AC %d in HANDOFF State.. Dropping"), ac); + pSession->readyForPowerSave = VOS_TRUE; + return eHAL_STATUS_SUCCESS; + } +#endif + + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d with return code %d", + __func__, __LINE__, + sessionId, paddts_rsp->rc); + /* Our outstanding request has been serviced + we can go into power save */ + pSession->readyForPowerSave = VOS_TRUE; + if(paddts_rsp->rc) + { + //event: EVENT_WLAN_QOS +#ifdef FEATURE_WLAN_DIAG_SUPPORT + qos.eventId = SME_QOS_DIAG_ADDTS_RSP; + qos.reasonCode = SME_QOS_DIAG_ADDTS_REFUSED; + WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif //FEATURE_WLAN_DIAG_SUPPORT + status = sme_QosProcessAddTsFailureRsp(pMac, sessionId, &paddts_rsp->rsp); + } + else + { + status = sme_QosProcessAddTsSuccessRsp(pMac, sessionId, &paddts_rsp->rsp); + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessDelTsRsp() - Function to process the + eWNI_SME_DELTS_RSP came from PE + + \param pMac - Pointer to the global MAC parameter structure. + \param pMsgBuf - Pointer to the msg buffer came from PE. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessDelTsRsp(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirDeltsRsp pDeltsRsp = (tpSirDeltsRsp)pMsgBuf; + sme_QosSessionInfo *pSession; + v_U8_t sessionId = pDeltsRsp->sessionId; + // msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d with return code %d", + __func__, __LINE__, + sessionId, pDeltsRsp->rc); + pSession = &sme_QosCb.sessionInfo[sessionId]; + /* Our outstanding request has been serviced + we can go into power save */ + pSession->readyForPowerSave = VOS_TRUE; + (void)sme_QosProcessBufferedCmd(sessionId); + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessDelTsInd() - Function to process the + eWNI_SME_DELTS_IND came from PE + + Since it's a DELTS indication from AP, will notify all the flows running on + this AC about QoS release + \param pMac - Pointer to the global MAC parameter structure. + \param pMsgBuf - Pointer to the msg buffer came from PE. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessDelTsInd(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirDeltsRsp pdeltsind = (tpSirDeltsRsp)pMsgBuf; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t sessionId = pdeltsind->sessionId; + sme_QosEdcaAcType ac; + sme_QosSearchInfo search_key; + sme_QosWmmUpType up = (sme_QosWmmUpType)pdeltsind->rsp.tspec.tsinfo.traffic.userPrio; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type); +#endif + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d for UP %d", + __func__, __LINE__, + sessionId, up); + ac = sme_QosUpToAc(up); + if(SME_QOS_EDCA_AC_MAX == ac) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, + ac, up); + return eHAL_STATUS_FAILURE; + } + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + /* + * Find all Flows on the particular AC & delete them, also send HDD + * indication through the callback it registered per request + */ + if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosDelTsIndFnp))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no match found for ac = %d", + __func__, __LINE__, + search_key.key.ac_type); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + +//event: EVENT_WLAN_QOS +#ifdef FEATURE_WLAN_DIAG_SUPPORT + qos.eventId = SME_QOS_DIAG_DELTS; + qos.reasonCode = SME_QOS_DIAG_DELTS_IND_FROM_AP; + WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif //FEATURE_WLAN_DIAG_SUPPORT + + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessAssocCompleteEv() - Function to process the + SME_QOS_CSR_ASSOC_COMPLETE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessAssocCompleteEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + eHalStatus status = eHAL_STATUS_FAILURE; + sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_BE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + if(((SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state)&& + (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state)&& + (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state)&& + (SME_QOS_INIT == pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state)) || + (pSession->handoffRequested)) + { + //get the association info + if(!pEvent_info) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: pEvent_info is NULL", + __func__, __LINE__); + return status; + } + if(!((sme_QosAssocInfo *)pEvent_info)->pBssDesc) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: pBssDesc is NULL", + __func__, __LINE__); + return status; + } + if((pSession->assocInfo.pBssDesc) && + (csrIsBssidMatch(pMac, (tCsrBssid *)&pSession->assocInfo.pBssDesc->bssId, + (tCsrBssid *) &(((sme_QosAssocInfo *)pEvent_info)->pBssDesc->bssId)))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: assoc with the same BSS, no update needed", + __func__, __LINE__); + } + else + { + status = sme_QosSaveAssocInfo(pSession, pEvent_info); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: wrong state: BE %d, BK %d, VI %d, VO %d", + __func__, __LINE__, + pSession->ac_info[SME_QOS_EDCA_AC_BE].curr_state, + pSession->ac_info[SME_QOS_EDCA_AC_BK].curr_state, + pSession->ac_info[SME_QOS_EDCA_AC_VI].curr_state, + pSession->ac_info[SME_QOS_EDCA_AC_VO].curr_state); + VOS_ASSERT(0); + return status; + } + // the session is active + pSession->sessionActive = VOS_TRUE; + if(pSession->handoffRequested) + { + pSession->handoffRequested = VOS_FALSE; + //renew all flows + (void)sme_QosProcessBufferedCmd(sessionId); + status = eHAL_STATUS_SUCCESS; + } + else + { + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_INIT: + sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP); + break; + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + case SME_QOS_HANDOFF: + case SME_QOS_CLOSED: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessReassocReqEv() - Function to process the + SME_QOS_CSR_REASSOC_REQ event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessReassocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + +#ifdef WLAN_FEATURE_VOWIFI_11R + if(pSession->ftHandoffInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: no need for state transition, should " + "already be in handoff state", + __func__, __LINE__); + if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) + { + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + sme_QosProcessFTReassocReqEv(pMac, sessionId, pEvent_info); + return eHAL_STATUS_SUCCESS; + } +#endif + + if(pSession->handoffRequested) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: no need for state transition, should " + "already be in handoff state", + __func__, __LINE__); + + if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) + { + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + + //buffer the existing flows to be renewed after handoff is done + sme_QosBufferExistingFlows(pMac, sessionId); + //clean up the control block partially for handoff + sme_QosCleanupCtrlBlkForHandoff(pMac, sessionId); + return eHAL_STATUS_SUCCESS; + } +//TBH: Assuming both handoff algo & 11r willn't be enabled at the same time +#ifdef WLAN_FEATURE_VOWIFI_11R + if(pSession->ftHandoffInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: no need for state transition, should " + "already be in handoff state", + __func__, __LINE__); + + if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) + { + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + + sme_QosProcessFTReassocReqEv(pMac, sessionId, pEvent_info); + return eHAL_STATUS_SUCCESS; + } +#endif + + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF); + break; + case SME_QOS_HANDOFF: + //This is normal because sme_QosRequestReassoc may already change the state + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessReassocSuccessEv() - Function to process the + SME_QOS_CSR_REASSOC_COMPLETE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + + tCsrRoamSession *pCsrRoamSession = NULL; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac, ac_index; + sme_QosSearchInfo search_key; + sme_QosSearchInfo search_key1; + eHalStatus status = eHAL_STATUS_FAILURE; + tListElem *pEntry= NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + + if (CSR_ROAM_SESSION_MAX <= sessionId) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + return status; + } + + pCsrRoamSession = CSR_GET_SESSION( pMac, sessionId ); + + pSession = &sme_QosCb.sessionInfo[sessionId]; + /* Our pending reassociation has completed + we can allow power save */ + pSession->readyForPowerSave = VOS_TRUE; + //get the association info + if(!pEvent_info) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: pEvent_info is NULL", + __func__, __LINE__); + return status; + } + if(!((sme_QosAssocInfo *)pEvent_info)->pBssDesc) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: pBssDesc is NULL", + __func__, __LINE__); + return status; + } + status = sme_QosSaveAssocInfo(pSession, pEvent_info); + if(status) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosSaveAssocInfo() failed", + __func__, __LINE__); + } +//TBH: Assuming both handoff algo & 11r willn't be enabled at the same time + if(pSession->handoffRequested) + { + pSession->handoffRequested = VOS_FALSE; + //renew all flows + (void)sme_QosProcessBufferedCmd(sessionId); + return eHAL_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSession->ftHandoffInProgress) + { + if (csrRoamIs11rAssoc(pMac, sessionId)) { + if (pCsrRoamSession && + pCsrRoamSession->connectedInfo.nRICRspLength) { + status = sme_QosProcessFTReassocRspEv(pMac, sessionId, + pEvent_info); + } + } +#ifdef FEATURE_WLAN_ESE + // If ESE association check for TSPEC IEs in the reassoc rsp frame + if (csrRoamIsESEAssoc(pMac, sessionId)) { + if (pCsrRoamSession && + pCsrRoamSession->connectedInfo.nTspecIeLength) { + status = sme_QosESEProcessReassocTspecRsp(pMac, sessionId, + pEvent_info); + } + } +#endif + pSession->ftHandoffInProgress = VOS_FALSE; + pSession->handoffRequested = VOS_FALSE; + return status; + } +#endif + + pSession->sessionActive = VOS_TRUE; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_HANDOFF: + // return to our previous state + sme_QosStateTransition(sessionId, ac, pACInfo->prev_state); + //for which ac APSD (hence the reassoc) is requested + if(pACInfo->reassoc_pending) + { + //update the apsd mask in CB - make sure to take care of the case + //where we are resetting the bit in apsd_mask + if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb) + { + pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac); + } + else + { + pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + } + pACInfo->reassoc_pending = VOS_FALSE; + //during setup it gets set as addts & reassoc both gets a pending flag + //pACInfo->tspec_pending = 0; + sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON); + // notify HDD with new Service Interval + pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] = + pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0]; + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + //notify PMC that reassoc is done for APSD on certain AC?? + + vos_mem_zero(&search_key1, sizeof(sme_QosSearchInfo)); + //set the hoRenewal field in control block if needed + search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3; + search_key1.key.reason = SME_QOS_REASON_SETUP; + search_key1.sessionId = sessionId; + for(ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX; ac_index++) + { + pEntry = sme_QosFindInFlowList(search_key1); + if(pEntry) + { + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if(flow_info->ac_type == ac) + { + pACInfo->hoRenewal = flow_info->hoRenewal; + break; + } + } + } + //notify HDD the success for the requested flow + //notify all the other flows running on the AC that QoS got modified + if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosReassocSuccessEvFnp))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no match found for ac = %d", + __func__, __LINE__, + search_key.key.ac_type); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + pACInfo->hoRenewal = VOS_FALSE; + vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + } + status = eHAL_STATUS_SUCCESS; + break; + case SME_QOS_INIT: + case SME_QOS_CLOSED: + //NOP + status = eHAL_STATUS_SUCCESS; + break; + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + (void)sme_QosProcessBufferedCmd(sessionId); + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosProcessReassocFailureEv() - Function to process the + SME_QOS_CSR_REASSOC_FAILURE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessReassocFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + /* Our pending reassociation has completed + we can allow power save */ + pSession->readyForPowerSave = VOS_TRUE; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_HANDOFF: + sme_QosStateTransition(sessionId, ac, SME_QOS_INIT); + if(pACInfo->reassoc_pending) + { + pACInfo->reassoc_pending = VOS_FALSE; + } + vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1], + sizeof(sme_QosWmmTspecInfo)); + vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1], + sizeof(sme_QosWmmTspecInfo)); + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR; + pACInfo->tspec_pending = 0; + pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0; + pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0; + break; + case SME_QOS_INIT: + case SME_QOS_CLOSED: + //NOP + break; + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + //need to clean up flows + sme_QosDeleteExistingFlows(pMac, sessionId); + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessHandoffAssocReqEv() - Function to process the + SME_QOS_CSR_HANDOFF_ASSOC_REQ event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessHandoffAssocReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t ac; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF); + break; + case SME_QOS_HANDOFF: + //print error msg +#ifdef WLAN_FEATURE_VOWIFI_11R + if(pSession->ftHandoffInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: %d: SME_QOS_CSR_HANDOFF_ASSOC_REQ received in " + "SME_QOS_HANDOFF state with FT in progress" + , __func__, __LINE__); + break; + } +#endif + + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (csrRoamIs11rAssoc(pMac, sessionId)) { + /* Need not check here if it is LFR3.0 roaming, + * since ftHandoffInProgress will be true if it + * is 11r assoc even with LFR2.0 */ + pSession->ftHandoffInProgress = VOS_TRUE; + } +#endif + + // If FT handoff is in progress, legacy handoff need not be enabled + if (!pSession->ftHandoffInProgress) { + pSession->handoffRequested = VOS_TRUE; + } + // this session no longer needs UAPSD + pSession->apsdMask = 0; + // do any sessions still require UAPSD? + if(!pMac->psOffloadEnabled) + { + if (!sme_QosIsUapsdActive()) + { + // No sessions require UAPSD so turn it off + // (really don't care when PMC stops it) + (void)pmcStopUapsd(pMac); + } + } + else + { + (void)pmcOffloadStopUapsd(pMac, sessionId); + } + pSession->uapsdAlreadyRequested = VOS_FALSE; + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessHandoffSuccessEv() - Function to process the + SME_QOS_CSR_HANDOFF_COMPLETE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessHandoffSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t ac; + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + //go back to original state before handoff + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_HANDOFF: + sme_QosStateTransition(sessionId, ac, pACInfo->prev_state); + //we will retry for the requested flow(s) with the new AP + if(SME_QOS_REQUESTED == pACInfo->curr_state) + { + pACInfo->curr_state = SME_QOS_LINK_UP; + } + status = eHAL_STATUS_SUCCESS; + break; + // FT logic, has already moved it to QOS_REQUESTED state during the + // reassoc request event, which would include the Qos (TSPEC) params + // in the reassoc req frame + case SME_QOS_REQUESTED: + break; + case SME_QOS_INIT: + case SME_QOS_CLOSED: + case SME_QOS_LINK_UP: + case SME_QOS_QOS_ON: + default: +#ifdef WLAN_FEATURE_VOWIFI_11R +/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the + state may be SME_QOS_REQUESTED */ + if( pSession->ftHandoffInProgress ) + break; +#endif + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessHandoffFailureEv() - Function to process the + SME_QOS_CSR_HANDOFF_FAILURE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessHandoffFailureEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t ac; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + switch(pACInfo->curr_state) + { + case SME_QOS_HANDOFF: + sme_QosStateTransition(sessionId, ac, SME_QOS_INIT); + //need to clean up flows: TODO + vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + vos_mem_zero(&pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_1], + sizeof(sme_QosWmmTspecInfo)); + vos_mem_zero(&pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_1], + sizeof(sme_QosWmmTspecInfo)); + pACInfo->tspec_mask_status = SME_QOS_TSPEC_MASK_CLEAR; + pACInfo->tspec_pending = 0; + pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0] = 0; + pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] = 0; + break; + case SME_QOS_INIT: + case SME_QOS_CLOSED: + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + //no longer in handoff + pSession->handoffRequested = VOS_FALSE; + //clean up the assoc info + if(pSession->assocInfo.pBssDesc) + { + vos_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessDisconnectEv() - Function to process the + SME_QOS_CSR_DISCONNECT_REQ or SME_QOS_CSR_DISCONNECT_IND event indication + from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessDisconnectEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + if((pSession->handoffRequested) +#ifdef WLAN_FEATURE_VOWIFI_11R +/* In case of 11r - RIC, we request QoS and Hand-off at the same time hence the + state may be SME_QOS_REQUESTED */ + && !pSession->ftHandoffInProgress +#endif + ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: no need for state transition, should " + "already be in handoff state", + __func__, __LINE__); + if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) + { + VOS_ASSERT(0); + return eHAL_STATUS_SUCCESS; + } + + return eHAL_STATUS_SUCCESS; + } + sme_QosInitACs(pMac, sessionId); + // this session doesn't require UAPSD + pSession->apsdMask = 0; + + if(!pMac->psOffloadEnabled) + { + // do any sessions still require UAPSD? + if (!sme_QosIsUapsdActive()) + { + // No sessions require UAPSD so turn it off + // (really don't care when PMC stops it) + (void)pmcStopUapsd(pMac); + } + } + else + { + (void)pmcOffloadStopUapsd(pMac, sessionId); + } + + pSession->uapsdAlreadyRequested = VOS_FALSE; + pSession->handoffRequested = VOS_FALSE; + pSession->readyForPowerSave = VOS_TRUE; + pSession->roamID = 0; + //need to clean up buffered req + sme_QosDeleteBufferedRequests(pMac, sessionId); + //need to clean up flows + sme_QosDeleteExistingFlows(pMac, sessionId); + //clean up the assoc info + if(pSession->assocInfo.pBssDesc) + { + vos_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + sme_QosCb.sessionInfo[sessionId].sessionActive = VOS_FALSE; + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessJoinReqEv() - Function to process the + SME_QOS_CSR_JOIN_REQ event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessJoinReqEv(tpAniSirGlobal pMac, v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosEdcaAcType ac; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + if(pSession->handoffRequested) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: no need for state transition, should " + "already be in handoff state", + __func__, __LINE__); + if ((pSession->ac_info[0].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[1].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[2].curr_state != SME_QOS_HANDOFF) || + (pSession->ac_info[3].curr_state != SME_QOS_HANDOFF)) + { + // just print + VOS_ASSERT(0); + } + + //buffer the existing flows to be renewed after handoff is done + sme_QosBufferExistingFlows(pMac, sessionId); + //clean up the control block partially for handoff + sme_QosCleanupCtrlBlkForHandoff(pMac, sessionId); + return eHAL_STATUS_SUCCESS; + } + + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + sme_QosStateTransition(sessionId, ac, SME_QOS_INIT); + } + //clean up the assoc info if already set + if(pSession->assocInfo.pBssDesc) + { + vos_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/*-------------------------------------------------------------------------- + \brief sme_QosProcessPreauthSuccessInd() - Function to process the + SME_QOS_CSR_PREAUTH_SUCCESS_IND event indication from CSR + + \param pEvent_info - Pointer to relevant info from CSR. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessPreauthSuccessInd(tpAniSirGlobal pMac, + v_U8_t sessionId, void * pEvent_info) +{ + sme_QosSessionInfo *pSession; + tCsrRoamSession *pSmeSession = CSR_GET_SESSION( pMac, sessionId ); + sme_QosACInfo *pACInfo; + v_U8_t ac; + eHalStatus status = eHAL_STATUS_SUCCESS; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + FL("invoked on SME session %d"), sessionId); + + if (NULL == pSmeSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("pSmeSession is NULL")); + return eHAL_STATUS_INVALID_PARAMETER; + } + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + + switch(pACInfo->curr_state) + { + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF); + break; + case SME_QOS_HANDOFF: + //print error msg + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + VOS_ASSERT(0); + break; + } + } + + pSession->ftHandoffInProgress = VOS_TRUE; + + // Check if its a 11R roaming before preparing the RIC IEs + if (csrRoamIs11rAssoc(pMac, sessionId)) { + v_U16_t ricOffset = 0; + v_U32_t ricIELength = 0; + v_U8_t *ricIE; + v_U8_t tspec_mask_status = 0; + v_U8_t tspec_pending_status = 0; + + /* Data is accessed from saved PreAuth Rsp */ + if (NULL == pSmeSession->ftSmeContext.psavedFTPreAuthRsp) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("psavedFTPreAuthRsp is NULL")); + return eHAL_STATUS_INVALID_PARAMETER; + } + + /* Any Block Ack info there, should have been already filled by PE and + present in this buffer and the ric_ies_length should contain the + length of the whole RIC IEs. Filling of TSPEC info should start + from this length */ + ricIE = pSmeSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies; + ricOffset = + pSmeSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length; + + /* Now we have to process the currentTspeInfo inside this session and + create the RIC IEs */ + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + volatile v_U8_t tspec_index = 0; + ricIELength = 0; + pACInfo = &pSession->ac_info[ac]; + tspec_pending_status = pACInfo->tspec_pending; + tspec_mask_status = pACInfo->tspec_mask_status; + vos_mem_zero(pACInfo->ricIdentifier, SME_QOS_TSPEC_INDEX_MAX); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("AC %d ==> TSPEC status = %d, tspec pending = %d"), + ac, tspec_mask_status, tspec_pending_status); + + do + { + if (tspec_mask_status & 0x1) + { + /* If a tspec status is pending, take requested_QoSInfo for + RIC request, else use curr_QoSInfo for the RIC request */ + if (tspec_pending_status & 0x1) + { + status = sme_QosCreateTspecRICIE(pMac, + &pACInfo->requested_QoSInfo[tspec_index], + ricIE + ricOffset, &ricIELength, + &pACInfo->ricIdentifier[tspec_index]); + } + else + { + status = sme_QosCreateTspecRICIE(pMac, + &pACInfo->curr_QoSInfo[tspec_index], + ricIE + ricOffset, &ricIELength, + &pACInfo->ricIdentifier[tspec_index]); + } + } + ricOffset += ricIELength; + pSmeSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length += + ricIELength; + + tspec_mask_status >>= 1; + tspec_pending_status >>= 1; + tspec_index++; + } while (tspec_mask_status); + } + } + return status; +} + +#endif + + +/*-------------------------------------------------------------------------- + \brief sme_QosProcessAddTsFailureRsp() - Function to process the + Addts request failure response came from PE + + We will notify HDD only for the requested Flow, other Flows running on the AC + stay intact + + \param pMac - Pointer to the global MAC parameter structure. + \param pRsp - Pointer to the addts response structure came from PE. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessAddTsFailureRsp(tpAniSirGlobal pMac, + v_U8_t sessionId, + tSirAddtsRspInfo * pRsp) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + sme_QosSearchInfo search_key; + v_U8_t tspec_pending; + sme_QosWmmUpType up = (sme_QosWmmUpType)pRsp->tspec.tsinfo.traffic.userPrio; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for UP %d", + __func__, __LINE__, + sessionId, up); + ac = sme_QosUpToAc(up); + if(SME_QOS_EDCA_AC_MAX == ac) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + return eHAL_STATUS_FAILURE; + } + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + // is there a TSPEC request pending on this AC? + tspec_pending = pACInfo->tspec_pending; + if(!tspec_pending) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d an AddTS is not pending on AC %d", + __func__, __LINE__, + sessionId, ac); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosAddTsFailureFnp))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d no match found for ac = %d", + __func__, __LINE__, + sessionId, search_key.key.ac_type); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1], + sizeof(sme_QosWmmTspecInfo)); + + if((!pACInfo->num_flows[0])&& + (!pACInfo->num_flows[1])) + { + pACInfo->tspec_mask_status &= SME_QOS_TSPEC_MASK_BIT_1_2_SET & + (~pACInfo->tspec_pending); + sme_QosStateTransition(sessionId, ac, SME_QOS_LINK_UP); + } + else + { + sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON); + } + pACInfo->tspec_pending = 0; + + (void)sme_QosProcessBufferedCmd(sessionId); + + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosUpdateTspecMask() - Utility function to update the tspec. + Typical usage while aggregating unidirectional flows into a bi-directional + flow on AC which is running multiple flows + + \param sessionId - Session upon which the TSPEC is being updated + \param ac - Enumeration of the various EDCA Access Categories. + \param old_tspec_mask - on which tspec per AC, the update is requested + \param new_tspec_mask - tspec to be set for this AC + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +static eHalStatus sme_QosUpdateTspecMask(v_U8_t sessionId, + sme_QosSearchInfo search_key, + v_U8_t new_tspec_mask) +{ + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for AC %d TSPEC %d", + __func__, __LINE__, + sessionId, search_key.key.ac_type, new_tspec_mask); + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + if (search_key.key.ac_type < SME_QOS_EDCA_AC_MAX) + { + pACInfo = &pSession->ac_info[search_key.key.ac_type]; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Exceeded the array bounds of pSession->ac_info", + __func__, __LINE__); + VOS_ASSERT (0); + return eHAL_STATUS_FAILURE; + } + + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, nothing to update", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + + if(search_key.sessionId == flow_info->sessionId) + { + if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_4) + { + if((search_key.key.ac_type == flow_info->ac_type) && + (search_key.direction == flow_info->QoSInfo.ts_info.direction)) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow %d matches", + __func__, __LINE__, + flow_info->QosFlowID); + pACInfo->num_flows[flow_info->tspec_mask - 1]--; + pACInfo->num_flows[new_tspec_mask - 1]++; + flow_info->tspec_mask = new_tspec_mask; + } + } + else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_5) + { + if((search_key.key.ac_type == flow_info->ac_type) && + (search_key.tspec_mask == flow_info->tspec_mask)) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow %d matches", + __func__, __LINE__, + flow_info->QosFlowID); + pACInfo->num_flows[flow_info->tspec_mask - 1]--; + pACInfo->num_flows[new_tspec_mask - 1]++; + flow_info->tspec_mask = new_tspec_mask; + } + } + } + + pEntry = pNextEntry; + } + + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessAddTsSuccessRsp() - Function to process the + Addts request success response came from PE + + We will notify HDD with addts success for the requested Flow, & for other + Flows running on the AC we will send an addts modify status + + + \param pMac - Pointer to the global MAC parameter structure. + \param pRsp - Pointer to the addts response structure came from PE. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessAddTsSuccessRsp(tpAniSirGlobal pMac, + v_U8_t sessionId, + tSirAddtsRspInfo * pRsp) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac, ac_index; + sme_QosSearchInfo search_key; + sme_QosSearchInfo search_key1; + v_U8_t tspec_pending; + tListElem *pEntry= NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosWmmUpType up = (sme_QosWmmUpType)pRsp->tspec.tsinfo.traffic.userPrio; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(qos, vos_event_wlan_qos_payload_type); + vos_log_qos_tspec_pkt_type *log_ptr = NULL; +#endif //FEATURE_WLAN_DIAG_SUPPORT + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for UP %d", + __func__, __LINE__, + sessionId, up); + pSession = &sme_QosCb.sessionInfo[sessionId]; + ac = sme_QosUpToAc(up); + if(SME_QOS_EDCA_AC_MAX == ac) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + return eHAL_STATUS_FAILURE; + } + pACInfo = &pSession->ac_info[ac]; + // is there a TSPEC request pending on this AC? + tspec_pending = pACInfo->tspec_pending; + if(!tspec_pending) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d an AddTS is not pending on AC %d", + __func__, __LINE__, + sessionId, ac); + return eHAL_STATUS_FAILURE; + } + //App is looking for APSD or the App which was looking for APSD has been + //released, so STA re-negotiated with AP + if(pACInfo->requested_QoSInfo[tspec_pending - 1].ts_info.psb) + { + //update the session's apsd mask + pSession->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac); + } + else + { + if(((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) > 0) && + ((SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) <= + SME_QOS_TSPEC_INDEX_MAX)) + { + if(!pACInfo->requested_QoSInfo + [(SME_QOS_TSPEC_MASK_BIT_1_2_SET & ~tspec_pending) - 1].ts_info.psb) + { + //update the session's apsd mask + pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Exceeded the array bounds of pACInfo->requested_QosInfo", + __func__, __LINE__); + VOS_ASSERT (0); + return eHAL_STATUS_FAILURE; + } + } + + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.burst_size_defn = + pRsp->tspec.tsinfo.traffic.burstSizeDefn; + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.ack_policy = + pRsp->tspec.tsinfo.traffic.ackPolicy; + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.up = + pRsp->tspec.tsinfo.traffic.userPrio; + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.psb = + pRsp->tspec.tsinfo.traffic.psb; + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.direction = + pRsp->tspec.tsinfo.traffic.direction; + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.tid = + pRsp->tspec.tsinfo.traffic.tsid; + pACInfo->curr_QoSInfo[tspec_pending - 1].nominal_msdu_size = + pRsp->tspec.nomMsduSz; + pACInfo->curr_QoSInfo[tspec_pending - 1].maximum_msdu_size = + pRsp->tspec.maxMsduSz; + pACInfo->curr_QoSInfo[tspec_pending - 1].min_service_interval = + pRsp->tspec.minSvcInterval; + pACInfo->curr_QoSInfo[tspec_pending - 1].max_service_interval = + pRsp->tspec.maxSvcInterval; + pACInfo->curr_QoSInfo[tspec_pending - 1].inactivity_interval = + pRsp->tspec.inactInterval; + pACInfo->curr_QoSInfo[tspec_pending - 1].suspension_interval = + pRsp->tspec.suspendInterval; + pACInfo->curr_QoSInfo[tspec_pending - 1].svc_start_time = + pRsp->tspec.svcStartTime; + pACInfo->curr_QoSInfo[tspec_pending - 1].min_data_rate = + pRsp->tspec.minDataRate; + pACInfo->curr_QoSInfo[tspec_pending - 1].mean_data_rate = + pRsp->tspec.meanDataRate; + pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate = + pRsp->tspec.peakDataRate; + pACInfo->curr_QoSInfo[tspec_pending - 1].max_burst_size = + pRsp->tspec.maxBurstSz; + pACInfo->curr_QoSInfo[tspec_pending - 1].delay_bound = + pRsp->tspec.delayBound; + + pACInfo->curr_QoSInfo[tspec_pending - 1].min_phy_rate = + pRsp->tspec.minPhyRate; + pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance = + pRsp->tspec.surplusBw; + pACInfo->curr_QoSInfo[tspec_pending - 1].medium_time = + pRsp->tspec.mediumTime; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AddTspec Medium Time %d", + __func__, __LINE__, + sessionId, pRsp->tspec.mediumTime); + + /* Check if the current flow is for bi-directional. If so, update the number of flows + * to reflect that all flows are aggregated into tspec index 0. */ + if((pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1].ts_info.direction == SME_QOS_WMM_TS_DIR_BOTH) && + (pACInfo->num_flows[SME_QOS_TSPEC_INDEX_1] > 0)) + { + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + /* update tspec_mask for all the flows having SME_QOS_TSPEC_MASK_BIT_2_SET to SME_QOS_TSPEC_MASK_BIT_1_SET */ + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_5; + search_key.sessionId = sessionId; + search_key.tspec_mask = SME_QOS_TSPEC_MASK_BIT_2_SET; + sme_QosUpdateTspecMask(sessionId, search_key, SME_QOS_TSPEC_MASK_BIT_1_SET); + } + + vos_mem_zero(&search_key1, sizeof(sme_QosSearchInfo)); + //set the horenewal field in control block if needed + search_key1.index = SME_QOS_SEARCH_KEY_INDEX_3; + search_key1.key.reason = SME_QOS_REASON_SETUP; + search_key1.sessionId = sessionId; + for(ac_index = SME_QOS_EDCA_AC_BE; ac_index < SME_QOS_EDCA_AC_MAX; ac_index++) + { + pEntry = sme_QosFindInFlowList(search_key1); + if(pEntry) + { + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if(flow_info->ac_type == ac) + { + pACInfo->hoRenewal = flow_info->hoRenewal; + break; + } + } + } + vos_mem_zero(&search_key, sizeof(sme_QosSearchInfo)); + //set the key type & the key to be searched in the Flow List + search_key.key.ac_type = ac; + search_key.index = SME_QOS_SEARCH_KEY_INDEX_2; + search_key.sessionId = sessionId; + //notify HDD the success for the requested flow + //notify all the other flows running on the AC that QoS got modified + if(!HAL_STATUS_SUCCESS(sme_QosFindAllInFlowList(pMac, search_key, sme_QosAddTsSuccessFnp))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d no match found for ac %d", + __func__, __LINE__, + sessionId, search_key.key.ac_type); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + pACInfo->hoRenewal = VOS_FALSE; + vos_mem_zero(&pACInfo->requested_QoSInfo[tspec_pending - 1], + sizeof(sme_QosWmmTspecInfo)); + //event: EVENT_WLAN_QOS +#ifdef FEATURE_WLAN_DIAG_SUPPORT + qos.eventId = SME_QOS_DIAG_ADDTS_RSP; + qos.reasonCode = SME_QOS_DIAG_ADDTS_ADMISSION_ACCEPTED; + WLAN_VOS_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); + WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_qos_tspec_pkt_type, LOG_WLAN_QOS_TSPEC_C); + if(log_ptr) + { + log_ptr->delay_bound = pACInfo->curr_QoSInfo[tspec_pending - 1].delay_bound; + log_ptr->inactivity_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].inactivity_interval; + log_ptr->max_burst_size = pACInfo->curr_QoSInfo[tspec_pending - 1].max_burst_size; + log_ptr->max_service_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].max_service_interval; + log_ptr->maximum_msdu_size = pACInfo->curr_QoSInfo[tspec_pending - 1].maximum_msdu_size; + log_ptr->mean_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].mean_data_rate; + log_ptr->medium_time = pACInfo->curr_QoSInfo[tspec_pending - 1].medium_time; + log_ptr->min_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].min_data_rate; + log_ptr->min_phy_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].min_phy_rate; + log_ptr->min_service_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].min_service_interval; + log_ptr->nominal_msdu_size = pACInfo->curr_QoSInfo[tspec_pending - 1].nominal_msdu_size; + log_ptr->peak_data_rate = pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate; + log_ptr->surplus_bw_allowance = pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance; + log_ptr->suspension_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].surplus_bw_allowance; + log_ptr->suspension_interval = pACInfo->curr_QoSInfo[tspec_pending - 1].suspension_interval; + log_ptr->svc_start_time = pACInfo->curr_QoSInfo[tspec_pending - 1].svc_start_time; + log_ptr->tsinfo[0] = pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.direction << 5 | + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.tid << 1; + log_ptr->tsinfo[1] = pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.up << 11 | + pACInfo->curr_QoSInfo[tspec_pending - 1].ts_info.psb << 10; + log_ptr->tsinfo[2] = 0; + } + WLAN_VOS_DIAG_LOG_REPORT(log_ptr); +#endif //FEATURE_WLAN_DIAG_SUPPORT +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + if (ac == SME_QOS_EDCA_AC_VO) + { + // Indicate to neighbor roam logic of the new required VO + // ac bandwidth requirement. + csrNeighborRoamIndicateVoiceBW( pMac, pACInfo->curr_QoSInfo[tspec_pending - 1].peak_data_rate, TRUE ); + } +#endif + pACInfo->tspec_pending = 0; + + sme_QosStateTransition(sessionId, ac, SME_QOS_QOS_ON); + + + (void)sme_QosProcessBufferedCmd(sessionId); + return eHAL_STATUS_SUCCESS; + +} +/*-------------------------------------------------------------------------- + \brief sme_QosAggregateParams() - Utility function to increment the TSPEC + params per AC. Typical usage while using flow aggregation or deletion of flows + + \param pInput_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains the + WMM TSPEC related info with which pCurrent_Tspec_Info will be updated + \param pCurrent_Tspec_Info - Pointer to sme_QosWmmTspecInfo which contains + current the WMM TSPEC related info + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosAggregateParams( + sme_QosWmmTspecInfo * pInput_Tspec_Info, + sme_QosWmmTspecInfo * pCurrent_Tspec_Info, + sme_QosWmmTspecInfo * pUpdated_Tspec_Info) +{ + sme_QosWmmTspecInfo TspecInfo; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked", + __func__, __LINE__); + if(!pInput_Tspec_Info) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: input is NULL, nothing to aggregate", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + if(!pCurrent_Tspec_Info) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Current is NULL, can't aggregate", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(&TspecInfo, pCurrent_Tspec_Info, + sizeof(sme_QosWmmTspecInfo)); + TspecInfo.ts_info.psb = pInput_Tspec_Info->ts_info.psb; + /*------------------------------------------------------------------------- + APSD preference is only meaningful if service interval was set by app + -------------------------------------------------------------------------*/ + if(pCurrent_Tspec_Info->min_service_interval && + pInput_Tspec_Info->min_service_interval && + (pCurrent_Tspec_Info->ts_info.direction != + pInput_Tspec_Info->ts_info.direction)) + { + TspecInfo.min_service_interval = VOS_MIN( + pCurrent_Tspec_Info->min_service_interval, + pInput_Tspec_Info->min_service_interval); + } + else if(pInput_Tspec_Info->min_service_interval) + { + TspecInfo.min_service_interval = pInput_Tspec_Info->min_service_interval; + } + if(pCurrent_Tspec_Info->max_service_interval && + pInput_Tspec_Info->max_service_interval && + (pCurrent_Tspec_Info->ts_info.direction != + pInput_Tspec_Info->ts_info.direction)) + { + TspecInfo.max_service_interval = VOS_MIN( + pCurrent_Tspec_Info->max_service_interval, + pInput_Tspec_Info->max_service_interval); + } + else + { + TspecInfo.max_service_interval = pInput_Tspec_Info->max_service_interval; + } + /*------------------------------------------------------------------------- + If directions don't match, it must necessarily be both uplink and + downlink + -------------------------------------------------------------------------*/ + if(pCurrent_Tspec_Info->ts_info.direction != + pInput_Tspec_Info->ts_info.direction) + { + TspecInfo.ts_info.direction = pInput_Tspec_Info->ts_info.direction; + } + /*------------------------------------------------------------------------- + Max MSDU size : these sizes are `maxed' + -------------------------------------------------------------------------*/ + TspecInfo.maximum_msdu_size = VOS_MAX(pCurrent_Tspec_Info->maximum_msdu_size, + pInput_Tspec_Info->maximum_msdu_size); + + /*------------------------------------------------------------------------- + Inactivity interval : these sizes are `maxed' + -------------------------------------------------------------------------*/ + TspecInfo.inactivity_interval = VOS_MAX(pCurrent_Tspec_Info->inactivity_interval, + pInput_Tspec_Info->inactivity_interval); + + /*------------------------------------------------------------------------- + Delay bounds: min of all values + Check on 0: if 0, it means initial value since delay can never be 0!! + -------------------------------------------------------------------------*/ + if(pCurrent_Tspec_Info->delay_bound) + { + TspecInfo.delay_bound = VOS_MIN(pCurrent_Tspec_Info->delay_bound, + pInput_Tspec_Info->delay_bound); + } + else + { + TspecInfo.delay_bound = pInput_Tspec_Info->delay_bound; + } + TspecInfo.max_burst_size = VOS_MAX(pCurrent_Tspec_Info->max_burst_size, + pInput_Tspec_Info->max_burst_size); + + /*------------------------------------------------------------------------- + Nominal MSDU size also has a fixed bit that needs to be `handled' before + aggregation + This can be handled only if previous size is the same as new or both have + the fixed bit set + These sizes are not added: but `maxed' + -------------------------------------------------------------------------*/ + TspecInfo.nominal_msdu_size = VOS_MAX( + pCurrent_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB, + pInput_Tspec_Info->nominal_msdu_size & ~SME_QOS_16BIT_MSB); + + if( ((pCurrent_Tspec_Info->nominal_msdu_size == 0) || + (pCurrent_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB)) && + ((pInput_Tspec_Info->nominal_msdu_size == 0) || + (pInput_Tspec_Info->nominal_msdu_size & SME_QOS_16BIT_MSB))) + { + TspecInfo.nominal_msdu_size |= SME_QOS_16BIT_MSB; + } + + /*------------------------------------------------------------------------- + Data rates: + Add up the rates for aggregation + -------------------------------------------------------------------------*/ + SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.peak_data_rate, + pInput_Tspec_Info->peak_data_rate ); + SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.min_data_rate, + pInput_Tspec_Info->min_data_rate ); + /* mean data rate = peak data rate: aggregate to be flexible on apps */ + SME_QOS_BOUNDED_U32_ADD_Y_TO_X( TspecInfo.mean_data_rate, + pInput_Tspec_Info->mean_data_rate ); + + /*------------------------------------------------------------------------- + Suspension interval : this is set to the inactivity interval since per + spec it is less than or equal to inactivity interval + This is not provided by app since we currently don't support the HCCA + mode of operation + Currently set it to 0 to avoid confusion: Cisco ESE needs ~0; spec + requires inactivity interval to be > suspension interval: this could + be tricky! + -------------------------------------------------------------------------*/ + TspecInfo.suspension_interval = pInput_Tspec_Info->suspension_interval; + /*------------------------------------------------------------------------- + Remaining parameters do not come from app as they are very WLAN + air interface specific + Set meaningful values here + -------------------------------------------------------------------------*/ + TspecInfo.medium_time = 0; /* per WMM spec */ + TspecInfo.min_phy_rate = SME_QOS_MIN_PHY_RATE; + TspecInfo.svc_start_time = 0; /* arbitrary */ + TspecInfo.surplus_bw_allowance += pInput_Tspec_Info->surplus_bw_allowance; + if(TspecInfo.surplus_bw_allowance > SME_QOS_SURPLUS_BW_ALLOWANCE) + { + TspecInfo.surplus_bw_allowance = SME_QOS_SURPLUS_BW_ALLOWANCE; + } + /* Set ack_policy to block ack even if one stream requests block ack policy */ + if((pInput_Tspec_Info->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) || + (pCurrent_Tspec_Info->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK)) + { + TspecInfo.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK; + } + + if(pInput_Tspec_Info->ts_info.burst_size_defn || pCurrent_Tspec_Info->ts_info.burst_size_defn ) + { + TspecInfo.ts_info.burst_size_defn = 1; + } + if(pUpdated_Tspec_Info) + { + vos_mem_copy(pUpdated_Tspec_Info, &TspecInfo, + sizeof(sme_QosWmmTspecInfo)); + } + else + { + vos_mem_copy(pCurrent_Tspec_Info, &TspecInfo, + sizeof(sme_QosWmmTspecInfo)); + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosUpdateParams() - Utility function to update the TSPEC + params per AC. Typical usage while deleting flows on AC which is running + multiple flows + + \param sessionId - Session upon which the TSPEC is being updated + \param ac - Enumeration of the various EDCA Access Categories. + \param tspec_mask - on which tspec per AC, the update is requested + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +static eHalStatus sme_QosUpdateParams(v_U8_t sessionId, + sme_QosEdcaAcType ac, + v_U8_t tspec_mask, + sme_QosWmmTspecInfo * pTspec_Info) +{ + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosWmmTspecInfo Tspec_Info; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for AC %d TSPEC %d", + __func__, __LINE__, + sessionId, ac, tspec_mask); + if(!pTspec_Info) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: output is NULL, can't aggregate", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(&Tspec_Info, sizeof(sme_QosWmmTspecInfo)); + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, nothing to update", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + //init the TS info field + Tspec_Info.ts_info.up = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.up; + Tspec_Info.ts_info.psb = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.psb; + Tspec_Info.ts_info.tid = pACInfo->curr_QoSInfo[tspec_mask - 1].ts_info.tid; + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if((sessionId == flow_info->sessionId) && + (ac == flow_info->ac_type) && + (tspec_mask == flow_info->tspec_mask)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow %d matches", + __func__, __LINE__, + flow_info->QosFlowID); + + if((SME_QOS_REASON_RELEASE == flow_info->reason ) || + (SME_QOS_REASON_MODIFY == flow_info->reason)) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Skipping Flow %d as it is marked " + "for release/modify", + __func__, __LINE__, + flow_info->QosFlowID); + } + else if(!HAL_STATUS_SUCCESS(sme_QosAggregateParams(&flow_info->QoSInfo, + &Tspec_Info, + NULL))) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosAggregateParams() failed", + __func__, __LINE__); + } + } + pEntry = pNextEntry; + } + // return the aggregate + *pTspec_Info = Tspec_Info; + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosAcToUp() - Utility function to map an AC to UP + Note: there is a quantization loss here because 4 ACs are mapped to 8 UPs + Mapping is done for consistency + \param ac - Enumeration of the various EDCA Access Categories. + \return an User Priority + + \sa + + --------------------------------------------------------------------------*/ +sme_QosWmmUpType sme_QosAcToUp(sme_QosEdcaAcType ac) +{ + sme_QosWmmUpType up = SME_QOS_WMM_UP_MAX; + if(ac >= 0 && ac < SME_QOS_EDCA_AC_MAX) + { + up = sme_QosACtoUPMap[ac]; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: ac = %d up = %d returned", + __func__, __LINE__, ac, up); + return up; +} +/*-------------------------------------------------------------------------- + \brief sme_QosUpToAc() - Utility function to map an UP to AC + \param up - Enumeration of the various User priorities (UP). + \return an Access Category + + \sa + + --------------------------------------------------------------------------*/ +sme_QosEdcaAcType sme_QosUpToAc(sme_QosWmmUpType up) +{ + sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_MAX; + if(up >= 0 && up < SME_QOS_WMM_UP_MAX) + { + ac = sme_QosUPtoACMap[up]; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: up = %d ac = %d returned", + __func__, __LINE__, up, ac); + return ac; +} +/*-------------------------------------------------------------------------- + \brief sme_QosStateTransition() - The state transition function per AC. We + save the previous state also. + \param sessionId - Session upon which the state machine is running + \param ac - Enumeration of the various EDCA Access Categories. + \param new_state - The state FSM is moving to. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +static void sme_QosStateTransition(v_U8_t sessionId, + sme_QosEdcaAcType ac, + sme_QosStates new_state) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + pACInfo->prev_state = pACInfo->curr_state; + pACInfo->curr_state = new_state; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d new state=%d, old state=%d, for AC=%d", + __func__, __LINE__, + sessionId, pACInfo->curr_state, pACInfo->prev_state, ac ); +} +/*-------------------------------------------------------------------------- + \brief sme_QosFindInFlowList() - Utility function to find an flow entry from + the flow_list. + \param search_key - We can either use the flowID or the ac type to find the + entry in the flow list. + A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB, + bit 0 - Flow ID + bit 1 - AC type + \return the pointer to the entry in the link list + + \sa + + --------------------------------------------------------------------------*/ +tListElem *sme_QosFindInFlowList(sme_QosSearchInfo search_key) +{ + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return NULL; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if((search_key.sessionId == flow_info->sessionId) || + (search_key.sessionId == SME_QOS_SEARCH_SESSION_ID_ANY)) + { + if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_1) + { + if(search_key.key.QosFlowID == flow_info->QosFlowID) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: match found on flowID, ending search", + __func__, __LINE__); + break; + } + } + else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_2) + { + if(search_key.key.ac_type == flow_info->ac_type) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: match found on ac, ending search", + __func__, __LINE__); + break; + } + } + else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_3) + { + if(search_key.key.reason == flow_info->reason) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: match found on reason, ending search", + __func__, __LINE__); + break; + } + } + else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_4) + { + if((search_key.key.ac_type == flow_info->ac_type) && + (search_key.direction == flow_info->QoSInfo.ts_info.direction)) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: match found on reason, ending search", + __func__, __LINE__); + + break; + } + } + } + pEntry = pNextEntry; + } + return pEntry; +} +/*-------------------------------------------------------------------------- + \brief sme_QosFindAllInFlowList() - Utility function to find an flow entry + from the flow_list & act on it. + \param search_key - We can either use the flowID or the ac type to find the + entry in the flow list. + A bitmap in sme_QosSearchInfo tells which key to use. Starting from LSB, + bit 0 - Flow ID + bit 1 - AC type + \param fnp - function pointer specifying the action type for the entry found + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosFindAllInFlowList(tpAniSirGlobal pMac, + sme_QosSearchInfo search_key, + sme_QosProcessSearchEntry fnp) +{ + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosSessionInfo *pSession; + sme_QosFlowInfoEntry *flow_info = NULL; + eHalStatus status = eHAL_STATUS_FAILURE; + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + if((search_key.sessionId == flow_info->sessionId) || + (search_key.sessionId == SME_QOS_SEARCH_SESSION_ID_ANY)) + { + if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_1) + { + if(search_key.key.QosFlowID == flow_info->QosFlowID) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: match found on flowID, ending search", + __func__, __LINE__); + status = fnp(pMac, pEntry); + if(eHAL_STATUS_FAILURE == status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Failed to process entry", + __func__, __LINE__); + break; + } + } + } + else if(search_key.index & SME_QOS_SEARCH_KEY_INDEX_2) + { + if(search_key.key.ac_type == flow_info->ac_type) + { + //msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: match found on ac, ending search", + __func__, __LINE__); + flow_info->hoRenewal = pSession->ac_info[flow_info->ac_type].hoRenewal; + status = fnp(pMac, pEntry); + if(eHAL_STATUS_FAILURE == status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Failed to process entry", + __func__, __LINE__); + break; + } + } + } + } + pEntry = pNextEntry; + } + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_QosIsACM() - Utility function to check if a particular AC + mandates Admission Control. + \param ac - Enumeration of the various EDCA Access Categories. + + \return VOS_TRUE if the AC mandates Admission Control + + \sa + + --------------------------------------------------------------------------*/ +v_BOOL_t sme_QosIsACM(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes) +{ + v_BOOL_t ret_val = VOS_FALSE; + tDot11fBeaconIEs *pIesLocal; + if(!pSirBssDesc) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: pSirBssDesc is NULL", + __func__, __LINE__); + return VOS_FALSE; + } + + if (NULL != pIes) + { + /* IEs were provided so use them locally */ + pIesLocal = pIes; + } + else + { + /* IEs were not provided so parse them ourselves */ + if (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: csrGetParsedBssDescriptionIEs() failed", + __func__, __LINE__); + return VOS_FALSE; + } + + /* if success then pIesLocal was allocated */ + } + + if(CSR_IS_QOS_BSS(pIesLocal)) + { + switch(ac) + { + case SME_QOS_EDCA_AC_BE: + if(pIesLocal->WMMParams.acbe_acm) ret_val = VOS_TRUE; + break; + case SME_QOS_EDCA_AC_BK: + if(pIesLocal->WMMParams.acbk_acm) ret_val = VOS_TRUE; + break; + case SME_QOS_EDCA_AC_VI: + if(pIesLocal->WMMParams.acvi_acm) ret_val = VOS_TRUE; + break; + case SME_QOS_EDCA_AC_VO: + if(pIesLocal->WMMParams.acvo_acm) ret_val = VOS_TRUE; + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: unknown AC = %d", + __func__, __LINE__, ac); + //Assert + VOS_ASSERT(0); + break; + } + }//IS_QOS_BSS + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: ACM = %d for AC = %d", + __func__, __LINE__, ret_val, ac ); + if (NULL == pIes) + { + /* IEs were allocated locally so free them */ + vos_mem_free(pIesLocal); + } + return ret_val; +} +/*-------------------------------------------------------------------------- + \brief sme_QosBufferExistingFlows() - Utility function to buffer the existing + flows in flow_list, so that we can renew them after handoff is done. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +static eHalStatus sme_QosBufferExistingFlows(tpAniSirGlobal pMac, + v_U8_t sessionId) +{ + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosSessionInfo *pSession; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosCmdInfo cmd; + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow List empty, nothing to buffer", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if (flow_info->sessionId == sessionId) + { + if((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason )|| + (SME_QOS_REASON_SETUP == flow_info->reason )) + { + cmd.command = SME_QOS_SETUP_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.setupCmdInfo.HDDcontext = flow_info->HDDcontext; + cmd.u.setupCmdInfo.QoSInfo = flow_info->QoSInfo; + cmd.u.setupCmdInfo.QoSCallback = flow_info->QoSCallback; + cmd.u.setupCmdInfo.UPType = SME_QOS_WMM_UP_MAX;//shouldn't be needed + cmd.u.setupCmdInfo.QosFlowID = flow_info->QosFlowID; + if(SME_QOS_REASON_SETUP == flow_info->reason ) + { + cmd.u.setupCmdInfo.hoRenewal = VOS_FALSE; + } + else + { + cmd.u.setupCmdInfo.hoRenewal = VOS_TRUE;//TODO: might need this for modify + } + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the setup request for " + "flow %d in handoff state", + __func__, __LINE__, + flow_info->QosFlowID); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: buffered a setup request for " + "flow %d in handoff state", + __func__, __LINE__, + flow_info->QosFlowID); + } + } + else if(SME_QOS_REASON_RELEASE == flow_info->reason ) + { + cmd.command = SME_QOS_RELEASE_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.releaseCmdInfo.QosFlowID = flow_info->QosFlowID; + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the release request for " + "flow %d in handoff state", + __func__, __LINE__, + flow_info->QosFlowID); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: buffered a release request for " + "flow %d in handoff state", + __func__, __LINE__, + flow_info->QosFlowID); + } + } + else if(SME_QOS_REASON_MODIFY_PENDING == flow_info->reason) + { + cmd.command = SME_QOS_MODIFY_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.modifyCmdInfo.QosFlowID = flow_info->QosFlowID; + cmd.u.modifyCmdInfo.QoSInfo = flow_info->QoSInfo; + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_TRUE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the modify request for " + "flow %d in handoff state", + __func__, __LINE__, + flow_info->QosFlowID); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: buffered a modify request for " + "flow %d in handoff state", + __func__, __LINE__, + flow_info->QosFlowID); + } + } + //delete the entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting original entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + vos_mem_free(flow_info); + } + pEntry = pNextEntry; + } + pSession = &sme_QosCb.sessionInfo[sessionId]; + pSession->uapsdAlreadyRequested = VOS_FALSE; + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosDeleteExistingFlows() - Utility function to Delete the existing + flows in flow_list, if we lost connectivity. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +static eHalStatus sme_QosDeleteExistingFlows(tpAniSirGlobal pMac, + v_U8_t sessionId) +{ + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_TRUE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: %d: Flow List empty, nothing to delete", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_TRUE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + if (flow_info->sessionId == sessionId) + { + if((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason )|| + (SME_QOS_REASON_SETUP == flow_info->reason )|| + (SME_QOS_REASON_RELEASE == flow_info->reason )|| + (SME_QOS_REASON_MODIFY == flow_info->reason )) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + NULL, + SME_QOS_STATUS_RELEASE_QOS_LOST_IND, + flow_info->QosFlowID); + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + //delete the entry from Flow List + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + vos_mem_free(flow_info); + } + pEntry = pNextEntry; + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosBufferCmd() - Utility function to buffer a request (setup/modify/ + release) from client while processing another one on the same AC. + \param pcmd - a pointer to the cmd structure to be saved inside the buffered + cmd link list + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosBufferCmd(sme_QosCmdInfo *pcmd, v_BOOL_t insert_head) +{ + sme_QosSessionInfo *pSession; + sme_QosCmdInfoEntry * pentry = NULL; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked", + __func__, __LINE__); + pentry = (sme_QosCmdInfoEntry *) vos_mem_malloc(sizeof(sme_QosCmdInfoEntry)); + if (!pentry) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Memory allocation failure", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + // copy the entire CmdInfo + pentry->cmdInfo = *pcmd; + + pSession = &sme_QosCb.sessionInfo[pcmd->sessionId]; + if(insert_head) + { + csrLLInsertHead(&pSession->bufferedCommandList, &pentry->link, VOS_TRUE); + } + else + { + csrLLInsertTail(&pSession->bufferedCommandList, &pentry->link, VOS_TRUE); + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosProcessBufferedCmd() - Utility function to process a buffered + request (setup/modify/release) initially came from the client. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +static eHalStatus sme_QosProcessBufferedCmd(v_U8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosCmdInfoEntry *pcmd = NULL; + tListElem *pEntry= NULL; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d", + __func__, __LINE__, + sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + if(!csrLLIsListEmpty( &pSession->bufferedCommandList, VOS_FALSE )) + { + pEntry = csrLLRemoveHead( &pSession->bufferedCommandList, VOS_TRUE ); + if(!pEntry) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: no more buffered commands on session %d", + __func__, __LINE__, + sessionId); + pSession->readyForPowerSave = VOS_TRUE; + return eHAL_STATUS_FAILURE; + } + pcmd = GET_BASE_ADDR( pEntry, sme_QosCmdInfoEntry, link ); + switch(pcmd->cmdInfo.command) + { + case SME_QOS_SETUP_REQ: + hdd_status = sme_QosInternalSetupReq(pcmd->cmdInfo.pMac, + pcmd->cmdInfo.sessionId, + &pcmd->cmdInfo.u.setupCmdInfo.QoSInfo, + pcmd->cmdInfo.u.setupCmdInfo.QoSCallback, + pcmd->cmdInfo.u.setupCmdInfo.HDDcontext, + pcmd->cmdInfo.u.setupCmdInfo.UPType, + pcmd->cmdInfo.u.setupCmdInfo.QosFlowID, + VOS_TRUE, + pcmd->cmdInfo.u.setupCmdInfo.hoRenewal); + if(SME_QOS_STATUS_SETUP_FAILURE_RSP == hdd_status) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosInternalSetupReq failed on session %d", + __func__, __LINE__, + sessionId); + halStatus = eHAL_STATUS_FAILURE; + } + break; + case SME_QOS_RELEASE_REQ: + hdd_status = sme_QosInternalReleaseReq(pcmd->cmdInfo.pMac, + pcmd->cmdInfo.u.releaseCmdInfo.QosFlowID, + VOS_TRUE); + if(SME_QOS_STATUS_RELEASE_FAILURE_RSP == hdd_status) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosInternalReleaseReq failed on session %d", + __func__, __LINE__, + sessionId); + halStatus = eHAL_STATUS_FAILURE; + } + break; + case SME_QOS_MODIFY_REQ: + hdd_status = sme_QosInternalModifyReq(pcmd->cmdInfo.pMac, + &pcmd->cmdInfo.u.modifyCmdInfo.QoSInfo, + pcmd->cmdInfo.u.modifyCmdInfo.QosFlowID, + VOS_TRUE); + if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == hdd_status) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosInternalModifyReq failed on session %d", + __func__, __LINE__, + sessionId); + halStatus = eHAL_STATUS_FAILURE; + } + break; + case SME_QOS_RESEND_REQ: + hdd_status = sme_QosReRequestAddTS(pcmd->cmdInfo.pMac, + pcmd->cmdInfo.sessionId, + &pcmd->cmdInfo.u.resendCmdInfo.QoSInfo, + pcmd->cmdInfo.u.resendCmdInfo.ac, + pcmd->cmdInfo.u.resendCmdInfo.tspecMask); + if(SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == hdd_status) + { + //Err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: sme_QosReRequestAddTS failed on session %d", + __func__, __LINE__, + sessionId); + halStatus = eHAL_STATUS_FAILURE; + } + break; + default: + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unknown cmd = %d", + __func__, __LINE__, + sessionId, pcmd->cmdInfo.command); + VOS_ASSERT(0); + break; + } + // buffered command has been processed, reclaim the memory + vos_mem_free(pcmd); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: cmd buffer empty", + __func__, __LINE__); + pSession->readyForPowerSave = VOS_TRUE; + } + return halStatus; +} +/*-------------------------------------------------------------------------- + \brief sme_QosDeleteBufferedRequests() - Utility function to Delete the buffered + requests in the buffered_cmd_list, if we lost connectivity. + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +static eHalStatus sme_QosDeleteBufferedRequests(tpAniSirGlobal pMac, + v_U8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosCmdInfoEntry *pcmd = NULL; + tListElem *pEntry= NULL, *pNextEntry = NULL; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_QosCb.sessionInfo[sessionId]; + pEntry = csrLLPeekHead( &pSession->bufferedCommandList, VOS_TRUE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: %d: Buffered List empty, nothing to delete on session %d", + __func__, __LINE__, + sessionId); + return eHAL_STATUS_FAILURE; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &pSession->bufferedCommandList, pEntry, VOS_TRUE ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: %d: deleting entry from buffered List", + __func__, __LINE__); + //delete the entry from Flow List + csrLLRemoveEntry(&pSession->bufferedCommandList, pEntry, VOS_TRUE ); + // reclaim the memory + pcmd = GET_BASE_ADDR( pEntry, sme_QosCmdInfoEntry, link ); + vos_mem_free(pcmd); + pEntry = pNextEntry; + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosSaveAssocInfo() - Utility function to save the assoc info in the + CB like BSS descriptor of the AP, the profile that HDD sent down with the + connect request, while CSR notifies for assoc/reassoc success. + \param pAssoc_info - pointer to the assoc structure to store the BSS + descriptor of the AP, the profile that HDD sent down with + the connect request + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosSaveAssocInfo(sme_QosSessionInfo *pSession, sme_QosAssocInfo *pAssoc_info) +{ + tSirBssDescription *pBssDesc = NULL; + v_U32_t bssLen = 0; + if(NULL == pAssoc_info) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: pAssoc_info is NULL", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + //clean up the assoc info if already set + if(pSession->assocInfo.pBssDesc) + { + vos_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + bssLen = pAssoc_info->pBssDesc->length + + sizeof(pAssoc_info->pBssDesc->length); + //save the bss Descriptor + pBssDesc = (tSirBssDescription *)vos_mem_malloc(bssLen); + if (!pBssDesc) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the bss Descriptor", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(pBssDesc, pAssoc_info->pBssDesc, bssLen); + pSession->assocInfo.pBssDesc = pBssDesc; + //save the apsd info from assoc + if(pAssoc_info->pProfile) + { + pSession->apsdMask |= pAssoc_info->pProfile->uapsd_mask; + } + // [TODO] Do we need to update the global APSD bitmap? + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosSetupFnp() - Utility function (pointer) to notify other entries + in FLOW list on the same AC that qos params got modified + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosSetupFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND; + sme_QosEdcaAcType ac; + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + if(SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) + { + //notify HDD, only the other Flows running on the AC + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + hdd_status, + flow_info->QosFlowID); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Entry with flowID = %d getting notified", + __func__, __LINE__, + flow_info->QosFlowID); + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosModificationNotifyFnp() - Utility function (pointer) to notify + other entries in FLOW list on the same AC that qos params got modified + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosModificationNotifyFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND; + sme_QosEdcaAcType ac; + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + if(SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) + { + //notify HDD, only the other Flows running on the AC + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[flow_info->tspec_mask - 1], + hdd_status, + flow_info->QosFlowID); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Entry with flowID = %d getting notified", + __func__, __LINE__, + flow_info->QosFlowID); + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosModifyFnp() - Utility function (pointer) to delete the original + entry in FLOW list & add the modified one + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosModifyFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosFlowInfoEntry *flow_info = NULL; + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + switch(flow_info->reason) + { + case SME_QOS_REASON_MODIFY_PENDING: + //set the proper reason code for the new (with modified params) entry + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + break; + case SME_QOS_REASON_MODIFY: + //delete the original entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting original entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + // reclaim the memory + vos_mem_free(flow_info); + break; + default: + break; + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosDelTsIndFnp() - Utility function (pointer) to find all Flows on + the particular AC & delete them, also send HDD indication through the callback + it registered per request + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosDelTsIndFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosEdcaAcType ac; + eHalStatus lock_status = eHAL_STATUS_FAILURE; + sme_QosStatusType status; + + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + //delete the entry from Flow List + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + pACInfo->relTrig = SME_QOS_RELEASE_BY_AP; + + lock_status = sme_AcquireGlobalLock( &pMac->sme ); + if ( !HAL_STATUS_SUCCESS( lock_status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Unable to obtain lock", + __func__, __LINE__); + return SME_QOS_STATUS_RELEASE_FAILURE_RSP; + } + //Call the internal function for QoS release, adding a layer of abstraction + status = sme_QosInternalReleaseReq(pMac, flow_info->QosFlowID, VOS_FALSE); + sme_ReleaseGlobalLock( &pMac->sme ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Release return status on Flow %d is %d", + __func__, __LINE__, + flow_info->QosFlowID, status); + + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosReassocSuccessEvFnp() - Utility function (pointer) to notify HDD + the success for the requested flow & notify all the other flows running on the + same AC that QoS params got modified + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosReassocSuccessEvFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + v_BOOL_t delete_entry = VOS_FALSE; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + sme_QosEdcaAcType ac; + eHalStatus pmc_status = eHAL_STATUS_FAILURE; + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + switch(flow_info->reason) + { + case SME_QOS_REASON_SETUP: + hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND; + delete_entry = VOS_FALSE; + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + //check for the case where we had to do reassoc to reset the apsd bit + //for the ac - release or modify scenario + if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb) + { + // notify PMC as App is looking for APSD. If we already requested + // then we don't need to do anything. + if(!pSession->uapsdAlreadyRequested) + { + // this is the first flow to detect we need PMC in UAPSD mode + if(!pMac->psOffloadEnabled) + { + pmc_status = pmcStartUapsd(pMac, + sme_QosPmcStartUapsdCallback, + pSession); + } + else + { + pmc_status = pmcOffloadStartUapsd(pMac, + flow_info->sessionId, + sme_QosPmcOffloadStartUapsdCallback, + pSession); + } + + // if PMC doesn't return success right away means it is yet to put + // the module in BMPS state & later to UAPSD state + + if(eHAL_STATUS_FAILURE == pmc_status) + { + hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED; + //we need to always notify this case + flow_info->hoRenewal = VOS_FALSE; + } + else if(eHAL_STATUS_PMC_PENDING == pmc_status) + { + // let other flows know PMC has been notified + pSession->uapsdAlreadyRequested = VOS_TRUE; + } + // for any other pmc status we declare success + } + } + break; + case SME_QOS_REASON_RELEASE: + pACInfo->num_flows[SME_QOS_TSPEC_INDEX_0]--; + // fall through + case SME_QOS_REASON_MODIFY: + delete_entry = VOS_TRUE; + break; + case SME_QOS_REASON_MODIFY_PENDING: + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND; + delete_entry = VOS_FALSE; + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + if(pACInfo->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb) + { + + if(!pSession->uapsdAlreadyRequested) + { + if(!pMac->psOffloadEnabled) + { + // this is the first flow to detect we need PMC in UAPSD mode + pmc_status = pmcStartUapsd(pMac, + sme_QosPmcStartUapsdCallback, + pSession); + } + else + { + // this is the first flow to detect we need PMC in UAPSD mode + pmc_status = pmcOffloadStartUapsd(pMac, + flow_info->sessionId, + sme_QosPmcOffloadStartUapsdCallback, + pSession); + } + + // if PMC doesn't return success right away means it is yet to put + // the module in BMPS state & later to UAPSD state + if(eHAL_STATUS_FAILURE == pmc_status) + { + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED; + // we need to always notify this case + flow_info->hoRenewal = VOS_FALSE; + } + else if(eHAL_STATUS_PMC_PENDING == pmc_status) + { + pSession->uapsdAlreadyRequested = VOS_TRUE; + } + // for any other pmc status we declare success + } + } + break; + case SME_QOS_REASON_REQ_SUCCESS: + hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND; + // fall through + default: + delete_entry = VOS_FALSE; + break; + } + if(!delete_entry) + { + if(!flow_info->hoRenewal) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + hdd_status, + flow_info->QosFlowID); + } + else + { + flow_info->hoRenewal = VOS_FALSE; + } + } + else + { + //delete the entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + // reclaim the memory + vos_mem_free(flow_info); + } + + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosAddTsFailureFnp() - Utility function (pointer), + if the Addts request was for for an flow setup request, delete the entry from + Flow list & notify HDD + if the Addts request was for downgrading of QoS params because of an flow + release requested on the AC, delete the entry from Flow list & notify HDD + if the Addts request was for change of QoS params because of an flow + modification requested on the AC, delete the new entry from Flow list & notify + HDD + + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosAddTsFailureFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + v_BOOL_t inform_hdd = VOS_FALSE; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + sme_QosEdcaAcType ac; + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + switch(flow_info->reason) + { + case SME_QOS_REASON_SETUP: + hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + pACInfo->num_flows[pACInfo->tspec_pending - 1]--; + inform_hdd = VOS_TRUE; + break; + case SME_QOS_REASON_RELEASE: + hdd_status = SME_QOS_STATUS_RELEASE_FAILURE_RSP; + pACInfo->num_flows[pACInfo->tspec_pending - 1]--; + inform_hdd = VOS_TRUE; + break; + case SME_QOS_REASON_MODIFY_PENDING: + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + inform_hdd = VOS_TRUE; + break; + case SME_QOS_REASON_MODIFY: + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + case SME_QOS_REASON_REQ_SUCCESS: + default: + inform_hdd = VOS_FALSE; + break; + } + if(inform_hdd) + { + //notify HDD, only the requested Flow, other Flows running on the AC stay + // intact + if(!flow_info->hoRenewal) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1], + hdd_status, + flow_info->QosFlowID); + } + else + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1], + SME_QOS_STATUS_RELEASE_QOS_LOST_IND, + flow_info->QosFlowID); + } + //delete the entry from Flow List + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + // reclaim the memory + vos_mem_free(flow_info); + } + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosAddTsSuccessFnp() - Utility function (pointer), + if the Addts request was for for an flow setup request, notify HDD for success + for the flow & notify all the other flows running on the same AC that QoS + params got modified + if the Addts request was for downgrading of QoS params because of an flow + release requested on the AC, delete the entry from Flow list & notify HDD + if the Addts request was for change of QoS params because of an flow + modification requested on the AC, delete the old entry from Flow list & notify + HDD for success for the flow & notify all the other flows running on the same + AC that QoS params got modified + \param pMac - Pointer to the global MAC parameter structure. + \param pEntry - Pointer to an entry in the flow_list(i.e. tListElem structure) + + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosAddTsSuccessFnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + v_BOOL_t inform_hdd = VOS_FALSE; + v_BOOL_t delete_entry = VOS_FALSE; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + sme_QosEdcaAcType ac; + eHalStatus pmc_status = eHAL_STATUS_FAILURE; + tCsrRoamModifyProfileFields modifyProfileFields; + + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", + __func__, __LINE__); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + ac = flow_info->ac_type; + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + if(flow_info->tspec_mask != pACInfo->tspec_pending) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: No need to notify the HDD, the ADDTS " + "success is not for index = %d of the AC = %d", + __func__, __LINE__, + flow_info->tspec_mask, ac); + return eHAL_STATUS_SUCCESS; + } + switch(flow_info->reason) + { + case SME_QOS_REASON_SETUP: + hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND; + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + delete_entry = VOS_FALSE; + inform_hdd = VOS_TRUE; + // check if App is looking for APSD + if(pACInfo->requested_QoSInfo[pACInfo->tspec_pending - 1].ts_info.psb) + { + // notify PMC as App is looking for APSD. If we already requested + // then we don't need to do anything + if(!pSession->uapsdAlreadyRequested) + { + if(!pMac->psOffloadEnabled) + { + // this is the first flow to detect we need PMC in UAPSD mode + pmc_status = pmcStartUapsd(pMac, + sme_QosPmcStartUapsdCallback, + pSession); + } + else + { + // this is the first flow to detect we need PMC in UAPSD mode + pmc_status = pmcOffloadStartUapsd(pMac, + flow_info->sessionId, + sme_QosPmcOffloadStartUapsdCallback, + pSession); + } + + // if PMC doesn't return success right away means it is yet to put + // the module in BMPS state & later to UAPSD state + if(eHAL_STATUS_FAILURE == pmc_status) + { + hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED; + // we need to always notify this case + flow_info->hoRenewal = VOS_FALSE; + } + else if(eHAL_STATUS_PMC_PENDING == pmc_status) + { + // let other flows know PMC has been notified + pSession->uapsdAlreadyRequested = VOS_TRUE; + } + // for any other pmc status we declare success + } + } + break; + case SME_QOS_REASON_RELEASE: + pACInfo->num_flows[pACInfo->tspec_pending - 1]--; + hdd_status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP; + inform_hdd = VOS_TRUE; + delete_entry = VOS_TRUE; + break; + case SME_QOS_REASON_MODIFY: + delete_entry = VOS_TRUE; + inform_hdd = VOS_FALSE; + break; + case SME_QOS_REASON_MODIFY_PENDING: + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND; + delete_entry = VOS_FALSE; + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + inform_hdd = VOS_TRUE; + //notify PMC if App is looking for APSD + if(pACInfo->requested_QoSInfo[pACInfo->tspec_pending - 1].ts_info.psb) + { + // notify PMC as App is looking for APSD. If we already requested + // then we don't need to do anything. + if(!pSession->uapsdAlreadyRequested) + { + if(!pMac->psOffloadEnabled) + { + // this is the first flow to detect we need PMC in UAPSD mode + pmc_status = pmcStartUapsd(pMac, + sme_QosPmcStartUapsdCallback, + pSession); + } + else + { + // this is the first flow to detect we need PMC in UAPSD mode + pmc_status = pmcOffloadStartUapsd(pMac, + flow_info->sessionId, + sme_QosPmcOffloadStartUapsdCallback, + pSession); + } + + // if PMC doesn't return success right away means it is yet to put + // the module in BMPS state & later to UAPSD state + if(eHAL_STATUS_FAILURE == pmc_status) + { + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND_APSD_SET_FAILED; + // we need to always notify this case + flow_info->hoRenewal = VOS_FALSE; + } + else if(eHAL_STATUS_PMC_PENDING == pmc_status) + { + // let other flows know PMC has been notified + pSession->uapsdAlreadyRequested = VOS_TRUE; + } + // for any other pmc status we declare success + } + } + else + { + if((pACInfo->num_flows[flow_info->tspec_mask - 1] == 1) && + (SME_QOS_TSPEC_MASK_BIT_1_2_SET != pACInfo->tspec_mask_status)) + { + // this is the only TSPEC active on this AC + // so indicate that we no longer require APSD + pSession->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + //Also update modifyProfileFields.uapsd_mask in CSR for consistency + csrGetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields); + modifyProfileFields.uapsd_mask = pSession->apsdMask; + csrSetModifyProfileFields(pMac, flow_info->sessionId, &modifyProfileFields); + if(!pSession->apsdMask) + { + if(!pMac->psOffloadEnabled) + { + // this session no longer needs UAPSD + // do any sessions still require UAPSD? + if (!sme_QosIsUapsdActive()) + { + // No sessions require UAPSD so turn it off + // (really don't care when PMC stops it) + (void)pmcStopUapsd(pMac); + } + } + else + { + (void)pmcOffloadStopUapsd(pMac, flow_info->sessionId); + } + } + } + } + break; + case SME_QOS_REASON_REQ_SUCCESS: + hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND; + inform_hdd = VOS_TRUE; + default: + delete_entry = VOS_FALSE; + break; + } + if(inform_hdd) + { + if(!flow_info->hoRenewal) + { + + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1], + hdd_status, + flow_info->QosFlowID); + } + else + { + /* + * For downgrading purpose, Hdd set WmmTspecValid to false during + * roaming. Need to set that flag. Call the hdd callback in successful + * case. + */ + if ((hdd_status == SME_QOS_STATUS_SETUP_SUCCESS_IND) +#if defined (WLAN_FEATURE_VOWIFI_11R) + && + (!csrRoamIs11rAssoc(pMac, flow_info->sessionId)) +#endif +#if defined(FEATURE_WLAN_ESE) + && + (!csrRoamIsESEAssoc(pMac, flow_info->sessionId)) +#endif + ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s calling hdd_wmm_smecallback during roaming for ac = %d", __func__, ac); + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pACInfo->curr_QoSInfo[pACInfo->tspec_pending - 1], + hdd_status, + flow_info->QosFlowID + ); + } + flow_info->hoRenewal = VOS_FALSE; + } + } + if(delete_entry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, + flow_info, flow_info->QosFlowID); + //delete the entry from Flow List + csrLLRemoveEntry(&sme_QosCb.flow_list, pEntry, VOS_TRUE ); + // reclaim the memory + vos_mem_free(flow_info); + } + + return eHAL_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + \brief sme_QosIsRspPending() - Utility function to check if we are waiting + for an AddTS or reassoc response on some AC other than the given AC + + \param sessionId - Session we are interested in + \param ac - Enumeration of the various EDCA Access Categories. + + \return boolean + TRUE - Response is pending on an AC + + \sa + + --------------------------------------------------------------------------*/ +static v_BOOL_t sme_QosIsRspPending(v_U8_t sessionId, sme_QosEdcaAcType ac) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType acIndex; + v_BOOL_t status = VOS_FALSE; + pSession = &sme_QosCb.sessionInfo[sessionId]; + for(acIndex = SME_QOS_EDCA_AC_BE; acIndex < SME_QOS_EDCA_AC_MAX; acIndex++) + { + if(acIndex == ac) + { + continue; + } + pACInfo = &pSession->ac_info[acIndex]; + if((pACInfo->tspec_pending) || (pACInfo->reassoc_pending)) + { + status = VOS_TRUE; + break; + } + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosUpdateHandOff() - Function which can be called to update + Hand-off state of SME QoS Session + \param sessionId - session id + \param updateHandOff - value True/False to update the handoff flag + + \sa + +-------------------------------------------------------------------------*/ +void sme_QosUpdateHandOff(v_U8_t sessionId, + v_BOOL_t updateHandOff) +{ + sme_QosSessionInfo *pSession; + pSession = &sme_QosCb.sessionInfo[sessionId]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "%s: %d: handoffRequested %d updateHandOff %d", + __func__, __LINE__,pSession->handoffRequested, + updateHandOff); + + pSession->handoffRequested = updateHandOff; + +} + +/*-------------------------------------------------------------------------- + \brief sme_QosIsUapsdActive() - Function which can be called to determine + if any sessions require PMC to be in U-APSD mode. + \return boolean + + Returns true if at least one session required PMC to be in U-APSD mode + Returns false if no sessions require PMC to be in U-APSD mode + + \sa + + --------------------------------------------------------------------------*/ +static v_BOOL_t sme_QosIsUapsdActive(void) +{ + sme_QosSessionInfo *pSession; + v_U8_t sessionId; + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) + { + pSession = &sme_QosCb.sessionInfo[sessionId]; + if ((pSession->sessionActive) && (pSession->apsdMask)) + { + return VOS_TRUE; + } + } + // no active sessions have U-APSD active + return VOS_FALSE; +} +/*-------------------------------------------------------------------------- + \brief sme_QosPmcFullPowerCallback() - Callback function registered with PMC + to notify SME-QoS when it puts the chip into full power + + \param callbackContext - The context passed to PMC during pmcRequestFullPower + call. + \param status - eHalStatus returned by PMC. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_QosPmcFullPowerCallback(void *callbackContext, eHalStatus status) +{ + sme_QosSessionInfo *pSession = callbackContext; + if(HAL_STATUS_SUCCESS(status)) + { + (void)sme_QosProcessBufferedCmd(pSession->sessionId); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: PMC failed to put the chip in Full power", + __func__, __LINE__); + VOS_ASSERT(0); + } +} + +void sme_QosPmcOffloadFullPowerCallback(void *callbackContext, tANI_U32 sessionId, + eHalStatus status) +{ + sme_QosSessionInfo *pSession = callbackContext; + if(HAL_STATUS_SUCCESS(status)) + { + (void)sme_QosProcessBufferedCmd(pSession->sessionId); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: PMC failed to put the chip in Full power", + __func__, __LINE__); + VOS_ASSERT(0); + } +} + +/*-------------------------------------------------------------------------- + \brief sme_QosPmcStartUAPSDCallback() - Callback function registered with PMC + to notify SME-QoS when it puts the chip into UAPSD mode + + \param callbackContext - The context passed to PMC during pmcStartUapsd call. + \param status - eHalStatus returned by PMC. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_QosPmcStartUapsdCallback(void *callbackContext, eHalStatus status) +{ + sme_QosSessionInfo *pSession = callbackContext; + // NOTE WELL + // + // In the original QoS design the TL module was responsible for + // the generation of trigger frames. When that design was in + // use, we had to queue up any flows which were waiting for PMC + // since we didn't want to notify HDD until PMC had changed to + // UAPSD state. Otherwise HDD would provide TL with the trigger + // frame parameters, and TL would start trigger frame generation + // before PMC was ready. The flows were queued in various places + // throughout this module, and they were dequeued here following + // a successful transition to the UAPSD state by PMC. + // + // In the current QoS design the Firmware is responsible for the + // generation of trigger frames, but the parameters are still + // provided by TL via HDD. The Firmware will be notified of the + // change to UAPSD state directly by PMC, at which time it will be + // responsible for the generation of trigger frames. Therefore + // where we used to queue up flows waiting for PMC to transition + // to the UAPSD state, we now always transition directly to the + // "success" state so that HDD will immediately provide the trigger + // frame parameters to TL, who will in turn plumb them down to the + // Firmware. That way the Firmware will have the trigger frame + // parameters when it needs them + // just note that there is no longer an outstanding request + pSession->uapsdAlreadyRequested = VOS_FALSE; +} + +void sme_QosPmcOffloadStartUapsdCallback(void *callbackContext, + tANI_U32 sessionId, eHalStatus status) +{ + sme_QosSessionInfo *pSession = callbackContext; + pSession->uapsdAlreadyRequested = VOS_FALSE; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosPmcCheckRoutine() - Function registered with PMC to check with + SME-QoS whenever the device is about to enter one of the power + save modes. PMC runs a poll with all the registered modules if device can + enter power save mode or remain in full power + + \param callbackContext - The context passed to PMC during registration through + pmcRegisterPowerSaveCheck. + \return boolean + + SME-QOS returns PMC true or false respectively if it wants to vote for + entering power save or not + + \sa + + --------------------------------------------------------------------------*/ +v_BOOL_t sme_QosPmcCheckRoutine(void *callbackContext) +{ + sme_QosSessionInfo *pSession; + v_U8_t sessionId; + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) + { + pSession = &sme_QosCb.sessionInfo[sessionId]; + if ((pSession->sessionActive) && + (!pSession->readyForPowerSave)) + { + return VOS_FALSE; + } + } + /* All active sessions have voted for power save */ + return VOS_TRUE; +} + +v_BOOL_t sme_QosPmcOffloadCheckRoutine(void *callbackContext, tANI_U32 sessionId) +{ + sme_QosSessionInfo *pSession = &sme_QosCb.sessionInfo[sessionId]; + + if ((pSession->sessionActive) && + (!pSession->readyForPowerSave)) + { + return VOS_FALSE; + } + return VOS_TRUE; + +} + +/*-------------------------------------------------------------------------- + \brief sme_QosPmcDeviceStateUpdateInd() - Callback function registered with + PMC to notify SME-QoS when it changes the power state + + \param callbackContext - The context passed to PMC during registration + through pmcRegisterDeviceStateUpdateInd. + \param pmcState - Current power state that PMC moved into. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_QosPmcDeviceStateUpdateInd(void *callbackContext, tPmcState pmcState) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( callbackContext ); + //check all the entries in Flow list for non-zero service interval, which will + //tell us if we need to notify HDD when PMC is out of UAPSD mode or going + // back to UAPSD mode + switch(pmcState) + { + case FULL_POWER: + status = sme_QosProcessOutOfUapsdMode(pMac); + break; + case UAPSD: + status = sme_QosProcessIntoUapsdMode(pMac); + break; + default: + status = eHAL_STATUS_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: nothing to process in PMC state %s (%d)", + __func__, __LINE__, + sme_PmcStatetoString(pmcState), pmcState); + + } + if(!HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: ignoring Device(PMC) state change to %s (%d)", + __func__, __LINE__, + sme_PmcStatetoString(pmcState), pmcState); + } + +} + +void sme_OffloadQosPmcDeviceStateUpdateInd(void *callbackContext, + tANI_U32 sessionId, tPmcState pmcState) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( callbackContext ); + /* + * check all the entries in Flow list for non-zero service interval, + * which will tell us if we need to notify HDD when + * PMC is out of UAPSD mode or going + * back to UAPSD mode + */ + switch(pmcState) + { + case FULL_POWER: + status = sme_OffloadQosProcessOutOfUapsdMode(pMac, sessionId); + break; + case UAPSD: + status = sme_OffloadQosProcessIntoUapsdMode(pMac, sessionId); + break; + default: + status = eHAL_STATUS_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: nothing to process in PMC state %d", + __func__, __LINE__, + pmcState); + } + if(!HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: ignoring Device(PMC) state change to %d", + __func__, __LINE__, + pmcState); + } +} + +/*-------------------------------------------------------------------------- + \brief sme_QosProcessOutOfUapsdMode() - Function to notify HDD when PMC + notifies SME-QoS that it moved out of UAPSD mode to FULL power + + \param pMac - Pointer to the global MAC parameter structure. + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessOutOfUapsdMode(tpAniSirGlobal pMac) +{ + sme_QosSessionInfo *pSession; + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + //only notify the flows which already successfully setup UAPSD + if((flow_info->QoSInfo.max_service_interval || + flow_info->QoSInfo.min_service_interval) && + (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pSession->ac_info[flow_info->ac_type].curr_QoSInfo[flow_info->tspec_mask - 1], + SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND, + flow_info->QosFlowID); + } + pEntry = pNextEntry; + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus sme_OffloadQosProcessOutOfUapsdMode(tpAniSirGlobal pMac, + tANI_U32 sessionId) +{ + sme_QosSessionInfo *pSession; + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while(pEntry) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + /* only notify the flows which already successfully setup UAPSD */ + if((sessionId == flow_info->sessionId) && + (flow_info->QoSInfo.max_service_interval || + flow_info->QoSInfo.min_service_interval) && + (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pSession->ac_info[flow_info->ac_type]. + curr_QoSInfo[flow_info->tspec_mask - 1], + SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND, + flow_info->QosFlowID); + } + pEntry = pNextEntry; + } + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_QosProcessIntoUapsdMode() - Function to notify HDD when PMC + notifies SME-QoS that it is moving into UAPSD mode + + \param pMac - Pointer to the global MAC parameter structure. + \return eHalStatus + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_QosProcessIntoUapsdMode(tpAniSirGlobal pMac) +{ + sme_QosSessionInfo *pSession; + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while( pEntry ) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + //only notify the flows which already successfully setup UAPSD + if( (flow_info->QoSInfo.ts_info.psb) && + (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) ) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pSession->ac_info[flow_info->ac_type].curr_QoSInfo[flow_info->tspec_mask - 1], + SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND, + flow_info->QosFlowID); + } + pEntry = pNextEntry; + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus sme_OffloadQosProcessIntoUapsdMode(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + sme_QosSessionInfo *pSession; + tListElem *pEntry= NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + pEntry = csrLLPeekHead( &sme_QosCb.flow_list, VOS_FALSE ); + if(!pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return eHAL_STATUS_FAILURE; + } + while(pEntry) + { + pNextEntry = csrLLNext( &sme_QosCb.flow_list, pEntry, VOS_FALSE ); + flow_info = GET_BASE_ADDR( pEntry, sme_QosFlowInfoEntry, link ); + pSession = &sme_QosCb.sessionInfo[flow_info->sessionId]; + /* only notify the flows which already successfully setup UAPSD */ + if((sessionId == flow_info->sessionId) && + (flow_info->QoSInfo.max_service_interval || + flow_info->QoSInfo.min_service_interval) && + (SME_QOS_REASON_REQ_SUCCESS == flow_info->reason)) + { + flow_info->QoSCallback(pMac, flow_info->HDDcontext, + &pSession->ac_info[flow_info->ac_type]. + curr_QoSInfo[flow_info->tspec_mask - 1], + SME_QOS_STATUS_INTO_APSD_POWER_MODE_IND, + flow_info->QosFlowID); + } + pEntry = pNextEntry; + } + return eHAL_STATUS_SUCCESS; +} + +void sme_QosCleanupCtrlBlkForHandoff(tpAniSirGlobal pMac, v_U8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + pSession = &sme_QosCb.sessionInfo[sessionId]; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + vos_mem_zero(pACInfo->curr_QoSInfo, + sizeof(sme_QosWmmTspecInfo) * SME_QOS_TSPEC_INDEX_MAX); + vos_mem_zero(pACInfo->requested_QoSInfo, + sizeof(sme_QosWmmTspecInfo) * SME_QOS_TSPEC_INDEX_MAX); + pACInfo->num_flows[0] = 0; + pACInfo->num_flows[1] = 0; + pACInfo->reassoc_pending = VOS_FALSE; + pACInfo->tspec_mask_status = 0; + pACInfo->tspec_pending = VOS_FALSE; + pACInfo->hoRenewal = VOS_FALSE; + pACInfo->prev_state = SME_QOS_LINK_UP; + } +} + +/*-------------------------------------------------------------------------- + \brief sme_QosIsTSInfoAckPolicyValid() - The SME QoS API exposed to HDD to + check if TS info ack policy field can be set to "HT-immediate block + acknowledgment" + + \param pMac - The handle returned by macOpen. + \param pQoSInfo - Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + related info, provided by HDD + \param sessionId - sessionId returned by sme_OpenSession. + + \return VOS_TRUE - Current Association is HT association and so TS info ack policy + can be set to "HT-immediate block acknowledgment" + + \sa + + --------------------------------------------------------------------------*/ +v_BOOL_t sme_QosIsTSInfoAckPolicyValid(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo * pQoSInfo, + v_U8_t sessionId) +{ + tDot11fBeaconIEs *pIes = NULL; + sme_QosSessionInfo *pSession; + eHalStatus hstatus; + if( !CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Session Id %d is invalid", + __func__, __LINE__, + sessionId); + return VOS_FALSE; + } + + pSession = &sme_QosCb.sessionInfo[sessionId]; + + if( !pSession->sessionActive ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Session %d is inactive", + __func__, __LINE__, + sessionId); + return VOS_FALSE; + } + + if(!pSession->assocInfo.pBssDesc) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Session %d has an Invalid BSS Descriptor", + __func__, __LINE__, + sessionId); + return VOS_FALSE; + } + + hstatus = csrGetParsedBssDescriptionIEs(pMac, + pSession->assocInfo.pBssDesc, + &pIes); + if(!HAL_STATUS_SUCCESS(hstatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unable to parse BSS IEs", + __func__, __LINE__, + sessionId); + return VOS_FALSE; + } + + /* success means pIes was allocated */ + + if(!pIes->HTCaps.present && + pQoSInfo->ts_info.ack_policy == SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d HT Caps aren't present but application set ack policy to HT ", + __func__, __LINE__, + sessionId); + + vos_mem_free(pIes); + return VOS_FALSE; + } + + vos_mem_free(pIes); + return VOS_TRUE; +} + +v_BOOL_t sme_QosValidateRequestedParams(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo * pQoSInfo, + v_U8_t sessionId) +{ + v_BOOL_t rc = VOS_FALSE; + + do + { + if(SME_QOS_WMM_TS_DIR_RESV == pQoSInfo->ts_info.direction) break; + if(!sme_QosIsTSInfoAckPolicyValid(pMac, pQoSInfo, sessionId)) break; + + rc = VOS_TRUE; + }while(0); + return rc; +} + +static eHalStatus qosIssueCommand( tpAniSirGlobal pMac, v_U8_t sessionId, + eSmeCommandType cmdType, sme_QosWmmTspecInfo * pQoSInfo, + sme_QosEdcaAcType ac, v_U8_t tspec_mask ) +{ + eHalStatus status = eHAL_STATUS_RESOURCES; + tSmeCmd *pCommand = NULL; + do + { + pCommand = smeGetCommandBuffer( pMac ); + if ( !pCommand ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: fail to get command buffer for command %d", + __func__, __LINE__, cmdType); + break; + } + pCommand->command = cmdType; + pCommand->sessionId = sessionId; + switch ( cmdType ) + { + case eSmeCommandAddTs: + if( pQoSInfo ) + { + status = eHAL_STATUS_SUCCESS; + pCommand->u.qosCmd.tspecInfo = *pQoSInfo; + pCommand->u.qosCmd.ac = ac; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: NULL pointer passed", + __func__, __LINE__); + status = eHAL_STATUS_INVALID_PARAMETER; + } + break; + case eSmeCommandDelTs: + status = eHAL_STATUS_SUCCESS; + pCommand->u.qosCmd.ac = ac; + pCommand->u.qosCmd.tspec_mask = tspec_mask; + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid command type %d", + __func__, __LINE__, cmdType ); + status = eHAL_STATUS_INVALID_PARAMETER; + break; + } + } while( 0 ); + if( HAL_STATUS_SUCCESS( status ) && pCommand ) + { + smePushCommand( pMac, pCommand, eANI_BOOLEAN_FALSE ); + } + else if( pCommand ) + { + qosReleaseCommand( pMac, pCommand ); + } + return( status ); +} +tANI_BOOLEAN qosProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE; + do + { + switch ( pCommand->command ) + { + case eSmeCommandAddTs: + status = sme_QosAddTsReq( pMac, (v_U8_t)pCommand->sessionId, &pCommand->u.qosCmd.tspecInfo, pCommand->u.qosCmd.ac); + if( HAL_STATUS_SUCCESS( status ) ) + { + fRemoveCmd = eANI_BOOLEAN_FALSE; + status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + } + break; + case eSmeCommandDelTs: + status = sme_QosDelTsReq( pMac, (v_U8_t)pCommand->sessionId, pCommand->u.qosCmd.ac, pCommand->u.qosCmd.tspec_mask ); + if( HAL_STATUS_SUCCESS( status ) ) + { + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: invalid command type %d", + __func__, __LINE__, pCommand->command ); + break; + }//switch + } while(0); + return( fRemoveCmd ); +} + +/* + sme_QosTriggerUapsdChange + Invoked by BTC when UAPSD bypass is enabled or disabled + We, in turn, must disable or enable UAPSD on all flows as appropriate + That may require us to re-add TSPECs or to reassociate +*/ +sme_QosStatusType sme_QosTriggerUapsdChange( tpAniSirGlobal pMac ) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + v_U8_t ac, tspec1 = 0, tspec2 = 0; + v_U8_t uapsd_mask; + tDot11fBeaconIEs *pIesLocal; + v_U8_t acm_mask; + v_BOOL_t fIsUapsdNeeded; + v_U8_t sessionId; + v_BOOL_t addtsWhenACMNotSet = CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked", + __func__, __LINE__); + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) + { + pSession = &sme_QosCb.sessionInfo[sessionId]; + if( !pSession->sessionActive ) + { + continue; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Session %d is active", + __func__, __LINE__, + sessionId); + if( HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSession->assocInfo.pBssDesc, &pIesLocal)) ) + { + // get the ACM mask + acm_mask = sme_QosGetACMMask(pMac, pSession->assocInfo.pBssDesc, pIesLocal); + vos_mem_free(pIesLocal); + // get the uapsd mask for this session + uapsd_mask = pSession->apsdMask; + // unmask the bits with ACM on to avoid reassoc on them + uapsd_mask &= ~acm_mask; + // iterate through the ACs to determine if we need to re-add any TSPECs + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + // Does this AC have QoS active? + if( SME_QOS_QOS_ON == pACInfo->curr_state ) + { + // Yes, QoS is active on this AC + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AC %d has QoS active", + __func__, __LINE__, + sessionId, ac); + // Does this AC require ACM? + if(( acm_mask & (1 << (SME_QOS_EDCA_AC_VO - ac)) ) || addtsWhenACMNotSet ) + { + // Yes, so we need to re-add any TSPECS + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AC %d has ACM enabled", + __func__, __LINE__, + sessionId, ac); + // Are any TSPECs active? + if( pACInfo->tspec_mask_status ) + { + // Yes, at least 1 TSPEC is active. Are they both active? + if( SME_QOS_TSPEC_MASK_BIT_1_2_SET == pACInfo->tspec_mask_status ) + { + //both TSPECS are active + tspec1 = SME_QOS_TSPEC_MASK_BIT_1_SET; + tspec2 = SME_QOS_TSPEC_MASK_BIT_2_SET; + } + else + { + // only one TSPEC is active, get its mask + tspec1 = SME_QOS_TSPEC_MASK_BIT_1_2_SET & pACInfo->tspec_mask_status; + } + // Does TSPEC 1 really require UAPSD? + fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[tspec1 - 1].ts_info.psb); + //double check whether we need to do anything + if( fIsUapsdNeeded ) + { + pACInfo->requested_QoSInfo[tspec1 - 1] = + pACInfo->curr_QoSInfo[tspec1 - 1]; + sme_QosReRequestAddTS( pMac, sessionId, + &pACInfo->requested_QoSInfo[tspec1 - 1], + ac, + tspec1 ); + } + // Is TSPEC 2 active? + if( tspec2 ) + { + // Does TSPEC 2 really require UAPSD? + fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[tspec2 - 1].ts_info.psb); + if( fIsUapsdNeeded ) + { + //No need to inform HDD + //pACInfo->hoRenewal = VOS_TRUE; + pACInfo->requested_QoSInfo[tspec2 - 1] = + pACInfo->curr_QoSInfo[tspec2 - 1]; + sme_QosReRequestAddTS( pMac, sessionId, + &pACInfo->requested_QoSInfo[tspec2 - 1], + ac, + tspec2); + } + } + } + else + { + // QoS is set, ACM is on, but no TSPECs -- inconsistent state + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d has QoS enabled and ACM is set, but no TSPEC", + __func__, __LINE__, + sessionId, ac); + VOS_ASSERT(0); + } + } + else + { + //Since ACM bit is not set, there should be only one QoS information for both directions. + fIsUapsdNeeded = (v_BOOL_t)(pACInfo->curr_QoSInfo[0].ts_info.psb); + if(fIsUapsdNeeded) + { + // we need UAPSD on this AC (and we may not currently have it) + uapsd_mask |= 1 << (SME_QOS_EDCA_AC_VO - ac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AC %d has ACM disabled, uapsd mask now 0x%X", + __func__, __LINE__, + sessionId, ac, uapsd_mask); + } + } + } + } + // do we need to reassociate? + if(uapsd_mask) + { + tCsrRoamModifyProfileFields modifyProfileFields; + //we need to do a reassoc on these AC + csrGetModifyProfileFields(pMac, sessionId, &modifyProfileFields); + if( btcIsReadyForUapsd(pMac) ) + { + modifyProfileFields.uapsd_mask = uapsd_mask; + } + else + { + modifyProfileFields.uapsd_mask = 0; + } + //Do we need to inform HDD? + if(!HAL_STATUS_SUCCESS(sme_QosRequestReassoc(pMac, sessionId, &modifyProfileFields, VOS_TRUE))) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On Session %d Reassoc failed", + __func__, __LINE__, + sessionId); + } + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On Session %d failed to parse IEs", + __func__, __LINE__, + sessionId); + } + } + // return status is ignored by BTC + return SME_QOS_STATUS_SETUP_SUCCESS_IND; +} + +/* + sme_QosReRequestAddTS to re-send AddTS for the combined QoS request +*/ +static sme_QosStatusType sme_QosReRequestAddTS(tpAniSirGlobal pMac, + v_U8_t sessionId, + sme_QosWmmTspecInfo * pQoSInfo, + sme_QosEdcaAcType ac, + v_U8_t tspecMask) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + sme_QosCmdInfo cmd; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d for AC %d TSPEC %d", + __func__, __LINE__, + sessionId, ac, tspecMask); + pSession = &sme_QosCb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + /* Need to vote off power save for the duration of this request */ + pSession->readyForPowerSave = VOS_FALSE; + /* + * Check to consider the following flowing scenario Addts request is pending + * on one AC, while APSD requested on another which needs a reassoc. + * Will buffer a request if Addts is pending on any AC, which will safeguard + * the above scenario, & also won't confuse PE with back to back Addts or + * Addts followed by Reassoc. + */ + if(!pMac->psOffloadEnabled) + { + if(sme_QosIsRspPending(sessionId, ac) || + ( eHAL_STATUS_PMC_PENDING == pmcRequestFullPower(pMac, + sme_QosPmcFullPowerCallback, pSession, eSME_REASON_OTHER))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d buffering the AddTS request " + "for AC %d in state %d as Addts is pending " + "on other AC or waiting for full power", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + //buffer cmd + cmd.command = SME_QOS_RESEND_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.resendCmdInfo.ac = ac; + cmd.u.resendCmdInfo.tspecMask = tspecMask; + cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo; + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unable to buffer the AddTS " + "request for AC %d TSPEC %d in state %d", + __func__, __LINE__, + sessionId, ac, tspecMask, pACInfo->curr_state); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + } + } + else + { + if(sme_QosIsRspPending(sessionId, ac) || + (eHAL_STATUS_PMC_PENDING == pmcOffloadRequestFullPower(pMac, sessionId, + sme_QosPmcOffloadFullPowerCallback, pSession, eSME_REASON_OTHER))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d buffering the AddTS request " + "for AC %d in state %d as Addts is pending " + "on other AC or waiting for full power", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + //buffer cmd + cmd.command = SME_QOS_RESEND_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.resendCmdInfo.ac = ac; + cmd.u.resendCmdInfo.tspecMask = tspecMask; + cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo; + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unable to buffer the AddTS " + "request for AC %d TSPEC %d in state %d", + __func__, __LINE__, + sessionId, ac, tspecMask, pACInfo->curr_state); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + return SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + } + } + + //get into the stat m/c to see if the request can be granted + switch(pACInfo->curr_state) + { + case SME_QOS_QOS_ON: + { + //if ACM, send out a new ADDTS + pACInfo->hoRenewal = VOS_TRUE; + status = sme_QosSetup(pMac, sessionId, pQoSInfo, ac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: sme_QosSetup returned in SME_QOS_QOS_ON state on " + "AC %d with status =%d", + __func__, __LINE__, + ac, status); + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) + { + /* We aren't waiting for a response from the AP + so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + } + if(SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) + { + status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + pACInfo->tspec_pending = tspecMask; + } + else if((SME_QOS_STATUS_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) || + (SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_PENDING == status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: UAPSD is setup already status = %d " + "returned by sme_QosSetup", + __func__, __LINE__, + status); + } + else + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: unexpected status = %d returned by sme_QosSetup", + __func__, __LINE__, + status); + } + } + break; + case SME_QOS_HANDOFF: + case SME_QOS_REQUESTED: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: Re-Add request in state = %d buffer the request", + __func__, __LINE__, + pACInfo->curr_state); + cmd.command = SME_QOS_RESEND_REQ; + cmd.pMac = pMac; + cmd.sessionId = sessionId; + cmd.u.resendCmdInfo.ac = ac; + cmd.u.resendCmdInfo.tspecMask = tspecMask; + cmd.u.resendCmdInfo.QoSInfo = *pQoSInfo; + if(!HAL_STATUS_SUCCESS(sme_QosBufferCmd(&cmd, VOS_FALSE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the read request in state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + case SME_QOS_LINK_UP: + default: + //print error msg, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: %d: ReAdd request in unexpected state = %d", + __func__, __LINE__, + pACInfo->curr_state ); + /* Unable to service the request + nothing is pending so vote power save back on */ + pSession->readyForPowerSave = VOS_TRUE; + // ASSERT? + break; + } + if((SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_NO_ACM_NO_APSD_RSP == status) || + (SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_APSD_SET_ALREADY == status)) + { + (void)sme_QosProcessBufferedCmd(sessionId); + } + return (status); +} + +static void sme_QosInitACs(tpAniSirGlobal pMac, v_U8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosEdcaAcType ac; + pSession = &sme_QosCb.sessionInfo[sessionId]; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + vos_mem_zero(&pSession->ac_info[ac], sizeof(sme_QosACInfo)); + sme_QosStateTransition(sessionId, ac, SME_QOS_INIT); + } +} +static eHalStatus sme_QosRequestReassoc(tpAniSirGlobal pMac, tANI_U8 sessionId, + tCsrRoamModifyProfileFields *pModFields, + v_BOOL_t fForce ) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + eHalStatus status; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d with UAPSD mask 0x%X", + __func__, __LINE__, + sessionId, pModFields->uapsd_mask); + pSession = &sme_QosCb.sessionInfo[sessionId]; + status = csrReassoc(pMac, sessionId, pModFields, &pSession->roamID, fForce); + if(HAL_STATUS_SUCCESS(status)) + { + //Update the state to Handoff so subsequent requests are queued until + // this one is finished + sme_QosEdcaAcType ac; + for(ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) + { + pACInfo = &pSession->ac_info[ac]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: %d: AC[%d] is in state [%d]", + __func__, __LINE__, + ac, pACInfo->curr_state ); + // If it is already in HANDOFF state, don't do anything since we + // MUST preserve the previous state and sme_QosStateTransition + // will change the previous state + if(SME_QOS_HANDOFF != pACInfo->curr_state) + { + sme_QosStateTransition(sessionId, ac, SME_QOS_HANDOFF); + } + } + } + return status; +} +static v_U32_t sme_QosAssignFlowId(void) +{ + v_U32_t flowId; + flowId = sme_QosCb.nextFlowId; + if (SME_QOS_MAX_FLOW_ID == flowId) + { + // The Flow ID wrapped. This is obviously not a real life scenario + // but handle it to keep the software test folks happy + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: Software Test made the flow counter wrap, " + "QoS may no longer be functional", + __func__, __LINE__); + sme_QosCb.nextFlowId = SME_QOS_MIN_FLOW_ID; + } + else + { + sme_QosCb.nextFlowId++; + } + return flowId; +} + +static v_U8_t sme_QosAssignDialogToken(void) +{ + v_U8_t token; + token = sme_QosCb.nextDialogToken; + if (SME_QOS_MAX_DIALOG_TOKEN == token) + { + // wrap is ok + sme_QosCb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN; + } + else + { + sme_QosCb.nextDialogToken++; + } + return token; +} +#endif /* WLAN_MDM_CODE_REDUCTION_OPT */ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/btc/btcApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/btc/btcApi.c new file mode 100644 index 000000000000..1d28c6c8b93d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/btc/btcApi.c @@ -0,0 +1,2070 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: btcApi.c +* +* Description: Routines that make up the BTC API. +* + +* +******************************************************************************/ +#include "wlan_qct_wda.h" +#ifndef WLAN_MDM_CODE_REDUCTION_OPT +#include "aniGlobal.h" +#include "smsDebug.h" +#include "btcApi.h" +#include "cfgApi.h" +#include "pmc.h" +#include "smeQosInternal.h" +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "vos_diag_core_event.h" +#include "vos_diag_core_log.h" +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ +static void btcLogEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent); +static void btcRestoreHeartBeatMonitoringHandle(void* hHal); +static void btcUapsdCheck( tpAniSirGlobal pMac, tpSmeBtEvent pBtEvent ); +VOS_STATUS btcCheckHeartBeatMonitoring(tHalHandle hHal, tpSmeBtEvent pBtEvent); +static void btcPowerStateCB( v_PVOID_t pContext, tPmcState pmcState ); +static void btcPowerOffloadStateCB(v_PVOID_t pContext, tANI_U32 sessionId, + tPmcState pmcState ); +static VOS_STATUS btcDeferEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ); +static VOS_STATUS btcDeferDisconnEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ); +#ifdef FEATURE_WLAN_DIAG_SUPPORT +static void btcDiagEventLog (tHalHandle hHal, tpSmeBtEvent pBtEvent); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ +/* --------------------------------------------------------------------------- + \fn btcOpen + \brief API to init the BTC Events Layer + \param hHal - The handle returned by macOpen. + \return VOS_STATUS + VOS_STATUS_E_FAILURE success + VOS_STATUS_SUCCESS failure + ---------------------------------------------------------------------------*/ +VOS_STATUS btcOpen (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus; + int i; + + /* Initialize BTC configuration. */ + pMac->btc.btcConfig.btcExecutionMode = BTC_SMART_COEXISTENCE; + + pMac->btc.btcReady = VOS_FALSE; + pMac->btc.btcEventState = 0; + pMac->btc.btcHBActive = VOS_TRUE; + pMac->btc.btcScanCompromise = VOS_FALSE; + + for (i = 0; i < MWS_COEX_MAX_CONFIG; i++) + { + pMac->btc.btcConfig.mwsCoexConfig[i] = 0; + } + + vosStatus = vos_timer_init( &pMac->btc.restoreHBTimer, + VOS_TIMER_TYPE_SW, + btcRestoreHeartBeatMonitoringHandle, + (void*) hHal); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcOpen: Fail to init timer"); + return VOS_STATUS_E_FAILURE; + } + + if(!pMac->psOffloadEnabled) + { + if(!HAL_STATUS_SUCCESS(pmcRegisterDeviceStateUpdateInd(pMac, + btcPowerStateCB, pMac))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "btcOpen: Fail to register PMC callback"); + return VOS_STATUS_E_FAILURE; + } + } + else + { + tANI_U32 i; + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + if(!HAL_STATUS_SUCCESS(pmcOffloadRegisterDeviceStateUpdateInd(pMac, + i, btcPowerOffloadStateCB, pMac))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "btcOpen: Fail to register PMC callback"); + return VOS_STATUS_E_FAILURE; + } + } + } + return VOS_STATUS_SUCCESS; +} +/* --------------------------------------------------------------------------- + \fn btcClose + \brief API to exit the BTC Events Layer + \param hHal - The handle returned by macOpen. + \return VOS_STATUS + VOS_STATUS_E_FAILURE success + VOS_STATUS_SUCCESS failure + ---------------------------------------------------------------------------*/ +VOS_STATUS btcClose (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus; + pMac->btc.btcReady = VOS_FALSE; + pMac->btc.btcUapsdOk = VOS_FALSE; + vos_timer_stop(&pMac->btc.restoreHBTimer); + vosStatus = vos_timer_destroy(&pMac->btc.restoreHBTimer); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcClose: Fail to destroy timer"); + return VOS_STATUS_E_FAILURE; + } + + if(!pMac->psOffloadEnabled) + { + if(!HAL_STATUS_SUCCESS( + pmcDeregisterDeviceStateUpdateInd(pMac, btcPowerStateCB))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: %d: cannot deregister pmcDeregisterDeviceStateUpdateInd()", + __func__, __LINE__); + } + } + else + { + tANI_U32 i; + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + if(!HAL_STATUS_SUCCESS(pmcOffloadDeregisterDeviceStateUpdateInd(pMac, + i, btcPowerOffloadStateCB))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "btcOpen: Fail to deregister PMC callback"); + return VOS_STATUS_E_FAILURE; + } + } + } + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn btcReady + \brief fn to inform BTC that eWNI_SME_SYS_READY_IND has been sent to PE. + This acts as a trigger to send a message to HAL to update the BTC + related config to FW. Note that if HDD configures any power BTC + related stuff before this API is invoked, BTC will buffer all the + configuration. + \param hHal - The handle returned by macOpen. + \return VOS_STATUS + ---------------------------------------------------------------------------*/ +VOS_STATUS btcReady (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_U32_t cfgVal = 0; + v_U8_t i; + pMac->btc.btcReady = VOS_TRUE; + pMac->btc.btcUapsdOk = VOS_TRUE; + for(i=0; i < BT_MAX_SCO_SUPPORT; i++) + { + pMac->btc.btcScoHandles[i] = BT_INVALID_CONN_HANDLE; + } + + // Read heartbeat threshold CFG and save it. + ccmCfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &cfgVal); + pMac->btc.btcHBCount = (v_U8_t)cfgVal; + if (btcSendCfgMsg(hHal, &(pMac->btc.btcConfig)) != VOS_STATUS_SUCCESS) + { + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +static VOS_STATUS btcSendBTEvent(tpAniSirGlobal pMac, tpSmeBtEvent pBtEvent) +{ + vos_msg_t msg; + tpSmeBtEvent ptrSmeBtEvent = NULL; + switch(pBtEvent->btEventType) + { + case BT_EVENT_CREATE_SYNC_CONNECTION: + case BT_EVENT_SYNC_CONNECTION_UPDATED: + if(pBtEvent->uEventParam.btSyncConnection.linkType != BT_SCO && + pBtEvent->uEventParam.btSyncConnection.linkType != BT_eSCO) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Invalid link type %d for Sync Connection. BT event will be dropped ", + __func__, pBtEvent->uEventParam.btSyncConnection.linkType); + return VOS_STATUS_E_FAILURE; + } + break; + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + if((pBtEvent->uEventParam.btSyncConnection.status == BT_CONN_STATUS_SUCCESS) && + ((pBtEvent->uEventParam.btSyncConnection.linkType != BT_SCO && pBtEvent->uEventParam.btSyncConnection.linkType != BT_eSCO) || + (pBtEvent->uEventParam.btSyncConnection.connectionHandle == BT_INVALID_CONN_HANDLE))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Invalid connection handle %d or link type %d for Sync Connection. BT event will be dropped ", + __func__, + pBtEvent->uEventParam.btSyncConnection.connectionHandle, + pBtEvent->uEventParam.btSyncConnection.linkType); + return VOS_STATUS_E_FAILURE; + } + break; + case BT_EVENT_MODE_CHANGED: + if(pBtEvent->uEventParam.btAclModeChange.mode >= BT_ACL_MODE_MAX) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Invalid mode %d for ACL Connection. BT event will be dropped ", + __func__, + pBtEvent->uEventParam.btAclModeChange.mode); + return VOS_STATUS_E_FAILURE; + } + break; + case BT_EVENT_DEVICE_SWITCHED_OFF: + pMac->btc.btcEventState = 0; + break; + default: + break; + } + ptrSmeBtEvent = vos_mem_malloc(sizeof(tSmeBtEvent)); + if (NULL == ptrSmeBtEvent) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Not able to allocate memory for BT event", __func__); + return VOS_STATUS_E_FAILURE; + } + btcLogEvent(pMac, pBtEvent); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + btcDiagEventLog(pMac, pBtEvent); +#endif + vos_mem_copy(ptrSmeBtEvent, pBtEvent, sizeof(tSmeBtEvent)); + msg.type = WDA_SIGNAL_BT_EVENT; + msg.reserved = 0; + msg.bodyptr = ptrSmeBtEvent; + 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_SIGNAL_BT_EVENT message to WDA", __func__); + vos_mem_free( ptrSmeBtEvent ); + return VOS_STATUS_E_FAILURE; + } + // After successfully posting the message, check if heart beat + // monitoring needs to be turned off + (void)btcCheckHeartBeatMonitoring(pMac, pBtEvent); + //Check whether BTC and UAPSD can co-exist + btcUapsdCheck( pMac, pBtEvent ); + return VOS_STATUS_SUCCESS; + } + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT +/* --------------------------------------------------------------------------- + \fn btcSignalBTEvent + \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the + BT event type and the current operating mode of Libra (full power, + BMPS, UAPSD etc), appropriate Bluetooth Coexistence (BTC) strategy + would be employed. + \param hHal - The handle returned by macOpen. + \param pBtEvent - Pointer to a caller allocated object of type tSmeBtEvent. + Caller owns the memory and is responsible for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE � BT Event not passed to HAL. This can happen + if driver has not yet been initialized or if BTC + Events Layer has been disabled. + VOS_STATUS_SUCCESS � BT Event passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS btcSignalBTEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + VOS_STATUS vosStatus; + if( NULL == pBtEvent ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Null pointer for SME BT Event", __func__); + return VOS_STATUS_E_FAILURE; + } + if(( BTC_WLAN_ONLY == pMac->btc.btcConfig.btcExecutionMode ) || + ( BTC_PTA_ONLY == pMac->btc.btcConfig.btcExecutionMode )) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "BTC execution mode not set to BTC_SMART_COEXISTENCE. BT event will be dropped", __func__); + return VOS_STATUS_E_FAILURE; + } + if( pBtEvent->btEventType < 0 || pBtEvent->btEventType >= BT_EVENT_TYPE_MAX ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Invalid BT event %d being passed. BT event will be dropped", + __func__, pBtEvent->btEventType); + return VOS_STATUS_E_FAILURE; + } + //Check PMC state to make sure whether we need to defer + //If we already have deferred events, defer the new one as well, in case PMC is in transition state + if( pMac->btc.fReplayBTEvents || !PMC_IS_CHIP_ACCESSIBLE(pmcGetPmcState( pMac )) ) + { + //We need to defer the event + vosStatus = btcDeferEvent(pMac, pBtEvent); + if( VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + pMac->btc.fReplayBTEvents = VOS_TRUE; + return VOS_STATUS_SUCCESS; + } + else + { + return vosStatus; + } + } + btcSendBTEvent(pMac, pBtEvent); + return VOS_STATUS_SUCCESS; +} +#endif +/* --------------------------------------------------------------------------- + \fn btcCheckHeartBeatMonitoring + \brief API to check whether heartbeat monitoring is required to be disabled + for specific BT start events which takes significant time to complete + during which WLAN misses beacons. To avoid WLAN-MAC from disconnecting + for the not enough beacons received we stop the heartbeat timer during + this start BT event till the stop of that BT event. + \param hHal - The handle returned by macOpen. + \param pBtEvent - Pointer to a caller allocated object of type tSmeBtEvent. + Caller owns the memory and is responsible for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE Config not passed to HAL. + VOS_STATUS_SUCCESS Config passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS btcCheckHeartBeatMonitoring(tHalHandle hHal, tpSmeBtEvent pBtEvent) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + VOS_STATUS vosStatus; + switch(pBtEvent->btEventType) + { + // Start events which requires heartbeat monitoring be disabled. + case BT_EVENT_INQUIRY_STARTED: + pMac->btc.btcEventState |= BT_INQUIRY_STARTED; + break; + case BT_EVENT_PAGE_STARTED: + pMac->btc.btcEventState |= BT_PAGE_STARTED; + break; + case BT_EVENT_CREATE_ACL_CONNECTION: + pMac->btc.btcEventState |= BT_CREATE_ACL_CONNECTION_STARTED; + break; + case BT_EVENT_CREATE_SYNC_CONNECTION: + pMac->btc.btcEventState |= BT_CREATE_SYNC_CONNECTION_STARTED; + break; + // Stop/done events which indicates heartbeat monitoring can be enabled + case BT_EVENT_INQUIRY_STOPPED: + pMac->btc.btcEventState &= ~(BT_INQUIRY_STARTED); + break; + case BT_EVENT_PAGE_STOPPED: + pMac->btc.btcEventState &= ~(BT_PAGE_STARTED); + break; + case BT_EVENT_ACL_CONNECTION_COMPLETE: + pMac->btc.btcEventState &= ~(BT_CREATE_ACL_CONNECTION_STARTED); + break; + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + pMac->btc.btcEventState &= ~(BT_CREATE_SYNC_CONNECTION_STARTED); + break; + default: + // Ignore other events + return VOS_STATUS_SUCCESS; + } + // Check if any of the BT start events are active + if (pMac->btc.btcEventState) { + if (pMac->btc.btcHBActive) { + // set heartbeat threshold CFG to zero + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0, NULL, eANI_BOOLEAN_FALSE); + pMac->btc.btcHBActive = VOS_FALSE; + } + // Deactivate and active the restore HB timer + vos_timer_stop( &pMac->btc.restoreHBTimer); + vosStatus= vos_timer_start( &pMac->btc.restoreHBTimer, BT_MAX_EVENT_DONE_TIMEOUT ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcCheckHeartBeatMonitoring: Fail to start timer"); + return VOS_STATUS_E_FAILURE; + } + } else { + // Restore CFG back to the original value only if it was disabled + if (!pMac->btc.btcHBActive) { + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE); + pMac->btc.btcHBActive = VOS_TRUE; + } + // Deactivate the timer + vosStatus = vos_timer_stop( &pMac->btc.restoreHBTimer); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcCheckHeartBeatMonitoring: Fail to stop timer"); + return VOS_STATUS_E_FAILURE; + } + } + return VOS_STATUS_SUCCESS; +} +/* --------------------------------------------------------------------------- + \fn btcRestoreHeartBeatMonitoringHandle + \brief Timer handler to handle the timeout condition when a specific BT + stop event does not come back, in which case to restore back the + heartbeat timer. + \param hHal - The handle returned by macOpen. + \return VOID + ---------------------------------------------------------------------------*/ +void btcRestoreHeartBeatMonitoringHandle(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + if( !pMac->btc.btcHBActive ) + { + tPmcState pmcState; + //Check PMC state to make sure whether we need to defer + pmcState = pmcGetPmcState( pMac ); + if( PMC_IS_CHIP_ACCESSIBLE(pmcState) ) + { + // Restore CFG back to the original value + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "BT event timeout, restoring back HeartBeat timer"); + } + else + { + //defer it + pMac->btc.btcEventReplay.fRestoreHBMonitor = VOS_TRUE; + } + } +} + + +/* --------------------------------------------------------------------------- + \fn btcSetConfig + \brief API to change the current Bluetooth Coexistence (BTC) configuration + This function should be invoked only after CFG download has completed. + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtcConfig. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE Config not passed to HAL. + VOS_STATUS_SUCCESS Config passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS btcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + //Save a copy in the global BTC config + vos_mem_copy(&(pMac->btc.btcConfig), pSmeBtcConfig, sizeof(tSmeBtcConfig)); + //Send the config down only if SME_HddReady has been invoked. If not ready, + //BTC config will plumbed down when btcReady is eventually invoked. + if(pMac->btc.btcReady) + { + if(VOS_STATUS_SUCCESS != btcSendCfgMsg(hHal, pSmeBtcConfig)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "Failure to send BTC config down"); + return VOS_STATUS_E_FAILURE; + } + } + return VOS_STATUS_SUCCESS; +} +/* --------------------------------------------------------------------------- + \fn btcPostBtcCfgMsg + \brief Private API to post BTC config message to HAL + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtcConfig. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE Config not passed to HAL. + VOS_STATUS_SUCCESS Config passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS btcSendCfgMsg(tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig) +{ + tpSmeBtcConfig ptrSmeBtcConfig = NULL; + vos_msg_t msg; + if( NULL == pSmeBtcConfig ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: " + "Null pointer for BTC Config"); + return VOS_STATUS_E_FAILURE; + } + if( pSmeBtcConfig->btcExecutionMode >= BT_EXEC_MODE_MAX ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: " + "Invalid BT execution mode %d being set", + pSmeBtcConfig->btcExecutionMode); + return VOS_STATUS_E_FAILURE; + } + ptrSmeBtcConfig = vos_mem_malloc(sizeof(tSmeBtcConfig)); + if (NULL == ptrSmeBtcConfig) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: " + "Not able to allocate memory for SME BTC Config"); + return VOS_STATUS_E_FAILURE; + } + vos_mem_copy(ptrSmeBtcConfig, pSmeBtcConfig, sizeof(tSmeBtcConfig)); + msg.type = WDA_BTC_SET_CFG; + msg.reserved = 0; + msg.bodyptr = ptrSmeBtcConfig; + if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcSendCfgMsg: " + "Not able to post WDA_BTC_SET_CFG message to WDA"); + vos_mem_free( ptrSmeBtcConfig ); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} +/* --------------------------------------------------------------------------- + \fn btcGetConfig + \brief API to retrieve the current Bluetooth Coexistence (BTC) configuration + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtcConfig. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS btcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + if( NULL == pSmeBtcConfig ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "btcGetConfig: " + "Null pointer for BTC Config"); + return VOS_STATUS_E_FAILURE; + } + vos_mem_copy(pSmeBtcConfig, &(pMac->btc.btcConfig), sizeof(tSmeBtcConfig)); + return VOS_STATUS_SUCCESS; +} +/* + btcFindAclEventHist find a suited ACL event buffer + Param: bdAddr - NULL meaning not care. + pointer to caller allocated buffer containing the BD + address to find a match + handle - BT_INVALID_CONN_HANDLE == not care + otherwise, a handle to match + NOPTE: Either bdAddr or handle can be valid, if both of them are valid, use bdAddr only. If neither + bdAddr nor handle is valid, return the next free slot. +*/ +static tpSmeBtAclEventHist btcFindAclEventHist( tpAniSirGlobal pMac, v_U8_t *bdAddr, v_U16_t handle ) +{ + int i, j; + tpSmeBtAclEventHist pRet = NULL; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + for( i = 0; (i < BT_MAX_ACL_SUPPORT) && (NULL == pRet); i++ ) + { + if( NULL != bdAddr ) + { + //try to match addr + if( pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx ) + { + for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++) + { + if( vos_mem_compare(pReplay->btcEventHist.btAclConnectionEvent[i].btAclConnection[j].bdAddr, + bdAddr, 6) ) + { + //found it + pRet = &pReplay->btcEventHist.btAclConnectionEvent[i]; + break; + } + } + } + } + else if( BT_INVALID_CONN_HANDLE != handle ) + { + //try to match handle + if( pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx ) + { + for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++) + { + if( pReplay->btcEventHist.btAclConnectionEvent[i].btAclConnection[j].connectionHandle == + handle ) + { + //found it + pRet = &pReplay->btcEventHist.btAclConnectionEvent[i]; + break; + } + } + } + } + else if( 0 == pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx ) + { + pRet = &pReplay->btcEventHist.btAclConnectionEvent[i]; + break; + } + } + return (pRet); +} + +/* + btcFindSyncEventHist find a suited SYNC event buffer + Param: bdAddr - NULL meaning not care. + pointer to caller allocated buffer containing the + BD address to find a match + handle - BT_INVALID_CONN_HANDLE == not care + otherwise, a handle to match + NOPTE: Either bdAddr or handle can be valid, if both of them are valid, use bdAddr only. If neither + bdAddr nor handle is valid, return the next free slot. +*/ +static tpSmeBtSyncEventHist btcFindSyncEventHist( tpAniSirGlobal pMac, v_U8_t *bdAddr, v_U16_t handle ) +{ + int i, j; + tpSmeBtSyncEventHist pRet = NULL; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + for( i = 0; (i < BT_MAX_SCO_SUPPORT) && (NULL == pRet); i++ ) + { + if( NULL != bdAddr ) + { + //try to match addr + if( pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx ) + { + for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++) + { + if( vos_mem_compare(pReplay->btcEventHist.btSyncConnectionEvent[i].btSyncConnection[j].bdAddr, + bdAddr, 6) ) + { + //found it + pRet = &pReplay->btcEventHist.btSyncConnectionEvent[i]; + break; + } + } + } + } + else if( BT_INVALID_CONN_HANDLE != handle ) + { + //try to match handle + if( pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx ) + { + for(j = 0; j < pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx; j++) + { + if( pReplay->btcEventHist.btSyncConnectionEvent[i].btSyncConnection[j].connectionHandle == + handle ) + { + //found it + pRet = &pReplay->btcEventHist.btSyncConnectionEvent[i]; + break; + } + } + } + } + else if( !pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx ) + { + pRet = &pReplay->btcEventHist.btSyncConnectionEvent[i]; + break; + } + } + return (pRet); +} + +/* + btcFindDisconnEventHist find a slot for the deferred disconnect event + If handle is invalid, it returns a free slot, if any. + If handle is valid, it tries to find a match first in case same disconnect event comes down again. +*/ +static tpSmeBtDisconnectEventHist btcFindDisconnEventHist( tpAniSirGlobal pMac, v_U16_t handle ) +{ + tpSmeBtDisconnectEventHist pRet = NULL; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + int i; + if( BT_INVALID_CONN_HANDLE != handle ) + { + for(i = 0; i < BT_MAX_DISCONN_SUPPORT; i++) + { + if( pReplay->btcEventHist.btDisconnectEvent[i].fValid && + (handle == pReplay->btcEventHist.btDisconnectEvent[i].btDisconnect.connectionHandle) ) + { + pRet = &pReplay->btcEventHist.btDisconnectEvent[i]; + break; + } + } + } + if( NULL == pRet ) + { + //Find a free slot + for(i = 0; i < BT_MAX_DISCONN_SUPPORT; i++) + { + if( !pReplay->btcEventHist.btDisconnectEvent[i].fValid ) + { + pRet = &pReplay->btcEventHist.btDisconnectEvent[i]; + break; + } + } + } + return (pRet); +} + +/* + btcFindModeChangeEventHist find a slot for the deferred mode change event + If handle is invalid, it returns a free slot, if any. + If handle is valid, it tries to find a match first in case same disconnect event comes down again. +*/ +tpSmeBtAclModeChangeEventHist btcFindModeChangeEventHist( tpAniSirGlobal pMac, v_U16_t handle ) +{ + tpSmeBtAclModeChangeEventHist pRet = NULL; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + int i; + if( BT_INVALID_CONN_HANDLE != handle ) + { + for(i = 0; i < BT_MAX_ACL_SUPPORT; i++) + { + if( pReplay->btcEventHist.btAclModeChangeEvent[i].fValid && + (handle == pReplay->btcEventHist.btAclModeChangeEvent[i].btAclModeChange.connectionHandle) ) + { + pRet = &pReplay->btcEventHist.btAclModeChangeEvent[i]; + break; + } + } + } + if( NULL == pRet ) + { + //Find a free slot + for(i = 0; i < BT_MAX_ACL_SUPPORT; i++) + { + if( !pReplay->btcEventHist.btAclModeChangeEvent[i].fValid ) + { + pRet = &pReplay->btcEventHist.btAclModeChangeEvent[i]; + break; + } + } + } + return (pRet); +} + +/* + btcFindSyncUpdateEventHist find a slot for the deferred SYNC_UPDATE event + If handle is invalid, it returns a free slot, if any. + If handle is valid, it tries to find a match first in case same disconnect event comes down again. +*/ +tpSmeBtSyncUpdateHist btcFindSyncUpdateEventHist( tpAniSirGlobal pMac, v_U16_t handle ) +{ + tpSmeBtSyncUpdateHist pRet = NULL; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + int i; + if( BT_INVALID_CONN_HANDLE != handle ) + { + for(i = 0; i < BT_MAX_SCO_SUPPORT; i++) + { + if( pReplay->btcEventHist.btSyncUpdateEvent[i].fValid && + (handle == pReplay->btcEventHist.btSyncUpdateEvent[i].btSyncConnection.connectionHandle) ) + { + pRet = &pReplay->btcEventHist.btSyncUpdateEvent[i]; + break; + } + } + } + if( NULL == pRet ) + { + //Find a free slot + for(i = 0; i < BT_MAX_SCO_SUPPORT; i++) + { + if( !pReplay->btcEventHist.btSyncUpdateEvent[i].fValid ) + { + pRet = &pReplay->btcEventHist.btSyncUpdateEvent[i]; + break; + } + } + } + return (pRet); +} + +/* + Call must validate pAclEventHist +*/ +static void btcReleaseAclEventHist( tpAniSirGlobal pMac, tpSmeBtAclEventHist pAclEventHist ) +{ + vos_mem_zero( pAclEventHist, sizeof(tSmeBtAclEventHist) ); +} + +/* + Call must validate pSyncEventHist +*/ +static void btcReleaseSyncEventHist( tpAniSirGlobal pMac, tpSmeBtSyncEventHist pSyncEventHist ) +{ + vos_mem_zero( pSyncEventHist, sizeof(tSmeBtSyncEventHist) ); +} + +/*To defer a ACL creation event + We only support one ACL per BD address. + If the last cached event another ACL create event, replace that event with the new event + If a completion event with success status code, and the new ACL creation + on same address, defer a new disconnect event(fake one), then cache this ACL creation event. + Otherwise, save this create event. +*/ +static VOS_STATUS btcDeferAclCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtAclEventHist pAclEventHist; + tSmeBtAclConnectionParam *pAclEvent = NULL; + do + { + //Find a match + pAclEventHist = btcFindAclEventHist( pMac, pEvent->uEventParam.btAclConnection.bdAddr, + BT_INVALID_CONN_HANDLE ); + if( NULL == pAclEventHist ) + { + //No cached ACL event on this address + //Find a free slot and save it + pAclEventHist = btcFindAclEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE ); + if( NULL != pAclEventHist ) + { + vos_mem_copy(&pAclEventHist->btAclConnection[0], &pEvent->uEventParam.btAclConnection, + sizeof(tSmeBtAclConnectionParam)); + pAclEventHist->btEventType[0] = BT_EVENT_CREATE_ACL_CONNECTION; + pAclEventHist->bNextEventIdx = 1; + } + else + { + smsLog(pMac, LOGE, FL(" failed to find ACL event slot")); + status = VOS_STATUS_E_RESOURCES; + } + //done + break; + } + else + { + //There is history on this BD address + if ((pAclEventHist->bNextEventIdx <= 0) || + (pAclEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_ACL_DEFERRED)) + { + VOS_ASSERT(0); + status = VOS_STATUS_E_FAILURE; + break; + } + pAclEvent = &pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx - 1]; + if(BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[pAclEventHist->bNextEventIdx - 1]) + { + //The last cached event is creation, replace it with the new one + if (pAclEvent) + { + vos_mem_copy(pAclEvent, + &pEvent->uEventParam.btAclConnection, + sizeof(tSmeBtAclConnectionParam)); + } + //done + break; + } + else if(BT_EVENT_ACL_CONNECTION_COMPLETE == + pAclEventHist->btEventType[pAclEventHist->bNextEventIdx - 1]) + { + //The last cached event is completion, check the status. + if(BT_CONN_STATUS_SUCCESS == pAclEvent->status) + { + tSmeBtEvent btEvent; + //The last event we have is success completion event. + //Should not get a creation event before creation. + smsLog(pMac, LOGE, FL(" Missing disconnect event on handle %d"), pAclEvent->connectionHandle); + //Fake a disconnect event + btEvent.btEventType = BT_EVENT_DISCONNECTION_COMPLETE; + btEvent.uEventParam.btDisconnect.connectionHandle = pAclEvent->connectionHandle; + btcDeferDisconnEvent(pMac, &btEvent); + } + } + //Need to save the new event + if(pAclEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED) + { + pAclEventHist->btEventType[pAclEventHist->bNextEventIdx] = BT_EVENT_CREATE_ACL_CONNECTION; + vos_mem_copy(&pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx], + &pEvent->uEventParam.btAclConnection, + sizeof(tSmeBtAclConnectionParam)); + pAclEventHist->bNextEventIdx++; + } + else + { + smsLog(pMac, LOGE, FL(" ACL event overflow")); + VOS_ASSERT(0); + } + } + }while(0); + return status; +} + +/*Defer a ACL completion event + If there is cached event on this BD address, check completion status. + If status is fail and last cached event is creation, remove the creation event and drop + this completion event. Otherwise, cache this completion event as the latest one. +*/ +static VOS_STATUS btcDeferAclComplete( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtAclEventHist pAclEventHist; + do + { + //Find a match + pAclEventHist = btcFindAclEventHist( pMac, pEvent->uEventParam.btAclConnection.bdAddr, + BT_INVALID_CONN_HANDLE ); + if(pAclEventHist) + { + if (pAclEventHist->bNextEventIdx <= 0) + { + VOS_ASSERT(pAclEventHist->bNextEventIdx >0); + return VOS_STATUS_E_EMPTY; + } + //Found one + if(BT_CONN_STATUS_SUCCESS != pEvent->uEventParam.btAclConnection.status) + { + //If completion fails, and the last one is creation, remove the creation event + if(BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[pAclEventHist->bNextEventIdx-1]) + { + vos_mem_zero(&pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx-1], + sizeof(tSmeBtAclConnectionParam)); + pAclEventHist->bNextEventIdx--; + //Done with this event + break; + } + else + { + smsLog(pMac, LOGE, FL(" ACL completion fail but last event(%d) not creation"), + pAclEventHist->btEventType[pAclEventHist->bNextEventIdx-1]); + } + } + } + if( NULL == pAclEventHist ) + { + pAclEventHist = btcFindAclEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE ); + } + if(pAclEventHist) + { + if(pAclEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED) + { + //Save this event + pAclEventHist->btEventType[pAclEventHist->bNextEventIdx] = BT_EVENT_ACL_CONNECTION_COMPLETE; + vos_mem_copy(&pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx], + &pEvent->uEventParam.btAclConnection, + sizeof(tSmeBtAclConnectionParam)); + pAclEventHist->bNextEventIdx++; + } + else + { + smsLog(pMac, LOGE, FL(" ACL event overflow")); + VOS_ASSERT(0); + } + } + else + { + smsLog(pMac, LOGE, FL(" cannot find match for failed " + "BT_EVENT_ACL_CONNECTION_COMPLETE of bdAddr " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pEvent->uEventParam.btAclConnection.bdAddr)); + status = VOS_STATUS_E_EMPTY; + } + }while(0); + return (status); +} + +/*To defer a SYNC creation event + If the last cached event is another SYNC create event, replace + that event with the new event. + If there is a completion event with success status code, cache a new + disconnect event(fake) first, then cache this SYNC creation event. + Otherwise, cache this create event. +*/ +static VOS_STATUS btcDeferSyncCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtSyncEventHist pSyncEventHist; + tSmeBtSyncConnectionParam *pSyncEvent = NULL; + do + { + //Find a match + pSyncEventHist = btcFindSyncEventHist( pMac, pEvent->uEventParam.btSyncConnection.bdAddr, + BT_INVALID_CONN_HANDLE ); + if( NULL == pSyncEventHist ) + { + //No cached ACL event on this address + //Find a free slot and save it + pSyncEventHist = btcFindSyncEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE ); + if( NULL != pSyncEventHist ) + { + vos_mem_copy(&pSyncEventHist->btSyncConnection[0], &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + pSyncEventHist->btEventType[0] = BT_EVENT_CREATE_SYNC_CONNECTION; + pSyncEventHist->bNextEventIdx = 1; + } + else + { + smsLog(pMac, LOGE, FL(" failed to find SYNC event slot")); + status = VOS_STATUS_E_RESOURCES; + } + //done + break; + } + else + { + //There is history on this BD address + if ((pSyncEventHist->bNextEventIdx <= 0) || + (pSyncEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_SCO_DEFERRED)) + { + VOS_ASSERT(0); + status = VOS_STATUS_E_FAILURE; + return status; + } + pSyncEvent = &pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx - 1]; + if(BT_EVENT_CREATE_SYNC_CONNECTION == + pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx - 1]) + { + //The last cached event is creation, replace it with the new one + if(pSyncEvent) + { + vos_mem_copy(pSyncEvent, + &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + } + //done + break; + } + else if(BT_EVENT_SYNC_CONNECTION_COMPLETE == + pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx - 1]) + { + //The last cached event is completion, check the status. + if(BT_CONN_STATUS_SUCCESS == pSyncEvent->status) + { + tSmeBtEvent btEvent; + //The last event we have is success completion event. + //Should not get a creation event before creation. + smsLog(pMac, LOGE, FL(" Missing disconnect event on handle %d"), pSyncEvent->connectionHandle); + //Fake a disconnect event + btEvent.btEventType = BT_EVENT_DISCONNECTION_COMPLETE; + btEvent.uEventParam.btDisconnect.connectionHandle = pSyncEvent->connectionHandle; + btcDeferDisconnEvent(pMac, &btEvent); + } + } + //Need to save the new event + if(pSyncEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_SCO_DEFERRED) + { + pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx] = BT_EVENT_CREATE_SYNC_CONNECTION; + vos_mem_copy(&pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx], + &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + pSyncEventHist->bNextEventIdx++; + } + else + { + smsLog(pMac, LOGE, FL(" SYNC event overflow")); + } + } + }while(0); + return status; +} + +/* + * Defer a SYNC completion event + * If there is cached event on this BD address, check completion status. + * If status is fail and last cached event is creation, remove the + * creation event and drop this completion event. + * Otherwise, cache this completion event as the latest one. + */ +static VOS_STATUS btcDeferSyncComplete( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtSyncEventHist pSyncEventHist; + do + { + //Find a match + pSyncEventHist = btcFindSyncEventHist( pMac, pEvent->uEventParam.btSyncConnection.bdAddr, + BT_INVALID_CONN_HANDLE ); + if(pSyncEventHist) + { + if (pSyncEventHist->bNextEventIdx <= 0) + { + VOS_ASSERT(pSyncEventHist->bNextEventIdx >0); + return VOS_STATUS_E_EMPTY; + } + //Found one + if(BT_CONN_STATUS_SUCCESS != pEvent->uEventParam.btSyncConnection.status) + { + //If completion fails, and the last one is creation, remove the creation event + if(BT_EVENT_CREATE_SYNC_CONNECTION == pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx-1]) + { + vos_mem_zero(&pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx-1], + sizeof(tSmeBtSyncConnectionParam)); + pSyncEventHist->bNextEventIdx--; + //Done with this event + break; + } + else + { + smsLog(pMac, LOGE, FL(" SYNC completion fail but last event(%d) not creation"), + pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx-1]); + } + } + } + if(NULL == pSyncEventHist) + { + //In case we don't defer the creation event + pSyncEventHist = btcFindSyncEventHist( pMac, NULL, BT_INVALID_CONN_HANDLE ); + } + if(pSyncEventHist) + { + if(pSyncEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED) + { + //Save this event + pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx] = BT_EVENT_SYNC_CONNECTION_COMPLETE; + vos_mem_copy(&pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx], + &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + pSyncEventHist->bNextEventIdx++; + } + else + { + smsLog(pMac, LOGE, FL(" SYNC event overflow")); + } + } + else + { + smsLog(pMac, LOGE, FL(" cannot find match for " + "BT_EVENT_SYNC_CONNECTION_COMPLETE of bdAddr " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pEvent->uEventParam.btSyncConnection.bdAddr)); + status = VOS_STATUS_E_EMPTY; + } + }while(0); + return (status); +} + +//return VOS_STATUS_E_EXISTS if the event handle cannot be found +//VOS_STATUS_SUCCESS if the event is processed +//Other error status meaning it cannot continue due to other errors +/* + Defer a disconnect event for ACL + Check if any history on this event handle. + If both ACL_CREATION and ACL_COMPLETION is cached, remove both those events and drop + this disconnect event. + Otherwise save disconnect event in this ACL's bin. + If not ACL match on this handle, not to do anything. + Either way, remove any cached MODE_CHANGE event matches this disconnect event's handle. +*/ +static VOS_STATUS btcDeferDisconnectEventForACL( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtAclEventHist pAclEventHist; + tpSmeBtAclModeChangeEventHist pModeChangeEventHist; + v_BOOL_t fDone = VOS_FALSE; + int i; + pAclEventHist = btcFindAclEventHist( pMac, NULL, + pEvent->uEventParam.btDisconnect.connectionHandle ); + if(pAclEventHist) + { + if( pAclEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_ACL_DEFERRED) + { + smsLog(pMac, LOGE, FL(" ACL event history index:%d overflow, resetting to BT_MAX_NUM_EVENT_ACL_DEFERRED"), pAclEventHist->bNextEventIdx); + pAclEventHist->bNextEventIdx = BT_MAX_NUM_EVENT_ACL_DEFERRED; + } + /* Looking back-words */ + for(i = pAclEventHist->bNextEventIdx - 1; i >= 0; i--) + { + if( BT_EVENT_ACL_CONNECTION_COMPLETE == pAclEventHist->btEventType[i] ) + { + //make sure we can cancel the link + if( (i > 0) && (BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[i - 1]) ) + { + fDone = VOS_TRUE; + if(i == 1) + { + //All events can be wiped off + btcReleaseAclEventHist(pMac, pAclEventHist); + break; + } + //we have both ACL creation and completion, wipe out all of them + pAclEventHist->bNextEventIdx = (tANI_U8)(i - 1); + vos_mem_zero(&pAclEventHist->btAclConnection[i-1], sizeof(tSmeBtAclConnectionParam)); + vos_mem_zero(&pAclEventHist->btAclConnection[i], sizeof(tSmeBtAclConnectionParam)); + break; + } + } + }//for loop + if(!fDone) + { + //Save this disconnect event + if(pAclEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_ACL_DEFERRED) + { + pAclEventHist->btEventType[pAclEventHist->bNextEventIdx] = + BT_EVENT_DISCONNECTION_COMPLETE; + pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx].connectionHandle = + pEvent->uEventParam.btDisconnect.connectionHandle; + pAclEventHist->bNextEventIdx++; + } + else + { + smsLog(pMac, LOGE, FL(" ACL event overflow")); + status = VOS_STATUS_E_FAILURE; + } + } + } + else + { + status = VOS_STATUS_E_EXISTS; + } + //Wipe out the related mode change event if it is there + pModeChangeEventHist = btcFindModeChangeEventHist( pMac, + pEvent->uEventParam.btDisconnect.connectionHandle ); + if( pModeChangeEventHist && pModeChangeEventHist->fValid ) + { + pModeChangeEventHist->fValid = VOS_FALSE; + } + return status; +} + +/* + * This function works the same as btcDeferDisconnectEventForACL except it + * handles SYNC events return VOS_STATUS_E_EXISTS if the event handle cannot be + * found VOS_STATUS_SUCCESS if the event is processed. + * Other error status meaning it cannot continue due to other errors + */ +/* + Defer a disconnect event for SYNC + Check if any SYNC history on this event handle. + If yes and if both SYNC_CREATION and SYNC_COMPLETION is cached, remove both those events and drop + this disconnect event. + Otherwise save disconnect event in this SYNC's bin. + If no match found, not to save this event here. + Either way, remove any cached SYNC_UPDATE event matches this disconnect event's handle. +*/ +static VOS_STATUS btcDeferDisconnectEventForSync( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtSyncEventHist pSyncEventHist; + tpSmeBtSyncUpdateHist pSyncUpdateHist; + v_BOOL_t fDone = VOS_FALSE; + int i; + pSyncEventHist = btcFindSyncEventHist( pMac, NULL, + pEvent->uEventParam.btDisconnect.connectionHandle ); + if(pSyncEventHist) + { + if( pSyncEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_SCO_DEFERRED) + { + smsLog(pMac, LOGE, FL(" SYNC event history index:%d overflow, resetting to BT_MAX_NUM_EVENT_SCO_DEFERRED"), pSyncEventHist->bNextEventIdx); + pSyncEventHist->bNextEventIdx = BT_MAX_NUM_EVENT_SCO_DEFERRED; + } + /* Looking back-words */ + for(i = pSyncEventHist->bNextEventIdx - 1; i >= 0; i--) + { + //if a mode change event exists, drop it + if( BT_EVENT_SYNC_CONNECTION_COMPLETE == pSyncEventHist->btEventType[i] ) + { + //make sure we can cancel the link + if( (i > 0) && (BT_EVENT_CREATE_SYNC_CONNECTION == pSyncEventHist->btEventType[i - 1]) ) + { + fDone = VOS_TRUE; + if(i == 1) + { + //All events can be wiped off + btcReleaseSyncEventHist(pMac, pSyncEventHist); + break; + } + //we have both ACL creation and completion, wipe out all of them + pSyncEventHist->bNextEventIdx = (tANI_U8)(i - 1); + vos_mem_zero(&pSyncEventHist->btSyncConnection[i-1], sizeof(tSmeBtSyncConnectionParam)); + vos_mem_zero(&pSyncEventHist->btSyncConnection[i], sizeof(tSmeBtSyncConnectionParam)); + break; + } + } + }//for loop + if(!fDone) + { + //Save this disconnect event + if(pSyncEventHist->bNextEventIdx < BT_MAX_NUM_EVENT_SCO_DEFERRED) + { + pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx] = + BT_EVENT_DISCONNECTION_COMPLETE; + pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx].connectionHandle = + pEvent->uEventParam.btDisconnect.connectionHandle; + pSyncEventHist->bNextEventIdx++; + } + else + { + smsLog(pMac, LOGE, FL(" SYNC event overflow")); + status = VOS_STATUS_E_FAILURE; + } + } + } + else + { + status = VOS_STATUS_E_EXISTS; + } + //Wipe out the related mode change event if it is there + pSyncUpdateHist = btcFindSyncUpdateEventHist( pMac, + pEvent->uEventParam.btDisconnect.connectionHandle ); + if( pSyncUpdateHist && pSyncUpdateHist->fValid ) + { + pSyncUpdateHist->fValid = VOS_FALSE; + } + return status; +} + +/* + Defer a disconnect event. + Try to defer it as part of the ACL event first. + If no match is found, try SYNC. + If still no match found, defer it at DISCONNECT event bin. +*/ +static VOS_STATUS btcDeferDisconnEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtDisconnectEventHist pDisconnEventHist; + if( BT_INVALID_CONN_HANDLE == pEvent->uEventParam.btDisconnect.connectionHandle ) + { + smsLog( pMac, LOGE, FL(" invalid handle") ); + return (VOS_STATUS_E_INVAL); + } + //Check ACL first + status = btcDeferDisconnectEventForACL(pMac, pEvent); + if(!VOS_IS_STATUS_SUCCESS(status)) + { + status = btcDeferDisconnectEventForSync(pMac, pEvent); + } + if( !VOS_IS_STATUS_SUCCESS(status) ) + { + //Save the disconnect event + pDisconnEventHist = btcFindDisconnEventHist( pMac, + pEvent->uEventParam.btDisconnect.connectionHandle ); + if( pDisconnEventHist ) + { + pDisconnEventHist->fValid = VOS_TRUE; + vos_mem_copy( &pDisconnEventHist->btDisconnect, &pEvent->uEventParam.btDisconnect, + sizeof(tSmeBtDisconnectParam) ); + status = VOS_STATUS_SUCCESS; + } + else + { + smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_DISCONNECTION_COMPLETE of handle (%d)"), + pEvent->uEventParam.btDisconnect.connectionHandle); + status = VOS_STATUS_E_EMPTY; + } + } + return (status); +} + +/* + btcDeferEvent save the event for possible replay when chip can be accessed + This function is called only when in IMPS/Standby state +*/ +static VOS_STATUS btcDeferEvent( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpSmeBtSyncUpdateHist pSyncUpdateHist; + tpSmeBtAclModeChangeEventHist pModeChangeEventHist; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + switch(pEvent->btEventType) + { + case BT_EVENT_DEVICE_SWITCHED_ON: + //Clear all events first + vos_mem_zero( &pReplay->btcEventHist, sizeof(tSmeBtcEventHist) ); + pReplay->fBTSwitchOn = VOS_TRUE; + pReplay->fBTSwitchOff = VOS_FALSE; + break; + case BT_EVENT_DEVICE_SWITCHED_OFF: + //Clear all events first + vos_mem_zero( &pReplay->btcEventHist, sizeof(tSmeBtcEventHist) ); + pReplay->fBTSwitchOff = VOS_TRUE; + pReplay->fBTSwitchOn = VOS_FALSE; + break; + case BT_EVENT_INQUIRY_STARTED: + pReplay->btcEventHist.nInquiryEvent++; + break; + case BT_EVENT_INQUIRY_STOPPED: + pReplay->btcEventHist.nInquiryEvent--; + break; + case BT_EVENT_PAGE_STARTED: + pReplay->btcEventHist.nPageEvent++; + break; + case BT_EVENT_PAGE_STOPPED: + pReplay->btcEventHist.nPageEvent--; + break; + case BT_EVENT_CREATE_ACL_CONNECTION: + status = btcDeferAclCreate(pMac, pEvent); + break; + case BT_EVENT_ACL_CONNECTION_COMPLETE: + status = btcDeferAclComplete( pMac, pEvent ); + break; + case BT_EVENT_CREATE_SYNC_CONNECTION: + status = btcDeferSyncCreate(pMac, pEvent); + break; + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + status = btcDeferSyncComplete( pMac, pEvent ); + break; + case BT_EVENT_SYNC_CONNECTION_UPDATED: + if( BT_INVALID_CONN_HANDLE == pEvent->uEventParam.btDisconnect.connectionHandle ) + { + smsLog( pMac, LOGE, FL(" invalid handle") ); + status = VOS_STATUS_E_INVAL; + break; + } + //Find a match on handle. If not found, get a free slot. + pSyncUpdateHist = btcFindSyncUpdateEventHist( pMac, + pEvent->uEventParam.btSyncConnection.connectionHandle ); + if(pSyncUpdateHist) + { + pSyncUpdateHist->fValid = VOS_TRUE; + vos_mem_copy(&pSyncUpdateHist->btSyncConnection, &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + } + else + { + smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_SYNC_CONNECTION_UPDATED of handle (%d)"), + pEvent->uEventParam.btSyncConnection.connectionHandle ); + status = VOS_STATUS_E_EMPTY; + } + break; + case BT_EVENT_DISCONNECTION_COMPLETE: + status = btcDeferDisconnEvent( pMac, pEvent ); + break; + case BT_EVENT_MODE_CHANGED: + if( BT_INVALID_CONN_HANDLE == pEvent->uEventParam.btDisconnect.connectionHandle ) + { + smsLog( pMac, LOGE, FL(" invalid handle") ); + status = VOS_STATUS_E_INVAL; + break; + } + //Find a match on handle, If not found, return a free slot + pModeChangeEventHist = btcFindModeChangeEventHist( pMac, + pEvent->uEventParam.btAclModeChange.connectionHandle ); + if(pModeChangeEventHist) + { + pModeChangeEventHist->fValid = VOS_TRUE; + vos_mem_copy( &pModeChangeEventHist->btAclModeChange, + &pEvent->uEventParam.btAclModeChange, sizeof(tSmeBtAclModeChangeParam) ); + } + else + { + smsLog( pMac, LOGE, FL(" cannot find match for BT_EVENT_MODE_CHANGED of handle (%d)"), + pEvent->uEventParam.btAclModeChange.connectionHandle); + status = VOS_STATUS_E_EMPTY; + } + break; + case BT_EVENT_A2DP_STREAM_START: + pReplay->btcEventHist.fA2DPStarted = VOS_TRUE; + pReplay->btcEventHist.fA2DPStopped = VOS_FALSE; + break; + case BT_EVENT_A2DP_STREAM_STOP: + pReplay->btcEventHist.fA2DPStopped = VOS_TRUE; + pReplay->btcEventHist.fA2DPStarted = VOS_FALSE; + break; + default: + smsLog( pMac, LOGE, FL(" event (%d) is not deferred"), pEvent->btEventType ); + status = VOS_STATUS_E_NOSUPPORT; + break; + } + return (status); +} + +/* + Replay all cached events in the following order + 1. If BT_SWITCH_OFF event, send it. + 2. Send INQUIRY event (START or STOP),if available + 3. Send PAGE event (START or STOP), if available + 4. Send DISCONNECT events, these DISCONNECT events are not tied to + any ACL/SYNC event that we have cached + 5. Send ACL events (possible events, CREATION, COMPLETION, DISCONNECT) + 6. Send MODE_CHANGE events, if available + 7. Send A2DP event(START or STOP), if available + 8. Send SYNC events (possible events, CREATION, COMPLETION, DISCONNECT) + 9. Send SYNC_UPDATE events, if available +*/ +static void btcReplayEvents( tpAniSirGlobal pMac ) +{ + int i, j; + tSmeBtEvent btEvent; + tpSmeBtAclEventHist pAclHist; + tpSmeBtSyncEventHist pSyncHist; + tSmeBtcEventReplay *pReplay = &pMac->btc.btcEventReplay; + //Always turn on HB monitor first. + //It is independent of BT events even though BT event causes this + if( pReplay->fRestoreHBMonitor ) + { + pReplay->fRestoreHBMonitor = VOS_FALSE; + //Only do it when needed + if( !pMac->btc.btcHBActive ) + { + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE); + pMac->btc.btcHBActive = VOS_TRUE; + } + } + if( pMac->btc.fReplayBTEvents ) + { + /*Set the flag to false here so btcSignalBTEvent won't defer any further. + This works because SME has it global lock*/ + pMac->btc.fReplayBTEvents = VOS_FALSE; + if( pReplay->fBTSwitchOff ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_DEVICE_SWITCHED_OFF; + btcSendBTEvent( pMac, &btEvent ); + pReplay->fBTSwitchOff = VOS_FALSE; + } + else if( pReplay->fBTSwitchOn ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_DEVICE_SWITCHED_ON; + btcSendBTEvent( pMac, &btEvent ); + pReplay->fBTSwitchOn = VOS_FALSE; + } + //Do inquire first + if( pReplay->btcEventHist.nInquiryEvent > 0 ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_INQUIRY_STARTED; + i = pReplay->btcEventHist.nInquiryEvent; + while(i--) + { + btcSendBTEvent( pMac, &btEvent ); + } + } + else if( pReplay->btcEventHist.nInquiryEvent < 0 ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_INQUIRY_STOPPED; + i = pReplay->btcEventHist.nInquiryEvent; + while(i++) + { + btcSendBTEvent( pMac, &btEvent ); + } + } + //Page + if( pReplay->btcEventHist.nPageEvent > 0 ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_PAGE_STARTED; + i = pReplay->btcEventHist.nPageEvent; + while(i--) + { + btcSendBTEvent( pMac, &btEvent ); + } + } + else if( pReplay->btcEventHist.nPageEvent < 0 ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_PAGE_STOPPED; + i = pReplay->btcEventHist.nPageEvent; + while(i++) + { + btcSendBTEvent( pMac, &btEvent ); + } + } + //Replay non-completion disconnect events first + //Disconnect + for( i = 0; i < BT_MAX_DISCONN_SUPPORT; i++ ) + { + if( pReplay->btcEventHist.btDisconnectEvent[i].fValid ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_DISCONNECTION_COMPLETE; + vos_mem_copy( &btEvent.uEventParam.btDisconnect, + &pReplay->btcEventHist.btDisconnectEvent[i].btDisconnect, sizeof(tSmeBtDisconnectParam) ); + btcSendBTEvent( pMac, &btEvent ); + } + } + //ACL + for( i = 0; i < BT_MAX_ACL_SUPPORT; i++ ) + { + if( pReplay->btcEventHist.btAclConnectionEvent[i].bNextEventIdx ) + { + pAclHist = &pReplay->btcEventHist.btAclConnectionEvent[i]; + //Replay all ACL events for this BD address/handle + for(j = 0; j < pAclHist->bNextEventIdx; j++) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = pAclHist->btEventType[j]; + if(BT_EVENT_DISCONNECTION_COMPLETE != btEvent.btEventType) + { + //It must be CREATE or CONNECTION_COMPLETE + vos_mem_copy( &btEvent.uEventParam.btAclConnection, + &pAclHist->btAclConnection[j], sizeof(tSmeBtAclConnectionParam) ); + } + else + { + btEvent.uEventParam.btDisconnect.connectionHandle = pAclHist->btAclConnection[j].connectionHandle; + } + btcSendBTEvent( pMac, &btEvent ); + } + } + } + //Mode change + for( i = 0; i < BT_MAX_ACL_SUPPORT; i++ ) + { + if( pReplay->btcEventHist.btAclModeChangeEvent[i].fValid ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_MODE_CHANGED; + vos_mem_copy( &btEvent.uEventParam.btAclModeChange, + &pReplay->btcEventHist.btAclModeChangeEvent[i].btAclModeChange, sizeof(tSmeBtAclModeChangeParam) ); + btcSendBTEvent( pMac, &btEvent ); + } + } + //A2DP + if( pReplay->btcEventHist.fA2DPStarted ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_A2DP_STREAM_START; + btcSendBTEvent( pMac, &btEvent ); + } + else if( pReplay->btcEventHist.fA2DPStopped ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_A2DP_STREAM_STOP; + btcSendBTEvent( pMac, &btEvent ); + } + //SCO + for( i = 0; i < BT_MAX_SCO_SUPPORT; i++ ) + { + if( pReplay->btcEventHist.btSyncConnectionEvent[i].bNextEventIdx ) + { + pSyncHist = &pReplay->btcEventHist.btSyncConnectionEvent[i]; + //Replay all SYNC events for this BD address/handle + for(j = 0; j < pSyncHist->bNextEventIdx; j++) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = pSyncHist->btEventType[j]; + if(BT_EVENT_DISCONNECTION_COMPLETE != btEvent.btEventType) + { + //Must be CREATION or CONNECTION_COMPLETE + vos_mem_copy( &btEvent.uEventParam.btSyncConnection, + &pSyncHist->btSyncConnection[j], sizeof(tSmeBtSyncConnectionParam) ); + } + else + { + btEvent.uEventParam.btDisconnect.connectionHandle = pSyncHist->btSyncConnection[j].connectionHandle; + } + btcSendBTEvent( pMac, &btEvent ); + } + } + } + //SYNC update + for( i = 0; i < BT_MAX_SCO_SUPPORT; i++ ) + { + if( pReplay->btcEventHist.btSyncUpdateEvent[i].fValid ) + { + vos_mem_zero( &btEvent, sizeof(tSmeBtEvent) ); + btEvent.btEventType = BT_EVENT_SYNC_CONNECTION_UPDATED; + vos_mem_copy( &btEvent.uEventParam.btSyncConnection, + &pReplay->btcEventHist.btSyncUpdateEvent[i].btSyncConnection, + sizeof(tSmeBtSyncConnectionParam) ); + btcSendBTEvent( pMac, &btEvent ); + } + } + //Clear all events + vos_mem_zero( &pReplay->btcEventHist, sizeof(tSmeBtcEventHist) ); + } +} + +static void btcPowerStateCB( v_PVOID_t pContext, tPmcState pmcState ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(pContext); + if( FULL_POWER == pmcState ) + { + btcReplayEvents( pMac ); + } +} + +static void btcPowerOffloadStateCB(v_PVOID_t pContext, tANI_U32 sessionId, + tPmcState pmcState ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(pContext); + if(FULL_POWER == pmcState) + { + btcReplayEvents(pMac); + } +} + + +/* --------------------------------------------------------------------------- + \fn btcLogEvent + \brief API to log the the current Bluetooth event + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtEvent. Caller owns the memory and is responsible + for freeing it. + \return None + ---------------------------------------------------------------------------*/ +static void btcLogEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent) +{ + v_U8_t bdAddrRev[6]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Bluetooth Event %d received", __func__, pBtEvent->btEventType); + switch(pBtEvent->btEventType) + { + case BT_EVENT_CREATE_SYNC_CONNECTION: + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + case BT_EVENT_SYNC_CONNECTION_UPDATED: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "SCO Connection: " + "connectionHandle = %d status = %d linkType %d " + "scoInterval %d scoWindow %d retransmisisonWindow = %d ", + pBtEvent->uEventParam.btSyncConnection.connectionHandle, + pBtEvent->uEventParam.btSyncConnection.status, + pBtEvent->uEventParam.btSyncConnection.linkType, + pBtEvent->uEventParam.btSyncConnection.scoInterval, + pBtEvent->uEventParam.btSyncConnection.scoWindow, + pBtEvent->uEventParam.btSyncConnection.retransmisisonWindow); + + bdAddrRev[0] = pBtEvent->uEventParam.btSyncConnection.bdAddr[5]; + bdAddrRev[1] = pBtEvent->uEventParam.btSyncConnection.bdAddr[4]; + bdAddrRev[2] = pBtEvent->uEventParam.btSyncConnection.bdAddr[3]; + bdAddrRev[3] = pBtEvent->uEventParam.btSyncConnection.bdAddr[2]; + bdAddrRev[4] = pBtEvent->uEventParam.btSyncConnection.bdAddr[1]; + bdAddrRev[5] = pBtEvent->uEventParam.btSyncConnection.bdAddr[0]; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "BD ADDR = " + MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bdAddrRev)); + break; + case BT_EVENT_CREATE_ACL_CONNECTION: + case BT_EVENT_ACL_CONNECTION_COMPLETE: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "ACL Connection: " + "connectionHandle = %d status = %d ", + pBtEvent->uEventParam.btAclConnection.connectionHandle, + pBtEvent->uEventParam.btAclConnection.status); + + bdAddrRev[0] = pBtEvent->uEventParam.btAclConnection.bdAddr[5]; + bdAddrRev[1] = pBtEvent->uEventParam.btAclConnection.bdAddr[4]; + bdAddrRev[2] = pBtEvent->uEventParam.btAclConnection.bdAddr[3]; + bdAddrRev[3] = pBtEvent->uEventParam.btAclConnection.bdAddr[2]; + bdAddrRev[4] = pBtEvent->uEventParam.btAclConnection.bdAddr[1]; + bdAddrRev[5] = pBtEvent->uEventParam.btAclConnection.bdAddr[0]; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "BD ADDR = " + MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bdAddrRev)); + break; + case BT_EVENT_MODE_CHANGED: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "ACL Mode change : " + "connectionHandle %d mode %d ", + pBtEvent->uEventParam.btAclModeChange.connectionHandle, + pBtEvent->uEventParam.btAclModeChange.mode); + break; + case BT_EVENT_DISCONNECTION_COMPLETE: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "Disconnect Event : " + "connectionHandle %d ", pBtEvent->uEventParam.btAclModeChange.connectionHandle); + break; + default: + break; + } + } + +/* + Caller can check whether BTC's current event allows UAPSD. This doesn't affect + BMPS. + return: VOS_TRUE -- BTC is ready for UAPSD + VOS_FALSE -- certain BT event is active, cannot enter UAPSD +*/ +v_BOOL_t btcIsReadyForUapsd( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return( pMac->btc.btcUapsdOk ); +} + +/* + Base on the BT event, this function sets the flag on whether to allow UAPSD + At this time, we are only interested in SCO and A2DP. + A2DP tracking is through BT_EVENT_A2DP_STREAM_START and BT_EVENT_A2DP_STREAM_STOP + SCO is through BT_EVENT_SYNC_CONNECTION_COMPLETE and BT_EVENT_DISCONNECTION_COMPLETE + BT_EVENT_DEVICE_SWITCHED_OFF overwrites them all +*/ +void btcUapsdCheck( tpAniSirGlobal pMac, tpSmeBtEvent pBtEvent ) +{ + v_U8_t i; + v_BOOL_t fLastUapsdState = pMac->btc.btcUapsdOk, fMoreSCO = VOS_FALSE; + switch( pBtEvent->btEventType ) + { + case BT_EVENT_DISCONNECTION_COMPLETE: + if( (VOS_FALSE == pMac->btc.btcUapsdOk) && + BT_INVALID_CONN_HANDLE != pBtEvent->uEventParam.btDisconnect.connectionHandle ) + { + //Check whether all SCO connections are gone + for(i=0; i < BT_MAX_SCO_SUPPORT; i++) + { + if( (BT_INVALID_CONN_HANDLE != pMac->btc.btcScoHandles[i]) && + (pMac->btc.btcScoHandles[i] != pBtEvent->uEventParam.btDisconnect.connectionHandle) ) + { + //We still have outstanding SCO connection + fMoreSCO = VOS_TRUE; + } + else if( pMac->btc.btcScoHandles[i] == pBtEvent->uEventParam.btDisconnect.connectionHandle ) + { + pMac->btc.btcScoHandles[i] = BT_INVALID_CONN_HANDLE; + } + } + if( !fMoreSCO && !pMac->btc.fA2DPUp ) + { + //All SCO is disconnected + smsLog( pMac, LOGE, "BT event (DISCONNECTION) happens, UAPSD-allowed flag (%d) change to TRUE", + pMac->btc.btcUapsdOk ); + pMac->btc.btcUapsdOk = VOS_TRUE; + } + } + break; + case BT_EVENT_DEVICE_SWITCHED_OFF: + smsLog( pMac, LOGE, "BT event (DEVICE_OFF) happens, UAPSD-allowed flag (%d) change to TRUE", + pMac->btc.btcUapsdOk ); + //Clean up SCO + for(i=0; i < BT_MAX_SCO_SUPPORT; i++) + { + pMac->btc.btcScoHandles[i] = BT_INVALID_CONN_HANDLE; + } + pMac->btc.fA2DPUp = VOS_FALSE; + pMac->btc.btcUapsdOk = VOS_TRUE; + break; + case BT_EVENT_A2DP_STREAM_STOP: + smsLog( pMac, LOGE, "BT event (A2DP_STREAM_STOP) happens, UAPSD-allowed flag (%d)", + pMac->btc.btcUapsdOk ); + pMac->btc.fA2DPUp = VOS_FALSE; + //Check whether SCO is on + for(i=0; i < BT_MAX_SCO_SUPPORT; i++) + { + if(pMac->btc.btcScoHandles[i] != BT_INVALID_CONN_HANDLE) + { + break; + } + } + if( BT_MAX_SCO_SUPPORT == i ) + { + pMac->btc.fA2DPTrafStop = VOS_TRUE; + smsLog( pMac, LOGE, "BT_EVENT_A2DP_STREAM_STOP: UAPSD-allowed flag is now %d", + pMac->btc.btcUapsdOk ); + } + break; + + case BT_EVENT_MODE_CHANGED: + smsLog( pMac, LOGE, "BT event (BT_EVENT_MODE_CHANGED) happens, Mode (%d) UAPSD-allowed flag (%d)", + pBtEvent->uEventParam.btAclModeChange.mode, pMac->btc.btcUapsdOk ); + if(pBtEvent->uEventParam.btAclModeChange.mode == BT_ACL_SNIFF) + { + //Check whether SCO is on + for(i=0; i < BT_MAX_SCO_SUPPORT; i++) + { + if(pMac->btc.btcScoHandles[i] != BT_INVALID_CONN_HANDLE) + { + break; + } + } + if( BT_MAX_SCO_SUPPORT == i ) + { + if(VOS_TRUE == pMac->btc.fA2DPTrafStop) + { + pMac->btc.btcUapsdOk = VOS_TRUE; + pMac->btc.fA2DPTrafStop = VOS_FALSE; + } + smsLog( pMac, LOGE, "BT_EVENT_MODE_CHANGED with Mode:%d UAPSD-allowed flag is now %d", + pBtEvent->uEventParam.btAclModeChange.mode,pMac->btc.btcUapsdOk ); + } + } + break; + case BT_EVENT_CREATE_SYNC_CONNECTION: + { + pMac->btc.btcUapsdOk = VOS_FALSE; + smsLog( pMac, LOGE, "BT_EVENT_CREATE_SYNC_CONNECTION (%d) happens, UAPSD-allowed flag (%d) change to FALSE", + pBtEvent->btEventType, pMac->btc.btcUapsdOk ); + } + break; + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + //Make sure it is a success + if( BT_CONN_STATUS_FAIL != pBtEvent->uEventParam.btSyncConnection.status ) + { + /* Save the handle for later use */ + for( i = 0; i < BT_MAX_SCO_SUPPORT; i++) + { + VOS_ASSERT(BT_INVALID_CONN_HANDLE != pBtEvent->uEventParam.btSyncConnection.connectionHandle); + if( (BT_INVALID_CONN_HANDLE == pMac->btc.btcScoHandles[i]) && + (BT_INVALID_CONN_HANDLE != pBtEvent->uEventParam.btSyncConnection.connectionHandle)) + { + pMac->btc.btcScoHandles[i] = pBtEvent->uEventParam.btSyncConnection.connectionHandle; + break; + } + } + + if( i >= BT_MAX_SCO_SUPPORT ) + { + smsLog(pMac, LOGE, FL("Too many SCO, ignore this one")); + } + } + else + { + //Check whether SCO is on + for(i=0; i < BT_MAX_SCO_SUPPORT; i++) + { + if(pMac->btc.btcScoHandles[i] != BT_INVALID_CONN_HANDLE) + { + break; + } + } + /*If No Other Sco/A2DP is ON reenable UAPSD*/ + if( (BT_MAX_SCO_SUPPORT == i) && !pMac->btc.fA2DPUp) + { + pMac->btc.btcUapsdOk = VOS_TRUE; + } + smsLog(pMac, LOGE, FL("TSYNC complete failed")); + } + break; + case BT_EVENT_A2DP_STREAM_START: + smsLog( pMac, LOGE, "BT_EVENT_A2DP_STREAM_START (%d) happens, UAPSD-allowed flag (%d) change to FALSE", + pBtEvent->btEventType, pMac->btc.btcUapsdOk ); + pMac->btc.fA2DPTrafStop = VOS_FALSE; + pMac->btc.btcUapsdOk = VOS_FALSE; + pMac->btc.fA2DPUp = VOS_TRUE; + break; + default: + //No change for these events + smsLog( pMac, LOGE, "BT event (%d) happens, UAPSD-allowed flag (%d) no change", + pBtEvent->btEventType, pMac->btc.btcUapsdOk ); + break; + } + if(fLastUapsdState != pMac->btc.btcUapsdOk) + { + sme_QosTriggerUapsdChange( pMac ); + } +} + +/* --------------------------------------------------------------------------- + \fn btcHandleCoexInd + \brief API to handle Coex indication from WDI + \param pMac - The handle returned by macOpen. + \return eHalStatus + eHAL_STATUS_FAILURE success + eHAL_STATUS_SUCCESS failure + ---------------------------------------------------------------------------*/ +eHalStatus btcHandleCoexInd(tHalHandle hHal, void* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeCoexInd *pSmeCoexInd = (tSirSmeCoexInd *)pMsg; + + if (NULL == pMsg) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + } + else + { + // DEBUG + smsLog(pMac, LOG1, "Coex indication in %s(), type %d", + __func__, pSmeCoexInd->coexIndType); + + // suspend heartbeat monitoring + if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_HB_MONITOR) + { + // set heartbeat threshold CFG to zero + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0, NULL, eANI_BOOLEAN_FALSE); + pMac->btc.btcHBActive = VOS_FALSE; + } + + // resume heartbeat monitoring + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_HB_MONITOR) + { + if (!pMac->btc.btcHBActive) + { + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->btc.btcHBCount, NULL, eANI_BOOLEAN_FALSE); + pMac->btc.btcHBActive = VOS_TRUE; + } + } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_SCAN_COMPROMISED) + { + pMac->btc.btcScanCompromise = VOS_TRUE; + smsLog(pMac, LOGW, "Coex indication in %s(), type - SIR_COEX_IND_TYPE_SCAN_COMPROMISED", + __func__); + } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED) + { + pMac->btc.btcScanCompromise = VOS_FALSE; + smsLog(pMac, LOGW, "Coex indication in %s(), type - SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED", + __func__); + } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4) + { + if (pMac->roam.configParam.disableAggWithBtc) + { + ccmCfgSetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, 1, + NULL, eANI_BOOLEAN_FALSE); + pMac->btc.btcBssfordisableaggr[0] = pSmeCoexInd->coexIndData[0] & 0xFF; + pMac->btc.btcBssfordisableaggr[1] = pSmeCoexInd->coexIndData[0] >> 8; + pMac->btc.btcBssfordisableaggr[2] = pSmeCoexInd->coexIndData[1] & 0xFF; + pMac->btc.btcBssfordisableaggr[3] = pSmeCoexInd->coexIndData[1] >> 8; + pMac->btc.btcBssfordisableaggr[4] = pSmeCoexInd->coexIndData[2] & 0xFF; + pMac->btc.btcBssfordisableaggr[5] = pSmeCoexInd->coexIndData[2] >> 8; + smsLog(pMac, LOGW, "Coex indication in %s(), " + "type - SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4 " + "for BSSID "MAC_ADDRESS_STR,__func__, + MAC_ADDR_ARRAY(pMac->btc.btcBssfordisableaggr)); + } + } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4) + { + if (pMac->roam.configParam.disableAggWithBtc) + { + ccmCfgSetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, 0, + NULL, eANI_BOOLEAN_FALSE); + smsLog(pMac, LOGW, + "Coex indication in %s(), type - SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4", + __func__); + } + } + // unknown indication type + else + { + smsLog(pMac, LOGE, "unknown Coex indication type in %s()", __func__); + } + } + + return(status); +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/* --------------------------------------------------------------------------- + \fn btcDiagEventLog + \brief API to log the the current Bluetooth event + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtEvent. Caller owns the memory and is responsible + for freeing it. + \return None + ---------------------------------------------------------------------------*/ +static void btcDiagEventLog (tHalHandle hHal, tpSmeBtEvent pBtEvent) +{ + //vos_event_wlan_btc_type *log_ptr = NULL; + WLAN_VOS_DIAG_EVENT_DEF(btDiagEvent, vos_event_wlan_btc_type); + { + btDiagEvent.eventId = pBtEvent->btEventType; + switch(pBtEvent->btEventType) + { + case BT_EVENT_CREATE_SYNC_CONNECTION: + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + case BT_EVENT_SYNC_CONNECTION_UPDATED: + btDiagEvent.connHandle = pBtEvent->uEventParam.btSyncConnection.connectionHandle; + btDiagEvent.connStatus = pBtEvent->uEventParam.btSyncConnection.status; + btDiagEvent.linkType = pBtEvent->uEventParam.btSyncConnection.linkType; + btDiagEvent.scoInterval = pBtEvent->uEventParam.btSyncConnection.scoInterval; + btDiagEvent.scoWindow = pBtEvent->uEventParam.btSyncConnection.scoWindow; + btDiagEvent.retransWindow = pBtEvent->uEventParam.btSyncConnection.retransmisisonWindow; + vos_mem_copy(btDiagEvent.btAddr, pBtEvent->uEventParam.btSyncConnection.bdAddr, + sizeof(btDiagEvent.btAddr)); + break; + case BT_EVENT_CREATE_ACL_CONNECTION: + case BT_EVENT_ACL_CONNECTION_COMPLETE: + btDiagEvent.connHandle = pBtEvent->uEventParam.btAclConnection.connectionHandle; + btDiagEvent.connStatus = pBtEvent->uEventParam.btAclConnection.status; + vos_mem_copy(btDiagEvent.btAddr, pBtEvent->uEventParam.btAclConnection.bdAddr, + sizeof(btDiagEvent.btAddr)); + break; + case BT_EVENT_MODE_CHANGED: + btDiagEvent.connHandle = pBtEvent->uEventParam.btAclModeChange.connectionHandle; + btDiagEvent.mode = pBtEvent->uEventParam.btAclModeChange.mode; + break; + case BT_EVENT_DISCONNECTION_COMPLETE: + btDiagEvent.connHandle = pBtEvent->uEventParam.btAclModeChange.connectionHandle; + break; + default: + break; + } + } + WLAN_VOS_DIAG_EVENT_REPORT(&btDiagEvent, EVENT_WLAN_BTC); +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmApi.c new file mode 100644 index 000000000000..6f5bea610af6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmApi.c @@ -0,0 +1,789 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "palTypes.h" +#include "wniApi.h" /* WNI_CFG_SET_REQ */ +#include "sirParams.h" /* tSirMbMsg */ +#include "smsDebug.h" /* smsLog */ +#include "cfgApi.h" +#include "ccmApi.h" +#include "logDump.h" + +#define CFGOBJ_ALIGNTO 4 +#define CFGOBJ_ALIGN(len) ( ((len)+CFGOBJ_ALIGNTO-1) & ~(CFGOBJ_ALIGNTO-1) ) + +#define CFGOBJ_ID_SIZE 4 /* 4 bytes for cfgId */ +#define CFGOBJ_LEN_SIZE 4 /* 4 bytes for length */ +#define CFGOBJ_INTEGER_VALUE_SIZE 4 /* 4 bytes for integer value */ + +#define CFG_UPDATE_MAGIC_DWORD 0xabab + +#define halHandle2HddHandle(hHal) ( (NULL == (hHal)) ? 0 : ((tpAniSirGlobal)(hHal))->hHdd ) + +static void ccmComplete(tHddHandle hHdd, void *done) +{ + if (done) + { + (void)palSemaphoreGive(hHdd, done); + } +} + +static void ccmWaitForCompletion(tHddHandle hHdd, void *done) +{ + if (done) + { + (void)palSemaphoreTake(hHdd, done); + } +} + +static tANI_U32 * encodeCfgReq(tHddHandle hHdd, tANI_U32 *pl, tANI_U32 cfgId, tANI_S32 length, void *pBuf, tANI_U32 value, tANI_U32 type) +{ + *pl++ = pal_cpu_to_be32(cfgId) ; + *pl++ = pal_cpu_to_be32(length) ; + if (type == CCM_INTEGER_TYPE) + { + *pl++ = pal_cpu_to_be32(value) ; + } + else + { + vos_mem_copy((void *)pl, (void *)pBuf, length); + pl += (CFGOBJ_ALIGN(length) / CFGOBJ_ALIGNTO); + } + return pl ; +} + +/* + * CCM_STRING_TYPE CCM_INTEGER_TYPE + * |<-------- 4 ----->| |<-------- 4 ----->| + * +----------+ <-- msg --> +----------+ + * |type | |type | + * +----------+ +----------+ + * |msgLen=24 | |msgLen=16 | + * +----------+----------+ +----------+----------+ + * | cfgId | | cfgId | + * +---------------------+ +---------------------+ + * | length=11 | | length=4 | + * +---------------------+ +---------------------+ + * | | | value | + * | | +---------------------+ + * | | + * | +----+ + * | |////| <- padding to 4-byte boundary + * +----------------+----+ + */ +static eHalStatus sendCfg(tpAniSirGlobal pMac, tHddHandle hHdd, tCfgReq *req, tANI_BOOLEAN fRsp) +{ + tSirMbMsg *msg; + eHalStatus status; + tANI_S16 msgLen = (tANI_U16)(4 + /* 4 bytes for msg header */ + CFGOBJ_ID_SIZE + + CFGOBJ_LEN_SIZE + + CFGOBJ_ALIGN(req->length)) ; + + msg = vos_mem_malloc(msgLen); + if ( NULL != msg ) + { + if( fRsp ) + { + msg->type = pal_cpu_to_be16(WNI_CFG_SET_REQ); + } + else + { + msg->type = pal_cpu_to_be16(WNI_CFG_SET_REQ_NO_RSP); + } + msg->msgLen = pal_cpu_to_be16(msgLen); + (void)encodeCfgReq(hHdd, msg->data, req->cfgId, req->length, req->ccmPtr, req->ccmValue, req->type) ; + + status = palSendMBMessage(hHdd, msg) ; + if (status != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, FL("palSendMBMessage() failed")); + //No need to free msg. palSendMBMessage frees it. + status = eHAL_STATUS_FAILURE ; + } + } + else + { + smsLog( pMac, LOGW, FL("failed to allocate memory(len=%d)"), msgLen ); + status = eHAL_STATUS_FAILURE; + } + + return status ; +} + +static tCfgReq * allocateCfgReq(tHddHandle hHdd, tANI_U32 type, tANI_S32 length) +{ + tCfgReq *req ; + tANI_S32 alloc_len = sizeof(tCfgReq) ; + + if (type == CCM_STRING_TYPE) + { + alloc_len += length ; + } + + req = vos_mem_malloc(alloc_len); + if ( NULL == req ) + { + return NULL ; + } + + req->ccmPtr = (req+1); + + return req ; +} + +static void freeCfgReq(tHddHandle hHdd, tCfgReq *req) +{ + vos_mem_free(req); +} + +static void add_req_tail(tCfgReq *req, struct ccmlink *q) +{ + if (q->tail) + { + q->tail->next = req; + q->tail = req ; + } + else + { + q->head = q->tail = req ; + } +} + +static void del_req(tCfgReq *req, struct ccmlink *q) +{ + q->head = req->next ; + req->next = NULL ; + if (q->head == NULL) + { + q->tail = NULL ; + } +} + +static void purgeReqQ(tHalHandle hHal) +{ + tHddHandle hHdd = halHandle2HddHandle(hHal); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCfgReq *req, *tmp ; + + for (req = pMac->ccm.reqQ.head; req; req = tmp) + { + /* loop thru reqQ and invoke callback to return failure */ + smsLog(pMac, LOGW, FL("deleting cfgReq, cfgid=%d"), (int)req->cfgId); + + tmp = req->next ; + + if (req->callback) + { + req->callback(hHal, eHAL_STATUS_FAILURE); + } + palSpinLockTake(hHdd, pMac->ccm.lock); + del_req(req, &pMac->ccm.reqQ); + palSpinLockGive(hHdd, pMac->ccm.lock); + freeCfgReq(hHdd, req); + } + return ; +} + +static void sendQueuedReqToMacSw(tpAniSirGlobal pMac, tHddHandle hHdd) +{ + tCfgReq *req ; + + /* Send the head req */ + req = pMac->ccm.reqQ.head ; + if (req) + { + if (req->state == eCCM_REQ_QUEUED) + { + /* Send WNI_CFG_SET_REQ */ + req->state = eCCM_REQ_SENT; + if (sendCfg(pMac, hHdd, req, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, FL("sendCfg() failed")); + palSpinLockTake(hHdd, pMac->ccm.lock); + del_req(req, &pMac->ccm.reqQ) ; + palSpinLockGive(hHdd, pMac->ccm.lock); + if (req->callback) + { + req->callback((tHalHandle)pMac, WNI_CFG_OTHER_ERROR) ; + } + + ccmComplete(hHdd, req->done); + + freeCfgReq(hHdd, req); + } + } + else + { + smsLog( pMac, LOGW, FL("reqState is not eCCM_REQ_QUEUED, is %d"), req->state ); + } + } + + return ; +} + +static eHalStatus cfgSetSub(tpAniSirGlobal pMac, tHddHandle hHdd, tANI_U32 cfgId, tANI_U32 type, + tANI_S32 length, void *ccmPtr, tANI_U32 ccmValue, + tCcmCfgSetCallback callback, eAniBoolean toBeSaved, void *sem, tCfgReq **r) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCfgReq *req ; + + do + { + *r = NULL ; + + if (pMac->ccm.state == eCCM_STOPPED) + { + status = eHAL_STATUS_FAILURE ; + break ; + } + + req = allocateCfgReq(hHdd, type, length); + if (req == NULL) + { + status = eHAL_STATUS_FAILED_ALLOC ; + break ; + } + + req->next = NULL ; + req->cfgId = (tANI_U16)cfgId ; + req->type = (tANI_U8)type ; + req->state = eCCM_REQ_QUEUED ; + req->toBeSaved = !!toBeSaved ; + req->length = length ; + req->done = sem ; + req->callback = callback ; + if (type == CCM_INTEGER_TYPE) + { + req->ccmValue = ccmValue ; + } + else + { + vos_mem_copy((void *)req->ccmPtr, (void *)ccmPtr, length); + } + + palSpinLockTake(hHdd, pMac->ccm.lock); + + add_req_tail(req, &pMac->ccm.reqQ); + /* If this is the first req on the queue, send it to MAC SW */ + if ((pMac->ccm.replay.started == 0) && (pMac->ccm.reqQ.head == req)) + { + /* Send WNI_CFG_SET_REQ */ + req->state = eCCM_REQ_SENT; + palSpinLockGive(hHdd, pMac->ccm.lock); + status = sendCfg(pMac, hHdd, req, eANI_BOOLEAN_TRUE) ; + if (status != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, FL("sendCfg() failed")); + palSpinLockTake(hHdd, pMac->ccm.lock); + del_req(req, &pMac->ccm.reqQ); + palSpinLockGive(hHdd, pMac->ccm.lock); + freeCfgReq(hHdd, req); + break ; + } + else + { + palSpinLockTake(hHdd, pMac->ccm.lock); + if(req != pMac->ccm.reqQ.head) + { + //We send the request and it must be done already + req = NULL; + } + palSpinLockGive(hHdd, pMac->ccm.lock); + } + } + else + { + palSpinLockGive(hHdd, pMac->ccm.lock); + } + *r = req ; + + } while(0) ; + + return status; +} + +static eHalStatus cfgSet(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 type, tANI_S32 length, void * ccmPtr, tANI_U32 ccmValue, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) +{ + tHddHandle hHdd = halHandle2HddHandle(hHal); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + tCfgReq *req ; + + if (pal_in_interrupt()) + { + status = cfgSetSub(pMac, hHdd, cfgId, type, length, ccmPtr, ccmValue, callback, toBeSaved, NULL, &req); + } + else + { + void *sem ; + + pal_local_bh_disable() ; + + status = palMutexAllocLocked( hHdd, &sem ) ; + if (status != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, FL("mutex alloc failed")); + sem = NULL; + } + else + { + status = cfgSetSub(pMac, hHdd, cfgId, type, length, ccmPtr, ccmValue, callback, toBeSaved, sem, &req); + if ((status != eHAL_STATUS_SUCCESS) || (req == NULL)) + { + //Either it fails to send or the req is finished already + palSemaphoreFree( hHdd, sem ); + sem = NULL; + } + } + + pal_local_bh_enable() ; + + if ((status == eHAL_STATUS_SUCCESS) && (sem != NULL)) + { + ccmWaitForCompletion(hHdd, sem); + + palSemaphoreFree( hHdd, sem ) ; + } + } + + return status ; +} + +eHalStatus ccmOpen(tHalHandle hHal) +{ + tHddHandle hHdd = halHandle2HddHandle(hHal); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + vos_mem_set(&pMac->ccm, sizeof(tCcm), 0); + return palSpinLockAlloc(hHdd, &pMac->ccm.lock); +} + +eHalStatus ccmClose(tHalHandle hHal) +{ + tHddHandle hHdd = halHandle2HddHandle(hHal); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U32 i ; + tCfgReq *req ; + + ccmStop(hHal); + + /* Go thru comp[] to free all saved requests */ + for (i = 0 ; i < CFG_PARAM_MAX_NUM ; ++i) + { + if ((req = pMac->ccm.comp[i]) != NULL) + { + freeCfgReq(hHdd, req); + } + } + + return palSpinLockFree(hHdd, pMac->ccm.lock); +} + +/* This function executes in (Linux) softirq context */ +void ccmCfgCnfMsgHandler(tHalHandle hHal, void *m) +{ + tHddHandle hHdd = halHandle2HddHandle(hHal); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSirMbMsg *msg = (tSirMbMsg *)m ; + tANI_U32 result, cfgId ; + tCfgReq *req, *old ; + + result = pal_be32_to_cpu(msg->data[0]); + cfgId = pal_be32_to_cpu(msg->data[1]); + + if (pMac->ccm.replay.started && cfgId == CFG_UPDATE_MAGIC_DWORD) + { + pMac->ccm.replay.in_progress = 1 ; + return ; + } + + if (pMac->ccm.replay.in_progress) + { + /* save error code */ + if (!CCM_IS_RESULT_SUCCESS(result)) + { + pMac->ccm.replay.result = result ; + } + + if (--pMac->ccm.replay.nr_param == 0) + { + pMac->ccm.replay.in_progress = 0 ; + + if (pMac->ccm.replay.callback) + { + pMac->ccm.replay.callback(hHal, pMac->ccm.replay.result); + } + + pMac->ccm.replay.started = 0 ; + + /* Wake up the sleeping process */ + ccmComplete(hHdd, pMac->ccm.replay.done); + //Let go with the rest of the set CFGs waiting. + sendQueuedReqToMacSw(pMac, hHdd); + } + } + else + { + /* + * Try to match this response with the request. + * What if i could not find the req entry ??? + */ + req = pMac->ccm.reqQ.head ; + if (req) + { + + if (req->cfgId == cfgId && req->state == eCCM_REQ_SENT) + { + palSpinLockTake(hHdd, pMac->ccm.lock); + del_req(req, &pMac->ccm.reqQ); + palSpinLockGive(hHdd, pMac->ccm.lock); + req->state = eCCM_REQ_DONE ; + + if (result == WNI_CFG_NEED_RESTART || + result == WNI_CFG_NEED_RELOAD) + { + //purgeReqQ(hHal); + } + + /* invoke callback */ + if (req->callback) + { + req->callback(hHal, result) ; + } + + /* Wake up the sleeping process */ + ccmComplete(hHdd, req->done); + + /* move the completed req from reqQ to comp[] */ + if (req->toBeSaved && (CCM_IS_RESULT_SUCCESS(result))) + { + if (cfgId < CFG_PARAM_MAX_NUM) + { + if ((old = pMac->ccm.comp[cfgId]) != NULL) + { + freeCfgReq(hHdd, old) ; + } + pMac->ccm.comp[cfgId] = req ; + } + } + else + { + freeCfgReq(hHdd, req) ; + } + sendQueuedReqToMacSw(pMac, hHdd); + } + else + { + smsLog( pMac, LOGW, FL("can not match RSP with REQ, rspcfgid=%d result=%d reqcfgid=%d reqstate=%d"), + (int)cfgId, (int)result, req->cfgId, req->state); + + } + + } + } + + return ; +} + +void ccmStart(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->ccm.state = eCCM_STARTED ; + +#if defined(ANI_LOGDUMP) + ccmDumpInit(hHal); +#endif //#if defined(ANI_LOGDUMP) + + return ; +} + +void ccmStop(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->ccm.state = eCCM_STOPPED ; + + pal_local_bh_disable() ; + purgeReqQ(hHal); + pal_local_bh_enable() ; + + return ; +} + +eHalStatus ccmCfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) +{ + if( callback || toBeSaved) + { + /* We need to synchronous this one */ + return cfgSet(hHal, cfgId, CCM_INTEGER_TYPE, sizeof(tANI_U32), NULL, ccmValue, callback, toBeSaved); + } + else + { + //Simply push to CFG and not waiting for the response + tCfgReq req; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + req.callback = NULL; + req.next = NULL; + req.cfgId = ( tANI_U16 )cfgId; + req.length = sizeof( tANI_U32 ); + req.type = CCM_INTEGER_TYPE; + req.ccmPtr = NULL; + req.ccmValue = ccmValue; + req.toBeSaved = toBeSaved; + req.state = eCCM_REQ_SENT; + + return ( sendCfg( pMac, pMac->hHdd, &req, eANI_BOOLEAN_FALSE ) ); + } +} + +eHalStatus ccmCfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr, tANI_U32 length, tCcmCfgSetCallback callback, eAniBoolean toBeSaved) +{ + if( callback || toBeSaved ) + { + /* We need to synchronous this one */ + return cfgSet(hHal, cfgId, CCM_STRING_TYPE, length, pStr, 0, callback, toBeSaved); + } + else + { + //Simply push to CFG and not waiting for the response + tCfgReq req; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + req.callback = NULL; + req.next = NULL; + req.cfgId = ( tANI_U16 )cfgId; + req.length = length; + req.type = CCM_STRING_TYPE; + req.ccmPtr = pStr; + req.ccmValue = 0; + req.toBeSaved = toBeSaved; + req.state = eCCM_REQ_SENT; + + return ( sendCfg( pMac, pMac->hHdd, &req, eANI_BOOLEAN_FALSE ) ); + } +} + +eHalStatus ccmCfgGetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 *pValue) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS ; + tCfgReq *req; + + if (cfgId >= CFG_PARAM_MAX_NUM) { + smsLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId); + return eHAL_STATUS_INVALID_PARAMETER; + } + + req = pMac->ccm.comp[cfgId] ; + + if (req && req->state == eCCM_REQ_DONE) + { + *pValue = req->ccmValue ; + } + else + { + if (wlan_cfgGetInt(pMac, (tANI_U16)cfgId, pValue) != eSIR_SUCCESS) + status = eHAL_STATUS_FAILURE; + } + + return status ; +} + +eHalStatus ccmCfgGetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pBuf, tANI_U32 *pLength) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tHddHandle hHdd; + eHalStatus status = eHAL_STATUS_SUCCESS ; + tCfgReq *req; + + if (!pMac) + return eHAL_STATUS_FAILURE; + + hHdd = halHandle2HddHandle(hHal); + + if (cfgId >= CFG_PARAM_MAX_NUM) { + smsLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId); + return eHAL_STATUS_INVALID_PARAMETER; + } + + req = pMac->ccm.comp[cfgId] ; + + if (req && req->state == eCCM_REQ_DONE && (tANI_U32)req->length <= *pLength) + { + *pLength = req->length ; + vos_mem_copy((void *)pBuf, (void *)req->ccmPtr, req->length); + } + else + { + if (wlan_cfgGetStr(pMac, (tANI_U16)cfgId, pBuf, pLength) != eSIR_SUCCESS) + status = eHAL_STATUS_FAILURE; + } + + return status ; +} + +/* + * Loop thru comp[] and form an ANI message which contains all completed cfgIds. + * The message begins with an INTEGER parameter (cfgId=CFG_UPDATE_MAGIC_DWORD) + * to mark the start of the message. + */ +static eHalStatus cfgUpdate(tpAniSirGlobal pMac, tHddHandle hHdd, tCcmCfgSetCallback callback) +{ + tANI_U32 i, *pl ; + tCfgReq *req ; + tSirMbMsg *msg ; + eHalStatus status ; + tANI_S16 msgLen = 4 + /* 4 bytes for msg header */ + /* for CFG_UPDATE_MAGIC_DWORD */ + CFGOBJ_ID_SIZE + + CFGOBJ_LEN_SIZE + + CFGOBJ_INTEGER_VALUE_SIZE ; + + if (pMac->ccm.state == eCCM_STOPPED || pMac->ccm.replay.started) + { + status = eHAL_STATUS_FAILURE ; + goto end ; + } + + palSpinLockTake(hHdd, pMac->ccm.lock); + + pMac->ccm.replay.started = 1 ; + pMac->ccm.replay.nr_param = 0 ; + + palSpinLockGive(hHdd, pMac->ccm.lock); + + /* Calculate message length */ + for (i = 0 ; i < CFG_PARAM_MAX_NUM ; ++i) + { + if ((req = pMac->ccm.comp[i]) != NULL) + { + msgLen += (tANI_S16)(CFGOBJ_ID_SIZE + CFGOBJ_LEN_SIZE + CFGOBJ_ALIGN(req->length)) ; + pMac->ccm.replay.nr_param += 1 ; + } + } + + if (pMac->ccm.replay.nr_param == 0) + { + if (callback) + { + callback((tHalHandle)pMac, WNI_CFG_SUCCESS) ; + } + status = eHAL_STATUS_SUCCESS ; + goto end ; + } + + pMac->ccm.replay.in_progress = 0 ; + pMac->ccm.replay.result = WNI_CFG_SUCCESS ; + pMac->ccm.replay.callback = callback ; + pMac->ccm.replay.done = NULL ; + + msg = vos_mem_malloc(msgLen); + if ( NULL == msg ) + { + pMac->ccm.replay.started = 0 ; + status = eHAL_STATUS_FAILURE; + goto end; + } + + msg->type = pal_cpu_to_be16(WNI_CFG_SET_REQ); + msg->msgLen = pal_cpu_to_be16(msgLen); + + /* Encode the starting cfgId */ + pl = encodeCfgReq(hHdd, msg->data, CFG_UPDATE_MAGIC_DWORD, 4, NULL, 0, CCM_INTEGER_TYPE) ; + + /* Encode the saved cfg requests */ + for (i = 0 ; i < CFG_PARAM_MAX_NUM ; ++i) + { + if ((req = pMac->ccm.comp[i]) != NULL) + { + pl = encodeCfgReq(hHdd, pl, req->cfgId, req->length, req->ccmPtr, req->ccmValue, req->type) ; + } + } + + status = palSendMBMessage(hHdd, msg) ; + if (status != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGW, FL("palSendMBMessage() failed. status=%d"), status); + pMac->ccm.replay.started = 0 ; + //No need to free msg. palSendMBMessage frees it. + goto end ; + } + + end: + return status ; +} + +eHalStatus ccmCfgUpdate(tHalHandle hHal, tCcmCfgSetCallback callback) +{ + tHddHandle hHdd = halHandle2HddHandle(hHal); + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status ; + + pal_local_bh_disable() ; + + status = cfgUpdate(pMac, hHdd, callback) ; + if (status == eHAL_STATUS_SUCCESS) + { + if (pMac->ccm.replay.nr_param == 0) + { + /* there is nothing saved at comp[], so we are done! */ + pMac->ccm.replay.started = 0 ; + } + else + { + /* we have sent update message to MAC SW */ + void *sem ; + + status = palMutexAllocLocked( hHdd, &sem ) ; + if (status != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, FL("mutex alloc failed")); + pMac->ccm.replay.started = 0 ; + } + else + { + pMac->ccm.replay.done = sem ; + } + } + } + + pal_local_bh_enable() ; + + /* Waiting here ... */ + if (status == eHAL_STATUS_SUCCESS && pMac->ccm.replay.done) + { + ccmWaitForCompletion(hHdd, pMac->ccm.replay.done); + + palSemaphoreFree( hHdd, pMac->ccm.replay.done) ; + } + + return status ; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmLogDump.c b/drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmLogDump.c new file mode 100644 index 000000000000..7ebd35b260c5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/ccm/ccmLogDump.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ +ccmLogDump.c + +Implements the dump commands specific to the ccm module. + ============================================================================*/ + + +#include "aniGlobal.h" +#include "logDump.h" + +#if defined(ANI_LOGDUMP) + +static tDumpFuncEntry ccmMenuDumpTable[] = { + + {0, "CCM (861-870)", NULL}, + //{861, "CCM: CCM testing ", dump_ccm} + +}; + +void ccmDumpInit(tHalHandle hHal) +{ + logDumpRegisterTable( (tpAniSirGlobal) hHal, &ccmMenuDumpTable[0], + sizeof(ccmMenuDumpTable)/sizeof(ccmMenuDumpTable[0]) ); +} + +#endif //#if defined(ANI_LOGDUMP) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c new file mode 100644 index 000000000000..cbc3acf3a404 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c @@ -0,0 +1,19681 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrApiRoam.c + + Implementation for the Common Roaming interfaces. +========================================================================== */ +/*=========================================================================== + EDIT HISTORY FOR FILE + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + when who what, where, why +---------- --- -------------------------------------------------------- +06/03/10 js Added support to hostapd driven + * deauth/disassoc/mic failure +===========================================================================*/ +#include "aniGlobal.h" //for tpAniSirGlobal +#include "wlan_qct_wda.h" +#include "halMsgApi.h" //for HAL_STA_INVALID_IDX. +#include "limUtils.h" +#include "palApi.h" +#include "csrInsideApi.h" +#include "smsDebug.h" +#include "logDump.h" +#include "smeQosInternal.h" +#include "wlan_qct_tl.h" +#include "smeInside.h" +#include "vos_diag_core_event.h" +#include "vos_diag_core_log.h" +#include "csrApi.h" +#include "pmc.h" +#include "vos_nvitem.h" +#include "macTrace.h" +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "csrNeighborRoam.h" +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "csrEse.h" +#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ +#include "regdomain_common.h" +#include "vos_utils.h" + +#define CSR_NUM_IBSS_START_CHANNELS_50 4 +#define CSR_NUM_IBSS_START_CHANNELS_24 3 +/* 15 seconds, for WPA, WPA2, CCKM */ +#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD (15 * VOS_TIMER_TO_SEC_UNIT) +/* 120 seconds, for WPS */ +#define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD (120 * VOS_TIMER_TO_SEC_UNIT) +/*--------------------------------------------------------------------------- + OBIWAN recommends [8 10]% : pick 9% +---------------------------------------------------------------------------*/ +#define CSR_VCC_UL_MAC_LOSS_THRESHOLD 9 +/*--------------------------------------------------------------------------- + OBIWAN recommends -85dBm +---------------------------------------------------------------------------*/ +#define CSR_VCC_RSSI_THRESHOLD 80 +#define CSR_MIN_GLOBAL_STAT_QUERY_PERIOD 500 //ms +#define CSR_MIN_GLOBAL_STAT_QUERY_PERIOD_IN_BMPS 2000 //ms +#define CSR_MIN_TL_STAT_QUERY_PERIOD 500 //ms + +//Flag to send/do not send disassoc frame over the air +#define CSR_DONT_SEND_DISASSOC_OVER_THE_AIR 1 +#define RSSI_HACK_BMPS (-40) +#define MAX_CB_VALUE_IN_INI (2) + +#define MAX_SOCIAL_CHANNELS 3 + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static tANI_BOOLEAN bRoamScanOffloadStarted = VOS_FALSE; +#endif + +/*-------------------------------------------------------------------------- + Static Type declarations + ------------------------------------------------------------------------*/ +static tCsrRoamSession csrRoamRoamSession[CSR_ROAM_SESSION_MAX]; + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +int diagAuthTypeFromCSRType(eCsrAuthType authType) +{ + int n = AUTH_OPEN; + switch(authType) + { + case eCSR_AUTH_TYPE_SHARED_KEY: + n = AUTH_SHARED; + break; + case eCSR_AUTH_TYPE_WPA: + n = AUTH_WPA_EAP; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + n = AUTH_WPA_PSK; + break; + case eCSR_AUTH_TYPE_RSN: +#ifdef WLAN_FEATURE_11W + case eCSR_AUTH_TYPE_RSN_8021X_SHA256: +#endif + n = AUTH_WPA2_EAP; + break; + case eCSR_AUTH_TYPE_RSN_PSK: +#ifdef WLAN_FEATURE_11W + case eCSR_AUTH_TYPE_RSN_PSK_SHA256: +#endif + n = AUTH_WPA2_PSK; + break; +#ifdef FEATURE_WLAN_WAPI + case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE: + n = AUTH_WAPI_CERT; + break; + case eCSR_AUTH_TYPE_WAPI_WAI_PSK: + n = AUTH_WAPI_PSK; + break; +#endif /* FEATURE_WLAN_WAPI */ + default: + break; + } + return (n); +} +int diagEncTypeFromCSRType(eCsrEncryptionType encType) +{ + int n = ENC_MODE_OPEN; + switch(encType) + { + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + n = ENC_MODE_WEP40; + break; + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104: + n = ENC_MODE_WEP104; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + n = ENC_MODE_TKIP; + break; + case eCSR_ENCRYPT_TYPE_AES: + n = ENC_MODE_AES; + break; +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + n = ENC_MODE_SMS4; + break; +#endif /* FEATURE_WLAN_WAPI */ + default: + break; + } + return (n); +} +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static const tANI_U8 csrStartIbssChannels50[ CSR_NUM_IBSS_START_CHANNELS_50 ] = { 36, 40, 44, 48}; +static const tANI_U8 csrStartIbssChannels24[ CSR_NUM_IBSS_START_CHANNELS_24 ] = { 1, 6, 11 }; +static void initConfigParam(tpAniSirGlobal pMac); +static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrRoamCompleteResult Result, void *Context ); +static eHalStatus csrRoamStartIbss( tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamProfile *pProfile, + tANI_BOOLEAN *pfSameIbss ); +static void csrRoamUpdateConnectedProfileFromNewBss( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirSmeNewBssInfo *pNewBss ); +static void csrRoamPrepareBssParams(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig, tDot11fBeaconIEs *pIes); +static ePhyChanBondState csrGetCBModeFromIes(tpAniSirGlobal pMac, tANI_U8 primaryChn, tDot11fBeaconIEs *pIes); +eHalStatus csrInitGetChannels(tpAniSirGlobal pMac); +static void csrRoamingStateConfigCnfProcessor( tpAniSirGlobal pMac, tANI_U32 result ); +eHalStatus csrRoamOpen(tpAniSirGlobal pMac); +eHalStatus csrRoamClose(tpAniSirGlobal pMac); +void csrRoamMICErrorTimerHandler(void *pv); +void csrRoamTKIPCounterMeasureTimerHandler(void *pv); +tANI_BOOLEAN csrRoamIsSameProfileKeys(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pConnProfile, tCsrRoamProfile *pProfile2); + +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, + tANI_U8 keyId, tANI_U8 keyLength, tANI_U8 *pKey, tANI_U8 paeRole, + tANI_U8 *pKeyRsc ); +static eHalStatus csrRoamIssueReassociate( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, + 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); +static void csrRoamLinkDown(tpAniSirGlobal pMac, tANI_U32 sessionId); +void csrRoamVccTrigger(tpAniSirGlobal pMac); +eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, + tANI_U8 staId, tANI_U8 sessionId); +/* + pStaEntry is no longer invalid upon the return of this function. +*/ +static void csrRoamRemoveStatListEntry(tpAniSirGlobal pMac, tListElem *pEntry); +static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,tANI_U8 operationChn, eCsrBand *pBand ); +static eHalStatus csrRoamGetQosInfoFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc); +tCsrStatsClientReqInfo * csrRoamInsertEntryIntoList( tpAniSirGlobal pMac, + tDblLinkList *pStaList, + tCsrStatsClientReqInfo *pStaEntry); +void csrRoamStatsClientTimerHandler(void *pv); +tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask, + tANI_U32 periodicity, + tANI_BOOLEAN *pFound, + tANI_U8 staId, + tANI_U8 sessionId); +void csrRoamReportStatistics(tpAniSirGlobal pMac, tANI_U32 statsMask, + tCsrStatsCallback callback, tANI_U8 staId, void *pContext); +void csrRoamSaveStatsFromTl(tpAniSirGlobal pMac, WLANTL_TRANSFER_STA_TYPE *pTlStats); +void csrRoamTlStatsTimerHandler(void *pv); +void csrRoamPeStatsTimerHandler(void *pv); +tListElem * csrRoamCheckClientReqList(tpAniSirGlobal pMac, tANI_U32 statsMask); +void csrRoamRemoveEntryFromPeStatsReqList(tpAniSirGlobal pMac, tCsrPeStatsReqInfo *pPeStaEntry); +tListElem * csrRoamFindInPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask); +eHalStatus csrRoamDeregStatisticsReq(tpAniSirGlobal pMac); +static tANI_U32 csrFindIbssSession( tpAniSirGlobal pMac ); +static uint32_t csr_find_sap_session(tpAniSirGlobal pMac); +static uint32_t csr_find_p2pgo_session(tpAniSirGlobal pMac); +static bool csr_is_conn_allow_2g_band(tpAniSirGlobal pMac, uint32_t chnl); +static bool csr_is_conn_allow_5g_band(tpAniSirGlobal pMac, uint32_t chnl); +static eHalStatus csrRoamStartWds( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc ); +static void csrInitSession( tpAniSirGlobal pMac, tANI_U32 sessionId ); +static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamSetKey *pSetKey, tANI_U32 roamId ); +static eHalStatus csrRoamGetQosInfoFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc); +void csrRoamReissueRoamCommand(tpAniSirGlobal pMac); +extern void SysProcessMmhMsg(tpAniSirGlobal pMac, tSirMsgQ* pMsg); +static void csrSerDesUnpackDiassocRsp(tANI_U8 *pBuf, tSirSmeDisassocRsp *pRsp); +void csrReinitPreauthCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrInitOperatingClasses(tHalHandle hHal); + +//Initialize global variables +static void csrRoamInitGlobals(tpAniSirGlobal pMac) +{ + if(pMac) + { + vos_mem_zero(&csrRoamRoamSession, sizeof(csrRoamRoamSession)); + pMac->roam.roamSession = csrRoamRoamSession; + } + return; +} + +static void csrRoamDeInitGlobals(tpAniSirGlobal pMac) +{ + if(pMac) + { + pMac->roam.roamSession = NULL; + } + return; +} +eHalStatus csrOpen(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 i; + + do + { + /* Initialize CSR Roam Globals */ + csrRoamInitGlobals(pMac); + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_STOP, i); + + initConfigParam(pMac); + if(!HAL_STATUS_SUCCESS((status = csrScanOpen(pMac)))) + break; + if(!HAL_STATUS_SUCCESS((status = csrRoamOpen(pMac)))) + break; + pMac->roam.nextRoamId = 1; //Must not be 0 + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &pMac->roam.statsClientReqList))) + break; + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &pMac->roam.peStatsReqList))) + break; + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &pMac->roam.roamCmdPendingList))) + break; + }while(0); + + return (status); +} + +eHalStatus csr_init_chan_list(tpAniSirGlobal mac, v_U8_t *alpha2) +{ + eHalStatus status; + v_REGDOMAIN_t reg_id; + v_CountryInfoSource_t source = COUNTRY_INIT; + + mac->scan.countryCodeDefault[0] = alpha2[0]; + mac->scan.countryCodeDefault[1] = alpha2[1]; + mac->scan.countryCodeDefault[2] = alpha2[2]; + + smsLog(mac, LOGE, FL("init time country code %.2s"), + mac->scan.countryCodeDefault); + + status = csrGetRegulatoryDomainForCountry(mac, + mac->scan.countryCodeDefault, + ®_id, source); + if (status != eHAL_STATUS_SUCCESS) + { + smsLog(mac, LOGE, FL("csrGetRegulatoryDomainForCountry failed")); + return status; + } + + if (vos_nv_setRegDomain(mac, reg_id, FALSE) != VOS_STATUS_SUCCESS) + { + smsLog(mac, LOGE, FL("vos_nv_setRegDomain failed")); + return eHAL_STATUS_FAILURE; + } + mac->scan.domainIdDefault = reg_id; + mac->scan.domainIdCurrent = mac->scan.domainIdDefault; + vos_mem_copy(mac->scan.countryCodeCurrent, + mac->scan.countryCodeDefault, + WNI_CFG_COUNTRY_CODE_LEN); + vos_mem_copy(mac->scan.countryCodeElected, + mac->scan.countryCodeDefault, + WNI_CFG_COUNTRY_CODE_LEN); + status = csrInitGetChannels(mac); + csrClearVotesForCountryInfo(mac); + return status; +} + +eHalStatus csrSetRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + v_REGDOMAIN_t regId; + v_U8_t cntryCodeLength; + if(NULL == apCntryCode) + { + smsLog( pMac, LOGE, FL(" Invalid country Code Pointer") ); + return eHAL_STATUS_FAILURE; + } + smsLog( pMac, LOG1, FL(" country Code %.2s"), apCntryCode ); + /* + * To get correct Regulatory domain from NV table + * 2 character Country code should be used + * 3rd character is optional for indoor/outdoor setting + */ + cntryCodeLength = WNI_CFG_COUNTRY_CODE_LEN; + status = csrGetRegulatoryDomainForCountry(pMac, apCntryCode, ®Id, + COUNTRY_USER); + if (status != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, FL(" fail to get regId for country Code %.2s"), apCntryCode ); + return status; + } + status = WDA_SetRegDomain(hHal, regId, eSIR_TRUE); + if (status != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, FL(" fail to get regId for country Code %.2s"), apCntryCode ); + return status; + } + pMac->scan.domainIdDefault = regId; + pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault; + /* Clear CC field */ + vos_mem_set(pMac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN, 0); + + /* Copy 2 or 3 bytes country code */ + vos_mem_copy(pMac->scan.countryCodeDefault, apCntryCode, cntryCodeLength); + + /* If 2 bytes country code, 3rd byte must be filled with space */ + if((WNI_CFG_COUNTRY_CODE_LEN - 1) == cntryCodeLength) + { + vos_mem_set(pMac->scan.countryCodeDefault + 2, 1, 0x20); + } + vos_mem_copy(pMac->scan.countryCodeCurrent, pMac->scan.countryCodeDefault, + WNI_CFG_COUNTRY_CODE_LEN); + status = csrInitGetChannels( pMac ); + return status; +} +eHalStatus csrSetChannels(tHalHandle hHal, tCsrConfigParam *pParam ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U8 index = 0; + vos_mem_copy(pParam->Csr11dinfo.countryCode, pMac->scan.countryCodeCurrent, + WNI_CFG_COUNTRY_CODE_LEN); + for ( index = 0; index < pMac->scan.base20MHzChannels.numChannels ; index++) + { + pParam->Csr11dinfo.Channels.channelList[index] = pMac->scan.base20MHzChannels.channelList[ index ]; + pParam->Csr11dinfo.ChnPower[index].firstChannel = pMac->scan.base20MHzChannels.channelList[ index ]; + pParam->Csr11dinfo.ChnPower[index].numChannels = 1; + pParam->Csr11dinfo.ChnPower[index].maxtxPower = pMac->scan.defaultPowerTable[index].pwr; + } + pParam->Csr11dinfo.Channels.numChannels = pMac->scan.base20MHzChannels.numChannels; + + return status; +} +eHalStatus csrClose(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + csrRoamClose(pMac); + csrScanClose(pMac); + csrLLClose(&pMac->roam.statsClientReqList); + csrLLClose(&pMac->roam.peStatsReqList); + csrLLClose(&pMac->roam.roamCmdPendingList); + /* DeInit Globals */ + csrRoamDeInitGlobals(pMac); + return (status); +} + +static tChannelPwrLimit csrFindChannelPwr(tChannelListWithPower * pdefaultPowerTable, + tANI_U8 ChannelNum) +{ + tANI_U8 i; + // TODO: if defaultPowerTable is guaranteed to be in ascending + // order of channel numbers, we can employ binary search + for (i = 0; i < WNI_CFG_VALID_CHANNEL_LIST_LEN; i++) + { + if (pdefaultPowerTable[i].chanId == ChannelNum) + return pdefaultPowerTable[i].pwr; + } + /* Could not find the channel list in default list + this should not have occurred */ + VOS_ASSERT(0); + return 0; +} + +eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) +{ + tSirUpdateChanList *pChanList; + tCsrScanStruct *pScan = &pMac->scan; + tANI_U8 numChan = pScan->base20MHzChannels.numChannels; + tANI_U8 num_channel = 0; + tANI_U32 bufLen; + vos_msg_t msg; + tANI_U8 i, j, social_channel[MAX_SOCIAL_CHANNELS] = {1,6,11}; + tANI_U8 channel_state; + + if (CSR_IS_5G_BAND_ONLY(pMac)) + { + for (i = 0; i < MAX_SOCIAL_CHANNELS; i++) + { + /* Scan is not performed on DSRC channels*/ + if (pScan->baseChannels.channelList[i] >= MIN_11P_CHANNEL) + continue; + if (vos_nv_getChannelEnabledState(social_channel[i]) + == NV_CHANNEL_ENABLE) + numChan++; + } + } + + bufLen = sizeof(tSirUpdateChanList) + + (sizeof(tSirUpdateChanParam) * (numChan)); + + csrInitOperatingClasses((tHalHandle)pMac); + pChanList = (tSirUpdateChanList *) vos_mem_malloc(bufLen); + if (!pChanList) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate memory for tSirUpdateChanList"); + return eHAL_STATUS_FAILED_ALLOC; + } + vos_mem_zero(pChanList, bufLen); + + for (i = 0; i < pScan->base20MHzChannels.numChannels; i++) + { + if (pScan->fcc_constraint) { + if (pScan->base20MHzChannels.channelList[i] == 12) + continue; + if (pScan->base20MHzChannels.channelList[i] == 13) + continue; + } + channel_state = + vos_nv_getChannelEnabledState( + pScan->base20MHzChannels.channelList[i]); + if ((NV_CHANNEL_ENABLE == channel_state) || + pMac->scan.fEnableDFSChnlScan) + { + pChanList->chanParam[num_channel].chanId = + pScan->base20MHzChannels.channelList[i]; + pChanList->chanParam[num_channel].pwr = + csrFindChannelPwr(pScan->defaultPowerTable, + pChanList->chanParam[num_channel].chanId); + if (NV_CHANNEL_ENABLE == channel_state) + pChanList->chanParam[num_channel].dfsSet = VOS_FALSE; + else + pChanList->chanParam[num_channel].dfsSet = VOS_TRUE; + num_channel++; + } + } + + + if (CSR_IS_5G_BAND_ONLY(pMac)) + { + for (j = 0; j < MAX_SOCIAL_CHANNELS; j++) + { + if (vos_nv_getChannelEnabledState(social_channel[j]) + == NV_CHANNEL_ENABLE) + { + pChanList->chanParam[num_channel].chanId = social_channel[j]; + pChanList->chanParam[num_channel].pwr = + csrFindChannelPwr(pScan->defaultPowerTable, + social_channel[j]); + pChanList->chanParam[num_channel].dfsSet = VOS_FALSE; + num_channel++; + } + } + } + + if ((pMac->roam.configParam.uCfgDot11Mode == eCSR_CFG_DOT11_MODE_AUTO) || + (pMac->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11AC) || + (pMac->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11AC_ONLY)) { + pChanList->vht_en = true; + if (pMac->roam.configParam.enableVhtFor24GHz) + pChanList->vht_24_en = true; + } + if ((pMac->roam.configParam.uCfgDot11Mode == eCSR_CFG_DOT11_MODE_AUTO) || + (pMac->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11N) || + (pMac->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11N_ONLY)) { + pChanList->ht_en = true; + } + msg.type = WDA_UPDATE_CHAN_LIST_REQ; + msg.reserved = 0; + msg.bodyptr = pChanList; + pChanList->numChan = num_channel; + + 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; + } + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrStart(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 i; + + do + { + //save the global vos context + pMac->roam.gVosContext = vos_get_global_context(VOS_MODULE_ID_SME, pMac); + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, i ); + + status = csrRoamStart(pMac); + if(!HAL_STATUS_SUCCESS(status)) break; + pMac->scan.f11dInfoApplied = eANI_BOOLEAN_FALSE; + + if(!pMac->psOffloadEnabled) + { + status = pmcRegisterPowerSaveCheck(pMac, csrCheckPSReady, pMac); + if(!HAL_STATUS_SUCCESS(status)) break; + } + else + { + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + status = pmcOffloadRegisterPowerSaveCheck(pMac, i, + csrCheckPSOffloadReady, pMac); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + "csrStart: Register Power Check Failed Session Id %x", i); + return status; + } + } + } + pMac->roam.sPendingCommands = 0; + csrScanEnable(pMac); +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) + status = csrNeighborRoamInit(pMac, i); +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ + pMac->roam.tlStatsReqInfo.numClient = 0; + pMac->roam.tlStatsReqInfo.periodicity = 0; + pMac->roam.tlStatsReqInfo.timerRunning = FALSE; + //init the link quality indication also + pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_MIN_IND; + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, " csrStart: Couldn't Init HO control blk "); + break; + } + + if (pMac->fScanOffload) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Scan offload is enabled, update default chan list"); + status = csrUpdateChannelList(pMac); + } + + }while(0); +#if defined(ANI_LOGDUMP) + csrDumpInit(pMac); +#endif //#if defined(ANI_LOGDUMP) + return (status); +} + +eHalStatus csrStop(tpAniSirGlobal pMac, tHalStopType stopType) +{ + tANI_U32 sessionId; + + for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + { + csrRoamCloseSession(pMac, sessionId, TRUE, NULL, NULL); + } + csrScanDisable(pMac); + pMac->scan.fCancelIdleScan = eANI_BOOLEAN_FALSE; + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE; + csrLLPurge( &pMac->roam.roamCmdPendingList, eANI_BOOLEAN_TRUE ); + +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + csrNeighborRoamClose(pMac, sessionId); +#endif + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + if (CSR_IS_SESSION_VALID(pMac, sessionId)) + csrScanFlushResult(pMac, sessionId); + + // deregister from PMC since we register during csrStart() + // (ignore status since there is nothing we can do if it fails) + if(!pMac->psOffloadEnabled) + { + (void) pmcDeregisterPowerSaveCheck(pMac, csrCheckPSReady); + } + else + { + for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + { + pmcOffloadDeregisterPowerSaveCheck(pMac, sessionId, + csrCheckPSOffloadReady); + } + } + + /* Reset the domain back to the default */ + pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + csrRoamStateChange(pMac, eCSR_ROAMING_STATE_STOP, sessionId); + pMac->roam.curSubState[sessionId] = eCSR_ROAM_SUBSTATE_NONE; + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* When HAL resets all the context information + * in HAL is lost, so we might need to send the + * scan offload request again when it comes + * out of reset for scan offload to be functional + */ + if (HAL_STOP_TYPE_SYS_RESET == stopType) + { + bRoamScanOffloadStarted = VOS_FALSE; + } +#endif + + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus csrReady(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + csrScanGetSupportedChannels( pMac ); + //WNI_CFG_VALID_CHANNEL_LIST should be set by this time + //use it to init the background scan list + csrInitBGScanChannelList(pMac); + status = csrInitChannelList( pMac ); + if ( ! HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, "csrInitChannelList failed during csrReady with status=%d", + status ); + } + return (status); +} +void csrSetDefaultDot11Mode( tpAniSirGlobal pMac ) +{ + v_U32_t wniDot11mode = 0; + wniDot11mode = csrTranslateToWNICfgDot11Mode(pMac,pMac->roam.configParam.uCfgDot11Mode); + ccmCfgSetInt(pMac, WNI_CFG_DOT11_MODE, wniDot11mode, NULL, eANI_BOOLEAN_FALSE); +} +void csrSetGlobalCfgs( tpAniSirGlobal pMac ) +{ + + ccmCfgSetInt(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, csrGetFragThresh(pMac), NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_RTS_THRESHOLD, csrGetRTSThresh(pMac), NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_11D_ENABLED, + ((pMac->roam.configParam.Is11hSupportEnabled) ? pMac->roam.configParam.Is11dSupportEnabled : pMac->roam.configParam.Is11dSupportEnabled), + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_11H_ENABLED, pMac->roam.configParam.Is11hSupportEnabled, NULL, eANI_BOOLEAN_FALSE); + /* For now we will just use the 5GHz CB mode ini parameter to decide whether CB supported or not in Probes when there is no session + * Once session is established we will use the session related params stored in PE session for CB mode + */ + ccmCfgSetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, !!(pMac->roam.configParam.channelBondingMode5GHz), NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->roam.configParam.HeartbeatThresh24, NULL, eANI_BOOLEAN_FALSE); + + //Update the operating mode to configured value during initialization, + //So that client can advertise full capabilities in Probe request frame. + csrSetDefaultDot11Mode( pMac ); +} + +eHalStatus csrRoamOpen(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 i; + tCsrRoamSession *pSession; + do + { + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + pSession = CSR_GET_SESSION( pMac, i ); + pSession->roamingTimerInfo.pMac = pMac; + pSession->roamingTimerInfo.sessionId = CSR_SESSION_ID_INVALID; + } + pMac->roam.WaitForKeyTimerInfo.pMac = pMac; + pMac->roam.WaitForKeyTimerInfo.sessionId = CSR_SESSION_ID_INVALID; + status = vos_timer_init(&pMac->roam.hTimerWaitForKey, VOS_TIMER_TYPE_SW, + csrRoamWaitForKeyTimeOutHandler, + &pMac->roam.WaitForKeyTimerInfo); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("cannot allocate memory for WaitForKey time out timer")); + break; + } + status = vos_timer_init(&pMac->roam.tlStatsReqInfo.hTlStatsTimer, + VOS_TIMER_TYPE_SW, csrRoamTlStatsTimerHandler, pMac); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("cannot allocate memory for summary Statistics timer")); + return eHAL_STATUS_FAILURE; + } + }while (0); + return (status); +} + +eHalStatus csrRoamClose(tpAniSirGlobal pMac) +{ + tANI_U32 sessionId; + for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + { + csrRoamCloseSession(pMac, sessionId, TRUE, NULL, NULL); + } + vos_timer_stop(&pMac->roam.hTimerWaitForKey); + vos_timer_destroy(&pMac->roam.hTimerWaitForKey); + vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer); + vos_timer_destroy(&pMac->roam.tlStatsReqInfo.hTlStatsTimer); + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus csrRoamStart(tpAniSirGlobal pMac) +{ + (void)pMac; + return (eHAL_STATUS_SUCCESS); +} + +void csrRoamStop(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + csrRoamStopRoamingTimer(pMac, sessionId); + /* deregister the clients requesting stats from PE/TL & also stop the corresponding timers*/ + csrRoamDeregStatisticsReq(pMac); +} +eHalStatus csrRoamGetConnectState(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrConnectState *pState) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + if ( CSR_IS_SESSION_VALID(pMac, sessionId) && (NULL != pState) ) + { + status = eHAL_STATUS_SUCCESS; + *pState = pMac->roam.roamSession[sessionId].connectState; + } + return (status); +} + +eHalStatus csrRoamCopyConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamConnectedProfile *pProfile) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_U32 size = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pProfile) + { + if(pSession->pConnectBssDesc) + { + do + { + size = pSession->pConnectBssDesc->length + sizeof(pSession->pConnectBssDesc->length); + if(size) + { + pProfile->pBssDesc = vos_mem_malloc(size); + if ( NULL != pProfile->pBssDesc ) + { + vos_mem_copy(pProfile->pBssDesc, + pSession->pConnectBssDesc, size); + status = eHAL_STATUS_SUCCESS; + } + else + break; + } + else + { + pProfile->pBssDesc = NULL; + } + pProfile->AuthType = pSession->connectedProfile.AuthType; + pProfile->EncryptionType = pSession->connectedProfile.EncryptionType; + pProfile->mcEncryptionType = pSession->connectedProfile.mcEncryptionType; + pProfile->BSSType = pSession->connectedProfile.BSSType; + pProfile->operationChannel = pSession->connectedProfile.operationChannel; + pProfile->CBMode = pSession->connectedProfile.CBMode; + vos_mem_copy(&pProfile->bssid, &pSession->connectedProfile.bssid, + sizeof(tCsrBssid)); + vos_mem_copy(&pProfile->SSID, &pSession->connectedProfile.SSID, + sizeof(tSirMacSSid)); +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSession->connectedProfile.MDID.mdiePresent) + { + pProfile->MDID.mdiePresent = 1; + pProfile->MDID.mobilityDomain = pSession->connectedProfile.MDID.mobilityDomain; + } + else + { + pProfile->MDID.mdiePresent = 0; + pProfile->MDID.mobilityDomain = 0; + } +#endif +#ifdef FEATURE_WLAN_ESE + pProfile->isESEAssoc = pSession->connectedProfile.isESEAssoc; + if (csrIsAuthTypeESE(pSession->connectedProfile.AuthType)) + { + vos_mem_copy (pProfile->eseCckmInfo.krk, + pSession->connectedProfile.eseCckmInfo.krk, + SIR_KRK_KEY_LEN); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + vos_mem_copy (pProfile->eseCckmInfo.btk, + pSession->connectedProfile.eseCckmInfo.btk, + SIR_BTK_KEY_LEN); +#endif + pProfile->eseCckmInfo.reassoc_req_num= + pSession->connectedProfile.eseCckmInfo.reassoc_req_num; + pProfile->eseCckmInfo.krk_plumbed = + pSession->connectedProfile.eseCckmInfo.krk_plumbed; + } +#endif + }while(0); + } + } + + return (status); +} + +eHalStatus csrRoamGetConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamConnectedProfile *pProfile) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + + if((csrIsConnStateConnected(pMac, sessionId)) || + (csrIsConnStateIbss(pMac, sessionId))) + { + if(pProfile) + { + status = csrRoamCopyConnectProfile(pMac, sessionId, pProfile); + } + } + return (status); +} + +eHalStatus csrRoamFreeConnectProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + if (pProfile->pBssDesc) + { + vos_mem_free(pProfile->pBssDesc); + } + if (pProfile->pAddIEAssoc) + { + vos_mem_free(pProfile->pAddIEAssoc); + } + vos_mem_set(pProfile, sizeof(tCsrRoamConnectedProfile), 0); + + pProfile->AuthType = eCSR_AUTH_TYPE_UNKNOWN; + return (status); +} + +static eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + if( pConnectedInfo->pbFrames ) + { + vos_mem_free(pConnectedInfo->pbFrames); + pConnectedInfo->pbFrames = NULL; + } + pConnectedInfo->nBeaconLength = 0; + pConnectedInfo->nAssocReqLength = 0; + pConnectedInfo->nAssocRspLength = 0; + pConnectedInfo->staId = 0; +#ifdef WLAN_FEATURE_VOWIFI_11R + pConnectedInfo->nRICRspLength = 0; +#endif +#ifdef FEATURE_WLAN_ESE + pConnectedInfo->nTspecIeLength = 0; +#endif + return ( status ); +} + + + + +void csrReleaseCommandPreauth(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csrReinitPreauthCmd(pMac, pCommand); + csrReleaseCommand( pMac, pCommand ); +} + +void csrReleaseCommandRoam(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csrReinitRoamCmd(pMac, pCommand); + csrReleaseCommand( pMac, pCommand ); +} + +void csrReleaseCommandScan(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csrReinitScanCmd(pMac, pCommand); + csrReleaseCommand( pMac, pCommand ); +} + +void csrReleaseCommandWmStatusChange(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csrReinitWmStatusChangeCmd(pMac, pCommand); + csrReleaseCommand( pMac, pCommand ); +} + +void csrReinitSetKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + vos_mem_set(&pCommand->u.setKeyCmd, sizeof(tSetKeyCmd), 0); +} + +void csrReinitRemoveKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + vos_mem_set(&pCommand->u.removeKeyCmd, sizeof(tRemoveKeyCmd), 0); +} + +void csrReleaseCommandSetKey(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csrReinitSetKeyCmd(pMac, pCommand); + csrReleaseCommand( pMac, pCommand ); +} +void csrReleaseCommandRemoveKey(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csrReinitRemoveKeyCmd(pMac, pCommand); + csrReleaseCommand( pMac, pCommand ); +} +void csrAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping ) +{ + + if( eSmeCsrCommandMask & pCommand->command ) + { + switch (pCommand->command) + { + case eSmeCommandScan: + // We need to inform the requester before dropping the scan command + smsLog( pMac, LOGW, "%s: Drop scan reason %d callback %p", + __func__, pCommand->u.scanCmd.reason, + pCommand->u.scanCmd.callback); + if (NULL != pCommand->u.scanCmd.callback) + { + smsLog( pMac, LOGW, "%s callback scan requester", __func__); + csrScanCallCallback(pMac, pCommand, eCSR_SCAN_ABORT); + } + csrReleaseCommandScan( pMac, pCommand ); + break; + case eSmeCommandRoam: + csrReleaseCommandRoam( pMac, pCommand ); + break; + + case eSmeCommandWmStatusChange: + csrReleaseCommandWmStatusChange( pMac, pCommand ); + break; + + case eSmeCommandSetKey: + csrReleaseCommandSetKey( pMac, pCommand ); + break; + + case eSmeCommandRemoveKey: + csrReleaseCommandRemoveKey( pMac, pCommand ); + break; + + default: + smsLog( pMac, LOGW, " CSR abort standard command %d", pCommand->command ); + csrReleaseCommand( pMac, pCommand ); + break; + } + } +} + +void csrRoamSubstateChange( tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate, tANI_U32 sessionId) +{ + smsLog(pMac, LOG1, FL("CSR RoamSubstate: [ %s <== %s ]"), + macTraceGetcsrRoamSubState(NewSubstate), + macTraceGetcsrRoamSubState(pMac->roam.curSubState[sessionId])); + if(pMac->roam.curSubState[sessionId] == NewSubstate) + { + return; + } + pMac->roam.curSubState[sessionId] = NewSubstate; +} + +eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId) +{ + eCsrRoamState PreviousState; + + smsLog(pMac, LOG1, FL("CSR RoamState[%hu]: [ %s <== %s ]"), sessionId, + macTraceGetcsrRoamState(NewRoamState), + macTraceGetcsrRoamState(pMac->roam.curState[sessionId])); + PreviousState = pMac->roam.curState[sessionId]; + + if ( NewRoamState != pMac->roam.curState[sessionId] ) + { + // Whenever we transition OUT of the Roaming state, clear the Roaming substate... + if ( CSR_IS_ROAM_JOINING(pMac, sessionId) ) + { + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId ); + } + + pMac->roam.curState[sessionId] = NewRoamState; + } + return( PreviousState ); +} + +void csrAssignRssiForCategory(tpAniSirGlobal pMac, tANI_S8 bestApRssi, tANI_U8 catOffset) +{ + int i; + + smsLog(pMac, LOG2, FL("best AP RSSI:%d, cat offset:%d"), bestApRssi, + catOffset); + if(catOffset) + { + pMac->roam.configParam.bCatRssiOffset = catOffset; + for(i = 0; i < CSR_NUM_RSSI_CAT; i++) + { + pMac->roam.configParam.RSSICat[CSR_NUM_RSSI_CAT - i - 1] = (int)bestApRssi - pMac->roam.configParam.nSelect5GHzMargin - (int)(i * catOffset); + } + } +} + +static void initConfigParam(tpAniSirGlobal pMac) +{ + int i; + pMac->roam.configParam.agingCount = CSR_AGING_COUNT; + pMac->roam.configParam.channelBondingMode24GHz = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + pMac->roam.configParam.channelBondingMode5GHz = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + + pMac->roam.configParam.phyMode = eCSR_DOT11_MODE_AUTO; + pMac->roam.configParam.eBand = eCSR_BAND_ALL; + pMac->roam.configParam.uCfgDot11Mode = eCSR_CFG_DOT11_MODE_AUTO; + pMac->roam.configParam.FragmentationThreshold = eCSR_DOT11_FRAG_THRESH_DEFAULT; + pMac->roam.configParam.HeartbeatThresh24 = 40; + pMac->roam.configParam.HeartbeatThresh50 = 40; + pMac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE; + pMac->roam.configParam.Is11dSupportEnabledOriginal = eANI_BOOLEAN_FALSE; + pMac->roam.configParam.Is11eSupportEnabled = eANI_BOOLEAN_TRUE; + pMac->roam.configParam.Is11hSupportEnabled = eANI_BOOLEAN_TRUE; + pMac->roam.configParam.RTSThreshold = 2346; + pMac->roam.configParam.shortSlotTime = eANI_BOOLEAN_TRUE; + pMac->roam.configParam.WMMSupportMode = eCsrRoamWmmAuto; + pMac->roam.configParam.ProprietaryRatesEnabled = eANI_BOOLEAN_TRUE; + pMac->roam.configParam.TxRate = eCSR_TX_RATE_AUTO; + pMac->roam.configParam.impsSleepTime = CSR_IDLE_SCAN_NO_PS_INTERVAL; + pMac->roam.configParam.scanAgeTimeNCNPS = CSR_SCAN_AGING_TIME_NOT_CONNECT_NO_PS; + pMac->roam.configParam.scanAgeTimeNCPS = CSR_SCAN_AGING_TIME_NOT_CONNECT_W_PS; + pMac->roam.configParam.scanAgeTimeCNPS = CSR_SCAN_AGING_TIME_CONNECT_NO_PS; + pMac->roam.configParam.scanAgeTimeCPS = CSR_SCAN_AGING_TIME_CONNECT_W_PS; + for(i = 0; i < CSR_NUM_RSSI_CAT; i++) + { + pMac->roam.configParam.BssPreferValue[i] = i; + } + csrAssignRssiForCategory(pMac, CSR_BEST_RSSI_VALUE, CSR_DEFAULT_RSSI_DB_GAP); + pMac->roam.configParam.nRoamingTime = CSR_DEFAULT_ROAMING_TIME; + pMac->roam.configParam.fEnforce11dChannels = eANI_BOOLEAN_FALSE; + pMac->roam.configParam.fSupplicantCountryCodeHasPriority = eANI_BOOLEAN_FALSE; + pMac->roam.configParam.fEnforceCountryCodeMatch = eANI_BOOLEAN_FALSE; + pMac->roam.configParam.fEnforceDefaultDomain = eANI_BOOLEAN_FALSE; + pMac->roam.configParam.nActiveMaxChnTime = CSR_ACTIVE_MAX_CHANNEL_TIME; + pMac->roam.configParam.nActiveMinChnTime = CSR_ACTIVE_MIN_CHANNEL_TIME; + pMac->roam.configParam.nPassiveMaxChnTime = CSR_PASSIVE_MAX_CHANNEL_TIME; + pMac->roam.configParam.nPassiveMinChnTime = CSR_PASSIVE_MIN_CHANNEL_TIME; + pMac->roam.configParam.nActiveMaxChnTimeBtc = CSR_ACTIVE_MAX_CHANNEL_TIME_BTC; + pMac->roam.configParam.nActiveMinChnTimeBtc = CSR_ACTIVE_MIN_CHANNEL_TIME_BTC; + pMac->roam.configParam.disableAggWithBtc = eANI_BOOLEAN_TRUE; +#ifdef WLAN_AP_STA_CONCURRENCY + pMac->roam.configParam.nActiveMaxChnTimeConc = CSR_ACTIVE_MAX_CHANNEL_TIME_CONC; + pMac->roam.configParam.nActiveMinChnTimeConc = CSR_ACTIVE_MIN_CHANNEL_TIME_CONC; + pMac->roam.configParam.nPassiveMaxChnTimeConc = CSR_PASSIVE_MAX_CHANNEL_TIME_CONC; + pMac->roam.configParam.nPassiveMinChnTimeConc = CSR_PASSIVE_MIN_CHANNEL_TIME_CONC; + pMac->roam.configParam.nRestTimeConc = CSR_REST_TIME_CONC; + pMac->roam.configParam.min_rest_time_conc = CSR_MIN_REST_TIME_CONC; + pMac->roam.configParam.idle_time_conc = CSR_IDLE_TIME_CONC; + pMac->roam.configParam.nNumStaChanCombinedConc = CSR_NUM_STA_CHAN_COMBINED_CONC; + pMac->roam.configParam.nNumP2PChanCombinedConc = CSR_NUM_P2P_CHAN_COMBINED_CONC; +#endif + pMac->roam.configParam.IsIdleScanEnabled = TRUE; //enable the idle scan by default + pMac->roam.configParam.nTxPowerCap = CSR_MAX_TX_POWER; + pMac->roam.configParam.statsReqPeriodicity = CSR_MIN_GLOBAL_STAT_QUERY_PERIOD; + pMac->roam.configParam.statsReqPeriodicityInPS = CSR_MIN_GLOBAL_STAT_QUERY_PERIOD_IN_BMPS; +#ifdef WLAN_FEATURE_VOWIFI_11R + pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported = 0; +#endif +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries = 3; + pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold = 120; + pMac->roam.configParam.neighborRoamConfig.nOpportunisticThresholdDiff = 30; + pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff = 5; + pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold = 125; + pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime = 20; + pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime = 40; + pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod = 200; + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels = 3; + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[0] = 1; + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[1] = 6; + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[2] = 11; + pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod = 20000; //20 seconds + pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod = 0; + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt = 10; + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt = 10; + pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight = 14; +#endif +#ifdef WLAN_FEATURE_11AC + pMac->roam.configParam.nVhtChannelWidth = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ + 1; +#endif + + pMac->roam.configParam.addTSWhenACMIsOff = 0; + pMac->roam.configParam.fScanTwice = eANI_BOOLEAN_FALSE; + + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + pMac->roam.configParam.doBMPSWorkaround = 0; + + pMac->roam.configParam.nInitialDwellTime = 0; + pMac->roam.configParam.initial_scan_no_dfs_chnl = 0; +} +eCsrBand csrGetCurrentBand(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.bandCapability; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* + This function flushes the roam scan cache +*/ +eHalStatus csrFlushRoamScanRoamChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo + = &pMac->roam.neighborRoamInfo[sessionId]; + /* Free up the memory first (if required) */ + if (NULL != + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList) + { + vos_mem_free( + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList + ); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList + = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels + = 0; + } + return status; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/* + This function flushes the roam scan cache +*/ +eHalStatus csrFlushCfgBgScanRoamChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + /* Free up the memory first (if required) */ + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + { + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0; + } + return status; +} + + + +/* + This function flushes the roam scan cache and creates fresh cache + based on the input channel list +*/ +eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + const tANI_U8 *pChannelList, + const tANI_U8 numChannels) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = numChannels; + + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = + vos_mem_malloc(pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels); + + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + { + smsLog(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed")); + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0; + return eHAL_STATUS_RESOURCES; + } + + /* Update the roam global structure */ + vos_mem_copy(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList, + pChannelList, + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels); + return status; +} + +/* This function modifies the bgscan channel list set via config ini or + runtime, whenever the band changes. + if the band is auto, then no operation is performed on the channel list + if the band is 2.4G, then make sure channel list contains only 2.4G valid channels + if the band is 5G, then make sure channel list contains only 5G valid channels +*/ +eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + eCsrBand eBand) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 outNumChannels = 0; + tANI_U8 inNumChannels = 0; + tANI_U8 *inPtr = NULL; + tANI_U8 i = 0; + tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "No update required for channel list " + "either cfg.ini channel list is not set up or " + "auto band (Band %d)", eBand); + return status; + } + + inNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; + inPtr = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList; + if (eCSR_BAND_24 == eBand) + { + for (i = 0; i < inNumChannels; i++) + { + if (CSR_IS_CHANNEL_24GHZ(inPtr[i]) && csrRoamIsChannelValid(pMac, inPtr[i])) + { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + csrFlushCfgBgScanRoamChannelList(pMac, sessionId); + csrCreateBgScanRoamChannelList(pMac, sessionId, ChannelList, + outNumChannels); + } + else if (eCSR_BAND_5G == eBand) + { + for (i = 0; i < inNumChannels; i++) + { + /* Add 5G Non-DFS channel */ + if (CSR_IS_CHANNEL_5GHZ(inPtr[i]) && + csrRoamIsChannelValid(pMac, inPtr[i]) && + !CSR_IS_CHANNEL_DFS(inPtr[i])) + { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + csrFlushCfgBgScanRoamChannelList(pMac, sessionId); + csrCreateBgScanRoamChannelList(pMac, sessionId, ChannelList, + outNumChannels); + } + else if (eCSR_BAND_ALL == eBand) + { + for (i = 0; i < inNumChannels; i++) + { + if (csrRoamIsChannelValid(pMac, inPtr[i]) && + !CSR_IS_CHANNEL_DFS(inPtr[i])) + { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + csrFlushCfgBgScanRoamChannelList(pMac, sessionId); + csrCreateBgScanRoamChannelList(pMac, sessionId, ChannelList, + outNumChannels); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "Invalid band, No operation carried out (Band %d)", eBand); + status = eHAL_STATUS_INVALID_PARAMETER; + } + + return status; +} +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* + * This function modifies the roam scan channel list as per AP neighbor + * report; AP neighbor report may be empty or may include only other AP + * channels; in any case, we merge the channel list with the learned occupied + * channels list. + * if the band is 2.4G, then make sure channel list contains only 2.4G + * valid channels if the band is 5G, then make sure channel list contains + * only 5G valid channels + */ +eHalStatus csrCreateRoamScanChannelList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tANI_U8 *pChannelList, + tANI_U8 numChannels, + const eCsrBand eBand) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo + = &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 outNumChannels = 0; + tANI_U8 inNumChannels = numChannels; + tANI_U8 *inPtr = pChannelList; + tANI_U8 i = 0; + tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tANI_U8 tmpChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tANI_U8 mergedOutputNumOfChannels = 0; + tpCsrChannelInfo currChannelListInfo + = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + /* + * Create a Union of occupied channel list learnt by the DUT along + * with the Neighbor report Channels. This increases the chances of + * the DUT to get a candidate AP while roaming even if the Neighbor + * Report is not able to provide sufficient information. + */ + if (pMac->scan.occupiedChannels[sessionId].numChannels) + { + csrNeighborRoamMergeChannelLists(pMac, + &pMac->scan.occupiedChannels[sessionId].channelList[0], + pMac->scan.occupiedChannels[sessionId].numChannels, + inPtr, + inNumChannels, + &mergedOutputNumOfChannels); + inNumChannels = mergedOutputNumOfChannels; + } + if (eCSR_BAND_24 == eBand) + { + for (i = 0; i < inNumChannels; i++) + { + if (CSR_IS_CHANNEL_24GHZ(inPtr[i]) + && csrRoamIsChannelValid(pMac, inPtr[i])) + { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + } + else if (eCSR_BAND_5G == eBand) + { + for (i = 0; i < inNumChannels; i++) + { + /* Add 5G Non-DFS channel */ + if (CSR_IS_CHANNEL_5GHZ(inPtr[i]) && + csrRoamIsChannelValid(pMac, inPtr[i]) && + !CSR_IS_CHANNEL_DFS(inPtr[i])) + { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + } + else if (eCSR_BAND_ALL == eBand) + { + for (i = 0; i < inNumChannels; i++) + { + if (csrRoamIsChannelValid(pMac, inPtr[i]) && + !CSR_IS_CHANNEL_DFS(inPtr[i])) + { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "Invalid band, No operation carried out (Band %d)", eBand); + return eHAL_STATUS_INVALID_PARAMETER; + } + /* + * if roaming within band is enabled, then select only the + * in band channels . + * This is required only if the band capability is set to ALL, + * E.g., if band capability is only 2.4G then all the channels in the + * list are already filtered for 2.4G channels, hence ignore this check + */ + if ((eCSR_BAND_ALL == eBand) && CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac)) + { + csrNeighborRoamChannelsFilterByCurrentBand( + pMac, + sessionId, + ChannelList, + outNumChannels, + tmpChannelList, + &outNumChannels); + vos_mem_copy(ChannelList, + tmpChannelList, outNumChannels); + } + /* Prepare final roam scan channel list */ + if(outNumChannels) + { + /* Clear the channel list first */ + if (NULL != currChannelListInfo->ChannelList) + { + vos_mem_free(currChannelListInfo->ChannelList); + currChannelListInfo->ChannelList = NULL; + currChannelListInfo->numOfChannels = 0; + } + currChannelListInfo->ChannelList + = vos_mem_malloc(outNumChannels * sizeof(tANI_U8)); + if (NULL == currChannelListInfo->ChannelList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "Failed to allocate memory for roam scan channel list"); + currChannelListInfo->numOfChannels = 0; + return VOS_STATUS_E_RESOURCES; + } + vos_mem_copy(currChannelListInfo->ChannelList, + ChannelList, outNumChannels); + } + return status; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +eHalStatus csrSetBand(tHalHandle hHal, tANI_U8 sessionId, eCsrBand eBand) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + if (CSR_IS_PHY_MODE_A_ONLY(pMac) && + (eBand == eCSR_BAND_24)) + { + /* DOT11 mode configured to 11a only and received + request to change the band to 2.4 GHz */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "failed to set band cfg80211 = %u, band = %u", + pMac->roam.configParam.uCfgDot11Mode, eBand); + return eHAL_STATUS_INVALID_PARAMETER; + } + if ((CSR_IS_PHY_MODE_B_ONLY(pMac) || + CSR_IS_PHY_MODE_G_ONLY(pMac)) && + (eBand == eCSR_BAND_5G)) + { + /* DOT11 mode configured to 11b/11g only and received + request to change the band to 5 GHz */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "failed to set band dot11mode = %u, band = %u", + pMac->roam.configParam.uCfgDot11Mode, eBand); + return eHAL_STATUS_INVALID_PARAMETER; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Band changed to %u (0 - ALL, 1 - 2.4 GHZ, 2 - 5GHZ)", eBand); + pMac->roam.configParam.eBand = eBand; + pMac->roam.configParam.bandCapability = eBand; + csrScanGetSupportedChannels( pMac ); +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) +#endif + csrUpdateBgScanConfigIniChannelList(pMac, sessionId, eBand); +#endif + status = csrInitGetChannels( pMac ); + if (eHAL_STATUS_SUCCESS == status) + csrInitChannelList( hHal ); + return status; +} + + +/* The function csrConvertCBIniValueToPhyCBState and + * csrConvertPhyCBStateToIniValue have been + * introduced to convert the ini value to the ENUM used in csr and MAC for CB state + * Ideally we should have kept the ini value and enum value same and representing the same + * cb values as in 11n standard i.e. + * Set to 1 (SCA) if the secondary channel is above the primary channel + * Set to 3 (SCB) if the secondary channel is below the primary channel + * Set to 0 (SCN) if no secondary channel is present + * However, since our driver is already distributed we will keep the ini definition as it is which is: + * 0 - secondary none + * 1 - secondary LOW + * 2 - secondary HIGH + * and convert to enum value used within the driver in + * csrChangeDefaultConfigParam using this function + * The enum values are as follows: + * PHY_SINGLE_CHANNEL_CENTERED = 0 + * PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1 + * PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3 + */ +ePhyChanBondState csrConvertCBIniValueToPhyCBState(v_U32_t cbIniValue) +{ + + ePhyChanBondState phyCbState; + switch (cbIniValue) { + // secondary none + case eCSR_INI_SINGLE_CHANNEL_CENTERED: + phyCbState = PHY_SINGLE_CHANNEL_CENTERED; + break; + // secondary LOW + case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY: + phyCbState = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + break; + // secondary HIGH + case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY: + phyCbState = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; + break; +#endif + default: + // If an invalid value is passed, disable CHANNEL BONDING + phyCbState = PHY_SINGLE_CHANNEL_CENTERED; + break; + } + return phyCbState; +} + +v_U32_t csrConvertPhyCBStateToIniValue(ePhyChanBondState phyCbState) +{ + + v_U32_t cbIniValue; + switch (phyCbState) { + // secondary none + case PHY_SINGLE_CHANNEL_CENTERED: + cbIniValue = eCSR_INI_SINGLE_CHANNEL_CENTERED; + break; + // secondary LOW + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + cbIniValue = eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + break; + // secondary HIGH + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + cbIniValue = eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + break; +#ifdef WLAN_FEATURE_11AC + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; + break; +#endif + default: + // return some invalid value + cbIniValue = eCSR_INI_CHANNEL_BONDING_STATE_MAX; + break; + } + return cbIniValue; +} + +eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + if(pParam) + { + pMac->roam.configParam.pkt_err_disconn_th = pParam->pkt_err_disconn_th; + pMac->roam.configParam.WMMSupportMode = pParam->WMMSupportMode; + cfgSetInt(pMac, WNI_CFG_WME_ENABLED, + (pParam->WMMSupportMode == eCsrRoamWmmNoQos)? 0:1); + pMac->roam.configParam.Is11eSupportEnabled = pParam->Is11eSupportEnabled; + pMac->roam.configParam.FragmentationThreshold = pParam->FragmentationThreshold; + pMac->roam.configParam.Is11dSupportEnabled = pParam->Is11dSupportEnabled; + pMac->roam.configParam.Is11dSupportEnabledOriginal = pParam->Is11dSupportEnabled; + pMac->roam.configParam.Is11hSupportEnabled = pParam->Is11hSupportEnabled; + + pMac->roam.configParam.fenableMCCMode = pParam->fEnableMCCMode; + pMac->roam.configParam.mcc_rts_cts_prot_enable = + pParam->mcc_rts_cts_prot_enable; + pMac->roam.configParam.mcc_bcast_prob_resp_enable = + pParam->mcc_bcast_prob_resp_enable; + + pMac->roam.configParam.fAllowMCCGODiffBI = pParam->fAllowMCCGODiffBI; + + /* channelBondingMode5GHz plays a dual role right now + * INFRA STA will use this non zero value as CB enabled and SOFTAP will use this non-zero value to determine the secondary channel offset + * This is how channelBondingMode5GHz works now and this is kept intact to avoid any cfg.ini change + */ + if (pParam->channelBondingMode24GHz > MAX_CB_VALUE_IN_INI) + { + smsLog( pMac, LOGW, "Invalid CB value from ini in 2.4GHz band %d, CB DISABLED", pParam->channelBondingMode24GHz); + } + pMac->roam.configParam.channelBondingMode24GHz = csrConvertCBIniValueToPhyCBState(pParam->channelBondingMode24GHz); + if (pParam->channelBondingMode5GHz > MAX_CB_VALUE_IN_INI) + { + smsLog( pMac, LOGW, "Invalid CB value from ini in 5GHz band %d, CB DISABLED", pParam->channelBondingMode5GHz); + } + pMac->roam.configParam.stacbmode = pParam->stacbmode; + pMac->roam.configParam.channelBondingMode5GHz = csrConvertCBIniValueToPhyCBState(pParam->channelBondingMode5GHz); + pMac->roam.configParam.RTSThreshold = pParam->RTSThreshold; + pMac->roam.configParam.phyMode = pParam->phyMode; + pMac->roam.configParam.shortSlotTime = pParam->shortSlotTime; + pMac->roam.configParam.HeartbeatThresh24 = pParam->HeartbeatThresh24; + pMac->roam.configParam.HeartbeatThresh50 = pParam->HeartbeatThresh50; + pMac->roam.configParam.ProprietaryRatesEnabled = pParam->ProprietaryRatesEnabled; + pMac->roam.configParam.TxRate = pParam->TxRate; + pMac->roam.configParam.AdHocChannel24 = pParam->AdHocChannel24; + pMac->roam.configParam.AdHocChannel5G = pParam->AdHocChannel5G; + pMac->roam.configParam.bandCapability = pParam->bandCapability; + pMac->roam.configParam.cbChoice = pParam->cbChoice; + pMac->roam.configParam.bgScanInterval = pParam->bgScanInterval; + pMac->roam.configParam.disableAggWithBtc = pParam->disableAggWithBtc; + + pMac->roam.configParam.neighborRoamConfig.delay_before_vdev_stop = + pParam->neighborRoamConfig.delay_before_vdev_stop; + + //if HDD passed down non zero values then only update, + //otherwise keep using the defaults + if (pParam->initial_scan_no_dfs_chnl) { + pMac->roam.configParam.initial_scan_no_dfs_chnl = + pParam->initial_scan_no_dfs_chnl; + } + if (pParam->nInitialDwellTime) + { + pMac->roam.configParam.nInitialDwellTime = + pParam->nInitialDwellTime; + } + if (pParam->nActiveMaxChnTime) + { + pMac->roam.configParam.nActiveMaxChnTime = pParam->nActiveMaxChnTime; + cfgSetInt(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + pParam->nActiveMaxChnTime); + } + if (pParam->nActiveMinChnTime) + { + pMac->roam.configParam.nActiveMinChnTime = pParam->nActiveMinChnTime; + cfgSetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + pParam->nActiveMinChnTime); + } + if (pParam->nPassiveMaxChnTime) + { + pMac->roam.configParam.nPassiveMaxChnTime = pParam->nPassiveMaxChnTime; + cfgSetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pParam->nPassiveMaxChnTime); + } + if (pParam->nPassiveMinChnTime) + { + pMac->roam.configParam.nPassiveMinChnTime = pParam->nPassiveMinChnTime; + cfgSetInt(pMac, WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME, + pParam->nPassiveMinChnTime); + } + if (pParam->nActiveMaxChnTimeBtc) + { + pMac->roam.configParam.nActiveMaxChnTimeBtc = pParam->nActiveMaxChnTimeBtc; + } + if (pParam->nActiveMinChnTimeBtc) + { + pMac->roam.configParam.nActiveMinChnTimeBtc = pParam->nActiveMinChnTimeBtc; + } +#ifdef WLAN_AP_STA_CONCURRENCY + if (pParam->nActiveMaxChnTimeConc) + { + pMac->roam.configParam.nActiveMaxChnTimeConc = pParam->nActiveMaxChnTimeConc; + } + if (pParam->nActiveMinChnTimeConc) + { + pMac->roam.configParam.nActiveMinChnTimeConc = pParam->nActiveMinChnTimeConc; + } + if (pParam->nPassiveMaxChnTimeConc) + { + pMac->roam.configParam.nPassiveMaxChnTimeConc = pParam->nPassiveMaxChnTimeConc; + } + if (pParam->nPassiveMinChnTimeConc) + { + pMac->roam.configParam.nPassiveMinChnTimeConc = pParam->nPassiveMinChnTimeConc; + } + if (pParam->nRestTimeConc) + { + pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc; + } + if (pParam->min_rest_time_conc) + { + pMac->roam.configParam.min_rest_time_conc = pParam->min_rest_time_conc; + } + if (pParam->idle_time_conc) + { + pMac->roam.configParam.idle_time_conc = pParam->idle_time_conc; + } + if (pParam->nNumStaChanCombinedConc) + { + pMac->roam.configParam.nNumStaChanCombinedConc = pParam->nNumStaChanCombinedConc; + } + if (pParam->nNumP2PChanCombinedConc) + { + pMac->roam.configParam.nNumP2PChanCombinedConc = pParam->nNumP2PChanCombinedConc; + } +#endif + //if upper layer wants to disable idle scan altogether set it to 0 + if (pParam->impsSleepTime) + { + //Change the unit from second to microsecond + tANI_U32 impsSleepTime = + pParam->impsSleepTime * VOS_TIMER_TO_SEC_UNIT; + + if(CSR_IDLE_SCAN_NO_PS_INTERVAL_MIN <= impsSleepTime) + { + pMac->roam.configParam.impsSleepTime = impsSleepTime; + } + else + { + pMac->roam.configParam.impsSleepTime = CSR_IDLE_SCAN_NO_PS_INTERVAL; + } + } + else + { + pMac->roam.configParam.impsSleepTime = 0; + } + pMac->roam.configParam.eBand = pParam->eBand; + pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(NULL, pMac->roam.configParam.phyMode, + pMac->roam.configParam.ProprietaryRatesEnabled); + //if HDD passed down non zero values for age params, then only update, + //otherwise keep using the defaults + if (pParam->nScanResultAgeCount) + { + pMac->roam.configParam.agingCount = pParam->nScanResultAgeCount; + } + if(pParam->scanAgeTimeNCNPS) + { + pMac->roam.configParam.scanAgeTimeNCNPS = pParam->scanAgeTimeNCNPS; + } + if(pParam->scanAgeTimeNCPS) + { + pMac->roam.configParam.scanAgeTimeNCPS = pParam->scanAgeTimeNCPS; + } + if(pParam->scanAgeTimeCNPS) + { + pMac->roam.configParam.scanAgeTimeCNPS = pParam->scanAgeTimeCNPS; + } + if(pParam->scanAgeTimeCPS) + { + pMac->roam.configParam.scanAgeTimeCPS = pParam->scanAgeTimeCPS; + } + + pMac->first_scan_bucket_threshold = + pParam->first_scan_bucket_threshold; + csrAssignRssiForCategory(pMac, pMac->first_scan_bucket_threshold, + pParam->bCatRssiOffset); + pMac->roam.configParam.nRoamingTime = pParam->nRoamingTime; + pMac->roam.configParam.fEnforce11dChannels = pParam->fEnforce11dChannels; + pMac->roam.configParam.fSupplicantCountryCodeHasPriority = pParam->fSupplicantCountryCodeHasPriority; + pMac->roam.configParam.fEnforceCountryCodeMatch = pParam->fEnforceCountryCodeMatch; + pMac->roam.configParam.fEnforceDefaultDomain = pParam->fEnforceDefaultDomain; + pMac->roam.configParam.vccRssiThreshold = pParam->vccRssiThreshold; + pMac->roam.configParam.vccUlMacLossThreshold = pParam->vccUlMacLossThreshold; + pMac->roam.configParam.IsIdleScanEnabled = pParam->IsIdleScanEnabled; + pMac->roam.configParam.statsReqPeriodicity = pParam->statsReqPeriodicity; + pMac->roam.configParam.statsReqPeriodicityInPS = pParam->statsReqPeriodicityInPS; + //Assign this before calling CsrInit11dInfo + pMac->roam.configParam.nTxPowerCap = pParam->nTxPowerCap; + if( csrIs11dSupported( pMac ) ) + { + status = CsrInit11dInfo(pMac, &pParam->Csr11dinfo); + } + else + { + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + } + + /* Initialize the power + channel information if 11h is enabled. + If 11d is enabled this information has already been initialized */ + if( csrIs11hSupported( pMac ) && !csrIs11dSupported( pMac ) ) + { + csrInitChannelPowerList(pMac, &pParam->Csr11dinfo); + } + + +#ifdef WLAN_FEATURE_VOWIFI_11R + vos_mem_copy(&pMac->roam.configParam.csr11rConfig, + &pParam->csr11rConfig, sizeof(tCsr11rConfigParams)); + smsLog( pMac, LOG1, "IsFTResourceReqSupp = %d", pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported); +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pMac->roam.configParam.isFastTransitionEnabled = pParam->isFastTransitionEnabled; + pMac->roam.configParam.RoamRssiDiff = pParam->RoamRssiDiff; + pMac->roam.configParam.nImmediateRoamRssiDiff = pParam->nImmediateRoamRssiDiff; + smsLog( pMac, LOG1, "nImmediateRoamRssiDiff = %d", + pMac->roam.configParam.nImmediateRoamRssiDiff ); + pMac->roam.configParam.nRoamPrefer5GHz = pParam->nRoamPrefer5GHz; + pMac->roam.configParam.nRoamIntraBand = pParam->nRoamIntraBand; + pMac->roam.configParam.isWESModeEnabled = pParam->isWESModeEnabled; + pMac->roam.configParam.nProbes = pParam->nProbes; + pMac->roam.configParam.nRoamScanHomeAwayTime = pParam->nRoamScanHomeAwayTime; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->roam.configParam.isRoamOffloadScanEnabled = pParam->isRoamOffloadScanEnabled; + pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = pParam->bFastRoamInConIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_LFR + pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled; + pMac->roam.configParam.MAWCEnabled = pParam->MAWCEnabled; +#endif + +#ifdef FEATURE_WLAN_ESE + pMac->roam.configParam.isEseIniFeatureEnabled = pParam->isEseIniFeatureEnabled; +#endif +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + vos_mem_copy(&pMac->roam.configParam.neighborRoamConfig, + &pParam->neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams)); + smsLog( pMac, LOG1, "nNeighborScanTimerPerioid = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod); + smsLog( pMac, LOG1, "nNeighborReassocRssiThreshold = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold); + smsLog( pMac, LOG1, "nNeighborLookupRssiThreshold = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold); + smsLog( pMac, LOG1, "nOpportunisticThresholdDiff = %d", pMac->roam.configParam.neighborRoamConfig.nOpportunisticThresholdDiff); + smsLog( pMac, LOG1, "nRoamRescanRssiDiff = %d", pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff); + smsLog( pMac, LOG1, "nNeighborScanMinChanTime = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime); + smsLog( pMac, LOG1, "nNeighborScanMaxChanTime = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime); + smsLog( pMac, LOG1, "nMaxNeighborRetries = %d", pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries); + smsLog( pMac, LOG1, "nNeighborResultsRefreshPeriod = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod); + smsLog( pMac, LOG1, "nEmptyScanRefreshPeriod = %d", pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod); + { + int i; + smsLog( pMac, LOG1, FL("Num of Channels in CFG Channel List: %d"), pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels); + for( i=0; i< pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels; i++) + { + smsLog( pMac, LOG1, "%d ", pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[i] ); + } + } + smsLog( pMac, LOG1, "nRoamBmissFirstBcnt = %d", pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt); + smsLog( pMac, LOG1, "nRoamBmissFinalBcnt = %d", pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt); + smsLog( pMac, LOG1, "nRoamBeaconRssiWeight = %d", pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight); +#endif + pMac->roam.configParam.addTSWhenACMIsOff = pParam->addTSWhenACMIsOff; + pMac->scan.fValidateList = pParam->fValidateList; + pMac->scan.fEnableBypass11d = pParam->fEnableBypass11d; + pMac->scan.fEnableDFSChnlScan = pParam->fEnableDFSChnlScan; + pMac->scan.scanResultCfgAgingTime = pParam->scanCfgAgingTime; + pMac->roam.configParam.fScanTwice = pParam->fScanTwice; + pMac->scan.fFirstScanOnly2GChnl = pParam->fFirstScanOnly2GChnl; + pMac->scan.scanBandPreference = pParam->scanBandPreference; + /* + * This parameter is not available in cfg and not passed from upper + * layers. Instead it is initialized here. This parameter is used in + * concurrency to determine if there are concurrent active sessions. + * Is used as a temporary fix to disconnect all active sessions when + * BMPS enabled so the active session if Infra STA + * will automatically connect back and resume BMPS since resume BMPS is + * not working when moving from concurrent to single session + */ + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + pMac->roam.configParam.doBMPSWorkaround = 0; + +#ifdef WLAN_FEATURE_11AC + pMac->roam.configParam.nVhtChannelWidth = pParam->nVhtChannelWidth; + pMac->roam.configParam.txBFEnable= pParam->enableTxBF; + pMac->roam.configParam.txBFCsnValue = pParam->txBFCsnValue; + pMac->roam.configParam.enable2x2= pParam->enable2x2; + pMac->roam.configParam.enableVhtFor24GHz = pParam->enableVhtFor24GHz; + pMac->roam.configParam.txMuBformee= pParam->enableMuBformee; + pMac->roam.configParam.enableVhtpAid = pParam->enableVhtpAid; + pMac->roam.configParam.enableVhtGid = pParam->enableVhtGid; +#endif + pMac->roam.configParam.enableAmpduPs = pParam->enableAmpduPs; + pMac->roam.configParam.enableHtSmps = pParam->enableHtSmps; + pMac->roam.configParam.htSmps= pParam->htSmps; + pMac->roam.configParam.txLdpcEnable = pParam->enableTxLdpc; + + pMac->roam.configParam.max_amsdu_num = pParam->max_amsdu_num; + pMac->roam.configParam.nSelect5GHzMargin = pParam->nSelect5GHzMargin; + pMac->roam.configParam.ignorePeerErpInfo = pParam->ignorePeerErpInfo; + pMac->roam.configParam.isCoalesingInIBSSAllowed = + pParam->isCoalesingInIBSSAllowed; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + pMac->roam.configParam.cc_switch_mode = pParam->cc_switch_mode; +#endif + pMac->roam.configParam.allowDFSChannelRoam = pParam->allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pMac->roam.configParam.isRoamOffloadEnabled = + pParam->isRoamOffloadEnabled; +#endif + pMac->roam.configParam.obssEnabled = pParam->obssEnabled; + pMac->roam.configParam.conc_custom_rule1 = + pParam->conc_custom_rule1; + pMac->roam.configParam.conc_custom_rule2 = + pParam->conc_custom_rule2; + pMac->roam.configParam.is_sta_connection_in_5gz_enabled = + pParam->is_sta_connection_in_5gz_enabled; + + pMac->enable_dot11p = pParam->enable_dot11p; + pMac->roam.configParam.sendDeauthBeforeCon = + pParam->sendDeauthBeforeCon; + } + + return status; +} + +eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + if(pParam) + { + pParam->WMMSupportMode = pMac->roam.configParam.WMMSupportMode; + pParam->Is11eSupportEnabled = pMac->roam.configParam.Is11eSupportEnabled; + pParam->FragmentationThreshold = pMac->roam.configParam.FragmentationThreshold; + pParam->Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabled; + pParam->Is11dSupportEnabledOriginal = pMac->roam.configParam.Is11dSupportEnabledOriginal; + pParam->Is11hSupportEnabled = pMac->roam.configParam.Is11hSupportEnabled; + pParam->channelBondingMode24GHz = csrConvertPhyCBStateToIniValue(pMac->roam.configParam.channelBondingMode24GHz); + pParam->channelBondingMode5GHz = csrConvertPhyCBStateToIniValue(pMac->roam.configParam.channelBondingMode5GHz); + pParam->stacbmode = pMac->roam.configParam.stacbmode; + pParam->RTSThreshold = pMac->roam.configParam.RTSThreshold; + pParam->phyMode = pMac->roam.configParam.phyMode; + pParam->shortSlotTime = pMac->roam.configParam.shortSlotTime; + pParam->HeartbeatThresh24 = pMac->roam.configParam.HeartbeatThresh24; + pParam->HeartbeatThresh50 = pMac->roam.configParam.HeartbeatThresh50; + pParam->ProprietaryRatesEnabled = pMac->roam.configParam.ProprietaryRatesEnabled; + pParam->TxRate = pMac->roam.configParam.TxRate; + pParam->AdHocChannel24 = pMac->roam.configParam.AdHocChannel24; + pParam->AdHocChannel5G = pMac->roam.configParam.AdHocChannel5G; + pParam->bandCapability = pMac->roam.configParam.bandCapability; + pParam->cbChoice = pMac->roam.configParam.cbChoice; + pParam->bgScanInterval = pMac->roam.configParam.bgScanInterval; + pParam->nActiveMaxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + pParam->nActiveMinChnTime = pMac->roam.configParam.nActiveMinChnTime; + pParam->nPassiveMaxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; + pParam->nPassiveMinChnTime = pMac->roam.configParam.nPassiveMinChnTime; + pParam->nActiveMaxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pParam->nActiveMinChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pParam->disableAggWithBtc = pMac->roam.configParam.disableAggWithBtc; +#ifdef WLAN_AP_STA_CONCURRENCY + pParam->nActiveMaxChnTimeConc = pMac->roam.configParam.nActiveMaxChnTimeConc; + pParam->nActiveMinChnTimeConc = pMac->roam.configParam.nActiveMinChnTimeConc; + pParam->nPassiveMaxChnTimeConc = pMac->roam.configParam.nPassiveMaxChnTimeConc; + pParam->nPassiveMinChnTimeConc = pMac->roam.configParam.nPassiveMinChnTimeConc; + pParam->nRestTimeConc = pMac->roam.configParam.nRestTimeConc; + pParam->min_rest_time_conc = pMac->roam.configParam.min_rest_time_conc; + pParam->idle_time_conc = pMac->roam.configParam.idle_time_conc; + + pParam->nNumStaChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + pParam->nNumP2PChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; +#endif + //Change the unit from microsecond to second + pParam->impsSleepTime = + pMac->roam.configParam.impsSleepTime / VOS_TIMER_TO_SEC_UNIT; + pParam->eBand = pMac->roam.configParam.eBand; + pParam->nScanResultAgeCount = pMac->roam.configParam.agingCount; + pParam->scanAgeTimeNCNPS = pMac->roam.configParam.scanAgeTimeNCNPS; + pParam->scanAgeTimeNCPS = pMac->roam.configParam.scanAgeTimeNCPS; + pParam->scanAgeTimeCNPS = pMac->roam.configParam.scanAgeTimeCNPS; + pParam->scanAgeTimeCPS = pMac->roam.configParam.scanAgeTimeCPS; + pParam->bCatRssiOffset = pMac->roam.configParam.bCatRssiOffset; + pParam->nRoamingTime = pMac->roam.configParam.nRoamingTime; + pParam->fEnforce11dChannels = pMac->roam.configParam.fEnforce11dChannels; + pParam->fSupplicantCountryCodeHasPriority = pMac->roam.configParam.fSupplicantCountryCodeHasPriority; + pParam->fEnforceCountryCodeMatch = pMac->roam.configParam.fEnforceCountryCodeMatch; + pParam->fEnforceDefaultDomain = pMac->roam.configParam.fEnforceDefaultDomain; + pParam->vccRssiThreshold = pMac->roam.configParam.vccRssiThreshold; + pParam->vccUlMacLossThreshold = pMac->roam.configParam.vccUlMacLossThreshold; + pParam->IsIdleScanEnabled = pMac->roam.configParam.IsIdleScanEnabled; + pParam->nTxPowerCap = pMac->roam.configParam.nTxPowerCap; + pParam->statsReqPeriodicity = pMac->roam.configParam.statsReqPeriodicity; + pParam->statsReqPeriodicityInPS = pMac->roam.configParam.statsReqPeriodicityInPS; + pParam->addTSWhenACMIsOff = pMac->roam.configParam.addTSWhenACMIsOff; + pParam->fValidateList = pMac->roam.configParam.fValidateList; + pParam->fEnableBypass11d = pMac->scan.fEnableBypass11d; + pParam->fEnableDFSChnlScan = pMac->scan.fEnableDFSChnlScan; + pParam->fScanTwice = pMac->roam.configParam.fScanTwice; + pParam->fFirstScanOnly2GChnl = pMac->scan.fFirstScanOnly2GChnl; + pParam->fEnableMCCMode = pMac->roam.configParam.fenableMCCMode; + pParam->fAllowMCCGODiffBI = pMac->roam.configParam.fAllowMCCGODiffBI; + pParam->scanCfgAgingTime = pMac->scan.scanResultCfgAgingTime; + pParam->scanBandPreference = pMac->scan.scanBandPreference; +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + vos_mem_copy(&pParam->neighborRoamConfig, + &pMac->roam.configParam.neighborRoamConfig, + sizeof(tCsrNeighborRoamConfigParams)); +#endif +#ifdef WLAN_FEATURE_11AC + pParam->nVhtChannelWidth = pMac->roam.configParam.nVhtChannelWidth; + pParam->enableTxBF = pMac->roam.configParam.txBFEnable; + pParam->txBFCsnValue = pMac->roam.configParam.txBFCsnValue; + pParam->enableMuBformee = pMac->roam.configParam.txMuBformee; + pParam->enableVhtFor24GHz = pMac->roam.configParam.enableVhtFor24GHz; + pParam->enable2x2 = pMac->roam.configParam.enable2x2; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + vos_mem_copy(&pMac->roam.configParam.csr11rConfig, + &pParam->csr11rConfig, sizeof(tCsr11rConfigParams)); +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pParam->isFastTransitionEnabled = pMac->roam.configParam.isFastTransitionEnabled; + pParam->RoamRssiDiff = pMac->roam.configParam.RoamRssiDiff; + pParam->nImmediateRoamRssiDiff = pMac->roam.configParam.nImmediateRoamRssiDiff; + pParam->nRoamPrefer5GHz = pMac->roam.configParam.nRoamPrefer5GHz; + pParam->nRoamIntraBand = pMac->roam.configParam.nRoamIntraBand; + pParam->isWESModeEnabled = pMac->roam.configParam.isWESModeEnabled; + pParam->nProbes = pMac->roam.configParam.nProbes; + pParam->nRoamScanHomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pParam->isRoamOffloadScanEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled; + pParam->bFastRoamInConIniFeatureEnabled = pMac->roam.configParam.bFastRoamInConIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_LFR + pParam->isFastRoamIniFeatureEnabled = pMac->roam.configParam.isFastRoamIniFeatureEnabled; +#endif + +#ifdef FEATURE_WLAN_ESE + pParam->isEseIniFeatureEnabled = pMac->roam.configParam.isEseIniFeatureEnabled; +#endif +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + vos_mem_copy(&pParam->neighborRoamConfig, + &pMac->roam.configParam.neighborRoamConfig, + sizeof(tCsrNeighborRoamConfigParams)); + { + int i; + smsLog( pMac, LOG1, FL("Num of Channels in CFG Channel List: %d"), pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels); + for( i=0; i< pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels; i++) + { + smsLog( pMac, LOG1, "%d ", pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[i] ); + } + } +#endif + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + pParam->cc_switch_mode = pMac->roam.configParam.cc_switch_mode; +#endif + pParam->enableTxLdpc = pMac->roam.configParam.txLdpcEnable; + + pParam->max_amsdu_num = pMac->roam.configParam.max_amsdu_num; + pParam->nSelect5GHzMargin = pMac->roam.configParam.nSelect5GHzMargin; + pParam->ignorePeerErpInfo = pMac->roam.configParam.ignorePeerErpInfo; + + pParam->isCoalesingInIBSSAllowed = + pMac->roam.configParam.isCoalesingInIBSSAllowed; + pParam->allowDFSChannelRoam = + pMac->roam.configParam.allowDFSChannelRoam; + pParam->nInitialDwellTime = + pMac->roam.configParam.nInitialDwellTime; + pParam->initial_scan_no_dfs_chnl = + pMac->roam.configParam.initial_scan_no_dfs_chnl; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pParam->isRoamOffloadEnabled = + pMac->roam.configParam.isRoamOffloadEnabled; +#endif + + pParam->enable_dot11p = pMac->enable_dot11p; + + csrSetChannels(pMac, pParam); + + pParam->obssEnabled = pMac->roam.configParam.obssEnabled; + + pParam->conc_custom_rule1 = + pMac->roam.configParam.conc_custom_rule1; + pParam->conc_custom_rule2 = + pMac->roam.configParam.conc_custom_rule2; + pParam->is_sta_connection_in_5gz_enabled = + pMac->roam.configParam.is_sta_connection_in_5gz_enabled; + pParam->sendDeauthBeforeCon = + pMac->roam.configParam.sendDeauthBeforeCon; + pParam->first_scan_bucket_threshold = + pMac->first_scan_bucket_threshold; + status = eHAL_STATUS_SUCCESS; + } + return (status); +} + +eHalStatus csrSetPhyMode(tHalHandle hHal, tANI_U32 phyMode, eCsrBand eBand, tANI_BOOLEAN *pfRestartNeeded) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fRestartNeeded = eANI_BOOLEAN_FALSE; + eCsrPhyMode newPhyMode = eCSR_DOT11_MODE_AUTO; + do + { + if(eCSR_BAND_24 == eBand) + { + if(CSR_IS_RADIO_A_ONLY(pMac)) break; + if(eCSR_DOT11_MODE_11a & phyMode) break; + } + if(eCSR_BAND_5G == eBand) + { + if(CSR_IS_RADIO_BG_ONLY(pMac)) break; + if((eCSR_DOT11_MODE_11b & phyMode) || (eCSR_DOT11_MODE_11b_ONLY & phyMode) || + (eCSR_DOT11_MODE_11g & phyMode) || (eCSR_DOT11_MODE_11g_ONLY & phyMode) + ) + { + break; + } + } + if (eCSR_DOT11_MODE_AUTO & phyMode) { + newPhyMode = eCSR_DOT11_MODE_AUTO; + } else { + //Check for dual band and higher capability first + if(eCSR_DOT11_MODE_11n_ONLY & phyMode) + { + if(eCSR_DOT11_MODE_11n_ONLY != phyMode) break; + newPhyMode = eCSR_DOT11_MODE_11n_ONLY; + } + else if(eCSR_DOT11_MODE_11g_ONLY & phyMode) + { + if(eCSR_DOT11_MODE_11g_ONLY != phyMode) break; + if(eCSR_BAND_5G == eBand) break; + newPhyMode = eCSR_DOT11_MODE_11g_ONLY; + eBand = eCSR_BAND_24; + } + else if(eCSR_DOT11_MODE_11b_ONLY & phyMode) + { + if(eCSR_DOT11_MODE_11b_ONLY != phyMode) break; + if(eCSR_BAND_5G == eBand) break; + newPhyMode = eCSR_DOT11_MODE_11b_ONLY; + eBand = eCSR_BAND_24; + } + else if(eCSR_DOT11_MODE_11n & phyMode) + { + newPhyMode = eCSR_DOT11_MODE_11n; + } + else if(eCSR_DOT11_MODE_abg & phyMode) + { + newPhyMode = eCSR_DOT11_MODE_abg; + } + else if(eCSR_DOT11_MODE_11a & phyMode) + { + if((eCSR_DOT11_MODE_11g & phyMode) || (eCSR_DOT11_MODE_11b & phyMode)) + { + if(eCSR_BAND_ALL == eBand) + { + newPhyMode = eCSR_DOT11_MODE_abg; + } + else + { + //bad setting + break; + } + } + else + { + newPhyMode = eCSR_DOT11_MODE_11a; + eBand = eCSR_BAND_5G; + } + } + else if(eCSR_DOT11_MODE_11g & phyMode) + { + newPhyMode = eCSR_DOT11_MODE_11g; + eBand = eCSR_BAND_24; + } + else if(eCSR_DOT11_MODE_11b & phyMode) + { + newPhyMode = eCSR_DOT11_MODE_11b; + eBand = eCSR_BAND_24; + } + else + { + //We will never be here + smsLog( pMac, LOGE, FL(" cannot recognize the phy mode 0x%08X"), phyMode ); + newPhyMode = eCSR_DOT11_MODE_AUTO; + } + } + //Done validating + status = eHAL_STATUS_SUCCESS; + //Now we need to check whether a restart is needed. + if(eBand != pMac->roam.configParam.eBand) + { + fRestartNeeded = eANI_BOOLEAN_TRUE; + break; + } + if(newPhyMode != pMac->roam.configParam.phyMode) + { + fRestartNeeded = eANI_BOOLEAN_TRUE; + break; + } + }while(0); + if(HAL_STATUS_SUCCESS(status)) + { + pMac->roam.configParam.eBand = eBand; + pMac->roam.configParam.phyMode = newPhyMode; + if(pfRestartNeeded) + { + *pfRestartNeeded = fRestartNeeded; + } + } + return (status); +} + +void csrPruneChannelListForMode( tpAniSirGlobal pMac, tCsrChannel *pChannelList ) +{ + tANI_U8 Index; + tANI_U8 cChannels; + // for dual band NICs, don't need to trim the channel list.... + if ( !CSR_IS_OPEARTING_DUAL_BAND( pMac ) ) + { + // 2.4 GHz band operation requires the channel list to be trimmed to + // the 2.4 GHz channels only... + if ( CSR_IS_24_BAND_ONLY( pMac ) ) + { + for( Index = 0, cChannels = 0; Index < pChannelList->numChannels; + Index++ ) + { + if ( CSR_IS_CHANNEL_24GHZ(pChannelList->channelList[ Index ]) ) + { + pChannelList->channelList[ cChannels ] = pChannelList->channelList[ Index ]; + cChannels++; + } + } + /* + * Cleanup the rest of channels. Note we only need to clean up the + * channels if we had to trim the list. + * The amount of memory to clear is the number of channels that we + * trimmed (pChannelList->numChannels - cChannels) times the size + * of a channel in the structure. + */ + + if ( pChannelList->numChannels > cChannels ) + { + vos_mem_set(&pChannelList->channelList[ cChannels ], + sizeof( pChannelList->channelList[ 0 ] ) * + ( pChannelList->numChannels - cChannels ), 0); + } + + pChannelList->numChannels = cChannels; + } + else if ( CSR_IS_5G_BAND_ONLY( pMac ) ) + { + for ( Index = 0, cChannels = 0; Index < pChannelList->numChannels; Index++ ) + { + if ( CSR_IS_CHANNEL_5GHZ(pChannelList->channelList[ Index ]) ) + { + pChannelList->channelList[ cChannels ] = pChannelList->channelList[ Index ]; + cChannels++; + } + } + /* + * Cleanup the rest of channels. Note we only need to clean up the + * channels if we had to trim the list. + * The amount of memory to clear is the number of channels that we + * trimmed (pChannelList->numChannels - cChannels) times the size + * of a channel in the structure. + */ + if ( pChannelList->numChannels > cChannels ) + { + vos_mem_set(&pChannelList->channelList[ cChannels ], + sizeof( pChannelList->channelList[ 0 ] ) * + ( pChannelList->numChannels - cChannels ), 0); + } + + pChannelList->numChannels = cChannels; + } + } +} +#define INFRA_AP_DEFAULT_CHANNEL 6 +VOS_STATUS csrIsValidChannel(tpAniSirGlobal pMac, tANI_U8 chnNum) +{ + tANI_U8 index= 0; + VOS_STATUS status = VOS_STATUS_E_NOSUPPORT; + + /* regulatory check */ + for (index=0; index < pMac->scan.base20MHzChannels.numChannels ;index++) + { + if(pMac->scan.base20MHzChannels.channelList[ index ] == chnNum){ + status = VOS_STATUS_SUCCESS; + break; + } + } + + if (status == VOS_STATUS_SUCCESS) + { + /* dfs nol */ + for (index = 0; + index < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; + index++) + { + tSapDfsNolInfo* dfsChan = + &pMac->sap.SapDfsInfo.sapDfsChannelNolList[index]; + if ((dfsChan->dfs_channel_number == chnNum) && + (dfsChan->radar_status_flag == eSAP_DFS_CHANNEL_UNAVAILABLE)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("channel %d is in dfs nol"), + chnNum); + status = VOS_STATUS_E_FAILURE; + break; + } + } + } + + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("channel %d is not available"), + chnNum); + } + + return status; +} + + +eHalStatus csrInitGetChannels(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U8 num20MHzChannelsFound = 0; + VOS_STATUS vosStatus; + tANI_U8 Index = 0; + tANI_U8 num40MHzChannelsFound = 0; + + + //TODO: this interface changed to include the 40MHz channel list + // this needs to be tied into the adapter structure somehow and referenced appropriately for CB operation + // Read the scan channel list (including the power limit) from EEPROM + vosStatus = vos_nv_getChannelListWithPower( pMac->scan.defaultPowerTable, &num20MHzChannelsFound, + pMac->scan.defaultPowerTable40MHz, &num40MHzChannelsFound); + if ( (VOS_STATUS_SUCCESS != vosStatus) || (num20MHzChannelsFound == 0) ) + { + smsLog( pMac, LOGE, FL("failed to get channels ")); + status = eHAL_STATUS_FAILURE; + } + else + { + if ( num20MHzChannelsFound > WNI_CFG_VALID_CHANNEL_LIST_LEN ) + { + num20MHzChannelsFound = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + pMac->scan.numChannelsDefault = num20MHzChannelsFound; + // Move the channel list to the global data + // structure -- this will be used as the scan list + for ( Index = 0; Index < num20MHzChannelsFound; Index++) + { + pMac->scan.base20MHzChannels.channelList[ Index ] = pMac->scan.defaultPowerTable[ Index ].chanId; + } + pMac->scan.base20MHzChannels.numChannels = num20MHzChannelsFound; + if(num40MHzChannelsFound > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + num40MHzChannelsFound = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + for ( Index = 0; Index < num40MHzChannelsFound; Index++) + { + pMac->scan.base40MHzChannels.channelList[ Index ] = pMac->scan.defaultPowerTable40MHz[ Index ].chanId; + } + pMac->scan.base40MHzChannels.numChannels = num40MHzChannelsFound; + } + return (status); +} +eHalStatus csrInitChannelList( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + csrPruneChannelListForMode(pMac, &pMac->scan.baseChannels); + csrPruneChannelListForMode(pMac, &pMac->scan.base20MHzChannels); + csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_FALSE); + csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_TRUE); + // Apply the base channel list, power info, and set the Country code... + csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent, eANI_BOOLEAN_TRUE ); + csrInitOperatingClasses(hHal); + return (status); +} +eHalStatus csrChangeConfigParams(tpAniSirGlobal pMac, + tCsrUpdateConfigParam *pUpdateConfigParam) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsr11dinfo *ps11dinfo = NULL; + ps11dinfo = &pUpdateConfigParam->Csr11dinfo; + status = CsrInit11dInfo(pMac, ps11dinfo); + return status; +} + +static eHalStatus CsrInit11dInfo(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_U8 index; + tANI_U32 count=0; + tSirMacChanInfo *pChanInfo; + tSirMacChanInfo *pChanInfoStart; + tANI_BOOLEAN applyConfig = TRUE; + + pMac->scan.currentCountryRSSI = -128; + if(!ps11dinfo) + { + return (status); + } + if ( ps11dinfo->Channels.numChannels && ( WNI_CFG_VALID_CHANNEL_LIST_LEN >= ps11dinfo->Channels.numChannels ) ) + { + pMac->scan.base20MHzChannels.numChannels = ps11dinfo->Channels.numChannels; + vos_mem_copy(pMac->scan.base20MHzChannels.channelList, + ps11dinfo->Channels.channelList, + ps11dinfo->Channels.numChannels); + } + else + { + //No change + return (eHAL_STATUS_SUCCESS); + } + //legacy maintenance + + vos_mem_copy(pMac->scan.countryCodeDefault, ps11dinfo->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + + + /* Tush: at csropen get this initialized with default, during csr reset if + this already set with some value no need initialize with default again */ + if(0 == pMac->scan.countryCodeCurrent[0]) + { + vos_mem_copy(pMac->scan.countryCodeCurrent, ps11dinfo->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + } + // need to add the max power channel list + pChanInfo = vos_mem_malloc(sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (pChanInfo != NULL) + { + vos_mem_set(pChanInfo, + sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN , + 0); + + pChanInfoStart = pChanInfo; + for(index = 0; index < ps11dinfo->Channels.numChannels; index++) + { + pChanInfo->firstChanNum = ps11dinfo->ChnPower[index].firstChannel; + pChanInfo->numChannels = ps11dinfo->ChnPower[index].numChannels; + pChanInfo->maxTxPower = CSR_ROAM_MIN( ps11dinfo->ChnPower[index].maxtxPower, pMac->roam.configParam.nTxPowerCap ); + pChanInfo++; + count++; + } + if(count) + { + csrSaveToChannelPower2G_5G( pMac, count * sizeof(tSirMacChanInfo), pChanInfoStart ); + } + vos_mem_free(pChanInfoStart); + } + //Only apply them to CFG when not in STOP state. Otherwise they will be applied later + if( HAL_STATUS_SUCCESS(status) ) + { + for( index = 0; index < CSR_ROAM_SESSION_MAX; index++ ) + { + if((CSR_IS_SESSION_VALID(pMac, index)) && CSR_IS_ROAM_STOP(pMac, index)) + { + applyConfig = FALSE; + } + } + + if(TRUE == applyConfig) + { + // Apply the base channel list, power info, and set the Country code... + csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent, eANI_BOOLEAN_TRUE ); + } + + } + return (status); +} +/* Initialize the Channel + Power List in the local cache and in the CFG */ +eHalStatus csrInitChannelPowerList( tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo) +{ + tANI_U8 index; + tANI_U32 count=0; + tSirMacChanInfo *pChanInfo; + tSirMacChanInfo *pChanInfoStart; + + if(!ps11dinfo || !pMac) + { + return eHAL_STATUS_FAILURE; + } + + pChanInfo = vos_mem_malloc(sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (pChanInfo != NULL) + { + vos_mem_set(pChanInfo, + sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN, + 0); + pChanInfoStart = pChanInfo; + + for(index = 0; index < ps11dinfo->Channels.numChannels; index++) + { + pChanInfo->firstChanNum = ps11dinfo->ChnPower[index].firstChannel; + pChanInfo->numChannels = ps11dinfo->ChnPower[index].numChannels; + pChanInfo->maxTxPower = CSR_ROAM_MIN( ps11dinfo->ChnPower[index].maxtxPower, pMac->roam.configParam.nTxPowerCap ); + pChanInfo++; + count++; + } + if(count) + { + csrSaveToChannelPower2G_5G( pMac, count * sizeof(tSirMacChanInfo), pChanInfoStart ); + } + vos_mem_free(pChanInfoStart); + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * csr_roam_remove_duplicate_cmd_from_list()- Remove duplicate roam cmd from + * list + * + * @mac_ctx: pointer to global mac + * @session_id: session id for the cmd + * @list: pending list from which cmd needs to be removed + * @command: cmd to be removed, can be NULL + * @roam_reason: cmd with reason to be removed + * + * Remove duplicate command from the pending list. + * + * Return: void + */ +static void csr_roam_remove_duplicate_cmd_from_list(tpAniSirGlobal mac_ctx, + tANI_U32 session_id, tDblLinkList *list, + tSmeCmd *command, eCsrRoamReason roam_reason) +{ + tListElem *entry, *next_entry; + tSmeCmd *dup_cmd; + tDblLinkList local_list; + + vos_mem_zero(&local_list, sizeof(tDblLinkList)); + if (!HAL_STATUS_SUCCESS(csrLLOpen(mac_ctx->hHdd, &local_list))) { + smsLog(mac_ctx, LOGE, FL(" failed to open list")); + return; + } + csrLLLock(list); + entry = csrLLPeekHead(list, LL_ACCESS_NOLOCK); + while (entry) { + next_entry = csrLLNext(list, entry, LL_ACCESS_NOLOCK); + dup_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + /* + * Remove the previous command if.. + * - the new roam command is for the same RoamReason... + * - the new roam command is a NewProfileList. + * - the new roam command is a Forced Dissoc + * - the new roam command is from an 802.11 OID + * (OID_SSID or OID_BSSID). + */ + if ((command && (command->sessionId == dup_cmd->sessionId) && + ((command->command == dup_cmd->command) && + /* + * This peermac check is requried for Softap/GO + * scenarios. For STA scenario below OR check will + * suffice as command will always be NULL for STA + * scenarios + */ + (vos_mem_compare(dup_cmd->u.roamCmd.peerMac, + command->u.roamCmd.peerMac, + sizeof(v_MACADDR_t))) && + ((command->u.roamCmd.roamReason == + dup_cmd->u.roamCmd.roamReason) || + (eCsrForcedDisassoc == + command->u.roamCmd.roamReason) || + (eCsrHddIssued == + command->u.roamCmd.roamReason)))) || + /* OR if pCommand is NULL */ + ((session_id == dup_cmd->sessionId) && + (eSmeCommandRoam == dup_cmd->command) && + ((eCsrForcedDisassoc == roam_reason) || + (eCsrHddIssued == roam_reason)))) { + smsLog(mac_ctx, LOGW, FL("RoamReason = %d"), + dup_cmd->u.roamCmd.roamReason); + /* Remove the roam command from the pending list */ + if (csrLLRemoveEntry(list, entry, LL_ACCESS_NOLOCK)) + csrLLInsertTail(&local_list, + entry, LL_ACCESS_NOLOCK); + } + entry = next_entry; + } + csrLLUnlock(list); + + while ((entry = csrLLRemoveHead(&local_list, LL_ACCESS_NOLOCK))) { + dup_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + /* Tell caller that the command is cancelled */ + csrRoamCallCallback(mac_ctx, dup_cmd->sessionId, NULL, + dup_cmd->u.roamCmd.roamId, + eCSR_ROAM_CANCELLED, eCSR_ROAM_RESULT_NONE); + csrReleaseCommandRoam(mac_ctx, dup_cmd); + } + csrLLClose(&local_list); +} + +/** + * csrRoamRemoveDuplicateCommand()- Remove duplicate roam cmd + * from pending lists. + * + * @mac_ctx: pointer to global mac + * @session_id: session id for the cmd + * @command: cmd to be removed, can be null + * @roam_reason: cmd with reason to be removed + * + * Remove duplicate command from the sme and roam pending list. + * + * Return: void + */ +void csrRoamRemoveDuplicateCommand(tpAniSirGlobal mac_ctx, + tANI_U32 session_id, tSmeCmd *command, + eCsrRoamReason roam_reason) +{ + /* Always lock active list before locking pending lists */ + csrLLLock(&mac_ctx->sme.smeCmdActiveList); + csr_roam_remove_duplicate_cmd_from_list(mac_ctx, + session_id, &mac_ctx->sme.smeCmdPendingList, + command, roam_reason); + csr_roam_remove_duplicate_cmd_from_list(mac_ctx, + session_id, &mac_ctx->roam.roamCmdPendingList, + command, roam_reason); + csrLLUnlock(&mac_ctx->sme.smeCmdActiveList); +} +eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus u1, eCsrRoamResult u2) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + tANI_U32 rssi = 0; + WLAN_VOS_DIAG_EVENT_DEF(connectionStatus, vos_event_wlan_status_payload_type); +#endif + tCsrRoamSession *pSession; + tDot11fBeaconIEs *beacon_ies = NULL; + tANI_U8 chan1, chan2; + ePhyChanBondState phy_state; + + if( CSR_IS_SESSION_VALID( pMac, sessionId) ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + } + else + { + smsLog(pMac, LOGE, "Session ID:%d is not valid", sessionId); + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + + if (eANI_BOOLEAN_FALSE == pSession->sessionActive) + { + smsLog(pMac, LOG1, "%s Session is not Active", __func__); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOG4, "Received RoamCmdStatus %d with Roam Result %d", u1, u2); + + if (eCSR_ROAM_ASSOCIATION_COMPLETION == u1 && + eCSR_ROAM_RESULT_ASSOCIATED == u2 && pRoamInfo) + { + smsLog(pMac, LOGW, " Assoc complete result = %d statusCode = %d reasonCode = %d", u2, pRoamInfo->statusCode, pRoamInfo->reasonCode); + + beacon_ies = vos_mem_malloc(sizeof(tDot11fBeaconIEs)); + + if ((NULL != beacon_ies) && (NULL != pRoamInfo->pBssDesc)) { + status = csrParseBssDescriptionIEs((tHalHandle)pMac, + pRoamInfo->pBssDesc, + beacon_ies); + + /* now extract the phymode and center frequencies */ + + /* get the VHT OPERATION IE */ + if (beacon_ies->VHTOperation.present) { + + chan1 = beacon_ies->VHTOperation.chanCenterFreqSeg1; + chan2 = beacon_ies->VHTOperation.chanCenterFreqSeg2; + pRoamInfo->chan_info.info = MODE_11AC_VHT80; + + } else if (beacon_ies->HTInfo.present) { + + if (beacon_ies->HTInfo.recommendedTxWidthSet == eHT_CHANNEL_WIDTH_40MHZ) { + phy_state = beacon_ies->HTInfo.secondaryChannelOffset; + if (phy_state == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + + chan1 = beacon_ies->HTInfo.primaryChannel + + CSR_CB_CENTER_CHANNEL_OFFSET; + else if (phy_state == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + chan1 = beacon_ies->HTInfo.primaryChannel - + CSR_CB_CENTER_CHANNEL_OFFSET; + else + chan1 = beacon_ies->HTInfo.primaryChannel; + pRoamInfo->chan_info.info = MODE_11NA_HT40; + } else { + chan1 = beacon_ies->HTInfo.primaryChannel; + pRoamInfo->chan_info.info = MODE_11NA_HT20; + } + chan2 = 0; + } else { + chan1 = 0; + chan2 = 0; + pRoamInfo->chan_info.info = MODE_11A; + } + + if (0 != chan1) + pRoamInfo->chan_info.band_center_freq1 = + vos_chan_to_freq(chan1); + else + pRoamInfo->chan_info.band_center_freq1 = 0; + + if (0 != chan2) + pRoamInfo->chan_info.band_center_freq2 = + vos_chan_to_freq(chan2); + else + pRoamInfo->chan_info.band_center_freq2 = 0; + } + else { + pRoamInfo->chan_info.band_center_freq1 = 0; + pRoamInfo->chan_info.band_center_freq2 = 0; + pRoamInfo->chan_info.info = 0; + } + pRoamInfo->chan_info.chan_id = pRoamInfo->u.pConnectedProfile->operationChannel; + pRoamInfo->chan_info.mhz = vos_chan_to_freq(pRoamInfo->chan_info.chan_id); + pRoamInfo->chan_info.reg_info_1 = + (csrGetCfgMaxTxPower(pMac, pRoamInfo->chan_info.chan_id) << 16); + pRoamInfo->chan_info.reg_info_2 = + (csrGetCfgMaxTxPower(pMac, pRoamInfo->chan_info.chan_id) << 8); + vos_mem_free(beacon_ies); + } else if ((u1 == eCSR_ROAM_FT_REASSOC_FAILED) && + (pSession->bRefAssocStartCnt)) { + /* + * Decrement bRefAssocStartCnt for FT reassoc failure. + * Reason: For FT reassoc failures, we first call + * csrRoamCallCallback before notifying a failed roam + * completion through csrRoamComplete. The latter in + * turn calls csrRoamProcessResults which tries to + * once again call csrRoamCallCallback if bRefAssocStartCnt + * is non-zero. Since this is redundant for FT reassoc + * failure, decrement bRefAssocStartCnt. + */ + pSession->bRefAssocStartCnt--; + } else if (u1 == eCSR_ROAM_SET_CHANNEL_RSP && u2 == + eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS) { + pSession->connectedProfile.operationChannel = + pRoamInfo->channelChangeRespEvent->newChannelNumber; + } + + if(NULL != pSession->callback) + { + if( pRoamInfo ) + { + pRoamInfo->sessionId = (tANI_U8)sessionId; + /* + * the reasonCode will be passed to supplicant by + * cfg80211_disconnected. Based on the document, the reason code + * passed to supplicant needs to set to 0 if unknown. + * eSIR_BEACON_MISSED reason code is not recognizable so that + * we set to 0 instead. + */ + pRoamInfo->reasonCode = + (pRoamInfo->reasonCode == eSIR_BEACON_MISSED) ? + 0 : pRoamInfo->reasonCode; + } + /* avoid holding the global lock when making the roaming callback, original change came + from a raised CR (CR304874). Since this callback is in HDD a potential deadlock + is possible on other OS ports where the callback may need to take locks to protect + HDD state + UPDATE : revert this change but keep the comments here. Need to revisit as there are callbacks + that may actually depend on the lock being held */ + // TODO: revisit: sme_ReleaseGlobalLock( &pMac->sme ); + status = pSession->callback(pSession->pContext, pRoamInfo, roamId, u1, u2); + // TODO: revisit: sme_AcquireGlobalLock( &pMac->sme ); + } + //EVENT_WLAN_STATUS: eCSR_ROAM_ASSOCIATION_COMPLETION, + // eCSR_ROAM_LOSTLINK, eCSR_ROAM_DISASSOCIATED, +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + vos_mem_set(&connectionStatus, + sizeof(vos_event_wlan_status_payload_type), 0); + + if((eCSR_ROAM_ASSOCIATION_COMPLETION == u1) && (eCSR_ROAM_RESULT_ASSOCIATED == u2) && pRoamInfo) + { + connectionStatus.eventId = eCSR_WLAN_STATUS_CONNECT; + connectionStatus.bssType = pRoamInfo->u.pConnectedProfile->BSSType; + + if(NULL != pRoamInfo->pBssDesc) + { + connectionStatus.rssi = pRoamInfo->pBssDesc->rssi * (-1); + connectionStatus.channel = pRoamInfo->pBssDesc->channelId; + } + if (ccmCfgSetInt(pMac, WNI_CFG_CURRENT_RSSI, connectionStatus.rssi, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) { + smsLog(pMac, LOGE, "Could not pass WNI_CFG_CURRENT_RSSI to Cfg"); + } + + connectionStatus.qosCapability = pRoamInfo->u.pConnectedProfile->qosConnection; + connectionStatus.authType = (v_U8_t)diagAuthTypeFromCSRType(pRoamInfo->u.pConnectedProfile->AuthType); + connectionStatus.encryptionType = (v_U8_t)diagEncTypeFromCSRType(pRoamInfo->u.pConnectedProfile->EncryptionType); + vos_mem_copy(connectionStatus.ssid, + pRoamInfo->u.pConnectedProfile->SSID.ssId, 6); + + connectionStatus.reason = eCSR_REASON_UNSPECIFIED; + vos_mem_copy(&pMac->sme.eventPayload, &connectionStatus, + sizeof(vos_event_wlan_status_payload_type)); + WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS); + } + if((eCSR_ROAM_MIC_ERROR_IND == u1) || (eCSR_ROAM_RESULT_MIC_FAILURE == u2)) + { + vos_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(vos_event_wlan_status_payload_type)); + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_CURRENT_RSSI, &rssi))) + connectionStatus.rssi = rssi; + + connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT; + connectionStatus.reason = eCSR_REASON_MIC_ERROR; + WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS); + } + if(eCSR_ROAM_RESULT_FORCED == u2) + { + vos_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(vos_event_wlan_status_payload_type)); + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_CURRENT_RSSI, &rssi))) + connectionStatus.rssi = rssi; + + connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT; + connectionStatus.reason = eCSR_REASON_USER_REQUESTED; + WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS); + } + if(eCSR_ROAM_RESULT_DISASSOC_IND == u2) + { + vos_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(vos_event_wlan_status_payload_type)); + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_CURRENT_RSSI, &rssi))) + connectionStatus.rssi = rssi; + + connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT; + connectionStatus.reason = eCSR_REASON_DISASSOC; + if(pRoamInfo) + connectionStatus.reasonDisconnect = pRoamInfo->reasonCode; + + WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS); + } + if(eCSR_ROAM_RESULT_DEAUTH_IND == u2) + { + vos_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(vos_event_wlan_status_payload_type)); + if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_CURRENT_RSSI, &rssi))) + connectionStatus.rssi = rssi; + + connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT; + connectionStatus.reason = eCSR_REASON_DEAUTH; + if(pRoamInfo) + connectionStatus.reasonDisconnect = pRoamInfo->reasonCode; + WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS); + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + + return (status); +} + +// Returns whether handoff is currently in progress or not +tANI_BOOLEAN csrRoamIsHandoffInProgress(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + return csrNeighborRoamIsHandoffInProgress(pMac, sessionId); +#else + return eANI_BOOLEAN_FALSE; +#endif +} + +eHalStatus csrRoamIssueDisassociate( tpAniSirGlobal pMac, tANI_U32 sessionId, + eCsrRoamSubState NewSubstate, tANI_BOOLEAN fMICFailure ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tANI_U16 reasonCode; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if ( fMICFailure ) + { + reasonCode = eSIR_MAC_MIC_FAILURE_REASON; + } + else if (NewSubstate == eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF) + { + reasonCode = eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON; + } + else if (eCSR_ROAM_SUBSTATE_DISASSOC_STA_HAS_LEFT == NewSubstate) + { + reasonCode = eSIR_MAC_DISASSOC_LEAVING_BSS_REASON; + NewSubstate = eCSR_ROAM_SUBSTATE_DISASSOC_FORCED; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("set to reason code eSIR_MAC_DISASSOC_LEAVING_BSS_REASON" + " and set back NewSubstate")); + } + else + { + reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if ( (csrRoamIsHandoffInProgress(pMac, sessionId)) && + (NewSubstate != eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF)) + { + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + vos_mem_copy(&bssId, + pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid, + sizeof(tSirMacAddr)); + } + else +#endif + if(pSession->pConnectBssDesc) + { + vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid)); + } + + smsLog(pMac, LOG2, FL("CSR Attempting to Disassociate Bssid="MAC_ADDRESS_STR + " subState = %s reason=%d"), + MAC_ADDR_ARRAY(bssId), macTraceGetcsrRoamSubState(NewSubstate), + reasonCode); + + csrRoamSubstateChange( pMac, NewSubstate, sessionId); + + status = csrSendMBDisassocReqMsg( pMac, sessionId, bssId, reasonCode ); + + if(HAL_STATUS_SUCCESS(status)) + { + csrRoamLinkDown(pMac, sessionId); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + //no need to tell QoS that we are disassociating, it will be taken care off in assoc req for HO + if(eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF != NewSubstate) + { + //notify QoS module that disassoc happening + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_REQ, NULL); + } +#endif + } + else + { + smsLog(pMac, LOGW, FL("csrSendMBDisassocReqMsg failed with status %d"), status); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn csrRoamIssueDisassociateStaCmd + \brief csr function that HDD calls to disassociate a associated station + \param sessionId - session Id for Soft AP + \param pPeerMacAddr - MAC of associated station to delete + \param reason - reason code, be one of the tSirMacReasonCodes + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamIssueDisassociateStaCmd( tpAniSirGlobal pMac, + tANI_U32 sessionId, + struct tagCsrDelStaParams + *pDelStaParams) + +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + + do + { + pCommand = csrGetCommandBuffer( pMac ); + if ( !pCommand ) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + break; + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamReason = eCsrForcedDisassocSta; + vos_mem_copy(pCommand->u.roamCmd.peerMac, pDelStaParams->peerMacAddr, + sizeof(tSirMacAddr)); + pCommand->u.roamCmd.reason = + (tSirMacReasonCodes)pDelStaParams->reason_code; + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandRoam( pMac, pCommand ); + } + }while(0); + + return status; +} + + +/* --------------------------------------------------------------------------- + \fn csrRoamIssueDeauthSta + \brief csr function that HDD calls to delete a associated station + \param sessionId - session Id for Soft AP + \param pDelStaParams- Pointer to parameters of the station to deauthenticate + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamIssueDeauthStaCmd( tpAniSirGlobal pMac, + tANI_U32 sessionId, + struct tagCsrDelStaParams *pDelStaParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + + do + { + pCommand = csrGetCommandBuffer( pMac ); + if ( !pCommand ) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + break; + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta; + vos_mem_copy(pCommand->u.roamCmd.peerMac, pDelStaParams->peerMacAddr, + sizeof(tSirMacAddr)); + pCommand->u.roamCmd.reason = + (tSirMacReasonCodes)pDelStaParams->reason_code; + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandRoam( pMac, pCommand ); + } + }while(0); + + return status; +} +eHalStatus +csrRoamIssueTkipCounterMeasures( tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_BOOLEAN bEnable ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (!pSession) + { + smsLog( pMac, LOGE, "csrRoamIssueTkipCounterMeasures:CSR Session not found"); + return (status); + } + if (pSession->pConnectBssDesc) + { + vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid)); + } + else + { + smsLog( pMac, LOGE, "csrRoamIssueTkipCounterMeasures:Connected BSS Description in CSR Session not found"); + return (status); + } + smsLog( pMac, LOG2, "CSR issuing tkip counter measures for Bssid = "MAC_ADDRESS_STR", Enable = %d", + MAC_ADDR_ARRAY(bssId), bEnable); + status = csrSendMBTkipCounterMeasuresReqMsg( pMac, sessionId, bEnable, bssId ); + return (status); +} +eHalStatus +csrRoamGetAssociatedStas( tpAniSirGlobal pMac, tANI_U32 sessionId, + VOS_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, v_U8_t *pAssocStasBuf ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (!pSession) + { + smsLog( pMac, LOGE, "csrRoamGetAssociatedStas:CSR Session not found"); + return (status); + } + if(pSession->pConnectBssDesc) + { + vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid)); + } + else + { + smsLog( pMac, LOGE, "csrRoamGetAssociatedStas:Connected BSS Description in CSR Session not found"); + return (status); + } + smsLog( pMac, LOG2, "CSR getting associated stations for Bssid = "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssId)); + status = csrSendMBGetAssociatedStasReqMsg( pMac, sessionId, modId, bssId, pUsrContext, pfnSapEventCallback, pAssocStasBuf ); + return (status); +} +eHalStatus +csrRoamGetWpsSessionOverlap( tpAniSirGlobal pMac, tANI_U32 sessionId, + void *pUsrContext, void *pfnSapEventCallback, v_MACADDR_t pRemoveMac ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (!pSession) + { + smsLog( pMac, LOGE, "csrRoamGetWpsSessionOverlap:CSR Session not found"); + return (status); + } + if(pSession->pConnectBssDesc) + { + vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid)); + } + else + { + smsLog( pMac, LOGE, "csrRoamGetWpsSessionOverlap:Connected BSS Description in CSR Session not found"); + return (status); + } + smsLog( pMac, LOG2, "CSR getting WPS Session Overlap for Bssid = "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssId)); + + status = csrSendMBGetWPSPBCSessions( pMac, sessionId, bssId, pUsrContext, pfnSapEventCallback, pRemoveMac); + + return (status); +} +eHalStatus csrRoamIssueDeauth( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pSession->pConnectBssDesc) + { + vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid)); + } + smsLog( pMac, LOG2, "CSR Attempting to Deauth Bssid= "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssId)); + csrRoamSubstateChange( pMac, NewSubstate, sessionId); + + status = csrSendMBDeauthReqMsg( pMac, sessionId, bssId, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON ); + if (HAL_STATUS_SUCCESS(status)) + csrRoamLinkDown(pMac, sessionId); + else + { + smsLog(pMac, LOGE, FL("csrSendMBDeauthReqMsg failed with status %d Session ID: %d" + MAC_ADDRESS_STR ), status, sessionId, MAC_ADDR_ARRAY(bssId)); + } + + return (status); +} + +eHalStatus csrRoamSaveConnectedBssDesc( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDesc ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tANI_U32 size; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + // If no BSS description was found in this connection (happens with start IBSS), then + // nix the BSS description that we keep around for the connected BSS) and get out... + if(NULL == pBssDesc) + { + csrFreeConnectBssDesc(pMac, sessionId); + } + else + { + size = pBssDesc->length + sizeof( pBssDesc->length ); + if(NULL != pSession->pConnectBssDesc) + { + if(((pSession->pConnectBssDesc->length) + sizeof(pSession->pConnectBssDesc->length)) < size) + { + //not enough room for the new BSS, pMac->roam.pConnectBssDesc is freed inside + csrFreeConnectBssDesc(pMac, sessionId); + } + } + if(NULL == pSession->pConnectBssDesc) + { + pSession->pConnectBssDesc = vos_mem_malloc(size); + } + if (NULL == pSession->pConnectBssDesc) + status = eHAL_STATUS_FAILURE; + else + vos_mem_copy(pSession->pConnectBssDesc, pBssDesc, size); + } + return (status); +} + +eHalStatus csrRoamPrepareBssConfig(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig, + tDot11fBeaconIEs *pIes) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + eCsrCfgDot11Mode cfgDot11Mode; + VOS_ASSERT( pIes != NULL ); + if (pIes == NULL) + return eHAL_STATUS_FAILURE; + + do + { + vos_mem_copy(&pBssConfig->BssCap, &pBssDesc->capabilityInfo, + sizeof(tSirMacCapabilityInfo)); + //get qos + pBssConfig->qosType = csrGetQoSFromBssDesc(pMac, pBssDesc, pIes); + //get SSID + if(pIes->SSID.present) + { + vos_mem_copy(&pBssConfig->SSID.ssId, pIes->SSID.ssid, pIes->SSID.num_ssid); + pBssConfig->SSID.length = pIes->SSID.num_ssid; + } + else + pBssConfig->SSID.length = 0; + if(csrIsNULLSSID(pBssConfig->SSID.ssId, pBssConfig->SSID.length)) + { + smsLog(pMac, LOGW, "BSS desc SSID is a wild card"); + //Return failed if profile doesn't have an SSID either. + if(pProfile->SSIDs.numOfSSIDs == 0) + { + smsLog(pMac, LOGW, " Both BSS desc and profile doesn't have SSID"); + status = eHAL_STATUS_FAILURE; + break; + } + } + if(CSR_IS_CHANNEL_5GHZ(pBssDesc->channelId)) + { + pBssConfig->eBand = eCSR_BAND_5G; + } + else + { + pBssConfig->eBand = eCSR_BAND_24; + } + //phymode + if(csrIsPhyModeMatch( pMac, pProfile->phyMode, pBssDesc, pProfile, &cfgDot11Mode, pIes )) + { + pBssConfig->uCfgDot11Mode = cfgDot11Mode; + } + else + { + smsLog(pMac, LOGW, " Can not find match phy mode"); + //force it + if(eCSR_BAND_24 == pBssConfig->eBand) + { + pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + } + else + { + pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + } + } + //Qos + if ((pBssConfig->uCfgDot11Mode != eCSR_CFG_DOT11_MODE_11N) && + (pMac->roam.configParam.WMMSupportMode == eCsrRoamWmmNoQos)) + { + //Joining BSS is not 11n capable and WMM is disabled on client. + //Disable QoS and WMM + pBssConfig->qosType = eCSR_MEDIUM_ACCESS_DCF; + } + + if (((pBssConfig->uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11N) || + (pBssConfig->uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11AC)) && + ((pBssConfig->qosType != eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP) || + (pBssConfig->qosType != eCSR_MEDIUM_ACCESS_11e_HCF) || + (pBssConfig->qosType != eCSR_MEDIUM_ACCESS_11e_eDCF) )) + { + //Joining BSS is 11n capable and WMM is disabled on AP. + //Assume all HT AP's are QOS AP's and enable WMM + pBssConfig->qosType = eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP; + } + + //auth type + switch( pProfile->negotiatedAuthType ) + { + default: + case eCSR_AUTH_TYPE_WPA: + case eCSR_AUTH_TYPE_WPA_PSK: + case eCSR_AUTH_TYPE_WPA_NONE: + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + pBssConfig->authType = eSIR_OPEN_SYSTEM; + break; + case eCSR_AUTH_TYPE_SHARED_KEY: + pBssConfig->authType = eSIR_SHARED_KEY; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + pBssConfig->authType = eSIR_AUTO_SWITCH; + break; + } + //short slot time + if( eCSR_CFG_DOT11_MODE_11B != cfgDot11Mode ) + { + pBssConfig->uShortSlotTime = pMac->roam.configParam.shortSlotTime; + } + else + { + pBssConfig->uShortSlotTime = 0; + } + if(pBssConfig->BssCap.ibss) + { + //We don't support 11h on IBSS + pBssConfig->f11hSupport = eANI_BOOLEAN_FALSE; + } + else + { + pBssConfig->f11hSupport = pMac->roam.configParam.Is11hSupportEnabled; + } + //power constraint + pBssConfig->uPowerLimit = csrGet11hPowerConstraint(pMac, &pIes->PowerConstraints); + //heartbeat + if ( CSR_IS_11A_BSS( pBssDesc ) ) + { + pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh50; + } + else + { + pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh24; + } + //Join timeout + // if we find a BeaconInterval in the BssDescription, then set the Join Timeout to + // be 10 x the BeaconInterval. + if ( pBssDesc->beaconInterval ) + { + //Make sure it is bigger than the minimal + pBssConfig->uJoinTimeOut = CSR_ROAM_MAX(10 * pBssDesc->beaconInterval, CSR_JOIN_FAILURE_TIMEOUT_MIN); + } + else + { + pBssConfig->uJoinTimeOut = CSR_JOIN_FAILURE_TIMEOUT_DEFAULT; + } + //validate CB + pBssConfig->cbMode = csrGetCBModeFromIes(pMac, pBssDesc->channelId, pIes); + }while(0); + return (status); +} + +static eHalStatus csrRoamPrepareBssConfigFromProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + tBssConfigParam *pBssConfig, tSirBssDescription *pBssDesc) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U8 operationChannel = 0; + tANI_U8 qAPisEnabled = FALSE; + //SSID + pBssConfig->SSID.length = 0; + if(pProfile->SSIDs.numOfSSIDs) + { + //only use the first one + vos_mem_copy(&pBssConfig->SSID, &pProfile->SSIDs.SSIDList[0].SSID, + sizeof(tSirMacSSid)); + } + else + { + //SSID must present + return eHAL_STATUS_FAILURE; + } + /* Setting up the capabilities */ + if( csrIsBssTypeIBSS(pProfile->BSSType) ) + { + pBssConfig->BssCap.ibss = 1; + } + else + { + pBssConfig->BssCap.ess = 1; + } + if( eCSR_ENCRYPT_TYPE_NONE != pProfile->EncryptionType.encryptionType[0] ) + { + pBssConfig->BssCap.privacy = 1; + } + pBssConfig->eBand = pMac->roam.configParam.eBand; + //phymode + if(pProfile->ChannelInfo.ChannelList) + { + operationChannel = pProfile->ChannelInfo.ChannelList[0]; + } + pBssConfig->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, pProfile, operationChannel, + &pBssConfig->eBand); + //QOS + //Is this correct to always set to this //*** + if ( pBssConfig->BssCap.ess == 1 ) + { + /*For Softap case enable WMM*/ + if(CSR_IS_INFRA_AP(pProfile) && (eCsrRoamWmmNoQos != pMac->roam.configParam.WMMSupportMode )){ + qAPisEnabled = TRUE; + } + else + if (csrRoamGetQosInfoFromBss(pMac, pBssDesc) == eHAL_STATUS_SUCCESS) { + qAPisEnabled = TRUE; + } else { + qAPisEnabled = FALSE; + } + } else { + qAPisEnabled = TRUE; + } + if ((eCsrRoamWmmNoQos != pMac->roam.configParam.WMMSupportMode && + qAPisEnabled) || + ((eCSR_CFG_DOT11_MODE_11N == pBssConfig->uCfgDot11Mode && + qAPisEnabled))) { + pBssConfig->qosType = eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP; + } else { + pBssConfig->qosType = eCSR_MEDIUM_ACCESS_DCF; + } + + //auth type + switch( pProfile->AuthType.authType[0] ) //Take the preferred Auth type. + { + default: + case eCSR_AUTH_TYPE_WPA: + case eCSR_AUTH_TYPE_WPA_PSK: + case eCSR_AUTH_TYPE_WPA_NONE: + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + pBssConfig->authType = eSIR_OPEN_SYSTEM; + break; + case eCSR_AUTH_TYPE_SHARED_KEY: + pBssConfig->authType = eSIR_SHARED_KEY; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + pBssConfig->authType = eSIR_AUTO_SWITCH; + break; + } + //short slot time + if( WNI_CFG_PHY_MODE_11B != pBssConfig->uCfgDot11Mode ) + { + pBssConfig->uShortSlotTime = pMac->roam.configParam.shortSlotTime; + } + else + { + pBssConfig->uShortSlotTime = 0; + } + //power constraint. We don't support 11h on IBSS + pBssConfig->f11hSupport = eANI_BOOLEAN_FALSE; + pBssConfig->uPowerLimit = 0; + //heartbeat + if ( eCSR_BAND_5G == pBssConfig->eBand ) + { + pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh50; + } + else + { + pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh24; + } + //Join timeout + pBssConfig->uJoinTimeOut = CSR_JOIN_FAILURE_TIMEOUT_DEFAULT; + + return (status); +} +static eHalStatus csrRoamGetQosInfoFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tDot11fBeaconIEs *pIes = NULL; + + do + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes))) + { + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "csrRoamGetQosInfoFromBss() failed"); + break; + } + //check if the AP is QAP & it supports APSD + if( CSR_IS_QOS_BSS(pIes) ) + { + status = eHAL_STATUS_SUCCESS; + } + } while (0); + + if (NULL != pIes) + { + vos_mem_free(pIes); + } + + return status; +} + +void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOLEAN fPrivacy ) +{ + // !! Note: the only difference between this function and the csrSetCfgPrivacyFromProfile() is the + // setting of the privacy CFG based on the advertised privacy setting from the AP for WPA associations. + // See !!Note: below in this function... + tANI_U32 PrivacyEnabled = 0; + tANI_U32 RsnEnabled = 0; + tANI_U32 WepDefaultKeyId = 0; + tANI_U32 WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_5; /* default 40 bits */ + tANI_U32 Key0Length = 0; + tANI_U32 Key1Length = 0; + tANI_U32 Key2Length = 0; + tANI_U32 Key3Length = 0; + + // Reserve for the biggest key + tANI_U8 Key0[ WNI_CFG_WEP_DEFAULT_KEY_1_LEN ]; + tANI_U8 Key1[ WNI_CFG_WEP_DEFAULT_KEY_2_LEN ]; + tANI_U8 Key2[ WNI_CFG_WEP_DEFAULT_KEY_3_LEN ]; + tANI_U8 Key3[ WNI_CFG_WEP_DEFAULT_KEY_4_LEN ]; + + switch ( pProfile->negotiatedUCEncryptionType ) + { + case eCSR_ENCRYPT_TYPE_NONE: + + // for NO encryption, turn off Privacy and Rsn. + PrivacyEnabled = 0; + RsnEnabled = 0; + + // WEP key length and Wep Default Key ID don't matter in this case.... + + // clear out the WEP keys that may be hanging around. + Key0Length = 0; + Key1Length = 0; + Key2Length = 0; + Key3Length = 0; + + break; + + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + + // Privacy is ON. NO RSN for Wep40 static key. + PrivacyEnabled = 1; + RsnEnabled = 0; + + // Set the Wep default key ID. + WepDefaultKeyId = pProfile->Keys.defaultIndex; + // Wep key size if 5 bytes (40 bits). + WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_5; + + // set encryption keys in the CFG database or clear those that are not present in this profile. + if ( pProfile->Keys.KeyLength[0] ) + { + vos_mem_copy(Key0, pProfile->Keys.KeyMaterial[0], + WNI_CFG_WEP_KEY_LENGTH_5); + Key0Length = WNI_CFG_WEP_KEY_LENGTH_5; + } + else + { + Key0Length = 0; + } + + if ( pProfile->Keys.KeyLength[1] ) + { + vos_mem_copy(Key1, pProfile->Keys.KeyMaterial[1], + WNI_CFG_WEP_KEY_LENGTH_5); + Key1Length = WNI_CFG_WEP_KEY_LENGTH_5; + } + else + { + Key1Length = 0; + } + + if ( pProfile->Keys.KeyLength[2] ) + { + vos_mem_copy(Key2, pProfile->Keys.KeyMaterial[2], + WNI_CFG_WEP_KEY_LENGTH_5); + Key2Length = WNI_CFG_WEP_KEY_LENGTH_5; + } + else + { + Key2Length = 0; + } + + if ( pProfile->Keys.KeyLength[3] ) + { + vos_mem_copy(Key3, pProfile->Keys.KeyMaterial[3], + WNI_CFG_WEP_KEY_LENGTH_5); + Key3Length = WNI_CFG_WEP_KEY_LENGTH_5; + } + else + { + Key3Length = 0; + } + break; + + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104: + + // Privacy is ON. NO RSN for Wep40 static key. + PrivacyEnabled = 1; + RsnEnabled = 0; + + // Set the Wep default key ID. + WepDefaultKeyId = pProfile->Keys.defaultIndex; + + // Wep key size if 13 bytes (104 bits). + WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_13; + + // set encryption keys in the CFG database or clear those that are not present in this profile. + if ( pProfile->Keys.KeyLength[0] ) + { + vos_mem_copy(Key0, pProfile->Keys.KeyMaterial[ 0 ], + WNI_CFG_WEP_KEY_LENGTH_13); + Key0Length = WNI_CFG_WEP_KEY_LENGTH_13; + } + else + { + Key0Length = 0; + } + + if ( pProfile->Keys.KeyLength[1] ) + { + vos_mem_copy(Key1, pProfile->Keys.KeyMaterial[ 1 ], + WNI_CFG_WEP_KEY_LENGTH_13); + Key1Length = WNI_CFG_WEP_KEY_LENGTH_13; + } + else + { + Key1Length = 0; + } + + if ( pProfile->Keys.KeyLength[2] ) + { + vos_mem_copy(Key2, pProfile->Keys.KeyMaterial[ 2 ], + WNI_CFG_WEP_KEY_LENGTH_13); + Key2Length = WNI_CFG_WEP_KEY_LENGTH_13; + } + else + { + Key2Length = 0; + } + + if ( pProfile->Keys.KeyLength[3] ) + { + vos_mem_copy(Key3, pProfile->Keys.KeyMaterial[ 3 ], + WNI_CFG_WEP_KEY_LENGTH_13); + Key3Length = WNI_CFG_WEP_KEY_LENGTH_13; + } + else + { + Key3Length = 0; + } + + break; + + case eCSR_ENCRYPT_TYPE_TKIP: + case eCSR_ENCRYPT_TYPE_AES: +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: +#endif /* FEATURE_WLAN_WAPI */ + // !! Note: this is the only difference between this function and the csrSetCfgPrivacyFromProfile() + // (setting of the privacy CFG based on the advertised privacy setting from the AP for WPA/WAPI associations ). + PrivacyEnabled = (0 != fPrivacy); + + // turn on RSN enabled for WPA associations + RsnEnabled = 1; + + // WEP key length and Wep Default Key ID don't matter in this case.... + + // clear out the static WEP keys that may be hanging around. + Key0Length = 0; + Key1Length = 0; + Key2Length = 0; + Key3Length = 0; + + break; + default: + PrivacyEnabled = 0; + RsnEnabled = 0; + break; + } + + ccmCfgSetInt(pMac, WNI_CFG_PRIVACY_ENABLED, PrivacyEnabled, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_RSN_ENABLED, RsnEnabled, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_1, Key0, Key0Length, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_2, Key1, Key1Length, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_3, Key2, Key2Length, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_4, Key3, Key3Length, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_WEP_KEY_LENGTH, WepKeyLength, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, WepDefaultKeyId, NULL, eANI_BOOLEAN_FALSE); +} + +static void csrSetCfgSsid( tpAniSirGlobal pMac, tSirMacSSid *pSSID ) +{ + tANI_U32 len = 0; + if(pSSID->length <= WNI_CFG_SSID_LEN) + { + len = pSSID->length; + } + ccmCfgSetStr(pMac, WNI_CFG_SSID, (tANI_U8 *)pSSID->ssId, len, NULL, eANI_BOOLEAN_FALSE); +} + +eHalStatus csrSetQosToCfg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrMediaAccessType qosType ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 QoSEnabled; + tANI_U32 WmeEnabled; + // set the CFG enable/disable variables based on the qosType being configured... + switch( qosType ) + { + case eCSR_MEDIUM_ACCESS_WMM_eDCF_802dot1p: + QoSEnabled = FALSE; + WmeEnabled = TRUE; + break; + case eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP: + QoSEnabled = FALSE; + WmeEnabled = TRUE; + break; + case eCSR_MEDIUM_ACCESS_WMM_eDCF_NoClassify: + QoSEnabled = FALSE; + WmeEnabled = TRUE; + break; + case eCSR_MEDIUM_ACCESS_11e_eDCF: + QoSEnabled = TRUE; + WmeEnabled = FALSE; + break; + case eCSR_MEDIUM_ACCESS_11e_HCF: + QoSEnabled = TRUE; + WmeEnabled = FALSE; + break; + default: + case eCSR_MEDIUM_ACCESS_DCF: + QoSEnabled = FALSE; + WmeEnabled = FALSE; + break; + } + //save the WMM setting for later use + pMac->roam.roamSession[sessionId].fWMMConnection = (tANI_BOOLEAN)WmeEnabled; + pMac->roam.roamSession[sessionId].fQOSConnection = (tANI_BOOLEAN)QoSEnabled; + return (status); +} +static eHalStatus csrGetRateSet( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes, tSirMacRateSet *pOpRateSet, tSirMacRateSet *pExRateSet) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + int i; + eCsrCfgDot11Mode cfgDot11Mode; + tANI_U8 *pDstRate; + tANI_U16 rateBitmap = 0; + vos_mem_set(pOpRateSet, sizeof(tSirMacRateSet), 0); + vos_mem_set(pExRateSet, sizeof(tSirMacRateSet), 0); + VOS_ASSERT( pIes != NULL ); + + if( NULL != pIes ) + { + csrIsPhyModeMatch( pMac, phyMode, pBssDesc, pProfile, &cfgDot11Mode, pIes ); + // Originally, we thought that for 11a networks, the 11a rates are always + // in the Operational Rate set & for 11b and 11g networks, the 11b rates + // appear in the Operational Rate set. Consequently, in either case, we + // would blindly put the rates we support into our Operational Rate set + // (including the basic rates, which we have already verified are + // supported earlier in the roaming decision). + // However, it turns out that this is not always the case. Some AP's + // (e.g. D-Link DI-784) ram 11g rates into the Operational Rate set, + // too. Now, we're a little more careful: + pDstRate = pOpRateSet->rate; + if(pIes->SuppRates.present) + { + for ( i = 0; i < pIes->SuppRates.num_rates; i++ ) + { + if (csrRatesIsDot11RateSupported(pMac, + pIes->SuppRates.rates[i])) { + if (!csrCheckRateBitmap(pIes->SuppRates.rates[i], rateBitmap)) { + csrAddRateBitmap(pIes->SuppRates.rates[i], &rateBitmap); + *pDstRate++ = pIes->SuppRates.rates[i]; + pOpRateSet->numRates++; + } + } + } + } + if ( eCSR_CFG_DOT11_MODE_11G == cfgDot11Mode || + eCSR_CFG_DOT11_MODE_11N == cfgDot11Mode || + eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode +#ifdef WLAN_FEATURE_11AC + || eCSR_CFG_DOT11_MODE_11AC == cfgDot11Mode +#endif + ) + { + // If there are Extended Rates in the beacon, we will reflect those + // extended rates that we support in out Extended Operational Rate + // set: + pDstRate = pExRateSet->rate; + if(pIes->ExtSuppRates.present) + { + for ( i = 0; i < pIes->ExtSuppRates.num_rates; i++ ) + { + if ( csrRatesIsDot11RateSupported( pMac, pIes->ExtSuppRates.rates[ i ] ) ) + { + if (!csrCheckRateBitmap(pIes->ExtSuppRates.rates[ i ], rateBitmap)) + { + *pDstRate++ = pIes->ExtSuppRates.rates[ i ]; + pExRateSet->numRates++; + } + } + } + } + } + }//Parsing BSSDesc + else + { + smsLog(pMac, LOGE, FL("failed to parse BssDesc")); + } + if (pOpRateSet->numRates > 0 || pExRateSet->numRates > 0) status = eHAL_STATUS_SUCCESS; + return status; +} + +static void csrSetCfgRateSet( tpAniSirGlobal pMac, eCsrPhyMode phyMode, tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes) +{ + int i; + tANI_U8 *pDstRate; + eCsrCfgDot11Mode cfgDot11Mode; + tANI_U8 OperationalRates[ CSR_DOT11_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates + tANI_U32 OperationalRatesLength = 0; + tANI_U8 ExtendedOperationalRates[ CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates + tANI_U32 ExtendedOperationalRatesLength = 0; + tANI_U8 MCSRateIdxSet[ SIZE_OF_SUPPORTED_MCS_SET ]; + tANI_U32 MCSRateLength = 0; + VOS_ASSERT( pIes != NULL ); + if( NULL != pIes ) + { + csrIsPhyModeMatch( pMac, phyMode, pBssDesc, pProfile, &cfgDot11Mode, pIes ); + // Originally, we thought that for 11a networks, the 11a rates are always + // in the Operational Rate set & for 11b and 11g networks, the 11b rates + // appear in the Operational Rate set. Consequently, in either case, we + // would blindly put the rates we support into our Operational Rate set + // (including the basic rates, which we have already verified are + // supported earlier in the roaming decision). + // However, it turns out that this is not always the case. Some AP's + // (e.g. D-Link DI-784) ram 11g rates into the Operational Rate set, + // too. Now, we're a little more careful: + pDstRate = OperationalRates; + if(pIes->SuppRates.present) + { + for ( i = 0; i < pIes->SuppRates.num_rates; i++ ) + { + if ( csrRatesIsDot11RateSupported( pMac, pIes->SuppRates.rates[ i ] ) && + ( OperationalRatesLength < CSR_DOT11_SUPPORTED_RATES_MAX )) + { + *pDstRate++ = pIes->SuppRates.rates[ i ]; + OperationalRatesLength++; + } + } + } + if (eCSR_CFG_DOT11_MODE_11G == cfgDot11Mode || + eCSR_CFG_DOT11_MODE_11N == cfgDot11Mode || + eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode) { + // If there are Extended Rates in the beacon, we will reflect those + // extended rates that we support in out Extended Operational Rate + // set: + pDstRate = ExtendedOperationalRates; + if(pIes->ExtSuppRates.present) + { + for ( i = 0; i < pIes->ExtSuppRates.num_rates; i++ ) + { + if ( csrRatesIsDot11RateSupported( pMac, pIes->ExtSuppRates.rates[ i ] ) && + ( ExtendedOperationalRatesLength < CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX )) + { + *pDstRate++ = pIes->ExtSuppRates.rates[ i ]; + ExtendedOperationalRatesLength++; + } + } + } + } + /* Get MCS Rate */ + pDstRate = MCSRateIdxSet; + if ( pIes->HTCaps.present ) + { + for ( i = 0; i < VALID_MAX_MCS_INDEX; i++ ) + { + if ( (unsigned int)pIes->HTCaps.supportedMCSSet[0] & (1 << i) ) + { + MCSRateLength++; + *pDstRate++ = i; + } + } + } + // Set the operational rate set CFG variables... + ccmCfgSetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, + OperationalRatesLength, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedOperationalRates, + ExtendedOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_CURRENT_MCS_SET, MCSRateIdxSet, + MCSRateLength, NULL, eANI_BOOLEAN_FALSE); + }//Parsing BSSDesc + else + { + smsLog(pMac, LOGE, FL("failed to parse BssDesc")); + } +} + +static void csrSetCfgRateSetFromProfile( tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile ) +{ + tSirMacRateSetIE DefaultSupportedRates11a = { SIR_MAC_RATESET_EID, + { 8, + { SIR_MAC_RATE_6, + SIR_MAC_RATE_9, + SIR_MAC_RATE_12, + SIR_MAC_RATE_18, + SIR_MAC_RATE_24, + SIR_MAC_RATE_36, + SIR_MAC_RATE_48, + SIR_MAC_RATE_54 } } }; + tSirMacRateSetIE DefaultSupportedRates11b = { SIR_MAC_RATESET_EID, + { 4, + { SIR_MAC_RATE_1, + SIR_MAC_RATE_2, + SIR_MAC_RATE_5_5, + SIR_MAC_RATE_11 } } }; + + + tSirMacPropRateSet DefaultSupportedPropRates = { 3, + { SIR_MAC_RATE_72, + SIR_MAC_RATE_96, + SIR_MAC_RATE_108 } }; + eCsrCfgDot11Mode cfgDot11Mode; + eCsrBand eBand; + tANI_U8 OperationalRates[ CSR_DOT11_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates + tANI_U32 OperationalRatesLength = 0; + tANI_U8 ExtendedOperationalRates[ CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates + tANI_U32 ExtendedOperationalRatesLength = 0; + tANI_U8 ProprietaryOperationalRates[ 4 ]; // leave enough room for the max number of proprietary rates + tANI_U32 ProprietaryOperationalRatesLength = 0; + tANI_U32 PropRatesEnable = 0; + tANI_U8 operationChannel = 0; + if(pProfile->ChannelInfo.ChannelList) + { + operationChannel = pProfile->ChannelInfo.ChannelList[0]; + } + cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, pProfile, operationChannel, &eBand ); + // For 11a networks, the 11a rates go into the Operational Rate set. For 11b and 11g + // networks, the 11b rates appear in the Operational Rate set. In either case, + // we can blindly put the rates we support into our Operational Rate set + // (including the basic rates, which we have already verified are supported + // earlier in the roaming decision). + if ( eCSR_BAND_5G == eBand ) + { + // 11a rates into the Operational Rate Set. + OperationalRatesLength = DefaultSupportedRates11a.supportedRateSet.numRates * + sizeof(*DefaultSupportedRates11a.supportedRateSet.rate); + vos_mem_copy(OperationalRates, + DefaultSupportedRates11a.supportedRateSet.rate, + OperationalRatesLength); + + // Nothing in the Extended rate set. + ExtendedOperationalRatesLength = 0; + // populate proprietary rates if user allows them + if ( pMac->roam.configParam.ProprietaryRatesEnabled ) + { + ProprietaryOperationalRatesLength = DefaultSupportedPropRates.numPropRates * + sizeof(*DefaultSupportedPropRates.propRate); + vos_mem_copy(ProprietaryOperationalRates, + DefaultSupportedPropRates.propRate, + ProprietaryOperationalRatesLength); + } + else + { + // No proprietary modes + ProprietaryOperationalRatesLength = 0; + } + } + else if ( eCSR_CFG_DOT11_MODE_11B == cfgDot11Mode ) + { + // 11b rates into the Operational Rate Set. + OperationalRatesLength = DefaultSupportedRates11b.supportedRateSet.numRates * + sizeof(*DefaultSupportedRates11b.supportedRateSet.rate); + vos_mem_copy(OperationalRates, + DefaultSupportedRates11b.supportedRateSet.rate, + OperationalRatesLength); + // Nothing in the Extended rate set. + ExtendedOperationalRatesLength = 0; + // No proprietary modes + ProprietaryOperationalRatesLength = 0; + } + else + { + // 11G + + // 11b rates into the Operational Rate Set. + OperationalRatesLength = DefaultSupportedRates11b.supportedRateSet.numRates * + sizeof(*DefaultSupportedRates11b.supportedRateSet.rate); + vos_mem_copy(OperationalRates, + DefaultSupportedRates11b.supportedRateSet.rate, + OperationalRatesLength); + + // 11a rates go in the Extended rate set. + ExtendedOperationalRatesLength = DefaultSupportedRates11a.supportedRateSet.numRates * + sizeof(*DefaultSupportedRates11a.supportedRateSet.rate); + vos_mem_copy(ExtendedOperationalRates, + DefaultSupportedRates11a.supportedRateSet.rate, + ExtendedOperationalRatesLength); + + // populate proprietary rates if user allows them + if ( pMac->roam.configParam.ProprietaryRatesEnabled ) + { + ProprietaryOperationalRatesLength = DefaultSupportedPropRates.numPropRates * + sizeof(*DefaultSupportedPropRates.propRate); + vos_mem_copy(ProprietaryOperationalRates, + DefaultSupportedPropRates.propRate, + ProprietaryOperationalRatesLength); + } + else + { + // No proprietary modes + ProprietaryOperationalRatesLength = 0; + } + } + // set this to 1 if prop. rates need to be advertised in to the IBSS beacon and user wants to use them + if ( ProprietaryOperationalRatesLength && pMac->roam.configParam.ProprietaryRatesEnabled ) + { + PropRatesEnable = 1; + } + else + { + PropRatesEnable = 0; + } + + // Set the operational rate set CFG variables... + ccmCfgSetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, + OperationalRatesLength, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedOperationalRates, + ExtendedOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetStr(pMac, WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET, + ProprietaryOperationalRates, + ProprietaryOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE); +} +void csrRoamCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + tListElem *pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + tANI_U32 sessionId; + tSmeCmd *pCommand = NULL; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tCsrRoamSession *pSession = NULL; +#endif + if(NULL == pEntry) + { + smsLog(pMac, LOGW, " CFG_CNF with active list empty"); + return; + } + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sessionId = pCommand->sessionId; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pSession = &pMac->roam.roamSession[sessionId]; + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR3:csrRoamCcmCfgSetCallback"); + } +#endif + + if(CSR_IS_ROAM_JOINING(pMac, sessionId) && CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId)) + { + csrRoamingStateConfigCnfProcessor(pMac, (tANI_U32)result); + } +} + +//This function is very dump. It is here because PE still need WNI_CFG_PHY_MODE +tANI_U32 csrRoamGetPhyModeFromDot11Mode(eCsrCfgDot11Mode dot11Mode, eCsrBand band) +{ + if(eCSR_CFG_DOT11_MODE_11B == dot11Mode) + { + return (WNI_CFG_PHY_MODE_11B); + } + else + { + if(eCSR_BAND_24 == band) + return (WNI_CFG_PHY_MODE_11G); + } + return (WNI_CFG_PHY_MODE_11A); +} + + +#ifdef WLAN_FEATURE_11AC +ePhyChanBondState csrGetHTCBStateFromVHTCBState(ePhyChanBondState aniCBMode) +{ + switch ( aniCBMode ) + { + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + return PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: + default : + return PHY_SINGLE_CHANNEL_CENTERED; + } +} +#endif + +//pIes may be NULL +eHalStatus csrRoamSetBssConfigCfg(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig, + tDot11fBeaconIEs *pIes, tANI_BOOLEAN resetCountry) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + tANI_U8 channel = 0; + //Make sure we have the domain info for the BSS we try to connect to. + //Do we need to worry about sequence for OSs that are not Windows?? + if (pBssDesc) + { + if (csrLearnCountryInformation(pMac, pBssDesc, pIes, eANI_BOOLEAN_TRUE)) + { + //Make sure the 11d info from this BSSDesc can be applied + pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE; + if (VOS_TRUE == resetCountry) + { + csrApplyCountryInformation(pMac, FALSE); + } + else + { + csrApplyCountryInformation(pMac, TRUE); + } + } + if ((csrIs11dSupported (pMac)) && pIes) + { + if (!pIes->Country.present) + { + csrResetCountryInformation(pMac, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE ); + } + else + { + //Let's also update the below to make sure we don't update CC while + //connected to an AP which is advertising some CC + vos_mem_copy(pMac->scan.currentCountryBssid, + pBssDesc->bssId, sizeof(tSirMacAddr)); + } + } + } + //Qos + csrSetQosToCfg( pMac, sessionId, pBssConfig->qosType ); + //SSID + csrSetCfgSsid(pMac, &pBssConfig->SSID ); + + //Auth type + ccmCfgSetInt(pMac, WNI_CFG_AUTHENTICATION_TYPE, pBssConfig->authType, NULL, eANI_BOOLEAN_FALSE); + //encryption type + csrSetCfgPrivacy(pMac, pProfile, (tANI_BOOLEAN)pBssConfig->BssCap.privacy ); + //short slot time + ccmCfgSetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, pBssConfig->uShortSlotTime, NULL, eANI_BOOLEAN_FALSE); + //11d + ccmCfgSetInt(pMac, WNI_CFG_11D_ENABLED, + ((pBssConfig->f11hSupport) ? pBssConfig->f11hSupport : pProfile->ieee80211d), + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, pBssConfig->uPowerLimit, NULL, eANI_BOOLEAN_FALSE); + //CB + + if (CSR_IS_INFRA_AP(pProfile) || CSR_IS_WDS_AP(pProfile) || + CSR_IS_IBSS(pProfile)) { + channel = pProfile->operationChannel; + } + else + { + if(pBssDesc) + { + channel = pBssDesc->channelId; + } + } + if(0 != channel) + { + if(CSR_IS_CHANNEL_24GHZ(channel)) + {//for now if we are on 2.4 Ghz, CB will be always disabled + cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + } + else + { + cfgCb = pBssConfig->cbMode; + } + } + + //Rate + //Fixed Rate + if(pBssDesc) + { + csrSetCfgRateSet(pMac, (eCsrPhyMode)pProfile->phyMode, pProfile, pBssDesc, pIes); + } + else + { + csrSetCfgRateSetFromProfile(pMac, pProfile); + } + //Make this the last CFG to set. The callback will trigger a join_req + //Join time out + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_CONFIG, sessionId ); + + ccmCfgSetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, pBssConfig->uJoinTimeOut, (tCcmCfgSetCallback)csrRoamCcmCfgSetCallback, eANI_BOOLEAN_FALSE); + return (status); +} + +eHalStatus csrRoamStopNetwork( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes) +{ + eHalStatus status; + tBssConfigParam *pBssConfig; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + pBssConfig = vos_mem_malloc(sizeof(tBssConfigParam)); + if ( NULL == pBssConfig ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pBssConfig, sizeof(tBssConfigParam), 0); + status = csrRoamPrepareBssConfig(pMac, pProfile, pBssDesc, pBssConfig, pIes); + if(HAL_STATUS_SUCCESS(status)) + { + pSession->bssParams.uCfgDot11Mode = pBssConfig->uCfgDot11Mode; + /* This will allow to pass cbMode during join req */ + pSession->bssParams.cbMode= pBssConfig->cbMode; + //For IBSS, we need to prepare some more information + if( csrIsBssTypeIBSS(pProfile->BSSType) || CSR_IS_WDS( pProfile ) + || CSR_IS_INFRA_AP(pProfile) + ) + { + csrRoamPrepareBssParams(pMac, sessionId, pProfile, pBssDesc, pBssConfig, pIes); + } + // If we are in an IBSS, then stop the IBSS... + ////Not worry about WDS connection for now + if ( csrIsConnStateIbss( pMac, sessionId ) ) + { + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING ); + } + else + { + // if we are in an Infrastructure association.... + if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + // and the new Bss is an Ibss OR we are roaming from Infra to Infra + // across SSIDs (roaming to a new SSID)... // + //Not worry about WDS connection for now + if ( pBssDesc && ( ( csrIsIbssBssDesc( pBssDesc ) ) || + !csrIsSsidEqual( pMac, pSession->pConnectBssDesc, pBssDesc, pIes ) ) ) + { + // then we need to disassociate from the Infrastructure network... + status = csrRoamIssueDisassociate( pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE ); + } + else + { + /* + * In an Infrastructure and going to an Infrastructure + * network with the same SSID. This calls for a + * Reassociation sequence. So issue the CFG + * sets for this new AP. + */ + if ( pBssDesc ) + { + // Set parameters for this Bss. + status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, + pBssDesc, pBssConfig, + pIes, eANI_BOOLEAN_FALSE); + } + } + } + else + { + /* + * Neither in IBSS nor in Infra. We can go ahead + * and set the CFG for the new network. Nothing to stop + */ + if ( pBssDesc || CSR_IS_WDS_AP( pProfile ) + || CSR_IS_INFRA_AP(pProfile) + ) + { + tANI_BOOLEAN is11rRoamingFlag = eANI_BOOLEAN_FALSE; + is11rRoamingFlag = csrRoamIs11rAssoc(pMac, sessionId); + // Set parameters for this Bss. + status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, + pBssDesc, pBssConfig, + pIes, is11rRoamingFlag); + } + } + } + }//Success getting BSS config info + vos_mem_free(pBssConfig); + }//Allocate memory + return (status); +} + +eCsrJoinState csrRoamJoin( tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrScanResultInfo *pScanResult, tCsrRoamProfile *pProfile ) +{ + eCsrJoinState eRoamState = eCsrContinueRoaming; + eHalStatus status; + tSirBssDescription *pBssDesc = &pScanResult->BssDescriptor; + tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)( pScanResult->pvIes ); //This may be NULL + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return (eCsrStopRoaming); + } + + if( CSR_IS_WDS_STA( pProfile ) ) + { + status = csrRoamStartWds( pMac, sessionId, pProfile, pBssDesc ); + if( !HAL_STATUS_SUCCESS( status ) ) + { + eRoamState = eCsrStopRoaming; + } + } + else + { + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" fail to parse IEs")); + return (eCsrStopRoaming); + } + if ( csrIsInfraBssDesc( pBssDesc ) ) + { + // If we are connected in infrastructure mode and the Join Bss description is for the same BssID, then we are + // attempting to join the AP we are already connected with. In that case, see if the Bss or Sta capabilities + // have changed and handle the changes (without disturbing the current association). + + if ( csrIsConnStateConnectedInfra(pMac, sessionId) && + csrIsBssIdEqual( pMac, pBssDesc, pSession->pConnectBssDesc ) && + csrIsSsidEqual( pMac, pSession->pConnectBssDesc, pBssDesc, pIesLocal ) + ) + { + /* + * Check to see if the Auth type has changed in the Profile. + * If so, we don't want to Reassociate with Authenticating first. + * To force this, stop the current association (Disassociate) and + * then re 'Join' the AP, which will force an Authentication + * (with the new Auth type) followed by a new Association. + */ + if(csrIsSameProfile(pMac, &pSession->connectedProfile, pProfile)) + { + smsLog(pMac, LOGW, FL(" detect same profile")); + if(csrRoamIsSameProfileKeys(pMac, &pSession->connectedProfile, pProfile)) + { + eRoamState = eCsrReassocToSelfNoCapChange; + } + else + { + tBssConfigParam bssConfig; + //The key changes + vos_mem_set(&bssConfig, sizeof(bssConfig), 0); + status = csrRoamPrepareBssConfig(pMac, pProfile, pBssDesc, &bssConfig, pIesLocal); + if(HAL_STATUS_SUCCESS(status)) + { + pSession->bssParams.uCfgDot11Mode = bssConfig.uCfgDot11Mode; + pSession->bssParams.cbMode = bssConfig.cbMode; + //Reapply the config including Keys so reassoc is happening. + status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, + pBssDesc, &bssConfig, + pIesLocal, eANI_BOOLEAN_FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + eRoamState = eCsrStopRoaming; + } + } + else + { + eRoamState = eCsrStopRoaming; + } + }//same profile + } + else + { + if(!HAL_STATUS_SUCCESS(csrRoamIssueDisassociate( pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISASSOC_REQ, FALSE ))) + { + smsLog(pMac, LOGE, FL(" fail to issue disassociate with Session ID %d"), + sessionId); + eRoamState = eCsrStopRoaming; + } + } + } + else + { + // note: we used to pre-auth here with open authentication networks but that was not working so well. + // + // stop the existing network before attempting to join the new network... + if(!HAL_STATUS_SUCCESS(csrRoamStopNetwork(pMac, sessionId, pProfile, pBssDesc, pIesLocal))) + { + eRoamState = eCsrStopRoaming; + } + } + }//Infra + else + { + if(!HAL_STATUS_SUCCESS(csrRoamStopNetwork(pMac, sessionId, pProfile, pBssDesc, pIesLocal))) + { + eRoamState = eCsrStopRoaming; + } + } + if( pIesLocal && !pScanResult->pvIes ) + { + vos_mem_free(pIesLocal); + } + } + return( eRoamState ); +} + +eHalStatus csrRoamShouldRoam(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirBssDescription *pBssDesc, tANI_U32 roamId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo roamInfo; + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pBssDesc; + status = csrRoamCallCallback(pMac, sessionId, &roamInfo, roamId, eCSR_ROAM_SHOULD_ROAM, eCSR_ROAM_RESULT_NONE); + return (status); +} +//In case no matching BSS is found, use whatever default we can find +static void csrRoamAssignDefaultParam( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + //Need to get all negotiated types in place first + //auth type + switch( pCommand->u.roamCmd.roamProfile.AuthType.authType[0] ) //Take the preferred Auth type. + { + default: + case eCSR_AUTH_TYPE_WPA: + case eCSR_AUTH_TYPE_WPA_PSK: + case eCSR_AUTH_TYPE_WPA_NONE: + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + pCommand->u.roamCmd.roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + break; + + case eCSR_AUTH_TYPE_SHARED_KEY: + pCommand->u.roamCmd.roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_SHARED_KEY; + break; + + case eCSR_AUTH_TYPE_AUTOSWITCH: + pCommand->u.roamCmd.roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_AUTOSWITCH; + break; + } + pCommand->u.roamCmd.roamProfile.negotiatedUCEncryptionType = + pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0]; + /* In this case, the multicast encryption needs to follow + the unicast ones */ + pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType = + pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0]; +} + + +static void csrSetAbortRoamingCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + switch(pCommand->u.roamCmd.roamReason) + { + case eCsrLostLink1: + pCommand->u.roamCmd.roamReason = eCsrLostLink1Abort; + break; + case eCsrLostLink2: + pCommand->u.roamCmd.roamReason = eCsrLostLink2Abort; + break; + case eCsrLostLink3: + pCommand->u.roamCmd.roamReason = eCsrLostLink3Abort; + break; + default: + smsLog(pMac, LOGE, FL(" aborting roaming reason %d not recognized"), + pCommand->u.roamCmd.roamReason); + break; + } +} + +static eCsrJoinState csrRoamJoinNextBss( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fUseSameBss ) +{ + eHalStatus status; + tCsrScanResult *pScanResult = NULL; + eCsrJoinState eRoamState = eCsrStopRoaming; + tScanResultList *pBSSList = (tScanResultList *)pCommand->u.roamCmd.hBSSList; + tANI_BOOLEAN fDone = eANI_BOOLEAN_FALSE; + tCsrRoamInfo roamInfo, *pRoamInfo = NULL; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + v_U8_t acm_mask = 0; +#endif + tANI_U32 sessionId = pCommand->sessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tCsrRoamProfile *pProfile = &pCommand->u.roamCmd.roamProfile; + tANI_U8 concurrentChannel = 0; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return (eCsrStopRoaming); + } + + do + { + // Check for Cardbus eject condition, before trying to Roam to any BSS + //***if( !balIsCardPresent(pAdapter) ) break; + + vos_mem_set(&roamInfo, sizeof(roamInfo), 0); + vos_mem_copy(&roamInfo.bssid, &pSession->joinFailStatusCode.bssId, + sizeof(tSirMacAddr)); + if(NULL != pBSSList) + { + // When handling AP's capability change, continue to associate to + // same BSS and make sure pRoamBssEntry is not Null. + if((eANI_BOOLEAN_FALSE == fUseSameBss) || (pCommand->u.roamCmd.pRoamBssEntry == NULL)) + { + if(pCommand->u.roamCmd.pRoamBssEntry == NULL) + { + //Try the first BSS + pCommand->u.roamCmd.pLastRoamBss = NULL; + pCommand->u.roamCmd.pRoamBssEntry = csrLLPeekHead(&pBSSList->List, LL_ACCESS_LOCK); + } + else + { + pCommand->u.roamCmd.pRoamBssEntry = csrLLNext(&pBSSList->List, pCommand->u.roamCmd.pRoamBssEntry, LL_ACCESS_LOCK); + if(NULL == pCommand->u.roamCmd.pRoamBssEntry) + { + //Done with all the BSSs + //In this case, will tell HDD the completion + break; + } + else + { + //We need to indicate to HDD that we are done with this one. + //vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss; //this shall not be NULL + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + pRoamInfo = &roamInfo; + } + } + while(pCommand->u.roamCmd.pRoamBssEntry) + { + pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link); + /*If concurrency enabled take the concurrent connected channel first. */ + /* Valid multichannel concurrent sessions exempted */ + if (vos_concurrent_open_sessions_running() && + !csrIsValidMcConcurrentSession(pMac, sessionId, + &pScanResult->Result.BssDescriptor)) + { + concurrentChannel = + csrGetConcurrentOperationChannel(pMac); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, "%s: " + " csr Concurrent Channel = %d", __func__, concurrentChannel); + if ((concurrentChannel) && + (concurrentChannel == + pScanResult->Result.BssDescriptor.channelId)) + { + //make this 0 because we do not want the + //below check to pass as we don't want to + //connect on other channel + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Concurrent channel match =%d"), + concurrentChannel); + concurrentChannel = 0; + } + } + + if (!concurrentChannel) + { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("csrRoamShouldRoam")); +#endif + + if(HAL_STATUS_SUCCESS(csrRoamShouldRoam(pMac, + sessionId, &pScanResult->Result.BssDescriptor, + pCommand->u.roamCmd.roamId))) + { + //Ok to roam this + break; + } + } + else + { + eRoamState = eCsrStopRoamingDueToConcurrency; + } + pCommand->u.roamCmd.pRoamBssEntry = csrLLNext(&pBSSList->List, pCommand->u.roamCmd.pRoamBssEntry, LL_ACCESS_LOCK); + if(NULL == pCommand->u.roamCmd.pRoamBssEntry) + { + //Done with all the BSSs + fDone = eANI_BOOLEAN_TRUE; + break; + } + } + if(fDone) + { + break; + } + } + } + + if (!pRoamInfo) + pRoamInfo = &roamInfo; + + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + + //We have something to roam, tell HDD when it is infra. + //For IBSS, the indication goes back to HDD via eCSR_ROAM_IBSS_IND + //For WDS, the indication is eCSR_ROAM_WDS_IND + if( CSR_IS_INFRASTRUCTURE( pProfile ) ) + { + if(pSession->bRefAssocStartCnt) + { + pSession->bRefAssocStartCnt--; + pRoamInfo->pProfile = pProfile; + /* Complete the last association attempt because a new one + is about to be tried */ + csrRoamCallCallback(pMac, sessionId, pRoamInfo, + pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_NOT_ASSOCIATED); + } + /* If the roaming has stopped, not to continue the roaming command*/ + if ( !CSR_IS_ROAMING(pSession) && CSR_IS_ROAMING_COMMAND(pCommand) ) + { + //No need to complete roaming here as it already completes + smsLog(pMac, LOGW, FL(" Roam command (reason %d) aborted due to roaming completed"), + pCommand->u.roamCmd.roamReason); + eRoamState = eCsrStopRoaming; + csrSetAbortRoamingCommand(pMac, pCommand); + break; + } + vos_mem_set(&roamInfo, sizeof(roamInfo), 0); + if(pScanResult) + { + tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)pScanResult->Result.pvIes; + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pScanResult->Result.BssDescriptor, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" cannot parse IEs")); + fDone = eANI_BOOLEAN_TRUE; + eRoamState = eCsrStopRoaming; + break; + } + roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor; + pCommand->u.roamCmd.pLastRoamBss = roamInfo.pBssDesc; + //No need to put uapsd_mask in if the BSS doesn't support uAPSD + if( pCommand->u.roamCmd.roamProfile.uapsd_mask && + CSR_IS_QOS_BSS(pIesLocal) && + CSR_IS_UAPSD_BSS(pIesLocal) ) + { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + acm_mask = sme_QosGetACMMask(pMac, &pScanResult->Result.BssDescriptor, + pIesLocal); +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + } + else + { + pCommand->u.roamCmd.roamProfile.uapsd_mask = 0; + } + if( pIesLocal && !pScanResult->Result.pvIes) + { + vos_mem_free(pIesLocal); + } + } + else + { + pCommand->u.roamCmd.roamProfile.uapsd_mask = 0; + } + roamInfo.pProfile = pProfile; + pSession->bRefAssocStartCnt++; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("csrGetParsedBssDescriptionIEs")); +#endif + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_START, eCSR_ROAM_RESULT_NONE ); + } + if ( NULL == pCommand->u.roamCmd.pRoamBssEntry ) + { + // If this is a start IBSS profile, then we need to start the IBSS. + if ( CSR_IS_START_IBSS(pProfile) ) + { + tANI_BOOLEAN fSameIbss = eANI_BOOLEAN_FALSE; + // Attempt to start this IBSS... + csrRoamAssignDefaultParam( pMac, pCommand ); + status = csrRoamStartIbss( pMac, sessionId, pProfile, &fSameIbss ); + if(HAL_STATUS_SUCCESS(status)) + { + if ( fSameIbss ) + { + eRoamState = eCsrStartIbssSameIbss; + } + else + { + eRoamState = eCsrContinueRoaming; + } + } + else + { + //it somehow fail need to stop + eRoamState = eCsrStopRoaming; + } + break; + } + else if ( (CSR_IS_WDS_AP(pProfile)) + || (CSR_IS_INFRA_AP(pProfile)) + ) + { + // Attempt to start this WDS... + csrRoamAssignDefaultParam( pMac, pCommand ); + /* For AP WDS, we dont have any BSSDescription */ + status = csrRoamStartWds( pMac, sessionId, pProfile, NULL ); + if(HAL_STATUS_SUCCESS(status)) + { + eRoamState = eCsrContinueRoaming; + } + else + { + //it somehow fail need to stop + eRoamState = eCsrStopRoaming; + } + } + else + { + //Nothing we can do + smsLog(pMac, LOGW, FL("cannot continue without BSS list")); + eRoamState = eCsrStopRoaming; + break; + } + } + else //We have BSS + { + //Need to assign these value because they are used in csrIsSameProfile + pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link); + /* The OSEN IE doesn't provide the cipher suite. + * Therefore set to constant value of AES */ + if(pCommand->u.roamCmd.roamProfile.bOSENAssociation) + { + pCommand->u.roamCmd.roamProfile.negotiatedUCEncryptionType = + eCSR_ENCRYPT_TYPE_AES; + pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType = + eCSR_ENCRYPT_TYPE_AES; + } + else + { + //Negotiated while building scan result. + pCommand->u.roamCmd.roamProfile.negotiatedUCEncryptionType = + pScanResult->ucEncryptionType; + pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType = + pScanResult->mcEncryptionType; + } + pCommand->u.roamCmd.roamProfile.negotiatedAuthType = pScanResult->authType; + if ( CSR_IS_START_IBSS(&pCommand->u.roamCmd.roamProfile) ) + { + if(csrIsSameProfile(pMac, &pSession->connectedProfile, pProfile)) + { + eRoamState = eCsrStartIbssSameIbss; + break; + } + } + if( pCommand->u.roamCmd.fReassocToSelfNoCapChange ) + { + //trying to connect to the one already connected + pCommand->u.roamCmd.fReassocToSelfNoCapChange = eANI_BOOLEAN_FALSE; + eRoamState = eCsrReassocToSelfNoCapChange; + break; + } + // Attempt to Join this Bss... + eRoamState = csrRoamJoin( pMac, sessionId, &pScanResult->Result, pProfile ); + break; + } + + } while( 0 ); + if( (eCsrStopRoaming == eRoamState) && (CSR_IS_INFRASTRUCTURE( pProfile )) ) + { + //Need to indicate association_completion if association_start has been done + if(pSession->bRefAssocStartCnt > 0) + { + pSession->bRefAssocStartCnt--; + /* Complete the last association attempt because a new one is + about to be tried */ + pRoamInfo = &roamInfo; + pRoamInfo->pProfile = pProfile; + csrRoamCallCallback(pMac, sessionId, pRoamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_NOT_ASSOCIATED); + } + } + + return( eRoamState ); +} + +static eHalStatus csrRoam( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + eCsrJoinState RoamState; + tANI_U32 sessionId = pCommand->sessionId; + + //***if( hddIsRadioStateOn( pAdapter ) ) + { + /* Attempt to join a Bss... */ + RoamState = csrRoamJoinNextBss( pMac, pCommand, eANI_BOOLEAN_FALSE ); + + // if nothing to join.. + if (( eCsrStopRoaming == RoamState ) || ( eCsrStopRoamingDueToConcurrency == RoamState)) + { + tANI_BOOLEAN fComplete = eANI_BOOLEAN_FALSE; + // and if connected in Infrastructure mode... + if ( csrIsConnStateInfra(pMac, sessionId) ) + { + //... then we need to issue a disassociation + status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN, FALSE ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, FL(" failed to issue disassociate, status = %d"), status); + //roam command is completed by caller in the failed case + fComplete = eANI_BOOLEAN_TRUE; + } + } + else if( csrIsConnStateIbss(pMac, sessionId) ) + { + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, FL(" failed to issue stop bss, status = %d"), status); + //roam command is completed by caller in the failed case + fComplete = eANI_BOOLEAN_TRUE; + } + } + else if (csrIsConnStateConnectedInfraAp(pMac, sessionId)) + { + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, FL(" failed to issue stop bss, status = %d"), status); + //roam command is completed by caller in the failed case + fComplete = eANI_BOOLEAN_TRUE; + } + } + else + { + fComplete = eANI_BOOLEAN_TRUE; + } + if(fComplete) + { + // ... otherwise, we can complete the Roam command here. + if(eCsrStopRoamingDueToConcurrency == RoamState) + { + csrRoamComplete( pMac, eCsrJoinFailureDueToConcurrency, NULL ); + } + else + { + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + } + } + else if ( eCsrReassocToSelfNoCapChange == RoamState ) + { + csrRoamComplete( pMac, eCsrSilentlyStopRoamingSaveState, NULL ); + } + else if ( eCsrStartIbssSameIbss == RoamState ) + { + csrRoamComplete( pMac, eCsrSilentlyStopRoaming, NULL ); + } + }//hddIsRadioStateOn + + return status; +} +eHalStatus csrProcessFTReassocRoamCommand ( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + tANI_U32 sessionId; + tCsrRoamSession *pSession; + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDesc = NULL; + eHalStatus status = eHAL_STATUS_SUCCESS; + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming) + { + /* The roaming is canceled. Simply complete the command */ + smsLog(pMac, LOG1, FL("Roam command canceled")); + csrRoamComplete(pMac, eCsrNothingToJoin, NULL); + return eHAL_STATUS_FAILURE; + } + if (pCommand->u.roamCmd.pRoamBssEntry) + { + pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link); + pBssDesc = &pScanResult->Result.BssDescriptor; + } + else + { + /* The roaming is canceled. Simply complete the command */ + smsLog(pMac, LOG1, FL("Roam command canceled")); + csrRoamComplete(pMac, eCsrNothingToJoin, NULL); + return eHAL_STATUS_FAILURE; + } + status = csrRoamIssueReassociate(pMac, sessionId, pBssDesc, + (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ), &pCommand->u.roamCmd.roamProfile); + return status; +} + +eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo roamInfo; + tANI_U32 sessionId = pCommand->sessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + smsLog(pMac, LOG1, FL("Roam Reason : %d, sessionId: %d"), + pCommand->u.roamCmd.roamReason, sessionId); + + switch ( pCommand->u.roamCmd.roamReason ) + { + case eCsrForcedDisassoc: + if (eCSR_ROAMING_STATE_IDLE == pMac->roam.curState[sessionId]) { + smsLog(pMac, LOGE, FL("Ignore eCsrForcedDisassoc cmd on roam state" + " %d"), eCSR_ROAMING_STATE_IDLE); + return eHAL_STATUS_FAILURE; + } + + status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE ); + csrFreeRoamProfile(pMac, sessionId); + break; + case eCsrSmeIssuedDisassocForHandoff: + //Not to free pMac->roam.pCurRoamProfile (via csrFreeRoamProfile) because it is needed after disconnect + status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE ); + + break; + case eCsrForcedDisassocMICFailure: + status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, TRUE ); + csrFreeRoamProfile(pMac, sessionId); + break; + case eCsrForcedDeauth: + status = csrRoamProcessDisassocDeauth( pMac, pCommand, FALSE, FALSE ); + csrFreeRoamProfile(pMac, sessionId); + break; + case eCsrHddIssuedReassocToSameAP: + case eCsrSmeIssuedReassocToSameAP: + { + tDot11fBeaconIEs *pIes = NULL; + + if( pSession->pConnectBssDesc ) + { + status = csrGetParsedBssDescriptionIEs(pMac, pSession->pConnectBssDesc, &pIes); + if(!HAL_STATUS_SUCCESS(status) ) + { + smsLog(pMac, LOGE, FL(" fail to parse IEs")); + } + else + { + roamInfo.reasonCode = eCsrRoamReasonStaCapabilityChanged; + csrRoamCallCallback(pMac, pSession->sessionId, &roamInfo, 0, eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE); + pSession->roamingReason = eCsrReassocRoaming; + roamInfo.pBssDesc = pSession->pConnectBssDesc; + roamInfo.pProfile = &pCommand->u.roamCmd.roamProfile; + pSession->bRefAssocStartCnt++; + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_START, eCSR_ROAM_RESULT_NONE ); + + smsLog(pMac, LOG1, FL(" calling csrRoamIssueReassociate")); + status = csrRoamIssueReassociate( pMac, sessionId, pSession->pConnectBssDesc, pIes, + &pCommand->u.roamCmd.roamProfile ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrRoamIssueReassociate failed with status %d"), status); + csrReleaseCommandRoam( pMac, pCommand ); + } + + vos_mem_free(pIes); + pIes = NULL; + } + } + else + { + smsLog(pMac, LOGE, FL + ("Reassoc To Same AP failed since Connected BSS is NULL")); + return eHAL_STATUS_FAILURE; + } + break; + } + case eCsrCapsChange: + smsLog(pMac, LOGE, FL("received eCsrCapsChange ")); + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId ); + status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE); + break; + case eCsrSmeIssuedFTReassoc: + smsLog(pMac, LOG1, FL("received FT Reassoc Req ")); + status = csrProcessFTReassocRoamCommand(pMac, pCommand); + break; + + case eCsrStopBss: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId); + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ); + break; + + case eCsrForcedDisassocSta: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_DISASSOC_REQ, sessionId); + status = csrSendMBDisassocReqMsg( pMac, sessionId, pCommand->u.roamCmd.peerMac, + pCommand->u.roamCmd.reason); + break; + + case eCsrForcedDeauthSta: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_DEAUTH_REQ, sessionId); + status = csrSendMBDeauthReqMsg( pMac, sessionId, pCommand->u.roamCmd.peerMac, + pCommand->u.roamCmd.reason); + break; + + case eCsrPerformPreauth: + smsLog(pMac, LOG1, FL("Attempting FT PreAuth Req")); + status = csrRoamIssueFTPreauthReq(pMac, sessionId, + pCommand->u.roamCmd.pLastRoamBss); + break; + default: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId ); + + if( pCommand->u.roamCmd.fUpdateCurRoamProfile ) + { + //Remember the roaming profile + csrFreeRoamProfile(pMac, sessionId); + pSession->pCurRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( NULL != pSession->pCurRoamProfile ) + { + vos_mem_set(pSession->pCurRoamProfile, sizeof(tCsrRoamProfile), 0); + csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, &pCommand->u.roamCmd.roamProfile); + } + } + + //At this point, original uapsd_mask is saved in pCurRoamProfile + //uapsd_mask in the pCommand may change from this point on. + + // Attempt to roam with the new scan results (if we need to..) + status = csrRoam( pMac, pCommand ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, FL("csrRoam() failed with status = 0x%08X"), status); + } + break; + } + return (status); +} + +void csrReinitPreauthCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + pCommand->u.roamCmd.pLastRoamBss = NULL; + pCommand->u.roamCmd.pRoamBssEntry = NULL; + //Because u.roamCmd is union and share with scanCmd and StatusChange + vos_mem_set(&pCommand->u.roamCmd, sizeof(tRoamCmd), 0); +} + +void csrReinitRoamCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + if(pCommand->u.roamCmd.fReleaseBssList) + { + csrScanResultPurge(pMac, pCommand->u.roamCmd.hBSSList); + pCommand->u.roamCmd.fReleaseBssList = eANI_BOOLEAN_FALSE; + pCommand->u.roamCmd.hBSSList = CSR_INVALID_SCANRESULT_HANDLE; + } + if(pCommand->u.roamCmd.fReleaseProfile) + { + csrReleaseProfile(pMac, &pCommand->u.roamCmd.roamProfile); + pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE; + } + pCommand->u.roamCmd.pRoamBssEntry = NULL; + //Because u.roamCmd is union and share with scanCmd and StatusChange + vos_mem_set(&pCommand->u.roamCmd, sizeof(tRoamCmd), 0); +} + +void csrReinitWmStatusChangeCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + vos_mem_set(&pCommand->u.wmStatusChangeCmd, sizeof(tWmStatusChangeCmd), 0); +} +void csrRoamComplete( tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, void *Context ) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + tANI_BOOLEAN fReleaseCommand = eANI_BOOLEAN_TRUE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: Roam Completion ...", __func__); + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + // If the head of the queue is Active and it is a ROAM command, remove + // and put this on the Free queue. + if ( eSmeCommandRoam == pCommand->command ) + { + //we need to process the result first before removing it from active list because state changes + //still happening insides roamQProcessRoamResults so no other roam command should be issued + fReleaseCommand = csrRoamProcessResults( pMac, pCommand, Result, Context ); + if( fReleaseCommand ) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandRoam( pMac, pCommand ); + } + else + { + smsLog( pMac, LOGE, " **********csrRoamComplete fail to release command reason %d", + pCommand->u.roamCmd.roamReason ); + } + } + else + { + smsLog( pMac, LOGE, " **********csrRoamComplete fail to release command reason %d", + pCommand->u.roamCmd.roamReason ); + } + } + else + { + smsLog( pMac, LOGW, "CSR: Roam Completion called but ROAM command is not ACTIVE ..." ); + } + } + else + { + smsLog( pMac, LOGW, "CSR: Roam Completion called but NO commands are ACTIVE ..." ); + } + if( fReleaseCommand ) + { + smeProcessPendingQueue( pMac ); + } +} + +void csrResetPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + vos_mem_set(&(pSession->PmkidCandidateInfo[0]), + sizeof(tPmkidCandidateInfo) * CSR_MAX_PMKID_ALLOWED, 0); + pSession->NumPmkidCandidate = 0; +} +#ifdef FEATURE_WLAN_WAPI +void csrResetBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + vos_mem_set(&(pSession->BkidCandidateInfo[0]), + sizeof(tBkidCandidateInfo) * CSR_MAX_BKID_ALLOWED, 0); + pSession->NumBkidCandidate = 0; +} +#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 status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tDot11fBeaconIEs *pIesLocal = pIes; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("LFR3:csrRoamSaveSecurityRspIE")); + } +#endif + + if((eCSR_AUTH_TYPE_WPA == authType) || + (eCSR_AUTH_TYPE_WPA_PSK == authType) || + (eCSR_AUTH_TYPE_RSN == authType) || + (eCSR_AUTH_TYPE_RSN_PSK == authType) +#if defined WLAN_FEATURE_VOWIFI_11R + || + (eCSR_AUTH_TYPE_FT_RSN == authType) || + (eCSR_AUTH_TYPE_FT_RSN_PSK == authType) +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_WAPI + || + (eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) || + (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType) +#endif /* FEATURE_WLAN_WAPI */ +#ifdef WLAN_FEATURE_11W + || + (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) || + (eCSR_AUTH_TYPE_RSN_8021X_SHA256 == authType) +#endif /* FEATURE_WLAN_WAPI */ + ) + { + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" cannot parse IEs")); + } + if( pIesLocal ) + { + tANI_U32 nIeLen; + tANI_U8 *pIeBuf; + if((eCSR_AUTH_TYPE_RSN == authType) || +#if defined WLAN_FEATURE_VOWIFI_11R + (eCSR_AUTH_TYPE_FT_RSN == authType) || + (eCSR_AUTH_TYPE_FT_RSN_PSK == authType) || +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#if defined WLAN_FEATURE_11W + (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) || + (eCSR_AUTH_TYPE_RSN_8021X_SHA256 == authType) || +#endif + (eCSR_AUTH_TYPE_RSN_PSK == authType)) + { + if(pIesLocal->RSN.present) + { + //Calculate the actual length + nIeLen = 8 //version + gp_cipher_suite + pwise_cipher_suite_count + + pIesLocal->RSN.pwise_cipher_suite_count * 4 //pwise_cipher_suites + + 2 //akm_suite_count + + pIesLocal->RSN.akm_suite_count * 4 //akm_suites + + 2; //reserved + if( pIesLocal->RSN.pmkid_count ) + { + nIeLen += 2 + pIesLocal->RSN.pmkid_count * 4; //pmkid + } + //nIeLen doesn't count EID and length fields + pSession->pWpaRsnRspIE = vos_mem_malloc(nIeLen + 2); + if (NULL == pSession->pWpaRsnRspIE) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pSession->pWpaRsnRspIE, nIeLen + 2, 0); + pSession->pWpaRsnRspIE[0] = DOT11F_EID_RSN; + pSession->pWpaRsnRspIE[1] = (tANI_U8)nIeLen; + /* Copy up to akm_suites */ + pIeBuf = pSession->pWpaRsnRspIE + 2; + vos_mem_copy(pIeBuf, &pIesLocal->RSN.version, + sizeof(pIesLocal->RSN.version)); + pIeBuf += sizeof(pIesLocal->RSN.version); + vos_mem_copy(pIeBuf, &pIesLocal->RSN.gp_cipher_suite, + sizeof(pIesLocal->RSN.gp_cipher_suite)); + pIeBuf += sizeof(pIesLocal->RSN.gp_cipher_suite); + vos_mem_copy(pIeBuf, &pIesLocal->RSN.pwise_cipher_suite_count, + sizeof(pIesLocal->RSN.pwise_cipher_suite_count)); + pIeBuf += sizeof(pIesLocal->RSN.pwise_cipher_suite_count ); + if( pIesLocal->RSN.pwise_cipher_suite_count ) + { + //copy pwise_cipher_suites + vos_mem_copy(pIeBuf, + pIesLocal->RSN.pwise_cipher_suites, + pIesLocal->RSN.pwise_cipher_suite_count * 4); + pIeBuf += pIesLocal->RSN.pwise_cipher_suite_count * 4; + } + vos_mem_copy(pIeBuf, &pIesLocal->RSN.akm_suite_count, 2); + pIeBuf += 2; + if( pIesLocal->RSN.akm_suite_count ) + { + //copy akm_suites + vos_mem_copy(pIeBuf, + pIesLocal->RSN.akm_suites, + pIesLocal->RSN.akm_suite_count * 4); + pIeBuf += pIesLocal->RSN.akm_suite_count * 4; + } + //copy the rest + vos_mem_copy(pIeBuf, + pIesLocal->RSN.akm_suites + pIesLocal->RSN.akm_suite_count * 4, + 2 + pIesLocal->RSN.pmkid_count * 4); + pSession->nWpaRsnRspIeLength = nIeLen + 2; + } + } + } + else if((eCSR_AUTH_TYPE_WPA == authType) || + (eCSR_AUTH_TYPE_WPA_PSK == authType)) + { + if(pIesLocal->WPA.present) + { + //Calculate the actual length + nIeLen = 12 //OUI + version + multicast_cipher + unicast_cipher_count + + pIesLocal->WPA.unicast_cipher_count * 4 //unicast_ciphers + + 2 //auth_suite_count + + pIesLocal->WPA.auth_suite_count * 4; //auth_suites + + /* + * The WPA capabilities follows the Auth Suite (two octets) + * this field is optional, and we always "send" zero, so + * just remove it. This is consistent with our assumptions + * in the frames compiler; c.f. bug 15234: + * nIeLen doesn't count EID and length fields + */ + + pSession->pWpaRsnRspIE = vos_mem_malloc(nIeLen + 2); + if ( NULL == pSession->pWpaRsnRspIE ) + status = eHAL_STATUS_FAILURE; + else + { + pSession->pWpaRsnRspIE[0] = DOT11F_EID_WPA; + pSession->pWpaRsnRspIE[1] = (tANI_U8)nIeLen; + pIeBuf = pSession->pWpaRsnRspIE + 2; + //Copy WPA OUI + vos_mem_copy(pIeBuf, &csrWpaOui[1], 4); + pIeBuf += 4; + vos_mem_copy(pIeBuf, &pIesLocal->WPA.version, + 8 + pIesLocal->WPA.unicast_cipher_count * 4); + pIeBuf += 8 + pIesLocal->WPA.unicast_cipher_count * 4; + vos_mem_copy(pIeBuf, &pIesLocal->WPA.auth_suite_count, + 2 + pIesLocal->WPA.auth_suite_count * 4); + pIeBuf += pIesLocal->WPA.auth_suite_count * 4; + pSession->nWpaRsnRspIeLength = nIeLen + 2; + } + } + } +#ifdef FEATURE_WLAN_WAPI + else if((eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) || + (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType)) + { + if(pIesLocal->WAPI.present) + { + //Calculate the actual length + nIeLen = 4 //version + akm_suite_count + + pIesLocal->WAPI.akm_suite_count * 4 // akm_suites + + 2 //pwise_cipher_suite_count + + pIesLocal->WAPI.unicast_cipher_suite_count * 4 //pwise_cipher_suites + + 6; //gp_cipher_suite + preauth + reserved + if( pIesLocal->WAPI.bkid_count ) + { + nIeLen += 2 + pIesLocal->WAPI.bkid_count * 4; //bkid + } + + //nIeLen doesn't count EID and length fields + pSession->pWapiRspIE = vos_mem_malloc(nIeLen + 2); + if ( NULL == pSession->pWapiRspIE ) + status = eHAL_STATUS_FAILURE; + else + { + pSession->pWapiRspIE[0] = DOT11F_EID_WAPI; + pSession->pWapiRspIE[1] = (tANI_U8)nIeLen; + pIeBuf = pSession->pWapiRspIE + 2; + /* Copy up to akm_suite_count */ + vos_mem_copy(pIeBuf, &pIesLocal->WAPI.version, 2); + pIeBuf += 4; + if( pIesLocal->WAPI.akm_suite_count ) + { + //copy akm_suites + vos_mem_copy(pIeBuf, pIesLocal->WAPI.akm_suites, + pIesLocal->WAPI.akm_suite_count * 4); + pIeBuf += pIesLocal->WAPI.akm_suite_count * 4; + } + vos_mem_copy(pIeBuf, + &pIesLocal->WAPI.unicast_cipher_suite_count, + 2); + pIeBuf += 2; + if( pIesLocal->WAPI.unicast_cipher_suite_count ) + { + //copy pwise_cipher_suites + vos_mem_copy( pIeBuf, + pIesLocal->WAPI.unicast_cipher_suites, + pIesLocal->WAPI.unicast_cipher_suite_count * 4); + pIeBuf += pIesLocal->WAPI.unicast_cipher_suite_count * 4; + } + //gp_cipher_suite + vos_mem_copy(pIeBuf, + pIesLocal->WAPI.multicast_cipher_suite, + 4); + pIeBuf += 4; + //preauth + reserved + vos_mem_copy(pIeBuf, + pIesLocal->WAPI.multicast_cipher_suite + 4, + 2); + pIeBuf += 2; + if (pIesLocal->WAPI.bkid_count) { + /* bkid_count */ + vos_mem_copy(pIeBuf, &pIesLocal->WAPI.bkid_count, 2); + pIeBuf += 2; + //copy akm_suites + vos_mem_copy(pIeBuf, pIesLocal->WAPI.bkid, + pIesLocal->WAPI.bkid_count * 4); + pIeBuf += pIesLocal->WAPI.bkid_count * 4; + } + pSession->nWapiRspIeLength = nIeLen + 2; + } + } + } +#endif /* FEATURE_WLAN_WAPI */ + if( !pIes ) + { + //locally allocated + vos_mem_free(pIesLocal); + } + } + } + return (status); +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +//Returns whether the current association is a 11r assoc or not +tANI_BOOLEAN csrRoamIs11rAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + return csrNeighborRoamIs11rAssoc(pMac, sessionId); +#else + return eANI_BOOLEAN_FALSE; +#endif +} +#endif +#ifdef FEATURE_WLAN_ESE +//Returns whether the current association is a ESE assoc or not +tANI_BOOLEAN csrRoamIsESEAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + return csrNeighborRoamIsESEAssoc(pMac, sessionId); +#else + return eANI_BOOLEAN_FALSE; +#endif +} +#endif +#ifdef FEATURE_WLAN_LFR +//Returns whether "Legacy Fast Roaming" is currently enabled...or not +tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = NULL; + + if (CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL != pSession->pCurRoamProfile) + { + if (pSession->pCurRoamProfile->csrPersona != VOS_STA_MODE) + { + return eANI_BOOLEAN_FALSE; + } + } + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (eANI_BOOLEAN_TRUE == CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac)) + { + return (pMac->roam.configParam.isFastRoamIniFeatureEnabled); + } + else +#endif + { + return (pMac->roam.configParam.isFastRoamIniFeatureEnabled && + (!csrIsConcurrentSessionRunning(pMac))); + } +} + +#ifdef FEATURE_WLAN_ESE +/* --------------------------------------------------------------------------- + \fn csrNeighborRoamIsESEAssoc + + \brief This function returns whether the current association + is a ESE assoc or not + + \param pMac - The handle returned by macOpen. + \param sessionId - Session Id + + \return eANI_BOOLEAN_TRUE if current assoc is ESE, eANI_BOOLEAN_FALSE + otherwise +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamIsESEAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + return pMac->roam.neighborRoamInfo[sessionId].isESEAssoc; +} +#endif /* FEATURE_WLAN_ESE */ + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +//Returns whether "FW based BG scan" is currently enabled...or not +tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac) +{ + return (pMac->roam.configParam.isRoamOffloadScanEnabled); +} +#endif +#endif + +#if defined(FEATURE_WLAN_ESE) +tANI_BOOLEAN csrRoamIsEseIniFeatureEnabled(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.isEseIniFeatureEnabled; +} +#endif /*FEATURE_WLAN_ESE*/ + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +eCsrPhyMode csrRoamdot11modeToPhymode(tANI_U8 dot11mode) +{ + eCsrPhyMode phymode = eCSR_DOT11_MODE_abg; + + switch (dot11mode) + { + case WNI_CFG_DOT11_MODE_ALL: + phymode = eCSR_DOT11_MODE_abg; + break; + case WNI_CFG_DOT11_MODE_11A: + phymode = eCSR_DOT11_MODE_11a; + break; + case WNI_CFG_DOT11_MODE_11B: + phymode = eCSR_DOT11_MODE_11b; + break; + case WNI_CFG_DOT11_MODE_11G: + phymode = eCSR_DOT11_MODE_11g; + break; + case WNI_CFG_DOT11_MODE_11N: + phymode = eCSR_DOT11_MODE_11n; + break; + case WNI_CFG_DOT11_MODE_11G_ONLY: + phymode = eCSR_DOT11_MODE_11g_ONLY; + break; + case WNI_CFG_DOT11_MODE_11N_ONLY: + phymode = eCSR_DOT11_MODE_11n_ONLY; + break; + case WNI_CFG_DOT11_MODE_11AC: + phymode = eCSR_DOT11_MODE_11ac; + break; + case WNI_CFG_DOT11_MODE_11AC_ONLY: + phymode = eCSR_DOT11_MODE_11ac_ONLY; + break; + default: + break; + } + + return phymode; +} +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus csrRoamOffloadSendSynchCnf(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tpSirSmeRoamOffloadSynchCnf pRoamOffloadSynchCnf; + vos_msg_t msg; + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + pRoamOffloadSynchCnf = + vos_mem_malloc(sizeof(tSirSmeRoamOffloadSynchCnf)); + if (NULL == pRoamOffloadSynchCnf) + { + VOS_TRACE(VOS_MODULE_ID_SME, + VOS_TRACE_LEVEL_ERROR, + "%s: not able to allocate memory for roam" + "offload synch confirmation data", __func__); + pSession->roamOffloadSynchParams.bRoamSynchInProgress = VOS_FALSE; + return eHAL_STATUS_FAILURE; + } + pRoamOffloadSynchCnf->sessionId = sessionId; + msg.type = WDA_ROAM_OFFLOAD_SYNCH_CNF; + msg.reserved = 0; + msg.bodyptr = pRoamOffloadSynchCnf; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "LFR3: Posting WDA_ROAM_OFFLOAD_SYNCH_CNF"); + if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message( + VOS_MODULE_ID_WDA, &msg))) + { + VOS_TRACE(VOS_MODULE_ID_SME,VOS_TRACE_LEVEL_DEBUG, + "%s: Not able to post WDA_ROAM_OFFLOAD_SYNCH_CNF message to WDA", + __func__); + vos_mem_free(pRoamOffloadSynchCnf); + pSession->roamOffloadSynchParams.bRoamSynchInProgress = VOS_FALSE; + return eHAL_STATUS_FAILURE; + } + pSession->roamOffloadSynchParams.bRoamSynchInProgress = VOS_FALSE; + return eHAL_STATUS_SUCCESS; +} +void csrRoamSynchCleanUp (tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + vos_msg_t msg; + tpSirRoamOffloadSynchFail pRoamOffloadFailed = NULL; + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + + /*Clean up the roam synch in progress for LFR3 */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Roam Synch Failed, Clean Up", __func__); + pSession->roamOffloadSynchParams.bRoamSynchInProgress = VOS_FALSE; + + pRoamOffloadFailed = + vos_mem_malloc(sizeof(tSirRoamOffloadSynchFail)); + if (NULL == pRoamOffloadFailed) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: unable to allocate memory for roam synch fail" , __func__); + return; + } + pRoamOffloadFailed->sessionId = sessionId; + msg.type = WDA_ROAM_OFFLOAD_SYNCH_FAIL; + msg.reserved = 0; + msg.bodyptr = pRoamOffloadFailed; + if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) { + VOS_TRACE(VOS_MODULE_ID_SME,VOS_TRACE_LEVEL_DEBUG, + "%s:Unable to post WDA_ROAM_OFFLOAD_SYNCH_FAIL msg to WDA",__func__); + vos_mem_free(pRoamOffloadFailed); + } +} +#endif + +//Return true means the command can be release, else not +static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrRoamCompleteResult Result, void *Context ) +{ + tANI_BOOLEAN fReleaseCommand = eANI_BOOLEAN_TRUE; + tSirBssDescription *pSirBssDesc = NULL; + tSirMacAddr BroadcastMac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + tCsrScanResult *pScanResult = NULL; + tCsrRoamInfo roamInfo; + sme_QosAssocInfo assocInfo; + sme_QosCsrEventIndType ind_qos;//indication for QoS module in SME + tANI_U8 acm_mask = 0; //HDD needs the ACM mask in the assoc rsp callback + tDot11fBeaconIEs *pIes = NULL; + tANI_U32 sessionId = pCommand->sessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tCsrRoamProfile *pProfile = &pCommand->u.roamCmd.roamProfile; + eRoamCmdStatus roamStatus; + eCsrRoamResult roamResult; + eHalStatus status; + tANI_U32 key_timeout_interval = 0; + tSirSmeStartBssRsp *pSmeStartBssRsp = NULL; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eANI_BOOLEAN_FALSE; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("Processing ROAM results...")); + switch( Result ) + { + case eCsrJoinSuccess: + // reset the IDLE timer + // !! + // !! fall through to the next CASE statement here is intentional !! + // !! + case eCsrReassocSuccess: + if(eCsrReassocSuccess == Result) + { + ind_qos = SME_QOS_CSR_REASSOC_COMPLETE; + } + else + { + ind_qos = SME_QOS_CSR_ASSOC_COMPLETE; + } + // Success Join Response from LIM. Tell NDIS we are connected and save the + // Connected state... + smsLog(pMac, LOGW, FL("receives association indication")); + vos_mem_set(&roamInfo, sizeof(roamInfo), 0); + //always free the memory here + if(pSession->pWpaRsnRspIE) + { + pSession->nWpaRsnRspIeLength = 0; + vos_mem_free(pSession->pWpaRsnRspIE); + pSession->pWpaRsnRspIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + if(pSession->pWapiRspIE) + { + pSession->nWapiRspIeLength = 0; + vos_mem_free(pSession->pWapiRspIE); + pSession->pWapiRspIE = NULL; + } +#endif /* FEATURE_WLAN_WAPI */ + /* This creates problem since we have not saved the connected profile. + So moving this after saving the profile + */ + //csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED ); + + /* Reset remainInPowerActiveTillDHCP as it might have been set + * by last failed secured connection. + * It should be set only for secured connection. + */ + pMac->pmc.remainInPowerActiveTillDHCP = FALSE; + if( CSR_IS_INFRASTRUCTURE( pProfile ) ) + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + } + else + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED; + } + //Use the last connected bssdesc for reassoc-ing to the same AP. + //NOTE: What to do when reassoc to a different AP??? + if( (eCsrHddIssuedReassocToSameAP == pCommand->u.roamCmd.roamReason) || + (eCsrSmeIssuedReassocToSameAP == pCommand->u.roamCmd.roamReason) ) + { + pSirBssDesc = pSession->pConnectBssDesc; + if(pSirBssDesc) + { + vos_mem_copy(&roamInfo.bssid, &pSirBssDesc->bssId, + sizeof(tCsrBssid)); + } + } + else + { + + if(pCommand->u.roamCmd.pRoamBssEntry) + { + pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link); + if(pScanResult != NULL) + { + pSirBssDesc = &pScanResult->Result.BssDescriptor; + //this can be NULL + pIes = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ); + vos_mem_copy(&roamInfo.bssid, &pSirBssDesc->bssId, + sizeof(tCsrBssid)); + } + } + } + if( pSirBssDesc ) + { + roamInfo.staId = HAL_STA_INVALID_IDX; + csrRoamSaveConnectedInfomation(pMac, sessionId, pProfile, pSirBssDesc, pIes); + //Save WPA/RSN IE + csrRoamSaveSecurityRspIE(pMac, sessionId, pProfile->negotiatedAuthType, pSirBssDesc, pIes); +#ifdef FEATURE_WLAN_ESE + roamInfo.isESEAssoc = pSession->connectedProfile.isESEAssoc; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSirBssDesc->mdiePresent) + { + if(csrIsAuthType11r(pProfile->negotiatedAuthType, VOS_TRUE) +#ifdef FEATURE_WLAN_ESE + && !((pProfile->negotiatedAuthType == + eCSR_AUTH_TYPE_OPEN_SYSTEM) && + (pIes && pIes->ESEVersion.present) && + (pMac->roam.configParam.isEseIniFeatureEnabled)) +#endif + ) + { + // is11Rconnection + roamInfo.is11rAssoc = VOS_TRUE; + } + else + { + // is11Rconnection + roamInfo.is11rAssoc = VOS_FALSE; + } + } +#endif + + /* csrRoamStateChange also affects sub-state. Hence, + * csrRoamStateChange happens first and then sub state change. + * Moving even save profile above so that below mentioned + * condition is also met. */ + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId ); + // Make sure the Set Context is issued before link indication to NDIS. After link indication is + // made to NDIS, frames could start flowing. If we have not set context with LIM, the frames + // will be dropped for the security context may not be set properly. + // + // this was causing issues in the 2c_wlan_wep WHQL test when the SetContext was issued after the link + // indication. (Link Indication happens in the profFSMSetConnectedInfra call). + // + + if( CSR_IS_ENC_TYPE_STATIC( pProfile->negotiatedUCEncryptionType ) && + !pProfile->bWPSAssociation) + { + // Issue the set Context request to LIM to establish the Unicast STA context + if( !HAL_STATUS_SUCCESS( csrRoamIssueSetContextReq( pMac, sessionId, + pProfile->negotiatedUCEncryptionType, + pSirBssDesc, &(pSirBssDesc->bssId), + FALSE, TRUE, eSIR_TX_RX, 0, 0, NULL, 0 ) ) ) // NO keys... these key parameters don't matter. + { + smsLog( pMac, LOGE, FL(" Set context for unicast fail") ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId ); + } + // Issue the set Context request to LIM to establish the Broadcast STA context + csrRoamIssueSetContextReq( pMac, sessionId, pProfile->negotiatedMCEncryptionType, + pSirBssDesc, &BroadcastMac, + FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter. + } + else + { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress && + (pSession->roamOffloadSynchParams.authStatus == + CSR_ROAM_AUTH_STATUS_AUTHENTICATED)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("LFR3:Do not start the wait for key timer")); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } else { +#endif + /* Need to wait for supplicant authentication */ + roamInfo.fAuthRequired = eANI_BOOLEAN_TRUE; + /* Set the sub-state to WaitForKey in case + authentication is needed */ + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, sessionId ); + + if(pProfile->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 + pMac->roam.WaitForKeyTimerInfo.sessionId = (tANI_U8)sessionId; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress && + (pSession->roamOffloadSynchParams.authStatus == + CSR_ROAM_AUTH_STATUS_CONNECTED)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("LFR3:Send Synch Cnf for Auth status connected")); + csrRoamOffloadSendSynchCnf( pMac, sessionId); + + } +#endif + //This time should be long enough for the rest of the process plus setting key + if(!HAL_STATUS_SUCCESS( csrRoamStartWaitForKeyTimer( pMac, key_timeout_interval ) ) ) + { + /* Reset our state so nothing is blocked. */ + smsLog( pMac, LOGE, FL(" Failed to start pre-auth timer") ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } +#endif + } + + assocInfo.pBssDesc = pSirBssDesc; //could be NULL + assocInfo.pProfile = pProfile; + if(Context) + { + tSirSmeJoinRsp *pJoinRsp = (tSirSmeJoinRsp *)Context; + tANI_U32 len; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("LFR3:csrRoamFreeConnectedInfo")); + } +#endif + csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo ); + len = pJoinRsp->assocReqLength + pJoinRsp->assocRspLength + pJoinRsp->beaconLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + len += pJoinRsp->parsedRicRspLen; +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef FEATURE_WLAN_ESE + len += pJoinRsp->tspecIeLen; +#endif + if(len) + { + pSession->connectedInfo.pbFrames = vos_mem_malloc(len); + if ( pSession->connectedInfo.pbFrames != NULL ) + { + vos_mem_copy(pSession->connectedInfo.pbFrames, + pJoinRsp->frames, len); + pSession->connectedInfo.nAssocReqLength = pJoinRsp->assocReqLength; + pSession->connectedInfo.nAssocRspLength = pJoinRsp->assocRspLength; + pSession->connectedInfo.nBeaconLength = pJoinRsp->beaconLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + pSession->connectedInfo.nRICRspLength = pJoinRsp->parsedRicRspLen; +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef FEATURE_WLAN_ESE + pSession->connectedInfo.nTspecIeLength = pJoinRsp->tspecIeLen; +#endif + roamInfo.nAssocReqLength = pJoinRsp->assocReqLength; + roamInfo.nAssocRspLength = pJoinRsp->assocRspLength; + roamInfo.nBeaconLength = pJoinRsp->beaconLength; + roamInfo.pbFrames = pSession->connectedInfo.pbFrames; + } + } + if(pCommand->u.roamCmd.fReassoc) + { + roamInfo.fReassocReq = roamInfo.fReassocRsp = eANI_BOOLEAN_TRUE; + } + pSession->connectedProfile.vht_channel_width = + pJoinRsp->vht_channel_width; + pSession->connectedInfo.staId = ( tANI_U8 )pJoinRsp->staId; + roamInfo.staId = ( tANI_U8 )pJoinRsp->staId; + roamInfo.ucastSig = ( tANI_U8 )pJoinRsp->ucastSig; + roamInfo.bcastSig = ( tANI_U8 )pJoinRsp->bcastSig; + roamInfo.timingMeasCap = pJoinRsp->timingMeasCap; + roamInfo.chan_info.nss = pJoinRsp->nss; + roamInfo.chan_info.rate_flags = pJoinRsp->max_rate_flags; +#ifdef FEATURE_WLAN_TDLS + roamInfo.tdls_prohibited = pJoinRsp->tdls_prohibited; + roamInfo.tdls_chan_swit_prohibited = + pJoinRsp->tdls_chan_swit_prohibited; + smsLog(pMac, LOG1, + FL("tdls_prohibited: %d, tdls_chan_swit_prohibited: %d"), + roamInfo.tdls_prohibited, + roamInfo.tdls_chan_swit_prohibited); +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (pMac->roam.configParam.cc_switch_mode + != VOS_MCC_TO_SCC_SWITCH_DISABLE) { + pSession->connectedProfile.HTProfile.phymode = + csrRoamdot11modeToPhymode(pJoinRsp->HTProfile.dot11mode); + pSession->connectedProfile.HTProfile.htCapability = + pJoinRsp->HTProfile.htCapability; + pSession->connectedProfile.HTProfile.htSupportedChannelWidthSet = + pJoinRsp->HTProfile.htSupportedChannelWidthSet; + pSession->connectedProfile.HTProfile.htRecommendedTxWidthSet = + pJoinRsp->HTProfile.htRecommendedTxWidthSet; + pSession->connectedProfile.HTProfile.htSecondaryChannelOffset = + pJoinRsp->HTProfile.htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + pSession->connectedProfile.HTProfile.vhtCapability = + pJoinRsp->HTProfile.vhtCapability; + pSession->connectedProfile.HTProfile.vhtTxChannelWidthSet = + pJoinRsp->HTProfile.vhtTxChannelWidthSet; + pSession->connectedProfile.HTProfile.apCenterChan = + pJoinRsp->HTProfile.apCenterChan; + pSession->connectedProfile.HTProfile.apChanWidth = + pJoinRsp->HTProfile.apChanWidth; +#endif + } +#endif + } + else + { + if(pCommand->u.roamCmd.fReassoc) + { + roamInfo.fReassocReq = roamInfo.fReassocRsp = eANI_BOOLEAN_TRUE; + roamInfo.nAssocReqLength = pSession->connectedInfo.nAssocReqLength; + roamInfo.nAssocRspLength = pSession->connectedInfo.nAssocRspLength; + roamInfo.nBeaconLength = pSession->connectedInfo.nBeaconLength; + roamInfo.pbFrames = pSession->connectedInfo.pbFrames; + } + } + + /* Update the staId from the previous connected profile info + as the reassociation is triggred at SME/HDD */ + if ((eCsrHddIssuedReassocToSameAP == + pCommand->u.roamCmd.roamReason) || + (eCsrSmeIssuedReassocToSameAP == + pCommand->u.roamCmd.roamReason)) + roamInfo.staId = pSession->connectedInfo.staId; + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + // Indicate SME-QOS with reassoc success event, only after + // copying the frames + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, ind_qos, &assocInfo); +#endif + roamInfo.pBssDesc = pSirBssDesc; + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + acm_mask = sme_QosGetACMMask(pMac, pSirBssDesc, NULL); +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + pSession->connectedProfile.acm_mask = acm_mask; + //start UAPSD if uapsd_mask is not 0 because HDD will configure for trigger frame + //It may be better to let QoS do this???? + if( pSession->connectedProfile.modifyProfileFields.uapsd_mask ) + { + smsLog(pMac, LOGE, " uapsd_mask (0x%X) set, request UAPSD now", + pSession->connectedProfile.modifyProfileFields.uapsd_mask); + if(!pMac->psOffloadEnabled) + { + pmcStartUapsd( pMac, NULL, NULL ); + } + else + { + pmcOffloadStartUapsd(pMac, sessionId, NULL, NULL); + } + } + pSession->connectedProfile.dot11Mode = pSession->bssParams.uCfgDot11Mode; + roamInfo.u.pConnectedProfile = &pSession->connectedProfile; + + if( pSession->bRefAssocStartCnt > 0 ) + { + pSession->bRefAssocStartCnt--; + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && ( csrIsConcurrentSessionRunning( pMac ))) + { + pMac->roam.configParam.doBMPSWorkaround = 1; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) { + roamInfo.roamSynchInProgress = 1; + roamInfo.synchAuthStatus = + pSession->roamOffloadSynchParams.authStatus; + vos_mem_copy(roamInfo.kck, pSession->roamOffloadSynchParams.kck, + SIR_KCK_KEY_LEN); + vos_mem_copy(roamInfo.kek, pSession->roamOffloadSynchParams.kek, + SIR_KEK_KEY_LEN); + vos_mem_copy(roamInfo.replay_ctr, + pSession->roamOffloadSynchParams.replay_ctr, + SIR_REPLAY_CTR_LEN); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("LFR3:csrRoamCallCallback:eCSR_ROAM_RESULT_ASSOCIATED")); + } +#endif + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED); + } + + csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_NONE, eANI_BOOLEAN_TRUE); + // reset the PMKID candidate list + csrResetPMKIDCandidateList( pMac, sessionId ); +#ifdef FEATURE_WLAN_WAPI + // reset the BKID candidate list + csrResetBKIDCandidateList( pMac, sessionId ); +#endif /* FEATURE_WLAN_WAPI */ + } + else + { + smsLog(pMac, LOGW, " Roam command doesn't have a BSS desc"); + } + csrScanCancelIdleScan(pMac); + //Not to signal link up because keys are yet to be set. + //The linkup function will overwrite the sub-state that we need to keep at this point. + if( !CSR_IS_WAIT_FOR_KEY(pMac, sessionId) ) + { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("NO CSR_IS_WAIT_FOR_KEY -> csrRoamLinkUp")); + } +#endif + csrRoamLinkUp(pMac, pSession->connectedProfile.bssid); + } + //Check if BMPS is required and start the BMPS retry timer. Timer period is large + //enough to let security and DHCP handshake succeed before entry into BMPS + if (!pMac->psOffloadEnabled && pmcShouldBmpsTimerRun(pMac)) + { + /* Set remainInPowerActiveTillDHCP to make sure we wait for + * until keys are set before going into BMPS. + */ + if(eANI_BOOLEAN_TRUE == roamInfo.fAuthRequired) + { + pMac->pmc.remainInPowerActiveTillDHCP = TRUE; + smsLog(pMac, LOG1, FL("Set remainInPowerActiveTillDHCP " + "to make sure we wait until keys are set before" + " going to BMPS")); + } + if (pmcStartTrafficTimer(pMac, BMPS_TRAFFIC_TIMER_ALLOW_SECURITY_DHCP) + != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGP, FL("Cannot start BMPS Retry timer")); + } + smsLog(pMac, LOG2, FL("BMPS Retry Timer already running or started")); + } + break; + + case eCsrStartBssSuccess: + // on the StartBss Response, LIM is returning the Bss Description that we + // are beaconing. Add this Bss Description to our scan results and + // chain the Profile to this Bss Description. On a Start BSS, there was no + // detected Bss description (no partner) so we issued the Start Bss to + // start the Ibss without any Bss description. Lim was kind enough to return + // the Bss Description that we start beaconing for the newly started Ibss. + smsLog(pMac, LOG2, FL("receives start BSS ok indication")); + status = eHAL_STATUS_FAILURE; + pSmeStartBssRsp = (tSirSmeStartBssRsp *)Context; + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + if( CSR_IS_IBSS( pProfile ) ) + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; + } + else if (CSR_IS_INFRA_AP(pProfile)) + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED; + } + else + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED; + } + if( !CSR_IS_WDS_STA( pProfile ) ) + { + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId ); + pSirBssDesc = &pSmeStartBssRsp->bssDescription; + if( !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs( pMac, pSirBssDesc, &pIes )) ) + { + smsLog(pMac, LOGW, FL("cannot parse IBSS IEs")); + roamInfo.pBssDesc = pSirBssDesc; + /* + * We need to associate_complete it first, because + * Associate_start already indicated. + */ + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_IBSS_IND, eCSR_ROAM_RESULT_IBSS_START_FAILED ); + break; + } + if (!CSR_IS_INFRA_AP(pProfile)) + { + pScanResult = csrScanAppendBssDescription(pMac, + pSirBssDesc, + pIes, FALSE, + sessionId); + } + csrRoamSaveConnectedBssDesc(pMac, sessionId, pSirBssDesc); + csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile); + csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo ); + if(pSirBssDesc) + { + csrRoamSaveConnectedInfomation(pMac, sessionId, pProfile, pSirBssDesc, pIes); + vos_mem_copy(&roamInfo.bssid, &pSirBssDesc->bssId, + sizeof(tCsrBssid)); + } + /* We are done with the IEs so free it */ + vos_mem_free(pIes); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + tANI_U32 bi; + + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + if(CSR_INVALID_SCANRESULT_HANDLE == pCommand->u.roamCmd.hBSSList) + { + //We start the IBSS (didn't find any matched IBSS out there) + pIbssLog->eventId = WLAN_IBSS_EVENT_START_IBSS_RSP; + } + else + { + pIbssLog->eventId = WLAN_IBSS_EVENT_JOIN_IBSS_RSP; + } + if(pSirBssDesc) + { + vos_mem_copy(pIbssLog->bssid, pSirBssDesc->bssId, 6); + pIbssLog->operatingChannel = pSirBssDesc->channelId; + } + if(HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &bi))) + { + //***U8 is not enough for beacon interval + pIbssLog->beaconInterval = (v_U8_t)bi; + } + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + //Only set context for non-WDS_STA. We don't even need it for WDS_AP. But since the encryption + //is WPA2-PSK so it won't matter. + if(CSR_IS_ENC_TYPE_STATIC(pProfile->negotiatedUCEncryptionType) + && pSession->pCurRoamProfile + && !CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) + { + // Issue the set Context request to LIM to establish the Broadcast STA context for the Ibss. + // In Rome IBSS case, dummy key installation will break + // proper BSS key installation, so skip it. + if (!CSR_IS_IBSS( pSession->pCurRoamProfile )) + { + csrRoamIssueSetContextReq( pMac, sessionId, + pProfile->negotiatedMCEncryptionType, + pSirBssDesc, &BroadcastMac, + FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter. + } + + } + } + else + { + //Keep the state to eCSR_ROAMING_STATE_JOINING + //Need to send join_req. + if(pCommand->u.roamCmd.pRoamBssEntry) + { + if((pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link))) + { + pSirBssDesc = &pScanResult->Result.BssDescriptor; + pIes = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ); + // Set the roaming substate to 'join attempt'... + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId); + status = csrSendJoinReqMsg( pMac, sessionId, pSirBssDesc, pProfile, pIes, eWNI_SME_JOIN_REQ ); + } + } + else + { + smsLog( pMac, LOGE, " StartBSS for WDS station with no BssDesc" ); + VOS_ASSERT( 0 ); + } + } + //Only tell upper layer is we start the BSS because Vista doesn't like multiple connection + //indications. If we don't start the BSS ourself, handler of eSIR_SME_JOINED_NEW_BSS will + //trigger the connection start indication in Vista + if( !CSR_IS_JOIN_TO_IBSS( pProfile ) ) + { + roamStatus = eCSR_ROAM_IBSS_IND; + roamResult = eCSR_ROAM_RESULT_IBSS_STARTED; + if( CSR_IS_WDS( pProfile ) ) + { + roamStatus = eCSR_ROAM_WDS_IND; + roamResult = eCSR_ROAM_RESULT_WDS_STARTED; + } + if( CSR_IS_INFRA_AP( pProfile ) ) + { + roamStatus = eCSR_ROAM_INFRA_IND; + roamResult = eCSR_ROAM_RESULT_INFRA_STARTED; + } + + //Only tell upper layer is we start the BSS because Vista doesn't like multiple connection + //indications. If we don't start the BSS ourself, handler of eSIR_SME_JOINED_NEW_BSS will + //trigger the connection start indication in Vista + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + //We start the IBSS (didn't find any matched IBSS out there) + roamInfo.pBssDesc = pSirBssDesc; + roamInfo.staId = (tANI_U8)pSmeStartBssRsp->staId; + vos_mem_copy(roamInfo.bssid, pSirBssDesc->bssId, + sizeof(tCsrBssid)); + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && + ( csrIsConcurrentSessionRunning( pMac ))) + { + pMac->roam.configParam.doBMPSWorkaround = 1; + } + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (pMac->roam.configParam.cc_switch_mode + != VOS_MCC_TO_SCC_SWITCH_DISABLE) { + pSession->connectedProfile.HTProfile.phymode = + csrRoamdot11modeToPhymode(pSmeStartBssRsp->HTProfile.dot11mode); + pSession->connectedProfile.HTProfile.htCapability = + pSmeStartBssRsp->HTProfile.htCapability; + pSession->connectedProfile.HTProfile.htSupportedChannelWidthSet = + pSmeStartBssRsp->HTProfile.htSupportedChannelWidthSet; + pSession->connectedProfile.HTProfile.htRecommendedTxWidthSet = + pSmeStartBssRsp->HTProfile.htRecommendedTxWidthSet; + pSession->connectedProfile.HTProfile.htSecondaryChannelOffset = + pSmeStartBssRsp->HTProfile.htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + pSession->connectedProfile.HTProfile.vhtCapability = + pSmeStartBssRsp->HTProfile.vhtCapability; + pSession->connectedProfile.HTProfile.vhtTxChannelWidthSet = + pSmeStartBssRsp->HTProfile.vhtTxChannelWidthSet; + pSession->connectedProfile.HTProfile.apCenterChan = + pSmeStartBssRsp->HTProfile.apCenterChan; + pSession->connectedProfile.HTProfile.apChanWidth = + pSmeStartBssRsp->HTProfile.apChanWidth; +#endif + } +#endif + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, roamStatus, roamResult ); + } + + csrScanCancelIdleScan(pMac); + + if( CSR_IS_WDS_STA( pProfile ) ) + { + //need to send stop BSS because we fail to send join_req + csrRoamIssueDisassociateCmd( pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED ); + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_STOPPED ); + } + break; + case eCsrStartBssFailure: +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + pIbssLog->status = WLAN_IBSS_STATUS_FAILURE; + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + roamStatus = eCSR_ROAM_IBSS_IND; + roamResult = eCSR_ROAM_RESULT_IBSS_STARTED; + if( CSR_IS_WDS( pProfile ) ) + { + roamStatus = eCSR_ROAM_WDS_IND; + roamResult = eCSR_ROAM_RESULT_WDS_STARTED; + } + if( CSR_IS_INFRA_AP( pProfile ) ) + { + roamStatus = eCSR_ROAM_INFRA_IND; + roamResult = eCSR_ROAM_RESULT_INFRA_START_FAILED; + } + if(Context) + { + pSirBssDesc = (tSirBssDescription *)Context; + } + else + { + pSirBssDesc = NULL; + } + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pSirBssDesc; + /* We need to associate_complete it first, because + Associate_start already indicated. */ + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, roamStatus, roamResult ); + csrSetDefaultDot11Mode( pMac ); + break; + case eCsrSilentlyStopRoaming: + // We are here because we try to start the same IBSS + //No message to PE + // return the roaming state to Joined. + smsLog(pMac, LOGW, FL("receives silently roaming indication")); + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId ); + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pSession->pConnectBssDesc; + if( roamInfo.pBssDesc ) + { + vos_mem_copy(&roamInfo.bssid, &roamInfo.pBssDesc->bssId, + sizeof(tCsrBssid)); + } + //Since there is no change in the current state, simply pass back no result otherwise + //HDD may be mistakenly mark to disconnected state. + csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_IBSS_IND, eCSR_ROAM_RESULT_NONE ); + break; + case eCsrSilentlyStopRoamingSaveState: + //We are here because we try to connect to the same AP + //No message to PE + smsLog(pMac, LOGW, FL("receives silently stop roaming indication")); + vos_mem_set(&roamInfo, sizeof(roamInfo), 0); + + /* To avoid resetting the substate to NONE */ + pMac->roam.curState[sessionId] = eCSR_ROAMING_STATE_JOINED; + //No need to change substate to wai_for_key because there is no state change + roamInfo.pBssDesc = pSession->pConnectBssDesc; + if( roamInfo.pBssDesc ) + { + vos_mem_copy(&roamInfo.bssid, &roamInfo.pBssDesc->bssId, + sizeof(tCsrBssid)); + } + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + roamInfo.nBeaconLength = pSession->connectedInfo.nBeaconLength; + roamInfo.nAssocReqLength = pSession->connectedInfo.nAssocReqLength; + roamInfo.nAssocRspLength = pSession->connectedInfo.nAssocRspLength; + roamInfo.pbFrames = pSession->connectedInfo.pbFrames; + roamInfo.staId = pSession->connectedInfo.staId; + roamInfo.u.pConnectedProfile = &pSession->connectedProfile; + if (0 == roamInfo.staId) + VOS_ASSERT(0); + pSession->bRefAssocStartCnt--; + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED); + csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_ASSOCIATED, eANI_BOOLEAN_TRUE); + break; + case eCsrReassocFailure: +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_REASSOC_FAILURE, NULL); +#endif + case eCsrJoinWdsFailure: + smsLog(pMac, LOGW, FL("failed to join WDS")); + csrFreeConnectBssDesc(pMac, sessionId); + csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile); + csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo ); + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss; + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_WDS_IND, + eCSR_ROAM_RESULT_WDS_NOT_ASSOCIATED); + //Need to issue stop_bss + break; + case eCsrJoinFailure: + case eCsrNothingToJoin: + case eCsrJoinFailureDueToConcurrency: + default: + { + smsLog(pMac, LOGW, FL("receives no association indication")); + smsLog(pMac, LOG1, FL("Assoc ref count %d"), + pSession->bRefAssocStartCnt); + if( CSR_IS_INFRASTRUCTURE( &pSession->connectedProfile ) || + CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ( pMac, sessionId ) ) + { + //do not free for the other profiles as we need to send down stop BSS later + csrFreeConnectBssDesc(pMac, sessionId); + csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile); + csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo ); + csrSetDefaultDot11Mode( pMac ); + } + + switch( pCommand->u.roamCmd.roamReason ) + { + // If this transition is because of an 802.11 OID, then we transition + // back to INIT state so we sit waiting for more OIDs to be issued and + // we don't start the IDLE timer. + case eCsrSmeIssuedFTReassoc: + case eCsrSmeIssuedAssocToSimilarAP: + case eCsrHddIssued: + case eCsrSmeIssuedDisassocForHandoff: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId ); + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss; + roamInfo.pProfile = &pCommand->u.roamCmd.roamProfile; + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + vos_mem_copy(&roamInfo.bssid, + &pSession->joinFailStatusCode.bssId, + sizeof(tCsrBssid)); + + /* Defeaturize this later if needed */ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + /* If Join fails while Handoff is in progress, indicate disassociated event to supplicant to reconnect */ + if (csrRoamIsHandoffInProgress(pMac, sessionId)) + { + /* Should indicate neighbor roam algorithm about the connect failure here */ + csrNeighborRoamIndicateConnect(pMac, (tANI_U8)sessionId, VOS_STATUS_E_FAILURE); + } +#endif + if(pSession->bRefAssocStartCnt > 0) + { + pSession->bRefAssocStartCnt--; + if(eCsrJoinFailureDueToConcurrency == Result) + { + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL); + } + else + { + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_FAILURE); + } + } + else + { + /* bRefAssocStartCnt is not incremented when + * eRoamState == eCsrStopRoamingDueToConcurrency + * in csrRoamJoinNextBss API. so handle this in + * else case by sending assoc failure + */ + csrRoamCallCallback(pMac, sessionId, &roamInfo, + pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_FAILURE, + eCSR_ROAM_RESULT_FAILURE); + } + smsLog(pMac, LOG1, FL(" roam(reason %d) failed"), pCommand->u.roamCmd.roamReason); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosUpdateHandOff((tANI_U8)sessionId, VOS_FALSE); + sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE); + csrScanStartIdleScan(pMac); + break; + case eCsrHddIssuedReassocToSameAP: + case eCsrSmeIssuedReassocToSameAP: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId); + + csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE); + csrScanStartIdleScan(pMac); + break; + case eCsrForcedDisassoc: + case eCsrForcedDeauth: + case eCsrSmeIssuedIbssJoinFailure: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId); + + if(eCsrSmeIssuedIbssJoinFailure == pCommand->u.roamCmd.roamReason) + { + // Notify HDD that IBSS join failed + csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_IBSS_IND, eCSR_ROAM_RESULT_IBSS_JOIN_FAILED); + } + else + { + csrRoamCallCallback(pMac, sessionId, NULL, + pCommand->u.roamCmd.roamId, + eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED); + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csrRoamLinkDown(pMac, sessionId); + + /* + * DelSta not done FW still in connected state so dont + * issue IMPS req + */ + + if (pMac->roam.deauthRspStatus == eSIR_SME_DEAUTH_STATUS) + { + smsLog(pMac, LOGW, FL("FW still in connected state ")); + break; + } + csrScanStartIdleScan(pMac); + break; + case eCsrForcedIbssLeave: + csrRoamCallCallback(pMac, sessionId, NULL, + pCommand->u.roamCmd.roamId, + eCSR_ROAM_IBSS_LEAVE, + eCSR_ROAM_RESULT_IBSS_STOP); + break; + case eCsrForcedDisassocMICFailure: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId ); + + csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_MIC_FAILURE); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_REQ, NULL); +#endif + csrScanStartIdleScan(pMac); + break; + case eCsrStopBss: + csrRoamCallCallback(pMac, sessionId, NULL, + pCommand->u.roamCmd.roamId, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_STOPPED); + break; + case eCsrForcedDisassocSta: + case eCsrForcedDeauthSta: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId); + if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + { + pSession = CSR_GET_SESSION(pMac, sessionId); + + if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) ) + { + roamInfo.u.pConnectedProfile = &pSession->connectedProfile; + vos_mem_copy(roamInfo.peerMac, + pCommand->u.roamCmd.peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = eCSR_ROAM_RESULT_FORCED; + roamInfo.statusCode = eSIR_SME_SUCCESS; + status = csrRoamCallCallback(pMac, sessionId, + &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_FORCED); + } + } + break; + case eCsrLostLink1: + // if lost link roam1 failed, then issue lost link Scan2 ... + csrScanRequestLostLink2(pMac, sessionId); + break; + case eCsrLostLink2: + // if lost link roam2 failed, then issue lost link scan3 ... + csrScanRequestLostLink3(pMac, sessionId); + break; + case eCsrLostLink3: + default: + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId ); + + /* We are done with one round of lost link roaming here */ + csrScanHandleFailedLostlink3(pMac, sessionId); + break; + } + break; + } + } + return ( fReleaseCommand ); +} + +eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, tCsrRoamProfile *pSrcProfile) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 size = 0; + + do + { + vos_mem_set(pDstProfile, sizeof(tCsrRoamProfile), 0); + if(pSrcProfile->BSSIDs.numOfBSSIDs) + { + size = sizeof(tCsrBssid) * pSrcProfile->BSSIDs.numOfBSSIDs; + pDstProfile->BSSIDs.bssid = vos_mem_malloc(size); + if ( NULL == pDstProfile->BSSIDs.bssid ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->BSSIDs.numOfBSSIDs = pSrcProfile->BSSIDs.numOfBSSIDs; + vos_mem_copy(pDstProfile->BSSIDs.bssid, + pSrcProfile->BSSIDs.bssid, size); + } + if(pSrcProfile->SSIDs.numOfSSIDs) + { + size = sizeof(tCsrSSIDInfo) * pSrcProfile->SSIDs.numOfSSIDs; + pDstProfile->SSIDs.SSIDList = vos_mem_malloc(size); + if ( NULL == pDstProfile->SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->SSIDs.numOfSSIDs = pSrcProfile->SSIDs.numOfSSIDs; + vos_mem_copy(pDstProfile->SSIDs.SSIDList, + pSrcProfile->SSIDs.SSIDList, size); + } + if(pSrcProfile->nWPAReqIELength) + { + pDstProfile->pWPAReqIE = vos_mem_malloc(pSrcProfile->nWPAReqIELength); + if ( NULL == pDstProfile->pWPAReqIE ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if (!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->nWPAReqIELength = pSrcProfile->nWPAReqIELength; + vos_mem_copy(pDstProfile->pWPAReqIE, pSrcProfile->pWPAReqIE, + pSrcProfile->nWPAReqIELength); + } + if(pSrcProfile->nRSNReqIELength) + { + pDstProfile->pRSNReqIE = vos_mem_malloc(pSrcProfile->nRSNReqIELength); + if ( NULL == pDstProfile->pRSNReqIE ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if (!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->nRSNReqIELength = pSrcProfile->nRSNReqIELength; + vos_mem_copy(pDstProfile->pRSNReqIE, pSrcProfile->pRSNReqIE, + pSrcProfile->nRSNReqIELength); + } +#ifdef FEATURE_WLAN_WAPI + if(pSrcProfile->nWAPIReqIELength) + { + pDstProfile->pWAPIReqIE = vos_mem_malloc(pSrcProfile->nWAPIReqIELength); + if ( NULL == pDstProfile->pWAPIReqIE ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->nWAPIReqIELength = pSrcProfile->nWAPIReqIELength; + vos_mem_copy(pDstProfile->pWAPIReqIE, pSrcProfile->pWAPIReqIE, + pSrcProfile->nWAPIReqIELength); + } +#endif /* FEATURE_WLAN_WAPI */ + if(pSrcProfile->nAddIEScanLength) + { + pDstProfile->pAddIEScan = vos_mem_malloc(pSrcProfile->nAddIEScanLength); + if ( NULL == pDstProfile->pAddIEScan ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->nAddIEScanLength = pSrcProfile->nAddIEScanLength; + vos_mem_copy(pDstProfile->pAddIEScan, pSrcProfile->pAddIEScan, + pSrcProfile->nAddIEScanLength); + } + if(pSrcProfile->nAddIEAssocLength) + { + pDstProfile->pAddIEAssoc = vos_mem_malloc(pSrcProfile->nAddIEAssocLength); + if ( NULL == pDstProfile->pAddIEAssoc ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->nAddIEAssocLength = pSrcProfile->nAddIEAssocLength; + vos_mem_copy(pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc, + pSrcProfile->nAddIEAssocLength); + } + if(pSrcProfile->ChannelInfo.ChannelList) + { + pDstProfile->ChannelInfo.ChannelList = vos_mem_malloc( + pSrcProfile->ChannelInfo.numOfChannels); + if ( NULL == pDstProfile->ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->ChannelInfo.numOfChannels = pSrcProfile->ChannelInfo.numOfChannels; + vos_mem_copy(pDstProfile->ChannelInfo.ChannelList, + pSrcProfile->ChannelInfo.ChannelList, + pSrcProfile->ChannelInfo.numOfChannels); + } + pDstProfile->AuthType = pSrcProfile->AuthType; + pDstProfile->EncryptionType = pSrcProfile->EncryptionType; + pDstProfile->mcEncryptionType = pSrcProfile->mcEncryptionType; + pDstProfile->negotiatedUCEncryptionType = pSrcProfile->negotiatedUCEncryptionType; + pDstProfile->negotiatedMCEncryptionType = pSrcProfile->negotiatedMCEncryptionType; + pDstProfile->negotiatedAuthType = pSrcProfile->negotiatedAuthType; +#ifdef WLAN_FEATURE_11W + pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled; + pDstProfile->MFPRequired = pSrcProfile->MFPRequired; + pDstProfile->MFPCapable = pSrcProfile->MFPCapable; +#endif + pDstProfile->BSSType = pSrcProfile->BSSType; + pDstProfile->phyMode = pSrcProfile->phyMode; + pDstProfile->csrPersona = pSrcProfile->csrPersona; + +#ifdef FEATURE_WLAN_WAPI + if(csrIsProfileWapi(pSrcProfile)) + { + if(pDstProfile->phyMode & eCSR_DOT11_MODE_11n) + { + pDstProfile->phyMode &= ~eCSR_DOT11_MODE_11n; + } + } +#endif /* FEATURE_WLAN_WAPI */ + pDstProfile->CBMode = pSrcProfile->CBMode; + pDstProfile->vht_channel_width = pSrcProfile->vht_channel_width; + /*Save the WPS info*/ + pDstProfile->bWPSAssociation = pSrcProfile->bWPSAssociation; + pDstProfile->bOSENAssociation = pSrcProfile->bOSENAssociation; + pDstProfile->uapsd_mask = pSrcProfile->uapsd_mask; + pDstProfile->beaconInterval = pSrcProfile->beaconInterval; + pDstProfile->privacy = pSrcProfile->privacy; + pDstProfile->fwdWPSPBCProbeReq = pSrcProfile->fwdWPSPBCProbeReq; + pDstProfile->csr80211AuthType = pSrcProfile->csr80211AuthType; + pDstProfile->dtimPeriod = pSrcProfile->dtimPeriod; + pDstProfile->ApUapsdEnable = pSrcProfile->ApUapsdEnable; + pDstProfile->SSIDs.SSIDList[0].ssidHidden = pSrcProfile->SSIDs.SSIDList[0].ssidHidden; + pDstProfile->protEnabled = pSrcProfile->protEnabled; + pDstProfile->obssProtEnabled = pSrcProfile->obssProtEnabled; + pDstProfile->cfg_protection = pSrcProfile->cfg_protection; + pDstProfile->wps_state = pSrcProfile->wps_state; + pDstProfile->ieee80211d = pSrcProfile->ieee80211d; + pDstProfile->sap_dot11mc = pSrcProfile->sap_dot11mc; + vos_mem_copy(&pDstProfile->Keys, &pSrcProfile->Keys, + sizeof(pDstProfile->Keys)); +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSrcProfile->MDID.mdiePresent) + { + pDstProfile->MDID.mdiePresent = 1; + pDstProfile->MDID.mobilityDomain = pSrcProfile->MDID.mobilityDomain; + } +#endif + vos_mem_copy(&pDstProfile->addIeParams, + &pSrcProfile->addIeParams, + sizeof(tSirAddIeParams)); + }while(0); + + if(!HAL_STATUS_SUCCESS(status)) + { + csrReleaseProfile(pMac, pDstProfile); + pDstProfile = NULL; + } + + return (status); +} + +eHalStatus csrRoamCopyConnectedProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pDstProfile ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamConnectedProfile *pSrcProfile = &pMac->roam.roamSession[sessionId].connectedProfile; + do + { + vos_mem_set(pDstProfile, sizeof(tCsrRoamProfile), 0); + if(pSrcProfile->bssid) + { + pDstProfile->BSSIDs.bssid = vos_mem_malloc(sizeof(tCsrBssid)); + if ( NULL == pDstProfile->BSSIDs.bssid ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + FL("failed to allocate memory for BSSID" + "%02x:%02x:%02x:%02x:%02x:%02x"), + pSrcProfile->bssid[0], pSrcProfile->bssid[1], + pSrcProfile->bssid[2], pSrcProfile->bssid[3], + pSrcProfile->bssid[4], pSrcProfile->bssid[5]); + break; + } + pDstProfile->BSSIDs.numOfBSSIDs = 1; + vos_mem_copy(pDstProfile->BSSIDs.bssid, pSrcProfile->bssid, + sizeof(tCsrBssid)); + } + if(pSrcProfile->SSID.ssId) + { + pDstProfile->SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if ( NULL == pDstProfile->SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + FL("failed to allocate memory for SSIDList" + "%02x:%02x:%02x:%02x:%02x:%02x"), + pSrcProfile->bssid[0], pSrcProfile->bssid[1], + pSrcProfile->bssid[2], pSrcProfile->bssid[3], + pSrcProfile->bssid[4], pSrcProfile->bssid[5]); + break; + } + pDstProfile->SSIDs.numOfSSIDs = 1; + pDstProfile->SSIDs.SSIDList[0].handoffPermitted = pSrcProfile->handoffPermitted; + pDstProfile->SSIDs.SSIDList[0].ssidHidden = pSrcProfile->ssidHidden; + vos_mem_copy(&pDstProfile->SSIDs.SSIDList[0].SSID, + &pSrcProfile->SSID, sizeof(tSirMacSSid)); + } + if(pSrcProfile->nAddIEAssocLength) + { + pDstProfile->pAddIEAssoc = vos_mem_malloc(pSrcProfile->nAddIEAssocLength); + if ( NULL == pDstProfile->pAddIEAssoc) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE, FL(" failed to allocate memory for additional IEs ") ); + break; + } + pDstProfile->nAddIEAssocLength = pSrcProfile->nAddIEAssocLength; + vos_mem_copy(pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc, + pSrcProfile->nAddIEAssocLength); + } + pDstProfile->ChannelInfo.ChannelList = vos_mem_malloc(1); + if ( NULL == pDstProfile->ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pDstProfile->ChannelInfo.numOfChannels = 1; + pDstProfile->ChannelInfo.ChannelList[0] = pSrcProfile->operationChannel; + pDstProfile->AuthType.numEntries = 1; + pDstProfile->AuthType.authType[0] = pSrcProfile->AuthType; + pDstProfile->negotiatedAuthType = pSrcProfile->AuthType; + pDstProfile->EncryptionType.numEntries = 1; + pDstProfile->EncryptionType.encryptionType[0] = pSrcProfile->EncryptionType; + pDstProfile->negotiatedUCEncryptionType = pSrcProfile->EncryptionType; + pDstProfile->mcEncryptionType.numEntries = 1; + pDstProfile->mcEncryptionType.encryptionType[0] = pSrcProfile->mcEncryptionType; + pDstProfile->negotiatedMCEncryptionType = pSrcProfile->mcEncryptionType; + pDstProfile->BSSType = pSrcProfile->BSSType; + pDstProfile->CBMode = pSrcProfile->CBMode; + vos_mem_copy(&pDstProfile->Keys, &pSrcProfile->Keys, + sizeof(pDstProfile->Keys)); +#ifdef WLAN_FEATURE_11W + pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled; + pDstProfile->MFPRequired = pSrcProfile->MFPRequired; + pDstProfile->MFPCapable = pSrcProfile->MFPCapable; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSrcProfile->MDID.mdiePresent) + { + pDstProfile->MDID.mdiePresent = 1; + pDstProfile->MDID.mobilityDomain = pSrcProfile->MDID.mobilityDomain; + } +#endif + + }while(0); + + if(!HAL_STATUS_SUCCESS(status)) + { + csrReleaseProfile(pMac, pDstProfile); + pDstProfile = NULL; + } + + return (status); +} + +eHalStatus csrRoamIssueConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tScanResultHandle hBSSList, + eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate, + tANI_BOOLEAN fClearScan) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + } + else + { + if( fClearScan ) + { + csrScanCancelIdleScan(pMac); + csrScanAbortMacScanNotForConnect(pMac, sessionId); + } + pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE; + if(NULL == pProfile) + { + //We can roam now + //Since pProfile is NULL, we need to build our own profile, set everything to default + //We can only support open and no encryption + pCommand->u.roamCmd.roamProfile.AuthType.numEntries = 1; + pCommand->u.roamCmd.roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; + pCommand->u.roamCmd.roamProfile.EncryptionType.numEntries = 1; + pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + pCommand->u.roamCmd.roamProfile.csrPersona = VOS_STA_MODE; + } + else + { + //make a copy of the profile + status = csrRoamCopyProfile(pMac, &pCommand->u.roamCmd.roamProfile, pProfile); + if(HAL_STATUS_SUCCESS(status)) + { + pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_TRUE; + } + } + + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.hBSSList = hBSSList; + pCommand->u.roamCmd.roamId = roamId; + pCommand->u.roamCmd.roamReason = reason; + //We need to free the BssList when the command is done + pCommand->u.roamCmd.fReleaseBssList = eANI_BOOLEAN_TRUE; + pCommand->u.roamCmd.fUpdateCurRoamProfile = eANI_BOOLEAN_TRUE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("CSR PERSONA=%d"), + pCommand->u.roamCmd.roamProfile.csrPersona); + status = csrQueueSmeCommand(pMac, pCommand, fImediate); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandRoam( pMac, pCommand ); + } + } + + return (status); +} +eHalStatus csrRoamIssueReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields *pMmodProfileFields, + eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + } + else + { + csrScanCancelIdleScan(pMac); + csrScanAbortMacScanNotForConnect(pMac, sessionId); + if(pProfile) + { + //This is likely trying to reassoc to different profile + pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE; + //make a copy of the profile + status = csrRoamCopyProfile(pMac, &pCommand->u.roamCmd.roamProfile, pProfile); + pCommand->u.roamCmd.fUpdateCurRoamProfile = eANI_BOOLEAN_TRUE; + } + else + { + status = csrRoamCopyConnectedProfile(pMac, sessionId, &pCommand->u.roamCmd.roamProfile); + //how to update WPA/WPA2 info in roamProfile?? + pCommand->u.roamCmd.roamProfile.uapsd_mask = pMmodProfileFields->uapsd_mask; + } + if(HAL_STATUS_SUCCESS(status)) + { + pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_TRUE; + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamId = roamId; + pCommand->u.roamCmd.roamReason = reason; + //We need to free the BssList when the command is done + //For reassoc there is no BSS list, so the boolean set to false + pCommand->u.roamCmd.hBSSList = CSR_INVALID_SCANRESULT_HANDLE; + pCommand->u.roamCmd.fReleaseBssList = eANI_BOOLEAN_FALSE; + pCommand->u.roamCmd.fReassoc = eANI_BOOLEAN_TRUE; + csrRoamRemoveDuplicateCommand(pMac, sessionId, pCommand, reason); + status = csrQueueSmeCommand(pMac, pCommand, fImediate); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE); + csrReleaseCommandRoam( pMac, pCommand ); + } + } + return (status); +} + +eHalStatus csrRoamEnqueuePreauth(tpAniSirGlobal pMac, tANI_U32 sessionId, tpSirBssDescription pBssDescription, + eCsrRoamReason reason, tANI_BOOLEAN fImmediate) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + } + else + { + if(pBssDescription) + { + //copy over the parameters we need later + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamReason = reason; + //this is the important parameter + //in this case we are using this field for the "next" BSS + pCommand->u.roamCmd.pLastRoamBss = pBssDescription; + status = csrQueueSmeCommand(pMac, pCommand, fImmediate); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to enqueue preauth command, status = %d"), status ); + csrReleaseCommandPreauth( pMac, pCommand ); + } + } + else + { + //Return failure + status = eHAL_STATUS_RESOURCES; + } + } + return (status); +} + +eHalStatus csrDequeueRoamCommand(tpAniSirGlobal pMac, eCsrRoamReason reason) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( (eSmeCommandRoam == pCommand->command) && + (eCsrPerformPreauth == reason)) + { + smsLog( pMac, LOG1, FL("DQ-Command = %d, Reason = %d"), + pCommand->command, pCommand->u.roamCmd.roamReason); + if (csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK )) { + csrReleaseCommandPreauth( pMac, pCommand ); + } + } + else if ((eSmeCommandRoam == pCommand->command) && + (eCsrSmeIssuedFTReassoc == reason)) + { + smsLog( pMac, LOG1, FL("DQ-Command = %d, Reason = %d"), + pCommand->command, pCommand->u.roamCmd.roamReason); + if (csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK )) { + csrReleaseCommandRoam( pMac, pCommand ); + } + } + else { + smsLog( pMac, LOGE, FL("Command = %d, Reason = %d "), + pCommand->command, pCommand->u.roamCmd.roamReason); + } + } + else { + smsLog( pMac, LOGE, FL("pEntry NULL for eWNI_SME_FT_PRE_AUTH_RSP")); + } + smeProcessPendingQueue( pMac ); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrRoamConnectWithBSSList(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tScanResultHandle hBssListIn, tANI_U32 *pRoamId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanResultHandle hBSSList; + tANI_U32 roamId = 0; + status = csrScanCopyResultList(pMac, hBssListIn, &hBSSList); + if(HAL_STATUS_SUCCESS(status)) + { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(pRoamId) + { + *pRoamId = roamId; + } + status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued, + roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("failed to start a join process")); + csrScanResultPurge(pMac, hBSSList); + } + } + return (status); +} + +eHalStatus csrRoamConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tScanResultHandle hBssListIn, tANI_U32 *pRoamId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tScanResultHandle hBSSList; + tCsrScanResultFilter *pScanFilter; + tANI_U32 roamId = 0; + tANI_BOOLEAN fCallCallback = eANI_BOOLEAN_FALSE; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (NULL == pSession) { + smsLog(pMac, LOGE, + FL("session does not exist for given sessionId:%d"), sessionId); + return eHAL_STATUS_FAILURE; + } + + if (NULL == pProfile) { + smsLog(pMac, LOGP, FL("No profile specified")); + return eHAL_STATUS_FAILURE; + } + /* Initialize the bssid count before proceeding with the Join requests */ + pSession->join_bssid_count = 0; + smsLog(pMac, LOG1, FL("called BSSType = %s (%d) authtype = %d " + "encryType = %d"), + lim_BssTypetoString(pProfile->BSSType), + pProfile->BSSType, + pProfile->AuthType.authType[0], + pProfile->EncryptionType.encryptionType[0]); + + if( CSR_IS_WDS( pProfile ) && + !HAL_STATUS_SUCCESS( status = csrIsBTAMPAllowed( pMac, pProfile->operationChannel ) ) ) + { + smsLog(pMac, LOGE, FL("Request for BT AMP connection failed, channel requested is different than infra = %d"), + pProfile->operationChannel); + return status; + } + csrRoamCancelRoaming(pMac, sessionId); + csrScanRemoveFreshScanCommand(pMac, sessionId); + csrScanCancelIdleScan(pMac); + //Only abort the scan if it is not used for other roam/connect purpose + csrScanAbortMacScan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT); + csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrHddIssued); + //Check whether ssid changes + if(csrIsConnStateConnected(pMac, sessionId)) + { + if(pProfile->SSIDs.numOfSSIDs && !csrIsSsidInList(pMac, &pSession->connectedProfile.SSID, &pProfile->SSIDs)) + { + csrRoamIssueDisassociateCmd(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + } + } + /* + * If roamSession.connectState is disconnecting that mean + * disconnect 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")); + status = csrRoamConnectWithBSSList(pMac, sessionId, pProfile, hBssListIn, pRoamId); + if(pRoamId) + { + roamId = *pRoamId; + } + if(!HAL_STATUS_SUCCESS(status)) + { + fCallCallback = eANI_BOOLEAN_TRUE; + } + } + else + { + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + //Try to connect to any BSS + if(NULL == pProfile) + { + //No encryption + pScanFilter->EncryptionType.numEntries = 1; + pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + }//we don't have a profile + else + { + //Here is the profile we need to connect to + status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); + }//We have a profile + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(pRoamId) + { + *pRoamId = roamId; + } + + if(HAL_STATUS_SUCCESS(status)) + { + /*Save the WPS info*/ + if(NULL != pProfile) + { + pScanFilter->bWPSAssociation = pProfile->bWPSAssociation; + pScanFilter->bOSENAssociation = pProfile->bOSENAssociation; + } + else + { + pScanFilter->bWPSAssociation = 0; + pScanFilter->bOSENAssociation = 0; + } + do + { + if( (pProfile && CSR_IS_WDS_AP( pProfile ) ) + || (pProfile && CSR_IS_INFRA_AP ( pProfile )) + ) + { + //This can be started right away + status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued, + roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" CSR failed to issue start BSS command with status = 0x%08X"), status); + fCallCallback = eANI_BOOLEAN_TRUE; + } + else + { + smsLog(pMac, LOG1, FL("Connect request to proceed for AMP/SoftAP mode")); + } + break; + } + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + smsLog(pMac, LOG1, "************ csrScanGetResult Status ********* %d", status); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued, + roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" CSR failed to issue connect command with status = 0x%08X"), status); + csrScanResultPurge(pMac, hBSSList); + fCallCallback = eANI_BOOLEAN_TRUE; + } + }//Have scan result + else if(NULL != pProfile) + { + //Check whether it is for start ibss + if(CSR_IS_START_IBSS(pProfile)) + { + status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued, + roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, " CSR failed to issue startIBSS command with status = 0x%08X", status); + fCallCallback = eANI_BOOLEAN_TRUE; + } + } + else + { + //scan for this SSID + status = csrScanForSSID(pMac, sessionId, pProfile, roamId, TRUE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" CSR failed to issue SSID scan command with status = 0x%08X"), status); + fCallCallback = eANI_BOOLEAN_TRUE; + } + else + { + smsLog(pMac, LOG1, FL("SSID scan requested for Infra connect req")); + } + } + } + else + { + fCallCallback = eANI_BOOLEAN_TRUE; + } + } while (0); + if(NULL != pProfile) + { + //we need to free memory for filter if profile exists + csrFreeScanFilter(pMac, pScanFilter); + } + }//Got the scan filter from profile + + vos_mem_free(pScanFilter); + }//allocated memory for pScanFilter + }//No Bsslist coming in + //tell the caller if we fail to trigger a join request + if( fCallCallback ) + { + csrRoamCallCallback(pMac, sessionId, NULL, roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE); + } + + return (status); +} +eHalStatus csrRoamReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + tANI_U32 *pRoamId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fCallCallback = eANI_BOOLEAN_TRUE; + tANI_U32 roamId = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL == pProfile) + { + smsLog(pMac, LOGP, FL("No profile specified")); + return eHAL_STATUS_FAILURE; + } + smsLog(pMac, LOG1, FL("called BSSType = %s (%d) authtype = %d " + "encryType = %d"), + lim_BssTypetoString(pProfile->BSSType), + pProfile->BSSType, + pProfile->AuthType.authType[0], + pProfile->EncryptionType.encryptionType[0]); + + csrScanRemoveFreshScanCommand(pMac, sessionId); + csrScanCancelIdleScan(pMac); + csrScanAbortMacScanNotForConnect(pMac, sessionId); + csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrHddIssuedReassocToSameAP); + if(csrIsConnStateConnected(pMac, sessionId)) + { + if(pProfile) + { + if(pProfile->SSIDs.numOfSSIDs && + csrIsSsidInList(pMac, &pSession->connectedProfile.SSID, &pProfile->SSIDs)) + { + fCallCallback = eANI_BOOLEAN_FALSE; + } + else + { + smsLog(pMac, LOG1, FL("Not connected to the same SSID asked in the profile")); + } + } + else if (!vos_mem_compare(&modProfileFields, + &pSession->connectedProfile.modifyProfileFields, + sizeof(tCsrRoamModifyProfileFields))) + { + fCallCallback = eANI_BOOLEAN_FALSE; + } + else + { + smsLog(pMac, LOG1, FL("Either the profile is NULL or none of the fields " + "in tCsrRoamModifyProfileFields got modified")); + } + } + else + { + smsLog(pMac, LOG1, FL("Not connected! No need to reassoc")); + } + if(!fCallCallback) + { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(pRoamId) + { + *pRoamId = roamId; + } + + status = csrRoamIssueReassoc(pMac, sessionId, pProfile, &modProfileFields, + eCsrHddIssuedReassocToSameAP, roamId, eANI_BOOLEAN_FALSE); + } + else + { + status = csrRoamCallCallback(pMac, sessionId, NULL, roamId, + eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE); + } + return status; +} +eHalStatus csrRoamJoinLastProfile(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanResultHandle hBSSList = NULL; + tCsrScanResultFilter *pScanFilter = NULL; + tANI_U32 roamId; + tCsrRoamProfile *pProfile = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + do + { + if(pSession->pCurRoamProfile) + { + csrScanCancelIdleScan(pMac); + csrScanAbortMacScanNotForConnect(pMac, sessionId); + //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect + pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( NULL == pProfile ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + break; + vos_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile); + if (!HAL_STATUS_SUCCESS(status)) + break; + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(HAL_STATUS_SUCCESS(status)) + { + //we want to put the last connected BSS to the very beginning, if possible + csrMoveBssToHeadFromBSSID(pMac, &pSession->connectedProfile.bssid, hBSSList); + status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued, + roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + csrScanResultPurge(pMac, hBSSList); + break; + } + } + else + { + //Do a scan on this profile + //scan for this SSID only in case the AP suppresses SSID + status = csrScanForSSID(pMac, sessionId, pProfile, roamId, TRUE); + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + } + }//We have a profile + else + { + smsLog(pMac, LOGW, FL("cannot find a roaming profile")); + break; + } + }while(0); + if(pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + if(NULL != pProfile) + { + csrReleaseProfile(pMac, pProfile); + vos_mem_free(pProfile); + } + return (status); +} +eHalStatus csrRoamReconnect(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + if(csrIsConnStateConnected(pMac, sessionId)) + { + status = csrRoamIssueDisassociateCmd(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrRoamJoinLastProfile(pMac, sessionId); + } + } + return (status); +} + +eHalStatus csrRoamConnectToLastProfile(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGW, FL("is called")); + csrRoamCancelRoaming(pMac, sessionId); + csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrHddIssued); + if(csrIsConnStateDisconnected(pMac, sessionId)) + { + status = csrRoamJoinLastProfile(pMac, sessionId); + } + return (status); +} + +eHalStatus csrRoamProcessDisassocDeauth( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fDisassoc, tANI_BOOLEAN fMICFailure ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fComplete = eANI_BOOLEAN_FALSE; + eCsrRoamSubState NewSubstate; + tANI_U32 sessionId = pCommand->sessionId; + + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ) + { + smsLog(pMac, LOG1, FL(" Stop Wait for key timer and change substate to" + " eCSR_ROAM_SUBSTATE_NONE")); + csrRoamStopWaitForKeyTimer( pMac ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } + // change state to 'Roaming'... + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId ); + + if ( csrIsConnStateIbss( pMac, sessionId ) ) + { + // If we are in an IBSS, then stop the IBSS... + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ); + fComplete = (!HAL_STATUS_SUCCESS(status)); + } + else if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + /* In Infrastructure, we need to disassociate from the + Infrastructure network... */ + NewSubstate = eCSR_ROAM_SUBSTATE_DISASSOC_FORCED; + if(eCsrSmeIssuedDisassocForHandoff == pCommand->u.roamCmd.roamReason) + { + NewSubstate = eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF; + } + else if ((eCsrForcedDisassoc == pCommand->u.roamCmd.roamReason) + && (eSIR_MAC_DISASSOC_LEAVING_BSS_REASON == + pCommand->u.roamCmd.reason)) + { + NewSubstate = eCSR_ROAM_SUBSTATE_DISASSOC_STA_HAS_LEFT; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("set to substate eCSR_ROAM_SUBSTATE_DISASSOC_STA_HAS_LEFT")); + } + if (eCsrSmeIssuedDisassocForHandoff != pCommand->u.roamCmd.roamReason) { + // If we are in neighbor preauth done state then on receiving + // disassoc or deauth we dont roam instead we just disassoc + // from current ap and then go to disconnected state + // This happens for ESE and 11r FT connections ONLY. +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csrRoamIs11rAssoc(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, sessionId); + } +#endif +#ifdef FEATURE_WLAN_ESE + if (csrRoamIsESEAssoc(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, sessionId); + } +#endif +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsFastRoamEnabled(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, sessionId); + } +#endif + } + if( fDisassoc ) + { + status = csrRoamIssueDisassociate( pMac, sessionId, NewSubstate, fMICFailure ); + } + else + { + status = csrRoamIssueDeauth( pMac, sessionId, eCSR_ROAM_SUBSTATE_DEAUTH_REQ ); + } + fComplete = (!HAL_STATUS_SUCCESS(status)); + } + else if ( csrIsConnStateWds( pMac, sessionId ) ) + { + if( CSR_IS_WDS_AP( &pMac->roam.roamSession[sessionId].connectedProfile ) ) + { + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ); + fComplete = (!HAL_STATUS_SUCCESS(status)); + } + //This has to be WDS station + else if( csrIsConnStateConnectedWds( pMac, sessionId ) ) //This has to be WDS station + { + + pCommand->u.roamCmd.fStopWds = eANI_BOOLEAN_TRUE; + if( fDisassoc ) + { + status = csrRoamIssueDisassociate( pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, fMICFailure ); + fComplete = (!HAL_STATUS_SUCCESS(status)); + } + } + } else { + // we got a dis-assoc request while not connected to any peer + // just complete the command + fComplete = eANI_BOOLEAN_TRUE; + status = eHAL_STATUS_FAILURE; + } + if(fComplete) + { + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + + if(HAL_STATUS_SUCCESS(status)) + { + if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + //Set the state to disconnect here + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } + } + else + { + smsLog(pMac, LOGW, FL(" failed with status %d"), status); + } + return (status); +} + +/** + * csr_prepare_disconnect_command() - function to prepare disconnect command + * @mac: pointer to global mac structure + * @session_id: sme session index + * @sme_cmd: pointer to sme command being prepared + * + * Function to prepare internal sme disconnect command + * Return: eHAL_STATUS_SUCCESS on success else eHAL_STATUS_RESOURCES on failure + */ + +eHalStatus csr_prepare_disconnect_command(tpAniSirGlobal mac, + tANI_U32 session_id, tSmeCmd **sme_cmd) +{ + tSmeCmd *command; + + command = csrGetCommandBuffer(mac); + if (!command) { + smsLog(mac, LOGE, FL("fail to get command buffer")); + return eHAL_STATUS_RESOURCES; + } + + command->command = eSmeCommandRoam; + command->sessionId = (tANI_U8)session_id; + command->u.roamCmd.roamReason = eCsrForcedDisassoc; + + *sme_cmd = command; + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrRoamIssueDisassociateCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + + do + { + pCommand = csrGetCommandBuffer( pMac ); + if ( !pCommand ) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + break; + } + //Change the substate in case it is wait-for-key + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ) + { + csrRoamStopWaitForKeyTimer( pMac ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + smsLog( pMac, LOG1, FL("Disassociate reason: %d, sessionId: %d"), + reason,sessionId); + switch ( reason ) + { + case eCSR_DISCONNECT_REASON_MIC_ERROR: + pCommand->u.roamCmd.roamReason = eCsrForcedDisassocMICFailure; + break; + case eCSR_DISCONNECT_REASON_DEAUTH: + pCommand->u.roamCmd.roamReason = eCsrForcedDeauth; + break; + case eCSR_DISCONNECT_REASON_HANDOFF: + pCommand->u.roamCmd.roamReason = eCsrSmeIssuedDisassocForHandoff; + break; + case eCSR_DISCONNECT_REASON_UNSPECIFIED: + case eCSR_DISCONNECT_REASON_DISASSOC: + pCommand->u.roamCmd.roamReason = eCsrForcedDisassoc; + break; + case eCSR_DISCONNECT_REASON_IBSS_JOIN_FAILURE: + pCommand->u.roamCmd.roamReason = eCsrSmeIssuedIbssJoinFailure; + break; + case eCSR_DISCONNECT_REASON_IBSS_LEAVE: + pCommand->u.roamCmd.roamReason = eCsrForcedIbssLeave; + break; + case eCSR_DISCONNECT_REASON_STA_HAS_LEFT: + pCommand->u.roamCmd.roamReason = eCsrForcedDisassoc; + pCommand->u.roamCmd.reason = eSIR_MAC_DISASSOC_LEAVING_BSS_REASON; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("SME convert to internal reason code eCsrStaHasLeft")); + break; + default: + break; + } + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandRoam( pMac, pCommand ); + } + } while( 0 ); + return( status ); +} + +eHalStatus csrRoamIssueStopBssCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN fHighPriority ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + pCommand = csrGetCommandBuffer( pMac ); + if ( NULL != pCommand ) + { + //Change the substate in case it is wait-for-key + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId) ) + { + csrRoamStopWaitForKeyTimer( pMac ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamReason = eCsrStopBss; + status = csrQueueSmeCommand(pMac, pCommand, fHighPriority); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandRoam( pMac, pCommand ); + } + } + else + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + } + return ( status ); +} + +eHalStatus csrRoamDisconnectInternal(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + //Not to call cancel roaming here + //Only issue disconnect when necessary + if(csrIsConnStateConnected(pMac, sessionId) || csrIsBssTypeIBSS(pSession->connectedProfile.BSSType) + || csrIsBssTypeWDS(pSession->connectedProfile.BSSType) + || csrIsRoamCommandWaitingForSession(pMac, sessionId) ) + + { + smsLog(pMac, LOG2, FL("called")); + status = csrRoamIssueDisassociateCmd(pMac, sessionId, reason); + } + else + { + pMac->roam.roamSession[sessionId].connectState = + eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING; + csrScanAbortScanForSSID(pMac, sessionId); + status = eHAL_STATUS_CMD_NOT_QUEUED; + smsLog( pMac, LOGE, + FL("Disconnect not queued, Abort Scan for SSID")); + } + return (status); +} + +eHalStatus csrRoamDisconnect(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + csrRoamCancelRoaming(pMac, sessionId); + csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrForcedDisassoc); + + return (csrRoamDisconnectInternal(pMac, sessionId, reason)); +} + +eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tDot11fBeaconIEs *pIesTemp = pIes; + tANI_U8 index; + tCsrRoamSession *pSession = NULL; + tCsrRoamConnectedProfile *pConnectProfile = NULL; + + pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pSession) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } + + pConnectProfile = &pSession->connectedProfile; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("csrRoamSaveConnectedInfomation")); + } +#endif + if(pConnectProfile->pAddIEAssoc) + { + vos_mem_free(pConnectProfile->pAddIEAssoc); + pConnectProfile->pAddIEAssoc = NULL; + } + vos_mem_set(&pSession->connectedProfile, sizeof(tCsrRoamConnectedProfile), 0); + pConnectProfile->AuthType = pProfile->negotiatedAuthType; + pConnectProfile->AuthInfo = pProfile->AuthType; + pConnectProfile->CBMode = pProfile->CBMode; //*** this may not be valid + pConnectProfile->EncryptionType = pProfile->negotiatedUCEncryptionType; + pConnectProfile->EncryptionInfo = pProfile->EncryptionType; + pConnectProfile->mcEncryptionType = pProfile->negotiatedMCEncryptionType; + pConnectProfile->mcEncryptionInfo = pProfile->mcEncryptionType; + pConnectProfile->BSSType = pProfile->BSSType; + pConnectProfile->modifyProfileFields.uapsd_mask = pProfile->uapsd_mask; + pConnectProfile->operationChannel = pSirBssDesc->channelId; + pConnectProfile->beaconInterval = pSirBssDesc->beaconInterval; + if (!pConnectProfile->beaconInterval) + { + smsLog(pMac, LOGW, FL("ERROR: Beacon interval is ZERO")); + } + vos_mem_copy(&pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys)); + /* Saving the additional IE`s like Hot spot indication element and + extended capabilities */ + if(pProfile->nAddIEAssocLength) + { + pConnectProfile->pAddIEAssoc = vos_mem_malloc(pProfile->nAddIEAssocLength); + if ( NULL == pConnectProfile->pAddIEAssoc ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("Failed to allocate memory for additional IEs")) ; + return eHAL_STATUS_FAILURE; + } + pConnectProfile->nAddIEAssocLength = pProfile->nAddIEAssocLength; + vos_mem_copy(pConnectProfile->pAddIEAssoc, pProfile->pAddIEAssoc, + pProfile->nAddIEAssocLength); + } + +#ifdef WLAN_FEATURE_11W + pConnectProfile->MFPEnabled = pProfile->MFPEnabled; + pConnectProfile->MFPRequired = pProfile->MFPRequired; + pConnectProfile->MFPCapable = pProfile->MFPCapable; +#endif + //Save bssid + csrGetBssIdBssDesc(pMac, pSirBssDesc, &pConnectProfile->bssid); +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSirBssDesc->mdiePresent) + { + pConnectProfile->MDID.mdiePresent = 1; + pConnectProfile->MDID.mobilityDomain = (pSirBssDesc->mdie[1] << 8) | (pSirBssDesc->mdie[0]); + } +#endif + if( NULL == pIesTemp ) + { + status = csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesTemp); + } +#ifdef FEATURE_WLAN_ESE + if ((csrIsProfileESE(pProfile) || + (HAL_STATUS_SUCCESS(status) && (pIesTemp->ESEVersion.present) + && (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM))) + && (pMac->roam.configParam.isEseIniFeatureEnabled)) + { + pConnectProfile->isESEAssoc = 1; + } +#endif + //save ssid + if(HAL_STATUS_SUCCESS(status)) + { + if(pIesTemp->SSID.present) + { + pConnectProfile->SSID.length = pIesTemp->SSID.num_ssid; + vos_mem_copy(pConnectProfile->SSID.ssId, pIesTemp->SSID.ssid, + pIesTemp->SSID.num_ssid); + } + + //Save the bss desc + status = csrRoamSaveConnectedBssDesc(pMac, sessionId, pSirBssDesc); + + if( CSR_IS_QOS_BSS(pIesTemp) || pIesTemp->HTCaps.present) + { + //Some HT AP's dont send WMM IE so in that case we assume all HT Ap's are Qos Enabled AP's + pConnectProfile->qap = TRUE; + } + else + { + pConnectProfile->qap = FALSE; + } + + if (pIesTemp->ExtCap.present) + { + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) + pIesTemp->ExtCap.bytes; + pConnectProfile->proxyARPService = p_ext_cap->proxyARPService; + } + + if ( NULL == pIes ) + { + //Free memory if it allocated locally + vos_mem_free(pIesTemp); + } + } + //Save Qos connection + pConnectProfile->qosConnection = pMac->roam.roamSession[sessionId].fWMMConnection; + + if(!HAL_STATUS_SUCCESS(status)) + { + csrFreeConnectBssDesc(pMac, sessionId); + } + for(index = 0; index < pProfile->SSIDs.numOfSSIDs; index++) + { + if ((pProfile->SSIDs.SSIDList[index].SSID.length == pConnectProfile->SSID.length) && + vos_mem_compare(pProfile->SSIDs.SSIDList[index].SSID.ssId, + pConnectProfile->SSID.ssId, + pConnectProfile->SSID.length)) + { + pConnectProfile->handoffPermitted = pProfile->SSIDs.SSIDList[index].handoffPermitted; + break; + } + pConnectProfile->handoffPermitted = FALSE; + } + + return (status); +} + + +boolean is_disconnect_pending(tpAniSirGlobal pmac, + uint8_t sessionid) +{ + tListElem *entry = NULL; + tListElem *next_entry = NULL; + tSmeCmd *command = NULL; + bool disconnect_cmd_exist = false; + + csrLLLock(&pmac->sme.smeCmdPendingList); + entry = csrLLPeekHead(&pmac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK); + while (entry) { + next_entry = csrLLNext(&pmac->sme.smeCmdPendingList, + entry, LL_ACCESS_NOLOCK); + + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (command && CSR_IS_DISCONNECT_COMMAND(command) && + command->sessionId == sessionid){ + disconnect_cmd_exist = true; + break; + } + entry = next_entry; + } + csrLLUnlock(&pmac->sme.smeCmdPendingList); + return disconnect_cmd_exist; +} + +static void csrRoamJoinRspProcessor( tpAniSirGlobal pMac, tSirSmeJoinRsp *pSmeJoinRsp ) +{ + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamSession *pSession; + + if (pSmeJoinRsp) + pSession = CSR_GET_SESSION(pMac, pSmeJoinRsp->sessionId); + else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Sme Join Response is NULL")); + return; + } + if (!pSession) { + smsLog(pMac, LOGE, FL("session %d not found"), pSmeJoinRsp->sessionId); + return; + } + //The head of the active list is the request we sent + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + } + if ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode ) + { + if(pCommand && eCsrSmeIssuedAssocToSimilarAP == pCommand->u.roamCmd.roamReason) + { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, pSmeJoinRsp->sessionId, SME_QOS_CSR_HANDOFF_COMPLETE, NULL); +#endif + } + + pSession->supported_nss_1x1 = pSmeJoinRsp->supported_nss_1x1; + smsLog(pMac, LOG1, FL("SME session supported nss: %d"), + pSession->supported_nss_1x1); + + /* The join bssid count can be reset as soon as + * we are done with the join requests and returning + * the response to upper layers + */ + pSession->join_bssid_count = 0; + csrRoamComplete( pMac, eCsrJoinSuccess, (void *)pSmeJoinRsp ); + } + else + { + tANI_U32 roamId = 0; + bool is_dis_pending; + //The head of the active list is the request we sent + //Try to get back the same profile and roam again + if(pCommand) + { + roamId = pCommand->u.roamCmd.roamId; + } + pSession->joinFailStatusCode.statusCode = pSmeJoinRsp->statusCode; + pSession->joinFailStatusCode.reasonCode = pSmeJoinRsp->protStatusCode; + smsLog( pMac, LOGW, "SmeJoinReq failed with statusCode= 0x%08X [%d]", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode ); +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + /* If Join fails while Handoff is in progress, indicate disassociated event to supplicant to reconnect */ + if (csrRoamIsHandoffInProgress(pMac, pSmeJoinRsp->sessionId)) + { + csrRoamCallCallback(pMac, pSmeJoinRsp->sessionId, NULL, roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED); + /* Should indicate neighbor roam algorithm about the connect failure here */ + csrNeighborRoamIndicateConnect(pMac, pSmeJoinRsp->sessionId, VOS_STATUS_E_FAILURE); + } +#endif + /* + * if userspace has issued disconnection, + * driver should not continue connecting + */ + is_dis_pending = is_disconnect_pending(pMac, pSession->sessionId); + + if (pCommand && (pSession->join_bssid_count < CSR_MAX_BSSID_COUNT) && + !is_dis_pending) + { + if(CSR_IS_WDS_STA( &pCommand->u.roamCmd.roamProfile )) + { + pCommand->u.roamCmd.fStopWds = eANI_BOOLEAN_TRUE; + pSession->connectedProfile.BSSType = eCSR_BSS_TYPE_WDS_STA; + csrRoamReissueRoamCommand(pMac); + } + else if( CSR_IS_WDS( &pCommand->u.roamCmd.roamProfile ) ) + { + pSession->join_bssid_count = 0; + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + else + { + csrRoam(pMac, pCommand); + } + } + else { + /* When the upper layers issue a connect command, there is a + * roam command with reason eCsrHddIssued that gets enqueued + * and an associated timer for the SME command timeout is + * started which is currently 120 seconds. This command would + * be dequeued only upon succesfull connections. In case of join + * failures, if there are too many BSS in the cache, and if we + * fail Join requests with all of them, there is a chance of + * timing out the above timer. + */ + if (pSession->join_bssid_count >= CSR_MAX_BSSID_COUNT) + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Excessive Join Request Failures")); + + if (is_dis_pending) + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("disconnect is pending, complete roam")); + pSession->join_bssid_count = 0; + csrRoamComplete(pMac, eCsrNothingToJoin, NULL); + } + } /*else: ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode ) */ +} + +eHalStatus csrRoamIssueJoin( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, + tCsrRoamProfile *pProfile, tANI_U32 roamId ) +{ + eHalStatus status; + smsLog( pMac, LOG1, "Attempting to Join Bssid= "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pSirBssDesc->bssId)); + + // Set the roaming substate to 'join attempt'... + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId); + // attempt to Join this BSS... + status = csrSendJoinReqMsg( pMac, sessionId, pSirBssDesc, pProfile, pIes, eWNI_SME_JOIN_REQ ); + return (status); +} + +static eHalStatus csrRoamIssueReassociate( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile) +{ + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId); + // Set the roaming substate to 'join attempt'... + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_REASSOC_REQ, sessionId ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL(" calling csrSendJoinReqMsg (eWNI_SME_REASSOC_REQ)")); + // attempt to Join this BSS... + return csrSendJoinReqMsg( pMac, sessionId, pSirBssDesc, pProfile, pIes, eWNI_SME_REASSOC_REQ); +} + +void csrRoamReissueRoamCommand(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + tCsrRoamInfo roamInfo; + tANI_U32 sessionId; + tCsrRoamSession *pSession; + + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if ( eSmeCommandRoam == pCommand->command ) + { + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + /* + * While switching between two AP, csr will reissue roam command + * again to the nextbss if it was interrupted by the dissconnect + * req for the previous bss. During this csr is incrementing + * bRefAssocStartCnt twice. So reset the bRefAssocStartCnt. + */ + if (pSession->bRefAssocStartCnt > 0) { + pSession->bRefAssocStartCnt--; + } + if( pCommand->u.roamCmd.fStopWds ) + { + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss; + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + if (CSR_IS_WDS(&pSession->connectedProfile)){ + pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED; + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_WDS_IND, + eCSR_ROAM_RESULT_WDS_DISASSOCIATED); + }else if (CSR_IS_INFRA_AP(&pSession->connectedProfile)){ + pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED; + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_DISASSOCIATED); + } + + + if( !HAL_STATUS_SUCCESS( csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ) ) ) + { + smsLog(pMac, LOGE, " Failed to reissue stop_bss command for WDS after disassociated"); + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + } + else + { + if (pSession->bRefAssocStartCnt > 0) + { + /* bRefAssocStartCnt was incremented in csrRoamJoinNextBss + * when the roam command issued previously. As part of reissuing + * the roam command again csrRoamJoinNextBss is going increment + * RefAssocStartCnt. So make sure to decrement the bRefAssocStartCnt + */ + pSession->bRefAssocStartCnt--; + } + + if(eCsrStopRoaming == csrRoamJoinNextBss(pMac, pCommand, eANI_BOOLEAN_TRUE)) + { + smsLog(pMac, LOGW, " Failed to reissue join command after disassociated"); + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + } + } + else + { + smsLog(pMac, LOGW, " Command is not roaming after disassociated"); + } + } + else + { + smsLog(pMac, LOGE, " Disassoc rsp cannot continue because no command is available"); + } +} + +tANI_BOOLEAN csrIsRoamCommandWaitingForSession(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tListElem *pEntry; + tSmeCmd *pCommand = NULL; + /* Always lock active list before locking pending list */ + csrLLLock( &pMac->sme.smeCmdActiveList ); + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK); + if(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( ( eSmeCommandRoam == pCommand->command ) && ( sessionId == pCommand->sessionId ) ) + { + fRet = eANI_BOOLEAN_TRUE; + } + } + if(eANI_BOOLEAN_FALSE == fRet) + { + csrLLLock(&pMac->sme.smeCmdPendingList); + pEntry = csrLLPeekHead(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK); + while(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( ( eSmeCommandRoam == pCommand->command ) && ( sessionId == pCommand->sessionId ) ) + { + fRet = eANI_BOOLEAN_TRUE; + break; + } + pEntry = csrLLNext(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK); + } + csrLLUnlock(&pMac->sme.smeCmdPendingList); + } + if (eANI_BOOLEAN_FALSE == fRet) + { + csrLLLock(&pMac->roam.roamCmdPendingList); + pEntry = csrLLPeekHead(&pMac->roam.roamCmdPendingList, LL_ACCESS_NOLOCK); + while (pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (( eSmeCommandRoam == pCommand->command ) && ( sessionId == pCommand->sessionId ) ) + { + fRet = eANI_BOOLEAN_TRUE; + break; + } + pEntry = csrLLNext(&pMac->roam.roamCmdPendingList, pEntry, LL_ACCESS_NOLOCK); + } + csrLLUnlock(&pMac->roam.roamCmdPendingList); + } + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + return (fRet); +} + +tANI_BOOLEAN csrIsRoamCommandWaiting(tpAniSirGlobal pMac) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tANI_U32 i; + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && ( fRet = csrIsRoamCommandWaitingForSession( pMac, i ) ) ) + { + break; + } + } + return ( fRet ); +} + +tANI_BOOLEAN csrIsCommandWaiting(tpAniSirGlobal pMac) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + /* Always lock active list before locking pending list */ + csrLLLock( &pMac->sme.smeCmdActiveList ); + fRet = csrLLIsListEmpty(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK); + if(eANI_BOOLEAN_FALSE == fRet) + { + fRet = csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK); + } + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + return (fRet); +} + +tANI_BOOLEAN csrIsScanForRoamCommandActive( tpAniSirGlobal pMac ) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tListElem *pEntry; + tCsrCmd *pCommand; + /* Always lock active list before locking pending list */ + csrLLLock( &pMac->sme.smeCmdActiveList ); + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK); + if( pEntry ) + { + pCommand = GET_BASE_ADDR(pEntry, tCsrCmd, Link); + if( ( eCsrRoamCommandScan == pCommand->command ) && + ( ( eCsrScanForSsid == pCommand->u.scanCmd.reason ) || + ( eCsrScanForCapsChange == pCommand->u.scanCmd.reason ) || + ( eCsrScanP2PFindPeer == pCommand->u.scanCmd.reason ) ) ) + { + fRet = eANI_BOOLEAN_TRUE; + } + } + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + return (fRet); +} +eHalStatus csrRoamIssueReassociateCmd( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand = NULL; + tANI_BOOLEAN fHighPriority = eANI_BOOLEAN_TRUE; + tANI_BOOLEAN fRemoveCmd = FALSE; + tListElem *pEntry; + // Delete the old assoc command. All is setup for reassoc to be serialized + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( !pCommand ) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + return eHAL_STATUS_RESOURCES; + } + if ( eSmeCommandRoam == pCommand->command ) + { + if (pCommand->u.roamCmd.roamReason == eCsrSmeIssuedAssocToSimilarAP) + { + fRemoveCmd = csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ); + } + else + { + smsLog( pMac, LOGE, FL(" Unexpected active roam command present ") ); + } + if (fRemoveCmd == FALSE) + { + // Implies we did not get the serialized assoc command we + // were expecting + pCommand = NULL; + } + } + } + if(NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer as expected based on previous connect roam command") ); + return eHAL_STATUS_RESOURCES; + } + do + { + //Change the substate in case it is wait-for-key + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ) + { + csrRoamStopWaitForKeyTimer( pMac ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId ); + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamReason = eCsrSmeIssuedFTReassoc; + status = csrQueueSmeCommand(pMac, pCommand, fHighPriority); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandRoam( pMac, pCommand ); + } + } while( 0 ); + + return( status ); +} +static void csrRoamingStateConfigCnfProcessor( tpAniSirGlobal pMac, tANI_U32 result ) +{ + tListElem *pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDesc = NULL; + tSmeCmd *pCommand = NULL; + tANI_U32 sessionId; + tCsrRoamSession *pSession; + if(NULL == pEntry) + { + smsLog(pMac, LOGE, " CFG_CNF with active list empty"); + return; + } + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if(CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming) + { + /* The roaming is canceled. Simply complete the command */ + smsLog(pMac, LOGW, FL(" Roam command canceled")); + csrRoamComplete(pMac, eCsrNothingToJoin, NULL); + } + /* If the roaming has stopped, not to continue the roaming command*/ + else if ( !CSR_IS_ROAMING(pSession) && CSR_IS_ROAMING_COMMAND(pCommand) ) + { + //No need to complete roaming here as it already completes + smsLog(pMac, LOGW, FL(" Roam command (reason %d) aborted due to roaming completed\n"), + pCommand->u.roamCmd.roamReason); + csrSetAbortRoamingCommand( pMac, pCommand ); + csrRoamComplete(pMac, eCsrNothingToJoin, NULL); + } + else + { + if ( CCM_IS_RESULT_SUCCESS(result) ) + { + smsLog(pMac, LOG2, "Cfg sequence complete"); + // Successfully set the configuration parameters for the new Bss. Attempt to + // join the roaming Bss. + if(pCommand->u.roamCmd.pRoamBssEntry) + { + pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link); + pBssDesc = &pScanResult->Result.BssDescriptor; + } + if ( csrIsBssTypeIBSS( pCommand->u.roamCmd.roamProfile.BSSType ) || + CSR_IS_WDS( &pCommand->u.roamCmd.roamProfile ) + || CSR_IS_INFRA_AP(&pCommand->u.roamCmd.roamProfile) + ) + { + if(!HAL_STATUS_SUCCESS(csrRoamIssueStartBss( pMac, sessionId, + &pSession->bssParams, &pCommand->u.roamCmd.roamProfile, + pBssDesc, pCommand->u.roamCmd.roamId ))) + { + smsLog(pMac, LOGE, " CSR start BSS failed"); + //We need to complete the command + csrRoamComplete(pMac, eCsrStartBssFailure, NULL); + } + } + else + { + if (!pCommand->u.roamCmd.pRoamBssEntry) + { + smsLog(pMac, LOGE, " pRoamBssEntry is NULL"); + //We need to complete the command + csrRoamComplete(pMac, eCsrJoinFailure, NULL); + return; + } + if ( NULL == pScanResult) + { + // If we are roaming TO an Infrastructure BSS... + VOS_ASSERT(pScanResult != NULL); + return; + } + if ( csrIsInfraBssDesc( pBssDesc ) ) + { + tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)pScanResult->Result.pvIes; + if(pIesLocal || (HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal))) ) + { + // ..and currently in an Infrastructure connection.... + if( csrIsConnStateConnectedInfra( pMac, sessionId ) ) + { + // ...and the SSIDs are equal, then we Reassoc. + if ( csrIsSsidEqual( pMac, pSession->pConnectBssDesc, pBssDesc, + pIesLocal ) ) + // ..and currently in an infrastructure connection + { + // then issue a Reassoc. + pCommand->u.roamCmd.fReassoc = eANI_BOOLEAN_TRUE; + csrRoamIssueReassociate( pMac, sessionId, pBssDesc, pIesLocal, + &pCommand->u.roamCmd.roamProfile ); + } + else + { + + // otherwise, we have to issue a new Join request to LIM because we disassociated from the + // previously associated AP. + if(!HAL_STATUS_SUCCESS(csrRoamIssueJoin( pMac, sessionId, pBssDesc, + pIesLocal, + &pCommand->u.roamCmd.roamProfile, pCommand->u.roamCmd.roamId ))) + { + //try something else + csrRoam( pMac, pCommand ); + } + } + } + else + { + eHalStatus status = eHAL_STATUS_SUCCESS; + + /* + * We need to come with other way to figure out that + * this is because of HO in BMP. The below API will be + * only available for Android as it uses a different + * HO algorithm. + * Reassoc request will be used only for ESE and 11r + * handoff whereas other legacy roaming should + * use join request */ +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csrRoamIsHandoffInProgress(pMac, sessionId) && + csrRoamIs11rAssoc(pMac, sessionId)) + { + status = csrRoamIssueReassociate(pMac, sessionId, pBssDesc, + (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ), &pCommand->u.roamCmd.roamProfile); + } + else +#endif +#ifdef FEATURE_WLAN_ESE + if (csrRoamIsHandoffInProgress(pMac, sessionId) && + csrRoamIsESEAssoc(pMac, sessionId)) + { + // Now serialize the reassoc command. + status = csrRoamIssueReassociateCmd(pMac, sessionId); + } + else +#endif +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsHandoffInProgress(pMac, sessionId) && + csrRoamIsFastRoamEnabled(pMac, sessionId)) + { + // Now serialize the reassoc command. + status = csrRoamIssueReassociateCmd(pMac, sessionId); + } + else +#endif + // else we are not connected and attempting to Join. Issue the + // Join request. + { + status = csrRoamIssueJoin( pMac, sessionId, pBssDesc, + (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ), + &pCommand->u.roamCmd.roamProfile, pCommand->u.roamCmd.roamId ); + } + if(!HAL_STATUS_SUCCESS(status)) + { + //try something else + csrRoam( pMac, pCommand ); + } + } + if( !pScanResult->Result.pvIes ) + { + //Locally allocated + vos_mem_free(pIesLocal); + } + } + }//if ( csrIsInfraBssDesc( pBssDesc ) ) + else + { + smsLog(pMac, LOGW, FL(" found BSSType mismatching the one in BSS description")); + } + }//else + }//if ( WNI_CFG_SUCCESS == result ) + else + { + // In the event the configuration failed, for infra let the roam processor + //attempt to join something else... + if( pCommand->u.roamCmd.pRoamBssEntry && CSR_IS_INFRASTRUCTURE( &pCommand->u.roamCmd.roamProfile ) ) + { + csrRoam(pMac, pCommand); + } + else + { + //We need to complete the command + if ( csrIsBssTypeIBSS( pCommand->u.roamCmd.roamProfile.BSSType ) ) + { + csrRoamComplete(pMac, eCsrStartBssFailure, NULL); + } + else + { + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + } + } + }//we have active entry +} + +static void csrRoamRoamingStateReassocRspProcessor( tpAniSirGlobal pMac, tpSirSmeJoinRsp pSmeJoinRsp ) +{ + eCsrRoamCompleteResult result; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pSmeJoinRsp->sessionId]; + tCsrRoamInfo roamInfo; + tANI_U32 roamId = 0; + + if ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("CSR SmeReassocReq Successful")); + result = eCsrReassocSuccess; + /* Defeaturize this part later if needed */ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + /* + * Since the neighbor roam algorithm uses reassoc req for + * handoff instead of join, we need the response contents while + * processing the result in csrRoamProcessResults() + */ + if (csrRoamIsHandoffInProgress(pMac, pSmeJoinRsp->sessionId)) + { + /* Need to dig more on indicating events to SME QoS module */ + sme_QosCsrEventInd(pMac, pSmeJoinRsp->sessionId, SME_QOS_CSR_HANDOFF_COMPLETE, NULL); + csrRoamComplete( pMac, result, pSmeJoinRsp); + } + else +#endif + { + csrRoamComplete( pMac, result, NULL ); + } + } + /* Should we handle this similar to handling the join failure? Is it ok + * to call csrRoamComplete() with state as CsrJoinFailure */ + else + { + smsLog( pMac, LOGW, "CSR SmeReassocReq failed with statusCode= 0x%08X [%d]", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode ); + result = eCsrReassocFailure; +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) + if ((eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE == pSmeJoinRsp->statusCode) || + (eSIR_SME_FT_REASSOC_FAILURE == pSmeJoinRsp->statusCode) || + (eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA == pSmeJoinRsp->statusCode) || + (eSIR_SME_INVALID_PARAMETERS == pSmeJoinRsp->statusCode)) { + /* Inform HDD to turn off FT flag in HDD */ + if (pNeighborRoamInfo) { + vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo)); + csrRoamCallCallback(pMac, pSmeJoinRsp->sessionId, &roamInfo, + roamId, eCSR_ROAM_FT_REASSOC_FAILED, + eSIR_SME_SUCCESS); + /* + * Since the above callback sends a disconnect + * to HDD, we should clean-up our state + * machine as well to be in sync with the upper + * layers. There is no need to send a disassoc + * since: 1) we will never reassoc to the current + * AP in LFR, and 2) there is no need to issue a + * disassoc to the AP with which we were trying + * to reassoc. + */ + csrRoamComplete(pMac, eCsrJoinFailure, NULL); + return; + } + } +#endif + // In the event that the Reassociation fails, then we need to Disassociate the current association and keep + // roaming. Note that we will attempt to Join the AP instead of a Reassoc since we may have attempted a + // 'Reassoc to self', which AP's that don't support Reassoc will force a Disassoc. + //The disassoc rsp message will remove the command from active list + if(!HAL_STATUS_SUCCESS(csrRoamIssueDisassociate( pMac, pSmeJoinRsp->sessionId, + eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, FALSE ))) + { + csrRoamComplete( pMac, eCsrJoinFailure, NULL ); + } + } +} + +static void csrRoamRoamingStateStopBssRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSmeRsp) +{ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + pIbssLog->eventId = WLAN_IBSS_EVENT_STOP_RSP; + if(eSIR_SME_SUCCESS != pSmeRsp->statusCode) + { + pIbssLog->status = WLAN_IBSS_STATUS_FAILURE; + } + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + pMac->roam.roamSession[pSmeRsp->sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + if(CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ( pMac, pSmeRsp->sessionId)) + { + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + else if(CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE( pMac, pSmeRsp->sessionId)) + { + csrRoamReissueRoamCommand(pMac); + } +} + +void csrRoamRoamingStateDisassocRspProcessor( tpAniSirGlobal pMac, tSirSmeDisassocRsp *pSmeRsp ) +{ + tSirResultCodes statusCode; +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + tScanResultHandle hBSSList; + tANI_BOOLEAN fCallCallback, fRemoveCmd; + eHalStatus status; + tCsrRoamInfo roamInfo; + tCsrScanResultFilter *pScanFilter = NULL; + tANI_U32 roamId = 0; + tCsrRoamProfile *pCurRoamProfile = NULL; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; +#endif + tANI_U32 sessionId; + tCsrRoamSession *pSession; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + tSirSmeDisassocRsp SmeDisassocRsp; + + csrSerDesUnpackDiassocRsp((tANI_U8 *)pSmeRsp, &SmeDisassocRsp); + sessionId = SmeDisassocRsp.sessionId; + statusCode = SmeDisassocRsp.statusCode; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("csrRoamRoamingStateDisassocRspProcessor sessionId %d"), sessionId); + + if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN( pMac, sessionId ) ) + { + smsLog( pMac, LOG2, "***eCsrNothingToJoin***"); + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + else if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_FORCED( pMac, sessionId ) || + CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ( pMac, sessionId ) ) + { + if ( eSIR_SME_SUCCESS == statusCode ) + { + smsLog( pMac, LOG2, "CSR SmeDisassocReq force disassociated Successfully" ); + //A callback to HDD will be issued from csrRoamComplete so no need to do anything here + } + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + else if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac, sessionId ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "CSR SmeDisassocReq due to HO on session %d", sessionId ); + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; +#if defined (WLAN_FEATURE_NEIGHBOR_ROAMING) + /* + * First ensure if the roam profile is in the scan cache. + * If not, post a reassoc failure and disconnect. + */ + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + pScanFilter->scan_filter_for_roam = 1; + status = csrRoamPrepareFilterFromProfile(pMac, + &pNeighborRoamInfo->csrNeighborRoamProfile, + pScanFilter); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, "%s: failed to prepare scan filter with status %d", + __func__, status); + goto POST_ROAM_FAILURE; + } + else + { + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE,"%s: csrScanGetResult failed with status %d", + __func__, status); + goto POST_ROAM_FAILURE; + } + } + } + else + { + smsLog( pMac, LOGE,"%s: alloc for pScanFilter failed with status %d", + __func__, status); + goto POST_ROAM_FAILURE; + } + + /* + * After ensuring that the roam profile is in the scan result list, + * dequeue the command from the active list. + */ + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + /* If the head of the queue is Active and it is a ROAM command, remove + * and put this on the Free queue. + */ + if ( eSmeCommandRoam == pCommand->command ) + { + + /* + * we need to process the result first before removing it from active list + * because state changes still happening insides roamQProcessRoamResults so + * no other roam command should be issued. + */ + fRemoveCmd = csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ); + if(pCommand->u.roamCmd.fReleaseProfile) + { + csrReleaseProfile(pMac, &pCommand->u.roamCmd.roamProfile); + pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE; + } + if( fRemoveCmd ) + csrReleaseCommandRoam( pMac, pCommand ); + else + { + smsLog( pMac, LOGE, "%s: fail to remove cmd reason %d", + __func__, pCommand->u.roamCmd.roamReason ); + } + } + else + { + smsLog( pMac, LOGE, "%s: roam command not active", __func__ ); + } + } + else + { + smsLog( pMac, LOGE, "%s: NO commands are active", __func__ ); + } + + /* Notify HDD about handoff and provide the BSSID too */ + roamInfo.reasonCode = eCsrRoamReasonBetterAP; + + vos_mem_copy(roamInfo.bssid, + pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid, + sizeof(tSirMacAddr)); + + csrRoamCallCallback(pMac,sessionId, &roamInfo, 0, + eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE); + + /* Copy the connected profile to apply the same for this connection as well */ + pCurRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( pCurRoamProfile != NULL ) + { + vos_mem_set(pCurRoamProfile, sizeof(tCsrRoamProfile), 0); + csrRoamCopyProfile(pMac, pCurRoamProfile, pSession->pCurRoamProfile); + //make sure to put it at the head of the cmd queue + status = csrRoamIssueConnect(pMac, sessionId, pCurRoamProfile, + hBSSList, eCsrSmeIssuedAssocToSimilarAP, + roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE); + + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE,"%s: csrRoamIssueConnect failed with status %d", + __func__, status); + fCallCallback = eANI_BOOLEAN_TRUE; + } + + /* Notify sub-modules like QoS etc. that handoff happening */ + sme_QosCsrEventInd(pMac, sessionId, SME_QOS_CSR_HANDOFF_ASSOC_REQ, NULL); + csrReleaseProfile(pMac, pCurRoamProfile); + vos_mem_free(pCurRoamProfile); + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + return; + } + +POST_ROAM_FAILURE: + if (pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + if (pCurRoamProfile) + vos_mem_free(pCurRoamProfile); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + csrRoamSynchCleanUp(pMac, sessionId); +#endif + /* Inform the upper layers that the reassoc failed */ + vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo)); + csrRoamCallCallback(pMac, sessionId, + &roamInfo, 0, eCSR_ROAM_FT_REASSOC_FAILED, eSIR_SME_SUCCESS); + + /* + * Issue a disassoc request so that PE/LIM uses this to clean-up the FT session. + * Upon success, we would re-enter this routine after receiving the disassoc + * response and will fall into the reassoc fail sub-state. And, eventually + * call csrRoamComplete which would remove the roam command from SME active + * queue. + */ + if (!HAL_STATUS_SUCCESS(csrRoamIssueDisassociate(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, FALSE))) + { + smsLog( pMac, LOGE,"%s: csrRoamIssueDisassociate failed with status %d", + __func__, status); + csrRoamComplete( pMac, eCsrJoinFailure, NULL ); + } +#endif + + } //else if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac ) ) + else if ( CSR_IS_ROAM_SUBSTATE_REASSOC_FAIL( pMac, sessionId ) ) + { + // Disassoc due to Reassoc failure falls into this codepath.... + csrRoamComplete( pMac, eCsrJoinFailure, NULL ); + } + else + { + if ( eSIR_SME_SUCCESS == statusCode ) + { + // Successfully disassociated from the 'old' Bss... + // + /* + * We get Disassociate response in three conditions. + * - First is the case where we are disassociating from an + * Infra Bss to start an IBSS. + * - Second is the when we are disassociating from an Infra Bss + * to join an IBSS or a new Infrastructure network. + * - Third is where we are doing an Infra to Infra roam between + * networks with different SSIDs. In all cases, we set the new + * Bss configuration here and attempt to join + */ + + smsLog( pMac, LOG2, "CSR SmeDisassocReq disassociated Successfully" ); + } + else + { + smsLog( pMac, LOGE, "SmeDisassocReq failed with statusCode= 0x%08X", statusCode ); + } + //We are not done yet. Get the data and continue roaming + csrRoamReissueRoamCommand(pMac); + } +} + +static void csrRoamRoamingStateDeauthRspProcessor( tpAniSirGlobal pMac, tSirSmeDeauthRsp *pSmeRsp ) +{ + tSirResultCodes statusCode; + //No one is sending eWNI_SME_DEAUTH_REQ to PE. + smsLog(pMac, LOGW, FL("is no-op")); + statusCode = csrGetDeAuthRspStatusCode( pSmeRsp ); + pMac->roam.deauthRspStatus = statusCode; + if ( CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ( pMac, pSmeRsp->sessionId) ) + { + csrRoamComplete( pMac, eCsrNothingToJoin, NULL ); + } + else + { + if ( eSIR_SME_SUCCESS == statusCode ) + { + // Successfully deauth from the 'old' Bss... + // + smsLog( pMac, LOG2, "CSR SmeDeauthReq disassociated Successfully" ); + } + else + { + smsLog( pMac, LOGW, "SmeDeauthReq failed with statusCode= 0x%08X", statusCode ); + } + //We are not done yet. Get the data and continue roaming + csrRoamReissueRoamCommand(pMac); + } +} + +static void csrRoamRoamingStateStartBssRspProcessor( tpAniSirGlobal pMac, tSirSmeStartBssRsp *pSmeStartBssRsp ) +{ + eCsrRoamCompleteResult result; + + if ( eSIR_SME_SUCCESS == pSmeStartBssRsp->statusCode ) + { + smsLog( pMac, LOGW, "SmeStartBssReq Successful" ); + result = eCsrStartBssSuccess; + } + else + { + smsLog( pMac, LOGW, "SmeStartBssReq failed with statusCode= 0x%08X", pSmeStartBssRsp->statusCode ); + //Let csrRoamComplete decide what to do + result = eCsrStartBssFailure; + } + csrRoamComplete( pMac, result, pSmeStartBssRsp); +} + +/* + * We need to be careful on whether to cast pMsgBuf (pSmeRsp) to other type of + * structures. It depends on how the message is constructed. If the message is + * sent by limSendSmeRsp, the pMsgBuf is only a generic response and can only be + * used as pointer to tSirSmeRsp. For the messages where sender allocates memory + * for specific structures, then it can be cast accordingly. + */ +void csrRoamingStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) +{ + tSirSmeRsp *pSmeRsp; + tSmeIbssPeerInd *pIbssPeerInd; + tCsrRoamInfo roamInfo; + // TODO Session Id need to be acquired in this function + tANI_U32 sessionId = 0; + pSmeRsp = (tSirSmeRsp *)pMsgBuf; + smsLog(pMac, LOG2, FL("Message %d[0x%04X] received in substate %s"), + pSmeRsp->messageType, pSmeRsp->messageType, + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pSmeRsp->sessionId])); + pSmeRsp->messageType = (pSmeRsp->messageType); + pSmeRsp->length = (pSmeRsp->length); + pSmeRsp->statusCode = (pSmeRsp->statusCode); + switch (pSmeRsp->messageType) + { + + case eWNI_SME_JOIN_RSP: // in Roaming state, process the Join response message... + if (CSR_IS_ROAM_SUBSTATE_JOIN_REQ(pMac, pSmeRsp->sessionId)) + { + //We sent a JOIN_REQ + csrRoamJoinRspProcessor( pMac, (tSirSmeJoinRsp *)pSmeRsp ); + } + break; + + case eWNI_SME_REASSOC_RSP: // or the Reassociation response message... + if (CSR_IS_ROAM_SUBSTATE_REASSOC_REQ( pMac, pSmeRsp->sessionId) ) + { + csrRoamRoamingStateReassocRspProcessor( pMac, (tpSirSmeJoinRsp )pSmeRsp ); + } + break; + + case eWNI_SME_STOP_BSS_RSP: // or the Stop Bss response message... + { + csrRoamRoamingStateStopBssRspProcessor(pMac, pSmeRsp); + } + break; + + case eWNI_SME_DISASSOC_RSP: // or the Disassociate response message... + if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ( pMac, pSmeRsp->sessionId ) || + CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN( pMac, pSmeRsp->sessionId ) || + CSR_IS_ROAM_SUBSTATE_REASSOC_FAIL( pMac, pSmeRsp->sessionId ) || + CSR_IS_ROAM_SUBSTATE_DISASSOC_FORCED( pMac, pSmeRsp->sessionId ) || + CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE( pMac, pSmeRsp->sessionId ) || +//HO + CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac, pSmeRsp->sessionId ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("eWNI_SME_DISASSOC_RSP subState = %s"), + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pSmeRsp->sessionId])); + csrRoamRoamingStateDisassocRspProcessor( pMac, (tSirSmeDisassocRsp *)pSmeRsp ); + } + break; + + case eWNI_SME_DEAUTH_RSP: // or the Deauthentication response message... + if ( CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ( pMac, pSmeRsp->sessionId ) ) + { + csrRoamRoamingStateDeauthRspProcessor( pMac, (tSirSmeDeauthRsp *)pSmeRsp ); + } + break; + + case eWNI_SME_START_BSS_RSP: // or the Start BSS response message... + if (CSR_IS_ROAM_SUBSTATE_START_BSS_REQ( pMac, pSmeRsp->sessionId ) ) + { + csrRoamRoamingStateStartBssRspProcessor( pMac, (tSirSmeStartBssRsp *)pSmeRsp ); + } + break; + + case WNI_CFG_SET_CNF: // process the Config Confirm messages when we are in 'Config' substate... + if ( CSR_IS_ROAM_SUBSTATE_CONFIG( pMac, pSmeRsp->sessionId ) ) + { + csrRoamingStateConfigCnfProcessor( pMac, ((tCsrCfgSetRsp *)pSmeRsp)->respStatus ); + } + break; + /* In case CSR issues STOP_BSS, we need to tell HDD about peer departed + because PE is removing them */ + case eWNI_SME_IBSS_PEER_DEPARTED_IND: + pIbssPeerInd = (tSmeIbssPeerInd*)pSmeRsp; + smsLog(pMac, LOGE, "CSR: Peer departed notification from LIM in joining state"); + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.staId = (tANI_U8)pIbssPeerInd->staId; + roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig; + roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig; + vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, + sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_CONNECT_STATUS_UPDATE, + eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED); + break; + case eWNI_SME_GET_RSSI_REQ: + { + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)pMsgBuf; + if (NULL != pGetRssiReq->rssiCallback) + { + ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))( pGetRssiReq->lastRSSI, + pGetRssiReq->staId, + pGetRssiReq->pDevContext); + } + else + { + smsLog(pMac, LOGE, FL("pGetRssiReq->rssiCallback is NULL")); + } + } + break; + + default: + smsLog(pMac, LOG1, + FL("Unexpected message type = %d[0x%X] received in substate %s"), + pSmeRsp->messageType, pSmeRsp->messageType, + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pSmeRsp->sessionId])); + //If we are connected, check the link status change + if(!csrIsConnStateDisconnected(pMac, sessionId)) + { + csrRoamCheckForLinkStatusChange( pMac, pSmeRsp ); + } + break; + } +} + +void csrRoamJoinedStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) +{ + tSirSmeRsp *pSirMsg = (tSirSmeRsp *)pMsgBuf; + switch (pSirMsg->messageType) + { + case eWNI_SME_GET_STATISTICS_RSP: + smsLog( pMac, LOG2, FL("Stats rsp from PE")); + csrRoamStatsRspProcessor( pMac, pSirMsg ); + break; + case eWNI_SME_UPPER_LAYER_ASSOC_CNF: + { + tCsrRoamSession *pSession; + tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf; + tCsrRoamInfo roamInfo; + tCsrRoamInfo *pRoamInfo = NULL; + tANI_U32 sessionId; + eHalStatus status; + smsLog( pMac, LOG1, FL("ASSOCIATION confirmation can be given to upper layer ")); + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + pRoamInfo = &roamInfo; + pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *)pMsgBuf; + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pUpperLayerAssocCnf->bssId, &sessionId ); + pSession = CSR_GET_SESSION(pMac, sessionId); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + pRoamInfo->statusCode = eSIR_SME_SUCCESS; //send the status code as Success + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + pRoamInfo->staId = (tANI_U8)pUpperLayerAssocCnf->aid; + pRoamInfo->rsnIELen = (tANI_U8)pUpperLayerAssocCnf->rsnIE.length; + pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata; +#ifdef FEATURE_WLAN_WAPI + pRoamInfo->wapiIELen = (tANI_U8)pUpperLayerAssocCnf->wapiIE.length; + pRoamInfo->pwapiIE = pUpperLayerAssocCnf->wapiIE.wapiIEdata; +#endif + pRoamInfo->addIELen = (tANI_U8)pUpperLayerAssocCnf->addIE.length; + pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata; + vos_mem_copy(pRoamInfo->peerMac, pUpperLayerAssocCnf->peerMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(&pRoamInfo->bssid, pUpperLayerAssocCnf->bssId, + sizeof(tCsrBssid)); + pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta; + pRoamInfo->timingMeasCap = pUpperLayerAssocCnf->timingMeasCap; + vos_mem_copy(&pRoamInfo->chan_info, &pUpperLayerAssocCnf->chan_info, + sizeof(tSirSmeChanInfo)); + if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile) ) + { + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED; + pRoamInfo->fReassocReq = pUpperLayerAssocCnf->reassocReq; + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); + } + if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile)) + { + vos_sleep( 100 ); + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED;//Sta + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);//Sta + } + + } + break; + default: + csrRoamCheckForLinkStatusChange( pMac, pSirMsg ); + break; + } +} + +eHalStatus csrRoamIssueSetContextReq( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrEncryptionType EncryptType, + tSirBssDescription *pBssDescription, + tSirMacAddr *bssId, tANI_BOOLEAN addKey, + tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection, + tANI_U8 keyId, tANI_U16 keyLength, + tANI_U8 *pKey, tANI_U8 paeRole ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tAniEdType edType; + + if(eCSR_ENCRYPT_TYPE_UNKNOWN == EncryptType) + { + EncryptType = eCSR_ENCRYPT_TYPE_NONE; //*** + } + + edType = csrTranslateEncryptTypeToEdType( EncryptType ); + + /* + * Allow 0 keys to be set for the non-WPA encrypt types. + * For WPA encrypt types, the num keys must be non-zero + * or LIM will reject the set context (assumes the SET_CONTEXT does not + * occur until the keys are distributed). + */ + if ( CSR_IS_ENC_TYPE_STATIC( EncryptType ) || + addKey ) + { + tCsrRoamSetKey setKey; + setKey.encType = EncryptType; + setKey.keyDirection = aniKeyDirection; //Tx, Rx or Tx-and-Rx + vos_mem_copy(&setKey.peerMac, bssId, sizeof(tCsrBssid)); + setKey.paeRole = paeRole; //0 for supplicant + setKey.keyId = keyId; /* Key index */ + setKey.keyLength = keyLength; + if( keyLength ) + { + vos_mem_copy(setKey.Key, pKey, keyLength); + } + status = csrRoamIssueSetKeyCommand( pMac, sessionId, &setKey, 0 ); + } + return (status); +} + +static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamSetKey *pSetKey, tANI_U32 roamId ) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tSmeCmd *pCommand = NULL; +#if defined(FEATURE_WLAN_ESE) || defined (FEATURE_WLAN_WAPI) + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL == pSession) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } +#endif /* FEATURE_WLAN_ESE */ + + do + { + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_zero(pCommand, sizeof(tSmeCmd)); + pCommand->command = eSmeCommandSetKey; + pCommand->sessionId = (tANI_U8)sessionId; + // validate the key length, Adjust if too long... + // for static WEP the keys are not set thru' SetContextReq + if ( ( eCSR_ENCRYPT_TYPE_WEP40 == pSetKey->encType ) || + ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pSetKey->encType ) ) + { + //KeyLength maybe 0 for static WEP + if( pSetKey->keyLength ) + { + if ( pSetKey->keyLength < CSR_WEP40_KEY_LEN ) + { + smsLog( pMac, LOGW, "Invalid WEP40 keylength [= %d] in SetContext call", pSetKey->keyLength ); + break; + } + + pCommand->u.setKeyCmd.keyLength = CSR_WEP40_KEY_LEN; + vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, + CSR_WEP40_KEY_LEN); + } + } + else if ( ( eCSR_ENCRYPT_TYPE_WEP104 == pSetKey->encType ) || + ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pSetKey->encType ) ) + { + //KeyLength maybe 0 for static WEP + if( pSetKey->keyLength ) + { + if ( pSetKey->keyLength < CSR_WEP104_KEY_LEN ) + { + smsLog( pMac, LOGW, "Invalid WEP104 keylength [= %d] in SetContext call", pSetKey->keyLength ); + break; + } + + pCommand->u.setKeyCmd.keyLength = CSR_WEP104_KEY_LEN; + vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, + CSR_WEP104_KEY_LEN); + } + } + else if ( eCSR_ENCRYPT_TYPE_TKIP == pSetKey->encType ) + { + if ( pSetKey->keyLength < CSR_TKIP_KEY_LEN ) + { + smsLog( pMac, LOGW, "Invalid TKIP keylength [= %d] in SetContext call", pSetKey->keyLength ); + break; + } + pCommand->u.setKeyCmd.keyLength = CSR_TKIP_KEY_LEN; + vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, + CSR_TKIP_KEY_LEN); + } + else if ( eCSR_ENCRYPT_TYPE_AES == pSetKey->encType ) + { + if ( pSetKey->keyLength < CSR_AES_KEY_LEN ) + { + smsLog( pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength ); + break; + } + pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN; + vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, + CSR_AES_KEY_LEN); + } +#ifdef FEATURE_WLAN_WAPI + else if ( eCSR_ENCRYPT_TYPE_WPI == pSetKey->encType ) + { + if ( pSetKey->keyLength < CSR_WAPI_KEY_LEN ) + { + smsLog( pMac, LOGW, + "Invalid WAPI keylength [= %d] in SetContext call", + pSetKey->keyLength ); + break; + } + pCommand->u.setKeyCmd.keyLength = CSR_WAPI_KEY_LEN; + vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, + CSR_WAPI_KEY_LEN); + if (pSession->pCurRoamProfile) + pSession->pCurRoamProfile->negotiatedUCEncryptionType = + eCSR_ENCRYPT_TYPE_WPI; + } +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_ESE + else if ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType ) + { + if ( pSetKey->keyLength < CSR_KRK_KEY_LEN ) + { + smsLog( pMac, LOGW, + "Invalid KRK keylength [= %d] in SetContext call", + pSetKey->keyLength ); + break; + } + vos_mem_copy(pSession->eseCckmInfo.krk, pSetKey->Key, + CSR_KRK_KEY_LEN); + pSession->eseCckmInfo.reassoc_req_num=1; + pSession->eseCckmInfo.krk_plumbed = eANI_BOOLEAN_TRUE; + status = eHAL_STATUS_SUCCESS; + break; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + else if (eCSR_ENCRYPT_TYPE_BTK == pSetKey->encType) { + if (pSetKey->keyLength < SIR_BTK_KEY_LEN) { + smsLog(pMac, LOGW, + "LFR3:Invalid BTK keylength [= %d] in SetContext call", + pSetKey->keyLength); + break; + } + vos_mem_copy(pSession->eseCckmInfo.btk, pSetKey->Key, + SIR_BTK_KEY_LEN); + status = eHAL_STATUS_SUCCESS; + break; + } +#endif +#endif /* FEATURE_WLAN_ESE */ + +#ifdef WLAN_FEATURE_11W + //Check for 11w BIP + else if (eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType) + { + if (pSetKey->keyLength < CSR_AES_KEY_LEN) + { + smsLog(pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength); + break; + } + pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN; + vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_AES_KEY_LEN); + } +#endif + status = eHAL_STATUS_SUCCESS; + pCommand->u.setKeyCmd.roamId = roamId; + pCommand->u.setKeyCmd.encType = pSetKey->encType; + pCommand->u.setKeyCmd.keyDirection = pSetKey->keyDirection; //Tx, Rx or Tx-and-Rx + vos_mem_copy(&pCommand->u.setKeyCmd.peerMac, &pSetKey->peerMac, + sizeof(tCsrBssid)); + pCommand->u.setKeyCmd.paeRole = pSetKey->paeRole; //0 for supplicant + pCommand->u.setKeyCmd.keyId = pSetKey->keyId; + vos_mem_copy(pCommand->u.setKeyCmd.keyRsc, pSetKey->keyRsc, CSR_MAX_RSC_LEN); + //Always put set key to the head of the Q because it is the only thing to get executed in case of WT_KEY state + + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + } + } while (0); + // Free the command if there has been a failure, or it is a + // "local" operation like the set ESE CCKM KRK key. + if ( ( NULL != pCommand ) && + ( (!HAL_STATUS_SUCCESS( status ) ) +#ifdef FEATURE_WLAN_ESE + || ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType ) +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + || ( eCSR_ENCRYPT_TYPE_BTK == pSetKey->encType ) +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ +#endif /* FEATURE_WLAN_ESE */ + ) ) + { + csrReleaseCommandSetKey( pMac, pCommand ); + } + return( status ); +} + +eHalStatus csrRoamIssueRemoveKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamRemoveKey *pRemoveKey, tANI_U32 roamId ) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tSmeCmd *pCommand = NULL; + tANI_BOOLEAN fImediate = eANI_BOOLEAN_TRUE; + do + { + if( !csrIsSetKeyAllowed(pMac, sessionId) ) + { + smsLog( pMac, LOGW, FL(" wrong state not allowed to set key") ); + status = eHAL_STATUS_CSR_WRONG_STATE; + break; + } + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + break; + } + pCommand->command = eSmeCommandRemoveKey; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.removeKeyCmd.roamId = roamId; + pCommand->u.removeKeyCmd.encType = pRemoveKey->encType; + vos_mem_copy(&pCommand->u.removeKeyCmd.peerMac, &pRemoveKey->peerMac, + sizeof(tSirMacAddr)); + pCommand->u.removeKeyCmd.keyId = pRemoveKey->keyId; + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ) + { + /* In this case, put it to the end of the Q in-case there + is a set key pending. */ + fImediate = eANI_BOOLEAN_FALSE; + } + smsLog( pMac, LOGE, FL("keyType=%d, keyId=%d, PeerMac="MAC_ADDRESS_STR), + pRemoveKey->encType, pRemoveKey->keyId, + MAC_ADDR_ARRAY(pCommand->u.removeKeyCmd.peerMac)); + status = csrQueueSmeCommand(pMac, pCommand, fImediate); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + } while (0); + if( !HAL_STATUS_SUCCESS( status ) && ( NULL != pCommand ) ) + { + csrReleaseCommandRemoveKey( pMac, pCommand ); + } + return (status ); +} + +eHalStatus csrRoamProcessSetKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status; + tANI_U8 numKeys = ( pCommand->u.setKeyCmd.keyLength ) ? 1 : 0; + tAniEdType edType = csrTranslateEncryptTypeToEdType( pCommand->u.setKeyCmd.encType ); + tANI_BOOLEAN fUnicast = ( pCommand->u.setKeyCmd.peerMac[0] == 0xFF ) ? eANI_BOOLEAN_FALSE : eANI_BOOLEAN_TRUE; + tANI_U32 sessionId = pCommand->sessionId; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + WLAN_VOS_DIAG_EVENT_DEF(setKeyEvent, vos_event_wlan_security_payload_type); + + if(NULL == pSession){ + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(eSIR_ED_NONE != edType) + { + vos_mem_set(&setKeyEvent, + sizeof(vos_event_wlan_security_payload_type), 0); + if( *(( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac) & 0x01 ) + { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_REQ; + setKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pCommand->u.setKeyCmd.encType); + setKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + } + else + { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_REQ; + setKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pCommand->u.setKeyCmd.encType); + setKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + } + vos_mem_copy(setKeyEvent.bssid, pSession->connectedProfile.bssid, 6); + if(CSR_IS_ENC_TYPE_STATIC(pCommand->u.setKeyCmd.encType)) + { + tANI_U32 defKeyId; + //It has to be static WEP here + if(HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, &defKeyId))) + { + setKeyEvent.keyId = (v_U8_t)defKeyId; + } + } + else + { + setKeyEvent.keyId = pCommand->u.setKeyCmd.keyId; + } + setKeyEvent.authMode = (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + WLAN_VOS_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY); + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + if( csrIsSetKeyAllowed(pMac, sessionId) ) + { + status = csrSendMBSetContextReqMsg( pMac, sessionId, + ( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac, + numKeys, edType, fUnicast, pCommand->u.setKeyCmd.keyDirection, + pCommand->u.setKeyCmd.keyId, pCommand->u.setKeyCmd.keyLength, + pCommand->u.setKeyCmd.Key, pCommand->u.setKeyCmd.paeRole, + pCommand->u.setKeyCmd.keyRsc); + } + else + { + smsLog( pMac, LOGW, FL(" cannot process not connected") ); + //Set this status so the error handling take care of the case. + status = eHAL_STATUS_CSR_WRONG_STATE; + } + if( !HAL_STATUS_SUCCESS(status) ) + { + smsLog( pMac, LOGE, FL(" error status %d"), status ); + csrRoamCallCallback( pMac, sessionId, NULL, pCommand->u.setKeyCmd.roamId, eCSR_ROAM_SET_KEY_COMPLETE, eCSR_ROAM_RESULT_FAILURE); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + if(eSIR_ED_NONE != edType) + { + if( *(( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac) & 0x01 ) + { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_RSP; + } + else + { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_RSP; + } + setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE; + WLAN_VOS_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY); + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + } + return ( status ); +} + +eHalStatus csrRoamProcessRemoveKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status; + tpSirSmeRemoveKeyReq pMsg = NULL; + tANI_U16 wMsgLen = sizeof(tSirSmeRemoveKeyReq); + tANI_U8 *p; + tANI_U32 sessionId = pCommand->sessionId; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + WLAN_VOS_DIAG_EVENT_DEF(removeKeyEvent, vos_event_wlan_security_payload_type); + + if(NULL == pSession){ + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + vos_mem_set(&removeKeyEvent, + sizeof(vos_event_wlan_security_payload_type),0); + removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_REQ; + removeKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + removeKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + vos_mem_copy(removeKeyEvent.bssid, pSession->connectedProfile.bssid, 6); + removeKeyEvent.keyId = pCommand->u.removeKeyCmd.keyId; + removeKeyEvent.authMode = (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + WLAN_VOS_DIAG_EVENT_REPORT(&removeKeyEvent, EVENT_WLAN_SECURITY); +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + if( csrIsSetKeyAllowed(pMac, sessionId) ) + { + pMsg = vos_mem_malloc(wMsgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + } + else + { + smsLog( pMac, LOGW, FL(" wrong state not allowed to set key") ); + //Set the error status so error handling kicks in below + status = eHAL_STATUS_CSR_WRONG_STATE; + } + if( HAL_STATUS_SUCCESS( status ) ) + { + vos_mem_set(pMsg, wMsgLen ,0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_REMOVEKEY_REQ); + pMsg->length = pal_cpu_to_be16(wMsgLen); + pMsg->sessionId = (tANI_U8)sessionId; + pMsg->transactionId = 0; + p = (tANI_U8 *)pMsg + sizeof(pMsg->messageType) + sizeof(pMsg->length) + + sizeof(pMsg->sessionId) + sizeof(pMsg->transactionId); + // bssId - copy from session Info + vos_mem_copy(p, + &pMac->roam.roamSession[sessionId].connectedProfile.bssid, + sizeof(tSirMacAddr)); + p += sizeof(tSirMacAddr); + // peerMacAddr + vos_mem_copy(p, pCommand->u.removeKeyCmd.peerMac, sizeof(tSirMacAddr)); + p += sizeof(tSirMacAddr); + // edType + *p = (tANI_U8)csrTranslateEncryptTypeToEdType( pCommand->u.removeKeyCmd.encType ); + p++; + // weptype + if( ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pCommand->u.removeKeyCmd.encType ) || + ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pCommand->u.removeKeyCmd.encType ) ) + { + *p = (tANI_U8)eSIR_WEP_STATIC; + } + else + { + *p = (tANI_U8)eSIR_WEP_DYNAMIC; + } + p++; + //keyid + *p = pCommand->u.removeKeyCmd.keyId; + p++; + *p = (pCommand->u.removeKeyCmd.peerMac[0] == 0xFF ) ? 0 : 1; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" error status %d"), status ); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_RSP; + removeKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE; + WLAN_VOS_DIAG_EVENT_REPORT(&removeKeyEvent, EVENT_WLAN_SECURITY); +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + csrRoamCallCallback( pMac, sessionId, NULL, pCommand->u.removeKeyCmd.roamId, eCSR_ROAM_REMOVE_KEY_COMPLETE, eCSR_ROAM_RESULT_FAILURE); + } + return ( status ); +} + +eHalStatus csrRoamSetKey( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 roamId ) +{ + eHalStatus status; + + if( !csrIsSetKeyAllowed(pMac, sessionId) ) + { + status = eHAL_STATUS_CSR_WRONG_STATE; + } + else + { + status = csrRoamIssueSetKeyCommand( pMac, sessionId, pSetKey, roamId ); + } + return ( status ); +} + +/* + Prepare a filter base on a profile for parsing the scan results. + Upon successful return, caller MUST call csrFreeScanFilter on + pScanFilter when it is done with the filter. +*/ +eHalStatus csrRoamPrepareFilterFromProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + tCsrScanResultFilter *pScanFilter) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + uint32_t size = 0; + tANI_U8 index = 0; + struct roam_ext_params *roam_params; + uint8_t i; + + roam_params = &pMac->roam.configParam.roam_params; + + do + { + if(pProfile->BSSIDs.numOfBSSIDs) + { + size = sizeof(tCsrBssid) * pProfile->BSSIDs.numOfBSSIDs; + pScanFilter->BSSIDs.bssid = vos_mem_malloc(size); + if ( NULL == pScanFilter->BSSIDs.bssid ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pScanFilter->BSSIDs.numOfBSSIDs = pProfile->BSSIDs.numOfBSSIDs; + vos_mem_copy(pScanFilter->BSSIDs.bssid, pProfile->BSSIDs.bssid, size); + } + if(pProfile->SSIDs.numOfSSIDs) + { + if( !CSR_IS_WDS_STA( pProfile ) ) + { + pScanFilter->SSIDs.numOfSSIDs = pProfile->SSIDs.numOfSSIDs; + } + else + { + //For WDS station + //We always use index 1 for self SSID. Index 0 for peer's SSID that we want to join + pScanFilter->SSIDs.numOfSSIDs = 1; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("No of Allowed List:%d"), roam_params->num_ssid_allowed_list); + if (pScanFilter->scan_filter_for_roam + && roam_params->num_ssid_allowed_list) { + pScanFilter->SSIDs.numOfSSIDs = + roam_params->num_ssid_allowed_list; + size = sizeof(tCsrSSIDInfo) * pScanFilter->SSIDs.numOfSSIDs; + pScanFilter->SSIDs.SSIDList = vos_mem_malloc(size); + if ( NULL == pScanFilter->SSIDs.SSIDList) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + break; + for (i=0; inum_ssid_allowed_list; i++) { + vos_mem_copy((void *)pScanFilter->SSIDs.SSIDList[i].SSID.ssId, + roam_params->ssid_allowed_list[i].ssId, + roam_params->ssid_allowed_list[i].length); + pScanFilter->SSIDs.SSIDList[i].SSID.length = + roam_params->ssid_allowed_list[i].length; + pScanFilter->SSIDs.SSIDList[i].handoffPermitted = 1; + pScanFilter->SSIDs.SSIDList[i].ssidHidden = 0; + } + } else { + size = sizeof(tCsrSSIDInfo) * pProfile->SSIDs.numOfSSIDs; + pScanFilter->SSIDs.SSIDList = vos_mem_malloc(size); + if ( NULL == pScanFilter->SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + vos_mem_copy(pScanFilter->SSIDs.SSIDList, pProfile->SSIDs.SSIDList, + size); + } + } + if(!pProfile->ChannelInfo.ChannelList || (pProfile->ChannelInfo.ChannelList[0] == 0) ) + { + pScanFilter->ChannelInfo.numOfChannels = 0; + pScanFilter->ChannelInfo.ChannelList = NULL; + } + else if(pProfile->ChannelInfo.numOfChannels) + { + pScanFilter->ChannelInfo.ChannelList = vos_mem_malloc( + sizeof(*pScanFilter->ChannelInfo.ChannelList) * + pProfile->ChannelInfo.numOfChannels); + if ( NULL == pScanFilter->ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + pScanFilter->ChannelInfo.numOfChannels = 0; + if(HAL_STATUS_SUCCESS(status)) + { + for(index = 0; index < pProfile->ChannelInfo.numOfChannels; index++) + { + if(csrRoamIsChannelValid(pMac, pProfile->ChannelInfo.ChannelList[index])) + { + pScanFilter->ChannelInfo.ChannelList[pScanFilter->ChannelInfo.numOfChannels] + = pProfile->ChannelInfo.ChannelList[index]; + pScanFilter->ChannelInfo.numOfChannels++; + } + else + { + smsLog(pMac, LOG1, FL("process a channel (%d) that is invalid"), pProfile->ChannelInfo.ChannelList[index]); + } + } + } + else + { + break; + } + } + else + { + smsLog(pMac, LOGE, FL("Channel list empty")); + status = eHAL_STATUS_FAILURE; + break; + } + pScanFilter->uapsd_mask = pProfile->uapsd_mask; + pScanFilter->authType = pProfile->AuthType; + pScanFilter->EncryptionType = pProfile->EncryptionType; + pScanFilter->mcEncryptionType = pProfile->mcEncryptionType; + pScanFilter->BSSType = pProfile->BSSType; + pScanFilter->phyMode = pProfile->phyMode; +#ifdef FEATURE_WLAN_WAPI + //check if user asked for WAPI with 11n or auto mode, in that case modify + //the phymode to 11g + if(csrIsProfileWapi(pProfile)) + { + if(pScanFilter->phyMode & eCSR_DOT11_MODE_11n) + { + pScanFilter->phyMode &= ~eCSR_DOT11_MODE_11n; + } + if(pScanFilter->phyMode & eCSR_DOT11_MODE_AUTO) + { + pScanFilter->phyMode &= ~eCSR_DOT11_MODE_AUTO; + } + if(!pScanFilter->phyMode) + { + pScanFilter->phyMode = eCSR_DOT11_MODE_11g; + } + } +#endif /* FEATURE_WLAN_WAPI */ + /*Save the WPS info*/ + pScanFilter->bWPSAssociation = pProfile->bWPSAssociation; + pScanFilter->bOSENAssociation = pProfile->bOSENAssociation; + if( pProfile->countryCode[0] ) + { + //This causes the matching function to use countryCode as one of the criteria. + vos_mem_copy(pScanFilter->countryCode, pProfile->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pProfile->MDID.mdiePresent) + { + pScanFilter->MDID.mdiePresent = 1; + pScanFilter->MDID.mobilityDomain = pProfile->MDID.mobilityDomain; + } +#endif + +#ifdef WLAN_FEATURE_11W + // Management Frame Protection + pScanFilter->MFPEnabled = pProfile->MFPEnabled; + pScanFilter->MFPRequired = pProfile->MFPRequired; + pScanFilter->MFPCapable = pProfile->MFPCapable; +#endif + + }while(0); + + if(!HAL_STATUS_SUCCESS(status)) + { + csrFreeScanFilter(pMac, pScanFilter); + } + + return(status); +} + +tANI_BOOLEAN csrRoamIssueWmStatusChange( tpAniSirGlobal pMac, tANI_U32 sessionId, + eCsrRoamWmStatusChangeTypes Type, tSirSmeRsp *pSmeRsp ) +{ + tANI_BOOLEAN fCommandQueued = eANI_BOOLEAN_FALSE; + tSmeCmd *pCommand; + do + { + // Validate the type is ok... + if ( ( eCsrDisassociated != Type ) && ( eCsrDeauthenticated != Type ) ) break; + pCommand = csrGetCommandBuffer( pMac ); + if ( !pCommand ) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + break; + } + //Change the substate in case it is waiting for key + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ) + { + csrRoamStopWaitForKeyTimer( pMac ); + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } + pCommand->command = eSmeCommandWmStatusChange; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.wmStatusChangeCmd.Type = Type; + if ( eCsrDisassociated == Type ) + { + vos_mem_copy(&pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg, + pSmeRsp, + sizeof( pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg )); + } + else + { + vos_mem_copy(&pCommand->u.wmStatusChangeCmd.u.DeauthIndMsg, + pSmeRsp, + sizeof( pCommand->u.wmStatusChangeCmd.u.DeauthIndMsg )); + } + if( HAL_STATUS_SUCCESS( csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE) ) ) + { + fCommandQueued = eANI_BOOLEAN_TRUE; + } + else + { + smsLog( pMac, LOGE, FL(" fail to send message ") ); + csrReleaseCommandWmStatusChange( pMac, pCommand ); + } + + /* AP has issued Dissac/Deauth, Set the operating mode value to configured value */ + csrSetDefaultDot11Mode( pMac ); + } while( 0 ); + return( fCommandQueued ); +} + +static void csrUpdateRssi(tpAniSirGlobal pMac, void* pMsg) +{ + v_S7_t rssi = 0; + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)pMsg; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + if(pGetRssiReq) + { + if(NULL != pGetRssiReq->pVosContext) + { + vosStatus = WLANTL_GetRssi(pGetRssiReq->pVosContext, pGetRssiReq->staId, &rssi,pGetRssiReq); + } + else + { + smsLog( pMac, LOGE, FL("pGetRssiReq->pVosContext is NULL")); + return; + } + + if(NULL != pGetRssiReq->rssiCallback) + { + if(vosStatus!=VOS_STATUS_E_BUSY) + ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(rssi, pGetRssiReq->staId, pGetRssiReq->pDevContext); + else smsLog( pMac, LOG1, FL("rssi request is posted. waiting for reply")); + } + else + { + smsLog( pMac, LOGE, FL("pGetRssiReq->rssiCallback is NULL")); + return; + } + } + else + { + smsLog( pMac, LOGE, FL("pGetRssiReq is NULL")); + } + return; + +} + +static void csrUpdateSnr(tpAniSirGlobal pMac, void* pMsg) +{ + tAniGetSnrReq *pGetSnrReq = (tAniGetSnrReq*)pMsg; + + if (pGetSnrReq) + { + if (VOS_STATUS_SUCCESS != + WDA_GetSnr(pGetSnrReq)) + { + smsLog(pMac, LOGE, FL("Error in WDA_GetSnr")); + return; + } + } + else + { + smsLog(pMac, LOGE, FL("pGetSnrReq is NULL")); + } + + return; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +void csrTsmStatsRspProcessor(tpAniSirGlobal pMac, void* pMsg) +{ + tAniGetTsmStatsRsp* pTsmStatsRsp = (tAniGetTsmStatsRsp*)pMsg; + + if (NULL != pTsmStatsRsp) + { + /* Get roam Rssi request is backed up and passed back to the response, + Extract the request message to fetch callback */ + tpAniGetTsmStatsReq reqBkp + = (tAniGetTsmStatsReq*)pTsmStatsRsp->tsmStatsReq; + + if (NULL != reqBkp) + { + if (NULL != reqBkp->tsmStatsCallback) + { + ((tCsrTsmStatsCallback)(reqBkp->tsmStatsCallback))( + pTsmStatsRsp->tsmMetrics, + pTsmStatsRsp->staId, + reqBkp->pDevContext + ); + reqBkp->tsmStatsCallback = NULL; + } + vos_mem_free(reqBkp); + pTsmStatsRsp->tsmStatsReq = NULL; + } + else + { + smsLog( pMac, LOGE, FL("reqBkp is NULL")); + if (NULL != reqBkp) + { + vos_mem_free(reqBkp); + pTsmStatsRsp->tsmStatsReq = NULL; + } + } + } + else + { + smsLog( pMac, LOGE, FL("pTsmStatsRsp is NULL")); + } + return; +} + +void csrSendEseAdjacentApRepInd(tpAniSirGlobal pMac, tCsrRoamSession *pSession) +{ + tANI_U32 roamTS2 = 0; + tCsrRoamInfo roamInfo; + tpPESession pSessionEntry = NULL; + tANI_U8 sessionId = CSR_SESSION_ID_INVALID; + + if (NULL == pSession) + { + smsLog(pMac, LOGE, FL("pSession is NULL")); + return; + } + + roamTS2 = vos_timer_get_system_time(); + roamInfo.tsmRoamDelay = roamTS2 - pSession->roamTS1; + smsLog(pMac, LOG1, "Bssid("MAC_ADDRESS_STR") Roaming Delay(%u ms)", + MAC_ADDR_ARRAY(pSession->connectedProfile.bssid), + roamInfo.tsmRoamDelay); + + pSessionEntry = peFindSessionByBssid(pMac, + pSession->connectedProfile.bssid, + &sessionId); + if (NULL == pSessionEntry) + { + smsLog(pMac, LOGE, FL("session %d not found"), sessionId); + return; + } + + pSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly + = roamInfo.tsmRoamDelay; + + csrRoamCallCallback(pMac, pSession->sessionId, &roamInfo, + 0, eCSR_ROAM_ESE_ADJ_AP_REPORT_IND, 0); +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +static void csrRoamRssiIndHdlr(tpAniSirGlobal pMac, void* pMsg) +{ + WLANTL_TlIndicationReq *pTlRssiInd = (WLANTL_TlIndicationReq*)pMsg; + if(pTlRssiInd) + { + if(NULL != pTlRssiInd->tlCallback) + { + ((WLANTL_RSSICrossThresholdCBType)(pTlRssiInd->tlCallback)) + (pTlRssiInd->pAdapter, pTlRssiInd->rssiNotification, pTlRssiInd->pUserCtxt, pTlRssiInd->avgRssi); + } + else + { + smsLog( pMac, LOGE, FL("pTlRssiInd->tlCallback is NULL")); + } + } + else + { + smsLog( pMac, LOGE, FL("pTlRssiInd is NULL")); + } + return; +} + +eHalStatus csrSendResetApCapsChanged(tpAniSirGlobal pMac, tSirMacAddr *bssId) +{ + tpSirResetAPCapsChange pMsg; + tANI_U16 len; + eHalStatus status = eHAL_STATUS_SUCCESS; + + /* Create the message and send to lim */ + len = sizeof(tSirResetAPCapsChange); + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pMsg, sizeof(tSirResetAPCapsChange), 0); + pMsg->messageType = eWNI_SME_RESET_AP_CAPS_CHANGED; + pMsg->length = len; + vos_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + smsLog( pMac, LOG1, FL("CSR reset caps change for Bssid= "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMsg->bssId)); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + else + { + smsLog( pMac, LOGE, FL("Memory allocation failed\n")); + } + return status; +} + +void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) +{ + tSirSmeAssocInd *pAssocInd; + tSirSmeDisassocInd *pDisassocInd; + tSirSmeDeauthInd *pDeauthInd; + tSirSmeWmStatusChangeNtf *pStatusChangeMsg; + tSirSmeNewBssInfo *pNewBss; + tSmeIbssPeerInd *pIbssPeerInd; + tSirMacAddr Broadcastaddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + tSirSmeApNewCaps *pApNewCaps; + eCsrRoamResult result = eCSR_ROAM_RESULT_NONE; + eRoamCmdStatus roamStatus = eCSR_ROAM_FAILED; + tCsrRoamInfo *pRoamInfo = NULL; + tCsrRoamInfo roamInfo; + eHalStatus status; + tANI_U32 sessionId = CSR_SESSION_ID_INVALID; + tCsrRoamSession *pSession = NULL; + tpSirSmeSwitchChannelInd pSwitchChnInd; + tSmeMaxAssocInd *pSmeMaxAssocInd; + tSmeCmd pCommand; + vos_mem_set(&roamInfo, sizeof(roamInfo), 0); + + if (NULL == pSirMsg) + { smsLog(pMac, LOGE, FL("pSirMsg is NULL")); + return; + } + switch( pSirMsg->messageType ) + { + case eWNI_SME_ASSOC_IND: + { + tCsrRoamSession *pSession; + smsLog( pMac, LOG1, FL("Receive WNI_SME_ASSOC_IND from SME")); + pAssocInd = (tSirSmeAssocInd *)pSirMsg; + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pAssocInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + pSession = CSR_GET_SESSION(pMac, sessionId); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + pRoamInfo = &roamInfo; + + // Required for indicating the frames to upper layer + pRoamInfo->assocReqLength = pAssocInd->assocReqLength; + pRoamInfo->assocReqPtr = pAssocInd->assocReqPtr; + + pRoamInfo->beaconPtr = pAssocInd->beaconPtr; + pRoamInfo->beaconLength = pAssocInd->beaconLength; + pRoamInfo->statusCode = eSIR_SME_SUCCESS; //send the status code as Success + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + + pRoamInfo->staId = (tANI_U8)pAssocInd->staId; + pRoamInfo->rsnIELen = (tANI_U8)pAssocInd->rsnIE.length; + pRoamInfo->prsnIE = pAssocInd->rsnIE.rsnIEdata; + +#ifdef FEATURE_WLAN_WAPI + pRoamInfo->wapiIELen = (tANI_U8)pAssocInd->wapiIE.length; + pRoamInfo->pwapiIE = pAssocInd->wapiIE.wapiIEdata; +#endif + pRoamInfo->addIELen = (tANI_U8)pAssocInd->addIE.length; + pRoamInfo->paddIE = pAssocInd->addIE.addIEdata; + vos_mem_copy(pRoamInfo->peerMac, pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(&pRoamInfo->bssid, pAssocInd->bssId, + sizeof(tCsrBssid)); + pRoamInfo->wmmEnabledSta = pAssocInd->wmmEnabledSta; + pRoamInfo->timingMeasCap = pAssocInd->timingMeasCap; + vos_mem_copy(&pRoamInfo->chan_info, &pAssocInd->chan_info, + sizeof(tSirSmeChanInfo)); + if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile)) + 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)) + { + if(pSession->pCurRoamProfile && + CSR_IS_ENC_TYPE_STATIC(pSession->pCurRoamProfile->negotiatedUCEncryptionType)) + { + csrRoamIssueSetContextReq( pMac, sessionId, pSession->pCurRoamProfile->negotiatedUCEncryptionType, + pSession->pConnectBssDesc, + &(pRoamInfo->peerMac), + FALSE, TRUE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter. + pRoamInfo->fAuthRequired = FALSE; + } + else + { + pRoamInfo->fAuthRequired = TRUE; + } + 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 + } + /* Send Association completion message to PE */ + status = csrSendAssocCnfMsg( pMac, pAssocInd, status );//Sta + + /* send a message to CSR itself just to avoid the EAPOL frames going + * OTA before association response */ + if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile)) + { + status = csrSendAssocIndToUpperLayerCnfMsg(pMac, pAssocInd, status, sessionId); + } + else if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile) && (pRoamInfo->statusCode != eSIR_SME_ASSOC_REFUSED)) + { + pRoamInfo->fReassocReq = pAssocInd->reassocReq; + //status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); + status = csrSendAssocIndToUpperLayerCnfMsg(pMac, pAssocInd, status, sessionId); + } + } + } + break; + case eWNI_SME_DISASSOC_IND: + // Check if AP dis-associated us because of MIC failure. If so, + // then we need to take action immediately and not wait till the + // the WmStatusChange requests is pushed and processed + pDisassocInd = (tSirSmeDisassocInd *)pSirMsg; + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pDisassocInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("DISASSOCIATION Indication from MAC for session %d "), sessionId); + smsLog( pMac, LOGE, FL("DISASSOCIATION from peer =" MAC_ADDRESS_STR " " + " reason = %d status = %d "), + MAC_ADDR_ARRAY(pDisassocInd->peerMacAddr), + pDisassocInd->reasonCode, pDisassocInd->statusCode); + // If we are in neighbor preauth done state then on receiving + // disassoc or deauth we dont roam instead we just disassoc + // from current ap and then go to disconnected state + // This happens for ESE and 11r FT connections ONLY. +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csrRoamIs11rAssoc(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, + sessionId); + } +#endif +#ifdef FEATURE_WLAN_ESE + if (csrRoamIsESEAssoc(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, + sessionId); + } +#endif +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsFastRoamEnabled(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, + sessionId); + } +#endif + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csrRoamLinkDown(pMac, sessionId); + csrRoamIssueWmStatusChange( pMac, sessionId, eCsrDisassociated, pSirMsg ); + if(CSR_IS_INFRA_AP(&pSession->connectedProfile)) + { + + pRoamInfo = &roamInfo; + + pRoamInfo->statusCode = pDisassocInd->statusCode; + pRoamInfo->reasonCode = pDisassocInd->reasonCode; + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + + pRoamInfo->staId = (tANI_U8)pDisassocInd->staId; + + vos_mem_copy(pRoamInfo->peerMac, pDisassocInd->peerMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(&pRoamInfo->bssid, pDisassocInd->bssId, + sizeof(tCsrBssid)); + + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_DISASSOC_IND); + + /* + * STA/P2P client got disassociated so remove any pending deauth + * commands in sme pending list + */ + pCommand.command = eSmeCommandRoam; + pCommand.sessionId = (tANI_U8)sessionId; + pCommand.u.roamCmd.roamReason = eCsrForcedDeauthSta; + vos_mem_copy(pCommand.u.roamCmd.peerMac, + pDisassocInd->peerMacAddr, + sizeof(tSirMacAddr)); + csrRoamRemoveDuplicateCommand(pMac, sessionId, &pCommand, eCsrForcedDeauthSta); + } + } + else + { + smsLog(pMac, LOGE, FL(" Session Id not found for BSSID " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDisassocInd->bssId)); + } + break; + case eWNI_SME_DEAUTH_IND: + smsLog( pMac, LOG1, FL("DEAUTHENTICATION Indication from MAC")); + pDeauthInd = (tpSirSmeDeauthInd)pSirMsg; + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pDeauthInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + // If we are in neighbor preauth done state then on receiving + // disassoc or deauth we dont roam instead we just disassoc + // from current ap and then go to disconnected state + // This happens for ESE and 11r FT connections ONLY. +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csrRoamIs11rAssoc(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, + sessionId); + } +#endif +#ifdef FEATURE_WLAN_ESE + if (csrRoamIsESEAssoc(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, + sessionId); + } +#endif +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsFastRoamEnabled(pMac, sessionId) && + (csrNeighborRoamStatePreauthDone(pMac, sessionId))) { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac, + sessionId); + } +#endif + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csrRoamLinkDown(pMac, sessionId); + csrRoamIssueWmStatusChange( pMac, sessionId, eCsrDeauthenticated, pSirMsg ); + if(CSR_IS_INFRA_AP(&pSession->connectedProfile)) + { + + pRoamInfo = &roamInfo; + + pRoamInfo->statusCode = pDeauthInd->statusCode; + pRoamInfo->reasonCode = pDeauthInd->reasonCode; + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + + pRoamInfo->staId = (tANI_U8)pDeauthInd->staId; + + vos_mem_copy(pRoamInfo->peerMac, pDeauthInd->peerMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(&pRoamInfo->bssid, pDeauthInd->bssId, + sizeof(tCsrBssid)); + + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_DEAUTH_IND); + } + } + break; + + case eWNI_SME_SWITCH_CHL_REQ: // in case of STA, the SWITCH_CHANNEL originates from its AP + smsLog( pMac, LOGW, FL("eWNI_SME_SWITCH_CHL_REQ from SME")); + pSwitchChnInd = (tpSirSmeSwitchChannelInd)pSirMsg; + //Update with the new channel id. + //The channel id is hidden in the statusCode. + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pSwitchChnInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + pSession->connectedProfile.operationChannel = (tANI_U8)pSwitchChnInd->newChannelId; + if(pSession->pConnectBssDesc) + { + pSession->pConnectBssDesc->channelId = (tANI_U8)pSwitchChnInd->newChannelId; + } + } + break; + + case eWNI_SME_DEAUTH_RSP: + smsLog( pMac, LOGW, FL("eWNI_SME_DEAUTH_RSP from SME")); + { + tSirSmeDeauthRsp* pDeauthRsp = (tSirSmeDeauthRsp *)pSirMsg; + sessionId = pDeauthRsp->sessionId; + if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + { + pSession = CSR_GET_SESSION(pMac, sessionId); + if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) ) + { + pRoamInfo = &roamInfo; + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + vos_mem_copy(pRoamInfo->peerMac, pDeauthRsp->peerMacAddr, + sizeof(tSirMacAddr)); + pRoamInfo->reasonCode = eCSR_ROAM_RESULT_FORCED; + pRoamInfo->statusCode = pDeauthRsp->statusCode; + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_FORCED); + } + } + } + break; + + case eWNI_SME_DISASSOC_RSP: + /* session id is invalid here so cant use it to access the array curSubstate as index */ + smsLog( pMac, LOGW, FL("eWNI_SME_DISASSOC_RSP from SME ")); + { + tSirSmeDisassocRsp *pDisassocRsp = (tSirSmeDisassocRsp *)pSirMsg; + sessionId = pDisassocRsp->sessionId; + if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + { + pSession = CSR_GET_SESSION(pMac, sessionId); + if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) ) + { + pRoamInfo = &roamInfo; + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + vos_mem_copy(pRoamInfo->peerMac, pDisassocRsp->peerMacAddr, + sizeof(tSirMacAddr)); + pRoamInfo->reasonCode = eCSR_ROAM_RESULT_FORCED; + pRoamInfo->statusCode = pDisassocRsp->statusCode; + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_FORCED); + } + } + } + break; + case eWNI_SME_MIC_FAILURE_IND: + { + tpSirSmeMicFailureInd pMicInd = (tpSirSmeMicFailureInd)pSirMsg; + eCsrRoamResult result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST; + + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pMicInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.u.pMICFailureInfo = &pMicInd->info; + pRoamInfo = &roamInfo; + if(pMicInd->info.multicast) + { + result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP; + } + else + { + result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST; + } + csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_MIC_ERROR_IND, result); + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + vos_mem_set(&secEvent, sizeof(vos_event_wlan_security_payload_type), 0); + secEvent.eventId = WLAN_SECURITY_EVENT_MIC_ERROR; + secEvent.encryptionModeMulticast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + secEvent.encryptionModeUnicast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + secEvent.authMode = + (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + vos_mem_copy(secEvent.bssid, + pSession->connectedProfile.bssid, 6); + WLAN_VOS_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY); + } +#endif//FEATURE_WLAN_DIAG_SUPPORT_CSR + } + break; + case eWNI_SME_WPS_PBC_PROBE_REQ_IND: + { + tpSirSmeProbeReqInd pProbeReqInd = (tpSirSmeProbeReqInd)pSirMsg; + smsLog( pMac, LOG1, FL("WPS PBC Probe request Indication from SME")); + + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pProbeReqInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.u.pWPSPBCProbeReq = &pProbeReqInd->WPSPBCProbeReq; + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_WPS_PBC_PROBE_REQ_IND, + eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND); + } + } + break; + + case eWNI_SME_WM_STATUS_CHANGE_NTF: + pStatusChangeMsg = (tSirSmeWmStatusChangeNtf *)pSirMsg; + switch( pStatusChangeMsg->statusChangeCode ) + { + case eSIR_SME_IBSS_ACTIVE: + sessionId = csrFindIbssSession( pMac ); + if( CSR_SESSION_ID_INVALID != sessionId ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED; + if(pSession->pConnectBssDesc) + { + vos_mem_copy(&roamInfo.bssid, + pSession->pConnectBssDesc->bssId, + sizeof(tCsrBssid)); + roamInfo.u.pConnectedProfile = &pSession->connectedProfile; + pRoamInfo = &roamInfo; + } + else + { + smsLog(pMac, LOGE, " CSR eSIR_SME_IBSS_NEW_PEER connected BSS is empty"); + } + result = eCSR_ROAM_RESULT_IBSS_CONNECT; + roamStatus = eCSR_ROAM_CONNECT_STATUS_UPDATE; + } + break; + case eSIR_SME_IBSS_INACTIVE: + sessionId = csrFindIbssSession( pMac ); + if( CSR_SESSION_ID_INVALID != sessionId ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; + result = eCSR_ROAM_RESULT_IBSS_INACTIVE; + roamStatus = eCSR_ROAM_CONNECT_STATUS_UPDATE; + } + break; + case eSIR_SME_JOINED_NEW_BSS: // IBSS coalescing. + sessionId = csrFindIbssSession( pMac ); + if( CSR_SESSION_ID_INVALID != sessionId ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + // update the connection state information + pNewBss = &pStatusChangeMsg->statusChangeInfo.newBssInfo; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + tANI_U32 bi; + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING; + if(pNewBss) + { + vos_mem_copy(pIbssLog->bssid, pNewBss->bssId, 6); + if(pNewBss->ssId.length) + { + vos_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId, + pNewBss->ssId.length); + } + pIbssLog->operatingChannel = pNewBss->channelNumber; + } + if(HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &bi))) + { + //***U8 is not enough for beacon interval + pIbssLog->beaconInterval = (v_U8_t)bi; + } + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + csrRoamUpdateConnectedProfileFromNewBss( pMac, sessionId, pNewBss ); + + if ((eCSR_ENCRYPT_TYPE_NONE == + pSession->connectedProfile.EncryptionType )) + { + csrRoamIssueSetContextReq( pMac, sessionId, + pSession->connectedProfile.EncryptionType, + pSession->pConnectBssDesc, + &Broadcastaddr, + FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 ); + } + result = eCSR_ROAM_RESULT_IBSS_COALESCED; + roamStatus = eCSR_ROAM_IBSS_IND; + vos_mem_copy(&roamInfo.bssid, &pNewBss->bssId, + sizeof(tCsrBssid)); + pRoamInfo = &roamInfo; + /* This BSSID is the real BSSID, let's save it */ + if(pSession->pConnectBssDesc) + { + vos_mem_copy(pSession->pConnectBssDesc->bssId, + &pNewBss->bssId, sizeof(tCsrBssid)); + } + } + smsLog(pMac, LOGW, "CSR: eSIR_SME_JOINED_NEW_BSS received from PE"); + break; + // detection by LIM that the capabilities of the associated AP have changed. + case eSIR_SME_AP_CAPS_CHANGED: + pApNewCaps = &pStatusChangeMsg->statusChangeInfo.apNewCaps; + smsLog(pMac, LOGW, "CSR handling eSIR_SME_AP_CAPS_CHANGED"); + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pApNewCaps->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) + { + if ((eCSR_ROAMING_STATE_JOINED == pMac->roam.curState[sessionId]) && + ((eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC == pMac->roam.curSubState[sessionId]) || + (eCSR_ROAM_SUBSTATE_NONE == pMac->roam.curSubState[sessionId]) || + (eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC == pMac->roam.curSubState[sessionId]) || + (eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC == pMac->roam.curSubState[sessionId])) + ) + { + smsLog(pMac, LOGW, "Calling csrRoamDisconnectInternal"); + csrRoamDisconnectInternal(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + } + else + { + smsLog(pMac, LOGW, + FL("Skipping csrScanForCapabilityChange as " + "CSR is in state %s and sub-state %s"), + macTraceGetcsrRoamState( + pMac->roam.curState[sessionId]), + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[sessionId])); + /* We ignore the caps change event if CSR is not in full connected state. + * Send one event to PE to reset limSentCapsChangeNtf + * Once limSentCapsChangeNtf set 0, lim can send sub sequent CAPS change event + * otherwise lim cannot send any CAPS change events to SME */ + csrSendResetApCapsChanged(pMac, &pApNewCaps->bssId); + } + } + break; + + default: + roamStatus = eCSR_ROAM_FAILED; + result = eCSR_ROAM_RESULT_NONE; + break; + } // end switch on statusChangeCode + if(eCSR_ROAM_RESULT_NONE != result) + { + csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, roamStatus, result); + } + break; + case eWNI_SME_IBSS_NEW_PEER_IND: + pIbssPeerInd = (tSmeIbssPeerInd *)pSirMsg; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_JOIN; + vos_mem_copy(pIbssLog->peerMacAddr, &pIbssPeerInd->peerAddr, 6); + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + sessionId = csrFindIbssSession( pMac ); + if( CSR_SESSION_ID_INVALID != sessionId ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + // Issue the set Context request to LIM to establish the Unicast STA context for the new peer... + if(pSession->pConnectBssDesc) + { + vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, + sizeof(tCsrBssid)); + vos_mem_copy(&roamInfo.bssid, pSession->pConnectBssDesc->bssId, + sizeof(tCsrBssid)); + if(pIbssPeerInd->mesgLen > sizeof(tSmeIbssPeerInd)) + { + roamInfo.pbFrames = vos_mem_malloc((pIbssPeerInd->mesgLen + - sizeof(tSmeIbssPeerInd))); + if ( NULL == roamInfo.pbFrames ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (HAL_STATUS_SUCCESS(status)) + { + roamInfo.nBeaconLength = (pIbssPeerInd->mesgLen - sizeof(tSmeIbssPeerInd)); + vos_mem_copy(roamInfo.pbFrames, + ((tANI_U8 *)pIbssPeerInd) + sizeof(tSmeIbssPeerInd), + roamInfo.nBeaconLength); + } + roamInfo.staId = (tANI_U8)pIbssPeerInd->staId; + roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig; + roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig; + roamInfo.pBssDesc = vos_mem_malloc(pSession->pConnectBssDesc->length); + if ( NULL == roamInfo.pBssDesc ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (HAL_STATUS_SUCCESS(status)) + { + vos_mem_copy(roamInfo.pBssDesc, + pSession->pConnectBssDesc, + pSession->pConnectBssDesc->length); + } + if(HAL_STATUS_SUCCESS(status)) + { + pRoamInfo = &roamInfo; + } + else + { + if(roamInfo.pbFrames) + { + vos_mem_free(roamInfo.pbFrames); + } + if(roamInfo.pBssDesc) + { + vos_mem_free(roamInfo.pBssDesc); + } + } + } + else + { + pRoamInfo = &roamInfo; + } + if ((eCSR_ENCRYPT_TYPE_NONE == + pSession->connectedProfile.EncryptionType )) + { + csrRoamIssueSetContextReq( pMac, sessionId, + pSession->connectedProfile.EncryptionType, + pSession->pConnectBssDesc, + &(pIbssPeerInd->peerAddr), + FALSE, TRUE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter. + } + } + else + { + smsLog(pMac, LOGW, " CSR eSIR_SME_IBSS_NEW_PEER connected BSS is empty"); + } + //send up the sec type for the new peer + if (pRoamInfo) + { + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + } + csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, + eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_NEW_PEER); + if(pRoamInfo) + { + if(roamInfo.pbFrames) + { + vos_mem_free(roamInfo.pbFrames); + } + if(roamInfo.pBssDesc) + { + vos_mem_free(roamInfo.pBssDesc); + } + } + } + break; + case eWNI_SME_IBSS_PEER_DEPARTED_IND: + pIbssPeerInd = (tSmeIbssPeerInd*)pSirMsg; + sessionId = csrFindIbssSession( pMac ); + if( CSR_SESSION_ID_INVALID != sessionId ) + { +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_LEAVE; + if(pIbssPeerInd) + { + vos_mem_copy(pIbssLog->peerMacAddr, + &pIbssPeerInd->peerAddr, 6); + } + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + smsLog(pMac, LOGW, "CSR: Peer departed notification from LIM"); + roamInfo.staId = (tANI_U8)pIbssPeerInd->staId; + roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig; + roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig; + vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, + sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED); + } + break; + case eWNI_SME_SETCONTEXT_RSP: + { + tSirSmeSetContextRsp *pRsp = (tSirSmeSetContextRsp *)pSirMsg; + tListElem *pEntry; + tSmeCmd *pCommand; + + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( eSmeCommandSetKey == pCommand->command ) + { + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + if(eCSR_ENCRYPT_TYPE_NONE != pSession->connectedProfile.EncryptionType) + { + WLAN_VOS_DIAG_EVENT_DEF(setKeyEvent, vos_event_wlan_security_payload_type); + vos_mem_set(&setKeyEvent, + sizeof(vos_event_wlan_security_payload_type), 0); + if( pRsp->peerMacAddr[0] & 0x01 ) + { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_RSP; + } + else + { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_RSP; + } + setKeyEvent.encryptionModeMulticast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + setKeyEvent.encryptionModeUnicast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + vos_mem_copy(setKeyEvent.bssid, + pSession->connectedProfile.bssid, 6); + setKeyEvent.authMode = + (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + if( eSIR_SME_SUCCESS != pRsp->statusCode ) + { + setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE; + } + WLAN_VOS_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY); + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId) ) + { + csrRoamStopWaitForKeyTimer( pMac ); + + /* We are done with authentication, + whether succeed or not */ + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + //We do it here because this linkup function is not called after association + //when a key needs to be set. + if( csrIsConnStateConnectedInfra(pMac, sessionId) ) + { + csrRoamLinkUp(pMac, pSession->connectedProfile.bssid); + } + } + if( eSIR_SME_SUCCESS == pRsp->statusCode ) + { + vos_mem_copy(&roamInfo.peerMac, + &pRsp->peerMacAddr, sizeof(tCsrBssid)); + //Make sure we install the GTK before indicating to HDD as authenticated + //This is to prevent broadcast packets go out after PTK and before GTK. + if ( vos_mem_compare( &Broadcastaddr, pRsp->peerMacAddr, + sizeof(tSirMacAddr) ) ) + { +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + tpSirSetActiveModeSetBncFilterReq pMsg; + pMsg = vos_mem_malloc(sizeof(tSirSetActiveModeSetBncFilterReq)); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SET_BCN_FILTER_REQ); + pMsg->length = pal_cpu_to_be16(sizeof( tANI_U8)); + pMsg->seesionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg ); + } +#endif + result = eCSR_ROAM_RESULT_AUTHENTICATED; + } + else + { + result = eCSR_ROAM_RESULT_NONE; + } + pRoamInfo = &roamInfo; + } + else + { + result = eCSR_ROAM_RESULT_FAILURE; + smsLog(pMac, LOGE, "CSR: Roam Completion setkey " + "command failed(%d) PeerMac "MAC_ADDRESS_STR, + pRsp->statusCode, MAC_ADDR_ARRAY(pRsp->peerMacAddr)); + } + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.setKeyCmd.roamId, + eCSR_ROAM_SET_KEY_COMPLETE, result); + // Indicate SME_QOS that the SET_KEY is completed, so that SME_QOS + // can go ahead and initiate the TSPEC if any are pending + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_SET_KEY_SUCCESS_IND, NULL); +#ifdef FEATURE_WLAN_ESE + /* Send Adjacent AP report to new AP. */ + if (result == eCSR_ROAM_RESULT_AUTHENTICATED && + pSession->isPrevApInfoValid && + pSession->connectedProfile.isESEAssoc) + { +#ifdef FEATURE_WLAN_ESE_UPLOAD + csrSendEseAdjacentApRepInd(pMac, pSession); +#else + csrEseSendAdjacentApRepMsg(pMac, pSession); +#endif + pSession->isPrevApInfoValid = FALSE; + } +#endif + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandSetKey( pMac, pCommand ); + } + } + else + { + smsLog( pMac, LOGE, "CSR: Roam Completion called but setkey command is not ACTIVE ..." ); + } + } + else + { + smsLog( pMac, LOGE, "CSR: SetKey Completion called but NO commands are ACTIVE ..." ); + } + smeProcessPendingQueue( pMac ); + } + break; + case eWNI_SME_REMOVEKEY_RSP: + { + tSirSmeRemoveKeyRsp *pRsp = (tSirSmeRemoveKeyRsp *)pSirMsg; + tListElem *pEntry; + tSmeCmd *pCommand; + + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( eSmeCommandRemoveKey == pCommand->command ) + { + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + WLAN_VOS_DIAG_EVENT_DEF(removeKeyEvent, vos_event_wlan_security_payload_type); + vos_mem_set(&removeKeyEvent, + sizeof(vos_event_wlan_security_payload_type), 0); + removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_RSP; + removeKeyEvent.encryptionModeMulticast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + removeKeyEvent.encryptionModeUnicast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + vos_mem_copy( removeKeyEvent.bssid, + pSession->connectedProfile.bssid, 6); + removeKeyEvent.authMode = + (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + if( eSIR_SME_SUCCESS != pRsp->statusCode ) + { + removeKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE; + } + WLAN_VOS_DIAG_EVENT_REPORT(&removeKeyEvent, EVENT_WLAN_SECURITY); + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + if( eSIR_SME_SUCCESS == pRsp->statusCode ) + { + vos_mem_copy(&roamInfo.peerMac, &pRsp->peerMacAddr, + sizeof(tCsrBssid)); + result = eCSR_ROAM_RESULT_NONE; + pRoamInfo = &roamInfo; + } + else + { + result = eCSR_ROAM_RESULT_FAILURE; + } + csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.setKeyCmd.roamId, + eCSR_ROAM_REMOVE_KEY_COMPLETE, result); + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandRemoveKey( pMac, pCommand ); + } + } + else + { + smsLog( pMac, LOGW, "CSR: Roam Completion called but setkey command is not ACTIVE ..." ); + } + } + else + { + smsLog( pMac, LOGW, "CSR: SetKey Completion called but NO commands are ACTIVE ..." ); + } + smeProcessPendingQueue( pMac ); + } + break; + case eWNI_SME_GET_STATISTICS_RSP: + smsLog( pMac, LOG2, FL("Stats rsp from PE")); + csrRoamStatsRspProcessor( pMac, pSirMsg ); + break; +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_GET_TSM_STATS_RSP: + smsLog( pMac, LOG2, FL("TSM Stats rsp from PE")); + csrTsmStatsRspProcessor( pMac, pSirMsg ); + break; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_GET_RSSI_REQ: + smsLog( pMac, LOG2, FL("GetRssiReq from self")); + csrUpdateRssi( pMac, pSirMsg ); + break; + + case eWNI_SME_GET_SNR_REQ: + smsLog( pMac, LOG2, FL("GetSnrReq from self")); + csrUpdateSnr(pMac, pSirMsg); + break; + +#ifdef WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_PRE_AUTH_RSP: + csrRoamFTPreAuthRspProcessor( 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")); + sessionId = pSmeMaxAssocInd->sessionId; + roamInfo.sessionId = sessionId; + vos_mem_copy(&roamInfo.peerMac, pSmeMaxAssocInd->peerMac, + sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED); + break; + + case eWNI_SME_BTAMP_LOG_LINK_IND: + smsLog( pMac, LOG1, FL("Establish logical link req from HCI serialized through MC thread")); + break; + case eWNI_SME_RSSI_IND: + smsLog( pMac, LOG1, FL("RSSI indication from TL serialized through MC thread")); + csrRoamRssiIndHdlr( pMac, pSirMsg ); + break; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eWNI_SME_CANDIDATE_FOUND_IND: + smsLog(pMac, LOG2, FL("Candidate found indication from PE")); + csrNeighborRoamCandidateFoundIndHdlr(pMac, pSirMsg); + break; + case eWNI_SME_HANDOFF_REQ: + smsLog( pMac, LOG2, FL("Handoff Req from self")); + csrNeighborRoamHandoffReqHdlr( pMac, pSirMsg ); + break; +#endif + + default: + break; + } // end switch on message type +} + +void csrCallRoamingCompletionCallback(tpAniSirGlobal pMac, tCsrRoamSession *pSession, + tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, eCsrRoamResult roamResult) +{ + if(pSession) + { + if(pSession->bRefAssocStartCnt) + { + pSession->bRefAssocStartCnt--; + + if (0 != pSession->bRefAssocStartCnt) + { + VOS_ASSERT( pSession->bRefAssocStartCnt == 0); + return; + } + //Need to call association_completion because there is an assoc_start pending. + csrRoamCallCallback(pMac, pSession->sessionId, NULL, roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_FAILURE); + } + csrRoamCallCallback(pMac, pSession->sessionId, pRoamInfo, roamId, eCSR_ROAM_ROAMING_COMPLETION, roamResult); + } + else + { + smsLog(pMac, LOGW, FL(" pSession is NULL")); + } +} + + +eHalStatus csrRoamStartRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamingReason roamingReason) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + if(CSR_IS_LOSTLINK_ROAMING(roamingReason) && + (eANI_BOOLEAN_FALSE == pMac->roam.roamSession[sessionId].fCancelRoaming)) + { + status = csrScanRequestLostLink1( pMac, sessionId ); + } + return(status); +} + +//return a boolean to indicate whether roaming completed or continue. +tANI_BOOLEAN csrRoamCompleteRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_BOOLEAN fForce, eCsrRoamResult roamResult) +{ + tANI_BOOLEAN fCompleted = eANI_BOOLEAN_TRUE; + tANI_TIMESTAMP roamTime = (tANI_TIMESTAMP)(pMac->roam.configParam.nRoamingTime * PAL_TICKS_PER_SECOND); + tANI_TIMESTAMP curTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eANI_BOOLEAN_FALSE; + } + //Check whether time is up + if(pSession->fCancelRoaming || fForce || + ((curTime - pSession->roamingStartTime) > roamTime) || + eCsrReassocRoaming == pSession->roamingReason || + eCsrDynamicRoaming == pSession->roamingReason) + { + smsLog(pMac, LOGW, FL(" indicates roaming completion")); + if(pSession->fCancelRoaming && CSR_IS_LOSTLINK_ROAMING(pSession->roamingReason)) + { + /* + * Roaming is canceled, tell HDD to indicate disconnect + * Because LIM overload deauth_ind for both deauth frame and + * missed beacon we need to use this logic to distinguish it. + * For missed beacon, LIM set reason to be eSIR_BEACON_MISSED + */ + if(eSIR_BEACON_MISSED == pSession->roamingStatusCode) + { + roamResult = eCSR_ROAM_RESULT_LOSTLINK; + } + else if(eCsrLostlinkRoamingDisassoc == pSession->roamingReason) + { + roamResult = eCSR_ROAM_RESULT_DISASSOC_IND; + } + else if(eCsrLostlinkRoamingDeauth == pSession->roamingReason) + { + roamResult = eCSR_ROAM_RESULT_DEAUTH_IND; + } + else + { + roamResult = eCSR_ROAM_RESULT_LOSTLINK; + } + } + csrCallRoamingCompletionCallback(pMac, pSession, NULL, 0, roamResult); + pSession->roamingReason = eCsrNotRoaming; + } + else + { + pSession->roamResult = roamResult; + if(!HAL_STATUS_SUCCESS(csrRoamStartRoamingTimer(pMac, sessionId, + VOS_TIMER_TO_SEC_UNIT))) + { + csrCallRoamingCompletionCallback(pMac, pSession, NULL, 0, roamResult); + pSession->roamingReason = eCsrNotRoaming; + } + else + { + fCompleted = eANI_BOOLEAN_FALSE; + } + } + return(fCompleted); +} + +void csrRoamCancelRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if(CSR_IS_ROAMING(pSession)) + { + smsLog(pMac, LOGW, "Cancel roaming"); + pSession->fCancelRoaming = eANI_BOOLEAN_TRUE; + if(CSR_IS_ROAM_JOINING(pMac, sessionId) && CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId)) + { + //No need to do anything in here because the handler takes care of it + } + else + { + eCsrRoamResult roamResult = CSR_IS_LOSTLINK_ROAMING(pSession->roamingReason) ? + eCSR_ROAM_RESULT_LOSTLINK : eCSR_ROAM_RESULT_NONE; + //Roaming is stopped after here + csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_TRUE, roamResult); + /* Since CSR may be in lost link roaming situation, abort all + roaming related activities */ + csrScanAbortMacScan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT); + csrRoamStopRoamingTimer(pMac, sessionId); + } + } +} + +void csrRoamRoamingTimerHandler(void *pv) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv; + tpAniSirGlobal pMac = pInfo->pMac; + tANI_U32 sessionId = pInfo->sessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if(eANI_BOOLEAN_FALSE == pSession->fCancelRoaming) + { + if(!HAL_STATUS_SUCCESS(csrRoamStartRoaming(pMac, sessionId, pSession->roamingReason))) + { + csrCallRoamingCompletionCallback(pMac, pSession, NULL, 0, pSession->roamResult); + pSession->roamingReason = eCsrNotRoaming; + } + } +} + +eHalStatus csrRoamStartRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval) +{ + eHalStatus status; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOG1, " csrScanStartRoamingTimer"); + pSession->roamingTimerInfo.sessionId = (tANI_U8)sessionId; + status = vos_timer_start(&pSession->hTimerRoaming, + interval/VOS_TIMER_TO_MS_UNIT); + + return (status); +} + +eHalStatus csrRoamStopRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + return (vos_timer_stop(&pMac->roam.roamSession[sessionId].hTimerRoaming)); +} + +void csrRoamWaitForKeyTimeOutHandler(void *pv) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv; + tpAniSirGlobal pMac = pInfo->pMac; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pInfo->sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if(pSession == NULL) { + smsLog(pMac, LOGE, "%s: session not found", __func__); + return; + } + + smsLog(pMac, LOGW, FL("WaitForKey timer expired in state=%s sub-state=%s"), + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[pInfo->sessionId].neighborRoamState), + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pInfo->sessionId])); + + if( CSR_IS_WAIT_FOR_KEY( pMac, pInfo->sessionId ) ) + { +#ifdef FEATURE_WLAN_LFR + if (csrNeighborRoamIsHandoffInProgress(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); + } +#endif + 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); + } + + if( csrIsConnStateConnectedInfra(pMac, pInfo->sessionId) ) + { + csrRoamLinkUp(pMac, pSession->connectedProfile.bssid); + smeProcessPendingQueue(pMac); + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status )) + { + csrRoamDisconnect(pMac, pInfo->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + sme_ReleaseGlobalLock(&pMac->sme); + } + } + else + { + smsLog(pMac, LOGE, "%s: Session id %d is disconnected", + __func__, pInfo->sessionId); + } + } +} + +eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, tANI_U32 interval) +{ + eHalStatus status; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pMac->roam.WaitForKeyTimerInfo.sessionId]; +#ifdef FEATURE_WLAN_LFR + if (csrNeighborRoamIsHandoffInProgress(pMac, + pMac->roam.WaitForKeyTimerInfo.sessionId)) + { + /* Disable heartbeat timer when hand-off is in progress */ + smsLog(pMac, LOG2, FL("disabling HB timer in state=%s sub-state=%s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState), + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pMac->roam.WaitForKeyTimerInfo.sessionId] + )); + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0, NULL, eANI_BOOLEAN_FALSE); + } +#endif + smsLog(pMac, LOG1, " csrScanStartWaitForKeyTimer"); + status = vos_timer_start(&pMac->roam.hTimerWaitForKey, + interval/VOS_TIMER_TO_MS_UNIT); + + return (status); +} + +eHalStatus csrRoamStopWaitForKeyTimer(tpAniSirGlobal pMac) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pMac->roam.WaitForKeyTimerInfo.sessionId]; + + smsLog(pMac, LOG2, FL("WaitForKey timer stopped in state=%s sub-state=%s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState), + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pMac->roam.WaitForKeyTimerInfo.sessionId])); +#ifdef FEATURE_WLAN_LFR + if (csrNeighborRoamIsHandoffInProgress(pMac, + pMac->roam.WaitForKeyTimerInfo.sessionId)) + { + /* + * Enable heartbeat timer when hand-off is in progress + * and Key Wait timer got stopped for some reason + */ + smsLog(pMac, LOG2, "Enabling HB timer after WaitKey stop" + " (nHBCount=%d)", + pMac->roam.configParam.HeartbeatThresh24); + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, + pMac->roam.configParam.HeartbeatThresh24, + NULL, eANI_BOOLEAN_FALSE); + } +#endif + return (vos_timer_stop(&pMac->roam.hTimerWaitForKey)); +} + +void csrRoamCompletion(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo, tSmeCmd *pCommand, + eCsrRoamResult roamResult, tANI_BOOLEAN fSuccess) +{ + eRoamCmdStatus roamStatus = csrGetRoamCompleteStatus(pMac, sessionId); + tANI_U32 roamId = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if(pCommand) + { + roamId = pCommand->u.roamCmd.roamId; + if (sessionId != pCommand->sessionId) + { + VOS_ASSERT( sessionId == pCommand->sessionId ); + return; + } + } + if(eCSR_ROAM_ROAMING_COMPLETION == roamStatus) + { + //if success, force roaming completion + csrRoamCompleteRoaming(pMac, sessionId, fSuccess, roamResult); + } + else + { + if (pSession->bRefAssocStartCnt != 0) + { + VOS_ASSERT(pSession->bRefAssocStartCnt == 0); + return; + } + smsLog(pMac, LOGW, FL(" indicates association completion. roamResult = %d"), roamResult); + csrRoamCallCallback(pMac, sessionId, pRoamInfo, roamId, roamStatus, roamResult); + } +} + +eHalStatus csrRoamLostLink( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 type, tSirSmeRsp *pSirMsg) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeDeauthInd *pDeauthIndMsg = NULL; + tSirSmeDisassocInd *pDisassocIndMsg = NULL; + eCsrRoamResult result = eCSR_ROAM_RESULT_LOSTLINK; + tCsrRoamInfo *pRoamInfo = NULL; + tCsrRoamInfo roamInfo; + tANI_BOOLEAN fToRoam; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + //Only need to roam for infra station. In this case P2P client will roam as well + fToRoam = CSR_IS_INFRASTRUCTURE(&pSession->connectedProfile); + pSession->fCancelRoaming = eANI_BOOLEAN_FALSE; + if ( eWNI_SME_DISASSOC_IND == type ) + { + result = eCSR_ROAM_RESULT_DISASSOC_IND; + pDisassocIndMsg = (tSirSmeDisassocInd *)pSirMsg; + pSession->roamingStatusCode = pDisassocIndMsg->statusCode; + pSession->joinFailStatusCode.reasonCode = pDisassocIndMsg->reasonCode; + } + else if ( eWNI_SME_DEAUTH_IND == type ) + { + result = eCSR_ROAM_RESULT_DEAUTH_IND; + pDeauthIndMsg = (tSirSmeDeauthInd *)pSirMsg; + pSession->roamingStatusCode = pDeauthIndMsg->statusCode; + /* Convert into proper reason code */ + if ((pDeauthIndMsg->reasonCode == eSIR_BEACON_MISSED) || + (pDeauthIndMsg->reasonCode == + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON)) + pSession->joinFailStatusCode.reasonCode = 0; + else + pSession->joinFailStatusCode.reasonCode = pDeauthIndMsg->reasonCode; + /* + * cfg layer expects 0 as reason code if the driver doesn't know the + * reason code eSIR_BEACON_MISSED is defined as locally + */ + } + else + { + smsLog(pMac, LOGW, FL("gets an unknown type (%d)"), type); + result = eCSR_ROAM_RESULT_NONE; + pSession->joinFailStatusCode.reasonCode = 1; + } + + // call profile lost link routine here + if(!CSR_IS_INFRA_AP(&pSession->connectedProfile)) + { + csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_LOSTLINK_DETECTED, result); + /*Move the state to Idle after disconnection*/ + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId ); + + } + + if ( eWNI_SME_DISASSOC_IND == type ) + { + status = csrSendMBDisassocCnfMsg(pMac, pDisassocIndMsg); + } + else if ( eWNI_SME_DEAUTH_IND == type ) + { + status = csrSendMBDeauthCnfMsg(pMac, pDeauthIndMsg); + } + if(!HAL_STATUS_SUCCESS(status)) + { + //If fail to send confirmation to PE, not to trigger roaming + fToRoam = eANI_BOOLEAN_FALSE; + } + + //prepare to tell HDD to disconnect + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.statusCode = (tSirResultCodes)pSession->roamingStatusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + if( eWNI_SME_DISASSOC_IND == type) + { + //staMacAddr + vos_mem_copy(roamInfo.peerMac, pDisassocIndMsg->peerMacAddr, + sizeof(tSirMacAddr)); + roamInfo.staId = (tANI_U8)pDisassocIndMsg->staId; + roamInfo.reasonCode = pDisassocIndMsg->reasonCode; + } + else if( eWNI_SME_DEAUTH_IND == type ) + { + //staMacAddr + vos_mem_copy(roamInfo.peerMac, pDeauthIndMsg->peerMacAddr, + sizeof(tSirMacAddr)); + roamInfo.staId = (tANI_U8)pDeauthIndMsg->staId; + roamInfo.reasonCode = pDeauthIndMsg->reasonCode; + roamInfo.rxRssi = pDeauthIndMsg->rssi; + } + smsLog(pMac, LOGW, FL("roamInfo.staId (%d)"), roamInfo.staId); + + /* See if we can possibly roam. If so, start the roaming process and notify HDD + that we are roaming. But if we cannot possibly roam, or if we are unable to + currently roam, then notify HDD of the lost link */ + if(fToRoam) + { + //Only remove the connected BSS in infrastructure mode + csrRoamRemoveConnectedBssFromScanCache(pMac, &pSession->connectedProfile); + /* Not to do anything for lost link with WDS */ + if( pMac->roam.configParam.nRoamingTime ) + { + if(HAL_STATUS_SUCCESS(status = csrRoamStartRoaming(pMac, sessionId, + ( eWNI_SME_DEAUTH_IND == type ) ? + eCsrLostlinkRoamingDeauth : eCsrLostlinkRoamingDisassoc))) + { + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + //For IBSS, we need to give some more info to HDD + if(csrIsBssTypeIBSS(pSession->connectedProfile.BSSType)) + { + roamInfo.u.pConnectedProfile = &pSession->connectedProfile; + roamInfo.statusCode = (tSirResultCodes)pSession->roamingStatusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + } + else + { + roamInfo.reasonCode = eCsrRoamReasonSmeIssuedForLostLink; + } + pRoamInfo = &roamInfo; + pSession->roamingReason = ( eWNI_SME_DEAUTH_IND == type ) ? + eCsrLostlinkRoamingDeauth : eCsrLostlinkRoamingDisassoc; + pSession->roamingStartTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_LOSTLINK); + } + else + { + smsLog(pMac, LOGW, " %s Fail to start roaming, status = %d", __func__, status); + fToRoam = eANI_BOOLEAN_FALSE; + } + } + else + { + /* We are told not to roam, indicate lost link */ + fToRoam = eANI_BOOLEAN_FALSE; + } + } + if(!fToRoam) + { + //Tell HDD about the lost link + if(!CSR_IS_INFRA_AP(&pSession->connectedProfile)) + { + /* Don't call csrRoamCallCallback for GO/SoftAp case as this indication + * was already given as part of eWNI_SME_DISASSOC_IND msg handling in + * csrRoamCheckForLinkStatusChange API. + */ + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_LOSTLINK, result); + } + + /*No need to start idle scan in case of IBSS/SAP + Still enable idle scan for polling in case concurrent sessions are running */ + if(CSR_IS_INFRASTRUCTURE(&pSession->connectedProfile)) + { + csrScanStartIdleScan(pMac); + } + } + + return (status); +} + +eHalStatus csrRoamLostLinkAfterhandoffFailure( tpAniSirGlobal pMac,tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + pSession->fCancelRoaming = eANI_BOOLEAN_FALSE; + //Only remove the connected BSS in infrastructure mode + csrRoamRemoveConnectedBssFromScanCache(pMac, &pSession->connectedProfile); + if(pMac->roam.configParam.nRoamingTime) + { + if(HAL_STATUS_SUCCESS(status = csrRoamStartRoaming(pMac,sessionId, pSession->roamingReason))) + { + //before starting the lost link logic release the roam command for handoff + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + } + if(pCommand) + { + if (( eSmeCommandRoam == pCommand->command ) && + ( eCsrSmeIssuedAssocToSimilarAP == pCommand->u.roamCmd.roamReason)) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandRoam( pMac, pCommand ); + } + } + } + smsLog( pMac, LOGW, "Lost link roaming started ..."); + } + } + else + { + /* We are told not to roam, indicate lost link */ + status = eHAL_STATUS_FAILURE; + } + + return (status); +} +void csrRoamWmStatusChangeComplete( tpAniSirGlobal pMac ) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( eSmeCommandWmStatusChange == pCommand->command ) + { + // Nothing to process in a Lost Link completion.... It just kicks off a + // roaming sequence. + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandWmStatusChange( pMac, pCommand ); + } + else + { + smsLog( pMac, LOGE, " ******csrRoamWmStatusChangeComplete fail to release command"); + } + + } + else + { + smsLog( pMac, LOGW, "CSR: WmStatusChange Completion called but LOST LINK command is not ACTIVE ..." ); + } + } + else + { + smsLog( pMac, LOGW, "CSR: WmStatusChange Completion called but NO commands are ACTIVE ..." ); + } + smeProcessPendingQueue( pMac ); +} + +void csrRoamProcessWmStatusChangeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tSirSmeRsp *pSirSmeMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pCommand->sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), pCommand->sessionId); + return; + } + smsLog(pMac, LOG1, FL("session:%d, CmdType : %d"), + pCommand->sessionId, + pCommand->u.wmStatusChangeCmd.Type); + switch ( pCommand->u.wmStatusChangeCmd.Type ) + { + case eCsrDisassociated: + pSirSmeMsg = (tSirSmeRsp *)&pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg; + status = csrRoamLostLink(pMac, pCommand->sessionId, eWNI_SME_DISASSOC_IND, pSirSmeMsg); + break; + case eCsrDeauthenticated: + pSirSmeMsg = (tSirSmeRsp *)&pCommand->u.wmStatusChangeCmd.u.DeauthIndMsg; + status = csrRoamLostLink(pMac, pCommand->sessionId, eWNI_SME_DEAUTH_IND, pSirSmeMsg); + break; + default: + smsLog(pMac, LOGW, FL("gets an unknown command %d"), pCommand->u.wmStatusChangeCmd.Type); + break; + } + //For WDS, we want to stop BSS as well when it is indicated that it is disconnected. + if( CSR_IS_CONN_WDS(&pSession->connectedProfile) ) + { + if( !HAL_STATUS_SUCCESS(csrRoamIssueStopBssCmd( pMac, pCommand->sessionId, eANI_BOOLEAN_TRUE )) ) + { + //This is not good + smsLog(pMac, LOGE, FL(" failed to issue stopBSS command")); + } + } + /* + * Lost Link just triggers a roaming sequence. We can complete the Lost Link + * command here since there is nothing else to do. + */ + csrRoamWmStatusChangeComplete( pMac ); +} + +//This function returns band and mode information. +//The only tricky part is that if phyMode is set to 11abg, this function may return eCSR_CFG_DOT11_MODE_11B +//instead of eCSR_CFG_DOT11_MODE_11G if everything is set to auto-pick. +static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + tANI_U8 operationChn, eCsrBand *pBand ) +{ + eCsrPhyMode phyModeIn = (eCsrPhyMode)pProfile->phyMode; + eCsrCfgDot11Mode cfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(pProfile, phyModeIn, + pMac->roam.configParam.ProprietaryRatesEnabled); + eCsrBand eBand; + //If the global setting for dot11Mode is set to auto/abg, we overwrite the setting in the profile. + if( ((!CSR_IS_INFRA_AP(pProfile )&& !CSR_IS_WDS(pProfile )) && + ((eCSR_CFG_DOT11_MODE_AUTO == pMac->roam.configParam.uCfgDot11Mode) || + (eCSR_CFG_DOT11_MODE_ABG == pMac->roam.configParam.uCfgDot11Mode))) || + (eCSR_CFG_DOT11_MODE_AUTO == cfgDot11Mode) || (eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode) ) + { + switch( pMac->roam.configParam.uCfgDot11Mode ) + { + case eCSR_CFG_DOT11_MODE_11A: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + eBand = eCSR_BAND_5G; + break; + case eCSR_CFG_DOT11_MODE_11B: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + eBand = eCSR_BAND_24; + break; + case eCSR_CFG_DOT11_MODE_11G: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + eBand = eCSR_BAND_24; + break; + case eCSR_CFG_DOT11_MODE_11N: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G; + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_CFG_DOT11_MODE_11AC: + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + /* If the operating channel is in 2.4 GHz band, check for + * INI item to disable VHT operation in 2.4 GHz band + */ + if (CSR_IS_CHANNEL_24GHZ(operationChn) && + !pMac->roam.configParam.enableVhtFor24GHz) + { + /* Disable 11AC operation */ + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; + } + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G; + } + break; + case eCSR_CFG_DOT11_MODE_11AC_ONLY: + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + /* If the operating channel is in 2.4 GHz band, check for + * INI item to disable VHT operation in 2.4 GHz band + */ + if (CSR_IS_CHANNEL_24GHZ(operationChn) && + !pMac->roam.configParam.enableVhtFor24GHz) + { + /* Disable 11AC operation */ + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC_ONLY; + } + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G; + } + else + { + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + break; +#endif + case eCSR_CFG_DOT11_MODE_AUTO: +#ifdef WLAN_FEATURE_11AC + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + /* If the operating channel is in 2.4 GHz band, check for + * INI item to disable VHT operation in 2.4 GHz band + */ + if (CSR_IS_CHANNEL_24GHZ(operationChn) && + !pMac->roam.configParam.enableVhtFor24GHz) + { + /* Disable 11AC operation */ + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; + } + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? + eCSR_BAND_24 : eCSR_BAND_5G; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? + eCSR_BAND_24 : eCSR_BAND_5G; + } +#else + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? + eCSR_BAND_24 : eCSR_BAND_5G; +#endif + break; + default: + // Global dot11 Mode setting is 11a/b/g. + // use the channel number to determine the Mode setting. + if ( eCSR_OPERATING_CHANNEL_AUTO == operationChn ) + { + eBand = pMac->roam.configParam.eBand; + if(eCSR_BAND_24 == eBand) + { + //See reason in else if ( CSR_IS_CHANNEL_24GHZ(operationChn) ) to pick 11B + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + } + else + { + //prefer 5GHz + eBand = eCSR_BAND_5G; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + } + } + else if ( CSR_IS_CHANNEL_24GHZ(operationChn) ) + { + // WiFi tests require IBSS networks to start in 11b mode + // without any change to the default parameter settings + // on the adapter. We use ACU to start an IBSS through + // creation of a startIBSS profile. This startIBSS profile + // has Auto MACProtocol and the adapter property setting + // for dot11Mode is also AUTO. So in this case, let's + // start the IBSS network in 11b mode instead of 11g mode. + // So this is for Auto=profile->MacProtocol && Auto=Global. + // dot11Mode && profile->channel is < 14, then start the IBSS + // in b mode. + // + // Note: we used to have this start as an 11g IBSS for best + // performance... now to specify that the user will have to + // set the do11Mode in the property page to 11g to force it. + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + eBand = eCSR_BAND_24; + } + else + { + // else, it's a 5.0GHz channel. Set mode to 11a. + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + eBand = eCSR_BAND_5G; + } + break; + }//switch + }//if( eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode ) + else + { + //dot11 mode is set, lets pick the band + if ( eCSR_OPERATING_CHANNEL_AUTO == operationChn ) + { + // channel is Auto also. + eBand = pMac->roam.configParam.eBand; + if(eCSR_BAND_ALL == eBand) + { + //prefer 5GHz + eBand = eCSR_BAND_5G; + } + } + else if ( CSR_IS_CHANNEL_24GHZ(operationChn) ) + { + eBand = eCSR_BAND_24; + } + else + { + eBand = eCSR_BAND_5G; + } + } + if(pBand) + { + *pBand = eBand; + } + + if (operationChn == 14){ + smsLog(pMac, LOGE, FL(" Switching to Dot11B mode ")); + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + } + + /* 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))) && + ((eCSR_CFG_DOT11_MODE_11N == cfgDot11Mode) || +#ifdef WLAN_FEATURE_11AC + (eCSR_CFG_DOT11_MODE_11AC == cfgDot11Mode) +#endif + )) { + /* We cannot do 11n here */ + if (CSR_IS_CHANNEL_24GHZ(operationChn)) { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + } else { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + } + } + return( cfgDot11Mode ); +} + +eHalStatus csrRoamIssueStopBss( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate ) +{ + eHalStatus status; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_ibss_pkt_type *pIbssLog; + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + pIbssLog->eventId = WLAN_IBSS_EVENT_STOP_REQ; + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + // Set the roaming substate to 'stop Bss request'... + csrRoamSubstateChange( pMac, NewSubstate, sessionId ); + + // attempt to stop the Bss (reason code is ignored...) + status = csrSendMBStopBssReqMsg( pMac, sessionId ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, FL("csrSendMBStopBssReqMsg failed with status %d"), status); + } + return (status); +} + +//pNumChan is a caller allocated space with the sizeof pChannels +eHalStatus csrGetCfgValidChannels(tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U32 *pNumChan) +{ + + return (ccmCfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + (tANI_U8 *)pChannels, + pNumChan)); +} + +tPowerdBm csrGetCfgMaxTxPower (tpAniSirGlobal pMac, tANI_U8 channel) +{ + tANI_U32 cfgLength = 0; + tANI_U16 cfgId = 0; + tPowerdBm maxTxPwr = 0; + tANI_U8 *pCountryInfo = NULL; + eHalStatus status; + tANI_U8 count = 0; + tANI_U8 firstChannel; + tANI_U8 maxChannels; + + if (CSR_IS_CHANNEL_5GHZ(channel)) + { + cfgId = WNI_CFG_MAX_TX_POWER_5; + cfgLength = WNI_CFG_MAX_TX_POWER_5_LEN; + } + else if (CSR_IS_CHANNEL_24GHZ(channel)) + { + cfgId = WNI_CFG_MAX_TX_POWER_2_4; + cfgLength = WNI_CFG_MAX_TX_POWER_2_4_LEN; + } + else + return maxTxPwr; + + pCountryInfo = vos_mem_malloc(cfgLength); + if ( NULL == pCountryInfo ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (status != eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("%s: failed to allocate memory, status = %d"), + __FUNCTION__, status); + goto error; + } + status = ccmCfgGetStr(pMac, cfgId, (tANI_U8 *)pCountryInfo, &cfgLength); + if (status != eHAL_STATUS_SUCCESS) + { + goto error; + } + /* Identify the channel and max txpower */ + while (count <= (cfgLength - (sizeof(tSirMacChanInfo)))) + { + firstChannel = pCountryInfo[count++]; + maxChannels = pCountryInfo[count++]; + maxTxPwr = pCountryInfo[count++]; + + if ((channel >= firstChannel) && + (channel < (firstChannel + maxChannels))) + { + break; + } + } + +error: + if (NULL != pCountryInfo) + vos_mem_free(pCountryInfo); + + return maxTxPwr; +} + + +tANI_BOOLEAN csrRoamIsChannelValid( tpAniSirGlobal pMac, tANI_U8 channel ) +{ + tANI_BOOLEAN fValid = FALSE; + tANI_U32 idxValidChannels; + tANI_U32 len = sizeof(pMac->roam.validChannelList); + + if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &len))) + { + for ( idxValidChannels = 0; ( idxValidChannels < len ); idxValidChannels++ ) + { + if ( channel == pMac->roam.validChannelList[ idxValidChannels ] ) + { + fValid = TRUE; + break; + } + } + } + pMac->roam.numValidChannels = len; + return fValid; +} + +tANI_BOOLEAN csrRoamIsValid40MhzChannel(tpAniSirGlobal pMac, tANI_U8 channel) +{ + tANI_BOOLEAN fValid = eANI_BOOLEAN_FALSE; + tANI_U8 i; + for(i = 0; i < pMac->scan.base40MHzChannels.numChannels; i++) + { + if(channel == pMac->scan.base40MHzChannels.channelList[i]) + { + fValid = eANI_BOOLEAN_TRUE; + break; + } + } + return (fValid); +} + +//This function check and validate whether the NIC can do CB (40MHz) + static ePhyChanBondState csrGetCBModeFromIes(tpAniSirGlobal pMac, tANI_U8 primaryChn, tDot11fBeaconIEs *pIes) +{ + ePhyChanBondState eRet = PHY_SINGLE_CHANNEL_CENTERED; + tANI_U8 centerChn; + tANI_U32 ChannelBondingMode; + if(CSR_IS_CHANNEL_24GHZ(primaryChn)) + { + /* 'gChannelBondingMode24GHz' configuration item is common for + * SAP and STA mode and currently MDM does not support + * HT40 in 2.4Ghz STA mode. + * So disabling the HT40 in 2.4GHz station mode */ +#ifdef QCA_HT_20_24G_STA_ONLY + ChannelBondingMode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; +#else + ChannelBondingMode = pMac->roam.configParam.channelBondingMode24GHz; +#endif + } + else + { + ChannelBondingMode = pMac->roam.configParam.stacbmode; + } + //Figure what the other side's CB mode + if(WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != ChannelBondingMode) + { + if(pIes->HTCaps.present && (eHT_CHANNEL_WIDTH_40MHZ == + pIes->HTCaps.supportedChannelWidthSet)) + { + /* In Case WPA2 and TKIP is the only one cipher suite in Pairwise */ + if ((pIes->RSN.present && + (pIes->RSN.pwise_cipher_suite_count == 1) && + !memcmp(&(pIes->RSN.pwise_cipher_suites[0][0]), + "\x00\x0f\xac\x02" ,4)) + /* In Case only WPA1 is supported and TKIP is the + * only one cipher suite in Unicast. + */ + ||(!pIes->RSN.present && + (pIes->WPA.present && (pIes->WPA.unicast_cipher_count == 1) + && !memcmp(&(pIes->WPA.unicast_ciphers[0][0]), + "\x00\x50\xf2\x02", 4)))) { + smsLog(pMac, LOGW, " No channel bonding in TKIP mode "); + eRet = PHY_SINGLE_CHANNEL_CENTERED; + } + + else if(pIes->HTInfo.present) + { + /* This is called during INFRA STA/CLIENT and should use the merged value of + * supported channel width and recommended tx width as per standard + */ + smsLog(pMac, LOG1, "scws %u rtws %u sco %u", + pIes->HTCaps.supportedChannelWidthSet, + pIes->HTInfo.recommendedTxWidthSet, + pIes->HTInfo.secondaryChannelOffset); + + if (pIes->HTInfo.recommendedTxWidthSet == eHT_CHANNEL_WIDTH_40MHZ) + eRet = (ePhyChanBondState)pIes->HTInfo.secondaryChannelOffset; + else + eRet = PHY_SINGLE_CHANNEL_CENTERED; + switch (eRet) { + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + centerChn = primaryChn + CSR_CB_CENTER_CHANNEL_OFFSET; + break; + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + centerChn = primaryChn - CSR_CB_CENTER_CHANNEL_OFFSET; + break; + case PHY_SINGLE_CHANNEL_CENTERED: + default: + centerChn = primaryChn; + break; + } + if((PHY_SINGLE_CHANNEL_CENTERED != eRet) && !csrRoamIsValid40MhzChannel(pMac, centerChn)) + { + smsLog(pMac, LOGE, " Invalid center channel (%d), disable 40MHz mode", centerChn); + eRet = PHY_SINGLE_CHANNEL_CENTERED; + } + } + } + } + return eRet; +} +tANI_BOOLEAN csrIsEncryptionInList( tpAniSirGlobal pMac, tCsrEncryptionList *pCipherList, eCsrEncryptionType encryptionType ) +{ + tANI_BOOLEAN fFound = FALSE; + tANI_U32 idx; + for( idx = 0; idx < pCipherList->numEntries; idx++ ) + { + if( pCipherList->encryptionType[idx] == encryptionType ) + { + fFound = TRUE; + break; + } + } + return fFound; +} +tANI_BOOLEAN csrIsAuthInList( tpAniSirGlobal pMac, tCsrAuthList *pAuthList, eCsrAuthType authType ) +{ + tANI_BOOLEAN fFound = FALSE; + tANI_U32 idx; + for( idx = 0; idx < pAuthList->numEntries; idx++ ) + { + if( pAuthList->authType[idx] == authType ) + { + fFound = TRUE; + break; + } + } + return fFound; +} +tANI_BOOLEAN csrIsSameProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile1, tCsrRoamProfile *pProfile2) +{ + tANI_BOOLEAN fCheck = eANI_BOOLEAN_FALSE; + tCsrScanResultFilter *pScanFilter = NULL; + eHalStatus status = eHAL_STATUS_SUCCESS; + + if(pProfile1 && pProfile2) + { + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csrRoamPrepareFilterFromProfile(pMac, pProfile2, pScanFilter); + if(HAL_STATUS_SUCCESS(status)) + { + fCheck = eANI_BOOLEAN_FALSE; + do + { + tANI_U32 i; + for(i = 0; i < pScanFilter->SSIDs.numOfSSIDs; i++) + { + fCheck = csrIsSsidMatch( pMac, pScanFilter->SSIDs.SSIDList[i].SSID.ssId, + pScanFilter->SSIDs.SSIDList[i].SSID.length, + pProfile1->SSID.ssId, pProfile1->SSID.length, eANI_BOOLEAN_FALSE ); + if ( fCheck ) break; + } + if(!fCheck) + { + break; + } + if( !csrIsAuthInList( pMac, &pProfile2->AuthType, pProfile1->AuthType) + || pProfile2->BSSType != pProfile1->BSSType + || !csrIsEncryptionInList( pMac, &pProfile2->EncryptionType, pProfile1->EncryptionType ) + ) + { + fCheck = eANI_BOOLEAN_FALSE; + break; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pProfile1->MDID.mdiePresent || pProfile2->MDID.mdiePresent) + { + if (pProfile1->MDID.mobilityDomain != pProfile2->MDID.mobilityDomain) + { + fCheck = eANI_BOOLEAN_FALSE; + break; + } + } +#endif + //Match found + fCheck = eANI_BOOLEAN_TRUE; + }while(0); + csrFreeScanFilter(pMac, pScanFilter); + } + vos_mem_free(pScanFilter); + } + } + + return (fCheck); +} + +tANI_BOOLEAN csrRoamIsSameProfileKeys(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pConnProfile, tCsrRoamProfile *pProfile2) +{ + tANI_BOOLEAN fCheck = eANI_BOOLEAN_FALSE; + int i; + do + { + //Only check for static WEP + if(!csrIsEncryptionInList(pMac, &pProfile2->EncryptionType, eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) && + !csrIsEncryptionInList(pMac, &pProfile2->EncryptionType, eCSR_ENCRYPT_TYPE_WEP104_STATICKEY)) + { + fCheck = eANI_BOOLEAN_TRUE; + break; + } + if(!csrIsEncryptionInList(pMac, &pProfile2->EncryptionType, pConnProfile->EncryptionType)) break; + if(pConnProfile->Keys.defaultIndex != pProfile2->Keys.defaultIndex) break; + for(i = 0; i < CSR_MAX_NUM_KEY; i++) + { + if(pConnProfile->Keys.KeyLength[i] != pProfile2->Keys.KeyLength[i]) break; + if (!vos_mem_compare(&pConnProfile->Keys.KeyMaterial[i], + &pProfile2->Keys.KeyMaterial[i], pProfile2->Keys.KeyLength[i])) + { + break; + } + } + if( i == CSR_MAX_NUM_KEY) + { + fCheck = eANI_BOOLEAN_TRUE; + } + }while(0); + return (fCheck); +} + +//IBSS + +tANI_U8 csrRoamGetIbssStartChannelNumber50( tpAniSirGlobal pMac ) +{ + tANI_U8 channel = 0; + tANI_U32 idx; + tANI_U32 idxValidChannels; + tANI_BOOLEAN fFound = FALSE; + tANI_U32 len = sizeof(pMac->roam.validChannelList); + + if(eCSR_OPERATING_CHANNEL_ANY != pMac->roam.configParam.AdHocChannel5G) + { + channel = pMac->roam.configParam.AdHocChannel5G; + if(!csrRoamIsChannelValid(pMac, channel)) + { + channel = 0; + } + } + if (0 == channel && HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len))) + { + for ( idx = 0; ( idx < CSR_NUM_IBSS_START_CHANNELS_50 ) && !fFound; idx++ ) + { + for ( idxValidChannels = 0; ( idxValidChannels < len ) && !fFound; idxValidChannels++ ) + { + if ( csrStartIbssChannels50[ idx ] == pMac->roam.validChannelList[ idxValidChannels ] ) + { + fFound = TRUE; + channel = csrStartIbssChannels50[ idx ]; + } + } + } + // this is rare, but if it does happen, we find anyone in 11a bandwidth and return the first 11a channel found! + if (!fFound) + { + for ( idxValidChannels = 0; idxValidChannels < len ; idxValidChannels++ ) + { + if ( CSR_IS_CHANNEL_5GHZ(pMac->roam.validChannelList[ idxValidChannels ]) ) // the max channel# in 11g is 14 + { + if (idxValidChannels < CSR_NUM_IBSS_START_CHANNELS_50) + { + channel = pMac->roam.validChannelList[idxValidChannels]; + } + break; + } + } + } + }//if + + return( channel ); +} + +tANI_U8 csrRoamGetIbssStartChannelNumber24( tpAniSirGlobal pMac ) +{ + tANI_U8 channel = 1; + tANI_U32 idx; + tANI_U32 idxValidChannels; + tANI_BOOLEAN fFound = FALSE; + tANI_U32 len = sizeof(pMac->roam.validChannelList); + + if(eCSR_OPERATING_CHANNEL_ANY != pMac->roam.configParam.AdHocChannel24) + { + channel = pMac->roam.configParam.AdHocChannel24; + if(!csrRoamIsChannelValid(pMac, channel)) + { + channel = 0; + } + } + + if (0 == channel && HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len))) + { + for ( idx = 0; ( idx < CSR_NUM_IBSS_START_CHANNELS_24 ) && !fFound; idx++ ) + { + for ( idxValidChannels = 0; ( idxValidChannels < len ) && !fFound; idxValidChannels++ ) + { + if ( csrStartIbssChannels24[ idx ] == pMac->roam.validChannelList[ idxValidChannels ] ) + { + fFound = TRUE; + channel = csrStartIbssChannels24[ idx ]; + } + } + } + } + + return( channel ); +} + +static void csrRoamGetBssStartParms( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + tCsrRoamStartBssParams *pParam ) +{ + eCsrBand eBand; + tANI_U8 channel = 0; + tSirNwType nwType; + tANI_U8 operationChannel = 0; + + if(pProfile->ChannelInfo.numOfChannels && pProfile->ChannelInfo.ChannelList) + { + operationChannel = pProfile->ChannelInfo.ChannelList[0]; + } + + pParam->uCfgDot11Mode = + csrRoamGetPhyModeBandForBss( pMac, pProfile, operationChannel, &eBand ); + + if( ( (pProfile->csrPersona == VOS_P2P_CLIENT_MODE) || + (pProfile->csrPersona == VOS_P2P_GO_MODE) ) + && ( pParam->uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11B) + ) + { + /* This should never happen */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + FL("For P2PClient/P2P-GO (persona %d) cfgDot11Mode is 11B"), + pProfile->csrPersona); + VOS_ASSERT(0); + } + + switch( pParam->uCfgDot11Mode ) + { + case eCSR_CFG_DOT11_MODE_11G: + nwType = eSIR_11G_NW_TYPE; + break; + case eCSR_CFG_DOT11_MODE_11B: + nwType = eSIR_11B_NW_TYPE; + break; + case eCSR_CFG_DOT11_MODE_11A: + nwType = eSIR_11A_NW_TYPE; + break; + default: + case eCSR_CFG_DOT11_MODE_11N: + /* Because LIM only verifies it against 11a, 11b or 11g, + set only 11g or 11a here */ + if (eCSR_BAND_24 == eBand) { + nwType = eSIR_11G_NW_TYPE; + } else { + nwType = eSIR_11A_NW_TYPE; + } + break; + } + + pParam->extendedRateSet.numRates = 0; + + switch ( nwType ) + { + default: + smsLog(pMac, LOGE, FL("sees an unknown pSirNwType (%d)"), nwType); + case eSIR_11A_NW_TYPE: + + pParam->operationalRateSet.numRates = 8; + + pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_6 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_9; + pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_12 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_18; + pParam->operationalRateSet.rate[4] = SIR_MAC_RATE_24 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[5] = SIR_MAC_RATE_36; + pParam->operationalRateSet.rate[6] = SIR_MAC_RATE_48; + pParam->operationalRateSet.rate[7] = SIR_MAC_RATE_54; + + if ( eCSR_OPERATING_CHANNEL_ANY == operationChannel ) + { + channel = csrRoamGetIbssStartChannelNumber50( pMac ); + if( 0 == channel && + CSR_IS_PHY_MODE_DUAL_BAND(pProfile->phyMode) && + CSR_IS_PHY_MODE_DUAL_BAND(pMac->roam.configParam.phyMode) + ) + { + //We could not find a 5G channel by auto pick, let's try 2.4G channels + //We only do this here because csrRoamGetPhyModeBandForBss always picks 11a for AUTO + nwType = eSIR_11B_NW_TYPE; + channel = csrRoamGetIbssStartChannelNumber24( pMac ); + pParam->operationalRateSet.numRates = 4; + pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_1 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_2 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_5_5 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_11 | CSR_DOT11_BASIC_RATE_MASK; + } + } + else + { + channel = operationChannel; + } + break; + + case eSIR_11B_NW_TYPE: + pParam->operationalRateSet.numRates = 4; + pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_1 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_2 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_5_5 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_11 | CSR_DOT11_BASIC_RATE_MASK; + if ( eCSR_OPERATING_CHANNEL_ANY == operationChannel ) + { + channel = csrRoamGetIbssStartChannelNumber24( pMac ); + } + else + { + channel = operationChannel; + } + + break; + case eSIR_11G_NW_TYPE: + /* For P2P Client and P2P GO, disable 11b rates */ + if( (pProfile->csrPersona == VOS_P2P_CLIENT_MODE) || + (pProfile->csrPersona == VOS_P2P_GO_MODE) || + (eCSR_CFG_DOT11_MODE_11G_ONLY == pParam->uCfgDot11Mode) + ) + { + pParam->operationalRateSet.numRates = 8; + + pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_6 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_9; + pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_12 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_18; + pParam->operationalRateSet.rate[4] = SIR_MAC_RATE_24 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[5] = SIR_MAC_RATE_36; + pParam->operationalRateSet.rate[6] = SIR_MAC_RATE_48; + pParam->operationalRateSet.rate[7] = SIR_MAC_RATE_54; + } + else + { + pParam->operationalRateSet.numRates = 4; + pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_1 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_2 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_5_5 | CSR_DOT11_BASIC_RATE_MASK; + pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_11 | CSR_DOT11_BASIC_RATE_MASK; + + pParam->extendedRateSet.numRates = 8; + pParam->extendedRateSet.rate[0] = SIR_MAC_RATE_6; + pParam->extendedRateSet.rate[1] = SIR_MAC_RATE_9; + pParam->extendedRateSet.rate[2] = SIR_MAC_RATE_12; + pParam->extendedRateSet.rate[3] = SIR_MAC_RATE_18; + pParam->extendedRateSet.rate[4] = SIR_MAC_RATE_24; + pParam->extendedRateSet.rate[5] = SIR_MAC_RATE_36; + pParam->extendedRateSet.rate[6] = SIR_MAC_RATE_48; + pParam->extendedRateSet.rate[7] = SIR_MAC_RATE_54; + } + + if ( eCSR_OPERATING_CHANNEL_ANY == operationChannel ) + { + channel = csrRoamGetIbssStartChannelNumber24( pMac ); + } + else + { + channel = operationChannel; + } + + break; + } + pParam->operationChn = channel; + pParam->sirNwType = nwType; + pParam->vht_channel_width = pProfile->vht_channel_width; +} + +static void csrRoamGetBssStartParmsFromBssDesc( tpAniSirGlobal pMac, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes, tCsrRoamStartBssParams *pParam ) +{ + + if( pParam ) + { + pParam->sirNwType = pBssDesc->nwType; + pParam->cbMode = PHY_SINGLE_CHANNEL_CENTERED; + pParam->operationChn = pBssDesc->channelId; + vos_mem_copy(&pParam->bssid, pBssDesc->bssId, sizeof(tCsrBssid)); + + if( pIes ) + { + if(pIes->SuppRates.present) + { + pParam->operationalRateSet.numRates = pIes->SuppRates.num_rates; + if(pIes->SuppRates.num_rates > SIR_MAC_RATESET_EID_MAX) + { + smsLog(pMac, LOGE, FL("num_rates :%d is more than SIR_MAC_RATESET_EID_MAX, resetting to SIR_MAC_RATESET_EID_MAX"), + pIes->SuppRates.num_rates); + pIes->SuppRates.num_rates = SIR_MAC_RATESET_EID_MAX; + } + vos_mem_copy(pParam->operationalRateSet.rate, pIes->SuppRates.rates, + sizeof(*pIes->SuppRates.rates) * pIes->SuppRates.num_rates); + } + if (pIes->ExtSuppRates.present) + { + pParam->extendedRateSet.numRates = pIes->ExtSuppRates.num_rates; + if(pIes->ExtSuppRates.num_rates > SIR_MAC_RATESET_EID_MAX) + { + smsLog(pMac, LOGE, + FL("num_rates :%d is more than SIR_MAC_RATESET_EID_MAX, resetting to SIR_MAC_RATESET_EID_MAX"), + pIes->ExtSuppRates.num_rates); + pIes->ExtSuppRates.num_rates = SIR_MAC_RATESET_EID_MAX; + } + vos_mem_copy(pParam->extendedRateSet.rate, + pIes->ExtSuppRates.rates, + sizeof(*pIes->ExtSuppRates.rates) * pIes->ExtSuppRates.num_rates); + } + if( pIes->SSID.present ) + { + pParam->ssId.length = pIes->SSID.num_ssid; + vos_mem_copy(pParam->ssId.ssId, pIes->SSID.ssid, + pParam->ssId.length); + } + pParam->cbMode = csrGetCBModeFromIes(pMac, pParam->operationChn, pIes); + } + else + { + pParam->ssId.length = 0; + pParam->operationalRateSet.numRates = 0; + } + } +} + +static void csrRoamDetermineMaxRateForAdHoc( tpAniSirGlobal pMac, tSirMacRateSet *pSirRateSet ) +{ + tANI_U8 MaxRate = 0; + tANI_U32 i; + tANI_U8 *pRate; + + pRate = pSirRateSet->rate; + for ( i = 0; i < pSirRateSet->numRates; i++ ) + { + MaxRate = CSR_MAX( MaxRate, ( pRate[ i ] & (~CSR_DOT11_BASIC_RATE_MASK) ) ); + } + + // Save the max rate in the connected state information... + + // modify LastRates variable as well + + return; +} + +eHalStatus csrRoamIssueStartBss( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamStartBssParams *pParam, + tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc, tANI_U32 roamId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + eCsrBand eBand; + // Set the roaming substate to 'Start BSS attempt'... + csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_START_BSS_REQ, sessionId ); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + //Need to figure out whether we need to log WDS??? + if( CSR_IS_IBSS( pProfile ) ) + { + vos_log_ibss_pkt_type *pIbssLog; + WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if(pIbssLog) + { + if(pBssDesc) + { + pIbssLog->eventId = WLAN_IBSS_EVENT_JOIN_IBSS_REQ; + vos_mem_copy(pIbssLog->bssid, pBssDesc->bssId, 6); + } + else + { + pIbssLog->eventId = WLAN_IBSS_EVENT_START_IBSS_REQ; + } + vos_mem_copy(pIbssLog->ssid, pParam->ssId.ssId, pParam->ssId.length); + if(pProfile->ChannelInfo.numOfChannels == 0) + { + pIbssLog->channelSetting = AUTO_PICK; + } + else + { + pIbssLog->channelSetting = SPECIFIED; + } + pIbssLog->operatingChannel = pParam->operationChn; + WLAN_VOS_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR + //Put RSN information in for Starting BSS + pParam->nRSNIELength = (tANI_U16)pProfile->nRSNReqIELength; + pParam->pRSNIE = pProfile->pRSNReqIE; + + pParam->privacy = pProfile->privacy; + pParam->fwdWPSPBCProbeReq = pProfile->fwdWPSPBCProbeReq; + pParam->authType = pProfile->csr80211AuthType; + pParam->beaconInterval = pProfile->beaconInterval; + pParam->dtimPeriod = pProfile->dtimPeriod; + pParam->ApUapsdEnable = pProfile->ApUapsdEnable; + pParam->ssidHidden = pProfile->SSIDs.SSIDList[0].ssidHidden; + if (CSR_IS_INFRA_AP(pProfile)&& (pParam->operationChn != 0)) + { + if (csrIsValidChannel(pMac, pParam->operationChn) != VOS_STATUS_SUCCESS) + { + pParam->operationChn = INFRA_AP_DEFAULT_CHANNEL; + } + } + pParam->protEnabled = pProfile->protEnabled; + pParam->obssProtEnabled = pProfile->obssProtEnabled; + pParam->ht_protection = pProfile->cfg_protection; + pParam->wps_state = pProfile->wps_state; + + pParam->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, pProfile, pParam->operationChn /* pProfile->operationChannel*/, + &eBand); + pParam->bssPersona = pProfile->csrPersona; + +#ifdef WLAN_FEATURE_11W + pParam->mfpCapable = (0 != pProfile->MFPCapable); + pParam->mfpRequired = (0 != pProfile->MFPRequired); +#endif + + pParam->addIeParams.probeRespDataLen = + pProfile->addIeParams.probeRespDataLen; + pParam->addIeParams.probeRespData_buff = + pProfile->addIeParams.probeRespData_buff; + + pParam->addIeParams.assocRespDataLen = + pProfile->addIeParams.assocRespDataLen; + pParam->addIeParams.assocRespData_buff = + pProfile->addIeParams.assocRespData_buff; + + if (CSR_IS_IBSS( pProfile )) + { + pParam->addIeParams.probeRespBCNDataLen = + pProfile->nWPAReqIELength; + pParam->addIeParams.probeRespBCNData_buff = + pProfile->pWPAReqIE; + } + else + { + pParam->addIeParams.probeRespBCNDataLen = + pProfile->addIeParams.probeRespBCNDataLen; + pParam->addIeParams.probeRespBCNData_buff = + pProfile->addIeParams.probeRespBCNData_buff; + } + pParam->sap_dot11mc = pProfile->sap_dot11mc; + // When starting an IBSS, start on the channel from the Profile. + status = csrSendMBStartBssReqMsg( pMac, sessionId, pProfile->BSSType, pParam, pBssDesc ); + return (status); +} + +static void csrRoamPrepareBssParams(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig, tDot11fBeaconIEs *pIes) +{ + tANI_U8 Channel; + ePhyChanBondState cbMode = PHY_SINGLE_CHANNEL_CENTERED; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if( pBssDesc ) + { + csrRoamGetBssStartParmsFromBssDesc( pMac, pBssDesc, pIes, &pSession->bssParams ); + //Since csrRoamGetBssStartParmsFromBssDesc fills in the bssid for pSession->bssParams + //The following code has to be do after that. + //For WDS station, use selfMac as the self BSSID + if( CSR_IS_WDS_STA( pProfile ) ) + { + vos_mem_copy(&pSession->bssParams.bssid, &pSession->selfMacAddr, + sizeof(tCsrBssid)); + } + } + else + { + csrRoamGetBssStartParms(pMac, pProfile, &pSession->bssParams); + //Use the first SSID + if(pProfile->SSIDs.numOfSSIDs) + { + vos_mem_copy(&pSession->bssParams.ssId, pProfile->SSIDs.SSIDList, + sizeof(tSirMacSSid)); + } + //For WDS station, use selfMac as the self BSSID + if( CSR_IS_WDS_STA( pProfile ) ) + { + vos_mem_copy(&pSession->bssParams.bssid, &pSession->selfMacAddr, + sizeof(tCsrBssid)); + } + //Use the first BSSID + else if( pProfile->BSSIDs.numOfBSSIDs ) + { + vos_mem_copy(&pSession->bssParams.bssid, pProfile->BSSIDs.bssid, + sizeof(tCsrBssid)); + } + else + { + vos_mem_set(&pSession->bssParams.bssid, sizeof(tCsrBssid), 0); + } + } + Channel = pSession->bssParams.operationChn; + //Set operating channel in pProfile which will be used + //in csrRoamSetBssConfigCfg() to determine channel bonding + //mode and will be configured in CFG later + pProfile->operationChannel = Channel; + + if(Channel == 0) + { + smsLog(pMac, LOGE, " CSR cannot find a channel to start IBSS"); + } + else + { + + csrRoamDetermineMaxRateForAdHoc( pMac, &pSession->bssParams.operationalRateSet ); + if (CSR_IS_INFRA_AP(pProfile) || CSR_IS_START_IBSS( pProfile ) ) + { + if(CSR_IS_CHANNEL_24GHZ(Channel) ) + { + cbMode = pMac->roam.configParam.channelBondingMode24GHz; + } + else + { + cbMode = pMac->roam.configParam.channelBondingMode5GHz; + } + smsLog(pMac, LOG1, "## cbMode %d", cbMode); + pBssConfig->cbMode = cbMode; + pSession->bssParams.cbMode = cbMode; + } + } +} + +static eHalStatus csrRoamStartIbss( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tANI_BOOLEAN *pfSameIbss ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fSameIbss = FALSE; + + if ( csrIsConnStateIbss( pMac, sessionId ) ) + { + // Check if any profile parameter has changed ? If any profile parameter + // has changed then stop old BSS and start a new one with new parameters + if ( csrIsSameProfile( pMac, &pMac->roam.roamSession[sessionId].connectedProfile, pProfile ) ) + { + fSameIbss = TRUE; + } + else + { + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING ); + } + } + else if ( csrIsConnStateConnectedInfra( pMac, sessionId ) ) + { + // Disassociate from the connected Infrastructure network... + status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE ); + } + else + { + tBssConfigParam *pBssConfig; + + pBssConfig = vos_mem_malloc(sizeof(tBssConfigParam)); + if ( NULL == pBssConfig ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pBssConfig, sizeof(tBssConfigParam), 0); + // there is no Bss description before we start an IBSS so we need to adopt + // all Bss configuration parameters from the Profile. + status = csrRoamPrepareBssConfigFromProfile(pMac, pProfile, pBssConfig, NULL); + if(HAL_STATUS_SUCCESS(status)) + { + //save dotMode + pMac->roam.roamSession[sessionId].bssParams.uCfgDot11Mode = pBssConfig->uCfgDot11Mode; + //Prepare some more parameters for this IBSS + csrRoamPrepareBssParams(pMac, sessionId, pProfile, NULL, pBssConfig, NULL); + status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, + NULL, pBssConfig, + NULL, eANI_BOOLEAN_FALSE); + } + + vos_mem_free(pBssConfig); + }//Allocate memory + } + + if(pfSameIbss) + { + *pfSameIbss = fSameIbss; + } + return( status ); +} + +static void csrRoamUpdateConnectedProfileFromNewBss( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirSmeNewBssInfo *pNewBss ) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if( pNewBss ) + { + // Set the operating channel. + pSession->connectedProfile.operationChannel = pNewBss->channelNumber; + // move the BSSId from the BSS description into the connected state information. + vos_mem_copy(&pSession->connectedProfile.bssid, &(pNewBss->bssId), + sizeof( tCsrBssid )); + } + return; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus csrRoamSetPSK_PMK(tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_U8 *pPSK_PMK, size_t pmk_len) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + smsLog(pMac, LOGE, FL("session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(pSession->psk_pmk, pPSK_PMK, sizeof(pSession->psk_pmk)); + pSession->pmk_len = pmk_len; + return eHAL_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ +eHalStatus csrRoamSetPMKIDCache( tpAniSirGlobal pMac, tANI_U32 sessionId, + tPmkidCacheInfo *pPMKIDCache, + tANI_U32 numItems, + tANI_BOOLEAN update_entire_cache ) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, "csrRoamSetPMKIDCache called, numItems = %d", numItems); + + if (numItems <= CSR_MAX_PMKID_ALLOWED) + { +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type); + vos_mem_set(&secEvent, + sizeof(vos_event_wlan_security_payload_type), 0); + secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_UPDATE; + secEvent.encryptionModeMulticast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + secEvent.encryptionModeUnicast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + vos_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid, 6); + secEvent.authMode = + (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + WLAN_VOS_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY); + } +#endif//FEATURE_WLAN_DIAG_SUPPORT_CSR + + status = eHAL_STATUS_SUCCESS; + if (update_entire_cache) { + if (numItems && pPMKIDCache) + { + pSession->NumPmkidCache = (uint16_t)numItems; + vos_mem_copy(pSession->PmkidCacheInfo, pPMKIDCache, + sizeof(tPmkidCacheInfo) * numItems); + pSession->curr_cache_idx = (uint16_t)numItems; + } + } else { + tANI_U32 i = 0; + tPmkidCacheInfo *pmksa; + + for (i = 0; i < numItems; i++) { + pmksa = &pPMKIDCache[i]; + + /* Delete the entry if present */ + csrRoamDelPMKIDfromCache(pMac,sessionId,pmksa->BSSID,FALSE); + + /* Add entry to the cache */ + vos_mem_copy( + pSession->PmkidCacheInfo[pSession->curr_cache_idx].BSSID, + pmksa->BSSID, ETHER_ADDR_LEN); + vos_mem_copy( + pSession->PmkidCacheInfo[pSession->curr_cache_idx].PMKID, + pmksa->PMKID, CSR_RSN_PMKID_SIZE); + + /* Increment the CSR local cache index */ + if (pSession->curr_cache_idx < (CSR_MAX_PMKID_ALLOWED - 1)) + pSession->curr_cache_idx++; + else + pSession->curr_cache_idx = 0; + + pSession->NumPmkidCache++; + if (pSession->NumPmkidCache > CSR_MAX_PMKID_ALLOWED) + pSession->NumPmkidCache = CSR_MAX_PMKID_ALLOWED; + } + } + } + return (status); +} + +eHalStatus csrRoamDelPMKIDfromCache( tpAniSirGlobal pMac, tANI_U32 sessionId, + const tANI_U8 *pBSSId, + tANI_BOOLEAN flush_cache ) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tANI_BOOLEAN fMatchFound = FALSE; + tANI_U32 Index; + uint32_t curr_idx; + uint32_t i; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + /* Check if there are no entries to delete */ + if (0 == pSession->NumPmkidCache) { + smsLog(pMac, LOG1, FL("No entries to delete/Flush")); + return eHAL_STATUS_SUCCESS; + } + + if (!flush_cache) { + for (Index = 0; Index < CSR_MAX_PMKID_ALLOWED; Index++) { + if (vos_mem_compare(pSession->PmkidCacheInfo[Index].BSSID, + pBSSId, VOS_MAC_ADDR_SIZE)) { + fMatchFound = 1; + + /* Clear this - the matched entry */ + vos_mem_zero(&pSession->PmkidCacheInfo[Index], + sizeof(tPmkidCacheInfo)); + + break; + } + } + + if (Index == CSR_MAX_PMKID_ALLOWED && !fMatchFound) { + smsLog(pMac, LOG1, FL("No such PMKSA entry exists "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pBSSId)); + } + else { + /* Match Found */ + curr_idx = pSession->curr_cache_idx; + if (Index < curr_idx) { + for (i = Index; i < (curr_idx - 1); i++) { + vos_mem_copy(&pSession->PmkidCacheInfo[i], + &pSession->PmkidCacheInfo[i+1], + sizeof(tPmkidCacheInfo)); + } + + pSession->curr_cache_idx--; + vos_mem_zero( + &pSession->PmkidCacheInfo[pSession->curr_cache_idx], + sizeof(tPmkidCacheInfo)); + } else if(Index > curr_idx) { + for (i = Index; i > (curr_idx); i--) { + vos_mem_copy(&pSession->PmkidCacheInfo[i], + &pSession->PmkidCacheInfo[i-1], + sizeof(tPmkidCacheInfo)); + } + vos_mem_zero( + &pSession->PmkidCacheInfo[pSession->curr_cache_idx], + sizeof(tPmkidCacheInfo)); + } + pSession->NumPmkidCache--; + } + } else { + /* Flush the entire cache */ + vos_mem_zero(pSession->PmkidCacheInfo, + sizeof(tPmkidCacheInfo) * CSR_MAX_PMKID_ALLOWED); + pSession->NumPmkidCache = 0; + pSession->curr_cache_idx = 0; + } + + return eHAL_STATUS_SUCCESS; +} + +tANI_U32 csrRoamGetNumPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + return (pMac->roam.roamSession[sessionId].NumPmkidCache); +} + +eHalStatus csrRoamGetPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pNum, tPmkidCacheInfo *pPmkidCache) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tPmkidCacheInfo *pmksa; + uint16_t i, j; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pNum && pPmkidCache) + { + if(pSession->NumPmkidCache == 0) + { + *pNum = 0; + status = eHAL_STATUS_SUCCESS; + } + else if(*pNum >= pSession->NumPmkidCache) + { + if(pSession->NumPmkidCache > CSR_MAX_PMKID_ALLOWED) + { + smsLog(pMac, LOGE, + FL("NumPmkidCache :%d is more than CSR_MAX_PMKID_ALLOWED, resetting to CSR_MAX_PMKID_ALLOWED"), + pSession->NumPmkidCache); + pSession->NumPmkidCache = CSR_MAX_PMKID_ALLOWED; + } + + for (i = 0,j = 0; + (j < pSession->NumPmkidCache) && (i < CSR_MAX_PMKID_ALLOWED); + i++) { + /* Fill the valid entries */ + pmksa = &pSession->PmkidCacheInfo[i]; + if (!csrIsMacAddressZero(pMac, &pmksa->BSSID)) { + vos_mem_copy(pPmkidCache, pmksa, + sizeof(tPmkidCacheInfo)); + pPmkidCache++; + j++; + } + } + + *pNum = pSession->NumPmkidCache; + status = eHAL_STATUS_SUCCESS; + } + } + return (status); +} + +eHalStatus csrRoamGetWpaRsnReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tANI_U32 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pLen) + { + len = *pLen; + *pLen = pSession->nWpaRsnReqIeLength; + if(pBuf) + { + if(len >= pSession->nWpaRsnReqIeLength) + { + vos_mem_copy(pBuf, pSession->pWpaRsnReqIE, + pSession->nWpaRsnReqIeLength); + status = eHAL_STATUS_SUCCESS; + } + } + } + return (status); +} + +eHalStatus csrRoamGetWpaRsnRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tANI_U32 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pLen) + { + len = *pLen; + *pLen = pSession->nWpaRsnRspIeLength; + if(pBuf) + { + if(len >= pSession->nWpaRsnRspIeLength) + { + vos_mem_copy(pBuf, pSession->pWpaRsnRspIE, + pSession->nWpaRsnRspIeLength); + status = eHAL_STATUS_SUCCESS; + } + } + } + return (status); +} +#ifdef FEATURE_WLAN_WAPI +eHalStatus csrRoamGetWapiReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tANI_U32 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pLen) + { + len = *pLen; + *pLen = pSession->nWapiReqIeLength; + if(pBuf) + { + if(len >= pSession->nWapiReqIeLength) + { + vos_mem_copy(pBuf, pSession->pWapiReqIE, + pSession->nWapiReqIeLength); + status = eHAL_STATUS_SUCCESS; + } + } + } + return (status); +} +eHalStatus csrRoamGetWapiRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tANI_U32 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if(pLen) + { + len = *pLen; + *pLen = pSession->nWapiRspIeLength; + if(pBuf) + { + if(len >= pSession->nWapiRspIeLength) + { + vos_mem_copy(pBuf, pSession->pWapiRspIE, + pSession->nWapiRspIeLength); + status = eHAL_STATUS_SUCCESS; + } + } + } + return (status); +} +#endif /* FEATURE_WLAN_WAPI */ +eRoamCmdStatus csrGetRoamCompleteStatus(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eRoamCmdStatus retStatus = eCSR_ROAM_CONNECT_COMPLETION; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return (retStatus); + } + + if(CSR_IS_ROAMING(pSession)) + { + retStatus = eCSR_ROAM_ROAMING_COMPLETION; + pSession->fRoaming = eANI_BOOLEAN_FALSE; + } + return (retStatus); +} + +/* This function remove the connected BSS from the cached scan result */ +eHalStatus csrRoamRemoveConnectedBssFromScanCache(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pConnProfile) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrScanResultFilter *pScanFilter = NULL; + tListElem *pEntry; + tCsrScanResult *pResult; + tDot11fBeaconIEs *pIes; + tANI_BOOLEAN fMatch; + if(!(csrIsMacAddressZero(pMac, &pConnProfile->bssid) || + csrIsMacAddressBroadcast(pMac, &pConnProfile->bssid))) + { + do + { + //Prepare the filter. Only fill in the necessary fields. Not all fields are needed + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + pScanFilter->BSSIDs.bssid = vos_mem_malloc(sizeof(tCsrBssid)); + if ( NULL == pScanFilter->BSSIDs.bssid ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + vos_mem_copy(pScanFilter->BSSIDs.bssid, &pConnProfile->bssid, + sizeof(tCsrBssid)); + pScanFilter->BSSIDs.numOfBSSIDs = 1; + if(!csrIsNULLSSID(pConnProfile->SSID.ssId, pConnProfile->SSID.length)) + { + pScanFilter->SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if ( NULL == pScanFilter->SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) break; + vos_mem_copy(&pScanFilter->SSIDs.SSIDList[0].SSID, + &pConnProfile->SSID, sizeof(tSirMacSSid)); + } + pScanFilter->authType.numEntries = 1; + pScanFilter->authType.authType[0] = pConnProfile->AuthType; + pScanFilter->BSSType = pConnProfile->BSSType; + pScanFilter->EncryptionType.numEntries = 1; + pScanFilter->EncryptionType.encryptionType[0] = pConnProfile->EncryptionType; + pScanFilter->mcEncryptionType.numEntries = 1; + pScanFilter->mcEncryptionType.encryptionType[0] = pConnProfile->mcEncryptionType; + //We ignore the channel for now, BSSID should be enough + pScanFilter->ChannelInfo.numOfChannels = 0; + //Also ignore the following fields + pScanFilter->uapsd_mask = 0; + pScanFilter->bWPSAssociation = eANI_BOOLEAN_FALSE; + pScanFilter->bOSENAssociation = eANI_BOOLEAN_FALSE; + pScanFilter->countryCode[0] = 0; + pScanFilter->phyMode = eCSR_DOT11_MODE_AUTO; + csrLLLock(&pMac->scan.scanResultList); + pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK ); + while( pEntry ) + { + pResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + pIes = (tDot11fBeaconIEs *)( pResult->Result.pvIes ); + fMatch = csrMatchBSS(pMac, &pResult->Result.BssDescriptor, + pScanFilter, NULL, NULL, NULL, &pIes); + //Release the IEs allocated by csrMatchBSS is needed + if( !pResult->Result.pvIes ) + { + //need to free the IEs since it is allocated by csrMatchBSS + vos_mem_free(pIes); + } + if(fMatch) + { + //We found the one + if( csrLLRemoveEntry(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK) ) + { + //Free the memory + csrFreeScanResultEntry( pMac, pResult ); + } + break; + } + pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); + }//while + csrLLUnlock(&pMac->scan.scanResultList); + }while(0); + if(pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + } + return (status); +} + +//BT-AMP +eHalStatus csrIsBTAMPAllowed( tpAniSirGlobal pMac, tANI_U32 chnId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 sessionId; + for( sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + if( csrIsConnStateIbss( pMac, sessionId ) || csrIsBTAMP( pMac, sessionId ) ) + { + //co-exist with IBSS or BT-AMP is not supported + smsLog( pMac, LOGW, " BTAMP is not allowed due to IBSS/BT-AMP exist in session %d", sessionId ); + status = eHAL_STATUS_CSR_WRONG_STATE; + break; + } + if( csrIsConnStateInfra( pMac, sessionId ) ) + { + if( chnId && + ( (tANI_U8)chnId != pMac->roam.roamSession[sessionId].connectedProfile.operationChannel ) ) + { + smsLog( pMac, LOGW, " BTAMP is not allowed due to channel (%d) diff than infr channel (%d)", + chnId, pMac->roam.roamSession[sessionId].connectedProfile.operationChannel ); + status = eHAL_STATUS_CSR_WRONG_STATE; + break; + } + } + } + } + return ( status ); +} + +static eHalStatus csrRoamStartWds( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tBssConfigParam bssConfig; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if ( csrIsConnStateIbss( pMac, sessionId ) ) + { + status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING ); + } + else if ( csrIsConnStateConnectedInfra( pMac, sessionId ) ) + { + // Disassociate from the connected Infrastructure network... + status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE ); + } + else + { + //We don't expect Bt-AMP HDD not to disconnect the last connection first at this time. + //Otherwise we need to add code to handle the + //situation just like IBSS. Though for WDS station, we need to send disassoc to PE first then + //send stop_bss to PE, before we can continue. + + if (csrIsConnStateWds( pMac, sessionId )) + { + VOS_ASSERT(0); + return eHAL_STATUS_FAILURE; + } + vos_mem_set(&bssConfig, sizeof(tBssConfigParam), 0); + /* Assume HDD provide bssid in profile */ + vos_mem_copy(&pSession->bssParams.bssid, pProfile->BSSIDs.bssid[0], + sizeof(tCsrBssid)); + // there is no Bss description before we start an WDS so we need + // to adopt all Bss configuration parameters from the Profile. + status = csrRoamPrepareBssConfigFromProfile(pMac, pProfile, &bssConfig, pBssDesc); + if(HAL_STATUS_SUCCESS(status)) + { + //Save profile for late use + csrFreeRoamProfile( pMac, sessionId ); + pSession->pCurRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if (pSession->pCurRoamProfile != NULL ) + { + vos_mem_set(pSession->pCurRoamProfile, + sizeof(tCsrRoamProfile), 0); + csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, pProfile); + } + //Prepare some more parameters for this WDS + csrRoamPrepareBssParams(pMac, sessionId, pProfile, NULL, &bssConfig, NULL); + status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile, + NULL, &bssConfig, + NULL, eANI_BOOLEAN_FALSE); + } + } + + return( status ); +} + +////////////////////Mail box + +//pBuf is caller allocated memory point to &(tSirSmeJoinReq->rsnIE.rsnIEdata[ 0 ]) + pMsg->rsnIE.length; +//or &(tSirSmeReassocReq->rsnIE.rsnIEdata[ 0 ]) + pMsg->rsnIE.length; +static void csrPrepareJoinReassocReqBuffer( tpAniSirGlobal pMac, + tSirBssDescription *pBssDescription, + tANI_U8 *pBuf, tANI_U8 uapsdMask) +{ + tCsrChannelSet channelGroup; + tSirMacCapabilityInfo *pAP_capabilityInfo; + tAniBool fTmp; + tANI_BOOLEAN found = FALSE; + tANI_U32 size = 0; + tANI_S8 pwrLimit = 0; + tANI_U16 i; + // 802.11h + //We can do this because it is in HOST CPU order for now. + pAP_capabilityInfo = (tSirMacCapabilityInfo *)&pBssDescription->capabilityInfo; + //tell the target AP my 11H capability only if both AP and STA support 11H and the channel being used is 11a + if ( csrIs11hSupported( pMac ) && pAP_capabilityInfo->spectrumMgt && eSIR_11A_NW_TYPE == pBssDescription->nwType ) + { + fTmp = (tAniBool)pal_cpu_to_be32(1); + } + else + fTmp = (tAniBool)0; + + // corresponds to --- pMsg->spectrumMgtIndicator = ON; + vos_mem_copy(pBuf, (tANI_U8 *)&fTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + *pBuf++ = MIN_TX_PWR_CAP; // it is for pMsg->powerCap.minTxPower = 0; + found = csrSearchChannelListForTxPower(pMac, pBssDescription, &channelGroup); + // This is required for 11k test VoWiFi Ent: Test 2. + // We need the power capabilities for Assoc Req. + // This macro is provided by the halPhyCfg.h. We pick our + // max and min capability by the halPhy provided macros + pwrLimit = csrGetCfgMaxTxPower (pMac, pBssDescription->channelId); + if (0 != pwrLimit) + { + *pBuf++ = pwrLimit; + } + else + { + *pBuf++ = MAX_TX_PWR_CAP; + } + size = sizeof(pMac->roam.validChannelList); + if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &size))) + { + tANI_U8 *actualSize = pBuf++; + *actualSize = 0; + + for ( i = 0; i < size; i++) + { + /* Only add 5ghz channels*/ + if (CSR_IS_CHANNEL_5GHZ(pMac->roam.validChannelList[ i ])) + { + *actualSize +=1; + *pBuf++ = pMac->roam.validChannelList[ i ]; + } + + } + } + else + { + smsLog(pMac, LOGE, FL("can not find any valid channel")); + *pBuf++ = 0; //tSirSupChnl->numChnl + } + //Check whether it is ok to enter UAPSD +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if( btcIsReadyForUapsd(pMac) ) +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + { + *pBuf++ = uapsdMask; + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + else + { + smsLog(pMac, LOGE, FL(" BTC doesn't allow UAPSD for uapsd_mask(0x%X)"), uapsdMask); + *pBuf++ = 0; + } +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + + // move the entire BssDescription into the join request. + vos_mem_copy(pBuf, pBssDescription, + pBssDescription->length + sizeof( pBssDescription->length )); + pBuf += pBssDescription->length + sizeof( pBssDescription->length ); // update to new location +} + +/* + * The communication between HDD and LIM is thru mailbox (MB). + * Both sides will access the data structure "tSirSmeJoinReq". + * The rule is, while the components of "tSirSmeJoinReq" can be accessed + * in the regular way like tSirSmeJoinReq.assocType, this guideline + * stops at component tSirRSNie; any access to the components after tSirRSNie + * is forbidden because the space from tSirRSNie is squeezed + * with the component "tSirBssDescription". And since the size of actual + * 'tSirBssDescription' varies, the receiving side (which is the routine + * limJoinReqSerDes() of limSerDesUtils.cc) should keep in mind not to access + * the components DIRECTLY after tSirRSNie. + */ +eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription, + tCsrRoamProfile *pProfile, tDot11fBeaconIEs *pIes, tANI_U16 messageType ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeJoinReq *pMsg; + tANI_U8 *pBuf; + v_U8_t acm_mask = 0, uapsd_mask; + tANI_U16 msgLen, wTmp, ieLen; + tSirMacRateSet OpRateSet; + tSirMacRateSet ExRateSet; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tANI_U32 dwTmp; + tANI_U8 wpaRsnIE[DOT11F_IE_RSN_MAX_LEN]; //RSN MAX is bigger than WPA MAX + tANI_U32 ucDot11Mode = 0; + tANI_U8 txBFCsnValue = 0; + tpCsrNeighborRoamControlInfo neigh_roam_info; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + if (NULL == pBssDescription) + { + smsLog(pMac, LOGE, FL(" pBssDescription is NULL")); + return eHAL_STATUS_FAILURE; + } + neigh_roam_info = &pMac->roam.neighborRoamInfo[sessionId]; + + if ((eWNI_SME_REASSOC_REQ == messageType) || + CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId) || + (abs(pBssDescription->rssi) < + (neigh_roam_info->cfgParams.neighborLookupThreshold + + neigh_roam_info->cfgParams.hi_rssi_scan_rssi_delta))) { + pSession->disable_hi_rssi = true; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Disabling HI_RSSI feature, AP channel=%d, rssi=%d", + pBssDescription->channelId, pBssDescription->rssi); + } + else { + pSession->disable_hi_rssi = false; + } + + do { + pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS; + pSession->joinFailStatusCode.reasonCode = 0; + vos_mem_copy(&pSession->joinFailStatusCode.bssId, + &pBssDescription->bssId, sizeof(tSirMacAddr)); + // 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. + pMsg = vos_mem_malloc(msgLen); + if (NULL == pMsg) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, msgLen , 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)messageType); + pMsg->length = pal_cpu_to_be16(msgLen); + pBuf = &pMsg->sessionId; + // sessionId + *pBuf = (tANI_U8)sessionId; + pBuf++; + // transactionId + *pBuf = 0; + *( pBuf + 1 ) = 0; + pBuf += sizeof(tANI_U16); + // ssId + if( pIes->SSID.present && pIes->SSID.num_ssid ) + { + // ssId len + *pBuf = pIes->SSID.num_ssid; + pBuf++; + vos_mem_copy(pBuf, pIes->SSID.ssid, pIes->SSID.num_ssid); + pBuf += pIes->SSID.num_ssid; + } + else + { + *pBuf = 0; + pBuf++; + } + smsLog(pMac, LOGE, + "Connecting to ssid:%.*s bssid: " + MAC_ADDRESS_STR" rssi: %d channel: %d country_code: %c%c", + pIes->SSID.num_ssid, pIes->SSID.ssid, + MAC_ADDR_ARRAY(pBssDescription->bssId), + pBssDescription->rssi, pBssDescription->channelId, + pMac->scan.countryCodeCurrent[0], + pMac->scan.countryCodeCurrent[1]); + // selfMacAddr + vos_mem_copy((tSirMacAddr *)pBuf, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + // bsstype + dwTmp = pal_cpu_to_be32( csrTranslateBsstypeToMacType( pProfile->BSSType ) ); + if (dwTmp == eSIR_BTAMP_STA_MODE) dwTmp = eSIR_BTAMP_AP_MODE; // Override BssType for BTAMP + vos_mem_copy(pBuf, &dwTmp, sizeof(tSirBssType)); + pBuf += sizeof(tSirBssType); + // dot11mode + ucDot11Mode = csrTranslateToWNICfgDot11Mode( pMac, pSession->bssParams.uCfgDot11Mode ); + if (pBssDescription->channelId <= 14 && + FALSE == pMac->roam.configParam.enableVhtFor24GHz && + WNI_CFG_DOT11_MODE_11AC == ucDot11Mode) + { + //Need to disable VHT operation in 2.4 GHz band + ucDot11Mode = WNI_CFG_DOT11_MODE_11N; + } + *pBuf = (tANI_U8)ucDot11Mode; + pBuf++; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + *pBuf = pMac->roam.configParam.cc_switch_mode; + pBuf += 1; +#endif + //Persona + *pBuf = (tANI_U8)pProfile->csrPersona; + pBuf++; + //CBMode + *pBuf = (tANI_U8)pSession->bssParams.cbMode; + pBuf += sizeof(ePhyChanBondState); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("CSR PERSONA=%d CSR CbMode %d"), pProfile->csrPersona, pSession->bssParams.cbMode); + + // uapsdPerAcBitmask + *pBuf = pProfile->uapsd_mask; + pBuf++; + + + + status = csrGetRateSet(pMac, pProfile, (eCsrPhyMode)pProfile->phyMode, pBssDescription, pIes, &OpRateSet, &ExRateSet); + if (HAL_STATUS_SUCCESS(status) ) + { + // OperationalRateSet + if (OpRateSet.numRates) { + *pBuf++ = OpRateSet.numRates; + vos_mem_copy(pBuf, OpRateSet.rate, OpRateSet.numRates); + pBuf += OpRateSet.numRates; + } else *pBuf++ = 0; + // ExtendedRateSet + if (ExRateSet.numRates) { + *pBuf++ = ExRateSet.numRates; + vos_mem_copy(pBuf, ExRateSet.rate, ExRateSet.numRates); + pBuf += ExRateSet.numRates; + } else *pBuf++ = 0; + } + else + { + *pBuf++ = 0; + *pBuf++ = 0; + } + // rsnIE + if ( csrIsProfileWpa( pProfile ) ) + { + // Insert the Wpa IE into the join request + ieLen = csrRetrieveWpaIe( pMac, pProfile, pBssDescription, pIes, + (tCsrWpaIe *)( wpaRsnIE ) ); + } + else if( csrIsProfileRSN( pProfile ) ) + { + // Insert the RSN IE into the join request + ieLen = csrRetrieveRsnIe( pMac, sessionId, pProfile, pBssDescription, pIes, + (tCsrRSNIe *)( wpaRsnIE ) ); + } +#ifdef FEATURE_WLAN_WAPI + else if( csrIsProfileWapi( pProfile ) ) + { + // Insert the WAPI IE into the join request + ieLen = csrRetrieveWapiIe( pMac, sessionId, pProfile, pBssDescription, pIes, + (tCsrWapiIe *)( wpaRsnIE ) ); + } +#endif /* FEATURE_WLAN_WAPI */ + else + { + ieLen = 0; + } + //remember the IE for future use + if( ieLen ) + { + if(ieLen > DOT11F_IE_RSN_MAX_LEN) + { + smsLog(pMac, LOGE, FL(" WPA RSN IE length :%d is more than DOT11F_IE_RSN_MAX_LEN, resetting to %d"), ieLen, DOT11F_IE_RSN_MAX_LEN); + ieLen = DOT11F_IE_RSN_MAX_LEN; + } +#ifdef FEATURE_WLAN_WAPI + if( csrIsProfileWapi( pProfile ) ) + { + //Check whether we need to allocate more memory + if(ieLen > pSession->nWapiReqIeLength) + { + if(pSession->pWapiReqIE && pSession->nWapiReqIeLength) + { + vos_mem_free(pSession->pWapiReqIE); + } + pSession->pWapiReqIE = vos_mem_malloc(ieLen); + if (NULL == pSession->pWapiReqIE) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + pSession->nWapiReqIeLength = ieLen; + vos_mem_copy(pSession->pWapiReqIE, wpaRsnIE, ieLen); + wTmp = pal_cpu_to_be16( ieLen ); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + vos_mem_copy(pBuf, wpaRsnIE, ieLen); + pBuf += ieLen; + } + else//should be WPA/WPA2 otherwise +#endif /* FEATURE_WLAN_WAPI */ + { + //Check whether we need to allocate more memory + if(ieLen > pSession->nWpaRsnReqIeLength) + { + if(pSession->pWpaRsnReqIE && pSession->nWpaRsnReqIeLength) + { + vos_mem_free(pSession->pWpaRsnReqIE); + } + pSession->pWpaRsnReqIE = vos_mem_malloc(ieLen); + if (NULL == pSession->pWpaRsnReqIE) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + pSession->nWpaRsnReqIeLength = ieLen; + vos_mem_copy(pSession->pWpaRsnReqIE, wpaRsnIE, ieLen); + wTmp = pal_cpu_to_be16( ieLen ); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + vos_mem_copy(pBuf, wpaRsnIE, ieLen); + pBuf += ieLen; + } + } + else + { + //free whatever old info + pSession->nWpaRsnReqIeLength = 0; + if(pSession->pWpaRsnReqIE) + { + vos_mem_free(pSession->pWpaRsnReqIE); + pSession->pWpaRsnReqIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + pSession->nWapiReqIeLength = 0; + if(pSession->pWapiReqIE) + { + vos_mem_free(pSession->pWapiReqIE); + pSession->pWapiReqIE = NULL; + } +#endif /* FEATURE_WLAN_WAPI */ + //length is two bytes + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += 2; + } +#ifdef FEATURE_WLAN_ESE + if( eWNI_SME_JOIN_REQ == messageType ) + { + // Never include the cckmIE in an Join Request + //length is two bytes + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += 2; + } + else if(eWNI_SME_REASSOC_REQ == messageType ) + { + // cckmIE + if( csrIsProfileESE( pProfile ) ) + { + // Insert the CCKM IE into the join request +#ifdef FEATURE_WLAN_ESE_UPLOAD + ieLen = pSession->suppCckmIeInfo.cckmIeLen; + vos_mem_copy((void *) (wpaRsnIE), + pSession->suppCckmIeInfo.cckmIe, ieLen); +#else + ieLen = csrConstructEseCckmIe( pMac, + pSession, + pProfile, + pBssDescription, + pSession->pWpaRsnReqIE, + pSession->nWpaRsnReqIeLength, + (void *)( wpaRsnIE ) ); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + } + else + { + ieLen = 0; + } + //If present, copy the IE into the eWNI_SME_REASSOC_REQ message buffer + if( ieLen ) + { + //Copy the CCKM IE over from the temp buffer (wpaRsnIE) + wTmp = pal_cpu_to_be16( ieLen ); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + vos_mem_copy(pBuf, wpaRsnIE, ieLen); + pBuf += ieLen; + } + else + { + //Indicate you have no CCKM IE + //length is two bytes + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += 2; + } + } +#endif /* FEATURE_WLAN_ESE */ + // addIEScan + if(pProfile->nAddIEScanLength && pProfile->pAddIEScan) + { + ieLen = pProfile->nAddIEScanLength; + if(ieLen > pSession->nAddIEScanLength) + { + if(pSession->pAddIEScan && pSession->nAddIEScanLength) + { + vos_mem_free(pSession->pAddIEScan); + } + pSession->pAddIEScan = vos_mem_malloc(ieLen); + if (NULL == pSession->pAddIEScan) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + pSession->nAddIEScanLength = ieLen; + vos_mem_copy(pSession->pAddIEScan, pProfile->pAddIEScan, ieLen); + wTmp = pal_cpu_to_be16( ieLen ); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + vos_mem_copy(pBuf, pProfile->pAddIEScan, ieLen); + pBuf += ieLen; + } + else + { + pSession->nAddIEScanLength = 0; + if(pSession->pAddIEScan) + { + vos_mem_free(pSession->pAddIEScan); + pSession->pAddIEScan = NULL; + } + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += 2; + } + // addIEAssoc + if(pProfile->nAddIEAssocLength && pProfile->pAddIEAssoc) + { + ieLen = pProfile->nAddIEAssocLength; + if(ieLen > pSession->nAddIEAssocLength) + { + if(pSession->pAddIEAssoc && pSession->nAddIEAssocLength) + { + vos_mem_free(pSession->pAddIEAssoc); + } + pSession->pAddIEAssoc = vos_mem_malloc(ieLen); + if (NULL == pSession->pAddIEAssoc) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + pSession->nAddIEAssocLength = ieLen; + vos_mem_copy(pSession->pAddIEAssoc, pProfile->pAddIEAssoc, ieLen); + wTmp = pal_cpu_to_be16( ieLen ); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + vos_mem_copy(pBuf, pProfile->pAddIEAssoc, ieLen); + pBuf += ieLen; + } + else + { + pSession->nAddIEAssocLength = 0; + if(pSession->pAddIEAssoc) + { + vos_mem_free(pSession->pAddIEAssoc); + pSession->pAddIEAssoc = NULL; + } + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += 2; + } + + if(eWNI_SME_REASSOC_REQ == messageType ) + { + //Unmask any AC in reassoc that is ACM-set + uapsd_mask = (v_U8_t)pProfile->uapsd_mask; + if( uapsd_mask && ( NULL != pBssDescription ) ) + { + if( CSR_IS_QOS_BSS(pIes) && CSR_IS_UAPSD_BSS(pIes) ) + { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + acm_mask = sme_QosGetACMMask(pMac, pBssDescription, pIes); +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + } + else + { + uapsd_mask = 0; + } + } + } + + dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedUCEncryptionType) ); + vos_mem_copy(pBuf, &dwTmp, sizeof(tANI_U32)); + pBuf += sizeof(tANI_U32); + + dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedMCEncryptionType) ); + vos_mem_copy(pBuf, &dwTmp, sizeof(tANI_U32)); + pBuf += sizeof(tANI_U32); +#ifdef WLAN_FEATURE_11W + //MgmtEncryption + if (pProfile->MFPEnabled) + { + dwTmp = pal_cpu_to_be32(eSIR_ED_AES_128_CMAC); + } + else + { + dwTmp = pal_cpu_to_be32(eSIR_ED_NONE); + } + vos_mem_copy(pBuf, &dwTmp, sizeof(tANI_U32)); + pBuf += sizeof(tANI_U32); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + pProfile->MDID.mdiePresent = pBssDescription->mdiePresent; + if (csrIsProfile11r( pProfile ) +#ifdef FEATURE_WLAN_ESE + && !((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) && + (pIes->ESEVersion.present) && (pMac->roam.configParam.isEseIniFeatureEnabled)) +#endif + ) + { + // is11Rconnection; + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)) ; + pBuf += sizeof(tAniBool); + } + else + { + // is11Rconnection; + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } +#endif +#ifdef FEATURE_WLAN_ESE + + // isESEFeatureIniEnabled + if (TRUE == pMac->roam.configParam.isEseIniFeatureEnabled) + { + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += 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 explicitly 11R only then we will get + * 11R. + */ + if ((csrIsProfileESE(pProfile) || + ((pIes->ESEVersion.present) + && (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM))) + && (pMac->roam.configParam.isEseIniFeatureEnabled)) + { + // isESEconnection; + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + //isESEconnection; + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + + if (eWNI_SME_JOIN_REQ == messageType) + { + 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(pBuf, &eseTspec, sizeof(tESETspecInfo)); + pBuf += sizeof(tESETspecInfo); + } + else if (eWNI_SME_REASSOC_REQ == messageType) + { + if ((csrIsProfileESE(pProfile) || + ((pIes->ESEVersion.present) + && (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM))) + && (pMac->roam.configParam.isEseIniFeatureEnabled)) + { + tESETspecInfo eseTspec; + // ESE Tspec information + vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0); + eseTspec.numTspecs = sme_QosEseRetrieveTspecInfo(pMac, sessionId, (tTspecInfo *) &eseTspec.tspec[0]); + *pBuf = eseTspec.numTspecs; + pBuf += sizeof(tANI_U8); + // Copy the TSPEC information only if present + if (eseTspec.numTspecs) { + vos_mem_copy(pBuf, (void*)&eseTspec.tspec[0], + (eseTspec.numTspecs*sizeof(tTspecInfo))); + } + pBuf += 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(pBuf, &eseTspec, sizeof(tESETspecInfo)); + pBuf += sizeof(tESETspecInfo); + } + } +#endif // FEATURE_WLAN_ESE +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + // Fill in isFastTransitionEnabled + if (pMac->roam.configParam.isFastTransitionEnabled +#ifdef FEATURE_WLAN_LFR + || csrRoamIsFastRoamEnabled(pMac, sessionId) +#endif + ) + { + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } +#endif +#ifdef FEATURE_WLAN_LFR + if(csrRoamIsFastRoamEnabled(pMac, sessionId)) + { + //legacy fast roaming enabled + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } +#endif + + // txLdpcIniFeatureEnabled + *pBuf = (tANI_U8)pMac->roam.configParam.txLdpcEnable; + pBuf++; + + if ((csrIs11hSupported (pMac)) && (CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId)) && + (pIes->Country.present) && (!pMac->roam.configParam.fSupplicantCountryCodeHasPriority)) + { + csrSaveToChannelPower2G_5G( pMac, pIes->Country.num_triplets * sizeof(tSirMacChanInfo), + (tSirMacChanInfo *)(&pIes->Country.triplets[0]) ); + csrApplyPower2Current(pMac); + } + + //HT Config + vos_mem_copy(pBuf, &pSession->htConfig, + sizeof(tSirHTConfig)); + pBuf += sizeof(tSirHTConfig); +#ifdef WLAN_FEATURE_11AC + // txBFIniFeatureEnabled + *pBuf = (tANI_U8)pMac->roam.configParam.txBFEnable; + pBuf++; + + // txBFCsnValue + if (IS_BSS_VHT_CAPABLE(pIes->VHTCaps) && + pMac->roam.configParam.txBFEnable) { + txBFCsnValue = (tANI_U8)pMac->roam.configParam.txBFCsnValue; + if (pIes->VHTCaps.numSoundingDim) + txBFCsnValue = MIN(txBFCsnValue, + pIes->VHTCaps.numSoundingDim); + } + *pBuf = txBFCsnValue; + pBuf++; + + // txMuBformee + *pBuf = (tANI_U8)pMac->roam.configParam.txMuBformee; + pBuf++; + + // enableVhtpAid + *pBuf = (tANI_U8)pMac->roam.configParam.enableVhtpAid; + pBuf++; + + // enableVhtGid + *pBuf = (tANI_U8)pMac->roam.configParam.enableVhtGid; + pBuf++; + +#endif + // enableAmpduPs + *pBuf = (tANI_U8)pMac->roam.configParam.enableAmpduPs; + pBuf++; + + // enableHtSmps + *pBuf = (tANI_U8)pMac->roam.configParam.enableHtSmps; + pBuf++; + + // htSmps + *pBuf = (tANI_U8)pMac->roam.configParam.htSmps; + pBuf++; + + *pBuf = (tANI_U8)pMac->roam.configParam.max_amsdu_num; + pBuf++; + + // WME + if(pMac->roam.roamSession[sessionId].fWMMConnection) + { + //WME enabled + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + + // QOS + if(pMac->roam.roamSession[sessionId].fQOSConnection) + { + //QOS enabled + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + // OSEN + if(pProfile->bOSENAssociation) + { + //OSEN connection + dwTmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)); + pBuf += sizeof(tAniBool); + } + /* Fill rrm config parameters */ + vos_mem_copy(pBuf, &pMac->rrm.rrmSmeContext.rrmConfig, + sizeof(struct rrm_config_param)); + pBuf += sizeof(struct rrm_config_param); + + //BssDesc + csrPrepareJoinReassocReqBuffer( pMac, pBssDescription, pBuf, + (tANI_U8)pProfile->uapsd_mask); + + /* + * conc_custom_rule1: + * If SAP comes up first and STA comes up later then SAP + * need to follow STA's channel in 2.4Ghz. In following if condition + * we are adding sanity check, just to make sure that if this rule + * is enabled then don't allow STA to connect on 5gz channel and also + * by this time SAP's channel should be the same as STA's channel. + */ + if (pMac->roam.configParam.conc_custom_rule1) { + if ((0 == pMac->roam.configParam.is_sta_connection_in_5gz_enabled) + && CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("STA connection on 5G band is not allowed")); + status = eHAL_STATUS_FAILURE; + break; + } + if (!CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId) && + (false == csr_is_conn_allow_2g_band(pMac, + pBssDescription->channelId))) { + status = eHAL_STATUS_FAILURE; + break; + } + } + + /* + * conc_custom_rule2: + * If P2PGO comes up first and STA comes up later then P2PGO + * need to follow STA's channel in 5Ghz. In following if condition + * we are just adding sanity check to make sure that by this time + * P2PGO's channel is same as STA's channel. + */ + if (pMac->roam.configParam.conc_custom_rule2) { + if (!CSR_IS_CHANNEL_24GHZ(pBssDescription->channelId) && + (false == csr_is_conn_allow_5g_band(pMac, + pBssDescription->channelId))) { + status = eHAL_STATUS_FAILURE; + break; + } + } + + status = palSendMBMessage(pMac->hHdd, pMsg ); + if(!HAL_STATUS_SUCCESS(status)) + { + /* + * palSendMBMessage would've released the memory allocated by pMsg. + * Let's make it defensive by assigning NULL to the pointer. + */ + pMsg = NULL; + break; + } + else + { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if (eWNI_SME_JOIN_REQ == messageType) + { + //Tush-QoS: notify QoS module that join happening + pSession->join_bssid_count++; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "BSSID Count = %d", pSession->join_bssid_count); + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_JOIN_REQ, NULL); + } + else if (eWNI_SME_REASSOC_REQ == messageType) + { + //Tush-QoS: notify QoS module that reassoc happening + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_REASSOC_REQ, NULL); + } +#endif + } + } while( 0 ); + + /* Clean up the memory in case of any failure */ + if (!HAL_STATUS_SUCCESS(status) && (NULL != pMsg)) { + vos_mem_free(pMsg); + } + return( status ); +} + +// +eHalStatus csrSendMBDisassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeDisassocReq *pMsg; + tANI_U8 *pBuf; + tANI_U16 wTmp; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (!CSR_IS_SESSION_VALID( pMac, sessionId )) + return eHAL_STATUS_FAILURE; + do { + pMsg = vos_mem_malloc(sizeof(tSirSmeDisassocReq)); + if (NULL == pMsg) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, sizeof( tSirSmeDisassocReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DISASSOC_REQ); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDisassocReq )); + pBuf = &pMsg->sessionId; + // sessionId + *pBuf++ = (tANI_U8)sessionId; + // transactionId + *pBuf = 0; + *( pBuf + 1 ) = 0; + pBuf += sizeof(tANI_U16); + + if ( (pSession->pCurRoamProfile != NULL) && + ((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) || + (CSR_IS_WDS_AP(pSession->pCurRoamProfile))) ) + { + // Set the bssid address before sending the message to LIM + vos_mem_copy((tSirMacAddr *)pBuf, pSession->selfMacAddr, + sizeof( tSirMacAddr )); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof ( tSirMacAddr ); + // Set the peer MAC address before sending the message to LIM + vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof( tSirMacAddr )); + //perMacAddr is passed as bssId for softAP + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof ( tSirMacAddr ); + } + else + { + // Set the peer MAC address before sending the message to LIM + vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof( tSirMacAddr )); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof ( tSirMacAddr ); + vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof( pMsg->bssId )); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof ( tSirMacAddr ); + } + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + // reasonCode + wTmp = pal_cpu_to_be16(reasonCode); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + pBuf += sizeof(tANI_U16); + /* The state will be DISASSOC_HANDOFF only when we are doing handoff. + Here we should not send the disassoc over the air to the AP */ + if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId) +#ifdef WLAN_FEATURE_VOWIFI_11R + && csrRoamIs11rAssoc(pMac, sessionId) +#endif + ) + { + *pBuf = CSR_DONT_SEND_DISASSOC_OVER_THE_AIR; /* Set DoNotSendOverTheAir flag to 1 only for handoff case */ + } + pBuf += sizeof(tANI_U8); + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} +eHalStatus csrSendMBTkipCounterMeasuresReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN bEnable, tSirMacAddr bssId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeTkipCntrMeasReq *pMsg; + tANI_U8 *pBuf; + do + { + pMsg = vos_mem_malloc(sizeof( tSirSmeTkipCntrMeasReq )); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, sizeof( tSirSmeTkipCntrMeasReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_TKIP_CNTR_MEAS_REQ); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeTkipCntrMeasReq )); + pBuf = &pMsg->sessionId; + // sessionId + *pBuf++ = (tANI_U8)sessionId; + // transactionId + *pBuf = 0; + *( pBuf + 1 ) = 0; + pBuf += sizeof(tANI_U16); + // bssid + vos_mem_copy(pMsg->bssId, bssId, sizeof( tSirMacAddr )); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof ( tSirMacAddr ); + // bEnable + *pBuf = (tANI_BOOLEAN)bEnable; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} +eHalStatus +csrSendMBGetAssociatedStasReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, + VOS_MODULE_ID modId, tSirMacAddr bssId, + void *pUsrContext, void *pfnSapEventCallback, + tANI_U8 *pAssocStasBuf ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeGetAssocSTAsReq *pMsg; + tANI_U8 *pBuf = NULL, *wTmpBuf = NULL; + tANI_U32 dwTmp; + do + { + pMsg = vos_mem_malloc(sizeof( tSirSmeGetAssocSTAsReq )); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) break; + vos_mem_set(pMsg, sizeof( tSirSmeGetAssocSTAsReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_ASSOC_STAS_REQ); + pBuf = (tANI_U8 *)&pMsg->bssId; + wTmpBuf = pBuf; + // bssId + vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + // modId + dwTmp = pal_cpu_to_be16((tANI_U16)modId); + vos_mem_copy(pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + // pUsrContext + vos_mem_copy(pBuf, (tANI_U8 *)pUsrContext, sizeof(void *)); + pBuf += sizeof(void*); + // pfnSapEventCallback + vos_mem_copy(pBuf, (tANI_U8 *)pfnSapEventCallback, sizeof(void*)); + pBuf += sizeof(void*); + // pAssocStasBuf + vos_mem_copy(pBuf, pAssocStasBuf, sizeof(void*)); + pBuf += sizeof(void*); + pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf)));//msg_header + msg + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); + } +eHalStatus +csrSendMBGetWPSPBCSessions( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr bssId, void *pUsrContext, void *pfnSapEventCallback,v_MACADDR_t pRemoveMac) + { + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeGetWPSPBCSessionsReq *pMsg; + tANI_U8 *pBuf = NULL, *wTmpBuf = NULL; + + do + { + pMsg = vos_mem_malloc(sizeof(tSirSmeGetWPSPBCSessionsReq)); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) break; + vos_mem_set(pMsg, sizeof( tSirSmeGetWPSPBCSessionsReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_WPSPBC_SESSION_REQ); + pBuf = (tANI_U8 *)&pMsg->pUsrContext; + + if( NULL == pBuf) + { + VOS_ASSERT(pBuf); + return eHAL_STATUS_FAILURE; + } + wTmpBuf = pBuf; + // pUsrContext + vos_mem_copy(pBuf, (tANI_U8 *)pUsrContext, sizeof(void*)); + pBuf += sizeof(void *); + // pSapEventCallback + vos_mem_copy(pBuf, (tANI_U8 *)pfnSapEventCallback, sizeof(void *)); + pBuf += sizeof(void *); + // bssId + vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + // MAC Address of STA in WPS session + vos_mem_copy((tSirMacAddr *)pBuf, pRemoveMac.bytes, sizeof(v_MACADDR_t)); + pBuf += sizeof(v_MACADDR_t); + pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf)));//msg_header + msg + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} + +eHalStatus +csrSendChngMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tpSirChangeBIParams pMsg; + tANI_U16 len = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + //NO need to update the Beacon Params if update beacon parameter flag is not set + if(!pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval ) + return eHAL_STATUS_SUCCESS; + + pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval = eANI_BOOLEAN_FALSE; + + /* Create the message and send to lim */ + len = sizeof(tSirChangeBIParams); + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pMsg, sizeof(tSirChangeBIParams), 0); + pMsg->messageType = eWNI_SME_CHNG_MCC_BEACON_INTERVAL; + pMsg->length = len; + + // bssId + vos_mem_copy((tSirMacAddr *)pMsg->bssId, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + smsLog( pMac, LOG1, FL("CSR Attempting to change BI for Bssid= "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMsg->bssId)); + pMsg->sessionId = sessionId; + smsLog(pMac, LOG1, FL(" session %d BeaconInterval %d"), sessionId, pMac->roam.roamSession[sessionId].bssParams.beaconInterval); + pMsg->beaconInterval = pMac->roam.roamSession[sessionId].bssParams.beaconInterval; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + return status; +} + +#ifdef QCA_HT_2040_COEX +eHalStatus csrSetHT2040Mode(tpAniSirGlobal pMac, tANI_U32 sessionId, + ePhyChanBondState cbMode, tANI_BOOLEAN obssEnabled) +{ + tpSirSetHT2040Mode pMsg; + tANI_U16 len = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + /* Create the message and send to lim */ + len = sizeof(tSirSetHT2040Mode); + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pMsg, sizeof(tSirSetHT2040Mode), 0); + pMsg->messageType = eWNI_SME_SET_HT_2040_MODE; + pMsg->length = len; + + // bssId + vos_mem_copy((tSirMacAddr *)pMsg->bssId, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + smsLog( pMac, LOG1, FL("CSR Attempting to set HT20/40 mode for Bssid= "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMsg->bssId)); + pMsg->sessionId = sessionId; + smsLog(pMac, LOG1, FL(" session %d HT20/40 mode %d"), sessionId, cbMode); + pMsg->cbMode = cbMode; + pMsg->obssEnabled = obssEnabled; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + return status; +} +#endif + +eHalStatus csrSendMBDeauthReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeDeauthReq *pMsg; + tANI_U8 *pBuf; + tANI_U16 wTmp; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (!CSR_IS_SESSION_VALID( pMac, sessionId )) + return eHAL_STATUS_FAILURE; + do { + pMsg = vos_mem_malloc(sizeof( tSirSmeDeauthReq )); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, sizeof( tSirSmeDeauthReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEAUTH_REQ); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDeauthReq )); + //sessionId + pBuf = &pMsg->sessionId; + *pBuf++ = (tANI_U8)sessionId; + + //tansactionId + *pBuf = 0; + *(pBuf + 1 ) = 0; + pBuf += sizeof(tANI_U16); + if ((pSession->pCurRoamProfile != NULL) && ( + (CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) || + (CSR_IS_WDS_AP(pSession->pCurRoamProfile)))){ + // Set the BSSID before sending the message to LIM + vos_mem_copy( (tSirMacAddr *)pBuf, pSession->selfMacAddr, + sizeof( pMsg->peerMacAddr ) ); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof(tSirMacAddr); + } + else + { + // Set the BSSID before sending the message to LIM + vos_mem_copy( (tSirMacAddr *)pBuf, bssId, sizeof( pMsg->peerMacAddr ) ); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof(tSirMacAddr); + } + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + // Set the peer MAC address before sending the message to LIM + vos_mem_copy( (tSirMacAddr *) pBuf, bssId, sizeof( pMsg->peerMacAddr ) ); + status = eHAL_STATUS_SUCCESS; + pBuf = pBuf + sizeof(tSirMacAddr); + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + wTmp = pal_cpu_to_be16(reasonCode); + vos_mem_copy( pBuf, &wTmp,sizeof( tANI_U16 ) ); + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} + +eHalStatus csrSendMBDisassocCnfMsg( tpAniSirGlobal pMac, tpSirSmeDisassocInd pDisassocInd ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeDisassocCnf *pMsg; + do { + pMsg = vos_mem_malloc(sizeof( tSirSmeDisassocCnf )); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, sizeof( tSirSmeDisassocCnf), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DISASSOC_CNF); + pMsg->statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDisassocCnf )); + vos_mem_copy(pMsg->peerMacAddr, pDisassocInd->peerMacAddr, + sizeof(pMsg->peerMacAddr)); + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + + vos_mem_copy(pMsg->bssId, pDisassocInd->bssId, sizeof(pMsg->peerMacAddr)); + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} + +eHalStatus csrSendMBDeauthCnfMsg( tpAniSirGlobal pMac, tpSirSmeDeauthInd pDeauthInd ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeDeauthCnf *pMsg; + do { + pMsg = vos_mem_malloc(sizeof( tSirSmeDeauthCnf )); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, sizeof( tSirSmeDeauthCnf ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEAUTH_CNF); + pMsg->statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDeauthCnf )); + vos_mem_copy(pMsg->bssId, pDeauthInd->bssId, sizeof(pMsg->bssId)); + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + vos_mem_copy(pMsg->peerMacAddr, pDeauthInd->peerMacAddr, + sizeof(pMsg->peerMacAddr)); + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(pMsg); + break; + } + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} +eHalStatus csrSendAssocCnfMsg( tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, eHalStatus Halstatus ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeAssocCnf *pMsg; + tANI_U8 *pBuf; + tSirResultCodes statusCode; + tANI_U16 wTmp; + smsLog( pMac, LOG1, FL("Posting eWNI_SME_ASSOC_CNF to LIM. " + "HalStatus : %d"), + Halstatus); + do { + pMsg = vos_mem_malloc(sizeof( tSirSmeAssocCnf )); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( !HAL_STATUS_SUCCESS(status) ) break; + vos_mem_set(pMsg, sizeof( tSirSmeAssocCnf ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ASSOC_CNF); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeAssocCnf )); + pBuf = (tANI_U8 *)&pMsg->statusCode; + if(HAL_STATUS_SUCCESS(Halstatus)) + statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS); + else + statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_ASSOC_REFUSED); + vos_mem_copy(pBuf, &statusCode, sizeof(tSirResultCodes)); + pBuf += sizeof(tSirResultCodes); + // bssId + vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr)); + status = eHAL_STATUS_SUCCESS; + pBuf += sizeof (tSirMacAddr); + // peerMacAddr + vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + status = eHAL_STATUS_SUCCESS; + pBuf += sizeof (tSirMacAddr); + // aid + wTmp = pal_cpu_to_be16(pAssocInd->aid); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof (tANI_U16); + // alternateBssId + vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr)); + status = eHAL_STATUS_SUCCESS; + pBuf += sizeof (tSirMacAddr); + // alternateChannelId + *pBuf = 11; + status = palSendMBMessage( pMac->hHdd, pMsg ); + if(!HAL_STATUS_SUCCESS(status)) + { + //pMsg is freed by palSendMBMessage + break; + } + } while( 0 ); + return( status ); +} +eHalStatus csrSendAssocIndToUpperLayerCnfMsg( tpAniSirGlobal pMac, + tpSirSmeAssocInd pAssocInd, + eHalStatus Halstatus, + tANI_U8 sessionId) +{ + tSirMsgQ msgQ; + tSirSmeAssocIndToUpperLayerCnf *pMsg; + tANI_U8 *pBuf; + tSirResultCodes statusCode; + tANI_U16 wTmp; + do { + pMsg = vos_mem_malloc(sizeof( tSirSmeAssocIndToUpperLayerCnf )); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, sizeof( tSirSmeAssocIndToUpperLayerCnf ), 0); + + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_UPPER_LAYER_ASSOC_CNF); + pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeAssocIndToUpperLayerCnf )); + + pMsg->sessionId = sessionId; + + pBuf = (tANI_U8 *)&pMsg->statusCode; + if(HAL_STATUS_SUCCESS(Halstatus)) + statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS); + else + statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_ASSOC_REFUSED); + vos_mem_copy(pBuf, &statusCode, sizeof(tSirResultCodes)) ; + pBuf += sizeof(tSirResultCodes); + // bssId + vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof (tSirMacAddr); + // peerMacAddr + vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + pBuf += sizeof (tSirMacAddr); + // StaId + wTmp = pal_cpu_to_be16(pAssocInd->staId); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof (tANI_U16); + // alternateBssId + vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof (tSirMacAddr); + // alternateChannelId + *pBuf = 11; + pBuf += sizeof (tANI_U8); + // Instead of copying roam Info, we just copy only WmmEnabled, RsnIE information + //Wmm + *pBuf = pAssocInd->wmmEnabledSta; + pBuf += sizeof (tANI_U8); + //RSN IE + vos_mem_copy((tSirRSNie *)pBuf, &pAssocInd->rsnIE, sizeof(tSirRSNie)); + pBuf += sizeof (tSirRSNie); +#ifdef FEATURE_WLAN_WAPI + //WAPI IE + vos_mem_copy((tSirWAPIie *)pBuf, &pAssocInd->wapiIE, + sizeof(tSirWAPIie)); + pBuf += sizeof (tSirWAPIie); +#endif + //Additional IE + vos_mem_copy((void *)pBuf, &pAssocInd->addIE, sizeof(tSirAddie)); + pBuf += sizeof (tSirAddie); + //reassocReq + *pBuf = pAssocInd->reassocReq; + pBuf += sizeof (tANI_U8); + //timingMeasCap + *pBuf = pAssocInd->timingMeasCap; + pBuf += sizeof (tANI_U8); + vos_mem_copy((void *)pBuf, &pAssocInd->chan_info, + sizeof(tSirSmeChanInfo)); + msgQ.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF; + msgQ.bodyptr = pMsg; + msgQ.bodyval = 0; + SysProcessMmhMsg(pMac, &msgQ); + } while( 0 ); + return( eHAL_STATUS_SUCCESS ); +} + +eHalStatus csrSendMBSetContextReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr peerMacAddr, tANI_U8 numKeys, tAniEdType edType, + tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection, + tANI_U8 keyId, tANI_U8 keyLength, tANI_U8 *pKey, tANI_U8 paeRole, + tANI_U8 *pKeyRsc ) +{ + tSirSmeSetContextReq *pMsg; + tANI_U16 msgLen; + eHalStatus status = eHAL_STATUS_FAILURE; + tAniEdType tmpEdType; + tAniKeyDirection tmpDirection; + tANI_U8 *pBuf = NULL; + tANI_U8 *p = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + smsLog( pMac, LOG1, FL("keylength is %d, Encry type is : %d"), + keyLength, edType); + do { + if( ( 1 != numKeys ) && ( 0 != numKeys ) ) break; + /* + * All of these fields appear in every SET_CONTEXT message. + * Below we'll add in the size for each key set. Since we only support + * up to one key, we always allocate memory for 1 key. + */ + msgLen = sizeof( tANI_U16) + sizeof( tANI_U16 ) + sizeof( tSirMacAddr ) + + sizeof( tSirMacAddr ) + 1 + sizeof(tANI_U16) + + sizeof( pMsg->keyMaterial.length ) + sizeof( pMsg->keyMaterial.edType ) + sizeof( pMsg->keyMaterial.numKeys ) + + ( sizeof( pMsg->keyMaterial.key ) ); + + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, msgLen, 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SETCONTEXT_REQ); + pMsg->length = pal_cpu_to_be16(msgLen); + //sessionId + pBuf = &pMsg->sessionId; + *pBuf = (tANI_U8)sessionId; + pBuf++; + // transactionId + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += sizeof(tANI_U16); + // peerMacAddr + vos_mem_copy(pBuf, (tANI_U8 *)peerMacAddr, sizeof(tSirMacAddr)); + + pBuf += sizeof(tSirMacAddr); + + // bssId + vos_mem_copy(pBuf, (tANI_U8 *)&pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + pBuf += sizeof(tSirMacAddr); + + p = pBuf; + // Set the pMsg->keyMaterial.length field (this length is defined as all data that follows the edType field + // in the tSirKeyMaterial keyMaterial; field). + // + // !!NOTE: This keyMaterial.length contains the length of a MAX size key, though the keyLength can be + // shorter than this max size. Is LIM interpreting this ok ? + p = pal_set_U16( p, pal_cpu_to_be16((tANI_U16)( sizeof( pMsg->keyMaterial.numKeys ) + ( numKeys * sizeof( pMsg->keyMaterial.key ) ) )) ); + // set pMsg->keyMaterial.edType + tmpEdType = (tAniEdType)pal_cpu_to_be32(edType); + vos_mem_copy(p, (tANI_U8 *)&tmpEdType, sizeof(tAniEdType)); + p += sizeof( pMsg->keyMaterial.edType ); + // set the pMsg->keyMaterial.numKeys field + *p = numKeys; + p += sizeof( pMsg->keyMaterial.numKeys ); + // set pSirKey->keyId = keyId; + *p = keyId; + p += sizeof( pMsg->keyMaterial.key[ 0 ].keyId ); + // set pSirKey->unicast = (tANI_U8)fUnicast; + *p = (tANI_U8)fUnicast; + p += sizeof( pMsg->keyMaterial.key[ 0 ].unicast ); + // set pSirKey->keyDirection = aniKeyDirection; + tmpDirection = (tAniKeyDirection)pal_cpu_to_be32(aniKeyDirection); + vos_mem_copy(p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection)); + p += sizeof(tAniKeyDirection); + // pSirKey->keyRsc = ;; + vos_mem_copy(p, pKeyRsc, CSR_MAX_RSC_LEN); + p += sizeof( pMsg->keyMaterial.key[ 0 ].keyRsc ); + // set pSirKey->paeRole + *p = paeRole; // 0 is Supplicant + p++; + // set pSirKey->keyLength = keyLength; + p = pal_set_U16( p, pal_cpu_to_be16(keyLength) ); + if (keyLength && pKey) + { + vos_mem_copy(p, pKey, keyLength); + smsLog(pMac, LOG1, FL("SME set keyIndx (%d) encType (%d) key"), + keyId, edType); + sirDumpBuf(pMac, SIR_SMS_MODULE_ID, LOG1, pKey, keyLength); + } + status = palSendMBMessage(pMac->hHdd, pMsg); + } while( 0 ); + return( status ); +} + +eHalStatus csrSendMBStartBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamBssType bssType, + tCsrRoamStartBssParams *pParam, tSirBssDescription *pBssDesc ) +{ + eHalStatus status; + tSirSmeStartBssReq *pMsg; + tANI_U8 *pBuf = NULL; + tANI_U8 *wTmpBuf = NULL; + tANI_U16 msgLen, wTmp; + tANI_U32 dwTmp; + tSirNwType nwType; + ePhyChanBondState cbMode; + tANI_U32 authType; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + do { + pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS; + pSession->joinFailStatusCode.reasonCode = 0; + msgLen = sizeof(tSirSmeStartBssReq); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, msgLen, 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_START_BSS_REQ); + pBuf = &pMsg->sessionId; + wTmpBuf = pBuf; + //sessionId + *pBuf = (tANI_U8)sessionId; + pBuf++; + // transactionId + *pBuf = 0; + *(pBuf + 1) = 0; + pBuf += sizeof(tANI_U16); + // bssid + vos_mem_copy(pBuf, pParam->bssid, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + // selfMacAddr + vos_mem_copy(pBuf, pSession->selfMacAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + // beaconInterval + if( pBssDesc && pBssDesc->beaconInterval ) + { + wTmp = pal_cpu_to_be16( pBssDesc->beaconInterval ); + } + else if(pParam->beaconInterval) + { + wTmp = pal_cpu_to_be16( pParam->beaconInterval ); + } + else + { + wTmp = pal_cpu_to_be16( WNI_CFG_BEACON_INTERVAL_STADEF ); + } + if(csrIsconcurrentsessionValid (pMac, sessionId, + pParam->bssPersona) + == eHAL_STATUS_SUCCESS ) + { + csrValidateMCCBeaconInterval(pMac, pParam->operationChn, &wTmp, sessionId, + pParam->bssPersona); + //Update the beacon Interval + pParam->beaconInterval = wTmp; + } + else + { + smsLog( pMac,LOGE, FL("****Start BSS failed persona already exists***")); + status = eHAL_STATUS_FAILURE; + vos_mem_free(pMsg); + return status; + } + + vos_mem_copy(pBuf, &wTmp, sizeof( tANI_U16 )); + pBuf += sizeof(tANI_U16); + // dot11mode + *pBuf = (tANI_U8)csrTranslateToWNICfgDot11Mode( pMac, pParam->uCfgDot11Mode ); + pBuf += 1; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + *pBuf = pMac->roam.configParam.cc_switch_mode; + pBuf += 1; +#endif + + // bssType + dwTmp = pal_cpu_to_be32( csrTranslateBsstypeToMacType( bssType ) ); + vos_mem_copy(pBuf, &dwTmp, sizeof(tSirBssType)); + pBuf += sizeof(tSirBssType); + // ssId + if( pParam->ssId.length ) + { + // ssId len + *pBuf = pParam->ssId.length; + pBuf++; + vos_mem_copy(pBuf, pParam->ssId.ssId, pParam->ssId.length); + pBuf += pParam->ssId.length; + } + else + { + *pBuf = 0; + pBuf++; + } + // set the channel Id + *pBuf = pParam->operationChn; + pBuf++; + //What should we really do for the cbmode. + cbMode = (ePhyChanBondState)pal_cpu_to_be32(pParam->cbMode); + vos_mem_copy(pBuf, (tANI_U8 *)&cbMode, sizeof(ePhyChanBondState)); + pBuf += sizeof(ePhyChanBondState); + /*set vht channel width*/ + *pBuf = pParam->vht_channel_width; + pBuf++; + + // Set privacy + *pBuf = pParam->privacy; + pBuf++; + + //Set Uapsd + *pBuf = pParam->ApUapsdEnable; + pBuf++; + //Set SSID hidden + *pBuf = pParam->ssidHidden; + pBuf++; + *pBuf = (tANI_U8)pParam->fwdWPSPBCProbeReq; + pBuf++; + + //Ht protection Enable/Disable + *pBuf = (tANI_U8)pParam->protEnabled; + pBuf++; + //Enable Beacons to Receive for OBSS protection Enable/Disable + *pBuf = (tANI_U8)pParam->obssProtEnabled; + pBuf++; + //set cfg related to protection + wTmp = pal_cpu_to_be16( pParam->ht_protection ); + vos_mem_copy(pBuf, &wTmp, sizeof( tANI_U16 )); + pBuf += sizeof(tANI_U16); + // Set Auth type + authType = pal_cpu_to_be32(pParam->authType); + vos_mem_copy(pBuf, (tANI_U8 *)&authType, sizeof(tANI_U32)); + pBuf += sizeof(tANI_U32); + // Set DTIM + dwTmp = pal_cpu_to_be32(pParam->dtimPeriod); + vos_mem_copy(pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32)); + pBuf += sizeof(tANI_U32); + // Set wps_state + *pBuf = pParam->wps_state; + pBuf++; + // set isCoalesingInIBSSAllowed + *pBuf = pMac->isCoalesingInIBSSAllowed; + pBuf++; + //Persona + *pBuf = (tANI_U8)pParam->bssPersona; + pBuf++; + + //txLdpcIniFeatureEnabled + *pBuf = (tANI_U8)(tANI_U8)pMac->roam.configParam.txLdpcEnable; + pBuf++; + +#ifdef WLAN_FEATURE_11W + // Set MFP capable/required + *pBuf = (tANI_U8)pParam->mfpCapable; + pBuf++; + *pBuf = (tANI_U8)pParam->mfpRequired; + pBuf++; +#endif + + // set RSN IE + if( pParam->nRSNIELength > sizeof(pMsg->rsnIE.rsnIEdata) ) + { + status = eHAL_STATUS_INVALID_PARAMETER; + vos_mem_free(pMsg); + break; + } + wTmp = pal_cpu_to_be16( pParam->nRSNIELength ); + vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16)); + pBuf += sizeof(tANI_U16); + if( wTmp ) + { + wTmp = pParam->nRSNIELength; + vos_mem_copy(pBuf, pParam->pRSNIE, wTmp); + pBuf += wTmp; + } + nwType = (tSirNwType)pal_cpu_to_be32(pParam->sirNwType); + vos_mem_copy(pBuf, (tANI_U8 *)&nwType, sizeof(tSirNwType)); + pBuf += sizeof(tSirNwType); + *pBuf = pParam->operationalRateSet.numRates; //tSirMacRateSet->numRates + pBuf++; + vos_mem_copy(pBuf, pParam->operationalRateSet.rate, + pParam->operationalRateSet.numRates ); + pBuf += pParam->operationalRateSet.numRates ; + *pBuf++ = pParam->extendedRateSet.numRates; + if(0 != pParam->extendedRateSet.numRates) + { + vos_mem_copy(pBuf, pParam->extendedRateSet.rate, + pParam->extendedRateSet.numRates); + pBuf += pParam->extendedRateSet.numRates; + } + + //HT Config + vos_mem_copy(pBuf, &pSession->htConfig, + sizeof(tSirHTConfig)); + pBuf += sizeof(tSirHTConfig); + + vos_mem_copy(pBuf, &pParam->addIeParams, sizeof( pParam->addIeParams )); + pBuf += sizeof(pParam->addIeParams); + + *pBuf++ = (tANI_U8)pMac->roam.configParam.obssEnabled; + *pBuf++ = (tANI_U8)pParam->sap_dot11mc; + + msgLen = (tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf)); //msg_header + msg + pMsg->length = pal_cpu_to_be16(msgLen); + + status = palSendMBMessage(pMac->hHdd, pMsg); + } while( 0 ); + return( status ); +} + +eHalStatus csrSendMBStopBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tSirSmeStopBssReq *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tANI_U8 *pBuf; + tANI_U16 msgLen; + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + do { + pMsg = vos_mem_malloc(sizeof(tSirSmeStopBssReq)); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, sizeof( tSirSmeStopBssReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_STOP_BSS_REQ); + pBuf = &pMsg->sessionId; + //sessionId + *pBuf = (tANI_U8)sessionId; + pBuf++; + // transactionId + *pBuf = 0; + pBuf += sizeof(tANI_U16); + //reason code + *pBuf = 0; + pBuf += sizeof(tSirResultCodes); + // bssid + // if BSSType is WDS sta, use selfmacAddr as bssid, else use bssid in connectedProfile + if( CSR_IS_CONN_WDS_STA(&pSession->connectedProfile) ) + { + vos_mem_copy(pBuf, (tANI_U8 *)&pSession->selfMacAddr, + sizeof(tSirMacAddr)); + } + else + { + vos_mem_copy(pBuf, (tANI_U8 *)&pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + } + pBuf += sizeof(tSirMacAddr); + msgLen = sizeof(tANI_U16) + sizeof(tANI_U16) + 1 + sizeof(tANI_U16) + sizeof(tSirResultCodes) + sizeof(tSirMacAddr); + pMsg->length = pal_cpu_to_be16(msgLen); + status = palSendMBMessage( pMac->hHdd, pMsg ); + } while( 0 ); + return( status ); +} + +eHalStatus csrReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamModifyProfileFields *pModProfileFields, + tANI_U32 *pRoamId, v_BOOL_t fForce) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_U32 roamId = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if((csrIsConnStateConnected(pMac, sessionId)) && + (fForce || (!vos_mem_compare( &pModProfileFields, + &pSession->connectedProfile.modifyProfileFields, + sizeof(tCsrRoamModifyProfileFields)))) ) + { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(pRoamId) + { + *pRoamId = roamId; + } + + status = csrRoamIssueReassoc(pMac, sessionId, NULL, pModProfileFields, + eCsrSmeIssuedReassocToSameAP, roamId, + eANI_BOOLEAN_FALSE); + } + return status; +} +static eHalStatus csrRoamSessionOpened(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo roamInfo; + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + status = csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_SESSION_OPENED, eCSR_ROAM_RESULT_NONE); + return (status); +} +eHalStatus csrProcessAddStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tSirSmeAddStaSelfRsp *pRsp; + do + { + if(pMsg == NULL) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + break; + } + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if(pEntry) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if(eSmeCommandAddStaSession == pCommand->command) + { + pRsp = (tSirSmeAddStaSelfRsp*)pMsg; + smsLog( pMac, LOG1, "Add Sta rsp status = %d", pRsp->status ); + //Nothing to be done. May be indicate the self sta addition success by calling session callback (TODO). + csrRoamSessionOpened(pMac, pCommand->sessionId); + //Remove this command out of the active list + if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK)) + { + /* Now put this command back on the available command list */ + csrReleaseCommand(pMac, pCommand); + } + smeProcessPendingQueue( pMac ); + } + else + { + smsLog(pMac, LOGE, "in %s eWNI_SME_ADD_STA_SELF_RSP Received but NO Add sta session command are ACTIVE ...", + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + } + else + { + smsLog(pMac, LOGE, "in %s eWNI_SME_ADD_STA_SELF_RSP Received but NO commands are ACTIVE ...", + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + } while(0); + return status; +} +/** + * csr_get_vdev_type_nss() - gets the nss value based on vdev type + * + * @mac_ctx: Pointer to Global MAC structure + * @dev_mode: current device operating mode. + * @nss2g: Pointer to the 2G Nss parameter. + * @nss5g: Pointer to the 5G Nss parameter. + * + * Fills the 2G and 5G Nss values based on device mode. + * + * Return: None + */ +void csr_get_vdev_type_nss(tpAniSirGlobal mac_ctx, tVOS_CON_MODE dev_mode, + uint8_t *nss_2g, uint8_t *nss_5g) +{ + switch (dev_mode) { + case VOS_STA_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.sta; + *nss_5g = mac_ctx->vdev_type_nss_5g.sta; + break; + case VOS_STA_SAP_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.sap; + *nss_5g = mac_ctx->vdev_type_nss_5g.sap; + break; + case VOS_P2P_CLIENT_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.p2p_cli; + *nss_5g = mac_ctx->vdev_type_nss_5g.p2p_cli; + break; + case VOS_P2P_GO_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.p2p_go; + *nss_5g = mac_ctx->vdev_type_nss_5g.p2p_go; + break; + case VOS_P2P_DEVICE_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.p2p_dev; + *nss_5g = mac_ctx->vdev_type_nss_5g.p2p_dev; + break; + case VOS_IBSS_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.ibss; + *nss_5g = mac_ctx->vdev_type_nss_5g.ibss; + break; + case VOS_OCB_MODE: + *nss_2g = mac_ctx->vdev_type_nss_2g.ocb; + *nss_5g = mac_ctx->vdev_type_nss_5g.ocb; + break; + default: + *nss_2g = 2; + *nss_5g = 2; + break; + } + smsLog(mac_ctx, LOG1, FL("mode - %d: nss_2g - %d, 5g - %d"), + dev_mode, *nss_2g, *nss_5g); +} +eHalStatus csrSendMBAddSelfStaReqMsg( tpAniSirGlobal pMac, + tAddStaForSessionCmd *pAddStaReq, + tANI_U8 sessionId) +{ + tSirSmeAddStaSelfReq *pMsg; + tANI_U16 msgLen; + eHalStatus status = eHAL_STATUS_FAILURE; + uint8_t nss_2g; + uint8_t nss_5g; + do { + msgLen = sizeof(tSirSmeAddStaSelfReq); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) break; + vos_mem_set(pMsg, msgLen, 0); + csr_get_vdev_type_nss(pMac, pAddStaReq->currDeviceMode, &nss_2g, &nss_5g); + pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ADD_STA_SELF_REQ); + pMsg->mesgLen = pal_cpu_to_be16(msgLen); + // self station address + vos_mem_copy((tANI_U8 *)pMsg->selfMacAddr, + (tANI_U8 *)&pAddStaReq->selfMacAddr, sizeof(tSirMacAddr)); + + pMsg->currDeviceMode = pAddStaReq->currDeviceMode; + pMsg->type = pAddStaReq->type; + pMsg->subType = pAddStaReq->subType; + pMsg->sessionId = sessionId; + pMsg->pkt_err_disconn_th = pMac->roam.configParam.pkt_err_disconn_th; + pMsg->nss_2g = nss_2g; + pMsg->nss_5g = nss_5g; + smsLog( pMac, LOG1, FL("selfMac="MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMsg->selfMacAddr)); + status = palSendMBMessage(pMac->hHdd, pMsg); + } while( 0 ); + return( status ); +} + +eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr sessionMacAddr, + tANI_U32 type, tANI_U32 subType) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + status = eHAL_STATUS_RESOURCES; + } + else + { + pCommand->command = eSmeCommandAddStaSession; + pCommand->sessionId = (tANI_U8)sessionId; + vos_mem_copy(pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr, + sizeof( tSirMacAddr ) ); + pCommand->u.addStaSessionCmd.currDeviceMode = pMac->sme.currDeviceMode; + pCommand->u.addStaSessionCmd.type = type; + pCommand->u.addStaSessionCmd.subType = subType; + status = csrQueueSmeCommand(pMac, pCommand, TRUE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + //Should be panic?? + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + } + } + return (status); +} +eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + return csrSendMBAddSelfStaReqMsg(pMac, + &pCommand->u.addStaSessionCmd, + pCommand->sessionId); +} +eHalStatus csrRoamOpenSession(tpAniSirGlobal pMac, + csrRoamCompleteCallback callback, + void *pContext, + tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId, + tANI_U32 type, tANI_U32 subType ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 i, value = 0; + union { + tANI_U16 nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + }uHTCapabilityInfo; + tCsrRoamSession *pSession; + *pbSessionId = CSR_SESSION_ID_INVALID; + + for( i = 0; i < pMac->sme.max_intf_count; i++ ) + { + if( !CSR_IS_SESSION_VALID( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + if (!pSession) + { + smsLog(pMac, LOGE, + FL("Session does not exist for interface %d"), i); + break; + } + status = eHAL_STATUS_SUCCESS; + pSession->sessionActive = eANI_BOOLEAN_TRUE; + pSession->sessionId = (tANI_U8)i; + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Initialize FT related data structures only in STA mode */ + sme_FTOpen(pMac, pSession->sessionId); +#endif + + pSession->callback = callback; + pSession->pContext = pContext; + vos_mem_copy(&pSession->selfMacAddr, pSelfMacAddr, + sizeof(tCsrBssid)); + *pbSessionId = (tANI_U8)i; + status = vos_timer_init(&pSession->hTimerRoaming, VOS_TIMER_TYPE_SW, + csrRoamRoamingTimerHandler, + &pSession->roamingTimerInfo); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + FL("cannot allocate memory for Roaming timer")); + break; + } + /* get the HT capability info*/ + status = ccmCfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &value); + if (!HAL_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: could not get HT capability info", + __func__); + break; + } + + uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; + pSession->htConfig.ht_rx_ldpc = + uHTCapabilityInfo.htCapInfo.advCodingCap; + pSession->htConfig.ht_tx_stbc = uHTCapabilityInfo.htCapInfo.txSTBC; + pSession->htConfig.ht_rx_stbc = uHTCapabilityInfo.htCapInfo.rxSTBC; + pSession->htConfig.ht_sgi = VOS_TRUE; + status = csrIssueAddStaForSessionReq ( pMac, i, pSelfMacAddr, type, + subType ); + break; + } + } + if( pMac->sme.max_intf_count == i ) + { + //No session is available + smsLog(pMac, LOGE, + "%s: Reached max interfaces: %d! Session creation will fail", + __func__, pMac->sme.max_intf_count); + status = eHAL_STATUS_RESOURCES; + } + return ( status ); +} + +eHalStatus csrProcessDelStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tSirSmeDelStaSelfRsp *pRsp; + do + { + if(pMsg == NULL) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + break; + } + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if(pEntry) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if(eSmeCommandDelStaSession == pCommand->command) + { + tANI_U8 sessionId = pCommand->sessionId; + pRsp = (tSirSmeDelStaSelfRsp*)pMsg; + smsLog( pMac, LOG1, "Del Sta rsp status = %d", pRsp->status ); + //This session is done. + csrCleanupSession(pMac, sessionId); + if(pCommand->u.delStaSessionCmd.callback) + { + + status = sme_ReleaseGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pCommand->u.delStaSessionCmd.callback( + pCommand->u.delStaSessionCmd.pContext); + status = sme_AcquireGlobalLock( &pMac->sme ); + if (! HAL_STATUS_SUCCESS( status ) ) + { + smsLog(pMac, LOGP, "%s: Failed to Acquire Lock", __func__); + return status; + } + } + else { + smsLog(pMac, LOGE, "%s: Failed to Release Lock", __func__); + } + } + + //Remove this command out of the active list + if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK)) + { + /* Now put this command back on the available command list */ + csrReleaseCommand(pMac, pCommand); + } + smeProcessPendingQueue( pMac ); + } + else + { + smsLog(pMac, LOGE, "in %s eWNI_SME_DEL_STA_SELF_RSP Received but NO Del sta session command are ACTIVE ...", + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + } + else + { + smsLog(pMac, LOGE, "in %s eWNI_SME_DEL_STA_SELF_RSP Received but NO commands are ACTIVE ...", + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + } while(0); + return status; +} +eHalStatus csrSendMBDelSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr, + tANI_U8 sessionId) +{ + tSirSmeDelStaSelfReq *pMsg; + tANI_U16 msgLen; + eHalStatus status = eHAL_STATUS_FAILURE; + do { + msgLen = sizeof(tSirSmeDelStaSelfReq); + pMsg = vos_mem_malloc(msgLen); + if (NULL == pMsg) + return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, msgLen, 0); + + pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEL_STA_SELF_REQ); + pMsg->mesgLen = pal_cpu_to_be16(msgLen); + pMsg->sessionId = sessionId; + // self station address + vos_mem_copy((tANI_U8 *)pMsg->selfMacAddr, (tANI_U8 *)macAddr, + sizeof(tSirMacAddr)); + status = palSendMBMessage(pMac->hHdd, pMsg); + } while( 0 ); + return( status ); +} +eHalStatus csrIssueDelStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr sessionMacAddr, + csrRoamSessionCloseCallback callback, + void *pContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + pCommand = csrGetCommandBuffer(pMac); + if(NULL == pCommand) + { + status = eHAL_STATUS_RESOURCES; + } + else + { + pCommand->command = eSmeCommandDelStaSession; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.delStaSessionCmd.callback = callback; + pCommand->u.delStaSessionCmd.pContext = pContext; + vos_mem_copy(pCommand->u.delStaSessionCmd.selfMacAddr, sessionMacAddr, + sizeof( tSirMacAddr )); + status = csrQueueSmeCommand(pMac, pCommand, TRUE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + //Should be panic?? + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + } + } + return (status); +} +eHalStatus csrProcessDelStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + return csrSendMBDelSelfStaReqMsg( pMac, + pCommand->u.delStaSessionCmd.selfMacAddr, + (tANI_U8)pCommand->sessionId); +} +static void purgeCsrSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tDblLinkList *pList = &pMac->roam.roamCmdPendingList; + tListElem *pEntry, *pNext; + tSmeCmd *pCommand; + tDblLinkList localList; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return; + } + csrLLLock(pList); + pEntry = csrLLPeekHead(pList, LL_ACCESS_NOLOCK); + while(pEntry != NULL) + { + pNext = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if(pCommand->sessionId == sessionId) + { + if(csrLLRemoveEntry(pList, pEntry, LL_ACCESS_NOLOCK)) + { + csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK); + } + } + pEntry = pNext; + } + csrLLUnlock(pList); + + while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + csrAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + } + csrLLClose(&localList); +} + +void csrCleanupSession(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + csrRoamStop(pMac, sessionId); + + /* Clean up FT related data structures */ +#if defined WLAN_FEATURE_VOWIFI_11R + sme_FTClose(pMac, sessionId); +#endif + csrFreeConnectBssDesc(pMac, sessionId); + csrRoamFreeConnectProfile( pMac, &pSession->connectedProfile ); + csrRoamFreeConnectedInfo ( pMac, &pSession->connectedInfo); + vos_timer_destroy(&pSession->hTimerRoaming); + purgeSmeSessionCmdList(pMac, sessionId, &pMac->sme.smeCmdPendingList); + if (pMac->fScanOffload) + { + purgeSmeSessionCmdList(pMac, sessionId, + &pMac->sme.smeScanCmdPendingList); + } + + purgeCsrSessionCmdList(pMac, sessionId); + csrInitSession(pMac, sessionId); + } +} + +eHalStatus csrRoamCloseSession( tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_BOOLEAN fSync, + csrRoamSessionCloseCallback callback, + void *pContext ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if(fSync) + { + csrCleanupSession(pMac, sessionId); + } + else + { + purgeSmeSessionCmdList(pMac, sessionId, + &pMac->sme.smeCmdPendingList); + if (pMac->fScanOffload) + { + purgeSmeSessionCmdList(pMac, sessionId, + &pMac->sme.smeScanCmdPendingList); + } + purgeCsrSessionCmdList(pMac, sessionId); + status = csrIssueDelStaForSessionReq( pMac, sessionId, + pSession->selfMacAddr, callback, pContext); + } + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + return ( status ); +} + +static void csrInitSession( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + pSession->sessionActive = eANI_BOOLEAN_FALSE; + pSession->sessionId = CSR_SESSION_ID_INVALID; + pSession->callback = NULL; + pSession->pContext = NULL; + pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + csrFreeRoamProfile( pMac, sessionId ); + csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile); + csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo ); + csrFreeConnectBssDesc(pMac, sessionId); + csrScanEnable(pMac); + vos_mem_set(&pSession->selfMacAddr, sizeof(tCsrBssid), 0); + if (pSession->pWpaRsnReqIE) + { + vos_mem_free(pSession->pWpaRsnReqIE); + pSession->pWpaRsnReqIE = NULL; + } + pSession->nWpaRsnReqIeLength = 0; + if (pSession->pWpaRsnRspIE) + { + vos_mem_free(pSession->pWpaRsnRspIE); + pSession->pWpaRsnRspIE = NULL; + } + pSession->nWpaRsnRspIeLength = 0; +#ifdef FEATURE_WLAN_WAPI + if (pSession->pWapiReqIE) + { + vos_mem_free(pSession->pWapiReqIE); + pSession->pWapiReqIE = NULL; + } + pSession->nWapiReqIeLength = 0; + if (pSession->pWapiRspIE) + { + vos_mem_free(pSession->pWapiRspIE); + pSession->pWapiRspIE = NULL; + } + pSession->nWapiRspIeLength = 0; +#endif /* FEATURE_WLAN_WAPI */ + if (pSession->pAddIEScan) + { + vos_mem_free(pSession->pAddIEScan); + pSession->pAddIEScan = NULL; + } + pSession->nAddIEScanLength = 0; + if (pSession->pAddIEAssoc) + { + vos_mem_free(pSession->pAddIEAssoc); + pSession->pAddIEAssoc = NULL; + } + pSession->nAddIEAssocLength = 0; +} + +eHalStatus csrRoamGetSessionIdFromBSSID( tpAniSirGlobal pMac, tCsrBssid *bssid, tANI_U32 *pSessionId ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_U32 i; + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) ) + { + if( csrIsMacAddressEqual( pMac, bssid, &pMac->roam.roamSession[i].connectedProfile.bssid ) ) + { + //Found it + status = eHAL_STATUS_SUCCESS; + *pSessionId = i; + break; + } + } + } + return( status ); +} + +//This function assumes that we only support one IBSS session. We cannot use BSSID to identify +//session because for IBSS, the bssid changes. +static tANI_U32 csrFindIbssSession( tpAniSirGlobal pMac ) +{ + tANI_U32 i, nRet = CSR_SESSION_ID_INVALID; + tCsrRoamSession *pSession; + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + if( pSession->pCurRoamProfile && ( csrIsBssTypeIBSS( pSession->connectedProfile.BSSType ) ) ) + { + //Found it + nRet = i; + break; + } + } + } + return (nRet); +} +static void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid) +{ + /* Update the current BSS info in ho control block based on connected + profile info from pmac global structure */ + + smsLog(pMac, LOGW, " csrRoamLinkUp: WLAN link UP with AP= "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssid)); + /* Check for user misconfig of RSSI trigger threshold */ + pMac->roam.configParam.vccRssiThreshold = + ( 0 == pMac->roam.configParam.vccRssiThreshold ) ? + CSR_VCC_RSSI_THRESHOLD : pMac->roam.configParam.vccRssiThreshold; + pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; + /* Check for user misconfig of UL MAC Loss trigger threshold */ + pMac->roam.configParam.vccUlMacLossThreshold = + ( 0 == pMac->roam.configParam.vccUlMacLossThreshold ) ? + CSR_VCC_UL_MAC_LOSS_THRESHOLD : pMac->roam.configParam.vccUlMacLossThreshold; +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + { + tANI_U32 sessionId = 0; + /* Indicate the neighbor roam algorithm about the connect indication */ + csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssid, &sessionId); + csrNeighborRoamIndicateConnect(pMac, sessionId, VOS_STATUS_SUCCESS); + } +#endif +} + +static void csrRoamLinkDown(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + //Only to handle the case for Handover on infra link + if( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType ) + { + return; + } + /* + * In-case of station mode, immediately stop data transmission whenever + * link down is detected. + */ + if (csrRoamIsStaMode(pMac, sessionId) + && !CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId) +#ifdef WLAN_FEATURE_VOWIFI_11R + && !csrRoamIs11rAssoc(pMac, sessionId) +#endif + ) { + smsLog(pMac, LOG1, FL("Inform Link lost for session %d"), sessionId); + csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_LOSTLINK, + eCSR_ROAM_RESULT_LOSTLINK); + } + /* deregister the clients requesting stats from PE/TL & also stop the corresponding timers*/ + csrRoamDeregStatisticsReq(pMac); + pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + /* Indicate the neighbor roam algorithm about the disconnect indication */ + csrNeighborRoamIndicateDisconnect(pMac, sessionId); +#endif + + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && + csrIsInfraApStarted( pMac ) && + pMac->roam.configParam.doBMPSWorkaround) + { + pMac->roam.configParam.doBMPSWorkaround = 0; + } + + if(pMac->psOffloadEnabled) + pmcOffloadCleanup(pMac, sessionId); + +} + +void csrRoamTlStatsTimerHandler(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + eHalStatus status; + pMac->roam.tlStatsReqInfo.timerRunning = FALSE; + + smsLog(pMac, LOG1, FL(" TL stat timer is no-op. It needs to support multiple stations")); + + if(!pMac->roam.tlStatsReqInfo.timerRunning) + { + if(pMac->roam.tlStatsReqInfo.periodicity) + { + //start timer + status = vos_timer_start(&pMac->roam.tlStatsReqInfo.hTlStatsTimer, + pMac->roam.tlStatsReqInfo.periodicity); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrRoamTlStatsTimerHandler:cannot start TlStatsTimer timer")); + return; + } + pMac->roam.tlStatsReqInfo.timerRunning = TRUE; + } + } +} +void csrRoamPeStatsTimerHandler(void *pv) +{ + tCsrPeStatsReqInfo *pPeStatsReqListEntry = (tCsrPeStatsReqInfo *)pv; + eHalStatus status; + tpAniSirGlobal pMac = pPeStatsReqListEntry->pMac; + VOS_STATUS vosStatus; + tPmcPowerState powerState; + pPeStatsReqListEntry->timerRunning = FALSE; + if( pPeStatsReqListEntry->timerStopFailed == TRUE ) + { + // If we entered here, meaning the timer could not be successfully + // stopped in csrRoamRemoveEntryFromPeStatsReqList(). So do it here. + + /* Destroy the timer */ + vosStatus = vos_timer_destroy( &pPeStatsReqListEntry->hPeStatsTimer ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:failed to destroy hPeStatsTimer timer")); + } + + // Free the entry + vos_mem_free(pPeStatsReqListEntry); + pPeStatsReqListEntry = NULL; + } + else + { + if(!pPeStatsReqListEntry->rspPending) + { + status = csrSendMBStatsReqMsg(pMac, pPeStatsReqListEntry->statsMask & ~(1 << eCsrGlobalClassDStats), + pPeStatsReqListEntry->staId, + pPeStatsReqListEntry->sessionId); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:failed to send down stats req to PE")); + } + else + { + pPeStatsReqListEntry->rspPending = TRUE; + } + } + + //send down a req + if(pPeStatsReqListEntry->periodicity && + (VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pPeStatsReqListEntry->hPeStatsTimer))) + { + pmcQueryPowerState(pMac, &powerState, NULL, NULL); + if(ePMC_FULL_POWER == powerState) + { + if(pPeStatsReqListEntry->periodicity < pMac->roam.configParam.statsReqPeriodicity) + { + pPeStatsReqListEntry->periodicity = pMac->roam.configParam.statsReqPeriodicity; + } + } + else + { + if(pPeStatsReqListEntry->periodicity < pMac->roam.configParam.statsReqPeriodicityInPS) + { + pPeStatsReqListEntry->periodicity = pMac->roam.configParam.statsReqPeriodicityInPS; + } + } + //start timer + vosStatus = vos_timer_start( &pPeStatsReqListEntry->hPeStatsTimer, pPeStatsReqListEntry->periodicity ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:cannot start hPeStatsTimer timer")); + return; + } + pPeStatsReqListEntry->timerRunning = TRUE; + + } + + } +} +void csrRoamStatsClientTimerHandler(void *pv) +{ + tCsrStatsClientReqInfo *pStaEntry = (tCsrStatsClientReqInfo *)pv; + if (VOS_TIMER_STATE_STOPPED == + vos_timer_getCurrentState(&pStaEntry->timer)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("roam stats client timer is stopped")); + } +} + + + +eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, + tANI_U8 staId, tANI_U8 sessionId) +{ + tAniGetPEStatsReq *pMsg; + eHalStatus status = eHAL_STATUS_SUCCESS; + pMsg = vos_mem_malloc(sizeof(tAniGetPEStatsReq)); + if ( NULL == pMsg ) + { + smsLog(pMac, LOGE, FL( "Failed to allocate mem for stats req ")); + return eHAL_STATUS_FAILURE; + } + // need to initiate a stats request to PE + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_STATISTICS_REQ); + pMsg->msgLen = (tANI_U16)sizeof(tAniGetPEStatsReq); + pMsg->staId = staId; + pMsg->statsMask = statsMask; + pMsg->sessionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOG1, FL("Failed to send down the stats req ")); + } + return status; +} +void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) +{ + tAniGetPEStatsRsp *pSmeStatsRsp; + eHalStatus status = eHAL_STATUS_FAILURE; + tListElem *pEntry = NULL; + tCsrStatsClientReqInfo *pTempStaEntry = NULL; + tCsrPeStatsReqInfo *pPeStaEntry = NULL; + tANI_U32 tempMask = 0; + tANI_U8 counter = 0; + tANI_U8 *pStats = NULL; + tANI_U32 length = 0; + v_PVOID_t pvosGCtx; + v_S7_t rssi = 0, snr = 0; + tANI_U32 *pRssi = NULL, *pSnr = NULL; + tANI_U32 linkCapacity; + pSmeStatsRsp = (tAniGetPEStatsRsp *)pSirMsg; + if(pSmeStatsRsp->rc) + { + smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:stats rsp from PE shows failure")); + goto post_update; + } + tempMask = pSmeStatsRsp->statsMask; + pStats = ((tANI_U8 *)&pSmeStatsRsp->statsMask) + sizeof(pSmeStatsRsp->statsMask); + /* subtract all statistics from this length, and after processing the entire + * 'stat' part of the message, if the length is not zero, then rssi is piggy packed + * in this 'stats' message. + */ + length = pSmeStatsRsp->msgLen - sizeof(tAniGetPEStatsRsp); + /* New stats info from PE, fill up the stats structures in PMAC */ + while(tempMask) + { + if(tempMask & 1) + { + switch(counter) + { + case eCsrSummaryStats: + smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:summary stats")); + vos_mem_copy((tANI_U8 *)&pMac->roam.summaryStatsInfo, + pStats, sizeof(tCsrSummaryStatsInfo)); + pStats += sizeof(tCsrSummaryStatsInfo); + length -= sizeof(tCsrSummaryStatsInfo); + break; + case eCsrGlobalClassAStats: + smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:ClassA stats")); + vos_mem_copy((tANI_U8 *)&pMac->roam.classAStatsInfo, + pStats, sizeof(tCsrGlobalClassAStatsInfo)); + pStats += sizeof(tCsrGlobalClassAStatsInfo); + length -= sizeof(tCsrGlobalClassAStatsInfo); + break; + case eCsrGlobalClassBStats: + smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:ClassB stats")); + vos_mem_copy((tANI_U8 *)&pMac->roam.classBStatsInfo, + pStats, sizeof(tCsrGlobalClassBStatsInfo)); + pStats += sizeof(tCsrGlobalClassBStatsInfo); + length -= sizeof(tCsrGlobalClassBStatsInfo); + break; + case eCsrGlobalClassCStats: + smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:ClassC stats")); + vos_mem_copy((tANI_U8 *)&pMac->roam.classCStatsInfo, + pStats, sizeof(tCsrGlobalClassCStatsInfo)); + pStats += sizeof(tCsrGlobalClassCStatsInfo); + length -= sizeof(tCsrGlobalClassCStatsInfo); + break; + case eCsrPerStaStats: + smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:PerSta stats")); + if( CSR_MAX_STA > pSmeStatsRsp->staId ) + { + vos_mem_copy((tANI_U8 *)&pMac->roam.perStaStatsInfo[pSmeStatsRsp->staId], + pStats, sizeof(tCsrPerStaStatsInfo)); + } + else + { + status = eHAL_STATUS_FAILURE; + smsLog( pMac, LOGE, FL("csrRoamStatsRspProcessor:out bound staId:%d"), pSmeStatsRsp->staId); + VOS_ASSERT( 0 ); + } + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy PerSta stats")); + } + pStats += sizeof(tCsrPerStaStatsInfo); + length -= sizeof(tCsrPerStaStatsInfo); + break; + default: + smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:unknown stats type")); + break; + } + } + tempMask >>=1; + counter++; + } + pvosGCtx = vos_get_global_context(VOS_MODULE_ID_SME, pMac); + if (length != 0) + { + pRssi = (tANI_U32*)pStats; + rssi = (v_S7_t)*pRssi; + pStats += sizeof(tANI_U32); + length -= sizeof(tANI_U32); + } + else + { + /* If riva is not sending rssi, continue to use the hack */ + rssi = RSSI_HACK_BMPS; + } + + WDA_UpdateRssiBmps(pvosGCtx, pSmeStatsRsp->staId, rssi); + + if (length != 0) + { + linkCapacity = *(tANI_U32*)pStats; + pStats += sizeof(tANI_U32); + length -= sizeof(tANI_U32); + } + else + { + linkCapacity = 0; + } + + WDA_UpdateLinkCapacity(pvosGCtx, pSmeStatsRsp->staId, linkCapacity); + + if (length != 0) + { + pSnr = (tANI_U32*)pStats; + snr = (v_S7_t)*pSnr; + } + else + { + snr = SNR_HACK_BMPS; + } + + WDA_UpdateSnrBmps(pvosGCtx, pSmeStatsRsp->staId, snr); +post_update: + //make sure to update the pe stats req list + pEntry = csrRoamFindInPeStatsReqList(pMac, pSmeStatsRsp->statsMask); + if(pEntry) + { + pPeStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link ); + pPeStaEntry->rspPending = FALSE; + + } + //check the one timer cases + pEntry = csrRoamCheckClientReqList(pMac, pSmeStatsRsp->statsMask); + if(pEntry) + { + pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link ); + if(pTempStaEntry->timerExpired) + { + //send up the stats report + csrRoamReportStatistics(pMac, pTempStaEntry->statsMask, pTempStaEntry->callback, + pTempStaEntry->staId, pTempStaEntry->pContext); + //also remove from the client list + csrRoamRemoveStatListEntry(pMac, pEntry); + pTempStaEntry = NULL; + } + } +} +tListElem * csrRoamFindInPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask) +{ + tListElem *pEntry = NULL; + tCsrPeStatsReqInfo *pTempStaEntry = NULL; + pEntry = csrLLPeekHead( &pMac->roam.peStatsReqList, LL_ACCESS_LOCK ); + if(!pEntry) + { + //list empty + smsLog(pMac, LOG2, "csrRoamFindInPeStatsReqList: List empty, no request to PE"); + return NULL; + } + while( pEntry ) + { + pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link ); + if(pTempStaEntry->statsMask == statsMask) + { + smsLog(pMac, LOG3, "csrRoamFindInPeStatsReqList: match found"); + break; + } + pEntry = csrLLNext( &pMac->roam.peStatsReqList, pEntry, LL_ACCESS_NOLOCK ); + } + return pEntry; +} + +tListElem * csrRoamChecknUpdateClientReqList(tpAniSirGlobal pMac, tCsrStatsClientReqInfo *pStaEntry, + tANI_BOOLEAN update) +{ + tListElem *pEntry; + tCsrStatsClientReqInfo *pTempStaEntry; + pEntry = csrLLPeekHead( &pMac->roam.statsClientReqList, LL_ACCESS_LOCK ); + if(!pEntry) + { + //list empty + smsLog(pMac, LOG2, "csrRoamChecknUpdateClientReqList: List empty, no request from " + "upper layer client(s)"); + return NULL; + } + while( pEntry ) + { + pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link ); + if((pTempStaEntry->requesterId == pStaEntry->requesterId) && + (pTempStaEntry->statsMask == pStaEntry->statsMask)) + { + smsLog(pMac, LOG3, "csrRoamChecknUpdateClientReqList: match found"); + if(update) + { + pTempStaEntry->periodicity = pStaEntry->periodicity; + pTempStaEntry->callback = pStaEntry->callback; + pTempStaEntry->pContext = pStaEntry->pContext; + } + break; + } + pEntry = csrLLNext( &pMac->roam.statsClientReqList, pEntry, LL_ACCESS_NOLOCK ); + } + return pEntry; +} +tListElem * csrRoamCheckClientReqList(tpAniSirGlobal pMac, tANI_U32 statsMask) +{ + tListElem *pEntry; + tCsrStatsClientReqInfo *pTempStaEntry; + pEntry = csrLLPeekHead( &pMac->roam.statsClientReqList, LL_ACCESS_LOCK ); + if(!pEntry) + { + //list empty + smsLog(pMac, LOG2, "csrRoamCheckClientReqList: List empty, no request from " + "upper layer client(s)"); + return NULL; + } + while( pEntry ) + { + pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link ); + if((pTempStaEntry->statsMask & ~(1 << eCsrGlobalClassDStats)) == statsMask) + { + smsLog(pMac, LOG3, "csrRoamCheckClientReqList: match found"); + break; + } + pEntry = csrLLNext( &pMac->roam.statsClientReqList, pEntry, LL_ACCESS_NOLOCK ); + } + return pEntry; +} +eHalStatus csrRoamRegisterLinkQualityIndCallback(tpAniSirGlobal pMac, + csrRoamLinkQualityIndCallback callback, + void *pContext) +{ + pMac->roam.linkQualityIndInfo.callback = callback; + pMac->roam.linkQualityIndInfo.context = pContext; + if( NULL == callback ) + { + smsLog(pMac, LOGW, "csrRoamRegisterLinkQualityIndCallback: indication callback being deregistered"); + } + else + { + smsLog(pMac, LOGW, "csrRoamRegisterLinkQualityIndCallback: indication callback being registered"); + /* do we need to invoke the callback to notify client of initial value ?? */ + } + return eHAL_STATUS_SUCCESS; +} +void csrRoamVccTrigger(tpAniSirGlobal pMac) +{ + eCsrRoamLinkQualityInd newVccLinkQuality; + tANI_U32 ul_mac_loss = 0; + tANI_U32 ul_mac_loss_trigger_threshold; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /*------------------------------------------------------------------------- + Link quality is currently binary based on OBIWAN recommended triggers + Check for a change in link quality and notify client if necessary + -------------------------------------------------------------------------*/ + ul_mac_loss_trigger_threshold = + pMac->roam.configParam.vccUlMacLossThreshold; + if (0 == ul_mac_loss_trigger_threshold) + { + VOS_ASSERT( ul_mac_loss_trigger_threshold != 0 ); + return; + } + smsLog(pMac, LOGW, "csrRoamVccTrigger: UL_MAC_LOSS_THRESHOLD is %d", + ul_mac_loss_trigger_threshold ); + if(ul_mac_loss_trigger_threshold < ul_mac_loss) + { + smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality is POOR "); + newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; + } + else + { + smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality is GOOD"); + newVccLinkQuality = eCSR_ROAM_LINK_QUAL_GOOD_IND; + } + smsLog(pMac, LOGW, "csrRoamVccTrigger: link qual : *** UL_MAC_LOSS %d *** ", + ul_mac_loss); + if(newVccLinkQuality != pMac->roam.vccLinkQuality) + { + smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality changed: trigger necessary"); + if(NULL != pMac->roam.linkQualityIndInfo.callback) + { + smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality indication %d", + newVccLinkQuality ); + + /* we now invoke the callback once to notify client of initial value */ + pMac->roam.linkQualityIndInfo.callback( newVccLinkQuality, + pMac->roam.linkQualityIndInfo.context ); + //event: EVENT_WLAN_VCC + } + } + pMac->roam.vccLinkQuality = newVccLinkQuality; + +} +VOS_STATUS csrRoamVccTriggerRssiIndCallback(tHalHandle hHal, + v_U8_t rssiNotification, + void * context) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( context ); + eCsrRoamLinkQualityInd newVccLinkQuality; + tANI_U32 sessionId = 0; + VOS_STATUS status = VOS_STATUS_SUCCESS; + /*------------------------------------------------------------------------- + Link quality is currently binary based on OBIWAN recommended triggers + Check for a change in link quality and notify client if necessary + -------------------------------------------------------------------------*/ + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: RSSI trigger threshold is %d", + pMac->roam.configParam.vccRssiThreshold); + if(!csrIsConnStateConnectedInfra(pMac, sessionId)) + { + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: ignoring the indication as we are not connected"); + return VOS_STATUS_SUCCESS; + } + if(WLANTL_HO_THRESHOLD_DOWN == rssiNotification) + { + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality is POOR"); + newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; + } + else if(WLANTL_HO_THRESHOLD_UP == rssiNotification) + { + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality is GOOD "); + newVccLinkQuality = eCSR_ROAM_LINK_QUAL_GOOD_IND; + } + else + { + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: unknown rssi notification %d", rssiNotification); + //Set to this so the code below won't do anything + newVccLinkQuality = pMac->roam.vccLinkQuality; + VOS_ASSERT(0); + } + + if(newVccLinkQuality != pMac->roam.vccLinkQuality) + { + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality changed: trigger necessary"); + if(NULL != pMac->roam.linkQualityIndInfo.callback) + { + smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality indication %d", + newVccLinkQuality); + /* we now invoke the callback once to notify client of initial value */ + pMac->roam.linkQualityIndInfo.callback( newVccLinkQuality, + pMac->roam.linkQualityIndInfo.context ); + //event: EVENT_WLAN_VCC + } + } + pMac->roam.vccLinkQuality = newVccLinkQuality; + return status; +} +tCsrStatsClientReqInfo * csrRoamInsertEntryIntoList( tpAniSirGlobal pMac, + tDblLinkList *pStaList, + tCsrStatsClientReqInfo *pStaEntry) +{ + tCsrStatsClientReqInfo *pNewStaEntry = NULL; + //if same entity requested for same set of stats with different periodicity & + // callback update it + if(NULL == csrRoamChecknUpdateClientReqList(pMac, pStaEntry, TRUE)) + { + + pNewStaEntry = vos_mem_malloc(sizeof(tCsrStatsClientReqInfo)); + if (NULL == pNewStaEntry) + { + smsLog(pMac, LOGW, "csrRoamInsertEntryIntoList: couldn't allocate memory for the " + "entry"); + return NULL; + } + + pNewStaEntry->callback = pStaEntry->callback; + pNewStaEntry->pContext = pStaEntry->pContext; + pNewStaEntry->periodicity = pStaEntry->periodicity; + pNewStaEntry->requesterId = pStaEntry->requesterId; + pNewStaEntry->statsMask = pStaEntry->statsMask; + pNewStaEntry->pPeStaEntry = pStaEntry->pPeStaEntry; + pNewStaEntry->pMac = pStaEntry->pMac; + pNewStaEntry->staId = pStaEntry->staId; + pNewStaEntry->timerExpired = pStaEntry->timerExpired; + + csrLLInsertTail( pStaList, &pNewStaEntry->link, LL_ACCESS_LOCK ); + } + return pNewStaEntry; +} + +tCsrPeStatsReqInfo * csrRoamInsertEntryIntoPeStatsReqList( tpAniSirGlobal pMac, + tDblLinkList *pStaList, + tCsrPeStatsReqInfo *pStaEntry) +{ + tCsrPeStatsReqInfo *pNewStaEntry = NULL; + pNewStaEntry = vos_mem_malloc(sizeof(tCsrPeStatsReqInfo)); + if (NULL == pNewStaEntry) + { + smsLog(pMac, LOGW, "csrRoamInsertEntryIntoPeStatsReqList: couldn't allocate memory for the " + "entry"); + return NULL; + } + + pNewStaEntry->hPeStatsTimer = pStaEntry->hPeStatsTimer; + pNewStaEntry->numClient = pStaEntry->numClient; + pNewStaEntry->periodicity = pStaEntry->periodicity; + pNewStaEntry->statsMask = pStaEntry->statsMask; + pNewStaEntry->pMac = pStaEntry->pMac; + pNewStaEntry->staId = pStaEntry->staId; + pNewStaEntry->timerRunning = pStaEntry->timerRunning; + pNewStaEntry->rspPending = pStaEntry->rspPending; + + csrLLInsertTail( pStaList, &pNewStaEntry->link, LL_ACCESS_LOCK ); + return pNewStaEntry; +} +eHalStatus csrGetRssi(tpAniSirGlobal pMac, + tCsrRssiCallback callback, + tANI_U8 staId, + tCsrBssid bssId, + tANI_S8 lastRSSI, + void *pContext, + void* pVosContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + vos_msg_t msg; + tANI_U32 sessionId; + + tAniGetRssiReq *pMsg; + smsLog(pMac, LOG2, FL("called")); + + status = csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssId, &sessionId); + if (!HAL_STATUS_SUCCESS(status)) + { + callback(lastRSSI, staId, pContext); + smsLog(pMac, LOGE, FL("Failed to get SessionId")); + return eHAL_STATUS_FAILURE; + } + + pMsg = vos_mem_malloc(sizeof(tAniGetRssiReq)); + if ( NULL == pMsg ) + { + smsLog(pMac, LOGE, " csrGetRssi: failed to allocate mem for req "); + return eHAL_STATUS_FAILURE; + } + + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_RSSI_REQ); + pMsg->msgLen = (tANI_U16)sizeof(tAniGetRssiReq); + pMsg->sessionId = sessionId; + pMsg->staId = staId; + pMsg->rssiCallback = callback; + pMsg->pDevContext = pContext; + pMsg->pVosContext = pVosContext; + /* + * store RSSI at time of calling, so that if RSSI request cannot + * be sent to firmware, this value can be used to return immediately + */ + pMsg->lastRSSI = lastRSSI; + msg.type = eWNI_SME_GET_RSSI_REQ; + msg.bodyptr = pMsg; + msg.reserved = 0; + if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg)) + { + smsLog(pMac, LOGE, " csrGetRssi failed to post msg to self "); + vos_mem_free((void *)pMsg); + status = eHAL_STATUS_FAILURE; + } + smsLog(pMac, LOG2, FL("returned")); + return status; +} + +eHalStatus csrGetSnr(tpAniSirGlobal pMac, + tCsrSnrCallback callback, + tANI_U8 staId, tCsrBssid bssId, + void *pContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + vos_msg_t msg; + tANI_U32 sessionId; + + tAniGetSnrReq *pMsg; + + smsLog(pMac, LOG2, FL("called")); + + pMsg =(tAniGetSnrReq *)vos_mem_malloc(sizeof(tAniGetSnrReq)); + if (NULL == pMsg ) + { + smsLog(pMac, LOGE, "%s: failed to allocate mem for req",__func__); + return status; + } + + csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssId, &sessionId); + + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_SNR_REQ); + pMsg->msgLen = (tANI_U16)sizeof(tAniGetSnrReq); + pMsg->sessionId = sessionId; + pMsg->staId = staId; + pMsg->snrCallback = callback; + pMsg->pDevContext = pContext; + msg.type = eWNI_SME_GET_SNR_REQ; + msg.bodyptr = pMsg; + msg.reserved = 0; + + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg)) + { + smsLog(pMac, LOGE, "%s failed to post msg to self", __func__); + vos_mem_free((v_VOID_t *)pMsg); + status = eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOG2, FL("returned")); + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +eHalStatus csrGetTsmStats(tpAniSirGlobal pMac, + tCsrTsmStatsCallback callback, + tANI_U8 staId, + tCsrBssid bssId, + void *pContext, + void* pVosContext, + tANI_U8 tid) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tAniGetTsmStatsReq *pMsg = NULL; + pMsg = vos_mem_malloc(sizeof(tAniGetTsmStatsReq)); + if (!pMsg) + { + smsLog(pMac, LOGE, "csrGetTsmStats: failed to allocate mem for req"); + return status; + } + // need to initiate a stats request to PE + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_TSM_STATS_REQ); + pMsg->msgLen = (tANI_U16)sizeof(tAniGetTsmStatsReq); + pMsg->staId = staId; + pMsg->tid = tid; + vos_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + pMsg->tsmStatsCallback = callback; + pMsg->pDevContext = pContext; + pMsg->pVosContext = pVosContext; + status = palSendMBMessage(pMac->hHdd, pMsg ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOG1, " csrGetTsmStats: failed to send down the rssi req"); + //pMsg is freed by palSendMBMessage + status = eHAL_STATUS_FAILURE; + } + return status; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/* --------------------------------------------------------------------------- + \fn csrGetTLSTAState + \helper function to get the TL STA State whenever the function is called. + + \param staId - The staID to be passed to the TL + to get the relevant TL STA State + \return the state as tANI_U16 + ---------------------------------------------------------------------------*/ +tANI_U16 csrGetTLSTAState(tpAniSirGlobal pMac, tANI_U8 staId) +{ + WLANTL_STAStateType tlSTAState; + tlSTAState = WLANTL_STA_INIT; + + //request TL for STA State + if ( !VOS_IS_STATUS_SUCCESS(WLANTL_GetSTAState(pMac->roam.gVosContext, staId, &tlSTAState)) ) + { + smsLog(pMac, LOGE, FL("csrGetTLSTAState:couldn't get the STA state from TL")); + } + + return tlSTAState; +} + +eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requesterId, + tANI_U32 statsMask, + tCsrStatsCallback callback, + tANI_U32 periodicity, tANI_BOOLEAN cache, + tANI_U8 staId, void *pContext, + tANI_U8 sessionId) +{ + tCsrStatsClientReqInfo staEntry; + tCsrStatsClientReqInfo *pStaEntry = NULL; + tCsrPeStatsReqInfo *pPeStaEntry = NULL; + tListElem *pEntry = NULL; + tANI_BOOLEAN found = FALSE; + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN insertInClientList = FALSE; + VOS_STATUS vosStatus; + WLANTL_TRANSFER_STA_TYPE *pTlStats; + + if( csrIsAllSessionDisconnected(pMac) ) + { + //smsLog(pMac, LOGW, "csrGetStatistics: wrong state curState(%d) not connected", pMac->roam.curState); + return eHAL_STATUS_FAILURE; + } + + if (csrNeighborMiddleOfRoaming((tHalHandle)pMac, sessionId)) + { + smsLog(pMac, LOG1, FL("in the middle of roaming states")); + return eHAL_STATUS_FAILURE; + } + + if((!statsMask) && (!callback)) + { + //msg + smsLog(pMac, LOGW, "csrGetStatistics: statsMask & callback empty in the request"); + return eHAL_STATUS_FAILURE; + } + //for the search list method for deregister + staEntry.requesterId = requesterId; + staEntry.statsMask = statsMask; + //requester wants to deregister or just an error + if((statsMask) && (!callback)) + { + pEntry = csrRoamChecknUpdateClientReqList(pMac, &staEntry, FALSE); + if(!pEntry) + { + //msg + smsLog(pMac, LOGW, "csrGetStatistics: callback is empty in the request & couldn't " + "find any existing request in statsClientReqList"); + return eHAL_STATUS_FAILURE; + } + else + { + //clean up & return + pStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link ); + if(NULL != pStaEntry->pPeStaEntry) + { + pStaEntry->pPeStaEntry->numClient--; + //check if we need to delete the entry from peStatsReqList too + if(!pStaEntry->pPeStaEntry->numClient) + { + csrRoamRemoveEntryFromPeStatsReqList(pMac, pStaEntry->pPeStaEntry); + } + } + + //check if we need to stop the tl stats timer too + pMac->roam.tlStatsReqInfo.numClient--; + if(!pMac->roam.tlStatsReqInfo.numClient) + { + if(pMac->roam.tlStatsReqInfo.timerRunning) + { + status = vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:cannot stop TlStatsTimer timer")); + return eHAL_STATUS_FAILURE; + } + } + pMac->roam.tlStatsReqInfo.periodicity = 0; + pMac->roam.tlStatsReqInfo.timerRunning = FALSE; + } + vos_timer_stop( &pStaEntry->timer ); + // Destroy the vos timer... + vosStatus = vos_timer_destroy( &pStaEntry->timer ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:failed to destroy Client req timer")); + } + csrRoamRemoveStatListEntry(pMac, pEntry); + pStaEntry = NULL; + return eHAL_STATUS_SUCCESS; + } + } + + if(cache && !periodicity) + { + //return the cached stats + csrRoamReportStatistics(pMac, statsMask, callback, staId, pContext); + } + else + { + //add the request in the client req list + staEntry.callback = callback; + staEntry.pContext = pContext; + staEntry.periodicity = periodicity; + staEntry.pPeStaEntry = NULL; + staEntry.staId = staId; + staEntry.pMac = pMac; + staEntry.timerExpired = FALSE; + staEntry.sessionId = sessionId; + + + //if periodic report requested with non cached result from PE/TL + if(periodicity) + { + + //if looking for stats from PE + if(statsMask & ~(1 << eCsrGlobalClassDStats)) + { + + //check if same request made already & waiting for rsp + pPeStaEntry = csrRoamCheckPeStatsReqList(pMac, statsMask & ~(1 << eCsrGlobalClassDStats), + periodicity, &found, staId, + sessionId); + if(!pPeStaEntry) + { + //bail out, maxed out on number of req for PE + return eHAL_STATUS_FAILURE; + } + else + { + staEntry.pPeStaEntry = pPeStaEntry; + } + + } + /* request stats from TL right away if requested by client, + update tlStatsReqInfo if needed */ + if(statsMask & (1 << eCsrGlobalClassDStats)) + { + if(cache && pMac->roam.tlStatsReqInfo.numClient) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:Looking for cached stats from TL")); + } + else + { + + //update periodicity + if(pMac->roam.tlStatsReqInfo.periodicity) + { + pMac->roam.tlStatsReqInfo.periodicity = + CSR_ROAM_MIN(periodicity, pMac->roam.tlStatsReqInfo.periodicity); + } + else + { + pMac->roam.tlStatsReqInfo.periodicity = periodicity; + } + if(pMac->roam.tlStatsReqInfo.periodicity < CSR_MIN_TL_STAT_QUERY_PERIOD) + { + pMac->roam.tlStatsReqInfo.periodicity = CSR_MIN_TL_STAT_QUERY_PERIOD; + } + + if(!pMac->roam.tlStatsReqInfo.timerRunning) + { + pTlStats = (WLANTL_TRANSFER_STA_TYPE *)vos_mem_malloc(sizeof(WLANTL_TRANSFER_STA_TYPE)); + if (NULL != pTlStats) + { + //req TL for class D stats + if(WLANTL_GetStatistics(pMac->roam.gVosContext, pTlStats, staId)) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:couldn't get the stats from TL")); + } + else + { + //save in SME + csrRoamSaveStatsFromTl(pMac, pTlStats); + } + vos_mem_free(pTlStats); + pTlStats = NULL; + } + else + { + smsLog(pMac, LOGE, FL("cannot allocate memory for TL stat")); + } + + if(pMac->roam.tlStatsReqInfo.periodicity) + { + //start timer + status = vos_timer_start(&pMac->roam.tlStatsReqInfo.hTlStatsTimer, + pMac->roam.tlStatsReqInfo.periodicity); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:cannot start TlStatsTimer timer")); + return eHAL_STATUS_FAILURE; + } + pMac->roam.tlStatsReqInfo.timerRunning = TRUE; + } + } + } + pMac->roam.tlStatsReqInfo.numClient++; + } + + insertInClientList = TRUE; + } + //if one time report requested with non cached result from PE/TL + else if(!cache && !periodicity) + { + if(statsMask & ~(1 << eCsrGlobalClassDStats)) + { + //send down a req + status = csrSendMBStatsReqMsg(pMac, + statsMask & ~(1 << eCsrGlobalClassDStats), + staId, + sessionId); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:failed to send down stats req to PE")); + } + //so that when the stats rsp comes back from PE we respond to upper layer + //right away + staEntry.timerExpired = TRUE; + insertInClientList = TRUE; + } + if(statsMask & (1 << eCsrGlobalClassDStats)) + { + pTlStats = (WLANTL_TRANSFER_STA_TYPE *)vos_mem_malloc(sizeof(WLANTL_TRANSFER_STA_TYPE)); + if (NULL != pTlStats) + { + //req TL for class D stats + if(!VOS_IS_STATUS_SUCCESS(WLANTL_GetStatistics(pMac->roam.gVosContext, pTlStats, staId))) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:couldn't get the stats from TL")); + } + else + { + //save in SME + csrRoamSaveStatsFromTl(pMac, pTlStats); + } + vos_mem_free(pTlStats); + pTlStats = NULL; + } + else + { + smsLog(pMac, LOGE, FL("cannot allocate memory for TL stat")); + } + + } + //if looking for stats from TL only + if(!insertInClientList) + { + //return the stats + csrRoamReportStatistics(pMac, statsMask, callback, staId, pContext); + } + } + if(insertInClientList) + { + pStaEntry = csrRoamInsertEntryIntoList(pMac, &pMac->roam.statsClientReqList, &staEntry); + if(!pStaEntry) + { + //msg + smsLog(pMac, LOGW, "csrGetStatistics: Failed to insert req in statsClientReqList"); + return eHAL_STATUS_FAILURE; + } + pStaEntry->periodicity = periodicity; + //Init & start timer if needed + if(periodicity) + { + vosStatus = vos_timer_init( &pStaEntry->timer, VOS_TIMER_TYPE_SW, + csrRoamStatsClientTimerHandler, pStaEntry ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:cannot init StatsClient timer")); + return eHAL_STATUS_FAILURE; + } + vosStatus = vos_timer_start( &pStaEntry->timer, periodicity ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrGetStatistics:cannot start StatsClient timer")); + return eHAL_STATUS_FAILURE; + } + } + } + } + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +static tSirRetStatus +csrRoamScanOffloadPopulateMacHeader(tpAniSirGlobal pMac, + tANI_U8* pBD, + tANI_U8 type, + tANI_U8 subType, + tSirMacAddr peerAddr, + tSirMacAddr selfMacAddr) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tpSirMacMgmtHdr pMacHdr; + + /* Prepare MAC management header */ + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + /* Prepare FC */ + pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + pMacHdr->fc.type = type; + pMacHdr->fc.subType = subType; + + /* Prepare Address 1 */ + vos_mem_copy((tANI_U8 *) pMacHdr->da, (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + + sirCopyMacAddr(pMacHdr->sa,selfMacAddr); + + /* Prepare Address 3 */ + vos_mem_copy((tANI_U8 *) pMacHdr->bssId, (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + return statusCode; +} /*** csrRoamScanOffloadPopulateMacHeader() ***/ + +static tSirRetStatus +csrRoamScanOffloadPrepareProbeReqTemplate(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tANI_U32 dot11mode, + tSirMacAddr selfMacAddr, + tANI_U8 *pFrame, + tANI_U16 *pusLen, + tCsrRoamSession *psession) +{ + tDot11fProbeRequest pr; + tANI_U32 nStatus, nBytes, nPayload; + tSirRetStatus nSirStatus; + /*Bcast tx*/ + tSirMacAddr bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + + vos_mem_set(( tANI_U8* )&pr, sizeof( pr ), 0); + + PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL); + + if ( WNI_CFG_DOT11_MODE_11B != dot11mode ) + { + PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); + } + + + if (IS_DOT11_MODE_HT(dot11mode)) + { + PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps ); + pr.HTCaps.advCodingCap = psession->htConfig.ht_rx_ldpc; + pr.HTCaps.txSTBC = psession->htConfig.ht_tx_stbc; + pr.HTCaps.rxSTBC = psession->htConfig.ht_rx_stbc; + if (!psession->htConfig.ht_sgi) { + pr.HTCaps.shortGI20MHz = pr.HTCaps.shortGI40MHz = 0; + } + } + + + nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to calculate the packed size f" + "or a Probe Request (0x%08x).\n", nStatus ); + + + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while calculating" + "the packed size for a Probe Request (" + "0x%08x).\n", nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + /* Prepare outgoing frame*/ + vos_mem_set(pFrame, nBytes , 0); + + + nSirStatus = csrRoamScanOffloadPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssId,selfMacAddr); + + if ( eSIR_SUCCESS != nSirStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to populate the buffer descriptor for a Probe Request (%d).\n", + nSirStatus ); + return nSirStatus; + } + + + nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame + + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to pack a Probe Request (0x%08x).\n", nStatus ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request (0x%08x).\n", + nStatus ); + } + + *pusLen = nPayload + sizeof(tSirMacMgmtHdr); + return eSIR_SUCCESS; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus csrRoamSetKeyMgmtOffload(tpAniSirGlobal pMac, + tANI_U32 sessionId, + v_BOOL_t nRoamKeyMgmtOffloadEnabled) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + smsLog(pMac, LOGE, FL("session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } + pSession->RoamKeyMgmtOffloadEnabled = nRoamKeyMgmtOffloadEnabled; + return eHAL_STATUS_SUCCESS; +} + +void csrRoamOffload(tpAniSirGlobal pMac, tSirRoamOffloadScanReq *pRequestBuf, + tCsrRoamSession *pSession) +{ + vos_mem_copy(pRequestBuf->PSK_PMK, pSession->psk_pmk, + sizeof(pRequestBuf->PSK_PMK)); + pRequestBuf->pmk_len = pSession->pmk_len; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR3: PMK Length = %d", pRequestBuf->pmk_len); + pRequestBuf->R0KH_ID_Length = pSession->ftSmeContext.r0kh_id_len; + vos_mem_copy(pRequestBuf->R0KH_ID, pSession->ftSmeContext.r0kh_id, + pRequestBuf->R0KH_ID_Length); + pRequestBuf->Prefer5GHz = pMac->roam.configParam.nRoamPrefer5GHz; + pRequestBuf->RoamRssiCatGap = pMac->roam.configParam.bCatRssiOffset; + pRequestBuf->Select5GHzMargin = pMac->roam.configParam.nSelect5GHzMargin; + if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + (tANI_U32 *)&pRequestBuf->ReassocFailureTimeout) + != eSIR_SUCCESS) + { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error and set some default value + */ + smsLog(pMac, LOGE, FL("could not retrieve ReassocFailureTimeout value")); + pRequestBuf->ReassocFailureTimeout = DEFAULT_REASSOC_FAILURE_TIMEOUT; + } +#ifdef FEATURE_WLAN_ESE + if (csrIsAuthTypeESE(pRequestBuf->ConnectedNetwork.authentication)) { + vos_mem_copy(pRequestBuf->KRK,pSession->eseCckmInfo.krk, SIR_KRK_KEY_LEN); + vos_mem_copy(pRequestBuf->BTK,pSession->eseCckmInfo.btk, SIR_BTK_KEY_LEN); + } +#endif + pRequestBuf->AcUapsd.acbe_uapsd = + SIR_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); + pRequestBuf->AcUapsd.acbk_uapsd = + SIR_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); + pRequestBuf->AcUapsd.acvi_uapsd = + SIR_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); + pRequestBuf->AcUapsd.acvo_uapsd = + SIR_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); +} +#endif + +/** + * check_allowed_ssid_list() - Check the WhiteList + * @req_buffer: Buffer which contains the connected profile SSID. + * @roam_params: Buffer which contains the whitelist SSID's. + * + * Check if the connected profile SSID exists in the whitelist. + * It is assumed that the framework provides this also in the whitelist. + * If it exists there is no issue. Otherwise add it to the list. + * + * Return: None + */ +static void check_allowed_ssid_list(tSirRoamOffloadScanReq *req_buffer, + struct roam_ext_params *roam_params) +{ + int i = 0; + bool match = false; + for (i = 0; i < roam_params->num_ssid_allowed_list; i++) { + if ((roam_params->ssid_allowed_list[i].length == + req_buffer->ConnectedNetwork.ssId.length) && + vos_mem_compare(roam_params->ssid_allowed_list[i].ssId, + req_buffer->ConnectedNetwork.ssId.ssId, + roam_params->ssid_allowed_list[i].length)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Whitelist contains connected profile SSID"); + match = true; + break; + } + } + if (!match) { + if (roam_params->num_ssid_allowed_list >= + MAX_SSID_ALLOWED_LIST) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Whitelist is FULL. Cannot Add another entry"); + return; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Adding Connected profile SSID to whitelist"); + /* i is the next available index to add the entry.*/ + i = roam_params->num_ssid_allowed_list; + vos_mem_copy(roam_params->ssid_allowed_list[i].ssId, + req_buffer->ConnectedNetwork.ssId.ssId, + req_buffer->ConnectedNetwork.ssId.length); + roam_params->ssid_allowed_list[i].length = + req_buffer->ConnectedNetwork.ssId.length; + roam_params->num_ssid_allowed_list++; + } +} + +/* + * Below Table describe whether RSO command can be send down to fimrware or not. + * Host check it on the basis of previous RSO command sent down to firmware. + *||==========================================================================|| + *|| New cmd | LAST SENT COMMAND ---> || + *||====|=====================================================================|| + *|| V | START | STOP | RESTART | UPDATE_CFG| ABORT_SCAN || + *|| -------------------------------------------------------------------------|| + *|| RSO_START | NO | YES | NO | NO | NO || + *|| RSO_STOP | YES | YES | YES | YES | YES || + *|| RSO_RESTART | YES | YES | NO | YES | YES || + *|| RSO_UPDATE_CFG | YES | NO | YES | YES | YES || + *|| RSO_ABORT_SCAN | YES | NO | YES | YES | YES || + *||==========================================================================|| + **/ +#define RSO_START_BIT (1<roam.neighborRoamInfo[session_id]; + tANI_U8 desiredMask = 0; + bool ret_val; + + switch(command) { + case ROAM_SCAN_OFFLOAD_START: + desiredMask = RSO_START_ALLOW_MASK; + break; + case ROAM_SCAN_OFFLOAD_STOP: + desiredMask = RSO_STOP_ALLOW_MASK; + break; + case ROAM_SCAN_OFFLOAD_RESTART: + desiredMask = RSO_RESTART_ALLOW_MASK; + break; + case ROAM_SCAN_OFFLOAD_UPDATE_CFG: + desiredMask = RSO_UPDATE_CFG_ALLOW_MASK; + break; + case ROAM_SCAN_OFFLOAD_ABORT_SCAN: + desiredMask = RSO_ABORT_SCAN_ALLOW_MASK; + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Wrong RSO command %d, not allowed"), command); + return 0;/*Cmd Not allowed*/ + } + ret_val = desiredMask & ( 1 << neigh_roam_info->lastSentCmd); + return ret_val; +} + +void csr_roam_send_restart_cmd(tpAniSirGlobal pMac, tANI_U8 session_id, + tANI_U8 command, tANI_U8 reason) +{ + struct sir_sme_roam_restart_req *msg; + eHalStatus status; + + msg = vos_mem_malloc(sizeof(struct sir_sme_roam_restart_req)); + if (msg == NULL) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Memory allocation failed")); + VOS_ASSERT(msg); + return; + } + vos_mem_set(msg, sizeof(struct sir_sme_roam_restart_req), 0); + msg->message_type = eWNI_SME_ROAM_RESTART_REQ; + msg->length = sizeof(struct sir_sme_roam_restart_req); + msg->sme_session_id = session_id; + msg->command = command; + msg->reason = reason; + status = palSendMBMessage(pMac->hHdd, msg); + if (eHAL_STATUS_FAILURE == status) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Sending msg eWNI_SME_ROAM_RESTART_REQ failed")); + vos_mem_free(msg); + } +} +eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 sessionId, + tANI_U8 command, tANI_U8 reason) +{ + vos_msg_t msg; + tSirRoamOffloadScanReq *pRequestBuf; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamSession *pSession; + tANI_U8 i,j,num_channels = 0, ucDot11Mode; + tANI_U8 *ChannelList = NULL; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrChannelInfo currChannelListInfo; + tANI_U32 host_channels = 0; + eCsrBand eBand; + tANI_U8 ChannelCacheStr[128] = {0}; + struct roam_ext_params *roam_params_dst; + struct roam_ext_params *roam_params_src; + uint8_t op_channel; + currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (NULL == pSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s:pSession is null", __func__); + return eHAL_STATUS_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress + && (ROAM_SCAN_OFFLOAD_STOP == command)) + { + /* When roam synch is in progress for propagation, there is no + * need to send down the STOP command since the firmware is not + * expecting any WMI commands when the roam synch is in progress.*/ + bRoamScanOffloadStarted = VOS_FALSE; + return eHAL_STATUS_SUCCESS; + } +#endif + if (0 == csrRoamIsRoamOffloadScanEnabled(pMac)) + { + smsLog( pMac, LOGE,"isRoamOffloadScanEnabled not set"); + return eHAL_STATUS_FAILURE; + } + + if (!csr_is_RSO_cmd_allowed(pMac, command, sessionId) && + reason != REASON_ROAM_SET_BLACKLIST_BSSID) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("RSO out-of-sync command %d lastSentCmd %d"), + command, pNeighborRoamInfo->lastSentCmd); + return eHAL_STATUS_FAILURE; + } + if (ROAM_SCAN_OFFLOAD_RESTART == command) { + csr_roam_send_restart_cmd(pMac, sessionId, command, reason); + goto cmd_sent; + } + if ((VOS_TRUE == bRoamScanOffloadStarted) && (ROAM_SCAN_OFFLOAD_START == command)) + { + smsLog( pMac, LOGE,"Roam Scan Offload is already started"); + return eHAL_STATUS_FAILURE; + } + /*The Dynamic Config Items Update may happen even if the state is in INIT. + * It is important to ensure that the command is passed down to the FW only + * if the Infra Station is in a connected state.A connected station could also be + * in a PREAUTH or REASSOC states.So, consider not sending the command down in INIT state. + * We also have to ensure that if there is a STOP command we always have to inform Riva, + * irrespective of whichever state we are in.*/ + + if ((pMac->roam.neighborRoamInfo[sessionId].neighborRoamState == + eCSR_NEIGHBOR_ROAM_STATE_INIT) && + (command != ROAM_SCAN_OFFLOAD_STOP) && + (reason != REASON_ROAM_SET_BLACKLIST_BSSID)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("Scan Command not sent to FW with state = %s and cmd=%d"), + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState), command); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for Roam Offload scan request)")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(pRequestBuf, sizeof(tSirRoamOffloadScanReq)); + pRequestBuf->Command = command; + /* If command is STOP, then pass down ScanOffloadEnabled as Zero.This will handle the case of + * host driver reloads, but Riva still up and running*/ + if(command == ROAM_SCAN_OFFLOAD_STOP) { + /* clear the roaming parameters that are per connection. + * For a new connection, they have to be programmed again. + */ + if (csrNeighborMiddleOfRoaming((tHalHandle)pMac, sessionId)) { + pRequestBuf->middle_of_roaming = 1; + } else { + csr_roam_reset_roam_params(pMac); + } + pRequestBuf->RoamScanOffloadEnabled = 0; + } + else + pRequestBuf->RoamScanOffloadEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled; + vos_mem_copy(pRequestBuf->ConnectedNetwork.currAPbssid, + pNeighborRoamInfo->currAPbssid, + sizeof(tCsrBssid)); + pRequestBuf->ConnectedNetwork.ssId.length = + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length; + vos_mem_copy(pRequestBuf->ConnectedNetwork.ssId.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId, + pRequestBuf->ConnectedNetwork.ssId.length); + pRequestBuf->ConnectedNetwork.authentication = + pMac->roam.roamSession[sessionId].connectedProfile.AuthType; + pRequestBuf->ConnectedNetwork.encryption = + pMac->roam.roamSession[sessionId].connectedProfile.EncryptionType; + pRequestBuf->ConnectedNetwork.mcencryption = + pMac->roam.roamSession[sessionId].connectedProfile.mcEncryptionType; +#ifdef WLAN_FEATURE_11W + pRequestBuf->ConnectedNetwork.MFPEnabled = + pMac->roam.roamSession[sessionId].connectedProfile.MFPEnabled; +#endif + pRequestBuf->delay_before_vdev_stop = + pNeighborRoamInfo->cfgParams.delay_before_vdev_stop; + pRequestBuf->OpportunisticScanThresholdDiff = + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff; + pRequestBuf->RoamRescanRssiDiff = + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff; + pRequestBuf->reason = reason; + pRequestBuf->NeighborScanTimerPeriod = + pNeighborRoamInfo->cfgParams.neighborScanPeriod; + pRequestBuf->NeighborRoamScanRefreshPeriod = + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod; + pRequestBuf->NeighborScanChannelMinTime = + pNeighborRoamInfo->cfgParams.minChannelScanTime; + pRequestBuf->NeighborScanChannelMaxTime = + pNeighborRoamInfo->cfgParams.maxChannelScanTime; + pRequestBuf->EmptyRefreshScanPeriod = + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod; + pRequestBuf->RoamBmissFirstBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt; + pRequestBuf->RoamBmissFinalBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt; + pRequestBuf->RoamBeaconRssiWeight = + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight; + /* MAWC feature */ + pRequestBuf->MAWCEnabled = + pMac->roam.configParam.MAWCEnabled; +#ifdef FEATURE_WLAN_ESE + pRequestBuf->IsESEAssoc = csrNeighborRoamIsESEAssoc(pMac, sessionId) && + ((pRequestBuf->ConnectedNetwork.authentication == + eCSR_AUTH_TYPE_OPEN_SYSTEM) || + (csrIsAuthTypeESE(pRequestBuf->ConnectedNetwork.authentication))); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR3:%s:IsEseAssoc=%d\n", __func__, pRequestBuf->IsESEAssoc); +#endif + if ( +#ifdef FEATURE_WLAN_ESE + ((pNeighborRoamInfo->isESEAssoc) && + (pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived == + eANI_BOOLEAN_FALSE)) || + (pNeighborRoamInfo->isESEAssoc == eANI_BOOLEAN_FALSE) || +#endif // ESE + currChannelListInfo->numOfChannels == 0) { + /* Retrieve the Channel Cache either from ini or from the Occupied + * Channels list. Give Preference to INI Channels.*/ + if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) { + ChannelList = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList; + /* The INI channels need to be filtered with respect to the current + * band that is supported. */ + eBand = pMac->roam.configParam.bandCapability; + if ((eCSR_BAND_24 != eBand) && (eCSR_BAND_5G != eBand) && + (eCSR_BAND_ALL != eBand)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Invalid band, No operation carried out (Band %d)", eBand); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + for (i = 0; + i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; + i++) { + if (((eCSR_BAND_24 == eBand) && + CSR_IS_CHANNEL_24GHZ(*ChannelList)) || + ((eCSR_BAND_5G == eBand) && + CSR_IS_CHANNEL_5GHZ(*ChannelList)) || + (eCSR_BAND_ALL == eBand)) { + /* Allow DFS channels only if the DFS channel + * roam flag is enabled */ + if (((pMac->roam.configParam.allowDFSChannelRoam + != CSR_ROAMING_DFS_CHANNEL_DISABLED) || + (!CSR_IS_CHANNEL_DFS(*ChannelList))) && + csrRoamIsChannelValid(pMac, *ChannelList) && + *ChannelList && + (num_channels < SIR_ROAM_MAX_CHANNELS)) { + pRequestBuf->ConnectedNetwork.ChannelCache[ + num_channels++] = *ChannelList; + } + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; + } else { + ChannelList = pMac->scan.occupiedChannels[sessionId].channelList; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Num of channels before filtering=%d", + pMac->scan.occupiedChannels[sessionId].numChannels); + for (i = 0; + i < pMac->scan.occupiedChannels[sessionId].numChannels; + i++) { + if(((pMac->roam.configParam.allowDFSChannelRoam + != CSR_ROAMING_DFS_CHANNEL_DISABLED) || + (!CSR_IS_CHANNEL_DFS(*ChannelList))) && *ChannelList && + (num_channels < SIR_ROAM_MAX_CHANNELS)) { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = + *ChannelList; + } + if (*ChannelList) + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "DFSRoam=%d, ChnlState=%d, Chnl=%d, num_ch=%d", + pMac->roam.configParam.allowDFSChannelRoam, + vos_nv_getChannelEnabledState(*ChannelList), + *ChannelList, + num_channels); + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + /* If the profile changes as to what it was earlier, inform the + * FW through FLUSH as ChannelCacheType in which case, + * the FW will flush the occupied channels for the earlier profile and + * try to learn them afresh.*/ + if (reason == REASON_FLUSH_CHANNEL_LIST) + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_FLUSH; + else { + if (csrNeighborRoamIsNewConnectedProfile(pMac, sessionId)) + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_INIT; + else + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE; + } + } + } +#ifdef FEATURE_WLAN_ESE + else + { + /* If ESE is enabled, and a neighbor Report is received,then + * Ignore the INI Channels or the Occupied Channel List. Consider + * the channels in the neighbor list sent by the ESE AP.*/ + if (currChannelListInfo->numOfChannels != 0) + { + ChannelList = currChannelListInfo->ChannelList; + for (i=0;inumOfChannels;i++) + { + if(((pMac->roam.configParam.allowDFSChannelRoam + != CSR_ROAMING_DFS_CHANNEL_DISABLED) || + (!CSR_IS_CHANNEL_DFS(*ChannelList))) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE; + } + } +#endif + for (i = 0, j = 0; i < pRequestBuf->ConnectedNetwork.ChannelCount; i++) + { + if (j < sizeof(ChannelCacheStr)) + { + j += snprintf(ChannelCacheStr + j, sizeof(ChannelCacheStr) - j," %d", + pRequestBuf->ConnectedNetwork.ChannelCache[i]); + } + else + { + break; + } + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "ChnlCacheType:%d, No of Chnls:%d,Channels: %s", + pRequestBuf->ChannelCacheType, + pRequestBuf->ConnectedNetwork.ChannelCount, + ChannelCacheStr); + num_channels = 0; + ChannelList = NULL; + + /* Maintain the Valid Channels List*/ + host_channels = sizeof(pMac->roam.validChannelList); + if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &host_channels))) + { + ChannelList = pMac->roam.validChannelList; + pMac->roam.numValidChannels = host_channels; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s:Failed to get the valid channel list", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + for(i=0; iroam.numValidChannels; i++) + { + if(((pMac->roam.configParam.allowDFSChannelRoam + != CSR_ROAMING_DFS_CHANNEL_DISABLED) || + (!CSR_IS_CHANNEL_DFS(*ChannelList))) && *ChannelList) + { + pRequestBuf->ValidChannelList[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ValidChannelCount = num_channels; + + pRequestBuf->MDID.mdiePresent = + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mdiePresent; + pRequestBuf->MDID.mobilityDomain = + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mobilityDomain; + pRequestBuf->sessionId = sessionId; + pRequestBuf->nProbes = pMac->roam.configParam.nProbes; + + pRequestBuf->HomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime; + + /* Home Away Time should be at least equal to (MaxDwell time + (2*RFS)), + * where RFS is the RF Switching time. It is twice RFS to consider the + * time to go off channel and return to the home channel. */ + if (pRequestBuf->HomeAwayTime < (pRequestBuf->NeighborScanChannelMaxTime + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)" + " Hence enforcing home away time to disable (0)", + __func__, pRequestBuf->HomeAwayTime, + (pRequestBuf->NeighborScanChannelMaxTime + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME) + )); + pRequestBuf->HomeAwayTime = 0; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,"HomeAwayTime:%d",pRequestBuf->HomeAwayTime); + + /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ + ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, + csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); + csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p24GProbeTemplate, + &pRequestBuf->us24GProbeTemplateLen, + pSession); + + csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p5GProbeTemplate, + &pRequestBuf->us5GProbeTemplateLen, + pSession); + pRequestBuf->allowDFSChannelRoam = pMac->roam.configParam.allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRequestBuf->RoamOffloadEnabled = csrRoamIsRoamOffloadEnabled(pMac); + pRequestBuf->RoamKeyMgmtOffloadEnabled = pSession->RoamKeyMgmtOffloadEnabled; + /* Roam Offload piggybacks upon the Roam Scan offload command.*/ + if (pRequestBuf->RoamOffloadEnabled){ + csrRoamOffload(pMac, pRequestBuf, pSession); + } +#endif + roam_params_dst = &pRequestBuf->roam_params; + roam_params_src = &pMac->roam.configParam.roam_params; + if (reason == REASON_ROAM_SET_SSID_ALLOWED) + check_allowed_ssid_list(pRequestBuf, roam_params_src); + /* Configure the lookup threshold either from INI or from framework. + * If both are present, give higher priority to the one from framework. + */ + if (roam_params_src->alert_rssi_threshold) + pRequestBuf->LookupThreshold = roam_params_src->alert_rssi_threshold; + else + pRequestBuf->LookupThreshold = + (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1); + vos_mem_copy(roam_params_dst, roam_params_src, + sizeof(struct roam_ext_params)); + pRequestBuf->hi_rssi_scan_max_count = + pNeighborRoamInfo->cfgParams.hi_rssi_scan_max_count; + pRequestBuf->hi_rssi_scan_delay = + pNeighborRoamInfo->cfgParams.hi_rssi_scan_delay; + pRequestBuf->hi_rssi_scan_rssi_ub = + pNeighborRoamInfo->cfgParams.hi_rssi_scan_rssi_ub; + /* rssi_diff which is updated via framework is equivalent to the + * INI RoamRssiDiff parameter and hence should be updated.*/ + if (roam_params_src->rssi_diff) + pMac->roam.configParam.RoamRssiDiff = roam_params_src->rssi_diff; + pRequestBuf->RoamRssiDiff = + pMac->roam.configParam.RoamRssiDiff; + op_channel = pSession->connectedProfile.operationChannel; + /* If the current operation channel is 5G frequency band, then + * there is no need to enable the HI_RSSI feature. This feature + * is useful only if we are connected to a 2.4 GHz AP and we wish + * to connect to a better 5GHz AP is available.*/ + if(pSession->disable_hi_rssi) + pRequestBuf->hi_rssi_scan_rssi_delta = 0; + else + pRequestBuf->hi_rssi_scan_rssi_delta = + pNeighborRoamInfo->cfgParams.hi_rssi_scan_rssi_delta; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "hi_rssi_delta=%d, hi_rssi_max_count=%d," + "hi_rssi_delay=%d, hi_rssi_ub=%d", + pRequestBuf->hi_rssi_scan_rssi_delta, + pRequestBuf->hi_rssi_scan_max_count, + pRequestBuf->hi_rssi_scan_delay, + pRequestBuf->hi_rssi_scan_rssi_ub); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "num_bssid_avoid_list: %d, num_ssid_allowed_list:%d, num_bssid_favored:%d," + "raise_rssi_thresh_5g: %d, drop_rssi_thresh_5g:%d, raise_rssi_type_5g:%d," + "raise_factor_5g:%d, drop_rssi_type_5g:%d, drop_factor_5g:%d," + "max_raise_rssi_5g=%d, max_drop_rssi_5g:%d, alert_rssi_threshold:%d", + roam_params_dst->num_bssid_avoid_list, + roam_params_dst->num_ssid_allowed_list, roam_params_dst->num_bssid_favored, + roam_params_dst->raise_rssi_thresh_5g, + roam_params_dst->drop_rssi_thresh_5g, roam_params_dst->raise_rssi_type_5g, + roam_params_dst->raise_factor_5g, roam_params_dst->drop_rssi_type_5g, + roam_params_dst->drop_factor_5g, roam_params_dst->max_raise_rssi_5g, + roam_params_dst->max_drop_rssi_5g, roam_params_dst->alert_rssi_threshold); + + for (i = 0; i < roam_params_dst->num_bssid_avoid_list; i++) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Blacklist Bssid("MAC_ADDRESS_STR")", + MAC_ADDR_ARRAY(roam_params_dst->bssid_avoid_list[i])); + } + for (i = 0; i < roam_params_dst->num_ssid_allowed_list; i++) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Whitelist: %.*s", + roam_params_dst->ssid_allowed_list[i].length, + roam_params_dst->ssid_allowed_list[i].ssId); + } + for (i = 0; i < roam_params_dst->num_bssid_favored; i++) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Preferred Bssid("MAC_ADDRESS_STR") score=%d", + MAC_ADDR_ARRAY(roam_params_dst->bssid_favored[i]), + roam_params_dst->bssid_favored_factor[i]); + } + msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_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_ROAM_SCAN_OFFLOAD_REQ message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + else + { + if (ROAM_SCAN_OFFLOAD_START == command) + bRoamScanOffloadStarted = VOS_TRUE; + else if (ROAM_SCAN_OFFLOAD_STOP == command) + bRoamScanOffloadStarted = VOS_FALSE; + } +cmd_sent: + /* update the last sent cmd */ + pNeighborRoamInfo->lastSentCmd = command; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Roam Scan Offload Command %d, Reason %d", command, reason); + return status; +} + +eHalStatus csrRoamOffloadScanRspHdlr(tpAniSirGlobal pMac, + tpSirRoamOffloadScanRsp scanOffloadRsp) +{ + switch (scanOffloadRsp->reason) { + case 0: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Rsp for Roam Scan Offload with failure status"); + break; + case REASON_OS_REQUESTED_ROAMING_NOW: + csrNeighborRoamProceedWithHandoffReq(pMac, + scanOffloadRsp->sessionId); + break; + + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Rsp for Roam Scan Offload with reason %d", + scanOffloadRsp->reason); + } + return eHAL_STATUS_SUCCESS; +} +#endif + +tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, + tANI_U32 statsMask, + tANI_U32 periodicity, + tANI_BOOLEAN *pFound, + tANI_U8 staId, + tANI_U8 sessionId) +{ + tANI_BOOLEAN found = FALSE; + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrPeStatsReqInfo staEntry; + tCsrPeStatsReqInfo *pTempStaEntry = NULL; + tListElem *pStaEntry = NULL; + VOS_STATUS vosStatus; + tPmcPowerState powerState; + *pFound = FALSE; + + pStaEntry = csrRoamFindInPeStatsReqList(pMac, statsMask); + if(pStaEntry) + { + pTempStaEntry = GET_BASE_ADDR( pStaEntry, tCsrPeStatsReqInfo, link ); + if(pTempStaEntry->periodicity) + { + pTempStaEntry->periodicity = + CSR_ROAM_MIN(periodicity, pTempStaEntry->periodicity); + } + else + { + pTempStaEntry->periodicity = periodicity; + } + pTempStaEntry->numClient++; + found = TRUE; + } + else + { + vos_mem_set(&staEntry, sizeof(tCsrPeStatsReqInfo), 0); + staEntry.numClient = 1; + staEntry.periodicity = periodicity; + staEntry.pMac = pMac; + staEntry.rspPending = FALSE; + staEntry.staId = staId; + staEntry.statsMask = statsMask; + staEntry.timerRunning = FALSE; + staEntry.sessionId = sessionId; + pTempStaEntry = csrRoamInsertEntryIntoPeStatsReqList(pMac, &pMac->roam.peStatsReqList, &staEntry); + if(!pTempStaEntry) + { + //msg + smsLog(pMac, LOGW, "csrRoamCheckPeStatsReqList: Failed to insert req in peStatsReqList"); + return NULL; + } + } + pmcQueryPowerState(pMac, &powerState, NULL, NULL); + if(ePMC_FULL_POWER == powerState) + { + if(pTempStaEntry->periodicity < pMac->roam.configParam.statsReqPeriodicity) + { + pTempStaEntry->periodicity = pMac->roam.configParam.statsReqPeriodicity; + } + } + else + { + if(pTempStaEntry->periodicity < pMac->roam.configParam.statsReqPeriodicityInPS) + { + pTempStaEntry->periodicity = pMac->roam.configParam.statsReqPeriodicityInPS; + } + } + if(!pTempStaEntry->timerRunning) + { + //send down a req in case of one time req, for periodic ones wait for timer to expire + if(!pTempStaEntry->rspPending && + !pTempStaEntry->periodicity) + { + status = csrSendMBStatsReqMsg(pMac, + statsMask & ~(1 << eCsrGlobalClassDStats), + staId, + sessionId); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:failed to send down stats req to PE")); + } + else + { + pTempStaEntry->rspPending = TRUE; + } + } + if(pTempStaEntry->periodicity) + { + if(!found) + { + + vosStatus = vos_timer_init( &pTempStaEntry->hPeStatsTimer, VOS_TIMER_TYPE_SW, + csrRoamPeStatsTimerHandler, pTempStaEntry ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:cannot init hPeStatsTimer timer")); + return NULL; + } + } + //start timer + smsLog(pMac, LOG1, "csrRoamCheckPeStatsReqList:peStatsTimer period %d", pTempStaEntry->periodicity); + vosStatus = vos_timer_start( &pTempStaEntry->hPeStatsTimer, pTempStaEntry->periodicity ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:cannot start hPeStatsTimer timer")); + return NULL; + } + pTempStaEntry->timerRunning = TRUE; + } + } + *pFound = found; + return pTempStaEntry; +} + +/* + pStaEntry is no longer invalid upon the return of this function. +*/ +static void csrRoamRemoveStatListEntry(tpAniSirGlobal pMac, tListElem *pEntry) +{ + if(pEntry) + { + if(csrLLRemoveEntry(&pMac->roam.statsClientReqList, pEntry, LL_ACCESS_LOCK)) + { + vos_mem_free(GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link )); + } + } + } + +void csrRoamRemoveEntryFromPeStatsReqList(tpAniSirGlobal pMac, tCsrPeStatsReqInfo *pPeStaEntry) +{ + tListElem *pEntry; + tCsrPeStatsReqInfo *pTempStaEntry; + VOS_STATUS vosStatus; + pEntry = csrLLPeekHead( &pMac->roam.peStatsReqList, LL_ACCESS_LOCK ); + if(!pEntry) + { + //list empty + smsLog(pMac, LOGE, FL(" List empty, no stats req for PE")); + return; + } + while( pEntry ) + { + pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link ); + if( pTempStaEntry && pTempStaEntry->statsMask == pPeStaEntry->statsMask) + { + smsLog(pMac, LOGW, FL("Match found")); + if(pTempStaEntry->timerRunning) + { + vosStatus = vos_timer_stop( &pTempStaEntry->hPeStatsTimer ); + /* If we are not able to stop the timer here, just remove + * the entry from the linked list. Destroy the timer object + * and free the memory in the timer CB + */ + if ( vosStatus == VOS_STATUS_SUCCESS ) + { + /* the timer is successfully stopped */ + pTempStaEntry->timerRunning = FALSE; + + /* Destroy the timer */ + vosStatus = vos_timer_destroy( &pTempStaEntry->hPeStatsTimer ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrRoamRemoveEntryFromPeStatsReqList:failed to destroy hPeStatsTimer timer")); + } + } + else + { + // the timer could not be stopped. Hence destroy and free the + // memory for the PE stat entry in the timer CB. + pTempStaEntry->timerStopFailed = TRUE; + } + } + + if(csrLLRemoveEntry(&pMac->roam.peStatsReqList, pEntry, LL_ACCESS_LOCK)) + { + // Only free the memory if we could stop the timer successfully + if(!pTempStaEntry->timerStopFailed) + { + vos_mem_free(pTempStaEntry); + pTempStaEntry = NULL; + } + break; + } + + pEntry = csrLLNext( &pMac->roam.peStatsReqList, pEntry, LL_ACCESS_NOLOCK ); + } + } + return; +} + + +void csrRoamSaveStatsFromTl(tpAniSirGlobal pMac, WLANTL_TRANSFER_STA_TYPE *pTlStats) +{ + + pMac->roam.classDStatsInfo.num_rx_bytes_crc_ok = pTlStats->rxBcntCRCok; + pMac->roam.classDStatsInfo.rx_bc_byte_cnt = pTlStats->rxBCBcnt; + pMac->roam.classDStatsInfo.rx_bc_frm_cnt = pTlStats->rxBCFcnt; + pMac->roam.classDStatsInfo.rx_byte_cnt = pTlStats->rxBcnt; + pMac->roam.classDStatsInfo.rx_mc_byte_cnt = pTlStats->rxMCBcnt; + pMac->roam.classDStatsInfo.rx_mc_frm_cnt = pTlStats->rxMCFcnt; + pMac->roam.classDStatsInfo.rx_rate = pTlStats->rxRate; + //?? need per AC + pMac->roam.classDStatsInfo.rx_uc_byte_cnt[0] = pTlStats->rxUCBcnt; + pMac->roam.classDStatsInfo.rx_uc_frm_cnt = pTlStats->rxUCFcnt; + pMac->roam.classDStatsInfo.tx_bc_byte_cnt = pTlStats->txBCBcnt; + pMac->roam.classDStatsInfo.tx_bc_frm_cnt = pTlStats->txBCFcnt; + pMac->roam.classDStatsInfo.tx_mc_byte_cnt = pTlStats->txMCBcnt; + pMac->roam.classDStatsInfo.tx_mc_frm_cnt = pTlStats->txMCFcnt; + //?? need per AC + pMac->roam.classDStatsInfo.tx_uc_byte_cnt[0] = pTlStats->txUCBcnt; + pMac->roam.classDStatsInfo.tx_uc_frm_cnt = pTlStats->txUCFcnt; + +} + +void csrRoamReportStatistics(tpAniSirGlobal pMac, tANI_U32 statsMask, + tCsrStatsCallback callback, tANI_U8 staId, void *pContext) +{ + tANI_U8 stats[500]; + tANI_U8 *pStats = NULL; + tANI_U32 tempMask = 0; + tANI_U8 counter = 0; + if(!callback) + { + smsLog(pMac, LOGE, FL("Cannot report callback NULL")); + return; + } + if(!statsMask) + { + smsLog(pMac, LOGE, FL("Cannot report statsMask is 0")); + return; + } + pStats = stats; + tempMask = statsMask; + while(tempMask) + { + if(tempMask & 1) + { + /* new stats info from PE, fill up the stats structures in PMAC */ + switch(counter) + { + case eCsrSummaryStats: + smsLog( pMac, LOG2, FL("Summary stats")); + vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.summaryStatsInfo, + sizeof(tCsrSummaryStatsInfo)); + pStats += sizeof(tCsrSummaryStatsInfo); + break; + case eCsrGlobalClassAStats: + smsLog( pMac, LOG2, FL("ClassA stats")); + vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classAStatsInfo, + sizeof(tCsrGlobalClassAStatsInfo)); + pStats += sizeof(tCsrGlobalClassAStatsInfo); + break; + case eCsrGlobalClassBStats: + smsLog( pMac, LOG2, FL("ClassB stats")); + vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classBStatsInfo, + sizeof(tCsrGlobalClassBStatsInfo)); + pStats += sizeof(tCsrGlobalClassBStatsInfo); + break; + case eCsrGlobalClassCStats: + smsLog( pMac, LOG2, FL("ClassC stats")); + vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classCStatsInfo, + sizeof(tCsrGlobalClassCStatsInfo)); + pStats += sizeof(tCsrGlobalClassCStatsInfo); + break; + case eCsrGlobalClassDStats: + smsLog( pMac, LOG2, FL("ClassD stats")); + vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classDStatsInfo, + sizeof(tCsrGlobalClassDStatsInfo)); + pStats += sizeof(tCsrGlobalClassDStatsInfo); + break; + case eCsrPerStaStats: + smsLog( pMac, LOG2, FL("PerSta stats")); + vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.perStaStatsInfo[staId], + sizeof(tCsrPerStaStatsInfo)); + pStats += sizeof(tCsrPerStaStatsInfo); + break; + default: + smsLog( pMac, LOGE, FL("Unknown stats type and counter %d"), counter); + break; + } + } + tempMask >>=1; + counter++; + } + callback(stats, pContext ); +} + +eHalStatus csrRoamDeregStatisticsReq(tpAniSirGlobal pMac) +{ + tListElem *pEntry = NULL; + tListElem *pPrevEntry = NULL; + tCsrStatsClientReqInfo *pTempStaEntry = NULL; + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus; + pEntry = csrLLPeekHead( &pMac->roam.statsClientReqList, LL_ACCESS_LOCK ); + if(!pEntry) + { + //list empty + smsLog(pMac, LOGW, "csrRoamDeregStatisticsReq: List empty, no request from " + "upper layer client(s)"); + return status; + } + while( pEntry ) + { + if(pPrevEntry) + { + pTempStaEntry = GET_BASE_ADDR( pPrevEntry, tCsrStatsClientReqInfo, link ); + //send up the stats report + csrRoamReportStatistics(pMac, pTempStaEntry->statsMask, pTempStaEntry->callback, + pTempStaEntry->staId, pTempStaEntry->pContext); + csrRoamRemoveStatListEntry(pMac, pPrevEntry); + } + pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link ); + if (pTempStaEntry->pPeStaEntry) //pPeStaEntry can be NULL + { + pTempStaEntry->pPeStaEntry->numClient--; + //check if we need to delete the entry from peStatsReqList too + if(!pTempStaEntry->pPeStaEntry->numClient) + { + csrRoamRemoveEntryFromPeStatsReqList(pMac, pTempStaEntry->pPeStaEntry); + } + } + //check if we need to stop the tl stats timer too + pMac->roam.tlStatsReqInfo.numClient--; + if(!pMac->roam.tlStatsReqInfo.numClient) + { + if(pMac->roam.tlStatsReqInfo.timerRunning) + { + status = vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("csrRoamDeregStatisticsReq:cannot stop TlStatsTimer timer")); + //we will continue + } + } + pMac->roam.tlStatsReqInfo.periodicity = 0; + pMac->roam.tlStatsReqInfo.timerRunning = FALSE; + } + if (pTempStaEntry->periodicity) + { + //While creating StaEntry in csrGetStatistics, + //Initializing and starting timer only when periodicity is set. + //So Stop and Destroy timer only when periodicity is set. + + vos_timer_stop( &pTempStaEntry->timer ); + // Destroy the vos timer... + vosStatus = vos_timer_destroy( &pTempStaEntry->timer ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + smsLog(pMac, LOGE, FL("csrRoamDeregStatisticsReq:failed to destroy Client req timer")); + } + } + + + pPrevEntry = pEntry; + pEntry = csrLLNext( &pMac->roam.statsClientReqList, pEntry, LL_ACCESS_NOLOCK ); + } + //the last one + if(pPrevEntry) + { + pTempStaEntry = GET_BASE_ADDR( pPrevEntry, tCsrStatsClientReqInfo, link ); + //send up the stats report + csrRoamReportStatistics(pMac, pTempStaEntry->statsMask, pTempStaEntry->callback, + pTempStaEntry->staId, pTempStaEntry->pContext); + csrRoamRemoveStatListEntry(pMac, pPrevEntry); + } + return status; + +} + +eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand, + tRequestFullPowerReason *pReason, + tANI_BOOLEAN *pfNeedPower ) +{ + tANI_BOOLEAN fNeedFullPower = eANI_BOOLEAN_FALSE; + tRequestFullPowerReason reason = eSME_REASON_OTHER; + tPmcState pmcState; + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 sessionId = 0; + if( pfNeedPower ) + { + *pfNeedPower = eANI_BOOLEAN_FALSE; + } + //We only handle CSR commands + if( !(eSmeCsrCommandMask & pCommand->command) ) + { + return eHAL_STATUS_SUCCESS; + } + //Check PMC state first + pmcState = pmcGetPmcState( pMac ); + switch( pmcState ) + { + case REQUEST_IMPS: + case IMPS: + if( eSmeCommandScan == pCommand->command ) + { + switch( pCommand->u.scanCmd.reason ) + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif + case eCsrScanGetResult: + case eCsrScanBGScanAbort: + case eCsrScanBGScanEnable: + case eCsrScanGetScanChnInfo: + //Internal process, no need for full power + fNeedFullPower = eANI_BOOLEAN_FALSE; + break; + default: + //Other scans are real scan, ask for power + fNeedFullPower = eANI_BOOLEAN_TRUE; + break; + } //switch + } + else + { + //ask for power for roam and status change + fNeedFullPower = eANI_BOOLEAN_TRUE; + } + break; + case REQUEST_BMPS: + case BMPS: + case REQUEST_START_UAPSD: + case UAPSD: + //We treat WOWL same as BMPS + case REQUEST_ENTER_WOWL: + case WOWL: + if( eSmeCommandRoam == pCommand->command ) + { + tScanResultList *pBSSList = (tScanResultList *)pCommand->u.roamCmd.hBSSList; + tCsrScanResult *pScanResult; + tListElem *pEntry; + switch ( pCommand->u.roamCmd.roamReason ) + { + case eCsrForcedDisassoc: + case eCsrForcedDisassocMICFailure: + reason = eSME_LINK_DISCONNECTED_BY_HDD; + fNeedFullPower = eANI_BOOLEAN_TRUE; + break; + case eCsrSmeIssuedDisassocForHandoff: + case eCsrForcedDeauth: + case eCsrHddIssuedReassocToSameAP: + case eCsrSmeIssuedReassocToSameAP: + fNeedFullPower = eANI_BOOLEAN_TRUE; + break; + case eCsrCapsChange: + fNeedFullPower = eANI_BOOLEAN_TRUE; + 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 power save in IBSS + */ + if ( csrIsConnStateConnectedInfra(pMac, sessionId) && pBSSList ) + { + //Only need to check the first one + pEntry = csrLLPeekHead(&pBSSList->List, LL_ACCESS_LOCK); + if( pEntry ) + { + pScanResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + } + } + //If we are here, full power is needed + fNeedFullPower = eANI_BOOLEAN_TRUE; + break; + } + } + else if( eSmeCommandWmStatusChange == pCommand->command ) + { + //need full power for all + fNeedFullPower = eANI_BOOLEAN_TRUE; + reason = eSME_LINK_DISCONNECTED_BY_OTHER; + } +#ifdef FEATURE_WLAN_TDLS + else if( eSmeCommandTdlsAddPeer == pCommand->command ) + { + //TDLS link is getting established. need full power + fNeedFullPower = eANI_BOOLEAN_TRUE; + reason = eSME_FULL_PWR_NEEDED_BY_TDLS_PEER_SETUP; + } +#endif + break; + case REQUEST_STOP_UAPSD: + case REQUEST_EXIT_WOWL: + if( eSmeCommandRoam == pCommand->command ) + { + fNeedFullPower = eANI_BOOLEAN_TRUE; + switch ( pCommand->u.roamCmd.roamReason ) + { + case eCsrForcedDisassoc: + case eCsrForcedDisassocMICFailure: + reason = eSME_LINK_DISCONNECTED_BY_HDD; + break; + default: + break; + } + } + break; + case STOPPED: + case REQUEST_STANDBY: + case STANDBY: + case LOW_POWER: + //We are not supposed to do anything + smsLog( pMac, LOGE, FL( "cannot process because PMC is in" + " stopped/standby state %s (%d)" ), + sme_PmcStatetoString(pmcState), pmcState ); + status = eHAL_STATUS_FAILURE; + break; + case FULL_POWER: + case REQUEST_FULL_POWER: + default: + //No need to ask for full power. This has to be FULL_POWER state + break; + } //switch + if( pReason ) + { + *pReason = reason; + } + if( pfNeedPower ) + { + *pfNeedPower = fNeedFullPower; + } + return ( status ); +} + +eHalStatus csrPsOffloadIsFullPowerNeeded(tpAniSirGlobal pMac, + tSmeCmd *pCommand, + tRequestFullPowerReason *pReason, + tANI_BOOLEAN *pfNeedPower) +{ + tANI_BOOLEAN fNeedFullPower = eANI_BOOLEAN_FALSE; + tRequestFullPowerReason reason = eSME_REASON_OTHER; + tPmcState pmcState; + eHalStatus status = eHAL_STATUS_SUCCESS; + + if(pfNeedPower) + { + *pfNeedPower = eANI_BOOLEAN_FALSE; + } + + /* We only handle CSR commands */ + if(!(eSmeCsrCommandMask & pCommand->command)) + { + return eHAL_STATUS_SUCCESS; + } + + /* + * No need to request for full power for the following commands + * Scan Related Command + * IMPS is handled in Fw so no need + */ + if(eSmeCommandScan == pCommand->command) + { + return eHAL_STATUS_SUCCESS; + } + + /* + * Check PMC state first + * Commands which require Full Power + * 1) eSmeCommandRoam + * -----eCsrForcedDisassoc + * -----eCsrForcedDisassocMICFailure + * -----eCsrSmeIssuedDisassocForHandoff + * -----eCsrForcedDeauth + * -----eCsrHddIssuedReassocToSameAP + * -----eCsrSmeIssuedReassocToSameAP + * -----eCsrCapsChange + * -----AddTs + * -----DelTs + * ----- etc + * 2) eSmeCommandWmStatusChange + * 3) eSmeCommandTdlsAddPeer + */ + pmcState = pmcOffloadGetPmcState(pMac, pCommand->sessionId); + switch(pmcState) + { + case REQUEST_BMPS: + case BMPS: + case REQUEST_START_UAPSD: + case REQUEST_STOP_UAPSD: + case UAPSD: + if(eSmeCommandRoam == pCommand->command) + { + switch (pCommand->u.roamCmd.roamReason) + { + case eCsrForcedDisassoc: + case eCsrForcedDisassocMICFailure: + reason = eSME_LINK_DISCONNECTED_BY_HDD; + case eCsrSmeIssuedDisassocForHandoff: + case eCsrForcedDeauth: + case eCsrHddIssuedReassocToSameAP: + case eCsrSmeIssuedReassocToSameAP: + case eCsrCapsChange: + default: + fNeedFullPower = eANI_BOOLEAN_TRUE; + break; + } + } + else if(eSmeCommandWmStatusChange == pCommand->command) + { + /* need full power for all */ + fNeedFullPower = eANI_BOOLEAN_TRUE; + reason = eSME_LINK_DISCONNECTED_BY_OTHER; + } +#ifdef FEATURE_WLAN_TDLS + else if(eSmeCommandTdlsAddPeer == pCommand->command) + { + /* TDLS link is getting established. need full power */ + fNeedFullPower = eANI_BOOLEAN_TRUE; + reason = eSME_FULL_PWR_NEEDED_BY_TDLS_PEER_SETUP; + } +#endif + break; + case STOPPED: + /* We are not supposed to do anything */ + smsLog( pMac, LOGE, + FL("cannot process because PMC is in stopped/standby state %d"), + pmcState ); + status = eHAL_STATUS_FAILURE; + break; + default: + /* No need to ask for full power. This has to be FULL_POWER state */ + break; + } + + if(pReason) + { + *pReason = reason; + } + if(pfNeedPower) + { + *pfNeedPower = fNeedFullPower; + } + return status; +} + +static eHalStatus csrRequestFullPower( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fNeedFullPower = eANI_BOOLEAN_FALSE; + tRequestFullPowerReason reason = eSME_REASON_OTHER; + + if(pMac->psOffloadEnabled) + status = csrPsOffloadIsFullPowerNeeded(pMac, pCommand, + &reason, &fNeedFullPower); + else + status = csrIsFullPowerNeeded(pMac, pCommand, &reason, + &fNeedFullPower); + + if( fNeedFullPower && HAL_STATUS_SUCCESS( status ) ) + { + if(!pMac->psOffloadEnabled) + { + status = pmcRequestFullPower(pMac, csrFullPowerCallback, + pMac, reason); + } + else + { + status = pmcOffloadRequestFullPower(pMac, pCommand->sessionId, + csrFullPowerOffloadCallback, + pMac, reason); + } + + } + return ( status ); +} + +tSmeCmd *csrGetCommandBuffer( tpAniSirGlobal pMac ) +{ + tSmeCmd *pCmd = smeGetCommandBuffer( pMac ); + if( pCmd ) + { + pMac->roam.sPendingCommands++; + } + return ( pCmd ); +} + +void csrReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + if (pMac->roam.sPendingCommands > 0) + { + //All command allocated through csrGetCommandBuffer need to + //decrement the pending count when releasing. + pMac->roam.sPendingCommands--; + smeReleaseCommand( pMac, pCommand ); + } + else + { + smsLog(pMac, LOGE, FL( "no pending commands")); + VOS_ASSERT(0); + } +} + +//Return SUCCESS is the command is queued, failed +eHalStatus csrQueueSmeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fHighPriority ) +{ + eHalStatus status; + + if (!SME_IS_START(pMac)) { + smsLog(pMac, LOGE, FL("Sme in stop state")); + return eHAL_STATUS_FAILURE; + } + + if( (eSmeCommandScan == pCommand->command) && pMac->scan.fDropScanCmd ) + { + smsLog(pMac, LOGW, FL(" drop scan (scan reason %d) command"), + pCommand->u.scanCmd.reason); + return eHAL_STATUS_CSR_WRONG_STATE; + } + + if (((pMac->fScanOffload) && (pCommand->command == eSmeCommandScan)) || + ((pMac->fP2pListenOffload) && + (pCommand->command == eSmeCommandRemainOnChannel))) + { + csrLLInsertTail(&pMac->sme.smeScanCmdPendingList, + &pCommand->Link, LL_ACCESS_LOCK); + // process the command queue... + smeProcessPendingQueue(pMac); + status = eHAL_STATUS_SUCCESS; + goto end; + } + + //We can call request full power first before putting the command into pending Q + //because we are holding SME lock at this point. + status = csrRequestFullPower( pMac, pCommand ); + if( HAL_STATUS_SUCCESS( status ) ) + { + tANI_BOOLEAN fNoCmdPending; + //make sure roamCmdPendingList is not empty first + fNoCmdPending = csrLLIsListEmpty( &pMac->roam.roamCmdPendingList, eANI_BOOLEAN_FALSE ); + if( fNoCmdPending ) + { + smePushCommand( pMac, pCommand, fHighPriority ); + } + else + { + //Other commands are waiting for PMC callback, queue the new command to the pending Q + //no list lock is needed since SME lock is held + if( !fHighPriority ) + { + csrLLInsertTail( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE ); + } + else { + csrLLInsertHead( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE ); + } + } + } + else if( eHAL_STATUS_PMC_PENDING == status ) + { + //no list lock is needed since SME lock is held + if( !fHighPriority ) + { + csrLLInsertTail( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE ); + } + else { + csrLLInsertHead( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE ); + } + //Let caller know the command is queue + status = eHAL_STATUS_SUCCESS; + } + else + { + //Not to decrease pMac->roam.sPendingCommands here. Caller will decrease it when it + //release the command. + smsLog( pMac, LOGE, FL( " cannot queue command %d" ), pCommand->command ); + } +end: + return ( status ); +} +eHalStatus csrRoamUpdateAPWPSIE( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirAPWPSIEs* pAPWPSIES ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirUpdateAPWPSIEsReq *pMsg; + tANI_U8 *pBuf = NULL, *wTmpBuf = NULL; + + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL( " Session does not exist for session id %d" ), sessionId); + return eHAL_STATUS_FAILURE; + } + + do + { + pMsg = vos_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, sizeof(tSirUpdateAPWPSIEsReq), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_UPDATE_APWPSIE_REQ); + + pBuf = (tANI_U8 *)&pMsg->transactionId; + + if (NULL == pBuf) + { + VOS_ASSERT(pBuf); + return eHAL_STATUS_FAILURE; + } + + wTmpBuf = pBuf; + // transactionId + *pBuf = 0; + *( pBuf + 1 ) = 0; + pBuf += sizeof(tANI_U16); + // bssId + vos_mem_copy((tSirMacAddr *)pBuf, &pSession->selfMacAddr, + sizeof(tSirMacAddr) ); + pBuf += sizeof(tSirMacAddr); + //sessionId + *pBuf++ = (tANI_U8)sessionId; + // APWPSIEs + vos_mem_copy((tSirAPWPSIEs *)pBuf, pAPWPSIES, sizeof(tSirAPWPSIEs)); + pBuf += sizeof(tSirAPWPSIEs); + pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32) + (pBuf - wTmpBuf))); //msg_header + msg + status = palSendMBMessage(pMac->hHdd, pMsg); + } while( 0 ); + return ( status ); +} +eHalStatus csrRoamUpdateWPARSNIEs( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirRSNie * pAPSirRSNie) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirUpdateAPWPARSNIEsReq *pMsg; + tANI_U8 *pBuf = NULL, *wTmpBuf = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL( " Session does not exist for session id %d" ), sessionId); + return eHAL_STATUS_FAILURE; + } + do + { + pMsg = vos_mem_malloc(sizeof(tSirUpdateAPWPARSNIEsReq)); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set(pMsg, sizeof( tSirUpdateAPWPARSNIEsReq ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SET_APWPARSNIEs_REQ); + pBuf = (tANI_U8 *)&pMsg->transactionId; + wTmpBuf = pBuf; + + if (NULL == pBuf) + { + VOS_ASSERT(pBuf); + return eHAL_STATUS_FAILURE; + } + // transactionId + *pBuf = 0; + *( pBuf + 1 ) = 0; + pBuf += sizeof(tANI_U16); + + // bssId + vos_mem_copy((tSirMacAddr *)pBuf, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + // sessionId + *pBuf++ = (tANI_U8)sessionId; + + // APWPARSNIEs + vos_mem_copy((tSirRSNie *)pBuf, pAPSirRSNie, sizeof(tSirRSNie)); + pBuf += sizeof(tSirRSNie); + pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf))); //msg_header + msg + status = palSendMBMessage(pMac->hHdd, pMsg); + } while( 0 ); + return ( status ); +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +eHalStatus +csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, + tpSirBssDescription pBssDescription) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tpSirFTPreAuthReq pftPreAuthReq; + tANI_U16 auth_req_len = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL == pSession) { + smsLog(pMac, LOGE, + FL("Session does not exist for session id(%d)"), sessionId); + return eHAL_STATUS_FAILURE; + } + + auth_req_len = sizeof(tSirFTPreAuthReq); + pftPreAuthReq = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len); + if (NULL == pftPreAuthReq) + { + smsLog(pMac, LOGE, + FL("Memory allocation for FT Preauth request failed")); + return eHAL_STATUS_RESOURCES; + } + // Save the SME Session ID here. We need it while processing the preauth response + pSession->ftSmeContext.smeSessionId = sessionId; + vos_mem_zero(pftPreAuthReq, auth_req_len); + + pftPreAuthReq->pbssDescription = (tpSirBssDescription)vos_mem_malloc( + sizeof(pBssDescription->length) + pBssDescription->length); + if (NULL == pftPreAuthReq->pbssDescription) + { + smsLog(pMac, LOGE, + FL("Memory allocation for FT Preauth request failed")); + vos_mem_free(pftPreAuthReq); + return eHAL_STATUS_RESOURCES; + } + + pftPreAuthReq->messageType = pal_cpu_to_be16(eWNI_SME_FT_PRE_AUTH_REQ); + + pftPreAuthReq->preAuthchannelNum = pBssDescription->channelId; + + vos_mem_copy((void *)&pftPreAuthReq->currbssId, + (void *)pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy((void *)&pftPreAuthReq->preAuthbssId, + (void *)pBssDescription->bssId, sizeof(tSirMacAddr)); + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csrRoamIs11rAssoc(pMac, sessionId) && + (pMac->roam.roamSession[sessionId].connectedProfile.AuthType != eCSR_AUTH_TYPE_OPEN_SYSTEM)) + { + pftPreAuthReq->ft_ies_length = + (tANI_U16)pSession->ftSmeContext.auth_ft_ies_length; + vos_mem_copy(pftPreAuthReq->ft_ies, pSession->ftSmeContext.auth_ft_ies, + pSession->ftSmeContext.auth_ft_ies_length); + } + else +#endif + { + pftPreAuthReq->ft_ies_length = 0; + } + vos_mem_copy(pftPreAuthReq->pbssDescription, pBssDescription, + sizeof(pBssDescription->length) + pBssDescription->length); + pftPreAuthReq->length = pal_cpu_to_be16(auth_req_len); + return palSendMBMessage(pMac->hHdd, pftPreAuthReq); +} +/*-------------------------------------------------------------------------- + * This will receive and process the FT Pre Auth Rsp from the current + * associated ap. + * + * This will invoke the hdd call back. This is so that hdd can now + * send the FTIEs from the Auth Rsp (Auth Seq 2) to the supplicant. + ------------------------------------------------------------------------*/ +void csrRoamFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; +#if defined(FEATURE_WLAN_LFR) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) + tCsrRoamInfo roamInfo; +#endif + eCsrAuthType conn_Auth_type; + tANI_U32 sessionId = pFTPreAuthRsp->smeSessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (NULL == pSession) + { + smsLog(pMac, LOGE, FL("pSession is NULL")); + return; + } + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + status = csrNeighborRoamPreauthRspHandler(pMac, pFTPreAuthRsp->smeSessionId, + pFTPreAuthRsp->status); + if (status != eHAL_STATUS_SUCCESS) { + /* + * Bail out if pre-auth was not even processed. + */ + smsLog(pMac, LOGE,FL("Preauth was not processed: %d SessionID: %d"), + status, sessionId); + return; + } +#endif + + /* The below function calls/timers should be invoked only if the pre-auth is successful */ + if (VOS_STATUS_SUCCESS != (VOS_STATUS)pFTPreAuthRsp->status) + return; + // Implies a success + pSession->ftSmeContext.FTState = eFT_AUTH_COMPLETE; + // Indicate SME QoS module the completion of Preauth success. This will trigger the creation of RIC IEs + pSession->ftSmeContext.psavedFTPreAuthRsp = pFTPreAuthRsp; + /* No need to notify qos module if this is a non 11r & ESE roam*/ + if (csrRoamIs11rAssoc(pMac, pFTPreAuthRsp->smeSessionId) +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) + || csrRoamIsESEAssoc(pMac, pFTPreAuthRsp->smeSessionId) +#endif + ) + { + sme_QosCsrEventInd(pMac, + pSession->ftSmeContext.smeSessionId, + SME_QOS_CSR_PREAUTH_SUCCESS_IND, NULL); + } + /* Start the pre-auth reassoc interval timer with a period of 400ms. When this expires, + * actual transition from the current to handoff AP is triggered */ + status = vos_timer_start(&pSession->ftSmeContext.preAuthReassocIntvlTimer, + 60); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Preauth reassoc interval timer start failed to start with status %d"), status); + return; + } + // Save the received response + vos_mem_copy((void *)&pSession->ftSmeContext.preAuthbssId, + (void *)pFTPreAuthRsp->preAuthbssId, sizeof(tCsrBssid)); + if (csrRoamIs11rAssoc(pMac, pFTPreAuthRsp->smeSessionId)) + csrRoamCallCallback(pMac, pFTPreAuthRsp->smeSessionId, NULL, 0, + eCSR_ROAM_FT_RESPONSE, eCSR_ROAM_RESULT_NONE); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + if (csrRoamIsESEAssoc(pMac, pFTPreAuthRsp->smeSessionId)) + { + /* read TSF */ + csrRoamReadTSF(pMac, (tANI_U8 *)roamInfo.timestamp, + pFTPreAuthRsp->smeSessionId); + // Save the bssid from the received response + vos_mem_copy((void *)&roamInfo.bssid, + (void *)pFTPreAuthRsp->preAuthbssId, sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, pFTPreAuthRsp->smeSessionId, &roamInfo, + 0, eCSR_ROAM_CCKM_PREAUTH_NOTIFY, 0); + } +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +#ifdef FEATURE_WLAN_LFR + // If Legacy Fast Roaming is enabled, signal the supplicant + // So he can send us a PMK-ID for this candidate AP. + if (csrRoamIsFastRoamEnabled(pMac, pFTPreAuthRsp->smeSessionId)) + { + // Save the bssid from the received response + vos_mem_copy((void *)&roamInfo.bssid, + (void *)pFTPreAuthRsp->preAuthbssId, sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, pFTPreAuthRsp->smeSessionId, &roamInfo, 0, eCSR_ROAM_PMK_NOTIFY, 0); + } + +#endif + + // If its an Open Auth, FT IEs are not provided by supplicant + // Hence populate them here + conn_Auth_type = + pMac->roam.roamSession[sessionId].connectedProfile.AuthType; + + pSession->ftSmeContext.addMDIE = FALSE; + // Done with it, init it. + pSession->ftSmeContext.psavedFTPreAuthRsp = NULL; + + if (csrRoamIs11rAssoc(pMac, pFTPreAuthRsp->smeSessionId) && + (conn_Auth_type == eCSR_AUTH_TYPE_OPEN_SYSTEM)) + { + tANI_U16 ft_ies_length; + ft_ies_length = pFTPreAuthRsp->ric_ies_length; + + if ( (pSession->ftSmeContext.reassoc_ft_ies) && + (pSession->ftSmeContext.reassoc_ft_ies_length)) + { + vos_mem_free(pSession->ftSmeContext.reassoc_ft_ies); + pSession->ftSmeContext.reassoc_ft_ies_length = 0; + pSession->ftSmeContext.reassoc_ft_ies = NULL; + } + + if (!ft_ies_length) + return; + + pSession->ftSmeContext.reassoc_ft_ies = vos_mem_malloc(ft_ies_length); + if ( NULL == pSession->ftSmeContext.reassoc_ft_ies ) + { + smsLog( pMac, LOGE, FL("Memory allocation failed for ft_ies")); + return; + } + else + { + // Copy the RIC IEs to reassoc IEs + vos_mem_copy(((tANI_U8 *)pSession->ftSmeContext.reassoc_ft_ies), + (tANI_U8 *)pFTPreAuthRsp->ric_ies, + pFTPreAuthRsp->ric_ies_length); + pSession->ftSmeContext.reassoc_ft_ies_length = ft_ies_length; + pSession->ftSmeContext.addMDIE = TRUE; + } + } +} +#endif + + + +/* + pBuf points to the beginning of the message + LIM packs disassoc rsp as below, + messageType - 2 bytes + messageLength - 2 bytes + sessionId - 1 byte + transactionId - 2 bytes (tANI_U16) + reasonCode - 4 bytes (sizeof(tSirResultCodes)) + peerMacAddr - 6 bytes +*/ +static void csrSerDesUnpackDiassocRsp(tANI_U8 *pBuf, tSirSmeDisassocRsp *pRsp) +{ + if(pBuf && pRsp) + { + pBuf += 4; //skip type and length + pRsp->sessionId = *pBuf++; + pal_get_U16( pBuf, (tANI_U16 *)&pRsp->transactionId ); + pBuf += 2; + pal_get_U32( pBuf, (tANI_U32 *)&pRsp->statusCode ); + pBuf += 4; + vos_mem_copy(pRsp->peerMacAddr, pBuf, 6); + } +} + +eHalStatus csrGetDefaultCountryCodeFrmNv(tpAniSirGlobal pMac, tANI_U8 *pCountry) +{ + static uNvTables nvTables; + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = vos_nv_readDefaultCountryTable( &nvTables ); + + /* read the country code from NV and use it */ + if ( VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + vos_mem_copy(pCountry, nvTables.defaultCountryTable.countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + return status; + } + else + { + vos_mem_copy(pCountry, "XXX", WNI_CFG_COUNTRY_CODE_LEN); + status = eHAL_STATUS_FAILURE; + return status; + } +} + +eHalStatus csrGetCurrentCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry) +{ + vos_mem_copy(pCountry, pMac->scan.countryCode11d, WNI_CFG_COUNTRY_CODE_LEN); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrSetTxPower(tpAniSirGlobal pMac, v_U8_t sessionId, v_U8_t mW) +{ + tSirSetTxPowerReq *pMsg = NULL; + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + pMsg = vos_mem_malloc(sizeof(tSirSetTxPowerReq)); + if ( NULL == pMsg ) return eHAL_STATUS_FAILURE; + vos_mem_set((void *)pMsg, sizeof(tSirSetTxPowerReq), 0); + pMsg->messageType = eWNI_SME_SET_TX_POWER_REQ; + pMsg->length = sizeof(tSirSetTxPowerReq); + pMsg->mwPower = mW; + vos_mem_copy((tSirMacAddr *)pMsg->bssId, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + status = palSendMBMessage(pMac->hHdd, pMsg); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" csr set TX Power Post MSG Fail %d "), status); + //pMsg is freed by palSendMBMessage + } + return status; +} + +/* Returns whether a session is in VOS_STA_MODE...or not */ +tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = NULL; + pSession = CSR_GET_SESSION ( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" %s: session %d not found "), __func__, sessionId); + return eANI_BOOLEAN_FALSE; + } + if ( !CSR_IS_SESSION_VALID ( pMac, sessionId ) ) + { + smsLog(pMac, LOGE, FL(" %s: Inactive session"), __func__); + return eANI_BOOLEAN_FALSE; + } + if ( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType ) + { + return eANI_BOOLEAN_FALSE; + } + /* There is a possibility that the above check may fail,because + * P2P CLI also uses the same BSSType (eCSR_BSS_TYPE_INFRASTRUCTURE) + * when it is connected.So,we may sneak through the above check even + * if we are not a STA mode INFRA station. So, if we sneak through + * the above condition, we can use the following check if we are + * really in STA Mode.*/ + + if ( NULL != pSession->pCurRoamProfile ) + { + if ( pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE ) + { + return eANI_BOOLEAN_TRUE; + } else { + return eANI_BOOLEAN_FALSE; + } + } + + return eANI_BOOLEAN_FALSE; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrHandoffRequest(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tCsrHandoffRequest *pHandoffInfo) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + vos_msg_t msg; + + tAniHandoffReq *pMsg; + pMsg = vos_mem_malloc(sizeof(tAniHandoffReq)); + if ( NULL == pMsg ) + { + smsLog(pMac, LOGE, " csrHandoffRequest: failed to allocate mem for req "); + return eHAL_STATUS_FAILURE; + } + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_HANDOFF_REQ); + pMsg->msgLen = (tANI_U16)sizeof(tAniHandoffReq); + pMsg->sessionId = sessionId; + pMsg->channel = pHandoffInfo->channel; + pMsg->handoff_src = pHandoffInfo->src; + vos_mem_copy(pMsg->bssid, + pHandoffInfo->bssid, + 6); + msg.type = eWNI_SME_HANDOFF_REQ; + msg.bodyptr = pMsg; + msg.reserved = 0; + if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg)) + { + smsLog(pMac, LOGE, " csrHandoffRequest failed to post msg to self "); + vos_mem_free((void *)pMsg); + status = eHAL_STATUS_FAILURE; + } + return status; +} +#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* --------------------------------------------------------------------------- + \fn csrSetCCKMIe + \brief This function stores the CCKM IE passed by the supplicant + in a place holder data structure and this IE will be packed inside + reassociation request + \param pMac - pMac global structure + \param sessionId - Current session id + \param pCckmIe - pointer to CCKM IE data + \param ccKmIeLen - length of the CCKM IE + \- return Success or failure + -------------------------------------------------------------------------*/ +VOS_STATUS csrSetCCKMIe(tpAniSirGlobal pMac, const tANI_U8 sessionId, + const tANI_U8 *pCckmIe, + const tANI_U8 ccKmIeLen) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(pSession->suppCckmIeInfo.cckmIe, pCckmIe, + ccKmIeLen); + pSession->suppCckmIeInfo.cckmIeLen = ccKmIeLen; + return status; +} + +/* --------------------------------------------------------------------------- + \fn csrRoamReadTSF + \brief This function reads the TSF; and also add the time elapsed since + last beacon or probe response reception from the hand off AP to arrive at + the latest TSF value. + \param pMac - pMac global structure + \param pTimestamp - output TSF time stamp + \- return Success or failure + -------------------------------------------------------------------------*/ +VOS_STATUS csrRoamReadTSF(tpAniSirGlobal pMac, tANI_U8 *pTimestamp, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamBSSInfo handoffNode; + tANI_U32 timer_diff = 0; + tANI_U32 timeStamp[2]; + tpSirBssDescription pBssDescription = NULL; + csrNeighborRoamGetHandoffAPInfo(pMac, &handoffNode, sessionId); + pBssDescription = handoffNode.pBssDescription; + // Get the time diff in milli seconds + timer_diff = vos_timer_get_system_time() - pBssDescription->scanSysTimeMsec; + // Convert msec to micro sec timer + timer_diff = (tANI_U32)(timer_diff * SYSTEM_TIME_MSEC_TO_USEC); + timeStamp[0] = pBssDescription->timeStamp[0]; + timeStamp[1] = pBssDescription->timeStamp[1]; + UpdateCCKMTSF(&(timeStamp[0]), &(timeStamp[1]), &timer_diff); + vos_mem_copy(pTimestamp, (void *) &timeStamp[0], + sizeof (tANI_U32) * 2); + return status; +} +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/* + * Post Channel Change Request to LIM + * This API is primarily used to post + * Channel Change Req for SAP + */ +eHalStatus +csrRoamChannelChangeReq(tpAniSirGlobal pMac, tCsrBssid bssid, + tANI_U8 cbMode, tCsrRoamProfile *pprofile) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirChanChangeRequest *pMsg; + tCsrRoamStartBssParams param; + + csrRoamGetBssStartParms(pMac, pprofile, ¶m); + pMsg = vos_mem_malloc( sizeof(tSirChanChangeRequest) ); + if (!pMsg) + { + return ( eHAL_STATUS_FAILURE ); + } + + vos_mem_set((void *)pMsg, sizeof( tSirChanChangeRequest ), 0); + + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_CHANNEL_CHANGE_REQ); + pMsg->messageLen = sizeof(tSirChanChangeRequest); + pMsg->targetChannel = pprofile->ChannelInfo.ChannelList[0]; + pMsg->cbMode = cbMode; + pMsg->vht_channel_width = pprofile->vht_channel_width; + pMsg->dot11mode = + csrTranslateToWNICfgDot11Mode(pMac,pMac->roam.configParam.uCfgDot11Mode); + + vos_mem_copy(pMsg->bssid, bssid, VOS_MAC_ADDR_SIZE); + vos_mem_copy((void*)&pMsg->operational_rateset, + (void*)¶m.operationalRateSet, sizeof(tSirMacRateSet)); + vos_mem_copy((void*)&pMsg->extended_rateset, (void*)¶m.extendedRateSet, + sizeof(tSirMacRateSet)); + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return ( status ); +} + +/* + * Post Beacon Tx Start request to LIM + * immediately after SAP CAC WAIT is + * completed without any RADAR indications. + */ +eHalStatus csrRoamStartBeaconReq( tpAniSirGlobal pMac, tCsrBssid bssid, + tANI_U8 dfsCacWaitStatus) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirStartBeaconIndication *pMsg; + + pMsg = vos_mem_malloc(sizeof(tSirStartBeaconIndication)); + + if (!pMsg) + { + return eHAL_STATUS_FAILURE; + } + + vos_mem_set((void *)pMsg, sizeof( tSirStartBeaconIndication ), 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_START_BEACON_REQ); + pMsg->messageLen = sizeof(tSirStartBeaconIndication); + pMsg->beaconStartStatus = dfsCacWaitStatus; + vos_mem_copy(pMsg->bssid, bssid, VOS_MAC_ADDR_SIZE); + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return ( status ); +} + + +/*---------------------------------------------------------------------------- + \fn csrRoamModifyAddIEs + \brief This function sends msg to modify the additional IE buffers in PE + \param pMac - pMac global structure + \param pModifyIE - pointer to tSirModifyIE structure + \param updateType - Type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus +csrRoamModifyAddIEs(tpAniSirGlobal pMac, + tSirModifyIE *pModifyIE, + eUpdateIEsType updateType) +{ + tpSirModifyIEsInd pModifyAddIEInd = NULL; + tANI_U8 *pLocalBuffer = NULL; + eHalStatus status; + + /* following buffer will be freed by consumer (PE) */ + pLocalBuffer = vos_mem_malloc(pModifyIE->ieBufferlength); + + if (NULL == pLocalBuffer) + { + smsLog(pMac, LOGE, FL("Memory Allocation Failure!!!")); + return eHAL_STATUS_FAILED_ALLOC; + } + + pModifyAddIEInd = vos_mem_malloc(sizeof(tSirModifyIEsInd)); + if (NULL == pModifyAddIEInd) + { + smsLog(pMac, LOGE, FL("Memory Allocation Failure!!!")); + vos_mem_free(pLocalBuffer); + return eHAL_STATUS_FAILED_ALLOC; + } + + /*copy the IE buffer */ + vos_mem_copy(pLocalBuffer, pModifyIE->pIEBuffer, pModifyIE->ieBufferlength); + vos_mem_zero(pModifyAddIEInd, sizeof(tSirModifyIEsInd)); + + pModifyAddIEInd->msgType = + pal_cpu_to_be16((tANI_U16)eWNI_SME_MODIFY_ADDITIONAL_IES); + pModifyAddIEInd->msgLen = sizeof(tSirModifyIEsInd); + + vos_mem_copy(pModifyAddIEInd->modifyIE.bssid, pModifyIE->bssid, + sizeof(tSirMacAddr)); + + pModifyAddIEInd->modifyIE.smeSessionId = pModifyIE->smeSessionId; + pModifyAddIEInd->modifyIE.notify = pModifyIE->notify; + pModifyAddIEInd->modifyIE.ieID = pModifyIE->ieID; + pModifyAddIEInd->modifyIE.ieIDLen = pModifyIE->ieIDLen; + pModifyAddIEInd->modifyIE.pIEBuffer = pLocalBuffer; + pModifyAddIEInd->modifyIE.ieBufferlength = pModifyIE->ieBufferlength; + + pModifyAddIEInd->updateType = updateType; + + status = palSendMBMessage(pMac->hHdd, pModifyAddIEInd); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + FL("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg" + "!!! status %d"), status); + vos_mem_free(pLocalBuffer); + } + return status; +} + + +/*---------------------------------------------------------------------------- + \fn csrRoamUpdateAddIEs + \brief This function sends msg to updates the additional IE buffers in PE + \param pMac - pMac global structure + \param sessionId - SME session id + \param bssid - BSSID + \param additionIEBuffer - buffer containing addition IE from hostapd + \param length - length of buffer + \param updateType - Type of buffer + \param append - append or replace completely + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus +csrRoamUpdateAddIEs(tpAniSirGlobal pMac, + tSirUpdateIE *pUpdateIE, + eUpdateIEsType updateType) +{ + tpSirUpdateIEsInd pUpdateAddIEs = NULL; + tANI_U8 *pLocalBuffer = NULL; + eHalStatus status; + + if (pUpdateIE->ieBufferlength != 0) + { + /* Following buffer will be freed by consumer (PE) */ + pLocalBuffer = vos_mem_malloc(pUpdateIE->ieBufferlength); + if (NULL == pLocalBuffer) + { + smsLog(pMac, LOGE, FL("Memory Allocation Failure!!!")); + return eHAL_STATUS_FAILED_ALLOC; + } + vos_mem_copy(pLocalBuffer, pUpdateIE->pAdditionIEBuffer, + pUpdateIE->ieBufferlength); + } + + pUpdateAddIEs = vos_mem_malloc( sizeof(tSirUpdateIEsInd) ); + if (NULL == pUpdateAddIEs) + { + smsLog(pMac, LOGE, FL("Memory Allocation Failure!!!")); + if (pLocalBuffer != NULL) + { + vos_mem_free(pLocalBuffer); + } + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(pUpdateAddIEs, sizeof(tSirUpdateIEsInd)); + + pUpdateAddIEs->msgType = + pal_cpu_to_be16((tANI_U16)eWNI_SME_UPDATE_ADDITIONAL_IES); + pUpdateAddIEs->msgLen = sizeof(tSirUpdateIEsInd); + + vos_mem_copy(pUpdateAddIEs->updateIE.bssid, pUpdateIE->bssid, sizeof(tSirMacAddr)); + + pUpdateAddIEs->updateIE.smeSessionId = pUpdateIE->smeSessionId; + pUpdateAddIEs->updateIE.append = pUpdateIE->append; + pUpdateAddIEs->updateIE.notify = pUpdateIE->notify; + pUpdateAddIEs->updateIE.ieBufferlength = pUpdateIE->ieBufferlength; + pUpdateAddIEs->updateIE.pAdditionIEBuffer = pLocalBuffer; + + pUpdateAddIEs->updateType = updateType; + + status = palSendMBMessage(pMac->hHdd, pUpdateAddIEs); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + FL("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg" + "!!! status %d"), status); + vos_mem_free(pLocalBuffer); + } + return status; +} + +/** + * csr_send_ext_change_channel()- function to post send ECSA + * action frame to lim. + * @mac_ctx: pointer to global mac structure + * @channel: new channel to switch + * @session_id: senssion it should be sent on. + * + * This function is called to post ECSA frame to lim. + * + * Return: success if msg posted to LIM else return failure + */ +eHalStatus csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, uint32_t channel, + uint8_t session_id) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + struct sir_sme_ext_cng_chan_req *msg; + + msg = vos_mem_malloc(sizeof(*msg)); + if (NULL == msg) + return eHAL_STATUS_FAILURE; + + vos_mem_zero(msg, sizeof(*msg)); + msg->message_type = + pal_cpu_to_be16((uint16_t)eWNI_SME_EXT_CHANGE_CHANNEL); + msg->length = + pal_cpu_to_be16((uint16_t)sizeof(*msg)); + msg->new_channel = channel; + msg->session_id = session_id; + status = palSendMBMessage(mac_ctx->hHdd, msg); + return status; +} + + +/*---------------------------------------------------------------------------- + \fn csrRoamSendChanSwIERequest + \brief This function sends request to transmit channel switch announcement + IE to lower layers + \param pMac - pMac global structure + \param sessionId - SME session id + \param pDfsCacInd - CAC indication data to PE/LIM + \param ch_bandwidth - Channel offset + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus +csrRoamSendChanSwIERequest(tpAniSirGlobal pMac, tCsrBssid bssid, + tANI_U8 targetChannel, tANI_U8 csaIeReqd, + u_int8_t ch_bandwidth) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirDfsCsaIeRequest *pMsg; + + pMsg = vos_mem_malloc(sizeof(tSirDfsCsaIeRequest)); + if (!pMsg) + { + return eHAL_STATUS_FAILURE; + } + + vos_mem_set((void *)pMsg, sizeof(tSirDfsCsaIeRequest), 0); + pMsg->msgType = + pal_cpu_to_be16((tANI_U16)eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ); + pMsg->msgLen = sizeof(tSirDfsCsaIeRequest); + + pMsg->targetChannel = targetChannel; + pMsg->csaIeRequired = csaIeReqd; + vos_mem_copy(pMsg->bssid, bssid, VOS_MAC_ADDR_SIZE); + pMsg->ch_bandwidth = ch_bandwidth; + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return status; +} +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/*---------------------------------------------------------------------------- + * fn csrProcessRoamOffloadSynchInd + * brief This will receive and process the Roam Offload Synch Ind + * param hHal - pMac global structure + * param pSmeRoamOffloadSynchInd - Roam Synch info is retrieved + * --------------------------------------------------------------------------*/ +void csrProcessRoamOffloadSynchInd( + tHalHandle hHal, tpSirRoamOffloadSynchInd pSmeRoamOffloadSynchInd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = NULL; + tANI_U8 sessionId = pSmeRoamOffloadSynchInd->roamedVdevId; + pSession = CSR_GET_SESSION(pMac, pSmeRoamOffloadSynchInd->roamedVdevId); + if (!pSession) { + smsLog(pMac, LOGE, FL("LFR3: session %d not found "), + pSmeRoamOffloadSynchInd->roamedVdevId); + goto err_synch_rsp; + } + if (!HAL_STATUS_SUCCESS(csrScanSaveRoamOffloadApToScanCache(pMac, + pSmeRoamOffloadSynchInd))) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "fail to save roam offload AP to scan cache"); + goto err_synch_rsp; + } + pSession->roamOffloadSynchParams.rssi = pSmeRoamOffloadSynchInd->rssi; + pSession->roamOffloadSynchParams.roamReason = + pSmeRoamOffloadSynchInd->roamReason; + pSession->roamOffloadSynchParams.roamedVdevId = + pSmeRoamOffloadSynchInd->roamedVdevId; + vos_mem_copy(pSession->roamOffloadSynchParams.bssid, + pSmeRoamOffloadSynchInd->bssId, sizeof(tSirMacAddr)); + pSession->roamOffloadSynchParams.txMgmtPower = + pSmeRoamOffloadSynchInd->txMgmtPower; + pSession->roamOffloadSynchParams.authStatus = + pSmeRoamOffloadSynchInd->authStatus; + pSession->roamOffloadSynchParams.bRoamSynchInProgress = eANI_BOOLEAN_TRUE; + /*Save the BSS descriptor for later use*/ + pSession->roamOffloadSynchParams.pbssDescription = + pSmeRoamOffloadSynchInd->pbssDescription; + pMac->roam.reassocRespLen = pSmeRoamOffloadSynchInd->reassocRespLength; + pMac->roam.pReassocResp = + vos_mem_malloc(pMac->roam.reassocRespLen); + if (NULL == pMac->roam.pReassocResp) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Memory allocation for reassoc response failed"); + goto err_synch_rsp; + } + vos_mem_copy(pMac->roam.pReassocResp, + (tANI_U8 *)pSmeRoamOffloadSynchInd + + pSmeRoamOffloadSynchInd->reassocRespOffset, + pMac->roam.reassocRespLen); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "LFR3:%s: the reassoc resp frame data:", __func__); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + pMac->roam.pReassocResp, pMac->roam.reassocRespLen); + + vos_mem_copy(pSession->roamOffloadSynchParams.kck, + pSmeRoamOffloadSynchInd->kck, SIR_KCK_KEY_LEN); + vos_mem_copy(pSession->roamOffloadSynchParams.kek, + pSmeRoamOffloadSynchInd->kek, SIR_KEK_KEY_LEN); + vos_mem_copy(pSession->roamOffloadSynchParams.replay_ctr, + pSmeRoamOffloadSynchInd->replay_ctr, SIR_REPLAY_CTR_LEN); + + if (eHAL_STATUS_SUCCESS != csrNeighborRoamOffloadUpdatePreauthList(pMac, + pSmeRoamOffloadSynchInd, sessionId)) { + /* + * Bail out if Roam Offload Synch Response was not even handled. + */ + smsLog(pMac, LOGE, FL("Roam Offload Synch Response " + "was not processed")); + goto err_synch_rsp; + } + + csrNeighborRoamRequestHandoff(pMac, sessionId); + +err_synch_rsp: + vos_mem_free(pSmeRoamOffloadSynchInd->pbssDescription); + pSmeRoamOffloadSynchInd->pbssDescription = NULL; +} + +/*---------------------------------------------------------------------------- + * fn csrProcessHOFailInd + * brief This function will process the Hand Off Failure indication + * received from the firmware. It will trigger a disconnect on + * the session which the firmware reported a hand off failure + * param pMac global structure + * param pMsgBuf - Contains the session ID for which the handler should apply + * --------------------------------------------------------------------------*/ +void csrProcessHOFailInd(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tSirSmeHOFailureInd *pSmeHOFailInd = (tSirSmeHOFailureInd *)pMsgBuf; + tANI_U32 sessionId; + + if (pSmeHOFailInd) + sessionId = pSmeHOFailInd->sessionId; + else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "LFR3: Hand-Off Failure Ind is NULL"); + return; + } + /* Roaming is supported only on Infra STA Mode. */ + if (!csrRoamIsStaMode(pMac, sessionId)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "LFR3:HO Fail cannot be handled for session %d",sessionId); + return; + } + + csrRoamSynchCleanUp(pMac, sessionId); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "LFR3:Issue Disconnect on session %d", sessionId); + csrRoamDisconnect(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); +} +#endif + +void csrInitOperatingClasses(tHalHandle hHal) +{ + tANI_U8 Index = 0; + tANI_U8 class = 0; + tANI_U8 i = 0; + tANI_U8 j = 0; + tANI_U8 swap = 0; + tANI_U8 numChannels = 0; + tANI_U8 numClasses = 0; + tANI_BOOLEAN found; + tANI_U8 opClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + u_int8_t ch_bandwidth; + + smsLog(pMac, LOG1, FL("Current Country = %c%c"), + pMac->scan.countryCodeCurrent[0], + pMac->scan.countryCodeCurrent[1]); + + for (j = 0; j < SIR_MAC_MAX_SUPP_OPER_CLASSES; j++) { + opClasses[j] = 0; + } + + numChannels = pMac->scan.baseChannels.numChannels; + + smsLog(pMac, LOG1, FL("Num of base channels %d"), numChannels); + + for (Index = 0; + Index < numChannels && i < (SIR_MAC_MAX_SUPP_OPER_CLASSES - 1); + Index++) { + for (ch_bandwidth = BW20; ch_bandwidth < BWALL; ch_bandwidth++) { + class = regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, + pMac->scan.baseChannels.channelList[Index], + ch_bandwidth); + smsLog(pMac, LOG4, FL("for chan %d, op class: %d"), + pMac->scan.baseChannels.channelList[Index], + class); + + found = FALSE; + for (j = 0 ; j < SIR_MAC_MAX_SUPP_OPER_CLASSES - 1; j++) { + if (opClasses[j] == class) { + found = TRUE; + break; + } + } + + if (!found) { + opClasses[i]= class; + i++; + } + } + } + + numChannels = pMac->scan.base20MHzChannels.numChannels; + + smsLog(pMac, LOG1, FL("Num of 20MHz channels %d"), numChannels); + + for (Index = 0; + Index < numChannels && i < (SIR_MAC_MAX_SUPP_OPER_CLASSES - 1); + Index++) { + class = regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, + pMac->scan.base20MHzChannels.channelList[Index], + BWALL); + smsLog(pMac, LOG4, FL("for chan %d, op class: %d"), + pMac->scan.base20MHzChannels.channelList[ Index ], + class); + + found = FALSE; + for (j = 0 ; j < SIR_MAC_MAX_SUPP_OPER_CLASSES - 1; j++) { + if (opClasses[j] == class) { + found = TRUE; + break; + } + } + if (!found) { + opClasses[i]= class; + i++; + } + } + + numChannels = pMac->scan.base40MHzChannels.numChannels; + + smsLog(pMac, LOG1, FL("Num of 40MHz channels %d"), numChannels); + + for (Index = 0; + Index < numChannels && i < (SIR_MAC_MAX_SUPP_OPER_CLASSES - 1); + Index++) { + class = regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, + pMac->scan.base40MHzChannels.channelList[Index], + BWALL); + smsLog(pMac, LOG4, FL("for chan %d, op class: %d"), + pMac->scan.base40MHzChannels.channelList[ Index ], + class); + + found = FALSE; + for (j = 0 ; j < SIR_MAC_MAX_SUPP_OPER_CLASSES - 1; j++) { + if (opClasses[j] == class) { + found = TRUE; + break; + } + } + if (!found) { + opClasses[i]= class; + i++; + } + } + + numClasses = i; + + /* As per spec the operating classes should be in ascending order. + * Bubble sort is fine since we don't have many classes + */ + for (i = 0 ; i < (numClasses - 1); i++) { + for (j = 0 ; j < (numClasses - i - 1); j++) { + /* For decreasing order use < */ + if (opClasses[j] > opClasses[j+1]) { + swap = opClasses[j]; + opClasses[j] = opClasses[j+1]; + opClasses[j+1] = swap; + } + } + } + + smsLog(pMac, LOG1, FL("Total number of unique supported op classes %d"), + numClasses); + for (i = 0; i < numClasses; i++) { + smsLog(pMac, LOG1, FL("supported opClasses[%d] = %d"), i, + opClasses[i]); + } + + /* Set the ordered list of op classes in regdomain + * for use by other modules + */ + regdm_set_curr_opclasses(numClasses, &opClasses[0]); +} + +/** + * csr_find_sap_session() - This function will find the AP sessions from all + * sessions. + * @mac_ctx: pointer to mac context. + * + * This function is written to find the sap session id. + * + * Return: sap session id. + */ +static uint32_t csr_find_sap_session(tpAniSirGlobal mac_ctx) +{ + uint32_t i, session_id = CSR_SESSION_ID_INVALID; + tCsrRoamSession *session_ptr; + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID( mac_ctx, i)){ + session_ptr = CSR_GET_SESSION(mac_ctx, i); + if (VOS_STA_SAP_MODE == session_ptr->bssParams.bssPersona) { + /* Found it */ + session_id = i; + break; + } + } + } + return session_id; +} + +/** + * csr_find_p2pgo_session() - This function will find the p2pgo session from all + * sessions. + * @mac_ctx: pointer to mac context. + * + * This function is written to find the p2pgo session id. + * + * Return: p2pgo session id. + */ +static uint32_t csr_find_p2pgo_session(tpAniSirGlobal mac_ctx) +{ + uint32_t i, session_id = CSR_SESSION_ID_INVALID; + tCsrRoamSession *session_ptr; + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID( mac_ctx, i)){ + session_ptr = CSR_GET_SESSION(mac_ctx, i); + if (VOS_P2P_GO_MODE == session_ptr->bssParams.bssPersona) { + /* Found it */ + session_id = i; + break; + } + } + } + return session_id; +} + +/** + * csr_is_conn_allow_2g_band() - This function will check if station's conn + * is allowed in 2.4Ghz band. + * @mac_ctx: pointer to mac context. + * @chnl: station's channel. + * + * This function will check if station's connection is allowed in 5Ghz band + * after comparing it with SAP's operating channel. If SAP's operating + * channel and Station's channel is different than this function will return + * false else true. + * + * Return: true or false. + */ +static bool csr_is_conn_allow_2g_band(tpAniSirGlobal mac_ctx, uint32_t chnl) +{ + uint32_t sap_session_id; + tCsrRoamSession *sap_session; + + if (0 == chnl) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("channel is zero, connection not allowed")); + + return false; + } + + sap_session_id = csr_find_sap_session(mac_ctx); + if (CSR_SESSION_ID_INVALID != sap_session_id) { + sap_session = CSR_GET_SESSION(mac_ctx, sap_session_id); + if ((0 != sap_session->bssParams.operationChn) && + (sap_session->bssParams.operationChn != chnl)) { + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Can't allow STA to connect, channels not same")); + return false; + } + } + return true; +} + +/** + * csr_is_conn_allow_5g_band() - This function will check if station's conn + * is allowed in 5Ghz band. + * @mac_ctx: pointer to mac context. + * @chnl: station's channel. + * + * This function will check if station's connection is allowed in 5Ghz band + * after comparing it with P2PGO's operating channel. If P2PGO's operating + * channel and Station's channel is different than this function will return + * false else true. + * + * Return: true or false. + */ +static bool csr_is_conn_allow_5g_band(tpAniSirGlobal mac_ctx, uint32_t chnl) +{ + uint32_t p2pgo_session_id; + tCsrRoamSession *p2pgo_session; + + if (0 == chnl) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("channel is zero, connection not allowed")); + return false; + } + + p2pgo_session_id = csr_find_p2pgo_session(mac_ctx); + if (CSR_SESSION_ID_INVALID != p2pgo_session_id) { + p2pgo_session = CSR_GET_SESSION(mac_ctx, p2pgo_session_id); + if ((0 != p2pgo_session->bssParams.operationChn) && + (eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED != + p2pgo_session->connectState) && + (p2pgo_session->bssParams.operationChn != chnl)) { + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Can't allow STA to connect, channels not same")); + return false; + } + } + return true; +} + +/** + * csr_clear_joinreq_param() - This function will clear station's params + * for stored join request to csr. + * @hal_handle: pointer to hal context. + * @session_id: station's session id. + * + * This function will clear station's allocated memory for cached join + * request. + * + * Return: true or false based on function's overall success. + */ +bool csr_clear_joinreq_param(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + tCsrRoamSession *sta_session; + tScanResultList *bss_list; + + if (NULL == mac_ctx) { + return false; + } + + sta_session = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == sta_session) { + return false; + } + + /* Release the memory allocated by previous join request */ + bss_list = + (tScanResultList *)&sta_session->stored_roam_profile.bsslist_handle; + if (NULL != bss_list) { + csrScanResultPurge(mac_ctx, + sta_session->stored_roam_profile.bsslist_handle); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("bss list is released for session %d"), session_id); + sta_session->stored_roam_profile.bsslist_handle = NULL; + } + sta_session->stored_roam_profile.bsslist_handle = NULL; + csrReleaseProfile(mac_ctx, &sta_session->stored_roam_profile.profile); + sta_session->stored_roam_profile.reason = 0; + sta_session->stored_roam_profile.roam_id = 0; + sta_session->stored_roam_profile.imediate_flag = false; + sta_session->stored_roam_profile.clear_flag = false; + return true; +} + +/** + * csr_store_joinreq_param() - This function will store station's join + * request to that station's session. + * @mac_ctx: pointer to mac context. + * @profile: pointer to station's roam profile. + * @scan_cache: pointer to station's scan cache. + * @roam_id: reference to roam_id variable being passed. + * @session_id: station's session id. + * + * This function will store station's join request to one of the + * csr structure and add it to station's session. + * + * Return: true or false based on function's overall success. + */ +bool csr_store_joinreq_param(tpAniSirGlobal mac_ctx, + tCsrRoamProfile *profile, + tScanResultHandle scan_cache, + uint32_t *roam_id, + uint32_t session_id) +{ + tCsrRoamSession *sta_session; + + if (NULL == mac_ctx) { + return false; + } + + sta_session = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == sta_session) { + return false; + } + + sta_session->stored_roam_profile.session_id = session_id; + csrRoamCopyProfile(mac_ctx, &sta_session->stored_roam_profile.profile, + profile); + /* new bsslist_handle's memory will be relased later */ + sta_session->stored_roam_profile.bsslist_handle = scan_cache; + sta_session->stored_roam_profile.reason = eCsrHddIssued; + sta_session->stored_roam_profile.roam_id = *roam_id; + sta_session->stored_roam_profile.imediate_flag = false; + sta_session->stored_roam_profile.clear_flag = false; + + return true; +} + +/** + * csr_issue_stored_joinreq() - This function will issues station's stored + * the join request. + * @mac_ctx: pointer to mac context. + * @roam_id: reference to roam_id variable being passed. + * @session_id: station's session id. + * + * This function will issue station's stored join request, from this point + * onwards the flow will be just like normal connect request. + * + * Return: eHAL_STATUS_SUCCESS or eHAL_STATUS_FAILURE. + */ +eHalStatus csr_issue_stored_joinreq(tpAniSirGlobal mac_ctx, + uint32_t *roam_id, + uint32_t session_id) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *sta_session; + uint32_t new_roam_id; + + sta_session = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == sta_session) { + return eHAL_STATUS_FAILURE; + } + new_roam_id = GET_NEXT_ROAM_ID(&mac_ctx->roam); + *roam_id = new_roam_id; + status = csrRoamIssueConnect(mac_ctx, + sta_session->stored_roam_profile.session_id, + &sta_session->stored_roam_profile.profile, + sta_session->stored_roam_profile.bsslist_handle, + sta_session->stored_roam_profile.reason, + new_roam_id, + sta_session->stored_roam_profile.imediate_flag, + sta_session->stored_roam_profile.clear_flag); + if (!HAL_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("CSR failed to issue connect cmd with status = 0x%08X"), + status); + csr_clear_joinreq_param(mac_ctx, session_id); + } + return status; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiScan.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiScan.c new file mode 100644 index 000000000000..0336690cb3ab --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiScan.c @@ -0,0 +1,8878 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrApiScan.c + + Implementation for the Common Scan interfaces. +========================================================================== */ + +#include "aniGlobal.h" + +#include "palApi.h" +#include "csrInsideApi.h" +#include "smeInside.h" +#include "smsDebug.h" + +#include "csrSupport.h" +#include "wlan_qct_tl.h" + +#include "vos_diag_core_log.h" +#include "vos_diag_core_event.h" + +#include "vos_nvitem.h" +#include "vos_memory.h" +#include "wlan_qct_wda.h" +#include "vos_utils.h" + +#define MIN_CHN_TIME_TO_FIND_GO 100 +#define MAX_CHN_TIME_TO_FIND_GO 100 +#define DIRECT_SSID_LEN 7 + +/* + * Purpose of HIDDEN_TIMER + * When we remove hidden ssid from the profile i.e., forget the SSID via GUI + * that SSID shouldn't see in the profile for above requirement we used timer + * limit, logic is explained below timer value is initialized to current time + * when it receives corresponding probe response of hidden SSID + * (The probe request is received regularly till SSID in the profile. + * Once it is removed from profile probe request is not sent.) when we receive + * probe response for broadcast probe request, during update SSID with saved + * SSID we will diff current time with saved SSID time if it is greater than + * 1 min then we are not updating with old one. + */ + +#define HIDDEN_TIMER (1*60*1000) + +/* Must be less than 100, represent the percentage of new RSSI */ +#define CSR_SCAN_RESULT_RSSI_WEIGHT 80 + +#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL 140 +#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL 120 + +#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 30 +#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 20 + +#define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \ + ( (pMac)->scan.nBssLimit <= (csrLLCount(&(pMac)->scan.scanResultList)) ) + +//*** This is temporary work around. It need to call CCM api to get to CFG later +/// Get string parameter value +extern tSirRetStatus wlan_cfgGetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32*); + +void csrScanGetResultTimerHandler(void *); +static void csrScanResultCfgAgingTimerHandler(void *pv); +void csrScanIdleScanTimerHandler(void *); +static void csrSetDefaultScanTiming( tpAniSirGlobal pMac, tSirScanType scanType, tCsrScanRequest *pScanRequest); +#ifdef WLAN_AP_STA_CONCURRENCY +static void csrStaApConcTimerHandler(void *); +#endif +tANI_BOOLEAN csrIsSupportedChannel(tpAniSirGlobal pMac, tANI_U8 channelId); +eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +void csrSetCfgValidChannelList( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels ); +void csrSaveTxPowerToCfg( tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 cfgId ); +void csrSetCfgCountryCode( tpAniSirGlobal pMac, tANI_U8 *countryCode ); +void csrPurgeChannelPower( tpAniSirGlobal pMac, tDblLinkList *pChannelList ); +//if bgPeriod is 0, background scan is disabled. It is in millisecond units +eHalStatus csrSetCfgBackgroundScanPeriod(tpAniSirGlobal pMac, tANI_U32 bgPeriod); +eHalStatus csrProcessSetBGScanParam(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrReleaseScanCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus); +static tANI_BOOLEAN csrScanValidateScanResult( tpAniSirGlobal pMac, tANI_U8 *pChannels, + tANI_U8 numChn, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs **ppIes ); +eHalStatus csrSetBGScanChannelList( tpAniSirGlobal pMac, tANI_U8 *pAdjustChannels, tANI_U8 NumAdjustChannels); +void csrReleaseCmdSingle(tpAniSirGlobal pMac, tSmeCmd *pCommand); +tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel ); +void csrPruneChannelListForMode( tpAniSirGlobal pMac, tCsrChannel *pChannelList ); + +#define CSR_IS_SOCIAL_CHANNEL(channel) (((channel) == 1) || ((channel) == 6) || ((channel) == 11) ) + + + +static void csrReleaseScanCmdPendingList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + + while((pEntry = csrLLRemoveHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK)) != NULL) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( eSmeCsrCommandMask & pCommand->command ) + { + csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_TRUE ); + } + else + { + smsLog(pMac, LOGE, FL("Error: Received command : %d"),pCommand->command); + } + } +} +//pResult is invalid calling this function. +void csrFreeScanResultEntry( tpAniSirGlobal pMac, tCsrScanResult *pResult ) +{ + if( NULL != pResult->Result.pvIes ) + { + vos_mem_free(pResult->Result.pvIes); + } + vos_mem_free(pResult); +} + + +static eHalStatus csrLLScanPurgeResult(tpAniSirGlobal pMac, tDblLinkList *pList) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry; + tCsrScanResult *pBssDesc; + + csrLLLock(pList); + + while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_NOLOCK)) != NULL) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + csrFreeScanResultEntry( pMac, pBssDesc ); + } + + csrLLUnlock(pList); + + return (status); +} + +eHalStatus csrScanOpen( tpAniSirGlobal pMac ) +{ + eHalStatus status; + + do + { + csrLLOpen(pMac->hHdd, &pMac->scan.scanResultList); + csrLLOpen(pMac->hHdd, &pMac->scan.tempScanResults); + csrLLOpen(pMac->hHdd, &pMac->scan.channelPowerInfoList24); + csrLLOpen(pMac->hHdd, &pMac->scan.channelPowerInfoList5G); +#ifdef WLAN_AP_STA_CONCURRENCY + csrLLOpen(pMac->hHdd, &pMac->scan.scanCmdPendingList); +#endif + pMac->scan.fFullScanIssued = eANI_BOOLEAN_FALSE; + pMac->scan.nBssLimit = CSR_MAX_BSS_SUPPORT; + status = vos_timer_init(&pMac->scan.hTimerGetResult, VOS_TIMER_TYPE_SW, csrScanGetResultTimerHandler, pMac); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("cannot allocate memory for getResult timer")); + break; + } +#ifdef WLAN_AP_STA_CONCURRENCY + status = vos_timer_init(&pMac->scan.hTimerStaApConcTimer, VOS_TIMER_TYPE_SW, csrStaApConcTimerHandler, pMac); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("cannot allocate memory for hTimerStaApConcTimer timer")); + break; + } +#endif + status = vos_timer_init(&pMac->scan.hTimerIdleScan, VOS_TIMER_TYPE_SW, csrScanIdleScanTimerHandler, pMac); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("cannot allocate memory for idleScan timer")); + break; + } + status = vos_timer_init(&pMac->scan.hTimerResultCfgAging, VOS_TIMER_TYPE_SW, + csrScanResultCfgAgingTimerHandler, pMac); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("cannot allocate memory for CFG ResultAging timer")); + break; + } + }while(0); + + return (status); +} + + +eHalStatus csrScanClose( tpAniSirGlobal pMac ) +{ + csrLLScanPurgeResult(pMac, &pMac->scan.tempScanResults); + csrLLScanPurgeResult(pMac, &pMac->scan.scanResultList); +#ifdef WLAN_AP_STA_CONCURRENCY + csrReleaseScanCmdPendingList(pMac); +#endif + csrLLClose(&pMac->scan.scanResultList); + csrLLClose(&pMac->scan.tempScanResults); +#ifdef WLAN_AP_STA_CONCURRENCY + csrLLClose(&pMac->scan.scanCmdPendingList); +#endif + csrPurgeChannelPower(pMac, &pMac->scan.channelPowerInfoList24); + csrPurgeChannelPower(pMac, &pMac->scan.channelPowerInfoList5G); + csrLLClose(&pMac->scan.channelPowerInfoList24); + csrLLClose(&pMac->scan.channelPowerInfoList5G); + csrScanDisable(pMac); + vos_timer_destroy(&pMac->scan.hTimerResultCfgAging); + vos_timer_destroy(&pMac->scan.hTimerGetResult); +#ifdef WLAN_AP_STA_CONCURRENCY + vos_timer_destroy(&pMac->scan.hTimerStaApConcTimer); +#endif + vos_timer_destroy(&pMac->scan.hTimerIdleScan); + return eHAL_STATUS_SUCCESS; +} + + +eHalStatus csrScanEnable( tpAniSirGlobal pMac ) +{ + + pMac->scan.fScanEnable = eANI_BOOLEAN_TRUE; + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + + return eHAL_STATUS_SUCCESS; +} + + +eHalStatus csrScanDisable( tpAniSirGlobal pMac ) +{ + + csrScanStopTimers(pMac); + pMac->scan.fScanEnable = eANI_BOOLEAN_FALSE; + + return eHAL_STATUS_SUCCESS; +} + + +//Set scan timing parameters according to state of other driver sessions +//No validation of the parameters is performed. +static void csrSetDefaultScanTiming( tpAniSirGlobal pMac, tSirScanType scanType, tCsrScanRequest *pScanRequest) +{ +#ifdef WLAN_AP_STA_CONCURRENCY + if(csrIsAnySessionConnected(pMac)) + { + /* Reset passive scan time as per ini parameter. */ + ccmCfgSetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pMac->roam.configParam.nPassiveMaxChnTimeConc, + NULL, false); + //If multi-session, use the appropriate default scan times + if(scanType == eSIR_ACTIVE_SCAN) + { + pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTimeConc; + pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTimeConc; + } + else + { + pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTimeConc; + pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTimeConc; + } + pScanRequest->maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pScanRequest->minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + + pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc; + pScanRequest->min_rest_time = pMac->roam.configParam.min_rest_time_conc; + pScanRequest->idle_time = pMac->roam.configParam.idle_time_conc; + + + //Return so that fields set above will not be overwritten. + return; + } +#endif + + //This portion of the code executed if multi-session not supported + //(WLAN_AP_STA_CONCURRENCY not defined) or no multi-session. + //Use the "regular" (non-concurrency) default scan timing. + ccmCfgSetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pMac->roam.configParam.nPassiveMaxChnTime, + NULL,eANI_BOOLEAN_FALSE); + if(pScanRequest->scanType == eSIR_ACTIVE_SCAN) + { + pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTime; + } + else + { + pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; + pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTime; + } + pScanRequest->maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pScanRequest->minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + +#ifdef WLAN_AP_STA_CONCURRENCY + /* No rest time/Idle time if no sessions are connected. */ + pScanRequest->restTime = 0; + pScanRequest->min_rest_time = 0; + pScanRequest->idle_time = 0; +#endif +} + +#ifdef WLAN_AP_STA_CONCURRENCY +//Return SUCCESS is the command is queued, else returns eHAL_STATUS_FAILURE +eHalStatus csrQueueScanRequest(tpAniSirGlobal pMac, tANI_U8 sessionId, + tSmeCmd *pScanCmd) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + tANI_BOOLEAN fNoCmdPending; + tSmeCmd *pQueueScanCmd=NULL; + tSmeCmd *pSendScanCmd=NULL; + tANI_U8 nNumChanCombinedConc = 0; + if (NULL == pScanCmd) + { + smsLog (pMac, LOGE, FL("Scan Req cmd is NULL")); + return eHAL_STATUS_FAILURE; + } + /* split scan if any one of the following: + * - STA session is connected and the scan is not a P2P search + * - any P2P session is connected + * Do not split scans if no concurrent infra connections are + * active and if the scan is a BG scan triggered by LFR (OR) + * any scan if LFR is in the middle of a BG scan. Splitting + * the scan is delaying the time it takes for LFR to find + * candidates and resulting in disconnects. + */ + + if(csrIsStaSessionConnected(pMac) && + !csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + } + else if(csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; + } + if ( (csrIsStaSessionConnected(pMac) && +#ifdef FEATURE_WLAN_LFR + (csrIsConcurrentInfraConnected(pMac) || + ((pScanCmd->u.scanCmd.reason != eCsrScanBgScan) && + (pMac->roam.neighborRoamInfo[sessionId].neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN))) && +#endif + (pScanCmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) || + (csrIsP2pSessionConnected(pMac)) ) + { + tCsrScanRequest scanReq; + tANI_U8 numChn = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo; + tANI_U8 channelToScan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_BOOLEAN bMemAlloc = eANI_BOOLEAN_FALSE; + + if (numChn == 0) + { + + numChn = pMac->scan.baseChannels.numChannels; + + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(numChn); + if ( NULL == pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) + { + smsLog( pMac, LOGE, FL(" Failed to get memory for channel list ") ); + return eHAL_STATUS_FAILURE; + } + bMemAlloc = eANI_BOOLEAN_TRUE; + vos_mem_copy(pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, + pMac->scan.baseChannels.channelList, numChn); + status = eHAL_STATUS_SUCCESS; + if( !HAL_STATUS_SUCCESS( status ) ) + { + vos_mem_free(pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL; + smsLog( pMac, LOGE, FL(" Failed to copy memory to channel list ") ); + return eHAL_STATUS_FAILURE; + } + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn; + } + + //Whenever we get a scan request with multiple channels we break it up into 2 requests + //First request for first channel to scan and second request to scan remaining channels + if ( numChn > nNumChanCombinedConc) + { + vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); + + pQueueScanCmd = csrGetCommandBuffer(pMac); //optimize this to use 2 command buffer only + if (!pQueueScanCmd) + { + if (bMemAlloc) + { + vos_mem_free(pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL; + + } + smsLog( pMac, LOGE, FL(" Failed to get Queue command buffer") ); + return eHAL_STATUS_FAILURE; + } + pQueueScanCmd->command = pScanCmd->command; + pQueueScanCmd->sessionId = pScanCmd->sessionId; + pQueueScanCmd->u.scanCmd.callback = pScanCmd->u.scanCmd.callback; + pQueueScanCmd->u.scanCmd.pContext = pScanCmd->u.scanCmd.pContext; + pQueueScanCmd->u.scanCmd.reason = pScanCmd->u.scanCmd.reason; + pQueueScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around + + /* First copy all the parameters to local variable of scan request */ + csrScanCopyRequest(pMac, &scanReq, &pScanCmd->u.scanCmd.u.scanRequest); + + /* Now modify the elements of local var scan request required to be modified for split scan */ + if(scanReq.ChannelInfo.ChannelList != NULL) + { + vos_mem_free(scanReq.ChannelInfo.ChannelList); + scanReq.ChannelInfo.ChannelList = NULL; + } + + pChnInfo->numOfChannels = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels - nNumChanCombinedConc; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL(" &channelToScan %p pScanCmd(%p) pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList(%p)numChn(%d)"), + &channelToScan[0], pScanCmd, + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn); + + vos_mem_copy(&channelToScan[0], + &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[ + nNumChanCombinedConc], + pChnInfo->numOfChannels * sizeof(tANI_U8)); + + pChnInfo->ChannelList = &channelToScan[0]; + + scanReq.BSSType = eCSR_BSS_TYPE_ANY; + //Use concurrency values for min/maxChnTime. + //We know csrIsAnySessionConnected(pMac) returns TRUE here + csrSetDefaultScanTiming(pMac, scanReq.scanType, &scanReq); + + status = csrScanCopyRequest(pMac, &pQueueScanCmd->u.scanCmd.u.scanRequest, &scanReq); + + if(!HAL_STATUS_SUCCESS(status)) + { + if (bMemAlloc) + { + vos_mem_free(pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL; + + } + if( scanReq.pIEField != NULL) + { + vos_mem_free(scanReq.pIEField); + scanReq.pIEField = NULL; + } + smsLog( pMac, LOGE, FL(" Failed to get copy csrScanRequest = %d"), status ); + return eHAL_STATUS_FAILURE; + } + /* Clean the local scan variable */ + scanReq.ChannelInfo.ChannelList = NULL; + scanReq.ChannelInfo.numOfChannels = 0; + csrScanFreeRequest(pMac, &scanReq); + + /* setup the command to scan 2 channels */ + pSendScanCmd = pScanCmd; + pSendScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nNumChanCombinedConc; + pSendScanCmd->u.scanCmd.u.scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + //Use concurrency values for min/maxChnTime. + //We know csrIsAnySessionConnected(pMac) returns TRUE here + csrSetDefaultScanTiming(pMac, pSendScanCmd->u.scanCmd.u.scanRequest.scanType, &pSendScanCmd->u.scanCmd.u.scanRequest); + pSendScanCmd->u.scanCmd.callback = NULL; + } else { + pSendScanCmd = pScanCmd; + pSendScanCmd->u.scanCmd.u.scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + //Use concurrency values for min/maxChnTime. + //We know csrIsAnySessionConnected(pMac) returns TRUE here + csrSetDefaultScanTiming(pMac, pSendScanCmd->u.scanCmd.u.scanRequest.scanType, &pSendScanCmd->u.scanCmd.u.scanRequest); + } + + fNoCmdPending = csrLLIsListEmpty( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK ); + + //Logic Below is as follows + // If the scanCmdPendingList is empty then we directly send that command + // to smeCommandQueue else we buffer it in our scanCmdPendingList Queue + if( fNoCmdPending ) + { + if (pQueueScanCmd != NULL) + { + csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pQueueScanCmd->Link, LL_ACCESS_LOCK ); + } + + if (pSendScanCmd != NULL) + { + return csrQueueSmeCommand(pMac, pSendScanCmd, eANI_BOOLEAN_FALSE); + } + } + else + { + if (pSendScanCmd != NULL) + { + csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pSendScanCmd->Link, LL_ACCESS_LOCK ); + } + + if (pQueueScanCmd != NULL) + { + csrLLInsertTail( &pMac->scan.scanCmdPendingList, &pQueueScanCmd->Link, LL_ACCESS_LOCK ); + } + } + } + else + { //No concurrency case + smsLog( pMac, LOG2, FL("Queuing scan command (reason=%d, roamState=%d" + " numOfChannels=%d)"), + pScanCmd->u.scanCmd.reason, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState, + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels); + return csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); + } + + return ( status ); +} +#endif + +/** + * csrScan2GOnyRequest() - This function will update the scan request with + * only 2.4GHz valid channel list. + * @mac_ctx: Pointer to Global MAC structure + * @scan_cmd scan cmd + * @scan_req scan req + * + * This function will update the scan request with only 2.4GHz valid channel + * list. + * + * @Return: status of operation + */ +static eHalStatus csrScan2GOnyRequest(tpAniSirGlobal mac_ctx, + tSmeCmd *scan_cmd, + tCsrScanRequest *scan_req) +{ + uint8_t idx, lst_sz = 0; + + VOS_ASSERT(scan_cmd && scan_req); + /* To silence the KW tool null check is added */ + if ((scan_cmd == NULL) || (scan_req == NULL)) { + smsLog(mac_ctx, LOGE, FL(" Scan Cmd or Scan Request is NULL ")); + return eHAL_STATUS_INVALID_PARAMETER; + } + + if (eCSR_SCAN_REQUEST_FULL_SCAN != scan_req->requestType) + return eHAL_STATUS_SUCCESS; + + smsLog(mac_ctx, LOG1, + FL("Scanning only 2G Channels during first scan")); + + /* Contsruct valid Supported 2.4 GHz Channel List */ + if (NULL == scan_req->ChannelInfo.ChannelList) { + scan_req->ChannelInfo.ChannelList = + vos_mem_malloc(NUM_2_4GHZ_CHANNELS); + if (NULL == scan_req->ChannelInfo.ChannelList) { + smsLog(mac_ctx, LOGE, FL("Memory allocation failed.")); + return eHAL_STATUS_FAILED_ALLOC; + } + for (idx = 1; idx <= NUM_2_4GHZ_CHANNELS; idx++) { + if (csrIsSupportedChannel(mac_ctx, idx)) { + scan_req->ChannelInfo.ChannelList[lst_sz] = idx; + lst_sz++; + } + } + } + else { + for (idx = 0; idx < scan_req->ChannelInfo.numOfChannels; idx++) { + if (scan_req->ChannelInfo.ChannelList[idx] <= VOS_24_GHZ_CHANNEL_14 + && csrIsSupportedChannel(mac_ctx, + scan_req->ChannelInfo.ChannelList[idx])) { + scan_req->ChannelInfo.ChannelList[lst_sz] = + scan_req->ChannelInfo.ChannelList[idx]; + lst_sz++; + } + } + } + scan_req->ChannelInfo.numOfChannels = lst_sz; + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrScanRequest(tpAniSirGlobal pMac, tANI_U16 sessionId, + tCsrScanRequest *pScanRequest, tANI_U32 *pScanRequestID, + csrScanCompleteCallback callback, void *pContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tSmeCmd *pScanCmd = NULL; + eCsrConnectState ConnectState; + + if(pScanRequest == NULL) + { + smsLog( pMac, LOGE, FL(" pScanRequest is NULL")); + VOS_ASSERT(0); + return status; + } + + /* During group formation, the P2P client scans for GO with the specific SSID. + * There will be chances of GO switching to other channels because of scan or + * to STA channel in case of STA+GO MCC scenario. So to increase the possibility + * of client to find the GO, the dwell time of scan is increased to 100ms. + */ + if(pScanRequest->p2pSearch) + { + if ((pScanRequest->SSIDs.numOfSSIDs) && (NULL != pScanRequest->SSIDs.SSIDList)) + { + //If the scan request is for specific SSId the length of SSID will be + //greater than 7 as SSID for p2p search contains "DIRECT-") + if(pScanRequest->SSIDs.SSIDList->SSID.length > DIRECT_SSID_LEN) + { + smsLog( pMac, LOG1, FL("P2P: Increasing the min and max Dwell" + " time to %d for specific SSID scan %.*s"), + MAX_CHN_TIME_TO_FIND_GO, + pScanRequest->SSIDs.SSIDList->SSID.length, + pScanRequest->SSIDs.SSIDList->SSID.ssId); + pScanRequest->maxChnTime = MAX_CHN_TIME_TO_FIND_GO; + pScanRequest->minChnTime = MIN_CHN_TIME_TO_FIND_GO; + } + } + } + + do + { + if(pMac->scan.fScanEnable) + { + pScanCmd = csrGetCommandBuffer(pMac); + if(pScanCmd) + { + vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + pScanCmd->command = eSmeCommandScan; + pScanCmd->sessionId = sessionId; + if (pScanCmd->sessionId >= CSR_ROAM_SESSION_MAX) + smsLog( pMac, LOGE, FL("Invalid Sme Session ID = %d"), sessionId); + pScanCmd->u.scanCmd.callback = callback; + pScanCmd->u.scanCmd.pContext = pContext; + if(eCSR_SCAN_REQUEST_11D_SCAN == pScanRequest->requestType) + { + pScanCmd->u.scanCmd.reason = eCsrScan11d1; + } + else if((eCSR_SCAN_REQUEST_FULL_SCAN == pScanRequest->requestType) || + (eCSR_SCAN_P2P_DISCOVERY == pScanRequest->requestType) +#ifdef SOFTAP_CHANNEL_RANGE + ||(eCSR_SCAN_SOFTAP_CHANNEL_RANGE == pScanRequest->requestType) +#endif + ) + { + pScanCmd->u.scanCmd.reason = eCsrScanUserRequest; + } + else if(eCSR_SCAN_HO_BG_SCAN == pScanRequest->requestType) + { + pScanCmd->u.scanCmd.reason = eCsrScanBgScan; + } + else if(eCSR_SCAN_HO_PROBE_SCAN == pScanRequest->requestType) + { + pScanCmd->u.scanCmd.reason = eCsrScanProbeBss; + } + else if(eCSR_SCAN_P2P_FIND_PEER == pScanRequest->requestType) + { + pScanCmd->u.scanCmd.reason = eCsrScanP2PFindPeer; + } + else + { + pScanCmd->u.scanCmd.reason = eCsrScanIdleScan; + } + if(pScanRequest->minChnTime == 0 && pScanRequest->maxChnTime == 0) + { + //The caller doesn't set the time correctly. Set it here + csrSetDefaultScanTiming(pMac, pScanRequest->scanType, + pScanRequest); + smsLog(pMac, LOG1, FL("Setting default min %d and max %d" + " ChnTime"), pScanRequest->minChnTime, + pScanRequest->maxChnTime); + } +#ifdef WLAN_AP_STA_CONCURRENCY + if(pScanRequest->restTime == 0) + { + /* Need to set restTime/min_Ret_time/idle_time only + * if at least one session is connected + */ + if(csrIsAnySessionConnected(pMac)) + { + pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc; + pScanRequest->min_rest_time = pMac->roam.configParam.min_rest_time_conc; + pScanRequest->idle_time = pMac->roam.configParam.idle_time_conc; + if(pScanRequest->scanType == eSIR_ACTIVE_SCAN) + { + pScanRequest->maxChnTime = pMac->roam.configParam.nActiveMaxChnTimeConc; + pScanRequest->minChnTime = pMac->roam.configParam.nActiveMinChnTimeConc; + } + else + { + pScanRequest->maxChnTime = pMac->roam.configParam.nPassiveMaxChnTimeConc; + pScanRequest->minChnTime = pMac->roam.configParam.nPassiveMinChnTimeConc; + } + } + } +#endif + /* Increase dwell time in case P2P Search and Miracast is not present*/ + if(pScanRequest->p2pSearch && + pScanRequest->ChannelInfo.numOfChannels == P2P_SOCIAL_CHANNELS + && (!(pMac->sme.miracast_value))) { + pScanRequest->maxChnTime += P2P_SEARCH_DWELL_TIME_INCREASE; + } + + /*For Standalone wlan : channel time will remain the same. + For BTC with A2DP up: Channel time = Channel time * 2, if station is not already associated. + This has been done to provide a larger scan window for faster connection during btc.Else Scan is seen + to take a long time. + For BTC with A2DP up: Channel time will not be doubled, if station is already associated. + */ + status = csrRoamGetConnectState(pMac,sessionId,&ConnectState); + if (HAL_STATUS_SUCCESS(status) && + pMac->btc.fA2DPUp && + (eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED != ConnectState) && + (eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED != ConnectState)) + { + pScanRequest->maxChnTime = pScanRequest->maxChnTime << 1; + pScanRequest->minChnTime = pScanRequest->minChnTime << 1; + smsLog( pMac, LOG1, FL("BTC A2DP up, doubling max and min" + " ChnTime (Max=%d Min=%d)"), + pScanRequest->maxChnTime, + pScanRequest->minChnTime); + } + + pScanRequest->maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pScanRequest->minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + //Need to make the following atomic + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around + + if(pScanRequestID) + { + *pScanRequestID = pScanCmd->u.scanCmd.scanID; + } + + // If it is the first scan request from HDD, CSR checks if it is for 11d. + // If it is not, CSR will save the scan request in the pending cmd queue + // & issue an 11d scan request to PE. + if (((false == pMac->first_scan_done) + && (eCSR_SCAN_REQUEST_11D_SCAN != pScanRequest->requestType)) +#ifdef SOFTAP_CHANNEL_RANGE + && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != pScanRequest->requestType) +#endif + && (eANI_BOOLEAN_FALSE == pMac->scan.fEnableBypass11d) + ) + { + tSmeCmd *p11dScanCmd; + tCsrScanRequest scanReq; + tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo; + + vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); + + p11dScanCmd = csrGetCommandBuffer(pMac); + if (p11dScanCmd) + { + tANI_U32 numChn = pMac->scan.baseChannels.numChannels; + + vos_mem_set(&p11dScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + pChnInfo->ChannelList = vos_mem_malloc(numChn); + if ( NULL == pChnInfo->ChannelList ) + { + smsLog(pMac, LOGE, FL("Failed to allocate memory")); + status = eHAL_STATUS_FAILURE; + break; + } + vos_mem_copy(pChnInfo->ChannelList, + pMac->scan.baseChannels.channelList, + numChn); + + pChnInfo->numOfChannels = (tANI_U8)numChn; + p11dScanCmd->command = eSmeCommandScan; + p11dScanCmd->u.scanCmd.callback = pMac->scan.callback11dScanDone; + p11dScanCmd->u.scanCmd.pContext = NULL; + p11dScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; + scanReq.BSSType = eCSR_BSS_TYPE_ANY; + + if ( csrIs11dSupported(pMac) ) + { + scanReq.scanType = eSIR_PASSIVE_SCAN; + scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN; + p11dScanCmd->u.scanCmd.reason = eCsrScan11d1; + scanReq.maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; + scanReq.minChnTime = pMac->roam.configParam.nPassiveMinChnTime; + } + else + { + scanReq.scanType = pScanRequest->scanType; + scanReq.requestType = eCSR_SCAN_IDLE_MODE_SCAN; + p11dScanCmd->u.scanCmd.reason = eCsrScanIdleScan; + scanReq.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + scanReq.minChnTime = pMac->roam.configParam.nActiveMinChnTime; + + scanReq.maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + scanReq.minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + } + if (pMac->roam.configParam.nInitialDwellTime) + { + scanReq.maxChnTime = + pMac->roam.configParam.nInitialDwellTime; + smsLog(pMac, LOG1, FL("11d scan, updating" + "dwell time for first scan %u"), + scanReq.maxChnTime); + } + + status = csrScanCopyRequest(pMac, &p11dScanCmd->u.scanCmd.u.scanRequest, &scanReq); + //Free the channel list + vos_mem_free(pChnInfo->ChannelList); + pChnInfo->ChannelList = NULL; + + if (HAL_STATUS_SUCCESS(status)) + { + pMac->scan.scanProfile.numOfChannels = + p11dScanCmd->u.scanCmd.u.scanRequest. + ChannelInfo.numOfChannels; + //Start process the command +#ifdef WLAN_AP_STA_CONCURRENCY + if (!pMac->fScanOffload) + status = csrQueueScanRequest(pMac, sessionId, + p11dScanCmd); + else + status = csrQueueSmeCommand(pMac, p11dScanCmd, + eANI_BOOLEAN_FALSE); +#else + status = csrQueueSmeCommand(pMac, p11dScanCmd, eANI_BOOLEAN_FALSE); +#endif + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" Failed to send message" + " status = %d"), status); + break; + } + } + else + { + smsLog(pMac, LOGE, FL("csrScanCopyRequest failed")); + break; + } + } + else + { + //error + smsLog( pMac, LOGE, FL("p11dScanCmd failed") ); + break; + } + } + + //Scan only 2G Channels if set in ini file + //This is mainly to reduce the First Scan duration + //Once we turn on Wifi + if(pMac->scan.fFirstScanOnly2GChnl + && false == pMac->first_scan_done) { + status = csrScan2GOnyRequest(pMac, pScanCmd, pScanRequest); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, LOGE, FL("csrScan2GOnyRequest failed.")); + break; + } + } + + pMac->first_scan_done = true; + + if (pMac->roam.configParam.nInitialDwellTime) + { + pScanRequest->maxChnTime = + pMac->roam.configParam.nInitialDwellTime; + pMac->roam.configParam.nInitialDwellTime = 0; + smsLog(pMac, LOG1, + FL("updating dwell time for first scan %u"), + pScanRequest->maxChnTime); + } + + status = csrScanCopyRequest(pMac, &pScanCmd->u.scanCmd.u.scanRequest, pScanRequest); + /* + * Reset the variable after the first scan is queued after + * loading the driver. The purpose of this parameter is that + * DFS channels are skipped during the first scan after loading + * the driver. The above API builds the target scan request in + * which this variable is used. + */ + pMac->roam.configParam.initial_scan_no_dfs_chnl = 0; + if(HAL_STATUS_SUCCESS(status)) + { + tCsrScanRequest *pTempScanReq = + &pScanCmd->u.scanCmd.u.scanRequest; + pMac->scan.scanProfile.numOfChannels = + pTempScanReq->ChannelInfo.numOfChannels; + + smsLog(pMac, LOG1, FL(" SId=%d scanId=%d" + " Scan reason=%u numSSIDs=%d" + " numChan=%d P2P search=%d minCT=%d maxCT=%d" + " minCBtc=%d maxCBtx=%d uIEFieldLen=%d"), + sessionId, pScanCmd->u.scanCmd.scanID, + pScanCmd->u.scanCmd.reason, + pTempScanReq->SSIDs.numOfSSIDs, + pTempScanReq->ChannelInfo.numOfChannels, + pTempScanReq->p2pSearch, + pTempScanReq->minChnTime, + pTempScanReq->maxChnTime, + pTempScanReq->minChnTimeBtc, + pTempScanReq->maxChnTimeBtc, + pTempScanReq->uIEFieldLen); + + //Start process the command +#ifdef WLAN_AP_STA_CONCURRENCY + if (!pMac->fScanOffload) + status = csrQueueScanRequest(pMac, sessionId, pScanCmd); + else + status = csrQueueSmeCommand(pMac, pScanCmd, + eANI_BOOLEAN_FALSE); +#else + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); +#endif + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + } + else + { + smsLog( pMac, LOGE, FL(" fail to copy request status = %d"), status ); + break; + } + } + else + { + smsLog( pMac, LOGE, FL(" pScanCmd is NULL")); + break; + } + } + else + { + smsLog( pMac, LOGE, FL("SId: %d Scanning not enabled" + " Scan type=%u, numOfSSIDs=%d P2P search=%d"), + sessionId, pScanRequest->requestType, + pScanRequest->SSIDs.numOfSSIDs, + pScanRequest->p2pSearch ); + } + } while(0); + if(!HAL_STATUS_SUCCESS(status) && pScanCmd) + { + if( eCsrScanIdleScan == pScanCmd->u.scanCmd.reason ) + { + //Set the flag back for restarting idle scan + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + } + smsLog( pMac, LOGE, FL(" SId: %d Failed with status=%d" + " Scan reason=%u numOfSSIDs=%d" + " P2P search=%d scanId=%d"), + sessionId, status, pScanCmd->u.scanCmd.reason, + pScanRequest->SSIDs.numOfSSIDs, pScanRequest->p2pSearch, + pScanCmd->u.scanCmd.scanID ); + csrReleaseCommandScan(pMac, pScanCmd); + } + + return (status); +} + + +eHalStatus csrScanRequestResult(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pScanCmd; + + if(pMac->scan.fScanEnable) + { + pScanCmd = csrGetCommandBuffer(pMac); + if(pScanCmd) + { + pScanCmd->command = eSmeCommandScan; + vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + pScanCmd->u.scanCmd.callback = NULL; + pScanCmd->u.scanCmd.pContext = NULL; + pScanCmd->u.scanCmd.reason = eCsrScanGetResult; + //Need to make the following atomic + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandScan(pMac, pScanCmd); + } + } + else + { + //log error + smsLog(pMac, LOGE, FL("can not obtain a common buffer")); + status = eHAL_STATUS_RESOURCES; + } + } + + return (status); +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, + csrScanCompleteCallback callback, void *pContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pScanCmd; + + if (pMac->scan.fScanEnable) + { + pScanCmd = csrGetCommandBuffer(pMac); + if (pScanCmd) + { + pScanCmd->command = eSmeCommandScan; + pScanCmd->sessionId = sessionId; + vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + pScanCmd->u.scanCmd.callback = callback; + pScanCmd->u.scanCmd.pContext = pContext; + pScanCmd->u.scanCmd.reason = eCsrScanGetLfrResult; + //Need to make the following atomic + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_TRUE); + if ( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status ); + csrReleaseCommandScan(pMac, pScanCmd); + } + } + else + { + //log error + smsLog(pMac, LOGE, FL("can not obtain a common buffer\n")); + status = eHAL_STATUS_RESOURCES; + } + } + + return (status); +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +eHalStatus csrScanAllChannels(tpAniSirGlobal pMac, eCsrRequestType reqType) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 scanId; + tCsrScanRequest scanReq; + + vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); + scanReq.BSSType = eCSR_BSS_TYPE_ANY; + scanReq.scanType = eSIR_ACTIVE_SCAN; + scanReq.requestType = reqType; + scanReq.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + scanReq.minChnTime = pMac->roam.configParam.nActiveMinChnTime; + scanReq.maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + scanReq.minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + //Scan with invalid sessionId. + //This results in SME using the first available session to scan. + status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq, + &scanId, NULL, NULL); + + return (status); +} + + + + +eHalStatus csrIssueRoamAfterLostlinkScan(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamReason reason) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanResultHandle hBSSList = NULL; + tCsrScanResultFilter *pScanFilter = NULL; + tANI_U32 roamId = 0; + tCsrRoamProfile *pProfile = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + do + { + smsLog(pMac, LOG1, " csrIssueRoamAfterLostlinkScan called"); + if(pSession->fCancelRoaming) + { + smsLog(pMac, LOGW, " lost link roaming is canceled"); + csrScanStartIdleScan(pMac); + status = eHAL_STATUS_SUCCESS; + break; + } + //Here is the profile we need to connect to + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + break; + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + if(NULL == pSession->pCurRoamProfile) + { + pScanFilter->EncryptionType.numEntries = 1; + pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + } + else + { + //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect + pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( NULL == pProfile ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + break; + vos_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile); + if(!HAL_STATUS_SUCCESS(status)) + break; + status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); + }//We have a profile + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(HAL_STATUS_SUCCESS(status)) + { + if(eCsrLostLink1 == reason) + { + //we want to put the last connected BSS to the very beginning, if possible + csrMoveBssToHeadFromBSSID(pMac, &pSession->connectedProfile.bssid, hBSSList); + } + status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, reason, + roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + if(!HAL_STATUS_SUCCESS(status)) + { + csrScanResultPurge(pMac, hBSSList); + } + }//Have scan result + } + }while(0); + if(pScanFilter) + { + //we need to free memory for filter if profile exists + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + if(NULL != pProfile) + { + csrReleaseProfile(pMac, pProfile); + vos_mem_free(pProfile); + } + + return (status); +} + + +eHalStatus csrScanGetScanChnInfo(tpAniSirGlobal pMac, tANI_U8 sessionId, + void *pContext, void *callback, + tANI_U32 scanID) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pScanCmd; + + if(pMac->scan.fScanEnable) + { + pScanCmd = csrGetCommandBuffer(pMac); + if(pScanCmd) + { + pScanCmd->command = eSmeCommandScan; + vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + pScanCmd->u.scanCmd.callback = callback; + pScanCmd->u.scanCmd.pContext = pContext; + pScanCmd->u.scanCmd.reason = eCsrScanGetScanChnInfo; + if (callback) + { + //use same scanID as maintained in pAdapter + pScanCmd->u.scanCmd.scanID = scanID; + } + else + { + //Need to make the following atomic + pScanCmd->u.scanCmd.scanID = + pMac->scan.nextScanID++; //let it wrap around + } + + pScanCmd->sessionId = sessionId; + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandScan(pMac, pScanCmd); + } + } + else + { + //log error + smsLog(pMac, LOGE, FL("can not obtain a common buffer")); + status = eHAL_STATUS_RESOURCES; + } + } + + return (status); +} + + +eHalStatus csrScanHandleFailedLostlink1(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, "Lost link scan 1 failed"); + if(pSession->fCancelRoaming) + { + csrScanStartIdleScan(pMac); + } + else if(pSession->pCurRoamProfile) + { + //We fail lostlink1 but there may be other BSS in the cached result fit the profile. Give it a try first + if(pSession->pCurRoamProfile->SSIDs.numOfSSIDs == 0 || + pSession->pCurRoamProfile->SSIDs.numOfSSIDs > 1) + { + /* Try lost link scan2 */ + status = csrScanRequestLostLink2(pMac, sessionId); + } + else if(!pSession->pCurRoamProfile->ChannelInfo.ChannelList || + pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) + { + /* Go straight to lost link scan3 */ + status = csrScanRequestLostLink3(pMac, sessionId); + } + else + { + /* We are done with lost link */ + if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) + { + csrScanStartIdleScan(pMac); + } + status = eHAL_STATUS_SUCCESS; + } + } + else + { + status = csrScanRequestLostLink3(pMac, sessionId); + } + + return (status); +} + + + +eHalStatus csrScanHandleFailedLostlink2(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, "Lost link scan 2 failed"); + if(pSession->fCancelRoaming) + { + csrScanStartIdleScan(pMac); + } + else if(!pSession->pCurRoamProfile || !pSession->pCurRoamProfile->ChannelInfo.ChannelList || + pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) + { + /* Try lost link scan3 */ + status = csrScanRequestLostLink3(pMac, sessionId); + } + else + { + /* We are done with lost link */ + if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) + { + csrScanStartIdleScan(pMac); + } + } + + return (status); +} + + + +eHalStatus csrScanHandleFailedLostlink3(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(pMac, LOGW, "Lost link scan 3 failed"); + if(eANI_BOOLEAN_TRUE == csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) + { + /* We are done with lost link */ + csrScanStartIdleScan(pMac); + } + + return (status); +} + + + + +//Lostlink1 scan is to actively scan the last connected profile's SSID on all matched BSS channels. +//If no roam profile (it should not), it is like lostlinkscan3 +eHalStatus csrScanRequestLostLink1( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand = NULL; + tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tCsrScanResultFilter *pScanFilter = NULL; + tScanResultHandle hBSSList = NULL; + tCsrScanResultInfo *pScanResult = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, FL(" called")); + do + { + pCommand = csrGetCommandBuffer(pMac); + if(!pCommand) + { + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); + pCommand->command = eSmeCommandScan; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.scanCmd.reason = eCsrScanLostLink1; + pCommand->u.scanCmd.callback = NULL; + pCommand->u.scanCmd.pContext = NULL; + pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime; + pCommand->u.scanCmd.u.scanRequest.maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pCommand->u.scanCmd.u.scanRequest.minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + if(pSession->connectedProfile.SSID.length) + { + pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if ( NULL == pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 1; + vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID, + &pSession->connectedProfile.SSID, sizeof(tSirMacSSid)); + } + else + { + pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 0; + } + if(pSession->pCurRoamProfile) + { + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter); + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + //Don't change variable status here because whether we can get result or not, the command goes to PE. + //The status is also used to indicate whether the command is queued. Not success meaning not queue + if(HAL_STATUS_SUCCESS((csrScanGetResult(pMac, pScanFilter, &hBSSList))) && hBSSList) + { + tANI_U8 i, nChn = 0; + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = + vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); + if ( NULL == pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && + nChn < WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + for(i = 0; i < nChn; i++) + { + if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] == + pScanResult->BssDescriptor.channelId) + { + break; + } + } + if(i == nChn) + { + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pScanResult->BssDescriptor.channelId; + } + } + //Include the last connected BSS' channel + if(csrRoamIsChannelValid(pMac, pSession->connectedProfile.operationChannel)) + { + for(i = 0; i < nChn; i++) + { + if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] == + pSession->connectedProfile.operationChannel) + { + break; + } + } + if(i == nChn) + { + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pSession->connectedProfile.operationChannel; + } + } + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nChn; + } + else + { + if(csrRoamIsChannelValid(pMac, pSession->connectedProfile.operationChannel)) + { + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(1); + if ( NULL == pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + //just try the last connected channel + if(HAL_STATUS_SUCCESS(status)) + { + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0] = pSession->connectedProfile.operationChannel; + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 1; + } + else + { + break; + } + } + } + } + vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid)); + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + } while( 0 ); + + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, " csrScanRequestLostLink1 failed with status %d", status); + if(pCommand) + { + csrReleaseCommandScan(pMac, pCommand); + } + status = csrScanHandleFailedLostlink1( pMac, sessionId ); + } + if(pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + if(hBSSList) + { + csrScanResultPurge(pMac, hBSSList); + } + + return( status ); +} + + +//Lostlink2 scan is to actively scan the all SSIDs of the last roaming profile's on all matched BSS channels. +//Since MAC doesn't support multiple SSID, we scan all SSIDs and filter them afterwards +eHalStatus csrScanRequestLostLink2( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tCsrScanResultFilter *pScanFilter = NULL; + tScanResultHandle hBSSList = NULL; + tCsrScanResultInfo *pScanResult = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, FL(" called")); + do + { + pCommand = csrGetCommandBuffer(pMac); + if(!pCommand) + { + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); + pCommand->command = eSmeCommandScan; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.scanCmd.reason = eCsrScanLostLink2; + pCommand->u.scanCmd.callback = NULL; + pCommand->u.scanCmd.pContext = NULL; + pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime; + pCommand->u.scanCmd.u.scanRequest.maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pCommand->u.scanCmd.u.scanRequest.minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + if(pSession->pCurRoamProfile) + { + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + break; + } + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter); + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + if(hBSSList) + { + tANI_U8 i, nChn = 0; + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = + vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); + if ( NULL == pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + break; + } + while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && + nChn < WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + for(i = 0; i < nChn; i++) + { + if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] == + pScanResult->BssDescriptor.channelId) + { + break; + } + } + if(i == nChn) + { + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nChn++] = pScanResult->BssDescriptor.channelId; + } + } + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nChn; + } + } + vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid)); + //Put to the head in pending queue + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + } while( 0 ); + + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, " csrScanRequestLostLink2 failed with status %d", status); + if(pCommand) + { + csrReleaseCommandScan(pMac, pCommand); + } + status = csrScanHandleFailedLostlink2( pMac, sessionId ); + } + if(pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + if(hBSSList) + { + csrScanResultPurge(pMac, hBSSList); + } + + return( status ); +} + + +//To actively scan all valid channels +eHalStatus csrScanRequestLostLink3( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand; + tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + smsLog(pMac, LOGW, FL(" called")); + do + { + pCommand = csrGetCommandBuffer(pMac); + if(!pCommand) + { + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); + pCommand->command = eSmeCommandScan; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.scanCmd.reason = eCsrScanLostLink3; + pCommand->u.scanCmd.callback = NULL; + pCommand->u.scanCmd.pContext = NULL; + pCommand->u.scanCmd.u.scanRequest.maxChnTime = pMac->roam.configParam.nActiveMaxChnTime; + pCommand->u.scanCmd.u.scanRequest.minChnTime = pMac->roam.configParam.nActiveMinChnTime; + pCommand->u.scanCmd.u.scanRequest.maxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pCommand->u.scanCmd.u.scanRequest.minChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + vos_mem_copy(&pCommand->u.scanCmd.u.scanRequest.bssid, bAddr, sizeof(tCsrBssid)); + //Put to the head of pending queue + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + } while( 0 ); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGW, " csrScanRequestLostLink3 failed with status %d", status); + if(csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_FALSE, eCSR_ROAM_RESULT_FAILURE)) + { + csrScanStartIdleScan(pMac); + } + if(pCommand) + { + csrReleaseCommandScan(pMac, pCommand); + } + } + + return( status ); +} + + +eHalStatus csrScanHandleSearchForSSID(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE; + tCsrScanResultFilter *pScanFilter = NULL; + tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile; + tANI_U32 sessionId = pCommand->sessionId; + do + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* If this scan is for LFR */ + if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) { + /* Notify LFR state m/c */ + if (eHAL_STATUS_SUCCESS != csrNeighborRoamSssidScanDone(pMac, + sessionId, + eHAL_STATUS_SUCCESS)) { + csrNeighborRoamStartLfrScan(pMac, sessionId); + } + status = eHAL_STATUS_SUCCESS; + break; + } +#endif + //If there is roam command waiting, ignore this roam because the newer roam command is the one to execute + if(csrIsRoamCommandWaitingForSession(pMac, sessionId)) + { + smsLog(pMac, LOGW, FL(" aborts because roam command waiting")); + break; + } + if(pProfile == NULL) + break; + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + break; + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); + if(!HAL_STATUS_SUCCESS(status)) + break; + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(!HAL_STATUS_SUCCESS(status)) + break; + if (pMac->roam.roamSession[sessionId].connectState == + eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING) { + smsLog(pMac, LOGE, FL("upper layer issued disconnetion")); + status = eHAL_STATUS_FAILURE; + break; + } + status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued, + pCommand->u.scanCmd.roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + }while(0); + if(!HAL_STATUS_SUCCESS(status)) + { + if(CSR_INVALID_SCANRESULT_HANDLE != hBSSList) + { + csrScanResultPurge(pMac, hBSSList); + } + //We haven't done anything to this profile + csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_FAILURE, eCSR_ROAM_RESULT_FAILURE); + //In case we have nothing else to do, restart idle scan + if(csrIsConnStateDisconnected(pMac, sessionId) && !csrIsRoamCommandWaiting(pMac)) + { + status = csrScanStartIdleScan(pMac); + } + } + if (pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + + return (status); +} + + +eHalStatus csrScanHandleSearchForSSIDFailure(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 sessionId = pCommand->sessionId; + tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (!pSession) { + smsLog(pMac, LOGE, FL("Session %d not found"), sessionId); + return eHAL_STATUS_FAILURE; + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* If this scan is for LFR */ + if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) { + /* Notify LFR state m/c */ + if (eHAL_STATUS_SUCCESS != csrNeighborRoamSssidScanDone(pMac, + sessionId, + eHAL_STATUS_FAILURE)) { + csrNeighborRoamStartLfrScan(pMac, sessionId); + } + return eHAL_STATUS_SUCCESS; + } +#endif + +#if defined(WLAN_DEBUG) + if(pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1) + { + char str[36]; + vos_mem_copy(str, + pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.ssId, + pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.length); + str[pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID.length] = 0; + smsLog(pMac, LOGW, FL(" SSID = %s"), str); + } +#endif + //Check whether it is for start ibss. No need to do anything if it is a JOIN request + if(pProfile && CSR_IS_START_IBSS(pProfile)) + { + status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued, + pCommand->u.scanCmd.roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("failed to issue startIBSS command with status = 0x%08X"), status); + csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE); + } + } + else + { + eCsrRoamResult roamResult = eCSR_ROAM_RESULT_FAILURE; + + if(csrIsConnStateDisconnected(pMac, sessionId) && + !csrIsRoamCommandWaitingForSession(pMac, sessionId)) + { + status = csrScanStartIdleScan(pMac); + } + if((NULL == pProfile) || !csrIsBssTypeIBSS(pProfile->BSSType)) + { + //Only indicate assoc_completion if we indicate assoc_start. + if(pSession->bRefAssocStartCnt > 0) + { + tCsrRoamInfo *pRoamInfo = NULL, roamInfo; + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + pRoamInfo = &roamInfo; + if(pCommand->u.roamCmd.pRoamBssEntry) + { + tCsrScanResult *pScanResult = + GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, + tCsrScanResult, Link); + roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor; + } + roamInfo.statusCode = pSession->joinFailStatusCode.statusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + pSession->bRefAssocStartCnt--; + csrRoamCallCallback(pMac, sessionId, pRoamInfo, + pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_FAILURE); + } + else + { + csrRoamCallCallback(pMac, sessionId, NULL, + pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_FAILURE, + eCSR_ROAM_RESULT_FAILURE); + } + } + else + { + roamResult = eCSR_ROAM_RESULT_IBSS_START_FAILED; + } + csrRoamCompletion(pMac, sessionId, NULL, pCommand, roamResult, eANI_BOOLEAN_FALSE); + } + + return (status); +} + + +//After scan for cap changes, issue a roaming command to either reconnect to the AP or pick another one to connect +eHalStatus csrScanHandleCapChangeScanComplete(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanResultHandle hBSSList = NULL; + tCsrScanResultFilter *pScanFilter = NULL; + tANI_U32 roamId = 0; + tCsrRoamProfile *pProfile = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + do + { + //Here is the profile we need to connect to + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + break; + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + if (NULL == pSession) break; + if (NULL == pSession->pCurRoamProfile) + { + pScanFilter->EncryptionType.numEntries = 1; + pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE; + } + else + { + //We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect + pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( NULL == pProfile ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + break; + status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile); + if(!HAL_STATUS_SUCCESS(status)) + break; + status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter); + }//We have a profile + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(HAL_STATUS_SUCCESS(status)) + { + //we want to put the last connected BSS to the very beginning, if possible + csrMoveBssToHeadFromBSSID(pMac, &pSession->connectedProfile.bssid, hBSSList); + status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, + eCsrCapsChange, 0, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + if(!HAL_STATUS_SUCCESS(status)) + { + csrScanResultPurge(pMac, hBSSList); + } + }//Have scan result + else + { + smsLog(pMac, LOGW, FL("cannot find matching BSS of " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pSession->connectedProfile.bssid)); + //Disconnect + csrRoamDisconnectInternal(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + } + } + }while(0); + if(pScanFilter) + { + csrFreeScanFilter(pMac, pScanFilter); + vos_mem_free(pScanFilter); + } + if(NULL != pProfile) + { + csrReleaseProfile(pMac, pProfile); + vos_mem_free(pProfile); + } + + return (status); +} + + + +eHalStatus csrScanResultPurge(tpAniSirGlobal pMac, tScanResultHandle hScanList) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tScanResultList *pScanList = (tScanResultList *)hScanList; + + if(pScanList) + { + status = csrLLScanPurgeResult(pMac, &pScanList->List); + csrLLClose(&pScanList->List); + vos_mem_free(pScanList); + } + return (status); +} + +/** + * csr_get_altered_rssi() - Artificially increase/decrease RSSI + * @mac_ctx: Global MAC Context pointer. + * @rssi: Actual RSSI of the AP. + * @channel_id: Channel on which the AP is parked. + * @bssid: BSSID of the AP to connect to. + * + * This routine will apply the boost and penalty parameters + * if the channel_id is of 5G band and it will also apply + * the preferred bssid score if there is a match between + * the bssid and the global preferred bssid list. + * + * Return: The modified RSSI Value + */ +static int csr_get_altered_rssi(tpAniSirGlobal mac_ctx, int rssi, + uint8_t channel_id, tCsrBssid *bssid) +{ + int modified_rssi; + int boost_factor; + int penalty_factor; + int i; + struct roam_ext_params *roam_params; + tCsrBssid local_bssid; + + modified_rssi = rssi; + vos_mem_set(&local_bssid, 0, VOS_MAC_ADDR_SIZE); + if (bssid) + vos_mem_copy(&local_bssid, bssid, VOS_MAC_ADDR_SIZE); + roam_params = &mac_ctx->roam.configParam.roam_params; + /* + * If the 5G pref feature is enabled, apply the roaming + * parameters to boost or penalize the rssi. + * Boost Factor = boost_factor * (Actual RSSI - boost Threshold) + * Penalty Factor = penalty factor * (penalty threshold - Actual RSSI) + */ + if (CSR_IS_SELECT_5G_PREFERRED(mac_ctx) && + CSR_IS_CHANNEL_5GHZ(channel_id)) { + if (rssi > roam_params->raise_rssi_thresh_5g) { + /* Check and boost the threshold*/ + boost_factor = roam_params->raise_factor_5g * + (rssi - roam_params->raise_rssi_thresh_5g); + /* Check and penalize the threshold */ + modified_rssi += CSR_MIN(roam_params->max_raise_rssi_5g, + boost_factor); + } else if(rssi < roam_params->drop_rssi_thresh_5g) { + penalty_factor = roam_params->drop_factor_5g * + (roam_params->drop_rssi_thresh_5g - rssi); + modified_rssi -= CSR_MAX(roam_params->max_drop_rssi_5g, + penalty_factor); + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("5G BSSID("MAC_ADDRESS_STR") AR:%d, MR:%d, ch=%d"), + MAC_ADDR_ARRAY(local_bssid), rssi, + modified_rssi, channel_id); + } + /* + * Check if there are preferred bssid and then apply the + * preferred score + */ + if (roam_params->num_bssid_favored) { + for (i=0; inum_bssid_favored; i++) { + if (!csrIsMacAddressEqual(mac_ctx, + &roam_params->bssid_favored[i], bssid)) + continue; + modified_rssi += roam_params->bssid_favored_factor[i]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("Pref: ("MAC_ADDRESS_STR") AR:%d, MR:%d, ch=%d"), + MAC_ADDR_ARRAY(local_bssid), rssi, modified_rssi, + channel_id); + } + } + return modified_rssi; +} + +/** + * csrGetBssPreferValue() - Get BSS Preference Value + * @pMac: Global MAC Context pointer. + * @rssi: Actual RSSI of the AP. + * @bssid: BSSID of the AP to connect to. + * @channel_id: Channel on which the AP is parked. + * + * + * This routine helps in determining the preference value + * of a particular BSS in the scan result which is further + * used in the sorting logic of the final candidate AP's. + * + * Return: The preference Value for a BSS. + */ +static tANI_U32 csrGetBssPreferValue(tpAniSirGlobal pMac, int rssi, + tCsrBssid *bssid, int channel_id) +{ + tANI_U32 ret = 0; + int i, modified_rssi; + + /* + * The RSSI does not get modified in case the 5G + * preference or preferred BSSID is not applicable + */ + modified_rssi = csr_get_altered_rssi(pMac, rssi, channel_id, bssid); + + i = CSR_NUM_RSSI_CAT - 1; + while(i >= 0) { + if(modified_rssi >= pMac->roam.configParam.RSSICat[i]) { + ret = pMac->roam.configParam.BssPreferValue[i]; + break; + } + i--; + }; + return (ret); +} + + +//Return a CapValue base on the capabilities of a BSS +static tANI_U32 csrGetBssCapValue(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes) +{ + tANI_U32 ret = CSR_BSS_CAP_VALUE_NONE; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if(CSR_IS_ROAM_PREFER_5GHZ(pMac) || CSR_IS_SELECT_5G_PREFERRED(pMac)) + { + if((pBssDesc) && CSR_IS_CHANNEL_5GHZ(pBssDesc->channelId)) + { + ret += CSR_BSS_CAP_VALUE_5GHZ; + } + } +#endif + /* if strict select 5GHz is non-zero then ignore the capability checking */ + if (pIes && !CSR_IS_SELECT_5GHZ_MARGIN(pMac)) + { + //We only care about 11N capability + if (pIes->VHTCaps.present) + ret += CSR_BSS_CAP_VALUE_VHT; + else if (pIes->HTCaps.present) + ret += CSR_BSS_CAP_VALUE_HT; + if(CSR_IS_QOS_BSS(pIes)) + { + ret += CSR_BSS_CAP_VALUE_WMM; + //Give advantage to UAPSD + if(CSR_IS_UAPSD_BSS(pIes)) + { + ret += CSR_BSS_CAP_VALUE_UAPSD; + } + } + } + + return (ret); +} + +/** + * csr_is_better_rssi() - Is bss1 better than bss2 + * @mac_ctx: Global MAC Context pointer. + * @bss1: Pointer to the first BSS. + * @bss2: Pointer to the second BSS. + * + * + * This routine helps in determining the preference value + * of a particular BSS in the scan result which is further + * used in the sorting logic of the final candidate AP's. + * + * Return: true, if bss1 is better than bss2 + * false, if bss2 is better than bss1. + */ +static bool csr_is_better_rssi(tpAniSirGlobal mac_ctx, + tCsrScanResult *bss1, tCsrScanResult *bss2) +{ + bool ret; + int rssi1, rssi2; + + rssi1 = bss1->Result.BssDescriptor.rssi; + rssi2 = bss2->Result.BssDescriptor.rssi; + /* + * Apply the boost and penlty logic and check + * which is the best RSSI + */ + rssi1 = csr_get_altered_rssi(mac_ctx, rssi1, + bss1->Result.BssDescriptor.channelId, + &bss1->Result.BssDescriptor.bssId); + rssi2 = csr_get_altered_rssi(mac_ctx, rssi2, + bss2->Result.BssDescriptor.channelId, + &bss2->Result.BssDescriptor.bssId); + if (CSR_IS_BETTER_RSSI(rssi1, rssi2)) + ret = true; + else + ret = false; + return ret; +} +/* To check whether pBss1 is better than pBss2 */ +static tANI_BOOLEAN csrIsBetterBss(tpAniSirGlobal mac_ctx, + tCsrScanResult *pBss1, tCsrScanResult *pBss2) +{ + tANI_BOOLEAN ret; + + if(CSR_IS_BETTER_PREFER_VALUE(pBss1->preferValue, pBss2->preferValue)) + ret = eANI_BOOLEAN_TRUE; + else if(CSR_IS_EQUAL_PREFER_VALUE + (pBss1->preferValue, pBss2->preferValue)) { + if(CSR_IS_BETTER_CAP_VALUE(pBss1->capValue, pBss2->capValue)) + ret = eANI_BOOLEAN_TRUE; + else if (CSR_IS_EQUAL_CAP_VALUE + (pBss1->capValue, pBss2->capValue)) { + if (csr_is_better_rssi(mac_ctx, pBss1, pBss2)) + ret = eANI_BOOLEAN_TRUE; + else + ret = eANI_BOOLEAN_FALSE; + } + else + ret = eANI_BOOLEAN_FALSE; + } + else + ret = eANI_BOOLEAN_FALSE; + + return (ret); +} + + +#ifdef FEATURE_WLAN_LFR +//Add the channel to the occupiedChannels array +static void csrScanAddToOccupiedChannels( + tpAniSirGlobal pMac, + tCsrScanResult *pResult, + tANI_U8 sessionId, + tCsrChannel *pOccupiedChannels, + tDot11fBeaconIEs *pIes) +{ + eHalStatus status; + tANI_U8 channel; + tANI_U8 numOccupiedChannels = pOccupiedChannels->numChannels; + tANI_U8 *pOccupiedChannelList = pOccupiedChannels->channelList; + + channel = pResult->Result.BssDescriptor.channelId; + + if (!csrIsChannelPresentInList(pOccupiedChannelList, numOccupiedChannels, channel) + && csrNeighborRoamConnectedProfileMatch(pMac, sessionId, pResult, pIes)) + { + status = csrAddToChannelListFront(pOccupiedChannelList, numOccupiedChannels, channel); + if(HAL_STATUS_SUCCESS(status)) + { + pOccupiedChannels->numChannels++; + smsLog(pMac, LOG2, FL("Added channel %d to the list (count=%d)"), + channel, pOccupiedChannels->numChannels); + if (pOccupiedChannels->numChannels > CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN) + pOccupiedChannels->numChannels = CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN; + } + } +} +#endif + +//Put the BSS into the scan result list +//pIes can not be NULL +static void csrScanAddResult(tpAniSirGlobal pMac, tCsrScanResult *pResult, + tDot11fBeaconIEs *pIes, tANI_U32 sessionId) +{ +#ifdef FEATURE_WLAN_LFR + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; +#endif + tCsrBssid *bssid = &pResult->Result.BssDescriptor.bssId; + uint8_t channel_id = pResult->Result.BssDescriptor.channelId; + pResult->preferValue = csrGetBssPreferValue(pMac, + (int)pResult->Result.BssDescriptor.rssi, bssid, channel_id); + pResult->capValue = + csrGetBssCapValue(pMac, &pResult->Result.BssDescriptor, pIes); + csrLLInsertTail( &pMac->scan.scanResultList, &pResult->Link, LL_ACCESS_LOCK ); +#ifdef FEATURE_WLAN_LFR + if(0 == pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) + { + /* Build the occupied channel list, only if "gNeighborScanChannelList" is + NOT set in the cfg.ini file */ + csrScanAddToOccupiedChannels(pMac, pResult, sessionId, + &pMac->scan.occupiedChannels[sessionId], + pIes); + } +#endif +} + + +eHalStatus csrScanGetResult(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter, tScanResultHandle *phResult) +{ + eHalStatus status; + tScanResultList *pRetList; + tCsrScanResult *pResult, *pBssDesc; + tANI_U32 count = 0; + tListElem *pEntry; + tANI_U32 bssLen, allocLen; + eCsrEncryptionType uc = eCSR_ENCRYPT_TYPE_NONE, mc = eCSR_ENCRYPT_TYPE_NONE; + eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM; + tDot11fBeaconIEs *pIes, *pNewIes; + tANI_BOOLEAN fMatch; + tANI_U16 i = 0; + struct roam_ext_params *roam_params = NULL; + + if(phResult) + { + *phResult = CSR_INVALID_SCANRESULT_HANDLE; + } + + if (pMac->roam.configParam.nSelect5GHzMargin || + CSR_IS_SELECT_5G_PREFERRED(pMac)) + { + pMac->scan.inScanResultBestAPRssi = -128; + roam_params = &pMac->roam.configParam.roam_params; +#ifdef WLAN_DEBUG_ROAM_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("nSelect5GHzMargin")); +#endif + csrLLLock(&pMac->scan.scanResultList); + /* For 5G preference feature, there is no + * need to check the filter match and also re-program the + * RSSI bucket categories, since we use the RSSI values + * while setting the preference value for the BSS. + * There is no need to check the match for roaming since + * it is already done.*/ + if(!CSR_IS_SELECT_5G_PREFERRED(pMac)) { + /* Find out the best AP Rssi going thru the scan results */ + pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while ( NULL != pEntry) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + fMatch = FALSE; + + + if (pFilter) + for(i = 0; i < pFilter->SSIDs.numOfSSIDs; i++) + { + fMatch = csrIsSsidMatch( pMac, pFilter->SSIDs.SSIDList[i].SSID.ssId, pFilter->SSIDs.SSIDList[i].SSID.length, + pBssDesc->Result.ssId.ssId, + pBssDesc->Result.ssId.length, eANI_BOOLEAN_TRUE ); + if (fMatch) + { + pIes = (tDot11fBeaconIEs *)( pBssDesc->Result.pvIes ); + + //At this time, pBssDescription->Result.pvIes may be NULL + if( !pIes && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + &pBssDesc->Result.BssDescriptor, &pIes))) ) + { + continue; + } + + smsLog(pMac, LOG1, FL("SSID Matched")); + + if ( pFilter->bOSENAssociation ) + { + fMatch = TRUE; + } + else + { +#ifdef WLAN_FEATURE_11W + fMatch = csrIsSecurityMatch(pMac, &pFilter->authType, + &pFilter->EncryptionType, + &pFilter->mcEncryptionType, + &pFilter->MFPEnabled, + &pFilter->MFPRequired, + &pFilter->MFPCapable, + &pBssDesc->Result.BssDescriptor, + pIes, NULL, NULL, NULL ); +#else + fMatch = csrIsSecurityMatch(pMac, &pFilter->authType, + &pFilter->EncryptionType, + &pFilter->mcEncryptionType, + NULL, NULL, NULL, + &pBssDesc->Result.BssDescriptor, + pIes, NULL, NULL, NULL ); +#endif + } + if ((pBssDesc->Result.pvIes == NULL) && pIes) + vos_mem_free(pIes); + + if (fMatch) + smsLog(pMac, LOG1, FL(" Security Matched")); + } + } + + if (fMatch && (pBssDesc->Result.BssDescriptor.rssi > pMac->scan.inScanResultBestAPRssi)) + { + smsLog(pMac, LOG1, FL("Best AP Rssi changed from %d to %d"), + pMac->scan.inScanResultBestAPRssi, + pBssDesc->Result.BssDescriptor.rssi); + pMac->scan.inScanResultBestAPRssi = pBssDesc->Result.BssDescriptor.rssi; + } + pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); + } + } + + if ((-128 != pMac->scan.inScanResultBestAPRssi) || + CSR_IS_SELECT_5G_PREFERRED(pMac)) + { + smsLog(pMac, LOG1, FL("Best AP Rssi is %d"), pMac->scan.inScanResultBestAPRssi); + /* Modify Rssi category based on best AP Rssi */ + if (-128 != pMac->scan.inScanResultBestAPRssi) + csrAssignRssiForCategory(pMac, pMac->scan.inScanResultBestAPRssi, pMac->roam.configParam.bCatRssiOffset); + + pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while ( NULL != pEntry) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + + /* re-assign preference value based on (modified rssi bucket (or) + * prefer 5G feature.*/ + pBssDesc->preferValue = csrGetBssPreferValue(pMac, + (int)pBssDesc->Result.BssDescriptor.rssi, + &pBssDesc->Result.BssDescriptor.bssId, + pBssDesc->Result.BssDescriptor.channelId); + + smsLog(pMac, LOG2, FL("BSSID("MAC_ADDRESS_STR + ") Rssi(%d) Chnl(%d) PrefVal(%u) SSID=%.*s"), + MAC_ADDR_ARRAY(pBssDesc->Result.BssDescriptor.bssId), + pBssDesc->Result.BssDescriptor.rssi, + pBssDesc->Result.BssDescriptor.channelId, + pBssDesc->preferValue, + pBssDesc->Result.ssId.length, pBssDesc->Result.ssId.ssId); + + pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); + } + } + + csrLLUnlock(&pMac->scan.scanResultList); + } + + pRetList = vos_mem_malloc(sizeof(tScanResultList)); + if ( NULL == pRetList ) + status = eHAL_STATUS_FAILURE; + else + { + status = eHAL_STATUS_SUCCESS; + vos_mem_set(pRetList, sizeof(tScanResultList), 0); + csrLLOpen(pMac->hHdd, &pRetList->List); + pRetList->pCurEntry = NULL; + + csrLLLock(&pMac->scan.scanResultList); + pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK ); + while( pEntry ) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + pIes = (tDot11fBeaconIEs *)( pBssDesc->Result.pvIes ); + /* + * If pBssDesc->Result.pvIes is NULL, we need to free any memory + * allocated by csrMatchBSS for any error condition, otherwise, + * it will be freed later. + */ + fMatch = eANI_BOOLEAN_FALSE; + pNewIes = NULL; + + if(pFilter) + { + fMatch = csrMatchBSS(pMac, &pBssDesc->Result.BssDescriptor, pFilter, &auth, &uc, &mc, &pIes); +#ifdef WLAN_DEBUG_ROAM_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("csrMatchBSS fmatch %d"), fMatch); +#endif + if( NULL != pIes ) + { + //Only save it when matching + if(fMatch) + { + if( !pBssDesc->Result.pvIes ) + { + //csrMatchBSS allocates the memory. Simply pass it and it is freed later + pNewIes = pIes; + } + else + { + //The pIes is allocated by someone else. make a copy + //Only to save parsed IEs if caller provides a filter. Most likely the caller + //is using to for association, hence save the parsed IEs + pNewIes = vos_mem_malloc(sizeof(tDot11fBeaconIEs)); + if ( NULL == pNewIes ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if ( HAL_STATUS_SUCCESS( status ) ) + { + vos_mem_copy(pNewIes, pIes, sizeof( tDot11fBeaconIEs )); + } + else + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for IEs")); + //Need to free memory allocated by csrMatchBSS + if( !pBssDesc->Result.pvIes ) + { + vos_mem_free(pIes); + } + break; + } + } + }//fMatch + else if( !pBssDesc->Result.pvIes ) + { + vos_mem_free(pIes); + } + } + } + if(NULL == pFilter || fMatch) + { + bssLen = pBssDesc->Result.BssDescriptor.length + sizeof(pBssDesc->Result.BssDescriptor.length); + allocLen = sizeof( tCsrScanResult ) + bssLen; + pResult = vos_mem_malloc(allocLen); + if ( NULL == pResult ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for scan result, len=%d"), allocLen); + if(pNewIes) + { + vos_mem_free(pNewIes); + } + break; + } + vos_mem_set(pResult, allocLen, 0); + pResult->capValue = pBssDesc->capValue; + pResult->preferValue = pBssDesc->preferValue; + pResult->ucEncryptionType = uc; + pResult->mcEncryptionType = mc; + pResult->authType = auth; + pResult->Result.ssId = pBssDesc->Result.ssId; + pResult->Result.timer = pBssDesc->Result.timer; + //save the pIes for later use + pResult->Result.pvIes = pNewIes; + //save bss description + vos_mem_copy(&pResult->Result.BssDescriptor, + &pBssDesc->Result.BssDescriptor, bssLen); + //No need to lock pRetList because it is locally allocated and no outside can access it at this time + if(csrLLIsListEmpty(&pRetList->List, LL_ACCESS_NOLOCK)) + { + csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_NOLOCK); + } + else + { + //To sort the list + tListElem *pTmpEntry; + tCsrScanResult *pTmpResult; + + pTmpEntry = csrLLPeekHead(&pRetList->List, LL_ACCESS_NOLOCK); + while(pTmpEntry) + { + pTmpResult = GET_BASE_ADDR( pTmpEntry, tCsrScanResult, Link ); + if(csrIsBetterBss(pMac, pResult, pTmpResult)) + { + csrLLInsertEntry(&pRetList->List, pTmpEntry, &pResult->Link, LL_ACCESS_NOLOCK); + //To indicate we are done + pResult = NULL; + break; + } + pTmpEntry = csrLLNext(&pRetList->List, pTmpEntry, LL_ACCESS_NOLOCK); + } + if(pResult != NULL) + { + /* This one is'nt better than anyone or the first one */ + csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_NOLOCK); + } + } + count++; + } + pEntry = csrLLNext( &pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK ); + }//while + csrLLUnlock(&pMac->scan.scanResultList); + + smsLog(pMac, LOG2, FL("return %d BSS"), csrLLCount(&pRetList->List)); + + if( !HAL_STATUS_SUCCESS(status) || (phResult == NULL) ) + { + //Fail or No one wants the result. + csrScanResultPurge(pMac, (tScanResultHandle)pRetList); + } + else + { + if(0 == count) + { + //We are here meaning the there is no match + csrLLClose(&pRetList->List); + vos_mem_free(pRetList); + status = eHAL_STATUS_E_NULL_VALUE; + } + else if(phResult) + { + *phResult = pRetList; + } + } + }//Allocated pRetList + + return (status); +} + +/* + * NOTE: This routine is being added to make + * sure that scan results are not being flushed + * while roaming. If the scan results are flushed, + * we are unable to recover from + * csrRoamRoamingStateDisassocRspProcessor. + * If it is needed to remove this routine, + * first ensure that we recover gracefully from + * csrRoamRoamingStateDisassocRspProcessor if + * csrScanGetResult returns with a failure because + * of not being able to find the roaming BSS. + */ +tANI_U8 csrScanFlushDenied(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + switch(pMac->roam.neighborRoamInfo[sessionId].neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN: + case eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING: + case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE: + case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: + return (pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + default: + return 0; + } +} + +eHalStatus csrScanFlushResult(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tANI_U8 isFlushDenied = csrScanFlushDenied(pMac, sessionId); + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirMbMsg *pMsg; + tANI_U16 msgLen; + + if (isFlushDenied) { + smsLog(pMac, LOGW, "%s: scan flush denied in roam state %d", + __func__, isFlushDenied); + return eHAL_STATUS_FAILURE; + } + + /* prepare and send clear cached scan results msg to lim */ + msgLen = (tANI_U16)(sizeof( tSirMbMsg )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL != pMsg ) { + vos_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_CLEAR_LIM_SCAN_CACHE); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + palSendMBMessage(pMac->hHdd, pMsg); + } else { + status = eHAL_STATUS_FAILED_ALLOC; + } + + csrLLScanPurgeResult( pMac, &pMac->scan.tempScanResults ); + csrLLScanPurgeResult( pMac, &pMac->scan.scanResultList ); + return( status ); +} + +eHalStatus csrScanFlushSelectiveResult(tpAniSirGlobal pMac, v_BOOL_t flushP2P) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry,*pFreeElem; + tCsrScanResult *pBssDesc; + tDblLinkList *pList = &pMac->scan.scanResultList; + + csrLLLock(pList); + + pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK ); + while( pEntry != NULL) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + if( flushP2P == vos_mem_compare( pBssDesc->Result.ssId.ssId, + "DIRECT-", 7) ) + { + pFreeElem = pEntry; + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + csrLLRemoveEntry(pList, pFreeElem, LL_ACCESS_NOLOCK); + csrFreeScanResultEntry( pMac, pBssDesc ); + continue; + } + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + } + + csrLLUnlock(pList); + + return (status); +} + +void csrScanFlushBssEntry(tpAniSirGlobal pMac, + tpSmeCsaOffloadInd pCsaOffloadInd) +{ + tListElem *pEntry,*pFreeElem; + tCsrScanResult *pBssDesc; + tDblLinkList *pList = &pMac->scan.scanResultList; + + csrLLLock(pList); + + pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK ); + while( pEntry != NULL) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + if( vos_mem_compare(pBssDesc->Result.BssDescriptor.bssId, + pCsaOffloadInd->bssId, sizeof(tSirMacAddr)) ) + { + pFreeElem = pEntry; + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + csrLLRemoveEntry(pList, pFreeElem, LL_ACCESS_NOLOCK); + csrFreeScanResultEntry( pMac, pBssDesc ); + smsLog( pMac, LOG1, FL("Removed BSS entry:%pM"), + pCsaOffloadInd->bssId); + continue; + } + + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + } + + csrLLUnlock(pList); +} + +/** + * csrCheck11dChannel + * + *FUNCTION: + * This function is called from csrScanFilterResults function and + * compare channel number with given channel list. + * + *LOGIC: + * Check Scan result channel number with CFG channel list + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param channelId channel number + * @param pChannelList Pointer to channel list + * @param numChannels Number of channel in channel list + * + * @return Status + */ + +eHalStatus csrCheck11dChannel(tANI_U8 channelId, tANI_U8 *pChannelList, tANI_U32 numChannels) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_U8 i = 0; + + for (i = 0; i < numChannels; i++) + { + if(pChannelList[ i ] == channelId) + { + status = eHAL_STATUS_SUCCESS; + break; + } + } + return status; +} + +/** + * csrScanFilterResults + * + *FUNCTION: + * This function is called from csrApplyCountryInformation function and + * filter scan result based on valid channel list number. + * + *LOGIC: + * Get scan result from scan list and Check Scan result channel number + * with 11d channel list if channel number is found in 11d channel list + * then do not remove scan result entry from scan list + * + *ASSUMPTIONS: + * + * + *NOTE: + * + * @param pMac Pointer to Global MAC structure + * + * @return Status + */ + +eHalStatus csrScanFilterResults(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry,*pTempEntry; + tCsrScanResult *pBssDesc; + tANI_U32 len = sizeof(pMac->roam.validChannelList); + + /* Get valid channels list from CFG */ + if (!HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, + pMac->roam.validChannelList, &len))) + { + smsLog( pMac, LOGE, "Failed to get Channel list from CFG"); + } + + csrLLLock(&pMac->scan.scanResultList); + + pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while( pEntry ) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + pTempEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + if(csrCheck11dChannel(pBssDesc->Result.BssDescriptor.channelId, + pMac->roam.validChannelList, len)) + { + /* Remove Scan result which does not have 11d channel */ + if( csrLLRemoveEntry(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK)) + { + csrFreeScanResultEntry( pMac, pBssDesc ); + } + } + else + { + smsLog( pMac, LOG1, FL("%d is a Valid channel"), + pBssDesc->Result.BssDescriptor.channelId); + } + pEntry = pTempEntry; + } + + csrLLUnlock(&pMac->scan.scanResultList); + csrLLLock(&pMac->scan.tempScanResults); + + pEntry = csrLLPeekHead(&pMac->scan.tempScanResults, LL_ACCESS_NOLOCK); + while( pEntry ) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + pTempEntry = csrLLNext(&pMac->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK); + if(csrCheck11dChannel(pBssDesc->Result.BssDescriptor.channelId, + pMac->roam.validChannelList, len)) + { + /* Remove Scan result which does not have 11d channel */ + if(csrLLRemoveEntry(&pMac->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK)) + { + csrFreeScanResultEntry( pMac, pBssDesc ); + } + } + else + { + smsLog( pMac, LOG1, FL("%d is a Valid channel"), + pBssDesc->Result.BssDescriptor.channelId); + } + pEntry = pTempEntry; + } + + csrLLUnlock(&pMac->scan.tempScanResults); + return status; +} + + +eHalStatus csrScanCopyResultList(tpAniSirGlobal pMac, tScanResultHandle hIn, tScanResultHandle *phResult) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tScanResultList *pRetList, *pInList = (tScanResultList *)hIn; + tCsrScanResult *pResult, *pScanResult; + tANI_U32 count = 0; + tListElem *pEntry; + tANI_U32 bssLen, allocLen; + + if(phResult) + { + *phResult = CSR_INVALID_SCANRESULT_HANDLE; + } + pRetList = vos_mem_malloc(sizeof(tScanResultList)); + if ( NULL == pRetList ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pRetList, sizeof(tScanResultList), 0); + csrLLOpen(pMac->hHdd, &pRetList->List); + pRetList->pCurEntry = NULL; + csrLLLock(&pMac->scan.scanResultList); + csrLLLock(&pInList->List); + + pEntry = csrLLPeekHead( &pInList->List, LL_ACCESS_NOLOCK ); + while( pEntry ) + { + pScanResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + bssLen = pScanResult->Result.BssDescriptor.length + sizeof(pScanResult->Result.BssDescriptor.length); + allocLen = sizeof( tCsrScanResult ) + bssLen; + pResult = vos_mem_malloc(allocLen); + if ( NULL == pResult ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + csrScanResultPurge(pMac, (tScanResultHandle *)pRetList); + count = 0; + break; + } + vos_mem_set(pResult, allocLen , 0); + vos_mem_copy(&pResult->Result.BssDescriptor, &pScanResult->Result.BssDescriptor, bssLen); + if( pScanResult->Result.pvIes ) + { + pResult->Result.pvIes = vos_mem_malloc(sizeof( tDot11fBeaconIEs )); + if ( NULL == pResult->Result.pvIes ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + //Free the memory we allocate above first + vos_mem_free(pResult); + csrScanResultPurge(pMac, (tScanResultHandle *)pRetList); + count = 0; + break; + } + vos_mem_copy(pResult->Result.pvIes, pScanResult->Result.pvIes, + sizeof( tDot11fBeaconIEs )); + } + csrLLInsertTail(&pRetList->List, &pResult->Link, LL_ACCESS_LOCK); + count++; + pEntry = csrLLNext( &pInList->List, pEntry, LL_ACCESS_NOLOCK ); + }//while + csrLLUnlock(&pInList->List); + csrLLUnlock(&pMac->scan.scanResultList); + + if(HAL_STATUS_SUCCESS(status)) + { + if(0 == count) + { + csrLLClose(&pRetList->List); + vos_mem_free(pRetList); + status = eHAL_STATUS_E_NULL_VALUE; + } + else if(phResult) + { + *phResult = pRetList; + } + } + }//Allocated pRetList + + return (status); +} + + + +eHalStatus csrScanningStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirMbMsg *pMsg = (tSirMbMsg *)pMsgBuf; + + if((eWNI_SME_SCAN_RSP == pMsg->type) || (eWNI_SME_GET_SCANNED_CHANNEL_RSP == pMsg->type)) + { + status = csrScanSmeScanResponse( pMac, pMsgBuf ); + } + else + { + if(pMsg->type == eWNI_SME_UPPER_LAYER_ASSOC_CNF) + { + tCsrRoamSession *pSession; + tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf; + tCsrRoamInfo roamInfo; + tCsrRoamInfo *pRoamInfo = NULL; + tANI_U32 sessionId; + eHalStatus status; + smsLog( pMac, LOG1, FL("Scanning : ASSOCIATION confirmation can be given to upper layer ")); + vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + pRoamInfo = &roamInfo; + pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *)pMsgBuf; + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pUpperLayerAssocCnf->bssId, &sessionId ); + pSession = CSR_GET_SESSION(pMac, sessionId); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + pRoamInfo->statusCode = eSIR_SME_SUCCESS; //send the status code as Success + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + pRoamInfo->staId = (tANI_U8)pUpperLayerAssocCnf->aid; + pRoamInfo->rsnIELen = (tANI_U8)pUpperLayerAssocCnf->rsnIE.length; + pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata; + pRoamInfo->addIELen = (tANI_U8)pUpperLayerAssocCnf->addIE.length; + pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata; + vos_mem_copy(pRoamInfo->peerMac, pUpperLayerAssocCnf->peerMacAddr, sizeof(tSirMacAddr)); + vos_mem_copy(&pRoamInfo->bssid, pUpperLayerAssocCnf->bssId, sizeof(tCsrBssid)); + pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta; + if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile) ) + { + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED; + pRoamInfo->fReassocReq = pUpperLayerAssocCnf->reassocReq; + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); + } + if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile)) + { + vos_sleep( 100 ); + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED;//Sta + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);//Sta + } + + } + else + { + + if( csrIsAnySessionInConnectState( pMac ) ) + { + //In case of we are connected, we need to check whether connect status changes + //because scan may also run while connected. + csrRoamCheckForLinkStatusChange( pMac, ( tSirSmeRsp * )pMsgBuf ); + } + else + { + smsLog( pMac, LOGW, "Message [0x%04x] received in state, when expecting Scan Response", pMsg->type ); + } + } + } + + return (status); +} + + + +void csrCheckNSaveWscIe(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr, tSirBssDescription *pOldBssDescr) +{ + int idx, len; + tANI_U8 *pbIe; + + //If failed to remove, assuming someone else got it. + if((pNewBssDescr->fProbeRsp != pOldBssDescr->fProbeRsp) && + (0 == pNewBssDescr->WscIeLen)) + { + idx = 0; + len = pOldBssDescr->length - sizeof(tSirBssDescription) + + sizeof(tANI_U16) + sizeof(tANI_U32) - DOT11F_IE_WSCPROBERES_MIN_LEN - 2; + pbIe = (tANI_U8 *)pOldBssDescr->ieFields; + //Save WPS IE if it exists + pNewBssDescr->WscIeLen = 0; + while(idx < len) + { + if((DOT11F_EID_WSCPROBERES == pbIe[0]) && + (0x00 == pbIe[2]) && (0x50 == pbIe[3]) && (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) + { + /* Found it */ + if((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= pbIe[1]) + { + vos_mem_copy(pNewBssDescr->WscIeProbeRsp, pbIe, pbIe[1] + 2); + pNewBssDescr->WscIeLen = pbIe[1] + 2; + } + break; + } + idx += pbIe[1] + 2; + pbIe += pbIe[1] + 2; + } + } +} + + + +//pIes may be NULL +tANI_BOOLEAN csrRemoveDupBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDescr, + tDot11fBeaconIEs *pIes, tAniSSID *pSsid, v_TIME_t *timer, tANI_BOOLEAN fForced ) +{ + tListElem *pEntry; + + tCsrScanResult *pBssDesc; + tANI_BOOLEAN fRC = FALSE; + + // Walk through all the chained BssDescriptions. If we find a chained BssDescription that + // matches the BssID of the BssDescription passed in, then these must be duplicate scan + // results for this Bss. In that case, remove the 'old' Bss description from the linked list. + csrLLLock(&pMac->scan.scanResultList); + pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + + while( pEntry ) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + + // we have a duplicate scan results only when BSSID, SSID, Channel and NetworkType + // matches + if ( csrIsDuplicateBssDescription( pMac, &pBssDesc->Result.BssDescriptor, + pSirBssDescr, pIes, fForced ) ) + { + int32_t rssi_new, rssi_old; + + rssi_new = (int32_t) pSirBssDescr->rssi; + rssi_old = (int32_t) pBssDesc->Result.BssDescriptor.rssi; + rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + + rssi_old * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; + pSirBssDescr->rssi = (tANI_S8) rssi_new; + + rssi_new = (int32_t) pSirBssDescr->rssi_raw; + rssi_old = (int32_t) pBssDesc->Result.BssDescriptor.rssi_raw; + rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + + rssi_old * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; + pSirBssDescr->rssi_raw = (tANI_S8) rssi_new; + + // Remove the 'old' entry from the list.... + if(csrLLRemoveEntry(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK)) + { + // !we need to free the memory associated with this node + //If failed to remove, assuming someone else got it. + *pSsid = pBssDesc->Result.ssId; + *timer = pBssDesc->Result.timer; + csrCheckNSaveWscIe(pMac, pSirBssDescr, &pBssDesc->Result.BssDescriptor); + + csrFreeScanResultEntry( pMac, pBssDesc ); + } + else + { + smsLog( pMac, LOGW, FL( " fail to remove entry" ) ); + } + fRC = TRUE; + + // If we found a match, we can stop looking through the list. + break; + } + + pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + } + csrLLUnlock(&pMac->scan.scanResultList); + + return fRC; +} + + +eHalStatus csrAddPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, "csrAddPMKIDCandidateList called pMac->scan.NumPmkidCandidate = %d", pSession->NumPmkidCandidate); + if( pIes ) + { + // check if this is a RSN BSS + if( pIes->RSN.present ) + { + // Check if the BSS is capable of doing pre-authentication + if( pSession->NumPmkidCandidate < CSR_MAX_PMKID_ALLOWED ) + { + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type); + vos_mem_set(&secEvent, sizeof(vos_event_wlan_security_payload_type), 0); + secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND; + secEvent.encryptionModeMulticast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType); + secEvent.encryptionModeUnicast = + (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType); + vos_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid, 6); + secEvent.authMode = + (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType); + WLAN_VOS_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY); + } +#endif//#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + + // if yes, then add to PMKIDCandidateList + vos_mem_copy(pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate].BSSID, + pBssDesc->bssId, VOS_MAC_ADDR_SIZE); + /* Bit 0 of first byte - PreAuthentication Capability */ + if ( (pIes->RSN.RSN_Cap[0] >> 0) & 0x1 ) + { + pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate].preAuthSupported + = eANI_BOOLEAN_TRUE; + } + else + { + pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate].preAuthSupported + = eANI_BOOLEAN_FALSE; + } + pSession->NumPmkidCandidate++; + } + else + { + status = eHAL_STATUS_FAILURE; + } + } + } + + return (status); +} + +//This function checks whether new AP is found for the current connected profile +//If it is found, it return the sessionId, else it return invalid sessionID +eHalStatus csrProcessBSSDescForPMKIDList(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes, + tANI_U8 sessionId) +{ + tCsrRoamSession *pSession; + tDot11fBeaconIEs *pIesLocal = pIes; + eHalStatus status = eHAL_STATUS_FAILURE; + + if (pIesLocal || + HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs( + pMac, pBssDesc, &pIesLocal))) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + pSession = CSR_GET_SESSION(pMac, sessionId); + if (csrIsConnStateConnectedInfra(pMac, sessionId) && + (eCSR_AUTH_TYPE_RSN == pSession->connectedProfile.AuthType)) { + if (csrMatchBSSToConnectProfile(pMac, + &pSession->connectedProfile, + pBssDesc, pIesLocal)) { + /* This new BSS fits the current profile connected */ + if (!HAL_STATUS_SUCCESS(csrAddPMKIDCandidateList(pMac, + sessionId, pBssDesc, pIesLocal))) { + smsLog(pMac, LOGE, + FL("csrAddPMKIDCandidateList failed")); + } else { + status = eHAL_STATUS_SUCCESS; + } + } + } + } + + if (!pIes) { + vos_mem_free(pIesLocal); + } + } + return status; +} + +#ifdef FEATURE_WLAN_WAPI +eHalStatus csrAddBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, "csrAddBKIDCandidateList called pMac->scan.NumBkidCandidate = %d", + pSession->NumBkidCandidate); + if( pIes ) + { + // check if this is a WAPI BSS + if( pIes->WAPI.present ) + { + // Check if the BSS is capable of doing pre-authentication + if( pSession->NumBkidCandidate < CSR_MAX_BKID_ALLOWED ) + { + + // if yes, then add to BKIDCandidateList + vos_mem_copy(pSession->BkidCandidateInfo[pSession->NumBkidCandidate].BSSID, + pBssDesc->bssId, VOS_MAC_ADDR_SIZE); + if ( pIes->WAPI.preauth ) + { + pSession->BkidCandidateInfo[pSession->NumBkidCandidate].preAuthSupported + = eANI_BOOLEAN_TRUE; + } + else + { + pSession->BkidCandidateInfo[pSession->NumBkidCandidate].preAuthSupported + = eANI_BOOLEAN_FALSE; + } + pSession->NumBkidCandidate++; + } + else + { + status = eHAL_STATUS_FAILURE; + } + } + } + + return (status); +} + +//This function checks whether new AP is found for the current connected profile +//if so add to BKIDCandidateList +tANI_BOOLEAN csrProcessBSSDescForBKIDList(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + tANI_BOOLEAN fRC = FALSE; + tDot11fBeaconIEs *pIesLocal = pIes; + tANI_U32 sessionId; + tCsrRoamSession *pSession; + + if( pIesLocal || HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal)) ) + { + for( sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId) ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if( csrIsConnStateConnectedInfra( pMac, sessionId ) && + eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == pSession->connectedProfile.AuthType) + { + if(csrMatchBSSToConnectProfile(pMac, &pSession->connectedProfile,pBssDesc, pIesLocal)) + { + //this new BSS fits the current profile connected + if(HAL_STATUS_SUCCESS(csrAddBKIDCandidateList(pMac, sessionId, pBssDesc, pIesLocal))) + { + fRC = TRUE; + } + } + } + } + } + if(!pIes) + { + vos_mem_free(pIesLocal); + } + + } + return fRC; +} + +#endif + + +static void csrMoveTempScanResultsToMainList(tpAniSirGlobal pMac, + tANI_U8 reason, + tANI_U8 sessionId) +{ + tListElem *pEntry; + tCsrScanResult *pBssDescription; + tANI_BOOLEAN fDupBss; +#ifdef FEATURE_WLAN_WAPI + tANI_BOOLEAN fNewWapiBSSForCurConnection = eANI_BOOLEAN_FALSE; +#endif /* FEATURE_WLAN_WAPI */ + tDot11fBeaconIEs *pIesLocal = NULL; + tAniSSID tmpSsid; + v_TIME_t timer=0; + + tmpSsid.length = 0; + + // remove the BSS descriptions from temporary list + while ((pEntry = csrLLRemoveTail(&pMac->scan.tempScanResults, + LL_ACCESS_LOCK)) != NULL) + { + pBssDescription = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + + smsLog( pMac, LOG2, "...Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = -%d", + MAC_ADDR_ARRAY(pBssDescription->Result.BssDescriptor.bssId), + pBssDescription->Result.BssDescriptor.channelId, + pBssDescription->Result.BssDescriptor.rssi * (-1) ); + + //At this time, pBssDescription->Result.pvIes may be NULL + pIesLocal = (tDot11fBeaconIEs *)( pBssDescription->Result.pvIes ); + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pBssDescription->Result.BssDescriptor, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" Cannot pared IEs")); + csrFreeScanResultEntry(pMac, pBssDescription); + continue; + } + fDupBss = csrRemoveDupBssDescription( pMac, &pBssDescription->Result.BssDescriptor, pIesLocal, &tmpSsid, &timer, FALSE ); + //Check whether we have reach out limit, but don't lose the LFR candidates came from FW + if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !( eCsrScanGetLfrResult == reason ) +#endif + ) + { + //Limit reach + smsLog(pMac, LOGW, FL(" BSS limit reached")); + //Free the resources + if( (pBssDescription->Result.pvIes == NULL) && pIesLocal ) + { + vos_mem_free(pIesLocal); + } + csrFreeScanResultEntry(pMac, pBssDescription); + //Continue because there may be duplicated BSS + continue; + } + // check for duplicate scan results + if ( !fDupBss ) + { + if (HAL_STATUS_SUCCESS(csrProcessBSSDescForPMKIDList(pMac, + &pBssDescription->Result.BssDescriptor, + pIesLocal, sessionId))) { + /* Found a new BSS */ + csrRoamCallCallback(pMac, sessionId, NULL, 0, + eCSR_ROAM_SCAN_FOUND_NEW_BSS, eCSR_ROAM_RESULT_NONE); + } + } + else + { + //Check if the new one has SSID it it, if not, use the older SSID if it exists. + if( (0 == pBssDescription->Result.ssId.length) && tmpSsid.length ) + { + //New BSS has a hidden SSID and old one has the SSID. Keep the SSID only + //if diff of saved SSID time and current time is less than 1 min to avoid + //side effect of saving SSID with old one is that if AP changes its SSID while remain + //hidden, we may never see it and also to address the requirement of + //When we remove hidden ssid from the profile i.e., forget the SSID via + // GUI that SSID shouldn't see in the profile + if( (vos_timer_get_system_time() - timer) <= HIDDEN_TIMER) + { + pBssDescription->Result.timer = timer; + pBssDescription->Result.ssId = tmpSsid; + } + } + } + + //Find a good AP for 11d info + if ( csrIs11dSupported( pMac ) ) + { + // check if country information element is present + if (pIesLocal->Country.present) + { + csrAddVoteForCountryInfo(pMac, pIesLocal->Country.country); + smsLog(pMac, LOGW, FL("11d AP Bssid " MAC_ADDRESS_STR + " chan= %d, rssi = -%d, countryCode %c%c"), + MAC_ADDR_ARRAY( pBssDescription->Result.BssDescriptor.bssId), + pBssDescription->Result.BssDescriptor.channelId, + pBssDescription->Result.BssDescriptor.rssi * (-1), + pIesLocal->Country.country[0],pIesLocal->Country.country[1] ); + } + } + + // append to main list + csrScanAddResult(pMac, pBssDescription, pIesLocal, sessionId); + if ( (pBssDescription->Result.pvIes == NULL) && pIesLocal ) + { + vos_mem_free(pIesLocal); + } + } + + pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_LOCK ); + if (pEntry && 0 != pMac->scan.scanResultCfgAgingTime) + csrScanStartResultCfgAgingTimer(pMac); + + /* We don't need to update CC while connected to an AP + which is advertising CC already */ + if (csrIs11dSupported(pMac)) + { + tCsrRoamSession *pSession; + tANI_U32 i; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if (CSR_IS_SESSION_VALID( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + if (csrIsConnStateConnected(pMac, i)) + { + smsLog(pMac, LOGW, FL("No need for updating CC in" + "connected state")); + goto end; + } + } + } + csrElectedCountryInfo(pMac); + csrLearnCountryInformation( pMac, NULL, NULL, eANI_BOOLEAN_TRUE ); + } + +end: + //If we can find the current 11d info in any of the scan results, or + // a good enough AP with the 11d info from the scan results then no need to + // get into ambiguous state + if(pMac->scan.fAmbiguous11dInfoFound) + { + if((pMac->scan.fCurrent11dInfoMatch)) + { + pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE; + } + } + +#ifdef FEATURE_WLAN_WAPI + if(fNewWapiBSSForCurConnection) + { + //remember it first + csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_SCAN_FOUND_NEW_BSS, eCSR_ROAM_RESULT_NEW_WAPI_BSS); + } +#endif /* FEATURE_WLAN_WAPI */ + + return; +} + + +static tCsrScanResult * +csrScanSaveBssDescription(tpAniSirGlobal pMac, + tSirBssDescription *pBSSDescription, + tDot11fBeaconIEs *pIes, + tANI_U8 sessionId) +{ + tCsrScanResult *pCsrBssDescription = NULL; + tANI_U32 cbBSSDesc; + tANI_U32 cbAllocated; + tListElem *pEntry; + + // figure out how big the BSS description is (the BSSDesc->length does NOT + // include the size of the length field itself). + cbBSSDesc = pBSSDescription->length + sizeof( pBSSDescription->length ); + + cbAllocated = sizeof( tCsrScanResult ) + cbBSSDesc; + + pCsrBssDescription = vos_mem_malloc(cbAllocated); + if ( NULL != pCsrBssDescription ) + { + vos_mem_set(pCsrBssDescription, cbAllocated, 0); + pCsrBssDescription->AgingCount = (tANI_S32)pMac->roam.configParam.agingCount; + smsLog(pMac, LOGW, + FL(" Set Aging Count = %d for BSS "MAC_ADDRESS_STR" "), + pCsrBssDescription->AgingCount, + MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.bssId)); + vos_mem_copy(&pCsrBssDescription->Result.BssDescriptor, pBSSDescription, cbBSSDesc); +#if defined(VOSS_ENSBALED) + if ( NULL != pCsrBssDescription->Result.pvIes) + { + VOS_ASSERT( pCsrBssDescription->Result.pvIes == NULL ); + return NULL; + } +#endif + csrScanAddResult(pMac, pCsrBssDescription, pIes, sessionId); + pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_LOCK ); + if (pEntry && 0 != pMac->scan.scanResultCfgAgingTime) + csrScanStartResultCfgAgingTimer(pMac); + } + + return( pCsrBssDescription ); +} + +// Append a Bss Description... +tCsrScanResult * +csrScanAppendBssDescription(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDescription, + tDot11fBeaconIEs *pIes, + tANI_BOOLEAN fForced, + tANI_U8 sessionId) +{ + tCsrScanResult *pCsrBssDescription = NULL; + tAniSSID tmpSsid; + v_TIME_t timer = 0; + int result; + + tmpSsid.length = 0; + result = csrRemoveDupBssDescription( pMac, pSirBssDescription, pIes, &tmpSsid, &timer, fForced ); + pCsrBssDescription = csrScanSaveBssDescription(pMac, pSirBssDescription, + pIes, sessionId); + if (result && (pCsrBssDescription != NULL)) + { + //Check if the new one has SSID it it, if not, use the older SSID if it exists. + if( (0 == pCsrBssDescription->Result.ssId.length) && tmpSsid.length ) + { + //New BSS has a hidden SSID and old one has the SSID. Keep the SSID only + //if diff of saved SSID time and current time is less than 1 min to avoid + //side effect of saving SSID with old one is that if AP changes its SSID while remain + //hidden, we may never see it and also to address the requirement of + //When we remove hidden ssid from the profile i.e., forget the SSID via + // GUI that SSID shouldn't see in the profile + if((vos_timer_get_system_time()-timer) <= HIDDEN_TIMER) + { + pCsrBssDescription->Result.ssId = tmpSsid; + pCsrBssDescription->Result.timer = timer; + } + } + } + + + return( pCsrBssDescription ); +} + + + +void csrPurgeChannelPower( tpAniSirGlobal pMac, tDblLinkList *pChannelList ) +{ + tCsrChannelPowerInfo *pChannelSet; + tListElem *pEntry; + + csrLLLock(pChannelList); + // Remove the channel sets from the learned list and put them in the free list + while( ( pEntry = csrLLRemoveHead( pChannelList, LL_ACCESS_NOLOCK ) ) != NULL) + { + pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link ); + if( pChannelSet ) + { + vos_mem_free(pChannelSet); + } + } + csrLLUnlock(pChannelList); + return; +} + + +/* + * Save the channelList into the ultimate storage as the final stage of channel + * Input: pCountryInfo -- the country code (e.g. "USI"), channel list, and power limit are all stored inside this data structure + */ +eHalStatus csrSaveToChannelPower2G_5G( tpAniSirGlobal pMac, tANI_U32 tableSize, tSirMacChanInfo *channelTable ) +{ + tANI_U32 i = tableSize / sizeof( tSirMacChanInfo ); + tSirMacChanInfo *pChannelInfo; + tCsrChannelPowerInfo *pChannelSet; + tANI_BOOLEAN f2GHzInfoFound = FALSE; + tANI_BOOLEAN f2GListPurged = FALSE, f5GListPurged = FALSE; + + pChannelInfo = channelTable; + /* At-least 3 bytes have to be remaining -- from "countryString" */ + while ( i-- ) + { + pChannelSet = vos_mem_malloc(sizeof(tCsrChannelPowerInfo)); + if ( NULL != pChannelSet ) + { + vos_mem_set(pChannelSet, sizeof(tCsrChannelPowerInfo), 0); + pChannelSet->firstChannel = pChannelInfo->firstChanNum; + pChannelSet->numChannels = pChannelInfo->numChannels; + + // Now set the inter-channel offset based on the frequency band the channel set lies in + if( (CSR_IS_CHANNEL_24GHZ(pChannelSet->firstChannel)) && + ((pChannelSet->firstChannel + (pChannelSet->numChannels - 1)) <= CSR_MAX_24GHz_CHANNEL_NUMBER) ) + + { + pChannelSet->interChannelOffset = 1; + f2GHzInfoFound = TRUE; + } + else if ( (CSR_IS_CHANNEL_5GHZ(pChannelSet->firstChannel)) && + ((pChannelSet->firstChannel + ((pChannelSet->numChannels - 1) * 4)) <= CSR_MAX_5GHz_CHANNEL_NUMBER) ) + { + pChannelSet->interChannelOffset = 4; + f2GHzInfoFound = FALSE; + } + else + { + smsLog( pMac, LOGW, FL("Invalid Channel %d Present in Country IE"), + pChannelSet->firstChannel); + vos_mem_free(pChannelSet); + return eHAL_STATUS_FAILURE; + } + + pChannelSet->txPower = CSR_ROAM_MIN( pChannelInfo->maxTxPower, pMac->roam.configParam.nTxPowerCap ); + + if( f2GHzInfoFound ) + { + if( !f2GListPurged ) + { + // purge previous results if found new + csrPurgeChannelPower( pMac, &pMac->scan.channelPowerInfoList24 ); + f2GListPurged = TRUE; + } + + if(CSR_IS_OPERATING_BG_BAND(pMac)) + { + // add to the list of 2.4 GHz channel sets + csrLLInsertTail( &pMac->scan.channelPowerInfoList24, &pChannelSet->link, LL_ACCESS_LOCK ); + } + else { + smsLog( pMac, LOGW, FL("Adding 11B/G channels in 11A mode -- First Channel is %d"), + pChannelSet->firstChannel); + vos_mem_free(pChannelSet); + } + } + else + { + // 5GHz info found + if( !f5GListPurged ) + { + // purge previous results if found new + csrPurgeChannelPower( pMac, &pMac->scan.channelPowerInfoList5G ); + f5GListPurged = TRUE; + } + + if(CSR_IS_OPERATING_A_BAND(pMac)) + { + // add to the list of 5GHz channel sets + csrLLInsertTail( &pMac->scan.channelPowerInfoList5G, &pChannelSet->link, LL_ACCESS_LOCK ); + } + else { + smsLog( pMac, LOGW, FL("Adding 11A channels in B/G mode -- First Channel is %d"), + pChannelSet->firstChannel); + vos_mem_free(pChannelSet); + } + } + } + + pChannelInfo++; // move to next entry + } + + return eHAL_STATUS_SUCCESS; +} + +static void csrClearDfsChannelList( tpAniSirGlobal pMac ) +{ + tSirMbMsg *pMsg; + tANI_U16 msgLen; + + msgLen = (tANI_U16)(sizeof( tSirMbMsg )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL != pMsg ) + { + vos_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_CLEAR_DFS_CHANNEL_LIST); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + palSendMBMessage(pMac->hHdd, pMsg); + } +} + +void csrApplyPower2Current( tpAniSirGlobal pMac ) +{ + smsLog( pMac, LOG3, FL(" Updating Cfg with power settings")); + csrSaveTxPowerToCfg( pMac, &pMac->scan.channelPowerInfoList24, WNI_CFG_MAX_TX_POWER_2_4 ); + csrSaveTxPowerToCfg( pMac, &pMac->scan.channelPowerInfoList5G, WNI_CFG_MAX_TX_POWER_5 ); +} + + +void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva) +{ + int i; + tANI_U8 numChannels = 0; + tANI_U8 tempNumChannels = 0; + tCsrChannel ChannelList; + + if (pChannelList->numChannels) + { + tempNumChannels = CSR_MIN(pChannelList->numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN); + + for (i = 0; i < tempNumChannels; i++) + { + ChannelList.channelList[numChannels] = pChannelList->channelList[i]; + numChannels++; + } + + ChannelList.numChannels = numChannels; + /* Store the channel + power info in the global place: Cfg */ + csrApplyPower2Current(pMac); + csrSetCfgValidChannelList(pMac, ChannelList.channelList, ChannelList.numChannels); + + // extend scan capability + // build a scan list based on the channel list : channel# + active/passive scan + csrSetCfgScanControlList(pMac, countryCode, &ChannelList); + /*Send msg to Lim to clear DFS channel list */ + csrClearDfsChannelList(pMac); +#ifdef FEATURE_WLAN_SCAN_PNO + if (updateRiva) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, FL(" Sending 11d PNO info to Riva")); + // Send HAL UpdateScanParams message + pmcUpdateScanParams(pMac, &(pMac->roam.configParam), &ChannelList, TRUE); + } +#endif // FEATURE_WLAN_SCAN_PNO + } + else + { + smsLog( pMac, LOGE, FL(" 11D channel list is empty")); + } + csrSetCfgCountryCode(pMac, countryCode); +} + + +void csrResetCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce, tANI_BOOLEAN updateRiva ) +{ + if( fForce || (csrIs11dSupported( pMac ) && (!pMac->scan.f11dInfoReset))) + { + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_802_11d_pkt_type *p11dLog; + int Index; + + WLAN_VOS_DIAG_LOG_ALLOC(p11dLog, vos_log_802_11d_pkt_type, LOG_WLAN_80211D_C); + if(p11dLog) + { + p11dLog->eventId = WLAN_80211D_EVENT_RESET; + vos_mem_copy(p11dLog->countryCode, pMac->scan.countryCodeCurrent, 3); + p11dLog->numChannel = pMac->scan.base20MHzChannels.numChannels; + if(p11dLog->numChannel <= VOS_LOG_MAX_NUM_CHANNEL) + { + vos_mem_copy(p11dLog->Channels, + pMac->scan.base20MHzChannels.channelList, + p11dLog->numChannel); + for (Index=0; Index < pMac->scan.base20MHzChannels.numChannels; Index++) + { + p11dLog->TxPwr[Index] = CSR_ROAM_MIN( pMac->scan.defaultPowerTable[Index].pwr, pMac->roam.configParam.nTxPowerCap ); + } + } + if(!pMac->roam.configParam.Is11dSupportEnabled) + { + p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED; + } + else if(pMac->roam.configParam.fEnforceDefaultDomain) + { + p11dLog->supportMultipleDomain = WLAN_80211D_NOT_SUPPORT_MULTI_DOMAIN; + } + else + { + p11dLog->supportMultipleDomain = WLAN_80211D_SUPPORT_MULTI_DOMAIN; + } + WLAN_VOS_DIAG_LOG_REPORT(p11dLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + + csrPruneChannelListForMode(pMac, &pMac->scan.baseChannels); + csrPruneChannelListForMode(pMac, &pMac->scan.base20MHzChannels); + + csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_FALSE); + csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_TRUE); + // ... and apply the channel list, power settings, and the country code. + csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent, updateRiva ); + // clear the 11d channel list + vos_mem_set(&pMac->scan.channels11d, sizeof(pMac->scan.channels11d), 0); + pMac->scan.f11dInfoReset = eANI_BOOLEAN_TRUE; + pMac->scan.f11dInfoApplied = eANI_BOOLEAN_FALSE; + } + + return; +} + + +eHalStatus csrResetCountryCodeInformation(tpAniSirGlobal pMac, tANI_BOOLEAN *pfRestartNeeded) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fRestart = eANI_BOOLEAN_FALSE; + + //Use the Country code and domain from EEPROM + vos_mem_copy(pMac->scan.countryCodeCurrent, pMac->scan.countryCodeDefault, + WNI_CFG_COUNTRY_CODE_LEN); + csrSetRegulatoryDomain(pMac, pMac->scan.domainIdCurrent, &fRestart); + if( ((eANI_BOOLEAN_FALSE == fRestart) || (pfRestartNeeded == NULL) ) + && !csrIsInfraConnected(pMac)) + { + //Only reset the country info if we don't need to restart + csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + } + if(pfRestartNeeded) + { + *pfRestartNeeded = fRestart; + } + + return (status); +} + +void csrClearVotesForCountryInfo(tpAniSirGlobal pMac) +{ + pMac->scan.countryCodeCount = 0; + vos_mem_set(pMac->scan.votes11d, + sizeof(tCsrVotes11d) * CSR_MAX_NUM_COUNTRY_CODE, 0); +} + +void csrAddVoteForCountryInfo(tpAniSirGlobal pMac, tANI_U8 *pCountryCode) +{ + tANI_BOOLEAN match = FALSE; + tANI_U8 i; + + /* convert to UPPER here so we are assured + * the strings are always in upper case. + */ + for( i = 0; i < 3; i++ ) + { + pCountryCode[ i ] = (tANI_U8)csrToUpper( pCountryCode[ i ] ); + } + + /* Some of the 'old' Cisco 350 series AP's advertise NA as the + * country code (for North America ??). NA is not a valid country code + * or domain so let's allow this by changing it to the proper + * country code (which is US). We've also seen some NETGEAR AP's + * that have "XX " as the country code with valid 2.4 GHz US channel + * information. If we cannot find the country code advertised in the + * 11d information element, let's default to US. + */ + + if ( !HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry( pMac, + pCountryCode, NULL,COUNTRY_QUERY ) ) ) + { + pCountryCode[ 0 ] = '0'; + pCountryCode[ 1 ] = '0'; + } + + /* We've seen some of the AP's improperly put a 0 for the + * third character of the country code. spec says valid charcters are + * 'O' (for outdoor), 'I' for Indoor, or ' ' (space; for either). + * if we see a 0 in this third character, let's change it to a ' '. + */ + if ( 0 == pCountryCode[ 2 ] ) + { + pCountryCode[ 2 ] = ' '; + } + + for (i = 0; i < pMac->scan.countryCodeCount; i++) + { + match = (vos_mem_compare(pMac->scan.votes11d[i].countryCode, + pCountryCode, 2)); + if(match) + { + break; + } + } + + if (match) + { + pMac->scan.votes11d[i].votes++; + } + else + { + vos_mem_copy( pMac->scan.votes11d[pMac->scan.countryCodeCount].countryCode, + pCountryCode, 3 ); + pMac->scan.votes11d[pMac->scan.countryCodeCount].votes = 1; + pMac->scan.countryCodeCount++; + } + + return; +} + +tANI_BOOLEAN csrElectedCountryInfo(tpAniSirGlobal pMac) +{ + tANI_BOOLEAN fRet = FALSE; + tANI_U8 maxVotes = 0; + tANI_U8 i, j=0; + + if (!pMac->scan.countryCodeCount) + { + return fRet; + } + maxVotes = pMac->scan.votes11d[0].votes; + fRet = TRUE; + + for(i = 1; i < pMac->scan.countryCodeCount; i++) + { + /* If we have a tie for max votes for 2 different country codes, + * pick random.we can put some more intelligence - TBD + */ + if (maxVotes < pMac->scan.votes11d[i].votes) + { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + " Votes for Country %c%c : %d\n", + pMac->scan.votes11d[i].countryCode[0], + pMac->scan.votes11d[i].countryCode[1], + pMac->scan.votes11d[i].votes); + + maxVotes = pMac->scan.votes11d[i].votes; + j = i; + fRet = TRUE; + } + + } + if (fRet) + { + vos_mem_copy(pMac->scan.countryCodeElected, + pMac->scan.votes11d[j].countryCode, WNI_CFG_COUNTRY_CODE_LEN); + vos_mem_copy(pMac->scan.countryCode11d, + pMac->scan.votes11d[j].countryCode, WNI_CFG_COUNTRY_CODE_LEN); + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Selected Country is %c%c With count %d\n", + pMac->scan.votes11d[j].countryCode[0], + pMac->scan.votes11d[j].countryCode[1], + pMac->scan.votes11d[j].votes); + } + return fRet; +} + +eHalStatus csrSetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + v_REGDOMAIN_t domainId; + + if(pCountry) + { + status = csrGetRegulatoryDomainForCountry(pMac, pCountry, &domainId, COUNTRY_USER); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrSetRegulatoryDomain(pMac, domainId, pfRestartNeeded); + if(HAL_STATUS_SUCCESS(status)) + { + //We don't need to check the pMac->roam.configParam.fEnforceDefaultDomain flag here, + //csrSetRegulatoryDomain will fail if the country doesn't fit our domain criteria. + vos_mem_copy(pMac->scan.countryCodeCurrent, pCountry, WNI_CFG_COUNTRY_CODE_LEN); + if((pfRestartNeeded == NULL) || !(*pfRestartNeeded)) + { + //Simply set it to cfg. If we need to restart, restart will apply it to the CFG + csrSetCfgCountryCode(pMac, pCountry); + } + } + } + } + + return (status); +} + + + +//caller allocated memory for pNumChn and pChnPowerInfo +//As input, *pNumChn has the size of the array of pChnPowerInfo +//Upon return, *pNumChn has the number of channels assigned. +void csrGetChannelPowerInfo( tpAniSirGlobal pMac, tDblLinkList *pList, + tANI_U32 *pNumChn, tChannelListWithPower *pChnPowerInfo) +{ + tListElem *pEntry; + tANI_U32 chnIdx = 0, idx; + tCsrChannelPowerInfo *pChannelSet; + + //Get 2.4Ghz first + pEntry = csrLLPeekHead( pList, LL_ACCESS_LOCK ); + while( pEntry && (chnIdx < *pNumChn) ) + { + pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link ); + if ( 1 != pChannelSet->interChannelOffset ) + { + for( idx = 0; (idx < pChannelSet->numChannels) && (chnIdx < *pNumChn); idx++ ) + { + pChnPowerInfo[chnIdx].chanId = (tANI_U8)(pChannelSet->firstChannel + ( idx * pChannelSet->interChannelOffset )); + pChnPowerInfo[chnIdx++].pwr = pChannelSet->txPower; + } + } + else + { + for( idx = 0; (idx < pChannelSet->numChannels) && (chnIdx < *pNumChn); idx++ ) + { + pChnPowerInfo[chnIdx].chanId = (tANI_U8)(pChannelSet->firstChannel + idx); + pChnPowerInfo[chnIdx++].pwr = pChannelSet->txPower; + } + } + + pEntry = csrLLNext( pList, pEntry, LL_ACCESS_LOCK ); + } + *pNumChn = chnIdx; + + return ; +} + + + +void csrApplyCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce ) +{ + v_REGDOMAIN_t domainId; + eHalStatus status = eHAL_STATUS_SUCCESS; + + do + { + if( !csrIs11dSupported( pMac ) || 0 == pMac->scan.channelOf11dInfo) break; + if( pMac->scan.fAmbiguous11dInfoFound ) + { + /* Ambiguous info found; Restore the default domain as well */ + if(HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry( + pMac, pMac->scan.countryCodeCurrent, + &domainId, COUNTRY_QUERY))) + { + pMac->scan.domainIdCurrent = domainId; + } + else + { + smsLog(pMac, LOGE, FL(" failed to get domain from currentCountryCode %02X%02X"), + pMac->scan.countryCodeCurrent[0], pMac->scan.countryCodeCurrent[1]); + } + csrResetCountryInformation( pMac, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE ); + break; + } + if ( pMac->scan.f11dInfoApplied && !fForce ) break; + if(HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry( + pMac, pMac->scan.countryCode11d, + &domainId, COUNTRY_QUERY))) + { + //Check whether we need to enforce default domain + if( ( !pMac->roam.configParam.fEnforceDefaultDomain ) || + (pMac->scan.domainIdCurrent == domainId) ) + { + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_802_11d_pkt_type *p11dLog; + tChannelListWithPower chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tANI_U32 nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp; + + WLAN_VOS_DIAG_LOG_ALLOC(p11dLog, vos_log_802_11d_pkt_type, LOG_WLAN_80211D_C); + if(p11dLog) + { + p11dLog->eventId = WLAN_80211D_EVENT_COUNTRY_SET; + vos_mem_copy(p11dLog->countryCode, pMac->scan.countryCode11d, 3); + p11dLog->numChannel = pMac->scan.channels11d.numChannels; + if(p11dLog->numChannel <= VOS_LOG_MAX_NUM_CHANNEL) + { + vos_mem_copy(p11dLog->Channels, + pMac->scan.channels11d.channelList, + p11dLog->numChannel); + csrGetChannelPowerInfo(pMac, &pMac->scan.channelPowerInfoList24, + &nChnInfo, chnPwrInfo); + nTmp = nChnInfo; + nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN - nTmp; + csrGetChannelPowerInfo(pMac, &pMac->scan.channelPowerInfoList5G, + &nChnInfo, &chnPwrInfo[nTmp]); + for(nTmp = 0; nTmp < p11dLog->numChannel; nTmp++) + { + for(nChnInfo = 0; nChnInfo < WNI_CFG_VALID_CHANNEL_LIST_LEN; nChnInfo++) + { + if(p11dLog->Channels[nTmp] == chnPwrInfo[nChnInfo].chanId) + { + p11dLog->TxPwr[nTmp] = chnPwrInfo[nChnInfo].pwr; + break; + } + } + } + } + if(!pMac->roam.configParam.Is11dSupportEnabled) + { + p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED; + } + else if(pMac->roam.configParam.fEnforceDefaultDomain) + { + p11dLog->supportMultipleDomain = WLAN_80211D_NOT_SUPPORT_MULTI_DOMAIN; + } + else + { + p11dLog->supportMultipleDomain = WLAN_80211D_SUPPORT_MULTI_DOMAIN; + } + WLAN_VOS_DIAG_LOG_REPORT(p11dLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + if(pMac->scan.domainIdCurrent != domainId) + { + smsLog(pMac, LOGW, FL("Domain Changed Old %d, new %d"), + pMac->scan.domainIdCurrent, domainId); + status = WDA_SetRegDomain(pMac, domainId, eSIR_TRUE); + } + if (status != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, FL(" fail to set regId %d"), domainId ); + } + pMac->scan.domainIdCurrent = domainId; + + // switch to active scans using this new channel list + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + pMac->scan.f11dInfoApplied = eANI_BOOLEAN_TRUE; + pMac->scan.f11dInfoReset = eANI_BOOLEAN_FALSE; + } + } + + } while( 0 ); + + return; +} + + + +tANI_BOOLEAN csrSave11dCountryString( tpAniSirGlobal pMac, tANI_U8 *pCountryCode, + tANI_BOOLEAN fForce) +{ + tANI_BOOLEAN fCountryStringChanged = FALSE, fUnknownCountryCode = FALSE; + tANI_U32 i; + v_REGDOMAIN_t regd; + tANI_BOOLEAN fCountryNotPresentInDriver = FALSE; + + // convert to UPPER here so we are assured the strings are always in upper case. + for( i = 0; i < 3; i++ ) + { + pCountryCode[ i ] = (tANI_U8)csrToUpper( pCountryCode[ i ] ); + } + + // Some of the 'old' Cisco 350 series AP's advertise NA as the country code (for North America ??). + // NA is not a valid country code or domain so let's allow this by changing it to the proper + // country code (which is US). We've also seen some NETGEAR AP's that have "XX " as the country code + // with valid 2.4 GHz US channel information. If we cannot find the country code advertised in the + // 11d information element, let's default to US. + if ( !HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry(pMac, + pCountryCode, + ®d, + COUNTRY_QUERY) ) ) + { + // Check the enforcement first + if( pMac->roam.configParam.fEnforceDefaultDomain || pMac->roam.configParam.fEnforceCountryCodeMatch ) + { + fUnknownCountryCode = TRUE; + } + else + { + fCountryNotPresentInDriver = TRUE; + } + } + //right now, even if we don't find the CC in driver we set to world. Making + //sure countryCode11d doesn't get updated with the invalid CC, instead + //reflect the world CC + else if (REGDOMAIN_WORLD == regd) + { + fCountryNotPresentInDriver = TRUE; + } + + /* + * We've seen some of the AP's improperly put a 0 for the third character + * of the country code. Spec says valid characters are 'O' (for outdoor), + * 'I' for Indoor, or ' ' (space; for either). + * if we see a 0 in this third character, let's change it to a ' '. + */ + if ( 0 == pCountryCode[ 2 ] ) + { + pCountryCode[ 2 ] = ' '; + } + + if( !fUnknownCountryCode ) + { + fCountryStringChanged = (!vos_mem_compare(pMac->scan.countryCode11d, pCountryCode, 2)); + + + if(( 0 == pMac->scan.countryCode11d[ 0 ] && 0 == pMac->scan.countryCode11d[ 1 ] ) + || (fForce)) + { + if (!fCountryNotPresentInDriver) + { + // this is the first .11d information + vos_mem_copy(pMac->scan.countryCode11d, pCountryCode, + sizeof( pMac->scan.countryCode11d )); + + } + else + { + pMac->scan.countryCode11d[0] = '0'; + pMac->scan.countryCode11d[1] = '0'; + } + } + } + + return( fCountryStringChanged ); +} + + +void csrSaveChannelPowerForBand( tpAniSirGlobal pMac, tANI_BOOLEAN fPopulate5GBand ) +{ + tANI_U32 Index, count=0; + tSirMacChanInfo *pChanInfo; + tSirMacChanInfo *pChanInfoStart; + tANI_S32 maxChannelIndex; + + maxChannelIndex = ( pMac->scan.base20MHzChannels.numChannels < WNI_CFG_VALID_CHANNEL_LIST_LEN ) ? + pMac->scan.base20MHzChannels.numChannels : WNI_CFG_VALID_CHANNEL_LIST_LEN ; + + pChanInfo = vos_mem_malloc(sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN); + if ( NULL != pChanInfo ) + { + vos_mem_set(pChanInfo, sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN, 0); + pChanInfoStart = pChanInfo; + for (Index=0; Index < maxChannelIndex; Index++) + { + if ((fPopulate5GBand && (CSR_IS_CHANNEL_5GHZ(pMac->scan.defaultPowerTable[Index].chanId))) || + (!fPopulate5GBand && (CSR_IS_CHANNEL_24GHZ(pMac->scan.defaultPowerTable[Index].chanId))) ) + { + if(count >= WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + smsLog( pMac, LOGW, FL(" csrSaveChannelPowerForBand, count exceeded, count = %d"), count); + break; + } + pChanInfo->firstChanNum = pMac->scan.defaultPowerTable[Index].chanId; + pChanInfo->numChannels = 1; + pChanInfo->maxTxPower = CSR_ROAM_MIN( pMac->scan.defaultPowerTable[Index].pwr, pMac->roam.configParam.nTxPowerCap ); + pChanInfo++; + count++; + } + } + if(count) + { + csrSaveToChannelPower2G_5G( pMac, count * sizeof(tSirMacChanInfo), pChanInfoStart ); + } + vos_mem_free(pChanInfoStart); + } +} + + +void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac ) +{ + tANI_BOOLEAN fPopulate5GBand = FALSE; + + do + { + // if this is not a dual band product, then we don't need to set the opposite + // band info. We only work in one band so no need to look in the other band. + if ( !CSR_IS_OPEARTING_DUAL_BAND( pMac ) ) break; + // if we found channel info on the 5.0 band and... + if ( CSR_IS_CHANNEL_5GHZ( pMac->scan.channelOf11dInfo ) ) + { + // and the 2.4 band is empty, then populate the 2.4 channel info + if ( !csrLLIsListEmpty( &pMac->scan.channelPowerInfoList24, LL_ACCESS_LOCK ) ) break; + fPopulate5GBand = FALSE; + } + else + { + // else, we found channel info in the 2.4 GHz band. If the 5.0 band is empty + // set the 5.0 band info from the 2.4 country code. + if ( !csrLLIsListEmpty( &pMac->scan.channelPowerInfoList5G, LL_ACCESS_LOCK ) ) break; + fPopulate5GBand = TRUE; + } + csrSaveChannelPowerForBand( pMac, fPopulate5GBand ); + + } while( 0 ); +} + + +tANI_BOOLEAN csrIsSupportedChannel(tpAniSirGlobal pMac, tANI_U8 channelId) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tANI_U32 i; + + //Make sure it is a channel that is in our supported list. + for ( i = 0; i < pMac->scan.baseChannels.numChannels; i++ ) + { + if ( channelId == pMac->scan.baseChannels.channelList[i] ) + { + fRet = eANI_BOOLEAN_TRUE; + break; + } + } + + //If it is configured to limit a set of the channels + if( fRet && pMac->roam.configParam.fEnforce11dChannels ) + { + fRet = eANI_BOOLEAN_FALSE; + for ( i = 0; i < pMac->scan.base20MHzChannels.numChannels; i++ ) + { + if ( channelId == pMac->scan.base20MHzChannels.channelList[i] ) + { + fRet = eANI_BOOLEAN_TRUE; + break; + } + } + } + + return (fRet); +} + + + +//bSize specify the buffer size of pChannelList +tANI_U8 csrGetChannelListFromChannelSet( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 bSize, tCsrChannelPowerInfo *pChannelSet ) +{ + tANI_U8 i, j = 0, chnId; + + bSize = CSR_MIN(bSize, pChannelSet->numChannels); + for( i = 0; i < bSize; i++ ) + { + chnId = (tANI_U8)(pChannelSet->firstChannel + ( i * pChannelSet->interChannelOffset )); + if ( csrIsSupportedChannel( pMac, chnId ) ) + { + pChannelList[j++] = chnId; + } + } + + return (j); +} + + + +//bSize -- specify the buffer size of pChannelList +void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pChannelSetList, + tANI_U8 *pChannelList, tANI_U8 bSize, tANI_U8 *pNumChannels ) +{ + tListElem *pEntry; + tCsrChannelPowerInfo *pChannelSet; + tANI_U8 numChannels; + tANI_U8 *pChannels; + + if( pChannelSetList && pChannelList && pNumChannels ) + { + pChannels = pChannelList; + *pNumChannels = 0; + pEntry = csrLLPeekHead( pChannelSetList, LL_ACCESS_LOCK ); + while( pEntry ) + { + pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link ); + numChannels = csrGetChannelListFromChannelSet( pMac, pChannels, bSize, pChannelSet ); + pChannels += numChannels; + *pNumChannels += numChannels; + pEntry = csrLLNext( pChannelSetList, pEntry, LL_ACCESS_LOCK ); + } + } +} + + +/* + * 802.11D only: Gather 11d IE via beacon or Probe response and store them in pAdapter->channels11d +*/ +tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tANI_BOOLEAN fForce) +{ + eHalStatus status; + tANI_U8 *pCountryCodeSelected; + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + v_REGDOMAIN_t domainId; + tDot11fBeaconIEs *pIesLocal = pIes; + tANI_BOOLEAN useVoting = eANI_BOOLEAN_FALSE; + + if (VOS_STA_SAP_MODE == vos_get_conparam ()) + return eHAL_STATUS_SUCCESS; + + if ((NULL == pSirBssDesc) && (NULL == pIes)) + useVoting = eANI_BOOLEAN_TRUE; + + do + { + // check if .11d support is enabled + if( !csrIs11dSupported( pMac ) ) break; + + if (eANI_BOOLEAN_FALSE == useVoting) + { + if( !pIesLocal && + (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + pSirBssDesc, &pIesLocal)))) + { + break; + } + // check if country information element is present + if(!pIesLocal->Country.present) + { + //No country info + break; + } + + if( HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry + (pMac, pIesLocal->Country.country, &domainId, + COUNTRY_QUERY)) && + ( domainId == REGDOMAIN_WORLD)) + { + break; + } + } //useVoting == eANI_BOOLEAN_FALSE + + if (eANI_BOOLEAN_FALSE == useVoting) + pCountryCodeSelected = pIesLocal->Country.country; + else + pCountryCodeSelected = pMac->scan.countryCodeElected; + + status = csrGetRegulatoryDomainForCountry(pMac, + pCountryCodeSelected, &domainId, COUNTRY_IE); + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to get regId %d"), domainId ); + fRet = eANI_BOOLEAN_FALSE; + break; + } + + /* updating 11d Country Code with Country code selected. */ + vos_mem_copy(pMac->scan.countryCode11d, + pCountryCodeSelected, + WNI_CFG_COUNTRY_CODE_LEN); + +#ifndef CONFIG_ENABLE_LINUX_REG + // Checking for Domain Id change + if ( domainId != pMac->scan.domainIdCurrent ) + { + vos_mem_copy(pMac->scan.countryCode11d, + pCountryCodeSelected, + sizeof( pMac->scan.countryCode11d ) ); + /* Set Current Country code and Current Regulatory domain */ + status = csrSetRegulatoryDomain(pMac, domainId, NULL); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, "Set Reg Domain Fail %d", status); + fRet = eANI_BOOLEAN_FALSE; + break; + } + //csrSetRegulatoryDomain will fail if the country doesn't fit our domain criteria. + vos_mem_copy(pMac->scan.countryCodeCurrent, + pCountryCodeSelected, WNI_CFG_COUNTRY_CODE_LEN); + //Simply set it to cfg. + csrSetCfgCountryCode(pMac, pCountryCodeSelected); + + /* overwrite the defualt country code */ + vos_mem_copy(pMac->scan.countryCodeDefault, + pMac->scan.countryCodeCurrent, + WNI_CFG_COUNTRY_CODE_LEN); + /* Set Current RegDomain */ + status = WDA_SetRegDomain(pMac, domainId, eSIR_TRUE); + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to Set regId %d"), domainId ); + fRet = eANI_BOOLEAN_FALSE; + break; + } + /* set to default domain ID */ + pMac->scan.domainIdCurrent = domainId; + /* get the channels based on new cc */ + status = csrInitGetChannels( pMac ); + + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to get Channels ")); + fRet = eANI_BOOLEAN_FALSE; + break; + } + } +#endif + fRet = eANI_BOOLEAN_TRUE; + + } while( 0 ); + + if( !pIes && pIesLocal ) + { + //locally allocated + vos_mem_free(pIesLocal); + } + + return( fRet ); +} + + +static void csrSaveScanResults(tpAniSirGlobal pMac, tANI_U8 reason, + tANI_U8 sessionId) +{ + // initialize this to FALSE. profMoveInterimScanResultsToMainList() routine + // will set this to the channel where an .11d beacon is seen + pMac->scan.channelOf11dInfo = 0; + // if we get any ambiguous .11d information then this will be set to TRUE + pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE; + //Tush + // if we get any ambiguous .11d information, then this will be set to TRUE + // only if the applied 11d info could be found in one of the scan results + pMac->scan.fCurrent11dInfoMatch = eANI_BOOLEAN_FALSE; + // move the scan results from interim list to the main scan list + csrMoveTempScanResultsToMainList(pMac, reason, sessionId); + + // Now check if we gathered any domain/country specific information + // If so, we should update channel list and apply Tx power settings + if( csrIs11dSupported(pMac) ) + { + csrApplyCountryInformation( pMac, FALSE ); + } +} + + +void csrReinitScanCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + switch (pCommand->u.scanCmd.reason) + { + case eCsrScanSetBGScanParam: + case eCsrScanAbortBgScan: + if(pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList) + { + vos_mem_free(pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList); + pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList = NULL; + } + break; + case eCsrScanBGScanAbort: + case eCsrScanBGScanEnable: + case eCsrScanGetScanChnInfo: + break; + case eCsrScanAbortNormalScan: + default: + csrScanFreeRequest(pMac, &pCommand->u.scanCmd.u.scanRequest); + break; + } + if(pCommand->u.scanCmd.pToRoamProfile) + { + csrReleaseProfile(pMac, pCommand->u.scanCmd.pToRoamProfile); + vos_mem_free(pCommand->u.scanCmd.pToRoamProfile); + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); +} + + +tANI_BOOLEAN csrGetRemainingChannelsFor11dScan( tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U8 *pcChannels ) +{ + tANI_U32 index11dChannels, index; + tANI_U32 indexCurrentChannels; + tANI_BOOLEAN fChannelAlreadyScanned; + tANI_U32 len = sizeof(pMac->roam.validChannelList); + + *pcChannels = 0; + if ( CSR_IS_11D_INFO_FOUND(pMac) && csrRoamIsChannelValid(pMac, pMac->scan.channelOf11dInfo) ) + { + if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len))) + { + //Find the channel index where we found the 11d info + for(index = 0; index < len; index++) + { + if(pMac->scan.channelOf11dInfo == pMac->roam.validChannelList[index]) + break; + } + //check whether we found the channel index + if(index < len) + { + // Now, look through the 11d channel list and create a list of all channels in the 11d list that are + // NOT in the current channel list. This gives us a list of the new channels that have not been + // scanned. We'll scan this new list so we have a complete set of scan results on all of the domain channels + // initially. + for ( index11dChannels = 0; index11dChannels < pMac->scan.channels11d.numChannels; index11dChannels++ ) + { + fChannelAlreadyScanned = eANI_BOOLEAN_FALSE; + + for( indexCurrentChannels = 0; indexCurrentChannels < index; indexCurrentChannels++ ) + { + if ( pMac->roam.validChannelList[ indexCurrentChannels ] == pMac->scan.channels11d.channelList[ index11dChannels ] ) + { + fChannelAlreadyScanned = eANI_BOOLEAN_TRUE; + break; + } + } + + if ( !fChannelAlreadyScanned ) + { + pChannels[ *pcChannels ] = pMac->scan.channels11d.channelList[ index11dChannels ]; + ( *pcChannels )++; + } + } + } + }//GetCFG + } + return( *pcChannels ); +} + + +eCsrScanCompleteNextCommand csrScanGetNextCommandState( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fSuccess ) +{ + eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing; + + switch( pCommand->u.scanCmd.reason ) + { + case eCsrScan11d1: + NextCommand = (fSuccess) ? eCsrNext11dScan1Success : eCsrNext11dScan1Failure; + break; + case eCsrScan11d2: + NextCommand = (fSuccess) ? eCsrNext11dScan2Success : eCsrNext11dScan2Failure; + break; + case eCsrScan11dDone: + NextCommand = eCsrNext11dScanComplete; + break; + case eCsrScanLostLink1: + NextCommand = (fSuccess) ? eCsrNextLostLinkScan1Success : eCsrNextLostLinkScan1Failed; + break; + case eCsrScanLostLink2: + NextCommand = (fSuccess) ? eCsrNextLostLinkScan2Success : eCsrNextLostLinkScan2Failed; + break; + case eCsrScanLostLink3: + NextCommand = (fSuccess) ? eCsrNextLostLinkScan3Success : eCsrNextLostLinkScan3Failed; + break; + case eCsrScanForSsid: + NextCommand = (fSuccess) ? eCsrNexteScanForSsidSuccess : eCsrNexteScanForSsidFailure; + break; + case eCsrScanForCapsChange: + NextCommand = eCsrNextCapChangeScanComplete; //don't care success or not + break; + case eCsrScanIdleScan: + NextCommand = eCsrNextIdleScanComplete; + break; + default: + NextCommand = eCsrNextScanNothing; + break; + } + return( NextCommand ); +} + + +//Return whether the pCommand is finished. +tANI_BOOLEAN csrHandleScan11d1Failure(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE; + + //Apply back the default setting and passively scan one more time. + csrResetCountryInformation(pMac, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + pCommand->u.scanCmd.reason = eCsrScan11d2; + if(HAL_STATUS_SUCCESS(csrScanChannels(pMac, pCommand))) + { + fRet = eANI_BOOLEAN_FALSE; + } + + return (fRet); +} + + +tANI_BOOLEAN csrHandleScan11dSuccess(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE; + tANI_U8 *pChannels; + tANI_U8 cChannels; + + pChannels = vos_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); + if ( NULL != pChannels ) + { + vos_mem_set(pChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN, 0); + if ( csrGetRemainingChannelsFor11dScan( pMac, pChannels, &cChannels ) ) + { + pCommand->u.scanCmd.reason = eCsrScan11dDone; + if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) + { + vos_mem_free(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL; + } + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(cChannels); + if ( NULL != pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) + { + vos_mem_copy(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, + pChannels, cChannels); + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = cChannels; + pCommand->u.scanCmd.u.scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + pCommand->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + if(HAL_STATUS_SUCCESS(csrScanChannels(pMac, pCommand))) + { + //Reuse the same command buffer + fRet = eANI_BOOLEAN_FALSE; + } + } + } + vos_mem_free(pChannels); + } + + return (fRet); +} + +//Return whether the command should be removed +tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp ) +{ + eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing; + tListElem *pEntry; + tSmeCmd *pCommand; + tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE; + tANI_BOOLEAN fSuccess; + + if (pMac->fScanOffload) + pEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK); + else + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + + // If the head of the queue is Active and it is a SCAN command, remove + // and put this on the Free queue. + if ( eSmeCommandScan == pCommand->command ) + { + tANI_U32 sessionId = pCommand->sessionId; + + if(eSIR_SME_SUCCESS != pScanRsp->statusCode) + { + fSuccess = eANI_BOOLEAN_FALSE; + } + else + { + //pMac->scan.tempScanResults is not empty meaning the scan found something + //This check only valid here because csrSaveScanresults is not yet called + fSuccess = (!csrLLIsListEmpty(&pMac->scan.tempScanResults, LL_ACCESS_LOCK)); + } + if (pCommand->u.scanCmd.abortScanDueToBandChange) + { + /* + * Scan aborted due to band change + * The scan results need to be flushed + */ + if (pCommand->u.scanCmd.callback + != pMac->scan.callback11dScanDone) + { + smsLog(pMac, LOG1, FL("Filtering the scan results as the " + "results may belong to wrong band")); + csrScanFilterResults(pMac); + } + else + { + smsLog(pMac, LOG1, FL("11d_scan_done will flush the scan" + " results")); + } + pCommand->u.scanCmd.abortScanDueToBandChange + = eANI_BOOLEAN_FALSE; + } + csrSaveScanResults(pMac, pCommand->u.scanCmd.reason, sessionId); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_scan_pkt_type *pScanLog = NULL; + tScanResultHandle hScanResult; + tCsrScanResultInfo *pScanResult; + tDot11fBeaconIEs *pIes; + int n = 0, c = 0; + + WLAN_VOS_DIAG_LOG_ALLOC(pScanLog, vos_log_scan_pkt_type, LOG_WLAN_SCAN_C); + if(pScanLog) + { + if(eCsrScanBgScan == pCommand->u.scanCmd.reason || + eCsrScanProbeBss == pCommand->u.scanCmd.reason || + eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason) + { + pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_RSP; + } + else + { + if( eSIR_PASSIVE_SCAN != pMac->scan.curScanType ) + { + pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP; + } + else + { + pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP; + } + } + if(eSIR_SME_SUCCESS == pScanRsp->statusCode) + { + if(HAL_STATUS_SUCCESS(csrScanGetResult(pMac, NULL, &hScanResult))) + { + while(((pScanResult = csrScanResultGetNext(pMac, hScanResult)) != NULL)) + { + if( n < VOS_LOG_MAX_NUM_BSSID ) + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pScanResult->BssDescriptor, &pIes))) + { + smsLog(pMac, LOGE, FL(" fail to parse IEs")); + break; + } + vos_mem_copy(pScanLog->bssid[n], + pScanResult->BssDescriptor.bssId, 6); + if(pIes && pIes->SSID.present && VOS_LOG_MAX_SSID_SIZE >= pIes->SSID.num_ssid) + { + vos_mem_copy(pScanLog->ssid[n], + pIes->SSID.ssid, pIes->SSID.num_ssid); + } + vos_mem_free(pIes); + n++; + } + c++; + } + pScanLog->numSsid = (v_U8_t)n; + pScanLog->totalSsid = (v_U8_t)c; + csrScanResultPurge(pMac, hScanResult); + } + } + else + { + pScanLog->status = WLAN_SCAN_STATUS_FAILURE; + } + WLAN_VOS_DIAG_LOG_REPORT(pScanLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + + NextCommand = csrScanGetNextCommandState(pMac, pCommand, fSuccess); + //We reuse the command here instead reissue a new command + switch(NextCommand) + { + case eCsrNext11dScan1Success: + case eCsrNext11dScan2Success: + smsLog( pMac, LOG2, FL("11dScan1/3 produced results. Reissue Active scan...")); + // if we found country information, no need to continue scanning further, bail out + fRemoveCommand = eANI_BOOLEAN_TRUE; + NextCommand = eCsrNext11dScanComplete; + break; + case eCsrNext11dScan1Failure: + //We are not done yet. 11d scan fail once. We will try to reset anything and do it over again + //The only meaningful thing for this retry is that we cannot find 11d information after a reset so + //we clear the "old" 11d info and give it once more chance + fRemoveCommand = csrHandleScan11d1Failure(pMac, pCommand); + if(fRemoveCommand) + { + NextCommand = eCsrNext11dScanComplete; + } + break; + case eCsrNextLostLinkScan1Success: + if(!HAL_STATUS_SUCCESS(csrIssueRoamAfterLostlinkScan(pMac, sessionId, eCsrLostLink1))) + { + csrScanHandleFailedLostlink1(pMac, sessionId); + } + break; + case eCsrNextLostLinkScan2Success: + if(!HAL_STATUS_SUCCESS(csrIssueRoamAfterLostlinkScan(pMac, sessionId, eCsrLostLink2))) + { + csrScanHandleFailedLostlink2(pMac, sessionId); + } + break; + case eCsrNextLostLinkScan3Success: + if(!HAL_STATUS_SUCCESS(csrIssueRoamAfterLostlinkScan(pMac, sessionId, eCsrLostLink3))) + { + csrScanHandleFailedLostlink3(pMac, sessionId); + } + break; + case eCsrNextLostLinkScan1Failed: + csrScanHandleFailedLostlink1(pMac, sessionId); + break; + case eCsrNextLostLinkScan2Failed: + csrScanHandleFailedLostlink2(pMac, sessionId); + break; + case eCsrNextLostLinkScan3Failed: + csrScanHandleFailedLostlink3(pMac, sessionId); + break; + case eCsrNexteScanForSsidSuccess: + csrScanHandleSearchForSSID(pMac, pCommand); + break; + case eCsrNexteScanForSsidFailure: + csrScanHandleSearchForSSIDFailure(pMac, pCommand); + break; + case eCsrNextIdleScanComplete: + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + break; + case eCsrNextCapChangeScanComplete: + csrScanHandleCapChangeScanComplete(pMac, sessionId); + break; + default: + + break; + } + } + else + { + smsLog( pMac, LOGW, FL("Scan Completion called but SCAN command is not ACTIVE ...")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + } + } + else + { + smsLog( pMac, LOGW, FL("Scan Completion called but NO commands are ACTIVE ...")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + } + + return( fRemoveCommand ); +} + + + +static void csrScanRemoveDupBssDescriptionFromInterimList( tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDescr, + tDot11fBeaconIEs *pIes) +{ + tListElem *pEntry; + tCsrScanResult *pCsrBssDescription; + + csrLLLock(&pMac->scan.tempScanResults); + // Walk through all the chained BssDescriptions. If we find a chained BssDescription that + // matches the BssID of the BssDescription passed in, then these must be duplicate scan + // results for this Bss. In that case, remove the 'old' Bss description from the linked list. + pEntry = csrLLPeekHead(&pMac->scan.tempScanResults, LL_ACCESS_NOLOCK); + while( pEntry ) + { + pCsrBssDescription = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + + // we have a duplicate scan results only when BSSID, SSID, Channel and NetworkType + // matches + + if ( csrIsDuplicateBssDescription( pMac, &pCsrBssDescription->Result.BssDescriptor, + pSirBssDescr, pIes, FALSE ) ) + { + pSirBssDescr->rssi = (tANI_S8)( (((tANI_S32)pSirBssDescr->rssi * CSR_SCAN_RESULT_RSSI_WEIGHT ) + + ((tANI_S32)pCsrBssDescription->Result.BssDescriptor.rssi * (100 - CSR_SCAN_RESULT_RSSI_WEIGHT) )) / 100 ); + + // Remove the 'old' entry from the list.... + if(csrLLRemoveEntry(&pMac->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK)) + { + csrCheckNSaveWscIe(pMac, pSirBssDescr, &pCsrBssDescription->Result.BssDescriptor); + // we need to free the memory associated with this node + csrFreeScanResultEntry( pMac, pCsrBssDescription ); + } + + // If we found a match, we can stop looking through the list. + break; + } + + pEntry = csrLLNext(&pMac->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK); + } + csrLLUnlock(&pMac->scan.tempScanResults); +} + + + +//Caller allocated memory pfNewBssForConn to return whether new candidate for +//current connection is found. Cannot be NULL +tCsrScanResult *csrScanSaveBssDescriptionToInterimList( tpAniSirGlobal pMac, + tSirBssDescription *pBSSDescription, + tDot11fBeaconIEs *pIes) +{ + tCsrScanResult *pCsrBssDescription = NULL; + tANI_U32 cbBSSDesc; + tANI_U32 cbAllocated; + + // figure out how big the BSS description is (the BSSDesc->length does NOT + // include the size of the length field itself). + cbBSSDesc = pBSSDescription->length + sizeof( pBSSDescription->length ); + + cbAllocated = sizeof( tCsrScanResult ) + cbBSSDesc; + + pCsrBssDescription = vos_mem_malloc(cbAllocated); + if ( NULL != pCsrBssDescription ) + { + vos_mem_set(pCsrBssDescription, cbAllocated, 0); + pCsrBssDescription->AgingCount = (tANI_S32)pMac->roam.configParam.agingCount; + smsLog(pMac, LOGW, + FL(" Set Aging Count = %d for BSS "MAC_ADDRESS_STR" "), + pCsrBssDescription->AgingCount, + MAC_ADDR_ARRAY(pBSSDescription->bssId)); + vos_mem_copy(&pCsrBssDescription->Result.BssDescriptor, pBSSDescription, cbBSSDesc ); + //Save SSID separately for later use + if( pIes->SSID.present && !csrIsNULLSSID(pIes->SSID.ssid, pIes->SSID.num_ssid) ) + { + //SSID not hidden + tANI_U32 len = pIes->SSID.num_ssid; + if (len > SIR_MAC_MAX_SSID_LENGTH) + { + // truncate to fit in our struct + len = SIR_MAC_MAX_SSID_LENGTH; + } + pCsrBssDescription->Result.ssId.length = len; + pCsrBssDescription->Result.timer = vos_timer_get_system_time(); + vos_mem_copy(pCsrBssDescription->Result.ssId.ssId, pIes->SSID.ssid, len); + } + csrLLInsertTail( &pMac->scan.tempScanResults, &pCsrBssDescription->Link, LL_ACCESS_LOCK ); + } + + return( pCsrBssDescription ); +} + + + + +tANI_BOOLEAN csrIsDuplicateBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2, tANI_BOOLEAN fForced ) +{ + tANI_BOOLEAN fMatch = FALSE; + tSirMacCapabilityInfo *pCap1, *pCap2; + tDot11fBeaconIEs *pIes1 = NULL; + tDot11fBeaconIEs *pIesTemp = pIes2; + + pCap1 = (tSirMacCapabilityInfo *)&pSirBssDesc1->capabilityInfo; + pCap2 = (tSirMacCapabilityInfo *)&pSirBssDesc2->capabilityInfo; + if(pCap1->ess == pCap2->ess) + { + if (pCap1->ess && + csrIsMacAddressEqual( pMac, (tCsrBssid *)pSirBssDesc1->bssId, (tCsrBssid *)pSirBssDesc2->bssId)&& + (fForced || (vos_chan_to_band(pSirBssDesc1->channelId) == vos_chan_to_band((pSirBssDesc2->channelId))))) + { + fMatch = TRUE; + // Check for SSID match, if exists + do + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc1, &pIes1))) + { + break; + } + if( NULL == pIesTemp ) + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc2, &pIesTemp))) + { + break; + } + } + if(pIes1->SSID.present && pIesTemp->SSID.present) + { + fMatch = csrIsSsidMatch(pMac, pIes1->SSID.ssid, pIes1->SSID.num_ssid, + pIesTemp->SSID.ssid, pIesTemp->SSID.num_ssid, eANI_BOOLEAN_TRUE); + } + }while(0); + + } + else if (pCap1->ibss && (pSirBssDesc1->channelId == pSirBssDesc2->channelId)) + { + + do + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc1, &pIes1))) + { + break; + } + if( NULL == pIesTemp ) + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc2, &pIesTemp))) + { + break; + } + } + //Same channel cannot have same SSID for different IBSS + if(pIes1->SSID.present && pIesTemp->SSID.present) + { + fMatch = csrIsSsidMatch(pMac, pIes1->SSID.ssid, pIes1->SSID.num_ssid, + pIesTemp->SSID.ssid, pIesTemp->SSID.num_ssid, eANI_BOOLEAN_TRUE); + } + }while(0); + } + /* In case of P2P devices, ess and ibss will be set to zero */ + else if (!pCap1->ess && + csrIsMacAddressEqual( pMac, (tCsrBssid *)pSirBssDesc1->bssId, (tCsrBssid *)pSirBssDesc2->bssId)) + { + fMatch = TRUE; + } + } + + if(pIes1) + { + vos_mem_free(pIes1); + } + + if( (NULL == pIes2) && pIesTemp ) + { + //locally allocated + vos_mem_free(pIesTemp); + } + + return( fMatch ); +} + + +tANI_BOOLEAN csrIsNetworkTypeEqual( tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 ) +{ + return( pSirBssDesc1->nwType == pSirBssDesc2->nwType ); +} + + +//to check whether the BSS matches the dot11Mode +static tANI_BOOLEAN csrScanIsBssAllowed(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + tANI_BOOLEAN fAllowed = eANI_BOOLEAN_FALSE; + eCsrPhyMode phyMode; + + if(HAL_STATUS_SUCCESS(csrGetPhyModeFromBss(pMac, pBssDesc, &phyMode, pIes))) + { + switch(pMac->roam.configParam.phyMode) + { + case eCSR_DOT11_MODE_11b: + fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11a != phyMode); + break; + case eCSR_DOT11_MODE_11g: + fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11a != phyMode); + break; + case eCSR_DOT11_MODE_11g_ONLY: + fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11g == phyMode); + break; + case eCSR_DOT11_MODE_11a: + fAllowed = (tANI_BOOLEAN)((eCSR_DOT11_MODE_11b != phyMode) && (eCSR_DOT11_MODE_11g != phyMode)); + break; + case eCSR_DOT11_MODE_11n_ONLY: + fAllowed = (tANI_BOOLEAN)((eCSR_DOT11_MODE_11n == phyMode)); + break; + +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac_ONLY: + fAllowed = (tANI_BOOLEAN)((eCSR_DOT11_MODE_11ac == phyMode)); + break; +#endif + case eCSR_DOT11_MODE_11b_ONLY: + fAllowed = (tANI_BOOLEAN)(eCSR_DOT11_MODE_11b == phyMode); + break; + case eCSR_DOT11_MODE_11n: +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: +#endif + default: + fAllowed = eANI_BOOLEAN_TRUE; + break; + } + } + + return (fAllowed); +} + + + +//Return pIes to caller for future use when returning TRUE. +static tANI_BOOLEAN csrScanValidateScanResult( tpAniSirGlobal pMac, tANI_U8 *pChannels, + tANI_U8 numChn, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs **ppIes ) +{ + tANI_BOOLEAN fValidChannel = FALSE; + tDot11fBeaconIEs *pIes = NULL; + tANI_U8 index; + + for( index = 0; index < numChn; index++ ) + { + /* + * This check relies on the fact that a single BSS description is + * returned in each ScanRsp call, which is the way LIM implemented + * the scan req/rsp functions. We changed to this model when we ran + * with a large number of APs. If this were to change, then this check + * would have to mess with removing the bssDescription from somewhere + * in an arbitrary index in the bssDescription array. + */ + if ( pChannels[ index ] == pBssDesc->channelId ) + { + fValidChannel = TRUE; + break; + } + } + *ppIes = NULL; + if(fValidChannel) + { + if( HAL_STATUS_SUCCESS( csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes) ) ) + { + fValidChannel = csrScanIsBssAllowed(pMac, pBssDesc, pIes); + if( fValidChannel ) + { + *ppIes = pIes; + } + else + { + vos_mem_free(pIes); + } + } + else + { + fValidChannel = FALSE; + } + } + + return( fValidChannel ); +} + + +//Return whether last scan result is received +static tANI_BOOLEAN csrScanProcessScanResults( tpAniSirGlobal pMac, tSmeCmd *pCommand, + tSirSmeScanRsp *pScanRsp, tANI_BOOLEAN *pfRemoveCommand ) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE, fRemoveCommand = eANI_BOOLEAN_FALSE; + tDot11fBeaconIEs *pIes = NULL; + tANI_U32 cbParsed; + tSirBssDescription *pSirBssDescription; + tANI_U32 cbBssDesc; + tANI_U32 cbScanResult = GET_FIELD_OFFSET( tSirSmeScanRsp, bssDescription ) + + sizeof(tSirBssDescription); //We need at least one CB + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pScanRsp->sessionId]; + + /* + * Don't consider the scan rsp to be valid if the status code is Scan + * Failure. Scan Failure is returned when the scan could not find anything. + * So if we get scan failure return that the scan response is invalid. + * Also check the length in the scan result for valid scan BssDescriptions. + */ + do + { + if ( ( cbScanResult <= pScanRsp->length ) && + (( eSIR_SME_SUCCESS == pScanRsp->statusCode ) || + ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW == pScanRsp->statusCode ) ) ) + { + tANI_U8 *pChannelList = NULL; + tANI_U8 cChannels = 0; + + //Different scan type can reach this point, we need to distinguish it +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if( eCsrScanGetLfrResult == pCommand->u.scanCmd.reason ) + { + pChannelList = NULL; + cChannels = 0; + } + else +#endif + if( eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason ) + { + //eCsrScanSetBGScanParam uses different structure + tCsrBGScanRequest *pBgScanReq = &pCommand->u.scanCmd.u.bgScanRequest; + + cChannels = pBgScanReq->ChannelInfo.numOfChannels; + pChannelList = pBgScanReq->ChannelInfo.ChannelList; + } + else + { + //the rest use generic scan request + cChannels = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + pChannelList = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList; + } + + // if the scan result is not on one of the channels in the Valid channel list, then it + // must have come from an AP on an overlapping channel (in the 2.4GHz band). In this case, + // let's drop the scan result. + // + // The other situation is where the scan request is for a scan on a particular channel set + // and the scan result is from a + + // if the NumChannels is 0, then we are supposed to be scanning all channels. Use the full channel + // list as the 'valid' channel list. Otherwise, use the specific channel list in the scan parms + // as the valid channels. + if ( 0 == cChannels ) + { + tANI_U32 len = sizeof(pMac->roam.validChannelList); + + if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len))) + { + pChannelList = pMac->roam.validChannelList; + cChannels = (tANI_U8)len; + } + else + { + //Cannot continue + smsLog( pMac, LOGE, "CSR: Processing internal SCAN results...csrGetCfgValidChannels failed" ); + break; + } + } + + smsLog( pMac, LOG2, "CSR: Processing internal SCAN results..." ); + cbParsed = GET_FIELD_OFFSET( tSirSmeScanRsp, bssDescription ); + pSirBssDescription = pScanRsp->bssDescription; + while( cbParsed < pScanRsp->length ) + { + if ( csrScanValidateScanResult( pMac, pChannelList, cChannels, pSirBssDescription, &pIes ) ) + { + csrScanRemoveDupBssDescriptionFromInterimList(pMac, pSirBssDescription, pIes); + csrScanSaveBssDescriptionToInterimList( pMac, pSirBssDescription, pIes ); + if( eSIR_PASSIVE_SCAN == pMac->scan.curScanType ) + { + if( csrIs11dSupported( pMac) ) + { + //Check whether the BSS is acceptable base on 11d info and our configs. + if( csrMatchCountryCode( pMac, NULL, pIes ) ) + { + //Double check whether the channel is acceptable by us. + if( csrIsSupportedChannel( pMac, pSirBssDescription->channelId ) ) + { + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + } + } + } + else + { + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + } + } + //Free the resource + vos_mem_free(pIes); + } + // skip over the BSS description to the next one... + cbBssDesc = pSirBssDescription->length + sizeof( pSirBssDescription->length ); + + cbParsed += cbBssDesc; + pSirBssDescription = (tSirBssDescription *)((tANI_U8 *)pSirBssDescription + cbBssDesc ); + + } //while + } + else + { + smsLog( pMac, LOGW, " Scanrsp fail (0x%08X), length = %d (expected %d)", + pScanRsp->statusCode, pScanRsp->length, cbScanResult); + //HO bg scan/probe failed no need to try autonomously + if(eCsrScanBgScan == pCommand->u.scanCmd.reason || + eCsrScanProbeBss == pCommand->u.scanCmd.reason || +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + eCsrScanGetLfrResult == pCommand->u.scanCmd.reason || +#endif + eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason) + { + fRemoveCommand = eANI_BOOLEAN_TRUE; + } + } + }while(0); + if ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW != pScanRsp->statusCode ) + { + smsLog(pMac, LOGE, "Found %d BSS, statusCode %d", + csrLLCount(&pMac->scan.tempScanResults), + pScanRsp->statusCode); + smsLog(pMac, LOG1, "scan reason is %d", pCommand->u.scanCmd.reason); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + csr_diag_event_report(pMac, eCSR_EVENT_SCAN_COMPLETE, eSIR_SUCCESS, + eSIR_SUCCESS); + if (csrLLCount(&pMac->scan.tempScanResults) > 0) + csr_diag_event_report(pMac, eCSR_EVENT_SCAN_RES_FOUND, eSIR_SUCCESS, + eSIR_SUCCESS); +#endif + fRemoveCommand = csrScanComplete( pMac, pScanRsp ); + fRet = eANI_BOOLEAN_TRUE; + }//if ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW != pScanRsp->statusCode ) + if(pfRemoveCommand) + { + *pfRemoveCommand = fRemoveCommand; + } + +#ifdef WLAN_AP_STA_CONCURRENCY + if (pMac->fScanOffload) + return fRet; + + if (!csrLLIsListEmpty( &pMac->scan.scanCmdPendingList, LL_ACCESS_LOCK )) + { + /* Pending scan commands in the list because the previous scan command + * was split into a scan command on one channel + a scan command for all + * remaining channels. + * + * Start timer to trigger processing of the next scan command. + * NOTE for LFR: + * Do not split scans if no concurrent infra connections are + * active and if the scan is a BG scan triggered by LFR (OR) + * any scan if LFR is in the middle of a BG scan. Splitting + * the scan is delaying the time it takes for LFR to find + * candidates and resulting in disconnects. + */ + if ((csrIsStaSessionConnected(pMac) && +#ifdef FEATURE_WLAN_LFR + (csrIsConcurrentInfraConnected(pMac) || + ((pCommand->u.scanCmd.reason != eCsrScanBgScan) && + (pNeighborRoamInfo->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN))) && +#endif + (pCommand->u.scanCmd.u.scanRequest.p2pSearch != 1)) || + (csrIsP2pSessionConnected(pMac))) + { + /* if active connected sessions present then continue to split scan + * with specified interval between consecutive scans */ + csrSetDefaultScanTiming(pMac, pCommand->u.scanCmd.u.scanRequest.scanType, &(pCommand->u.scanCmd.u.scanRequest)); + vos_timer_start(&pMac->scan.hTimerStaApConcTimer, + pCommand->u.scanCmd.u.scanRequest.restTime); + } else { + /* if no connected sessions present then initiate next scan command immediately */ + /* minimum timer granularity is 10ms */ + vos_timer_start(&pMac->scan.hTimerStaApConcTimer, 10); + } + } +#endif + return (fRet); +} + + +tANI_BOOLEAN csrScanIsWildCardScan( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + tANI_U8 bssid[VOS_MAC_ADDR_SIZE] = {0, 0, 0, 0, 0, 0}; + tANI_BOOLEAN f = vos_mem_compare(pCommand->u.scanCmd.u.scanRequest.bssid, + bssid, sizeof(tCsrBssid)); + + //It is not a wild card scan if the bssid is not broadcast and the number of SSID is 1. + return ((tANI_BOOLEAN)( (f || (0xff == pCommand->u.scanCmd.u.scanRequest.bssid[0])) && + (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs != 1) )); +} + +#ifdef FEATURE_WLAN_SCAN_PNO +eHalStatus csrSavePnoScanResults(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp, + tANI_U8 sessionId) +{ + tSirBssDescription *pSirBssDescription; + tANI_U32 cbScanResult = GET_FIELD_OFFSET( tSirSmeScanRsp, bssDescription ) + + sizeof(tSirBssDescription); //We need at least one CB + tCsrScanResult *pScanResult = NULL; + tAniSSID tmpSsid; + v_TIME_t timer; + tANI_U32 cbParsed; + tANI_U32 cbBssDesc; + tANI_U16 ieLen; + + if ((cbScanResult > pScanRsp->length ) || + (( eSIR_SME_SUCCESS != pScanRsp->statusCode ) && + ( eSIR_SME_MORE_SCAN_RESULTS_FOLLOW != pScanRsp->statusCode ) ) ) + return eHAL_STATUS_FAILURE; + + cbParsed = GET_FIELD_OFFSET( tSirSmeScanRsp, bssDescription ); + pSirBssDescription = pScanRsp->bssDescription; + + while( cbParsed < pScanRsp->length ) + { + // Check whether we have reach out limit + if ( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + { + smsLog( pMac, LOGW, FL( "BSS limit reached")); + return eHAL_STATUS_RESOURCES; + } + + ieLen = (pSirBssDescription->length + sizeof( pSirBssDescription->length ) + - GET_FIELD_OFFSET( tSirBssDescription, ieFields )); + + pScanResult = vos_mem_malloc(sizeof(tCsrScanResult) + ieLen); + if (NULL == pScanResult) + { + smsLog(pMac, LOGE, FL(" Fail to allocate memory for frame")); + return eHAL_STATUS_RESOURCES; + } + + vos_mem_set(pScanResult, sizeof(tCsrScanResult) + ieLen, 0); + + if (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + pSirBssDescription, (tDot11fBeaconIEs **)&pScanResult->Result.pvIes))) + { + smsLog(pMac, LOGE, FL(" Cannot parse IEs")); + csrFreeScanResultEntry(pMac, pScanResult); + return eHAL_STATUS_RESOURCES; + } + + cbBssDesc = pSirBssDescription->length + + sizeof( pSirBssDescription->length ); + + vos_mem_copy(&pScanResult->Result.BssDescriptor, pSirBssDescription, + cbBssDesc); + + // Remove duplicate entry + csrRemoveDupBssDescription( pMac, &pScanResult->Result.BssDescriptor, + (tDot11fBeaconIEs *)pScanResult->Result.pvIes, + &tmpSsid , &timer, FALSE ); + //Add to scan cache + csrScanAddResult(pMac, pScanResult, + (tDot11fBeaconIEs *)pScanResult->Result.pvIes, + sessionId); + + // skip over the BSS description to the next one... + cbParsed += cbBssDesc; + pSirBssDescription = (tSirBssDescription *)((tANI_U8 *)pSirBssDescription + + cbBssDesc ); + } + + return eHAL_STATUS_SUCCESS; +} +#endif + +eHalStatus csrScanSmeScanResponse( tpAniSirGlobal pMac, void *pMsgBuf ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry; + tSmeCmd *pCommand; + eCsrScanStatus scanStatus; + tSirSmeScanRsp *pScanRsp = (tSirSmeScanRsp *)pMsgBuf; + tSmeGetScanChnRsp *pScanChnInfo; + tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE; + eCsrScanReason reason = eCsrScanOther; + + if (pMac->fScanOffload) + pEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, + LL_ACCESS_LOCK); + else + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( eSmeCommandScan == pCommand->command ) + { + scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ? eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE; + reason = pCommand->u.scanCmd.reason; + switch(pCommand->u.scanCmd.reason) + { + case eCsrScanAbortBgScan: + case eCsrScanAbortNormalScan: + case eCsrScanBGScanAbort: + case eCsrScanBGScanEnable: + break; + case eCsrScanGetScanChnInfo: + pScanChnInfo = (tSmeGetScanChnRsp *)pMsgBuf; + /* + * status code not available in tSmeGetScanChnRsp, so + * by default considering it to be success + */ + scanStatus = eSIR_SME_SUCCESS; + csrScanAgeResults(pMac, pScanChnInfo); + break; + case eCsrScanForCapsChange: + csrScanProcessScanResults( pMac, pCommand, pScanRsp, &fRemoveCommand ); + break; + case eCsrScanP2PFindPeer: + scanStatus = ((eSIR_SME_SUCCESS == pScanRsp->statusCode) && (pScanRsp->length > 50)) ? eCSR_SCAN_FOUND_PEER : eCSR_SCAN_FAILURE; + csrScanProcessScanResults( pMac, pCommand, pScanRsp, NULL ); + break; + case eCsrScanSetBGScanParam: + default: + if(csrScanProcessScanResults( pMac, pCommand, pScanRsp, &fRemoveCommand )) + { + /* + * Not to get channel info if the scan is not a + * wild card scan because it may cause scan results got + * aged out incorrectly. + */ + if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (pCommand->u.scanCmd.reason != eCsrScanGetLfrResult) +#endif + ) + { + //Get the list of channels scanned + if( pCommand->u.scanCmd.reason != eCsrScanUserRequest) + { + csrScanGetScanChnInfo(pMac, pCommand->sessionId, + NULL, NULL, + pCommand->u.scanCmd.scanID); + } + else + { + csrScanGetScanChnInfo(pMac, + pCommand->sessionId, + pCommand->u.scanCmd.pContext, + pCommand->u.scanCmd.callback, + pCommand->u.scanCmd.scanID); + pCommand->u.scanCmd.callback = NULL; + } + } + } + break; + }//switch + if(fRemoveCommand) + { + + csrReleaseScanCommand(pMac, pCommand, scanStatus); + + } + smeProcessPendingQueue( pMac ); + } +#ifdef FEATURE_WLAN_SCAN_PNO + else if (pMac->pnoOffload && + !HAL_STATUS_SUCCESS(csrSavePnoScanResults(pMac, pScanRsp, + pScanRsp->sessionId))) + { + smsLog( pMac, LOGE, "CSR: Unable to store scan results for PNO" ); + status = eHAL_STATUS_FAILURE; + } +#endif + else + { + smsLog( pMac, LOGE, "CSR: Scan Completion called but SCAN command is not ACTIVE ..." ); + status = eHAL_STATUS_FAILURE; + } + } +#ifdef FEATURE_WLAN_SCAN_PNO + else if (pMac->pnoOffload && + !HAL_STATUS_SUCCESS(csrSavePnoScanResults(pMac, pScanRsp, + pScanRsp->sessionId))) + { + smsLog( pMac, LOGE, "CSR: Unable to store scan results for PNO" ); + status = eHAL_STATUS_FAILURE; + } +#endif + else if (pMac->pnoOffload == FALSE) + { + smsLog( pMac, LOGE, "CSR: Scan Completion called but NO commands are ACTIVE ..." ); + status = eHAL_STATUS_FAILURE; + } + + return (status); +} + + + + +tCsrScanResultInfo *csrScanResultGetFirst(tpAniSirGlobal pMac, tScanResultHandle hScanResult) +{ + tListElem *pEntry; + tCsrScanResult *pResult; + tCsrScanResultInfo *pRet = NULL; + tScanResultList *pResultList = (tScanResultList *)hScanResult; + + if(pResultList) + { + csrLLLock(&pResultList->List); + pEntry = csrLLPeekHead(&pResultList->List, LL_ACCESS_NOLOCK); + if(pEntry) + { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pRet = &pResult->Result; + } + pResultList->pCurEntry = pEntry; + csrLLUnlock(&pResultList->List); + } + + return pRet; +} + + +tCsrScanResultInfo *csrScanResultGetNext(tpAniSirGlobal pMac, tScanResultHandle hScanResult) +{ + tListElem *pEntry = NULL; + tCsrScanResult *pResult = NULL; + tCsrScanResultInfo *pRet = NULL; + tScanResultList *pResultList = (tScanResultList *)hScanResult; + + if(pResultList) + { + csrLLLock(&pResultList->List); + if(NULL == pResultList->pCurEntry) + { + pEntry = csrLLPeekHead(&pResultList->List, LL_ACCESS_NOLOCK); + } + else + { + pEntry = csrLLNext(&pResultList->List, pResultList->pCurEntry, LL_ACCESS_NOLOCK); + } + if(pEntry) + { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pRet = &pResult->Result; + } + pResultList->pCurEntry = pEntry; + csrLLUnlock(&pResultList->List); + } + + return pRet; +} + + +//This function moves the first BSS that matches the bssid to the head of the result +eHalStatus csrMoveBssToHeadFromBSSID(tpAniSirGlobal pMac, tCsrBssid *bssid, tScanResultHandle hScanResult) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanResultList *pResultList = (tScanResultList *)hScanResult; + tCsrScanResult *pResult = NULL; + tListElem *pEntry = NULL; + + if(pResultList && bssid) + { + csrLLLock(&pResultList->List); + pEntry = csrLLPeekHead(&pResultList->List, LL_ACCESS_NOLOCK); + while(pEntry) + { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + if (vos_mem_compare(bssid, pResult->Result.BssDescriptor.bssId, sizeof(tCsrBssid))) + { + status = eHAL_STATUS_SUCCESS; + csrLLRemoveEntry(&pResultList->List, pEntry, LL_ACCESS_NOLOCK); + csrLLInsertHead(&pResultList->List, pEntry, LL_ACCESS_NOLOCK); + break; + } + pEntry = csrLLNext(&pResultList->List, pResultList->pCurEntry, LL_ACCESS_NOLOCK); + } + csrLLUnlock(&pResultList->List); + } + + return (status); +} + + +//Remove the BSS if possible. +//Return -- TRUE == the BSS is remove. False == Fail to remove it +//This function is called when list lock is held. Be caution what functions it can call. +tANI_BOOLEAN csrScanAgeOutBss(tpAniSirGlobal pMac, tCsrScanResult *pResult) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tANI_U32 i; + tCsrRoamSession *pSession; + tANI_BOOLEAN isConnBssfound = eANI_BOOLEAN_FALSE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + //Not to remove the BSS we are connected to. + if(csrIsConnStateConnectedInfra(pMac, i) && (NULL != pSession->pConnectBssDesc) && + (csrIsDuplicateBssDescription(pMac, &pResult->Result.BssDescriptor, + pSession->pConnectBssDesc, NULL, FALSE)) + ) + { + isConnBssfound = eANI_BOOLEAN_TRUE; + break; + } + } + } + + if( isConnBssfound ) + { + /* Reset the counter so that aging out of connected BSS won't + happen too soon */ + pResult->AgingCount = (tANI_S32)pMac->roam.configParam.agingCount; + smsLog(pMac, LOGW, + FL(" Connected BSS, Set Aging Count=%d for BSS "MAC_ADDRESS_STR" "), + pResult->AgingCount, + MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId)); + pResult->Result.BssDescriptor.nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + return (fRet); + } + else + { + smsLog(pMac, LOGW, "Aging out BSS "MAC_ADDRESS_STR" Channel %d", + MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId), + pResult->Result.BssDescriptor.channelId); + //No need to hold the spin lock because caller should hold the lock for pMac->scan.scanResultList + if(csrLLRemoveEntry(&pMac->scan.scanResultList, &pResult->Link, + LL_ACCESS_NOLOCK)) + { + if (csrIsMacAddressEqual(pMac, + (tCsrBssid *) pResult->Result.BssDescriptor.bssId, + (tCsrBssid *) pMac->scan.currentCountryBssid)) + { + smsLog(pMac, LOGW, "Aging out 11d BSS "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId)); + pMac->scan.currentCountryRSSI = -128; + } + csrFreeScanResultEntry(pMac, pResult); + fRet = eANI_BOOLEAN_TRUE; + } + } + + return (fRet); +} + + +eHalStatus csrScanAgeResults(tpAniSirGlobal pMac, tSmeGetScanChnRsp *pScanChnInfo) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry, *tmpEntry; + tCsrScanResult *pResult; + tLimScanChn *pChnInfo; + tANI_U8 i; + + csrLLLock(&pMac->scan.scanResultList); + for(i = 0; i < pScanChnInfo->numChn; i++) + { + pChnInfo = &pScanChnInfo->scanChn[i]; + pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while( pEntry ) + { + tmpEntry = csrLLNext(&pMac->scan.scanResultList, + pEntry, LL_ACCESS_NOLOCK); + pResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + if(pResult->Result.BssDescriptor.channelId == pChnInfo->channelId) + { + if(pResult->AgingCount <= 0) + { + smsLog(pMac, LOGW, " age out due to ref count"); + csrScanAgeOutBss(pMac, pResult); + } + else + { + pResult->AgingCount--; + smsLog(pMac, LOGW, + FL("Decremented AgingCount=%d for BSS "MAC_ADDRESS_STR""), + pResult->AgingCount, + MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId)); + } + } + pEntry = tmpEntry; + } + } + csrLLUnlock(&pMac->scan.scanResultList); + + return (status); +} + + +eHalStatus csrSendMBScanReq( tpAniSirGlobal pMac, tANI_U16 sessionId, + tCsrScanRequest *pScanReq, tScanReqParam *pScanReqParam ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeScanReq *pMsg; + tANI_U16 msgLen; + tANI_U8 bssid[VOS_MAC_ADDR_SIZE] = {0, 0, 0, 0, 0, 0}; + tSirScanType scanType = pScanReq->scanType; + tANI_U32 minChnTime; //in units of milliseconds + tANI_U32 maxChnTime; //in units of milliseconds + tANI_U32 i; + tANI_U8 selfMacAddr[VOS_MAC_ADDR_SIZE]; + tANI_U8 *pSelfMac = NULL; + + msgLen = (tANI_U16)(sizeof( tSirSmeScanReq ) - sizeof( pMsg->channelList.channelNumber ) + + ( sizeof( pMsg->channelList.channelNumber ) * pScanReq->ChannelInfo.numOfChannels )) + + ( pScanReq->uIEFieldLen ) ; + + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (HAL_STATUS_SUCCESS(status)) + { + do + { + vos_mem_set(pMsg, msgLen, 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ); + pMsg->length = pal_cpu_to_be16(msgLen); + //ToDO: Fill in session info when we need to do scan base on session. + if ((pMac->fScanOffload) && (sessionId != CSR_SESSION_ID_INVALID)) + { + pMsg->sessionId = sessionId; + } + else + { + /* if sessionId == CSR_SESSION_ID_INVALID, then send the scan + request on first available session */ + pMsg->sessionId = 0; + } + if (pMsg->sessionId >= CSR_ROAM_SESSION_MAX) + smsLog( pMac, LOGE, FL(" Invalid Sme Session ID = %d"), pMsg->sessionId ); + pMsg->transactionId = 0; + pMsg->dot11mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); + pMsg->bssType = pal_cpu_to_be32(csrTranslateBsstypeToMacType(pScanReq->BSSType)); + + if ( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + pSelfMac = (tANI_U8 *)&pMac->roam.roamSession[sessionId].selfMacAddr; + } + else + { + // Since we don't have session for the scanning, we find a valid session. In case we fail to + // do so, get the WNI_CFG_STA_ID + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) ) + { + pSelfMac = (tANI_U8 *)&pMac->roam.roamSession[i].selfMacAddr; + break; + } + } + if( CSR_ROAM_SESSION_MAX == i ) + { + tANI_U32 len = VOS_MAC_ADDR_SIZE; + pSelfMac = selfMacAddr; + status = ccmCfgGetStr( pMac, WNI_CFG_STA_ID, pSelfMac, &len ); + if( !HAL_STATUS_SUCCESS( status ) || + ( len < VOS_MAC_ADDR_SIZE ) ) + { + smsLog( pMac, LOGE, FL(" Can not get self MAC address from CFG status = %d"), status ); + //Force failed status + status = eHAL_STATUS_FAILURE; + break; + } + } + } + vos_mem_copy((tANI_U8 *)pMsg->selfMacAddr, pSelfMac, sizeof(tSirMacAddr)); + + //sirCopyMacAddr + vos_mem_copy((tANI_U8 *)pMsg->bssId, (tANI_U8 *)&pScanReq->bssid, sizeof(tSirMacAddr)); + if ( vos_mem_compare(pScanReq->bssid, bssid, sizeof(tCsrBssid))) + { + vos_mem_set(pMsg->bssId, sizeof(tSirMacAddr), 0xff); + } + else + { + vos_mem_copy(pMsg->bssId, pScanReq->bssid, VOS_MAC_ADDR_SIZE); + } + minChnTime = pScanReq->minChnTime; + maxChnTime = pScanReq->maxChnTime; + + //Verify the scan type first, if the scan is active scan, we need to make sure we + //are allowed to do so. + /* if 11d is enabled & we don't see any beacon around, scan type falls + back to passive. But in BT AMP STA mode we need to send out a + directed probe*/ + if( (eSIR_PASSIVE_SCAN != scanType) && (eCSR_SCAN_P2P_DISCOVERY != pScanReq->requestType) + && (eCSR_BSS_TYPE_WDS_STA != pScanReq->BSSType) + && (eANI_BOOLEAN_FALSE == pMac->scan.fEnableBypass11d)) + { + scanType = pMac->scan.curScanType; + if(eSIR_PASSIVE_SCAN == pMac->scan.curScanType) + { + if(minChnTime < pMac->roam.configParam.nPassiveMinChnTime) + { + minChnTime = pMac->roam.configParam.nPassiveMinChnTime; + } + if(maxChnTime < pMac->roam.configParam.nPassiveMaxChnTime) + { + maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; + } + } + } + pMsg->scanType = pal_cpu_to_be32(scanType); + + pMsg->numSsid = + (pScanReq->SSIDs.numOfSSIDs < SIR_SCAN_MAX_NUM_SSID) ? + pScanReq->SSIDs.numOfSSIDs : SIR_SCAN_MAX_NUM_SSID; + if((pScanReq->SSIDs.numOfSSIDs != 0) && ( eSIR_PASSIVE_SCAN != scanType )) + { + for (i = 0; i < pMsg->numSsid; i++) + { + vos_mem_copy(&pMsg->ssId[i], + &pScanReq->SSIDs.SSIDList[i].SSID, sizeof(tSirMacSSid)); + } + } + else + { + //Otherwise we scan all SSID and let the result filter later + for (i = 0; i < SIR_SCAN_MAX_NUM_SSID; i++) + { + pMsg->ssId[i].length = 0; + } + } + + pMsg->minChannelTime = pal_cpu_to_be32(minChnTime); + pMsg->maxChannelTime = pal_cpu_to_be32(maxChnTime); + pMsg->minChannelTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pMsg->maxChannelTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + //hidden SSID option + pMsg->hiddenSsid = pScanReqParam->hiddenSsid; + /* maximum rest time */ + pMsg->restTime = pScanReq->restTime; + /* Minimum rest time */ + pMsg->min_rest_time = pScanReq->min_rest_time; + /* Idle time */ + pMsg->idle_time = pScanReq->idle_time; + + pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch; + // All the scan results caching will be done by Roaming + // We do not want LIM to do any caching of scan results, + // so delete the LIM cache on all scan requests + pMsg->returnFreshResults = pScanReqParam->freshScan; + //Always ask for unique result + pMsg->returnUniqueResults = pScanReqParam->fUniqueResult; + pMsg->channelList.numChannels = (tANI_U8)pScanReq->ChannelInfo.numOfChannels; + if(pScanReq->ChannelInfo.numOfChannels) + { + //Assuming the channelNumber is tANI_U8 (1 byte) + vos_mem_copy(pMsg->channelList.channelNumber, + pScanReq->ChannelInfo.ChannelList, + pScanReq->ChannelInfo.numOfChannels); + } + + pMsg->uIEFieldLen = (tANI_U16) pScanReq->uIEFieldLen; + pMsg->uIEFieldOffset = (tANI_U16)(sizeof( tSirSmeScanReq ) - sizeof( pMsg->channelList.channelNumber ) + + ( sizeof( pMsg->channelList.channelNumber ) * pScanReq->ChannelInfo.numOfChannels )) ; + if(pScanReq->uIEFieldLen != 0) + { + vos_mem_copy((tANI_U8 *)pMsg+pMsg->uIEFieldOffset, pScanReq->pIEField, + pScanReq->uIEFieldLen); + } + pMsg->p2pSearch = pScanReq->p2pSearch; + + if (pScanReq->requestType == eCSR_SCAN_HO_BG_SCAN) + { + pMsg->backgroundScanMode = eSIR_ROAMING_SCAN; + } + + }while(0); + smsLog(pMac, LOG1, FL("domainIdCurrent %s (%d) scanType %s (%d)" + "bssType %s (%d), requestType %s(%d)" + "numChannels %d"), + voss_DomainIdtoString(pMac->scan.domainIdCurrent), + pMac->scan.domainIdCurrent, + lim_ScanTypetoString(pMsg->scanType), pMsg->scanType, + lim_BssTypetoString(pMsg->bssType), pMsg->bssType, + sme_requestTypetoString(pScanReq->requestType), + pScanReq->requestType, + pMsg->channelList.numChannels); + + + for(i = 0; i < pMsg->channelList.numChannels; i++) + { + smsLog(pMac, LOG1, FL("channelNumber[%d]= %d"), i, pMsg->channelList.channelNumber[i]); + } + + if(HAL_STATUS_SUCCESS(status)) + { + status = palSendMBMessage(pMac->hHdd, pMsg); + } + else + { + smsLog( pMac, LOGE, FL(" failed to send down scan req with status = %d"), status ); + vos_mem_free(pMsg); + } + }//Success allocated memory + else + { + smsLog( pMac, LOGE, FL(" memory allocation failure")); + } + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOG1, FL("Failed: SId: %d FirstMatch = %d" + " UniqueResult = %d freshScan = %d hiddenSsid = %d"), + sessionId, pScanReqParam->bReturnAfter1stMatch, + pScanReqParam->fUniqueResult, pScanReqParam->freshScan, + pScanReqParam->hiddenSsid ); + smsLog( pMac, LOG1, FL("scanType = %s (%d) BSSType = %s (%d) " + "numOfSSIDs = %d numOfChannels = %d requestType = %s (%d)" + " p2pSearch = %d\n"), + lim_ScanTypetoString(pScanReq->scanType), + pScanReq->scanType, + lim_BssTypetoString(pScanReq->BSSType), + pScanReq->BSSType, + pScanReq->SSIDs.numOfSSIDs, + pScanReq->ChannelInfo.numOfChannels, + sme_requestTypetoString(pScanReq->requestType), + pScanReq->requestType, + pScanReq->p2pSearch ); + + } + + return( status ); +} + +eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tANI_U32 sessionId, tScanReqParam *pScanReqParam ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeScanReq *pMsg; + tANI_U16 msgLen; + + msgLen = (tANI_U16)(sizeof( tSirSmeScanReq )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pMsg, msgLen, 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ); + pMsg->length = pal_cpu_to_be16(msgLen); + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; + pMsg->returnFreshResults = pScanReqParam->freshScan; + //Always ask for unique result + pMsg->returnUniqueResults = pScanReqParam->fUniqueResult; + pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch; + status = palSendMBMessage(pMac->hHdd, pMsg); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE, FL(" failed to send down scan req with status = %d\n"), status ); + } + + } + + return( status ); +} + + + +eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanReqParam scanReq; + + do + { + /* + * Don't delete cached results. Rome rssi based scan candidates + * may land up in scan cache instead of LFR cache. + * They will be deleted upon query. + */ + scanReq.freshScan = SIR_BG_SCAN_RETURN_FRESH_RESULTS; + scanReq.fUniqueResult = TRUE; + scanReq.hiddenSsid = SIR_SCAN_NO_HIDDEN_SSID; + if(eCsrScanForSsid == pCommand->u.scanCmd.reason) + { + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_FIRST_MATCH; + } + else + { + // Basically do scan on all channels even for 11D 1st scan case. + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + if((eCsrScanBgScan == pCommand->u.scanCmd.reason)|| + (eCsrScanProbeBss == pCommand->u.scanCmd.reason)) + { + scanReq.hiddenSsid = SIR_SCAN_HIDDEN_SSID_PE_DECISION; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_scan_pkt_type *pScanLog = NULL; + + WLAN_VOS_DIAG_LOG_ALLOC(pScanLog, vos_log_scan_pkt_type, LOG_WLAN_SCAN_C); + if(pScanLog) + { + if(eCsrScanBgScan == pCommand->u.scanCmd.reason || + eCsrScanProbeBss == pCommand->u.scanCmd.reason) + { + pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ; + } + else + { + if( (eSIR_PASSIVE_SCAN != pCommand->u.scanCmd.u.scanRequest.scanType) && + (eSIR_PASSIVE_SCAN != pMac->scan.curScanType) ) + { + pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ; + } + else + { + pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ; + } + } + pScanLog->minChnTime = (v_U8_t)pCommand->u.scanCmd.u.scanRequest.minChnTime; + pScanLog->maxChnTime = (v_U8_t)pCommand->u.scanCmd.u.scanRequest.maxChnTime; + pScanLog->numChannel = (v_U8_t)pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + if(pScanLog->numChannel && (pScanLog->numChannel < VOS_LOG_MAX_NUM_CHANNEL)) + { + vos_mem_copy(pScanLog->channels, + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, + pScanLog->numChannel); + } + WLAN_VOS_DIAG_LOG_REPORT(pScanLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + + csrClearVotesForCountryInfo(pMac); + status = csrSendMBScanReq(pMac, pCommand->sessionId, + &pCommand->u.scanCmd.u.scanRequest, &scanReq); + }while(0); + + return( status ); +} + + +eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tScanReqParam scanReq; + + do + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (eCsrScanGetLfrResult == pCommand->u.scanCmd.reason) + { + //to get the LFR candidates from PE cache + scanReq.freshScan = SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS|SIR_BG_SCAN_PURGE_LFR_RESULTS; + scanReq.fUniqueResult = TRUE; + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + else +#endif + { + //not a fresh scan + scanReq.freshScan = SIR_BG_SCAN_PURGE_RESUTLS; + scanReq.fUniqueResult = TRUE; + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + status = csrSendMBScanResultReq(pMac, pCommand->sessionId, &scanReq); + }while(0); + + return (status); +} + + + +eHalStatus csrProcessScanCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrChannelInfo newChannelInfo = {0, NULL}; + int i, j; + tANI_U8 *pChannel = NULL; + tANI_U32 len = 0; + + // Transition to Scanning state... + if (!pMac->fScanOffload) + { + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + pCommand->u.scanCmd.lastRoamState[i] = + csrRoamStateChange( pMac, eCSR_ROAMING_STATE_SCANNING, i); + smsLog( pMac, LOG3, "starting SCAN command from %d state...." + " reason is %d", pCommand->u.scanCmd.lastRoamState[i], + pCommand->u.scanCmd.reason ); + } + } + else + { + pCommand->u.scanCmd.lastRoamState[pCommand->sessionId] = + csrRoamStateChange(pMac, eCSR_ROAMING_STATE_SCANNING, + pCommand->sessionId); + smsLog( pMac, LOG3, + "starting SCAN command from %d state.... reason is %d", + pCommand->u.scanCmd.lastRoamState[pCommand->sessionId], + pCommand->u.scanCmd.reason ); + } + + switch(pCommand->u.scanCmd.reason) + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif + case eCsrScanGetResult: + case eCsrScanForCapsChange: //For cap change, LIM already save BSS description + status = csrScanRetrieveResult(pMac, pCommand); + break; + case eCsrScanSetBGScanParam: + status = csrProcessSetBGScanParam(pMac, pCommand); + break; + case eCsrScanBGScanAbort: + status = csrSetCfgBackgroundScanPeriod(pMac, 0); + break; + case eCsrScanBGScanEnable: + status = csrSetCfgBackgroundScanPeriod(pMac, pMac->roam.configParam.bgScanInterval); + break; + case eCsrScanGetScanChnInfo: + status = csrScanGetScanChannelInfo(pMac, pCommand->sessionId); + break; + case eCsrScanUserRequest: + if(pMac->roam.configParam.fScanTwice) + { + //We scan 2.4 channel twice + if(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels && + (NULL != pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)) + { + len = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + /* Allocate twice the channel */ + newChannelInfo.ChannelList = vos_mem_malloc(len * 2); + pChannel = pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList; + } + else + { + //get the valid channel list to scan all. + len = sizeof(pMac->roam.validChannelList); + + if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len))) + { + //allocate twice the channel + newChannelInfo.ChannelList = (tANI_U8 *)vos_mem_malloc(len * 2); + pChannel = pMac->roam.validChannelList; + } + } + if(NULL == newChannelInfo.ChannelList) + { + newChannelInfo.numOfChannels = 0; + } + else + { + j = 0; + for(i = 0; i < len; i++) + { + newChannelInfo.ChannelList[j++] = pChannel[i]; + if(CSR_MAX_24GHz_CHANNEL_NUMBER >= pChannel[i]) + { + newChannelInfo.ChannelList[j++] = pChannel[i]; + } + } + if(NULL != pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) + { + //pChannel points to the channellist from the command, free it. + vos_mem_free(pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = NULL; + } + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = j; + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = newChannelInfo.ChannelList; + } + } //if(pMac->roam.configParam.fScanTwice) + + status = csrScanChannels(pMac, pCommand); + + break; + default: + status = csrScanChannels(pMac, pCommand); + break; + } + + if(!HAL_STATUS_SUCCESS(status)) + { + csrReleaseScanCommand(pMac, pCommand, eCSR_SCAN_FAILURE); + } + + return (status); +} + + +eHalStatus csrScanSetBGScanparams(tpAniSirGlobal pMac, tCsrBGScanRequest *pScanReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand = NULL; + + if(pScanReq) + { + do + { + pCommand = csrGetCommandBuffer(pMac); + if(!pCommand) + { + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); + pCommand->command = eSmeCommandScan; + pCommand->u.scanCmd.reason = eCsrScanSetBGScanParam; + pCommand->u.scanCmd.callback = NULL; + pCommand->u.scanCmd.pContext = NULL; + vos_mem_copy(&pCommand->u.scanCmd.u.bgScanRequest, pScanReq, sizeof(tCsrBGScanRequest)); + //we have to do the follow + if(pScanReq->ChannelInfo.numOfChannels == 0) + { + pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList = NULL; + } + else + { + pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList + = vos_mem_malloc(pScanReq->ChannelInfo.numOfChannels); + if ( NULL != pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList ) + { + vos_mem_copy(pCommand->u.scanCmd.u.bgScanRequest.ChannelInfo.ChannelList, + pScanReq->ChannelInfo.ChannelList, + pScanReq->ChannelInfo.numOfChannels); + } + else + { + smsLog(pMac, LOGE, FL("ran out of memory")); + csrReleaseCommandScan(pMac, pCommand); + return eHAL_STATUS_FAILURE; + } + } + + //scan req for SSID + if(pScanReq->SSID.length) + { + vos_mem_copy(pCommand->u.scanCmd.u.bgScanRequest.SSID.ssId, + pScanReq->SSID.ssId, pScanReq->SSID.length); + pCommand->u.scanCmd.u.bgScanRequest.SSID.length = pScanReq->SSID.length; + + } + pCommand->u.scanCmd.u.bgScanRequest.maxChnTime= pScanReq->maxChnTime; + pCommand->u.scanCmd.u.bgScanRequest.minChnTime = pScanReq->minChnTime; + pCommand->u.scanCmd.u.bgScanRequest.scanInterval = pScanReq->scanInterval; + + + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandScan( pMac, pCommand ); + break; + } + }while(0); + } + + return (status); +} + +eHalStatus csrScanBGScanAbort( tpAniSirGlobal pMac ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand = NULL; + + do + { + pCommand = csrGetCommandBuffer(pMac); + if(!pCommand) + { + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); + pCommand->command = eSmeCommandScan; + pCommand->u.scanCmd.reason = eCsrScanBGScanAbort; + pCommand->u.scanCmd.callback = NULL; + pCommand->u.scanCmd.pContext = NULL; + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandScan( pMac, pCommand ); + break; + } + }while(0); + + return (status); +} + + +//This will enable the background scan with the non-zero interval +eHalStatus csrScanBGScanEnable(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pCommand = NULL; + + if(pMac->roam.configParam.bgScanInterval) + { + do + { + pCommand = csrGetCommandBuffer(pMac); + if(!pCommand) + { + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); + pCommand->command = eSmeCommandScan; + pCommand->u.scanCmd.reason = eCsrScanBGScanEnable; + pCommand->u.scanCmd.callback = NULL; + pCommand->u.scanCmd.pContext = NULL; + status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + csrReleaseCommandScan( pMac, pCommand ); + break; + } + }while(0); + } + else + { + smsLog(pMac, LOGE, FL("cannot continue because the bgscan interval is 0")); + status = eHAL_STATUS_INVALID_PARAMETER; + } + + return (status); +} + + +eHalStatus csrScanCopyRequest(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, tCsrScanRequest *pSrcReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 len = sizeof(pMac->roam.validChannelList); + tANI_U32 index = 0; + tANI_U32 new_index = 0; + eNVChannelEnabledType NVchannel_state; + bool skip_dfs_chnl = pMac->roam.configParam.initial_scan_no_dfs_chnl || + !pMac->scan.fEnableDFSChnlScan; + + do + { + status = csrScanFreeRequest(pMac, pDstReq); + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_copy(pDstReq, pSrcReq, sizeof(tCsrScanRequest)); + /* Re-initialize the pointers to NULL since we did a copy */ + pDstReq->pIEField = NULL; + pDstReq->ChannelInfo.ChannelList = NULL; + pDstReq->SSIDs.SSIDList = NULL; + + if(pSrcReq->uIEFieldLen == 0) + { + pDstReq->pIEField = NULL; + } + else + { + pDstReq->pIEField = vos_mem_malloc(pSrcReq->uIEFieldLen); + if ( NULL == pDstReq->pIEField ) + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, FL("No memory for scanning IE fields")); + break; + } + else + { + status = eHAL_STATUS_SUCCESS; + vos_mem_copy(pDstReq->pIEField, pSrcReq->pIEField, + pSrcReq->uIEFieldLen); + pDstReq->uIEFieldLen = pSrcReq->uIEFieldLen; + } + }//Allocate memory for IE field + { + if(pSrcReq->ChannelInfo.numOfChannels == 0) + { + pDstReq->ChannelInfo.ChannelList = NULL; + pDstReq->ChannelInfo.numOfChannels = 0; + } + else + { + pDstReq->ChannelInfo.ChannelList = vos_mem_malloc( + pSrcReq->ChannelInfo.numOfChannels + * sizeof(*pDstReq->ChannelInfo.ChannelList)); + if ( NULL == pDstReq->ChannelInfo.ChannelList ) + { status = eHAL_STATUS_FAILURE; + pDstReq->ChannelInfo.numOfChannels = 0; + smsLog(pMac, LOGE, FL("No memory for scanning Channel" + " List")); + break; + } + + if((pSrcReq->scanType == eSIR_PASSIVE_SCAN) && (pSrcReq->requestType == eCSR_SCAN_REQUEST_11D_SCAN)) + { + for ( index = 0; index < pSrcReq->ChannelInfo.numOfChannels ; index++ ) + { + NVchannel_state = vos_nv_getChannelEnabledState( + pSrcReq->ChannelInfo.ChannelList[index]); + if (pSrcReq->ChannelInfo.ChannelList[index] < MIN_11P_CHANNEL && + ((NV_CHANNEL_ENABLE == NVchannel_state) || + ((NV_CHANNEL_DFS == NVchannel_state) && + !skip_dfs_chnl))) + { + pDstReq->ChannelInfo.ChannelList[new_index] = + pSrcReq->ChannelInfo.ChannelList[index]; + new_index++; + } + } + pDstReq->ChannelInfo.numOfChannels = new_index; + } + else if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &len))) + { + new_index = 0; + pMac->roam.numValidChannels = len; + for ( index = 0; index < pSrcReq->ChannelInfo.numOfChannels ; index++ ) + { + /* Allow scan on valid channels only. + * If it is p2p scan and valid channel list doesnt contain + * social channels, enforce scan on social channels because + * that is the only way to find p2p peers. + * This can happen only if band is set to 5Ghz mode. + */ + if(pSrcReq->ChannelInfo.ChannelList[index] < MIN_11P_CHANNEL && + ((csrRoamIsValidChannel(pMac, pSrcReq->ChannelInfo.ChannelList[index])) || + ((eCSR_SCAN_P2P_DISCOVERY == pSrcReq->requestType) && + CSR_IS_SOCIAL_CHANNEL(pSrcReq->ChannelInfo.ChannelList[index])))) + { + if( ((pSrcReq->skipDfsChnlInP2pSearch || + skip_dfs_chnl) && + (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(pSrcReq->ChannelInfo.ChannelList[index])) ) +#ifdef FEATURE_WLAN_LFR + /* + * If LFR is requesting a contiguous scan + * (i.e. numOfChannels > 1), then ignore + * DFS channels. + * TODO: vos_nv_getChannelEnabledState is returning + * 120, 124 and 128 as non-DFS channels. Hence, the + * use of direct check for channels below. + */ + || ((eCSR_SCAN_HO_BG_SCAN == pSrcReq->requestType) && + (pSrcReq->ChannelInfo.numOfChannels > 1) && + (CSR_IS_CHANNEL_DFS(pSrcReq->ChannelInfo.ChannelList[index])) && + !pMac->roam.configParam.allowDFSChannelRoam ) +#endif + ) + { +#ifdef FEATURE_WLAN_LFR + smsLog(pMac, LOG2, + FL(" reqType= %s (%d), numOfChannels=%d," + " ignoring DFS channel %d"), + sme_requestTypetoString(pSrcReq->requestType), + pSrcReq->requestType, + pSrcReq->ChannelInfo.numOfChannels, + pSrcReq->ChannelInfo.ChannelList[index]); +#endif + continue; + } + + pDstReq->ChannelInfo.ChannelList[new_index] = + pSrcReq->ChannelInfo.ChannelList[index]; + new_index++; + } + } + pDstReq->ChannelInfo.numOfChannels = new_index; +#ifdef FEATURE_WLAN_LFR + if ((eCSR_SCAN_HO_BG_SCAN == pSrcReq->requestType) && + (0 == pDstReq->ChannelInfo.numOfChannels)) + { + /* + * No valid channels found in the request. + * Only perform scan on the channels passed + * pSrcReq if it is a eCSR_SCAN_HO_BG_SCAN. + * Passing 0 to LIM will trigger a scan on + * all valid channels which is not desirable. + */ + smsLog(pMac, LOGE, FL(" no valid channels found" + " (request=%d)"), pSrcReq->requestType); + for ( index = 0; index < pSrcReq->ChannelInfo.numOfChannels ; index++ ) + { + smsLog(pMac, LOGE, FL("pSrcReq index=%d" + " channel=%d"), index, + pSrcReq->ChannelInfo.ChannelList[index]); + } + status = eHAL_STATUS_FAILURE; + break; + } +#endif + } + else + { + smsLog(pMac, LOGE, FL("Couldn't get the valid Channel" + " List, keeping requester's list")); + new_index = 0; + for ( index = 0; + index < pSrcReq->ChannelInfo.numOfChannels; + index++ ) + { + if (pSrcReq->ChannelInfo.ChannelList[index] < + MIN_11P_CHANNEL) + { + pDstReq->ChannelInfo.ChannelList[new_index] = + pSrcReq->ChannelInfo.ChannelList[index]; + new_index++; + } + } + pDstReq->ChannelInfo.numOfChannels = new_index; + } + }//Allocate memory for Channel List + } + if(pSrcReq->SSIDs.numOfSSIDs == 0) + { + pDstReq->SSIDs.numOfSSIDs = 0; + pDstReq->SSIDs.SSIDList = NULL; + } + else + { + pDstReq->SSIDs.SSIDList = vos_mem_malloc( + pSrcReq->SSIDs.numOfSSIDs * sizeof(*pDstReq->SSIDs.SSIDList)); + if ( NULL == pDstReq->SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (HAL_STATUS_SUCCESS(status)) + { + pDstReq->SSIDs.numOfSSIDs = pSrcReq->SSIDs.numOfSSIDs; + vos_mem_copy(pDstReq->SSIDs.SSIDList, + pSrcReq->SSIDs.SSIDList, + pSrcReq->SSIDs.numOfSSIDs * sizeof(*pDstReq->SSIDs.SSIDList)); + } + else + { + pDstReq->SSIDs.numOfSSIDs = 0; + smsLog(pMac, LOGE, FL("No memory for scanning SSID List")); + break; + } + }//Allocate memory for SSID List + pDstReq->p2pSearch = pSrcReq->p2pSearch; + pDstReq->skipDfsChnlInP2pSearch = pSrcReq->skipDfsChnlInP2pSearch; + + } + }while(0); + + if(!HAL_STATUS_SUCCESS(status)) + { + csrScanFreeRequest(pMac, pDstReq); + } + + return (status); +} + + +eHalStatus csrScanFreeRequest(tpAniSirGlobal pMac, tCsrScanRequest *pReq) +{ + + if(pReq->ChannelInfo.ChannelList) + { + vos_mem_free(pReq->ChannelInfo.ChannelList); + pReq->ChannelInfo.ChannelList = NULL; + } + pReq->ChannelInfo.numOfChannels = 0; + if(pReq->pIEField) + { + vos_mem_free(pReq->pIEField); + pReq->pIEField = NULL; + } + pReq->uIEFieldLen = 0; + if(pReq->SSIDs.SSIDList) + { + vos_mem_free(pReq->SSIDs.SSIDList); + pReq->SSIDs.SSIDList = NULL; + } + pReq->SSIDs.numOfSSIDs = 0; + + return eHAL_STATUS_SUCCESS; +} + + +void csrScanCallCallback(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus) +{ + if(pCommand->u.scanCmd.callback) + { + pCommand->u.scanCmd.callback(pMac, pCommand->u.scanCmd.pContext, + pCommand->sessionId, + pCommand->u.scanCmd.scanID, scanStatus); + } else { + smsLog( pMac, LOG2, "%s:%d - Callback NULL!!!", __func__, __LINE__); + } +} + + +void csrScanStopTimers(tpAniSirGlobal pMac) +{ + csrScanStopIdleScanTimer(pMac); + csrScanStopGetResultTimer(pMac); + if(0 != pMac->scan.scanResultCfgAgingTime ) + { + csrScanStopResultCfgAgingTimer(pMac); + } + +} + + +eHalStatus csrScanStartGetResultTimer(tpAniSirGlobal pMac) +{ + eHalStatus status; + + if(pMac->scan.fScanEnable) + { + status = vos_timer_start(&pMac->scan.hTimerGetResult, CSR_SCAN_GET_RESULT_INTERVAL/VOS_TIMER_TO_MS_UNIT); + } + else + { + status = eHAL_STATUS_FAILURE; + } + + return (status); +} + + +eHalStatus csrScanStopGetResultTimer(tpAniSirGlobal pMac) +{ + return (vos_timer_stop(&pMac->scan.hTimerGetResult)); +} + + +void csrScanGetResultTimerHandler(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + + csrScanRequestResult(pMac); + + vos_timer_start(&pMac->scan.hTimerGetResult, CSR_SCAN_GET_RESULT_INTERVAL/VOS_TIMER_TO_MS_UNIT); +} + +#ifdef WLAN_AP_STA_CONCURRENCY +static void csrStaApConcTimerHandler(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + tListElem *pEntry; + tSmeCmd *pScanCmd; + tANI_U32 sessionId = CSR_SESSION_ID_INVALID; + + csrLLLock(&pMac->scan.scanCmdPendingList); + + if ( NULL != ( pEntry = csrLLPeekHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_NOLOCK) ) ) + { + tCsrScanRequest scanReq; + tSmeCmd *pSendScanCmd = NULL; + tANI_U8 numChn = 0; + tANI_U8 nNumChanCombinedConc = 0; + tANI_U8 i, j; + tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo; + tANI_U8 channelToScan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + eHalStatus status; + + pScanCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + numChn = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + sessionId = pScanCmd->sessionId; + + /* if any session is connected and the number of channels to scan is + * greater than 1 then split the scan into multiple scan operations + * on each individual channel else continue to perform scan on all + * specified channels */ + + /* split scan if number of channels to scan is greater than 1 and + * any one of the following: + * - STA session is connected and the scan is not a P2P search + * - any P2P session is connected + * Do not split scans if no concurrent infra connections are + * active and if the scan is a BG scan triggered by LFR (OR) + * any scan if LFR is in the middle of a BG scan. Splitting + * the scan is delaying the time it takes for LFR to find + * candidates and resulting in disconnects. + */ + + if((csrIsStaSessionConnected(pMac) && + !csrIsP2pSessionConnected(pMac))) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + } + else if(csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; + } + + if ( (numChn > nNumChanCombinedConc) && + ((csrIsStaSessionConnected(pMac) && +#ifdef FEATURE_WLAN_LFR + (csrIsConcurrentInfraConnected(pMac) || + ((pScanCmd->u.scanCmd.reason != eCsrScanBgScan) && + (pMac->roam.neighborRoamInfo[sessionId].neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN))) && +#endif + (pScanCmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) || + (csrIsP2pSessionConnected(pMac)))) + { + vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); + + pSendScanCmd = csrGetCommandBuffer(pMac); //optimize this to use 2 command buffer only + if (!pSendScanCmd) + { + smsLog( pMac, LOGE, FL(" Failed to get Queue command buffer") ); + csrLLUnlock(&pMac->scan.scanCmdPendingList); + return; + } + pSendScanCmd->command = pScanCmd->command; + pSendScanCmd->sessionId = pScanCmd->sessionId; + pSendScanCmd->u.scanCmd.callback = NULL; + pSendScanCmd->u.scanCmd.pContext = pScanCmd->u.scanCmd.pContext; + pSendScanCmd->u.scanCmd.reason = pScanCmd->u.scanCmd.reason; + pSendScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around + + /* First copy all the parameters to local variable of scan request */ + csrScanCopyRequest(pMac, &scanReq, &pScanCmd->u.scanCmd.u.scanRequest); + + /* Now modify the elements of local var scan request required to be modified for split scan */ + if(scanReq.ChannelInfo.ChannelList != NULL) + { + vos_mem_free(scanReq.ChannelInfo.ChannelList); + scanReq.ChannelInfo.ChannelList = NULL; + } + + pChnInfo->numOfChannels = nNumChanCombinedConc; + vos_mem_copy(&channelToScan[0], + &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0], + pChnInfo->numOfChannels * sizeof(tANI_U8));//just send one channel + pChnInfo->ChannelList = &channelToScan[0]; + + for (i = 0, j = nNumChanCombinedConc; i < (numChn-nNumChanCombinedConc); i++, j++) + { + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] = + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[j]; //Move all the channels one step + } + + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn - nNumChanCombinedConc; //reduce outstanding # of channels to be scanned + + scanReq.BSSType = eCSR_BSS_TYPE_ANY; + //Use concurrency values for min/maxChnTime. + csrSetDefaultScanTiming(pMac, scanReq.scanType, &scanReq); + + status = csrScanCopyRequest(pMac, &pSendScanCmd->u.scanCmd.u.scanRequest, &scanReq); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE, FL(" Failed to get copy csrScanRequest = %d"), status ); + csrLLUnlock(&pMac->scan.scanCmdPendingList); + return; + } + /* Clean the local scan variable */ + scanReq.ChannelInfo.ChannelList = NULL; + scanReq.ChannelInfo.numOfChannels = 0; + csrScanFreeRequest(pMac, &scanReq); + } + else + { + /* no active connected session present or numChn == 1 + * scan all remaining channels */ + pSendScanCmd = pScanCmd; + //remove this command from pending list + if (csrLLRemoveHead( &pMac->scan.scanCmdPendingList, LL_ACCESS_NOLOCK) == NULL) + { //In case between PeekHead and here, the entry got removed by another thread. + smsLog( pMac, LOGE, FL(" Failed to remove entry from scanCmdPendingList")); + } + + } + csrQueueSmeCommand(pMac, pSendScanCmd, eANI_BOOLEAN_FALSE); + + } + + csrLLUnlock(&pMac->scan.scanCmdPendingList); + +} +#endif + +eHalStatus csrScanStartResultCfgAgingTimer(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + + if(pMac->scan.fScanEnable) + { + status = vos_timer_start(&pMac->scan.hTimerResultCfgAging, CSR_SCAN_RESULT_CFG_AGING_INTERVAL/VOS_TIMER_TO_MS_UNIT); + } + return (status); +} + +eHalStatus csrScanStopResultCfgAgingTimer(tpAniSirGlobal pMac) +{ + return (vos_timer_stop(&pMac->scan.hTimerResultCfgAging)); +} + + +static void csrScanResultCfgAgingTimerHandler(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + tListElem *pEntry, *tmpEntry; + tCsrScanResult *pResult; + tANI_TIMESTAMP ageOutTime = pMac->scan.scanResultCfgAgingTime * PAL_TICKS_PER_SECOND; + tANI_TIMESTAMP curTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + csrLLLock(&pMac->scan.scanResultList); + pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK ); + while( pEntry ) + { + tmpEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + pResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + if((curTime - pResult->Result.BssDescriptor.nReceivedTime) > ageOutTime) + { + smsLog(pMac, LOGW, " age out due to time out"); + csrScanAgeOutBss(pMac, pResult); + } + pEntry = tmpEntry; + } + csrLLUnlock(&pMac->scan.scanResultList); + if (pEntry) + vos_timer_start(&pMac->scan.hTimerResultCfgAging, + CSR_SCAN_RESULT_CFG_AGING_INTERVAL/VOS_TIMER_TO_MS_UNIT); +} + +eHalStatus csrScanStartIdleScanTimer(tpAniSirGlobal pMac, tANI_U32 interval) +{ + eHalStatus status; + + smsLog(pMac, LOG1, " csrScanStartIdleScanTimer"); + if((pMac->scan.fScanEnable) && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) && interval) + { + pMac->scan.nIdleScanTimeGap += interval; + vos_timer_stop(&pMac->scan.hTimerIdleScan); + status = vos_timer_start(&pMac->scan.hTimerIdleScan, interval/VOS_TIMER_TO_MS_UNIT); + if( !HAL_STATUS_SUCCESS(status) ) + { + smsLog(pMac, LOGE, " Fail to start Idle scan timer. status = %d interval = %d", status, interval); + //This should not happen but set the flag to restart when ready + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + } + } + else + { + if( pMac->scan.fScanEnable && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) ) + { + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + } + status = eHAL_STATUS_FAILURE; + } + + return (status); +} + + +eHalStatus csrScanStopIdleScanTimer(tpAniSirGlobal pMac) +{ + return (vos_timer_stop(&pMac->scan.hTimerIdleScan)); +} + + +//Stop CSR from asking for IMPS, This function doesn't disable IMPS from CSR +void csrScanSuspendIMPS( tpAniSirGlobal pMac ) +{ + csrScanCancelIdleScan(pMac); +} + + +//Start CSR from asking for IMPS. This function doesn't trigger CSR to request entering IMPS +//because IMPS maybe disabled. +void csrScanResumeIMPS( tpAniSirGlobal pMac ) +{ + csrScanStartIdleScan( pMac ); +} + + +void csrScanIMPSCallback(void *callbackContext, eHalStatus status) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( callbackContext ); + + if(eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) + { + if(pMac->roam.configParam.IsIdleScanEnabled) + { + if(HAL_STATUS_SUCCESS(status)) + { + if(csrIsAllSessionDisconnected(pMac) && !csrIsRoamCommandWaiting(pMac)) + { + smsLog(pMac, LOGW, FL("starts idle mode full scan")); + csrScanAllChannels(pMac, eCSR_SCAN_IDLE_MODE_SCAN); + } + else + { + smsLog(pMac, LOGW, FL("cannot start idle mode full scan")); + //even though we are in timer handle, calling stop timer will make sure the timer + //doesn't get to restart. + csrScanStopIdleScanTimer(pMac); + } + } + else + { + smsLog(pMac, LOGE, FL("sees not success status (%d)"), status); + } + } + else + {//we might need another flag to check if CSR needs to request imps at all + + tANI_U32 nTime = 0; + + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE; + if(!HAL_STATUS_SUCCESS(csrScanTriggerIdleScan(pMac, &nTime))) + { + csrScanStartIdleScanTimer(pMac, nTime); + } + } + } +} + + +/* + * Param: pTimeInterval -- Caller allocated memory in return, if failed, + * to specify the next time interval for idle scan timer interval + * Return: Not success -- meaning it cannot start IMPS, caller needs to + * start a timer for idle scan + */ +eHalStatus csrScanTriggerIdleScan(tpAniSirGlobal pMac, tANI_U32 *pTimeInterval) +{ + eHalStatus status = eHAL_STATUS_CSR_WRONG_STATE; + + //Do not trigger IMPS in case of concurrency + if (vos_concurrent_open_sessions_running() && + csrIsAnySessionInConnectState(pMac)) + { + smsLog( pMac, LOG1, FL("Cannot request IMPS because Concurrent Sessions Running") ); + return (status); + } + + if(pTimeInterval) + { + *pTimeInterval = 0; + } + + smsLog(pMac, LOG3, FL("called")); + if( smeCommandPending( pMac ) ) + { + smsLog( pMac, LOG1, FL(" Cannot request IMPS because command pending") ); + //Not to enter IMPS because more work to do + if(pTimeInterval) + { + *pTimeInterval = 0; + } + //restart when ready + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + + return (status); + } + if (IsPmcImpsReqFailed (pMac)) + { + if(pTimeInterval) + { + *pTimeInterval = 1000000; //usec + } + //restart when ready + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + + return status; + } + if((pMac->scan.fScanEnable) && + (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)) { + //Stop get result timer because idle scan gets scan result out of PE + csrScanStopGetResultTimer(pMac); + if(pTimeInterval) + { + *pTimeInterval = pMac->roam.configParam.impsSleepTime; + } + //pmcRequestImps take a period in millisecond unit. + status = pmcRequestImps(pMac, + pMac->roam.configParam.impsSleepTime / VOS_TIMER_TO_MS_UNIT, + csrScanIMPSCallback, pMac); + if(!HAL_STATUS_SUCCESS(status)) + { + if(eHAL_STATUS_PMC_ALREADY_IN_IMPS != status) + { + //Do restart the timer if CSR thinks it cannot do IMPS + if( !csrCheckPSReady( pMac ) ) + { + if(pTimeInterval) + { + *pTimeInterval = 0; + } + //Set the restart flag to true because that idle scan + //can be restarted even though the timer will not be running + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + } + else + { + //For not now, we do a quicker retry + if(pTimeInterval) + { + *pTimeInterval = CSR_IDLE_SCAN_WAIT_TIME; + } + } + smsLog(pMac, LOGW, FL("call pmcRequestImps and it returns status code (%d)"), status); + } + else + { + smsLog(pMac, LOGW, FL("already in IMPS")); + //Since CSR is the only module to request for IMPS. If it is already in IMPS, CSR assumes + //the callback will be called in the future. Should not happen though. + status = eHAL_STATUS_SUCCESS; + pMac->scan.nIdleScanTimeGap = 0; + } + } + else + { + //requested so let's reset the value + pMac->scan.nIdleScanTimeGap = 0; + } + } + + return (status); +} + + +eHalStatus csrScanStartIdleScan(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_CSR_WRONG_STATE; + tANI_U32 nTime = 0; + + smsLog(pMac, LOGW, FL("called")); + /* + * Idle Scan not supported with Power Save Offload + * Enabled + */ + if(pMac->psOffloadEnabled) + { + return eHAL_STATUS_SUCCESS; + } + + if(pMac->roam.configParam.IsIdleScanEnabled) + { + //stop bg scan first + csrScanBGScanAbort(pMac); + //Stop get result timer because idle scan gets scan result out of PE + csrScanStopGetResultTimer(pMac); + } + pMac->scan.fCancelIdleScan = eANI_BOOLEAN_FALSE; + status = csrScanTriggerIdleScan(pMac, &nTime); + if(!HAL_STATUS_SUCCESS(status)) + { + csrScanStartIdleScanTimer(pMac, nTime); + } + + return (status); +} + + +void csrScanCancelIdleScan(tpAniSirGlobal pMac) +{ + /* + * Idle Scan not supported with Power Save Offload + * Enabled + */ + if(pMac->psOffloadEnabled) + { + return; + } + + if(eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) + { + if (vos_concurrent_open_sessions_running()) { + return; + } + smsLog(pMac, LOG1, " csrScanCancelIdleScan"); + pMac->scan.fCancelIdleScan = eANI_BOOLEAN_TRUE; + /* Set the restart flag in case later on it is uncanceled */ + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + csrScanStopIdleScanTimer(pMac); + csrScanRemoveNotRoamingScanCommand(pMac); + } +} + + +void csrScanIdleScanTimerHandler(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + eHalStatus status; + tANI_U32 nTime = 0; + + smsLog(pMac, LOGW, " csrScanIdleScanTimerHandler called "); + pmcResetImpsFailStatus (pMac); + status = csrScanTriggerIdleScan(pMac, &nTime); + if(!HAL_STATUS_SUCCESS(status) && (eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)) + { + //Check whether it is time to actually do an idle scan + if(pMac->scan.nIdleScanTimeGap >= pMac->roam.configParam.impsSleepTime) + { + pMac->scan.nIdleScanTimeGap = 0; + csrScanIMPSCallback(pMac, eHAL_STATUS_SUCCESS); + } + else + { + csrScanStartIdleScanTimer(pMac, nTime); + } + } +} + + + + +tANI_BOOLEAN csrScanRemoveNotRoamingScanCommand(tpAniSirGlobal pMac) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tListElem *pEntry, *pEntryTmp; + tSmeCmd *pCommand; + tDblLinkList localList; + tDblLinkList *pCmdList; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return fRet; + } + if (!pMac->fScanOffload) + pCmdList = &pMac->sme.smeCmdPendingList; + else + pCmdList = &pMac->sme.smeScanCmdPendingList; + + csrLLLock(pCmdList); + pEntry = csrLLPeekHead(pCmdList, LL_ACCESS_NOLOCK); + while(pEntry) + { + pEntryTmp = csrLLNext(pCmdList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( eSmeCommandScan == pCommand->command ) + { + switch( pCommand->u.scanCmd.reason ) + { + case eCsrScanIdleScan: + if( csrLLRemoveEntry(pCmdList, pEntry, LL_ACCESS_NOLOCK) ) + { + csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK); + } + fRet = eANI_BOOLEAN_TRUE; + break; + + default: + break; + } //switch + } + pEntry = pEntryTmp; + } + + csrLLUnlock(pCmdList); + + while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + csrReleaseCommandScan( pMac, pCommand ); + } + + csrLLClose(&localList); + + return (fRet); +} + + +tANI_BOOLEAN csrScanRemoveFreshScanCommand(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tListElem *pEntry, *pEntryTmp; + tSmeCmd *pCommand; + tDblLinkList localList; + tDblLinkList *pCmdList; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return fRet; + } + + if (!pMac->fScanOffload) + pCmdList = &pMac->sme.smeCmdPendingList; + else + pCmdList = &pMac->sme.smeScanCmdPendingList; + + csrLLLock(pCmdList); + pEntry = csrLLPeekHead(pCmdList, LL_ACCESS_NOLOCK); + while(pEntry) + { + pEntryTmp = csrLLNext(pCmdList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( (eSmeCommandScan == pCommand->command) && (sessionId == pCommand->sessionId) ) + { + switch(pCommand->u.scanCmd.reason) + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif + case eCsrScanGetResult: + case eCsrScanSetBGScanParam: + case eCsrScanBGScanAbort: + case eCsrScanBGScanEnable: + case eCsrScanGetScanChnInfo: + break; + default: + smsLog (pMac, LOGW, "%s: -------- abort scan command reason = %d", + __func__, pCommand->u.scanCmd.reason); + //The rest are fresh scan requests + if( csrLLRemoveEntry(pCmdList, pEntry, LL_ACCESS_NOLOCK) ) + { + csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK); + } + fRet = eANI_BOOLEAN_TRUE; + break; + } + } + pEntry = pEntryTmp; + } + + csrLLUnlock(pCmdList); + + while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (pCommand->u.scanCmd.callback) + { + /* User scan request is pending, + * send response with status eCSR_SCAN_ABORT*/ + pCommand->u.scanCmd.callback(pMac, + pCommand->u.scanCmd.pContext, + sessionId, + pCommand->u.scanCmd.scanID, + eCSR_SCAN_ABORT); + } + csrReleaseCommandScan( pMac, pCommand ); + } + csrLLClose(&localList); + + return (fRet); +} + + +void csrReleaseScanCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus) +{ + eCsrScanReason reason = pCommand->u.scanCmd.reason; + tANI_BOOLEAN status; + + if (!pMac->fScanOffload) + { + tANI_U32 i; + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + csrRoamStateChange(pMac, pCommand->u.scanCmd.lastRoamState[i], i); + } + else + { + csrRoamStateChange(pMac, + pCommand->u.scanCmd.lastRoamState[pCommand->sessionId], + pCommand->sessionId); + } + + csrScanCallCallback(pMac, pCommand, scanStatus); + + smsLog(pMac, LOG3, " Remove Scan command reason = %d", reason); + if (pMac->fScanOffload) + { + status = csrLLRemoveEntry(&pMac->sme.smeScanCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK); + } + else + { + status = csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK); + } + + if(status) + { + csrReleaseCommandScan( pMac, pCommand ); + } + else + { + smsLog(pMac, LOGE, + " ********csrReleaseScanCommand cannot release command reason %d", + pCommand->u.scanCmd.reason ); + } +} + + +eHalStatus csrScanGetPMKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId, + tPmkidCandidateInfo *pPmkidList, tANI_U32 *pNumItems ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, " pMac->scan.NumPmkidCandidate = %d", pSession->NumPmkidCandidate); + csrResetPMKIDCandidateList(pMac, sessionId); + if(csrIsConnStateConnected(pMac, sessionId) && pSession->pCurRoamProfile) + { + tCsrScanResultFilter *pScanFilter; + tCsrScanResultInfo *pScanResult; + tScanResultHandle hBSSList; + tANI_U32 nItems = *pNumItems; + + *pNumItems = 0; + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + //Here is the profile we need to connect to + status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(HAL_STATUS_SUCCESS(status)) + { + while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && ( pSession->NumPmkidCandidate < nItems)) + { + //NumPmkidCandidate adds up here + csrProcessBSSDescForPMKIDList(pMac, + &pScanResult->BssDescriptor, + (tDot11fBeaconIEs *)(pScanResult->pvIes), + sessionId); + } + if(pSession->NumPmkidCandidate) + { + *pNumItems = pSession->NumPmkidCandidate; + vos_mem_copy(pPmkidList, pSession->PmkidCandidateInfo, + pSession->NumPmkidCandidate * sizeof(tPmkidCandidateInfo)); + } + csrScanResultPurge(pMac, hBSSList); + }//Have scan result + csrFreeScanFilter(pMac, pScanFilter); + } + vos_mem_free(pScanFilter); + } + } + + return (status); +} + + + +#ifdef FEATURE_WLAN_WAPI +eHalStatus csrScanGetBKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId, + tBkidCandidateInfo *pBkidList, tANI_U32 *pNumItems ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOGW, " pMac->scan.NumBkidCandidate = %d", pSession->NumBkidCandidate); + csrResetBKIDCandidateList(pMac, sessionId); + if(csrIsConnStateConnected(pMac, sessionId) && pSession->pCurRoamProfile) + { + tCsrScanResultFilter *pScanFilter; + tCsrScanResultInfo *pScanResult; + tScanResultHandle hBSSList; + tANI_U32 nItems = *pNumItems; + *pNumItems = 0; + pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if ( NULL == pScanFilter ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + //Here is the profile we need to connect to + status = csrRoamPrepareFilterFromProfile(pMac, pSession->pCurRoamProfile, pScanFilter); + if(HAL_STATUS_SUCCESS(status)) + { + status = csrScanGetResult(pMac, pScanFilter, &hBSSList); + if(HAL_STATUS_SUCCESS(status)) + { + while(((pScanResult = csrScanResultGetNext(pMac, hBSSList)) != NULL) && ( pSession->NumBkidCandidate < nItems)) + { + //pMac->scan.NumBkidCandidate adds up here + csrProcessBSSDescForBKIDList(pMac, &pScanResult->BssDescriptor, + (tDot11fBeaconIEs *)( pScanResult->pvIes )); + + } + if(pSession->NumBkidCandidate) + { + *pNumItems = pSession->NumBkidCandidate; + vos_mem_copy(pBkidList, pSession->BkidCandidateInfo, pSession->NumBkidCandidate * sizeof(tBkidCandidateInfo)); + } + csrScanResultPurge(pMac, hBSSList); + }//Have scan result + } + vos_mem_free(pScanFilter); + } + } + + return (status); +} +#endif /* FEATURE_WLAN_WAPI */ + + + +//This function is usually used for BSSs that suppresses SSID so the profile +//shall have one and only one SSID +eHalStatus csrScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tANI_U32 roamId, tANI_BOOLEAN notify) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tSmeCmd *pScanCmd = NULL; + tANI_U8 bAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tANI_U8 index = 0; + tANI_U32 numSsid = pProfile->SSIDs.numOfSSIDs; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + smsLog(pMac, LOG2, FL("called")); + //For WDS, we use the index 0. There must be at least one in there + if( CSR_IS_WDS_STA( pProfile ) && numSsid ) + { + numSsid = 1; + } + if(pMac->scan.fScanEnable && ( numSsid == 1 ) ) + { + do + { + pScanCmd = csrGetCommandBuffer(pMac); + if(!pScanCmd) + { + smsLog(pMac, LOGE, FL("failed to allocate command buffer")); + break; + } + vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + pScanCmd->u.scanCmd.pToRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( NULL == pScanCmd->u.scanCmd.pToRoamProfile ) + { + status = eHAL_STATUS_FAILURE; + } + else + { + status = csrRoamCopyProfile(pMac, pScanCmd->u.scanCmd.pToRoamProfile, pProfile); + } + if(!HAL_STATUS_SUCCESS(status)) + break; + pScanCmd->u.scanCmd.roamId = roamId; + pScanCmd->command = eSmeCommandScan; + pScanCmd->sessionId = (tANI_U8)sessionId; + pScanCmd->u.scanCmd.callback = NULL; + pScanCmd->u.scanCmd.pContext = NULL; + pScanCmd->u.scanCmd.reason = eCsrScanForSsid;//Need to check: might need a new reason for SSID scan for LFR during multisession with p2p + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around + vos_mem_set(&pScanCmd->u.scanCmd.u.scanRequest, sizeof(tCsrScanRequest), 0); + pScanCmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + pScanCmd->u.scanCmd.u.scanRequest.BSSType = pProfile->BSSType; + // To avoid 11b rate in probe request Set p2pSearch flag as 1 for P2P Client Mode + if(VOS_P2P_CLIENT_MODE == pProfile->csrPersona) + { + pScanCmd->u.scanCmd.u.scanRequest.p2pSearch = 1; + } + if(pProfile->pAddIEScan) + { + pScanCmd->u.scanCmd.u.scanRequest.pIEField = vos_mem_malloc( + pProfile->nAddIEScanLength); + if ( NULL == pScanCmd->u.scanCmd.u.scanRequest.pIEField ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + vos_mem_set(pScanCmd->u.scanCmd.u.scanRequest.pIEField, + pProfile->nAddIEScanLength, 0); + if (HAL_STATUS_SUCCESS(status)) + { + vos_mem_copy(pScanCmd->u.scanCmd.u.scanRequest.pIEField, + pProfile->pAddIEScan, pProfile->nAddIEScanLength); + pScanCmd->u.scanCmd.u.scanRequest.uIEFieldLen = pProfile->nAddIEScanLength; + } + else + { + smsLog(pMac, LOGE, "No memory for scanning IE fields"); + } + } //Allocate memory for IE field + else + { + pScanCmd->u.scanCmd.u.scanRequest.uIEFieldLen = 0; + } + /* For one channel be good enough time to receive beacon at-least */ + if( 1 == pProfile->ChannelInfo.numOfChannels ) + { +#if defined (WLAN_FEATURE_ROAM_SCAN_OFFLOAD) + if (pNeighborRoamInfo->handoffReqInfo.src == FASTREASSOC) { + pScanCmd->u.scanCmd.u.scanRequest.maxChnTime = + MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC; + pScanCmd->u.scanCmd.u.scanRequest.minChnTime = + MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC; + /* Reset this value */ + pNeighborRoamInfo->handoffReqInfo.src = 0; + } + else +#endif + { + pScanCmd->u.scanCmd.u.scanRequest.maxChnTime = MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL; + pScanCmd->u.scanCmd.u.scanRequest.minChnTime = MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL; + } + } + else + { + pScanCmd->u.scanCmd.u.scanRequest.maxChnTime = + pMac->roam.configParam.nActiveMaxChnTime; + pScanCmd->u.scanCmd.u.scanRequest.minChnTime = + pMac->roam.configParam.nActiveMinChnTime; + } + pScanCmd->u.scanCmd.u.scanRequest.maxChnTimeBtc = + pMac->roam.configParam.nActiveMaxChnTimeBtc; + pScanCmd->u.scanCmd.u.scanRequest.minChnTimeBtc = + pMac->roam.configParam.nActiveMinChnTimeBtc; + if(pProfile->BSSIDs.numOfBSSIDs == 1) + { + vos_mem_copy(pScanCmd->u.scanCmd.u.scanRequest.bssid, + pProfile->BSSIDs.bssid, sizeof(tCsrBssid)); + } + else + { + vos_mem_copy(pScanCmd->u.scanCmd.u.scanRequest.bssid, bAddr, 6); + } + if(pProfile->ChannelInfo.numOfChannels) + { + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = vos_mem_malloc( + sizeof(*pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) + * pProfile->ChannelInfo.numOfChannels); + if ( NULL == pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 0; + if(HAL_STATUS_SUCCESS(status)) + { + csrRoamIsChannelValid(pMac, pProfile->ChannelInfo.ChannelList[0]); + for(index = 0; index < pProfile->ChannelInfo.numOfChannels; index++) + { + if(csrRoamIsValidChannel(pMac, pProfile->ChannelInfo.ChannelList[index])) + { + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels] + = pProfile->ChannelInfo.ChannelList[index]; + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels++; + } + else + { + smsLog(pMac, LOGW, FL("process a channel (%d) that is invalid"), pProfile->ChannelInfo.ChannelList[index]); + } + + } + } + else + { + break; + } + + } + else + { + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = 0; + } + if(pProfile->SSIDs.numOfSSIDs) + { + pScanCmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList = vos_mem_malloc( + pProfile->SSIDs.numOfSSIDs * sizeof(tCsrSSIDInfo)); + if ( NULL == pScanCmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) + { + break; + } + pScanCmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = 1; + vos_mem_copy(pScanCmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList, + pProfile->SSIDs.SSIDList, sizeof(tCsrSSIDInfo)); + } + //Start process the command + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + }while(0); + if(!HAL_STATUS_SUCCESS(status)) + { + if(pScanCmd) + { + csrReleaseCommandScan(pMac, pScanCmd); + //TODO:free the memory that is allocated in this function + } + if(notify) + { + csrRoamCallCallback(pMac, sessionId, NULL, roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE); + } + } + }//valid + else + { + smsLog(pMac, LOGE, FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid"), + pMac->scan.fScanEnable, pProfile->SSIDs.numOfSSIDs); + } + + return (status); +} + + +/* + * Issue a scan based on the new capability information + * This should only happen when the associated AP changes its capability. + * After this scan is done, CSR re-roams based on the new scan results + */ +eHalStatus csrScanForCapabilityChange(tpAniSirGlobal pMac, tSirSmeApNewCaps *pNewCaps) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tSmeCmd *pScanCmd = NULL; + + if(pNewCaps) + { + do + { + pScanCmd = csrGetCommandBuffer(pMac); + if(!pScanCmd) + { + smsLog(pMac, LOGE, FL("failed to allocate command buffer")); + status = eHAL_STATUS_RESOURCES; + break; + } + vos_mem_set(&pScanCmd->u.scanCmd, sizeof(tScanCmd), 0); + status = eHAL_STATUS_SUCCESS; + pScanCmd->u.scanCmd.roamId = 0; + pScanCmd->command = eSmeCommandScan; + pScanCmd->u.scanCmd.callback = NULL; + pScanCmd->u.scanCmd.pContext = NULL; + pScanCmd->u.scanCmd.reason = eCsrScanForCapsChange; + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID++; //let it wrap around + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_FALSE); + if( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status ); + break; + } + }while(0); + if(!HAL_STATUS_SUCCESS(status)) + { + if(pScanCmd) + { + csrReleaseCommandScan(pMac, pScanCmd); + } + } + } + + return (status); +} + + + +void csrInitBGScanChannelList(tpAniSirGlobal pMac) +{ + tANI_U32 len = CSR_MIN(sizeof(pMac->roam.validChannelList), sizeof(pMac->scan.bgScanChannelList)); + + vos_mem_set(pMac->scan.bgScanChannelList, len, 0); + pMac->scan.numBGScanChannel = 0; + + if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &len))) + { + pMac->roam.numValidChannels = len; + pMac->scan.numBGScanChannel = (tANI_U8)CSR_MIN(len, WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN); + vos_mem_copy(pMac->scan.bgScanChannelList, pMac->roam.validChannelList, + pMac->scan.numBGScanChannel); + csrSetBGScanChannelList(pMac, pMac->scan.bgScanChannelList, pMac->scan.numBGScanChannel); + } +} + + +//This function return TRUE if background scan channel list is adjusted. +//this function will only shrink the background scan channel list +tANI_BOOLEAN csrAdjustBGScanChannelList(tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels, + tANI_U8 *pAdjustChannels, tANI_U8 *pNumAdjustChannels) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; + tANI_U8 i, j, count = *pNumAdjustChannels; + + i = 0; + while(i < count) + { + for(j = 0; j < NumChannels; j++) + { + if(pChannelList[j] == pAdjustChannels[i]) + break; + } + if(j == NumChannels) + { + //This channel is not in the list, remove it + fRet = eANI_BOOLEAN_TRUE; + count--; + if(count - i) + { + vos_mem_copy(&pAdjustChannels[i], &pAdjustChannels[i+1], count - i); + } + else + { + //already remove the last one. Done. + break; + } + } + else + { + i++; + } + }//while(iscan.baseChannels.channelList, &n, NULL, NULL ); + if( HAL_STATUS_SUCCESS(status) ) + { + pMac->scan.baseChannels.numChannels = (tANI_U8)n; + } + else + { + smsLog( pMac, LOGE, FL(" failed") ); + pMac->scan.baseChannels.numChannels = 0; + } + + return ( status ); +} + +//This function use the input pChannelList to validate the current saved channel list +eHalStatus csrSetBGScanChannelList( tpAniSirGlobal pMac, tANI_U8 *pAdjustChannels, tANI_U8 NumAdjustChannels) +{ + tANI_U32 dataLen = sizeof( tANI_U8 ) * NumAdjustChannels; + + return (ccmCfgSetStr(pMac, WNI_CFG_BG_SCAN_CHANNEL_LIST, pAdjustChannels, dataLen, NULL, eANI_BOOLEAN_FALSE)); +} + + +void csrSetCfgValidChannelList( tpAniSirGlobal pMac, tANI_U8 *pChannelList, tANI_U8 NumChannels ) +{ + tANI_U32 dataLen = sizeof( tANI_U8 ) * NumChannels; + eHalStatus status; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: dump valid channel list(NumChannels(%d))", + __func__,NumChannels); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + pChannelList, NumChannels); + ccmCfgSetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, pChannelList, dataLen, NULL, eANI_BOOLEAN_FALSE); + + if (pMac->fScanOffload) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Scan offload is enabled, update default chan list"); + /* + * disable fcc constraint since new country code + * is being set + */ + pMac->scan.fcc_constraint = false; + status = csrUpdateChannelList(pMac); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "failed to update the supported channel list"); + } + } + return; +} + + + +/* + * The Tx power limits are saved in the cfg for future usage. + */ +void csrSaveTxPowerToCfg( tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 cfgId ) +{ + tListElem *pEntry; + tANI_U32 cbLen = 0, dataLen; + tCsrChannelPowerInfo *pChannelSet; + tANI_U32 idx; + tSirMacChanInfo *pChannelPowerSet; + tANI_U8 *pBuf = NULL; + + //allocate maximum space for all channels + dataLen = WNI_CFG_VALID_CHANNEL_LIST_LEN * sizeof(tSirMacChanInfo); + if ( (pBuf = vos_mem_malloc(dataLen)) != NULL ) + { + vos_mem_set(pBuf, dataLen, 0); + pChannelPowerSet = (tSirMacChanInfo *)(pBuf); + + pEntry = csrLLPeekHead( pList, LL_ACCESS_LOCK ); + // write the tuples (startChan, numChan, txPower) for each channel found in the channel power list. + while( pEntry ) + { + pChannelSet = GET_BASE_ADDR( pEntry, tCsrChannelPowerInfo, link ); + if ( 1 != pChannelSet->interChannelOffset ) + { + /* + * we keep the 5G channel sets internally with an inter channel + * offset of 4. Expand these to the right format. + * (inter channel offset of 1 is the only option for the + * triplets that 11d advertises. + */ + if ((cbLen + (pChannelSet->numChannels * sizeof(tSirMacChanInfo))) >= dataLen) + { + // expanding this entry will overflow our allocation + smsLog(pMac, LOGE, + "%s: Buffer overflow, start %d, num %d, offset %d", + __func__, + pChannelSet->firstChannel, + pChannelSet->numChannels, + pChannelSet->interChannelOffset); + break; + } + + for( idx = 0; idx < pChannelSet->numChannels; idx++ ) + { + pChannelPowerSet->firstChanNum = (tSirMacChanNum)(pChannelSet->firstChannel + ( idx * pChannelSet->interChannelOffset )); + smsLog(pMac, LOG3, " Setting Channel Number %d", pChannelPowerSet->firstChanNum); + pChannelPowerSet->numChannels = 1; + pChannelPowerSet->maxTxPower = CSR_ROAM_MIN( pChannelSet->txPower, pMac->roam.configParam.nTxPowerCap ); + smsLog(pMac, LOG3, " Setting Max Transmit Power %d", pChannelPowerSet->maxTxPower); + cbLen += sizeof( tSirMacChanInfo ); + pChannelPowerSet++; + } + } + else + { + if (cbLen >= dataLen) + { + // this entry will overflow our allocation + smsLog(pMac, LOGE, + "%s: Buffer overflow, start %d, num %d, offset %d", + __func__, + pChannelSet->firstChannel, + pChannelSet->numChannels, + pChannelSet->interChannelOffset); + break; + } + pChannelPowerSet->firstChanNum = pChannelSet->firstChannel; + smsLog(pMac, LOG3, " Setting Channel Number %d", pChannelPowerSet->firstChanNum); + pChannelPowerSet->numChannels = pChannelSet->numChannels; + pChannelPowerSet->maxTxPower = CSR_ROAM_MIN( pChannelSet->txPower, pMac->roam.configParam.nTxPowerCap ); + smsLog(pMac, LOG3, " Setting Max Transmit Power %d, nTxPower %d", pChannelPowerSet->maxTxPower,pMac->roam.configParam.nTxPowerCap ); + + + cbLen += sizeof( tSirMacChanInfo ); + pChannelPowerSet++; + } + + pEntry = csrLLNext( pList, pEntry, LL_ACCESS_LOCK ); + } + + if(cbLen) + { + ccmCfgSetStr(pMac, cfgId, (tANI_U8 *)pBuf, cbLen, NULL, eANI_BOOLEAN_FALSE); + } + vos_mem_free(pBuf); + }//Allocate memory +} + + +void csrSetCfgCountryCode( tpAniSirGlobal pMac, tANI_U8 *countryCode ) +{ + tANI_U8 cc[WNI_CFG_COUNTRY_CODE_LEN]; + ///v_REGDOMAIN_t DomainId; + + smsLog( pMac, LOG3, "Setting Country Code in Cfg from csrSetCfgCountryCode %s",countryCode ); + vos_mem_copy(cc, countryCode, WNI_CFG_COUNTRY_CODE_LEN); + + // don't program the bogus country codes that we created for Korea in the MAC. if we see + // the bogus country codes, program the MAC with the right country code. + if ( ( 'K' == countryCode[ 0 ] && '1' == countryCode[ 1 ] ) || + ( 'K' == countryCode[ 0 ] && '2' == countryCode[ 1 ] ) || + ( 'K' == countryCode[ 0 ] && '3' == countryCode[ 1 ] ) || + ( 'K' == countryCode[ 0 ] && '4' == countryCode[ 1 ] ) ) + { + // replace the alternate Korea country codes, 'K1', 'K2', .. with 'KR' for Korea + cc[ 1 ] = 'R'; + } + ccmCfgSetStr(pMac, WNI_CFG_COUNTRY_CODE, cc, WNI_CFG_COUNTRY_CODE_LEN, NULL, eANI_BOOLEAN_FALSE); + + //Need to let HALPHY know about the current domain so it can apply some + //domain-specific settings (TX filter...) + /*if(HAL_STATUS_SUCCESS(csrGetRegulatoryDomainForCountry(pMac, cc, &DomainId))) + { + halPhySetRegDomain(pMac, DomainId); + }*/ +} + + + +eHalStatus csrGetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *pbLen) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tANI_U32 len; + + if(pBuf && pbLen && (*pbLen >= WNI_CFG_COUNTRY_CODE_LEN)) + { + len = *pbLen; + status = ccmCfgGetStr(pMac, WNI_CFG_COUNTRY_CODE, pBuf, &len); + if(HAL_STATUS_SUCCESS(status)) + { + *pbLen = (tANI_U8)len; + } + } + + return (status); +} + + +void csrSetCfgScanControlList( tpAniSirGlobal pMac, tANI_U8 *countryCode, tCsrChannel *pChannelList ) +{ + tANI_U8 i, j; + tANI_BOOLEAN found=FALSE; + tANI_U8 *pControlList = NULL; + tANI_U32 len = WNI_CFG_SCAN_CONTROL_LIST_LEN; + + if ( (pControlList = vos_mem_malloc(WNI_CFG_SCAN_CONTROL_LIST_LEN)) != NULL ) + { + vos_mem_set((void *)pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN, 0); + if(HAL_STATUS_SUCCESS(ccmCfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, pControlList, &len))) + { + for (i = 0; i < pChannelList->numChannels; i++) + { + for (j = 0; j < len; j += 2) + { + if (pControlList[j] == pChannelList->channelList[i]) + { + found = TRUE; + break; + } + } + + if (found) // insert a pair(channel#, flag) + { + pControlList[j+1] = csrGetScanType(pMac, pControlList[j]); + found = FALSE; // reset the flag + } + + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: dump scan control list",__func__); + VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + pControlList, len); + + ccmCfgSetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, pControlList, len, NULL, eANI_BOOLEAN_FALSE); + }//Successfully getting scan control list + vos_mem_free(pControlList); + }//AllocateMemory +} + + +//if bgPeriod is 0, background scan is disabled. It is in millisecond units +eHalStatus csrSetCfgBackgroundScanPeriod(tpAniSirGlobal pMac, tANI_U32 bgPeriod) +{ + return (ccmCfgSetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, bgPeriod, (tCcmCfgSetCallback) csrScanCcmCfgSetCallback, eANI_BOOLEAN_FALSE)); +} + + +void csrScanCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result) +{ + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tDblLinkList *pCmdList ; + + if (!pMac->fScanOffload) + pCmdList = &pMac->sme.smeCmdActiveList; + else + pCmdList = &pMac->sme.smeScanCmdActiveList; + + pEntry = csrLLPeekHead( pCmdList, LL_ACCESS_LOCK ); + if ( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if ( eSmeCommandScan == pCommand->command ) + { + eCsrScanStatus scanStatus = (CCM_IS_RESULT_SUCCESS(result)) ? eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE; + csrReleaseScanCommand(pMac, pCommand, scanStatus); + } + else + { + smsLog( pMac, LOGW, "CSR: Scan Completion called but SCAN command is not ACTIVE ..." ); + } + } + smeProcessPendingQueue( pMac ); +} + +eHalStatus csrProcessSetBGScanParam(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + eHalStatus status; + tCsrBGScanRequest *pScanReq = &pCommand->u.scanCmd.u.bgScanRequest; + tANI_U32 dataLen = sizeof( tANI_U8 ) * pScanReq->ChannelInfo.numOfChannels; + + //***setcfg for background scan channel list + status = ccmCfgSetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, pScanReq->minChnTime, NULL, eANI_BOOLEAN_FALSE); + status = ccmCfgSetInt(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, pScanReq->maxChnTime, NULL, eANI_BOOLEAN_FALSE); + //Not set the background scan interval if not connected because bd scan should not be run if not connected + if(!csrIsAllSessionDisconnected(pMac)) + { +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + vos_log_scan_pkt_type *pScanLog = NULL; + + WLAN_VOS_DIAG_LOG_ALLOC(pScanLog, vos_log_scan_pkt_type, LOG_WLAN_SCAN_C); + if(pScanLog) + { + pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ; + pScanLog->minChnTime = (v_U8_t)pScanReq->minChnTime; + pScanLog->maxChnTime = (v_U8_t)pScanReq->maxChnTime; + pScanLog->timeBetweenBgScan = (v_U8_t)pScanReq->scanInterval; + pScanLog->numChannel = pScanReq->ChannelInfo.numOfChannels; + if(pScanLog->numChannel && (pScanLog->numChannel < VOS_LOG_MAX_NUM_CHANNEL)) + { + vos_mem_copy(pScanLog->channels, + pScanReq->ChannelInfo.ChannelList, + pScanLog->numChannel); + } + WLAN_VOS_DIAG_LOG_REPORT(pScanLog); + } + } +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + + status = ccmCfgSetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, pScanReq->scanInterval, NULL, eANI_BOOLEAN_FALSE); + } + else + { + //No need to stop aging because IDLE scan is still running + status = ccmCfgSetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, 0, NULL, eANI_BOOLEAN_FALSE); + } + + if(pScanReq->SSID.length > WNI_CFG_SSID_LEN) + { + pScanReq->SSID.length = WNI_CFG_SSID_LEN; + } + + status = ccmCfgSetStr(pMac, WNI_CFG_BG_SCAN_CHANNEL_LIST, pScanReq->ChannelInfo.ChannelList, dataLen, NULL, eANI_BOOLEAN_FALSE); + status = ccmCfgSetStr(pMac, WNI_CFG_SSID, (tANI_U8 *)pScanReq->SSID.ssId, pScanReq->SSID.length, NULL, eANI_BOOLEAN_FALSE); + + + + return (status); +} + + +eHalStatus csrScanAbortMacScan(tpAniSirGlobal pMac, tANI_U8 sessionId, + eCsrAbortReason reason) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tSirSmeScanAbortReq *pMsg; + tANI_U16 msgLen; + tListElem *pEntry; + tSmeCmd *pCommand; + + if (!pMac->fScanOffload) + { +#ifdef WLAN_AP_STA_CONCURRENCY + csrLLLock(&pMac->scan.scanCmdPendingList); + while(NULL != + (pEntry = csrLLRemoveHead(&pMac->scan.scanCmdPendingList, + LL_ACCESS_NOLOCK))) + { + + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE); + } + csrLLUnlock(&pMac->scan.scanCmdPendingList); +#endif + + pMac->scan.fDropScanCmd = eANI_BOOLEAN_TRUE; + csrRemoveCmdFromPendingList( pMac, &pMac->roam.roamCmdPendingList, eSmeCommandScan); + csrRemoveCmdFromPendingList( pMac, &pMac->sme.smeCmdPendingList, eSmeCommandScan); + pMac->scan.fDropScanCmd = eANI_BOOLEAN_FALSE; + + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + } + else + { + pMac->scan.fDropScanCmd = eANI_BOOLEAN_TRUE; + csrRemoveCmdWithSessionIdFromPendingList(pMac, + sessionId, + &pMac->sme.smeScanCmdPendingList, + eSmeCommandScan); + pMac->scan.fDropScanCmd = eANI_BOOLEAN_FALSE; + + pEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK); + } + + //We need to abort scan only if we are scanning + if(NULL != pEntry) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if(eSmeCommandScan == pCommand->command && + pCommand->sessionId == sessionId) + { + msgLen = (tANI_U16)(sizeof(tSirSmeScanAbortReq)); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, FL("Failed to allocate memory for SmeScanAbortReq")); + } + else + { + if(reason == eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE) + { + pCommand->u.scanCmd.abortScanDueToBandChange + = eANI_BOOLEAN_TRUE; + } + vos_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_ABORT_IND); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + pMsg->sessionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + } + } + + return(status); +} + +void csrRemoveCmdWithSessionIdFromPendingList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tDblLinkList *pList, + eSmeCommandType commandType) +{ + tDblLinkList localList; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pEntryToRemove; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return; + } + + csrLLLock(pList); + if ((pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK))) + { + + /* Have to make sure we don't loop back to the head of the list, + * which will happen if the entry is NOT on the list */ + while (pEntry) + { + pEntryToRemove = pEntry; + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR( pEntryToRemove, tSmeCmd, Link ); + if ((pCommand->command == commandType) && + (pCommand->sessionId == sessionId)) + { + /* Remove that entry only */ + if (csrLLRemoveEntry( pList, pEntryToRemove, LL_ACCESS_NOLOCK)) + { + csrLLInsertTail(&localList, pEntryToRemove, + LL_ACCESS_NOLOCK); + } + } + } + } + csrLLUnlock(pList); + + while ((pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK))) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + csrAbortCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + } + + csrLLClose(&localList); +} + +void csrRemoveCmdFromPendingList(tpAniSirGlobal pMac, tDblLinkList *pList, + eSmeCommandType commandType ) +{ + tDblLinkList localList; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pEntryToRemove; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return; + } + + csrLLLock(pList); + if( !csrLLIsListEmpty( pList, LL_ACCESS_NOLOCK ) ) + { + pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK); + + // Have to make sure we don't loop back to the head of the list, which will + // happen if the entry is NOT on the list... + while( pEntry ) + { + pEntryToRemove = pEntry; + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR( pEntryToRemove, tSmeCmd, Link ); + if ( pCommand->command == commandType ) + { + // Remove that entry only + if(csrLLRemoveEntry( pList, pEntryToRemove, LL_ACCESS_NOLOCK)) + { + csrLLInsertTail(&localList, pEntryToRemove, LL_ACCESS_NOLOCK); + } + } + } + + + } + csrLLUnlock(pList); + + while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE); + } + csrLLClose(&localList); + +} + +eHalStatus csrScanAbortScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeScanAbortReq *pMsg; + tANI_U16 msgLen; + tListElem *pEntry; + tSmeCmd *pCommand; + + if (!pMac->fScanOffload) + { + pMac->scan.fDropScanCmd = eANI_BOOLEAN_TRUE; +#ifdef WLAN_AP_STA_CONCURRENCY + csrRemoveScanForSSIDFromPendingList( pMac, &pMac->scan.scanCmdPendingList, sessionId); +#endif + csrRemoveScanForSSIDFromPendingList( pMac, &pMac->roam.roamCmdPendingList, sessionId); + csrRemoveScanForSSIDFromPendingList( pMac, &pMac->sme.smeCmdPendingList, sessionId); + pMac->scan.fDropScanCmd = eANI_BOOLEAN_FALSE; + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + } + else + { + pMac->scan.fDropScanCmd = eANI_BOOLEAN_TRUE; + csrRemoveScanForSSIDFromPendingList( pMac, &pMac->sme.smeScanCmdPendingList, sessionId); + pMac->scan.fDropScanCmd = eANI_BOOLEAN_FALSE; + pEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK); + } + + if(NULL != pEntry) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + + if ( (eSmeCommandScan == pCommand->command ) && + (sessionId == pCommand->sessionId)) + { + if ( eCsrScanForSsid == pCommand->u.scanCmd.reason) + { + msgLen = (tANI_U16)(sizeof( tSirSmeScanAbortReq )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, FL("Failed to allocate memory for SmeScanAbortReq")); + } + else + { + vos_mem_zero((void *)pMsg, msgLen); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_ABORT_IND); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + pMsg->sessionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + } + } + } + return( status ); +} + +void csrRemoveScanForSSIDFromPendingList(tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 sessionId) +{ + tDblLinkList localList; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pEntryToRemove; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return; + } + + csrLLLock(pList); + if( !csrLLIsListEmpty( pList, LL_ACCESS_NOLOCK ) ) + { + pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK); + + // Have to make sure we don't loop back to the head of the list, which will + // happen if the entry is NOT on the list... + while( pEntry ) + { + pEntryToRemove = pEntry; + pEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR( pEntryToRemove, tSmeCmd, Link ); + if ( (eSmeCommandScan == pCommand->command ) && + (sessionId == pCommand->sessionId) ) + { + if ( eCsrScanForSsid == pCommand->u.scanCmd.reason) + { + // Remove that entry only + if ( csrLLRemoveEntry( pList, pEntryToRemove, LL_ACCESS_NOLOCK)) + { + csrLLInsertTail(&localList, pEntryToRemove, LL_ACCESS_NOLOCK); + } + } + } + } + } + csrLLUnlock(pList); + + while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + csrAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE); + } + csrLLClose(&localList); +} + +eHalStatus csrScanAbortMacScanNotForConnect(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + if( !csrIsScanForRoamCommandActive( pMac ) ) + { + //Only abort the scan if it is not used for other roam/connect purpose + status = csrScanAbortMacScan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT); + } + + return (status); +} + + +eHalStatus csrScanGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirMbMsg *pMsg; + tANI_U16 msgLen; + + if (pMac->fScanOffload) + msgLen = (tANI_U16)(sizeof(tSirSmeGetScanChanReq)); + else + msgLen = (tANI_U16)(sizeof(tSirMbMsg)); + + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pMsg, msgLen, 0); + pMsg->type = eWNI_SME_GET_SCANNED_CHANNEL_REQ; + pMsg->msgLen = msgLen; + if (pMac->fScanOffload) + ((tSirSmeGetScanChanReq *)pMsg)->sessionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + + return( status ); +} + +tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel ) +{ + tANI_BOOLEAN fValid = FALSE; + tANI_U32 idxValidChannels; + tANI_U32 len = pMac->roam.numValidChannels; + + for ( idxValidChannels = 0; ( idxValidChannels < len ); idxValidChannels++ ) + { + if ( channel == pMac->roam.validChannelList[ idxValidChannels ] ) + { + fValid = TRUE; + break; + } + } + + return fValid; +} + +#ifdef FEATURE_WLAN_SCAN_PNO +eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + v_U32_t uLen = 0; + tpSirProbeRespBeacon pParsedFrame; + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDescr = NULL; + tANI_BOOLEAN fDupBss; + tDot11fBeaconIEs *pIesLocal = NULL; + tAniSSID tmpSsid; + v_TIME_t timer=0; + tpSirMacMgmtHdr macHeader = (tpSirMacMgmtHdr)pPrefNetworkFoundInd->data; + tListElem *pEntry; + + pParsedFrame = + (tpSirProbeRespBeacon)vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + + if (NULL == pParsedFrame) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for frame")); + return eHAL_STATUS_RESOURCES; + } + + if ( pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A ) + { + smsLog(pMac, LOGE, + FL("Not enough bytes in PNO indication probe resp frame! length=%d"), + pPrefNetworkFoundInd->frameLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + + if (sirConvertProbeFrame2Struct(pMac, + &pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A], + pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A, + pParsedFrame) != eSIR_SUCCESS || + !pParsedFrame->ssidPresent) + { + smsLog(pMac, LOGE, + FL("Parse error ProbeResponse, length=%d"), + pPrefNetworkFoundInd->frameLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + //24 byte MAC header and 12 byte to ssid IE + if (pPrefNetworkFoundInd->frameLength > + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) + { + uLen = pPrefNetworkFoundInd->frameLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + } + + pScanResult = vos_mem_malloc(sizeof(tCsrScanResult) + uLen); + if ( NULL == pScanResult ) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for frame")); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + vos_mem_set(pScanResult, sizeof(tCsrScanResult) + uLen, 0); + pBssDescr = &pScanResult->Result.BssDescriptor; + /* + * Length of BSS description is without length of length itself and length + * of pointer that holds the next BSS description + */ + pBssDescr->length = (tANI_U16)( + sizeof(tSirBssDescription) - sizeof(tANI_U16) - + sizeof(tANI_U32) + uLen); + if (pParsedFrame->dsParamsPresent) + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + else if (pParsedFrame->HTInfo.present) + { + pBssDescr->channelId = pParsedFrame->HTInfo.primaryChannel; + } + else + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + + if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) + { + int i; + // 11b or 11g packet + // 11g iff extended Rate IE is present or + // if there is an A rate in suppRate IE + for (i = 0; i < pParsedFrame->supportedRates.numRates; i++) + { + if (sirIsArate(pParsedFrame->supportedRates.rate[i] & 0x7f)) + { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (pParsedFrame->extendedRatesPresent) + { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + } + } + else + { + // 11a packet + pBssDescr->nwType = eSIR_11A_NW_TYPE; + } + + pBssDescr->sinr = 0; + pBssDescr->rssi = -1 * pPrefNetworkFoundInd->rssi; + pBssDescr->beaconInterval = pParsedFrame->beaconInterval; + if (!pBssDescr->beaconInterval) + { + smsLog(pMac, LOGW, + FL("Bcn Interval is Zero , default to 100" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pBssDescr->bssId) ); + pBssDescr->beaconInterval = 100; + } + pBssDescr->timeStamp[0] = pParsedFrame->timeStamp[0]; + pBssDescr->timeStamp[1] = pParsedFrame->timeStamp[1]; + pBssDescr->capabilityInfo = *((tANI_U16 *)&pParsedFrame->capabilityInfo); + vos_mem_copy((tANI_U8 *) &pBssDescr->bssId, (tANI_U8 *) macHeader->bssId, sizeof(tSirMacAddr)); + pBssDescr->nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + smsLog( pMac, LOG2, "(%s):Bssid= "MAC_ADDRESS_STR + " chan= %d, rssi = %d", __func__, + MAC_ADDR_ARRAY(pBssDescr->bssId), + pBssDescr->channelId, + pBssDescr->rssi ); + + //IEs + if (uLen) + { + vos_mem_copy(&pBssDescr->ieFields, + pPrefNetworkFoundInd->data + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET), + uLen); + } + + pIesLocal = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ); + if ( !pIesLocal && + (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + &pScanResult->Result.BssDescriptor, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" Cannot parse IEs")); + csrFreeScanResultEntry(pMac, pScanResult); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + fDupBss = csrRemoveDupBssDescription( pMac, + &pScanResult->Result.BssDescriptor, pIesLocal, &tmpSsid, &timer, FALSE); + //Check whether we have reach out limit + if ( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + { + //Limit reach + smsLog(pMac, LOGE, FL(" BSS limit reached")); + //Free the resources + if( (pScanResult->Result.pvIes == NULL) && pIesLocal ) + { + vos_mem_free(pIesLocal); + } + csrFreeScanResultEntry(pMac, pScanResult); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + if ((macHeader->fc.type == SIR_MAC_MGMT_FRAME) && + (macHeader->fc.subType == SIR_MAC_MGMT_PROBE_RSP)) + { + pScanResult->Result.BssDescriptor.fProbeRsp = 1; + } + //Add to scan cache + csrScanAddResult(pMac, pScanResult, pIesLocal, + pPrefNetworkFoundInd->sessionId); + pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_LOCK ); + if (pEntry && 0 != pMac->scan.scanResultCfgAgingTime) + csrScanStartResultCfgAgingTimer(pMac); + + if( (pScanResult->Result.pvIes == NULL) && pIesLocal ) + { + vos_mem_free(pIesLocal); + } + + vos_mem_free(pParsedFrame); + + return eHAL_STATUS_SUCCESS; +} +#endif //FEATURE_WLAN_SCAN_PNO + +#ifdef FEATURE_WLAN_LFR +void csrInitOccupiedChannelsList(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tListElem *pEntry = NULL; + tCsrScanResult *pBssDesc = NULL; + tDot11fBeaconIEs *pIes = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) + { + smsLog(pMac, LOG1, FL("Ini file contains neighbor scan channel list, " + "hence NO need to build occupied channel list (numChannels = %d)"), + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels); + return; + } + + if (!csrNeighborRoamIsNewConnectedProfile(pMac, sessionId)) + { + smsLog(pMac, LOG2, FL("donot flush occupied list since current roam " + "profile matches previous (numChannels = %d)"), + pMac->scan.occupiedChannels[sessionId].numChannels); + return; + } + + /* Empty occupied channels here */ + pMac->scan.occupiedChannels[sessionId].numChannels = 0; + + csrLLLock(&pMac->scan.scanResultList); + pEntry = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while( pEntry ) + { + pBssDesc = GET_BASE_ADDR( pEntry, tCsrScanResult, Link ); + pIes = (tDot11fBeaconIEs *)( pBssDesc->Result.pvIes ); + + //At this time, pBssDescription->Result.pvIes may be NULL + if( !pIes && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + &pBssDesc->Result.BssDescriptor, &pIes))) ) + { + continue; + } + + csrScanAddToOccupiedChannels(pMac, pBssDesc, sessionId, + &pMac->scan.occupiedChannels[sessionId], + pIes); + + /* + * Free the memory allocated for pIes in csrGetParsedBssDescriptionIEs + */ + if( (pBssDesc->Result.pvIes == NULL) && pIes ) + { + vos_mem_free(pIes); + } + + pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); + }//while + csrLLUnlock(&pMac->scan.scanResultList); +} +#endif + +eHalStatus csrScanCreateEntryInScanCache(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrBssid bssid, tANI_U8 channel) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tDot11fBeaconIEs *pNewIes = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tSirBssDescription *pNewBssDescriptor = NULL; + tANI_U32 size = 0; + + if(NULL == pSession) + { + status = eHAL_STATUS_FAILURE; + return status; + } + smsLog(pMac, LOG2, FL("csrScanCreateEntryInScanCache: Current bssid::" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pSession->pConnectBssDesc->bssId)); + smsLog(pMac, LOG2, FL("csrScanCreateEntryInScanCache: My bssid::" + MAC_ADDRESS_STR" channel %d"), + MAC_ADDR_ARRAY(bssid), channel); + + do + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + pSession->pConnectBssDesc, &pNewIes))) + { + smsLog(pMac, LOGE, FL("%s: Failed to parse IEs"), + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + + size = pSession->pConnectBssDesc->length + sizeof(pSession->pConnectBssDesc->length); + if (size) + { + pNewBssDescriptor = vos_mem_malloc(size); + if ( NULL == pNewBssDescriptor ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (HAL_STATUS_SUCCESS(status)) + { + vos_mem_copy(pNewBssDescriptor, pSession->pConnectBssDesc, size); + } + else + { + smsLog(pMac, LOGE, FL("%s: memory allocation failed"), + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + + //change the BSSID & channel as passed + vos_mem_copy(pNewBssDescriptor->bssId, bssid, sizeof(tSirMacAddr)); + pNewBssDescriptor->channelId = channel; + if (NULL == csrScanAppendBssDescription(pMac, pNewBssDescriptor, + pNewIes, TRUE, sessionId)) { + smsLog(pMac, LOGE, FL("csrScanAppendBssDescription failed")); + status = eHAL_STATUS_FAILURE; + break; + } + } + else + { + smsLog(pMac, LOGE, FL("%s: length of bss descriptor is 0"), + __func__); + status = eHAL_STATUS_FAILURE; + break; + } + smsLog(pMac, LOGE, FL("%s: entry successfully added in scan cache"), + __func__); + }while(0); + + if(pNewIes) + { + vos_mem_free(pNewIes); + } + if(pNewBssDescriptor) + { + vos_mem_free(pNewBssDescriptor); + } + return status; +} + +#ifdef FEATURE_WLAN_ESE +// Update the TSF with the difference in system time +void UpdateCCKMTSF(tANI_U32 *timeStamp0, tANI_U32 *timeStamp1, tANI_U32 *incr) +{ + tANI_U64 timeStamp64 = ((tANI_U64)*timeStamp1 << 32) | (*timeStamp0); + timeStamp64 = (tANI_U64)(timeStamp64 + (tANI_U64)*incr); + *timeStamp0 = (tANI_U32)(timeStamp64 & 0xffffffff); + *timeStamp1 = (tANI_U32)((timeStamp64 >> 32) & 0xffffffff); +} +#endif + +/** + * csrScanSaveRoamOffloadApToScanCache + * This function parses the received beacon/probe response + * from the firmware as part of the roam synch indication. + * The beacon or the probe response is parsed and is also + * saved into the scan cache + * + * @param pMac Pointer to Global Mac + * @param pRoamOffloadSynchInd Roam Synch Indication from + * firmware which also contains the beacon/probe + * response + * @return Status + */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +eHalStatus csrScanSaveRoamOffloadApToScanCache(tpAniSirGlobal pMac, + tSirRoamOffloadSynchInd *pRoamOffloadSynchInd) +{ + v_U32_t uLen = 0; + tANI_BOOLEAN fDupBss; + tDot11fBeaconIEs *pIesLocal = NULL; + tAniSSID tmpSsid; + v_TIME_t timer=0; + tCsrScanResult *pScanResult = NULL; + tANI_U8 sessionId = pRoamOffloadSynchInd->roamedVdevId; + + uLen = pRoamOffloadSynchInd->beaconProbeRespLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + pScanResult = vos_mem_malloc(sizeof(tCsrScanResult) + uLen); + if ( pScanResult == NULL ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + " fail to allocate memory for frame"); + return eHAL_STATUS_RESOURCES; + } + + vos_mem_zero(pScanResult, sizeof(tCsrScanResult) + uLen ); + vos_mem_copy(&pScanResult->Result.BssDescriptor, + pRoamOffloadSynchInd->pbssDescription, + (sizeof(tSirBssDescription) + uLen)); + pIesLocal = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ); + if ( !pIesLocal && + (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + &pScanResult->Result.BssDescriptor, &pIesLocal))) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s:Cannot Parse IEs", __func__); + csrFreeScanResultEntry(pMac, pScanResult); + return eHAL_STATUS_RESOURCES; + } + + fDupBss = csrRemoveDupBssDescription(pMac, + &pScanResult->Result.BssDescriptor, + pIesLocal, &tmpSsid, &timer, TRUE); + if ( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s:BSS Limit Exceed", __func__); + if( (pScanResult->Result.pvIes == NULL) && pIesLocal ) + { + vos_mem_free(pIesLocal); + } + csrFreeScanResultEntry(pMac, pScanResult); + return eHAL_STATUS_RESOURCES; + } + csrScanAddResult(pMac, pScanResult, pIesLocal, sessionId); + return eHAL_STATUS_SUCCESS; +} +#endif + +/** + * csr_get_bssdescr_from_scan_handle() - This function to extract + * first bss description from scan handle + * @result_handle: an object for the result. + * + * This function is written to extract first bss from scan handle. + * + * Return: first bss descriptor from the scan handle. + */ +tSirBssDescription* +csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, + tSirBssDescription *bss_descr) +{ + tListElem *first_element = NULL; + tCsrScanResult *scan_result = NULL; + tScanResultList *bss_list = (tScanResultList *)result_handle; + + if (NULL == bss_list) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Empty bss_list")); + return NULL; + } + if (csrLLIsListEmpty(&bss_list->List, LL_ACCESS_NOLOCK)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("bss_list->List is empty")); + vos_mem_free(bss_list); + return NULL; + } + first_element = csrLLPeekHead(&bss_list->List, LL_ACCESS_NOLOCK); + if (first_element) { + scan_result = GET_BASE_ADDR(first_element, + tCsrScanResult, + Link); + vos_mem_copy(bss_descr, + &scan_result->Result.BssDescriptor, + sizeof(tSirBssDescription)); + } + return bss_descr; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrCmdProcess.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrCmdProcess.c new file mode 100644 index 000000000000..dd3b97fe0126 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrCmdProcess.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csrCmdProcess.c + + Implementation for processing various commands. +========================================================================== */ + + + +#include "aniGlobal.h" + +#include "palApi.h" +#include "csrInsideApi.h" +#include "smeInside.h" +#include "smsDebug.h" +#include "macTrace.h" + + + +eHalStatus csrMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeRsp *pSmeRsp = (tSirSmeRsp *)pMsgBuf; +#ifdef FEATURE_WLAN_SCAN_PNO + tSirMbMsg *pMsg = (tSirMbMsg *)pMsgBuf; + tCsrRoamSession *pSession; +#endif + + smsLog(pMac, LOG2, FL("Message %d[0x%04X] received in curState %s" + " and substate %s sessionId (%d)"), + pSmeRsp->messageType, pSmeRsp->messageType, + macTraceGetcsrRoamState(pMac->roam.curState[pSmeRsp->sessionId]), + macTraceGetcsrRoamSubState( + pMac->roam.curSubState[pSmeRsp->sessionId]), pSmeRsp->sessionId); + +#ifdef FEATURE_WLAN_SCAN_PNO + /* + * PNO scan responses have to be handled irrespective of CSR roam state. + * Check if PNO has been started and only then process the PNO scan results. + * Also note that normal scan is not allowed when PNO scan is in progress + * and so the scan responses reaching here when PNO is started must be + * PNO responses. For normal scan, the PNO started flag will be FALSE and + * it will be processed as usual based on the current CSR roam state. + */ + pSession = CSR_GET_SESSION(pMac, pSmeRsp->sessionId); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found, msgType : %d"), pSmeRsp->sessionId, + pMsg->type); + return eHAL_STATUS_FAILURE; + } + + if((eWNI_SME_SCAN_RSP == pMsg->type) && (TRUE == pSession->pnoStarted)) + { + status = csrScanningStateMsgProcessor(pMac, pMsgBuf); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL(" handling PNO scan resp msg 0x%X CSR state is %d"), + pSmeRsp->messageType, pMac->roam.curState[pSmeRsp->sessionId]); + } + return (status); + } +#endif + + // Process the message based on the state of the roaming states... + +#if defined( ANI_RTT_DEBUG ) + if(!pAdapter->fRttModeEnabled) + { +#endif//RTT + switch (pMac->roam.curState[pSmeRsp->sessionId]) + { + case eCSR_ROAMING_STATE_SCANNING: + { + //Are we in scan state +#if defined( ANI_EMUL_ASSOC ) + emulScanningStateMsgProcessor( pAdapter, pMBBufHdr ); +#else + status = csrScanningStateMsgProcessor(pMac, pMsgBuf); +#endif + break; + } + + case eCSR_ROAMING_STATE_JOINED: + { + //are we in joined state + csrRoamJoinedStateMsgProcessor( pMac, pMsgBuf ); + break; + } + + case eCSR_ROAMING_STATE_JOINING: + { + //are we in roaming states +#if defined( ANI_EMUL_ASSOC ) + emulRoamingStateMsgProcessor( pAdapter, pMBBufHdr ); +#endif + csrRoamingStateMsgProcessor( pMac, pMsgBuf ); + break; + } + + //For all other messages, we ignore it + default: + { + /*To work-around an issue where checking for set/remove key base on connection state is no longer + * 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) ) + { + smsLog(pMac, LOGW, FL(" handling msg 0x%X CSR state is %d"), pSmeRsp->messageType, pMac->roam.curState[pSmeRsp->sessionId]); + csrRoamCheckForLinkStatusChange(pMac, pSmeRsp); + } + else if(eWNI_SME_GET_RSSI_REQ == pSmeRsp->messageType) + { + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)pMsgBuf; + if(NULL != pGetRssiReq->rssiCallback) + { + smsLog(pMac, + LOGW, + FL("Message eWNI_SME_GET_RSSI_REQ is not handled" + " by CSR in state %d. calling RSSI callback"), + pMac->roam.curState[pSmeRsp->sessionId]); + ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(pGetRssiReq->lastRSSI, + pGetRssiReq->staId, + pGetRssiReq->pDevContext); + } + else + { + smsLog(pMac, LOGE, FL("pGetRssiReq->rssiCallback is NULL")); + } + } + else + { + smsLog(pMac, LOGE, "Message 0x%04X is not handled by CSR " + " CSR state is %d session Id %d", pSmeRsp->messageType, + pMac->roam.curState[pSmeRsp->sessionId], pSmeRsp->sessionId); + + if (eWNI_SME_FT_PRE_AUTH_RSP == pSmeRsp->messageType) { + smsLog(pMac, LOGE, "Dequeue eSmeCommandRoam command" + " with reason eCsrPerformPreauth"); + csrDequeueRoamCommand(pMac, eCsrPerformPreauth); + } + else if (eWNI_SME_REASSOC_RSP == pSmeRsp->messageType) { + smsLog(pMac, LOGE, "Dequeue eSmeCommandRoam command" + " with reason eCsrSmeIssuedFTReassoc"); + csrDequeueRoamCommand(pMac, eCsrSmeIssuedFTReassoc); + } + } + break; + } + + }//switch + +#if defined( ANI_RTT_DEBUG ) + } +#endif//RTT + + return (status); +} + + + +tANI_BOOLEAN csrCheckPSReady(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + + if (pMac->roam.sPendingCommands < 0) + { + VOS_ASSERT( pMac->roam.sPendingCommands >= 0 ); + return 0; + } + return (pMac->roam.sPendingCommands == 0); +} + +tANI_BOOLEAN csrCheckPSOffloadReady(void *pv, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(pv); + + VOS_ASSERT(pMac->roam.sPendingCommands >= 0); + return (pMac->roam.sPendingCommands == 0); +} + +void csrFullPowerCallback(void *pv, eHalStatus status) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + tListElem *pEntry; + tSmeCmd *pCommand; + + (void)status; + + while( NULL != ( pEntry = csrLLRemoveHead( &pMac->roam.roamCmdPendingList, eANI_BOOLEAN_TRUE ) ) ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + smePushCommand( pMac, pCommand, eANI_BOOLEAN_FALSE ); + } + +} + +void csrFullPowerOffloadCallback(void *pv, tANI_U32 sessionId, eHalStatus status) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( pv ); + tListElem *pEntry; + tSmeCmd *pCommand; + + (void)status; + + while(NULL != (pEntry = csrLLRemoveHead(&pMac->roam.roamCmdPendingList, + eANI_BOOLEAN_TRUE))) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + smePushCommand(pMac, pCommand, eANI_BOOLEAN_FALSE); + } + +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrInsideApi.h b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrInsideApi.h new file mode 100644 index 000000000000..d7ea4fd92229 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrInsideApi.h @@ -0,0 +1,1081 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrInsideApi.h + + Define interface only used by CSR. +========================================================================== */ +#ifndef CSR_INSIDE_API_H__ +#define CSR_INSIDE_API_H__ + + +#include "csrSupport.h" +#include "smeInside.h" +#include "vos_nvitem.h" + +#define CSR_PASSIVE_MAX_CHANNEL_TIME 110 +#define CSR_PASSIVE_MIN_CHANNEL_TIME 60 + +#define CSR_ACTIVE_MAX_CHANNEL_TIME 40 +#define CSR_ACTIVE_MIN_CHANNEL_TIME 20 + +#define CSR_ACTIVE_MAX_CHANNEL_TIME_BTC 120 +#define CSR_ACTIVE_MIN_CHANNEL_TIME_BTC 60 + +#ifdef WLAN_AP_STA_CONCURRENCY +#define CSR_PASSIVE_MAX_CHANNEL_TIME_CONC 110 +#define CSR_PASSIVE_MIN_CHANNEL_TIME_CONC 60 + +#define CSR_ACTIVE_MAX_CHANNEL_TIME_CONC 27 +#define CSR_ACTIVE_MIN_CHANNEL_TIME_CONC 20 + +#define CSR_REST_TIME_CONC 100 + +#define CSR_MIN_REST_TIME_CONC 50 + +#define CSR_IDLE_TIME_CONC 25 + +#define CSR_NUM_STA_CHAN_COMBINED_CONC 3 +#define CSR_NUM_P2P_CHAN_COMBINED_CONC 1 +#endif + +#define CSR_MAX_NUM_SUPPORTED_CHANNELS 55 + +#define CSR_MAX_2_4_GHZ_SUPPORTED_CHANNELS 14 + +#define CSR_MAX_BSS_SUPPORT 250 +#define SYSTEM_TIME_MSEC_TO_USEC 1000 + +/* This number minus 1 means the number of times a channel is scanned + before a BSS is removed from cache scan result */ +#define CSR_AGING_COUNT 3 +//The following defines are used by palTimer +//This is used for palTimer when request to imps fails +#define CSR_IDLE_SCAN_WAIT_TIME (1 * VOS_TIMER_TO_SEC_UNIT) //1 second +//This is used for palTimer when imps ps is disabled +//This number shall not be smaller than 5-6 seconds in general because a full scan may take 3-4 seconds +#define CSR_IDLE_SCAN_NO_PS_INTERVAL (10 * VOS_TIMER_TO_SEC_UNIT) //10 second +#define CSR_IDLE_SCAN_NO_PS_INTERVAL_MIN (5 * VOS_TIMER_TO_SEC_UNIT) +#define CSR_SCAN_GET_RESULT_INTERVAL (5 * VOS_TIMER_TO_SEC_UNIT) //5 seconds +#define CSR_MIC_ERROR_TIMEOUT (60 * VOS_TIMER_TO_SEC_UNIT) //60 seconds +#define CSR_TKIP_COUNTER_MEASURE_TIMEOUT (60 * VOS_TIMER_TO_SEC_UNIT) //60 seconds +#define CSR_SCAN_RESULT_CFG_AGING_INTERVAL (VOS_TIMER_TO_SEC_UNIT) // 1 second +//the following defines are NOT used by palTimer +#define CSR_SCAN_AGING_TIME_NOT_CONNECT_NO_PS 50 //50 seconds +#define CSR_SCAN_AGING_TIME_NOT_CONNECT_W_PS 300 //300 seconds +#define CSR_SCAN_AGING_TIME_CONNECT_NO_PS 150 //150 seconds +#define CSR_SCAN_AGING_TIME_CONNECT_W_PS 600 //600 seconds +#define CSR_JOIN_FAILURE_TIMEOUT_DEFAULT ( 3000 ) +#define CSR_JOIN_FAILURE_TIMEOUT_MIN (1000) //minimal value +//These are going against the signed RSSI (tANI_S8) so it is between -+127 +#define CSR_BEST_RSSI_VALUE (-30) //RSSI >= this is in CAT4 +#define CSR_DEFAULT_RSSI_DB_GAP 30 //every 30 dbm for one category +#define CSR_BSS_CAP_VALUE_NONE 0 //not much value +#define CSR_BSS_CAP_VALUE_HT 1 +#define CSR_BSS_CAP_VALUE_VHT 2 +#define CSR_BSS_CAP_VALUE_WMM 1 +#define CSR_BSS_CAP_VALUE_UAPSD 1 +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +#define CSR_BSS_CAP_VALUE_5GHZ 2 +#endif +#define CSR_DEFAULT_ROAMING_TIME 10 //10 seconds +#define CSR_ROAM_MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#define CSR_ROAM_MAX(X, Y) ((X) > (Y) ? (X) : (Y)) + + +#define CSR_ROAMING_DFS_CHANNEL_DISABLED (0) +#define CSR_ROAMING_DFS_CHANNEL_ENABLED_NORMAL (1) +#define CSR_ROAMING_DFS_CHANNEL_ENABLED_ACTIVE (2) + +/* The MAX BSSID Count should be lower than the command timeout + * value and it can be of a fraction of 3/4 of the total command + * timeout value */ +#define CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE 1000*30*4 //120s +#define CSR_MAX_BSSID_COUNT ((CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE/4000) * 3) +#define CSR_CUSTOM_CONC_GO_BI 100 +#define MIN_11P_CHANNEL 170 + +typedef enum +{ + eCsrNextScanNothing, + eCsrNextLostLinkScan1Success, + eCsrNextLostLinkScan1Failed, + eCsrNextLostLinkScan2Success, + eCsrNextLostLinkScan2Failed, + eCsrNextLostLinkScan3Success, + eCsrNexteScanForSsidSuccess, + eCsrNextLostLinkScan3Failed, + eCsrNext11dScan1Failure, + eCsrNext11dScan1Success, + eCsrNext11dScan2Failure, + eCsrNext11dScan2Success, + eCsrNext11dScanComplete, + eCsrNexteScanForSsidFailure, + eCsrNextIdleScanComplete, + eCsrNextCapChangeScanComplete, + +}eCsrScanCompleteNextCommand; + +typedef enum +{ + eCsrJoinSuccess, + eCsrJoinFailure, + eCsrReassocSuccess, + eCsrReassocFailure, + eCsrNothingToJoin, + eCsrStartBssSuccess, + eCsrStartBssFailure, + eCsrSilentlyStopRoaming, + eCsrSilentlyStopRoamingSaveState, + eCsrJoinWdsFailure, + eCsrJoinFailureDueToConcurrency, + +}eCsrRoamCompleteResult; + +typedef struct tagScanReqParam +{ + tANI_U8 bReturnAfter1stMatch; + tANI_U8 fUniqueResult; + tANI_U8 freshScan; + tANI_U8 hiddenSsid; + tANI_U8 reserved; +}tScanReqParam; + +typedef struct tagCsrScanResult +{ + tListElem Link; + tANI_S32 AgingCount; //This BSS is removed when it reaches 0 or less + tANI_U32 preferValue; //The bigger the number, the better the BSS. This value override capValue + + /* The bigger the better. This value is in use only if + we have equal preferValue */ + tANI_U32 capValue; + + /* + * This member must be the last in the structure because the end of + * tSirBssDescription (inside) is an array with non known size at this time + */ + + eCsrEncryptionType ucEncryptionType; //Preferred Encryption type that matched with profile. + eCsrEncryptionType mcEncryptionType; + eCsrAuthType authType; //Preferred auth type that matched with the profile. + + tCsrScanResultInfo Result; +}tCsrScanResult; + +typedef struct +{ + tDblLinkList List; + tListElem *pCurEntry; +}tScanResultList; + + + + +#define CSR_IS_ROAM_REASON( pCmd, reason ) ( (reason) == (pCmd)->roamCmd.roamReason ) +#define CSR_IS_BETTER_PREFER_VALUE(v1, v2) ((v1) > (v2)) +#define CSR_IS_EQUAL_PREFER_VALUE(v1, v2) ((v1) == (v2)) +#define CSR_IS_BETTER_CAP_VALUE(v1, v2) ((v1) > (v2)) +#define CSR_IS_EQUAL_CAP_VALUE(v1, v2) ((v1) == (v2)) +#define CSR_IS_BETTER_RSSI(v1, v2) ((v1) > (v2)) +#define CSR_IS_ENC_TYPE_STATIC( encType ) ( ( eCSR_ENCRYPT_TYPE_NONE == (encType) ) || \ + ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == (encType) ) || \ + ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == (encType) ) ) +#define CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) ( CSR_IS_ROAM_JOINED( pMac, sessionId ) && CSR_IS_ROAM_SUBSTATE_WAITFORKEY( pMac, sessionId ) ) +//WIFI has a test case for not using HT rates with TKIP as encryption +//We may need to add WEP but for now, TKIP only. + +#define CSR_IS_11n_ALLOWED( encType ) (( eCSR_ENCRYPT_TYPE_TKIP != (encType) ) && \ + ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY != (encType) ) && \ + ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY != (encType) ) && \ + ( 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_CLOSE_SESSION_COMMAND(pCommand) \ + ((pCommand)->command == eSmeCommandDelStaSession) + +eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId); +eHalStatus csrScanningStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ); +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); +void csrReleaseCommandScan(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrReleaseCommandWmStatusChange(tpAniSirGlobal pMac, tSmeCmd *pCommand); + +tANI_BOOLEAN csrIsDuplicateBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2, tANI_BOOLEAN fForced ); +eHalStatus csrRoamSaveConnectedBssDesc( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDesc ); +tANI_BOOLEAN csrIsNetworkTypeEqual( tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 ); +eHalStatus csrScanSmeScanResponse( tpAniSirGlobal pMac, void *pMsgBuf ); +/* + Prepare a filter base on a profile for parsing the scan results. + Upon successful return, caller MUST call csrFreeScanFilter on + pScanFilter when it is done with the filter. +*/ +eHalStatus csrRoamPrepareFilterFromProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tCsrScanResultFilter *pScanFilter); +eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, tCsrRoamProfile *pSrcProfile); +eHalStatus csrRoamStart(tpAniSirGlobal pMac); +void csrRoamStop(tpAniSirGlobal pMac, tANI_U32 sessionId); +void csrRoamStartMICFailureTimer(tpAniSirGlobal pMac); +void csrRoamStopMICFailureTimer(tpAniSirGlobal pMac); +void csrRoamStartTKIPCounterMeasureTimer(tpAniSirGlobal pMac); +void csrRoamStopTKIPCounterMeasureTimer(tpAniSirGlobal pMac); + +eHalStatus csrScanOpen(tpAniSirGlobal pMac); +eHalStatus csrScanClose(tpAniSirGlobal pMac); +eHalStatus csrScanRequestLostLink1( tpAniSirGlobal pMac, tANI_U32 sessionId ); +eHalStatus csrScanRequestLostLink2( tpAniSirGlobal pMac, tANI_U32 sessionId ); +eHalStatus csrScanRequestLostLink3( tpAniSirGlobal pMac, tANI_U32 sessionId ); +eHalStatus csrScanHandleFailedLostlink1(tpAniSirGlobal pMac, tANI_U32 sessionId); +eHalStatus csrScanHandleFailedLostlink2(tpAniSirGlobal pMac, tANI_U32 sessionId); +eHalStatus csrScanHandleFailedLostlink3(tpAniSirGlobal pMac, tANI_U32 sessionId); +tCsrScanResult *csrScanAppendBssDescription(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDescription, + tDot11fBeaconIEs *pIes, + tANI_BOOLEAN fForced, + tANI_U8 sessionId); +void csrScanCallCallback(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus); +eHalStatus csrScanCopyRequest(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, tCsrScanRequest *pSrcReq); +eHalStatus csrScanFreeRequest(tpAniSirGlobal pMac, tCsrScanRequest *pReq); +eHalStatus csrScanCopyResultList(tpAniSirGlobal pMac, tScanResultHandle hIn, tScanResultHandle *phResult); +void csrInitBGScanChannelList(tpAniSirGlobal pMac); +eHalStatus csrScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tANI_U32 roamId, tANI_BOOLEAN notify); +eHalStatus csrScanForCapabilityChange(tpAniSirGlobal pMac, tSirSmeApNewCaps *pNewCaps); +eHalStatus csrScanStartGetResultTimer(tpAniSirGlobal pMac); +eHalStatus csrScanStopGetResultTimer(tpAniSirGlobal pMac); +eHalStatus csrScanStartResultCfgAgingTimer(tpAniSirGlobal pMac); +eHalStatus csrScanStopResultCfgAgingTimer(tpAniSirGlobal pMac); +eHalStatus csrScanBGScanEnable(tpAniSirGlobal pMac); +eHalStatus csrScanStartIdleScanTimer(tpAniSirGlobal pMac, tANI_U32 interval); +eHalStatus csrScanStopIdleScanTimer(tpAniSirGlobal pMac); +eHalStatus csrScanStartIdleScan(tpAniSirGlobal pMac); +/* Param: pTimeInterval -- Caller allocated memory in return, if failed, + to specify the next time interval for idle scan timer interval */ +//Return: Not success -- meaning it cannot start IMPS, caller needs to start a timer for idle scan +eHalStatus csrScanTriggerIdleScan(tpAniSirGlobal pMac, tANI_U32 *pTimeInterval); +void csrScanCancelIdleScan(tpAniSirGlobal pMac); +void csrScanStopTimers(tpAniSirGlobal pMac); +//This function will remove scan commands that are not related to association or IBSS +tANI_BOOLEAN csrScanRemoveNotRoamingScanCommand(tpAniSirGlobal pMac); +//To remove fresh scan commands from the pending queue +tANI_BOOLEAN csrScanRemoveFreshScanCommand(tpAniSirGlobal pMac, tANI_U8 sessionId); +eHalStatus csrScanAbortMacScan(tpAniSirGlobal pMac, tANI_U8 sessionId, + eCsrAbortReason reason); +void csrRemoveCmdFromPendingList(tpAniSirGlobal pMac, tDblLinkList *pList, + eSmeCommandType commandType ); +void csrRemoveCmdWithSessionIdFromPendingList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tDblLinkList *pList, + eSmeCommandType commandType); +eHalStatus csrScanAbortMacScanNotForConnect(tpAniSirGlobal pMac, + tANI_U8 sessionId); +eHalStatus csrScanGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 sessionId); +eHalStatus csrScanAbortScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId); +void csrRemoveScanForSSIDFromPendingList(tpAniSirGlobal pMac, tDblLinkList *pList, tANI_U32 sessionId); + +//To age out scan results base. tSmeGetScanChnRsp is a pointer returned by LIM that +//has the information regarding scanned channels. +//The logic is that whenever CSR add a BSS to scan result, it set the age count to +//a value. This function deduct the age count if channelId matches the BSS' channelId +//The BSS is remove if the count reaches 0. +eHalStatus csrScanAgeResults(tpAniSirGlobal pMac, tSmeGetScanChnRsp *pScanChnInfo); + +//If fForce is TRUE we will save the new String that is learn't. +//Typically it will be true in case of Join or user initiated ioctl +tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tANI_BOOLEAN fForce ); +void csrApplyCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce ); +void csrSetCfgScanControlList( tpAniSirGlobal pMac, tANI_U8 *countryCode, tCsrChannel *pChannelList ); +void csrReinitScanCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrFreeScanResultEntry( tpAniSirGlobal pMac, tCsrScanResult *pResult ); + +eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus u1, eCsrRoamResult u2); +eHalStatus csrRoamIssueConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tScanResultHandle hBSSList, + eCsrRoamReason reason, tANI_U32 roamId, + tANI_BOOLEAN fImediate, tANI_BOOLEAN fClearScan); +eHalStatus csrRoamIssueReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields *pModProfileFields, + eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate); +void csrRoamComplete( tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, void *Context ); +eHalStatus csrRoamIssueSetContextReq( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrEncryptionType EncryptType, + tSirBssDescription *pBssDescription, + tSirMacAddr *bssId, tANI_BOOLEAN addKey, + tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection, + tANI_U8 keyId, tANI_U16 keyLength, + tANI_U8 *pKey, tANI_U8 paeRole ); +eHalStatus csrRoamProcessDisassocDeauth( tpAniSirGlobal pMac, tSmeCmd *pCommand, + tANI_BOOLEAN fDisassoc, tANI_BOOLEAN fMICFailure ); +eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes); +void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ); +void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg); +eHalStatus csrRoamIssueStartBss( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamStartBssParams *pParam, + tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc, tANI_U32 roamId ); +eHalStatus csrRoamIssueStopBss( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate ); +tANI_BOOLEAN csrIsSameProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile1, tCsrRoamProfile *pProfile2); +tANI_BOOLEAN csrIsRoamCommandWaiting(tpAniSirGlobal pMac); +tANI_BOOLEAN csrIsRoamCommandWaitingForSession(tpAniSirGlobal pMac, tANI_U32 sessionId); +tANI_BOOLEAN csrIsScanForRoamCommandActive( tpAniSirGlobal pMac ); +eRoamCmdStatus csrGetRoamCompleteStatus(tpAniSirGlobal pMac, tANI_U32 sessionId); +//pBand can be NULL if caller doesn't need to get it +//eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, eCsrPhyMode phyModeIn, tANI_U8 operationChn, eCsrBand *pBand ); +eHalStatus csrRoamIssueDisassociateCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason ); +eHalStatus csrRoamDisconnectInternal(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason); +//pCommand may be NULL +void csrRoamRemoveDuplicateCommand(tpAniSirGlobal pMac, tANI_U32 sessionId, tSmeCmd *pCommand, eCsrRoamReason eRoamReason); + +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 ); +eHalStatus csrSendMBDeauthReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode ); +eHalStatus csrSendMBDisassocCnfMsg( tpAniSirGlobal pMac, tpSirSmeDisassocInd pDisassocInd ); +eHalStatus csrSendMBDeauthCnfMsg( tpAniSirGlobal pMac, tpSirSmeDeauthInd pDeauthInd ); +eHalStatus csrSendAssocCnfMsg( tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, eHalStatus status ); +eHalStatus csrSendAssocIndToUpperLayerCnfMsg( tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, eHalStatus Halstatus, tANI_U8 sessionId ); +eHalStatus csrSendMBStartBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamBssType bssType, + tCsrRoamStartBssParams *pParam, tSirBssDescription *pBssDesc ); +eHalStatus csrSendMBStopBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId ); + +tANI_BOOLEAN csrIsMacAddressEqual( tpAniSirGlobal pMac, tCsrBssid *pMacAddr1, tCsrBssid *pMacAddr2 ); +//Caller should put the BSS' ssid to fiedl bssSsid when comparing SSID for a BSS. +tANI_BOOLEAN csrIsSsidMatch( tpAniSirGlobal pMac, tANI_U8 *ssid1, tANI_U8 ssid1Len, tANI_U8 *bssSsid, + tANI_U8 bssSsidLen, tANI_BOOLEAN fSsidRequired ); +tANI_BOOLEAN csrIsPhyModeMatch( tpAniSirGlobal pMac, tANI_U32 phyMode, + tSirBssDescription *pSirBssDesc, tCsrRoamProfile *pProfile, + eCsrCfgDot11Mode *pReturnCfgDot11Mode, + tDot11fBeaconIEs *pIes); +tANI_BOOLEAN csrRoamIsChannelValid( tpAniSirGlobal pMac, tANI_U8 channel ); + +//pNumChan is a caller allocated space with the sizeof pChannels +eHalStatus csrGetCfgValidChannels(tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U32 *pNumChan); +void csrRoamCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result); +void csrScanCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result); + +tPowerdBm csrGetCfgMaxTxPower (tpAniSirGlobal pMac, tANI_U8 channel); + +//To free the last roaming profile +void csrFreeRoamProfile(tpAniSirGlobal pMac, tANI_U32 sessionId); +void csrFreeConnectBssDesc(tpAniSirGlobal pMac, tANI_U32 sessionId); +eHalStatus csrMoveBssToHeadFromBSSID(tpAniSirGlobal pMac, tCsrBssid *bssid, tScanResultHandle hScanResult); +tANI_BOOLEAN csrCheckPSReady(void *pv); +tANI_BOOLEAN csrCheckPSOffloadReady(void *pv, tANI_U32 sessionId); +void csrFullPowerCallback(void *pv, eHalStatus status); +void csrFullPowerOffloadCallback(void *pv, tANI_U32 sessionId, + eHalStatus status); + +//to free memory allocated inside the profile structure +void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile); +//To free memory allocated inside scanFilter +void csrFreeScanFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter); +eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tANI_BOOLEAN fProprietary); +tANI_U32 csrTranslateToWNICfgDot11Mode(tpAniSirGlobal pMac, eCsrCfgDot11Mode csrDot11Mode); +void csrSaveChannelPowerForBand( tpAniSirGlobal pMac, tANI_BOOLEAN fPopulate5GBand ); +void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva); +void csrApplyPower2Current( tpAniSirGlobal pMac ); +void csrAssignRssiForCategory(tpAniSirGlobal pMac, tANI_S8 bestApRssi, tANI_U8 catOffset); +tANI_BOOLEAN csrIsMacAddressZero( tpAniSirGlobal pMac, tCsrBssid *pMacAddr ); +tANI_BOOLEAN csrIsMacAddressBroadcast( tpAniSirGlobal pMac, tCsrBssid *pMacAddr ); +eHalStatus csrRoamRemoveConnectedBssFromScanCache(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pConnProfile); +eHalStatus csrRoamStartRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamingReason roamingReason); +//return a boolean to indicate whether roaming completed or continue. +tANI_BOOLEAN csrRoamCompleteRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_BOOLEAN fForce, eCsrRoamResult roamResult); +void csrRoamCompletion(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo, tSmeCmd *pCommand, eCsrRoamResult roamResult, tANI_BOOLEAN fSuccess); +void csrRoamCancelRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId); +void csrResetCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce, tANI_BOOLEAN updateRiva ); +void csrResetPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId ); +#ifdef FEATURE_WLAN_WAPI +void csrResetBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId ); +#endif /* FEATURE_WLAN_WAPI */ +eHalStatus csrSaveToChannelPower2G_5G( tpAniSirGlobal pMac, tANI_U32 tableSize, tSirMacChanInfo *channelTable ); +//Get the list of the base channels to scan for passively 11d info +eHalStatus csrScanGetSupportedChannels( tpAniSirGlobal pMac ); +//To check whether a country code matches the one in the IE +//Only check the first two characters, ignoring in/outdoor +//pCountry -- caller allocated buffer contain the country code that is checking against +//the one in pIes. It can be NULL. +//caller must provide pIes, it cannot be NULL +//This function always return TRUE if 11d support is not turned on. +//pIes cannot be NULL +tANI_BOOLEAN csrMatchCountryCode( tpAniSirGlobal pMac, tANI_U8 *pCountry, tDot11fBeaconIEs *pIes ); +eHalStatus csrRoamSetKey( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 roamId ); +eHalStatus csrRoamOpenSession(tpAniSirGlobal pMac, + csrRoamCompleteCallback callback, + void *pContext, + tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId, + tANI_U32 type, tANI_U32 subType ); +/* fSync: TRUE means clean up needs to handle synchronously. */ +eHalStatus csrRoamCloseSession( tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_BOOLEAN fSync, + csrRoamSessionCloseCallback callback, + void *pContext ); +void csrCleanupSession(tpAniSirGlobal pMac, tANI_U32 sessionId); +eHalStatus csrRoamGetSessionIdFromBSSID( tpAniSirGlobal pMac, tCsrBssid *bssid, tANI_U32 *pSessionId ); +eCsrCfgDot11Mode csrFindBestPhyMode( tpAniSirGlobal pMac, tANI_U32 phyMode ); + +/* --------------------------------------------------------------------------- + \fn csrScanEnable + \brief Enable the scanning feature of CSR. It must be called before any scan request can be performed. + \param tHalHandle - HAL context handle + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanEnable(tpAniSirGlobal); + +/* --------------------------------------------------------------------------- + \fn csrScanDisable + \brief Disabling the scanning feature of CSR. After this function return + success, no scan is performed until a successful to csrScanEnable + \param tHalHandle - HAL context handle + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanDisable(tpAniSirGlobal); +/* --------------------------------------------------------------------------- + \fn csrScanRequest + \brief Request a 11d or full scan. + \param pScanRequestID - pointer to an object to get back the request ID + \param callback - a callback function that scan calls upon finish, will not be called if csrScanRequest returns error + \param pContext - a pointer passed in for the callback + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanRequest(tpAniSirGlobal, tANI_U16, tCsrScanRequest *, + tANI_U32 *pScanRequestID, csrScanCompleteCallback callback, + void *pContext); + +/* --------------------------------------------------------------------------- + \fn csrScanAbort + \brief If a scan request is abort, the scan complete callback will be called first before csrScanAbort returns. + \param pScanRequestID - The request ID returned from csrScanRequest + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanAbort(tpAniSirGlobal, tANI_U32 scanRequestID); + +eHalStatus csrScanSetBGScanparams(tpAniSirGlobal, tCsrBGScanRequest *); +eHalStatus csrScanBGScanAbort(tpAniSirGlobal); + +/* --------------------------------------------------------------------------- + \fn csrScanGetResult + \brief Return scan results. + \param pFilter - If pFilter is NULL, all cached results are returned + \param phResult - an object for the result. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanGetResult(tpAniSirGlobal, tCsrScanResultFilter *pFilter, tScanResultHandle *phResult); + +/* --------------------------------------------------------------------------- + \fn csrScanFlushResult + \brief Clear scan results. + \param pMac - pMac global pointer + \param sessionId - Session Identifier + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanFlushResult(tpAniSirGlobal, tANI_U8 sessionId); +/* --------------------------------------------------------------------------- + * \fn csrScanFilterResults + * \brief Filter scan results based on valid channel list. + * \param pMac - Pointer to Global MAC structure + * \return eHalStatus + *------------------------------------------------------------------------------- + */ +eHalStatus csrScanFilterResults(tpAniSirGlobal pMac); + +eHalStatus csrScanFlushSelectiveResult(tpAniSirGlobal, v_BOOL_t flushP2P); +/* --------------------------------------------------------------------------- + \fn csrScanBGScanGetParam + \brief Returns the current background scan settings. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanBGScanGetParam(tpAniSirGlobal, tCsrBGScanRequest *); + +/* --------------------------------------------------------------------------- + \fn csrScanResultGetFirst + \brief Returns the first element of scan result. + \param hScanResult - returned from csrScanGetResult + \return tCsrScanResultInfo * - NULL if no result + -------------------------------------------------------------------------------*/ +tCsrScanResultInfo *csrScanResultGetFirst(tpAniSirGlobal, tScanResultHandle hScanResult); +/* --------------------------------------------------------------------------- + \fn csrScanResultGetNext + \brief Returns the next element of scan result. It can be called without calling csrScanResultGetFirst first + \param hScanResult - returned from csrScanGetResult + \return Null if no result or reach the end + -------------------------------------------------------------------------------*/ +tCsrScanResultInfo *csrScanResultGetNext(tpAniSirGlobal, tScanResultHandle hScanResult); + +/* --------------------------------------------------------------------------- + \fn csrGetCountryCode + \brief this function is to get the country code current being used + \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return, this has the country code + \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return, + this contains the length of the data in pBuf + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrGetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *pbLen); + +/* --------------------------------------------------------------------------- + \fn csrSetCountryCode + \brief this function is to set the country code so channel/power + setting matches the country code and the domain it belongs to. + \param pCountry - Caller allocated buffer with at least 3 bytes specifying the country code + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrSetCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded); + +/* --------------------------------------------------------------------------- + \fn csrResetCountryCodeInformation + \brief this function is to reset the country code current being used back to EEPROM default + this includes channel list and power setting. + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrResetCountryCodeInformation(tpAniSirGlobal pMac, tANI_BOOLEAN *pfRestartNeeded); + +/* --------------------------------------------------------------------------- + \fn csrGetSupportedCountryCode + \brief this function is to get a list of the country code current being supported + \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return, + this has the country code list. 3 bytes for each country code. This may be NULL if + caller wants to know the needed bytes. + \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return, + this contains the length of the data in pBuf + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrGetSupportedCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U32 *pbLen); + +/* --------------------------------------------------------------------------- + \fn csrSetRegulatoryDomain + \brief this function is to set the current regulatory domain. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + CSR. + \param domainId - indicate the domain (defined in the driver) needs to set to. + See eRegDomainId for definition + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrSetRegulatoryDomain(tpAniSirGlobal pMac, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded); + +/* --------------------------------------------------------------------------- + \fn csrGetCurrentRegulatoryDomain + \brief this function is to get the current regulatory domain. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + CSR. + \return eRegDomainId + -------------------------------------------------------------------------------*/ +v_REGDOMAIN_t csrGetCurrentRegulatoryDomain(tpAniSirGlobal pMac); + +/* --------------------------------------------------------------------------- + \fn csrGetRegulatoryDomainForCountry + \brief this function is to get the regulatory domain for a country. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + CSR. + \param pCountry - Caller allocated buffer with at least 3 bytes specifying the country code + \param pDomainId - Caller allocated buffer to get the return domain ID upon success return. Can be NULL. + \param source - the source of country information. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrGetRegulatoryDomainForCountry(tpAniSirGlobal pMac, + tANI_U8 *pCountry, + v_REGDOMAIN_t *pDomainId, + v_CountryInfoSource_t source); + + +tANI_BOOLEAN csrSave11dCountryString( tpAniSirGlobal pMac, tANI_U8 *pCountryCode, tANI_BOOLEAN fForce ); + +//some support functions +tANI_BOOLEAN csrIs11dSupported(tpAniSirGlobal pMac); +tANI_BOOLEAN csrIs11hSupported(tpAniSirGlobal pMac); +tANI_BOOLEAN csrIs11eSupported(tpAniSirGlobal pMac); +tANI_BOOLEAN csrIsWmmSupported(tpAniSirGlobal pMac); +tANI_BOOLEAN csrIsMCCSupported(tpAniSirGlobal pMac); + +//Upper layer to get the list of the base channels to scan for passively 11d info from csr +eHalStatus csrScanGetBaseChannels( tpAniSirGlobal pMac, tCsrChannelInfo * pChannelInfo ); +//Return SUCCESS is the command is queued, failed +eHalStatus csrQueueSmeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fHighPriority ); +tSmeCmd *csrGetCommandBuffer( tpAniSirGlobal pMac ); +void csrReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csrScanFlushBssEntry(tpAniSirGlobal pMac, + tpSmeCsaOffloadInd pCsaOffloadInd); +#ifdef FEATURE_WLAN_WAPI +tANI_BOOLEAN csrIsProfileWapi( tCsrRoamProfile *pProfile ); +#endif /* FEATURE_WLAN_WAPI */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + +//Security +#define WLAN_SECURITY_EVENT_SET_PTK_REQ 1 +#define WLAN_SECURITY_EVENT_SET_PTK_RSP 2 +#define WLAN_SECURITY_EVENT_SET_GTK_REQ 3 +#define WLAN_SECURITY_EVENT_SET_GTK_RSP 4 +#define WLAN_SECURITY_EVENT_REMOVE_KEY_REQ 5 +#define WLAN_SECURITY_EVENT_REMOVE_KEY_RSP 6 +#define WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND 7 +#define WLAN_SECURITY_EVENT_PMKID_UPDATE 8 +#define WLAN_SECURITY_EVENT_MIC_ERROR 9 + +#define AUTH_OPEN 0 +#define AUTH_SHARED 1 +#define AUTH_WPA_EAP 2 +#define AUTH_WPA_PSK 3 +#define AUTH_WPA2_EAP 4 +#define AUTH_WPA2_PSK 5 +#ifdef FEATURE_WLAN_WAPI +#define AUTH_WAPI_CERT 6 +#define AUTH_WAPI_PSK 7 +#endif /* FEATURE_WLAN_WAPI */ + +#define ENC_MODE_OPEN 0 +#define ENC_MODE_WEP40 1 +#define ENC_MODE_WEP104 2 +#define ENC_MODE_TKIP 3 +#define ENC_MODE_AES 4 +#ifdef FEATURE_WLAN_WAPI +#define ENC_MODE_SMS4 5 //WAPI +#endif /* FEATURE_WLAN_WAPI */ + +#define NO_MATCH 0 +#define MATCH 1 + +#define WLAN_SECURITY_STATUS_SUCCESS 0 +#define WLAN_SECURITY_STATUS_FAILURE 1 + +//Scan +#define WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ 1 +#define WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP 2 +#define WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ 3 +#define WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP 4 +#define WLAN_SCAN_EVENT_HO_SCAN_REQ 5 +#define WLAN_SCAN_EVENT_HO_SCAN_RSP 6 + +#define WLAN_SCAN_STATUS_SUCCESS 0 +#define WLAN_SCAN_STATUS_FAILURE 1 +#define WLAN_SCAN_STATUS_ABORT 2 + +//Ibss +#define WLAN_IBSS_EVENT_START_IBSS_REQ 0 +#define WLAN_IBSS_EVENT_START_IBSS_RSP 1 +#define WLAN_IBSS_EVENT_JOIN_IBSS_REQ 2 +#define WLAN_IBSS_EVENT_JOIN_IBSS_RSP 3 +#define WLAN_IBSS_EVENT_COALESCING 4 +#define WLAN_IBSS_EVENT_PEER_JOIN 5 +#define WLAN_IBSS_EVENT_PEER_LEAVE 6 +#define WLAN_IBSS_EVENT_STOP_REQ 7 +#define WLAN_IBSS_EVENT_STOP_RSP 8 + +#define AUTO_PICK 0 +#define SPECIFIED 1 + +#define WLAN_IBSS_STATUS_SUCCESS 0 +#define WLAN_IBSS_STATUS_FAILURE 1 + +//11d +#define WLAN_80211D_EVENT_COUNTRY_SET 0 +#define WLAN_80211D_EVENT_RESET 1 + +#define WLAN_80211D_DISABLED 0 +#define WLAN_80211D_SUPPORT_MULTI_DOMAIN 1 +#define WLAN_80211D_NOT_SUPPORT_MULTI_DOMAIN 2 + +int diagAuthTypeFromCSRType(eCsrAuthType authType); +int diagEncTypeFromCSRType(eCsrEncryptionType encType); +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +/* --------------------------------------------------------------------------- + \fn csrScanResultPurge + \brief remove all items(tCsrScanResult) in the list and free memory for each item + \param hScanResult - returned from csrScanGetResult. hScanResult is considered gone by + calling this function and even before this function returns. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrScanResultPurge(tpAniSirGlobal pMac, tScanResultHandle hScanResult); + + +///////////////////////////////////////////Common Scan ends + +/* --------------------------------------------------------------------------- + \fn csrRoamConnect + \brief To initiate an association + \param pProfile - can be NULL to join to any open ones + \param hBssListIn - a list of BSS descriptor to roam to. It is returned from csrScanGetResult + \param pRoamId - to get back the request ID + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tScanResultHandle hBssListIn, tANI_U32 *pRoamId); + +/* --------------------------------------------------------------------------- + \fn csrRoamReassoc + \brief To initiate a re-association + \param pProfile - can be NULL to join the currently connected AP. In that + case modProfileFields should carry the modified field(s) which could trigger + reassoc + \param modProfileFields - fields which are part of tCsrRoamConnectedProfile + that might need modification dynamically once STA is up & running and this + could trigger a reassoc + \param pRoamId - to get back the request ID + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + tANI_U32 *pRoamId); + + +/* --------------------------------------------------------------------------- + \fn csrRoamReconnect + \brief To disconnect and reconnect with the same profile + \return eHalStatus. It returns fail if currently not connected + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamReconnect(tpAniSirGlobal pMac, tANI_U32 sessionId); + +/* --------------------------------------------------------------------------- + \fn csrRoamSetPMKIDCache + \brief return the PMKID candidate list + \param pPMKIDCache - caller allocated buffer point to an array of tPmkidCacheInfo + \param numItems - A variable that has the number of tPmkidCacheInfo allocated + when returning, this is either the number needed or + number of items put into pPMKIDCache + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough and pNumItems + has the number of tPmkidCacheInfo. + \Note: pNumItems is a number of tPmkidCacheInfo, not sizeof(tPmkidCacheInfo) * something + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamSetPMKIDCache( tpAniSirGlobal pMac, tANI_U32 sessionId, + tPmkidCacheInfo *pPMKIDCache, + tANI_U32 numItems, + tANI_BOOLEAN update_entire_cache ); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* --------------------------------------------------------------------------- + *\fn csrRoamSetPSK_PMK + *\brief store PSK/PMK + *\param pMac - pointer to global structure for MAC + *\param sessionId - Sme session id + *\param pPSK_PMK - pointer to an array of Psk/Pmk + *\return eHalStatus - usually it succeed unless sessionId is not found + *\Note: + *-------------------------------------------------------------------------------*/ +eHalStatus csrRoamSetPSK_PMK(tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_U8 *pPSK_PMK, size_t pmk_len); + +/* --------------------------------------------------------------------------- + *\fn csrRoamSetKeyMgmtOffload + *\brief sets nRoamKeyMgmtOffloadEnabled + *\param pMac - pointer to global structure for MAC + *\param sessionId - Sme session id + *\param nRoamKeyMgmtOffloadEnabled - value of key mgmt offload enable + *\return eHalStatus - usually it succeed unless sessionId is not found + *\Note: + *-------------------------------------------------------------------------------*/ +eHalStatus csrRoamSetKeyMgmtOffload(tpAniSirGlobal pMac, + tANI_U32 sessionId, + v_BOOL_t nRoamKeyMgmtOffloadEnabled); +#endif +/* --------------------------------------------------------------------------- + \fn csrRoamGetWpaRsnReqIE + \brief return the WPA or RSN IE CSR passes to PE to JOIN request or START_BSS request + \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the + needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetWpaRsnReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetWpaRsnRspIE + \brief return the WPA or RSN IE from the beacon or probe rsp if connected + \param pLen - caller allocated memory that has the length of pBuf as input. Upon returned, *pLen has the + needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetWpaRsnRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf); + + +/* --------------------------------------------------------------------------- + \fn csrRoamGetNumPMKIDCache + \brief return number of PMKID cache entries + \return tANI_U32 - the number of PMKID cache entries + -------------------------------------------------------------------------------*/ +tANI_U32 csrRoamGetNumPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetPMKIDCache + \brief return PMKID cache from CSR + \param pNum - caller allocated memory that has the space of the number of pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the + needed or actually number in tPmkidCacheInfo. + \param pPmkidCache - Caller allocated memory that contains PMKID cache, if any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId, + tANI_U32 *pNum, tPmkidCacheInfo *pPmkidCache); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetConnectProfile + \brief To return the current connect profile. Caller must call csrRoamFreeConnectProfile + after it is done and before reuse for another csrRoamGetConnectProfile call. + \param pProfile - pointer to a caller allocated structure tCsrRoamConnectedProfile + \return eHalStatus. Failure if not connected + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamConnectedProfile *pProfile); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetConnectState + \brief To return the current connect state of Roaming + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamGetConnectState(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrConnectState *pState); + +/* --------------------------------------------------------------------------- + \fn csrRoamFreeConnectProfile + \brief To free and reinitialize the profile return previous by csrRoamGetConnectProfile. + \param pProfile - pointer to a caller allocated structure tCsrRoamConnectedProfile + \return eHalStatus. + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamFreeConnectProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile); + +/* --------------------------------------------------------------------------- + \fn csrInitChannelList + \brief HDD calls this function to set the WNI_CFG_VALID_CHANNEL_LIST base on the band/mode settings. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + CSR. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrInitChannelList( tHalHandle hHal ); + +/* --------------------------------------------------------------------------- + \fn csrChangeConfigParams + \brief The CSR API exposed for HDD to provide config params to CSR during + SMEs stop -> start sequence. + If HDD changed the domain that will cause a reset. This function will + provide the new set of 11d information for the new domain. Currently this + API provides info regarding 11d only at reset but we can extend this for + other params (PMC, QoS) which needs to be initialized again at reset. + \param + hHal - Handle to the HAL. The HAL handle is returned by the HAL after it is + opened (by calling halOpen). + pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that + currently provides 11d related information like Country code, + Regulatory domain, valid channel list, Tx power per channel, a + list with active/passive scan allowed per valid channel. + + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrChangeConfigParams(tpAniSirGlobal pMac, + tCsrUpdateConfigParam *pUpdateConfigParam); + +/* --------------------------------------------------------------------------- + \fn csrRoamConnectToLastProfile + \brief To disconnect and reconnect with the same profile + \return eHalStatus. It returns fail if currently connected + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamConnectToLastProfile(tpAniSirGlobal pMac, tANI_U32 sessionId); + +/* --------------------------------------------------------------------------- + \fn csrRoamDisconnect + \brief To disconnect from a network + \param reason -- To indicate the reason for disconnecting. Currently, + only eCSR_DISCONNECT_REASON_MIC_ERROR is meaningful. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrRoamDisconnect(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason); + +/* --------------------------------------------------------------------------- + \fn csrScanGetPMKIDCandidateList + \brief return the PMKID candidate list + \param pPmkidList - caller allocated buffer point to an array of tPmkidCandidateInfo + \param pNumItems - pointer to a variable that has the number of + tPmkidCandidateInfo allocated when returning, this is + either the number needed or number of items put into + pPmkidList. + \return eHalStatus - when fail, it usually means the buffer allocated is not big enough and pNumItems + has the number of tPmkidCandidateInfo. + \Note: pNumItems is a number of tPmkidCandidateInfo, not sizeof(tPmkidCandidateInfo) * something + -------------------------------------------------------------------------------*/ +eHalStatus csrScanGetPMKIDCandidateList(tpAniSirGlobal pMac, tANI_U32 sessionId, + tPmkidCandidateInfo *pPmkidList, tANI_U32 *pNumItems ); + +//This function is used to stop a BSS. It is similar of csrRoamIssueDisconnect but this function +//doesn't have any logic other than blindly trying to stop BSS +eHalStatus csrRoamIssueStopBssCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN fHighPriority ); + +void csrCallRoamingCompletionCallback(tpAniSirGlobal pMac, tCsrRoamSession *pSession, + tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, eCsrRoamResult roamResult); + +/* --------------------------------------------------------------------------- + \fn csrRoamIssueDisassociateStaCmd + \brief csr function that HDD calls to disassociate a associated station + \param sessionId - session Id for Soft AP + \param pPeerMacAddr - MAC of associated station to delete + \param reason - reason code, be one of the tSirMacReasonCodes + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamIssueDisassociateStaCmd(tpAniSirGlobal pMac, + tANI_U32 sessionId, + struct tagCsrDelStaParams *pDelStaParams); + +/* --------------------------------------------------------------------------- + \fn csrRoamIssueDeauthSta + \brief csr function that HDD calls to delete a associated station + \param sessionId - session Id for Soft AP + \param pDelStaParams- Pointer to parameters of the station to deauthenticate + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamIssueDeauthStaCmd( tpAniSirGlobal pMac, + tANI_U32 sessionId, + struct tagCsrDelStaParams *pDelStaParams); + +/* --------------------------------------------------------------------------- + \fn csrRoamIssueTkipCounterMeasures + \brief csr function that HDD calls to start and stop tkip countermeasures + \param sessionId - session Id for Soft AP + \param bEnable - Flag to start/stop countermeasures + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamIssueTkipCounterMeasures( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN bEnable); + +eHalStatus csrSendMBTkipCounterMeasuresReqMsg( tpAniSirGlobal pMac, tANI_U32 sessinId, tANI_BOOLEAN bEnable, tSirMacAddr bssId ); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetAssociatedStas + \brief csr function that HDD calls to get list of associated stations based on module ID + \param sessionId - session Id for Soft AP + \param modId - module ID - PE/HAL/TL + \param pUsrContext - Opaque HDD context + \param pfnSapEventCallback - Sap event callback in HDD + \param pAssocStasBuf - Caller allocated memory to be filled with associated + stations info + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamGetAssociatedStas( tpAniSirGlobal pMac, tANI_U32 sessionId, VOS_MODULE_ID modId, + void *pUsrContext, void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf ); + +eHalStatus csrSendMBGetAssociatedStasReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, VOS_MODULE_ID modId, tSirMacAddr bssId, + void *pUsrContext, void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf ); + +/* --------------------------------------------------------------------------- + \fn csrRoamGetWpsSessionOverlap + \brief csr function that HDD calls to get WPS PBC session overlap information + \param sessionId - session Id for Soft AP + \param pUsrContext - Opaque HDD context + \param pfnSapEventCallback - Sap event callback in HDD + \param pRemoveMac - pointer to MAC address of session to be removed + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus csrRoamGetWpsSessionOverlap( tpAniSirGlobal pMac, tANI_U32 sessionId, + void *pUsrContext, void *pfnSapEventCallback,v_MACADDR_t pRemoveMac ); + +eHalStatus csrSendMBGetWPSPBCSessions( tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr bssId, void *pUsrContext, void *pfnSapEventCallback,v_MACADDR_t pRemoveMac); + +/* --------------------------------------------------------------------------- + \fn csrSendChngMCCBeaconInterval + \brief csr function that HDD calls to send Update beacon interval + \param sessionId - session Id for Soft AP + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus +csrSendChngMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U32 sessionId); + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* --------------------------------------------------------------------------- + \fn csrRoamFTPreAuthRspProcessor + \brief csr function that handles pre auth response from LIM + ---------------------------------------------------------------------------*/ +void csrRoamFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp ); +#endif + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +void csrEseSendAdjacentApRepMsg(tpAniSirGlobal pMac, tCsrRoamSession *pSession); +#endif + +#if defined(FEATURE_WLAN_ESE) +void UpdateCCKMTSF(tANI_U32 *timeStamp0, tANI_U32 *timeStamp1, tANI_U32 *incr); +#endif + +eHalStatus csrGetDefaultCountryCodeFrmNv(tpAniSirGlobal pMac, tANI_U8 *pCountry); +eHalStatus csrGetCurrentCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry); + + +eHalStatus csrRoamEnqueuePreauth(tpAniSirGlobal pMac, tANI_U32 sessionId, tpSirBssDescription pBssDescription, + eCsrRoamReason reason, tANI_BOOLEAN fImmediate); +eHalStatus csrDequeueRoamCommand(tpAniSirGlobal pMac, eCsrRoamReason reason); +#ifdef FEATURE_WLAN_LFR +void csrInitOccupiedChannelsList(tpAniSirGlobal pMac, tANI_U8 sessionId); +tANI_BOOLEAN csrNeighborRoamIsNewConnectedProfile(tpAniSirGlobal pMac, + tANI_U8 sessionId); +tANI_BOOLEAN csrNeighborRoamConnectedProfileMatch(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tCsrScanResult *pResult, + tDot11fBeaconIEs *pIes); +#endif +eHalStatus csrSetTxPower(tpAniSirGlobal pMac, v_U8_t sessionId, v_U8_t mW); + +eHalStatus csrScanCreateEntryInScanCache(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrBssid bssid, tANI_U8 channel); + +eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac); +eHalStatus csrRoamDelPMKIDfromCache(tpAniSirGlobal pMac, + tANI_U32 sessionId, + const tANI_U8 *pBSSId, + tANI_BOOLEAN flush_cache); + +tANI_BOOLEAN csrElectedCountryInfo(tpAniSirGlobal pMac); +void csrAddVoteForCountryInfo(tpAniSirGlobal pMac, tANI_U8 *pCountryCode); +void csrClearVotesForCountryInfo(tpAniSirGlobal pMac); + +#endif +eHalStatus csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, + uint32_t channel, uint8_t session_id); + +boolean is_disconnect_pending(tpAniSirGlobal pmac, uint8_t sessionid); + +#ifdef QCA_HT_2040_COEX +eHalStatus csrSetHT2040Mode(tpAniSirGlobal pMac, tANI_U32 sessionId, + ePhyChanBondState cbMode, tANI_BOOLEAN obssEnabled); +#endif +tSirBssDescription* +csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, + tSirBssDescription *bss_descr); +eHalStatus csr_prepare_disconnect_command(tpAniSirGlobal mac, + tANI_U32 session_id, tSmeCmd **sme_cmd); diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLinkList.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLinkList.c new file mode 100644 index 000000000000..8a81a344e4b1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLinkList.c @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csrLinkList.c + + Implementation for the Common link list interfaces. +========================================================================== */ + +#include "palApi.h" +#include "csrLinkList.h" +#include "vos_lock.h" +#include "vos_memory.h" +#include "vos_trace.h" +#include "vos_timer.h" + + +ANI_INLINE_FUNCTION void csrListInit(tListElem *pList) +{ + pList->last = pList->next = pList; +} + + +ANI_INLINE_FUNCTION void csrListRemoveEntry(tListElem *pEntry) +{ + tListElem *pLast; + tListElem *pNext; + + pLast = pEntry->last; + pNext = pEntry->next; + pLast->next = pNext; + pNext->last = pLast; +} + + +ANI_INLINE_FUNCTION tListElem * csrListRemoveHead(tListElem *pHead) +{ + tListElem *pEntry; + tListElem *pNext; + + pEntry = pHead->next; + pNext = pEntry->next; + pHead->next = pNext; + pNext->last = pHead; + + return (pEntry); +} + + + +ANI_INLINE_FUNCTION tListElem * csrListRemoveTail(tListElem *pHead) +{ + tListElem *pEntry; + tListElem *pLast; + + pEntry = pHead->last; + pLast = pEntry->last; + pHead->last = pLast; + pLast->next = pHead; + + return (pEntry); +} + + +ANI_INLINE_FUNCTION void csrListInsertTail(tListElem *pHead, tListElem *pEntry) +{ + tListElem *pLast; + + pLast = pHead->last; + pEntry->last = pLast; + pEntry->next = pHead; + pLast->next = pEntry; + pHead->last = pEntry; +} + + +ANI_INLINE_FUNCTION void csrListInsertHead(tListElem *pHead, tListElem *pEntry) +{ + tListElem *pNext; + + pNext = pHead->next; + pEntry->next = pNext; + pEntry->last = pHead; + pNext->last = pEntry; + pHead->next = pEntry; +} + + +//Insert pNewEntry before pEntry +void csrListInsertEntry(tListElem *pEntry, tListElem *pNewEntry) +{ + tListElem *pLast; + if( !pEntry) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pEntry is Null", __func__); + return; + } + + pLast = pEntry->last; + pLast->next = pNewEntry; + pEntry->last = pNewEntry; + pNewEntry->next = pEntry; + pNewEntry->last = pLast; +} + +tANI_U32 csrLLCount( tDblLinkList *pList ) +{ + tANI_U32 c = 0; + + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return c; + } + + if ( pList && ( LIST_FLAG_OPEN == pList->Flag ) ) + { + c = pList->Count; + } + + return( c ); +} + + +void csrLLLock( tDblLinkList *pList ) +{ + + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + vos_lock_acquire(&pList->Lock); + } +} + + +void csrLLUnlock( tDblLinkList *pList ) +{ + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + vos_lock_release(&pList->Lock); + } +} + + +tANI_BOOLEAN csrLLIsListEmpty( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ) +{ + tANI_BOOLEAN fEmpty = eANI_BOOLEAN_TRUE; + + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return fEmpty ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if(fInterlocked) + { + csrLLLock(pList); + } + + fEmpty = csrIsListEmpty( &pList->ListHead ); + + if(fInterlocked) + { + csrLLUnlock(pList); + } + } + return( fEmpty ); +} + + + +tANI_BOOLEAN csrLLFindEntry( tDblLinkList *pList, tListElem *pEntryToFind ) +{ + tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE; + tListElem *pEntry; + + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return fFound ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK); + + // Have to make sure we don't loop back to the head of the list, which will + // happen if the entry is NOT on the list... + + while( pEntry && ( pEntry != &pList->ListHead ) ) + { + if ( pEntry == pEntryToFind ) + { + fFound = eANI_BOOLEAN_TRUE; + break; + } + pEntry = pEntry->next; + } + + } + return( fFound ); +} + + +eHalStatus csrLLOpen( tHddHandle hHdd, tDblLinkList *pList ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return eHAL_STATUS_FAILURE ; + } + + if ( LIST_FLAG_OPEN != pList->Flag ) + { + pList->Count = 0; + pList->cmdTimeoutTimer = NULL; + vosStatus = vos_lock_init(&pList->Lock); + + if(VOS_IS_STATUS_SUCCESS(vosStatus)) + { + csrListInit( &pList->ListHead ); + pList->Flag = LIST_FLAG_OPEN; + pList->hHdd = hHdd; + } + else + { + status = eHAL_STATUS_FAILURE; + } + } + return (status); +} + +void csrLLClose( tDblLinkList *pList ) +{ + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + // Make sure the list is empty... + csrLLPurge( pList, LL_ACCESS_LOCK ); + vos_lock_destroy( &pList->Lock ); + pList->Flag = LIST_FLAG_CLOSE; + } +} + +void csrLLInsertTail( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ) +{ + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if(fInterlocked) + { + csrLLLock(pList); + } + csrListInsertTail( &pList->ListHead, pEntry ); + pList->Count++; + if(fInterlocked) + { + csrLLUnlock(pList); + } + } +} + + + +void csrLLInsertHead( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ) +{ + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if(fInterlocked) + { + csrLLLock(pList); + } + csrListInsertHead( &pList->ListHead, pEntry ); + pList->Count++; + if(fInterlocked) + { + csrLLUnlock(pList); + } + if ( pList->cmdTimeoutTimer && pList->cmdTimeoutDuration ) + { + /* timer to detect pending command in activelist*/ + vos_timer_start( pList->cmdTimeoutTimer, + pList->cmdTimeoutDuration); + } + } +} + + +void csrLLInsertEntry( tDblLinkList *pList, tListElem *pEntry, tListElem *pNewEntry, tANI_BOOLEAN fInterlocked ) +{ + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if(fInterlocked) + { + csrLLLock(pList); + } + csrListInsertEntry( pEntry, pNewEntry ); + pList->Count++; + if(fInterlocked) + { + csrLLUnlock(pList); + } + } +} + + + +tListElem *csrLLRemoveTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pEntry = NULL; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return pEntry ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + if ( !csrIsListEmpty(&pList->ListHead) ) + { + + pEntry = csrListRemoveTail( &pList->ListHead ); + pList->Count--; + } + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } + + return( pEntry ); +} + + +tListElem *csrLLPeekTail( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pEntry = NULL; + + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return pEntry ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + if ( !csrIsListEmpty(&pList->ListHead) ) + { + pEntry = pList->ListHead.last; + } + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } + + return( pEntry ); +} + + + +tListElem *csrLLRemoveHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pEntry = NULL; + + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return pEntry ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + if ( !csrIsListEmpty(&pList->ListHead) ) + { + pEntry = csrListRemoveHead( &pList->ListHead ); + pList->Count--; + } + + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } + + return( pEntry ); +} + + +tListElem *csrLLPeekHead( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pEntry = NULL; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return pEntry ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + if ( !csrIsListEmpty(&pList->ListHead) ) + { + pEntry = pList->ListHead.next; + } + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } + + return( pEntry ); +} + + + +void csrLLPurge( tDblLinkList *pList, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pEntry; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + while( (pEntry = csrLLRemoveHead( pList, LL_ACCESS_NOLOCK )) ) + { + // just remove everything from the list until + // nothing left on the list. + } + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } +} + + +tANI_BOOLEAN csrLLRemoveEntry( tDblLinkList *pList, tListElem *pEntryToRemove, tANI_BOOLEAN fInterlocked ) +{ + tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE; + tListElem *pEntry; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return fFound; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + pEntry = csrLLPeekHead( pList, LL_ACCESS_NOLOCK ); + + // Have to make sure we don't loop back to the head of the list, which will + // happen if the entry is NOT on the list... + while( pEntry && ( pEntry != &pList->ListHead ) ) + { + if ( pEntry == pEntryToRemove ) + { + csrListRemoveEntry( pEntry ); + pList->Count--; + + fFound = eANI_BOOLEAN_TRUE; + break; + } + + pEntry = pEntry->next; + } + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + if ( pList->cmdTimeoutTimer ) + { + vos_timer_stop(pList->cmdTimeoutTimer); + } + } + + return( fFound ); +} + + + +tListElem *csrLLNext( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pNextEntry = NULL; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return pNextEntry ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + if ( !csrIsListEmpty(&pList->ListHead) && csrLLFindEntry( pList, pEntry ) ) + { + pNextEntry = pEntry->next; + //Make sure we don't walk past the head + if ( pNextEntry == &pList->ListHead ) + { + pNextEntry = NULL; + } + } + + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } + + return( pNextEntry ); +} + + +tListElem *csrLLPrevious( tDblLinkList *pList, tListElem *pEntry, tANI_BOOLEAN fInterlocked ) +{ + tListElem *pNextEntry = NULL; + + if( !pList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,"%s: Error!! pList is Null", __func__); + return pNextEntry ; + } + + if ( LIST_FLAG_OPEN == pList->Flag ) + { + if ( fInterlocked ) + { + csrLLLock( pList ); + } + + if ( !csrIsListEmpty(&pList->ListHead) && csrLLFindEntry( pList, pEntry ) ) + { + pNextEntry = pEntry->last; + //Make sure we don't walk past the head + if ( pNextEntry == &pList->ListHead ) + { + pNextEntry = NULL; + } + } + + if ( fInterlocked ) + { + csrLLUnlock( pList ); + } + } + + return( pNextEntry ); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLogDump.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLogDump.c new file mode 100644 index 000000000000..0a64afd38235 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrLogDump.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ +csrLogDump.c +Implements the dump commands specific to the csr module. +============================================================================*/ +#include "aniGlobal.h" +#include "csrApi.h" +#include "btcApi.h" +#include "logDump.h" +#include "smsDebug.h" +#include "smeInside.h" +#include "csrInsideApi.h" +#if defined(ANI_LOGDUMP) +static char * +dump_csr( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p ) +{ + static tCsrRoamProfile x; + static tSirMacSSid ssid; //To be allocated for array of SSIDs + static tANI_U8 sessionId; // Defined for fixed session ID + vos_mem_set((void*)&x, sizeof(x), 0); + x.SSIDs.numOfSSIDs=1 ; + x.SSIDs.SSIDList[0].SSID = ssid ; + ssid.length=6 ; + vos_mem_copy(ssid.ssId, "AniNet", 6); + if(HAL_STATUS_SUCCESS(sme_AcquireGlobalLock( &pMac->sme ))) + { + (void)csrRoamConnect(pMac, sessionId, &x, NULL, NULL); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return p; +} +static char *dump_btcSetEvent( tpAniSirGlobal pMac, tANI_U32 arg1, + tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p ) +{ + tSmeBtEvent btEvent; + if( arg1 < BT_EVENT_TYPE_MAX ) + { + smsLog(pMac, LOGE, FL(" signal BT event (%d) handle (%d) 3rd param(%d)"), arg1, arg2, arg3); + vos_mem_zero(&btEvent, sizeof(tSmeBtEvent)); + btEvent.btEventType = arg1; + switch( arg1 ) + { + case BT_EVENT_SYNC_CONNECTION_COMPLETE: + case BT_EVENT_SYNC_CONNECTION_UPDATED: + btEvent.uEventParam.btSyncConnection.connectionHandle = (v_U16_t)arg2; + btEvent.uEventParam.btSyncConnection.status = (v_U8_t)arg3; + break; + case BT_EVENT_DISCONNECTION_COMPLETE: + btEvent.uEventParam.btDisconnect.connectionHandle = (v_U16_t)arg2; + break; + case BT_EVENT_CREATE_ACL_CONNECTION: + case BT_EVENT_ACL_CONNECTION_COMPLETE: + btEvent.uEventParam.btAclConnection.connectionHandle = (v_U16_t)arg2; + btEvent.uEventParam.btAclConnection.status = (v_U8_t)arg3; + break; + case BT_EVENT_MODE_CHANGED: + btEvent.uEventParam.btAclModeChange.connectionHandle = (v_U16_t)arg2; + break; + default: + break; + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if(HAL_STATUS_SUCCESS(sme_AcquireGlobalLock( &pMac->sme ))) + { + btcSignalBTEvent(pMac, &btEvent); + sme_ReleaseGlobalLock( &pMac->sme ); + } +#endif + } + else + { + smsLog(pMac, LOGE, FL(" invalid event (%d)"), arg1); + } + return p; +} +static char* dump_csrApConcScanParams( tpAniSirGlobal pMac, tANI_U32 arg1, + tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p ) +{ + if( arg1 ) + { + pMac->roam.configParam.nRestTimeConc = arg1; + } + if( arg2 ) + { + pMac->roam.configParam.nActiveMinChnTimeConc = arg2; + } + if( arg3 ) + { + pMac->roam.configParam.nActiveMaxChnTimeConc = arg3; + } + + smsLog(pMac, LOGE, FL(" Working %d %d %d"), (int) pMac->roam.configParam.nRestTimeConc, + (int)pMac->roam.configParam.nActiveMinChnTimeConc, (int) pMac->roam.configParam.nActiveMaxChnTimeConc); + return p; +} + +static tDumpFuncEntry csrMenuDumpTable[] = { + {0, "CSR (850-860)", NULL}, + {851, "CSR: CSR testing connection to AniNet", dump_csr}, + {852, "BTC: Fake BT events (event, handle)", dump_btcSetEvent}, + {853, "CSR: Split Scan related params", dump_csrApConcScanParams}, +}; + +void csrDumpInit(tHalHandle hHal) +{ + logDumpRegisterTable( (tpAniSirGlobal)hHal, &csrMenuDumpTable[0], + sizeof(csrMenuDumpTable)/sizeof(csrMenuDumpTable[0]) ); +} + +#endif //#if defined(ANI_LOGDUMP) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c new file mode 100644 index 000000000000..e983f9e125ed --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c @@ -0,0 +1,6341 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrNeighborRoam.c + + Implementation for the simple roaming algorithm for 802.11r Fast transitions and Legacy roaming for Android platform. +========================================================================== */ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- +08/01/10 Murali Created + +===========================================================================*/ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "wlan_qct_wda.h" +#include "palApi.h" +#include "csrInsideApi.h" +#include "smsDebug.h" +#include "logDump.h" +#include "smeQosInternal.h" +#include "wlan_qct_tl.h" +#include "smeInside.h" +#include "vos_diag_core_event.h" +#include "vos_diag_core_log.h" +#include "csrApi.h" +#include "wlan_qct_tl.h" +#include "sme_Api.h" +#include "csrNeighborRoam.h" +#include "macTrace.h" +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "csrEse.h" +#endif + +#define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG +#define NEIGHBOR_ROAM_DEBUG smsLog +#else +#define NEIGHBOR_ROAM_DEBUG(x...) +#endif + +static void csrNeighborRoamResetChannelInfo(tpCsrNeighborRoamChannelInfo rChInfo); +static void csrNeighborRoamResetCfgListChanScanControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId); +static void csrNeighborRoamResetPreauthControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId); +static void csrNeighborRoamDeregAllRssiIndication(tpAniSirGlobal pMac, + tANI_U8 sessionId); + +VOS_STATUS csrNeighborRoamNeighborLookupUPCallback (v_PVOID_t pAdapter, v_U8_t rssiNotification, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi); +VOS_STATUS csrNeighborRoamNeighborLookupDOWNCallback (v_PVOID_t pAdapter, v_U8_t rssiNotification, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi); +void csrNeighborRoamRRMNeighborReportResult(void *context, VOS_STATUS vosStatus); +eHalStatus csrRoamCopyConnectedProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pDstProfile ); + +#ifdef WLAN_FEATURE_VOWIFI_11R +static eHalStatus csrNeighborRoamIssuePreauthReq(tpAniSirGlobal pMac, + tANI_U8 sessionId); +VOS_STATUS csrNeighborRoamIssueNeighborRptRequest(tpAniSirGlobal pMac, + tANI_U8 sessionId); +#endif + +v_U8_t *csrNeighborRoamStateToString(v_U8_t state) +{ + switch(state) + { + CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_CLOSED ); + CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_INIT ); + CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_CONNECTED ); + CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN ); + CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING ); + CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY ); + 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 ); + default: + return "eCSR_NEIGHBOR_ROAM_STATE_UNKNOWN"; + } + +} + +/* State Transition macro */ +#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(newState, sessionId)\ +{\ + pMac->roam.neighborRoamInfo[sessionId].prevNeighborRoamState = \ + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState;\ + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState = newState;\ + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, \ + FL("Session id(%d) Neighbor Roam Transition from state %s ==> %s"), \ + sessionId, \ + csrNeighborRoamStateToString ( \ + pMac->roam.neighborRoamInfo[sessionId].prevNeighborRoamState), \ + csrNeighborRoamStateToString (newState));\ +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamFreeNeighborRoamBSSNode + + \brief This function frees all the internal pointers CSR NeighborRoam BSS Info + and also frees the node itself + + \param pMac - The handle returned by macOpen. + neighborRoamBSSNode - Neighbor Roam BSS Node to be freed + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamFreeNeighborRoamBSSNode(tpAniSirGlobal pMac, tpCsrNeighborRoamBSSInfo neighborRoamBSSNode) +{ + if (neighborRoamBSSNode) + { + if (neighborRoamBSSNode->pBssDescription) + { + vos_mem_free(neighborRoamBSSNode->pBssDescription); + neighborRoamBSSNode->pBssDescription = NULL; + } + vos_mem_free(neighborRoamBSSNode); + neighborRoamBSSNode = NULL; + } + + return; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamRemoveRoamableAPListEntry + + \brief This function removes a given entry from the given list + + \param pMac - The handle returned by macOpen. + pList - The list from which the entry should be removed + pNeighborEntry - Neighbor Roam BSS Node to be removed + + \return TRUE if successfully removed, else FALSE + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamRemoveRoamableAPListEntry(tpAniSirGlobal pMac, + tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry) +{ + if(pList) + { + return csrLLRemoveEntry(pList, &pNeighborEntry->List, LL_ACCESS_LOCK); + } + + smsLog(pMac, LOGE, FL("Removing neighbor BSS node from list failed. Current count = %d"), csrLLCount(pList)); + + return eANI_BOOLEAN_FALSE; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamGetRoamableAPListNextEntry + + \brief Gets the entry next to passed entry. If NULL is passed, return the entry in the head of the list + + \param pMac - The handle returned by macOpen. + pList - The list from which the entry should be returned + pNeighborEntry - Neighbor Roam BSS Node whose next entry should be returned + + \return Neighbor Roam BSS Node to be returned + +---------------------------------------------------------------------------*/ +tpCsrNeighborRoamBSSInfo csrNeighborRoamGetRoamableAPListNextEntry(tpAniSirGlobal pMac, + tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry) +{ + tListElem *pEntry = NULL; + tpCsrNeighborRoamBSSInfo pResult = NULL; + + if(pList) + { + if(NULL == pNeighborEntry) + { + pEntry = csrLLPeekHead(pList, LL_ACCESS_LOCK); + } + else + { + pEntry = csrLLNext(pList, &pNeighborEntry->List, LL_ACCESS_LOCK); + } + if(pEntry) + { + pResult = GET_BASE_ADDR(pEntry, tCsrNeighborRoamBSSInfo, List); + } + } + + return pResult; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamFreeRoamableBSSList + + \brief Empties and frees all the nodes in the roam able AP list + + \param pMac - The handle returned by macOpen. + pList - Neighbor Roam BSS List to be emptied + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamFreeRoamableBSSList(tpAniSirGlobal pMac, tDblLinkList *pList) +{ + tpCsrNeighborRoamBSSInfo pResult = NULL; + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Emptying the BSS list. Current count = %d"), csrLLCount(pList)); + + /* Pick up the head, remove and free the node till the list becomes empty */ + while ((pResult = csrNeighborRoamGetRoamableAPListNextEntry(pMac, pList, NULL)) != NULL) + { + csrNeighborRoamRemoveRoamableAPListEntry(pMac, pList, pResult); + csrNeighborRoamFreeNeighborRoamBSSNode(pMac, pResult); + } + return; +} + +static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; +#ifdef WLAN_FEATURE_VOWIFI_11R + if ((pNeighborRoamInfo->is11rAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) + { + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) || + (eSME_ROAM_TRIGGER_FAST_ROAM == pNeighborRoamInfo->cfgRoamEn)) + { + csrNeighborRoamIssuePreauthReq(pMac, sessionId); + pNeighborRoamInfo->cfgRoamEn = eSME_ROAM_TRIGGER_NONE; + vos_mem_set(&pNeighborRoamInfo->cfgRoambssId[0], + sizeof(pNeighborRoamInfo->cfgRoambssId), + 0xFF); + } + else + { + smsLog(pMac, LOGE, FL("11R Reassoc indication received in unexpected state %s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + VOS_ASSERT(0); + } + } + else +#endif + +#ifdef FEATURE_WLAN_ESE + if ((pNeighborRoamInfo->isESEAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) + { + if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) + { + csrNeighborRoamIssuePreauthReq(pMac, sessionId); + } + else + { + smsLog(pMac, LOGE, FL("CCX Reassoc indication received in unexpected state %s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + VOS_ASSERT(0); + } + } + else +#endif +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsFastRoamEnabled(pMac, sessionId)) + { + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + || csrRoamIsRoamOffloadScanEnabled(pMac) || + (eSME_ROAM_TRIGGER_FAST_ROAM == pNeighborRoamInfo->cfgRoamEn) +#endif + ) + { + csrNeighborRoamIssuePreauthReq(pMac, sessionId); + pNeighborRoamInfo->cfgRoamEn = eSME_ROAM_TRIGGER_NONE; + vos_mem_set(&pNeighborRoamInfo->cfgRoambssId[0], + sizeof(pNeighborRoamInfo->cfgRoambssId), + 0xFF); + } + else + { + smsLog(pMac, LOGE, FL("LFR Reassoc indication received in unexpected state %s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + VOS_ASSERT(0); + } + } + else +#endif + { + if (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pNeighborRoamInfo->neighborRoamState) + { + csrNeighborRoamRequestHandoff(pMac, sessionId); + } + else + { + smsLog(pMac, LOGE, FL("Non-11R Reassoc indication received in unexpected state %s or Roaming is disabled"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + } + } +} + +VOS_STATUS +csrNeighborRoamUpdateFastRoamingEnabled(tpAniSirGlobal pMac, + tANI_U8 sessionId, + const v_BOOL_t fastRoamEnabled) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpFTRoamCallbackUsrCtx pUsrCtx; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) + { + if (VOS_TRUE == fastRoamEnabled) + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, + REASON_CONNECT); + } else { +#endif + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup " + "DOWN event with TL, RSSI = %d"), + pNeighborRoamInfo->currentNeighborLookupThreshold); + + /* Both pMac and sessionId are required to identify for which + * session the indication is being received + */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + /* Register Neighbor Lookup threshold callback with TL for + DOWN event only */ + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME, pUsrCtx); + vos_mem_free(pUsrCtx); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + smsLog(pMac, LOGW, + FL("Failed to register RSSI indication callback = %d"), + vosStatus); + vosStatus = VOS_STATUS_E_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + } + else if (VOS_FALSE == fastRoamEnabled) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Currently in CONNECTED state, so deregister all events")); + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_STOP, + REASON_DISCONNECTED); + } else { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + } + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Currently in INIT state, Nothing to do")); + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Unexpected state %s, returning failure"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +#ifdef FEATURE_WLAN_ESE +VOS_STATUS csrNeighborRoamUpdateEseModeEnabled(tpAniSirGlobal pMac, + tANI_U8 sessionId, + const v_BOOL_t eseMode) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpFTRoamCallbackUsrCtx pUsrCtx; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) + { + if (VOS_TRUE == eseMode) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), + pNeighborRoamInfo->currentNeighborLookupThreshold); + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, + REASON_CONNECT); + } else { +#endif + /* This user context data will be returned with callback */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME, pUsrCtx); + vos_mem_free(pUsrCtx); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + smsLog(pMac, LOGW, + FL("Failed to register RSSI indication callback: Status = %d"), + vosStatus); + + /* Registration failed, free the user context */ + vosStatus = VOS_STATUS_E_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + } + else if (VOS_FALSE == eseMode) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, so deregister all events")); + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_STOP, + REASON_DISCONNECTED); + } else { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + } + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == + pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, Nothing to do")); + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Unexpected state %d, returning failure"), + pNeighborRoamInfo->neighborRoamState); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +#endif + + +VOS_STATUS csrNeighborRoamSetLookupRssiThreshold(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t neighborLookupRssiThreshold) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpFTRoamCallbackUsrCtx pUsrCtx; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == + pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("In CONNECTED state, re-register for DOWN event only")); + + pNeighborRoamInfo->cfgParams.neighborLookupThreshold = + neighborLookupRssiThreshold; + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_LOOKUP_THRESH_CHANGED); + } + else + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); + + /* This user context data will be returned with callback */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), + pNeighborRoamInfo->currentNeighborLookupThreshold); + + /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME, pUsrCtx); + vos_mem_free(pUsrCtx); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + smsLog(pMac, LOGE, + FL("Failed to register DOWN event with TL: Status = %d"), + vosStatus); + + /* Registration failed, free the user context */ + vosStatus = VOS_STATUS_E_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, safe to set lookupRssi threshold")); + pNeighborRoamInfo->cfgParams.neighborLookupThreshold = + neighborLookupRssiThreshold; + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Unexpected state %s, returning failure"), + macTraceGetNeighbourRoamState(pNeighborRoamInfo->neighborRoamState)); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +VOS_STATUS +csrNeighborRoamSetOpportunisticScanThresholdDiff(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nOpportunisticThresholdDiff) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in CONNECTED state, so deregister " + "all and re-register for DOWN event again")); + + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, + sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_OPPORTUNISTIC_THRESH_DIFF_CHANGED); + } +#endif + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in INIT state, safe to set " + "opportunistic threshold diff")); + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +VOS_STATUS +csrNeighborRoamSetRoamRescanRssiDiff(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamRescanRssiDiff) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in CONNECTED state, so deregister " + "all and re-register for DOWN event again")); + + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff = + nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = + nRoamRescanRssiDiff; + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, + sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_RESCAN_RSSI_DIFF_CHANGED); + } +#endif + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in INIT state, safe to set roam " + "rescan rssi diff")); + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff = + nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = nRoamRescanRssiDiff; + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +VOS_STATUS +csrNeighborRoamSetRoamBmissFirstBcnt(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamBmissFirstBcnt) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in CONNECTED state, so deregister all and re-register for DOWN event again")); + + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = nRoamBmissFirstBcnt; + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, + sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_BMISS_FIRST_BCNT_CHANGED); + } +#endif + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in INIT state, safe to set roam rescan rssi diff")); + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = nRoamBmissFirstBcnt; + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +VOS_STATUS +csrNeighborRoamSetRoamBmissFinalBcnt(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamBmissFinalBcnt) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in CONNECTED state, so deregister all and re-register for DOWN event again")); + + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = nRoamBmissFinalBcnt; + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_BMISS_FINAL_BCNT_CHANGED); + } +#endif + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in INIT state, safe to set roam rescan rssi diff")); + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = nRoamBmissFinalBcnt; + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} + +VOS_STATUS +csrNeighborRoamSetRoamBeaconRssiWeight(tpAniSirGlobal pMac, + tANI_U8 sessionId, + v_U8_t nRoamBeaconRssiWeight) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in CONNECTED state, so deregister all and re-register for DOWN event again")); + + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = nRoamBeaconRssiWeight; + + /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_BEACON_RSSI_WEIGHT_CHANGED); + } +#endif + } + else if (eCSR_NEIGHBOR_ROAM_STATE_INIT + == pNeighborRoamInfo->neighborRoamState) + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL("Currently in INIT state, safe to set roam rescan rssi diff")); + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + vosStatus = VOS_STATUS_E_FAILURE; + } + return vosStatus; +} +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamReassocIndCallback + + \brief Reassoc callback invoked by TL on crossing the registered re-assoc threshold. + Directly trigger HO in case of non-11r association + In case of 11R association, triggers a pre-auth eventually followed by actual HO + + \param pAdapter - VOS Context + trafficStatus - UP/DOWN indication from TL + pUserCtxt - Parameter for callback registered during callback registration. Should be pMac + + \return VOID + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamReassocIndCallback(v_PVOID_t pAdapter, + v_U8_t trafficStatus, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi) +{ + tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *)pUserCtxt; + tANI_U8 sessionId = pUsrCtx->sessionId; + tpAniSirGlobal pMac = pUsrCtx->pMac; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + if (eSME_ROAM_TRIGGER_FAST_ROAM != pNeighborRoamInfo->cfgRoamEn) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Deregistering DOWN event reassoc callback with TL. " + "Threshold RSSI = %d Reported RSSI = %d"), + pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1), + avgRssi); + + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamReassocIndCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d"), vosStatus); + } + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Rcvd reassoc notification-deregister UP indication. Threshold RSSI = %d Reported RSSI = %d"), + NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), avgRssi); + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamNeighborLookupUPCallback with TL: Status = %d"), vosStatus); + } + } + /* We dont need to run this timer any more. */ + vos_timer_stop(&pNeighborRoamInfo->neighborResultsRefreshTimer); + vos_timer_stop(&pNeighborRoamInfo->emptyScanRefreshTimer); + + csrNeighborRoamTriggerHandoff(pMac, sessionId); + vos_mem_free(pUsrCtx); + + return VOS_STATUS_SUCCESS; +} + +/*CleanUP Routines*/ +static void csrNeighborRoamResetChannelInfo(tpCsrNeighborRoamChannelInfo rChInfo) +{ + if ((rChInfo->IAPPNeighborListReceived == FALSE) && + (rChInfo->currentChannelListInfo.numOfChannels)) + { + rChInfo->currentChanIndex = CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX; + rChInfo->currentChannelListInfo.numOfChannels = 0; + + if (rChInfo->currentChannelListInfo.ChannelList) + vos_mem_free(rChInfo->currentChannelListInfo.ChannelList); + + rChInfo->currentChannelListInfo.ChannelList = NULL; + rChInfo->chanListScanInProgress = eANI_BOOLEAN_FALSE; + } + else + { + rChInfo->currentChanIndex = 0; + rChInfo->chanListScanInProgress = eANI_BOOLEAN_TRUE; + } +} + +static void csrNeighborRoamResetCfgListChanScanControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + /* Stop neighbor scan timer */ + vos_timer_stop(&pNeighborRoamInfo->neighborScanTimer); + + /* Stop neighbor scan results refresh timer */ + vos_timer_stop(&pNeighborRoamInfo->neighborResultsRefreshTimer); + + /* Stop empty scan results refresh timer */ + vos_timer_stop(&pNeighborRoamInfo->emptyScanRefreshTimer); + + /* Abort any ongoing scan */ + if (eANI_BOOLEAN_TRUE == pNeighborRoamInfo->scanRspPending) + { + csrScanAbortMacScan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT); + } + pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE; + + /* Reset roam channel list information */ + csrNeighborRoamResetChannelInfo(&pNeighborRoamInfo->roamChannelInfo); +} + +static void csrNeighborRoamResetPreauthControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_FALSE; + /* Purge pre-auth fail list */ + csrNeighborRoamPurgePreauthFailedList(pMac); +#endif + + pNeighborRoamInfo->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Do not free up the preauth done list here */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT); +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; + vos_mem_zero(&pNeighborRoamInfo->handoffReqInfo, + sizeof(tCsrHandoffRequest)); +#endif +} + +static void csrNeighborRoamDeregAllRssiIndication(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Deregister neighbor lookup UP callback with TL. RSSI = %d"), + NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + /* Deregister reassoc callback. Ignore return status */ + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL("Couldn't deregister csrNeighborRoamNeighborLookupUPCallback with TL: Status = %d"), + vosStatus); + } + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Deregistering reassoc DOWN callback with TL. RSSI = %d"), + pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1)); + + /* Deregister reassoc callback. Ignore return status */ + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamReassocIndCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d"), + vosStatus); + } + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Deregistering neighborLookup DOWN callback with TL. RSSI = %d"), + pNeighborRoamInfo->currentNeighborLookupThreshold * (-1)); + + /* Deregister neighbor lookup callback. Ignore return status */ + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL(" Couldn't deregister csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), + vosStatus); + } + + /* Reset thresholds only after deregistering DOWN event from TL */ + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight; +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->uEmptyScanCount = 0; + pNeighborRoamInfo->lookupDOWNRssi = 0; + pNeighborRoamInfo->uScanMode = DEFAULT_SCAN; +#endif +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamResetConnectedStateControlInfo + + \brief This function will reset the neighbor roam control info data structures. + This function should be invoked whenever we move to CONNECTED state from + any state other than INIT state + + \param pMac - The handle returned by macOpen. + \param sessionId - session id + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamResetConnectedStateControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + csrNeighborRoamResetChannelInfo(&pNeighborRoamInfo->roamChannelInfo); + csrNeighborRoamFreeRoamableBSSList(pMac, &pNeighborRoamInfo->roamableAPList); + + /* We dont need to run this timer any more. */ + vos_timer_stop(&pNeighborRoamInfo->neighborResultsRefreshTimer); + vos_timer_stop(&pNeighborRoamInfo->emptyScanRefreshTimer); + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Do not free up the preauth done list here */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + pNeighborRoamInfo->FTRoamInfo.preauthRspPending = 0; + vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT); +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; + vos_mem_zero(&pNeighborRoamInfo->handoffReqInfo, + sizeof(tCsrHandoffRequest)); +#endif +} + +void csrNeighborRoamResetReportScanStateControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + vos_mem_set(pNeighborRoamInfo->currAPbssid, sizeof(tCsrBssid), 0); + pNeighborRoamInfo->neighborScanTimerInfo.pMac = pMac; + pNeighborRoamInfo->neighborScanTimerInfo.sessionId = CSR_SESSION_ID_INVALID; +#ifdef FEATURE_WLAN_ESE + pNeighborRoamInfo->isESEAssoc = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->isVOAdmitted = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->MinQBssLoadRequired = 0; +#endif + + /* Stop scan refresh timer */ + vos_timer_stop(&pNeighborRoamInfo->neighborResultsRefreshTimer); + /* Stop empty scan results refresh timer */ + vos_timer_stop(&pNeighborRoamInfo->emptyScanRefreshTimer); + /* Purge roam able AP list */ + csrNeighborRoamFreeRoamableBSSList(pMac, &pNeighborRoamInfo->roamableAPList); + return; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamResetInitStateControlInfo + + \brief This function will reset the neighbor roam control info data structures. + This function should be invoked whenever we move to CONNECTED state from + INIT state + + \param pMac - The handle returned by macOpen. + \param sessionId - Session Id + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamResetInitStateControlInfo(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + csrNeighborRoamResetConnectedStateControlInfo(pMac, sessionId); + + /* In addition to the above resets, + we should clear off the curAPBssId/Session ID in the timers */ + csrNeighborRoamResetReportScanStateControlInfo(pMac, sessionId); +} + + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamBssIdScanFilter + + \brief This API is used to prepare a filter to obtain scan results when + we complete the scan in the REPORT_SCAN state after receiving a + valid neighbor report from AP. This filter includes BSSIDs received from + the neighbor report from the AP in addition to the other filter parameters + created from connected profile + + \param pMac - The handle returned by macOpen. + pScanFilter - Scan filter to be filled and returned + + \return eHAL_STATUS_SUCCESS on successful filter creation, corresponding + error code otherwise + +---------------------------------------------------------------------------*/ +static eHalStatus csrNeighborRoamBssIdScanFilter(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tCsrScanResultFilter *pScanFilter) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 i = 0; + + VOS_ASSERT(pScanFilter != NULL); + if (pScanFilter == NULL) + return eHAL_STATUS_FAILURE; + vos_mem_zero(pScanFilter, sizeof(tCsrScanResultFilter)); + + pScanFilter->BSSIDs.numOfBSSIDs = pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport; + pScanFilter->BSSIDs.bssid = vos_mem_malloc(sizeof(tSirMacAddr) * pScanFilter->BSSIDs.numOfBSSIDs); + if (NULL == pScanFilter->BSSIDs.bssid) + { + smsLog(pMac, LOGE, FL("Scan Filter BSSID mem alloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(pScanFilter->BSSIDs.bssid, sizeof(tSirMacAddr) * pScanFilter->BSSIDs.numOfBSSIDs); + + /* Populate the BSSID from Neighbor BSS info received from neighbor report */ + for (i = 0; i < pScanFilter->BSSIDs.numOfBSSIDs; i++) { + vos_mem_copy(&pScanFilter->BSSIDs.bssid[i], + pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[i].neighborBssId, + sizeof(tSirMacAddr)); + } + + /* Fill other general scan filter params */ + return csrNeighborRoamPrepareScanProfileFilter(pMac, pScanFilter, sessionId); +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamPurgePreauthFailList + + \brief This function empties the preauth fail list + + \param pMac - The handle returned by macOpen. + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamPurgePreauthFailList(tpAniSirGlobal pMac) +{ + tANI_U8 i; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Purging the preauth fail list")); + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[i]; + while (pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress) { + vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress-1], + sizeof(tSirMacAddr)); + pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress--; + } + } + return; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamAddBssIdToPreauthFailList + + \brief This function adds the given BSSID to the Preauth fail list + + \param pMac - The handle returned by macOpen. + bssId - BSSID to be added to the preauth fail list + + \return eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamAddBssIdToPreauthFailList(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tSirMacAddr bssId) +{ + tANI_U8 i = 0; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Added BSSID "MAC_ADDRESS_STR + " to Preauth failed list"), MAC_ADDR_ARRAY(bssId)); + + for (i = 0; i < pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress; + i++) { + if (VOS_TRUE == vos_mem_compare( + pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[i], + bssId, sizeof(tSirMacAddr))) { + smsLog(pMac, LOGW, FL("BSSID "MAC_ADDRESS_STR" already present in preauth fail list"), + MAC_ADDR_ARRAY(bssId)); + return eHAL_STATUS_SUCCESS; + } + } + + if ((pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress + 1) > + MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS) + { + smsLog(pMac, LOGE, FL("Preauth fail list already full.. Cannot add new one")); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[ + pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress], + bssId, + sizeof(tSirMacAddr)); + pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress++; + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIsPreauthCandidate + + \brief This function checks whether the given MAC address is already + present in the preauth fail list and returns TRUE/FALSE accordingly + + \param pMac - The handle returned by macOpen. + + \return eANI_BOOLEAN_TRUE if preauth candidate, eANI_BOOLEAN_FALSE otherwise + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamIsPreauthCandidate(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tSirMacAddr bssId) +{ + tANI_U8 i = 0; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + return eANI_BOOLEAN_TRUE; + } +#endif + if (0 == pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress) + return eANI_BOOLEAN_TRUE; + + for (i = 0; i < pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress; i++) + { + if (VOS_TRUE == vos_mem_compare(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[i], + bssId, sizeof(tSirMacAddr))) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("BSSID "MAC_ADDRESS_STR" already present in preauth fail list"), + MAC_ADDR_ARRAY(bssId)); + return eANI_BOOLEAN_FALSE; + } + } + + return eANI_BOOLEAN_TRUE; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIssuePreauthReq + + \brief This function issues preauth request to PE with the 1st AP entry in the + roam able AP list + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise + +---------------------------------------------------------------------------*/ +static eHalStatus csrNeighborRoamIssuePreauthReq(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamBSSInfo pNeighborBssNode; + +#ifdef FEATURE_WLAN_LFR_METRICS + tCsrRoamInfo *roamInfo; +#endif + + if (eANI_BOOLEAN_FALSE != pNeighborRoamInfo->FTRoamInfo.preauthRspPending) + { + /* This must not be true here */ + VOS_ASSERT(pNeighborRoamInfo->FTRoamInfo.preauthRspPending == eANI_BOOLEAN_FALSE); + return eHAL_STATUS_FAILURE; + } + + /* Issue Preauth request to PE here */ + /* + * Need to issue the preauth request with the BSSID that is there in the + * head of the roam able AP list + * Parameters that should be passed are BSSID, Channel number and the + * neighborScanPeriod(probably) + * If roamableAPList gets empty, should transition to REPORT_SCAN state + */ + pNeighborBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->roamableAPList, NULL); + + if (NULL == pNeighborBssNode) + { + smsLog(pMac, LOGW, FL("Roamable AP list is empty.. ")); + return eHAL_STATUS_FAILURE; + } + else + { +#ifdef FEATURE_WLAN_LFR_METRICS + /* LFR metrics - pre-auth initiation metric. + Send the event to supplicant that pre-auth was initiated */ + roamInfo = vos_mem_malloc(sizeof(tCsrRoamInfo)); + if (NULL == roamInfo) + { + smsLog(pMac, LOG1, FL("Memory allocation failed!")); + } + else + { + vos_mem_copy((void *)roamInfo->bssid, + (void *)pNeighborBssNode->pBssDescription->bssId, + sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, roamInfo, 0, + eCSR_ROAM_PREAUTH_INIT_NOTIFY, 0); + vos_mem_free(roamInfo); + } +#endif + + status = csrRoamEnqueuePreauth(pMac, sessionId, + pNeighborBssNode->pBssDescription, + eCsrPerformPreauth, eANI_BOOLEAN_TRUE); + + smsLog(pMac, LOG1, FL("Before Pre-Auth: BSSID "MAC_ADDRESS_STR", Ch:%d"), + MAC_ADDR_ARRAY(pNeighborBssNode->pBssDescription->bssId), + (int)pNeighborBssNode->pBssDescription->channelId); + + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Send Preauth request to PE failed with status %d"), status); + return status; + } + } + + pNeighborRoamInfo->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_TRUE; + + /* Increment the preauth retry count */ + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries++; + + /* Transition the state to preauthenticating */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING, + sessionId) + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamPreauthRspHandler + + \brief This function handle the Preauth response from PE + Every preauth is allowed max 3 tries if it fails. If a bssid failed + for more than MAX_TRIES, we will remove it from the list and try + with the next node in the roam able AP list and add the BSSID + to pre-auth failed list. If no more entries present in + roam able AP list, transition to REPORT_SCAN state + + \param pMac - The handle returned by macOpen. + limStatus - eSIR_SUCCESS/eSIR_FAILURE/eSIR_LIM_MAX_STA_REACHED_ERROR/ + eSIT_LIM_AUTH_RSP_TIMEOUT status from PE + + \return eHAL_STATUS_SUCCESS on success (i.e. pre-auth processed), + eHAL_STATUS_FAILURE otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tSirRetStatus limStatus) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + eHalStatus preauthProcessed = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamBSSInfo pPreauthRspNode = NULL; + tpFTRoamCallbackUsrCtx pUsrCtx; + +#ifdef FEATURE_WLAN_LFR_METRICS + tCsrRoamInfo *roamInfo; +#endif + + if (eANI_BOOLEAN_FALSE == pNeighborRoamInfo->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. + */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + FL("Unexpected pre-auth response in state %d"), + pNeighborRoamInfo->neighborRoamState); + preauthProcessed = eHAL_STATUS_FAILURE; + goto DEQ_PREAUTH; + } + + // We can receive it in these 2 states. + if ((pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING) && + (pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN)) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + FL("Preauth response received in state %s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + preauthProcessed = eHAL_STATUS_FAILURE; + goto DEQ_PREAUTH; + } + + pNeighborRoamInfo->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE; + + if (eSIR_SUCCESS == limStatus) + { + pPreauthRspNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, + &pNeighborRoamInfo->roamableAPList, + NULL); + } + if ((eSIR_SUCCESS == limStatus) && (NULL != pPreauthRspNode)) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Preauth completed successfully after %d tries"), pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries); + + smsLog(pMac, LOG1, FL("After Pre-Auth: BSSID "MAC_ADDRESS_STR", Ch:%d"), + MAC_ADDR_ARRAY(pPreauthRspNode->pBssDescription->bssId), + (int)pPreauthRspNode->pBssDescription->channelId); + +#ifdef FEATURE_WLAN_LFR_METRICS + /* LFR metrics - pre-auth completion metric. + Send the event to supplicant that pre-auth successfully completed */ + roamInfo = vos_mem_malloc(sizeof(tCsrRoamInfo)); + if (NULL == roamInfo) + { + smsLog(pMac, LOG1, FL("Memory allocation failed!")); + } + else + { + vos_mem_copy((void *)roamInfo->bssid, + (void *)pPreauthRspNode->pBssDescription->bssId, + sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, roamInfo, 0, + eCSR_ROAM_PREAUTH_STATUS_SUCCESS, 0); + vos_mem_free(roamInfo); + } +#endif + + /* Preauth completed successfully. Insert the preauthenticated + node to tail of preAuthDoneList */ + csrNeighborRoamRemoveRoamableAPListEntry(pMac, &pNeighborRoamInfo->roamableAPList, pPreauthRspNode); + csrLLInsertTail(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, &pPreauthRspNode->List, LL_ACCESS_LOCK); + + /* Pre-auth completed successfully. Transition to PREAUTH Done state */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE, + sessionId) + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; + + /* + * The caller of this function would start a timer and by the time it + * expires, supplicant should have provided the updated FTIEs to SME. + * So, when it expires, handoff will be triggered then + */ + } + else + { + tpCsrNeighborRoamBSSInfo pNeighborBssNode = NULL; + tListElem *pEntry; + bool is_dis_pending = false; + + 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 roam able AP list */ + if ((pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries >= + CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES) || + (eSIR_LIM_MAX_STA_REACHED_ERROR == limStatus)) + { + /* We are going to remove the node as it fails for more than MAX tries. Reset this count to 0 */ + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; + + /* The one in the head of the list should be one with which we issued pre-auth and failed */ + pEntry = csrLLRemoveHead(&pNeighborRoamInfo->roamableAPList, LL_ACCESS_LOCK); + if(pEntry) + { + pNeighborBssNode = GET_BASE_ADDR(pEntry, tCsrNeighborRoamBSSInfo, List); + /* Add the BSSID to pre-auth fail list if it is not requested by HDD */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!pNeighborRoamInfo->uOsRequestedHandoff) +#endif + { + status = csrNeighborRoamAddBssIdToPreauthFailList(pMac, + sessionId, + pNeighborBssNode->pBssDescription->bssId); + } + +#ifdef FEATURE_WLAN_LFR_METRICS + /* LFR metrics - pre-auth completion metric. Send the event + to supplicant that pre-auth successfully completed */ + roamInfo = vos_mem_malloc(sizeof(tCsrRoamInfo)); + if (NULL == roamInfo) + { + smsLog(pMac, LOG1, FL("Memory allocation failed!")); + } + else + { + vos_mem_copy((void *)roamInfo->bssid, + (void *)pNeighborBssNode->pBssDescription->bssId, + sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, roamInfo, 0, + eCSR_ROAM_PREAUTH_STATUS_FAILURE, 0); + vos_mem_free(roamInfo); + } +#endif + + /* Now we can free this node */ + csrNeighborRoamFreeNeighborRoamBSSNode(pMac, pNeighborBssNode); + } + } + + is_dis_pending = is_disconnect_pending(pMac, sessionId); + if (is_dis_pending) { + smsLog(pMac, LOGE, + FL(" Disconnect in progress, Abort preauth")); + goto abort_preauth; + } + + + + /* Issue preauth request for the same/next entry */ + if (eHAL_STATUS_SUCCESS == csrNeighborRoamIssuePreauthReq(pMac, + sessionId)) + goto DEQ_PREAUTH; + +abort_preauth: +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + if(pNeighborRoamInfo->uOsRequestedHandoff) + { + pNeighborRoamInfo->uOsRequestedHandoff = 0; + csrRoamOffloadScan(pMac, 0, ROAM_SCAN_OFFLOAD_START, + REASON_PREAUTH_FAILED_FOR_ALL); + } + else + { + csrRoamOffloadScan(pMac, 0, ROAM_SCAN_OFFLOAD_RESTART, + REASON_PREAUTH_FAILED_FOR_ALL); + } + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + sessionId); + } else + { +#endif + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN, + sessionId); + + /* Register Neighbor Lookup threshold callback with TL + for UP event now */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-" + "register UP indication with TL. RSSI = %d,"), + NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failed for pUsrCtx")); + return eHAL_STATUS_FAILED_ALLOC; + } + + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME, pUsrCtx); + vos_mem_free(pUsrCtx); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status); + } + + /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */ + status = vos_timer_start(&pNeighborRoamInfo->neighborResultsRefreshTimer, + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod); + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status); + } + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + +DEQ_PREAUTH: + csrDequeueRoamCommand(pMac, eCsrPerformPreauth); + return preauthProcessed; +} +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* --------------------------------------------------------------------------- + * \fn csrNeighborRoamOffloadUpdatePreauthList + * \brief This function handle the RoamOffloadSynch and adds the + * roamed AP to the preauth done list + * \param pMac - The handle returned by macOpen. + * \param pSmeRoamOffloadSynchInd - Roam offload sync Ind Info + * \param sessionId - Session identifier + * \return eHAL_STATUS_SUCCESS on success, + * eHAL_STATUS_FAILURE otherwise + * --------------------------------------------------------------------------*/ +eHalStatus +csrNeighborRoamOffloadUpdatePreauthList(tpAniSirGlobal pMac, + tpSirRoamOffloadSynchInd pSmeRoamOffloadSynchInd, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tpCsrNeighborRoamBSSInfo pBssInfo; + tANI_U16 bssDescLen; + + if (pNeighborRoamInfo->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + FL("LFR3:Roam Offload Synch Ind received in state %d"), + pNeighborRoamInfo->neighborRoamState); + return eHAL_STATUS_FAILURE; + } + + pBssInfo = vos_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo)); + if (NULL == pBssInfo) + { + smsLog(pMac, LOGE, + FL("LFR3:Memory allocation for Neighbor Roam BSS Info failed")); + return eHAL_STATUS_FAILURE; + } + bssDescLen = pSmeRoamOffloadSynchInd->pbssDescription->length + + sizeof(pSmeRoamOffloadSynchInd->pbssDescription->length); + pBssInfo->pBssDescription = vos_mem_malloc(bssDescLen); + if (pBssInfo->pBssDescription != NULL) + { + vos_mem_copy(pBssInfo->pBssDescription, + pSmeRoamOffloadSynchInd->pbssDescription, + bssDescLen); + } + else + { + smsLog(pMac, LOGE, + FL("LFR3:Mem alloc for Neighbor Roam BSS Descriptor failed")); + vos_mem_free(pBssInfo); + return eHAL_STATUS_FAILURE; + + } + csrLLInsertTail(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, + &pBssInfo->List, LL_ACCESS_LOCK); + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE, + sessionId) + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR3:Entry added to Auth Done List"); + + return eHAL_STATUS_SUCCESS; +} +#endif +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamPrepareScanProfileFilter + + \brief This function creates a scan filter based on the currently connected profile. + Based on this filter, scan results are obtained + + \param pMac - The handle returned by macOpen. + pScanFilter - Populated scan filter based on the connected profile + + \return eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise + +---------------------------------------------------------------------------*/ +eHalStatus +csrNeighborRoamPrepareScanProfileFilter(tpAniSirGlobal pMac, + tCsrScanResultFilter *pScanFilter, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamConnectedProfile *pCurProfile = &pMac->roam.roamSession[sessionId].connectedProfile; + tANI_U8 i = 0; + struct roam_ext_params *roam_params; + + VOS_ASSERT(pScanFilter != NULL); + if (pScanFilter == NULL) + return eHAL_STATUS_FAILURE; + + vos_mem_zero(pScanFilter, sizeof(tCsrScanResultFilter)); + + roam_params = &pMac->roam.configParam.roam_params; + /* We dont want to set BSSID based Filter */ + pScanFilter->BSSIDs.numOfBSSIDs = 0; + pScanFilter->scan_filter_for_roam = 1; + //only for HDD requested handoff fill in the BSSID in the filter +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pNeighborRoamInfo->uOsRequestedHandoff) + { + pScanFilter->BSSIDs.numOfBSSIDs = 1; + pScanFilter->BSSIDs.bssid = vos_mem_malloc(sizeof(tSirMacAddr) * pScanFilter->BSSIDs.numOfBSSIDs); + if (NULL == pScanFilter->BSSIDs.bssid) + { + smsLog(pMac, LOGE, FL("Scan Filter BSSID mem alloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(pScanFilter->BSSIDs.bssid, sizeof(tSirMacAddr) * pScanFilter->BSSIDs.numOfBSSIDs); + + /* Populate the BSSID from handoff info received from HDD */ + for (i = 0; i < pScanFilter->BSSIDs.numOfBSSIDs; i++) + { + vos_mem_copy(&pScanFilter->BSSIDs.bssid[i], + pNeighborRoamInfo->handoffReqInfo.bssid, sizeof(tSirMacAddr)); + } + } +#endif + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("No of Allowed SSID List:%d"), roam_params->num_ssid_allowed_list); + if (roam_params->num_ssid_allowed_list) { + pScanFilter->SSIDs.numOfSSIDs = (roam_params->num_ssid_allowed_list); + pScanFilter->SSIDs.SSIDList = + vos_mem_malloc(sizeof(tCsrSSIDInfo) * pScanFilter->SSIDs.numOfSSIDs); + if (NULL == pScanFilter->SSIDs.SSIDList) { + smsLog(pMac, LOGE, FL("Scan Filter SSID mem alloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + for(i = 0; i < roam_params->num_ssid_allowed_list; i++) { + pScanFilter->SSIDs.SSIDList[i].handoffPermitted = 1; + pScanFilter->SSIDs.SSIDList[i].ssidHidden = 0; + vos_mem_copy((void *)pScanFilter->SSIDs.SSIDList[i].SSID.ssId, + roam_params->ssid_allowed_list[i].ssId, + roam_params->ssid_allowed_list[i].length); + pScanFilter->SSIDs.SSIDList[i].SSID.length = + roam_params->ssid_allowed_list[i].length; + } + } else { + /* Populate all the information from the connected profile */ + pScanFilter->SSIDs.numOfSSIDs = 1; + pScanFilter->SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if (NULL == pScanFilter->SSIDs.SSIDList) { + smsLog(pMac, LOGE, FL("Scan Filter SSID mem alloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + pScanFilter->SSIDs.SSIDList->handoffPermitted = 1; + pScanFilter->SSIDs.SSIDList->ssidHidden = 0; + pScanFilter->SSIDs.SSIDList->SSID.length = pCurProfile->SSID.length; + vos_mem_copy((void *)pScanFilter->SSIDs.SSIDList->SSID.ssId, + (void *)pCurProfile->SSID.ssId, pCurProfile->SSID.length); + + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Filtering for SSID %.*s from scan results," + "length of SSID = %u"), + pScanFilter->SSIDs.SSIDList->SSID.length, + pScanFilter->SSIDs.SSIDList->SSID.ssId, + pScanFilter->SSIDs.SSIDList->SSID.length); + } + pScanFilter->authType.numEntries = 1; + pScanFilter->authType.authType[0] = pCurProfile->AuthType; + + pScanFilter->EncryptionType.numEntries = 1; //This must be 1 + pScanFilter->EncryptionType.encryptionType[0] = pCurProfile->EncryptionType; + + pScanFilter->mcEncryptionType.numEntries = 1; + pScanFilter->mcEncryptionType.encryptionType[0] = pCurProfile->mcEncryptionType; + + pScanFilter->BSSType = pCurProfile->BSSType; + + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels) + { + /* We are interested only in the scan results on channels we scanned */ + pScanFilter->ChannelInfo.numOfChannels = + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels; + pScanFilter->ChannelInfo.ChannelList = + vos_mem_malloc(pScanFilter->ChannelInfo.numOfChannels * sizeof(tANI_U8)); + if (NULL == pScanFilter->ChannelInfo.ChannelList) { + smsLog(pMac, LOGE, FL("Scan Filter Channel list mem alloc failed")); + vos_mem_free(pScanFilter->SSIDs.SSIDList); + pScanFilter->SSIDs.SSIDList = NULL; + return eHAL_STATUS_FAILED_ALLOC; + } + for (i = 0; i < pScanFilter->ChannelInfo.numOfChannels; i++) + pScanFilter->ChannelInfo.ChannelList[i] = + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[i]; + } else { + pScanFilter->ChannelInfo.numOfChannels = 0; + pScanFilter->ChannelInfo.ChannelList = NULL; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pNeighborRoamInfo->is11rAssoc) + { + /* MDIE should be added as a part of profile. This should be added as a part of filter as well */ + pScanFilter->MDID.mdiePresent = pCurProfile->MDID.mdiePresent; + pScanFilter->MDID.mobilityDomain = pCurProfile->MDID.mobilityDomain; + } +#endif + +#ifdef WLAN_FEATURE_11W + pScanFilter->MFPEnabled = pCurProfile->MFPEnabled; + pScanFilter->MFPRequired = pCurProfile->MFPRequired; + pScanFilter->MFPCapable = pCurProfile->MFPCapable; +#endif + return eHAL_STATUS_SUCCESS; +} + +tANI_U32 csrGetCurrentAPRssi(tpAniSirGlobal pMac, + tScanResultHandle *pScanResultList, + tANI_U8 sessionId) +{ + tCsrScanResultInfo *pScanResult; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; +#ifdef FEATURE_WLAN_LFR + tANI_U32 CurrAPRssi = pNeighborRoamInfo->lookupDOWNRssi; +#else + /* We are setting this as default value to make sure we return this value, + when we do not see this AP in the scan result for some reason.However,it is + less likely that we are associated to an AP and do not see it in the scan list */ + tANI_U32 CurrAPRssi = -125; +#endif + + while (NULL != (pScanResult = csrScanResultGetNext(pMac, *pScanResultList))) + { + if (VOS_TRUE == vos_mem_compare(pScanResult->BssDescriptor.bssId, + pNeighborRoamInfo->currAPbssid, sizeof(tSirMacAddr))) + { + /* We got a match with the currently associated AP. + * Capture the RSSI value and complete the while loop. + * The while loop is completed in order to make the current entry go back to NULL, + * and in the next while loop, it properly starts searching from the head of the list. + * TODO: Can also try setting the current entry directly to NULL as soon as we find the new AP*/ + + CurrAPRssi = (int)pScanResult->BssDescriptor.rssi * (-1); + + } else { + continue; + } + } + + return CurrAPRssi; + +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamProcessScanResults + + \brief This function extracts scan results, sorts on the basis of neighbor score(todo). + Assumed that the results are already sorted by RSSI by csrScanGetResult + + \param pMac - The handle returned by macOpen. + pScanResultList - Scan result result obtained from csrScanGetResult() + + \return tANI_BOOLEAN - return TRUE if we have a candidate we can immediately + roam to. Otherwise, return FALSE. + +---------------------------------------------------------------------------*/ + +static tANI_BOOLEAN +csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, + tANI_U8 sessionId, + tScanResultHandle *pScanResultList) +{ + tCsrScanResultInfo *pScanResult; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tpCsrNeighborRoamBSSInfo pBssInfo; + tANI_U32 CurrAPRssi; + tANI_U8 RoamRssiDiff = pMac->roam.configParam.RoamRssiDiff; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tANI_U8 immediateRoamRssiDiff = + pMac->roam.configParam.nImmediateRoamRssiDiff; +#endif + tANI_BOOLEAN roamNow = eANI_BOOLEAN_FALSE; + tScanResultHandle *pScanResultListSaved = NULL; + tANI_U32 apAgeTicks = 0; + tANI_U32 apAgeLimitTicks = adf_os_msecs_to_ticks(ROAM_AP_AGE_LIMIT_MS); + tANI_U8 numCandidates = 0; + tANI_U8 numAPsDropped = 0; + /* + * first iteration of scan list should consider + * age constraint for candidates + */ + tANI_BOOLEAN ageConstraint = eANI_BOOLEAN_TRUE; + + /*************************************************************** + * Find out the Current AP RSSI and keep it handy to check if + * it is better than the RSSI of the AP which we are + * going to roam.If so, we are going to continue with the + * current AP. + ***************************************************************/ + CurrAPRssi = csrGetCurrentAPRssi(pMac, pScanResultList, sessionId); + + /* + * Expecting the scan result already to be in the sorted order based on the + * RSSI. Based on the previous state we need to check whether the list + * should be sorted again taking neighbor score into consideration. If + * previous state is CFG_CHAN_LIST_SCAN, there should not be any neighbor + * score associated with any of the BSS. If the previous state is + * REPORT_QUERY, then there will be neighbor score for each of the APs. For + * now, let us take the top of the list provided as it is by the CSR Scan + * result API. This means it is assumed that neighbor score and rssi score + * are in the same order. This will be taken care later + */ + + do { + /* save the scan result pointer for next iteration */ + pScanResultListSaved = pScanResultList; + while (NULL != (pScanResult = csrScanResultGetNext(pMac, + *pScanResultList))) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("Scan result: BSSID "MAC_ADDRESS_STR" (Rssi %ld, Ch:%d)"), + MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId), + abs(pScanResult->BssDescriptor.rssi), + pScanResult->BssDescriptor.channelId); + + if ((VOS_TRUE == vos_mem_compare(pScanResult->BssDescriptor.bssId, + pNeighborRoamInfo->currAPbssid, sizeof(tSirMacAddr))) || + ((eSME_ROAM_TRIGGER_SCAN == pNeighborRoamInfo->cfgRoamEn) && + (VOS_TRUE != vos_mem_compare(pScanResult->BssDescriptor.bssId, + pNeighborRoamInfo->cfgRoambssId, sizeof(tSirMacAddr))))) { + /* + * currently associated AP. Do not have this in the roam able AP + * list + */ + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "SKIP-currently associated AP"); + continue; + } + +#ifdef FEATURE_WLAN_LFR +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* + * In case of reassoc requested by upper layer, look for exact match + * of bssid & channel. csr cache might have duplicates + */ + if ((pNeighborRoamInfo->uOsRequestedHandoff) && + ((VOS_FALSE == vos_mem_compare(pScanResult->BssDescriptor.bssId, + pNeighborRoamInfo->handoffReqInfo.bssid, + sizeof(tSirMacAddr)))|| + (pScanResult->BssDescriptor.channelId != + pNeighborRoamInfo->handoffReqInfo.channel))) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "SKIP-not a candidate AP for OS requested roam"); + continue; + } +#endif +#endif + + /* + * This condition is to ensure to roam to an AP with better RSSI. + * if the value of RoamRssiDiff is Zero, this feature + * is disabled and we continue to roam without any check + */ + if ((RoamRssiDiff > 0) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + && ((eSME_ROAM_TRIGGER_SCAN != pNeighborRoamInfo->cfgRoamEn) || + (eSME_ROAM_TRIGGER_FAST_ROAM != pNeighborRoamInfo->cfgRoamEn))) { + /* + * If RSSI is lower than the lookup threshold, then continue. + */ + if (abs(pScanResult->BssDescriptor.rssi) > + pNeighborRoamInfo->currentNeighborLookupThreshold) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("new ap rssi (%d) lower than lookup threshold (%d)"), + (int)pScanResult->BssDescriptor.rssi * (-1), + (int)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1)); + continue; + } + + if (abs(CurrAPRssi) < abs(pScanResult->BssDescriptor.rssi)) { + /* Do not roam to an AP with worse RSSI than the current */ + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: [INFOLOG]Current AP rssi=%d new ap rssi " + "worse=%d", __func__, + CurrAPRssi, + (int)pScanResult->BssDescriptor.rssi * (-1) ); + continue; + } else { + /* + * Do not roam to an AP which is having better RSSI than the + * current AP, but still less than the margin that is + * provided by user from the ini file (RoamRssiDiff) + */ + if (abs(abs(CurrAPRssi) - + abs(pScanResult->BssDescriptor.rssi)) < RoamRssiDiff) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: [INFOLOG]Current AP rssi=%d new ap " + "rssi=%d not good enough, roamRssiDiff=%d", + __func__, + CurrAPRssi, + (int)pScanResult->BssDescriptor.rssi * (-1), + RoamRssiDiff); + continue; + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: [INFOLOG]Current AP rssi=%d new ap " + "rssi better=%d", + __func__, + CurrAPRssi, + (int)pScanResult->BssDescriptor.rssi * (-1) ); + } + } + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pNeighborRoamInfo->is11rAssoc) { + if (!csrNeighborRoamIsPreauthCandidate(pMac, sessionId, + pScanResult->BssDescriptor.bssId)) { + smsLog(pMac, LOGE, + FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +#ifdef FEATURE_WLAN_ESE +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) { +#endif + if (pNeighborRoamInfo->isESEAssoc) { + if (!csrNeighborRoamIsPreauthCandidate(pMac, sessionId, + pScanResult->BssDescriptor.bssId)) { + smsLog(pMac, LOGE, + FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } + } + if ((pScanResult->BssDescriptor.QBSSLoad_present) && + (pScanResult->BssDescriptor.QBSSLoad_avail)) { + if (pNeighborRoamInfo->isVOAdmitted) { + smsLog(pMac, LOG1, FL("New AP has %x BW available"), + (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail); + smsLog(pMac, LOG1, FL("We need %x BW available"), + (unsigned int)pNeighborRoamInfo->MinQBssLoadRequired); + if (pScanResult->BssDescriptor.QBSSLoad_avail < + pNeighborRoamInfo->MinQBssLoadRequired) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "[INFOLOG]BSSID : "MAC_ADDRESS_STR" has no" + " bandwidth ignoring..not adding to roam" + " list", + MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId)); + continue; + } + } + } else { + smsLog(pMac, LOGE, FL("No QBss %x %x"), + (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, + (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present); + if (pNeighborRoamInfo->isVOAdmitted) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "[INFOLOG]BSSID : "MAC_ADDRESS_STR" has no " + "QBSSLoad IE, ignoring..not adding to roam list", + MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId)); + continue; + } + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif +#endif /* FEATURE_WLAN_ESE */ + +#ifdef FEATURE_WLAN_LFR + /* + * If we are supporting legacy roaming, and + * if the candidate is on the "pre-auth failed" list, ignore it. + */ + if (csrRoamIsFastRoamEnabled(pMac, sessionId)) { + if (!csrNeighborRoamIsPreauthCandidate(pMac, sessionId, + pScanResult->BssDescriptor.bssId)) { + smsLog(pMac, LOGE, + FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } + } +#endif /* FEATURE_WLAN_LFR */ + + /* + * If the received times tamp in BSS description is earlier than the + * scan request time stamp, skip this result + */ + if ((pNeighborRoamInfo->scanRequestTimeStamp >= + pScanResult->BssDescriptor.nReceivedTime) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { + smsLog(pMac, LOGE, + FL("Ignoring BSS as it is older than the scan request " + "time stamp")); + continue; + } + + pBssInfo = vos_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo)); + if (NULL == pBssInfo) { + smsLog(pMac, LOGE, + FL("Memory allocation for Neighbor Roam BSS Info " + "failed.. Just ignoring")); + continue; + } + + pBssInfo->pBssDescription = + vos_mem_malloc(pScanResult->BssDescriptor.length + + sizeof(pScanResult->BssDescriptor.length)); + if (pBssInfo->pBssDescription != NULL) { + vos_mem_copy(pBssInfo->pBssDescription, + &pScanResult->BssDescriptor, + pScanResult->BssDescriptor.length + + sizeof(pScanResult->BssDescriptor.length)); + } else { + smsLog(pMac, LOGE, + FL("Memory allocation for Neighbor Roam BSS Descriptor " + "failed.. Just ignoring")); + vos_mem_free(pBssInfo); + continue; + } + /* + * some value for now. Need to calculate the actual score based on + * RSSI and neighbor AP score + */ + pBssInfo->apPreferenceVal = 10; + + if (ageConstraint == eANI_BOOLEAN_FALSE) { + /* just add to candidate list, irrespective of age */ + numCandidates++; + csrLLInsertTail(&pNeighborRoamInfo->roamableAPList, + &pBssInfo->List, + LL_ACCESS_LOCK); + } else { + /* check the age of the AP first */ + apAgeTicks = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd) - + pScanResult->BssDescriptor.nReceivedTime; + if (apAgeTicks < apAgeLimitTicks) { + numCandidates++; + csrLLInsertTail(&pNeighborRoamInfo->roamableAPList, + &pBssInfo->List, + LL_ACCESS_LOCK); + } else { + numAPsDropped++; + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("Skipping because received AP " + "(probe rsp/beacon) is old.")); + if (pBssInfo->pBssDescription) + vos_mem_free(pBssInfo->pBssDescription); + if (pBssInfo) + vos_mem_free(pBssInfo); + continue; + } + } +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if ((eSME_ROAM_TRIGGER_SCAN == pNeighborRoamInfo->cfgRoamEn) || + (eSME_ROAM_TRIGGER_FAST_ROAM == pNeighborRoamInfo->cfgRoamEn)) { + roamNow = eANI_BOOLEAN_FALSE; + } + else if ((abs(abs(CurrAPRssi) - + abs(pScanResult->BssDescriptor.rssi)) >= + immediateRoamRssiDiff) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: [INFOLOG] potential candidate to roam " + "immediately (diff=%ld, expected=%d)", + __func__, + abs(abs(CurrAPRssi) - + abs(pScanResult->BssDescriptor.rssi)), + immediateRoamRssiDiff); + roamNow = eANI_BOOLEAN_TRUE; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* + * If we are here means, FW already found candidates to roam, + * so we are good to go with pre-auth + */ + if(csrRoamIsRoamOffloadScanEnabled(pMac)) { + roamNow = eANI_BOOLEAN_TRUE; + } +#endif +#endif + } /* end of while (csrScanResultGetNext) */ + /* set the scan results for next iteration */ + pScanResultList = pScanResultListSaved; + + /* if some candidates were found, then no need to repeat */ + if (numCandidates) + break; + /* + * if ageConstraint is already false, we have done two + * iterations and no candidate were found */ + if (ageConstraint == eANI_BOOLEAN_FALSE) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: No roam able candidates found", __func__); + break; + } + /* + * if all candidates were dropped rescan the scan + * list but this time without age constraint. + */ + ageConstraint = eANI_BOOLEAN_FALSE; + /* if no candidates were dropped no need to repeat */ + } while (numAPsDropped); + + /* + * Now we have all the scan results in our local list. Good time to free + * up the the list we got as a part of csrGetScanResult + */ + csrScanResultPurge(pMac, *pScanResultList); + + return roamNow; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamHandleEmptyScanResult + + \brief This function will be invoked in CFG_CHAN_LIST_SCAN state when + there are no valid APs in the scan result for roaming. This means + our AP is the best and no other AP is around. No point in scanning + again and again. Performing the following here. + 1. Stop the neighbor scan timer. + 2a. If this is the first time we encountered empty scan, then + re-register with TL with modified lookup threshold. + 2b. Else if this is the second time we encountered empty scan, + then start neighbor scan results refresh timer (20s). + 2c. Else, nothing more to do. + NOTE: In LFR, channels selected for scanning is derived from + the occupied channel list. Scan cycle following one which + yielded empty results is split into two halves: (i) scan on + channels in the occupied list, and (ii) scan on channels not + in the occupied list. This helps converging faster (while + looking for candidates in the occupied list first), and also, + adds channels to the occupied channel list upon finding candidates + matching SSID profile of interest. + + uEmptyScanCount Comments + eFirstEmptyScan Previous scan was done on channels in the + occupied list and yielded potential candidates. + This scan cycle was likely triggered through + receipt of lookup DOWN notification event. + eSecondEmptyScan Previous scan was done on channels in the + occupied list and yielded no candidates. This scan + cycle was triggered through RSSI notification + with modified lookup threshold. + eThirdEmptyScan Previous scan was done on channels NOT in + the occupied list and yielded no candidates. This + scan cycle was triggered immediately after scanning + channels in the occupied list and no candidates + were found. + eFourthEmptyScan Previous scan was done on channels in the + occupied list and yielded no candidates. This scan + cycle was triggered upon expiry of + neighborScanResultsRefreshPeriod (=20s). + eFifthEmptyScan Previous scan was done on channels NOT in + the occupied list and yielded no candidates. This + scan cycle was triggered immediately after scanning + channels in the occupied list and no candidates + were found. + + [1], [2,3] and [4,5] together form one discrete set of scan cycle. + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +static VOS_STATUS csrNeighborRoamHandleEmptyScanResult(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpFTRoamCallbackUsrCtx pUsrCtx; + +#ifdef FEATURE_WLAN_LFR + tANI_BOOLEAN performPeriodicScan = + (pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod) ? TRUE : FALSE; +#endif + + /* Stop neighbor scan timer */ + vos_timer_stop(&pNeighborRoamInfo->neighborScanTimer); + /* + * Increase the neighbor lookup threshold by 3 dB + * after every scan cycle. NOTE: uEmptyScanCount + * would be either 1, 3 or 5 at the end of every + * scan cycle. + */ +#ifdef FEATURE_WLAN_LFR + if ((++pNeighborRoamInfo->uEmptyScanCount) > eFifthEmptyScan) + { + pNeighborRoamInfo->uEmptyScanCount = eFifthEmptyScan; + } + if (((0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) || + (abs(pNeighborRoamInfo->lookupDOWNRssi) > + abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold))) && + ((pNeighborRoamInfo->uEmptyScanCount == eSecondEmptyScan) || + (pNeighborRoamInfo->uEmptyScanCount == eFourthEmptyScan))) + { + /* + * If the scan was triggered due to lookupDOWNRssi > reassoc threshold, + * then it would be a contiguous scan on all valid non-DFS channels. + * If channels are configured in INI, then only those channels need + * to be scanned. + * In either of these modes, there is no need to trigger an immediate + * scan upon empty scan results for the second and fourth time (which + * would be equivalent to scanning on channels in non-occupied list). + * Incrementing uEmptyScanCount will correspond to skipping this step. + * NOTE: double increment of uEmptyScanCount corresponds to completion + * of scans on all valid channels. + */ + ++pNeighborRoamInfo->uEmptyScanCount; + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, "Extra increment of empty scan count (=%d)" + " in contiguous scan mode", pNeighborRoamInfo->uEmptyScanCount); + } +#endif + if (((pNeighborRoamInfo->currentNeighborLookupThreshold+3) < + pNeighborRoamInfo->cfgParams.neighborReassocThreshold) +#ifdef FEATURE_WLAN_LFR + && ((pNeighborRoamInfo->uEmptyScanCount % 2) == 1) +#endif + ) + { + pNeighborRoamInfo->currentNeighborLookupThreshold += 3; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Clear off the old neighbor report details */ + vos_mem_zero(&pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT); +#endif + + /* Transition to CONNECTED state */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + sessionId); + + /* Reset all the necessary variables before transitioning to the CONNECTED state */ + csrNeighborRoamResetConnectedStateControlInfo(pMac, sessionId); + +#ifdef FEATURE_WLAN_LFR + if (pNeighborRoamInfo->uEmptyScanCount == eFirstEmptyScan) + { +#endif + /* Empty scan results for the first time */ + /* Re-register neighbor lookup DOWN threshold callback with TL */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Registering DOWN event neighbor lookup callback with TL for RSSI = %d"), + pNeighborRoamInfo->currentNeighborLookupThreshold * (-1)); + + /* This user context data will be returned with callback */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME, pUsrCtx); + + vos_mem_free(pUsrCtx); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL("Couldn't re-register csrNeighborRoamNeighborLookupDOWNCallback" + " with TL: Status = %d"), status); + } + +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->lookupDOWNRssi = 0; + } + else if ((pNeighborRoamInfo->uEmptyScanCount == eSecondEmptyScan) || + (pNeighborRoamInfo->uEmptyScanCount == eFourthEmptyScan)) + { + /* Empty scan results for the second or fourth time */ + + /* Immediately scan on channels in non-occupied list */ + csrNeighborRoamTransitToCFGChanScan(pMac, sessionId); + } + else if (pNeighborRoamInfo->uEmptyScanCount >= eThirdEmptyScan) + { + /* Empty scan results for the third time */ + if (performPeriodicScan) + { + smsLog(pMac, LOGE, FL("Performing periodic scan, uEmptyScanCount=%d"), + pNeighborRoamInfo->uEmptyScanCount); + + /* + * Set uEmptyScanCount to MAX so that we always enter this + * condition on subsequent empty scan results + */ + pNeighborRoamInfo->uEmptyScanCount = eMaxEmptyScan; + + /* From here on, ONLY scan on channels in the occupied list */ + pNeighborRoamInfo->uScanMode = SPLIT_SCAN_OCCUPIED_LIST; + + /* Start empty scan refresh timer */ + if (VOS_STATUS_SUCCESS != + vos_timer_start(&pNeighborRoamInfo->emptyScanRefreshTimer, + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod)) + { + smsLog(pMac, LOGE, FL("Empty scan refresh timer failed to start (%d)"), + status); + vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + vosStatus = VOS_STATUS_E_FAILURE; + } + else + { + smsLog(pMac, LOGE, FL("Empty scan refresh timer started (%d ms)"), + (pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod)); + } + } + else if (eThirdEmptyScan == pNeighborRoamInfo->uEmptyScanCount) + { + /* Start neighbor scan results refresh timer */ + if (VOS_STATUS_SUCCESS != + vos_timer_start(&pNeighborRoamInfo->neighborResultsRefreshTimer, + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod)) + { + smsLog(pMac, LOGE, FL("Neighbor results refresh timer failed to start (%d)"), + status); + vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + vosStatus = VOS_STATUS_E_FAILURE; + } + else + { + smsLog(pMac, LOG2, FL("Neighbor results refresh timer started (%d ms)"), + (pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * VOS_TIMER_TO_MS_UNIT)); + } + } + } + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, "Neighbor roam empty scan count=%d scan mode=%d", + pNeighborRoamInfo->uEmptyScanCount, pNeighborRoamInfo->uScanMode); +#endif + return vosStatus; +} + + +static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrScanResultFilter scanFilter; + tScanResultHandle scanResult; + tANI_U32 tempVal = 0; + tANI_BOOLEAN roamNow = eANI_BOOLEAN_FALSE; + eHalStatus hstatus; + tpFTRoamCallbackUsrCtx pUsrCtx; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + /* If the state is REPORT_SCAN, then this must be the scan after the REPORT_QUERY state. So, we + should use the BSSID filter made out of neighbor reports */ + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!csrRoamIsRoamOffloadScanEnabled(pMac)) +#endif + ) + { + hstatus = csrNeighborRoamBssIdScanFilter(pMac, sessionId, &scanFilter); + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R or ESE Association: Prepare scan filter status with neighbor AP = %d"), hstatus); + tempVal = 1; + } + else +#endif + { + hstatus = csrNeighborRoamPrepareScanProfileFilter(pMac, + &scanFilter, sessionId); + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R/ESE/Other Association: Prepare scan to find neighbor AP filter status = %d"), hstatus); + } + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Scan Filter preparation failed for Assoc type %d.. Bailing out.."), tempVal); + return eHAL_STATUS_FAILURE; + } + hstatus = csrScanGetResult(pMac, &scanFilter, &scanResult); + if (hstatus != eHAL_STATUS_SUCCESS) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Get Scan Result status code %d"), hstatus); + } + /* Process the scan results and update roam able AP list */ + roamNow = csrNeighborRoamProcessScanResults(pMac, sessionId, + &scanResult); + + /* Free the scan filter */ + csrFreeScanFilter(pMac, &scanFilter); + + tempVal = csrLLCount(&pNeighborRoamInfo->roamableAPList); + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + switch(pNeighborRoamInfo->neighborRoamState) + { + case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: + if (tempVal) + { +#ifdef FEATURE_WLAN_LFR + /* + * Since there are non-zero candidates found + * after the scan, reset empty scan count. + */ + pNeighborRoamInfo->uEmptyScanCount = 0; + pNeighborRoamInfo->uScanMode = DEFAULT_SCAN; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + /* + * If this is a non-11r association, then we can register + * the reassoc callback here as we have some APs in the + * roam able AP list + */ + if (pNeighborRoamInfo->is11rAssoc) { + /* Valid APs are found after scan. Now we can initiate + pre-authentication */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN, + sessionId) + } else +#endif +#ifdef FEATURE_WLAN_ESE + /* + * If this is a non-11r association, then we can register + * the reassoc callback here as we have some APs in the + * roam able AP list + */ + if (pNeighborRoamInfo->isESEAssoc) { + /* Valid APs are found after scan. Now we can initiate + pre-authentication */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN, + sessionId) + } else +#endif +#ifdef FEATURE_WLAN_LFR + /* + * If LFR is enabled, then we can register the reassoc + * callback here as we have some APs in the roam able + * AP list + */ + if (csrRoamIsFastRoamEnabled(pMac, sessionId)) { + /* Valid APs are found after scan. Now we can initiate + pre-authentication */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN, + sessionId) + } else +#endif + { + + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Completed scanning of CFG CHAN LIST in non-11r association. Registering reassoc callback")); + /* Nothing much to do now. Will continue to remain in this state in case of non-11r association */ + } + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("No candidate found after" + "scanning in state %s .. "), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + /* Handle it appropriately */ + csrNeighborRoamHandleEmptyScanResult(pMac, sessionId); + } + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN: + if (!tempVal) + { + smsLog(pMac, LOGE, + FL("No candidate found after scanning" + "in state %s .. "), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + /* Stop the timer here as the same timer will be started again in CFG_CHAN_SCAN_STATE */ + csrNeighborRoamTransitToCFGChanScan(pMac, sessionId); + } + break; +#endif /* WLAN_FEATURE_VOWIFI_11R */ + default: + // Can come only in INIT state. Where in we are associated, we sent scan and user + // in the meantime decides to disassoc, we will be in init state and still received call + // back issued. Should not come here in any other state, printing just in case + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("State %s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + // Lets just exit out silently. + return eHAL_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + + if (tempVal) + { + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + if (roamNow) + { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Immediate roam-deregister UP indication. RSSI = %d"), + NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + + csrNeighborRoamTriggerHandoff(pMac, sessionId); + return eHAL_STATUS_SUCCESS; + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + hstatus = vos_timer_start( + &pNeighborRoamInfo->neighborResultsRefreshTimer, + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod); + + /* This timer should be started before registering the Reassoc + * callback with TL. This is because, it is very likely that the + * callback getting called immediately and the timer would never + * be stopped when pre-auth is in progress */ + if (hstatus != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, FL( + "Neighbor results refresh timer failed to start, status = %d"), + hstatus); + vos_mem_free( + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = + NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = + 0; + return eHAL_STATUS_FAILURE; + } + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL( + "Registering DOWN event Reassoc callback with TL. RSSI = %d"), + pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1)); + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Allocation failed for pUsrCtx")); + return eHAL_STATUS_FAILURE; + } + + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + /* Register a reassoc Indication callback */ + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamReassocIndCallback, + VOS_MODULE_ID_SME, pUsrCtx); + vos_mem_free(pUsrCtx); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGW, FL( + "Couldn't register with TL: Status = %d"), + vosStatus); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + if (!tempVal || !roamNow) + { + if ((eSME_ROAM_TRIGGER_SCAN == pNeighborRoamInfo->cfgRoamEn) || + (eSME_ROAM_TRIGGER_FAST_ROAM == pNeighborRoamInfo->cfgRoamEn)) + { + /* This is ioctl based roaming if we did not find any roamable + * candidate then just log it. */ + smsLog(pMac, LOGE, + FL("tempVal = %u, roamNow = %d uOsRequestedHandoff = %d"), + tempVal, roamNow, pNeighborRoamInfo->uOsRequestedHandoff); + } + else + { + if (pNeighborRoamInfo->uOsRequestedHandoff) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, + REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + pNeighborRoamInfo->uOsRequestedHandoff = 0; + } + else + { + /* There is no candidate or We are not roaming Now. + * Inform the FW to restart Roam Offload Scan */ + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_RESTART, + REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + } + } + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + sessionId); + } + } +#endif + return eHAL_STATUS_SUCCESS; + +} + + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamScanRequestCallback + + \brief This function is the callback function registered in csrScanRequest() to + indicate the completion of scan. If scan is completed for all the channels in + the channel list, this function gets the scan result and starts the refresh results + timer to avoid having stale results. If scan is not completed on all the channels, + it restarts the neighbor scan timer which on expiry issues scan on the next + channel + + \param halHandle - The handle returned by macOpen. + pContext - not used + scanId - not used + status - not used + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, + void *pContext, tANI_U8 sessionId, + tANI_U32 scanId, eCsrScanStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 currentChanIndex; + eHalStatus hstatus; + + if (NULL != pContext) + { +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsStaMode(pMac, sessionId)) + { + smsLog(pMac, LOGE, + FL("Ignoring scan request callback on non-infra" + "session %d in state %s"), + sessionId, macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + + if (!csrRoamIsFastRoamEnabled(pMac,sessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } +#endif + } + + pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE; + + /* This can happen when we receive a UP event from TL in any of the scan states. Silently ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + + /* -1 is done because the chanIndex would have got incremented after + issuing a successful scan request */ + currentChanIndex = (pNeighborRoamInfo->roamChannelInfo.currentChanIndex) ? (pNeighborRoamInfo->roamChannelInfo.currentChanIndex - 1) : 0; + + /* Validate inputs */ + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList) { + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + FL("csrNeighborRoamScanRequestCallback received for Channel = %d, " + "ChanIndex = %d"), + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[currentChanIndex], + currentChanIndex); + } + else + { + smsLog(pMac, LOG1, FL("Received during clean-up. Silently ignore scan completion event.")); + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + + if (eANI_BOOLEAN_FALSE == pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress) + { + /* Scan is completed in the CFG_CHAN_SCAN state. We can transition to REPORT_SCAN state + just to get the results and perform PREAUTH */ + /* Now we have completed scanning the channel list. We have get the result by applying appropriate filter + sort the results based on neighborScore and RSSI and select the best candidate out of the list */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Channel list scan completed. Current chan index = %d"), currentChanIndex); + + if (pNeighborRoamInfo->roamChannelInfo.currentChanIndex != 0) + { + VOS_ASSERT(pNeighborRoamInfo->roamChannelInfo.currentChanIndex == 0); + return eHAL_STATUS_FAILURE; + } + + hstatus = csrNeighborRoamProcessScanComplete(pMac, sessionId); + + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_FAILURE; + } + } + else + { + + /* Restart the timer for the next scan sequence as scanning is not over */ + hstatus = vos_timer_start(&pNeighborRoamInfo->neighborScanTimer, + pNeighborRoamInfo->cfgParams.neighborScanPeriod); + if (eHAL_STATUS_SUCCESS != hstatus) + { + /* Timer start failed.. Should we ASSERT here??? */ + smsLog(pMac, LOGE, FL("Neighbor scan PAL Timer start failed, status = %d, Ignoring state transition"), status); + vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_FAILURE; + } + } + + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamScanResultRequestCallback + + \brief This function is the callback function registered in csrScanRequestLfrResult() to + indicate the completion of scan. If scan is completed for all the channels in + the channel list, this function gets the scan result and treats them as candidates + + \param halHandle - The handle returned by macOpen. + pContext - not used + scanId - not used + status - not used + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +static eHalStatus csrNeighborRoamScanResultRequestCallback(tHalHandle halHandle, + void *pContext, + tANI_U8 sessionId, + tANI_U32 scanId, + eCsrScanStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus hstatus; + + smsLog(pMac, LOG2, FL("called ")); + pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE; + + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it")); + return eHAL_STATUS_SUCCESS; + } + + /* Now we have completed scanning the channel list. We have get the result by applying appropriate filter + sort the results based on neighborScore and RSSI and select the best candidate out of the list */ + + hstatus = csrNeighborRoamProcessScanComplete(pMac, sessionId); + + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +#ifdef FEATURE_WLAN_LFR +static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHandle, + void *pContext, tANI_U8 sessionId, + tANI_U32 scanId, eCsrScanStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus hstatus = eHAL_STATUS_SUCCESS; + + if (NULL != pContext) + { + sessionId = *((tANI_U32*)pContext); + if (!csrRoamIsFastRoamEnabled(pMac,sessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + } + + pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE; + + /* This can happen when we receive a UP event from TL in any of the scan states. Silently ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + + if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGE, FL("Received in INIT state. Must have disconnected. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, "%s: process scan results", __func__); + hstatus = csrNeighborRoamProcessScanComplete(pMac, sessionId); + + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + } + + if (NULL != pContext) + vos_mem_free(pContext); + + return hstatus; +} +#endif + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIssueBgScanRequest + + \brief This function issues CSR scan request after populating all the BG scan params + passed + + \param pMac - The handle returned by macOpen. + pBgScanParams - Params that need to be populated into csr Scan request + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamIssueBgScanRequest(tpAniSirGlobal pMac, + tCsrBGScanRequest *pBgScanParams, + tANI_U32 sessionId, + csrScanCompleteCallback callbackfn) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 scanId; + tCsrScanRequest scanReq; + tANI_U8 channel; + void * userData = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (1 == pBgScanParams->ChannelInfo.numOfChannels) + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Channel = %d, ChanIndex = %d"), + pBgScanParams->ChannelInfo.ChannelList[0], + pNeighborRoamInfo->roamChannelInfo.currentChanIndex); + + //send down the scan req for 1 channel on the associated SSID + vos_mem_set(&scanReq, sizeof(tCsrScanRequest), 0); + /* Fill in the SSID Info */ + scanReq.SSIDs.numOfSSIDs = 1; + scanReq.SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo) * scanReq.SSIDs.numOfSSIDs); + if (NULL == scanReq.SSIDs.SSIDList) + { + //err msg + smsLog(pMac, LOGE, FL("Couldn't allocate memory for the SSID..Freeing memory allocated for Channel List")); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(scanReq.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) * scanReq.SSIDs.numOfSSIDs); + + scanReq.SSIDs.SSIDList[0].handoffPermitted = eANI_BOOLEAN_TRUE; + scanReq.SSIDs.SSIDList[0].ssidHidden = eANI_BOOLEAN_TRUE; + vos_mem_copy((void *)&scanReq.SSIDs.SSIDList[0].SSID, (void *)&pBgScanParams->SSID, sizeof(pBgScanParams->SSID)); + + scanReq.ChannelInfo.numOfChannels = pBgScanParams->ChannelInfo.numOfChannels; + if (1 == pBgScanParams->ChannelInfo.numOfChannels) + { + channel = pBgScanParams->ChannelInfo.ChannelList[0]; + scanReq.ChannelInfo.ChannelList = &channel; + } + else + { + scanReq.ChannelInfo.ChannelList = pBgScanParams->ChannelInfo.ChannelList; + } + + scanReq.BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; + scanReq.scanType = eSIR_ACTIVE_SCAN; + scanReq.requestType = eCSR_SCAN_HO_BG_SCAN; + scanReq.maxChnTime = pBgScanParams->maxChnTime; + scanReq.minChnTime = pBgScanParams->minChnTime; + + userData = vos_mem_malloc(sizeof(tANI_U32)); + if (NULL == userData) + { + smsLog(pMac, LOGE, FL("Failed to allocate memory for scan request")); + vos_mem_free(scanReq.SSIDs.SSIDList); + return eHAL_STATUS_FAILURE; + } + *((tANI_U32*)userData) = sessionId; + status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq, + &scanId, callbackfn, (void *) userData); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("CSR Scan Request failed with status %d"), status); + vos_mem_free(scanReq.SSIDs.SSIDList); + vos_mem_free(userData); + return status; + } + pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_TRUE; + + vos_mem_free(scanReq.SSIDs.SSIDList); + if (1 == pBgScanParams->ChannelInfo.numOfChannels) + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Channel List Address = %p, Actual index = %d"), + &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[0], + pNeighborRoamInfo->roamChannelInfo.currentChanIndex); + + return status; +} + +static void csrNeighborRoamFillNonChannelBgScanParams (tpAniSirGlobal pMac, + tANI_U8 sessionId, + tpCsrBGScanRequest bgScanParams) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 broadcastBssid[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + vos_mem_copy(bgScanParams->bssid, broadcastBssid, sizeof(tCsrBssid)); + bgScanParams->SSID.length = + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length; + vos_mem_copy(bgScanParams->SSID.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length); + + bgScanParams->minChnTime = pNeighborRoamInfo->cfgParams.minChannelScanTime; + bgScanParams->maxChnTime = pNeighborRoamInfo->cfgParams.maxChannelScanTime; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamPerformBgScan + + \brief This function is invoked on every expiry of neighborScanTimer till all + the channels in the channel list are scanned. It populates necessary + parameters for BG scan and calls appropriate AP to invoke the CSR scan + request + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrBGScanRequest bgScanParams; + tANI_U8 channel = 0; + + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList + && + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels) { + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Channel List Address = %p"), &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[0]); + } + else + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Channel List Empty")); + // Go back and restart. Mostly timer start failure has occurred. + // When timer start is declared a failure, then we delete the list. + // Should not happen now as we stop and then only start the scan timer. + // still handle the unlikely case. + csrNeighborRoamHandleEmptyScanResult(pMac, sessionId); + return status; + } + + /* Validate the currentChanIndex value before using it to index the ChannelList array */ + if ( pNeighborRoamInfo->roamChannelInfo.currentChanIndex + > pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Invalid channel index: %d"), pNeighborRoamInfo->roamChannelInfo.currentChanIndex); + // Go back and restart. + csrNeighborRoamHandleEmptyScanResult(pMac, sessionId); + return status; + } + + /* Need to perform scan here before getting the list */ + + vos_mem_set(&bgScanParams, sizeof(tCsrBGScanRequest), 0); + + channel = pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[pNeighborRoamInfo->roamChannelInfo.currentChanIndex]; + bgScanParams.ChannelInfo.numOfChannels = 1; + bgScanParams.ChannelInfo.ChannelList = &channel; + + csrNeighborRoamFillNonChannelBgScanParams(pMac, sessionId, &bgScanParams); + /* Update the passive scan time for DFS channel */ + if ((TRUE == CSR_IS_CHANNEL_DFS(channel)) && + (CSR_ROAMING_DFS_CHANNEL_DISABLED != + pMac->roam.configParam.allowDFSChannelRoam)) + { + bgScanParams.minChnTime = pMac->roam.configParam.nPassiveMinChnTime; + bgScanParams.maxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; + } + + status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, + sessionId, csrNeighborRoamScanRequestCallback); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Issue of BG Scan request failed: Status = %d"), status); + } + + pNeighborRoamInfo->roamChannelInfo.currentChanIndex++; + if (pNeighborRoamInfo->roamChannelInfo.currentChanIndex >= + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Completed scanning channels in Channel List: CurrChanIndex = %d, Num Channels = %d"), + pNeighborRoamInfo->roamChannelInfo.currentChanIndex, + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels); + /* We have completed scanning all the channels */ + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0; + /* We are no longer scanning the channel list. Next timer firing should be used to get the scan results + and select the best AP in the list */ + if (eANI_BOOLEAN_TRUE == pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress) + { + pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE; + } + } + + if (eHAL_STATUS_SUCCESS != status) + { + /* + * If the status is not success, we need to call the callback + * routine so that the state machine does not get stuck. + */ + csrNeighborRoamScanRequestCallback(pMac, NULL, sessionId, 0, + eCSR_SCAN_FAILURE); + } + + return status; +} + +#ifdef FEATURE_WLAN_LFR +eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac, + tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrBGScanRequest bgScanParams; + tANI_U8 numOfChannels = 0, i = 0; + tANI_U8 *channelList = NULL; + tANI_U8 *pInChannelList = NULL; + tANI_U8 tmpChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + + vos_mem_set(&bgScanParams, sizeof(tCsrBGScanRequest), 0); + + /* Contiguously scan all channels from valid list */ + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("get valid channel list")); + + numOfChannels = sizeof(pMac->roam.validChannelList); + + if(!HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, + (tANI_U8 *)pMac->roam.validChannelList, + (tANI_U32 *) &numOfChannels))) + { + smsLog(pMac, LOGE, FL("Could not get valid channel list")); + return eHAL_STATUS_FAILURE; + } + pInChannelList = pMac->roam.validChannelList; + + if (CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac)) + { + csrNeighborRoamChannelsFilterByCurrentBand( + pMac, + sessionId, + pInChannelList, + numOfChannels, + tmpChannelList, + &numOfChannels); + pInChannelList = tmpChannelList; + } + + channelList = vos_mem_malloc(numOfChannels); + if ( NULL == channelList ) + { + smsLog(pMac, LOGE, FL("could not allocate memory for channelList")); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(channelList, (tANI_U8 *)pInChannelList, + numOfChannels * sizeof(tANI_U8)); + + bgScanParams.ChannelInfo.numOfChannels = numOfChannels; + bgScanParams.ChannelInfo.ChannelList = channelList; + for (i = 0; i < numOfChannels; i++) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, "%s: valid channel list = %d", + __func__, bgScanParams.ChannelInfo.ChannelList[i]); + } + csrNeighborRoamFillNonChannelBgScanParams(pMac, sessionId, &bgScanParams); + + status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, + sessionId, csrNeighborRoamContiguousScanRequestCallback); + + vos_mem_free(channelList); + + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Issue of BG Scan request failed: Status = %d"), status); + } + + return status; +} +#endif + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamNeighborScanTimerCallback + + \brief This function is the neighbor scan timer callback function. It invokes + the BG scan request based on the current and previous states + + \param pv - CSR timer context info which includes pMac and session ID + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamNeighborScanTimerCallback(void *pv) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv; + tpAniSirGlobal pMac = pInfo->pMac; + tANI_U32 sessionId = pInfo->sessionId; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo; + + if (!pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("pMac is Null")); + return; + } + if (CSR_SESSION_ID_INVALID == sessionId) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("invalid sessionId")); + return; + } + + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + + // check if bg scan is on going, no need to send down the new params if true + if(eANI_BOOLEAN_TRUE == pNeighborRoamInfo->scanRspPending) + { + //msg + smsLog(pMac, LOGW, FL("Already BgScanRsp is Pending")); + return; + } + + switch (pNeighborRoamInfo->neighborRoamState) + { +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN: + switch(pNeighborRoamInfo->prevNeighborRoamState) + { + case eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY: + csrNeighborRoamPerformBgScan(pMac, sessionId); + break; + default: + smsLog(pMac, LOGE, + FL("Neighbor scan callback received in" + "state %s, prev state = %s"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->prevNeighborRoamState)); + break; + } + break; +#endif /* WLAN_FEATURE_VOWIFI_11R */ + case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: + csrNeighborRoamPerformBgScan(pMac, sessionId); + break; + default: + break; + } + return; +} + +void csrNeighborRoamEmptyScanRefreshTimerCallback(void *context) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *)context; + tpAniSirGlobal pMac = pInfo->pMac; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tANI_U32 sessionId = pInfo->sessionId; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo; + + if (!pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("pMac is Null")); + return; + } + if (CSR_SESSION_ID_INVALID == sessionId) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("invalid sessionId")); + return; + } + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + + /* Reset all the variables just as no scan had happened before */ + csrNeighborRoamResetConnectedStateControlInfo(pMac, sessionId); + +#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI + if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled)) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("11R Association:Neighbor Lookup Down event received in CONNECTED state")); + vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac, sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d"), vosStatus); + return; + } + /* Increment the neighbor report retry count after sending the neighbor request successfully */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++; + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE; + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY, + sessionId) + } else +#endif + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Non 11R or ESE Association:empty scan refresh timer expired")); + vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac, sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + return; + } + } + return; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamResultsRefreshTimerCallback + + \brief This function is the timer callback function for results + refresh timer. When this is invoked, it is as good as down event + received from TL. So, clear off the roam able AP list and start + the scan procedure based on 11R or non-11R association + + \param context - CSR timer context info which includes pMac and session ID + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamResultsRefreshTimerCallback(void *context) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *)context; + tpAniSirGlobal pMac = pInfo->pMac; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tANI_U32 sessionId = pInfo->sessionId; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo; + + if (!pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("pMac is Null")); + return; + } + if (CSR_SESSION_ID_INVALID == sessionId) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("invalid sessionId")); + return; + } + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event reassoc callback with TL. RSSI = %d"), pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1)); + + /* Deregister reassoc callback. Ignore return status */ + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->cfgParams.neighborReassocThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamReassocIndCallback, + VOS_MODULE_ID_SME); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGW, FL(" Couldn't deregister csrNeighborRoamReassocIndCallback with TL: Status = %d"), vosStatus); + } + + /* Reset all the variables just as no scan had happened before */ + csrNeighborRoamResetConnectedStateControlInfo(pMac, pInfo->sessionId); + +#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI + if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled)) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("11R Association:Neighbor Lookup Down event received in CONNECTED state")); + vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac, sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d"), vosStatus); + return; + } + /* Increment the neighbor report retry count after sending the neighbor request successfully */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++; + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE; + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY, + sessionId) + } + else +#endif + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Non 11R or ESE Association:results refresh timer expired")); + vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac, sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + return; + } + } + return; +} + +#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIssueNeighborRptRequest + + \brief This function is invoked when TL issues a down event and the current assoc + is a 11R association. It invokes SME RRM API to issue the neighbor request to + the currently associated AP with the current SSID + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamIssueNeighborRptRequest(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tRrmNeighborRspCallbackInfo callbackInfo; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tRrmNeighborReq neighborReq; + tpFTRoamCallbackUsrCtx pUsrCtx; + + /* This user context data will be returned with callback */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + neighborReq.no_ssid = 0; + + /* Fill in the SSID */ + neighborReq.ssid.length = + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length; + vos_mem_copy(neighborReq.ssid.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length); + + callbackInfo.neighborRspCallback = csrNeighborRoamRRMNeighborReportResult; + callbackInfo.neighborRspCallbackContext = pUsrCtx; + callbackInfo.timeout = pNeighborRoamInfo->FTRoamInfo.neighborReportTimeout; + + return sme_NeighborReportRequest(pMac, sessionId, &neighborReq, + &callbackInfo); +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamChannelsFilterByCurrentBand + + \brief This function is used to filter out the channels + based on the currently associated AP channel + + \param pMac - The handle returned by macOpen. + \param pInputChannelList - The input channel list + \param inputNumOfChannels - The number of channels in input channel list + \param pOutputChannelList - The output channel list + \param outputNumOfChannels - The number of channels in output channel list + \param pMergedOutputNumOfChannels - The final number of channels in the output channel list. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ + +VOS_STATUS csrNeighborRoamChannelsFilterByCurrentBand( + tpAniSirGlobal pMac, + tANI_U8 sessionId, + tANI_U8* pInputChannelList, + tANI_U8 inputNumOfChannels, + tANI_U8* pOutputChannelList, + tANI_U8* pMergedOutputNumOfChannels + ) +{ + tANI_U8 i = 0; + tANI_U8 numChannels = 0; + tANI_U8 currAPoperationChannel = + pMac->roam.neighborRoamInfo[sessionId].currAPoperationChannel; + // Check for NULL pointer + if (!pInputChannelList) return VOS_STATUS_E_INVAL; + + // Check for NULL pointer + if (!pOutputChannelList) return VOS_STATUS_E_INVAL; + + if (inputNumOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Input Channels %d", + __func__, inputNumOfChannels); + return VOS_STATUS_E_INVAL; + } + for (i = 0; i < inputNumOfChannels; i++) + { + if (GetRFBand(currAPoperationChannel) == GetRFBand(pInputChannelList[i])) + { + pOutputChannelList[numChannels] = pInputChannelList[i]; + numChannels++; + } + } + + // Return final number of channels + *pMergedOutputNumOfChannels = numChannels; + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamMergeChannelLists + + \brief This function is used to merge two channel list. + NB: If called with outputNumOfChannels == 0, this routines + simply copies the input channel list to the output channel list. + if number of merged channels are more than 100, num of channels + set to 100 + + \param pMac - The handle returned by macOpen. + \param pInputChannelList - The additional channels to merge in to the "merged" channels list. + \param inputNumOfChannels - The number of additional channels. + \param pOutputChannelList - The place to put the "merged" channel list. + \param outputNumOfChannels - The original number of channels in the "merged" channels list. + \param pMergedOutputNumOfChannels - The final number of channels in the "merged" channel list. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamMergeChannelLists( + tpAniSirGlobal pMac, + tANI_U8 *pInputChannelList, + tANI_U8 inputNumOfChannels, + tANI_U8 *pOutputChannelList, + tANI_U8 outputNumOfChannels, + tANI_U8 *pMergedOutputNumOfChannels + ) +{ + tANI_U8 i = 0; + tANI_U8 j = 0; + tANI_U8 numChannels = outputNumOfChannels; + + // Check for NULL pointer + if (!pInputChannelList) return VOS_STATUS_E_INVAL; + + // Check for NULL pointer + if (!pOutputChannelList) return VOS_STATUS_E_INVAL; + + if (inputNumOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Input Channels %d", + __func__, inputNumOfChannels); + return VOS_STATUS_E_INVAL; + } + if (outputNumOfChannels >= WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Output Channels %d", + __func__, outputNumOfChannels); + return VOS_STATUS_E_INVAL; + } + // Add the "new" channels in the input list to the end of the output list. + for (i = 0; i < inputNumOfChannels; i++) + { + for (j = 0; j < outputNumOfChannels; j++) + { + if (pInputChannelList[i] == pOutputChannelList[j]) + break; + } + if (j == outputNumOfChannels) + { + if (pInputChannelList[i]) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: [INFOLOG] Adding extra %d to Neighbor channel list", __func__, + pInputChannelList[i]); + pOutputChannelList[numChannels] = pInputChannelList[i]; + numChannels++; + } + } + if (numChannels >= WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Merge Neighbor channel list reached Max " + "limit %d", __func__, + numChannels); + break; + } + } + + // Return final number of channels + *pMergedOutputNumOfChannels = numChannels; + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamCreateChanListFromNeighborReport + + \brief This function is invoked when neighbor report is received for the + neighbor request. Based on the channels present in the neighbor report, + it generates channel list which will be used in REPORT_SCAN state to + scan for these neighbor APs + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpRrmNeighborReportDesc pNeighborBssDesc; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 numChannels = 0; + tANI_U8 i = 0; + tANI_U8 channelList[MAX_BSS_IN_NEIGHBOR_RPT]; + tANI_U8 mergedOutputNumOfChannels = 0; + + /* This should always start from 0 whenever we create a channel list out of neighbor AP list */ + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + + pNeighborBssDesc = smeRrmGetFirstBssEntryFromNeighborCache(pMac); + + while (pNeighborBssDesc) + { + if (pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport >= MAX_BSS_IN_NEIGHBOR_RPT) break; + + /* Update the neighbor BSS Info in the 11r FT Roam Info */ + pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport].channelNum = + pNeighborBssDesc->pNeighborBssDescription->channel; + pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport].neighborScore = + (tANI_U8)pNeighborBssDesc->roamScore; + vos_mem_copy(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo[pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport].neighborBssId, + pNeighborBssDesc->pNeighborBssDescription->bssId, sizeof(tSirMacAddr)); + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport++; + + /* Saving the channel list non-redundantly */ + for (i = 0; (i < numChannels && i < MAX_BSS_IN_NEIGHBOR_RPT); i++) + { + if (pNeighborBssDesc->pNeighborBssDescription->channel == channelList[i]) + break; + } + + if (i == numChannels) + { + if (pNeighborBssDesc->pNeighborBssDescription->channel) + { + if (CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac)) + { + // Make sure to add only if its the same band + if (GetRFBand(pNeighborRoamInfo->currAPoperationChannel) == + GetRFBand(pNeighborBssDesc->pNeighborBssDescription->channel)) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: [INFOLOG] Adding %d to Neighbor channel list (Same band)\n", __func__, + pNeighborBssDesc->pNeighborBssDescription->channel); + channelList[numChannels] = pNeighborBssDesc->pNeighborBssDescription->channel; + numChannels++; + } + } + else + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: [INFOLOG] Adding %d to Neighbor channel list\n", __func__, + pNeighborBssDesc->pNeighborBssDescription->channel); + channelList[numChannels] = pNeighborBssDesc->pNeighborBssDescription->channel; + numChannels++; + } + } + } + + pNeighborBssDesc = smeRrmGetNextBssEntryFromNeighborCache(pMac, pNeighborBssDesc); + } + + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList) + { + vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + } + + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + /* Store the obtained channel list to the Neighbor Control data structure */ + if (numChannels) + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = vos_mem_malloc((numChannels) * sizeof(tANI_U8)); + if (NULL == pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList) + { + smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed.. TL event ignored")); + return VOS_STATUS_E_RESOURCES; + } + + vos_mem_copy(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList, + channelList, (numChannels) * sizeof(tANI_U8)); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = numChannels; + /* + * Create a Union of occupied channel list learnt by the DUT along with the Neighbor + * report Channels. This increases the chances of the DUT to get a candidate AP while + * roaming even if the Neighbor Report is not able to provide sufficient information. + * */ + if (pMac->scan.occupiedChannels[sessionId].numChannels) { + csrNeighborRoamMergeChannelLists(pMac, + &pMac->scan.occupiedChannels[sessionId].channelList[0], + pMac->scan.occupiedChannels[sessionId].numChannels, + &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList[0], + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels, + &mergedOutputNumOfChannels); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = + mergedOutputNumOfChannels; + + } + /*Indicate the firmware about the update only if any new channels are added. + * Otherwise, the firmware would already be knowing the non-IAPPneighborlist + * channels. There is no need to update.*/ + if (numChannels) + { + smsLog(pMac, LOG1, + FL("IAPP Neighbor list callback received as expected" + "in state %s."), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_TRUE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + } +#endif + } + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0; + pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE; + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamRRMNeighborReportResult + + \brief This function is the neighbor report callback that will be invoked by + SME RRM on receiving a neighbor report or of neighbor report is not + received after timeout. On receiving a valid report, it generates a + channel list from the neighbor report and starts the + neighbor scan timer + + \param context - The handle returned by macOpen. + vosStatus - Status of the callback(SUCCESS/FAILURE) + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamRRMNeighborReportResult(void *context, VOS_STATUS vosStatus) +{ + tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *)context; + tANI_U32 sessionId = pUsrCtx->sessionId; + tpAniSirGlobal pMac = pUsrCtx->pMac; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(pMac, LOG1, FL("Neighbor report result callback with status = %d"), vosStatus); + switch (pNeighborRoamInfo->neighborRoamState) + { + case eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY: + /* Reset the report pending variable */ + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_FALSE; + if (VOS_STATUS_SUCCESS == vosStatus) + { + /* Need to create channel list based on the neighbor AP list and transition to REPORT_SCAN state */ + vosStatus = csrNeighborRoamCreateChanListFromNeighborReport( + pMac, + sessionId); + if (VOS_STATUS_SUCCESS == vosStatus) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Channel List created from Neighbor report, Transitioning to NEIGHBOR_SCAN state")); + } + + /* We are gonna scan now. Remember the time stamp to filter out + results only after this time stamp */ + pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + /* Now ready for neighbor scan based on the channel list created */ + status = vos_timer_start(&pNeighborRoamInfo->neighborScanTimer, + pNeighborRoamInfo->cfgParams.neighborScanPeriod); + if (eHAL_STATUS_SUCCESS != status) + { + /* Timer start failed.. Should we ASSERT here??? */ + smsLog(pMac, LOGE, FL("PAL Timer start for neighbor scan timer failed, status = %d, Ignoring state transition"), status); + vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + vos_mem_free(pUsrCtx); + return; + } + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + /* Neighbor scan timer started. Transition to REPORT_SCAN state */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN, + sessionId) + } + else + { + /* Neighbor report timeout happened in SME RRM. We can try sending more neighbor requests until we + reach the maxNeighborRetries or receiving a successful neighbor response */ + smsLog(pMac, LOGE, FL("Neighbor report result failed after %d retries, MAX RETRIES = %d"), + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum, pNeighborRoamInfo->cfgParams.maxNeighborRetries); + if (pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum >= + pNeighborRoamInfo->cfgParams.maxNeighborRetries) + { + smsLog(pMac, LOGE, FL("Bailing out to CFG Channel list scan.. ")); + vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac, + sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + smsLog(pMac, LOGE, FL("Transit to CFG Channel list scan state failed with status %d "), vosStatus); + vos_mem_free(pUsrCtx); + return; + } + /* We transitioned to different state now. Reset the Neighbor report retry count */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + } + else + { + vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac, + sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d"), vosStatus); + vos_mem_free(pUsrCtx); + return; + } + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE; + /* Increment the neighbor report retry count after sending the neighbor request successfully */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++; + } + } + break; + default: + smsLog(pMac, LOGE, + FL("Neighbor result callback not expected in" + "state %s, Ignoring.."), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + break; + } + vos_mem_free(pUsrCtx); + return; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + +#ifdef FEATURE_WLAN_LFR +tANI_BOOLEAN csrNeighborRoamIsSsidAndSecurityMatch( + tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pCurProfile, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + tCsrAuthList authType; + tCsrEncryptionList uCEncryptionType; + tCsrEncryptionList mCEncryptionType; + tANI_BOOLEAN fMatch = FALSE; + + authType.numEntries = 1; + authType.authType[0] = pCurProfile->AuthType; + uCEncryptionType.numEntries = 1; + uCEncryptionType.encryptionType[0] = pCurProfile->EncryptionType; + mCEncryptionType.numEntries = 1; + mCEncryptionType.encryptionType[0] = pCurProfile->mcEncryptionType; + + if( pIes ) + { + if(pIes->SSID.present) + { + fMatch = csrIsSsidMatch( pMac, + (void *)pCurProfile->SSID.ssId, pCurProfile->SSID.length, + pIes->SSID.ssid, pIes->SSID.num_ssid, + eANI_BOOLEAN_TRUE ); + if(TRUE == fMatch) + { + /* + * for now we are sending NULL for all PMF related filter + * parameters during roam to the neighbor AP because + * so far 80211W spec doesn't specify anything about + * roaming scenario. + * + * Once roaming scenario is defined, we should re-visit + * this section and remove this comment. + */ + fMatch = csrIsSecurityMatch(pMac, &authType, &uCEncryptionType, + &mCEncryptionType, + NULL, NULL, NULL, + pBssDesc, pIes, NULL, NULL, NULL); + return (fMatch); + } + else + { + return (fMatch); + } + + } + else + { + return FALSE; // Treat a missing SSID as a non-match. + } + } + else + { + return FALSE; // Again, treat missing pIes as a non-match. + } +} + +tANI_BOOLEAN csrNeighborRoamIsNewConnectedProfile(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamConnectedProfile *pCurrProfile = NULL; + tCsrRoamConnectedProfile *pPrevProfile = NULL; + tDot11fBeaconIEs *pIes = NULL; + tSirBssDescription *pBssDesc = NULL; + tANI_BOOLEAN fNew = TRUE; + + if(!(pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId))) + { + return (fNew); + } + + pCurrProfile = &pMac->roam.roamSession[sessionId].connectedProfile; + if( !pCurrProfile ) + { + return (fNew); +} + + pPrevProfile = &pNeighborRoamInfo->prevConnProfile; + if( !pPrevProfile ) + { + return (fNew); + } + + pBssDesc = pPrevProfile->pBssDesc; + if (pBssDesc) + { + if (HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + pBssDesc, &pIes)) && + csrNeighborRoamIsSsidAndSecurityMatch(pMac, pCurrProfile, pBssDesc, pIes)) + { + fNew = FALSE; + } + if (pIes) + { + vos_mem_free(pIes); + } + } + + if (fNew) + { + smsLog(pMac, LOG1, FL("Prev roam profile did not match current")); + } + else + { + smsLog(pMac, LOG1, FL("Prev roam profile matches current")); + } + + return (fNew); +} + +tANI_BOOLEAN csrNeighborRoamConnectedProfileMatch( + tpAniSirGlobal pMac, + tANI_U8 sessionId, + tCsrScanResult *pResult, + tDot11fBeaconIEs *pIes) +{ + tCsrRoamConnectedProfile *pCurProfile = NULL; + tSirBssDescription *pBssDesc = &pResult->Result.BssDescriptor; + + if( !(pMac->roam.roamSession + && CSR_IS_SESSION_VALID(pMac, sessionId))) + { + return FALSE; + } + + pCurProfile = &pMac->roam.roamSession[sessionId].connectedProfile; + + if( !pCurProfile) + { + return FALSE; + } + + return csrNeighborRoamIsSsidAndSecurityMatch(pMac, pCurProfile, pBssDesc, pIes); +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamPrepareNonOccupiedChannelList + + \brief This function is used to prepare a channel list that is derived from + the list of valid channels and does not include those in the occupied + list. + + \param pMac - The handle returned by macOpen. + \param pInputChannelList - The default channels list. + \param numOfChannels - The number of channels in the default channels list. + \param pOutputChannelList - The place to put the non-occupied channel list. + \param pOutputNumOfChannels - The number of channels in the non-occupied channel list. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamPrepareNonOccupiedChannelList( + tpAniSirGlobal pMac, + tANI_U8 sessionId, + tANI_U8 *pInputChannelList, + tANI_U8 numOfChannels, + tANI_U8 *pOutputChannelList, + tANI_U8 *pOutputNumOfChannels + ) +{ + tANI_U8 i = 0; + tANI_U8 outputNumOfChannels = 0; // Clear the output number of channels + tANI_U8 numOccupiedChannels = + pMac->scan.occupiedChannels[sessionId].numChannels; + tANI_U8 *pOccupiedChannelList = + pMac->scan.occupiedChannels[sessionId].channelList; + + for (i = 0; i < numOfChannels; i++) + { + if (!csrIsChannelPresentInList(pOccupiedChannelList, numOccupiedChannels, + pInputChannelList[i])) + { + /* DFS channel will be added in the list only when the + DFS Roaming scan flag is enabled*/ + if (CSR_IS_CHANNEL_DFS(pInputChannelList[i])) + { + if (CSR_ROAMING_DFS_CHANNEL_DISABLED != + pMac->roam.configParam.allowDFSChannelRoam) + { + pOutputChannelList[outputNumOfChannels++] = pInputChannelList[i]; + } + } + else + { + pOutputChannelList[outputNumOfChannels++] = pInputChannelList[i]; + } + } + } + + smsLog(pMac, LOG2, FL("Number of channels in the valid channel list=%d; " + "Number of channels in the non-occupied list list=%d"), + numOfChannels, outputNumOfChannels); + + // Return the number of channels + *pOutputNumOfChannels = outputNumOfChannels; + + return eHAL_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_LFR */ + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamTransitToCFGChanScan + + \brief This function is called whenever there is a transition to CFG chan scan + state from any state. It frees up the current channel list and allocates + a new memory for the channels received from CFG item. It then starts the + neighbor scan timer to perform the scan on each channel one by one + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + int i = 0; + tANI_U8 numOfChannels = 0; + tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tpCsrChannelInfo currChannelListInfo; + tANI_U8 scanChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + int outputNumOfChannels = 0; + + currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + + if ( +#ifdef FEATURE_WLAN_ESE + ((pNeighborRoamInfo->isESEAssoc) && + (pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived == eANI_BOOLEAN_FALSE)) || + (pNeighborRoamInfo->isESEAssoc == eANI_BOOLEAN_FALSE) || +#endif // ESE + currChannelListInfo->numOfChannels == 0) + { + smsLog(pMac, LOGW, FL("Building channel list to scan")); + + + /* Free up the channel list and allocate a new memory. This is because we dont know how much + was allocated last time. If we directly copy more number of bytes than allocated earlier, this might + result in memory corruption */ + if (NULL != currChannelListInfo->ChannelList) + { + vos_mem_free(currChannelListInfo->ChannelList); + currChannelListInfo->ChannelList = NULL; + currChannelListInfo->numOfChannels = 0; + } + + // Now obtain the contents for "channelList" (the "default valid channel list") from EITHER + // the gNeighborScanChannelList in "cfg.ini", OR the actual "valid channel list" information formed by CSR. + if (0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) + { + // Copy the "default valid channel list" (channelList) from the gNeighborScanChannelList in "cfg.ini". + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, "Using the channel list from cfg.ini"); + status = csrNeighborRoamMergeChannelLists( + pMac, + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList, + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels, + channelList, + 0, //NB: If 0, simply copy the input channel list to the output list. + &numOfChannels ); + + if (CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac)) + { + csrNeighborRoamChannelsFilterByCurrentBand( + pMac, + sessionId, + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList, + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels, + channelList, + &numOfChannels); + } + if(numOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + smsLog(pMac, LOGE, FL("Received wrong number of Channel list")); + return VOS_STATUS_E_INVAL; + } + /* Remove the DFS channels from CFG channel list when ' + gAllowRoamToDFS is disabled */ + if (pMac->roam.configParam.allowDFSChannelRoam == FALSE) { + for (i = 0; i < numOfChannels; i++) { + if (!(CSR_IS_CHANNEL_DFS(channelList[i]))) { + scanChannelList[outputNumOfChannels++] = channelList[i]; + } + } + } else { + /* Move all the channels to roam scan channel list */ + vos_mem_copy(scanChannelList, + channelList, + numOfChannels * sizeof(uint8_t)); + outputNumOfChannels = numOfChannels; + } + if (outputNumOfChannels == 0) + { + smsLog(pMac, LOGE, FL("No channels to scan")); + return VOS_STATUS_E_FAILURE; + } + currChannelListInfo->ChannelList = + vos_mem_malloc(outputNumOfChannels * sizeof(uint8_t)); + if (NULL == currChannelListInfo->ChannelList) + { + smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); + return VOS_STATUS_E_RESOURCES; + } + currChannelListInfo->numOfChannels = outputNumOfChannels; + vos_mem_copy(currChannelListInfo->ChannelList, + scanChannelList, outputNumOfChannels * sizeof(tANI_U8)); + } +#ifdef FEATURE_WLAN_LFR + else if ((pNeighborRoamInfo->uScanMode == DEFAULT_SCAN) && + (abs(pNeighborRoamInfo->lookupDOWNRssi) > + abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold))) + { + /* + * Trigger a contiguous scan on all channels when the + * RSSI in the lookup DOWN notification is below reassoc + * threshold. This will help us find the best available + * candidate and also update the channel cache. + */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, "Triggering contiguous scan " + "(lookupDOWNRssi=%d,reassocThreshold=%d)", + pNeighborRoamInfo->lookupDOWNRssi, + pNeighborRoamInfo->cfgParams.neighborReassocThreshold*(-1)); + + pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + vos_timer_stop(&pNeighborRoamInfo->neighborScanTimer); + + /* We are about to start a fresh scan cycle, + * purge non-P2P results from the past */ + csrScanFlushSelectiveResult(pMac, VOS_FALSE); + + csrNeighborRoamPerformContiguousBgScan(pMac, sessionId); + + /* Transition to CFG_CHAN_LIST_SCAN */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN, + sessionId); + + return VOS_STATUS_SUCCESS; + } +#endif + else + { + numOfChannels = pMac->scan.occupiedChannels[sessionId].numChannels; + if (numOfChannels +#ifdef FEATURE_WLAN_LFR + && ((pNeighborRoamInfo->uScanMode == SPLIT_SCAN_OCCUPIED_LIST) || + (pNeighborRoamInfo->uEmptyScanCount == 0) || + ((pNeighborRoamInfo->uEmptyScanCount % 2) == 1)) +#endif + ) + { + /* + * Always scan channels in the occupied channel list + * before scanning on the non-occupied list. + */ + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, "Switching to occupied channel list" +#ifdef FEATURE_WLAN_LFR + "-uScanMode=%d, uEmptyScanCount=%d", + pNeighborRoamInfo->uScanMode, + pNeighborRoamInfo->uEmptyScanCount +#endif + ); + if (CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac)) + { + csrNeighborRoamChannelsFilterByCurrentBand( + pMac, + sessionId, + pMac->scan.occupiedChannels[sessionId].channelList, + numOfChannels, + channelList, + &numOfChannels); + } + else + { + if (numOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + vos_mem_copy(channelList, + pMac->scan.occupiedChannels[sessionId].channelList, + numOfChannels * sizeof(tANI_U8)); + } + + /* Remove the DFS channels from CFG channel list when + * gAllowRoamToDFS is disabled + */ + if (pMac->roam.configParam.allowDFSChannelRoam == FALSE) { + for (i = 0; i < numOfChannels; i++) { + if (!(CSR_IS_CHANNEL_DFS(channelList[i]))) { + scanChannelList[outputNumOfChannels++] = + channelList[i]; + } + } + } else { + vos_mem_copy(scanChannelList, + channelList, + numOfChannels * (sizeof(uint8_t))); + outputNumOfChannels = numOfChannels; + } + if (outputNumOfChannels == 0) + { + smsLog(pMac, LOGE, FL("No channels to scan")); + return VOS_STATUS_E_FAILURE; + } + currChannelListInfo->ChannelList = + vos_mem_malloc(outputNumOfChannels * sizeof(tANI_U8)); + + if (NULL == currChannelListInfo->ChannelList) + { + smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); + return VOS_STATUS_E_RESOURCES; + } + if (numOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + currChannelListInfo->numOfChannels = outputNumOfChannels; + vos_mem_copy(currChannelListInfo->ChannelList, + scanChannelList, + outputNumOfChannels * sizeof(tANI_U8)); + } + else + { + /* Scan all channels from non-occupied list */ + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, "Get valid channel list"); + numOfChannels = sizeof(pMac->roam.validChannelList); + + if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, + (tANI_U8 *)pMac->roam.validChannelList, + (tANI_U32 *) &numOfChannels))) + { + if (numOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } +#ifdef FEATURE_WLAN_LFR + /* + * Prepare non-occupied channel list (channelList) + * from the actual "valid channel list" information + * formed by CSR. + */ + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, "Switching to non-occupied channel list"); + status = csrNeighborRoamPrepareNonOccupiedChannelList(pMac, + sessionId, + (tANI_U8 *)pMac->roam.validChannelList, + numOfChannels, + channelList, + &numOfChannels); +#else + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, "Merging channel list"); + status = csrNeighborRoamMergeChannelLists( + pMac, + (tANI_U8 *)pMac->roam.validChannelList, + numOfChannels, // The number of channels in the validChannelList + channelList, + 0, //NB: If 0, simply copy the input channel list to the output list. + &numOfChannels ); // The final number of channels in the output list. Will be numOfChannels +#endif + } + else + { + smsLog(pMac, LOGE, FL("Could not get valid channel list")); + return VOS_STATUS_E_FAILURE; + } + + if (CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac)) + { + csrNeighborRoamChannelsFilterByCurrentBand( + pMac, + sessionId, + (tANI_U8 *)pMac->roam.validChannelList, + numOfChannels, + channelList, + &numOfChannels); + } + if (numOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + if (outputNumOfChannels == 0) + { + smsLog(pMac, LOGE, FL("No channels to scan")); + return VOS_STATUS_E_FAILURE; + } + currChannelListInfo->ChannelList = + vos_mem_malloc(numOfChannels*sizeof(tANI_U8)); + + if (NULL == currChannelListInfo->ChannelList) + { + smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); + return VOS_STATUS_E_RESOURCES; + } + currChannelListInfo->numOfChannels = numOfChannels; +#ifdef FEATURE_WLAN_LFR + vos_mem_copy(currChannelListInfo->ChannelList, + channelList, numOfChannels * sizeof(tANI_U8)); +#else + vos_mem_copy(currChannelListInfo->ChannelList, + (tANI_U8 *)pMac->roam.validChannelList, + numOfChannels * sizeof(tANI_U8)); +#endif + } + } + + /* Adjust for the actual number that are used */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + "Number of channels from CFG (or) (non-)occupied list=%d", + currChannelListInfo->numOfChannels); + for (i = 0; i < currChannelListInfo->numOfChannels; i++) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, "Channel List from CFG (or) (non-)occupied list" + "= %d", currChannelListInfo->ChannelList[i]); + } + } + + /* We are gonna scan now. Remember the time stamp to filter out results + only after this time stamp */ + pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + vos_timer_stop(&pNeighborRoamInfo->neighborScanTimer); + status = vos_timer_start(&pNeighborRoamInfo->neighborScanTimer, + pNeighborRoamInfo->cfgParams.neighborScanPeriod); + + if (eHAL_STATUS_SUCCESS != status) + { + /* Timer start failed.. */ + smsLog(pMac, LOGE, FL("Neighbor scan PAL Timer start failed, status = %d, Ignoring state transition"), status); + vos_mem_free(currChannelListInfo->ChannelList); + currChannelListInfo->ChannelList = NULL; + currChannelListInfo->numOfChannels = 0; + return VOS_STATUS_E_FAILURE; + } + + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0; + pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE; + /* We are about to start a fresh scan cycle, + * purge non-P2P results from the past */ + csrScanFlushSelectiveResult(pMac, VOS_FALSE); + + /* We are about to start a fresh scan cycle, + * purge failed pre-auth results from the past */ + csrNeighborRoamPurgePreauthFailedList(pMac); + + /* Transition to CFG_CHAN_LIST_SCAN_STATE */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN, + sessionId) + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamNeighborLookupUpEvent + + \brief This function is called as soon as TL indicates that the current AP's + RSSI is better than the neighbor lookup threshold. Here, we transition to + CONNECTED state and reset all the scan parameters + + \param pMac - The handle returned by macOpen. + \param sessionId - Session ID + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamNeighborLookupUpEvent(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus; + tpFTRoamCallbackUsrCtx pUsrCtx; + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); + + /* Recheck whether the below check is needed. */ + if ((pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) + && (pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING)) + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + sessionId) +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsFastRoamEnabled(pMac, sessionId)) { + smsLog(pMac, LOGE, FL("LookUp event received when fast roam is " + "disabled. Ignore it")); + return eHAL_STATUS_SUCCESS; + } +#endif + /* Reset all the neighbor roam info control variables. Free all the allocated memory. It is like we are just associated now */ + csrNeighborRoamResetConnectedStateControlInfo(pMac, sessionId); + + /* This user context data will be returned with callback */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering DOWN event neighbor lookup callback with TL. RSSI = %d,"), pNeighborRoamInfo->currentNeighborLookupThreshold * (-1)); + /* Register Neighbor Lookup threshold callback with TL for DOWN event now */ + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME, pUsrCtx); +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->lookupDOWNRssi = 0; +#endif + vos_mem_free(pUsrCtx); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback DOWN event with TL: Status = %d"), vosStatus); + } + + + return vosStatus; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamNeighborLookupDownEvent + + \brief This function is called as soon as TL indicates that the current AP's + RSSI falls below the current neighbor lookup threshold. + Here, we transition to REPORT_QUERY for 11r association and + CFG_CHAN_LIST_SCAN state if the assoc is a non-11R association. + + \param pMac - The handle returned by macOpen. + \param sessionId - Session Id + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS csrNeighborRoamNeighborLookupDownEvent(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpFTRoamCallbackUsrCtx pUsrCtx; + + switch (pNeighborRoamInfo->neighborRoamState) + { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Deregistering DOWN event neighbor lookup callback with TL. RSSI = %d,"), + pNeighborRoamInfo->currentNeighborLookupThreshold * (-1)); + /* De-register Neighbor Lookup threshold callback with TL */ + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGW, FL(" Couldn't Deregister csrNeighborRoamNeighborLookupCallback DOWN event from TL: Status = %d"), vosStatus); + } +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsFastRoamEnabled(pMac, sessionId)) { + smsLog(pMac, LOGE, FL("LookDown event received when fast roam " + "is disabled. Ignore it")); + return eHAL_STATUS_SUCCESS; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI + if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled)) + { + + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("11R Association:Neighbor Lookup Down event received in CONNECTED state")); + vosStatus = csrNeighborRoamIssueNeighborRptRequest(pMac, + sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + smsLog(pMac, LOGE, FL("Neighbor report request failed. status = %d"), vosStatus); + return vosStatus; + } + /* Increment the neighbor report retry count after sending the neighbor request successfully */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum++; + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = eANI_BOOLEAN_TRUE; + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY, + sessionId) + } + else +#endif + { + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Non 11R or ESE Association:Neighbor Lookup Down event received in CONNECTED state")); + + vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac, sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("csrNeighborRoamTransitToCFGChanScan failed" + " with status=%d"), vosStatus); + return vosStatus; + } + } + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering UP event neighbor lookup callback with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + /* Register Neighbor Lookup threshold callback with TL for UP event now */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME, pUsrCtx); + vos_mem_free(pUsrCtx); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGE, + FL(" Couldn't register csrNeighborRoamNeighborLookupCallback" + "UP event with TL: Status = %d"), + status); + } + break; + default: + smsLog(pMac, LOGE, FL("DOWN event received in invalid" + "state %s ..Ignoring..."), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + break; + + } + return vosStatus; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamNeighborLookupUPCallback + + \brief This function is registered with TL to indicate whenever the RSSI + gets better than the neighborLookup RSSI Threshold + + \param pAdapter - VOS Context + trafficStatus - UP/DOWN indication from TL + pUserCtxt - Parameter for callback registered during callback registration. Should be pMac + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS +csrNeighborRoamNeighborLookupUPCallback (v_PVOID_t pAdapter, + v_U8_t rssiNotification, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi) +{ + tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *)pUserCtxt; + tANI_U32 sessionId = pUsrCtx->sessionId; + tpAniSirGlobal pMac = pUsrCtx->pMac; + VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS; + + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Neighbor Lookup UP indication callback called with notification %d Reported RSSI = %d"), + rssiNotification, + avgRssi); + + if (!csrIsConnStateConnectedInfra(pMac, sessionId)) { + smsLog(pMac, LOGW, FL("LookUp Event received when we are not connected. " + "Ignore it")); + vos_mem_free(pUsrCtx); + return VOS_STATUS_SUCCESS; + } + + if (WLANTL_HO_THRESHOLD_UP != rssiNotification) + { + VOS_ASSERT(WLANTL_HO_THRESHOLD_UP == rssiNotification); + vos_mem_free(pUsrCtx); + return VOS_STATUS_E_FAILURE; + } + vosStatus = csrNeighborRoamNeighborLookupUpEvent(pMac, sessionId); + vos_mem_free(pUsrCtx); + return vosStatus; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamNeighborLookupDOWNCallback + + \brief This function is registered with TL to indicate whenever the RSSI + falls below the current neighborLookup RSSI Threshold + + \param pAdapter - VOS Context + trafficStatus - UP/DOWN indication from TL + pUserCtxt - Parameter for callback registered during callback registration. Should be pMac + + \return VOS_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +VOS_STATUS +csrNeighborRoamNeighborLookupDOWNCallback (v_PVOID_t pAdapter, + v_U8_t rssiNotification, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi) +{ + tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *)pUserCtxt; + tANI_U32 sessionId = pUsrCtx->sessionId; + tpAniSirGlobal pMac = pUsrCtx->pMac; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = eHAL_STATUS_SUCCESS; + + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Neighbor Lookup DOWN indication callback called with notification %d Reported RSSI = %d"), + rssiNotification, + avgRssi); + +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->lookupDOWNRssi = avgRssi; +#endif + if (!csrIsConnStateConnectedInfra(pMac, sessionId)) { + smsLog(pMac, LOGW, FL("LookDown Event received when we are not " + "connected. Ignore it")); + vos_mem_free(pUsrCtx); + return VOS_STATUS_SUCCESS; + } + + if (WLANTL_HO_THRESHOLD_DOWN != rssiNotification) + { + VOS_ASSERT(WLANTL_HO_THRESHOLD_DOWN == rssiNotification); + vos_mem_free(pUsrCtx); + return VOS_STATUS_E_FAILURE; + } + vosStatus = csrNeighborRoamNeighborLookupDownEvent(pMac, sessionId); + vos_mem_free(pUsrCtx); + + return vosStatus; +} + +/** + * csr_roam_reset_roam_params() - API to reset the roaming parameters + * @mac_ctx: Global MAC Context pointer. + * + * Return: VOID + */ +void csr_roam_reset_roam_params(tpAniSirGlobal mac_ctx) +{ + struct roam_ext_params *roam_params = NULL; + /* clear all the whitelist parameters, + * remaining needs to be retained across connections. */ + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Roaming parameters are reset")); + roam_params = &mac_ctx->roam.configParam.roam_params; + roam_params->num_ssid_allowed_list = 0; + vos_mem_set(&roam_params->ssid_allowed_list, 0, + sizeof(tSirMacSSid) * MAX_SSID_ALLOWED_LIST); +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIndicateDisconnect + + \brief This function is called by CSR as soon as the station disconnects from + the AP. This function does the necessary cleanup of neighbor roam data + structures. Neighbor roam state transitions to INIT state whenever this + function is called except if the current state is REASSOCIATING + + \param pMac - The handle returned by macOpen. + sessionId - CSR session id that got disconnected + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; +#ifdef FEATURE_WLAN_LFR + tCsrRoamConnectedProfile *pPrevProfile = &pNeighborRoamInfo->prevConnProfile; +#endif + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId); + + if (NULL == pSession) + { + smsLog(pMac, LOGE, FL("pSession is NULL ")); + return eHAL_STATUS_FAILURE; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Disconnect indication on session %d in state %d from BSSID : " + MAC_ADDRESS_STR), sessionId, pNeighborRoamInfo->neighborRoamState, + MAC_ADDR_ARRAY(pSession->connectedProfile.bssid)); +#ifdef FEATURE_WLAN_LFR + /*Free the current previous profile and move the current profile to prev profile.*/ + csrRoamFreeConnectProfile(pMac, pPrevProfile); + csrRoamCopyConnectProfile(pMac, sessionId, pPrevProfile); + + /* clear the roaming parameters that are per connection. + * For a new connection, they have to be programmed again. */ + if (!csrNeighborMiddleOfRoaming((tHalHandle)pMac, sessionId)) + csr_roam_reset_roam_params(pMac); +#endif + if (NULL != pSession) + { + if (NULL != pSession->pCurRoamProfile) + { + if (VOS_STA_MODE != pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona) + { + smsLog(pMac, LOGE, FL("Ignoring Disconnect indication received from a non STA persona." + "sessionId: %d, csrPersonna %d"), sessionId, + (int)pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona); + return eHAL_STATUS_SUCCESS; + } + } + +#ifdef FEATURE_WLAN_ESE + if (pSession->connectedProfile.isESEAssoc) + { + vos_mem_copy(&pSession->prevApSSID, &pSession->connectedProfile.SSID, + sizeof(tSirMacSSid)); + vos_mem_copy(pSession->prevApBssid, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + pSession->prevOpChannel = pSession->connectedProfile.operationChannel; + pSession->isPrevApInfoValid = TRUE; + pSession->roamTS1 = vos_timer_get_system_time(); + } +#endif + } //if (NULL != pSession) + + switch (pNeighborRoamInfo->neighborRoamState) + { + case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: + // Stop scan and neighbor refresh timers. + // These are indeed not required when we are in reassociating + // state. + vos_timer_stop(&pNeighborRoamInfo->neighborScanTimer); + vos_timer_stop(&pNeighborRoamInfo->neighborResultsRefreshTimer); + vos_timer_stop(&pNeighborRoamInfo->emptyScanRefreshTimer); + if (!CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac, sessionId )) { + /* + * Disconnect indication during Disassoc Handoff sub-state + * is received when we are trying to disconnect with the old + * AP during roam. BUT, if receive a disconnect indication + * outside of Disassoc Handoff sub-state, then it means that + * this is a genuine disconnect and we need to clean up. + * Otherwise, we will be stuck in reassoc state which will + * in-turn block scans. + */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId); + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + } + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + csrNeighborRoamResetInitStateControlInfo(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + break; + + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + csrNeighborRoamResetConnectedStateControlInfo(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + break; + + case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId); + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + csrNeighborRoamResetCfgListChanScanControlInfo(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + break; + + case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE: + /* Stop pre-auth to reassoc interval timer */ + vos_timer_stop(&pSession->ftSmeContext.preAuthReassocIntvlTimer); + case eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN: + case eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING: + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + csrNeighborRoamResetPreauthControlInfo(pMac, sessionId); + csrNeighborRoamResetReportScanStateControlInfo(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + break; + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Received disconnect event" + "in state %s "), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Transitioning to INIT state")); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + break; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /*Inform the Firmware to STOP Scanning as the host has a disconnect.*/ + if (csrRoamIsStaMode(pMac, sessionId)) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_STOP, + REASON_DISCONNECTED); + } +#endif + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIndicateConnect + + \brief This function is called by CSR as soon as the station connects to an AP. + This initializes all the necessary data structures related to the + associated AP and transitions the state to CONNECTED state + + \param pMac - The handle returned by macOpen. + sessionId - CSR session id that got connected + vosStatus - connect status SUCCESS/FAILURE + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, + tANI_U8 sessionId, + VOS_STATUS vosStatus) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vstatus; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tCsrRoamInfo roamInfo; + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; +#endif + tpFTRoamCallbackUsrCtx pUsrCtx; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + int init_ft_flag = FALSE; +#endif + // if session id invalid then we need return failure + if (NULL == pNeighborRoamInfo || !CSR_IS_SESSION_VALID(pMac, sessionId) || + (NULL == pMac->roam.roamSession[sessionId].pCurRoamProfile)) + { + return eHAL_STATUS_FAILURE; + } + + smsLog(pMac, LOG2, + FL("Connect indication received with session id %d" + "in state %s"), + sessionId, macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + + + // Bail out if this is NOT a STA persona + if (pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona != VOS_STA_MODE) + { + smsLog(pMac, LOGE, FL("Ignoring Connect indication received from a non STA persona." + "sessionId: %d, csrPersonna %d"), + sessionId, + (int)pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona); + return eHAL_STATUS_SUCCESS; + } + + // if a concurrent session is running +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (eANI_BOOLEAN_FALSE == CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac)) + { +#endif + if (csrIsConcurrentSessionRunning(pMac)) + { + smsLog(pMac, LOGE, FL("Ignoring Connect indication received in multisession %d"), + csrIsConcurrentSessionRunning(pMac)); + return eHAL_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress && + (eSIR_ROAM_AUTH_STATUS_AUTHENTICATED == + pSession->roamOffloadSynchParams.authStatus)) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR3:csrNeighborRoamIndicateConnect"); +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE + if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + tpSirSetActiveModeSetBncFilterReq pMsg; + pMsg = vos_mem_malloc(sizeof(tSirSetActiveModeSetBncFilterReq)); + if (pMsg == NULL) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "LFR3:Mem Alloc failed for tSirSetActiveModeSetBncFilterReq"); + return eHAL_STATUS_FAILURE; + } + pMsg->messageType = + pal_cpu_to_be16((tANI_U16)eWNI_SME_SET_BCN_FILTER_REQ); + pMsg->length = pal_cpu_to_be16(sizeof( tANI_U8)); + pMsg->seesionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg ); + } +#endif + vos_mem_copy(&roamInfo.peerMac, + pMac->roam.roamSession[sessionId].connectedProfile.bssid,6); + roamInfo.roamSynchInProgress = + pSession->roamOffloadSynchParams.bRoamSynchInProgress; + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_SET_KEY_COMPLETE, eCSR_ROAM_RESULT_AUTHENTICATED); + } +#endif + + switch (pNeighborRoamInfo->neighborRoamState) + { + 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, + sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + break; + } + /* Fall through if the status is SUCCESS */ + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + /* Reset all the data structures here */ + csrNeighborRoamResetInitStateControlInfo(pMac, sessionId); + +#ifdef FEATURE_WLAN_LFR + /* + * Initialize the occupied list ONLY if we are + * transitioning from INIT state to CONNECTED state. + */ + if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) + csrInitOccupiedChannelsList(pMac, sessionId); +#endif + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + sessionId); + + vos_mem_copy(pNeighborRoamInfo->currAPbssid, + pMac->roam.roamSession[sessionId].connectedProfile.bssid, sizeof(tCsrBssid)); + pNeighborRoamInfo->currAPoperationChannel = pMac->roam.roamSession[sessionId].connectedProfile.operationChannel; + pNeighborRoamInfo->neighborScanTimerInfo.pMac = pMac; + pNeighborRoamInfo->neighborScanTimerInfo.sessionId = sessionId; + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight; +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->uEmptyScanCount = 0; + pNeighborRoamInfo->lookupDOWNRssi = 0; + pNeighborRoamInfo->uScanMode = DEFAULT_SCAN; +#endif + + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + /* Now we can clear the preauthDone that was saved as we are connected afresh */ + csrNeighborRoamFreeRoamableBSSList(pMac, + &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList); +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + // Based on the auth scheme tell if we are 11r + if ( csrIsAuthType11r( pMac->roam.roamSession[sessionId].connectedProfile.AuthType, + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mdiePresent)) + { + if (pMac->roam.configParam.isFastTransitionEnabled) + init_ft_flag = TRUE; + pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_TRUE; + } + else + pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_FALSE; + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("11rAssoc is = %d"), pNeighborRoamInfo->is11rAssoc); +#endif + +#ifdef FEATURE_WLAN_ESE + // Based on the auth scheme tell if we are 11r + if (pMac->roam.roamSession[sessionId].connectedProfile.isESEAssoc) + { + if (pMac->roam.configParam.isFastTransitionEnabled) + init_ft_flag = TRUE; + pNeighborRoamInfo->isESEAssoc = eANI_BOOLEAN_TRUE; + } + else + pNeighborRoamInfo->isESEAssoc = eANI_BOOLEAN_FALSE; + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("isESEAssoc is = %d ft = %d"), + pNeighborRoamInfo->isESEAssoc, init_ft_flag); + +#endif + +#ifdef FEATURE_WLAN_LFR + // If "Legacy Fast Roaming" is enabled + if (csrRoamIsFastRoamEnabled(pMac, sessionId)) + { + init_ft_flag = TRUE; + } +#endif + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if ( init_ft_flag == TRUE ) + { + /* Initialize all the data structures needed for the 11r FT Preauth */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + csrNeighborRoamPurgePreauthFailedList(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!vos_is_multiple_active_sta_sessions() && + csrRoamIsRoamOffloadScanEnabled(pMac)) + { + /*If this is not a INFRA type BSS, then do not send the command + * down to firmware.Do not send the START command for other session + * connections.*/ + if(csrRoamIsStaMode(pMac, sessionId)) + { + pNeighborRoamInfo->uOsRequestedHandoff = 0; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) + { + if (pMac->roam.pReassocResp != NULL) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "Free Reassoc Rsp"); + vos_mem_free(pMac->roam.pReassocResp); + pMac->roam.pReassocResp = NULL; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR3:Send SynchCnf auth status authenticated"); + csrRoamOffloadSendSynchCnf( pMac, sessionId); + } else +#endif + csrRoamOffloadScan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_START, + REASON_CONNECT); + } + } else { +#endif + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), + pNeighborRoamInfo->currentNeighborLookupThreshold); + + /* This user context data will be returned with callback */ + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return VOS_STATUS_E_NOMEM; + } + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); + /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ + vstatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), + WLANTL_HO_THRESHOLD_DOWN, + csrNeighborRoamNeighborLookupDOWNCallback, + VOS_MODULE_ID_SME, pUsrCtx); +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->lookupDOWNRssi = 0; +#endif + vos_mem_free(pUsrCtx); + if(!VOS_IS_STATUS_SUCCESS(vstatus)) + { + //err msg + smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vstatus); + status = eHAL_STATUS_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ + } +#endif + break; + default: + smsLog(pMac, LOGE, + FL("Connect event received in invalid state %s" + "..Ignoring..."), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + break; + } + return status; +} + + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamPurgePreauthFailedList + + \brief This function purges all the MAC addresses in the pre-auth fail list + + \param pMac - The handle returned by macOpen. + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamPurgePreauthFailedList(tpAniSirGlobal pMac) +{ + tANI_U8 i, j; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + for (j = 0; j < CSR_ROAM_SESSION_MAX; j++) { + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[j]; + for (i = 0; + i < pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress; + i++) { + vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.preAuthFailList.macAddress[i], + sizeof(tSirMacAddr)); + } + pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress = 0; + } +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamInit11rAssocInfo + + \brief This function initializes 11r related neighbor roam data structures + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamInit11rAssocInfo(tpAniSirGlobal pMac) +{ + eHalStatus status; + tANI_U8 i; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + tpCsr11rAssocNeighborInfo pFTRoamInfo = NULL; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[i]; + pFTRoamInfo = &pNeighborRoamInfo->FTRoamInfo; + + pNeighborRoamInfo->is11rAssoc = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->cfgParams.maxNeighborRetries = + pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries; + + pFTRoamInfo->neighborReportTimeout = + CSR_NEIGHBOR_ROAM_REPORT_QUERY_TIMEOUT; + pFTRoamInfo->PEPreauthRespTimeout = + CSR_NEIGHBOR_ROAM_PREAUTH_RSP_WAIT_MULTIPLIER * + pNeighborRoamInfo->cfgParams.neighborScanPeriod; + pFTRoamInfo->neighborRptPending = eANI_BOOLEAN_FALSE; + pFTRoamInfo->preauthRspPending = eANI_BOOLEAN_FALSE; + + pFTRoamInfo->currentNeighborRptRetryNum = 0; + pFTRoamInfo->numBssFromNeighborReport = 0; + + vos_mem_zero(pFTRoamInfo->neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT); + + status = csrLLOpen(pMac->hHdd, &pFTRoamInfo->preAuthDoneList); + if (eHAL_STATUS_SUCCESS != status) { + smsLog(pMac, LOGE, FL("LL Open of preauth done AP List failed")); + return eHAL_STATUS_RESOURCES; + } + } + return status; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamInit + + \brief This function initializes neighbor roam data structures + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamInit(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + eHalStatus status; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + pNeighborRoamInfo->neighborRoamState = eCSR_NEIGHBOR_ROAM_STATE_CLOSED; + pNeighborRoamInfo->prevNeighborRoamState = eCSR_NEIGHBOR_ROAM_STATE_CLOSED; + pNeighborRoamInfo->cfgParams.maxChannelScanTime = pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime; + pNeighborRoamInfo->cfgParams.minChannelScanTime = pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime; + pNeighborRoamInfo->cfgParams.maxNeighborRetries = 0; + pNeighborRoamInfo->cfgParams.neighborLookupThreshold = pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold; + pNeighborRoamInfo->cfgParams.delay_before_vdev_stop = + pMac->roam.configParam.neighborRoamConfig.delay_before_vdev_stop; + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff = + pMac->roam.configParam.neighborRoamConfig.nOpportunisticThresholdDiff; + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff = + pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff; + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt = + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt; + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt = + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt; + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight = + pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight; + pNeighborRoamInfo->cfgParams.neighborReassocThreshold = pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold; + pNeighborRoamInfo->cfgParams.neighborScanPeriod = pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod; + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod = pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod; + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod = pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod; + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels; + if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels != 0) { + + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = + vos_mem_malloc(pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels); + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { + smsLog(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed")); + return eHAL_STATUS_RESOURCES; + } + /* Update the roam global structure from CFG */ + vos_mem_copy(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList, + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList, + pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels); + } + else { + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + smsLog(pMac, LOGW, FL("invalid neighbor roam channel list: %u"), + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels); + } + pNeighborRoamInfo->cfgParams.hi_rssi_scan_max_count = + pMac->roam.configParam.neighborRoamConfig.nhi_rssi_scan_max_count; + pNeighborRoamInfo->cfgParams.hi_rssi_scan_rssi_delta = + pMac->roam.configParam.neighborRoamConfig.nhi_rssi_scan_rssi_delta; + pNeighborRoamInfo->cfgParams.hi_rssi_scan_delay = + pMac->roam.configParam.neighborRoamConfig.nhi_rssi_scan_delay; + pNeighborRoamInfo->cfgParams.hi_rssi_scan_rssi_ub = + pMac->roam.configParam.neighborRoamConfig.nhi_rssi_scan_rssi_ub; + + vos_mem_set(pNeighborRoamInfo->currAPbssid, sizeof(tCsrBssid), 0); + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight; + +#ifdef FEATURE_WLAN_LFR + pNeighborRoamInfo->lookupDOWNRssi = 0; + pNeighborRoamInfo->uEmptyScanCount = 0; + pNeighborRoamInfo->uScanMode = DEFAULT_SCAN; + vos_mem_set(&pNeighborRoamInfo->prevConnProfile, sizeof(tCsrRoamConnectedProfile), 0); +#endif + pNeighborRoamInfo->scanRspPending = eANI_BOOLEAN_FALSE; + + pNeighborRoamInfo->neighborScanTimerInfo.pMac = pMac; + pNeighborRoamInfo->neighborScanTimerInfo.sessionId = CSR_SESSION_ID_INVALID; + status = vos_timer_init(&pNeighborRoamInfo->neighborScanTimer, VOS_TIMER_TYPE_SW, + csrNeighborRoamNeighborScanTimerCallback, (void *)&pNeighborRoamInfo->neighborScanTimerInfo); + + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Neighbor scan timer allocation failed")); + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + return eHAL_STATUS_RESOURCES; + } + + status = vos_timer_init(&pNeighborRoamInfo->neighborResultsRefreshTimer, VOS_TIMER_TYPE_SW, + csrNeighborRoamResultsRefreshTimerCallback, (void *)&pNeighborRoamInfo->neighborScanTimerInfo); + + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Neighbor results refresh timer allocation failed")); + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + vos_timer_destroy(&pNeighborRoamInfo->neighborScanTimer); + return eHAL_STATUS_RESOURCES; + } + + status = vos_timer_init(&pNeighborRoamInfo->emptyScanRefreshTimer, VOS_TIMER_TYPE_SW, + csrNeighborRoamEmptyScanRefreshTimerCallback, + (void *)&pNeighborRoamInfo->neighborScanTimerInfo); + + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Empty scan refresh timer allocation failed")); + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + vos_timer_destroy(&pNeighborRoamInfo->neighborScanTimer); + vos_timer_destroy(&pNeighborRoamInfo->neighborResultsRefreshTimer); + return eHAL_STATUS_RESOURCES; + } + + status = csrLLOpen(pMac->hHdd, &pNeighborRoamInfo->roamableAPList); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("LL Open of roam able AP List failed")); + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + vos_timer_destroy(&pNeighborRoamInfo->neighborScanTimer); + vos_timer_destroy(&pNeighborRoamInfo->neighborResultsRefreshTimer); + vos_timer_destroy(&pNeighborRoamInfo->emptyScanRefreshTimer); + return eHAL_STATUS_RESOURCES; + } + + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + +#ifdef WLAN_FEATURE_VOWIFI_11R + status = csrNeighborRoamInit11rAssocInfo(pMac); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("LL Open of roam able AP List failed")); + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + vos_timer_destroy(&pNeighborRoamInfo->neighborScanTimer); + vos_timer_destroy(&pNeighborRoamInfo->neighborResultsRefreshTimer); + vos_timer_destroy(&pNeighborRoamInfo->emptyScanRefreshTimer); + csrLLClose(&pNeighborRoamInfo->roamableAPList); + return eHAL_STATUS_RESOURCES; + } +#endif + /* Initialize this with the current tick count */ + pNeighborRoamInfo->scanRequestTimeStamp = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT, sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + /* Set the Last Sent Cmd as RSO_STOP */ + pNeighborRoamInfo->lastSentCmd = ROAM_SCAN_OFFLOAD_STOP; + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamClose + + \brief This function closes/frees all the neighbor roam data structures + + \param pMac - The handle returned by macOpen. + \param sessionId - Session identifier + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamClose(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CLOSED == pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGW, FL("Neighbor Roam Algorithm Already Closed")); + return; + } + + if (pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); + + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + + pNeighborRoamInfo->neighborScanTimerInfo.pMac = NULL; + pNeighborRoamInfo->neighborScanTimerInfo.sessionId = CSR_SESSION_ID_INVALID; + vos_timer_destroy(&pNeighborRoamInfo->neighborScanTimer); + vos_timer_destroy(&pNeighborRoamInfo->neighborResultsRefreshTimer); + vos_timer_destroy(&pNeighborRoamInfo->emptyScanRefreshTimer); + + /* Should free up the nodes in the list before closing the double Linked list */ + csrNeighborRoamFreeRoamableBSSList(pMac, &pNeighborRoamInfo->roamableAPList); + csrLLClose(&pNeighborRoamInfo->roamableAPList); + + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList) + { + vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); + } + + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; + pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_FALSE; + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; + + /* Free the profile.. */ + csrReleaseProfile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile); +#ifdef FEATURE_WLAN_LFR + csrRoamFreeConnectProfile(pMac, &pNeighborRoamInfo->prevConnProfile); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + vos_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * MAX_BSS_IN_NEIGHBOR_RPT); + csrNeighborRoamFreeRoamableBSSList(pMac, + &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList); + csrLLClose(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CLOSED, + sessionId) + + return; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamRequestHandoff + + \brief This function triggers actual switching from one AP to the new AP. + It issues disassociate with reason code as Handoff and CSR as a + part of handling disassoc rsp, issues reassociate to the new AP + + \param pMac - The handle returned by macOpen. + + \return VOID + +---------------------------------------------------------------------------*/ +void csrNeighborRoamRequestHandoff(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tCsrRoamInfo roamInfo; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrNeighborRoamBSSInfo handoffNode; + + extern void csrRoamRoamingStateDisassocRspProcessor( tpAniSirGlobal pMac, tSirSmeDisassocRsp *pSmeDisassocRsp ); + tANI_U32 roamId = 0; + eHalStatus status; + +#ifdef FEATURE_WLAN_LFR_METRICS + tCsrRoamInfo *roamInfoMetrics; +#endif + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,"%s sessionId=%d", + __func__, sessionId); + + if (pNeighborRoamInfo->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) { + smsLog(pMac, LOGE, + FL("Roam requested when Neighbor roam is in %s state"), + macTraceGetNeighbourRoamState( + pNeighborRoamInfo->neighborRoamState)); + return; + } + if (eANI_BOOLEAN_FALSE == + csrNeighborRoamGetHandoffAPInfo(pMac, &handoffNode, sessionId)) { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("failed to obtain handoff AP")); + return; + } + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("HANDOFF CANDIDATE BSSID "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(handoffNode.pBssDescription->bssId)); + + vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo)); + csrRoamCallCallback(pMac, sessionId, &roamInfo, roamId, eCSR_ROAM_FT_START, + eSIR_SME_SUCCESS); + + vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo)); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING, + sessionId) + +#ifdef FEATURE_WLAN_LFR_METRICS + /* LFR metrics - pre-auth completion metric. + Send the event to supplicant that pre-auth successfully completed */ + roamInfoMetrics = vos_mem_malloc(sizeof(tCsrRoamInfo)); + if (NULL == roamInfoMetrics) + { + smsLog(pMac, LOG1, FL("Memory allocation failed!")); + } + else + { + vos_mem_copy((void *)roamInfoMetrics->bssid, + (void *)&handoffNode.pBssDescription->bssId, sizeof(tCsrBssid)); + csrRoamCallCallback(pMac, sessionId, roamInfoMetrics, 0, + eCSR_ROAM_HANDOVER_SUCCESS, 0); + vos_mem_free(roamInfoMetrics); + } +#endif + + /* Free the profile.. Just to make sure we dont leak memory here */ + csrReleaseProfile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile); + /* + * Create the Handoff AP profile. Copy the currently connected profile and + * update only the BSSID and channel number. This should happen before + * issuing disconnect. + */ + status = csrRoamCopyConnectedProfile(pMac, sessionId, + &pNeighborRoamInfo->csrNeighborRoamProfile); + if (eHAL_STATUS_SUCCESS != status) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("csrRoamCopyConnectedProfile returned failed %d"), status); + return; + } + vos_mem_copy(pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid, handoffNode.pBssDescription->bssId, sizeof(tSirMacAddr)); + pNeighborRoamInfo->csrNeighborRoamProfile.ChannelInfo.ChannelList[0] = handoffNode.pBssDescription->channelId; + + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, " csrRoamHandoffRequested: disassociating with current AP"); + + if(!HAL_STATUS_SUCCESS(csrRoamIssueDisassociateCmd(pMac, sessionId, eCSR_DISCONNECT_REASON_HANDOFF))) + { + smsLog(pMac, LOGW, "csrRoamHandoffRequested: fail to issue disassociate"); + return; + } + + /* Notify HDD for handoff, providing the BSSID too */ + roamInfo.reasonCode = eCsrRoamReasonBetterAP; + + vos_mem_copy(roamInfo.bssid, + handoffNode.pBssDescription->bssId, + sizeof( tCsrBssid )); + + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE); + + return; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIsHandoffInProgress + + \brief This function returns whether hand-off is in progress or not based + on the current neighbor roam state + + \param pMac - The handle returned by macOpen. + is11rReassoc - Return whether reassoc is of type 802.11r reassoc + + \return eANI_BOOLEAN_TRUE if reassoc in progress, eANI_BOOLEAN_FALSE otherwise + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamIsHandoffInProgress(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + if (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING == + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState) + return eANI_BOOLEAN_TRUE; + + return eANI_BOOLEAN_FALSE; +} + +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(WLAN_FEATURE_NEIGHBOR_ROAMING) +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamIs11rAssoc + + \brief This function returns whether the current association is a 11r assoc or not + + \param pMac - The handle returned by macOpen. + + \return eANI_BOOLEAN_TRUE if current assoc is 11r, eANI_BOOLEAN_FALSE otherwise + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamIs11rAssoc(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + return pMac->roam.neighborRoamInfo[sessionId].is11rAssoc; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamGetHandoffAPInfo + + \brief This function returns the best possible AP for handoff. + For 11R case, it returns the 1st entry from pre-auth done list. + For non-11r case, it returns the 1st entry from roam able AP list + + \param pMac - The handle returned by macOpen. + pHandoffNode - AP node that is the hand-off candidate returned + + \return true if able find handoff AP, false otherwise + +---------------------------------------------------------------------------*/ +bool csrNeighborRoamGetHandoffAPInfo(tpAniSirGlobal pMac, + tpCsrNeighborRoamBSSInfo pHandoffNode, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tpCsrNeighborRoamBSSInfo pBssNode = NULL; + + if (NULL == pHandoffNode) + { + VOS_ASSERT(NULL != pHandoffNode); + return false; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pNeighborRoamInfo->is11rAssoc) + { + /* Always the BSS info in the head is the handoff candidate */ + pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, + &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, FL("Number of Handoff candidates = %d"), csrLLCount(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList)); + } + else +#endif +#ifdef FEATURE_WLAN_ESE + if (pNeighborRoamInfo->isESEAssoc) + { + /* Always the BSS info in the head is the hand-off candidate */ + pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csrLLCount(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList)); + } + else +#endif +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsFastRoamEnabled(pMac, sessionId)) + { + /* Always the BSS info in the head is the hand-off candidate */ + pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->FTRoamInfo.preAuthDoneList, NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csrLLCount(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList)); + } + else +#endif + { + pBssNode = csrNeighborRoamGetRoamableAPListNextEntry(pMac, &pNeighborRoamInfo->roamableAPList, NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csrLLCount(&pNeighborRoamInfo->roamableAPList)); + } + if (NULL == pBssNode) + return false; + vos_mem_copy(pHandoffNode, pBssNode, sizeof(tCsrNeighborRoamBSSInfo)); + + return true; +} + +/* --------------------------------------------------------------------------- + \brief This function returns TRUE if preauth is completed + + \param pMac - The handle returned by macOpen. + + \return boolean + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamStatePreauthDone(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + return (pMac->roam.neighborRoamInfo[sessionId].neighborRoamState == + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE); +} + +/* --------------------------------------------------------------------------- + \brief In the event that we are associated with AP1 and we have + completed pre auth with AP2. Then we receive a deauth/disassoc from + AP1. + At this point neighbor roam is in pre auth done state, pre auth timer + is running. We now handle this case by stopping timer and clearing + the pre-auth state. We basically clear up and just go to disconnected + state. + + \param pMac - The handle returned by macOpen. + + \return boolean +---------------------------------------------------------------------------*/ +void csrNeighborRoamTranistionPreauthDoneToDisconnected(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("pSession is NULL")); + return; + } + + if (pNeighborRoamInfo->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) return; + + // Stop timer + vos_timer_stop(&pSession->ftSmeContext.preAuthReassocIntvlTimer); + + // Transition to init state + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT, sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; +} + +/* --------------------------------------------------------------------------- + \brief This function returns TRUE if background scan triggered by + LFR is in progress. + + \param halHandle - The handle from HDD context. + + \return boolean + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborRoamScanRspPending(tHalHandle hHal, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return (pMac->roam.neighborRoamInfo[sessionId].scanRspPending); +} + +/* --------------------------------------------------------------------------- + \brief This function returns TRUE if STA is in the middle of roaming states + + \param halHandle - The handle from HDD context. + \param sessionId - Session identifier + + \return boolean + +---------------------------------------------------------------------------*/ +tANI_BOOLEAN csrNeighborMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_BOOLEAN val = (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING == + pNeighborRoamInfo->neighborRoamState) || + (eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING == + pNeighborRoamInfo->neighborRoamState) || + (eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE == + pNeighborRoamInfo->neighborRoamState) || + (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == + pNeighborRoamInfo->neighborRoamState) || + (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == + pNeighborRoamInfo->neighborRoamState); + return (val); +} +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamCandidateFoundIndHdlr + + \brief This function is called by CSR as soon as TL posts the candidate + found indication to SME via MC thread + + \param pMac - The handle returned by macOpen. + pMsg - Msg sent by PE + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg) +{ + tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd = + (tSirSmeCandidateFoundInd *)pMsg; + tANI_U32 sessionId = pSirSmeCandidateFoundInd->sessionId; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + /* we must be in connected state, if not ignore it */ + if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + || (pNeighborRoamInfo->uOsRequestedHandoff)) + { + smsLog(pMac, LOGE, FL("Received in not CONNECTED state OR uOsRequestedHandoff is set. Ignore it")); + status = eHAL_STATUS_FAILURE; + } + else + { + /* We are about to start a fresh scan cycle, + * purge non-P2P results from the past */ + csrScanFlushSelectiveResult(pMac, VOS_FALSE); + /* Once it gets the candidates found indication from PE, will issue + * a scan req to PE with �freshScan� in scanreq structure set + * as follows: 0x42 - Return & purge LFR scan results + */ + status = csrScanRequestLfrResult(pMac, sessionId, + csrNeighborRoamScanResultRequestCallback, + pMac); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamProcessHandoffReq + + \brief This function is called start with the handoff process. First do a + SSID scan for the BSSID provided + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamProcessHandoffReq(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 roamId; + tCsrRoamProfile *pProfile = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tANI_U8 i = 0; + + if (NULL == pSession) + { + smsLog(pMac, LOGE, FL("pSession is NULL ")); + return eHAL_STATUS_FAILURE; + } + + do + { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile)); + if ( NULL == pProfile ) + { + smsLog(pMac, LOGE, FL("Memory alloc failed")); + return eHAL_STATUS_FAILURE; + } + vos_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("Profile copy failed")); + break; + } + + //Add the BSSID & Channel + pProfile->BSSIDs.numOfBSSIDs = 1; + + if (NULL == pProfile->BSSIDs.bssid) + { + pProfile->BSSIDs.bssid = + vos_mem_malloc(sizeof(tSirMacAddr) * pProfile->BSSIDs.numOfBSSIDs); + if (NULL == pProfile->BSSIDs.bssid) + { + smsLog(pMac, LOGE, FL("mem alloc failed for BSSID")); + status = eHAL_STATUS_FAILURE; + break; + } + } + + vos_mem_zero(pProfile->BSSIDs.bssid, sizeof(tSirMacAddr) * pProfile->BSSIDs.numOfBSSIDs); + + /* Populate the BSSID from handoff info received from HDD */ + for (i = 0; i < pProfile->BSSIDs.numOfBSSIDs; i++) + { + vos_mem_copy(&pProfile->BSSIDs.bssid[i], + pNeighborRoamInfo->handoffReqInfo.bssid, sizeof(tSirMacAddr)); + } + + pProfile->ChannelInfo.numOfChannels = 1; + if (NULL == pProfile->ChannelInfo.ChannelList) + { + pProfile->ChannelInfo.ChannelList = + vos_mem_malloc(sizeof(*pProfile->ChannelInfo.ChannelList) * + pProfile->ChannelInfo.numOfChannels); + if (NULL == pProfile->ChannelInfo.ChannelList) + { + smsLog(pMac, LOGE, FL("mem alloc failed for ChannelList")); + status = eHAL_STATUS_FAILURE; + break; + } + } + pProfile->ChannelInfo.ChannelList[0] = pNeighborRoamInfo->handoffReqInfo.channel; + + //do a SSID scan + status = csrScanForSSID(pMac, sessionId, pProfile, roamId, FALSE); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("SSID scan failed")); + } + }while(0); + + if(NULL != pProfile) + { + csrReleaseProfile(pMac, pProfile); + vos_mem_free(pProfile); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamSssidScanDone + + \brief This function is called once SSID scan is done. If SSID scan failed + to find our candidate add an entry to csr scan cache ourself before starting + the hand-off process + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamSssidScanDone(tpAniSirGlobal pMac, + tANI_U8 sessionId, + eHalStatus status) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus hstatus; + + smsLog(pMac, LOGE, FL("called ")); + + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGE, FL("Received in not CONNECTED state. Ignore it")); + return eHAL_STATUS_FAILURE; + } + + //if SSID scan failed to find our candidate add an entry to csr scan cache ourself + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL("Add an entry to csr scan cache")); + hstatus = csrScanCreateEntryInScanCache(pMac, sessionId, + pNeighborRoamInfo->handoffReqInfo.bssid, + pNeighborRoamInfo->handoffReqInfo.channel); + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("csrScanCreateEntryInScanCache failed with status %d"), hstatus); + return eHAL_STATUS_FAILURE; + } + } + + /* Now we have completed scanning for the candidate provided by HDD. Let move on to HO*/ + hstatus = csrNeighborRoamProcessScanComplete(pMac, sessionId); + + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamHandoffReqHdlr + + \brief This function is called by CSR as soon as it gets a handoff request + to SME via MC thread + + \param pMac - The handle returned by macOpen. + pMsg - Msg sent by HDD + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamHandoffReqHdlr(tpAniSirGlobal pMac, void* pMsg) +{ + tAniHandoffReq *pHandoffReqInfo = (tAniHandoffReq *)pMsg; + tANI_U32 sessionId = pHandoffReqInfo->sessionId; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGE, FL("Received in not CONNECTED state. Ignore it")); + status = eHAL_STATUS_FAILURE; + } + else + { + //save the handoff info came from HDD as part of the reassoc req + pHandoffReqInfo = (tAniHandoffReq *)pMsg; + if (NULL != pHandoffReqInfo) + { + //sanity check + if (VOS_FALSE == vos_mem_compare(pHandoffReqInfo->bssid, + pNeighborRoamInfo->currAPbssid, + sizeof(tSirMacAddr))) + { + + pNeighborRoamInfo->handoffReqInfo.channel = pHandoffReqInfo->channel; + pNeighborRoamInfo->handoffReqInfo.src = pHandoffReqInfo->handoff_src; + vos_mem_copy(pNeighborRoamInfo->handoffReqInfo.bssid, + pHandoffReqInfo->bssid, + 6); + pNeighborRoamInfo->uOsRequestedHandoff = 1; + status = csrRoamOffloadScan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_STOP, + REASON_OS_REQUESTED_ROAMING_NOW); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("csrRoamOffloadScan failed")); + pNeighborRoamInfo->uOsRequestedHandoff = 0; + } + } + else + { + smsLog(pMac, LOGE, FL("Received req has same BSSID as current AP!!")); + status = eHAL_STATUS_FAILURE; + } + } + else + { + smsLog(pMac, LOGE, FL("Received msg is NULL")); + status = eHAL_STATUS_FAILURE; + } + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamProceedWithHandoffReq + + \brief This function is called by CSR as soon as it gets rsp back for + ROAM_SCAN_OFFLOAD_STOP with reason REASON_OS_REQUESTED_ROAMING_NOW + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamProceedWithHandoffReq(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + /* we must be in connected state, if not ignore it */ + if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + || (!pNeighborRoamInfo->uOsRequestedHandoff)) + { + smsLog(pMac, LOGE, FL("Received in not CONNECTED state or uOsRequestedHandoff is not set. Ignore it")); + status = eHAL_STATUS_FAILURE; + } + else + { + //Let's go ahead with handoff + status = csrNeighborRoamProcessHandoffReq(pMac, sessionId); + } + if(!HAL_STATUS_SUCCESS(status)) + { + pNeighborRoamInfo->uOsRequestedHandoff = 0; + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamStartLfrScan + + \brief This function is called if HDD requested handoff failed for some + reason. start the LFR logic at that point.By the time, this function is + called, a STOP command has already been issued. + + \param pMac - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamStartLfrScan(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + pNeighborRoamInfo->uOsRequestedHandoff = 0; + /* There is no candidate or We are not roaming Now. + * Inform the FW to restart Roam Offload Scan */ + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, + REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + + return eHAL_STATUS_SUCCESS; +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrTdlsProcess.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrTdlsProcess.c new file mode 100644 index 000000000000..e76e7e3884b1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrTdlsProcess.c @@ -0,0 +1,847 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrTdlsProcess.c + + Implementation for the TDLS interface to PE. +========================================================================== */ + +#ifdef FEATURE_WLAN_TDLS + +#include "aniGlobal.h" //for tpAniSirGlobal +#include "palApi.h" +#include "csrInsideApi.h" +#include "smeInside.h" +#include "smsDebug.h" + +#include "csrSupport.h" +#include "wlan_qct_tl.h" + +#include "vos_diag_core_log.h" +#include "vos_diag_core_event.h" +#include "csrInternal.h" + + + + +/* + * common routine to remove TDLS cmd from SME command list.. + * commands are removed after getting response from PE. + */ +eHalStatus csrTdlsRemoveSmeCmd(tpAniSirGlobal pMac, eSmeCommandType cmdType) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tListElem *pEntry; + tSmeCmd *pCommand; + + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if( pEntry ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( cmdType == pCommand->command ) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + pEntry, LL_ACCESS_LOCK ) ) + { + vos_mem_zero( &pCommand->u.tdlsCmd, sizeof( tTdlsCmd ) ); + csrReleaseCommand( pMac, pCommand ); + smeProcessPendingQueue( pMac ); + status = eHAL_STATUS_SUCCESS ; + } + } + } + return status ; +} + +/* + * TDLS request API, called from HDD to send a TDLS frame + * in SME/CSR and send message to PE to trigger TDLS discovery procedure. + */ +eHalStatus csrTdlsSendMgmtReq(tHalHandle hHal, tANI_U8 sessionId, tCsrTdlsSendMgmt *tdlsSendMgmt) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSmeCmd *tdlsSendMgmtCmd ; + eHalStatus status = eHAL_STATUS_FAILURE ; + + //If connected and in Infra. Only then allow this + if( CSR_IS_SESSION_VALID( pMac, sessionId ) && + csrIsConnStateConnectedInfra( pMac, sessionId ) && + (NULL != tdlsSendMgmt) ) + { + tdlsSendMgmtCmd = csrGetCommandBuffer(pMac) ; + + if(tdlsSendMgmtCmd) + { + tTdlsSendMgmtCmdInfo *tdlsSendMgmtCmdInfo = + &tdlsSendMgmtCmd->u.tdlsCmd.u.tdlsSendMgmtCmdInfo ; + + tdlsSendMgmtCmd->sessionId = sessionId; + + tdlsSendMgmtCmdInfo->frameType = tdlsSendMgmt->frameType ; + tdlsSendMgmtCmdInfo->dialog = tdlsSendMgmt->dialog ; + tdlsSendMgmtCmdInfo->statusCode = tdlsSendMgmt->statusCode ; + tdlsSendMgmtCmdInfo->responder = tdlsSendMgmt->responder; + tdlsSendMgmtCmdInfo->peerCapability = tdlsSendMgmt->peerCapability; + vos_mem_copy(tdlsSendMgmtCmdInfo->peerMac, + tdlsSendMgmt->peerMac, sizeof(tSirMacAddr)) ; + + if( (0 != tdlsSendMgmt->len) && (NULL != tdlsSendMgmt->buf) ) + { + tdlsSendMgmtCmdInfo->buf = vos_mem_malloc(tdlsSendMgmt->len); + if ( NULL == tdlsSendMgmtCmdInfo->buf ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("Alloc Failed") ); + VOS_ASSERT(0) ; + return status ; + } + vos_mem_copy(tdlsSendMgmtCmdInfo->buf, + tdlsSendMgmt->buf, tdlsSendMgmt->len ); + tdlsSendMgmtCmdInfo->len = tdlsSendMgmt->len; + } + else + { + tdlsSendMgmtCmdInfo->buf = NULL; + tdlsSendMgmtCmdInfo->len = 0; + } + + tdlsSendMgmtCmd->command = eSmeCommandTdlsSendMgmt ; + tdlsSendMgmtCmd->u.tdlsCmd.size = sizeof(tTdlsSendMgmtCmdInfo) ; + smePushCommand(pMac, tdlsSendMgmtCmd, FALSE) ; + status = eHAL_STATUS_SUCCESS ; + smsLog( pMac, LOG1, + FL("Successfully posted tdlsSendMgmtCmd to SME")); + } + } + + return status ; +} + +/* + * TDLS request API, called from HDD to add a TDLS peer + */ +eHalStatus csrTdlsChangePeerSta(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSmeCmd *tdlsAddStaCmd ; + eHalStatus status = eHAL_STATUS_FAILURE ; + + //If connected and in Infra. Only then allow this + if (CSR_IS_SESSION_VALID( pMac, sessionId ) && + csrIsConnStateConnectedInfra( pMac, sessionId ) && + (NULL != peerMac) && (NULL != pstaParams)) { + + tdlsAddStaCmd = csrGetCommandBuffer(pMac) ; + + if (tdlsAddStaCmd) + { + tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo = + &tdlsAddStaCmd->u.tdlsCmd.u.tdlsAddStaCmdInfo ; + + tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_UPDATE; + + tdlsAddStaCmd->sessionId = sessionId; + + vos_mem_copy(tdlsAddStaCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)) ; + tdlsAddStaCmdInfo->capability = pstaParams->capability; + tdlsAddStaCmdInfo->uapsdQueues = pstaParams->uapsd_queues; + tdlsAddStaCmdInfo->maxSp = pstaParams->max_sp; + vos_mem_copy(tdlsAddStaCmdInfo->extnCapability, + pstaParams->extn_capability, + sizeof(pstaParams->extn_capability)); + + tdlsAddStaCmdInfo->htcap_present = pstaParams->htcap_present; + if(pstaParams->htcap_present) + vos_mem_copy(&tdlsAddStaCmdInfo->HTCap, + &pstaParams->HTCap, sizeof(pstaParams->HTCap)); + else + vos_mem_set(&tdlsAddStaCmdInfo->HTCap, sizeof(pstaParams->HTCap), 0); + + tdlsAddStaCmdInfo->vhtcap_present = pstaParams->vhtcap_present; + if(pstaParams->vhtcap_present) + vos_mem_copy(&tdlsAddStaCmdInfo->VHTCap, + &pstaParams->VHTCap, sizeof(pstaParams->VHTCap)); + else + vos_mem_set(&tdlsAddStaCmdInfo->VHTCap, sizeof(pstaParams->VHTCap), 0); + + tdlsAddStaCmdInfo->supportedRatesLen = pstaParams->supported_rates_len; + + if (0 != pstaParams->supported_rates_len) + vos_mem_copy(&tdlsAddStaCmdInfo->supportedRates, + pstaParams->supported_rates, + pstaParams->supported_rates_len); + + tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer; + tdlsAddStaCmd->u.tdlsCmd.size = sizeof(tTdlsAddStaCmdInfo) ; + smePushCommand(pMac, tdlsAddStaCmd, FALSE) ; + smsLog( pMac, LOG1, + FL("Successfully posted tdlsAddStaCmd to SME to modify peer ")); + status = eHAL_STATUS_SUCCESS ; + } + } + + return status ; +} +/* + * TDLS request API, called from HDD to Send Link Establishment Parameters + */ +VOS_STATUS csrTdlsSendLinkEstablishParams(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams *tdlsLinkEstablishParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSmeCmd *tdlsLinkEstablishCmd; + eHalStatus status = eHAL_STATUS_FAILURE ; + //If connected and in Infra. Only then allow this + if( CSR_IS_SESSION_VALID( pMac, sessionId ) && + csrIsConnStateConnectedInfra( pMac, sessionId ) && + (NULL != peerMac) ) + { + tdlsLinkEstablishCmd = csrGetCommandBuffer(pMac) ; + + if(tdlsLinkEstablishCmd) + { + tTdlsLinkEstablishCmdInfo *tdlsLinkEstablishCmdInfo = + &tdlsLinkEstablishCmd->u.tdlsCmd.u.tdlsLinkEstablishCmdInfo ; + + tdlsLinkEstablishCmd->sessionId = sessionId; + + vos_mem_copy( tdlsLinkEstablishCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)); + tdlsLinkEstablishCmdInfo->isBufSta = tdlsLinkEstablishParams->isBufSta; + tdlsLinkEstablishCmdInfo->isResponder= tdlsLinkEstablishParams->isResponder; + tdlsLinkEstablishCmdInfo->maxSp= tdlsLinkEstablishParams->maxSp; + tdlsLinkEstablishCmdInfo->uapsdQueues= tdlsLinkEstablishParams->uapsdQueues; + tdlsLinkEstablishCmdInfo->isOffChannelSupported = + tdlsLinkEstablishParams->isOffChannelSupported; + vos_mem_copy(tdlsLinkEstablishCmdInfo->supportedChannels, + tdlsLinkEstablishParams->supportedChannels, + tdlsLinkEstablishParams->supportedChannelsLen); + tdlsLinkEstablishCmdInfo->supportedChannelsLen = + tdlsLinkEstablishParams->supportedChannelsLen; + vos_mem_copy(tdlsLinkEstablishCmdInfo->supportedOperClasses, + tdlsLinkEstablishParams->supportedOperClasses, + tdlsLinkEstablishParams->supportedOperClassesLen); + tdlsLinkEstablishCmdInfo->supportedOperClassesLen = + tdlsLinkEstablishParams->supportedOperClassesLen; + tdlsLinkEstablishCmdInfo->isResponder= tdlsLinkEstablishParams->isResponder; + tdlsLinkEstablishCmdInfo->maxSp= tdlsLinkEstablishParams->maxSp; + tdlsLinkEstablishCmdInfo->uapsdQueues= tdlsLinkEstablishParams->uapsdQueues; + tdlsLinkEstablishCmd->command = eSmeCommandTdlsLinkEstablish ; + tdlsLinkEstablishCmd->u.tdlsCmd.size = sizeof(tTdlsLinkEstablishCmdInfo) ; + smePushCommand(pMac, tdlsLinkEstablishCmd, FALSE) ; + status = eHAL_STATUS_SUCCESS ; + smsLog( pMac, LOG1, + FL("Successfully posted tdlsLinkEstablishCmd to SME")); + } + } + + return status ; +} + +/* + * TDLS request API, called from HDD to add a TDLS peer + */ +eHalStatus csrTdlsAddPeerSta(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSmeCmd *tdlsAddStaCmd ; + eHalStatus status = eHAL_STATUS_FAILURE ; + + //If connected and in Infra. Only then allow this + if( CSR_IS_SESSION_VALID( pMac, sessionId ) && + csrIsConnStateConnectedInfra( pMac, sessionId ) && + (NULL != peerMac) ) + { + tdlsAddStaCmd = csrGetCommandBuffer(pMac) ; + + if(tdlsAddStaCmd) + { + tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo = + &tdlsAddStaCmd->u.tdlsCmd.u.tdlsAddStaCmdInfo ; + + tdlsAddStaCmd->sessionId = sessionId; + tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_ADD; + + vos_mem_copy( tdlsAddStaCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)) ; + + tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer ; + tdlsAddStaCmd->u.tdlsCmd.size = sizeof(tTdlsAddStaCmdInfo) ; + smePushCommand(pMac, tdlsAddStaCmd, FALSE) ; + status = eHAL_STATUS_SUCCESS ; + smsLog( pMac, LOG1, + FL("Successfully posted tdlsAddStaCmd to SME")); + } + } + + return status ; +} + +/* + * TDLS request API, called from HDD to delete a TDLS peer + */ +eHalStatus csrTdlsDelPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSmeCmd *tdlsDelStaCmd ; + eHalStatus status = eHAL_STATUS_FAILURE ; + + //If connected and in Infra. Only then allow this + if( CSR_IS_SESSION_VALID( pMac, sessionId ) && + csrIsConnStateConnectedInfra( pMac, sessionId ) && + (NULL != peerMac) ) + { + tdlsDelStaCmd = csrGetCommandBuffer(pMac) ; + + if(tdlsDelStaCmd) + { + tTdlsDelStaCmdInfo *tdlsDelStaCmdInfo = + &tdlsDelStaCmd->u.tdlsCmd.u.tdlsDelStaCmdInfo ; + + tdlsDelStaCmd->sessionId = sessionId; + + vos_mem_copy(tdlsDelStaCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)) ; + + tdlsDelStaCmd->command = eSmeCommandTdlsDelPeer ; + tdlsDelStaCmd->u.tdlsCmd.size = sizeof(tTdlsDelStaCmdInfo) ; + smePushCommand(pMac, tdlsDelStaCmd, FALSE) ; + status = eHAL_STATUS_SUCCESS ; + smsLog( pMac, LOG1, + FL("Successfully posted tdlsDelStaCmd to SME")); + } + } + + return status ; +} + +/* + * TDLS messages sent to PE . + */ +eHalStatus tdlsSendMessage(tpAniSirGlobal pMac, tANI_U16 msg_type, + void *msg_data, tANI_U32 msg_size) +{ + + tSirMbMsg *pMsg = (tSirMbMsg *)msg_data ; + pMsg->type = msg_type ; + pMsg->msgLen = (tANI_U16) (msg_size) ; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("sending msg = %d"), pMsg->type) ; + /* Send message. */ + if (palSendMBMessage(pMac->hHdd, pMsg) != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, FL("Cannot send message")); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrTdlsProcessSendMgmt( tpAniSirGlobal pMac, tSmeCmd *cmd ) +{ + tTdlsSendMgmtCmdInfo *tdlsSendMgmtCmdInfo = &cmd->u.tdlsCmd.u.tdlsSendMgmtCmdInfo ; + tSirTdlsSendMgmtReq *tdlsSendMgmtReq = NULL ; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return eHAL_STATUS_FAILURE; + } + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS Description is not present") ); + return eHAL_STATUS_FAILURE; + } + + tdlsSendMgmtReq = vos_mem_malloc( + sizeof(tSirTdlsSendMgmtReq) + tdlsSendMgmtCmdInfo->len); + if ( NULL == tdlsSendMgmtReq ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if (!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("alloc failed") ); + VOS_ASSERT(0) ; + return status ; + } + tdlsSendMgmtReq->sessionId = cmd->sessionId; + //Using dialog as transactionId. This can be used to match response with request + tdlsSendMgmtReq->transactionId = tdlsSendMgmtCmdInfo->dialog; + tdlsSendMgmtReq->reqType = tdlsSendMgmtCmdInfo->frameType ; + tdlsSendMgmtReq->dialog = tdlsSendMgmtCmdInfo->dialog ; + tdlsSendMgmtReq->statusCode = tdlsSendMgmtCmdInfo->statusCode ; + tdlsSendMgmtReq->responder = tdlsSendMgmtCmdInfo->responder; + tdlsSendMgmtReq->peerCapability = tdlsSendMgmtCmdInfo->peerCapability; + + vos_mem_copy(tdlsSendMgmtReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + + vos_mem_copy(tdlsSendMgmtReq->peerMac, + tdlsSendMgmtCmdInfo->peerMac, sizeof(tSirMacAddr)) ; + + if(tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) + { + vos_mem_copy(tdlsSendMgmtReq->addIe, tdlsSendMgmtCmdInfo->buf, + tdlsSendMgmtCmdInfo->len); + + } + // Send the request to PE. + smsLog( pMac, LOG1, FL( "sending TDLS Mgmt Frame req to PE ")); + status = tdlsSendMessage(pMac, eWNI_SME_TDLS_SEND_MGMT_REQ, + (void *)tdlsSendMgmtReq , sizeof(tSirTdlsSendMgmtReq)+tdlsSendMgmtCmdInfo->len) ; + if(!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("Failed to send request to MAC")); + } + if(tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) + { + //Done with the buf. Free it. + vos_mem_free( tdlsSendMgmtCmdInfo->buf ); + tdlsSendMgmtCmdInfo->buf = NULL; + tdlsSendMgmtCmdInfo->len = 0; + } + + return status; +} + +eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) +{ + tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo = &cmd->u.tdlsCmd.u.tdlsAddStaCmdInfo ; + tSirTdlsAddStaReq *tdlsAddStaReq = NULL ; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS description is not present") ); + return eHAL_STATUS_FAILURE; + } + + tdlsAddStaReq = vos_mem_malloc(sizeof(tSirTdlsAddStaReq)); + if ( NULL == tdlsAddStaReq ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + if (!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("alloc failed") ); + VOS_ASSERT(0) ; + return status ; + } + tdlsAddStaReq->sessionId = cmd->sessionId; + tdlsAddStaReq->tdlsAddOper = tdlsAddStaCmdInfo->tdlsAddOper; + //Using dialog as transactionId. This can be used to match response with request + tdlsAddStaReq->transactionId = 0; + + vos_mem_copy( tdlsAddStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + + vos_mem_copy( tdlsAddStaReq->peerMac, + tdlsAddStaCmdInfo->peerMac, sizeof(tSirMacAddr)) ; + + tdlsAddStaReq->capability = tdlsAddStaCmdInfo->capability; + tdlsAddStaReq->uapsd_queues = tdlsAddStaCmdInfo->uapsdQueues; + tdlsAddStaReq->max_sp = tdlsAddStaCmdInfo->maxSp; + + vos_mem_copy( tdlsAddStaReq->extn_capability, + tdlsAddStaCmdInfo->extnCapability, + SIR_MAC_MAX_EXTN_CAP); + tdlsAddStaReq->htcap_present = tdlsAddStaCmdInfo->htcap_present; + vos_mem_copy( &tdlsAddStaReq->htCap, + &tdlsAddStaCmdInfo->HTCap, sizeof(tdlsAddStaCmdInfo->HTCap)); + tdlsAddStaReq->vhtcap_present = tdlsAddStaCmdInfo->vhtcap_present; + vos_mem_copy( &tdlsAddStaReq->vhtCap, + &tdlsAddStaCmdInfo->VHTCap, sizeof(tdlsAddStaCmdInfo->VHTCap)); + tdlsAddStaReq->supported_rates_length = tdlsAddStaCmdInfo->supportedRatesLen; + vos_mem_copy( &tdlsAddStaReq->supported_rates, + tdlsAddStaCmdInfo->supportedRates, tdlsAddStaCmdInfo->supportedRatesLen); + + // Send the request to PE. + smsLog( pMac, LOG1, "sending TDLS Add Sta req to PE " ); + status = tdlsSendMessage(pMac, eWNI_SME_TDLS_ADD_STA_REQ, + (void *)tdlsAddStaReq , sizeof(tSirTdlsAddStaReq)) ; + if(!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("Failed to send request to MAC")); + } + return status; +} + +eHalStatus csrTdlsProcessDelSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) +{ + tTdlsDelStaCmdInfo *tdlsDelStaCmdInfo = &cmd->u.tdlsCmd.u.tdlsDelStaCmdInfo ; + tSirTdlsDelStaReq *tdlsDelStaReq = NULL ; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS description is not present") ); + return eHAL_STATUS_FAILURE; + } + + tdlsDelStaReq = vos_mem_malloc(sizeof(tSirTdlsDelStaReq)); + if ( NULL == tdlsDelStaReq ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + + + if (!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("alloc failed") ); + VOS_ASSERT(0) ; + return status ; + } + tdlsDelStaReq->sessionId = cmd->sessionId; + //Using dialog as transactionId. This can be used to match response with request + tdlsDelStaReq->transactionId = 0; + + vos_mem_copy( tdlsDelStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + + vos_mem_copy( tdlsDelStaReq->peerMac, + tdlsDelStaCmdInfo->peerMac, sizeof(tSirMacAddr)) ; + + // Send the request to PE. + smsLog( pMac, LOG1, + "sending TDLS Del Sta "MAC_ADDRESS_STR" req to PE", + MAC_ADDR_ARRAY(tdlsDelStaCmdInfo->peerMac)); + status = tdlsSendMessage(pMac, eWNI_SME_TDLS_DEL_STA_REQ, + (void *)tdlsDelStaReq , sizeof(tSirTdlsDelStaReq)) ; + if(!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("Failed to send request to MAC")); + } + return status; +} +/* + * commands received from CSR + */ +eHalStatus csrTdlsProcessCmd(tpAniSirGlobal pMac, tSmeCmd *cmd) +{ + eSmeCommandType cmdType = cmd->command ; + tANI_BOOLEAN status = eANI_BOOLEAN_TRUE; + switch(cmdType) + { + case eSmeCommandTdlsSendMgmt: + { + status = csrTdlsProcessSendMgmt( pMac, cmd ); + if(HAL_STATUS_SUCCESS( status ) ) + { + status = eANI_BOOLEAN_FALSE ; + } + } + break ; + case eSmeCommandTdlsAddPeer: + { + status = csrTdlsProcessAddSta( pMac, cmd ); + if(HAL_STATUS_SUCCESS( status ) ) + { + status = eANI_BOOLEAN_FALSE ; + } + } + break; + case eSmeCommandTdlsDelPeer: + { + status = csrTdlsProcessDelSta( pMac, cmd ); + if(HAL_STATUS_SUCCESS( status ) ) + { + status = eANI_BOOLEAN_FALSE ; + } + } + break; + case eSmeCommandTdlsLinkEstablish: + { + status = csrTdlsProcessLinkEstablish( pMac, cmd ); + if(HAL_STATUS_SUCCESS( status ) ) + { + status = eANI_BOOLEAN_FALSE ; + } + } + break; + default: + { + /* TODO: Add default handling */ + break ; + } + + } + return status ; +} + +eHalStatus csrTdlsProcessLinkEstablish( tpAniSirGlobal pMac, tSmeCmd *cmd ) +{ + tTdlsLinkEstablishCmdInfo *tdlsLinkEstablishCmdInfo = &cmd->u.tdlsCmd.u.tdlsLinkEstablishCmdInfo ; + tSirTdlsLinkEstablishReq *tdlsLinkEstablishReq = NULL ; + eHalStatus status = eHAL_STATUS_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); + + if (NULL == pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return eHAL_STATUS_FAILURE; + } + + tdlsLinkEstablishReq = vos_mem_malloc(sizeof(tSirTdlsLinkEstablishReq)); + + if (tdlsLinkEstablishReq == NULL) + { + smsLog( pMac, LOGE, FL("alloc failed \n") ); + VOS_ASSERT(0) ; + return status ; + } + tdlsLinkEstablishReq->sessionId = cmd->sessionId; + //Using dialog as transactionId. This can be used to match response with request + tdlsLinkEstablishReq->transactionId = 0; + vos_mem_copy(tdlsLinkEstablishReq->peerMac, + tdlsLinkEstablishCmdInfo->peerMac, sizeof(tSirMacAddr)); + vos_mem_copy(tdlsLinkEstablishReq->bssid, pSession->pConnectBssDesc->bssId, + sizeof (tSirMacAddr)); + vos_mem_copy(tdlsLinkEstablishReq->supportedChannels, + tdlsLinkEstablishCmdInfo->supportedChannels, + tdlsLinkEstablishCmdInfo->supportedChannelsLen); + tdlsLinkEstablishReq->supportedChannelsLen = + tdlsLinkEstablishCmdInfo->supportedChannelsLen; + vos_mem_copy(tdlsLinkEstablishReq->supportedOperClasses, + tdlsLinkEstablishCmdInfo->supportedOperClasses, + tdlsLinkEstablishCmdInfo->supportedOperClassesLen); + tdlsLinkEstablishReq->supportedOperClassesLen = + tdlsLinkEstablishCmdInfo->supportedOperClassesLen; + tdlsLinkEstablishReq->isBufSta = tdlsLinkEstablishCmdInfo->isBufSta; + tdlsLinkEstablishReq->isResponder= tdlsLinkEstablishCmdInfo->isResponder; + tdlsLinkEstablishReq->uapsdQueues= tdlsLinkEstablishCmdInfo->uapsdQueues; + tdlsLinkEstablishReq->maxSp= tdlsLinkEstablishCmdInfo->maxSp; + + + // Send the request to PE. + smsLog( pMac, LOGE, "sending TDLS Link Establish Request to PE \n" ); + status = tdlsSendMessage(pMac, eWNI_SME_TDLS_LINK_ESTABLISH_REQ, + (void *)tdlsLinkEstablishReq, + sizeof(tSirTdlsLinkEstablishReq)); + if (!HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL("Failed to send request to MAC\n")); + } + return status; +} + +/* + * TDLS Message processor, will be called after TDLS message received from + * PE + */ +eHalStatus tdlsMsgProcessor(tpAniSirGlobal pMac, v_U16_t msgType, + void *pMsgBuf) +{ + tCsrRoamInfo roamInfo = {0} ; + switch(msgType) + { + case eWNI_SME_TDLS_SEND_MGMT_RSP: + { + /* remove pending eSmeCommandTdlsDiscovery command */ + csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsSendMgmt) ; + } + break; + case eWNI_SME_TDLS_ADD_STA_RSP: + { + tSirTdlsAddStaRsp *addStaRsp = (tSirTdlsAddStaRsp *) pMsgBuf ; + eCsrRoamResult roamResult ; + vos_mem_copy( &roamInfo.peerMac, addStaRsp->peerMac, + sizeof(tSirMacAddr)) ; + roamInfo.staId = addStaRsp->staId ; + roamInfo.ucastSig = addStaRsp->ucastSig ; + roamInfo.bcastSig = addStaRsp->bcastSig ; + roamInfo.statusCode = addStaRsp->statusCode ; + /* + * register peer with TL, we have to go through HDD as this is + * the only way to register any STA with TL. + */ + if (addStaRsp->tdlsAddOper == TDLS_OPER_ADD) + roamResult = eCSR_ROAM_RESULT_ADD_TDLS_PEER; + else /* addStaRsp->tdlsAddOper must be TDLS_OPER_UPDATE */ + roamResult = eCSR_ROAM_RESULT_UPDATE_TDLS_PEER; + csrRoamCallCallback(pMac, addStaRsp->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + roamResult); + + /* remove pending eSmeCommandTdlsDiscovery command */ + csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsAddPeer) ; + } + break; + case eWNI_SME_TDLS_DEL_STA_RSP: + { + tSirTdlsDelStaRsp *delStaRsp = (tSirTdlsDelStaRsp *) pMsgBuf ; + + vos_mem_copy( &roamInfo.peerMac, delStaRsp->peerMac, + sizeof(tSirMacAddr)) ; + roamInfo.staId = delStaRsp->staId ; + roamInfo.statusCode = delStaRsp->statusCode ; + /* + * register peer with TL, we have to go through HDD as this is + * the only way to register any STA with TL. + */ + csrRoamCallCallback(pMac, delStaRsp->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_DELETE_TDLS_PEER); + + csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsDelPeer) ; + } + break; + case eWNI_SME_TDLS_DEL_STA_IND: + { + tpSirTdlsDelStaInd pSirTdlsDelStaInd = (tpSirTdlsDelStaInd) pMsgBuf ; + vos_mem_copy( &roamInfo.peerMac, pSirTdlsDelStaInd->peerMac, + sizeof(tSirMacAddr)) ; + roamInfo.staId = pSirTdlsDelStaInd->staId ; + roamInfo.reasonCode = pSirTdlsDelStaInd->reasonCode ; + + /* Sending the TEARDOWN indication to HDD. */ + csrRoamCallCallback(pMac, pSirTdlsDelStaInd->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND); + break ; + } + case eWNI_SME_TDLS_DEL_ALL_PEER_IND: + { + tpSirTdlsDelAllPeerInd pSirTdlsDelAllPeerInd = (tpSirTdlsDelAllPeerInd) pMsgBuf ; + + /* Sending the TEARDOWN indication to HDD. */ + csrRoamCallCallback(pMac, pSirTdlsDelAllPeerInd->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND); + break ; + } + case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND: + { + tpSirMgmtTxCompletionInd pSirTdlsDelAllPeerInd = (tpSirMgmtTxCompletionInd) pMsgBuf ; + roamInfo.reasonCode = pSirTdlsDelAllPeerInd->txCompleteStatus; + + csrRoamCallCallback(pMac, pSirTdlsDelAllPeerInd->sessionId, &roamInfo, + 0, eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND, 0); + break; + } + case eWNI_SME_TDLS_LINK_ESTABLISH_RSP: + { + tSirTdlsLinkEstablishReqRsp *linkEstablishReqRsp = (tSirTdlsLinkEstablishReqRsp *) pMsgBuf ; + csrRoamCallCallback(pMac, linkEstablishReqRsp->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP); + /* remove pending eSmeCommandTdlsLinkEstablish command */ + csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsLinkEstablish); + break; + } + case eWNI_SME_TDLS_SHOULD_DISCOVER: + { + tSirTdlsEventNotify *tevent = (tSirTdlsEventNotify *) pMsgBuf; + vos_mem_copy(&roamInfo.peerMac, tevent->peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = tevent->peer_reason; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: eWNI_SME_TDLS_SHOULD_DISCOVER for peer mac: " + MAC_ADDRESS_STR " peer_reason: %d", + __func__, MAC_ADDR_ARRAY(tevent->peerMac), + tevent->peer_reason); + csrRoamCallCallback(pMac, tevent->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER); + break; + } + case eWNI_SME_TDLS_SHOULD_TEARDOWN: + { + tSirTdlsEventNotify *tevent = (tSirTdlsEventNotify *) pMsgBuf; + vos_mem_copy(&roamInfo.peerMac, tevent->peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = tevent->peer_reason; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: eWNI_SME_TDLS_SHOULD_TEARDOWN for peer mac: " + MAC_ADDRESS_STR " peer_reason: %d", + __func__, MAC_ADDR_ARRAY(tevent->peerMac), + tevent->peer_reason); + csrRoamCallCallback(pMac, tevent->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN); + break; + } + case eWNI_SME_TDLS_PEER_DISCONNECTED: + { + tSirTdlsEventNotify *tevent = (tSirTdlsEventNotify *) pMsgBuf; + vos_mem_copy(&roamInfo.peerMac, tevent->peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = tevent->peer_reason; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: eWNI_SME_TDLS_PEER_DISCONNECTED for peer mac: " + MAC_ADDRESS_STR " peer_reason: %d", + __func__, MAC_ADDR_ARRAY(tevent->peerMac), + tevent->peer_reason); + csrRoamCallCallback(pMac, tevent->sessionId, &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED); + break; + } + default: + { + break ; + } + } + + return eHAL_STATUS_SUCCESS ; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c new file mode 100644 index 000000000000..b0668b3357c6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c @@ -0,0 +1,6069 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrUtil.c + + Implementation supporting routines for CSR. +========================================================================== */ + + +#include "aniGlobal.h" + +#include "palApi.h" +#include "csrSupport.h" +#include "csrInsideApi.h" +#include "smsDebug.h" +#include "smeQosInternal.h" +#include "wlan_qct_wda.h" +#include "vos_utils.h" + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "csrEse.h" +#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD*/ + +tANI_U8 csrWpaOui[][ CSR_WPA_OUI_SIZE ] = { + { 0x00, 0x50, 0xf2, 0x00 }, + { 0x00, 0x50, 0xf2, 0x01 }, + { 0x00, 0x50, 0xf2, 0x02 }, + { 0x00, 0x50, 0xf2, 0x03 }, + { 0x00, 0x50, 0xf2, 0x04 }, + { 0x00, 0x50, 0xf2, 0x05 }, +#ifdef FEATURE_WLAN_ESE + { 0x00, 0x40, 0x96, 0x00 }, // CCKM +#endif /* FEATURE_WLAN_ESE */ +}; + +tANI_U8 csrRSNOui[][ CSR_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 + { 0x00, 0x0F, 0xAC, 0x06 }, // BIP (encryption type) or RSN-PSK-SHA256 (authentication type) + /* RSN-8021X-SHA256 (authentication type) */ + { 0x00, 0x0F, 0xAC, 0x05 } +}; + +#ifdef FEATURE_WLAN_WAPI +tANI_U8 csrWapiOui[][ CSR_WAPI_OUI_SIZE ] = { + { 0x00, 0x14, 0x72, 0x00 }, // Reserved + { 0x00, 0x14, 0x72, 0x01 }, // WAI certificate or SMS4 + { 0x00, 0x14, 0x72, 0x02 } // WAI PSK +}; +#endif /* FEATURE_WLAN_WAPI */ +tANI_U8 csrWmeInfoOui[ CSR_WME_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x02 }; +tANI_U8 csrWmeParmOui[ CSR_WME_OUI_SIZE ] = { 0x00, 0x50, 0xf2, 0x02 }; + +static tCsrIELenInfo gCsrIELengthTable[] = { +/* 000 */ { SIR_MAC_SSID_EID_MIN, SIR_MAC_SSID_EID_MAX }, +/* 001 */ { SIR_MAC_RATESET_EID_MIN, SIR_MAC_RATESET_EID_MAX }, +/* 002 */ { SIR_MAC_FH_PARAM_SET_EID_MIN, SIR_MAC_FH_PARAM_SET_EID_MAX }, +/* 003 */ { SIR_MAC_DS_PARAM_SET_EID_MIN, SIR_MAC_DS_PARAM_SET_EID_MAX }, +/* 004 */ { SIR_MAC_CF_PARAM_SET_EID_MIN, SIR_MAC_CF_PARAM_SET_EID_MAX }, +/* 005 */ { SIR_MAC_TIM_EID_MIN, SIR_MAC_TIM_EID_MAX }, +/* 006 */ { SIR_MAC_IBSS_PARAM_SET_EID_MIN, SIR_MAC_IBSS_PARAM_SET_EID_MAX }, +/* 007 */ { SIR_MAC_COUNTRY_EID_MIN, SIR_MAC_COUNTRY_EID_MAX }, +/* 008 */ { SIR_MAC_FH_PARAMS_EID_MIN, SIR_MAC_FH_PARAMS_EID_MAX }, +/* 009 */ { SIR_MAC_FH_PATTERN_EID_MIN, SIR_MAC_FH_PATTERN_EID_MAX }, +/* 010 */ { SIR_MAC_REQUEST_EID_MIN, SIR_MAC_REQUEST_EID_MAX }, +/* 011 */ { SIR_MAC_QBSS_LOAD_EID_MIN, SIR_MAC_QBSS_LOAD_EID_MAX }, +/* 012 */ { SIR_MAC_EDCA_PARAM_SET_EID_MIN, SIR_MAC_EDCA_PARAM_SET_EID_MAX }, +/* 013 */ { SIR_MAC_TSPEC_EID_MIN, SIR_MAC_TSPEC_EID_MAX }, +/* 014 */ { SIR_MAC_TCLAS_EID_MIN, SIR_MAC_TCLAS_EID_MAX }, +/* 015 */ { SIR_MAC_QOS_SCHEDULE_EID_MIN, SIR_MAC_QOS_SCHEDULE_EID_MAX }, +/* 016 */ { SIR_MAC_CHALLENGE_TEXT_EID_MIN, SIR_MAC_CHALLENGE_TEXT_EID_MAX }, +/* 017 */ { 0, 255 }, +/* 018 */ { 0, 255 }, +/* 019 */ { 0, 255 }, +/* 020 */ { 0, 255 }, +/* 021 */ { 0, 255 }, +/* 022 */ { 0, 255 }, +/* 023 */ { 0, 255 }, +/* 024 */ { 0, 255 }, +/* 025 */ { 0, 255 }, +/* 026 */ { 0, 255 }, +/* 027 */ { 0, 255 }, +/* 028 */ { 0, 255 }, +/* 029 */ { 0, 255 }, +/* 030 */ { 0, 255 }, +/* 031 */ { 0, 255 }, +/* 032 */ { SIR_MAC_PWR_CONSTRAINT_EID_MIN, SIR_MAC_PWR_CONSTRAINT_EID_MAX }, +/* 033 */ { SIR_MAC_PWR_CAPABILITY_EID_MIN, SIR_MAC_PWR_CAPABILITY_EID_MAX }, +/* 034 */ { SIR_MAC_TPC_REQ_EID_MIN, SIR_MAC_TPC_REQ_EID_MAX }, +/* 035 */ { SIR_MAC_TPC_RPT_EID_MIN, SIR_MAC_TPC_RPT_EID_MAX }, +/* 036 */ { SIR_MAC_SPRTD_CHNLS_EID_MIN, SIR_MAC_SPRTD_CHNLS_EID_MAX }, +/* 037 */ { SIR_MAC_CHNL_SWITCH_ANN_EID_MIN, SIR_MAC_CHNL_SWITCH_ANN_EID_MAX }, +/* 038 */ { SIR_MAC_MEAS_REQ_EID_MIN, SIR_MAC_MEAS_REQ_EID_MAX }, +/* 039 */ { SIR_MAC_MEAS_RPT_EID_MIN, SIR_MAC_MEAS_RPT_EID_MAX }, +/* 040 */ { SIR_MAC_QUIET_EID_MIN, SIR_MAC_QUIET_EID_MAX }, +/* 041 */ { SIR_MAC_IBSS_DFS_EID_MIN, SIR_MAC_IBSS_DFS_EID_MAX }, +/* 042 */ { SIR_MAC_ERP_INFO_EID_MIN, SIR_MAC_ERP_INFO_EID_MAX }, +/* 043 */ { SIR_MAC_TS_DELAY_EID_MIN, SIR_MAC_TS_DELAY_EID_MAX }, +/* 044 */ { SIR_MAC_TCLAS_PROC_EID_MIN, SIR_MAC_TCLAS_PROC_EID_MAX }, +/* 045 */ { SIR_MAC_QOS_ACTION_EID_MIN, SIR_MAC_QOS_ACTION_EID_MAX }, +/* 046 */ { SIR_MAC_QOS_CAPABILITY_EID_MIN, SIR_MAC_QOS_CAPABILITY_EID_MAX }, +/* 047 */ { 0, 255 }, +/* 048 */ { SIR_MAC_RSN_EID_MIN, SIR_MAC_RSN_EID_MAX }, +/* 049 */ { 0, 255 }, +/* 050 */ { SIR_MAC_EXTENDED_RATE_EID_MIN, SIR_MAC_EXTENDED_RATE_EID_MAX }, +/* 051 */ { 0, 255 }, +/* 052 */ { 0, 255 }, +/* 053 */ { 0, 255 }, +/* 054 */ { 0, 255 }, +/* 055 */ { 0, 255 }, +/* 056 */ { 0, 255 }, +/* 057 */ { 0, 255 }, +/* 058 */ { 0, 255 }, +/* 059 */ { SIR_MAC_OPERATING_CLASS_EID_MIN, SIR_MAC_OPERATING_CLASS_EID_MAX }, +/* 060 */ { SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID_MIN, SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID_MAX}, +/* 061 */ { 0, 255 }, +/* 062 */ { 0, 255 }, +/* 063 */ { 0, 255 }, +/* 064 */ { 0, 255 }, +/* 065 */ { 0, 255 }, +/* 066 */ { 0, 255 }, +/* 067 */ { 0, 255 }, +#ifdef FEATURE_WLAN_WAPI +/* 068 */ { DOT11F_EID_WAPI, DOT11F_IE_WAPI_MAX_LEN }, +#else +/* 068 */ { 0, 255 }, +#endif /* FEATURE_WLAN_WAPI */ +/* 069 */ { 0, 255 }, +/* 070 */ { 0, 255 }, +/* 071 */ { 0, 255 }, +/* 072 */ { 0, 255 }, +/* 073 */ { 0, 255 }, +/* 074 */ { 0, 255 }, +/* 075 */ { 0, 255 }, +/* 076 */ { 0, 255 }, +/* 077 */ { 0, 255 }, +/* 078 */ { 0, 255 }, +/* 079 */ { 0, 255 }, +/* 080 */ { 0, 255 }, +/* 081 */ { 0, 255 }, +/* 082 */ { 0, 255 }, +/* 083 */ { 0, 255 }, +/* 084 */ { 0, 255 }, +/* 085 */ { 0, 255 }, +/* 086 */ { 0, 255 }, +/* 087 */ { 0, 255 }, +/* 088 */ { 0, 255 }, +/* 089 */ { 0, 255 }, +/* 090 */ { 0, 255 }, +/* 091 */ { 0, 255 }, +/* 092 */ { 0, 255 }, +/* 093 */ { 0, 255 }, +/* 094 */ { 0, 255 }, +/* 095 */ { 0, 255 }, +/* 096 */ { 0, 255 }, +/* 097 */ { 0, 255 }, +/* 098 */ { 0, 255 }, +/* 099 */ { 0, 255 }, +/* 100 */ { 0, 255 }, +/* 101 */ { 0, 255 }, +/* 102 */ { 0, 255 }, +/* 103 */ { 0, 255 }, +/* 104 */ { 0, 255 }, +/* 105 */ { 0, 255 }, +/* 106 */ { 0, 255 }, +/* 107 */ { 0, 255 }, +/* 108 */ { 0, 255 }, +/* 109 */ { 0, 255 }, +/* 110 */ { 0, 255 }, +/* 111 */ { 0, 255 }, +/* 112 */ { 0, 255 }, +/* 113 */ { 0, 255 }, +/* 114 */ { 0, 255 }, +/* 115 */ { 0, 255 }, +/* 116 */ { 0, 255 }, +/* 117 */ { 0, 255 }, +/* 118 */ { 0, 255 }, +/* 119 */ { 0, 255 }, +/* 120 */ { 0, 255 }, +/* 121 */ { 0, 255 }, +/* 122 */ { 0, 255 }, +/* 123 */ { 0, 255 }, +/* 124 */ { 0, 255 }, +/* 125 */ { 0, 255 }, +/* 126 */ { 0, 255 }, +/* 127 */ { 0, 255 }, +/* 128 */ { 0, 255 }, +/* 129 */ { 0, 255 }, +/* 130 */ { 0, 255 }, +/* 131 */ { 0, 255 }, +/* 132 */ { 0, 255 }, +/* 133 */ { 0, 255 }, +/* 134 */ { 0, 255 }, +/* 135 */ { 0, 255 }, +/* 136 */ { 0, 255 }, +/* 137 */ { 0, 255 }, +/* 138 */ { 0, 255 }, +/* 139 */ { 0, 255 }, +/* 140 */ { 0, 255 }, +/* 141 */ { 0, 255 }, +/* 142 */ { 0, 255 }, +/* 143 */ { 0, 255 }, +/* 144 */ { 0, 255 }, +/* 145 */ { 0, 255 }, +/* 146 */ { 0, 255 }, +/* 147 */ { 0, 255 }, +/* 148 */ { 0, 255 }, +/* 149 */ { 0, 255 }, +/* 150 */ { 0, 255 }, +/* 151 */ { 0, 255 }, +/* 152 */ { 0, 255 }, +/* 153 */ { 0, 255 }, +/* 154 */ { 0, 255 }, +/* 155 */ { 0, 255 }, +/* 156 */ { 0, 255 }, +/* 157 */ { 0, 255 }, +/* 158 */ { 0, 255 }, +/* 159 */ { 0, 255 }, +/* 160 */ { 0, 255 }, +/* 161 */ { 0, 255 }, +/* 162 */ { 0, 255 }, +/* 163 */ { 0, 255 }, +/* 164 */ { 0, 255 }, +/* 165 */ { 0, 255 }, +/* 166 */ { 0, 255 }, +/* 167 */ { 0, 255 }, +/* 168 */ { 0, 255 }, +/* 169 */ { 0, 255 }, +/* 170 */ { 0, 255 }, +/* 171 */ { 0, 255 }, +/* 172 */ { 0, 255 }, +/* 173 */ { 0, 255 }, +/* 174 */ { 0, 255 }, +/* 175 */ { 0, 255 }, +/* 176 */ { 0, 255 }, +/* 177 */ { 0, 255 }, +/* 178 */ { 0, 255 }, +/* 179 */ { 0, 255 }, +/* 180 */ { 0, 255 }, +/* 181 */ { 0, 255 }, +/* 182 */ { 0, 255 }, +/* 183 */ { 0, 255 }, +/* 184 */ { 0, 255 }, +/* 185 */ { 0, 255 }, +/* 186 */ { 0, 255 }, +/* 187 */ { 0, 255 }, +/* 188 */ { 0, 255 }, +/* 189 */ { 0, 255 }, +/* 190 */ { 0, 255 }, +/* 191 */ { 0, 255 }, +/* 192 */ { 0, 255 }, +/* 193 */ { 0, 255 }, +/* 194 */ { 0, 255 }, +/* 195 */ { 0, 255 }, +/* 196 */ { 0, 255 }, +/* 197 */ { 0, 255 }, +/* 198 */ { 0, 255 }, +/* 199 */ { 0, 255 }, +/* 200 */ { 0, 255 }, +/* 201 */ { 0, 255 }, +/* 202 */ { 0, 255 }, +/* 203 */ { 0, 255 }, +/* 204 */ { 0, 255 }, +/* 205 */ { 0, 255 }, +/* 206 */ { 0, 255 }, +/* 207 */ { 0, 255 }, +/* 208 */ { 0, 255 }, +/* 209 */ { 0, 255 }, +/* 210 */ { 0, 255 }, +/* 211 */ { 0, 255 }, +/* 212 */ { 0, 255 }, +/* 213 */ { 0, 255 }, +/* 214 */ { 0, 255 }, +/* 215 */ { 0, 255 }, +/* 216 */ { 0, 255 }, +/* 217 */ { 0, 255 }, +/* 218 */ { 0, 255 }, +/* 219 */ { 0, 255 }, +/* 220 */ { 0, 255 }, +/* 221 */ { SIR_MAC_WPA_EID_MIN, SIR_MAC_WPA_EID_MAX }, +/* 222 */ { 0, 255 }, +/* 223 */ { 0, 255 }, +/* 224 */ { 0, 255 }, +/* 225 */ { 0, 255 }, +/* 226 */ { 0, 255 }, +/* 227 */ { 0, 255 }, +/* 228 */ { 0, 255 }, +/* 229 */ { 0, 255 }, +/* 230 */ { 0, 255 }, +/* 231 */ { 0, 255 }, +/* 232 */ { 0, 255 }, +/* 233 */ { 0, 255 }, +/* 234 */ { 0, 255 }, +/* 235 */ { 0, 255 }, +/* 236 */ { 0, 255 }, +/* 237 */ { 0, 255 }, +/* 238 */ { 0, 255 }, +/* 239 */ { 0, 255 }, +/* 240 */ { 0, 255 }, +/* 241 */ { 0, 255 }, +/* 242 */ { 0, 255 }, +/* 243 */ { 0, 255 }, +/* 244 */ { 0, 255 }, +/* 245 */ { 0, 255 }, +/* 246 */ { 0, 255 }, +/* 247 */ { 0, 255 }, +/* 248 */ { 0, 255 }, +/* 249 */ { 0, 255 }, +/* 250 */ { 0, 255 }, +/* 251 */ { 0, 255 }, +/* 252 */ { 0, 255 }, +/* 253 */ { 0, 255 }, +/* 254 */ { 0, 255 }, +/* 255 */ { SIR_MAC_ANI_WORKAROUND_EID_MIN, SIR_MAC_ANI_WORKAROUND_EID_MAX } +}; + +extern const tRfChannelProps rfChannels[NUM_RF_CHANNELS]; + +//////////////////////////////////////////////////////////////////////// + +/** + * \var gPhyRatesSuppt + * + * \brief Rate support lookup table + * + * + * This is a lookup table indexing rates & configuration parameters to + * support. Given a rate (in unites of 0.5Mpbs) & three booleans (MIMO + * Enabled, Channel Bonding Enabled, & Concatenation Enabled), one can + * determine whether the given rate is supported by computing two + * indices. The first maps the rate to table row as indicated below + * (i.e. eHddSuppRate_6Mbps maps to row zero, eHddSuppRate_9Mbps to row + * 1, and so on). Index two can be computed like so: + * + * \code + idx2 = ( fEsf ? 0x4 : 0x0 ) | + ( fCb ? 0x2 : 0x0 ) | + ( fMimo ? 0x1 : 0x0 ); + * \endcode + * + * + * Given that: + * + \code + fSupported = gPhyRatesSuppt[idx1][idx2]; + \endcode + * + * + * This table is based on the document "PHY Supported Rates.doc". This + * table is permissive in that a rate is reflected as being supported + * even when turning off an enabled feature would be required. For + * instance, "PHY Supported Rates" lists 42Mpbs as unsupported when CB, + * ESF, & MIMO are all on. However, if we turn off either of CB or + * MIMO, it then becomes supported. Therefore, we mark it as supported + * even in index 7 of this table. + * + * + */ + +static const tANI_BOOLEAN gPhyRatesSuppt[24][8] = { + + // SSF SSF SSF SSF ESF ESF ESF ESF + // SIMO MIMO SIMO MIMO SIMO MIMO SIMO MIMO + // No CB No CB CB CB No CB No CB CB CB + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 6Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 9Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 12Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 18Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE }, // 20Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 24Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 36Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 40Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 42Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 48Mbps + { TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // 54Mbps + { FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 72Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 80Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 84Mbps + { FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 96Mbps + { FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 108Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 120Mbps + { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE }, // 126Mbps + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 144Mbps + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 160Mbps + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 168Mbps + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 192Mbps + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 216Mbps + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE }, // 240Mbps + +}; + +#define CASE_RETURN_STR(n) case (n): return (#n) + +const char * +get_eRoamCmdStatus_str(eRoamCmdStatus val) +{ + switch (val) + { + CASE_RETURN_STR(eCSR_ROAM_CANCELLED); + CASE_RETURN_STR(eCSR_ROAM_FAILED); + CASE_RETURN_STR(eCSR_ROAM_ROAMING_START); + CASE_RETURN_STR(eCSR_ROAM_ROAMING_COMPLETION); + CASE_RETURN_STR(eCSR_ROAM_CONNECT_COMPLETION); + CASE_RETURN_STR(eCSR_ROAM_ASSOCIATION_START); + CASE_RETURN_STR(eCSR_ROAM_ASSOCIATION_COMPLETION); + CASE_RETURN_STR(eCSR_ROAM_DISASSOCIATED); + CASE_RETURN_STR(eCSR_ROAM_SHOULD_ROAM); + CASE_RETURN_STR(eCSR_ROAM_SCAN_FOUND_NEW_BSS); + CASE_RETURN_STR(eCSR_ROAM_LOSTLINK); + CASE_RETURN_STR(eCSR_ROAM_LOSTLINK_DETECTED); + CASE_RETURN_STR(eCSR_ROAM_MIC_ERROR_IND); + CASE_RETURN_STR(eCSR_ROAM_IBSS_IND); + CASE_RETURN_STR(eCSR_ROAM_CONNECT_STATUS_UPDATE); + CASE_RETURN_STR(eCSR_ROAM_GEN_INFO); + CASE_RETURN_STR(eCSR_ROAM_SET_KEY_COMPLETE); + CASE_RETURN_STR(eCSR_ROAM_REMOVE_KEY_COMPLETE); + CASE_RETURN_STR(eCSR_ROAM_IBSS_LEAVE); + CASE_RETURN_STR(eCSR_ROAM_WDS_IND); + CASE_RETURN_STR(eCSR_ROAM_INFRA_IND); + CASE_RETURN_STR(eCSR_ROAM_WPS_PBC_PROBE_REQ_IND); +#ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STR(eCSR_ROAM_FT_RESPONSE); +#endif + CASE_RETURN_STR(eCSR_ROAM_FT_START); + CASE_RETURN_STR(eCSR_ROAM_INDICATE_MGMT_FRAME); + CASE_RETURN_STR(eCSR_ROAM_REMAIN_CHAN_READY); + CASE_RETURN_STR(eCSR_ROAM_SEND_ACTION_CNF); + CASE_RETURN_STR(eCSR_ROAM_SESSION_OPENED); + CASE_RETURN_STR(eCSR_ROAM_FT_REASSOC_FAILED); +#ifdef FEATURE_WLAN_LFR + CASE_RETURN_STR(eCSR_ROAM_PMK_NOTIFY); +#endif +#ifdef FEATURE_WLAN_LFR_METRICS + CASE_RETURN_STR(eCSR_ROAM_PREAUTH_INIT_NOTIFY); + CASE_RETURN_STR(eCSR_ROAM_PREAUTH_STATUS_SUCCESS); + CASE_RETURN_STR(eCSR_ROAM_PREAUTH_STATUS_FAILURE); + CASE_RETURN_STR(eCSR_ROAM_HANDOVER_SUCCESS); +#endif +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STR(eCSR_ROAM_TDLS_STATUS_UPDATE); + CASE_RETURN_STR(eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND); +#endif + CASE_RETURN_STR(eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS); + CASE_RETURN_STR(eCSR_ROAM_SEND_P2P_STOP_BSS); +#ifdef WLAN_FEATURE_11W + CASE_RETURN_STR(eCSR_ROAM_UNPROT_MGMT_FRAME_IND); +#endif +#ifdef WLAN_FEATURE_RMC + CASE_RETURN_STR(eCSR_ROAM_IBSS_PEER_INFO_COMPLETE); +#endif +#ifdef WLAN_FEATURE_AP_HT40_24G + CASE_RETURN_STR(eCSR_ROAM_2040_COEX_INFO_IND); +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + CASE_RETURN_STR(eCSR_ROAM_TSM_IE_IND); + CASE_RETURN_STR(eCSR_ROAM_CCKM_PREAUTH_NOTIFY); + CASE_RETURN_STR(eCSR_ROAM_ESE_ADJ_AP_REPORT_IND); + CASE_RETURN_STR(eCSR_ROAM_ESE_BCN_REPORT_IND); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + default: + return "unknown"; + } +} + +const char * +get_eCsrRoamResult_str(eCsrRoamResult val) +{ + switch (val) + { + CASE_RETURN_STR(eCSR_ROAM_RESULT_NONE); + CASE_RETURN_STR(eCSR_ROAM_RESULT_FAILURE); + CASE_RETURN_STR(eCSR_ROAM_RESULT_ASSOCIATED); + CASE_RETURN_STR(eCSR_ROAM_RESULT_NOT_ASSOCIATED); + CASE_RETURN_STR(eCSR_ROAM_RESULT_MIC_FAILURE); + CASE_RETURN_STR(eCSR_ROAM_RESULT_FORCED); + CASE_RETURN_STR(eCSR_ROAM_RESULT_DISASSOC_IND); + CASE_RETURN_STR(eCSR_ROAM_RESULT_DEAUTH_IND); + CASE_RETURN_STR(eCSR_ROAM_RESULT_CAP_CHANGED); + CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_CONNECT); + CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_INACTIVE); + CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_NEW_PEER); + CASE_RETURN_STR(eCSR_ROAM_RESULT_IBSS_COALESCED); + default: + return "unknown"; + } +} + + + +tANI_BOOLEAN csrGetBssIdBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc, tCsrBssid *pBssId ) +{ + vos_mem_copy(pBssId, &pSirBssDesc->bssId[ 0 ], sizeof(tCsrBssid)); + return( TRUE ); +} + + +tANI_BOOLEAN csrIsBssIdEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1, tSirBssDescription *pSirBssDesc2 ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fEqual = FALSE; + tCsrBssid bssId1; + tCsrBssid bssId2; + + do { + if ( !pSirBssDesc1 ) break; + if ( !pSirBssDesc2 ) break; + + if ( !csrGetBssIdBssDesc( pMac, pSirBssDesc1, &bssId1 ) ) break; + if ( !csrGetBssIdBssDesc( pMac, pSirBssDesc2, &bssId2 ) ) break; + + //sirCompareMacAddr + fEqual = csrIsMacAddressEqual(pMac, &bssId1, &bssId2); + + } while( 0 ); + + return( fEqual ); +} + +tANI_BOOLEAN csrIsConnStateConnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED == pMac->roam.roamSession[sessionId].connectState ); +} + +tANI_BOOLEAN csrIsConnStateDisconnectedIbss( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED == pMac->roam.roamSession[sessionId].connectState ); +} + +tANI_BOOLEAN csrIsConnStateConnectedInfra( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED == pMac->roam.roamSession[sessionId].connectState ); +} + +tANI_BOOLEAN csrIsConnStateConnected( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + if( csrIsConnStateConnectedIbss( pMac, sessionId ) || csrIsConnStateConnectedInfra( pMac, sessionId ) || csrIsConnStateConnectedWds( pMac, sessionId) ) + return TRUE; + else + return FALSE; +} + +tANI_BOOLEAN csrIsConnStateInfra( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( csrIsConnStateConnectedInfra( pMac, sessionId ) ); +} + +tANI_BOOLEAN csrIsConnStateIbss( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( csrIsConnStateConnectedIbss( pMac, sessionId ) || csrIsConnStateDisconnectedIbss( pMac, sessionId ) ); +} + + +tANI_BOOLEAN csrIsConnStateConnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED == pMac->roam.roamSession[sessionId].connectState ); +} + +tANI_BOOLEAN csrIsConnStateConnectedInfraAp( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( (eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED == pMac->roam.roamSession[sessionId].connectState) || + (eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED == pMac->roam.roamSession[sessionId].connectState ) ); +} + +tANI_BOOLEAN csrIsConnStateDisconnectedWds( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED == pMac->roam.roamSession[sessionId].connectState ); +} + +tANI_BOOLEAN csrIsConnStateWds( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return( csrIsConnStateConnectedWds( pMac, sessionId ) || + csrIsConnStateDisconnectedWds( pMac, sessionId ) ); +} + +tANI_BOOLEAN csrIsConnStateAp( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + tCsrRoamSession *pSession; + pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) + return eANI_BOOLEAN_FALSE; + if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) ) + { + return eANI_BOOLEAN_TRUE; + } + return eANI_BOOLEAN_FALSE; +} + +tANI_BOOLEAN csrIsAnySessionInConnectState( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && + ( csrIsConnStateInfra( pMac, i ) + || csrIsConnStateIbss( pMac, i ) + || csrIsConnStateAp( pMac, i) ) ) + { + fRc = eANI_BOOLEAN_TRUE; + break; + } + } + + return ( fRc ); +} + +tANI_S8 csrGetInfraSessionId( tpAniSirGlobal pMac ) +{ + tANI_U8 i; + tANI_S8 sessionid = -1; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateInfra( pMac, i ) ) + { + sessionid = i; + break; + } + } + + return ( sessionid ); +} + +tANI_U8 csrGetInfraOperationChannel( tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tANI_U8 channel; + + if( CSR_IS_SESSION_VALID( pMac, sessionId )) + { + channel = pMac->roam.roamSession[sessionId].connectedProfile.operationChannel; + } + else + { + channel = 0; + } + return channel; +} + +tANI_BOOLEAN csrIsSessionClientAndConnected(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tCsrRoamSession *pSession = NULL; + if (CSR_IS_SESSION_VALID( pMac, sessionId) && csrIsConnStateInfra( pMac, sessionId)) + { + pSession = CSR_GET_SESSION( pMac, sessionId); + if (NULL != pSession->pCurRoamProfile) + { + if ((pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE) || + (pSession->pCurRoamProfile->csrPersona == VOS_P2P_CLIENT_MODE)) + return TRUE; + } + } + return FALSE; +} +//This routine will return operating channel on FIRST BSS that is active/operating to be used for concurrency mode. +//If other BSS is not up or not connected it will return 0 + +tANI_U8 csrGetConcurrentOperationChannel( tpAniSirGlobal pMac ) +{ + tCsrRoamSession *pSession = NULL; + tANI_U8 i = 0; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + + if (NULL != pSession->pCurRoamProfile) + { + if ( + (((pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE) || + (pSession->pCurRoamProfile->csrPersona == VOS_P2P_CLIENT_MODE)) && + (pSession->connectState == eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED)) + || + (((pSession->pCurRoamProfile->csrPersona == VOS_P2P_GO_MODE) || + (pSession->pCurRoamProfile->csrPersona == VOS_STA_SAP_MODE)) && + (pSession->connectState != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) + ) + return (pSession->connectedProfile.operationChannel); + } + + } + } + return 0; +} +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + +#define HALF_BW_OF(eCSR_bw_val) ((eCSR_bw_val)/2) + +/* calculation of center channel based on V/HT BW and WIFI channel bw=5MHz) */ + +#define CSR_GET_HT40_PLUS_CCH(och) ((och)+2) +#define CSR_GET_HT40_MINUS_CCH(och) ((och)-2) + +#define CSR_GET_HT80_PLUS_LL_CCH(och) ((och)+6) +#define CSR_GET_HT80_PLUS_HL_CCH(och) ((och)+2) +#define CSR_GET_HT80_MINUS_LH_CCH(och) ((och)-2) +#define CSR_GET_HT80_MINUS_HH_CCH(och) ((och)-6) + +void csrGetChFromHTProfile (tpAniSirGlobal pMac, tCsrRoamHTProfile *htp, + tANI_U16 och, tANI_U16 *cfreq, tANI_U16 *hbw) +{ + tANI_U16 cch, ch_bond; + + if (och > 14) + ch_bond = pMac->roam.configParam.channelBondingMode5GHz; + else + ch_bond = pMac->roam.configParam.channelBondingMode24GHz; + + cch = och; + *hbw = HALF_BW_OF(eCSR_BW_20MHz_VAL); + + if (!ch_bond) { + goto ret; + } + smsLog(pMac, LOG1, + FL("##HTC: %d scbw: %d rcbw: %d sco: %d" +#ifdef WLAN_FEATURE_11AC + "VHTC: %d apc: %d apbw: %d" +#endif + ), + htp->htCapability, htp->htSupportedChannelWidthSet, + htp->htRecommendedTxWidthSet, htp->htSecondaryChannelOffset, +#ifdef WLAN_FEATURE_11AC + htp->vhtCapability, htp->apCenterChan, htp->apChanWidth +#endif + ); + +#ifdef WLAN_FEATURE_11AC + if (htp->vhtCapability) { + cch = htp->apCenterChan; + if (htp->apChanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) + *hbw = HALF_BW_OF(eCSR_BW_80MHz_VAL); + else if (htp->apChanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) + *hbw = HALF_BW_OF(eCSR_BW_160MHz_VAL); + + if (!*hbw && htp->htCapability) { + if (htp->htSupportedChannelWidthSet == eHT_CHANNEL_WIDTH_40MHZ) + *hbw = HALF_BW_OF(eCSR_BW_40MHz_VAL); + else + *hbw = HALF_BW_OF(eCSR_BW_20MHz_VAL); + } + } else +#endif + if (htp->htCapability) { + if (htp->htSupportedChannelWidthSet == eHT_CHANNEL_WIDTH_40MHZ) { + *hbw = HALF_BW_OF(eCSR_BW_40MHz_VAL); + if (htp->htSecondaryChannelOffset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + cch = CSR_GET_HT40_PLUS_CCH(och); + else if (htp->htSecondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + cch = CSR_GET_HT40_MINUS_CCH(och); + } else { + cch = och; + *hbw = HALF_BW_OF(eCSR_BW_20MHz_VAL); + } + } + +ret: + *cfreq = vos_chan_to_freq(cch); + return; +} + +v_U16_t csrCheckConcurrentChannelOverlap(tpAniSirGlobal pMac, v_U16_t sap_ch, + eCsrPhyMode sap_phymode, v_U8_t cc_switch_mode) +{ + tCsrRoamSession *pSession = NULL; + v_U8_t i = 0, chb = PHY_SINGLE_CHANNEL_CENTERED; + v_U16_t intf_ch=0, sap_hbw = 0, intf_hbw = 0, intf_cfreq = 0, sap_cfreq = 0; + v_U16_t sap_lfreq, sap_hfreq, intf_lfreq, intf_hfreq, sap_cch; + + if (pMac->roam.configParam.cc_switch_mode == VOS_MCC_TO_SCC_SWITCH_DISABLE) + return 0; + + if (sap_ch !=0) { + + sap_cch = sap_ch; + sap_hbw = HALF_BW_OF(eCSR_BW_20MHz_VAL); + + if (sap_ch > 14) + chb = pMac->roam.configParam.channelBondingMode5GHz; + else + chb = pMac->roam.configParam.channelBondingMode24GHz; + + if (chb) { + if (sap_phymode == eCSR_DOT11_MODE_11n || + sap_phymode == eCSR_DOT11_MODE_11n_ONLY) { + + sap_hbw = HALF_BW_OF(eCSR_BW_40MHz_VAL); + if (chb == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + sap_cch = CSR_GET_HT40_PLUS_CCH(sap_ch); + else if (chb == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + sap_cch = CSR_GET_HT40_MINUS_CCH(sap_ch); + + } +#ifdef WLAN_FEATURE_11AC + else if (sap_phymode == eCSR_DOT11_MODE_11ac || + sap_phymode == eCSR_DOT11_MODE_11ac_ONLY) { + /*11AC only 80/40/20 Mhz supported in Rome */ + if (pMac->roam.configParam.nVhtChannelWidth == + (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ + 1)) { + sap_hbw = HALF_BW_OF(eCSR_BW_80MHz_VAL); + if (chb == (PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW-1)) + sap_cch = CSR_GET_HT80_PLUS_LL_CCH(sap_ch); + else if (chb == + (PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW-1)) + sap_cch = CSR_GET_HT80_PLUS_HL_CCH(sap_ch); + else if (chb == + (PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH-1)) + sap_cch = CSR_GET_HT80_MINUS_LH_CCH(sap_ch); + else if (chb == + (PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH-1)) + sap_cch = CSR_GET_HT80_MINUS_HH_CCH(sap_ch); + } else { + sap_hbw = HALF_BW_OF(eCSR_BW_40MHz_VAL); + if (chb == (PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW-1)) + sap_cch = CSR_GET_HT40_PLUS_CCH(sap_ch); + else if (chb == + (PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW-1)) + sap_cch = CSR_GET_HT40_MINUS_CCH(sap_ch); + else if (chb == + (PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH-1)) + sap_cch = CSR_GET_HT40_PLUS_CCH(sap_ch); + else if (chb == + (PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH-1)) + sap_cch = CSR_GET_HT40_MINUS_CCH(sap_ch); + } + } +#endif + } + sap_cfreq = vos_chan_to_freq(sap_cch); + } + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) { + if( !CSR_IS_SESSION_VALID( pMac, i ) ) + continue; + + pSession = CSR_GET_SESSION( pMac, i ); + + if (NULL != pSession->pCurRoamProfile) { + if (((pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE) || + (pSession->pCurRoamProfile->csrPersona == + VOS_P2P_CLIENT_MODE)) && + (pSession->connectState == + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED)) { + intf_ch = pSession->connectedProfile.operationChannel; + csrGetChFromHTProfile(pMac, + &pSession->connectedProfile.HTProfile, intf_ch, + &intf_cfreq, &intf_hbw); + } else if(((pSession->pCurRoamProfile->csrPersona == + VOS_P2P_GO_MODE) || + (pSession->pCurRoamProfile->csrPersona == + VOS_STA_SAP_MODE)) && + (pSession->connectState != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + if (pSession->ch_switch_in_progress) + continue; + /* + * if conc_custom_rule1 is defined then we don't want p2pgo to + * follow SAP's channel or SAP to follow P2PGO's channel. + */ + if (0 == pMac->roam.configParam.conc_custom_rule1 && + 0 == pMac->roam.configParam.conc_custom_rule2) { + if (sap_ch == 0) { + sap_ch = pSession->connectedProfile.operationChannel; + csrGetChFromHTProfile(pMac, + &pSession->connectedProfile.HTProfile, sap_ch, + &sap_cfreq, &sap_hbw); + } else if (sap_ch != + pSession->connectedProfile.operationChannel) { + intf_ch = pSession->connectedProfile.operationChannel; + csrGetChFromHTProfile(pMac, + &pSession->connectedProfile.HTProfile, intf_ch, + &intf_cfreq, &intf_hbw); + } + } else { + if (sap_ch == 0 && + (pSession->pCurRoamProfile->csrPersona == + VOS_STA_SAP_MODE)) { + sap_ch = pSession->connectedProfile.operationChannel; + csrGetChFromHTProfile(pMac, + &pSession->connectedProfile.HTProfile, sap_ch, + &sap_cfreq, &sap_hbw); + } + } + } + } + } + + + if (intf_ch && sap_ch != intf_ch && + cc_switch_mode != VOS_MCC_TO_SCC_SWITCH_FORCE) { + sap_lfreq = sap_cfreq - sap_hbw; + sap_hfreq = sap_cfreq + sap_hbw; + intf_lfreq = intf_cfreq -intf_hbw; + intf_hfreq = intf_cfreq +intf_hbw; + + smsLog(pMac, LOGE, + FL("\nSAP: OCH: %03d OCF: %d CCH: %03d CF: %d BW: %d LF: %d HF: %d\n" + "INTF: OCH: %03d OCF: %d CCH: %03d CF: %d BW: %d LF: %d HF: %d"), + sap_ch, vos_chan_to_freq(sap_ch), vos_freq_to_chan(sap_cfreq), + sap_cfreq, sap_hbw*2, sap_lfreq, sap_hfreq, + intf_ch, vos_chan_to_freq(intf_ch), + vos_freq_to_chan(intf_cfreq), + intf_cfreq, intf_hbw*2, intf_lfreq, intf_hfreq); + + if (!( + ((sap_lfreq > intf_lfreq && sap_lfreq < intf_hfreq) || + (sap_hfreq > intf_lfreq && sap_hfreq < intf_hfreq)) + || ((intf_lfreq > sap_lfreq && intf_lfreq < sap_hfreq) || + (intf_hfreq > sap_lfreq && intf_hfreq < sap_hfreq)) + )) { + intf_ch = 0; + } + } + else if (intf_ch && sap_ch!= intf_ch && + cc_switch_mode == VOS_MCC_TO_SCC_SWITCH_FORCE) { + if (!((intf_ch < 14 && sap_ch < 14) || (intf_ch > 14 && sap_ch > 14))) + intf_ch = 0; + }else if (intf_ch == sap_ch) + intf_ch = 0; + + smsLog(pMac, LOGE, FL("##Concurrent Channels %s Interfering"), intf_ch == 0 ? + "Not" : "Are" ); + return intf_ch; +} +#endif + +tANI_BOOLEAN csrIsAllSessionDisconnected( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_TRUE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && !csrIsConnStateDisconnected( pMac, i ) ) + { + fRc = eANI_BOOLEAN_FALSE; + break; + } + } + + return ( fRc ); +} + +tANI_BOOLEAN csrIsStaSessionConnected( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + tCsrRoamSession *pSession = NULL; + tANI_U32 countSta = 0; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && !csrIsConnStateDisconnected( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + + if (NULL != pSession->pCurRoamProfile) + { + if (pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE) { + countSta++; + } + } + } + } + + /* return TRUE if one of the following conditions is TRUE: + * - more than one STA session connected + */ + if ( countSta > 0) { + fRc = eANI_BOOLEAN_TRUE; + } + + return( fRc ); +} + +tANI_BOOLEAN csrIsP2pSessionConnected( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + tCsrRoamSession *pSession = NULL; + tANI_U32 countP2pCli = 0; + tANI_U32 countP2pGo = 0; + tANI_U32 countSAP = 0; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && !csrIsConnStateDisconnected( pMac, i ) ) + { + pSession = CSR_GET_SESSION( pMac, i ); + + if (NULL != pSession->pCurRoamProfile) + { + if (pSession->pCurRoamProfile->csrPersona == VOS_P2P_CLIENT_MODE) { + countP2pCli++; + } + + if (pSession->pCurRoamProfile->csrPersona == VOS_P2P_GO_MODE) { + countP2pGo++; + } + if (pSession->pCurRoamProfile->csrPersona == + VOS_STA_SAP_MODE) { + countSAP++; + } + + } + } + } + + /* return TRUE if one of the following conditions is TRUE: + * - at least one P2P CLI session is connected + * - at least one P2P GO session is connected + */ + if ((countP2pCli > 0) || (countP2pGo > 0 ) || (countSAP > 0)) { + fRc = eANI_BOOLEAN_TRUE; + } + + return( fRc ); +} + +tANI_BOOLEAN csrIsAnySessionConnected( tpAniSirGlobal pMac ) +{ + tANI_U32 i, count; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + count = 0; + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && !csrIsConnStateDisconnected( pMac, i ) ) + { + count++; + } + } + + if (count > 0) + { + fRc = eANI_BOOLEAN_TRUE; + } + return( fRc ); +} + +tANI_BOOLEAN csrIsInfraConnected( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateConnectedInfra( pMac, i ) ) + { + fRc = eANI_BOOLEAN_TRUE; + break; + } + } + + return ( fRc ); +} + +tANI_BOOLEAN csrIsConcurrentInfraConnected( tpAniSirGlobal pMac ) +{ + tANI_U32 i, noOfConnectedInfra = 0; + + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateConnectedInfra( pMac, i ) ) + { + ++noOfConnectedInfra; + } + } + + // More than one Infra Sta Connected + if(noOfConnectedInfra > 1) + { + fRc = eANI_BOOLEAN_TRUE; + } + + return ( fRc ); +} + +tANI_BOOLEAN csrIsIBSSStarted( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateIbss( pMac, i ) ) + { + fRc = eANI_BOOLEAN_TRUE; + break; + } + } + + return ( fRc ); +} + + +tANI_BOOLEAN csrIsBTAMPStarted( tpAniSirGlobal pMac ) +{ + tANI_U32 i; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) + { + if( CSR_IS_SESSION_VALID( pMac, i ) && csrIsConnStateConnectedWds( pMac, i ) ) + { + fRc = eANI_BOOLEAN_TRUE; + break; + } + } + + return ( fRc ); +} + +tANI_BOOLEAN csrIsConcurrentSessionRunning( tpAniSirGlobal pMac ) +{ + tANI_U32 sessionId, noOfCocurrentSession = 0; + eCsrConnectState connectState; + + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + connectState = pMac->roam.roamSession[sessionId].connectState; + if( (eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED == connectState) || + (eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED == connectState) || + (eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED == connectState) ) + { + ++noOfCocurrentSession; + } + } + } + + // More than one session is Up and Running + if(noOfCocurrentSession > 1) + { + fRc = eANI_BOOLEAN_TRUE; + } + + return ( fRc ); +} + +tANI_BOOLEAN csrIsInfraApStarted( tpAniSirGlobal pMac ) +{ + tANI_U32 sessionId; + tANI_BOOLEAN fRc = eANI_BOOLEAN_FALSE; + + for( sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) && (csrIsConnStateConnectedInfraAp(pMac, sessionId)) ) + { + fRc = eANI_BOOLEAN_TRUE; + break; + } + } + + return ( fRc ); + +} + +tANI_BOOLEAN csrIsBTAMP( tpAniSirGlobal pMac, tANI_U32 sessionId ) +{ + return ( csrIsConnStateConnectedWds( pMac, sessionId ) ); +} + + +tANI_BOOLEAN csrIsConnStateDisconnected(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + return (eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED == pMac->roam.roamSession[sessionId].connectState); +} + +tANI_BOOLEAN csrIsValidMcConcurrentSession(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirBssDescription *pBssDesc) +{ + tCsrRoamSession *pSession = NULL; + eAniBoolean status = eANI_BOOLEAN_FALSE; + + //Check for MCC support + if (!pMac->roam.configParam.fenableMCCMode) + { + return status; + } + + //Validate BeaconInterval + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL != pSession->pCurRoamProfile) + { + if (csrIsconcurrentsessionValid (pMac, sessionId, + pSession->pCurRoamProfile->csrPersona) + == eHAL_STATUS_SUCCESS ) + { + if (csrValidateMCCBeaconInterval( pMac, pBssDesc->channelId, + &pBssDesc->beaconInterval, sessionId, + pSession->pCurRoamProfile->csrPersona) + != eHAL_STATUS_SUCCESS) + { + status = eANI_BOOLEAN_FALSE; + } + else + { + status = eANI_BOOLEAN_TRUE; + } + } + else + { + status = eANI_BOOLEAN_FALSE; + } + } + } + return status; +} + +static tSirMacCapabilityInfo csrGetBssCapabilities( tSirBssDescription *pSirBssDesc ) +{ + tSirMacCapabilityInfo dot11Caps; + + //tSirMacCapabilityInfo is 16-bit + pal_get_U16( (tANI_U8 *)&pSirBssDesc->capabilityInfo, (tANI_U16 *)&dot11Caps ); + + return( dot11Caps ); +} + +tANI_BOOLEAN csrIsInfraBssDesc( tSirBssDescription *pSirBssDesc ) +{ + tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc ); + + return( (tANI_BOOLEAN)dot11Caps.ess ); +} + + +tANI_BOOLEAN csrIsIbssBssDesc( tSirBssDescription *pSirBssDesc ) +{ + tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc ); + + return( (tANI_BOOLEAN)dot11Caps.ibss ); +} + +tANI_BOOLEAN csrIsQoSBssDesc( tSirBssDescription *pSirBssDesc ) +{ + tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc ); + + return( (tANI_BOOLEAN)dot11Caps.qos ); +} + +tANI_BOOLEAN csrIsPrivacy( tSirBssDescription *pSirBssDesc ) +{ + tSirMacCapabilityInfo dot11Caps = csrGetBssCapabilities( pSirBssDesc ); + + return( (tANI_BOOLEAN)dot11Caps.privacy ); +} + + +tANI_BOOLEAN csrIs11dSupported(tpAniSirGlobal pMac) +{ + return(pMac->roam.configParam.Is11dSupportEnabled); +} + + +tANI_BOOLEAN csrIs11hSupported(tpAniSirGlobal pMac) +{ + return(pMac->roam.configParam.Is11hSupportEnabled); +} + + +tANI_BOOLEAN csrIs11eSupported(tpAniSirGlobal pMac) +{ + return(pMac->roam.configParam.Is11eSupportEnabled); +} + +tANI_BOOLEAN csrIsMCCSupported ( tpAniSirGlobal pMac ) +{ + return(pMac->roam.configParam.fenableMCCMode); + +} + +tANI_BOOLEAN csrIsWmmSupported(tpAniSirGlobal pMac) +{ + if(eCsrRoamWmmNoQos == pMac->roam.configParam.WMMSupportMode) + { + return eANI_BOOLEAN_FALSE; + } + else + { + return eANI_BOOLEAN_TRUE; + } +} + + + + +//pIes is the IEs for pSirBssDesc2 +tANI_BOOLEAN csrIsSsidEqual( tHalHandle hHal, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2 ) +{ + tANI_BOOLEAN fEqual = FALSE; + tSirMacSSid Ssid1, Ssid2; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tDot11fBeaconIEs *pIes1 = NULL; + tDot11fBeaconIEs *pIesLocal = pIes2; + + do { + if( ( NULL == pSirBssDesc1 ) || ( NULL == pSirBssDesc2 ) ) break; + if( !pIesLocal && !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc2, &pIesLocal)) ) + { + smsLog(pMac, LOGE, FL(" fail to parse IEs")); + break; + } + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc1, &pIes1))) + { + break; + } + if( ( !pIes1->SSID.present ) || ( !pIesLocal->SSID.present ) ) break; + if ( pIes1->SSID.num_ssid != pIesLocal->SSID.num_ssid ) break; + vos_mem_copy(Ssid1.ssId, pIes1->SSID.ssid, pIes1->SSID.num_ssid); + vos_mem_copy(Ssid2.ssId, pIesLocal->SSID.ssid, pIesLocal->SSID.num_ssid); + + fEqual = vos_mem_compare(Ssid1.ssId, Ssid2.ssId, pIesLocal->SSID.num_ssid); + + } while( 0 ); + if(pIes1) + { + vos_mem_free(pIes1); + } + if( pIesLocal && !pIes2 ) + { + vos_mem_free(pIesLocal); + } + + return( fEqual ); +} + + +//pIes can be passed in as NULL if the caller doesn't have one prepared +tANI_BOOLEAN csrIsBssDescriptionWme( tHalHandle hHal, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + // Assume that WME is found... + tANI_BOOLEAN fWme = TRUE; + tDot11fBeaconIEs *pIesTemp = pIes; + + do + { + if(pIesTemp == NULL) + { + if( !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesTemp)) ) + { + fWme = FALSE; + break; + } + } + // if the Wme Info IE is found, then WME is supported... + if ( CSR_IS_QOS_BSS(pIesTemp) ) break; + // if none of these are found, then WME is NOT supported... + fWme = FALSE; + } while( 0 ); + if( !csrIsWmmSupported( pMac ) && fWme) + { + if( !pIesTemp->HTCaps.present ) + { + fWme = FALSE; + } + } + if( ( pIes == NULL ) && ( NULL != pIesTemp ) ) + { + //we allocate memory here so free it before returning + vos_mem_free(pIesTemp); + } + + return( fWme ); +} + +eCsrMediaAccessType csrGetQoSFromBssDesc( tHalHandle hHal, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes ) +{ + eCsrMediaAccessType qosType = eCSR_MEDIUM_ACCESS_DCF; + + if (NULL == pIes) + { + VOS_ASSERT( pIes != NULL ); + return( qosType ); + } + + do + { + // if we find WMM in the Bss Description, then we let this + // override and use WMM. + if ( csrIsBssDescriptionWme( hHal, pSirBssDesc, pIes ) ) + { + qosType = eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP; + } + else + { + // if the QoS bit is on, then the AP is advertising 11E QoS... + if (csrIsQoSBssDesc(pSirBssDesc)) { + qosType = eCSR_MEDIUM_ACCESS_11e_eDCF; + } else { + qosType = eCSR_MEDIUM_ACCESS_DCF; + } + // scale back based on the types turned on for the adapter... + if ( eCSR_MEDIUM_ACCESS_11e_eDCF == qosType && !csrIs11eSupported( hHal ) ) + { + qosType = eCSR_MEDIUM_ACCESS_DCF; + } + } + + } while(0); + + return( qosType ); +} + + + + +//Caller allocates memory for pIEStruct +eHalStatus csrParseBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIEStruct) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + int ieLen = (int)(pBssDesc->length + sizeof( pBssDesc->length ) - GET_FIELD_OFFSET( tSirBssDescription, ieFields )); + + if(ieLen > 0 && pIEStruct) + { + if(!DOT11F_FAILED(dot11fUnpackBeaconIEs( pMac, (tANI_U8 *)pBssDesc->ieFields, ieLen, pIEStruct ))) + { + status = eHAL_STATUS_SUCCESS; + } + } + + return (status); +} + + +//This function will allocate memory for the parsed IEs to the caller. Caller must free the memory +//after it is done with the data only if this function succeeds +eHalStatus csrGetParsedBssDescriptionIEs(tHalHandle hHal, tSirBssDescription *pBssDesc, tDot11fBeaconIEs **ppIEStruct) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if(pBssDesc && ppIEStruct) + { + *ppIEStruct = vos_mem_malloc(sizeof(tDot11fBeaconIEs)); + if ( (*ppIEStruct) != NULL) + { + vos_mem_set((void *)*ppIEStruct, sizeof(tDot11fBeaconIEs), 0); + status = csrParseBssDescriptionIEs(hHal, pBssDesc, *ppIEStruct); + if(!HAL_STATUS_SUCCESS(status)) + { + vos_mem_free(*ppIEStruct); + *ppIEStruct = NULL; + } + } + else + { + smsLog( pMac, LOGE, FL(" failed to allocate memory") ); + VOS_ASSERT( 0 ); + return eHAL_STATUS_FAILURE; + } + } + + return (status); +} + + + + +tANI_BOOLEAN csrIsNULLSSID( tANI_U8 *pBssSsid, tANI_U8 len ) +{ + tANI_BOOLEAN fNullSsid = FALSE; + + tANI_U32 SsidLength; + tANI_U8 *pSsidStr; + + do + { + if ( 0 == len ) + { + fNullSsid = TRUE; + break; + } + + //Consider 0 or space for hidden SSID + if ( 0 == pBssSsid[0] ) + { + fNullSsid = TRUE; + break; + } + + SsidLength = len; + pSsidStr = pBssSsid; + + while ( SsidLength ) + { + if( *pSsidStr ) + break; + + pSsidStr++; + SsidLength--; + } + + if( 0 == SsidLength ) + { + fNullSsid = TRUE; + break; + } + } + while( 0 ); + + return fNullSsid; +} + + +tANI_U32 csrGetFragThresh( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return pMac->roam.configParam.FragmentationThreshold; +} + +tANI_U32 csrGetRTSThresh( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return pMac->roam.configParam.RTSThreshold; +} + +eCsrPhyMode csrTranslateToPhyModeFromBssDesc( tSirBssDescription *pSirBssDesc ) +{ + eCsrPhyMode phyMode; + + switch ( pSirBssDesc->nwType ) + { + case eSIR_11A_NW_TYPE: + phyMode = eCSR_DOT11_MODE_11a; + break; + + case eSIR_11B_NW_TYPE: + phyMode = eCSR_DOT11_MODE_11b; + break; + + case eSIR_11G_NW_TYPE: + phyMode = eCSR_DOT11_MODE_11g; + break; + + case eSIR_11N_NW_TYPE: + phyMode = eCSR_DOT11_MODE_11n; + break; +#ifdef WLAN_FEATURE_11AC + case eSIR_11AC_NW_TYPE: + default: + phyMode = eCSR_DOT11_MODE_11ac; +#else + default: + phyMode = eCSR_DOT11_MODE_11n; +#endif + break; + } + return( phyMode ); +} + + +tANI_U32 csrTranslateToWNICfgDot11Mode(tpAniSirGlobal pMac, eCsrCfgDot11Mode csrDot11Mode) +{ + tANI_U32 ret; + + switch(csrDot11Mode) + { + case eCSR_CFG_DOT11_MODE_AUTO: + smsLog(pMac, LOGW, FL(" Warning: sees eCSR_CFG_DOT11_MODE_AUTO ")); +#ifdef WLAN_FEATURE_11AC + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + ret = WNI_CFG_DOT11_MODE_11AC; + else + ret = WNI_CFG_DOT11_MODE_11N; +#else + //We cannot decide until now. + ret = WNI_CFG_DOT11_MODE_11N; +#endif + break; + case eCSR_CFG_DOT11_MODE_11A: + ret = WNI_CFG_DOT11_MODE_11A; + break; + case eCSR_CFG_DOT11_MODE_11B: + ret = WNI_CFG_DOT11_MODE_11B; + break; + case eCSR_CFG_DOT11_MODE_11G: + ret = WNI_CFG_DOT11_MODE_11G; + break; + case eCSR_CFG_DOT11_MODE_11N: + ret = WNI_CFG_DOT11_MODE_11N; + break; + case eCSR_CFG_DOT11_MODE_11G_ONLY: + ret = WNI_CFG_DOT11_MODE_11G_ONLY; + break; + case eCSR_CFG_DOT11_MODE_11N_ONLY: + ret = WNI_CFG_DOT11_MODE_11N_ONLY; + break; + +#ifdef WLAN_FEATURE_11AC + case eCSR_CFG_DOT11_MODE_11AC_ONLY: + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + ret = WNI_CFG_DOT11_MODE_11AC_ONLY; + else + ret = WNI_CFG_DOT11_MODE_11N; + break; + case eCSR_CFG_DOT11_MODE_11AC: + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + ret = WNI_CFG_DOT11_MODE_11AC; + else + ret = WNI_CFG_DOT11_MODE_11N; + break; +#endif + default: + smsLog(pMac, LOGW, FL("doesn't expect %d as csrDo11Mode"), csrDot11Mode); + if(eCSR_BAND_24 == pMac->roam.configParam.eBand) + { + ret = WNI_CFG_DOT11_MODE_11G; + } + else + { + ret = WNI_CFG_DOT11_MODE_11A; + } + break; + } + + return (ret); +} + + +//This function should only return the super set of supported modes. 11n implies 11b/g/a/n. +eHalStatus csrGetPhyModeFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBSSDescription, + eCsrPhyMode *pPhyMode, tDot11fBeaconIEs *pIes) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + eCsrPhyMode phyMode = csrTranslateToPhyModeFromBssDesc(pBSSDescription); + + if (pIes) { + if (pIes->HTCaps.present) { + phyMode = eCSR_DOT11_MODE_11n; +#ifdef WLAN_FEATURE_11AC + if (IS_BSS_VHT_CAPABLE(pIes->VHTCaps)) { + phyMode = eCSR_DOT11_MODE_11ac; + } +#endif + } + + *pPhyMode = phyMode; + } + + return (status); + +} + + +//This function returns the correct eCSR_CFG_DOT11_MODE is the two phyModes matches +//bssPhyMode is the mode derived from the BSS description +//f5GhzBand is derived from the channel id of BSS description +tANI_BOOLEAN csrGetPhyModeInUse( eCsrPhyMode phyModeIn, eCsrPhyMode bssPhyMode, tANI_BOOLEAN f5GhzBand, + eCsrCfgDot11Mode *pCfgDot11ModeToUse ) +{ + tANI_BOOLEAN fMatch = FALSE; + eCsrCfgDot11Mode cfgDot11Mode; + + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; // to suppress compiler warning + + switch( phyModeIn ) + { + case eCSR_DOT11_MODE_abg: //11a or 11b or 11g + if( f5GhzBand ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + } + else if( eCSR_DOT11_MODE_11b == bssPhyMode ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + } + else + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + } + break; + + case eCSR_DOT11_MODE_11a: //11a + if( f5GhzBand ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + } + break; + + case eCSR_DOT11_MODE_11g: + if(!f5GhzBand) + { + if( eCSR_DOT11_MODE_11b == bssPhyMode ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + } + else + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + } + } + break; + + case eCSR_DOT11_MODE_11g_ONLY: + if( eCSR_DOT11_MODE_11g == bssPhyMode ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + } + break; + + case eCSR_DOT11_MODE_11b: + if( !f5GhzBand ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + } + break; + + case eCSR_DOT11_MODE_11b_ONLY: + if( eCSR_DOT11_MODE_11b == bssPhyMode ) + { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + } + break; + + case eCSR_DOT11_MODE_11n: + fMatch = TRUE; + switch(bssPhyMode) + { + case eCSR_DOT11_MODE_11g: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + break; + case eCSR_DOT11_MODE_11b: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + break; + case eCSR_DOT11_MODE_11a: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + break; + case eCSR_DOT11_MODE_11n: +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: +#endif + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + break; + + default: +#ifdef WLAN_FEATURE_11AC + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; +#else + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; +#endif + break; + } + break; + + case eCSR_DOT11_MODE_11n_ONLY: + if ((eCSR_DOT11_MODE_11n == bssPhyMode)) { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: + fMatch = TRUE; + switch(bssPhyMode) + { + case eCSR_DOT11_MODE_11g: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + break; + case eCSR_DOT11_MODE_11b: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + break; + case eCSR_DOT11_MODE_11a: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + break; + case eCSR_DOT11_MODE_11n: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + break; + case eCSR_DOT11_MODE_11ac: + default: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; + break; + } + break; + + case eCSR_DOT11_MODE_11ac_ONLY: + if ((eCSR_DOT11_MODE_11ac == bssPhyMode)) { + fMatch = TRUE; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; + } + break; +#endif + + default: + fMatch = TRUE; + switch(bssPhyMode) + { + case eCSR_DOT11_MODE_11g: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + break; + case eCSR_DOT11_MODE_11b: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + break; + case eCSR_DOT11_MODE_11a: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + break; + case eCSR_DOT11_MODE_11n: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; + break; +#endif + default: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_AUTO; + break; + } + break; + } + + if ( fMatch && pCfgDot11ModeToUse ) + { +#ifdef WLAN_FEATURE_11AC + if(cfgDot11Mode == eCSR_CFG_DOT11_MODE_11AC && (!IS_FEATURE_SUPPORTED_BY_FW(DOT11AC))) + { + *pCfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11N; + } + else +#endif + { + *pCfgDot11ModeToUse = cfgDot11Mode; + } + } + return( fMatch ); +} + + +//This function decides whether the one of the bit of phyMode is matching the mode in the BSS and allowed by the user +//setting, pMac->roam.configParam.uCfgDot11Mode. It returns the mode that fits the criteria. +tANI_BOOLEAN csrIsPhyModeMatch( tpAniSirGlobal pMac, tANI_U32 phyMode, + tSirBssDescription *pSirBssDesc, tCsrRoamProfile *pProfile, + eCsrCfgDot11Mode *pReturnCfgDot11Mode, + tDot11fBeaconIEs *pIes) +{ + tANI_BOOLEAN fMatch = FALSE; + eCsrPhyMode phyModeInBssDesc = eCSR_DOT11_MODE_AUTO, phyMode2; + eCsrCfgDot11Mode cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_AUTO; + tANI_U32 bitMask, loopCount; + + if (HAL_STATUS_SUCCESS(csrGetPhyModeFromBss(pMac, pSirBssDesc, + &phyModeInBssDesc, pIes))) { + if ((0 == phyMode) || (eCSR_DOT11_MODE_AUTO & phyMode)) { + if (eCSR_CFG_DOT11_MODE_ABG == pMac->roam.configParam.uCfgDot11Mode) { + phyMode = eCSR_DOT11_MODE_abg; + } else if (eCSR_CFG_DOT11_MODE_AUTO == + pMac->roam.configParam.uCfgDot11Mode) { +#ifdef WLAN_FEATURE_11AC + phyMode = eCSR_DOT11_MODE_11ac; +#else + phyMode = eCSR_DOT11_MODE_11n; +#endif + } else { + //user's pick + phyMode = pMac->roam.configParam.phyMode; + } + } + + if ((0 == phyMode) || (eCSR_DOT11_MODE_AUTO & phyMode)) { + if (0 != phyMode) { + if (eCSR_DOT11_MODE_AUTO & phyMode) { + phyMode2 = eCSR_DOT11_MODE_AUTO & phyMode; + } + } else { + phyMode2 = phyMode; + } + fMatch = csrGetPhyModeInUse( phyMode2, phyModeInBssDesc, CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId), + &cfgDot11ModeToUse ); + } + else + { + bitMask = 1; + loopCount = 0; + while(loopCount < eCSR_NUM_PHY_MODE) + { + if(0 != ( phyMode2 = (phyMode & (bitMask << loopCount++)) )) + { + fMatch = csrGetPhyModeInUse( phyMode2, phyModeInBssDesc, CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId), + &cfgDot11ModeToUse ); + if(fMatch) break; + } + } + } + if ( fMatch && pReturnCfgDot11Mode ) + { + if( pProfile ) + { + /* IEEE 11n spec (8.4.3): HT STA shall eliminate TKIP as a + * choice for the pairwise cipher suite if CCMP is advertised + * by the AP or if the AP included an HT capabilities element + * in its Beacons and Probe Response. + */ + if ((!CSR_IS_11n_ALLOWED(pProfile->negotiatedUCEncryptionType)) && + ((eCSR_CFG_DOT11_MODE_11N == cfgDot11ModeToUse) || +#ifdef WLAN_FEATURE_11AC + (eCSR_CFG_DOT11_MODE_11AC == cfgDot11ModeToUse) +#endif + )) { + /* We cannot do 11n here */ + if (!CSR_IS_CHANNEL_5GHZ(pSirBssDesc->channelId)) { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11G; + } else { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11A; + } + } + } + *pReturnCfgDot11Mode = cfgDot11ModeToUse; + } + } + + return( fMatch ); +} + + +eCsrCfgDot11Mode csrFindBestPhyMode( tpAniSirGlobal pMac, tANI_U32 phyMode ) +{ + eCsrCfgDot11Mode cfgDot11ModeToUse; + eCsrBand eBand = pMac->roam.configParam.eBand; + + + if ((0 == phyMode) || +#ifdef WLAN_FEATURE_11AC + (eCSR_DOT11_MODE_11ac & phyMode) || +#endif + (eCSR_DOT11_MODE_AUTO & phyMode)) + { +#ifdef WLAN_FEATURE_11AC + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11AC; + } + else +#endif + { + /* Default to 11N mode if user has configured 11ac mode + * and FW doesn't supports 11ac mode . + */ + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11N; + } + } + else + { + if( ( eCSR_DOT11_MODE_11n | eCSR_DOT11_MODE_11n_ONLY ) & phyMode ) + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11N; + } + else if ( eCSR_DOT11_MODE_abg & phyMode ) + { + if( eCSR_BAND_24 != eBand ) + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11A; + } + else + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11G; + } + } + else if(eCSR_DOT11_MODE_11a & phyMode) + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11A; + } + else if( ( eCSR_DOT11_MODE_11g | eCSR_DOT11_MODE_11g_ONLY ) & phyMode ) + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11G; + } + else + { + cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_11B; + } + } + + return ( cfgDot11ModeToUse ); +} + + + + +tANI_U32 csrGet11hPowerConstraint( tHalHandle hHal, tDot11fIEPowerConstraints *pPowerConstraint ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U32 localPowerConstraint = 0; + + // check if .11h support is enabled, if not, the power constraint is 0. + if(pMac->roam.configParam.Is11hSupportEnabled && pPowerConstraint->present) + { + localPowerConstraint = pPowerConstraint->localPowerConstraints; + } + + return( localPowerConstraint ); +} + + +tANI_BOOLEAN csrIsProfileWpa( tCsrRoamProfile *pProfile ) +{ + tANI_BOOLEAN fWpaProfile = FALSE; + + switch ( pProfile->negotiatedAuthType ) + { + case eCSR_AUTH_TYPE_WPA: + case eCSR_AUTH_TYPE_WPA_PSK: + case eCSR_AUTH_TYPE_WPA_NONE: +#ifdef FEATURE_WLAN_ESE + case eCSR_AUTH_TYPE_CCKM_WPA: +#endif + fWpaProfile = TRUE; + break; + + default: + fWpaProfile = FALSE; + break; + } + + if ( fWpaProfile ) + { + switch ( pProfile->negotiatedUCEncryptionType ) + { + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_TKIP: + case eCSR_ENCRYPT_TYPE_AES: + fWpaProfile = TRUE; + break; + + default: + fWpaProfile = FALSE; + break; + } + } + return( fWpaProfile ); +} + +tANI_BOOLEAN csrIsProfileRSN( tCsrRoamProfile *pProfile ) +{ + tANI_BOOLEAN fRSNProfile = FALSE; + + switch ( pProfile->negotiatedAuthType ) + { + case eCSR_AUTH_TYPE_RSN: + case eCSR_AUTH_TYPE_RSN_PSK: +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: + case eCSR_AUTH_TYPE_FT_RSN_PSK: +#endif +#ifdef FEATURE_WLAN_ESE + case eCSR_AUTH_TYPE_CCKM_RSN: +#endif +#ifdef WLAN_FEATURE_11W + case eCSR_AUTH_TYPE_RSN_PSK_SHA256: + case eCSR_AUTH_TYPE_RSN_8021X_SHA256: +#endif + fRSNProfile = TRUE; + break; + + default: + fRSNProfile = FALSE; + break; + } + + if ( fRSNProfile ) + { + switch ( pProfile->negotiatedUCEncryptionType ) + { + // !!REVIEW - For WPA2, use of RSN IE mandates + // use of AES as encryption. Here, we qualify + // even if encryption type is WEP or TKIP + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_TKIP: + case eCSR_ENCRYPT_TYPE_AES: + fRSNProfile = TRUE; + break; + + default: + fRSNProfile = FALSE; + break; + } + } + return( fRSNProfile ); +} + +eHalStatus +csrIsconcurrentsessionValid(tpAniSirGlobal pMac,tANI_U32 cursessionId, + tVOS_CON_MODE currBssPersona) +{ + tANI_U32 sessionId = 0; + tANI_U8 automotive_support_enable = + (pMac->roam.configParam.conc_custom_rule1 | + pMac->roam.configParam.conc_custom_rule2); + tVOS_CON_MODE bss_persona; + eCsrConnectState connect_state; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + if (cursessionId != sessionId ) { + if (!CSR_IS_SESSION_VALID( pMac, sessionId )) { + continue; + } + bss_persona = + pMac->roam.roamSession[sessionId].bssParams.bssPersona; + connect_state = + pMac->roam.roamSession[sessionId].connectState; + + switch (currBssPersona) { + + case VOS_STA_MODE: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("** STA session **")); + return eHAL_STATUS_SUCCESS; + + case VOS_STA_SAP_MODE: +#ifndef WLAN_FEATURE_MBSSID + if ((bss_persona == VOS_STA_SAP_MODE) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("**SoftAP mode already exists **")); + return eHAL_STATUS_FAILURE; + } + else +#endif + if (((bss_persona == VOS_P2P_GO_MODE) && (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED) && + (0 == automotive_support_enable)) || + ((bss_persona == VOS_IBSS_MODE) && (connect_state != + eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED))) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Can't start multiple beaconing role")); + return eHAL_STATUS_FAILURE; + } + break; + + case VOS_P2P_GO_MODE: + if ((bss_persona == VOS_P2P_GO_MODE) && (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL(" ****P2P GO mode already exists ****")); + return eHAL_STATUS_FAILURE; + + } else if (((bss_persona == VOS_STA_SAP_MODE) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED) && + (0 == automotive_support_enable)) || + ((bss_persona == VOS_IBSS_MODE) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED))) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Can't start multiple beaconing role")); + return eHAL_STATUS_FAILURE; + } + break; + case VOS_IBSS_MODE: + if ((bss_persona == VOS_IBSS_MODE) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL(" ****IBSS mode already exists ****")); + return eHAL_STATUS_FAILURE; + } else if (((bss_persona == VOS_P2P_GO_MODE) || + (bss_persona == VOS_STA_SAP_MODE)) && + (connect_state + != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("**Cannot start Multiple Beaconing Role**")); + return eHAL_STATUS_FAILURE; + } + break; + case VOS_P2P_CLIENT_MODE: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("**P2P-Client session**")); + return eHAL_STATUS_SUCCESS; + default : + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("**Persona not handled = %d**"), + currBssPersona); + break; + } + } + } + return eHAL_STATUS_SUCCESS; + +} + +eHalStatus csrUpdateMCCp2pBeaconInterval(tpAniSirGlobal pMac) +{ + tANI_U32 sessionId = 0; + + //If MCC is not supported just break and return SUCCESS + if ( !pMac->roam.configParam.fenableMCCMode){ + return eHAL_STATUS_FAILURE; + } + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ ) + { + /* If GO in MCC support different beacon interval, + * change the BI of the P2P-GO */ + if (pMac->roam.roamSession[sessionId].bssParams.bssPersona + == VOS_P2P_GO_MODE) + { + /* Handle different BI scenario based on the configuration set. + * If Config is set to 0x02 then Disconnect all the P2P clients + * associated. If config is set to 0x04 then update the BI + * without disconnecting all the clients + */ + if ((pMac->roam.configParam.fAllowMCCGODiffBI == 0x04) && + (pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval)) + { + return csrSendChngMCCBeaconInterval( pMac, sessionId); + } + //If the configuration of fAllowMCCGODiffBI is set to other than 0x04 + else if ( pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval) + { + return csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, eCSR_ROAM_RESULT_NONE); + } + } + } + return eHAL_STATUS_FAILURE; +} + +tANI_U16 csrCalculateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U16 sta_bi, tANI_U16 go_gbi) +{ + tANI_U8 num_beacons = 0; + tANI_U8 is_multiple = 0; + tANI_U16 go_cbi = 0; + tANI_U16 go_fbi = 0; + tANI_U16 sta_cbi = 0; + + //If GO's given beacon Interval is less than 100 + if(go_gbi < 100) + go_cbi = 100; + //if GO's given beacon Interval is greater than or equal to 100 + else + go_cbi = 100 + (go_gbi % 100); + + if ( sta_bi == 0 ) + { + /* There is possibility to receive zero as value. + Which will cause divide by zero. Hence initialize with 100 + */ + sta_bi = 100; + smsLog(pMac, LOGW, + FL("sta_bi 2nd parameter is zero, initialize to %d"), sta_bi); + } + + // check, if either one is multiple of another + if (sta_bi > go_cbi) + { + is_multiple = !(sta_bi % go_cbi); + } + else + { + is_multiple = !(go_cbi % sta_bi); + } + // if it is multiple, then accept GO's beacon interval range [100,199] as it is + if (is_multiple) + { + return go_cbi; + } + //else , if it is not multiple, then then check for number of beacons to be + //inserted based on sta BI + num_beacons = sta_bi / 100; + if (num_beacons) + { + // GO's final beacon interval will be aligned to sta beacon interval, but + //in the range of [100, 199]. + sta_cbi = sta_bi / num_beacons; + go_fbi = sta_cbi; + } + else + { + // if STA beacon interval is less than 100, use GO's change bacon interval + //instead of updating to STA's beacon interval. + go_fbi = go_cbi; + } + return go_fbi; +} + +eHalStatus csrValidateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U8 channelId, + tANI_U16 *beaconInterval, tANI_U32 cursessionId, + tVOS_CON_MODE currBssPersona) +{ + tANI_U32 sessionId = 0; + tANI_U16 new_beaconInterval = 0; + + //If MCC is not supported just break + if (!pMac->roam.configParam.fenableMCCMode){ + return eHAL_STATUS_FAILURE; + } + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ ) + { + if (cursessionId != sessionId ) + { + if (!CSR_IS_SESSION_VALID( pMac, sessionId )) + { + continue; + } + + switch (currBssPersona) + { + case VOS_STA_MODE: + if (pMac->roam.roamSession[sessionId].pCurRoamProfile && + (pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona + == VOS_P2P_CLIENT_MODE)) //check for P2P client mode + { + smsLog(pMac, LOG1, FL(" Beacon Interval Validation not required for STA/CLIENT")); + } + //IF SAP has started and STA wants to connect on different channel MCC should + //MCC should not be enabled so making it false to enforce on same channel + else if (pMac->roam.roamSession[sessionId].bssParams.bssPersona + == VOS_STA_SAP_MODE) + { + if (pMac->roam.roamSession[sessionId].bssParams.operationChn + != channelId ) + { + smsLog(pMac, LOGE, FL("*** MCC with SAP+STA sessions ****")); + return eHAL_STATUS_SUCCESS; + } + } + else if (pMac->roam.roamSession[sessionId].bssParams.bssPersona + == VOS_P2P_GO_MODE) //Check for P2P go scenario + { + /* if GO in MCC support different beacon interval, + * change the BI of the P2P-GO */ + if ((pMac->roam.roamSession[sessionId].bssParams.operationChn + != channelId ) && + (pMac->roam.roamSession[sessionId].bssParams.beaconInterval + != *beaconInterval)) + { + /* if GO in MCC support different beacon interval, return success */ + if ( pMac->roam.configParam.fAllowMCCGODiffBI == 0x01) + { + return eHAL_STATUS_SUCCESS; + } + // Send only Broadcast disassoc and update beaconInterval + //If configuration is set to 0x04 then dont + // disconnect all the station + else if ((pMac->roam.configParam.fAllowMCCGODiffBI == 0x02) || + (pMac->roam.configParam.fAllowMCCGODiffBI == 0x04)) + { + //Check to pass the right beacon Interval + if (pMac->roam.configParam.conc_custom_rule1 || + pMac->roam.configParam.conc_custom_rule2) { + new_beaconInterval = CSR_CUSTOM_CONC_GO_BI; + } else { + new_beaconInterval = + csrCalculateMCCBeaconInterval(pMac, + *beaconInterval, + pMac->roam.roamSession[sessionId].bssParams.beaconInterval); + } + smsLog(pMac, LOG1, FL(" Peer AP BI : %d, new Beacon Interval: %d"),*beaconInterval,new_beaconInterval ); + //Update the becon Interval + if (new_beaconInterval != pMac->roam.roamSession[sessionId].bssParams.beaconInterval) + { + //Update the beaconInterval now + smsLog(pMac, LOGE, FL(" Beacon Interval got changed config used: %d\n"), + pMac->roam.configParam.fAllowMCCGODiffBI); + + pMac->roam.roamSession[sessionId].bssParams.beaconInterval = new_beaconInterval; + pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval = eANI_BOOLEAN_TRUE; + return csrUpdateMCCp2pBeaconInterval(pMac); + } + return eHAL_STATUS_SUCCESS; + } + //Disconnect the P2P session + else if (pMac->roam.configParam.fAllowMCCGODiffBI == 0x03) + { + pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval = eANI_BOOLEAN_FALSE; + return csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_SEND_P2P_STOP_BSS, eCSR_ROAM_RESULT_NONE); + } + else + { + smsLog(pMac, LOGE, FL("BeaconInterval is different cannot connect to preferred AP...")); + return eHAL_STATUS_FAILURE; + } + } + } + break; + + case VOS_P2P_CLIENT_MODE: + if (pMac->roam.roamSession[sessionId].pCurRoamProfile && + (pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona + == VOS_STA_MODE)) //check for P2P client mode + { + smsLog(pMac, LOG1, FL(" Ignore Beacon Interval Validation...")); + } + //IF SAP has started and STA wants to connect on different channel MCC should + //MCC should not be enabled so making it false to enforce on same channel + else if (pMac->roam.roamSession[sessionId].bssParams.bssPersona + == VOS_STA_SAP_MODE) + { + if (pMac->roam.roamSession[sessionId].bssParams.operationChn + != channelId ) + { + smsLog(pMac, LOGE, FL("***MCC is not enabled for SAP + CLIENT****")); + return eHAL_STATUS_FAILURE; + } + } + else if (pMac->roam.roamSession[sessionId].bssParams.bssPersona + == VOS_P2P_GO_MODE) //Check for P2P go scenario + { + if ((pMac->roam.roamSession[sessionId].bssParams.operationChn + != channelId ) && + (pMac->roam.roamSession[sessionId].bssParams.beaconInterval + != *beaconInterval)) + { + smsLog(pMac, LOGE, FL("BeaconInterval is different cannot connect to P2P_GO network ...")); + return eHAL_STATUS_FAILURE; + } + } + break; + + case VOS_STA_SAP_MODE : + break; + + case VOS_P2P_GO_MODE : + { + if (pMac->roam.roamSession[sessionId].pCurRoamProfile && + ((pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona + == VOS_P2P_CLIENT_MODE) || + (pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona + == VOS_STA_MODE))) //check for P2P_client scenario + { + if ((pMac->roam.roamSession[sessionId].connectedProfile.operationChannel + == 0 )&& + (pMac->roam.roamSession[sessionId].connectedProfile.beaconInterval + == 0)) + { + continue; + } + + + if (csrIsConnStateConnectedInfra(pMac, sessionId) && + (pMac->roam.roamSession[sessionId].connectedProfile.operationChannel + != channelId ) && + (pMac->roam.roamSession[sessionId].connectedProfile.beaconInterval + != *beaconInterval)) + { + /* + * Updated beaconInterval should be used only when + * we are starting a new BSS not in-case of client + * or STA case + */ + /* Calculate beacon Interval for P2P-GO + in-case of MCC */ + if (pMac->roam.configParam.conc_custom_rule1 || + pMac->roam.configParam.conc_custom_rule2) { + new_beaconInterval = CSR_CUSTOM_CONC_GO_BI; + } else { + new_beaconInterval = + csrCalculateMCCBeaconInterval(pMac, + pMac->roam.roamSession[sessionId].connectedProfile.beaconInterval, + *beaconInterval); + } + if(*beaconInterval != new_beaconInterval) + *beaconInterval = new_beaconInterval; + return eHAL_STATUS_SUCCESS; + } + } + } + break; + + default : + smsLog(pMac, LOGE, FL(" Persona not supported : %d"),currBssPersona); + return eHAL_STATUS_FAILURE; + } + } + } + + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* Function to return TRUE if the auth type is 11r */ +tANI_BOOLEAN csrIsAuthType11r( eCsrAuthType AuthType, tANI_U8 mdiePresent) +{ + switch ( AuthType ) + { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + if(mdiePresent) + return TRUE; + break; + case eCSR_AUTH_TYPE_FT_RSN_PSK: + case eCSR_AUTH_TYPE_FT_RSN: + return TRUE; + break; + default: + break; + } + return FALSE; +} + +/* Function to return TRUE if the profile is 11r */ +tANI_BOOLEAN csrIsProfile11r( tCsrRoamProfile *pProfile ) +{ + return csrIsAuthType11r( pProfile->negotiatedAuthType, pProfile->MDID.mdiePresent ); +} + +#endif + +#ifdef FEATURE_WLAN_ESE + +/* Function to return TRUE if the auth type is ESE */ +tANI_BOOLEAN csrIsAuthTypeESE( eCsrAuthType AuthType ) +{ + switch ( AuthType ) + { + case eCSR_AUTH_TYPE_CCKM_WPA: + case eCSR_AUTH_TYPE_CCKM_RSN: + return TRUE; + break; + default: + break; + } + return FALSE; +} + +/* Function to return TRUE if the profile is ESE */ +tANI_BOOLEAN csrIsProfileESE( tCsrRoamProfile *pProfile ) +{ + return (csrIsAuthTypeESE( pProfile->negotiatedAuthType )); +} + +#endif + +#ifdef FEATURE_WLAN_WAPI +tANI_BOOLEAN csrIsProfileWapi( tCsrRoamProfile *pProfile ) +{ + tANI_BOOLEAN fWapiProfile = FALSE; + + switch ( pProfile->negotiatedAuthType ) + { + case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE: + case eCSR_AUTH_TYPE_WAPI_WAI_PSK: + fWapiProfile = TRUE; + break; + + default: + fWapiProfile = FALSE; + break; + } + + if ( fWapiProfile ) + { + switch ( pProfile->negotiatedUCEncryptionType ) + { + case eCSR_ENCRYPT_TYPE_WPI: + fWapiProfile = TRUE; + break; + + default: + fWapiProfile = FALSE; + break; + } + } + return( fWapiProfile ); +} + +static tANI_BOOLEAN csrIsWapiOuiEqual( tpAniSirGlobal pMac, tANI_U8 *Oui1, tANI_U8 *Oui2 ) +{ + return (vos_mem_compare(Oui1, Oui2, CSR_WAPI_OUI_SIZE)); +} + +static tANI_BOOLEAN csrIsWapiOuiMatch( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WAPI_OUI_SIZE], + tANI_U8 cAllCyphers, + tANI_U8 Cypher[], + tANI_U8 Oui[] ) +{ + tANI_BOOLEAN fYes = FALSE; + tANI_U8 idx; + + for ( idx = 0; idx < cAllCyphers; idx++ ) + { + if ( csrIsWapiOuiEqual( pMac, AllCyphers[ idx ], Cypher ) ) + { + fYes = TRUE; + break; + } + } + + if ( fYes && Oui ) + { + vos_mem_copy(Oui, AllCyphers[ idx ], CSR_WAPI_OUI_SIZE); + } + + return( fYes ); +} +#endif /* FEATURE_WLAN_WAPI */ + +static tANI_BOOLEAN csrIsWpaOuiEqual( tpAniSirGlobal pMac, tANI_U8 *Oui1, tANI_U8 *Oui2 ) +{ + return(vos_mem_compare(Oui1, Oui2, CSR_WPA_OUI_SIZE)); +} + +static tANI_BOOLEAN csrIsOuiMatch( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WPA_OUI_SIZE], + tANI_U8 cAllCyphers, + tANI_U8 Cypher[], + tANI_U8 Oui[] ) +{ + tANI_BOOLEAN fYes = FALSE; + tANI_U8 idx; + + for ( idx = 0; idx < cAllCyphers; idx++ ) + { + if ( csrIsWpaOuiEqual( pMac, AllCyphers[ idx ], Cypher ) ) + { + fYes = TRUE; + break; + } + } + + if ( fYes && Oui ) + { + vos_mem_copy(Oui, AllCyphers[ idx ], CSR_WPA_OUI_SIZE); + } + + return( fYes ); +} + +static tANI_BOOLEAN csrMatchRSNOUIIndex( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllCyphers, tANI_U8 ouiIndex, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrRSNOui[ouiIndex], Oui ) ); + +} + +#ifdef FEATURE_WLAN_WAPI +static tANI_BOOLEAN csrMatchWapiOUIIndex( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_WAPI_OUI_SIZE], + tANI_U8 cAllCyphers, tANI_U8 ouiIndex, + tANI_U8 Oui[] ) +{ + return( csrIsWapiOuiMatch( pMac, AllCyphers, cAllCyphers, csrWapiOui[ouiIndex], Oui ) ); + +} +#endif /* FEATURE_WLAN_WAPI */ + +static tANI_BOOLEAN csrMatchWPAOUIIndex( tpAniSirGlobal pMac, tANI_U8 AllCyphers[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllCyphers, tANI_U8 ouiIndex, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllCyphers, cAllCyphers, csrWpaOui[ouiIndex], Oui ) ); + +} + +#ifdef FEATURE_WLAN_WAPI +static tANI_BOOLEAN csrIsAuthWapiCert( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WAPI_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsWapiOuiMatch( pMac, AllSuites, cAllSuites, csrWapiOui[1], Oui ) ); +} +static tANI_BOOLEAN csrIsAuthWapiPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WAPI_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsWapiOuiMatch( pMac, AllSuites, cAllSuites, csrWapiOui[2], Oui ) ); +} +#endif /* FEATURE_WLAN_WAPI */ + +#ifdef WLAN_FEATURE_VOWIFI_11R + +/* + * Function for 11R FT Authentication. We match the FT Authentication Cipher suite + * here. This matches for FT Auth with the 802.1X exchange. + * + */ +static tANI_BOOLEAN csrIsFTAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[03], Oui ) ); +} + +/* + * Function for 11R FT Authentication. We match the FT Authentication Cipher suite + * here. This matches for FT Auth with the PSK. + * + */ +static tANI_BOOLEAN csrIsFTAuthRSNPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[04], Oui ) ); +} + +#endif + +#ifdef FEATURE_WLAN_ESE + +/* + * Function for ESE CCKM AKM Authentication. We match the CCKM AKM Authentication Key Management suite + * here. This matches for CCKM AKM Auth with the 802.1X exchange. + * + */ +static tANI_BOOLEAN csrIsEseCckmAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ) ); +} + +static tANI_BOOLEAN csrIsEseCckmAuthWpa( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[06], Oui ) ); +} + +#endif + +static tANI_BOOLEAN csrIsAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) ); +} +static tANI_BOOLEAN csrIsAuthRSNPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) ); +} + +#ifdef WLAN_FEATURE_11W +static tANI_BOOLEAN csrIsAuthRSNPskSha256( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[07], Oui ); +} +static tANI_BOOLEAN csrIsAuthRSN8021xSha256(tpAniSirGlobal pMac, + tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[8], Oui ); +} +#endif + +static tANI_BOOLEAN csrIsAuthWpa( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[01], Oui ) ); +} + +static tANI_BOOLEAN csrIsAuthWpaPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_WPA_OUI_SIZE], + tANI_U8 cAllSuites, + tANI_U8 Oui[] ) +{ + return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrWpaOui[02], Oui ) ); +} + +tANI_U8 csrGetOUIIndexFromCipher( eCsrEncryptionType enType ) +{ + tANI_U8 OUIIndex; + + switch ( enType ) + { + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + OUIIndex = CSR_OUI_WEP40_OR_1X_INDEX; + break; + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + OUIIndex = CSR_OUI_WEP104_INDEX; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + OUIIndex = CSR_OUI_TKIP_OR_PSK_INDEX; + break; + case eCSR_ENCRYPT_TYPE_AES: + OUIIndex = CSR_OUI_AES_INDEX; + break; + case eCSR_ENCRYPT_TYPE_NONE: + OUIIndex = CSR_OUI_USE_GROUP_CIPHER_INDEX; + break; +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + OUIIndex = CSR_OUI_WAPI_WAI_CERT_OR_SMS4_INDEX; + break; +#endif /* FEATURE_WLAN_WAPI */ + default: //HOWTO handle this? + OUIIndex = CSR_OUI_RESERVED_INDEX; + break; + }//switch + + return OUIIndex; +} + +tANI_BOOLEAN csrGetRSNInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pMCEncryption, + tDot11fIERSN *pRSNIe, + tANI_U8 *UnicastCypher, + tANI_U8 *MulticastCypher, + tANI_U8 *AuthSuite, + tCsrRSNCapabilities *Capabilities, + eCsrAuthType *pNegotiatedAuthtype, + eCsrEncryptionType *pNegotiatedMCCipher ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fAcceptableCyphers = FALSE; + tANI_U8 cUnicastCyphers = 0; + tANI_U8 cMulticastCyphers = 0; + tANI_U8 cAuthSuites = 0, i; + tANI_U8 Unicast[ CSR_RSN_OUI_SIZE ]; + tANI_U8 Multicast[ CSR_RSN_OUI_SIZE ]; + tANI_U8 AuthSuites[ CSR_RSN_MAX_AUTH_SUITES ][ CSR_RSN_OUI_SIZE ]; + tANI_U8 Authentication[ CSR_RSN_OUI_SIZE ]; + tANI_U8 MulticastCyphers[ CSR_RSN_MAX_MULTICAST_CYPHERS ][ CSR_RSN_OUI_SIZE ]; + eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + + do{ + if ( pRSNIe->present ) + { + cMulticastCyphers++; + vos_mem_copy(MulticastCyphers, pRSNIe->gp_cipher_suite, CSR_RSN_OUI_SIZE); + cUnicastCyphers = (tANI_U8)(pRSNIe->pwise_cipher_suite_count); + cAuthSuites = (tANI_U8)(pRSNIe->akm_suite_count); + for(i = 0; i < cAuthSuites && i < CSR_RSN_MAX_AUTH_SUITES; i++) + { + vos_mem_copy((void *)&AuthSuites[i], + (void *)&pRSNIe->akm_suites[i], + CSR_RSN_OUI_SIZE); + } + + //Check - Is requested Unicast Cipher supported by the BSS. + fAcceptableCyphers = csrMatchRSNOUIIndex( pMac, pRSNIe->pwise_cipher_suites, cUnicastCyphers, + csrGetOUIIndexFromCipher( enType ), Unicast ); + + if( !fAcceptableCyphers ) break; + + + //Unicast is supported. Pick the first matching Group cipher, if any. + for( i = 0 ; i < pMCEncryption->numEntries ; i++ ) + { + fAcceptableCyphers = csrMatchRSNOUIIndex( pMac, MulticastCyphers, cMulticastCyphers, + csrGetOUIIndexFromCipher( pMCEncryption->encryptionType[i] ), Multicast ); + if(fAcceptableCyphers) + { + break; + } + } + if( !fAcceptableCyphers ) break; + + if( pNegotiatedMCCipher ) + *pNegotiatedMCCipher = pMCEncryption->encryptionType[i]; + + /* Initializing with FALSE as it has TRUE value already */ + fAcceptableCyphers = FALSE; + for (i = 0 ; i < pAuthType->numEntries; i++) + { + //Ciphers are supported, Match authentication algorithm and pick first matching authtype. + #ifdef WLAN_FEATURE_VOWIFI_11R + /* Changed the AKM suites according to order of preference */ + if ( csrIsFTAuthRSN( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_FT_RSN == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_FT_RSN; + } + if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsFTAuthRSNPsk( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_FT_RSN_PSK == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_FT_RSN_PSK; + } +#endif +#ifdef FEATURE_WLAN_ESE + /* ESE only supports 802.1X. No PSK. */ + if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsEseCckmAuthRSN( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_CCKM_RSN == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_CCKM_RSN; + } +#endif + if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSN( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_RSN == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_RSN; + } + if ((negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSNPsk( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_RSN_PSK == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_RSN_PSK; + } +#ifdef WLAN_FEATURE_11W + if ((negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSNPskSha256( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_RSN_PSK_SHA256; + } + if ((negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && + csrIsAuthRSN8021xSha256(pMac, AuthSuites, + cAuthSuites, Authentication)) { + if (eCSR_AUTH_TYPE_RSN_8021X_SHA256 == + pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_RSN_8021X_SHA256; + } +#endif + + // The 1st auth type in the APs RSN IE, to match stations connecting + // profiles auth type will cause us to exit this loop + // This is added as some APs advertise multiple akms in the RSN IE. + if (eCSR_AUTH_TYPE_UNKNOWN != negAuthType) + { + fAcceptableCyphers = TRUE; + break; + } + } // for + } + + }while (0); + + if ( fAcceptableCyphers ) + { + if ( MulticastCypher ) + { + vos_mem_copy(MulticastCypher, Multicast, CSR_RSN_OUI_SIZE); + } + + if ( UnicastCypher ) + { + vos_mem_copy(UnicastCypher, Unicast, CSR_RSN_OUI_SIZE); + } + + if ( AuthSuite ) + { + vos_mem_copy(AuthSuite, Authentication, CSR_RSN_OUI_SIZE); + } + + if ( pNegotiatedAuthtype ) + { + *pNegotiatedAuthtype = negAuthType; + } + if ( Capabilities ) + { + Capabilities->PreAuthSupported = (pRSNIe->RSN_Cap[0] >> 0) & 0x1 ; // Bit 0 PreAuthentication + Capabilities->NoPairwise = (pRSNIe->RSN_Cap[0] >> 1) & 0x1 ; // Bit 1 No Pairwise + Capabilities->PTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 2) & 0x3 ; // Bit 2, 3 PTKSA Replay Counter + Capabilities->GTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 4) & 0x3 ; // Bit 4, 5 GTKSA Replay Counter +#ifdef WLAN_FEATURE_11W + Capabilities->MFPRequired = (pRSNIe->RSN_Cap[0] >> 6) & 0x1 ; // Bit 6 MFPR + Capabilities->MFPCapable = (pRSNIe->RSN_Cap[0] >> 7) & 0x1 ; // Bit 7 MFPC +#else + Capabilities->MFPRequired = 0 ; // Bit 6 MFPR + Capabilities->MFPCapable = 0 ; // Bit 7 MFPC +#endif + Capabilities->Reserved = pRSNIe->RSN_Cap[1] & 0xff ; // remaining reserved + } + } + return( fAcceptableCyphers ); +} + +#ifdef WLAN_FEATURE_11W +/* --------------------------------------------------------------------------- + \fn csrIsPMFCapabilitiesInRSNMatch + + \brief this function is to match our current capabilities with the AP + to which we are expecting make the connection. + + \param hHal - HAL Pointer + pFilterMFPEnabled - given by supplicant to us to specify what kind + of connection supplicant is expecting to make + if it is enabled then make PMF connection. + if it is disabled then make normal connection. + pFilterMFPRequired - given by supplicant based on our configuration + if it is 1 then we will require mandatory + PMF connection and if it is 0 then we PMF + connection is optional. + pFilterMFPCapable - given by supplicant based on our configuration + if it 1 then we are PMF capable and if it 0 + then we are not PMF capable. + pRSNIe - RSNIe from Beacon/probe response of + neighbor AP against which we will compare + our capabilities. + + \return tANI_BOOLEAN - if our PMF capabilities matches with AP then we + will return true to indicate that we are good + to make connection with it. Else we will return + false. + -------------------------------------------------------------------------------*/ +static tANI_BOOLEAN +csrIsPMFCapabilitiesInRSNMatch( tHalHandle hHal, + tANI_BOOLEAN *pFilterMFPEnabled, + tANI_U8 *pFilterMFPRequired, + tANI_U8 *pFilterMFPCapable, + tDot11fIERSN *pRSNIe) +{ + tANI_U8 apProfileMFPCapable = 0; + tANI_U8 apProfileMFPRequired = 0; + if (pRSNIe && pFilterMFPEnabled && pFilterMFPCapable && pFilterMFPRequired) + { + /* Extracting MFPCapable bit from RSN Ie */ + apProfileMFPCapable = (pRSNIe->RSN_Cap[0] >> 7) & 0x1; + apProfileMFPRequired = (pRSNIe->RSN_Cap[0] >> 6) & 0x1; + if (*pFilterMFPEnabled && *pFilterMFPCapable && *pFilterMFPRequired + && (apProfileMFPCapable == 0)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "AP is not capable to make PMF connection"); + return VOS_FALSE; + } + else if (*pFilterMFPEnabled && *pFilterMFPCapable && + !(*pFilterMFPRequired) && (apProfileMFPCapable == 0)) + { + /* + * This is tricky, because supplicant asked us to make mandatory + * PMF connection even though PMF connection is optional here. + * so if AP is not capable of PMF then drop it. Don't try to + * connect with it. + */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "we need PMF connection & AP isn't capable to make PMF connection"); + return VOS_FALSE; + } + else if (!(*pFilterMFPCapable) && + apProfileMFPCapable && apProfileMFPRequired) + { + + /* + * In this case, AP with whom we trying to connect requires + * mandatory PMF connections and we are not capable so this AP + * is not good choice to connect + */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "AP needs PMF connection and we are not capable of pmf connection"); + return VOS_FALSE; + } + else if (!(*pFilterMFPEnabled) && *pFilterMFPCapable && + (apProfileMFPCapable == 1)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "we don't need PMF connection even though both parties are capable"); + return VOS_FALSE; + } + } + return VOS_TRUE; +} +#endif + +tANI_BOOLEAN csrIsRSNMatch( tHalHandle hHal, tCsrAuthList *pAuthType, + eCsrEncryptionType enType, + tCsrEncryptionList *pEnMcType, + tANI_BOOLEAN *pMFPEnabled, tANI_U8 *pMFPRequired, + tANI_U8 *pMFPCapable, + tDot11fBeaconIEs *pIes, + eCsrAuthType *pNegotiatedAuthType, + eCsrEncryptionType *pNegotiatedMCCipher ) +{ + tANI_BOOLEAN fRSNMatch = FALSE; + + // See if the cyphers in the Bss description match with the settings in the profile. + fRSNMatch = csrGetRSNInformation( hHal, pAuthType, enType, pEnMcType, &pIes->RSN, NULL, NULL, NULL, NULL, + pNegotiatedAuthType, pNegotiatedMCCipher ); +#ifdef WLAN_FEATURE_11W + /* If all the filter matches then finally checks for PMF capabilities */ + if (fRSNMatch) + { + fRSNMatch = csrIsPMFCapabilitiesInRSNMatch( hHal, pMFPEnabled, + pMFPRequired, pMFPCapable, + &pIes->RSN); + } +#endif + return( fRSNMatch ); +} + + +tANI_BOOLEAN csrLookupPMKID( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U8 *pBSSId, tANI_U8 *pPMKId ) +{ + tANI_BOOLEAN fRC = FALSE, fMatchFound = FALSE; + tANI_U32 Index; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return FALSE; + } + + do + { + for (Index = 0; Index < CSR_MAX_PMKID_ALLOWED; Index++) + { + smsLog(pMac, LOG1, "match PMKID "MAC_ADDRESS_STR " to ", + MAC_ADDR_ARRAY(pBSSId)); + if( vos_mem_compare(pBSSId, pSession->PmkidCacheInfo[Index].BSSID, sizeof(tCsrBssid)) ) + { + // match found + fMatchFound = TRUE; + break; + } + } + + if( !fMatchFound ) break; + + vos_mem_copy(pPMKId, pSession->PmkidCacheInfo[Index].PMKID, CSR_RSN_PMKID_SIZE); + + fRC = TRUE; + } + while( 0 ); + smsLog(pMac, LOGW, "csrLookupPMKID called return match = %d pMac->roam.NumPmkidCache = %d", + fRC, pSession->NumPmkidCache); + + return fRC; +} + + +tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrRSNIe *pRSNIe ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fRSNMatch; + tANI_U8 cbRSNIe = 0; + tANI_U8 UnicastCypher[ CSR_RSN_OUI_SIZE ]; + tANI_U8 MulticastCypher[ CSR_RSN_OUI_SIZE ]; + tANI_U8 AuthSuite[ CSR_RSN_OUI_SIZE ]; + tCsrRSNAuthIe *pAuthSuite; + tCsrRSNCapabilities RSNCapabilities; + tCsrRSNPMKIe *pPMK; + tANI_U8 PMKId[CSR_RSN_PMKID_SIZE]; +#ifdef WLAN_FEATURE_11W + tANI_U8 *pGroupMgmtCipherSuite; +#endif + tDot11fBeaconIEs *pIesLocal = pIes; + eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + + smsLog(pMac, LOGW, "%s called...", __func__); + + do + { + if ( !csrIsProfileRSN( pProfile ) ) break; + + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) ) + { + break; + } + + // See if the cyphers in the Bss description match with the settings in the profile. + fRSNMatch = csrGetRSNInformation( hHal, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType, + &pProfile->mcEncryptionType, &pIesLocal->RSN, + UnicastCypher, MulticastCypher, AuthSuite, &RSNCapabilities, &negAuthType, NULL ); + if ( !fRSNMatch ) break; + + pRSNIe->IeHeader.ElementID = SIR_MAC_RSN_EID; + + pRSNIe->Version = CSR_RSN_VERSION_SUPPORTED; + + vos_mem_copy(pRSNIe->MulticastOui, MulticastCypher, sizeof( MulticastCypher )); + + pRSNIe->cUnicastCyphers = 1; + + vos_mem_copy(&pRSNIe->UnicastOui[ 0 ], UnicastCypher, sizeof( UnicastCypher )); + + pAuthSuite = (tCsrRSNAuthIe *)( &pRSNIe->UnicastOui[ pRSNIe->cUnicastCyphers ] ); + + pAuthSuite->cAuthenticationSuites = 1; + vos_mem_copy(&pAuthSuite->AuthOui[ 0 ], AuthSuite, sizeof( AuthSuite )); + + /* + * RSN capabilities follows the Auth Suite (two octets) + * !!REVIEW - What should STA put in RSN capabilities, currently + * just putting back APs capabilities For one, we shouldn't EVER be + * sending out "pre-auth supported". It is an AP only capability. + * For another, we should use the Management Frame Protection + * values given by the supplicant + */ + RSNCapabilities.PreAuthSupported = 0; +#ifdef WLAN_FEATURE_11W + if (RSNCapabilities.MFPCapable && pProfile->MFPCapable) { + RSNCapabilities.MFPCapable = pProfile->MFPCapable; + RSNCapabilities.MFPRequired = pProfile->MFPRequired; + } + else { + RSNCapabilities.MFPCapable = 0; + RSNCapabilities.MFPRequired = 0; + } +#endif + *(tANI_U16 *)( &pAuthSuite->AuthOui[ 1 ] ) = *((tANI_U16 *)(&RSNCapabilities)); + + pPMK = (tCsrRSNPMKIe *)( ((tANI_U8 *)(&pAuthSuite->AuthOui[ 1 ])) + sizeof(tANI_U16) ); + + // Don't include the PMK SA IDs for CCKM associations. + if ( +#ifdef FEATURE_WLAN_ESE + (eCSR_AUTH_TYPE_CCKM_RSN != negAuthType) && +#endif + csrLookupPMKID( pMac, sessionId, pSirBssDesc->bssId, &(PMKId[0]))) + { + pPMK->cPMKIDs = 1; + + vos_mem_copy(pPMK->PMKIDList[0].PMKID, PMKId, CSR_RSN_PMKID_SIZE); + } + else + { + pPMK->cPMKIDs = 0; + } + +#ifdef WLAN_FEATURE_11W + if ( pProfile->MFPEnabled ) + { + pGroupMgmtCipherSuite = (tANI_U8 *) pPMK + sizeof ( tANI_U16 ) + + ( pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE ); + vos_mem_copy(pGroupMgmtCipherSuite, csrRSNOui[07], CSR_WPA_OUI_SIZE); + } +#endif + + // Add in the fixed fields plus 1 Unicast cypher, less the IE Header length + // Add in the size of the Auth suite (count plus a single OUI) + // Add in the RSN caps field. + // Add PMKID count and PMKID (if any) + // Add group management cipher suite + pRSNIe->IeHeader.Length = (tANI_U8) (sizeof( *pRSNIe ) - sizeof ( pRSNIe->IeHeader ) + + sizeof( *pAuthSuite ) + + sizeof( tCsrRSNCapabilities )); + if(pPMK->cPMKIDs) + { + pRSNIe->IeHeader.Length += (tANI_U8)(sizeof( tANI_U16 ) + + (pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE)); + } +#ifdef WLAN_FEATURE_11W + if ( pProfile->MFPEnabled ) + { + if ( 0 == pPMK->cPMKIDs ) + pRSNIe->IeHeader.Length += sizeof( tANI_U16 ); + pRSNIe->IeHeader.Length += CSR_WPA_OUI_SIZE; + } +#endif + + // return the size of the IE header (total) constructed... + cbRSNIe = pRSNIe->IeHeader.Length + sizeof( pRSNIe->IeHeader ); + + } while( 0 ); + + if( !pIes && pIesLocal ) + { + //locally allocated + vos_mem_free(pIesLocal); + } + + return( cbRSNIe ); +} + + +#ifdef FEATURE_WLAN_WAPI +tANI_BOOLEAN csrGetWapiInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pMCEncryption, + tDot11fIEWAPI *pWapiIe, + tANI_U8 *UnicastCypher, + tANI_U8 *MulticastCypher, + tANI_U8 *AuthSuite, + eCsrAuthType *pNegotiatedAuthtype, + eCsrEncryptionType *pNegotiatedMCCipher ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fAcceptableCyphers = FALSE; + tANI_U8 cUnicastCyphers = 0; + tANI_U8 cMulticastCyphers = 0; + tANI_U8 cAuthSuites = 0, i; + tANI_U8 Unicast[ CSR_WAPI_OUI_SIZE ]; + tANI_U8 Multicast[ CSR_WAPI_OUI_SIZE ]; + tANI_U8 AuthSuites[ CSR_WAPI_MAX_AUTH_SUITES ][ CSR_WAPI_OUI_SIZE ]; + tANI_U8 Authentication[ CSR_WAPI_OUI_SIZE ]; + tANI_U8 MulticastCyphers[ CSR_WAPI_MAX_MULTICAST_CYPHERS ][ CSR_WAPI_OUI_SIZE ]; + eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + tANI_U8 wapiOuiIndex = 0; + do{ + if ( pWapiIe->present ) + { + cMulticastCyphers++; + vos_mem_copy(MulticastCyphers, pWapiIe->multicast_cipher_suite, + CSR_WAPI_OUI_SIZE); + cUnicastCyphers = (tANI_U8)(pWapiIe->unicast_cipher_suite_count); + cAuthSuites = (tANI_U8)(pWapiIe->akm_suite_count); + for(i = 0; i < cAuthSuites && i < CSR_WAPI_MAX_AUTH_SUITES; i++) + { + vos_mem_copy((void *)&AuthSuites[i], (void *)&pWapiIe->akm_suites[i], + CSR_WAPI_OUI_SIZE); + } + + wapiOuiIndex = csrGetOUIIndexFromCipher( enType ); + if (wapiOuiIndex >= CSR_OUI_WAPI_WAI_MAX_INDEX) + { + smsLog(pMac, LOGE, FL("Wapi OUI index = %d out of limit"), wapiOuiIndex); + fAcceptableCyphers = FALSE; + break; + } + //Check - Is requested Unicast Cipher supported by the BSS. + fAcceptableCyphers = csrMatchWapiOUIIndex( pMac, pWapiIe->unicast_cipher_suites, cUnicastCyphers, + wapiOuiIndex, Unicast ); + + if( !fAcceptableCyphers ) break; + + //Unicast is supported. Pick the first matching Group cipher, if any. + for( i = 0 ; i < pMCEncryption->numEntries ; i++ ) + { + wapiOuiIndex = csrGetOUIIndexFromCipher( pMCEncryption->encryptionType[i] ); + if (wapiOuiIndex >= CSR_OUI_WAPI_WAI_MAX_INDEX) + { + smsLog(pMac, LOGE, FL("Wapi OUI index = %d out of limit"), wapiOuiIndex); + fAcceptableCyphers = FALSE; + break; + } + fAcceptableCyphers = csrMatchWapiOUIIndex( pMac, MulticastCyphers, cMulticastCyphers, + wapiOuiIndex, Multicast ); + if(fAcceptableCyphers) + { + break; + } + } + if( !fAcceptableCyphers ) break; + + if( pNegotiatedMCCipher ) + *pNegotiatedMCCipher = pMCEncryption->encryptionType[i]; + + /* Ciphers are supported, Match authentication algorithm and pick + first matching auth type. */ + if ( csrIsAuthWapiCert( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + negAuthType = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE; + } + else if ( csrIsAuthWapiPsk( pMac, AuthSuites, cAuthSuites, Authentication ) ) + { + negAuthType = eCSR_AUTH_TYPE_WAPI_WAI_PSK; + } + else + { + fAcceptableCyphers = FALSE; + negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + } + if( ( 0 == pAuthType->numEntries ) || ( FALSE == fAcceptableCyphers ) ) + { + //Caller doesn't care about auth type, or BSS doesn't match + break; + } + fAcceptableCyphers = FALSE; + for( i = 0 ; i < pAuthType->numEntries; i++ ) + { + if( pAuthType->authType[i] == negAuthType ) + { + fAcceptableCyphers = TRUE; + break; + } + } + } + }while (0); + + if ( fAcceptableCyphers ) + { + if ( MulticastCypher ) + { + vos_mem_copy(MulticastCypher, Multicast, CSR_WAPI_OUI_SIZE); + } + + if ( UnicastCypher ) + { + vos_mem_copy(UnicastCypher, Unicast, CSR_WAPI_OUI_SIZE); + } + + if ( AuthSuite ) + { + vos_mem_copy(AuthSuite, Authentication, CSR_WAPI_OUI_SIZE); + } + + if ( pNegotiatedAuthtype ) + { + *pNegotiatedAuthtype = negAuthType; + } + } + return( fAcceptableCyphers ); +} + +tANI_BOOLEAN csrIsWapiMatch( tHalHandle hHal, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pEnMcType, + tDot11fBeaconIEs *pIes, eCsrAuthType *pNegotiatedAuthType, eCsrEncryptionType *pNegotiatedMCCipher ) +{ + tANI_BOOLEAN fWapiMatch = FALSE; + + // See if the cyphers in the Bss description match with the settings in the profile. + fWapiMatch = csrGetWapiInformation( hHal, pAuthType, enType, pEnMcType, &pIes->WAPI, NULL, NULL, NULL, + pNegotiatedAuthType, pNegotiatedMCCipher ); + + return( fWapiMatch ); +} + +tANI_BOOLEAN csrLookupBKID( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U8 *pBSSId, tANI_U8 *pBKId ) +{ + tANI_BOOLEAN fRC = FALSE, fMatchFound = FALSE; + tANI_U32 Index; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return FALSE; + } + + do + { + for( Index=0; Index < pSession->NumBkidCache; Index++ ) + { + smsLog(pMac, LOGW, "match BKID "MAC_ADDRESS_STR" to ", + MAC_ADDR_ARRAY(pBSSId)); + if (vos_mem_compare(pBSSId, pSession->BkidCacheInfo[Index].BSSID, sizeof(tCsrBssid) ) ) + { + // match found + fMatchFound = TRUE; + break; + } + } + + if( !fMatchFound ) break; + + vos_mem_copy(pBKId, pSession->BkidCacheInfo[Index].BKID, CSR_WAPI_BKID_SIZE); + + fRC = TRUE; + } + while( 0 ); + smsLog(pMac, LOGW, "csrLookupBKID called return match = %d pMac->roam.NumBkidCache = %d", fRC, pSession->NumBkidCache); + + return fRC; +} + +tANI_U8 csrConstructWapiIe( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe ) +{ + tANI_BOOLEAN fWapiMatch = FALSE; + tANI_U8 cbWapiIe = 0; + tANI_U8 UnicastCypher[ CSR_WAPI_OUI_SIZE ]; + tANI_U8 MulticastCypher[ CSR_WAPI_OUI_SIZE ]; + tANI_U8 AuthSuite[ CSR_WAPI_OUI_SIZE ]; + tANI_U8 BKId[CSR_WAPI_BKID_SIZE]; + tANI_U8 *pWapi = NULL; + tANI_BOOLEAN fBKIDFound = FALSE; + tDot11fBeaconIEs *pIesLocal = pIes; + + do + { + if ( !csrIsProfileWapi( pProfile ) ) break; + + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) ) + { + break; + } + + // See if the cyphers in the Bss description match with the settings in the profile. + fWapiMatch = csrGetWapiInformation( pMac, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType, + &pProfile->mcEncryptionType, &pIesLocal->WAPI, + UnicastCypher, MulticastCypher, AuthSuite, NULL, NULL ); + if ( !fWapiMatch ) break; + + vos_mem_set(pWapiIe, sizeof(tCsrWapiIe), 0); + + pWapiIe->IeHeader.ElementID = DOT11F_EID_WAPI; + + pWapiIe->Version = CSR_WAPI_VERSION_SUPPORTED; + + pWapiIe->cAuthenticationSuites = 1; + vos_mem_copy(&pWapiIe->AuthOui[ 0 ], AuthSuite, sizeof( AuthSuite )); + + pWapi = (tANI_U8 *) (&pWapiIe->AuthOui[ 1 ]); + + *pWapi = (tANI_U16)1; //cUnicastCyphers + pWapi+=2; + vos_mem_copy(pWapi, UnicastCypher, sizeof( UnicastCypher )); + pWapi += sizeof( UnicastCypher ); + + vos_mem_copy(pWapi, MulticastCypher, sizeof( MulticastCypher )); + pWapi += sizeof( MulticastCypher ); + + + /* + * WAPI capabilities follows the Auth Suite (two octets) + * we shouldn't EVER be sending out "pre-auth supported". + * It is an AP only capability & since we already did a memset + * pWapiIe to 0, skip these fields + */ + pWapi +=2; + + fBKIDFound = csrLookupBKID( pMac, sessionId, pSirBssDesc->bssId, &(BKId[0]) ); + + + if( fBKIDFound ) + { + /* Do we need to change the endianness here */ + *pWapi = (tANI_U16)1; //cBKIDs + pWapi+=2; + vos_mem_copy(pWapi, BKId, CSR_WAPI_BKID_SIZE); + } + else + { + *pWapi = 0; + pWapi+=1; + *pWapi = 0; + pWapi+=1; + } + + // Add in the IE fields except the IE header + // Add BKID count and BKID (if any) + pWapiIe->IeHeader.Length = (tANI_U8) (sizeof( *pWapiIe ) - sizeof ( pWapiIe->IeHeader )); + + /*2 bytes for BKID Count field*/ + pWapiIe->IeHeader.Length += sizeof( tANI_U16 ); + + if(fBKIDFound) + { + pWapiIe->IeHeader.Length += CSR_WAPI_BKID_SIZE; + } + // return the size of the IE header (total) constructed... + cbWapiIe = pWapiIe->IeHeader.Length + sizeof( pWapiIe->IeHeader ); + + } while( 0 ); + + if( !pIes && pIesLocal ) + { + //locally allocated + vos_mem_free(pIesLocal); + } + + return( cbWapiIe ); +} +#endif /* FEATURE_WLAN_WAPI */ + +tANI_BOOLEAN csrGetWpaCyphers( tpAniSirGlobal pMac, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pMCEncryption, + tDot11fIEWPA *pWpaIe, + tANI_U8 *UnicastCypher, + tANI_U8 *MulticastCypher, + tANI_U8 *AuthSuite, + eCsrAuthType *pNegotiatedAuthtype, + eCsrEncryptionType *pNegotiatedMCCipher ) +{ + tANI_BOOLEAN fAcceptableCyphers = FALSE; + tANI_U8 cUnicastCyphers = 0; + tANI_U8 cMulticastCyphers = 0; + tANI_U8 cAuthSuites = 0; + tANI_U8 Unicast[ CSR_WPA_OUI_SIZE ]; + tANI_U8 Multicast[ CSR_WPA_OUI_SIZE ]; + tANI_U8 Authentication[ CSR_WPA_OUI_SIZE ]; + tANI_U8 MulticastCyphers[ 1 ][ CSR_WPA_OUI_SIZE ]; + tANI_U8 i; + eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + + do + { + if ( pWpaIe->present ) + { + cMulticastCyphers = 1; + vos_mem_copy(MulticastCyphers, pWpaIe->multicast_cipher, CSR_WPA_OUI_SIZE); + cUnicastCyphers = (tANI_U8)(pWpaIe->unicast_cipher_count); + cAuthSuites = (tANI_U8)(pWpaIe->auth_suite_count); + + //Check - Is requested Unicast Cipher supported by the BSS. + fAcceptableCyphers = csrMatchWPAOUIIndex( pMac, pWpaIe->unicast_ciphers, cUnicastCyphers, + csrGetOUIIndexFromCipher( enType ), Unicast ); + + if( !fAcceptableCyphers ) break; + + + //Unicast is supported. Pick the first matching Group cipher, if any. + for( i = 0 ; i < pMCEncryption->numEntries ; i++ ) + { + fAcceptableCyphers = csrMatchWPAOUIIndex( pMac, MulticastCyphers, cMulticastCyphers, + csrGetOUIIndexFromCipher( pMCEncryption->encryptionType[i]), Multicast ); + if(fAcceptableCyphers) + { + break; + } + } + if( !fAcceptableCyphers ) break; + + if( pNegotiatedMCCipher ) + *pNegotiatedMCCipher = pMCEncryption->encryptionType[i]; + + /* Initializing with FALSE as it has TRUE value already */ + fAcceptableCyphers = FALSE; + for (i = 0 ; i < pAuthType->numEntries; i++) + { + /* Ciphers are supported, Match authentication algorithm + and pick first matching auth type */ + if ( csrIsAuthWpa( pMac, pWpaIe->auth_suites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_WPA == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_WPA; + } + if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthWpaPsk( pMac, pWpaIe->auth_suites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_WPA_PSK == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_WPA_PSK; + } +#ifdef FEATURE_WLAN_ESE + if ( (negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsEseCckmAuthWpa( pMac, pWpaIe->auth_suites, cAuthSuites, Authentication ) ) + { + if (eCSR_AUTH_TYPE_CCKM_WPA == pAuthType->authType[i]) + negAuthType = eCSR_AUTH_TYPE_CCKM_WPA; + } +#endif /* FEATURE_WLAN_ESE */ + + // The 1st auth type in the APs WPA IE, to match stations connecting + // profiles auth type will cause us to exit this loop + // This is added as some APs advertise multiple akms in the WPA IE. + if (eCSR_AUTH_TYPE_UNKNOWN != negAuthType) + { + fAcceptableCyphers = TRUE; + break; + } + } // for + } + }while(0); + + if ( fAcceptableCyphers ) + { + if ( MulticastCypher ) + { + vos_mem_copy((tANI_U8 **)MulticastCypher, Multicast, CSR_WPA_OUI_SIZE); + } + + if ( UnicastCypher ) + { + vos_mem_copy((tANI_U8 **)UnicastCypher, Unicast, CSR_WPA_OUI_SIZE); + } + + if ( AuthSuite ) + { + vos_mem_copy((tANI_U8 **)AuthSuite, Authentication, CSR_WPA_OUI_SIZE); + } + + if( pNegotiatedAuthtype ) + { + *pNegotiatedAuthtype = negAuthType; + } + } + + return( fAcceptableCyphers ); +} + + + +tANI_BOOLEAN csrIsWpaEncryptionMatch( tpAniSirGlobal pMac, tCsrAuthList *pAuthType, eCsrEncryptionType enType, tCsrEncryptionList *pEnMcType, + tDot11fBeaconIEs *pIes, eCsrAuthType *pNegotiatedAuthtype, eCsrEncryptionType *pNegotiatedMCCipher ) +{ + tANI_BOOLEAN fWpaMatch = eANI_BOOLEAN_FALSE; + + // See if the cyphers in the Bss description match with the settings in the profile. + fWpaMatch = csrGetWpaCyphers( pMac, pAuthType, enType, pEnMcType, &pIes->WPA, NULL, NULL, NULL, pNegotiatedAuthtype, pNegotiatedMCCipher ); + + return( fWpaMatch ); +} + + +tANI_U8 csrConstructWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fWpaMatch; + tANI_U8 cbWpaIe = 0; + tANI_U8 UnicastCypher[ CSR_WPA_OUI_SIZE ]; + tANI_U8 MulticastCypher[ CSR_WPA_OUI_SIZE ]; + tANI_U8 AuthSuite[ CSR_WPA_OUI_SIZE ]; + tCsrWpaAuthIe *pAuthSuite; + tDot11fBeaconIEs *pIesLocal = pIes; + + do + { + if ( !csrIsProfileWpa( pProfile ) ) break; + + if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) ) + { + break; + } + // See if the cyphers in the Bss description match with the settings in the profile. + fWpaMatch = csrGetWpaCyphers( hHal, &pProfile->AuthType, pProfile->negotiatedUCEncryptionType, &pProfile->mcEncryptionType, + &pIesLocal->WPA, UnicastCypher, MulticastCypher, AuthSuite, NULL, NULL ); + if ( !fWpaMatch ) break; + + pWpaIe->IeHeader.ElementID = SIR_MAC_WPA_EID; + + vos_mem_copy(pWpaIe->Oui, csrWpaOui[01], sizeof( pWpaIe->Oui )); + + pWpaIe->Version = CSR_WPA_VERSION_SUPPORTED; + + vos_mem_copy(pWpaIe->MulticastOui, MulticastCypher, sizeof( MulticastCypher )); + + pWpaIe->cUnicastCyphers = 1; + + vos_mem_copy(&pWpaIe->UnicastOui[ 0 ], UnicastCypher, sizeof( UnicastCypher )); + + pAuthSuite = (tCsrWpaAuthIe *)( &pWpaIe->UnicastOui[ pWpaIe->cUnicastCyphers ] ); + + pAuthSuite->cAuthenticationSuites = 1; + vos_mem_copy(&pAuthSuite->AuthOui[ 0 ], AuthSuite, sizeof( AuthSuite )); + + /* + * The WPA capabilities follows the Auth Suite (two octets)-- + * this field is optional, and we always "send" zero, so just + * remove it. This is consistent with our assumptions in the + * frames compiler; c.f. bug 15234: + * http://gold.woodsidenet.com/bugzilla/show_bug.cgi?id=15234 + * + * Add in the fixed fields plus 1 Unicast cypher, less the IE Header + * length + * Add in the size of the Auth suite (count plus a single OUI) + */ + pWpaIe->IeHeader.Length = sizeof( *pWpaIe ) - sizeof ( pWpaIe->IeHeader ) + + sizeof( *pAuthSuite ); + + // return the size of the IE header (total) constructed... + cbWpaIe = pWpaIe->IeHeader.Length + sizeof( pWpaIe->IeHeader ); + + } while( 0 ); + + if( !pIes && pIesLocal ) + { + //locally allocated + vos_mem_free(pIesLocal); + } + + return( cbWpaIe ); +} + + +tANI_BOOLEAN csrGetWpaRsnIe( tHalHandle hHal, tANI_U8 *pIes, tANI_U32 len, + tANI_U8 *pWpaIe, tANI_U8 *pcbWpaIe, tANI_U8 *pRSNIe, tANI_U8 *pcbRSNIe) +{ + tDot11IEHeader *pIEHeader; + tSirMacPropIE *pSirMacPropIE; + tANI_U32 cbParsed; + tANI_U32 cbIE; + int cExpectedIEs = 0; + int cFoundIEs = 0; + int cbPropIETotal; + + pIEHeader = (tDot11IEHeader *)pIes; + if(pWpaIe) cExpectedIEs++; + if(pRSNIe) cExpectedIEs++; + + // bss description length includes all fields other than the length itself + cbParsed = 0; + + // Loop as long as there is data left in the IE of the Bss Description + // and the number of Expected IEs is NOT found yet. + while( ( (cbParsed + sizeof( *pIEHeader )) <= len ) && ( cFoundIEs < cExpectedIEs ) ) + { + cbIE = sizeof( *pIEHeader ) + pIEHeader->Length; + + if ( ( cbIE + cbParsed ) > len ) break; + + if ( ( pIEHeader->Length >= gCsrIELengthTable[ pIEHeader->ElementID ].min ) && + ( pIEHeader->Length <= gCsrIELengthTable[ pIEHeader->ElementID ].max ) ) + { + switch( pIEHeader->ElementID ) + { + // Parse the 221 (0xdd) Proprietary IEs here... + // Note that the 221 IE is overloaded, containing the WPA IE, WMM/WME IE, and the + // Airgo proprietary IE information. + case SIR_MAC_WPA_EID: + { + tANI_U32 aniOUI; + tANI_U8 *pOui = (tANI_U8 *)&aniOUI; + + pOui++; + aniOUI = ANI_OUI; + aniOUI = i_ntohl( aniOUI ); + + pSirMacPropIE = ( tSirMacPropIE *)pIEHeader; + cbPropIETotal = pSirMacPropIE->length; + + // Validate the ANI OUI is in the OUI field in the proprietary IE... + if ( ( pSirMacPropIE->length >= WNI_CFG_MANUFACTURER_OUI_LEN ) && + pOui[ 0 ] == pSirMacPropIE->oui[ 0 ] && + pOui[ 1 ] == pSirMacPropIE->oui[ 1 ] && + pOui[ 2 ] == pSirMacPropIE->oui[ 2 ] ) + { + } + else + { + tCsrWpaIe *pIe = ( tCsrWpaIe * )pIEHeader; + + if(!pWpaIe || !pcbWpaIe) break; + // Check if this is a valid WPA IE. Then check that the + // WPA OUI is in place and the version is one that we support. + if ( ( pIe->IeHeader.Length >= SIR_MAC_WPA_IE_MIN_LENGTH ) && + ( vos_mem_compare( pIe->Oui, (void *)csrWpaOui[1], + sizeof( pIe->Oui ) ) ) && + ( pIe->Version <= CSR_WPA_VERSION_SUPPORTED ) ) + { + vos_mem_copy(pWpaIe, pIe, + pIe->IeHeader.Length + sizeof( pIe->IeHeader )); + *pcbWpaIe = pIe->IeHeader.Length + sizeof( pIe->IeHeader ); + cFoundIEs++; + + break; + } + } + + break; + } + + case SIR_MAC_RSN_EID: + { + tCsrRSNIe *pIe; + + if(!pcbRSNIe || !pRSNIe) break; + pIe = (tCsrRSNIe *)pIEHeader; + + // Check the length of the RSN Ie to assure it is valid. Then check that the + // version is one that we support. + + if ( pIe->IeHeader.Length < SIR_MAC_RSN_IE_MIN_LENGTH ) break; + if ( pIe->Version > CSR_RSN_VERSION_SUPPORTED ) break; + + cFoundIEs++; + + // if there is enough room in the WpaIE passed in, then copy the Wpa IE into + // the buffer passed in. + if ( *pcbRSNIe < pIe->IeHeader.Length + sizeof( pIe->IeHeader ) ) break; + vos_mem_copy(pRSNIe, pIe, + pIe->IeHeader.Length + sizeof( pIe->IeHeader )); + *pcbRSNIe = pIe->IeHeader.Length + sizeof( pIe->IeHeader ); + + break; + } + + // Add support for other IE here... + default: + break; + } + } + + cbParsed += cbIE; + + pIEHeader = (tDot11IEHeader *)( ((tANI_U8 *)pIEHeader) + cbIE ); + + } + + // return a BOOL that tells if all of the IEs asked for were found... + return( cFoundIEs == cExpectedIEs ); +} + + +/* + * If a WPAIE exists in the profile, just use it. Or else construct one from + * the BSS Caller allocated memory for pWpaIe and guarantee it can contain a max + * length WPA IE + */ +tANI_U8 csrRetrieveWpaIe( tHalHandle hHal, tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U8 cbWpaIe = 0; + + do + { + if ( !csrIsProfileWpa( pProfile ) ) break; + if(pProfile->nWPAReqIELength && pProfile->pWPAReqIE) + { + if(SIR_MAC_WPA_IE_MAX_LENGTH >= pProfile->nWPAReqIELength) + { + cbWpaIe = (tANI_U8)pProfile->nWPAReqIELength; + vos_mem_copy(pWpaIe, pProfile->pWPAReqIE, cbWpaIe); + } + else + { + smsLog(pMac, LOGW, " csrRetrieveWpaIe detect invalid WPA IE length (%d) ", pProfile->nWPAReqIELength); + } + } + else + { + cbWpaIe = csrConstructWpaIe(pMac, pProfile, pSirBssDesc, pIes, pWpaIe); + } + }while(0); + + return (cbWpaIe); +} + + +/* + * If a RSNIE exists in the profile, just use it. Or else construct one from the + * BSS. Caller allocated memory for pWpaIe and guarantee it can contain a max + * length WPA IE + */ +tANI_U8 csrRetrieveRsnIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tCsrRSNIe *pRsnIe ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U8 cbRsnIe = 0; + + do + { + if ( !csrIsProfileRSN( pProfile ) ) break; +#ifdef FEATURE_WLAN_LFR + if (csrRoamIsFastRoamEnabled(pMac, sessionId)) + { + // If "Legacy Fast Roaming" is enabled ALWAYS rebuild the RSN IE from + // scratch. So it contains the current PMK-IDs + cbRsnIe = csrConstructRSNIe(pMac, sessionId, pProfile, pSirBssDesc, pIes, pRsnIe); + } + else +#endif + if(pProfile->nRSNReqIELength && pProfile->pRSNReqIE) + { + // If you have one started away, re-use it. + if(SIR_MAC_WPA_IE_MAX_LENGTH >= pProfile->nRSNReqIELength) + { + cbRsnIe = (tANI_U8)pProfile->nRSNReqIELength; + vos_mem_copy(pRsnIe, pProfile->pRSNReqIE, cbRsnIe); + } + else + { + smsLog(pMac, LOGW, " csrRetrieveRsnIe detect invalid RSN IE length (%d) ", pProfile->nRSNReqIELength); + } + } + else + { + cbRsnIe = csrConstructRSNIe(pMac, sessionId, pProfile, pSirBssDesc, pIes, pRsnIe); + } + }while(0); + + return (cbRsnIe); +} + + +#ifdef FEATURE_WLAN_WAPI +/* + * If a WAPI IE exists in the profile, just use it. Or else construct one from + * the BSS. Caller allocated memory for pWapiIe and guarantee it can contain a + * max length WAPI IE. + */ +tANI_U8 csrRetrieveWapiIe( tHalHandle hHal, tANI_U32 sessionId, + tCsrRoamProfile *pProfile, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U8 cbWapiIe = 0; + + do + { + if ( !csrIsProfileWapi( pProfile ) ) break; + if(pProfile->nWAPIReqIELength && pProfile->pWAPIReqIE) + { + if(DOT11F_IE_WAPI_MAX_LEN >= pProfile->nWAPIReqIELength) + { + cbWapiIe = (tANI_U8)pProfile->nWAPIReqIELength; + vos_mem_copy(pWapiIe, pProfile->pWAPIReqIE, cbWapiIe); + } + else + { + smsLog(pMac, LOGW, " csrRetrieveWapiIe detect invalid WAPI IE length (%d) ", pProfile->nWAPIReqIELength); + } + } + else + { + cbWapiIe = csrConstructWapiIe(pMac, sessionId, pProfile, pSirBssDesc, pIes, pWapiIe); + } + }while(0); + + return (cbWapiIe); +} +#endif /* FEATURE_WLAN_WAPI */ + +tANI_BOOLEAN csrSearchChannelListForTxPower(tHalHandle hHal, tSirBssDescription *pBssDescription, tCsrChannelSet *returnChannelGroup) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tListElem *pEntry; + tANI_U16 i; + tANI_U16 startingChannel; + tANI_BOOLEAN found = FALSE; + tCsrChannelSet *pChannelGroup; + + pEntry = csrLLPeekHead( &pMac->roam.channelList5G, LL_ACCESS_LOCK ); + + while ( pEntry ) + { + pChannelGroup = GET_BASE_ADDR( pEntry, tCsrChannelSet, channelListLink ); + startingChannel = pChannelGroup->firstChannel; + for ( i = 0; i < pChannelGroup->numChannels; i++ ) + { + if ( startingChannel + i * pChannelGroup->interChannelOffset == pBssDescription->channelId ) + { + found = TRUE; + break; + } + } + + if ( found ) + { + vos_mem_copy(returnChannelGroup, pChannelGroup, sizeof(tCsrChannelSet)); + break; + } + else + { + pEntry = csrLLNext( &pMac->roam.channelList5G, pEntry, LL_ACCESS_LOCK ); + } + } + + return( found ); +} + +tANI_BOOLEAN csrRatesIsDot11Rate11bSupportedRate( tANI_U8 dot11Rate ) +{ + tANI_BOOLEAN fSupported = FALSE; + tANI_U16 nonBasicRate = (tANI_U16)( BITS_OFF( dot11Rate, CSR_DOT11_BASIC_RATE_MASK ) ); + + switch ( nonBasicRate ) + { + case eCsrSuppRate_1Mbps: + case eCsrSuppRate_2Mbps: + case eCsrSuppRate_5_5Mbps: + case eCsrSuppRate_11Mbps: + fSupported = TRUE; + break; + + default: + break; + } + + return( fSupported ); +} + +tANI_BOOLEAN csrRatesIsDot11Rate11aSupportedRate( tANI_U8 dot11Rate ) +{ + tANI_BOOLEAN fSupported = FALSE; + tANI_U16 nonBasicRate = (tANI_U16)( BITS_OFF( dot11Rate, CSR_DOT11_BASIC_RATE_MASK ) ); + + switch ( nonBasicRate ) + { + case eCsrSuppRate_6Mbps: + case eCsrSuppRate_9Mbps: + case eCsrSuppRate_12Mbps: + case eCsrSuppRate_18Mbps: + case eCsrSuppRate_24Mbps: + case eCsrSuppRate_36Mbps: + case eCsrSuppRate_48Mbps: + case eCsrSuppRate_54Mbps: + fSupported = TRUE; + break; + + default: + break; + } + + return( fSupported ); +} + + + +tAniEdType csrTranslateEncryptTypeToEdType( eCsrEncryptionType EncryptType ) +{ + tAniEdType edType; + + switch ( EncryptType ) + { + default: + case eCSR_ENCRYPT_TYPE_NONE: + edType = eSIR_ED_NONE; + break; + + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + edType = eSIR_ED_WEP40; + break; + + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104: + edType = eSIR_ED_WEP104; + break; + + case eCSR_ENCRYPT_TYPE_TKIP: + edType = eSIR_ED_TKIP; + break; + + case eCSR_ENCRYPT_TYPE_AES: + edType = eSIR_ED_CCMP; + break; +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + edType = eSIR_ED_WPI; + break ; +#endif +#ifdef WLAN_FEATURE_11W + //11w BIP + case eCSR_ENCRYPT_TYPE_AES_CMAC: + edType = eSIR_ED_AES_128_CMAC; + break; +#endif + } + + return( edType ); +} + + +//pIes can be NULL +tANI_BOOLEAN csrValidateWep( tpAniSirGlobal pMac, eCsrEncryptionType ucEncryptionType, + tCsrAuthList *pAuthList, tCsrEncryptionList *pMCEncryptionList, + eCsrAuthType *pNegotiatedAuthType, eCsrEncryptionType *pNegotiatedMCEncryption, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes ) +{ + tANI_U32 idx; + tANI_BOOLEAN fMatch = FALSE; + eCsrAuthType negotiatedAuth = eCSR_AUTH_TYPE_OPEN_SYSTEM; + eCsrEncryptionType negotiatedMCCipher = eCSR_ENCRYPT_TYPE_UNKNOWN; + + //This function just checks whether HDD is giving correct values for Multicast cipher and Auth. + + do + { + //If privacy bit is not set, consider no match + if ( !csrIsPrivacy( pSirBssDesc ) ) break; + + for( idx = 0; idx < pMCEncryptionList->numEntries; idx++ ) + { + switch( pMCEncryptionList->encryptionType[idx] ) + { + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP104: + /* Multicast list may contain WEP40/WEP104. Check whether it matches UC. + */ + if( ucEncryptionType == pMCEncryptionList->encryptionType[idx] ) + { + fMatch = TRUE; + negotiatedMCCipher = pMCEncryptionList->encryptionType[idx]; + } + break; + default: + fMatch = FALSE; + break; + } + if(fMatch) break; + } + + if(!fMatch) break; + + for( idx = 0; idx < pAuthList->numEntries; idx++ ) + { + switch( pAuthList->authType[idx] ) + { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + case eCSR_AUTH_TYPE_SHARED_KEY: + case eCSR_AUTH_TYPE_AUTOSWITCH: + fMatch = TRUE; + negotiatedAuth = pAuthList->authType[idx]; + break; + default: + fMatch = FALSE; + } + if (fMatch) break; + } + + if(!fMatch) break; + //In case of WPA / WPA2, check whether it supports WEP as well + if(pIes) + { + //Prepare the encryption type for WPA/WPA2 functions + if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == ucEncryptionType ) + { + ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP40; + } + else if( eCSR_ENCRYPT_TYPE_WEP104 == ucEncryptionType ) + { + ucEncryptionType = eCSR_ENCRYPT_TYPE_WEP104; + } + //else we can use the encryption type directly + if ( pIes->WPA.present ) + { + fMatch = vos_mem_compare(pIes->WPA.multicast_cipher, + csrWpaOui[csrGetOUIIndexFromCipher( ucEncryptionType )], + CSR_WPA_OUI_SIZE); + if( fMatch ) break; + } + if ( pIes->RSN.present ) + { + fMatch = vos_mem_compare(pIes->RSN.gp_cipher_suite, + csrRSNOui[csrGetOUIIndexFromCipher( ucEncryptionType )], + CSR_RSN_OUI_SIZE); + } + } + + }while(0); + + if( fMatch ) + { + if( pNegotiatedAuthType ) + *pNegotiatedAuthType = negotiatedAuth; + + if( pNegotiatedMCEncryption ) + *pNegotiatedMCEncryption = negotiatedMCCipher; + } + + + return fMatch; +} + + +//pIes shall contain IEs from pSirBssDesc. It shall be returned from function csrGetParsedBssDescriptionIEs +tANI_BOOLEAN csrIsSecurityMatch( tHalHandle hHal, tCsrAuthList *authType, + tCsrEncryptionList *pUCEncryptionType, + tCsrEncryptionList *pMCEncryptionType, + tANI_BOOLEAN *pMFPEnabled, + tANI_U8 *pMFPRequired, tANI_U8 *pMFPCapable, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, + eCsrAuthType *negotiatedAuthtype, + eCsrEncryptionType *negotiatedUCCipher, + eCsrEncryptionType *negotiatedMCCipher ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fMatch = FALSE; + tANI_U8 i,idx; + eCsrEncryptionType mcCipher = eCSR_ENCRYPT_TYPE_UNKNOWN, ucCipher = eCSR_ENCRYPT_TYPE_UNKNOWN; + eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + + for( i = 0 ; ((i < pUCEncryptionType->numEntries) && (!fMatch)) ; i++ ) + { + ucCipher = pUCEncryptionType->encryptionType[i]; + // If the Bss description shows the Privacy bit is on, then we must have some sort of encryption configured + // for the profile to work. Don't attempt to join networks with Privacy bit set when profiles say NONE for + // encryption type. + switch ( ucCipher ) + { + case eCSR_ENCRYPT_TYPE_NONE: + { + // for NO encryption, if the Bss description has the Privacy bit turned on, then encryption is + // required so we have to reject this Bss. + if ( csrIsPrivacy( pSirBssDesc ) ) + { + fMatch = FALSE; + } + else + { + fMatch = TRUE; + } + + if ( fMatch ) + { + fMatch = FALSE; + //Check Multicast cipher requested and Auth type requested. + for( idx = 0 ; idx < pMCEncryptionType->numEntries ; idx++ ) + { + if( eCSR_ENCRYPT_TYPE_NONE == pMCEncryptionType->encryptionType[idx] ) + { + fMatch = TRUE; //Multicast can only be none. + mcCipher = pMCEncryptionType->encryptionType[idx]; + break; + } + } + if (!fMatch) break; + + fMatch = FALSE; + //Check Auth list. It should contain AuthOpen. + for( idx = 0 ; idx < authType->numEntries ; idx++ ) + { + if(( eCSR_AUTH_TYPE_OPEN_SYSTEM == authType->authType[idx] ) || + ( eCSR_AUTH_TYPE_AUTOSWITCH == authType->authType[idx] )) + { + fMatch = TRUE; + negAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + break; + } + } + if (!fMatch) break; + + } + break; + } + + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + // !! might want to check for WEP keys set in the Profile.... ? + // !! don't need to have the privacy bit in the Bss description. Many AP policies make legacy + // encryption 'optional' so we don't know if we can associate or not. The AP will reject if + // encryption is not allowed without the Privacy bit turned on. + fMatch = csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes); + + break; + + // these are all of the WPA encryption types... + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP104: + fMatch = csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes); + break; + + case eCSR_ENCRYPT_TYPE_TKIP: + case eCSR_ENCRYPT_TYPE_AES: + { + if(pIes) + { + // First check if there is a RSN match + fMatch = csrIsRSNMatch( pMac, authType, ucCipher, + pMCEncryptionType, pMFPEnabled, + pMFPRequired, pMFPCapable, + pIes, &negAuthType, &mcCipher ); + if( !fMatch ) + { + // If not RSN, then check if there is a WPA match + fMatch = csrIsWpaEncryptionMatch( pMac, authType, ucCipher, pMCEncryptionType, pIes, + &negAuthType, &mcCipher ); + } + } + else + { + fMatch = FALSE; + } + break; + } +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI://WAPI + { + if(pIes) + { + fMatch = csrIsWapiMatch( hHal, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher ); + } + else + { + fMatch = FALSE; + } + break; + } +#endif /* FEATURE_WLAN_WAPI */ + case eCSR_ENCRYPT_TYPE_ANY: + default: + { + tANI_BOOLEAN fMatchAny = eANI_BOOLEAN_FALSE; + + fMatch = eANI_BOOLEAN_TRUE; + //It is allowed to match anything. Try the more secured ones first. + if(pIes) + { + //Check AES first + ucCipher = eCSR_ENCRYPT_TYPE_AES; + fMatchAny = csrIsRSNMatch( hHal, authType, ucCipher, + pMCEncryptionType, pMFPEnabled, + pMFPRequired, pMFPCapable, pIes, + &negAuthType, &mcCipher ); + if(!fMatchAny) + { + //Check TKIP + ucCipher = eCSR_ENCRYPT_TYPE_TKIP; + fMatchAny = csrIsRSNMatch( hHal, authType, ucCipher, + pMCEncryptionType, + pMFPEnabled, pMFPRequired, + pMFPCapable, pIes, + &negAuthType, &mcCipher ); + } +#ifdef FEATURE_WLAN_WAPI + if(!fMatchAny) + { + //Check WAPI + ucCipher = eCSR_ENCRYPT_TYPE_WPI; + fMatchAny = csrIsWapiMatch( hHal, authType, ucCipher, pMCEncryptionType, pIes, &negAuthType, &mcCipher ); + } +#endif /* FEATURE_WLAN_WAPI */ + } + if(!fMatchAny) + { + ucCipher = eCSR_ENCRYPT_TYPE_WEP104; + if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes)) + { + ucCipher = eCSR_ENCRYPT_TYPE_WEP40; + if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes)) + { + ucCipher = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes)) + { + ucCipher = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + if(!csrValidateWep( pMac, ucCipher, authType, pMCEncryptionType, &negAuthType, &mcCipher, pSirBssDesc, pIes)) + { + //It must be open and no encryption + if ( csrIsPrivacy( pSirBssDesc ) ) + { + //This is not right + fMatch = eANI_BOOLEAN_FALSE; + } + else + { + negAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + mcCipher = eCSR_ENCRYPT_TYPE_NONE; + ucCipher = eCSR_ENCRYPT_TYPE_NONE; + } + } + } + } + } + } + break; + } + } + + } + + if( fMatch ) + { + if( negotiatedUCCipher ) + *negotiatedUCCipher = ucCipher; + + if( negotiatedMCCipher ) + *negotiatedMCCipher = mcCipher; + + if( negotiatedAuthtype ) + *negotiatedAuthtype = negAuthType; + } + + return( fMatch ); +} + + +tANI_BOOLEAN csrIsSsidMatch( tpAniSirGlobal pMac, tANI_U8 *ssid1, tANI_U8 ssid1Len, tANI_U8 *bssSsid, + tANI_U8 bssSsidLen, tANI_BOOLEAN fSsidRequired ) +{ + tANI_BOOLEAN fMatch = FALSE; + + do { + /* + * Check for the specification of the Broadcast SSID at the beginning + * of the list. If specified, then all SSIDs are matches + * (broadcast SSID means accept all SSIDs). + */ + if ( ssid1Len == 0 ) + { + fMatch = TRUE; + break; + } + + /* + * There are a few special cases. If the Bss description has a + * Broadcast SSID, then our Profile must have a single SSID without + * Wild cards so we can program the SSID. + * SSID could be suppressed in beacons. In that case SSID IE has valid + * length but the SSID value is all NULL characters. + * That condition is treated same as NULL SSID. + */ + if ( csrIsNULLSSID( bssSsid, bssSsidLen ) ) + { + if ( eANI_BOOLEAN_FALSE == fSsidRequired ) + { + fMatch = TRUE; + break; + } + } + + if(ssid1Len != bssSsidLen) break; + if (vos_mem_compare(bssSsid, ssid1, bssSsidLen)) + { + fMatch = TRUE; + break; + } + + } while( 0 ); + + return( fMatch ); +} + + +//Null ssid means match +tANI_BOOLEAN csrIsSsidInList( tHalHandle hHal, tSirMacSSid *pSsid, tCsrSSIDs *pSsidList ) +{ + tANI_BOOLEAN fMatch = FALSE; + tANI_U32 i; + + if ( pSsidList && pSsid ) + { + for(i = 0; i < pSsidList->numOfSSIDs; i++) + { + if(csrIsNULLSSID(pSsidList->SSIDList[i].SSID.ssId, pSsidList->SSIDList[i].SSID.length) || + ((pSsidList->SSIDList[i].SSID.length == pSsid->length) && + vos_mem_compare(pSsid->ssId, pSsidList->SSIDList[i].SSID.ssId, pSsid->length))) + { + fMatch = TRUE; + break; + } + } + } + + return (fMatch); +} + +//like to use sirCompareMacAddr +tANI_BOOLEAN csrIsMacAddressZero( tpAniSirGlobal pMac, tCsrBssid *pMacAddr ) +{ + tANI_U8 bssid[VOS_MAC_ADDR_SIZE] = {0, 0, 0, 0, 0, 0}; + + return (vos_mem_compare(bssid, pMacAddr, VOS_MAC_ADDR_SIZE)); +} + +//like to use sirCompareMacAddr +tANI_BOOLEAN csrIsMacAddressBroadcast( tpAniSirGlobal pMac, tCsrBssid *pMacAddr ) +{ + tANI_U8 bssid[VOS_MAC_ADDR_SIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + return(vos_mem_compare(bssid, pMacAddr, VOS_MAC_ADDR_SIZE)); +} + + +//like to use sirCompareMacAddr +tANI_BOOLEAN csrIsMacAddressEqual( tpAniSirGlobal pMac, tCsrBssid *pMacAddr1, tCsrBssid *pMacAddr2 ) +{ + return(vos_mem_compare(pMacAddr1, pMacAddr2, sizeof(tCsrBssid))); +} + + +tANI_BOOLEAN csrIsBssidMatch( tHalHandle hHal, tCsrBssid *pProfBssid, tCsrBssid *BssBssid ) +{ + tANI_BOOLEAN fMatch = FALSE; + tCsrBssid ProfileBssid; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + // for efficiency of the MAC_ADDRESS functions, move the + // Bssid's into MAC_ADDRESS structs. + vos_mem_copy(&ProfileBssid, pProfBssid, sizeof(tCsrBssid)); + + do { + + // Give the profile the benefit of the doubt... accept either all 0 or + // the real broadcast Bssid (all 0xff) as broadcast Bssids (meaning to + // match any Bssids). + if ( csrIsMacAddressZero( pMac, &ProfileBssid ) || + csrIsMacAddressBroadcast( pMac, &ProfileBssid ) ) + { + fMatch = TRUE; + break; + } + + if ( csrIsMacAddressEqual( pMac, BssBssid, &ProfileBssid ) ) + { + fMatch = TRUE; + break; + } + + } while( 0 ); + + return( fMatch ); +} + + +tANI_BOOLEAN csrIsBSSTypeMatch(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2) +{ + if((eCSR_BSS_TYPE_ANY != bssType1 && eCSR_BSS_TYPE_ANY != bssType2) && (bssType1 != bssType2)) + return eANI_BOOLEAN_FALSE; + else + return eANI_BOOLEAN_TRUE; +} + + +tANI_BOOLEAN csrIsBssTypeIBSS(eCsrRoamBssType bssType) +{ + return((tANI_BOOLEAN)(eCSR_BSS_TYPE_START_IBSS == bssType || eCSR_BSS_TYPE_IBSS == bssType)); +} + +tANI_BOOLEAN csrIsBssTypeWDS(eCsrRoamBssType bssType) +{ + return((tANI_BOOLEAN)(eCSR_BSS_TYPE_WDS_STA == bssType || eCSR_BSS_TYPE_WDS_AP == bssType)); +} + +tANI_BOOLEAN csrIsBSSTypeCapsMatch( eCsrRoamBssType bssType, tSirBssDescription *pSirBssDesc ) +{ + tANI_BOOLEAN fMatch = TRUE; + + do + { + switch( bssType ) + { + case eCSR_BSS_TYPE_ANY: + break; + + case eCSR_BSS_TYPE_INFRASTRUCTURE: + case eCSR_BSS_TYPE_WDS_STA: + if( !csrIsInfraBssDesc( pSirBssDesc ) ) + fMatch = FALSE; + + break; + + case eCSR_BSS_TYPE_IBSS: + case eCSR_BSS_TYPE_START_IBSS: + if( !csrIsIbssBssDesc( pSirBssDesc ) ) + fMatch = FALSE; + + break; + + case eCSR_BSS_TYPE_WDS_AP: //For WDS AP, no need to match anything + default: + fMatch = FALSE; + break; + } + } + while( 0 ); + + + return( fMatch ); +} + +static tANI_BOOLEAN csrIsCapabilitiesMatch( tpAniSirGlobal pMac, eCsrRoamBssType bssType, tSirBssDescription *pSirBssDesc ) +{ + return( csrIsBSSTypeCapsMatch( bssType, pSirBssDesc ) ); +} + + + +static tANI_BOOLEAN csrIsSpecificChannelMatch( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tANI_U8 Channel ) +{ + tANI_BOOLEAN fMatch = TRUE; + + do + { + // if the channel is ANY, then always match... + if ( eCSR_OPERATING_CHANNEL_ANY == Channel ) break; + if ( Channel == pSirBssDesc->channelId ) break; + + // didn't match anything.. so return NO match + fMatch = FALSE; + + } while( 0 ); + + return( fMatch ); +} + + +tANI_BOOLEAN csrIsChannelBandMatch( tpAniSirGlobal pMac, tANI_U8 channelId, tSirBssDescription *pSirBssDesc ) +{ + tANI_BOOLEAN fMatch = TRUE; + + do + { + // if the profile says Any channel AND the global settings says ANY channel, then we + // always match... + if ( eCSR_OPERATING_CHANNEL_ANY == channelId ) break; + + if ( eCSR_OPERATING_CHANNEL_ANY != channelId ) + { + fMatch = csrIsSpecificChannelMatch( pMac, pSirBssDesc, channelId ); + } + + } while( 0 ); + + return( fMatch ); +} + + +/** + * \brief Enquire as to whether a given rate is supported by the + * adapter as currently configured + * + * + * \param nRate A rate in units of 500kbps + * + * \return TRUE if the adapter is currently capable of supporting this + * rate, FALSE else + * + * + * The rate encoding is just as in 802.11 Information Elements, except + * that the high bit is \em not interpreted as indicating a Basic Rate, + * and proprietary rates are allowed, too. + * + * Note that if the adapter's dot11Mode is g, we don't restrict the + * rates. According to hwReadEepromParameters, this will happen when: + * + * ... the card is configured for ALL bands through the property + * page. If this occurs, and the card is not an ABG card ,then this + * code is setting the dot11Mode to assume the mode that the + * hardware can support. For example, if the card is an 11BG card + * and we are configured to support ALL bands, then we change the + * dot11Mode to 11g because ALL in this case is only what the + * hardware can support. + * + * + */ + +static tANI_BOOLEAN csrIsAggregateRateSupported( tpAniSirGlobal pMac, tANI_U16 rate ) +{ + tANI_BOOLEAN fSupported = eANI_BOOLEAN_FALSE; + tANI_U16 idx, newRate; + + //In case basic rate flag is set + newRate = BITS_OFF(rate, CSR_DOT11_BASIC_RATE_MASK); + if ( eCSR_CFG_DOT11_MODE_11A == pMac->roam.configParam.uCfgDot11Mode ) + { + switch ( newRate ) + { + case eCsrSuppRate_6Mbps: + case eCsrSuppRate_9Mbps: + case eCsrSuppRate_12Mbps: + case eCsrSuppRate_18Mbps: + case eCsrSuppRate_24Mbps: + case eCsrSuppRate_36Mbps: + case eCsrSuppRate_48Mbps: + case eCsrSuppRate_54Mbps: + fSupported = TRUE; + break; + default: + fSupported = FALSE; + break; + } + + } + else if( eCSR_CFG_DOT11_MODE_11B == pMac->roam.configParam.uCfgDot11Mode ) + { + switch ( newRate ) + { + case eCsrSuppRate_1Mbps: + case eCsrSuppRate_2Mbps: + case eCsrSuppRate_5_5Mbps: + case eCsrSuppRate_11Mbps: + fSupported = TRUE; + break; + default: + fSupported = FALSE; + break; + } + } + else if ( !pMac->roam.configParam.ProprietaryRatesEnabled ) + { + + switch ( newRate ) + { + case eCsrSuppRate_1Mbps: + case eCsrSuppRate_2Mbps: + case eCsrSuppRate_5_5Mbps: + case eCsrSuppRate_6Mbps: + case eCsrSuppRate_9Mbps: + case eCsrSuppRate_11Mbps: + case eCsrSuppRate_12Mbps: + case eCsrSuppRate_18Mbps: + case eCsrSuppRate_24Mbps: + case eCsrSuppRate_36Mbps: + case eCsrSuppRate_48Mbps: + case eCsrSuppRate_54Mbps: + fSupported = TRUE; + break; + default: + fSupported = FALSE; + break; + } + + } + else { + + if ( eCsrSuppRate_1Mbps == newRate || + eCsrSuppRate_2Mbps == newRate || + eCsrSuppRate_5_5Mbps == newRate || + eCsrSuppRate_11Mbps == newRate ) + { + fSupported = TRUE; + } + else { + idx = 0x1; + + switch ( newRate ) + { + case eCsrSuppRate_6Mbps: + fSupported = gPhyRatesSuppt[0][idx]; + break; + case eCsrSuppRate_9Mbps: + fSupported = gPhyRatesSuppt[1][idx]; + break; + case eCsrSuppRate_12Mbps: + fSupported = gPhyRatesSuppt[2][idx]; + break; + case eCsrSuppRate_18Mbps: + fSupported = gPhyRatesSuppt[3][idx]; + break; + case eCsrSuppRate_20Mbps: + fSupported = gPhyRatesSuppt[4][idx]; + break; + case eCsrSuppRate_24Mbps: + fSupported = gPhyRatesSuppt[5][idx]; + break; + case eCsrSuppRate_36Mbps: + fSupported = gPhyRatesSuppt[6][idx]; + break; + case eCsrSuppRate_40Mbps: + fSupported = gPhyRatesSuppt[7][idx]; + break; + case eCsrSuppRate_42Mbps: + fSupported = gPhyRatesSuppt[8][idx]; + break; + case eCsrSuppRate_48Mbps: + fSupported = gPhyRatesSuppt[9][idx]; + break; + case eCsrSuppRate_54Mbps: + fSupported = gPhyRatesSuppt[10][idx]; + break; + case eCsrSuppRate_72Mbps: + fSupported = gPhyRatesSuppt[11][idx]; + break; + case eCsrSuppRate_80Mbps: + fSupported = gPhyRatesSuppt[12][idx]; + break; + case eCsrSuppRate_84Mbps: + fSupported = gPhyRatesSuppt[13][idx]; + break; + case eCsrSuppRate_96Mbps: + fSupported = gPhyRatesSuppt[14][idx]; + break; + case eCsrSuppRate_108Mbps: + fSupported = gPhyRatesSuppt[15][idx]; + break; + case eCsrSuppRate_120Mbps: + fSupported = gPhyRatesSuppt[16][idx]; + break; + case eCsrSuppRate_126Mbps: + fSupported = gPhyRatesSuppt[17][idx]; + break; + case eCsrSuppRate_144Mbps: + fSupported = gPhyRatesSuppt[18][idx]; + break; + case eCsrSuppRate_160Mbps: + fSupported = gPhyRatesSuppt[19][idx]; + break; + case eCsrSuppRate_168Mbps: + fSupported = gPhyRatesSuppt[20][idx]; + break; + case eCsrSuppRate_192Mbps: + fSupported = gPhyRatesSuppt[21][idx]; + break; + case eCsrSuppRate_216Mbps: + fSupported = gPhyRatesSuppt[22][idx]; + break; + case eCsrSuppRate_240Mbps: + fSupported = gPhyRatesSuppt[23][idx]; + break; + default: + fSupported = FALSE; + break; + } + } + } + + return fSupported; +} + + + +static tANI_BOOLEAN csrIsRateSetMatch( tpAniSirGlobal pMac, + tDot11fIESuppRates *pBssSuppRates, + tDot11fIEExtSuppRates *pBssExtSuppRates ) +{ + tANI_BOOLEAN fMatch = TRUE; + tANI_U32 i; + + + // Validate that all of the Basic rates advertised in the Bss description are supported. + if ( pBssSuppRates ) + { + for( i = 0; i < pBssSuppRates->num_rates; i++ ) + { + if ( CSR_IS_BASIC_RATE( pBssSuppRates->rates[ i ] ) ) + { + if ( !csrIsAggregateRateSupported( pMac, pBssSuppRates->rates[ i ] ) ) + { + fMatch = FALSE; + break; + } + } + } + } + + if ( fMatch && pBssExtSuppRates ) + { + for( i = 0; i < pBssExtSuppRates->num_rates; i++ ) + { + if ( CSR_IS_BASIC_RATE( pBssExtSuppRates->rates[ i ] ) ) + { + if ( !csrIsAggregateRateSupported( pMac, pBssExtSuppRates->rates[ i ] ) ) + { + fMatch = FALSE; + break; + } + } + } + } + + return( fMatch ); + +} + + +//ppIes can be NULL. If caller want to get the *ppIes allocated by this function, pass in *ppIes = NULL +tANI_BOOLEAN csrMatchBSS( tHalHandle hHal, tSirBssDescription *pBssDesc, tCsrScanResultFilter *pFilter, + eCsrAuthType *pNegAuth, eCsrEncryptionType *pNegUc, eCsrEncryptionType *pNegMc, + tDot11fBeaconIEs **ppIes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fRC = eANI_BOOLEAN_FALSE, fCheck, blacklist_check; + tANI_U32 i; + tDot11fBeaconIEs *pIes = NULL; + tANI_U8 *pb; + tCsrBssid *blacklist_bssid = NULL; + struct roam_ext_params *roam_params; + + roam_params = &pMac->roam.configParam.roam_params; + do { + if( ( NULL == ppIes ) || ( *ppIes ) == NULL ) + { + //If no IEs passed in, get our own. + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes))) + { + break; + } + } + else + { + //Save the one pass in for local use + pIes = *ppIes; + } + + //Check if caller wants P2P + fCheck = (!pFilter->p2pResult || pIes->P2PBeaconProbeRes.present); + if(!fCheck) break; + + /* Check for Blacklist BSSID's and avoid connections */ + blacklist_check = false; + blacklist_bssid = (tCsrBssid *)&roam_params->bssid_avoid_list; + for (i = 0; i < roam_params->num_bssid_avoid_list; i++) { + if (csrIsMacAddressEqual(pMac, blacklist_bssid, + (tCsrBssid *)pBssDesc->bssId)) { + blacklist_check = true; + break; + } + blacklist_bssid++; + } + if(blacklist_check) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Do not Attempt connection to blacklist bssid"); + break; + } + + if(pIes->SSID.present) + { + for(i = 0; i < pFilter->SSIDs.numOfSSIDs; i++) + { + fCheck = csrIsSsidMatch( pMac, pFilter->SSIDs.SSIDList[i].SSID.ssId, pFilter->SSIDs.SSIDList[i].SSID.length, + pIes->SSID.ssid, + pIes->SSID.num_ssid, eANI_BOOLEAN_TRUE ); + if ( fCheck ) break; + } + if(!fCheck) break; + } + fCheck = eANI_BOOLEAN_TRUE; + for(i = 0; i < pFilter->BSSIDs.numOfBSSIDs; i++) + { + fCheck = csrIsBssidMatch( pMac, (tCsrBssid *)&pFilter->BSSIDs.bssid[i], (tCsrBssid *)pBssDesc->bssId ); + if ( fCheck ) break; + + if (pFilter->p2pResult && pIes->P2PBeaconProbeRes.present) + { + fCheck = csrIsBssidMatch( pMac, (tCsrBssid *)&pFilter->BSSIDs.bssid[i], + (tCsrBssid *)pIes->P2PBeaconProbeRes.P2PDeviceInfo.P2PDeviceAddress ); + + if ( fCheck ) break; + } + } + if(!fCheck) break; + fCheck = eANI_BOOLEAN_TRUE; + for(i = 0; i < pFilter->ChannelInfo.numOfChannels; i++) + { + fCheck = csrIsChannelBandMatch( pMac, pFilter->ChannelInfo.ChannelList[i], pBssDesc ); + if ( fCheck ) break; + } + if(!fCheck) + break; +#if defined WLAN_FEATURE_VOWIFI + /* If this is for measurement filtering */ + if( pFilter->fMeasurement ) + { + fRC = eANI_BOOLEAN_TRUE; + break; + } +#endif + if ( !csrIsPhyModeMatch( pMac, pFilter->phyMode, pBssDesc, NULL, NULL, pIes ) ) break; + if ( (!pFilter->bWPSAssociation) && (!pFilter->bOSENAssociation) && +#ifdef WLAN_FEATURE_11W + !csrIsSecurityMatch( pMac, &pFilter->authType, + &pFilter->EncryptionType, + &pFilter->mcEncryptionType, + &pFilter->MFPEnabled, + &pFilter->MFPRequired, + &pFilter->MFPCapable, + pBssDesc, pIes, pNegAuth, + pNegUc, pNegMc ) +#else + !csrIsSecurityMatch( pMac, &pFilter->authType, + &pFilter->EncryptionType, + &pFilter->mcEncryptionType, + NULL, NULL, NULL, + pBssDesc, pIes, pNegAuth, + pNegUc, pNegMc ) +#endif + ) break; + if ( !csrIsCapabilitiesMatch( pMac, pFilter->BSSType, pBssDesc ) ) break; + if ( !csrIsRateSetMatch( pMac, &pIes->SuppRates, &pIes->ExtSuppRates ) ) break; + //Tush-QoS: validate first if asked for APSD or WMM association + if ( (eCsrRoamWmmQbssOnly == pMac->roam.configParam.WMMSupportMode) && + !CSR_IS_QOS_BSS(pIes) ) + break; + //Check country. check even when pb is NULL because we may want to make sure + //AP has a country code in it if fEnforceCountryCodeMatch is set. + pb = ( pFilter->countryCode[0] ) ? ( pFilter->countryCode) : NULL; + + fCheck = csrMatchCountryCode( pMac, pb, pIes ); + if(!fCheck) + break; + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pFilter->MDID.mdiePresent && + csrRoamIs11rAssoc(pMac, pMac->roam.roamSession->sessionId)) { + if (pBssDesc->mdiePresent) + { + if (pFilter->MDID.mobilityDomain != (pBssDesc->mdie[1] << 8 | pBssDesc->mdie[0])) + break; + } + else + break; + } +#endif + fRC = eANI_BOOLEAN_TRUE; + + } while( 0 ); + if( ppIes ) + { + *ppIes = pIes; + } + else if( pIes ) + { + vos_mem_free(pIes); + } + + return( fRC ); +} + +tANI_BOOLEAN csrMatchConnectedBSSSecurity( tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes) +{ + tCsrEncryptionList ucEncryptionList, mcEncryptionList; + tCsrAuthList authList; + + ucEncryptionList.numEntries = 1; + ucEncryptionList.encryptionType[0] = pProfile->EncryptionType; + + mcEncryptionList.numEntries = 1; + mcEncryptionList.encryptionType[0] = pProfile->mcEncryptionType; + + authList.numEntries = 1; + authList.authType[0] = pProfile->AuthType; + + return( csrIsSecurityMatch( pMac, &authList, &ucEncryptionList, + &mcEncryptionList, NULL, NULL, NULL, + pBssDesc, pIes, NULL, NULL, NULL )); + +} + + +tANI_BOOLEAN csrMatchBSSToConnectProfile( tHalHandle hHal, tCsrRoamConnectedProfile *pProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN fRC = eANI_BOOLEAN_FALSE, fCheck; + tDot11fBeaconIEs *pIesLocal = pIes; + + do { + if( !pIes ) + { + if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal))) + { + break; + } + } + fCheck = eANI_BOOLEAN_TRUE; + if(pIesLocal->SSID.present) + { + tANI_BOOLEAN fCheckSsid = eANI_BOOLEAN_FALSE; + if(pProfile->SSID.length) + { + fCheckSsid = eANI_BOOLEAN_TRUE; + } + fCheck = csrIsSsidMatch( pMac, pProfile->SSID.ssId, pProfile->SSID.length, + pIesLocal->SSID.ssid, pIesLocal->SSID.num_ssid, fCheckSsid ); + if(!fCheck) break; + } + if ( !csrMatchConnectedBSSSecurity( pMac, pProfile, pBssDesc, pIesLocal) ) break; + if ( !csrIsCapabilitiesMatch( pMac, pProfile->BSSType, pBssDesc ) ) break; + if ( !csrIsRateSetMatch( pMac, &pIesLocal->SuppRates, &pIesLocal->ExtSuppRates ) ) break; + fCheck = csrIsChannelBandMatch( pMac, pProfile->operationChannel, pBssDesc ); + if(!fCheck) + break; + + fRC = eANI_BOOLEAN_TRUE; + + } while( 0 ); + + if( !pIes && pIesLocal ) + { + //locally allocated + vos_mem_free(pIesLocal); + } + + return( fRC ); +} + +void csrAddRateBitmap(tANI_U8 rate, tANI_U16 *pRateBitmap) +{ + tANI_U16 rateBitmap; + tANI_U16 n = BITS_OFF( rate, CSR_DOT11_BASIC_RATE_MASK ); + rateBitmap = *pRateBitmap; + switch(n) + { + case SIR_MAC_RATE_1: + rateBitmap |= SIR_MAC_RATE_1_BITMAP; + break; + case SIR_MAC_RATE_2: + rateBitmap |= SIR_MAC_RATE_2_BITMAP; + break; + case SIR_MAC_RATE_5_5: + rateBitmap |= SIR_MAC_RATE_5_5_BITMAP; + break; + case SIR_MAC_RATE_11: + rateBitmap |= SIR_MAC_RATE_11_BITMAP; + break; + case SIR_MAC_RATE_6: + rateBitmap |= SIR_MAC_RATE_6_BITMAP; + break; + case SIR_MAC_RATE_9: + rateBitmap |= SIR_MAC_RATE_9_BITMAP; + break; + case SIR_MAC_RATE_12: + rateBitmap |= SIR_MAC_RATE_12_BITMAP; + break; + case SIR_MAC_RATE_18: + rateBitmap |= SIR_MAC_RATE_18_BITMAP; + break; + case SIR_MAC_RATE_24: + rateBitmap |= SIR_MAC_RATE_24_BITMAP; + break; + case SIR_MAC_RATE_36: + rateBitmap |= SIR_MAC_RATE_36_BITMAP; + break; + case SIR_MAC_RATE_48: + rateBitmap |= SIR_MAC_RATE_48_BITMAP; + break; + case SIR_MAC_RATE_54: + rateBitmap |= SIR_MAC_RATE_54_BITMAP; + break; + } + *pRateBitmap = rateBitmap; +} + +tANI_BOOLEAN csrCheckRateBitmap(tANI_U8 rate, tANI_U16 rateBitmap) +{ + tANI_U16 n = BITS_OFF( rate, CSR_DOT11_BASIC_RATE_MASK ); + + switch(n) + { + case SIR_MAC_RATE_1: + rateBitmap &= SIR_MAC_RATE_1_BITMAP; + break; + case SIR_MAC_RATE_2: + rateBitmap &= SIR_MAC_RATE_2_BITMAP; + break; + case SIR_MAC_RATE_5_5: + rateBitmap &= SIR_MAC_RATE_5_5_BITMAP; + break; + case SIR_MAC_RATE_11: + rateBitmap &= SIR_MAC_RATE_11_BITMAP; + break; + case SIR_MAC_RATE_6: + rateBitmap &= SIR_MAC_RATE_6_BITMAP; + break; + case SIR_MAC_RATE_9: + rateBitmap &= SIR_MAC_RATE_9_BITMAP; + break; + case SIR_MAC_RATE_12: + rateBitmap &= SIR_MAC_RATE_12_BITMAP; + break; + case SIR_MAC_RATE_18: + rateBitmap &= SIR_MAC_RATE_18_BITMAP; + break; + case SIR_MAC_RATE_24: + rateBitmap &= SIR_MAC_RATE_24_BITMAP; + break; + case SIR_MAC_RATE_36: + rateBitmap &= SIR_MAC_RATE_36_BITMAP; + break; + case SIR_MAC_RATE_48: + rateBitmap &= SIR_MAC_RATE_48_BITMAP; + break; + case SIR_MAC_RATE_54: + rateBitmap &= SIR_MAC_RATE_54_BITMAP; + break; + } + return !!rateBitmap; +} + +tANI_BOOLEAN csrRatesIsDot11RateSupported( tHalHandle hHal, tANI_U8 rate ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U16 n = BITS_OFF( rate, CSR_DOT11_BASIC_RATE_MASK ); + + return csrIsAggregateRateSupported( pMac, n ); +} + + +tANI_U16 csrRatesMacPropToDot11( tANI_U16 Rate ) +{ + tANI_U16 ConvertedRate = Rate; + + switch( Rate ) + { + case SIR_MAC_RATE_1: + ConvertedRate = 2; + break; + case SIR_MAC_RATE_2: + ConvertedRate = 4; + break; + case SIR_MAC_RATE_5_5: + ConvertedRate = 11; + break; + case SIR_MAC_RATE_11: + ConvertedRate = 22; + break; + + case SIR_MAC_RATE_6: + ConvertedRate = 12; + break; + case SIR_MAC_RATE_9: + ConvertedRate = 18; + break; + case SIR_MAC_RATE_12: + ConvertedRate = 24; + break; + case SIR_MAC_RATE_18: + ConvertedRate = 36; + break; + case SIR_MAC_RATE_24: + ConvertedRate = 48; + break; + case SIR_MAC_RATE_36: + ConvertedRate = 72; + break; + case SIR_MAC_RATE_42: + ConvertedRate = 84; + break; + case SIR_MAC_RATE_48: + ConvertedRate = 96; + break; + case SIR_MAC_RATE_54: + ConvertedRate = 108; + break; + + case SIR_MAC_RATE_72: + ConvertedRate = 144; + break; + case SIR_MAC_RATE_84: + ConvertedRate = 168; + break; + case SIR_MAC_RATE_96: + ConvertedRate = 192; + break; + case SIR_MAC_RATE_108: + ConvertedRate = 216; + break; + case SIR_MAC_RATE_126: + ConvertedRate = 252; + break; + case SIR_MAC_RATE_144: + ConvertedRate = 288; + break; + case SIR_MAC_RATE_168: + ConvertedRate = 336; + break; + case SIR_MAC_RATE_192: + ConvertedRate = 384; + break; + case SIR_MAC_RATE_216: + ConvertedRate = 432; + break; + case SIR_MAC_RATE_240: + ConvertedRate = 480; + break; + + case 0xff: + ConvertedRate = 0; + break; + } + + return ConvertedRate; +} + + +tANI_U16 csrRatesFindBestRate( tSirMacRateSet *pSuppRates, tSirMacRateSet *pExtRates, tSirMacPropRateSet *pPropRates ) +{ + tANI_U8 i; + tANI_U16 nBest; + + nBest = pSuppRates->rate[ 0 ] & ( ~CSR_DOT11_BASIC_RATE_MASK ); + + if(pSuppRates->numRates > SIR_MAC_RATESET_EID_MAX) + { + pSuppRates->numRates = SIR_MAC_RATESET_EID_MAX; + } + + for ( i = 1U; i < pSuppRates->numRates; ++i ) + { + nBest = (tANI_U16)CSR_MAX( nBest, pSuppRates->rate[ i ] & ( ~CSR_DOT11_BASIC_RATE_MASK ) ); + } + + if ( NULL != pExtRates ) + { + for ( i = 0U; i < pExtRates->numRates; ++i ) + { + nBest = (tANI_U16)CSR_MAX( nBest, pExtRates->rate[ i ] & ( ~CSR_DOT11_BASIC_RATE_MASK ) ); + } + } + + if ( NULL != pPropRates ) + { + for ( i = 0U; i < pPropRates->numPropRates; ++i ) + { + nBest = (tANI_U16)CSR_MAX( nBest, csrRatesMacPropToDot11( pPropRates->propRate[ i ] ) ); + } + } + + return nBest; +} + + +void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) +{ + if(pProfile) + { + if(pProfile->BSSIDs.bssid) + { + vos_mem_free(pProfile->BSSIDs.bssid); + pProfile->BSSIDs.bssid = NULL; + } + if(pProfile->SSIDs.SSIDList) + { + vos_mem_free(pProfile->SSIDs.SSIDList); + pProfile->SSIDs.SSIDList = NULL; + } + if(pProfile->pWPAReqIE) + { + vos_mem_free(pProfile->pWPAReqIE); + pProfile->pWPAReqIE = NULL; + } + if(pProfile->pRSNReqIE) + { + vos_mem_free(pProfile->pRSNReqIE); + pProfile->pRSNReqIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + if(pProfile->pWAPIReqIE) + { + vos_mem_free(pProfile->pWAPIReqIE); + pProfile->pWAPIReqIE = NULL; + } +#endif /* FEATURE_WLAN_WAPI */ + + if(pProfile->pAddIEScan) + { + vos_mem_free(pProfile->pAddIEScan); + pProfile->pAddIEScan = NULL; + } + + if(pProfile->pAddIEAssoc) + { + vos_mem_free(pProfile->pAddIEAssoc); + pProfile->pAddIEAssoc = NULL; + } + if(pProfile->ChannelInfo.ChannelList) + { + vos_mem_free(pProfile->ChannelInfo.ChannelList); + pProfile->ChannelInfo.ChannelList = NULL; + } + vos_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + } +} + +void csrFreeScanFilter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter) +{ + if(pScanFilter->BSSIDs.bssid) + { + vos_mem_free(pScanFilter->BSSIDs.bssid); + pScanFilter->BSSIDs.bssid = NULL; + } + if(pScanFilter->ChannelInfo.ChannelList) + { + vos_mem_free(pScanFilter->ChannelInfo.ChannelList); + pScanFilter->ChannelInfo.ChannelList = NULL; + } + if(pScanFilter->SSIDs.SSIDList) + { + vos_mem_free(pScanFilter->SSIDs.SSIDList); + pScanFilter->SSIDs.SSIDList = NULL; + } +} + + +void csrFreeRoamProfile(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + + if(pSession->pCurRoamProfile) + { + csrReleaseProfile(pMac, pSession->pCurRoamProfile); + vos_mem_free(pSession->pCurRoamProfile); + pSession->pCurRoamProfile = NULL; + } +} + + +void csrFreeConnectBssDesc(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + + if(pSession->pConnectBssDesc) + { + vos_mem_free(pSession->pConnectBssDesc); + pSession->pConnectBssDesc = NULL; + } +} + + + +tSirResultCodes csrGetDisassocRspStatusCode( tSirSmeDisassocRsp *pSmeDisassocRsp ) +{ + tANI_U8 *pBuffer = (tANI_U8 *)pSmeDisassocRsp; + tANI_U32 ret; + + pBuffer += (sizeof(tANI_U16) + sizeof(tANI_U16) + sizeof(tSirMacAddr)); + /* tSirResultCodes is an enum, assuming is 32bit + If we cannot make this assumption, use copy memory */ + pal_get_U32( pBuffer, &ret ); + + return( ( tSirResultCodes )ret ); +} + + +tSirResultCodes csrGetDeAuthRspStatusCode( tSirSmeDeauthRsp *pSmeRsp ) +{ + tANI_U8 *pBuffer = (tANI_U8 *)pSmeRsp; + tANI_U32 ret; + + pBuffer += (sizeof(tANI_U16) + sizeof(tANI_U16) + sizeof(tANI_U8) +sizeof(tANI_U16)); + /* tSirResultCodes is an enum, assuming is 32bit + If we cannot make this assumption, use copy memory */ + pal_get_U32( pBuffer, &ret ); + + return( ( tSirResultCodes )ret ); +} + +tSirScanType csrGetScanType(tpAniSirGlobal pMac, tANI_U8 chnId) +{ + tSirScanType scanType = eSIR_PASSIVE_SCAN; + eNVChannelEnabledType channelEnabledType; + + channelEnabledType = vos_nv_getChannelEnabledState(chnId); + if( NV_CHANNEL_ENABLE == channelEnabledType) + { + scanType = eSIR_ACTIVE_SCAN; + } + return (scanType); +} + + +tANI_U8 csrToUpper( tANI_U8 ch ) +{ + tANI_U8 chOut; + + if ( ch >= 'a' && ch <= 'z' ) + { + chOut = ch - 'a' + 'A'; + } + else + { + chOut = ch; + } + return( chOut ); +} + + +tSirBssType csrTranslateBsstypeToMacType(eCsrRoamBssType csrtype) +{ + tSirBssType ret; + + switch(csrtype) + { + case eCSR_BSS_TYPE_INFRASTRUCTURE: + ret = eSIR_INFRASTRUCTURE_MODE; + break; + case eCSR_BSS_TYPE_IBSS: + case eCSR_BSS_TYPE_START_IBSS: + ret = eSIR_IBSS_MODE; + break; + case eCSR_BSS_TYPE_WDS_AP: + ret = eSIR_BTAMP_AP_MODE; + break; + case eCSR_BSS_TYPE_WDS_STA: + ret = eSIR_BTAMP_STA_MODE; + break; + case eCSR_BSS_TYPE_INFRA_AP: + ret = eSIR_INFRA_AP_MODE; + break; + case eCSR_BSS_TYPE_ANY: + default: + ret = eSIR_AUTO_MODE; + break; + } + + return (ret); +} + + +//This function use the parameters to decide the CFG value. +//CSR never sets WNI_CFG_DOT11_MODE_ALL to the CFG +//So PE should not see WNI_CFG_DOT11_MODE_ALL when it gets the CFG value +eCsrCfgDot11Mode csrGetCfgDot11ModeFromCsrPhyMode(tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tANI_BOOLEAN fProprietary) +{ + tANI_U32 cfgDot11Mode = eCSR_CFG_DOT11_MODE_ABG; + + switch(phyMode) + { + case eCSR_DOT11_MODE_11a: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + break; + case eCSR_DOT11_MODE_11b: + case eCSR_DOT11_MODE_11b_ONLY: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + break; + case eCSR_DOT11_MODE_11g: + case eCSR_DOT11_MODE_11g_ONLY: + if(pProfile && (CSR_IS_INFRA_AP(pProfile)) && (phyMode == eCSR_DOT11_MODE_11g_ONLY)) + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G_ONLY; + else + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + break; + case eCSR_DOT11_MODE_11n: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + break; + case eCSR_DOT11_MODE_11n_ONLY: + if(pProfile && CSR_IS_INFRA_AP(pProfile)) + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N_ONLY; + else + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + break; + case eCSR_DOT11_MODE_abg: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_ABG; + break; + case eCSR_DOT11_MODE_AUTO: + cfgDot11Mode = eCSR_CFG_DOT11_MODE_AUTO; + break; + +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + break; + case eCSR_DOT11_MODE_11ac_ONLY: + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC_ONLY; + } + else + { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + break; +#endif + default: + //No need to assign anything here + break; + } + + return (cfgDot11Mode); +} + + +eHalStatus csrSetRegulatoryDomain(tpAniSirGlobal pMac, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fRestart; + + if(pMac->scan.domainIdCurrent == domainId) + { + //no change + fRestart = eANI_BOOLEAN_FALSE; + } + else if( !pMac->roam.configParam.fEnforceDefaultDomain ) + { + pMac->scan.domainIdCurrent = domainId; + fRestart = eANI_BOOLEAN_TRUE; + } + else + { + //We cannot change the domain + status = eHAL_STATUS_CSR_WRONG_STATE; + fRestart = eANI_BOOLEAN_FALSE; + } + if(pfRestartNeeded) + { + *pfRestartNeeded = fRestart; + } + + return (status); +} + + +v_REGDOMAIN_t csrGetCurrentRegulatoryDomain(tpAniSirGlobal pMac) +{ + return (pMac->scan.domainIdCurrent); +} + + +eHalStatus csrGetRegulatoryDomainForCountry +( +tpAniSirGlobal pMac, +tANI_U8 *pCountry, +v_REGDOMAIN_t *pDomainId, +v_CountryInfoSource_t source +) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + VOS_STATUS vosStatus; + v_COUNTRYCODE_t countryCode; + v_REGDOMAIN_t domainId; + + if(pCountry) + { + countryCode[0] = pCountry[0]; + countryCode[1] = pCountry[1]; + vosStatus = vos_nv_getRegDomainFromCountryCode(&domainId, + countryCode, + source); + + if( VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + if( pDomainId ) + { + *pDomainId = domainId; + } + status = eHAL_STATUS_SUCCESS; + } + else + { + smsLog(pMac, LOGW, FL(" Couldn't find domain for country code %c%c"), pCountry[0], pCountry[1]); + status = eHAL_STATUS_INVALID_PARAMETER; + } + } + + return (status); +} + +//To check whether a country code matches the one in the IE +//Only check the first two characters, ignoring in/outdoor +//pCountry -- caller allocated buffer contain the country code that is checking against +//the one in pIes. It can be NULL. +//caller must provide pIes, it cannot be NULL +//This function always return TRUE if 11d support is not turned on. +tANI_BOOLEAN csrMatchCountryCode( tpAniSirGlobal pMac, tANI_U8 *pCountry, tDot11fBeaconIEs *pIes ) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE; + v_REGDOMAIN_t domainId = REGDOMAIN_COUNT; //This is init to invalid value + eHalStatus status; + + do + { + if( !csrIs11dSupported( pMac) ) + { + break; + } + if( !pIes ) + { + smsLog(pMac, LOGE, FL(" No IEs")); + break; + } + if( pMac->roam.configParam.fEnforceDefaultDomain || + pMac->roam.configParam.fEnforceCountryCodeMatch ) + { + //Make sure this country is recognizable + if( pIes->Country.present ) + { + status = csrGetRegulatoryDomainForCountry(pMac, + pIes->Country.country, + &domainId, COUNTRY_QUERY); + if( !HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetRegulatoryDomainForCountry(pMac, + pMac->scan.countryCode11d, + (v_REGDOMAIN_t *) &domainId, + COUNTRY_QUERY); + if( !HAL_STATUS_SUCCESS( status ) ) + { + fRet = eANI_BOOLEAN_FALSE; + break; + } + } + } + //check whether it is needed to enforce to the default regulatory domain first + if( pMac->roam.configParam.fEnforceDefaultDomain ) + { + if( domainId != pMac->scan.domainIdCurrent ) + { + fRet = eANI_BOOLEAN_FALSE; + break; + } + } + if( pMac->roam.configParam.fEnforceCountryCodeMatch ) + { + if( domainId >= REGDOMAIN_COUNT ) + { + fRet = eANI_BOOLEAN_FALSE; + break; + } + } + } + if( pCountry ) + { + tANI_U32 i; + + if( !pIes->Country.present ) + { + fRet = eANI_BOOLEAN_FALSE; + break; + } + // Convert the CountryCode characters to upper + for ( i = 0; i < WNI_CFG_COUNTRY_CODE_LEN - 1; i++ ) + { + pCountry[i] = csrToUpper( pCountry[i] ); + } + if (!vos_mem_compare(pIes->Country.country, pCountry, + WNI_CFG_COUNTRY_CODE_LEN - 1)) + { + fRet = eANI_BOOLEAN_FALSE; + break; + } + } + } while(0); + + return (fRet); +} + + +eHalStatus csrGetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamModifyProfileFields *pModifyProfileFields) +{ + + if(!pModifyProfileFields) + { + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pModifyProfileFields, + &pMac->roam.roamSession[sessionId].connectedProfile.modifyProfileFields, + sizeof(tCsrRoamModifyProfileFields)); + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus csrSetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamModifyProfileFields *pModifyProfileFields) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + vos_mem_copy(&pSession->connectedProfile.modifyProfileFields, + pModifyProfileFields, + sizeof(tCsrRoamModifyProfileFields)); + + return eHAL_STATUS_SUCCESS; +} + + + +/* --------------------------------------------------------------------------- + \fn csrGetSupportedCountryCode + \brief this function is to get a list of the country code current being supported + \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return, + this has the country code list. 3 bytes for each country code. This may be NULL if + caller wants to know the needed bytes. + \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return, + this contains the length of the data in pBuf + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus csrGetSupportedCountryCode(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U32 *pbLen) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus; + v_SIZE_t size = (v_SIZE_t)*pbLen; + + vosStatus = vos_nv_getSupportedCountryCode( pBuf, &size, 1 ); + /* Either way, return the value back */ + *pbLen = (tANI_U32)size; + + //If pBuf is NULL, caller just want to get the size, consider it success + if(pBuf) + { + if( VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + tANI_U32 i, n = *pbLen / 3; + + for( i = 0; i < n; i++ ) + { + pBuf[i*3 + 2] = ' '; + } + } + else + { + status = eHAL_STATUS_FAILURE; + } + } + + return (status); +} + + + +//Upper layer to get the list of the base channels to scan for passively 11d info from csr +eHalStatus csrScanGetBaseChannels( tpAniSirGlobal pMac, tCsrChannelInfo * pChannelInfo ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + + do + { + + if(!pMac->scan.baseChannels.numChannels || !pChannelInfo) + { + break; + } + pChannelInfo->ChannelList = vos_mem_malloc(pMac->scan.baseChannels.numChannels); + if ( NULL == pChannelInfo->ChannelList ) + { + smsLog( pMac, LOGE, FL("csrScanGetBaseChannels: fail to allocate memory") ); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(pChannelInfo->ChannelList, + pMac->scan.baseChannels.channelList, + pMac->scan.baseChannels.numChannels); + pChannelInfo->numOfChannels = pMac->scan.baseChannels.numChannels; + + }while(0); + + return ( status ); +} + + +tANI_BOOLEAN csrIsSetKeyAllowed(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tANI_BOOLEAN fRet = eANI_BOOLEAN_TRUE; + tCsrRoamSession *pSession; + + pSession =CSR_GET_SESSION(pMac, sessionId); + + /*This condition is not working for infra state. When infra is in not-connected state + * the pSession->pCurRoamProfile is NULL. And this function returns TRUE, that is incorrect. + * Since SAP requires to set key without any BSS started, it needs this condition to be met. + * In other words, this function is useless. + * The current work-around is to process setcontext_rsp and removekey_rsp no matter what the + * state is. + */ + smsLog( pMac, LOG2, FL(" is not what it intends to. Must be revisit or removed") ); + if( (NULL == pSession) || + ( csrIsConnStateDisconnected( pMac, sessionId ) && + (pSession->pCurRoamProfile != NULL) && + (!(CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) ) + ) + { + fRet = eANI_BOOLEAN_FALSE; + } + + return ( fRet ); +} + +//no need to acquire lock for this basic function +tANI_U16 sme_ChnToFreq(tANI_U8 chanNum) +{ + int i; + + for (i = 0; i < NUM_RF_CHANNELS; i++) + { + if (rfChannels[i].channelNum == chanNum) + { + return rfChannels[i].targetFreq; + } + } + + return (0); +} + +/* Disconnect all active sessions by sending disassoc. This is mainly used to disconnect the remaining session when we + * transition from concurrent sessions to a single session. The use case is Infra STA and wifi direct multiple sessions are up and + * P2P session is removed. The Infra STA session remains and should resume BMPS if BMPS is enabled by default. However, there + * are some issues seen with BMPS resume during this transition and this is a workaround which will allow the Infra STA session to + * disconnect and auto connect back and enter BMPS this giving the same effect as resuming BMPS + */ + +//Remove this code once SLM_Sessionization is supported +//BMPS_WORKAROUND_NOT_NEEDED +void csrDisconnectAllActiveSessions(tpAniSirGlobal pMac) +{ + tANI_U8 i; + + /* Disconnect all the active sessions */ + for (i=0; i 0; i--) + { + pChannelList[i] = pChannelList[i-1]; + } + + // Now add the NEW channel...at the front + pChannelList[0] = channel; + + return eHAL_STATUS_SUCCESS; +} +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * csr_diag_event_report() - send PE diag event + * @pmac: pointer to global MAC context. + * @event_typev: sub event type for DIAG event. + * @status: status of the event + * @reasoncode: reasoncode for the given status + * + * This function is called to send diag event + * + * Return: NA + */ + +void csr_diag_event_report(tpAniSirGlobal pmac, uint16_t event_type, + uint16_t status, uint16_t reasoncode) +{ + tSirMacAddr nullbssid = { 0, 0, 0, 0, 0, 0 }; + WLAN_VOS_DIAG_EVENT_DEF(diag_event, vos_event_wlan_pe_payload_type); + + vos_mem_set(&diag_event, sizeof(vos_event_wlan_pe_payload_type), 0); + + vos_mem_copy(diag_event.bssid, nullbssid, sizeof(tSirMacAddr)); + diag_event.sme_state = (tANI_U16)pmac->lim.gLimSmeState; + diag_event.mlm_state = (tANI_U16)pmac->lim.gLimMlmState; + diag_event.event_type = event_type; + diag_event.status = status; + diag_event.reason_code = reasoncode; + + WLAN_VOS_DIAG_EVENT_REPORT(&diag_event, EVENT_WLAN_PE); + return; +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/nan/nan_Api.c b/drivers/staging/qcacld-2.0/CORE/SME/src/nan/nan_Api.c new file mode 100644 index 000000000000..26650ac40b0b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/nan/nan_Api.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include "sme_Api.h" +#include "smsDebug.h" +#include "csrInsideApi.h" +#include "smeInside.h" +#include "nan_Api.h" +#include "limApi.h" +#include "cfgApi.h" + +/****************************************************************************** + * Function: sme_NanRegisterCallback + * + * Description: + * This function gets called when HDD wants register nan rsp callback with + * sme layer. + * + * Args: + * hHal and callback which needs to be registered. + * + * Returns: + * void + *****************************************************************************/ +void sme_NanRegisterCallback(tHalHandle hHal, NanCallback callback) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL == hHal) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("hHal is not valid")); + return; + } + pMac = PMAC_STRUCT(hHal); + pMac->sme.nanCallback = callback; +} + +/****************************************************************************** + * Function: sme_NanRequest + * + * Description: + * This function gets called when HDD receives NAN vendor command + * from user space + * + * Args: + * Nan Request structure ptr + * + * Returns: + * VOS_STATUS + *****************************************************************************/ +VOS_STATUS sme_NanRequest(tpNanRequestReq input) +{ + vos_msg_t msg; + tpNanRequest data; + size_t data_len; + + data_len = sizeof(tNanRequest) + 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_FAULT; + } + + 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.type = WDA_NAN_REQUEST; + msg.reserved = 0; + msg.bodyptr = data; + + 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_NAN_REQUEST message to WDA")); + vos_mem_free(data); + return VOS_STATUS_SUCCESS; + } + + return VOS_STATUS_SUCCESS; +} + +/****************************************************************************** + * Function: sme_NanEvent + * + * Description: + * This callback function will be called when SME received eWNI_SME_NAN_EVENT + * event from WMA + * + * Args: + * hHal - HAL handle for device + * pMsg - Message body passed from WDA; includes NAN header + * + * Returns: + * VOS_STATUS +******************************************************************************/ +VOS_STATUS sme_NanEvent(tHalHandle hHal, void* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS status = VOS_STATUS_SUCCESS; + + if (NULL == pMsg) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("msg ptr is NULL")); + status = VOS_STATUS_E_FAILURE; + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + FL("SME: Received sme_NanEvent")); + if (pMac->sme.nanCallback) { + pMac->sme.nanCallback(pMac->hHdd, + (tSirNanEvent *)pMsg); + } + } + + return status; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c new file mode 100644 index 000000000000..d0d6df07cc79 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file oemDataApi.c + + Implementation for the OEM DATA REQ/RSP interfaces. +========================================================================== */ +#include "aniGlobal.h" +#include "oemDataApi.h" +#include "palApi.h" +#include "smeInside.h" +#include "smsDebug.h" + +#include "csrSupport.h" +#include "wlan_qct_tl.h" + +#include "vos_diag_core_log.h" +#include "vos_diag_core_event.h" + +/* --------------------------------------------------------------------------- + \fn oemData_OemDataReqOpen + \brief This function must be called before any API call to (OEM DATA REQ/RSP module) + \return eHalStatus + -------------------------------------------------------------------------------*/ + +eHalStatus oemData_OemDataReqOpen(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do + { + //initialize all the variables to null + vos_mem_set(&(pMac->oemData), sizeof(tOemDataStruct), 0); + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, "oemData_OemDataReqOpen: Cannot allocate memory for the timer function"); + break; + } + } while(0); + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oemData_OemDataReqClose + \brief This function must be called before closing the csr module + \return eHalStatus + -------------------------------------------------------------------------------*/ + +eHalStatus oemData_OemDataReqClose(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do + { + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, "oemData_OemDataReqClose: Failed in oemData_OemDataReqClose at StopTimers"); + break; + } + + //initialize all the variables to null + vos_mem_set(&(pMac->oemData), sizeof(tOemDataStruct), 0); + } while(0); + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn oemData_ReleaseOemDataReqCommand + \brief This function removes the oemDataCommand from the active list and + and frees up any memory occupied by this + \return eHalStatus + -------------------------------------------------------------------------------*/ +void oemData_ReleaseOemDataReqCommand(tpAniSirGlobal pMac, tSmeCmd *pOemDataCmd, eOemDataReqStatus oemDataReqStatus) +{ + + //First take this command out of the active list + if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, &pOemDataCmd->Link, LL_ACCESS_LOCK)) + { + vos_mem_set(&(pOemDataCmd->u.oemDataCmd), sizeof(tOemDataCmd), 0); + + /* Now put this command back on the available command list */ + smeReleaseCommand(pMac, pOemDataCmd); + } + else + { + smsLog(pMac, LOGE, "OEM_DATA: **************** oemData_ReleaseOemDataReqCommand cannot release the command"); + } +} + +/* --------------------------------------------------------------------------- + \fn oemData_OemDataReq + \brief Request an OEM DATA RSP + \param sessionId - Id of session to be used + \param pOemDataReqID - pointer to an object to get back the request ID + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus oemData_OemDataReq(tHalHandle hHal, + tANI_U8 sessionId, + tOemDataReqConfig *oemDataReqConfig, + tANI_U32 *pOemDataReqID) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tSmeCmd *pOemDataCmd = NULL; + + do + { + if( !CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = eHAL_STATUS_FAILURE; + break; + } + + pMac->oemData.oemDataReqConfig.sessionId = sessionId; + pMac->oemData.oemDataReqID = *(pOemDataReqID); + + vos_mem_copy((v_VOID_t*)(pMac->oemData.oemDataReqConfig.oemDataReq), + (v_VOID_t*)(oemDataReqConfig->oemDataReq), + OEM_DATA_REQ_SIZE); + + pMac->oemData.oemDataReqActive = eANI_BOOLEAN_FALSE; + + pOemDataCmd = smeGetCommandBuffer(pMac); + + //fill up the command before posting it. + if(pOemDataCmd) + { + pOemDataCmd->command = eSmeCommandOemDataReq; + pOemDataCmd->u.oemDataCmd.oemDataReqID = pMac->oemData.oemDataReqID; + + //set the oem data request + pOemDataCmd->u.oemDataCmd.oemDataReq.sessionId = pMac->oemData.oemDataReqConfig.sessionId; + vos_mem_copy((v_VOID_t*)(pOemDataCmd->u.oemDataCmd.oemDataReq.oemDataReq), + (v_VOID_t*)(pMac->oemData.oemDataReqConfig.oemDataReq), + OEM_DATA_REQ_SIZE); + } + else + { + status = eHAL_STATUS_FAILURE; + break; + } + + //now queue this command in the sme command queue + //Here since this is not interacting with the csr just push the command + //into the sme queue. Also push this command with the normal priority + smePushCommand(pMac, pOemDataCmd, eANI_BOOLEAN_FALSE); + + } while(0); + + if(!HAL_STATUS_SUCCESS(status) && pOemDataCmd) + { + oemData_ReleaseOemDataReqCommand(pMac, pOemDataCmd, eOEM_DATA_REQ_FAILURE); + pMac->oemData.oemDataReqActive = eANI_BOOLEAN_FALSE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oemData_SendMBOemDataReq + \brief Request an OEM DATA REQ to be passed down to PE + \param pMac: + \param pOemDataReq: Pointer to the oem data request + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus oemData_SendMBOemDataReq(tpAniSirGlobal pMac, tOemDataReq *pOemDataReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirOemDataReq* pMsg; + tANI_U16 msgLen; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pOemDataReq->sessionId ); + + smsLog(pMac, LOGW, "OEM_DATA: entering Function %s", __func__); + + msgLen = (tANI_U16)(sizeof(tSirOemDataReq)); + + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(HAL_STATUS_SUCCESS(status)) + { + vos_mem_set(pMsg, msgLen, 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_OEM_DATA_REQ); + pMsg->messageLen = pal_cpu_to_be16(msgLen); + vos_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr, sizeof(tSirMacAddr) ); + vos_mem_copy(pMsg->oemDataReq, pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE); + smsLog(pMac, LOGW, "OEM_DATA: sending message to pe%s", __func__); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + + smsLog(pMac, LOGW, "OEM_DATA: exiting Function %s", __func__); + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oemData_ProcessOemDataReqCommand + \brief This function is called by the smeProcessCommand when the case hits + eSmeCommandOemDataReq + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus oemData_ProcessOemDataReqCommand(tpAniSirGlobal pMac, tSmeCmd *pOemDataReqCmd) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + + //check if the system is in proper mode of operation for + //oem data req/rsp to be functional. Currently, concurrency is not + //supported and the driver must be operational only as + //STA for oem data req/rsp to be functional. We return an invalid + //mode flag if it is operational as any one of the following + //in any of the active sessions + //1. AP Mode + //2. IBSS Mode + //3. BTAMP Mode ... + + if(eHAL_STATUS_SUCCESS == oemData_IsOemDataReqAllowed(pMac)) + { + smsLog(pMac, LOG1, "%s: OEM_DATA REQ allowed in the current mode", __func__); + pMac->oemData.oemDataReqActive = eANI_BOOLEAN_TRUE; + status = oemData_SendMBOemDataReq(pMac, &(pOemDataReqCmd->u.oemDataCmd.oemDataReq)); + } + else + { + smsLog(pMac, LOG1, "%s: OEM_DATA REQ not allowed in the current mode", __func__); + status = eHAL_STATUS_FAILURE; + } + + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, LOG1, FL("OEM_DATA Failure, Release command")); + oemData_ReleaseOemDataReqCommand(pMac, pOemDataReqCmd, eOEM_DATA_REQ_INVALID_MODE); + pMac->oemData.oemDataReqActive = eANI_BOOLEAN_FALSE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_HandleOemDataRsp + \brief This function processes the oem data response obtained from the PE + \param pMsg - Pointer to the pSirOemDataRsp + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_HandleOemDataRsp(tHalHandle hHal, tANI_U8* pMsg) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tSirOemDataRsp* pOemDataRsp = NULL; + tANI_U32 *msgSubType; + + pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG1, "%s: OEM_DATA Entering", __func__); + + do + { + if(pMsg == NULL) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + break; + } + + /* In this case, there can be multiple OEM Data Responses for one + * OEM Data request, SME does not peek into data response so SME + * can not know which response is the last one. So SME clears active + * request command on receiving first response and thereafter SME + * passes each subsequent response to upper user layer. + */ + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandOemDataReq == pCommand->command) + { + if (csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) + { + vos_mem_set(&(pCommand->u.oemDataCmd), + sizeof(tOemDataCmd), 0); + smeReleaseCommand(pMac, pCommand); + } + } + } + + pOemDataRsp = (tSirOemDataRsp *)pMsg; + + /* check if message is to be forwarded to oem application or not */ + msgSubType = (tANI_U32 *) (&pOemDataRsp->oemDataRsp[0]); + if (*msgSubType != OEM_MESSAGE_SUBTYPE_INTERNAL) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: calling send_oem_data_rsp_msg, msgSubType(0x%x)", + __func__, *msgSubType); + send_oem_data_rsp_msg(sizeof(tOemDataRsp), + &pOemDataRsp->oemDataRsp[0]); + } + else + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: received internal oem data resp, msgSubType (0x%x)", + __func__, *msgSubType); + } while(0); + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oemData_IsOemDataReqAllowed + \brief This function checks if OEM DATA REQs can be performed in the + current driver state + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus oemData_IsOemDataReqAllowed(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U32 sessionId; + + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + { + if(CSR_IS_SESSION_VALID(pMac, sessionId)) + { + //co-exist with IBSS or BT-AMP mode is not supported + if(csrIsConnStateIbss(pMac, sessionId) || csrIsBTAMP(pMac, sessionId) ) + { + //co-exist with IBSS or BT-AMP mode is not supported + smsLog(pMac, LOGW, "OEM DATA REQ is not allowed due to IBSS|BTAMP exist in session %d", sessionId); + status = eHAL_STATUS_CSR_WRONG_STATE; + break; + } + } + } + + smsLog(pMac, LOG1, "Exiting oemData_IsOemDataReqAllowed with status %d", status); + + return (status); +} + +#endif /*FEATURE_OEM_DATA_SUPPORT*/ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c b/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c new file mode 100644 index 000000000000..cd26f5002603 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + + +#include "sme_Api.h" +#include "smsDebug.h" +#include "csrInsideApi.h" +#include "smeInside.h" +#include "p2p_Api.h" +#include "limApi.h" +#include "cfgApi.h" + + +eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd); + +/** + * csr_release_roc_req_cmd() - Release the command + * @mac_ctx: Global MAC Context + * + * Release the remain on channel request command from the queue + * + * Return: None + */ +void csr_release_roc_req_cmd(tpAniSirGlobal mac_ctx) +{ + tListElem *entry = NULL; + tSmeCmd *cmd = NULL; + + entry = csrLLPeekHead(&mac_ctx->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (entry) { + cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (eSmeCommandRemainOnChannel == cmd->command) { + remainOnChanCallback callback = + cmd->u.remainChlCmd.callback; + /* process the msg */ + if (callback) + callback(mac_ctx, + cmd->u.remainChlCmd.callbackCtx, 0); + smsLog(mac_ctx, LOGE, + FL("Remove RoC Request from Active Cmd List")); + /* Now put this cmd back on the avilable command list */ + if (csrLLRemoveEntry(&mac_ctx->sme.smeCmdActiveList, + entry, LL_ACCESS_LOCK)) + smeReleaseCommand(mac_ctx, cmd); + } + } +} + +/*------------------------------------------------------------------ + * + * handle SME remain on channel request. + * + *------------------------------------------------------------------*/ + +eHalStatus p2pProcessRemainOnChannelCmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tSirRemainOnChnReq* pMsg; + tANI_U32 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, p2pRemainonChn->sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), p2pRemainonChn->sessionId); + goto error; + } + + + if(!pSession->sessionActive) + { + smsLog(pMac, LOGE, FL(" session %d is invalid or listen is disabled "), + p2pRemainonChn->sessionId); + goto error; + } + len = sizeof(tSirRemainOnChnReq) + pMac->p2pContext.probeRspIeLength; + + if( len > 0xFFFF ) + { + /*In coming len for Msg is more then 16bit value*/ + smsLog(pMac, LOGE, FL(" Message length is very large, %d"), + len); + goto error; + } + + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + goto error; + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s call", __func__); + vos_mem_set(pMsg, sizeof(tSirRemainOnChnReq), 0); + pMsg->messageType = eWNI_SME_REMAIN_ON_CHANNEL_REQ; + pMsg->length = (tANI_U16)len; + vos_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr, sizeof(tSirMacAddr)); + pMsg->chnNum = p2pRemainonChn->u.remainChlCmd.chn; + pMsg->phyMode = p2pRemainonChn->u.remainChlCmd.phyMode; + pMsg->duration = p2pRemainonChn->u.remainChlCmd.duration; + pMsg->sessionId = p2pRemainonChn->sessionId; + pMsg->isProbeRequestAllowed = p2pRemainonChn->u.remainChlCmd.isP2PProbeReqAllowed; + if( pMac->p2pContext.probeRspIeLength ) + vos_mem_copy((void *)pMsg->probeRspIe, (void *)pMac->p2pContext.probeRspIe, + pMac->p2pContext.probeRspIeLength); + status = palSendMBMessage(pMac->hHdd, pMsg); + } +error: + if (eHAL_STATUS_FAILURE == status) + csr_release_roc_req_cmd(pMac); + return status; +} + + +/*------------------------------------------------------------------ + * + * handle LIM remain on channel rsp: Success/failure. + * + *------------------------------------------------------------------*/ + +eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tANI_BOOLEAN fFound; + tSirSmeRsp *pRsp = (tSirSmeRsp *)pMsg; + + if (pMac->fP2pListenOffload) + pEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK); + else + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if( pEntry ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( eSmeCommandRemainOnChannel == pCommand->command ) + { + remainOnChanCallback callback = pCommand->u.remainChlCmd.callback; + /* process the msg */ + if( callback ) + callback(pMac, pCommand->u.remainChlCmd.callbackCtx, + pRsp->statusCode); + + if (pMac->fP2pListenOffload) + { + fFound = csrLLRemoveEntry( &pMac->sme.smeScanCmdActiveList, + pEntry, LL_ACCESS_LOCK); + } + else + { + fFound = csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK); + } + + if (fFound) + { + /* Now put this command back on the available command list */ + smeReleaseCommand(pMac, pCommand); + } + smeProcessPendingQueue( pMac ); + } + } + return status; +} + + +/*------------------------------------------------------------------ + * + * Handle the Mgmt frm ind from LIM and forward to HDD. + * + *------------------------------------------------------------------*/ + +eHalStatus sme_mgmtFrmInd( tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = {0}; + tANI_U8 i = 0; + tANI_U32 SessionId = pSmeMgmtFrm->sessionId; + + pRoamInfo.nFrameLength = pSmeMgmtFrm->mesgLen - sizeof(tSirSmeMgmtFrameInd); + pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; + pRoamInfo.frameType = pSmeMgmtFrm->frameType; + pRoamInfo.rxChan = pSmeMgmtFrm->rxChan; + pRoamInfo.rxRssi = pSmeMgmtFrm->rxRssi; + if(CSR_IS_SESSION_ANY(SessionId)) + { + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + if(CSR_IS_SESSION_VALID(pMac, i)) + { + SessionId = i; + break; + } + } + } + + if (i == CSR_ROAM_SESSION_MAX) { + smsLog(pMac, LOGE, FL("No valid sessions found.")); + return eHAL_STATUS_FAILURE; + } + /* forward the mgmt frame to HDD */ + csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_INDICATE_MGMT_FRAME, 0); + + return status; +} + + +/*------------------------------------------------------------------ + * + * Handle the remain on channel ready indication from PE + * + *------------------------------------------------------------------*/ + +eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamInfo RoamInfo; + + if (pMac->fP2pListenOffload) + pEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK); + else + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + + if( pEntry ) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if( eSmeCommandRemainOnChannel == pCommand->command ) + { + + /* forward the indication to HDD */ + RoamInfo.pRemainCtx = pCommand->u.remainChlCmd.callbackCtx; + csrRoamCallCallback(pMac, ((tSirSmeRsp*)pMsg)->sessionId, &RoamInfo, + 0, eCSR_ROAM_REMAIN_CHAN_READY, 0); + } + } + + return status; +} + + +eHalStatus sme_sendActionCnf( tHalHandle hHal, tANI_U8* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo RoamInfo; + tSirSmeRsp* pSmeRsp = (tSirSmeRsp*)pMsg; + + /* forward the indication to HDD */ + //RoamInfo can be passed as NULL....todo + csrRoamCallCallback(pMac, pSmeRsp->sessionId, &RoamInfo, 0, + eCSR_ROAM_SEND_ACTION_CNF, + (pSmeRsp->statusCode == eSIR_SME_SUCCESS) ? 0: + eCSR_ROAM_RESULT_SEND_ACTION_FAIL); + return status; +} + + + + +eHalStatus sme_p2pOpen( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + //If static structure is too big, Need to change this function to allocate memory dynamically + vos_mem_zero(&pMac->p2pContext, sizeof( tp2pContext )); + + if(!HAL_STATUS_SUCCESS(status)) + { + sme_p2pClose(hHal); + } + + return status; +} + + +eHalStatus p2pStop( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if( pMac->p2pContext.probeRspIe ) + { + vos_mem_free(pMac->p2pContext.probeRspIe); + pMac->p2pContext.probeRspIe = NULL; + } + + pMac->p2pContext.probeRspIeLength = 0; + + return eHAL_STATUS_SUCCESS; +} + + +eHalStatus sme_p2pClose( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if( pMac->p2pContext.probeRspIe ) + { + vos_mem_free(pMac->p2pContext.probeRspIe); + pMac->p2pContext.probeRspIe = NULL; + } + + pMac->p2pContext.probeRspIeLength = 0; + + return eHAL_STATUS_SUCCESS; +} + + +tSirRFBand GetRFBand(tANI_U8 channel) +{ + if ((channel >= SIR_11A_CHANNEL_BEGIN) && + (channel <= SIR_11A_CHANNEL_END)) + return SIR_BAND_5_GHZ; + + if ((channel >= SIR_11B_CHANNEL_BEGIN) && + (channel <= SIR_11B_CHANNEL_END)) + return SIR_BAND_2_4_GHZ; + + return SIR_BAND_UNKNOWN; +} + +/* --------------------------------------------------------------------------- + + \fn p2pRemainOnChannel + \brief API to post the remain on channel command. + \param hHal - The handle returned by macOpen. + \param sessinId - HDD session ID. + \param channel - Channel to remain on channel. + \param duration - Duration for which we should remain on channel + \param callback - callback function. + \param pContext - argument to the callback function + \return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus p2pRemainOnChannel(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 channel, tANI_U32 duration, + remainOnChanCallback callback, + void *pContext, tANI_U8 isP2PProbeReqAllowed + ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *pRemainChlCmd = NULL; + tANI_U32 phyMode; + + pRemainChlCmd = smeGetCommandBuffer(pMac); + if(pRemainChlCmd == NULL) + return eHAL_STATUS_FAILURE; + + if (SIR_BAND_5_GHZ == GetRFBand(channel)) + { + phyMode = WNI_CFG_PHY_MODE_11A; + } + else + { + phyMode = WNI_CFG_PHY_MODE_11G; + } + + cfgSetInt(pMac, WNI_CFG_PHY_MODE, phyMode); + + do + { + /* call set in context */ + pRemainChlCmd->command = eSmeCommandRemainOnChannel; + pRemainChlCmd->sessionId = sessionId; + pRemainChlCmd->u.remainChlCmd.chn = channel; + pRemainChlCmd->u.remainChlCmd.duration = duration; + pRemainChlCmd->u.remainChlCmd.isP2PProbeReqAllowed = isP2PProbeReqAllowed; + pRemainChlCmd->u.remainChlCmd.callback = callback; + pRemainChlCmd->u.remainChlCmd.callbackCtx = pContext; + + //Put it at the head of the Q if we just finish finding the peer and ready to send a frame + status = csrQueueSmeCommand(pMac, pRemainChlCmd, eANI_BOOLEAN_FALSE); + } while(0); + + smsLog(pMac, LOGW, "exiting function %s", __func__); + + return(status); +} + +eHalStatus p2pSendAction(tHalHandle hHal, tANI_U8 sessionId, + const tANI_U8 *pBuf, tANI_U32 len, tANI_U16 wait, tANI_BOOLEAN noack) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirMbMsgP2p *pMsg; + tANI_U16 msgLen; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + " %s sends action frame", __func__); + msgLen = (tANI_U16)((sizeof( tSirMbMsg )) + len); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_SEND_ACTION_FRAME_IND); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + pMsg->sessionId = sessionId; + pMsg->noack = noack; + pMsg->wait = (tANI_U16)wait; + vos_mem_copy(pMsg->data, pBuf, len); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + + return( status ); +} + +eHalStatus p2pCancelRemainOnChannel(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirMbMsgP2p *pMsg; + tANI_U16 msgLen; + + //Need to check session ID to support concurrency + + msgLen = (tANI_U16)(sizeof( tSirMbMsg )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_ABORT_REMAIN_ON_CHAN_IND); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + pMsg->sessionId = sessionId; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + + return( status ); +} + +eHalStatus p2pSetPs(tHalHandle hHal, tP2pPsConfig *pNoA) +{ + tpP2pPsConfig pNoAParam; + tSirMsgQ msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pNoAParam = vos_mem_malloc(sizeof(tP2pPsConfig)); + if ( NULL == pNoAParam ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pNoAParam, sizeof(tP2pPsConfig), 0); + vos_mem_copy(pNoAParam, pNoA, sizeof(tP2pPsConfig)); + msg.type = eWNI_SME_UPDATE_NOA; + msg.bodyval = 0; + msg.bodyptr = pNoAParam; + limPostMsgApi(pMac, &msg); + } + return status; +} + + +eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd) +{ + tpP2pPsConfig pNoA; + tSirMsgQ msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + + pNoA = vos_mem_malloc(sizeof(tP2pPsConfig)); + if ( NULL == pNoA ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pNoA, sizeof(tP2pPsConfig), 0); + pNoA->opp_ps = pNoACmd->u.NoACmd.NoA.opp_ps; + pNoA->ctWindow = pNoACmd->u.NoACmd.NoA.ctWindow; + pNoA->duration = pNoACmd->u.NoACmd.NoA.duration; + pNoA->interval = pNoACmd->u.NoACmd.NoA.interval; + pNoA->count = pNoACmd->u.NoACmd.NoA.count; + pNoA->single_noa_duration = pNoACmd->u.NoACmd.NoA.single_noa_duration; + pNoA->psSelection = pNoACmd->u.NoACmd.NoA.psSelection; + pNoA->sessionid = pNoACmd->u.NoACmd.NoA.sessionid; + msg.type = eWNI_SME_UPDATE_NOA; + msg.bodyval = 0; + msg.bodyptr = pNoA; + limPostMsgApi(pMac, &msg); + } + return status; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmc.c b/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmc.c new file mode 100644 index 000000000000..b9d31e5848af --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmc.c @@ -0,0 +1,3640 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: pmc.c +* +* Description: + Power Management Control (PMC) processing routines. +* + +* +* +******************************************************************************/ + +#include "palTypes.h" +#include "aniGlobal.h" +#include "csrLinkList.h" +#include "csrApi.h" +#include "smeInside.h" +#include "sme_Api.h" +#include "smsDebug.h" +#include "pmc.h" +#include "wlan_qct_wda.h" +#include "wlan_ps_wow_diag.h" +#include "csrInsideApi.h" + +static void pmcProcessDeferredMsg( tpAniSirGlobal pMac ); + +/****************************************************************************** +* +* Name: pmcEnterLowPowerState +* +* Description: +* Have the device enter Low Power State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterLowPowerState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcEnterLowPowerState")); + + /* If already in Low Power State, just return. */ + if (pMac->pmc.pmcState == LOW_POWER) + return eHAL_STATUS_SUCCESS; + + /* Cancel any running timers. */ + if (vos_timer_stop(&pMac->pmc.hImpsTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot cancel IMPS timer")); + return eHAL_STATUS_FAILURE; + } + + pmcStopTrafficTimer(hHal); + + if (vos_timer_stop(&pMac->pmc.hExitPowerSaveTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot cancel exit power save mode timer")); + return eHAL_STATUS_FAILURE; + } + + /* Do all the callbacks. */ + pmcDoCallbacks(hHal, eHAL_STATUS_FAILURE); + + /* Change state. */ + pMac->pmc.pmcState = LOW_POWER; + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcExitLowPowerState +* +* Description: +* Have the device exit the Low Power State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcExitLowPowerState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcExitLowPowerState")); + + /* Must be in Low Power State if we are going to exit that state. */ + if (pMac->pmc.pmcState != LOW_POWER) + { + pmcLog(pMac, LOGE, FL("Cannot exit Low Power State if not in that state")); + return eHAL_STATUS_FAILURE; + } + + /* Both WLAN switches much be on to exit Low Power State. */ + if ((pMac->pmc.hwWlanSwitchState == ePMC_SWITCH_OFF) || (pMac->pmc.swWlanSwitchState == ePMC_SWITCH_OFF)) + return eHAL_STATUS_SUCCESS; + + /* Change state. */ + pMac->pmc.pmcState = FULL_POWER; + if(pmcShouldBmpsTimerRun(pMac)) + { + if (pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcEnterFullPowerState +* +* Description: +* Have the device enter the Full Power State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterFullPowerState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG1, FL("PMC state is %d"), pMac->pmc.pmcState); + /* Take action based on the current state. */ + switch (pMac->pmc.pmcState) + { + + /* Already in Full Power State. */ + case FULL_POWER: + break; + + /* Notify everyone that we are going to full power. + Change to Full Power State. */ + case REQUEST_FULL_POWER: + case REQUEST_IMPS: + case REQUEST_BMPS: + case REQUEST_STANDBY: + + /* Change state. */ + pMac->pmc.pmcState = FULL_POWER; + pMac->pmc.requestFullPowerPending = FALSE; + + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + + pmcProcessDeferredMsg( pMac ); + /* Do all the callbacks. */ + pmcDoCallbacks(hHal, eHAL_STATUS_SUCCESS); + + /* + * Update registered modules that we are entering Full Power. This is + * only way to inform modules if PMC exited a power save mode because + * of error conditions or if some other module requested full power. + */ + pmcDoDeviceStateUpdateCallbacks(hHal, FULL_POWER); + break; + + /* Cannot go directly to Full Power State from these states. */ + default: + pmcLog(pMac, LOGE, FL("Trying to enter Full Power State from state %d"), pMac->pmc.pmcState); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + pmcLog(pMac, LOG1, "PMC: Enter full power done"); + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcEnterRequestFullPowerState +* +* Description: +* Have the device enter the Request Full Power State. +* +* Parameters: +* hHal - HAL handle for device +* fullPowerReason - Reason code for requesting full power +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterRequestFullPowerState (tHalHandle hHal, tRequestFullPowerReason fullPowerReason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcEnterRequestFullPowerState")); + + /* Take action based on the current state of the device. */ + switch (pMac->pmc.pmcState) + { + + /* Should not request full power if already there. */ + case FULL_POWER: + pmcLog(pMac, LOGE, FL("Requesting Full Power State when already there")); + return eHAL_STATUS_FAILURE; + + /* Only power events can take device out of Low Power State. */ + case LOW_POWER: + pmcLog(pMac, LOGE, FL("Cannot request exit from Low Power State")); + return eHAL_STATUS_FAILURE; + + /* Cannot go directly to Request Full Power state from these states. + Record that this is pending and take care of it later. */ + case REQUEST_IMPS: + case REQUEST_START_UAPSD: + case REQUEST_STOP_UAPSD: + case REQUEST_STANDBY: + case REQUEST_BMPS: + case REQUEST_ENTER_WOWL: + case REQUEST_EXIT_WOWL: + pmcLog(pMac, LOGW, FL("Request for full power is being buffered. " + "Current state is %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), + pMac->pmc.pmcState); + + //Ignore the new reason if request for full power is already pending + if( !pMac->pmc.requestFullPowerPending ) + { + pMac->pmc.requestFullPowerPending = TRUE; + pMac->pmc.requestFullPowerReason = fullPowerReason; + } + return eHAL_STATUS_SUCCESS; + + /* Tell MAC to have device enter full power mode. */ + case IMPS: + if (pmcIssueCommand( pMac, 0, eSmeCommandExitImps, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + + /* Tell MAC to have device enter full power mode. */ + case BMPS: + { + tExitBmpsInfo exitBmpsInfo; + exitBmpsInfo.exitBmpsReason = fullPowerReason; + + if (pmcIssueCommand(hHal, 0, eSmeCommandExitBmps, &exitBmpsInfo, + sizeof(tExitBmpsInfo), FALSE) != eHAL_STATUS_SUCCESS) + { + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + } + /* Already in Request Full Power State. */ + case REQUEST_FULL_POWER: + return eHAL_STATUS_SUCCESS; + + /* Tell MAC to have device enter full power mode. */ + case STANDBY: + if (pmcIssueCommand(hHal, 0, eSmeCommandExitImps, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_EXIT_IMPS_REQ"); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; + + /* Tell MAC to have device exit UAPSD mode first */ + case UAPSD: + //Need to save the reason code here in case later on we need to exit BMPS as well + if (pmcIssueCommand(hHal, 0, eSmeCommandExitUapsd, &fullPowerReason, + sizeof(tRequestFullPowerReason), FALSE) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_EXIT_UAPSD_REQ"); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + + /* Tell MAC to have device exit WOWL mode first */ + case WOWL: + if (pmcIssueCommand(hHal, 0, eSmeCommandExitWowl, &fullPowerReason, + sizeof(tRequestFullPowerReason), FALSE) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGP, "PMC: failure to send message " + "eWNI_PMC_EXIT_WOWL_REQ"); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + + /* Cannot go directly to Request Full Power State from these states. */ + default: + pmcLog(pMac, LOGE, + FL("Trying to enter Request Full Power State from state %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), + pMac->pmc.pmcState); + + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } +} + + +/****************************************************************************** +* +* Name: pmcEnterRequestImpsState +* +* Description: +* Have the device enter the Request IMPS State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterRequestImpsState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcEnterRequestImpsState")); + + /* Can enter Request IMPS State only from Full Power State. */ + if (pMac->pmc.pmcState != FULL_POWER) + { + pmcLog(pMac, LOGE, FL("Trying to enter Request IMPS State from state %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Make sure traffic timer that triggers bmps entry is not running */ + pmcStopTrafficTimer(hHal); + + /* Tell MAC to have device enter IMPS mode. */ + if (pmcIssueCommand(hHal, 0, eSmeCommandEnterImps, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ"); + pMac->pmc.pmcState = FULL_POWER; + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + return eHAL_STATUS_FAILURE; + } + + pmcLog(pMac, LOG2, FL("eWNI_PMC_ENTER_IMPS_REQ sent to PE")); + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcEnterImpsState +* +* Description: +* Have the device enter the IMPS State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterImpsState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcEnterImpsState")); + + /* Can enter IMPS State only from Request IMPS State. */ + if (pMac->pmc.pmcState != REQUEST_IMPS) + { + pmcLog(pMac, LOGE, FL("Trying to enter IMPS State from state %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), pMac->pmc.pmcState); + + return eHAL_STATUS_FAILURE; + } + + /* Change state. */ + pMac->pmc.pmcState = IMPS; + + /* If we have a request for full power pending then we have to go + directly into full power. */ + if (pMac->pmc.requestFullPowerPending) + { + + /* Start exit IMPS sequence now. */ + return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason); + } + + /* Set timer to come out of IMPS.only if impsPeriod is non-Zero*/ + if(0 != pMac->pmc.impsPeriod) + { + if (vos_timer_start(&pMac->pmc.hImpsTimer, pMac->pmc.impsPeriod) != VOS_STATUS_SUCCESS) + { + PMC_ABORT; + pMac->pmc.ImpsReqTimerFailed = VOS_TRUE; + if (!(pMac->pmc.ImpsReqTimerfailCnt & 0xF)) + { + pMac->pmc.ImpsReqTimerfailCnt++; + pmcLog(pMac, LOGE, + FL("Cannot start IMPS timer, FailCnt - %d"), pMac->pmc.ImpsReqTimerfailCnt); + } + pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER); + return eHAL_STATUS_FAILURE; + } + if (pMac->pmc.ImpsReqTimerfailCnt) + { + pmcLog(pMac, LOGE, + FL("Start IMPS timer was failed %d times before success"), pMac->pmc.ImpsReqTimerfailCnt); + } + pMac->pmc.ImpsReqTimerfailCnt = 0; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcEnterRequestBmpsState +* +* Description: +* Have the device enter the Request BMPS State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterRequestBmpsState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcEnterRequestBmpsState")); + + /* Can enter Request BMPS State only from Full Power State. */ + if (pMac->pmc.pmcState != FULL_POWER) + { + pmcLog(pMac, LOGE, + FL("Trying to enter Request BMPS State from state %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), pMac->pmc.pmcState); + + return eHAL_STATUS_FAILURE; + } + + /* Stop Traffic timer if running. Note: timer could have expired because of possible + race conditions. So no need to check for errors. Just make sure timer is not running */ + pmcStopTrafficTimer(hHal); + + /* Tell MAC to have device enter BMPS mode. */ + if ( !pMac->pmc.bmpsRequestQueued ) + { + pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_TRUE; + if(pmcIssueCommand(hHal, 0, eSmeCommandEnterBmps, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ"); + pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE; + pMac->pmc.pmcState = FULL_POWER; + if(pmcShouldBmpsTimerRun(pMac)) + { + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + } + return eHAL_STATUS_FAILURE; + } + } + else + { + pmcLog(pMac, LOGE, "PMC: enter BMPS command already queued"); + //restart the timer if needed + if(pmcShouldBmpsTimerRun(pMac)) + { + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + } + return eHAL_STATUS_SUCCESS; + } + + pmcLog(pMac, LOGW, FL("eWNI_PMC_ENTER_BMPS_REQ sent to PE")); + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcEnterBmpsState +* +* Description: +* Have the device enter the BMPS State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterBmpsState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcEnterBmpsState")); + + /* Can enter BMPS State only from 5 states. */ + if (pMac->pmc.pmcState != REQUEST_BMPS && + pMac->pmc.pmcState != REQUEST_START_UAPSD && + pMac->pmc.pmcState != REQUEST_STOP_UAPSD && + pMac->pmc.pmcState != REQUEST_ENTER_WOWL && + pMac->pmc.pmcState != REQUEST_EXIT_WOWL) + { + pmcLog(pMac, LOGE, FL("Trying to enter BMPS State from state %d"), pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Change state. */ + pMac->pmc.pmcState = BMPS; + + /* + * Update registered modules that we are entering BMPS. This is + * only way to inform modules if PMC entered BMPS power save mode + * on its own because of traffic timer. + */ + pmcDoDeviceStateUpdateCallbacks(hHal, BMPS); + + /* If we have a request for full power pending then we have to go directly + into full power. */ + if (pMac->pmc.requestFullPowerPending) + { + + /* Start exit BMPS sequence now. */ + pmcLog(pMac, LOGW, FL("Pending Full Power request found on entering BMPS mode. " + "Start exit BMPS exit sequence")); + //Note: Reason must have been set when requestFullPowerPending flag was set. + pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason); + return eHAL_STATUS_SUCCESS; + } + + /*This should never happen ideally. WOWL and UAPSD not supported at the same time */ + if (pMac->pmc.wowlModeRequired && pMac->pmc.uapsdSessionRequired) + { + pmcLog(pMac, LOGW, FL("Both UAPSD and WOWL is required on entering BMPS mode. " + "UAPSD will be prioritized over WOWL")); + } + + /* Do we need Uapsd?*/ + if (pMac->pmc.uapsdSessionRequired) + { + pmcLog(pMac, LOGW, FL("UAPSD session is required on entering BMPS mode. " + "Start UAPSD entry sequence")); + pmcEnterRequestStartUapsdState(hHal); + return eHAL_STATUS_SUCCESS; + } + + /* Do we need WOWL?*/ + if (pMac->pmc.wowlModeRequired) + { + pmcLog(pMac, LOGW, FL("WOWL is required on entering BMPS mode. " + "Start WOWL entry sequence")); + pmcRequestEnterWowlState(hHal, &(pMac->pmc.wowlEnterParams)); + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcPowerSaveCheck +* +* Description: +* Check if device is allowed to enter a power save mode. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* TRUE - entry is allowed +* FALSE - entry is not allowed at this time +* +******************************************************************************/ +tANI_BOOLEAN pmcPowerSaveCheck (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpPowerSaveCheckEntry pPowerSaveCheckEntry; + tANI_BOOLEAN (*checkRoutine) (void *checkContext); + tANI_BOOLEAN bResult=FALSE; + + pmcLog(pMac, LOG2, FL("Entering pmcPowerSaveCheck")); + + /* Call the routines in the power save check routine list. If any + return FALSE, then we cannot go into power save mode. */ + pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE); + while (pEntry != NULL) + { + pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link); + checkRoutine = pPowerSaveCheckEntry->checkRoutine; + + /* If the checkRoutine is NULL for a particular entry, proceed with + * other entries in the list */ + if (NULL != checkRoutine) + { + if (!checkRoutine(pPowerSaveCheckEntry->checkContext)) + { + pmcLog(pMac, LOGE, FL("pmcPowerSaveCheck fail!")); + bResult = FALSE; + break; + } + else + { + bResult = TRUE; + } + } + pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE); + } + + return bResult; +} + + +/****************************************************************************** +* +* Name: pmcSendPowerSaveConfigMessage +* +* Description: +* Send a message to PE/MAC to configure the power saving modes. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - message successfully sent +* eHAL_STATUS_FAILURE - error while sending message +* +******************************************************************************/ +eHalStatus pmcSendPowerSaveConfigMessage (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirPowerSaveCfg powerSaveConfig; + + pmcLog(pMac, LOG2, FL("Entering pmcSendPowerSaveConfigMessage")); + + vos_mem_set(&(powerSaveConfig), sizeof(tSirPowerSaveCfg), 0); + + switch (pMac->pmc.bmpsConfig.forwardBeacons) + { + case ePMC_NO_BEACONS: + powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NONE; + break; + case ePMC_BEACONS_WITH_TIM_SET: + powerSaveConfig.beaconFwd = ePM_BEACON_FWD_TIM; + break; + case ePMC_BEACONS_WITH_DTIM_SET: + powerSaveConfig.beaconFwd = ePM_BEACON_FWD_DTIM; + break; + case ePMC_NTH_BEACON: + powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH; + powerSaveConfig.nthBeaconFwd = (tANI_U16)pMac->pmc.bmpsConfig.valueOfN; + break; + case ePMC_ALL_BEACONS: + powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH; + powerSaveConfig.nthBeaconFwd = 1; + break; + } + powerSaveConfig.fEnablePwrSaveImmediately = pMac->pmc.bmpsConfig.setPmOnLastFrame; + powerSaveConfig.fPSPoll = pMac->pmc.bmpsConfig.usePsPoll; + powerSaveConfig.fEnableBeaconEarlyTermination = + pMac->pmc.bmpsConfig.enableBeaconEarlyTermination; + powerSaveConfig.bcnEarlyTermWakeInterval = + pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval; + + /* setcfg for listenInterval. Make sure CFG is updated because PE reads this + from CFG at the time of assoc or reassoc */ + ccmCfgSetInt(pMac, WNI_CFG_LISTEN_INTERVAL, pMac->pmc.bmpsConfig.bmpsPeriod, + NULL, eANI_BOOLEAN_FALSE); + + if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS ) + { + //Wake up the chip first + eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_PWR_SAVE_CFG, + &powerSaveConfig, sizeof(tSirPowerSaveCfg) ); + + if( eHAL_STATUS_PMC_PENDING == status ) + { + return eHAL_STATUS_SUCCESS; + } + else + { + //either fail or already in full power + if( !HAL_STATUS_SUCCESS( status ) ) + { + return ( status ); + } + //else let it through because it is in full power state + } + } + /* Send a message so that FW System config is also updated and is in sync with + the CFG.*/ + if (pmcSendMessage(hHal, eWNI_PMC_PWR_SAVE_CFG, &powerSaveConfig, sizeof(tSirPowerSaveCfg)) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed")); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcSendMessage +* +* Description: +* Send a message to PE/MAC. +* +* Parameters: +* hHal - HAL handle for device +* messageType - message type to send +* pMessageData - pointer to message data +* messageSize - Size of the message data +* +* Returns: +* eHAL_STATUS_SUCCESS - message successfully sent +* eHAL_STATUS_FAILURE - error while sending message +* +******************************************************************************/ +eHalStatus pmcSendMessage (tpAniSirGlobal pMac, tANI_U16 messageType, void *pMessageData, tANI_U32 messageSize) +{ + tSirMbMsg *pMsg; + + pmcLog(pMac, LOG2, FL("Entering pmcSendMessage, message type %d"), messageType); + + /* Allocate and fill in message. */ + pMsg = vos_mem_malloc(WNI_CFG_MB_HDR_LEN + messageSize); + if ( NULL == pMsg ) + { + pmcLog(pMac, LOGE, FL("Cannot allocate memory for message")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + pMsg->type = messageType; + pMsg->msgLen = (tANI_U16) (WNI_CFG_MB_HDR_LEN + messageSize); + if (messageSize > 0) + { + vos_mem_copy(pMsg->data, pMessageData, messageSize); + } + + /* Send message. */ + if (palSendMBMessage(pMac->hHdd, pMsg) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot send message")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcDoCallbacks +* +* Description: +* Call the IMPS callback routine and the routines in the request full +* power callback routine list. +* +* Parameters: +* hHal - HAL handle for device +* callbackStatus - status to pass to the callback routines +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcDoCallbacks (tHalHandle hHal, eHalStatus callbackStatus) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpRequestFullPowerEntry pRequestFullPowerEntry; + + pmcLog(pMac, LOG2, FL("Enter")); + + /* Call IMPS callback routine. */ + if (pMac->pmc.impsCallbackRoutine != NULL) + { + pMac->pmc.impsCallbackRoutine(pMac->pmc.impsCallbackContext, callbackStatus); + pMac->pmc.impsCallbackRoutine = NULL; + } + + /* Call the routines in the request full power callback routine list. */ + while (NULL != (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, TRUE))) + { + pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link); + if (pRequestFullPowerEntry->callbackRoutine) + pRequestFullPowerEntry->callbackRoutine(pRequestFullPowerEntry->callbackContext, callbackStatus); + vos_mem_free(pRequestFullPowerEntry); + } + +} + + +/****************************************************************************** +* +* Name: pmcStartTrafficTimer +* +* Description: +* Start the timer used in Full Power State to measure traffic +* levels and determine when to enter BMPS. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - timer successfully started +* eHAL_STATUS_FAILURE - error while starting timer +* +******************************************************************************/ +eHalStatus pmcStartTrafficTimer (tHalHandle hHal, tANI_U32 expirationTime) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus; + + pmcLog(pMac, LOG2, FL("Entering pmcStartTrafficTimer")); + + vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, expirationTime); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + if( VOS_STATUS_E_ALREADY == vosStatus ) + { + //Consider this ok since the timer is already started. + pmcLog(pMac, LOGW, FL(" traffic timer is already started")); + } + else + { + pmcLog(pMac, LOGP, FL("Cannot start traffic timer")); + return eHAL_STATUS_FAILURE; + } + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcStopTrafficTimer +* +* Description: +* Cancels the timer (if running) used in Full Power State to measure traffic +* levels and determine when to enter BMPS. +* +* Parameters: +* hHal - HAL handle for device +* +* +******************************************************************************/ +void pmcStopTrafficTimer (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pmcLog(pMac, LOG2, FL("Entering pmcStopTrafficTimer")); + vos_timer_stop(&pMac->pmc.hTrafficTimer); +} + + +/****************************************************************************** +* +* Name: pmcImpsTimerExpired +* +* Description: +* Called when IMPS timer expires. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcImpsTimerExpired (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcImpsTimerExpired")); + + /* If timer expires and we are in a state other than IMPS State then something is wrong. */ + if (pMac->pmc.pmcState != IMPS) + { + pmcLog(pMac, LOGE, FL("Got IMPS timer expiration in state %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), pMac->pmc.pmcState); + + PMC_ABORT; + return; + } + + /* Start on the path of going back to full power. */ + pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER); +} + + +/****************************************************************************** +* +* Name: pmcTrafficTimerExpired +* +* Description: +* Called when traffic measurement timer expires. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcTrafficTimerExpired (tHalHandle hHal) +{ + + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus; + + pmcLog(pMac, LOG2, FL("BMPS Traffic timer expired")); + + /* If timer expires and we are in a state other than Full Power State then something is wrong. */ + if (pMac->pmc.pmcState != FULL_POWER) + { + pmcLog(pMac, LOGE, FL("Got traffic timer expiration in state %s (%d)"), + sme_PmcStatetoString(pMac->pmc.pmcState), pMac->pmc.pmcState); + + return; + } + + /* Until DHCP is not completed remain in power active */ + if(pMac->pmc.remainInPowerActiveTillDHCP) + { + pmcLog(pMac, LOG2, FL("BMPS Traffic Timer expired before DHCP completion ignore enter BMPS")); + pMac->pmc.remainInPowerActiveThreshold++; + if( pMac->pmc.remainInPowerActiveThreshold >= DHCP_REMAIN_POWER_ACTIVE_THRESHOLD) + { + pmcLog(pMac, LOGE, + FL("Remain in power active DHCP threshold reached FALLBACK to enable enter BMPS")); + /*FALLBACK: reset the flag to make BMPS entry possible*/ + pMac->pmc.remainInPowerActiveTillDHCP = FALSE; + pMac->pmc.remainInPowerActiveThreshold = 0; + } + //Activate the Traffic Timer again for entering into BMPS + vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) ) + { + pmcLog(pMac, LOGP, FL("Cannot re-start traffic timer")); + } + return; + } + + /* Clear remain in power active threshold */ + pMac->pmc.remainInPowerActiveThreshold = 0; + + /* Check if the timer should be running */ + if (!pmcShouldBmpsTimerRun(pMac)) + { + pmcLog(pMac, LOGE, FL("BMPS timer should not be running")); + return; + } + +#ifdef FEATURE_WLAN_TDLS + if (pMac->isTdlsPowerSaveProhibited) + { + pmcLog(pMac, LOGE, FL("TDLS peer(s) connected/discovery sent. Dont enter BMPS")); + return; + } +#endif + + if (pmcPowerSaveCheck(hHal)) + { + pmcLog(pMac, LOGW, FL("BMPS entry criteria satisfied. Requesting BMPS state")); + (void)pmcEnterRequestBmpsState(hHal); + } + else + { + /*Some module voted against Power Save. So timer should be restarted again to retry BMPS */ + pmcLog(pMac, LOGE, FL("Power Save check failed. Retry BMPS again later")); + //Since hTrafficTimer is a vos_timer now, we need to restart the timer here + vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) ) + { + pmcLog(pMac, LOGP, FL("Cannot start traffic timer")); + return; + } + } +} + + +/****************************************************************************** +* +* Name: pmcExitPowerSaveTimerExpired +* +* Description: +* Called when timer used to schedule a deferred power save mode exit expires. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcExitPowerSaveTimerExpired (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcExitPowerSaveTimerExpired")); + + /* Make sure process of exiting power save mode might hasn't already been started due to another trigger. */ + if (pMac->pmc.requestFullPowerPending) + + /* Start on the path of going back to full power. */ + pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason); +} + +/****************************************************************************** +* +* Name: pmcDoBmpsCallbacks +* +* Description: +* Call the registered BMPS callback routines because device is unable to +* enter BMPS state +* +* Parameters: +* hHal - HAL handle for device +* callbackStatus - Success or Failure. +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcDoBmpsCallbacks (tHalHandle hHal, eHalStatus callbackStatus) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpRequestBmpsEntry pRequestBmpsEntry; + + pmcLog(pMac, LOG2, "PMC: entering pmcDoBmpsCallbacks"); + + /* Call the routines in the request BMPS callback routine list. */ + csrLLLock(&pMac->pmc.requestBmpsList); + pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE); + while (pEntry != NULL) + { + pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link); + if (pRequestBmpsEntry->callbackRoutine) + pRequestBmpsEntry->callbackRoutine(pRequestBmpsEntry->callbackContext, + callbackStatus); + vos_mem_free(pRequestBmpsEntry); + pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE); + } + csrLLUnlock(&pMac->pmc.requestBmpsList); +} + + + + +/****************************************************************************** +* +* Name: pmcDoStartUapsdCallbacks +* +* Description: +* Call the registered UAPSD callback routines because device is unable to +* start UAPSD state +* +* Parameters: +* hHal - HAL handle for device +* callbackStatus - Success or Failure. +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcDoStartUapsdCallbacks (tHalHandle hHal, eHalStatus callbackStatus) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpStartUapsdEntry pStartUapsdEntry; + + pmcLog(pMac, LOG2, "PMC: entering pmcDoStartUapsdCallbacks"); + csrLLLock(&pMac->pmc.requestStartUapsdList); + /* Call the routines in the request start UAPSD callback routine list. */ + pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE); + while (pEntry != NULL) + { + pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link); + pStartUapsdEntry->callbackRoutine(pStartUapsdEntry->callbackContext, + callbackStatus); + vos_mem_free(pStartUapsdEntry); + pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE); + } + csrLLUnlock(&pMac->pmc.requestStartUapsdList); +} + +/****************************************************************************** +* +* Name: pmcEnterRequestStartUapsdState +* +* Description: +* Have the device enter the UAPSD State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterRequestStartUapsdState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_BOOL_t fFullPower = VOS_FALSE; //need to get back to full power state + + pmcLog(pMac, LOG2, "PMC: entering pmcEnterRequestStartUapsdState"); + + /* Can enter UAPSD State only from FULL_POWER or BMPS State. */ + switch (pMac->pmc.pmcState) + { + case FULL_POWER: + /* Check that entry into a power save mode is allowed at this time. */ + if (!pmcPowerSaveCheck(hHal)) + { + pmcLog(pMac, LOGW, "PMC: Power save check failed. UAPSD request " + "will be accepted and buffered"); + /* UAPSD mode will be attempted when we enter BMPS later */ + pMac->pmc.uapsdSessionRequired = TRUE; + /* Make sure the BMPS retry timer is running */ + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + break; + } + else + { + pMac->pmc.uapsdSessionRequired = TRUE; + //Check BTC state +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if( btcIsReadyForUapsd( pMac ) ) +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + { + /* Put device in BMPS mode first. This step should NEVER fail. + That is why no need to buffer the UAPSD request*/ + if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: Device in Full Power. Enter Request Bmps failed. " + "UAPSD request will be dropped "); + return eHAL_STATUS_FAILURE; + } + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + else + { + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + } +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + } + break; + + case BMPS: + //It is already in BMPS mode, check BTC state +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if( btcIsReadyForUapsd(pMac) ) +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + { + /* Tell MAC to have device enter UAPSD mode. */ + if (pmcIssueCommand(hHal, 0, eSmeCommandEnterUapsd, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_ENTER_BMPS_REQ"); + return eHAL_STATUS_FAILURE; + } + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + else + { + //Not ready for UAPSD at this time, save it first and wake up the chip + pmcLog(pMac, LOGE, " PMC state = %d",pMac->pmc.pmcState); + pMac->pmc.uapsdSessionRequired = TRUE; + /* While BTC traffic is going on, STA can be in BMPS + * and need not go to Full Power */ + //fFullPower = VOS_TRUE; + } +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + break; + + case REQUEST_START_UAPSD: +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if( !btcIsReadyForUapsd(pMac) ) + { + //BTC rejects UAPSD, bring it back to full power + fFullPower = VOS_TRUE; + } +#endif + break; + + case REQUEST_BMPS: + /* Buffer request for UAPSD mode. */ + pMac->pmc.uapsdSessionRequired = TRUE; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if( !btcIsReadyForUapsd(pMac) ) + { + //BTC rejects UAPSD, bring it back to full power + fFullPower = VOS_TRUE; + } +#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + break; + + default: + pmcLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d", + pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + if(fFullPower) + { + if( eHAL_STATUS_PMC_PENDING != pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER ) ) + { + //This is an error + pmcLog(pMac, LOGE, FL(" fail to request full power because BTC")); + } + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcEnterUapsdState +* +* Description: +* Have the device enter the UAPSD State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterUapsdState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcEnterUapsdState"); + + /* Can enter UAPSD State only from Request UAPSD State. */ + if (pMac->pmc.pmcState != REQUEST_START_UAPSD ) + { + pmcLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d", + pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Change state. */ + pMac->pmc.pmcState = UAPSD; + + /* + * Update registered modules that we are entering UAPSD. This is + * only way to inform modules if PMC resumed UAPSD power save mode + * on its own after full power mode. + */ + pmcDoDeviceStateUpdateCallbacks(hHal, UAPSD); + + /* If we have a request for full power pending then we have to go + directly into full power. */ + if (pMac->pmc.requestFullPowerPending) + { + /* Start exit UAPSD sequence now. */ + return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason); + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcEnterRequestStopUapsdState +* +* Description: +* Have the device Stop the UAPSD State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterRequestStopUapsdState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcEnterRequestStopUapsdState"); + + /* If already in REQUEST_STOP_UAPSD, simply return */ + if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD) + { + return eHAL_STATUS_SUCCESS; + } + + /* Can enter Request Stop UAPSD State only from UAPSD */ + if (pMac->pmc.pmcState != UAPSD) + { + pmcLog(pMac, LOGE, "PMC: trying to enter Request Stop UAPSD State from " + "state %d", pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Tell MAC to have device exit UAPSD mode. */ + if (pmcIssueCommand(hHal, 0, eSmeCommandExitUapsd, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_EXIT_UAPSD_REQ"); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcEnterRequestStandbyState +* +* Description: +* Have the device enter the Request STANDBY State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterRequestStandbyState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcEnterRequestStandbyState"); + + /* Can enter Standby State only from Full Power State. */ + if (pMac->pmc.pmcState != FULL_POWER) + { + pmcLog(pMac, LOGE, "PMC: trying to enter Standby State from " + "state %d", pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + // Stop traffic timer. Just making sure timer is not running + pmcStopTrafficTimer(hHal); + + /* Tell MAC to have device enter STANDBY mode. We are using the same message + as IMPS mode to avoid code changes in layer below (PE/HAL)*/ + if (pmcIssueCommand(hHal, 0, eSmeCommandEnterStandby, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_ENTER_IMPS_REQ"); + pMac->pmc.pmcState = FULL_POWER; + + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcEnterStandbyState +* +* Description: +* Have the device enter the STANDBY State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterStandbyState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcEnterStandbyState"); + + /* Can enter STANDBY State only from REQUEST_STANDBY State. */ + if (pMac->pmc.pmcState != REQUEST_STANDBY) + { + pmcLog(pMac, LOGE, "PMC: trying to enter STANDBY State from state %d", + pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Change state. */ + pMac->pmc.pmcState = STANDBY; + + /* If we have a request for full power pending then we have to go + directly into full power. */ + if (pMac->pmc.requestFullPowerPending) + { + /* Start exit STANDBY sequence now. */ + return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason); + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcDoStandbyCallbacks +* +* Description: +* Call the registered Standby callback routines +* +* Parameters: +* hHal - HAL handle for device +* callbackStatus - Success or Failure. +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcDoStandbyCallbacks (tHalHandle hHal, eHalStatus callbackStatus) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcDoStandbyCallbacks"); + + /* Call Standby callback routine. */ + if (pMac->pmc.standbyCallbackRoutine != NULL) + pMac->pmc.standbyCallbackRoutine(pMac->pmc.standbyCallbackContext, callbackStatus); + pMac->pmc.standbyCallbackRoutine = NULL; + pMac->pmc.standbyCallbackContext = NULL; +} + +/****************************************************************************** +* +* Name: pmcGetPmcState +* +* Description: +* Return the PMC state +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* tPmcState (one of IMPS, REQUEST_IMPS, BMPS, REQUEST_BMPS etc) +* +******************************************************************************/ +tPmcState pmcGetPmcState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->pmc.pmcState; +} + +const char* pmcGetPmcStateStr(tPmcState state) +{ + switch(state) + { + case STOPPED: + return "STOPPED"; + case FULL_POWER: + return "FULL_POWER"; + case LOW_POWER: + return "LOW_POWER"; + case IMPS: + return "IMPS"; + case BMPS: + return "BMPS"; + case UAPSD: + return "UAPSD"; + case STANDBY: + return "STANDBY"; + case REQUEST_IMPS: + return "REQUEST_IMPS"; + case REQUEST_BMPS: + return "REQUEST_BMPS"; + case REQUEST_START_UAPSD: + return "REQUEST_START_UAPSD"; + case REQUEST_STOP_UAPSD: + return "REQUEST_STOP_UAPSD"; + case REQUEST_FULL_POWER: + return "REQUEST_FULL_POWER"; + case REQUEST_STANDBY: + return "REQUEST_STANDBY"; + case REQUEST_ENTER_WOWL: + return "REQUEST_ENTER_WOWL"; + case REQUEST_EXIT_WOWL: + return "REQUEST_EXIT_WOWL"; + case WOWL: + return "WOWL"; + default: + break; + } + + return "UNKNOWN"; +} + +void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry; + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState); + + pmcLog(pMac, LOG2, FL("PMC - Update registered modules of new device " + "state: %s"), pmcGetPmcStateStr(state)); + + /* Call the routines in the update device state routine list. */ + pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE); + while (pEntry != NULL) + { + pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link); + callbackRoutine = pDeviceStateUpdateIndEntry->callbackRoutine; + callbackRoutine(pDeviceStateUpdateIndEntry->callbackContext, state); + pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE); + } +} + +/****************************************************************************** +* +* Name: pmcRequestEnterWowlState +* +* Description: +* Have the device enter the WOWL State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - WOWL mode will be entered +* eHAL_STATUS_FAILURE - WOWL mode cannot be entered +* +******************************************************************************/ +eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pmcLog(pMac, LOG2, "PMC: entering pmcRequestEnterWowlState"); + + if(pMac->psOffloadEnabled) + { + if (pmcIssueCommand(hHal, 0, eSmeCommandEnterWowl, wowlEnterParams, + sizeof(tSirSmeWowlEnterParams), FALSE) != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ"); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; + } + + switch (pMac->pmc.pmcState) + { + case FULL_POWER: + /* Put device in BMPS mode first. This step should NEVER fail. */ + if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: Device in Full Power. pmcEnterRequestBmpsState failed. " + "Cannot enter WOWL"); + return eHAL_STATUS_FAILURE; + } + break; + + case REQUEST_BMPS: + pmcLog(pMac, LOGW, "PMC: BMPS transaction going on. WOWL request " + "will be buffered"); + break; + + case BMPS: + case WOWL: + /* Tell MAC to have device enter WOWL mode. Note: We accept WOWL request + when we are in WOWL mode. This allows HDD to change WOWL configuration + without having to exit WOWL mode */ + if (pmcIssueCommand(hHal, 0, eSmeCommandEnterWowl, wowlEnterParams, + sizeof(tSirSmeWowlEnterParams), FALSE) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ"); + return eHAL_STATUS_FAILURE; + } + break; + + case REQUEST_ENTER_WOWL: + //Multiple enter WOWL requests at the same time are not accepted + pmcLog(pMac, LOGE, "PMC: Enter WOWL transaction already going on. New WOWL request " + "will be rejected"); + return eHAL_STATUS_FAILURE; + + case REQUEST_EXIT_WOWL: + pmcLog(pMac, LOGW, "PMC: Exit WOWL transaction going on. New WOWL request " + "will be buffered"); + break; + + default: + pmcLog(pMac, LOGE, "PMC: Trying to enter WOWL State from state %s", + pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcEnterWowlState +* +* Description: +* Have the device enter the WOWL State. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - changing state successful +* eHAL_STATUS_FAILURE - changing state not successful +* +******************************************************************************/ +eHalStatus pmcEnterWowlState (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcEnterWowlState"); + + /* Can enter WOWL State only from Request WOWL State. */ + if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL ) + { + pmcLog(pMac, LOGP, "PMC: trying to enter WOWL State from state %d", + pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Change state. */ + pMac->pmc.pmcState = WOWL; + + /* Clear the buffered command for WOWL */ + pMac->pmc.wowlModeRequired = FALSE; + + /* If we have a request for full power pending then we have to go + directly into full power. */ + if (pMac->pmc.requestFullPowerPending) + { + /* Start exit Wowl sequence now. */ + return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason); + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcRequestExitWowlState +* +* Description: +* Have the device exit WOWL State. +* +* Parameters: +* hHal - HAL handle for device +* wowlExitParams - Carries info on which smesession wowl exit is requested. + +* Returns: +* eHAL_STATUS_SUCCESS - Exit WOWL successful +* eHAL_STATUS_FAILURE - Exit WOWL unsuccessful +* +******************************************************************************/ +eHalStatus pmcRequestExitWowlState(tHalHandle hHal, + tpSirSmeWowlExitParams wowlExitParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcRequestExitWowlState"); + + if (pMac->psOffloadEnabled) + { + if (pmcIssueCommand(hHal, 0, eSmeCommandExitWowl, wowlExitParams, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ"); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; + } + + switch (pMac->pmc.pmcState) + { + case WOWL: + /* Tell MAC to have device exit WOWL mode. */ + if (pmcIssueCommand(hHal, 0, eSmeCommandExitWowl, NULL, 0, FALSE) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ"); + return eHAL_STATUS_FAILURE; + } + break; + + case REQUEST_ENTER_WOWL: + pmcLog(pMac, LOGP, "PMC: Rcvd exit WOWL even before enter WOWL was completed"); + return eHAL_STATUS_FAILURE; + + default: + pmcLog(pMac, LOGW, "PMC: Got exit WOWL in state %s. Nothing to do as already out of WOWL", + pmcGetPmcStateStr(pMac->pmc.pmcState)); + break; + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcDoEnterWowlCallbacks +* +* Description: +* Invoke Enter WOWL callbacks +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: None +* +******************************************************************************/ +void pmcDoEnterWowlCallbacks (tHalHandle hHal, eHalStatus callbackStatus) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, "PMC: entering pmcDoWowlCallbacks"); + + /* Call Wowl callback routine. */ + if (pMac->pmc.enterWowlCallbackRoutine != NULL) + pMac->pmc.enterWowlCallbackRoutine(pMac->pmc.enterWowlCallbackContext, callbackStatus); + + pMac->pmc.enterWowlCallbackRoutine = NULL; + pMac->pmc.enterWowlCallbackContext = NULL; +} + + +static void pmcProcessDeferredMsg( tpAniSirGlobal pMac ) +{ + tPmcDeferredMsg *pDeferredMsg; + tListElem *pEntry; + + while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_TRUE ) ) ) + { + pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link ); + switch (pDeferredMsg->messageType) + { + case eWNI_PMC_WOWL_ADD_BCAST_PTRN: + if (pDeferredMsg->size != sizeof(tSirWowlAddBcastPtrn)) + { + VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlAddBcastPtrn) ); + return; + } + + if (pmcSendMessage(pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN, + &pDeferredMsg->u.wowlAddPattern, sizeof(tSirWowlAddBcastPtrn)) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed")); + } + break; + + case eWNI_PMC_WOWL_DEL_BCAST_PTRN: + if (pDeferredMsg->size != sizeof(tSirWowlDelBcastPtrn)) + { + VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlDelBcastPtrn) ); + return; + } + if (pmcSendMessage(pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN, + &pDeferredMsg->u.wowlDelPattern, sizeof(tSirWowlDelBcastPtrn)) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed")); + } + break; + + case eWNI_PMC_PWR_SAVE_CFG: + if (pDeferredMsg->size != sizeof(tSirPowerSaveCfg)) + { + VOS_ASSERT( pDeferredMsg->size == sizeof(tSirPowerSaveCfg) ); + return; + } + if (pmcSendMessage(pMac, eWNI_PMC_PWR_SAVE_CFG, + &pDeferredMsg->u.powerSaveConfig, sizeof(tSirPowerSaveCfg)) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed")); + } + break; + + default: + pmcLog(pMac, LOGE, FL("unknown message (%d)"), pDeferredMsg->messageType); + break; + } + //Need to free the memory here + vos_mem_free(pDeferredMsg); + } //while +} + + +eHalStatus pmcDeferMsg( tpAniSirGlobal pMac, tANI_U16 messageType, void *pData, tANI_U32 size) +{ + tPmcDeferredMsg *pDeferredMsg; + eHalStatus status; + + pDeferredMsg = vos_mem_malloc(sizeof(tPmcDeferredMsg)); + if ( NULL == pDeferredMsg ) + { + pmcLog(pMac, LOGE, FL("Cannot allocate memory for callback context")); + return eHAL_STATUS_RESOURCES; + } + vos_mem_set(pDeferredMsg, sizeof(tPmcDeferredMsg), 0); + pDeferredMsg->messageType = messageType; + pDeferredMsg->size = (tANI_U16)size; + if( pData ) + { + vos_mem_copy(&pDeferredMsg->u.data, pData, size); + } + csrLLInsertTail( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE ); + //No callback is needed. The messages are put into deferred queue and be processed first + //when enter full power is complete. + status = pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER ); + if( eHAL_STATUS_PMC_PENDING != status ) + { + //either fail or already in full power + if( csrLLRemoveEntry( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE ) ) + { + vos_mem_free(pDeferredMsg); + } + if( !HAL_STATUS_SUCCESS( status ) ) + { + pmcLog(pMac, LOGE, FL("failed to request full power status = %d"), status); + } + } + + return (status); +} + +void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + if(!pCommand->u.pmcCmd.fReleaseWhenDone) + { + /* This is a normal command, put it back to the free list */ + pCommand->u.pmcCmd.size = 0; + smeReleaseCommand( pMac, pCommand ); + } + else + { + /* This is a specially allocated command due to out of command buffer. + free it. */ + vos_mem_free(pCommand); + } +} + + +//this function is used to abort a command where the normal processing of the command +//is terminated without going through the normal path. it is here to take care of callbacks for +//the command, if applicable. +void pmcAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping ) +{ + if( eSmePmcCommandMask & pCommand->command ) + { + if( !fStopping ) + { + switch( pCommand->command ) + { + case eSmeCommandEnterImps: + pmcLog(pMac, LOGE, FL("aborting request to enter IMPS")); + pmcEnterFullPowerState(pMac); + break; + + case eSmeCommandExitImps: + pmcLog(pMac, LOGE, FL("aborting request to exit IMPS ")); + pmcEnterFullPowerState(pMac); + break; + + case eSmeCommandEnterBmps: + pmcLog(pMac, LOGE, FL("aborting request to enter BMPS ")); + pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE; + pmcEnterFullPowerState(pMac); + pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE); + break; + + case eSmeCommandExitBmps: + pmcLog(pMac, LOGE, FL("aborting request to exit BMPS ")); + pmcEnterFullPowerState(pMac); + break; + + case eSmeCommandEnterUapsd: + pmcLog(pMac, LOGE, FL("aborting request to enter UAPSD ")); + //Since there is no retry for UAPSD, tell the requester here we are done with failure + pMac->pmc.uapsdSessionRequired = FALSE; + pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE); + break; + + case eSmeCommandExitUapsd: + pmcLog(pMac, LOGE, FL("aborting request to exit UAPSD ")); + break; + + case eSmeCommandEnterWowl: + pmcLog(pMac, LOGE, FL("aborting request to enter WOWL ")); + pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE); + break; + + case eSmeCommandExitWowl: + pmcLog(pMac, LOGE, FL("aborting request to exit WOWL ")); + break; + + case eSmeCommandEnterStandby: + pmcLog(pMac, LOGE, FL("aborting request to enter Standby ")); + pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE); + break; + + default: + pmcLog(pMac, LOGE, FL("Request for PMC command (%d) is dropped"), pCommand->command); + break; + } + }// !stopping + pmcReleaseCommand( pMac, pCommand ); + } +} + + + +//These commands are not supposed to fail due to out of command buffer, +//otherwise other commands are not executed and no command is released. It will be deadlock. +#define PMC_IS_COMMAND_CANNOT_FAIL(cmdType)\ + ( (eSmeCommandEnterStandby == (cmdType )) ||\ + (eSmeCommandExitImps == (cmdType )) ||\ + (eSmeCommandExitBmps == (cmdType )) ||\ + (eSmeCommandExitUapsd == (cmdType )) ||\ + (eSmeCommandExitWowl == (cmdType )) ) + +eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + eSmeCommandType cmdType, void *pvParam, + tANI_U32 size, tSmeCmd **ppCmd) +{ + eHalStatus status = eHAL_STATUS_RESOURCES; + tSmeCmd *pCommand = NULL; + + if (NULL == ppCmd) + { + VOS_ASSERT( ppCmd ); + return eHAL_STATUS_FAILURE; + } + do + { + pCommand = smeGetCommandBuffer( pMac ); + if ( pCommand ) + { + //Make sure it will be put back to the list + pCommand->u.pmcCmd.fReleaseWhenDone = FALSE; + } + else + { + pmcLog( pMac, LOGE, + FL(" fail to get command buffer for command 0x%X curState = %d"), + cmdType, pMac->pmc.pmcState ); + //For certain PMC command, we cannot fail + if( PMC_IS_COMMAND_CANNOT_FAIL(cmdType) ) + { + pmcLog( pMac, LOGE, + FL(" command 0x%X cannot fail try allocating memory for it"), cmdType ); + pCommand = vos_mem_malloc(sizeof(tSmeCmd)); + if ( NULL == pCommand ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s fail to allocate memory for command (0x%X)", + __func__, cmdType); + pCommand = NULL; + return eHAL_STATUS_FAILURE; + } + vos_mem_set(pCommand, sizeof(tSmeCmd), 0); + //Make sure it will be free when it is done + pCommand->u.pmcCmd.fReleaseWhenDone = TRUE; + } + else + { + break; + } + } + pCommand->command = cmdType; + pCommand->sessionId = sessionId; + pCommand->u.pmcCmd.size = size; + //Initialize the reason code here. It may be overwritten later when + //a particular reason is needed. + pCommand->u.pmcCmd.fullPowerReason = eSME_REASON_OTHER; + switch ( cmdType ) + { + case eSmeCommandEnterImps: + case eSmeCommandExitImps: + case eSmeCommandEnterBmps: + case eSmeCommandEnterUapsd: + case eSmeCommandEnterStandby: + status = eHAL_STATUS_SUCCESS; + break; + + case eSmeCommandExitUapsd: + case eSmeCommandExitWowl: + status = eHAL_STATUS_SUCCESS; + if( pvParam ) + { + if (pMac->psOffloadEnabled && cmdType == eSmeCommandExitWowl) + { + pCommand->u.pmcCmd.u.exitWowlInfo = + *( ( tSirSmeWowlExitParams * )pvParam ); + } + else + { + pCommand->u.pmcCmd.fullPowerReason = + *( (tRequestFullPowerReason *)pvParam ); + } + } + break; + + case eSmeCommandExitBmps: + status = eHAL_STATUS_SUCCESS; + if( pvParam ) + { + pCommand->u.pmcCmd.u.exitBmpsInfo = *( (tExitBmpsInfo *)pvParam ); + pCommand->u.pmcCmd.fullPowerReason = pCommand->u.pmcCmd.u.exitBmpsInfo.exitBmpsReason; + } + else + { + pmcLog( pMac, LOGE, (" exit BMPS must have a reason code") ); + } + break; + + case eSmeCommandEnterWowl: + status = eHAL_STATUS_SUCCESS; + if( pvParam ) + { + pCommand->u.pmcCmd.u.enterWowlInfo = *( ( tSirSmeWowlEnterParams * )pvParam ); + } + break; + + default: + pmcLog( pMac, LOGE, FL(" invalid command type %d"), cmdType ); + status = eHAL_STATUS_INVALID_PARAMETER; + break; + } + + } while( 0 ); + + if( HAL_STATUS_SUCCESS( status ) && pCommand ) + { + *ppCmd = pCommand; + } + else if( pCommand ) + { + pmcReleaseCommand( pMac, pCommand ); + } + + return (status); +} + + +eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + eSmeCommandType cmdType, void *pvParam, + tANI_U32 size, tANI_BOOLEAN fPutToListHead ) +{ + eHalStatus status = eHAL_STATUS_RESOURCES; + tSmeCmd *pCommand = NULL; + + status = pmcPrepareCommand( pMac, sessionId, cmdType, pvParam, size, + &pCommand ); + if( HAL_STATUS_SUCCESS( status ) && pCommand ) + { + smePushCommand( pMac, pCommand, fPutToListHead ); + } + else if( pCommand ) + { + pmcReleaseCommand( pMac, pCommand ); + } + + return( status ); +} + + + +tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE; + + do + { + switch ( pCommand->command ) + { + case eSmeCommandEnterImps: + if( FULL_POWER == pMac->pmc.pmcState ) + { + status = pmcEnterImpsCheck( pMac ); + if( HAL_STATUS_SUCCESS( status ) ) + { + /* Change state. */ + pMac->pmc.pmcState = REQUEST_IMPS; + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0); + if( HAL_STATUS_SUCCESS( status ) ) + { + /* + * If we already went back Full Power State (meaning + * that request did not get as far as the device) + * then we are not successful. + */ + if ( FULL_POWER != pMac->pmc.pmcState ) + { + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + } + } + if( !HAL_STATUS_SUCCESS( status ) ) + { + pmcLog(pMac, LOGE, + "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ or pmcEnterImpsCheck failed"); + pmcEnterFullPowerState( pMac ); + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + } + }//full_power + break; + + case eSmeCommandExitImps: + pMac->pmc.requestFullPowerPending = FALSE; + if( ( IMPS == pMac->pmc.pmcState ) || ( STANDBY == pMac->pmc.pmcState ) ) + { + //Check state before sending message. The state may change after that + if( STANDBY == pMac->pmc.pmcState ) + { + //Enable Idle scan in CSR + csrScanResumeIMPS(pMac); + } + + status = pmcSendMessage(pMac, eWNI_PMC_EXIT_IMPS_REQ, NULL, 0); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->pmc.pmcState = REQUEST_FULL_POWER; + pmcLog(pMac, LOG2, FL("eWNI_PMC_EXIT_IMPS_REQ sent to PE")); + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + pmcLog(pMac, LOGE, + FL("eWNI_PMC_EXIT_IMPS_REQ fail to be sent to PE status %d"), status); + pmcEnterFullPowerState(pMac); + } + } + break; + + case eSmeCommandEnterBmps: + if( FULL_POWER == pMac->pmc.pmcState ) + { + //This function will not return success because the pmc state is not BMPS + status = pmcEnterBmpsCheck( pMac ); + if( HAL_STATUS_SUCCESS( status ) ) + { + /* Change PMC state */ + pMac->pmc.pmcState = REQUEST_BMPS; + pmcLog(pMac, LOG2, "PMC: Enter BMPS req done"); + /* Tell MAC to have device enter BMPS mode. */ + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_BMPS_REQ, NULL, 0); + if ( HAL_STATUS_SUCCESS( status ) ) + { + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + pmcLog(pMac, LOGE, "Fail to send enter BMPS msg to PE"); + } + } + if( !HAL_STATUS_SUCCESS( status ) ) + { + pmcLog(pMac, LOGE, + "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ status %d", status); + pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE; + pmcEnterFullPowerState(pMac); + //Do not call UAPSD callback here since it may be retried + pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE); + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + } + } + break; + + case eSmeCommandExitBmps: + if(( BMPS == pMac->pmc.pmcState ) || (UAPSD == pMac->pmc.pmcState)) + { + tPmcState origState = pMac->pmc.pmcState; + pMac->pmc.requestFullPowerPending = FALSE; + + status = pmcSendMessage( pMac, eWNI_PMC_EXIT_BMPS_REQ, + &pCommand->u.pmcCmd.u.exitBmpsInfo, sizeof(tExitBmpsInfo) ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->pmc.pmcState = REQUEST_FULL_POWER; + fRemoveCmd = eANI_BOOLEAN_FALSE; + pmcLog(pMac, LOG2, FL("eWNI_PMC_EXIT_BMPS_REQ sent to PE")); + + } + else + { + pMac->pmc.pmcState = origState; + pmcLog(pMac, LOGE, FL("eWNI_PMC_EXIT_BMPS_REQ fail to be sent to PE status %d"), status); + pmcEnterFullPowerState(pMac); + } + } + break; + + case eSmeCommandEnterUapsd: + if( BMPS == pMac->pmc.pmcState ) + { + pMac->pmc.uapsdSessionRequired = TRUE; + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_UAPSD_REQ, NULL, 0); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->pmc.pmcState = REQUEST_START_UAPSD; + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_ENTER_BMPS_REQ"); + /* There is no retry for re-entering UAPSD so tell the + requester we are done with failure. */ + pMac->pmc.uapsdSessionRequired = FALSE; + pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE); + } + } + break; + + case eSmeCommandExitUapsd: + if( UAPSD == pMac->pmc.pmcState ) + { + pMac->pmc.requestFullPowerPending = FALSE; + /* If already in REQUEST_STOP_UAPSD, simply return */ + if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD) + { + break; + } + + /* Tell MAC to have device exit UAPSD mode. */ + status = pmcSendMessage(pMac, eWNI_PMC_EXIT_UAPSD_REQ, NULL, 0); + if ( HAL_STATUS_SUCCESS( status ) ) + { + /* Change state. Note that device will be put in BMPS state at the + end of REQUEST_STOP_UAPSD state even if response is a failure*/ + pMac->pmc.pmcState = REQUEST_STOP_UAPSD; + pMac->pmc.requestFullPowerPending = TRUE; + pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason; + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_EXIT_UAPSD_REQ"); + pmcEnterBmpsState(pMac); + } + } + + break; + + case eSmeCommandEnterWowl: + if( ( BMPS == pMac->pmc.pmcState ) || ( WOWL == pMac->pmc.pmcState ) ) + { + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_WOWL_REQ, + &pCommand->u.pmcCmd.u.enterWowlInfo, sizeof(tSirSmeWowlEnterParams)); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->pmc.pmcState = REQUEST_ENTER_WOWL; + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + pmcLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ"); + pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE); + } + } + else + { + fRemoveCmd = eANI_BOOLEAN_TRUE; + } + break; + + case eSmeCommandExitWowl: + if( WOWL == pMac->pmc.pmcState ) + { + pMac->pmc.requestFullPowerPending = FALSE; + pMac->pmc.pmcState = REQUEST_EXIT_WOWL; + status = pmcSendMessage(pMac, eWNI_PMC_EXIT_WOWL_REQ, NULL, 0); + if ( HAL_STATUS_SUCCESS( status ) ) + { + fRemoveCmd = eANI_BOOLEAN_FALSE; + pMac->pmc.requestFullPowerPending = TRUE; + pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason; + } + else + { + pmcLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ"); + pmcEnterBmpsState(pMac); + } + } + break; + + case eSmeCommandEnterStandby: + if( FULL_POWER == pMac->pmc.pmcState ) + { + /* + * Disallow standby if concurrent sessions are present. Note that + * CSR would have caused the STA to disconnect the Infra session + * (if not already disconnected) because of standby request. + * But we are now failing the standby request because of + * concurrent session. So was the tearing of infra session + * wasteful if we were going to fail the standby request? + * Not really. This is because if and when BT-AMP etc sessions + * are torn down we will transition to IMPS/standby and still + * save power. + */ + if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "WLAN: IBSS or BT-AMP session present. Cannot honor standby request"); + + pmcDoStandbyCallbacks(pMac, eHAL_STATUS_PMC_NOT_NOW); + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + break; + } + + // Stop traffic timer. Just making sure timer is not running + pmcStopTrafficTimer(pMac); + + /* Change state. */ + pMac->pmc.pmcState = REQUEST_STANDBY; + + /* Tell MAC to have device enter STANDBY mode. We are using the same message + as IMPS mode to avoid code changes in layer below (PE/HAL)*/ + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0); + if ( HAL_STATUS_SUCCESS( status ) ) + { + //Disable Idle scan in CSR + csrScanSuspendIMPS(pMac); + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + pmcLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_ENTER_IMPS_REQ"); + pmcEnterFullPowerState(pMac); + pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE); + /* Start the timer only if Auto BMPS feature is enabled or an UAPSD session is + required */ + if(pmcShouldBmpsTimerRun(pMac)) + (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod); + } + } + break; + + default: + pmcLog( pMac, LOGE, FL(" invalid command type %d"), pCommand->command ); + break; + } + + } while( 0 ); + + return( fRemoveCmd ); +} + +eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac ) +{ + + if( !PMC_IS_READY(pMac) ) + { + pmcLog(pMac, LOGE, FL("Requesting IMPS when PMC not ready")); + pmcLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s"), + pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + /* Check if IMPS is enabled. */ + if (!pMac->pmc.impsEnabled) + { + pmcLog(pMac, LOG2, FL("IMPS is disabled")); + return eHAL_STATUS_PMC_DISABLED; + } + + /* Check if IMPS enabled for current power source. */ + if ((pMac->pmc.powerSource == AC_POWER) && !pMac->pmc.impsConfig.enterOnAc) + { + pmcLog(pMac, LOG2, FL("IMPS is disabled when operating on AC power")); + return eHAL_STATUS_PMC_AC_POWER; + } + + /* Check that entry into a power save mode is allowed at this time. */ + if (!pmcPowerSaveCheck(pMac)) + { + pmcLog(pMac, LOG2, FL("IMPS cannot be entered now")); + return eHAL_STATUS_PMC_NOT_NOW; + } + + /* Check that entry into a power save mode is allowed at this time if all + running sessions agree. */ + if (!pmcAllowImps(pMac)) + { + pmcLog(pMac, LOG2, FL("IMPS cannot be entered now")); + return eHAL_STATUS_PMC_NOT_NOW; + } + + /* Check if already in IMPS. */ + if ((pMac->pmc.pmcState == REQUEST_IMPS) || (pMac->pmc.pmcState == IMPS) || + (pMac->pmc.pmcState == REQUEST_FULL_POWER)) + { + pmcLog(pMac, LOG2, FL("Already in IMPS")); + return eHAL_STATUS_PMC_ALREADY_IN_IMPS; + } + + /* Check whether driver load unload is in progress */ + if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL)) + { + pmcLog(pMac, LOGW, FL("Driver load/unload is in progress")); + return eHAL_STATUS_PMC_NOT_NOW; + } + + return ( eHAL_STATUS_SUCCESS ); +} + +/* + * This API determines if it is ok to proceed with a Enter BMPS Request or not. + * Note when device is in BMPS/UAPSD states, this API returns failure because it + * is not ok to issue a BMPS request. + */ +eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac ) +{ + + /* Check if BMPS is enabled. */ + if (!pMac->pmc.bmpsEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot initiate BMPS. BMPS is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + if( !PMC_IS_READY(pMac) ) + { + pmcLog(pMac, LOGE, FL("Requesting BMPS when PMC not ready")); + pmcLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s"), + pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + /* Check that we are associated with a single active session. */ + if (!pmcValidateConnectState( pMac )) + { + pmcLog(pMac, LOGE, "PMC: STA not associated with an AP with single active session. BMPS cannot be entered"); + return eHAL_STATUS_FAILURE; + } + + /* BMPS can only be requested when device is in Full Power */ + if (pMac->pmc.pmcState != FULL_POWER) + { + pmcLog(pMac, LOGE, + "PMC: Device not in full power. Cannot request BMPS. pmcState %d", pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + /* Check that entry into a power save mode is allowed at this time. */ + if (!pmcPowerSaveCheck(pMac)) + { + pmcLog(pMac, LOGE, "PMC: Power save check failed. BMPS cannot be entered now"); + return eHAL_STATUS_PMC_NOT_NOW; + } + + //Remove this code once SLM_Sessionization is supported + //BMPS_WORKAROUND_NOT_NEEDED + if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION)) + { + pmcLog(pMac, LOG1, FL("doBMPSWorkaround %u"), pMac->roam.configParam.doBMPSWorkaround); + if (pMac->roam.configParam.doBMPSWorkaround) + { + pMac->roam.configParam.doBMPSWorkaround = 0; + pmcLog(pMac, LOG1, + FL("reset doBMPSWorkaround to disabled %u"), pMac->roam.configParam.doBMPSWorkaround); + csrDisconnectAllActiveSessions(pMac); + pmcLog(pMac, LOGE, + "PMC: doBMPSWorkaround was enabled. First Disconnect all sessions. pmcState %d", pMac->pmc.pmcState); + return eHAL_STATUS_FAILURE; + } + } + + return ( eHAL_STATUS_SUCCESS ); +} + +tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac ) +{ + /* Check if BMPS is enabled and if Auto BMPS Feature is still enabled + * or there is a pending Uapsd request or HDD requested BMPS or there + * is a pending request for WoWL. In all these cases BMPS is required. + * Otherwise just stop the timer and return. + */ + if (!(pMac->pmc.bmpsEnabled && (pMac->pmc.autoBmpsEntryEnabled || + pMac->pmc.uapsdSessionRequired || pMac->pmc.bmpsRequestedByHdd || + pMac->pmc.wowlModeRequired ))) + { + pmcLog(pMac, LOG1, FL("BMPS is not enabled or not required")); + return eANI_BOOLEAN_FALSE; + } + + if(pMac->pmc.isHostPsEn && pMac->pmc.remainInPowerActiveTillDHCP) + { + pmcLog(pMac, LOG1, + FL("Host controlled ps enabled and host wants active mode, so dont allow BMPS")); + return eANI_BOOLEAN_FALSE; + } + + if ((vos_concurrent_open_sessions_running()) && + ((csrIsConcurrentInfraConnected( pMac ) || + (vos_get_concurrency_mode()& VOS_SAP) || + (vos_get_concurrency_mode()& VOS_P2P_GO)))) + { + pmcLog(pMac, LOG1, FL("Multiple Sessions/GO/SAP sessions . BMPS should not be started")); + return eANI_BOOLEAN_FALSE; + } + /* Check if there is an Infra session. BMPS is possible only if there is + * an Infra session */ + if (!csrIsInfraConnected(pMac)) + { + pmcLog(pMac, LOG1, FL("No Infra Session or multiple sessions. BMPS should not be started")); + return eANI_BOOLEAN_FALSE; + } + return eANI_BOOLEAN_TRUE; +} + +/** + * sme_PmcStatetoString(): converts PMC state enum to string. + * @pmcState: PMC state enum. + */ +const char * sme_PmcStatetoString(const v_U8_t pmcState) +{ switch (pmcState) + { + CASE_RETURN_STRING( STOPPED ); + CASE_RETURN_STRING( FULL_POWER ); + CASE_RETURN_STRING( LOW_POWER); + CASE_RETURN_STRING( REQUEST_IMPS ); + CASE_RETURN_STRING( IMPS ); + CASE_RETURN_STRING( REQUEST_BMPS ); + CASE_RETURN_STRING( BMPS ); + CASE_RETURN_STRING( REQUEST_FULL_POWER ); + CASE_RETURN_STRING( REQUEST_START_UAPSD ); + CASE_RETURN_STRING( REQUEST_STOP_UAPSD ); + CASE_RETURN_STRING( UAPSD ); + CASE_RETURN_STRING( REQUEST_STANDBY ); + CASE_RETURN_STRING( STANDBY ); + CASE_RETURN_STRING( REQUEST_ENTER_WOWL ); + CASE_RETURN_STRING( REQUEST_EXIT_WOWL ); + CASE_RETURN_STRING( WOWL ); + default: + return "Invalid pmcState"; + } +} + +void pmcOffloadClosePowerSaveCheckList(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tListElem *pEntry; + tpPmcOffloadPsCheckEntry pPowerSaveCheckEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + csrLLLock(&pmc->pwrsaveCheckList); + pEntry = csrLLRemoveHead(&pmc->pwrsaveCheckList, FALSE); + while(pEntry) + { + pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPmcOffloadPsCheckEntry, + link); + vos_mem_free(pPowerSaveCheckEntry); + pEntry = csrLLRemoveHead(&pmc->pwrsaveCheckList, FALSE); + } + csrLLUnlock(&pmc->pwrsaveCheckList); + csrLLClose(&pmc->pwrsaveCheckList); +} + +void pmcOffloadCloseDeviceStateUpdateList(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tListElem *pEntry; + tpPmcOffloadDevStateUpdIndEntry pPowerSaveDevStateEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + csrLLLock(&pmc->deviceStateUpdateIndList); + pEntry = csrLLRemoveHead(&pmc->deviceStateUpdateIndList, FALSE); + while(pEntry) + { + pPowerSaveDevStateEntry = GET_BASE_ADDR(pEntry, + tPmcOffloadDevStateUpdIndEntry, link); + vos_mem_free(pPowerSaveDevStateEntry); + pEntry = csrLLRemoveHead(&pmc->deviceStateUpdateIndList, FALSE); + } + csrLLUnlock(&pmc->deviceStateUpdateIndList); + csrLLClose(&pmc->deviceStateUpdateIndList); +} + +void pmcOffloadCloseReqStartUapsdList(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tListElem *pEntry; + tpPmcOffloadStartUapsdEntry pPowerSaveStartUapsdEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + csrLLLock(&pmc->uapsdCbList); + pEntry = csrLLRemoveHead(&pmc->uapsdCbList, FALSE); + while(pEntry) + { + pPowerSaveStartUapsdEntry = GET_BASE_ADDR(pEntry, + tPmcOffloadStartUapsdEntry, link); + vos_mem_free(pPowerSaveStartUapsdEntry); + pEntry = csrLLRemoveHead(&pmc->uapsdCbList, FALSE); + } + csrLLUnlock(&pmc->uapsdCbList); + csrLLClose(&pmc->uapsdCbList); +} + +void pmcOffloadCloseReqFullPwrList(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tListElem *pEntry; + tpPmcOffloadReqFullPowerEntry pPowerSaveFullPowerReqEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + csrLLLock(&pmc->fullPowerCbList); + pEntry = csrLLRemoveHead(&pmc->fullPowerCbList, FALSE); + while(pEntry) + { + pPowerSaveFullPowerReqEntry = GET_BASE_ADDR(pEntry, + tPmcOffloadReqFullPowerEntry, link); + vos_mem_free(pPowerSaveFullPowerReqEntry); + pEntry = csrLLRemoveHead(&pmc->fullPowerCbList, FALSE); + } + csrLLUnlock(&pmc->fullPowerCbList); + csrLLClose(&pmc->fullPowerCbList); +} + +eHalStatus pmcOffloadOpenPerSession(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadOpenPerSession")); + + pmc->pmcState = STOPPED; + pmc->sessionId = sessionId; + pmc->pMac = pMac; + + /* Allocate a timer to enable ps automatically */ + if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pmc->autoPsEnableTimer, + VOS_TIMER_TYPE_SW, + pmcOffloadAutoPsEntryTimerExpired, pmc))) + { + smsLog(pMac, LOGE, FL("Cannot allocate timer for auto ps entry")); + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for power save check routines and request full power callback routines. */ + if (csrLLOpen(pMac->hHdd, &pmc->pwrsaveCheckList) != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, + FL("Cannot initialize power save check routine list")); + return eHAL_STATUS_FAILURE; + } + if (csrLLOpen(pMac->hHdd, &pmc->fullPowerCbList) != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, + FL("Cannot initialize request full power callback routine list")); + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for request start UAPSD callback routines. */ + if (csrLLOpen(pMac->hHdd, &pmc->uapsdCbList) != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, + FL("Cannot initialize uapsd callback routine list")); + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for device state update indication callback routines. */ + if (csrLLOpen(pMac->hHdd, &pmc->deviceStateUpdateIndList) + != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, + FL("Cannot initialize device state update ind callback list")); + return eHAL_STATUS_FAILURE; + } + + pmc->UapsdEnabled = TRUE; + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadStartPerSession(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadStartPerSession")); + pmc->uapsdSessionRequired = FALSE; + pmc->fullPowerReqPend = FALSE; + pmc->configStaPsEnabled = FALSE; + pmc->pmcState = FULL_POWER; + pmc->autoPsEntryTimerPeriod = AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE; +#ifdef FEATURE_WLAN_TDLS + pmc->isTdlsPowerSaveProhibited = FALSE; +#endif + pmc->configDefStaPsEnabled = FALSE; + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadStopPerSession(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadStopPerSession")); + pmc->uapsdSessionRequired = FALSE; + pmc->fullPowerReqPend = FALSE; + pmc->configStaPsEnabled = FALSE; + pmc->pmcState = STOPPED; + pmc->autoPsEntryTimerPeriod = AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE; + pmc->pMac = pMac; +#ifdef FEATURE_WLAN_TDLS + pmc->isTdlsPowerSaveProhibited = FALSE; +#endif + pmc->configDefStaPsEnabled = FALSE; + + pmcOffloadStopAutoStaPsTimer(pMac, sessionId); + pmcOffloadDoFullPowerCallbacks(pMac, sessionId, eHAL_STATUS_FAILURE); + pmcOffloadDoStartUapsdCallbacks(pMac, sessionId, eHAL_STATUS_FAILURE); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadClosePerSession(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadDeInitPerSession")); + + if(!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pmc->autoPsEnableTimer))) + { + smsLog(pMac, LOGE, FL("Cannot deallocate traffic timer")); + } + + pmcOffloadClosePowerSaveCheckList(pMac, sessionId); + pmcOffloadCloseDeviceStateUpdateList(pMac, sessionId); + pmcOffloadCloseReqStartUapsdList(pMac, sessionId); + pmcOffloadCloseReqFullPwrList(pMac, sessionId); + return eHAL_STATUS_SUCCESS; +} + +void pmcOffloadDoFullPowerCallbacks(tpAniSirGlobal pMac, tANI_U32 sessionId, + eHalStatus status) +{ + tListElem *pEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + tpPmcOffloadReqFullPowerEntry pReqFullPwrEntry; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadDoFullPowerCallbacks")); + + /* Call the routines in the request full power callback routine list. */ + pEntry = csrLLRemoveHead(&pmc->fullPowerCbList, TRUE); + while(pEntry) + { + pReqFullPwrEntry = + GET_BASE_ADDR(pEntry, tPmcOffloadReqFullPowerEntry, link); + + if(pReqFullPwrEntry->fullPwrCb) + pReqFullPwrEntry->fullPwrCb(pReqFullPwrEntry->callbackContext, + sessionId, status); + vos_mem_free(pReqFullPwrEntry); + pEntry = csrLLRemoveHead(&pmc->fullPowerCbList, TRUE); + } +} + +void pmcOffloadDoDeviceStateUpdateCallbacks (tpAniSirGlobal pMac, + tANI_U32 sessionId, tPmcState state) +{ + tListElem *pEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + tpPmcOffloadDevStateUpdIndEntry pDeviceStateUpdateIndEntry; + + smsLog(pMac, LOG2, FL("PMC - Update registered modules of new device " + "state: %s"), pmcGetPmcStateStr(state)); + + /* Call the routines in the update device state routine list. */ + pEntry = csrLLPeekHead(&pmc->deviceStateUpdateIndList, FALSE); + while(pEntry) + { + pDeviceStateUpdateIndEntry = + GET_BASE_ADDR(pEntry, tPmcOffloadDevStateUpdIndEntry, link); + + pDeviceStateUpdateIndEntry->stateChangeCb( + pDeviceStateUpdateIndEntry->callbackContext, + sessionId, state); + pEntry = csrLLNext(&pmc->deviceStateUpdateIndList, pEntry, FALSE); + } +} + +void pmcOffloadDoStartUapsdCallbacks(tpAniSirGlobal pMac, tANI_U32 sessionId, + eHalStatus status) +{ + tListElem *pEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + tpPmcOffloadStartUapsdEntry pStartUapsdEntry; + + smsLog(pMac, LOG2, "PMC: entering pmcOffloadDoStartUapsdCallbacks"); + + csrLLLock(&pmc->uapsdCbList); + /* Call the routines in the request start UAPSD callback routine list. */ + pEntry = csrLLRemoveHead(&pmc->uapsdCbList, FALSE); + while(pEntry) + { + pStartUapsdEntry = GET_BASE_ADDR(pEntry, tPmcOffloadStartUapsdEntry, link); + pStartUapsdEntry->uapsdStartInd(pStartUapsdEntry->callbackContext, + pStartUapsdEntry->sessionId, status); + vos_mem_free(pStartUapsdEntry); + pEntry = csrLLRemoveHead(&pmc->uapsdCbList, FALSE); + } + csrLLUnlock(&pmc->uapsdCbList); +} + +tANI_BOOLEAN pmcOffloadPowerSaveCheck(tHalHandle hHal, + tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpPmcOffloadPsCheckEntry pPowerSaveCheckEntry; + PwrSaveCheckRoutine checkRoutine = NULL; + tANI_BOOLEAN bResult=TRUE; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadPowerSaveCheck")); + + /* + * Call the routines in the power save check routine list. + * If any return FALSE, then we cannot go into power save mode. + */ + pEntry = csrLLPeekHead(&pmc->pwrsaveCheckList, FALSE); + while(pEntry) + { + pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPmcOffloadPsCheckEntry, + link); + checkRoutine = pPowerSaveCheckEntry->pwrsaveCheckCb; + /* + * If the checkRoutine is NULL for a particular entry, + * proceed with other entries + * in the list + */ + if(checkRoutine) + { + if (!checkRoutine(pPowerSaveCheckEntry->checkContext, sessionId)) + { + smsLog(pMac, LOGE, FL("pmcOffloadPowerSaveCheck fail!")); + bResult = FALSE; + break; + } + } + pEntry = csrLLNext(&pmc->pwrsaveCheckList, pEntry, FALSE); + } + return bResult; +} + +/* + * This API checks whether it is ok to enable sta mode power save. + * Pre Condition for enabling sta mode power save + * 1) Sta Mode Ps should be enabled in ini file. + * 2) Session should be in infra mode and in connected state. + * 3) Ps State should be in full power + * 4) Modules registered with PMC Offload should vote + * for power save enabling. + */ +eHalStatus pmcOffloadEnableStaPsCheck(tpAniSirGlobal pMac, + tANI_U32 sessionId) +{ + /* Check if Sta Ps is enabled. */ + if(!pMac->pmcOffloadInfo.staPsEnabled) + { + smsLog(pMac, LOG1, "PMC: Cannot initiate BMPS. BMPS is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + /* Check whether the give session is Infra and in Connected State */ + if(!csrIsConnStateConnectedInfra(pMac, sessionId)) + { + smsLog(pMac, LOG1, "PMC:Sta not infra/connected state %d", sessionId); + return eHAL_STATUS_FAILURE; + } + + /* Check whether the PMC Offload state is in Full Power or not */ + if(FULL_POWER != pMac->pmcOffloadInfo.pmc[sessionId].pmcState) + { + smsLog(pMac, LOG1, + "PMC: Device not in full power. Cannot request BMPS. pmcState %d", + pMac->pmcOffloadInfo.pmc[sessionId].pmcState); + return eHAL_STATUS_FAILURE; + } + +#ifdef FEATURE_WLAN_TDLS + if (pMac->pmcOffloadInfo.pmc[sessionId].isTdlsPowerSaveProhibited) + { + smsLog(pMac, LOG1, + "Dont enter BMPS.TDLS session active on session %d", sessionId); + return eHAL_STATUS_FAILURE; + } +#endif + + /* Check that entry into a power save mode is allowed at this time. */ + if(!pmcOffloadPowerSaveCheck(pMac, sessionId)) + { + smsLog(pMac, LOG1, + "PMC: Power save check failed. BMPS cannot be entered now"); + return eHAL_STATUS_PMC_NOT_NOW; + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadStartAutoStaPsTimer (tpAniSirGlobal pMac, + tANI_U32 sessionId, + tANI_U32 timerValue) +{ + VOS_STATUS vosStatus; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Entering pmcOffloadStartAutoStaPsTimer")); + + vosStatus = vos_timer_start(&pmc->autoPsEnableTimer, + timerValue); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + if(VOS_STATUS_E_ALREADY == vosStatus) + { + /* Consider this ok since the timer is already started */ + smsLog(pMac, LOGW, + FL("pmcOffloadStartAutoStaPsTimer is already started")); + } + else + { + smsLog(pMac, LOGP, + FL("Cannot start pmcOffloadStartAutoStaPsTimer")); + return eHAL_STATUS_FAILURE; + } + } + return eHAL_STATUS_SUCCESS; +} + +void pmcOffloadStopAutoStaPsTimer(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + /* + * Stop the auto ps entry timer if running + */ + if(VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pmc->autoPsEnableTimer)) + { + vos_timer_stop(&pmc->autoPsEnableTimer); + } +} + +eHalStatus pmcOffloadQueueStartUapsdRequest(tpAniSirGlobal pMac, + tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + switch(pmc->pmcState) + { + case FULL_POWER: + case REQUEST_BMPS: + pmc->uapsdSessionRequired = TRUE; + break; + case BMPS: + if(pmc->uapsdSessionRequired) + { + smsLog(pMac, LOGE, + FL("Uapsd is already pending")); + break; + } + /* Request to Enable Sta Mode Power Save */ + if(pmcIssueCommand(pMac, sessionId, eSmeCommandEnterUapsd, + NULL, 0, FALSE) == eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOG2, + FL("eSmeCommandEnterUapsd issue successfully")); + break; + } + else + { + /* Fail to issue eSmeCommandEnterUapsd */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandEnterUapsd")); + return eHAL_STATUS_FAILURE; + } + default: + return eHAL_STATUS_SUCCESS; + } + return eHAL_STATUS_PMC_PENDING; +} + +eHalStatus pmcOffloadQueueStopUapsdRequest(tpAniSirGlobal pMac, + tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + switch(pmc->pmcState) + { + case REQUEST_STOP_UAPSD: + break; + case UAPSD: + /* Queue the Stop UAPSD Request */ + if(pmcIssueCommand(pMac, sessionId, eSmeCommandExitUapsd, + NULL, 0, FALSE) == eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOG2, + FL("eSmeCommandExitUapsd issue successfully")); + break; + } + else + { + /* + * Fail to issue eSmeCommandExitUapsd + * just fall through to restart the timer + */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandExitUapsd")); + return eHAL_STATUS_FAILURE; + } + default: + pmc->uapsdSessionRequired = FALSE; + smsLog(pMac, LOG2, + "PMC: trying to enter Req Stop UAPSD State from state %d", + pmc->pmcState); + return eHAL_STATUS_SUCCESS; + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadQueueRequestFullPower (tpAniSirGlobal pMac, + tANI_U32 sessionId, tRequestFullPowerReason fullPowerReason) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + tExitBmpsInfo exitBmpsInfo; + + if(FULL_POWER == pmc->pmcState) + { + smsLog(pMac, LOG2, + FL("Already in Full Power")); + return eHAL_STATUS_SUCCESS; + } + + exitBmpsInfo.exitBmpsReason = fullPowerReason; + + /* Queue Full Power Request */ + if(pmcIssueCommand(pMac, sessionId, eSmeCommandExitBmps, &exitBmpsInfo, + sizeof(tExitBmpsInfo), FALSE) == eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOG2, + FL("eSmeCommandExitBmps issue successfully")); + pmc->fullPowerReqPend = TRUE; + } + else + { + /* + * Fail to issue eSmeCommandExitBmps + */ + pmc->fullPowerReqPend = FALSE; + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandExitBmps")); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_PMC_PENDING; +} + +eHalStatus pmcOffloadEnableStaPsHandler(tpAniSirGlobal pMac, + tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + VOS_STATUS vosStatus; + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(pMac, LOG2, FL("Enter pmcOffloadEnableStaPsHandler")); + + status = pmcOffloadEnableStaPsCheck(pMac, sessionId); + + switch(status) + { + case eHAL_STATUS_SUCCESS: + /* Request to Enable Sta Mode Power Save */ + if(pmcIssueCommand(pMac, sessionId, eSmeCommandEnterBmps, + NULL, 0, FALSE) == eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOG2, + FL("eSmeCommandEnterBmps issue successfully")); + break; + } + else + { + /* + * Fail to issue eSmeCommandEnterBmps + * just fall through to restart the timer + */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandEnterBmps")); + } + case eHAL_STATUS_PMC_NOT_NOW: + /* + * Some module voted against Power Save. + * Restart the Auto Ps Entry Timer + */ + smsLog(pMac, LOGE, + FL("Power Save check failed. Retry Enable Sta Ps later")); + vosStatus = vos_timer_start(&pmc->autoPsEnableTimer, + pmc->autoPsEntryTimerPeriod); + if (!VOS_IS_STATUS_SUCCESS(vosStatus) && + (VOS_STATUS_E_ALREADY != vosStatus)) + { + smsLog(pMac, LOGP, FL("Cannot start traffic timer")); + return eHAL_STATUS_FAILURE; + } + break; + + default: + break; + } + return status; +} + +eHalStatus pmcOffloadDisableStaPsHandler(tpAniSirGlobal pMac, + tANI_U8 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Enter pmcOffloadDisableStaPsHandler")); + + /* + * Clear the master flag so that + * further enable request will not be + * honored + */ + pmc->configStaPsEnabled = FALSE; + + /* + * Check whether the give session is Infra and in Connected State + * This is case where Session is already disconnected + */ + if(!csrIsConnStateConnectedInfra(pMac, sessionId)) + { + /* + * Stop the auto ps entry timer if running + */ + pmcOffloadStopAutoStaPsTimer(pMac, sessionId); + smsLog(pMac, LOG2, "PMC:Sta not infra/connected state %d", sessionId); + return eHAL_STATUS_SUCCESS; + } + + switch(pmc->pmcState) + { + case REQUEST_FULL_POWER: + case FULL_POWER: + /* + * Stop the auto ps entry timer if running + */ + pmcOffloadStopAutoStaPsTimer(pMac, sessionId); + break; + + case REQUEST_BMPS: + case BMPS: + case REQUEST_START_UAPSD: + case REQUEST_STOP_UAPSD: + case UAPSD: + if(eHAL_STATUS_FAILURE == + pmcOffloadQueueRequestFullPower(pMac, sessionId, + eSME_BMPS_MODE_DISABLED)) + { + /* + * Fail to issue eSmeCommandExitBmps + */ + smsLog(pMac, LOGW, FL("Fail to issue eSmeCommandExitBmps")); + return eHAL_STATUS_FAILURE; + } + break; + + default: + smsLog(pMac, LOGW, + FL("Invalid pmcState State %x"), pmc->pmcState); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + +void pmcOffloadAutoPsEntryTimerExpired(void *pmcInfo) +{ + tpPsOffloadPerSessionInfo pmc = (tpPsOffloadPerSessionInfo)pmcInfo; + tpAniSirGlobal pMac = pmc->pMac; + + smsLog(pMac, LOG2, FL("Auto PS timer expired")); + + if(eHAL_STATUS_FAILURE == pmcOffloadEnableStaPsHandler(pMac, + pmc->sessionId)) + { + smsLog(pMac, LOGE, FL("Auto PS timer expired in wrong state")); + } +} + +eHalStatus pmcOffloadEnterPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + /* + * Sta Power Save is successfully Enabled + * 1)If Req for full power is pending then + * Queue the Full power Req + * Else + * Queue uapsd req if pending + * 2) Change PS State + * PMC_POWER_SAVE if uapsd is not enabled + * PMC_POWER_SAVE_UAPSD if uapsd is already enabled + */ + if(PMC_UAPSD_ENABLE_PENDING == pmc->uapsdStatus) + { + pmc->pmcState = UAPSD; + pmc->uapsdStatus = PMC_UAPSD_ENABLED; + /* Call registered uapsd cbs */ + pmcOffloadDoStartUapsdCallbacks(pMac, sessionId, eHAL_STATUS_SUCCESS); + } + else + { + pmc->uapsdStatus = PMC_UAPSD_DISABLED; + if (pmc->pmcState == UAPSD) + pmc->uapsdSessionRequired = FALSE; + + pmc->pmcState = BMPS; + } + + /* Indicate Device State Change Indication */ + pmcOffloadDoDeviceStateUpdateCallbacks(pMac, sessionId, pmc->pmcState); + + if(pmc->fullPowerReqPend) + { + if(eHAL_STATUS_FAILURE == + pmcOffloadQueueRequestFullPower(pMac, sessionId, + eSME_REASON_OTHER)) + { + /* + * Fail to issue eSmeCommandExitBmps + */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandExitBmps")); + + /* Call registered callbacks with failure */ + pmcOffloadDoFullPowerCallbacks(pMac, sessionId, + eHAL_STATUS_FAILURE); + } + } + else if((UAPSD != pmc->pmcState) && pmc->uapsdSessionRequired) + { + if(eHAL_STATUS_FAILURE == + pmcOffloadQueueStartUapsdRequest(pMac, sessionId)) + { + pmc->uapsdSessionRequired = FALSE; + /* + * Fail to issue eSmeCommandEnterUapsd + */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandEnterUapsd")); + + /* Call uapsd Cbs with failure */ + pmcOffloadDoStartUapsdCallbacks(pMac, sessionId, + eHAL_STATUS_FAILURE); + } + } + else + { + smsLog(pMac, LOG2, FL("Stay in Power Save State")); + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadExitPowersaveState(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + /* + * Sta Power Save is successfully Disabled + * 1) Set the PS State to Full Power + * 2) Indicate State Change + * 3) Start Auto Ps Entry Timer + * We can try to Queue the ps request + * then we can start the timer if any module + * votes against ps + */ + pmc->pmcState = FULL_POWER; + pmc->fullPowerReqPend = FALSE; + + if(PMC_UAPSD_DISABLE_PENDING == pmc->uapsdStatus) + { + pmc->uapsdStatus = PMC_UAPSD_DISABLED; + } + + /* Indicate Device State Change Indication */ + pmcOffloadDoDeviceStateUpdateCallbacks(pMac, sessionId, pmc->pmcState); + + /* Call Full Power Req Cbs */ + pmcOffloadDoFullPowerCallbacks(pMac, sessionId, eHAL_STATUS_SUCCESS); + + if (pmc->configStaPsEnabled || pmc->configDefStaPsEnabled) + pmcOffloadStartAutoStaPsTimer(pMac, sessionId, + pmc->autoPsEntryTimerPeriod); + else + smsLog(pMac, LOGE, FL("Master Sta Ps Disabled")); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadEnterUapsdState(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, "PMC: entering pmcOffloadEnterUapsdState"); + + /* Can enter UAPSD State only from Request UAPSD State. */ + if(REQUEST_START_UAPSD != pmc->pmcState) + { + smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d", + pmc->pmcState); + return eHAL_STATUS_FAILURE; + } + + /* Change the State */ + pmc->pmcState = UAPSD; + + /* Call the State Change Indication through Registered Cbs */ + pmcOffloadDoDeviceStateUpdateCallbacks(pMac, sessionId, UAPSD); + + /* Call the registered uapsd cbs */ + pmcOffloadDoStartUapsdCallbacks(pMac, sessionId, eHAL_STATUS_SUCCESS); + + if(pmc->fullPowerReqPend) + { + if(eHAL_STATUS_FAILURE == pmcOffloadQueueRequestFullPower(pMac, + sessionId, eSME_REASON_OTHER)) + { + /* + * Fail to issue eSmeCommandExitBmps + */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandExitBmps")); + + /* Call registered callbacks with failure */ + pmcOffloadDoFullPowerCallbacks(pMac, sessionId, + eHAL_STATUS_FAILURE); + } + } + return eHAL_STATUS_SUCCESS; +} + +void pmcOffloadExitBmpsIndHandler(tpAniSirGlobal pMac, tSirSmeRsp *pMsg) +{ + tpSirSmeExitBmpsInd pExitBmpsInd = (tpSirSmeExitBmpsInd)pMsg; + /* Enter Full Power State. */ + if (pExitBmpsInd->statusCode != eSIR_SME_SUCCESS) + { + smsLog(pMac, LOGP, + FL("Exit BMPS indication indicates failure, status %x"), + pMsg->statusCode); + } + else + { + smsLog(pMac, LOG1, + FL("Exit BMPS indication on session %u, reason %d"), + pExitBmpsInd->smeSessionId, pExitBmpsInd->exitBmpsReason); + pmcOffloadQueueRequestFullPower(pMac, pExitBmpsInd->smeSessionId, + pExitBmpsInd->exitBmpsReason); + } +} + +void pmcOffloadProcessResponse(tpAniSirGlobal pMac, tSirSmeRsp *pMsg) +{ + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE; + tpPsOffloadPerSessionInfo pmc = NULL; + + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + + smsLog(pMac, LOG2, FL("process message = %d"), pMsg->messageType); + + /* Process each different type of message. */ + switch(pMsg->messageType) + { + case eWNI_PMC_ENTER_BMPS_RSP: + smsLog(pMac, LOG2, + FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP with status = %d"), + pMsg->statusCode); + + if(eSmeCommandEnterBmps != pCommand->command) + { + smsLog(pMac, LOGW, + FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP without request")); + + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + + /* Enter PS State if response indicates success. */ + if(eSIR_SME_SUCCESS == pMsg->statusCode) + { + pmcOffloadEnterPowersaveState(pMac, pCommand->sessionId); + } + else + { + pmcOffloadExitPowersaveState(pMac, pCommand->sessionId); + } + break; + + case eWNI_PMC_EXIT_BMPS_RSP: + smsLog(pMac, LOG2, + FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP with status = %d"), + pMsg->statusCode); + + if(eSmeCommandExitBmps != pCommand->command) + { + smsLog(pMac, LOGW, + FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP without req")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + + /* Enter Full Power State if response indicates success. */ + if(eSIR_SME_SUCCESS == pMsg->statusCode) + { + pmcOffloadExitPowersaveState(pMac, pCommand->sessionId); + } + else + { + pmc = &pMac->pmcOffloadInfo.pmc[pCommand->sessionId]; + pmc->fullPowerReqPend = FALSE; + + /* Indicate Full Power Req Failure */ + pmcOffloadDoFullPowerCallbacks(pMac, pCommand->sessionId, + eHAL_STATUS_FAILURE); + pmcOffloadEnterPowersaveState(pMac, pCommand->sessionId); + } + break; + + case eWNI_PMC_ENTER_UAPSD_RSP: + smsLog(pMac, LOG2, + FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP with status = %d"), + pMsg->statusCode); + if(eSmeCommandEnterUapsd != pCommand->command) + { + smsLog(pMac, LOGW, + FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + + pmc = &pMac->pmcOffloadInfo.pmc[pCommand->sessionId]; + + /* Check that we are in the correct state for this message. */ + if(REQUEST_START_UAPSD != pmc->pmcState) + { + smsLog(pMac, LOGE, + FL("Got Enter Uapsd rsp Message while in state %d"), + pmc->pmcState); + break; + } + + /* Enter uapsd State if response indicates success. */ + if(eSIR_SME_SUCCESS == pMsg->statusCode) + { + pmcOffloadEnterUapsdState(pMac, pCommand->sessionId); + } + else + { + smsLog(pMac, LOGE, FL("Got Enter Uapsd rsp Failed")); + pmc->uapsdSessionRequired = FALSE; + /* Indicate Failure through registered cbs */ + pmcOffloadDoStartUapsdCallbacks(pMac, pCommand->sessionId, + eHAL_STATUS_FAILURE); + pmcOffloadEnterPowersaveState(pMac, pCommand->sessionId); + } + break; + + case eWNI_PMC_EXIT_UAPSD_RSP: + smsLog(pMac, LOG2, + FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP with status = %d"), + pMsg->statusCode); + if(eSmeCommandExitUapsd != pCommand->command) + { + smsLog(pMac, LOGW, + FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP without req")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + + /* Enter Full Power State if response indicates success. */ + if(pMsg->statusCode != eSIR_SME_SUCCESS) + { + smsLog(pMac, LOGE, + FL("eWNI_PMC_EXIT_UAPSD_RSP Failed SessionId %d"), + pCommand->sessionId); + } + + /* Move to BMPS State irrespective of Status */ + pmcOffloadEnterPowersaveState(pMac, pCommand->sessionId); + break; + + default: + smsLog(pMac, LOGE, + FL("Invalid message type %d received"), pMsg->messageType); + break; + } + + if(fRemoveCommand) + { + if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) + { + pmcReleaseCommand(pMac, pCommand ); + smeProcessPendingQueue(pMac); + } + } + } + else + { + smsLog(pMac, LOGE, + FL("message type %d received but no request is found"), + pMsg->messageType); + } +} + +void pmcOffloadAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, + tANI_BOOLEAN fStopping ) +{ + if(eSmePmcCommandMask & pCommand->command) + { + if( !fStopping ) + { + tpPsOffloadPerSessionInfo pmc = + &pMac->pmcOffloadInfo.pmc[pCommand->sessionId]; + switch( pCommand->command ) + { + case eSmeCommandEnterBmps: + smsLog(pMac, LOGE, FL("aborting request to enter BMPS ")); + pmcOffloadExitPowersaveState(pMac, pCommand->sessionId); + break; + + case eSmeCommandExitBmps: + smsLog(pMac, LOGE, FL("aborting request to exit BMPS ")); + pmcOffloadEnterPowersaveState(pMac, pCommand->sessionId); + break; + + case eSmeCommandEnterUapsd: + smsLog(pMac, LOGE, FL("aborting request to enter UAPSD ")); + /* + * Since there is no retry for UAPSD, + * tell the requester here we are done with failure + */ + pmc->uapsdSessionRequired = FALSE; + pmcOffloadDoStartUapsdCallbacks(pMac, pCommand->sessionId, + eHAL_STATUS_FAILURE); + break; + + case eSmeCommandExitUapsd: + smsLog(pMac, LOGE, FL("aborting request to exit UAPSD ")); + break; + + case eSmeCommandEnterWowl: + smsLog(pMac, LOGE, FL("aborting request to enter WOWL ")); + break; + + case eSmeCommandExitWowl: + smsLog(pMac, LOGE, FL("aborting request to exit WOWL ")); + break; + + default: + smsLog(pMac, LOGE, FL("Request for PMC command (%d) is dropped"), pCommand->command); + break; + } + }// !stopping + pmcReleaseCommand( pMac, pCommand ); + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcApi.c new file mode 100644 index 000000000000..9a01999419cb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcApi.c @@ -0,0 +1,4143 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: pmcApi.c +* +* Description: Routines that make up the Power Management Control (PMC) API. +* + +* +******************************************************************************/ + +#include "palTypes.h" +#include "aniGlobal.h" +#include "csrLinkList.h" +#include "smsDebug.h" +#include "pmcApi.h" +#include "pmc.h" +#include "cfgApi.h" +#include "smeInside.h" +#include "csrInsideApi.h" +#include "wlan_ps_wow_diag.h" +#include "wlan_qct_wda.h" +#include "limSessionUtils.h" +#include "csrInsideApi.h" +#include "sme_Api.h" + +extern void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); + +void pmcCloseDeferredMsgList(tpAniSirGlobal pMac); +void pmcCloseDeviceStateUpdateList(tpAniSirGlobal pMac); +void pmcCloseRequestStartUapsdList(tpAniSirGlobal pMac); +void pmcCloseRequestBmpsList(tpAniSirGlobal pMac); +void pmcCloseRequestFullPowerList(tpAniSirGlobal pMac); +void pmcClosePowerSaveCheckList(tpAniSirGlobal pMac); + +/****************************************************************************** +* +* Name: pmcOpen +* +* Description: +* Does a PMC open operation on the device. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - open successful +* eHAL_STATUS_FAILURE - open not successful +* +******************************************************************************/ +eHalStatus pmcOpen (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcOpen")); + + /* Initialize basic PMC information about device. */ + pMac->pmc.powerSource = BATTERY_POWER; + pMac->pmc.pmcState = STOPPED; + pMac->pmc.pmcReady = FALSE; + + /* Initialize Power Save Modes */ + pMac->pmc.impsEnabled = FALSE; + pMac->pmc.autoBmpsEntryEnabled = FALSE; + pMac->pmc.smpsEnabled = FALSE; + pMac->pmc.uapsdEnabled = TRUE; + pMac->pmc.bmpsEnabled = TRUE; + pMac->pmc.standbyEnabled = TRUE; + pMac->pmc.wowlEnabled = TRUE; + + vos_mem_set(&(pMac->pmc.bmpsConfig), sizeof(tPmcBmpsConfigParams), 0); + vos_mem_set(&(pMac->pmc.impsConfig), sizeof(tPmcImpsConfigParams), 0); + vos_mem_set(&(pMac->pmc.smpsConfig), sizeof(tPmcSmpsConfigParams), 0); + + /* Allocate a timer to use with IMPS. */ + if (vos_timer_init(&pMac->pmc.hImpsTimer, VOS_TIMER_TYPE_SW, pmcImpsTimerExpired, hHal) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot allocate timer for IMPS")); + return eHAL_STATUS_FAILURE; + } + + /* Allocate a timer used in Full Power State to measure traffic + levels and determine when to enter BMPS. */ + if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer, + VOS_TIMER_TYPE_SW, pmcTrafficTimerExpired, hHal))) + { + pmcLog(pMac, LOGE, FL("Cannot allocate timer for traffic measurement")); + return eHAL_STATUS_FAILURE; + } + + //Initialize the default value for Bmps related config. + pMac->pmc.bmpsConfig.trafficMeasurePeriod = BMPS_TRAFFIC_TIMER_DEFAULT; + pMac->pmc.bmpsConfig.bmpsPeriod = WNI_CFG_LISTEN_INTERVAL_STADEF; + + /* Allocate a timer used to schedule a deferred power save mode exit. */ + if (vos_timer_init(&pMac->pmc.hExitPowerSaveTimer, VOS_TIMER_TYPE_SW, + pmcExitPowerSaveTimerExpired, hHal) !=VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot allocate exit power save mode timer")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for power save check routines and request full power callback routines. */ + if (csrLLOpen(pMac->hHdd, &pMac->pmc.powerSaveCheckList) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot initialize power save check routine list")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestFullPowerList) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot initialize request full power callback routine list")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for request BMPS callback routines. */ + if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestBmpsList) != + eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: cannot initialize request BMPS callback routine list"); + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for request start UAPSD callback routines. */ + if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestStartUapsdList) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: cannot initialize request start UAPSD callback routine list"); + return eHAL_STATUS_FAILURE; + } + + /* Initialize lists for device state update indication callback routines. */ + if (csrLLOpen(pMac->hHdd, &pMac->pmc.deviceStateUpdateIndList) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, "PMC: cannot initialize device state update indication callback list"); + return eHAL_STATUS_FAILURE; + } + + if (csrLLOpen(pMac->hHdd, &pMac->pmc.deferredMsgList) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot initialize deferred msg list")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcStart +* +* Description: +* Does a PMC start operation on the device. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - start successful +* eHAL_STATUS_FAILURE - start not successful +* +******************************************************************************/ +eHalStatus pmcStart (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; + + pmcLog(pMac, LOG2, FL("Entering pmcStart")); + + /* Initialize basic PMC information about device. */ + pMac->pmc.pmcState = FULL_POWER; + pMac->pmc.requestFullPowerPending = FALSE; + pMac->pmc.uapsdSessionRequired = FALSE; + pMac->pmc.wowlModeRequired = FALSE; + pMac->pmc.bmpsRequestedByHdd = FALSE; + pMac->pmc.remainInPowerActiveTillDHCP = FALSE; + pMac->pmc.remainInPowerActiveThreshold = 0; + + /* WLAN Switch initial states. */ + pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_ON; + pMac->pmc.swWlanSwitchState = ePMC_SWITCH_ON; + + /* No IMPS callback routine yet. */ + pMac->pmc.impsCallbackRoutine = NULL; + + /* No STANDBY callback routine yet. */ + pMac->pmc.standbyCallbackRoutine = NULL; + + /* No WOWL callback routine yet. */ + pMac->pmc.enterWowlCallbackRoutine = NULL; + + /* Initialize BMPS traffic counts. */ + pMac->pmc.cLastTxUnicastFrames = 0; + pMac->pmc.cLastRxUnicastFrames = 0; + pMac->pmc.ImpsReqFailed = VOS_FALSE; + pMac->pmc.ImpsReqFailCnt = 0; + pMac->pmc.ImpsReqTimerFailed = 0; + pMac->pmc.ImpsReqTimerfailCnt = 0; + + /* Configure SMPS. */ + if (pMac->pmc.smpsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.smpsConfig.enterOnAc)) + { + if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS) + htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC; + if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS) + htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC; + } + else + htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT; + + if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, + sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + +#if defined(ANI_LOGDUMP) + pmcDumpInit(hHal); +#endif + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcStop +* +* Description: +* Does a PMC stop operation on the device. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - stop successful +* eHAL_STATUS_FAILURE - stop not successful +* +******************************************************************************/ +eHalStatus pmcStop (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tPmcDeferredMsg *pDeferredMsg; + + pmcLog(pMac, LOG2, FL("Entering pmcStop")); + + /* Cancel any running timers. */ + if (vos_timer_stop(&pMac->pmc.hImpsTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot cancel IMPS timer")); + } + + pmcStopTrafficTimer(hHal); + + if (vos_timer_stop(&pMac->pmc.hExitPowerSaveTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot cancel exit power save mode timer")); + } + + /* Do all the callbacks. */ + pmcDoCallbacks(hHal, eHAL_STATUS_FAILURE); + pmcDoBmpsCallbacks(hHal, eHAL_STATUS_FAILURE); + pMac->pmc.uapsdSessionRequired = FALSE; + pmcDoStartUapsdCallbacks(hHal, eHAL_STATUS_FAILURE); + pmcDoStandbyCallbacks(hHal, eHAL_STATUS_FAILURE); + + //purge the deferred msg list + csrLLLock( &pMac->pmc.deferredMsgList ); + while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_FALSE ) ) ) + { + pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link ); + vos_mem_free(pDeferredMsg); + } + csrLLUnlock( &pMac->pmc.deferredMsgList ); + + /* PMC is stopped. */ + pMac->pmc.pmcState = STOPPED; + pMac->pmc.pmcReady = FALSE; + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcClose +* +* Description: +* Does a PMC close operation on the device. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - close successful +* eHAL_STATUS_FAILURE - close not successful +* +******************************************************************************/ +eHalStatus pmcClose (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcClose")); + + /* Free up allocated resources. */ + if (vos_timer_destroy(&pMac->pmc.hImpsTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot deallocate IMPS timer")); + } + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pMac->pmc.hTrafficTimer))) + { + pmcLog(pMac, LOGE, FL("Cannot deallocate traffic timer")); + } + if (vos_timer_destroy(&pMac->pmc.hExitPowerSaveTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot deallocate exit power save mode timer")); + } + + /* + The following list's entries are dynamically allocated so they need their own + cleanup function + */ + pmcClosePowerSaveCheckList(pMac); + pmcCloseRequestFullPowerList(pMac); + pmcCloseRequestBmpsList(pMac); + pmcCloseRequestStartUapsdList(pMac); + pmcCloseDeviceStateUpdateList(pMac); + pmcCloseDeferredMsgList(pMac); + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcSetConfigPowerSave +* +* Description: +* Configures one of the power saving modes. +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode to configure +* pConfigParams - pointer to configuration parameters specific to the +* power saving mode +* +* Returns: +* eHAL_STATUS_SUCCESS - configuration successful +* eHAL_STATUS_FAILURE - configuration not successful +* +******************************************************************************/ +eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); +#endif + + pmcLog(pMac, LOG2, FL("Entering pmcSetConfigPowerSave, power save mode %d"), psMode); + + /* Configure the specified power saving mode. */ + switch (psMode) + { + + case ePMC_IDLE_MODE_POWER_SAVE: + pMac->pmc.impsConfig = *(tpPmcImpsConfigParams)pConfigParams; + pmcLog(pMac, LOG3, FL("IMPS configuration")); + pmcLog(pMac, LOG3, " enter on AC: %d", + pMac->pmc.impsConfig.enterOnAc); + break; + + case ePMC_BEACON_MODE_POWER_SAVE: + pMac->pmc.bmpsConfig = *(tpPmcBmpsConfigParams)pConfigParams; + pmcLog(pMac, LOG3, FL("BMPS configuration")); + pmcLog(pMac, LOG3, " enter on AC: %d", + pMac->pmc.bmpsConfig.enterOnAc); + pmcLog(pMac, LOG3, " TX threshold: %d", + pMac->pmc.bmpsConfig.txThreshold); + pmcLog(pMac, LOG3, " RX threshold: %d", + pMac->pmc.bmpsConfig.rxThreshold); + pmcLog(pMac, LOG3, " traffic measurement period (ms): %d", + pMac->pmc.bmpsConfig.trafficMeasurePeriod); + pmcLog(pMac, LOG3, " BMPS period: %d", + pMac->pmc.bmpsConfig.bmpsPeriod); + pmcLog(pMac, LOG3, " beacons to forward code: %d", + pMac->pmc.bmpsConfig.forwardBeacons); + pmcLog(pMac, LOG3, " value of N: %d", + pMac->pmc.bmpsConfig.valueOfN); + pmcLog(pMac, LOG3, " use PS poll: %d", + pMac->pmc.bmpsConfig.usePsPoll); + pmcLog(pMac, LOG3, " set PM on last frame: %d", + pMac->pmc.bmpsConfig.setPmOnLastFrame); + pmcLog(pMac, LOG3, " value of enableBeaconEarlyTermination: %d", + pMac->pmc.bmpsConfig.enableBeaconEarlyTermination); + pmcLog(pMac, LOG3, " value of bcnEarlyTermWakeInterval: %d", + pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_BMPS_SET_CONFIG; + /* possible loss of data due to mismatch but expectation is that + values can reasonably be expected to fit in target widths */ + psRequest.bmps_auto_timer_duration = (v_U16_t)pMac->pmc.bmpsConfig.trafficMeasurePeriod; + psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + + break; + + case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE: + pMac->pmc.smpsConfig = *(tpPmcSmpsConfigParams)pConfigParams; + pmcLog(pMac, LOG3, FL("SMPS configuration")); + pmcLog(pMac, LOG3, " mode: %d", pMac->pmc.smpsConfig.mode); + pmcLog(pMac, LOG3, " enter on AC: %d", + pMac->pmc.smpsConfig.enterOnAc); + break; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + //Send the power save config down to PE/HAL/FW if BMPS mode is being configured + //and pmcReady has been invoked + if(PMC_IS_READY(pMac) && psMode == ePMC_BEACON_MODE_POWER_SAVE) + { + if (pmcSendPowerSaveConfigMessage(hHal) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcGetConfigPowerSave +* +* Description: +* Get the config for the specified power save mode +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode to configure +* pConfigParams - pointer to configuration parameters specific to the +* power saving mode +* +* Returns: +* eHAL_STATUS_SUCCESS - configuration successful +* eHAL_STATUS_FAILURE - configuration not successful +* +******************************************************************************/ +eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcGetConfigPowerSave, power save mode %d"), psMode); + + /* Configure the specified power saving mode. */ + switch (psMode) + { + + case ePMC_IDLE_MODE_POWER_SAVE: + *(tpPmcImpsConfigParams)pConfigParams = pMac->pmc.impsConfig; + break; + + case ePMC_BEACON_MODE_POWER_SAVE: + *(tpPmcBmpsConfigParams)pConfigParams = pMac->pmc.bmpsConfig; + break; + + case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE: + *(tpPmcSmpsConfigParams)pConfigParams = pMac->pmc.smpsConfig; + break; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} +/****************************************************************************** +* +* Name: pmcEnablePowerSave +* +* Description: +* Enables one of the power saving modes. +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode to enable +* +* Returns: +* eHAL_STATUS_SUCCESS - successfully enabled +* eHAL_STATUS_FAILURE - not successfully enabled +* +******************************************************************************/ +eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_PS_MODE_ENABLE_REQ; + psRequest.enable_disable_powersave_mode = psMode; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, FL("Entering pmcEnablePowerSave, power save mode %d"), psMode); + + /* Enable the specified power saving mode. */ + switch (psMode) + { + + case ePMC_IDLE_MODE_POWER_SAVE: + pMac->pmc.impsEnabled = TRUE; + break; + + case ePMC_BEACON_MODE_POWER_SAVE: + pMac->pmc.bmpsEnabled = TRUE; + break; + + case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE: + pMac->pmc.smpsEnabled = TRUE; + + /* If PMC already started, then turn on SMPS. */ + if (pMac->pmc.pmcState != STOPPED) + if (pMac->pmc.powerSource != AC_POWER || + pMac->pmc.smpsConfig.enterOnAc) + { + if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS) + htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC; + if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS) + htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC; + if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, + sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + } + break; + + case ePMC_UAPSD_MODE_POWER_SAVE: + pMac->pmc.uapsdEnabled = TRUE; + break; + + case ePMC_STANDBY_MODE_POWER_SAVE: + pMac->pmc.standbyEnabled = TRUE; + break; + + case ePMC_WOWL_MODE_POWER_SAVE: + pMac->pmc.wowlEnabled = TRUE; + break; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} +/* --------------------------------------------------------------------------- + \fn pmcStartAutoBmpsTimer + \brief Starts a timer that periodically polls all the registered + module for entry into Bmps mode. This timer is started only if BMPS is + enabled and whenever the device is in full power. + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_START_BMPS_AUTO_TIMER_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, FL("Entering pmcStartAutoBmpsTimer")); + + /* Check if BMPS is enabled. */ + if (!pMac->pmc.bmpsEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot enable BMPS timer. BMPS is disabled"); + return eHAL_STATUS_FAILURE; + } + + pMac->pmc.autoBmpsEntryEnabled = TRUE; + + /* Check if there is an Infra session. If there is no Infra session, timer will be started + when STA associates to AP */ + + if (pmcShouldBmpsTimerRun(pMac)) + { + if (pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + } + + + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcStopAutoBmpsTimer + \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer + Stopping the timer does not cause a device state change. Only the timer + is stopped. If "Full Power" is desired, use the pmcRequestFullPower API + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_STOP_BMPS_AUTO_TIMER_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, FL("Entering pmcStopAutoBmpsTimer")); + + pMac->pmc.autoBmpsEntryEnabled = FALSE; + /* If uapsd session is not required or HDD has not requested BMPS, stop the auto bmps timer.*/ + if (!pMac->pmc.uapsdSessionRequired && !pMac->pmc.bmpsRequestedByHdd) + pmcStopTrafficTimer(hHal); + + return eHAL_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Name: pmcDisablePowerSave +* +* Description: +* Disables one of the power saving modes. +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode to disable +* +* Returns: +* eHAL_STATUS_SUCCESS - successfully disabled +* eHAL_STATUS_FAILURE - not successfully disabled +* +******************************************************************************/ +eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_PS_MODE_DISABLE_REQ; + psRequest.enable_disable_powersave_mode = psMode; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, FL("Entering pmcDisablePowerSave, power save mode %d"), psMode); + + /* Disable the specified power saving mode. */ + switch (psMode) + { + + case ePMC_IDLE_MODE_POWER_SAVE: + pMac->pmc.impsEnabled = FALSE; + break; + + case ePMC_BEACON_MODE_POWER_SAVE: + pMac->pmc.bmpsEnabled = FALSE; + break; + + case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE: + pMac->pmc.smpsEnabled = FALSE; + + /* Turn off SMPS. */ + htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT; + if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, + sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + break; + + case ePMC_UAPSD_MODE_POWER_SAVE: + pMac->pmc.uapsdEnabled = FALSE; + break; + + case ePMC_STANDBY_MODE_POWER_SAVE: + pMac->pmc.standbyEnabled = FALSE; + break; + + case ePMC_WOWL_MODE_POWER_SAVE: + pMac->pmc.wowlEnabled = FALSE; + break; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcQueryPowerState +* +* Description: +* Returns the current power state of the device. +* +* Parameters: +* hHal - HAL handle for device +* pPowerState - pointer to location to return power state +* pHwWlanSwitchState - pointer to location to return Hardware WLAN +* Switch state +* pSwWlanSwitchState - pointer to location to return Software WLAN +* Switch state +* +* Returns: +* eHAL_STATUS_SUCCESS - power state successfully returned +* eHAL_STATUS_FAILURE - power state not successfully returned +* +******************************************************************************/ +eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState, + tPmcSwitchState *pHwWlanSwitchState, tPmcSwitchState *pSwWlanSwitchState) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcQueryPowerState")); + + /* Return current power state based on PMC state. */ + if(pPowerState != NULL) + { + /* Return current power state based on PMC state. */ + switch (pMac->pmc.pmcState) + { + + case FULL_POWER: + *pPowerState = ePMC_FULL_POWER; + break; + + default: + *pPowerState = ePMC_LOW_POWER; + break; + } + } + + /* Return current switch settings. */ + if(pHwWlanSwitchState != NULL) + *pHwWlanSwitchState = pMac->pmc.hwWlanSwitchState; + if(pSwWlanSwitchState != NULL) + *pSwWlanSwitchState = pMac->pmc.swWlanSwitchState; + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcIsPowerSaveEnabled +* +* Description: +* Checks if the device is able to enter one of the power save modes. +* "Able to enter" means the power save mode is enabled for the device +* and the host is using the correct power source for entry into the +* power save mode. This routine does not indicate whether the device +* is actually in the power save mode at a particular point in time. +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode +* +* Returns: +* TRUE if device is able to enter the power save mode, FALSE otherwise +* +******************************************************************************/ +tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcIsPowerSaveEnabled, power save mode %d"), psMode); + + /* Check ability to enter based on the specified power saving mode. */ + switch (psMode) + { + + case ePMC_IDLE_MODE_POWER_SAVE: + return pMac->pmc.impsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.impsConfig.enterOnAc); + + case ePMC_BEACON_MODE_POWER_SAVE: + return pMac->pmc.bmpsEnabled; + + case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE: + return pMac->pmc.smpsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.smpsConfig.enterOnAc); + + case ePMC_UAPSD_MODE_POWER_SAVE: + return pMac->pmc.uapsdEnabled; + + case ePMC_STANDBY_MODE_POWER_SAVE: + return pMac->pmc.standbyEnabled; + + case ePMC_WOWL_MODE_POWER_SAVE: + return pMac->pmc.wowlEnabled; + break; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + PMC_ABORT; + return FALSE; + } +} + + +/****************************************************************************** +* +* Name: pmcRequestFullPower +* +* Description: +* Request that the device be brought to full power state. +* +* Parameters: +* hHal - HAL handle for device +* callbackRoutine - routine to call when device actually achieves full +* power state if "eHAL_STATUS_PMC_PENDING" is returned +* callbackContext - value to be passed as parameter to routine specified +* above +* fullPowerReason - Reason for requesting full power mode. This is used +* by PE to decide whether data null should be sent to +* AP when exiting BMPS mode. Caller should use the +* eSME_LINK_DISCONNECTED reason if link is disconnected +* and there is no need to tell the AP that we are going +* out of power save. +* +* Returns: +* eHAL_STATUS_SUCCESS - device brought to full power state +* eHAL_STATUS_FAILURE - device cannot be brought to full power state +* eHAL_STATUS_PMC_PENDING - device is being brought to full power state, +* callbackRoutine will be called when completed +* +******************************************************************************/ +eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext, tRequestFullPowerReason fullPowerReason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpRequestFullPowerEntry pEntry; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_ENTER_FULL_POWER_REQ; + psRequest.full_power_request_reason = fullPowerReason; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, FL("Entering pmcRequestFullPower")); + + if( !PMC_IS_READY(pMac) ) + { + pmcLog(pMac, LOGE, FL("Requesting Full Power when PMC not ready")); + pmcLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s"), + pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + /* If HDD is requesting full power, clear any buffered requests for WOWL and BMPS that were + requested by HDD previously */ + if(SIR_IS_FULL_POWER_NEEDED_BY_HDD(fullPowerReason)) + { + pMac->pmc.bmpsRequestedByHdd = FALSE; + pMac->pmc.wowlModeRequired = FALSE; + } + + /* If already in full power, just return. */ + if (pMac->pmc.pmcState == FULL_POWER) + return eHAL_STATUS_SUCCESS; + + /* If in IMPS State, then cancel the timer. */ + if (pMac->pmc.pmcState == IMPS) + if (vos_timer_stop(&pMac->pmc.hImpsTimer) != VOS_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Cannot cancel IMPS timer")); + } + /* Enter Request Full Power State. */ + if (pmcEnterRequestFullPowerState(hHal, fullPowerReason) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + + /* If able to enter Request Full Power State, then request is pending. + Allocate entry for request full power callback routine list. */ + //If caller doesn't need a callback, simply waits up the chip. + if( callbackRoutine ) + { + pEntry = vos_mem_malloc(sizeof(tRequestFullPowerEntry)); + if ( NULL == pEntry ) + { + pmcLog(pMac, LOGE, + FL("Cannot allocate memory for request full power routine list entry")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->callbackRoutine = callbackRoutine; + pEntry->callbackContext = callbackContext; + + /* Add entry to list. */ + csrLLInsertTail(&pMac->pmc.requestFullPowerList, &pEntry->link, TRUE); + } + + return eHAL_STATUS_PMC_PENDING; +} + + +/****************************************************************************** +* +* Name: pmcRequestImps +* +* Description: +* Request that the device be placed in Idle Mode Power Save (IMPS). +* The Common Scan/Roam Module makes this request. The device will be +* placed into IMPS for the specified amount of time, and then returned +* to full power. +* +* Parameters: +* hHal - HAL handle for device +* impsPeriod - amount of time to remain in IMPS (milliseconds) +* callbackRoutine - routine to call when IMPS period has finished and +* the device has been brought to full power +* callbackContext - value to be passed as parameter to routine specified +* above +* +* Returns: +* eHAL_STATUS_SUCCESS - device will enter IMPS +* eHAL_STATUS_PMC_DISABLED - IMPS is disabled +* eHAL_STATUS_PMC_NOT_NOW - another module is prohibiting entering IMPS +* at this time +* eHAL_STATUS_PMC_AC_POWER - IMPS is disabled when host operating from +* AC power +* eHAL_STATUS_PMC_ALREADY_IN_IMPS - device is already in IMPS +* eHAL_STATUS_PMC_SYS_ERROR - system error that prohibits entering IMPS +* +******************************************************************************/ +eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_IMPS_ENTER_REQ; + psRequest.imps_period = impsPeriod; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + + pmcLog(pMac, LOG2, FL("Entering pmcRequestImps")); + + status = pmcEnterImpsCheck( pMac ); + if( HAL_STATUS_SUCCESS( status ) ) + { + /* Enter Request IMPS State. */ + status = pmcEnterRequestImpsState( hHal ); + if (HAL_STATUS_SUCCESS( status )) + { + /* Save the period and callback routine for when we need it. */ + pMac->pmc.impsPeriod = impsPeriod; + pMac->pmc.impsCallbackRoutine = callbackRoutine; + pMac->pmc.impsCallbackContext = callbackContext; + + } + else + { + status = eHAL_STATUS_PMC_SYS_ERROR; + } + } + + return status; +} + + +/****************************************************************************** +* +* Name: pmcRegisterPowerSaveCheck +* +* Description: +* Allows a routine to be registered so that the routine is called whenever +* the device is about to enter one of the power save modes. This routine +* will say whether the device is allowed to enter the power save mode at +* the time of the call. +* +* Parameters: +* hHal - HAL handle for device +* checkRoutine - routine to call before entering a power save mode, should +* return TRUE if the device is allowed to enter the power +* save mode, FALSE otherwise +* checkContext - value to be passed as parameter to routine specified above +* +* Returns: +* eHAL_STATUS_SUCCESS - successfully registered +* eHAL_STATUS_FAILURE - not successfully registered +* +******************************************************************************/ +eHalStatus pmcRegisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext), + void *checkContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPowerSaveCheckEntry pEntry; + + pmcLog(pMac, LOG2, FL("Entering pmcRegisterPowerSaveCheck")); + + /* Allocate entry for power save check routine list. */ + pEntry = vos_mem_malloc(sizeof(tPowerSaveCheckEntry)); + if ( NULL == pEntry ) + { + pmcLog(pMac, LOGE, FL("Cannot allocate memory for power save check routine list entry")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->checkRoutine = checkRoutine; + pEntry->checkContext = checkContext; + + /* Add entry to list. */ + csrLLInsertTail(&pMac->pmc.powerSaveCheckList, &pEntry->link, FALSE); + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** +* +* Name: pmcDeregisterPowerSaveCheck +* +* Description: +* Re-registers a routine that was previously registered with +* pmcRegisterPowerSaveCheck. +* +* Parameters: +* hHal - HAL handle for device +* checkRoutine - routine to deregister +* +* Returns: +* eHAL_STATUS_SUCCESS - successfully deregistered +* eHAL_STATUS_FAILURE - not successfully deregistered +* +******************************************************************************/ +eHalStatus pmcDeregisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext)) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpPowerSaveCheckEntry pPowerSaveCheckEntry; + + pmcLog(pMac, LOG2, FL("Entering pmcDeregisterPowerSaveCheck")); + + /* Find entry in the power save check routine list that matches + the specified routine and remove it. */ + pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE); + while (pEntry != NULL) + { + pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link); + if (pPowerSaveCheckEntry->checkRoutine == checkRoutine) + { + if (csrLLRemoveEntry(&pMac->pmc.powerSaveCheckList, pEntry, FALSE)) + { + vos_mem_free(pPowerSaveCheckEntry); + } + else + { + pmcLog(pMac, LOGE, FL("Cannot remove power save check routine list entry")); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + } + pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE); + } + + /* Could not find matching entry. */ + return eHAL_STATUS_FAILURE; +} + + +static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) +{ + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE; + + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if(pEntry) + { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + + pmcLog(pMac, LOG2, FL("process message = %d"), pMsg->messageType); + + /* Process each different type of message. */ + switch (pMsg->messageType) + { + + /* We got a response to our IMPS request. */ + case eWNI_PMC_ENTER_IMPS_RSP: + pmcLog(pMac, LOG2, FL("Rcvd eWNI_PMC_ENTER_IMPS_RSP with status = %d"), pMsg->statusCode); + if( (eSmeCommandEnterImps != pCommand->command) && (eSmeCommandEnterStandby != pCommand->command) ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_IMPS_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + if(pMac->pmc.pmcState == REQUEST_IMPS) + { + /* Enter IMPS State if response indicates success. */ + if (pMsg->statusCode == eSIR_SME_SUCCESS) + { + pMac->pmc.ImpsReqFailed = VOS_FALSE; + pmcEnterImpsState(pMac); + if (!(pMac->pmc.ImpsReqFailed || pMac->pmc.ImpsReqTimerFailed) && pMac->pmc.ImpsReqFailCnt) + { + pmcLog(pMac, LOGE, + FL("Response message to request to enter IMPS was failed %d times before success"), + pMac->pmc.ImpsReqFailCnt); + pMac->pmc.ImpsReqFailCnt = 0; + } + } + + /* If response is failure, then we stay in Full Power State and tell everyone that we aren't going into IMPS. */ + else + { + pMac->pmc.ImpsReqFailed = VOS_TRUE; + if (!(pMac->pmc.ImpsReqFailCnt & 0xF)) + { + pmcLog(pMac, LOGE, + FL("Response message to request to enter IMPS indicates failure, status %x, FailCnt - %d"), + pMsg->statusCode, ++pMac->pmc.ImpsReqFailCnt); + } + else + { + pMac->pmc.ImpsReqFailCnt++; + } + pmcEnterFullPowerState(pMac); + } + } + else if (pMac->pmc.pmcState == REQUEST_STANDBY) + { + /* Enter STANDBY State if response indicates success. */ + if (pMsg->statusCode == eSIR_SME_SUCCESS) + { + pmcEnterStandbyState(pMac); + pmcDoStandbyCallbacks(pMac, eHAL_STATUS_SUCCESS); + } + + /* If response is failure, then we stay in Full Power State + and tell everyone that we aren't going into STANDBY. */ + else + { + pmcLog(pMac, LOGE, "PMC: response message to request to enter " + "standby indicates failure, status %x", pMsg->statusCode); + pmcEnterFullPowerState(pMac); + pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE); + } + } + else + { + pmcLog(pMac, LOGE, "PMC: Enter IMPS rsp rcvd when device is " + "in %d state", pMac->pmc.pmcState); + } + break; + + /* We got a response to our wake from IMPS request. */ + case eWNI_PMC_EXIT_IMPS_RSP: + pmcLog(pMac, LOG2, FL("Rcvd eWNI_PMC_EXIT_IMPS_RSP with status = %d"), pMsg->statusCode); + if( eSmeCommandExitImps != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_IMPS_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_FULL_POWER) + { + pmcLog(pMac, LOGE, FL("Got Exit IMPS Response Message while " + "in state %d"), pMac->pmc.pmcState); + break; + } + + /* Enter Full Power State. */ + if (pMsg->statusCode != eSIR_SME_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Response message to request to exit " + "IMPS indicates failure, status %x"), pMsg->statusCode); + if (eHAL_STATUS_SUCCESS == + pmcSendMessage(pMac, eWNI_PMC_EXIT_IMPS_REQ, NULL, 0)) { + fRemoveCommand = eANI_BOOLEAN_FALSE; + pMac->pmc.pmcState = REQUEST_FULL_POWER; + pmcLog(pMac, LOGE, FL("eWNI_PMC_EXIT_IMPS_REQ sent again" + " to PE")); + break; + } + } + pmcEnterFullPowerState(pMac); + break; + + /* We got a response to our BMPS request. */ + case eWNI_PMC_ENTER_BMPS_RSP: + pmcLog(pMac, LOG2, FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP with status = %d"), pMsg->statusCode); + if( eSmeCommandEnterBmps != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE; + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_BMPS) + { + pmcLog(pMac, LOGE, + FL("Got Enter BMPS Response Message while in state %d"), pMac->pmc.pmcState); + break; + } + + /* Enter BMPS State if response indicates success. */ + if (pMsg->statusCode == eSIR_SME_SUCCESS) + { + pmcEnterBmpsState(pMac); + /* Note: If BMPS was requested because of start UAPSD, + there will no entries for BMPS callback routines and + pmcDoBmpsCallbacks will be a No-Op*/ + pmcDoBmpsCallbacks(pMac, eHAL_STATUS_SUCCESS); + } + /* If response is failure, then we stay in Full Power State and tell everyone that we aren't going into BMPS. */ + else + { + pmcLog(pMac, LOGE, + FL("Response message to request to enter BMPS indicates failure, status %x"), + pMsg->statusCode); + pmcEnterFullPowerState(pMac); + //Do not call UAPSD callback here since it may be re-entered + pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE); + } + break; + + /* We got a response to our wake from BMPS request. */ + case eWNI_PMC_EXIT_BMPS_RSP: + pmcLog(pMac, LOG2, FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP with status = %d"), pMsg->statusCode); + if( eSmeCommandExitBmps != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_FULL_POWER) + { + pmcLog(pMac, LOGE, + FL("Got Exit BMPS Response Message while in state %d"), pMac->pmc.pmcState); + break; + } + + /* Enter Full Power State. */ + if (pMsg->statusCode != eSIR_SME_SUCCESS) + { + pmcLog(pMac, LOGP, + FL("Response message to request to exit BMPS indicates failure, status %x"), + pMsg->statusCode); + /*Status is not succes, so set back the pmc state as BMPS*/ + pMac->pmc.pmcState = BMPS; + } + else + pmcEnterFullPowerState(pMac); + break; + + /* We got a response to our Start UAPSD request. */ + case eWNI_PMC_ENTER_UAPSD_RSP: + pmcLog(pMac, LOG2, FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP with status = %d"), pMsg->statusCode); + if( eSmeCommandEnterUapsd != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_START_UAPSD) + { + pmcLog(pMac, LOGE, + FL("Got Enter Uapsd rsp Message while in state %d"), pMac->pmc.pmcState); + break; + } + + /* Enter UAPSD State if response indicates success. */ + if (pMsg->statusCode == eSIR_SME_SUCCESS) + { + pmcEnterUapsdState(pMac); + pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_SUCCESS); + } + /* If response is failure, then we try to put the chip back in + BMPS mode*/ + else { + pmcLog(pMac, LOGE, "PMC: response message to request to enter " + "UAPSD indicates failure, status %x", pMsg->statusCode); + //Need to reset the UAPSD flag so pmcEnterBmpsState won't try to enter UAPSD. + pMac->pmc.uapsdSessionRequired = FALSE; + pmcEnterBmpsState(pMac); + //UAPSD will not be retied in this case so tell requester we are done with failure + pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE); + } + break; + + /* We got a response to our Stop UAPSD request. */ + case eWNI_PMC_EXIT_UAPSD_RSP: + pmcLog(pMac, LOG2, FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP with status = %d"), pMsg->statusCode); + if( eSmeCommandExitUapsd != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_STOP_UAPSD) + { + pmcLog(pMac, LOGE, + FL("Got Exit Uapsd rsp Message while in state %d"), pMac->pmc.pmcState); + break; + } + + /* Enter BMPS State */ + if (pMsg->statusCode != eSIR_SME_SUCCESS) { + pmcLog(pMac, LOGP, "PMC: response message to request to exit " + "UAPSD indicates failure, status %x", pMsg->statusCode); + } + pmcEnterBmpsState(pMac); + break; + + /* We got a response to our enter WOWL request. */ + case eWNI_PMC_ENTER_WOWL_RSP: + + if( eSmeCommandEnterWowl != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_WOWL_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL) + { + pmcLog(pMac, LOGE, FL("Got eWNI_PMC_ENTER_WOWL_RSP while in state %s"), + pmcGetPmcStateStr(pMac->pmc.pmcState)); + break; + } + + /* Enter WOWL State if response indicates success. */ + if (pMsg->statusCode == eSIR_SME_SUCCESS) { + pmcEnterWowlState(pMac); + pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_SUCCESS); + } + + /* If response is failure, then we try to put the chip back in + BMPS mode*/ + else { + pmcLog(pMac, LOGE, "PMC: response message to request to enter " + "WOWL indicates failure, status %x", pMsg->statusCode); + pmcEnterBmpsState(pMac); + pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE); + } + break; + + /* We got a response to our exit WOWL request. */ + case eWNI_PMC_EXIT_WOWL_RSP: + + if( eSmeCommandExitWowl != pCommand->command ) + { + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_WOWL_RSP without request")); + fRemoveCommand = eANI_BOOLEAN_FALSE; + break; + } + /* Check that we are in the correct state for this message. */ + if (pMac->pmc.pmcState != REQUEST_EXIT_WOWL) + { + pmcLog(pMac, LOGE, FL("Got Exit WOWL rsp Message while in state %d"), pMac->pmc.pmcState); + break; + } + + /* Enter BMPS State */ + if (pMsg->statusCode != eSIR_SME_SUCCESS) { + pmcLog(pMac, LOGP, "PMC: response message to request to exit " + "WOWL indicates failure, status %x", pMsg->statusCode); + } + pmcEnterBmpsState(pMac); + break; + + default: + pmcLog(pMac, LOGE, FL("Invalid message type %d received"), pMsg->messageType); + PMC_ABORT; + break; + }//switch + + if( fRemoveCommand ) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) ) + { + pmcReleaseCommand( pMac, pCommand ); + smeProcessPendingQueue( pMac ); + } + } + } + else + { + pmcLog(pMac, LOGE, FL("message type %d received but no request is found"), pMsg->messageType); + } +} + + +/****************************************************************************** +* +* Name: pmcMessageProcessor +* +* Description: +* Process a message received by PMC. +* +* Parameters: +* hHal - HAL handle for device +* pMsg - pointer to received message +* +* Returns: +* nothing +* +******************************************************************************/ +void pmcMessageProcessor (tHalHandle hHal, tSirSmeRsp *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Message type %d"), pMsg->messageType); + + switch( pMsg->messageType ) + { + case eWNI_PMC_EXIT_BMPS_IND: + //When PMC needs to handle more indication from PE, they need to be added here. + { + /* Device left BMPS on its own. */ + pmcLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_IND with status = %d"), pMsg->statusCode); + /* Check that we are in the correct state for this message. */ + switch(pMac->pmc.pmcState) + { + case BMPS: + case REQUEST_START_UAPSD: + case UAPSD: + case REQUEST_STOP_UAPSD: + case REQUEST_ENTER_WOWL: + case WOWL: + case REQUEST_EXIT_WOWL: + case REQUEST_FULL_POWER: + pmcLog(pMac, LOGW, FL("Got eWNI_PMC_EXIT_BMPS_IND while in state %d"), pMac->pmc.pmcState); + break; + default: + pmcLog(pMac, LOGE, FL("Got eWNI_PMC_EXIT_BMPS_IND while in state %d"), pMac->pmc.pmcState); + PMC_ABORT; + break; + } + + /* Enter Full Power State. */ + if (pMsg->statusCode != eSIR_SME_SUCCESS) + { + pmcLog(pMac, LOGP, FL("Exit BMPS indication indicates failure, status %x"), pMsg->statusCode); + } + else + { + tpSirSmeExitBmpsInd pExitBmpsInd = (tpSirSmeExitBmpsInd)pMsg; + pmcEnterRequestFullPowerState(hHal, pExitBmpsInd->exitBmpsReason); + } + break; + } + + default: + pmcProcessResponse( pMac, pMsg ); + break; + } + +} + + +tANI_BOOLEAN pmcValidateConnectState( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if ( !csrIsInfraConnected( pMac ) ) + { + pmcLog(pMac, LOGW, "PMC: STA not associated. BMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } + + //Cannot have other session + if ( csrIsIBSSStarted( pMac ) ) + { + pmcLog(pMac, LOGW, "PMC: IBSS started. BMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } + if ( csrIsBTAMPStarted( pMac ) ) + { + pmcLog(pMac, LOGW, "PMC: BT-AMP exists. BMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } + if ((vos_concurrent_open_sessions_running()) && + (csrIsConcurrentInfraConnected( pMac ) || + (vos_get_concurrency_mode()& VOS_SAP) || + (vos_get_concurrency_mode()& VOS_P2P_GO))) + { + pmcLog(pMac, LOGW, "PMC: Multiple active sessions exists. BMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } +#ifdef FEATURE_WLAN_TDLS + if (pMac->isTdlsPowerSaveProhibited) { + pmcLog(pMac, LOGE, FL("TDLS peer(s) connected/discovery sent. " + "Dont enter BMPS")); + return eANI_BOOLEAN_FALSE; + } +#endif + return eANI_BOOLEAN_TRUE; +} + +tANI_BOOLEAN pmcAllowImps( tHalHandle hHal ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + //Cannot have other session like IBSS or BT AMP running + if ( csrIsIBSSStarted( pMac ) ) + { + pmcLog(pMac, LOGW, "PMC: IBSS started. IMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } + if ( csrIsBTAMPStarted( pMac ) ) + { + pmcLog(pMac, LOGW, "PMC: BT-AMP exists. IMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } + + //All sessions must be disconnected to allow IMPS + if ( !csrIsAllSessionDisconnected( pMac ) ) + { + pmcLog(pMac, LOGW, + "PMC: At-least one connected session. IMPS cannot be entered"); + return eANI_BOOLEAN_FALSE; + } + + return eANI_BOOLEAN_TRUE; +} + +/****************************************************************************** +* +* Name: pmcRequestBmps +* +* Description: +* Request that the device be put in BMPS state. +* +* Parameters: +* hHal - HAL handle for device +* callbackRoutine - Callback routine invoked in case of success/failure +* callbackContext - value to be passed as parameter to routine specified +* above +* +* Returns: +* eHAL_STATUS_SUCCESS - device is in BMPS state +* eHAL_STATUS_FAILURE - device cannot be brought to BMPS state +* eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state, +* +******************************************************************************/ +eHalStatus pmcRequestBmps ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpRequestBmpsEntry pEntry; + eHalStatus status; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_BMPS_ENTER_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, "PMC: entering pmcRequestBmps"); + + /* If already in BMPS, just return. */ + if (pMac->pmc.pmcState == BMPS || REQUEST_START_UAPSD == pMac->pmc.pmcState || UAPSD == pMac->pmc.pmcState) + { + pmcLog(pMac, LOG2, "PMC: Device already in BMPS pmcState %d", pMac->pmc.pmcState); + pMac->pmc.bmpsRequestedByHdd = TRUE; + return eHAL_STATUS_SUCCESS; + } + + status = pmcEnterBmpsCheck( pMac ); + if(HAL_STATUS_SUCCESS( status )) + { + status = pmcEnterRequestBmpsState(hHal); + /* Enter Request BMPS State. */ + if ( HAL_STATUS_SUCCESS( status ) ) + { + /* Remember that HDD requested BMPS. This flag will be used to put the + device back into BMPS if any module other than HDD (e.g. CSR, QoS, or BAP) + requests full power for any reason */ + pMac->pmc.bmpsRequestedByHdd = TRUE; + + /* If able to enter Request BMPS State, then request is pending. + Allocate entry for request BMPS callback routine list. */ + pEntry = vos_mem_malloc(sizeof(tRequestBmpsEntry)); + if ( NULL == pEntry ) + { + pmcLog(pMac, LOGE, "PMC: cannot allocate memory for request " + "BMPS routine list entry"); + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->callbackRoutine = callbackRoutine; + pEntry->callbackContext = callbackContext; + + /* Add entry to list. */ + csrLLInsertTail(&pMac->pmc.requestBmpsList, &pEntry->link, FALSE); + + status = eHAL_STATUS_PMC_PENDING; + } + else + { + status = eHAL_STATUS_FAILURE; + } + } + /* Retry to enter the BMPS if the + status = eHAL_STATUS_PMC_NOT_NOW */ + else if (status == eHAL_STATUS_PMC_NOT_NOW) + { + pmcStopTrafficTimer(hHal); + pmcLog(pMac, LOG1, FL("Can't enter BMPS+++")); + if (pmcShouldBmpsTimerRun(pMac)) + { + if (pmcStartTrafficTimer(pMac, + pMac->pmc.bmpsConfig.trafficMeasurePeriod) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOG1, FL("Cannot start BMPS Retry timer")); + } + pmcLog(pMac, LOG1, + FL("BMPS Retry Timer already running or started")); + } + } + + return status; +} + +/****************************************************************************** +* +* Name: pmcStartUapsd +* +* Description: +* Request that the device be put in UAPSD state. +* +* Parameters: +* hHal - HAL handle for device +* callbackRoutine - Callback routine invoked in case of success/failure +* callbackContext - value to be passed as parameter to routine specified +* above +* +* Returns: +* eHAL_STATUS_SUCCESS - device is in UAPSD state +* eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state +* eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state +* eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled +* +******************************************************************************/ +eHalStatus pmcStartUapsd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpStartUapsdEntry pEntry; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_UAPSD_START_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, "PMC: entering pmcStartUapsd"); + + if( !PMC_IS_READY(pMac) ) + { + pmcLog(pMac, LOGE, FL("Requesting UAPSD when PMC not ready")); + pmcLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s"), + pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + /* Check if BMPS is enabled. */ + if (!pMac->pmc.bmpsEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot enter UAPSD. BMPS is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + /* Check if UAPSD is enabled. */ + if (!pMac->pmc.uapsdEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot enter UAPSD. UAPSD is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + /* If already in UAPSD, just return. */ + if (pMac->pmc.pmcState == UAPSD) + return eHAL_STATUS_SUCCESS; + + /* Check that we are associated. */ + if (!pmcValidateConnectState( pMac )) + { + pmcLog(pMac, LOGE, "PMC: STA not associated with an AP. UAPSD cannot be entered"); + return eHAL_STATUS_FAILURE; + } + + /* Enter REQUEST_START_UAPSD State. */ + if (pmcEnterRequestStartUapsdState(hHal) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + + if( NULL != callbackRoutine ) + { + /* If success then request is pending. Allocate entry for callback routine list. */ + pEntry = vos_mem_malloc(sizeof(tStartUapsdEntry)); + if ( NULL == pEntry ) + { + pmcLog(pMac, LOGE, "PMC: cannot allocate memory for request " + "start UAPSD routine list entry"); + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->callbackRoutine = callbackRoutine; + pEntry->callbackContext = callbackContext; + + /* Add entry to list. */ + csrLLInsertTail(&pMac->pmc.requestStartUapsdList, &pEntry->link, FALSE); + } + + return eHAL_STATUS_PMC_PENDING; +} + +/****************************************************************************** +* +* Name: pmcStopUapsd +* +* Description: +* Request that the device be put out of UAPSD state. +* +* Parameters: +* hHal - HAL handle for device +* +* Returns: +* eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state +* eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state +* +******************************************************************************/ +eHalStatus pmcStopUapsd (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_UAPSD_STOP_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, "PMC: entering pmcStopUapsd"); + + /* Clear any buffered command for entering UAPSD */ + pMac->pmc.uapsdSessionRequired = FALSE; + + /* Nothing to be done if we are already out of UAPSD. This can happen if + some other module (HDD, BT-AMP) requested Full Power.*/ + if (pMac->pmc.pmcState != UAPSD && pMac->pmc.pmcState != REQUEST_STOP_UAPSD) + { + pmcLog(pMac, LOGW, "PMC: Device is already out of UAPSD " + "state. Current state is %d", pMac->pmc.pmcState); + return eHAL_STATUS_SUCCESS; + } + + /* Enter REQUEST_STOP_UAPSD State*/ + if (pmcEnterRequestStopUapsdState(hHal) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcRequestStandby + \brief Request that the device be put in standby. + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine invoked in case of success/failure + \param callbackContext - value to be passed as parameter to callback + \return eHalStatus + eHAL_STATUS_SUCCESS - device is in Standby mode + eHAL_STATUS_FAILURE - device cannot be put in standby mode + eHAL_STATUS_PMC_PENDING - device is being put in standby mode + ---------------------------------------------------------------------------*/ +extern eHalStatus pmcRequestStandby ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); + + vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); + psRequest.event_subtype = WLAN_ENTER_STANDBY_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); +#endif + + pmcLog(pMac, LOG2, "PMC: entering pmcRequestStandby"); + + /* Check if standby is enabled. */ + if (!pMac->pmc.standbyEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot enter standby. Standby is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + if( !PMC_IS_READY(pMac) ) + { + pmcLog(pMac, LOGE, FL("Requesting standby when PMC not ready")); + pmcLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s"), + pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + /* If already in STANDBY, just return. */ + if (pMac->pmc.pmcState == STANDBY) + return eHAL_STATUS_SUCCESS; + + + if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "WLAN: IBSS or BT-AMP session present. Cannot honor standby request"); + return eHAL_STATUS_PMC_NOT_NOW; + } + + /* Enter Request Standby State. */ + if (pmcEnterRequestStandbyState(hHal) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + + /* Save the callback routine for when we need it. */ + pMac->pmc.standbyCallbackRoutine = callbackRoutine; + pMac->pmc.standbyCallbackContext = callbackContext; + + return eHAL_STATUS_PMC_PENDING; +} + +/* --------------------------------------------------------------------------- + \fn pmcRegisterDeviceStateUpdateInd + \brief Register a callback routine that is called whenever + the device enters a new device state (Full Power, BMPS, UAPSD) + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine to be registered + \param callbackContext - Cookie to be passed back during callback + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully registered + eHAL_STATUS_FAILURE - not successfully registered + ---------------------------------------------------------------------------*/ +extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState), + void *callbackContext) +{ + + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpDeviceStateUpdateIndEntry pEntry; + + pmcLog(pMac, LOG2, FL("Entering pmcRegisterDeviceStateUpdateInd")); + + /* Allocate entry for device power state update indication. */ + pEntry = vos_mem_malloc(sizeof(tDeviceStateUpdateIndEntry)); + if ( NULL == pEntry ) + { + pmcLog(pMac, LOGE, FL("Cannot allocate memory for device power state update indication")); + PMC_ABORT; + return eHAL_STATUS_FAILURE; + } + + /* Store routine in entry. */ + pEntry->callbackRoutine = callbackRoutine; + pEntry->callbackContext = callbackContext; + + /* Add entry to list. */ + csrLLInsertTail(&pMac->pmc.deviceStateUpdateIndList, &pEntry->link, FALSE); + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcDeregisterDeviceStateUpdateInd + \brief Deregister a routine that was registered for device state changes + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine to be deregistered + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered + ---------------------------------------------------------------------------*/ +eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState)) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry; + + pmcLog(pMac, LOG2, FL("Enter")); + + /* Find entry in the power save update routine list that matches + the specified routine and remove it. */ + pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE); + while (pEntry != NULL) + { + pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link); + if (pDeviceStateUpdateIndEntry->callbackRoutine == callbackRoutine) + { + if (!csrLLRemoveEntry(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE)) + { + pmcLog(pMac, LOGE, FL("Cannot remove device state update ind entry from list")); + return eHAL_STATUS_FAILURE; + } + vos_mem_free(pDeviceStateUpdateIndEntry); + return eHAL_STATUS_SUCCESS; + } + pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE); + } + + /* Could not find matching entry. */ + return eHAL_STATUS_FAILURE; +} + +/* --------------------------------------------------------------------------- + \fn pmcReady + \brief fn to inform PMC that eWNI_SME_SYS_READY_IND has been sent to PE. + This acts as a trigger to send a message to PE to update the power + save related config to FW. Note that if HDD configures any power + save related stuff before this API is invoked, PMC will buffer all + the configuration. + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus pmcReady(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pmcLog(pMac, LOG2, FL("Entering pmcReady")); + + if(pMac->pmc.pmcState == STOPPED) + { + pmcLog(pMac, LOGP, FL("pmcReady is invoked even before pmcStart")); + return eHAL_STATUS_FAILURE; + } + + pMac->pmc.pmcReady = TRUE; + if (pmcSendPowerSaveConfigMessage(hHal) != eHAL_STATUS_SUCCESS) + { + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcWowlAddBcastPattern + \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will + do a pattern match on these patterns when Wowl is enabled during BMPS + mode. Note that Firmware performs the pattern matching only on + broadcast frames and while Libra is in BMPS mode. + \param hHal - The handle returned by macOpen. + \param pattern - Pointer to the pattern to be added + \return eHalStatus + eHAL_STATUS_FAILURE Cannot add pattern + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcWowlAddBcastPattern ( + tHalHandle hHal, + tpSirWowlAddBcastPtrn pattern, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + vos_log_powersave_wow_add_ptrn_pkt_type *log_ptr = NULL; +#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT + + pmcLog(pMac, LOG2, "PMC: entering pmcWowlAddBcastPattern"); + + if(pattern == NULL) + { + pmcLog(pMac, LOGE, FL("Null broadcast pattern being passed")); + return eHAL_STATUS_FAILURE; + } + + if( pSession == NULL) + { + pmcLog(pMac, LOGE, FL("Session not found ")); + return eHAL_STATUS_FAILURE; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_powersave_wow_add_ptrn_pkt_type, LOG_WLAN_POWERSAVE_WOW_ADD_PTRN_C); + if( log_ptr ) + { + log_ptr->pattern_id = pattern->ucPatternId; + log_ptr->pattern_byte_offset = pattern->ucPatternByteOffset; + log_ptr->pattern_size = + (pattern->ucPatternSize <= VOS_LOG_MAX_WOW_PTRN_SIZE) ? + pattern->ucPatternSize : VOS_LOG_MAX_WOW_PTRN_SIZE; + log_ptr->pattern_mask_size = + (pattern->ucPatternMaskSize <= VOS_LOG_MAX_WOW_PTRN_MASK_SIZE) ? + pattern->ucPatternMaskSize : VOS_LOG_MAX_WOW_PTRN_MASK_SIZE; + + vos_mem_copy(log_ptr->pattern, pattern->ucPattern, + log_ptr->pattern_size); + /* 1 bit in the pattern mask denotes 1 byte of pattern. */ + vos_mem_copy(log_ptr->pattern_mask, pattern->ucPatternMask, + log_ptr->pattern_mask_size); + //The same macro frees the memory. + WLAN_VOS_DIAG_LOG_REPORT(log_ptr); + } + +#endif + + + /* No need to care PMC state transition when ps offload is enabled. */ + if(pMac->psOffloadEnabled) + goto skip_pmc_state_transition; + + if( pMac->pmc.pmcState == STANDBY || pMac->pmc.pmcState == REQUEST_STANDBY ) + { + pmcLog(pMac, LOGE, FL("Cannot add WoWL Pattern as chip is in %s state"), + pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS ) + { + pmcLog(pMac, LOGE, FL("Cannot add WoWL Pattern as chip is in %s state"), + pmcGetPmcStateStr(pMac->pmc.pmcState)); + 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)); + +skip_pmc_state_transition: + + if (pmcSendMessage(hHal, eWNI_PMC_WOWL_ADD_BCAST_PTRN, pattern, sizeof(tSirWowlAddBcastPtrn)) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed")); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcWowlDelBcastPattern + \brief Delete a pattern that was added for Pattern Byte Matching. + \param hHal - The handle returned by macOpen. + \param pattern - Pattern to be deleted + \return eHalStatus + eHAL_STATUS_FAILURE Cannot delete pattern + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcWowlDelBcastPattern ( + tHalHandle hHal, + tpSirWowlDelBcastPtrn pattern, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); + + vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); + wowRequest.event_subtype = WLAN_WOW_DEL_PTRN_REQ; + wowRequest.wow_del_ptrn_id = pattern->ucPatternId; + + WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW); +#endif + + pmcLog(pMac, LOG2, "PMC: entering pmcWowlDelBcastPattern"); + + if( NULL == pSession ) + { + pmcLog(pMac, LOGE, FL("Session not found ")); + return eHAL_STATUS_FAILURE; + } + + + /* No need to care PMC state transition when ps offload is enabled. */ + if(pMac->psOffloadEnabled) + goto skip_pmc_state_transition; + + if(pMac->pmc.pmcState == STANDBY || pMac->pmc.pmcState == REQUEST_STANDBY) + { + pmcLog(pMac, LOGE, FL("Cannot delete WoWL Pattern as chip is in %s state"), + pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + + if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS ) + { + eHalStatus status; + + vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + //Wake up the chip first + status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN, + pattern, sizeof(tSirWowlDelBcastPtrn) ); + + if( eHAL_STATUS_PMC_PENDING == status ) + { + return eHAL_STATUS_SUCCESS; + } + else + { + //either fail or already in full power + if( !HAL_STATUS_SUCCESS( status ) ) + { + return ( status ); + } + //else let it through because it is in full power state + } + } + +skip_pmc_state_transition: + + if (pmcSendMessage(hHal, eWNI_PMC_WOWL_DEL_BCAST_PTRN, pattern, sizeof(tSirWowlDelBcastPtrn)) + != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_DEL_BCAST_PTRN to PE failed")); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcEnterWowl + \brief Request that the device be brought to full power state. + Note 1: If "fullPowerReason" specified in this API is set to + eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" + requests and also clear any "buffered BMPS requests by HDD". + Assumption is that since HDD is requesting full power, we need to + undo any previous HDD requests for BMPS (using sme_RequestBmps) or + WoWL (using sme_EnterWoWL). If the reason is specified anything + other than above, the buffered requests for BMPS and WoWL + will not be cleared. + Note 2: Requesting full power (no matter what the fullPowerReason + is) doesn't disable the "auto bmps timer" (if it is enabled) or + clear any "buffered uapsd request". + Note 3: When the device finally enters Full Power PMC will start + a timer if any of the following holds true: + - Auto BMPS mode is enabled + - Uapsd request is pending + - HDD's request for BMPS is pending + - HDD's request for WoWL is pending + On timer expiry PMC will attempt to put the device in BMPS mode + if following (in addition to those listed above) holds true: + - Polling of all modules through the Power Save Check routine passes + - STA is associated to an access point + \param hHal - The handle returned by macOpen. + \param - enterWowlCallbackRoutine Callback routine invoked in case of + success/failure + \param - enterWowlCallbackContext - Cookie to be passed back during + callback + \param - wakeReasonIndCB Callback routine invoked for Wake Reason + Indication + \param - wakeReasonIndCBContext - Cookie to be passed back during callback + \param - fullPowerReason - Reason why this API is being invoked. SME needs + to distinguish between BAP and HDD requests + \return eHalStatus - status + eHAL_STATUS_SUCCESS - device brought to full power state + eHAL_STATUS_FAILURE - device cannot be brought to full power state + eHAL_STATUS_PMC_PENDING - device is being brought to full power state, + ---------------------------------------------------------------------------*/ +eHalStatus pmcEnterWowl ( + tHalHandle hHal, + void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status), + void *enterWowlCallbackContext, +#ifdef WLAN_WAKEUP_EVENTS + void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd), + void *wakeReasonIndCBContext, +#endif // WLAN_WAKEUP_EVENTS + tpSirSmeWowlEnterParams wowlEnterParams, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); + + vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); + wowRequest.event_subtype = WLAN_WOW_ENTER_REQ; + wowRequest.wow_type = 0; + + if(wowlEnterParams->ucMagicPktEnable) + { + wowRequest.wow_type |= 1; + vos_mem_copy(wowRequest.wow_magic_pattern, + (tANI_U8 *)wowlEnterParams->magicPtrn, 6); + } + + if(wowlEnterParams->ucPatternFilteringEnable) + { + wowRequest.wow_type |= 2; + } + WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW); +#endif + + pmcLog(pMac, LOG2, FL("PMC: entering pmcEnterWowl")); + + if( NULL == pSession ) + { + pmcLog(pMac, LOGE, FL("Session not found ")); + return eHAL_STATUS_FAILURE; + } + + /* No need worry about PMC state when power save offload is enabled. */ + if( pMac->psOffloadEnabled ) + goto skip_pmc_state_transition; + + if( !PMC_IS_READY(pMac) ) + { + pmcLog(pMac, LOGE, FL("Requesting WoWL when PMC not ready")); + pmcLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s"), + pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState)); + return eHAL_STATUS_FAILURE; + } + + /* 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 if WoWL is enabled. */ + if (!pMac->pmc.wowlEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot enter WoWL. WoWL 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; + } + + /* Is there a pending UAPSD request? HDD should have triggered QoS + module to do the necessary cleanup before triggering WOWL*/ + if(pMac->pmc.uapsdSessionRequired) + { + pmcLog(pMac, LOGE, "PMC: Cannot request WOWL. Pending UAPSD request"); + return eHAL_STATUS_FAILURE; + } + + /* Check that entry into a power save mode is allowed at this time. */ + if (pMac->pmc.pmcState == FULL_POWER && !pmcPowerSaveCheck(hHal)) + { + pmcLog(pMac, LOGE, "PMC: Power save check failed. WOWL request " + "will not be accepted"); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(wowlEnterParams->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + +skip_pmc_state_transition: + // To avoid race condition, set callback routines before sending message. + /* cache the WOWL information */ + pMac->pmc.wowlEnterParams = *wowlEnterParams; + pMac->pmc.enterWowlCallbackRoutine = enterWowlCallbackRoutine; + pMac->pmc.enterWowlCallbackContext = enterWowlCallbackContext; +#ifdef WLAN_WAKEUP_EVENTS + /* Cache the Wake Reason Indication callback information */ + pMac->pmc.wakeReasonIndCB = wakeReasonIndCB; + pMac->pmc.wakeReasonIndCBContext = wakeReasonIndCBContext; +#endif // WLAN_WAKEUP_EVENTS + + /* Enter Request WOWL State. */ + if (pmcRequestEnterWowlState(hHal, wowlEnterParams) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + + if(!pMac->psOffloadEnabled) + pMac->pmc.wowlModeRequired = TRUE; + + return eHAL_STATUS_PMC_PENDING; +} + +/* --------------------------------------------------------------------------- + \fn pmcExitWowl + \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. + SME will initiate exit from WoWLAN mode and device will be put in BMPS + mode. + \param hHal - The handle returned by macOpen. + \param wowlExitParams - Carries info on which smesession + wowl exit is requested. + \return eHalStatus + eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode. + eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. + ---------------------------------------------------------------------------*/ +eHalStatus pmcExitWowl (tHalHandle hHal, tpSirSmeWowlExitParams wowlExitParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); + + vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); + wowRequest.event_subtype = WLAN_WOW_EXIT_REQ; + + WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW); +#endif + + pmcLog(pMac, LOG2, "PMC: entering pmcExitWowl"); + + /* Clear any buffered command for entering WOWL */ + pMac->pmc.wowlModeRequired = FALSE; + + /* Enter REQUEST_EXIT_WOWL State*/ + if (pmcRequestExitWowlState(hHal, wowlExitParams) != eHAL_STATUS_SUCCESS) + return eHAL_STATUS_FAILURE; + + /* Clear the callback routines */ + pMac->pmc.enterWowlCallbackRoutine = NULL; + pMac->pmc.enterWowlCallbackContext = NULL; + + return eHAL_STATUS_SUCCESS; +} + + + +/* --------------------------------------------------------------------------- + \fn pmcSetHostOffload + \brief Set the host offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the offload request. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, + tANI_U8 sessionId) +{ + tpSirHostOffloadReq pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: IP address = %d.%d.%d.%d", __func__, + pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1], + pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]); + + if(NULL == pSession ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: SESSION not Found\n", __func__); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for host offload request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirHostOffloadReq)); + + msg.type = WDA_SET_HOST_OFFLOAD; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + 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_HOST_OFFLOAD message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcSetKeepAlive + \brief Set the Keep Alive feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the Keep Alive. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the keep alive. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 sessionId) +{ + tpSirKeepAliveReq pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_LOW, "%s: " + "WDA_SET_KEEP_ALIVE message", __func__); + + if(pSession == NULL ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + " Session not Found", __func__); + return eHAL_STATUS_FAILURE; + } + pRequestBuf = vos_mem_malloc(sizeof(tSirKeepAliveReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "Not able to allocate memory for keep alive request", + __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirKeepAliveReq)); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_LOW, "buff TP %d " + "input TP %d ", pRequestBuf->timePeriod, pRequest->timePeriod); + pRequestBuf->sessionId = sessionId; + + msg.type = WDA_SET_KEEP_ALIVE; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + 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_KEEP_ALIVE message to WDA", + __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +#ifdef WLAN_NS_OFFLOAD + +/* --------------------------------------------------------------------------- + \fn pmcSetNSOffload + \brief Set the host offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the offload request. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpSirHostOffloadReq pRequestBuf; + vos_msg_t msg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if( NULL == pSession ) + { + pmcLog(pMac, LOGE, FL("Session not found ")); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for NS offload request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirHostOffloadReq)); + + msg.type = WDA_SET_NS_OFFLOAD; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + 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 SIR_HAL_SET_HOST_OFFLOAD message to HAL", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +#endif //WLAN_NS_OFFLOAD + + +void pmcClosePowerSaveCheckList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tpPowerSaveCheckEntry pPowerSaveCheckEntry; + + csrLLLock(&pMac->pmc.powerSaveCheckList); + while ( (pEntry = csrLLRemoveHead(&pMac->pmc.powerSaveCheckList, FALSE)) ) + { + pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link); + vos_mem_free(pPowerSaveCheckEntry); + } + csrLLUnlock(&pMac->pmc.powerSaveCheckList); + csrLLClose(&pMac->pmc.powerSaveCheckList); +} + + +void pmcCloseRequestFullPowerList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tpRequestFullPowerEntry pRequestFullPowerEntry; + + csrLLLock(&pMac->pmc.requestFullPowerList); + while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, FALSE)) ) + { + pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link); + vos_mem_free(pRequestFullPowerEntry); + } + csrLLUnlock(&pMac->pmc.requestFullPowerList); + csrLLClose(&pMac->pmc.requestFullPowerList); +} + + +void pmcCloseRequestBmpsList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tpRequestBmpsEntry pRequestBmpsEntry; + + csrLLLock(&pMac->pmc.requestBmpsList); + while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE)) ) + { + pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link); + vos_mem_free(pRequestBmpsEntry); + } + csrLLUnlock(&pMac->pmc.requestBmpsList); + csrLLClose(&pMac->pmc.requestBmpsList); +} + + +void pmcCloseRequestStartUapsdList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tpStartUapsdEntry pStartUapsdEntry; + + csrLLLock(&pMac->pmc.requestStartUapsdList); + while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE)) ) + { + pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link); + vos_mem_free(pStartUapsdEntry); + } + csrLLUnlock(&pMac->pmc.requestStartUapsdList); + csrLLClose(&pMac->pmc.requestStartUapsdList); +} + + +void pmcCloseDeviceStateUpdateList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry; + + csrLLLock(&pMac->pmc.deviceStateUpdateIndList); + while ( (pEntry = csrLLRemoveHead(&pMac->pmc.deviceStateUpdateIndList, FALSE)) ) + { + pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link); + vos_mem_free(pDeviceStateUpdateIndEntry); + } + csrLLUnlock(&pMac->pmc.deviceStateUpdateIndList); + csrLLClose(&pMac->pmc.deviceStateUpdateIndList); +} + + +void pmcCloseDeferredMsgList(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tPmcDeferredMsg *pDeferredMsg; + + csrLLLock(&pMac->pmc.deferredMsgList); + while ( (pEntry = csrLLRemoveHead(&pMac->pmc.deferredMsgList, FALSE)) ) + { + pDeferredMsg = GET_BASE_ADDR(pEntry, tPmcDeferredMsg, link); + vos_mem_free(pDeferredMsg); + } + csrLLUnlock(&pMac->pmc.deferredMsgList); + csrLLClose(&pMac->pmc.deferredMsgList); +} + + +#ifdef FEATURE_WLAN_SCAN_PNO + +static tSirRetStatus +pmcPopulateMacHeader( tpAniSirGlobal pMac, + tANI_U8* pBD, + tANI_U8 type, + tANI_U8 subType, + tSirMacAddr peerAddr, + tSirMacAddr selfMacAddr) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tpSirMacMgmtHdr pMacHdr; + + /// Prepare MAC management header + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + // Prepare FC + pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + pMacHdr->fc.type = type; + pMacHdr->fc.subType = subType; + + // Prepare Address 1 + vos_mem_copy((tANI_U8 *) pMacHdr->da, (tANI_U8 *) peerAddr, sizeof( tSirMacAddr )); + + sirCopyMacAddr(pMacHdr->sa,selfMacAddr); + + // Prepare Address 3 + vos_mem_copy((tANI_U8 *) pMacHdr->bssId, (tANI_U8 *) peerAddr, sizeof( tSirMacAddr )); + return statusCode; +} /*** pmcPopulateMacHeader() ***/ + + +static tSirRetStatus +pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tANI_U32 dot11mode, + tSirMacAddr selfMacAddr, + tANI_U8 *pFrame, + tANI_U16 *pusLen, + tCsrRoamSession *psession) +{ + tDot11fProbeRequest pr; + tANI_U32 nStatus, nBytes, nPayload; + tSirRetStatus nSirStatus; + /*Bcast tx*/ + tSirMacAddr bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + // The scheme here is to fill out a 'tDot11fProbeRequest' structure + // and then hand it off to 'dot11fPackProbeRequest' (for + // serialization). We start by zero-initializing the structure: + vos_mem_set(( tANI_U8* )&pr, sizeof( pr ), 0); + + PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL); + + if ( WNI_CFG_DOT11_MODE_11B != dot11mode ) + { + PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); + } + + + if (IS_DOT11_MODE_HT(dot11mode)) + { + PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps ); + pr.HTCaps.advCodingCap = psession->htConfig.ht_rx_ldpc; + pr.HTCaps.txSTBC = psession->htConfig.ht_tx_stbc; + pr.HTCaps.rxSTBC = psession->htConfig.ht_rx_stbc; + if (!psession->htConfig.ht_sgi) { + pr.HTCaps.shortGI20MHz = pr.HTCaps.shortGI40MHz = 0; + } + } + + // That's it-- now we pack it. First, how much space are we going to + // need? + nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to calculate the packed size f" + "or a Probe Request (0x%08x).", nStatus ); + + // We'll fall back on the worst case scenario: + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while calculating" + "the packed size for a Probe Request (" + "0x%08x).", nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + /* Prepare outgoing frame*/ + vos_mem_set(pFrame, nBytes, 0); + + // Next, we fill out the buffer descriptor: + nSirStatus = pmcPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssId,selfMacAddr); + + if ( eSIR_SUCCESS != nSirStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to populate the buffer descriptor for a Probe Request (%d).", + nSirStatus ); + return nSirStatus; // allocated! + } + + // That done, pack the Probe Request: + nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame + + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to pack a Probe Request (0x%08x).", nStatus ); + return eSIR_FAILURE; // allocated! + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request" ); + } + + *pusLen = nPayload + sizeof(tSirMacMgmtHdr); + return eSIR_SUCCESS; +} // End pmcPrepareProbeReqTemplate. + + +eHalStatus pmcSetPreferredNetworkList +( + tHalHandle hHal, + tpSirPNOScanReq pRequest, + tANI_U8 sessionId, + preferredNetworkFoundIndCallback callbackRoutine, + void *callbackContext +) +{ + tpSirPNOScanReq pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + tANI_U8 ucDot11Mode; + + if (NULL == pSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: pSession is NULL", __func__); + return eHAL_STATUS_FAILURE; + } + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: SSID = 0x%08x%08x%08x%08x%08x%08x%08x%08x, " + "0x%08x%08x%08x%08x%08x%08x%08x%08x", __func__, + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[0]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[4]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[8]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[12]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[16]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[20]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[24]), + *((v_U32_t *) &pRequest->aNetworks[0].ssId.ssId[28]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[0]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[4]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[8]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[12]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[16]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[20]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[24]), + *((v_U32_t *) &pRequest->aNetworks[1].ssId.ssId[28])); + + if (!pSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: pSessionis NULL", __func__); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirPNOScanReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for PNO request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq)); + + /*Must translate the mode first*/ + ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, + csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); + + /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ + if (eSIR_SUCCESS == pmcPrepareProbeReqTemplate(pMac, SIR_PNO_24G_DEFAULT_CH, + ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p24GProbeTemplate, + &pRequestBuf->us24GProbeTemplateLen, pSession)) + { + /* Append IE passed by supplicant(if any) to probe request */ + if ((0 < pRequest->us24GProbeTemplateLen) && + ((pRequestBuf->us24GProbeTemplateLen + + pRequest->us24GProbeTemplateLen) < SIR_PNO_MAX_PB_REQ_SIZE )) + { + vos_mem_copy((tANI_U8 *)&pRequestBuf->p24GProbeTemplate + + pRequestBuf->us24GProbeTemplateLen, + (tANI_U8 *)&pRequest->p24GProbeTemplate, + pRequest->us24GProbeTemplateLen); + pRequestBuf->us24GProbeTemplateLen += + pRequest->us24GProbeTemplateLen; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: pRequest->us24GProbeTemplateLen = %d", __func__, + pRequest->us24GProbeTemplateLen); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Extra ie discarded on 2.4G, IE length = %d", __func__, + pRequest->us24GProbeTemplateLen); + } + } + + if (eSIR_SUCCESS == pmcPrepareProbeReqTemplate(pMac, SIR_PNO_5G_DEFAULT_CH, + ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p5GProbeTemplate, + &pRequestBuf->us5GProbeTemplateLen, pSession)) + { + /* Append IE passed by supplicant(if any) to probe request */ + if ((0 < pRequest->us5GProbeTemplateLen ) && + ((pRequestBuf->us5GProbeTemplateLen + + pRequest->us5GProbeTemplateLen) < SIR_PNO_MAX_PB_REQ_SIZE )) + { + vos_mem_copy((tANI_U8 *)&pRequestBuf->p5GProbeTemplate + + pRequestBuf->us5GProbeTemplateLen, + (tANI_U8 *)&pRequest->p5GProbeTemplate, + pRequest->us5GProbeTemplateLen); + pRequestBuf->us5GProbeTemplateLen += pRequest->us5GProbeTemplateLen; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: pRequestBuf->us5GProbeTemplateLen = %d", __func__, + pRequest->us5GProbeTemplateLen); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Extra IE discarded on 5G, IE length = %d", __func__, + pRequest->us5GProbeTemplateLen); + } + } + + if (pMac->pnoOffload) + { + if (pRequestBuf->enable) + { + pSession->pnoStarted = TRUE; + } + else + { + pSession->pnoStarted = FALSE; + } + + pRequestBuf->sessionId = sessionId; + } + + if (csrIsAnySessionConnected(pMac)) { + /* if AP-STA concurrency is active */ + pRequestBuf->active_max_time = + pMac->roam.configParam.nActiveMaxChnTimeConc; + pRequestBuf->active_min_time = + pMac->roam.configParam.nActiveMinChnTimeConc; + pRequestBuf->passive_max_time = + pMac->roam.configParam.nPassiveMaxChnTimeConc; + pRequestBuf->passive_min_time = + pMac->roam.configParam.nPassiveMinChnTimeConc; + } else { + pRequestBuf->active_max_time = + pMac->roam.configParam.nActiveMaxChnTime; + pRequestBuf->active_min_time = + pMac->roam.configParam.nActiveMinChnTime; + pRequestBuf->passive_max_time = + pMac->roam.configParam.nPassiveMaxChnTime; + pRequestBuf->passive_min_time = + pMac->roam.configParam.nPassiveMinChnTime; + } + + msg.type = WDA_SET_PNO_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_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_PNO_REQ message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + /* Cache the Preferred Network Found Indication callback information */ + pMac->pmc.prefNetwFoundCB = callbackRoutine; + pMac->pmc.preferredNetworkFoundIndCallbackContext = callbackContext; + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "-%s", __func__); + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChannel *pChannelList, tANI_U8 b11dResolved) +{ + tpSirUpdateScanParams pRequestBuf; + vos_msg_t msg; + int i; + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s started", __func__); + + pRequestBuf = vos_mem_malloc(sizeof(tSirUpdateScanParams)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for UpdateScanParams request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + // + // Fill pRequestBuf structure from pRequest + // + pRequestBuf->b11dEnabled = pRequest->Is11eSupportEnabled; + pRequestBuf->b11dResolved = b11dResolved; + pRequestBuf->ucChannelCount = + ( pChannelList->numChannels < SIR_PNO_MAX_NETW_CHANNELS_EX )? + pChannelList->numChannels:SIR_PNO_MAX_NETW_CHANNELS_EX; + + for (i=0; i < pRequestBuf->ucChannelCount; i++) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Channel List %d: %d", __FUNCTION__, i, pChannelList->channelList[i] ); + + pRequestBuf->aChannels[i] = pChannelList->channelList[i]; + } + pRequestBuf->usPassiveMinChTime = pRequest->nPassiveMinChnTime; + pRequestBuf->usPassiveMaxChTime = pRequest->nPassiveMaxChnTime; + pRequestBuf->usActiveMinChTime = pRequest->nActiveMinChnTime; + pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime; + pRequestBuf->ucCBState = PHY_SINGLE_CHANNEL_CENTERED; + + msg.type = WDA_UPDATE_SCAN_PARAMS_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_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_UPDATE_SCAN_PARAMS message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} +#endif // FEATURE_WLAN_SCAN_PNO + +eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams, tANI_BOOLEAN forced) +{ + tSirSetPowerParamsReq* pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPESession psessionEntry; + + psessionEntry = peGetValidPowerSaveSession(pMac); + if (!forced && (psessionEntry == NULL)) + { + return eHAL_STATUS_NOT_INITIALIZED; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirSetPowerParamsReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for Power Paramrequest", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + + vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf)); + + + msg.type = WDA_SET_POWER_PARAMS_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + + 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_POWER_PARAMS_REQ message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +eHalStatus pmcGetFilterMatchCount +( + tHalHandle hHal, + FilterMatchCountCallback callbackRoutine, + void *callbackContext, + tANI_U8 sessionId +) +{ + tpSirRcvFltPktMatchRsp pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s", __func__); + + if(NULL == pSession ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Session not found ", __func__); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltPktMatchRsp)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate " + "memory for Get PC Filter Match Count request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + msg.type = WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + + /* Cache the Packet Coalescing Filter Match Count callback information */ + if (NULL != pMac->pmc.FilterMatchCountCB) + { + // Do we need to check if the callback is in use? + // Because we are not sending the same message again when it is pending, + // the only case when the callback is not NULL is that the previous message + //was timed out or failed. + // So, it will be safe to set the callback in this case. + } + + pMac->pmc.FilterMatchCountCB = callbackRoutine; + pMac->pmc.FilterMatchCountCBContext = callbackContext; + + 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_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ " + "message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} +#endif // WLAN_FEATURE_PACKET_FILTERING + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/* --------------------------------------------------------------------------- + \fn pmcSetGTKOffload + \brief Set GTK offload feature. + \param hHal - The handle returned by macOpen. + \param pGtkOffload - Pointer to the GTK offload request. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, + tANI_U8 sessionId) +{ + tpSirGtkOffloadParams pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %lld", + __func__, pGtkOffload->ullKeyReplayCounter); + + if(NULL == pSession ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Session not found ", __func__); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = (tpSirGtkOffloadParams)vos_mem_malloc(sizeof(tSirGtkOffloadParams)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate " + "memory for GTK offload request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + vos_mem_copy(pRequestBuf, pGtkOffload, sizeof(tSirGtkOffloadParams)); + + msg.type = WDA_GTK_OFFLOAD_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_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 " + "SIR_HAL_SET_GTK_OFFLOAD message to HAL", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn pmcGetGTKOffload + \brief Get GTK offload information. + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine. + \return eHalStatus + eHAL_STATUS_FAILURE Cannot set the offload. + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, + void *callbackContext, tANI_U8 sessionId) +{ + tpSirGtkOffloadGetInfoRspParams pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: Entered", + __func__); + + if(NULL == pSession ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Session not found ", __func__); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = (tpSirGtkOffloadGetInfoRspParams) + vos_mem_malloc(sizeof (tSirGtkOffloadGetInfoRspParams)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate " + "memory for Get GTK offload request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + + msg.type = WDA_GTK_OFFLOAD_GETINFO_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + + /* Cache the Get GTK Offload callback information */ + if (NULL != pMac->pmc.GtkOffloadGetInfoCB) + { + // Do we need to check if the callback is in use? + // Because we are not sending the same message again when it is pending, + // the only case when the callback is not NULL is that the previous message was timed out or failed. + // So, it will be safe to set the callback in this case. + } + + pMac->pmc.GtkOffloadGetInfoCB = callbackRoutine; + pMac->pmc.GtkOffloadGetInfoCBContext = callbackContext; + + if (!VOS_IS_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_GTK_OFFLOAD_GETINFO_REQ message to WDA", + __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} +#endif // WLAN_FEATURE_GTK_OFFLOAD + +v_BOOL_t IsPmcImpsReqFailed (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_BOOL_t impsReqFailStatus; + + impsReqFailStatus = (pMac->pmc.ImpsReqFailed || pMac->pmc.ImpsReqTimerFailed); + + return impsReqFailStatus; + +} + +void pmcResetImpsFailStatus (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->pmc.ImpsReqFailed = VOS_FALSE; + pMac->pmc.ImpsReqTimerFailed = VOS_FALSE; +} + +eHalStatus pmcOffloadCleanup(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Enter")); + + pmc->uapsdSessionRequired = FALSE; + pmc->configStaPsEnabled = FALSE; + pmc->configDefStaPsEnabled = FALSE; + pmcOffloadStopAutoStaPsTimer(pMac, sessionId); + pmcOffloadDoStartUapsdCallbacks(pMac, sessionId, eHAL_STATUS_FAILURE); + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadOpen(tHalHandle hHal) +{ + tANI_U32 i; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG2, FL("Enter")); + + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + if(eHAL_STATUS_SUCCESS != pmcOffloadOpenPerSession(hHal, i)) + { + smsLog(pMac, LOGE, FL("PMC Init Failed for session %d"), i); + return eHAL_STATUS_FAILURE; + } + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadClose(tHalHandle hHal) +{ + tANI_U32 i; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG2, FL("Entering pmcOffloadClose")); + + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + pmcOffloadClosePerSession(hHal, i); + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadStart(tHalHandle hHal) +{ + tANI_U32 i; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG2, FL("Entering pmcOffloadStart")); + + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + if(eHAL_STATUS_SUCCESS != pmcOffloadStartPerSession(hHal, i)) + { + smsLog(pMac, LOGE, FL("PMC Init Failed for session %d"), i); + return eHAL_STATUS_FAILURE; + } + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadStop(tHalHandle hHal) +{ + tANI_U32 i; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG2, FL("Entering pmcOffloadStop")); + + for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) + { + pmcOffloadStopPerSession(hHal, i); + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadConfigEnablePowerSave(tHalHandle hHal, + tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG1, FL("Config Set Power Save Mode %d"), psMode); + + switch(psMode) + { + case ePMC_BEACON_MODE_POWER_SAVE: + pMac->pmcOffloadInfo.staPsEnabled = TRUE; + break; + case ePMC_UAPSD_MODE_POWER_SAVE: + break; + default: + smsLog(pMac, LOGE, + FL("Config Set Power Save Mode -> Not Supported %d"), psMode); + break; + } + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadConfigDisablePowerSave(tHalHandle hHal, + tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG1, FL("Config Set Power Save Mode %d"), psMode); + + switch(psMode) + { + case ePMC_BEACON_MODE_POWER_SAVE: + pMac->pmcOffloadInfo.staPsEnabled = FALSE; + break; + case ePMC_UAPSD_MODE_POWER_SAVE: + break; + default: + smsLog(pMac, LOGE, + FL("Config Set Power Save Mode -> Not Supported %d"), psMode); + break; + } + return eHAL_STATUS_SUCCESS; +} + +tPmcState pmcOffloadGetPmcState(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->pmcOffloadInfo.pmc[sessionId].pmcState; +} + +eHalStatus pmcOffloadRegisterPowerSaveCheck(tHalHandle hHal, tANI_U32 sessionId, + PwrSaveCheckRoutine checkRoutine, + void *checkContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPmcOffloadPsCheckEntry pEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Enter pmcOffloadRegPowerSaveCheck")); + + /* Allocate entry for power save check routine list. */ + pEntry = vos_mem_malloc(sizeof(tPmcOffloadPsCheckEntry)); + if (!pEntry) + { + smsLog(pMac, LOGE, + FL("Cannot allocate memory for power save check routine list")); + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->pwrsaveCheckCb = checkRoutine; + pEntry->checkContext = checkContext; + pEntry->sessionId = sessionId; + + /* Add entry to list. */ + csrLLInsertTail(&pmc->pwrsaveCheckList, &pEntry->link, FALSE); + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadDeregisterPowerSaveCheck(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveCheckRoutine checkRoutine) + +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpPmcOffloadPsCheckEntry pPowerSaveCheckEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Enter pmcOffloadDeregisterPowerSaveCheck")); + + /* + * Find entry in the power save check routine list that matches + * the specified routine and remove it. + */ + pEntry = csrLLPeekHead(&pmc->pwrsaveCheckList, FALSE); + while(pEntry != NULL) + { + pPowerSaveCheckEntry = + GET_BASE_ADDR(pEntry, tPmcOffloadPsCheckEntry, link); + if(pPowerSaveCheckEntry->pwrsaveCheckCb == checkRoutine) + { + if(csrLLRemoveEntry(&pmc->pwrsaveCheckList, pEntry, FALSE)) + { + vos_mem_free(pPowerSaveCheckEntry); + } + else + { + smsLog(pMac, LOGE, + FL("Cannot remove power save check routine list entry")); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + } + pEntry = csrLLNext(&pmc->pwrsaveCheckList, pEntry, FALSE); + } + + /* Could not find matching entry. */ + return eHAL_STATUS_FAILURE; +} + +eHalStatus pmcOffloadRegisterDeviceStateUpdateInd(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveStateChangeIndCb stateChangeCb, + void *callbackContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPmcOffloadDevStateUpdIndEntry pEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Enter pmcOffloadRegisterDeviceStateUpdateInd")); + + /* Allocate entry for device power state update indication. */ + pEntry = vos_mem_malloc(sizeof(tPmcOffloadDevStateUpdIndEntry)); + if (!pEntry) + { + smsLog(pMac, LOGE, + FL("Cannot allocate memory for device power state update ind")); + return eHAL_STATUS_FAILURE; + } + + /* Store routine in entry. */ + pEntry->stateChangeCb = stateChangeCb; + pEntry->callbackContext = callbackContext; + pEntry->sessionId = sessionId; + + /* Add entry to list. */ + csrLLInsertTail(&pmc->deviceStateUpdateIndList, &pEntry->link, FALSE); + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus pmcOffloadDeregisterDeviceStateUpdateInd(tHalHandle hHal, + tANI_U32 sessionId, PwrSaveStateChangeIndCb stateChangeCb) + +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tListElem *pEntry; + tpPmcOffloadDevStateUpdIndEntry pDeviceStateUpdateIndEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOG2, FL("Enter pmcOffloadDeregisterDeviceStateUpdateInd")); + + /* + * Find entry in the power save update routine list that matches + * the specified routine and remove it. + */ + pEntry = csrLLPeekHead(&pmc->deviceStateUpdateIndList, FALSE); + while(pEntry != NULL) + { + pDeviceStateUpdateIndEntry = + GET_BASE_ADDR(pEntry, tPmcOffloadDevStateUpdIndEntry, link); + if(pDeviceStateUpdateIndEntry->stateChangeCb == stateChangeCb) + { + if(!csrLLRemoveEntry(&pmc->deviceStateUpdateIndList, + pEntry, FALSE)) + { + smsLog(pMac, LOGE, + FL("Cannot remove device state update ind entry list")); + return eHAL_STATUS_FAILURE; + } + vos_mem_free(pDeviceStateUpdateIndEntry); + return eHAL_STATUS_SUCCESS; + } + pEntry = csrLLNext(&pmc->deviceStateUpdateIndList, pEntry, FALSE); + } + + /* Could not find matching entry. */ + return eHAL_STATUS_FAILURE; +} + +eHalStatus PmcOffloadEnableStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + if(!pMac->pmcOffloadInfo.staPsEnabled) + { + smsLog(pMac, LOGE, + FL("STA Mode PowerSave is not enabled in ini")); + return eHAL_STATUS_FAILURE; + } + + if(!pmc->configStaPsEnabled) + { + eHalStatus status; + status = pmcOffloadEnableStaPsHandler(pMac, sessionId); + + if((eHAL_STATUS_SUCCESS == status) || + (eHAL_STATUS_PMC_NOT_NOW == status)) + { + /* Successfully Queued Enabling Sta Mode Ps Request */ + smsLog(pMac, LOG2, + FL("Successful Queued Enabling Sta Mode Ps Request")); + + pmc->configStaPsEnabled = TRUE; + return eHAL_STATUS_SUCCESS; + } + else + { + /* Failed to Queue Sta Mode Ps Request */ + smsLog(pMac, LOGW, + FL("Failed to Queue Sta Mode Ps Request")); + return eHAL_STATUS_FAILURE; + } + } + else + { + /* + * configStaPsEnabled is the master flag + * to enable sta mode power save + * If it is already set Auto Power save Timer + * will take care of enabling Power Save + */ + smsLog(pMac, LOGW, + FL("sta mode power save already enabled")); + return eHAL_STATUS_SUCCESS; + } +} + +eHalStatus PmcOffloadDisableStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + + if (pmc->configStaPsEnabled) { + status = pmcOffloadDisableStaPsHandler(pMac, sessionId); + } else { + /* + * configStaPsEnabled is the master flag + * to enable sta mode power save + * If it is already cleared then no need to + * do anything + */ + smsLog(pMac, LOGW, + FL("sta mode power save already disabled")); + /* Stop the Auto Sta Ps Timer if running */ + pmcOffloadStopAutoStaPsTimer(pMac, sessionId); + pmc->configDefStaPsEnabled = FALSE; + } + return status; +} + +eHalStatus pmcOffloadRequestFullPower (tHalHandle hHal, tANI_U32 sessionId, + FullPowerReqCb fullpwrReqCb,void *callbackContext, + tRequestFullPowerReason fullPowerReason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + if(FULL_POWER == pmc->pmcState) + { + smsLog(pMac, LOG2, + FL("Already in Full Power")); + return eHAL_STATUS_SUCCESS; + } + + if(pmc->fullPowerReqPend) + { + smsLog(pMac, LOG2, + FL("Full Power Req Pending")); + goto full_pwr_req_pending; + } + + if(eHAL_STATUS_FAILURE == + pmcOffloadQueueRequestFullPower(pMac, sessionId, fullPowerReason)) + { + /* + * Fail to issue eSmeCommandExitBmps + */ + smsLog(pMac, LOGE, FL("Fail to issue eSmeCommandExitBmps")); + return eHAL_STATUS_FAILURE; + } +full_pwr_req_pending: + if(fullpwrReqCb) + { + tpPmcOffloadReqFullPowerEntry pEntry; + + /* Allocate entry for Full Power Cb list. */ + pEntry = vos_mem_malloc(sizeof(tPmcOffloadReqFullPowerEntry)); + if (!pEntry) + { + smsLog(pMac, LOGE, + FL("Cannot allocate memory for Full Power routine list")); + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->fullPwrCb = fullpwrReqCb; + pEntry->callbackContext = callbackContext; + pEntry->sessionId = sessionId; + + /* Add entry to list. */ + csrLLInsertTail(&pmc->fullPowerCbList, &pEntry->link, FALSE); + } + return eHAL_STATUS_PMC_PENDING; +} + +eHalStatus pmcOffloadStartUapsd(tHalHandle hHal, tANI_U32 sessionId, + UapsdStartIndCb uapsdStartIndCb, void *callbackContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(pMac, LOG2, "PMC: Start UAPSD Req"); + + /* Check if Sta Ps is enabled. */ + if(!pMac->pmcOffloadInfo.staPsEnabled) + { + smsLog(pMac, LOG2, "PMC: Cannot start uapsd. BMPS is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + /* Check whether the give session is Infra and in Connected State */ + if(!csrIsConnStateConnectedInfra(pMac, sessionId)) + { + smsLog(pMac, LOG2, "PMC:Sta not infra/connected state %d", sessionId); + return eHAL_STATUS_FAILURE; + } + + status = pmcOffloadQueueStartUapsdRequest(pMac, sessionId); + + if(eHAL_STATUS_PMC_PENDING != status) + { + smsLog(pMac, LOG2, "PMC: Start UAPSD Req:Not Pending"); + return status; + } + + /* + * Store the cbs so that corresponding registered + * module will be notified upon starting of + * uapsd + */ + if(uapsdStartIndCb) + { + tpPmcOffloadStartUapsdEntry pEntry; + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + /* Allocate entry for Start Uapsd Cb list. */ + pEntry = vos_mem_malloc(sizeof(tPmcOffloadStartUapsdEntry)); + if (!pEntry) + { + smsLog(pMac, LOGE, + FL("Cannot allocate memory for start uapsd list")); + return eHAL_STATUS_FAILURE; + } + + /* Store routine and context in entry. */ + pEntry->uapsdStartInd = uapsdStartIndCb; + pEntry->callbackContext = callbackContext; + pEntry->sessionId = sessionId; + + /* Add entry to list. */ + csrLLInsertTail(&pmc->uapsdCbList, &pEntry->link, FALSE); + } + return status; +} + +eHalStatus pmcOffloadStopUapsd(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(pMac, LOG2, "PMC: Stop UAPSD Req"); + + /* Check if Sta Ps is enabled. */ + if(!pMac->pmcOffloadInfo.staPsEnabled) + { + smsLog(pMac, LOGW, "PMC: Cannot stop uapsd. BMPS is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + + /* Check whether the give session is Infra and in Connected State */ + if(!csrIsConnStateConnectedInfra(pMac, sessionId)) + { + smsLog(pMac, LOGW, "PMC:Sta not infra/connected state %d", sessionId); + return eHAL_STATUS_FAILURE; + } + + status = pmcOffloadQueueStopUapsdRequest(pMac, sessionId); + if(eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGW, "PMC:Failed to queue Stop Uapsd Req SessionId %d", + sessionId); + } + return status; +} + +tANI_BOOLEAN pmcOffloadIsStaInPowerSave(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tpPsOffloadPerSessionInfo pmc; + tANI_BOOLEAN StainPS = TRUE; + + if(!CSR_IS_SESSION_VALID(pMac, sessionId)) + { + smsLog(pMac, LOGE, FL("Invalid SessionId %x"), sessionId); + return TRUE; + } + + /* Check whether the give session is Infra and in Connected State */ + if(!csrIsConnStateConnectedInfra(pMac, sessionId)) + { + smsLog(pMac, LOG1, FL("Sta not infra/connected state %d"), sessionId); + return TRUE; + } + else + { + pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + StainPS = (pmc->pmcState == BMPS) || (pmc->pmcState == UAPSD); + return StainPS; + } +} + +tANI_BOOLEAN pmcOffloadProcessCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE; + tANI_U32 sessionId = pCommand->sessionId; + tpPsOffloadPerSessionInfo pmc; + + /* Check whether Session is valid or not */ + if(!CSR_IS_SESSION_VALID(pMac, sessionId)) + { + smsLog(pMac, LOGE, "PMC Offload Proc Cmd Fail:Invalid SessionId %x", + pCommand->sessionId); + return fRemoveCmd; + } + + /* Get the Session specific PMC info */ + pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + do + { + switch(pCommand->command) + { + case eSmeCommandEnterBmps: + if(FULL_POWER == pmc->pmcState) + { + status = pmcOffloadEnableStaPsCheck(pMac, sessionId); + if(HAL_STATUS_SUCCESS(status)) + { + tSirPsReqData psData; + tCsrRoamSession *pSession = + CSR_GET_SESSION(pMac, sessionId); + + /* PE uses this BSSID to retrieve corresponding PE Session */ + vos_mem_copy(psData.bssId, + pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + + /* + * If uapsd is pending + * sent the req as combined request for both + * enabling ps and uapsd + */ + if(pmc->uapsdSessionRequired) + { + psData.addOnReq = eSIR_ADDON_ENABLE_UAPSD; + pmc->uapsdStatus = PMC_UAPSD_ENABLE_PENDING; + } + else + { + psData.addOnReq = eSIR_ADDON_NOTHING; + pmc->uapsdStatus = PMC_UAPSD_DISABLED; + } + + smsLog(pMac, LOG2, "PMC: Enter BMPS req done"); + + /* Tell MAC to have device enter BMPS mode. */ + status = + pmcSendMessage(pMac,eWNI_PMC_ENTER_BMPS_REQ, + &psData, sizeof(tSirPsReqData)); + if(HAL_STATUS_SUCCESS(status)) + { + /* Change PMC state */ + pmc->pmcState = REQUEST_BMPS; + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + } + if(!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, + "PMC: failure to send message" + "eWNI_PMC_ENTER_BMPS_REQ status %d", status); + + pmcOffloadExitPowersaveState(pMac, sessionId); + } + } + else + { + smsLog(pMac, LOGE, + "Fail to send enterBMPS msg to PE state %d", pmc->pmcState); + } + break; + + case eSmeCommandExitBmps: + if((BMPS == pmc->pmcState) || + (UAPSD == pmc->pmcState)) + { + tSirPsReqData psData; + tCsrRoamSession *pSession = + CSR_GET_SESSION(pMac, sessionId); + + /* PE uses this BSSID to retrieve corresponding PE Session */ + vos_mem_copy(psData.bssId, + pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + + if(UAPSD == pmc->pmcState) + { + psData.addOnReq = eSIR_ADDON_DISABLE_UAPSD; + pmc->uapsdStatus = PMC_UAPSD_DISABLE_PENDING; + } + else + { + psData.addOnReq = eSIR_ADDON_NOTHING; + } + + /* Tell MAC to have device exit BMPS mode. */ + status = pmcSendMessage(pMac, eWNI_PMC_EXIT_BMPS_REQ, &psData, + sizeof(tSirPsReqData)); + if(HAL_STATUS_SUCCESS(status)) + { + /* Change PMC state */ + pmc->pmcState = REQUEST_FULL_POWER; + fRemoveCmd = eANI_BOOLEAN_FALSE; + smsLog(pMac, LOG2, + FL("eWNI_PMC_OFFLOAD_PS_REQ (disable) sent to PE")); + } + else + { + /* Call Full Req Cb with Failure */ + pmcOffloadDoFullPowerCallbacks(pMac, sessionId, + eHAL_STATUS_FAILURE); + smsLog(pMac, LOGE, "Fail to send exit BMPS msg to PE"); + } + } + else + { + smsLog(pMac, LOGE, + "Fail to send exitBMPS msg to PE state %d", pmc->pmcState); + } + break; + + case eSmeCommandEnterUapsd: + if(BMPS == pmc->pmcState) + { + tSirPsReqData psData; + tCsrRoamSession *pSession = + CSR_GET_SESSION(pMac, sessionId); + /* PE uses this BSSID to retrieve corresponding PE Session */ + vos_mem_copy(psData.bssId, + pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + pmc->uapsdSessionRequired = TRUE; + + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_UAPSD_REQ, &psData, + sizeof(tSirPsReqData)); + + if(HAL_STATUS_SUCCESS(status)) + { + pmc->pmcState = REQUEST_START_UAPSD; + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + smsLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_ENTER_UAPSD_REQ"); + /* there is no retry for re-entering UAPSD so tell the requester */ + pMac->pmc.uapsdSessionRequired = FALSE; + /* call uapsd cbs with failure */ + pmcOffloadDoStartUapsdCallbacks(pMac, pCommand->sessionId, + eHAL_STATUS_FAILURE); + } + } + else + { + smsLog(pMac, LOGE, + "Fail to send EnterUapsd to PE state %d", pmc->pmcState); + } + break; + + case eSmeCommandExitUapsd: + if(UAPSD == pmc->pmcState) + { + tSirPsReqData psData; + tCsrRoamSession *pSession = + CSR_GET_SESSION(pMac, sessionId); + /* PE uses this BSSID to retrieve corresponding PE Session */ + vos_mem_copy(psData.bssId, + pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + + status = pmcSendMessage(pMac, eWNI_PMC_EXIT_UAPSD_REQ, &psData, + sizeof(tSirPsReqData)); + + if(HAL_STATUS_SUCCESS(status)) + { + pmc->pmcState = REQUEST_STOP_UAPSD; + fRemoveCmd = eANI_BOOLEAN_FALSE; + } + else + { + smsLog(pMac, LOGE, "PMC: failure to send message " + "eWNI_PMC_EXIT_UAPSD_REQ"); + pmcOffloadEnterPowersaveState(pMac, sessionId); + } + } + else + { + smsLog(pMac, LOGE, + "Fail to send ExitUapsd to PE state %d", pmc->pmcState); + } + break; + + case eSmeCommandEnterWowl: + status = pmcSendMessage(pMac, eWNI_PMC_ENTER_WOWL_REQ, + &pCommand->u.pmcCmd.u.enterWowlInfo, + sizeof(tSirSmeWowlEnterParams)); + if ( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ"); + } + break; + + case eSmeCommandExitWowl: + status = pmcSendMessage(pMac, eWNI_PMC_EXIT_WOWL_REQ, + &pCommand->u.pmcCmd.u.exitWowlInfo, + sizeof(tSirSmeWowlExitParams)); + if ( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ"); + } + break; + + case eSmeCommandEnterStandby: + smsLog(pMac, LOGE, "PMC: eSmeCommandEnterStandby " + "is not supported"); + break; + + default: + smsLog( pMac, LOGE, FL(" invalid command type %d"), pCommand->command ); + break; + } + } while(0); + + return fRemoveCmd; +} + +void pmcOffloadMessageProcessor(tHalHandle hHal, tSirSmeRsp *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOG2, + FL("Entering pmcMessageProcessor, message type %d"), pMsg->messageType); + + switch(pMsg->messageType) + { + case eWNI_PMC_EXIT_BMPS_IND: + /* Device left BMPS on its own. */ + smsLog(pMac, LOGW, + FL("Rcvd eWNI_PMC_EXIT_BMPS_IND with status = %d"), pMsg->statusCode); + + pmcOffloadExitBmpsIndHandler(pMac, pMsg); + break; + + default: + pmcOffloadProcessResponse(pMac,pMsg ); + break; + } +} + +#ifdef FEATURE_WLAN_TDLS +eHalStatus pmcOffloadSetTdlsProhibitBmpsStatus(tHalHandle hHal, + tANI_U32 sessionId, + v_BOOL_t val) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc; + + /* Get the Session specific PMC info */ + pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + smsLog(pMac, LOGW, + FL("Set TdlsProhibitBmpsStatus %d for session %d"), val, sessionId); + + pmc->isTdlsPowerSaveProhibited = val; + return eHAL_STATUS_SUCCESS; +} +#endif + +/****************************************************************************** +* +* Name: pmcOffloadIsPowerSaveEnabled +* +* Description: +* Checks if the device is able to enter one of the power save modes. +* "Able to enter" means the power save mode is enabled for the device +* and the host is using the correct power source for entry into the +* power save mode. This routine does not indicate whether the device +* is actually in the power save mode at a particular point in time. +* +* Parameters: +* hHal - HAL handle for device +* psMode - the power saving mode +* +* Returns: +* TRUE if device is able to enter the power save mode, FALSE otherwise +* +******************************************************************************/ +tANI_BOOLEAN pmcOffloadIsPowerSaveEnabled (tHalHandle hHal, tANI_U32 sessionId, + tPmcPowerSavingMode psMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + pmcLog(pMac, LOG2, FL("Entering pmcIsPowerSaveEnabled, power save mode %d"), + psMode); + + /* Check ability to enter based on the specified power saving mode. */ + switch (psMode) + { + case ePMC_BEACON_MODE_POWER_SAVE: + return pMac->pmcOffloadInfo.staPsEnabled; + + case ePMC_UAPSD_MODE_POWER_SAVE: + return pmc->UapsdEnabled; + + default: + pmcLog(pMac, LOGE, FL("Invalid power save mode %d"), psMode); + PMC_ABORT; + return FALSE; + } +} + +eHalStatus PmcOffloadEnableDeferredStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId, + tANI_BOOLEAN isReassoc) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_U32 timer_value; + + if (!pMac->pmcOffloadInfo.staPsEnabled) + { + smsLog(pMac, LOGE, + FL("STA Mode PowerSave is not enabled in ini")); + return status; + } + + if(isReassoc) + timer_value = AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE; + else + timer_value = AUTO_DEFERRED_PS_ENTRY_TIMER_DEFAULT_VALUE; + + pmcLog(pMac, LOG1, FL("Start AutoPsTimer for %d isReassoc:%d "), + timer_value, isReassoc); + + status = pmcOffloadStartAutoStaPsTimer(pMac, sessionId, + timer_value); + if (eHAL_STATUS_SUCCESS == status) + { + smsLog(pMac, LOG2, + FL("Enabled Deferred ps for session %d"), sessionId); + pmc->configDefStaPsEnabled = TRUE; + } + return status; +} + +eHalStatus PmcOffloadDisableDeferredStaModePowerSave(tHalHandle hHal, + tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpPsOffloadPerSessionInfo pmc = &pMac->pmcOffloadInfo.pmc[sessionId]; + + /* Stop the Auto Sta Ps Timer if running */ + pmcOffloadStopAutoStaPsTimer(pMac, sessionId); + pmc->configDefStaPsEnabled = FALSE; + return eHAL_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcLogDump.c b/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcLogDump.c new file mode 100644 index 000000000000..264a4bfcfb69 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/pmc/pmcLogDump.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* +* Name: pmcLogDump.c +* +* Description: Implements the dump commands specific to PMC module +* + +* +******************************************************************************/ + +#include "palTypes.h" +#include "aniGlobal.h" +#include "pmcApi.h" +#include "pmc.h" +#include "logDump.h" +#include "smsDebug.h" +#include "sme_Api.h" +#include "cfgApi.h" + +#if defined(ANI_LOGDUMP) + +void dump_pmc_callbackRoutine (void *callbackContext, eHalStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext; + pmcLog(pMac, LOGW, "*********Received callback from PMC with status = %d\n*********",status); +} + +#ifdef WLAN_WAKEUP_EVENTS +void dump_pmc_callbackRoutine2 (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext; + pmcLog(pMac, LOGW, "*********Received callback from PMC with reason = %d\n*********",pWakeReasonInd->ulReason); +} +#endif // WLAN_WAKEUP_EVENTS + +void dump_pmc_deviceUpdateRoutine (void *callbackContext, tPmcState pmcState) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext; + pmcLog(pMac, LOGW, "*********Received msg from PMC: Device is in %s state\n*********", pmcGetPmcStateStr(pmcState)); +} + +static char * +dump_pmc_state( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + char *ptr = p; + + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + + p += log_sprintf( pMac,p, "******** PMC State & Configuration ******** \n"); + p += log_sprintf( pMac,p, " PMC: IMPS Enabled? %d\n", pMac->pmc.impsEnabled); + p += log_sprintf( pMac,p, " PMC: Auto BMPS Timer Enabled? %d\n", pMac->pmc.autoBmpsEntryEnabled); + p += log_sprintf( pMac,p, " PMC: BMPS Enabled? %d\n", pMac->pmc.bmpsEnabled); + p += log_sprintf( pMac,p, " PMC: UAPSD Enabled? %d\n", pMac->pmc.uapsdEnabled); + p += log_sprintf( pMac,p, " PMC: WoWL Enabled? %d\n", pMac->pmc.wowlEnabled); + p += log_sprintf( pMac,p, " PMC: Standby Enabled? %d\n", pMac->pmc.standbyEnabled); + p += log_sprintf( pMac,p, " PMC: Auto BMPS timer period (ms): %d\n", pMac->pmc.bmpsConfig.trafficMeasurePeriod); + p += log_sprintf( pMac,p, " PMC: BMPS Listen Interval (Beacon intervals): %d\n", pMac->pmc.bmpsConfig.bmpsPeriod); + p += log_sprintf( pMac,p, " PMC: Device State = %s\n", pmcGetPmcStateStr(pMac->pmc.pmcState)); + 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); + + pmcLog(pMac, LOGW, "\n%s", ptr); + + return p; +} + +static char * +dump_pmc_enable_imps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcEnablePowerSave(pMac, ePMC_IDLE_MODE_POWER_SAVE); + return p; +} + +static char * +dump_pmc_disable_imps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcDisablePowerSave(pMac, ePMC_IDLE_MODE_POWER_SAVE); + return p; +} + +static char * +dump_pmc_request_imps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + pMac->pmc.impsEnabled = TRUE; + (void)pmcRequestImps(pMac, arg1, dump_pmc_callbackRoutine, pMac); + return p; +} + +static char * +dump_pmc_start_auto_bmps_timer( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + pMac->pmc.bmpsEnabled = TRUE; + (void)pmcStartAutoBmpsTimer(pMac); + return p; +} + +static char * +dump_pmc_stop_auto_bmps_timer( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcStopAutoBmpsTimer(pMac); + return p; +} + +static char * +dump_pmc_enable_bmps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcEnablePowerSave(pMac, ePMC_BEACON_MODE_POWER_SAVE); + return p; +} + +static char * +dump_pmc_disable_bmps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcDisablePowerSave(pMac, ePMC_BEACON_MODE_POWER_SAVE); + return p; +} + +static char * +dump_pmc_request_bmps( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + pMac->pmc.bmpsEnabled = TRUE; + (void)sme_RequestBmps(pMac, dump_pmc_callbackRoutine, pMac); + return p; +} + +static char * +dump_pmc_enable_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcEnablePowerSave(pMac, ePMC_UAPSD_MODE_POWER_SAVE); + return p; +} + +static char * +dump_pmc_disable_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcDisablePowerSave(pMac, ePMC_UAPSD_MODE_POWER_SAVE); + return p; +} + +static char * +dump_pmc_start_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + pMac->pmc.bmpsEnabled = TRUE; + pMac->pmc.uapsdEnabled = TRUE; + (void)pmcStartUapsd(pMac, dump_pmc_callbackRoutine, pMac); + return p; +} + +static char * +dump_pmc_stop_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)pmcStopUapsd(pMac); + return p; +} + +static char * +dump_pmc_request_standby( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + pMac->pmc.standbyEnabled = TRUE; + (void)pmcRequestStandby(pMac, dump_pmc_callbackRoutine, pMac); + return p; +} + +static char * +dump_pmc_request_full_power( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)sme_RequestFullPower(pMac, dump_pmc_callbackRoutine, pMac, eSME_FULL_PWR_NEEDED_BY_HDD); + return p; +} + +static char * +dump_pmc_enter_wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirSmeWowlEnterParams wowlEnterParams; + tSirRetStatus status; + tANI_U32 length; + tANI_U8 sessionId = 0; + + (void) arg4; + + vos_mem_set(&wowlEnterParams, sizeof(tSirSmeWowlEnterParams), 0); + + if (arg1 == 0 && arg2 == 0) + { + pmcLog(pMac, LOGE, + "Requesting WoWL but neither magic pkt and ptrn byte matching is being enabled\n"); + return p; + } + if(arg1 == 1) + { + wowlEnterParams.ucMagicPktEnable = 1; + /* magic packet */ + length = SIR_MAC_ADDR_LENGTH; + status = wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, (tANI_U8 *)wowlEnterParams.magicPtrn, &length); + if (eSIR_SUCCESS != status) + { + pmcLog(pMac, LOGE, + "Reading of WNI_CFG_STA_ID from CFG failed. Using hardcoded STA MAC Addr\n"); + wowlEnterParams.magicPtrn[0] = 0x00; + wowlEnterParams.magicPtrn[1] = 0x0a; + wowlEnterParams.magicPtrn[2] = 0xf5; + wowlEnterParams.magicPtrn[3] = 0x04; + wowlEnterParams.magicPtrn[4] = 0x05; + wowlEnterParams.magicPtrn[5] = 0x06; + } + } + if(arg2 == 1) + { + wowlEnterParams.ucPatternFilteringEnable = 1; + } + + if(arg3 == CSR_ROAM_SESSION_MAX ) + { + pmcLog(pMac, LOGE, "Enter valid sessionId\n"); + return p; + } + pMac->pmc.bmpsEnabled = TRUE; + pMac->pmc.wowlEnabled = TRUE; + + sessionId = (tANI_U8 ) arg3; +#ifdef WLAN_WAKEUP_EVENTS + (void)sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, dump_pmc_callbackRoutine2, pMac, + &wowlEnterParams, sessionId); +#else // WLAN_WAKEUP_EVENTS + (void)sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, &wowlEnterParams, sessionId); +#endif // WLAN_WAKEUP_EVENTS + return p; +} + +static char * +dump_pmc_exit_wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirSmeWowlExitParams wowlExitParams; + + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + (void)sme_ExitWowl(pMac, &wowlExitParams); + return p; +} + +static char * +dump_pmc_remove_ptrn( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirWowlDelBcastPtrn delPattern; + tANI_U8 sessionId = 0; + (void) arg3; (void) arg4; + + vos_mem_set(&delPattern, sizeof(tSirWowlDelBcastPtrn), 0); + + if((arg1 <= 7) || (arg2 == CSR_ROAM_SESSION_MAX)) + { + delPattern.ucPatternId = (tANI_U8)arg1; + } + else + { + pmcLog(pMac, LOGE, "dump_pmc_remove_ptrn: Invalid pattern Id %d\n",arg1); + return p; + } + + sessionId = (tANI_U8 ) arg2; + (void)pmcWowlDelBcastPattern(pMac, &delPattern, sessionId); + return p; +} + +static char * +dump_pmc_test_uapsd( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirSmeRsp smeRsp; + smeRsp.statusCode = eSIR_SME_SUCCESS; + + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + + pMac->pmc.uapsdEnabled = TRUE; + pMac->pmc.pmcState = BMPS; + + pmcRegisterDeviceStateUpdateInd(pMac, dump_pmc_deviceUpdateRoutine, pMac); + + pmcStartUapsd(pMac, dump_pmc_callbackRoutine, pMac); + smeRsp.messageType = eWNI_PMC_ENTER_UAPSD_RSP; + pmcMessageProcessor(pMac, &smeRsp); + pmcStopUapsd(pMac); + smeRsp.messageType = eWNI_PMC_EXIT_UAPSD_RSP; + pmcMessageProcessor(pMac, &smeRsp); + pmcDeregisterDeviceStateUpdateInd(pMac, dump_pmc_deviceUpdateRoutine); + return p; +} + +static char * +dump_pmc_test_Wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tSirSmeRsp smeRsp; + tSirWowlAddBcastPtrn addPattern; + tSirWowlDelBcastPtrn delPattern; + tSirSmeWowlEnterParams wowlEnterParams; + tSirSmeWowlExitParams wowlExitParams; + tANI_U8 sessionId = 0; + + smeRsp.statusCode = eSIR_SME_SUCCESS; + vos_mem_set(&addPattern, sizeof(tSirWowlAddBcastPtrn), 0); + vos_mem_set(&delPattern, sizeof(tSirWowlDelBcastPtrn), 0); + vos_mem_set(&wowlEnterParams, sizeof(tSirSmeWowlEnterParams), 0); + + (void) arg2; (void) arg3; (void) arg4; + + if(arg1 == CSR_ROAM_SESSION_MAX) + { + pmcLog(pMac, LOGE, "dump_pmc_test_Wowl: Invalid sessionId\n"); + return p; + } + + sessionId = (tANI_U8 ) arg1; + //Add pattern + sme_WowlAddBcastPattern(pMac, &addPattern, sessionId); + + //Delete pattern + sme_WowlDelBcastPattern(pMac, &delPattern, sessionId); + + //Force the device into BMPS + pMac->pmc.pmcState = BMPS; + + //Enter Wowl +#ifdef WLAN_WAKEUP_EVENTS + sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, dump_pmc_callbackRoutine2, pMac, + &wowlEnterParams, sessionId); +#else // WLAN_WAKEUP_EVENTS + sme_EnterWowl(pMac, dump_pmc_callbackRoutine, pMac, &wowlEnterParams, sessionId); +#endif // WLAN_WAKEUP_EVENTS + smeRsp.messageType = eWNI_PMC_ENTER_WOWL_RSP; + pmcMessageProcessor(pMac, &smeRsp); + + //Exit Wowl + sme_ExitWowl(pMac, &wowlExitParams); + smeRsp.messageType = eWNI_PMC_EXIT_WOWL_RSP; + pmcMessageProcessor(pMac, &smeRsp); + return p; +} + +static tDumpFuncEntry pmcMenuDumpTable[] = { + {0, "PMC (900-925)", NULL}, + // General + {900, "PMC: Dump State + config", dump_pmc_state}, + // IMPS Related + {901, "PMC: Enable IMPS", dump_pmc_enable_imps}, + {902, "PMC: Disable IMPS", dump_pmc_disable_imps}, + {903, "PMC: Request IMPS: Syntax: dump 903 ", dump_pmc_request_imps}, + // BMPS Related + {904, "PMC: Start Auto BMPS Timer", dump_pmc_start_auto_bmps_timer}, + {905, "PMC: Stop Auto BMPS Timer", dump_pmc_stop_auto_bmps_timer}, + {906, "PMC: Request BMPS", dump_pmc_request_bmps}, + // UAPSD Related + {907, "PMC: Enable UAPSD", dump_pmc_enable_uapsd}, + {908, "PMC: Disable UAPSD", dump_pmc_disable_uapsd}, + {909, "PMC: Start UAPSD", dump_pmc_start_uapsd}, + {910, "PMC: Stop UAPSD", dump_pmc_stop_uapsd}, + // Standby Related + {911, "PMC: Request Standby", dump_pmc_request_standby}, + // Full Power Related + {912, "PMC: Request Full Power", dump_pmc_request_full_power}, + //Unit Test Related + {913, "PMC: Test UAPSD", dump_pmc_test_uapsd}, + {914, "PMC: Test WOWL : Syntax :dump 914 ", dump_pmc_test_Wowl}, + // WoWL Related + {915, "PMC: Enter WoWL: Syntax: dump 915 ", dump_pmc_enter_wowl}, + {916, "PMC: Exit WoWL", dump_pmc_exit_wowl}, + {917, "PMC: Remove a pattern: Syntax: dump 917 >", dump_pmc_remove_ptrn}, + {918, "PMC: Enable BMPS", dump_pmc_enable_bmps}, + {919, "PMC: Disable BMPS", dump_pmc_disable_bmps} +}; + +void pmcDumpInit(tHalHandle hHal) +{ + logDumpRegisterTable( (tpAniSirGlobal)hHal, &pmcMenuDumpTable[0], + sizeof(pmcMenuDumpTable)/sizeof(pmcMenuDumpTable[0]) ); +} + +#endif //#if defined(ANI_LOGDUMP) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c new file mode 100644 index 000000000000..9652bde3f5a3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c @@ -0,0 +1,1625 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/**========================================================================= + + \file sme_Rrm.c + + \brief implementation for SME RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +#if defined WLAN_FEATURE_VOWIFI +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "aniGlobal.h" +#include "smeInside.h" +#include "sme_Api.h" +#include "smsDebug.h" +#include "cfgApi.h" + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "vos_diag_core_event.h" +#include "vos_diag_core_log.h" +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +#include "csrInsideApi.h" + +#include "rrmGlobal.h" + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +#include "csrEse.h" +#endif + +/* Roam score for a neighbor AP will be calculated based on the below definitions. + The calculated roam score will be used to select the roam able + candidate from neighbor AP list */ +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY 0 /* When we support 11r over the DS, this should have a non-zero value */ +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY 10 +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE 20 +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0 /* Not used */ +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS 5 +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD 3 +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM 8 +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA 0 /* We dont support delayed BA */ +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA 3 +#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN 30 + +#ifdef FEATURE_WLAN_ESE +#define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST 30 +#endif + +v_TIME_t RRM_scan_timer; + +/**--------------------------------------------------------------------------- + + \brief rrmLLPurgeNeighborCache() - + This function purges all the entries in the neighbor cache and frees up all the internal nodes + + \param - pMac - Pointer to the Hal Handle. + - pList - Pointer the List that should be purged. + \return - void + + --------------------------------------------------------------------------*/ +static void rrmLLPurgeNeighborCache(tpAniSirGlobal pMac, tDblLinkList *pList) +{ + tListElem *pEntry; + tRrmNeighborReportDesc *pNeighborReportDesc; + + csrLLLock(pList); + + while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_NOLOCK)) != NULL) + { + pNeighborReportDesc = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List ); + vos_mem_free(pNeighborReportDesc->pNeighborBssDescription); + vos_mem_free(pNeighborReportDesc); + } + + csrLLUnlock(pList); + + return; +} + +/**--------------------------------------------------------------------------- + + \brief rrmIndicateNeighborReportResult() - + This function calls the callback register by the caller while requesting for + neighbor report. This function gets invoked if a neighbor report is received from an AP + or neighbor response wait timer expires. + + \param - pMac - Pointer to the Hal Handle. + - vosStatus - VOS_STATUS_SUCCESS/VOS_STATUS_FAILURE based on whether a valid report is + received or neighbor timer expired + \return - void + + --------------------------------------------------------------------------*/ +void rrmIndicateNeighborReportResult(tpAniSirGlobal pMac, VOS_STATUS vosStatus) +{ + NeighborReportRspCallback callback; + void *callbackContext; + + /* Reset the neighbor response pending status */ + pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_FALSE; + + /* Stop the timer if it is already running. The timer should be running only in the SUCCESS case. */ + if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer)) + { + smsLog( pMac, LOG1, FL("No entry in neighbor report cache")); + vos_timer_stop(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer); + } + callback = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback; + callbackContext = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext; + + /* Reset the callback and the callback context before calling the callback. It is very likely that there may be a registration in + callback itself. */ + pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback = NULL; + pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext = NULL; + + /* Call the callback with the status received from caller */ + if (callback) + callback(callbackContext, vosStatus); +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) + // We came here with IAPP AP List + // Make sure we inform CSR of the neighbor list + // for ESE Associations. First clear the cache. + else + if (csrNeighborRoamIsESEAssoc(pMac)) + { + ProcessIAPPNeighborAPList(pMac); + } +#endif + + return; + +} + +/**--------------------------------------------------------------------------- + + \brief sme_RrmBeaconReportXmitInd() - + + Create and send the beacon report Xmit ind message to PE. + + \param - pMac - Pointer to the Hal Handle. + - pResult - scan result. + - measurementDone - flag to indicate that the measurement is done. + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, + tCsrScanResultInfo **pResultArr, + tANI_U8 measurementDone, + tANI_U8 bss_count ) +{ + tpSirBssDescription pBssDesc = NULL; + tpSirBeaconReportXmitInd pBeaconRep; + tANI_U16 length, ie_len; + tANI_U8 bssCounter=0, msgCounter=0; + tCsrScanResultInfo *pCurResult=NULL; + eHalStatus status = eHAL_STATUS_FAILURE; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Beacon report xmit Ind to PE"); +#endif + + if( NULL == pResultArr && !measurementDone ) + { + smsLog( pMac, LOGE, "Beacon report xmit Ind to PE Failed"); + return eHAL_STATUS_FAILURE; + } + + if (pResultArr) + pCurResult=pResultArr[bssCounter]; + + do + { + length = sizeof(tSirBeaconReportXmitInd); + pBeaconRep = vos_mem_malloc ( length ); + if ( NULL == pBeaconRep ) + { + smsLog( pMac, LOGP, "Unable to allocate memory for beacon report"); + return eHAL_STATUS_FAILED_ALLOC; + } + vos_mem_zero( pBeaconRep, length ); +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Allocated memory for pBeaconRep")); +#endif + pBeaconRep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND; + pBeaconRep->length = length; + pBeaconRep->uDialogToken = pSmeRrmContext->token; + pBeaconRep->duration = pSmeRrmContext->duration[0]; + pBeaconRep->regClass = pSmeRrmContext->regClass; + vos_mem_copy( pBeaconRep->bssId, pSmeRrmContext->sessionBssId, sizeof(tSirMacAddr) ); + + msgCounter=0; + while (pCurResult) + { + pBssDesc = &pCurResult->BssDescriptor; + if(pBssDesc != NULL) + { + ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length ); + pBeaconRep->pBssDescription[msgCounter] = vos_mem_malloc ( + ie_len+sizeof(tSirBssDescription)); + if (NULL == pBeaconRep->pBssDescription[msgCounter]) + break; + vos_mem_copy( pBeaconRep->pBssDescription[msgCounter], + pBssDesc, + sizeof(tSirBssDescription) ); + vos_mem_copy( &pBeaconRep->pBssDescription[msgCounter]->ieFields[0], + pBssDesc->ieFields, ie_len ); + smsLog( pMac, LOG1, + "...RRM Result Bssid = "MAC_ADDRESS_STR" chan= %d, rssi = -%d", + MAC_ADDR_ARRAY(pBeaconRep->pBssDescription[msgCounter]->bssId), + pBeaconRep->pBssDescription[msgCounter]->channelId, + pBeaconRep->pBssDescription[msgCounter]->rssi * (-1)); + + pBeaconRep->numBssDesc++; + + if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + + pCurResult = pResultArr[bssCounter + msgCounter]; + } + else + { + pCurResult = NULL; + break; + } + } + + bssCounter+=msgCounter; + if (!pResultArr || (pCurResult == NULL) || (bssCounter >= bss_count)) + { + pCurResult = NULL; + smsLog(pMac, LOG1, + "Reached to the max/last BSS in pCurResult list"); + } + else + { + pCurResult = pResultArr[bssCounter]; + smsLog(pMac, LOG1, + "Move to the next BSS set in pCurResult list"); + } + + pBeaconRep->fMeasureDone = (pCurResult)?false:measurementDone; + + smsLog(pMac, LOG1, + "SME Sending BcnRepXmit to PE numBss %d msgCounter %d bssCounter %d", + pBeaconRep->numBssDesc, msgCounter, bssCounter); + + status = palSendMBMessage(pMac->hHdd, pBeaconRep); + + } while (pCurResult); + + return status; +} + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +/**--------------------------------------------------------------------------- + + \brief sme_EseSendBeaconReqScanResults() + + This function sends up the scan results received as a part of + beacon request scanning. + This function is called after receiving the scan results per channel + Due to the limitation on the size of the IWEVCUSTOM buffer, we send 3 BSSIDs of + beacon report information in one custom event; + + \param - pMac - Pointer to the Hal Handle. + - sessionId - Session id + - channel - scan results belongs to this channel + - pResultArr - scan result. + - measurementDone - flag to indicate that the measurement is done. + - bss_count - number of bss found + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +static eHalStatus sme_EseSendBeaconReqScanResults(tpAniSirGlobal pMac, + tANI_U32 sessionId, + tANI_U8 channel, + tCsrScanResultInfo **pResultArr, + tANI_U8 measurementDone, + tANI_U8 bss_count) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tSirRetStatus fillIeStatus; + tpSirBssDescription pBssDesc = NULL; + tANI_U32 ie_len = 0; + tANI_U32 outIeLen = 0; + tANI_U8 bssCounter = 0; + tCsrScanResultInfo *pCurResult = NULL; + tANI_U8 msgCounter = 0; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tCsrRoamInfo roamInfo; + tSirEseBcnReportRsp bcnReport; + tpSirEseBcnReportRsp pBcnReport = &bcnReport; + tpCsrEseBeaconReqParams pCurMeasReqIe = NULL; + tANI_U8 i = 0; + + if (NULL == pSmeRrmContext) + { + smsLog( pMac, LOGE, "pSmeRrmContext is NULL"); + return eHAL_STATUS_FAILURE; + } + + if (NULL == pResultArr && !measurementDone) + { + smsLog( pMac, LOGE, "Beacon report xmit Ind to HDD Failed"); + return eHAL_STATUS_FAILURE; + } + + if (pResultArr) + pCurResult=pResultArr[bssCounter]; + + vos_mem_zero(&bcnReport, sizeof(tSirEseBcnReportRsp)); + do + { + pCurMeasReqIe = NULL; + for (i = 0; i < pSmeRrmContext->eseBcnReqInfo.numBcnReqIe; i++) + { + if(pSmeRrmContext->eseBcnReqInfo.bcnReq[i].channel == channel) + { + pCurMeasReqIe = &pSmeRrmContext->eseBcnReqInfo.bcnReq[i]; + break; + } + } + if(NULL != pCurMeasReqIe) + pBcnReport->measurementToken = pCurMeasReqIe->measurementToken; + smsLog( pMac, LOG1, "Channel(%d) MeasToken(%d)", channel, pBcnReport->measurementToken); + + msgCounter=0; + while (pCurResult) + { + pBssDesc = &pCurResult->BssDescriptor; + if (NULL != pBssDesc) + { + ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length ); + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.ChanNum = pBssDesc->channelId; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.Spare = 0; + if(NULL != pCurMeasReqIe) + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.MeasDuration = pCurMeasReqIe->measurementDuration; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.PhyType = pBssDesc->nwType; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.RecvSigPower = pBssDesc->rssi; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.ParentTsf = pBssDesc->parentTSF; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.TargetTsf[0] = pBssDesc->timeStamp[0]; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.TargetTsf[1] = pBssDesc->timeStamp[1]; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.BcnInterval = pBssDesc->beaconInterval; + pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.CapabilityInfo = pBssDesc->capabilityInfo; + vos_mem_copy(pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.Bssid, + pBssDesc->bssId, sizeof(tSirMacAddr)); + + fillIeStatus = sirFillBeaconMandatoryIEforEseBcnReport(pMac, + (tANI_U8 *)pBssDesc->ieFields, + ie_len, + &(pBcnReport->bcnRepBssInfo[msgCounter].pBuf), + &outIeLen); + if (eSIR_FAILURE == fillIeStatus) + { + continue; + } + pBcnReport->bcnRepBssInfo[msgCounter].ieLen = outIeLen; + + smsLog( pMac, LOG1,"Bssid("MAC_ADDRESS_STR") Channel=%d Rssi=%d", + MAC_ADDR_ARRAY(pBssDesc->bssId), + pBssDesc->channelId, (-1) * pBssDesc->rssi); + + pBcnReport->numBss++; + + if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + + pCurResult = pResultArr[msgCounter]; + } + else + { + pCurResult = NULL; + break; + } + } + + bssCounter += msgCounter; + if (!pResultArr || !pCurResult || (bssCounter >= SIR_BCN_REPORT_MAX_BSS_DESC)) + { + pCurResult = NULL; + smsLog(pMac, LOGE, + "Reached to the max/last BSS in pCurResult list"); + } + else + { + pCurResult = pResultArr[bssCounter]; + smsLog(pMac, LOGE, + "Move to the next BSS set in pCurResult list"); + } + + pBcnReport->flag = (measurementDone << 1)|((pCurResult)?true:false); + + smsLog(pMac, LOG1, "SME Sending BcnRep to HDD numBss(%d)" + " msgCounter(%d) bssCounter(%d) flag(%d)", + pBcnReport->numBss, msgCounter, bssCounter, pBcnReport->flag); + + roamInfo.pEseBcnReportRsp = pBcnReport; + status = csrRoamCallCallback(pMac, sessionId, &roamInfo, + 0, eCSR_ROAM_ESE_BCN_REPORT_IND, 0); + + /* Free the memory allocated to IE */ + for (i = 0; i < msgCounter; i++) + { + if (pBcnReport->bcnRepBssInfo[i].pBuf) + vos_mem_free(pBcnReport->bcnRepBssInfo[i].pBuf); + } + } while (pCurResult); + return status; +} + +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +/**--------------------------------------------------------------------------- + + \brief sme_RrmSendScanRequest() - + + This function is called to get the scan result from CSR and send the beacon report + xmit ind message to PE. + + \param - pMac - Pointer to the Hal Handle. + - num_chan - number of channels. + - channel list - list of channels to fetch the result from. + - measurementDone - flag to indicate that the measurement is done. + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ +static eHalStatus sme_RrmSendScanResult( tpAniSirGlobal pMac, + tANI_U8 num_chan, + tANI_U8* chanList, + tANI_U8 measurementDone ) +{ + tCsrScanResultFilter filter; + tScanResultHandle pResult; + tCsrScanResultInfo *pScanResult, *pNextResult; + tCsrScanResultInfo *pScanResultsArr[SIR_BCN_REPORT_MAX_BSS_DESC]; + eHalStatus status; + tANI_U8 counter=0; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tANI_U32 sessionId; + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Send scan result to PE "); +#endif + + vos_mem_zero( &filter, sizeof(filter) ); + vos_mem_zero( pScanResultsArr, sizeof(pNextResult)*SIR_BCN_REPORT_MAX_BSS_DESC ); + + filter.BSSIDs.numOfBSSIDs = 1; + filter.BSSIDs.bssid = &pSmeRrmContext->bssId; + + if( pSmeRrmContext->ssId.length ) + { + filter.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if( filter.SSIDs.SSIDList == NULL ) + { + smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") ); + return eHAL_STATUS_FAILURE; + } +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Allocated memory for SSIDList")); +#endif + vos_mem_zero( filter.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) ); + + filter.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length; + vos_mem_copy(filter.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length); + filter.SSIDs.numOfSSIDs = 1; + } + else + { + filter.SSIDs.numOfSSIDs = 0; + } + + filter.ChannelInfo.numOfChannels = num_chan; + filter.ChannelInfo.ChannelList = chanList; + + filter.fMeasurement = TRUE; + + /* + * In case this is beacon report request from last AP (before roaming) + * following call to csrRoamGetSessionIdFromBSSID will fail, hence use + * current session ID instead of one stored in SME rrm context + */ + if (eHAL_STATUS_FAILURE == + csrRoamGetSessionIdFromBSSID(pMac, + (tCsrBssid*)pSmeRrmContext->sessionBssId, + &sessionId )) { + smsLog( pMac, LOG1, FL("BSSID mismatch, using current sessionID")); + sessionId = pMac->roam.roamSession->sessionId; + } + + status = sme_ScanGetResult(pMac, (tANI_U8)sessionId, &filter, &pResult); + + if( filter.SSIDs.SSIDList ) + { + //Free the memory allocated for SSIDList. + vos_mem_free( filter.SSIDs.SSIDList ); +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Free memory for SSIDList") ); +#endif + } + + if (NULL == pResult) + { + /* + * no scan results + * + * Spec. doesnt say anything about such condition. + * Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report frame should + * contain one or more report IEs. It probably means dont send any + * response if no matching BSS found. Moreover, there is no flag or + * field in measurement report IE(7.3.2.22) OR beacon report + * IE(7.3.2.22.6) that can be set to indicate no BSS found on a + * given channel. + * + * If we finished measurement on all the channels, we still need to + * send a xmit indication with moreToFollow set to MEASURMENT_DONE + * so that PE can clean any context allocated. + */ + if( measurementDone ) + { +#if defined(FEATURE_WLAN_ESE_UPLOAD) + if (eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource) + { + status = sme_EseSendBeaconReqScanResults(pMac, + sessionId, + chanList[0], + NULL, + measurementDone, + 0); + } + else +#endif /*FEATURE_WLAN_ESE_UPLOAD*/ + status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone, 0); + } + return status; + } + + pScanResult = sme_ScanResultGetFirst(pMac, pResult); + + if( NULL == pScanResult && measurementDone ) + { +#if defined(FEATURE_WLAN_ESE_UPLOAD) + if (eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource) + { + status = sme_EseSendBeaconReqScanResults(pMac, + sessionId, + chanList[0], + NULL, + measurementDone, + 0); + } + else +#endif /*FEATURE_WLAN_ESE_UPLOAD*/ + status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone, 0 ); + } + + counter=0; + while (pScanResult) + { + pNextResult = sme_ScanResultGetNext(pMac, pResult); + if(pScanResult->timer >= RRM_scan_timer) + { + pScanResultsArr[counter++] = pScanResult; + } + pScanResult = pNextResult; //sme_ScanResultGetNext(hHal, pResult); + if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + } + + if (counter) + { + smsLog(pMac, LOG1, " Number of BSS Desc with RRM Scan %d ", counter); +#if defined(FEATURE_WLAN_ESE_UPLOAD) + if (eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource) + { + status = sme_EseSendBeaconReqScanResults(pMac, + sessionId, + chanList[0], + pScanResultsArr, + measurementDone, + counter); + } + else +#endif /*FEATURE_WLAN_ESE_UPLOAD*/ + status = sme_RrmSendBeaconReportXmitInd( pMac, + pScanResultsArr, + measurementDone, + counter); + } + sme_ScanResultPurge(pMac, pResult); + + return status; +} +/**--------------------------------------------------------------------------- + + \brief sme_RrmScanRequestCallback() - + + The sme module calls this callback function once it finish the scan request + and this function send the beacon report xmit to PE and starts a timer of + random interval to issue next request. + + \param - halHandle - Pointer to the Hal Handle. + - pContext - Pointer to the data context. + - scanId - Scan ID. + - status - CSR Status. + \return - 0 for success, non zero for failure + + --------------------------------------------------------------------------*/ + +static eHalStatus sme_RrmScanRequestCallback(tHalHandle halHandle, + void *pContext, + tANI_U8 sessionId, + tANI_U32 scanId, + eCsrScanStatus status) +{ + + tANI_U16 interval; + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tANI_U32 time_tick; + + + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Scan Request callback "); +#endif + //if any more channels are pending, start a timer of a random value within randomization interval. + // + // + if( (pSmeRrmContext->currentIndex + 1) < pSmeRrmContext->channelList.numOfChannels ) + { + sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], false ); + + pSmeRrmContext->currentIndex++; //Advance the current index. + + /* Start the timer to issue next request. From timer tick get a random + number within 10ms and max randomization interval. */ + time_tick = vos_timer_get_system_ticks(); + interval = time_tick % (pSmeRrmContext->randnIntvl - 10 + 1) + 10; + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Set timer for interval %d ", interval); +#endif + vos_timer_start( &pSmeRrmContext->IterMeasTimer, interval ); + + } + else + { + //Done with the measurement. Clean up all context and send a message to PE with measurement done flag set. + sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], true ); + vos_mem_free( pSmeRrmContext->channelList.ChannelList ); +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + pSmeRrmContext->eseBcnReqInProgress = FALSE; +#endif +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Free memory for ChannelList") ); +#endif + } + + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_RrmIssueScanReq() - This is called to send a scan request as part + of beacon report request . + + \param pMac - pMac global pointer + + \return eHAL_STATUS_SUCCESS - Validation is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_RrmIssueScanReq( tpAniSirGlobal pMac ) +{ + //Issue scan request. + tCsrScanRequest scanRequest; + v_U32_t scanId = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tANI_U32 sessionId; + tSirScanType scanType; + + status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId ); + if( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, "%s : Invalid sme Session ID", __func__); + return eHAL_STATUS_FAILURE; + } + + if ((pSmeRrmContext->currentIndex) >= pSmeRrmContext->channelList.numOfChannels) + return status; + + if( eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource || + eRRM_MSG_SOURCE_LEGACY_ESE == pSmeRrmContext->msgSource ) + scanType = pSmeRrmContext->measMode[pSmeRrmContext->currentIndex]; + else + scanType = pSmeRrmContext->measMode[0]; + + if ((eSIR_ACTIVE_SCAN == scanType) || (eSIR_PASSIVE_SCAN == scanType)) + { +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Issue scan request " ); +#endif + + vos_mem_zero( &scanRequest, sizeof(scanRequest)); + + /* set scanType, active or passive */ + scanRequest.scanType = scanType; + + vos_mem_copy(scanRequest.bssid, + pSmeRrmContext->bssId, sizeof(scanRequest.bssid) ); + + if (pSmeRrmContext->ssId.length) + { + scanRequest.SSIDs.numOfSSIDs = 1; + scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo)); + if (NULL == scanRequest.SSIDs.SSIDList) + { + smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") ); + return eHAL_STATUS_FAILURE; + } +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Allocated memory for pSSIDList")); +#endif + vos_mem_zero( scanRequest.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) ); + scanRequest.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length; + vos_mem_copy(scanRequest.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length); + } + + /* set min and max channel time */ + scanRequest.minChnTime = 0; //pSmeRrmContext->duration; Dont use min timeout. + if( eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource || + eRRM_MSG_SOURCE_LEGACY_ESE == pSmeRrmContext->msgSource ) + scanRequest.maxChnTime = pSmeRrmContext->duration[pSmeRrmContext->currentIndex]; + else + scanRequest.maxChnTime = pSmeRrmContext->duration[0]; + + smsLog( pMac, LOG1, "Scan Type(%d) Max Dwell Time(%d)", scanRequest.scanType, + scanRequest.maxChnTime ); + + RRM_scan_timer = vos_timer_get_system_time(); + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "For Duration %d ", scanRequest.maxChnTime ); +#endif + + /* set BSSType to default type */ + scanRequest.BSSType = eCSR_BSS_TYPE_ANY; + + /*Scan all the channels */ + scanRequest.ChannelInfo.numOfChannels = 1; + + scanRequest.ChannelInfo.ChannelList = &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex]; +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "On channel %d ", pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex] ); +#endif + + /* set requestType to full scan */ + scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + + status = sme_ScanRequest( pMac, (tANI_U8)sessionId, &scanRequest, &scanId, &sme_RrmScanRequestCallback, NULL ); + + if ( pSmeRrmContext->ssId.length ) + { + vos_mem_free(scanRequest.SSIDs.SSIDList); +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Free memory for SSIDList")); +#endif + } + } + else if (eSIR_BEACON_TABLE == scanType) /* beacon table */ + { + /*In beacon table mode, scan results are taken directly from scan cache + without issuing any scan request. So, it is not proper to update + RRM_scan_timer with latest time and hence made it to zero to satisfy + pScanResult->timer >= RRM_scan_timer */ + RRM_scan_timer = 0; + + if ((pSmeRrmContext->currentIndex + 1) < pSmeRrmContext->channelList.numOfChannels) + { + sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], false ); + pSmeRrmContext->currentIndex++; //Advance the current index. + sme_RrmIssueScanReq(pMac); +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + pSmeRrmContext->eseBcnReqInProgress = FALSE; +#endif + } + else + { + //Done with the measurement. Clean up all context and send a message to PE with measurement done flag set. + sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], true ); + vos_mem_free( pSmeRrmContext->channelList.ChannelList ); + } + } + else + { + smsLog( pMac, LOGE, "Unknown beacon report request mode(%d)", scanType); + /* Indicate measurement completion to PE */ + /* If this is not done, pCurrentReq pointer will not be freed and + PE will not handle subsequent Beacon requests */ + sme_RrmSendBeaconReportXmitInd(pMac, NULL, true, 0); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_RrmProcessBeaconReportReqInd() - This is called to process the Beacon + report request from peer AP forwarded through PE . + + \param pMsgBuf - a pointer to a buffer that maps to various structures base + on the message type. + The beginning of the buffer can always map to tSirSmeRsp. + + \return eHAL_STATUS_SUCCESS - Validation is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_RrmProcessBeaconReportReqInd(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tANI_U32 len = 0, i = 0; + eHalStatus status = eHAL_STATUS_SUCCESS; + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Received Beacon report request ind Channel = %d", pBeaconReq->channelInfo.channelNum ); +#endif + //section 11.10.8.1 (IEEE Std 802.11k-2008) + //channel 0 and 255 has special meaning. + if( (pBeaconReq->channelInfo.channelNum == 0) || + ((pBeaconReq->channelInfo.channelNum == 255) && (pBeaconReq->channelList.numChannels == 0) ) ) + { + //Add all the channel in the regulatory domain. + wlan_cfgGetStrLen( pMac, WNI_CFG_VALID_CHANNEL_LIST, &len ); + pSmeRrmContext->channelList.ChannelList = vos_mem_malloc( len ); + if( pSmeRrmContext->channelList.ChannelList == NULL ) + { + smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") ); + return eHAL_STATUS_FAILURE; + } +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Allocated memory for ChannelList") ); +#endif + csrGetCfgValidChannels( pMac, pSmeRrmContext->channelList.ChannelList, &len ); + pSmeRrmContext->channelList.numOfChannels = (tANI_U8)len; +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "channel == 0 performing on all channels"); +#endif + } + else + { + len = 0; + pSmeRrmContext->channelList.numOfChannels = 0; + + //If valid channel is present. We first Measure on the given channel. and + //if there are additional channels present in APchannelreport, measure on these also. + if ( pBeaconReq->channelInfo.channelNum != 255 ) + len = 1; +#if defined WLAN_VOWIFI_DEBUG + else + smsLog( pMac, LOGE, "channel == 255"); +#endif + + len += pBeaconReq->channelList.numChannels; + + pSmeRrmContext->channelList.ChannelList = vos_mem_malloc( len ); + if( pSmeRrmContext->channelList.ChannelList == NULL ) + { + smsLog( pMac, LOGP, FL("vos_mem_malloc failed") ); + return eHAL_STATUS_FAILURE; + } +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Allocated memory for ChannelList") ); +#endif + + if ( pBeaconReq->channelInfo.channelNum != 255 ) + { +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "channel == %d ", pBeaconReq->channelInfo.channelNum ); +#endif + if(csrRoamIsChannelValid( pMac, pBeaconReq->channelInfo.channelNum )) + pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->channelList.numOfChannels++] = pBeaconReq->channelInfo.channelNum; +#if defined WLAN_VOWIFI_DEBUG + else + smsLog( pMac, LOGE, "is Invalid channel, Ignoring this channel" ); +#endif + } + + for ( i = 0 ; i < pBeaconReq->channelList.numChannels; i++ ) + { + if(csrRoamIsChannelValid( pMac, pBeaconReq->channelList.channelNumber[i] )) + { + pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->channelList.numOfChannels] = pBeaconReq->channelList.channelNumber[i]; + pSmeRrmContext->channelList.numOfChannels++; + } + } + } + + //Copy session bssid + vos_mem_copy( pSmeRrmContext->sessionBssId, pBeaconReq->bssId, sizeof(tSirMacAddr) ); + + //copy measurement bssid + vos_mem_copy( pSmeRrmContext->bssId, pBeaconReq->macaddrBssid, sizeof(tSirMacAddr) ); + + //Copy ssid + vos_mem_copy( &pSmeRrmContext->ssId, &pBeaconReq->ssId, sizeof(tAniSSID) ); + + pSmeRrmContext->token = pBeaconReq->uDialogToken; + pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass; + pSmeRrmContext->randnIntvl = VOS_MAX(pBeaconReq->randomizationInterval, pSmeRrmContext->rrmConfig.max_randn_interval); + pSmeRrmContext->currentIndex = 0; + pSmeRrmContext->msgSource = pBeaconReq->msgSource; + vos_mem_copy((tANI_U8*)&pSmeRrmContext->measMode, (tANI_U8*)&pBeaconReq->fMeasurementtype, SIR_ESE_MAX_MEAS_IE_REQS); + vos_mem_copy((tANI_U8*)&pSmeRrmContext->duration, (tANI_U8*)&pBeaconReq->measurementDuration, SIR_ESE_MAX_MEAS_IE_REQS); + + status = sme_RrmIssueScanReq( pMac ); + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_RrmNeighborReportRequest() - This is API can be used to trigger a + Neighbor report from the peer. + + \param sessionId - session identifier on which the request should be made. + \param pNeighborReq - a pointer to a neighbor report request. + + \return eHAL_STATUS_SUCCESS - Validation is successful. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sme_RrmNeighborReportRequest(tpAniSirGlobal pMac, tANI_U8 sessionId, + tpRrmNeighborReq pNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpSirNeighborReportReqInd pMsg; + tCsrRoamSession *pSession; + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Request to send Neighbor report request received ")); +#endif + if( !CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + smsLog( pMac, LOGE, FL("Invalid session %d"), sessionId ); + return VOS_STATUS_E_INVAL; + } + pSession = CSR_GET_SESSION( pMac, sessionId ); + + /* If already a report is pending, return failure */ + if (eANI_BOOLEAN_TRUE == pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending) + { + smsLog( pMac, LOGE, FL("Neighbor request already pending.. Not allowed")); + return VOS_STATUS_E_AGAIN; + } + + pMsg = vos_mem_malloc ( sizeof(tSirNeighborReportReqInd) ); + if ( NULL == pMsg ) + { + smsLog( pMac, LOGE, "Unable to allocate memory for Neighbor request"); + return VOS_STATUS_E_NOMEM; + } + + + vos_mem_zero( pMsg, sizeof(tSirNeighborReportReqInd) ); +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL(" Allocated memory for Neighbor request") ); +#endif + + rrmLLPurgeNeighborCache(pMac, &pMac->rrm.rrmSmeContext.neighborReportCache); + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, FL("Purged the neighbor cache before sending Neighbor request: Status = %d"), status ); +#endif + + pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND; + pMsg->length = sizeof( tSirNeighborReportReqInd ); + vos_mem_copy( &pMsg->bssId, &pSession->connectedProfile.bssid, sizeof(tSirMacAddr) ); + pMsg->noSSID = pNeighborReq->no_ssid; + vos_mem_copy( &pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid)); + + status = palSendMBMessage(pMac->hHdd, pMsg); + if( status != eHAL_STATUS_SUCCESS ) + return VOS_STATUS_E_FAILURE; + + /* Neighbor report request message sent successfully to PE. Now register the callbacks */ + pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback = + callbackInfo->neighborRspCallback; + pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext = + callbackInfo->neighborRspCallbackContext; + pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_TRUE; + + /* Start neighbor response wait timer now */ + vos_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer, callbackInfo->timeout); + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief rrmCalculateNeighborAPRoamScore() - This API is called while handling + individual neighbor reports from the APs neighbor AP report to + calculate the cumulative roam score before storing it in neighbor + cache. + + \param pNeighborReportDesc - Neighbor BSS Descriptor node for which roam score + should be calculated + + \return void. +--------------------------------------------------------------------------*/ +static void rrmCalculateNeighborAPRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc pNeighborReportDesc) +{ + tpSirNeighborBssDescripton pNeighborBssDesc; + tANI_U32 roamScore = 0; +#ifdef FEATURE_WLAN_ESE + tANI_U8 sessionId; +#endif + + if (NULL == pNeighborReportDesc) + { + VOS_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + VOS_ASSERT(0); + return; + } + + pNeighborBssDesc = pNeighborReportDesc->pNeighborBssDescription; + + if (pNeighborBssDesc->bssidInfo.rrmInfo.fMobilityDomain) + { + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fSameSecurityMode) + { + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fSameAuthenticator) + { + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapRadioMeasurement) + { + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapSpectrumMeasurement) + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapQos) + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapApsd) + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapDelayedBlockAck) + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapImmediateBlockAck) + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA; + if (pNeighborBssDesc->bssidInfo.rrmInfo.fApPreauthReachable) + roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY; + } + } + } + } +#ifdef FEATURE_WLAN_ESE + sessionId = pNeighborReportDesc->sessionId; + /* It has come in the report so its the best score */ + if (csrNeighborRoamIs11rAssoc(pMac, sessionId) == FALSE) { + /* IAPP Route so lets make use of this info + * save all AP, as the list does not come all the time + * Save and reuse till the next AP List comes to us. + * Even save our own MAC address. Will be useful next time around. + */ + roamScore += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST; + } +#endif + pNeighborReportDesc->roamScore = roamScore; + + return; +} + +/*-------------------------------------------------------------------------- + \brief rrmStoreNeighborRptByRoamScore() - This API is called to store a given + Neighbor BSS descriptor to the neighbor cache. This function + stores the neighbor BSS descriptors in such a way that descriptors + are sorted by roamScore in descending order + + \param pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache + + \return void. +--------------------------------------------------------------------------*/ +void rrmStoreNeighborRptByRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc pNeighborReportDesc) +{ + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tListElem *pEntry; + tRrmNeighborReportDesc *pTempNeighborReportDesc; + + if (NULL == pNeighborReportDesc) + { + VOS_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + VOS_ASSERT(0); + return; + } + + if (csrLLIsListEmpty(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) + { + smsLog(pMac, LOGE, FL("Neighbor report cache is empty.. Adding a entry now")); + /* Neighbor list cache is empty. Insert this entry in the tail */ + csrLLInsertTail(&pSmeRrmContext->neighborReportCache, &pNeighborReportDesc->List, LL_ACCESS_LOCK); + return; + } + else + { + /* Should store the neighbor BSS description in the order sorted by roamScore in descending + order. APs with highest roamScore should be the 1st entry in the list */ + pEntry = csrLLPeekHead(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK); + while (pEntry != NULL) + { + pTempNeighborReportDesc = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List ); + if (pTempNeighborReportDesc->roamScore < pNeighborReportDesc->roamScore) + break; + pEntry = csrLLNext(&pSmeRrmContext->neighborReportCache, pEntry, LL_ACCESS_LOCK); + } + + if (pEntry) + /* This BSS roamscore is better than something in the list. Insert this before that one */ + csrLLInsertEntry(&pSmeRrmContext->neighborReportCache, pEntry, &pNeighborReportDesc->List, LL_ACCESS_LOCK); + else + /* All the entries in the list has a better roam Score than this one. Insert this at the last */ + csrLLInsertTail(&pSmeRrmContext->neighborReportCache, &pNeighborReportDesc->List, LL_ACCESS_LOCK); + } + return; +} + +/*-------------------------------------------------------------------------- + \brief sme_RrmProcessNeighborReport() - This is called to process the Neighbor + report received from PE. + + \param pMsgBuf - a pointer to a buffer that maps to various structures base + on the message type. + The beginning of the buffer can always map to tSirSmeRsp. + + \return eHAL_STATUS_SUCCESS - Validation is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_RrmProcessNeighborReport(tpAniSirGlobal pMac, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpSirNeighborReportInd pNeighborRpt = (tpSirNeighborReportInd) pMsgBuf; + tpRrmNeighborReportDesc pNeighborReportDesc; + tANI_U8 i = 0; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tANI_U8 sessionId; + + /* Get the session id */ + status = csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)pNeighborRpt->bssId, + (tANI_U32*) &sessionId); + if (HAL_STATUS_SUCCESS(status)) { +#ifdef FEATURE_WLAN_ESE + /* Clear the cache for ESE. */ + if (csrNeighborRoamIsESEAssoc(pMac, sessionId)) { + rrmLLPurgeNeighborCache(pMac, + &pMac->rrm.rrmSmeContext.neighborReportCache); + } +#endif + } + + for (i = 0; i < pNeighborRpt->numNeighborReports; i++) + { + pNeighborReportDesc = vos_mem_malloc(sizeof(tRrmNeighborReportDesc)); + if (NULL == pNeighborReportDesc) + { + smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report desc"); + status = eHAL_STATUS_FAILED_ALLOC; + goto end; + + } + + vos_mem_zero(pNeighborReportDesc, sizeof(tRrmNeighborReportDesc)); + pNeighborReportDesc->pNeighborBssDescription = vos_mem_malloc(sizeof(tSirNeighborBssDescription)); + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report BSS Description"); + vos_mem_free(pNeighborReportDesc); + status = eHAL_STATUS_FAILED_ALLOC; + goto end; + } + vos_mem_zero(pNeighborReportDesc->pNeighborBssDescription, sizeof(tSirNeighborBssDescription)); + vos_mem_copy(pNeighborReportDesc->pNeighborBssDescription, &pNeighborRpt->sNeighborBssDescription[i], + sizeof(tSirNeighborBssDescription)); + +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Received neighbor report with Neighbor BSSID: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pNeighborRpt->sNeighborBssDescription[i].bssId)); +#endif + + /* Calculate the roam score based on the BSS Capability in the BSSID Information and store it in Neighbor report Desc */ + rrmCalculateNeighborAPRoamScore(pMac, pNeighborReportDesc); + + /* Store the Neighbor report Desc in the cache based on the roam score */ + if ( pNeighborReportDesc->roamScore > 0) + { + rrmStoreNeighborRptByRoamScore(pMac, pNeighborReportDesc); + } + else + { + smsLog(pMac, LOGE, FL("Roam score of BSSID "MAC_ADDRESS_STR" is 0, Ignoring.."), + MAC_ADDR_ARRAY(pNeighborRpt->sNeighborBssDescription[i].bssId)); + + vos_mem_free(pNeighborReportDesc->pNeighborBssDescription); + vos_mem_free(pNeighborReportDesc); + } + } +end: + + if (!csrLLCount(&pMac->rrm.rrmSmeContext.neighborReportCache)) + vosStatus = VOS_STATUS_E_FAILURE; + + /* Received a report from AP. Indicate SUCCESS to the caller if there are some valid reports */ + rrmIndicateNeighborReportResult(pMac, vosStatus); + + return status; +} +/*-------------------------------------------------------------------------- + \brief sme_RrmMsgProcessor() - sme_ProcessMsg() calls this function for the + messages that are handled by SME RRM module. + + \param pMac - Pointer to the global MAC parameter structure. + \param msg_type - the type of msg passed by PE as defined in wniApi.h + \param pMsgBuf - a pointer to a buffer that maps to various structures base + on the message type. + The beginning of the buffer can always map to tSirSmeRsp. + + \return eHAL_STATUS_SUCCESS - Validation is successful. + + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_RrmMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type, + void *pMsgBuf) +{ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, + FL(" Msg = %d for RRM measurement") , msg_type ); + + //switch on the msg type & make the state transition accordingly + switch(msg_type) + { + case eWNI_SME_NEIGHBOR_REPORT_IND: + sme_RrmProcessNeighborReport( pMac, pMsgBuf ); + break; + + case eWNI_SME_BEACON_REPORT_REQ_IND: + sme_RrmProcessBeaconReportReqInd( pMac, pMsgBuf ); + break; + + default: + //err msg + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("sme_RrmMsgProcessor:unknown msg type = %d"), msg_type); + + break; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn rrmIterMeasTimerHandle + + \brief Timer handler to handle the timeout condition when a specific BT + stop event does not come back, in which case to restore back the + heartbeat timer. + + \param pMac - The handle returned by macOpen. + + \return VOID + + ---------------------------------------------------------------------------*/ + +void rrmIterMeasTimerHandle( v_PVOID_t userData ) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) userData; +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Randomization timer expired...send on next channel "); +#endif + //Issue a scan req for next channel. + sme_RrmIssueScanReq( pMac ); +} + +/* --------------------------------------------------------------------------- + + \fn rrmNeighborRspTimeoutHandler + + \brief Timer handler to handle the timeout condition when a neighbor request is sent + and no neighbor response is received from the AP + + \param pMac - The handle returned by macOpen. + + \return VOID + +---------------------------------------------------------------------------*/ + +void rrmNeighborRspTimeoutHandler +( v_PVOID_t userData ) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) userData; +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Neighbor Response timed out "); +#endif + rrmIndicateNeighborReportResult(pMac, VOS_STATUS_E_FAILURE); + return; +} + +/* --------------------------------------------------------------------------- + + \fn rrmOpen + + \brief + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS + + VOS_STATUS_E_FAILURE success + + VOS_STATUS_SUCCESS failure + + ---------------------------------------------------------------------------*/ + +VOS_STATUS rrmOpen (tpAniSirGlobal pMac) + +{ + + VOS_STATUS vosStatus; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + + pSmeRrmContext->rrmConfig.max_randn_interval = 50; //ms + + vosStatus = vos_timer_init( &pSmeRrmContext->IterMeasTimer, + + VOS_TIMER_TYPE_SW, + + rrmIterMeasTimerHandle, + + (void*) pMac); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to init timer"); + + return VOS_STATUS_E_FAILURE; + } + + vosStatus = vos_timer_init( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer, + + VOS_TIMER_TYPE_SW, + + rrmNeighborRspTimeoutHandler, + + (void*) pMac); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to init timer"); + + return VOS_STATUS_E_FAILURE; + } + + pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_FALSE; + + halStatus = csrLLOpen(pMac->hHdd, &pSmeRrmContext->neighborReportCache); + if (eHAL_STATUS_SUCCESS != halStatus) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to open neighbor cache result"); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + + +/* --------------------------------------------------------------------------- + + \fn rrmClose + + \brief + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS + + VOS_STATUS_E_FAILURE success + + VOS_STATUS_SUCCESS failure + + ---------------------------------------------------------------------------*/ + +VOS_STATUS rrmClose (tpAniSirGlobal pMac) + +{ + + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + if( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState( &pSmeRrmContext->IterMeasTimer ) ) + { + vosStatus = vos_timer_stop( &pSmeRrmContext->IterMeasTimer ); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Timer stop fail") ); + } + } + + vosStatus = vos_timer_destroy( &pSmeRrmContext->IterMeasTimer ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Fail to destroy timer") ); + + } + + if( VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer ) ) + { + vosStatus = vos_timer_stop( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer ); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, FL("Timer stop fail") ); + } + } + + vosStatus = vos_timer_destroy( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, FL("Fail to destroy timer") ); + + } + + rrmLLPurgeNeighborCache(pMac, &pSmeRrmContext->neighborReportCache); + + csrLLClose(&pSmeRrmContext->neighborReportCache); + + return vosStatus; + +} + + + + +/* --------------------------------------------------------------------------- + + \fn rrmReady + + \brief fn + + \param pMac - The handle returned by macOpen. + + \return VOS_STATUS + + ---------------------------------------------------------------------------*/ + +VOS_STATUS rrmReady (tpAniSirGlobal pMac) + +{ + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn rrmChangeDefaultConfigParam + \brief fn + + \param pMac - The handle returned by macOpen. + \param pRrmConfig - pointer to new rrm configs. + + \return VOS_STATUS + + ---------------------------------------------------------------------------*/ +VOS_STATUS rrmChangeDefaultConfigParam(tpAniSirGlobal pMac, + struct rrm_config_param *pRrmConfig) +{ + vos_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, pRrmConfig, + sizeof(struct rrm_config_param)); + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn smeRrmGetFirstBssEntryFromNeighborCache() + + \brief This function returns the first entry from the neighbor cache to the caller + + \param pMac - The handle returned by macOpen. + + \return VOID + +---------------------------------------------------------------------------*/ +tRrmNeighborReportDesc* smeRrmGetFirstBssEntryFromNeighborCache( tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tRrmNeighborReportDesc *pTempBssEntry = NULL; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + + pEntry = csrLLPeekHead( &pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK ); + + if(!pEntry || !csrLLCount(&pSmeRrmContext->neighborReportCache)) + { + //list empty + smsLog(pMac, LOGW, FL("List empty")); + return NULL; + } + + pTempBssEntry = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List ); + + return pTempBssEntry; +} + +/* --------------------------------------------------------------------------- + + \fn smeRrmGetNextBssEntryFromNeighborCache() + + \brief This function returns the entry next to the given entry from the + neighbor cache to the caller + + \param pMac - The handle returned by macOpen. + + \return VOID + +---------------------------------------------------------------------------*/ +tRrmNeighborReportDesc* smeRrmGetNextBssEntryFromNeighborCache( tpAniSirGlobal pMac, + tpRrmNeighborReportDesc pBssEntry) +{ + tListElem *pEntry; + tRrmNeighborReportDesc *pTempBssEntry = NULL; + + pEntry = csrLLNext(&pMac->rrm.rrmSmeContext.neighborReportCache, &pBssEntry->List, LL_ACCESS_LOCK); + + if(!pEntry) + { + //list empty + smsLog(pMac, LOGW, FL("List empty")); + return NULL; + } + + pTempBssEntry = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List ); + + return pTempBssEntry; +} + +#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) +void csrEseSendAdjacentApRepMsg(tpAniSirGlobal pMac, tCsrRoamSession *pSession) +{ + tpSirAdjacentApRepInd pAdjRep; + tANI_U16 length; + tANI_U32 roamTS2; + + smsLog( pMac, LOG1, "Adjacent AP Report Msg to PE"); + + length = sizeof(tSirAdjacentApRepInd ); + pAdjRep = vos_mem_malloc ( length ); + + if ( NULL == pAdjRep ) + { + smsLog( pMac, LOGP, "Unable to allocate memory for Adjacent AP report"); + return; + } + + vos_mem_zero( pAdjRep, length ); + pAdjRep->messageType = eWNI_SME_ESE_ADJACENT_AP_REPORT; + pAdjRep->length = length; + pAdjRep->channelNum = pSession->prevOpChannel; + vos_mem_copy( pAdjRep->bssid, &pSession->connectedProfile.bssid, sizeof(tSirMacAddr) ); + vos_mem_copy( pAdjRep->prevApMacAddr, &pSession->prevApBssid, sizeof(tSirMacAddr) ); + vos_mem_copy( &pAdjRep->prevApSSID, &pSession->prevApSSID, sizeof(tSirMacSSid) ); + roamTS2 = vos_timer_get_system_time(); + pAdjRep->tsmRoamdelay = roamTS2 - pSession->roamTS1; + pAdjRep->roamReason =SIR_ESE_ASSOC_REASON_UNSPECIFIED; + pAdjRep->clientDissSecs =(pAdjRep->tsmRoamdelay/1000); + + palSendMBMessage(pMac->hHdd, pAdjRep); + + return; +} +#endif /* FEATURE_WLAN_ESE */ +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c new file mode 100644 index 000000000000..7a7cdb04ff8b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c @@ -0,0 +1,17447 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/**========================================================================= + + \file smeApi.c + + \brief Definitions for SME APIs + + ========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + + when who what, where, why +---------- --- -------------------------------------------------------- +06/03/10 js Added support to hostapd driven + * deauth/disassoc/mic failure + +===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "smsDebug.h" +#include "sme_Api.h" +#include "csrInsideApi.h" +#include "smeInside.h" +#include "csrInternal.h" +#include "wlan_qct_wda.h" +#include "halMsgApi.h" +#include "vos_trace.h" +#include "sme_Trace.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "vos_utils.h" +#include "sapApi.h" +#include "macTrace.h" +#ifdef WLAN_FEATURE_NAN +#include "nan_Api.h" +#endif +#include "regdomain_common.h" + +extern tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); + +#define LOG_SIZE 256 +#define READ_MEMORY_DUMP_CMD 9 +#define TL_INIT_STATE 0 + +static tSelfRecoveryStats gSelfRecoveryStats; + + +// TxMB Functions +extern eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, tANI_U32 sessionId, + eSmeCommandType cmdType, void *pvParam, + tANI_U32 size, tSmeCmd **ppCmd); +extern void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +extern void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); +extern void csr_release_roc_req_cmd(tpAniSirGlobal mac_ctx); +extern eHalStatus p2pProcessRemainOnChannelCmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn); +extern eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg); +extern eHalStatus sme_mgmtFrmInd( tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm); +extern eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg); +extern eHalStatus sme_sendActionCnf( tHalHandle hHal, tANI_U8* pMsg); +extern eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd); + +static eHalStatus initSmeCmdList(tpAniSirGlobal pMac); +static void smeAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping ); + +eCsrPhyMode sme_GetPhyMode(tHalHandle hHal); + +eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf); + +void sme_DisconnectConnectedSessions(tpAniSirGlobal pMac); + +eHalStatus sme_HandleGenericChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf); + +eHalStatus sme_HandlePreChannelSwitchInd(tHalHandle hHal, void *pMsgBuf); + +eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +tANI_BOOLEAN csrIsSupportedChannel(tpAniSirGlobal pMac, tANI_U8 channelId); +#endif + +#ifdef WLAN_FEATURE_11W +eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, + tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm ); +#endif + +/* Message processor for events from DFS */ +eHalStatus dfsMsgProcessor(tpAniSirGlobal pMac, + v_U16_t msg_type,void *pMsgBuf); + +/* Channel Change Response Indication Handler */ +eHalStatus sme_ProcessChannelChangeResp(tpAniSirGlobal pMac, + v_U16_t msg_type,void *pMsgBuf); +eHalStatus sme_process_set_max_tx_power(tpAniSirGlobal pMac, + tSmeCmd *command); + +//Internal SME APIs +eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + + if(psSme) + { + if( VOS_IS_STATUS_SUCCESS( vos_lock_acquire( &psSme->lkSmeGlobalLock) ) ) + { + status = eHAL_STATUS_SUCCESS; + } + } + + return (status); +} + + +eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + + if(psSme) + { + if( VOS_IS_STATUS_SUCCESS( vos_lock_release( &psSme->lkSmeGlobalLock) ) ) + { + status = eHAL_STATUS_SUCCESS; + } + } + + return (status); +} + +/** + * free_sme_cmds() - This function frees memory allocated for SME commands + * @mac_ctx: Pointer to Global MAC structure + * + * This function frees memory allocated for SME commands + * + * @Return: void + */ +static void free_sme_cmds(tpAniSirGlobal mac_ctx) +{ + uint32_t idx; + if (NULL == mac_ctx->sme.pSmeCmdBufAddr) + return; + + for (idx = 0; idx < mac_ctx->sme.totalSmeCmd; idx++) + vos_mem_free(mac_ctx->sme.pSmeCmdBufAddr[idx]); + + vos_mem_free(mac_ctx->sme.pSmeCmdBufAddr); + mac_ctx->sme.pSmeCmdBufAddr = NULL; +} + +static eHalStatus initSmeCmdList(tpAniSirGlobal pMac) +{ + eHalStatus status; + tSmeCmd *pCmd; + tANI_U32 cmd_idx; + uint32_t sme_cmd_ptr_ary_sz; + VOS_STATUS vosStatus; + vos_timer_t* cmdTimeoutTimer = NULL; + + pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND; + if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, + &pMac->sme.smeCmdActiveList))) + goto end; + + if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, + &pMac->sme.smeCmdPendingList))) + goto end; + + if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, + &pMac->sme.smeScanCmdActiveList))) + goto end; + + if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, + &pMac->sme.smeScanCmdPendingList))) + goto end; + + if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd, + &pMac->sme.smeCmdFreeList))) + goto end; + + /* following pointer contains array of pointers for tSmeCmd* */ + sme_cmd_ptr_ary_sz = sizeof(void*) * pMac->sme.totalSmeCmd; + pMac->sme.pSmeCmdBufAddr = vos_mem_malloc(sme_cmd_ptr_ary_sz); + if (NULL == pMac->sme.pSmeCmdBufAddr) { + status = eHAL_STATUS_FAILURE; + goto end; + } + + status = eHAL_STATUS_SUCCESS; + vos_mem_set(pMac->sme.pSmeCmdBufAddr, sme_cmd_ptr_ary_sz, 0); + for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) { + /* + * Since total size of all commands together can be huge chunk of + * memory, allocate SME cmd individually. These SME CMDs are moved + * between pending and active queues. And these freeing of these + * queues just manipulates the list but does not actually frees SME + * CMD pointers. Hence store each SME CMD address in the array, + * sme.pSmeCmdBufAddr. This will later facilitate freeing up of all + * SME CMDs with just a for loop. + */ + pMac->sme.pSmeCmdBufAddr[cmd_idx] = vos_mem_malloc(sizeof(tSmeCmd)); + if (NULL == pMac->sme.pSmeCmdBufAddr[cmd_idx]) { + status = eHAL_STATUS_FAILURE; + free_sme_cmds(pMac); + goto end; + } + pCmd = (tSmeCmd*)pMac->sme.pSmeCmdBufAddr[cmd_idx]; + csrLLInsertTail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK); + } + + /* This timer is only to debug the active list command timeout */ + + cmdTimeoutTimer = (vos_timer_t*)vos_mem_malloc(sizeof(vos_timer_t)); + if (cmdTimeoutTimer) + { + pMac->sme.smeCmdActiveList.cmdTimeoutTimer = cmdTimeoutTimer; + vosStatus = + vos_timer_init( pMac->sme.smeCmdActiveList.cmdTimeoutTimer, + VOS_TIMER_TYPE_SW, + activeListCmdTimeoutHandle, + (void*) pMac); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Init Timer fail for active list command process time out"); + vos_mem_free(pMac->sme.smeCmdActiveList.cmdTimeoutTimer); + } + else + { + pMac->sme.smeCmdActiveList.cmdTimeoutDuration = + CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE; + } + } + +end: + if (!HAL_STATUS_SUCCESS(status)) + smsLog(pMac, LOGE, "failed to initialize sme command list:%d\n", + status); + + return (status); +} + + +void smeReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCmd) +{ + pCmd->command = eSmeNoCommand; + csrLLInsertTail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK); +} + + + +static void smeReleaseCmdList(tpAniSirGlobal pMac, tDblLinkList *pList) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + + while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_LOCK)) != NULL) + { + //TODO: base on command type to call release functions + //reinitialize different command types so they can be reused + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + smeAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + } +} + +static void purgeSmeCmdList(tpAniSirGlobal pMac) +{ + //release any out standing commands back to free command list + smeReleaseCmdList(pMac, &pMac->sme.smeCmdPendingList); + smeReleaseCmdList(pMac, &pMac->sme.smeCmdActiveList); + smeReleaseCmdList(pMac, &pMac->sme.smeScanCmdPendingList); + smeReleaseCmdList(pMac, &pMac->sme.smeScanCmdActiveList); +} + +void purgeSmeSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId, + tDblLinkList *pList) +{ + //release any out standing commands back to free command list + tListElem *pEntry, *pNext; + tSmeCmd *pCommand; + tDblLinkList localList; + + vos_mem_zero(&localList, sizeof(tDblLinkList)); + if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList))) + { + smsLog(pMac, LOGE, FL(" failed to open list")); + return; + } + + csrLLLock(pList); + pEntry = csrLLPeekHead(pList, LL_ACCESS_NOLOCK); + while(pEntry != NULL) + { + pNext = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if(pCommand->sessionId == sessionId) + { + if(csrLLRemoveEntry(pList, pEntry, LL_ACCESS_NOLOCK)) + { + csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK); + } + } + pEntry = pNext; + } + csrLLUnlock(pList); + + while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + smeAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE); + } + csrLLClose(&localList); +} + + +static eHalStatus freeSmeCmdList(tpAniSirGlobal pMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + purgeSmeCmdList(pMac); + csrLLClose(&pMac->sme.smeCmdPendingList); + csrLLClose(&pMac->sme.smeCmdActiveList); + csrLLClose(&pMac->sme.smeScanCmdPendingList); + csrLLClose(&pMac->sme.smeScanCmdActiveList); + csrLLClose(&pMac->sme.smeCmdFreeList); + + /*destroy active list command time out timer */ + vos_timer_destroy(pMac->sme.smeCmdActiveList.cmdTimeoutTimer); + vos_mem_free(pMac->sme.smeCmdActiveList.cmdTimeoutTimer); + pMac->sme.smeCmdActiveList.cmdTimeoutTimer = NULL; + + status = vos_lock_acquire(&pMac->sme.lkSmeGlobalLock); + if(status != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, + FL("Failed to acquire the lock status = %d"), status); + goto done; + } + + free_sme_cmds(pMac); + + status = vos_lock_release(&pMac->sme.lkSmeGlobalLock); + if(status != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOGE, + FL("Failed to release the lock status = %d"), status); + } +done: + return (status); +} + + +void dumpCsrCommandInfo(tpAniSirGlobal pMac, tSmeCmd *pCmd) +{ + switch( pCmd->command ) + { + case eSmeCommandScan: + smsLog( pMac, LOGE, " scan command reason is %d", pCmd->u.scanCmd.reason ); + break; + + case eSmeCommandRoam: + smsLog( pMac, LOGE, " roam command reason is %d", pCmd->u.roamCmd.roamReason ); + break; + + case eSmeCommandWmStatusChange: + smsLog( pMac, LOGE, " WMStatusChange command type is %d", pCmd->u.wmStatusChangeCmd.Type ); + break; + + case eSmeCommandSetKey: + smsLog( pMac, LOGE, " setKey command auth(%d) enc(%d)", + pCmd->u.setKeyCmd.authType, pCmd->u.setKeyCmd.encType ); + break; + + case eSmeCommandRemoveKey: + smsLog( pMac, LOGE, " removeKey command auth(%d) enc(%d)", + pCmd->u.removeKeyCmd.authType, pCmd->u.removeKeyCmd.encType ); + break; + + default: + smsLog( pMac, LOGE, " default: Unhandled command %d", + pCmd->command); + break; + } +} + +tSmeCmd *smeGetCommandBuffer( tpAniSirGlobal pMac ) +{ + tSmeCmd *pRetCmd = NULL, *pTempCmd = NULL; + tListElem *pEntry; + static int smeCommandQueueFull = 0; + + pEntry = csrLLRemoveHead( &pMac->sme.smeCmdFreeList, LL_ACCESS_LOCK ); + + /* + * If we can get another MS Msg buffer, then we are ok. Just link + * the entry onto the linked list. (We are using the linked list + * to keep track of the message buffers). + */ + if ( pEntry ) + { + pRetCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + /* reset when free list is available */ + smeCommandQueueFull = 0; + } + else + { + int idx = 1; + + //Cannot change pRetCmd here since it needs to return later. + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if( pEntry ) + { + pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + } + smsLog( pMac, LOGE, "Out of command buffer.... command (0x%X) stuck", + (pTempCmd) ? pTempCmd->command : eSmeNoCommand ); + if(pTempCmd) + { + if( eSmeCsrCommandMask & pTempCmd->command ) + { + //CSR command is stuck. See what the reason code is for that command + dumpCsrCommandInfo(pMac, pTempCmd); + } + } //if(pTempCmd) + + //dump what is in the pending queue + csrLLLock(&pMac->sme.smeCmdPendingList); + pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK ); + while(pEntry && !smeCommandQueueFull) + { + pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + /* Print only 1st five commands from pending queue. */ + if (idx <= 5) + smsLog( pMac, LOGE, "Out of command buffer.... SME pending command #%d (0x%X)", + idx, pTempCmd->command ); + idx++; + if( eSmeCsrCommandMask & pTempCmd->command ) + { + //CSR command is stuck. See what the reason code is for that command + dumpCsrCommandInfo(pMac, pTempCmd); + } + pEntry = csrLLNext( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK ); + } + csrLLUnlock(&pMac->sme.smeCmdPendingList); + + idx = 1; + //There may be some more command in CSR's own pending queue + csrLLLock(&pMac->roam.roamCmdPendingList); + pEntry = csrLLPeekHead( &pMac->roam.roamCmdPendingList, LL_ACCESS_NOLOCK ); + while(pEntry && !smeCommandQueueFull) + { + pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + /* Print only 1st five commands from CSR pending queue */ + if (idx <= 5) + smsLog( pMac, LOGE, + "Out of command buffer.... CSR roamCmdPendingList command #%d (0x%X)", + idx, pTempCmd->command ); + idx++; + dumpCsrCommandInfo(pMac, pTempCmd); + pEntry = csrLLNext( &pMac->roam.roamCmdPendingList, pEntry, LL_ACCESS_NOLOCK ); + } + /* Increament static variable so that it prints pending command only once*/ + smeCommandQueueFull++; + csrLLUnlock(&pMac->roam.roamCmdPendingList); + + /* panic with out-of-command */ + VOS_BUG(0); + } + + /* memset to zero */ + if (pRetCmd) { + vos_mem_set((tANI_U8 *)&pRetCmd->command, sizeof(pRetCmd->command), 0); + vos_mem_set((tANI_U8 *)&pRetCmd->sessionId, + sizeof(pRetCmd->sessionId), 0); + vos_mem_set((tANI_U8 *)&pRetCmd->u, sizeof(pRetCmd->u), 0); + } + + return(pRetCmd); +} + + +void smePushCommand( tpAniSirGlobal pMac, tSmeCmd *pCmd, tANI_BOOLEAN fHighPriority ) +{ + if (!SME_IS_START(pMac)) { + smsLog(pMac, LOGE, FL("Sme in stop state")); + return; + } + + if ( fHighPriority ) + { + csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pCmd->Link, LL_ACCESS_LOCK ); + } + else + { + csrLLInsertTail( &pMac->sme.smeCmdPendingList, &pCmd->Link, LL_ACCESS_LOCK ); + } + + // process the command queue... + smeProcessPendingQueue( pMac ); + + return; +} + + +static eSmeCommandType smeIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand ) +{ + eSmeCommandType pmcCommand = eSmeNoCommand; + tANI_BOOLEAN fFullPowerNeeded = eANI_BOOLEAN_FALSE; + tPmcState pmcState; + eHalStatus status; + + do + { + pmcState = pmcGetPmcState(pMac); + + status = csrIsFullPowerNeeded( pMac, pCommand, NULL, &fFullPowerNeeded ); + if( !HAL_STATUS_SUCCESS(status) ) + { + //PMC state is not right for the command, drop it + return ( eSmeDropCommand ); + } + if( fFullPowerNeeded ) break; + fFullPowerNeeded = ( ( eSmeCommandAddTs == pCommand->command ) || + ( eSmeCommandDelTs == pCommand->command ) ); + if( fFullPowerNeeded ) break; +#ifdef FEATURE_OEM_DATA_SUPPORT + fFullPowerNeeded = (pmcState == IMPS && + eSmeCommandOemDataReq == pCommand->command); + if(fFullPowerNeeded) break; +#endif + fFullPowerNeeded = (pmcState == IMPS && + eSmeCommandRemainOnChannel == pCommand->command); + if(fFullPowerNeeded) break; + } while(0); + + if( fFullPowerNeeded ) + { + switch( pmcState ) + { + case IMPS: + case STANDBY: + pmcCommand = eSmeCommandExitImps; + break; + + case BMPS: + pmcCommand = eSmeCommandExitBmps; + break; + + case UAPSD: + pmcCommand = eSmeCommandExitUapsd; + break; + + case WOWL: + pmcCommand = eSmeCommandExitWowl; + break; + + default: + break; + } + } + + return ( pmcCommand ); +} + +static eSmeCommandType smePsOffloadIsFullPowerNeeded(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + eSmeCommandType pmcCommand = eSmeNoCommand; + tANI_BOOLEAN fFullPowerNeeded = eANI_BOOLEAN_FALSE; + eHalStatus status; + tPmcState pmcState; + + do + { + /* Check for CSR Commands which require full power */ + status = csrPsOffloadIsFullPowerNeeded(pMac, pCommand, NULL, + &fFullPowerNeeded); + if(!HAL_STATUS_SUCCESS(status)) + { + /* PMC state is not right for the command, drop it */ + return eSmeDropCommand; + } + if(fFullPowerNeeded) break; + + /* Check for SME Commands which require Full Power */ + if((eSmeCommandAddTs == pCommand->command) || + ((eSmeCommandDelTs == pCommand->command))) + { + /* Get the PMC State */ + pmcState = pmcOffloadGetPmcState(pMac, pCommand->sessionId); + switch(pmcState) + { + case REQUEST_BMPS: + case BMPS: + case REQUEST_START_UAPSD: + case REQUEST_STOP_UAPSD: + case UAPSD: + fFullPowerNeeded = eANI_BOOLEAN_TRUE; + break; + case STOPPED: + break; + default: + break; + } + break; + } + } while(0); + + if(fFullPowerNeeded) + { + pmcCommand = eSmeCommandExitBmps; + } + + return pmcCommand; +} + + +//For commands that need to do extra cleanup. +static void smeAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping ) +{ + if( eSmePmcCommandMask & pCommand->command ) + { + if(!pMac->psOffloadEnabled) + pmcAbortCommand( pMac, pCommand, fStopping ); + else + pmcOffloadAbortCommand(pMac, pCommand, fStopping); + } + else if ( eSmeCsrCommandMask & pCommand->command ) + { + csrAbortCommand( pMac, pCommand, fStopping ); + } + else + { + switch( pCommand->command ) + { + case eSmeCommandRemainOnChannel: + if (NULL != pCommand->u.remainChlCmd.callback) + { + remainOnChanCallback callback = + pCommand->u.remainChlCmd.callback; + /* process the msg */ + if( callback ) + { + callback(pMac, pCommand->u.remainChlCmd.callbackCtx, + eCSR_SCAN_ABORT ); + } + } + smeReleaseCommand( pMac, pCommand ); + break; + default: + smeReleaseCommand( pMac, pCommand ); + break; + } + } +} + +tListElem *csrGetCmdToProcess(tpAniSirGlobal pMac, tDblLinkList *pList, + tANI_U8 sessionId, tANI_BOOLEAN fInterlocked) +{ + tListElem *pCurEntry = NULL; + tSmeCmd *pCommand; + + /* Go through the list and return the command whose session id is not + * matching with the current ongoing scan cmd sessionId */ + pCurEntry = csrLLPeekHead( pList, LL_ACCESS_LOCK ); + while (pCurEntry) + { + pCommand = GET_BASE_ADDR(pCurEntry, tSmeCmd, Link); + if (pCommand->sessionId != sessionId) + { + smsLog(pMac, LOG1, "selected the command with different sessionId"); + return pCurEntry; + } + + pCurEntry = csrLLNext(pList, pCurEntry, fInterlocked); + } + + smsLog(pMac, LOG1, "No command pending with different sessionId"); + return NULL; +} + +tANI_BOOLEAN smeProcessScanQueue(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pSmeEntry = NULL; + tSmeCmd *pSmeCommand = NULL; + tANI_BOOLEAN status = eANI_BOOLEAN_TRUE; + + if ((!csrLLIsListEmpty(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ))) { + pSmeEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (pSmeEntry) + pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link) ; + } + + csrLLLock( &pMac->sme.smeScanCmdActiveList ); + if (csrLLIsListEmpty( &pMac->sme.smeScanCmdActiveList, + LL_ACCESS_NOLOCK )) + { + if (!csrLLIsListEmpty(&pMac->sme.smeScanCmdPendingList, + LL_ACCESS_LOCK)) + { + pEntry = csrLLPeekHead( &pMac->sme.smeScanCmdPendingList, + LL_ACCESS_LOCK ); + if (pEntry) { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + if (pSmeCommand != NULL) { + /* if there is an active SME command, do not process + * the pending scan cmd + */ + smsLog(pMac, LOGE, "SME scan cmd is pending on session %d", + pSmeCommand->sessionId); + status = eANI_BOOLEAN_FALSE; + goto end; + } + //We cannot execute any command in wait-for-key state until setKey is through. + if (CSR_IS_WAIT_FOR_KEY( pMac, pCommand->sessionId)) + { + if (!CSR_IS_SET_KEY_COMMAND(pCommand)) + { + smsLog(pMac, LOGE, + " Cannot process command(%d) while waiting for key", + pCommand->command); + status = eANI_BOOLEAN_FALSE; + goto end; + } + } + if ( csrLLRemoveEntry( &pMac->sme.smeScanCmdPendingList, + pEntry, LL_ACCESS_LOCK ) ) + { + csrLLInsertHead( &pMac->sme.smeScanCmdActiveList, + &pCommand->Link, LL_ACCESS_NOLOCK ); + + switch (pCommand->command) + { + case eSmeCommandScan: + smsLog(pMac, LOG1, + " Processing scan offload command "); + csrProcessScanCommand( pMac, pCommand ); + break; + case eSmeCommandRemainOnChannel: + smsLog(pMac, LOG1, + "Processing req remain on channel offload" + " command"); + p2pProcessRemainOnChannelCmd(pMac, pCommand); + break; + default: + smsLog(pMac, LOGE, + " Something wrong, wrong command enqueued" + " to smeScanCmdPendingList"); + pEntry = csrLLRemoveHead( + &pMac->sme.smeScanCmdActiveList, + LL_ACCESS_NOLOCK ); + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + smeReleaseCommand( pMac, pCommand ); + break; + } + } + } + } + } +end: + csrLLUnlock(&pMac->sme.smeScanCmdActiveList); + return status; +} + +tANI_BOOLEAN smeProcessCommand( tpAniSirGlobal pMac ) +{ + tANI_BOOLEAN fContinue = eANI_BOOLEAN_FALSE; + eHalStatus status = eHAL_STATUS_SUCCESS; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pSmeEntry; + tSmeCmd *pSmeCommand; + eSmeCommandType pmcCommand = eSmeNoCommand; + + /* + * If the ActiveList is empty, then nothing is active so we can process a + * pending command. + * Always lock active list before locking pending list. + */ + csrLLLock( &pMac->sme.smeCmdActiveList ); + if ( csrLLIsListEmpty( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ) ) + { + if(!csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK)) + { + /* If scan command is pending in the smeScanCmdActive list + * then pick the command from smeCmdPendingList which is + * not matching with the scan command session id. + * At any point of time only one command will be allowed + * on a single session. */ + if ((pMac->fScanOffload) && + (!csrLLIsListEmpty(&pMac->sme.smeScanCmdActiveList, + LL_ACCESS_LOCK))) + { + pSmeEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList, + LL_ACCESS_LOCK); + if (pSmeEntry) + { + pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link); + + pEntry = csrGetCmdToProcess(pMac, + &pMac->sme.smeCmdPendingList, + pSmeCommand->sessionId, + LL_ACCESS_LOCK); + goto sme_process_cmd; + } + } + + //Peek the command + pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK ); +sme_process_cmd: + if( pEntry ) + { + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + + /* Allow only disconnect command + * in wait-for-key state until setKey is through. + */ + if( CSR_IS_WAIT_FOR_KEY( pMac, pCommand->sessionId ) && + !CSR_IS_DISCONNECT_COMMAND( pCommand ) ) + { + if (CSR_IS_CLOSE_SESSION_COMMAND(pCommand)) { + tSmeCmd *sme_cmd = NULL; + + smsLog(pMac, LOGE, + FL("SessionId %d: close session command issued while waiting for key, issue disconnect first"), + pCommand->sessionId); + status = csr_prepare_disconnect_command(pMac, + pCommand->sessionId, &sme_cmd); + if (HAL_STATUS_SUCCESS(status) && sme_cmd) { + csrLLLock(&pMac->sme.smeCmdPendingList); + csrLLInsertHead(&pMac->sme.smeCmdPendingList, + &sme_cmd->Link, LL_ACCESS_NOLOCK); + pEntry = csrLLPeekHead(&pMac->sme.smeCmdPendingList, + LL_ACCESS_NOLOCK); + csrLLUnlock(&pMac->sme.smeCmdPendingList); + goto sme_process_cmd; + } + } + + if( !CSR_IS_SET_KEY_COMMAND( pCommand ) ) + { + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + smsLog(pMac, LOGE, FL("SessionId %d: Cannot process " + "command(%d) while waiting for key"), + pCommand->sessionId, pCommand->command); + fContinue = eANI_BOOLEAN_FALSE; + goto sme_process_scan_queue; + } + } + if(pMac->psOffloadEnabled) + pmcCommand = smePsOffloadIsFullPowerNeeded(pMac, pCommand); + else + pmcCommand = smeIsFullPowerNeeded( pMac, pCommand ); + if( eSmeDropCommand == pmcCommand ) + { + csrLLUnlock(&pMac->sme.smeCmdActiveList); + //This command is not ok for current PMC state + if( csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_LOCK ) ) + { + smeAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE ); + } + //tell caller to continue + fContinue = eANI_BOOLEAN_TRUE; + goto sme_process_scan_queue; + } + else if( eSmeNoCommand != pmcCommand ) + { + tExitBmpsInfo exitBmpsInfo; + void *pv = NULL; + tANI_U32 size = 0; + tSmeCmd *pPmcCmd = NULL; + + if( eSmeCommandExitBmps == pmcCommand ) + { + exitBmpsInfo.exitBmpsReason = eSME_REASON_OTHER; + pv = (void *)&exitBmpsInfo; + size = sizeof(tExitBmpsInfo); + } + //pmcCommand has to be one of the exit power save command + status = pmcPrepareCommand(pMac, pCommand->sessionId, + pmcCommand, pv, size, + &pPmcCmd); + if( HAL_STATUS_SUCCESS( status ) && pPmcCmd ) + { + //Force this command to wake up the chip + csrLLInsertHead( &pMac->sme.smeCmdActiveList, &pPmcCmd->Link, LL_ACCESS_NOLOCK ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_COMMAND, pPmcCmd->sessionId, pPmcCmd->command)); + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + /* Handle PS Offload Case Separately */ + if(pMac->psOffloadEnabled) + { + fContinue = pmcOffloadProcessCommand(pMac, pPmcCmd); + } + else + { + fContinue = pmcProcessCommand( pMac, pPmcCmd ); + } + if( fContinue ) + { + //The command failed, remove it + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, &pPmcCmd->Link, LL_ACCESS_NOLOCK ) ) + { + pmcReleaseCommand( pMac, pPmcCmd ); + } + } + } + else + { + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + smsLog( pMac, LOGE, FL( "Cannot issue command(0x%X) to wake up the chip. Status = %d"), pmcCommand, status ); + //Let it retry + fContinue = eANI_BOOLEAN_TRUE; + } + goto sme_process_scan_queue; + } + if ( csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_LOCK ) ) + { + // we can reuse the pCommand + + // Insert the command onto the ActiveList... + csrLLInsertHead( &pMac->sme.smeCmdActiveList, &pCommand->Link, LL_ACCESS_NOLOCK ); + + // .... and process the command. + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_COMMAND, pCommand->sessionId, pCommand->command)); + switch ( pCommand->command ) + { + + case eSmeCommandScan: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + status = csrProcessScanCommand( pMac, pCommand ); + break; + + case eSmeCommandRoam: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + status = csrRoamProcessCommand( pMac, pCommand ); + if(!HAL_STATUS_SUCCESS(status)) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandRoam( pMac, pCommand ); + } + } + break; + + case eSmeCommandWmStatusChange: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + csrRoamProcessWmStatusChangeCommand(pMac, pCommand); + break; + + case eSmeCommandSetKey: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + status = csrRoamProcessSetKeyCommand( pMac, pCommand ); + if(!HAL_STATUS_SUCCESS(status)) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandSetKey( pMac, pCommand ); + } + } + break; + + case eSmeCommandRemoveKey: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + status = csrRoamProcessRemoveKeyCommand( pMac, pCommand ); + if(!HAL_STATUS_SUCCESS(status)) + { + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK ) ) + { + csrReleaseCommandRemoveKey( pMac, pCommand ); + } + } + break; + + case eSmeCommandAddStaSession: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + csrProcessAddStaSessionCommand( pMac, pCommand ); + break; + case eSmeCommandDelStaSession: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + csrProcessDelStaSessionCommand( pMac, pCommand ); + break; + case eSmeCommandSetMaxTxPower: + csrLLUnlock(&pMac->sme.smeCmdActiveList); + sme_process_set_max_tx_power(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); + } + break; + +#ifdef FEATURE_OEM_DATA_SUPPORT + case eSmeCommandOemDataReq: + csrLLUnlock(&pMac->sme.smeCmdActiveList); + oemData_ProcessOemDataReqCommand(pMac, pCommand); + break; +#endif + case eSmeCommandRemainOnChannel: + csrLLUnlock(&pMac->sme.smeCmdActiveList); + p2pProcessRemainOnChannelCmd(pMac, pCommand); + break; + case eSmeCommandNoAUpdate: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + p2pProcessNoAReq(pMac,pCommand); + case eSmeCommandEnterImps: + case eSmeCommandExitImps: + case eSmeCommandEnterBmps: + case eSmeCommandExitBmps: + case eSmeCommandEnterUapsd: + case eSmeCommandExitUapsd: + case eSmeCommandEnterWowl: + case eSmeCommandExitWowl: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + if(pMac->psOffloadEnabled) + { + fContinue = + pmcOffloadProcessCommand(pMac, pCommand); + } + else + { + fContinue = pmcProcessCommand(pMac, pCommand); + } + if( fContinue ) + { + //The command failed, remove it + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK ) ) + { + pmcReleaseCommand( pMac, pCommand ); + } + } + break; + + //Treat standby differently here because caller may not be able to handle + //the failure so we do our best here + case eSmeCommandEnterStandby: + if( csrIsConnStateDisconnected( pMac, pCommand->sessionId ) ) + { + //It can continue + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + if(pMac->psOffloadEnabled) + { + fContinue = + pmcOffloadProcessCommand(pMac, pCommand); + } + else + { + fContinue = + pmcProcessCommand(pMac, pCommand); + } + if( fContinue ) + { + //The command failed, remove it + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK ) ) + { + pmcReleaseCommand( pMac, pCommand ); + } + } + } + else + { + //Need to issue a disconnect first before processing this command + tSmeCmd *pNewCmd; + + //We need to re-run the command + fContinue = eANI_BOOLEAN_TRUE; + //Pull off the standby command first + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_NOLOCK ) ) + { + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + //Need to call CSR function here because the disconnect command + //is handled by CSR + pNewCmd = csrGetCommandBuffer( pMac ); + if( NULL != pNewCmd ) + { + //Put the standby command to the head of the pending list first + csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pCommand->Link, + LL_ACCESS_LOCK ); + pNewCmd->command = eSmeCommandRoam; + pNewCmd->u.roamCmd.roamReason = eCsrForcedDisassoc; + //Put the disassoc command before the standby command + csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pNewCmd->Link, + LL_ACCESS_LOCK ); + } + else + { + //Continue the command here + if(pMac->psOffloadEnabled) + { + fContinue = + pmcOffloadProcessCommand(pMac, + pCommand); + } + else + { + fContinue = pmcProcessCommand(pMac, + pCommand); + } + if( fContinue ) + { + //The command failed, remove it + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK ) ) + { + pmcReleaseCommand( pMac, pCommand ); + } + } + } + } + else + { + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + smsLog( pMac, LOGE, FL(" failed to remove standby command") ); + VOS_ASSERT(0); + } + } + break; + + case eSmeCommandAddTs: + case eSmeCommandDelTs: + csrLLUnlock( &pMac->sme.smeCmdActiveList ); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + fContinue = qosProcessCommand( pMac, pCommand ); + if( fContinue ) + { + //The command failed, remove it + if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_NOLOCK ) ) + { +//#ifndef WLAN_MDM_CODE_REDUCTION_OPT + qosReleaseCommand( pMac, pCommand ); +//#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/ + } + } +#endif + break; +#ifdef FEATURE_WLAN_TDLS + case eSmeCommandTdlsSendMgmt: + case eSmeCommandTdlsAddPeer: + case eSmeCommandTdlsDelPeer: + case eSmeCommandTdlsLinkEstablish: + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "sending TDLS Command 0x%x to PE", pCommand->command); + + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + status = csrTdlsProcessCmd( pMac, pCommand ); + } + break ; +#endif + + default: + //something is wrong + //remove it from the active list + smsLog(pMac, LOGE, " csrProcessCommand processes an unknown command %d", pCommand->command); + pEntry = csrLLRemoveHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ); + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + smeReleaseCommand( pMac, pCommand ); + status = eHAL_STATUS_FAILURE; + break; + } + if(!HAL_STATUS_SUCCESS(status)) + { + fContinue = eANI_BOOLEAN_TRUE; + } + }//if(pEntry) + else + { + //This is odd. Some one else pull off the command. + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + } + } + else + { + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + } + } + else + { + //No command waiting + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + /* + * This is only used to restart an idle mode scan, + * it means at least one other idle scan has finished. + * Moreover Idle Scan is not supported with power + * save offload supported + */ + if(!pMac->psOffloadEnabled && + pMac->scan.fRestartIdleScan && + eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan) + { + tANI_U32 nTime = 0; + + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE; + if(!HAL_STATUS_SUCCESS(csrScanTriggerIdleScan(pMac, &nTime))) + { + csrScanStartIdleScanTimer(pMac, nTime); + } + } + } + } + else { + csrLLUnlock( &pMac->sme.smeCmdActiveList ); + } + +sme_process_scan_queue: + if (pMac->fScanOffload && !(smeProcessScanQueue(pMac))) + fContinue = eANI_BOOLEAN_FALSE; + + return ( fContinue ); +} + +void smeProcessPendingQueue( tpAniSirGlobal pMac ) +{ + while( smeProcessCommand( pMac ) ); +} + + +tANI_BOOLEAN smeCommandPending(tpAniSirGlobal pMac) +{ + return ( !csrLLIsListEmpty( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ) || + !csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK) ); +} + + + +//Global APIs + +/*-------------------------------------------------------------------------- + + \brief sme_Open() - Initialize all SME modules and put them at idle state + + The function initializes each module inside SME, PMC, CCM, CSR, etc. . Upon + successfully return, all modules are at idle state ready to start. + + smeOpen must be called before any other SME APIs can be involved. + smeOpen must be called after macOpen. + This is a synchronous call + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME is successfully initialized. + + Other status means SME is failed to be initialized + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Open(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); +#ifndef WLAN_FEATURE_MBSSID + v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_SAP, NULL); +#endif + + do { + pMac->sme.state = SME_STATE_STOP; + pMac->sme.currDeviceMode = VOS_STA_MODE; + if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pMac->sme.lkSmeGlobalLock ) ) ) + { + smsLog( pMac, LOGE, "sme_Open failed init lock" ); + status = eHAL_STATUS_FAILURE; + break; + } + + status = ccmOpen(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "ccmOpen failed during initialization with status=%d", status ); + break; + } + + status = csrOpen(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "csrOpen failed during initialization with status=%d", status ); + break; + } + + if(!pMac->psOffloadEnabled) + { + status = pmcOpen(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "pmcOpen failed during initialization with status=%d", + status ); + break; + } + } + else + { + status = pmcOffloadOpen(hHal); + if (! HAL_STATUS_SUCCESS(status)) { + smsLog( pMac, LOGE, + "pmcOffloadOpen failed during initialization with status=%d", + status ); + break; + } + } + +#ifdef FEATURE_WLAN_TDLS + pMac->isTdlsPowerSaveProhibited = 0; +#endif + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + status = sme_QosOpen(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "Qos open failed during initialization with status=%d", status ); + break; + } + + status = btcOpen(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "btcOpen open failed during initialization with status=%d", status ); + break; + } +#endif +#ifdef FEATURE_OEM_DATA_SUPPORT + status = oemData_OemDataReqOpen(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog(pMac, LOGE, + "oemData_OemDataReqOpen failed during initialization with status=%d", status ); + break; + } +#endif + + if(!HAL_STATUS_SUCCESS((status = initSmeCmdList(pMac)))) + break; + +#ifndef WLAN_FEATURE_MBSSID + if ( NULL == pvosGCtx ){ + smsLog( pMac, LOGE, "WLANSAP_Open open failed during initialization"); + status = eHAL_STATUS_FAILURE; + break; + } + + status = WLANSAP_Open( pvosGCtx ); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "WLANSAP_Open open failed during initialization with status=%d", status ); + break; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI + status = rrmOpen(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "rrmOpen open failed during initialization with status=%d", status ); + break; + } +#endif + + sme_p2pOpen(pMac); + smeTraceInit(pMac); + + }while (0); + + return status; +} + +/* + * sme_init_chan_list, triggers channel setup based on country code. + */ +eHalStatus sme_init_chan_list(tHalHandle hal, v_U8_t *alpha2, + COUNTRY_CODE_SOURCE cc_src) +{ + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + + if ((cc_src == COUNTRY_CODE_SET_BY_USER) && + (pmac->roam.configParam.fSupplicantCountryCodeHasPriority)) + { + pmac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE; + } + + return csr_init_chan_list(pmac, alpha2); +} + +/*-------------------------------------------------------------------------- + + \brief sme_set11dinfo() - Set the 11d information about valid channels + and there power using information from nvRAM + This function is called only for AP. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + \Param pSmeConfigParams - a pointer to a caller allocated object of + typedef struct _smeConfigParams. + + \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully. + + Other status means SME is failed to update the config parameters. + \sa +--------------------------------------------------------------------------*/ + +eHalStatus sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO, NO_SESSION, 0)); + if (NULL == pSmeConfigParams ) { + smsLog( pMac, LOGE, + "Empty config param structure for SME, nothing to update"); + return status; + } + + status = csrSetChannels(hHal, &pSmeConfigParams->csrConfig ); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrChangeDefaultConfigParam failed with status=%d", + status ); + } + return status; +} + +/*-------------------------------------------------------------------------- + + \brief sme_getSoftApDomain() - Get the current regulatory domain of softAp. + + This is a synchronous call + + \param hHal - The handle returned by HostapdAdapter. + \Param v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp. + + \return eHAL_STATUS_SUCCESS - SME successfully completed the request. + + Other status means, failed to get the current regulatory domain. + \sa +--------------------------------------------------------------------------*/ + +eHalStatus sme_getSoftApDomain(tHalHandle hHal, v_REGDOMAIN_t *domainIdSoftAp) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN, NO_SESSION, 0)); + if (NULL == domainIdSoftAp ) { + smsLog( pMac, LOGE, "Uninitialized domain Id"); + return status; + } + + *domainIdSoftAp = pMac->scan.domainIdCurrent; + status = eHAL_STATUS_SUCCESS; + + return status; +} + + +eHalStatus sme_setRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SET_REGINFO, NO_SESSION, 0)); + if (NULL == apCntryCode ) { + smsLog( pMac, LOGE, "Empty Country Code, nothing to update"); + return status; + } + + status = csrSetRegInfo(hHal, apCntryCode ); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrSetRegInfo failed with status=%d", + status ); + } + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +eHalStatus sme_SetPlmRequest(tHalHandle hHal, tpSirPlmReq pPlmReq) +{ + eHalStatus status; + tANI_BOOLEAN ret = eANI_BOOLEAN_FALSE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tANI_U8 ch_list[WNI_CFG_VALID_CHANNEL_LIST] = {0}; + tANI_U8 count, valid_count = 0; + vos_msg_t msg; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pPlmReq->sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL("session %d not found"), pPlmReq->sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + if( !pSession->sessionActive ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s Invalid Sessionid", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + if (pPlmReq->enable) { + + /* validating channel numbers */ + for (count = 0; count < pPlmReq->plmNumCh; count++) { + + ret = csrIsSupportedChannel(pMac, pPlmReq->plmChList[count]); + if (ret && pPlmReq->plmChList[count] > 14) + { + if (NV_CHANNEL_DFS == + vos_nv_getChannelEnabledState(pPlmReq->plmChList[count])) + { + /* DFS channel is provided, no PLM bursts can be + * transmitted. Ignoring these channels. + */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s DFS channel %d ignored for PLM", __func__, + pPlmReq->plmChList[count]); + continue; + } + } + else if (!ret) + { + /* Not supported, ignore the channel */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s Unsupported channel %d ignored for PLM", + __func__, pPlmReq->plmChList[count]); + continue; + } + ch_list[valid_count] = pPlmReq->plmChList[count]; + valid_count++; + } /* End of for () */ + + /* Copying back the valid channel list to plm struct */ + vos_mem_set((void *)pPlmReq->plmChList, pPlmReq->plmNumCh, 0); + if (valid_count) + vos_mem_copy(pPlmReq->plmChList, ch_list, valid_count); + /* All are invalid channels, FW need to send the PLM + * report with "incapable" bit set. + */ + pPlmReq->plmNumCh = valid_count; + } /* PLM START */ + + msg.type = WDA_SET_PLM_REQ; + msg.reserved = 0; + msg.bodyptr = pPlmReq; + + if (!VOS_IS_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_PLM_REQ message to WDA", + __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock(&pMac->sme); + } + return (status); +} +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO +/*-------------------------------------------------------------------------- + + \brief sme_UpdateChannelConfig() - Update channel configuration in RIVA. + + It is used at driver start up to inform RIVA of the default channel + configuration. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME update the channel config successfully. + + Other status means SME is failed to update the channel config. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateChannelConfig(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CHANNEL_CONFIG, NO_SESSION, 0)); + pmcUpdateScanParams( pMac, &(pMac->roam.configParam), + &pMac->scan.base20MHzChannels, FALSE); + return eHAL_STATUS_SUCCESS; +} +#endif // FEATURE_WLAN_SCAN_PNLO + +/*-------------------------------------------------------------------------- + + \brief sme_UpdateConfig() - Change configurations for all SME modules + + The function updates some configuration for modules in SME, CCM, CSR, etc + during SMEs close open sequence. + + Modules inside SME apply the new configuration at the next transaction. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + \Param pSmeConfigParams - a pointer to a caller allocated object of + typedef struct _smeConfigParams. + + \return eHAL_STATUS_SUCCESS - SME update the config parameters successfully. + + Other status means SME is failed to update the config parameters. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateConfig(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG, NO_SESSION, 0)); + if (NULL == pSmeConfigParams ) { + smsLog( pMac, LOGE, + "Empty config param structure for SME, nothing to update"); + return status; + } + + status = csrChangeDefaultConfigParam(pMac, &pSmeConfigParams->csrConfig); + + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrChangeDefaultConfigParam failed with status=%d", + status ); + } +#if defined WLAN_FEATURE_VOWIFI + status = rrmChangeDefaultConfigParam(hHal, &pSmeConfigParams->rrmConfig); + + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "rrmChangeDefaultConfigParam failed with status=%d", + status ); + } +#endif + //For SOC, CFG is set before start + //We don't want to apply global CFG in connect state because that may cause some side affect + if( + csrIsAllSessionDisconnected( pMac) ) + { + csrSetGlobalCfgs(pMac); + } + + /* update the directed scan offload setting */ + pMac->fScanOffload = pSmeConfigParams->fScanOffload; + + if (pMac->fScanOffload) + { + /* + * If scan offload is enabled then lim has allow the sending of + * scan request to firmware even in power save mode. The firmware has + * to take care of exiting from power save mode + */ + status = ccmCfgSetInt(hHal, WNI_CFG_SCAN_IN_POWERSAVE, + eANI_BOOLEAN_TRUE, NULL, eANI_BOOLEAN_FALSE); + + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CCM"); + } + } + pMac->isCoalesingInIBSSAllowed = + pSmeConfigParams->csrConfig.isCoalesingInIBSSAllowed; + + /* update the p2p listen offload setting */ + pMac->fP2pListenOffload = pSmeConfigParams->fP2pListenOffload; + + /* update p2p offload status */ + pMac->pnoOffload = pSmeConfigParams->pnoOffload; + + pMac->fEnableDebugLog = pSmeConfigParams->fEnableDebugLog; + + /* update interface configuration */ + pMac->sme.max_intf_count = pSmeConfigParams->max_intf_count; + + pMac->enable5gEBT = pSmeConfigParams->enable5gEBT; + pMac->sme.enableSelfRecovery = pSmeConfigParams->enableSelfRecovery; + + pMac->f_sta_miracast_mcc_rest_time_val = + pSmeConfigParams->f_sta_miracast_mcc_rest_time_val; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + pMac->sap.sap_channel_avoidance = pSmeConfigParams->sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + pMac->f_prefer_non_dfs_on_radar = + pSmeConfigParams->f_prefer_non_dfs_on_radar; + pMac->fine_time_meas_cap = pSmeConfigParams->fine_time_meas_cap; + + return status; +} + +/** + * sme_update_roam_params - Store/Update the roaming params + * @hHal Handle for Hal layer + * @session_id SME Session ID + * @roam_params_src The source buffer to copy + * @update_param Type of parameter to be updated + * + * Return: Return the status of the updation. + */ +eHalStatus sme_update_roam_params(tHalHandle hHal, + uint8_t session_id, struct roam_ext_params roam_params_src, + int update_param) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + struct roam_ext_params *roam_params_dst; + uint8_t i; + + roam_params_dst = &pMac->roam.configParam.roam_params; + switch(update_param) { + case REASON_ROAM_EXT_SCAN_PARAMS_CHANGED: + roam_params_dst->raise_rssi_thresh_5g = + roam_params_src.raise_rssi_thresh_5g; + roam_params_dst->drop_rssi_thresh_5g = + roam_params_src.drop_rssi_thresh_5g; + roam_params_dst->raise_factor_5g= + roam_params_src.raise_factor_5g; + roam_params_dst->drop_factor_5g = + roam_params_src.drop_factor_5g; + roam_params_dst->max_raise_rssi_5g = + roam_params_src.max_raise_rssi_5g; + roam_params_dst->max_drop_rssi_5g= + roam_params_src.max_drop_rssi_5g; + roam_params_dst->alert_rssi_threshold = + roam_params_src.alert_rssi_threshold; + roam_params_dst->is_5g_pref_enabled = true; + break; + case REASON_ROAM_SET_SSID_ALLOWED: + vos_mem_set(&roam_params_dst->ssid_allowed_list, 0, + sizeof(tSirMacSSid) * MAX_SSID_ALLOWED_LIST); + roam_params_dst->num_ssid_allowed_list= + roam_params_src.num_ssid_allowed_list; + for (i=0; inum_ssid_allowed_list; i++) { + roam_params_dst->ssid_allowed_list[i].length = + roam_params_src.ssid_allowed_list[i].length; + vos_mem_copy(roam_params_dst->ssid_allowed_list[i].ssId, + roam_params_src.ssid_allowed_list[i].ssId, + roam_params_dst->ssid_allowed_list[i].length); + } + break; + case REASON_ROAM_SET_FAVORED_BSSID: + vos_mem_set(&roam_params_dst->bssid_favored, 0, + sizeof(tSirMacAddr) * MAX_BSSID_FAVORED); + roam_params_dst->num_bssid_favored= + roam_params_src.num_bssid_favored; + for (i=0; inum_bssid_favored; i++) { + vos_mem_copy(&roam_params_dst->bssid_favored[i], + &roam_params_src.bssid_favored[i], + sizeof(tSirMacAddr)); + roam_params_dst->bssid_favored_factor[i] = + roam_params_src.bssid_favored_factor[i]; + } + break; + case REASON_ROAM_SET_BLACKLIST_BSSID: + vos_mem_set(&roam_params_dst->bssid_avoid_list, 0, + sizeof(tSirMacAddr) * MAX_BSSID_AVOID_LIST); + roam_params_dst->num_bssid_avoid_list = + roam_params_src.num_bssid_avoid_list; + for (i=0; inum_bssid_avoid_list; i++) { + vos_mem_copy(&roam_params_dst->bssid_avoid_list[i], + &roam_params_src.bssid_avoid_list[i], + sizeof(tSirMacAddr)); + } + break; + case REASON_ROAM_GOOD_RSSI_CHANGED: + roam_params_dst->good_rssi_roam = + roam_params_src.good_rssi_roam; + break; + default: + break; + } + csrRoamOffloadScan(pMac, session_id, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, update_param); + return 0; +} +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void sme_ProcessGetGtkInfoRsp( tHalHandle hHal, + tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return ; + } + if (pMac->pmc.GtkOffloadGetInfoCB == NULL) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: HDD callback is null", __func__); + return ; + } + pMac->pmc.GtkOffloadGetInfoCB(pMac->pmc.GtkOffloadGetInfoCBContext, + pGtkOffloadGetInfoRsp); +} +#endif + +/*-------------------------------------------------------------------------- + + \fn - sme_ProcessReadyToSuspend + \brief - On getting ready to suspend indication, this function calls + callback registered (HDD callbacks) with SME to inform + ready to suspend indication. + + \param hHal - Handle returned by macOpen. + pReadyToSuspend - Parameter received along with ready to suspend + indication from WMA. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_ProcessReadyToSuspend( tHalHandle hHal, + tpSirReadyToSuspendInd pReadyToSuspend) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return ; + } + + if (NULL != pMac->readyToSuspendCallback) + { + pMac->readyToSuspendCallback (pMac->readyToSuspendContext, + pReadyToSuspend->suspended); + pMac->readyToSuspendCallback = NULL; + } +} + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +/*-------------------------------------------------------------------------- + + \fn - sme_ProcessReadyToExtWoW + \brief - On getting ready to Ext WoW indication, this function calls + callback registered (HDD callbacks) with SME to inform + ready to ExtWoW indication. + + \param hHal - Handle returned by macOpen. + pReadyToExtWoW - Parameter received along with ready to Ext WoW + indication from WMA. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_ProcessReadyToExtWoW( tHalHandle hHal, + tpSirReadyToExtWoWInd pReadyToExtWoW) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return ; + } + + if (NULL != pMac->readyToExtWoWCallback) + { + pMac->readyToExtWoWCallback (pMac->readyToExtWoWContext, + pReadyToExtWoW->status); + pMac->readyToExtWoWCallback = NULL; + pMac->readyToExtWoWContext = NULL; + } + +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_ChangeConfigParams + \brief The SME API exposed for HDD to provide config params to SME during + SMEs stop -> start sequence. + + If HDD changed the domain that will cause a reset. This function will + provide the new set of 11d information for the new domain. Currently this + API provides info regarding 11d only at reset but we can extend this for + other params (PMC, QoS) which needs to be initialized again at reset. + + This is a synchronous call + + \param hHal - The handle returned by macOpen. + + \Param + pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that + currently provides 11d related information like Country code, + Regulatory domain, valid channel list, Tx power per channel, a + list with active/passive scan allowed per valid channel. + + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ChangeConfigParams(tHalHandle hHal, + tCsrUpdateConfigParam *pUpdateConfigParam) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pUpdateConfigParam ) { + smsLog( pMac, LOGE, + "Empty config param structure for SME, nothing to reset"); + return status; + } + + status = csrChangeConfigParams(pMac, pUpdateConfigParam); + + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrUpdateConfigParam failed with status=%d", + status ); + } + + return status; + +} + +/*-------------------------------------------------------------------------- + + \brief sme_HDDReadyInd() - SME sends eWNI_SME_SYS_READY_IND to PE to inform + that the NIC is ready to run. + + The function is called by HDD at the end of initialization stage so PE/HAL can + enable the NIC to running state. + + This is a synchronous call + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE + successfully. + + Other status means SME failed to send the message to PE. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_HDDReadyInd(tHalHandle hHal) +{ + tSirSmeReadyReq Msg; + eHalStatus status = eHAL_STATUS_FAILURE; + tPmcPowerState powerState; + tPmcSwitchState hwWlanSwitchState; + tPmcSwitchState swWlanSwitchState; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_HDDREADYIND, NO_SESSION, 0)); + do + { + + Msg.messageType = eWNI_SME_SYS_READY_IND; + Msg.length = sizeof( tSirSmeReadyReq ); + + if (eSIR_FAILURE != uMacPostCtrlMsg( hHal, (tSirMbMsg*)&Msg )) + { + status = eHAL_STATUS_SUCCESS; + } + else + { + smsLog( pMac, LOGE, + "uMacPostCtrlMsg failed to send eWNI_SME_SYS_READY_IND"); + break; + } + + if(!pMac->psOffloadEnabled) + { + status = pmcQueryPowerState( hHal, &powerState, + &hwWlanSwitchState, &swWlanSwitchState ); + if ( ! HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, "pmcQueryPowerState failed with status=%d", + status ); + break; + } + + if ( (ePMC_SWITCH_OFF != hwWlanSwitchState) && + (ePMC_SWITCH_OFF != swWlanSwitchState) ) + { + status = csrReady(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, "csrReady failed with status=%d", status ); + break; + } + status = pmcReady(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, "pmcReady failed with status=%d", status ); + break; + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if(VOS_STATUS_SUCCESS != btcReady(hHal)) + { + status = eHAL_STATUS_FAILURE; + smsLog( pMac, LOGE, "btcReady failed"); + break; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI + if(VOS_STATUS_SUCCESS != rrmReady(hHal)) + { + status = eHAL_STATUS_FAILURE; + smsLog( pMac, LOGE, "rrmReady failed"); + break; + } +#endif + } + } + else + { + status = csrReady(pMac); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE, "csrReady failed with status=%d", status ); + break; + } +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if(VOS_STATUS_SUCCESS != btcReady(hHal)) + { + status = eHAL_STATUS_FAILURE; + smsLog( pMac, LOGE, "btcReady failed"); + break; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI + if(VOS_STATUS_SUCCESS != rrmReady(hHal)) + { + status = eHAL_STATUS_FAILURE; + smsLog( pMac, LOGE, "rrmReady failed"); + break; + } +#endif + } + pMac->sme.state = SME_STATE_READY; + } while( 0 ); + + return status; +} + +/*-------------------------------------------------------------------------- + + \brief sme_Start() - Put all SME modules at ready state. + + The function starts each module in SME, PMC, CCM, CSR, etc. . Upon + successfully return, all modules are ready to run. + This is a synchronous call + \param hHal - The handle returned by macOpen. + + \return eHAL_STATUS_SUCCESS - SME is ready. + + Other status means SME is failed to start + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Start(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + do + { + status = csrStart(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrStart failed during smeStart with status=%d", + status ); + break; + } + + if(!pMac->psOffloadEnabled) + { + status = pmcStart(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "pmcStart failed during smeStart with status=%d", + status ); + break; + } + } + else + { + status = pmcOffloadStart(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "pmcOffloadStart failed during smeStart with status=%d", + status ); + break; + } + } + +#ifndef WLAN_FEATURE_MBSSID + status = WLANSAP_Start(vos_get_global_context(VOS_MODULE_ID_SAP, NULL)); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "WLANSAP_Start failed during smeStart with status=%d", + status ); + break; + } +#endif + + pMac->sme.state = SME_STATE_START; + }while (0); + + return status; +} + + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/****************************************************************************** +* +* Name: sme_PCFilterMatchCountResponseHandler +* +* Description: +* Invoke Packet Coalescing Filter Match Count callback routine +* +* Parameters: +* hHal - HAL handle for device +* pMsg - Pointer to tRcvFltPktMatchRsp structure +* +* Returns: eHalStatus +* +******************************************************************************/ +eHalStatus sme_PCFilterMatchCountResponseHandler(tHalHandle hHal, void* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + tpSirRcvFltPktMatchRsp pRcvFltPktMatchRsp = (tpSirRcvFltPktMatchRsp)pMsg; + + if (NULL == pMsg) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + } + else + { + smsLog(pMac, LOG2, "SME: entering " + "sme_FilterMatchCountResponseHandler"); + + /* Call Packet Coalescing Filter Match Count callback routine. */ + if (pMac->pmc.FilterMatchCountCB != NULL) + pMac->pmc.FilterMatchCountCB(pMac->pmc.FilterMatchCountCBContext, + pRcvFltPktMatchRsp); + + smsLog(pMac, LOG1, "%s: status=0x%x", __func__, + pRcvFltPktMatchRsp->status); + + pMac->pmc.FilterMatchCountCB = NULL; + pMac->pmc.FilterMatchCountCBContext = NULL; + } + + return(status); +} +#endif // WLAN_FEATURE_PACKET_FILTERING + + +#ifdef WLAN_FEATURE_11W +/*------------------------------------------------------------------ + * + * Handle the unprotected management frame indication from LIM and + * forward it to HDD. + * + *------------------------------------------------------------------*/ + +eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, + tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = {0}; + tANI_U32 SessionId = pSmeMgmtFrm->sessionId; + + pRoamInfo.nFrameLength = pSmeMgmtFrm->frameLen; + pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; + pRoamInfo.frameType = pSmeMgmtFrm->frameType; + + /* forward the mgmt frame to HDD */ + csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0); + + return status; +} +#endif + +/*------------------------------------------------------------------ + * + * Handle the DFS Radar Event and indicate it to the SAP + * + *------------------------------------------------------------------*/ +eHalStatus dfsMsgProcessor(tpAniSirGlobal pMac, v_U16_t msgType, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo roamInfo = {0}; + tSirSmeDfsEventInd *dfs_event; + tSirSmeCSAIeTxCompleteRsp *csaIeTxCompleteRsp; + tANI_U32 sessionId = 0; + eRoamCmdStatus roamStatus; + eCsrRoamResult roamResult; + int i; + + switch (msgType) + { + case eWNI_SME_DFS_RADAR_FOUND: + { + /* Radar found !! */ + dfs_event = (tSirSmeDfsEventInd *)pMsgBuf; + if (NULL == dfs_event) + { + smsLog(pMac, LOGE, + "%s: pMsg is NULL for eWNI_SME_DFS_RADAR_FOUND message", + __func__); + return eHAL_STATUS_FAILURE; + } + sessionId = dfs_event->sessionId; + roamInfo.dfs_event.sessionId = sessionId; + roamInfo.dfs_event.chan_list.nchannels = + dfs_event->chan_list.nchannels; + for (i = 0; i < dfs_event->chan_list.nchannels; i++) + { + roamInfo.dfs_event.chan_list.channels[i] = + dfs_event->chan_list.channels[i]; + } + + roamInfo.dfs_event.dfs_radar_status = dfs_event->dfs_radar_status; + roamInfo.dfs_event.use_nol = dfs_event->use_nol; + + roamStatus = eCSR_ROAM_DFS_RADAR_IND; + roamResult = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Radar indication event occurred"); + break; + } + case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: + { + csaIeTxCompleteRsp = (tSirSmeCSAIeTxCompleteRsp *)pMsgBuf; + if (NULL == csaIeTxCompleteRsp) + { + smsLog(pMac, LOGE, + "%s: pMsg is NULL for eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND", + __func__); + return eHAL_STATUS_FAILURE; + } + sessionId = csaIeTxCompleteRsp->sessionId; + roamStatus = eCSR_ROAM_DFS_CHAN_SW_NOTIFY; + roamResult = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Received eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND for session id [%d]", + sessionId ); + break; + } + default: + { + smsLog(pMac, LOG1, "%s: Invalid DFS message = 0x%x", __func__, + msgType); + status = eHAL_STATUS_FAILURE; + return status; + } + } + + /* Indicate Radar Event to SAP */ + csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, + roamStatus, roamResult); + return status; +} + +/** + * sme_extended_change_channel_ind()- function to indicate ECSA + * action frame is received in lim to SAP + * @mac_ctx: pointer to global mac structure + * @msg_buf: contain new channel and session id. + * + * This function is called to post ECSA action frame + * receive event to SAP. + * + * Return: success if msg indicated to SAP else return failure + */ +static eHalStatus sme_extended_change_channel_ind(tpAniSirGlobal mac_ctx, + void *msg_buf) +{ + struct sir_sme_ext_cng_chan_ind *ext_chan_ind; + eHalStatus status = eHAL_STATUS_SUCCESS; + uint32_t session_id = 0; + tCsrRoamInfo roamInfo = {0}; + eRoamCmdStatus roamStatus; + eCsrRoamResult roamResult; + + + ext_chan_ind = msg_buf; + if (NULL == ext_chan_ind) { + smsLog(mac_ctx, LOGE, + FL("pMsg is NULL for eWNI_SME_EXT_CHANGE_CHANNEL_IND")); + return eHAL_STATUS_FAILURE; + } + session_id = ext_chan_ind->session_id; + roamInfo.target_channel = ext_chan_ind->new_channel; + roamStatus = eCSR_ROAM_EXT_CHG_CHNL_IND; + roamResult = eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND; + smsLog(mac_ctx, LOG1, + FL("sapdfs: Received eWNI_SME_EXT_CHANGE_CHANNEL_IND for session id [%d]"), + session_id); + + /* Indicate Ext Channel Change event to SAP */ + csrRoamCallCallback(mac_ctx, session_id, &roamInfo, 0, + roamStatus, roamResult); + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/*------------------------------------------------------------------ + * + * Handle the tsm ie indication from LIM and forward it to HDD. + * + *------------------------------------------------------------------*/ +eHalStatus sme_TsmIeInd(tHalHandle hHal, tSirSmeTsmIEInd *pSmeTsmIeInd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = {0}; + tANI_U32 SessionId = pSmeTsmIeInd->sessionId; + pRoamInfo.tsmIe.tsid= pSmeTsmIeInd->tsmIe.tsid; + pRoamInfo.tsmIe.state= pSmeTsmIeInd->tsmIe.state; + pRoamInfo.tsmIe.msmt_interval= pSmeTsmIeInd->tsmIe.msmt_interval; + /* forward the tsm ie information to HDD */ + csrRoamCallCallback(pMac, + SessionId, + &pRoamInfo, + 0, + eCSR_ROAM_TSM_IE_IND, + 0); + return status; +} +/* --------------------------------------------------------------------------- + \fn sme_SetCCKMIe + \brief function to store the CCKM IE passed from supplicant and use + it while packing reassociation request + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param pCckmIe - pointer to CCKM IE data + \param pCckmIeLen - length of the CCKM IE + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_SetCCKMIe(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 *pCckmIe, tANI_U8 cckmIeLen) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + csrSetCCKMIe(pMac, sessionId, pCckmIe, cckmIeLen); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetEseBeaconRequest + \brief function to set ESE beacon request parameters + \param hHal - HAL handle for device + \param sessionId - Session id + \param pEseBcnReq - pointer to ESE beacon request + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_SetEseBeaconRequest(tHalHandle hHal, const tANI_U8 sessionId, + const tCsrEseBeaconReq* pEseBcnReq) +{ + eHalStatus status = eSIR_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tpSirBeaconReportReqInd pSmeBcnReportReq = NULL; + tCsrEseBeaconReqParams *pBeaconReq = NULL; + tANI_U8 counter = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + if (pSmeRrmContext->eseBcnReqInProgress == TRUE) + { + smsLog(pMac, LOGE, "A Beacon Report Req is already in progress"); + return eHAL_STATUS_RESOURCES; + } + + /* Store the info in RRM context */ + vos_mem_copy(&pSmeRrmContext->eseBcnReqInfo, pEseBcnReq, sizeof(tCsrEseBeaconReq)); + + //Prepare the request to send to SME. + pSmeBcnReportReq = vos_mem_malloc(sizeof( tSirBeaconReportReqInd )); + if(NULL == pSmeBcnReportReq) + { + smsLog(pMac, LOGP, "Memory Allocation Failure!!! ESE BcnReq Ind to SME"); + return eSIR_FAILURE; + } + + pSmeRrmContext->eseBcnReqInProgress = TRUE; + + smsLog(pMac, LOGE, "Sending Beacon Report Req to SME"); + vos_mem_zero( pSmeBcnReportReq, sizeof( tSirBeaconReportReqInd )); + + pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND; + pSmeBcnReportReq->length = sizeof( tSirBeaconReportReqInd ); + vos_mem_copy( pSmeBcnReportReq->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr) ); + pSmeBcnReportReq->channelInfo.channelNum = 255; + pSmeBcnReportReq->channelList.numChannels = pEseBcnReq->numBcnReqIe; + pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_ESE_UPLOAD; + + for (counter = 0; counter < pEseBcnReq->numBcnReqIe; counter++) + { + pBeaconReq = (tCsrEseBeaconReqParams *)&pEseBcnReq->bcnReq[counter]; + pSmeBcnReportReq->fMeasurementtype[counter] = pBeaconReq->scanMode; + pSmeBcnReportReq->measurementDuration[counter] = SYS_TU_TO_MS(pBeaconReq->measurementDuration); + pSmeBcnReportReq->channelList.channelNumber[counter] = pBeaconReq->channel; + } + + status = sme_RrmProcessBeaconReportReqInd(pMac, pSmeBcnReportReq); + + if(status != eHAL_STATUS_SUCCESS) + pSmeRrmContext->eseBcnReqInProgress = FALSE; + + return status; +} + +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/** + * sme_process_fw_mem_dump_rsp - process fw memory dump response from WMA + * + * @pMac - pointer to MAC handle. + * @pMsg - pointer to received SME msg. + * + * This function process the received SME message and calls the corresponding + * callback which was already registered with SME. + */ +#ifdef WLAN_FEATURE_MEMDUMP +static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal pMac, vos_msg_t* pMsg) +{ + if (pMsg->bodyptr) { + if (pMac->sme.fw_dump_callback) + pMac->sme.fw_dump_callback(pMac->hHdd, + (struct fw_dump_rsp*) pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } +} +#else +static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal pMac, vos_msg_t* pMsg) +{ +} +#endif + +/*-------------------------------------------------------------------------- + + \brief sme_ProcessMsg() - The main message processor for SME. + + The function is called by a message dispatcher when to process a message + targeted for SME. + + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param pMsg - A pointer to a caller allocated object of tSirMsgQ. + + \return eHAL_STATUS_SUCCESS - SME successfully process the message. + + Other status means SME failed to process the message to HAL. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (pMsg == NULL) { + smsLog( pMac, LOGE, "Empty message for SME, nothing to process"); + return status; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( SME_IS_START(pMac) ) + { + switch (pMsg->type) { // TODO: Will be modified to do a range check for msgs instead of having cases for each msgs +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case eWNI_SME_HO_FAIL_IND: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "LFR3:%s: Rcvd eWNI_SME_HO_FAIL_IND", __func__); + csrProcessHOFailInd(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_ROAM_OFFLOAD_SYNCH_IND: + csrProcessRoamOffloadSynchInd(pMac, + (tpSirRoamOffloadSynchInd)pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + break; +#endif + case eWNI_PMC_ENTER_BMPS_RSP: + case eWNI_PMC_EXIT_BMPS_RSP: + case eWNI_PMC_EXIT_BMPS_IND: + case eWNI_PMC_ENTER_IMPS_RSP: + case eWNI_PMC_EXIT_IMPS_RSP: + case eWNI_PMC_SMPS_STATE_IND: + case eWNI_PMC_ENTER_UAPSD_RSP: + case eWNI_PMC_EXIT_UAPSD_RSP: + case eWNI_PMC_ENTER_WOWL_RSP: + case eWNI_PMC_EXIT_WOWL_RSP: + //PMC + if (pMsg->bodyptr) + { + if(!pMac->psOffloadEnabled) + { + pmcMessageProcessor(hHal, pMsg->bodyptr); + } + else + { + pmcOffloadMessageProcessor(hHal, pMsg->bodyptr); + } + status = eHAL_STATUS_SUCCESS; + vos_mem_free(pMsg->bodyptr); + } else { + smsLog( pMac, LOGE, "Empty rsp message for PMC, nothing to process"); + } + break; + + case WNI_CFG_SET_CNF: + case WNI_CFG_DNLD_CNF: + case WNI_CFG_GET_RSP: + case WNI_CFG_ADD_GRP_ADDR_CNF: + case WNI_CFG_DEL_GRP_ADDR_CNF: + //CCM + if (pMsg->bodyptr) + { + ccmCfgCnfMsgHandler(hHal, pMsg->bodyptr); + status = eHAL_STATUS_SUCCESS; + vos_mem_free(pMsg->bodyptr); + } else { + smsLog( pMac, LOGE, "Empty rsp message for CCM, nothing to process"); + } + break; + + case eWNI_SME_ADDTS_RSP: + case eWNI_SME_DELTS_RSP: + case eWNI_SME_DELTS_IND: +#ifdef WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_AGGR_QOS_RSP: +#endif + //QoS + if (pMsg->bodyptr) + { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + status = sme_QosMsgProcessor(pMac, pMsg->type, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); +#endif + } else { + smsLog( pMac, LOGE, "Empty rsp message for QoS, nothing to process"); + } + break; +#if defined WLAN_FEATURE_VOWIFI + case eWNI_SME_NEIGHBOR_REPORT_IND: + case eWNI_SME_BEACON_REPORT_REQ_IND: +#if defined WLAN_VOWIFI_DEBUG + smsLog( pMac, LOGE, "Received RRM message. Message Id = %d", pMsg->type ); +#endif + if ( pMsg->bodyptr ) + { + status = sme_RrmMsgProcessor( pMac, pMsg->type, pMsg->bodyptr ); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty message for RRM, nothing to process"); + } + break; +#endif + +#ifdef FEATURE_OEM_DATA_SUPPORT + //Handle the eWNI_SME_OEM_DATA_RSP: + case eWNI_SME_OEM_DATA_RSP: + if(pMsg->bodyptr) + { + status = sme_HandleOemDataRsp(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for oemData_ (eWNI_SME_OEM_DATA_RSP), nothing to process"); + } + smeProcessPendingQueue( pMac ); + break; +#endif + + case eWNI_SME_ADD_STA_SELF_RSP: + if(pMsg->bodyptr) + { + status = csrProcessAddStaSessionRsp(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_ADD_STA_SELF_RSP), nothing to process"); + } + break; + case eWNI_SME_DEL_STA_SELF_RSP: + if(pMsg->bodyptr) + { + status = csrProcessDelStaSessionRsp(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_DEL_STA_SELF_RSP), nothing to process"); + } + break; + case eWNI_SME_REMAIN_ON_CHN_RSP: + if(pMsg->bodyptr) + { + status = sme_remainOnChnRsp(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RSP), nothing to process"); + } + break; + case eWNI_SME_REMAIN_ON_CHN_RDY_IND: + if(pMsg->bodyptr) + { + status = sme_remainOnChnReady(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RDY_IND), nothing to process"); + } + break; + case eWNI_SME_MGMT_FRM_IND: + if(pMsg->bodyptr) + { + sme_mgmtFrmInd(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_MGMT_FRM_IND), nothing to process"); + } + break; + case eWNI_SME_ACTION_FRAME_SEND_CNF: + if(pMsg->bodyptr) + { + status = sme_sendActionCnf(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_ACTION_FRAME_SEND_CNF), nothing to process"); + } + break; + case eWNI_SME_COEX_IND: + if(pMsg->bodyptr) + { + status = btcHandleCoexInd((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_COEX_IND), nothing to process"); + } + break; + +#ifdef FEATURE_WLAN_SCAN_PNO + case eWNI_SME_PREF_NETWORK_FOUND_IND: + if(pMsg->bodyptr) + { + status = sme_PreferredNetworkFoundInd((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_PREF_NETWORK_FOUND_IND), nothing to process"); + } + break; +#endif // FEATURE_WLAN_SCAN_PNO + + case eWNI_SME_TX_PER_HIT_IND: + if (pMac->sme.pTxPerHitCallback) + { + pMac->sme.pTxPerHitCallback(pMac->sme.pTxPerHitCbContext); + } + break; + + case eWNI_SME_CHANGE_COUNTRY_CODE: + if(pMsg->bodyptr) + { + status = sme_HandleChangeCountryCode((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for message (eWNI_SME_CHANGE_COUNTRY_CODE), nothing to process"); + } + break; + + case eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE: + if (pMsg->bodyptr) + { + status = sme_HandleGenericChangeCountryCode((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for message (eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE), nothing to process"); + } + break; + +#ifdef WLAN_FEATURE_PACKET_FILTERING + case eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP: + if(pMsg->bodyptr) + { + status = sme_PCFilterMatchCountResponseHandler((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for meas " + "(PACKET_COALESCING_FILTER_MATCH_COUNT_RSP), nothing to process"); + } + break; +#endif // WLAN_FEATURE_PACKET_FILTERING + case eWNI_SME_PRE_SWITCH_CHL_IND: + if(pMsg->bodyptr) + { + status = sme_HandlePreChannelSwitchInd(pMac,pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for meas " + "(eWNI_SME_PRE_SWITCH_CHL_IND), nothing to process"); + } + break; + case eWNI_SME_POST_SWITCH_CHL_IND: + { + status = sme_HandlePostChannelSwitchInd(pMac); + break; + } + +#ifdef WLAN_WAKEUP_EVENTS + case eWNI_SME_WAKE_REASON_IND: + if(pMsg->bodyptr) + { + status = sme_WakeReasonIndCallback((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_WAKE_REASON_IND), nothing to process"); + } + break; +#endif // WLAN_WAKEUP_EVENTS + +#ifdef FEATURE_WLAN_TDLS + /* + * command received from PE, SME tdls msg processor shall be called + * to process commands received from PE + */ + case eWNI_SME_TDLS_SEND_MGMT_RSP: + case eWNI_SME_TDLS_ADD_STA_RSP: + case eWNI_SME_TDLS_DEL_STA_RSP: + case eWNI_SME_TDLS_DEL_STA_IND: + case eWNI_SME_TDLS_DEL_ALL_PEER_IND: + case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND: + case eWNI_SME_TDLS_LINK_ESTABLISH_RSP: + case eWNI_SME_TDLS_SHOULD_DISCOVER: + case eWNI_SME_TDLS_SHOULD_TEARDOWN: + case eWNI_SME_TDLS_PEER_DISCONNECTED: + { + if (pMsg->bodyptr) + { + status = tdlsMsgProcessor(pMac, pMsg->type, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, + "Empty rsp message for TDLS, nothing to process"); + } + break; + } +#endif + +#ifdef WLAN_FEATURE_11W + case eWNI_SME_UNPROT_MGMT_FRM_IND: + if (pMsg->bodyptr) + { + sme_UnprotectedMgmtFrmInd(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_UNPROT_MGMT_FRM_IND), nothing to process"); + } + break; +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_TSM_IE_IND: + { + if (pMsg->bodyptr) + { + sme_TsmIeInd(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, + "Empty rsp message for (eWNI_SME_TSM_IE_IND), nothing to process"); + } + break; + } +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eWNI_SME_ROAM_SCAN_OFFLOAD_RSP: + status = csrRoamOffloadScanRspHdlr((void *)pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + break; +#endif // WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +#ifdef WLAN_FEATURE_GTK_OFFLOAD + case eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP: + if (pMsg->bodyptr) + { + sme_ProcessGetGtkInfoRsp(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for (eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP), nothing to process"); + } + break ; +#endif + +#ifdef FEATURE_WLAN_LPHB + /* LPHB timeout indication arrived, send IND to client */ + case eWNI_SME_LPHB_IND: + if (pMac->sme.pLphbIndCb) + { + pMac->sme.pLphbIndCb(pMac->hHdd, pMsg->bodyptr); + } + vos_mem_free(pMsg->bodyptr); + + break; +#endif /* FEATURE_WLAN_LPHB */ + + case eWNI_SME_READY_TO_SUSPEND_IND: + if (pMsg->bodyptr) + { + sme_ProcessReadyToSuspend(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message for (eWNI_SME_READY_TO_SUSPEND_IND), nothing to process"); + } + break ; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + case eWNI_SME_READY_TO_EXTWOW_IND: + if (pMsg->bodyptr) + { + sme_ProcessReadyToExtWoW(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, "Empty rsp message" + "for (eWNI_SME_READY_TO_EXTWOW_IND), nothing to process"); + } + break ; +#endif + +#ifdef FEATURE_WLAN_CH_AVOID + /* channel avoid message arrived, send IND to client */ + case eWNI_SME_CH_AVOID_IND: + if (pMac->sme.pChAvoidNotificationCb) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: CH avoid notification", __func__); + pMac->sme.pChAvoidNotificationCb(pMac->hHdd, pMsg->bodyptr); + } + vos_mem_free(pMsg->bodyptr); + break; +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + case eWNI_SME_AUTO_SHUTDOWN_IND: + if (pMac->sme.pAutoShutdownNotificationCb) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Auto shutdown notification", __func__); + pMac->sme.pAutoShutdownNotificationCb(); + } + vos_mem_free(pMsg->bodyptr); + break; +#endif + case eWNI_SME_DFS_RADAR_FOUND: + case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: + { + status = dfsMsgProcessor(pMac, pMsg->type, pMsg->bodyptr); + vos_mem_free( pMsg->bodyptr ); + } + break; + case eWNI_SME_EXT_CHANGE_CHANNEL_IND: + status = sme_extended_change_channel_ind(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_CHANNEL_CHANGE_RSP: + if (pMsg->bodyptr) + { + status = sme_ProcessChannelChangeResp(pMac, + pMsg->type, pMsg->bodyptr); + vos_mem_free( pMsg->bodyptr ); + } + else + { + smsLog( pMac, LOGE, + "Empty rsp message for (eWNI_SME_CHANNEL_CHANGE_RSP)," + "nothing to process"); + } + break ; + +#ifdef WLAN_FEATURE_STATS_EXT + case eWNI_SME_STATS_EXT_EVENT: + if (pMsg->bodyptr) + { + status = sme_StatsExtEvent(hHal, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, + "Empty event message for eWNI_SME_STATS_EXT_EVENT, nothing to process"); + } + break; +#endif + case eWNI_SME_LINK_SPEED_IND: + if (pMac->sme.pLinkSpeedIndCb) + { + pMac->sme.pLinkSpeedIndCb(pMsg->bodyptr, + pMac->sme.pLinkSpeedCbContext); + } + if (pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + } + break; + case eWNI_SME_GET_RSSI_IND: + if (pMac->sme.pget_rssi_ind_cb) + pMac->sme.pget_rssi_ind_cb(pMsg->bodyptr, + pMac->sme.pget_rssi_cb_context); + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_CSA_OFFLOAD_EVENT: + if (pMsg->bodyptr) + { + csrScanFlushBssEntry(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + break; + case eWNI_SME_TSF_EVENT: + if (pMac->sme.get_tsf_cb) { + pMac->sme.get_tsf_cb(pMac->sme.get_tsf_cxt, + (struct stsf *)pMsg->bodyptr); + } + if (pMsg->bodyptr) { + vos_mem_free(pMsg->bodyptr); + pMsg->bodyptr = NULL; + } + break; +#ifdef WLAN_FEATURE_NAN + case eWNI_SME_NAN_EVENT: + if (pMsg->bodyptr) + { + sme_NanEvent(hHal, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + break; +#endif /* WLAN_FEATURE_NAN */ + case eWNI_SME_LINK_STATUS_IND: + { + tAniGetLinkStatus *pLinkStatus = + (tAniGetLinkStatus *) pMsg->bodyptr; + if (pLinkStatus) { + if (pMac->sme.linkStatusCallback) { + pMac->sme.linkStatusCallback(pLinkStatus->linkStatus, + pMac->sme.linkStatusContext); + } + + pMac->sme.linkStatusCallback = NULL; + pMac->sme.linkStatusContext = NULL; + vos_mem_free(pLinkStatus); + } + break; + } + case eWNI_SME_MSG_GET_TEMPERATURE_IND: + if (pMac->sme.pGetTemperatureCb) + { + pMac->sme.pGetTemperatureCb(pMsg->bodyval, + pMac->sme.pTemperatureCbContext); + } + break; + case eWNI_SME_SNR_IND: + { + tAniGetSnrReq *pSnrReq = (tAniGetSnrReq *) pMsg->bodyptr; + if (pSnrReq) { + if (pSnrReq->snrCallback) { + ((tCsrSnrCallback)(pSnrReq->snrCallback))(pSnrReq->snr, + pSnrReq->staId, + pSnrReq->pDevContext); + } + + vos_mem_free(pSnrReq); + } + break; + } +#ifdef FEATURE_WLAN_EXTSCAN + case eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND: + { + if (pMac->sme.pExtScanIndCb) { + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_FULL_SCAN_RESULT_IND, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, + FL("callback not registered to process eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND")); + } + vos_mem_free(pMsg->bodyptr); + break; + } + case eWNI_SME_EPNO_NETWORK_FOUND_IND: + { + if (pMac->sme.pExtScanIndCb) { + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EPNO_NETWORK_FOUND_IND, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, + FL("callback not registered to process eWNI_SME_EPNO_NETWORK_FOUND_IND")); + } + vos_mem_free(pMsg->bodyptr); + break; + } +#endif + case eWNI_SME_FW_STATUS_IND: + if (pMac->sme.fw_state_callback) + pMac->sme.fw_state_callback(pMac->sme.fw_state_context); + + pMac->sme.fw_state_callback = NULL; + pMac->sme.fw_state_context = NULL; + break; + case eWNI_SME_OCB_SET_CONFIG_RSP: + if (pMac->sme.ocb_set_config_callback) { + pMac->sme.ocb_set_config_callback( + pMac->sme.ocb_set_config_context, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, FL( + "Error processing message. The callback is NULL.")); + } + pMac->sme.ocb_set_config_callback = NULL; + pMac->sme.ocb_set_config_context = NULL; + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_OCB_GET_TSF_TIMER_RSP: + if (pMac->sme.ocb_get_tsf_timer_callback) { + pMac->sme.ocb_get_tsf_timer_callback( + pMac->sme.ocb_get_tsf_timer_context, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, FL( + "Error processing message. The callback is NULL.")); + } + pMac->sme.ocb_get_tsf_timer_callback = NULL; + pMac->sme.ocb_get_tsf_timer_context = NULL; + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_DCC_GET_STATS_RSP: + if (pMac->sme.dcc_get_stats_callback) { + pMac->sme.dcc_get_stats_callback( + pMac->sme.dcc_get_stats_context, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, FL( + "Error processing message. The callback or context is NULL.")); + } + pMac->sme.dcc_get_stats_callback = NULL; + pMac->sme.dcc_get_stats_context = NULL; + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_DCC_UPDATE_NDL_RSP: + if (pMac->sme.dcc_update_ndl_callback) { + pMac->sme.dcc_update_ndl_callback( + pMac->sme.dcc_update_ndl_context, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, FL( + "Error processing message. The callback or context is NULL.")); + } + pMac->sme.dcc_update_ndl_callback = NULL; + pMac->sme.dcc_update_ndl_context = NULL; + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_DCC_STATS_EVENT: + if (pMac->sme.dcc_stats_event_callback) { + pMac->sme.dcc_stats_event_callback( + pMac->sme.dcc_stats_event_context, + pMsg->bodyptr); + } else { + smsLog(pMac, LOGE, FL( + "Error processing message. The callback or context is NULL.")); + } + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_FW_DUMP_IND: + sme_process_fw_mem_dump_rsp(pMac, pMsg); + break; + case eWNI_SME_SET_THERMAL_LEVEL_IND: + if (pMac->sme.set_thermal_level_cb) + { + pMac->sme.set_thermal_level_cb(pMac->hHdd, pMsg->bodyval); + } + break; + case eWNI_SME_LOST_LINK_INFO_IND: + if (pMac->sme.lost_link_info_cb) { + pMac->sme.lost_link_info_cb(pMac->hHdd, + (struct sir_lost_link_info *)pMsg->bodyptr); + } + vos_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_SMPS_FORCE_MODE_IND: + if (pMac->sme.smps_force_mode_cb) + pMac->sme.smps_force_mode_cb(pMac->hHdd, + (struct sir_smps_force_mode_event *) + pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + break; + default: + + if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN ) + && ( pMsg->type <= eWNI_SME_MSG_TYPES_END ) ) + { + //CSR + if (pMsg->bodyptr) + { + status = csrMsgProcessor(hHal, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog( pMac, LOGE, "Empty rsp message for CSR, nothing to process"); + } + } + else + { + smsLog( pMac, LOGW, "Unknown message type %d, nothing to process", + pMsg->type); + if (pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + } + } + }//switch + } //SME_IS_START + else + { + smsLog( pMac, LOGW, "message type %d in stop state ignored", pMsg->type); + if (pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + } + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + else + { + smsLog( pMac, LOGW, "Locking failed, bailing out"); + if (pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + } + } + + return status; +} + + +//No need to hold the global lock here because this function can only be called +//after sme_Stop. +v_VOID_t sme_FreeMsg( tHalHandle hHal, vos_msg_t* pMsg ) +{ + if( pMsg ) + { + if (pMsg->bodyptr) + { + vos_mem_free(pMsg->bodyptr); + } + } + +} + + +/*-------------------------------------------------------------------------- + + \brief sme_Stop() - Stop all SME modules and put them at idle state + + The function stops each module in SME, PMC, CCM, CSR, etc. . Upon + return, all modules are at idle state ready to start. + + This is a synchronous call + \param hHal - The handle returned by macOpen + \param tHalStopType - reason for stopping + + \return eHAL_STATUS_SUCCESS - SME is stopped. + + Other status means SME is failed to stop but caller should still + consider SME is stopped. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Stop(tHalHandle hHal, tHalStopType stopType) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + eHalStatus fail_status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + +#ifndef WLAN_FEATURE_MBSSID + status = WLANSAP_Stop(vos_get_global_context(VOS_MODULE_ID_SAP, NULL)); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "WLANSAP_Stop failed during smeStop with status=%d", + status ); + fail_status = status; + } +#endif + + p2pStop(hHal); + + if(!pMac->psOffloadEnabled) + { + status = pmcStop(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "pmcStop failed during smeStop with status=%d", + status ); + fail_status = status; + } + } + else + { + status = pmcOffloadStop(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, + "pmcOffloadStop failed during smeStop with status=%d", + status ); + fail_status = status; + } + } + + status = csrStop(pMac, stopType); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrStop failed during smeStop with status=%d", + status ); + fail_status = status; + } + + ccmStop(hHal); + + purgeSmeCmdList(pMac); + + if (!HAL_STATUS_SUCCESS( fail_status )) { + status = fail_status; + } + + pMac->sme.state = SME_STATE_STOP; + + return status; +} + +/*-------------------------------------------------------------------------- + + \brief sme_Close() - Release all SME modules and their resources. + + The function release each module in SME, PMC, CCM, CSR, etc. . Upon + return, all modules are at closed state. + + No SME APIs can be involved after smeClose except smeOpen. + smeClose must be called before macClose. + This is a synchronous call + \param hHal - The handle returned by macOpen + + \return eHAL_STATUS_SUCCESS - SME is successfully close. + + Other status means SME is failed to be closed but caller still cannot + call any other SME functions except smeOpen. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_Close(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + eHalStatus fail_status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (!pMac) + return eHAL_STATUS_FAILURE; + + /* Note: pSession will be invalid from here on, do not access */ + status = csrClose(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "csrClose failed during sme close with status=%d", + status ); + fail_status = status; + } + +#ifndef WLAN_FEATURE_MBSSID + status = WLANSAP_Close(vos_get_global_context(VOS_MODULE_ID_SAP, NULL)); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "WLANSAP_close failed during sme close with status=%d", + status ); + fail_status = status; + } +#endif + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + status = btcClose(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "BTC close failed during sme close with status=%d", + status ); + fail_status = status; + } + + status = sme_QosClose(pMac); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "Qos close failed during sme close with status=%d", + status ); + fail_status = status; + } +#endif +#ifdef FEATURE_OEM_DATA_SUPPORT + status = oemData_OemDataReqClose(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "OEM DATA REQ close failed during sme close with status=%d", + status ); + fail_status = status; + } +#endif + + status = ccmClose(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "ccmClose failed during sme close with status=%d", + status ); + fail_status = status; + } + + if(!pMac->psOffloadEnabled) + { + status = pmcClose(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog(pMac, LOGE, "pmcClose failed during sme close with status=%d", + status); + fail_status = status; + } + } + else + { + status = pmcOffloadClose(hHal); + if(!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, LOGE, "pmcOffloadClose failed during smeClose status=%d", + status); + fail_status = status; + } + } +#if defined WLAN_FEATURE_VOWIFI + status = rrmClose(hHal); + if ( ! HAL_STATUS_SUCCESS( status ) ) { + smsLog( pMac, LOGE, "RRM close failed during sme close with status=%d", + status ); + fail_status = status; + } +#endif + + sme_p2pClose(hHal); + + freeSmeCmdList(pMac); + + if( !VOS_IS_STATUS_SUCCESS( vos_lock_destroy( &pMac->sme.lkSmeGlobalLock ) ) ) + { + fail_status = eHAL_STATUS_FAILURE; + } + + if (!HAL_STATUS_SUCCESS( fail_status )) { + status = fail_status; + } + + pMac->sme.state = SME_STATE_STOP; + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ScanRequest + \brief a wrapper function to Request a 11d or full scan from CSR. + This is an asynchronous call + \param pScanRequestID - pointer to an object to get back the request ID + \param callback - a callback function that scan calls upon finish, will not + be called if csrScanRequest returns error + \param pContext - a pointer passed in for the callback + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanRequest(tHalHandle hHal, tANI_U8 sessionId, tCsrScanRequest *pscanReq, + tANI_U32 *pScanRequestID, + csrScanCompleteCallback callback, void *pContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_REQ, sessionId, pscanReq->scanType)); + smsLog(pMac, LOG2, FL("enter")); + do + { + if(pMac->scan.fScanEnable) + { + status = sme_AcquireGlobalLock( &pMac->sme ); + if (HAL_STATUS_SUCCESS(status )) { + status = csrScanRequest(hHal, sessionId, pscanReq, + pScanRequestID, callback, pContext); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, LOGE, + FL("csrScanRequest failed sessionId(%d)"), sessionId); + } + sme_ReleaseGlobalLock( &pMac->sme ); + } else { + smsLog(pMac, LOGE, FL("sme_AcquireGlobalLock failed")); + } + } //if(pMac->scan.fScanEnable) + else + { + smsLog(pMac, LOGE, FL("fScanEnable FALSE")); + } + } while( 0 ); + + return (status); + + +} + +/* --------------------------------------------------------------------------- + \fn sme_ScanGetResult + \brief a wrapper function to request scan results from CSR. + This is a synchronous call + \param pFilter - If pFilter is NULL, all cached results are returned + \param phResult - an object for the result. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanGetResult(tHalHandle hHal, tANI_U8 sessionId, tCsrScanResultFilter *pFilter, + tScanResultHandle *phResult) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_GET_RESULTS, sessionId,0 )); + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanGetResult( hHal, pFilter, phResult ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + smsLog(pMac, LOG2, FL("exit status %d"), status); + + return (status); +} + +/** + * sme_get_ap_channel_from_scan_cache() - a wrapper function to get AP's + * channel id from CSR by filtering the + * result which matches our roam profile. + * @profile: SAP adapter + * @ap_chnl_id: pointer to channel id of SAP. Fill the value after finding the + * best ap from scan cache. + * + * This function is written to get AP's channel id from CSR by filtering + * the result which matches our roam profile. This is a synchronous call. + * + * Return: VOS_STATUS. + */ +VOS_STATUS sme_get_ap_channel_from_scan_cache(tHalHandle hHal, + tCsrRoamProfile *profile, + tScanResultHandle *scan_cache, + tANI_U8 *ap_chnl_id) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrScanResultFilter *scan_filter = NULL; + tScanResultHandle filtered_scan_result = NULL; + tSirBssDescription first_ap_profile; + VOS_STATUS ret_status = VOS_STATUS_SUCCESS; + + if (NULL == pMac) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("pMac is NULL")); + return VOS_STATUS_E_FAILURE; + } + scan_filter = vos_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == scan_filter) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("scan_filter mem alloc failed")); + return VOS_STATUS_E_FAILURE; + } else { + vos_mem_set(scan_filter, sizeof(tCsrScanResultFilter), 0); + vos_mem_set(&first_ap_profile, sizeof(tSirBssDescription), 0); + + if (NULL == profile) { + scan_filter->EncryptionType.numEntries = 1; + scan_filter->EncryptionType.encryptionType[0] + = eCSR_ENCRYPT_TYPE_NONE; + } else { + /* Here is the profile we need to connect to */ + status = csrRoamPrepareFilterFromProfile(pMac, profile, scan_filter); + } + + if (HAL_STATUS_SUCCESS(status)) { + /* Save the WPS info */ + if(NULL != profile) { + scan_filter->bWPSAssociation = profile->bWPSAssociation; + scan_filter->bOSENAssociation = profile->bOSENAssociation; + } else { + scan_filter->bWPSAssociation = 0; + scan_filter->bOSENAssociation = 0; + } + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Preparing the profile filter failed")); + vos_mem_free(scan_filter); + return VOS_STATUS_E_FAILURE; + } + } + status = sme_AcquireGlobalLock( &pMac->sme ); + if (eHAL_STATUS_SUCCESS == status) { + status = csrScanGetResult(hHal, scan_filter, &filtered_scan_result); + if (eHAL_STATUS_SUCCESS == status) { + csr_get_bssdescr_from_scan_handle(filtered_scan_result, + &first_ap_profile); + *scan_cache = filtered_scan_result; + if (0 != first_ap_profile.channelId) { + *ap_chnl_id = first_ap_profile.channelId; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Found best AP and it is on channel[%d]"), + first_ap_profile.channelId); + } else { + /* + * This means scan result is empty + * so set the channel to zero, caller should + * take of zero channel id case. + */ + *ap_chnl_id = 0; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Scan result is empty, setting channel to 0")); + ret_status = VOS_STATUS_E_FAILURE; + } + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Failed to get scan get result")); + ret_status = VOS_STATUS_E_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Aquiring lock failed")); + ret_status = VOS_STATUS_E_FAILURE; + } + + vos_mem_free(scan_filter); + + return ret_status; +} + +/** + * sme_store_joinreq_param() - This function will pass station's join + * request to store to csr. + * @hal_handle: pointer to hal context. + * @profile: pointer to station's roam profile. + * @scan_cache: pointer to station's scan cache. + * @roam_id: reference to roam_id variable being passed. + * @session_id: station's session id. + * + * This function will pass station's join request further down to csr + * to store it. this stored parameter will be used later. + * + * Return: true or false based on function's overall success. + */ +bool sme_store_joinreq_param(tHalHandle hal_handle, + tCsrRoamProfile *profile, + tScanResultHandle scan_cache, + uint32_t *roam_id, + uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + eHalStatus status = eHAL_STATUS_FAILURE; + bool ret_status = true; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_STORE_JOIN_REQ, + session_id, 0)); + status = sme_AcquireGlobalLock( &mac_ctx->sme ); + if (HAL_STATUS_SUCCESS(status)) { + if (false == csr_store_joinreq_param(mac_ctx, profile, scan_cache, + roam_id, session_id)) { + ret_status = false; + } + sme_ReleaseGlobalLock(&mac_ctx->sme); + } else { + ret_status = false; + } + + return ret_status; +} + +/** + * sme_clear_joinreq_param() - This function will pass station's clear + * the join request to csr. + * @hal_handle: pointer to hal context. + * @session_id: station's session id. + * + * This function will pass station's clear join request further down to csr + * to cleanup. + * + * Return: true or false based on function's overall success. + */ +bool sme_clear_joinreq_param(tHalHandle hal_handle, + uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + eHalStatus status = eHAL_STATUS_FAILURE; + bool ret_status = true; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CLEAR_JOIN_REQ, + session_id, 0)); + status = sme_AcquireGlobalLock( &mac_ctx->sme ); + if (HAL_STATUS_SUCCESS(status)) { + if (false == csr_clear_joinreq_param(mac_ctx, + session_id)) { + ret_status = false; + } + sme_ReleaseGlobalLock(&mac_ctx->sme); + } else { + ret_status = false; + } + + return ret_status; +} + +/** + * sme_issue_stored_joinreq() - This function will issues station's stored + * the join request to csr. + * @hal_handle: pointer to hal context. + * @roam_id: reference to roam_id variable being passed. + * @session_id: station's session id. + * + * This function will issue station's stored join request further down to csr + * to proceed forward. + * + * Return: VOS_STATUS_SUCCESS or VOS_STATUS_E_FAILURE. + */ +VOS_STATUS sme_issue_stored_joinreq(tHalHandle hal_handle, + uint32_t *roam_id, + uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_STATUS ret_status = VOS_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ISSUE_JOIN_REQ, + session_id, 0)); + status = sme_AcquireGlobalLock( &mac_ctx->sme ); + if (HAL_STATUS_SUCCESS(status)) { + if (!HAL_STATUS_SUCCESS(csr_issue_stored_joinreq(mac_ctx, + roam_id, + session_id))) { + ret_status = VOS_STATUS_E_FAILURE; + } + sme_ReleaseGlobalLock(&mac_ctx->sme); + } else { + csr_clear_joinreq_param(mac_ctx, session_id); + ret_status = VOS_STATUS_E_FAILURE; + } + return ret_status; +} +/* --------------------------------------------------------------------------- + \fn sme_ScanFlushResult + \brief a wrapper function to request CSR to clear scan results. + This is a synchronous call + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanFlushResult(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, sessionId,0 )); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanFlushResult(hHal, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_FilterScanResults + \brief a wrapper function to request CSR to clear scan results. + This is a synchronous call + \param tHalHandle - HAL context handle + \param sessionId - session id + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_FilterScanResults(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, sessionId,0 )); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + csrScanFilterResults(pMac); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +eHalStatus sme_ScanFlushP2PResult(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_P2PRESULTS, sessionId,0 )); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanFlushSelectiveResult( hHal, VOS_TRUE ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_ScanResultGetFirst + \brief a wrapper function to request CSR to returns the first element of + scan result. + This is a synchronous call + \param hScanResult - returned from csrScanGetResult + \return tCsrScanResultInfo * - NULL if no result + ---------------------------------------------------------------------------*/ +tCsrScanResultInfo *sme_ScanResultGetFirst(tHalHandle hHal, + tScanResultHandle hScanResult) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrScanResultInfo *pRet = NULL; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETFIRST, NO_SESSION,0 )); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pRet = csrScanResultGetFirst( pMac, hScanResult ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (pRet); +} + + +/* --------------------------------------------------------------------------- + \fn sme_ScanResultGetNext + \brief a wrapper function to request CSR to returns the next element of + scan result. It can be called without calling csrScanResultGetFirst + first + This is a synchronous call + \param hScanResult - returned from csrScanGetResult + \return Null if no result or reach the end + ---------------------------------------------------------------------------*/ +tCsrScanResultInfo *sme_ScanResultGetNext(tHalHandle hHal, + tScanResultHandle hScanResult) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrScanResultInfo *pRet = NULL; + + MTRACE(vos_trace(VOS_MODULE_ID_SME , + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETNEXT, NO_SESSION,0 )); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pRet = csrScanResultGetNext( pMac, hScanResult ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (pRet); +} + + +/* --------------------------------------------------------------------------- + \fn sme_ScanSetBGScanparams + \brief a wrapper function to request CSR to set BG scan params in PE + This is a synchronous call + \param pScanReq - BG scan request structure + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanSetBGScanparams(tHalHandle hHal, tANI_U8 sessionId, tCsrBGScanRequest *pScanReq) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if( NULL != pScanReq ) + { + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanSetBGScanparams( hHal, pScanReq ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_ScanResultPurge + \brief a wrapper function to request CSR to remove all items(tCsrScanResult) + in the list and free memory for each item + This is a synchronous call + \param hScanResult - returned from csrScanGetResult. hScanResult is + considered gone by + calling this function and even before this function returns. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanResultPurge(tHalHandle hHal, tScanResultHandle hScanResult) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_PURGE, NO_SESSION,0 )); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanResultPurge( hHal, hScanResult ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_ScanGetPMKIDCandidateList + \brief a wrapper function to return the PMKID candidate list + This is a synchronous call + \param pPmkidList - caller allocated buffer point to an array of + tPmkidCandidateInfo + \param pNumItems - pointer to a variable that has the number of + tPmkidCandidateInfo allocated when returning, this is + either the number needed or number of items put into + pPmkidList + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough and pNumItems + has the number of tPmkidCandidateInfo. + \Note: pNumItems is a number of tPmkidCandidateInfo, + not sizeof(tPmkidCandidateInfo) * something + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanGetPMKIDCandidateList(tHalHandle hHal, tANI_U8 sessionId, + tPmkidCandidateInfo *pPmkidList, + tANI_U32 *pNumItems ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanGetPMKIDCandidateList( pMac, sessionId, pPmkidList, pNumItems ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/*---------------------------------------------------------------------------- + \fn sme_RoamRegisterLinkQualityIndCallback + + \brief + a wrapper function to allow HDD to register a callback handler with CSR for + link quality indications. + + Only one callback may be registered at any time. + In order to deregister the callback, a NULL cback may be provided. + + Registration happens in the task context of the caller. + + \param callback - Call back being registered + \param pContext - user data + + DEPENDENCIES: After CSR open + + \return eHalStatus +-----------------------------------------------------------------------------*/ +eHalStatus sme_RoamRegisterLinkQualityIndCallback(tHalHandle hHal, tANI_U8 sessionId, + csrRoamLinkQualityIndCallback callback, + void *pContext) +{ + return(csrRoamRegisterLinkQualityIndCallback((tpAniSirGlobal)hHal, callback, pContext)); +} + +eCsrPhyMode sme_GetPhyMode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.phyMode; +} + +/* --------------------------------------------------------------------------- + \fn sme_GetChannelBondingMode5G + \brief get the channel bonding mode for 5G band + \param hHal - HAL handle + \return channel bonding mode for 5G + ---------------------------------------------------------------------------*/ +tANI_U32 sme_GetChannelBondingMode5G(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeConfigParams smeConfig; + + sme_GetConfigParam(pMac, &smeConfig); + + return smeConfig.csrConfig.channelBondingMode5GHz; +} + +/* --------------------------------------------------------------------------- + \fn sme_GetChannelBondingMode24G + \brief get the channel bonding mode for 2.4G band + \param hHal - HAL handle + \return channel bonding mode for 2.4G + ---------------------------------------------------------------------------*/ +tANI_U32 sme_GetChannelBondingMode24G(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeConfigParams smeConfig; + + sme_GetConfigParam(pMac, &smeConfig); + + return smeConfig.csrConfig.channelBondingMode24GHz; +} + + +/* --------------------------------------------------------------------------- + \fn sme_RoamConnect + \brief a wrapper function to request CSR to initiate an association + This is an asynchronous call. + \param sessionId - the sessionId returned by sme_OpenSession. + \param pProfile - description of the network to which to connect + \param hBssListIn - a list of BSS descriptor to roam to. It is returned + from csrScanGetResult + \param pRoamId - to get back the request ID + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamConnect(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile, + tANI_U32 *pRoamId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (!pMac) + { + return eHAL_STATUS_FAILURE; + } + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_CONNECT, sessionId, 0)); + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamConnect( pMac, sessionId, pProfile, NULL, pRoamId ); + } + else + { + smsLog(pMac, LOGE, FL("invalid sessionID %d"), sessionId); + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + else + { + smsLog(pMac, LOGE, FL("sme_AcquireGlobalLock failed")); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_SetPhyMode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by macOpen. + + \param phyMode new phyMode which is to set + + \return eHalStatus SUCCESS. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetPhyMode(tHalHandle hHal, eCsrPhyMode phyMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return eHAL_STATUS_FAILURE; + } + + pMac->roam.configParam.phyMode = phyMode; + pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(NULL, + pMac->roam.configParam.phyMode, + pMac->roam.configParam.ProprietaryRatesEnabled); + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamReassoc + \brief a wrapper function to request CSR to initiate a re-association + \param pProfile - can be NULL to join the currently connected AP. In that + case modProfileFields should carry the modified field(s) which could trigger + reassoc + \param modProfileFields - fields which are part of tCsrRoamConnectedProfile + that might need modification dynamically once STA is up & running and this + could trigger a reassoc + \param pRoamId - to get back the request ID + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamReassoc(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + tANI_U32 *pRoamId, v_BOOL_t fForce) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_REASSOC, sessionId, 0)); + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + if((NULL == pProfile) && (fForce == 1)) + { + status = csrReassoc( pMac, sessionId, &modProfileFields, pRoamId , fForce); + } + else + { + status = csrRoamReassoc( pMac, sessionId, pProfile, modProfileFields, pRoamId ); + } + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamConnectToLastProfile + \brief a wrapper function to request CSR to disconnect and reconnect with + the same profile + This is an asynchronous call. + \return eHalStatus. It returns fail if currently connected + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamConnectToLastProfile(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamConnectToLastProfile( pMac, sessionId ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamDisconnect + \brief a wrapper function to request CSR to disconnect from a network + This is an asynchronous call. + \param reason -- To indicate the reason for disconnecting. Currently, only + eCSR_DISCONNECT_REASON_MIC_ERROR is meaningful. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamDisconnect(tHalHandle hHal, tANI_U8 sessionId, eCsrRoamDisconnectReason reason) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_DISCONNECT, sessionId, reason)); + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamDisconnect( pMac, sessionId, reason ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamStopBss + \brief To stop BSS for Soft AP. This is an asynchronous API. + \param hHal - Global structure + \param sessionId - sessionId of SoftAP + \return eHalStatus SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamStopBss(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamIssueStopBssCmd( pMac, sessionId, eANI_BOOLEAN_TRUE ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamDisconnectSta + \brief To disassociate a station. This is an asynchronous API. + \param hHal - Global structure + \param sessionId - sessionId of SoftAP + \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes) + \return eHalStatus SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamDisconnectSta(tHalHandle hHal, tANI_U8 sessionId, + struct tagCsrDelStaParams *pDelStaParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if ( NULL == pMac ) + { + VOS_ASSERT(0); + return status; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamIssueDisassociateStaCmd( pMac, sessionId, pDelStaParams); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamDeauthSta + \brief To disassociate a station. This is an asynchronous API. + \param hHal - Global structure + \param sessionId - sessionId of SoftAP + \param pDelStaParams -Pointer to parameters of the station to deauthenticate + \return eHalStatus SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamDeauthSta(tHalHandle hHal, tANI_U8 sessionId, + struct tagCsrDelStaParams *pDelStaParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if ( NULL == pMac ) + { + VOS_ASSERT(0); + return status; + } + + MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_MSG_DEAUTH_STA, + sessionId, pDelStaParams->reason_code)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamIssueDeauthStaCmd( pMac, sessionId, pDelStaParams); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamTKIPCounterMeasures + \brief To start or stop TKIP counter measures. This is an asynchronous API. + \param sessionId - sessionId of SoftAP + \param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes) + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamTKIPCounterMeasures(tHalHandle hHal, tANI_U8 sessionId, + tANI_BOOLEAN bEnable) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if ( NULL == pMac ) + { + VOS_ASSERT(0); + return status; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamIssueTkipCounterMeasures( pMac, sessionId, bEnable); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetAssociatedStas + \brief To probe the list of associated stations from various modules of CORE stack. + \This is an asynchronous API. + \param sessionId - sessionId of SoftAP + \param modId - Module from whom list of associated stations is to be probed. + If an invalid module is passed then by default VOS_MODULE_ID_PE will be probed + \param pUsrContext - Opaque HDD context + \param pfnSapEventCallback - Sap event callback in HDD + \param pAssocBuf - Caller allocated memory to be filled with + associated stations info + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetAssociatedStas(tHalHandle hHal, tANI_U8 sessionId, + VOS_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, tANI_U8 *pAssocStasBuf) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if ( NULL == pMac ) + { + VOS_ASSERT(0); + return status; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetAssociatedStas( pMac, sessionId, modId, pUsrContext, pfnSapEventCallback, pAssocStasBuf ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetWpsSessionOverlap + \brief To get the WPS PBC session overlap information. + \This is an asynchronous API. + \param sessionId - sessionId of SoftAP + \param pUsrContext - Opaque HDD context + \param pfnSapEventCallback - Sap event callback in HDD + \pRemoveMac - pointer to Mac address which needs to be removed from session + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetWpsSessionOverlap(tHalHandle hHal, tANI_U8 sessionId, + void *pUsrContext, void + *pfnSapEventCallback, v_MACADDR_t pRemoveMac) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if ( NULL == pMac ) + { + VOS_ASSERT(0); + return status; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetWpsSessionOverlap( pMac, sessionId, pUsrContext, pfnSapEventCallback, pRemoveMac); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetConnectState + \brief a wrapper function to request CSR to return the current connect state + of Roaming + This is a synchronous call. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetConnectState(tHalHandle hHal, tANI_U8 sessionId, eCsrConnectState *pState) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetConnectState( pMac, sessionId, pState ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetConnectProfile + \brief a wrapper function to request CSR to return the current connect + profile. Caller must call csrRoamFreeConnectProfile after it is done + and before reuse for another csrRoamGetConnectProfile call. + This is a synchronous call. + \param pProfile - pointer to a caller allocated structure + tCsrRoamConnectedProfile + \return eHalStatus. Failure if not connected + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetConnectProfile(tHalHandle hHal, tANI_U8 sessionId, + tCsrRoamConnectedProfile *pProfile) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetConnectProfile( pMac, sessionId, pProfile ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamFreeConnectProfile + \brief a wrapper function to request CSR to free and reinitialize the + profile returned previously by csrRoamGetConnectProfile. + This is a synchronous call. + \param pProfile - pointer to a caller allocated structure + tCsrRoamConnectedProfile + \return eHalStatus. + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamFreeConnectProfile(tHalHandle hHal, + tCsrRoamConnectedProfile *pProfile) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamFreeConnectProfile( pMac, pProfile ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamSetPMKIDCache + \brief a wrapper function to request CSR to return the PMKID candidate list + This is a synchronous call. + \param pPMKIDCache - caller allocated buffer point to an array of + tPmkidCacheInfo + \param numItems - a variable that has the number of tPmkidCacheInfo + allocated when returning, this is either the number needed + or number of items put into pPMKIDCache + \param update_entire_cache - this bool value specifies if the entire pmkid + cache should be overwritten or should it be + updated entry by entry. + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough and pNumItems has the number of + tPmkidCacheInfo. + \Note: pNumItems is a number of tPmkidCacheInfo, + not sizeof(tPmkidCacheInfo) * something + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamSetPMKIDCache( tHalHandle hHal, tANI_U8 sessionId, + tPmkidCacheInfo *pPMKIDCache, + tANI_U32 numItems, + tANI_BOOLEAN update_entire_cache ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_SET_PMKIDCACHE, sessionId, numItems)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamSetPMKIDCache( pMac, sessionId, pPMKIDCache, + numItems, update_entire_cache); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +eHalStatus sme_RoamDelPMKIDfromCache( tHalHandle hHal, tANI_U8 sessionId, + const tANI_U8 *pBSSId, + tANI_BOOLEAN flush_cache ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE, sessionId, flush_cache)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamDelPMKIDfromCache( pMac, sessionId, + pBSSId, flush_cache ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* --------------------------------------------------------------------------- + *\fn sme_RoamSetPSK_PMK + *\brief a wrapper function to request CSR to save PSK/PMK + * This is a synchronous call. + *\param hHal - Global structure + *\param sessionId - SME sessionId + *\param pPSK_PMK - pointer to an array of Psk[]/Pmk + *\param pmk_len - Length could be only 16 bytes in case if LEAP + connections. Need to pass this information to + firmware. + *\return eHalStatus -status whether PSK/PMK is set or not + *---------------------------------------------------------------------------*/ +eHalStatus sme_RoamSetPSK_PMK (tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 *pPSK_PMK, size_t pmk_len) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = csrRoamSetPSK_PMK(pMac, sessionId, pPSK_PMK, pmk_len); + } + else { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return (status); +} +#endif +/* --------------------------------------------------------------------------- + \fn sme_RoamGetSecurityReqIE + \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE CSR + passes to PE to JOIN request or START_BSS request + This is a synchronous call. + \param pLen - caller allocated memory that has the length of pBuf as input. + Upon returned, *pLen has the needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, + upon return + \param secType - Specifies whether looking for WPA/WPA2/WAPI IE + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetSecurityReqIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen, + tANI_U8 *pBuf, eCsrSecurityType secType) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetWpaRsnReqIE( hHal, sessionId, pLen, pBuf ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetSecurityRspIE + \brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE from + the beacon or probe rsp if connected + This is a synchronous call. + \param pLen - caller allocated memory that has the length of pBuf as input. + Upon returned, *pLen has the needed or IE length in pBuf. + \param pBuf - Caller allocated memory that contain the IE field, if any, + upon return + \param secType - Specifies whether looking for WPA/WPA2/WAPI IE + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetSecurityRspIE(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pLen, + tANI_U8 *pBuf, eCsrSecurityType secType) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetWpaRsnRspIE( pMac, sessionId, pLen, pBuf ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); + +} + + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetNumPMKIDCache + \brief a wrapper function to request CSR to return number of PMKID cache + entries + This is a synchronous call. + \return tANI_U32 - the number of PMKID cache entries + ---------------------------------------------------------------------------*/ +tANI_U32 sme_RoamGetNumPMKIDCache(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U32 numPmkidCache = 0; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + numPmkidCache = csrRoamGetNumPMKIDCache( pMac, sessionId ); + status = eHAL_STATUS_SUCCESS; + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (numPmkidCache); +} + +/* --------------------------------------------------------------------------- + \fn sme_RoamGetPMKIDCache + \brief a wrapper function to request CSR to return PMKID cache from CSR + This is a synchronous call. + \param pNum - caller allocated memory that has the space of the number of + pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the + needed or actually number in tPmkidCacheInfo. + \param pPmkidCache - Caller allocated memory that contains PMKID cache, if + any, upon return + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +eHalStatus sme_RoamGetPMKIDCache(tHalHandle hHal, tANI_U8 sessionId, tANI_U32 *pNum, + tPmkidCacheInfo *pPmkidCache) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_GET_PMKIDCACHE, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrRoamGetPMKIDCache( pMac, sessionId, pNum, pPmkidCache ); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_GetConfigParam + \brief a wrapper function that HDD calls to get the global settings + currently maintained by CSR. + This is a synchronous call. + \param pParam - caller allocated memory + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetConfigParam(tHalHandle hHal, tSmeConfigParams *pParam) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_CONFIGPARAM, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetConfigParam(pMac, &pParam->csrConfig); + if (status != eHAL_STATUS_SUCCESS) + { + smsLog( pMac, LOGE, "%s csrGetConfigParam failed", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return status; + } +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + pParam->sap_channel_avoidance = pMac->sap.sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + pParam->fScanOffload = pMac->fScanOffload; + pParam->fP2pListenOffload = pMac->fP2pListenOffload; + pParam->pnoOffload = pMac->pnoOffload; + pParam->max_intf_count = pMac->sme.max_intf_count; + pParam->enableSelfRecovery = pMac->sme.enableSelfRecovery; + pParam->f_prefer_non_dfs_on_radar = pMac->f_prefer_non_dfs_on_radar; + pParam->fine_time_meas_cap = pMac->fine_time_meas_cap; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_CfgSetInt + \brief a wrapper function that HDD calls to set parameters in CFG. + This is a synchronous call. + \param cfgId - Configuration Parameter ID (type) for STA. + \param ccmValue - The information related to Configuration Parameter ID + which needs to be saved in CFG + \param callback - To be registered by CSR with CCM. Once the CFG done with + saving the information in the database, it notifies CCM & + then the callback will be invoked to notify. + \param toBeSaved - To save the request for future reference + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_CfgSetInt(tHalHandle hHal, tANI_U32 cfgId, tANI_U32 ccmValue, + tCcmCfgSetCallback callback, eAniBoolean toBeSaved) +{ + return(ccmCfgSetInt(hHal, cfgId, ccmValue, callback, toBeSaved)); +} + +/* --------------------------------------------------------------------------- + \fn sme_CfgSetStr + \brief a wrapper function that HDD calls to set parameters in CFG. + This is a synchronous call. + \param cfgId - Configuration Parameter ID (type) for STA. + \param pStr - Pointer to the byte array which carries the information needs + to be saved in CFG + \param length - Length of the data to be saved + \param callback - To be registered by CSR with CCM. Once the CFG done with + saving the information in the database, it notifies CCM & + then the callback will be invoked to notify. + \param toBeSaved - To save the request for future reference + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_CfgSetStr(tHalHandle hHal, tANI_U32 cfgId, tANI_U8 *pStr, + tANI_U32 length, tCcmCfgSetCallback callback, + eAniBoolean toBeSaved) +{ + return(ccmCfgSetStr(hHal, cfgId, pStr, length, callback, toBeSaved)); +} + +/* --------------------------------------------------------------------------- + \fn sme_GetModifyProfileFields + \brief HDD or SME - QOS calls this function to get the current values of + connected profile fields, changing which can cause reassoc. + This function must be called after CFG is downloaded and STA is in connected + state. Also, make sure to call this function to get the current profile + fields before calling the reassoc. So that pModifyProfileFields will have + all the latest values plus the one(s) has been updated as part of reassoc + request. + \param pModifyProfileFields - pointer to the connected profile fields + changing which can cause reassoc + + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetModifyProfileFields(tHalHandle hHal, tANI_U8 sessionId, + tCsrRoamModifyProfileFields * pModifyProfileFields) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_MODPROFFIELDS, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = csrGetModifyProfileFields(pMac, sessionId, pModifyProfileFields); + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/*-------------------------------------------------------------------------- + \fn sme_SetConfigPowerSave + \brief Wrapper fn to change power save configuration in SME (PMC) module. + For BMPS related configuration, this function also updates the CFG + and sends a message to FW to pick up the new values. Note: Calling + this function only updates the configuration and does not enable + the specified power save mode. + \param hHal - The handle returned by macOpen. + \param psMode - Power Saving mode being modified + \param pConfigParams - a pointer to a caller allocated object of type + tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams + \return eHalStatus + --------------------------------------------------------------------------*/ +eHalStatus sme_SetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode, + void *pConfigParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_CONFIG_PWRSAVE, NO_SESSION, 0)); + if (NULL == pConfigParams ) { + smsLog( pMac, LOGE, "Empty config param structure for PMC, " + "nothing to update"); + return eHAL_STATUS_FAILURE; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcSetConfigPowerSave(hHal, psMode, pConfigParams); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/*-------------------------------------------------------------------------- + \fn sme_GetConfigPowerSave + \brief Wrapper fn to retrieve power save configuration in SME (PMC) module + \param hHal - The handle returned by macOpen. + \param psMode - Power Saving mode + \param pConfigParams - a pointer to a caller allocated object of type + tPmcSmpsConfigParams or tPmcBmpsConfigParams or tPmcImpsConfigParams + \return eHalStatus + --------------------------------------------------------------------------*/ +eHalStatus sme_GetConfigPowerSave(tHalHandle hHal, tPmcPowerSavingMode psMode, + void *pConfigParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_CONFIG_PWRSAVE, NO_SESSION, 0)); + if (NULL == pConfigParams ) { + smsLog( pMac, LOGE, "Empty config param structure for PMC, " + "nothing to update"); + return eHAL_STATUS_FAILURE; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcGetConfigPowerSave(hHal, psMode, pConfigParams); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_EnablePowerSave + \brief Enables one of the power saving modes. + \param hHal - The handle returned by macOpen. + \param psMode - The power saving mode to enable. If BMPS mode is enabled + while the chip is operating in Full Power, PMC will start + a timer that will try to put the chip in BMPS mode after + expiry. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_EnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ENABLE_PWRSAVE, NO_SESSION, psMode)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcEnablePowerSave(hHal, psMode); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_DisablePowerSave + \brief Disables one of the power saving modes. + \param hHal - The handle returned by macOpen. + \param psMode - The power saving mode to disable. Disabling does not imply + that device will be brought out of the current PS mode. This + is purely a configuration API. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_DisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_DISABLE_PWRSAVE, NO_SESSION, psMode)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcDisablePowerSave(hHal, psMode); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); + } + +/* --------------------------------------------------------------------------- ++ \fn sme_SetHostPowerSave ++ \brief Enables BMPS logic to be controlled by User level apps ++ \param hHal - The handle returned by macOpen. ++ \param psMode - The power saving mode to disable. Disabling does not imply ++ that device will be brought out of the current PS mode. This ++ is purely a configuration API. ++ \return eHalStatus ++ ---------------------------------------------------------------------------*/ +eHalStatus sme_SetHostPowerSave (tHalHandle hHal, v_BOOL_t psMode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->pmc.isHostPsEn = psMode; + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_StartAutoBmpsTimer + \brief Starts a timer that periodically polls all the registered + module for entry into Bmps mode. This timer is started only if BMPS is + enabled and whenever the device is in full power. + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_StartAutoBmpsTimer ( tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_START_AUTO_BMPSTIMER, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcStartAutoBmpsTimer(hHal); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +/* --------------------------------------------------------------------------- + \fn sme_StopAutoBmpsTimer + \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer + Stopping the timer does not cause a device state change. Only the timer + is stopped. If "Full Power" is desired, use the sme_RequestFullPower API + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_StopAutoBmpsTimer ( tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_STOP_AUTO_BMPSTIMER, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcStopAutoBmpsTimer(hHal); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +/** + * sme_process_set_max_tx_power() - Set the Maximum Transmit Power + * + * @pMac: mac pointer. + * @command: cmd param containing bssid, self mac + * and power in db + * + * Set the maximum transmit power dynamically. + * + * Return: eHalStatus + * + */ +eHalStatus sme_process_set_max_tx_power(tpAniSirGlobal pMac, + tSmeCmd *command) +{ + vos_msg_t msg; + tMaxTxPowerParams *max_tx_params = NULL; + + max_tx_params = vos_mem_malloc(sizeof(*max_tx_params)); + if (NULL == max_tx_params) + { + smsLog(pMac, LOGE, FL("fail to allocate memory for max_tx_params")); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(max_tx_params->bssId, + command->u.set_tx_max_pwr.bssid, SIR_MAC_ADDR_LENGTH); + vos_mem_copy(max_tx_params->selfStaMacAddr, + command->u.set_tx_max_pwr.self_sta_mac_addr, + SIR_MAC_ADDR_LENGTH); + max_tx_params->power = + command->u.set_tx_max_pwr.power; + + msg.type = WDA_SET_MAX_TX_POWER_REQ; + msg.reserved = 0; + msg.bodyptr = max_tx_params; + + if(VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) + { + smsLog(pMac, LOGE, + FL("Not able to post WDA_SET_MAX_TX_POWER_REQ message to WDA")); + vos_mem_free(max_tx_params); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn sme_QueryPowerState + \brief Returns the current power state of the device. + \param hHal - The handle returned by macOpen. + \param pPowerState - pointer to location to return power state (LOW or HIGH) + \param pSwWlanSwitchState - ptr to location to return SW WLAN Switch state + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_QueryPowerState ( + tHalHandle hHal, + tPmcPowerState *pPowerState, + tPmcSwitchState *pSwWlanSwitchState) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcQueryPowerState (hHal, pPowerState, NULL, pSwWlanSwitchState); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_IsPowerSaveEnabled + \brief Checks if the device is able to enter a particular power save mode + This does not imply that the device is in a particular PS mode + \param hHal - The handle returned by macOpen. + \param sessionId - sme session id + \param psMode - the power saving mode + \return eHalStatus + ---------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_IsPowerSaveEnabled (tHalHandle hHal, + tANI_U32 sessionId, + tPmcPowerSavingMode psMode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_BOOLEAN result = false; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_IS_PWRSAVE_ENABLED, NO_SESSION, psMode)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if(!pMac->psOffloadEnabled) + result = pmcIsPowerSaveEnabled(hHal, psMode); + else + result = pmcOffloadIsPowerSaveEnabled(hHal, sessionId, psMode); + sme_ReleaseGlobalLock( &pMac->sme ); + return result; + } + + return false; +} + +/* --------------------------------------------------------------------------- + \fn sme_RequestFullPower + \brief Request that the device be brought to full power state. When the + device enters Full Power PMC will start a BMPS timer if BMPS PS mode + is enabled. On timer expiry PMC will attempt to put the device in + BMPS mode if following holds true: + - BMPS mode is enabled + - Polling of all modules through the Power Save Check routine passes + - STA is associated to an access point + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \return eHalStatus - status + eHAL_STATUS_SUCCESS - device brought to full power state + eHAL_STATUS_FAILURE - device cannot be brought to full power state + eHAL_STATUS_PMC_PENDING - device is being brought to full power state, + ---------------------------------------------------------------------------*/ +eHalStatus sme_RequestFullPower ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext, + tRequestFullPowerReason fullPowerReason) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REQUEST_FULLPOWER, NO_SESSION, fullPowerReason)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcRequestFullPower(hHal, callbackRoutine, callbackContext, fullPowerReason); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RequestBmps + \brief Request that the device be put in BMPS state. Request will be + accepted only if BMPS mode is enabled and power save check routine + passes. + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \return eHalStatus + eHAL_STATUS_SUCCESS - device is in BMPS state + eHAL_STATUS_FAILURE - device cannot be brought to BMPS state + eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state + ---------------------------------------------------------------------------*/ +eHalStatus sme_RequestBmps ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REQUEST_BMPS, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcRequestBmps(hHal, callbackRoutine, callbackContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_SetDHCPTillPowerActiveFlag + \brief Sets/Clears DHCP related flag in PMC to disable/enable auto BMPS + entry by PMC + \param hHal - The handle returned by macOpen. + ---------------------------------------------------------------------------*/ +void sme_SetDHCPTillPowerActiveFlag(tHalHandle hHal, tANI_U8 flag) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_DHCP_FLAG, NO_SESSION, flag)); + /* Set/Clear the DHCP flag which will disable/enable + auto BMPS enter by PMC */ + pMac->pmc.remainInPowerActiveTillDHCP = flag; +} + + +/* --------------------------------------------------------------------------- + \fn sme_StartUapsd + \brief Request that the device be put in UAPSD state. If the device is in + Full Power it will be put in BMPS mode first and then into UAPSD + mode. + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + eHAL_STATUS_SUCCESS - device is in UAPSD state + eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state + eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state + eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_StartUapsd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcStartUapsd(hHal, callbackRoutine, callbackContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); + } + +/* --------------------------------------------------------------------------- + \fn sme_StopUapsd + \brief Request that the device be put out of UAPSD state. Device will be + put in in BMPS state after stop UAPSD completes. + \param hHal - The handle returned by macOpen. + \return eHalStatus + eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state + eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state + ---------------------------------------------------------------------------*/ +eHalStatus sme_StopUapsd (tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcStopUapsd(hHal); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RequestStandby + \brief Request that the device be put in standby. It is HDD's responsibility + to bring the chip to full power and do a disassoc before calling + this API. + \param hHal - The handle returned by macOpen. + \param - callbackRoutine Callback routine invoked in case of success/failure + \return eHalStatus + eHAL_STATUS_SUCCESS - device is in Standby mode + eHAL_STATUS_FAILURE - device cannot be put in standby mode + eHAL_STATUS_PMC_PENDING - device is being put in standby mode + ---------------------------------------------------------------------------*/ +eHalStatus sme_RequestStandby ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, eHalStatus status), + void *callbackContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REQUEST_STANDBY, NO_SESSION, 0)); + smsLog( pMac, LOG1, FL(" called") ); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcRequestStandby(hHal, callbackRoutine, callbackContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RegisterPowerSaveCheck + \brief Register a power save check routine that is called whenever + the device is about to enter one of the power save modes. + \param hHal - The handle returned by macOpen. + \param checkRoutine - Power save check routine to be registered + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully registered + eHAL_STATUS_FAILURE - not successfully registered + ---------------------------------------------------------------------------*/ +eHalStatus sme_RegisterPowerSaveCheck ( + tHalHandle hHal, + tANI_BOOLEAN (*checkRoutine) (void *checkContext), void *checkContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcRegisterPowerSaveCheck (hHal, checkRoutine, checkContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_Register11dScanDoneCallback + \brief Register a routine of type csrScanCompleteCallback which is + called whenever an 11d scan is done + \param hHal - The handle returned by macOpen. + \param callback - 11d scan complete routine to be registered + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_Register11dScanDoneCallback ( + tHalHandle hHal, + csrScanCompleteCallback callback) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->scan.callback11dScanDone = callback; + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_DeregisterPowerSaveCheck + \brief Deregister a power save check routine + \param hHal - The handle returned by macOpen. + \param checkRoutine - Power save check routine to be deregistered + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered + ---------------------------------------------------------------------------*/ +eHalStatus sme_DeregisterPowerSaveCheck ( + tHalHandle hHal, + tANI_BOOLEAN (*checkRoutine) (void *checkContext)) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcDeregisterPowerSaveCheck (hHal, checkRoutine); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_RegisterDeviceStateUpdateInd + \brief Register a callback routine that is called whenever + the device enters a new device state (Full Power, BMPS, UAPSD) + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine to be registered + \param callbackContext - Cookie to be passed back during callback + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully registered + eHAL_STATUS_FAILURE - not successfully registered + ---------------------------------------------------------------------------*/ +eHalStatus sme_RegisterDeviceStateUpdateInd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState), + void *callbackContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcRegisterDeviceStateUpdateInd (hHal, callbackRoutine, callbackContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_DeregisterDeviceStateUpdateInd + \brief Deregister a routine that was registered for device state changes + \param hHal - The handle returned by macOpen. + \param callbackRoutine - Callback routine to be deregistered + \return eHalStatus + eHAL_STATUS_SUCCESS - successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered + ---------------------------------------------------------------------------*/ +eHalStatus sme_DeregisterDeviceStateUpdateInd ( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackContext, tPmcState pmcState)) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcDeregisterDeviceStateUpdateInd (hHal, callbackRoutine); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_WowlAddBcastPattern + \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will + do a pattern match on these patterns when Wowl is enabled during BMPS + mode. Note that Firmware performs the pattern matching only on + broadcast frames and while Libra is in BMPS mode. + \param hHal - The handle returned by macOpen. + \param pattern - Pattern to be added + \return eHalStatus + eHAL_STATUS_FAILURE Cannot add pattern + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus sme_WowlAddBcastPattern ( + tHalHandle hHal, + tpSirWowlAddBcastPtrn pattern, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_WOWL_ADDBCAST_PATTERN, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcWowlAddBcastPattern (hHal, pattern, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_WowlDelBcastPattern + \brief Delete a pattern that was added for Pattern Byte Matching. + \param hHal - The handle returned by macOpen. + \param pattern - Pattern to be deleted + \return eHalStatus + eHAL_STATUS_FAILURE Cannot delete pattern + eHAL_STATUS_SUCCESS Request accepted. + ---------------------------------------------------------------------------*/ +eHalStatus sme_WowlDelBcastPattern ( + tHalHandle hHal, + tpSirWowlDelBcastPtrn pattern, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_WOWL_DELBCAST_PATTERN, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcWowlDelBcastPattern (hHal, pattern, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_EnterWowl + \brief This is the SME API exposed to HDD to request enabling of WOWL mode. + WoWLAN works on top of BMPS mode. If the device is not in BMPS mode, + SME will will cache the information that WOWL has been enabled and + attempt to put the device in BMPS. On entry into BMPS, SME will + enable the WOWL mode. + Note 1: If we exit BMPS mode (someone requests full power), we + will NOT resume WOWL when we go back to BMPS again. Request for full + power (while in WOWL mode) means disable WOWL and go to full power. + Note 2: Both UAPSD and WOWL work on top of BMPS. On entry into BMPS, SME + will give priority to UAPSD and enable only UAPSD if both UAPSD and WOWL + are required. Currently there is no requirement or use case to support + UAPSD and WOWL at the same time. + + \param hHal - The handle returned by macOpen. + \param enterWowlCallbackRoutine - Callback routine provided by HDD. + Used for success/failure notification by SME + \param enterWowlCallbackContext - A cookie passed by HDD, that is passed back to HDD + at the time of callback. + \param wakeReasonIndCB - Callback routine provided by HDD. + Used for Wake Reason Indication by SME + \param wakeReasonIndCBContext - A cookie passed by HDD, that is passed back to HDD + at the time of callback. + \return eHalStatus + eHAL_STATUS_SUCCESS Device is already in WoWLAN mode + eHAL_STATUS_FAILURE Device cannot enter WoWLAN mode. + eHAL_STATUS_PMC_PENDING Request accepted. SME will enable WOWL after + BMPS mode is entered. + ---------------------------------------------------------------------------*/ +eHalStatus sme_EnterWowl ( + tHalHandle hHal, + void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status), + void *enterWowlCallbackContext, +#ifdef WLAN_WAKEUP_EVENTS + void (*wakeIndicationCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd), + void *wakeIndicationCBContext, +#endif // WLAN_WAKEUP_EVENTS + tpSirSmeWowlEnterParams wowlEnterParams, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ENTER_WOWL, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcEnterWowl (hHal, enterWowlCallbackRoutine, enterWowlCallbackContext, +#ifdef WLAN_WAKEUP_EVENTS + wakeIndicationCB, wakeIndicationCBContext, +#endif // WLAN_WAKEUP_EVENTS + wowlEnterParams, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} +/* --------------------------------------------------------------------------- + \fn sme_ExitWowl + \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. + SME will initiate exit from WoWLAN mode and device will be put in BMPS + mode. + \param hHal - The handle returned by macOpen. + \param wowlExitParams - Carries info on which smesession + wowl exit is requested. + \return eHalStatus + eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode. + eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. + ---------------------------------------------------------------------------*/ +eHalStatus sme_ExitWowl (tHalHandle hHal, tpSirSmeWowlExitParams wowlExitParams) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_EXIT_WOWL, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcExitWowl (hHal, wowlExitParams); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_RoamSetKey + + \brief To set encryption key. This function should be called only when connected + This is an asynchronous API. + + \param pSetKeyInfo - pointer to a caller allocated object of tCsrSetContextInfo + + \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback + + \return eHalStatus SUCCESS Roam callback will be called indicate actually results + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamSetKey(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 *pRoamId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U32 roamId; + tANI_U32 i; + tCsrRoamSession *pSession = NULL; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_KEY, sessionId, 0)); + if (pSetKey->keyLength > CSR_MAX_KEY_LEN) + { + smsLog(pMac, LOGE, FL("Invalid key length %d"), pSetKey->keyLength); + return eHAL_STATUS_FAILURE; + } + /*Once Setkey is done, we can go in BMPS*/ + if(pSetKey->keyLength) { + pMac->pmc.remainInPowerActiveTillDHCP = FALSE; + smsLog(pMac, LOG1, FL("Reset remainInPowerActiveTillDHCP" + " to allow BMPS")); + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(pRoamId) + { + *pRoamId = roamId; + } + + smsLog(pMac, LOG2, FL("keyLength %d"), pSetKey->keyLength); + + for(i=0; ikeyLength; i++) + smsLog(pMac, LOG2, FL("%02x"), pSetKey->Key[i]); + + smsLog(pMac, LOG2, "\n sessionId=%d roamId=%d", sessionId, roamId); + + pSession = CSR_GET_SESSION(pMac, sessionId); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + if(CSR_IS_INFRA_AP(&pSession->connectedProfile)) + { + if(pSetKey->keyDirection == eSIR_TX_DEFAULT) + { + if ( ( eCSR_ENCRYPT_TYPE_WEP40 == pSetKey->encType ) || + ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pSetKey->encType )) + { + pSession->pCurRoamProfile->negotiatedUCEncryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + if ( ( eCSR_ENCRYPT_TYPE_WEP104 == pSetKey->encType ) || + ( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pSetKey->encType )) + { + pSession->pCurRoamProfile->negotiatedUCEncryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + } + } + } + + status = csrRoamSetKey ( pMac, sessionId, pSetKey, roamId ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* + * sme_roam_set_default_key_index - function to set default wep key idx + * @hHal: pointer to hal handler + * @session_id: session id + * @default_idx: default wep key index + * + * function prepares a message and post to WMA to set wep default + * key index + * + * return: Success:eHAL_STATUS_SUCCESS Failure: Error value + */ +eHalStatus sme_roam_set_default_key_index(tHalHandle hHal, uint8_t session_id, + uint8_t default_idx) +{ + vos_msg_t msg; + struct wep_update_default_key_idx *update_key; + + update_key = vos_mem_malloc(sizeof(struct wep_update_default_key_idx)); + if (!update_key) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate memory for update key"); + return eHAL_STATUS_FAILED_ALLOC; + } + + update_key->session_id = session_id; + update_key->default_idx = default_idx; + + msg.type = WDA_UPDATE_WEP_DEFAULT_KEY; + msg.reserved = 0; + msg.bodyptr = (void *)update_key; + + 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(update_key); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/* --------------------------------------------------------------------------- + + \fn sme_RoamRemoveKey + + \brief To set encryption key. This is an asynchronous API. + + \param pRemoveKey - pointer to a caller allocated object of tCsrRoamRemoveKey + + \param pRoamId Upon success return, this is the id caller can use to identify the request in roamcallback + + \return eHalStatus SUCCESS Roam callback will be called indicate actually results + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamRemoveKey(tHalHandle hHal, tANI_U8 sessionId, + tCsrRoamRemoveKey *pRemoveKey, tANI_U32 *pRoamId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U32 roamId; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REMOVE_KEY, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if(pRoamId) + { + *pRoamId = roamId; + } + status = csrRoamIssueRemoveKeyCommand( pMac, sessionId, pRemoveKey, roamId ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_GetRssi + \brief a wrapper function that client calls to register a callback to get + RSSI + + \param hHal - HAL handle for device + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param bssid - The bssid of the connected session + \param lastRSSI - RSSI value at time of request. In case fw cannot provide + RSSI, do not hold up but return this value. + \param pContext - user context to be passed back along with the callback + \param pVosContext - vos context + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetRssi(tHalHandle hHal, + tCsrRssiCallback callback, + tANI_U8 staId, tCsrBssid bssId, tANI_S8 lastRSSI, + void *pContext, void* pVosContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_RSSI, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetRssi( pMac, callback, + staId, bssId, lastRSSI, + pContext, pVosContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_GetSnr + \brief a wrapper function that client calls to register a callback to + get SNR + + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param pContext - user context to be passed back along with the callback + \param pVosContext - vos context + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetSnr(tHalHandle hHal, + tCsrSnrCallback callback, + tANI_U8 staId, tCsrBssid bssId, + void *pContext) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetSnr(pMac, callback, + staId, bssId, pContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* --------------------------------------------------------------------------- + \fn sme_GetTsmStats + \brief a wrapper function that client calls to register a callback to + get TSM Stats + \param callback - SME sends back the requested stats using the callback + \param staId - The station ID for which the stats is requested for + \param pContext - user context to be passed back along with the callback + \param pVosContext - vos context + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetTsmStats(tHalHandle hHal, + tCsrTsmStatsCallback callback, + tANI_U8 staId, tCsrBssid bssId, + void *pContext, void* pVosContext, tANI_U8 tid) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetTsmStats( pMac, callback, + staId, bssId, pContext, pVosContext, tid); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_GetStatistics + \brief a wrapper function that client calls to register a callback to get + different PHY level statistics from CSR. + + \param requesterId - different client requesting for statistics, HDD, UMA/GAN etc + \param statsMask - The different category/categories of stats requester is looking for + \param callback - SME sends back the requested stats using the callback + \param periodicity - If requester needs periodic update in millisec, 0 means + it's an one time request + \param cache - If requester is happy with cached stats + \param staId - The station ID for which the stats is requested for + \param pContext - user context to be passed back along with the callback + \param sessionId - sme session interface + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetStatistics(tHalHandle hHal, eCsrStatsRequesterType requesterId, + tANI_U32 statsMask, + tCsrStatsCallback callback, + tANI_U32 periodicity, tANI_BOOLEAN cache, + tANI_U8 staId, void *pContext, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_STATS, NO_SESSION, periodicity)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetStatistics( pMac, requesterId , statsMask, callback, + periodicity, cache, staId, pContext, + sessionId ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); + +} + +eHalStatus sme_getLinkStatus(tHalHandle hHal, + tCsrLinkStatusCallback callback, + void *pContext, + tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tAniGetLinkStatus *pMsg; + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) { + pMsg = vos_mem_malloc(sizeof(tAniGetLinkStatus)); + if (NULL == pMsg) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for link status", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg->msgType = WDA_LINK_STATUS_GET_REQ; + pMsg->msgLen = (tANI_U16)sizeof(tAniGetLinkStatus); + pMsg->sessionId = sessionId; + pMac->sme.linkStatusContext = pContext; + pMac->sme.linkStatusCallback = callback; + + vosMessage.type = WDA_LINK_STATUS_GET_REQ; + vosMessage.bodyptr = pMsg; + vosMessage.reserved = 0; + + 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: Post LINK STATUS MSG fail", __func__); + vos_mem_free(pMsg); + pMac->sme.linkStatusContext = NULL; + pMac->sme.linkStatusCallback = NULL; + status = eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock(&pMac->sme); + } + + return (status); +} + +/** + * sme_get_fw_state() - post message to wma to get firmware state + * @callback: HDD callback to be called on receiving firmware state + * @pcontext: callback context + * + * Return: eHAL_STATUS_SUCCESS on success or failure status + */ +eHalStatus sme_get_fw_state(tHalHandle hHal, + tcsr_fw_state_callback callback, + void *context) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal mac = PMAC_STRUCT(hHal); + vos_msg_t vos_message; + + status = sme_AcquireGlobalLock(&mac->sme); + if (HAL_STATUS_SUCCESS(status)) { + vos_message.type = WDA_GET_FW_STATUS_REQ; + vos_message.bodyptr = NULL; + vos_message.reserved = 0; + mac->sme.fw_state_context = context; + mac->sme.fw_state_callback = callback; + + if (!VOS_IS_STATUS_SUCCESS( + vos_mq_post_message(VOS_MODULE_ID_WDA, &vos_message))) { + smsLog(mac, LOGE, FL("Post firmware STATUS MSG fail")); + mac->sme.fw_state_context = NULL; + mac->sme.fw_state_callback = NULL; + status = eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock(&mac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn smeGetTLSTAState + \helper function to get the TL STA State whenever the function is called. + + \param staId - The staID to be passed to the TL + to get the relevant TL STA State + \return the state as tANI_U16 + ---------------------------------------------------------------------------*/ +tANI_U16 smeGetTLSTAState(tHalHandle hHal, tANI_U8 staId) +{ + tANI_U16 tlSTAState = TL_INIT_STATE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_FAILURE; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + tlSTAState = csrGetTLSTAState( pMac, staId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return tlSTAState; +} + +/* --------------------------------------------------------------------------- + + \fn sme_GetCountryCode + + \brief To return the current country code. If no country code is applied, + default country code is used to fill the buffer. + If 11d supported is turned off, an error is return and the last + applied/default country code is used. + This is a synchronous API. + + \param pBuf - pointer to a caller allocated buffer for returned country code + + \param pbLen For input, this parameter indicates how big is the buffer. + Upon return, this parameter has the number of bytes for + country. If pBuf doesn't have enough space, + this function returns fail status and this parameter contains + the number that is needed. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + ----------------------------------------------------------------------------*/ +eHalStatus sme_GetCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U8 *pbLen) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_CNTRYCODE, NO_SESSION, 0)); + + return ( csrGetCountryCode( pMac, pBuf, pbLen ) ); +} + + +/* --------------------------------------------------------------------------- + + \fn sme_SetCountryCode + + \brief To change the current/default country code. + If 11d supported is turned off, an error is return. + This is a synchronous API. + + \param pCountry - pointer to a caller allocated buffer for the country code. + + \param pfRestartNeeded A pointer to caller allocated memory, upon successful return, it indicates + whether a reset is required. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetCountryCode(tHalHandle hHal, tANI_U8 *pCountry, tANI_BOOLEAN *pfRestartNeeded) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_CNTRYCODE, NO_SESSION, 0)); + return ( csrSetCountryCode( pMac, pCountry, pfRestartNeeded ) ); +} + + +/* --------------------------------------------------------------------------- + \fn sme_ResetCountryCodeInformation + \brief this function is to reset the country code current being used back to EEPROM default + this includes channel list and power setting. This is a synchronous API. + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_ResetCountryCodeInformation(tHalHandle hHal, tANI_BOOLEAN *pfRestartNeeded) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return ( csrResetCountryCodeInformation( pMac, pfRestartNeeded ) ); +} + + +/* --------------------------------------------------------------------------- + \fn sme_GetSupportedCountryCode + \brief this function is to get a list of the country code current being supported + \param pBuf - Caller allocated buffer with at least 3 bytes, upon success return, + this has the country code list. 3 bytes for each country code. This may be NULL if + caller wants to know the needed byte count. + \param pbLen - Caller allocated, as input, it indicates the length of pBuf. Upon success return, + this contains the length of the data in pBuf. If pbuf is NULL, as input, *pbLen should be 0. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetSupportedCountryCode(tHalHandle hHal, tANI_U8 *pBuf, tANI_U32 *pbLen) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return ( csrGetSupportedCountryCode( pMac, pBuf, pbLen ) ); +} + + +/* --------------------------------------------------------------------------- + \fn sme_GetCurrentRegulatoryDomain + \brief this function is to get the current regulatory domain. This is a synchronous API. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + SME. The function fails if 11d support is turned off. + \param pDomain - Caller allocated buffer to return the current domain. + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetCurrentRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t *pDomain) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + + if( pDomain ) + { + if( csrIs11dSupported( pMac ) ) + { + *pDomain = csrGetCurrentRegulatoryDomain( pMac ); + status = eHAL_STATUS_SUCCESS; + } + else + { + status = eHAL_STATUS_FAILURE; + } + } + + return ( status ); +} + + +/* --------------------------------------------------------------------------- + \fn sme_SetRegulatoryDomain + \brief this function is to set the current regulatory domain. + This function must be called after CFG is downloaded and all the band/mode setting already passed into + SME. This is a synchronous API. + \param domainId - indicate the domain (defined in the driver) needs to set to. + See v_REGDOMAIN_t for definition + \param pfRestartNeeded - pointer to a caller allocated space. Upon successful return, it indicates whether + a restart is needed to apply the change + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetRegulatoryDomain(tHalHandle hHal, v_REGDOMAIN_t domainId, tANI_BOOLEAN *pfRestartNeeded) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return ( csrSetRegulatoryDomain( pMac, domainId, pfRestartNeeded ) ); +} + + +/* --------------------------------------------------------------------------- + + \fn sme_GetRegulatoryDomainForCountry + + \brief To return a regulatory domain base on a country code. This is a synchronous API. + + \param pCountry - pointer to a caller allocated buffer for input country code. + + \param pDomainId Upon successful return, it is the domain that country belongs to. + If it is NULL, returning success means that the country code is known. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetRegulatoryDomainForCountry(tHalHandle hHal, tANI_U8 *pCountry, v_REGDOMAIN_t *pDomainId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return csrGetRegulatoryDomainForCountry(pMac, pCountry, pDomainId, + COUNTRY_QUERY); +} + + + + +/* --------------------------------------------------------------------------- + + \fn sme_GetSupportedRegulatoryDomains + + \brief To return a list of supported regulatory domains. This is a synchronous API. + + \param pDomains - pointer to a caller allocated buffer for returned regulatory domains. + + \param pNumDomains For input, this parameter indicates how many + domains pDomains can hold. Upon return, this parameter + has the number for supported domains. If pDomains + doesn't have enough space for all the supported domains, + this function returns fail status and this parameter + contains the number that is needed. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetSupportedRegulatoryDomains(tHalHandle hHal, v_REGDOMAIN_t *pDomains, tANI_U32 *pNumDomains) +{ + eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; + + //We support all domains for now + if( pNumDomains ) + { + if( NUM_REG_DOMAINS <= *pNumDomains ) + { + status = eHAL_STATUS_SUCCESS; + } + *pNumDomains = NUM_REG_DOMAINS; + } + if( HAL_STATUS_SUCCESS( status ) ) + { + if( pDomains ) + { + pDomains[0] = REGDOMAIN_FCC; + pDomains[1] = REGDOMAIN_ETSI; + pDomains[2] = REGDOMAIN_JAPAN; + pDomains[3] = REGDOMAIN_WORLD; + pDomains[4] = REGDOMAIN_N_AMER_EXC_FCC; + pDomains[5] = REGDOMAIN_APAC; + pDomains[6] = REGDOMAIN_KOREA; + pDomains[7] = REGDOMAIN_HI_5GHZ; + pDomains[8] = REGDOMAIN_NO_5GHZ; + } + else + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + } + + return ( status ); +} + + +//some support functions +tANI_BOOLEAN sme_Is11dSupported(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return ( csrIs11dSupported( pMac ) ); +} + + +tANI_BOOLEAN sme_Is11hSupported(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return ( csrIs11hSupported( pMac ) ); +} + + +tANI_BOOLEAN sme_IsWmmSupported(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return ( csrIsWmmSupported( pMac ) ); +} + +//Upper layer to get the list of the base channels to scan for passively 11d info from csr +eHalStatus sme_ScanGetBaseChannels( tHalHandle hHal, tCsrChannelInfo * pChannelInfo ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + return(csrScanGetBaseChannels(pMac,pChannelInfo) ); +} + +/* --------------------------------------------------------------------------- + + \fn sme_ChangeCountryCode + + \brief Change Country code from upper layer during WLAN driver operation. + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + + \param pCountry New Country Code String + + \param sendRegHint If we want to send reg hint to nl80211 + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_ChangeCountryCode( tHalHandle hHal, + tSmeChangeCountryCallback callback, + tANI_U8 *pCountry, + void *pContext, + void* pVosContext, + tAniBool countryFromUserSpace, + tAniBool sendRegHint ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t msg; + tAniChangeCountryCodeReq *pMsg; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CHANGE_CNTRYCODE, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + smsLog(pMac, LOG1, FL(" called")); + + if ((pMac->roam.configParam.Is11dSupportEnabledOriginal == true) && + (!pMac->roam.configParam.fSupplicantCountryCodeHasPriority)) + { + + smsLog(pMac, LOGW, "Set Country Code Fail since the STA is associated and userspace does not have priority "); + + sme_ReleaseGlobalLock( &pMac->sme ); + status = eHAL_STATUS_FAILURE; + return status; + } + + pMsg = vos_mem_malloc(sizeof(tAniChangeCountryCodeReq)); + if ( NULL == pMsg ) + { + smsLog(pMac, LOGE, " csrChangeCountryCode: failed to allocate mem for req"); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_CHANGE_COUNTRY_CODE); + pMsg->msgLen = (tANI_U16)sizeof(tAniChangeCountryCodeReq); + vos_mem_copy(pMsg->countryCode, pCountry, 3); + pMsg->countryFromUserSpace = countryFromUserSpace; + pMsg->sendRegHint = sendRegHint; + pMsg->changeCCCallback = callback; + pMsg->pDevContext = pContext; + pMsg->pVosContext = pVosContext; + + msg.type = eWNI_SME_CHANGE_COUNTRY_CODE; + msg.bodyptr = pMsg; + msg.reserved = 0; + + if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg)) + { + smsLog(pMac, LOGE, " sme_ChangeCountryCode failed to post msg to self "); + vos_mem_free((void *)pMsg); + status = eHAL_STATUS_FAILURE; + } + smsLog(pMac, LOG1, FL(" returned")); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/*-------------------------------------------------------------------------- + + \fn sme_GenericChangeCountryCode + + \brief Change Country code from upper layer during WLAN driver operation. + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + + \param pCountry New Country Code String + + \param reg_domain regulatory domain + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + +-----------------------------------------------------------------------------*/ +eHalStatus sme_GenericChangeCountryCode( tHalHandle hHal, + tANI_U8 *pCountry, + v_REGDOMAIN_t reg_domain) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t msg; + tAniGenericChangeCountryCodeReq *pMsg; + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return status; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + smsLog(pMac, LOG1, FL(" called")); + pMsg = vos_mem_malloc(sizeof(tAniGenericChangeCountryCodeReq)); + + if (NULL == pMsg) + { + smsLog(pMac, LOGE, " sme_GenericChangeCountryCode: failed to allocate mem for req"); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE); + pMsg->msgLen = (tANI_U16)sizeof(tAniGenericChangeCountryCodeReq); + vos_mem_copy(pMsg->countryCode, pCountry, 2); + pMsg->countryCode[2] = ' '; /* For ASCII space */ + pMsg->domain_index = reg_domain; + + msg.type = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE; + msg.bodyptr = pMsg; + msg.reserved = 0; + + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg)) + { + smsLog(pMac, LOGE, "sme_GenericChangeCountryCode failed to post msg to self"); + vos_mem_free(pMsg); + status = eHAL_STATUS_FAILURE; + } + smsLog(pMac, LOG1, FL(" returned")); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +/* --------------------------------------------------------------------------- + + \fn sme_DHCPStartInd + + \brief API to signal the FW about the DHCP Start event. + + \param hHal - HAL handle for device. + + \param device_mode - mode(AP,SAP etc) of the device. + + \param macAddr - MAC address of the adapter. + + \param sessionId - session ID. + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + --------------------------------------------------------------------------*/ +eHalStatus sme_DHCPStartInd( tHalHandle hHal, + tANI_U8 device_mode, + tANI_U8 *macAddr, + tANI_U8 sessionId ) +{ + eHalStatus status; + VOS_STATUS vosStatus; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t vosMessage; + tAniDHCPInd *pMsg; + tCsrRoamSession *pSession; + + status = sme_AcquireGlobalLock(&pMac->sme); + if ( eHAL_STATUS_SUCCESS == status) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (!pSession) + { + smsLog(pMac, LOGE, FL("session %d not found "), sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg = (tAniDHCPInd*)vos_mem_malloc(sizeof(tAniDHCPInd)); + if (NULL == pMsg) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for dhcp start", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + pMsg->msgType = WDA_DHCP_START_IND; + pMsg->msgLen = (tANI_U16)sizeof(tAniDHCPInd); + pMsg->device_mode = device_mode; + vos_mem_copy( pMsg->adapterMacAddr, macAddr, sizeof(tSirMacAddr)); + vos_mem_copy( pMsg->peerMacAddr, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr) ); + + vosMessage.type = WDA_DHCP_START_IND; + vosMessage.bodyptr = pMsg; + vosMessage.reserved = 0; + + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post DHCP Start MSG fail", __func__); + vos_mem_free(pMsg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} +/* --------------------------------------------------------------------------- + \fn sme_DHCPStopInd + + \brief API to signal the FW about the DHCP complete event. + + \param hHal - HAL handle for device. + + \param device_mode - mode(AP, SAP etc) of the device. + + \param macAddr - MAC address of the adapter. + + \param sessionId - session ID. + + \return eHalStatus SUCCESS. + FAILURE or RESOURCES The API finished and failed. + --------------------------------------------------------------------------*/ +eHalStatus sme_DHCPStopInd( tHalHandle hHal, + tANI_U8 device_mode, + tANI_U8 *macAddr, + tANI_U8 sessionId ) +{ + eHalStatus status; + VOS_STATUS vosStatus; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t vosMessage; + tAniDHCPInd *pMsg; + tCsrRoamSession *pSession; + + status = sme_AcquireGlobalLock(&pMac->sme); + if ( eHAL_STATUS_SUCCESS == status) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if (!pSession) + { + smsLog(pMac, LOGE, FL("session %d not found "), sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg = (tAniDHCPInd*)vos_mem_malloc(sizeof(tAniDHCPInd)); + if (NULL == pMsg) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for dhcp stop", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg->msgType = WDA_DHCP_STOP_IND; + pMsg->msgLen = (tANI_U16)sizeof(tAniDHCPInd); + pMsg->device_mode = device_mode; + vos_mem_copy( pMsg->adapterMacAddr, macAddr, sizeof(tSirMacAddr)); + vos_mem_copy( pMsg->peerMacAddr, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr) ); + + vosMessage.type = WDA_DHCP_STOP_IND; + vosMessage.bodyptr = pMsg; + vosMessage.reserved = 0; + + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post DHCP Stop MSG fail", __func__); + vos_mem_free(pMsg); + status = eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_BtcSignalBtEvent + \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the + BT event type and the current operating mode of Libra (full power, + BMPS, UAPSD etc), appropriate Bluetooth Coexistence (BTC) strategy + would be employed. + \param hHal - The handle returned by macOpen. + \param pBtEvent - Pointer to a caller allocated object of type tSmeBtEvent + Caller owns the memory and is responsible for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE BT Event not passed to HAL. This can happen + if BTC execution mode is set to BTC_WLAN_ONLY + or BTC_PTA_ONLY. + VOS_STATUS_SUCCESS BT Event passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_BtcSignalBtEvent (tHalHandle hHal, tpSmeBtEvent pBtEvent) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_BTC_SIGNALEVENT, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + status = btcSignalBTEvent (hHal, pBtEvent); + sme_ReleaseGlobalLock( &pMac->sme ); + } +#endif + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_BtcSetConfig + \brief API to change the current Bluetooth Coexistence (BTC) configuration + This function should be invoked only after CFG download has completed. + Calling it after sme_HDDReadyInd is recommended. + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type tSmeBtcConfig. + Caller owns the memory and is responsible for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE Config not passed to HAL. + VOS_STATUS_SUCCESS Config passed to HAL + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_BtcSetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_BTC_SETCONFIG, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + status = btcSetConfig (hHal, pSmeBtcConfig); + sme_ReleaseGlobalLock( &pMac->sme ); + } +#endif + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_BtcGetConfig + \brief API to retrieve the current Bluetooth Coexistence (BTC) configuration + \param hHal - The handle returned by macOpen. + \param pSmeBtcConfig - Pointer to a caller allocated object of type + tSmeBtcConfig. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_BtcGetConfig (tHalHandle hHal, tpSmeBtcConfig pSmeBtcConfig) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_BTC_GETCONFIG, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + status = btcGetConfig (hHal, pSmeBtcConfig); + sme_ReleaseGlobalLock( &pMac->sme ); + } +#endif + return (status); +} +/* --------------------------------------------------------------------------- + \fn sme_SetCfgPrivacy + \brief API to set configure privacy parameters + \param hHal - The handle returned by macOpen. + \param pProfile - Pointer CSR Roam profile. + \param fPrivacy - This parameter indicates status of privacy + + \return void + ---------------------------------------------------------------------------*/ +void sme_SetCfgPrivacy( tHalHandle hHal, + tCsrRoamProfile *pProfile, + tANI_BOOLEAN fPrivacy + ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_CFGPRIVACY, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + csrSetCfgPrivacy(pMac, pProfile, fPrivacy); + sme_ReleaseGlobalLock( &pMac->sme ); + } +} + +#if defined WLAN_FEATURE_VOWIFI +/* --------------------------------------------------------------------------- + \fn sme_NeighborReportRequest + \brief API to request neighbor report. + \param hHal - The handle returned by macOpen. + \param pRrmNeighborReq - Pointer to a caller allocated object of type + tRrmNeighborReq. Caller owns the memory and is responsible + for freeing it. + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_NeighborReportRequest (tHalHandle hHal, tANI_U8 sessionId, + tpRrmNeighborReq pRrmNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo) +{ + VOS_STATUS status = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ, NO_SESSION, 0)); + + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + status = sme_RrmNeighborReportRequest (hHal, sessionId, pRrmNeighborReq, callbackInfo); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +#endif + +void pmcLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString, ...) +{ + VOS_TRACE_LEVEL vosDebugLevel; + char logBuffer[LOG_SIZE]; + va_list marker; + + /* getting proper Debug level */ + vosDebugLevel = getVosDebugLevel(loglevel); + + /* extracting arguments from pstring */ + va_start( marker, pString ); + vsnprintf(logBuffer, LOG_SIZE, pString, marker); + + VOS_TRACE(VOS_MODULE_ID_PMC, vosDebugLevel, "%s", logBuffer); + va_end( marker ); +} + + +void smsLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) +{ +#ifdef WLAN_DEBUG + // Verify against current log level + if ( loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_SMS_MODULE_ID )] ) + return; + else + { + va_list marker; + + va_start( marker, pString ); /* Initialize variable arguments. */ + + logDebug(pMac, SIR_SMS_MODULE_ID, loglevel, pString, marker); + + va_end( marker ); /* Reset variable arguments. */ + } +#endif +} + +/* --------------------------------------------------------------------------- + \fn sme_GetWcnssWlanCompiledVersion + \brief This API returns the version of the WCNSS WLAN API with + which the HOST driver was built + \param hHal - The handle returned by macOpen. + \param pVersion - Points to the Version structure to be filled + \return VOS_STATUS + VOS_STATUS_E_INVAL - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_GetWcnssWlanCompiledVersion(tHalHandle hHal, + tSirVersionType *pVersion) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL); + + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + if( pVersion != NULL ) + { + status = WDA_GetWcnssWlanCompiledVersion(vosContext, pVersion); + } + else + { + status = VOS_STATUS_E_INVAL; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_GetWcnssWlanReportedVersion + \brief This API returns the version of the WCNSS WLAN API with + which the WCNSS driver reports it was built + \param hHal - The handle returned by macOpen. + \param pVersion - Points to the Version structure to be filled + \return VOS_STATUS + VOS_STATUS_E_INVAL - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_GetWcnssWlanReportedVersion(tHalHandle hHal, + tSirVersionType *pVersion) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL); + + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + if( pVersion != NULL ) + { + status = WDA_GetWcnssWlanReportedVersion(vosContext, pVersion); + } + else + { + status = VOS_STATUS_E_INVAL; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_GetWcnssSoftwareVersion + \brief This API returns the version string of the WCNSS driver + \param hHal - The handle returned by macOpen. + \param pVersion - Points to the Version string buffer to be filled + \param versionBufferSize - THe size of the Version string buffer + \return VOS_STATUS + VOS_STATUS_E_INVAL - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_GetWcnssSoftwareVersion(tHalHandle hHal, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL); + + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + if( pVersion != NULL ) + { + status = WDA_GetWcnssSoftwareVersion(vosContext, pVersion, + versionBufferSize); + } + else + { + status = VOS_STATUS_E_INVAL; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn sme_GetWcnssHardwareVersion + \brief This API returns the version string of the WCNSS hardware + \param hHal - The handle returned by macOpen. + \param pVersion - Points to the Version string buffer to be filled + \param versionBufferSize - THe size of the Version string buffer + \return VOS_STATUS + VOS_STATUS_E_INVAL - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +VOS_STATUS sme_GetWcnssHardwareVersion(tHalHandle hHal, + tANI_U8 *pVersion, + tANI_U32 versionBufferSize) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL); + + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + if( pVersion != NULL ) + { + status = WDA_GetWcnssHardwareVersion(vosContext, pVersion, + versionBufferSize); + } + else + { + status = VOS_STATUS_E_INVAL; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +#ifdef FEATURE_WLAN_WAPI + +/* --------------------------------------------------------------------------- + \fn sme_ScanGetBKIDCandidateList + \brief a wrapper function to return the BKID candidate list + \param pBkidList - caller allocated buffer point to an array of + tBkidCandidateInfo + \param pNumItems - pointer to a variable that has the number of + tBkidCandidateInfo allocated when returning, this is + either the number needed or number of items put into + pPmkidList + \return eHalStatus - when fail, it usually means the buffer allocated is not + big enough and pNumItems + has the number of tBkidCandidateInfo. + \Note: pNumItems is a number of tBkidCandidateInfo, + not sizeof(tBkidCandidateInfo) * something + ---------------------------------------------------------------------------*/ +eHalStatus sme_ScanGetBKIDCandidateList(tHalHandle hHal, tANI_U32 sessionId, + tBkidCandidateInfo *pBkidList, + tANI_U32 *pNumItems ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanGetBKIDCandidateList( pMac, sessionId, pBkidList, pNumItems ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +#endif /* FEATURE_WLAN_WAPI */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/***************************************************************************** + OEM DATA related modifications and function additions + *****************************************************************************/ + +/* --------------------------------------------------------------------------- + \fn sme_OemDataReq + \brief a wrapper function for OEM DATA REQ + \param sessionId - session id to be used. + \param pOemDataReqId - pointer to an object to get back the request ID + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_OemDataReq(tHalHandle hHal, + tANI_U8 sessionId, + tOemDataReqConfig *pOemDataReqConfig, + tANI_U32 *pOemDataReqID) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do + { + //acquire the lock for the sme object + status = sme_AcquireGlobalLock(&pMac->sme); + if(HAL_STATUS_SUCCESS(status)) + { + tANI_U32 lOemDataReqId = pMac->oemData.oemDataReqID++; //let it wrap around + + if(pOemDataReqID) + { + *pOemDataReqID = lOemDataReqId; + } + else + { + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + status = oemData_OemDataReq(hHal, sessionId, pOemDataReqConfig, pOemDataReqID); + + //release the lock for the sme object + sme_ReleaseGlobalLock( &pMac->sme ); + } + } while(0); + + smsLog(pMac, LOGW, "exiting function %s", __func__); + + return(status); +} + +#endif /*FEATURE_OEM_DATA_SUPPORT*/ + +/*-------------------------------------------------------------------------- + + \brief sme_OpenSession() - Open a session for scan/roam operation. + + This is a synchronous API. + + + \param hHal - The handle returned by macOpen. + \param callback - A pointer to the function caller specifies for roam/connect status indication + \param pContext - The context passed with callback + \param pSelfMacAddr - Caller allocated memory filled with self MAC address (6 bytes) + \param pbSessionId - pointer to a caller allocated buffer for returned session ID + + \return eHAL_STATUS_SUCCESS - session is opened. sessionId returned. + + Other status means SME is failed to open the session. + eHAL_STATUS_RESOURCES - no more session available. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, + void *pContext, + tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId, + tANI_U32 type, tANI_U32 subType) +{ + eHalStatus status; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: type=%d, subType=%d", __func__, type, subType); + + if( NULL == pbSessionId ) + { + status = eHAL_STATUS_INVALID_PARAMETER; + } + else + { + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamOpenSession( pMac, callback, pContext, pSelfMacAddr, + pbSessionId, type, subType ); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + } + if( NULL != pbSessionId ) + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_OPEN_SESSION,*pbSessionId, 0)); + + return ( status ); +} + + +/*-------------------------------------------------------------------------- + + \brief sme_CloseSession() - Open a session for scan/roam operation. + + This is a synchronous API. + + + \param hHal - The handle returned by macOpen. + + \param sessionId - A previous opened session's ID. + + \return eHAL_STATUS_SUCCESS - session is closed. + + Other status means SME is failed to open the session. + eHAL_STATUS_INVALID_PARAMETER - session is not opened. + \sa + + --------------------------------------------------------------------------*/ +eHalStatus sme_CloseSession(tHalHandle hHal, tANI_U8 sessionId, + csrRoamSessionCloseCallback callback, void *pContext) +{ + eHalStatus status; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamCloseSession( pMac, sessionId, FALSE, + callback, pContext ); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return ( status ); +} + +/* --------------------------------------------------------------------------- + + \fn sme_RoamUpdateAPWPSIE + + \brief To update AP's WPS IE. This function should be called after SME AP session is created + This is an asynchronous API. + + \param pAPWPSIES - pointer to a caller allocated object of tSirAPWPSIEs + + \return eHalStatus – SUCCESS – + + FAILURE or RESOURCES – The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamUpdateAPWPSIE(tHalHandle hHal, tANI_U8 sessionId, tSirAPWPSIEs *pAPWPSIES) +{ + + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + status = csrRoamUpdateAPWPSIE( pMac, sessionId, pAPWPSIES ); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +/* --------------------------------------------------------------------------- + + \fn sme_RoamUpdateAPWPARSNIEs + + \brief To update AP's WPA/RSN IEs. This function should be called after SME AP session is created + This is an asynchronous API. + + \param pAPSirRSNie - pointer to a caller allocated object of tSirRSNie with WPS/RSN IEs + + \return eHalStatus – SUCCESS – + + FAILURE or RESOURCES – The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_RoamUpdateAPWPARSNIEs(tHalHandle hHal, tANI_U8 sessionId, tSirRSNie * pAPSirRSNie) +{ + + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + status = csrRoamUpdateWPARSNIEs( pMac, sessionId, pAPSirRSNie); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +/* --------------------------------------------------------------------------- + + \fn sme_ChangeMCCBeaconInterval + + \brief To update P2P-GO beaconInterval. This function should be called after + disassociating all the station is done + This is an asynchronous API. + + \param + + \return eHalStatus SUCCESS + FAILURE or RESOURCES + The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_ChangeMCCBeaconInterval(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + smsLog(pMac, LOG1, FL("Update Beacon PARAMS ")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrSendChngMCCBeaconInterval( pMac, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + + +/* --------------------------------------------------------------------------- + \fn smeIssueFastRoamNeighborAPEvent + \brief API to trigger fast BSS roam independent of RSSI triggers + \param hHal - The handle returned by macOpen. + \param bssid - Pointer to the BSSID to roam to. + \param fastRoamTrig - Trigger to Scan or roam + \param sessionId - Session Identifier + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus smeIssueFastRoamNeighborAPEvent(tHalHandle hHal, + tANI_U8 *bssid, + tSmeFastRoamTrigger fastRoamTrig, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + eHalStatus status = eHAL_STATUS_SUCCESS; + tFTRoamCallbackUsrCtx *pUsrCtx; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: invoked", __func__); + + if (eSME_ROAM_TRIGGER_SCAN == fastRoamTrig) + { + smsLog(pMac, LOG1, FL("CFG Channel list scan... ")); + pNeighborRoamInfo->cfgRoamEn = eSME_ROAM_TRIGGER_SCAN; + vos_mem_copy((void *)(&pNeighborRoamInfo->cfgRoambssId), + (void *)bssid, sizeof(tSirMacAddr)); + smsLog(pMac, LOG1, "Calling Roam Look Up down Event BSSID " + MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pNeighborRoamInfo->cfgRoambssId)); + + vosStatus = csrNeighborRoamTransitToCFGChanScan(pMac, sessionId); + if (VOS_STATUS_SUCCESS != vosStatus) + { + smsLog(pMac, LOGE, + FL("CFG Channel list scan state failed with status %d "), + vosStatus); + } + } + else if (eSME_ROAM_TRIGGER_FAST_ROAM == fastRoamTrig) + { + vos_mem_copy((void *)(&pNeighborRoamInfo->cfgRoambssId), + (void *)bssid, sizeof(tSirMacAddr)); + pNeighborRoamInfo->cfgRoamEn = eSME_ROAM_TRIGGER_FAST_ROAM; + smsLog(pMac, LOG1, "Roam to BSSID "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pNeighborRoamInfo->cfgRoambssId)); + + pUsrCtx = vos_mem_malloc(sizeof(*pUsrCtx)); + if (NULL == pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + /* Populate user context */ + pUsrCtx->pMac = pMac; + pUsrCtx->sessionId = sessionId; + + vosStatus = csrNeighborRoamReassocIndCallback( + pMac->roam.gVosContext, + 0, pUsrCtx, 0); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, + LOGE, + FL(" Call to csrNeighborRoamReassocIndCallback failed, status = %d"), + vosStatus); + } + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return vosStatus; +} +/* --------------------------------------------------------------------------- + \fn sme_SetHostOffload + \brief API to set the host offload feature. + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param pRequest - Pointer to the offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetHostOffload (tHalHandle hHal, tANI_U8 sessionId, + tpSirHostOffloadReq pRequest) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_FAILURE; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_HOSTOFFLOAD, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { +#ifdef WLAN_NS_OFFLOAD + if(SIR_IPV6_NS_OFFLOAD == pRequest->offloadType) + { + status = pmcSetNSOffload( hHal, pRequest, sessionId); + } + else +#endif //WLAN_NS_OFFLOAD + { + status = pmcSetHostOffload (hHal, pRequest, sessionId); + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_SetGTKOffload + \brief API to set GTK offload information. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the GTK offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pRequest, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_GTKOFFLOAD, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + status = pmcSetGTKOffload( hHal, pRequest, sessionId ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_GetGTKOffload + \brief API to get GTK offload information. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the GTK offload response. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_GetGTKOffload (tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, + void *callbackContext, tANI_U8 sessionId ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_GTKOFFLOAD, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + pmcGetGTKOffload(hHal, callbackRoutine, callbackContext, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +#endif // WLAN_FEATURE_GTK_OFFLOAD + +/* --------------------------------------------------------------------------- + \fn sme_SetKeepAlive + \brief API to set the Keep Alive feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the Keep Alive request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetKeepAlive (tHalHandle hHal, tANI_U8 sessionId, + tpSirKeepAliveReq pRequest) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + status = pmcSetKeepAlive (hHal, pRequest, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +#ifdef FEATURE_WLAN_SCAN_PNO +/* --------------------------------------------------------------------------- + \fn sme_SetPreferredNetworkList + \brief API to set the Preferred Network List Offload feature. + \param hHal - The handle returned by macOpen. + \param pRequest - Pointer to the offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetPreferredNetworkList (tHalHandle hHal, tpSirPNOScanReq pRequest, tANI_U8 sessionId, void (*callbackRoutine) (void *callbackContext, tSirPrefNetworkFoundInd *pPrefNetworkFoundInd), void *callbackContext ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_PREF_NET_LIST, + sessionId, pRequest->ucNetworksCount)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + pmcSetPreferredNetworkList(hHal, pRequest, sessionId, callbackRoutine, callbackContext); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} +#endif // FEATURE_WLAN_SCAN_PNO + +eHalStatus sme_SetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams, tANI_BOOLEAN forced) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_POWERPARAMS, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + pmcSetPowerParams(hHal, pwParams, forced); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_AbortMacScan + \brief API to cancel MAC scan. + \param hHal - The handle returned by macOpen. + \param sessionId - sessionId on which we need to abort scan. + \param reason - Reason to abort the scan. + \return VOS_STATUS + VOS_STATUS_E_FAILURE - failure + VOS_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +eHalStatus sme_AbortMacScan(tHalHandle hHal, tANI_U8 sessionId, + eCsrAbortReason reason) +{ + eHalStatus status; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ABORT_MACSCAN, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrScanAbortMacScan(pMac, sessionId, reason); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return ( status ); +} + +/* ---------------------------------------------------------------------------- + \fn sme_GetOperationChannel + \brief API to get current channel on which STA is parked + this function gives channel information only of infra station or IBSS station + \param hHal, pointer to memory location and sessionId + \returns eHAL_STATUS_SUCCESS + eHAL_STATUS_FAILURE +-------------------------------------------------------------------------------*/ +eHalStatus sme_GetOperationChannel(tHalHandle hHal, tANI_U32 *pChannel, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession; + + if (CSR_IS_SESSION_VALID( pMac, sessionId )) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_INFRASTRUCTURE ) || + ( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_IBSS ) || + ( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_INFRA_AP ) || + ( pSession->connectedProfile.BSSType == eCSR_BSS_TYPE_START_IBSS )) + { + *pChannel =pSession->connectedProfile.operationChannel; + return eHAL_STATUS_SUCCESS; + } + } + return eHAL_STATUS_FAILURE; +}// sme_GetOperationChannel ends here + +/* --------------------------------------------------------------------------- + + \fn sme_RegisterMgtFrame + + \brief To register management frame of specified type and subtype. + \param frameType - type of the frame that needs to be passed to HDD. + \param matchData - data which needs to be matched before passing frame + to HDD. + \param matchDataLen - Length of matched data. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_RegisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId, + tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REGISTER_MGMTFR, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + tSirRegisterMgmtFrame *pMsg; + tANI_U16 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!CSR_IS_SESSION_ANY(sessionId) && !pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + if( !CSR_IS_SESSION_ANY(sessionId) && !pSession->sessionActive ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s Invalid Sessionid", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + len = sizeof(tSirRegisterMgmtFrame) + matchLen; + + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pMsg, len, 0); + pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ; + pMsg->length = len; + pMsg->sessionId = sessionId; + pMsg->registerFrame = VOS_TRUE; + pMsg->frameType = frameType; + pMsg->matchLen = matchLen; + vos_mem_copy(pMsg->matchData, matchData, matchLen); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_DeregisterMgtFrame + + \brief To De-register management frame of specified type and subtype. + \param frameType - type of the frame that needs to be passed to HDD. + \param matchData - data which needs to be matched before passing frame + to HDD. + \param matchDataLen - Length of matched data. + \return eHalStatus + -------------------------------------------------------------------------------*/ +eHalStatus sme_DeregisterMgmtFrame(tHalHandle hHal, tANI_U8 sessionId, + tANI_U16 frameType, tANI_U8* matchData, tANI_U16 matchLen) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_DEREGISTER_MGMTFR, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + tSirRegisterMgmtFrame *pMsg; + tANI_U16 len; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!CSR_IS_SESSION_ANY(sessionId) && !pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + if( !CSR_IS_SESSION_ANY(sessionId) && !pSession->sessionActive ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s Invalid Sessionid", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + len = sizeof(tSirRegisterMgmtFrame) + matchLen; + + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pMsg, len, 0); + pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ; + pMsg->length = len; + pMsg->registerFrame = VOS_FALSE; + pMsg->frameType = frameType; + pMsg->matchLen = matchLen; + vos_mem_copy(pMsg->matchData, matchData, matchLen); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_RemainOnChannel + \brief API to request remain on channel for 'x' duration. used in p2p in listen state + \param hHal - The handle returned by macOpen. + \param pRequest - channel + \param duration - duration in ms + \param callback - HDD registered callback to process reaminOnChannelRsp + \param context - HDD Callback param + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_RemainOnChannel(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 channel, tANI_U32 duration, + remainOnChanCallback callback, + void *pContext, + tANI_U8 isP2PProbeReqAllowed) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REMAIN_ONCHAN, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + status = p2pRemainOnChannel (hHal, sessionId, channel, duration, callback, pContext, + isP2PProbeReqAllowed + ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_ReportProbeReq + \brief API to enable/disable forwarding of probeReq to apps in p2p. + \param hHal - The handle returned by macOpen. + \param flag: to set the Probe request forwarding to wpa_supplicant in + listen state in p2p + \return eHalStatus + ---------------------------------------------------------------------------*/ + +#ifndef WLAN_FEATURE_CONCURRENT_P2P +eHalStatus sme_ReportProbeReq(tHalHandle hHal, tANI_U8 flag) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do + { + //acquire the lock for the sme object + status = sme_AcquireGlobalLock(&pMac->sme); + if(HAL_STATUS_SUCCESS(status)) + { + /* call set in context */ + pMac->p2pContext.probeReqForwarding = flag; + //release the lock for the sme object + sme_ReleaseGlobalLock( &pMac->sme ); + } + } while(0); + + smsLog(pMac, LOGW, "exiting function %s", __func__); + + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_updateP2pIe + \brief API to set the P2p Ie in p2p context + \param hHal - The handle returned by macOpen. + \param p2pIe - Ptr to p2pIe from HDD. + \param p2pIeLength: length of p2pIe + \return eHalStatus + ---------------------------------------------------------------------------*/ + +eHalStatus sme_updateP2pIe(tHalHandle hHal, void *p2pIe, tANI_U32 p2pIeLength) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_P2P_IE, NO_SESSION, 0)); + //acquire the lock for the sme object + status = sme_AcquireGlobalLock(&pMac->sme); + if(HAL_STATUS_SUCCESS(status)) + { + if(NULL != pMac->p2pContext.probeRspIe){ + vos_mem_free(pMac->p2pContext.probeRspIe); + pMac->p2pContext.probeRspIeLength = 0; + } + + pMac->p2pContext.probeRspIe = vos_mem_malloc(p2pIeLength); + if (NULL == pMac->p2pContext.probeRspIe) + { + smsLog(pMac, LOGE, "%s: Unable to allocate P2P IE", __func__); + pMac->p2pContext.probeRspIeLength = 0; + status = eHAL_STATUS_FAILURE; + } + else + { + pMac->p2pContext.probeRspIeLength = p2pIeLength; + + sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG2, + pMac->p2pContext.probeRspIe, + pMac->p2pContext.probeRspIeLength ); + vos_mem_copy((tANI_U8 *)pMac->p2pContext.probeRspIe, p2pIe, + p2pIeLength); + } + + //release the lock for the sme object + sme_ReleaseGlobalLock( &pMac->sme ); + } + + smsLog(pMac, LOG2, "exiting function %s", __func__); + + return(status); +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_sendAction + \brief API to send action frame from supplicant. + \param hHal - The handle returned by macOpen. + \return eHalStatus + ---------------------------------------------------------------------------*/ + +eHalStatus sme_sendAction(tHalHandle hHal, tANI_U8 sessionId, + const tANI_U8 *pBuf, tANI_U32 len, + tANI_U16 wait, tANI_BOOLEAN noack) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SEND_ACTION, sessionId, 0)); + //acquire the lock for the sme object + status = sme_AcquireGlobalLock(&pMac->sme); + if(HAL_STATUS_SUCCESS(status)) + { + p2pSendAction(hHal, sessionId, pBuf, len, wait, noack); + //release the lock for the sme object + sme_ReleaseGlobalLock( &pMac->sme ); + } + + smsLog(pMac, LOGW, "exiting function %s", __func__); + + return(status); +} + +eHalStatus sme_CancelRemainOnChannel(tHalHandle hHal, tANI_U8 sessionId ) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CANCEL_REMAIN_ONCHAN, sessionId, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + status = p2pCancelRemainOnChannel (hHal, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +//Power Save Related +eHalStatus sme_p2pSetPs(tHalHandle hHal, tP2pPsConfig * data) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + status = p2pSetPs (hHal, data); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureRxpFilter + + \brief + SME will pass this request to lower mac to set/reset the filter on RXP for + multicast & broadcast traffic. + + \param + + hHal - The handle returned by macOpen. + + filterMask- Currently the API takes a 1 or 0 (set or reset) as filter. + Basically to enable/disable the filter (to filter "all" mcbc traffic) based + on this param. In future we can use this as a mask to set various types of + filters as suggested below: + FILTER_ALL_MULTICAST: + FILTER_ALL_BROADCAST: + FILTER_ALL_MULTICAST_BROADCAST: + + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureRxpFilter( tHalHandle hHal, + tpSirWlanSetRxpFilters wlanRxpFilterParam) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_RXPFIL, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + /* serialize the req through MC thread */ + vosMessage.bodyptr = wlanRxpFilterParam; + vosMessage.type = WDA_CFG_RXP_FILTER_REQ; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureSuspendInd + + \brief + SME will pass this request to lower mac to Indicate that the wlan needs to + be suspended + + \param + + hHal - The handle returned by macOpen. + + wlanSuspendParam- Depicts the wlan suspend params + + csrReadyToSuspendCallback - Callback to be called when ready to suspend + event is received. + callbackContext - Context associated with csrReadyToSuspendCallback. + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureSuspendInd( tHalHandle hHal, + tpSirWlanSuspendParam wlanSuspendParam, + csrReadyToSuspendCallback callback, + void *callbackContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_SUSPENDIND, NO_SESSION, 0)); + + pMac->readyToSuspendCallback = callback; + pMac->readyToSuspendContext = callbackContext; + + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + /* serialize the req through MC thread */ + vosMessage.bodyptr = wlanSuspendParam; + vosMessage.type = WDA_WLAN_SUSPEND_IND; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) { + pMac->readyToSuspendCallback = NULL; + pMac->readyToSuspendContext = NULL; + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return(status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureResumeReq + + \brief + SME will pass this request to lower mac to Indicate that the wlan needs to + be Resumed + + \param + + hHal - The handle returned by macOpen. + + wlanResumeParam- Depicts the wlan resume params + + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureResumeReq( tHalHandle hHal, + tpSirWlanResumeParam wlanResumeParam) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_RESUMEREQ, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + /* serialize the req through MC thread */ + vosMessage.bodyptr = wlanResumeParam; + vosMessage.type = WDA_WLAN_RESUME_REQ; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureExtWoW + + \brief + SME will pass this request to lower mac to configure Extr WoW + + \param + + hHal - The handle returned by macOpen. + + wlanExtParams- Depicts the wlan Ext params + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureExtWoW( tHalHandle hHal, + tpSirExtWoWParams wlanExtParams, + csrReadyToExtWoWCallback callback, + void *callbackContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tpSirExtWoWParams MsgPtr = vos_mem_malloc(sizeof(*MsgPtr)); + + if (!MsgPtr) + return eHAL_STATUS_FAILURE; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_EXTWOW, NO_SESSION, 0)); + + pMac->readyToExtWoWCallback = callback; + pMac->readyToExtWoWContext = callbackContext; + + if ( eHAL_STATUS_SUCCESS == + ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) { + + /* serialize the req through MC thread */ + vos_mem_copy(MsgPtr, wlanExtParams, sizeof(*MsgPtr)); + vosMessage.bodyptr = MsgPtr; + vosMessage.type = WDA_WLAN_EXT_WOW; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) { + pMac->readyToExtWoWCallback = NULL; + pMac->readyToExtWoWContext = NULL; + vos_mem_free(MsgPtr); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } else { + pMac->readyToExtWoWCallback = NULL; + pMac->readyToExtWoWContext = NULL; + vos_mem_free(MsgPtr); + } + + return(status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureAppType1Params + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by macOpen. + + wlanAppType1Params- Depicts the wlan App Type 1(Indoor) params + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureAppType1Params( tHalHandle hHal, + tpSirAppType1Params wlanAppType1Params) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tpSirAppType1Params MsgPtr = vos_mem_malloc(sizeof(*MsgPtr)); + + if (!MsgPtr) + return eHAL_STATUS_FAILURE; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE1, NO_SESSION, 0)); + + if ( eHAL_STATUS_SUCCESS == + ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) { + + /* serialize the req through MC thread */ + vos_mem_copy(MsgPtr, wlanAppType1Params, sizeof(*MsgPtr)); + vosMessage.bodyptr = MsgPtr; + vosMessage.type = WDA_WLAN_SET_APP_TYPE1_PARAMS; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) { + vos_mem_free(MsgPtr); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } else { + vos_mem_free(MsgPtr); + } + + return(status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_ConfigureAppType2Params + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by macOpen. + + wlanAppType2Params- Depicts the wlan App Type 2 (Outdoor) params + + \return eHalStatus + + +--------------------------------------------------------------------------- */ +eHalStatus sme_ConfigureAppType2Params( tHalHandle hHal, + tpSirAppType2Params wlanAppType2Params) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tpSirAppType2Params MsgPtr = vos_mem_malloc(sizeof(*MsgPtr)); + + if (!MsgPtr) + return eHAL_STATUS_FAILURE; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE2, NO_SESSION, 0)); + + if ( eHAL_STATUS_SUCCESS == + ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) { + + /* serialize the req through MC thread */ + vos_mem_copy(MsgPtr, wlanAppType2Params, sizeof(*MsgPtr)); + vosMessage.bodyptr = MsgPtr; + vosMessage.type = WDA_WLAN_SET_APP_TYPE2_PARAMS; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) { + vos_mem_free(MsgPtr); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } else { + vos_mem_free(MsgPtr); + } + + return(status); +} +#endif + +/* --------------------------------------------------------------------------- + + \fn sme_GetInfraSessionId + + \brief To get the session ID for infra session, if connected + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + + \return sessionid, -1 if infra session is not connected + + -------------------------------------------------------------------------------*/ +tANI_S8 sme_GetInfraSessionId(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_S8 sessionid = -1; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + sessionid = csrGetInfraSessionId( pMac); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (sessionid); +} + +/* --------------------------------------------------------------------------- + + \fn sme_GetInfraOperationChannel + + \brief To get the operating channel for infra session, if connected + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + \param sessionId - the sessionId returned by sme_OpenSession. + + \return operating channel, 0 if infra session is not connected + + -------------------------------------------------------------------------------*/ +tANI_U8 sme_GetInfraOperationChannel( tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U8 channel = 0; + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + channel = csrGetInfraOperationChannel( pMac, sessionId); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (channel); +} + +/* + * This routine will return operating channel on which other BSS is operating to + * be used for concurrency mode. + * If other BSS is not up or not connected it will return 0. + */ +tANI_U8 sme_GetConcurrentOperationChannel( tHalHandle hHal ) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tANI_U8 channel = 0; + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + channel = csrGetConcurrentOperationChannel( pMac ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, "%s: " + " Other Concurrent Channel = %d", __func__,channel); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (channel); +} +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +v_U16_t sme_CheckConcurrentChannelOverlap( tHalHandle hHal, v_U16_t sap_ch, + eCsrPhyMode sapPhyMode, v_U8_t cc_switch_mode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + v_U16_t channel = 0; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + channel = csrCheckConcurrentChannelOverlap( pMac, sap_ch, sapPhyMode, + cc_switch_mode); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (channel); +} +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO +/****************************************************************************** +* +* Name: sme_PreferredNetworkFoundInd +* +* Description: +* Invoke Preferred Network Found Indication +* +* Parameters: +* hHal - HAL handle for device +* pMsg - found network description +* +* Returns: eHalStatus +* +******************************************************************************/ +eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = (tSirPrefNetworkFoundInd *)pMsg; + v_U8_t dumpSsId[SIR_MAC_MAX_SSID_LENGTH + 1]; + tANI_U8 ssIdLength = 0; + + if (NULL == pMsg) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + return eHAL_STATUS_FAILURE; + } + + if (pMac->pnoOffload) + { + /* Call Preferred Network Found Indication callback routine. */ + if (pMac->pmc.prefNetwFoundCB != NULL) + { + pMac->pmc.prefNetwFoundCB( + pMac->pmc.preferredNetworkFoundIndCallbackContext, + pPrefNetworkFoundInd); + } + return status; + } + + if (pPrefNetworkFoundInd->ssId.length > 0) + { + ssIdLength = CSR_MIN(SIR_MAC_MAX_SSID_LENGTH, + pPrefNetworkFoundInd->ssId.length); + vos_mem_copy(dumpSsId, pPrefNetworkFoundInd->ssId.ssId, ssIdLength); + dumpSsId[ssIdLength] = 0; + smsLog(pMac, LOG2, "%s:SSID=%s frame length %d", + __func__, dumpSsId, pPrefNetworkFoundInd->frameLength); + + /* Flush scan results, So as to avoid indication/updation of + * stale entries, which may not have aged out during APPS collapse + */ + sme_ScanFlushResult(hHal,0); + + //Save the frame to scan result + if (pPrefNetworkFoundInd->mesgLen > sizeof(tSirPrefNetworkFoundInd)) + { + //we may have a frame + status = csrScanSavePreferredNetworkFound(pMac, + pPrefNetworkFoundInd); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" fail to save preferred network")); + } + } + else + { + smsLog(pMac, LOGE, FL(" not enough data length %d needed %zu"), + pPrefNetworkFoundInd->mesgLen, sizeof(tSirPrefNetworkFoundInd)); + } + + /* Call Preferred Network Found Indication callback routine. */ + if (HAL_STATUS_SUCCESS(status) && (pMac->pmc.prefNetwFoundCB != NULL)) + { + pMac->pmc.prefNetwFoundCB( + pMac->pmc.preferredNetworkFoundIndCallbackContext, + pPrefNetworkFoundInd); + } + } + else + { + smsLog(pMac, LOGE, "%s: callback failed - SSID is NULL", __func__); + status = eHAL_STATUS_FAILURE; + } + + return(status); +} + +#endif // FEATURE_WLAN_SCAN_PNO + + +eHalStatus sme_GetCfgValidChannels(tHalHandle hHal, tANI_U8 *aValidChannels, tANI_U32 *len) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrGetCfgValidChannels(pMac, aValidChannels, len); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + + +/* --------------------------------------------------------------------------- + + \fn sme_SetTxPerTracking + + \brief Set Tx PER tracking configuration parameters + + \param hHal - The handle returned by macOpen. + \param pTxPerTrackingConf - Tx PER configuration parameters + + \return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetTxPerTracking(tHalHandle hHal, + void (*pCallbackfn) (void *pCallbackContext), + void *pCallbackContext, + tpSirTxPerTrackingParam pTxPerTrackingParam) +{ + vos_msg_t msg; + tpSirTxPerTrackingParam pTxPerTrackingParamReq = NULL; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if ( eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock( &pMac->sme ) ) + { + pMac->sme.pTxPerHitCallback = pCallbackfn; + pMac->sme.pTxPerHitCbContext = pCallbackContext; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + // free this memory in failure case or WDA request callback function + pTxPerTrackingParamReq = vos_mem_malloc(sizeof(tSirTxPerTrackingParam)); + if (NULL == pTxPerTrackingParamReq) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for tSirTxPerTrackingParam", __func__); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pTxPerTrackingParamReq, (void*)pTxPerTrackingParam, + sizeof(tSirTxPerTrackingParam)); + msg.type = WDA_SET_TX_PER_TRACKING_REQ; + msg.reserved = 0; + msg.bodyptr = pTxPerTrackingParamReq; + + 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_TX_PER_TRACKING_REQ message to WDA", __func__); + vos_mem_free(pTxPerTrackingParamReq); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_HandleChangeCountryCode + + \brief Change Country code, Reg Domain and channel list + + \details Country Code Priority + 0 = 11D > Configured Country > NV + 1 = Configured Country > 11D > NV + If Supplicant country code is priority than 11d is disabled. + If 11D is enabled, we update the country code after every scan. + Hence when Supplicant country code is priority, we don't need 11D info. + Country code from Supplicant is set as current country code. + User can send reset command XX (instead of country code) to reset the + country code to default values which is read from NV. + In case of reset, 11D is enabled and default NV code is Set as current country code + If 11D is priority, + Than Supplicant country code code is set to default code. But 11D code is set as current country code + + \param pMac - The handle returned by macOpen. + \param pMsgBuf - MSG Buffer + + \return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tAniChangeCountryCodeReq *pMsg; + v_REGDOMAIN_t domainIdIoctl; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + static uNvTables nvTables; + pMsg = (tAniChangeCountryCodeReq *)pMsgBuf; + + + /* if the reset Supplicant country code command is triggered, enable 11D, reset the NV country code and return */ + if( VOS_TRUE == vos_mem_compare(pMsg->countryCode, SME_INVALID_COUNTRY_CODE, 2) ) + { + pMac->roam.configParam.Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabledOriginal; + + vosStatus = vos_nv_readDefaultCountryTable( &nvTables ); + + /* read the country code from NV and use it */ + if ( VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + vos_mem_copy(pMsg->countryCode, + nvTables.defaultCountryTable.countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + } + else + { + status = eHAL_STATUS_FAILURE; + return status; + } + /* + * Update the 11d country to default country from NV bin so that when + * callback is received for this default country, driver will not + * disable the 11d taking it as valid country by user. + */ + smsLog(pMac, LOG1, + FL + ("Set default country code (%c%c) from NV as invalid country received"), + pMsg->countryCode[0],pMsg->countryCode[1]); + vos_mem_copy(pMac->scan.countryCode11d, pMsg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + + } + else + { + /* if Supplicant country code has priority, disable 11d */ + if(pMac->roam.configParam.fSupplicantCountryCodeHasPriority && + pMsg->countryFromUserSpace) + { + pMac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE; + } + } + + /* WEXT set country code means + * 11D should be supported? + * 11D Channel should be enforced? + * 11D Country code should be matched? + * 11D Reg Domain should be matched? + * Country string changed */ + if(pMac->roam.configParam.Is11dSupportEnabled && + pMac->roam.configParam.fEnforce11dChannels && + pMac->roam.configParam.fEnforceCountryCodeMatch && + pMac->roam.configParam.fEnforceDefaultDomain && + !csrSave11dCountryString(pMac, pMsg->countryCode, eANI_BOOLEAN_TRUE)) + { + /* All 11D related options are already enabled + * Country string is not changed + * Do not need do anything for country code change request */ + return eHAL_STATUS_SUCCESS; + } + + /* Set Current Country code and Current Regulatory domain */ + status = csrSetCountryCode(pMac, pMsg->countryCode, NULL); + if(eHAL_STATUS_SUCCESS != status) + { + /* Supplicant country code failed. So give 11D priority */ + pMac->roam.configParam.Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabledOriginal; + smsLog(pMac, LOGE, "Set Country Code Fail %d", status); + return status; + } + + /* Overwrite the default country code */ + vos_mem_copy(pMac->scan.countryCodeDefault, + pMac->scan.countryCodeCurrent, + WNI_CFG_COUNTRY_CODE_LEN); + + /* Get Domain ID from country code */ + status = csrGetRegulatoryDomainForCountry(pMac, + pMac->scan.countryCodeCurrent, + (v_REGDOMAIN_t *) &domainIdIoctl, + COUNTRY_QUERY); + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to get regId %d"), domainIdIoctl ); + return status; + } + else if (REGDOMAIN_WORLD == domainIdIoctl) + { + /* Supplicant country code is invalid, so we are on world mode now. So + give 11D chance to update */ + pMac->roam.configParam.Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabledOriginal; + smsLog(pMac, LOG1, FL("Country Code unrecognized by driver")); + } + + + status = WDA_SetRegDomain(pMac, domainIdIoctl, pMsg->sendRegHint); + + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to set regId %d"), domainIdIoctl ); + return status; + } + else + { + //if 11d has priority, clear currentCountryBssid & countryCode11d to get + //set again if we find AP with 11d info during scan + if (!pMac->roam.configParam.fSupplicantCountryCodeHasPriority) + { + smsLog( pMac, LOGW, FL("Clearing currentCountryBssid, countryCode11d")); + vos_mem_zero(&pMac->scan.currentCountryBssid, sizeof(tCsrBssid)); + vos_mem_zero( pMac->scan.countryCode11d, sizeof( pMac->scan.countryCode11d ) ); + } + } + + if( pMsg->changeCCCallback ) + { + ((tSmeChangeCountryCallback)(pMsg->changeCCCallback))((void *)pMsg->pDevContext); + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_HandleChangeCountryCodeByUser + + \brief Change Country code, Reg Domain and channel list + + If Supplicant country code is priority than 11d is disabled. + If 11D is enabled, we update the country code after every scan. + Hence when Supplicant country code is priority, we don't need 11D info. + Country code from Supplicant is set as current country code. + + \param pMac - The handle returned by macOpen. + \param pMsg - Carrying new CC & domain set in kernel by user + + \return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_HandleChangeCountryCodeByUser(tpAniSirGlobal pMac, + tAniGenericChangeCountryCodeReq *pMsg) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + v_REGDOMAIN_t reg_domain_id; + v_BOOL_t is11dCountry = VOS_FALSE; + + smsLog(pMac, LOG1, FL(" called")); + reg_domain_id = (v_REGDOMAIN_t)pMsg->domain_index; + + if (memcmp(pMsg->countryCode, pMac->scan.countryCode11d, + VOS_COUNTRY_CODE_LEN) == 0) + { + is11dCountry = VOS_TRUE; + } + + /* Set the country code given by user space when 11dOriginal is FALSE + * when 11doriginal is True,is11dCountry =0 and + * fSupplicantCountryCodeHasPriority = 0, then revert the country code, + * and return failure + */ + if(pMac->roam.configParam.Is11dSupportEnabledOriginal == true) + { + if ((!is11dCountry) && (!pMac->roam.configParam.fSupplicantCountryCodeHasPriority)) + { + + smsLog( pMac, LOGW, FL(" incorrect country being set, nullify this request")); + + /* we have got a request for a country that should not have been added since the + * STA is associated; nullify this request. + * If both countryCode11d[0] and countryCode11d[1] are zero, revert it to World + * domain to avoid from causing cfg80211 call trace. + */ + if ((pMac->scan.countryCode11d[0] == 0) && (pMac->scan.countryCode11d[1] == 0)) + status = csrGetRegulatoryDomainForCountry(pMac, + "00", + (v_REGDOMAIN_t *) ®_domain_id, + COUNTRY_IE); + else + status = csrGetRegulatoryDomainForCountry(pMac, + pMac->scan.countryCode11d, + (v_REGDOMAIN_t *) ®_domain_id, + COUNTRY_IE); + + return eHAL_STATUS_FAILURE; + } + } + /* if Supplicant country code has priority, disable 11d */ + if (!is11dCountry && pMac->roam.configParam.fSupplicantCountryCodeHasPriority) + { + pMac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE; + } + + vos_mem_copy(pMac->scan.countryCodeCurrent, pMsg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + + status = WDA_SetRegDomain(pMac, reg_domain_id, eSIR_TRUE); + + if (VOS_FALSE == is11dCountry ) + { + /* Overwrite the default country code */ + vos_mem_copy(pMac->scan.countryCodeDefault, + pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); + /* set to default domain ID */ + pMac->scan.domainIdDefault = pMac->scan.domainIdCurrent; + } + + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to set regId %d"), reg_domain_id ); + return status; + } + else + { + //if 11d has priority, clear currentCountryBssid & countryCode11d to get + //set again if we find AP with 11d info during scan + if((!pMac->roam.configParam.fSupplicantCountryCodeHasPriority) && + (VOS_FALSE == is11dCountry )) + { + smsLog( pMac, LOGW, FL("Clearing currentCountryBssid, countryCode11d")); + vos_mem_zero(&pMac->scan.currentCountryBssid, sizeof(tCsrBssid)); + vos_mem_zero( pMac->scan.countryCode11d, sizeof( pMac->scan.countryCode11d ) ); + } + } + + /* get the channels based on new cc */ + status = csrInitGetChannels(pMac); + + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to get Channels ")); + return status; + } + + /* reset info based on new cc, and we are done */ + csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + if (VOS_TRUE == is11dCountry) + { + pMac->scan.f11dInfoApplied = eANI_BOOLEAN_TRUE; + pMac->scan.f11dInfoReset = eANI_BOOLEAN_FALSE; + } + /* Country code Changed, Purge Only scan result + * which does not have channel number belong to 11d + * channel list + */ + csrScanFilterResults(pMac); + // Do active scans after the country is set by User hints or Country IE + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + + sme_DisconnectConnectedSessions(pMac); + + smsLog(pMac, LOG1, FL(" returned")); + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_HandleChangeCountryCodeByCore + + \brief Update Country code in the driver if set by kernel as world + + If 11D is enabled, we update the country code after every scan & notify kernel. + This is to make sure kernel & driver are in sync in case of CC found in + driver but not in kernel database + + \param pMac - The handle returned by macOpen. + \param pMsg - Carrying new CC set in kernel + + \return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_HandleChangeCountryCodeByCore(tpAniSirGlobal pMac, tAniGenericChangeCountryCodeReq *pMsg) +{ + eHalStatus status; + + smsLog(pMac, LOG1, FL(" called")); + + //this is to make sure kernel & driver are in sync in case of CC found in + //driver but not in kernel database + if (('0' == pMsg->countryCode[0]) && ('0' == pMsg->countryCode[1])) + { + smsLog( pMac, LOGW, FL("Setting countryCode11d & countryCodeCurrent to world CC")); + vos_mem_copy(pMac->scan.countryCode11d, pMsg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + vos_mem_copy(pMac->scan.countryCodeCurrent, pMsg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + } + + status = WDA_SetRegDomain(pMac, REGDOMAIN_WORLD, eSIR_TRUE); + + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to set regId") ); + return status; + } + else + { + status = csrInitGetChannels(pMac); + if ( status != eHAL_STATUS_SUCCESS ) + { + smsLog( pMac, LOGE, FL(" fail to get Channels ")); + } + else + { + csrInitChannelList(pMac); + } + } + /* Country code Changed, Purge Only scan result + * which does not have channel number belong to 11d + * channel list + */ + csrScanFilterResults(pMac); + smsLog(pMac, LOG1, FL(" returned")); + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_DisconnectConnectedSessions + + \brief Disconnect STA and P2P client session if channel is not supported + + If new country code does not support the channel on which STA/P2P client + is connected, it sends the disconnect to the AP/P2P GO + + \param pMac - The handle returned by macOpen + + \return void + + -------------------------------------------------------------------------------*/ + +void sme_DisconnectConnectedSessions(tpAniSirGlobal pMac) +{ + v_U8_t i,sessionId, isChanFound = false; + tANI_U8 currChannel; + + for (sessionId=0; sessionId< CSR_ROAM_SESSION_MAX; sessionId++) + { + if (csrIsSessionClientAndConnected(pMac, sessionId)) + { + isChanFound = false; + //Session is connected.Check the channel + currChannel = csrGetInfraOperationChannel(pMac, sessionId); + smsLog(pMac, LOGW, "Current Operating channel : %d, session :%d", + currChannel, sessionId); + for (i=0; i < pMac->scan.base20MHzChannels.numChannels; i++) + { + if (pMac->scan.base20MHzChannels.channelList[i] == currChannel) + { + isChanFound = true; + break; + } + } + + if (!isChanFound) + { + for (i=0; i < pMac->scan.base40MHzChannels.numChannels; i++) + { + if(pMac->scan.base40MHzChannels.channelList[i] == currChannel) + { + isChanFound = true; + break; + } + } + } + + if (!isChanFound) + { + smsLog(pMac, LOGW, "%s : Disconnect Session :%d", __func__, sessionId); + csrRoamDisconnect(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); + } + } + } +} + + +/* --------------------------------------------------------------------------- + + \fn sme_HandleGenericChangeCountryCode + + \brief Change Country code, Reg Domain and channel list + + If Supplicant country code is priority than 11d is disabled. + If 11D is enabled, we update the country code after every scan. + Hence when Supplicant country code is priority, we don't need 11D info. + Country code from kernel is set as current country code. + + \param pMac - The handle returned by macOpen. + \param pMsgBuf - message buffer + + \return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_HandleGenericChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tAniGenericChangeCountryCodeReq *pMsg; + v_REGDOMAIN_t reg_domain_id; + + smsLog(pMac, LOG1, FL(" called")); + pMsg = (tAniGenericChangeCountryCodeReq *)pMsgBuf; + reg_domain_id = (v_REGDOMAIN_t)pMsg->domain_index; + + if (REGDOMAIN_COUNT == reg_domain_id) + { + sme_HandleChangeCountryCodeByCore(pMac, pMsg); + } + else + { + sme_HandleChangeCountryCodeByUser(pMac, pMsg); + } + smsLog(pMac, LOG1, FL(" returned")); + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +eHalStatus sme_8023MulticastList (tHalHandle hHal, tANI_U8 sessionId, tpSirRcvFltMcAddrList pMulticastAddrs) +{ + tpSirRcvFltMcAddrList pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = NULL; + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: " + "ulMulticastAddrCnt=%d, multicastAddr[0]=%p", __func__, + pMulticastAddrs->ulMulticastAddrCnt, + pMulticastAddrs->multicastAddr[0]); + + /* + *Find the connected Infra / P2P_client connected session + */ + if (CSR_IS_SESSION_VALID(pMac, sessionId) && + csrIsConnStateInfra(pMac, sessionId)) + { + pSession = CSR_GET_SESSION( pMac, sessionId ); + } + + if (pSession == NULL) { + smsLog(pMac, LOGW, FL("Unable to find the session Id: %d"), sessionId); + return eHAL_STATUS_FAILURE; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to " + "allocate memory for 8023 Multicast List request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + if( !csrIsConnStateConnectedInfra (pMac, sessionId )) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Ignoring the " + "indication as we are not connected", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pRequestBuf, pMulticastAddrs, sizeof(tSirRcvFltMcAddrList)); + + vos_mem_copy(pRequestBuf->selfMacAddr, pSession->selfMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + msg.type = WDA_8023_MULTICAST_LIST_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + 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_8023_MULTICAST_LIST message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus sme_ReceiveFilterSetFilter(tHalHandle hHal, tpSirRcvPktFilterCfgType pRcvPktFilterCfg, + tANI_U8 sessionId) +{ + tpSirRcvPktFilterCfgType pRequestBuf; + v_SINT_t allocSize; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + v_U8_t idx=0; + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterType=%d, " + "filterId = %d", __func__, + pRcvPktFilterCfg->filterType, pRcvPktFilterCfg->filterId); + + allocSize = sizeof(tSirRcvPktFilterCfgType); + + pRequestBuf = vos_mem_malloc(allocSize); + + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to " + "allocate memory for Receive Filter Set Filter request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + if( NULL == pSession ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Session Not found ", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pRcvPktFilterCfg->selfMacAddr, pSession->selfMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(pRcvPktFilterCfg->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf, pRcvPktFilterCfg, allocSize); + + msg.type = WDA_RECEIVE_FILTER_SET_FILTER_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Pkt Flt Req : " + "FT %d FID %d ", + pRequestBuf->filterType, pRequestBuf->filterId); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Pkt Flt Req : " + "params %d CT %d", + pRequestBuf->numFieldParams, pRequestBuf->coalesceTime); + + for (idx=0; idxnumFieldParams; idx++) + { + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Proto %d Comp Flag %d ", + pRequestBuf->paramsData[idx].protocolLayer, + pRequestBuf->paramsData[idx].cmpFlag); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Data Offset %d Data Len %d", + pRequestBuf->paramsData[idx].dataOffset, + pRequestBuf->paramsData[idx].dataLength); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "CData: %d:%d:%d:%d:%d:%d", + pRequestBuf->paramsData[idx].compareData[0], + pRequestBuf->paramsData[idx].compareData[1], + pRequestBuf->paramsData[idx].compareData[2], + pRequestBuf->paramsData[idx].compareData[3], + pRequestBuf->paramsData[idx].compareData[4], + pRequestBuf->paramsData[idx].compareData[5]); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "MData: %d:%d:%d:%d:%d:%d", + pRequestBuf->paramsData[idx].dataMask[0], + pRequestBuf->paramsData[idx].dataMask[1], + pRequestBuf->paramsData[idx].dataMask[2], + pRequestBuf->paramsData[idx].dataMask[3], + pRequestBuf->paramsData[idx].dataMask[4], + pRequestBuf->paramsData[idx].dataMask[5]); + + } + + 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_RECEIVE_FILTER_SET_FILTER message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +eHalStatus sme_GetFilterMatchCount(tHalHandle hHal, + FilterMatchCountCallback callbackRoutine, + void *callbackContext, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status; + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "+%s", __func__); + + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme))) + { + pmcGetFilterMatchCount(hHal, callbackRoutine, callbackContext, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "-%s", __func__); + + return (status); +} + +eHalStatus sme_ReceiveFilterClearFilter(tHalHandle hHal, tpSirRcvFltPktClearParam pRcvFltPktClearParam, + tANI_U8 sessionId) +{ + tpSirRcvFltPktClearParam pRequestBuf; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d", __func__, + pRcvFltPktClearParam->filterId); + + pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltPktClearParam)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for Receive Filter " + "Clear Filter request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + if( NULL == pSession ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Session Not find ", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pRcvFltPktClearParam->selfMacAddr, pSession->selfMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(pRcvFltPktClearParam->bssId, pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + vos_mem_copy(pRequestBuf, pRcvFltPktClearParam, sizeof(tSirRcvFltPktClearParam)); + + msg.type = WDA_RECEIVE_FILTER_CLEAR_FILTER_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + 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_RECEIVE_FILTER_CLEAR_FILTER message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} +#endif // WLAN_FEATURE_PACKET_FILTERING + +/* --------------------------------------------------------------------------- + \fn sme_PreChannelSwitchIndFullPowerCB + \brief call back function for the PMC full power request because of pre + channel switch. + \param callbackContext + \param status + ---------------------------------------------------------------------------*/ +void sme_PreChannelSwitchIndFullPowerCB(void *callbackContext, + eHalStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext; + tSirMbMsg *pMsg; + tANI_U16 msgLen; + + msgLen = (tANI_U16)(sizeof( tSirMbMsg )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL != pMsg ) + { + vos_mem_set(pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + + return; +} + +/* --------------------------------------------------------------------------- + \fn sme_PreChannelSwitchIndOffloadFullPowerCB + \brief call back function for the PMC full power request because of pre + channel switch for offload case. + \param callbackContext + \param sessionId + \param status + ---------------------------------------------------------------------------*/ +void sme_PreChannelSwitchIndOffloadFullPowerCB(void *callbackContext,tANI_U32 sessionId, + eHalStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal)callbackContext; + tSirMbMsg *pMsg; + tANI_U16 msgLen; + + msgLen = (tANI_U16)(sizeof( tSirMbMsg )); + pMsg = vos_mem_malloc(msgLen); + if ( NULL != pMsg ) + { + vos_mem_set(pMsg, msgLen, 0); + pMsg->type = pal_cpu_to_be16((tANI_U16)eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER); + pMsg->msgLen = pal_cpu_to_be16(msgLen); + status = palSendMBMessage(pMac->hHdd, pMsg); + } + + return; +} + +/* --------------------------------------------------------------------------- + \fn sme_HandlePreChannelSwitchInd + \brief Processes the indication from PE for pre-channel switch. + \param hHal + \param void *pMsgBuf to carry session id + \- The handle returned by macOpen. return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_HandlePreChannelSwitchInd(tHalHandle hHal, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tpSirSmePreSwitchChannelInd pPreSwitchChInd = (tpSirSmePreSwitchChannelInd)pMsgBuf; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + if(!pMac->psOffloadEnabled) + { + status = pmcRequestFullPower(hHal, sme_PreChannelSwitchIndFullPowerCB, + pMac, eSME_FULL_PWR_NEEDED_BY_CHANNEL_SWITCH); + } + else + { + if (NULL != pPreSwitchChInd) + { + status = pmcOffloadRequestFullPower(hHal, pPreSwitchChInd->sessionId, + sme_PreChannelSwitchIndOffloadFullPowerCB, + pMac, eSME_FULL_PWR_NEEDED_BY_CHANNEL_SWITCH); + } + else + { + smsLog(pMac, LOGE, "Empty pMsgBuf message for channel switch " + "(eWNI_SME_PRE_SWITCH_CHL_IND), nothing to process"); + } + } + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_HandlePostChannelSwitchInd + \brief Processes the indication from PE for post-channel switch. + \param hHal + \- The handle returned by macOpen. return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcRequestBmps(hHal, NULL, NULL); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + + \fn sme_IsChannelValid + + \brief To check if the channel is valid for currently established domain + This is a synchronous API. + + \param hHal - The handle returned by macOpen. + \param channel - channel to verify + + \return TRUE/FALSE, TRUE if channel is valid + + -------------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_IsChannelValid(tHalHandle hHal, tANI_U8 channel) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tANI_BOOLEAN valid = FALSE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + + valid = csrRoamIsChannelValid( pMac, channel); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (valid); +} + +/* --------------------------------------------------------------------------- + \fn sme_SetFreqBand + \brief Used to set frequency band. + \param hHal + \param sessionId - Session Identifier + \eBand band value to be configured + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetFreqBand(tHalHandle hHal, tANI_U8 sessionId, eCsrBand eBand) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrSetBand(hHal, sessionId, eBand); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_GetFreqBand + \brief Used to get the current band settings. + \param hHal + \pBand pointer to hold band value + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetFreqBand(tHalHandle hHal, eCsrBand *pBand) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + *pBand = csrGetCurrentBand( hHal ); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +#ifdef WLAN_WAKEUP_EVENTS +/****************************************************************************** + \fn sme_WakeReasonIndCallback + + \brief + a callback function called when SME received eWNI_SME_WAKE_REASON_IND event from WDA + + \param hHal - HAL handle for device + \param pMsg - Message body passed from WDA; includes Wake Reason Indication parameter + + \return eHalStatus +******************************************************************************/ +eHalStatus sme_WakeReasonIndCallback (tHalHandle hHal, void* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirWakeReasonInd *pWakeReasonInd = (tSirWakeReasonInd *)pMsg; + + if (NULL == pMsg) + { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + } + else + { + smsLog(pMac, LOG2, "SME: entering sme_WakeReasonIndCallback"); + + /* Call Wake Reason Indication callback routine. */ + if (pMac->pmc.wakeReasonIndCB != NULL) + pMac->pmc.wakeReasonIndCB(pMac->pmc.wakeReasonIndCBContext, pWakeReasonInd); + + pMac->pmc.wakeReasonIndCB = NULL; + pMac->pmc.wakeReasonIndCBContext = NULL; + + smsLog(pMac, LOG1, "Wake Reason Indication in %s(), reason=%d", __func__, pWakeReasonInd->ulReason); + } + + return(status); +} +#endif // WLAN_WAKEUP_EVENTS + + +/* --------------------------------------------------------------------------- + \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) +{ + vos_msg_t msg; + tpMaxTxPowerPerBandParams pMaxTxPowerPerBandParams = NULL; + + 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; + } + + pMaxTxPowerPerBandParams->power = dB; + pMaxTxPowerPerBandParams->bandInfo = band; + + msg.type = WDA_SET_MAX_TX_POWER_PER_BAND_REQ; + msg.reserved = 0; + msg.bodyptr = pMaxTxPowerPerBandParams; + + 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; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_SetMaxTxPower() - Set the Maximum Transmit Power + * + * @hHal: hal pointer. + * @bssid: bssid to set the power cap for + * @self_mac_addr:self mac address + * @db: power to set in dB + * + * Set the maximum transmit power dynamically. + * + * Return: eHalStatus + * + */ +eHalStatus sme_SetMaxTxPower(tHalHandle hHal, tSirMacAddr bssid, + tSirMacAddr self_mac_addr, v_S7_t db) +{ + tpAniSirGlobal mac_ptr = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *set_max_tx_pwr; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_MAXTXPOW, NO_SESSION, 0)); + smsLog(mac_ptr, LOG1, + FL("bssid :" MAC_ADDRESS_STR " self addr: "MAC_ADDRESS_STR" power %d Db"), + MAC_ADDR_ARRAY(bssid), MAC_ADDR_ARRAY(self_mac_addr), db); + + status = sme_AcquireGlobalLock(&mac_ptr->sme); + if (HAL_STATUS_SUCCESS(status)) { + set_max_tx_pwr = csrGetCommandBuffer(mac_ptr); + if (set_max_tx_pwr) { + set_max_tx_pwr->command = eSmeCommandSetMaxTxPower; + vos_mem_copy(set_max_tx_pwr->u.set_tx_max_pwr.bssid, + bssid, SIR_MAC_ADDR_LENGTH); + vos_mem_copy(set_max_tx_pwr->u.set_tx_max_pwr.self_sta_mac_addr, + self_mac_addr, SIR_MAC_ADDR_LENGTH); + set_max_tx_pwr->u.set_tx_max_pwr.power = db; + status = csrQueueSmeCommand(mac_ptr, set_max_tx_pwr, + eANI_BOOLEAN_TRUE); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(mac_ptr, LOGE, + FL("fail to send msg status = %d"), + status); + csrReleaseCommandScan(mac_ptr, set_max_tx_pwr); + } + } + else + { + smsLog(mac_ptr, LOGE, + FL("can not obtain a common buffer")); + status = eHAL_STATUS_RESOURCES; + } + sme_ReleaseGlobalLock(&mac_ptr->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_SetCustomMacAddr + + \brief Set the customer Mac Address. + + \param customMacAddr customer MAC Address + \- return eHalStatus + + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetCustomMacAddr(tSirMacAddr customMacAddr) +{ + vos_msg_t msg; + tSirMacAddr *pBaseMacAddr; + + pBaseMacAddr = vos_mem_malloc(sizeof(tSirMacAddr)); + if (NULL == pBaseMacAddr) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for pBaseMacAddr")); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(*pBaseMacAddr, customMacAddr, sizeof(tSirMacAddr)); + + msg.type = SIR_HAL_SET_BASE_MACADDR_IND; + msg.reserved = 0; + msg.bodyptr = pBaseMacAddr; + + 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 SIR_HAL_SET_BASE_MACADDR_IND message to WDA")); + vos_mem_free(pBaseMacAddr); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* ---------------------------------------------------------------------------- + \fn sme_SetTxPower + \brief Set Transmit Power dynamically. + \param hHal + \param sessionId Target Session ID + \pBSSId BSSID + \dev_mode dev_mode such as station, P2PGO, SAP + \param dBm power to set + \- return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTxPower(tHalHandle hHal, v_U8_t sessionId, + tSirMacAddr pBSSId, + tVOS_CON_MODE dev_mode, int dBm) +{ + vos_msg_t msg; + tpMaxTxPowerParams pTxParams = NULL; + v_S7_t power = (v_S7_t)dBm; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_TXPOW, sessionId, 0)); + + /* make sure there is no overflow */ + if ((int)power != dBm) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: error, invalid power = %d", __func__, dBm); + return eHAL_STATUS_FAILURE; + } + + pTxParams = vos_mem_malloc(sizeof(tMaxTxPowerParams)); + if (NULL == pTxParams) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for pTxParams", __func__); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(pTxParams->bssId, pBSSId, SIR_MAC_ADDR_LENGTH); + pTxParams->power = power; /* unit is dBm */ + pTxParams->dev_mode = dev_mode; + msg.type = WDA_SET_TX_POWER_REQ; + msg.reserved = 0; + msg.bodyptr = pTxParams; + + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: failed to post WDA_SET_TX_POWER_REQ to WDA", + __func__); + vos_mem_free(pTxParams); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_HideSSID + + \brief hide/show SSID dynamically. Note: this setting will + not persist over reboots. + + \param hHal + \param sessionId + \param ssidHidden 0 - Broadcast SSID, 1 - Disable broadcast SSID + \- return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_HideSSID(tHalHandle hHal, v_U8_t sessionId, v_U8_t ssidHidden) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tANI_U16 len; + + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + tpSirUpdateParams pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + + if(!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + if( !pSession->sessionActive ) + VOS_ASSERT(0); + + /* Create the message and send to lim */ + len = sizeof(tSirUpdateParams); + pMsg = vos_mem_malloc(len); + if ( NULL == pMsg ) + status = eHAL_STATUS_FAILURE; + else + { + vos_mem_set(pMsg, sizeof(tSirUpdateParams), 0); + pMsg->messageType = eWNI_SME_HIDE_SSID_REQ; + pMsg->length = len; + /* Data starts from here */ + pMsg->sessionId = sessionId; + pMsg->ssidHidden = ssidHidden; + status = palSendMBMessage(pMac->hHdd, pMsg); + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_SetTmLevel + \brief Set Thermal Mitigation Level to RIVA + \param hHal - The handle returned by macOpen. + \param newTMLevel - new Thermal Mitigation Level + \param tmMode - Thermal Mitigation handle mode, default 0 + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetTmLevel(tHalHandle hHal, v_U16_t newTMLevel, v_U16_t tmMode) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tAniSetTmLevelReq *setTmLevelReq = NULL; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_TMLEVEL, NO_SESSION, 0)); + if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme ) ) ) + { + setTmLevelReq = (tAniSetTmLevelReq *)vos_mem_malloc(sizeof(tAniSetTmLevelReq)); + if (NULL == setTmLevelReq) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for sme_SetTmLevel", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + setTmLevelReq->tmMode = tmMode; + setTmLevelReq->newTmLevel = newTMLevel; + + /* serialize the req through MC thread */ + vosMessage.bodyptr = setTmLevelReq; + vosMessage.type = WDA_SET_TM_LEVEL_REQ; + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &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(setTmLevelReq); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +/*--------------------------------------------------------------------------- + + \brief sme_featureCapsExchange() - SME interface to exchange capabilities between + Host and FW. + + \param hHal - HAL handle for device + + \return NONE + +---------------------------------------------------------------------------*/ +void sme_featureCapsExchange( tHalHandle hHal) +{ + v_CONTEXT_t vosContext = vos_get_global_context(VOS_MODULE_ID_SME, NULL); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CAPS_EXCH, NO_SESSION, 0)); + WDA_featureCapsExchange(vosContext); +} + +/*--------------------------------------------------------------------------- + + \brief sme_disableFeatureCapablity() - SME interface to disable Active mode + offload capability in Host. + + \param hHal - HAL handle for device + + \return NONE + +---------------------------------------------------------------------------*/ +void sme_disableFeatureCapablity(tANI_U8 feature_index) +{ + WDA_disableCapablityFeature(feature_index); +} + + + +/* --------------------------------------------------------------------------- + + \fn sme_GetDefaultCountryCode + + \brief Get the default country code from NV + + \param hHal + \param pCountry + \- return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetDefaultCountryCodeFrmNv(tHalHandle hHal, tANI_U8 *pCountry) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_DEFCCNV, NO_SESSION, 0)); + return csrGetDefaultCountryCodeFrmNv(pMac, pCountry); +} + +/* --------------------------------------------------------------------------- + + \fn sme_GetCurrentCountryCode + + \brief Get the current country code + + \param hHal + \param pCountry + \- return eHalStatus + + -------------------------------------------------------------------------------*/ +eHalStatus sme_GetCurrentCountryCode(tHalHandle hHal, tANI_U8 *pCountry) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_CURCC, NO_SESSION, 0)); + return csrGetCurrentCountryCode(pMac, pCountry); +} + +/* --------------------------------------------------------------------------- + \fn sme_transportDebug + \brief Dynamically monitoring Transport channels + Private IOCTL will query transport channel status if driver loaded + \param hHal Upper MAC context + \param displaySnapshot Display transport channel snapshot option + \param toggleStallDetect Enable stall detect feature + This feature will take effect to data performance + Not integrate till fully verification + \- return NONE + -------------------------------------------------------------------------*/ +void sme_transportDebug(tHalHandle hHal, v_BOOL_t displaySnapshot, v_BOOL_t toggleStallDetect) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return; + } + WDA_TransportChannelDebug(pMac, displaySnapshot, toggleStallDetect); +} + +/* --------------------------------------------------------------------------- + \fn sme_ResetPowerValuesFor5G + \brief Reset the power values for 5G band with NV power values. + \param hHal - HAL handle for device + \- return NONE + -------------------------------------------------------------------------*/ +void sme_ResetPowerValuesFor5G (tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT (hHal); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_RESET_PW5G, NO_SESSION, 0)); + csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_TRUE); + csrApplyPower2Current(pMac); // Store the channel+power info in the global place: Cfg +} + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamPrefer5GHz + \brief enable/disable Roam prefer 5G runtime option + This function is called through dynamic setConfig callback function + to configure the Roam prefer 5G runtime option + \param hHal - HAL handle for device + \param nRoamPrefer5GHz Enable/Disable Roam prefer 5G runtime option + \- return Success or failure + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamPrefer5GHz(tHalHandle hHal, v_BOOL_t nRoamPrefer5GHz) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_RP5G, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamPrefer5GHz is changed from %d to %d", __func__, + pMac->roam.configParam.nRoamPrefer5GHz, + nRoamPrefer5GHz); + pMac->roam.configParam.nRoamPrefer5GHz = nRoamPrefer5GHz; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_setRoamIntraBand + \brief enable/disable Intra band roaming + This function is called through dynamic setConfig callback function + to configure the intra band roaming + \param hHal - HAL handle for device + \param nRoamIntraBand Enable/Disable Intra band roaming + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_ROAMIBAND, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamIntraBand is changed from %d to %d", __func__, + pMac->roam.configParam.nRoamIntraBand, + nRoamIntraBand); + pMac->roam.configParam.nRoamIntraBand = nRoamIntraBand; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanNProbes + \brief function to update roam scan N probes + This function is called through dynamic setConfig callback function + to update roam scan N probes + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nProbes number of probe requests to be sent out + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanNProbes(tHalHandle hHal, tANI_U8 sessionId, + const v_U8_t nProbes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_N_PROBES, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanNProbes is changed from %d to %d", __func__, + pMac->roam.configParam.nProbes, + nProbes); + pMac->roam.configParam.nProbes = nProbes; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NPROBES_CHANGED); + } +#endif + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanHomeAwayTime + \brief function to update roam scan Home away time + This function is called through dynamic setConfig callback function + to update roam scan home away time + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nRoamScanAwayTime Scan home away time + \param bSendOffloadCmd If TRUE then send offload command to firmware + If FALSE then command is not sent to firmware + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanHomeAwayTime(tHalHandle hHal, + tANI_U8 sessionId, + const v_U16_t nRoamScanHomeAwayTime, + const eAniBoolean bSendOffloadCmd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_HOME_AWAY_TIME, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHomeAwayTime is changed from %d to %d", __func__, + pMac->roam.configParam.nRoamScanHomeAwayTime, + nRoamScanHomeAwayTime); + pMac->roam.configParam.nRoamScanHomeAwayTime = nRoamScanHomeAwayTime; + sme_ReleaseGlobalLock( &pMac->sme ); + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled && bSendOffloadCmd) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_HOME_AWAY_TIME_CHANGED); + } +#endif + return status; +} + +/** + * sme_ext_change_channel()- function to post send ECSA + * action frame to csr. + * @hHal: Hal context + * @channel: new channel to switch + * @session_id: senssion it should be sent on. + * + * This function is called to post ECSA frame to csr. + * + * Return: success if msg is sent else return failure + */ +eHalStatus sme_ext_change_channel(tHalHandle hHal, uint32_t channel, + uint8_t session_id) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal); + uint8_t channel_state; + + smsLog(mac_ctx, LOGE, FL(" Set Channel %d "), channel); + channel_state = + vos_nv_getChannelEnabledState(channel); + + if ((NV_CHANNEL_DISABLE == channel_state)) { + smsLog(mac_ctx, LOGE, FL(" Invalid channel %d "), channel); + return eHAL_STATUS_FAILURE; + } + + status = sme_AcquireGlobalLock(&mac_ctx->sme); + + if (eHAL_STATUS_SUCCESS == status) { + /* update the channel list to the firmware */ + status = csr_send_ext_change_channel(mac_ctx, + channel, session_id); + sme_ReleaseGlobalLock(&mac_ctx->sme); + } + + return status; +} +/* --------------------------------------------------------------------------- + \fn sme_getRoamIntraBand + \brief get Intra band roaming + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_BOOL_t sme_getRoamIntraBand(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_ROAMIBAND, NO_SESSION, 0)); + return pMac->roam.configParam.nRoamIntraBand; +} + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanNProbes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U8_t sme_getRoamScanNProbes(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nProbes; +} + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanHomeAwayTime + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U16_t sme_getRoamScanHomeAwayTime(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nRoamScanHomeAwayTime; +} + + +/* --------------------------------------------------------------------------- + \fn sme_UpdateImmediateRoamRssiDiff + \brief Update nImmediateRoamRssiDiff + This function is called through dynamic setConfig callback function + to configure nImmediateRoamRssiDiff + Usage: adb shell iwpriv wlan0 setConfig gImmediateRoamRssiDiff=[0 .. 125] + \param hHal - HAL handle for device + \param nImmediateRoamRssiDiff - minimum rssi difference between potential + candidate and current AP. + \param sessionId - Session Identifier + \- return Success or failure + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateImmediateRoamRssiDiff(tHalHandle hHal, + v_U8_t nImmediateRoamRssiDiff, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_RSSIDIFF, NO_SESSION, 0)); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set immediate roam rssi diff to %d - old value is %d - roam state is %s", + nImmediateRoamRssiDiff, + pMac->roam.configParam.nImmediateRoamRssiDiff, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pMac->roam.configParam.nImmediateRoamRssiDiff = nImmediateRoamRssiDiff; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamRssiDiff + \brief Update RoamRssiDiff + This function is called through dynamic setConfig callback function + to configure RoamRssiDiff + Usage: adb shell iwpriv wlan0 setConfig RoamRssiDiff=[0 .. 125] + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param RoamRssiDiff - minimum rssi difference between potential + candidate and current AP. + \- return Success or failure + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamRssiDiff(tHalHandle hHal, tANI_U8 sessionId, + v_U8_t RoamRssiDiff) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam rssi diff to %d - old value is %d - roam state is %s", + RoamRssiDiff, + pMac->roam.configParam.RoamRssiDiff, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_RSSI_DIFF_CHANGED); + } +#endif + return status ; +} + +/*-------------------------------------------------------------------------- + \brief sme_UpdateFastTransitionEnabled() - enable/disable Fast Transition support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isFastTransitionEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update isFastTransitionEnabled config successfully. + Other status means SME is failed to update isFastTransitionEnabled. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateFastTransitionEnabled(tHalHandle hHal, + v_BOOL_t isFastTransitionEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_FTENABLED, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: FastTransitionEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isFastTransitionEnabled, + isFastTransitionEnabled); + pMac->roam.configParam.isFastTransitionEnabled = isFastTransitionEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateWESMode + \brief Update WES Mode + This function is called through dynamic setConfig callback function + to configure isWESModeEnabled + \param hHal - HAL handle for device + \param isWESModeEnabled - WES mode + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update isWESModeEnabled config successfully. + Other status means SME is failed to update isWESModeEnabled. + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateWESMode(tHalHandle hHal, v_BOOL_t isWESModeEnabled, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set WES Mode to %d - old value is %d - roam state is %s", + isWESModeEnabled, + pMac->roam.configParam.isWESModeEnabled, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pMac->roam.configParam.isWESModeEnabled = isWESModeEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamScanControl + \brief Set roam scan control + This function is called to set roam scan control + if roam scan control is set to 0, roaming scan cache is cleared + any value other than 0 is treated as invalid value + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamScanControl(tHalHandle hHal, tANI_U8 sessionId, + v_BOOL_t roamScanControl) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_SCANCTRL, NO_SESSION, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan control to %d - old value is %d - roam state is %s", + roamScanControl, + pMac->roam.configParam.nRoamScanControl, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pMac->roam.configParam.nRoamScanControl = roamScanControl; + if ( 0 == roamScanControl) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully cleared roam scan cache"); + csrFlushCfgBgScanRoamChannelList(pMac, sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_FLUSH_CHANNEL_LIST); + } +#endif + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; +} +#endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_ESE) || (FEATURE_WLAN_LFR) */ + +#ifdef FEATURE_WLAN_LFR +/*-------------------------------------------------------------------------- + \brief sme_UpdateIsFastRoamIniFeatureEnabled() - enable/disable LFR support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isFastRoamIniFeatureEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update isFastRoamIniFeatureEnabled config successfully. + Other status means SME is failed to update isFastRoamIniFeatureEnabled. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateIsFastRoamIniFeatureEnabled +( + tHalHandle hHal, + tANI_U8 sessionId, + const v_BOOL_t isFastRoamIniFeatureEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMac->roam.configParam.isFastRoamIniFeatureEnabled == + isFastRoamIniFeatureEnabled) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: FastRoam is already enabled or disabled, nothing to do (returning) old(%d) new(%d)", __func__, + pMac->roam.configParam.isFastRoamIniFeatureEnabled, + isFastRoamIniFeatureEnabled); + return eHAL_STATUS_SUCCESS; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "%s: FastRoamEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isFastRoamIniFeatureEnabled, + isFastRoamIniFeatureEnabled); + pMac->roam.configParam.isFastRoamIniFeatureEnabled = + isFastRoamIniFeatureEnabled; + csrNeighborRoamUpdateFastRoamingEnabled(pMac, sessionId, + isFastRoamIniFeatureEnabled); + + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_UpdateIsMAWCIniFeatureEnabled() - + Enable/disable LFR MAWC support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isMAWCIniFeatureEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update MAWCEnabled config successfully. + Other status means SME is failed to update MAWCEnabled. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateIsMAWCIniFeatureEnabled(tHalHandle hHal, + const v_BOOL_t MAWCEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: MAWCEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.MAWCEnabled, + MAWCEnabled); + pMac->roam.configParam.MAWCEnabled = MAWCEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; + +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_stopRoaming() - Stop roaming for a given sessionId + This is a synchronous call + \param hHal - The handle returned by macOpen + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS on success + Other status on failure + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_stopRoaming(tHalHandle hHal, + tANI_U8 sessionId, + tANI_U8 reason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_STOP, reason); + sme_ReleaseGlobalLock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_startRoaming() - Start roaming for a given sessionId + This is a synchronous call + \param hHal - The handle returned by macOpen + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS on success + Other status on failure + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_startRoaming(tHalHandle hHal, + tANI_U8 sessionId, + tANI_U8 reason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, reason); + sme_ReleaseGlobalLock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_UpdateEnableFastRoamInConcurrency() - enable/disable LFR if Concurrent session exists + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS + Other status means SME is failed + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateEnableFastRoamInConcurrency(tHalHandle hHal, + v_BOOL_t bFastRoamInConIniFeatureEnabled) +{ + + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = bFastRoamInConIniFeatureEnabled; + if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled) + { + pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = 0; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status; +} +#endif +#endif /* FEATURE_WLAN_LFR */ + +#ifdef FEATURE_WLAN_ESE +/*-------------------------------------------------------------------------- + \brief sme_UpdateIsEseFeatureEnabled() - enable/disable ESE support at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + isEseIniFeatureEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param isEseIniFeatureEnabled - flag to enable/disable + \return eHAL_STATUS_SUCCESS - SME update isEseIniFeatureEnabled config successfully. + Other status means SME is failed to update isEseIniFeatureEnabled. + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_UpdateIsEseFeatureEnabled +( + tHalHandle hHal, + tANI_U8 sessionId, + const v_BOOL_t isEseIniFeatureEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMac->roam.configParam.isEseIniFeatureEnabled == isEseIniFeatureEnabled) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: ESE Mode is already enabled or disabled, nothing to do (returning) old(%d) new(%d)", __func__, + pMac->roam.configParam.isEseIniFeatureEnabled, + isEseIniFeatureEnabled); + return eHAL_STATUS_SUCCESS; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: EseEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isEseIniFeatureEnabled, + isEseIniFeatureEnabled); + pMac->roam.configParam.isEseIniFeatureEnabled = isEseIniFeatureEnabled; + csrNeighborRoamUpdateEseModeEnabled(pMac, sessionId, + isEseIniFeatureEnabled); + + if (TRUE == isEseIniFeatureEnabled) + { + sme_UpdateFastTransitionEnabled(hHal, TRUE); + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ESE_INI_CFG_CHANGED); + } +#endif + return eHAL_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_ESE */ + +/*-------------------------------------------------------------------------- + \brief sme_UpdateConfigFwRssiMonitoring() - enable/disable firmware RSSI Monitoring at runtime + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + fEnableFwRssiMonitoring. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update fEnableFwRssiMonitoring. config successfully. + Other status means SME is failed to update fEnableFwRssiMonitoring. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateConfigFwRssiMonitoring(tHalHandle hHal, + v_BOOL_t fEnableFwRssiMonitoring) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + + if (ccmCfgSetInt(hHal, WNI_CFG_PS_ENABLE_RSSI_MONITOR, fEnableFwRssiMonitoring, + NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) + { + halStatus = eHAL_STATUS_FAILURE; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failure: Could not pass on WNI_CFG_PS_RSSI_MONITOR configuration info to CCM"); + } + + return (halStatus); +} + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +/* --------------------------------------------------------------------------- + \fn sme_SetRoamOpportunisticScanThresholdDiff + \brief Update Opportunistic Scan threshold diff + This function is called through dynamic setConfig callback function + to configure nOpportunisticThresholdDiff + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nOpportunisticThresholdDiff - Opportunistic Scan threshold diff + \return eHAL_STATUS_SUCCESS - SME update nOpportunisticThresholdDiff config + successfully. + else SME is failed to update nOpportunisticThresholdDiff. + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamOpportunisticScanThresholdDiff(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nOpportunisticThresholdDiff) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrNeighborRoamSetOpportunisticScanThresholdDiff(pMac, + sessionId, + nOpportunisticThresholdDiff); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set " + "opportunistic threshold diff to %d" + " - old value is %d - roam state is %d", + nOpportunisticThresholdDiff, + pMac->roam.configParam.neighborRoamConfig.nOpportunisticThresholdDiff, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + pMac->roam.configParam.neighborRoamConfig.nOpportunisticThresholdDiff = nOpportunisticThresholdDiff; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamOpportunisticScanThresholdDiff() + \brief gets Opportunistic Scan threshold diff + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nOpportunisticThresholdDiff + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamOpportunisticScanThresholdDiff(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nOpportunisticThresholdDiff; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamRescanRssiDiff + \brief Update roam rescan rssi diff + This function is called through dynamic setConfig callback function + to configure nRoamRescanRssiDiff + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nRoamRescanRssiDiff - roam rescan rssi diff + \return eHAL_STATUS_SUCCESS - SME update nRoamRescanRssiDiff config + successfully. + else SME is failed to update nRoamRescanRssiDiff. + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamRescanRssiDiff(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nRoamRescanRssiDiff) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrNeighborRoamSetRoamRescanRssiDiff(pMac, sessionId, + nRoamRescanRssiDiff); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set " + "opportunistic threshold diff to %d" + " - old value is %d - roam state is %d", + nRoamRescanRssiDiff, + pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff = + nRoamRescanRssiDiff; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamRescanRssiDiff + \brief gets roam rescan rssi diff + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_S7_t - nRoamRescanRssiDiff + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamRescanRssiDiff(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamBmissFirstBcnt + \brief Update Roam count for first beacon miss + This function is called through dynamic setConfig callback function + to configure nRoamBmissFirstBcnt + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nRoamBmissFirstBcnt - Roam first bmiss count + \return eHAL_STATUS_SUCCESS - SME update nRoamBmissFirstBcnt + successfully. + else SME is failed to update nRoamBmissFirstBcnt + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamBmissFirstBcnt(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nRoamBmissFirstBcnt) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrNeighborRoamSetRoamBmissFirstBcnt(pMac, sessionId, + nRoamBmissFirstBcnt); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set " + "beacon miss first beacon count to %d" + " - old value is %d - roam state is %d", + nRoamBmissFirstBcnt, + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_GetRoamBmissFirstBcnt + \brief get neighbor roam beacon miss first count + \param hHal - The handle returned by macOpen. + \return v_U8_t - neighbor roam beacon miss first count + -------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamBmissFirstBcnt(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamBmissFinalBcnt + \brief Update Roam count for final beacon miss + This function is called through dynamic setConfig callback function + to configure nRoamBmissFinalBcnt + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nRoamBmissFinalBcnt - Roam final bmiss count + \return eHAL_STATUS_SUCCESS - SME update nRoamBmissFinalBcnt + successfully. + else SME is failed to update nRoamBmissFinalBcnt + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamBmissFinalBcnt(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nRoamBmissFinalBcnt) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrNeighborRoamSetRoamBmissFinalBcnt(pMac, sessionId, + nRoamBmissFinalBcnt); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set " + "beacon miss final beacon count to %d" + " - old value is %d - roam state is %d", + nRoamBmissFinalBcnt, + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamBmissFinalBcnt + \brief gets Roam count for final beacon miss + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nRoamBmissFinalBcnt + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamBmissFinalBcnt(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamBeaconRssiWeight + \brief Update Roam beacon rssi weight + This function is called through dynamic setConfig callback function + to configure nRoamBeaconRssiWeight + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nRoamBeaconRssiWeight - Roam beacon rssi weight + \return eHAL_STATUS_SUCCESS - SME update nRoamBeaconRssiWeight config + successfully. + else SME is failed to update nRoamBeaconRssiWeight + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamBeaconRssiWeight(tHalHandle hHal, + tANI_U8 sessionId, + const v_U8_t nRoamBeaconRssiWeight) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrNeighborRoamSetRoamBeaconRssiWeight(pMac, sessionId, + nRoamBeaconRssiWeight); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set " + "beacon miss final beacon count to %d" + " - old value is %d - roam state is %d", + nRoamBeaconRssiWeight, + pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_GetRoamBeaconRssiWeight + \brief gets Roam beacon rssi weight + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - nRoamBeaconRssiWeight + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetRoamBeaconRssiWeight(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight; +} +/*-------------------------------------------------------------------------- + \brief sme_setNeighborLookupRssiThreshold() - update neighbor lookup rssi threshold + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborLookupRssiThreshold +( + tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t neighborLookupRssiThreshold) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if (HAL_STATUS_SUCCESS(status)) + { + status = csrNeighborRoamSetLookupRssiThreshold(pMac, sessionId, + neighborLookupRssiThreshold); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set Lookup threshold to %d - old value is %d - roam state is %s", + neighborLookupRssiThreshold, + pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold = + neighborLookupRssiThreshold; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_set_delay_before_vdev_stop() - update delay before VDEV_STOP + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_set_delay_before_vdev_stop(tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t delay_before_vdev_stop) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + status = sme_AcquireGlobalLock( &pMac->sme ); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, + VOS_TRACE_LEVEL_DEBUG, + FL("LFR param delay_before_vdev_stop changed from %d to %d"), + pMac->roam.configParam.neighborRoamConfig.delay_before_vdev_stop, + delay_before_vdev_stop); + + pMac->roam.neighborRoamInfo[sessionId].cfgParams.delay_before_vdev_stop = + delay_before_vdev_stop; + pMac->roam.configParam.neighborRoamConfig.delay_before_vdev_stop = + delay_before_vdev_stop; + sme_ReleaseGlobalLock( &pMac->sme ); + } + return eHAL_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_setNeighborReassocRssiThreshold() - update neighbor reassoc rssi threshold + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborReassocRssiThreshold +( + tHalHandle hHal, + tANI_U8 sessionId, + v_U8_t neighborReassocRssiThreshold) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if (HAL_STATUS_SUCCESS(status)) + { + pNeighborRoamConfig = &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set Reassoc threshold to %d- old value is %d - roam state is %s", + neighborReassocRssiThreshold, + pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pNeighborRoamConfig->nNeighborReassocRssiThreshold = + neighborReassocRssiThreshold; + pNeighborRoamInfo->cfgParams.neighborReassocThreshold = + neighborReassocRssiThreshold; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + + +/*-------------------------------------------------------------------------- + \brief sme_getNeighborLookupRssiThreshold() - get neighbor lookup rssi threshold + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_getNeighborLookupRssiThreshold(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold; +} + +/*-------------------------------------------------------------------------- + \brief sme_setNeighborScanRefreshPeriod() - set neighbor scan results refresh period + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanRefreshPeriod +( + tHalHandle hHal, + tANI_U8 sessionId, + v_U16_t neighborScanResultsRefreshPeriod) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pNeighborRoamConfig = &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan refresh period to %d- old value is %d - roam state is %s", + neighborScanResultsRefreshPeriod, + pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pNeighborRoamConfig->nNeighborResultsRefreshPeriod = + neighborScanResultsRefreshPeriod; + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod = + neighborScanResultsRefreshPeriod; + + sme_ReleaseGlobalLock( &pMac->sme ); + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED); + } +#endif + return status ; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamScanOffloadEnabled() - + Enable/disable roam scan offload feature + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, + v_BOOL_t nRoamScanOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + FL("gRoamScanOffloadEnabled is changed from %d to %d"), + pMac->roam.configParam.isRoamOffloadScanEnabled, + nRoamScanOffloadEnabled); + pMac->roam.configParam.isRoamOffloadScanEnabled = + nRoamScanOffloadEnabled; + sme_ReleaseGlobalLock(&pMac->sme); + } + + return status ; +} +#endif + +/*-------------------------------------------------------------------------- + \brief sme_getNeighborScanRefreshPeriod() - get neighbor scan results refresh period + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_U16_t - Neighbor scan results refresh period value + \sa + --------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanRefreshPeriod(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod; +} + +/*-------------------------------------------------------------------------- + \brief sme_getEmptyScanRefreshPeriod() - get empty scan refresh period + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +v_U16_t sme_getEmptyScanRefreshPeriod(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateEmptyScanRefreshPeriod + \brief Update nEmptyScanRefreshPeriod + This function is called through dynamic setConfig callback function + to configure nEmptyScanRefreshPeriod + Usage: adb shell iwpriv wlan0 setConfig nEmptyScanRefreshPeriod=[0 .. 60] + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nEmptyScanRefreshPeriod - scan period following empty scan results. + \- return Success or failure + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateEmptyScanRefreshPeriod(tHalHandle hHal, tANI_U8 sessionId, + v_U16_t nEmptyScanRefreshPeriod) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pNeighborRoamConfig = &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan period to %d -old value is %d - roam state is %s", + nEmptyScanRefreshPeriod, + pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pNeighborRoamConfig->nEmptyScanRefreshPeriod = nEmptyScanRefreshPeriod; + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod = + nEmptyScanRefreshPeriod; + sme_ReleaseGlobalLock( &pMac->sme ); + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_EMPTY_SCAN_REF_PERIOD_CHANGED); + } +#endif + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_setNeighborScanMinChanTime + \brief Update nNeighborScanMinChanTime + This function is called through dynamic setConfig callback function + to configure gNeighborScanChannelMinTime + Usage: adb shell iwpriv wlan0 setConfig gNeighborScanChannelMinTime=[0 .. 60] + \param hHal - HAL handle for device + \param nNeighborScanMinChanTime - Channel minimum dwell time + \param sessionId - Session Identifier + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanMinChanTime(tHalHandle hHal, + const v_U16_t nNeighborScanMinChanTime, + tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set channel min dwell time to %d - old value is %d - roam state is %s", + nNeighborScanMinChanTime, + pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + + pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime = + nNeighborScanMinChanTime; + pMac->roam.neighborRoamInfo[sessionId].cfgParams.minChannelScanTime = + nNeighborScanMinChanTime; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_setNeighborScanMaxChanTime + \brief Update nNeighborScanMaxChanTime + This function is called through dynamic setConfig callback function + to configure gNeighborScanChannelMaxTime + Usage: adb shell iwpriv wlan0 setConfig gNeighborScanChannelMaxTime=[0 .. 60] + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nNeighborScanMinChanTime - Channel maximum dwell time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanMaxChanTime(tHalHandle hHal, tANI_U8 sessionId, + const v_U16_t nNeighborScanMaxChanTime) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pNeighborRoamConfig = &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set channel max dwell time to %d - old value is %d - roam state is %s", + nNeighborScanMaxChanTime, + pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pNeighborRoamConfig->nNeighborScanMaxChanTime = + nNeighborScanMaxChanTime; + pNeighborRoamInfo->cfgParams.maxChannelScanTime = + nNeighborScanMaxChanTime; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_SCAN_CH_TIME_CHANGED); + } +#endif + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborScanMinChanTime + \brief get neighbor scan min channel time + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U16_t - channel min time value + -------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanMinChanTime(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.neighborRoamInfo[sessionId].cfgParams.minChannelScanTime; +} + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborRoamState + \brief get neighbor roam state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - neighbor roam state + -------------------------------------------------------------------------*/ +v_U32_t sme_getNeighborRoamState(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.neighborRoamInfo[sessionId].neighborRoamState; +} + +/* --------------------------------------------------------------------------- + \fn sme_getCurrentRoamState + \brief get current roam state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - current roam state + -------------------------------------------------------------------------*/ +v_U32_t sme_getCurrentRoamState(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.curState[sessionId]; +} + +/* --------------------------------------------------------------------------- + \fn sme_getCurrentRoamSubState + \brief get neighbor roam sub state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - current roam sub state + -------------------------------------------------------------------------*/ +v_U32_t sme_getCurrentRoamSubState(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.curSubState[sessionId]; +} + +/* --------------------------------------------------------------------------- + \fn sme_getLimSmeState + \brief get Lim Sme state + \param hHal - The handle returned by macOpen. + \return v_U32_t - Lim Sme state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimSmeState(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gLimSmeState; +} + +/* --------------------------------------------------------------------------- + \fn sme_getLimMlmState + \brief get Lim Mlm state + \param hHal - The handle returned by macOpen. + \return v_U32_t - Lim Mlm state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimMlmState(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gLimMlmState; +} + +/* --------------------------------------------------------------------------- + \fn sme_IsLimSessionValid + \brief is Lim session valid + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_BOOL_t - true or false + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsLimSessionValid(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (sessionId > pMac->lim.maxBssId) { + smsLog(pMac, LOG1, FL("invalid sessionId:%d"), sessionId); + return FALSE; + } + + return pMac->lim.gpSession[sessionId].valid; +} + +/* --------------------------------------------------------------------------- + \fn sme_getLimSmeSessionState + \brief get Lim Sme session state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - Lim Sme session state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimSmeSessionState(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gpSession[sessionId].limSmeState; +} + +/* --------------------------------------------------------------------------- + \fn sme_getLimMlmSessionState + \brief get Lim Mlm session state + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U32_t - Lim Mlm session state + -------------------------------------------------------------------------*/ +v_U32_t sme_getLimMlmSessionState(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gpSession[sessionId].limMlmState; +} + + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborScanMaxChanTime + \brief get neighbor scan max channel time + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U16_t - channel max time value + -------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanMaxChanTime(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.neighborRoamInfo[sessionId].cfgParams.maxChannelScanTime; +} + +/* --------------------------------------------------------------------------- + \fn sme_setNeighborScanPeriod + \brief Update nNeighborScanPeriod + This function is called through dynamic setConfig callback function + to configure nNeighborScanPeriod + Usage: adb shell iwpriv wlan0 setConfig nNeighborScanPeriod=[0 .. 1000] + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param nNeighborScanPeriod - neighbor scan period + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_setNeighborScanPeriod(tHalHandle hHal, tANI_U8 sessionId, + const v_U16_t nNeighborScanPeriod) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pNeighborRoamConfig = &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set neighbor scan period to %d" + " - old value is %d - roam state is %s", + nNeighborScanPeriod, + pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pNeighborRoamConfig->nNeighborScanTimerPeriod = nNeighborScanPeriod; + pNeighborRoamInfo->cfgParams.neighborScanPeriod = nNeighborScanPeriod; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_SCAN_HOME_TIME_CHANGED); + } +#endif + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_getNeighborScanPeriod + \brief get neighbor scan period + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return v_U16_t - neighbor scan period + -------------------------------------------------------------------------*/ +v_U16_t sme_getNeighborScanPeriod(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.neighborRoamInfo[sessionId].cfgParams.neighborScanPeriod; +} + +#endif + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + +/*-------------------------------------------------------------------------- + \brief sme_getRoamRssiDiff() - get Roam rssi diff + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_U16_t - Rssi diff value + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_getRoamRssiDiff(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.RoamRssiDiff; +} + +/*-------------------------------------------------------------------------- + \brief sme_ChangeRoamScanChannelList() - Change roam scan channel list + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param pChannelList - Output channel list + \param numChannels - Output number of channels + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 *pChannelList, + tANI_U8 numChannels) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tANI_U8 oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN*2] = {0}; + tANI_U8 newChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN*2] = {0}; + tANI_U8 i = 0, j = 0; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + { + for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) + { + if (j < sizeof(oldChannelList)) + { + j += snprintf(oldChannelList + j, sizeof(oldChannelList) - j," %d", + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); + } + else + { + break; + } + } + } + csrFlushCfgBgScanRoamChannelList(pMac, sessionId); + csrCreateBgScanRoamChannelList(pMac, sessionId, pChannelList, + numChannels); + sme_SetRoamScanControl(hHal, sessionId, 1); + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + { + j = 0; + for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) + { + if (j < sizeof(newChannelList)) + { + j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); + } + else + { + break; + } + } + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", + newChannelList, oldChannelList, + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + } +#endif + + return status ; +} + +#ifdef FEATURE_WLAN_ESE_UPLOAD +/*-------------------------------------------------------------------------- + \brief sme_SetEseRoamScanChannelList() - set ese roam scan channel list + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param pChannelList - Input channel list + \param numChannels - Input number of channels + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_SetEseRoamScanChannelList(tHalHandle hHal, + tANI_U8 sessionId, + tANI_U8 *pChannelList, + tANI_U8 numChannels) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo + = &pMac->roam.neighborRoamInfo[sessionId]; + tpCsrChannelInfo currChannelListInfo + = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + tANI_U8 oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN*2] = {0}; + tANI_U8 newChannelList[128] = {0}; + tANI_U8 i = 0, j = 0; + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if (NULL != currChannelListInfo->ChannelList) + { + for (i = 0; i < currChannelListInfo->numOfChannels; i++) + { + j += snprintf(oldChannelList + j, + sizeof(oldChannelList) - j, + " %d", + currChannelListInfo->ChannelList[i]); + } + } + status = csrCreateRoamScanChannelList(pMac, sessionId, pChannelList, + numChannels, csrGetCurrentBand(hHal)); + if ( HAL_STATUS_SUCCESS( status )) + { + if (NULL != currChannelListInfo->ChannelList) + { + j = 0; + for (i = 0; i < currChannelListInfo->numOfChannels; i++) + { + j += snprintf(newChannelList + j, + sizeof(newChannelList) - j, + " %d", + currChannelListInfo->ChannelList[i]); + } + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, +"ESE roam scan channel list successfully set to \ +%s - old value is %s - roam state is %d", + newChannelList, oldChannelList, + pNeighborRoamInfo->neighborRoamState); + } + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + } +#endif + return status ; +} +#endif + +/*-------------------------------------------------------------------------- + \brief sme_getRoamScanChannelList() - get roam scan channel list + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param pChannelList - Output channel list + \param numChannels - Output number of channels + \param sessionId - Session Identifier + \return eHAL_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, + tANI_U8 *pNumChannels, tANI_U8 sessionId) +{ + int i = 0; + tANI_U8 *pOutPtr = pChannelList; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "Roam Scan channel list is NOT yet initialized"); + *pNumChannels = 0; + sme_ReleaseGlobalLock( &pMac->sme ); + return status; + } + + *pNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; + for (i = 0; i < (*pNumChannels); i++) + { + pOutPtr[i] = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]; + } + pOutPtr[i] = '\0'; + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; +} + +/*-------------------------------------------------------------------------- + \brief sme_getIsEseFeatureEnabled() - get ESE feature enabled or not + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return TRUE (1) - if the ESE feature is enabled + FALSE (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_getIsEseFeatureEnabled(tHalHandle hHal) +{ +#ifdef FEATURE_WLAN_ESE + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return csrRoamIsEseIniFeatureEnabled(pMac); +#else + return eANI_BOOLEAN_FALSE; +#endif +} + +/*-------------------------------------------------------------------------- + \brief sme_GetWESMode() - get WES Mode + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetWESMode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.isWESModeEnabled; +} + +/*-------------------------------------------------------------------------- + \brief sme_GetRoamScanControl() - get scan control + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_BOOL_t - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetRoamScanControl(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nRoamScanControl; +} +#endif + +/*-------------------------------------------------------------------------- + \brief sme_getIsLfrFeatureEnabled() - get LFR feature enabled or not + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return TRUE (1) - if the feature is enabled + FALSE (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_getIsLfrFeatureEnabled(tHalHandle hHal) +{ +#ifdef FEATURE_WLAN_LFR + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.isFastRoamIniFeatureEnabled; +#else + return eANI_BOOLEAN_FALSE; +#endif +} + +/*-------------------------------------------------------------------------- + \brief sme_getIsFtFeatureEnabled() - get FT feature enabled or not + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return TRUE (1) - if the feature is enabled + FALSE (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_getIsFtFeatureEnabled(tHalHandle hHal) +{ +#ifdef WLAN_FEATURE_VOWIFI_11R + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.isFastTransitionEnabled; +#else + return eANI_BOOLEAN_FALSE; +#endif +} + + +/* --------------------------------------------------------------------------- + \fn sme_IsFeatureSupportedByFW + \brief Check if an feature is enabled by FW + + \param feattEnumValue - Enumeration value from placeHolderInCapBitmap + \- return 1/0 (TRUE/FALSE) + -------------------------------------------------------------------------*/ +tANI_U8 sme_IsFeatureSupportedByFW(tANI_U8 featEnumValue) +{ + return IS_FEATURE_SUPPORTED_BY_FW(featEnumValue); +} +#ifdef FEATURE_WLAN_TDLS + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsLinkEstablishParams + \brief API to send TDLS Peer Link Establishment Parameters. + + \param peerMac - peer's Mac Address. + \param tdlsLinkEstablishParams - TDLS Peer Link Establishment Parameters + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_SendTdlsLinkEstablishParams(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams *tdlsLinkEstablishParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_LINK_ESTABLISH_PARAM, + sessionId, tdlsLinkEstablishParams->isOffChannelSupported)); + status = sme_AcquireGlobalLock( &pMac->sme ); + + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrTdlsSendLinkEstablishParams(hHal, sessionId, peerMac, tdlsLinkEstablishParams) ; + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsMgmtFrame + \brief API to send TDLS management frames. + + \param peerMac - peer's Mac Address. + \param frame_type - Type of TDLS mgmt frame to be sent. + \param dialog - dialog token used in the frame. + \param status - status to be included in the frame. + \param peerCapability - peer capabilities + \param buf - additional IEs to be included + \param len - length of additional Ies + \param responder - Tdls request type + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_SendTdlsMgmtFrame(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac, tANI_U8 frame_type, + tANI_U8 dialog, tANI_U16 statusCode, + tANI_U32 peerCapability, tANI_U8 *buf, + tANI_U8 len, tANI_U8 responder) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrTdlsSendMgmt sendTdlsReq = {{0}} ; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_SEND_MGMT_FRAME, + sessionId, statusCode)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + vos_mem_copy(sendTdlsReq.peerMac, peerMac, sizeof(tSirMacAddr)) ; + sendTdlsReq.frameType = frame_type; + sendTdlsReq.buf = buf; + sendTdlsReq.len = len; + sendTdlsReq.dialog = dialog; + sendTdlsReq.statusCode = statusCode; + sendTdlsReq.responder = responder; + sendTdlsReq.peerCapability = peerCapability; + + status = csrTdlsSendMgmtReq(hHal, sessionId, &sendTdlsReq) ; + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; + +} +/* --------------------------------------------------------------------------- + \fn sme_ChangeTdlsPeerSta + \brief API to Update TDLS peer sta parameters. + + \param peerMac - peer's Mac Address. + \param staParams - Peer Station Parameters + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_ChangeTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pstaParams) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s :pstaParams is NULL",__func__); + return eHAL_STATUS_FAILURE; + } + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_CHANGE_PEER_STA, sessionId, + pstaParams->capability)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrTdlsChangePeerSta(hHal, sessionId, peerMac, pstaParams); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; + +} + +/* --------------------------------------------------------------------------- + \fn sme_AddTdlsPeerSta + \brief API to Add TDLS peer sta entry. + + \param peerMac - peer's Mac Address. + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_AddTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, + const tSirMacAddr peerMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_ADD_PEER_STA, + sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrTdlsAddPeerSta(hHal, sessionId, peerMac); + + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; + +} +/* --------------------------------------------------------------------------- + \fn sme_DeleteTdlsPeerSta + \brief API to Delete TDLS peer sta entry. + + \param peerMac - peer's Mac Address. + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, + tANI_U8 sessionId, + const tSirMacAddr peerMac) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_DEL_PEER_STA, + sessionId, 0)); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrTdlsDelPeerSta(hHal, sessionId, peerMac) ; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; + +} +/* --------------------------------------------------------------------------- + \fn sme_SetTdlsPowerSaveProhibited + \API to set/reset the isTdlsPowerSaveProhibited. + + \- return void + -------------------------------------------------------------------------*/ +void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t val) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (!pMac->psOffloadEnabled) + { + pMac->isTdlsPowerSaveProhibited = val; + } + else + { + pmcOffloadSetTdlsProhibitBmpsStatus(hHal, sessionId, val); + } + smsLog(pMac, LOG1, FL("isTdlsPowerSaveProhibited is %d"), + pMac->isTdlsPowerSaveProhibited); + return; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateFwTdlsState + + \brief + SME will send message to WMA to set TDLS state in f/w + + \param + + hHal - The handle returned by macOpen + + psmeTdlsParams - TDLS state info to update in f/w + + useSmeLock - Need to acquire SME Global Lock before state update or not + + \return eHalStatus +--------------------------------------------------------------------------- */ +eHalStatus sme_UpdateFwTdlsState(tHalHandle hHal, void *psmeTdlsParams, + tANI_BOOLEAN useSmeLock) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = NULL; + vos_msg_t vosMessage; + + /* only acquire sme global lock before state update if asked to */ + if (useSmeLock) { + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) + return eHAL_STATUS_FAILURE; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS != status) + return status; + } + + /* serialize the req through MC thread */ + vosMessage.bodyptr = psmeTdlsParams; + vosMessage.type = WDA_UPDATE_FW_TDLS_STATE; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + /* release the lock if it was acquired */ + if (useSmeLock) + sme_ReleaseGlobalLock(&pMac->sme); + + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateTdlsPeerState + + \brief + SME will send message to WMA to set TDLS Peer state in f/w + + \param + + hHal - The handle returned by macOpen + + peerStateParams - TDLS Peer state info to update in f/w + + \return eHalStatus +--------------------------------------------------------------------------- */ +eHalStatus sme_UpdateTdlsPeerState(tHalHandle hHal, + tSmeTdlsPeerStateParams *peerStateParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tTdlsPeerStateParams *pTdlsPeerStateParams = NULL; + vos_msg_t vosMessage; + tANI_U8 num; + tANI_U8 chanId; + tANI_U8 i; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + pTdlsPeerStateParams = vos_mem_malloc(sizeof(*pTdlsPeerStateParams)); + if (NULL == pTdlsPeerStateParams) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: failed to allocate mem for tdls peer state param", + __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(pTdlsPeerStateParams, sizeof(*pTdlsPeerStateParams)); + vos_mem_copy(&pTdlsPeerStateParams->peerMacAddr, + &peerStateParams->peerMacAddr, + sizeof(tSirMacAddr)); + pTdlsPeerStateParams->vdevId = peerStateParams->vdevId; + pTdlsPeerStateParams->peerState = peerStateParams->peerState; + + switch (peerStateParams->peerState) + { + case eSME_TDLS_PEER_STATE_PEERING: + pTdlsPeerStateParams->peerState = WDA_TDLS_PEER_STATE_PEERING; + break; + + case eSME_TDLS_PEER_STATE_CONNECTED: + pTdlsPeerStateParams->peerState = WDA_TDLS_PEER_STATE_CONNECTED; + break; + + case eSME_TDLS_PEER_STATE_TEARDOWN: + pTdlsPeerStateParams->peerState = WDA_TDLS_PEER_STATE_TEARDOWN; + break; + + case eSME_TDLS_PEER_ADD_MAC_ADDR: + pTdlsPeerStateParams->peerState = WDA_TDLS_PEER_ADD_MAC_ADDR; + break; + + case eSME_TDLS_PEER_REMOVE_MAC_ADDR: + pTdlsPeerStateParams->peerState = WDA_TDLS_PEER_REMOVE_MAC_ADDR; + break; + + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid peer state param (%d)", + __func__, peerStateParams->peerState); + vos_mem_free(pTdlsPeerStateParams); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + pTdlsPeerStateParams->peerCap.isPeerResponder = + peerStateParams->peerCap.isPeerResponder; + pTdlsPeerStateParams->peerCap.peerUapsdQueue = + peerStateParams->peerCap.peerUapsdQueue; + pTdlsPeerStateParams->peerCap.peerMaxSp = + peerStateParams->peerCap.peerMaxSp; + pTdlsPeerStateParams->peerCap.peerBuffStaSupport = + peerStateParams->peerCap.peerBuffStaSupport; + pTdlsPeerStateParams->peerCap.peerOffChanSupport = + peerStateParams->peerCap.peerOffChanSupport; + pTdlsPeerStateParams->peerCap.peerCurrOperClass = + peerStateParams->peerCap.peerCurrOperClass; + pTdlsPeerStateParams->peerCap.selfCurrOperClass = + peerStateParams->peerCap.selfCurrOperClass; + + num = 0; + for (i = 0; i < peerStateParams->peerCap.peerChanLen; i++) + { + chanId = peerStateParams->peerCap.peerChan[i]; + if (csrRoamIsChannelValid(pMac, chanId)) + { + pTdlsPeerStateParams->peerCap.peerChan[num].chanId = chanId; + pTdlsPeerStateParams->peerCap.peerChan[num].pwr = + csrGetCfgMaxTxPower(pMac, chanId); + + if (vos_nv_getChannelEnabledState(chanId) == NV_CHANNEL_DFS) + { + pTdlsPeerStateParams->peerCap.peerChan[num].dfsSet = + VOS_TRUE; + } + else + { + pTdlsPeerStateParams->peerCap.peerChan[num].dfsSet = + VOS_FALSE; + } + num++; + } + } + pTdlsPeerStateParams->peerCap.peerChanLen = num; + + pTdlsPeerStateParams->peerCap.peerOperClassLen = + peerStateParams->peerCap.peerOperClassLen; + for (i = 0; i < HAL_TDLS_MAX_SUPP_OPER_CLASSES; i++) + { + pTdlsPeerStateParams->peerCap.peerOperClass[i] = + peerStateParams->peerCap.peerOperClass[i]; + } + + pTdlsPeerStateParams->peerCap.prefOffChanNum = + peerStateParams->peerCap.prefOffChanNum; + pTdlsPeerStateParams->peerCap.prefOffChanBandwidth = + peerStateParams->peerCap.prefOffChanBandwidth; + pTdlsPeerStateParams->peerCap.opClassForPrefOffChan = + peerStateParams->peerCap.opClassForPrefOffChan; + + vosMessage.type = WDA_UPDATE_TDLS_PEER_STATE; + vosMessage.reserved = 0; + vosMessage.bodyptr = pTdlsPeerStateParams; + + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + vos_mem_free(pTdlsPeerStateParams); + status = eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsChanSwitchReq + \brief API to send TDLS channel switch parameters to WMA. + + \param hHal - Umac handle. + \param chanSwitchParams- vdev, channel, offset, mode, peerMac + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +eHalStatus sme_SendTdlsChanSwitchReq(tHalHandle hHal, + tSmeTdlsChanSwitchParams *chanSwitchParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tTdlsChanSwitchParams *pTdlsChanSwitchParams = NULL; + vos_msg_t vosMessage; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_CHAN_SWITCH_REQ, NO_SESSION, + chanSwitchParams->tdls_off_channel)); + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + pTdlsChanSwitchParams = vos_mem_malloc(sizeof(*pTdlsChanSwitchParams)); + if (NULL == pTdlsChanSwitchParams) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("failed to allocate mem for tdls chan switch param")); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(pTdlsChanSwitchParams, sizeof(*pTdlsChanSwitchParams)); + + switch (chanSwitchParams->tdls_off_ch_mode) + { + case ENABLE_CHANSWITCH: + pTdlsChanSwitchParams->tdlsSwMode = + WDA_TDLS_ENABLE_OFFCHANNEL; + break; + + case DISABLE_CHANSWITCH: + pTdlsChanSwitchParams->tdlsSwMode = + WDA_TDLS_DISABLE_OFFCHANNEL; + break; + + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("invalid off channel command (%d)"), + chanSwitchParams->tdls_off_ch_mode); + vos_mem_free(pTdlsChanSwitchParams); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(&pTdlsChanSwitchParams->peerMacAddr, + &chanSwitchParams->peer_mac_addr, + sizeof(tSirMacAddr)); + pTdlsChanSwitchParams->vdevId = + chanSwitchParams->vdev_id; + pTdlsChanSwitchParams->tdlsOffCh = + chanSwitchParams->tdls_off_channel; + pTdlsChanSwitchParams->tdlsOffChBwOffset = + chanSwitchParams->tdls_off_ch_bw_offset; + pTdlsChanSwitchParams->is_responder= + chanSwitchParams->is_responder; + pTdlsChanSwitchParams->operClass = chanSwitchParams->opclass; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Country Code=%s, Requested offset=%d, Selected Operating Class=%d"), + pMac->scan.countryCodeCurrent, + pTdlsChanSwitchParams->tdlsOffChBwOffset, + pTdlsChanSwitchParams->operClass); + + vosMessage.type = WDA_TDLS_SET_OFFCHAN_MODE; + vosMessage.reserved = 0; + vosMessage.bodyptr = pTdlsChanSwitchParams; + + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Message Post failed status=%d"), vosStatus); + vos_mem_free(pTdlsChanSwitchParams); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); +} +#endif /* FEATURE_WLAN_TDLS */ + +eHalStatus sme_GetLinkSpeed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq, void *plsContext, + void (*pCallbackfn)(tSirLinkSpeedInfo *indParam, void *pContext) ) +{ + + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + if ( (NULL == pCallbackfn) && + (NULL == pMac->sme.pLinkSpeedIndCb)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Indication Call back did not registered", __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + else if (NULL != pCallbackfn) + { + pMac->sme.pLinkSpeedCbContext = plsContext; + pMac->sme.pLinkSpeedIndCb = pCallbackfn; + } + /* serialize the req through MC thread */ + vosMessage.bodyptr = lsReq; + vosMessage.type = WDA_GET_LINK_SPEED; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Link Speed msg fail", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); +} + + +/** + * sme_get_rssi() - get station's rssi + * @hal: hal interface + * @req: get rssi request information + * @context: event handle context + * @pcallbackfn: callback function pointer + * + * This function will send WDA_GET_RSSI to WMA + * + * Return: 0 on success, otherwise error value + */ +eHalStatus sme_get_rssi(tHalHandle hal, struct sir_rssi_req req, + void *context, + void (*callbackfn)(struct sir_rssi_resp *param, + void *pcontext)) +{ + + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosstatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vosmessage; + + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + if (NULL == callbackfn) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Indication Call back is NULL", + __func__); + sme_ReleaseGlobalLock(&mac->sme); + return eHAL_STATUS_FAILURE; + } + + mac->sme.pget_rssi_ind_cb = callbackfn; + mac->sme.pget_rssi_cb_context = context; + + /* serialize the req through MC thread */ + vosmessage.bodyptr = vos_mem_malloc(sizeof(req)); + if (NULL == vosmessage.bodyptr) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation failed.", __func__); + sme_ReleaseGlobalLock(&mac->sme); + return eHAL_STATUS_E_MALLOC_FAILED; + } + vos_mem_copy(vosmessage.bodyptr, &req, sizeof(req)); + vosmessage.type = WDA_GET_RSSI; + vosstatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosmessage); + if (!VOS_IS_STATUS_SUCCESS(vosstatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post get rssi msg fail", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_IsPmcBmps + \API to Check if PMC state is BMPS. + + \- return v_BOOL_t + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsPmcBmps(tHalHandle hHal) +{ + return (BMPS == pmcGetPmcState(hHal)); +} + + +eHalStatus sme_UpdateDfsSetting(tHalHandle hHal, tANI_U8 fUpdateEnableDFSChnlScan) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->scan.fEnableDFSChnlScan = fUpdateEnableDFSChnlScan; + sme_ReleaseGlobalLock( &pMac->sme ); + } + smsLog(pMac, LOG2, FL("exit status %d"), status); + + return (status); +} + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_UpdateEnableSSR(tHalHandle hHal, tANI_BOOLEAN enableSSR) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "SSR level is changed %d", enableSSR); + /* not serializing this message, as this is only going + * to set a variable in WDA/WDI + */ + WDA_SetEnableSSR(enableSSR); + sme_ReleaseGlobalLock(&pMac->sme); + } + return; +} + +/* + * SME API to stringify bonding mode. (hostapd convention) + */ + +static const char* sme_CBMode2String( tANI_U32 mode) +{ + switch (mode) + { + case eCSR_INI_SINGLE_CHANNEL_CENTERED: + return "HT20"; + case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY: + return "HT40-"; /* lower secondary channel */ + case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY: + return "HT40+"; /* upper secondary channel */ +#ifdef WLAN_FEATURE_11AC + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + return "VHT80+40+"; /* upper secondary channels */ + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + return "VHT80+40-"; /* 1 lower and 2 upper secondary channels */ + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + return "VHT80-40+"; /* 2 lower and 1 upper secondary channels */ + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + return "VHT80-40-"; /* lower secondary channels */ +#endif + default: + VOS_ASSERT(0); + return "Unknown"; + } +} + +/* + * SME API to adjust bonding mode to regulatory, dfs nol .. etc. + * + */ +static VOS_STATUS sme_AdjustCBMode(tAniSirGlobal* pMac, + tSmeConfigParams *smeConfig, + uint8_t channel, uint16_t *vht_channel_width) +{ + + const tANI_U8 step = 4; + tANI_U8 i, startChan = channel, chanCnt = 0, chanBitmap = 0; + tANI_BOOLEAN violation = VOS_FALSE; + tANI_U32 newMode, mode; + tANI_U8 center_chan = channel; + /* to validate 40MHz channels against the regulatory domain */ + tANI_BOOLEAN ht40_phymode = VOS_FALSE; + + /* get the bonding mode */ + mode = (channel <= 14) ? smeConfig->csrConfig.channelBondingMode24GHz : + smeConfig->csrConfig.channelBondingMode5GHz; + newMode = mode; + + /* get the channels */ + switch (mode) + { + case eCSR_INI_SINGLE_CHANNEL_CENTERED: + startChan = channel; + chanCnt = 1; + break; + case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY: + startChan = channel - step; + chanCnt = 2; + center_chan = channel - CSR_CB_CENTER_CHANNEL_OFFSET; + ht40_phymode = VOS_TRUE; + break; + case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY: + startChan = channel; + chanCnt=2; + center_chan = channel + CSR_CB_CENTER_CHANNEL_OFFSET; + ht40_phymode = VOS_TRUE; + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + startChan = channel; + chanCnt = 4; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + startChan = channel - step; + chanCnt = 4; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + startChan = channel - 2*step; + chanCnt = 4; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + startChan = channel - 3*step; + chanCnt = 4; + break; +#endif + default: + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* find violation; also map valid channels to a bitmap */ + for (i = 0; i < chanCnt; i++) { + if (csrIsValidChannel(pMac, (startChan + (i * step))) == + VOS_STATUS_SUCCESS) + chanBitmap = chanBitmap | 1 << i; + else + violation = VOS_TRUE; + } + + /* validate if 40MHz channel is allowed */ + if (ht40_phymode) { + if (!csrRoamIsValid40MhzChannel(pMac, center_chan)) + violation = VOS_TRUE; + } + + /* no channels are valid */ + if (chanBitmap == 0) + { + /* never be in this case */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("channel %d %s is not supported"), + channel, + sme_CBMode2String(mode)); + return VOS_STATUS_E_INVAL; + } + + /* fix violation */ + if (violation) + { + const tANI_U8 lowerMask = 0x03, upperMask = 0x0c; + /* fall back to single channel in all exception cases */ + newMode = eCSR_INI_SINGLE_CHANNEL_CENTERED; + + switch (mode) + { + case eCSR_INI_SINGLE_CHANNEL_CENTERED: + /* fall thru */ + case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY: + /* fall thru */ + case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY: + break; +#ifdef WLAN_FEATURE_11AC + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + if ((chanBitmap & lowerMask) == lowerMask) + newMode = eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + if ((chanBitmap & lowerMask) == lowerMask) + newMode = eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + if ((chanBitmap & upperMask) == upperMask) + newMode = eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + break; + case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + if ((chanBitmap & upperMask) == upperMask) + newMode = eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + break; +#endif + default: + return VOS_STATUS_E_NOSUPPORT; + break; + } + + if (eCSR_INI_SINGLE_CHANNEL_CENTERED == newMode) { + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + } else { + *vht_channel_width = eHT_CHANNEL_WIDTH_40MHZ; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("bonding mode adjust: %s to %s"), + sme_CBMode2String(mode), + sme_CBMode2String(newMode)); + } + + /* check for mode change */ + if (newMode != mode) + { + if (channel <= 14) + smeConfig->csrConfig.channelBondingMode24GHz = newMode; + else + smeConfig->csrConfig.channelBondingMode5GHz = newMode; + } + + return VOS_STATUS_SUCCESS; + +} + +/* + * SME API to determine the channel bonding mode + */ +eIniChanBondState sme_SelectCBMode(tHalHandle hHal, eCsrPhyMode eCsrPhyMode, + uint8_t channel, uint8_t ht_sec_ch, + uint16_t *vht_channel_width, + uint16_t ch_width_orig) +{ + tSmeConfigParams smeConfig; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eIniChanBondState cb_mode = eCSR_INI_SINGLE_CHANNEL_CENTERED; + /* Donot check pMac->roam.configParam.channelBondingMode5GHz / 24GHz + * Doing so results in circular reference + */ + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: HW: %d CH: %d ORIG_BW: %d\n", __func__, eCsrPhyMode, + channel, ch_width_orig); + + *vht_channel_width = ch_width_orig; + vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams)); + sme_GetConfigParam(pMac, &smeConfig); + + if ((eCSR_DOT11_MODE_11ac == eCsrPhyMode || + eCSR_DOT11_MODE_11ac_ONLY == eCsrPhyMode) && + (eHT_CHANNEL_WIDTH_80MHZ == ch_width_orig)) { + if (channel== 36 || channel == 52 || channel == 100 || + channel == 116 || channel == 149 || channel == 132) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW; + } else if (channel == 40 || channel == 56 || channel == 104 || + channel == 120 || channel == 153 || channel == 136) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW; + } else if (channel == 44 || channel == 60 || channel == 108 || + channel == 124 || channel == 157 || channel == 140) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; + } else if (channel == 48 || channel == 64 || channel == 112 || + channel == 128 || channel == 144 || channel == 161) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; + } else if (channel == 165) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + } else if (channel >= 1 && channel < 5) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + *vht_channel_width = eHT_CHANNEL_WIDTH_40MHZ; + } else if (channel >= 5 && channel <= 9) { + if (0 != ht_sec_ch) { + if (ht_sec_ch > channel) + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + else + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + } + *vht_channel_width = eHT_CHANNEL_WIDTH_40MHZ; + } else if (channel > 9 && channel <= 13) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + *vht_channel_width = eHT_CHANNEL_WIDTH_40MHZ; + } else if (channel ==14) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + } + } else if ((eCSR_DOT11_MODE_11n == eCsrPhyMode || + eCSR_DOT11_MODE_11n_ONLY == eCsrPhyMode || + eCSR_DOT11_MODE_11ac == eCsrPhyMode || + eCSR_DOT11_MODE_11ac_ONLY == eCsrPhyMode) && + (eHT_CHANNEL_WIDTH_40MHZ == ch_width_orig)) { + if (channel== 40 || channel == 48 || channel == 56 || + channel == 64 || channel == 104 || channel == 112 || + channel == 120 || channel == 128 || channel == 136 || + channel == 153 || channel == 161 || channel == 144) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + } else if (channel== 36 || channel == 44 || channel == 52 || + channel == 60 || channel == 100 || channel == 108 || + channel == 116 || channel == 124 || channel == 132 || + channel == 149 || channel == 157 || channel == 140) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + } else if (channel == 165) { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + } else if (channel >= 1 && channel < 5) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + } else if (channel >= 5 && channel <= 9) { + if (ht_sec_ch > channel) + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + else + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + } else if (channel > 9 && channel <= 13) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + } else if (channel ==14) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + } + } else { + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + if (channel <= 14) { + smeConfig.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + } else { + smeConfig.csrConfig.channelBondingMode5GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + } + } + + sme_AdjustCBMode(pMac, &smeConfig, channel, vht_channel_width); + sme_UpdateConfig (pMac, &smeConfig); + cb_mode = (channel <= 14) ? smeConfig.csrConfig.channelBondingMode24GHz : + smeConfig.csrConfig.channelBondingMode5GHz; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + "%s: CH: %d NEW_BW: %d %s-CB_Mode:%d", __func__, channel, + *vht_channel_width, (channel <=14) ? "2G" : "5G", cb_mode); + + return cb_mode; +} + +/*convert the ini value to the ENUM used in csr and MAC for CB state*/ +ePhyChanBondState sme_GetCBPhyStateFromCBIniValue(tANI_U32 cb_ini_value) +{ + return(csrConvertCBIniValueToPhyCBState(cb_ini_value)); +} +/*-------------------------------------------------------------------------- + + \brief sme_SetCurrDeviceMode() - Sets the current operating device mode. + \param hHal - The handle returned by macOpen. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ + +void sme_SetCurrDeviceMode (tHalHandle hHal, tVOS_CON_MODE currDeviceMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->sme.currDeviceMode = currDeviceMode; + return; +} + +/** + * sme_set_pdev_ht_vht_ies() - sends the set pdev IE req + * + * @hal: Pointer to HAL + * @enable2x2: 1x1 or 2x2 mode. + * + * Sends the set pdev IE req with Nss value. + * + * Return: None + */ +void sme_set_pdev_ht_vht_ies(tHalHandle hal, bool enable2x2) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct sir_set_ht_vht_cfg *ht_vht_cfg; + eHalStatus status = eHAL_STATUS_FAILURE; + + if (!mac_ctx->per_band_chainmask_supp) + return; + + if (!((mac_ctx->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_AUTO) || + (mac_ctx->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11N) || + (mac_ctx->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11N_ONLY) || + (mac_ctx->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11AC) || + (mac_ctx->roam.configParam.uCfgDot11Mode == + eCSR_CFG_DOT11_MODE_11AC_ONLY))) + return; + + status = sme_AcquireGlobalLock(&mac_ctx->sme); + if (eHAL_STATUS_SUCCESS == status) { + ht_vht_cfg = vos_mem_malloc(sizeof(*ht_vht_cfg)); + if (NULL == ht_vht_cfg) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: mem alloc failed for ht_vht_cfg", + __func__); + sme_ReleaseGlobalLock(&mac_ctx->sme); + return; + } + + ht_vht_cfg->pdev_id = 0; + if (enable2x2) + ht_vht_cfg->nss = 2; + else + ht_vht_cfg->nss = 1; + ht_vht_cfg->dot11mode = + (tANI_U8)csrTranslateToWNICfgDot11Mode(mac_ctx, + mac_ctx->roam.configParam.uCfgDot11Mode); + + ht_vht_cfg->msg_type = eWNI_SME_PDEV_SET_HT_VHT_IE; + ht_vht_cfg->len = sizeof(*ht_vht_cfg); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: send PDEV_SET_HT_VHT_IE with nss - %d, dot11mode - %d", + __func__, ht_vht_cfg->nss, ht_vht_cfg->dot11mode); + status = palSendMBMessage(mac_ctx->hHdd, ht_vht_cfg); + if (eHAL_STATUS_SUCCESS != status) { + smsLog(mac_ctx, LOGE, FL( + "SME_PDEV_SET_HT_VHT_IE msg to PE failed")); + vos_mem_free(ht_vht_cfg); + } + sme_ReleaseGlobalLock(&mac_ctx->sme); + } + return; +} +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_HandoffRequest() - a wrapper function to Request a handoff + from CSR. + This is a synchronous call + \param hHal - The handle returned by macOpen + \param sessionId - Session Identifier + \param pHandoffInfo - info provided by HDD with the handoff request (namely: + BSSID, channel etc.) + \return eHAL_STATUS_SUCCESS - SME passed the request to CSR successfully. + Other status means SME is failed to send the request. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_HandoffRequest(tHalHandle hHal, + tANI_U8 sessionId, + tCsrHandoffRequest *pHandoffInfo) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: invoked", __func__); + status = csrHandoffRequest(pMac, sessionId, pHandoffInfo); + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +#ifdef IPA_UC_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_ipa_offload_enable_disable + \brief API to enable/disable IPA offload + \param hal - The handle returned by macOpen. + \param session_id - Session Identifier + \param request - Pointer to the offload request. + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_ipa_offload_enable_disable(tHalHandle hal, tANI_U8 session_id, + struct sir_ipa_offload_enable_disable *request) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hal ); + eHalStatus status = eHAL_STATUS_FAILURE; + struct sir_ipa_offload_enable_disable *request_buf; + vos_msg_t msg; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + request_buf = vos_mem_malloc(sizeof(*request_buf)); + if (NULL == request_buf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for IPA_OFFLOAD_ENABLE_DISABLE", + __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILED_ALLOC; + } + + request_buf->offload_type = request->offload_type; + request_buf->vdev_id = request->vdev_id; + request_buf->enable = request->enable; + + msg.type = WDA_IPA_OFFLOAD_ENABLE_DISABLE; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (!VOS_IS_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_IPA_OFFLOAD_ENABLE_DISABLE message to WDA", + __func__); + vos_mem_free(request_buf); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock(&pMac->sme); + } + + return eHAL_STATUS_SUCCESS; +} +#endif + +#endif + +/* + * SME API to check if there is any infra station or + * P2P client is connected + */ +VOS_STATUS sme_isSta_p2p_clientConnected(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + if(csrIsInfraConnected(pMac)) + { + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAILURE; +} + + +#ifdef FEATURE_WLAN_LPHB +/* --------------------------------------------------------------------------- + \fn sme_LPHBConfigReq + \API to make configuration LPHB within FW. + \param hHal - The handle returned by macOpen + \param lphdReq - LPHB request argument by client + \param pCallbackfn - LPHB timeout notification callback function pointer + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +eHalStatus sme_LPHBConfigReq +( + tHalHandle hHal, + tSirLPHBReq *lphdReq, + void (*pCallbackfn)(void *pHddCtx, tSirLPHBInd *indParam) +) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ, + NO_SESSION, lphdReq->cmd)); + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + if ((LPHB_SET_EN_PARAMS_INDID == lphdReq->cmd) && + (NULL == pCallbackfn) && + (NULL == pMac->sme.pLphbIndCb)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Indication Call back did not registered", __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + else if (NULL != pCallbackfn) + { + pMac->sme.pLphbIndCb = pCallbackfn; + } + + /* serialize the req through MC thread */ + vosMessage.bodyptr = lphdReq; + vosMessage.type = WDA_LPHB_CONF_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Config LPHB MSG fail", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} +#endif /* FEATURE_WLAN_LPHB */ +/*-------------------------------------------------------------------------- + \brief sme_enable_disable_split_scan() - a wrapper function to set the split + scan parameter. + This is a synchronous call + \param hHal - The handle returned by macOpen + \return NONE. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, + tANI_U8 nNumP2PChan) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->roam.configParam.nNumStaChanCombinedConc = nNumStaChan; + pMac->roam.configParam.nNumP2PChanCombinedConc = nNumP2PChan; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: SCAN nNumStaChanCombinedConc : %d," + "nNumP2PChanCombinedConc : %d ", + __func__, nNumStaChan, nNumP2PChan); + + return; + +} + +/** + * sme_AddPeriodicTxPtrn() - Add Periodic TX Pattern + * @hal: global hal handle + * @addPeriodicTxPtrnParams: request message + * + * Return: eHalStatus enumeration + */ +eHalStatus +sme_AddPeriodicTxPtrn(tHalHandle hal, + struct sSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sSirAddPeriodicTxPtrn *req_msg; + vos_msg_t msg; + + smsLog(mac, LOG1, FL("enter")); + + req_msg = vos_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + smsLog(mac, LOGE, FL("vos_mem_malloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + *req_msg = *addPeriodicTxPtrnParams; + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + msg.bodyptr = req_msg; + msg.type = WDA_ADD_PERIODIC_TX_PTRN_IND; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +/** + * sme_DelPeriodicTxPtrn() - Delete Periodic TX Pattern + * @hal: global hal handle + * @delPeriodicTxPtrnParams: request message + * + * Return: eHalStatus enumeration + */ +eHalStatus +sme_DelPeriodicTxPtrn(tHalHandle hal, + struct sSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sSirDelPeriodicTxPtrn *req_msg; + vos_msg_t msg; + + smsLog(mac, LOG1, FL("enter")); + + req_msg = vos_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + smsLog(mac, LOGE, FL("vos_mem_malloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + *req_msg = *delPeriodicTxPtrnParams; + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + msg.bodyptr = req_msg; + msg.type = WDA_DEL_PERIODIC_TX_PTRN_IND; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +void smeGetCommandQStatus( tHalHandle hHal ) +{ + tSmeCmd *pTempCmd = NULL; + tListElem *pEntry; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: pMac is NULL", __func__); + return; + } + + pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ); + if( pEntry ) + { + pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link ); + } + smsLog( pMac, LOGE, "Currently smeCmdActiveList has command (0x%X)", + (pTempCmd) ? pTempCmd->command : eSmeNoCommand ); + if(pTempCmd) + { + if( eSmeCsrCommandMask & pTempCmd->command ) + { + //CSR command is stuck. See what the reason code is for that command + dumpCsrCommandInfo(pMac, pTempCmd); + } + } //if(pTempCmd) + + smsLog( pMac, LOGE, "Currently smeCmdPendingList has %d commands", + csrLLCount(&pMac->sme.smeCmdPendingList)); + + smsLog( pMac, LOGE, "Currently roamCmdPendingList has %d commands", + csrLLCount(&pMac->roam.roamCmdPendingList)); + + return; +} + +/* ------------------------------------------------------------------------- + \fn sme_set_dot11p_config + \brief API to Set 802.11p config + \param hal - The handle returned by macOpen + \param enable_dot11p - 802.11p config param + \return eHalStatus +---------------------------------------------------------------------------*/ +void sme_set_dot11p_config(tHalHandle hal, bool enable_dot11p) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + mac->enable_dot11p = enable_dot11p; +} + +/** + * copy_sir_ocb_config() - Performs deep copy of an OCB configuration + * @src: the source configuration + * + * Return: pointer to the copied OCB configuration + */ +static struct sir_ocb_config *sme_copy_sir_ocb_config(struct sir_ocb_config *src) +{ + struct sir_ocb_config *dst; + uint32_t length; + void *cursor; + + length = sizeof(*src) + + src->channel_count * sizeof(*src->channels) + + src->schedule_size * sizeof(*src->schedule) + + src->dcc_ndl_chan_list_len + + src->dcc_ndl_active_state_list_len; + + dst = vos_mem_malloc(length); + if (!dst) + return NULL; + + *dst = *src; + + cursor = dst; + cursor += sizeof(*dst); + dst->channels = cursor; + cursor += src->channel_count * sizeof(*src->channels); + vos_mem_copy(dst->channels, src->channels, + src->channel_count * sizeof(*src->channels)); + dst->schedule = cursor; + cursor += src->schedule_size * sizeof(*src->schedule); + vos_mem_copy(dst->schedule, src->schedule, + src->schedule_size * sizeof(*src->schedule)); + dst->dcc_ndl_chan_list = cursor; + cursor += src->dcc_ndl_chan_list_len; + vos_mem_copy(dst->dcc_ndl_chan_list, src->dcc_ndl_chan_list, + src->dcc_ndl_chan_list_len); + dst->dcc_ndl_active_state_list = cursor; + cursor += src->dcc_ndl_active_state_list_len; + vos_mem_copy(dst->dcc_ndl_active_state_list, + src->dcc_ndl_active_state_list, + src->dcc_ndl_active_state_list_len); + return dst; +} + +/** + * sme_ocb_set_config() - Set the OCB configuration + * @hHal: reference to the HAL + * @context: the context of the call + * @callback: the callback to hdd + * @config: the OCB configuration + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_ocb_set_config(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_config *config) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t msg = {0}; + struct sir_ocb_config *msg_body; + + /* Lock the SME structure */ + status = sme_AcquireGlobalLock(&pMac->sme); + if (!HAL_STATUS_SUCCESS(status)) + return status; + + /* Check if there is a pending request and return an error if one exists */ + if (pMac->sme.ocb_set_config_callback) { + status = eHAL_STATUS_FW_PS_BUSY; + goto end; + } + + msg_body = sme_copy_sir_ocb_config(config); + + if (!msg_body) { + status = eHAL_STATUS_FAILED_ALLOC; + goto end; + } + + msg.type = WDA_OCB_SET_CONFIG_CMD; + msg.bodyptr = msg_body; + + /* Set the request callback and context */ + pMac->sme.ocb_set_config_callback = callback; + pMac->sme.ocb_set_config_context = context; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), vos_status); + pMac->sme.ocb_set_config_callback = callback; + pMac->sme.ocb_set_config_context = context; + vos_mem_free(msg_body); + goto end; + } + +end: + sme_ReleaseGlobalLock(&pMac->sme); + + if (status) + return status; + if (vos_status) + return eHAL_STATUS_FAILURE; + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_ocb_set_utc_time() - Set the OCB UTC time + * @utc: the UTC time struct + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_ocb_set_utc_time(struct sir_ocb_utc *utc) +{ + vos_msg_t msg = {0}; + struct sir_ocb_utc *sme_utc; + + sme_utc = vos_mem_malloc(sizeof(*sme_utc)); + if (!sme_utc) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Malloc failed")); + return eHAL_STATUS_E_MALLOC_FAILED; + } + *sme_utc = *utc; + + msg.type = WDA_OCB_SET_UTC_TIME_CMD; + msg.reserved = 0; + msg.bodyptr = sme_utc; + if (!VOS_IS_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 message to WDA")); + vos_mem_free(utc); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_ocb_start_timing_advert() - Start sending timing advert frames + * @timing_advert: the timing advertisement struct + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_ocb_start_timing_advert( + struct sir_ocb_timing_advert *timing_advert) +{ + vos_msg_t msg; + void *buf; + struct sir_ocb_timing_advert *sme_timing_advert; + + buf = vos_mem_malloc(sizeof(*sme_timing_advert) + + timing_advert->template_length); + if (!buf) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for start TA")); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + sme_timing_advert = (struct sir_ocb_timing_advert *)buf; + *sme_timing_advert = *timing_advert; + sme_timing_advert->template_value = buf + sizeof(*sme_timing_advert); + vos_mem_copy(sme_timing_advert->template_value, + timing_advert->template_value, timing_advert->template_length); + + msg.type = WDA_OCB_START_TIMING_ADVERT_CMD; + msg.reserved = 0; + msg.bodyptr = buf; + if (!VOS_IS_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 msg to WDA")); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_ocb_stop_timing_advert() - Stop sending timing advert frames on a channel + * @timing_advert: the timing advertisement struct + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_ocb_stop_timing_advert( + struct sir_ocb_timing_advert *timing_advert) +{ + vos_msg_t msg; + struct sir_ocb_timing_advert *sme_timing_advert; + + sme_timing_advert = vos_mem_malloc(sizeof(*timing_advert)); + if (!sme_timing_advert) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for stop TA")); + return eHAL_STATUS_E_MALLOC_FAILED; + } + *sme_timing_advert = *timing_advert; + + msg.type = WDA_OCB_STOP_TIMING_ADVERT_CMD; + msg.reserved = 0; + msg.bodyptr = sme_timing_advert; + if (!VOS_IS_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 msg to WDA")); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_ocb_get_tsf_timer() - Get the TSF timer value + * @hHal: reference to the HAL + * @context: the context of the call + * @callback: the callback to hdd + * @request: the TSF timer request + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_ocb_get_tsf_timer(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_get_tsf_timer *request) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t msg = {0}; + struct sir_ocb_get_tsf_timer *msg_body; + + /* Lock the SME structure */ + status = sme_AcquireGlobalLock(&pMac->sme); + if (!HAL_STATUS_SUCCESS(status)) + return status; + + /* Allocate memory for the WMI request, and copy the parameter */ + msg_body = vos_mem_malloc(sizeof(*msg_body)); + if (!msg_body) { + status = eHAL_STATUS_FAILED_ALLOC; + goto end; + } + *msg_body = *request; + + msg.type = WDA_OCB_GET_TSF_TIMER_CMD; + msg.bodyptr = msg_body; + + /* Set the request callback and the context */ + pMac->sme.ocb_get_tsf_timer_callback = callback; + pMac->sme.ocb_get_tsf_timer_context = context; + + /* Post the message to WDA */ + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), vos_status); + pMac->sme.ocb_get_tsf_timer_callback = NULL; + pMac->sme.ocb_get_tsf_timer_context = NULL; + vos_mem_free(msg_body); + goto end; + } + +end: + sme_ReleaseGlobalLock(&pMac->sme); + + if (status) + return status; + if (vos_status) + return eHAL_STATUS_FAILURE; + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_dcc_get_stats() - Get the DCC stats + * @hHal: reference to the HAL + * @context: the context of the call + * @callback: the callback to hdd + * @request: the get DCC stats request + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_dcc_get_stats(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_get_stats *request) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t msg = {0}; + struct sir_dcc_get_stats *msg_body; + + /* Lock the SME structure */ + status = sme_AcquireGlobalLock(&pMac->sme); + if (!HAL_STATUS_SUCCESS(status)) + return status; + + /* Allocate memory for the WMI request, and copy the parameter */ + msg_body = vos_mem_malloc(sizeof(*msg_body) + + request->request_array_len); + if (!msg_body) { + status = eHAL_STATUS_FAILED_ALLOC; + goto end; + } + *msg_body = *request; + msg_body->request_array = (void *)msg_body + sizeof(*msg_body); + vos_mem_copy(msg_body->request_array, request->request_array, + request->request_array_len); + + msg.type = WDA_DCC_GET_STATS_CMD; + msg.bodyptr = msg_body; + + /* Set the request callback and context */ + pMac->sme.dcc_get_stats_callback = callback; + pMac->sme.dcc_get_stats_context = context; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), vos_status); + pMac->sme.dcc_get_stats_callback = callback; + pMac->sme.dcc_get_stats_context = context; + vos_mem_free(msg_body); + goto end; + } + +end: + sme_ReleaseGlobalLock(&pMac->sme); + + if (status) + return status; + if (vos_status) + return eHAL_STATUS_FAILURE; + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_dcc_clear_stats() - Clear the DCC stats + * @vdev_id: vdev id for OCB interface + * @dcc_stats_bitmap: the entries in the stats to clear + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_dcc_clear_stats(uint32_t vdev_id, uint32_t dcc_stats_bitmap) +{ + vos_msg_t msg = {0}; + struct sir_dcc_clear_stats *request = + vos_mem_malloc(sizeof(struct sir_dcc_clear_stats)); + if (!request) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory")); + return eHAL_STATUS_E_MALLOC_FAILED; + } + vos_mem_zero(request, sizeof(*request)); + request->vdev_id = vdev_id; + request->dcc_stats_bitmap = dcc_stats_bitmap; + + msg.type = WDA_DCC_CLEAR_STATS_CMD; + msg.bodyptr = request; + + if (!VOS_IS_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 msg to WDA")); + vos_mem_free(request); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_dcc_update_ndl() - Update the DCC settings + * @hHal: reference to the HAL + * @context: the context of the call + * @callback: the callback to hdd + * @request: the update DCC request + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_dcc_update_ndl(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_update_ndl *request) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t msg = {0}; + struct sir_dcc_update_ndl *msg_body; + + /* Lock the SME structure */ + status = sme_AcquireGlobalLock(&pMac->sme); + if (!HAL_STATUS_SUCCESS(status)) + return status; + + /* Allocate memory for the WMI request, and copy the parameter */ + msg_body = vos_mem_malloc(sizeof(*msg_body) + + request->dcc_ndl_chan_list_len + + request->dcc_ndl_active_state_list_len); + if (!msg_body) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Failed to allocate memory")); + status = eHAL_STATUS_FAILED_ALLOC; + goto end; + } + + *msg_body = *request; + + msg_body->dcc_ndl_chan_list = (void *)msg_body + sizeof(*msg_body); + msg_body->dcc_ndl_active_state_list = msg_body->dcc_ndl_chan_list + + request->dcc_ndl_chan_list_len; + vos_mem_copy(msg_body->dcc_ndl_chan_list, request->dcc_ndl_chan_list, + request->dcc_ndl_active_state_list_len); + vos_mem_copy(msg_body->dcc_ndl_active_state_list, + request->dcc_ndl_active_state_list, + request->dcc_ndl_active_state_list_len); + + msg.type = WDA_DCC_UPDATE_NDL_CMD; + msg.bodyptr = msg_body; + + /* Set the request callback and the context */ + pMac->sme.dcc_update_ndl_callback = callback; + pMac->sme.dcc_update_ndl_context = context; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), vos_status); + pMac->sme.dcc_update_ndl_callback = NULL; + pMac->sme.dcc_update_ndl_context = NULL; + vos_mem_free(msg_body); + goto end; + } + +end: + sme_ReleaseGlobalLock(&pMac->sme); + + if (status) + return status; + if (vos_status) + return eHAL_STATUS_FAILURE; + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_register_for_dcc_stats_event() - Register for the periodic DCC stats + * event + * @hHal: reference to the HAL + * @context: the context of the call + * @callback: the callback to hdd + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE on failure + */ +eHalStatus sme_register_for_dcc_stats_event(tHalHandle hHal, void *context, + ocb_callback callback) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_FAILURE; + + status = sme_AcquireGlobalLock(&pMac->sme); + pMac->sme.dcc_stats_event_callback = callback; + pMac->sme.dcc_stats_event_context = context; + sme_ReleaseGlobalLock(&pMac->sme); + + return 0; +} + +void sme_getRecoveryStats(tHalHandle hHal) { + tANI_U8 i; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "Self Recovery Stats"); + for (i = 0; i < MAX_ACTIVE_CMD_STATS; i++) { + if (eSmeNoCommand != gSelfRecoveryStats.activeCmdStats[i].command) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "timestamp %llu: command 0x%0X: reason %d: session %d", + gSelfRecoveryStats.activeCmdStats[i].timestamp, + gSelfRecoveryStats.activeCmdStats[i].command, + gSelfRecoveryStats.activeCmdStats[i].reason, + gSelfRecoveryStats.activeCmdStats[i].sessionId); + } + } +} + +void sme_SaveActiveCmdStats(tHalHandle hHal) { + tSmeCmd *pTempCmd = NULL; + tListElem *pEntry; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tANI_U8 statsIndx = 0; + + if (NULL == pMac) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: pMac is NULL", __func__); + return; + } + + pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + } + + if (pTempCmd) { + if (eSmeCsrCommandMask & pTempCmd->command) { + statsIndx = gSelfRecoveryStats.cmdStatsIndx; + gSelfRecoveryStats.activeCmdStats[statsIndx].command = + pTempCmd->command; + gSelfRecoveryStats.activeCmdStats[statsIndx].sessionId = + pTempCmd->sessionId; + gSelfRecoveryStats.activeCmdStats[statsIndx].timestamp = + vos_get_monotonic_boottime(); + if (eSmeCommandRoam == pTempCmd->command) { + gSelfRecoveryStats.activeCmdStats[statsIndx].reason = + pTempCmd->u.roamCmd.roamReason; + } else if (eSmeCommandScan == pTempCmd->command) { + gSelfRecoveryStats.activeCmdStats[statsIndx].reason = + pTempCmd->u.scanCmd.reason; + } else { + gSelfRecoveryStats.activeCmdStats[statsIndx].reason = 0xFF; + } + + gSelfRecoveryStats.cmdStatsIndx = + ((gSelfRecoveryStats.cmdStatsIndx + 1) & + (MAX_ACTIVE_CMD_STATS - 1)); + } + } + return; +} + +void activeListCmdTimeoutHandle(void *userData) +{ + if (NULL == userData) + return; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Active List command timeout Cmd List Count %d", __func__, + csrLLCount(&((tpAniSirGlobal) userData)->sme.smeCmdActiveList) ); + smeGetCommandQStatus((tHalHandle) userData); + + if (((tpAniSirGlobal)userData)->sme.enableSelfRecovery) { + sme_SaveActiveCmdStats((tHalHandle)userData); + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } +} + +VOS_STATUS sme_notify_modem_power_state(tHalHandle hHal, tANI_U32 value) +{ + vos_msg_t msg; + tpSirModemPowerStateInd pRequestBuf; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + return VOS_STATUS_E_FAILURE; + } + + pRequestBuf = vos_mem_malloc(sizeof(tSirModemPowerStateInd)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for MODEM POWER STATE IND", + __func__); + return VOS_STATUS_E_FAILURE; + } + + pRequestBuf->param = value; + + msg.type = WDA_MODEM_POWER_STATE_IND; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_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_MODEM_POWER_STATE_IND message" + " to WDA", __func__); + vos_mem_free(pRequestBuf); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +#ifdef QCA_HT_2040_COEX +VOS_STATUS sme_notify_ht2040_mode(tHalHandle hHal, tANI_U16 staId, + v_MACADDR_t macAddrSTA, v_U8_t sessionId, tANI_U8 channel_type) +{ + vos_msg_t msg; + tUpdateVHTOpMode *pHtOpMode = NULL; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + return VOS_STATUS_E_FAILURE; + } + + pHtOpMode = vos_mem_malloc(sizeof(tUpdateVHTOpMode)); + if ( NULL == pHtOpMode ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for setting OP mode", + __func__); + return VOS_STATUS_E_FAILURE; + } + + switch (channel_type) + { + case eHT_CHAN_HT20: + pHtOpMode->opMode = eHT_CHANNEL_WIDTH_20MHZ; + break; + + case eHT_CHAN_HT40MINUS: + case eHT_CHAN_HT40PLUS: + pHtOpMode->opMode = eHT_CHANNEL_WIDTH_40MHZ; + break; + + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid OP mode", + __func__); + return VOS_STATUS_E_FAILURE; + } + + pHtOpMode->staId = staId, + vos_mem_copy(pHtOpMode->peer_mac, macAddrSTA.bytes, + sizeof(tSirMacAddr)); + pHtOpMode->smesessionId = sessionId; + + msg.type = WDA_UPDATE_OP_MODE; + msg.reserved = 0; + msg.bodyptr = pHtOpMode; + if (!VOS_IS_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_UPDATE_OP_MODE message" + " to WDA", __func__); + vos_mem_free(pHtOpMode); + return VOS_STATUS_E_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Notifed FW about OP mode: %d for staId=%d", + __func__, pHtOpMode->opMode, staId); + + + return VOS_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_SetHT2040Mode + + \brief To update HT Operation beacon IE. + + \param hHal - The handle returned by macOPen + \param sessionId - session id + \param channel_type - indicates channel width + \param obssEnabled - OBSS enabled/disabled + + \return eHalStatus SUCCESS + FAILURE or RESOURCES + The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetHT2040Mode(tHalHandle hHal, tANI_U8 sessionId, + tANI_U8 channel_type, tANI_BOOLEAN obssEnabled) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + ePhyChanBondState cbMode; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Update HT operation beacon IE, channel_type=%d", + __func__, channel_type); + + switch (channel_type) + { + case eHT_CHAN_HT20: + cbMode = PHY_SINGLE_CHANNEL_CENTERED; + break; + case eHT_CHAN_HT40MINUS: + cbMode = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + break; + case eHT_CHAN_HT40PLUS: + cbMode = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + break; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s:Error!!! Invalid HT20/40 mode !", + __func__); + return VOS_STATUS_E_FAILURE; + } + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) { + status = csrSetHT2040Mode(pMac, sessionId, cbMode, obssEnabled); + sme_ReleaseGlobalLock(&pMac->sme ); + } + return (status); +} +#endif + +/* + * SME API to enable/disable idle mode power save + * This should be called only if power save offload + * is enabled + */ +VOS_STATUS sme_SetIdlePowersaveConfig(v_PVOID_t vosContext, tANI_U32 value) +{ + v_PVOID_t wdaContext = vos_get_context(VOS_MODULE_ID_WDA, vosContext); + + if (NULL == wdaContext) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: wdaContext is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + " Idle Ps Set Value %d", value); + + if (VOS_STATUS_SUCCESS != WDA_SetIdlePsConfig(wdaContext, value)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + " Failed to Set Idle Ps Value %d", value); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +eHalStatus sme_ConfigEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcOffloadConfigEnablePowerSave(hHal, psMode); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +eHalStatus sme_ConfigDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = pmcOffloadConfigDisablePowerSave(hHal, psMode); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +eHalStatus sme_PsOffloadEnablePowerSave (tHalHandle hHal, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_AcquireGlobalLock(&pMac->sme); + if(HAL_STATUS_SUCCESS( status )) + { + status = PmcOffloadEnableStaModePowerSave(hHal, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +eHalStatus sme_PsOffloadDisablePowerSave (tHalHandle hHal, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_AcquireGlobalLock(&pMac->sme); + if(HAL_STATUS_SUCCESS( status )) + { + status = PmcOffloadDisableStaModePowerSave(hHal, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +eHalStatus sme_PsOffloadEnableDeferredPowerSave (tHalHandle hHal, + tANI_U32 sessionId, + tANI_BOOLEAN isReassoc) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS( status )) + { + status = PmcOffloadEnableDeferredStaModePowerSave(hHal, sessionId, + isReassoc); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +eHalStatus sme_PsOffloadDisableDeferredPowerSave (tHalHandle hHal, + tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS( status )) + { + status = PmcOffloadDisableDeferredStaModePowerSave(hHal, sessionId); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +tANI_S16 sme_GetHTConfig(tHalHandle hHal, tANI_U8 session_id, tANI_U16 ht_capab) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id); + + if (NULL == pSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: pSession is NULL", __func__); + return -EIO; + } + switch (ht_capab) { + case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: + return pSession->htConfig.ht_rx_ldpc; + case WNI_CFG_HT_CAP_INFO_TX_STBC: + return pSession->htConfig.ht_tx_stbc; + case WNI_CFG_HT_CAP_INFO_RX_STBC: + return pSession->htConfig.ht_rx_stbc; + case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: + case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: + return pSession->htConfig.ht_sgi; + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "invalid ht capability"); + return -EIO; + } +} + +int sme_UpdateHTConfig(tHalHandle hHal, tANI_U8 sessionId, tANI_U16 htCapab, + int value) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL == pSession) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: pSession is NULL", __func__); + return -EIO; + } + + if (eHAL_STATUS_SUCCESS != WDA_SetHTConfig(sessionId, htCapab, value)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to set ht capability in target"); + return -EIO; + } + + switch (htCapab) { + case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: + pSession->htConfig.ht_rx_ldpc = value; + break; + case WNI_CFG_HT_CAP_INFO_TX_STBC: + pSession->htConfig.ht_tx_stbc = value; + break; + case WNI_CFG_HT_CAP_INFO_RX_STBC: + pSession->htConfig.ht_rx_stbc = value; + break; + case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: + case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: + pSession->htConfig.ht_sgi = value; + break; + } + + return 0; +} + +#define HT20_SHORT_GI_MCS7_RATE 722 +/* --------------------------------------------------------------------------- + \fn sme_SendRateUpdateInd + \brief API to Update rate + \param hHal - The handle returned by macOpen + \param rateUpdateParams - Pointer to rate update params + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SendRateUpdateInd(tHalHandle hHal, + tSirRateUpdateInd *rateUpdateParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status; + vos_msg_t msg; + tSirRateUpdateInd *rateUpdate = vos_mem_malloc(sizeof(tSirRateUpdateInd)); + if (rateUpdate == NULL) { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: SET_MC_RATE indication alloc fail", __func__); + return eHAL_STATUS_FAILURE; + } + *rateUpdate = *rateUpdateParams; + + if (rateUpdate->mcastDataRate24GHz == + HT20_SHORT_GI_MCS7_RATE) + rateUpdate->mcastDataRate24GHzTxFlag = + eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; + else if (rateUpdate->reliableMcastDataRate == + HT20_SHORT_GI_MCS7_RATE) + rateUpdate->reliableMcastDataRateTxFlag = + eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + msg.type = WDA_RATE_UPDATE_IND; + msg.bodyptr = rateUpdate; + + if (!VOS_IS_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_RMC_RATE_IND to WDA!", + __func__); + + vos_mem_free(rateUpdate); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_SUCCESS; + } + + return status; +} + +eHalStatus sme_getRegInfo(tHalHandle hHal, tANI_U8 chanId, + tANI_U32 *regInfo1, tANI_U32 *regInfo2) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status; + tANI_U8 i; + eAniBoolean found = false; + + status = sme_AcquireGlobalLock(&pMac->sme); + *regInfo1 = 0; + *regInfo2 = 0; + if (HAL_STATUS_SUCCESS(status)) + { + for (i = 0 ; i < WNI_CFG_VALID_CHANNEL_LIST_LEN; i++) + { + if (pMac->scan.defaultPowerTable[i].chanId == chanId) + { + SME_SET_CHANNEL_REG_POWER(*regInfo1, + pMac->scan.defaultPowerTable[i].pwr); + + SME_SET_CHANNEL_MAX_TX_POWER(*regInfo2, + pMac->scan.defaultPowerTable[i].pwr); + + + found = true; + break; + } + } + + if (!found) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +/* --------------------------------------------------------------------------- + \fn sme_auto_shutdown_cb + \brief Used to plug in callback function for receiving auto shutdown evt + \param hHal + \param pCallbackfn : callback function pointer should be plugged in + \- return eHalStatus +-------------------------------------------------------------------------*/ +eHalStatus sme_set_auto_shutdown_cb +( + tHalHandle hHal, + void (*pCallbackfn)(void) +) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Plug in Auto shutdown event callback", __func__); + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + if (NULL != pCallbackfn) + { + pMac->sme.pAutoShutdownNotificationCb = pCallbackfn; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} +/* --------------------------------------------------------------------------- + \fn sme_set_auto_shutdown_timer + \API to set auto shutdown timer value in FW. + \param hHal - The handle returned by macOpen + \param timer_val - The auto shutdown timer value to be set + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +eHalStatus sme_set_auto_shutdown_timer(tHalHandle hHal, tANI_U32 timer_val) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirAutoShutdownCmdParams *auto_sh_cmd; + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + auto_sh_cmd = (tSirAutoShutdownCmdParams *) + vos_mem_malloc(sizeof(tSirAutoShutdownCmdParams)); + if (auto_sh_cmd == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s Request Buffer Alloc Fail", __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + auto_sh_cmd->timer_val = timer_val; + + /* serialize the req through MC thread */ + vosMessage.bodyptr = auto_sh_cmd; + vosMessage.type = WDA_SET_AUTO_SHUTDOWN_TIMER_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Auto shutdown MSG fail", __func__); + vos_mem_free(auto_sh_cmd); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Posted Auto shutdown MSG", __func__); + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} +#endif + +#ifdef FEATURE_WLAN_CH_AVOID +/* --------------------------------------------------------------------------- + \fn sme_AddChAvoidCallback + \brief Used to plug in callback function + Which notify channel may not be used with SAP or P2PGO mode. + Notification come from FW. + \param hHal + \param pCallbackfn : callback function pointer should be plugged in + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_AddChAvoidCallback +( + tHalHandle hHal, + void (*pCallbackfn)(void *pAdapter, void *indParam) +) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Plug in CH AVOID CB", __func__); + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + if (NULL != pCallbackfn) + { + pMac->sme.pChAvoidNotificationCb = pCallbackfn; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_ChAvoidUpdateReq + \API to request channel avoidance update from FW. + \param hHal - The handle returned by macOpen + \param update_type - The udpate_type parameter of this request call + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +eHalStatus sme_ChAvoidUpdateReq +( + tHalHandle hHal +) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirChAvoidUpdateReq *cauReq; + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + cauReq = (tSirChAvoidUpdateReq *) + vos_mem_malloc(sizeof(tSirChAvoidUpdateReq)); + if (NULL == cauReq) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s Request Buffer Alloc Fail", __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + cauReq->reserved_param = 0; + + /* serialize the req through MC thread */ + vosMessage.bodyptr = cauReq; + vosMessage.type = WDA_CH_AVOID_UPDATE_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Ch Avoid Update MSG fail", __func__); + vos_mem_free(cauReq); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: Posted Ch Avoid Update MSG", __func__); + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} +#endif /* FEATURE_WLAN_CH_AVOID */ + +/** + * sme_set_miracast() - Function to set miracast value to UMAC + * @hal: Handle returned by macOpen + * @filter_type: 0-Disabled, 1-Source, 2-sink + * + * This function passes down the value of miracast set by + * framework to UMAC + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +eHalStatus sme_set_miracast(tHalHandle hal, uint8_t filter_type) +{ + vos_msg_t msg; + uint32_t *val; + tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); + + val = vos_mem_malloc(sizeof(*val)); + if (NULL == val || NULL == mac_ptr) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pointer", __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + *val = filter_type; + + msg.type = SIR_HAL_SET_MIRACAST; + msg.reserved = 0; + msg.bodyptr = val; + + if (!VOS_IS_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_MAS_ENABLE_DISABLE to WMA!", + __func__); + vos_mem_free(val); + return eHAL_STATUS_FAILURE; + } + + mac_ptr->sme.miracast_value = filter_type; + return eHAL_STATUS_SUCCESS; +} + +/** + * sme_set_mas() - Function to set MAS value to UMAC + * @val: 1-Enable, 0-Disable + * + * This function passes down the value of MAS to the UMAC. A + * value of 1 will enable MAS and a value of 0 will disable MAS + * + * Return: Configuration message posting status, SUCCESS or Fail + * + */ +eHalStatus sme_set_mas(uint32_t val) +{ + vos_msg_t msg; + uint32_t *ptr_val; + + ptr_val = vos_mem_malloc(sizeof(*ptr_val)); + if (NULL == ptr_val) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: could not allocate ptr_val", __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + *ptr_val = val; + + msg.type = SIR_HAL_SET_MAS; + msg.reserved = 0; + msg.bodyptr = ptr_val; + + if (!VOS_IS_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_MAS_ENABLE_DISABLE to WMA!", + __func__); + vos_mem_free(ptr_val); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + +/* ------------------------------------------------------------------------- + \fn sme_RoamChannelChangeReq + \brief API to Indicate Channel change to new target channel + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamChannelChangeReq(tHalHandle hHal, tCsrBssid bssid, + tANI_U32 cbMode, tCsrRoamProfile *pprofile) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + u_int8_t ch_mode; + + ch_mode = (pprofile->ChannelInfo.ChannelList[0] <= 14) ? + pMac->roam.configParam.channelBondingMode24GHz : + pMac->roam.configParam.channelBondingMode5GHz; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("sapdfs: requested CBmode=%d & new negotiated CBmode=%d"), + cbMode, ch_mode); + status = csrRoamChannelChangeReq(pMac, bssid, ch_mode, pprofile); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* ------------------------------------------------------------------------- + \fn sme_ProcessChannelChangeResp + \brief API to Indicate Channel change response message to SAP. + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_ProcessChannelChangeResp(tpAniSirGlobal pMac, + v_U16_t msg_type, void *pMsgBuf) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = {0}; + eCsrRoamResult roamResult; + tpSwitchChannelParams pChnlParams = (tpSwitchChannelParams) pMsgBuf; + tANI_U32 SessionId = pChnlParams->peSessionId; + + pRoamInfo.channelChangeRespEvent = + (tSirChanChangeResponse *)vos_mem_malloc( + sizeof(tSirChanChangeResponse)); + if (NULL == pRoamInfo.channelChangeRespEvent) + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, "Channel Change Event Allocation Failed: %d\n", + status); + return status; + } + if (msg_type == eWNI_SME_CHANNEL_CHANGE_RSP) + { + pRoamInfo.channelChangeRespEvent->sessionId = SessionId; + pRoamInfo.channelChangeRespEvent->newChannelNumber = + pChnlParams->channelNumber; + pRoamInfo.channelChangeRespEvent->secondaryChannelOffset = + pChnlParams->secondaryChannelOffset; + + if (pChnlParams->status == eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Received success eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]", + SessionId); + pRoamInfo.channelChangeRespEvent->channelChangeStatus = 1; + roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED, + "sapdfs: Received failure eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]", + SessionId); + pRoamInfo.channelChangeRespEvent->channelChangeStatus = 0; + roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE; + } + + csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, + eCSR_ROAM_SET_CHANNEL_RSP, roamResult); + + } + else + { + status = eHAL_STATUS_FAILURE; + smsLog(pMac, LOGE, "Invalid Channel Change Resp Message: %d\n", + status); + } + vos_mem_free(pRoamInfo.channelChangeRespEvent); + + return status; +} + +/* ------------------------------------------------------------------------- + \fn sme_RoamStartBeaconReq + \brief API to Indicate LIM to start Beacon Tx + \after SAP CAC Wait is completed. + \param hHal - The handle returned by macOpen + \param sessionId - session ID + \param dfsCacWaitStatus - CAC WAIT status flag + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamStartBeaconReq( tHalHandle hHal, tCsrBssid bssid, + tANI_U8 dfsCacWaitStatus) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamStartBeaconReq( pMac, bssid, dfsCacWaitStatus); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* ------------------------------------------------------------------------- + \fn sme_RoamCsaIeRequest + \brief API to request CSA IE transmission from PE + \param hHal - The handle returned by macOpen + \param pDfsCsaReq - CSA IE request + \param bssid - SAP bssid + \param ch_bandwidth - Channel offset + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_RoamCsaIeRequest(tHalHandle hHal, tCsrBssid bssid, + tANI_U8 targetChannel, + tANI_U8 csaIeReqd, + u_int8_t ch_bandwidth) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamSendChanSwIERequest(pMac, bssid, targetChannel, + csaIeReqd, ch_bandwidth); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_InitThermalInfo + \brief SME API to initialize the thermal mitigation parameters + \param hHal + \param thermalParam : thermal mitigation parameters + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_InitThermalInfo( tHalHandle hHal, + tSmeThermalParams thermalParam ) +{ + t_thermal_mgmt * pWdaParam; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pWdaParam = (t_thermal_mgmt *)vos_mem_malloc(sizeof(t_thermal_mgmt)); + if (NULL == pWdaParam) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: could not allocate tThermalMgmt", __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + vos_mem_zero((void*)pWdaParam, sizeof(t_thermal_mgmt)); + + pWdaParam->thermalMgmtEnabled = thermalParam.smeThermalMgmtEnabled; + pWdaParam->throttlePeriod = thermalParam.smeThrottlePeriod; + pWdaParam->thermalLevels[0].minTempThreshold = + thermalParam.smeThermalLevels[0].smeMinTempThreshold; + pWdaParam->thermalLevels[0].maxTempThreshold = + thermalParam.smeThermalLevels[0].smeMaxTempThreshold; + pWdaParam->thermalLevels[1].minTempThreshold = + thermalParam.smeThermalLevels[1].smeMinTempThreshold; + pWdaParam->thermalLevels[1].maxTempThreshold = + thermalParam.smeThermalLevels[1].smeMaxTempThreshold; + pWdaParam->thermalLevels[2].minTempThreshold = + thermalParam.smeThermalLevels[2].smeMinTempThreshold; + pWdaParam->thermalLevels[2].maxTempThreshold = + thermalParam.smeThermalLevels[2].smeMaxTempThreshold; + pWdaParam->thermalLevels[3].minTempThreshold = + thermalParam.smeThermalLevels[3].smeMinTempThreshold; + pWdaParam->thermalLevels[3].maxTempThreshold = + thermalParam.smeThermalLevels[3].smeMaxTempThreshold; + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) + { + msg.type = WDA_INIT_THERMAL_INFO_CMD; + msg.bodyptr = pWdaParam; + + if (!VOS_IS_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_THERMAL_INFO_CMD to WDA!", + __func__); + vos_mem_free(pWdaParam); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_SUCCESS; + } + vos_mem_free(pWdaParam); + return eHAL_STATUS_FAILURE; +} + +/* + * Plug in set thermal level callback + */ +void sme_add_set_thermal_level_callback(tHalHandle hHal, + tSmeSetThermalLevelCallback callback) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pMac->sme.set_thermal_level_cb = callback; +} + +/** + * sme_SetThermalLevel() - SME API to set the thermal mitigation level + * hHal: Handler to HAL + * level: Thermal mitigation level + * + * Return: HAL status code + */ +eHalStatus sme_SetThermalLevel( tHalHandle hHal, tANI_U8 level ) +{ + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) { + vos_mem_set(&msg, sizeof(msg), 0); + msg.type = WDA_SET_THERMAL_LEVEL; + msg.bodyval = level; + + vosStatus = vos_mq_post_message(VOS_MODULE_ID_WDA, &msg); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_THERMAL_LEVEL to WDA!", + __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_SUCCESS; + } + return eHAL_STATUS_FAILURE; +} + + +/* --------------------------------------------------------------------------- + \fn sme_TxpowerLimit + \brief SME API to set txpower limits + \param hHal + \param psmetx : power limits for 2g/5g + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_TxpowerLimit(tHalHandle hHal, tSirTxPowerLimit *psmetx) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + vos_msg_t vosMessage; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + vosMessage.type = WDA_TX_POWER_LIMIT; + vosMessage.reserved = 0; + vosMessage.bodyptr = psmetx; + + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: not able to post WDA_TX_POWER_LIMIT", + __func__); + status = eHAL_STATUS_FAILURE; + vos_mem_free(psmetx); + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); +} + +eHalStatus sme_UpdateConnectDebug(tHalHandle hHal, tANI_U32 set_value) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->fEnableDebugLog = set_value; + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_ApDisableIntraBssFwd + + \brief + SME will send message to WMA to set Intra BSS in txrx + + \param + + hHal - The handle returned by macOpen + + sessionId - session id ( vdev id) + + disablefwd - boolean value that indicate disable intrabss fwd disable + + \return eHalStatus +--------------------------------------------------------------------------- */ +eHalStatus sme_ApDisableIntraBssFwd(tHalHandle hHal, tANI_U8 sessionId, + tANI_BOOLEAN disablefwd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + int status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + vos_msg_t vosMessage; + tpDisableIntraBssFwd pSapDisableIntraFwd = NULL; + + //Prepare the request to send to SME. + pSapDisableIntraFwd = vos_mem_malloc(sizeof(tDisableIntraBssFwd)); + if (NULL == pSapDisableIntraFwd) + { + smsLog(pMac, LOGP, "Memory Allocation Failure!!! %s", __func__); + return eSIR_MEM_ALLOC_FAILED; + } + + vos_mem_zero(pSapDisableIntraFwd, sizeof(tDisableIntraBssFwd)); + + pSapDisableIntraFwd->sessionId = sessionId; + pSapDisableIntraFwd->disableintrabssfwd = disablefwd; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + /* serialize the req through MC thread */ + vosMessage.bodyptr = pSapDisableIntraFwd; + vosMessage.type = WDA_SET_SAP_INTRABSS_DIS; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + status = eHAL_STATUS_FAILURE; + vos_mem_free(pSapDisableIntraFwd); + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return (status); +} + +#ifdef WLAN_FEATURE_STATS_EXT + +/****************************************************************************** + \fn sme_StatsExtRegisterCallback + + \brief + a function called to register the callback that send vendor event for stats + ext + + \param callback - callback to be registered +******************************************************************************/ +void sme_StatsExtRegisterCallback(tHalHandle hHal, StatsExtCallback callback) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pMac->sme.StatsExtCallback = callback; +} + +/****************************************************************************** + \fn sme_StatsExtRequest + + \brief + a function called when HDD receives STATS EXT vendor command from user space + + \param sessionID - vdevID for the stats ext request + + \param input - Stats Ext Request structure ptr + + \return eHalStatus +******************************************************************************/ +eHalStatus sme_StatsExtRequest(tANI_U8 session_id, tpStatsExtRequestReq input) +{ + vos_msg_t msg; + tpStatsExtRequest data; + size_t data_len; + + data_len = sizeof(tStatsExtRequest) + input->request_data_len; + data = vos_mem_malloc(data_len); + + if (data == NULL) { + return eHAL_STATUS_FAILURE; + } + + vos_mem_zero(data, data_len); + data->vdev_id = session_id; + 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.type = WDA_STATS_EXT_REQUEST; + msg.reserved = 0; + msg.bodyptr = data; + + 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_STATS_EXT_REQUEST message to WDA", + __func__); + vos_mem_free(data); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + + +/****************************************************************************** + \fn sme_StatsExtEvent + + \brief + a callback function called when SME received eWNI_SME_STATS_EXT_EVENT + response from WDA + + \param hHal - HAL handle for device + \param pMsg - Message body passed from WDA; includes NAN header + \return eHalStatus +******************************************************************************/ +eHalStatus sme_StatsExtEvent(tHalHandle hHal, void* pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + if (NULL == pMsg) { + smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = eHAL_STATUS_FAILURE; + } else { + smsLog(pMac, LOG2, "SME: entering %s", __func__); + + if (pMac->sme.StatsExtCallback) { + pMac->sme.StatsExtCallback(pMac->hHdd, (tpStatsExtEvent)pMsg); + } + } + + return status; +} + +#endif + +#if defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) +/** + * sme_init_bad_peer_txctl_info() - SME API to initialize the bad peer + * tx flow control parameters + * @hHal: handle of Hal. + * @param: Configuration of SME module. + * + * Read configuation from SME module setting, and then update the setting + * to WMA module. + * + * Return: Status of the WMA message sending + */ +eHalStatus sme_init_bad_peer_txctl_info( tHalHandle hHal, + struct sme_bad_peer_txctl_param param ) +{ + struct t_bad_peer_txtcl_config *p_config; + vos_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + int i = 0; + + p_config = vos_mem_malloc(sizeof(struct t_bad_peer_txtcl_config)); + if (NULL == p_config) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: could not allocate tBadPeerInfo", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + vos_mem_zero((void*)p_config, sizeof(struct t_bad_peer_txtcl_config)); + p_config->enable = param.enabled; + p_config->period = param.period; + p_config->txq_limit = param.txq_limit; + p_config->tgt_backoff = param.tgt_backoff; + p_config->tgt_report_prd = param.tgt_report_prd; + + for (i = 0; i <= WLAN_WMA_IEEE80211_AC_LEVEL; i++) { + p_config->threshold[i].cond = param.thresh[i].cond; + p_config->threshold[i].delta = param.thresh[i].delta; + p_config->threshold[i].percentage = param.thresh[i].percentage; + p_config->threshold[i].thresh[0] = param.thresh[i].thresh; + p_config->threshold[i].txlimit = param.thresh[i].limit; + } + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) { + msg.type = WDA_INIT_BAD_PEER_TX_CTL_INFO_CMD; + msg.bodyptr = p_config; + + if (!VOS_IS_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_INIT_BAD_PEER_TX_CTL_INFO_CMD to WDA!", + __func__); + + vos_mem_free(p_config); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_SUCCESS; + } + vos_mem_free(p_config); + return eHAL_STATUS_FAILURE; +} +#endif /* defined(CONFIG_HL_SUPPORT) && defined(QCA_BAD_PEER_TX_FLOW_CL) */ + +/* --------------------------------------------------------------------------- + \fn sme_UpdateDFSScanMode + \brief Update DFS roam scan mode + This function is called through dynamic setConfig callback function + to configure allowDFSChannelRoam. + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \param allowDFSChannelRoam - DFS roaming scan mode 0 (disable), + 1 (passive), 2 (active) + \return eHAL_STATUS_SUCCESS - SME update DFS roaming scan config + successfully. + Other status means SME failed to update DFS roaming scan config. + \sa + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateDFSScanMode(tHalHandle hHal, tANI_U8 sessionId, + v_U8_t allowDFSChannelRoam) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set AllowDFSChannelRoam Mode to " + "%d - old value is %d - roam state is %s", + allowDFSChannelRoam, + pMac->roam.configParam.allowDFSChannelRoam, + macTraceGetNeighbourRoamState( + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState)); + pMac->roam.configParam.allowDFSChannelRoam = allowDFSChannelRoam; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_DFS_SCAN_MODE_CHANGED); + } +#endif + + return status ; +} + +/*-------------------------------------------------------------------------- + \brief sme_GetDFSScanMode() - get DFS roam scan mode + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return DFS roaming scan mode 0 (disable), 1 (passive), 2 (active) + \sa + --------------------------------------------------------------------------*/ +v_U8_t sme_GetDFSScanMode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.allowDFSChannelRoam; +} + + +/*---------------------------------------------------------------------------- + \fn sme_ModifyAddIE + \brief This function sends msg to updates the additional IE buffers in PE + \param hHal - global structure + \param pModifyIE - pointer to tModifyIE structure + \param updateType - type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus sme_ModifyAddIE(tHalHandle hHal, + tSirModifyIE *pModifyIE, + eUpdateIEsType updateType) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamModifyAddIEs(pMac, pModifyIE, updateType); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/*---------------------------------------------------------------------------- + \fn sme_UpdateAddIE + \brief This function sends msg to updates the additional IE buffers in PE + \param hHal - global structure + \param pUpdateIE - pointer to structure tUpdateIE + \param updateType - type of buffer + \- return Success or failure +-----------------------------------------------------------------------------*/ +eHalStatus sme_UpdateAddIE(tHalHandle hHal, + tSirUpdateIE *pUpdateIE, + eUpdateIEsType updateType) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + status = sme_AcquireGlobalLock( &pMac->sme ); + + if ( HAL_STATUS_SUCCESS( status ) ) + { + status = csrRoamUpdateAddIEs(pMac, pUpdateIE, updateType); + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_staInMiddleOfRoaming + \brief This function returns TRUE if STA is in the middle of roaming state + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \- return TRUE or FALSE + -------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_staInMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN ret = FALSE; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + ret = csrNeighborMiddleOfRoaming(hHal, sessionId); + sme_ReleaseGlobalLock(&pMac->sme); + } + return ret; +} + +/* --------------------------------------------------------------------------- + \fn sme_PsOffloadIsStaInPowerSave + \brief This function returns TRUE if STA is in power save + \param hHal - HAL handle for device + \param sessionId - Session Identifier + \return TRUE or FALSE + -------------------------------------------------------------------------*/ +tANI_BOOLEAN sme_PsOffloadIsStaInPowerSave(tHalHandle hHal, tANI_U8 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_BOOLEAN ret = FALSE; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + ret = pmcOffloadIsStaInPowerSave(pMac, sessionId); + sme_ReleaseGlobalLock(&pMac->sme); + } + return ret; +} + +VOS_STATUS sme_UpdateDSCPtoUPMapping( tHalHandle hHal, + sme_QosWmmUpType *dscpmapping, + v_U8_t sessionId ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + v_U8_t i, j, peSessionId; + tCsrRoamSession *pCsrSession = NULL; + tpPESession pSession = NULL; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pCsrSession = CSR_GET_SESSION( pMac, sessionId ); + if (pCsrSession == NULL) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Session lookup fails for CSR session", __func__); + sme_ReleaseGlobalLock( &pMac->sme); + return eHAL_STATUS_FAILURE; + } + if (!CSR_IS_SESSION_VALID( pMac, sessionId )) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid session Id %u", __func__, sessionId); + sme_ReleaseGlobalLock( &pMac->sme); + return eHAL_STATUS_FAILURE; + } + + pSession = peFindSessionByBssid( pMac, + pCsrSession->connectedProfile.bssid, &peSessionId ); + + if (pSession == NULL) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Session lookup fails for BSSID", __func__); + sme_ReleaseGlobalLock( &pMac->sme); + return eHAL_STATUS_FAILURE; + } + + if (!pSession->QosMapSet.present) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, + FL("QOS Mapping IE not present")); + sme_ReleaseGlobalLock( &pMac->sme); + return eHAL_STATUS_FAILURE; + } + else + { + for (i = 0; i < SME_QOS_WMM_UP_MAX; i++) + { + for (j = pSession->QosMapSet.dscp_range[i][0]; + j <= pSession->QosMapSet.dscp_range[i][1]; j++) + { + if ((pSession->QosMapSet.dscp_range[i][0] == 255) && + (pSession->QosMapSet.dscp_range[i][1] == 255)) + { + dscpmapping[j]= 0; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: User Priority %d is not used in mapping", + __func__, i); + break; + } + else + { + dscpmapping[j]= i; + } + } + } + for (i = 0; i< pSession->QosMapSet.num_dscp_exceptions; i++) + { + if (pSession->QosMapSet.dscp_exceptions[i][0] != 255) + { + dscpmapping[pSession->QosMapSet.dscp_exceptions[i][0] ] = + pSession->QosMapSet.dscp_exceptions[i][1]; + } + } + } + } + sme_ReleaseGlobalLock( &pMac->sme); + return status; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_abortRoamScan + \brief API to abort current roam scan cycle by roam scan offload module. + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \return eHalStatus + ---------------------------------------------------------------------------*/ + +eHalStatus sme_abortRoamScan(tHalHandle hHal, tANI_U8 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + smsLog(pMac, LOGW, "entering function %s", __func__); + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + /* acquire the lock for the sme object */ + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + csrRoamOffloadScan(pMac, sessionId, ROAM_SCAN_OFFLOAD_ABORT_SCAN, + REASON_ROAM_ABORT_ROAM_SCAN); + /* release the lock for the sme object */ + sme_ReleaseGlobalLock( &pMac->sme ); + } + } + + return(status); +} +#endif //#if WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +#ifdef FEATURE_WLAN_EXTSCAN +/* --------------------------------------------------------------------------- + \fn sme_GetValidChannelsByBand + \brief SME API to fetch all valid channels filtered by band + \param hHal + \param wifiBand: RF band information + \param aValidChannels: output array to store channel info + \param pNumChannels: output number of channels + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetValidChannelsByBand(tHalHandle hHal, + tANI_U8 wifiBand, + tANI_U32 *aValidChannels, + tANI_U8 *pNumChannels) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tANI_U8 chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tANI_U8 numChannels = 0; + tANI_U8 i = 0; + tANI_U32 totValidChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if (!aValidChannels || !pNumChannels) { + smsLog(pMac, VOS_TRACE_LEVEL_ERROR, + FL("Output channel list/NumChannels is NULL")); + return eHAL_STATUS_INVALID_PARAMETER; + } + + if ((wifiBand < WIFI_BAND_UNSPECIFIED) || (wifiBand >= WIFI_BAND_MAX)) { + smsLog(pMac, VOS_TRACE_LEVEL_ERROR, + FL("Invalid wifiBand (%d)"), wifiBand); + return eHAL_STATUS_INVALID_PARAMETER; + } + + status = sme_GetCfgValidChannels(hHal, &chanList[0], + &totValidChannels); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, VOS_TRACE_LEVEL_ERROR, + FL("Failed to get valid channel list (err=%d)"), status); + return status; + } + + switch (wifiBand) { + case WIFI_BAND_UNSPECIFIED: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, FL("Unspecified wifiBand, " + "return all (%d) valid channels"), totValidChannels); + numChannels = totValidChannels; + for (i = 0; i < totValidChannels; i++) { + aValidChannels[i] = vos_chan_to_freq(chanList[i]); + } + break; + + case WIFI_BAND_BG: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, FL("WIFI_BAND_BG (2.4 GHz)")); + for (i = 0; i < totValidChannels; i++) { + if (CSR_IS_CHANNEL_24GHZ(chanList[i])) { + aValidChannels[numChannels++] = + vos_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_A: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, + FL("WIFI_BAND_A (5 GHz without DFS)")); + for (i = 0; i < totValidChannels; i++) { + if (CSR_IS_CHANNEL_5GHZ(chanList[i]) && + !CSR_IS_CHANNEL_DFS(chanList[i])) { + aValidChannels[numChannels++] = + vos_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_ABG: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, + FL("WIFI_BAND_ABG (2.4 GHz + 5 GHz; no DFS)")); + for (i = 0; i < totValidChannels; i++) { + if ((CSR_IS_CHANNEL_24GHZ(chanList[i]) || + CSR_IS_CHANNEL_5GHZ(chanList[i])) && + !CSR_IS_CHANNEL_DFS(chanList[i])) { + aValidChannels[numChannels++] = + vos_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_A_DFS_ONLY: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, + FL("WIFI_BAND_A_DFS (5 GHz DFS only)")); + for (i = 0; i < totValidChannels; i++) { + if (CSR_IS_CHANNEL_5GHZ(chanList[i]) && + CSR_IS_CHANNEL_DFS(chanList[i])) { + aValidChannels[numChannels++] = + vos_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_A_WITH_DFS: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, + FL("WIFI_BAND_A_WITH_DFS (5 GHz with DFS)")); + for (i = 0; i < totValidChannels; i++) { + if (CSR_IS_CHANNEL_5GHZ(chanList[i])) { + aValidChannels[numChannels++] = + vos_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_ABG_WITH_DFS: + smsLog(pMac, VOS_TRACE_LEVEL_INFO, + FL("WIFI_BAND_ABG_WITH_DFS (2.4 GHz + 5 GHz with DFS)")); + for (i = 0; i < totValidChannels; i++) { + if (CSR_IS_CHANNEL_24GHZ(chanList[i]) || + CSR_IS_CHANNEL_5GHZ(chanList[i])) { + aValidChannels[numChannels++] = + vos_chan_to_freq(chanList[i]); + } + } + break; + + default: + smsLog(pMac, VOS_TRACE_LEVEL_ERROR, + FL("Unknown wifiBand (%d))"), wifiBand); + return eHAL_STATUS_INVALID_PARAMETER; + break; + } + *pNumChannels = numChannels; + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanGetCapabilities + \brief SME API to fetch extscan capabilities + \param hHal + \param pReq: extscan capabilities structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanGetCapabilities (tHalHandle hHal, + tSirGetExtScanCapabilitiesReqParams *pReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pReq; + vosMessage.type = WDA_EXTSCAN_GET_CAPABILITIES_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanStart + \brief SME API to issue extscan start + \param hHal + \param pStartCmd: extscan start structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanStart (tHalHandle hHal, + tSirWifiScanCmdReqParams *pStartCmd) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pStartCmd; + vosMessage.type = WDA_EXTSCAN_START_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ExtScanStop + \brief SME API to issue extscan stop + \param hHal + \param pStopReq: extscan stop structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ExtScanStop(tHalHandle hHal, tSirExtScanStopReqParams *pStopReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pStopReq; + vosMessage.type = WDA_EXTSCAN_STOP_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetBssHotlist + \brief SME API to set BSSID hotlist + \param hHal + \param pSetHotListReq: extscan set hotlist structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetBssHotlist (tHalHandle hHal, + tSirExtScanSetBssidHotListReqParams *pSetHotListReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pSetHotListReq; + vosMessage.type = WDA_EXTSCAN_SET_BSSID_HOTLIST_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ResetBssHotlist + \brief SME API to reset BSSID hotlist + \param hHal + \param pSetHotListReq: extscan set hotlist structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ResetBssHotlist (tHalHandle hHal, + tSirExtScanResetBssidHotlistReqParams *pResetReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pResetReq; + vosMessage.type = WDA_EXTSCAN_RESET_BSSID_HOTLIST_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/** + * sme_set_ssid_hotlist() - Set the SSID hotlist + * @hal: SME handle + * @request: set ssid hotlist request + * + * Return: eHalStatus + */ +eHalStatus +sme_set_ssid_hotlist(tHalHandle hal, + struct sir_set_ssid_hotlist_request *request) +{ + eHalStatus status; + VOS_STATUS vstatus; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vos_message; + struct sir_set_ssid_hotlist_request *set_req; + + set_req = vos_mem_malloc(sizeof(*set_req)); + if (!set_req) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_EXTSCAN_SET_SSID_HOTLIST_REQ", + __func__); + return eHAL_STATUS_FAILURE; + } + + *set_req = *request; + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* Serialize the req through MC thread */ + vos_message.bodyptr = set_req; + vos_message.type = WDA_EXTSCAN_SET_SSID_HOTLIST_REQ; + vstatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + sme_ReleaseGlobalLock(&mac->sme); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) { + vos_mem_free(set_req); + status = eHAL_STATUS_FAILURE; + } + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error", __func__); + vos_mem_free(set_req); + status = eHAL_STATUS_FAILURE; + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetSignificantChange + \brief SME API to set significant change + \param hHal + \param pSetSignificantChangeReq: extscan set significant change structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetSignificantChange (tHalHandle hHal, + tSirExtScanSetSigChangeReqParams *pSetSignificantChangeReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pSetSignificantChangeReq; + vosMessage.type = WDA_EXTSCAN_SET_SIGNF_CHANGE_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ResetSignificantChange + \brief SME API to reset significant change + \param hHal + \param pResetReq: extscan reset significant change structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_ResetSignificantChange (tHalHandle hHal, + tSirExtScanResetSignificantChangeReqParams *pResetReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pResetReq; + vosMessage.type = WDA_EXTSCAN_RESET_SIGNF_CHANGE_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_getCachedResults + \brief SME API to get cached results + \param hHal + \param pCachedResultsReq: extscan get cached results structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_getCachedResults (tHalHandle hHal, + tSirExtScanGetCachedResultsReqParams *pCachedResultsReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pCachedResultsReq; + vosMessage.type = WDA_EXTSCAN_GET_CACHED_RESULTS_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/** + * sme_set_epno_list() - set epno network list + * @hHal: global hal handle + * @input: request message + * + * This function constructs the vos message and fill in message type, + * bodyptr with %input and posts it to WDA queue. + * + * Return: eHalStatus enumeration + */ +eHalStatus sme_set_epno_list(tHalHandle hal, + struct wifi_epno_params *input) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vos_message; + struct wifi_epno_params *req_msg; + int len, i; + + smsLog(mac, LOG1, FL("enter")); + len = sizeof(*req_msg) + + (input->num_networks * sizeof(struct wifi_epno_network)); + req_msg = vos_mem_malloc(len); + if (!req_msg) { + smsLog(mac, LOGE, FL("vos_mem_malloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(req_msg, len); + req_msg->num_networks = input->num_networks; + req_msg->request_id = input->request_id; + req_msg->session_id = input->session_id; + for (i = 0; i < req_msg->num_networks; i++) { + req_msg->networks[i].rssi_threshold = + input->networks[i].rssi_threshold; + req_msg->networks[i].flags = input->networks[i].flags; + req_msg->networks[i].auth_bit_field = + input->networks[i].auth_bit_field; + req_msg->networks[i].ssid.length = + input->networks[i].ssid.length; + vos_mem_copy(req_msg->networks[i].ssid.ssId, + input->networks[i].ssid.ssId, + req_msg->networks[i].ssid.length); + } + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + vos_message.bodyptr = req_msg; + vos_message.type = WDA_SET_EPNO_LIST_REQ; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +/** + * sme_set_passpoint_list() - set passpoint network list + * @hal: global hal handle + * @input: request message + * + * This function constructs the vos message and fill in message type, + * bodyptr with @input and posts it to WDA queue. + * + * Return: eHalStatus enumeration + */ +eHalStatus sme_set_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *input) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vos_message; + struct wifi_passpoint_req *req_msg; + int len, i; + + smsLog(mac, LOG1, FL("enter")); + len = sizeof(*req_msg) + + (input->num_networks * sizeof(struct wifi_passpoint_network)); + req_msg = vos_mem_malloc(len); + if (!req_msg) { + smsLog(mac, LOGE, FL("vos_mem_malloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(req_msg, len); + req_msg->num_networks = input->num_networks; + req_msg->request_id = input->request_id; + req_msg->session_id = input->session_id; + for (i = 0; i < req_msg->num_networks; i++) { + req_msg->networks[i].id = + input->networks[i].id; + vos_mem_copy(req_msg->networks[i].realm, + input->networks[i].realm, + strlen(input->networks[i].realm) + 1); + vos_mem_copy(req_msg->networks[i].plmn, + input->networks[i].plmn, + SIR_PASSPOINT_PLMN_LEN); + vos_mem_copy(req_msg->networks[i].roaming_consortium_ids, + input->networks[i].roaming_consortium_ids, + sizeof(req_msg->networks[i].roaming_consortium_ids)); + } + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + vos_message.bodyptr = req_msg; + vos_message.type = WDA_SET_PASSPOINT_LIST_REQ; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +/** + * sme_reset_passpoint_list() - reset passpoint network list + * @hHal: global hal handle + * @input: request message + * + * Return: eHalStatus enumeration + */ +eHalStatus sme_reset_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *input) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vos_message; + struct wifi_passpoint_req *req_msg; + + smsLog(mac, LOG1, FL("enter")); + req_msg = vos_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + smsLog(mac, LOGE, FL("vos_mem_malloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(req_msg, sizeof(*req_msg)); + req_msg->request_id = input->request_id; + req_msg->session_id = input->session_id; + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + vos_message.bodyptr = req_msg; + vos_message.type = WDA_RESET_PASSPOINT_LIST_REQ; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +eHalStatus sme_ExtScanRegisterCallback (tHalHandle hHal, + void (*pExtScanIndCb)(void *, const tANI_U16, void *)) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + pMac->sme.pExtScanIndCb = pExtScanIndCb; + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +#endif /* FEATURE_WLAN_EXTSCAN */ + +/** + * sme_set_rssi_threshold_breached_cb() - set rssi threshold breached callback + * @hal: global hal handle + * @cb: callback function pointer + * + * This function stores the rssi threshold breached callback function. + * + * Return: eHalStatus enumeration. + */ +eHalStatus sme_set_rssi_threshold_breached_cb(tHalHandle hal, + void (*cb)(void *, struct rssi_breach_event *)) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + return status; + } + + mac->sme.rssi_threshold_breached_cb = cb; + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +/** + * sme_set_rssi_monitoring() - set rssi monitoring + * @hal: global hal handle + * @input: request message + * + * This function constructs the vos message and fill in message type, + * bodyptr with @input and posts it to WDA queue. + * + * Return: eHalStatus enumeration + */ +eHalStatus sme_set_rssi_monitoring(tHalHandle hal, + struct rssi_monitor_req *input) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vos_message; + struct rssi_monitor_req *req_msg; + + smsLog(mac, LOG1, FL("enter")); + req_msg = vos_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + smsLog(mac, LOGE, FL("memory allocation failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + *req_msg = *input; + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + vos_message.bodyptr = req_msg; + vos_message.type = WDA_SET_RSSI_MONITOR_REQ; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + } + sme_ReleaseGlobalLock(&mac->sme); + + return status; +} + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +/* --------------------------------------------------------------------------- + \fn sme_LLStatsClearReq + \brief SME API to clear Link Layer Statistics + \param hHal + \param pclearStatsReq: Link Layer clear stats request params structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_LLStatsClearReq (tHalHandle hHal, + tSirLLStatsClearReq *pclearStatsReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tSirLLStatsClearReq *clear_stats_req; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "staId = %u", pclearStatsReq->staId); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "statsClearReqMask = 0x%X", + pclearStatsReq->statsClearReqMask); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "stopReq = %u", pclearStatsReq->stopReq); + + clear_stats_req = vos_mem_malloc(sizeof(*clear_stats_req)); + + if (!clear_stats_req) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_LL_STATS_CLEAR_REQ", + __func__); + return eHAL_STATUS_FAILURE; + } + + *clear_stats_req = *pclearStatsReq; + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) + { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = clear_stats_req; + vosMessage.type = WDA_LINK_LAYER_STATS_CLEAR_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: not able to post WDA_LL_STATS_CLEAR_REQ", + __func__); + vos_mem_free(clear_stats_req); + 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(clear_stats_req); + status = eHAL_STATUS_FAILURE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_LLStatsSetReq + \brief SME API to set the Link Layer Statistics + \param hHal + \param psetStatsReq: Link Layer set stats request params structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_LLStatsSetReq (tHalHandle hHal, + tSirLLStatsSetReq *psetStatsReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tSirLLStatsSetReq *set_stats_req; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: MPDU Size = %u", __func__, + psetStatsReq->mpduSizeThreshold); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + " Aggressive Stats Collections = %u", + psetStatsReq->aggressiveStatisticsGathering); + + set_stats_req = vos_mem_malloc(sizeof(*set_stats_req)); + + if (!set_stats_req) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_LL_STATS_SET_REQ", + __func__); + return eHAL_STATUS_FAILURE; + } + + *set_stats_req = *psetStatsReq; + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) + { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = set_stats_req; + vosMessage.type = WDA_LINK_LAYER_STATS_SET_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: not able to post WDA_LL_STATS_SET_REQ", + __func__); + vos_mem_free(set_stats_req); + 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(set_stats_req); + status = eHAL_STATUS_FAILURE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_LLStatsGetReq + \brief SME API to get the Link Layer Statistics + \param hHal + \param pgetStatsReq: Link Layer get stats request params structure + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_LLStatsGetReq (tHalHandle hHal, + tSirLLStatsGetReq *pgetStatsReq) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tSirLLStatsGetReq *get_stats_req; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "reqId = %u", pgetStatsReq->reqId); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "staId = %u", pgetStatsReq->staId); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "Stats Type = %u", pgetStatsReq->paramIdMask); + + get_stats_req = vos_mem_malloc(sizeof(*get_stats_req)); + + if (!get_stats_req) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_LL_STATS_GET_REQ", + __func__); + return eHAL_STATUS_FAILURE; + } + + *get_stats_req = *pgetStatsReq; + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) + { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = get_stats_req; + vosMessage.type = WDA_LINK_LAYER_STATS_GET_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: not able to post WDA_LL_STATS_GET_REQ", + __func__); + + vos_mem_free(get_stats_req); + 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(get_stats_req); + status = eHAL_STATUS_FAILURE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetLinkLayerStatsIndCB + \brief SME API to trigger the stats are available after get request + \param hHal + \param callbackRoutine - HDD callback which needs to be invoked after + getting status notification from FW + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetLinkLayerStatsIndCB +( + tHalHandle hHal, + void (*callbackRoutine) (void *callbackCtx, int indType, void *pRsp) +) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + pMac->sme.pLinkLayerStatsIndCallback = callbackRoutine; + sme_ReleaseGlobalLock(&pMac->sme); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: " + "sme_AcquireGlobalLock error", __func__); + } + + return(status); +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +/** + * sme_fw_mem_dump_register_cb() - Register fw memory dump callback + * + * @hHal - MAC global handle + * @callback_routine - callback routine from HDD + * + * This API is invoked by HDD to register its callback in SME + * + * Return: eHalStatus + */ +#ifdef WLAN_FEATURE_MEMDUMP +eHalStatus sme_fw_mem_dump_register_cb(tHalHandle hal, + void (*callback_routine)(void *cb_context, + struct fw_dump_rsp *rsp)) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + + status = sme_AcquireGlobalLock(&pmac->sme); + if (eHAL_STATUS_SUCCESS == status) { + pmac->sme.fw_dump_callback = callback_routine; + sme_ReleaseGlobalLock(&pmac->sme); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("sme_AcquireGlobalLock error")); + } + + return status; +} +#else +eHalStatus sme_fw_mem_dump_register_cb(tHalHandle hal, + void (*callback_routine)(void *cb_context, + struct fw_dump_rsp *rsp)) +{ + return eHAL_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +/** + * sme_fw_mem_dump_unregister_cb() - Unregister fw memory dump callback + * + * @hHal - MAC global handle + * + * This API is invoked by HDD to unregister its callback in SME + * + * Return: eHalStatus + */ +#ifdef WLAN_FEATURE_MEMDUMP +eHalStatus sme_fw_mem_dump_unregister_cb(tHalHandle hal) +{ + eHalStatus status; + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + + status = sme_AcquireGlobalLock(&pmac->sme); + if (eHAL_STATUS_SUCCESS == status) { + pmac->sme.fw_dump_callback = NULL; + sme_ReleaseGlobalLock(&pmac->sme); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("sme_AcquireGlobalLock error")); + } + + return status; +} +#else +eHalStatus sme_fw_mem_dump_unregister_cb(tHalHandle hal) +{ + return eHAL_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamOffloadEnabled() - enable/disable roam offload feature + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + \param hHal - The handle returned by macOpen. + \param nRoamOffloadEnabled - The boolean to update with + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamOffloadEnabled(tHalHandle hHal, + v_BOOL_t nRoamOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: LFR3:gRoamOffloadEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isRoamOffloadEnabled, + nRoamOffloadEnabled); + pMac->roam.configParam.isRoamOffloadEnabled = nRoamOffloadEnabled; + sme_ReleaseGlobalLock(&pMac->sme); + } + + return status ; +} + +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamKeyMgmtOffloadEnabled() - enable/disable key mgmt offload + This is a synchronous call + \param hHal - The handle returned by macOpen. + \param sessionId - Session Identifier + \param nRoamKeyMgmtOffloadEnabled - The boolean to update with + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamKeyMgmtOffloadEnabled(tHalHandle hHal, + tANI_U8 sessionId, + v_BOOL_t nRoamKeyMgmtOffloadEnabled) + +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: LFR3: KeyMgmtOffloadEnabled changed to %d", + __func__, + nRoamKeyMgmtOffloadEnabled); + status = csrRoamSetKeyMgmtOffload(pMac, + sessionId, + nRoamKeyMgmtOffloadEnabled); + } else { + status = eHAL_STATUS_INVALID_PARAMETER; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + + return status ; +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_GetTemperature + \brief SME API to get the pdev temperature + \param hHal + \param temperature context + \param pCallbackfn: callback fn with response (temperature) + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_GetTemperature(tHalHandle hHal, + void *tempContext, + void (*pCallbackfn)(int temperature, void *pContext)) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + if ( (NULL == pCallbackfn) && + (NULL == pMac->sme.pGetTemperatureCb)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Indication Call back did not registered")); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + else if (NULL != pCallbackfn) + { + pMac->sme.pTemperatureCbContext = tempContext; + pMac->sme.pGetTemperatureCb = pCallbackfn; + } + /* serialize the req through MC thread */ + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_GET_TEMPERATURE_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Post Get Temperature msg fail")); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_SetScanningMacOui + \brief SME API to set scanning mac oui + \param hHal + \param pScanMacOui: Scanning Mac Oui (input 3 bytes) + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SetScanningMacOui(tHalHandle hHal, tSirScanMacOui *pScanMacOui) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = pScanMacOui; + vosMessage.type = WDA_SET_SCAN_MAC_OUI_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Msg post Set Scan Mac OUI failed")); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +#ifdef DHCP_SERVER_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_setDhcpSrvOffload + \brief SME API to set DHCP server offload info + \param hHal + \param pDhcpSrvInfo : DHCP server offload info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setDhcpSrvOffload(tHalHandle hHal, + tSirDhcpSrvOffloadInfo *pDhcpSrvInfo) +{ + vos_msg_t vosMessage; + tSirDhcpSrvOffloadInfo *pSmeDhcpSrvInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pSmeDhcpSrvInfo = vos_mem_malloc(sizeof(*pSmeDhcpSrvInfo)); + + if (!pSmeDhcpSrvInfo) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_SET_DHCP_SERVER_OFFLOAD_CMD", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + *pSmeDhcpSrvInfo = *pDhcpSrvInfo; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vosMessage.type = WDA_SET_DHCP_SERVER_OFFLOAD_CMD; + vosMessage.bodyptr = pSmeDhcpSrvInfo; + + 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_DHCP_SERVER_OFFLOAD_CMD to WDA!", + __func__); + vos_mem_free(pSmeDhcpSrvInfo); + 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(pSmeDhcpSrvInfo); + } + + return (status); +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +/* --------------------------------------------------------------------------- + \fn sme_SetLedFlashing + \brief API to set the Led flashing parameters. + \param hHal - The handle returned by macOpen. + \param x0, x1 - led flashing parameters + \param gpio_num - GPIO number + \return eHalStatus + ---------------------------------------------------------------------------*/ +eHalStatus sme_SetLedFlashing (tHalHandle hHal, tANI_U8 type, + tANI_U32 x0, tANI_U32 x1, tANI_U32 gpio_num) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tSirLedFlashingReq *ledflashing; + + ledflashing = vos_mem_malloc(sizeof(*ledflashing)); + if (!ledflashing) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for WDA_LED_TIMING_REQ")); + return eHAL_STATUS_FAILURE; + } + + ledflashing->pattern_id = type; + ledflashing->led_x0 = x0; + ledflashing->led_x1 = x1; + ledflashing->gpio_num = gpio_num; + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) { + /* Serialize the req through MC thread */ + vosMessage.bodyptr = ledflashing; + vosMessage.type = WDA_LED_FLASHING_REQ; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + status = eHAL_STATUS_FAILURE; + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_handle_dfS_chan_scan + \brief SME API to enable/disable DFS channel scan + \param hHal + \param dfs_flag: whether dfs needs to be enabled or disabled + \return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_handle_dfs_chan_scan(tHalHandle hHal, tANI_U8 dfs_flag) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_AcquireGlobalLock(&pMac->sme); + + if (eHAL_STATUS_SUCCESS == status) { + + pMac->scan.fEnableDFSChnlScan = dfs_flag; + + /* update the channel list to the firmware */ + status = csrUpdateChannelList(pMac); + + sme_ReleaseGlobalLock(&pMac->sme); + } + + return status; +} + +#ifdef MDNS_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_setMDNSOffload + \brief SME API to set mDNS offload info + \param hHal + \param pMDNSInfo : mDNS offload info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setMDNSOffload(tHalHandle hHal, + tSirMDNSOffloadInfo *pMDNSInfo) +{ + vos_msg_t vosMessage; + tSirMDNSOffloadInfo *pSmeMDNSOffloadInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pSmeMDNSOffloadInfo = vos_mem_malloc(sizeof(*pSmeMDNSOffloadInfo)); + + if (!pSmeMDNSOffloadInfo) { + 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; + } + + *pSmeMDNSOffloadInfo = *pMDNSInfo; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vosMessage.type = WDA_SET_MDNS_OFFLOAD_CMD; + vosMessage.bodyptr = pSmeMDNSOffloadInfo; + + 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_MDNS_OFFLOAD_CMD to WDA!", + __func__); + vos_mem_free(pSmeMDNSOffloadInfo); + 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(pSmeMDNSOffloadInfo); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_setMDNSFqdn + \brief SME API to set mDNS Fqdn info + \param hHal + \param pMDNSFqdnInfo : mDNS Fqdn info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setMDNSFqdn(tHalHandle hHal, + tSirMDNSFqdnInfo *pMDNSFqdnInfo) +{ + vos_msg_t vosMessage; + tSirMDNSFqdnInfo *pSmeMDNSFqdnInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pSmeMDNSFqdnInfo = vos_mem_malloc(sizeof(*pSmeMDNSFqdnInfo)); + + if (!pSmeMDNSFqdnInfo) { + 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; + } + + *pSmeMDNSFqdnInfo = *pMDNSFqdnInfo; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vosMessage.type = WDA_SET_MDNS_FQDN_CMD; + vosMessage.bodyptr = pSmeMDNSFqdnInfo; + + 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_MDNS_FQDN_CMD to WDA!", + __func__); + vos_mem_free(pSmeMDNSFqdnInfo); + 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(pSmeMDNSFqdnInfo); + } + + return (status); +} + +/* --------------------------------------------------------------------------- + \fn sme_setMDNSResponse + \brief SME API to set mDNS response info + \param hHal + \param pMDNSRespInfo : mDNS response info struct + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_setMDNSResponse(tHalHandle hHal, + tSirMDNSResponseInfo *pMDNSRespInfo) +{ + vos_msg_t vosMessage; + tSirMDNSResponseInfo *pSmeMDNSRespInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pSmeMDNSRespInfo = vos_mem_malloc(sizeof(*pSmeMDNSRespInfo)); + + if (!pSmeMDNSRespInfo) { + 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; + } + + *pSmeMDNSRespInfo = *pMDNSRespInfo; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vosMessage.type = WDA_SET_MDNS_RESPONSE_CMD; + vosMessage.bodyptr = pSmeMDNSRespInfo; + + 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_MDNS_RESPONSE_CMD to WDA!", + __func__); + vos_mem_free(pSmeMDNSRespInfo); + 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(pSmeMDNSRespInfo); + } + + return (status); +} +#endif /* MDNS_OFFLOAD */ + +#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 vosMessage; + struct tSirSapOffloadInfo *sme_sap_auth_offload_info; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + 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; + + sme_sap_auth_offload_info = + vos_mem_malloc(sizeof(*sme_sap_auth_offload_info)); + + 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); + +} + +/** + * sme_set_client_block_info set client block configuration. + * + * @hHal: hal layer handler + * @client_block_info: client block info struct pointer + * + * This function set client block info including reconnect_cnt, + * con_fail_duration, block_duration. + * + * Return: Return eHalStatus. + */ +eHalStatus sme_set_client_block_info(tHalHandle hHal, + struct sblock_info *pclient_block_info) +{ + vos_msg_t vosMessage; + eHalStatus status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + VOS_STATUS vos_status; + struct sblock_info *client_block_info; + + if (!pclient_block_info) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid sblock_info pointer", __func__); + return eHAL_STATUS_INVALID_PARAMETER; + } + + client_block_info = vos_mem_malloc(sizeof(*client_block_info)); + if (NULL == client_block_info) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: fail to alloc sblock_info", + __func__); + return eHAL_STATUS_FAILURE; + } + + *client_block_info = *pclient_block_info; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + vosMessage.type = WDA_SET_CLIENT_BLOCK_INFO; + vosMessage.bodyptr = client_block_info; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post msg to WDA!", + __func__); + vos_mem_free(client_block_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(client_block_info); + status = eHAL_STATUS_FAILURE; + } + return status; +} +#endif /* SAP_AUTH_OFFLOAD */ + +#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_FAULT; + } + + 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.type = WDA_APFIND_SET_CMD; + msg.reserved = 0; + msg.bodyptr = data; + + 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_SUCCESS; + } + + return VOS_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_APFIND */ +/** + * sme_fw_mem_dump() - Get FW memory dump + * + * This API is invoked by HDD to indicate FW to start + * dumping firmware memory. + * + * Return: eHalStatus + */ +#ifdef WLAN_FEATURE_MEMDUMP +eHalStatus sme_fw_mem_dump(tHalHandle hHal, void *recvd_req) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t msg; + struct fw_dump_req* send_req; + struct fw_dump_seg_req seg_req; + int loop; + + send_req = vos_mem_malloc(sizeof(*send_req)); + if(!send_req) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Memory allocation failed for WDA_FW_MEM_DUMP")); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(send_req, recvd_req, sizeof(*send_req)); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("request_id:%d num_seg:%d"), + send_req->request_id, send_req->num_seg); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Segment Information")); + for (loop = 0; loop < send_req->num_seg; loop++) { + seg_req = send_req->segment[loop]; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("seg_number:%d"), loop); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"), + seg_req.seg_id, seg_req.seg_start_addr_lo, + seg_req.seg_start_addr_hi); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"), + seg_req.seg_length, seg_req.dst_addr_lo, + seg_req.dst_addr_hi); + } + + if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) { + msg.bodyptr = send_req; + msg.type = WDA_FW_MEM_DUMP_REQ; + msg.reserved = 0; + + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, &msg); + if (VOS_STATUS_SUCCESS != vos_status) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to post WDA_FW_MEM_DUMP")); + vos_mem_free(send_req); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Failed to acquire SME Global Lock")); + vos_mem_free(send_req); + status = eHAL_STATUS_FAILURE; + } + + return status; +} +#else +eHalStatus sme_fw_mem_dump(tHalHandle hHal, void *recvd_req) +{ + return eHAL_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_MEMDUMP */ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/* + * sme_validate_sap_channel_switch() - validate target channel switch w.r.t + * concurreny rules set to avoid channel interference. + * @hal - Hal context + * @sap_phy_mode - phy mode of SAP + * @cc_switch_mode - concurreny switch mode + * @session_id - sme session id. + * + * Return: true if there is no channel interference else return false + */ +bool sme_validate_sap_channel_switch(tHalHandle hal, + uint16_t sap_ch, + eCsrPhyMode sap_phy_mode, + uint8_t cc_switch_mode, + uint32_t session_id) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id); + uint16_t intf_channel = 0; + + if (!session) + return false; + session->ch_switch_in_progress = true; + status = sme_AcquireGlobalLock(&mac->sme); + if (HAL_STATUS_SUCCESS(status)) { + intf_channel = csrCheckConcurrentChannelOverlap(mac, sap_ch, + sap_phy_mode, + cc_switch_mode); + sme_ReleaseGlobalLock(&mac->sme); + } else { + smsLog(mac, LOGE, FL(" sme_AcquireGlobalLock error!")); + session->ch_switch_in_progress = false; + return false; + } + + session->ch_switch_in_progress = false; + return (intf_channel == 0)? true : false; +} +#endif + +/** + * sme_configure_stats_avg_factor() - function to config avg. stats factor + * @hHal: hHal + * @session_id: session ID + * @stats_avg_factor: average stats factor + * + * This function configures the avg stats factor in firmware + * + * Return: eHalStatus + */ +eHalStatus sme_configure_stats_avg_factor(tHalHandle hHal, tANI_U8 session_id, + tANI_U16 stats_avg_factor) +{ + vos_msg_t msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + struct sir_stats_avg_factor *stats_factor; + + stats_factor = vos_mem_malloc(sizeof(*stats_factor)); + + if (!stats_factor) { + 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; + } + + status = sme_AcquireGlobalLock(&pMac->sme); + + if (eHAL_STATUS_SUCCESS == status) { + + stats_factor->vdev_id = session_id; + stats_factor->stats_avg_factor = stats_avg_factor; + + /* serialize the req through MC thread */ + msg.type = SIR_HAL_CONFIG_STATS_FACTOR; + msg.bodyptr = stats_factor; + + if (!VOS_IS_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 SIR_HAL_CONFIG_STATS_FACTOR to WMA!", + __func__); + vos_mem_free(stats_factor); + 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(stats_factor); + } + + return status; +} + +/** + * sme_configure_guard_time() - function to configure guard time + * @hHal: SME API to enable/disable DFS channel scan + * @session_id: session ID + * @guard_time: Guard time + * + * This function configures the guard time in firmware + * + * Return: eHalStatus + */ +eHalStatus sme_configure_guard_time(tHalHandle hHal, tANI_U8 session_id, + tANI_U32 guard_time) +{ + vos_msg_t msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + struct sir_guard_time_request *g_time; + + g_time = vos_mem_malloc(sizeof(*g_time)); + + if (!g_time) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for SIR_HAL_CONFIG_GUARD_TIME", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + + status = sme_AcquireGlobalLock(&pMac->sme); + + if (eHAL_STATUS_SUCCESS == status) { + + g_time->vdev_id = session_id; + g_time->guard_time = guard_time; + + /* serialize the req through MC thread */ + msg.type = SIR_HAL_CONFIG_GUARD_TIME; + msg.bodyptr = g_time; + + if (!VOS_IS_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 SIR_HAL_CONFIG_GUARD_TIME to WDA!", + __func__); + vos_mem_free(g_time); + 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(g_time); + } + + return status; +} + +/** + * sme_update_roam_scan_hi_rssi_scan_params() - update high rssi scan + * params + * @hal_handle - The handle returned by macOpen. + * @session_id - Session Identifier + * @notify_id - Identifies 1 of the 4 parameters to be modified + * @val New value of the parameter + * + * Return: eHAL_STATUS_SUCCESS - SME update config successful. + * Other status means SME failed to update + */ + +eHalStatus sme_update_roam_scan_hi_rssi_scan_params(tHalHandle hal_handle, + uint8_t session_id, + uint32_t notify_id, + int32_t val) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrNeighborRoamConfig *nr_config = NULL; + tpCsrNeighborRoamControlInfo nr_info = NULL; + uint32_t reason = 0; + + status = sme_AcquireGlobalLock(&mac_ctx->sme); + if (HAL_STATUS_SUCCESS(status)) { + nr_config = &mac_ctx->roam.configParam.neighborRoamConfig; + nr_info = &mac_ctx->roam.neighborRoamInfo[session_id]; + switch (notify_id) { + case eCSR_HI_RSSI_SCAN_MAXCOUNT_ID: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHirssiMaxCount is changed from %d to %d", + __func__, nr_config->nhi_rssi_scan_max_count, + val); + nr_config->nhi_rssi_scan_max_count = val; + nr_info->cfgParams.hi_rssi_scan_max_count = val; + reason = REASON_ROAM_SCAN_HI_RSSI_MAXCOUNT_CHANGED; + break; + + case eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHiRssiDelta is changed from %d to %d", + __func__, nr_config->nhi_rssi_scan_rssi_delta, + val); + nr_config->nhi_rssi_scan_rssi_delta = val; + nr_info->cfgParams.hi_rssi_scan_rssi_delta = val; + reason = REASON_ROAM_SCAN_HI_RSSI_DELTA_CHANGED; + break; + + case eCSR_HI_RSSI_SCAN_DELAY_ID: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHiRssiDelay is changed from %d to %d", + __func__, nr_config->nhi_rssi_scan_delay, + val); + nr_config->nhi_rssi_scan_delay = val; + nr_info->cfgParams.hi_rssi_scan_delay = val; + reason = REASON_ROAM_SCAN_HI_RSSI_DELAY_CHANGED; + break; + + case eCSR_HI_RSSI_SCAN_RSSI_UB_ID: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHiRssiUpperBound is changed from %d to %d", + __func__, + nr_config->nhi_rssi_scan_rssi_ub, + val); + nr_config->nhi_rssi_scan_rssi_ub = val; + nr_info->cfgParams.hi_rssi_scan_rssi_ub = val; + reason = REASON_ROAM_SCAN_HI_RSSI_UB_CHANGED; + break; + + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid parameter notify_id %d", __func__, + notify_id); + status = eHAL_STATUS_INVALID_PARAMETER; + break; + } + sme_ReleaseGlobalLock(&mac_ctx->sme); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled && + status == eHAL_STATUS_SUCCESS) { + csrRoamOffloadScan(mac_ctx, session_id, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason); + } +#endif + + return status; +} + +/** + * sme_configure_modulated_dtim() - function to configure modulated dtim + * @h_hal: SME API to enable/disable modulated DTIM instantaneously + * @session_id: session ID + * @modulated_dtim: modulated dtim value + * + * This function configures the guard time in firmware + * + * Return: eHalStatus + */ +eHalStatus sme_configure_modulated_dtim(tHalHandle h_hal, tANI_U8 session_id, + tANI_U32 modulated_dtim) +{ + vos_msg_t msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(h_hal); + wda_cli_set_cmd_t *iwcmd; + + iwcmd = vos_mem_malloc(sizeof(*iwcmd)); + if (NULL == iwcmd) { + VOS_TRACE(VOS_MODULE_ID_SME, + VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_alloc failed", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + status = sme_AcquireGlobalLock(&pMac->sme); + + if (eHAL_STATUS_SUCCESS == status) { + + vos_mem_zero((void *)iwcmd, sizeof(*iwcmd)); + iwcmd->param_value = modulated_dtim; + iwcmd->param_vdev_id = session_id; + iwcmd->param_id = GEN_PARAM_MODULATED_DTIM; + iwcmd->param_vp_dev = GEN_CMD; + msg.type = WDA_CLI_SET_CMD; + msg.reserved = 0; + msg.bodyptr = (void *)iwcmd; + + if (!VOS_IS_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 SIR_HAL_CONFIG_GUARD_TIME to WDA!", + __func__); + vos_mem_free(iwcmd); + 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(iwcmd); + } + + return status; +} + +/** + * sme_set_tsfcb() - set callback which to handle WMI_VDEV_TSF_REPORT_EVENTID + * + * @hHal: Handler return by macOpen. + * @pcallbackfn: callback to handle the tsf event + * @pcallbackcontext: callback context + * + * Return: eHalStatus. + */ +eHalStatus sme_set_tsfcb +( + tHalHandle hHal, + int (*pcallbackfn)(void *pcallbackcontext, struct stsf *pTsf), + void *pcallbackcontext +) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + pMac->sme.get_tsf_cb = pcallbackfn; + pMac->sme.get_tsf_cxt = pcallbackcontext; + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +#ifdef WLAN_FEATURE_TSF +/* + * sme_set_tsf_gpio() - set gpio pin that be toggled when capture tef + * + * @hHal: Handler return by macOpen + * @pinvalue: gpio pin id + * + * Return: eHalStatus + */ +eHalStatus sme_set_tsf_gpio(tHalHandle hHal, uint32_t pinvalue) +{ + eHalStatus status; + VOS_STATUS vos_status; + vos_msg_t vos_msg = {0}; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) { + vos_msg.type = WDA_TSF_GPIO_PIN; + vos_msg.reserved = 0; + vos_msg.bodyval = pinvalue; + + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: not able to post WDA_TSF_GPIO_PIN", + __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} +#endif + +/* + * sme_wifi_start_logger() - This function send the command to WMA + * to either start/stop logging + * @hal: HAL context + * @start_log: Structure containing the wifi start logger params + * + * This function send the command to WMA to either start/stop logging + * + * Return: eHAL_STATUS_SUCCESS on successful posting + */ +eHalStatus sme_wifi_start_logger(tHalHandle hal, + struct sir_wifi_start_log start_log) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + vos_msg_t vos_message; + struct sir_wifi_start_log *req_msg; + uint32_t len; + + len = sizeof(*req_msg); + req_msg = vos_mem_malloc(len); + if (!req_msg) { + smsLog(mac, LOGE, FL("vos_mem_malloc failed")); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(req_msg, len); + + req_msg->verbose_level = start_log.verbose_level; + req_msg->flag = start_log.flag; + req_msg->ring_id = start_log.ring_id; + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + vos_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + vos_message.bodyptr = req_msg; + vos_message.type = SIR_HAL_START_STOP_LOGGING; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + vos_mem_free(req_msg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +/** + * smeNeighborMiddleOfRoaming() - Function to know if + * STA is in the middle of roaming states + * @hal: Handle returned by macOpen + * @sessionId: sessionId of the STA session + * + * This function is a wrapper to call + * csrNeighborMiddleOfRoaming to know if + * STA is in the middle of roaming states + * + * Return: True or False + * + */ +bool smeNeighborMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId) +{ + return csrNeighborMiddleOfRoaming(PMAC_STRUCT(hHal), sessionId); +} + +/** + * sme_update_nss() - SME API to change the number for spatial streams (1 or 2) + * @hal: - Handle returned by macOpen + * @nss: - Number of spatial streams + * + * This function is used to update the number of spatial streams supported. + * + * Return: Success upon successfully changing nss else failure + * + */ +eHalStatus sme_update_nss(tHalHandle h_hal, uint8_t nss) +{ + eHalStatus status; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal); + uint32_t i, value = 0; + union { + uint16_t cfg_value16; + tSirMacHTCapabilityInfo ht_cap_info; + } uHTCapabilityInfo; + tCsrRoamSession *csr_session; + + status = sme_AcquireGlobalLock(&mac_ctx->sme); + + if (eHAL_STATUS_SUCCESS == status) { + mac_ctx->roam.configParam.enable2x2 = (nss == 1) ? 0 : 1; + + /* get the HT capability info*/ + ccmCfgGetInt(mac_ctx, WNI_CFG_HT_CAP_INFO, &value); + uHTCapabilityInfo.cfg_value16 = (0xFFFF & value); + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(mac_ctx, i)) { + csr_session = &mac_ctx->roam.roamSession[i]; + csr_session->htConfig.ht_tx_stbc = + uHTCapabilityInfo.ht_cap_info.txSTBC; + } + } + + sme_ReleaseGlobalLock(&mac_ctx->sme); + } + + return status; +} + +uint8_t sme_is_any_session_in_connected_state(tHalHandle h_hal) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal); + eHalStatus status; + uint8_t ret = FALSE; + + status = sme_AcquireGlobalLock(&mac_ctx->sme); + if (eHAL_STATUS_SUCCESS == status) { + ret = csrIsAnySessionInConnectState(mac_ctx); + sme_ReleaseGlobalLock(&mac_ctx->sme); + } + return ret; +} + +/** + * vos_send_flush_logs_cmd_to_fw() - Flush FW logs + * @mac: MAC handle + * + * This function is used to send the command that will + * be used to flush the logs in the firmware + * + * Return: eHalStatus + */ +eHalStatus vos_send_flush_logs_cmd_to_fw(tpAniSirGlobal mac) +{ + eHalStatus status; + VOS_STATUS vos_status; + vos_msg_t vos_message; + + status = sme_AcquireGlobalLock(&mac->sme); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + return status; + } + + /* Serialize the req through MC thread */ + vos_message.bodyptr = NULL; + vos_message.type = SIR_HAL_FLUSH_LOG_TO_FW; + vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + smsLog(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + vos_status); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + return status; +} + +/** + * sme_disable_non_fcc_channel() - non-fcc channel disable request + * @hal: HAL pointer + * @fcc_constraint: true: disable, false; enable + * + * Return: eHalStatus. + */ +eHalStatus sme_disable_non_fcc_channel(tHalHandle hal, bool fcc_constraint) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); + + status = sme_AcquireGlobalLock(&mac_ptr->sme); + + if (eHAL_STATUS_SUCCESS == status) { + + if (fcc_constraint != mac_ptr->scan.fcc_constraint) { + mac_ptr->scan.fcc_constraint = fcc_constraint; + + /* update the channel list to the firmware */ + status = csrUpdateChannelList(mac_ptr); + } + + sme_ReleaseGlobalLock(&mac_ptr->sme); + } + + return status; +} +/** + * sme_enable_phy_error_logs() - Enable DFS phy error logs + * @hal: global hal handle + * @enable_log: value to set + * + * Since the frequency of DFS phy error is very high, enabling logs for them + * all the times can cause crash and will also create lot of useless logs + * causing difficulties in debugging other issue. This function will be called + * from iwpriv cmd to eanble such logs temporarily. + * + * Return: void + */ +void sme_enable_phy_error_logs(tHalHandle hal, bool enable_log) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + mac_ctx->sap.enable_dfs_phy_error_logs = enable_log; +} + +/** + * sme_SetDefDot11Mode() - Updates pMac with default dot11mode + * @hal: Global MAC pointer + * + * Return: NULL. + */ +void sme_SetDefDot11Mode(tHalHandle hal) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT( hal ); + csrSetDefaultDot11Mode(mac_ctx); +} + +/** + * sme_update_user_configured_nss() - sets the nss based on user request + * @hal: Pointer to HAL + * @nss: number of streams + * + * Return: None + */ +void sme_update_user_configured_nss(tHalHandle hal, uint8_t nss) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + mac_ctx->user_configured_nss = nss; +} + +/** + * sme_set_vdev_nss() - sets the vdev nss based on INI + * @hal: Pointer to HAL + * @enable2x2: 1x1 or 2x2 mode. + * + * Sets the per band Nss for each vdev type based on INI. + * + * Return: None + */ +void sme_set_vdev_nss(tHalHandle hal, bool enable2x2) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct vdev_type_nss *vdev_nss; + uint8_t i; + uint8_t nss_val; + uint8_t coex; + + if (enable2x2) { + if (mac_ctx->lteCoexAntShare) + coex = 1; + else + coex = 0; + nss_val = 2; + } else { + nss_val = 1; + coex = 0; + } + mac_ctx->user_configured_nss = nss_val; + + vdev_nss = &mac_ctx->vdev_type_nss_2g; + + for (i = 0; i < NUM_OF_BANDS; i++) { + vdev_nss->sta = nss_val; + vdev_nss->sap = nss_val - coex; + vdev_nss->p2p_go = nss_val - coex; + vdev_nss->p2p_cli = nss_val - coex; + vdev_nss->p2p_dev = nss_val - coex; + vdev_nss->ibss = nss_val - coex; + vdev_nss->tdls = nss_val - coex; + vdev_nss->ocb = nss_val - coex; + + vdev_nss = &mac_ctx->vdev_type_nss_5g; + coex = 0; + } +} + +/** + * sme_update_vdev_type_nss() - sets the nss per vdev type + * @hal: Pointer to HAL + * @max_supp_nss: max_supported Nss + * @band: 5G or 2.4G band + * + * Sets the per band Nss for each vdev type based on INI and configured + * chain mask value. + * + * Return: None + */ +void sme_update_vdev_type_nss(tHalHandle hal, uint8_t max_supp_nss, + uint32_t vdev_type_nss, eCsrBand band) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct vdev_type_nss *vdev_nss; + + if (eCSR_BAND_5G == band) { + vdev_nss = &mac_ctx->vdev_type_nss_5g; + } else { + vdev_nss = &mac_ctx->vdev_type_nss_2g; + } + + vdev_nss->sta = VOS_MIN(max_supp_nss, CFG_STA_NSS(vdev_type_nss)); + vdev_nss->sap = VOS_MIN(max_supp_nss, CFG_SAP_NSS(vdev_type_nss)); + vdev_nss->p2p_go = VOS_MIN(max_supp_nss, + CFG_P2P_GO_NSS(vdev_type_nss)); + vdev_nss->p2p_cli = VOS_MIN(max_supp_nss, + CFG_P2P_CLI_NSS(vdev_type_nss)); + vdev_nss->p2p_dev = VOS_MIN(max_supp_nss, + CFG_P2P_DEV_NSS(vdev_type_nss)); + vdev_nss->ibss = VOS_MIN(max_supp_nss, CFG_IBSS_NSS(vdev_type_nss)); + vdev_nss->tdls = VOS_MIN(max_supp_nss, CFG_TDLS_NSS(vdev_type_nss)); + vdev_nss->ocb = VOS_MIN(max_supp_nss, CFG_OCB_NSS(vdev_type_nss)); + mac_ctx->user_configured_nss = max_supp_nss; + + smsLog(mac_ctx, LOG1, + "band %d NSS: sta %d sap %d cli %d go %d dev %d ibss %d tdls %d ocb %d", + band, vdev_nss->sta, vdev_nss->sap, vdev_nss->p2p_cli, + vdev_nss->p2p_go, vdev_nss->p2p_dev, vdev_nss->ibss, + vdev_nss->tdls, vdev_nss->ocb); +} + +/** + * sme_set_per_band_chainmask_supp() - sets the per band chainmask support + * @hal: Pointer to HAL + * @val: Value to be set. + * + * Sets the per band chain mask support to mac context. + * Return: None + */ +void sme_set_per_band_chainmask_supp(tHalHandle hal, bool val) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + mac_ctx->per_band_chainmask_supp = val; +} + +/** + * sme_set_lte_coex_supp() - sets the lte coex antenna share support + * @hal: Pointer to HAL + * @val: Value to be set. + * + * Sets the lte coex antenna share support to mac context. + * Return: None + */ +void sme_set_lte_coex_supp(tHalHandle hal, bool val) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + mac_ctx->lteCoexAntShare = val; +} + +/** + * sme_set_bcon_offload_supp() - sets the beacon offload support + * @hal: Pointer to HAL + * @val: Value to be set. + * + * Sets the beacon offload support to mac context. + * Return: None + */ +void sme_set_bcon_offload_supp(tHalHandle hal, bool val) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + mac_ctx->beacon_offload = val; +} + +#ifdef FEATURE_WLAN_TDLS + +/** + * sme_get_opclass() - determine operating class + * @hal: Pointer to HAL + * @channel: channel id + * @bw_offset: bandwidth offset + * @opclass: pointer to operating class + * + * Function will determine operating class from regdm_get_opclass_from_channel + * + * Return: none + */ +void sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset, + uint8_t *opclass) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + + /* redgm opclass table contains opclass for 40MHz low primary, + * 40MHz high primary and 20MHz. No support for 80MHz yet. So + * first we will check if bit for 40MHz is set and if so find + * matching opclass either with low primary or high primary + * (a channel would never be in both) and then search for opclass + * matching 20MHz, else for any BW. + */ + if (bw_offset & (1 << BW_40_OFFSET_BIT)) { + *opclass = regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, + BW40_LOW_PRIMARY); + if (!(*opclass)) { + *opclass = regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, + BW40_HIGH_PRIMARY); + } + } else if (bw_offset & (1 << BW_20_OFFSET_BIT)) { + *opclass = regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, + BW20); + } else { + *opclass = regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, + BWALL); + } +} + +#endif + + + +#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD +/** + * sme_set_udp_resp_offload() - set udp response payload. + * @pudp_resp_cmd: specific udp and response udp payload struct pointer + * + * This function set specific udp and response udp payload info + * including enable dest_port,udp_payload, resp_payload. + * + * Return: Return VOS_STATUS. + */ +VOS_STATUS sme_set_udp_resp_offload(struct udp_resp_offload *pudp_resp_cmd) +{ + vos_msg_t vos_message; + VOS_STATUS vos_status; + struct udp_resp_offload *udp_resp_cmd; + + if (!pudp_resp_cmd) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid pudp_resp_cmd pointer", __func__); + return VOS_STATUS_E_FAILURE; + } + + udp_resp_cmd = vos_mem_malloc(sizeof(*udp_resp_cmd)); + if (NULL == udp_resp_cmd) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: fail to alloc sudp_cmd", __func__); + return VOS_STATUS_E_FAILURE; + } + + *udp_resp_cmd = *pudp_resp_cmd; + + vos_message.type = WDA_SET_UDP_RESP_OFFLOAD; + vos_message.bodyptr = udp_resp_cmd; + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, + &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post msg to WDA!", + __func__); + vos_mem_free(udp_resp_cmd); + vos_status = VOS_STATUS_E_FAILURE; + } + + return vos_status; +} +#endif + +/** + * sme_set_lost_link_info_cb() - plug in callback function for receiving + * lost link info + * @hal: HAL handle + * @cb: callback function + * + * Return: HAL status + */ +eHalStatus sme_set_lost_link_info_cb(tHalHandle hal, + void (*cb)(void *, + struct sir_lost_link_info *)) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + mac->sme.lost_link_info_cb = cb; + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: set lost link info callback", __func__); + sme_ReleaseGlobalLock(&mac->sme); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error status %d", + __func__, status); + } + return status; +} + +/** + * sme_set_smps_force_mode_cb() - callback set by HDD for smps + * force mode event + * @hal: The handle returned by macOpen + * @cb: callback function + * + * Return: eHAL_STATUS_SUCCESS if callback was set successfully + * else failure status + */ +eHalStatus sme_set_smps_force_mode_cb(tHalHandle hal, + void (*cb)(void *, + struct sir_smps_force_mode_event *)) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + mac->sme.smps_force_mode_cb = cb; + sme_ReleaseGlobalLock(&mac->sme); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: set smps force mode callback", __func__); + } else { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error status %d", + __func__, status); + } + return status; +} + +/** + * sme_update_mimo_power_save() - Update MIMO power save + * configuration + * @hal: The handle returned by macOpen + * @is_ht_smps_enabled: enable/disable ht smps + * @ht_smps_mode: smps mode disabled/static/dynamic + * + * Return: eHAL_STATUS_SUCCESS if SME update mimo power save + * configuration sucsess else failue status + */ +eHalStatus sme_update_mimo_power_save(tHalHandle hal, + uint8_t is_ht_smps_enabled, + uint8_t ht_smps_mode) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + eHalStatus status; + + status = sme_AcquireGlobalLock(&mac_ctx->sme); + if (HAL_STATUS_SUCCESS(status)) { + smsLog(mac_ctx, LOG1, + "update mimo power save config enable smps: %d smps mode: %d", + is_ht_smps_enabled, ht_smps_mode); + mac_ctx->roam.configParam.enableHtSmps = + is_ht_smps_enabled; + mac_ctx->roam.configParam.htSmps = ht_smps_mode; + sme_ReleaseGlobalLock(&mac_ctx->sme); + } + return status; +} + +/** + * sme_is_sta_smps_allowed() - check if the supported nss for + * the session is greater than 1x1 to enable sta SMPS + * @hal: The handle returned by macOpen + * @session_id: session id + * + * Return: bool returns true if supported nss is greater than + * 1x1 else false + */ +bool sme_is_sta_smps_allowed(tHalHandle hal, uint8_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + tCsrRoamSession *csr_session; + + if (!mac_ctx) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Failed to get mac_ctx")); + return false; + } + + if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { + smsLog(mac_ctx, LOGE, "CSR session not valid: %d", session_id); + return false; + } + + csr_session = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == csr_session) { + smsLog(mac_ctx, LOGE, "SME session not valid: %d", session_id); + return false; + } + + return (csr_session->supported_nss_1x1 == true) ? false : true; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c new file mode 100644 index 000000000000..56573eb43109 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_FTApi.c @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef WLAN_FEATURE_VOWIFI_11R +/**========================================================================= + + \brief Definitions for SME FT APIs + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include + +/*-------------------------------------------------------------------------- + Initialize the FT context. + ------------------------------------------------------------------------*/ +void sme_FTOpen(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL != pSession) { + /* Clean up the context */ + vos_mem_set(&pSession->ftSmeContext, sizeof(tftSMEContext), 0); + + pSession->ftSmeContext.pUsrCtx = vos_mem_malloc( + sizeof(tFTRoamCallbackUsrCtx)); + + if (NULL == pSession->ftSmeContext.pUsrCtx) { + smsLog(pMac, LOGE, FL("Memory allocation failure")); + return; + } + pSession->ftSmeContext.pUsrCtx->pMac = pMac; + pSession->ftSmeContext.pUsrCtx->sessionId = sessionId; + + status = + vos_timer_init(&pSession->ftSmeContext.preAuthReassocIntvlTimer, + VOS_TIMER_TYPE_SW, + sme_PreauthReassocIntvlTimerCallback, + (void *)pSession->ftSmeContext.pUsrCtx); + + if (eHAL_STATUS_SUCCESS != status) { + smsLog(pMac, LOGE, + FL("Preauth Reassoc interval Timer allocation failed")); + vos_mem_free(pSession->ftSmeContext.pUsrCtx); + pSession->ftSmeContext.pUsrCtx = NULL; + return; + } + } +} + +/*-------------------------------------------------------------------------- + Cleanup the SME FT Global context. + ------------------------------------------------------------------------*/ +void sme_FTClose(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = NULL; + + /* Clear the FT Context */ + sme_FTReset(hHal, sessionId); + + pSession = CSR_GET_SESSION( pMac, sessionId ); + if (NULL != pSession) + { + /* check if the timer is running */ + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState( + &pSession->ftSmeContext.preAuthReassocIntvlTimer)) + { + vos_timer_stop(&pSession->ftSmeContext.preAuthReassocIntvlTimer); + } + + if (VOS_STATUS_SUCCESS != + vos_timer_destroy(&pSession->ftSmeContext.preAuthReassocIntvlTimer)) + { + smsLog(pMac, LOGE, FL("preAuthReAssocTimer destroy failed")); + } + + if (pSession->ftSmeContext.pUsrCtx != NULL) { + smsLog(pMac, LOG1, + FL("Freeing ftSmeContext.pUsrCtx and setting to NULL")); + vos_mem_free(pSession->ftSmeContext.pUsrCtx); + pSession->ftSmeContext.pUsrCtx = NULL; + } + } +} + +void sme_SetFTPreAuthState(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (pSession) + pSession->ftSmeContext.setFTPreAuthState = state; +} + +v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + if (pSession) + return pSession->ftSmeContext.setFTPreAuthState; + + return FALSE; +} + +/*-------------------------------------------------------------------------- + Each time the supplicant sends down the FT IEs to the driver. + This function is called in SME. This function packages and sends + the FT IEs to PE. + ------------------------------------------------------------------------*/ +void sme_SetFTIEs(tHalHandle hHal, tANI_U32 sessionId, const tANI_U8 *ft_ies, + tANI_U16 ft_ies_length ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (NULL == pSession || NULL == ft_ies) + { + smsLog( pMac, LOGE, FL(" ft ies or pSession is NULL")); + return; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if (!( HAL_STATUS_SUCCESS( status ))) return; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, "FT IEs Req is received in state %d", + pSession->ftSmeContext.FTState); +#endif + + // Global Station FT State + switch(pSession->ftSmeContext.FTState) + { + case eFT_START_READY: + case eFT_AUTH_REQ_READY: + if ((pSession->ftSmeContext.auth_ft_ies) && + (pSession->ftSmeContext.auth_ft_ies_length)) + { + // Free the one we received last from the supplicant + vos_mem_free(pSession->ftSmeContext.auth_ft_ies); + pSession->ftSmeContext.auth_ft_ies_length = 0; + pSession->ftSmeContext.auth_ft_ies = NULL; + } + + // Save the FT IEs + pSession->ftSmeContext.auth_ft_ies = + vos_mem_malloc(ft_ies_length); + if ( NULL == pSession->ftSmeContext.auth_ft_ies ) + { + smsLog( pMac, LOGE, FL("Memory allocation failed for " + "auth_ft_ies")); + sme_ReleaseGlobalLock( &pMac->sme ); + return; + } + pSession->ftSmeContext.auth_ft_ies_length = ft_ies_length; + vos_mem_copy((tANI_U8 *)pSession->ftSmeContext.auth_ft_ies, + ft_ies,ft_ies_length); + pSession->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: + // We will need to re-start preauth. If we received FT IEs in + // eFT_PRE_AUTH_DONE state, it implies there was a rekey in + // our pre-auth state. Hence this implies we need Pre-auth again. + + // OK now inform SME we have no pre-auth list. + // Delete the pre-auth node locally. Set your self back to restart pre-auth + // TBD +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, + "Pre-auth done and now receiving---> AUTH REQ <---- in state %d", + pSession->ftSmeContext.FTState); + smsLog( pMac, LOG1, "Unhandled reception of FT IES in state %d", + pSession->ftSmeContext.FTState); +#endif + break; + + case eFT_REASSOC_REQ_WAIT: + // We are done with pre-auth, hence now waiting for + // reassoc req. This is the new FT Roaming in place + + // At this juncture we are ready to start sending Re-Assoc Req. +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, "New Reassoc Req=%p in state %d", + ft_ies, pSession->ftSmeContext.FTState); +#endif + if ((pSession->ftSmeContext.reassoc_ft_ies) && + (pSession->ftSmeContext.reassoc_ft_ies_length)) + { + // Free the one we received last from the supplicant + vos_mem_free(pSession->ftSmeContext.reassoc_ft_ies); + pSession->ftSmeContext.reassoc_ft_ies_length = 0; + } + + // Save the FT IEs + pSession->ftSmeContext.reassoc_ft_ies = vos_mem_malloc(ft_ies_length); + if ( NULL == pSession->ftSmeContext.reassoc_ft_ies ) + { + smsLog( pMac, LOGE, FL("Memory allocation failed for " + "reassoc_ft_ies")); + sme_ReleaseGlobalLock( &pMac->sme ); + return; + } + pSession->ftSmeContext.reassoc_ft_ies_length = ft_ies_length; + vos_mem_copy((tANI_U8 *)pSession->ftSmeContext.reassoc_ft_ies, ft_ies, + ft_ies_length); + + pSession->ftSmeContext.FTState = eFT_SET_KEY_WAIT; +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, "ft_ies_length=%d state=%d", ft_ies_length, + pSession->ftSmeContext.FTState); +#endif + + break; + + default: + smsLog( pMac, LOGE, FL(" Unhandled state=%d"), + pSession->ftSmeContext.FTState); + break; + } + sme_ReleaseGlobalLock( &pMac->sme ); +} + +eHalStatus sme_FTSendUpdateKeyInd(tHalHandle hHal, tANI_U32 sessionId, + tCsrRoamSetKey * pFTKeyInfo) +{ + tSirFTUpdateKeyInfo *pMsg; + tANI_U16 msgLen; + eHalStatus status = eHAL_STATUS_FAILURE; + tAniEdType tmpEdType; + tSirKeyMaterial *keymaterial = NULL; + tAniEdType edType; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + int i = 0; + + smsLog(pMac, LOG1, FL("keyLength %d"), pFTKeyInfo->keyLength); + + for (i=0; ikeyLength; i++) + smsLog(pMac, LOG1, FL("%02x"), pFTKeyInfo->Key[i]); +#endif + + if(pFTKeyInfo->keyLength > CSR_MAX_KEY_LEN) + { + smsLog( pMac, LOGE, "%s: invalid keyLength %d", __func__,pFTKeyInfo->keyLength); + return eHAL_STATUS_FAILURE; + } + + msgLen = sizeof(tSirFTUpdateKeyInfo); + + pMsg = vos_mem_malloc(msgLen); + if ( NULL == pMsg ) + { + return eHAL_STATUS_FAILURE; + } + + vos_mem_set(pMsg, msgLen, 0); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_FT_UPDATE_KEY); + pMsg->length = pal_cpu_to_be16(msgLen); + + keymaterial = &pMsg->keyMaterial; + + keymaterial->length = pFTKeyInfo->keyLength; + + edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType ); + tmpEdType = pal_cpu_to_be32(edType); + keymaterial->edType = tmpEdType; + + // Set the pMsg->keyMaterial.length field (this length is defined as all + // data that follows the edType field + // in the tSirKeyMaterial keyMaterial; field). + // + // !!NOTE: This keyMaterial.length contains the length of a MAX size key, + // though the keyLength can be + // shorter than this max size. Is LIM interpreting this ok ? + keymaterial->numKeys = 1; + keymaterial->key[ 0 ].keyId = pFTKeyInfo->keyId; + keymaterial->key[ 0 ].unicast = (tANI_U8)eANI_BOOLEAN_TRUE; + keymaterial->key[ 0 ].keyDirection = pFTKeyInfo->keyDirection; + + vos_mem_copy(&keymaterial->key[ 0 ].keyRsc, pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN); + keymaterial->key[ 0 ].paeRole = pFTKeyInfo->paeRole; + + keymaterial->key[ 0 ].keyLength = pFTKeyInfo->keyLength; + + if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key ) + { + vos_mem_copy(&keymaterial->key[ 0 ].key, pFTKeyInfo->Key, pFTKeyInfo->keyLength); + if(pFTKeyInfo->keyLength == 16) + { + smsLog(pMac, LOG1, + "SME Set Update Ind keyIdx (%d) encType(%d) key = " + "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", + pMsg->keyMaterial.key[0].keyId, (tAniEdType)pMsg->keyMaterial.edType, + pMsg->keyMaterial.key[0].key[0], pMsg->keyMaterial.key[0].key[1], + pMsg->keyMaterial.key[0].key[2], pMsg->keyMaterial.key[0].key[3], + pMsg->keyMaterial.key[0].key[4], pMsg->keyMaterial.key[0].key[5], + pMsg->keyMaterial.key[0].key[6], pMsg->keyMaterial.key[0].key[7], + pMsg->keyMaterial.key[0].key[8], pMsg->keyMaterial.key[0].key[9], + pMsg->keyMaterial.key[0].key[10], pMsg->keyMaterial.key[0].key[11], + pMsg->keyMaterial.key[0].key[12], pMsg->keyMaterial.key[0].key[13], + pMsg->keyMaterial.key[0].key[14], pMsg->keyMaterial.key[0].key[15]); + } + } + + vos_mem_copy( &pMsg->bssId[ 0 ], + &pFTKeyInfo->peerMac[ 0 ], + sizeof(tCsrBssid) ); + + pMsg->smeSessionId = sessionId; + + smsLog(pMac, LOG1, "BSSID = "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pMsg->bssId)); + + status = palSendMBMessage(pMac->hHdd, pMsg); + + return( status ); +} + +v_BOOL_t sme_GetFTPTKState(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + smsLog(pMac, LOGE, FL("pSession is NULL")); + return VOS_FALSE; + } + return pSession->ftSmeContext.setFTPTKState; +} + +void sme_SetFTPTKState(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + smsLog(pMac, LOGE, FL("pSession is NULL")); + return; + } + pSession->ftSmeContext.setFTPTKState = state; +} + +eHalStatus sme_FTUpdateKey(tHalHandle hHal, tANI_U32 sessionId, + tCsrRoamSetKey * pFTKeyInfo ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (!pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return eHAL_STATUS_FAILURE; + } + + if (pFTKeyInfo == NULL) + { + smsLog( pMac, LOGE, "%s: pFTKeyInfo is NULL", __func__); + return eHAL_STATUS_FAILURE; + } + + status = sme_AcquireGlobalLock( &pMac->sme ); + if (!( HAL_STATUS_SUCCESS( status ))) + { + return eHAL_STATUS_FAILURE; + } + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, "sme_FTUpdateKey is received in state %d", + pSession->ftSmeContext.FTState); +#endif + + // Global Station FT State + switch(pSession->ftSmeContext.FTState) + { + case eFT_SET_KEY_WAIT: + if (sme_GetFTPreAuthState(hHal, sessionId) == TRUE) + { + status = sme_FTSendUpdateKeyInd(pMac, sessionId, pFTKeyInfo); + if (status != 0 ) + { + smsLog( pMac, LOGE, "%s: Key set failure %d", __func__, + status); + pSession->ftSmeContext.setFTPTKState = FALSE; + status = eHAL_STATUS_FT_PREAUTH_KEY_FAILED; + } + else + { + pSession->ftSmeContext.setFTPTKState = TRUE; + status = eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS; + smsLog( pMac, LOG1, "%s: Key set success", __func__); + } + sme_SetFTPreAuthState(hHal, sessionId, FALSE); + } + + pSession->ftSmeContext.FTState = eFT_START_READY; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, "%s: state changed to %d status %d", __func__, + pSession->ftSmeContext.FTState, status); +#endif + break; + + default: + smsLog( pMac, LOGW, "%s: Unhandled state=%d", __func__, + pSession->ftSmeContext.FTState); + status = eHAL_STATUS_FAILURE; + break; + } + sme_ReleaseGlobalLock( &pMac->sme ); + + return status; +} +/*-------------------------------------------------------------------------- + * + * HDD Interface to SME. SME now sends the Auth 2 and RIC IEs up to the supplicant. + * The supplicant will then proceed to send down the + * Reassoc Req. + * + *------------------------------------------------------------------------*/ +void sme_GetFTPreAuthResponse( tHalHandle hHal, tANI_U32 sessionId, tANI_U8 *ft_ies, + tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (!pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return; + } + + *ft_ies_length = 0; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if (!( HAL_STATUS_SUCCESS( status ))) + return; + + /* All or nothing - proceed only if both BSSID and FT IE fit */ + if((ANI_MAC_ADDR_SIZE + + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies_length) > ft_ies_ip_len) + { + sme_ReleaseGlobalLock( &pMac->sme ); + return; + } + + // hdd needs to pack the bssid also along with the + // auth response to supplicant + vos_mem_copy(ft_ies, pSession->ftSmeContext.preAuthbssId, ANI_MAC_ADDR_SIZE); + + // Copy the auth resp FTIEs + vos_mem_copy(&(ft_ies[ANI_MAC_ADDR_SIZE]), + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies, + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies_length); + + *ft_ies_length = ANI_MAC_ADDR_SIZE + + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies_length; + + pSession->ftSmeContext.FTState = eFT_REASSOC_REQ_WAIT; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, FL(" Filled auth resp = %d"), *ft_ies_length); +#endif + sme_ReleaseGlobalLock( &pMac->sme ); + return; +} + +/*-------------------------------------------------------------------------- + * + * SME now sends the RIC IEs up to the supplicant. + * The supplicant will then proceed to send down the + * Reassoc Req. + * + *------------------------------------------------------------------------*/ +void sme_GetRICIEs(tHalHandle hHal, tANI_U32 sessionId, tANI_U8 *ric_ies, + tANI_U32 ric_ies_ip_len, tANI_U32 *ric_ies_length ) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); + eHalStatus status = eHAL_STATUS_FAILURE; + + if (!pSession) + { + smsLog( pMac, LOGE, FL("pSession is NULL")); + return; + } + + *ric_ies_length = 0; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if (!( HAL_STATUS_SUCCESS( status ))) + return; + + /* All or nothing */ + if (pSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length > + ric_ies_ip_len) + { + sme_ReleaseGlobalLock( &pMac->sme ); + return; + } + + vos_mem_copy(ric_ies, pSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies, + pSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length); + + *ric_ies_length = pSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, FL(" Filled ric ies = %d"), *ric_ies_length); +#endif + + sme_ReleaseGlobalLock( &pMac->sme ); + return; +} + +/*-------------------------------------------------------------------------- + * + * Timer callback for the timer that is started between the preauth completion and + * reassoc request to the PE. In this interval, it is expected that the pre-auth response + * and RIC IEs are passed up to the WPA supplicant and received back the necessary FTIEs + * required to be sent in the reassoc request + * + *------------------------------------------------------------------------*/ +void sme_PreauthReassocIntvlTimerCallback(void *context) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *)context; + + if (pUsrCtx) { + csrNeighborRoamRequestHandoff(pUsrCtx->pMac, pUsrCtx->sessionId); + } +#endif + return; +} + +/*-------------------------------------------------------------------------- + Reset the FT context. + ------------------------------------------------------------------------*/ +void sme_FTReset(tHalHandle hHal, tANI_U32 sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = NULL; + + if (pMac == NULL) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("pMac is NULL")); + return; + } + + pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL != pSession) { + if (pSession->ftSmeContext.auth_ft_ies != NULL) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog(pMac, LOG1, FL("Freeing FT Auth IE %p and setting to NULL"), + pSession->ftSmeContext.auth_ft_ies); +#endif + vos_mem_free(pSession->ftSmeContext.auth_ft_ies); + pSession->ftSmeContext.auth_ft_ies = NULL; + } + pSession->ftSmeContext.auth_ft_ies_length = 0; + + if (pSession->ftSmeContext.reassoc_ft_ies != NULL) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog(pMac, LOG1, + FL("Freeing FT Reassoc IE %p and setting to NULL"), + pSession->ftSmeContext.reassoc_ft_ies); +#endif + vos_mem_free(pSession->ftSmeContext.reassoc_ft_ies); + pSession->ftSmeContext.reassoc_ft_ies = NULL; + } + pSession->ftSmeContext.reassoc_ft_ies_length = 0; + + if (pSession->ftSmeContext.psavedFTPreAuthRsp != NULL) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, FL("Freeing FtPreAuthRsp %p and setting to NULL"), + pSession->ftSmeContext.psavedFTPreAuthRsp); +#endif + vos_mem_free(pSession->ftSmeContext.psavedFTPreAuthRsp); + pSession->ftSmeContext.psavedFTPreAuthRsp = NULL; + } + pSession->ftSmeContext.setFTPreAuthState = VOS_FALSE; + pSession->ftSmeContext.setFTPTKState = VOS_FALSE; + + vos_mem_zero(pSession->ftSmeContext.preAuthbssId, ANI_MAC_ADDR_SIZE); + pSession->ftSmeContext.FTState = eFT_START_READY; + } +} + +/* End of File */ +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Trace.c b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Trace.c new file mode 100644 index 000000000000..65aaf7fd591c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Trace.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/************************************************************************ + smeTrace.c + + \brief implementation for trace related APIs + + \author Kiran Kumar Reddy CH L V + + ========================================================================*/ +#include "aniGlobal.h" //for tpAniSirGlobal +#include "smsDebug.h" +#include "macTrace.h" +#include "sme_Trace.h" +#include "smeInternal.h" +#ifndef SME_TRACE_RECORD +void smeTraceInit(tpAniSirGlobal pMac) +{ + return; +} +#endif +#ifdef SME_TRACE_RECORD + + +static tANI_U8* smeTraceGetRxMsgString( tANI_U32 code ) +{ + switch(code) + { + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_REQ); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_GET_RESULTS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_CONNECT); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SET_REGINFO); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CHANNEL_CONFIG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_HDDREADYIND); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_P2PRESULTS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETFIRST); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETNEXT); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_PURGE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_REASSOC); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_DISCONNECT); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_SET_PMKIDCACHE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ROAM_GET_PMKIDCACHE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_CONFIGPARAM); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_MODPROFFIELDS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_CONFIG_PWRSAVE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_CONFIG_PWRSAVE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ENABLE_PWRSAVE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DISABLE_PWRSAVE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SIGNAL_POWER_EVENT); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_START_AUTO_BMPSTIMER); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_STOP_AUTO_BMPSTIMER); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_IS_PWRSAVE_ENABLED); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_REQUEST_FULLPOWER); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_REQUEST_BMPS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_DHCP_FLAG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_REQUEST_STANDBY); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_WOWL_ADDBCAST_PATTERN); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_WOWL_DELBCAST_PATTERN); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ENTER_WOWL); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_EXIT_WOWL); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_KEY); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_REMOVE_KEY); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_STATS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_RSSI); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_CNTRYCODE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_CNTRYCODE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CHANGE_CNTRYCODE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_BTC_SIGNALEVENT); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_BTC_SETCONFIG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_BTC_GETCONFIG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_CFGPRIVACY); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DBG_READREG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DBG_WRITEREG); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DBG_READMEM); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DBG_WRITEMEM); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_OPEN_SESSION); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CLOSE_SESSION); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_HOSTOFFLOAD); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_GTKOFFLOAD); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_GTKOFFLOAD); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_POWERPARAMS); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ABORT_MACSCAN); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_REGISTER_MGMTFR); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DEREGISTER_MGMTFR); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_REMAIN_ONCHAN); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SEND_ACTION); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CANCEL_REMAIN_ONCHAN); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CONFIG_RXPFIL); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CONFIG_SUSPENDIND); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CONFIG_RESUMEREQ); +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CONFIG_EXTWOW); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE1); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE2); +#endif + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_MAXTXPOW); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_TXPOW); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_TMLEVEL); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CAPS_EXCH); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_DISABLE_CAP); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_DEFCCNV); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_CURCC); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_RESET_PW5G); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_RP5G); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_ROAMIBAND); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_GET_ROAMIBAND); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_RSSIDIFF); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_IMMRSSIDIFF); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_FTENABLED); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_WESMODE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_SET_SCANCTRL); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_P2P_IE); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_N_PROBES); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_HOME_AWAY_TIME); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_STORE_JOIN_REQ); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_CLEAR_JOIN_REQ); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_ISSUE_JOIN_REQ); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_MSG_DEAUTH_STA); +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_TDLS_LINK_ESTABLISH_PARAM); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_TDLS_CHAN_SWITCH_REQ); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_TDLS_SEND_MGMT_FRAME); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_TDLS_CHANGE_PEER_STA); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_TDLS_ADD_PEER_STA); + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_TDLS_DEL_PEER_STA); +#endif + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_PREF_NET_LIST); +#ifdef FEATURE_WLAN_LPHB + CASE_RETURN_STRING(TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ); +#endif /* FEATURE_WLAN_LPHB */ + default: + return( "UNKNOWN" ); + break; + } +} +static tANI_U8* smeTraceGetCommandString( tANI_U32 command ) +{ + switch(command) + { + CASE_RETURN_STRING(eSmeNoCommand); + CASE_RETURN_STRING(eSmeDropCommand); + CASE_RETURN_STRING(eSmeCsrCommandMask); + CASE_RETURN_STRING(eSmeCommandScan); + CASE_RETURN_STRING(eSmeCommandRoam); + CASE_RETURN_STRING(eSmeCommandWmStatusChange); + CASE_RETURN_STRING(eSmeCommandSetKey); + CASE_RETURN_STRING(eSmeCommandRemoveKey); + CASE_RETURN_STRING(eSmeCommandAddStaSession); + CASE_RETURN_STRING(eSmeCommandDelStaSession); + CASE_RETURN_STRING(eSmePmcCommandMask); + CASE_RETURN_STRING(eSmeCommandEnterImps); + CASE_RETURN_STRING(eSmeCommandExitImps); + CASE_RETURN_STRING(eSmeCommandEnterBmps); + CASE_RETURN_STRING(eSmeCommandExitBmps); + CASE_RETURN_STRING(eSmeCommandEnterUapsd); + CASE_RETURN_STRING(eSmeCommandExitUapsd); + CASE_RETURN_STRING(eSmeCommandEnterWowl); + CASE_RETURN_STRING(eSmeCommandExitWowl); + CASE_RETURN_STRING(eSmeCommandEnterStandby); + CASE_RETURN_STRING(eSmeQosCommandMask); + CASE_RETURN_STRING(eSmeCommandAddTs); + CASE_RETURN_STRING(eSmeCommandDelTs); +#ifdef FEATURE_OEM_DATA_SUPPORT + CASE_RETURN_STRING(eSmeCommandOemDataReq); +#endif + CASE_RETURN_STRING(eSmeCommandRemainOnChannel); + CASE_RETURN_STRING(eSmeCommandNoAUpdate); + default: + return( "UNKNOWN" ); + break; + } +} +static void smeTraceDump(tpAniSirGlobal pMac, tpvosTraceRecord pRecord, + tANI_U16 recIndex) +{ + if (TRACE_CODE_SME_COMMAND == pRecord->code) + { + smsLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, + pRecord->time, pRecord->session, "SME COMMAND:", + smeTraceGetCommandString(pRecord->data), pRecord->data ); + } + else + { + smsLog(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, + pRecord->time, pRecord->session, "RX HDD MSG:", + smeTraceGetRxMsgString(pRecord->code), pRecord->data ); + } +} + +void smeTraceInit(tpAniSirGlobal pMac) +{ + vosTraceRegister(VOS_MODULE_ID_SME, (tpvosTraceCb)&smeTraceDump); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/external/wlan_nlink_common.h b/drivers/staging/qcacld-2.0/CORE/SVC/external/wlan_nlink_common.h new file mode 100644 index 000000000000..8bf9f87e3b10 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/external/wlan_nlink_common.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + \file wlan_nlink_common.h + + Exports and types for the Netlink Service interface. This header file contains + message types and definitions that is shared between the user space service + (e.g. BTC service) and WLAN kernel module. + +===========================================================================*/ + +#ifndef WLAN_NLINK_COMMON_H__ +#define WLAN_NLINK_COMMON_H__ + +#include +#ifdef QCA_FEATURE_RPS +#include +#endif +/*--------------------------------------------------------------------------- + * External Functions + *-------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + *-------------------------------------------------------------------------*/ +#define WLAN_NL_MAX_PAYLOAD 256 /* maximum size for netlink message*/ +#define WLAN_NLINK_PROTO_FAMILY NETLINK_USERSOCK +#define WLAN_NLINK_MCAST_GRP_ID 0x01 + +/*--------------------------------------------------------------------------- + * Type Declarations + *-------------------------------------------------------------------------*/ + +/* + * The following enum defines the target service within WLAN driver for which the + * message is intended for. Each service along with its counterpart + * in the user space, define a set of messages they recognize. + * Each of this message will have an header of type tAniMsgHdr defined below. + * Each Netlink message to/from a kernel module will contain only one + * message which is preceded by a tAniMsgHdr. The maximun size (in bytes) of + * a netlink message is assumed to be MAX_PAYLOAD bytes. + * + * +------------+-------+----------+----------+ + * |Netlink hdr | Align |tAniMsgHdr| msg body | + * +------------+-------+----------|----------+ + */ + +// Message Types +#define WLAN_BTC_QUERY_STATE_REQ 0x01 // BTC --> WLAN +#define WLAN_BTC_BT_EVENT_IND 0x02 // BTC --> WLAN +#define WLAN_BTC_QUERY_STATE_RSP 0x03 // WLAN --> BTC +#define WLAN_MODULE_UP_IND 0x04 // WLAN --> BTC +#define WLAN_MODULE_DOWN_IND 0x05 // WLAN --> BTC +#define WLAN_STA_ASSOC_DONE_IND 0x06 // WLAN --> BTC +#define WLAN_STA_DISASSOC_DONE_IND 0x07 // WLAN --> BTC + +// Special Message Type used by AMP, intercepted by send_btc_nlink_msg() and +// replaced by WLAN_STA_ASSOC_DONE_IND or WLAN_STA_DISASSOC_DONE_IND +#define WLAN_AMP_ASSOC_DONE_IND 0x10 + +// Special Message Type used by SoftAP, intercepted by send_btc_nlink_msg() and +// replaced by WLAN_STA_ASSOC_DONE_IND +#define WLAN_BTC_SOFTAP_BSS_START 0x11 +#define WLAN_SVC_FW_CRASHED_IND 0x100 +#define WLAN_SVC_LTE_COEX_IND 0x101 +#define WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND 0x102 +#define WLAN_SVC_DFS_CAC_START_IND 0x103 +#define WLAN_SVC_DFS_CAC_END_IND 0x104 +#define WLAN_SVC_DFS_RADAR_DETECT_IND 0x105 +#define WLAN_SVC_WLAN_STATUS_IND 0x106 +#define WLAN_SVC_WLAN_VERSION_IND 0x107 +#define WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND 0x108 +#define WLAN_SVC_WLAN_TP_IND 0x109 +#define WLAN_SVC_RPS_ENABLE_IND 0x10A +#define WLAN_SVC_WLAN_TP_TX_IND 0x10B + +#define WLAN_SVC_MAX_SSID_LEN 32 +#define WLAN_SVC_MAX_BSSID_LEN 6 +#define WLAN_SVC_MAX_STR_LEN 16 +#define WLAN_SVC_MAX_NUM_CHAN 128 +#define WLAN_SVC_COUNTRY_CODE_LEN 3 + +/* + * Maximim number of queues supported by WLAN driver. Setting an upper + * limit. Actual number of queues may be smaller than this value. + */ +#define WLAN_SVC_IFACE_NUM_QUEUES 6 + +// Event data for WLAN_BTC_QUERY_STATE_RSP & WLAN_STA_ASSOC_DONE_IND +typedef struct +{ + unsigned char channel; // 0 implies STA not associated to AP +} tWlanAssocData; + +#define ANI_NL_MSG_BASE 0x10 /* Some arbitrary base */ + +typedef enum eAniNlModuleTypes { + ANI_NL_MSG_PUMAC = ANI_NL_MSG_BASE + 0x01,// PTT Socket App + ANI_NL_MSG_PTT = ANI_NL_MSG_BASE + 0x07,// Quarky GUI + WLAN_NL_MSG_BTC, + WLAN_NL_MSG_OEM, + WLAN_NL_MSG_SVC, + WLAN_NL_MSG_CNSS_DIAG = ANI_NL_MSG_BASE + 0x0B,//Value needs to be 27 + ANI_NL_MSG_LOG, + ANI_NL_MSG_MAX +} tAniNlModTypes, tWlanNlModTypes; + +#define WLAN_NL_MSG_BASE ANI_NL_MSG_BASE +#define WLAN_NL_MSG_MAX ANI_NL_MSG_MAX + +//All Netlink messages must contain this header +typedef struct sAniHdr { + unsigned short type; + unsigned short length; +} tAniHdr, tAniMsgHdr; + +struct wlan_status_data { + uint8_t lpss_support; + uint8_t is_on; + uint8_t vdev_id; + uint8_t is_connected; + int8_t rssi; + uint8_t ssid_len; + uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN]; + uint32_t vdev_mode; + uint32_t freq; + uint32_t numChannels; + uint8_t channel_list[WLAN_SVC_MAX_NUM_CHAN]; + uint8_t ssid[WLAN_SVC_MAX_SSID_LEN]; + uint8_t bssid[WLAN_SVC_MAX_BSSID_LEN]; +}; + +struct wlan_version_data { + uint32_t chip_id; + char chip_name[WLAN_SVC_MAX_STR_LEN]; + char chip_from[WLAN_SVC_MAX_STR_LEN]; + char host_version[WLAN_SVC_MAX_STR_LEN]; + char fw_version[WLAN_SVC_MAX_STR_LEN]; +}; + +#ifdef QCA_FEATURE_RPS +/** + * struct wlan_rps_data - structure to send RPS info to cnss-daemon + * @ifname: interface name for which the RPS data belongs to + * @num_queues: number of rx queues for which RPS data is being sent + * @cpu_map_list: array of cpu maps for different rx queues supported by + * the wlan driver + * + * The structure specifies the format of data exchanged between wlan + * driver and cnss-daemon. On receipt of the data, cnss-daemon is expected + * to apply the 'cpu_map' for each rx queue belonging to the interface 'ifname' + */ +struct wlan_rps_data { + char ifname[IFNAMSIZ]; + uint16_t num_queues; + uint16_t cpu_map_list[WLAN_SVC_IFACE_NUM_QUEUES]; +}; +#endif + +struct wlan_dfs_info { + uint16_t channel; + uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN]; +}; + +/** + * enum wlan_tp_level - indicates wlan throughput level + * + * The different throughput levels are determined on the basis of # of tx and + * rx packets and other threshold values. For example, if the # of total packets + * sent or received by the driver is greater than 500 in the last 100ms, the + * driver has a high throughput requirement. The driver may tweak certain system + * parameters based on the throughput level. + * + * @WLAN_SVC_TP_NONE - used for initialization + * @WLAN_SVC_TP_LOW - used to identify low throughput level + * @WLAN_SVC_TP_MEDIUM - used to identify medium throughput level + * @WLAN_SVC_TP_HIGH - used to identify high throughput level + */ +enum wlan_tp_level { + WLAN_SVC_TP_NONE, + WLAN_SVC_TP_LOW, + WLAN_SVC_TP_MEDIUM, + WLAN_SVC_TP_HIGH, +}; + +#endif //WLAN_NLINK_COMMON_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_btc_svc.h b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_btc_svc.h new file mode 100644 index 000000000000..7eee2dec2527 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_btc_svc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + * wlan_btc_svc.h + * + ******************************************************************************/ + +#ifndef WLAN_BTC_SVC_H +#define WLAN_BTC_SVC_H + +void send_btc_nlink_msg (int type, int dest_pid); +int btc_activate_service(void *pAdapter); + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_logging_sock_svc.h b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_logging_sock_svc.h new file mode 100644 index 000000000000..ce009b69ecd8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_logging_sock_svc.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + * wlan_logging_sock_svc.h + * + ******************************************************************************/ + +#ifndef WLAN_LOGGING_SOCK_SVC_H +#define WLAN_LOGGING_SOCK_SVC_H + +#include +#include +#include +#include +#include + +int wlan_logging_sock_init_svc(void); +int wlan_logging_sock_deinit_svc(void); +int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf); +int wlan_logging_sock_deactivate_svc(void); +int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length); +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE +void wlan_logging_set_per_pkt_stats(void); +void wlan_logging_set_log_level(void); +void wlan_logging_set_fw_flush_complete(void); +#else +static inline void wlan_logging_set_per_pkt_stats(void) +{ + return; +} +static inline void wlan_logging_set_log_level(void) +{ + return; +} +static inline void wlan_logging_set_fw_flush_complete(void) +{ + return; +} +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void wlan_report_log_completion(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code); +#else +static inline void wlan_report_log_completion(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code) +{ + return; +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ +#endif /* WLAN_LOGGING_SOCK_SVC_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_nlink_srv.h b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_nlink_srv.h new file mode 100644 index 000000000000..2d5db8b3c56c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_nlink_srv.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + * wlan_nlink_srv.h + * + * wlan_nlink_srv is used to RX/TX Netlink messages from user space to kernel + * modules and vice versa. Kernel modules must register a message handler for a + * message type so that the wlan_nlink_srv can invoke the corresponding msg handler + * whenever a Netlink message of a particular type has been received from an + * application. In the opposite direction, wlan_nlink_srv provides a mechanism + * which kernel modules can use to send Netlink messages to applications. + * + ******************************************************************************/ + +#ifndef WLAN_NLINK_SRV_H +#define WLAN_NLINK_SRV_H + +#include +#include +#include + +#define INVALID_PID -1 +#define NLINK_MAX_CALLBACKS (WLAN_NL_MSG_MAX - WLAN_NL_MSG_BASE) + +typedef int (* nl_srv_msg_callback)(struct sk_buff * skb); + +int nl_srv_init(void); +#ifdef WLAN_KD_READY_NOTIFIER +void nl_srv_exit(int dst_pid); +#else +void nl_srv_exit(void); +#endif /* WLAN_KD_READY_NOTIFIER */ +int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler); +int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler); +int nl_srv_ucast(struct sk_buff * skb, int dst_pid, int flag); +int nl_srv_bcast(struct sk_buff * skb); +int nl_srv_is_initialized(void); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_ptt_sock_svc.h b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_ptt_sock_svc.h new file mode 100644 index 000000000000..9a2c71884b9b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/inc/wlan_ptt_sock_svc.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + * wlan_ptt_sock_svc.c + * + ******************************************************************************/ +#ifndef PTT_SOCK_SVC_H +#define PTT_SOCK_SVC_H +#include +#include +#include +#include +#include +#include +/* + * Quarky Message Format: + * The following is the messaging protocol between Quarky and PTT Socket App. + * The totalMsgLen is the length from Radio till msgBody. The value of Radio + * is always defaulted to 0. The MsgLen is the length from msgId till msgBody. + * The length of the msgBody varies with respect to the MsgId. Buffer space + * for MsgBody is already allocated in the received buffer. So in case of READ + * we just need to populate the values in the received message and send it + * back + * +------------+-------+-------+--------+-------+---------+ + * |TotalMsgLen | Radio | MsgId | MsgLen |Status |MsgBody | + * +------------+-------+-------|--------+-------+---------+ + * <------4----><--4---><---2--><---2---><---4--><---------> + */ +// PTT Socket App Message Ids +#define PTT_MSG_READ_REGISTER 0x3040 +#define PTT_MSG_WRITE_REGISTER 0x3041 +#define PTT_MSG_READ_MEMORY 0x3044 +#define PTT_MSG_WRITE_MEMORY 0x3045 +#define PTT_MSG_LOG_DUMP_DBG 0x32A1 +#define PTT_MSG_FTM_CMDS_TYPE 0x4040 +#define ANI_DRIVER_MSG_START 0x0001 +#define ANI_MSG_APP_REG_REQ (ANI_DRIVER_MSG_START + 0) +#define ANI_MSG_APP_REG_RSP (ANI_DRIVER_MSG_START + 1) +#define ANI_MSG_OEM_DATA_REQ (ANI_DRIVER_MSG_START + 2) +#define ANI_MSG_OEM_DATA_RSP (ANI_DRIVER_MSG_START + 3) +#define ANI_MSG_CHANNEL_INFO_REQ (ANI_DRIVER_MSG_START + 4) +#define ANI_MSG_CHANNEL_INFO_RSP (ANI_DRIVER_MSG_START + 5) +#define ANI_MSG_OEM_ERROR (ANI_DRIVER_MSG_START + 6) +#define ANI_MSG_PEER_STATUS_IND (ANI_DRIVER_MSG_START + 7) + +#define ANI_MAX_RADIOS 3 +#define ANI_NL_MSG_OK 0 +#define ANI_NL_MSG_ERROR -1 +#define ANI_NL_MSG_OVERHEAD (NLMSG_SPACE(tAniHdr + 4)) +/* + * Packet Format for READ_REGISTER & WRITE_REGISTER: + * TotalMsgLen : 4 bytes [value=20 bytes] + * Radio : 4 bytes + * MsgId : 2 bytes + * MsgLen : 2 bytes + * Status : 4 bytes + * Address : 4 bytes + * Payload : 4 bytes +*/ +/* + * Packet Format for READ_MEMORY & WRITE_MEMORY : + * TotalMsgLen : 4 bytes [value= 20+LEN_PAYLOAD bytes] + * Radio : 4 bytes + * MsgId : 2 bytes + * MsgLen : 2 bytes + * Status : 4 bytes + * Address : 4 bytes + * Length : 4 bytes [LEN_PAYLOAD] + * Payload : LEN_PAYLOAD bytes +*/ +int ptt_sock_activate_svc(void *pAdapter); +int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid); + +/* + * Format of message exchanged between the PTT Socket App in userspace and the + * WLAN Driver, in either direction. Each msg will begin with this header and + * will followed by the Quarky message + */ +typedef struct sAniNlMsg { + struct nlmsghdr nlh; // Netlink Header + int radio; // unit number of the radio + tAniHdr wmsg; // Airgo Message Header +} tAniNlHdr; +typedef struct sAniAppRegReq { + tAniNlModTypes type; // module id + int pid; // process id +} tAniNlAppRegReq; +typedef struct sAniNlAppRegRsp { + tAniHdr wniHdr; // Generic WNI msg header + tAniNlAppRegReq regReq; // The original request msg + int ret; // Return code +} tAniNlAppRegRsp; +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/src/btc/wlan_btc_svc.c b/drivers/staging/qcacld-2.0/CORE/SVC/src/btc/wlan_btc_svc.c new file mode 100644 index 000000000000..7d4aeaf7538f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/btc/wlan_btc_svc.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/****************************************************************************** + * wlan_btc_svc.c + * + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +// Global variables +static struct hdd_context_s *pHddCtx; + +static int gWiFiChannel; /* WiFi associated channel 1-13, or 0 (none) */ +static int gAmpChannel; /* AMP associated channel 1-13, or 0 (none) */ +static int gBtcDriverMode = WLAN_HDD_INFRA_STATION; /* Driver mode in BTC */ + + +// Forward declrarion +static int btc_msg_callback (struct sk_buff * skb); +/* + * Send a netlink message to the user space. + * Destination pid as zero implies broadcast + */ +void send_btc_nlink_msg (int type, int dest_pid) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tWlanAssocData *assocData; + skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL); + if(skb == NULL) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "BTC: alloc_skb failed\n"); + return; + } + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_BTC; + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = type; + + /* Set BTC driver mode correctly based on received events type */ + if(type == WLAN_BTC_SOFTAP_BSS_START) + { + /* Event is SoftAP BSS Start set BTC driver mode to SoftAP */ + gBtcDriverMode = WLAN_HDD_SOFTAP; + } + if(type == WLAN_STA_ASSOC_DONE_IND) + { + /* Event is STA Assoc done set BTC driver mode to INFRA STA*/ + gBtcDriverMode = WLAN_HDD_INFRA_STATION; + } + + switch( type ) + { + case WLAN_STA_DISASSOC_DONE_IND: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, + "WiFi unassociated; gAmpChannel %d gWiFiChannel %d", gAmpChannel, gWiFiChannel); + + /* If AMP is using a channel (non-zero), no message sent. + Or, if WiFi wasn't using a channel before, no message sent. + Logic presumes same channel has to be used for WiFi and AMP if both are active. + In any case, track the WiFi channel in use (none) */ + if((gAmpChannel != 0) || (gWiFiChannel == 0)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, + "No msg for AFH will be sent"); + gWiFiChannel = 0; + kfree_skb(skb); + return; + } + gWiFiChannel = 0; + + /* No Break: Fall into next cases */ + + case WLAN_MODULE_UP_IND: + case WLAN_MODULE_DOWN_IND: + aniHdr->length = 0; + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr))); + skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr))); + break; + case WLAN_BTC_SOFTAP_BSS_START: + case WLAN_BTC_QUERY_STATE_RSP: + case WLAN_STA_ASSOC_DONE_IND: + aniHdr->length = sizeof(tWlanAssocData); + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + sizeof(tWlanAssocData))); + assocData = ( tWlanAssocData *)((char*)aniHdr + sizeof(tAniMsgHdr)); + + assocData->channel = hdd_get_operating_channel( pHddCtx, gBtcDriverMode ); + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, + "New WiFi channel %d gAmpChannel %d gWiFiChannel %d", + assocData->channel, gAmpChannel, gWiFiChannel); + + /* If WiFi has finished associating */ + if(type == WLAN_STA_ASSOC_DONE_IND) + { + /* If AMP is using a channel (non-zero), no message sent. + Or, if the WiFi channel did not change, no message sent. + Logic presumes same channel has to be used for WiFi and AMP if both are active. + In any case, track the WiFi channel in use (1-13 or none, in assocData->channel) */ + if((gAmpChannel != 0) || (assocData->channel == gWiFiChannel)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, + "No msg for AFH will be sent"); + gWiFiChannel = assocData->channel; + kfree_skb(skb); + return; + } + } + if(type == WLAN_BTC_SOFTAP_BSS_START) + { + /*Replace WLAN_BTC_SOFTAP_BSS_START by WLAN_STA_ASSOC_DONE_IND*/ + aniHdr->type = WLAN_STA_ASSOC_DONE_IND; + } + gWiFiChannel = assocData->channel; + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr)+ sizeof(tWlanAssocData)))); + break; + + case WLAN_AMP_ASSOC_DONE_IND: + + /* This is an overloaded type. It means that AMP is connected (dest_pid is channel 1-13), + or it means AMP is now disconnected (dest_pid is 0) */ + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, + "New AMP channel %d gAmpChannel %d gWiFiChannel %d", dest_pid, gAmpChannel, gWiFiChannel); + /* If WiFi is using a channel (non-zero), no message sent. + Or, if the AMP channel did not change, no message sent. + Logic presumes same channel has to be used for WiFi and AMP if both are active. + In any case, track the AMP channel in use (1-13 or none, in dest_pid) */ + if((gWiFiChannel != 0) || (dest_pid == gAmpChannel)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, + "No msg for AFH will be sent"); + gAmpChannel = dest_pid; + kfree_skb(skb); + return; + } + + gAmpChannel = dest_pid; + + /* Fix overloaded parameters and finish message formatting */ + if(dest_pid != 0) + { + aniHdr->type = WLAN_STA_ASSOC_DONE_IND; + aniHdr->length = sizeof(tWlanAssocData); + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + sizeof(tWlanAssocData))); + assocData = ( tWlanAssocData *)((char*)aniHdr + sizeof(tAniMsgHdr)); + assocData->channel = dest_pid; + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr)+ sizeof(tWlanAssocData)))); + } + else + { + aniHdr->type = WLAN_STA_DISASSOC_DONE_IND; + aniHdr->length = 0; + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr))); + skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr))); + } + dest_pid = 0; + break; + + default: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "BTC: Attempt to send unknown nlink message %d\n", type); + kfree_skb(skb); + return; + } + if(dest_pid == 0) + (void)nl_srv_bcast(skb); + else + (void)nl_srv_ucast(skb, dest_pid, MSG_DONTWAIT); +} +/* + * Activate BTC handler. This will register a handler to receive + * netlink messages addressed to WLAN_NL_MSG_BTC from user space + */ +int btc_activate_service(void *pAdapter) +{ + pHddCtx = (struct hdd_context_s*)pAdapter; + + //Register the msg handler for msgs addressed to ANI_NL_MSG_BTC + nl_srv_register(WLAN_NL_MSG_BTC, btc_msg_callback); + return 0; +} +/* + * Callback function invoked by Netlink service for all netlink + * messages (from user space) addressed to WLAN_NL_MSG_BTC + */ +int btc_msg_callback (struct sk_buff * skb) +{ + struct nlmsghdr *nlh; + tAniMsgHdr *msg_hdr; + tSmeBtEvent *btEvent = NULL; + nlh = (struct nlmsghdr *)skb->data; + msg_hdr = NLMSG_DATA(nlh); + + /* Continue with parsing payload. */ + switch(msg_hdr->type) + { + case WLAN_BTC_QUERY_STATE_REQ: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "BTC: Received probe from BTC Service\n"); + send_btc_nlink_msg(WLAN_BTC_QUERY_STATE_RSP, nlh->nlmsg_pid); + break; + case WLAN_BTC_BT_EVENT_IND: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "BTC: Received Bluetooth event indication\n"); + if(msg_hdr->length != sizeof(tSmeBtEvent)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "BTC: Size mismatch in BT event data\n"); + break; + } + btEvent = (tSmeBtEvent*)((char*)msg_hdr + sizeof(tAniMsgHdr)); + (void)sme_BtcSignalBtEvent(pHddCtx->hHal, btEvent); + break; + default: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "BTC: Received Invalid Msg type [%d]\n", msg_hdr->type); + break; + } + return 0; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c new file mode 100644 index 000000000000..8e5517ef7d9b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + * wlan_logging_sock_svc.c + * + ******************************************************************************/ + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pktlog_ac.h" + +#define LOGGING_TRACE(level, args...) \ + VOS_TRACE(VOS_MODULE_ID_HDD, level, ## args) + +/* Global variables */ + +#define ANI_NL_MSG_LOG_TYPE 89 +#define ANI_NL_MSG_READY_IND_TYPE 90 +#define MAX_LOGMSG_LENGTH 4096 + +#define HOST_LOG_DRIVER_MSG 0x001 +#define HOST_LOG_PER_PKT_STATS 0x002 +#define HOST_LOG_FW_FLUSH_COMPLETE 0x003 + +struct log_msg { + struct list_head node; + unsigned int radio; + unsigned int index; + /* indicates the current filled log length in logbuf */ + unsigned int filled_length; + /* + * Buf to hold the log msg + * tAniHdr + log + */ + char logbuf[MAX_LOGMSG_LENGTH]; +}; + +struct wlan_logging { + /* Log Fatal and ERROR to console */ + bool log_fe_to_console; + /* Number of buffers to be used for logging */ + int num_buf; + /* Lock to synchronize access to shared logging resource */ + spinlock_t spin_lock; + /* Holds the free node which can be used for filling logs */ + struct list_head free_list; + /* Holds the filled nodes which needs to be indicated to APP */ + struct list_head filled_list; + /* Wait queue for Logger thread */ + wait_queue_head_t wait_queue; + /* Logger thread */ + struct task_struct *thread; + /* Logging thread sets this variable on exit */ + struct completion shutdown_comp; + /* Indicates to logger thread to exit */ + bool exit; + /* Holds number of dropped logs*/ + unsigned int drop_count; + /* current logbuf to which the log will be filled to */ + struct log_msg *pcur_node; + /* Event flag used for wakeup and post indication*/ + unsigned long eventFlag; + /* Indicates logger thread is activated */ + bool is_active; + /* Flush completion check */ + bool is_flush_complete; +}; + +static struct wlan_logging gwlan_logging; +static struct log_msg *gplog_msg; + +/* PID of the APP to log the message */ +static int gapp_pid = INVALID_PID; + +/* Utility function to send a netlink message to an application + * in user space + */ +static int wlan_send_sock_msg_to_app(tAniHdr *wmsg, int radio, + int src_mod, int pid) +{ + int err = -1; + int payload_len; + int tot_msg_len; + tAniNlHdr *wnl = NULL; + struct sk_buff *skb; + struct nlmsghdr *nlh; + int wmsg_length = wmsg->length; + static int nlmsg_seq; + + if (radio < 0 || radio > ANI_MAX_RADIOS) { + LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, + "%s: invalid radio id [%d]", + __func__, radio); + return -EINVAL; + } + + payload_len = wmsg_length + sizeof(wnl->radio); + tot_msg_len = NLMSG_SPACE(payload_len); + skb = dev_alloc_skb(tot_msg_len); + if (skb == NULL) { + LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, + "%s: dev_alloc_skb() failed for msg size[%d]", + __func__, tot_msg_len); + return -ENOMEM; + } + nlh = nlmsg_put(skb, pid, nlmsg_seq++, src_mod, payload_len, + NLM_F_REQUEST); + if (NULL == nlh) { + LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, + "%s: nlmsg_put() failed for msg size[%d]", + __func__, tot_msg_len); + kfree_skb(skb); + return -ENOMEM; + } + + wnl = (tAniNlHdr *) nlh; + wnl->radio = radio; + memcpy(&wnl->wmsg, wmsg, wmsg_length); + LOGGING_TRACE(VOS_TRACE_LEVEL_INFO, + "%s: Sending Msg Type [0x%X] to pid[%d]\n", + __func__, be16_to_cpu(wmsg->type), pid); + + err = nl_srv_ucast(skb, pid, MSG_DONTWAIT); + return err; +} + +/** + * is_data_path_module() - To check for a Datapath module + * @mod_id: Module id + * + * Checks if the input module id belongs to data path. + * + * Return: True if the module belongs to data path, false otherwise + */ +static bool is_data_path_module(VOS_MODULE_ID mod_id) +{ + switch (mod_id) { + case VOS_MODULE_ID_HDD_DATA: + case VOS_MODULE_ID_HDD_SAP_DATA: + case VOS_MODULE_ID_HTC: + case VOS_MODULE_ID_TXRX: + case VOS_MODULE_ID_HIF: + case VOS_MODULE_ID_VOSS: + case VOS_MODULE_ID_TL: + return true; + default: + return false; + } +} + +static void set_default_logtoapp_log_level(void) +{ + int i; + + /* module id 0 is reserved */ + for (i = 1; i < VOS_MODULE_ID_MAX; i++) { + if (is_data_path_module(i)) + vos_trace_set_module_trace_level(i, + VOS_DATA_PATH_TRACE_LEVEL); + else + vos_trace_setValue(i, VOS_TRACE_LEVEL_ALL, VOS_TRUE); + } +} + +static void clear_default_logtoapp_log_level(void) +{ + int module; + + for (module = 0; module < VOS_MODULE_ID_MAX; module++) { + vos_trace_setValue(module, VOS_TRACE_LEVEL_NONE, + VOS_FALSE); + vos_trace_setValue(module, VOS_TRACE_LEVEL_FATAL, + VOS_TRUE); + vos_trace_setValue(module, VOS_TRACE_LEVEL_ERROR, + VOS_TRUE); + } + + vos_trace_setValue(VOS_MODULE_ID_RSV3, VOS_TRACE_LEVEL_NONE, + VOS_FALSE); + vos_trace_setValue(VOS_MODULE_ID_RSV4, VOS_TRACE_LEVEL_NONE, + VOS_FALSE); +} + +/* Need to call this with spin_lock acquired */ +static int wlan_queue_logmsg_for_app(void) +{ + char *ptr; + int ret = 0; + ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; + ptr[gwlan_logging.pcur_node->filled_length] = '\0'; + + *(unsigned short *)(gwlan_logging.pcur_node->logbuf) = + ANI_NL_MSG_LOG_TYPE; + *(unsigned short *)(gwlan_logging.pcur_node->logbuf + 2) = + gwlan_logging.pcur_node->filled_length; + list_add_tail(&gwlan_logging.pcur_node->node, + &gwlan_logging.filled_list); + + if (!list_empty(&gwlan_logging.free_list)) { + /* Get buffer from free list */ + gwlan_logging.pcur_node = + (struct log_msg *)(gwlan_logging.free_list.next); + list_del_init(gwlan_logging.free_list.next); + } else if (!list_empty(&gwlan_logging.filled_list)) { + /* Get buffer from filled list */ + /* This condition will drop the packet from being + * indicated to app + */ + gwlan_logging.pcur_node = + (struct log_msg *)(gwlan_logging.filled_list.next); + ++gwlan_logging.drop_count; + /* print every 64th drop count */ + if (vos_is_multicast_logging() && + (!(gwlan_logging.drop_count % 0x40))) { + pr_info("%s: drop_count = %u index = %d filled_length = %d\n", + __func__, gwlan_logging.drop_count, + gwlan_logging.pcur_node->index, + gwlan_logging.pcur_node->filled_length); + } + list_del_init(gwlan_logging.filled_list.next); + ret = 1; + } + + /* Reset the current node values */ + gwlan_logging.pcur_node->filled_length = 0; + return ret; +} + + +int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) +{ + /* Add the current time stamp */ + char *ptr; + char tbuf[50]; + int tlen; + int total_log_len; + unsigned int *pfilled_length; + bool wake_up_thread = false; + unsigned long flags; + uint64_t ts; + uint32_t rem; + + if (!vos_is_multicast_logging()) { + /* + * This is to make sure that we print the logs to kmsg console + * when no logger app is running. This is also needed to + * log the initial messages during loading of driver where even + * if app is running it will not be able to + * register with driver immediately and start logging all the + * messages. + */ + pr_info("%s\n", to_be_sent); + } else { + + /* Format the Log time [Seconds.microseconds] */ + ts = adf_get_boottime(); + rem = do_div(ts, VOS_TIMER_TO_SEC_UNIT); + tlen = snprintf(tbuf, sizeof(tbuf), "[%s][%lu.%06lu] ", + current->comm, + (unsigned long) ts, (unsigned long)rem); + + /* 1+1 indicate '\n'+'\0' */ + total_log_len = length + tlen + 1 + 1; + + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + // wlan logging svc resources are not yet initialized + if (!gwlan_logging.pcur_node) { + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + return -EIO; + } + + pfilled_length = &gwlan_logging.pcur_node->filled_length; + + /* Check if we can accomodate more log into current + * node/buffer + */ + if ((MAX_LOGMSG_LENGTH <= (*pfilled_length + + sizeof(tAniNlHdr))) || + ((MAX_LOGMSG_LENGTH - (*pfilled_length + + sizeof(tAniNlHdr))) < total_log_len)) { + wake_up_thread = true; + wlan_queue_logmsg_for_app(); + pfilled_length = + &gwlan_logging.pcur_node->filled_length; + } + + ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; + + /* Assumption here is that we receive logs which is always + * less than MAX_LOGMSG_LENGTH, where we can accomodate the + * tAniNlHdr + [context][timestamp] + log + * VOS_ASSERT if we cannot accomodate the the complete log into + * the available buffer. + * + * Continue and copy logs to the available length and + * discard the rest. + */ + if (MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len)) { + VOS_ASSERT(0); + total_log_len = MAX_LOGMSG_LENGTH - + sizeof(tAniNlHdr) - 2; + } + + memcpy(&ptr[*pfilled_length], tbuf, tlen); + memcpy(&ptr[*pfilled_length + tlen], to_be_sent, + min(length, (total_log_len - tlen))); + *pfilled_length += tlen + min(length, total_log_len - tlen); + ptr[*pfilled_length] = '\n'; + *pfilled_length += 1; + + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + + /* Wakeup logger thread */ + if ((true == wake_up_thread)) { + /* If there is logger app registered wakeup the logging + * thread (or) if always multicasting of host messages + * is enabled, wake up the logging thread + */ + set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); + } + + if (gwlan_logging.log_fe_to_console + && ((VOS_TRACE_LEVEL_FATAL == log_level) + || (VOS_TRACE_LEVEL_ERROR == log_level))) { + pr_info("%s\n", to_be_sent); + } + } + return 0; +} + +static int send_filled_buffers_to_user(void) +{ + int ret = -1; + struct log_msg *plog_msg; + int payload_len; + int tot_msg_len; + tAniNlHdr *wnl; + struct sk_buff *skb = NULL; + struct nlmsghdr *nlh; + static int nlmsg_seq; + unsigned long flags; + static int rate_limit; + + while (!list_empty(&gwlan_logging.filled_list) + && !gwlan_logging.exit) { + + skb = dev_alloc_skb(MAX_LOGMSG_LENGTH); + if (skb == NULL) { + if (!rate_limit) { + pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n", + __func__, MAX_LOGMSG_LENGTH, + gwlan_logging.drop_count); + } + rate_limit = 1; + ret = -ENOMEM; + break; + } + rate_limit = 0; + + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + + plog_msg = (struct log_msg *) + (gwlan_logging.filled_list.next); + list_del_init(gwlan_logging.filled_list.next); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + /* 4 extra bytes for the radio idx */ + payload_len = plog_msg->filled_length + + sizeof(wnl->radio) + sizeof(tAniHdr); + + tot_msg_len = NLMSG_SPACE(payload_len); + nlh = nlmsg_put(skb, 0, nlmsg_seq++, + ANI_NL_MSG_LOG, payload_len, + NLM_F_REQUEST); + if (NULL == nlh) { + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + list_add_tail(&plog_msg->node, + &gwlan_logging.free_list); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, + flags); + pr_err("%s: drop_count = %u\n", __func__, + ++gwlan_logging.drop_count); + pr_err("%s: nlmsg_put() failed for msg size[%d]\n", + __func__, tot_msg_len); + dev_kfree_skb(skb); + skb = NULL; + ret = -EINVAL; + continue; + } + + wnl = (tAniNlHdr *) nlh; + wnl->radio = plog_msg->radio; + memcpy(&wnl->wmsg, plog_msg->logbuf, + plog_msg->filled_length + + sizeof(tAniHdr)); + + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + list_add_tail(&plog_msg->node, + &gwlan_logging.free_list); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + + ret = nl_srv_bcast(skb); + /* print every 64th drop count */ + if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) { + pr_err("%s: Send Failed %d drop_count = %u\n", + __func__, ret, ++gwlan_logging.drop_count); + skb = NULL; + } else { + skb = NULL; + ret = 0; + } + } + + return ret; +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * wlan_report_log_completion() - Report bug report completion to userspace + * @is_fatal: Type of event, fatal or not + * @indicator: Source of bug report, framework/host/firmware + * @reason_code: Reason for triggering bug report + * + * This function is used to report the bug report completion to userspace + * + * Return: None + */ +void wlan_report_log_completion(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code) +{ + WLAN_VOS_DIAG_EVENT_DEF(wlan_diag_event, + struct vos_event_wlan_log_complete); + + wlan_diag_event.is_fatal = is_fatal; + wlan_diag_event.indicator = indicator; + wlan_diag_event.reason_code = reason_code; + wlan_diag_event.reserved = 0; + + WLAN_VOS_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_LOG_COMPLETE); +} +#endif + +/** + * send_flush_completion_to_user() - Indicate flush completion to the user + * + * This function is used to send the flush completion message to user space + * + * Return: None + */ +void send_flush_completion_to_user(void) +{ + uint32_t is_fatal, indicator, reason_code; + + vos_get_log_completion(&is_fatal, &indicator, &reason_code); + + /* Error on purpose, so that it will get logged in the kmsg */ + LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, + "%s: Sending flush done to userspace", __func__); + + wlan_report_log_completion(is_fatal, indicator, reason_code); +} + +/** + * wlan_logging_thread() - The WLAN Logger thread + * @Arg - pointer to the HDD context + * + * This thread logs log message to App registered for the logs. + */ +static int wlan_logging_thread(void *Arg) +{ + int ret_wait_status = 0; + int ret = 0; + + set_user_nice(current, -2); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + daemonize("wlan_logging_thread"); +#endif + + while (!gwlan_logging.exit) { + ret_wait_status = wait_event_interruptible( + gwlan_logging.wait_queue, + (!list_empty(&gwlan_logging.filled_list) + || test_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag) + || test_bit(HOST_LOG_PER_PKT_STATS, + &gwlan_logging.eventFlag) + || test_bit(HOST_LOG_FW_FLUSH_COMPLETE, + &gwlan_logging.eventFlag) + || gwlan_logging.exit)); + + if (ret_wait_status == -ERESTARTSYS) { + pr_err("%s: wait_event_interruptible returned -ERESTARTSYS", + __func__); + break; + } + + if (gwlan_logging.exit) { + pr_err("%s: Exiting the thread\n", __func__); + break; + } + + if (test_and_clear_bit(HOST_LOG_DRIVER_MSG, + &gwlan_logging.eventFlag)) { + ret = send_filled_buffers_to_user(); + if (-ENOMEM == ret) { + msleep(200); + } + } + + if (test_and_clear_bit(HOST_LOG_PER_PKT_STATS, + &gwlan_logging.eventFlag)) { + ret = pktlog_send_per_pkt_stats_to_user(); + if (-ENOMEM == ret) { + msleep(200); + } + } + + if (test_and_clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, + &gwlan_logging.eventFlag)) { + /* Flush bit could have been set while we were mid + * way in the logging thread. So, need to check other + * buffers like log messages, per packet stats again + * to flush any residual data in them + */ + if (gwlan_logging.is_flush_complete == true) { + gwlan_logging.is_flush_complete = false; + send_flush_completion_to_user(); + } else { + gwlan_logging.is_flush_complete = true; + set_bit(HOST_LOG_DRIVER_MSG, + &gwlan_logging.eventFlag); + set_bit(HOST_LOG_PER_PKT_STATS, + &gwlan_logging.eventFlag); + set_bit(HOST_LOG_FW_FLUSH_COMPLETE, + &gwlan_logging.eventFlag); + wake_up_interruptible( + &gwlan_logging.wait_queue); + } + } + } + + pr_info("%s: Terminating\n", __func__); + + complete_and_exit(&gwlan_logging.shutdown_comp, 0); + + return 0; +} + +/* + * Process all the Netlink messages from Logger Socket app in user space + */ +static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb) +{ + tAniNlHdr *wnl; + int radio; + int type; + int ret; + + wnl = (tAniNlHdr *) skb->data; + radio = wnl->radio; + type = wnl->nlh.nlmsg_type; + + if (radio < 0 || radio > ANI_MAX_RADIOS) { + LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, + "%s: invalid radio id [%d]\n", + __func__, radio); + return -EINVAL; + } + + if (gapp_pid != INVALID_PID) { + if (wnl->nlh.nlmsg_pid > gapp_pid) { + gapp_pid = wnl->nlh.nlmsg_pid; + } + + spin_lock_bh(&gwlan_logging.spin_lock); + if (gwlan_logging.pcur_node->filled_length) { + wlan_queue_logmsg_for_app(); + } + spin_unlock_bh(&gwlan_logging.spin_lock); + set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); + } else { + /* This is to set the default levels (WLAN logging + * default values not the VOS trace default) when + * logger app is registered for the first time. + */ + gapp_pid = wnl->nlh.nlmsg_pid; + } + + ret = wlan_send_sock_msg_to_app(&wnl->wmsg, 0, + ANI_NL_MSG_LOG, wnl->nlh.nlmsg_pid); + if (ret < 0) { + LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, + "wlan_send_sock_msg_to_app: failed"); + } + + return ret; +} + +int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf) +{ + int i = 0; + unsigned long irq_flag; + + pr_info("%s: Initalizing FEConsoleLog = %d NumBuff = %d\n", + __func__, log_fe_to_console, num_buf); + + gapp_pid = INVALID_PID; + + gplog_msg = (struct log_msg *) vmalloc( + num_buf * sizeof(struct log_msg)); + if (!gplog_msg) { + pr_err("%s: Could not allocate memory\n", __func__); + return -ENOMEM; + } + + vos_mem_zero(gplog_msg, (num_buf * sizeof(struct log_msg))); + + gwlan_logging.log_fe_to_console = !!log_fe_to_console; + gwlan_logging.num_buf = num_buf; + + spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); + INIT_LIST_HEAD(&gwlan_logging.free_list); + INIT_LIST_HEAD(&gwlan_logging.filled_list); + + for (i = 0; i < num_buf; i++) { + list_add(&gplog_msg[i].node, &gwlan_logging.free_list); + gplog_msg[i].index = i; + } + gwlan_logging.pcur_node = (struct log_msg *) + (gwlan_logging.free_list.next); + list_del_init(gwlan_logging.free_list.next); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); + + init_waitqueue_head(&gwlan_logging.wait_queue); + gwlan_logging.exit = false; + clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); + clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); + init_completion(&gwlan_logging.shutdown_comp); + gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL, + "wlan_logging_thread"); + if (IS_ERR(gwlan_logging.thread)) { + pr_err("%s: Could not Create LogMsg Thread Controller", + __func__); + spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); + vfree(gplog_msg); + gplog_msg = NULL; + gwlan_logging.pcur_node = NULL; + spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); + return -ENOMEM; + } + wake_up_process(gwlan_logging.thread); + gwlan_logging.is_active = true; + gwlan_logging.is_flush_complete = false; + + nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg); + + pr_info("%s: Activated wlan_logging svc\n", __func__); + return 0; +} + +int wlan_logging_sock_deactivate_svc(void) +{ + unsigned long irq_flag; + + if (!gplog_msg) + return 0; + + nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg); + clear_default_logtoapp_log_level(); + gapp_pid = INVALID_PID; + + INIT_COMPLETION(gwlan_logging.shutdown_comp); + gwlan_logging.exit = true; + gwlan_logging.is_active = false; + vos_set_multicast_logging(0); + gwlan_logging.is_flush_complete = false; + clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); + clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); + wait_for_completion(&gwlan_logging.shutdown_comp); + + spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); + vfree(gplog_msg); + gplog_msg = NULL; + gwlan_logging.pcur_node = NULL; + spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); + + pr_info("%s: Deactivate wlan_logging svc\n", __func__); + + return 0; +} + +int wlan_logging_sock_init_svc(void) +{ + spin_lock_init(&gwlan_logging.spin_lock); + gapp_pid = INVALID_PID; + gwlan_logging.pcur_node = NULL; + + return 0; +} + +int wlan_logging_sock_deinit_svc(void) +{ + gwlan_logging.pcur_node = NULL; + gapp_pid = INVALID_PID; + + return 0; +} + +/** + * wlan_logging_set_per_pkt_stats() - This function triggers per packet logging + * + * This function is used to send signal to the logger thread for logging per + * packet stats + * + * Return: None + * + */ +void wlan_logging_set_per_pkt_stats(void) +{ + if (gwlan_logging.is_active == false) + return; + + set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); +} + +/** + * wlan_logging_set_log_level() - Set the logging level + * + * This function is used to set the logging level of host debug messages + * + * Return: None + */ +void wlan_logging_set_log_level(void) +{ + set_default_logtoapp_log_level(); +} + +/* + * wlan_logging_set_fw_flush_complete() - FW log flush completion + * + * This function is used to send signal to the logger thread to indicate + * that the flushing of FW logs is complete by the FW + * + * Return: None + * + */ +void wlan_logging_set_fw_flush_complete(void) +{ + if (gwlan_logging.is_active == false) + return; + + set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); +} +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/src/nlink/wlan_nlink_srv.c b/drivers/staging/qcacld-2.0/CORE/SVC/src/nlink/wlan_nlink_srv.c new file mode 100644 index 000000000000..1ac0bc904e2c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/nlink/wlan_nlink_srv.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* wlan_nlink_srv.c +* +* This file contains the definitions specific to the wlan_nlink_srv +* +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global variables */ +static DEFINE_MUTEX(nl_srv_sem); +static struct sock *nl_srv_sock; +static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS]; + +/* Forward declaration */ +static void nl_srv_rcv (struct sk_buff *sk); +static void nl_srv_rcv_skb (struct sk_buff *skb); +static void nl_srv_rcv_msg (struct sk_buff *skb, struct nlmsghdr *nlh); + +/* + * Initialize the netlink service. + * Netlink service is usable after this. + */ +int nl_srv_init(void) +{ + int retcode = 0; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct netlink_kernel_cfg cfg = { + .groups = WLAN_NLINK_MCAST_GRP_ID, + .input = nl_srv_rcv + }; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_PROTO_FAMILY, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) + THIS_MODULE, +#endif + &cfg); +#else + nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_PROTO_FAMILY, + WLAN_NLINK_MCAST_GRP_ID, nl_srv_rcv, NULL, THIS_MODULE); +#endif + + if (nl_srv_sock != NULL) { + memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler)); + } else { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "NLINK: netlink_kernel_create failed"); + retcode = -ECONNREFUSED; + } + return retcode; +} + +/* + * Deinit the netlink service. + * Netlink service is unusable after this. + */ +#ifdef WLAN_KD_READY_NOTIFIER +void nl_srv_exit(int dst_pid) +#else +void nl_srv_exit(void) +#endif /* WLAN_KD_READY_NOTIFIER */ +{ + netlink_kernel_release(nl_srv_sock); + nl_srv_sock = NULL; +} + +/* + * Register a message handler for a specified module. + * Each module (e.g. WLAN_NL_MSG_BTC )will register a + * handler to handle messages addressed to it. + */ +int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler) +{ + int retcode = 0; + + if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) && + msg_handler != NULL) + { + nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler; + } + else { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: nl_srv_register failed for msg_type %d", msg_type); + retcode = -EINVAL; + } + + return retcode; +} +/* + * Unregister the message handler for a specified module. + */ +int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler) +{ + int retcode = 0; + + if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) && + (nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) + { + nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL; + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: nl_srv_unregister failed for msg_type %d", msg_type); + retcode = -EINVAL; + } + + return retcode; +} + +/* + * Unicast the message to the process in user space identfied + * by the dst-pid + */ +int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag) +{ + int err = 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) + NETLINK_CB(skb).pid = 0; //sender's pid +#else + NETLINK_CB(skb).portid = 0; //sender's pid +#endif + NETLINK_CB(skb).dst_group = 0; //not multicast + + if (nl_srv_sock != NULL) { + err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag); + } else { + dev_kfree_skb(skb); + } + + if (err < 0) + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: netlink_unicast to pid[%d] failed, ret[0x%X]", dst_pid, err); + + return err; +} + +/* + * Broadcast the message. Broadcast will return an error if + * there are no listeners + */ +int nl_srv_bcast(struct sk_buff *skb) +{ + int err = 0; + int flags = GFP_KERNEL; + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) + NETLINK_CB(skb).pid = 0; //sender's pid +#else + NETLINK_CB(skb).portid = 0; //sender's pid +#endif + NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; //destination group + + if (nl_srv_sock != NULL) { + err = netlink_broadcast(nl_srv_sock, skb, 0, WLAN_NLINK_MCAST_GRP_ID, flags); + } else { + dev_kfree_skb(skb); + } + if (err < 0) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: netlink_broadcast failed err = %d", err); + } + return err; +} + +/* + * Processes the Netlink socket input queue. + * Dequeue skb's from the socket input queue and process + * all the netlink messages in that skb, before moving + * to the next skb. + */ +static void nl_srv_rcv (struct sk_buff *sk) +{ + mutex_lock(&nl_srv_sem); + nl_srv_rcv_skb(sk); + mutex_unlock(&nl_srv_sem); +} + +/* + * Each skb could contain multiple Netlink messages. Process all the + * messages in one skb and discard malformed skb's silently. + */ +static void nl_srv_rcv_skb (struct sk_buff *skb) +{ + struct nlmsghdr * nlh; + + while (skb->len >= NLMSG_SPACE(0)) { + u32 rlen; + + nlh = (struct nlmsghdr *)skb->data; + + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "NLINK: Invalid " + "Netlink message: skb[%p], len[%d], nlhdr[%p], nlmsg_len[%d]", + skb, skb->len, nlh, nlh->nlmsg_len); + return; + } + + rlen = NLMSG_ALIGN(nlh->nlmsg_len); + if (rlen > skb->len) + rlen = skb->len; + nl_srv_rcv_msg(skb, nlh); + skb_pull(skb, rlen); + } +} + +/* + * Process a netlink message. + * Each netlink message will have a message of type tAniMsgHdr inside. + */ +static void nl_srv_rcv_msg (struct sk_buff *skb, struct nlmsghdr *nlh) +{ + int type; + + /* Only requests are handled by kernel now */ + if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: Received Invalid NL Req type [%x]", nlh->nlmsg_flags); + return; + } + + type = nlh->nlmsg_type; + + /* Unknown message */ + if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: Received Invalid NL Msg type [%x]", type); + return; + } + + /* + * All the messages must at least carry the tAniMsgHdr + * Drop any message with invalid length + */ + if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: Received NL Msg with invalid len[%x]", nlh->nlmsg_len); + return; + } + + // turn type into dispatch table offset + type -= WLAN_NL_MSG_BASE; + + // dispatch to handler + if (nl_srv_msg_handler[type] != NULL) { + (nl_srv_msg_handler[type])(skb); + } else { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "NLINK: No handler for Netlink Msg [0x%X]", type); + } +} + +/** + * nl_srv_is_initialized() - This function is used check if the netlink + * service is initialized + * + * This function is used check if the netlink service is initialized + * + * Return: Return -EPERM if the service is not initialized + * + */ +int nl_srv_is_initialized() +{ + if (nl_srv_sock) + return 0; + else + return -EPERM; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c b/drivers/staging/qcacld-2.0/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c new file mode 100644 index 000000000000..69e18face235 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** + * wlan_ptt_sock_svc.c + * + ******************************************************************************/ +#ifdef PTT_SOCK_SVC_ENABLE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PTT_SOCK_DEBUG +#ifdef PTT_SOCK_DEBUG +#define PTT_TRACE(level, args...) VOS_TRACE( VOS_MODULE_ID_HDD, level, ## args) +#else +#define PTT_TRACE(level, args...) +#endif +// Global variables +static struct hdd_context_s *pAdapterHandle; + +#ifdef PTT_SOCK_DEBUG_VERBOSE +//Utility function to perform a hex dump +static void ptt_sock_dump_buf(const unsigned char * pbuf, int cnt) +{ + int i; + for (i = 0; i < cnt ; i++) { + if ((i%16)==0) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"\n%p:", pbuf); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO," %02X", *pbuf); + pbuf++; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"\n"); +} +#endif +//Utility function to send a netlink message to an application in user space +int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid) +{ + int err = -1; + int payload_len; + int tot_msg_len; + tAniNlHdr *wnl; + struct sk_buff *skb; + struct nlmsghdr *nlh; + int wmsg_length = be16_to_cpu(wmsg->length); + static int nlmsg_seq; + if (radio < 0 || radio > ANI_MAX_RADIOS) { + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: invalid radio id [%d]\n", + __func__, radio); + return -EINVAL; + } + payload_len = wmsg_length + 4; // 4 extra bytes for the radio idx + tot_msg_len = NLMSG_SPACE(payload_len); + if ((skb = dev_alloc_skb(tot_msg_len)) == NULL) { + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: dev_alloc_skb() failed for msg size[%d]\n", + __func__, tot_msg_len); + return -ENOMEM; + } + nlh = nlmsg_put(skb, pid, nlmsg_seq++, src_mod, payload_len, NLM_F_REQUEST); + if (NULL == nlh) { + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_put() failed for msg size[%d]\n", + __func__, tot_msg_len); + kfree_skb(skb); + return -ENOMEM; + } + wnl = (tAniNlHdr *) nlh; + wnl->radio = radio; + memcpy(&wnl->wmsg, wmsg, wmsg_length); + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Sending Msg Type [0x%X] to pid[%d]\n", + __func__, be16_to_cpu(wmsg->type), pid); +#ifdef PTT_SOCK_DEBUG_VERBOSE + ptt_sock_dump_buf((const unsigned char *)skb->data, skb->len); +#endif + + if (pid != -1) { + err = nl_srv_ucast(skb, pid, MSG_DONTWAIT); + } else { + err = nl_srv_bcast(skb); + } + + return err; +} +/* + * Process tregisteration request and send registration response messages + * to the PTT Socket App in user space + */ +static void ptt_sock_proc_reg_req(tAniHdr *wmsg, int radio) +{ + tAniNlAppRegReq *reg_req; + tAniNlAppRegRsp rspmsg; + reg_req = (tAniNlAppRegReq *)(wmsg + 1); + memset((char *)&rspmsg, 0, sizeof(rspmsg)); + /* send reg response message to the application */ + rspmsg.ret = ANI_NL_MSG_OK; + rspmsg.regReq.type = reg_req->type; + + /* Save the pid */ + pAdapterHandle->ptt_pid = reg_req->pid; + rspmsg.regReq.pid= reg_req->pid; + rspmsg.wniHdr.type = cpu_to_be16(ANI_MSG_APP_REG_RSP); + rspmsg.wniHdr.length = cpu_to_be16(sizeof(rspmsg)); + if (ptt_sock_send_msg_to_app((tAniHdr *)&rspmsg.wniHdr, radio, + ANI_NL_MSG_PUMAC, reg_req->pid) < 0) + { + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Error sending ANI_MSG_APP_REG_RSP to pid[%d]\n", + __func__, reg_req->pid); + } +} +/* + * Process all the messages from the PTT Socket App in user space + */ +static void ptt_proc_pumac_msg(struct sk_buff * skb, tAniHdr *wmsg, int radio) +{ + u16 ani_msg_type = be16_to_cpu(wmsg->type); + switch(ani_msg_type) + { + case ANI_MSG_APP_REG_REQ: + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Received ANI_MSG_APP_REG_REQ [0x%X]\n", + __func__, ani_msg_type); + ptt_sock_proc_reg_req(wmsg, radio); + break; + default: + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Received Unknown Msg Type[0x%X]\n", + __func__, ani_msg_type); + break; + } +} +/* + * Process all the Netlink messages from PTT Socket app in user space + */ +static int ptt_sock_rx_nlink_msg (struct sk_buff * skb) +{ + tAniNlHdr *wnl; + int radio; + int type; + wnl = (tAniNlHdr *) skb->data; + radio = wnl->radio; + type = wnl->nlh.nlmsg_type; + switch (type) { + case ANI_NL_MSG_PUMAC: // Message from the PTT socket APP + PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Received ANI_NL_MSG_PUMAC Msg [0x%X]\n", + __func__, type); + ptt_proc_pumac_msg(skb, &wnl->wmsg, radio); + break; + default: + PTT_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: Unknown NL Msg [0x%X]\n",__func__, type); + break; + } + return 0; +} +int ptt_sock_activate_svc(void *pAdapter) +{ + pAdapterHandle = (struct hdd_context_s*)pAdapter; + pAdapterHandle->ptt_pid = INVALID_PID; + nl_srv_register(ANI_NL_MSG_PUMAC, ptt_sock_rx_nlink_msg); + nl_srv_register(ANI_NL_MSG_PTT, ptt_sock_rx_nlink_msg); + return 0; +} +#endif // PTT_SOCK_SVC_ENABLE diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/common/inc/wlan_qct_sys.h b/drivers/staging/qcacld-2.0/CORE/SYS/common/inc/wlan_qct_sys.h new file mode 100644 index 000000000000..24f8e9e7be88 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/common/inc/wlan_qct_sys.h @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( WLAN_QCT_SYS_H__ ) +#define WLAN_QCT_SYS_H__ + +/**=========================================================================== + + \file wlan_qct_sys.h + + \brief System module API + + ==========================================================================*/ + +/* $HEADER$ */ + +/*--------------------------------------------------------------------------- + Include files + -------------------------------------------------------------------------*/ +#include +#include +#include + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + + /*---------------------------------------------------------------------------- + + \brief sysResponseCback() - SYS async resonse callback + + This is a protype for the callback function that SYS makes to various + modules in the system. + + \param pUserData - user data that is passed to the Callback function + when it is invoked. + + \return Nothing + + \sa sysMcStart(), sysMcThreadProbe(), sysTxThreadProbe() + + --------------------------------------------------------------------------*/ +typedef v_VOID_t ( * sysResponseCback ) ( v_VOID_t *pUserData ); + + + +typedef enum +{ + SYS_MSG_ID_MC_START, + SYS_MSG_ID_MC_THR_PROBE, + SYS_MSG_ID_MC_TIMER, + + SYS_MSG_ID_TX_THR_PROBE, + SYS_MSG_ID_TX_TIMER, + + SYS_MSG_ID_RX_TIMER, + + SYS_MSG_ID_MC_STOP, + SYS_MSG_ID_FTM_RSP, + +} SYS_MSG_ID; + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Function declarations and documenation + -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + \brief sysBuildMessageHeader() - Build / initialize a SYS message header + + This function will initialize the SYS message header with the message type + and any internal fields needed for a new SYS message. This function sets + all but the message body, which is up to the caller to setup based on the + specific message being built. + + \note There are internal / reserved items in a SYS message that must be + set correctly for the message to be recognized as a SYS message by + the SYS message handlers. It is important for every SYS message to + be setup / built / initialized through this function. + + \param sysMsgId - a valid message ID for a SYS message. See the + SYS_MSG_ID enum for all the valid SYS message IDs. + + \param pMsg - pointer to the message structure to be setup. + + \return + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysBuildMessageHeader( SYS_MSG_ID sysMsgId, vos_msg_t *pMsg ); + +/*---------------------------------------------------------------------------- + + \brief sysOpen() - Open (initialize) the SYS module. + + This function opens the SYS modules. All SYS resources are allocated + as a result of this open call. + + \param pVosContext - pointer to the VOS Context (from which all other + context entities can be derived). + + \return VOS_STATUS_SUCCESS - the SYS module is open. All resources needed + for operation of the SYS modules are allocated and initialized. + + VOS_STATUS_E_RESOURCES - the SYS module open failed because needed + system resources are not available. + + VOS_STATUS_E_FAILURE - the SYS module open failed due to some + unknown reason. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysOpen( v_CONTEXT_t pVosContext ); + + +/*---------------------------------------------------------------------------- + + \brief sysMcStart() - start the system Main Controller thread. + + This function starts the SYS (Main Controller) module. Starting this + module triggers the CFG download to the 'legacy' MAC software. + + \param pVosContext - pointer to the VOS Context + + \param userCallback - this is a callback that is called when the SYS + has completed the 'start' funciton. + + \param pUserData - pointer to some user data entity that is passed to + the callback function as a parameter when invoked. + + \return VOS_STATUS_SUCCESS - + + \todo: We have not 'status' on the callback. How do we notify the + callback that there is a failure ? + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysMcStart( v_CONTEXT_t pVosContext, sysResponseCback userCallback, + v_VOID_t *pUserData ); + + +/*---------------------------------------------------------------------------- + + \brief sysStop() - Stop the SYS module. + + This function stops the SYS module. + + \todo: What else do we need to do on sysStop()? + + \param pVosContext - pointer to the VOS Context + + \return VOS_STATUS_SUCCESS - the SYS module is stopped. + + VOS_STATUS_E_FAILURE - the SYS module open failed to stop. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysStop( v_CONTEXT_t pVosContext ); + + +/*---------------------------------------------------------------------------- + + \brief sysClose() - Close the SYS module. + + This function closes the SYS module. All resources allocated during + sysOpen() are free'd and returned to the system. The Sys module is unable + to operate until opened again through a call to sysOpen(). + + \param pVosContext - pointer to the VOS Context + + \return VOS_STATUS_SUCCESS - the SYS module is closed. + + VOS_STATUS_E_FAILURE - the SYS module open failed to close + + \sa sysOpen(), sysMcStart() + + --------------------------------------------------------------------------*/ +VOS_STATUS sysClose( v_CONTEXT_t pVosContext ); + + +/*---------------------------------------------------------------------------- + + \brief sysMcThreadProbe() - Probe the SYS Main Controller thread + + This function is called during initialization to 'probe' the Main Controller + thread. Probing means a specific message is posted to the SYS module to + assure the Main Controller thread is operating and processing messages + correctly. + + Following the successful 'probe' of the Main Controller thread, the + callback specified on this function is called to notify another entity + that the Main Controller is operational. + + \param pVosContext - pointer to the VOS Context + + \param userCallback - this is a callback that is called when the SYS + has completed probing the Main Controller thread. + + \param pUserData - pointer to some user data entity that is passed to + the callback function as a parameter when invoked. + + \return VOS_STATUS_SUCCESS - + \todo: how do we tell the callback there is a failure? + + \sa sysOpen(), sysMcStart() + + --------------------------------------------------------------------------*/ +v_VOID_t sysMcThreadProbe( v_CONTEXT_t pVosContex, sysResponseCback userCallback, + v_VOID_t *pUserData ); + +/*---------------------------------------------------------------------------- + + \brief sysTxThreadProbe() - Probe the Tx thread + + This function is called during initialization to 'probe' the Tx + thread. Probing means a specific message is posted to the SYS module to + assure the Tx is operating and processing messages correctly. + + Following the successful 'probe' of the Tx, the callback specified + on this function is called to notify another entity that the Tx thread + is operational. + + \param pVosContext - pointer to the VOS Context + + \param userCallback - this is a callback that is called when the SYS + has completed probing the Tx thread. + + \param pUserData - pointer to some user data entity that is passed to + the callback function as a parameter when invoked. + + \return VOS_STATUS_SUCCESS - + \todo: how do we tell the callback there is a failure? + + \sa sysOpen(), sysMcStart() + + --------------------------------------------------------------------------*/ +v_VOID_t sysTxThreadProbe( v_CONTEXT_t pVosContex, sysResponseCback userCallback, + v_VOID_t *pUserData ); + +/*---------------------------------------------------------------------------- + + \brief sysMcProcessMsg() - process SYS messages on the Main Controller thread + + This function processes SYS Messages on the Main Controller thread. + SYS messages consist of all 'legacy' messages (messages bound for legacy + modules like LIM, HAL, PE, etc.) as well as newly defined SYS message + types. + + SYS messages are identified by their type (in the SYS_MESSAGES enum) as + well as a 'cookie' that is in the reserved field of the message structure. + This 'cookie' is introduced to prevent any message type/ID conflicts with + the 'legacy' message types. + + Any module attempting to post a message to the SYS module must set the + message type to one of the types in the SYS_MESSAGE enum *and* must also + set the Reserved field in the message body to SYS_MSG_COOKIE. + + \param pVosContext - pointer to the VOS Context + + \param pMsg - pointer to the message to be processed. + + \return - VOS_STATUS_SUCCESS - the message was processed successfully. + + VOS_STATUS_E_BADMSG - a bad (unknown type) message was received + and subsequently not processed. + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysMcProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t* pMsg ); + +/*---------------------------------------------------------------------------- + + \brief sysTxProcessMsg() - process SYS messages on the Tx thread + + This function processes SYS Messages on the Tx thread. + SYS messages consist of all 'legacy' messages (messages bound for legacy + modules like LIM, HAL, PE, etc.) as well as newly defined SYS message + types. + + SYS messages are identified by their type (in the SYS_MESSAGES enum) as + well as a 'cookie' that is in the reserved field of the message structure. + This 'cookie' is introduced to prevent any message type/ID conflicts with + the 'legacy' message types. + + Any module attempting to post a message to the SYS module must set the + message type to one of the types in the SYS_MESSAGE enum *and* must also + set the Reserved field in the message body to SYS_MSG_COOKIE. + + \param pVosContext - pointer to the VOS Context + + \param pMsg - pointer to the message to be processed. + + \return - VOS_STATUS_SUCCESS - the message was processed successfully. + + VOS_STATUS_E_BADMSG - a bad (unknown type) message was received + and subsequently not processed. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysTxProcessMsg( v_CONTEXT_t pVContext, vos_msg_t* pMsg ); + +/*---------------------------------------------------------------------------- + + \brief sysTxProcessMsg() - process SYS messages on the Rx thread + + This function processes SYS Messages on the Rx thread. + SYS messages consist of all 'legacy' messages (messages bound for legacy + modules like LIM, HAL, PE, etc.) as well as newly defined SYS message + types. + + SYS messages are identified by their type (in the SYS_MESSAGES enum) as + well as a 'cookie' that is in the reserved field of the message structure. + This 'cookie' is introduced to prevent any message type/ID conflicts with + the 'legacy' message types. + + Any module attempting to post a message to the SYS module must set the + message type to one of the types in the SYS_MESSAGE enum *and* must also + set the Reserved field in the message body to SYS_MSG_COOKIE. + + \param pVosContext - pointer to the VOS Context + + \param pMsg - pointer to the message to be processed. + + \return - VOS_STATUS_SUCCESS - the message was processed successfully. + + VOS_STATUS_E_BADMSG - a bad (unknown type) message was received + and subsequently not processed. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS sysRxProcessMsg( v_CONTEXT_t pVContext, vos_msg_t* pMsg ); + +/*---------------------------------------------------------------------------- + + \brief sysMcFreeMsg() - free a message queue'd to the Main Controller thread + + This fnction will free a SYS Message that is pending in the main controller + thread queue. These messages are free'd when the message queue needs to be + purged, for example during a Reset of Shutdown of the system. + + \param pVosContext - pointer to the VOS Context + + \param pMsg - the message to be free'd + + \return Nothing. + + --------------------------------------------------------------------------*/ +v_VOID_t sysMcFreeMsg( v_CONTEXT_t pVosContext, vos_msg_t* pMsg ); + +/*---------------------------------------------------------------------------- + + \brief sysTxFreeMsg() - free a message queue'd to the Tx thread + + This fnction will free a SYS Message that is pending in the Tx + thread queue. These messages are free'd when the message queue needs to be + purged, for example during a Reset of Shutdown of the system. + + \param pVosContext - pointer to the VOS Context + + \param pMsg - the message to be free'd + + \return Nothing. + + --------------------------------------------------------------------------*/ +v_VOID_t sysTxFreeMsg( v_CONTEXT_t pVContext, vos_msg_t* pMsg ); + +/*---------------------------------------------------------------------------- + + \brief wlan_sys_ftm() - FTM Cmd Response from halPhy + + This fnction is called by halPhy and carried the FTM command response. + This message is handled by SYS thread and finally the message will be convyed to used space + + + \param pttMsgBuffer - pointer to the pttMsgBuffer + + + \return Nothing. + + --------------------------------------------------------------------------*/ + +void wlan_sys_ftm(void *pMsgPtr); +void wlan_sys_probe(void); + + +#endif // WLAN_QCT_SYS_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/common/src/wlan_qct_sys.c b/drivers/staging/qcacld-2.0/CORE/SYS/common/src/wlan_qct_sys.c new file mode 100644 index 000000000000..875851737f48 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/common/src/wlan_qct_sys.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2012-2013, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + W L A N S Y S T E M M O D U L E + + +DESCRIPTION + This file contains the system module that implements the 'exectution model' + in the Gen6 host software. +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + +when who what, where, why +-------- --- ----------------------------------------------------- +12/15/08 sho Resolved AMSS compiler errors and warnings when this + is being ported from WM +07/02/08 lac Added support for eWNI_SME_START_REQ/RSP in init seq +06/26/08 hba Added implementation of mbReceiveMBMsg() +06/26/08 lac Created module. + +===========================================================================*/ + + +#include +#include + +#include // needed for tSirRetStatus +#include // needed for tSirMbMsg +#include // needed for SIR_... message types +#include // needed for WNI_... message types +#include "aniGlobal.h" +#include "wlan_qct_wda.h" +#include "sme_Api.h" +#include "macInitApi.h" + +VOS_STATUS WLANFTM_McProcessMsg (v_VOID_t *message); + + + +// Cookie for SYS messages. Note that anyone posting a SYS Message has to +// write the COOKIE in the reserved field of the message. The SYS Module +// relies on this COOKIE +#define FTM_SYS_MSG_COOKIE 0xFACE + +#define SYS_MSG_COOKIE ( 0xFACE ) + +/* SYS stop timeout 30 seconds */ +#define SYS_STOP_TIMEOUT (30000) + +// need to define FIELD_OFFSET for non-WM platforms +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(x,y) offsetof(x,y) +#endif + +VOS_STATUS sys_SendSmeStartReq( v_CONTEXT_t pVosContext ); + +// add this to the sys Context data... ? +typedef struct +{ + sysResponseCback mcStartCB; + v_VOID_t * mcStartUserData; + +} sysContextData; + + +static vos_event_t gStopEvt; + +VOS_STATUS sysBuildMessageHeader( SYS_MSG_ID sysMsgId, vos_msg_t *pMsg ) +{ + pMsg->type = sysMsgId; + pMsg->reserved = SYS_MSG_COOKIE; + + return( VOS_STATUS_SUCCESS ); +} + + +VOS_STATUS sysOpen( v_CONTEXT_t pVosContext ) +{ + return( VOS_STATUS_SUCCESS ); +} + + + +v_VOID_t sysStopCompleteCb +( + v_VOID_t *pUserData +) +{ + vos_event_t* pStopEvt = (vos_event_t *) pUserData; + VOS_STATUS vosStatus; +/*-------------------------------------------------------------------------*/ + + vosStatus = vos_event_set( pStopEvt ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS ( vosStatus ) ); + +} /* vos_sys_stop_complete_cback() */ + +VOS_STATUS sysStop( v_CONTEXT_t pVosContext ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + vos_msg_t sysMsg; + + /* Initialize the stop event */ + vosStatus = vos_event_init( &gStopEvt ); + + if(! VOS_IS_STATUS_SUCCESS( vosStatus )) + { + return vosStatus; + } + + /* post a message to SYS module in MC to stop SME and MAC */ + sysBuildMessageHeader( SYS_MSG_ID_MC_STOP, &sysMsg ); + + // Save the user callback and user data + // finished. + sysMsg.callback = sysStopCompleteCb; + sysMsg.bodyptr = (void *) &gStopEvt; + + // post the message.. + vosStatus = vos_mq_post_message( VOS_MQ_ID_SYS, &sysMsg ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + vosStatus = VOS_STATUS_E_BADMSG; + } + + vosStatus = vos_wait_single_event(&gStopEvt, SYS_STOP_TIMEOUT); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS ( vosStatus ) ); + + vosStatus = vos_event_destroy( &gStopEvt ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS ( vosStatus ) ); + + return( vosStatus ); +} + + +VOS_STATUS sysClose( v_CONTEXT_t pVosContext ) +{ + return( VOS_STATUS_SUCCESS ); +} + + + + + + +#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK) +#pragma pack( push ) +#pragma pack( 1 ) +#elif defined(__ANI_COMPILER_PRAGMA_PACK) +#pragma pack( 1 ) +#endif + +typedef struct sPolFileVersion +{ + unsigned char MajorVersion; + unsigned char MinorVersion; + unsigned char Suffix; + unsigned char Build; + +} tPolFileVersion; + + +typedef struct sPolFileHeader +{ + tPolFileVersion FileVersion; + tPolFileVersion HWCapabilities; + unsigned int FileLength; + unsigned int NumDirectoryEntries; + +} tPolFileHeader; + + +typedef enum ePolFileDirTypes +{ + ePOL_DIR_TYPE_BOOTLOADER = 0, + ePOL_DIR_TYPE_STA_FIRMWARE, + ePOL_DIR_TYPE_AP_FIRMWARE, + ePOL_DIR_TYPE_DIAG_FIRMWARE, + ePOL_DIR_TYPE_STA_CONFIG, + ePOL_DIR_TYPE_AP_CONFIG + +} tPolFileDirTypes; + + +typedef struct sPolFileDirEntry +{ + unsigned int DirEntryType; + unsigned int DirEntryFileOffset; + unsigned int DirEntryLength; + +} tPolFileDirEntry; + +#if defined(__ANI_COMPILER_PRAGMA_PACK_STACK) +#pragma pack( pop ) +#endif + + +static unsigned short polFileChkSum( unsigned short *FileData, unsigned long NumWords ) +{ + unsigned long Sum; + + for ( Sum = 0; NumWords > 0; NumWords-- ) + { + Sum += *FileData++; + } + + Sum = (Sum >> 16) + (Sum & 0xffff); // add carry + Sum += (Sum >> 16); // maybe last unsigned short + + return( (unsigned short)( ~Sum ) ); +} + +v_BOOL_t sys_validateStaConfig( void *pImage, unsigned long cbFile, + void **ppStaConfig, v_SIZE_t *pcbStaConfig ) +{ + v_BOOL_t fFound = VOS_FALSE; + tPolFileHeader *pFileHeader = NULL; + tPolFileDirEntry *pDirEntry = NULL; + v_U32_t idx; + + do + { + // Compute the checksum before bothering to copy... + if ( polFileChkSum( ( v_U16_t *)pImage, cbFile / sizeof( v_U16_t ) ) ) + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Failed to validate the checksum for CFG binary" ); + break; + } + + pFileHeader = (tPolFileHeader *)pImage; + + *ppStaConfig = NULL; + *pcbStaConfig = 0; + + pDirEntry = ( tPolFileDirEntry* ) ( pFileHeader + 1 ); + + for ( idx = 0; idx < pFileHeader->NumDirectoryEntries; ++idx ) + { + if ( ePOL_DIR_TYPE_STA_CONFIG == pDirEntry[ idx ].DirEntryType ) + { + *ppStaConfig = pDirEntry[ idx ].DirEntryFileOffset + ( v_U8_t * )pFileHeader; + + *pcbStaConfig = pDirEntry[ idx ].DirEntryLength; + + break; + } + + } // End iteration over the header's entries + + if ( NULL != *ppStaConfig ) + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO_LOW, + "Found the Station CFG in the CFG binary!!" ); + + fFound = VOS_TRUE; + } + else + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Failed to find Station CFG in the CFG binary" ); + } + + } while( 0 ); + + VOS_ASSERT( VOS_TRUE == fFound ); + + return( fFound ); +} + + + + + + + + + + +VOS_STATUS sysMcProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + v_VOID_t *hHal; + + if (NULL == pMsg) + { + VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer to vos_msg_t", __func__); + return VOS_STATUS_E_INVAL; + } + + // All 'new' SYS messages are identified by a cookie in the reserved + // field of the message as well as the message type. This prevents + // the possibility of overlap in the message types defined for new + // SYS messages with the 'legacy' message types. The legacy messages + // will not have this cookie in the reserved field + if ( SYS_MSG_COOKIE == pMsg->reserved ) + { + // Process all the new SYS messages.. + switch( pMsg->type ) + { + case SYS_MSG_ID_MC_START: + { + /* Handling for this message is not needed now so adding + *debug print and VOS_ASSERT*/ + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + " Received SYS_MSG_ID_MC_START message msgType= %d [0x%08x]", + pMsg->type, pMsg->type ); + VOS_ASSERT(0); + break; + } + + case SYS_MSG_ID_MC_STOP: + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Processing SYS MC STOP" ); + + // get the HAL context... + hHal = vos_get_context( VOS_MODULE_ID_PE, pVosContext ); + if (NULL == hHal) + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hHal", __func__ ); + } + else + { + vosStatus = sme_Stop( hHal, HAL_STOP_TYPE_SYS_DEEP_SLEEP); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + + vosStatus = macStop( hHal, HAL_STOP_TYPE_SYS_DEEP_SLEEP ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + + ((sysResponseCback)pMsg->callback)((v_VOID_t *)pMsg->bodyptr); + + vosStatus = VOS_STATUS_SUCCESS; + } + break; + } + + // Process MC thread probe. Just callback to the + // function that is in the message. + case SYS_MSG_ID_MC_THR_PROBE: + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + " Received SYS_MSG_ID_MC_THR_PROBE message msgType = %d [0x%08x]", + pMsg->type, pMsg->type); + break; + } + + case SYS_MSG_ID_MC_TIMER: + { + vos_timer_callback_t timerCB = pMsg->callback; + + if (NULL != timerCB) + { + timerCB(pMsg->bodyptr); + } + break; + } + case SYS_MSG_ID_FTM_RSP: + { + WLANFTM_McProcessMsg((v_VOID_t *)pMsg->bodyptr); + break; + } + + default: + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Unknown message type in sysMcProcessMsg() msgType= %d [0x%08x]", + pMsg->type, pMsg->type ); + break; + } + + } // end switch on message type + + } // end if cookie set + else + { + // Process all 'legacy' messages + switch( pMsg->type ) + { + + default: + { + VOS_ASSERT( 0 ); + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Received SYS message cookie with unidentified " + "MC message type= %d [0x%08X]", pMsg->type, pMsg->type ); + + vosStatus = VOS_STATUS_E_BADMSG; + if (pMsg->bodyptr) + vos_mem_free(pMsg->bodyptr); + break; + } + } // end switch on pMsg->type + } // end else + + return( vosStatus ); +} + + + + +VOS_STATUS sysTxProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + if (NULL == pMsg) + { + VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer to vos_msg_t", __func__); + return VOS_STATUS_E_INVAL; + } + // All 'new' SYS messages are identified by a cookie in the reserved + // field of the message as well as the message type. This prevents + // the possibility of overlap in the message types defined for new + // SYS messages with the 'legacy' message types. The legacy messages + // will not have this cookie in the reserved field + if ( SYS_MSG_COOKIE == pMsg->reserved ) + { + // Process all the new SYS messages.. + switch( pMsg->type ) + { + // Process TX thread probe. Just callback to the + // function that is in the message. + case SYS_MSG_ID_TX_THR_PROBE: + { + /* Handling for this message is not needed now so adding + * debug print and VOS_ASSERT*/ + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + " Received SYS_MSG_ID_TX_THR_PROBE message msgType= %d [0x%08x]", + pMsg->type, pMsg->type ); + VOS_ASSERT(0); + + break; + } + + case SYS_MSG_ID_TX_TIMER: + { + vos_timer_callback_t timerCB = pMsg->callback; + + if (NULL != timerCB) + { + timerCB(pMsg->bodyptr); + } + break; + } + + default: + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Unknown message type in sysTxProcessMsg() msgType= %d [0x%08x]", + pMsg->type, pMsg->type ); + break; + } + + } // end switch on message type + } // end if cookie set + else + { + VOS_ASSERT( 0 ); + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Received SYS message cookie with unidentified TX message " + " type= %d [0x%08X]", pMsg->type, pMsg->type ); + + vosStatus = VOS_STATUS_E_BADMSG; + } // end else + + return( vosStatus ); +} + + +VOS_STATUS sysRxProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + if (NULL == pMsg) + { + VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer to vos_msg_t", __func__); + return VOS_STATUS_E_INVAL; + } + + // All 'new' SYS messages are identified by a cookie in the reserved + // field of the message as well as the message type. This prevents + // the possibility of overlap in the message types defined for new + // SYS messages with the 'legacy' message types. The legacy messages + // will not have this cookie in the reserved field + if ( SYS_MSG_COOKIE == pMsg->reserved ) + { + // Process all the new SYS messages.. + switch( pMsg->type ) + { + case SYS_MSG_ID_RX_TIMER: + { + vos_timer_callback_t timerCB = pMsg->callback; + + if (NULL != timerCB) + { + timerCB(pMsg->bodyptr); + } + break; + } + + default: + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Unknown message type in sysRxProcessMsg() msgType= %d [0x%08x]", + pMsg->type, pMsg->type ); + break; + } + + } // end switch on message type + } // end if cookie set + else + { + VOS_ASSERT( 0 ); + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Received SYS message cookie with unidentified RX message " + " type= %d [0x%08X]", pMsg->type, pMsg->type ); + + vosStatus = VOS_STATUS_E_BADMSG; + } // end else + + return( vosStatus ); +} + + +v_VOID_t sysMcFreeMsg( v_CONTEXT_t pVContext, vos_msg_t* pMsg ) +{ + return; +} + + +v_VOID_t sysTxFreeMsg( v_CONTEXT_t pVContext, vos_msg_t* pMsg ) +{ + return; +} + + +void +SysProcessMmhMsg +( + tpAniSirGlobal pMac, + tSirMsgQ* pMsg +) +{ + VOS_MQ_ID targetMQ = VOS_MQ_ID_SYS; +/*-------------------------------------------------------------------------*/ + /* + ** The body of this pMsg is a tSirMbMsg + ** Contrary to Gen4, we cannot free it here! + ** It is up to the callee to free it + */ + + + if (NULL == pMsg) + { + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "NULL Message Pointer"); + VOS_ASSERT(0); + return; + } + + + switch (pMsg->type) + { + /* + ** Following messages are routed to SYS + */ + case WNI_CFG_DNLD_REQ: + case WNI_CFG_DNLD_CNF: + case WDA_APP_SETUP_NTF: + case WDA_NIC_OPER_NTF: + case WDA_RESET_REQ: + case eWNI_SME_START_RSP: + { + /* Forward this message to the SYS module */ + targetMQ = VOS_MQ_ID_SYS; + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Handling for the Message ID %d is removed in SYS\r\n", + pMsg->type); + + VOS_ASSERT(0); + break; + } + + + /* + ** Following messages are routed to HAL + */ + case WNI_CFG_DNLD_RSP: + case WDA_INIT_START_REQ: + { + /* Forward this message to the HAL module */ + targetMQ = VOS_MQ_ID_WDA; + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Handling for the Message ID %d is removed as there is no HAL \r\n", + pMsg->type); + + VOS_ASSERT(0); + break; + } + + case eWNI_SME_START_REQ: + case WNI_CFG_GET_REQ: + case WNI_CFG_SET_REQ: + case WNI_CFG_SET_REQ_NO_RSP: + case eWNI_SME_SYS_READY_IND: + { + /* Forward this message to the PE module */ + targetMQ = VOS_MQ_ID_PE; + break; + } + + + case WNI_CFG_GET_RSP: + case WNI_CFG_SET_CNF: +/* case eWNI_SME_DISASSOC_RSP: + case eWNI_SME_STA_STAT_RSP: + case eWNI_SME_AGGR_STAT_RSP: + case eWNI_SME_GLOBAL_STAT_RSP: + case eWNI_SME_STAT_SUMM_RSP: + case eWNI_PMC_ENTER_BMPS_RSP: + case eWNI_PMC_EXIT_BMPS_RSP: + case eWNI_PMC_EXIT_BMPS_IND: + case eWNI_PMC_ENTER_IMPS_RSP: + case eWNI_PMC_EXIT_IMPS_RSP: + case eWNI_PMC_ENTER_UAPSD_RSP: + case eWNI_PMC_EXIT_UAPSD_RSP: + case eWNI_PMC_ENTER_WOWL_RSP: + case eWNI_PMC_EXIT_WOWL_RSP: + case eWNI_SME_SWITCH_CHL_REQ: */ //Taken care by the check in default case + { + /* Forward this message to the SME module */ + targetMQ = VOS_MQ_ID_SME; + break; + } + + default: + { + + if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN ) && ( pMsg->type <= eWNI_SME_MSG_TYPES_END ) ) + { + targetMQ = VOS_MQ_ID_SME; + break; + } + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Message of ID %d is not yet handled by SYS\r\n", + pMsg->type); + + VOS_ASSERT(0); + } + + } + + + /* + ** Post now the message to the appropriate module for handling + */ + if(VOS_STATUS_SUCCESS != vos_mq_post_message(targetMQ, (vos_msg_t*)pMsg)) + { + //Caller doesn't allocate memory for the pMsg. It allocate memory for bodyptr + /* free the mem and return */ + if(pMsg->bodyptr) + { + vos_mem_free( pMsg->bodyptr); + } + } + +} /* SysProcessMmhMsg() */ + +/*========================================================================== + FUNCTION WLAN_FTM_SYS_FTM + + DESCRIPTION + Called by VOSS to free a given FTM message on the Main thread when there + are messages pending in the queue when the whole system is been reset. + + DEPENDENCIES + FTM must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to FTM's + control block can be extracted from its context + message: type and content of the message + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_SUCCESS: + + SIDE EFFECTS + NONE +============================================================================*/ + +void wlan_sys_ftm(void *pMsgPtr) +{ + vos_msg_t vosMessage; + + + + vosMessage.reserved = FTM_SYS_MSG_COOKIE; + vosMessage.type = SYS_MSG_ID_FTM_RSP; + vosMessage.bodyptr = pMsgPtr; + + vos_mq_post_message(VOS_MQ_ID_SYS, &vosMessage); + + return; +} + + + +void wlan_sys_probe(void) +{ + vos_msg_t vosMessage; + + vosMessage.reserved = FTM_SYS_MSG_COOKIE; + vosMessage.type = SYS_MSG_ID_MC_THR_PROBE; + vosMessage.bodyptr = NULL; + + vos_mq_post_message(VOS_MQ_ID_SYS, &vosMessage); + + return; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/inc/palApi.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/inc/palApi.h new file mode 100644 index 000000000000..5f8572093411 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/inc/palApi.h @@ -0,0 +1,761 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file palApi.h + + \brief Exports and types for the Platform Abstraction Layer interfaces. + + $Id$This file contains all the interfaces for thge Platform Abstration Layer + functions. It is intended to be included in all modules that are using + the PAL interfaces. + + ========================================================================== */ +#ifndef PALAPI_H__ +#define PALAPI_H__ + +#include "halTypes.h" + +/** + \mainpage Platform Abstraction Layer (PAL) + + \section intro Introduction + + palApi is the Platform Abstration Layer. + + This is the latest attempt to abstract the entire Platform, including the + hardware, chip, OS and Bus into a generic API. We are doing this to give + the MAC the ability to call + generic APIs that will allow the MAC to function in an abstract manner + with any Airgo chipset, on any supported OS (Windows and Linux for now) + across any system bus interface (PCI, PCIe, Cardbus, USB, etc.). + + \todo + - palReadRegister: register read + -# add an Open/Close abstraction to accomodate the PAL before the entire MAC is loaded. + -# Review with Linux folks to see this basic scructure works for them. + -# Figure out how to organize the directory structure + - palMemory: memory read/write + - include async versions of read/write register + - palTx: an abstraction for transmit frames that manages the Td and Tm rings + - palRx: an abstracion for receiving frames from a chip across any of the supported buses + - palInterrupt: abstract the interrupts into the HAL + + + \section impl_notes Implementation Notes + + \subsection subsection_codeStructure Code strucure + + */ + + +/** --------------------------------------------------------------------------- + + \fn palReadRegister + + \brief chip and bus agnostic funtion to read a register value + + \param hHdd - HDD context handle + + \param regAddress - address (offset) of the register to be read from the start + of register space. + + \param pRegValue - pointer to the memory where the register contents are written + + \return eHalStatus - status of the register read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palReadRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 *pRegValue ); + + +/** --------------------------------------------------------------------------- + + \fn palWriteRegister + + \brief chip and bus agnostic funtion to write a register value + + \param hHdd - HDD context handle + + \param regAddress - address (offset) of the register to be read from the start + of register space. + + \param pRegValue - pointer to the value being written into the register + + \return eHalStatus - status of the register read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regValue ); + +/** --------------------------------------------------------------------------- + + \fn palAsyncWriteRegister + + \brief chip and bus agnostic async funtion to write a register value + + \param hHdd - HDD context handle + + \param regAddress - address (offset) of the register to be written from the start + of register space. + + \param regValue - value being written into the register + + \return eHalStatus - status of the register write. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ + +eHalStatus palAsyncWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regValue ); + + +/** --------------------------------------------------------------------------- + + \fn palReadDeviceMemory + + \brief chip and bus agnostic funtion to read memory from the chip + + \param hHdd - HDD context handle + + \param memOffset - address (offset) of the memory from the top of the + memory map (as exposed to the host) where the memory will be read from. + + \param pBuffer - pointer to a buffer where the memory will be placed in host + memory space after retreived from the chip. + + \param numBytes - the number of bytes to be read. + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palReadDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); + +/** --------------------------------------------------------------------------- + + \fn palWriteDeviceMemory + + \brief chip and bus agnostic funtion to write memory to the chip + + \param hHdd - HDD context handle + + \param memOffset - address (offset) of the memory from the top of the on-chip + memory that will be written. + + \param pBuffer - pointer to a buffer that has the source data that will be + written to the chip. + + \param numBytes - the number of bytes to be written. + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palWriteDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); + + +/** --------------------------------------------------------------------------- + + \fn palAllocateMemory + + \brief OS agnostic funtion to allocate host memory. + + \note Host memory that needs to be shared between the host and the + device needs to be allocated with the palAllocateSharedMemory() + and free'd with palFreeSharedMemory() functions. + + \param hHdd - HDD context handle + + \param ppMemory - pointer to a void pointer where the address of the + memory allocated will be placed upon return from this function. + + \param numBytes - the number of bytes to allocate. + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be + returned and no memory will be allocated (the *ppMemory will be NULL so don't + try to use it unless the status returns success). + + -------------------------------------------------------------------------------*/ +#ifndef FEATURE_WLAN_PAL_MEM_DISABLE + +#ifdef MEMORY_DEBUG +#define palAllocateMemory(hHdd, ppMemory, numBytes) palAllocateMemory_debug(hHdd, ppMemory, numBytes, __FILE__, __LINE__) +eHalStatus palAllocateMemory_debug( tHddHandle hHdd, void **ppMemory, tANI_U32 numBytes, char* fileName, tANI_U32 lineNum ); +#else +eHalStatus palAllocateMemory( tHddHandle hHdd, void **ppMemory, tANI_U32 numBytes ); +#endif + + +/** --------------------------------------------------------------------------- + + \fn palFreeMemory + + \brief OS agnostic funtion to free host memory that was allocated with + palAllcoateMemory() calls. + + \note Host memory that needs to be shared between the host and the + device needs to be allocated with the palAllocateSharedMemory() + and free'd with palFreeSharedMemory() functions. + + \param hHdd - HDD context handle + + \param pMemory - pointer to memory that will be free'd. + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be + returned and no memory will be allocated (the *ppMemory will be NULL so don't + try to use it unless the status returns success). + + -------------------------------------------------------------------------------*/ +eHalStatus palFreeMemory( tHddHandle hHdd, void *pMemory ); + + + +/** --------------------------------------------------------------------------- + + \fn palFillMemory + + \brief OS agnostic funtion to fill host memory with a specified byte value + + \param hHdd - HDD context handle + + \param pMemory - pointer to memory that will be filled. + + \param numBytes - the number of bytes to be filled. + + \param fillValue - the byte to be written to fill the memory with. + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be + returned and no memory will be allocated (the *ppMemory will be NULL so don't + try to use it unless the status returns success). + + -------------------------------------------------------------------------------*/ +eHalStatus palFillMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes, tANI_BYTE fillValue ); + +/** --------------------------------------------------------------------------- + + \fn palCopyMemory + + \brief OS agnostic funtion to copy host memory from one location to another + + \param hHdd - HDD context handle + + \param pSrc - pointer to source memory location (to copy from) + + \param pSrc - pointer to destination memory location (to copy to) + + \param numBytes - the number of bytes to be be copied. + + \return eHalStatus - status of the memory copy + + -------------------------------------------------------------------------------*/ +eHalStatus palCopyMemory( tHddHandle hHdd, void *pDst, const void *pSrc, tANI_U32 numBytes ); + +/** --------------------------------------------------------------------------- + + \fn palFillMemory + + \brief OS agnostic funtion to fill host memory with a specified byte value + + \param hHdd - HDD context handle + + \param pMemory - pointer to memory that will be filled. + + \param numBytes - the number of bytes to be filled. + + \param fillValue - the byte to be written to fill the memory with. + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be + returned and no memory will be allocated (the *ppMemory will be NULL so don't + try to use it unless the status returns success). + + -------------------------------------------------------------------------------*/ +ANI_INLINE_FUNCTION +eHalStatus palZeroMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes ) +{ + return( palFillMemory( hHdd, pMemory, numBytes, 0 ) ); +} + + +/** --------------------------------------------------------------------------- + + \fn palEqualMemory + + \brief OS agnostic funtion to compare two pieces of memory, similar to + memcmp function in standard C. + + \param hHdd - HDD context handle + + \param pMemory1 - pointer to one location in memory to compare. + + \param pMemory2 - pointer to second location in memory to compare. + + \param numBytes - the number of bytes to compare. + + \return tANI_BOOLEAN - returns a boolean value that tells if the memory + locations are equal or now equal. + + -------------------------------------------------------------------------------*/ +tANI_BOOLEAN palEqualMemory( tHddHandle hHdd, void *pMemory1, void *pMemory2, tANI_U32 numBytes ); +#endif +/** --------------------------------------------------------------------------- + + \fn palFillDeviceMemory + + \brief OS agnostic funtion to fill device memory with a specified + 32bit value + + \param hHdd - HDD context handle + + \param memOffset - offset of the memory on the device to fill. + + \param numBytes - the number of bytes to be filled. + + \param fillValue - the byte pattern to fill into memory on the device + + \return eHalStatus - status of the register read. Note that this function + can fail. + + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not + a multiple of 4 bytes. + + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a + 4 byte boundary. + + \note return failure if the memOffset is not 32bit aligned and not a + multiple of 4 bytes (the device does not support anything else). + + -------------------------------------------------------------------------------*/ +eHalStatus palFillDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 numBytes, tANI_BYTE fillValue ); + + +/** --------------------------------------------------------------------------- + + \fn palZeroDeviceMemory + + \brief OS agnostic funtion to fill device memory with a specified byte value + + \param hHdd - HDD context handle + + \param memOffset - offset of the memory on the device to fill. + + \param numBytes - the number of bytes to be filled. + + \param fillValue - the 32bit pattern to fill the memory with. + + \return eHalStatus - status of the register read. Note that this function + can fail. + + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not + a multiple of 4 bytes. + + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a + 4 byte boundary. + + \note return failure if the memOffset is not 32bit aligned and not a + multiple of 4 bytes (the device does not support anything else). + + -------------------------------------------------------------------------------*/ +ANI_INLINE_FUNCTION +eHalStatus palZeroDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 numBytes ) +{ + return( palFillDeviceMemory( hHdd, memOffset, numBytes, 0 ) ); +} + +/*---------------------------------------------------------------------------------- + + Allocate a packet for sending through the Tx APIs. + + \param hHdd - HDD context handle + + \param frmType - Frame type + + \param size + + \param data - + + \param ppPacket - + + \return eHalStatus - +----------------------------------------------------------------------------------*/ +eHalStatus palPktAlloc(tHddHandle hHdd, eFrameType frmType, tANI_U16 size, void **data, void **ppPacket) ; + + +// This should return Ssome sort of status..... +void palPktFree( tHddHandle hHdd, eFrameType frmType, void* buf, void *pPacket); + + + +//PAL lock functions +//pHandle -- pointer to a caller allocated tPalSpinLockHandle object +eHalStatus palSpinLockAlloc( tHddHandle hHdd, tPalSpinLockHandle *pHandle ); +//hSpinLock -- a handle returned by palSpinLockAlloc +eHalStatus palSpinLockFree( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ); +//hSpinLock -- a handle returned by palSpinLockAlloc +eHalStatus palSpinLockTake( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ); +//hSpinLock -- a handle returned by palSpinLockAlloc +eHalStatus palSpinLockGive( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ); +//PAL lock functions end + + +//This function send a message to MAC, +//pMsgBuf is a buffer allocated by caller. The actual structure varies base on message type +//The beginning of the buffer can always map to tSirMbMsg +//This function must take care of padding if it is required for the OS +eHalStatus palSendMBMessage(tHddHandle hHdd, void *pBuf); + +extern void palGetUnicastStats(tHddHandle hHdd, tANI_U32 *tx, tANI_U32 *rx); + + +/*---------------------------------------------------------------------------------- + this function is to return a tick count (one tick = ~10ms). It is used to calculate + time difference. + + \param hHdd - HDD context handle + + \return tick count. +----------------------------------------------------------------------------------*/ +tANI_U32 palGetTickCount(tHddHandle hHdd); + +/** --------------------------------------------------------------------------- + + \fn palReadRegMemory + + \brief chip and bus agnostic function to read memory from the PHY register space as memory + i.e. to read more than 4 bytes from the contiguous register space + + \param hHdd - HDD context handle + + \param memOffset - address (offset) of the memory from the top of the + memory map (as exposed to the host) where the memory will be read from. + + \param pBuffer - pointer to a buffer where the memory will be placed in host + memory space after retreived from the chip. + + \param numBytes - the number of bytes to be read. + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palReadRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); + +/** --------------------------------------------------------------------------- + + \fn palAsyncWriteRegMemory + + \brief chip and bus agnostic function to write memory to the PHY register space as memory + i.e. to write more than 4 bytes from the contiguous register space. In USB interface, this + API does the write asynchronously. + + \param hHdd - HDD context handle + + \param memOffset - address (offset) of the memory from the top of the on-chip + memory that will be written. + + \param pBuffer - pointer to a buffer that has the source data that will be + written to the chip. + + \param numBytes - the number of bytes to be written. + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palAsyncWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); + +/** --------------------------------------------------------------------------- + + \fn palWriteRegMemory + \brief chip and bus agnostic function to write memory to the PHY register space as memory + i.e. to write more than 4 bytes from the contiguous register space. The difference from the + above routine is, in USB interface, this routine performs the write synchronously where as + the above routine performs it asynchronously. + + \param hHdd - HDD context handle + + \param memOffset - address (offset) of the memory from the top of the on-chip + memory that will be written. + + \param pBuffer - pointer to a buffer that has the source data that will be + written to the chip. + + \param numBytes - the number of bytes to be written. + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); + + +/** --------------------------------------------------------------------------- + + \fn palWaitRegVal + + \brief is a blocking function which reads the register and waits for the given number of iterations + until the read value matches the waitRegVal. The delay between is perIterWaitInNanoSec(in nanoseconds) + + \param hHdd - HDD context handle + + \param reg - address of the register to be read + + \param mask - mask to be applied for the read value + + \param waitRegVal - expected value from the register after applying the mask. + + \param perIterWaitInNanoSec - delay between the two iterations in nanoseconds + + \param numIter - max number of reads before the timeout + + \param pReadRegVal - the value read from the register + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, + tANI_U32 waitRegVal, tANI_U32 perIterWaitInNanoSec, + tANI_U32 numIter, tANI_U32 *pReadRegVal ); + +/** --------------------------------------------------------------------------- + + \fn palReadModifyWriteReg + + \brief chip and bus agnostic function to read a PHY register apply the given masks(AND and OR masks) + and writes back the new value to the register + + \param hHdd - HDD context handle + + \param reg - address of the register to be modified. + + \param andMask - The value read will be ANDed with this mask + + \parma orMask - The value after applying the andMask will be ORed with this value + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return + a failure. + + -------------------------------------------------------------------------------*/ +eHalStatus palReadModifyWriteReg( tHddHandle hHdd, tANI_U32 reg, tANI_U32 andMask, tANI_U32 orMask ); + +//PAL semaphore functions +eHalStatus palSemaphoreAlloc( tHddHandle hHdd, tPalSemaphoreHandle *pHandle, tANI_S32 count ); +eHalStatus palSemaphoreFree( tHddHandle hHdd, tPalSemaphoreHandle hSemaphore ); +eHalStatus palSemaphoreTake( tHddHandle hHdd, tPalSemaphoreHandle hSemaphore ); +eHalStatus palSemaphoreGive( tHddHandle hHdd, tPalSemaphoreHandle hSemaphore ); +eHalStatus palMutexAlloc( tHddHandle hHdd, tPalSemaphoreHandle *pHandle) ; +eHalStatus palMutexAllocLocked( tHddHandle hHdd, tPalSemaphoreHandle *pHandle) ; + +//PAL irq/softirq +eAniBoolean pal_in_interrupt(void) ; +void pal_local_bh_disable(void) ; +void pal_local_bh_enable(void) ; + +//PAL byte swap +tANI_U32 pal_be32_to_cpu(tANI_U32 x) ; +tANI_U32 pal_cpu_to_be32(tANI_U32 x) ; +tANI_U16 pal_be16_to_cpu(tANI_U16 x) ; +tANI_U16 pal_cpu_to_be16(tANI_U16 x) ; + + +#if defined( ANI_LITTLE_BYTE_ENDIAN ) + +// Need to eliminate these and use the ani_cpu_to_le, etc. macros.... +ANI_INLINE_FUNCTION unsigned long i_htonl( unsigned long ul ) +{ + return( ( ( ul & 0x000000ff ) << 24 ) | + ( ( ul & 0x0000ff00 ) << 8 ) | + ( ( ul & 0x00ff0000 ) >> 8 ) | + ( ( ul & 0xff000000 ) >> 24 ) ); +} + +ANI_INLINE_FUNCTION unsigned short i_htons( unsigned short us ) +{ + return( ( ( us >> 8 ) & 0x00ff ) + ( ( us << 8 ) & 0xff00 ) ); +} + +ANI_INLINE_FUNCTION unsigned short i_ntohs( unsigned short us ) +{ + return( i_htons( us ) ); +} + +ANI_INLINE_FUNCTION unsigned long i_ntohl( unsigned long ul ) +{ + return( i_htonl( ul ) ); +} + +#endif //#if defined( ANI_LITTLE_BYTE_ENDIAN ) + + +/** --------------------------------------------------------------------------- + + \fn pal_set_U32 + + \brief Assign 32-bit unsigned value to a byte array base on CPU's endianness. + + \note Caller must validate the byte array has enough space to hold the vlaue + + \param ptr - Starting address of a byte array + + \param value - The value to assign to the byte array + + \return - The address to the byte after the assignment. This may or may not + be valid. Caller to verify. + + -------------------------------------------------------------------------------*/ +ANI_INLINE_FUNCTION tANI_U8 * pal_set_U32(tANI_U8 *ptr, tANI_U32 value) +{ +#if defined( ANI_BIG_BYTE_ENDIAN ) + *(ptr) = ( tANI_U8 )( value >> 24 ); + *(ptr + 1) = ( tANI_U8 )( value >> 16 ); + *(ptr + 2) = ( tANI_U8 )( value >> 8 ); + *(ptr + 3) = ( tANI_U8 )( value ); +#else + *(ptr + 3) = ( tANI_U8 )( value >> 24 ); + *(ptr + 2) = ( tANI_U8 )( value >> 16 ); + *(ptr + 1) = ( tANI_U8 )( value >> 8 ); + *(ptr) = ( tANI_U8 )( value ); +#endif + + return (ptr + 4); +} + + +/** --------------------------------------------------------------------------- + + \fn pal_set_U16 + + \brief Assign 16-bit unsigned value to a byte array base on CPU's endianness. + + \note Caller must validate the byte array has enough space to hold the vlaue + + \param ptr - Starting address of a byte array + + \param value - The value to assign to the byte array + + \return - The address to the byte after the assignment. This may or may not + be valid. Caller to verify. + + -------------------------------------------------------------------------------*/ +ANI_INLINE_FUNCTION tANI_U8 * pal_set_U16(tANI_U8 *ptr, tANI_U16 value) +{ +#if defined( ANI_BIG_BYTE_ENDIAN ) + *(ptr) = ( tANI_U8 )( value >> 8 ); + *(ptr + 1) = ( tANI_U8 )( value ); +#else + *(ptr + 1) = ( tANI_U8 )( value >> 8 ); + *(ptr) = ( tANI_U8 )( value ); +#endif + + return (ptr + 2); +} + + +/** --------------------------------------------------------------------------- + + \fn pal_get_U16 + + \brief Retrieve a 16-bit unsigned value from a byte array base on CPU's endianness. + + \note Caller must validate the byte array has enough space to hold the vlaue + + \param ptr - Starting address of a byte array + + \param pValue - Pointer to a caller allocated buffer for 16 bit value. Value is to assign + to this location. + + \return - The address to the byte after the assignment. This may or may not + be valid. Caller to verify. + + -------------------------------------------------------------------------------*/ +ANI_INLINE_FUNCTION tANI_U8 * pal_get_U16(tANI_U8 *ptr, tANI_U16 *pValue) +{ +#if defined( ANI_BIG_BYTE_ENDIAN ) + *pValue = (((tANI_U16) (*ptr << 8)) | + ((tANI_U16) (*(ptr+1)))); +#else + *pValue = (((tANI_U16) (*(ptr+1) << 8)) | + ((tANI_U16) (*ptr))); +#endif + + return (ptr + 2); +} + + +/** --------------------------------------------------------------------------- + + \fn pal_get_U32 + + \brief Retrieve a 32-bit unsigned value from a byte array base on CPU's endianness. + + \note Caller must validate the byte array has enough space to hold the vlaue + + \param ptr - Starting address of a byte array + + \param pValue - Pointer to a caller allocated buffer for 32 bit value. Value is to assign + to this location. + + \return - The address to the byte after the assignment. This may or may not + be valid. Caller to verify. + + -------------------------------------------------------------------------------*/ +ANI_INLINE_FUNCTION tANI_U8 * pal_get_U32(tANI_U8 *ptr, tANI_U32 *pValue) +{ +#if defined( ANI_BIG_BYTE_ENDIAN ) + *pValue = ( (tANI_U32)(*(ptr) << 24) | + (tANI_U32)(*(ptr+1) << 16) | + (tANI_U32)(*(ptr+2) << 8) | + (tANI_U32)(*(ptr+3)) ); +#else + *pValue = ( (tANI_U32)(*(ptr+3) << 24) | + (tANI_U32)(*(ptr+2) << 16) | + (tANI_U32)(*(ptr+1) << 8) | + (tANI_U32)(*(ptr)) ); +#endif + + return (ptr + 4); +} + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/src/palApiComm.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/src/palApiComm.c new file mode 100644 index 000000000000..75543da78698 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/pal/src/palApiComm.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include +#include // needed for tSirRetStatus +#include + +#include // needed for tSirMbMsg +#include "wlan_qct_wda.h" +#include "adf_nbuf.h" + +#ifndef FEATURE_WLAN_PAL_MEM_DISABLE + +#ifdef MEMORY_DEBUG +eHalStatus palAllocateMemory_debug( tHddHandle hHdd, void **ppMemory, tANI_U32 numBytes, char* fileName, tANI_U32 lineNum ) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + + *ppMemory = vos_mem_malloc_debug( numBytes, fileName, lineNum ); + + if ( NULL == *ppMemory ) + { + halStatus = eHAL_STATUS_FAILURE; + } + + return( halStatus ); +} +#else +eHalStatus palAllocateMemory( tHddHandle hHdd, void **ppMemory, tANI_U32 numBytes ) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + + *ppMemory = vos_mem_malloc( numBytes ); + + if ( NULL == *ppMemory ) + { + halStatus = eHAL_STATUS_FAILURE; + } + + return( halStatus ); +} +#endif + + +eHalStatus palFreeMemory( tHddHandle hHdd, void *pMemory ) +{ + vos_mem_free( pMemory ); + + return( eHAL_STATUS_SUCCESS ); +} + +eHalStatus palFillMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes, tANI_BYTE fillValue ) +{ + vos_mem_set( pMemory, numBytes, fillValue ); + + return( eHAL_STATUS_SUCCESS ); +} + + +eHalStatus palCopyMemory( tHddHandle hHdd, void *pDst, const void *pSrc, tANI_U32 numBytes ) +{ + vos_mem_copy( pDst, pSrc, numBytes ); + + return( eHAL_STATUS_SUCCESS ); +} + + + +tANI_BOOLEAN palEqualMemory( tHddHandle hHdd, void *pMemory1, void *pMemory2, tANI_U32 numBytes ) +{ + return( vos_mem_compare( pMemory1, pMemory2, numBytes ) ); +} +#endif + +#define TX_PKT_MIN_HEADROOM 64 +eHalStatus palPktAlloc(tHddHandle hHdd, eFrameType frmType, tANI_U16 size, + void **data, void **ppPacket) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + adf_nbuf_t nbuf; + + nbuf = adf_nbuf_alloc(NULL, roundup(size+TX_PKT_MIN_HEADROOM, 4), + TX_PKT_MIN_HEADROOM, + sizeof(tANI_U32), FALSE); + + if (nbuf != NULL) { + adf_nbuf_put_tail(nbuf, size); + adf_nbuf_set_protocol(nbuf, ETH_P_CONTROL); + *ppPacket = nbuf; + *data = adf_nbuf_data(nbuf); + halStatus = eHAL_STATUS_SUCCESS; + } + + return halStatus; +} + +void palPktFree( tHddHandle hHdd, eFrameType frmType, void* buf, void *pPacket) +{ + adf_nbuf_free((adf_nbuf_t)pPacket); +} + +tANI_U32 palGetTickCount(tHddHandle hHdd) +{ + return( vos_timer_get_system_ticks() ); +} + + +tANI_U32 pal_be32_to_cpu(tANI_U32 x) +{ + return( x ); +} + +tANI_U32 pal_cpu_to_be32(tANI_U32 x) +{ + return(( x ) ); +} + +tANI_U16 pal_be16_to_cpu(tANI_U16 x) +{ + return( ( x ) ); +} + +tANI_U16 pal_cpu_to_be16(tANI_U16 x) +{ + return( ( x ) ); +} + + + +eHalStatus palSpinLockAlloc( tHddHandle hHdd, tPalSpinLockHandle *pHandle ) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + VOS_STATUS vosStatus; + vos_lock_t *pLock; + + do + { + pLock = vos_mem_malloc( sizeof( vos_lock_t ) ); + + if ( NULL == pLock ) break; + + vos_mem_set(pLock, sizeof(vos_lock_t), 0); + + vosStatus = vos_lock_init( pLock ); + if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + vos_mem_free( pLock ); + break; + } + + *pHandle = (tPalSpinLockHandle)pLock; + halStatus = eHAL_STATUS_SUCCESS; + + } while( 0 ); + + return( halStatus ); +} + + +eHalStatus palSpinLockFree( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + vos_lock_t *pLock = (vos_lock_t *)hSpinLock; + VOS_STATUS vosStatus; + + vosStatus = vos_lock_destroy( pLock ); + if ( VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + // if we successfully destroy the lock, free + // the memory and indicate success to the caller. + vos_mem_free( pLock ); + + halStatus = eHAL_STATUS_SUCCESS; + } + return( halStatus ); +} + + +eHalStatus palSpinLockTake( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + vos_lock_t *pLock = (vos_lock_t *)hSpinLock; + VOS_STATUS vosStatus; + + vosStatus = vos_lock_acquire( pLock ); + if ( VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + // if successfully acquire the lock, indicate success + // to the caller. + halStatus = eHAL_STATUS_SUCCESS; + } + + return( halStatus ); +} + + + + + +eHalStatus palSpinLockGive( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + vos_lock_t *pLock = (vos_lock_t *)hSpinLock; + VOS_STATUS vosStatus; + + vosStatus = vos_lock_release( pLock ); + if ( VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + // if successfully acquire the lock, indicate success + // to the caller. + halStatus = eHAL_STATUS_SUCCESS; + } + + return( halStatus ); +} + + +// Caller of this function MUST dynamically allocate memory for pBuf +// because this funciton will free the memory. +eHalStatus palSendMBMessage(tHddHandle hHdd, void *pBuf) +{ + eHalStatus halStatus = eHAL_STATUS_FAILURE; + tSirRetStatus sirStatus; + v_CONTEXT_t vosContext; + v_VOID_t *hHal; + + vosContext = vos_get_global_context( VOS_MODULE_ID_HDD, hHdd ); + if (NULL == vosContext) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: invalid vosContext", __func__); + } + else + { + hHal = vos_get_context( VOS_MODULE_ID_SME, vosContext ); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "%s: invalid hHal", __func__); + } + else + { + sirStatus = uMacPostCtrlMsg( hHal, pBuf ); + if ( eSIR_SUCCESS == sirStatus ) + { + halStatus = eHAL_STATUS_SUCCESS; + } + } + } + + vos_mem_free( pBuf ); + + return( halStatus ); +} + + + +//All semophore functions are no-op here +//PAL semaphore functions +//All functions MUST return success. If change needs to be made, please check all callers' logic +eHalStatus palSemaphoreAlloc( tHddHandle hHdd, tPalSemaphoreHandle *pHandle, tANI_S32 count ) +{ + (void)hHdd; + (void)pHandle; + (void)count; + if(pHandle) + { + *pHandle = NULL; + } + + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus palSemaphoreFree( tHddHandle hHdd, tPalSemaphoreHandle hSemaphore ) +{ + (void)hHdd; + (void)hSemaphore; + + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus palSemaphoreTake( tHddHandle hHdd, tPalSemaphoreHandle hSemaphore ) +{ + (void)hHdd; + (void)hSemaphore; + + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus palSemaphoreGive( tHddHandle hHdd, tPalSemaphoreHandle hSemaphore ) +{ + (void)hHdd; + (void)hSemaphore; + + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus palMutexAlloc( tHddHandle hHdd, tPalSemaphoreHandle *pHandle) +{ + (void)hHdd; + (void)pHandle; + + if(pHandle) + { + *pHandle = NULL; + } + return (eHAL_STATUS_SUCCESS); +} + +eHalStatus palMutexAllocLocked( tHddHandle hHdd, tPalSemaphoreHandle *pHandle) +{ + (void)hHdd; + (void)pHandle; + + if(pHandle) + { + *pHandle = NULL; + } + return (eHAL_STATUS_SUCCESS); +} + + +eAniBoolean pal_in_interrupt(void) +{ + return (eANI_BOOLEAN_FALSE); +} + +void pal_local_bh_disable(void) +{ +} + +void pal_local_bh_enable(void) +{ +} diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/inc/VossWrapper.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/inc/VossWrapper.h new file mode 100644 index 000000000000..5ce353040a1d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/inc/VossWrapper.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __VOSS_WRAPPER_H +#define __VOSS_WRAPPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*=========================================================================== + @file VossWrapper.h + + @brief This header file contains the various structure definitions and + function prototypes for the RTOS abstraction layer, implemented for VOSS +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 12/15/08 sho Resolved warnings and errors from AMSS compiler when + this is ported to WM + 11/20/08 sho Renamed this to VossWrapper.h; remove all dependencies + on WM platform and allow this to work on all VOSS enabled + platforms + 06/24/08 tbh Modified the file to remove the dependecy on HDD files as + part of Gen6 bring up process. + 10/29/02 Neelay Das Created file. + +===========================================================================*/ + +/*--------------------------------------------------------------------------- + * Include Files + * ------------------------------------------------------------------------*/ + +#include "sirTypes.h" +#include "sirParams.h" +#include "sysDef.h" +#include "vos_timer.h" +#include "palApi.h" +#include "vos_types.h" +#include "vos_trace.h" +#include "vos_memory.h" + +/* Interlocked Compare Exchange related definitions */ + + + +/* Define basic constants for the ThreadX kernel. */ + +#define TX_NO_WAIT 0 +#define TX_WAIT_FOREVER 0xFFFFFFFFUL +#define TX_AUTO_ACTIVATE 1 +#define TX_NO_ACTIVATE 0 + + + +/* API return values. */ +#define TX_SUCCESS 0x00 +#define TX_QUEUE_FULL 0x01 +// ... +#define TX_NO_INSTANCE 0x0D +// ... +#define TX_TIMER_ERROR 0x15 +#define TX_TICK_ERROR 0x16 +// ... + + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +/* Following macro specifies the number of milliseconds which constitute 1 ThreadX timer tick. Used + for mimicking the ThreadX timer behaviour on VOSS. */ +// Use the same MACRO used by firmware modules to calculate TICKs from mSec +// Mismatch would cause worng timer value to be programmed +#define TX_MSECS_IN_1_TICK SYS_TICK_DUR_MS + +// Signature with which the TX_TIMER struct is initialized, when the timer is created +#define TX_AIRGO_TMR_SIGNATURE 0xDEADBEEF + +#ifdef TIMER_MANAGER +#define tx_timer_create(a, b, c, d, e, f, g) tx_timer_create_intern_debug((v_PVOID_t)pMac, a, b, c, d, e, f, g, __FILE__, __LINE__) +#else +#define tx_timer_create(a, b, c, d, e, f, g) tx_timer_create_intern((v_PVOID_t)pMac, a, b, c, d, e, f, g) +#endif + +/*--------------------------------------------------------------------*/ +/* Timer structure */ +/* This structure is used to implement ThreadX timer facility. Just */ +/* like ThreadX, timer expiration handler executes at the highest */ +/* possible priority level, i.e. DISPATCH_LEVEL. */ +/*--------------------------------------------------------------------*/ +typedef struct TX_TIMER_STRUCT +{ +#ifdef WLAN_DEBUG +#define TIMER_MAX_NAME_LEN 50 + char timerName[TIMER_MAX_NAME_LEN]; +#endif + v_ULONG_t tmrSignature; + v_VOID_t (*pExpireFunc)(v_PVOID_t, tANI_U32); + tANI_U32 expireInput; + v_ULONG_t initScheduleTimeInMsecs; + v_ULONG_t rescheduleTimeInMsecs; + vos_timer_t vosTimer; + + // Pointer to the MAC global structure, which stores the context for the NIC, + // for which this timer is supposed to operate. + v_PVOID_t pMac; + tANI_U8 sessionId; + +} TX_TIMER; + +#define TX_TIMER_VALID(timer) (timer.pMac != 0) + +extern v_ULONG_t tx_time_get(v_VOID_t); +extern v_UINT_t tx_timer_activate(TX_TIMER*); +extern v_UINT_t tx_timer_change(TX_TIMER*, v_ULONG_t, v_ULONG_t); +extern v_UINT_t tx_timer_change_context(TX_TIMER*, tANI_U32); +#ifdef TIMER_MANAGER +extern v_UINT_t tx_timer_create_intern_debug(v_PVOID_t, TX_TIMER*, char *, v_VOID_t(*)(v_PVOID_t, tANI_U32), + tANI_U32, v_ULONG_t, v_ULONG_t, v_ULONG_t, char* fileName, v_U32_t lineNum ); +#else +extern v_UINT_t tx_timer_create_intern(v_PVOID_t, TX_TIMER*, char *, v_VOID_t(*)(v_PVOID_t, tANI_U32), tANI_U32, v_ULONG_t, v_ULONG_t, v_ULONG_t); +#endif +extern v_UINT_t tx_timer_deactivate(TX_TIMER*); +extern v_UINT_t tx_timer_delete(TX_TIMER*); +extern v_BOOL_t tx_timer_running(TX_TIMER*); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/src/VossWrapper.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/src/VossWrapper.c new file mode 100644 index 000000000000..56a5a72e6002 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/platform/src/VossWrapper.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + @file VossWrapper.c + + @brief This source file contains the various function definitions for the + RTOS abstraction layer, implemented for VOSS +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 03/31/09 sho Remove the use of vosTimerIsActive flag as it is not + thread-safe + 02/17/08 sho Fix the timer callback function to work when it is called + after the timer has stopped due to a race condition. + 02/10/08 sho Refactor the TX timer to use VOS timer directly instead + of using VOS utility timer + 12/15/08 sho Resolved errors and warnings from the AMSS compiler when + this is ported from WM + 11/20/08 sho Renamed this to VosWrapper.c; remove all dependencies on + WM platform and allow this to work on all VOSS enabled + platform + 06/24/08 tbh Modified the file to remove the dependecy on HDD files as + part of Gen6 bring up process. + 10/29/02 Neelay Das Created file. + +===========================================================================*/ + +/*--------------------------------------------------------------------------- + * Include Files + * ------------------------------------------------------------------------*/ +#include "VossWrapper.h" + +#ifdef WLAN_DEBUG +#define TIMER_NAME (timer_ptr->timerName) +#else +#define TIMER_NAME "N/A" +#endif + +/**--------------------------------------------------------------------- + * tx_time_get() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return current system time in units of miliseconds + * + */ +v_ULONG_t tx_time_get( void ) +{ + return(vos_timer_get_system_ticks()); + +} //* tx_time_get() + + +/**--------------------------------------------------------------------- + * tx_timer_activate() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +v_UINT_t tx_timer_activate(TX_TIMER *timer_ptr) +{ + VOS_STATUS status; + + // Uncomment the asserts, if the intention is to debug the occurence of the + // following anomalous cnditions. + + // Assert that the timer structure pointer passed, is not NULL + //dbgAssert(NULL != timer_ptr); + + // If the NIC is halting just spoof a successful timer activation, so that all + // the timers can be cleaned up. + + if(NULL == timer_ptr) + return TX_TIMER_ERROR; + + // Put a check for the free builds + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) { + VOS_ASSERT( timer_ptr->tmrSignature == 0 ); + + return TX_TIMER_ERROR; + + } + + // Check for an uninitialized timer + VOS_ASSERT(0 != strlen(TIMER_NAME)); + + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Timer %s being activated\n", TIMER_NAME); + + status = vos_timer_start( &timer_ptr->vosTimer, + timer_ptr->initScheduleTimeInMsecs ); + + if (VOS_STATUS_SUCCESS == status) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Timer %s now activated\n", TIMER_NAME); + return TX_SUCCESS; + } + else if (VOS_STATUS_E_ALREADY == status) + { + // starting timer fails because timer is already started; this is okay + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Timer %s is already running\n", TIMER_NAME); + return TX_SUCCESS; + } + else + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Timer %s fails to activate\n", TIMER_NAME); + return TX_TIMER_ERROR; + } +} /*** tx_timer_activate() ***/ + + +/**--------------------------------------------------------------------- + * tx_timer_change() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +v_UINT_t tx_timer_change(TX_TIMER *timer_ptr, + v_ULONG_t initScheduleTimeInTicks, v_ULONG_t rescheduleTimeInTicks) +{ + // Put a check for the free builds + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) { + VOS_ASSERT( timer_ptr->tmrSignature == 0 ); + + return TX_TIMER_ERROR; + } + + // changes cannot be applied until timer stops running + if (VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&timer_ptr->vosTimer)) + { + timer_ptr->initScheduleTimeInMsecs = TX_MSECS_IN_1_TICK * initScheduleTimeInTicks; + timer_ptr->rescheduleTimeInMsecs = TX_MSECS_IN_1_TICK * rescheduleTimeInTicks; + return TX_SUCCESS; + } + else + { + return TX_TIMER_ERROR; + } +} /*** tx_timer_change() ***/ + +/**--------------------------------------------------------------------- + * tx_timer_change_context() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +v_UINT_t tx_timer_change_context(TX_TIMER *timer_ptr, tANI_U32 expiration_input) +{ + + // Put a check for the free builds + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) { + VOS_ASSERT( timer_ptr->tmrSignature == 0 ); + + return TX_TIMER_ERROR; + } + + // changes cannot be applied until timer stops running + if (VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&timer_ptr->vosTimer)) + { + timer_ptr->expireInput = expiration_input; + return TX_SUCCESS; + } + else + { + return TX_TIMER_ERROR; + } +} /*** tx_timer_change() ***/ + + +/**--------------------------------------------------------------------- + * tx_main_timer_func() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return None. + * + */ +static v_VOID_t tx_main_timer_func( v_PVOID_t functionContext ) +{ + TX_TIMER *timer_ptr = (TX_TIMER *)functionContext; + + + if (NULL == timer_ptr) + { + VOS_ASSERT(0); + return; + } + + + if (NULL == timer_ptr->pExpireFunc) + { + VOS_ASSERT(0); + return; + } + + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Timer %s triggered", TIMER_NAME); + + // Now call the actual timer function, taking the function pointer, + // from the timer structure. + (* timer_ptr->pExpireFunc)( timer_ptr->pMac, timer_ptr->expireInput ); + + // check if this needs to be rescheduled + if (0 != timer_ptr->rescheduleTimeInMsecs) + { + VOS_STATUS status; + status = vos_timer_start( &timer_ptr->vosTimer, + timer_ptr->rescheduleTimeInMsecs ); + timer_ptr->rescheduleTimeInMsecs = 0; + + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_WARN, + "Unable to reschedule timer %s; status=%d", TIMER_NAME, status); + } + } +} /*** tx_timer_change() ***/ + +#ifdef TIMER_MANAGER +v_UINT_t tx_timer_create_intern_debug( v_PVOID_t pMacGlobal, TX_TIMER *timer_ptr, + char *name_ptr, + v_VOID_t ( *expiration_function )( v_PVOID_t, tANI_U32 ), + tANI_U32 expiration_input, v_ULONG_t initScheduleTimeInTicks, + v_ULONG_t rescheduleTimeInTicks, v_ULONG_t auto_activate, + char* fileName, v_U32_t lineNum) +{ + VOS_STATUS status; + + if (NULL == expiration_function) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "NULL timer expiration"); + VOS_ASSERT(0); + return TX_TIMER_ERROR; + } + + if(NULL == name_ptr) + { + + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "NULL name pointer for timer"); + VOS_ASSERT(0); + return TX_TIMER_ERROR; + } + if (!initScheduleTimeInTicks) + return TX_TICK_ERROR; + + if (!timer_ptr) + return TX_TIMER_ERROR; + + // Initialize timer structure + timer_ptr->pExpireFunc = expiration_function; + timer_ptr->expireInput = expiration_input; + timer_ptr->initScheduleTimeInMsecs = + TX_MSECS_IN_1_TICK * initScheduleTimeInTicks; + timer_ptr->rescheduleTimeInMsecs = + TX_MSECS_IN_1_TICK * rescheduleTimeInTicks; + timer_ptr->pMac = pMacGlobal; + + // Set the flag indicating that the timer was created + timer_ptr->tmrSignature = TX_AIRGO_TMR_SIGNATURE; + +#ifdef WLAN_DEBUG + // Store the timer name + strlcpy(timer_ptr->timerName, name_ptr, sizeof(timer_ptr->timerName)); +#endif // Store the timer name, for Debug build only + + status = vos_timer_init_debug( &timer_ptr->vosTimer, VOS_TIMER_TYPE_SW, + tx_main_timer_func, (v_PVOID_t)timer_ptr, fileName, lineNum); + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Cannot create timer for %s\n", TIMER_NAME); + return TX_TIMER_ERROR; + } + + if(0 != rescheduleTimeInTicks) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Creating periodic timer for %s\n", TIMER_NAME); + } + + // Activate this timer if required + if (auto_activate) + { + tx_timer_activate(timer_ptr); + } + + return TX_SUCCESS; + +} //** tx_timer_create() ***/ +#else +v_UINT_t tx_timer_create_intern( v_PVOID_t pMacGlobal, TX_TIMER *timer_ptr, + char *name_ptr, + v_VOID_t ( *expiration_function )( v_PVOID_t, tANI_U32 ), + tANI_U32 expiration_input, v_ULONG_t initScheduleTimeInTicks, + v_ULONG_t rescheduleTimeInTicks, v_ULONG_t auto_activate ) +{ + VOS_STATUS status; + + if((NULL == name_ptr) || (NULL == expiration_function)) + return TX_TIMER_ERROR; + + if (!initScheduleTimeInTicks) + return TX_TICK_ERROR; + + if (!timer_ptr) + return TX_TIMER_ERROR; + + // Initialize timer structure + timer_ptr->pExpireFunc = expiration_function; + timer_ptr->expireInput = expiration_input; + timer_ptr->initScheduleTimeInMsecs = + TX_MSECS_IN_1_TICK * initScheduleTimeInTicks; + timer_ptr->rescheduleTimeInMsecs = + TX_MSECS_IN_1_TICK * rescheduleTimeInTicks; + timer_ptr->pMac = pMacGlobal; + + // Set the flag indicating that the timer was created + timer_ptr->tmrSignature = TX_AIRGO_TMR_SIGNATURE; + +#ifdef WLAN_DEBUG + // Store the timer name + strlcpy(timer_ptr->timerName, name_ptr, sizeof(timer_ptr->timerName)); +#endif // Store the timer name, for Debug build only + + status = vos_timer_init( &timer_ptr->vosTimer, VOS_TIMER_TYPE_SW, + tx_main_timer_func, (v_PVOID_t)timer_ptr ); + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, + "Cannot create timer for %s\n", TIMER_NAME); + return TX_TIMER_ERROR; + } + + if(0 != rescheduleTimeInTicks) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Creating periodic timer for %s\n", TIMER_NAME); + } + + // Activate this timer if required + if (auto_activate) + { + tx_timer_activate(timer_ptr); + } + + return TX_SUCCESS; + +} //** tx_timer_create() ***/ +#endif + + +/**--------------------------------------------------------------------- + * tx_timer_deactivate() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +v_UINT_t tx_timer_deactivate(TX_TIMER *timer_ptr) +{ + VOS_STATUS vStatus; + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "tx_timer_deactivate() called for timer %s\n", TIMER_NAME); + + // Put a check for the free builds + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) + { + return TX_TIMER_ERROR; + } + + // if the timer is not running then we do not need to do anything here + vStatus = vos_timer_stop( &timer_ptr->vosTimer ); + if (VOS_STATUS_SUCCESS != vStatus) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO_HIGH, + "Unable to stop timer %s; status =%d\n", + TIMER_NAME, vStatus); + } + + return TX_SUCCESS; + +} /*** tx_timer_deactivate() ***/ + +v_UINT_t tx_timer_delete( TX_TIMER *timer_ptr ) +{ + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "tx_timer_delete() called for timer %s\n", TIMER_NAME); + + // Put a check for the free builds + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) + { + return TX_TIMER_ERROR; + } + + vos_timer_destroy( &timer_ptr->vosTimer ); + return TX_SUCCESS; +} /*** tx_timer_delete() ***/ + + + +/**--------------------------------------------------------------------- + * tx_timer_running() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +v_BOOL_t tx_timer_running(TX_TIMER *timer_ptr) +{ + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "tx_timer_running() called for timer %s\n", TIMER_NAME); + + // Put a check for the free builds + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) + return VOS_FALSE; + + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState( &timer_ptr->vosTimer )) + { + return VOS_TRUE; + } + return VOS_FALSE; + +} /*** tx_timer_running() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDebug.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDebug.h new file mode 100644 index 000000000000..8cf24f9d9a67 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDebug.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file sysGlobal.h contains the logDump utility for system module. + * Author: V. K. Kandarpa + * Date: 01/24/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __SYS_DEBUG_H__ +#define __SYS_DEBUG_H__ + +#include +# include "utilsApi.h" +# include "sirDebug.h" +# include "sirParams.h" + +void sysLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...); + +#endif // __SYS_DEBUG_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDef.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDef.h new file mode 100644 index 000000000000..97b5b70d8a65 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysDef.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file sysDef.h contains the common definitions used to bring up + * Sirius system. + * Author: V. K. Kandarpa + * Date: 04/13/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#ifndef __SYSDEF_H +#define __SYSDEF_H + +/// Sirius system level definitions +// NOTE: Do not program system timer tick duration to less than 1msec + +/// System timer tick duration in nanoseconds +#define SYS_TICK_DUR_NS 10000000 // 10ms +#define SYS_TICK_TO_MICRO_SECOND 10000 + +/// System timer tick duration in milliseconds +#define SYS_TICK_DUR_MS (SYS_TICK_DUR_NS/1000000) + +/// Clocks in a millisecond +#define SYS_CLOCKS_PER_MS 120000 // 120 MHz + +// In Milliseconds +#define SYS_ADD_BA_RSP_DUR 1000 + +/// System timer tick duration in clocks +#define SYS_TICK_DUR_CLK (SYS_TICK_DUR_MS * SYS_CLOCKS_PER_MS) + +/// Number of timer ticks in a second +#define SYS_TICKS_PER_SECOND (1000/SYS_TICK_DUR_MS) + +/// Macro to convert MS to Ticks +#define SYS_MS_TO_TICKS(x) ((x) / SYS_TICK_DUR_MS) + +/// Macro to convert Seconds to Ticks +#define SYS_SEC_TO_TICKS(x) ((x) * SYS_TICKS_PER_SECOND) + +/// Macro to convert Minutes to Ticks +#define SYS_MIN_TO_TICKS(x) (((x) * 60) * SYS_TICKS_PER_SECOND) + +/// MNT task processing interval in seconds +#define SYS_MNT_INTERVAL 60 + +/// MS to Time Units +#define SYS_MS_TO_TU(x) ((x * 1000) >> 10) + +/// TU to MS +#define SYS_TU_TO_MS(x) ((x << 10) / 1000) + +// --------- End of Windows & RTAI ----------- + +/// Message queue definitions + +/// gHalMsgQ +# define SYS_HAL_Q_SIZE 200 // Holds up to 25 messages + +/// gMMHhiPriorityMsgQ +# define SYS_MMH_HI_PRI_Q_SIZE 200 // Holds up to 25 messages + +/// gMMHprotocolMsgQ +# define SYS_MMH_PROT_Q_SIZE 400 // Holds up to 50 messages + +/// gMMHdebugMsgQ +# define SYS_MMH_DEBUG_Q_SIZE 800 // Holds up to 100 messages + +/// gMAINTmsgQ +# define SYS_MNT_Q_SIZE 200 // Holds up to 25 messages + +/// LIM Message Queue +# define SYS_LIM_Q_SIZE 400 // Holds up to 50 messages + +/// Scheduler Message Queue +# define SYS_SCH_Q_SIZE 800 // Holds up to 25 messages + +/// PMM Message Queue +# define SYS_PMM_Q_SIZE 800 // Holds up to 100 messages + +/// TX Message Queue +# define SYS_TX_Q_SIZE 2048 // Holds up to 400 messages + +/// RX Message Queue +# define SYS_RX_Q_SIZE 2048 // Holds up to 400 messages + +/// PTT Message Queue +# define SYS_NIM_PTT_Q_SIZE 200 // Holds up to 25 messages + +/// Semaphore definitions +// Data Semaphore + +# define SYS_DPH_SEM_INITIAL_CNT 0 + +// Transport Semaphore + +# define SYS_BBT_SEM_INITIAL_CNT 0 + +/// Thread definitions +// tHAL + +# define SYS_HAL_THREAD_ENTRY_FUNCTION halEntry +# define SYS_HAL_STACK_SIZE 8192 +# define SYS_HAL_THREAD_PRIORITY 2 + +// tDPH + +# define SYS_DPH_THREAD_ENTRY_FUNCTION dphEntry +# define SYS_DPH_STACK_SIZE 8192 +# define SYS_DPH_THREAD_PRIORITY 15 + +// tBBT + +# define SYS_BBT_THREAD_ENTRY_FUNCTION bbtEntry +# define SYS_BBT_STACK_SIZE 8192 +# define SYS_BBT_THREAD_PRIORITY 16 + +// tSCH + +# define SYS_SCH_STACK_SIZE 8192 +# define SYS_SCH_THREAD_PRIORITY 17 + +// tPMM + +# define SYS_PMM_STACK_SIZE 8192 +# define SYS_PMM_THREAD_PRIORITY 17 + +// tLIM + +# define SYS_LIM_THREAD_ENTRY_FUNCTION limEntry +# define SYS_LIM_STACK_SIZE 8192 +# define SYS_LIM_THREAD_PRIORITY 18 + +// tMAINT + +# define SYS_MNT_THREAD_ENTRY_FUNCTION mntEntry +# define SYS_MNT_STACK_SIZE 8192 +# define SYS_MNT_THREAD_PRIORITY 25 + +// tMMH + +# define SYS_MMH_THREAD_ENTRY_FUNCTION mmhEntry +# define SYS_MMH_STACK_SIZE 8192 +# define SYS_MMH_THREAD_PRIORITY 10 + +// tNIM_MNT_PKT_GEN + +# define SYS_NIM_PTT_THREAD_STACK_SIZE 8192 +# define SYS_NIM_PTT_THREAD_PRIORITY 28 + +#endif // __SYSDEF_H diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysEntryFunc.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysEntryFunc.h new file mode 100644 index 000000000000..82b06eb50e9c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysEntryFunc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file sysEntryFunc.h contains module entry functions definitions + * Author: V. K. Kandarpa + * Date: 04/13/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef __SYS_ENTRY_FUNC_H +#define __SYS_ENTRY_FUNC_H + +#include "aniGlobal.h" + +extern tSirRetStatus sysInitGlobals(tpAniSirGlobal); +extern void sysBbtEntry(tANI_U32 dummy); +extern void sysSchEntry(tANI_U32 dummy); +extern void sysPmmEntry(tANI_U32 dummy); +extern void sysDphEntry(tANI_U32 dummy); +extern void sysLimEntry(tANI_U32 dummy); +extern void sysMmhEntry(tANI_U32 dummy); +extern void sysMntEntry(tANI_U32 dummy); +extern void sysHalEntry(tANI_U32 dummy); +extern void sysNimPttEntry(tANI_U32 dummy); + +#endif // __SYS_ENTRY_FUNC_H diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysStartup.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysStartup.h new file mode 100644 index 000000000000..4eb50d1f5bcc --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/inc/sysStartup.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * + * sysStartup.h: System startup header file. + * Author: V. K. Kandarpa + * Date: 01/29/2002 + * + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------------- + * + */ + +# ifndef __SYSSTARTUP_H +# define __SYSSTARTUP_H + +#include "sirParams.h" + +/* Defines */ + +/* Function */ + +extern void sysMACCleanup(void *); +extern tSirRetStatus sysBbtProcessMessageCore(struct sAniSirGlobal *, tpSirMsgQ, + tANI_U32, tANI_U32); + + +# endif /* __SYSSTARTUP_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/macInitApi.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/macInitApi.c new file mode 100644 index 000000000000..17205641c5fa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/macInitApi.c @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * macInitApi.c - This file has all the mac level init functions + * for all the defined threads at system level. + * Author: Dinesh Upadhyay + * Date: 04/23/2007 + * History:- + * Date: 04/08/2008 Modified by: Santosh Mandiganal + * Modification Information: Code to allocate and free the memory for DumpTable entry. + * -------------------------------------------------------------------------- + * + */ +/* Standard include files */ +#include "cfgApi.h" // cfgCleanup +#include "limApi.h" // limCleanup +#include "sirTypes.h" +#include "sysDebug.h" +#include "sysEntryFunc.h" +#include "macInitApi.h" +#if defined(ANI_LOGDUMP) +#include "logDump.h" +#endif //#if defined(ANI_LOGDUMP) + +#ifdef TRACE_RECORD +#include "macTrace.h" +#endif + +extern tSirRetStatus halDoCfgInit(tpAniSirGlobal pMac); +extern tSirRetStatus halProcessStartEvent(tpAniSirGlobal pMac); + + + + +tSirRetStatus macReset(tpAniSirGlobal pMac, tANI_U32 rc); + +tSirRetStatus macPreStart(tHalHandle hHal) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + +#if defined(ANI_LOGDUMP) + //logDumpInit must be called before any module starts + logDumpInit(pMac); +#endif //#if defined(ANI_LOGDUMP) + + return eSIR_SUCCESS; +} + +tSirRetStatus macStart(tHalHandle hHal, void* pHalMacStartParams) +{ + tSirRetStatus status = eSIR_SUCCESS; + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + + if (NULL == pMac) + { + VOS_ASSERT(0); + status = eSIR_FAILURE; + return status; + } + + pMac->gDriverType = ((tHalMacStartParameters*)pHalMacStartParams)->driverType; + + sysLog(pMac, LOG2, FL("called\n")); + + do + { + pMac->pResetMsg = vos_mem_malloc(sizeof(tSirMbMsg)); + if ( NULL == pMac->pResetMsg ) + { + sysLog(pMac, LOGE, FL("pMac->pResetMsg is NULL\n")); + status = eSIR_FAILURE; + break; + } + else + { + vos_mem_set(pMac->pResetMsg, sizeof(tSirMbMsg), 0); + } + + if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) { + status = peStart(pMac); + } + + } while(0); + pMac->sys.abort = false; + + return status; +} + + +/** ------------------------------------------------------------- +\fn macStop +\brief this function will be called from HDD to stop MAC. This function will stop all the mac modules. +\ memory with global context will only be initialized not freed here. +\param tHalHandle hHal +\param tHalStopType +\return tSirRetStatus + -------------------------------------------------------------*/ + +tSirRetStatus macStop(tHalHandle hHal, tHalStopType stopType) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + peStop(pMac); + cfgCleanup( pMac ); + // need to free memory if not called in reset context. + // in reset context this memory will be freed by HDD. + if(false == pMac->sys.abort) + { + vos_mem_free(pMac->pResetMsg); + pMac->pResetMsg = NULL; + } + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn macOpen +\brief this function will be called during init. This function is suppose to allocate all the +\ memory with the global context will be allocated here. +\param tHalHandle pHalHandle +\param tHddHandle hHdd +\param tHalOpenParameters* pHalOpenParams +\return tSirRetStatus + -------------------------------------------------------------*/ + +tSirRetStatus macOpen(tHalHandle *pHalHandle, tHddHandle hHdd, tMacOpenParameters *pMacOpenParms) +{ + tpAniSirGlobal p_mac = NULL; + tSirRetStatus status = eSIR_SUCCESS; + uint8_t i =0; + bool mem_alloc_failed = false; + + if(pHalHandle == NULL) + return eSIR_FAILURE; + + /* + * Make sure this adapter is not already opened. (Compare pAdapter pointer in already + * allocated p_mac structures.) + * If it is opened just return pointer to previously allocated p_mac pointer. + * Or should this result in error? + */ + + /* Allocate p_mac */ + p_mac = vos_mem_malloc(sizeof(tAniSirGlobal)); + if (NULL == p_mac) + return eSIR_FAILURE; + + /* Initialize the p_mac structure */ + vos_mem_set(p_mac, sizeof(tAniSirGlobal), 0); + + /* + * Set various global fields of p_mac here + * (Could be platform dependant as some variables in p_mac are platform + * dependant) + */ + p_mac->hHdd = hHdd; + *pHalHandle = (tHalHandle)p_mac; + + { + /* Call various PE (and other layer init here) */ + if (eSIR_SUCCESS != logInit(p_mac)) { + vos_mem_free(p_mac); + return eSIR_FAILURE; + } + + /* Call routine to initialize CFG data structures */ + if (eSIR_SUCCESS != cfgInit(p_mac)) { + vos_mem_free(p_mac); + return eSIR_FAILURE; + } + + sysInitGlobals(p_mac); + } + + /* Set the Powersave Offload Capability to TRUE irrespective of + * INI param as it should be always enabled for qca-cld driver + */ + p_mac->psOffloadEnabled = TRUE; + + p_mac->scan.nextScanID = FIRST_SCAN_ID; + /* FW: 0 to 2047 and Host: 2048 to 4095 */ + p_mac->mgmtSeqNum = WLAN_HOST_SEQ_NUM_MIN-1; + p_mac->first_scan_done = false; + + status = peOpen(p_mac, pMacOpenParms); + + if (eSIR_SUCCESS != status) { + sysLog(p_mac, LOGE, FL("macOpen failure\n")); + vos_mem_free(p_mac); + return status; + } + + for (i=0; idumpTableEntry[i] = vos_mem_malloc(sizeof(tDumpModuleEntry)); + if (NULL == p_mac->dumpTableEntry[i]) + { + mem_alloc_failed = eANI_BOOLEAN_TRUE; + break; + } + else + { + vos_mem_set(p_mac->dumpTableEntry[i], sizeof(tSirMbMsg), 0); + } + } + + if (mem_alloc_failed) + { + while (i>0) + { + i--; + vos_mem_free(p_mac->dumpTableEntry[i]); + } + + peClose(p_mac); + vos_mem_free(p_mac); + return eSIR_FAILURE; + } + + return status; +} + +/** ------------------------------------------------------------- +\fn macClose +\brief this function will be called in shutdown sequence from HDD. All the +\ allocated memory with global context will be freed here. +\param tpAniSirGlobal pMac +\return none + -------------------------------------------------------------*/ + +tSirRetStatus macClose(tHalHandle hHal) +{ + + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + uint8_t i =0; + + if (!pMac) + return eHAL_STATUS_FAILURE; + + peClose(pMac); + pMac->psOffloadEnabled = FALSE; + + /* Call routine to free-up all CFG data structures */ + cfgDeInit(pMac); + + logDeinit(pMac); + + /* Free the DumpTableEntry */ + for(i=0; idumpTableEntry[i]); + } + + // Finally, de-allocate the global MAC datastructure: + vos_mem_free( pMac ); + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- +\fn macReset +\brief this function is called to send Reset message to HDD. Then HDD will start the reset process. +\param tpAniSirGlobal pMac +\param tANI_U32 rc +\return tSirRetStatus. + -------------------------------------------------------------*/ + +tSirRetStatus macReset(tpAniSirGlobal pMac, tANI_U32 rc) +{ + tSirRetStatus status = eSIR_SUCCESS; + sysLog(pMac, LOGE, FL("*************No-op. Need to call WDA reset function \n")); + return status; +} + +// ---------------------------------------------------------------------- +/** + * macSysResetReq + * + * FUNCTION: + * All MAC modules use this interface in case of an exception. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * + * NOTE: + * + * @param tpAniSirGlobal MAC parameters structure + * @param tANI_U32 reset reason code + * @return tANI_U16 - returs the status. + */ + +void +macSysResetReq(tpAniSirGlobal pMac, tANI_U32 rc) +{ + sysLog(pMac, LOGE, FL("Reason Code = 0x%X\n"),rc); + + switch (rc) + { + case eSIR_STOP_BSS: + case eSIR_SME_BSS_RESTART: + case eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF: + case eSIR_CFB_FLAG_STUCK_EXCEPTION: + // FIXME + //macReset(pMac, rc); + break; + + case eSIR_EOF_SOF_EXCEPTION: + case eSIR_BMU_EXCEPTION: + case eSIR_CP_EXCEPTION: + case eSIR_LOW_PDU_EXCEPTION: + case eSIR_USER_TRIG_RESET: + case eSIR_AHB_HANG_EXCEPTION: + default: + macReset(pMac, rc); + break; + + } +} + +// ------------------------------------------------------------- +/** + * macSysResetReqFromHDD + * + * FUNCTION: + * This reset function gets invoked from the HDD to request a reset. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * + * NOTE: + * + * @param tpAniSirGlobal MAC parameters structure + * @return tANI_U16 - returs the status. + */ + +void +macSysResetReqFromHDD(void *pMac, tANI_U32 rc) +{ + macSysResetReq( (tpAniSirGlobal)pMac, rc ); +} diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/sysEntryFunc.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/sysEntryFunc.c new file mode 100644 index 000000000000..c050fd4f4e5c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/system/src/sysEntryFunc.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * sysEntryFunc.cc - This file has all the system level entry functions + * for all the defined threads at system level. + * Author: V. K. Kandarpa + * Date: 01/16/2002 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------------- + * + */ +/* Standard include files */ + +/* Application Specific include files */ +#include "sirCommon.h" +#include "aniGlobal.h" + + +#include "limApi.h" +#include "schApi.h" +#include "utilsApi.h" +#include "pmmApi.h" + +#include "sysDebug.h" +#include "sysDef.h" +#include "sysEntryFunc.h" +#include "sysStartup.h" +#include "limTrace.h" +#include "wlan_qct_wda.h" + +tSirRetStatus +postPTTMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +#include "vos_types.h" +#include "vos_packet.h" + +#define MAX_DEAUTH_ALLOWED 5 +// --------------------------------------------------------------------------- +/** + * sysInitGlobals + * + * FUNCTION: + * Initializes system level global parameters + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param tpAniSirGlobal Sirius software parameter struct pointer + * @return None + */ + +tSirRetStatus +sysInitGlobals(tpAniSirGlobal pMac) +{ + + vos_mem_set((tANI_U8 *) &pMac->sys, sizeof(pMac->sys), 0); + + pMac->sys.gSysEnableScanMode = 1; + pMac->sys.gSysEnableLinkMonitorMode = 0; + schInitGlobals(pMac); + + return eSIR_SUCCESS; +} + +// --------------------------------------------------------------------------- +/** + * sysBbtProcessMessageCore + * + * FUNCTION: + * Process BBT messages + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param tpAniSirGlobal A pointer to MAC params instance + * @param pMsg message pointer + * @param tANI_U32 type + * @param tANI_U32 sub type + * @return None + */ +tSirRetStatus +sysBbtProcessMessageCore(tpAniSirGlobal pMac, tpSirMsgQ pMsg, tANI_U32 type, + tANI_U32 subType) +{ + tANI_U32 framecount; + tSirRetStatus ret; + void* pBd; + tMgmtFrmDropReason dropReason; + vos_pkt_t *pVosPkt = (vos_pkt_t *)pMsg->bodyptr; + VOS_STATUS vosStatus = + WDA_DS_PeekRxPacketInfo( pVosPkt, (v_PVOID_t *)&pBd, VOS_FALSE ); + tANI_U8 sessionId; + tpPESession psessionEntry; + tpSirMacMgmtHdr pMacHdr; + + pMac->sys.gSysBbtReceived++; + + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + goto fail; + } + + PELOG3(sysLog(pMac, LOG3, FL("Rx Mgmt Frame Subtype: %d\n"), subType); + sirDumpBuf(pMac, SIR_SYS_MODULE_ID, LOG3, (tANI_U8 *)WDA_GET_RX_MAC_HEADER(pBd), WDA_GET_RX_MPDU_LEN(pBd)); + sirDumpBuf(pMac, SIR_SYS_MODULE_ID, LOG3, WDA_GET_RX_MPDU_DATA(pBd), WDA_GET_RX_PAYLOAD_LEN(pBd));) + + pMac->sys.gSysFrameCount[type][subType]++; + framecount = pMac->sys.gSysFrameCount[type][subType]; + + if(type == SIR_MAC_MGMT_FRAME) + { + if (VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) + { + pMacHdr = WDA_GET_RX_MAC_HEADER(pBd); + psessionEntry = peFindSessionByBssid(pMac, + pMacHdr->bssId, &sessionId); + if (psessionEntry && + (psessionEntry->pePersona == VOS_STA_SAP_MODE)) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO_HIGH, + FL("CAC timer is running, dropping the mgmt frame")); + goto fail; + } + } + + /* + * Drop beacon frames in deferred state to avoid VOSS run out of + * message wrappers. + */ + if ((subType == SIR_MAC_MGMT_BEACON) && + (!limIsSystemInScanState(pMac)) && + (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) && + !pMac->lim.gLimSystemInScanLearnMode) { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO_HIGH, + FL("dropping received beacon in deffered state")); + goto fail; + } + + dropReason = limIsPktCandidateForDrop(pMac, pBd, subType); + if (dropReason != eMGMT_DROP_NO_DROP) { + PELOG1(limLog(pMac, LOG1, + FL("Mgmt Frame %d being dropped, reason: %d\n"), + subType, dropReason);) + MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_DROP, NO_SESSION, dropReason);) + goto fail; + } + + if (subType == SIR_MAC_MGMT_DEAUTH) + { + tpSirMacMgmtHdr pMacHdr = WDA_GET_RX_MAC_HEADER(pBd); + PELOGE(sysLog( pMac, LOGE, + FL("DEAUTH frame allowed: " + "da: " MAC_ADDRESS_STR ", " + "sa: " MAC_ADDRESS_STR ", " + "bssid: " MAC_ADDRESS_STR ", " + "DEAUTH count so far: %d\n"), + MAC_ADDR_ARRAY(pMacHdr->da), + MAC_ADDR_ARRAY(pMacHdr->sa), + MAC_ADDR_ARRAY(pMacHdr->bssId), + pMac->sys.gSysFrameCount[type][subType] );); + } + if (subType == SIR_MAC_MGMT_DISASSOC) + { + tpSirMacMgmtHdr pMacHdr = WDA_GET_RX_MAC_HEADER(pBd); + PELOGE(sysLog( pMac, LOGE, + FL("DISASSOC frame allowed: " + "da: " MAC_ADDRESS_STR ", " + "sa: " MAC_ADDRESS_STR ", " + "bssid: " MAC_ADDRESS_STR ", " + "DISASSOC count so far: %d\n"), + MAC_ADDR_ARRAY(pMacHdr->da), + MAC_ADDR_ARRAY(pMacHdr->sa), + MAC_ADDR_ARRAY(pMacHdr->bssId), + pMac->sys.gSysFrameCount[type][subType] );); + } + + //Post the message to PE Queue + ret = (tSirRetStatus) limPostMsgApi(pMac, pMsg); + if (ret != eSIR_SUCCESS) + { + /* Print only one debug failure out of 512 failure messages */ + if(pMac->sys.gSysBbtReceived & 0x0200) + sysLog(pMac, LOGE, FL("posting to LIM2 failed, ret %d\n"), ret); + goto fail; + } + pMac->sys.gSysBbtPostedToLim++; + } + else if (type == SIR_MAC_DATA_FRAME) + { +#ifdef FEATURE_WLAN_ESE + PELOGW(sysLog(pMac, LOGW, FL("IAPP Frame...\n"));); + //Post the message to PE Queue + ret = (tSirRetStatus) limPostMsgApi(pMac, pMsg); + if (ret != eSIR_SUCCESS) + { + PELOGE(sysLog(pMac, LOGE, FL("posting to LIM2 failed, ret %d\n"), ret);) + goto fail; + } + pMac->sys.gSysBbtPostedToLim++; +#endif + } + else + { + PELOG3(sysLog(pMac, LOG3, "BBT received Invalid type %d subType %d " + "LIM state %X. BD dump is:\n", + type, subType, limGetSmeState(pMac)); + sirDumpBuf(pMac, SIR_SYS_MODULE_ID, LOG3, + (tANI_U8 *) pBd, WLANHAL_RX_BD_HEADER_SIZE);) + + goto fail; + } + + return eSIR_SUCCESS; + +fail: + + pMac->sys.gSysBbtDropped++; + return eSIR_FAILURE; +} + + +void sysLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) +{ + // Verify against current log level + if ( loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_SYS_MODULE_ID )] ) + return; + else + { + va_list marker; + + va_start( marker, pString ); /* Initialize variable arguments. */ + + logDebug(pMac, SIR_SYS_MODULE_ID, loglevel, pString, marker); + + va_end( marker ); /* Reset variable arguments. */ + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/dot11fdefs.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/dot11fdefs.h new file mode 100644 index 000000000000..aafb8ec5337b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/dot11fdefs.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef DOT11FDEFS_H_82A7B72E_C36C_465D_82A7_139EA5322582 +#define DOT11FDEFS_H_82A7B72E_C36C_465D_82A7_139EA5322582 +/** + * \file dot11fdefs.h + * + * \brief C defines customizing our framesc-generated code + * + * + * + * + * 'framesc' generates code written in terms of a number of macros + * intended for customization. + * + * + */ + +#include "parserApi.h" + +// This controls how the "dot11f" code copies memory +#define DOT11F_MEMCPY(ctx, dst, src, len) \ + vos_mem_copy( ( tANI_U8* )( dst ), ( tANI_U8* )( src ), ( len ) ) + +// This controls how the "dot11f" code compares memory +#define DOT11F_MEMCMP(ctx, lhs, rhs, len) \ + ( ! vos_mem_compare( ( tANI_U8* )( lhs ), ( tANI_U8* )( rhs ), ( len ) ) ) + +# if defined ( DBG ) && ( DBG != 0 ) + +# //define DOT11F_ENABLE_LOGGING +# //define DOT11F_DUMP_FRAMES +# define DOT11F_LOG_GATE ( 4 ) +# define FRAMES_SEV_FOR_FRAME(ctx, sig) \ + ( DOT11F_ASSOCREQUEST == (sig) ? 3 : 5 ) + + #if defined( DOT11F_ENABLE_LOGGING ) + +# define DOT11F_HAVE_LOG_MACROS + +# define FRAMES_LOG0(ctx, sev, fmt) \ + dot11fLog((ctx), (sev), (fmt)); + +# define FRAMES_LOG1(ctx, sev, fmt, p1) \ + dot11fLog((ctx), (sev), (fmt), (p1)); + +# define FRAMES_LOG2(ctx, sev, fmt, p1, p2) \ + dot11fLog((ctx), (sev), (fmt), (p1), (p2)); + +# define FRAMES_LOG3(ctx, sev, fmt, p1, p2, p3) \ + dot11fLog((ctx), (sev), (fmt), (p1), (p2), (p3)); + +# define FRAMES_DUMP(ctx, sev, p, n) \ + sirDumpBuf((pCtx), SIR_DBG_MODULE_ID, (sev), (p), (n)); + + #endif //#if defined( DOT11F_ENABLE_LOGGING ) + +# else + +# undef DOT11F_ENABLE_LOGGING +# undef DOT11F_DUMP_FRAMES +# define DOT11F_LOG_GATE ( 1 ) + +# endif + + +// #define DOT11F_ENABLE_DBG_BREAK ( 1 ) + +// Local Variables: +// fill-column: 72 +// indent-tabs-mode: nil +// show-trailing-whitespace: t +// End: + +#endif // DOT11FDEFS_H_82A7B72E_C36C_465D_82A7_139EA5322582 diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/utilsParser.h b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/utilsParser.h new file mode 100644 index 000000000000..aa2da8544849 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/inc/utilsParser.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * + * This file utilsParser.h contains the utility function protos + * used internally by the parser + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#ifndef __UTILS_PARSE_H__ +#define __UTILS_PARSE_H__ + +#include +#include "sirApi.h" +#include "dot11f.h" +#include "utilsApi.h" + +void ConvertSSID (tpAniSirGlobal, tSirMacSSid*, tDot11fIESSID*); +void ConvertSuppRates (tpAniSirGlobal, tSirMacRateSet*, tDot11fIESuppRates*); +void ConvertFHParams (tpAniSirGlobal, tSirMacFHParamSet*, tDot11fIEFHParamSet*); +void ConvertExtSuppRates (tpAniSirGlobal, tSirMacRateSet*, tDot11fIEExtSuppRates*); +void ConvertQOSCaps (tpAniSirGlobal, tSirMacQosCapabilityIE*, tDot11fIEQOSCapsAp*); +void ConvertQOSCapsStation (tpAniSirGlobal, tSirMacQosCapabilityStaIE*, tDot11fIEQOSCapsStation*); +tSirRetStatus ConvertWPA (tpAniSirGlobal, tSirMacWpaInfo*, tDot11fIEWPA*); +tSirRetStatus ConvertWPAOpaque (tpAniSirGlobal, tSirMacWpaInfo*, tDot11fIEWPAOpaque*); +tSirRetStatus ConvertWAPIOpaque (tpAniSirGlobal, tSirMacWapiInfo*, tDot11fIEWAPIOpaque*); +tSirRetStatus ConvertRSN (tpAniSirGlobal, tSirMacRsnInfo*, tDot11fIERSN*); +tSirRetStatus ConvertRSNOpaque (tpAniSirGlobal, tSirMacRsnInfo*, tDot11fIERSNOpaque*); +void ConvertPowerCaps (tpAniSirGlobal, tSirMacPowerCapabilityIE*, tDot11fIEPowerCaps*); +void ConvertSuppChannels (tpAniSirGlobal, tSirMacSupportedChannelIE*, tDot11fIESuppChannels*); +void ConvertCFParams (tpAniSirGlobal, tSirMacCfParamSet*, tDot11fIECFParams*); +void ConvertTIM (tpAniSirGlobal, tSirMacTim*, tDot11fIETIM*); +void ConvertCountry (tpAniSirGlobal, tSirCountryInformation*, tDot11fIECountry*); +void ConvertWMMParams (tpAniSirGlobal, tSirMacEdcaParamSetIE*, tDot11fIEWMMParams*); +void ConvertERPInfo (tpAniSirGlobal, tSirMacErpInfo*, tDot11fIEERPInfo*); +void ConvertEDCAParam (tpAniSirGlobal, tSirMacEdcaParamSetIE*, tDot11fIEEDCAParamSet*); +void ConvertTSPEC (tpAniSirGlobal, tSirMacTspecIE*, tDot11fIETSPEC*); +tSirRetStatus ConvertTCLAS (tpAniSirGlobal, tSirTclasInfo*, tDot11fIETCLAS*); +void ConvertWMMTSPEC (tpAniSirGlobal, tSirMacTspecIE*, tDot11fIEWMMTSPEC*); +tSirRetStatus ConvertWMMTCLAS (tpAniSirGlobal, tSirTclasInfo*, tDot11fIEWMMTCLAS*); +void ConvertTSDelay (tpAniSirGlobal, tSirMacTsDelayIE*, tDot11fIETSDelay*); +void ConvertSchedule (tpAniSirGlobal, tSirMacScheduleIE*, tDot11fIESchedule*); +void ConvertWMMSchedule (tpAniSirGlobal, tSirMacScheduleIE*, tDot11fIEWMMSchedule*); +tSirRetStatus ConvertWscOpaque (tpAniSirGlobal, tSirAddie*, tDot11fIEWscIEOpaque*); +tSirRetStatus ConvertP2POpaque (tpAniSirGlobal, tSirAddie*, tDot11fIEP2PIEOpaque*); +#ifdef WLAN_FEATURE_WFD +tSirRetStatus ConvertWFDOpaque (tpAniSirGlobal, tSirAddie*, tDot11fIEWFDIEOpaque*); +#endif +void ConvertQosMapsetFrame(tpAniSirGlobal, tSirQosMapSet*, tDot11fIEQosMapSet*); + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c new file mode 100644 index 000000000000..0f542d0c927b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/dot11f.c @@ -0,0 +1,42378 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * \file dot11f.c + * + * \brief Structures, functions & definitions for + * working with 802.11 Frames + * + * + * + * + * This file was automatically generated by 'framesc' + * Tue Sep 29 17:32:33 2015 from the following file(s): + * + * dot11f.frms + * + * PLEASE DON'T EDIT THIS FILE BY HAND! + * + * + */ + +#if !defined ANI_OS_TYPE_OSX && !defined ANI_OS_TYPE_LINUX && !defined ANI_OS_TYPE_ANDROID +#include /* For memcpy */ +#include /* For _vsnprintf */ +#include /* For offsetof */ +#endif + +#include +#include +#include "dot11fdefs.h" +#include "dot11f.h" + +#if defined ( _MSC_VER ) +# pragma warning (disable: 4244) +# pragma warning (disable: 4505) +# pragma warning (disable: 4702) +# pragma warning (disable: 4996) /* ... was declared deprecated */ +#endif /* Microsoft C/C++ */ + +typedef unsigned char tFRAMES_BOOL; +typedef void (*pfnGeneric_t)(void); + +typedef struct sFFDefn { + const char *name; + tANI_U32 offset; + tANI_U16 sig; + tANI_U8 size; +} tFFDefn; + +typedef struct sIEDefn { + tANI_U32 offset; + tANI_U32 presenceOffset; + tANI_U32 countOffset; + const char *name; + tANI_U16 arraybound; + tANI_U16 minSize; + tANI_U16 maxSize; + tANI_U16 sig; + unsigned char oui[5]; + unsigned char noui; + tANI_U8 eid; + tFRAMES_BOOL fMandatory; +} tIEDefn; + +#if !defined(countof) +#define countof(x) ( sizeof( (x) ) / sizeof( (x)[0] ) ) +#endif + +#if ! defined(DOT11F_MEMCPY) +# define DOT11F_MEMCPY(ctx, dst, src, len) \ + memcpy( (dst), (src), (len) ) \ + +#endif + +#if ! defined(DOT11F_MEMCMP) +# define DOT11F_MEMCMP(ctx, lhs, rhs, len) \ + memcmp( (lhs), (rhs), (len) ) \ + +#endif + +#ifndef DOT11F_HAVE_LOG_SEVERITIES +# define FRLOG_OFF ( 0 ) +# define FRLOGP ( 1 ) +# define FRLOGE ( 2 ) +# define FRLOGW ( 3 ) +# define FRLOG1 ( 4 ) +# define FRLOG2 ( 5 ) +# define FRLOG3 ( 6 ) +# define FRLOG4 ( 7 ) +#endif + +#define FRFL(x) x + +#ifdef DOT11F_ENABLE_LOGGING + +#ifndef DOT11F_HAVE_LOG_MACROS + +#include +#include + +#ifndef DOT11F_LOG_GATE +# define DOT11F_LOG_GATE FRLOGW +#endif // DOT11F_LOG_GATE + +#ifdef WIN32 + +#if defined ( _CONSOLE ) || defined ( _WINDOWS ) || defined ( _DLL ) || defined ( _LIB ) +#include +#define DBGPRINT OutputDebugStringA +#else /* Not User mode */ +#define DBGPRINT DbgPrint +#endif /* User mode */ + +static void framesLog(tpAniSirGlobal pCtx, int nSev, + const char *lpszFormat, ...) +{ +#ifdef WLAN_DEBUG + va_list val; + char buffer[1024]; + (void)pCtx; + if ( nSev <= DOT11F_LOG_GATE ) + { + va_start(val, lpszFormat); + _vsnprintf(buffer, 1024, lpszFormat, val); + va_end(val); + DBGPRINT(buffer); + } +#endif +} +static void framesDump(tpAniSirGlobal pCtx, int nSev, tANI_U8 *pBuf, int nBuf) +{ +#ifdef WLAN_DEBUG + char buffer[35]; + int i, offset; + pCtx; + offset = 0; + if ( nSev > DOT11F_LOG_GATE ) return; + for (i = 0; i < nBuf/8; ++i) + { + _snprintf(buffer, 35, "%08x: %02x %02x %02x %02x %02x %02x %02x %02x\n", offset, *pBuf, *(pBuf + 1), *(pBuf + 2), *(pBuf + 3), *(pBuf + 4), *(pBuf + 5), *(pBuf + 6), *(pBuf + 7)); + pBuf += 8; offset += 8; + DBGPRINT(buffer); + } + _snprintf(buffer, 35, "%08x: ", offset); + DBGPRINT(buffer); + for (i = 0; i < nBuf % 8; ++i) + { + _snprintf(buffer, 35, "%02x ", *pBuf); + ++pBuf; + DBGPRINT(buffer); + } + DBGPRINT("\n"); +#endif +} + +#elif defined OS_X /* Not WIN32 */ +static void framesLog(tpAniSirGlobal pCtx, int nSev, + const char *lpszFormat, ...) +{// To fill in when needed using IOLog + +} + +static void framesDump(tpAniSirGlobal pCtx, int nSev, tANI_U8 *pBuf, int nBuf) +{ +} + +#elif defined LINUX + +static void framesLog(tpAniSirGlobal pCtx, int nSev, + const char *lpszFormat, ...) +{ +#ifdef WLAN_DEBUG + va_list marker; + (void)pCtx; + if ( nSev <= DOT11F_LOG_GATE ) + { + va_start( marker, lpszFormat ); + vprintf(lpszFormat, marker); + va_end( marker ); + } +#endif +} + +static void framesDump(tpAniSirGlobal pCtx, int nSev, tANI_U8 *pBuf, int nBuf) +{ +#ifdef WLAN_DEBUG + char buffer[35]; + int i, offset; + (void)pCtx; + offset = 0; + if ( nSev > DOT11F_LOG_GATE ) return; + for (i = 0; i < nBuf/8; ++i) + { + printf("%08x: %02x %02x %02x %02x %02x %02x %02x %02x\n", offset, *pBuf, *(pBuf + 1), *(pBuf + 2), *(pBuf + 3), *(pBuf + 4), *(pBuf + 5), *(pBuf + 6), *(pBuf + 7)); + pBuf += 8; offset += 8; + } + printf("%08x: ", offset); + for (i = 0; i < nBuf % 8; ++i) + { + printf("%02x ", *pBuf); + ++pBuf; + } + printf("\n"); +#endif +} + +#endif /* WIN32 */ + +#define FRAMES_LOG0(ctx, sev, fmt) \ + framesLog((ctx), (sev), (fmt)); +#define FRAMES_LOG1(ctx, sev, fmt, p1) \ + framesLog((ctx), (sev), (fmt), (p1)); +#define FRAMES_LOG2(ctx, sev, fmt, p1, p2) \ + framesLog((ctx), (sev), (fmt), (p1), (p2)); +#define FRAMES_LOG3(ctx, sev, fmt, p1, p2, p3) \ + framesLog((ctx), (sev), (fmt), (p1), (p2), (p3)); +#define FRAMES_DUMP(ctx, sev, p, n) \ + framesDump((ctx), (sev), (p), (n)); +#ifndef FRAMES_SEV_FOR_FRAME +# define FRAMES_SEV_FOR_FRAME(ctx, sig) FRLOG3 +#endif + +#endif /* End DOT11F_HAVE_LOG_MACROS */ + +#else // ! DOT11F_ENABLE_LOGGING +# define FRAMES_LOG0(ctx, sev, fmt) +# define FRAMES_LOG1(ctx, sev, fmt, p1) +# define FRAMES_LOG2(ctx, sev, fmt, p1, p2) +# define FRAMES_LOG3(ctx, sev, fmt, p1, p2, p3) +# define FRAMES_DUMP(ctx, sev, p, n) +# ifndef FRAMES_SEV_FOR_FRAME +# define FRAMES_SEV_FOR_FRAME(ctx, sig) FRLOG3 +# endif +#endif // DOT11F_ENABLE_LOGGING + +#if defined( DOT11F_ENABLE_DBG_BREAK ) && defined ( WIN32 ) +# define FRAMES_DBG_BREAK() { _asm int 3 } +#else +# define FRAMES_DBG_BREAK() +#endif + +#if ! defined(DOT11F_PARAMETER_CHECK) +# if defined (DOT11F_HAVE_WIN32_API) + +# define DOT11F_PARAMETER_CHECK(pBuf, nBuf, pFrm, nFrm) \ + if (!pBuf || IsBadReadPtr(pBuf, nBuf)) return DOT11F_BAD_INPUT_BUFFER; \ + if (!pFrm || IsBadWritePtr(pFrm, nFrm)) return DOT11F_BAD_OUTPUT_BUFFER \ + +# define DOT11F_PARAMETER_CHECK2(pSrc, pBuf, nBuf, pnConsumed) \ + if (!pSrc || IsBadReadPtr(pSrc, 4)) return DOT11F_BAD_INPUT_BUFFER; \ + if (!pBuf || IsBadWritePtr(pBuf, nBuf)) return DOT11F_BAD_OUTPUT_BUFFER; \ + if (!nBuf) return DOT11F_BAD_OUTPUT_BUFFER; \ + if (IsBadWritePtr(pnConsumed, 4)) return DOT11F_BAD_OUTPUT_BUFFER \ + +# else + +# define DOT11F_PARAMETER_CHECK(pBuf, nBuf, pFrm, nFrm) \ + if (!pBuf) return DOT11F_BAD_INPUT_BUFFER; \ + if (!pFrm) return DOT11F_BAD_OUTPUT_BUFFER \ + +# define DOT11F_PARAMETER_CHECK2(pSrc, pBuf, nBuf, pnConsumed) \ + if (!pSrc) return DOT11F_BAD_INPUT_BUFFER; \ + if (!pBuf) return DOT11F_BAD_OUTPUT_BUFFER; \ + if (!nBuf) return DOT11F_BAD_OUTPUT_BUFFER; \ + if (!pnConsumed) return DOT11F_BAD_OUTPUT_BUFFER \ + +# endif +#endif + +static void framesntohs(tpAniSirGlobal pCtx, + tANI_U16 *pOut, + tANI_U8 *pIn, + tFRAMES_BOOL fMsb) +{ + (void)pCtx; +# if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + if ( !fMsb ) + { + DOT11F_MEMCPY(pCtx, ( tANI_U16* )pOut, pIn, 2); + } + else + { + *pOut = ( tANI_U16 )( *pIn << 8 ) | *( pIn + 1 ); + } +# else + if ( !fMsb ) + { + *pOut = ( tANI_U16 )( *pIn | ( *( pIn + 1 ) << 8 ) ); + } + else + { + DOT11F_MEMCPY(pCtx, ( tANI_U16* )pOut, pIn, 2); + } +# endif +} + +static void framesntohl(tpAniSirGlobal pCtx, + tANI_U32 *pOut, + tANI_U8 *pIn, + tFRAMES_BOOL fMsb) +{ + (void)pCtx; +# if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + if ( !fMsb ) + { + DOT11F_MEMCPY(pCtx, ( tANI_U32* )pOut, pIn, 4); + } + else + { + *pOut = ( tANI_U32 )( *pIn << 24 ) | + ( *( pIn + 1 ) << 16 ) | + ( *( pIn + 2 ) << 8 ) | + ( *( pIn + 3 ) ); + } +# else + if ( !fMsb ) + { + *pOut = ( tANI_U32 )( *( pIn + 3 ) << 24 ) | + ( *( pIn + 2 ) << 16 ) | + ( *( pIn + 1 ) << 8 ) | + ( *( pIn ) ); + } + else + { + *pOut = * ( tANI_U32* )pIn; + } +# endif +} + +static void framesntohq(tpAniSirGlobal pCtx, + tDOT11F_U64 *pOut, + tANI_U8 *pIn, + tFRAMES_BOOL fMsb) +{ +# if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + framesntohl( pCtx, &((*pOut)[0]), pIn, fMsb); + framesntohl( pCtx, &((*pOut)[1]), pIn + 4, fMsb); +# else + framesntohl( pCtx, &((*pOut)[1]), pIn, fMsb); + framesntohl( pCtx, &((*pOut)[0]), pIn + 4, fMsb); +# endif +} + +static void frameshtons(tpAniSirGlobal pCtx +, tANI_U8 *pOut, + tANI_U16 pIn, + tFRAMES_BOOL fMsb) +{ + (void)pCtx; +# if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + if ( !fMsb ) + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 2); + } + else + { + *pOut = ( pIn & 0xff00 ) >> 8; + *( pOut + 1 ) = pIn & 0xff; + } +# else + if ( !fMsb ) + { + *pOut = pIn & 0xff; + *( pOut + 1 ) = ( pIn & 0xff00 ) >> 8; + } + else + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 2); + } +# endif +} + +static void frameshtonl(tpAniSirGlobal pCtx, + tANI_U8 *pOut, + tANI_U32 pIn, + tFRAMES_BOOL fMsb) +{ + (void)pCtx; +# if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + if ( !fMsb ) + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 4); + } + else + { + *pOut = ( pIn & 0xff000000 ) >> 24; + *( pOut + 1 ) = ( pIn & 0x00ff0000 ) >> 16; + *( pOut + 2 ) = ( pIn & 0x0000ff00 ) >> 8; + *( pOut + 3 ) = ( pIn & 0x000000ff ); + } +# else + if ( !fMsb ) + { + *( pOut ) = ( pIn & 0x000000ff ); + *( pOut + 1 ) = ( pIn & 0x0000ff00 ) >> 8; + *( pOut + 2 ) = ( pIn & 0x00ff0000 ) >> 16; + *( pOut + 3 ) = ( pIn & 0xff000000 ) >> 24; + } + else + { + DOT11F_MEMCPY(pCtx, pOut, &pIn, 4); + } +# endif +} + +static void frameshtonq(tpAniSirGlobal pCtx, + tANI_U8 *pOut, + tDOT11F_U64 pIn, + tFRAMES_BOOL fMsb) +{ +# if defined ( DOT11F_LITTLE_ENDIAN_HOST ) + frameshtonl( pCtx, pOut, pIn[0], fMsb); + frameshtonl( pCtx, pOut + 4, pIn[1], fMsb); +# else + frameshtonl( pCtx, pOut + 4, pIn[1], fMsb); + frameshtonl( pCtx, pOut, pIn[0], fMsb); +# endif +} +static const tIEDefn* FindIEDefn(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + const tIEDefn IEs[]) +{ + const tIEDefn *pIe; + + (void)pCtx; + + pIe = &(IEs[0]); + while (0xff != pIe->eid) + { + if (*pBuf == pIe->eid) + { + if (0 == pIe->noui) return pIe; + + if ( ( nBuf > (tANI_U32)(pIe->noui + 2) ) && + ( !DOT11F_MEMCMP(pCtx, pBuf + 2, pIe->oui, pIe->noui) ) ) + return pIe; + } + + ++pIe; + } + + return NULL; +} + +static tANI_U32 GetContainerIesLen(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U8 *pnConsumed, + const tIEDefn IEs[]) +{ + const tIEDefn *pIe, *pIeFirst; + tANI_U8 *pBufRemaining = pBuf; + tANI_U8 len = 0; + + (void)pCtx; + + pIeFirst = &(IEs[0]); + + if( *pBufRemaining != pIeFirst->eid ) + return DOT11F_INTERNAL_ERROR; + len += *(pBufRemaining+1); + pBufRemaining += len + 2; + len += 2; + while ( len < nBuf ) + { + if( NULL == (pIe = FindIEDefn(pCtx, pBufRemaining, nBuf + len, IEs))) + break; + if( pIe->eid == pIeFirst->eid ) + break; + len += *(pBufRemaining + 1) + 2; + pBufRemaining += *(pBufRemaining + 1) + 2; + } + + *pnConsumed = len; + return DOT11F_PARSE_SUCCESS; + +} + + + +static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + const tFFDefn FFs[], + const tIEDefn IEs[], + tANI_U8 *pFrm, + size_t nFrm); +static tANI_U32 PackCore(tpAniSirGlobal pCtx, + tANI_U8 *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed, + const tFFDefn FFs[], + const tIEDefn IEs[]); +static tANI_U32 GetPackedSizeCore(tpAniSirGlobal pCtx, + tANI_U8 *pFrm, + tANI_U32 *pnNeeded, + const tIEDefn IEs[]); + + +tANI_U32 dot11fUnpackTlvCommonFunc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tANI_U8 *pDstPresent, tANI_U8 *pDstField) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)tlvlen; /* Shutup the compiler */ + + *pDstPresent = 1; + *pDstField = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvCommonFunc. */ + +tANI_U32 dot11fUnpackTlvCommonFunc2(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tANI_U8 *pDstPresent, tANI_U16 *pDstState) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)tlvlen; /* Shutup the compiler */ + + *pDstPresent = 1; + framesntohs(pCtx, pDstState, pBuf, 1); + (void)pCtx; + return status; + +} /* End dot11fUnpackTlvCommonFunc2. */ + +void dot11fUnpackFfCommonFunc(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, tANI_U16 *pDstField) +{ + framesntohs(pCtx, pDstField, pBuf, 0); + (void)pCtx; +} /* End dot11fUnpackFfCommonFunc. */ + +tANI_U32 dot11fUnpackIeCommonFunc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, + tANI_U8 *pDstPresent , tANI_U8 *pDstField) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)ielen; + (void)pBuf; + if ((*pDstPresent)) status = DOT11F_DUPLICATE_IE; + *pDstPresent = 1; + *pDstField = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeComonFunc. */ +typedef struct sTLVDefn { + tANI_U32 offset; + tANI_U32 presenceOffset; + const char * name; + tANI_U16 sig; + tANI_U32 id; + tANI_U32 pec; + tANI_U32 minSize; + tANI_U32 maxSize; + tANI_U8 fMandatory; + tANI_U8 sType; + tANI_U8 sLen; + tANI_U8 fMsb; +} tTLVDefn; + +static const tTLVDefn* FindTLVDefn( tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + const tTLVDefn TLVs[ ] ) +{ + const tTLVDefn *pTlv; + tANI_U32 pec; + tANI_U16 id; + + pTlv = &( TLVs[ 0 ] ); + (void)pCtx; + if ( pTlv->sType == 2 ) + framesntohs( pCtx, &id, pBuf, 1 ); + else + id = *pBuf; + + while ( 0xffff != pTlv->id ) + { + if ( id == pTlv->id ) + { + if ( 0 == pTlv->pec ) return pTlv; + + if( nBuf > 5 ) + { + pec = ( ( * ( pBuf + 4 ) ) << 16 ) | + ( ( * ( pBuf + 5 ) ) << 8 ) | + * ( pBuf + 6 ); + if ( pec == pTlv->pec ) + { + return pTlv; + } + } + } + + ++pTlv; + } + + return NULL; +} + +static tANI_U32 UnpackTlvCore( tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + const tTLVDefn TLVs[ ], + tANI_U8 *pFrm, + size_t nFrm ); +static tANI_U32 PackTlvCore(tpAniSirGlobal pCtx, + tANI_U8 *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed, + const tTLVDefn TLVs[], + tANI_U32 *pidx); +static tANI_U32 GetPackedSizeTlvCore(tpAniSirGlobal pCtx, + tANI_U8 *pFrm, + tANI_U32 *pnNeeded, + const tTLVDefn TLVs[]); + +#define SigFfAID ( 0x0001 ) + +void dot11fUnpackFfAction(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfAction *pDst) +{ + pDst->action = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfAction. */ + +#define SigFfAction ( 0x0002 ) + +void dot11fUnpackFfAddBAParameterSet(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfAddBAParameterSet *pDst) +{ + tANI_U16 tmp0__; + framesntohs(pCtx, &tmp0__, pBuf, 0); + pDst->amsduSupported = tmp0__ >> 0 & 0x1; + pDst->policy = tmp0__ >> 1 & 0x1; + pDst->tid = tmp0__ >> 2 & 0xf; + pDst->bufferSize = tmp0__ >> 6 & 0x3ff; + (void)pCtx; +} /* End dot11fUnpackFfAddBAParameterSet. */ + +#define SigFfAddBAParameterSet ( 0x0003 ) + +#define SigFfAuthAlgo ( 0x0004 ) + +#define SigFfAuthSeqNo ( 0x0005 ) + +void dot11fUnpackFfBAStartingSequenceControl(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfBAStartingSequenceControl *pDst) +{ + tANI_U16 tmp1__; + framesntohs(pCtx, &tmp1__, pBuf, 0); + pDst->fragNumber = tmp1__ >> 0 & 0xf; + pDst->ssn = tmp1__ >> 4 & 0xfff; + (void)pCtx; +} /* End dot11fUnpackFfBAStartingSequenceControl. */ + +#define SigFfBAStartingSequenceControl ( 0x0006 ) + +#define SigFfBATimeout ( 0x0007 ) + +#define SigFfBeaconInterval ( 0x0008 ) + +void dot11fUnpackFfCapabilities(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfCapabilities *pDst) +{ + tANI_U16 tmp2__; + framesntohs(pCtx, &tmp2__, pBuf, 0); + pDst->ess = tmp2__ >> 0 & 0x1; + pDst->ibss = tmp2__ >> 1 & 0x1; + pDst->cfPollable = tmp2__ >> 2 & 0x1; + pDst->cfPollReq = tmp2__ >> 3 & 0x1; + pDst->privacy = tmp2__ >> 4 & 0x1; + pDst->shortPreamble = tmp2__ >> 5 & 0x1; + pDst->pbcc = tmp2__ >> 6 & 0x1; + pDst->channelAgility = tmp2__ >> 7 & 0x1; + pDst->spectrumMgt = tmp2__ >> 8 & 0x1; + pDst->qos = tmp2__ >> 9 & 0x1; + pDst->shortSlotTime = tmp2__ >> 10 & 0x1; + pDst->apsd = tmp2__ >> 11 & 0x1; + pDst->rrm = tmp2__ >> 12 & 0x1; + pDst->dsssOfdm = tmp2__ >> 13 & 0x1; + pDst->delayedBA = tmp2__ >> 14 & 0x1; + pDst->immediateBA = tmp2__ >> 15 & 0x1; + (void)pCtx; +} /* End dot11fUnpackFfCapabilities. */ + +#define SigFfCapabilities ( 0x0009 ) + +void dot11fUnpackFfCategory(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfCategory *pDst) +{ + pDst->category = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfCategory. */ + +#define SigFfCategory ( 0x000a ) + +void dot11fUnpackFfCurrentAPAddress(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfCurrentAPAddress *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->mac, pBuf, 6); + (void)pCtx; +} /* End dot11fUnpackFfCurrentAPAddress. */ + +#define SigFfCurrentAPAddress ( 0x000b ) + +void dot11fUnpackFfDelBAParameterSet(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfDelBAParameterSet *pDst) +{ + tANI_U16 tmp3__; + framesntohs(pCtx, &tmp3__, pBuf, 0); + pDst->reserved = tmp3__ >> 0 & 0x7ff; + pDst->initiator = tmp3__ >> 11 & 0x1; + pDst->tid = tmp3__ >> 12 & 0xf; + (void)pCtx; +} /* End dot11fUnpackFfDelBAParameterSet. */ + +#define SigFfDelBAParameterSet ( 0x000c ) + +void dot11fUnpackFfDialogToken(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfDialogToken *pDst) +{ + pDst->token = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfDialogToken. */ + +#define SigFfDialogToken ( 0x000d ) + +void dot11fUnpackFfLinkMargin(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfLinkMargin *pDst) +{ + pDst->linkMargin = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfLinkMargin. */ + +#define SigFfLinkMargin ( 0x000e ) + +#define SigFfListenInterval ( 0x000f ) + +void dot11fUnpackFfMaxTxPower(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfMaxTxPower *pDst) +{ + pDst->maxTxPower = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfMaxTxPower. */ + +#define SigFfMaxTxPower ( 0x0010 ) + +void dot11fUnpackFfNumOfRepetitions(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfNumOfRepetitions *pDst) +{ + framesntohs(pCtx, &pDst->repetitions, pBuf, 0); + (void)pCtx; +} /* End dot11fUnpackFfNumOfRepetitions. */ + +#define SigFfNumOfRepetitions ( 0x0011 ) + +void dot11fUnpackFfOperatingMode(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfOperatingMode *pDst) +{ + tANI_U8 tmp4__; + tmp4__ = *pBuf; + pDst->chanWidth = tmp4__ >> 0 & 0x3; + pDst->reserved = tmp4__ >> 2 & 0x3; + pDst->rxNSS = tmp4__ >> 4 & 0x7; + pDst->rxNSSType = tmp4__ >> 7 & 0x1; + (void)pCtx; +} /* End dot11fUnpackFfOperatingMode. */ + +#define SigFfOperatingMode ( 0x0012 ) + +void dot11fUnpackFfP2POUI(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfP2POUI *pDst) +{ + framesntohl(pCtx, &pDst->oui, pBuf, 0); + (void)pCtx; +} /* End dot11fUnpackFfP2POUI. */ + +#define SigFfP2POUI ( 0x0013 ) + +void dot11fUnpackFfP2POUISubType(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfP2POUISubType *pDst) +{ + pDst->ouiSubtype = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfP2POUISubType. */ + +#define SigFfP2POUISubType ( 0x0014 ) + +void dot11fUnpackFfRCPI(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfRCPI *pDst) +{ + pDst->rcpi = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfRCPI. */ + +#define SigFfRCPI ( 0x0015 ) + +void dot11fUnpackFfRSNI(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfRSNI *pDst) +{ + pDst->rsni = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfRSNI. */ + +#define SigFfRSNI ( 0x0016 ) + +#define SigFfReason ( 0x0017 ) + +void dot11fUnpackFfRxAntennaId(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfRxAntennaId *pDst) +{ + pDst->antennaId = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfRxAntennaId. */ + +#define SigFfRxAntennaId ( 0x0018 ) + +void dot11fUnpackFfSMPowerModeSet(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfSMPowerModeSet *pDst) +{ + tANI_U8 tmp5__; + tmp5__ = *pBuf; + pDst->PowerSave_En = tmp5__ >> 0 & 0x1; + pDst->Mode = tmp5__ >> 1 & 0x1; + pDst->reserved = tmp5__ >> 2 & 0x3f; + (void)pCtx; +} /* End dot11fUnpackFfSMPowerModeSet. */ + +#define SigFfSMPowerModeSet ( 0x0019 ) + +#define SigFfStatus ( 0x001a ) + +void dot11fUnpackFfStatusCode(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfStatusCode *pDst) +{ + pDst->statusCode = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfStatusCode. */ + +#define SigFfStatusCode ( 0x001b ) + +void dot11fUnpackFfTPCEleID(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTPCEleID *pDst) +{ + pDst->TPCId = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfTPCEleID. */ + +#define SigFfTPCEleID ( 0x001c ) + +void dot11fUnpackFfTPCEleLen(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTPCEleLen *pDst) +{ + pDst->TPCLen = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfTPCEleLen. */ + +#define SigFfTPCEleLen ( 0x001d ) + +void dot11fUnpackFfTSInfo(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTSInfo *pDst) +{ + tANI_U32 tmp6__; + framesntohl(pCtx, &tmp6__, pBuf, 0); + pDst->traffic_type = tmp6__ >> 0 & 0x1; + pDst->tsid = tmp6__ >> 1 & 0xf; + pDst->direction = tmp6__ >> 5 & 0x3; + pDst->access_policy = tmp6__ >> 7 & 0x3; + pDst->aggregation = tmp6__ >> 9 & 0x1; + pDst->psb = tmp6__ >> 10 & 0x1; + pDst->user_priority = tmp6__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp6__ >> 14 & 0x3; + pDst->schedule = tmp6__ >> 16 & 0x1; + pDst->unused = tmp6__ >> 17 & 0x7fff; + (void)pCtx; +} /* End dot11fUnpackFfTSInfo. */ + +#define SigFfTSInfo ( 0x001e ) + +void dot11fUnpackFfTimeStamp(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTimeStamp *pDst) +{ + framesntohq(pCtx, &pDst->timestamp, pBuf, 0); + (void)pCtx; +} /* End dot11fUnpackFfTimeStamp. */ + +#define SigFfTimeStamp ( 0x001f ) + +void dot11fUnpackFfTransactionId(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTransactionId *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->transId, pBuf, 2); + (void)pCtx; +} /* End dot11fUnpackFfTransactionId. */ + +#define SigFfTransactionId ( 0x0020 ) + +void dot11fUnpackFfTxAntennaId(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTxAntennaId *pDst) +{ + pDst->antennaId = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfTxAntennaId. */ + +#define SigFfTxAntennaId ( 0x0021 ) + +void dot11fUnpackFfTxPower(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfTxPower *pDst) +{ + pDst->txPower = *pBuf; + (void)pCtx; +} /* End dot11fUnpackFfTxPower. */ + +#define SigFfTxPower ( 0x0022 ) + +void dot11fUnpackFfVhtMembershipStatusArray(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfVhtMembershipStatusArray *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->membershipStatusArray, pBuf, 8); + (void)pCtx; +} /* End dot11fUnpackFfVhtMembershipStatusArray. */ + +#define SigFfVhtMembershipStatusArray ( 0x0023 ) + +void dot11fUnpackFfVhtUserPositionArray(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfVhtUserPositionArray *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->userPositionArray, pBuf, 16); + (void)pCtx; +} /* End dot11fUnpackFfVhtUserPositionArray. */ + +#define SigFfVhtUserPositionArray ( 0x0024 ) + +void dot11fUnpackFfext_chan_switch_ann_action(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tDot11fFfext_chan_switch_ann_action *pDst) +{ + tANI_U32 tmp7__; + framesntohl(pCtx, &tmp7__, pBuf, 0); + pDst->switch_mode = tmp7__ >> 0 & 0xff; + pDst->op_class = tmp7__ >> 8 & 0xff; + pDst->new_channel = tmp7__ >> 16 & 0xff; + pDst->switch_count = tmp7__ >> 24 & 0xff; + (void)pCtx; +} /* End dot11fUnpackFfext_chan_switch_ann_action. */ + +#define SigFfext_chan_switch_ann_action ( 0x0025 ) + +tANI_U32 dot11fUnpackTlvAuthorizedMACs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVAuthorizedMACs *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->mac, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvAuthorizedMACs. */ + +#define SigTlvAuthorizedMACs ( 0x0001 ) + + +#define SigTlvRequestToEnroll ( 0x0002 ) + + +tANI_U32 dot11fUnpackTlvVersion2(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVVersion2 *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp8__; + pDst->present = 1; + tmp8__ = *pBuf; + pBuf += 1; + tlvlen -= 1; + pDst->minor = tmp8__ >> 0 & 0xf; + pDst->major = tmp8__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvVersion2. */ + +#define SigTlvVersion2 ( 0x0003 ) + + +#define SigTlvAPSetupLocked ( 0x0004 ) + + +#define SigTlvAssociationState ( 0x0005 ) + + +tANI_U32 dot11fUnpackTlvChannelList(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVChannelList *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->countryString, pBuf, 3); + pBuf += 3; + tlvlen -= (tANI_U8)3; + pDst->num_channelList = (tANI_U8)( tlvlen ); + if (tlvlen > 251){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->channelList, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvChannelList. */ + +#define SigTlvChannelList ( 0x0006 ) + + +#define SigTlvConfigMethods ( 0x0007 ) + + +#define SigTlvConfigurationError ( 0x0008 ) + + +tANI_U32 dot11fUnpackTlvConfigurationTimeout(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVConfigurationTimeout *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->GOConfigTimeout = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + pDst->CLConfigTimeout = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvConfigurationTimeout. */ + +#define SigTlvConfigurationTimeout ( 0x0009 ) + + +tANI_U32 dot11fUnpackTlvDeviceName(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVDeviceName *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (tANI_U8)( tlvlen ); + if (tlvlen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->text, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvDeviceName. */ + +#define SigTlvDeviceName ( 0x000a ) + + +#define SigTlvDevicePasswordID ( 0x000b ) + + +tANI_U32 dot11fUnpackTlvExtendedListenTiming(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVExtendedListenTiming *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + framesntohs(pCtx, &pDst->availibilityPeriod, pBuf, 0); + pBuf += 2; + tlvlen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->availibilityInterval, pBuf, 0); + pBuf += 2; + tlvlen -= (tANI_U8)2; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvExtendedListenTiming. */ + +#define SigTlvExtendedListenTiming ( 0x000c ) + + +#define SigTlvGOIntent ( 0x000d ) + + +tANI_U32 dot11fUnpackTlvIntendedP2PInterfaceAddress(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVIntendedP2PInterfaceAddress *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PInterfaceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvIntendedP2PInterfaceAddress. */ + +#define SigTlvIntendedP2PInterfaceAddress ( 0x000e ) + + +#define SigTlvInvitationFlags ( 0x000f ) + + +tANI_U32 dot11fUnpackTlvListenChannel(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVListenChannel *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->countryString, pBuf, 3); + pBuf += 3; + tlvlen -= (tANI_U8)3; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + pDst->channel = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvListenChannel. */ + +#define SigTlvListenChannel ( 0x0010 ) + + +tANI_U32 dot11fUnpackTlvManufacturer(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVManufacturer *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_name = (tANI_U8)( tlvlen ); + if (tlvlen > 64){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->name, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvManufacturer. */ + +#define SigTlvManufacturer ( 0x0011 ) + + +#define SigTlvMinorReasonCode ( 0x0012 ) + + +tANI_U32 dot11fUnpackTlvModelName(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVModelName *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (tANI_U8)( tlvlen ); + if (tlvlen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->text, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvModelName. */ + +#define SigTlvModelName ( 0x0013 ) + + +tANI_U32 dot11fUnpackTlvModelNumber(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVModelNumber *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (tANI_U8)( tlvlen ); + if (tlvlen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->text, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvModelNumber. */ + +#define SigTlvModelNumber ( 0x0014 ) + + +tANI_U32 dot11fUnpackTlvNoticeOfAbsence(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVNoticeOfAbsence *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->index = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + pDst->CTSWindowOppPS = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + pDst->num_NoADesc = (tANI_U8)( tlvlen ); + if (tlvlen > 36){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->NoADesc, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvNoticeOfAbsence. */ + +#define SigTlvNoticeOfAbsence ( 0x0015 ) + + +tANI_U32 dot11fUnpackTlvOperatingChannel(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVOperatingChannel *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->countryString, pBuf, 3); + pBuf += 3; + tlvlen -= (tANI_U8)3; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + pDst->channel = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvOperatingChannel. */ + +#define SigTlvOperatingChannel ( 0x0016 ) + + +tANI_U32 dot11fUnpackTlvP2PCapability(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PCapability *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->deviceCapability = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + pDst->groupCapability = *pBuf; + pBuf += 1; + tlvlen -= (tANI_U8)1; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvP2PCapability. */ + +#define SigTlvP2PCapability ( 0x0017 ) + + +tANI_U32 dot11fUnpackTlvP2PDeviceId(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PDeviceId *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PDeviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvP2PDeviceId. */ + +#define SigTlvP2PDeviceId ( 0x0018 ) + + + static const tTLVDefn TLVS_P2PDeviceInfo[] = { + {offsetof(tDot11fTLVP2PDeviceInfo, DeviceName), offsetof(tDot11fTLVDeviceName, present), "DeviceName", SigTlvDeviceName, DOT11F_TLV_DEVICENAME, 0, 4, 36, 1, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackTlvP2PDeviceInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PDeviceInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PDeviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + framesntohs(pCtx, &pDst->configMethod, pBuf, 0); + pBuf += 2; + tlvlen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->primaryDeviceType, pBuf, 8); + pBuf += 8; + tlvlen -= (tANI_U8)8; + (void)pCtx; + status |= UnpackTlvCore(pCtx, + pBuf, + tlvlen, + TLVS_P2PDeviceInfo, + ( tANI_U8* )pDst, + sizeof(*pDst)); + return status; +} /* End dot11fUnpackTlvP2PDeviceInfo. */ + +#define SigTlvP2PDeviceInfo ( 0x0019 ) + + +tANI_U32 dot11fUnpackTlvP2PGroupBssid(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PGroupBssid *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PGroupBssid, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvP2PGroupBssid. */ + +#define SigTlvP2PGroupBssid ( 0x001a ) + + +tANI_U32 dot11fUnpackTlvP2PGroupId(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PGroupId *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->deviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + pDst->num_ssid = (tANI_U8)( tlvlen ); + if (tlvlen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->ssid, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvP2PGroupId. */ + +#define SigTlvP2PGroupId ( 0x001b ) + + +tANI_U32 dot11fUnpackTlvP2PGroupInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PGroupInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_P2PClientInfoDesc = (tANI_U8)( tlvlen ); + DOT11F_MEMCPY(pCtx, pDst->P2PClientInfoDesc, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvP2PGroupInfo. */ + +#define SigTlvP2PGroupInfo ( 0x001c ) + + +#define SigTlvP2PStatus ( 0x001d ) + + +tANI_U32 dot11fUnpackTlvPrimaryDeviceType(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVPrimaryDeviceType *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)tlvlen; /* Shutup the compiler */ + pDst->present = 1; + framesntohs(pCtx, &pDst->primary_category, pBuf, 1); + pBuf += 2; + tlvlen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->oui, pBuf, 4); + pBuf += 4; + tlvlen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->sub_category, pBuf, 1); + pBuf += 2; + tlvlen -= (tANI_U8)2; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvPrimaryDeviceType. */ + +#define SigTlvPrimaryDeviceType ( 0x001e ) + + +#define SigTlvRFBands ( 0x001f ) + + +tANI_U32 dot11fUnpackTlvRequestDeviceType(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVRequestDeviceType *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + framesntohs(pCtx, &pDst->primary_category, pBuf, 1); + pBuf += 2; + tlvlen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->oui, pBuf, 4); + pBuf += 4; + tlvlen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->sub_category, pBuf, 1); + pBuf += 2; + tlvlen -= (tANI_U8)2; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvRequestDeviceType. */ + +#define SigTlvRequestDeviceType ( 0x0020 ) + + +#define SigTlvRequestType ( 0x0021 ) + + +#define SigTlvResponseType ( 0x0022 ) + + +#define SigTlvSelectedRegistrar ( 0x0023 ) + + +#define SigTlvSelectedRegistrarConfigMethods ( 0x0024 ) + + +tANI_U32 dot11fUnpackTlvSerialNumber(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVSerialNumber *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (tANI_U8)( tlvlen ); + if (tlvlen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->text, pBuf, ( tlvlen ) ); + pBuf += ( tlvlen ); + tlvlen -= ( tlvlen ); + (void)pCtx; + return status; +} /* End dot11fUnpackTlvSerialNumber. */ + +#define SigTlvSerialNumber ( 0x0025 ) + + +tANI_U32 dot11fUnpackTlvUUID_E(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVUUID_E *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->uuid, pBuf, 16); + pBuf += 16; + tlvlen -= (tANI_U8)16; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvUUID_E. */ + +#define SigTlvUUID_E ( 0x0026 ) + + +tANI_U32 dot11fUnpackTlvUUID_R(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVUUID_R *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->uuid, pBuf, 16); + pBuf += 16; + tlvlen -= (tANI_U8)16; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvUUID_R. */ + +#define SigTlvUUID_R ( 0x0027 ) + + + static const tTLVDefn TLVS_VendorExtension[] = { + {offsetof(tDot11fTLVVendorExtension, Version2), offsetof(tDot11fTLVVersion2, present), "Version2", SigTlvVersion2, DOT11F_TLV_VERSION2, 0, 3, 3, 0, 1, 1, 1, }, + {offsetof(tDot11fTLVVendorExtension, AuthorizedMACs), offsetof(tDot11fTLVAuthorizedMACs, present), "AuthorizedMACs", SigTlvAuthorizedMACs, DOT11F_TLV_AUTHORIZEDMACS, 0, 8, 8, 0, 1, 1, 1, }, + {offsetof(tDot11fTLVVendorExtension, RequestToEnroll), offsetof(tDot11fTLVRequestToEnroll, present), "RequestToEnroll", SigTlvRequestToEnroll, DOT11F_TLV_REQUESTTOENROLL, 0, 3, 3, 0, 1, 1, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackTlvVendorExtension(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVVendorExtension *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->vendorId, pBuf, 3); + pBuf += 3; + tlvlen -= (tANI_U8)3; + (void)pCtx; + status |= UnpackTlvCore(pCtx, + pBuf, + tlvlen, + TLVS_VendorExtension, + ( tANI_U8* )pDst, + sizeof(*pDst)); + return status; +} /* End dot11fUnpackTlvVendorExtension. */ + +#define SigTlvVendorExtension ( 0x0028 ) + + +tANI_U32 dot11fUnpackTlvVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVVersion *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp9__; + pDst->present = 1; + tmp9__ = *pBuf; + pBuf += 1; + tlvlen -= 1; + pDst->minor = tmp9__ >> 0 & 0xf; + pDst->major = tmp9__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvVersion. */ + +#define SigTlvVersion ( 0x0029 ) + + +#define SigTlvWPSState ( 0x002a ) + + +tANI_U32 dot11fUnpackTlvP2PInterface(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVP2PInterface *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PDeviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (tANI_U8)6; + (void)pCtx; + return status; +} /* End dot11fUnpackTlvP2PInterface. */ + +#define SigTlvP2PInterface ( 0x002b ) + + +#define SigTlvP2PManageability ( 0x002c ) + + +tANI_U32 dot11fUnpackIeCondensedCountryStr(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECondensedCountryStr *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->countryStr, pBuf, 2); + (void)pCtx; + return status; +} /* End dot11fUnpackIeCondensedCountryStr. */ + +#define SigIeCondensedCountryStr ( 0x0001 ) + + +tANI_U32 dot11fUnpackIeGTK(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEGTK *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp10__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp10__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->keyId = tmp10__ >> 0 & 0x3; + pDst->reserved = tmp10__ >> 2 & 0x3feb; + pDst->keyLength = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->RSC, pBuf, 8); + pBuf += 8; + ielen -= (tANI_U8)8; + pDst->num_key = (tANI_U8)( ielen ); + if (ielen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->key, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeGTK. */ + +#define SigIeGTK ( 0x0002 ) + + +tANI_U32 dot11fUnpackIeIGTK(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEIGTK *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->keyID, pBuf, 2); + pBuf += 2; + ielen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->IPN, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + pDst->keyLength = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->key, pBuf, 24); + (void)pCtx; + return status; +} /* End dot11fUnpackIeIGTK. */ + +#define SigIeIGTK ( 0x0003 ) + + +tANI_U32 dot11fUnpackIeR0KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIER0KH_ID *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_PMK_R0_ID = (tANI_U8)( ielen ); + if (ielen > 48){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->PMK_R0_ID, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeR0KH_ID. */ + +#define SigIeR0KH_ID ( 0x0004 ) + + +tANI_U32 dot11fUnpackIeR1KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIER1KH_ID *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->PMK_R1_ID, pBuf, 6); + (void)pCtx; + return status; +} /* End dot11fUnpackIeR1KH_ID. */ + +#define SigIeR1KH_ID ( 0x0005 ) + + +tANI_U32 dot11fUnpackIeTSFInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSFInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->TsfOffset, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->BeaconIntvl, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeTSFInfo. */ + +#define SigIeTSFInfo ( 0x0006 ) + + +tANI_U32 dot11fUnpackIeAPChannelReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEAPChannelReport *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_channelList = (tANI_U8)( ielen ); + if (ielen > 50){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->channelList, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeAPChannelReport. */ + +#define SigIeAPChannelReport ( 0x0007 ) + + +tANI_U32 dot11fUnpackIeBcnReportingDetail(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBcnReportingDetail *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->reportingDetail = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeBcnReportingDetail. */ + +#define SigIeBcnReportingDetail ( 0x0008 ) + + +tANI_U32 dot11fUnpackIeBeaconReportFrmBody(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBeaconReportFrmBody *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_reportedFields = (tANI_U8)( ielen ); + if (ielen > 224){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->reportedFields, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeBeaconReportFrmBody. */ + +#define SigIeBeaconReportFrmBody ( 0x0009 ) + + +tANI_U32 dot11fUnpackIeBeaconReporting(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBeaconReporting *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->reportingCondition = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->threshold = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeBeaconReporting. */ + +#define SigIeBeaconReporting ( 0x000a ) + + +tANI_U32 dot11fUnpackIeMeasurementPilot(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMeasurementPilot *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->measurementPilot = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_vendorSpecific = (tANI_U8)( ielen ); + DOT11F_MEMCPY(pCtx, pDst->vendorSpecific, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeMeasurementPilot. */ + +#define SigIeMeasurementPilot ( 0x000b ) + + +tANI_U32 dot11fUnpackIeMultiBssid(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMultiBssid *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->maxBSSIDIndicator = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_vendorSpecific = (tANI_U8)( ielen ); + DOT11F_MEMCPY(pCtx, pDst->vendorSpecific, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeMultiBssid. */ + +#define SigIeMultiBssid ( 0x000c ) + + +tANI_U32 dot11fUnpackIeRICData(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICData *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->Identifier = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->resourceDescCount = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->statusCode, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeRICData. */ + +#define SigIeRICData ( 0x000d ) + + +tANI_U32 dot11fUnpackIeRICDescriptor(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICDescriptor *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->resourceType = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_variableData = (tANI_U8)( ielen ); + DOT11F_MEMCPY(pCtx, pDst->variableData, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeRICDescriptor. */ + +#define SigIeRICDescriptor ( 0x000e ) + + +tANI_U32 dot11fUnpackIeRRMEnabledCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERRMEnabledCap *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp11__; + tANI_U8 tmp12__; + tANI_U8 tmp13__; + tANI_U8 tmp14__; + tANI_U8 tmp15__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp11__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->LinkMeasurement = tmp11__ >> 0 & 0x1; + pDst->NeighborRpt = tmp11__ >> 1 & 0x1; + pDst->parallel = tmp11__ >> 2 & 0x1; + pDst->repeated = tmp11__ >> 3 & 0x1; + pDst->BeaconPassive = tmp11__ >> 4 & 0x1; + pDst->BeaconActive = tmp11__ >> 5 & 0x1; + pDst->BeaconTable = tmp11__ >> 6 & 0x1; + pDst->BeaconRepCond = tmp11__ >> 7 & 0x1; + tmp12__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->FrameMeasurement = tmp12__ >> 0 & 0x1; + pDst->ChannelLoad = tmp12__ >> 1 & 0x1; + pDst->NoiseHistogram = tmp12__ >> 2 & 0x1; + pDst->statistics = tmp12__ >> 3 & 0x1; + pDst->LCIMeasurement = tmp12__ >> 4 & 0x1; + pDst->LCIAzimuth = tmp12__ >> 5 & 0x1; + pDst->TCMCapability = tmp12__ >> 6 & 0x1; + pDst->triggeredTCM = tmp12__ >> 7 & 0x1; + tmp13__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->APChanReport = tmp13__ >> 0 & 0x1; + pDst->RRMMIBEnabled = tmp13__ >> 1 & 0x1; + pDst->operatingChanMax = tmp13__ >> 2 & 0x7; + pDst->nonOperatinChanMax = tmp13__ >> 5 & 0x7; + tmp14__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->MeasurementPilot = tmp14__ >> 0 & 0x7; + pDst->MeasurementPilotEnabled = tmp14__ >> 3 & 0x1; + pDst->NeighborTSFOffset = tmp14__ >> 4 & 0x1; + pDst->RCPIMeasurement = tmp14__ >> 5 & 0x1; + pDst->RSNIMeasurement = tmp14__ >> 6 & 0x1; + pDst->BssAvgAccessDelay = tmp14__ >> 7 & 0x1; + tmp15__ = *pBuf; + pDst->BSSAvailAdmission = tmp15__ >> 0 & 0x1; + pDst->AntennaInformation = tmp15__ >> 1 & 0x1; + pDst->fine_time_meas_rpt = tmp15__ >> 2 & 0x1; + pDst->lci_capability = tmp15__ >> 3 & 0x1; + pDst->reserved = tmp15__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeRRMEnabledCap. */ + +#define SigIeRRMEnabledCap ( 0x000f ) + + +tANI_U32 dot11fUnpackIeRequestedInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERequestedInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_requested_eids = (tANI_U8)( ielen ); + DOT11F_MEMCPY(pCtx, pDst->requested_eids, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeRequestedInfo. */ + +#define SigIeRequestedInfo ( 0x0010 ) + + +tANI_U32 dot11fUnpackIeSSID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESSID *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + { + status = DOT11F_DUPLICATE_IE; + return status; + } + pDst->present = 1; + pDst->num_ssid = (tANI_U8)( ielen ); + if (ielen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->ssid, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeSSID. */ + +#define SigIeSSID ( 0x0011 ) + + +tANI_U32 dot11fUnpackIeSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESchedule *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp16__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp16__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->aggregation = tmp16__ >> 0 & 0x1; + pDst->tsid = tmp16__ >> 1 & 0xf; + pDst->direction = tmp16__ >> 5 & 0x3; + pDst->reserved = tmp16__ >> 7 & 0x1ff; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->service_interval, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->max_service_dur, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->spec_interval, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeSchedule. */ + +#define SigIeSchedule ( 0x0012 ) + + +tANI_U32 dot11fUnpackIeTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETCLAS *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->user_priority = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->classifier_type = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->classifier_mask = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + switch (pDst->classifier_type) + { + case 0: + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.source, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.dest, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + framesntohs(pCtx, &pDst->info.EthParams.type, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + case 1: + pDst->info.IpParams.version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + switch (pDst->info.IpParams.version) + { + case 4: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.source, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.dest, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->info.IpParams.params.IpV4Params.DSCP = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->info.IpParams.params.IpV4Params.proto = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->info.IpParams.params.IpV4Params.reserved = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + break; + case 6: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.source, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.dest, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.flow_label, pBuf, 3); + pBuf += 3; + ielen -= (tANI_U8)3; + break; + } + break; + case 2: + framesntohs(pCtx, &pDst->info.Params8021dq.tag_type, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeTCLAS. */ + +#define SigIeTCLAS ( 0x0013 ) + + +#define SigIeTCLASSPROC ( 0x0014 ) + + +tANI_U32 dot11fUnpackIeTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSDelay *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohl(pCtx, &pDst->delay, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeTSDelay. */ + +#define SigIeTSDelay ( 0x0015 ) + + +tANI_U32 dot11fUnpackIeTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSPEC *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp17__; + tANI_U8 tmp18__; + tANI_U16 tmp19__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp17__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->traffic_type = tmp17__ >> 0 & 0x1; + pDst->tsid = tmp17__ >> 1 & 0xf; + pDst->direction = tmp17__ >> 5 & 0x3; + pDst->access_policy = tmp17__ >> 7 & 0x3; + pDst->aggregation = tmp17__ >> 9 & 0x1; + pDst->psb = tmp17__ >> 10 & 0x1; + pDst->user_priority = tmp17__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp17__ >> 14 & 0x3; + tmp18__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->schedule = tmp18__ >> 0 & 0x1; + pDst->unused = tmp18__ >> 1 & 0x7f; + framesntohs(pCtx, &tmp19__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->size = tmp19__ >> 0 & 0x7fff; + pDst->fixed = tmp19__ >> 15 & 0x1; + framesntohs(pCtx, &pDst->max_msdu_size, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohl(pCtx, &pDst->min_service_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->max_service_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->inactivity_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->suspension_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->min_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->mean_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->peak_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->burst_size, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->delay_bound, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->min_phy_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->surplus_bw_allowance, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->medium_time, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeTSPEC. */ + +#define SigIeTSPEC ( 0x0016 ) + + +tANI_U32 dot11fUnpackIeWMMSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMSchedule *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp20__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + framesntohs(pCtx, &tmp20__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->aggregation = tmp20__ >> 0 & 0x1; + pDst->tsid = tmp20__ >> 1 & 0xf; + pDst->direction = tmp20__ >> 5 & 0x3; + pDst->reserved = tmp20__ >> 7 & 0x1ff; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->service_interval, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->max_service_dur, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->spec_interval, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMSchedule. */ + +#define SigIeWMMSchedule ( 0x0017 ) + + +tANI_U32 dot11fUnpackIeWMMTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTCLAS *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + pDst->user_priority = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->classifier_type = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->classifier_mask = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + switch (pDst->classifier_type) + { + case 0: + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.source, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.dest, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + framesntohs(pCtx, &pDst->info.EthParams.type, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + case 1: + pDst->info.IpParams.version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + switch (pDst->info.IpParams.version) + { + case 4: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.source, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.dest, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->info.IpParams.params.IpV4Params.DSCP = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->info.IpParams.params.IpV4Params.proto = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->info.IpParams.params.IpV4Params.reserved = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + break; + case 6: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.source, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.dest, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.flow_label, pBuf, 3); + pBuf += 3; + ielen -= (tANI_U8)3; + break; + } + break; + case 2: + framesntohs(pCtx, &pDst->info.Params8021dq.tag_type, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMTCLAS. */ + +#define SigIeWMMTCLAS ( 0x0018 ) + + +tANI_U32 dot11fUnpackIeWMMTCLASPROC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTCLASPROC *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + pDst->processing = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMTCLASPROC. */ + +#define SigIeWMMTCLASPROC ( 0x0019 ) + + +tANI_U32 dot11fUnpackIeWMMTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTSDelay *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + framesntohl(pCtx, &pDst->delay, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMTSDelay. */ + +#define SigIeWMMTSDelay ( 0x001a ) + + +tANI_U32 dot11fUnpackIeWMMTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTSPEC *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp21__; + tANI_U8 tmp22__; + tANI_U16 tmp23__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + framesntohs(pCtx, &tmp21__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->traffic_type = tmp21__ >> 0 & 0x1; + pDst->tsid = tmp21__ >> 1 & 0xf; + pDst->direction = tmp21__ >> 5 & 0x3; + pDst->access_policy = tmp21__ >> 7 & 0x3; + pDst->aggregation = tmp21__ >> 9 & 0x1; + pDst->psb = tmp21__ >> 10 & 0x1; + pDst->user_priority = tmp21__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp21__ >> 14 & 0x3; + tmp22__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->tsinfo_rsvd = tmp22__ >> 0 & 0x7f; + pDst->burst_size_defn = tmp22__ >> 7 & 0x1; + framesntohs(pCtx, &tmp23__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->size = tmp23__ >> 0 & 0x7fff; + pDst->fixed = tmp23__ >> 15 & 0x1; + framesntohs(pCtx, &pDst->max_msdu_size, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohl(pCtx, &pDst->min_service_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->max_service_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->inactivity_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->suspension_int, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->min_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->mean_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->peak_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->burst_size, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->delay_bound, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohl(pCtx, &pDst->min_phy_rate, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &pDst->surplus_bw_allowance, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->medium_time, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMTSPEC. */ + +#define SigIeWMMTSPEC ( 0x001b ) + + +tANI_U32 dot11fUnpackIeWiderBWChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWiderBWChanSwitchAnn *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->newChanWidth = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->newCenterChanFreq0 = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->newCenterChanFreq1 = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeWiderBWChanSwitchAnn. */ + +#define SigIeWiderBWChanSwitchAnn ( 0x001c ) + + +tANI_U32 dot11fUnpackIeAID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEAID *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->assocId, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeAID. */ + +#define SigIeAID ( 0x001d ) + + +tANI_U32 dot11fUnpackIeCFParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECFParams *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->cfp_count = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->cfp_period = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->cfp_maxduration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->cfp_durremaining, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeCFParams. */ + +#define SigIeCFParams ( 0x001e ) + + +tANI_U32 dot11fUnpackIeChallengeText(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChallengeText *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_text = (tANI_U8)( ielen ); + if (ielen > 253){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->text, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeChallengeText. */ + +#define SigIeChallengeText ( 0x001f ) + + +tANI_U32 dot11fUnpackIeChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChanSwitchAnn *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->switchMode = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->newChannel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->switchCount = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeChanSwitchAnn. */ + +#define SigIeChanSwitchAnn ( 0x0020 ) + + + static const tFFDefn FFS_ChannelSwitchWrapper[ ] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ChannelSwitchWrapper[ ] = { + {offsetof(tDot11fIEChannelSwitchWrapper, WiderBWChanSwitchAnn), offsetof(tDot11fIEWiderBWChanSwitchAnn, present), 0, "WiderBWChanSwitchAnn" , 0, 5, 5, SigIeWiderBWChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WIDERBWCHANSWITCHANN, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, + }; + +tANI_U32 dot11fUnpackIeChannelSwitchWrapper(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChannelSwitchWrapper *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + status |= UnpackCore(pCtx, + pBuf, + ielen, + FFS_ChannelSwitchWrapper, + IES_ChannelSwitchWrapper, + ( tANI_U8* )pDst, + sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeChannelSwitchWrapper. */ + +#define SigIeChannelSwitchWrapper ( 0x0021 ) + + +tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECountry *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->country, pBuf, 3); + pBuf += 3; + ielen -= (tANI_U8)3; + if ( ! ielen ) + { + pDst->num_triplets = 0U; + return 0U; + } + else + { + pDst->num_triplets = (tANI_U8)( ielen / 3 ); + if (ielen > 84 * 3){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->triplets, pBuf, ( ielen ) ); + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeCountry. */ + +#define SigIeCountry ( 0x0022 ) + + +#define SigIeDSParams ( 0x0023 ) + + +tANI_U32 dot11fUnpackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEEDCAParamSet *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp24__; + tANI_U8 tmp25__; + tANI_U8 tmp26__; + tANI_U8 tmp27__; + tANI_U8 tmp28__; + tANI_U8 tmp29__; + tANI_U8 tmp30__; + tANI_U8 tmp31__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->qos = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->reserved = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp24__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_aifsn = tmp24__ >> 0 & 0xf; + pDst->acbe_acm = tmp24__ >> 4 & 0x1; + pDst->acbe_aci = tmp24__ >> 5 & 0x3; + pDst->unused1 = tmp24__ >> 7 & 0x1; + tmp25__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_acwmin = tmp25__ >> 0 & 0xf; + pDst->acbe_acwmax = tmp25__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbe_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp26__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_aifsn = tmp26__ >> 0 & 0xf; + pDst->acbk_acm = tmp26__ >> 4 & 0x1; + pDst->acbk_aci = tmp26__ >> 5 & 0x3; + pDst->unused2 = tmp26__ >> 7 & 0x1; + tmp27__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_acwmin = tmp27__ >> 0 & 0xf; + pDst->acbk_acwmax = tmp27__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbk_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp28__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_aifsn = tmp28__ >> 0 & 0xf; + pDst->acvi_acm = tmp28__ >> 4 & 0x1; + pDst->acvi_aci = tmp28__ >> 5 & 0x3; + pDst->unused3 = tmp28__ >> 7 & 0x1; + tmp29__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_acwmin = tmp29__ >> 0 & 0xf; + pDst->acvi_acwmax = tmp29__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvi_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp30__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_aifsn = tmp30__ >> 0 & 0xf; + pDst->acvo_acm = tmp30__ >> 4 & 0x1; + pDst->acvo_aci = tmp30__ >> 5 & 0x3; + pDst->unused4 = tmp30__ >> 7 & 0x1; + tmp31__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_acwmin = tmp31__ >> 0 & 0xf; + pDst->acvo_acwmax = tmp31__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvo_txoplimit, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeEDCAParamSet. */ + +#define SigIeEDCAParamSet ( 0x0024 ) + + +tANI_U32 dot11fUnpackIeERPInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEERPInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp32__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp32__ = *pBuf; + pDst->non_erp_present = tmp32__ >> 0 & 0x1; + pDst->use_prot = tmp32__ >> 1 & 0x1; + pDst->barker_preamble = tmp32__ >> 2 & 0x1; + pDst->unused = tmp32__ >> 3 & 0x1f; + (void)pCtx; + return status; +} /* End dot11fUnpackIeERPInfo. */ + +#define SigIeERPInfo ( 0x0025 ) + + +tANI_U32 dot11fUnpackIeESECckmOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEESECckmOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 20){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeESECckmOpaque. */ + +#define SigIeESECckmOpaque ( 0x0026 ) + + +tANI_U32 dot11fUnpackIeESERadMgmtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEESERadMgmtCap *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp33__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->mgmt_state = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp33__ = *pBuf; + pDst->mbssid_mask = tmp33__ >> 0 & 0x7; + pDst->reserved = tmp33__ >> 3 & 0x1f; + (void)pCtx; + return status; +} /* End dot11fUnpackIeESERadMgmtCap. */ + +#define SigIeESERadMgmtCap ( 0x0027 ) + + +tANI_U32 dot11fUnpackIeESETrafStrmMet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEESETrafStrmMet *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->tsid = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->state = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->msmt_interval, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeESETrafStrmMet. */ + +#define SigIeESETrafStrmMet ( 0x0028 ) + + +tANI_U32 dot11fUnpackIeESETrafStrmRateSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEESETrafStrmRateSet *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->tsid = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_tsrates = (tANI_U8)( ielen ); + if (ielen > 8){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->tsrates, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeESETrafStrmRateSet. */ + +#define SigIeESETrafStrmRateSet ( 0x0029 ) + + +tANI_U32 dot11fUnpackIeESETxmitPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEESETxmitPower *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->power_limit = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->reserved = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeESETxmitPower. */ + +#define SigIeESETxmitPower ( 0x002a ) + + +tANI_U32 dot11fUnpackIeESEVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEESEVersion *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeESEVersion. */ + +#define SigIeESEVersion ( 0x002b ) + + +tANI_U32 dot11fUnpackIeExtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEExtCap *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + + if (!ielen) /* Check to ensure copying of ielen bytes */ + goto endUnpackIeExtCap; + pDst->num_bytes = (tANI_U8)( ielen ); + if (ielen > 9){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->bytes, pBuf, ( ielen ) ); + +endUnpackIeExtCap: + (void)pCtx; + return status; +} /* End dot11fUnpackIeExtCap. */ + +#define SigIeExtCap ( 0x002c ) + + +tANI_U32 dot11fUnpackIeExtSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEExtSuppRates *pDst) +{ + tANI_U8 i; + tANI_U8 rate_indx = 0; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + for (i = 0; i < ielen; i++) { + if ((DOT11F_IS_BG_RATE(pBuf[i] & 0x7F)) && + (rate_indx < 12)) { + pDst->rates[rate_indx++] = pBuf[i]; + } + } + + if(rate_indx == 0) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + pDst->num_rates = rate_indx; + (void)pCtx; + return status; +} /* End dot11fUnpackIeExtSuppRates. */ + +#define SigIeExtSuppRates ( 0x002d ) + + +tANI_U32 dot11fUnpackIeFHParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHParamSet *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->dwell_time, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->hop_set = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->hop_pattern = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->hop_index = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeFHParamSet. */ + +#define SigIeFHParamSet ( 0x002e ) + + +tANI_U32 dot11fUnpackIeFHParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHParams *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->radix = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->nchannels = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeFHParams. */ + +#define SigIeFHParams ( 0x002f ) + + +tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHPattTable *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->flag = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->nsets = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->modulus = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->offset = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_randtable = (tANI_U8)( ielen ); + if (ielen > 251){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->randtable, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeFHPattTable. */ + +#define SigIeFHPattTable ( 0x0030 ) + + + static const tFFDefn FFS_FTInfo[ ] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_FTInfo[ ] = { + {offsetof(tDot11fIEFTInfo, R1KH_ID), offsetof(tDot11fIER1KH_ID, present), 0, "R1KH_ID" , 0, 8, 8, SigIeR1KH_ID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_R1KH_ID, 0, }, + {offsetof(tDot11fIEFTInfo, GTK), offsetof(tDot11fIEGTK, present), 0, "GTK" , 0, 18, 45, SigIeGTK, {0, 0, 0, 0, 0}, 0, DOT11F_EID_GTK, 0, }, + {offsetof(tDot11fIEFTInfo, R0KH_ID), offsetof(tDot11fIER0KH_ID, present), 0, "R0KH_ID" , 0, 3, 50, SigIeR0KH_ID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_R0KH_ID, 0, }, + {offsetof(tDot11fIEFTInfo, IGTK), offsetof(tDot11fIEIGTK, present), 0, "IGTK" , 0, 35, 35, SigIeIGTK, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IGTK, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, + }; + +tANI_U32 dot11fUnpackIeFTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFTInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp34__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp34__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->reserved = tmp34__ >> 0 & 0xff; + pDst->IECount = tmp34__ >> 8 & 0xff; + DOT11F_MEMCPY(pCtx, pDst->MIC, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + DOT11F_MEMCPY(pCtx, pDst->Anonce, pBuf, 32); + pBuf += 32; + ielen -= (tANI_U8)32; + DOT11F_MEMCPY(pCtx, pDst->Snonce, pBuf, 32); + pBuf += 32; + ielen -= (tANI_U8)32; + (void)pCtx; + status |= UnpackCore(pCtx, + pBuf, + ielen, + FFS_FTInfo, + IES_FTInfo, + ( tANI_U8* )pDst, + sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeFTInfo. */ + +#define SigIeFTInfo ( 0x0031 ) + + +tANI_U32 dot11fUnpackIeHT2040BSSCoexistence(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHT2040BSSCoexistence *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp35__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp35__ = *pBuf; + pDst->infoRequest = tmp35__ >> 0 & 0x1; + pDst->fortyMHzIntolerant = tmp35__ >> 1 & 0x1; + pDst->twentyMHzBssWidthReq = tmp35__ >> 2 & 0x1; + pDst->obssScanExemptionReq = tmp35__ >> 3 & 0x1; + pDst->obssScanExemptionGrant = tmp35__ >> 4 & 0x1; + pDst->unused = tmp35__ >> 5 & 0x7; + (void)pCtx; + return status; +} /* End dot11fUnpackIeHT2040BSSCoexistence. */ + +#define SigIeHT2040BSSCoexistence ( 0x0032 ) + + +tANI_U32 dot11fUnpackIeHT2040BSSIntolerantReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHT2040BSSIntolerantReport *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->operatingClass = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_channelList = (tANI_U8)( ielen ); + if (ielen > 50){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->channelList, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeHT2040BSSIntolerantReport. */ + +#define SigIeHT2040BSSIntolerantReport ( 0x0033 ) + + +tANI_U32 dot11fUnpackIeHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHTCaps *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp36__; + tANI_U8 tmp37__; + tANI_U16 tmp38__; + tANI_U32 tmp39__; + tANI_U8 tmp40__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp36__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->advCodingCap = tmp36__ >> 0 & 0x1; + pDst->supportedChannelWidthSet = tmp36__ >> 1 & 0x1; + pDst->mimoPowerSave = tmp36__ >> 2 & 0x3; + pDst->greenField = tmp36__ >> 4 & 0x1; + pDst->shortGI20MHz = tmp36__ >> 5 & 0x1; + pDst->shortGI40MHz = tmp36__ >> 6 & 0x1; + pDst->txSTBC = tmp36__ >> 7 & 0x1; + pDst->rxSTBC = tmp36__ >> 8 & 0x3; + pDst->delayedBA = tmp36__ >> 10 & 0x1; + pDst->maximalAMSDUsize = tmp36__ >> 11 & 0x1; + pDst->dsssCckMode40MHz = tmp36__ >> 12 & 0x1; + pDst->psmp = tmp36__ >> 13 & 0x1; + pDst->stbcControlFrame = tmp36__ >> 14 & 0x1; + pDst->lsigTXOPProtection = tmp36__ >> 15 & 0x1; + tmp37__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->maxRxAMPDUFactor = tmp37__ >> 0 & 0x3; + pDst->mpduDensity = tmp37__ >> 2 & 0x7; + pDst->reserved1 = tmp37__ >> 5 & 0x7; + DOT11F_MEMCPY(pCtx, pDst->supportedMCSSet, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + framesntohs(pCtx, &tmp38__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->pco = tmp38__ >> 0 & 0x1; + pDst->transitionTime = tmp38__ >> 1 & 0x3; + pDst->reserved2 = tmp38__ >> 3 & 0x1f; + pDst->mcsFeedback = tmp38__ >> 8 & 0x3; + pDst->reserved3 = tmp38__ >> 10 & 0x3f; + framesntohl(pCtx, &tmp39__, pBuf, 0); + pBuf += 4; + ielen -= 4; + pDst->txBF = tmp39__ >> 0 & 0x1; + pDst->rxStaggeredSounding = tmp39__ >> 1 & 0x1; + pDst->txStaggeredSounding = tmp39__ >> 2 & 0x1; + pDst->rxZLF = tmp39__ >> 3 & 0x1; + pDst->txZLF = tmp39__ >> 4 & 0x1; + pDst->implicitTxBF = tmp39__ >> 5 & 0x1; + pDst->calibration = tmp39__ >> 6 & 0x3; + pDst->explicitCSITxBF = tmp39__ >> 8 & 0x1; + pDst->explicitUncompressedSteeringMatrix = tmp39__ >> 9 & 0x1; + pDst->explicitBFCSIFeedback = tmp39__ >> 10 & 0x7; + pDst->explicitUncompressedSteeringMatrixFeedback = tmp39__ >> 13 & 0x7; + pDst->explicitCompressedSteeringMatrixFeedback = tmp39__ >> 16 & 0x7; + pDst->csiNumBFAntennae = tmp39__ >> 19 & 0x3; + pDst->uncompressedSteeringMatrixBFAntennae = tmp39__ >> 21 & 0x3; + pDst->compressedSteeringMatrixBFAntennae = tmp39__ >> 23 & 0x3; + pDst->reserved4 = tmp39__ >> 25 & 0x7f; + tmp40__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->antennaSelection = tmp40__ >> 0 & 0x1; + pDst->explicitCSIFeedbackTx = tmp40__ >> 1 & 0x1; + pDst->antennaIndicesFeedbackTx = tmp40__ >> 2 & 0x1; + pDst->explicitCSIFeedback = tmp40__ >> 3 & 0x1; + pDst->antennaIndicesFeedback = tmp40__ >> 4 & 0x1; + pDst->rxAS = tmp40__ >> 5 & 0x1; + pDst->txSoundingPPDUs = tmp40__ >> 6 & 0x1; + pDst->reserved5 = tmp40__ >> 7 & 0x1; + pDst->num_rsvd = (tANI_U8)( ielen ); + if (ielen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->rsvd, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeHTCaps. */ + +#define SigIeHTCaps ( 0x0034 ) + + +tANI_U32 dot11fUnpackIeHTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHTInfo *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp41__; + tANI_U16 tmp42__; + tANI_U16 tmp43__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->primaryChannel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp41__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->secondaryChannelOffset = tmp41__ >> 0 & 0x3; + pDst->recommendedTxWidthSet = tmp41__ >> 2 & 0x1; + pDst->rifsMode = tmp41__ >> 3 & 0x1; + pDst->controlledAccessOnly = tmp41__ >> 4 & 0x1; + pDst->serviceIntervalGranularity = tmp41__ >> 5 & 0x7; + framesntohs(pCtx, &tmp42__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->opMode = tmp42__ >> 0 & 0x3; + pDst->nonGFDevicesPresent = tmp42__ >> 2 & 0x1; + pDst->transmitBurstLimit = tmp42__ >> 3 & 0x1; + pDst->obssNonHTStaPresent = tmp42__ >> 4 & 0x1; + pDst->reserved = tmp42__ >> 5 & 0x7ff; + framesntohs(pCtx, &tmp43__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->basicSTBCMCS = tmp43__ >> 0 & 0x7f; + pDst->dualCTSProtection = tmp43__ >> 7 & 0x1; + pDst->secondaryBeacon = tmp43__ >> 8 & 0x1; + pDst->lsigTXOPProtectionFullSupport = tmp43__ >> 9 & 0x1; + pDst->pcoActive = tmp43__ >> 10 & 0x1; + pDst->pcoPhase = tmp43__ >> 11 & 0x1; + pDst->reserved2 = tmp43__ >> 12 & 0xf; + DOT11F_MEMCPY(pCtx, pDst->basicMCSSet, pBuf, 16); + pBuf += 16; + ielen -= (tANI_U8)16; + pDst->num_rsvd = (tANI_U8)( ielen ); + if (ielen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->rsvd, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeHTInfo. */ + +#define SigIeHTInfo ( 0x0035 ) + + +tANI_U32 dot11fUnpackIeIBSSParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEIBSSParams *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->atim, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeIBSSParams. */ + +#define SigIeIBSSParams ( 0x0036 ) + + +tANI_U32 dot11fUnpackIeLinkIdentifier(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELinkIdentifier *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->bssid, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + DOT11F_MEMCPY(pCtx, pDst->InitStaAddr, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + DOT11F_MEMCPY(pCtx, pDst->RespStaAddr, pBuf, 6); + (void)pCtx; + return status; +} /* End dot11fUnpackIeLinkIdentifier. */ + +#define SigIeLinkIdentifier ( 0x0037 ) + + +static const tFFDefn FFS_reportBeacon[ ] = { +{ NULL, 0, 0, 0,}, +}; + +static const tIEDefn IES_reportBeacon[ ] = { + {offsetof(tDot11fIEMeasurementReport, report.Beacon.BeaconReportFrmBody), offsetof(tDot11fIEBeaconReportFrmBody, present), 0, "BeaconReportFrmBody" , 0, 2, 226, SigIeBeaconReportFrmBody, {0, 0, 0, 0, 0}, 0, DOT11F_EID_BEACONREPORTFRMBODY, 0, }, +{0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, +}; + +tANI_U32 dot11fUnpackIeMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMeasurementReport *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp44__; + tANI_U8 tmp45__; + tANI_U8 tmp46__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->token = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp44__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->late = tmp44__ >> 0 & 0x1; + pDst->incapable = tmp44__ >> 1 & 0x1; + pDst->refused = tmp44__ >> 2 & 0x1; + pDst->unused = tmp44__ >> 3 & 0x1f; + pDst->type = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if ( ! ielen ) + { + return 0U; + } + else + { + switch (pDst->type) + { + case 0: + pDst->report.Basic.channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohq(pCtx, &pDst->report.Basic.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->report.Basic.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp45__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->report.Basic.bss = tmp45__ >> 0 & 0x1; + pDst->report.Basic.ofdm_preamble = tmp45__ >> 1 & 0x1; + pDst->report.Basic.unid_signal = tmp45__ >> 2 & 0x1; + pDst->report.Basic.rader = tmp45__ >> 3 & 0x1; + pDst->report.Basic.unmeasured = tmp45__ >> 4 & 0x1; + pDst->report.Basic.unused = tmp45__ >> 5 & 0x7; + break; + case 1: + pDst->report.CCA.channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohq(pCtx, &pDst->report.CCA.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->report.CCA.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->report.CCA.cca_busy_fraction = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + break; + case 2: + pDst->report.RPIHistogram.channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohq(pCtx, &pDst->report.RPIHistogram.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->report.RPIHistogram.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->report.RPIHistogram.rpi0_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi1_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi2_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi3_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi4_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi5_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi6_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.RPIHistogram.rpi7_density = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + break; + case 5: + pDst->report.Beacon.regClass = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.Beacon.channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohq(pCtx, &pDst->report.Beacon.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->report.Beacon.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp46__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->report.Beacon.condensed_PHY = tmp46__ >> 0 & 0x7f; + pDst->report.Beacon.reported_frame_type = tmp46__ >> 7 & 0x1; + pDst->report.Beacon.RCPI = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->report.Beacon.RSNI = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->report.Beacon.BSSID, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + pDst->report.Beacon.antenna_id = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohl(pCtx, &pDst->report.Beacon.parent_TSF, pBuf, 0); + pBuf += 4; + ielen -= (tANI_U8)4; + status |= UnpackCore(pCtx, + pBuf, + ielen, + FFS_reportBeacon, + IES_reportBeacon, + ( tANI_U8* )pDst, + sizeof(*pDst)); + break; + } + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeMeasurementReport. */ + +#define SigIeMeasurementReport ( 0x0038 ) + + +static const tFFDefn FFS_measurement_requestBeacon[ ] = { +{ NULL, 0, 0, 0,}, +}; + +static const tIEDefn IES_measurement_requestBeacon[ ] = { + {offsetof(tDot11fIEMeasurementRequest, measurement_request.Beacon.SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 0, }, + {offsetof(tDot11fIEMeasurementRequest, measurement_request.Beacon.BeaconReporting), offsetof(tDot11fIEBeaconReporting, present), 0, "BeaconReporting" , 0, 4, 4, SigIeBeaconReporting, {0, 0, 0, 0, 0}, 0, DOT11F_EID_BEACONREPORTING, 0, }, + {offsetof(tDot11fIEMeasurementRequest, measurement_request.Beacon.BcnReportingDetail), offsetof(tDot11fIEBcnReportingDetail, present), 0, "BcnReportingDetail" , 0, 3, 3, SigIeBcnReportingDetail, {0, 0, 0, 0, 0}, 0, DOT11F_EID_BCNREPORTINGDETAIL, 0, }, + {offsetof(tDot11fIEMeasurementRequest, measurement_request.Beacon.RequestedInfo), offsetof(tDot11fIERequestedInfo, present), 0, "RequestedInfo" , 0, 2, 257, SigIeRequestedInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_REQUESTEDINFO, 0, }, + {offsetof(tDot11fIEMeasurementRequest, measurement_request.Beacon.APChannelReport), offsetof(tDot11fIEAPChannelReport, present), offsetof(tDot11fIEMeasurementRequest, measurement_request.Beacon.num_APChannelReport), "APChannelReport" , 2, 3, 53, SigIeAPChannelReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_APCHANNELREPORT, 0, }, +{0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, +}; + +tANI_U32 dot11fUnpackIeMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMeasurementRequest *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp47__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->measurement_token = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp47__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->parallel = tmp47__ >> 0 & 0x1; + pDst->enable = tmp47__ >> 1 & 0x1; + pDst->request = tmp47__ >> 2 & 0x1; + pDst->report = tmp47__ >> 3 & 0x1; + pDst->durationMandatory = tmp47__ >> 4 & 0x1; + pDst->unused = tmp47__ >> 5 & 0x7; + pDst->measurement_type = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + switch (pDst->measurement_type) + { + case 0: + pDst->measurement_request.Basic.channel_no = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.Basic.meas_start_time, pBuf, 8); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->measurement_request.Basic.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + case 1: + pDst->measurement_request.CCA.channel_no = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.CCA.meas_start_time, pBuf, 8); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->measurement_request.CCA.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + case 2: + pDst->measurement_request.RPIHistogram.channel_no = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.RPIHistogram.meas_start_time, pBuf, 8); + pBuf += 8; + ielen -= (tANI_U8)8; + framesntohs(pCtx, &pDst->measurement_request.RPIHistogram.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + case 5: + pDst->measurement_request.Beacon.regClass = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->measurement_request.Beacon.channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->measurement_request.Beacon.randomization, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->measurement_request.Beacon.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->measurement_request.Beacon.meas_mode = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.Beacon.BSSID, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + status |= UnpackCore(pCtx, + pBuf, + ielen, + FFS_measurement_requestBeacon, + IES_measurement_requestBeacon, + ( tANI_U8* )pDst, + sizeof(*pDst)); + break; + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeMeasurementRequest. */ + +#define SigIeMeasurementRequest ( 0x0039 ) + + +tANI_U32 dot11fUnpackIeMobilityDomain(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMobilityDomain *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp48__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->MDID, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp48__ = *pBuf; + pDst->overDSCap = tmp48__ >> 0 & 0x1; + pDst->resourceReqCap = tmp48__ >> 1 & 0x1; + pDst->reserved = tmp48__ >> 2 & 0x3f; + (void)pCtx; + return status; +} /* End dot11fUnpackIeMobilityDomain. */ + +#define SigIeMobilityDomain ( 0x003a ) + + + static const tFFDefn FFS_NeighborReport[ ] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_NeighborReport[ ] = { + {offsetof(tDot11fIENeighborReport, TSFInfo), offsetof(tDot11fIETSFInfo, present), 0, "TSFInfo" , 0, 6, 6, SigIeTSFInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TSFINFO, 0, }, + {offsetof(tDot11fIENeighborReport, CondensedCountryStr), offsetof(tDot11fIECondensedCountryStr, present), 0, "CondensedCountryStr" , 0, 4, 4, SigIeCondensedCountryStr, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CONDENSEDCOUNTRYSTR, 0, }, + {offsetof(tDot11fIENeighborReport, MeasurementPilot), offsetof(tDot11fIEMeasurementPilot, present), 0, "MeasurementPilot" , 0, 3, 258, SigIeMeasurementPilot, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MEASUREMENTPILOT, 0, }, + {offsetof(tDot11fIENeighborReport, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fIENeighborReport, MultiBssid), offsetof(tDot11fIEMultiBssid, present), 0, "MultiBssid" , 0, 3, 258, SigIeMultiBssid, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MULTIBSSID, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, + }; + +tANI_U32 dot11fUnpackIeNeighborReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIENeighborReport *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp49__; + tANI_U8 tmp50__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->bssid, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + tmp49__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->APReachability = tmp49__ >> 0 & 0x3; + pDst->Security = tmp49__ >> 2 & 0x1; + pDst->KeyScope = tmp49__ >> 3 & 0x1; + pDst->SpecMgmtCap = tmp49__ >> 4 & 0x1; + pDst->QosCap = tmp49__ >> 5 & 0x1; + pDst->apsd = tmp49__ >> 6 & 0x1; + pDst->rrm = tmp49__ >> 7 & 0x1; + tmp50__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->DelayedBA = tmp50__ >> 0 & 0x1; + pDst->ImmBA = tmp50__ >> 1 & 0x1; + pDst->MobilityDomain = tmp50__ >> 2 & 0x1; + pDst->reserved = tmp50__ >> 3 & 0x1f; + framesntohs(pCtx, &pDst->reserved1, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->PhyType = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + (void)pCtx; + status |= UnpackCore(pCtx, + pBuf, + ielen, + FFS_NeighborReport, + IES_NeighborReport, + ( tANI_U8* )pDst, + sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeNeighborReport. */ + +#define SigIeNeighborReport ( 0x003b ) + + +tANI_U32 dot11fUnpackIeOBSSScanParameters(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEOBSSScanParameters *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->obssScanPassiveDwell, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->obssScanActiveDwell, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->bssChannelWidthTriggerScanInterval, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->obssScanPassiveTotalPerChannel, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->obssScanActiveTotalPerChannel, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->bssWidthChannelTransitionDelayFactor, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->obssScanActivityThreshold, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeOBSSScanParameters. */ + +#define SigIeOBSSScanParameters ( 0x003c ) + + +tANI_U32 dot11fUnpackIeOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEOperatingMode *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp51__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp51__ = *pBuf; + pDst->chanWidth = tmp51__ >> 0 & 0x3; + pDst->reserved = tmp51__ >> 2 & 0x3; + pDst->rxNSS = tmp51__ >> 4 & 0x7; + pDst->rxNSSType = tmp51__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeOperatingMode. */ + +#define SigIeOperatingMode ( 0x003d ) + + + static const tTLVDefn TLVS_P2PAssocReq[ ] = { + {offsetof(tDot11fIEP2PAssocReq, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PAssocReq, ExtendedListenTiming), offsetof(tDot11fTLVExtendedListenTiming, present), "ExtendedListenTiming", SigTlvExtendedListenTiming, DOT11F_TLV_EXTENDEDLISTENTIMING, 0, 7, 7, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PAssocReq, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PAssocReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PAssocReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PAssocReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PAssocReq. */ + +#define SigIeP2PAssocReq ( 0x003e ) + + + static const tTLVDefn TLVS_P2PAssocRes[ ] = { + {offsetof(tDot11fIEP2PAssocRes, P2PStatus), offsetof(tDot11fTLVP2PStatus, present), "P2PStatus", SigTlvP2PStatus, DOT11F_TLV_P2PSTATUS, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PAssocRes, ExtendedListenTiming), offsetof(tDot11fTLVExtendedListenTiming, present), "ExtendedListenTiming", SigTlvExtendedListenTiming, DOT11F_TLV_EXTENDEDLISTENTIMING, 0, 7, 7, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PAssocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PAssocRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PAssocRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PAssocRes. */ + +#define SigIeP2PAssocRes ( 0x003f ) + + + static const tTLVDefn TLVS_P2PBeacon[ ] = { + {offsetof(tDot11fIEP2PBeacon, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeacon, P2PDeviceId), offsetof(tDot11fTLVP2PDeviceId, present), "P2PDeviceId", SigTlvP2PDeviceId, DOT11F_TLV_P2PDEVICEID, 0, 9, 9, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeacon, NoticeOfAbsence), offsetof(tDot11fTLVNoticeOfAbsence, present), "NoticeOfAbsence", SigTlvNoticeOfAbsence, DOT11F_TLV_NOTICEOFABSENCE, 0, 5, 41, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PBeacon *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PBeacon,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PBeacon. */ + +#define SigIeP2PBeacon ( 0x0040 ) + + + static const tTLVDefn TLVS_P2PBeaconProbeRes[ ] = { + {offsetof(tDot11fIEP2PBeaconProbeRes, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeaconProbeRes, P2PDeviceId), offsetof(tDot11fTLVP2PDeviceId, present), "P2PDeviceId", SigTlvP2PDeviceId, DOT11F_TLV_P2PDEVICEID, 0, 9, 9, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeaconProbeRes, ExtendedListenTiming), offsetof(tDot11fTLVExtendedListenTiming, present), "ExtendedListenTiming", SigTlvExtendedListenTiming, DOT11F_TLV_EXTENDEDLISTENTIMING, 0, 7, 7, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeaconProbeRes, NoticeOfAbsence), offsetof(tDot11fTLVNoticeOfAbsence, present), "NoticeOfAbsence", SigTlvNoticeOfAbsence, DOT11F_TLV_NOTICEOFABSENCE, 0, 5, 41, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeaconProbeRes, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PBeaconProbeRes, P2PGroupInfo), offsetof(tDot11fTLVP2PGroupInfo, present), "P2PGroupInfo", SigTlvP2PGroupInfo, DOT11F_TLV_P2PGROUPINFO, 0, 3, 1027, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PBeaconProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PBeaconProbeRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PBeaconProbeRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PBeaconProbeRes. */ + +#define SigIeP2PBeaconProbeRes ( 0x0041 ) + + + static const tTLVDefn TLVS_P2PDeAuth[ ] = { + {offsetof(tDot11fIEP2PDeAuth, MinorReasonCode), offsetof(tDot11fTLVMinorReasonCode, present), "MinorReasonCode", SigTlvMinorReasonCode, DOT11F_TLV_MINORREASONCODE, 0, 4, 4, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PDeAuth(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PDeAuth *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PDeAuth,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PDeAuth. */ + +#define SigIeP2PDeAuth ( 0x0042 ) + + + static const tTLVDefn TLVS_P2PDeviceDiscoverabilityReq[ ] = { + {offsetof(tDot11fIEP2PDeviceDiscoverabilityReq, P2PDeviceId), offsetof(tDot11fTLVP2PDeviceId, present), "P2PDeviceId", SigTlvP2PDeviceId, DOT11F_TLV_P2PDEVICEID, 0, 9, 9, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PDeviceDiscoverabilityReq, P2PGroupId), offsetof(tDot11fTLVP2PGroupId, present), "P2PGroupId", SigTlvP2PGroupId, DOT11F_TLV_P2PGROUPID, 0, 9, 41, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PDeviceDiscoverabilityReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PDeviceDiscoverabilityReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PDeviceDiscoverabilityReq. */ + +#define SigIeP2PDeviceDiscoverabilityReq ( 0x0043 ) + + + static const tTLVDefn TLVS_P2PDeviceDiscoverabilityRes[ ] = { + {offsetof(tDot11fIEP2PDeviceDiscoverabilityRes, P2PStatus), offsetof(tDot11fTLVP2PStatus, present), "P2PStatus", SigTlvP2PStatus, DOT11F_TLV_P2PSTATUS, 0, 4, 4, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PDeviceDiscoverabilityRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PDeviceDiscoverabilityRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PDeviceDiscoverabilityRes. */ + +#define SigIeP2PDeviceDiscoverabilityRes ( 0x0044 ) + + + static const tTLVDefn TLVS_P2PDisAssoc[ ] = { + {offsetof(tDot11fIEP2PDisAssoc, MinorReasonCode), offsetof(tDot11fTLVMinorReasonCode, present), "MinorReasonCode", SigTlvMinorReasonCode, DOT11F_TLV_MINORREASONCODE, 0, 4, 4, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PDisAssoc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PDisAssoc *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PDisAssoc,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PDisAssoc. */ + +#define SigIeP2PDisAssoc ( 0x0045 ) + + + static const tTLVDefn TLVS_P2PGONegCnf[ ] = { + {offsetof(tDot11fIEP2PGONegCnf, P2PStatus), offsetof(tDot11fTLVP2PStatus, present), "P2PStatus", SigTlvP2PStatus, DOT11F_TLV_P2PSTATUS, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegCnf, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegCnf, OperatingChannel), offsetof(tDot11fTLVOperatingChannel, present), "OperatingChannel", SigTlvOperatingChannel, DOT11F_TLV_OPERATINGCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegCnf, ChannelList), offsetof(tDot11fTLVChannelList, present), "ChannelList", SigTlvChannelList, DOT11F_TLV_CHANNELLIST, 0, 6, 257, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegCnf, P2PGroupId), offsetof(tDot11fTLVP2PGroupId, present), "P2PGroupId", SigTlvP2PGroupId, DOT11F_TLV_P2PGROUPID, 0, 9, 41, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PGONegCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PGONegCnf *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PGONegCnf,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PGONegCnf. */ + +#define SigIeP2PGONegCnf ( 0x0046 ) + + + static const tTLVDefn TLVS_P2PGONegReq[ ] = { + {offsetof(tDot11fIEP2PGONegReq, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, GOIntent), offsetof(tDot11fTLVGOIntent, present), "GOIntent", SigTlvGOIntent, DOT11F_TLV_GOINTENT, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, ConfigurationTimeout), offsetof(tDot11fTLVConfigurationTimeout, present), "ConfigurationTimeout", SigTlvConfigurationTimeout, DOT11F_TLV_CONFIGURATIONTIMEOUT, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, ListenChannel), offsetof(tDot11fTLVListenChannel, present), "ListenChannel", SigTlvListenChannel, DOT11F_TLV_LISTENCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, ExtendedListenTiming), offsetof(tDot11fTLVExtendedListenTiming, present), "ExtendedListenTiming", SigTlvExtendedListenTiming, DOT11F_TLV_EXTENDEDLISTENTIMING, 0, 7, 7, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, IntendedP2PInterfaceAddress), offsetof(tDot11fTLVIntendedP2PInterfaceAddress, present), "IntendedP2PInterfaceAddress", SigTlvIntendedP2PInterfaceAddress, DOT11F_TLV_INTENDEDP2PINTERFACEADDRESS, 0, 9, 9, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, ChannelList), offsetof(tDot11fTLVChannelList, present), "ChannelList", SigTlvChannelList, DOT11F_TLV_CHANNELLIST, 0, 6, 257, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegReq, OperatingChannel), offsetof(tDot11fTLVOperatingChannel, present), "OperatingChannel", SigTlvOperatingChannel, DOT11F_TLV_OPERATINGCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PGONegReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PGONegReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PGONegReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PGONegReq. */ + +#define SigIeP2PGONegReq ( 0x0047 ) + + + static const tTLVDefn TLVS_P2PGONegRes[ ] = { + {offsetof(tDot11fIEP2PGONegRes, P2PStatus), offsetof(tDot11fTLVP2PStatus, present), "P2PStatus", SigTlvP2PStatus, DOT11F_TLV_P2PSTATUS, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, GOIntent), offsetof(tDot11fTLVGOIntent, present), "GOIntent", SigTlvGOIntent, DOT11F_TLV_GOINTENT, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, ConfigurationTimeout), offsetof(tDot11fTLVConfigurationTimeout, present), "ConfigurationTimeout", SigTlvConfigurationTimeout, DOT11F_TLV_CONFIGURATIONTIMEOUT, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, OperatingChannel), offsetof(tDot11fTLVOperatingChannel, present), "OperatingChannel", SigTlvOperatingChannel, DOT11F_TLV_OPERATINGCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, IntendedP2PInterfaceAddress), offsetof(tDot11fTLVIntendedP2PInterfaceAddress, present), "IntendedP2PInterfaceAddress", SigTlvIntendedP2PInterfaceAddress, DOT11F_TLV_INTENDEDP2PINTERFACEADDRESS, 0, 9, 9, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, ChannelList), offsetof(tDot11fTLVChannelList, present), "ChannelList", SigTlvChannelList, DOT11F_TLV_CHANNELLIST, 0, 6, 257, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PGONegRes, P2PGroupId), offsetof(tDot11fTLVP2PGroupId, present), "P2PGroupId", SigTlvP2PGroupId, DOT11F_TLV_P2PGROUPID, 0, 9, 41, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PGONegRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PGONegRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PGONegRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PGONegRes. */ + +#define SigIeP2PGONegRes ( 0x0048 ) + + + static const tTLVDefn TLVS_P2PGONegWPS[ ] = { + {offsetof(tDot11fIEP2PGONegWPS, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEP2PGONegWPS, DevicePasswordID), offsetof(tDot11fTLVDevicePasswordID, present), "DevicePasswordID", SigTlvDevicePasswordID, DOT11F_TLV_DEVICEPASSWORDID, 0, 6, 6, 1, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PGONegWPS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PGONegWPS *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PGONegWPS,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PGONegWPS. */ + +#define SigIeP2PGONegWPS ( 0x0049 ) + + +tANI_U32 dot11fUnpackIeP2PIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PIEOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 249){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeP2PIEOpaque. */ + +#define SigIeP2PIEOpaque ( 0x004a ) + + + static const tTLVDefn TLVS_P2PInvitationReq[ ] = { + {offsetof(tDot11fIEP2PInvitationReq, ConfigurationTimeout), offsetof(tDot11fTLVConfigurationTimeout, present), "ConfigurationTimeout", SigTlvConfigurationTimeout, DOT11F_TLV_CONFIGURATIONTIMEOUT, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationReq, InvitationFlags), offsetof(tDot11fTLVInvitationFlags, present), "InvitationFlags", SigTlvInvitationFlags, DOT11F_TLV_INVITATIONFLAGS, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationReq, OperatingChannel), offsetof(tDot11fTLVOperatingChannel, present), "OperatingChannel", SigTlvOperatingChannel, DOT11F_TLV_OPERATINGCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationReq, P2PGroupBssid), offsetof(tDot11fTLVP2PGroupBssid, present), "P2PGroupBssid", SigTlvP2PGroupBssid, DOT11F_TLV_P2PGROUPBSSID, 0, 9, 9, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationReq, ChannelList), offsetof(tDot11fTLVChannelList, present), "ChannelList", SigTlvChannelList, DOT11F_TLV_CHANNELLIST, 0, 6, 257, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationReq, P2PGroupId), offsetof(tDot11fTLVP2PGroupId, present), "P2PGroupId", SigTlvP2PGroupId, DOT11F_TLV_P2PGROUPID, 0, 9, 41, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationReq, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PInvitationReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PInvitationReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PInvitationReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PInvitationReq. */ + +#define SigIeP2PInvitationReq ( 0x004b ) + + + static const tTLVDefn TLVS_P2PInvitationRes[ ] = { + {offsetof(tDot11fIEP2PInvitationRes, P2PStatus), offsetof(tDot11fTLVP2PStatus, present), "P2PStatus", SigTlvP2PStatus, DOT11F_TLV_P2PSTATUS, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationRes, ConfigurationTimeout), offsetof(tDot11fTLVConfigurationTimeout, present), "ConfigurationTimeout", SigTlvConfigurationTimeout, DOT11F_TLV_CONFIGURATIONTIMEOUT, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationRes, OperatingChannel), offsetof(tDot11fTLVOperatingChannel, present), "OperatingChannel", SigTlvOperatingChannel, DOT11F_TLV_OPERATINGCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationRes, P2PGroupBssid), offsetof(tDot11fTLVP2PGroupBssid, present), "P2PGroupBssid", SigTlvP2PGroupBssid, DOT11F_TLV_P2PGROUPBSSID, 0, 9, 9, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PInvitationRes, ChannelList), offsetof(tDot11fTLVChannelList, present), "ChannelList", SigTlvChannelList, DOT11F_TLV_CHANNELLIST, 0, 6, 257, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PInvitationRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PInvitationRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PInvitationRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PInvitationRes. */ + +#define SigIeP2PInvitationRes ( 0x004c ) + + + static const tTLVDefn TLVS_P2PNoticeOfAbsence[ ] = { + {offsetof(tDot11fIEP2PNoticeOfAbsence, NoticeOfAbsence), offsetof(tDot11fTLVNoticeOfAbsence, present), "NoticeOfAbsence", SigTlvNoticeOfAbsence, DOT11F_TLV_NOTICEOFABSENCE, 0, 5, 41, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PNoticeOfAbsence(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PNoticeOfAbsence *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PNoticeOfAbsence,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PNoticeOfAbsence. */ + +#define SigIeP2PNoticeOfAbsence ( 0x004d ) + + + static const tTLVDefn TLVS_P2PPresenceResponse[ ] = { + {offsetof(tDot11fIEP2PPresenceResponse, P2PStatus), offsetof(tDot11fTLVP2PStatus, present), "P2PStatus", SigTlvP2PStatus, DOT11F_TLV_P2PSTATUS, 0, 4, 4, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PPresenceResponse, NoticeOfAbsence), offsetof(tDot11fTLVNoticeOfAbsence, present), "NoticeOfAbsence", SigTlvNoticeOfAbsence, DOT11F_TLV_NOTICEOFABSENCE, 0, 5, 41, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PPresenceResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PPresenceResponse *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PPresenceResponse,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PPresenceResponse. */ + +#define SigIeP2PPresenceResponse ( 0x004e ) + + + static const tTLVDefn TLVS_P2PProbeReq[ ] = { + {offsetof(tDot11fIEP2PProbeReq, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeReq, P2PDeviceId), offsetof(tDot11fTLVP2PDeviceId, present), "P2PDeviceId", SigTlvP2PDeviceId, DOT11F_TLV_P2PDEVICEID, 0, 9, 9, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeReq, ListenChannel), offsetof(tDot11fTLVListenChannel, present), "ListenChannel", SigTlvListenChannel, DOT11F_TLV_LISTENCHANNEL, 0, 8, 8, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeReq, ExtendedListenTiming), offsetof(tDot11fTLVExtendedListenTiming, present), "ExtendedListenTiming", SigTlvExtendedListenTiming, DOT11F_TLV_EXTENDEDLISTENTIMING, 0, 7, 7, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeReq, OperatingChannel), offsetof(tDot11fTLVOperatingChannel, present), "OperatingChannel", SigTlvOperatingChannel, DOT11F_TLV_OPERATINGCHANNEL, 0, 8, 8, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PProbeReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PProbeReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PProbeReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PProbeReq. */ + +#define SigIeP2PProbeReq ( 0x004f ) + + + static const tTLVDefn TLVS_P2PProbeRes[ ] = { + {offsetof(tDot11fIEP2PProbeRes, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeRes, ExtendedListenTiming), offsetof(tDot11fTLVExtendedListenTiming, present), "ExtendedListenTiming", SigTlvExtendedListenTiming, DOT11F_TLV_EXTENDEDLISTENTIMING, 0, 7, 7, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeRes, NoticeOfAbsence), offsetof(tDot11fTLVNoticeOfAbsence, present), "NoticeOfAbsence", SigTlvNoticeOfAbsence, DOT11F_TLV_NOTICEOFABSENCE, 0, 5, 41, 0, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeRes, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProbeRes, P2PGroupInfo), offsetof(tDot11fTLVP2PGroupInfo, present), "P2PGroupInfo", SigTlvP2PGroupInfo, DOT11F_TLV_P2PGROUPINFO, 0, 3, 1027, 0, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PProbeRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PProbeRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PProbeRes. */ + +#define SigIeP2PProbeRes ( 0x0050 ) + + + static const tTLVDefn TLVS_P2PProvisionDiscoveryReq[ ] = { + {offsetof(tDot11fIEP2PProvisionDiscoveryReq, P2PCapability), offsetof(tDot11fTLVP2PCapability, present), "P2PCapability", SigTlvP2PCapability, DOT11F_TLV_P2PCAPABILITY, 0, 5, 5, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProvisionDiscoveryReq, P2PDeviceInfo), offsetof(tDot11fTLVP2PDeviceInfo, present), "P2PDeviceInfo", SigTlvP2PDeviceInfo, DOT11F_TLV_P2PDEVICEINFO, 0, 19, 55, 1, 1, 2, 0, }, + {offsetof(tDot11fIEP2PProvisionDiscoveryReq, P2PGroupId), offsetof(tDot11fTLVP2PGroupId, present), "P2PGroupId", SigTlvP2PGroupId, DOT11F_TLV_P2PGROUPID, 0, 9, 41, 1, 1, 2, 0, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PProvisionDiscoveryReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PProvisionDiscoveryReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PProvisionDiscoveryReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PProvisionDiscoveryReq. */ + +#define SigIeP2PProvisionDiscoveryReq ( 0x0051 ) + + + static const tTLVDefn TLVS_P2PWSCProvisionDiscoveryRes[ ] = { + {offsetof(tDot11fIEP2PWSCProvisionDiscoveryRes, ConfigMethods), offsetof(tDot11fTLVConfigMethods, present), "ConfigMethods", SigTlvConfigMethods, DOT11F_TLV_CONFIGMETHODS, 0, 6, 6, 1, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeP2PWSCProvisionDiscoveryRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PWSCProvisionDiscoveryRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_P2PWSCProvisionDiscoveryRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeP2PWSCProvisionDiscoveryRes. */ + +#define SigIeP2PWSCProvisionDiscoveryRes ( 0x0052 ) + + +tANI_U32 dot11fUnpackIePTIControl(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPTIControl *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->tid = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->sequence_control, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIePTIControl. */ + +#define SigIePTIControl ( 0x0053 ) + + +tANI_U32 dot11fUnpackIePUBufferStatus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPUBufferStatus *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp52__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp52__ = *pBuf; + pDst->ac_bk_traffic_aval = tmp52__ >> 0 & 0x1; + pDst->ac_be_traffic_aval = tmp52__ >> 1 & 0x1; + pDst->ac_vi_traffic_aval = tmp52__ >> 2 & 0x1; + pDst->ac_vo_traffic_aval = tmp52__ >> 3 & 0x1; + pDst->reserved = tmp52__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11fUnpackIePUBufferStatus. */ + +#define SigIePUBufferStatus ( 0x0054 ) + + +tANI_U32 dot11fUnpackIePowerCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPowerCaps *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->minTxPower = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->maxTxPower = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIePowerCaps. */ + +#define SigIePowerCaps ( 0x0055 ) + + +tANI_U32 dot11fUnpackIePowerConstraints(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPowerConstraints *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->localPowerConstraints = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIePowerConstraints. */ + +#define SigIePowerConstraints ( 0x0056 ) + + +tANI_U32 dot11fUnpackIeQBSSLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQBSSLoad *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->stacount, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + pDst->chautil = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->avail, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeQBSSLoad. */ + +#define SigIeQBSSLoad ( 0x0057 ) + + +tANI_U32 dot11fUnpackIeQComVendorIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQComVendorIE *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->type = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->channel = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeQComVendorIE. */ + +#define SigIeQComVendorIE ( 0x0058 ) + + +tANI_U32 dot11fUnpackIeQOSCapsAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQOSCapsAp *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp53__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp53__ = *pBuf; + pDst->count = tmp53__ >> 0 & 0xf; + pDst->qack = tmp53__ >> 4 & 0x1; + pDst->qreq = tmp53__ >> 5 & 0x1; + pDst->txopreq = tmp53__ >> 6 & 0x1; + pDst->reserved = tmp53__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeQOSCapsAp. */ + +#define SigIeQOSCapsAp ( 0x0059 ) + + +tANI_U32 dot11fUnpackIeQOSCapsStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQOSCapsStation *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp54__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp54__ = *pBuf; + pDst->acvo_uapsd = tmp54__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp54__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp54__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp54__ >> 3 & 0x1; + pDst->qack = tmp54__ >> 4 & 0x1; + pDst->max_sp_length = tmp54__ >> 5 & 0x3; + pDst->more_data_ack = tmp54__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeQOSCapsStation. */ + +#define SigIeQOSCapsStation ( 0x005a ) + + +tANI_U32 dot11fUnpackIeQosMapSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQosMapSet *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_dscp_exceptions = (tANI_U8)( ielen ); + if (ielen > 60){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->dscp_exceptions, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeQosMapSet. */ + +#define SigIeQosMapSet ( 0x005b ) + + +tANI_U32 dot11fUnpackIeQuiet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQuiet *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->count = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->period = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->duration, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &pDst->offset, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeQuiet. */ + +#define SigIeQuiet ( 0x005c ) + + +tANI_U32 dot11fUnpackIeRCPIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERCPIIE *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->rcpi = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeRCPIIE. */ + +#define SigIeRCPIIE ( 0x005d ) + + + static const tFFDefn FFS_RICDataDesc[ ] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_RICDataDesc[ ] = { + {offsetof(tDot11fIERICDataDesc, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 1, }, + {offsetof(tDot11fIERICDataDesc, RICDescriptor), offsetof(tDot11fIERICDescriptor, present), 0, "RICDescriptor" , 0, 3, 258, SigIeRICDescriptor, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDESCRIPTOR, 0, }, + {offsetof(tDot11fIERICDataDesc, TSPEC), offsetof(tDot11fIETSPEC, present), 0, "TSPEC" , 0, 57, 57, SigIeTSPEC, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TSPEC, 0, }, + {offsetof(tDot11fIERICDataDesc, TCLAS), offsetof(tDot11fIETCLAS, present), offsetof(tDot11fIERICDataDesc, num_TCLAS), "TCLAS" , 2, 7, 45, SigIeTCLAS, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TCLAS, 0, }, + {offsetof(tDot11fIERICDataDesc, TCLASSPROC), offsetof(tDot11fIETCLASSPROC, present), 0, "TCLASSPROC" , 0, 3, 3, SigIeTCLASSPROC, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TCLASSPROC, 0, }, + {offsetof(tDot11fIERICDataDesc, TSDelay), offsetof(tDot11fIETSDelay, present), 0, "TSDelay" , 0, 6, 6, SigIeTSDelay, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TSDELAY, 0, }, + {offsetof(tDot11fIERICDataDesc, Schedule), offsetof(tDot11fIESchedule, present), 0, "Schedule" , 0, 16, 16, SigIeSchedule, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SCHEDULE, 0, }, + {offsetof(tDot11fIERICDataDesc, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), 0, "WMMTSPEC" , 0, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fIERICDataDesc, WMMTCLAS), offsetof(tDot11fIEWMMTCLAS, present), offsetof(tDot11fIERICDataDesc, num_WMMTCLAS), "WMMTCLAS" , 2, 13, 51, SigIeWMMTCLAS, {0, 80, 242, 2, 6}, 5, DOT11F_EID_WMMTCLAS, 0, }, + {offsetof(tDot11fIERICDataDesc, WMMTCLASPROC), offsetof(tDot11fIEWMMTCLASPROC, present), 0, "WMMTCLASPROC" , 0, 9, 9, SigIeWMMTCLASPROC, {0, 80, 242, 2, 7}, 5, DOT11F_EID_WMMTCLASPROC, 0, }, + {offsetof(tDot11fIERICDataDesc, WMMTSDelay), offsetof(tDot11fIEWMMTSDelay, present), 0, "WMMTSDelay" , 0, 12, 12, SigIeWMMTSDelay, {0, 80, 242, 2, 8}, 5, DOT11F_EID_WMMTSDELAY, 0, }, + {offsetof(tDot11fIERICDataDesc, WMMSchedule), offsetof(tDot11fIEWMMSchedule, present), 0, "WMMSchedule" , 0, 22, 22, SigIeWMMSchedule, {0, 80, 242, 2, 9}, 5, DOT11F_EID_WMMSCHEDULE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, + }; + +tANI_U32 dot11fUnpackIeRICDataDesc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICDataDesc *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + status |= UnpackCore(pCtx, + pBuf, + ielen, + FFS_RICDataDesc, + IES_RICDataDesc, + ( tANI_U8* )pDst, + sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeRICDataDesc. */ + +#define SigIeRICDataDesc ( 0x005e ) + + +tANI_U32 dot11fUnpackIeRSN(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSN *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->version, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + DOT11F_MEMCPY(pCtx, pDst->gp_cipher_suite, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + if ( ! ielen ) + { + pDst->pwise_cipher_suite_count = 0U; + pDst->akm_suite_count = 0U; + pDst->pmkid_count = 0U; + return 0U; + } + else + { + framesntohs(pCtx, &pDst->pwise_cipher_suite_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if (pDst->pwise_cipher_suite_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->pwise_cipher_suites, pBuf, ( pDst->pwise_cipher_suite_count * 4 ) ); + pBuf += ( pDst->pwise_cipher_suite_count * 4 ); + ielen -= ( pDst->pwise_cipher_suite_count * 4 ); + if ( ! ielen ) + { + pDst->akm_suite_count = 0U; + pDst->pmkid_count = 0U; + return 0U; + } + else + { + framesntohs(pCtx, &pDst->akm_suite_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if (pDst->akm_suite_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->akm_suites, pBuf, ( pDst->akm_suite_count * 4 ) ); + pBuf += ( pDst->akm_suite_count * 4 ); + ielen -= ( pDst->akm_suite_count * 4 ); + if ( ! ielen ) + { + pDst->pmkid_count = 0U; + return 0U; + } + else + { + DOT11F_MEMCPY(pCtx, pDst->RSN_Cap, pBuf, 2); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if ( ! ielen ) + { + pDst->pmkid_count = 0U; + return 0U; + } + else + { + framesntohs(pCtx, &pDst->pmkid_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if (pDst->pmkid_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->pmkid, pBuf, ( pDst->pmkid_count * 16 ) ); + pBuf += ( pDst->pmkid_count * 16 ); + ielen -= ( pDst->pmkid_count * 16 ); + if ( ! ielen ) + { + return 0U; + } + else + { + DOT11F_MEMCPY(pCtx, pDst->gp_mgmt_cipher_suite, pBuf, 4); + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeRSN. */ + +#define SigIeRSN ( 0x005f ) + + +tANI_U32 dot11fUnpackIeRSNIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSNIIE *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->rsni = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeRSNIIE. */ + +#define SigIeRSNIIE ( 0x0060 ) + + +tANI_U32 dot11fUnpackIeRSNOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSNOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 253){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeRSNOpaque. */ + +#define SigIeRSNOpaque ( 0x0061 ) + + +tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppChannels *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_bands = (tANI_U8)( ielen / 2 ); + if (ielen > 48 * 2){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->bands, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeSuppChannels. */ + +#define SigIeSuppChannels ( 0x0062 ) + + +tANI_U32 dot11fUnpackIeSuppOperatingClasses(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppOperatingClasses *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_classes = (tANI_U8)( ielen ); + if (ielen > 32){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->classes, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeSuppOperatingClasses. */ + +#define SigIeSuppOperatingClasses ( 0x0063 ) + + +tANI_U32 dot11fUnpackIeSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppRates *pDst) +{ + tANI_U8 i; + tANI_U8 rate_indx = 0; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + for (i = 0; i < ielen; i++) { + if ((DOT11F_IS_BG_RATE(pBuf[i] & 0x7F)) && + (rate_indx < 12)) { + pDst->rates[rate_indx++] = pBuf[i]; + } + } + + if(rate_indx == 0) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + pDst->num_rates = rate_indx; + (void)pCtx; + return status; +} /* End dot11fUnpackIeSuppRates. */ + +#define SigIeSuppRates ( 0x0064 ) + + +tANI_U32 dot11fUnpackIeTIM(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETIM *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->dtim_count = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->dtim_period = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->bmpctl = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->num_vbmp = (tANI_U8)( ielen ); + if (ielen > 251){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->vbmp, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeTIM. */ + +#define SigIeTIM ( 0x0065 ) + + +tANI_U32 dot11fUnpackIeTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETPCReport *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->tx_power = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->link_margin = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeTPCReport. */ + +#define SigIeTPCReport ( 0x0066 ) + + +tANI_U32 dot11fUnpackIeTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETPCRequest *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeTPCRequest. */ + +#define SigIeTPCRequest ( 0x0067 ) + + +tANI_U32 dot11fUnpackIeTimeAdvertisement(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETimeAdvertisement *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->timing_capabilities = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->time_value, pBuf, 10); + pBuf += 10; + ielen -= (tANI_U8)10; + DOT11F_MEMCPY(pCtx, pDst->time_error, pBuf, 5); + (void)pCtx; + return status; +} /* End dot11fUnpackIeTimeAdvertisement. */ + +#define SigIeTimeAdvertisement ( 0x0068 ) + + +tANI_U32 dot11fUnpackIeTimeoutInterval(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETimeoutInterval *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->timeoutType = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohl(pCtx, &pDst->timeoutValue, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeTimeoutInterval. */ + +#define SigIeTimeoutInterval ( 0x0069 ) + + +tANI_U32 dot11fUnpackIeVHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTCaps *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 tmp55__; + tANI_U16 tmp56__; + tANI_U16 tmp57__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohl(pCtx, &tmp55__, pBuf, 0); + pBuf += 4; + ielen -= 4; + pDst->maxMPDULen = tmp55__ >> 0 & 0x3; + pDst->supportedChannelWidthSet = tmp55__ >> 2 & 0x3; + pDst->ldpcCodingCap = tmp55__ >> 4 & 0x1; + pDst->shortGI80MHz = tmp55__ >> 5 & 0x1; + pDst->shortGI160and80plus80MHz = tmp55__ >> 6 & 0x1; + pDst->txSTBC = tmp55__ >> 7 & 0x1; + pDst->rxSTBC = tmp55__ >> 8 & 0x7; + pDst->suBeamFormerCap = tmp55__ >> 11 & 0x1; + pDst->suBeamformeeCap = tmp55__ >> 12 & 0x1; + pDst->csnofBeamformerAntSup = tmp55__ >> 13 & 0x7; + pDst->numSoundingDim = tmp55__ >> 16 & 0x7; + pDst->muBeamformerCap = tmp55__ >> 19 & 0x1; + pDst->muBeamformeeCap = tmp55__ >> 20 & 0x1; + pDst->vhtTXOPPS = tmp55__ >> 21 & 0x1; + pDst->htcVHTCap = tmp55__ >> 22 & 0x1; + pDst->maxAMPDULenExp = tmp55__ >> 23 & 0x7; + pDst->vhtLinkAdaptCap = tmp55__ >> 26 & 0x3; + pDst->rxAntPattern = tmp55__ >> 28 & 0x1; + pDst->txAntPattern = tmp55__ >> 29 & 0x1; + pDst->reserved1 = tmp55__ >> 30 & 0x3; + framesntohs(pCtx, &pDst->rxMCSMap, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &tmp56__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->rxHighSupDataRate = tmp56__ >> 0 & 0x1fff; + pDst->reserved2 = tmp56__ >> 13 & 0x7; + framesntohs(pCtx, &pDst->txMCSMap, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + framesntohs(pCtx, &tmp57__, pBuf, 0); + pDst->txSupDataRate = tmp57__ >> 0 & 0x1fff; + pDst->reserved3 = tmp57__ >> 13 & 0x7; + (void)pCtx; + return status; +} /* End dot11fUnpackIeVHTCaps. */ + +#define SigIeVHTCaps ( 0x006a ) + + +tANI_U32 dot11fUnpackIeVHTExtBssLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTExtBssLoad *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->muMIMOCapStaCount = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->ssUnderUtil = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->FortyMHzUtil = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->EightyMHzUtil = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->OneSixtyMHzUtil = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeVHTExtBssLoad. */ + +#define SigIeVHTExtBssLoad ( 0x006b ) + + +tANI_U32 dot11fUnpackIeVHTOperation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTOperation *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->chanWidth = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->chanCenterFreqSeg1 = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->chanCenterFreqSeg2 = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + framesntohs(pCtx, &pDst->basicMCSSet, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeVHTOperation. */ + +#define SigIeVHTOperation ( 0x006c ) + + +tANI_U32 dot11fUnpackIeVendor1IE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVendor1IE *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeVendor1IE. */ + +#define SigIeVendor1IE ( 0x006d ) + + +tANI_U32 dot11fUnpackIeVendor2IE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVendor2IE *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeVendor2IE. */ + +#define SigIeVendor2IE ( 0x006e ) + + +tANI_U32 dot11fUnpackIeVendor3IE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVendor3IE *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeVendor3IE. */ + +#define SigIeVendor3IE ( 0x006f ) + + +tANI_U32 dot11fUnpackIeWAPI(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWAPI *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U16 tmp58__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->version, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + framesntohs(pCtx, &pDst->akm_suite_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + if (pDst->akm_suite_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->akm_suites, pBuf, ( pDst->akm_suite_count * 4 ) ); + pBuf += ( pDst->akm_suite_count * 4 ); + ielen -= ( pDst->akm_suite_count * 4 ); + framesntohs(pCtx, &pDst->unicast_cipher_suite_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + if (pDst->unicast_cipher_suite_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->unicast_cipher_suites, pBuf, ( pDst->unicast_cipher_suite_count * 4 ) ); + pBuf += ( pDst->unicast_cipher_suite_count * 4 ); + ielen -= ( pDst->unicast_cipher_suite_count * 4 ); + DOT11F_MEMCPY(pCtx, pDst->multicast_cipher_suite, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + framesntohs(pCtx, &tmp58__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->preauth = tmp58__ >> 0 & 0x1; + pDst->reserved = tmp58__ >> 1 & 0x7fff; + if ( ! ielen ) + { + pDst->bkid_count = 0U; + return 0U; + } + else + { + framesntohs(pCtx, &pDst->bkid_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if (pDst->bkid_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->bkid, pBuf, ( pDst->bkid_count * 16 ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWAPI. */ + +#define SigIeWAPI ( 0x0070 ) + + +tANI_U32 dot11fUnpackIeWAPIOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWAPIOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 253){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWAPIOpaque. */ + +#define SigIeWAPIOpaque ( 0x0071 ) + + +tANI_U32 dot11fUnpackIeWFATPC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWFATPC *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->txPower = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->linkMargin = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeWFATPC. */ + +#define SigIeWFATPC ( 0x0072 ) + + +tANI_U32 dot11fUnpackIeWFDIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWFDIEOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 249){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWFDIEOpaque. */ + +#define SigIeWFDIEOpaque ( 0x0073 ) + + +tANI_U32 dot11fUnpackIeWMMCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMCaps *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp59__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + tmp59__ = *pBuf; + pDst->reserved = tmp59__ >> 0 & 0xf; + pDst->qack = tmp59__ >> 4 & 0x1; + pDst->queue_request = tmp59__ >> 5 & 0x1; + pDst->txop_request = tmp59__ >> 6 & 0x1; + pDst->more_ack = tmp59__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMCaps. */ + +#define SigIeWMMCaps ( 0x0074 ) + + +tANI_U32 dot11fUnpackIeWMMInfoAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMInfoAp *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp60__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp60__ = *pBuf; + pDst->param_set_count = tmp60__ >> 0 & 0xf; + pDst->reserved = tmp60__ >> 4 & 0x7; + pDst->uapsd = tmp60__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMInfoAp. */ + +#define SigIeWMMInfoAp ( 0x0075 ) + + +tANI_U32 dot11fUnpackIeWMMInfoStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMInfoStation *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp61__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp61__ = *pBuf; + pDst->acvo_uapsd = tmp61__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp61__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp61__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp61__ >> 3 & 0x1; + pDst->reserved1 = tmp61__ >> 4 & 0x1; + pDst->max_sp_length = tmp61__ >> 5 & 0x3; + pDst->reserved2 = tmp61__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMInfoStation. */ + +#define SigIeWMMInfoStation ( 0x0076 ) + + +tANI_U32 dot11fUnpackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMParams *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp62__; + tANI_U8 tmp63__; + tANI_U8 tmp64__; + tANI_U8 tmp65__; + tANI_U8 tmp66__; + tANI_U8 tmp67__; + tANI_U8 tmp68__; + tANI_U8 tmp69__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + pDst->qosInfo = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->reserved2 = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + tmp62__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_aifsn = tmp62__ >> 0 & 0xf; + pDst->acbe_acm = tmp62__ >> 4 & 0x1; + pDst->acbe_aci = tmp62__ >> 5 & 0x3; + pDst->unused1 = tmp62__ >> 7 & 0x1; + tmp63__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_acwmin = tmp63__ >> 0 & 0xf; + pDst->acbe_acwmax = tmp63__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbe_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp64__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_aifsn = tmp64__ >> 0 & 0xf; + pDst->acbk_acm = tmp64__ >> 4 & 0x1; + pDst->acbk_aci = tmp64__ >> 5 & 0x3; + pDst->unused2 = tmp64__ >> 7 & 0x1; + tmp65__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_acwmin = tmp65__ >> 0 & 0xf; + pDst->acbk_acwmax = tmp65__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbk_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp66__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_aifsn = tmp66__ >> 0 & 0xf; + pDst->acvi_acm = tmp66__ >> 4 & 0x1; + pDst->acvi_aci = tmp66__ >> 5 & 0x3; + pDst->unused3 = tmp66__ >> 7 & 0x1; + tmp67__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_acwmin = tmp67__ >> 0 & 0xf; + pDst->acvi_acwmax = tmp67__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvi_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + tmp68__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_aifsn = tmp68__ >> 0 & 0xf; + pDst->acvo_acm = tmp68__ >> 4 & 0x1; + pDst->acvo_aci = tmp68__ >> 5 & 0x3; + pDst->unused4 = tmp68__ >> 7 & 0x1; + tmp69__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_acwmin = tmp69__ >> 0 & 0xf; + pDst->acvo_acwmax = tmp69__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvo_txoplimit, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWMMParams. */ + +#define SigIeWMMParams ( 0x0077 ) + + +tANI_U32 dot11fUnpackIeWPA(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWPA *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &pDst->version, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + if (pDst->version != 0x1) + { + pDst->present = 0; + return ( status | DOT11F_BAD_FIXED_VALUE ); + } + if ( ! ielen ) + { + pDst->multicast_cipher_present = 0U; + pDst->unicast_cipher_count = 0U; + pDst->auth_suite_count = 0U; + return 0U; + } + else + { + pDst->multicast_cipher_present = 1U; + DOT11F_MEMCPY(pCtx, pDst->multicast_cipher, pBuf, 4); + pBuf += 4; + ielen -= (tANI_U8)4; + } + if ( ! ielen ) + { + pDst->unicast_cipher_count = 0U; + pDst->auth_suite_count = 0U; + return 0U; + } + else + { + framesntohs(pCtx, &pDst->unicast_cipher_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if (pDst->unicast_cipher_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->unicast_ciphers, pBuf, ( pDst->unicast_cipher_count * 4 ) ); + pBuf += ( pDst->unicast_cipher_count * 4 ); + ielen -= ( pDst->unicast_cipher_count * 4 ); + if ( ! ielen ) + { + pDst->auth_suite_count = 0U; + return 0U; + } + else + { + framesntohs(pCtx, &pDst->auth_suite_count, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + } + if (pDst->auth_suite_count > 4){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->auth_suites, pBuf, ( pDst->auth_suite_count * 4 ) ); + pBuf += ( pDst->auth_suite_count * 4 ); + ielen -= ( pDst->auth_suite_count * 4 ); + if ( ! ielen ) + { + return 0U; + } + else + { + framesntohs(pCtx, &pDst->caps, pBuf, 0); + } + (void)pCtx; + return status; +} /* End dot11fUnpackIeWPA. */ + +#define SigIeWPA ( 0x0078 ) + + +tANI_U32 dot11fUnpackIeWPAOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWPAOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 249){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWPAOpaque. */ + +#define SigIeWPAOpaque ( 0x0079 ) + + + static const tTLVDefn TLVS_WSC[ ] = { + {offsetof(tDot11fIEWSC, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, WPSState), offsetof(tDot11fTLVWPSState, present), "WPSState", SigTlvWPSState, DOT11F_TLV_WPSSTATE, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, APSetupLocked), offsetof(tDot11fTLVAPSetupLocked, present), "APSetupLocked", SigTlvAPSetupLocked, DOT11F_TLV_APSETUPLOCKED, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, SelectedRegistrarConfigMethods), offsetof(tDot11fTLVSelectedRegistrarConfigMethods, present), "SelectedRegistrarConfigMethods", SigTlvSelectedRegistrarConfigMethods, DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, UUID_E), offsetof(tDot11fTLVUUID_E, present), "UUID_E", SigTlvUUID_E, DOT11F_TLV_UUID_E, 0, 20, 20, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, UUID_R), offsetof(tDot11fTLVUUID_R, present), "UUID_R", SigTlvUUID_R, DOT11F_TLV_UUID_R, 0, 20, 20, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, RFBands), offsetof(tDot11fTLVRFBands, present), "RFBands", SigTlvRFBands, DOT11F_TLV_RFBANDS, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, SelectedRegistrar), offsetof(tDot11fTLVSelectedRegistrar, present), "SelectedRegistrar", SigTlvSelectedRegistrar, DOT11F_TLV_SELECTEDREGISTRAR, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, ConfigMethods), offsetof(tDot11fTLVConfigMethods, present), "ConfigMethods", SigTlvConfigMethods, DOT11F_TLV_CONFIGMETHODS, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, AssociationState), offsetof(tDot11fTLVAssociationState, present), "AssociationState", SigTlvAssociationState, DOT11F_TLV_ASSOCIATIONSTATE, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, ConfigurationError), offsetof(tDot11fTLVConfigurationError, present), "ConfigurationError", SigTlvConfigurationError, DOT11F_TLV_CONFIGURATIONERROR, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, Manufacturer), offsetof(tDot11fTLVManufacturer, present), "Manufacturer", SigTlvManufacturer, DOT11F_TLV_MANUFACTURER, 0, 4, 68, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, ModelName), offsetof(tDot11fTLVModelName, present), "ModelName", SigTlvModelName, DOT11F_TLV_MODELNAME, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, ModelNumber), offsetof(tDot11fTLVModelNumber, present), "ModelNumber", SigTlvModelNumber, DOT11F_TLV_MODELNUMBER, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, SerialNumber), offsetof(tDot11fTLVSerialNumber, present), "SerialNumber", SigTlvSerialNumber, DOT11F_TLV_SERIALNUMBER, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, DeviceName), offsetof(tDot11fTLVDeviceName, present), "DeviceName", SigTlvDeviceName, DOT11F_TLV_DEVICENAME, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, DevicePasswordID), offsetof(tDot11fTLVDevicePasswordID, present), "DevicePasswordID", SigTlvDevicePasswordID, DOT11F_TLV_DEVICEPASSWORDID, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, PrimaryDeviceType), offsetof(tDot11fTLVPrimaryDeviceType, present), "PrimaryDeviceType", SigTlvPrimaryDeviceType, DOT11F_TLV_PRIMARYDEVICETYPE, 0, 12, 12, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, RequestType), offsetof(tDot11fTLVRequestType, present), "RequestType", SigTlvRequestType, DOT11F_TLV_REQUESTTYPE, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, ResponseType), offsetof(tDot11fTLVResponseType, present), "ResponseType", SigTlvResponseType, DOT11F_TLV_RESPONSETYPE, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWSC, RequestDeviceType), offsetof(tDot11fTLVRequestDeviceType, present), "RequestDeviceType", SigTlvRequestDeviceType, DOT11F_TLV_REQUESTDEVICETYPE, 0, 12, 12, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWSC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWSC *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WSC,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWSC. */ + +#define SigIeWSC ( 0x007a ) + + + static const tTLVDefn TLVS_WscAssocReq[ ] = { + {offsetof(tDot11fIEWscAssocReq, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscAssocReq, RequestType), offsetof(tDot11fTLVRequestType, present), "RequestType", SigTlvRequestType, DOT11F_TLV_REQUESTTYPE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscAssocReq, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscAssocReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscAssocReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscAssocReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscAssocReq. */ + +#define SigIeWscAssocReq ( 0x007b ) + + + static const tTLVDefn TLVS_WscAssocRes[ ] = { + {offsetof(tDot11fIEWscAssocRes, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscAssocRes, ResponseType), offsetof(tDot11fTLVResponseType, present), "ResponseType", SigTlvResponseType, DOT11F_TLV_RESPONSETYPE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscAssocRes, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscAssocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscAssocRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscAssocRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscAssocRes. */ + +#define SigIeWscAssocRes ( 0x007c ) + + + static const tTLVDefn TLVS_WscBeacon[ ] = { + {offsetof(tDot11fIEWscBeacon, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, WPSState), offsetof(tDot11fTLVWPSState, present), "WPSState", SigTlvWPSState, DOT11F_TLV_WPSSTATE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, APSetupLocked), offsetof(tDot11fTLVAPSetupLocked, present), "APSetupLocked", SigTlvAPSetupLocked, DOT11F_TLV_APSETUPLOCKED, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, SelectedRegistrar), offsetof(tDot11fTLVSelectedRegistrar, present), "SelectedRegistrar", SigTlvSelectedRegistrar, DOT11F_TLV_SELECTEDREGISTRAR, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, DevicePasswordID), offsetof(tDot11fTLVDevicePasswordID, present), "DevicePasswordID", SigTlvDevicePasswordID, DOT11F_TLV_DEVICEPASSWORDID, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, SelectedRegistrarConfigMethods), offsetof(tDot11fTLVSelectedRegistrarConfigMethods, present), "SelectedRegistrarConfigMethods", SigTlvSelectedRegistrarConfigMethods, DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, UUID_E), offsetof(tDot11fTLVUUID_E, present), "UUID_E", SigTlvUUID_E, DOT11F_TLV_UUID_E, 0, 20, 20, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, RFBands), offsetof(tDot11fTLVRFBands, present), "RFBands", SigTlvRFBands, DOT11F_TLV_RFBANDS, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeacon, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscBeacon *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscBeacon,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscBeacon. */ + +#define SigIeWscBeacon ( 0x007d ) + + + static const tTLVDefn TLVS_WscBeaconProbeRes[ ] = { + {offsetof(tDot11fIEWscBeaconProbeRes, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, WPSState), offsetof(tDot11fTLVWPSState, present), "WPSState", SigTlvWPSState, DOT11F_TLV_WPSSTATE, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, APSetupLocked), offsetof(tDot11fTLVAPSetupLocked, present), "APSetupLocked", SigTlvAPSetupLocked, DOT11F_TLV_APSETUPLOCKED, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, SelectedRegistrar), offsetof(tDot11fTLVSelectedRegistrar, present), "SelectedRegistrar", SigTlvSelectedRegistrar, DOT11F_TLV_SELECTEDREGISTRAR, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, DevicePasswordID), offsetof(tDot11fTLVDevicePasswordID, present), "DevicePasswordID", SigTlvDevicePasswordID, DOT11F_TLV_DEVICEPASSWORDID, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, SelectedRegistrarConfigMethods), offsetof(tDot11fTLVSelectedRegistrarConfigMethods, present), "SelectedRegistrarConfigMethods", SigTlvSelectedRegistrarConfigMethods, DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, ResponseType), offsetof(tDot11fTLVResponseType, present), "ResponseType", SigTlvResponseType, DOT11F_TLV_RESPONSETYPE, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, UUID_E), offsetof(tDot11fTLVUUID_E, present), "UUID_E", SigTlvUUID_E, DOT11F_TLV_UUID_E, 0, 20, 20, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, Manufacturer), offsetof(tDot11fTLVManufacturer, present), "Manufacturer", SigTlvManufacturer, DOT11F_TLV_MANUFACTURER, 0, 4, 68, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, ModelName), offsetof(tDot11fTLVModelName, present), "ModelName", SigTlvModelName, DOT11F_TLV_MODELNAME, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, ModelNumber), offsetof(tDot11fTLVModelNumber, present), "ModelNumber", SigTlvModelNumber, DOT11F_TLV_MODELNUMBER, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, SerialNumber), offsetof(tDot11fTLVSerialNumber, present), "SerialNumber", SigTlvSerialNumber, DOT11F_TLV_SERIALNUMBER, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, PrimaryDeviceType), offsetof(tDot11fTLVPrimaryDeviceType, present), "PrimaryDeviceType", SigTlvPrimaryDeviceType, DOT11F_TLV_PRIMARYDEVICETYPE, 0, 12, 12, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, DeviceName), offsetof(tDot11fTLVDeviceName, present), "DeviceName", SigTlvDeviceName, DOT11F_TLV_DEVICENAME, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, ConfigMethods), offsetof(tDot11fTLVConfigMethods, present), "ConfigMethods", SigTlvConfigMethods, DOT11F_TLV_CONFIGMETHODS, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, RFBands), offsetof(tDot11fTLVRFBands, present), "RFBands", SigTlvRFBands, DOT11F_TLV_RFBANDS, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscBeaconProbeRes, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscBeaconProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscBeaconProbeRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscBeaconProbeRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscBeaconProbeRes. */ + +#define SigIeWscBeaconProbeRes ( 0x007e ) + + +tANI_U32 dot11fUnpackIeWscIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscIEOpaque *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (tANI_U8)( ielen ); + if (ielen > 249){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, ( ielen ) ); + (void)pCtx; + return status; +} /* End dot11fUnpackIeWscIEOpaque. */ + +#define SigIeWscIEOpaque ( 0x007f ) + + + static const tTLVDefn TLVS_WscProbeReq[ ] = { + {offsetof(tDot11fIEWscProbeReq, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, RequestType), offsetof(tDot11fTLVRequestType, present), "RequestType", SigTlvRequestType, DOT11F_TLV_REQUESTTYPE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, ConfigMethods), offsetof(tDot11fTLVConfigMethods, present), "ConfigMethods", SigTlvConfigMethods, DOT11F_TLV_CONFIGMETHODS, 0, 6, 6, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, UUID_E), offsetof(tDot11fTLVUUID_E, present), "UUID_E", SigTlvUUID_E, DOT11F_TLV_UUID_E, 0, 20, 20, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, PrimaryDeviceType), offsetof(tDot11fTLVPrimaryDeviceType, present), "PrimaryDeviceType", SigTlvPrimaryDeviceType, DOT11F_TLV_PRIMARYDEVICETYPE, 0, 12, 12, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, RFBands), offsetof(tDot11fTLVRFBands, present), "RFBands", SigTlvRFBands, DOT11F_TLV_RFBANDS, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, AssociationState), offsetof(tDot11fTLVAssociationState, present), "AssociationState", SigTlvAssociationState, DOT11F_TLV_ASSOCIATIONSTATE, 0, 6, 6, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, ConfigurationError), offsetof(tDot11fTLVConfigurationError, present), "ConfigurationError", SigTlvConfigurationError, DOT11F_TLV_CONFIGURATIONERROR, 0, 6, 6, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, DevicePasswordID), offsetof(tDot11fTLVDevicePasswordID, present), "DevicePasswordID", SigTlvDevicePasswordID, DOT11F_TLV_DEVICEPASSWORDID, 0, 6, 6, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, Manufacturer), offsetof(tDot11fTLVManufacturer, present), "Manufacturer", SigTlvManufacturer, DOT11F_TLV_MANUFACTURER, 0, 4, 68, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, ModelName), offsetof(tDot11fTLVModelName, present), "ModelName", SigTlvModelName, DOT11F_TLV_MODELNAME, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, ModelNumber), offsetof(tDot11fTLVModelNumber, present), "ModelNumber", SigTlvModelNumber, DOT11F_TLV_MODELNUMBER, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, DeviceName), offsetof(tDot11fTLVDeviceName, present), "DeviceName", SigTlvDeviceName, DOT11F_TLV_DEVICENAME, 0, 4, 36, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeReq, RequestDeviceType), offsetof(tDot11fTLVRequestDeviceType, present), "RequestDeviceType", SigTlvRequestDeviceType, DOT11F_TLV_REQUESTDEVICETYPE, 0, 12, 12, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscProbeReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscProbeReq *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscProbeReq,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscProbeReq. */ + +#define SigIeWscProbeReq ( 0x0080 ) + + + static const tTLVDefn TLVS_WscProbeRes[ ] = { + {offsetof(tDot11fIEWscProbeRes, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, WPSState), offsetof(tDot11fTLVWPSState, present), "WPSState", SigTlvWPSState, DOT11F_TLV_WPSSTATE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, APSetupLocked), offsetof(tDot11fTLVAPSetupLocked, present), "APSetupLocked", SigTlvAPSetupLocked, DOT11F_TLV_APSETUPLOCKED, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, SelectedRegistrar), offsetof(tDot11fTLVSelectedRegistrar, present), "SelectedRegistrar", SigTlvSelectedRegistrar, DOT11F_TLV_SELECTEDREGISTRAR, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, DevicePasswordID), offsetof(tDot11fTLVDevicePasswordID, present), "DevicePasswordID", SigTlvDevicePasswordID, DOT11F_TLV_DEVICEPASSWORDID, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, SelectedRegistrarConfigMethods), offsetof(tDot11fTLVSelectedRegistrarConfigMethods, present), "SelectedRegistrarConfigMethods", SigTlvSelectedRegistrarConfigMethods, DOT11F_TLV_SELECTEDREGISTRARCONFIGMETHODS, 0, 6, 6, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, ResponseType), offsetof(tDot11fTLVResponseType, present), "ResponseType", SigTlvResponseType, DOT11F_TLV_RESPONSETYPE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, UUID_E), offsetof(tDot11fTLVUUID_E, present), "UUID_E", SigTlvUUID_E, DOT11F_TLV_UUID_E, 0, 20, 20, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, Manufacturer), offsetof(tDot11fTLVManufacturer, present), "Manufacturer", SigTlvManufacturer, DOT11F_TLV_MANUFACTURER, 0, 4, 68, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, ModelName), offsetof(tDot11fTLVModelName, present), "ModelName", SigTlvModelName, DOT11F_TLV_MODELNAME, 0, 4, 36, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, ModelNumber), offsetof(tDot11fTLVModelNumber, present), "ModelNumber", SigTlvModelNumber, DOT11F_TLV_MODELNUMBER, 0, 4, 36, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, SerialNumber), offsetof(tDot11fTLVSerialNumber, present), "SerialNumber", SigTlvSerialNumber, DOT11F_TLV_SERIALNUMBER, 0, 4, 36, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, PrimaryDeviceType), offsetof(tDot11fTLVPrimaryDeviceType, present), "PrimaryDeviceType", SigTlvPrimaryDeviceType, DOT11F_TLV_PRIMARYDEVICETYPE, 0, 12, 12, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, DeviceName), offsetof(tDot11fTLVDeviceName, present), "DeviceName", SigTlvDeviceName, DOT11F_TLV_DEVICENAME, 0, 4, 36, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, ConfigMethods), offsetof(tDot11fTLVConfigMethods, present), "ConfigMethods", SigTlvConfigMethods, DOT11F_TLV_CONFIGMETHODS, 0, 6, 6, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, RFBands), offsetof(tDot11fTLVRFBands, present), "RFBands", SigTlvRFBands, DOT11F_TLV_RFBANDS, 0, 5, 5, 0, 2, 2, 1, }, + {offsetof(tDot11fIEWscProbeRes, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscProbeRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscProbeRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscProbeRes. */ + +#define SigIeWscProbeRes ( 0x0081 ) + + + static const tTLVDefn TLVS_WscReassocRes[ ] = { + {offsetof(tDot11fIEWscReassocRes, Version), offsetof(tDot11fTLVVersion, present), "Version", SigTlvVersion, DOT11F_TLV_VERSION, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscReassocRes, ResponseType), offsetof(tDot11fTLVResponseType, present), "ResponseType", SigTlvResponseType, DOT11F_TLV_RESPONSETYPE, 0, 5, 5, 1, 2, 2, 1, }, + {offsetof(tDot11fIEWscReassocRes, VendorExtension), offsetof(tDot11fTLVVendorExtension, present), "VendorExtension", SigTlvVendorExtension, DOT11F_TLV_VENDOREXTENSION, 0, 7, 21, 0, 2, 2, 1, }, + {0, 0, NULL, 0, 0xffff, 0, 0, 0, 0, 0, 0}, + }; + +tANI_U32 dot11fUnpackIeWscReassocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscReassocRes *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = UnpackTlvCore(pCtx,pBuf,ielen,TLVS_WscReassocRes,(tANI_U8*)pDst,sizeof(*pDst)); + return status; +} /* End dot11fUnpackIeWscReassocRes. */ + +#define SigIeWscReassocRes ( 0x0082 ) + + +tANI_U32 dot11fUnpackIeext_chan_switch_ann(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEext_chan_switch_ann *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->switch_mode = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->new_reg_class = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->new_channel = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + pDst->switch_count = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIeext_chan_switch_ann. */ + +#define SigIeext_chan_switch_ann ( 0x0083 ) + + +tANI_U32 dot11fUnpackIesec_chan_offset_ele(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEsec_chan_offset_ele *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->secondaryChannelOffset = *pBuf; + (void)pCtx; + return status; +} /* End dot11fUnpackIesec_chan_offset_ele. */ + +#define SigIesec_chan_offset_ele ( 0x0084 ) + + + static const tFFDefn FFS_AddBAReq[] = { + { "Category", offsetof(tDot11fAddBAReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fAddBAReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fAddBAReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "AddBAParameterSet", offsetof(tDot11fAddBAReq, AddBAParameterSet), SigFfAddBAParameterSet , DOT11F_FF_ADDBAPARAMETERSET_LEN, }, + { "BATimeout", offsetof(tDot11fAddBAReq, BATimeout), SigFfBATimeout , DOT11F_FF_BATIMEOUT_LEN, }, + { "BAStartingSequenceControl", offsetof(tDot11fAddBAReq, BAStartingSequenceControl), SigFfBAStartingSequenceControl , DOT11F_FF_BASTARTINGSEQUENCECONTROL_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_AddBAReq[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackAddBAReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddBAReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_AddBAReq, IES_AddBAReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("Unpacked the AddBAReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("AddBAParameterSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("amsduSupported (1): %d\n"), pFrm->AddBAParameterSet.amsduSupported); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("policy (1): %d\n"), pFrm->AddBAParameterSet.policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("tid (4): %d\n"), pFrm->AddBAParameterSet.tid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("bufferSize (10): %d\n"), pFrm->AddBAParameterSet.bufferSize); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("BATimeout:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->BATimeout.timeout, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("BAStartingSequenceControl:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("fragNumber (4): %d\n"), pFrm->BAStartingSequenceControl.fragNumber); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("ssn (12): %d\n"), pFrm->BAStartingSequenceControl.ssn); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddBAReq. */ + + static const tFFDefn FFS_AddBARsp[] = { + { "Category", offsetof(tDot11fAddBARsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fAddBARsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fAddBARsp, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "Status", offsetof(tDot11fAddBARsp, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { "AddBAParameterSet", offsetof(tDot11fAddBARsp, AddBAParameterSet), SigFfAddBAParameterSet , DOT11F_FF_ADDBAPARAMETERSET_LEN, }, + { "BATimeout", offsetof(tDot11fAddBARsp, BATimeout), SigFfBATimeout , DOT11F_FF_BATIMEOUT_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_AddBARsp[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackAddBARsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddBARsp *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_AddBARsp, IES_AddBARsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Unpacked the AddBARsp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("AddBAParameterSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("amsduSupported (1): %d\n"), pFrm->AddBAParameterSet.amsduSupported); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("policy (1): %d\n"), pFrm->AddBAParameterSet.policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("tid (4): %d\n"), pFrm->AddBAParameterSet.tid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("bufferSize (10): %d\n"), pFrm->AddBAParameterSet.bufferSize); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("BATimeout:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->BATimeout.timeout, 2); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddBARsp. */ + + static const tFFDefn FFS_AddTSRequest[] = { + { "Category", offsetof(tDot11fAddTSRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fAddTSRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fAddTSRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_AddTSRequest[] = { + {offsetof(tDot11fAddTSRequest, TSPEC), offsetof(tDot11fIETSPEC, present), 0, "TSPEC" , 0, 57, 57, SigIeTSPEC, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TSPEC, 1, }, + {offsetof(tDot11fAddTSRequest, TCLAS), offsetof(tDot11fIETCLAS, present), offsetof(tDot11fAddTSRequest, num_TCLAS), "TCLAS" , 2, 7, 45, SigIeTCLAS, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TCLAS, 0, }, + {offsetof(tDot11fAddTSRequest, TCLASSPROC), offsetof(tDot11fIETCLASSPROC, present), 0, "TCLASSPROC" , 0, 3, 3, SigIeTCLASSPROC, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TCLASSPROC, 0, }, + {offsetof(tDot11fAddTSRequest, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), 0, "WMMTSPEC" , 0, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fAddTSRequest, WMMTCLAS), offsetof(tDot11fIEWMMTCLAS, present), offsetof(tDot11fAddTSRequest, num_WMMTCLAS), "WMMTCLAS" , 2, 13, 51, SigIeWMMTCLAS, {0, 80, 242, 2, 6}, 5, DOT11F_EID_WMMTCLAS, 0, }, + {offsetof(tDot11fAddTSRequest, WMMTCLASPROC), offsetof(tDot11fIEWMMTCLASPROC, present), 0, "WMMTCLASPROC" , 0, 9, 9, SigIeWMMTCLASPROC, {0, 80, 242, 2, 7}, 5, DOT11F_EID_WMMTCLASPROC, 0, }, + {offsetof(tDot11fAddTSRequest, ESETrafStrmRateSet), offsetof(tDot11fIEESETrafStrmRateSet, present), 0, "ESETrafStrmRateSet" , 0, 7, 15, SigIeESETrafStrmRateSet, {0, 64, 150, 8, 0}, 4, DOT11F_EID_ESETRAFSTRMRATESET, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackAddTSRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddTSRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_AddTSRequest, IES_AddTSRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Unpacked the AddTSRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("TSPEC:\n")); + if (!pFrm->TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsid (4): %d\n"), pFrm->TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("direction (2): %d\n"), pFrm->TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("access_policy (2): %d\n"), pFrm->TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("aggregation (1): %d\n"), pFrm->TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("psb (1): %d\n"), pFrm->TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("user_priority (3): %d\n"), pFrm->TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("schedule (1): %d\n"), pFrm->TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("unused (7): %d\n"), pFrm->TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("size (15): %d\n"), pFrm->TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("fixed (1): %d\n"), pFrm->TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].classifier_mask, 1); + switch (pFrm->TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.version, 1); + switch (pFrm->TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("TCLASSPROC:\n")); + if (!pFrm->TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddTSRequest. */ + + static const tFFDefn FFS_AddTSResponse[] = { + { "Category", offsetof(tDot11fAddTSResponse, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fAddTSResponse, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fAddTSResponse, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "Status", offsetof(tDot11fAddTSResponse, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_AddTSResponse[] = { + {offsetof(tDot11fAddTSResponse, TSDelay), offsetof(tDot11fIETSDelay, present), 0, "TSDelay" , 0, 6, 6, SigIeTSDelay, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TSDELAY, 1, }, + {offsetof(tDot11fAddTSResponse, TSPEC), offsetof(tDot11fIETSPEC, present), 0, "TSPEC" , 0, 57, 57, SigIeTSPEC, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TSPEC, 1, }, + {offsetof(tDot11fAddTSResponse, TCLAS), offsetof(tDot11fIETCLAS, present), offsetof(tDot11fAddTSResponse, num_TCLAS), "TCLAS" , 2, 7, 45, SigIeTCLAS, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TCLAS, 0, }, + {offsetof(tDot11fAddTSResponse, TCLASSPROC), offsetof(tDot11fIETCLASSPROC, present), 0, "TCLASSPROC" , 0, 3, 3, SigIeTCLASSPROC, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TCLASSPROC, 0, }, + {offsetof(tDot11fAddTSResponse, Schedule), offsetof(tDot11fIESchedule, present), 0, "Schedule" , 0, 16, 16, SigIeSchedule, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SCHEDULE, 0, }, + {offsetof(tDot11fAddTSResponse, WMMTSDelay), offsetof(tDot11fIEWMMTSDelay, present), 0, "WMMTSDelay" , 0, 12, 12, SigIeWMMTSDelay, {0, 80, 242, 2, 8}, 5, DOT11F_EID_WMMTSDELAY, 0, }, + {offsetof(tDot11fAddTSResponse, WMMSchedule), offsetof(tDot11fIEWMMSchedule, present), 0, "WMMSchedule" , 0, 22, 22, SigIeWMMSchedule, {0, 80, 242, 2, 9}, 5, DOT11F_EID_WMMSCHEDULE, 0, }, + {offsetof(tDot11fAddTSResponse, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), 0, "WMMTSPEC" , 0, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fAddTSResponse, WMMTCLAS), offsetof(tDot11fIEWMMTCLAS, present), offsetof(tDot11fAddTSResponse, num_WMMTCLAS), "WMMTCLAS" , 2, 13, 51, SigIeWMMTCLAS, {0, 80, 242, 2, 6}, 5, DOT11F_EID_WMMTCLAS, 0, }, + {offsetof(tDot11fAddTSResponse, WMMTCLASPROC), offsetof(tDot11fIEWMMTCLASPROC, present), 0, "WMMTCLASPROC" , 0, 9, 9, SigIeWMMTCLASPROC, {0, 80, 242, 2, 7}, 5, DOT11F_EID_WMMTCLASPROC, 0, }, + {offsetof(tDot11fAddTSResponse, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackAddTSResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAddTSResponse *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_AddTSResponse, IES_AddTSResponse, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Unpacked the AddTSResponse:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TSDelay:\n")); + if (!pFrm->TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TSPEC:\n")); + if (!pFrm->TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("psb (1): %d\n"), pFrm->TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("schedule (1): %d\n"), pFrm->TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("unused (7): %d\n"), pFrm->TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("size (15): %d\n"), pFrm->TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("fixed (1): %d\n"), pFrm->TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].classifier_mask, 1); + switch (pFrm->TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.version, 1); + switch (pFrm->TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TCLASSPROC:\n")); + if (!pFrm->TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Schedule:\n")); + if (!pFrm->Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("reserved (9): %d\n"), pFrm->Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTSDelay:\n")); + if (!pFrm->WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMSchedule:\n")); + if (!pFrm->WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("reserved (9): %d\n"), pFrm->WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddTSResponse. */ + + static const tFFDefn FFS_AssocRequest[] = { + { "Capabilities", offsetof(tDot11fAssocRequest, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { "ListenInterval", offsetof(tDot11fAssocRequest, ListenInterval), SigFfListenInterval , DOT11F_FF_LISTENINTERVAL_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_AssocRequest[] = { + {offsetof(tDot11fAssocRequest, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fAssocRequest, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fAssocRequest, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fAssocRequest, PowerCaps), offsetof(tDot11fIEPowerCaps, present), 0, "PowerCaps" , 0, 4, 4, SigIePowerCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCAPS, 0, }, + {offsetof(tDot11fAssocRequest, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, + {offsetof(tDot11fAssocRequest, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, + {offsetof(tDot11fAssocRequest, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, + {offsetof(tDot11fAssocRequest, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fAssocRequest, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fAssocRequest, WPAOpaque), offsetof(tDot11fIEWPAOpaque, present), 0, "WPAOpaque" , 0, 8, 255, SigIeWPAOpaque, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPAOPAQUE, 0, }, + {offsetof(tDot11fAssocRequest, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fAssocRequest, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fAssocRequest, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, + {offsetof(tDot11fAssocRequest, WscIEOpaque), offsetof(tDot11fIEWscIEOpaque, present), 0, "WscIEOpaque" , 0, 8, 255, SigIeWscIEOpaque, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCIEOPAQUE, 0, }, + {offsetof(tDot11fAssocRequest, WAPIOpaque), offsetof(tDot11fIEWAPIOpaque, present), 0, "WAPIOpaque" , 0, 8, 255, SigIeWAPIOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPIOPAQUE, 0, }, + {offsetof(tDot11fAssocRequest, WAPI), offsetof(tDot11fIEWAPI, present), 0, "WAPI" , 0, 14, 112, SigIeWAPI, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPI, 0, }, + {offsetof(tDot11fAssocRequest, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fAssocRequest, ESEVersion), offsetof(tDot11fIEESEVersion, present), 0, "ESEVersion" , 0, 7, 7, SigIeESEVersion, {0, 64, 150, 3, 0}, 4, DOT11F_EID_ESEVERSION, 0, }, + {offsetof(tDot11fAssocRequest, P2PIEOpaque), offsetof(tDot11fIEP2PIEOpaque, present), 0, "P2PIEOpaque" , 0, 8, 255, SigIeP2PIEOpaque, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PIEOPAQUE, 0, }, + {offsetof(tDot11fAssocRequest, WFDIEOpaque), offsetof(tDot11fIEWFDIEOpaque, present), 0, "WFDIEOpaque" , 0, 8, 255, SigIeWFDIEOpaque, {80, 111, 154, 10, 0}, 4, DOT11F_EID_WFDIEOPAQUE, 0, }, + {offsetof(tDot11fAssocRequest, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fAssocRequest, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 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, }, + {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) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_AssocRequest, IES_AssocRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Unpacked the AssocRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ListenInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->ListenInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("PowerCaps:\n")); + if (!pFrm->PowerCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.minTxPower, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.maxTxPower, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.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("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.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("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WPAOpaque:\n")); + if (!pFrm->WPAOpaque.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("num_data: %d.\n"), pFrm->WPAOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WPAOpaque.data, pFrm->WPAOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WscIEOpaque:\n")); + if (!pFrm->WscIEOpaque.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("num_data: %d.\n"), pFrm->WscIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WscIEOpaque.data, pFrm->WscIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WAPIOpaque:\n")); + if (!pFrm->WAPIOpaque.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("num_data: %d.\n"), pFrm->WAPIOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPIOpaque.data, pFrm->WAPIOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("P2PIEOpaque:\n")); + if (!pFrm->P2PIEOpaque.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("num_data: %d.\n"), pFrm->P2PIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->P2PIEOpaque.data, pFrm->P2PIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WFDIEOpaque:\n")); + if (!pFrm->WFDIEOpaque.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("num_data: %d.\n"), pFrm->WFDIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WFDIEOpaque.data, pFrm->WFDIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.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("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); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAssocRequest. */ + + static const tFFDefn FFS_AssocResponse[] = { + { "Capabilities", offsetof(tDot11fAssocResponse, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { "Status", offsetof(tDot11fAssocResponse, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { "AID", offsetof(tDot11fAssocResponse, AID), SigFfAID , DOT11F_FF_AID_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_AssocResponse[] = { + {offsetof(tDot11fAssocResponse, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fAssocResponse, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fAssocResponse, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fAssocResponse, RCPIIE), offsetof(tDot11fIERCPIIE, present), 0, "RCPIIE" , 0, 3, 3, SigIeRCPIIE, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RCPIIE, 0, }, + {offsetof(tDot11fAssocResponse, RSNIIE), offsetof(tDot11fIERSNIIE, present), 0, "RSNIIE" , 0, 3, 3, SigIeRSNIIE, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNIIE, 0, }, + {offsetof(tDot11fAssocResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fAssocResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fAssocResponse, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fAssocResponse, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, + {offsetof(tDot11fAssocResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, + {offsetof(tDot11fAssocResponse, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fAssocResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fAssocResponse, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fAssocResponse, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fAssocResponse, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fAssocResponse, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fAssocResponse, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {offsetof(tDot11fAssocResponse, ESETxmitPower), offsetof(tDot11fIEESETxmitPower, present), 0, "ESETxmitPower" , 0, 8, 8, SigIeESETxmitPower, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESETXMITPOWER, 0, }, + {offsetof(tDot11fAssocResponse, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), offsetof(tDot11fAssocResponse, num_WMMTSPEC), "WMMTSPEC" , 4, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fAssocResponse, WscAssocRes), offsetof(tDot11fIEWscAssocRes, present), 0, "WscAssocRes" , 0, 6, 37, SigIeWscAssocRes, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCASSOCRES, 0, }, + {offsetof(tDot11fAssocResponse, P2PAssocRes), offsetof(tDot11fIEP2PAssocRes, present), 0, "P2PAssocRes" , 0, 6, 17, SigIeP2PAssocRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PASSOCRES, 0, }, + {offsetof(tDot11fAssocResponse, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fAssocResponse, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fAssocResponse, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {offsetof(tDot11fAssocResponse, OBSSScanParameters), offsetof(tDot11fIEOBSSScanParameters, present), 0, "OBSSScanParameters" , 0, 16, 16, SigIeOBSSScanParameters, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OBSSSCANPARAMETERS, 0, }, + {offsetof(tDot11fAssocResponse, QosMapSet), offsetof(tDot11fIEQosMapSet, present), 0, "QosMapSet" , 0, 2, 62, SigIeQosMapSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSMAPSET, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAssocResponse *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_AssocResponse, IES_AssocResponse, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Unpacked the AssocResponse:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("AID:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->AID.associd, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RCPIIE:\n")); + if (!pFrm->RCPIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RCPIIE.rcpi, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RSNIIE:\n")); + if (!pFrm->RSNIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RSNIIE.rsni, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + for (i = 0; i < pFrm->num_WMMTSPEC; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTSPEC[%d]:\n"), i); + if (!pFrm->WMMTSPEC[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC[i].traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC[i].tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC[i].direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC[i].access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC[i].aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC[i].psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC[i].user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC[i].tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC[i].tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC[i].burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC[i].size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC[i].fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].medium_time, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WscAssocRes:\n")); + if (!pFrm->WscAssocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Version:\n")); + if (!pFrm->WscAssocRes.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscAssocRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscAssocRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ResponseType:\n")); + if (!pFrm->WscAssocRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("VendorExtension:\n")); + if (!pFrm->WscAssocRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Version2:\n")); + if (!pFrm->WscAssocRes.VendorExtension.Version2.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscAssocRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscAssocRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscAssocRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscAssocRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("P2PAssocRes:\n")); + if (!pFrm->P2PAssocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("P2PStatus:\n")); + if (!pFrm->P2PAssocRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PAssocRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityInterval, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAssocResponse. */ + + static const tFFDefn FFS_Authentication[] = { + { "AuthAlgo", offsetof(tDot11fAuthentication, AuthAlgo), SigFfAuthAlgo , DOT11F_FF_AUTHALGO_LEN, }, + { "AuthSeqNo", offsetof(tDot11fAuthentication, AuthSeqNo), SigFfAuthSeqNo , DOT11F_FF_AUTHSEQNO_LEN, }, + { "Status", offsetof(tDot11fAuthentication, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_Authentication[] = { + {offsetof(tDot11fAuthentication, ChallengeText), offsetof(tDot11fIEChallengeText, present), 0, "ChallengeText" , 0, 3, 255, SigIeChallengeText, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHALLENGETEXT, 0, }, + {offsetof(tDot11fAuthentication, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, + {offsetof(tDot11fAuthentication, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fAuthentication, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fAuthentication, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fAuthentication, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fAuthentication, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackAuthentication(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAuthentication *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_Authentication, IES_Authentication, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Unpacked the Authentication:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("AuthAlgo:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->AuthAlgo.algo, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("AuthSeqNo:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->AuthSeqNo.no, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("ChallengeText:\n")); + if (!pFrm->ChallengeText.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_text: %d.\n"), pFrm->ChallengeText.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->ChallengeText.text, pFrm->ChallengeText.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAuthentication. */ + + static const tFFDefn FFS_Beacon[] = { + { "TimeStamp", offsetof(tDot11fBeacon, TimeStamp), SigFfTimeStamp , DOT11F_FF_TIMESTAMP_LEN, }, + { "BeaconInterval", offsetof(tDot11fBeacon, BeaconInterval), SigFfBeaconInterval , DOT11F_FF_BEACONINTERVAL_LEN, }, + { "Capabilities", offsetof(tDot11fBeacon, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_Beacon[] = { + {offsetof(tDot11fBeacon, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fBeacon, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fBeacon, FHParamSet), offsetof(tDot11fIEFHParamSet, present), 0, "FHParamSet" , 0, 7, 7, SigIeFHParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPARAMSET, 0, }, + {offsetof(tDot11fBeacon, DSParams), offsetof(tDot11fIEDSParams, present), 0, "DSParams" , 0, 3, 3, SigIeDSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_DSPARAMS, 0, }, + {offsetof(tDot11fBeacon, CFParams), offsetof(tDot11fIECFParams, present), 0, "CFParams" , 0, 8, 8, SigIeCFParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CFPARAMS, 0, }, + {offsetof(tDot11fBeacon, IBSSParams), offsetof(tDot11fIEIBSSParams, present), 0, "IBSSParams" , 0, 4, 4, SigIeIBSSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IBSSPARAMS, 0, }, + {offsetof(tDot11fBeacon, TIM), offsetof(tDot11fIETIM, present), 0, "TIM" , 0, 6, 256, SigIeTIM, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIM, 0, }, + {offsetof(tDot11fBeacon, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fBeacon, FHParams), offsetof(tDot11fIEFHParams, present), 0, "FHParams" , 0, 4, 4, SigIeFHParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPARAMS, 0, }, + {offsetof(tDot11fBeacon, FHPattTable), offsetof(tDot11fIEFHPattTable, present), 0, "FHPattTable" , 0, 6, 257, SigIeFHPattTable, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPATTTABLE, 0, }, + {offsetof(tDot11fBeacon, PowerConstraints), offsetof(tDot11fIEPowerConstraints, present), 0, "PowerConstraints" , 0, 3, 3, SigIePowerConstraints, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCONSTRAINTS, 0, }, + {offsetof(tDot11fBeacon, ChanSwitchAnn), offsetof(tDot11fIEChanSwitchAnn, present), 0, "ChanSwitchAnn" , 0, 5, 5, SigIeChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANSWITCHANN, 0, }, + {offsetof(tDot11fBeacon, ext_chan_switch_ann), offsetof(tDot11fIEext_chan_switch_ann, present), 0, "ext_chan_switch_ann" , 0, 6, 6, SigIeext_chan_switch_ann, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXT_CHAN_SWITCH_ANN, 0, }, + {offsetof(tDot11fBeacon, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fBeacon, Quiet), offsetof(tDot11fIEQuiet, present), 0, "Quiet" , 0, 8, 8, SigIeQuiet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QUIET, 0, }, + {offsetof(tDot11fBeacon, TPCReport), offsetof(tDot11fIETPCReport, present), 0, "TPCReport" , 0, 4, 4, SigIeTPCReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TPCREPORT, 0, }, + {offsetof(tDot11fBeacon, ERPInfo), offsetof(tDot11fIEERPInfo, present), 0, "ERPInfo" , 0, 3, 3, SigIeERPInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_ERPINFO, 0, }, + {offsetof(tDot11fBeacon, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fBeacon, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 116, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, + {offsetof(tDot11fBeacon, QBSSLoad), offsetof(tDot11fIEQBSSLoad, present), 0, "QBSSLoad" , 0, 7, 7, SigIeQBSSLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QBSSLOAD, 0, }, + {offsetof(tDot11fBeacon, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fBeacon, QOSCapsAp), offsetof(tDot11fIEQOSCapsAp, present), 0, "QOSCapsAp" , 0, 3, 3, SigIeQOSCapsAp, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSAP, 0, }, + {offsetof(tDot11fBeacon, APChannelReport), offsetof(tDot11fIEAPChannelReport, present), 0, "APChannelReport" , 0, 3, 53, SigIeAPChannelReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_APCHANNELREPORT, 0, }, + {offsetof(tDot11fBeacon, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fBeacon, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fBeacon, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, + {offsetof(tDot11fBeacon, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fBeacon, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fBeacon, sec_chan_offset_ele), offsetof(tDot11fIEsec_chan_offset_ele, present), 0, "sec_chan_offset_ele" , 0, 3, 3, SigIesec_chan_offset_ele, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SEC_CHAN_OFFSET_ELE, 0, }, + {offsetof(tDot11fBeacon, WMMInfoAp), offsetof(tDot11fIEWMMInfoAp, present), 0, "WMMInfoAp" , 0, 9, 9, SigIeWMMInfoAp, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOAP, 0, }, + {offsetof(tDot11fBeacon, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fBeacon, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fBeacon, WAPI), offsetof(tDot11fIEWAPI, present), 0, "WAPI" , 0, 14, 112, SigIeWAPI, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPI, 0, }, + {offsetof(tDot11fBeacon, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fBeacon, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {offsetof(tDot11fBeacon, ESETxmitPower), offsetof(tDot11fIEESETxmitPower, present), 0, "ESETxmitPower" , 0, 8, 8, SigIeESETxmitPower, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESETXMITPOWER, 0, }, + {offsetof(tDot11fBeacon, WscBeacon), offsetof(tDot11fIEWscBeacon, present), 0, "WscBeacon" , 0, 6, 84, SigIeWscBeacon, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCBEACON, 0, }, + {offsetof(tDot11fBeacon, P2PBeacon), offsetof(tDot11fIEP2PBeacon, present), 0, "P2PBeacon" , 0, 6, 61, SigIeP2PBeacon, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PBEACON, 0, }, + {offsetof(tDot11fBeacon, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fBeacon, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fBeacon, VHTExtBssLoad), offsetof(tDot11fIEVHTExtBssLoad, present), 0, "VHTExtBssLoad" , 0, 7, 7, SigIeVHTExtBssLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTEXTBSSLOAD, 0, }, + {offsetof(tDot11fBeacon, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {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, Vendor1IE), offsetof(tDot11fIEVendor1IE, present), 0, "Vendor1IE" , 0, 5, 5, SigIeVendor1IE, {0, 16, 24, 0, 0}, 3, DOT11F_EID_VENDOR1IE, 0, }, + {offsetof(tDot11fBeacon, Vendor2IE), offsetof(tDot11fIEVendor2IE, present), 0, "Vendor2IE" , 0, 5, 5, SigIeVendor2IE, {0, 144, 76, 0, 0}, 3, DOT11F_EID_VENDOR2IE, 0, }, + {offsetof(tDot11fBeacon, Vendor3IE), offsetof(tDot11fIEVendor3IE, present), 0, "Vendor3IE" , 0, 5, 5, SigIeVendor3IE, {0, 22, 50, 0, 0}, 3, DOT11F_EID_VENDOR3IE, 0, }, + {offsetof(tDot11fBeacon, ChannelSwitchWrapper), offsetof(tDot11fIEChannelSwitchWrapper, present), 0, "ChannelSwitchWrapper" , 0, 2, 7, SigIeChannelSwitchWrapper, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANNELSWITCHWRAPPER, 0, }, + {offsetof(tDot11fBeacon, QComVendorIE), offsetof(tDot11fIEQComVendorIE, present), 0, "QComVendorIE" , 0, 7, 7, SigIeQComVendorIE, {0, 160, 198, 0, 0}, 3, DOT11F_EID_QCOMVENDORIE, 0, }, + {offsetof(tDot11fBeacon, ESEVersion), offsetof(tDot11fIEESEVersion, present), 0, "ESEVersion" , 0, 7, 7, SigIeESEVersion, {0, 64, 150, 3, 0}, 4, DOT11F_EID_ESEVERSION, 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) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_Beacon, IES_Beacon, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Unpacked the Beacon:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->BeaconInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FHParamSet:\n")); + if (!pFrm->FHParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.dwell_time, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.hop_set, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.hop_pattern, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.hop_index, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("CFParams:\n")); + if (!pFrm->CFParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_maxduration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_durremaining, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TIM:\n")); + if (!pFrm->TIM.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TIM.dtim_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TIM.dtim_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TIM.bmpctl, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_vbmp: %d.\n"), pFrm->TIM.num_vbmp); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->TIM.vbmp, pFrm->TIM.num_vbmp); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FHParams:\n")); + if (!pFrm->FHParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParams.radix, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParams.nchannels, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FHPattTable:\n")); + if (!pFrm->FHPattTable.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.flag, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.nsets, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.modulus, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.offset, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_randtable: %d.\n"), pFrm->FHPattTable.num_randtable); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->FHPattTable.randtable, pFrm->FHPattTable.num_randtable); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("QBSSLoad:\n")); + if (!pFrm->QBSSLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QBSSLoad.stacount, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QBSSLoad.chautil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QBSSLoad.avail, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("QOSCapsAp:\n")); + if (!pFrm->QOSCapsAp.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("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WscBeacon:\n")); + if (!pFrm->WscBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Version:\n")); + if (!pFrm->WscBeacon.Version.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("minor (4): %d\n"), pFrm->WscBeacon.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("major (4): %d\n"), pFrm->WscBeacon.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WPSState:\n")); + if (!pFrm->WscBeacon.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APSetupLocked:\n")); + if (!pFrm->WscBeacon.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscBeacon.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscBeacon.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscBeacon.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("UUID_E:\n")); + if (!pFrm->WscBeacon.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RFBands:\n")); + if (!pFrm->WscBeacon.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VendorExtension:\n")); + if (!pFrm->WscBeacon.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Version2:\n")); + if (!pFrm->WscBeacon.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("major (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscBeacon.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscBeacon.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("P2PBeacon:\n")); + if (!pFrm->P2PBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("P2PCapability:\n")); + if (!pFrm->P2PBeacon.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PBeacon.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PBeacon.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_NoADesc: %d.\n"), pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->P2PBeacon.NoticeOfAbsence.NoADesc, pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeacon. */ + + static const tFFDefn FFS_Beacon1[] = { + { "TimeStamp", offsetof(tDot11fBeacon1, TimeStamp), SigFfTimeStamp , DOT11F_FF_TIMESTAMP_LEN, }, + { "BeaconInterval", offsetof(tDot11fBeacon1, BeaconInterval), SigFfBeaconInterval , DOT11F_FF_BEACONINTERVAL_LEN, }, + { "Capabilities", offsetof(tDot11fBeacon1, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_Beacon1[] = { + {offsetof(tDot11fBeacon1, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fBeacon1, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fBeacon1, DSParams), offsetof(tDot11fIEDSParams, present), 0, "DSParams" , 0, 3, 3, SigIeDSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_DSPARAMS, 0, }, + {offsetof(tDot11fBeacon1, IBSSParams), offsetof(tDot11fIEIBSSParams, present), 0, "IBSSParams" , 0, 4, 4, SigIeIBSSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IBSSPARAMS, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackBeacon1(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeacon1 *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_Beacon1, IES_Beacon1, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Unpacked the Beacon1:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("BeaconInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->BeaconInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("SSID:\n")); + if (!pFrm->SSID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeacon1. */ + + static const tFFDefn FFS_Beacon2[] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_Beacon2[] = { + {offsetof(tDot11fBeacon2, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fBeacon2, PowerConstraints), offsetof(tDot11fIEPowerConstraints, present), 0, "PowerConstraints" , 0, 3, 3, SigIePowerConstraints, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCONSTRAINTS, 0, }, + {offsetof(tDot11fBeacon2, ChanSwitchAnn), offsetof(tDot11fIEChanSwitchAnn, present), 0, "ChanSwitchAnn" , 0, 5, 5, SigIeChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANSWITCHANN, 0, }, + {offsetof(tDot11fBeacon2, ext_chan_switch_ann), offsetof(tDot11fIEext_chan_switch_ann, present), 0, "ext_chan_switch_ann" , 0, 6, 6, SigIeext_chan_switch_ann, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXT_CHAN_SWITCH_ANN, 0, }, + {offsetof(tDot11fBeacon2, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fBeacon2, Quiet), offsetof(tDot11fIEQuiet, present), 0, "Quiet" , 0, 8, 8, SigIeQuiet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QUIET, 0, }, + {offsetof(tDot11fBeacon2, TPCReport), offsetof(tDot11fIETPCReport, present), 0, "TPCReport" , 0, 4, 4, SigIeTPCReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TPCREPORT, 0, }, + {offsetof(tDot11fBeacon2, ERPInfo), offsetof(tDot11fIEERPInfo, present), 0, "ERPInfo" , 0, 3, 3, SigIeERPInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_ERPINFO, 0, }, + {offsetof(tDot11fBeacon2, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fBeacon2, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, + {offsetof(tDot11fBeacon2, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fBeacon2, APChannelReport), offsetof(tDot11fIEAPChannelReport, present), 0, "APChannelReport" , 0, 3, 53, SigIeAPChannelReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_APCHANNELREPORT, 0, }, + {offsetof(tDot11fBeacon2, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fBeacon2, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fBeacon2, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, + {offsetof(tDot11fBeacon2, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fBeacon2, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fBeacon2, sec_chan_offset_ele), offsetof(tDot11fIEsec_chan_offset_ele, present), 0, "sec_chan_offset_ele" , 0, 3, 3, SigIesec_chan_offset_ele, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SEC_CHAN_OFFSET_ELE, 0, }, + {offsetof(tDot11fBeacon2, WMMInfoAp), offsetof(tDot11fIEWMMInfoAp, present), 0, "WMMInfoAp" , 0, 9, 9, SigIeWMMInfoAp, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOAP, 0, }, + {offsetof(tDot11fBeacon2, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fBeacon2, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fBeacon2, WscBeacon), offsetof(tDot11fIEWscBeacon, present), 0, "WscBeacon" , 0, 6, 84, SigIeWscBeacon, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCBEACON, 0, }, + {offsetof(tDot11fBeacon2, WAPI), offsetof(tDot11fIEWAPI, present), 0, "WAPI" , 0, 14, 112, SigIeWAPI, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPI, 0, }, + {offsetof(tDot11fBeacon2, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fBeacon2, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {offsetof(tDot11fBeacon2, ESETxmitPower), offsetof(tDot11fIEESETxmitPower, present), 0, "ESETxmitPower" , 0, 8, 8, SigIeESETxmitPower, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESETXMITPOWER, 0, }, + {offsetof(tDot11fBeacon2, P2PBeacon), offsetof(tDot11fIEP2PBeacon, present), 0, "P2PBeacon" , 0, 6, 61, SigIeP2PBeacon, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PBEACON, 0, }, + {offsetof(tDot11fBeacon2, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fBeacon2, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fBeacon2, VHTExtBssLoad), offsetof(tDot11fIEVHTExtBssLoad, present), 0, "VHTExtBssLoad" , 0, 7, 7, SigIeVHTExtBssLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTEXTBSSLOAD, 0, }, + {offsetof(tDot11fBeacon2, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {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, Vendor1IE), offsetof(tDot11fIEVendor1IE, present), 0, "Vendor1IE" , 0, 5, 5, SigIeVendor1IE, {0, 16, 24, 0, 0}, 3, DOT11F_EID_VENDOR1IE, 0, }, + {offsetof(tDot11fBeacon2, Vendor2IE), offsetof(tDot11fIEVendor2IE, present), 0, "Vendor2IE" , 0, 5, 5, SigIeVendor2IE, {0, 144, 76, 0, 0}, 3, DOT11F_EID_VENDOR2IE, 0, }, + {offsetof(tDot11fBeacon2, Vendor3IE), offsetof(tDot11fIEVendor3IE, present), 0, "Vendor3IE" , 0, 5, 5, SigIeVendor3IE, {0, 22, 50, 0, 0}, 3, DOT11F_EID_VENDOR3IE, 0, }, + {offsetof(tDot11fBeacon2, ChannelSwitchWrapper), offsetof(tDot11fIEChannelSwitchWrapper, present), 0, "ChannelSwitchWrapper" , 0, 2, 7, SigIeChannelSwitchWrapper, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANNELSWITCHWRAPPER, 0, }, + {offsetof(tDot11fBeacon2, QComVendorIE), offsetof(tDot11fIEQComVendorIE, present), 0, "QComVendorIE" , 0, 7, 7, SigIeQComVendorIE, {0, 160, 198, 0, 0}, 3, DOT11F_EID_QCOMVENDORIE, 0, }, + {offsetof(tDot11fBeacon2, ESEVersion), offsetof(tDot11fIEESEVersion, present), 0, "ESEVersion" , 0, 7, 7, SigIeESEVersion, {0, 64, 150, 3, 0}, 4, DOT11F_EID_ESEVERSION, 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) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_Beacon2, IES_Beacon2, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Unpacked the Beacon2:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WscBeacon:\n")); + if (!pFrm->WscBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Version:\n")); + if (!pFrm->WscBeacon.Version.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("minor (4): %d\n"), pFrm->WscBeacon.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("major (4): %d\n"), pFrm->WscBeacon.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WPSState:\n")); + if (!pFrm->WscBeacon.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("APSetupLocked:\n")); + if (!pFrm->WscBeacon.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscBeacon.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscBeacon.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscBeacon.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("UUID_E:\n")); + if (!pFrm->WscBeacon.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RFBands:\n")); + if (!pFrm->WscBeacon.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VendorExtension:\n")); + if (!pFrm->WscBeacon.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Version2:\n")); + if (!pFrm->WscBeacon.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("major (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscBeacon.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscBeacon.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("P2PBeacon:\n")); + if (!pFrm->P2PBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("P2PCapability:\n")); + if (!pFrm->P2PBeacon.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PBeacon.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PBeacon.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_NoADesc: %d.\n"), pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->P2PBeacon.NoticeOfAbsence.NoADesc, pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeacon2. */ + + static const tFFDefn FFS_BeaconIEs[] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_BeaconIEs[] = { + {offsetof(tDot11fBeaconIEs, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fBeaconIEs, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fBeaconIEs, FHParamSet), offsetof(tDot11fIEFHParamSet, present), 0, "FHParamSet" , 0, 7, 7, SigIeFHParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPARAMSET, 0, }, + {offsetof(tDot11fBeaconIEs, DSParams), offsetof(tDot11fIEDSParams, present), 0, "DSParams" , 0, 3, 3, SigIeDSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_DSPARAMS, 0, }, + {offsetof(tDot11fBeaconIEs, CFParams), offsetof(tDot11fIECFParams, present), 0, "CFParams" , 0, 8, 8, SigIeCFParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CFPARAMS, 0, }, + {offsetof(tDot11fBeaconIEs, IBSSParams), offsetof(tDot11fIEIBSSParams, present), 0, "IBSSParams" , 0, 4, 4, SigIeIBSSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IBSSPARAMS, 0, }, + {offsetof(tDot11fBeaconIEs, TIM), offsetof(tDot11fIETIM, present), 0, "TIM" , 0, 6, 256, SigIeTIM, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIM, 0, }, + {offsetof(tDot11fBeaconIEs, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fBeaconIEs, FHParams), offsetof(tDot11fIEFHParams, present), 0, "FHParams" , 0, 4, 4, SigIeFHParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPARAMS, 0, }, + {offsetof(tDot11fBeaconIEs, FHPattTable), offsetof(tDot11fIEFHPattTable, present), 0, "FHPattTable" , 0, 6, 257, SigIeFHPattTable, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPATTTABLE, 0, }, + {offsetof(tDot11fBeaconIEs, PowerConstraints), offsetof(tDot11fIEPowerConstraints, present), 0, "PowerConstraints" , 0, 3, 3, SigIePowerConstraints, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCONSTRAINTS, 0, }, + {offsetof(tDot11fBeaconIEs, ChanSwitchAnn), offsetof(tDot11fIEChanSwitchAnn, present), 0, "ChanSwitchAnn" , 0, 5, 5, SigIeChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANSWITCHANN, 0, }, + {offsetof(tDot11fBeaconIEs, ext_chan_switch_ann), offsetof(tDot11fIEext_chan_switch_ann, present), 0, "ext_chan_switch_ann" , 0, 6, 6, SigIeext_chan_switch_ann, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXT_CHAN_SWITCH_ANN, 0, }, + {offsetof(tDot11fBeaconIEs, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fBeaconIEs, Quiet), offsetof(tDot11fIEQuiet, present), 0, "Quiet" , 0, 8, 8, SigIeQuiet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QUIET, 0, }, + {offsetof(tDot11fBeaconIEs, TPCReport), offsetof(tDot11fIETPCReport, present), 0, "TPCReport" , 0, 4, 4, SigIeTPCReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TPCREPORT, 0, }, + {offsetof(tDot11fBeaconIEs, ERPInfo), offsetof(tDot11fIEERPInfo, present), 0, "ERPInfo" , 0, 3, 3, SigIeERPInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_ERPINFO, 0, }, + {offsetof(tDot11fBeaconIEs, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fBeaconIEs, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 116, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, + {offsetof(tDot11fBeaconIEs, QBSSLoad), offsetof(tDot11fIEQBSSLoad, present), 0, "QBSSLoad" , 0, 7, 7, SigIeQBSSLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QBSSLOAD, 0, }, + {offsetof(tDot11fBeaconIEs, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fBeaconIEs, QOSCapsAp), offsetof(tDot11fIEQOSCapsAp, present), 0, "QOSCapsAp" , 0, 3, 3, SigIeQOSCapsAp, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSAP, 0, }, + {offsetof(tDot11fBeaconIEs, APChannelReport), offsetof(tDot11fIEAPChannelReport, present), 0, "APChannelReport" , 0, 3, 53, SigIeAPChannelReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_APCHANNELREPORT, 0, }, + {offsetof(tDot11fBeaconIEs, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fBeaconIEs, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fBeaconIEs, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, + {offsetof(tDot11fBeaconIEs, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fBeaconIEs, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fBeaconIEs, sec_chan_offset_ele), offsetof(tDot11fIEsec_chan_offset_ele, present), 0, "sec_chan_offset_ele" , 0, 3, 3, SigIesec_chan_offset_ele, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SEC_CHAN_OFFSET_ELE, 0, }, + {offsetof(tDot11fBeaconIEs, WMMInfoAp), offsetof(tDot11fIEWMMInfoAp, present), 0, "WMMInfoAp" , 0, 9, 9, SigIeWMMInfoAp, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOAP, 0, }, + {offsetof(tDot11fBeaconIEs, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fBeaconIEs, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fBeaconIEs, WAPI), offsetof(tDot11fIEWAPI, present), 0, "WAPI" , 0, 14, 112, SigIeWAPI, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPI, 0, }, + {offsetof(tDot11fBeaconIEs, ESEVersion), offsetof(tDot11fIEESEVersion, present), 0, "ESEVersion" , 0, 7, 7, SigIeESEVersion, {0, 64, 150, 3, 0}, 4, DOT11F_EID_ESEVERSION, 0, }, + {offsetof(tDot11fBeaconIEs, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fBeaconIEs, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {offsetof(tDot11fBeaconIEs, ESETxmitPower), offsetof(tDot11fIEESETxmitPower, present), 0, "ESETxmitPower" , 0, 8, 8, SigIeESETxmitPower, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESETXMITPOWER, 0, }, + {offsetof(tDot11fBeaconIEs, WscBeaconProbeRes), offsetof(tDot11fIEWscBeaconProbeRes, present), 0, "WscBeaconProbeRes" , 0, 6, 319, SigIeWscBeaconProbeRes, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCBEACONPROBERES, 0, }, + {offsetof(tDot11fBeaconIEs, P2PBeaconProbeRes), offsetof(tDot11fIEP2PBeaconProbeRes, present), 0, "P2PBeaconProbeRes" , 0, 6, 1150, SigIeP2PBeaconProbeRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PBEACONPROBERES, 0, }, + {offsetof(tDot11fBeaconIEs, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fBeaconIEs, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fBeaconIEs, VHTExtBssLoad), offsetof(tDot11fIEVHTExtBssLoad, present), 0, "VHTExtBssLoad" , 0, 7, 7, SigIeVHTExtBssLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTEXTBSSLOAD, 0, }, + {offsetof(tDot11fBeaconIEs, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {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, Vendor1IE), offsetof(tDot11fIEVendor1IE, present), 0, "Vendor1IE" , 0, 5, 5, SigIeVendor1IE, {0, 16, 24, 0, 0}, 3, DOT11F_EID_VENDOR1IE, 0, }, + {offsetof(tDot11fBeaconIEs, Vendor2IE), offsetof(tDot11fIEVendor2IE, present), 0, "Vendor2IE" , 0, 5, 5, SigIeVendor2IE, {0, 144, 76, 0, 0}, 3, DOT11F_EID_VENDOR2IE, 0, }, + {offsetof(tDot11fBeaconIEs, Vendor3IE), offsetof(tDot11fIEVendor3IE, present), 0, "Vendor3IE" , 0, 5, 5, SigIeVendor3IE, {0, 22, 50, 0, 0}, 3, DOT11F_EID_VENDOR3IE, 0, }, + {offsetof(tDot11fBeaconIEs, ChannelSwitchWrapper), offsetof(tDot11fIEChannelSwitchWrapper, present), 0, "ChannelSwitchWrapper" , 0, 2, 7, SigIeChannelSwitchWrapper, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANNELSWITCHWRAPPER, 0, }, + {offsetof(tDot11fBeaconIEs, QComVendorIE), offsetof(tDot11fIEQComVendorIE, present), 0, "QComVendorIE" , 0, 7, 7, SigIeQComVendorIE, {0, 160, 198, 0, 0}, 3, DOT11F_EID_QCOMVENDORIE, 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) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_BeaconIEs, IES_BeaconIEs, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Unpacked the BeaconIEs:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FHParamSet:\n")); + if (!pFrm->FHParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.dwell_time, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.hop_set, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.hop_pattern, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.hop_index, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("CFParams:\n")); + if (!pFrm->CFParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_maxduration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_durremaining, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("TIM:\n")); + if (!pFrm->TIM.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TIM.dtim_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TIM.dtim_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TIM.bmpctl, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_vbmp: %d.\n"), pFrm->TIM.num_vbmp); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->TIM.vbmp, pFrm->TIM.num_vbmp); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FHParams:\n")); + if (!pFrm->FHParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParams.radix, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParams.nchannels, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FHPattTable:\n")); + if (!pFrm->FHPattTable.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.flag, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.nsets, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.modulus, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.offset, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_randtable: %d.\n"), pFrm->FHPattTable.num_randtable); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->FHPattTable.randtable, pFrm->FHPattTable.num_randtable); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("QBSSLoad:\n")); + if (!pFrm->QBSSLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QBSSLoad.stacount, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QBSSLoad.chautil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QBSSLoad.avail, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("QOSCapsAp:\n")); + if (!pFrm->QOSCapsAp.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("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WscBeaconProbeRes:\n")); + if (!pFrm->WscBeaconProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Version:\n")); + if (!pFrm->WscBeaconProbeRes.Version.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("minor (4): %d\n"), pFrm->WscBeaconProbeRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("major (4): %d\n"), pFrm->WscBeaconProbeRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WPSState:\n")); + if (!pFrm->WscBeaconProbeRes.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APSetupLocked:\n")); + if (!pFrm->WscBeaconProbeRes.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscBeaconProbeRes.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscBeaconProbeRes.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscBeaconProbeRes.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ResponseType:\n")); + if (!pFrm->WscBeaconProbeRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("UUID_E:\n")); + if (!pFrm->WscBeaconProbeRes.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Manufacturer:\n")); + if (!pFrm->WscBeaconProbeRes.Manufacturer.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("num_name: %d.\n"), pFrm->WscBeaconProbeRes.Manufacturer.num_name); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.Manufacturer.name, pFrm->WscBeaconProbeRes.Manufacturer.num_name); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ModelName:\n")); + if (!pFrm->WscBeaconProbeRes.ModelName.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.ModelName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.ModelName.text, pFrm->WscBeaconProbeRes.ModelName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ModelNumber:\n")); + if (!pFrm->WscBeaconProbeRes.ModelNumber.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.ModelNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.ModelNumber.text, pFrm->WscBeaconProbeRes.ModelNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SerialNumber:\n")); + if (!pFrm->WscBeaconProbeRes.SerialNumber.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.SerialNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.SerialNumber.text, pFrm->WscBeaconProbeRes.SerialNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("PrimaryDeviceType:\n")); + if (!pFrm->WscBeaconProbeRes.PrimaryDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.PrimaryDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.PrimaryDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.PrimaryDeviceType.sub_category, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DeviceName:\n")); + if (!pFrm->WscBeaconProbeRes.DeviceName.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.DeviceName.text, pFrm->WscBeaconProbeRes.DeviceName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ConfigMethods:\n")); + if (!pFrm->WscBeaconProbeRes.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.ConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RFBands:\n")); + if (!pFrm->WscBeaconProbeRes.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VendorExtension:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Version2:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscBeaconProbeRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("major (4): %d\n"), pFrm->WscBeaconProbeRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PBeaconProbeRes:\n")); + if (!pFrm->P2PBeaconProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PCapability:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PBeaconProbeRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PBeaconProbeRes.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_NoADesc: %d.\n"), pFrm->P2PBeaconProbeRes.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->P2PBeaconProbeRes.NoticeOfAbsence.NoADesc, pFrm->P2PBeaconProbeRes.NoticeOfAbsence.num_NoADesc); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DeviceName:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.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("num_text: %d.\n"), pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.text, pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PGroupInfo:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PGroupInfo.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("num_P2PClientInfoDesc: %d.\n"), pFrm->P2PBeaconProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->P2PBeaconProbeRes.P2PGroupInfo.P2PClientInfoDesc, pFrm->P2PBeaconProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeaconIEs. */ + + static const tFFDefn FFS_ChannelSwitch[] = { + { "Category", offsetof(tDot11fChannelSwitch, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fChannelSwitch, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ChannelSwitch[] = { + {offsetof(tDot11fChannelSwitch, ChanSwitchAnn), offsetof(tDot11fIEChanSwitchAnn, present), 0, "ChanSwitchAnn" , 0, 5, 5, SigIeChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANSWITCHANN, 1, }, + {offsetof(tDot11fChannelSwitch, sec_chan_offset_ele), offsetof(tDot11fIEsec_chan_offset_ele, present), 0, "sec_chan_offset_ele" , 0, 3, 3, SigIesec_chan_offset_ele, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SEC_CHAN_OFFSET_ELE, 0, }, + {offsetof(tDot11fChannelSwitch, WiderBWChanSwitchAnn), offsetof(tDot11fIEWiderBWChanSwitchAnn, present), 0, "WiderBWChanSwitchAnn" , 0, 5, 5, SigIeWiderBWChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WIDERBWCHANSWITCHANN, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackChannelSwitch(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fChannelSwitch *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ChannelSwitch, IES_ChannelSwitch, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Unpacked the ChannelSwitch:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackChannelSwitch. */ + + static const tFFDefn FFS_DeAuth[] = { + { "Reason", offsetof(tDot11fDeAuth, Reason), SigFfReason , DOT11F_FF_REASON_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_DeAuth[] = { + {offsetof(tDot11fDeAuth, P2PDeAuth), offsetof(tDot11fIEP2PDeAuth, present), 0, "P2PDeAuth" , 0, 6, 10, SigIeP2PDeAuth, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PDEAUTH, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackDeAuth(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDeAuth *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_DeAuth, IES_DeAuth, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Unpacked the DeAuth:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("P2PDeAuth:\n")); + if (!pFrm->P2PDeAuth.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("MinorReasonCode:\n")); + if (!pFrm->P2PDeAuth.MinorReasonCode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), ( tANI_U8* )&pFrm->P2PDeAuth.MinorReasonCode.minorReasonCode, 1); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDeAuth. */ + + static const tFFDefn FFS_DelBAInd[] = { + { "Category", offsetof(tDot11fDelBAInd, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fDelBAInd, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DelBAParameterSet", offsetof(tDot11fDelBAInd, DelBAParameterSet), SigFfDelBAParameterSet , DOT11F_FF_DELBAPARAMETERSET_LEN, }, + { "Reason", offsetof(tDot11fDelBAInd, Reason), SigFfReason , DOT11F_FF_REASON_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_DelBAInd[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackDelBAInd(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDelBAInd *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_DelBAInd, IES_DelBAInd, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Unpacked the DelBAInd:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("DelBAParameterSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("reserved (11): %d\n"), pFrm->DelBAParameterSet.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("initiator (1): %d\n"), pFrm->DelBAParameterSet.initiator); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("tid (4): %d\n"), pFrm->DelBAParameterSet.tid); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), ( tANI_U8* )&pFrm->Reason.code, 2); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDelBAInd. */ + + static const tFFDefn FFS_DelTS[] = { + { "Category", offsetof(tDot11fDelTS, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fDelTS, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "TSInfo", offsetof(tDot11fDelTS, TSInfo), SigFfTSInfo , DOT11F_FF_TSINFO_LEN, }, + { "Reason", offsetof(tDot11fDelTS, Reason), SigFfReason , DOT11F_FF_REASON_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_DelTS[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackDelTS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDelTS *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_DelTS, IES_DelTS, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Unpacked the DelTS:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("TSInfo:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("traffic_type (1): %d\n"), pFrm->TSInfo.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("tsid (4): %d\n"), pFrm->TSInfo.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("direction (2): %d\n"), pFrm->TSInfo.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("access_policy (2): %d\n"), pFrm->TSInfo.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("aggregation (1): %d\n"), pFrm->TSInfo.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("psb (1): %d\n"), pFrm->TSInfo.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("user_priority (3): %d\n"), pFrm->TSInfo.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->TSInfo.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("schedule (1): %d\n"), pFrm->TSInfo.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("unused (15): %d\n"), pFrm->TSInfo.unused); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), ( tANI_U8* )&pFrm->Reason.code, 2); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDelTS. */ + + static const tFFDefn FFS_DeviceDiscoverabilityReq[] = { + { "Category", offsetof(tDot11fDeviceDiscoverabilityReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fDeviceDiscoverabilityReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fDeviceDiscoverabilityReq, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fDeviceDiscoverabilityReq, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fDeviceDiscoverabilityReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_DeviceDiscoverabilityReq[] = { + {offsetof(tDot11fDeviceDiscoverabilityReq, P2PDeviceDiscoverabilityReq), offsetof(tDot11fIEP2PDeviceDiscoverabilityReq, present), 0, "P2PDeviceDiscoverabilityReq" , 0, 6, 56, SigIeP2PDeviceDiscoverabilityReq, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PDEVICEDISCOVERABILITYREQ, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDeviceDiscoverabilityReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_DeviceDiscoverabilityReq, IES_DeviceDiscoverabilityReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Unpacked the DeviceDiscoverabilityReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2PDeviceDiscoverabilityReq:\n")); + if (!pFrm->P2PDeviceDiscoverabilityReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PDeviceDiscoverabilityReq.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2PDeviceDiscoverabilityReq.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("num_ssid: %d.\n"), pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* ) pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.ssid, pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.num_ssid); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDeviceDiscoverabilityReq. */ + + static const tFFDefn FFS_DeviceDiscoverabilityRes[] = { + { "Category", offsetof(tDot11fDeviceDiscoverabilityRes, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fDeviceDiscoverabilityRes, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fDeviceDiscoverabilityRes, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fDeviceDiscoverabilityRes, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fDeviceDiscoverabilityRes, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_DeviceDiscoverabilityRes[] = { + {offsetof(tDot11fDeviceDiscoverabilityRes, P2PDeviceDiscoverabilityRes), offsetof(tDot11fIEP2PDeviceDiscoverabilityRes, present), 0, "P2PDeviceDiscoverabilityRes" , 0, 6, 10, SigIeP2PDeviceDiscoverabilityRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PDEVICEDISCOVERABILITYRES, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDeviceDiscoverabilityRes *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_DeviceDiscoverabilityRes, IES_DeviceDiscoverabilityRes, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Unpacked the DeviceDiscoverabilityRes:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2PDeviceDiscoverabilityRes:\n")); + if (!pFrm->P2PDeviceDiscoverabilityRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PDeviceDiscoverabilityRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->P2PDeviceDiscoverabilityRes.P2PStatus.status, 1); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDeviceDiscoverabilityRes. */ + + static const tFFDefn FFS_Disassociation[] = { + { "Reason", offsetof(tDot11fDisassociation, Reason), SigFfReason , DOT11F_FF_REASON_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_Disassociation[] = { + {offsetof(tDot11fDisassociation, P2PDisAssoc), offsetof(tDot11fIEP2PDisAssoc, present), 0, "P2PDisAssoc" , 0, 6, 10, SigIeP2PDisAssoc, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PDISASSOC, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackDisassociation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fDisassociation *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_Disassociation, IES_Disassociation, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Unpacked the Disassociation:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("P2PDisAssoc:\n")); + if (!pFrm->P2PDisAssoc.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("MinorReasonCode:\n")); + if (!pFrm->P2PDisAssoc.MinorReasonCode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), ( tANI_U8* )&pFrm->P2PDisAssoc.MinorReasonCode.minorReasonCode, 1); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDisassociation. */ + + static const tFFDefn FFS_GODiscoverabilityReq[] = { + { "Category", offsetof(tDot11fGODiscoverabilityReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "P2POUI", offsetof(tDot11fGODiscoverabilityReq, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fGODiscoverabilityReq, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fGODiscoverabilityReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_GODiscoverabilityReq[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackGODiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGODiscoverabilityReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_GODiscoverabilityReq, IES_GODiscoverabilityReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("Unpacked the GODiscoverabilityReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGODiscoverabilityReq. */ + + static const tFFDefn FFS_GONegCnf[] = { + { "Category", offsetof(tDot11fGONegCnf, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fGONegCnf, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fGONegCnf, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fGONegCnf, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fGONegCnf, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_GONegCnf[] = { + {offsetof(tDot11fGONegCnf, P2PGONegCnf), offsetof(tDot11fIEP2PGONegCnf, present), 0, "P2PGONegCnf" , 0, 6, 321, SigIeP2PGONegCnf, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PGONEGCNF, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackGONegCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGONegCnf *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_GONegCnf, IES_GONegCnf, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Unpacked the GONegCnf:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PGONegCnf:\n")); + if (!pFrm->P2PGONegCnf.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PStatus:\n")); + if (!pFrm->P2PGONegCnf.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PCapability:\n")); + if (!pFrm->P2PGONegCnf.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PGONegCnf.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("ChannelList:\n")); + if (!pFrm->P2PGONegCnf.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("num_channelList: %d.\n"), pFrm->P2PGONegCnf.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* ) pFrm->P2PGONegCnf.ChannelList.channelList, pFrm->P2PGONegCnf.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PGONegCnf.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("num_ssid: %d.\n"), pFrm->P2PGONegCnf.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* ) pFrm->P2PGONegCnf.P2PGroupId.ssid, pFrm->P2PGONegCnf.P2PGroupId.num_ssid); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGONegCnf. */ + + static const tFFDefn FFS_GONegReq[] = { + { "Category", offsetof(tDot11fGONegReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fGONegReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fGONegReq, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fGONegReq, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fGONegReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_GONegReq[] = { + {offsetof(tDot11fGONegReq, P2PGONegWPS), offsetof(tDot11fIEP2PGONegWPS, present), 0, "P2PGONegWPS" , 0, 6, 17, SigIeP2PGONegWPS, {0, 80, 242, 4, 0}, 4, DOT11F_EID_P2PGONEGWPS, 1, }, + {offsetof(tDot11fGONegReq, P2PGONegReq), offsetof(tDot11fIEP2PGONegReq, present), 0, "P2PGONegReq" , 0, 6, 364, SigIeP2PGONegReq, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PGONEGREQ, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackGONegReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGONegReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_GONegReq, IES_GONegReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Unpacked the GONegReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PGONegWPS:\n")); + if (!pFrm->P2PGONegWPS.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Version:\n")); + if (!pFrm->P2PGONegWPS.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("minor (4): %d\n"), pFrm->P2PGONegWPS.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("major (4): %d\n"), pFrm->P2PGONegWPS.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("DevicePasswordID:\n")); + if (!pFrm->P2PGONegWPS.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegWPS.DevicePasswordID.id, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PGONegReq:\n")); + if (!pFrm->P2PGONegReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PCapability:\n")); + if (!pFrm->P2PGONegReq.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("GOIntent:\n")); + if (!pFrm->P2PGONegReq.GOIntent.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.GOIntent.GOIntent, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PGONegReq.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ListenChannel:\n")); + if (!pFrm->P2PGONegReq.ListenChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ListenChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ListenChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ListenChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PGONegReq.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("IntendedP2PInterfaceAddress:\n")); + if (!pFrm->P2PGONegReq.IntendedP2PInterfaceAddress.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.IntendedP2PInterfaceAddress.P2PInterfaceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ChannelList:\n")); + if (!pFrm->P2PGONegReq.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("num_channelList: %d.\n"), pFrm->P2PGONegReq.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* ) pFrm->P2PGONegReq.ChannelList.channelList, pFrm->P2PGONegReq.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PGONegReq.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("DeviceName:\n")); + if (!pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("num_text: %d.\n"), pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* ) pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.text, pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PGONegReq.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.OperatingChannel.channel, 1); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGONegReq. */ + + static const tFFDefn FFS_GONegRes[] = { + { "Category", offsetof(tDot11fGONegRes, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fGONegRes, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fGONegRes, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fGONegRes, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fGONegRes, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_GONegRes[] = { + {offsetof(tDot11fGONegRes, P2PGONegWPS), offsetof(tDot11fIEP2PGONegWPS, present), 0, "P2PGONegWPS" , 0, 6, 17, SigIeP2PGONegWPS, {0, 80, 242, 4, 0}, 4, DOT11F_EID_P2PGONEGWPS, 1, }, + {offsetof(tDot11fGONegRes, P2PGONegRes), offsetof(tDot11fIEP2PGONegRes, present), 0, "P2PGONegRes" , 0, 6, 394, SigIeP2PGONegRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PGONEGRES, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackGONegRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fGONegRes *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_GONegRes, IES_GONegRes, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Unpacked the GONegRes:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PGONegWPS:\n")); + if (!pFrm->P2PGONegWPS.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Version:\n")); + if (!pFrm->P2PGONegWPS.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("minor (4): %d\n"), pFrm->P2PGONegWPS.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("major (4): %d\n"), pFrm->P2PGONegWPS.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("DevicePasswordID:\n")); + if (!pFrm->P2PGONegWPS.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegWPS.DevicePasswordID.id, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PGONegRes:\n")); + if (!pFrm->P2PGONegRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PGONegRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PCapability:\n")); + if (!pFrm->P2PGONegRes.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("GOIntent:\n")); + if (!pFrm->P2PGONegRes.GOIntent.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.GOIntent.GOIntent, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PGONegRes.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PGONegRes.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("IntendedP2PInterfaceAddress:\n")); + if (!pFrm->P2PGONegRes.IntendedP2PInterfaceAddress.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.IntendedP2PInterfaceAddress.P2PInterfaceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("ChannelList:\n")); + if (!pFrm->P2PGONegRes.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("num_channelList: %d.\n"), pFrm->P2PGONegRes.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* ) pFrm->P2PGONegRes.ChannelList.channelList, pFrm->P2PGONegRes.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PGONegRes.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("DeviceName:\n")); + if (!pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("num_text: %d.\n"), pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* ) pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.text, pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PGONegRes.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("num_ssid: %d.\n"), pFrm->P2PGONegRes.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* ) pFrm->P2PGONegRes.P2PGroupId.ssid, pFrm->P2PGONegRes.P2PGroupId.num_ssid); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGONegRes. */ + + static const tFFDefn FFS_HT2040BSSCoexistenceManagementActionFrame[] = { + { "Category", offsetof(tDot11fHT2040BSSCoexistenceManagementActionFrame, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fHT2040BSSCoexistenceManagementActionFrame, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_HT2040BSSCoexistenceManagementActionFrame[] = { + {offsetof(tDot11fHT2040BSSCoexistenceManagementActionFrame, HT2040BSSCoexistence), offsetof(tDot11fIEHT2040BSSCoexistence, present), 0, "HT2040BSSCoexistence" , 0, 3, 3, SigIeHT2040BSSCoexistence, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040BSSCOEXISTENCE, 1, }, + {offsetof(tDot11fHT2040BSSCoexistenceManagementActionFrame, HT2040BSSIntolerantReport), offsetof(tDot11fIEHT2040BSSIntolerantReport, present), 0, "HT2040BSSIntolerantReport" , 0, 3, 53, SigIeHT2040BSSIntolerantReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040BSSINTOLERANTREPORT, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackHT2040BSSCoexistenceManagementActionFrame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_HT2040BSSCoexistenceManagementActionFrame, IES_HT2040BSSCoexistenceManagementActionFrame, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Unpacked the HT2040BSSCoexistenceManagementActionFrame:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("HT2040BSSIntolerantReport:\n")); + if (!pFrm->HT2040BSSIntolerantReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->HT2040BSSIntolerantReport.operatingClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("num_channelList: %d.\n"), pFrm->HT2040BSSIntolerantReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* ) pFrm->HT2040BSSIntolerantReport.channelList, pFrm->HT2040BSSIntolerantReport.num_channelList); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackHT2040BSSCoexistenceManagementActionFrame. */ + + static const tFFDefn FFS_InvitationReq[] = { + { "Category", offsetof(tDot11fInvitationReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fInvitationReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fInvitationReq, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fInvitationReq, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fInvitationReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_InvitationReq[] = { + {offsetof(tDot11fInvitationReq, P2PInvitationReq), offsetof(tDot11fIEP2PInvitationReq, present), 0, "P2PInvitationReq" , 0, 6, 385, SigIeP2PInvitationReq, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PINVITATIONREQ, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackInvitationReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fInvitationReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_InvitationReq, IES_InvitationReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Unpacked the InvitationReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PInvitationReq:\n")); + if (!pFrm->P2PInvitationReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PInvitationReq.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("InvitationFlags:\n")); + if (!pFrm->P2PInvitationReq.InvitationFlags.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.InvitationFlags.invitationFlags, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PInvitationReq.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PGroupBssid:\n")); + if (!pFrm->P2PInvitationReq.P2PGroupBssid.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PGroupBssid.P2PGroupBssid, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("ChannelList:\n")); + if (!pFrm->P2PInvitationReq.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("num_channelList: %d.\n"), pFrm->P2PInvitationReq.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* ) pFrm->P2PInvitationReq.ChannelList.channelList, pFrm->P2PInvitationReq.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PInvitationReq.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("num_ssid: %d.\n"), pFrm->P2PInvitationReq.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* ) pFrm->P2PInvitationReq.P2PGroupId.ssid, pFrm->P2PInvitationReq.P2PGroupId.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PInvitationReq.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("DeviceName:\n")); + if (!pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("num_text: %d.\n"), pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* ) pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.text, pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.num_text); + } + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackInvitationReq. */ + + static const tFFDefn FFS_InvitationRes[] = { + { "Category", offsetof(tDot11fInvitationRes, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fInvitationRes, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fInvitationRes, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fInvitationRes, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fInvitationRes, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_InvitationRes[] = { + {offsetof(tDot11fInvitationRes, P2PInvitationRes), offsetof(tDot11fIEP2PInvitationRes, present), 0, "P2PInvitationRes" , 0, 6, 289, SigIeP2PInvitationRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PINVITATIONRES, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackInvitationRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fInvitationRes *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_InvitationRes, IES_InvitationRes, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Unpacked the InvitationRes:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2PInvitationRes:\n")); + if (!pFrm->P2PInvitationRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PInvitationRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PInvitationRes.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PInvitationRes.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2PGroupBssid:\n")); + if (!pFrm->P2PInvitationRes.P2PGroupBssid.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.P2PGroupBssid.P2PGroupBssid, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("ChannelList:\n")); + if (!pFrm->P2PInvitationRes.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("num_channelList: %d.\n"), pFrm->P2PInvitationRes.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* ) pFrm->P2PInvitationRes.ChannelList.channelList, pFrm->P2PInvitationRes.ChannelList.num_channelList); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackInvitationRes. */ + + static const tFFDefn FFS_LinkMeasurementReport[] = { + { "Category", offsetof(tDot11fLinkMeasurementReport, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fLinkMeasurementReport, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fLinkMeasurementReport, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "TPCEleID", offsetof(tDot11fLinkMeasurementReport, TPCEleID), SigFfTPCEleID , DOT11F_FF_TPCELEID_LEN, }, + { "TPCEleLen", offsetof(tDot11fLinkMeasurementReport, TPCEleLen), SigFfTPCEleLen , DOT11F_FF_TPCELELEN_LEN, }, + { "TxPower", offsetof(tDot11fLinkMeasurementReport, TxPower), SigFfTxPower , DOT11F_FF_TXPOWER_LEN, }, + { "LinkMargin", offsetof(tDot11fLinkMeasurementReport, LinkMargin), SigFfLinkMargin , DOT11F_FF_LINKMARGIN_LEN, }, + { "RxAntennaId", offsetof(tDot11fLinkMeasurementReport, RxAntennaId), SigFfRxAntennaId , DOT11F_FF_RXANTENNAID_LEN, }, + { "TxAntennaId", offsetof(tDot11fLinkMeasurementReport, TxAntennaId), SigFfTxAntennaId , DOT11F_FF_TXANTENNAID_LEN, }, + { "RCPI", offsetof(tDot11fLinkMeasurementReport, RCPI), SigFfRCPI , DOT11F_FF_RCPI_LEN, }, + { "RSNI", offsetof(tDot11fLinkMeasurementReport, RSNI), SigFfRSNI , DOT11F_FF_RSNI_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_LinkMeasurementReport[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackLinkMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fLinkMeasurementReport *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_LinkMeasurementReport, IES_LinkMeasurementReport, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("Unpacked the LinkMeasurementReport:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TPCEleID:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TPCEleID.TPCId, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TPCEleLen:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TPCEleLen.TPCLen, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TxPower:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TxPower.txPower, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("LinkMargin:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->LinkMargin.linkMargin, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("RxAntennaId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->RxAntennaId.antennaId, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TxAntennaId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TxAntennaId.antennaId, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("RCPI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->RCPI.rcpi, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("RSNI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->RSNI.rsni, 1); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackLinkMeasurementReport. */ + + static const tFFDefn FFS_LinkMeasurementRequest[] = { + { "Category", offsetof(tDot11fLinkMeasurementRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fLinkMeasurementRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fLinkMeasurementRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "TxPower", offsetof(tDot11fLinkMeasurementRequest, TxPower), SigFfTxPower , DOT11F_FF_TXPOWER_LEN, }, + { "MaxTxPower", offsetof(tDot11fLinkMeasurementRequest, MaxTxPower), SigFfMaxTxPower , DOT11F_FF_MAXTXPOWER_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_LinkMeasurementRequest[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackLinkMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fLinkMeasurementRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_LinkMeasurementRequest, IES_LinkMeasurementRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("Unpacked the LinkMeasurementRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("TxPower:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->TxPower.txPower, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("MaxTxPower:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MaxTxPower.maxTxPower, 1); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackLinkMeasurementRequest. */ + + static const tFFDefn FFS_MeasurementReport[] = { + { "Category", offsetof(tDot11fMeasurementReport, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fMeasurementReport, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fMeasurementReport, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_MeasurementReport[] = { + {offsetof(tDot11fMeasurementReport, MeasurementReport), offsetof(tDot11fIEMeasurementReport, present), 0, "MeasurementReport" , 0, 5, 31, SigIeMeasurementReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MEASUREMENTREPORT, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fMeasurementReport *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_MeasurementReport, IES_MeasurementReport, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Unpacked the MeasurementReport:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("MeasurementReport:\n")); + if (!pFrm->MeasurementReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("late (1): %d\n"), pFrm->MeasurementReport.late); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("incapable (1): %d\n"), pFrm->MeasurementReport.incapable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("refused (1): %d\n"), pFrm->MeasurementReport.refused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unused (5): %d\n"), pFrm->MeasurementReport.unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.type, 1); + switch (pFrm->MeasurementReport.type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Basic.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Basic.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("bss (1): %d\n"), pFrm->MeasurementReport.report.Basic.bss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("ofdm_preamble (1): %d\n"), pFrm->MeasurementReport.report.Basic.ofdm_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unid_signal (1): %d\n"), pFrm->MeasurementReport.report.Basic.unid_signal); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("rader (1): %d\n"), pFrm->MeasurementReport.report.Basic.rader); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unmeasured (1): %d\n"), pFrm->MeasurementReport.report.Basic.unmeasured); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unused (3): %d\n"), pFrm->MeasurementReport.report.Basic.unused); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.cca_busy_fraction, 1); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi0_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi1_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi2_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi3_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi4_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi5_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi6_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi7_density, 1); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("condensed_PHY (7): %d\n"), pFrm->MeasurementReport.report.Beacon.condensed_PHY); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("reported_frame_type (1): %d\n"), pFrm->MeasurementReport.report.Beacon.reported_frame_type); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.RCPI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.RSNI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.BSSID, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.antenna_id, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.parent_TSF, 4); + break; + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackMeasurementReport. */ + + static const tFFDefn FFS_MeasurementRequest[] = { + { "Category", offsetof(tDot11fMeasurementRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fMeasurementRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fMeasurementRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_MeasurementRequest[] = { + {offsetof(tDot11fMeasurementRequest, MeasurementRequest), offsetof(tDot11fIEMeasurementRequest, present), offsetof(tDot11fMeasurementRequest, num_MeasurementRequest), "MeasurementRequest" , 4, 16, 18, SigIeMeasurementRequest, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MEASUREMENTREQUEST, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fMeasurementRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_MeasurementRequest, IES_MeasurementRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Unpacked the MeasurementRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + for (i = 0; i < pFrm->num_MeasurementRequest; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("MeasurementRequest[%d]:\n"), i); + if (!pFrm->MeasurementRequest[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("parallel (1): %d\n"), pFrm->MeasurementRequest[i].parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("enable (1): %d\n"), pFrm->MeasurementRequest[i].enable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("request (1): %d\n"), pFrm->MeasurementRequest[i].request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("report (1): %d\n"), pFrm->MeasurementRequest[i].report); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("durationMandatory (1): %d\n"), pFrm->MeasurementRequest[i].durationMandatory); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("unused (3): %d\n"), pFrm->MeasurementRequest[i].unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_type, 1); + switch (pFrm->MeasurementRequest[i].measurement_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_duration, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_duration, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_duration, 2); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.randomization, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.BSSID, 6); + break; + } + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackMeasurementRequest. */ + + static const tFFDefn FFS_NeighborReportRequest[] = { + { "Category", offsetof(tDot11fNeighborReportRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fNeighborReportRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fNeighborReportRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_NeighborReportRequest[] = { + {offsetof(tDot11fNeighborReportRequest, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackNeighborReportRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fNeighborReportRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_NeighborReportRequest, IES_NeighborReportRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Unpacked the NeighborReportRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackNeighborReportRequest. */ + + static const tFFDefn FFS_NeighborReportResponse[] = { + { "Category", offsetof(tDot11fNeighborReportResponse, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fNeighborReportResponse, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fNeighborReportResponse, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_NeighborReportResponse[] = { + {offsetof(tDot11fNeighborReportResponse, NeighborReport), offsetof(tDot11fIENeighborReport, present), offsetof(tDot11fNeighborReportResponse, num_NeighborReport), "NeighborReport" , 15, 15, 548, SigIeNeighborReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_NEIGHBORREPORT, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackNeighborReportResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fNeighborReportResponse *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_NeighborReportResponse, IES_NeighborReportResponse, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Unpacked the NeighborReportResponse:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->DialogToken.token, 1); + for (i = 0; i < pFrm->num_NeighborReport; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NeighborReport[%d]:\n"), i); + if (!pFrm->NeighborReport[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].bssid, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("APReachability (2): %d\n"), pFrm->NeighborReport[i].APReachability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Security (1): %d\n"), pFrm->NeighborReport[i].Security); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("KeyScope (1): %d\n"), pFrm->NeighborReport[i].KeyScope); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("SpecMgmtCap (1): %d\n"), pFrm->NeighborReport[i].SpecMgmtCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("QosCap (1): %d\n"), pFrm->NeighborReport[i].QosCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("apsd (1): %d\n"), pFrm->NeighborReport[i].apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("rrm (1): %d\n"), pFrm->NeighborReport[i].rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("DelayedBA (1): %d\n"), pFrm->NeighborReport[i].DelayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("ImmBA (1): %d\n"), pFrm->NeighborReport[i].ImmBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MobilityDomain (1): %d\n"), pFrm->NeighborReport[i].MobilityDomain); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("reserved (5): %d\n"), pFrm->NeighborReport[i].reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].reserved1, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].PhyType, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("TSFInfo:\n")); + if (!pFrm->NeighborReport[i].TSFInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].TSFInfo.TsfOffset, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].TSFInfo.BeaconIntvl, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("CondensedCountryStr:\n")); + if (!pFrm->NeighborReport[i].CondensedCountryStr.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].CondensedCountryStr.countryStr, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MeasurementPilot:\n")); + if (!pFrm->NeighborReport[i].MeasurementPilot.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].MeasurementPilot.measurementPilot, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("num_vendorSpecific: %d.\n"), pFrm->NeighborReport[i].MeasurementPilot.num_vendorSpecific); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* ) pFrm->NeighborReport[i].MeasurementPilot.vendorSpecific, pFrm->NeighborReport[i].MeasurementPilot.num_vendorSpecific); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->NeighborReport[i].RRMEnabledCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("LinkMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("parallel (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("repeated (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("statistics (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("reserved (4): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MultiBssid:\n")); + if (!pFrm->NeighborReport[i].MultiBssid.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].MultiBssid.maxBSSIDIndicator, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("num_vendorSpecific: %d.\n"), pFrm->NeighborReport[i].MultiBssid.num_vendorSpecific); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* ) pFrm->NeighborReport[i].MultiBssid.vendorSpecific, pFrm->NeighborReport[i].MultiBssid.num_vendorSpecific); + } + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackNeighborReportResponse. */ + + static const tFFDefn FFS_NoticeOfAbs[] = { + { "Category", offsetof(tDot11fNoticeOfAbs, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "P2POUI", offsetof(tDot11fNoticeOfAbs, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fNoticeOfAbs, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fNoticeOfAbs, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_NoticeOfAbs[] = { + {offsetof(tDot11fNoticeOfAbs, P2PNoticeOfAbsence), offsetof(tDot11fIEP2PNoticeOfAbsence, present), 0, "P2PNoticeOfAbsence" , 0, 6, 47, SigIeP2PNoticeOfAbsence, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PNOTICEOFABSENCE, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackNoticeOfAbs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fNoticeOfAbs *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_NoticeOfAbs, IES_NoticeOfAbs, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Unpacked the NoticeOfAbs:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("P2PNoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("num_NoADesc: %d.\n"), pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* ) pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.NoADesc, pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackNoticeOfAbs. */ + + static const tFFDefn FFS_OperatingMode[] = { + { "Category", offsetof(tDot11fOperatingMode, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fOperatingMode, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "OperatingMode", offsetof(tDot11fOperatingMode, OperatingMode), SigFfOperatingMode , DOT11F_FF_OPERATINGMODE_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_OperatingMode[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fOperatingMode *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_OperatingMode, IES_OperatingMode, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("Unpacked the OperatingMode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("OperatingMode:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackOperatingMode. */ + + static const tFFDefn FFS_PresenceReq[] = { + { "Category", offsetof(tDot11fPresenceReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "P2POUI", offsetof(tDot11fPresenceReq, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fPresenceReq, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fPresenceReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_PresenceReq[] = { + {offsetof(tDot11fPresenceReq, P2PNoticeOfAbsence), offsetof(tDot11fIEP2PNoticeOfAbsence, present), 0, "P2PNoticeOfAbsence" , 0, 6, 47, SigIeP2PNoticeOfAbsence, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PNOTICEOFABSENCE, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackPresenceReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fPresenceReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_PresenceReq, IES_PresenceReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Unpacked the PresenceReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("P2PNoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("num_NoADesc: %d.\n"), pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* ) pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.NoADesc, pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackPresenceReq. */ + + static const tFFDefn FFS_PresenceRes[] = { + { "Category", offsetof(tDot11fPresenceRes, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "P2POUI", offsetof(tDot11fPresenceRes, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fPresenceRes, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fPresenceRes, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_PresenceRes[] = { + {offsetof(tDot11fPresenceRes, P2PPresenceResponse), offsetof(tDot11fIEP2PPresenceResponse, present), 0, "P2PPresenceResponse" , 0, 6, 51, SigIeP2PPresenceResponse, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PPRESENCERESPONSE, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackPresenceRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fPresenceRes *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_PresenceRes, IES_PresenceRes, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Unpacked the PresenceRes:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2PPresenceResponse:\n")); + if (!pFrm->P2PPresenceResponse.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PPresenceResponse.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2PPresenceResponse.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PPresenceResponse.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2PPresenceResponse.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2PPresenceResponse.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("num_NoADesc: %d.\n"), pFrm->P2PPresenceResponse.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* ) pFrm->P2PPresenceResponse.NoticeOfAbsence.NoADesc, pFrm->P2PPresenceResponse.NoticeOfAbsence.num_NoADesc); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackPresenceRes. */ + + static const tFFDefn FFS_ProbeRequest[] = { + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ProbeRequest[] = { + {offsetof(tDot11fProbeRequest, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fProbeRequest, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fProbeRequest, RequestedInfo), offsetof(tDot11fIERequestedInfo, present), 0, "RequestedInfo" , 0, 2, 257, SigIeRequestedInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_REQUESTEDINFO, 0, }, + {offsetof(tDot11fProbeRequest, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fProbeRequest, DSParams), offsetof(tDot11fIEDSParams, present), 0, "DSParams" , 0, 3, 3, SigIeDSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_DSPARAMS, 0, }, + {offsetof(tDot11fProbeRequest, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fProbeRequest, WscProbeReq), offsetof(tDot11fIEWscProbeReq, present), 0, "WscProbeReq" , 0, 6, 286, SigIeWscProbeReq, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCPROBEREQ, 0, }, + {offsetof(tDot11fProbeRequest, WFATPC), offsetof(tDot11fIEWFATPC, present), 0, "WFATPC" , 0, 9, 9, SigIeWFATPC, {0, 80, 242, 8, 0}, 5, DOT11F_EID_WFATPC, 0, }, + {offsetof(tDot11fProbeRequest, P2PProbeReq), offsetof(tDot11fIEP2PProbeReq, present), 0, "P2PProbeReq" , 0, 6, 43, SigIeP2PProbeReq, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PPROBEREQ, 0, }, + {offsetof(tDot11fProbeRequest, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fProbeRequest, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackProbeRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProbeRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ProbeRequest, IES_ProbeRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Unpacked the ProbeRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestedInfo:\n")); + if (!pFrm->RequestedInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_requested_eids: %d.\n"), pFrm->RequestedInfo.num_requested_eids); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->RequestedInfo.requested_eids, pFrm->RequestedInfo.num_requested_eids); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("WscProbeReq:\n")); + if (!pFrm->WscProbeReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Version:\n")); + if (!pFrm->WscProbeReq.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("minor (4): %d\n"), pFrm->WscProbeReq.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("major (4): %d\n"), pFrm->WscProbeReq.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestType:\n")); + if (!pFrm->WscProbeReq.RequestType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestType.reqType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ConfigMethods:\n")); + if (!pFrm->WscProbeReq.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.ConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("UUID_E:\n")); + if (!pFrm->WscProbeReq.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("PrimaryDeviceType:\n")); + if (!pFrm->WscProbeReq.PrimaryDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.PrimaryDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.PrimaryDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.PrimaryDeviceType.sub_category, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RFBands:\n")); + if (!pFrm->WscProbeReq.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("AssociationState:\n")); + if (!pFrm->WscProbeReq.AssociationState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.AssociationState.state, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ConfigurationError:\n")); + if (!pFrm->WscProbeReq.ConfigurationError.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.ConfigurationError.error, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscProbeReq.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Manufacturer:\n")); + if (!pFrm->WscProbeReq.Manufacturer.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_name: %d.\n"), pFrm->WscProbeReq.Manufacturer.num_name); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.Manufacturer.name, pFrm->WscProbeReq.Manufacturer.num_name); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ModelName:\n")); + if (!pFrm->WscProbeReq.ModelName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_text: %d.\n"), pFrm->WscProbeReq.ModelName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.ModelName.text, pFrm->WscProbeReq.ModelName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ModelNumber:\n")); + if (!pFrm->WscProbeReq.ModelNumber.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_text: %d.\n"), pFrm->WscProbeReq.ModelNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.ModelNumber.text, pFrm->WscProbeReq.ModelNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("DeviceName:\n")); + if (!pFrm->WscProbeReq.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_text: %d.\n"), pFrm->WscProbeReq.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.DeviceName.text, pFrm->WscProbeReq.DeviceName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("VendorExtension:\n")); + if (!pFrm->WscProbeReq.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Version2:\n")); + if (!pFrm->WscProbeReq.VendorExtension.Version2.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("minor (4): %d\n"), pFrm->WscProbeReq.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("major (4): %d\n"), pFrm->WscProbeReq.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscProbeReq.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscProbeReq.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.VendorExtension.RequestToEnroll.req, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestDeviceType:\n")); + if (!pFrm->WscProbeReq.RequestDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestDeviceType.sub_category, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("WFATPC:\n")); + if (!pFrm->WFATPC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WFATPC.txPower, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WFATPC.linkMargin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("P2PProbeReq:\n")); + if (!pFrm->P2PProbeReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("P2PCapability:\n")); + if (!pFrm->P2PProbeReq.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PProbeReq.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ListenChannel:\n")); + if (!pFrm->P2PProbeReq.ListenChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ListenChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ListenChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ListenChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PProbeReq.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PProbeReq.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.OperatingChannel.channel, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProbeRequest. */ + + static const tFFDefn FFS_ProbeResponse[] = { + { "TimeStamp", offsetof(tDot11fProbeResponse, TimeStamp), SigFfTimeStamp , DOT11F_FF_TIMESTAMP_LEN, }, + { "BeaconInterval", offsetof(tDot11fProbeResponse, BeaconInterval), SigFfBeaconInterval , DOT11F_FF_BEACONINTERVAL_LEN, }, + { "Capabilities", offsetof(tDot11fProbeResponse, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ProbeResponse[] = { + {offsetof(tDot11fProbeResponse, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fProbeResponse, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fProbeResponse, FHParamSet), offsetof(tDot11fIEFHParamSet, present), 0, "FHParamSet" , 0, 7, 7, SigIeFHParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPARAMSET, 0, }, + {offsetof(tDot11fProbeResponse, DSParams), offsetof(tDot11fIEDSParams, present), 0, "DSParams" , 0, 3, 3, SigIeDSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_DSPARAMS, 0, }, + {offsetof(tDot11fProbeResponse, CFParams), offsetof(tDot11fIECFParams, present), 0, "CFParams" , 0, 8, 8, SigIeCFParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CFPARAMS, 0, }, + {offsetof(tDot11fProbeResponse, IBSSParams), offsetof(tDot11fIEIBSSParams, present), 0, "IBSSParams" , 0, 4, 4, SigIeIBSSParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IBSSPARAMS, 0, }, + {offsetof(tDot11fProbeResponse, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fProbeResponse, FHParams), offsetof(tDot11fIEFHParams, present), 0, "FHParams" , 0, 4, 4, SigIeFHParams, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPARAMS, 0, }, + {offsetof(tDot11fProbeResponse, FHPattTable), offsetof(tDot11fIEFHPattTable, present), 0, "FHPattTable" , 0, 6, 257, SigIeFHPattTable, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FHPATTTABLE, 0, }, + {offsetof(tDot11fProbeResponse, PowerConstraints), offsetof(tDot11fIEPowerConstraints, present), 0, "PowerConstraints" , 0, 3, 3, SigIePowerConstraints, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCONSTRAINTS, 0, }, + {offsetof(tDot11fProbeResponse, ChanSwitchAnn), offsetof(tDot11fIEChanSwitchAnn, present), 0, "ChanSwitchAnn" , 0, 5, 5, SigIeChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANSWITCHANN, 0, }, + {offsetof(tDot11fProbeResponse, ext_chan_switch_ann), offsetof(tDot11fIEext_chan_switch_ann, present), 0, "ext_chan_switch_ann" , 0, 6, 6, SigIeext_chan_switch_ann, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXT_CHAN_SWITCH_ANN, 0, }, + {offsetof(tDot11fProbeResponse, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fProbeResponse, Quiet), offsetof(tDot11fIEQuiet, present), 0, "Quiet" , 0, 8, 8, SigIeQuiet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QUIET, 0, }, + {offsetof(tDot11fProbeResponse, TPCReport), offsetof(tDot11fIETPCReport, present), 0, "TPCReport" , 0, 4, 4, SigIeTPCReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TPCREPORT, 0, }, + {offsetof(tDot11fProbeResponse, ERPInfo), offsetof(tDot11fIEERPInfo, present), 0, "ERPInfo" , 0, 3, 3, SigIeERPInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_ERPINFO, 0, }, + {offsetof(tDot11fProbeResponse, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fProbeResponse, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, + {offsetof(tDot11fProbeResponse, QBSSLoad), offsetof(tDot11fIEQBSSLoad, present), 0, "QBSSLoad" , 0, 7, 7, SigIeQBSSLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QBSSLOAD, 0, }, + {offsetof(tDot11fProbeResponse, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fProbeResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fProbeResponse, APChannelReport), offsetof(tDot11fIEAPChannelReport, present), 0, "APChannelReport" , 0, 3, 53, SigIeAPChannelReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_APCHANNELREPORT, 0, }, + {offsetof(tDot11fProbeResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fProbeResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, + {offsetof(tDot11fProbeResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fProbeResponse, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fProbeResponse, sec_chan_offset_ele), offsetof(tDot11fIEsec_chan_offset_ele, present), 0, "sec_chan_offset_ele" , 0, 3, 3, SigIesec_chan_offset_ele, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SEC_CHAN_OFFSET_ELE, 0, }, + {offsetof(tDot11fProbeResponse, WMMInfoAp), offsetof(tDot11fIEWMMInfoAp, present), 0, "WMMInfoAp" , 0, 9, 9, SigIeWMMInfoAp, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOAP, 0, }, + {offsetof(tDot11fProbeResponse, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fProbeResponse, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fProbeResponse, WAPI), offsetof(tDot11fIEWAPI, present), 0, "WAPI" , 0, 14, 112, SigIeWAPI, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPI, 0, }, + {offsetof(tDot11fProbeResponse, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fProbeResponse, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {offsetof(tDot11fProbeResponse, ESETxmitPower), offsetof(tDot11fIEESETxmitPower, present), 0, "ESETxmitPower" , 0, 8, 8, SigIeESETxmitPower, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESETXMITPOWER, 0, }, + {offsetof(tDot11fProbeResponse, WscProbeRes), offsetof(tDot11fIEWscProbeRes, present), 0, "WscProbeRes" , 0, 6, 319, SigIeWscProbeRes, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCPROBERES, 0, }, + {offsetof(tDot11fProbeResponse, P2PProbeRes), offsetof(tDot11fIEP2PProbeRes, present), 0, "P2PProbeRes" , 0, 6, 1141, SigIeP2PProbeRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PPROBERES, 0, }, + {offsetof(tDot11fProbeResponse, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fProbeResponse, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {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, 10, 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, Vendor1IE), offsetof(tDot11fIEVendor1IE, present), 0, "Vendor1IE" , 0, 5, 5, SigIeVendor1IE, {0, 16, 24, 0, 0}, 3, DOT11F_EID_VENDOR1IE, 0, }, + {offsetof(tDot11fProbeResponse, Vendor2IE), offsetof(tDot11fIEVendor2IE, present), 0, "Vendor2IE" , 0, 5, 5, SigIeVendor2IE, {0, 144, 76, 0, 0}, 3, DOT11F_EID_VENDOR2IE, 0, }, + {offsetof(tDot11fProbeResponse, Vendor3IE), offsetof(tDot11fIEVendor3IE, present), 0, "Vendor3IE" , 0, 5, 5, SigIeVendor3IE, {0, 22, 50, 0, 0}, 3, DOT11F_EID_VENDOR3IE, 0, }, + {offsetof(tDot11fProbeResponse, ChannelSwitchWrapper), offsetof(tDot11fIEChannelSwitchWrapper, present), 0, "ChannelSwitchWrapper" , 0, 2, 7, SigIeChannelSwitchWrapper, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHANNELSWITCHWRAPPER, 0, }, + {offsetof(tDot11fProbeResponse, QComVendorIE), offsetof(tDot11fIEQComVendorIE, present), 0, "QComVendorIE" , 0, 7, 7, SigIeQComVendorIE, {0, 160, 198, 0, 0}, 3, DOT11F_EID_QCOMVENDORIE, 0, }, + {offsetof(tDot11fProbeResponse, ESEVersion), offsetof(tDot11fIEESEVersion, present), 0, "ESEVersion" , 0, 7, 7, SigIeESEVersion, {0, 64, 150, 3, 0}, 4, DOT11F_EID_ESEVERSION, 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) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ProbeResponse, IES_ProbeResponse, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Unpacked the ProbeResponse:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->BeaconInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FHParamSet:\n")); + if (!pFrm->FHParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.dwell_time, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.hop_set, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.hop_pattern, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.hop_index, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("CFParams:\n")); + if (!pFrm->CFParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_maxduration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_durremaining, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FHParams:\n")); + if (!pFrm->FHParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParams.radix, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParams.nchannels, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FHPattTable:\n")); + if (!pFrm->FHPattTable.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.flag, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.nsets, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.modulus, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.offset, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_randtable: %d.\n"), pFrm->FHPattTable.num_randtable); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->FHPattTable.randtable, pFrm->FHPattTable.num_randtable); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("QBSSLoad:\n")); + if (!pFrm->QBSSLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QBSSLoad.stacount, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QBSSLoad.chautil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QBSSLoad.avail, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WscProbeRes:\n")); + if (!pFrm->WscProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Version:\n")); + if (!pFrm->WscProbeRes.Version.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("minor (4): %d\n"), pFrm->WscProbeRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("major (4): %d\n"), pFrm->WscProbeRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WPSState:\n")); + if (!pFrm->WscProbeRes.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("APSetupLocked:\n")); + if (!pFrm->WscProbeRes.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscProbeRes.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscProbeRes.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscProbeRes.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ResponseType:\n")); + if (!pFrm->WscProbeRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("UUID_E:\n")); + if (!pFrm->WscProbeRes.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Manufacturer:\n")); + if (!pFrm->WscProbeRes.Manufacturer.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("num_name: %d.\n"), pFrm->WscProbeRes.Manufacturer.num_name); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.Manufacturer.name, pFrm->WscProbeRes.Manufacturer.num_name); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ModelName:\n")); + if (!pFrm->WscProbeRes.ModelName.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("num_text: %d.\n"), pFrm->WscProbeRes.ModelName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.ModelName.text, pFrm->WscProbeRes.ModelName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ModelNumber:\n")); + if (!pFrm->WscProbeRes.ModelNumber.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("num_text: %d.\n"), pFrm->WscProbeRes.ModelNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.ModelNumber.text, pFrm->WscProbeRes.ModelNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SerialNumber:\n")); + if (!pFrm->WscProbeRes.SerialNumber.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("num_text: %d.\n"), pFrm->WscProbeRes.SerialNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.SerialNumber.text, pFrm->WscProbeRes.SerialNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("PrimaryDeviceType:\n")); + if (!pFrm->WscProbeRes.PrimaryDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.PrimaryDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.PrimaryDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.PrimaryDeviceType.sub_category, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DeviceName:\n")); + if (!pFrm->WscProbeRes.DeviceName.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("num_text: %d.\n"), pFrm->WscProbeRes.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.DeviceName.text, pFrm->WscProbeRes.DeviceName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ConfigMethods:\n")); + if (!pFrm->WscProbeRes.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.ConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RFBands:\n")); + if (!pFrm->WscProbeRes.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VendorExtension:\n")); + if (!pFrm->WscProbeRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Version2:\n")); + if (!pFrm->WscProbeRes.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscProbeRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("major (4): %d\n"), pFrm->WscProbeRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscProbeRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscProbeRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PProbeRes:\n")); + if (!pFrm->P2PProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PCapability:\n")); + if (!pFrm->P2PProbeRes.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PProbeRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PProbeRes.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_NoADesc: %d.\n"), pFrm->P2PProbeRes.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->P2PProbeRes.NoticeOfAbsence.NoADesc, pFrm->P2PProbeRes.NoticeOfAbsence.num_NoADesc); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PProbeRes.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DeviceName:\n")); + if (!pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.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("num_text: %d.\n"), pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.text, pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PGroupInfo:\n")); + if (!pFrm->P2PProbeRes.P2PGroupInfo.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("num_P2PClientInfoDesc: %d.\n"), pFrm->P2PProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->P2PProbeRes.P2PGroupInfo.P2PClientInfoDesc, pFrm->P2PProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProbeResponse. */ + + static const tFFDefn FFS_ProvisionDiscoveryReq[] = { + { "Category", offsetof(tDot11fProvisionDiscoveryReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fProvisionDiscoveryReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fProvisionDiscoveryReq, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fProvisionDiscoveryReq, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fProvisionDiscoveryReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ProvisionDiscoveryReq[] = { + {offsetof(tDot11fProvisionDiscoveryReq, P2PProvisionDiscoveryReq), offsetof(tDot11fIEP2PProvisionDiscoveryReq, present), 0, "P2PProvisionDiscoveryReq" , 0, 6, 107, SigIeP2PProvisionDiscoveryReq, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PPROVISIONDISCOVERYREQ, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackProvisionDiscoveryReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProvisionDiscoveryReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ProvisionDiscoveryReq, IES_ProvisionDiscoveryReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Unpacked the ProvisionDiscoveryReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PProvisionDiscoveryReq:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PCapability:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("DeviceName:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("num_text: %d.\n"), pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* ) pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.text, pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("num_ssid: %d.\n"), pFrm->P2PProvisionDiscoveryReq.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* ) pFrm->P2PProvisionDiscoveryReq.P2PGroupId.ssid, pFrm->P2PProvisionDiscoveryReq.P2PGroupId.num_ssid); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProvisionDiscoveryReq. */ + + static const tFFDefn FFS_ProvisionDiscoveryRes[] = { + { "Category", offsetof(tDot11fProvisionDiscoveryRes, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fProvisionDiscoveryRes, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "P2POUI", offsetof(tDot11fProvisionDiscoveryRes, P2POUI), SigFfP2POUI , DOT11F_FF_P2POUI_LEN, }, + { "P2POUISubType", offsetof(tDot11fProvisionDiscoveryRes, P2POUISubType), SigFfP2POUISubType , DOT11F_FF_P2POUISUBTYPE_LEN, }, + { "DialogToken", offsetof(tDot11fProvisionDiscoveryRes, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ProvisionDiscoveryRes[] = { + {offsetof(tDot11fProvisionDiscoveryRes, P2PWSCProvisionDiscoveryRes), offsetof(tDot11fIEP2PWSCProvisionDiscoveryRes, present), 0, "P2PWSCProvisionDiscoveryRes" , 0, 6, 12, SigIeP2PWSCProvisionDiscoveryRes, {0, 80, 242, 4, 0}, 4, DOT11F_EID_P2PWSCPROVISIONDISCOVERYRES, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackProvisionDiscoveryRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProvisionDiscoveryRes *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ProvisionDiscoveryRes, IES_ProvisionDiscoveryRes, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Unpacked the ProvisionDiscoveryRes:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("P2PWSCProvisionDiscoveryRes:\n")); + if (!pFrm->P2PWSCProvisionDiscoveryRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("ConfigMethods:\n")); + if (!pFrm->P2PWSCProvisionDiscoveryRes.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->P2PWSCProvisionDiscoveryRes.ConfigMethods.methods, 2); + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProvisionDiscoveryRes. */ + + static const tFFDefn FFS_QosMapConfigure[] = { + { "Category", offsetof(tDot11fQosMapConfigure, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fQosMapConfigure, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_QosMapConfigure[] = { + {offsetof(tDot11fQosMapConfigure, QosMapSet), offsetof(tDot11fIEQosMapSet, present), 0, "QosMapSet" , 0, 2, 62, SigIeQosMapSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSMAPSET, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackQosMapConfigure(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fQosMapConfigure *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_QosMapConfigure, IES_QosMapConfigure, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Unpacked the QosMapConfigure:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackQosMapConfigure. */ + + static const tFFDefn FFS_RadioMeasurementReport[] = { + { "Category", offsetof(tDot11fRadioMeasurementReport, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fRadioMeasurementReport, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fRadioMeasurementReport, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_RadioMeasurementReport[] = { + {offsetof(tDot11fRadioMeasurementReport, MeasurementReport), offsetof(tDot11fIEMeasurementReport, present), offsetof(tDot11fRadioMeasurementReport, num_MeasurementReport), "MeasurementReport" , 4, 5, 31, SigIeMeasurementReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MEASUREMENTREPORT, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackRadioMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fRadioMeasurementReport *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_RadioMeasurementReport, IES_RadioMeasurementReport, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Unpacked the RadioMeasurementReport:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + for (i = 0; i < pFrm->num_MeasurementReport; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("MeasurementReport[%d]:\n"), i); + if (!pFrm->MeasurementReport[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("late (1): %d\n"), pFrm->MeasurementReport[i].late); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("incapable (1): %d\n"), pFrm->MeasurementReport[i].incapable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("refused (1): %d\n"), pFrm->MeasurementReport[i].refused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unused (5): %d\n"), pFrm->MeasurementReport[i].unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].type, 1); + switch (pFrm->MeasurementReport[i].type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Basic.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Basic.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("bss (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.bss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("ofdm_preamble (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.ofdm_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unid_signal (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.unid_signal); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("rader (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.rader); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unmeasured (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.unmeasured); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unused (3): %d\n"), pFrm->MeasurementReport[i].report.Basic.unused); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.cca_busy_fraction, 1); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi0_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi1_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi2_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi3_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi4_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi5_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi6_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi7_density, 1); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("condensed_PHY (7): %d\n"), pFrm->MeasurementReport[i].report.Beacon.condensed_PHY); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("reported_frame_type (1): %d\n"), pFrm->MeasurementReport[i].report.Beacon.reported_frame_type); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.RCPI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.RSNI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.BSSID, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.antenna_id, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.parent_TSF, 4); + break; + } + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackRadioMeasurementReport. */ + + static const tFFDefn FFS_RadioMeasurementRequest[] = { + { "Category", offsetof(tDot11fRadioMeasurementRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fRadioMeasurementRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fRadioMeasurementRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "NumOfRepetitions", offsetof(tDot11fRadioMeasurementRequest, NumOfRepetitions), SigFfNumOfRepetitions , DOT11F_FF_NUMOFREPETITIONS_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_RadioMeasurementRequest[] = { + {offsetof(tDot11fRadioMeasurementRequest, MeasurementRequest), offsetof(tDot11fIEMeasurementRequest, present), offsetof(tDot11fRadioMeasurementRequest, num_MeasurementRequest), "MeasurementRequest" , 2, 16, 18, SigIeMeasurementRequest, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MEASUREMENTREQUEST, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackRadioMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fRadioMeasurementRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_RadioMeasurementRequest, IES_RadioMeasurementRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Unpacked the RadioMeasurementRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("NumOfRepetitions:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->NumOfRepetitions.repetitions, 2); + for (i = 0; i < pFrm->num_MeasurementRequest; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("MeasurementRequest[%d]:\n"), i); + if (!pFrm->MeasurementRequest[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("parallel (1): %d\n"), pFrm->MeasurementRequest[i].parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("enable (1): %d\n"), pFrm->MeasurementRequest[i].enable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("request (1): %d\n"), pFrm->MeasurementRequest[i].request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("report (1): %d\n"), pFrm->MeasurementRequest[i].report); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("durationMandatory (1): %d\n"), pFrm->MeasurementRequest[i].durationMandatory); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("unused (3): %d\n"), pFrm->MeasurementRequest[i].unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_type, 1); + switch (pFrm->MeasurementRequest[i].measurement_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_duration, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_duration, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_duration, 2); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.randomization, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.BSSID, 6); + break; + } + } + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackRadioMeasurementRequest. */ + + static const tFFDefn FFS_ReAssocRequest[] = { + { "Capabilities", offsetof(tDot11fReAssocRequest, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { "ListenInterval", offsetof(tDot11fReAssocRequest, ListenInterval), SigFfListenInterval , DOT11F_FF_LISTENINTERVAL_LEN, }, + { "CurrentAPAddress", offsetof(tDot11fReAssocRequest, CurrentAPAddress), SigFfCurrentAPAddress , DOT11F_FF_CURRENTAPADDRESS_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ReAssocRequest[] = { + {offsetof(tDot11fReAssocRequest, SSID), offsetof(tDot11fIESSID, present), 0, "SSID" , 0, 2, 34, SigIeSSID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SSID, 1, }, + {offsetof(tDot11fReAssocRequest, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fReAssocRequest, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fReAssocRequest, PowerCaps), offsetof(tDot11fIEPowerCaps, present), 0, "PowerCaps" , 0, 4, 4, SigIePowerCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCAPS, 0, }, + {offsetof(tDot11fReAssocRequest, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, + {offsetof(tDot11fReAssocRequest, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, + {offsetof(tDot11fReAssocRequest, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fReAssocRequest, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fReAssocRequest, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fReAssocRequest, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fReAssocRequest, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, + {offsetof(tDot11fReAssocRequest, WPAOpaque), offsetof(tDot11fIEWPAOpaque, present), 0, "WPAOpaque" , 0, 8, 255, SigIeWPAOpaque, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPAOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fReAssocRequest, WMMCaps), offsetof(tDot11fIEWMMCaps, present), 0, "WMMCaps" , 0, 9, 9, SigIeWMMCaps, {0, 80, 242, 2, 5}, 5, DOT11F_EID_WMMCAPS, 0, }, + {offsetof(tDot11fReAssocRequest, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, + {offsetof(tDot11fReAssocRequest, WscIEOpaque), offsetof(tDot11fIEWscIEOpaque, present), 0, "WscIEOpaque" , 0, 8, 255, SigIeWscIEOpaque, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCIEOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, WAPIOpaque), offsetof(tDot11fIEWAPIOpaque, present), 0, "WAPIOpaque" , 0, 8, 255, SigIeWAPIOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPIOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, WAPI), offsetof(tDot11fIEWAPI, present), 0, "WAPI" , 0, 14, 112, SigIeWAPI, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WAPI, 0, }, + {offsetof(tDot11fReAssocRequest, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fReAssocRequest, ESEVersion), offsetof(tDot11fIEESEVersion, present), 0, "ESEVersion" , 0, 7, 7, SigIeESEVersion, {0, 64, 150, 3, 0}, 4, DOT11F_EID_ESEVERSION, 0, }, + {offsetof(tDot11fReAssocRequest, ESECckmOpaque), offsetof(tDot11fIEESECckmOpaque, present), 0, "ESECckmOpaque" , 0, 12, 26, SigIeESECckmOpaque, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESECCKMOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), offsetof(tDot11fReAssocRequest, num_WMMTSPEC), "WMMTSPEC" , 4, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fReAssocRequest, ESETrafStrmRateSet), offsetof(tDot11fIEESETrafStrmRateSet, present), 0, "ESETrafStrmRateSet" , 0, 7, 15, SigIeESETrafStrmRateSet, {0, 64, 150, 8, 0}, 4, DOT11F_EID_ESETRAFSTRMRATESET, 0, }, + {offsetof(tDot11fReAssocRequest, P2PIEOpaque), offsetof(tDot11fIEP2PIEOpaque, present), 0, "P2PIEOpaque" , 0, 8, 255, SigIeP2PIEOpaque, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PIEOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, WFDIEOpaque), offsetof(tDot11fIEWFDIEOpaque, present), 0, "WFDIEOpaque" , 0, 8, 255, SigIeWFDIEOpaque, {80, 111, 154, 10, 0}, 4, DOT11F_EID_WFDIEOPAQUE, 0, }, + {offsetof(tDot11fReAssocRequest, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fReAssocRequest, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 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, }, + {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) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ReAssocRequest, IES_ReAssocRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Unpacked the ReAssocRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ListenInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ListenInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("CurrentAPAddress:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->CurrentAPAddress.mac, 6); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("PowerCaps:\n")); + if (!pFrm->PowerCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.minTxPower, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.maxTxPower, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.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("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.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("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.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("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.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("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.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("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.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("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.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("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WPAOpaque:\n")); + if (!pFrm->WPAOpaque.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("num_data: %d.\n"), pFrm->WPAOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WPAOpaque.data, pFrm->WPAOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WscIEOpaque:\n")); + if (!pFrm->WscIEOpaque.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("num_data: %d.\n"), pFrm->WscIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WscIEOpaque.data, pFrm->WscIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WAPIOpaque:\n")); + if (!pFrm->WAPIOpaque.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("num_data: %d.\n"), pFrm->WAPIOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPIOpaque.data, pFrm->WAPIOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESECckmOpaque:\n")); + if (!pFrm->ESECckmOpaque.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("num_data: %d.\n"), pFrm->ESECckmOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ESECckmOpaque.data, pFrm->ESECckmOpaque.num_data); + } + for (i = 0; i < pFrm->num_WMMTSPEC; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTSPEC[%d]:\n"), i); + if (!pFrm->WMMTSPEC[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC[i].traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC[i].tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC[i].direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC[i].access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC[i].aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC[i].psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC[i].user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC[i].tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC[i].tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC[i].burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("size (15): %d\n"), pFrm->WMMTSPEC[i].size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC[i].fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].medium_time, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("P2PIEOpaque:\n")); + if (!pFrm->P2PIEOpaque.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("num_data: %d.\n"), pFrm->P2PIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->P2PIEOpaque.data, pFrm->P2PIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WFDIEOpaque:\n")); + if (!pFrm->WFDIEOpaque.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("num_data: %d.\n"), pFrm->WFDIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WFDIEOpaque.data, pFrm->WFDIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.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("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); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackReAssocRequest. */ + + static const tFFDefn FFS_ReAssocResponse[] = { + { "Capabilities", offsetof(tDot11fReAssocResponse, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { "Status", offsetof(tDot11fReAssocResponse, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { "AID", offsetof(tDot11fReAssocResponse, AID), SigFfAID , DOT11F_FF_AID_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ReAssocResponse[] = { + {offsetof(tDot11fReAssocResponse, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fReAssocResponse, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fReAssocResponse, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fReAssocResponse, RCPIIE), offsetof(tDot11fIERCPIIE, present), 0, "RCPIIE" , 0, 3, 3, SigIeRCPIIE, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RCPIIE, 0, }, + {offsetof(tDot11fReAssocResponse, RSNIIE), offsetof(tDot11fIERSNIIE, present), 0, "RSNIIE" , 0, 3, 3, SigIeRSNIIE, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNIIE, 0, }, + {offsetof(tDot11fReAssocResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, + {offsetof(tDot11fReAssocResponse, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, + {offsetof(tDot11fReAssocResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, + {offsetof(tDot11fReAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fReAssocResponse, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fReAssocResponse, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, + {offsetof(tDot11fReAssocResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, + {offsetof(tDot11fReAssocResponse, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fReAssocResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fReAssocResponse, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fReAssocResponse, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fReAssocResponse, ESERadMgmtCap), offsetof(tDot11fIEESERadMgmtCap, present), 0, "ESERadMgmtCap" , 0, 8, 8, SigIeESERadMgmtCap, {0, 64, 150, 1, 0}, 4, DOT11F_EID_ESERADMGMTCAP, 0, }, + {offsetof(tDot11fReAssocResponse, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {offsetof(tDot11fReAssocResponse, ESETxmitPower), offsetof(tDot11fIEESETxmitPower, present), 0, "ESETxmitPower" , 0, 8, 8, SigIeESETxmitPower, {0, 64, 150, 0, 0}, 4, DOT11F_EID_ESETXMITPOWER, 0, }, + {offsetof(tDot11fReAssocResponse, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), offsetof(tDot11fReAssocResponse, num_WMMTSPEC), "WMMTSPEC" , 4, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fReAssocResponse, ESETrafStrmRateSet), offsetof(tDot11fIEESETrafStrmRateSet, present), 0, "ESETrafStrmRateSet" , 0, 7, 15, SigIeESETrafStrmRateSet, {0, 64, 150, 8, 0}, 4, DOT11F_EID_ESETRAFSTRMRATESET, 0, }, + {offsetof(tDot11fReAssocResponse, WscReassocRes), offsetof(tDot11fIEWscReassocRes, present), 0, "WscReassocRes" , 0, 6, 37, SigIeWscReassocRes, {0, 80, 242, 4, 0}, 4, DOT11F_EID_WSCREASSOCRES, 0, }, + {offsetof(tDot11fReAssocResponse, P2PAssocRes), offsetof(tDot11fIEP2PAssocRes, present), 0, "P2PAssocRes" , 0, 6, 17, SigIeP2PAssocRes, {80, 111, 154, 9, 0}, 4, DOT11F_EID_P2PASSOCRES, 0, }, + {offsetof(tDot11fReAssocResponse, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fReAssocResponse, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fReAssocResponse, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {offsetof(tDot11fReAssocResponse, OBSSScanParameters), offsetof(tDot11fIEOBSSScanParameters, present), 0, "OBSSScanParameters" , 0, 16, 16, SigIeOBSSScanParameters, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OBSSSCANPARAMETERS, 0, }, + {offsetof(tDot11fReAssocResponse, QosMapSet), offsetof(tDot11fIEQosMapSet, present), 0, "QosMapSet" , 0, 2, 62, SigIeQosMapSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSMAPSET, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackReAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fReAssocResponse *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ReAssocResponse, IES_ReAssocResponse, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Unpacked the ReAssocResponse:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("AID:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->AID.associd, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RCPIIE:\n")); + if (!pFrm->RCPIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RCPIIE.rcpi, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RSNIIE:\n")); + if (!pFrm->RSNIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RSNIIE.rsni, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + for (i = 0; i < pFrm->num_WMMTSPEC; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTSPEC[%d]:\n"), i); + if (!pFrm->WMMTSPEC[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC[i].traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC[i].tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC[i].direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC[i].access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC[i].aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC[i].psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC[i].user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC[i].tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC[i].tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC[i].burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC[i].size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC[i].fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].medium_time, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WscReassocRes:\n")); + if (!pFrm->WscReassocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Version:\n")); + if (!pFrm->WscReassocRes.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscReassocRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscReassocRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ResponseType:\n")); + if (!pFrm->WscReassocRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("VendorExtension:\n")); + if (!pFrm->WscReassocRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Version2:\n")); + if (!pFrm->WscReassocRes.VendorExtension.Version2.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscReassocRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscReassocRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscReassocRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscReassocRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("P2PAssocRes:\n")); + if (!pFrm->P2PAssocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("P2PStatus:\n")); + if (!pFrm->P2PAssocRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PAssocRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityInterval, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackReAssocResponse. */ + + static const tFFDefn FFS_SMPowerSave[] = { + { "Category", offsetof(tDot11fSMPowerSave, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fSMPowerSave, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "SMPowerModeSet", offsetof(tDot11fSMPowerSave, SMPowerModeSet), SigFfSMPowerModeSet , DOT11F_FF_SMPOWERMODESET_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_SMPowerSave[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackSMPowerSave(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSMPowerSave *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_SMPowerSave, IES_SMPowerSave, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Unpacked the SMPowerSave:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("SMPowerModeSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("PowerSave_En (1): %d\n"), pFrm->SMPowerModeSet.PowerSave_En); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Mode (1): %d\n"), pFrm->SMPowerModeSet.Mode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("reserved (6): %d\n"), pFrm->SMPowerModeSet.reserved); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackSMPowerSave. */ + + static const tFFDefn FFS_SaQueryReq[] = { + { "Category", offsetof(tDot11fSaQueryReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fSaQueryReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "TransactionId", offsetof(tDot11fSaQueryReq, TransactionId), SigFfTransactionId , DOT11F_FF_TRANSACTIONID_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_SaQueryReq[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackSaQueryReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_SaQueryReq, IES_SaQueryReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("Unpacked the SaQueryReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("TransactionId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), ( tANI_U8* )&pFrm->TransactionId.transId, 2); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackSaQueryReq. */ + + static const tFFDefn FFS_SaQueryRsp[] = { + { "Category", offsetof(tDot11fSaQueryRsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fSaQueryRsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "TransactionId", offsetof(tDot11fSaQueryRsp, TransactionId), SigFfTransactionId , DOT11F_FF_TRANSACTIONID_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_SaQueryRsp[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackSaQueryRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryRsp *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_SaQueryRsp, IES_SaQueryRsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Unpacked the SaQueryRsp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("TransactionId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->TransactionId.transId, 2); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackSaQueryRsp. */ + + static const tFFDefn FFS_TDLSDisReq[] = { + { "Category", offsetof(tDot11fTDLSDisReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSDisReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSDisReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSDisReq[] = { + {offsetof(tDot11fTDLSDisReq, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSDisReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSDisReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSDisReq, IES_TDLSDisReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Unpacked the TDLSDisReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSDisReq. */ + + static const tFFDefn FFS_TDLSDisRsp[] = { + { "Category", offsetof(tDot11fTDLSDisRsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSDisRsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSDisRsp, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "Capabilities", offsetof(tDot11fTDLSDisRsp, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSDisRsp[] = { + {offsetof(tDot11fTDLSDisRsp, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fTDLSDisRsp, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fTDLSDisRsp, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, + {offsetof(tDot11fTDLSDisRsp, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fTDLSDisRsp, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 116, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, + {offsetof(tDot11fTDLSDisRsp, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {offsetof(tDot11fTDLSDisRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSDisRsp, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fTDLSDisRsp, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, + {offsetof(tDot11fTDLSDisRsp, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fTDLSDisRsp, HT2040BSSCoexistence), offsetof(tDot11fIEHT2040BSSCoexistence, present), 0, "HT2040BSSCoexistence" , 0, 3, 3, SigIeHT2040BSSCoexistence, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040BSSCOEXISTENCE, 0, }, + {offsetof(tDot11fTDLSDisRsp, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, + {offsetof(tDot11fTDLSDisRsp, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSDisRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSDisRsp *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSDisRsp, IES_TDLSDisRsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Unpacked the TDLSDisRsp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("RICData:\n")); + if (!pFrm->RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSDisRsp. */ + + static const tFFDefn FFS_TDLSPeerTrafficInd[] = { + { "Category", offsetof(tDot11fTDLSPeerTrafficInd, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSPeerTrafficInd, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSPeerTrafficInd, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSPeerTrafficInd[] = { + {offsetof(tDot11fTDLSPeerTrafficInd, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, + {offsetof(tDot11fTDLSPeerTrafficInd, PTIControl), offsetof(tDot11fIEPTIControl, present), 0, "PTIControl" , 0, 5, 5, SigIePTIControl, {0, 0, 0, 0, 0}, 0, DOT11F_EID_PTICONTROL, 0, }, + {offsetof(tDot11fTDLSPeerTrafficInd, PUBufferStatus), offsetof(tDot11fIEPUBufferStatus, present), 0, "PUBufferStatus" , 0, 3, 3, SigIePUBufferStatus, {0, 0, 0, 0, 0}, 0, DOT11F_EID_PUBUFFERSTATUS, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSPeerTrafficInd(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSPeerTrafficInd *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSPeerTrafficInd, IES_TDLSPeerTrafficInd, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Unpacked the TDLSPeerTrafficInd:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("PTIControl:\n")); + if (!pFrm->PTIControl.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->PTIControl.tid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->PTIControl.sequence_control, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("PUBufferStatus:\n")); + if (!pFrm->PUBufferStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_bk_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_bk_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_be_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_be_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_vi_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_vi_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_vo_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_vo_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("reserved (4): %d\n"), pFrm->PUBufferStatus.reserved); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSPeerTrafficInd. */ + + static const tFFDefn FFS_TDLSPeerTrafficRsp[] = { + { "Category", offsetof(tDot11fTDLSPeerTrafficRsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSPeerTrafficRsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSPeerTrafficRsp, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSPeerTrafficRsp[] = { + {offsetof(tDot11fTDLSPeerTrafficRsp, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSPeerTrafficRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSPeerTrafficRsp *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSPeerTrafficRsp, IES_TDLSPeerTrafficRsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Unpacked the TDLSPeerTrafficRsp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSPeerTrafficRsp. */ + + static const tFFDefn FFS_TDLSSetupCnf[] = { + { "Category", offsetof(tDot11fTDLSSetupCnf, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSSetupCnf, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "Status", offsetof(tDot11fTDLSSetupCnf, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSSetupCnf, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSSetupCnf[] = { + {offsetof(tDot11fTDLSSetupCnf, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 116, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, + {offsetof(tDot11fTDLSSetupCnf, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, + {offsetof(tDot11fTDLSSetupCnf, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupCnf, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fTDLSSetupCnf, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, + {offsetof(tDot11fTDLSSetupCnf, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 0, }, + {offsetof(tDot11fTDLSSetupCnf, WMMParams), offsetof(tDot11fIEWMMParams, present), 0, "WMMParams" , 0, 26, 26, SigIeWMMParams, {0, 80, 242, 2, 1}, 5, DOT11F_EID_WMMPARAMS, 0, }, + {offsetof(tDot11fTDLSSetupCnf, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fTDLSSetupCnf, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupCnf *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSSetupCnf, IES_TDLSSetupCnf, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Unpacked the TDLSSetupCnf:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSSetupCnf. */ + + static const tFFDefn FFS_TDLSSetupReq[] = { + { "Category", offsetof(tDot11fTDLSSetupReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSSetupReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSSetupReq, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "Capabilities", offsetof(tDot11fTDLSSetupReq, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSSetupReq[] = { + {offsetof(tDot11fTDLSSetupReq, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 1, }, + {offsetof(tDot11fTDLSSetupReq, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fTDLSSetupReq, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fTDLSSetupReq, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, + {offsetof(tDot11fTDLSSetupReq, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 116, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, + {offsetof(tDot11fTDLSSetupReq, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {offsetof(tDot11fTDLSSetupReq, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fTDLSSetupReq, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, + {offsetof(tDot11fTDLSSetupReq, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupReq, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fTDLSSetupReq, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, + {offsetof(tDot11fTDLSSetupReq, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fTDLSSetupReq, HT2040BSSCoexistence), offsetof(tDot11fIEHT2040BSSCoexistence, present), 0, "HT2040BSSCoexistence" , 0, 3, 3, SigIeHT2040BSSCoexistence, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040BSSCOEXISTENCE, 0, }, + {offsetof(tDot11fTDLSSetupReq, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, + {offsetof(tDot11fTDLSSetupReq, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, + {offsetof(tDot11fTDLSSetupReq, AID), offsetof(tDot11fIEAID, present), 0, "AID" , 0, 4, 4, SigIeAID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_AID, 0, }, + {offsetof(tDot11fTDLSSetupReq, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupReq *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSSetupReq, IES_TDLSSetupReq, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Unpacked the TDLSSetupReq:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("RICData:\n")); + if (!pFrm->RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("AID:\n")); + if (!pFrm->AID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->AID.assocId, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSSetupReq. */ + + static const tFFDefn FFS_TDLSSetupRsp[] = { + { "Category", offsetof(tDot11fTDLSSetupRsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSSetupRsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "Status", offsetof(tDot11fTDLSSetupRsp, Status), SigFfStatus , DOT11F_FF_STATUS_LEN, }, + { "DialogToken", offsetof(tDot11fTDLSSetupRsp, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "Capabilities", offsetof(tDot11fTDLSSetupRsp, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSSetupRsp[] = { + {offsetof(tDot11fTDLSSetupRsp, SuppRates), offsetof(tDot11fIESuppRates, present), 0, "SuppRates" , 0, 2, 14, SigIeSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPRATES, 0, }, + {offsetof(tDot11fTDLSSetupRsp, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fTDLSSetupRsp, ExtSuppRates), offsetof(tDot11fIEExtSuppRates, present), 0, "ExtSuppRates" , 0, 3, 14, SigIeExtSuppRates, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTSUPPRATES, 0, }, + {offsetof(tDot11fTDLSSetupRsp, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, + {offsetof(tDot11fTDLSSetupRsp, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 116, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, + {offsetof(tDot11fTDLSSetupRsp, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {offsetof(tDot11fTDLSSetupRsp, SuppOperatingClasses), offsetof(tDot11fIESuppOperatingClasses, present), 0, "SuppOperatingClasses" , 0, 3, 34, SigIeSuppOperatingClasses, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPOPERATINGCLASSES, 0, }, + {offsetof(tDot11fTDLSSetupRsp, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, + {offsetof(tDot11fTDLSSetupRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupRsp, TimeoutInterval), offsetof(tDot11fIETimeoutInterval, present), 0, "TimeoutInterval" , 0, 7, 7, SigIeTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEOUTINTERVAL, 0, }, + {offsetof(tDot11fTDLSSetupRsp, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, + {offsetof(tDot11fTDLSSetupRsp, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, + {offsetof(tDot11fTDLSSetupRsp, HT2040BSSCoexistence), offsetof(tDot11fIEHT2040BSSCoexistence, present), 0, "HT2040BSSCoexistence" , 0, 3, 3, SigIeHT2040BSSCoexistence, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040BSSCOEXISTENCE, 0, }, + {offsetof(tDot11fTDLSSetupRsp, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 0, }, + {offsetof(tDot11fTDLSSetupRsp, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, + {offsetof(tDot11fTDLSSetupRsp, AID), offsetof(tDot11fIEAID, present), 0, "AID" , 0, 4, 4, SigIeAID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_AID, 0, }, + {offsetof(tDot11fTDLSSetupRsp, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fTDLSSetupRsp, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupRsp *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSSetupRsp, IES_TDLSSetupRsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Unpacked the TDLSSetupRsp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("RICData:\n")); + if (!pFrm->RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("AID:\n")); + if (!pFrm->AID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->AID.assocId, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSSetupRsp. */ + + static const tFFDefn FFS_TDLSTeardown[] = { + { "Category", offsetof(tDot11fTDLSTeardown, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTDLSTeardown, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "Reason", offsetof(tDot11fTDLSTeardown, Reason), SigFfReason , DOT11F_FF_REASON_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TDLSTeardown[] = { + {offsetof(tDot11fTDLSTeardown, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSTeardown, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTDLSTeardown(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSTeardown *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TDLSTeardown, IES_TDLSTeardown, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Unpacked the TDLSTeardown:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSTeardown. */ + + static const tFFDefn FFS_TPCReport[] = { + { "Category", offsetof(tDot11fTPCReport, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTPCReport, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTPCReport, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TPCReport[] = { + {offsetof(tDot11fTPCReport, TPCReport), offsetof(tDot11fIETPCReport, present), 0, "TPCReport" , 0, 4, 4, SigIeTPCReport, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TPCREPORT, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTPCReport *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TPCReport, IES_TPCReport, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Unpacked the TPCReport:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTPCReport. */ + + static const tFFDefn FFS_TPCRequest[] = { + { "Category", offsetof(tDot11fTPCRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fTPCRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fTPCRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TPCRequest[] = { + {offsetof(tDot11fTPCRequest, TPCRequest), offsetof(tDot11fIETPCRequest, present), 0, "TPCRequest" , 0, 2, 2, SigIeTPCRequest, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TPCREQUEST, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTPCRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TPCRequest, IES_TPCRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Unpacked the TPCRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("TPCRequest:\n")); + if (!pFrm->TPCRequest.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Not present.\n")); + } + else + { + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTPCRequest. */ + + static const tFFDefn FFS_TimingAdvertisementFrame[] = { + { "TimeStamp", offsetof(tDot11fTimingAdvertisementFrame, TimeStamp), SigFfTimeStamp , DOT11F_FF_TIMESTAMP_LEN, }, + { "Capabilities", offsetof(tDot11fTimingAdvertisementFrame, Capabilities), SigFfCapabilities , DOT11F_FF_CAPABILITIES_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_TimingAdvertisementFrame[] = { + {offsetof(tDot11fTimingAdvertisementFrame, Country), offsetof(tDot11fIECountry, present), 0, "Country" , 0, 5, 257, SigIeCountry, {0, 0, 0, 0, 0}, 0, DOT11F_EID_COUNTRY, 0, }, + {offsetof(tDot11fTimingAdvertisementFrame, PowerConstraints), offsetof(tDot11fIEPowerConstraints, present), 0, "PowerConstraints" , 0, 3, 3, SigIePowerConstraints, {0, 0, 0, 0, 0}, 0, DOT11F_EID_POWERCONSTRAINTS, 0, }, + {offsetof(tDot11fTimingAdvertisementFrame, TimeAdvertisement), offsetof(tDot11fIETimeAdvertisement, present), 0, "TimeAdvertisement" , 0, 18, 18, SigIeTimeAdvertisement, {0, 0, 0, 0, 0}, 0, DOT11F_EID_TIMEADVERTISEMENT, 0, }, + {offsetof(tDot11fTimingAdvertisementFrame, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, + {offsetof(tDot11fTimingAdvertisementFrame, Vendor1IE), offsetof(tDot11fIEVendor1IE, present), 0, "Vendor1IE" , 0, 5, 5, SigIeVendor1IE, {0, 16, 24, 0, 0}, 3, DOT11F_EID_VENDOR1IE, 0, }, + {offsetof(tDot11fTimingAdvertisementFrame, Vendor2IE), offsetof(tDot11fIEVendor2IE, present), 0, "Vendor2IE" , 0, 5, 5, SigIeVendor2IE, {0, 144, 76, 0, 0}, 3, DOT11F_EID_VENDOR2IE, 0, }, + {offsetof(tDot11fTimingAdvertisementFrame, Vendor3IE), offsetof(tDot11fIEVendor3IE, present), 0, "Vendor3IE" , 0, 5, 5, SigIeVendor3IE, {0, 22, 50, 0, 0}, 3, DOT11F_EID_VENDOR3IE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackTimingAdvertisementFrame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTimingAdvertisementFrame *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_TimingAdvertisementFrame, IES_TimingAdvertisementFrame, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Unpacked the TimingAdvertisementFrame:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("TimeAdvertisement:\n")); + if (!pFrm->TimeAdvertisement.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeAdvertisement.timing_capabilities, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeAdvertisement.time_value, 10); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeAdvertisement.time_error, 5); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTimingAdvertisementFrame. */ + + static const tFFDefn FFS_VHTGidManagementActionFrame[] = { + { "Category", offsetof(tDot11fVHTGidManagementActionFrame, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fVHTGidManagementActionFrame, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "VhtMembershipStatusArray", offsetof(tDot11fVHTGidManagementActionFrame, VhtMembershipStatusArray), SigFfVhtMembershipStatusArray , DOT11F_FF_VHTMEMBERSHIPSTATUSARRAY_LEN, }, + { "VhtUserPositionArray", offsetof(tDot11fVHTGidManagementActionFrame, VhtUserPositionArray), SigFfVhtUserPositionArray , DOT11F_FF_VHTUSERPOSITIONARRAY_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_VHTGidManagementActionFrame[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackVHTGidManagementActionFrame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fVHTGidManagementActionFrame *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_VHTGidManagementActionFrame, IES_VHTGidManagementActionFrame, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("Unpacked the VHTGidManagementActionFrame:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("VhtMembershipStatusArray:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->VhtMembershipStatusArray.membershipStatusArray, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("VhtUserPositionArray:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->VhtUserPositionArray.userPositionArray, 16); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackVHTGidManagementActionFrame. */ + + static const tFFDefn FFS_WMMAddTSRequest[] = { + { "Category", offsetof(tDot11fWMMAddTSRequest, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fWMMAddTSRequest, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fWMMAddTSRequest, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "StatusCode", offsetof(tDot11fWMMAddTSRequest, StatusCode), SigFfStatusCode , DOT11F_FF_STATUSCODE_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_WMMAddTSRequest[] = { + {offsetof(tDot11fWMMAddTSRequest, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), 0, "WMMTSPEC" , 0, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 1, }, + {offsetof(tDot11fWMMAddTSRequest, ESETrafStrmRateSet), offsetof(tDot11fIEESETrafStrmRateSet, present), 0, "ESETrafStrmRateSet" , 0, 7, 15, SigIeESETrafStrmRateSet, {0, 64, 150, 8, 0}, 4, DOT11F_EID_ESETRAFSTRMRATESET, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackWMMAddTSRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fWMMAddTSRequest *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_WMMAddTSRequest, IES_WMMAddTSRequest, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Unpacked the WMMAddTSRequest:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("StatusCode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->StatusCode.statusCode, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackWMMAddTSRequest. */ + + static const tFFDefn FFS_WMMAddTSResponse[] = { + { "Category", offsetof(tDot11fWMMAddTSResponse, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fWMMAddTSResponse, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fWMMAddTSResponse, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "StatusCode", offsetof(tDot11fWMMAddTSResponse, StatusCode), SigFfStatusCode , DOT11F_FF_STATUSCODE_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_WMMAddTSResponse[] = { + {offsetof(tDot11fWMMAddTSResponse, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), 0, "WMMTSPEC" , 0, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 0, }, + {offsetof(tDot11fWMMAddTSResponse, ESETrafStrmMet), offsetof(tDot11fIEESETrafStrmMet, present), 0, "ESETrafStrmMet" , 0, 10, 10, SigIeESETrafStrmMet, {0, 64, 150, 7, 0}, 4, DOT11F_EID_ESETRAFSTRMMET, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackWMMAddTSResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fWMMAddTSResponse *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_WMMAddTSResponse, IES_WMMAddTSResponse, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Unpacked the WMMAddTSResponse:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("StatusCode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->StatusCode.statusCode, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackWMMAddTSResponse. */ + + static const tFFDefn FFS_WMMDelTS[] = { + { "Category", offsetof(tDot11fWMMDelTS, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fWMMDelTS, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "DialogToken", offsetof(tDot11fWMMDelTS, DialogToken), SigFfDialogToken , DOT11F_FF_DIALOGTOKEN_LEN, }, + { "StatusCode", offsetof(tDot11fWMMDelTS, StatusCode), SigFfStatusCode , DOT11F_FF_STATUSCODE_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_WMMDelTS[] = { + {offsetof(tDot11fWMMDelTS, WMMTSPEC), offsetof(tDot11fIEWMMTSPEC, present), 0, "WMMTSPEC" , 0, 63, 63, SigIeWMMTSPEC, {0, 80, 242, 2, 2}, 5, DOT11F_EID_WMMTSPEC, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackWMMDelTS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fWMMDelTS *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_WMMDelTS, IES_WMMDelTS, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Unpacked the WMMDelTS:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("StatusCode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->StatusCode.statusCode, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackWMMDelTS. */ + + static const tFFDefn FFS_ext_channel_switch_action_frame[] = { + { "Category", offsetof(tDot11fext_channel_switch_action_frame, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fext_channel_switch_action_frame, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, + { "ext_chan_switch_ann_action", offsetof(tDot11fext_channel_switch_action_frame, ext_chan_switch_ann_action), SigFfext_chan_switch_ann_action , DOT11F_FF_EXT_CHAN_SWITCH_ANN_ACTION_LEN, }, + { NULL, 0, 0, 0,}, + }; + + static const tIEDefn IES_ext_channel_switch_action_frame[] = { + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; + +tANI_U32 dot11fUnpackext_channel_switch_action_frame(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fext_channel_switch_action_frame *pFrm) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + status = UnpackCore(pCtx, pBuf, nBuf, FFS_ext_channel_switch_action_frame, IES_ext_channel_switch_action_frame, ( tANI_U8* )pFrm, sizeof(*pFrm)); + + (void)i; +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("Unpacked the ext_channel_switch_action_frame:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), pBuf, nBuf); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("to:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("ext_chan_switch_ann_action:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("switch_mode (8): %d\n"), pFrm->ext_chan_switch_ann_action.switch_mode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("op_class (8): %d\n"), pFrm->ext_chan_switch_ann_action.op_class); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("new_channel (8): %d\n"), pFrm->ext_chan_switch_ann_action.new_channel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("switch_count (8): %d\n"), pFrm->ext_chan_switch_ann_action.switch_count); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackext_channel_switch_action_frame. */ + +static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + const tFFDefn FFs[], + const tIEDefn IEs[], + tANI_U8 *pFrm, + size_t nFrm) +{ + const tFFDefn *pFf; + const tIEDefn *pIe; + tANI_U8 *pBufRemaining; + tANI_U32 nBufRemaining, status; + tANI_U8 eid, len; + tFRAMES_BOOL *pfFound; + tANI_U32 countOffset = 0; + + DOT11F_PARAMETER_CHECK(pBuf, nBuf, pFrm, nFrm); + (void)nFrm; + + (void)pCtx; + status = DOT11F_PARSE_SUCCESS; + pBufRemaining = pBuf; + nBufRemaining = nBuf; + + pIe = &IEs[0]; + while (0xff != pIe->eid) + { + pfFound = (tFRAMES_BOOL*)(pFrm + pIe->offset + + pIe->presenceOffset); + *pfFound = 0U; + if (pIe->countOffset) + { + *( tANI_U16* )(pFrm + pIe->countOffset) = 0U; + } + ++pIe; + } + + pFf = &FFs[0]; + while (pFf->size) + { + if (pFf->size > nBufRemaining) + { + FRAMES_LOG3(pCtx, FRLOGE, FRFL("Fixed field %s is %d b" + "ytes in size, but there are only %d bytes left i" + "n this frame.\n"), pFf->name, pFf->size, + nBufRemaining); + FRAMES_DBG_BREAK(); + return DOT11F_MISSING_FIXED_FIELD; + } + + switch (pFf->sig) + { + + case SigFfAID: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfAID* )(pFrm + pFf->offset ))->associd)); + break; + case SigFfAction: + dot11fUnpackFfAction(pCtx, pBufRemaining, ( tDot11fFfAction* )(pFrm + pFf->offset )); + break; + case SigFfAddBAParameterSet: + dot11fUnpackFfAddBAParameterSet(pCtx, pBufRemaining, ( tDot11fFfAddBAParameterSet* )(pFrm + pFf->offset )); + break; + case SigFfAuthAlgo: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfAuthAlgo* )(pFrm + pFf->offset ))->algo)); + break; + case SigFfAuthSeqNo: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfAuthSeqNo* )(pFrm + pFf->offset ))->no)); + break; + case SigFfBAStartingSequenceControl: + dot11fUnpackFfBAStartingSequenceControl(pCtx, pBufRemaining, ( tDot11fFfBAStartingSequenceControl* )(pFrm + pFf->offset )); + break; + case SigFfBATimeout: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfBATimeout* )(pFrm + pFf->offset ))->timeout)); + break; + case SigFfBeaconInterval: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfBeaconInterval* )(pFrm + pFf->offset ))->interval)); + break; + case SigFfCapabilities: + dot11fUnpackFfCapabilities(pCtx, pBufRemaining, ( tDot11fFfCapabilities* )(pFrm + pFf->offset )); + break; + case SigFfCategory: + dot11fUnpackFfCategory(pCtx, pBufRemaining, ( tDot11fFfCategory* )(pFrm + pFf->offset )); + break; + case SigFfCurrentAPAddress: + dot11fUnpackFfCurrentAPAddress(pCtx, pBufRemaining, ( tDot11fFfCurrentAPAddress* )(pFrm + pFf->offset )); + break; + case SigFfDelBAParameterSet: + dot11fUnpackFfDelBAParameterSet(pCtx, pBufRemaining, ( tDot11fFfDelBAParameterSet* )(pFrm + pFf->offset )); + break; + case SigFfDialogToken: + dot11fUnpackFfDialogToken(pCtx, pBufRemaining, ( tDot11fFfDialogToken* )(pFrm + pFf->offset )); + break; + case SigFfLinkMargin: + dot11fUnpackFfLinkMargin(pCtx, pBufRemaining, ( tDot11fFfLinkMargin* )(pFrm + pFf->offset )); + break; + case SigFfListenInterval: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfListenInterval* )(pFrm + pFf->offset ))->interval)); + break; + case SigFfMaxTxPower: + dot11fUnpackFfMaxTxPower(pCtx, pBufRemaining, ( tDot11fFfMaxTxPower* )(pFrm + pFf->offset )); + break; + case SigFfNumOfRepetitions: + dot11fUnpackFfNumOfRepetitions(pCtx, pBufRemaining, ( tDot11fFfNumOfRepetitions* )(pFrm + pFf->offset )); + break; + case SigFfOperatingMode: + dot11fUnpackFfOperatingMode(pCtx, pBufRemaining, ( tDot11fFfOperatingMode* )(pFrm + pFf->offset )); + break; + case SigFfP2POUI: + dot11fUnpackFfP2POUI(pCtx, pBufRemaining, ( tDot11fFfP2POUI* )(pFrm + pFf->offset )); + break; + case SigFfP2POUISubType: + dot11fUnpackFfP2POUISubType(pCtx, pBufRemaining, ( tDot11fFfP2POUISubType* )(pFrm + pFf->offset )); + break; + case SigFfRCPI: + dot11fUnpackFfRCPI(pCtx, pBufRemaining, ( tDot11fFfRCPI* )(pFrm + pFf->offset )); + break; + case SigFfRSNI: + dot11fUnpackFfRSNI(pCtx, pBufRemaining, ( tDot11fFfRSNI* )(pFrm + pFf->offset )); + break; + case SigFfReason: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfReason* )(pFrm + pFf->offset ))->code)); + break; + case SigFfRxAntennaId: + dot11fUnpackFfRxAntennaId(pCtx, pBufRemaining, ( tDot11fFfRxAntennaId* )(pFrm + pFf->offset )); + break; + case SigFfSMPowerModeSet: + dot11fUnpackFfSMPowerModeSet(pCtx, pBufRemaining, ( tDot11fFfSMPowerModeSet* )(pFrm + pFf->offset )); + break; + case SigFfStatus: + dot11fUnpackFfCommonFunc(pCtx, pBufRemaining, (tANI_U16*)&((( tDot11fFfStatus* )(pFrm + pFf->offset ))->status)); + break; + case SigFfStatusCode: + dot11fUnpackFfStatusCode(pCtx, pBufRemaining, ( tDot11fFfStatusCode* )(pFrm + pFf->offset )); + break; + case SigFfTPCEleID: + dot11fUnpackFfTPCEleID(pCtx, pBufRemaining, ( tDot11fFfTPCEleID* )(pFrm + pFf->offset )); + break; + case SigFfTPCEleLen: + dot11fUnpackFfTPCEleLen(pCtx, pBufRemaining, ( tDot11fFfTPCEleLen* )(pFrm + pFf->offset )); + break; + case SigFfTSInfo: + dot11fUnpackFfTSInfo(pCtx, pBufRemaining, ( tDot11fFfTSInfo* )(pFrm + pFf->offset )); + break; + case SigFfTimeStamp: + dot11fUnpackFfTimeStamp(pCtx, pBufRemaining, ( tDot11fFfTimeStamp* )(pFrm + pFf->offset )); + break; + case SigFfTransactionId: + dot11fUnpackFfTransactionId(pCtx, pBufRemaining, ( tDot11fFfTransactionId* )(pFrm + pFf->offset )); + break; + case SigFfTxAntennaId: + dot11fUnpackFfTxAntennaId(pCtx, pBufRemaining, ( tDot11fFfTxAntennaId* )(pFrm + pFf->offset )); + break; + case SigFfTxPower: + dot11fUnpackFfTxPower(pCtx, pBufRemaining, ( tDot11fFfTxPower* )(pFrm + pFf->offset )); + break; + case SigFfVhtMembershipStatusArray: + dot11fUnpackFfVhtMembershipStatusArray(pCtx, pBufRemaining, ( tDot11fFfVhtMembershipStatusArray* )(pFrm + pFf->offset )); + break; + case SigFfVhtUserPositionArray: + dot11fUnpackFfVhtUserPositionArray(pCtx, pBufRemaining, ( tDot11fFfVhtUserPositionArray* )(pFrm + pFf->offset )); + break; + case SigFfext_chan_switch_ann_action: + dot11fUnpackFfext_chan_switch_ann_action(pCtx, pBufRemaining, ( tDot11fFfext_chan_switch_ann_action* )(pFrm + pFf->offset )); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR: I don'" + "t know about the FF signature %d-- this is most " + "likely a 'framesc' bug.\n"), pFf->sig); + return DOT11F_INTERNAL_ERROR; + } + + pBufRemaining += pFf->size; + nBufRemaining -= pFf->size; + ++pFf; + } + + while (nBufRemaining) + { + if (1 == nBufRemaining) + { + FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " + "only one byte remaining after it's fixed fields.\n")); + status |= DOT11F_INCOMPLETE_IE; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + + pIe = FindIEDefn(pCtx, pBufRemaining, nBufRemaining, IEs); + + eid = *pBufRemaining++; --nBufRemaining; + len = *pBufRemaining++; --nBufRemaining; + + if (pIe && pIe->noui) + { + if (pIe->noui > nBufRemaining) + { + FRAMES_LOG3(pCtx, FRLOGW, FRFL("IE %d reports " + "length %d, but it has an OUI of %d bytes.\n"), + eid, len, pIe->noui); + FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf); + FRAMES_LOG2(pCtx, FRLOG1, FRFL("We've parsed %d by" + "tes of this buffer, and show %d left.\n"), pBufRemaining - pBuf, nBufRemaining); + status |= DOT11F_INCOMPLETE_IE; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + pBufRemaining += pIe->noui; + nBufRemaining -= pIe->noui; + len -= pIe->noui; + } + + if (len > nBufRemaining) + { + FRAMES_LOG3(pCtx, FRLOGW, FRFL("IE %d reports length %" + "d, but there are only %d bytes remaining in this" + " frame.\n"), eid, len, nBufRemaining); + FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf); + FRAMES_LOG2(pCtx, FRLOG1, FRFL("We've parsed %d by" + "tes of this buffer, and show %d left.\n"), pBufRemaining - pBuf, nBufRemaining); + status |= DOT11F_INCOMPLETE_IE; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + + if (pIe) + { + if (nBufRemaining < pIe->minSize - pIe->noui - 2U) + { + FRAMES_LOG3(pCtx, FRLOGW, FRFL("The IE %s must be " + "at least %d bytes in size, but there are onl" + "y %d bytes remaining in this frame.\n"), + pIe->name, pIe->minSize, nBufRemaining); + FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf); + status |= DOT11F_INCOMPLETE_IE; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + else + { + if (len > pIe->maxSize - pIe->noui - 2U){ + FRAMES_LOG1(pCtx, FRLOGW, FRFL("The IE %s reports " + "an unexpectedly large size; it is presumably " + "more up-to-date than this parser, but this wa" + "rning may also indicate a corrupt frame.\n"), + pIe->name); + FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf); + } + + countOffset = ( (0 != pIe->arraybound) * ( *(tANI_U16* )(pFrm + pIe->countOffset))); + switch (pIe->sig) + { + case SigIeCondensedCountryStr: + status |= dot11fUnpackIeCondensedCountryStr(pCtx, pBufRemaining, len, ( tDot11fIECondensedCountryStr* )(pFrm + pIe->offset + sizeof(tDot11fIECondensedCountryStr)*countOffset) ); + break; + case SigIeGTK: + status |= dot11fUnpackIeGTK(pCtx, pBufRemaining, len, ( tDot11fIEGTK* )(pFrm + pIe->offset + sizeof(tDot11fIEGTK)*countOffset) ); + break; + case SigIeIGTK: + status |= dot11fUnpackIeIGTK(pCtx, pBufRemaining, len, ( tDot11fIEIGTK* )(pFrm + pIe->offset + sizeof(tDot11fIEIGTK)*countOffset) ); + break; + case SigIeR0KH_ID: + status |= dot11fUnpackIeR0KH_ID(pCtx, pBufRemaining, len, ( tDot11fIER0KH_ID* )(pFrm + pIe->offset + sizeof(tDot11fIER0KH_ID)*countOffset) ); + break; + case SigIeR1KH_ID: + status |= dot11fUnpackIeR1KH_ID(pCtx, pBufRemaining, len, ( tDot11fIER1KH_ID* )(pFrm + pIe->offset + sizeof(tDot11fIER1KH_ID)*countOffset) ); + break; + case SigIeTSFInfo: + status |= dot11fUnpackIeTSFInfo(pCtx, pBufRemaining, len, ( tDot11fIETSFInfo* )(pFrm + pIe->offset + sizeof(tDot11fIETSFInfo)*countOffset) ); + break; + case SigIeAPChannelReport: + status |= dot11fUnpackIeAPChannelReport(pCtx, pBufRemaining, len, ( tDot11fIEAPChannelReport* )(pFrm + pIe->offset + sizeof(tDot11fIEAPChannelReport)*countOffset) ); + break; + case SigIeBcnReportingDetail: + status |= dot11fUnpackIeBcnReportingDetail(pCtx, pBufRemaining, len, ( tDot11fIEBcnReportingDetail* )(pFrm + pIe->offset + sizeof(tDot11fIEBcnReportingDetail)*countOffset) ); + break; + case SigIeBeaconReportFrmBody: + status |= dot11fUnpackIeBeaconReportFrmBody(pCtx, pBufRemaining, len, ( tDot11fIEBeaconReportFrmBody* )(pFrm + pIe->offset + sizeof(tDot11fIEBeaconReportFrmBody)*countOffset) ); + break; + case SigIeBeaconReporting: + status |= dot11fUnpackIeBeaconReporting(pCtx, pBufRemaining, len, ( tDot11fIEBeaconReporting* )(pFrm + pIe->offset + sizeof(tDot11fIEBeaconReporting)*countOffset) ); + break; + case SigIeMeasurementPilot: + status |= dot11fUnpackIeMeasurementPilot(pCtx, pBufRemaining, len, ( tDot11fIEMeasurementPilot* )(pFrm + pIe->offset + sizeof(tDot11fIEMeasurementPilot)*countOffset) ); + break; + case SigIeMultiBssid: + status |= dot11fUnpackIeMultiBssid(pCtx, pBufRemaining, len, ( tDot11fIEMultiBssid* )(pFrm + pIe->offset + sizeof(tDot11fIEMultiBssid)*countOffset) ); + break; + case SigIeRICData: + status |= dot11fUnpackIeRICData(pCtx, pBufRemaining, len, ( tDot11fIERICData* )(pFrm + pIe->offset + sizeof(tDot11fIERICData)*countOffset) ); + break; + case SigIeRICDescriptor: + status |= dot11fUnpackIeRICDescriptor(pCtx, pBufRemaining, len, ( tDot11fIERICDescriptor* )(pFrm + pIe->offset + sizeof(tDot11fIERICDescriptor)*countOffset) ); + break; + case SigIeRRMEnabledCap: + status |= dot11fUnpackIeRRMEnabledCap(pCtx, pBufRemaining, len, ( tDot11fIERRMEnabledCap* )(pFrm + pIe->offset + sizeof(tDot11fIERRMEnabledCap)*countOffset) ); + break; + case SigIeRequestedInfo: + status |= dot11fUnpackIeRequestedInfo(pCtx, pBufRemaining, len, ( tDot11fIERequestedInfo* )(pFrm + pIe->offset + sizeof(tDot11fIERequestedInfo)*countOffset) ); + break; + case SigIeSSID: + status |= dot11fUnpackIeSSID(pCtx, pBufRemaining, len, ( tDot11fIESSID* )(pFrm + pIe->offset + sizeof(tDot11fIESSID)*countOffset) ); + break; + case SigIeSchedule: + status |= dot11fUnpackIeSchedule(pCtx, pBufRemaining, len, ( tDot11fIESchedule* )(pFrm + pIe->offset + sizeof(tDot11fIESchedule)*countOffset) ); + break; + case SigIeTCLAS: + status |= dot11fUnpackIeTCLAS(pCtx, pBufRemaining, len, ( tDot11fIETCLAS* )(pFrm + pIe->offset + sizeof(tDot11fIETCLAS)*countOffset) ); + break; + case SigIeTCLASSPROC: + status |= dot11fUnpackIeCommonFunc(pCtx, pBufRemaining, len, + (tANI_U8*) &((( tDot11fIETCLASSPROC* )(pFrm + pIe->offset + sizeof( tDot11fIETCLASSPROC)*countOffset ) )->present), + (tANI_U8*) &((( tDot11fIETCLASSPROC* )(pFrm + pIe->offset + sizeof(tDot11fIETCLASSPROC)*countOffset ) )->processing) ); + break; + case SigIeTSDelay: + status |= dot11fUnpackIeTSDelay(pCtx, pBufRemaining, len, ( tDot11fIETSDelay* )(pFrm + pIe->offset + sizeof(tDot11fIETSDelay)*countOffset) ); + break; + case SigIeTSPEC: + status |= dot11fUnpackIeTSPEC(pCtx, pBufRemaining, len, ( tDot11fIETSPEC* )(pFrm + pIe->offset + sizeof(tDot11fIETSPEC)*countOffset) ); + break; + case SigIeWMMSchedule: + status |= dot11fUnpackIeWMMSchedule(pCtx, pBufRemaining, len, ( tDot11fIEWMMSchedule* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMSchedule)*countOffset) ); + break; + case SigIeWMMTCLAS: + status |= dot11fUnpackIeWMMTCLAS(pCtx, pBufRemaining, len, ( tDot11fIEWMMTCLAS* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMTCLAS)*countOffset) ); + break; + case SigIeWMMTCLASPROC: + status |= dot11fUnpackIeWMMTCLASPROC(pCtx, pBufRemaining, len, ( tDot11fIEWMMTCLASPROC* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMTCLASPROC)*countOffset) ); + break; + case SigIeWMMTSDelay: + status |= dot11fUnpackIeWMMTSDelay(pCtx, pBufRemaining, len, ( tDot11fIEWMMTSDelay* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMTSDelay)*countOffset) ); + break; + case SigIeWMMTSPEC: + status |= dot11fUnpackIeWMMTSPEC(pCtx, pBufRemaining, len, ( tDot11fIEWMMTSPEC* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMTSPEC)*countOffset) ); + break; + case SigIeWiderBWChanSwitchAnn: + status |= dot11fUnpackIeWiderBWChanSwitchAnn(pCtx, pBufRemaining, len, ( tDot11fIEWiderBWChanSwitchAnn* )(pFrm + pIe->offset + sizeof(tDot11fIEWiderBWChanSwitchAnn)*countOffset) ); + break; + case SigIeAID: + status |= dot11fUnpackIeAID(pCtx, pBufRemaining, len, ( tDot11fIEAID* )(pFrm + pIe->offset + sizeof(tDot11fIEAID)*countOffset) ); + break; + case SigIeCFParams: + status |= dot11fUnpackIeCFParams(pCtx, pBufRemaining, len, ( tDot11fIECFParams* )(pFrm + pIe->offset + sizeof(tDot11fIECFParams)*countOffset) ); + break; + case SigIeChallengeText: + status |= dot11fUnpackIeChallengeText(pCtx, pBufRemaining, len, ( tDot11fIEChallengeText* )(pFrm + pIe->offset + sizeof(tDot11fIEChallengeText)*countOffset) ); + break; + case SigIeChanSwitchAnn: + status |= dot11fUnpackIeChanSwitchAnn(pCtx, pBufRemaining, len, ( tDot11fIEChanSwitchAnn* )(pFrm + pIe->offset + sizeof(tDot11fIEChanSwitchAnn)*countOffset) ); + break; + case SigIeChannelSwitchWrapper: + status |= dot11fUnpackIeChannelSwitchWrapper(pCtx, pBufRemaining, len, ( tDot11fIEChannelSwitchWrapper* )(pFrm + pIe->offset + sizeof(tDot11fIEChannelSwitchWrapper)*countOffset) ); + break; + case SigIeCountry: + status |= dot11fUnpackIeCountry(pCtx, pBufRemaining, len, ( tDot11fIECountry* )(pFrm + pIe->offset + sizeof(tDot11fIECountry)*countOffset) ); + break; + case SigIeDSParams: + status |= dot11fUnpackIeCommonFunc(pCtx, pBufRemaining, len, + (tANI_U8*) &((( tDot11fIEDSParams* )(pFrm + pIe->offset + sizeof( tDot11fIEDSParams)*countOffset ) )->present), + (tANI_U8*) &((( tDot11fIEDSParams* )(pFrm + pIe->offset + sizeof(tDot11fIEDSParams)*countOffset ) )->curr_channel) ); + break; + case SigIeEDCAParamSet: + status |= dot11fUnpackIeEDCAParamSet(pCtx, pBufRemaining, len, ( tDot11fIEEDCAParamSet* )(pFrm + pIe->offset + sizeof(tDot11fIEEDCAParamSet)*countOffset) ); + break; + case SigIeERPInfo: + status |= dot11fUnpackIeERPInfo(pCtx, pBufRemaining, len, ( tDot11fIEERPInfo* )(pFrm + pIe->offset + sizeof(tDot11fIEERPInfo)*countOffset) ); + break; + case SigIeESECckmOpaque: + status |= dot11fUnpackIeESECckmOpaque(pCtx, pBufRemaining, len, ( tDot11fIEESECckmOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEESECckmOpaque)*countOffset) ); + break; + case SigIeESERadMgmtCap: + status |= dot11fUnpackIeESERadMgmtCap(pCtx, pBufRemaining, len, ( tDot11fIEESERadMgmtCap* )(pFrm + pIe->offset + sizeof(tDot11fIEESERadMgmtCap)*countOffset) ); + break; + case SigIeESETrafStrmMet: + status |= dot11fUnpackIeESETrafStrmMet(pCtx, pBufRemaining, len, ( tDot11fIEESETrafStrmMet* )(pFrm + pIe->offset + sizeof(tDot11fIEESETrafStrmMet)*countOffset) ); + break; + case SigIeESETrafStrmRateSet: + status |= dot11fUnpackIeESETrafStrmRateSet(pCtx, pBufRemaining, len, ( tDot11fIEESETrafStrmRateSet* )(pFrm + pIe->offset + sizeof(tDot11fIEESETrafStrmRateSet)*countOffset) ); + break; + case SigIeESETxmitPower: + status |= dot11fUnpackIeESETxmitPower(pCtx, pBufRemaining, len, ( tDot11fIEESETxmitPower* )(pFrm + pIe->offset + sizeof(tDot11fIEESETxmitPower)*countOffset) ); + break; + case SigIeESEVersion: + status |= dot11fUnpackIeESEVersion(pCtx, pBufRemaining, len, ( tDot11fIEESEVersion* )(pFrm + pIe->offset + sizeof(tDot11fIEESEVersion)*countOffset) ); + break; + case SigIeExtCap: + status |= dot11fUnpackIeExtCap(pCtx, pBufRemaining, len, ( tDot11fIEExtCap* )(pFrm + pIe->offset + sizeof(tDot11fIEExtCap)*countOffset) ); + break; + case SigIeExtSuppRates: + status |= dot11fUnpackIeExtSuppRates(pCtx, pBufRemaining, len, ( tDot11fIEExtSuppRates* )(pFrm + pIe->offset + sizeof(tDot11fIEExtSuppRates)*countOffset) ); + break; + case SigIeFHParamSet: + status |= dot11fUnpackIeFHParamSet(pCtx, pBufRemaining, len, ( tDot11fIEFHParamSet* )(pFrm + pIe->offset + sizeof(tDot11fIEFHParamSet)*countOffset) ); + break; + case SigIeFHParams: + status |= dot11fUnpackIeFHParams(pCtx, pBufRemaining, len, ( tDot11fIEFHParams* )(pFrm + pIe->offset + sizeof(tDot11fIEFHParams)*countOffset) ); + break; + case SigIeFHPattTable: + status |= dot11fUnpackIeFHPattTable(pCtx, pBufRemaining, len, ( tDot11fIEFHPattTable* )(pFrm + pIe->offset + sizeof(tDot11fIEFHPattTable)*countOffset) ); + break; + case SigIeFTInfo: + status |= dot11fUnpackIeFTInfo(pCtx, pBufRemaining, len, ( tDot11fIEFTInfo* )(pFrm + pIe->offset + sizeof(tDot11fIEFTInfo)*countOffset) ); + break; + case SigIeHT2040BSSCoexistence: + status |= dot11fUnpackIeHT2040BSSCoexistence(pCtx, pBufRemaining, len, ( tDot11fIEHT2040BSSCoexistence* )(pFrm + pIe->offset + sizeof(tDot11fIEHT2040BSSCoexistence)*countOffset) ); + break; + case SigIeHT2040BSSIntolerantReport: + status |= dot11fUnpackIeHT2040BSSIntolerantReport(pCtx, pBufRemaining, len, ( tDot11fIEHT2040BSSIntolerantReport* )(pFrm + pIe->offset + sizeof(tDot11fIEHT2040BSSIntolerantReport)*countOffset) ); + break; + case SigIeHTCaps: + status |= dot11fUnpackIeHTCaps(pCtx, pBufRemaining, len, ( tDot11fIEHTCaps* )(pFrm + pIe->offset + sizeof(tDot11fIEHTCaps)*countOffset) ); + break; + case SigIeHTInfo: + status |= dot11fUnpackIeHTInfo(pCtx, pBufRemaining, len, ( tDot11fIEHTInfo* )(pFrm + pIe->offset + sizeof(tDot11fIEHTInfo)*countOffset) ); + break; + case SigIeIBSSParams: + status |= dot11fUnpackIeIBSSParams(pCtx, pBufRemaining, len, ( tDot11fIEIBSSParams* )(pFrm + pIe->offset + sizeof(tDot11fIEIBSSParams)*countOffset) ); + break; + case SigIeLinkIdentifier: + status |= dot11fUnpackIeLinkIdentifier(pCtx, pBufRemaining, len, ( tDot11fIELinkIdentifier* )(pFrm + pIe->offset + sizeof(tDot11fIELinkIdentifier)*countOffset) ); + break; + case SigIeMeasurementReport: + status |= dot11fUnpackIeMeasurementReport(pCtx, pBufRemaining, len, ( tDot11fIEMeasurementReport* )(pFrm + pIe->offset + sizeof(tDot11fIEMeasurementReport)*countOffset) ); + break; + case SigIeMeasurementRequest: + status |= dot11fUnpackIeMeasurementRequest(pCtx, pBufRemaining, len, ( tDot11fIEMeasurementRequest* )(pFrm + pIe->offset + sizeof(tDot11fIEMeasurementRequest)*countOffset) ); + break; + case SigIeMobilityDomain: + status |= dot11fUnpackIeMobilityDomain(pCtx, pBufRemaining, len, ( tDot11fIEMobilityDomain* )(pFrm + pIe->offset + sizeof(tDot11fIEMobilityDomain)*countOffset) ); + break; + case SigIeNeighborReport: + if (countOffset < MAX_SUPPORTED_NEIGHBOR_RPT) { + status |= dot11fUnpackIeNeighborReport(pCtx, pBufRemaining, len, ( tDot11fIENeighborReport* )(pFrm + pIe->offset + sizeof(tDot11fIENeighborReport)*countOffset) ); + } else { + status |= DOT11F_BUFFER_OVERFLOW; + } + break; + case SigIeOBSSScanParameters: + status |= dot11fUnpackIeOBSSScanParameters(pCtx, pBufRemaining, len, ( tDot11fIEOBSSScanParameters* )(pFrm + pIe->offset + sizeof(tDot11fIEOBSSScanParameters)*countOffset) ); + break; + case SigIeOperatingMode: + status |= dot11fUnpackIeOperatingMode(pCtx, pBufRemaining, len, ( tDot11fIEOperatingMode* )(pFrm + pIe->offset + sizeof(tDot11fIEOperatingMode)*countOffset) ); + break; + case SigIeP2PAssocReq: + status |= dot11fUnpackIeP2PAssocReq(pCtx, pBufRemaining, len, ( tDot11fIEP2PAssocReq* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PAssocReq)*countOffset) ); + break; + case SigIeP2PAssocRes: + status |= dot11fUnpackIeP2PAssocRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PAssocRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PAssocRes)*countOffset) ); + break; + case SigIeP2PBeacon: + status |= dot11fUnpackIeP2PBeacon(pCtx, pBufRemaining, len, ( tDot11fIEP2PBeacon* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PBeacon)*countOffset) ); + break; + case SigIeP2PBeaconProbeRes: + status |= dot11fUnpackIeP2PBeaconProbeRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PBeaconProbeRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PBeaconProbeRes)*countOffset) ); + break; + case SigIeP2PDeAuth: + status |= dot11fUnpackIeP2PDeAuth(pCtx, pBufRemaining, len, ( tDot11fIEP2PDeAuth* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PDeAuth)*countOffset) ); + break; + case SigIeP2PDeviceDiscoverabilityReq: + status |= dot11fUnpackIeP2PDeviceDiscoverabilityReq(pCtx, pBufRemaining, len, ( tDot11fIEP2PDeviceDiscoverabilityReq* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PDeviceDiscoverabilityReq)*countOffset) ); + break; + case SigIeP2PDeviceDiscoverabilityRes: + status |= dot11fUnpackIeP2PDeviceDiscoverabilityRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PDeviceDiscoverabilityRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PDeviceDiscoverabilityRes)*countOffset) ); + break; + case SigIeP2PDisAssoc: + status |= dot11fUnpackIeP2PDisAssoc(pCtx, pBufRemaining, len, ( tDot11fIEP2PDisAssoc* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PDisAssoc)*countOffset) ); + break; + case SigIeP2PGONegCnf: + status |= dot11fUnpackIeP2PGONegCnf(pCtx, pBufRemaining, len, ( tDot11fIEP2PGONegCnf* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PGONegCnf)*countOffset) ); + break; + case SigIeP2PGONegReq: + status |= dot11fUnpackIeP2PGONegReq(pCtx, pBufRemaining, len, ( tDot11fIEP2PGONegReq* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PGONegReq)*countOffset) ); + break; + case SigIeP2PGONegRes: + status |= dot11fUnpackIeP2PGONegRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PGONegRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PGONegRes)*countOffset) ); + break; + case SigIeP2PGONegWPS: + status |= dot11fUnpackIeP2PGONegWPS(pCtx, pBufRemaining, len, ( tDot11fIEP2PGONegWPS* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PGONegWPS)*countOffset) ); + break; + case SigIeP2PIEOpaque: + status |= dot11fUnpackIeP2PIEOpaque(pCtx, pBufRemaining, len, ( tDot11fIEP2PIEOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PIEOpaque)*countOffset) ); + break; + case SigIeP2PInvitationReq: + status |= dot11fUnpackIeP2PInvitationReq(pCtx, pBufRemaining, len, ( tDot11fIEP2PInvitationReq* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PInvitationReq)*countOffset) ); + break; + case SigIeP2PInvitationRes: + status |= dot11fUnpackIeP2PInvitationRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PInvitationRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PInvitationRes)*countOffset) ); + break; + case SigIeP2PNoticeOfAbsence: + status |= dot11fUnpackIeP2PNoticeOfAbsence(pCtx, pBufRemaining, len, ( tDot11fIEP2PNoticeOfAbsence* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PNoticeOfAbsence)*countOffset) ); + break; + case SigIeP2PPresenceResponse: + status |= dot11fUnpackIeP2PPresenceResponse(pCtx, pBufRemaining, len, ( tDot11fIEP2PPresenceResponse* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PPresenceResponse)*countOffset) ); + break; + case SigIeP2PProbeReq: + status |= dot11fUnpackIeP2PProbeReq(pCtx, pBufRemaining, len, ( tDot11fIEP2PProbeReq* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PProbeReq)*countOffset) ); + break; + case SigIeP2PProbeRes: + status |= dot11fUnpackIeP2PProbeRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PProbeRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PProbeRes)*countOffset) ); + break; + case SigIeP2PProvisionDiscoveryReq: + status |= dot11fUnpackIeP2PProvisionDiscoveryReq(pCtx, pBufRemaining, len, ( tDot11fIEP2PProvisionDiscoveryReq* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PProvisionDiscoveryReq)*countOffset) ); + break; + case SigIeP2PWSCProvisionDiscoveryRes: + status |= dot11fUnpackIeP2PWSCProvisionDiscoveryRes(pCtx, pBufRemaining, len, ( tDot11fIEP2PWSCProvisionDiscoveryRes* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PWSCProvisionDiscoveryRes)*countOffset) ); + break; + case SigIePTIControl: + status |= dot11fUnpackIePTIControl(pCtx, pBufRemaining, len, ( tDot11fIEPTIControl* )(pFrm + pIe->offset + sizeof(tDot11fIEPTIControl)*countOffset) ); + break; + case SigIePUBufferStatus: + status |= dot11fUnpackIePUBufferStatus(pCtx, pBufRemaining, len, ( tDot11fIEPUBufferStatus* )(pFrm + pIe->offset + sizeof(tDot11fIEPUBufferStatus)*countOffset) ); + break; + case SigIePowerCaps: + status |= dot11fUnpackIePowerCaps(pCtx, pBufRemaining, len, ( tDot11fIEPowerCaps* )(pFrm + pIe->offset + sizeof(tDot11fIEPowerCaps)*countOffset) ); + break; + case SigIePowerConstraints: + status |= dot11fUnpackIePowerConstraints(pCtx, pBufRemaining, len, ( tDot11fIEPowerConstraints* )(pFrm + pIe->offset + sizeof(tDot11fIEPowerConstraints)*countOffset) ); + break; + case SigIeQBSSLoad: + status |= dot11fUnpackIeQBSSLoad(pCtx, pBufRemaining, len, ( tDot11fIEQBSSLoad* )(pFrm + pIe->offset + sizeof(tDot11fIEQBSSLoad)*countOffset) ); + break; + case SigIeQComVendorIE: + status |= dot11fUnpackIeQComVendorIE(pCtx, pBufRemaining, len, ( tDot11fIEQComVendorIE* )(pFrm + pIe->offset + sizeof(tDot11fIEQComVendorIE)*countOffset) ); + break; + case SigIeQOSCapsAp: + status |= dot11fUnpackIeQOSCapsAp(pCtx, pBufRemaining, len, ( tDot11fIEQOSCapsAp* )(pFrm + pIe->offset + sizeof(tDot11fIEQOSCapsAp)*countOffset) ); + break; + case SigIeQOSCapsStation: + status |= dot11fUnpackIeQOSCapsStation(pCtx, pBufRemaining, len, ( tDot11fIEQOSCapsStation* )(pFrm + pIe->offset + sizeof(tDot11fIEQOSCapsStation)*countOffset) ); + break; + case SigIeQosMapSet: + status |= dot11fUnpackIeQosMapSet(pCtx, pBufRemaining, len, ( tDot11fIEQosMapSet* )(pFrm + pIe->offset + sizeof(tDot11fIEQosMapSet)*countOffset) ); + break; + case SigIeQuiet: + status |= dot11fUnpackIeQuiet(pCtx, pBufRemaining, len, ( tDot11fIEQuiet* )(pFrm + pIe->offset + sizeof(tDot11fIEQuiet)*countOffset) ); + break; + case SigIeRCPIIE: + status |= dot11fUnpackIeRCPIIE(pCtx, pBufRemaining, len, ( tDot11fIERCPIIE* )(pFrm + pIe->offset + sizeof(tDot11fIERCPIIE)*countOffset) ); + break; + case SigIeRICDataDesc: + //reset the pointers back since this is a container IE and it doesnt have its own EID and Len. + pBufRemaining -= 2; nBufRemaining += 2; + if ( pIe && pIe->noui ) + { + pBufRemaining -= pIe->noui; + nBufRemaining += pIe->noui; + len += pIe->noui; + } + status |= GetContainerIesLen(pCtx, pBufRemaining, nBufRemaining, &len, IES_RICDataDesc); + if (status != DOT11F_PARSE_SUCCESS && status != DOT11F_UNKNOWN_IES ) break; + status |= dot11fUnpackIeRICDataDesc(pCtx, pBufRemaining, len, ( tDot11fIERICDataDesc* )(pFrm + pIe->offset + sizeof(tDot11fIERICDataDesc)*countOffset) ); + break; + case SigIeRSN: + status |= dot11fUnpackIeRSN(pCtx, pBufRemaining, len, ( tDot11fIERSN* )(pFrm + pIe->offset + sizeof(tDot11fIERSN)*countOffset) ); + break; + case SigIeRSNIIE: + status |= dot11fUnpackIeRSNIIE(pCtx, pBufRemaining, len, ( tDot11fIERSNIIE* )(pFrm + pIe->offset + sizeof(tDot11fIERSNIIE)*countOffset) ); + break; + case SigIeRSNOpaque: + status |= dot11fUnpackIeRSNOpaque(pCtx, pBufRemaining, len, ( tDot11fIERSNOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIERSNOpaque)*countOffset) ); + break; + case SigIeSuppChannels: + status |= dot11fUnpackIeSuppChannels(pCtx, pBufRemaining, len, ( tDot11fIESuppChannels* )(pFrm + pIe->offset + sizeof(tDot11fIESuppChannels)*countOffset) ); + break; + case SigIeSuppOperatingClasses: + status |= dot11fUnpackIeSuppOperatingClasses(pCtx, pBufRemaining, len, ( tDot11fIESuppOperatingClasses* )(pFrm + pIe->offset + sizeof(tDot11fIESuppOperatingClasses)*countOffset) ); + break; + case SigIeSuppRates: + status |= dot11fUnpackIeSuppRates(pCtx, pBufRemaining, len, ( tDot11fIESuppRates* )(pFrm + pIe->offset + sizeof(tDot11fIESuppRates)*countOffset) ); + break; + case SigIeTIM: + status |= dot11fUnpackIeTIM(pCtx, pBufRemaining, len, ( tDot11fIETIM* )(pFrm + pIe->offset + sizeof(tDot11fIETIM)*countOffset) ); + break; + case SigIeTPCReport: + status |= dot11fUnpackIeTPCReport(pCtx, pBufRemaining, len, ( tDot11fIETPCReport* )(pFrm + pIe->offset + sizeof(tDot11fIETPCReport)*countOffset) ); + break; + case SigIeTPCRequest: + status |= dot11fUnpackIeTPCRequest(pCtx, pBufRemaining, len, ( tDot11fIETPCRequest* )(pFrm + pIe->offset + sizeof(tDot11fIETPCRequest)*countOffset) ); + break; + case SigIeTimeAdvertisement: + status |= dot11fUnpackIeTimeAdvertisement(pCtx, pBufRemaining, len, ( tDot11fIETimeAdvertisement* )(pFrm + pIe->offset + sizeof(tDot11fIETimeAdvertisement)*countOffset) ); + break; + case SigIeTimeoutInterval: + status |= dot11fUnpackIeTimeoutInterval(pCtx, pBufRemaining, len, ( tDot11fIETimeoutInterval* )(pFrm + pIe->offset + sizeof(tDot11fIETimeoutInterval)*countOffset) ); + break; + case SigIeVHTCaps: + status |= dot11fUnpackIeVHTCaps(pCtx, pBufRemaining, len, ( tDot11fIEVHTCaps* )(pFrm + pIe->offset + sizeof(tDot11fIEVHTCaps)*countOffset) ); + break; + case SigIeVHTExtBssLoad: + status |= dot11fUnpackIeVHTExtBssLoad(pCtx, pBufRemaining, len, ( tDot11fIEVHTExtBssLoad* )(pFrm + pIe->offset + sizeof(tDot11fIEVHTExtBssLoad)*countOffset) ); + break; + case SigIeVHTOperation: + status |= dot11fUnpackIeVHTOperation(pCtx, pBufRemaining, len, ( tDot11fIEVHTOperation* )(pFrm + pIe->offset + sizeof(tDot11fIEVHTOperation)*countOffset) ); + break; + case SigIeVendor1IE: + status |= dot11fUnpackIeVendor1IE(pCtx, pBufRemaining, len, ( tDot11fIEVendor1IE* )(pFrm + pIe->offset + sizeof(tDot11fIEVendor1IE)*countOffset) ); + break; + case SigIeVendor2IE: + status |= dot11fUnpackIeVendor2IE(pCtx, pBufRemaining, len, ( tDot11fIEVendor2IE* )(pFrm + pIe->offset + sizeof(tDot11fIEVendor2IE)*countOffset) ); + break; + case SigIeVendor3IE: + status |= dot11fUnpackIeVendor3IE(pCtx, pBufRemaining, len, ( tDot11fIEVendor3IE* )(pFrm + pIe->offset + sizeof(tDot11fIEVendor3IE)*countOffset) ); + break; + case SigIeWAPI: + status |= dot11fUnpackIeWAPI(pCtx, pBufRemaining, len, ( tDot11fIEWAPI* )(pFrm + pIe->offset + sizeof(tDot11fIEWAPI)*countOffset) ); + break; + case SigIeWAPIOpaque: + status |= dot11fUnpackIeWAPIOpaque(pCtx, pBufRemaining, len, ( tDot11fIEWAPIOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWAPIOpaque)*countOffset) ); + break; + case SigIeWFATPC: + status |= dot11fUnpackIeWFATPC(pCtx, pBufRemaining, len, ( tDot11fIEWFATPC* )(pFrm + pIe->offset + sizeof(tDot11fIEWFATPC)*countOffset) ); + break; + case SigIeWFDIEOpaque: + status |= dot11fUnpackIeWFDIEOpaque(pCtx, pBufRemaining, len, ( tDot11fIEWFDIEOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWFDIEOpaque)*countOffset) ); + break; + case SigIeWMMCaps: + status |= dot11fUnpackIeWMMCaps(pCtx, pBufRemaining, len, ( tDot11fIEWMMCaps* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMCaps)*countOffset) ); + break; + case SigIeWMMInfoAp: + status |= dot11fUnpackIeWMMInfoAp(pCtx, pBufRemaining, len, ( tDot11fIEWMMInfoAp* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMInfoAp)*countOffset) ); + break; + case SigIeWMMInfoStation: + status |= dot11fUnpackIeWMMInfoStation(pCtx, pBufRemaining, len, ( tDot11fIEWMMInfoStation* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMInfoStation)*countOffset) ); + break; + case SigIeWMMParams: + status |= dot11fUnpackIeWMMParams(pCtx, pBufRemaining, len, ( tDot11fIEWMMParams* )(pFrm + pIe->offset + sizeof(tDot11fIEWMMParams)*countOffset) ); + break; + case SigIeWPA: + status |= dot11fUnpackIeWPA(pCtx, pBufRemaining, len, ( tDot11fIEWPA* )(pFrm + pIe->offset + sizeof(tDot11fIEWPA)*countOffset) ); + break; + case SigIeWPAOpaque: + status |= dot11fUnpackIeWPAOpaque(pCtx, pBufRemaining, len, ( tDot11fIEWPAOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWPAOpaque)*countOffset) ); + break; + case SigIeWSC: + status |= dot11fUnpackIeWSC(pCtx, pBufRemaining, len, ( tDot11fIEWSC* )(pFrm + pIe->offset + sizeof(tDot11fIEWSC)*countOffset) ); + break; + case SigIeWscAssocReq: + status |= dot11fUnpackIeWscAssocReq(pCtx, pBufRemaining, len, ( tDot11fIEWscAssocReq* )(pFrm + pIe->offset + sizeof(tDot11fIEWscAssocReq)*countOffset) ); + break; + case SigIeWscAssocRes: + status |= dot11fUnpackIeWscAssocRes(pCtx, pBufRemaining, len, ( tDot11fIEWscAssocRes* )(pFrm + pIe->offset + sizeof(tDot11fIEWscAssocRes)*countOffset) ); + break; + case SigIeWscBeacon: + status |= dot11fUnpackIeWscBeacon(pCtx, pBufRemaining, len, ( tDot11fIEWscBeacon* )(pFrm + pIe->offset + sizeof(tDot11fIEWscBeacon)*countOffset) ); + break; + case SigIeWscBeaconProbeRes: + status |= dot11fUnpackIeWscBeaconProbeRes(pCtx, pBufRemaining, len, ( tDot11fIEWscBeaconProbeRes* )(pFrm + pIe->offset + sizeof(tDot11fIEWscBeaconProbeRes)*countOffset) ); + break; + case SigIeWscIEOpaque: + status |= dot11fUnpackIeWscIEOpaque(pCtx, pBufRemaining, len, ( tDot11fIEWscIEOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWscIEOpaque)*countOffset) ); + break; + case SigIeWscProbeReq: + status |= dot11fUnpackIeWscProbeReq(pCtx, pBufRemaining, len, ( tDot11fIEWscProbeReq* )(pFrm + pIe->offset + sizeof(tDot11fIEWscProbeReq)*countOffset) ); + break; + case SigIeWscProbeRes: + status |= dot11fUnpackIeWscProbeRes(pCtx, pBufRemaining, len, ( tDot11fIEWscProbeRes* )(pFrm + pIe->offset + sizeof(tDot11fIEWscProbeRes)*countOffset) ); + break; + case SigIeWscReassocRes: + status |= dot11fUnpackIeWscReassocRes(pCtx, pBufRemaining, len, ( tDot11fIEWscReassocRes* )(pFrm + pIe->offset + sizeof(tDot11fIEWscReassocRes)*countOffset) ); + break; + case SigIeext_chan_switch_ann: + status |= dot11fUnpackIeext_chan_switch_ann(pCtx, pBufRemaining, len, ( tDot11fIEext_chan_switch_ann* )(pFrm + pIe->offset + sizeof(tDot11fIEext_chan_switch_ann)*countOffset) ); + break; + case SigIesec_chan_offset_ele: + status |= dot11fUnpackIesec_chan_offset_ele(pCtx, pBufRemaining, len, ( tDot11fIEsec_chan_offset_ele* )(pFrm + pIe->offset + sizeof(tDot11fIEsec_chan_offset_ele)*countOffset) ); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR" + ": I don't know about the IE signature %d" + "-- this is most likely a 'framesc' bug.\n"), + pIe->sig); + FRAMES_DBG_BREAK(); + return DOT11F_INTERNAL_ERROR; + } + if (pIe->arraybound) (++( *(tANI_U16*)(pFrm + pIe->countOffset) )); + } + + + } + else + { + FRAMES_LOG2(pCtx, FRLOG3, FRFL("Skipping unknown IE %d" + " (length %d)\n"), eid, len); + FRAMES_DUMP(pCtx, FRLOG3, pBufRemaining - 2, len); + status |= DOT11F_UNKNOWN_IES; + } + + pBufRemaining += len; + + if (len > nBufRemaining) + { + FRAMES_LOG0(pCtx, FRLOGW, FRFL("This IE extends past " + "the buffer as it was defined to us. This could" + "mean a corrupt frame, or just an incorrect leng" + "th parameter.\n")); + FRAMES_DBG_BREAK(); + status |= DOT11F_LAST_IE_TOO_LONG; + goto MandatoryCheck; + } + + nBufRemaining -= len; + + } + +MandatoryCheck: + pIe = &IEs[0]; + while (0xff != pIe->eid) + { + if (pIe->fMandatory) + { + pfFound = (tFRAMES_BOOL*)(pFrm + pIe->offset + + pIe->presenceOffset); + if (!*pfFound) + { + FRAMES_LOG1(pCtx, FRLOGW, FRFL("ERROR: The mandato" + "ry IE %s wasn't seen.\n"), + pIe->name); + FRAMES_DBG_BREAK(); + status |= DOT11F_MANDATORY_IE_MISSING; + } + + } + ++pIe; + } + + return status; +} /* End UnpackCore. */ + +static tANI_U32 UnpackTlvCore( tpAniSirGlobal pCtx, + tANI_U8 *pBuf, + tANI_U32 nBuf, + const tTLVDefn TLVs[ ], + tANI_U8 *pFrm, + size_t nFrm ) +{ + const tTLVDefn *pTlv; + tANI_U32 nBufRemaining, status, npec; + tANI_U16 id, len; + tANI_U8 *pBufRemaining, *pfFound; + + (void)pCtx; // Shutup the compiler + (void)nFrm; + status = DOT11F_PARSE_SUCCESS; + pBufRemaining = pBuf; + nBufRemaining = nBuf; + + // While we have data... + while ( nBufRemaining ) + { + if ( 3 > nBufRemaining ) + { + FRAMES_LOG0( pCtx, FRLOGE, FRFL( "This frame reports " + "fewer three byte(s) remaining.\n" ) ); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + + npec = 0U; + + // Look for a matching TLV definition, + pTlv = FindTLVDefn( pCtx, pBufRemaining, nBufRemaining, TLVs ); + // consume the type, + if ( pTlv ) + { + if ( pTlv->sType == 2) + { + framesntohs(pCtx, &id, pBufRemaining, pTlv->fMsb); + pBufRemaining += 2; + nBufRemaining -= 2; + }else + { + id = *pBufRemaining; + pBufRemaining += 1; + nBufRemaining -= 1; + } + // & length, + if ( pTlv->sLen == 2) + { + framesntohs(pCtx, &len, pBufRemaining, pTlv->fMsb); + if ( 2 > nBufRemaining ) + { + FRAMES_LOG0( pCtx, FRLOGE, FRFL("This frame reports " + "fewer two byte(s) remaining.\n") ); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + pBufRemaining += 2; + nBufRemaining -= 2; + }else + { + len = *pBufRemaining; + pBufRemaining += 1; + nBufRemaining -= 1; + } + } + else + { + pBufRemaining += TLVs[0].sType; + nBufRemaining -= TLVs[0].sType; + framesntohs(pCtx, &len, pBufRemaining, (TLVs[0].sType == 2)); + if ( 2 > nBufRemaining ) + { + FRAMES_LOG0( pCtx, FRLOGE, FRFL("This frame reports " + "fewer two byte(s) remaining.\n") ); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + pBufRemaining += 2; + nBufRemaining -= 2; + } + + if ( pTlv && pTlv->pec ) + { + npec = 3U; + if ( 3 > nBufRemaining ) + { + FRAMES_LOG2(pCtx, FRLOGW, FRFL("TLV %d reports length" + "%d, but it has a Private Enterprise Code (3 byte" + "s.\n"), id, len); + FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf); + FRAMES_LOG2(pCtx, FRLOG1, FRFL("We've parsed %d bytes" + "of this buffer, and show %d left.\n"), + pBufRemaining - pBuf, nBufRemaining); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + pBufRemaining += 3; + nBufRemaining -= 3; + len -= 3; + } + + // Whether we found a hit or not, we can validate the reported + // length of this TLV: + if ( len > nBufRemaining ) + { + FRAMES_LOG3(pCtx, FRLOGW, FRFL("TLV %d reports length %" + "d, but there are only %d bytes remaining in this f" + "rame.\n"), id, len, nBufRemaining ); + FRAMES_DUMP( pCtx, FRLOG1, pBuf, nBuf ); + FRAMES_LOG2( pCtx, FRLOG1, FRFL( "We've parsed %d bytes" + " of this buffer, and show %d left.\n"), + pBufRemaining - pBuf, nBufRemaining); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK(); + goto MandatoryCheck; + } + + // Now, *if* we found a hit... + if ( pTlv ) + { + if ( len < pTlv->minSize - npec ) + { + FRAMES_LOG3( pCtx, FRLOGW, FRFL("The IE %s must be " + "at least %d bytes in size, but the size is only " + "%d bytes.\n"), + pTlv->name, pTlv->minSize, len ); + FRAMES_DUMP( pCtx, FRLOG1, pBuf, nBuf ); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK( ); + goto MandatoryCheck; + } + if ( nBufRemaining < pTlv->minSize - npec - (pTlv->sType + pTlv->sLen) ) + { + FRAMES_LOG3( pCtx, FRLOGW, FRFL("The IE %s must be " + "at least %d bytes in size, but there are only " + "%d bytes remaining in this frame.\n"), + pTlv->name, pTlv->minSize, nBufRemaining ); + FRAMES_DUMP( pCtx, FRLOG1, pBuf, nBuf ); + status |= DOT11F_INCOMPLETE_TLV; + FRAMES_DBG_BREAK( ); + goto MandatoryCheck; + } + else if ( len > pTlv->maxSize - npec - (pTlv->sType + pTlv->sLen) ) + { + FRAMES_LOG1( pCtx, FRLOGW, FRFL("The TLV %s reports " + "an illegally large size; this TLV is presumably" + "corrupt or otherwise invalid & will be skipped " + "ipped.\n"), pTlv->name ); + FRAMES_DUMP( pCtx, FRLOG1, pBuf, nBuf ); + FRAMES_LOG2( pCtx, FRLOG1, FRFL("We've parsed %d by" + "tes of this buffer, and show %d left.\n"), + pBufRemaining - pBuf, nBufRemaining); + FRAMES_DBG_BREAK(); + status |= DOT11F_SKIPPED_BAD_TLV; + } + else + { + switch (pTlv->sig) + { + case SigTlvAuthorizedMACs: + status |= dot11fUnpackTlvAuthorizedMACs(pCtx, pBufRemaining, len, ( tDot11fTLVAuthorizedMACs* )(pFrm + pTlv->offset )); + break; + case SigTlvRequestToEnroll: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVRequestToEnroll* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVRequestToEnroll*)(pFrm + pTlv->offset ))->req)); + break; + case SigTlvVersion2: + status |= dot11fUnpackTlvVersion2(pCtx, pBufRemaining, len, ( tDot11fTLVVersion2* )(pFrm + pTlv->offset )); + break; + case SigTlvAPSetupLocked: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVAPSetupLocked* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVAPSetupLocked*)(pFrm + pTlv->offset ))->fLocked)); + break; + case SigTlvAssociationState: + status |= dot11fUnpackTlvCommonFunc2(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVAssociationState* )(pFrm + pTlv->offset ))->present), (tANI_U16*)&((( tDot11fTLVAssociationState*)(pFrm + pTlv->offset ))->state)); + break; + case SigTlvChannelList: + status |= dot11fUnpackTlvChannelList(pCtx, pBufRemaining, len, ( tDot11fTLVChannelList* )(pFrm + pTlv->offset )); + break; + case SigTlvConfigMethods: + status |= dot11fUnpackTlvCommonFunc2(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVConfigMethods* )(pFrm + pTlv->offset ))->present), (tANI_U16*)&((( tDot11fTLVConfigMethods*)(pFrm + pTlv->offset ))->methods)); + break; + case SigTlvConfigurationError: + status |= dot11fUnpackTlvCommonFunc2(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVConfigurationError* )(pFrm + pTlv->offset ))->present), (tANI_U16*)&((( tDot11fTLVConfigurationError*)(pFrm + pTlv->offset ))->error)); + break; + case SigTlvConfigurationTimeout: + status |= dot11fUnpackTlvConfigurationTimeout(pCtx, pBufRemaining, len, ( tDot11fTLVConfigurationTimeout* )(pFrm + pTlv->offset )); + break; + case SigTlvDeviceName: + status |= dot11fUnpackTlvDeviceName(pCtx, pBufRemaining, len, ( tDot11fTLVDeviceName* )(pFrm + pTlv->offset )); + break; + case SigTlvDevicePasswordID: + status |= dot11fUnpackTlvCommonFunc2(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVDevicePasswordID* )(pFrm + pTlv->offset ))->present), (tANI_U16*)&((( tDot11fTLVDevicePasswordID*)(pFrm + pTlv->offset ))->id)); + break; + case SigTlvExtendedListenTiming: + status |= dot11fUnpackTlvExtendedListenTiming(pCtx, pBufRemaining, len, ( tDot11fTLVExtendedListenTiming* )(pFrm + pTlv->offset )); + break; + case SigTlvGOIntent: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVGOIntent* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVGOIntent*)(pFrm + pTlv->offset ))->GOIntent)); + break; + case SigTlvIntendedP2PInterfaceAddress: + status |= dot11fUnpackTlvIntendedP2PInterfaceAddress(pCtx, pBufRemaining, len, ( tDot11fTLVIntendedP2PInterfaceAddress* )(pFrm + pTlv->offset )); + break; + case SigTlvInvitationFlags: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVInvitationFlags* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVInvitationFlags*)(pFrm + pTlv->offset ))->invitationFlags)); + break; + case SigTlvListenChannel: + status |= dot11fUnpackTlvListenChannel(pCtx, pBufRemaining, len, ( tDot11fTLVListenChannel* )(pFrm + pTlv->offset )); + break; + case SigTlvManufacturer: + status |= dot11fUnpackTlvManufacturer(pCtx, pBufRemaining, len, ( tDot11fTLVManufacturer* )(pFrm + pTlv->offset )); + break; + case SigTlvMinorReasonCode: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVMinorReasonCode* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVMinorReasonCode*)(pFrm + pTlv->offset ))->minorReasonCode)); + break; + case SigTlvModelName: + status |= dot11fUnpackTlvModelName(pCtx, pBufRemaining, len, ( tDot11fTLVModelName* )(pFrm + pTlv->offset )); + break; + case SigTlvModelNumber: + status |= dot11fUnpackTlvModelNumber(pCtx, pBufRemaining, len, ( tDot11fTLVModelNumber* )(pFrm + pTlv->offset )); + break; + case SigTlvNoticeOfAbsence: + status |= dot11fUnpackTlvNoticeOfAbsence(pCtx, pBufRemaining, len, ( tDot11fTLVNoticeOfAbsence* )(pFrm + pTlv->offset )); + break; + case SigTlvOperatingChannel: + status |= dot11fUnpackTlvOperatingChannel(pCtx, pBufRemaining, len, ( tDot11fTLVOperatingChannel* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PCapability: + status |= dot11fUnpackTlvP2PCapability(pCtx, pBufRemaining, len, ( tDot11fTLVP2PCapability* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PDeviceId: + status |= dot11fUnpackTlvP2PDeviceId(pCtx, pBufRemaining, len, ( tDot11fTLVP2PDeviceId* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PDeviceInfo: + status |= dot11fUnpackTlvP2PDeviceInfo(pCtx, pBufRemaining, len, ( tDot11fTLVP2PDeviceInfo* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PGroupBssid: + status |= dot11fUnpackTlvP2PGroupBssid(pCtx, pBufRemaining, len, ( tDot11fTLVP2PGroupBssid* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PGroupId: + status |= dot11fUnpackTlvP2PGroupId(pCtx, pBufRemaining, len, ( tDot11fTLVP2PGroupId* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PGroupInfo: + status |= dot11fUnpackTlvP2PGroupInfo(pCtx, pBufRemaining, len, ( tDot11fTLVP2PGroupInfo* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PStatus: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVP2PStatus* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVP2PStatus*)(pFrm + pTlv->offset ))->status)); + break; + case SigTlvPrimaryDeviceType: + status |= dot11fUnpackTlvPrimaryDeviceType(pCtx, pBufRemaining, len, ( tDot11fTLVPrimaryDeviceType* )(pFrm + pTlv->offset )); + break; + case SigTlvRFBands: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVRFBands* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVRFBands*)(pFrm + pTlv->offset ))->bands)); + break; + case SigTlvRequestDeviceType: + status |= dot11fUnpackTlvRequestDeviceType(pCtx, pBufRemaining, len, ( tDot11fTLVRequestDeviceType* )(pFrm + pTlv->offset )); + break; + case SigTlvRequestType: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVRequestType* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVRequestType*)(pFrm + pTlv->offset ))->reqType)); + break; + case SigTlvResponseType: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVResponseType* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVResponseType*)(pFrm + pTlv->offset ))->resType)); + break; + case SigTlvSelectedRegistrar: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVSelectedRegistrar* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVSelectedRegistrar*)(pFrm + pTlv->offset ))->selected)); + break; + case SigTlvSelectedRegistrarConfigMethods: + status |= dot11fUnpackTlvCommonFunc2(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVSelectedRegistrarConfigMethods* )(pFrm + pTlv->offset ))->present), (tANI_U16*)&((( tDot11fTLVSelectedRegistrarConfigMethods*)(pFrm + pTlv->offset ))->methods)); + break; + case SigTlvSerialNumber: + status |= dot11fUnpackTlvSerialNumber(pCtx, pBufRemaining, len, ( tDot11fTLVSerialNumber* )(pFrm + pTlv->offset )); + break; + case SigTlvUUID_E: + status |= dot11fUnpackTlvUUID_E(pCtx, pBufRemaining, len, ( tDot11fTLVUUID_E* )(pFrm + pTlv->offset )); + break; + case SigTlvUUID_R: + status |= dot11fUnpackTlvUUID_R(pCtx, pBufRemaining, len, ( tDot11fTLVUUID_R* )(pFrm + pTlv->offset )); + break; + case SigTlvVendorExtension: + status |= dot11fUnpackTlvVendorExtension(pCtx, pBufRemaining, len, ( tDot11fTLVVendorExtension* )(pFrm + pTlv->offset )); + break; + case SigTlvVersion: + status |= dot11fUnpackTlvVersion(pCtx, pBufRemaining, len, ( tDot11fTLVVersion* )(pFrm + pTlv->offset )); + break; + case SigTlvWPSState: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVWPSState* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVWPSState*)(pFrm + pTlv->offset ))->state)); + break; + case SigTlvP2PInterface: + status |= dot11fUnpackTlvP2PInterface(pCtx, pBufRemaining, len, ( tDot11fTLVP2PInterface* )(pFrm + pTlv->offset )); + break; + case SigTlvP2PManageability: + status |= dot11fUnpackTlvCommonFunc(pCtx, pBufRemaining, len, (tANI_U8*)&((( tDot11fTLVP2PManageability* )(pFrm + pTlv->offset ))->present), (tANI_U8*)&((( tDot11fTLVP2PManageability*)(pFrm + pTlv->offset ))->manageability)); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR: I" + " don't know about the TLV signature %d-- thi" + "s is most likely a 'framesc' bug.\n"), + pTlv->sig); + FRAMES_DBG_BREAK(); + return DOT11F_INTERNAL_ERROR; + } // End switch on sig. + } // End if on length check. + + } + else + { + FRAMES_LOG2(pCtx, FRLOG3, FRFL("Skipping unknown TLV %d (" + "length %d)\n"), id, len); + FRAMES_DUMP(pCtx, FRLOG3, pBufRemaining - (pTlv->sType + pTlv->sLen), len); + status |= DOT11F_UNKNOWN_TLVS; + } + + // Advance to the next TLV + pBufRemaining += len; + + if (len > nBufRemaining) + { + FRAMES_LOG0(pCtx, FRLOGW, FRFL("This TLV extends past th" + "e buffer as it was defined to us. This could mean " + "a corrupt frame, or just an incorrect length parame" + "ter.\n")); + FRAMES_DBG_BREAK(); + status |= DOT11F_LAST_TLV_TOO_LONG; + goto MandatoryCheck; + } + + nBufRemaining -= len; + + } // End iteration over TLVs. + +MandatoryCheck: + pTlv = &TLVs[0]; + while (0xffff != pTlv->id) + { + if (pTlv->fMandatory) + { + pfFound = (tANI_U8*)(pFrm + pTlv->offset + + pTlv->presenceOffset); + if (!*pfFound) + { + FRAMES_LOG1(pCtx, FRLOGW, FRFL("ERROR: The mandatory " + "TLV %s wasn't seen.\n"), + pTlv->name); + FRAMES_DBG_BREAK(); + status |= DOT11F_MANDATORY_TLV_MISSING; + } + + } + ++pTlv; + } + + return status; +} /* End UnpacTlvkCore. */ +tANI_U32 dot11fGetPackedIETCLAS(tpAniSirGlobal pCtx, tDot11fIETCLAS *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + switch (pIe->classifier_type) + { + case 0: + *pnNeeded += 6; + *pnNeeded += 6; + *pnNeeded += 2; + break; + case 1: + *pnNeeded += 1; + switch (pIe->info.IpParams.version) + { + case 4: + *pnNeeded += 4; + *pnNeeded += 4; + *pnNeeded += 2; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + break; + case 6: + *pnNeeded += 16; + *pnNeeded += 16; + *pnNeeded += 2; + *pnNeeded += 2; + *pnNeeded += 3; + break; + } + break; + case 2: + *pnNeeded += 2; + break; + } + break; + } + return status; +} /* End dot11fGetPackedIETCLAS. */ + +tANI_U32 dot11fGetPackedIEWMMTCLAS(tpAniSirGlobal pCtx, tDot11fIEWMMTCLAS *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + switch (pIe->classifier_type) + { + case 0: + *pnNeeded += 6; + *pnNeeded += 6; + *pnNeeded += 2; + break; + case 1: + *pnNeeded += 1; + switch (pIe->info.IpParams.version) + { + case 4: + *pnNeeded += 4; + *pnNeeded += 4; + *pnNeeded += 2; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + break; + case 6: + *pnNeeded += 16; + *pnNeeded += 16; + *pnNeeded += 2; + *pnNeeded += 2; + *pnNeeded += 3; + break; + } + break; + case 2: + *pnNeeded += 2; + break; + } + break; + } + return status; +} /* End dot11fGetPackedIEWMMTCLAS. */ + +tANI_U32 dot11fGetPackedIEChannelSwitchWrapper(tpAniSirGlobal pCtx, tDot11fIEChannelSwitchWrapper *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pIe, pnNeeded, IES_ChannelSwitchWrapper); + break; + } + return status; +} /* End dot11fGetPackedIEChannelSwitchWrapper. */ + +tANI_U32 dot11fGetPackedIECountry(tpAniSirGlobal pCtx, tDot11fIECountry *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 3; + if ( pIe->num_triplets ) + { + *pnNeeded += ( pIe->num_triplets * 3 ); + } + else break; + break; + } + return status; +} /* End dot11fGetPackedIECountry. */ + +tANI_U32 dot11fGetPackedIEFTInfo(tpAniSirGlobal pCtx, tDot11fIEFTInfo *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 2; + *pnNeeded += 16; + *pnNeeded += 32; + *pnNeeded += 32; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pIe, pnNeeded, IES_FTInfo); + break; + } + return status; +} /* End dot11fGetPackedIEFTInfo. */ + +tANI_U32 dot11fGetPackedIEMeasurementReport(tpAniSirGlobal pCtx, tDot11fIEMeasurementReport *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + if ( pIe->type ) + { + switch (pIe->type) + { + case 0: + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + *pnNeeded += 1; + break; + case 1: + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + *pnNeeded += 1; + break; + case 2: + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + break; + case 5: + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 6; + *pnNeeded += 1; + *pnNeeded += 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pIe, pnNeeded, IES_reportBeacon); + break; + } + } + else break; + break; + } + return status; +} /* End dot11fGetPackedIEMeasurementReport. */ + +tANI_U32 dot11fGetPackedIEMeasurementRequest(tpAniSirGlobal pCtx, tDot11fIEMeasurementRequest *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + switch (pIe->measurement_type) + { + case 0: + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + break; + case 1: + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + break; + case 2: + *pnNeeded += 1; + *pnNeeded += 8; + *pnNeeded += 2; + break; + case 5: + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 2; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 6; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pIe, pnNeeded, IES_measurement_requestBeacon); + break; + } + break; + } + return status; +} /* End dot11fGetPackedIEMeasurementRequest. */ + +tANI_U32 dot11fGetPackedIENeighborReport(tpAniSirGlobal pCtx, tDot11fIENeighborReport *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 6; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pIe, pnNeeded, IES_NeighborReport); + break; + } + return status; +} /* End dot11fGetPackedIENeighborReport. */ + +tANI_U32 dot11fGetPackedIEP2PAssocReq(tpAniSirGlobal pCtx, tDot11fIEP2PAssocReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PAssocReq); + break; + } + return status; +} /* End dot11fGetPackedIEP2PAssocReq. */ + +tANI_U32 dot11fGetPackedIEP2PAssocRes(tpAniSirGlobal pCtx, tDot11fIEP2PAssocRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PAssocRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PAssocRes. */ + +tANI_U32 dot11fGetPackedIEP2PBeacon(tpAniSirGlobal pCtx, tDot11fIEP2PBeacon *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PBeacon); + break; + } + return status; +} /* End dot11fGetPackedIEP2PBeacon. */ + +tANI_U32 dot11fGetPackedIEP2PBeaconProbeRes(tpAniSirGlobal pCtx, tDot11fIEP2PBeaconProbeRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PBeaconProbeRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PBeaconProbeRes. */ + +tANI_U32 dot11fGetPackedIEP2PDeAuth(tpAniSirGlobal pCtx, tDot11fIEP2PDeAuth *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PDeAuth); + break; + } + return status; +} /* End dot11fGetPackedIEP2PDeAuth. */ + +tANI_U32 dot11fGetPackedIEP2PDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tDot11fIEP2PDeviceDiscoverabilityReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PDeviceDiscoverabilityReq); + break; + } + return status; +} /* End dot11fGetPackedIEP2PDeviceDiscoverabilityReq. */ + +tANI_U32 dot11fGetPackedIEP2PDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tDot11fIEP2PDeviceDiscoverabilityRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PDeviceDiscoverabilityRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PDeviceDiscoverabilityRes. */ + +tANI_U32 dot11fGetPackedIEP2PDisAssoc(tpAniSirGlobal pCtx, tDot11fIEP2PDisAssoc *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PDisAssoc); + break; + } + return status; +} /* End dot11fGetPackedIEP2PDisAssoc. */ + +tANI_U32 dot11fGetPackedIEP2PGONegCnf(tpAniSirGlobal pCtx, tDot11fIEP2PGONegCnf *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PGONegCnf); + break; + } + return status; +} /* End dot11fGetPackedIEP2PGONegCnf. */ + +tANI_U32 dot11fGetPackedIEP2PGONegReq(tpAniSirGlobal pCtx, tDot11fIEP2PGONegReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PGONegReq); + break; + } + return status; +} /* End dot11fGetPackedIEP2PGONegReq. */ + +tANI_U32 dot11fGetPackedIEP2PGONegRes(tpAniSirGlobal pCtx, tDot11fIEP2PGONegRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PGONegRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PGONegRes. */ + +tANI_U32 dot11fGetPackedIEP2PGONegWPS(tpAniSirGlobal pCtx, tDot11fIEP2PGONegWPS *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PGONegWPS); + break; + } + return status; +} /* End dot11fGetPackedIEP2PGONegWPS. */ + +tANI_U32 dot11fGetPackedIEP2PInvitationReq(tpAniSirGlobal pCtx, tDot11fIEP2PInvitationReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PInvitationReq); + break; + } + return status; +} /* End dot11fGetPackedIEP2PInvitationReq. */ + +tANI_U32 dot11fGetPackedIEP2PInvitationRes(tpAniSirGlobal pCtx, tDot11fIEP2PInvitationRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PInvitationRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PInvitationRes. */ + +tANI_U32 dot11fGetPackedIEP2PNoticeOfAbsence(tpAniSirGlobal pCtx, tDot11fIEP2PNoticeOfAbsence *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PNoticeOfAbsence); + break; + } + return status; +} /* End dot11fGetPackedIEP2PNoticeOfAbsence. */ + +tANI_U32 dot11fGetPackedIEP2PPresenceResponse(tpAniSirGlobal pCtx, tDot11fIEP2PPresenceResponse *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PPresenceResponse); + break; + } + return status; +} /* End dot11fGetPackedIEP2PPresenceResponse. */ + +tANI_U32 dot11fGetPackedIEP2PProbeReq(tpAniSirGlobal pCtx, tDot11fIEP2PProbeReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PProbeReq); + break; + } + return status; +} /* End dot11fGetPackedIEP2PProbeReq. */ + +tANI_U32 dot11fGetPackedIEP2PProbeRes(tpAniSirGlobal pCtx, tDot11fIEP2PProbeRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PProbeRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PProbeRes. */ + +tANI_U32 dot11fGetPackedIEP2PProvisionDiscoveryReq(tpAniSirGlobal pCtx, tDot11fIEP2PProvisionDiscoveryReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PProvisionDiscoveryReq); + break; + } + return status; +} /* End dot11fGetPackedIEP2PProvisionDiscoveryReq. */ + +tANI_U32 dot11fGetPackedIEP2PWSCProvisionDiscoveryRes(tpAniSirGlobal pCtx, tDot11fIEP2PWSCProvisionDiscoveryRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_P2PWSCProvisionDiscoveryRes); + break; + } + return status; +} /* End dot11fGetPackedIEP2PWSCProvisionDiscoveryRes. */ + +tANI_U32 dot11fGetPackedIERICDataDesc(tpAniSirGlobal pCtx, tDot11fIERICDataDesc *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pIe, pnNeeded, IES_RICDataDesc); + break; + } + return status; +} /* End dot11fGetPackedIERICDataDesc. */ + +tANI_U32 dot11fGetPackedIERSN(tpAniSirGlobal pCtx, tDot11fIERSN *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 2; + *pnNeeded += 4; + if ( pIe->pwise_cipher_suite_count ) + { + *pnNeeded += 2; + } + else break; + *pnNeeded += ( pIe->pwise_cipher_suite_count * 4 ); + if ( pIe->akm_suite_count ) + { + *pnNeeded += 2; + } + else break; + *pnNeeded += ( pIe->akm_suite_count * 4 ); + if ( pIe->RSN_Cap ) + { + *pnNeeded += 2; + } + else break; + if ( pIe->pmkid_count ) + { + *pnNeeded += 2; + } + else break; + *pnNeeded += ( pIe->pmkid_count * 16 ); + if ( pIe->gp_mgmt_cipher_suite ) + { + *pnNeeded += 4; + } + else break; + break; + } + return status; +} /* End dot11fGetPackedIERSN. */ + +tANI_U32 dot11fGetPackedIEWAPI(tpAniSirGlobal pCtx, tDot11fIEWAPI *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 2; + *pnNeeded += 2; + *pnNeeded += ( pIe->akm_suite_count * 4 ); + *pnNeeded += 2; + *pnNeeded += ( pIe->unicast_cipher_suite_count * 4 ); + *pnNeeded += 4; + *pnNeeded += 2; + if ( pIe->bkid_count ) + { + *pnNeeded += 2; + } + else break; + *pnNeeded += ( pIe->bkid_count * 16 ); + break; + } + return status; +} /* End dot11fGetPackedIEWAPI. */ + +tANI_U32 dot11fGetPackedIEWPA(tpAniSirGlobal pCtx, tDot11fIEWPA *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 2; + if ( pIe->multicast_cipher_present ) + { + *pnNeeded += 4; + } + else break; + if ( pIe->unicast_cipher_count ) + { + *pnNeeded += 2; + } + else break; + *pnNeeded += ( pIe->unicast_cipher_count * 4 ); + if ( pIe->auth_suite_count ) + { + *pnNeeded += 2; + } + else break; + *pnNeeded += ( pIe->auth_suite_count * 4 ); + if ( pIe->caps ) + { + *pnNeeded += 2; + } + else break; + break; + } + return status; +} /* End dot11fGetPackedIEWPA. */ + +tANI_U32 dot11fGetPackedIEWSC(tpAniSirGlobal pCtx, tDot11fIEWSC *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WSC); + break; + } + return status; +} /* End dot11fGetPackedIEWSC. */ + +tANI_U32 dot11fGetPackedIEWscAssocReq(tpAniSirGlobal pCtx, tDot11fIEWscAssocReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscAssocReq); + break; + } + return status; +} /* End dot11fGetPackedIEWscAssocReq. */ + +tANI_U32 dot11fGetPackedIEWscAssocRes(tpAniSirGlobal pCtx, tDot11fIEWscAssocRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscAssocRes); + break; + } + return status; +} /* End dot11fGetPackedIEWscAssocRes. */ + +tANI_U32 dot11fGetPackedIEWscBeacon(tpAniSirGlobal pCtx, tDot11fIEWscBeacon *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscBeacon); + break; + } + return status; +} /* End dot11fGetPackedIEWscBeacon. */ + +tANI_U32 dot11fGetPackedIEWscBeaconProbeRes(tpAniSirGlobal pCtx, tDot11fIEWscBeaconProbeRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscBeaconProbeRes); + break; + } + return status; +} /* End dot11fGetPackedIEWscBeaconProbeRes. */ + +tANI_U32 dot11fGetPackedIEWscProbeReq(tpAniSirGlobal pCtx, tDot11fIEWscProbeReq *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscProbeReq); + break; + } + return status; +} /* End dot11fGetPackedIEWscProbeReq. */ + +tANI_U32 dot11fGetPackedIEWscProbeRes(tpAniSirGlobal pCtx, tDot11fIEWscProbeRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscProbeRes); + break; + } + return status; +} /* End dot11fGetPackedIEWscProbeRes. */ + +tANI_U32 dot11fGetPackedIEWscReassocRes(tpAniSirGlobal pCtx, tDot11fIEWscReassocRes *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + status = GetPackedSizeTlvCore(pCtx,(tANI_U8*)pIe,pnNeeded,TLVS_WscReassocRes); + break; + } + return status; +} /* End dot11fGetPackedIEWscReassocRes. */ + +tANI_U32 dot11fGetPackedAddBAReqSize(tpAniSirGlobal pCtx, tDot11fAddBAReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 9; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_AddBAReq); + return status; +} /* End dot11fGetPackedAddBAReqSize. */ + +tANI_U32 dot11fGetPackedAddBARspSize(tpAniSirGlobal pCtx, tDot11fAddBARsp *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 9; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_AddBARsp); + return status; +} /* End dot11fGetPackedAddBARspSize. */ + +tANI_U32 dot11fGetPackedAddTSRequestSize(tpAniSirGlobal pCtx, tDot11fAddTSRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_AddTSRequest); + return status; +} /* End dot11fGetPackedAddTSRequestSize. */ + +tANI_U32 dot11fGetPackedAddTSResponseSize(tpAniSirGlobal pCtx, tDot11fAddTSResponse *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 5; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_AddTSResponse); + return status; +} /* End dot11fGetPackedAddTSResponseSize. */ + +tANI_U32 dot11fGetPackedAssocRequestSize(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_AssocRequest); + return status; +} /* End dot11fGetPackedAssocRequestSize. */ + +tANI_U32 dot11fGetPackedAssocResponseSize(tpAniSirGlobal pCtx, tDot11fAssocResponse *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 6; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_AssocResponse); + return status; +} /* End dot11fGetPackedAssocResponseSize. */ + +tANI_U32 dot11fGetPackedAuthenticationSize(tpAniSirGlobal pCtx, tDot11fAuthentication *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 6; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_Authentication); + return status; +} /* End dot11fGetPackedAuthenticationSize. */ + +tANI_U32 dot11fGetPackedBeaconSize(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 12; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_Beacon); + return status; +} /* End dot11fGetPackedBeaconSize. */ + +tANI_U32 dot11fGetPackedBeacon1Size(tpAniSirGlobal pCtx, tDot11fBeacon1 *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 12; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_Beacon1); + return status; +} /* End dot11fGetPackedBeacon1Size. */ + +tANI_U32 dot11fGetPackedBeacon2Size(tpAniSirGlobal pCtx, tDot11fBeacon2 *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 0; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_Beacon2); + return status; +} /* End dot11fGetPackedBeacon2Size. */ + +tANI_U32 dot11fGetPackedBeaconIEsSize(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 0; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_BeaconIEs); + return status; +} /* End dot11fGetPackedBeaconIEsSize. */ + +tANI_U32 dot11fGetPackedChannelSwitchSize(tpAniSirGlobal pCtx, tDot11fChannelSwitch *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 2; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ChannelSwitch); + return status; +} /* End dot11fGetPackedChannelSwitchSize. */ + +tANI_U32 dot11fGetPackedDeAuthSize(tpAniSirGlobal pCtx, tDot11fDeAuth *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 2; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_DeAuth); + return status; +} /* End dot11fGetPackedDeAuthSize. */ + +tANI_U32 dot11fGetPackedDelBAIndSize(tpAniSirGlobal pCtx, tDot11fDelBAInd *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 6; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_DelBAInd); + return status; +} /* End dot11fGetPackedDelBAIndSize. */ + +tANI_U32 dot11fGetPackedDelTSSize(tpAniSirGlobal pCtx, tDot11fDelTS *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 7; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_DelTS); + return status; +} /* End dot11fGetPackedDelTSSize. */ + +tANI_U32 dot11fGetPackedDeviceDiscoverabilityReqSize(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_DeviceDiscoverabilityReq); + return status; +} /* End dot11fGetPackedDeviceDiscoverabilityReqSize. */ + +tANI_U32 dot11fGetPackedDeviceDiscoverabilityResSize(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityRes *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_DeviceDiscoverabilityRes); + return status; +} /* End dot11fGetPackedDeviceDiscoverabilityResSize. */ + +tANI_U32 dot11fGetPackedDisassociationSize(tpAniSirGlobal pCtx, tDot11fDisassociation *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 2; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_Disassociation); + return status; +} /* End dot11fGetPackedDisassociationSize. */ + +tANI_U32 dot11fGetPackedGODiscoverabilityReqSize(tpAniSirGlobal pCtx, tDot11fGODiscoverabilityReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 7; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_GODiscoverabilityReq); + return status; +} /* End dot11fGetPackedGODiscoverabilityReqSize. */ + +tANI_U32 dot11fGetPackedGONegCnfSize(tpAniSirGlobal pCtx, tDot11fGONegCnf *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_GONegCnf); + return status; +} /* End dot11fGetPackedGONegCnfSize. */ + +tANI_U32 dot11fGetPackedGONegReqSize(tpAniSirGlobal pCtx, tDot11fGONegReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_GONegReq); + return status; +} /* End dot11fGetPackedGONegReqSize. */ + +tANI_U32 dot11fGetPackedGONegResSize(tpAniSirGlobal pCtx, tDot11fGONegRes *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_GONegRes); + return status; +} /* End dot11fGetPackedGONegResSize. */ + +tANI_U32 dot11fGetPackedHT2040BSSCoexistenceManagementActionFrameSize(tpAniSirGlobal pCtx, tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 2; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_HT2040BSSCoexistenceManagementActionFrame); + return status; +} /* End dot11fGetPackedHT2040BSSCoexistenceManagementActionFrameSize. */ + +tANI_U32 dot11fGetPackedInvitationReqSize(tpAniSirGlobal pCtx, tDot11fInvitationReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_InvitationReq); + return status; +} /* End dot11fGetPackedInvitationReqSize. */ + +tANI_U32 dot11fGetPackedInvitationResSize(tpAniSirGlobal pCtx, tDot11fInvitationRes *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_InvitationRes); + return status; +} /* End dot11fGetPackedInvitationResSize. */ + +tANI_U32 dot11fGetPackedLinkMeasurementReportSize(tpAniSirGlobal pCtx, tDot11fLinkMeasurementReport *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 11; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_LinkMeasurementReport); + return status; +} /* End dot11fGetPackedLinkMeasurementReportSize. */ + +tANI_U32 dot11fGetPackedLinkMeasurementRequestSize(tpAniSirGlobal pCtx, tDot11fLinkMeasurementRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 5; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_LinkMeasurementRequest); + return status; +} /* End dot11fGetPackedLinkMeasurementRequestSize. */ + +tANI_U32 dot11fGetPackedMeasurementReportSize(tpAniSirGlobal pCtx, tDot11fMeasurementReport *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_MeasurementReport); + return status; +} /* End dot11fGetPackedMeasurementReportSize. */ + +tANI_U32 dot11fGetPackedMeasurementRequestSize(tpAniSirGlobal pCtx, tDot11fMeasurementRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_MeasurementRequest); + return status; +} /* End dot11fGetPackedMeasurementRequestSize. */ + +tANI_U32 dot11fGetPackedNeighborReportRequestSize(tpAniSirGlobal pCtx, tDot11fNeighborReportRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_NeighborReportRequest); + return status; +} /* End dot11fGetPackedNeighborReportRequestSize. */ + +tANI_U32 dot11fGetPackedNeighborReportResponseSize(tpAniSirGlobal pCtx, tDot11fNeighborReportResponse *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_NeighborReportResponse); + return status; +} /* End dot11fGetPackedNeighborReportResponseSize. */ + +tANI_U32 dot11fGetPackedNoticeOfAbsSize(tpAniSirGlobal pCtx, tDot11fNoticeOfAbs *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 7; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_NoticeOfAbs); + return status; +} /* End dot11fGetPackedNoticeOfAbsSize. */ + +tANI_U32 dot11fGetPackedOperatingModeSize(tpAniSirGlobal pCtx, tDot11fOperatingMode *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_OperatingMode); + return status; +} /* End dot11fGetPackedOperatingModeSize. */ + +tANI_U32 dot11fGetPackedPresenceReqSize(tpAniSirGlobal pCtx, tDot11fPresenceReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 7; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_PresenceReq); + return status; +} /* End dot11fGetPackedPresenceReqSize. */ + +tANI_U32 dot11fGetPackedPresenceResSize(tpAniSirGlobal pCtx, tDot11fPresenceRes *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 7; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_PresenceRes); + return status; +} /* End dot11fGetPackedPresenceResSize. */ + +tANI_U32 dot11fGetPackedProbeRequestSize(tpAniSirGlobal pCtx, tDot11fProbeRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 0; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ProbeRequest); + return status; +} /* End dot11fGetPackedProbeRequestSize. */ + +tANI_U32 dot11fGetPackedProbeResponseSize(tpAniSirGlobal pCtx, tDot11fProbeResponse *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 12; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ProbeResponse); + return status; +} /* End dot11fGetPackedProbeResponseSize. */ + +tANI_U32 dot11fGetPackedProvisionDiscoveryReqSize(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ProvisionDiscoveryReq); + return status; +} /* End dot11fGetPackedProvisionDiscoveryReqSize. */ + +tANI_U32 dot11fGetPackedProvisionDiscoveryResSize(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryRes *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 8; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ProvisionDiscoveryRes); + return status; +} /* End dot11fGetPackedProvisionDiscoveryResSize. */ + +tANI_U32 dot11fGetPackedQosMapConfigureSize(tpAniSirGlobal pCtx, tDot11fQosMapConfigure *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 2; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_QosMapConfigure); + return status; +} /* End dot11fGetPackedQosMapConfigureSize. */ + +tANI_U32 dot11fGetPackedRadioMeasurementReportSize(tpAniSirGlobal pCtx, tDot11fRadioMeasurementReport *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_RadioMeasurementReport); + return status; +} /* End dot11fGetPackedRadioMeasurementReportSize. */ + +tANI_U32 dot11fGetPackedRadioMeasurementRequestSize(tpAniSirGlobal pCtx, tDot11fRadioMeasurementRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 5; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_RadioMeasurementRequest); + return status; +} /* End dot11fGetPackedRadioMeasurementRequestSize. */ + +tANI_U32 dot11fGetPackedReAssocRequestSize(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 10; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ReAssocRequest); + return status; +} /* End dot11fGetPackedReAssocRequestSize. */ + +tANI_U32 dot11fGetPackedReAssocResponseSize(tpAniSirGlobal pCtx, tDot11fReAssocResponse *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 6; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ReAssocResponse); + return status; +} /* End dot11fGetPackedReAssocResponseSize. */ + +tANI_U32 dot11fGetPackedSMPowerSaveSize(tpAniSirGlobal pCtx, tDot11fSMPowerSave *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_SMPowerSave); + return status; +} /* End dot11fGetPackedSMPowerSaveSize. */ + +tANI_U32 dot11fGetPackedSaQueryReqSize(tpAniSirGlobal pCtx, tDot11fSaQueryReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_SaQueryReq); + return status; +} /* End dot11fGetPackedSaQueryReqSize. */ + +tANI_U32 dot11fGetPackedSaQueryRspSize(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_SaQueryRsp); + return status; +} /* End dot11fGetPackedSaQueryRspSize. */ + +tANI_U32 dot11fGetPackedTDLSDisReqSize(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSDisReq); + return status; +} /* End dot11fGetPackedTDLSDisReqSize. */ + +tANI_U32 dot11fGetPackedTDLSDisRspSize(tpAniSirGlobal pCtx, tDot11fTDLSDisRsp *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 5; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSDisRsp); + return status; +} /* End dot11fGetPackedTDLSDisRspSize. */ + +tANI_U32 dot11fGetPackedTDLSPeerTrafficIndSize(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficInd *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSPeerTrafficInd); + return status; +} /* End dot11fGetPackedTDLSPeerTrafficIndSize. */ + +tANI_U32 dot11fGetPackedTDLSPeerTrafficRspSize(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficRsp *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSPeerTrafficRsp); + return status; +} /* End dot11fGetPackedTDLSPeerTrafficRspSize. */ + +tANI_U32 dot11fGetPackedTDLSSetupCnfSize(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 5; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSSetupCnf); + return status; +} /* End dot11fGetPackedTDLSSetupCnfSize. */ + +tANI_U32 dot11fGetPackedTDLSSetupReqSize(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 5; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSSetupReq); + return status; +} /* End dot11fGetPackedTDLSSetupReqSize. */ + +tANI_U32 dot11fGetPackedTDLSSetupRspSize(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 7; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSSetupRsp); + return status; +} /* End dot11fGetPackedTDLSSetupRspSize. */ + +tANI_U32 dot11fGetPackedTDLSTeardownSize(tpAniSirGlobal pCtx, tDot11fTDLSTeardown *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TDLSTeardown); + return status; +} /* End dot11fGetPackedTDLSTeardownSize. */ + +tANI_U32 dot11fGetPackedTPCReportSize(tpAniSirGlobal pCtx, tDot11fTPCReport *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TPCReport); + return status; +} /* End dot11fGetPackedTPCReportSize. */ + +tANI_U32 dot11fGetPackedTPCRequestSize(tpAniSirGlobal pCtx, tDot11fTPCRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 3; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TPCRequest); + return status; +} /* End dot11fGetPackedTPCRequestSize. */ + +tANI_U32 dot11fGetPackedTimingAdvertisementFrameSize(tpAniSirGlobal pCtx, tDot11fTimingAdvertisementFrame *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 10; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_TimingAdvertisementFrame); + return status; +} /* End dot11fGetPackedTimingAdvertisementFrameSize. */ + +tANI_U32 dot11fGetPackedVHTGidManagementActionFrameSize(tpAniSirGlobal pCtx, tDot11fVHTGidManagementActionFrame *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 26; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_VHTGidManagementActionFrame); + return status; +} /* End dot11fGetPackedVHTGidManagementActionFrameSize. */ + +tANI_U32 dot11fGetPackedWMMAddTSRequestSize(tpAniSirGlobal pCtx, tDot11fWMMAddTSRequest *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_WMMAddTSRequest); + return status; +} /* End dot11fGetPackedWMMAddTSRequestSize. */ + +tANI_U32 dot11fGetPackedWMMAddTSResponseSize(tpAniSirGlobal pCtx, tDot11fWMMAddTSResponse *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_WMMAddTSResponse); + return status; +} /* End dot11fGetPackedWMMAddTSResponseSize. */ + +tANI_U32 dot11fGetPackedWMMDelTSSize(tpAniSirGlobal pCtx, tDot11fWMMDelTS *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 4; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_WMMDelTS); + return status; +} /* End dot11fGetPackedWMMDelTSSize. */ + +tANI_U32 dot11fGetPackedext_channel_switch_action_frameSize(tpAniSirGlobal pCtx, tDot11fext_channel_switch_action_frame *pFrm, tANI_U32 *pnNeeded) +{ + tANI_U32 status = 0; + *pnNeeded = 6; + status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_ext_channel_switch_action_frame); + return status; +} /* End dot11fGetPackedext_channel_switch_action_frameSize. */ + +static tANI_U32 GetPackedSizeCore(tpAniSirGlobal pCtx, + tANI_U8 *pFrm, + tANI_U32 *pnNeeded, + const tIEDefn IEs[]) +{ + const tIEDefn *pIe; + tANI_U16 i, n; + tANI_U32 status; + tFRAMES_BOOL *pfFound; + tANI_U32 countOffset = 0; + tANI_U32 byteCount = 0; + tANI_U8 pIePresent = 0; + tANI_U32 offset = 0; + + status = DOT11F_PARSE_SUCCESS; + + (void)pCtx; /* Shutup the compiler if we have no FFs nor IEs... */ + i=0; n=0; + pIe = &( IEs[0] ); + while ( 0xff != pIe->eid ) + { + pfFound = (tFRAMES_BOOL*)(pFrm + pIe->offset + + pIe->presenceOffset); + if ( *pfFound ) + { + countOffset = ((0 == pIe->arraybound) ? 1 : (*( tANI_U16* )(pFrm + pIe->countOffset)) ); + for (i = 0U; i < countOffset; ++i) + { + *pnNeeded += 2U + pIe->noui; + byteCount = 0; + switch (pIe->sig) + { + case SigIeCondensedCountryStr: + offset = sizeof(tDot11fIECondensedCountryStr); + byteCount = 2; + pIePresent = ( (tDot11fIECondensedCountryStr* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeGTK: + offset = sizeof(tDot11fIEGTK); + byteCount = ((tDot11fIEGTK* )(pFrm + pIe->offset + sizeof(tDot11fIEGTK) * i ))->num_key + 11; + pIePresent = ( (tDot11fIEGTK* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeIGTK: + offset = sizeof(tDot11fIEIGTK); + byteCount = 33; + pIePresent = ( (tDot11fIEIGTK* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeR0KH_ID: + offset = sizeof(tDot11fIER0KH_ID); + byteCount = ((tDot11fIER0KH_ID* )(pFrm + pIe->offset + sizeof(tDot11fIER0KH_ID) * i ))->num_PMK_R0_ID; + pIePresent = ( (tDot11fIER0KH_ID* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeR1KH_ID: + offset = sizeof(tDot11fIER1KH_ID); + byteCount = 6; + pIePresent = ( (tDot11fIER1KH_ID* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTSFInfo: + offset = sizeof(tDot11fIETSFInfo); + byteCount = 4; + pIePresent = ( (tDot11fIETSFInfo* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeAPChannelReport: + offset = sizeof(tDot11fIEAPChannelReport); + byteCount = ((tDot11fIEAPChannelReport* )(pFrm + pIe->offset + sizeof(tDot11fIEAPChannelReport) * i ))->num_channelList + 1; + pIePresent = ( (tDot11fIEAPChannelReport* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeBcnReportingDetail: + offset = sizeof(tDot11fIEBcnReportingDetail); + byteCount = 1; + pIePresent = ( (tDot11fIEBcnReportingDetail* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeBeaconReportFrmBody: + offset = sizeof(tDot11fIEBeaconReportFrmBody); + byteCount = ((tDot11fIEBeaconReportFrmBody* )(pFrm + pIe->offset + sizeof(tDot11fIEBeaconReportFrmBody) * i ))->num_reportedFields; + pIePresent = ( (tDot11fIEBeaconReportFrmBody* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeBeaconReporting: + offset = sizeof(tDot11fIEBeaconReporting); + byteCount = 2; + pIePresent = ( (tDot11fIEBeaconReporting* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeMeasurementPilot: + offset = sizeof(tDot11fIEMeasurementPilot); + byteCount = ((tDot11fIEMeasurementPilot* )(pFrm + pIe->offset + sizeof(tDot11fIEMeasurementPilot) * i ))->num_vendorSpecific + 1; + pIePresent = ( (tDot11fIEMeasurementPilot* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeMultiBssid: + offset = sizeof(tDot11fIEMultiBssid); + byteCount = ((tDot11fIEMultiBssid* )(pFrm + pIe->offset + sizeof(tDot11fIEMultiBssid) * i ))->num_vendorSpecific + 1; + pIePresent = ( (tDot11fIEMultiBssid* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRICData: + offset = sizeof(tDot11fIERICData); + byteCount = 4; + pIePresent = ( (tDot11fIERICData* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRICDescriptor: + offset = sizeof(tDot11fIERICDescriptor); + byteCount = ((tDot11fIERICDescriptor* )(pFrm + pIe->offset + sizeof(tDot11fIERICDescriptor) * i ))->num_variableData + 1; + pIePresent = ( (tDot11fIERICDescriptor* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRRMEnabledCap: + offset = sizeof(tDot11fIERRMEnabledCap); + byteCount = 5; + pIePresent = ( (tDot11fIERRMEnabledCap* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRequestedInfo: + offset = sizeof(tDot11fIERequestedInfo); + byteCount = ((tDot11fIERequestedInfo* )(pFrm + pIe->offset + sizeof(tDot11fIERequestedInfo) * i ))->num_requested_eids; + pIePresent = ( (tDot11fIERequestedInfo* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeSSID: + offset = sizeof(tDot11fIESSID); + byteCount = ((tDot11fIESSID* )(pFrm + pIe->offset + sizeof(tDot11fIESSID) * i ))->num_ssid; + pIePresent = ( (tDot11fIESSID* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeSchedule: + offset = sizeof(tDot11fIESchedule); + byteCount = 14; + pIePresent = ( (tDot11fIESchedule* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTCLAS: + offset = sizeof(tDot11fIETCLAS); + status |= dot11fGetPackedIETCLAS(pCtx, ( tDot11fIETCLAS* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeTCLASSPROC: + offset = sizeof(tDot11fIETCLASSPROC); + byteCount = 1; + pIePresent = ( (tDot11fIETCLASSPROC* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTSDelay: + offset = sizeof(tDot11fIETSDelay); + byteCount = 4; + pIePresent = ( (tDot11fIETSDelay* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTSPEC: + offset = sizeof(tDot11fIETSPEC); + byteCount = 55; + pIePresent = ( (tDot11fIETSPEC* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMSchedule: + offset = sizeof(tDot11fIEWMMSchedule); + byteCount = 15; + pIePresent = ( (tDot11fIEWMMSchedule* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMTCLAS: + offset = sizeof(tDot11fIEWMMTCLAS); + status |= dot11fGetPackedIEWMMTCLAS(pCtx, ( tDot11fIEWMMTCLAS* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWMMTCLASPROC: + offset = sizeof(tDot11fIEWMMTCLASPROC); + byteCount = 2; + pIePresent = ( (tDot11fIEWMMTCLASPROC* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMTSDelay: + offset = sizeof(tDot11fIEWMMTSDelay); + byteCount = 5; + pIePresent = ( (tDot11fIEWMMTSDelay* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMTSPEC: + offset = sizeof(tDot11fIEWMMTSPEC); + byteCount = 56; + pIePresent = ( (tDot11fIEWMMTSPEC* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWiderBWChanSwitchAnn: + offset = sizeof(tDot11fIEWiderBWChanSwitchAnn); + byteCount = 3; + pIePresent = ( (tDot11fIEWiderBWChanSwitchAnn* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeAID: + offset = sizeof(tDot11fIEAID); + byteCount = 2; + pIePresent = ( (tDot11fIEAID* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeCFParams: + offset = sizeof(tDot11fIECFParams); + byteCount = 6; + pIePresent = ( (tDot11fIECFParams* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeChallengeText: + offset = sizeof(tDot11fIEChallengeText); + byteCount = ((tDot11fIEChallengeText* )(pFrm + pIe->offset + sizeof(tDot11fIEChallengeText) * i ))->num_text; + pIePresent = ( (tDot11fIEChallengeText* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeChanSwitchAnn: + offset = sizeof(tDot11fIEChanSwitchAnn); + byteCount = 3; + pIePresent = ( (tDot11fIEChanSwitchAnn* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeChannelSwitchWrapper: + offset = sizeof(tDot11fIEChannelSwitchWrapper); + status |= dot11fGetPackedIEChannelSwitchWrapper(pCtx, ( tDot11fIEChannelSwitchWrapper* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeCountry: + offset = sizeof(tDot11fIECountry); + status |= dot11fGetPackedIECountry(pCtx, ( tDot11fIECountry* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeDSParams: + offset = sizeof(tDot11fIEDSParams); + byteCount = 1; + pIePresent = ( (tDot11fIEDSParams* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeEDCAParamSet: + offset = sizeof(tDot11fIEEDCAParamSet); + byteCount = 18; + pIePresent = ( (tDot11fIEEDCAParamSet* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeERPInfo: + offset = sizeof(tDot11fIEERPInfo); + byteCount = 1; + pIePresent = ( (tDot11fIEERPInfo* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeESECckmOpaque: + offset = sizeof(tDot11fIEESECckmOpaque); + byteCount = ((tDot11fIEESECckmOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEESECckmOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIEESECckmOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeESERadMgmtCap: + offset = sizeof(tDot11fIEESERadMgmtCap); + byteCount = 2; + pIePresent = ( (tDot11fIEESERadMgmtCap* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeESETrafStrmMet: + offset = sizeof(tDot11fIEESETrafStrmMet); + byteCount = 4; + pIePresent = ( (tDot11fIEESETrafStrmMet* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeESETrafStrmRateSet: + offset = sizeof(tDot11fIEESETrafStrmRateSet); + byteCount = ((tDot11fIEESETrafStrmRateSet* )(pFrm + pIe->offset + sizeof(tDot11fIEESETrafStrmRateSet) * i ))->num_tsrates + 1; + pIePresent = ( (tDot11fIEESETrafStrmRateSet* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeESETxmitPower: + offset = sizeof(tDot11fIEESETxmitPower); + byteCount = 2; + pIePresent = ( (tDot11fIEESETxmitPower* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeESEVersion: + offset = sizeof(tDot11fIEESEVersion); + byteCount = 1; + pIePresent = ( (tDot11fIEESEVersion* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeExtCap: + offset = sizeof(tDot11fIEExtCap); + byteCount = ((tDot11fIEExtCap* )(pFrm + pIe->offset + sizeof(tDot11fIEExtCap) * i ))->num_bytes; + pIePresent = ( (tDot11fIEExtCap* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeExtSuppRates: + offset = sizeof(tDot11fIEExtSuppRates); + byteCount = ((tDot11fIEExtSuppRates* )(pFrm + pIe->offset + sizeof(tDot11fIEExtSuppRates) * i ))->num_rates; + pIePresent = ( (tDot11fIEExtSuppRates* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeFHParamSet: + offset = sizeof(tDot11fIEFHParamSet); + byteCount = 5; + pIePresent = ( (tDot11fIEFHParamSet* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeFHParams: + offset = sizeof(tDot11fIEFHParams); + byteCount = 2; + pIePresent = ( (tDot11fIEFHParams* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeFHPattTable: + offset = sizeof(tDot11fIEFHPattTable); + byteCount = ((tDot11fIEFHPattTable* )(pFrm + pIe->offset + sizeof(tDot11fIEFHPattTable) * i ))->num_randtable + 4; + pIePresent = ( (tDot11fIEFHPattTable* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeFTInfo: + offset = sizeof(tDot11fIEFTInfo); + status |= dot11fGetPackedIEFTInfo(pCtx, ( tDot11fIEFTInfo* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeHT2040BSSCoexistence: + offset = sizeof(tDot11fIEHT2040BSSCoexistence); + byteCount = 1; + pIePresent = ( (tDot11fIEHT2040BSSCoexistence* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeHT2040BSSIntolerantReport: + offset = sizeof(tDot11fIEHT2040BSSIntolerantReport); + byteCount = ((tDot11fIEHT2040BSSIntolerantReport* )(pFrm + pIe->offset + sizeof(tDot11fIEHT2040BSSIntolerantReport) * i ))->num_channelList + 1; + pIePresent = ( (tDot11fIEHT2040BSSIntolerantReport* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeHTCaps: + offset = sizeof(tDot11fIEHTCaps); + byteCount = ((tDot11fIEHTCaps* )(pFrm + pIe->offset + sizeof(tDot11fIEHTCaps) * i ))->num_rsvd + 26; + pIePresent = ( (tDot11fIEHTCaps* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeHTInfo: + offset = sizeof(tDot11fIEHTInfo); + byteCount = ((tDot11fIEHTInfo* )(pFrm + pIe->offset + sizeof(tDot11fIEHTInfo) * i ))->num_rsvd + 22; + pIePresent = ( (tDot11fIEHTInfo* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeIBSSParams: + offset = sizeof(tDot11fIEIBSSParams); + byteCount = 2; + pIePresent = ( (tDot11fIEIBSSParams* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeLinkIdentifier: + offset = sizeof(tDot11fIELinkIdentifier); + byteCount = 18; + pIePresent = ( (tDot11fIELinkIdentifier* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeMeasurementReport: + offset = sizeof(tDot11fIEMeasurementReport); + status |= dot11fGetPackedIEMeasurementReport(pCtx, ( tDot11fIEMeasurementReport* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeMeasurementRequest: + offset = sizeof(tDot11fIEMeasurementRequest); + status |= dot11fGetPackedIEMeasurementRequest(pCtx, ( tDot11fIEMeasurementRequest* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeMobilityDomain: + offset = sizeof(tDot11fIEMobilityDomain); + byteCount = 3; + pIePresent = ( (tDot11fIEMobilityDomain* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeNeighborReport: + offset = sizeof(tDot11fIENeighborReport); + status |= dot11fGetPackedIENeighborReport(pCtx, ( tDot11fIENeighborReport* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeOBSSScanParameters: + offset = sizeof(tDot11fIEOBSSScanParameters); + byteCount = 14; + pIePresent = ( (tDot11fIEOBSSScanParameters* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeOperatingMode: + offset = sizeof(tDot11fIEOperatingMode); + byteCount = 1; + pIePresent = ( (tDot11fIEOperatingMode* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeP2PAssocReq: + offset = sizeof(tDot11fIEP2PAssocReq); + status |= dot11fGetPackedIEP2PAssocReq(pCtx, ( tDot11fIEP2PAssocReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PAssocRes: + offset = sizeof(tDot11fIEP2PAssocRes); + status |= dot11fGetPackedIEP2PAssocRes(pCtx, ( tDot11fIEP2PAssocRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PBeacon: + offset = sizeof(tDot11fIEP2PBeacon); + status |= dot11fGetPackedIEP2PBeacon(pCtx, ( tDot11fIEP2PBeacon* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PBeaconProbeRes: + offset = sizeof(tDot11fIEP2PBeaconProbeRes); + status |= dot11fGetPackedIEP2PBeaconProbeRes(pCtx, ( tDot11fIEP2PBeaconProbeRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PDeAuth: + offset = sizeof(tDot11fIEP2PDeAuth); + status |= dot11fGetPackedIEP2PDeAuth(pCtx, ( tDot11fIEP2PDeAuth* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PDeviceDiscoverabilityReq: + offset = sizeof(tDot11fIEP2PDeviceDiscoverabilityReq); + status |= dot11fGetPackedIEP2PDeviceDiscoverabilityReq(pCtx, ( tDot11fIEP2PDeviceDiscoverabilityReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PDeviceDiscoverabilityRes: + offset = sizeof(tDot11fIEP2PDeviceDiscoverabilityRes); + status |= dot11fGetPackedIEP2PDeviceDiscoverabilityRes(pCtx, ( tDot11fIEP2PDeviceDiscoverabilityRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PDisAssoc: + offset = sizeof(tDot11fIEP2PDisAssoc); + status |= dot11fGetPackedIEP2PDisAssoc(pCtx, ( tDot11fIEP2PDisAssoc* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PGONegCnf: + offset = sizeof(tDot11fIEP2PGONegCnf); + status |= dot11fGetPackedIEP2PGONegCnf(pCtx, ( tDot11fIEP2PGONegCnf* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PGONegReq: + offset = sizeof(tDot11fIEP2PGONegReq); + status |= dot11fGetPackedIEP2PGONegReq(pCtx, ( tDot11fIEP2PGONegReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PGONegRes: + offset = sizeof(tDot11fIEP2PGONegRes); + status |= dot11fGetPackedIEP2PGONegRes(pCtx, ( tDot11fIEP2PGONegRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PGONegWPS: + offset = sizeof(tDot11fIEP2PGONegWPS); + status |= dot11fGetPackedIEP2PGONegWPS(pCtx, ( tDot11fIEP2PGONegWPS* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PIEOpaque: + offset = sizeof(tDot11fIEP2PIEOpaque); + byteCount = ((tDot11fIEP2PIEOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEP2PIEOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIEP2PIEOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeP2PInvitationReq: + offset = sizeof(tDot11fIEP2PInvitationReq); + status |= dot11fGetPackedIEP2PInvitationReq(pCtx, ( tDot11fIEP2PInvitationReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PInvitationRes: + offset = sizeof(tDot11fIEP2PInvitationRes); + status |= dot11fGetPackedIEP2PInvitationRes(pCtx, ( tDot11fIEP2PInvitationRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PNoticeOfAbsence: + offset = sizeof(tDot11fIEP2PNoticeOfAbsence); + status |= dot11fGetPackedIEP2PNoticeOfAbsence(pCtx, ( tDot11fIEP2PNoticeOfAbsence* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PPresenceResponse: + offset = sizeof(tDot11fIEP2PPresenceResponse); + status |= dot11fGetPackedIEP2PPresenceResponse(pCtx, ( tDot11fIEP2PPresenceResponse* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PProbeReq: + offset = sizeof(tDot11fIEP2PProbeReq); + status |= dot11fGetPackedIEP2PProbeReq(pCtx, ( tDot11fIEP2PProbeReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PProbeRes: + offset = sizeof(tDot11fIEP2PProbeRes); + status |= dot11fGetPackedIEP2PProbeRes(pCtx, ( tDot11fIEP2PProbeRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PProvisionDiscoveryReq: + offset = sizeof(tDot11fIEP2PProvisionDiscoveryReq); + status |= dot11fGetPackedIEP2PProvisionDiscoveryReq(pCtx, ( tDot11fIEP2PProvisionDiscoveryReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeP2PWSCProvisionDiscoveryRes: + offset = sizeof(tDot11fIEP2PWSCProvisionDiscoveryRes); + status |= dot11fGetPackedIEP2PWSCProvisionDiscoveryRes(pCtx, ( tDot11fIEP2PWSCProvisionDiscoveryRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIePTIControl: + offset = sizeof(tDot11fIEPTIControl); + byteCount = 3; + pIePresent = ( (tDot11fIEPTIControl* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIePUBufferStatus: + offset = sizeof(tDot11fIEPUBufferStatus); + byteCount = 1; + pIePresent = ( (tDot11fIEPUBufferStatus* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIePowerCaps: + offset = sizeof(tDot11fIEPowerCaps); + byteCount = 2; + pIePresent = ( (tDot11fIEPowerCaps* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIePowerConstraints: + offset = sizeof(tDot11fIEPowerConstraints); + byteCount = 1; + pIePresent = ( (tDot11fIEPowerConstraints* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeQBSSLoad: + offset = sizeof(tDot11fIEQBSSLoad); + byteCount = 5; + pIePresent = ( (tDot11fIEQBSSLoad* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeQComVendorIE: + offset = sizeof(tDot11fIEQComVendorIE); + byteCount = 2; + pIePresent = ( (tDot11fIEQComVendorIE* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeQOSCapsAp: + offset = sizeof(tDot11fIEQOSCapsAp); + byteCount = 1; + pIePresent = ( (tDot11fIEQOSCapsAp* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeQOSCapsStation: + offset = sizeof(tDot11fIEQOSCapsStation); + byteCount = 1; + pIePresent = ( (tDot11fIEQOSCapsStation* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeQosMapSet: + offset = sizeof(tDot11fIEQosMapSet); + byteCount = ((tDot11fIEQosMapSet* )(pFrm + pIe->offset + sizeof(tDot11fIEQosMapSet) * i ))->num_dscp_exceptions; + pIePresent = ( (tDot11fIEQosMapSet* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeQuiet: + offset = sizeof(tDot11fIEQuiet); + byteCount = 6; + pIePresent = ( (tDot11fIEQuiet* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRCPIIE: + offset = sizeof(tDot11fIERCPIIE); + byteCount = 1; + pIePresent = ( (tDot11fIERCPIIE* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRICDataDesc: + offset = sizeof(tDot11fIERICDataDesc); + pnNeeded -= 2 ; //Subtract the length and Oui as this is our container IE to group Ies and it doesnt have its own length and OUI. + status |= dot11fGetPackedIERICDataDesc(pCtx, ( tDot11fIERICDataDesc* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeRSN: + offset = sizeof(tDot11fIERSN); + status |= dot11fGetPackedIERSN(pCtx, ( tDot11fIERSN* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeRSNIIE: + offset = sizeof(tDot11fIERSNIIE); + byteCount = 1; + pIePresent = ( (tDot11fIERSNIIE* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeRSNOpaque: + offset = sizeof(tDot11fIERSNOpaque); + byteCount = ((tDot11fIERSNOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIERSNOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIERSNOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeSuppChannels: + offset = sizeof(tDot11fIESuppChannels); + byteCount = ((tDot11fIESuppChannels* )(pFrm + pIe->offset + sizeof(tDot11fIESuppChannels) * i ))->num_bands * 2; + pIePresent = ( (tDot11fIESuppChannels* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeSuppOperatingClasses: + offset = sizeof(tDot11fIESuppOperatingClasses); + byteCount = ((tDot11fIESuppOperatingClasses* )(pFrm + pIe->offset + sizeof(tDot11fIESuppOperatingClasses) * i ))->num_classes; + pIePresent = ( (tDot11fIESuppOperatingClasses* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeSuppRates: + offset = sizeof(tDot11fIESuppRates); + byteCount = ((tDot11fIESuppRates* )(pFrm + pIe->offset + sizeof(tDot11fIESuppRates) * i ))->num_rates; + pIePresent = ( (tDot11fIESuppRates* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTIM: + offset = sizeof(tDot11fIETIM); + byteCount = ((tDot11fIETIM* )(pFrm + pIe->offset + sizeof(tDot11fIETIM) * i ))->num_vbmp + 3; + pIePresent = ( (tDot11fIETIM* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTPCReport: + offset = sizeof(tDot11fIETPCReport); + byteCount = 2; + pIePresent = ( (tDot11fIETPCReport* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTPCRequest: + offset = sizeof(tDot11fIETPCRequest); + byteCount = 0; + pIePresent = ( (tDot11fIETPCRequest* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTimeAdvertisement: + offset = sizeof(tDot11fIETimeAdvertisement); + byteCount = 16; + pIePresent = ( (tDot11fIETimeAdvertisement* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeTimeoutInterval: + offset = sizeof(tDot11fIETimeoutInterval); + byteCount = 5; + pIePresent = ( (tDot11fIETimeoutInterval* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeVHTCaps: + offset = sizeof(tDot11fIEVHTCaps); + byteCount = 12; + pIePresent = ( (tDot11fIEVHTCaps* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeVHTExtBssLoad: + offset = sizeof(tDot11fIEVHTExtBssLoad); + byteCount = 5; + pIePresent = ( (tDot11fIEVHTExtBssLoad* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeVHTOperation: + offset = sizeof(tDot11fIEVHTOperation); + byteCount = 5; + pIePresent = ( (tDot11fIEVHTOperation* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeVendor1IE: + offset = sizeof(tDot11fIEVendor1IE); + byteCount = 0; + pIePresent = ( (tDot11fIEVendor1IE* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeVendor2IE: + offset = sizeof(tDot11fIEVendor2IE); + byteCount = 0; + pIePresent = ( (tDot11fIEVendor2IE* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeVendor3IE: + offset = sizeof(tDot11fIEVendor3IE); + byteCount = 0; + pIePresent = ( (tDot11fIEVendor3IE* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWAPI: + offset = sizeof(tDot11fIEWAPI); + status |= dot11fGetPackedIEWAPI(pCtx, ( tDot11fIEWAPI* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWAPIOpaque: + offset = sizeof(tDot11fIEWAPIOpaque); + byteCount = ((tDot11fIEWAPIOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWAPIOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIEWAPIOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWFATPC: + offset = sizeof(tDot11fIEWFATPC); + byteCount = 2; + pIePresent = ( (tDot11fIEWFATPC* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWFDIEOpaque: + offset = sizeof(tDot11fIEWFDIEOpaque); + byteCount = ((tDot11fIEWFDIEOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWFDIEOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIEWFDIEOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMCaps: + offset = sizeof(tDot11fIEWMMCaps); + byteCount = 2; + pIePresent = ( (tDot11fIEWMMCaps* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMInfoAp: + offset = sizeof(tDot11fIEWMMInfoAp); + byteCount = 2; + pIePresent = ( (tDot11fIEWMMInfoAp* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMInfoStation: + offset = sizeof(tDot11fIEWMMInfoStation); + byteCount = 2; + pIePresent = ( (tDot11fIEWMMInfoStation* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWMMParams: + offset = sizeof(tDot11fIEWMMParams); + byteCount = 19; + pIePresent = ( (tDot11fIEWMMParams* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWPA: + offset = sizeof(tDot11fIEWPA); + status |= dot11fGetPackedIEWPA(pCtx, ( tDot11fIEWPA* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWPAOpaque: + offset = sizeof(tDot11fIEWPAOpaque); + byteCount = ((tDot11fIEWPAOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWPAOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIEWPAOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWSC: + offset = sizeof(tDot11fIEWSC); + status |= dot11fGetPackedIEWSC(pCtx, ( tDot11fIEWSC* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscAssocReq: + offset = sizeof(tDot11fIEWscAssocReq); + status |= dot11fGetPackedIEWscAssocReq(pCtx, ( tDot11fIEWscAssocReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscAssocRes: + offset = sizeof(tDot11fIEWscAssocRes); + status |= dot11fGetPackedIEWscAssocRes(pCtx, ( tDot11fIEWscAssocRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscBeacon: + offset = sizeof(tDot11fIEWscBeacon); + status |= dot11fGetPackedIEWscBeacon(pCtx, ( tDot11fIEWscBeacon* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscBeaconProbeRes: + offset = sizeof(tDot11fIEWscBeaconProbeRes); + status |= dot11fGetPackedIEWscBeaconProbeRes(pCtx, ( tDot11fIEWscBeaconProbeRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscIEOpaque: + offset = sizeof(tDot11fIEWscIEOpaque); + byteCount = ((tDot11fIEWscIEOpaque* )(pFrm + pIe->offset + sizeof(tDot11fIEWscIEOpaque) * i ))->num_data; + pIePresent = ( (tDot11fIEWscIEOpaque* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIeWscProbeReq: + offset = sizeof(tDot11fIEWscProbeReq); + status |= dot11fGetPackedIEWscProbeReq(pCtx, ( tDot11fIEWscProbeReq* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscProbeRes: + offset = sizeof(tDot11fIEWscProbeRes); + status |= dot11fGetPackedIEWscProbeRes(pCtx, ( tDot11fIEWscProbeRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeWscReassocRes: + offset = sizeof(tDot11fIEWscReassocRes); + status |= dot11fGetPackedIEWscReassocRes(pCtx, ( tDot11fIEWscReassocRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; + case SigIeext_chan_switch_ann: + offset = sizeof(tDot11fIEext_chan_switch_ann); + byteCount = 4; + pIePresent = ( (tDot11fIEext_chan_switch_ann* )(pFrm + pIe->offset + offset * i ))->present; + break; + case SigIesec_chan_offset_ele: + offset = sizeof(tDot11fIEsec_chan_offset_ele); + byteCount = 1; + pIePresent = ( (tDot11fIEsec_chan_offset_ele* )(pFrm + pIe->offset + offset * i ))->present; + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" + "'t know about the IE signature %d; this is most l" + "ikely a bug in 'framesc'.\n"), pIe->sig); + return DOT11F_INTERNAL_ERROR; + }/*End of switch Case*/ + if( byteCount && pIePresent ) + *pnNeeded += byteCount; + } /*End of for loop*/ + } + ++pIe; + } + return status; + +} + +static tANI_U32 GetPackedSizeTlvCore(tpAniSirGlobal pCtx, + tANI_U8 *pFrm, + tANI_U32 *pnNeeded, + const tTLVDefn TLVs[]) +{ + const tTLVDefn *pTlv; + tANI_U32 status; + tFRAMES_BOOL *pfFound; + tANI_U32 byteCount = 0; + tANI_U8 pTlvPresent = 0; + + status = DOT11F_PARSE_SUCCESS; + + pTlv = &( TLVs[0] ); + while ( 0xffff != pTlv->id ) + { + pfFound = (tFRAMES_BOOL*)(pFrm + pTlv->offset + + pTlv->presenceOffset); + if ( *pfFound ) + { + *pnNeeded += (pTlv->sType + pTlv->sLen); + if ( pTlv->pec ) *pnNeeded += 3U; + switch (pTlv->sig) + { + case SigTlvAuthorizedMACs: + byteCount = 6; + pTlvPresent = (( tDot11fTLVAuthorizedMACs* )(pFrm + pTlv->offset))->present; + break; + case SigTlvRequestToEnroll: + byteCount = 1; + pTlvPresent = (( tDot11fTLVRequestToEnroll* )(pFrm + pTlv->offset))->present; + break; + case SigTlvVersion2: + byteCount = 1; + pTlvPresent = (( tDot11fTLVVersion2* )(pFrm + pTlv->offset))->present; + break; + case SigTlvAPSetupLocked: + byteCount = 1; + pTlvPresent = (( tDot11fTLVAPSetupLocked* )(pFrm + pTlv->offset))->present; + break; + case SigTlvAssociationState: + byteCount = 2; + pTlvPresent = (( tDot11fTLVAssociationState* )(pFrm + pTlv->offset))->present; + break; + case SigTlvChannelList: + byteCount = ((tDot11fTLVChannelList*)(pFrm + pTlv->offset))->num_channelList+3; + pTlvPresent = (( tDot11fTLVChannelList* )(pFrm + pTlv->offset))->present; + break; + case SigTlvConfigMethods: + byteCount = 2; + pTlvPresent = (( tDot11fTLVConfigMethods* )(pFrm + pTlv->offset))->present; + break; + case SigTlvConfigurationError: + byteCount = 2; + pTlvPresent = (( tDot11fTLVConfigurationError* )(pFrm + pTlv->offset))->present; + break; + case SigTlvConfigurationTimeout: + byteCount = 2; + pTlvPresent = (( tDot11fTLVConfigurationTimeout* )(pFrm + pTlv->offset))->present; + break; + case SigTlvDeviceName: + byteCount = ((tDot11fTLVDeviceName*)(pFrm + pTlv->offset))->num_text; + pTlvPresent = (( tDot11fTLVDeviceName* )(pFrm + pTlv->offset))->present; + break; + case SigTlvDevicePasswordID: + byteCount = 2; + pTlvPresent = (( tDot11fTLVDevicePasswordID* )(pFrm + pTlv->offset))->present; + break; + case SigTlvExtendedListenTiming: + byteCount = 4; + pTlvPresent = (( tDot11fTLVExtendedListenTiming* )(pFrm + pTlv->offset))->present; + break; + case SigTlvGOIntent: + byteCount = 1; + pTlvPresent = (( tDot11fTLVGOIntent* )(pFrm + pTlv->offset))->present; + break; + case SigTlvIntendedP2PInterfaceAddress: + byteCount = 6; + pTlvPresent = (( tDot11fTLVIntendedP2PInterfaceAddress* )(pFrm + pTlv->offset))->present; + break; + case SigTlvInvitationFlags: + byteCount = 1; + pTlvPresent = (( tDot11fTLVInvitationFlags* )(pFrm + pTlv->offset))->present; + break; + case SigTlvListenChannel: + byteCount = 5; + pTlvPresent = (( tDot11fTLVListenChannel* )(pFrm + pTlv->offset))->present; + break; + case SigTlvManufacturer: + byteCount = ((tDot11fTLVManufacturer*)(pFrm + pTlv->offset))->num_name; + pTlvPresent = (( tDot11fTLVManufacturer* )(pFrm + pTlv->offset))->present; + break; + case SigTlvMinorReasonCode: + byteCount = 1; + pTlvPresent = (( tDot11fTLVMinorReasonCode* )(pFrm + pTlv->offset))->present; + break; + case SigTlvModelName: + byteCount = ((tDot11fTLVModelName*)(pFrm + pTlv->offset))->num_text; + pTlvPresent = (( tDot11fTLVModelName* )(pFrm + pTlv->offset))->present; + break; + case SigTlvModelNumber: + byteCount = ((tDot11fTLVModelNumber*)(pFrm + pTlv->offset))->num_text; + pTlvPresent = (( tDot11fTLVModelNumber* )(pFrm + pTlv->offset))->present; + break; + case SigTlvNoticeOfAbsence: + byteCount = ((tDot11fTLVNoticeOfAbsence*)(pFrm + pTlv->offset))->num_NoADesc+2; + pTlvPresent = (( tDot11fTLVNoticeOfAbsence* )(pFrm + pTlv->offset))->present; + break; + case SigTlvOperatingChannel: + byteCount = 5; + pTlvPresent = (( tDot11fTLVOperatingChannel* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PCapability: + byteCount = 2; + pTlvPresent = (( tDot11fTLVP2PCapability* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PDeviceId: + byteCount = 6; + pTlvPresent = (( tDot11fTLVP2PDeviceId* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PDeviceInfo: + status = GetPackedSizeTlvCore(pCtx, ( tANI_U8* )pFrm + pTlv->offset, pnNeeded, TLVS_P2PDeviceInfo); + byteCount = 16; + pTlvPresent = (( tDot11fTLVP2PDeviceInfo* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PGroupBssid: + byteCount = 6; + pTlvPresent = (( tDot11fTLVP2PGroupBssid* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PGroupId: + byteCount = ((tDot11fTLVP2PGroupId*)(pFrm + pTlv->offset))->num_ssid+6; + pTlvPresent = (( tDot11fTLVP2PGroupId* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PGroupInfo: + byteCount = ((tDot11fTLVP2PGroupInfo*)(pFrm + pTlv->offset))->num_P2PClientInfoDesc; + pTlvPresent = (( tDot11fTLVP2PGroupInfo* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PStatus: + byteCount = 1; + pTlvPresent = (( tDot11fTLVP2PStatus* )(pFrm + pTlv->offset))->present; + break; + case SigTlvPrimaryDeviceType: + byteCount = 8; + pTlvPresent = (( tDot11fTLVPrimaryDeviceType* )(pFrm + pTlv->offset))->present; + break; + case SigTlvRFBands: + byteCount = 1; + pTlvPresent = (( tDot11fTLVRFBands* )(pFrm + pTlv->offset))->present; + break; + case SigTlvRequestDeviceType: + byteCount = 8; + pTlvPresent = (( tDot11fTLVRequestDeviceType* )(pFrm + pTlv->offset))->present; + break; + case SigTlvRequestType: + byteCount = 1; + pTlvPresent = (( tDot11fTLVRequestType* )(pFrm + pTlv->offset))->present; + break; + case SigTlvResponseType: + byteCount = 1; + pTlvPresent = (( tDot11fTLVResponseType* )(pFrm + pTlv->offset))->present; + break; + case SigTlvSelectedRegistrar: + byteCount = 1; + pTlvPresent = (( tDot11fTLVSelectedRegistrar* )(pFrm + pTlv->offset))->present; + break; + case SigTlvSelectedRegistrarConfigMethods: + byteCount = 2; + pTlvPresent = (( tDot11fTLVSelectedRegistrarConfigMethods* )(pFrm + pTlv->offset))->present; + break; + case SigTlvSerialNumber: + byteCount = ((tDot11fTLVSerialNumber*)(pFrm + pTlv->offset))->num_text; + pTlvPresent = (( tDot11fTLVSerialNumber* )(pFrm + pTlv->offset))->present; + break; + case SigTlvUUID_E: + byteCount = 16; + pTlvPresent = (( tDot11fTLVUUID_E* )(pFrm + pTlv->offset))->present; + break; + case SigTlvUUID_R: + byteCount = 16; + pTlvPresent = (( tDot11fTLVUUID_R* )(pFrm + pTlv->offset))->present; + break; + case SigTlvVendorExtension: + status = GetPackedSizeTlvCore(pCtx, ( tANI_U8* )pFrm + pTlv->offset, pnNeeded, TLVS_VendorExtension); + byteCount = 3; + pTlvPresent = (( tDot11fTLVVendorExtension* )(pFrm + pTlv->offset))->present; + break; + case SigTlvVersion: + byteCount = 1; + pTlvPresent = (( tDot11fTLVVersion* )(pFrm + pTlv->offset))->present; + break; + case SigTlvWPSState: + byteCount = 1; + pTlvPresent = (( tDot11fTLVWPSState* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PInterface: + byteCount = 6; + pTlvPresent = (( tDot11fTLVP2PInterface* )(pFrm + pTlv->offset))->present; + break; + case SigTlvP2PManageability: + byteCount = 1; + pTlvPresent = (( tDot11fTLVP2PManageability* )(pFrm + pTlv->offset))->present; + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" + "'t know about the TLV signature %d; this is most l" + "ikely a bug in 'framesc'.\n"), pTlv->sig); + return DOT11F_INTERNAL_ERROR; + } + if(pTlvPresent) { + *pnNeeded += byteCount; + } + } + ++pTlv; + } + return status; +} +void dot11fPackFfAID(tpAniSirGlobal pCtx, + tDot11fFfAID *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->associd, 0); + (void)pCtx; +} /* End dot11fPackFfAID. */ + +void dot11fPackFfAction(tpAniSirGlobal pCtx, + tDot11fFfAction *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->action; + (void)pCtx; +} /* End dot11fPackFfAction. */ + +void dot11fPackFfAddBAParameterSet(tpAniSirGlobal pCtx, + tDot11fFfAddBAParameterSet *pSrc, + tANI_U8 *pBuf) +{ + tANI_U16 tmp70__; + tmp70__ = 0U; + tmp70__ |= ( pSrc->amsduSupported << 0 ); + tmp70__ |= ( pSrc->policy << 1 ); + tmp70__ |= ( pSrc->tid << 2 ); + tmp70__ |= ( pSrc->bufferSize << 6 ); + frameshtons(pCtx, pBuf, tmp70__, 0); + (void)pCtx; +} /* End dot11fPackFfAddBAParameterSet. */ + +void dot11fPackFfAuthAlgo(tpAniSirGlobal pCtx, + tDot11fFfAuthAlgo *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->algo, 0); + (void)pCtx; +} /* End dot11fPackFfAuthAlgo. */ + +void dot11fPackFfAuthSeqNo(tpAniSirGlobal pCtx, + tDot11fFfAuthSeqNo *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->no, 0); + (void)pCtx; +} /* End dot11fPackFfAuthSeqNo. */ + +void dot11fPackFfBAStartingSequenceControl(tpAniSirGlobal pCtx, + tDot11fFfBAStartingSequenceControl *pSrc, + tANI_U8 *pBuf) +{ + tANI_U16 tmp71__; + tmp71__ = 0U; + tmp71__ |= ( pSrc->fragNumber << 0 ); + tmp71__ |= ( pSrc->ssn << 4 ); + frameshtons(pCtx, pBuf, tmp71__, 0); + (void)pCtx; +} /* End dot11fPackFfBAStartingSequenceControl. */ + +void dot11fPackFfBATimeout(tpAniSirGlobal pCtx, + tDot11fFfBATimeout *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->timeout, 0); + (void)pCtx; +} /* End dot11fPackFfBATimeout. */ + +void dot11fPackFfBeaconInterval(tpAniSirGlobal pCtx, + tDot11fFfBeaconInterval *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->interval, 0); + (void)pCtx; +} /* End dot11fPackFfBeaconInterval. */ + +void dot11fPackFfCapabilities(tpAniSirGlobal pCtx, + tDot11fFfCapabilities *pSrc, + tANI_U8 *pBuf) +{ + tANI_U16 tmp72__; + tmp72__ = 0U; + tmp72__ |= ( pSrc->ess << 0 ); + tmp72__ |= ( pSrc->ibss << 1 ); + tmp72__ |= ( pSrc->cfPollable << 2 ); + tmp72__ |= ( pSrc->cfPollReq << 3 ); + tmp72__ |= ( pSrc->privacy << 4 ); + tmp72__ |= ( pSrc->shortPreamble << 5 ); + tmp72__ |= ( pSrc->pbcc << 6 ); + tmp72__ |= ( pSrc->channelAgility << 7 ); + tmp72__ |= ( pSrc->spectrumMgt << 8 ); + tmp72__ |= ( pSrc->qos << 9 ); + tmp72__ |= ( pSrc->shortSlotTime << 10 ); + tmp72__ |= ( pSrc->apsd << 11 ); + tmp72__ |= ( pSrc->rrm << 12 ); + tmp72__ |= ( pSrc->dsssOfdm << 13 ); + tmp72__ |= ( pSrc->delayedBA << 14 ); + tmp72__ |= ( pSrc->immediateBA << 15 ); + frameshtons(pCtx, pBuf, tmp72__, 0); + (void)pCtx; +} /* End dot11fPackFfCapabilities. */ + +void dot11fPackFfCategory(tpAniSirGlobal pCtx, + tDot11fFfCategory *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->category; + (void)pCtx; +} /* End dot11fPackFfCategory. */ + +void dot11fPackFfCurrentAPAddress(tpAniSirGlobal pCtx, + tDot11fFfCurrentAPAddress *pSrc, + tANI_U8 *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->mac, 6); + (void)pCtx; +} /* End dot11fPackFfCurrentAPAddress. */ + +void dot11fPackFfDelBAParameterSet(tpAniSirGlobal pCtx, + tDot11fFfDelBAParameterSet *pSrc, + tANI_U8 *pBuf) +{ + tANI_U16 tmp73__; + tmp73__ = 0U; + tmp73__ |= ( pSrc->reserved << 0 ); + tmp73__ |= ( pSrc->initiator << 11 ); + tmp73__ |= ( pSrc->tid << 12 ); + frameshtons(pCtx, pBuf, tmp73__, 0); + (void)pCtx; +} /* End dot11fPackFfDelBAParameterSet. */ + +void dot11fPackFfDialogToken(tpAniSirGlobal pCtx, + tDot11fFfDialogToken *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->token; + (void)pCtx; +} /* End dot11fPackFfDialogToken. */ + +void dot11fPackFfLinkMargin(tpAniSirGlobal pCtx, + tDot11fFfLinkMargin *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->linkMargin; + (void)pCtx; +} /* End dot11fPackFfLinkMargin. */ + +void dot11fPackFfListenInterval(tpAniSirGlobal pCtx, + tDot11fFfListenInterval *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->interval, 0); + (void)pCtx; +} /* End dot11fPackFfListenInterval. */ + +void dot11fPackFfMaxTxPower(tpAniSirGlobal pCtx, + tDot11fFfMaxTxPower *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->maxTxPower; + (void)pCtx; +} /* End dot11fPackFfMaxTxPower. */ + +void dot11fPackFfNumOfRepetitions(tpAniSirGlobal pCtx, + tDot11fFfNumOfRepetitions *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->repetitions, 0); + (void)pCtx; +} /* End dot11fPackFfNumOfRepetitions. */ + +void dot11fPackFfOperatingMode(tpAniSirGlobal pCtx, + tDot11fFfOperatingMode *pSrc, + tANI_U8 *pBuf) +{ + tANI_U8 tmp74__; + tmp74__ = 0U; + tmp74__ |= ( pSrc->chanWidth << 0 ); + tmp74__ |= ( pSrc->reserved << 2 ); + tmp74__ |= ( pSrc->rxNSS << 4 ); + tmp74__ |= ( pSrc->rxNSSType << 7 ); + *pBuf = tmp74__; + (void)pCtx; +} /* End dot11fPackFfOperatingMode. */ + +void dot11fPackFfP2POUI(tpAniSirGlobal pCtx, + tDot11fFfP2POUI *pSrc, + tANI_U8 *pBuf) +{ + frameshtonl(pCtx, pBuf, pSrc->oui, 0); + (void)pCtx; +} /* End dot11fPackFfP2POUI. */ + +void dot11fPackFfP2POUISubType(tpAniSirGlobal pCtx, + tDot11fFfP2POUISubType *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->ouiSubtype; + (void)pCtx; +} /* End dot11fPackFfP2POUISubType. */ + +void dot11fPackFfRCPI(tpAniSirGlobal pCtx, + tDot11fFfRCPI *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->rcpi; + (void)pCtx; +} /* End dot11fPackFfRCPI. */ + +void dot11fPackFfRSNI(tpAniSirGlobal pCtx, + tDot11fFfRSNI *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->rsni; + (void)pCtx; +} /* End dot11fPackFfRSNI. */ + +void dot11fPackFfReason(tpAniSirGlobal pCtx, + tDot11fFfReason *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->code, 0); + (void)pCtx; +} /* End dot11fPackFfReason. */ + +void dot11fPackFfRxAntennaId(tpAniSirGlobal pCtx, + tDot11fFfRxAntennaId *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->antennaId; + (void)pCtx; +} /* End dot11fPackFfRxAntennaId. */ + +void dot11fPackFfSMPowerModeSet(tpAniSirGlobal pCtx, + tDot11fFfSMPowerModeSet *pSrc, + tANI_U8 *pBuf) +{ + tANI_U8 tmp75__; + tmp75__ = 0U; + tmp75__ |= ( pSrc->PowerSave_En << 0 ); + tmp75__ |= ( pSrc->Mode << 1 ); + tmp75__ |= ( pSrc->reserved << 2 ); + *pBuf = tmp75__; + (void)pCtx; +} /* End dot11fPackFfSMPowerModeSet. */ + +void dot11fPackFfStatus(tpAniSirGlobal pCtx, + tDot11fFfStatus *pSrc, + tANI_U8 *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->status, 0); + (void)pCtx; +} /* End dot11fPackFfStatus. */ + +void dot11fPackFfStatusCode(tpAniSirGlobal pCtx, + tDot11fFfStatusCode *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->statusCode; + (void)pCtx; +} /* End dot11fPackFfStatusCode. */ + +void dot11fPackFfTPCEleID(tpAniSirGlobal pCtx, + tDot11fFfTPCEleID *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->TPCId; + (void)pCtx; +} /* End dot11fPackFfTPCEleID. */ + +void dot11fPackFfTPCEleLen(tpAniSirGlobal pCtx, + tDot11fFfTPCEleLen *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->TPCLen; + (void)pCtx; +} /* End dot11fPackFfTPCEleLen. */ + +void dot11fPackFfTSInfo(tpAniSirGlobal pCtx, + tDot11fFfTSInfo *pSrc, + tANI_U8 *pBuf) +{ + tANI_U32 tmp76__; + tmp76__ = 0U; + tmp76__ |= ( pSrc->traffic_type << 0 ); + tmp76__ |= ( pSrc->tsid << 1 ); + tmp76__ |= ( pSrc->direction << 5 ); + tmp76__ |= ( pSrc->access_policy << 7 ); + tmp76__ |= ( pSrc->aggregation << 9 ); + tmp76__ |= ( pSrc->psb << 10 ); + tmp76__ |= ( pSrc->user_priority << 11 ); + tmp76__ |= ( pSrc->tsinfo_ack_pol << 14 ); + tmp76__ |= ( pSrc->schedule << 16 ); + tmp76__ |= ( pSrc->unused << 17 ); + frameshtonl(pCtx, pBuf, tmp76__, 0); + (void)pCtx; +} /* End dot11fPackFfTSInfo. */ + +void dot11fPackFfTimeStamp(tpAniSirGlobal pCtx, + tDot11fFfTimeStamp *pSrc, + tANI_U8 *pBuf) +{ + frameshtonq(pCtx, pBuf, pSrc->timestamp, 0); + (void)pCtx; +} /* End dot11fPackFfTimeStamp. */ + +void dot11fPackFfTransactionId(tpAniSirGlobal pCtx, + tDot11fFfTransactionId *pSrc, + tANI_U8 *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->transId, 2); + (void)pCtx; +} /* End dot11fPackFfTransactionId. */ + +void dot11fPackFfTxAntennaId(tpAniSirGlobal pCtx, + tDot11fFfTxAntennaId *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->antennaId; + (void)pCtx; +} /* End dot11fPackFfTxAntennaId. */ + +void dot11fPackFfTxPower(tpAniSirGlobal pCtx, + tDot11fFfTxPower *pSrc, + tANI_U8 *pBuf) +{ + *pBuf = pSrc->txPower; + (void)pCtx; +} /* End dot11fPackFfTxPower. */ + +void dot11fPackFfVhtMembershipStatusArray(tpAniSirGlobal pCtx, + tDot11fFfVhtMembershipStatusArray *pSrc, + tANI_U8 *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->membershipStatusArray, 8); + (void)pCtx; +} /* End dot11fPackFfVhtMembershipStatusArray. */ + +void dot11fPackFfVhtUserPositionArray(tpAniSirGlobal pCtx, + tDot11fFfVhtUserPositionArray *pSrc, + tANI_U8 *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->userPositionArray, 16); + (void)pCtx; +} /* End dot11fPackFfVhtUserPositionArray. */ + +void dot11fPackFfext_chan_switch_ann_action(tpAniSirGlobal pCtx, + tDot11fFfext_chan_switch_ann_action *pSrc, + tANI_U8 *pBuf) +{ + tANI_U32 tmp77__; + tmp77__ = 0U; + tmp77__ |= ( pSrc->switch_mode << 0 ); + tmp77__ |= ( pSrc->op_class << 8 ); + tmp77__ |= ( pSrc->new_channel << 16 ); + tmp77__ |= ( pSrc->switch_count << 24 ); + frameshtonl(pCtx, pBuf, tmp77__, 0); + (void)pCtx; +} /* End dot11fPackFfext_chan_switch_ann_action. */ + +tANI_U32 dot11fPackTlvAuthorizedMACs(tpAniSirGlobal pCtx, + tDot11fTLVAuthorizedMACs *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 8; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 1; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 1; *pnConsumed += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->mac, 6); + *pnConsumed += 6; + pBuf += 6; + break; + } + (void)pCtx; + if (pTlvLen) + { + *pTlvLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvAuthorizedMACs. */ + +tANI_U32 dot11fPackTlvRequestToEnroll(tpAniSirGlobal pCtx, + tDot11fTLVRequestToEnroll *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 3; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 3; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 1; *pnConsumed += 1; + *pBuf = pSrc->req; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + *pTlvLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvRequestToEnroll. */ + +tANI_U32 dot11fPackTlvVersion2(tpAniSirGlobal pCtx, + tDot11fTLVVersion2 *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp78__; + nNeeded += 3; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 0; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 1; *pnConsumed += 1; + tmp78__ = 0U; + tmp78__ |= ( pSrc->minor << 0 ); + tmp78__ |= ( pSrc->major << 4 ); + *pBuf = tmp78__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pTlvLen) + { + *pTlvLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvVersion2. */ + +tANI_U32 dot11fPackTlvAPSetupLocked(tpAniSirGlobal pCtx, + tDot11fTLVAPSetupLocked *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4183, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->fLocked; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvAPSetupLocked. */ + +tANI_U32 dot11fPackTlvAssociationState(tpAniSirGlobal pCtx, + tDot11fTLVAssociationState *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4098, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->state, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvAssociationState. */ + +tANI_U32 dot11fPackTlvChannelList(tpAniSirGlobal pCtx, + tDot11fTLVChannelList *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_channelList + 6) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 11; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->countryString, 3); + *pnConsumed += 3; + pBuf += 3; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->channelList ), pSrc->num_channelList); + *pnConsumed += pSrc->num_channelList; + pBuf += pSrc->num_channelList; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvChannelList. */ + +tANI_U32 dot11fPackTlvConfigMethods(tpAniSirGlobal pCtx, + tDot11fTLVConfigMethods *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4104, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->methods, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvConfigMethods. */ + +tANI_U32 dot11fPackTlvConfigurationError(tpAniSirGlobal pCtx, + tDot11fTLVConfigurationError *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4105, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->error, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvConfigurationError. */ + +tANI_U32 dot11fPackTlvConfigurationTimeout(tpAniSirGlobal pCtx, + tDot11fTLVConfigurationTimeout *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 5; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->GOConfigTimeout; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->CLConfigTimeout; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvConfigurationTimeout. */ + +tANI_U32 dot11fPackTlvDeviceName(tpAniSirGlobal pCtx, + tDot11fTLVDeviceName *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_text + 4) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4113, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->text ), pSrc->num_text); + *pnConsumed += pSrc->num_text; + pBuf += pSrc->num_text; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvDeviceName. */ + +tANI_U32 dot11fPackTlvDevicePasswordID(tpAniSirGlobal pCtx, + tDot11fTLVDevicePasswordID *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4114, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->id, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvDevicePasswordID. */ + +tANI_U32 dot11fPackTlvExtendedListenTiming(tpAniSirGlobal pCtx, + tDot11fTLVExtendedListenTiming *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 7; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 8; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->availibilityPeriod, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->availibilityInterval, 0); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvExtendedListenTiming. */ + +tANI_U32 dot11fPackTlvGOIntent(tpAniSirGlobal pCtx, + tDot11fTLVGOIntent *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 4; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->GOIntent; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvGOIntent. */ + +tANI_U32 dot11fPackTlvIntendedP2PInterfaceAddress(tpAniSirGlobal pCtx, + tDot11fTLVIntendedP2PInterfaceAddress *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 9; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 9; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->P2PInterfaceAddress, 6); + *pnConsumed += 6; + pBuf += 6; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvIntendedP2PInterfaceAddress. */ + +tANI_U32 dot11fPackTlvInvitationFlags(tpAniSirGlobal pCtx, + tDot11fTLVInvitationFlags *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 18; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->invitationFlags; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvInvitationFlags. */ + +tANI_U32 dot11fPackTlvListenChannel(tpAniSirGlobal pCtx, + tDot11fTLVListenChannel *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 8; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 6; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->countryString, 3); + *pnConsumed += 3; + pBuf += 3; + *pBuf = pSrc->regulatoryClass; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->channel; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvListenChannel. */ + +tANI_U32 dot11fPackTlvManufacturer(tpAniSirGlobal pCtx, + tDot11fTLVManufacturer *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_name + 4) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4129, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->name ), pSrc->num_name); + *pnConsumed += pSrc->num_name; + pBuf += pSrc->num_name; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvManufacturer. */ + +tANI_U32 dot11fPackTlvMinorReasonCode(tpAniSirGlobal pCtx, + tDot11fTLVMinorReasonCode *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 1; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->minorReasonCode; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvMinorReasonCode. */ + +tANI_U32 dot11fPackTlvModelName(tpAniSirGlobal pCtx, + tDot11fTLVModelName *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_text + 4) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4131, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->text ), pSrc->num_text); + *pnConsumed += pSrc->num_text; + pBuf += pSrc->num_text; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvModelName. */ + +tANI_U32 dot11fPackTlvModelNumber(tpAniSirGlobal pCtx, + tDot11fTLVModelNumber *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_text + 4) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4132, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->text ), pSrc->num_text); + *pnConsumed += pSrc->num_text; + pBuf += pSrc->num_text; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvModelNumber. */ + +tANI_U32 dot11fPackTlvNoticeOfAbsence(tpAniSirGlobal pCtx, + tDot11fTLVNoticeOfAbsence *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_NoADesc + 5) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 12; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->index; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->CTSWindowOppPS; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->NoADesc ), pSrc->num_NoADesc); + *pnConsumed += pSrc->num_NoADesc; + pBuf += pSrc->num_NoADesc; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvNoticeOfAbsence. */ + +tANI_U32 dot11fPackTlvOperatingChannel(tpAniSirGlobal pCtx, + tDot11fTLVOperatingChannel *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 8; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 17; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->countryString, 3); + *pnConsumed += 3; + pBuf += 3; + *pBuf = pSrc->regulatoryClass; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->channel; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvOperatingChannel. */ + +tANI_U32 dot11fPackTlvP2PCapability(tpAniSirGlobal pCtx, + tDot11fTLVP2PCapability *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 2; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->deviceCapability; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->groupCapability; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PCapability. */ + +tANI_U32 dot11fPackTlvP2PDeviceId(tpAniSirGlobal pCtx, + tDot11fTLVP2PDeviceId *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 9; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 3; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->P2PDeviceAddress, 6); + *pnConsumed += 6; + pBuf += 6; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PDeviceId. */ + +tANI_U32 dot11fPackTlvP2PDeviceInfo(tpAniSirGlobal pCtx, + tDot11fTLVP2PDeviceInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + tANI_U32 idx = 0; + nNeeded += 19; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 13; + pBuf += 1; nBuf -= 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; nBuf -= 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->P2PDeviceAddress, 6); + *pnConsumed += 6; + pBuf += 6; + frameshtons(pCtx, pBuf, pSrc->configMethod, 1); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->primaryDeviceType, 8); + *pnConsumed += 8; + pBuf += 8; + status |= PackTlvCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + TLVS_P2PDeviceInfo, &idx); + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return status; +} /* End dot11fPackTlvP2PDeviceInfo. */ + +tANI_U32 dot11fPackTlvP2PGroupBssid(tpAniSirGlobal pCtx, + tDot11fTLVP2PGroupBssid *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 9; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 7; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->P2PGroupBssid, 6); + *pnConsumed += 6; + pBuf += 6; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PGroupBssid. */ + +tANI_U32 dot11fPackTlvP2PGroupId(tpAniSirGlobal pCtx, + tDot11fTLVP2PGroupId *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_ssid + 9) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 15; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->deviceAddress, 6); + *pnConsumed += 6; + pBuf += 6; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->ssid ), pSrc->num_ssid); + *pnConsumed += pSrc->num_ssid; + pBuf += pSrc->num_ssid; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PGroupId. */ + +tANI_U32 dot11fPackTlvP2PGroupInfo(tpAniSirGlobal pCtx, + tDot11fTLVP2PGroupInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_P2PClientInfoDesc + 3) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 14; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->P2PClientInfoDesc ), pSrc->num_P2PClientInfoDesc); + *pnConsumed += pSrc->num_P2PClientInfoDesc; + pBuf += pSrc->num_P2PClientInfoDesc; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PGroupInfo. */ + +tANI_U32 dot11fPackTlvP2PStatus(tpAniSirGlobal pCtx, + tDot11fTLVP2PStatus *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 0; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->status; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PStatus. */ + +tANI_U32 dot11fPackTlvPrimaryDeviceType(tpAniSirGlobal pCtx, + tDot11fTLVPrimaryDeviceType *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 12; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4180, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->primary_category, 1); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->oui, 4); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->sub_category, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvPrimaryDeviceType. */ + +tANI_U32 dot11fPackTlvRFBands(tpAniSirGlobal pCtx, + tDot11fTLVRFBands *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4156, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->bands; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvRFBands. */ + +tANI_U32 dot11fPackTlvRequestDeviceType(tpAniSirGlobal pCtx, + tDot11fTLVRequestDeviceType *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 12; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4202, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->primary_category, 1); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->oui, 4); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->sub_category, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvRequestDeviceType. */ + +tANI_U32 dot11fPackTlvRequestType(tpAniSirGlobal pCtx, + tDot11fTLVRequestType *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4154, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->reqType; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvRequestType. */ + +tANI_U32 dot11fPackTlvResponseType(tpAniSirGlobal pCtx, + tDot11fTLVResponseType *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4155, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->resType; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvResponseType. */ + +tANI_U32 dot11fPackTlvSelectedRegistrar(tpAniSirGlobal pCtx, + tDot11fTLVSelectedRegistrar *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4161, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->selected; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvSelectedRegistrar. */ + +tANI_U32 dot11fPackTlvSelectedRegistrarConfigMethods(tpAniSirGlobal pCtx, + tDot11fTLVSelectedRegistrarConfigMethods *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4179, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + frameshtons(pCtx, pBuf, pSrc->methods, 1); + *pnConsumed += 2; + pBuf += 2; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvSelectedRegistrarConfigMethods. */ + +tANI_U32 dot11fPackTlvSerialNumber(tpAniSirGlobal pCtx, + tDot11fTLVSerialNumber *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += ( pSrc->num_text + 4) ; + + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4162, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->text ), pSrc->num_text); + *pnConsumed += pSrc->num_text; + pBuf += pSrc->num_text; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvSerialNumber. */ + +tANI_U32 dot11fPackTlvUUID_E(tpAniSirGlobal pCtx, + tDot11fTLVUUID_E *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 20; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4167, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->uuid, 16); + *pnConsumed += 16; + pBuf += 16; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvUUID_E. */ + +tANI_U32 dot11fPackTlvUUID_R(tpAniSirGlobal pCtx, + tDot11fTLVUUID_R *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 20; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4168, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->uuid, 16); + *pnConsumed += 16; + pBuf += 16; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvUUID_R. */ + +tANI_U32 dot11fPackTlvVendorExtension(tpAniSirGlobal pCtx, + tDot11fTLVVendorExtension *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + tANI_U32 idx = 0; + nNeeded += 7; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4169, 1); + pBuf += 2; nBuf -= 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; nBuf -= 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->vendorId, 3); + *pnConsumed += 3; + pBuf += 3; + status |= PackTlvCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + TLVS_VendorExtension, &idx); + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return status; +} /* End dot11fPackTlvVendorExtension. */ + +tANI_U32 dot11fPackTlvVersion(tpAniSirGlobal pCtx, + tDot11fTLVVersion *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp79__; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4170, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + tmp79__ = 0U; + tmp79__ |= ( pSrc->minor << 0 ); + tmp79__ |= ( pSrc->major << 4 ); + *pBuf = tmp79__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvVersion. */ + +tANI_U32 dot11fPackTlvWPSState(tpAniSirGlobal pCtx, + tDot11fTLVWPSState *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + frameshtons( pCtx, pBuf, 4164, 1); + pBuf += 2; *pnConsumed += 2; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->state; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvWPSState. */ + +tANI_U32 dot11fPackTlvP2PInterface(tpAniSirGlobal pCtx, + tDot11fTLVP2PInterface *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 9; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 16; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->P2PDeviceAddress, 6); + *pnConsumed += 6; + pBuf += 6; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PInterface. */ + +tANI_U32 dot11fPackTlvP2PManageability(tpAniSirGlobal pCtx, + tDot11fTLVP2PManageability *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pTlvLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + while ( pSrc->present ) + { + *pBuf = 10; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 2; *pnConsumed += 2; + *pBuf = pSrc->manageability; + *pnConsumed += 1; + pBuf += 1; + break; + } + (void)pCtx; + if (pTlvLen) + { + frameshtons( pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackTlvP2PManageability. */ + +tANI_U32 dot11fPackIeCondensedCountryStr(tpAniSirGlobal pCtx, + tDot11fIECondensedCountryStr *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 2; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->countryStr, 2); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeCondensedCountryStr. */ + +tANI_U32 dot11fPackIeGTK(tpAniSirGlobal pCtx, + tDot11fIEGTK *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp80__; + nNeeded += (pSrc->num_key + 11); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 2; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp80__ = 0U; + tmp80__ |= ( pSrc->keyId << 0 ); + tmp80__ |= ( pSrc->reserved << 2 ); + frameshtons(pCtx, pBuf, tmp80__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + *pBuf = pSrc->keyLength; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->RSC, 8); + *pnConsumed += 8; + pBuf += 8; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->key ), pSrc->num_key); + *pnConsumed += pSrc->num_key; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeGTK. */ + +tANI_U32 dot11fPackIeIGTK(tpAniSirGlobal pCtx, + tDot11fIEIGTK *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 33; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 4; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->keyID, 2); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->IPN, 6); + *pnConsumed += 6; + pBuf += 6; + *pBuf = pSrc->keyLength; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->key, 24); + *pnConsumed += 24; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeIGTK. */ + +tANI_U32 dot11fPackIeR0KH_ID(tpAniSirGlobal pCtx, + tDot11fIER0KH_ID *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_PMK_R0_ID; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 3; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->PMK_R0_ID ), pSrc->num_PMK_R0_ID); + *pnConsumed += pSrc->num_PMK_R0_ID; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeR0KH_ID. */ + +tANI_U32 dot11fPackIeR1KH_ID(tpAniSirGlobal pCtx, + tDot11fIER1KH_ID *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 1; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->PMK_R1_ID, 6); + *pnConsumed += 6; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeR1KH_ID. */ + +tANI_U32 dot11fPackIeTSFInfo(tpAniSirGlobal pCtx, + tDot11fIETSFInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 1; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->TsfOffset, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->BeaconIntvl, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTSFInfo. */ + +tANI_U32 dot11fPackIeAPChannelReport(tpAniSirGlobal pCtx, + tDot11fIEAPChannelReport *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_channelList + 1); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 51; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->regulatoryClass; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->channelList ), pSrc->num_channelList); + *pnConsumed += pSrc->num_channelList; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeAPChannelReport. */ + +tANI_U32 dot11fPackIeBcnReportingDetail(tpAniSirGlobal pCtx, + tDot11fIEBcnReportingDetail *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 2; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->reportingDetail; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeBcnReportingDetail. */ + +tANI_U32 dot11fPackIeBeaconReportFrmBody(tpAniSirGlobal pCtx, + tDot11fIEBeaconReportFrmBody *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_reportedFields; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 1; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->reportedFields ), pSrc->num_reportedFields); + *pnConsumed += pSrc->num_reportedFields; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeBeaconReportFrmBody. */ + +tANI_U32 dot11fPackIeBeaconReporting(tpAniSirGlobal pCtx, + tDot11fIEBeaconReporting *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 1; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->reportingCondition; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->threshold; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeBeaconReporting. */ + +tANI_U32 dot11fPackIeMeasurementPilot(tpAniSirGlobal pCtx, + tDot11fIEMeasurementPilot *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_vendorSpecific + 1); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 66; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->measurementPilot; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->vendorSpecific ), pSrc->num_vendorSpecific); + *pnConsumed += pSrc->num_vendorSpecific; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeMeasurementPilot. */ + +tANI_U32 dot11fPackIeMultiBssid(tpAniSirGlobal pCtx, + tDot11fIEMultiBssid *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_vendorSpecific + 1); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 71; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->maxBSSIDIndicator; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->vendorSpecific ), pSrc->num_vendorSpecific); + *pnConsumed += pSrc->num_vendorSpecific; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeMultiBssid. */ + +tANI_U32 dot11fPackIeRICData(tpAniSirGlobal pCtx, + tDot11fIERICData *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 57; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->Identifier; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->resourceDescCount; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->statusCode, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRICData. */ + +tANI_U32 dot11fPackIeRICDescriptor(tpAniSirGlobal pCtx, + tDot11fIERICDescriptor *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_variableData + 1); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 75; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->resourceType; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->variableData ), pSrc->num_variableData); + *pnConsumed += pSrc->num_variableData; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRICDescriptor. */ + +tANI_U32 dot11fPackIeRRMEnabledCap(tpAniSirGlobal pCtx, + tDot11fIERRMEnabledCap *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp81__; + tANI_U8 tmp82__; + tANI_U8 tmp83__; + tANI_U8 tmp84__; + tANI_U8 tmp85__; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 70; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp81__ = 0U; + tmp81__ |= ( pSrc->LinkMeasurement << 0 ); + tmp81__ |= ( pSrc->NeighborRpt << 1 ); + tmp81__ |= ( pSrc->parallel << 2 ); + tmp81__ |= ( pSrc->repeated << 3 ); + tmp81__ |= ( pSrc->BeaconPassive << 4 ); + tmp81__ |= ( pSrc->BeaconActive << 5 ); + tmp81__ |= ( pSrc->BeaconTable << 6 ); + tmp81__ |= ( pSrc->BeaconRepCond << 7 ); + *pBuf = tmp81__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp82__ = 0U; + tmp82__ |= ( pSrc->FrameMeasurement << 0 ); + tmp82__ |= ( pSrc->ChannelLoad << 1 ); + tmp82__ |= ( pSrc->NoiseHistogram << 2 ); + tmp82__ |= ( pSrc->statistics << 3 ); + tmp82__ |= ( pSrc->LCIMeasurement << 4 ); + tmp82__ |= ( pSrc->LCIAzimuth << 5 ); + tmp82__ |= ( pSrc->TCMCapability << 6 ); + tmp82__ |= ( pSrc->triggeredTCM << 7 ); + *pBuf = tmp82__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp83__ = 0U; + tmp83__ |= ( pSrc->APChanReport << 0 ); + tmp83__ |= ( pSrc->RRMMIBEnabled << 1 ); + tmp83__ |= ( pSrc->operatingChanMax << 2 ); + tmp83__ |= ( pSrc->nonOperatinChanMax << 5 ); + *pBuf = tmp83__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp84__ = 0U; + tmp84__ |= ( pSrc->MeasurementPilot << 0 ); + tmp84__ |= ( pSrc->MeasurementPilotEnabled << 3 ); + tmp84__ |= ( pSrc->NeighborTSFOffset << 4 ); + tmp84__ |= ( pSrc->RCPIMeasurement << 5 ); + tmp84__ |= ( pSrc->RSNIMeasurement << 6 ); + tmp84__ |= ( pSrc->BssAvgAccessDelay << 7 ); + *pBuf = tmp84__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp85__ = 0U; + tmp85__ |= ( pSrc->BSSAvailAdmission << 0 ); + tmp85__ |= ( pSrc->AntennaInformation << 1 ); + tmp85__ |= ( pSrc->fine_time_meas_rpt << 2 ); + tmp85__ |= ( pSrc->lci_capability << 3 ); + tmp85__ |= ( pSrc->reserved << 4 ); + *pBuf = tmp85__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRRMEnabledCap. */ + +tANI_U32 dot11fPackIeRequestedInfo(tpAniSirGlobal pCtx, + tDot11fIERequestedInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_requested_eids; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 10; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->requested_eids ), pSrc->num_requested_eids); + *pnConsumed += pSrc->num_requested_eids; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRequestedInfo. */ + +tANI_U32 dot11fPackIeSSID(tpAniSirGlobal pCtx, + tDot11fIESSID *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_ssid; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 0; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->ssid ), pSrc->num_ssid); + *pnConsumed += pSrc->num_ssid; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeSSID. */ + +tANI_U32 dot11fPackIeSchedule(tpAniSirGlobal pCtx, + tDot11fIESchedule *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp86__; + nNeeded += 14; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 15; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp86__ = 0U; + tmp86__ |= ( pSrc->aggregation << 0 ); + tmp86__ |= ( pSrc->tsid << 1 ); + tmp86__ |= ( pSrc->direction << 5 ); + tmp86__ |= ( pSrc->reserved << 7 ); + frameshtons(pCtx, pBuf, tmp86__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + frameshtonl(pCtx, pBuf, pSrc->service_start_time, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->service_interval, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->max_service_dur, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->spec_interval, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeSchedule. */ + +tANI_U32 dot11fPackIeTCLAS(tpAniSirGlobal pCtx, + tDot11fIETCLAS *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIETCLAS(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 14; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->user_priority; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->classifier_type; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->classifier_mask; + *pnConsumed += 1; + pBuf += 1; + switch (pSrc->classifier_type) + { + case 0: + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.EthParams.source, 6); + *pnConsumed += 6; + pBuf += 6; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.EthParams.dest, 6); + *pnConsumed += 6; + pBuf += 6; + frameshtons(pCtx, pBuf, pSrc->info.EthParams.type, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + case 1: + *pBuf = pSrc->info.IpParams.version; + *pnConsumed += 1; + pBuf += 1; + switch (pSrc->info.IpParams.version) + { + case 4: + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.source, 4); + *pnConsumed += 4; + pBuf += 4; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.dest, 4); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.src_port, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.dest_port, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->info.IpParams.params.IpV4Params.DSCP; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->info.IpParams.params.IpV4Params.proto; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->info.IpParams.params.IpV4Params.reserved; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + case 6: + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.source, 16); + *pnConsumed += 16; + pBuf += 16; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.dest, 16); + *pnConsumed += 16; + pBuf += 16; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.src_port, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.dest_port, 0); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.flow_label, 3); + *pnConsumed += 3; + // fieldsEndFlag = 1 + break; + } + break; + case 2: + frameshtons(pCtx, pBuf, pSrc->info.Params8021dq.tag_type, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeTCLAS. */ + +tANI_U32 dot11fPackIeTCLASSPROC(tpAniSirGlobal pCtx, + tDot11fIETCLASSPROC *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 44; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->processing; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTCLASSPROC. */ + +tANI_U32 dot11fPackIeTSDelay(tpAniSirGlobal pCtx, + tDot11fIETSDelay *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 43; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtonl(pCtx, pBuf, pSrc->delay, 0); + *pnConsumed += 4; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTSDelay. */ + +tANI_U32 dot11fPackIeTSPEC(tpAniSirGlobal pCtx, + tDot11fIETSPEC *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp87__; + tANI_U8 tmp88__; + tANI_U16 tmp89__; + nNeeded += 55; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 13; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp87__ = 0U; + tmp87__ |= ( pSrc->traffic_type << 0 ); + tmp87__ |= ( pSrc->tsid << 1 ); + tmp87__ |= ( pSrc->direction << 5 ); + tmp87__ |= ( pSrc->access_policy << 7 ); + tmp87__ |= ( pSrc->aggregation << 9 ); + tmp87__ |= ( pSrc->psb << 10 ); + tmp87__ |= ( pSrc->user_priority << 11 ); + tmp87__ |= ( pSrc->tsinfo_ack_pol << 14 ); + frameshtons(pCtx, pBuf, tmp87__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp88__ = 0U; + tmp88__ |= ( pSrc->schedule << 0 ); + tmp88__ |= ( pSrc->unused << 1 ); + *pBuf = tmp88__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp89__ = 0U; + tmp89__ |= ( pSrc->size << 0 ); + tmp89__ |= ( pSrc->fixed << 15 ); + frameshtons(pCtx, pBuf, tmp89__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + frameshtons(pCtx, pBuf, pSrc->max_msdu_size, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtonl(pCtx, pBuf, pSrc->min_service_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->max_service_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->inactivity_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->suspension_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->service_start_time, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->min_data_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->mean_data_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->peak_data_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->burst_size, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->delay_bound, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->min_phy_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->surplus_bw_allowance, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->medium_time, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTSPEC. */ + +tANI_U32 dot11fPackIeWMMSchedule(tpAniSirGlobal pCtx, + tDot11fIEWMMSchedule *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp90__; + nNeeded += 15; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + tmp90__ = 0U; + tmp90__ |= ( pSrc->aggregation << 0 ); + tmp90__ |= ( pSrc->tsid << 1 ); + tmp90__ |= ( pSrc->direction << 5 ); + tmp90__ |= ( pSrc->reserved << 7 ); + frameshtons(pCtx, pBuf, tmp90__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + frameshtonl(pCtx, pBuf, pSrc->service_start_time, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->service_interval, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->max_service_dur, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->spec_interval, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMSchedule. */ + +tANI_U32 dot11fPackIeWMMTCLAS(tpAniSirGlobal pCtx, + tDot11fIEWMMTCLAS *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEWMMTCLAS(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 = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x6; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->user_priority; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->classifier_type; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->classifier_mask; + *pnConsumed += 1; + pBuf += 1; + switch (pSrc->classifier_type) + { + case 0: + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.EthParams.source, 6); + *pnConsumed += 6; + pBuf += 6; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.EthParams.dest, 6); + *pnConsumed += 6; + pBuf += 6; + frameshtons(pCtx, pBuf, pSrc->info.EthParams.type, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + case 1: + *pBuf = pSrc->info.IpParams.version; + *pnConsumed += 1; + pBuf += 1; + switch (pSrc->info.IpParams.version) + { + case 4: + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.source, 4); + *pnConsumed += 4; + pBuf += 4; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.dest, 4); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.src_port, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV4Params.dest_port, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->info.IpParams.params.IpV4Params.DSCP; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->info.IpParams.params.IpV4Params.proto; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->info.IpParams.params.IpV4Params.reserved; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + case 6: + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.source, 10); + *pnConsumed += 10; + pBuf += 10; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.dest, 10); + *pnConsumed += 10; + pBuf += 10; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.src_port, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.dest_port, 0); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->info.IpParams.params.IpV6Params.flow_label, 3); + *pnConsumed += 3; + // fieldsEndFlag = 1 + break; + } + break; + case 2: + frameshtons(pCtx, pBuf, pSrc->info.Params8021dq.tag_type, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeWMMTCLAS. */ + +tANI_U32 dot11fPackIeWMMTCLASPROC(tpAniSirGlobal pCtx, + tDot11fIEWMMTCLASPROC *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x7; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->processing; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMTCLASPROC. */ + +tANI_U32 dot11fPackIeWMMTSDelay(tpAniSirGlobal pCtx, + tDot11fIEWMMTSDelay *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x8; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + frameshtonl(pCtx, pBuf, pSrc->delay, 0); + *pnConsumed += 4; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMTSDelay. */ + +tANI_U32 dot11fPackIeWMMTSPEC(tpAniSirGlobal pCtx, + tDot11fIEWMMTSPEC *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp91__; + tANI_U8 tmp92__; + tANI_U16 tmp93__; + nNeeded += 38; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + tmp91__ = 0U; + tmp91__ |= ( pSrc->traffic_type << 0 ); + tmp91__ |= ( pSrc->tsid << 1 ); + tmp91__ |= ( pSrc->direction << 5 ); + tmp91__ |= ( pSrc->access_policy << 7 ); + tmp91__ |= ( pSrc->aggregation << 9 ); + tmp91__ |= ( pSrc->psb << 10 ); + tmp91__ |= ( pSrc->user_priority << 11 ); + tmp91__ |= ( pSrc->tsinfo_ack_pol << 14 ); + frameshtons(pCtx, pBuf, tmp91__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp92__ = 0U; + tmp92__ |= ( pSrc->tsinfo_rsvd << 0 ); + tmp92__ |= ( pSrc->burst_size_defn << 7 ); + *pBuf = tmp92__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp93__ = 0U; + tmp93__ |= ( pSrc->size << 0 ); + tmp93__ |= ( pSrc->fixed << 15 ); + frameshtons(pCtx, pBuf, tmp93__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + frameshtons(pCtx, pBuf, pSrc->max_msdu_size, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtonl(pCtx, pBuf, pSrc->min_service_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->max_service_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->inactivity_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->suspension_int, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->service_start_time, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->min_data_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->mean_data_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->peak_data_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->burst_size, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->delay_bound, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtonl(pCtx, pBuf, pSrc->min_phy_rate, 0); + *pnConsumed += 4; + pBuf += 4; + frameshtons(pCtx, pBuf, pSrc->surplus_bw_allowance, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->medium_time, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMTSPEC. */ + +tANI_U32 dot11fPackIeWiderBWChanSwitchAnn(tpAniSirGlobal pCtx, + tDot11fIEWiderBWChanSwitchAnn *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 3; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 194; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->newChanWidth; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->newCenterChanFreq0; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->newCenterChanFreq1; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWiderBWChanSwitchAnn. */ + +tANI_U32 dot11fPackIeAID(tpAniSirGlobal pCtx, + tDot11fIEAID *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 197; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->assocId, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeAID. */ + +tANI_U32 dot11fPackIeCFParams(tpAniSirGlobal pCtx, + tDot11fIECFParams *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 4; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->cfp_count; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->cfp_period; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->cfp_maxduration, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->cfp_durremaining, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeCFParams. */ + +tANI_U32 dot11fPackIeChallengeText(tpAniSirGlobal pCtx, + tDot11fIEChallengeText *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_text; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 16; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->text ), pSrc->num_text); + *pnConsumed += pSrc->num_text; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeChallengeText. */ + +tANI_U32 dot11fPackIeChanSwitchAnn(tpAniSirGlobal pCtx, + tDot11fIEChanSwitchAnn *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 3; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 37; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->switchMode; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->newChannel; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->switchCount; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeChanSwitchAnn. */ + +tANI_U32 dot11fPackIeChannelSwitchWrapper(tpAniSirGlobal pCtx, + tDot11fIEChannelSwitchWrapper *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEChannelSwitchWrapper(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 196; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + status = PackCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_ChannelSwitchWrapper, + IES_ChannelSwitchWrapper); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeChannelSwitchWrapper. */ + +tANI_U32 dot11fPackIeCountry(tpAniSirGlobal pCtx, + tDot11fIECountry *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIECountry(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 7; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->country, 3); + *pnConsumed += 3; + pBuf += 3; + if ( pSrc->num_triplets ) { + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->triplets ), ( pSrc->num_triplets * 3 )); + *pnConsumed += ( pSrc->num_triplets * 3 ); + // fieldsEndFlag = 1 + } + else break; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeCountry. */ + +tANI_U32 dot11fPackIeDSParams(tpAniSirGlobal pCtx, + tDot11fIEDSParams *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 3; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->curr_channel; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeDSParams. */ + +tANI_U32 dot11fPackIeEDCAParamSet(tpAniSirGlobal pCtx, + tDot11fIEEDCAParamSet *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp94__; + tANI_U8 tmp95__; + tANI_U8 tmp96__; + tANI_U8 tmp97__; + tANI_U8 tmp98__; + tANI_U8 tmp99__; + tANI_U8 tmp100__; + tANI_U8 tmp101__; + nNeeded += 18; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 12; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->qos; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->reserved; + *pnConsumed += 1; + pBuf += 1; + tmp94__ = 0U; + tmp94__ |= ( pSrc->acbe_aifsn << 0 ); + tmp94__ |= ( pSrc->acbe_acm << 4 ); + tmp94__ |= ( pSrc->acbe_aci << 5 ); + tmp94__ |= ( pSrc->unused1 << 7 ); + *pBuf = tmp94__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp95__ = 0U; + tmp95__ |= ( pSrc->acbe_acwmin << 0 ); + tmp95__ |= ( pSrc->acbe_acwmax << 4 ); + *pBuf = tmp95__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp96__ = 0U; + tmp96__ |= ( pSrc->acbk_aifsn << 0 ); + tmp96__ |= ( pSrc->acbk_acm << 4 ); + tmp96__ |= ( pSrc->acbk_aci << 5 ); + tmp96__ |= ( pSrc->unused2 << 7 ); + *pBuf = tmp96__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp97__ = 0U; + tmp97__ |= ( pSrc->acbk_acwmin << 0 ); + tmp97__ |= ( pSrc->acbk_acwmax << 4 ); + *pBuf = tmp97__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp98__ = 0U; + tmp98__ |= ( pSrc->acvi_aifsn << 0 ); + tmp98__ |= ( pSrc->acvi_acm << 4 ); + tmp98__ |= ( pSrc->acvi_aci << 5 ); + tmp98__ |= ( pSrc->unused3 << 7 ); + *pBuf = tmp98__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp99__ = 0U; + tmp99__ |= ( pSrc->acvi_acwmin << 0 ); + tmp99__ |= ( pSrc->acvi_acwmax << 4 ); + *pBuf = tmp99__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp100__ = 0U; + tmp100__ |= ( pSrc->acvo_aifsn << 0 ); + tmp100__ |= ( pSrc->acvo_acm << 4 ); + tmp100__ |= ( pSrc->acvo_aci << 5 ); + tmp100__ |= ( pSrc->unused4 << 7 ); + *pBuf = tmp100__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp101__ = 0U; + tmp101__ |= ( pSrc->acvo_acwmin << 0 ); + tmp101__ |= ( pSrc->acvo_acwmax << 4 ); + *pBuf = tmp101__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeEDCAParamSet. */ + +tANI_U32 dot11fPackIeERPInfo(tpAniSirGlobal pCtx, + tDot11fIEERPInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp102__; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 42; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp102__ = 0U; + tmp102__ |= ( pSrc->non_erp_present << 0 ); + tmp102__ |= ( pSrc->use_prot << 1 ); + tmp102__ |= ( pSrc->barker_preamble << 2 ); + tmp102__ |= ( pSrc->unused << 3 ); + *pBuf = tmp102__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeERPInfo. */ + +tANI_U32 dot11fPackIeESECckmOpaque(tpAniSirGlobal pCtx, + tDot11fIEESECckmOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 156; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x40; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x96; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeESECckmOpaque. */ + +tANI_U32 dot11fPackIeESERadMgmtCap(tpAniSirGlobal pCtx, + tDot11fIEESERadMgmtCap *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp103__; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x40; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x96; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x1; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->mgmt_state; + *pnConsumed += 1; + pBuf += 1; + tmp103__ = 0U; + tmp103__ |= ( pSrc->mbssid_mask << 0 ); + tmp103__ |= ( pSrc->reserved << 3 ); + *pBuf = tmp103__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeESERadMgmtCap. */ + +tANI_U32 dot11fPackIeESETrafStrmMet(tpAniSirGlobal pCtx, + tDot11fIEESETrafStrmMet *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x40; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x96; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x7; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->tsid; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->state; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->msmt_interval, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeESETrafStrmMet. */ + +tANI_U32 dot11fPackIeESETrafStrmRateSet(tpAniSirGlobal pCtx, + tDot11fIEESETrafStrmRateSet *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_tsrates + 1); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x40; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x96; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x8; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->tsid; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->tsrates ), pSrc->num_tsrates); + *pnConsumed += pSrc->num_tsrates; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeESETrafStrmRateSet. */ + +tANI_U32 dot11fPackIeESETxmitPower(tpAniSirGlobal pCtx, + tDot11fIEESETxmitPower *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 150; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x40; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x96; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->power_limit; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->reserved; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeESETxmitPower. */ + +tANI_U32 dot11fPackIeESEVersion(tpAniSirGlobal pCtx, + tDot11fIEESEVersion *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x40; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x96; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x3; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeESEVersion. */ + +tANI_U32 dot11fPackIeExtCap(tpAniSirGlobal pCtx, + tDot11fIEExtCap *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_bytes; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 127; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->bytes ), pSrc->num_bytes); + *pnConsumed += pSrc->num_bytes; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeExtCap. */ + +tANI_U32 dot11fPackIeExtSuppRates(tpAniSirGlobal pCtx, + tDot11fIEExtSuppRates *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_rates; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 50; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->rates ), pSrc->num_rates); + *pnConsumed += pSrc->num_rates; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeExtSuppRates. */ + +tANI_U32 dot11fPackIeFHParamSet(tpAniSirGlobal pCtx, + tDot11fIEFHParamSet *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 2; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->dwell_time, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->hop_set; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->hop_pattern; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->hop_index; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeFHParamSet. */ + +tANI_U32 dot11fPackIeFHParams(tpAniSirGlobal pCtx, + tDot11fIEFHParams *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 8; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->radix; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->nchannels; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeFHParams. */ + +tANI_U32 dot11fPackIeFHPattTable(tpAniSirGlobal pCtx, + tDot11fIEFHPattTable *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_randtable + 4); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 9; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->flag; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->nsets; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->modulus; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->offset; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->randtable ), pSrc->num_randtable); + *pnConsumed += pSrc->num_randtable; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeFHPattTable. */ + +tANI_U32 dot11fPackIeFTInfo(tpAniSirGlobal pCtx, + tDot11fIEFTInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp104__; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEFTInfo(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 55; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + tmp104__ = 0U; + tmp104__ |= ( pSrc->reserved << 0 ); + tmp104__ |= ( pSrc->IECount << 8 ); + frameshtons(pCtx, pBuf, tmp104__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->MIC, 16); + *pnConsumed += 16; + pBuf += 16; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->Anonce, 32); + *pnConsumed += 32; + pBuf += 32; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->Snonce, 32); + *pnConsumed += 32; + pBuf += 32; + status = PackCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_FTInfo, + IES_FTInfo); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeFTInfo. */ + +tANI_U32 dot11fPackIeHT2040BSSCoexistence(tpAniSirGlobal pCtx, + tDot11fIEHT2040BSSCoexistence *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp105__; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 72; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp105__ = 0U; + tmp105__ |= ( pSrc->infoRequest << 0 ); + tmp105__ |= ( pSrc->fortyMHzIntolerant << 1 ); + tmp105__ |= ( pSrc->twentyMHzBssWidthReq << 2 ); + tmp105__ |= ( pSrc->obssScanExemptionReq << 3 ); + tmp105__ |= ( pSrc->obssScanExemptionGrant << 4 ); + tmp105__ |= ( pSrc->unused << 5 ); + *pBuf = tmp105__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeHT2040BSSCoexistence. */ + +tANI_U32 dot11fPackIeHT2040BSSIntolerantReport(tpAniSirGlobal pCtx, + tDot11fIEHT2040BSSIntolerantReport *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_channelList + 1); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 73; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->operatingClass; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->channelList ), pSrc->num_channelList); + *pnConsumed += pSrc->num_channelList; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeHT2040BSSIntolerantReport. */ + +tANI_U32 dot11fPackIeHTCaps(tpAniSirGlobal pCtx, + tDot11fIEHTCaps *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp106__; + tANI_U8 tmp107__; + tANI_U16 tmp108__; + tANI_U32 tmp109__; + tANI_U8 tmp110__; + nNeeded += (pSrc->num_rsvd + 26); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 45; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp106__ = 0U; + tmp106__ |= ( pSrc->advCodingCap << 0 ); + tmp106__ |= ( pSrc->supportedChannelWidthSet << 1 ); + tmp106__ |= ( pSrc->mimoPowerSave << 2 ); + tmp106__ |= ( pSrc->greenField << 4 ); + tmp106__ |= ( pSrc->shortGI20MHz << 5 ); + tmp106__ |= ( pSrc->shortGI40MHz << 6 ); + tmp106__ |= ( pSrc->txSTBC << 7 ); + tmp106__ |= ( pSrc->rxSTBC << 8 ); + tmp106__ |= ( pSrc->delayedBA << 10 ); + tmp106__ |= ( pSrc->maximalAMSDUsize << 11 ); + tmp106__ |= ( pSrc->dsssCckMode40MHz << 12 ); + tmp106__ |= ( pSrc->psmp << 13 ); + tmp106__ |= ( pSrc->stbcControlFrame << 14 ); + tmp106__ |= ( pSrc->lsigTXOPProtection << 15 ); + frameshtons(pCtx, pBuf, tmp106__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp107__ = 0U; + tmp107__ |= ( pSrc->maxRxAMPDUFactor << 0 ); + tmp107__ |= ( pSrc->mpduDensity << 2 ); + tmp107__ |= ( pSrc->reserved1 << 5 ); + *pBuf = tmp107__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->supportedMCSSet, 16); + *pnConsumed += 16; + pBuf += 16; + tmp108__ = 0U; + tmp108__ |= ( pSrc->pco << 0 ); + tmp108__ |= ( pSrc->transitionTime << 1 ); + tmp108__ |= ( pSrc->reserved2 << 3 ); + tmp108__ |= ( pSrc->mcsFeedback << 8 ); + tmp108__ |= ( pSrc->reserved3 << 10 ); + frameshtons(pCtx, pBuf, tmp108__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp109__ = 0U; + tmp109__ |= ( pSrc->txBF << 0 ); + tmp109__ |= ( pSrc->rxStaggeredSounding << 1 ); + tmp109__ |= ( pSrc->txStaggeredSounding << 2 ); + tmp109__ |= ( pSrc->rxZLF << 3 ); + tmp109__ |= ( pSrc->txZLF << 4 ); + tmp109__ |= ( pSrc->implicitTxBF << 5 ); + tmp109__ |= ( pSrc->calibration << 6 ); + tmp109__ |= ( pSrc->explicitCSITxBF << 8 ); + tmp109__ |= ( pSrc->explicitUncompressedSteeringMatrix << 9 ); + tmp109__ |= ( pSrc->explicitBFCSIFeedback << 10 ); + tmp109__ |= ( pSrc->explicitUncompressedSteeringMatrixFeedback << 13 ); + tmp109__ |= ( pSrc->explicitCompressedSteeringMatrixFeedback << 16 ); + tmp109__ |= ( pSrc->csiNumBFAntennae << 19 ); + tmp109__ |= ( pSrc->uncompressedSteeringMatrixBFAntennae << 21 ); + tmp109__ |= ( pSrc->compressedSteeringMatrixBFAntennae << 23 ); + tmp109__ |= ( pSrc->reserved4 << 25 ); + frameshtonl(pCtx, pBuf, tmp109__, 0); + *pnConsumed += 4; + pBuf += 4; + nBuf -= 4 ; + tmp110__ = 0U; + tmp110__ |= ( pSrc->antennaSelection << 0 ); + tmp110__ |= ( pSrc->explicitCSIFeedbackTx << 1 ); + tmp110__ |= ( pSrc->antennaIndicesFeedbackTx << 2 ); + tmp110__ |= ( pSrc->explicitCSIFeedback << 3 ); + tmp110__ |= ( pSrc->antennaIndicesFeedback << 4 ); + tmp110__ |= ( pSrc->rxAS << 5 ); + tmp110__ |= ( pSrc->txSoundingPPDUs << 6 ); + tmp110__ |= ( pSrc->reserved5 << 7 ); + *pBuf = tmp110__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->rsvd ), pSrc->num_rsvd); + *pnConsumed += pSrc->num_rsvd; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeHTCaps. */ + +tANI_U32 dot11fPackIeHTInfo(tpAniSirGlobal pCtx, + tDot11fIEHTInfo *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp111__; + tANI_U16 tmp112__; + tANI_U16 tmp113__; + nNeeded += (pSrc->num_rsvd + 22); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 61; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->primaryChannel; + *pnConsumed += 1; + pBuf += 1; + tmp111__ = 0U; + tmp111__ |= ( pSrc->secondaryChannelOffset << 0 ); + tmp111__ |= ( pSrc->recommendedTxWidthSet << 2 ); + tmp111__ |= ( pSrc->rifsMode << 3 ); + tmp111__ |= ( pSrc->controlledAccessOnly << 4 ); + tmp111__ |= ( pSrc->serviceIntervalGranularity << 5 ); + *pBuf = tmp111__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp112__ = 0U; + tmp112__ |= ( pSrc->opMode << 0 ); + tmp112__ |= ( pSrc->nonGFDevicesPresent << 2 ); + tmp112__ |= ( pSrc->transmitBurstLimit << 3 ); + tmp112__ |= ( pSrc->obssNonHTStaPresent << 4 ); + tmp112__ |= ( pSrc->reserved << 5 ); + frameshtons(pCtx, pBuf, tmp112__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp113__ = 0U; + tmp113__ |= ( pSrc->basicSTBCMCS << 0 ); + tmp113__ |= ( pSrc->dualCTSProtection << 7 ); + tmp113__ |= ( pSrc->secondaryBeacon << 8 ); + tmp113__ |= ( pSrc->lsigTXOPProtectionFullSupport << 9 ); + tmp113__ |= ( pSrc->pcoActive << 10 ); + tmp113__ |= ( pSrc->pcoPhase << 11 ); + tmp113__ |= ( pSrc->reserved2 << 12 ); + frameshtons(pCtx, pBuf, tmp113__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->basicMCSSet, 16); + *pnConsumed += 16; + pBuf += 16; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->rsvd ), pSrc->num_rsvd); + *pnConsumed += pSrc->num_rsvd; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeHTInfo. */ + +tANI_U32 dot11fPackIeIBSSParams(tpAniSirGlobal pCtx, + tDot11fIEIBSSParams *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 6; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->atim, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeIBSSParams. */ + +tANI_U32 dot11fPackIeLinkIdentifier(tpAniSirGlobal pCtx, + tDot11fIELinkIdentifier *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 18; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 101; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->bssid, 6); + *pnConsumed += 6; + pBuf += 6; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->InitStaAddr, 6); + *pnConsumed += 6; + pBuf += 6; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->RespStaAddr, 6); + *pnConsumed += 6; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeLinkIdentifier. */ + +tANI_U32 dot11fPackIeMeasurementReport(tpAniSirGlobal pCtx, + tDot11fIEMeasurementReport *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp114__; + tANI_U8 tmp115__; + tANI_U8 tmp116__; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEMeasurementReport(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 39; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->token; + *pnConsumed += 1; + pBuf += 1; + tmp114__ = 0U; + tmp114__ |= ( pSrc->late << 0 ); + tmp114__ |= ( pSrc->incapable << 1 ); + tmp114__ |= ( pSrc->refused << 2 ); + tmp114__ |= ( pSrc->unused << 3 ); + *pBuf = tmp114__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + *pBuf = pSrc->type; + *pnConsumed += 1; + pBuf += 1; + if ( pSrc->type ) { + switch (pSrc->type) + { + case 0: + *pBuf = pSrc->report.Basic.channel; + *pnConsumed += 1; + pBuf += 1; + frameshtonq(pCtx, pBuf, pSrc->report.Basic.meas_start_time, 0); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->report.Basic.meas_duration, 0); + *pnConsumed += 2; + pBuf += 2; + tmp115__ = 0U; + tmp115__ |= ( pSrc->report.Basic.bss << 0 ); + tmp115__ |= ( pSrc->report.Basic.ofdm_preamble << 1 ); + tmp115__ |= ( pSrc->report.Basic.unid_signal << 2 ); + tmp115__ |= ( pSrc->report.Basic.rader << 3 ); + tmp115__ |= ( pSrc->report.Basic.unmeasured << 4 ); + tmp115__ |= ( pSrc->report.Basic.unused << 5 ); + *pBuf = tmp115__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + case 1: + *pBuf = pSrc->report.CCA.channel; + *pnConsumed += 1; + pBuf += 1; + frameshtonq(pCtx, pBuf, pSrc->report.CCA.meas_start_time, 0); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->report.CCA.meas_duration, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->report.CCA.cca_busy_fraction; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + case 2: + *pBuf = pSrc->report.RPIHistogram.channel; + *pnConsumed += 1; + pBuf += 1; + frameshtonq(pCtx, pBuf, pSrc->report.RPIHistogram.meas_start_time, 0); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->report.RPIHistogram.meas_duration, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->report.RPIHistogram.rpi0_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi1_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi2_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi3_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi4_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi5_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi6_density; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.RPIHistogram.rpi7_density; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + case 5: + *pBuf = pSrc->report.Beacon.regClass; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.Beacon.channel; + *pnConsumed += 1; + pBuf += 1; + frameshtonq(pCtx, pBuf, pSrc->report.Beacon.meas_start_time, 0); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->report.Beacon.meas_duration, 0); + *pnConsumed += 2; + pBuf += 2; + tmp116__ = 0U; + tmp116__ |= ( pSrc->report.Beacon.condensed_PHY << 0 ); + tmp116__ |= ( pSrc->report.Beacon.reported_frame_type << 7 ); + *pBuf = tmp116__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + *pBuf = pSrc->report.Beacon.RCPI; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->report.Beacon.RSNI; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->report.Beacon.BSSID, 6); + *pnConsumed += 6; + pBuf += 6; + *pBuf = pSrc->report.Beacon.antenna_id; + *pnConsumed += 1; + pBuf += 1; + frameshtonl(pCtx, pBuf, pSrc->report.Beacon.parent_TSF, 0); + *pnConsumed += 4; + pBuf += 4; + status = PackCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_reportBeacon, + IES_reportBeacon); + break; + } + } + else break; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeMeasurementReport. */ + +tANI_U32 dot11fPackIeMeasurementRequest(tpAniSirGlobal pCtx, + tDot11fIEMeasurementRequest *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp117__; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEMeasurementRequest(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 38; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->measurement_token; + *pnConsumed += 1; + pBuf += 1; + tmp117__ = 0U; + tmp117__ |= ( pSrc->parallel << 0 ); + tmp117__ |= ( pSrc->enable << 1 ); + tmp117__ |= ( pSrc->request << 2 ); + tmp117__ |= ( pSrc->report << 3 ); + tmp117__ |= ( pSrc->durationMandatory << 4 ); + tmp117__ |= ( pSrc->unused << 5 ); + *pBuf = tmp117__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + *pBuf = pSrc->measurement_type; + *pnConsumed += 1; + pBuf += 1; + switch (pSrc->measurement_type) + { + case 0: + *pBuf = pSrc->measurement_request.Basic.channel_no; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->measurement_request.Basic.meas_start_time, 8); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->measurement_request.Basic.meas_duration, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + case 1: + *pBuf = pSrc->measurement_request.CCA.channel_no; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->measurement_request.CCA.meas_start_time, 8); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->measurement_request.CCA.meas_duration, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + case 2: + *pBuf = pSrc->measurement_request.RPIHistogram.channel_no; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->measurement_request.RPIHistogram.meas_start_time, 8); + *pnConsumed += 8; + pBuf += 8; + frameshtons(pCtx, pBuf, pSrc->measurement_request.RPIHistogram.meas_duration, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + case 5: + *pBuf = pSrc->measurement_request.Beacon.regClass; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->measurement_request.Beacon.channel; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->measurement_request.Beacon.randomization, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->measurement_request.Beacon.meas_duration, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->measurement_request.Beacon.meas_mode; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->measurement_request.Beacon.BSSID, 6); + *pnConsumed += 6; + pBuf += 6; + status = PackCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_measurement_requestBeacon, + IES_measurement_requestBeacon); + break; + } + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeMeasurementRequest. */ + +tANI_U32 dot11fPackIeMobilityDomain(tpAniSirGlobal pCtx, + tDot11fIEMobilityDomain *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp118__; + nNeeded += 3; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 54; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->MDID, 0); + *pnConsumed += 2; + pBuf += 2; + tmp118__ = 0U; + tmp118__ |= ( pSrc->overDSCap << 0 ); + tmp118__ |= ( pSrc->resourceReqCap << 1 ); + tmp118__ |= ( pSrc->reserved << 2 ); + *pBuf = tmp118__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeMobilityDomain. */ + +tANI_U32 dot11fPackIeNeighborReport(tpAniSirGlobal pCtx, + tDot11fIENeighborReport *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp119__; + tANI_U8 tmp120__; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIENeighborReport(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 52; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->bssid, 6); + *pnConsumed += 6; + pBuf += 6; + tmp119__ = 0U; + tmp119__ |= ( pSrc->APReachability << 0 ); + tmp119__ |= ( pSrc->Security << 2 ); + tmp119__ |= ( pSrc->KeyScope << 3 ); + tmp119__ |= ( pSrc->SpecMgmtCap << 4 ); + tmp119__ |= ( pSrc->QosCap << 5 ); + tmp119__ |= ( pSrc->apsd << 6 ); + tmp119__ |= ( pSrc->rrm << 7 ); + *pBuf = tmp119__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp120__ = 0U; + tmp120__ |= ( pSrc->DelayedBA << 0 ); + tmp120__ |= ( pSrc->ImmBA << 1 ); + tmp120__ |= ( pSrc->MobilityDomain << 2 ); + tmp120__ |= ( pSrc->reserved << 3 ); + *pBuf = tmp120__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->reserved1, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->regulatoryClass; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->channel; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->PhyType; + *pnConsumed += 1; + pBuf += 1; + status = PackCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_NeighborReport, + IES_NeighborReport); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeNeighborReport. */ + +tANI_U32 dot11fPackIeOBSSScanParameters(tpAniSirGlobal pCtx, + tDot11fIEOBSSScanParameters *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 14; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 74; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->obssScanPassiveDwell, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->obssScanActiveDwell, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->bssChannelWidthTriggerScanInterval, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->obssScanPassiveTotalPerChannel, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->obssScanActiveTotalPerChannel, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->bssWidthChannelTransitionDelayFactor, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->obssScanActivityThreshold, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeOBSSScanParameters. */ + +tANI_U32 dot11fPackIeOperatingMode(tpAniSirGlobal pCtx, + tDot11fIEOperatingMode *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp121__; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 199; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp121__ = 0U; + tmp121__ |= ( pSrc->chanWidth << 0 ); + tmp121__ |= ( pSrc->reserved << 2 ); + tmp121__ |= ( pSrc->rxNSS << 4 ); + tmp121__ |= ( pSrc->rxNSSType << 7 ); + *pBuf = tmp121__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeOperatingMode. */ + +tANI_U32 dot11fPackIeP2PAssocReq(tpAniSirGlobal pCtx, + tDot11fIEP2PAssocReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PAssocReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PAssocReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PAssocReq. */ + +tANI_U32 dot11fPackIeP2PAssocRes(tpAniSirGlobal pCtx, + tDot11fIEP2PAssocRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PAssocRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PAssocRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PAssocRes. */ + +tANI_U32 dot11fPackIeP2PBeacon(tpAniSirGlobal pCtx, + tDot11fIEP2PBeacon *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PBeacon(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PBeacon+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PBeacon. */ + +tANI_U32 dot11fPackIeP2PBeaconProbeRes(tpAniSirGlobal pCtx, + tDot11fIEP2PBeaconProbeRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PBeaconProbeRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PBeaconProbeRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PBeaconProbeRes. */ + +tANI_U32 dot11fPackIeP2PDeAuth(tpAniSirGlobal pCtx, + tDot11fIEP2PDeAuth *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PDeAuth(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PDeAuth+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PDeAuth. */ + +tANI_U32 dot11fPackIeP2PDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, + tDot11fIEP2PDeviceDiscoverabilityReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PDeviceDiscoverabilityReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PDeviceDiscoverabilityReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PDeviceDiscoverabilityReq. */ + +tANI_U32 dot11fPackIeP2PDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, + tDot11fIEP2PDeviceDiscoverabilityRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PDeviceDiscoverabilityRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PDeviceDiscoverabilityRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PDeviceDiscoverabilityRes. */ + +tANI_U32 dot11fPackIeP2PDisAssoc(tpAniSirGlobal pCtx, + tDot11fIEP2PDisAssoc *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PDisAssoc(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PDisAssoc+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PDisAssoc. */ + +tANI_U32 dot11fPackIeP2PGONegCnf(tpAniSirGlobal pCtx, + tDot11fIEP2PGONegCnf *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PGONegCnf(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PGONegCnf+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PGONegCnf. */ + +tANI_U32 dot11fPackIeP2PGONegReq(tpAniSirGlobal pCtx, + tDot11fIEP2PGONegReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PGONegReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PGONegReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PGONegReq. */ + +tANI_U32 dot11fPackIeP2PGONegRes(tpAniSirGlobal pCtx, + tDot11fIEP2PGONegRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PGONegRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PGONegRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PGONegRes. */ + +tANI_U32 dot11fPackIeP2PGONegWPS(tpAniSirGlobal pCtx, + tDot11fIEP2PGONegWPS *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PGONegWPS(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PGONegWPS+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PGONegWPS. */ + +tANI_U32 dot11fPackIeP2PIEOpaque(tpAniSirGlobal pCtx, + tDot11fIEP2PIEOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + 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 = 0x9; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeP2PIEOpaque. */ + +tANI_U32 dot11fPackIeP2PInvitationReq(tpAniSirGlobal pCtx, + tDot11fIEP2PInvitationReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PInvitationReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PInvitationReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PInvitationReq. */ + +tANI_U32 dot11fPackIeP2PInvitationRes(tpAniSirGlobal pCtx, + tDot11fIEP2PInvitationRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PInvitationRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PInvitationRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PInvitationRes. */ + +tANI_U32 dot11fPackIeP2PNoticeOfAbsence(tpAniSirGlobal pCtx, + tDot11fIEP2PNoticeOfAbsence *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PNoticeOfAbsence(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PNoticeOfAbsence+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PNoticeOfAbsence. */ + +tANI_U32 dot11fPackIeP2PPresenceResponse(tpAniSirGlobal pCtx, + tDot11fIEP2PPresenceResponse *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PPresenceResponse(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PPresenceResponse+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PPresenceResponse. */ + +tANI_U32 dot11fPackIeP2PProbeReq(tpAniSirGlobal pCtx, + tDot11fIEP2PProbeReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PProbeReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PProbeReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PProbeReq. */ + +tANI_U32 dot11fPackIeP2PProbeRes(tpAniSirGlobal pCtx, + tDot11fIEP2PProbeRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PProbeRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PProbeRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PProbeRes. */ + +tANI_U32 dot11fPackIeP2PProvisionDiscoveryReq(tpAniSirGlobal pCtx, + tDot11fIEP2PProvisionDiscoveryReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PProvisionDiscoveryReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x9; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PProvisionDiscoveryReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PProvisionDiscoveryReq. */ + +tANI_U32 dot11fPackIeP2PWSCProvisionDiscoveryRes(tpAniSirGlobal pCtx, + tDot11fIEP2PWSCProvisionDiscoveryRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEP2PWSCProvisionDiscoveryRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_P2PWSCProvisionDiscoveryRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeP2PWSCProvisionDiscoveryRes. */ + +tANI_U32 dot11fPackIePTIControl(tpAniSirGlobal pCtx, + tDot11fIEPTIControl *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 3; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 105; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->tid; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->sequence_control, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIePTIControl. */ + +tANI_U32 dot11fPackIePUBufferStatus(tpAniSirGlobal pCtx, + tDot11fIEPUBufferStatus *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp122__; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 106; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp122__ = 0U; + tmp122__ |= ( pSrc->ac_bk_traffic_aval << 0 ); + tmp122__ |= ( pSrc->ac_be_traffic_aval << 1 ); + tmp122__ |= ( pSrc->ac_vi_traffic_aval << 2 ); + tmp122__ |= ( pSrc->ac_vo_traffic_aval << 3 ); + tmp122__ |= ( pSrc->reserved << 4 ); + *pBuf = tmp122__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIePUBufferStatus. */ + +tANI_U32 dot11fPackIePowerCaps(tpAniSirGlobal pCtx, + tDot11fIEPowerCaps *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 33; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->minTxPower; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->maxTxPower; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIePowerCaps. */ + +tANI_U32 dot11fPackIePowerConstraints(tpAniSirGlobal pCtx, + tDot11fIEPowerConstraints *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 32; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->localPowerConstraints; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIePowerConstraints. */ + +tANI_U32 dot11fPackIeQBSSLoad(tpAniSirGlobal pCtx, + tDot11fIEQBSSLoad *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 11; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->stacount, 0); + *pnConsumed += 2; + pBuf += 2; + *pBuf = pSrc->chautil; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->avail, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeQBSSLoad. */ + +tANI_U32 dot11fPackIeQComVendorIE(tpAniSirGlobal pCtx, + tDot11fIEQComVendorIE *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xa0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xc6; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->type; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->channel; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeQComVendorIE. */ + +tANI_U32 dot11fPackIeQOSCapsAp(tpAniSirGlobal pCtx, + tDot11fIEQOSCapsAp *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp123__; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 46; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp123__ = 0U; + tmp123__ |= ( pSrc->count << 0 ); + tmp123__ |= ( pSrc->qack << 4 ); + tmp123__ |= ( pSrc->qreq << 5 ); + tmp123__ |= ( pSrc->txopreq << 6 ); + tmp123__ |= ( pSrc->reserved << 7 ); + *pBuf = tmp123__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeQOSCapsAp. */ + +tANI_U32 dot11fPackIeQOSCapsStation(tpAniSirGlobal pCtx, + tDot11fIEQOSCapsStation *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp124__; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 46; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp124__ = 0U; + tmp124__ |= ( pSrc->acvo_uapsd << 0 ); + tmp124__ |= ( pSrc->acvi_uapsd << 1 ); + tmp124__ |= ( pSrc->acbk_uapsd << 2 ); + tmp124__ |= ( pSrc->acbe_uapsd << 3 ); + tmp124__ |= ( pSrc->qack << 4 ); + tmp124__ |= ( pSrc->max_sp_length << 5 ); + tmp124__ |= ( pSrc->more_data_ack << 7 ); + *pBuf = tmp124__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeQOSCapsStation. */ + +tANI_U32 dot11fPackIeQosMapSet(tpAniSirGlobal pCtx, + tDot11fIEQosMapSet *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_dscp_exceptions; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 110; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->dscp_exceptions ), pSrc->num_dscp_exceptions); + *pnConsumed += pSrc->num_dscp_exceptions; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeQosMapSet. */ + +tANI_U32 dot11fPackIeQuiet(tpAniSirGlobal pCtx, + tDot11fIEQuiet *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 6; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 40; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->count; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->period; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->duration, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->offset, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeQuiet. */ + +tANI_U32 dot11fPackIeRCPIIE(tpAniSirGlobal pCtx, + tDot11fIERCPIIE *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 53; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->rcpi; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRCPIIE. */ + +tANI_U32 dot11fPackIeRICDataDesc(tpAniSirGlobal pCtx, + tDot11fIERICDataDesc *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIERICDataDesc(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + status = PackCore(pCtx, + (tANI_U8*)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_RICDataDesc, + IES_RICDataDesc); + break; + } + (void)pCtx; + return status; +} /* End dot11fPackIeRICDataDesc. */ + +tANI_U32 dot11fPackIeRSN(tpAniSirGlobal pCtx, + tDot11fIERSN *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIERSN(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 48; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->version, 0); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->gp_cipher_suite, 4); + *pnConsumed += 4; + pBuf += 4; + if ( pSrc->pwise_cipher_suite_count ) { + frameshtons(pCtx, pBuf, pSrc->pwise_cipher_suite_count, 0); + *pnConsumed += 2; + pBuf += 2; + } + else break; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->pwise_cipher_suites ), ( pSrc->pwise_cipher_suite_count * 4 )); + *pnConsumed += ( pSrc->pwise_cipher_suite_count * 4 ); + pBuf += ( pSrc->pwise_cipher_suite_count * 4 ); + if ( pSrc->akm_suite_count ) { + frameshtons(pCtx, pBuf, pSrc->akm_suite_count, 0); + *pnConsumed += 2; + pBuf += 2; + } + else break; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->akm_suites ), ( pSrc->akm_suite_count * 4 )); + *pnConsumed += ( pSrc->akm_suite_count * 4 ); + pBuf += ( pSrc->akm_suite_count * 4 ); + if ( pSrc->RSN_Cap ) { + DOT11F_MEMCPY(pCtx, pBuf, pSrc->RSN_Cap, 2); + *pnConsumed += 2; + pBuf += 2; + } + else break; + if ( pSrc->pmkid_count ) { + frameshtons(pCtx, pBuf, pSrc->pmkid_count, 0); + *pnConsumed += 2; + pBuf += 2; + } + else break; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->pmkid ), ( pSrc->pmkid_count * 16 )); + *pnConsumed += ( pSrc->pmkid_count * 16 ); + pBuf += ( pSrc->pmkid_count * 16 ); + if ( pSrc->gp_mgmt_cipher_suite ) { + DOT11F_MEMCPY(pCtx, pBuf, pSrc->gp_mgmt_cipher_suite, 4); + *pnConsumed += 4; + // fieldsEndFlag = 1 + } + else break; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeRSN. */ + +tANI_U32 dot11fPackIeRSNIIE(tpAniSirGlobal pCtx, + tDot11fIERSNIIE *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 65; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->rsni; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRSNIIE. */ + +tANI_U32 dot11fPackIeRSNOpaque(tpAniSirGlobal pCtx, + tDot11fIERSNOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 48; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeRSNOpaque. */ + +tANI_U32 dot11fPackIeSuppChannels(tpAniSirGlobal pCtx, + tDot11fIESuppChannels *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_bands * 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 36; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->bands ), ( pSrc->num_bands * 2 )); + *pnConsumed += ( pSrc->num_bands * 2 ); + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeSuppChannels. */ + +tANI_U32 dot11fPackIeSuppOperatingClasses(tpAniSirGlobal pCtx, + tDot11fIESuppOperatingClasses *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_classes; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 59; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->classes ), pSrc->num_classes); + *pnConsumed += pSrc->num_classes; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeSuppOperatingClasses. */ + +tANI_U32 dot11fPackIeSuppRates(tpAniSirGlobal pCtx, + tDot11fIESuppRates *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_rates; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 1; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->rates ), pSrc->num_rates); + *pnConsumed += pSrc->num_rates; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeSuppRates. */ + +tANI_U32 dot11fPackIeTIM(tpAniSirGlobal pCtx, + tDot11fIETIM *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += (pSrc->num_vbmp + 3); + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 5; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->dtim_count; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->dtim_period; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->bmpctl; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->vbmp ), pSrc->num_vbmp); + *pnConsumed += pSrc->num_vbmp; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTIM. */ + +tANI_U32 dot11fPackIeTPCReport(tpAniSirGlobal pCtx, + tDot11fIETPCReport *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 35; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->tx_power; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->link_margin; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTPCReport. */ + +tANI_U32 dot11fPackIeTPCRequest(tpAniSirGlobal pCtx, + tDot11fIETPCRequest *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 0; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 34; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTPCRequest. */ + +tANI_U32 dot11fPackIeTimeAdvertisement(tpAniSirGlobal pCtx, + tDot11fIETimeAdvertisement *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 16; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 69; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->timing_capabilities; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->time_value, 10); + *pnConsumed += 10; + pBuf += 10; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->time_error, 5); + *pnConsumed += 5; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTimeAdvertisement. */ + +tANI_U32 dot11fPackIeTimeoutInterval(tpAniSirGlobal pCtx, + tDot11fIETimeoutInterval *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 56; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->timeoutType; + *pnConsumed += 1; + pBuf += 1; + frameshtonl(pCtx, pBuf, pSrc->timeoutValue, 0); + *pnConsumed += 4; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeTimeoutInterval. */ + +tANI_U32 dot11fPackIeVHTCaps(tpAniSirGlobal pCtx, + tDot11fIEVHTCaps *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 tmp125__; + tANI_U16 tmp126__; + tANI_U16 tmp127__; + nNeeded += 12; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 191; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp125__ = 0U; + tmp125__ |= ( pSrc->maxMPDULen << 0 ); + tmp125__ |= ( pSrc->supportedChannelWidthSet << 2 ); + tmp125__ |= ( pSrc->ldpcCodingCap << 4 ); + tmp125__ |= ( pSrc->shortGI80MHz << 5 ); + tmp125__ |= ( pSrc->shortGI160and80plus80MHz << 6 ); + tmp125__ |= ( pSrc->txSTBC << 7 ); + tmp125__ |= ( pSrc->rxSTBC << 8 ); + tmp125__ |= ( pSrc->suBeamFormerCap << 11 ); + tmp125__ |= ( pSrc->suBeamformeeCap << 12 ); + tmp125__ |= ( pSrc->csnofBeamformerAntSup << 13 ); + tmp125__ |= ( pSrc->numSoundingDim << 16 ); + tmp125__ |= ( pSrc->muBeamformerCap << 19 ); + tmp125__ |= ( pSrc->muBeamformeeCap << 20 ); + tmp125__ |= ( pSrc->vhtTXOPPS << 21 ); + tmp125__ |= ( pSrc->htcVHTCap << 22 ); + tmp125__ |= ( pSrc->maxAMPDULenExp << 23 ); + tmp125__ |= ( pSrc->vhtLinkAdaptCap << 26 ); + tmp125__ |= ( pSrc->rxAntPattern << 28 ); + tmp125__ |= ( pSrc->txAntPattern << 29 ); + tmp125__ |= ( pSrc->reserved1 << 30 ); + frameshtonl(pCtx, pBuf, tmp125__, 0); + *pnConsumed += 4; + pBuf += 4; + nBuf -= 4 ; + frameshtons(pCtx, pBuf, pSrc->rxMCSMap, 0); + *pnConsumed += 2; + pBuf += 2; + tmp126__ = 0U; + tmp126__ |= ( pSrc->rxHighSupDataRate << 0 ); + tmp126__ |= ( pSrc->reserved2 << 13 ); + frameshtons(pCtx, pBuf, tmp126__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + frameshtons(pCtx, pBuf, pSrc->txMCSMap, 0); + *pnConsumed += 2; + pBuf += 2; + tmp127__ = 0U; + tmp127__ |= ( pSrc->txSupDataRate << 0 ); + tmp127__ |= ( pSrc->reserved3 << 13 ); + frameshtons(pCtx, pBuf, tmp127__, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + nBuf -= 2 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeVHTCaps. */ + +tANI_U32 dot11fPackIeVHTExtBssLoad(tpAniSirGlobal pCtx, + tDot11fIEVHTExtBssLoad *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 193; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->muMIMOCapStaCount; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->ssUnderUtil; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->FortyMHzUtil; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->EightyMHzUtil; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->OneSixtyMHzUtil; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeVHTExtBssLoad. */ + +tANI_U32 dot11fPackIeVHTOperation(tpAniSirGlobal pCtx, + tDot11fIEVHTOperation *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 5; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 192; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->chanWidth; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->chanCenterFreqSeg1; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->chanCenterFreqSeg2; + *pnConsumed += 1; + pBuf += 1; + frameshtons(pCtx, pBuf, pSrc->basicMCSSet, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeVHTOperation. */ + +tANI_U32 dot11fPackIeVendor1IE(tpAniSirGlobal pCtx, + tDot11fIEVendor1IE *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 0; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x10; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x18; + ++pBuf; ++(*pnConsumed); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeVendor1IE. */ + +tANI_U32 dot11fPackIeVendor2IE(tpAniSirGlobal pCtx, + tDot11fIEVendor2IE *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 0; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x90; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x4c; + ++pBuf; ++(*pnConsumed); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeVendor2IE. */ + +tANI_U32 dot11fPackIeVendor3IE(tpAniSirGlobal pCtx, + tDot11fIEVendor3IE *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 0; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x16; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x32; + ++pBuf; ++(*pnConsumed); + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeVendor3IE. */ + +tANI_U32 dot11fPackIeWAPI(tpAniSirGlobal pCtx, + tDot11fIEWAPI *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U16 tmp128__; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEWAPI(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 68; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->version, 0); + *pnConsumed += 2; + pBuf += 2; + frameshtons(pCtx, pBuf, pSrc->akm_suite_count, 0); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->akm_suites ), ( pSrc->akm_suite_count * 4 )); + *pnConsumed += ( pSrc->akm_suite_count * 4 ); + pBuf += ( pSrc->akm_suite_count * 4 ); + frameshtons(pCtx, pBuf, pSrc->unicast_cipher_suite_count, 0); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->unicast_cipher_suites ), ( pSrc->unicast_cipher_suite_count * 4 )); + *pnConsumed += ( pSrc->unicast_cipher_suite_count * 4 ); + pBuf += ( pSrc->unicast_cipher_suite_count * 4 ); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->multicast_cipher_suite, 4); + *pnConsumed += 4; + pBuf += 4; + tmp128__ = 0U; + tmp128__ |= ( pSrc->preauth << 0 ); + tmp128__ |= ( pSrc->reserved << 1 ); + frameshtons(pCtx, pBuf, tmp128__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + if ( pSrc->bkid_count ) { + frameshtons(pCtx, pBuf, pSrc->bkid_count, 0); + *pnConsumed += 2; + pBuf += 2; + } + else break; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->bkid ), ( pSrc->bkid_count * 16 )); + *pnConsumed += ( pSrc->bkid_count * 16 ); + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeWAPI. */ + +tANI_U32 dot11fPackIeWAPIOpaque(tpAniSirGlobal pCtx, + tDot11fIEWAPIOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 68; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWAPIOpaque. */ + +tANI_U32 dot11fPackIeWFATPC(tpAniSirGlobal pCtx, + tDot11fIEWFATPC *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x8; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->txPower; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->linkMargin; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWFATPC. */ + +tANI_U32 dot11fPackIeWFDIEOpaque(tpAniSirGlobal pCtx, + tDot11fIEWFDIEOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + 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 = 0xa; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWFDIEOpaque. */ + +tANI_U32 dot11fPackIeWMMCaps(tpAniSirGlobal pCtx, + tDot11fIEWMMCaps *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp129__; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x5; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + tmp129__ = 0U; + tmp129__ |= ( pSrc->reserved << 0 ); + tmp129__ |= ( pSrc->qack << 4 ); + tmp129__ |= ( pSrc->queue_request << 5 ); + tmp129__ |= ( pSrc->txop_request << 6 ); + tmp129__ |= ( pSrc->more_ack << 7 ); + *pBuf = tmp129__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMCaps. */ + +tANI_U32 dot11fPackIeWMMInfoAp(tpAniSirGlobal pCtx, + tDot11fIEWMMInfoAp *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp130__; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + tmp130__ = 0U; + tmp130__ |= ( pSrc->param_set_count << 0 ); + tmp130__ |= ( pSrc->reserved << 4 ); + tmp130__ |= ( pSrc->uapsd << 7 ); + *pBuf = tmp130__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMInfoAp. */ + +tANI_U32 dot11fPackIeWMMInfoStation(tpAniSirGlobal pCtx, + tDot11fIEWMMInfoStation *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp131__; + nNeeded += 2; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + tmp131__ = 0U; + tmp131__ |= ( pSrc->acvo_uapsd << 0 ); + tmp131__ |= ( pSrc->acvi_uapsd << 1 ); + tmp131__ |= ( pSrc->acbk_uapsd << 2 ); + tmp131__ |= ( pSrc->acbe_uapsd << 3 ); + tmp131__ |= ( pSrc->reserved1 << 4 ); + tmp131__ |= ( pSrc->max_sp_length << 5 ); + tmp131__ |= ( pSrc->reserved2 << 7 ); + *pBuf = tmp131__; + *pnConsumed += 1; + // fieldsEndFlag = 1 + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMInfoStation. */ + +tANI_U32 dot11fPackIeWMMParams(tpAniSirGlobal pCtx, + tDot11fIEWMMParams *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp132__; + tANI_U8 tmp133__; + tANI_U8 tmp134__; + tANI_U8 tmp135__; + tANI_U8 tmp136__; + tANI_U8 tmp137__; + tANI_U8 tmp138__; + tANI_U8 tmp139__; + nNeeded += 19; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x1; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->version; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->qosInfo; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->reserved2; + *pnConsumed += 1; + pBuf += 1; + tmp132__ = 0U; + tmp132__ |= ( pSrc->acbe_aifsn << 0 ); + tmp132__ |= ( pSrc->acbe_acm << 4 ); + tmp132__ |= ( pSrc->acbe_aci << 5 ); + tmp132__ |= ( pSrc->unused1 << 7 ); + *pBuf = tmp132__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp133__ = 0U; + tmp133__ |= ( pSrc->acbe_acwmin << 0 ); + tmp133__ |= ( pSrc->acbe_acwmax << 4 ); + *pBuf = tmp133__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp134__ = 0U; + tmp134__ |= ( pSrc->acbk_aifsn << 0 ); + tmp134__ |= ( pSrc->acbk_acm << 4 ); + tmp134__ |= ( pSrc->acbk_aci << 5 ); + tmp134__ |= ( pSrc->unused2 << 7 ); + *pBuf = tmp134__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp135__ = 0U; + tmp135__ |= ( pSrc->acbk_acwmin << 0 ); + tmp135__ |= ( pSrc->acbk_acwmax << 4 ); + *pBuf = tmp135__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp136__ = 0U; + tmp136__ |= ( pSrc->acvi_aifsn << 0 ); + tmp136__ |= ( pSrc->acvi_acm << 4 ); + tmp136__ |= ( pSrc->acvi_aci << 5 ); + tmp136__ |= ( pSrc->unused3 << 7 ); + *pBuf = tmp136__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp137__ = 0U; + tmp137__ |= ( pSrc->acvi_acwmin << 0 ); + tmp137__ |= ( pSrc->acvi_acwmax << 4 ); + *pBuf = tmp137__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp138__ = 0U; + tmp138__ |= ( pSrc->acvo_aifsn << 0 ); + tmp138__ |= ( pSrc->acvo_acm << 4 ); + tmp138__ |= ( pSrc->acvo_aci << 5 ); + tmp138__ |= ( pSrc->unused4 << 7 ); + *pBuf = tmp138__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp139__ = 0U; + tmp139__ |= ( pSrc->acvo_acwmin << 0 ); + tmp139__ |= ( pSrc->acvo_acwmax << 4 ); + *pBuf = tmp139__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWMMParams. */ + +tANI_U32 dot11fPackIeWPA(tpAniSirGlobal pCtx, + tDot11fIEWPA *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEWPA(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 = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x1; + ++pBuf; ++(*pnConsumed); + frameshtons(pCtx, pBuf, pSrc->version, 0); + *pnConsumed += 2; + pBuf += 2; + if ( pSrc->multicast_cipher_present ) { + DOT11F_MEMCPY(pCtx, pBuf, pSrc->multicast_cipher, 4); + *pnConsumed += 4; + pBuf += 4; + } + else break; + if ( pSrc->unicast_cipher_count ) { + frameshtons(pCtx, pBuf, pSrc->unicast_cipher_count, 0); + *pnConsumed += 2; + pBuf += 2; + } + else break; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->unicast_ciphers ), ( pSrc->unicast_cipher_count * 4 )); + *pnConsumed += ( pSrc->unicast_cipher_count * 4 ); + pBuf += ( pSrc->unicast_cipher_count * 4 ); + if ( pSrc->auth_suite_count ) { + frameshtons(pCtx, pBuf, pSrc->auth_suite_count, 0); + *pnConsumed += 2; + pBuf += 2; + } + else break; + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->auth_suites ), ( pSrc->auth_suite_count * 4 )); + *pnConsumed += ( pSrc->auth_suite_count * 4 ); + pBuf += ( pSrc->auth_suite_count * 4 ); + if ( pSrc->caps ) { + frameshtons(pCtx, pBuf, pSrc->caps, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + } + else break; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIeWPA. */ + +tANI_U32 dot11fPackIeWPAOpaque(tpAniSirGlobal pCtx, + tDot11fIEWPAOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x1; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWPAOpaque. */ + +tANI_U32 dot11fPackIeWSC(tpAniSirGlobal pCtx, + tDot11fIEWSC *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWSC(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WSC+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWSC. */ + +tANI_U32 dot11fPackIeWscAssocReq(tpAniSirGlobal pCtx, + tDot11fIEWscAssocReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscAssocReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscAssocReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscAssocReq. */ + +tANI_U32 dot11fPackIeWscAssocRes(tpAniSirGlobal pCtx, + tDot11fIEWscAssocRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscAssocRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscAssocRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscAssocRes. */ + +tANI_U32 dot11fPackIeWscBeacon(tpAniSirGlobal pCtx, + tDot11fIEWscBeacon *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscBeacon(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscBeacon+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscBeacon. */ + +tANI_U32 dot11fPackIeWscBeaconProbeRes(tpAniSirGlobal pCtx, + tDot11fIEWscBeaconProbeRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscBeaconProbeRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscBeaconProbeRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscBeaconProbeRes. */ + +tANI_U32 dot11fPackIeWscIEOpaque(tpAniSirGlobal pCtx, + tDot11fIEWscIEOpaque *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += pSrc->num_data; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, &( pSrc->data ), pSrc->num_data); + *pnConsumed += pSrc->num_data; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeWscIEOpaque. */ + +tANI_U32 dot11fPackIeWscProbeReq(tpAniSirGlobal pCtx, + tDot11fIEWscProbeReq *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscProbeReq(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscProbeReq+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscProbeReq. */ + +tANI_U32 dot11fPackIeWscProbeRes(tpAniSirGlobal pCtx, + tDot11fIEWscProbeRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscProbeRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscProbeRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscProbeRes. */ + +tANI_U32 dot11fPackIeWscReassocRes(tpAniSirGlobal pCtx, + tDot11fIEWscReassocRes *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 n, idx = 0,idxlast; + tANI_U32 nConsumedSoFar, nConsumedNow; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U32 nNeeded = 0U; + status = dot11fGetPackedIEWscReassocRes(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + (void)pCtx; + if (pSrc->present) { + do { + nConsumedSoFar=*pnConsumed; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0xf2; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4; + ++pBuf; --nBuf; ++(*pnConsumed); + n = ( 255 - 4) < nBuf ? ( 255 - 4) : nBuf; + nConsumedNow=*pnConsumed; + idxlast=idx; + status = PackTlvCore(pCtx,(tANI_U8*)pSrc,pBuf,n,pnConsumed,TLVS_WscReassocRes+idx,&idx); + nConsumedNow=*pnConsumed-nConsumedNow; + *pIeLen = *pnConsumed - nConsumedSoFar - 2; + pBuf+=nConsumedNow; + nBuf-=nConsumedNow; + } while (DOT11F_BUFFER_OVERFLOW == status && idxlast != idx); + } + return status; +} /* End dot11fPackIeWscReassocRes. */ + +tANI_U32 dot11fPackIeext_chan_switch_ann(tpAniSirGlobal pCtx, + tDot11fIEext_chan_switch_ann *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 4; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 60; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->switch_mode; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->new_reg_class; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->new_channel; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->switch_count; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeext_chan_switch_ann. */ + +tANI_U32 dot11fPackIesec_chan_offset_ele(tpAniSirGlobal pCtx, + tDot11fIEsec_chan_offset_ele *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 1; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 62; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->secondaryChannelOffset; + *pnConsumed += 1; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIesec_chan_offset_ele. */ + +tANI_U32 dot11fPackAddBAReq(tpAniSirGlobal pCtx, tDot11fAddBAReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_AddBAReq, IES_AddBAReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("Packed the AddBAReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("AddBAParameterSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("amsduSupported (1): %d\n"), pFrm->AddBAParameterSet.amsduSupported); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("policy (1): %d\n"), pFrm->AddBAParameterSet.policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("tid (4): %d\n"), pFrm->AddBAParameterSet.tid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("bufferSize (10): %d\n"), pFrm->AddBAParameterSet.bufferSize); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("BATimeout:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), ( tANI_U8* )&pFrm->BATimeout.timeout, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("BAStartingSequenceControl:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("fragNumber (4): %d\n"), pFrm->BAStartingSequenceControl.fragNumber); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("ssn (12): %d\n"), pFrm->BAStartingSequenceControl.ssn); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBAREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddBAReq. */ + +tANI_U32 dot11fPackAddBARsp(tpAniSirGlobal pCtx, tDot11fAddBARsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_AddBARsp, IES_AddBARsp); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Packed the AddBARsp:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("AddBAParameterSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("amsduSupported (1): %d\n"), pFrm->AddBAParameterSet.amsduSupported); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("policy (1): %d\n"), pFrm->AddBAParameterSet.policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("tid (4): %d\n"), pFrm->AddBAParameterSet.tid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("bufferSize (10): %d\n"), pFrm->AddBAParameterSet.bufferSize); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("BATimeout:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), ( tANI_U8* )&pFrm->BATimeout.timeout, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDBARSP), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddBARsp. */ + +tANI_U32 dot11fPackAddTSRequest(tpAniSirGlobal pCtx, tDot11fAddTSRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_AddTSRequest, IES_AddTSRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Packed the AddTSRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("TSPEC:\n")); + if (!pFrm->TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsid (4): %d\n"), pFrm->TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("direction (2): %d\n"), pFrm->TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("access_policy (2): %d\n"), pFrm->TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("aggregation (1): %d\n"), pFrm->TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("psb (1): %d\n"), pFrm->TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("user_priority (3): %d\n"), pFrm->TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("schedule (1): %d\n"), pFrm->TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("unused (7): %d\n"), pFrm->TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("size (15): %d\n"), pFrm->TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("fixed (1): %d\n"), pFrm->TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].classifier_mask, 1); + switch (pFrm->TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.version, 1); + switch (pFrm->TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("TCLASSPROC:\n")); + if (!pFrm->TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddTSRequest. */ + +tANI_U32 dot11fPackAddTSResponse(tpAniSirGlobal pCtx, tDot11fAddTSResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_AddTSResponse, IES_AddTSResponse); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Packed the AddTSResponse:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TSDelay:\n")); + if (!pFrm->TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TSPEC:\n")); + if (!pFrm->TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("psb (1): %d\n"), pFrm->TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("schedule (1): %d\n"), pFrm->TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("unused (7): %d\n"), pFrm->TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("size (15): %d\n"), pFrm->TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("fixed (1): %d\n"), pFrm->TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].classifier_mask, 1); + switch (pFrm->TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.version, 1); + switch (pFrm->TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("TCLASSPROC:\n")); + if (!pFrm->TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Schedule:\n")); + if (!pFrm->Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("reserved (9): %d\n"), pFrm->Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTSDelay:\n")); + if (!pFrm->WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMSchedule:\n")); + if (!pFrm->WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("reserved (9): %d\n"), pFrm->WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMSchedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ADDTSRESPONSE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAddTSResponse. */ + +tANI_U32 dot11fPackAssocRequest(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_AssocRequest, IES_AssocRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Packed the AssocRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ListenInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->ListenInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("PowerCaps:\n")); + if (!pFrm->PowerCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.minTxPower, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.maxTxPower, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.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("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.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("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WPAOpaque:\n")); + if (!pFrm->WPAOpaque.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("num_data: %d.\n"), pFrm->WPAOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WPAOpaque.data, pFrm->WPAOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WscIEOpaque:\n")); + if (!pFrm->WscIEOpaque.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("num_data: %d.\n"), pFrm->WscIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WscIEOpaque.data, pFrm->WscIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WAPIOpaque:\n")); + if (!pFrm->WAPIOpaque.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("num_data: %d.\n"), pFrm->WAPIOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPIOpaque.data, pFrm->WAPIOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("P2PIEOpaque:\n")); + if (!pFrm->P2PIEOpaque.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("num_data: %d.\n"), pFrm->P2PIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->P2PIEOpaque.data, pFrm->P2PIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("WFDIEOpaque:\n")); + if (!pFrm->WFDIEOpaque.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("num_data: %d.\n"), pFrm->WFDIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->WFDIEOpaque.data, pFrm->WFDIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.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("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("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAssocRequest. */ + +tANI_U32 dot11fPackAssocResponse(tpAniSirGlobal pCtx, tDot11fAssocResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_AssocResponse, IES_AssocResponse); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Packed the AssocResponse:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("AID:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->AID.associd, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RCPIIE:\n")); + if (!pFrm->RCPIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RCPIIE.rcpi, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RSNIIE:\n")); + if (!pFrm->RSNIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RSNIIE.rsni, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + for (i = 0; i < pFrm->num_WMMTSPEC; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WMMTSPEC[%d]:\n"), i); + if (!pFrm->WMMTSPEC[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC[i].traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC[i].tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC[i].direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC[i].access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC[i].aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC[i].psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC[i].user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC[i].tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC[i].tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC[i].burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC[i].size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC[i].fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].medium_time, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("WscAssocRes:\n")); + if (!pFrm->WscAssocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Version:\n")); + if (!pFrm->WscAssocRes.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscAssocRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscAssocRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ResponseType:\n")); + if (!pFrm->WscAssocRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("VendorExtension:\n")); + if (!pFrm->WscAssocRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Version2:\n")); + if (!pFrm->WscAssocRes.VendorExtension.Version2.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscAssocRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscAssocRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscAssocRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscAssocRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->WscAssocRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("P2PAssocRes:\n")); + if (!pFrm->P2PAssocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("P2PStatus:\n")); + if (!pFrm->P2PAssocRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PAssocRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityInterval, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAssocResponse. */ + +tANI_U32 dot11fPackAuthentication(tpAniSirGlobal pCtx, tDot11fAuthentication *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_Authentication, IES_Authentication); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Packed the Authentication:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("AuthAlgo:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->AuthAlgo.algo, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("AuthSeqNo:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->AuthSeqNo.no, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("ChallengeText:\n")); + if (!pFrm->ChallengeText.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_text: %d.\n"), pFrm->ChallengeText.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->ChallengeText.text, pFrm->ChallengeText.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackAuthentication. */ + +tANI_U32 dot11fPackBeacon(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_Beacon, IES_Beacon); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Packed the Beacon:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->BeaconInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FHParamSet:\n")); + if (!pFrm->FHParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.dwell_time, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.hop_set, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.hop_pattern, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParamSet.hop_index, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("CFParams:\n")); + if (!pFrm->CFParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_maxduration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->CFParams.cfp_durremaining, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TIM:\n")); + if (!pFrm->TIM.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TIM.dtim_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TIM.dtim_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TIM.bmpctl, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_vbmp: %d.\n"), pFrm->TIM.num_vbmp); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->TIM.vbmp, pFrm->TIM.num_vbmp); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FHParams:\n")); + if (!pFrm->FHParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParams.radix, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHParams.nchannels, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FHPattTable:\n")); + if (!pFrm->FHPattTable.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.flag, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.nsets, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.modulus, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->FHPattTable.offset, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_randtable: %d.\n"), pFrm->FHPattTable.num_randtable); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->FHPattTable.randtable, pFrm->FHPattTable.num_randtable); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("QBSSLoad:\n")); + if (!pFrm->QBSSLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QBSSLoad.stacount, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QBSSLoad.chautil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QBSSLoad.avail, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("QOSCapsAp:\n")); + if (!pFrm->QOSCapsAp.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("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WscBeacon:\n")); + if (!pFrm->WscBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Version:\n")); + if (!pFrm->WscBeacon.Version.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("minor (4): %d\n"), pFrm->WscBeacon.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("major (4): %d\n"), pFrm->WscBeacon.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WPSState:\n")); + if (!pFrm->WscBeacon.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APSetupLocked:\n")); + if (!pFrm->WscBeacon.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscBeacon.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscBeacon.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscBeacon.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("UUID_E:\n")); + if (!pFrm->WscBeacon.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RFBands:\n")); + if (!pFrm->WscBeacon.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VendorExtension:\n")); + if (!pFrm->WscBeacon.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Version2:\n")); + if (!pFrm->WscBeacon.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("major (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscBeacon.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscBeacon.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("P2PBeacon:\n")); + if (!pFrm->P2PBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("P2PCapability:\n")); + if (!pFrm->P2PBeacon.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PBeacon.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PBeacon.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("num_NoADesc: %d.\n"), pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->P2PBeacon.NoticeOfAbsence.NoADesc, pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + 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); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeacon. */ + +tANI_U32 dot11fPackBeacon1(tpAniSirGlobal pCtx, tDot11fBeacon1 *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_Beacon1, IES_Beacon1); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Packed the Beacon1:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("BeaconInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->BeaconInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("SSID:\n")); + if (!pFrm->SSID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON1), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeacon1. */ + +tANI_U32 dot11fPackBeacon2(tpAniSirGlobal pCtx, tDot11fBeacon2 *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_Beacon2, IES_Beacon2); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Packed the Beacon2:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WscBeacon:\n")); + if (!pFrm->WscBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Version:\n")); + if (!pFrm->WscBeacon.Version.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("minor (4): %d\n"), pFrm->WscBeacon.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("major (4): %d\n"), pFrm->WscBeacon.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WPSState:\n")); + if (!pFrm->WscBeacon.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("APSetupLocked:\n")); + if (!pFrm->WscBeacon.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscBeacon.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscBeacon.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscBeacon.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("UUID_E:\n")); + if (!pFrm->WscBeacon.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RFBands:\n")); + if (!pFrm->WscBeacon.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VendorExtension:\n")); + if (!pFrm->WscBeacon.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Version2:\n")); + if (!pFrm->WscBeacon.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("major (4): %d\n"), pFrm->WscBeacon.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscBeacon.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscBeacon.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WscBeacon.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("P2PBeacon:\n")); + if (!pFrm->P2PBeacon.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("P2PCapability:\n")); + if (!pFrm->P2PBeacon.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PBeacon.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PBeacon.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->P2PBeacon.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("num_NoADesc: %d.\n"), pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->P2PBeacon.NoticeOfAbsence.NoADesc, pFrm->P2PBeacon.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + 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); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeacon2. */ + +tANI_U32 dot11fPackBeaconIEs(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_BeaconIEs, IES_BeaconIEs); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Packed the BeaconIEs:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FHParamSet:\n")); + if (!pFrm->FHParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.dwell_time, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.hop_set, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.hop_pattern, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParamSet.hop_index, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("CFParams:\n")); + if (!pFrm->CFParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_maxduration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->CFParams.cfp_durremaining, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("TIM:\n")); + if (!pFrm->TIM.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TIM.dtim_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TIM.dtim_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TIM.bmpctl, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_vbmp: %d.\n"), pFrm->TIM.num_vbmp); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->TIM.vbmp, pFrm->TIM.num_vbmp); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FHParams:\n")); + if (!pFrm->FHParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParams.radix, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHParams.nchannels, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FHPattTable:\n")); + if (!pFrm->FHPattTable.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.flag, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.nsets, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.modulus, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->FHPattTable.offset, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_randtable: %d.\n"), pFrm->FHPattTable.num_randtable); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->FHPattTable.randtable, pFrm->FHPattTable.num_randtable); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("QBSSLoad:\n")); + if (!pFrm->QBSSLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QBSSLoad.stacount, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QBSSLoad.chautil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QBSSLoad.avail, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("QOSCapsAp:\n")); + if (!pFrm->QOSCapsAp.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("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WscBeaconProbeRes:\n")); + if (!pFrm->WscBeaconProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Version:\n")); + if (!pFrm->WscBeaconProbeRes.Version.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("minor (4): %d\n"), pFrm->WscBeaconProbeRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("major (4): %d\n"), pFrm->WscBeaconProbeRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WPSState:\n")); + if (!pFrm->WscBeaconProbeRes.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APSetupLocked:\n")); + if (!pFrm->WscBeaconProbeRes.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscBeaconProbeRes.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscBeaconProbeRes.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscBeaconProbeRes.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ResponseType:\n")); + if (!pFrm->WscBeaconProbeRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("UUID_E:\n")); + if (!pFrm->WscBeaconProbeRes.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Manufacturer:\n")); + if (!pFrm->WscBeaconProbeRes.Manufacturer.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("num_name: %d.\n"), pFrm->WscBeaconProbeRes.Manufacturer.num_name); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.Manufacturer.name, pFrm->WscBeaconProbeRes.Manufacturer.num_name); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ModelName:\n")); + if (!pFrm->WscBeaconProbeRes.ModelName.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.ModelName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.ModelName.text, pFrm->WscBeaconProbeRes.ModelName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ModelNumber:\n")); + if (!pFrm->WscBeaconProbeRes.ModelNumber.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.ModelNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.ModelNumber.text, pFrm->WscBeaconProbeRes.ModelNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("SerialNumber:\n")); + if (!pFrm->WscBeaconProbeRes.SerialNumber.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.SerialNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.SerialNumber.text, pFrm->WscBeaconProbeRes.SerialNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("PrimaryDeviceType:\n")); + if (!pFrm->WscBeaconProbeRes.PrimaryDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.PrimaryDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.PrimaryDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.PrimaryDeviceType.sub_category, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DeviceName:\n")); + if (!pFrm->WscBeaconProbeRes.DeviceName.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("num_text: %d.\n"), pFrm->WscBeaconProbeRes.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->WscBeaconProbeRes.DeviceName.text, pFrm->WscBeaconProbeRes.DeviceName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ConfigMethods:\n")); + if (!pFrm->WscBeaconProbeRes.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.ConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RFBands:\n")); + if (!pFrm->WscBeaconProbeRes.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VendorExtension:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Version2:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscBeaconProbeRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("major (4): %d\n"), pFrm->WscBeaconProbeRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscBeaconProbeRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WscBeaconProbeRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PBeaconProbeRes:\n")); + if (!pFrm->P2PBeaconProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PCapability:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PBeaconProbeRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PBeaconProbeRes.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("num_NoADesc: %d.\n"), pFrm->P2PBeaconProbeRes.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->P2PBeaconProbeRes.NoticeOfAbsence.NoADesc, pFrm->P2PBeaconProbeRes.NoticeOfAbsence.num_NoADesc); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->P2PBeaconProbeRes.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("DeviceName:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.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("num_text: %d.\n"), pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.text, pFrm->P2PBeaconProbeRes.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("P2PGroupInfo:\n")); + if (!pFrm->P2PBeaconProbeRes.P2PGroupInfo.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("num_P2PClientInfoDesc: %d.\n"), pFrm->P2PBeaconProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->P2PBeaconProbeRes.P2PGroupInfo.P2PClientInfoDesc, pFrm->P2PBeaconProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + 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); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackBeaconIEs. */ + +tANI_U32 dot11fPackChannelSwitch(tpAniSirGlobal pCtx, tDot11fChannelSwitch *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ChannelSwitch, IES_ChannelSwitch); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Packed the ChannelSwitch:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), ( tANI_U8* )&pFrm->WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_CHANNELSWITCH), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackChannelSwitch. */ + +tANI_U32 dot11fPackDeAuth(tpAniSirGlobal pCtx, tDot11fDeAuth *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_DeAuth, IES_DeAuth); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Packed the DeAuth:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("P2PDeAuth:\n")); + if (!pFrm->P2PDeAuth.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("MinorReasonCode:\n")); + if (!pFrm->P2PDeAuth.MinorReasonCode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), ( tANI_U8* )&pFrm->P2PDeAuth.MinorReasonCode.minorReasonCode, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEAUTH), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDeAuth. */ + +tANI_U32 dot11fPackDelBAInd(tpAniSirGlobal pCtx, tDot11fDelBAInd *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_DelBAInd, IES_DelBAInd); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Packed the DelBAInd:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("DelBAParameterSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("reserved (11): %d\n"), pFrm->DelBAParameterSet.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("initiator (1): %d\n"), pFrm->DelBAParameterSet.initiator); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("tid (4): %d\n"), pFrm->DelBAParameterSet.tid); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELBAIND), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDelBAInd. */ + +tANI_U32 dot11fPackDelTS(tpAniSirGlobal pCtx, tDot11fDelTS *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_DelTS, IES_DelTS); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Packed the DelTS:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("TSInfo:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("traffic_type (1): %d\n"), pFrm->TSInfo.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("tsid (4): %d\n"), pFrm->TSInfo.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("direction (2): %d\n"), pFrm->TSInfo.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("access_policy (2): %d\n"), pFrm->TSInfo.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("aggregation (1): %d\n"), pFrm->TSInfo.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("psb (1): %d\n"), pFrm->TSInfo.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("user_priority (3): %d\n"), pFrm->TSInfo.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->TSInfo.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("schedule (1): %d\n"), pFrm->TSInfo.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("unused (15): %d\n"), pFrm->TSInfo.unused); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DELTS), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDelTS. */ + +tANI_U32 dot11fPackDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_DeviceDiscoverabilityReq, IES_DeviceDiscoverabilityReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Packed the DeviceDiscoverabilityReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2PDeviceDiscoverabilityReq:\n")); + if (!pFrm->P2PDeviceDiscoverabilityReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PDeviceDiscoverabilityReq.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2PDeviceDiscoverabilityReq.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("num_ssid: %d.\n"), pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), ( tANI_U8* ) pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.ssid, pFrm->P2PDeviceDiscoverabilityReq.P2PGroupId.num_ssid); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDeviceDiscoverabilityReq. */ + +tANI_U32 dot11fPackDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tDot11fDeviceDiscoverabilityRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_DeviceDiscoverabilityRes, IES_DeviceDiscoverabilityRes); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Packed the DeviceDiscoverabilityRes:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2PDeviceDiscoverabilityRes:\n")); + if (!pFrm->P2PDeviceDiscoverabilityRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PDeviceDiscoverabilityRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), ( tANI_U8* )&pFrm->P2PDeviceDiscoverabilityRes.P2PStatus.status, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DEVICEDISCOVERABILITYRES), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDeviceDiscoverabilityRes. */ + +tANI_U32 dot11fPackDisassociation(tpAniSirGlobal pCtx, tDot11fDisassociation *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_Disassociation, IES_Disassociation); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Packed the Disassociation:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("P2PDisAssoc:\n")); + if (!pFrm->P2PDisAssoc.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("MinorReasonCode:\n")); + if (!pFrm->P2PDisAssoc.MinorReasonCode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), ( tANI_U8* )&pFrm->P2PDisAssoc.MinorReasonCode.minorReasonCode, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_DISASSOCIATION), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackDisassociation. */ + +tANI_U32 dot11fPackGODiscoverabilityReq(tpAniSirGlobal pCtx, tDot11fGODiscoverabilityReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_GODiscoverabilityReq, IES_GODiscoverabilityReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("Packed the GODiscoverabilityReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GODISCOVERABILITYREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGODiscoverabilityReq. */ + +tANI_U32 dot11fPackGONegCnf(tpAniSirGlobal pCtx, tDot11fGONegCnf *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_GONegCnf, IES_GONegCnf); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Packed the GONegCnf:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PGONegCnf:\n")); + if (!pFrm->P2PGONegCnf.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PStatus:\n")); + if (!pFrm->P2PGONegCnf.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PCapability:\n")); + if (!pFrm->P2PGONegCnf.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PGONegCnf.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("ChannelList:\n")); + if (!pFrm->P2PGONegCnf.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("num_channelList: %d.\n"), pFrm->P2PGONegCnf.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* ) pFrm->P2PGONegCnf.ChannelList.channelList, pFrm->P2PGONegCnf.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PGONegCnf.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* )&pFrm->P2PGONegCnf.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("num_ssid: %d.\n"), pFrm->P2PGONegCnf.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), ( tANI_U8* ) pFrm->P2PGONegCnf.P2PGroupId.ssid, pFrm->P2PGONegCnf.P2PGroupId.num_ssid); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGCNF), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGONegCnf. */ + +tANI_U32 dot11fPackGONegReq(tpAniSirGlobal pCtx, tDot11fGONegReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_GONegReq, IES_GONegReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Packed the GONegReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PGONegWPS:\n")); + if (!pFrm->P2PGONegWPS.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Version:\n")); + if (!pFrm->P2PGONegWPS.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("minor (4): %d\n"), pFrm->P2PGONegWPS.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("major (4): %d\n"), pFrm->P2PGONegWPS.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("DevicePasswordID:\n")); + if (!pFrm->P2PGONegWPS.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegWPS.DevicePasswordID.id, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PGONegReq:\n")); + if (!pFrm->P2PGONegReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PCapability:\n")); + if (!pFrm->P2PGONegReq.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("GOIntent:\n")); + if (!pFrm->P2PGONegReq.GOIntent.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.GOIntent.GOIntent, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PGONegReq.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ListenChannel:\n")); + if (!pFrm->P2PGONegReq.ListenChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ListenChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ListenChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ListenChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PGONegReq.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("IntendedP2PInterfaceAddress:\n")); + if (!pFrm->P2PGONegReq.IntendedP2PInterfaceAddress.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.IntendedP2PInterfaceAddress.P2PInterfaceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("ChannelList:\n")); + if (!pFrm->P2PGONegReq.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("num_channelList: %d.\n"), pFrm->P2PGONegReq.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* ) pFrm->P2PGONegReq.ChannelList.channelList, pFrm->P2PGONegReq.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PGONegReq.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("DeviceName:\n")); + if (!pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("num_text: %d.\n"), pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* ) pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.text, pFrm->P2PGONegReq.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PGONegReq.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), ( tANI_U8* )&pFrm->P2PGONegReq.OperatingChannel.channel, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGONegReq. */ + +tANI_U32 dot11fPackGONegRes(tpAniSirGlobal pCtx, tDot11fGONegRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_GONegRes, IES_GONegRes); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Packed the GONegRes:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PGONegWPS:\n")); + if (!pFrm->P2PGONegWPS.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Version:\n")); + if (!pFrm->P2PGONegWPS.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("minor (4): %d\n"), pFrm->P2PGONegWPS.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("major (4): %d\n"), pFrm->P2PGONegWPS.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("DevicePasswordID:\n")); + if (!pFrm->P2PGONegWPS.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegWPS.DevicePasswordID.id, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PGONegRes:\n")); + if (!pFrm->P2PGONegRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PGONegRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PCapability:\n")); + if (!pFrm->P2PGONegRes.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("GOIntent:\n")); + if (!pFrm->P2PGONegRes.GOIntent.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.GOIntent.GOIntent, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PGONegRes.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PGONegRes.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("IntendedP2PInterfaceAddress:\n")); + if (!pFrm->P2PGONegRes.IntendedP2PInterfaceAddress.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.IntendedP2PInterfaceAddress.P2PInterfaceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("ChannelList:\n")); + if (!pFrm->P2PGONegRes.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("num_channelList: %d.\n"), pFrm->P2PGONegRes.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* ) pFrm->P2PGONegRes.ChannelList.channelList, pFrm->P2PGONegRes.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PGONegRes.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("DeviceName:\n")); + if (!pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("num_text: %d.\n"), pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* ) pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.text, pFrm->P2PGONegRes.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PGONegRes.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* )&pFrm->P2PGONegRes.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("num_ssid: %d.\n"), pFrm->P2PGONegRes.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), ( tANI_U8* ) pFrm->P2PGONegRes.P2PGroupId.ssid, pFrm->P2PGONegRes.P2PGroupId.num_ssid); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_GONEGRES), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackGONegRes. */ + +tANI_U32 dot11fPackHT2040BSSCoexistenceManagementActionFrame(tpAniSirGlobal pCtx, tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_HT2040BSSCoexistenceManagementActionFrame, IES_HT2040BSSCoexistenceManagementActionFrame); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Packed the HT2040BSSCoexistenceManagementActionFrame:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("HT2040BSSIntolerantReport:\n")); + if (!pFrm->HT2040BSSIntolerantReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->HT2040BSSIntolerantReport.operatingClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("num_channelList: %d.\n"), pFrm->HT2040BSSIntolerantReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), ( tANI_U8* ) pFrm->HT2040BSSIntolerantReport.channelList, pFrm->HT2040BSSIntolerantReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_HT2040BSSCOEXISTENCEMANAGEMENTACTIONFRAME), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackHT2040BSSCoexistenceManagementActionFrame. */ + +tANI_U32 dot11fPackInvitationReq(tpAniSirGlobal pCtx, tDot11fInvitationReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_InvitationReq, IES_InvitationReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Packed the InvitationReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PInvitationReq:\n")); + if (!pFrm->P2PInvitationReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PInvitationReq.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("InvitationFlags:\n")); + if (!pFrm->P2PInvitationReq.InvitationFlags.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.InvitationFlags.invitationFlags, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PInvitationReq.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PGroupBssid:\n")); + if (!pFrm->P2PInvitationReq.P2PGroupBssid.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PGroupBssid.P2PGroupBssid, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("ChannelList:\n")); + if (!pFrm->P2PInvitationReq.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("num_channelList: %d.\n"), pFrm->P2PInvitationReq.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* ) pFrm->P2PInvitationReq.ChannelList.channelList, pFrm->P2PInvitationReq.ChannelList.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PInvitationReq.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("num_ssid: %d.\n"), pFrm->P2PInvitationReq.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* ) pFrm->P2PInvitationReq.P2PGroupId.ssid, pFrm->P2PInvitationReq.P2PGroupId.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PInvitationReq.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* )&pFrm->P2PInvitationReq.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("DeviceName:\n")); + if (!pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("num_text: %d.\n"), pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), ( tANI_U8* ) pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.text, pFrm->P2PInvitationReq.P2PDeviceInfo.DeviceName.num_text); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackInvitationReq. */ + +tANI_U32 dot11fPackInvitationRes(tpAniSirGlobal pCtx, tDot11fInvitationRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_InvitationRes, IES_InvitationRes); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Packed the InvitationRes:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2PInvitationRes:\n")); + if (!pFrm->P2PInvitationRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PInvitationRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("ConfigurationTimeout:\n")); + if (!pFrm->P2PInvitationRes.ConfigurationTimeout.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.ConfigurationTimeout.GOConfigTimeout, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.ConfigurationTimeout.CLConfigTimeout, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PInvitationRes.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.OperatingChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("P2PGroupBssid:\n")); + if (!pFrm->P2PInvitationRes.P2PGroupBssid.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.P2PGroupBssid.P2PGroupBssid, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("ChannelList:\n")); + if (!pFrm->P2PInvitationRes.ChannelList.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* )&pFrm->P2PInvitationRes.ChannelList.countryString, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("num_channelList: %d.\n"), pFrm->P2PInvitationRes.ChannelList.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), ( tANI_U8* ) pFrm->P2PInvitationRes.ChannelList.channelList, pFrm->P2PInvitationRes.ChannelList.num_channelList); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_INVITATIONRES), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackInvitationRes. */ + +tANI_U32 dot11fPackLinkMeasurementReport(tpAniSirGlobal pCtx, tDot11fLinkMeasurementReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_LinkMeasurementReport, IES_LinkMeasurementReport); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("Packed the LinkMeasurementReport:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TPCEleID:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TPCEleID.TPCId, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TPCEleLen:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TPCEleLen.TPCLen, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TxPower:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TxPower.txPower, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("LinkMargin:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->LinkMargin.linkMargin, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("RxAntennaId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->RxAntennaId.antennaId, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("TxAntennaId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->TxAntennaId.antennaId, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("RCPI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->RCPI.rcpi, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("RSNI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), ( tANI_U8* )&pFrm->RSNI.rsni, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREPORT), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackLinkMeasurementReport. */ + +tANI_U32 dot11fPackLinkMeasurementRequest(tpAniSirGlobal pCtx, tDot11fLinkMeasurementRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_LinkMeasurementRequest, IES_LinkMeasurementRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("Packed the LinkMeasurementRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("TxPower:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->TxPower.txPower, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("MaxTxPower:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MaxTxPower.maxTxPower, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_LINKMEASUREMENTREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackLinkMeasurementRequest. */ + +tANI_U32 dot11fPackMeasurementReport(tpAniSirGlobal pCtx, tDot11fMeasurementReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_MeasurementReport, IES_MeasurementReport); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Packed the MeasurementReport:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("MeasurementReport:\n")); + if (!pFrm->MeasurementReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("late (1): %d\n"), pFrm->MeasurementReport.late); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("incapable (1): %d\n"), pFrm->MeasurementReport.incapable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("refused (1): %d\n"), pFrm->MeasurementReport.refused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unused (5): %d\n"), pFrm->MeasurementReport.unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.type, 1); + switch (pFrm->MeasurementReport.type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Basic.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Basic.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("bss (1): %d\n"), pFrm->MeasurementReport.report.Basic.bss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("ofdm_preamble (1): %d\n"), pFrm->MeasurementReport.report.Basic.ofdm_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unid_signal (1): %d\n"), pFrm->MeasurementReport.report.Basic.unid_signal); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("rader (1): %d\n"), pFrm->MeasurementReport.report.Basic.rader); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unmeasured (1): %d\n"), pFrm->MeasurementReport.report.Basic.unmeasured); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("unused (3): %d\n"), pFrm->MeasurementReport.report.Basic.unused); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.CCA.cca_busy_fraction, 1); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi0_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi1_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi2_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi3_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi4_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi5_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi6_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.RPIHistogram.rpi7_density, 1); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("condensed_PHY (7): %d\n"), pFrm->MeasurementReport.report.Beacon.condensed_PHY); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("reported_frame_type (1): %d\n"), pFrm->MeasurementReport.report.Beacon.reported_frame_type); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.RCPI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.RSNI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.BSSID, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.antenna_id, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport.report.Beacon.parent_TSF, 4); + break; + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREPORT), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackMeasurementReport. */ + +tANI_U32 dot11fPackMeasurementRequest(tpAniSirGlobal pCtx, tDot11fMeasurementRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_MeasurementRequest, IES_MeasurementRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Packed the MeasurementRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + for (i = 0; i < pFrm->num_MeasurementRequest; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("MeasurementRequest[%d]:\n"), i); + if (!pFrm->MeasurementRequest[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("parallel (1): %d\n"), pFrm->MeasurementRequest[i].parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("enable (1): %d\n"), pFrm->MeasurementRequest[i].enable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("request (1): %d\n"), pFrm->MeasurementRequest[i].request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("report (1): %d\n"), pFrm->MeasurementRequest[i].report); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("durationMandatory (1): %d\n"), pFrm->MeasurementRequest[i].durationMandatory); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("unused (3): %d\n"), pFrm->MeasurementRequest[i].unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_type, 1); + switch (pFrm->MeasurementRequest[i].measurement_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_duration, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_duration, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_duration, 2); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.randomization, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.BSSID, 6); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_MEASUREMENTREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackMeasurementRequest. */ + +tANI_U32 dot11fPackNeighborReportRequest(tpAniSirGlobal pCtx, tDot11fNeighborReportRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_NeighborReportRequest, IES_NeighborReportRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Packed the NeighborReportRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackNeighborReportRequest. */ + +tANI_U32 dot11fPackNeighborReportResponse(tpAniSirGlobal pCtx, tDot11fNeighborReportResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_NeighborReportResponse, IES_NeighborReportResponse); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Packed the NeighborReportResponse:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->DialogToken.token, 1); + for (i = 0; i < pFrm->num_NeighborReport; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NeighborReport[%d]:\n"), i); + if (!pFrm->NeighborReport[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].bssid, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("APReachability (2): %d\n"), pFrm->NeighborReport[i].APReachability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Security (1): %d\n"), pFrm->NeighborReport[i].Security); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("KeyScope (1): %d\n"), pFrm->NeighborReport[i].KeyScope); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("SpecMgmtCap (1): %d\n"), pFrm->NeighborReport[i].SpecMgmtCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("QosCap (1): %d\n"), pFrm->NeighborReport[i].QosCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("apsd (1): %d\n"), pFrm->NeighborReport[i].apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("rrm (1): %d\n"), pFrm->NeighborReport[i].rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("DelayedBA (1): %d\n"), pFrm->NeighborReport[i].DelayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("ImmBA (1): %d\n"), pFrm->NeighborReport[i].ImmBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MobilityDomain (1): %d\n"), pFrm->NeighborReport[i].MobilityDomain); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("reserved (5): %d\n"), pFrm->NeighborReport[i].reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].reserved1, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].PhyType, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("TSFInfo:\n")); + if (!pFrm->NeighborReport[i].TSFInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].TSFInfo.TsfOffset, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].TSFInfo.BeaconIntvl, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("CondensedCountryStr:\n")); + if (!pFrm->NeighborReport[i].CondensedCountryStr.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].CondensedCountryStr.countryStr, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MeasurementPilot:\n")); + if (!pFrm->NeighborReport[i].MeasurementPilot.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].MeasurementPilot.measurementPilot, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("num_vendorSpecific: %d.\n"), pFrm->NeighborReport[i].MeasurementPilot.num_vendorSpecific); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* ) pFrm->NeighborReport[i].MeasurementPilot.vendorSpecific, pFrm->NeighborReport[i].MeasurementPilot.num_vendorSpecific); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->NeighborReport[i].RRMEnabledCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("LinkMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("parallel (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("repeated (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("statistics (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("reserved (4): %d\n"), pFrm->NeighborReport[i].RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("MultiBssid:\n")); + if (!pFrm->NeighborReport[i].MultiBssid.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* )&pFrm->NeighborReport[i].MultiBssid.maxBSSIDIndicator, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("num_vendorSpecific: %d.\n"), pFrm->NeighborReport[i].MultiBssid.num_vendorSpecific); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), ( tANI_U8* ) pFrm->NeighborReport[i].MultiBssid.vendorSpecific, pFrm->NeighborReport[i].MultiBssid.num_vendorSpecific); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NEIGHBORREPORTRESPONSE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackNeighborReportResponse. */ + +tANI_U32 dot11fPackNoticeOfAbs(tpAniSirGlobal pCtx, tDot11fNoticeOfAbs *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_NoticeOfAbs, IES_NoticeOfAbs); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Packed the NoticeOfAbs:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("P2PNoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("num_NoADesc: %d.\n"), pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), ( tANI_U8* ) pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.NoADesc, pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_NOTICEOFABS), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackNoticeOfAbs. */ + +tANI_U32 dot11fPackOperatingMode(tpAniSirGlobal pCtx, tDot11fOperatingMode *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_OperatingMode, IES_OperatingMode); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("Packed the OperatingMode:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("OperatingMode:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_OPERATINGMODE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackOperatingMode. */ + +tANI_U32 dot11fPackPresenceReq(tpAniSirGlobal pCtx, tDot11fPresenceReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_PresenceReq, IES_PresenceReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Packed the PresenceReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("P2PNoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* )&pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("num_NoADesc: %d.\n"), pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), ( tANI_U8* ) pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.NoADesc, pFrm->P2PNoticeOfAbsence.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCEREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackPresenceReq. */ + +tANI_U32 dot11fPackPresenceRes(tpAniSirGlobal pCtx, tDot11fPresenceRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_PresenceRes, IES_PresenceRes); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Packed the PresenceRes:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2PPresenceResponse:\n")); + if (!pFrm->P2PPresenceResponse.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("P2PStatus:\n")); + if (!pFrm->P2PPresenceResponse.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2PPresenceResponse.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PPresenceResponse.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2PPresenceResponse.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* )&pFrm->P2PPresenceResponse.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("num_NoADesc: %d.\n"), pFrm->P2PPresenceResponse.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), ( tANI_U8* ) pFrm->P2PPresenceResponse.NoticeOfAbsence.NoADesc, pFrm->P2PPresenceResponse.NoticeOfAbsence.num_NoADesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PRESENCERES), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackPresenceRes. */ + +tANI_U32 dot11fPackProbeRequest(tpAniSirGlobal pCtx, tDot11fProbeRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ProbeRequest, IES_ProbeRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Packed the ProbeRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestedInfo:\n")); + if (!pFrm->RequestedInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_requested_eids: %d.\n"), pFrm->RequestedInfo.num_requested_eids); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->RequestedInfo.requested_eids, pFrm->RequestedInfo.num_requested_eids); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("WscProbeReq:\n")); + if (!pFrm->WscProbeReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Version:\n")); + if (!pFrm->WscProbeReq.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("minor (4): %d\n"), pFrm->WscProbeReq.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("major (4): %d\n"), pFrm->WscProbeReq.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestType:\n")); + if (!pFrm->WscProbeReq.RequestType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestType.reqType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ConfigMethods:\n")); + if (!pFrm->WscProbeReq.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.ConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("UUID_E:\n")); + if (!pFrm->WscProbeReq.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("PrimaryDeviceType:\n")); + if (!pFrm->WscProbeReq.PrimaryDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.PrimaryDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.PrimaryDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.PrimaryDeviceType.sub_category, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RFBands:\n")); + if (!pFrm->WscProbeReq.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("AssociationState:\n")); + if (!pFrm->WscProbeReq.AssociationState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.AssociationState.state, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ConfigurationError:\n")); + if (!pFrm->WscProbeReq.ConfigurationError.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.ConfigurationError.error, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscProbeReq.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Manufacturer:\n")); + if (!pFrm->WscProbeReq.Manufacturer.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_name: %d.\n"), pFrm->WscProbeReq.Manufacturer.num_name); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.Manufacturer.name, pFrm->WscProbeReq.Manufacturer.num_name); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ModelName:\n")); + if (!pFrm->WscProbeReq.ModelName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_text: %d.\n"), pFrm->WscProbeReq.ModelName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.ModelName.text, pFrm->WscProbeReq.ModelName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ModelNumber:\n")); + if (!pFrm->WscProbeReq.ModelNumber.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_text: %d.\n"), pFrm->WscProbeReq.ModelNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.ModelNumber.text, pFrm->WscProbeReq.ModelNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("DeviceName:\n")); + if (!pFrm->WscProbeReq.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_text: %d.\n"), pFrm->WscProbeReq.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->WscProbeReq.DeviceName.text, pFrm->WscProbeReq.DeviceName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("VendorExtension:\n")); + if (!pFrm->WscProbeReq.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Version2:\n")); + if (!pFrm->WscProbeReq.VendorExtension.Version2.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("minor (4): %d\n"), pFrm->WscProbeReq.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("major (4): %d\n"), pFrm->WscProbeReq.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscProbeReq.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscProbeReq.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.VendorExtension.RequestToEnroll.req, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("RequestDeviceType:\n")); + if (!pFrm->WscProbeReq.RequestDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WscProbeReq.RequestDeviceType.sub_category, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("WFATPC:\n")); + if (!pFrm->WFATPC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WFATPC.txPower, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->WFATPC.linkMargin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("P2PProbeReq:\n")); + if (!pFrm->P2PProbeReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("P2PCapability:\n")); + if (!pFrm->P2PProbeReq.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("P2PDeviceId:\n")); + if (!pFrm->P2PProbeReq.P2PDeviceId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.P2PDeviceId.P2PDeviceAddress, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ListenChannel:\n")); + if (!pFrm->P2PProbeReq.ListenChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ListenChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ListenChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ListenChannel.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PProbeReq.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("OperatingChannel:\n")); + if (!pFrm->P2PProbeReq.OperatingChannel.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.OperatingChannel.countryString, 3); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.OperatingChannel.regulatoryClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->P2PProbeReq.OperatingChannel.channel, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBEREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProbeRequest. */ + +tANI_U32 dot11fPackProbeResponse(tpAniSirGlobal pCtx, tDot11fProbeResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ProbeResponse, IES_ProbeResponse); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Packed the ProbeResponse:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->BeaconInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FHParamSet:\n")); + if (!pFrm->FHParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.dwell_time, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.hop_set, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.hop_pattern, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParamSet.hop_index, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DSParams:\n")); + if (!pFrm->DSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->DSParams.curr_channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("CFParams:\n")); + if (!pFrm->CFParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_maxduration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->CFParams.cfp_durremaining, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("IBSSParams:\n")); + if (!pFrm->IBSSParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->IBSSParams.atim, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FHParams:\n")); + if (!pFrm->FHParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParams.radix, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHParams.nchannels, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FHPattTable:\n")); + if (!pFrm->FHPattTable.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.flag, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.nsets, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.modulus, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->FHPattTable.offset, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_randtable: %d.\n"), pFrm->FHPattTable.num_randtable); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->FHPattTable.randtable, pFrm->FHPattTable.num_randtable); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ChanSwitchAnn:\n")); + if (!pFrm->ChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchMode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChanSwitchAnn.newChannel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChanSwitchAnn.switchCount, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ext_chan_switch_ann:\n")); + if (!pFrm->ext_chan_switch_ann.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_reg_class, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.new_channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ext_chan_switch_ann.switch_count, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.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("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Quiet:\n")); + if (!pFrm->Quiet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.count, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.period, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->Quiet.offset, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ERPInfo:\n")); + if (!pFrm->ERPInfo.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("non_erp_present (1): %d\n"), pFrm->ERPInfo.non_erp_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("use_prot (1): %d\n"), pFrm->ERPInfo.use_prot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("barker_preamble (1): %d\n"), pFrm->ERPInfo.barker_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused (5): %d\n"), pFrm->ERPInfo.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("QBSSLoad:\n")); + if (!pFrm->QBSSLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QBSSLoad.stacount, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QBSSLoad.chautil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QBSSLoad.avail, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("APChannelReport:\n")); + if (!pFrm->APChannelReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->APChannelReport.regulatoryClass, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_channelList: %d.\n"), pFrm->APChannelReport.num_channelList); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->APChannelReport.channelList, pFrm->APChannelReport.num_channelList); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("sec_chan_offset_ele:\n")); + if (!pFrm->sec_chan_offset_ele.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->sec_chan_offset_ele.secondaryChannelOffset, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WMMInfoAp:\n")); + if (!pFrm->WMMInfoAp.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMInfoAp.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("param_set_count (4): %d\n"), pFrm->WMMInfoAp.param_set_count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (3): %d\n"), pFrm->WMMInfoAp.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("uapsd (1): %d\n"), pFrm->WMMInfoAp.uapsd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WscProbeRes:\n")); + if (!pFrm->WscProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Version:\n")); + if (!pFrm->WscProbeRes.Version.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("minor (4): %d\n"), pFrm->WscProbeRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("major (4): %d\n"), pFrm->WscProbeRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WPSState:\n")); + if (!pFrm->WscProbeRes.WPSState.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.WPSState.state, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("APSetupLocked:\n")); + if (!pFrm->WscProbeRes.APSetupLocked.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.APSetupLocked.fLocked, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SelectedRegistrar:\n")); + if (!pFrm->WscProbeRes.SelectedRegistrar.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.SelectedRegistrar.selected, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DevicePasswordID:\n")); + if (!pFrm->WscProbeRes.DevicePasswordID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.DevicePasswordID.id, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SelectedRegistrarConfigMethods:\n")); + if (!pFrm->WscProbeRes.SelectedRegistrarConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.SelectedRegistrarConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ResponseType:\n")); + if (!pFrm->WscProbeRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("UUID_E:\n")); + if (!pFrm->WscProbeRes.UUID_E.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.UUID_E.uuid, 16); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Manufacturer:\n")); + if (!pFrm->WscProbeRes.Manufacturer.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("num_name: %d.\n"), pFrm->WscProbeRes.Manufacturer.num_name); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.Manufacturer.name, pFrm->WscProbeRes.Manufacturer.num_name); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ModelName:\n")); + if (!pFrm->WscProbeRes.ModelName.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("num_text: %d.\n"), pFrm->WscProbeRes.ModelName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.ModelName.text, pFrm->WscProbeRes.ModelName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ModelNumber:\n")); + if (!pFrm->WscProbeRes.ModelNumber.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("num_text: %d.\n"), pFrm->WscProbeRes.ModelNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.ModelNumber.text, pFrm->WscProbeRes.ModelNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("SerialNumber:\n")); + if (!pFrm->WscProbeRes.SerialNumber.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("num_text: %d.\n"), pFrm->WscProbeRes.SerialNumber.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.SerialNumber.text, pFrm->WscProbeRes.SerialNumber.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("PrimaryDeviceType:\n")); + if (!pFrm->WscProbeRes.PrimaryDeviceType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.PrimaryDeviceType.primary_category, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.PrimaryDeviceType.oui, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.PrimaryDeviceType.sub_category, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DeviceName:\n")); + if (!pFrm->WscProbeRes.DeviceName.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("num_text: %d.\n"), pFrm->WscProbeRes.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->WscProbeRes.DeviceName.text, pFrm->WscProbeRes.DeviceName.num_text); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ConfigMethods:\n")); + if (!pFrm->WscProbeRes.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.ConfigMethods.methods, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RFBands:\n")); + if (!pFrm->WscProbeRes.RFBands.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.RFBands.bands, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VendorExtension:\n")); + if (!pFrm->WscProbeRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Version2:\n")); + if (!pFrm->WscProbeRes.VendorExtension.Version2.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("minor (4): %d\n"), pFrm->WscProbeRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("major (4): %d\n"), pFrm->WscProbeRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscProbeRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscProbeRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->WscProbeRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PProbeRes:\n")); + if (!pFrm->P2PProbeRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PCapability:\n")); + if (!pFrm->P2PProbeRes.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PProbeRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.ExtendedListenTiming.availibilityInterval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("NoticeOfAbsence:\n")); + if (!pFrm->P2PProbeRes.NoticeOfAbsence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.NoticeOfAbsence.index, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.NoticeOfAbsence.CTSWindowOppPS, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("num_NoADesc: %d.\n"), pFrm->P2PProbeRes.NoticeOfAbsence.num_NoADesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->P2PProbeRes.NoticeOfAbsence.NoADesc, pFrm->P2PProbeRes.NoticeOfAbsence.num_NoADesc); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PProbeRes.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->P2PProbeRes.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("DeviceName:\n")); + if (!pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.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("num_text: %d.\n"), pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.text, pFrm->P2PProbeRes.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("P2PGroupInfo:\n")); + if (!pFrm->P2PProbeRes.P2PGroupInfo.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("num_P2PClientInfoDesc: %d.\n"), pFrm->P2PProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->P2PProbeRes.P2PGroupInfo.P2PClientInfoDesc, pFrm->P2PProbeRes.P2PGroupInfo.num_P2PClientInfoDesc); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("VHTExtBssLoad:\n")); + if (!pFrm->VHTExtBssLoad.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.muMIMOCapStaCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.ssUnderUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.FortyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.EightyMHzUtil, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->VHTExtBssLoad.OneSixtyMHzUtil, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + 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("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ChannelSwitchWrapper:\n")); + if (!pFrm->ChannelSwitchWrapper.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("WiderBWChanSwitchAnn:\n")); + if (!pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1, 1); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("QComVendorIE:\n")); + if (!pFrm->QComVendorIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QComVendorIE.type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->QComVendorIE.channel, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + 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); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProbeResponse. */ + +tANI_U32 dot11fPackProvisionDiscoveryReq(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ProvisionDiscoveryReq, IES_ProvisionDiscoveryReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Packed the ProvisionDiscoveryReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PProvisionDiscoveryReq:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PCapability:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PCapability.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PCapability.deviceCapability, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PCapability.groupCapability, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PDeviceInfo:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.P2PDeviceAddress, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.configMethod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.primaryDeviceType, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("DeviceName:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("num_text: %d.\n"), pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.num_text); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* ) pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.text, pFrm->P2PProvisionDiscoveryReq.P2PDeviceInfo.DeviceName.num_text); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("P2PGroupId:\n")); + if (!pFrm->P2PProvisionDiscoveryReq.P2PGroupId.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* )&pFrm->P2PProvisionDiscoveryReq.P2PGroupId.deviceAddress, 6); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("num_ssid: %d.\n"), pFrm->P2PProvisionDiscoveryReq.P2PGroupId.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), ( tANI_U8* ) pFrm->P2PProvisionDiscoveryReq.P2PGroupId.ssid, pFrm->P2PProvisionDiscoveryReq.P2PGroupId.num_ssid); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProvisionDiscoveryReq. */ + +tANI_U32 dot11fPackProvisionDiscoveryRes(tpAniSirGlobal pCtx, tDot11fProvisionDiscoveryRes *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ProvisionDiscoveryRes, IES_ProvisionDiscoveryRes); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Packed the ProvisionDiscoveryRes:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("P2POUI:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->P2POUI.oui, 4); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("P2POUISubType:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->P2POUISubType.ouiSubtype, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("P2PWSCProvisionDiscoveryRes:\n")); + if (!pFrm->P2PWSCProvisionDiscoveryRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("ConfigMethods:\n")); + if (!pFrm->P2PWSCProvisionDiscoveryRes.ConfigMethods.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), ( tANI_U8* )&pFrm->P2PWSCProvisionDiscoveryRes.ConfigMethods.methods, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROVISIONDISCOVERYRES), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackProvisionDiscoveryRes. */ + +tANI_U32 dot11fPackQosMapConfigure(tpAniSirGlobal pCtx, tDot11fQosMapConfigure *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_QosMapConfigure, IES_QosMapConfigure); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Packed the QosMapConfigure:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_QOSMAPCONFIGURE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackQosMapConfigure. */ + +tANI_U32 dot11fPackRadioMeasurementReport(tpAniSirGlobal pCtx, tDot11fRadioMeasurementReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_RadioMeasurementReport, IES_RadioMeasurementReport); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Packed the RadioMeasurementReport:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + for (i = 0; i < pFrm->num_MeasurementReport; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("MeasurementReport[%d]:\n"), i); + if (!pFrm->MeasurementReport[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("late (1): %d\n"), pFrm->MeasurementReport[i].late); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("incapable (1): %d\n"), pFrm->MeasurementReport[i].incapable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("refused (1): %d\n"), pFrm->MeasurementReport[i].refused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unused (5): %d\n"), pFrm->MeasurementReport[i].unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].type, 1); + switch (pFrm->MeasurementReport[i].type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Basic.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Basic.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("bss (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.bss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("ofdm_preamble (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.ofdm_preamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unid_signal (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.unid_signal); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("rader (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.rader); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unmeasured (1): %d\n"), pFrm->MeasurementReport[i].report.Basic.unmeasured); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("unused (3): %d\n"), pFrm->MeasurementReport[i].report.Basic.unused); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.CCA.cca_busy_fraction, 1); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi0_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi1_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi2_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi3_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi4_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi5_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi6_density, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.RPIHistogram.rpi7_density, 1); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.meas_duration, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("condensed_PHY (7): %d\n"), pFrm->MeasurementReport[i].report.Beacon.condensed_PHY); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("reported_frame_type (1): %d\n"), pFrm->MeasurementReport[i].report.Beacon.reported_frame_type); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.RCPI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.RSNI, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.BSSID, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.antenna_id, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), ( tANI_U8* )&pFrm->MeasurementReport[i].report.Beacon.parent_TSF, 4); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREPORT), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackRadioMeasurementReport. */ + +tANI_U32 dot11fPackRadioMeasurementRequest(tpAniSirGlobal pCtx, tDot11fRadioMeasurementRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_RadioMeasurementRequest, IES_RadioMeasurementRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Packed the RadioMeasurementRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("NumOfRepetitions:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->NumOfRepetitions.repetitions, 2); + for (i = 0; i < pFrm->num_MeasurementRequest; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("MeasurementRequest[%d]:\n"), i); + if (!pFrm->MeasurementRequest[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_token, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("parallel (1): %d\n"), pFrm->MeasurementRequest[i].parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("enable (1): %d\n"), pFrm->MeasurementRequest[i].enable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("request (1): %d\n"), pFrm->MeasurementRequest[i].request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("report (1): %d\n"), pFrm->MeasurementRequest[i].report); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("durationMandatory (1): %d\n"), pFrm->MeasurementRequest[i].durationMandatory); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("unused (3): %d\n"), pFrm->MeasurementRequest[i].unused); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_type, 1); + switch (pFrm->MeasurementRequest[i].measurement_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Basic.meas_duration, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.CCA.meas_duration, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.channel_no, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_start_time, 8); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.RPIHistogram.meas_duration, 2); + break; + case 5: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.regClass, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.channel, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.randomization, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_duration, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.meas_mode, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), ( tANI_U8* )&pFrm->MeasurementRequest[i].measurement_request.Beacon.BSSID, 6); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_RADIOMEASUREMENTREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackRadioMeasurementRequest. */ + +tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ReAssocRequest, IES_ReAssocRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Packed the ReAssocRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ListenInterval:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ListenInterval.interval, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("CurrentAPAddress:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->CurrentAPAddress.mac, 6); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("SSID:\n")); + if (!pFrm->SSID.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("num_ssid: %d.\n"), pFrm->SSID.num_ssid); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->SSID.ssid, pFrm->SSID.num_ssid); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.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("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.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("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("PowerCaps:\n")); + if (!pFrm->PowerCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.minTxPower, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->PowerCaps.maxTxPower, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.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("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.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("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.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("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.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("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.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("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.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("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.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("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.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("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.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("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WPAOpaque:\n")); + if (!pFrm->WPAOpaque.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("num_data: %d.\n"), pFrm->WPAOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WPAOpaque.data, pFrm->WPAOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.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("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMCaps:\n")); + if (!pFrm->WMMCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMCaps.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (4): %d\n"), pFrm->WMMCaps.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->WMMCaps.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("queue_request (1): %d\n"), pFrm->WMMCaps.queue_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txop_request (1): %d\n"), pFrm->WMMCaps.txop_request); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_ack (1): %d\n"), pFrm->WMMCaps.more_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WscIEOpaque:\n")); + if (!pFrm->WscIEOpaque.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("num_data: %d.\n"), pFrm->WscIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WscIEOpaque.data, pFrm->WscIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WAPIOpaque:\n")); + if (!pFrm->WAPIOpaque.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("num_data: %d.\n"), pFrm->WAPIOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPIOpaque.data, pFrm->WAPIOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WAPI:\n")); + if (!pFrm->WAPI.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.akm_suites, 4 * pFrm->WAPI.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.unicast_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.unicast_cipher_suites, 4 * pFrm->WAPI.unicast_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.multicast_cipher_suite, 4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("preauth (1): %d\n"), pFrm->WAPI.preauth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (15): %d\n"), pFrm->WAPI.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WAPI.bkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WAPI.bkid, 16 * pFrm->WAPI.bkid_count); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESEVersion:\n")); + if (!pFrm->ESEVersion.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ESEVersion.version, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESECckmOpaque:\n")); + if (!pFrm->ESECckmOpaque.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("num_data: %d.\n"), pFrm->ESECckmOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ESECckmOpaque.data, pFrm->ESECckmOpaque.num_data); + } + for (i = 0; i < pFrm->num_WMMTSPEC; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WMMTSPEC[%d]:\n"), i); + if (!pFrm->WMMTSPEC[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC[i].traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC[i].tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC[i].direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC[i].access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC[i].aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC[i].psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC[i].user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC[i].tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC[i].tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC[i].burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("size (15): %d\n"), pFrm->WMMTSPEC[i].size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC[i].fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC[i].medium_time, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("P2PIEOpaque:\n")); + if (!pFrm->P2PIEOpaque.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("num_data: %d.\n"), pFrm->P2PIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->P2PIEOpaque.data, pFrm->P2PIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("WFDIEOpaque:\n")); + if (!pFrm->WFDIEOpaque.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("num_data: %d.\n"), pFrm->WFDIEOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->WFDIEOpaque.data, pFrm->WFDIEOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.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("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.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("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.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("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.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("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("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackReAssocRequest. */ + +tANI_U32 dot11fPackReAssocResponse(tpAniSirGlobal pCtx, tDot11fReAssocResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ReAssocResponse, IES_ReAssocResponse); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Packed the ReAssocResponse:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("AID:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->AID.associd, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RCPIIE:\n")); + if (!pFrm->RCPIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RCPIIE.rcpi, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RSNIIE:\n")); + if (!pFrm->RSNIIE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RSNIIE.rsni, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RRMEnabledCap:\n")); + if (!pFrm->RRMEnabledCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("LinkMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LinkMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("NeighborRpt (1): %d\n"), pFrm->RRMEnabledCap.NeighborRpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("parallel (1): %d\n"), pFrm->RRMEnabledCap.parallel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("repeated (1): %d\n"), pFrm->RRMEnabledCap.repeated); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconPassive (1): %d\n"), pFrm->RRMEnabledCap.BeaconPassive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconActive (1): %d\n"), pFrm->RRMEnabledCap.BeaconActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconTable (1): %d\n"), pFrm->RRMEnabledCap.BeaconTable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BeaconRepCond (1): %d\n"), pFrm->RRMEnabledCap.BeaconRepCond); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("FrameMeasurement (1): %d\n"), pFrm->RRMEnabledCap.FrameMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ChannelLoad (1): %d\n"), pFrm->RRMEnabledCap.ChannelLoad); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("NoiseHistogram (1): %d\n"), pFrm->RRMEnabledCap.NoiseHistogram); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("statistics (1): %d\n"), pFrm->RRMEnabledCap.statistics); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("LCIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.LCIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("LCIAzimuth (1): %d\n"), pFrm->RRMEnabledCap.LCIAzimuth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TCMCapability (1): %d\n"), pFrm->RRMEnabledCap.TCMCapability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("triggeredTCM (1): %d\n"), pFrm->RRMEnabledCap.triggeredTCM); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("APChanReport (1): %d\n"), pFrm->RRMEnabledCap.APChanReport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RRMMIBEnabled (1): %d\n"), pFrm->RRMEnabledCap.RRMMIBEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("operatingChanMax (3): %d\n"), pFrm->RRMEnabledCap.operatingChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("nonOperatinChanMax (3): %d\n"), pFrm->RRMEnabledCap.nonOperatinChanMax); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("MeasurementPilot (3): %d\n"), pFrm->RRMEnabledCap.MeasurementPilot); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("MeasurementPilotEnabled (1): %d\n"), pFrm->RRMEnabledCap.MeasurementPilotEnabled); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("NeighborTSFOffset (1): %d\n"), pFrm->RRMEnabledCap.NeighborTSFOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RCPIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RCPIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RSNIMeasurement (1): %d\n"), pFrm->RRMEnabledCap.RSNIMeasurement); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BssAvgAccessDelay (1): %d\n"), pFrm->RRMEnabledCap.BssAvgAccessDelay); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("BSSAvailAdmission (1): %d\n"), pFrm->RRMEnabledCap.BSSAvailAdmission); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("AntennaInformation (1): %d\n"), pFrm->RRMEnabledCap.AntennaInformation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fine_time_meas_rpt (1): %d\n"), pFrm->RRMEnabledCap.fine_time_meas_rpt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("lci_capability (1): %d\n"), pFrm->RRMEnabledCap.lci_capability); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (4): %d\n"), pFrm->RRMEnabledCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RSNOpaque:\n")); + if (!pFrm->RSNOpaque.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_data: %d.\n"), pFrm->RSNOpaque.num_data); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->RSNOpaque.data, pFrm->RSNOpaque.num_data); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("MobilityDomain:\n")); + if (!pFrm->MobilityDomain.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->MobilityDomain.MDID, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("overDSCap (1): %d\n"), pFrm->MobilityDomain.overDSCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("resourceReqCap (1): %d\n"), pFrm->MobilityDomain.resourceReqCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (6): %d\n"), pFrm->MobilityDomain.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + for (i = 0; i < pFrm->num_RICDataDesc; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RICDataDesc[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RICData:\n")); + if (!pFrm->RICDataDesc[i].RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RICDescriptor:\n")); + if (!pFrm->RICDataDesc[i].RICDescriptor.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].RICDescriptor.resourceType, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_variableData: %d.\n"), pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->RICDataDesc[i].RICDescriptor.variableData, pFrm->RICDataDesc[i].RICDescriptor.num_variableData); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TSPEC:\n")); + if (!pFrm->RICDataDesc[i].TSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].TSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].TSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("schedule (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.schedule); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused (7): %d\n"), pFrm->RICDataDesc[i].TSPEC.unused); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].TSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].TSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_TCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].TCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TCLASSPROC:\n")); + if (!pFrm->RICDataDesc[i].TCLASSPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TCLASSPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TSDelay:\n")); + if (!pFrm->RICDataDesc[i].TSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].TSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Schedule:\n")); + if (!pFrm->RICDataDesc[i].Schedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].Schedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].Schedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].Schedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].Schedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].Schedule.spec_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->RICDataDesc[i].WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->RICDataDesc[i].WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSPEC.medium_time, 2); + } + for (i = 0; i < pFrm->RICDataDesc[i].num_WMMTCLAS; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTCLAS[%d]:\n"), i); + if (!pFrm->RICDataDesc[i].WMMTCLAS[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].user_priority, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_mask, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].classifier_type) + { + case 0: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.source, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.dest, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.EthParams.type, 2); + break; + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version, 1); + switch (pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.version) + { + case 4: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.source, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.DSCP, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.proto, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV4Params.reserved, 1); + break; + case 6: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.source, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.src_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.dest_port, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.IpParams.params.IpV6Params.flow_label, 3); + break; + } + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLAS[i].info.Params8021dq.tag_type, 2); + break; + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTCLASPROC:\n")); + if (!pFrm->RICDataDesc[i].WMMTCLASPROC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTCLASPROC.processing, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTSDelay:\n")); + if (!pFrm->RICDataDesc[i].WMMTSDelay.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMTSDelay.delay, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMSchedule:\n")); + if (!pFrm->RICDataDesc[i].WMMSchedule.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (9): %d\n"), pFrm->RICDataDesc[i].WMMSchedule.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.service_interval, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.max_service_dur, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->RICDataDesc[i].WMMSchedule.spec_interval, 2); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WPA:\n")); + if (!pFrm->WPA.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.multicast_cipher, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.unicast_cipher_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.unicast_ciphers, 4 * pFrm->WPA.unicast_cipher_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.auth_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->WPA.auth_suites, 4 * pFrm->WPA.auth_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WPA.caps, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESERadMgmtCap:\n")); + if (!pFrm->ESERadMgmtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESERadMgmtCap.mgmt_state, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("mbssid_mask (3): %d\n"), pFrm->ESERadMgmtCap.mbssid_mask); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved (5): %d\n"), pFrm->ESERadMgmtCap.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESETxmitPower:\n")); + if (!pFrm->ESETxmitPower.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.power_limit, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETxmitPower.reserved, 1); + } + for (i = 0; i < pFrm->num_WMMTSPEC; ++i) + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WMMTSPEC[%d]:\n"), i); + if (!pFrm->WMMTSPEC[i].present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC[i].traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC[i].tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC[i].direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC[i].access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC[i].aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC[i].psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC[i].user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC[i].tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC[i].tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC[i].burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC[i].size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC[i].fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC[i].medium_time, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("WscReassocRes:\n")); + if (!pFrm->WscReassocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Version:\n")); + if (!pFrm->WscReassocRes.Version.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscReassocRes.Version.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscReassocRes.Version.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ResponseType:\n")); + if (!pFrm->WscReassocRes.ResponseType.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.ResponseType.resType, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("VendorExtension:\n")); + if (!pFrm->WscReassocRes.VendorExtension.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.VendorExtension.vendorId, 3); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Version2:\n")); + if (!pFrm->WscReassocRes.VendorExtension.Version2.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("minor (4): %d\n"), pFrm->WscReassocRes.VendorExtension.Version2.minor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("major (4): %d\n"), pFrm->WscReassocRes.VendorExtension.Version2.major); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("AuthorizedMACs:\n")); + if (!pFrm->WscReassocRes.VendorExtension.AuthorizedMACs.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.VendorExtension.AuthorizedMACs.mac, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("RequestToEnroll:\n")); + if (!pFrm->WscReassocRes.VendorExtension.RequestToEnroll.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->WscReassocRes.VendorExtension.RequestToEnroll.req, 1); + } + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("P2PAssocRes:\n")); + if (!pFrm->P2PAssocRes.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("P2PStatus:\n")); + if (!pFrm->P2PAssocRes.P2PStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.P2PStatus.status, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ExtendedListenTiming:\n")); + if (!pFrm->P2PAssocRes.ExtendedListenTiming.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityPeriod, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->P2PAssocRes.ExtendedListenTiming.availibilityInterval, 2); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("OBSSScanParameters:\n")); + if (!pFrm->OBSSScanParameters.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveDwell, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssChannelWidthTriggerScanInterval, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanPassiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActiveTotalPerChannel, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("QosMapSet:\n")); + if (!pFrm->QosMapSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackReAssocResponse. */ + +tANI_U32 dot11fPackSMPowerSave(tpAniSirGlobal pCtx, tDot11fSMPowerSave *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_SMPowerSave, IES_SMPowerSave); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Packed the SMPowerSave:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("SMPowerModeSet:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("PowerSave_En (1): %d\n"), pFrm->SMPowerModeSet.PowerSave_En); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("Mode (1): %d\n"), pFrm->SMPowerModeSet.Mode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("reserved (6): %d\n"), pFrm->SMPowerModeSet.reserved); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SMPOWERSAVE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackSMPowerSave. */ + +tANI_U32 dot11fPackSaQueryReq(tpAniSirGlobal pCtx, tDot11fSaQueryReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_SaQueryReq, IES_SaQueryReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("Packed the SaQueryReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("TransactionId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), ( tANI_U8* )&pFrm->TransactionId.transId, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackSaQueryReq. */ + +tANI_U32 dot11fPackSaQueryRsp(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_SaQueryRsp, IES_SaQueryRsp); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Packed the SaQueryRsp:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("TransactionId:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->TransactionId.transId, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackSaQueryRsp. */ + +tANI_U32 dot11fPackTDLSDisReq(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSDisReq, IES_TDLSDisReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Packed the TDLSDisReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSDisReq. */ + +tANI_U32 dot11fPackTDLSDisRsp(tpAniSirGlobal pCtx, tDot11fTDLSDisRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSDisRsp, IES_TDLSDisRsp); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Packed the TDLSDisRsp:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("RICData:\n")); + if (!pFrm->RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSDisRsp. */ + +tANI_U32 dot11fPackTDLSPeerTrafficInd(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficInd *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSPeerTrafficInd, IES_TDLSPeerTrafficInd); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Packed the TDLSPeerTrafficInd:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("PTIControl:\n")); + if (!pFrm->PTIControl.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->PTIControl.tid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), ( tANI_U8* )&pFrm->PTIControl.sequence_control, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("PUBufferStatus:\n")); + if (!pFrm->PUBufferStatus.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_bk_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_bk_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_be_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_be_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_vi_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_vi_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("ac_vo_traffic_aval (1): %d\n"), pFrm->PUBufferStatus.ac_vo_traffic_aval); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("reserved (4): %d\n"), pFrm->PUBufferStatus.reserved); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICIND), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSPeerTrafficInd. */ + +tANI_U32 dot11fPackTDLSPeerTrafficRsp(tpAniSirGlobal pCtx, tDot11fTDLSPeerTrafficRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSPeerTrafficRsp, IES_TDLSPeerTrafficRsp); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Packed the TDLSPeerTrafficRsp:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSPEERTRAFFICRSP), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSPeerTrafficRsp. */ + +tANI_U32 dot11fPackTDLSSetupCnf(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSSetupCnf, IES_TDLSSetupCnf); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Packed the TDLSSetupCnf:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("EDCAParamSet:\n")); + if (!pFrm->EDCAParamSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.qos, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.reserved, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acm (1): %d\n"), pFrm->EDCAParamSet.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aci (2): %d\n"), pFrm->EDCAParamSet.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused1 (1): %d\n"), pFrm->EDCAParamSet.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aifsn (4): %d\n"), pFrm->EDCAParamSet.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acm (1): %d\n"), pFrm->EDCAParamSet.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aci (2): %d\n"), pFrm->EDCAParamSet.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused2 (1): %d\n"), pFrm->EDCAParamSet.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmin (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmax (4): %d\n"), pFrm->EDCAParamSet.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acm (1): %d\n"), pFrm->EDCAParamSet.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aci (2): %d\n"), pFrm->EDCAParamSet.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused3 (1): %d\n"), pFrm->EDCAParamSet.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aifsn (4): %d\n"), pFrm->EDCAParamSet.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acm (1): %d\n"), pFrm->EDCAParamSet.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aci (2): %d\n"), pFrm->EDCAParamSet.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused4 (1): %d\n"), pFrm->EDCAParamSet.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmin (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmax (4): %d\n"), pFrm->EDCAParamSet.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->EDCAParamSet.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("HTInfo:\n")); + if (!pFrm->HTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->HTInfo.primaryChannel, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("secondaryChannelOffset (2): %d\n"), pFrm->HTInfo.secondaryChannelOffset); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("recommendedTxWidthSet (1): %d\n"), pFrm->HTInfo.recommendedTxWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rifsMode (1): %d\n"), pFrm->HTInfo.rifsMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("controlledAccessOnly (1): %d\n"), pFrm->HTInfo.controlledAccessOnly); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("serviceIntervalGranularity (3): %d\n"), pFrm->HTInfo.serviceIntervalGranularity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("opMode (2): %d\n"), pFrm->HTInfo.opMode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("nonGFDevicesPresent (1): %d\n"), pFrm->HTInfo.nonGFDevicesPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("transmitBurstLimit (1): %d\n"), pFrm->HTInfo.transmitBurstLimit); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("obssNonHTStaPresent (1): %d\n"), pFrm->HTInfo.obssNonHTStaPresent); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (11): %d\n"), pFrm->HTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("basicSTBCMCS (7): %d\n"), pFrm->HTInfo.basicSTBCMCS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("dualCTSProtection (1): %d\n"), pFrm->HTInfo.dualCTSProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("secondaryBeacon (1): %d\n"), pFrm->HTInfo.secondaryBeacon); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("lsigTXOPProtectionFullSupport (1): %d\n"), pFrm->HTInfo.lsigTXOPProtectionFullSupport); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("pcoActive (1): %d\n"), pFrm->HTInfo.pcoActive); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("pcoPhase (1): %d\n"), pFrm->HTInfo.pcoPhase); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved2 (4): %d\n"), pFrm->HTInfo.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->HTInfo.basicMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_rsvd: %d.\n"), pFrm->HTInfo.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->HTInfo.rsvd, pFrm->HTInfo.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("WMMParams:\n")); + if (!pFrm->WMMParams.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.version, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.qosInfo, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.reserved2, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aifsn (4): %d\n"), pFrm->WMMParams.acbe_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acm (1): %d\n"), pFrm->WMMParams.acbe_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_aci (2): %d\n"), pFrm->WMMParams.acbe_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused1 (1): %d\n"), pFrm->WMMParams.unused1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmin (4): %d\n"), pFrm->WMMParams.acbe_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbe_acwmax (4): %d\n"), pFrm->WMMParams.acbe_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acbe_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aifsn (4): %d\n"), pFrm->WMMParams.acbk_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acm (1): %d\n"), pFrm->WMMParams.acbk_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_aci (2): %d\n"), pFrm->WMMParams.acbk_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused2 (1): %d\n"), pFrm->WMMParams.unused2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmin (4): %d\n"), pFrm->WMMParams.acbk_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acbk_acwmax (4): %d\n"), pFrm->WMMParams.acbk_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acbk_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aifsn (4): %d\n"), pFrm->WMMParams.acvi_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acm (1): %d\n"), pFrm->WMMParams.acvi_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_aci (2): %d\n"), pFrm->WMMParams.acvi_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused3 (1): %d\n"), pFrm->WMMParams.unused3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmin (4): %d\n"), pFrm->WMMParams.acvi_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvi_acwmax (4): %d\n"), pFrm->WMMParams.acvi_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acvi_txoplimit, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aifsn (4): %d\n"), pFrm->WMMParams.acvo_aifsn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acm (1): %d\n"), pFrm->WMMParams.acvo_acm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_aci (2): %d\n"), pFrm->WMMParams.acvo_aci); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("unused4 (1): %d\n"), pFrm->WMMParams.unused4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmin (4): %d\n"), pFrm->WMMParams.acvo_acwmin); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("acvo_acwmax (4): %d\n"), pFrm->WMMParams.acvo_acwmax); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->WMMParams.acvo_txoplimit, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("VHTOperation:\n")); + if (!pFrm->VHTOperation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanWidth, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg1, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSSetupCnf. */ + +tANI_U32 dot11fPackTDLSSetupReq(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSSetupReq, IES_TDLSSetupReq); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Packed the TDLSSetupReq:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("RICData:\n")); + if (!pFrm->RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("AID:\n")); + if (!pFrm->AID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->AID.assocId, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSSetupReq. */ + +tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSSetupRsp, IES_TDLSSetupRsp); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Packed the TDLSSetupRsp:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Status:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Status.status, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("SuppRates:\n")); + if (!pFrm->SuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_rates: %d.\n"), pFrm->SuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->SuppRates.rates, pFrm->SuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ExtSuppRates:\n")); + if (!pFrm->ExtSuppRates.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_rates: %d.\n"), pFrm->ExtSuppRates.num_rates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->ExtSuppRates.rates, pFrm->ExtSuppRates.num_rates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("SuppChannels:\n")); + if (!pFrm->SuppChannels.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_bands: %d.\n"), pFrm->SuppChannels.num_bands); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->SuppChannels.bands, 2 * pFrm->SuppChannels.num_bands); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("RSN:\n")); + if (!pFrm->RSN.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.version, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.gp_cipher_suite, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.pwise_cipher_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->RSN.pwise_cipher_suites, 4 * pFrm->RSN.pwise_cipher_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.akm_suite_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->RSN.akm_suites, 4 * pFrm->RSN.akm_suite_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.RSN_Cap, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.pmkid_count, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->RSN.pmkid, 16 * pFrm->RSN.pmkid_count); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RSN.gp_mgmt_cipher_suite, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("SuppOperatingClasses:\n")); + if (!pFrm->SuppOperatingClasses.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_classes: %d.\n"), pFrm->SuppOperatingClasses.num_classes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->SuppOperatingClasses.classes, pFrm->SuppOperatingClasses.num_classes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("QOSCapsStation:\n")); + if (!pFrm->QOSCapsStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("TimeoutInterval:\n")); + if (!pFrm->TimeoutInterval.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutType, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->TimeoutInterval.timeoutValue, 4); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("RICData:\n")); + if (!pFrm->RICData.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RICData.Identifier, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RICData.resourceDescCount, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->RICData.statusCode, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("HTCaps:\n")); + if (!pFrm->HTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("advCodingCap (1): %d\n"), pFrm->HTCaps.advCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("supportedChannelWidthSet (1): %d\n"), pFrm->HTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("mimoPowerSave (2): %d\n"), pFrm->HTCaps.mimoPowerSave); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("greenField (1): %d\n"), pFrm->HTCaps.greenField); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI20MHz (1): %d\n"), pFrm->HTCaps.shortGI20MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI40MHz (1): %d\n"), pFrm->HTCaps.shortGI40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSTBC (1): %d\n"), pFrm->HTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxSTBC (2): %d\n"), pFrm->HTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("delayedBA (1): %d\n"), pFrm->HTCaps.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maximalAMSDUsize (1): %d\n"), pFrm->HTCaps.maximalAMSDUsize); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("dsssCckMode40MHz (1): %d\n"), pFrm->HTCaps.dsssCckMode40MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("psmp (1): %d\n"), pFrm->HTCaps.psmp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("stbcControlFrame (1): %d\n"), pFrm->HTCaps.stbcControlFrame); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("lsigTXOPProtection (1): %d\n"), pFrm->HTCaps.lsigTXOPProtection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maxRxAMPDUFactor (2): %d\n"), pFrm->HTCaps.maxRxAMPDUFactor); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("mpduDensity (3): %d\n"), pFrm->HTCaps.mpduDensity); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved1 (3): %d\n"), pFrm->HTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->HTCaps.supportedMCSSet, 16); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("pco (1): %d\n"), pFrm->HTCaps.pco); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("transitionTime (2): %d\n"), pFrm->HTCaps.transitionTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved2 (5): %d\n"), pFrm->HTCaps.reserved2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("mcsFeedback (2): %d\n"), pFrm->HTCaps.mcsFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (6): %d\n"), pFrm->HTCaps.reserved3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txBF (1): %d\n"), pFrm->HTCaps.txBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxStaggeredSounding (1): %d\n"), pFrm->HTCaps.rxStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txStaggeredSounding (1): %d\n"), pFrm->HTCaps.txStaggeredSounding); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxZLF (1): %d\n"), pFrm->HTCaps.rxZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txZLF (1): %d\n"), pFrm->HTCaps.txZLF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("implicitTxBF (1): %d\n"), pFrm->HTCaps.implicitTxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("calibration (2): %d\n"), pFrm->HTCaps.calibration); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCSITxBF (1): %d\n"), pFrm->HTCaps.explicitCSITxBF); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitUncompressedSteeringMatrix (1): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrix); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitBFCSIFeedback (3): %d\n"), pFrm->HTCaps.explicitBFCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitUncompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitUncompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCompressedSteeringMatrixFeedback (3): %d\n"), pFrm->HTCaps.explicitCompressedSteeringMatrixFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("csiNumBFAntennae (2): %d\n"), pFrm->HTCaps.csiNumBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("uncompressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.uncompressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("compressedSteeringMatrixBFAntennae (2): %d\n"), pFrm->HTCaps.compressedSteeringMatrixBFAntennae); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved4 (7): %d\n"), pFrm->HTCaps.reserved4); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("antennaSelection (1): %d\n"), pFrm->HTCaps.antennaSelection); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCSIFeedbackTx (1): %d\n"), pFrm->HTCaps.explicitCSIFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("antennaIndicesFeedbackTx (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedbackTx); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("explicitCSIFeedback (1): %d\n"), pFrm->HTCaps.explicitCSIFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("antennaIndicesFeedback (1): %d\n"), pFrm->HTCaps.antennaIndicesFeedback); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxAS (1): %d\n"), pFrm->HTCaps.rxAS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSoundingPPDUs (1): %d\n"), pFrm->HTCaps.txSoundingPPDUs); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved5 (1): %d\n"), pFrm->HTCaps.reserved5); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_rsvd: %d.\n"), pFrm->HTCaps.num_rsvd); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->HTCaps.rsvd, pFrm->HTCaps.num_rsvd); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("HT2040BSSCoexistence:\n")); + if (!pFrm->HT2040BSSCoexistence.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("infoRequest (1): %d\n"), pFrm->HT2040BSSCoexistence.infoRequest); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("fortyMHzIntolerant (1): %d\n"), pFrm->HT2040BSSCoexistence.fortyMHzIntolerant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("twentyMHzBssWidthReq (1): %d\n"), pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("obssScanExemptionReq (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("obssScanExemptionGrant (1): %d\n"), pFrm->HT2040BSSCoexistence.obssScanExemptionGrant); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("unused (3): %d\n"), pFrm->HT2040BSSCoexistence.unused); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("WMMInfoStation:\n")); + if (!pFrm->WMMInfoStation.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->WMMInfoStation.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->WMMInfoStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->WMMInfoStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved1 (1): %d\n"), pFrm->WMMInfoStation.reserved1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->WMMInfoStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved2 (1): %d\n"), pFrm->WMMInfoStation.reserved2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("AID:\n")); + if (!pFrm->AID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->AID.assocId, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("VHTCaps:\n")); + if (!pFrm->VHTCaps.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maxMPDULen (2): %d\n"), pFrm->VHTCaps.maxMPDULen); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("supportedChannelWidthSet (2): %d\n"), pFrm->VHTCaps.supportedChannelWidthSet); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("ldpcCodingCap (1): %d\n"), pFrm->VHTCaps.ldpcCodingCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI80MHz (1): %d\n"), pFrm->VHTCaps.shortGI80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("shortGI160and80plus80MHz (1): %d\n"), pFrm->VHTCaps.shortGI160and80plus80MHz); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSTBC (1): %d\n"), pFrm->VHTCaps.txSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxSTBC (3): %d\n"), pFrm->VHTCaps.rxSTBC); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("suBeamFormerCap (1): %d\n"), pFrm->VHTCaps.suBeamFormerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("suBeamformeeCap (1): %d\n"), pFrm->VHTCaps.suBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("csnofBeamformerAntSup (3): %d\n"), pFrm->VHTCaps.csnofBeamformerAntSup); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("numSoundingDim (3): %d\n"), pFrm->VHTCaps.numSoundingDim); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("muBeamformerCap (1): %d\n"), pFrm->VHTCaps.muBeamformerCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("muBeamformeeCap (1): %d\n"), pFrm->VHTCaps.muBeamformeeCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("vhtTXOPPS (1): %d\n"), pFrm->VHTCaps.vhtTXOPPS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("htcVHTCap (1): %d\n"), pFrm->VHTCaps.htcVHTCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("maxAMPDULenExp (3): %d\n"), pFrm->VHTCaps.maxAMPDULenExp); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("vhtLinkAdaptCap (2): %d\n"), pFrm->VHTCaps.vhtLinkAdaptCap); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxAntPattern (1): %d\n"), pFrm->VHTCaps.rxAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txAntPattern (1): %d\n"), pFrm->VHTCaps.txAntPattern); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved1 (2): %d\n"), pFrm->VHTCaps.reserved1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->VHTCaps.rxMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxHighSupDataRate (13): %d\n"), pFrm->VHTCaps.rxHighSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved2 (3): %d\n"), pFrm->VHTCaps.reserved2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->VHTCaps.txMCSMap, 2); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSSetupRsp. */ + +tANI_U32 dot11fPackTDLSTeardown(tpAniSirGlobal pCtx, tDot11fTDLSTeardown *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TDLSTeardown, IES_TDLSTeardown); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Packed the TDLSTeardown:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Reason:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->Reason.code, 2); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("FTInfo:\n")); + if (!pFrm->FTInfo.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("reserved (8): %d\n"), pFrm->FTInfo.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IECount (8): %d\n"), pFrm->FTInfo.IECount); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.MIC, 16); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.Anonce, 32); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.Snonce, 32); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("R1KH_ID:\n")); + if (!pFrm->FTInfo.R1KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.R1KH_ID.PMK_R1_ID, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("GTK:\n")); + if (!pFrm->FTInfo.GTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("keyId (2): %d\n"), pFrm->FTInfo.GTK.keyId); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("reserved (14): %d\n"), pFrm->FTInfo.GTK.reserved); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.GTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.GTK.RSC, 8); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_key: %d.\n"), pFrm->FTInfo.GTK.num_key); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.GTK.key, pFrm->FTInfo.GTK.num_key); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("R0KH_ID:\n")); + if (!pFrm->FTInfo.R0KH_ID.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("LinkIdentifier:\n")); + if (!pFrm->LinkIdentifier.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->LinkIdentifier.bssid, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->LinkIdentifier.InitStaAddr, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->LinkIdentifier.RespStaAddr, 6); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTDLSTeardown. */ + +tANI_U32 dot11fPackTPCReport(tpAniSirGlobal pCtx, tDot11fTPCReport *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TPCReport, IES_TPCReport); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Packed the TPCReport:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("TPCReport:\n")); + if (!pFrm->TPCReport.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->TPCReport.tx_power, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), ( tANI_U8* )&pFrm->TPCReport.link_margin, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREPORT), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTPCReport. */ + +tANI_U32 dot11fPackTPCRequest(tpAniSirGlobal pCtx, tDot11fTPCRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TPCRequest, IES_TPCRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Packed the TPCRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("TPCRequest:\n")); + if (!pFrm->TPCRequest.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TPCREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTPCRequest. */ + +tANI_U32 dot11fPackTimingAdvertisementFrame(tpAniSirGlobal pCtx, tDot11fTimingAdvertisementFrame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_TimingAdvertisementFrame, IES_TimingAdvertisementFrame); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Packed the TimingAdvertisementFrame:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("TimeStamp:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeStamp.timestamp, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Capabilities:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("ess (1): %d\n"), pFrm->Capabilities.ess); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("ibss (1): %d\n"), pFrm->Capabilities.ibss); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("cfPollable (1): %d\n"), pFrm->Capabilities.cfPollable); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("cfPollReq (1): %d\n"), pFrm->Capabilities.cfPollReq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("privacy (1): %d\n"), pFrm->Capabilities.privacy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("shortPreamble (1): %d\n"), pFrm->Capabilities.shortPreamble); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("pbcc (1): %d\n"), pFrm->Capabilities.pbcc); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("channelAgility (1): %d\n"), pFrm->Capabilities.channelAgility); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("spectrumMgt (1): %d\n"), pFrm->Capabilities.spectrumMgt); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("qos (1): %d\n"), pFrm->Capabilities.qos); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("shortSlotTime (1): %d\n"), pFrm->Capabilities.shortSlotTime); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("apsd (1): %d\n"), pFrm->Capabilities.apsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("rrm (1): %d\n"), pFrm->Capabilities.rrm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("dsssOfdm (1): %d\n"), pFrm->Capabilities.dsssOfdm); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("delayedBA (1): %d\n"), pFrm->Capabilities.delayedBA); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("immediateBA (1): %d\n"), pFrm->Capabilities.immediateBA); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Country:\n")); + if (!pFrm->Country.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->Country.country, 3); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("num_triplets: %d.\n"), pFrm->Country.num_triplets); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* ) pFrm->Country.triplets, 3 * pFrm->Country.num_triplets); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("PowerConstraints:\n")); + if (!pFrm->PowerConstraints.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->PowerConstraints.localPowerConstraints, 1); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("TimeAdvertisement:\n")); + if (!pFrm->TimeAdvertisement.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeAdvertisement.timing_capabilities, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeAdvertisement.time_value, 10); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* )&pFrm->TimeAdvertisement.time_error, 5); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("ExtCap:\n")); + if (!pFrm->ExtCap.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("num_bytes: %d.\n"), pFrm->ExtCap.num_bytes); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), ( tANI_U8* ) pFrm->ExtCap.bytes, pFrm->ExtCap.num_bytes); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Vendor1IE:\n")); + if (!pFrm->Vendor1IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Vendor2IE:\n")); + if (!pFrm->Vendor2IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Vendor3IE:\n")); + if (!pFrm->Vendor3IE.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("Not present.\n")); + } + else + { + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TIMINGADVERTISEMENTFRAME), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackTimingAdvertisementFrame. */ + +tANI_U32 dot11fPackVHTGidManagementActionFrame(tpAniSirGlobal pCtx, tDot11fVHTGidManagementActionFrame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_VHTGidManagementActionFrame, IES_VHTGidManagementActionFrame); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("Packed the VHTGidManagementActionFrame:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("VhtMembershipStatusArray:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->VhtMembershipStatusArray.membershipStatusArray, 8); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("VhtUserPositionArray:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), ( tANI_U8* )&pFrm->VhtUserPositionArray.userPositionArray, 16); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_VHTGIDMANAGEMENTACTIONFRAME), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackVHTGidManagementActionFrame. */ + +tANI_U32 dot11fPackWMMAddTSRequest(tpAniSirGlobal pCtx, tDot11fWMMAddTSRequest *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_WMMAddTSRequest, IES_WMMAddTSRequest); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Packed the WMMAddTSRequest:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("StatusCode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->StatusCode.statusCode, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("ESETrafStrmRateSet:\n")); + if (!pFrm->ESETrafStrmRateSet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* )&pFrm->ESETrafStrmRateSet.tsid, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("num_tsrates: %d.\n"), pFrm->ESETrafStrmRateSet.num_tsrates); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), ( tANI_U8* ) pFrm->ESETrafStrmRateSet.tsrates, pFrm->ESETrafStrmRateSet.num_tsrates); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSREQUEST), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackWMMAddTSRequest. */ + +tANI_U32 dot11fPackWMMAddTSResponse(tpAniSirGlobal pCtx, tDot11fWMMAddTSResponse *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_WMMAddTSResponse, IES_WMMAddTSResponse); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Packed the WMMAddTSResponse:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("StatusCode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->StatusCode.statusCode, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("ESETrafStrmMet:\n")); + if (!pFrm->ESETrafStrmMet.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.tsid, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.state, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), ( tANI_U8* )&pFrm->ESETrafStrmMet.msmt_interval, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMADDTSRESPONSE), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackWMMAddTSResponse. */ + +tANI_U32 dot11fPackWMMDelTS(tpAniSirGlobal pCtx, tDot11fWMMDelTS *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_WMMDelTS, IES_WMMDelTS); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Packed the WMMDelTS:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("DialogToken:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->DialogToken.token, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("StatusCode:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->StatusCode.statusCode, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("WMMTSPEC:\n")); + if (!pFrm->WMMTSPEC.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.version, 1); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("traffic_type (1): %d\n"), pFrm->WMMTSPEC.traffic_type); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("tsid (4): %d\n"), pFrm->WMMTSPEC.tsid); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("direction (2): %d\n"), pFrm->WMMTSPEC.direction); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("access_policy (2): %d\n"), pFrm->WMMTSPEC.access_policy); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("aggregation (1): %d\n"), pFrm->WMMTSPEC.aggregation); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("psb (1): %d\n"), pFrm->WMMTSPEC.psb); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("user_priority (3): %d\n"), pFrm->WMMTSPEC.user_priority); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("tsinfo_ack_pol (2): %d\n"), pFrm->WMMTSPEC.tsinfo_ack_pol); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("tsinfo_rsvd (7): %d\n"), pFrm->WMMTSPEC.tsinfo_rsvd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("burst_size_defn (1): %d\n"), pFrm->WMMTSPEC.burst_size_defn); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("size (15): %d\n"), pFrm->WMMTSPEC.size); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("fixed (1): %d\n"), pFrm->WMMTSPEC.fixed); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.max_msdu_size, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.min_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.max_service_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.inactivity_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.suspension_int, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.service_start_time, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.min_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.mean_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.peak_data_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.burst_size, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.delay_bound, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.min_phy_rate, 4); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.surplus_bw_allowance, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), ( tANI_U8* )&pFrm->WMMTSPEC.medium_time, 2); + } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_WMMDELTS), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackWMMDelTS. */ + +tANI_U32 dot11fPackext_channel_switch_action_frame(tpAniSirGlobal pCtx, tDot11fext_channel_switch_action_frame *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) +{ + tANI_U32 i = 0; + tANI_U32 status = 0; + (void)i; + *pnConsumed = 0U; + status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_ext_channel_switch_action_frame, IES_ext_channel_switch_action_frame); + +# ifdef DOT11F_DUMP_FRAMES + if (!DOT11F_FAILED(status)) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("Packed the ext_channel_switch_action_frame:\n")); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("Category:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), ( tANI_U8* )&pFrm->Category.category, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("Action:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), ( tANI_U8* )&pFrm->Action.action, 1); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("ext_chan_switch_ann_action:\n")); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("switch_mode (8): %d\n"), pFrm->ext_chan_switch_ann_action.switch_mode); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("op_class (8): %d\n"), pFrm->ext_chan_switch_ann_action.op_class); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("new_channel (8): %d\n"), pFrm->ext_chan_switch_ann_action.new_channel); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("switch_count (8): %d\n"), pFrm->ext_chan_switch_ann_action.switch_count); + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), FRFL("to:\n")); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME), pBuf, nBuf); + } +# endif // DOT11F_DUMP_FRAMES + return status; + +} /* End dot11fUnpackext_channel_switch_action_frame. */ + +static tANI_U32 PackCore(tpAniSirGlobal pCtx, + tANI_U8 *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed, + const tFFDefn FFs[], + const tIEDefn IEs[]) +{ + const tFFDefn *pFf; + const tIEDefn *pIe; + tFRAMES_BOOL *pfFound; + tANI_U8 *pBufRemaining; + tANI_U16 i; + tANI_U32 nBufRemaining, status, len; + tANI_U32 countOffset = 0; + + (void)pCtx; /* Shutup the compiler if we have no FFs nor IEs... */ + i=0; + + DOT11F_PARAMETER_CHECK2(pSrc, pBuf, nBuf, pnConsumed); + + status = DOT11F_PARSE_SUCCESS; + pBufRemaining = pBuf; + nBufRemaining = nBuf; + + pFf = &( FFs[0] ); + while ( pFf->size ) + { + if ( pFf->size > nBufRemaining ) + { + FRAMES_LOG3(pCtx, FRLOGE, FRFL("The Fixed Field %s req" + "uires %d bytes, but there are only %d remaining.\n"), + pFf->name, pFf->size, nBufRemaining); + return DOT11F_BUFFER_OVERFLOW; + } + + switch ( pFf->sig ) + { + case SigFfAID: + dot11fPackFfAID(pCtx, (tDot11fFfAID* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAction: + dot11fPackFfAction(pCtx, (tDot11fFfAction* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAddBAParameterSet: + dot11fPackFfAddBAParameterSet(pCtx, (tDot11fFfAddBAParameterSet* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAuthAlgo: + dot11fPackFfAuthAlgo(pCtx, (tDot11fFfAuthAlgo* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAuthSeqNo: + dot11fPackFfAuthSeqNo(pCtx, (tDot11fFfAuthSeqNo* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfBAStartingSequenceControl: + dot11fPackFfBAStartingSequenceControl(pCtx, (tDot11fFfBAStartingSequenceControl* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfBATimeout: + dot11fPackFfBATimeout(pCtx, (tDot11fFfBATimeout* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfBeaconInterval: + dot11fPackFfBeaconInterval(pCtx, (tDot11fFfBeaconInterval* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfCapabilities: + dot11fPackFfCapabilities(pCtx, (tDot11fFfCapabilities* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfCategory: + dot11fPackFfCategory(pCtx, (tDot11fFfCategory* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfCurrentAPAddress: + dot11fPackFfCurrentAPAddress(pCtx, (tDot11fFfCurrentAPAddress* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfDelBAParameterSet: + dot11fPackFfDelBAParameterSet(pCtx, (tDot11fFfDelBAParameterSet* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfDialogToken: + dot11fPackFfDialogToken(pCtx, (tDot11fFfDialogToken* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfLinkMargin: + dot11fPackFfLinkMargin(pCtx, (tDot11fFfLinkMargin* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfListenInterval: + dot11fPackFfListenInterval(pCtx, (tDot11fFfListenInterval* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfMaxTxPower: + dot11fPackFfMaxTxPower(pCtx, (tDot11fFfMaxTxPower* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfNumOfRepetitions: + dot11fPackFfNumOfRepetitions(pCtx, (tDot11fFfNumOfRepetitions* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfOperatingMode: + dot11fPackFfOperatingMode(pCtx, (tDot11fFfOperatingMode* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfP2POUI: + dot11fPackFfP2POUI(pCtx, (tDot11fFfP2POUI* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfP2POUISubType: + dot11fPackFfP2POUISubType(pCtx, (tDot11fFfP2POUISubType* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfRCPI: + dot11fPackFfRCPI(pCtx, (tDot11fFfRCPI* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfRSNI: + dot11fPackFfRSNI(pCtx, (tDot11fFfRSNI* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfReason: + dot11fPackFfReason(pCtx, (tDot11fFfReason* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfRxAntennaId: + dot11fPackFfRxAntennaId(pCtx, (tDot11fFfRxAntennaId* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfSMPowerModeSet: + dot11fPackFfSMPowerModeSet(pCtx, (tDot11fFfSMPowerModeSet* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfStatus: + dot11fPackFfStatus(pCtx, (tDot11fFfStatus* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfStatusCode: + dot11fPackFfStatusCode(pCtx, (tDot11fFfStatusCode* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTPCEleID: + dot11fPackFfTPCEleID(pCtx, (tDot11fFfTPCEleID* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTPCEleLen: + dot11fPackFfTPCEleLen(pCtx, (tDot11fFfTPCEleLen* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTSInfo: + dot11fPackFfTSInfo(pCtx, (tDot11fFfTSInfo* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTimeStamp: + dot11fPackFfTimeStamp(pCtx, (tDot11fFfTimeStamp* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTransactionId: + dot11fPackFfTransactionId(pCtx, (tDot11fFfTransactionId* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTxAntennaId: + dot11fPackFfTxAntennaId(pCtx, (tDot11fFfTxAntennaId* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTxPower: + dot11fPackFfTxPower(pCtx, (tDot11fFfTxPower* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfVhtMembershipStatusArray: + dot11fPackFfVhtMembershipStatusArray(pCtx, (tDot11fFfVhtMembershipStatusArray* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfVhtUserPositionArray: + dot11fPackFfVhtUserPositionArray(pCtx, (tDot11fFfVhtUserPositionArray* )(pSrc + pFf->offset), pBufRemaining); + break; + case SigFfext_chan_switch_ann_action: + dot11fPackFfext_chan_switch_ann_action(pCtx, (tDot11fFfext_chan_switch_ann_action* )(pSrc + pFf->offset), pBufRemaining); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" + "'t know about the Fixed Field %d; this is most l" + "ikely a bug in 'framesg'.\n"), pFf->sig); + return DOT11F_INTERNAL_ERROR; + } + + pBufRemaining += pFf->size; + nBufRemaining -= pFf->size; + *pnConsumed += pFf->size; + ++pFf; + + } + + pIe = &( IEs[0] ); + while ( 0xff != pIe->eid ) + { + pfFound = (tFRAMES_BOOL*)(pSrc + pIe->offset + + pIe->presenceOffset); + if ( *pfFound && pIe->minSize > nBufRemaining ) + { + FRAMES_LOG3(pCtx, FRLOGE, FRFL("The IE %s takes at le" + "ast %d bytes, but there are only %d left in the b" + "uffer.\n"), pIe->name, pIe->minSize, nBufRemaining); + return DOT11F_BUFFER_OVERFLOW; + } + + + countOffset = ( (0 == pIe->arraybound) ? 1: *(tANI_U16* )(pSrc + pIe->countOffset) ); + for (i = 0; i < countOffset; ++i) + { + len = 0U; + switch ( pIe->sig ) + { + case SigIeCondensedCountryStr: + status |= dot11fPackIeCondensedCountryStr(pCtx, ( tDot11fIECondensedCountryStr* )(pSrc + pIe->offset + sizeof(tDot11fIECondensedCountryStr) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeGTK: + status |= dot11fPackIeGTK(pCtx, ( tDot11fIEGTK* )(pSrc + pIe->offset + sizeof(tDot11fIEGTK) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeIGTK: + status |= dot11fPackIeIGTK(pCtx, ( tDot11fIEIGTK* )(pSrc + pIe->offset + sizeof(tDot11fIEIGTK) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeR0KH_ID: + status |= dot11fPackIeR0KH_ID(pCtx, ( tDot11fIER0KH_ID* )(pSrc + pIe->offset + sizeof(tDot11fIER0KH_ID) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeR1KH_ID: + status |= dot11fPackIeR1KH_ID(pCtx, ( tDot11fIER1KH_ID* )(pSrc + pIe->offset + sizeof(tDot11fIER1KH_ID) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTSFInfo: + status |= dot11fPackIeTSFInfo(pCtx, ( tDot11fIETSFInfo* )(pSrc + pIe->offset + sizeof(tDot11fIETSFInfo) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeAPChannelReport: + status |= dot11fPackIeAPChannelReport(pCtx, ( tDot11fIEAPChannelReport* )(pSrc + pIe->offset + sizeof(tDot11fIEAPChannelReport) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeBcnReportingDetail: + status |= dot11fPackIeBcnReportingDetail(pCtx, ( tDot11fIEBcnReportingDetail* )(pSrc + pIe->offset + sizeof(tDot11fIEBcnReportingDetail) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeBeaconReportFrmBody: + status |= dot11fPackIeBeaconReportFrmBody(pCtx, ( tDot11fIEBeaconReportFrmBody* )(pSrc + pIe->offset + sizeof(tDot11fIEBeaconReportFrmBody) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeBeaconReporting: + status |= dot11fPackIeBeaconReporting(pCtx, ( tDot11fIEBeaconReporting* )(pSrc + pIe->offset + sizeof(tDot11fIEBeaconReporting) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeMeasurementPilot: + status |= dot11fPackIeMeasurementPilot(pCtx, ( tDot11fIEMeasurementPilot* )(pSrc + pIe->offset + sizeof(tDot11fIEMeasurementPilot) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeMultiBssid: + status |= dot11fPackIeMultiBssid(pCtx, ( tDot11fIEMultiBssid* )(pSrc + pIe->offset + sizeof(tDot11fIEMultiBssid) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRICData: + status |= dot11fPackIeRICData(pCtx, ( tDot11fIERICData* )(pSrc + pIe->offset + sizeof(tDot11fIERICData) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRICDescriptor: + status |= dot11fPackIeRICDescriptor(pCtx, ( tDot11fIERICDescriptor* )(pSrc + pIe->offset + sizeof(tDot11fIERICDescriptor) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRRMEnabledCap: + status |= dot11fPackIeRRMEnabledCap(pCtx, ( tDot11fIERRMEnabledCap* )(pSrc + pIe->offset + sizeof(tDot11fIERRMEnabledCap) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRequestedInfo: + status |= dot11fPackIeRequestedInfo(pCtx, ( tDot11fIERequestedInfo* )(pSrc + pIe->offset + sizeof(tDot11fIERequestedInfo) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeSSID: + status |= dot11fPackIeSSID(pCtx, ( tDot11fIESSID* )(pSrc + pIe->offset + sizeof(tDot11fIESSID) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeSchedule: + status |= dot11fPackIeSchedule(pCtx, ( tDot11fIESchedule* )(pSrc + pIe->offset + sizeof(tDot11fIESchedule) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTCLAS: + status |= dot11fPackIeTCLAS(pCtx, ( tDot11fIETCLAS* )(pSrc + pIe->offset + sizeof(tDot11fIETCLAS) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTCLASSPROC: + status |= dot11fPackIeTCLASSPROC(pCtx, ( tDot11fIETCLASSPROC* )(pSrc + pIe->offset + sizeof(tDot11fIETCLASSPROC) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTSDelay: + status |= dot11fPackIeTSDelay(pCtx, ( tDot11fIETSDelay* )(pSrc + pIe->offset + sizeof(tDot11fIETSDelay) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTSPEC: + status |= dot11fPackIeTSPEC(pCtx, ( tDot11fIETSPEC* )(pSrc + pIe->offset + sizeof(tDot11fIETSPEC) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMSchedule: + status |= dot11fPackIeWMMSchedule(pCtx, ( tDot11fIEWMMSchedule* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMSchedule) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTCLAS: + status |= dot11fPackIeWMMTCLAS(pCtx, ( tDot11fIEWMMTCLAS* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMTCLAS) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTCLASPROC: + status |= dot11fPackIeWMMTCLASPROC(pCtx, ( tDot11fIEWMMTCLASPROC* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMTCLASPROC) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTSDelay: + status |= dot11fPackIeWMMTSDelay(pCtx, ( tDot11fIEWMMTSDelay* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMTSDelay) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTSPEC: + status |= dot11fPackIeWMMTSPEC(pCtx, ( tDot11fIEWMMTSPEC* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMTSPEC) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWiderBWChanSwitchAnn: + status |= dot11fPackIeWiderBWChanSwitchAnn(pCtx, ( tDot11fIEWiderBWChanSwitchAnn* )(pSrc + pIe->offset + sizeof(tDot11fIEWiderBWChanSwitchAnn) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeAID: + status |= dot11fPackIeAID(pCtx, ( tDot11fIEAID* )(pSrc + pIe->offset + sizeof(tDot11fIEAID) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeCFParams: + status |= dot11fPackIeCFParams(pCtx, ( tDot11fIECFParams* )(pSrc + pIe->offset + sizeof(tDot11fIECFParams) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeChallengeText: + status |= dot11fPackIeChallengeText(pCtx, ( tDot11fIEChallengeText* )(pSrc + pIe->offset + sizeof(tDot11fIEChallengeText) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeChanSwitchAnn: + status |= dot11fPackIeChanSwitchAnn(pCtx, ( tDot11fIEChanSwitchAnn* )(pSrc + pIe->offset + sizeof(tDot11fIEChanSwitchAnn) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeChannelSwitchWrapper: + status |= dot11fPackIeChannelSwitchWrapper(pCtx, ( tDot11fIEChannelSwitchWrapper* )(pSrc + pIe->offset + sizeof(tDot11fIEChannelSwitchWrapper) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeCountry: + status |= dot11fPackIeCountry(pCtx, ( tDot11fIECountry* )(pSrc + pIe->offset + sizeof(tDot11fIECountry) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeDSParams: + status |= dot11fPackIeDSParams(pCtx, ( tDot11fIEDSParams* )(pSrc + pIe->offset + sizeof(tDot11fIEDSParams) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeEDCAParamSet: + status |= dot11fPackIeEDCAParamSet(pCtx, ( tDot11fIEEDCAParamSet* )(pSrc + pIe->offset + sizeof(tDot11fIEEDCAParamSet) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeERPInfo: + status |= dot11fPackIeERPInfo(pCtx, ( tDot11fIEERPInfo* )(pSrc + pIe->offset + sizeof(tDot11fIEERPInfo) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeESECckmOpaque: + status |= dot11fPackIeESECckmOpaque(pCtx, ( tDot11fIEESECckmOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIEESECckmOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeESERadMgmtCap: + status |= dot11fPackIeESERadMgmtCap(pCtx, ( tDot11fIEESERadMgmtCap* )(pSrc + pIe->offset + sizeof(tDot11fIEESERadMgmtCap) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeESETrafStrmMet: + status |= dot11fPackIeESETrafStrmMet(pCtx, ( tDot11fIEESETrafStrmMet* )(pSrc + pIe->offset + sizeof(tDot11fIEESETrafStrmMet) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeESETrafStrmRateSet: + status |= dot11fPackIeESETrafStrmRateSet(pCtx, ( tDot11fIEESETrafStrmRateSet* )(pSrc + pIe->offset + sizeof(tDot11fIEESETrafStrmRateSet) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeESETxmitPower: + status |= dot11fPackIeESETxmitPower(pCtx, ( tDot11fIEESETxmitPower* )(pSrc + pIe->offset + sizeof(tDot11fIEESETxmitPower) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeESEVersion: + status |= dot11fPackIeESEVersion(pCtx, ( tDot11fIEESEVersion* )(pSrc + pIe->offset + sizeof(tDot11fIEESEVersion) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeExtCap: + status |= dot11fPackIeExtCap(pCtx, ( tDot11fIEExtCap* )(pSrc + pIe->offset + sizeof(tDot11fIEExtCap) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeExtSuppRates: + status |= dot11fPackIeExtSuppRates(pCtx, ( tDot11fIEExtSuppRates* )(pSrc + pIe->offset + sizeof(tDot11fIEExtSuppRates) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeFHParamSet: + status |= dot11fPackIeFHParamSet(pCtx, ( tDot11fIEFHParamSet* )(pSrc + pIe->offset + sizeof(tDot11fIEFHParamSet) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeFHParams: + status |= dot11fPackIeFHParams(pCtx, ( tDot11fIEFHParams* )(pSrc + pIe->offset + sizeof(tDot11fIEFHParams) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeFHPattTable: + status |= dot11fPackIeFHPattTable(pCtx, ( tDot11fIEFHPattTable* )(pSrc + pIe->offset + sizeof(tDot11fIEFHPattTable) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeFTInfo: + status |= dot11fPackIeFTInfo(pCtx, ( tDot11fIEFTInfo* )(pSrc + pIe->offset + sizeof(tDot11fIEFTInfo) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeHT2040BSSCoexistence: + status |= dot11fPackIeHT2040BSSCoexistence(pCtx, ( tDot11fIEHT2040BSSCoexistence* )(pSrc + pIe->offset + sizeof(tDot11fIEHT2040BSSCoexistence) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeHT2040BSSIntolerantReport: + status |= dot11fPackIeHT2040BSSIntolerantReport(pCtx, ( tDot11fIEHT2040BSSIntolerantReport* )(pSrc + pIe->offset + sizeof(tDot11fIEHT2040BSSIntolerantReport) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeHTCaps: + status |= dot11fPackIeHTCaps(pCtx, ( tDot11fIEHTCaps* )(pSrc + pIe->offset + sizeof(tDot11fIEHTCaps) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeHTInfo: + status |= dot11fPackIeHTInfo(pCtx, ( tDot11fIEHTInfo* )(pSrc + pIe->offset + sizeof(tDot11fIEHTInfo) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeIBSSParams: + status |= dot11fPackIeIBSSParams(pCtx, ( tDot11fIEIBSSParams* )(pSrc + pIe->offset + sizeof(tDot11fIEIBSSParams) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeLinkIdentifier: + status |= dot11fPackIeLinkIdentifier(pCtx, ( tDot11fIELinkIdentifier* )(pSrc + pIe->offset + sizeof(tDot11fIELinkIdentifier) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeMeasurementReport: + status |= dot11fPackIeMeasurementReport(pCtx, ( tDot11fIEMeasurementReport* )(pSrc + pIe->offset + sizeof(tDot11fIEMeasurementReport) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeMeasurementRequest: + status |= dot11fPackIeMeasurementRequest(pCtx, ( tDot11fIEMeasurementRequest* )(pSrc + pIe->offset + sizeof(tDot11fIEMeasurementRequest) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeMobilityDomain: + status |= dot11fPackIeMobilityDomain(pCtx, ( tDot11fIEMobilityDomain* )(pSrc + pIe->offset + sizeof(tDot11fIEMobilityDomain) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeNeighborReport: + status |= dot11fPackIeNeighborReport(pCtx, ( tDot11fIENeighborReport* )(pSrc + pIe->offset + sizeof(tDot11fIENeighborReport) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeOBSSScanParameters: + status |= dot11fPackIeOBSSScanParameters(pCtx, ( tDot11fIEOBSSScanParameters* )(pSrc + pIe->offset + sizeof(tDot11fIEOBSSScanParameters) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeOperatingMode: + status |= dot11fPackIeOperatingMode(pCtx, ( tDot11fIEOperatingMode* )(pSrc + pIe->offset + sizeof(tDot11fIEOperatingMode) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PAssocReq: + status |= dot11fPackIeP2PAssocReq(pCtx, ( tDot11fIEP2PAssocReq* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PAssocReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PAssocRes: + status |= dot11fPackIeP2PAssocRes(pCtx, ( tDot11fIEP2PAssocRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PAssocRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PBeacon: + status |= dot11fPackIeP2PBeacon(pCtx, ( tDot11fIEP2PBeacon* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PBeacon) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PBeaconProbeRes: + status |= dot11fPackIeP2PBeaconProbeRes(pCtx, ( tDot11fIEP2PBeaconProbeRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PBeaconProbeRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PDeAuth: + status |= dot11fPackIeP2PDeAuth(pCtx, ( tDot11fIEP2PDeAuth* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PDeAuth) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PDeviceDiscoverabilityReq: + status |= dot11fPackIeP2PDeviceDiscoverabilityReq(pCtx, ( tDot11fIEP2PDeviceDiscoverabilityReq* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PDeviceDiscoverabilityReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PDeviceDiscoverabilityRes: + status |= dot11fPackIeP2PDeviceDiscoverabilityRes(pCtx, ( tDot11fIEP2PDeviceDiscoverabilityRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PDeviceDiscoverabilityRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PDisAssoc: + status |= dot11fPackIeP2PDisAssoc(pCtx, ( tDot11fIEP2PDisAssoc* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PDisAssoc) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PGONegCnf: + status |= dot11fPackIeP2PGONegCnf(pCtx, ( tDot11fIEP2PGONegCnf* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PGONegCnf) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PGONegReq: + status |= dot11fPackIeP2PGONegReq(pCtx, ( tDot11fIEP2PGONegReq* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PGONegReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PGONegRes: + status |= dot11fPackIeP2PGONegRes(pCtx, ( tDot11fIEP2PGONegRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PGONegRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PGONegWPS: + status |= dot11fPackIeP2PGONegWPS(pCtx, ( tDot11fIEP2PGONegWPS* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PGONegWPS) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PIEOpaque: + status |= dot11fPackIeP2PIEOpaque(pCtx, ( tDot11fIEP2PIEOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PIEOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PInvitationReq: + status |= dot11fPackIeP2PInvitationReq(pCtx, ( tDot11fIEP2PInvitationReq* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PInvitationReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PInvitationRes: + status |= dot11fPackIeP2PInvitationRes(pCtx, ( tDot11fIEP2PInvitationRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PInvitationRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PNoticeOfAbsence: + status |= dot11fPackIeP2PNoticeOfAbsence(pCtx, ( tDot11fIEP2PNoticeOfAbsence* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PNoticeOfAbsence) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PPresenceResponse: + status |= dot11fPackIeP2PPresenceResponse(pCtx, ( tDot11fIEP2PPresenceResponse* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PPresenceResponse) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PProbeReq: + status |= dot11fPackIeP2PProbeReq(pCtx, ( tDot11fIEP2PProbeReq* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PProbeReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PProbeRes: + status |= dot11fPackIeP2PProbeRes(pCtx, ( tDot11fIEP2PProbeRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PProbeRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PProvisionDiscoveryReq: + status |= dot11fPackIeP2PProvisionDiscoveryReq(pCtx, ( tDot11fIEP2PProvisionDiscoveryReq* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PProvisionDiscoveryReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PWSCProvisionDiscoveryRes: + status |= dot11fPackIeP2PWSCProvisionDiscoveryRes(pCtx, ( tDot11fIEP2PWSCProvisionDiscoveryRes* )(pSrc + pIe->offset + sizeof(tDot11fIEP2PWSCProvisionDiscoveryRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIePTIControl: + status |= dot11fPackIePTIControl(pCtx, ( tDot11fIEPTIControl* )(pSrc + pIe->offset + sizeof(tDot11fIEPTIControl) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIePUBufferStatus: + status |= dot11fPackIePUBufferStatus(pCtx, ( tDot11fIEPUBufferStatus* )(pSrc + pIe->offset + sizeof(tDot11fIEPUBufferStatus) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIePowerCaps: + status |= dot11fPackIePowerCaps(pCtx, ( tDot11fIEPowerCaps* )(pSrc + pIe->offset + sizeof(tDot11fIEPowerCaps) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIePowerConstraints: + status |= dot11fPackIePowerConstraints(pCtx, ( tDot11fIEPowerConstraints* )(pSrc + pIe->offset + sizeof(tDot11fIEPowerConstraints) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeQBSSLoad: + status |= dot11fPackIeQBSSLoad(pCtx, ( tDot11fIEQBSSLoad* )(pSrc + pIe->offset + sizeof(tDot11fIEQBSSLoad) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeQComVendorIE: + status |= dot11fPackIeQComVendorIE(pCtx, ( tDot11fIEQComVendorIE* )(pSrc + pIe->offset + sizeof(tDot11fIEQComVendorIE) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeQOSCapsAp: + status |= dot11fPackIeQOSCapsAp(pCtx, ( tDot11fIEQOSCapsAp* )(pSrc + pIe->offset + sizeof(tDot11fIEQOSCapsAp) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeQOSCapsStation: + status |= dot11fPackIeQOSCapsStation(pCtx, ( tDot11fIEQOSCapsStation* )(pSrc + pIe->offset + sizeof(tDot11fIEQOSCapsStation) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeQosMapSet: + status |= dot11fPackIeQosMapSet(pCtx, ( tDot11fIEQosMapSet* )(pSrc + pIe->offset + sizeof(tDot11fIEQosMapSet) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeQuiet: + status |= dot11fPackIeQuiet(pCtx, ( tDot11fIEQuiet* )(pSrc + pIe->offset + sizeof(tDot11fIEQuiet) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRCPIIE: + status |= dot11fPackIeRCPIIE(pCtx, ( tDot11fIERCPIIE* )(pSrc + pIe->offset + sizeof(tDot11fIERCPIIE) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRICDataDesc: + status |= dot11fPackIeRICDataDesc(pCtx, ( tDot11fIERICDataDesc* )(pSrc + pIe->offset + sizeof(tDot11fIERICDataDesc) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRSN: + status |= dot11fPackIeRSN(pCtx, ( tDot11fIERSN* )(pSrc + pIe->offset + sizeof(tDot11fIERSN) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRSNIIE: + status |= dot11fPackIeRSNIIE(pCtx, ( tDot11fIERSNIIE* )(pSrc + pIe->offset + sizeof(tDot11fIERSNIIE) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeRSNOpaque: + status |= dot11fPackIeRSNOpaque(pCtx, ( tDot11fIERSNOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIERSNOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeSuppChannels: + status |= dot11fPackIeSuppChannels(pCtx, ( tDot11fIESuppChannels* )(pSrc + pIe->offset + sizeof(tDot11fIESuppChannels) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeSuppOperatingClasses: + status |= dot11fPackIeSuppOperatingClasses(pCtx, ( tDot11fIESuppOperatingClasses* )(pSrc + pIe->offset + sizeof(tDot11fIESuppOperatingClasses) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeSuppRates: + status |= dot11fPackIeSuppRates(pCtx, ( tDot11fIESuppRates* )(pSrc + pIe->offset + sizeof(tDot11fIESuppRates) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTIM: + status |= dot11fPackIeTIM(pCtx, ( tDot11fIETIM* )(pSrc + pIe->offset + sizeof(tDot11fIETIM) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTPCReport: + status |= dot11fPackIeTPCReport(pCtx, ( tDot11fIETPCReport* )(pSrc + pIe->offset + sizeof(tDot11fIETPCReport) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTPCRequest: + status |= dot11fPackIeTPCRequest(pCtx, ( tDot11fIETPCRequest* )(pSrc + pIe->offset + sizeof(tDot11fIETPCRequest) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTimeAdvertisement: + status |= dot11fPackIeTimeAdvertisement(pCtx, ( tDot11fIETimeAdvertisement* )(pSrc + pIe->offset + sizeof(tDot11fIETimeAdvertisement) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeTimeoutInterval: + status |= dot11fPackIeTimeoutInterval(pCtx, ( tDot11fIETimeoutInterval* )(pSrc + pIe->offset + sizeof(tDot11fIETimeoutInterval) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeVHTCaps: + status |= dot11fPackIeVHTCaps(pCtx, ( tDot11fIEVHTCaps* )(pSrc + pIe->offset + sizeof(tDot11fIEVHTCaps) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeVHTExtBssLoad: + status |= dot11fPackIeVHTExtBssLoad(pCtx, ( tDot11fIEVHTExtBssLoad* )(pSrc + pIe->offset + sizeof(tDot11fIEVHTExtBssLoad) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeVHTOperation: + status |= dot11fPackIeVHTOperation(pCtx, ( tDot11fIEVHTOperation* )(pSrc + pIe->offset + sizeof(tDot11fIEVHTOperation) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeVendor1IE: + status |= dot11fPackIeVendor1IE(pCtx, ( tDot11fIEVendor1IE* )(pSrc + pIe->offset + sizeof(tDot11fIEVendor1IE) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeVendor2IE: + status |= dot11fPackIeVendor2IE(pCtx, ( tDot11fIEVendor2IE* )(pSrc + pIe->offset + sizeof(tDot11fIEVendor2IE) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeVendor3IE: + status |= dot11fPackIeVendor3IE(pCtx, ( tDot11fIEVendor3IE* )(pSrc + pIe->offset + sizeof(tDot11fIEVendor3IE) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWAPI: + status |= dot11fPackIeWAPI(pCtx, ( tDot11fIEWAPI* )(pSrc + pIe->offset + sizeof(tDot11fIEWAPI) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWAPIOpaque: + status |= dot11fPackIeWAPIOpaque(pCtx, ( tDot11fIEWAPIOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIEWAPIOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWFATPC: + status |= dot11fPackIeWFATPC(pCtx, ( tDot11fIEWFATPC* )(pSrc + pIe->offset + sizeof(tDot11fIEWFATPC) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWFDIEOpaque: + status |= dot11fPackIeWFDIEOpaque(pCtx, ( tDot11fIEWFDIEOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIEWFDIEOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMCaps: + status |= dot11fPackIeWMMCaps(pCtx, ( tDot11fIEWMMCaps* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMCaps) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMInfoAp: + status |= dot11fPackIeWMMInfoAp(pCtx, ( tDot11fIEWMMInfoAp* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMInfoAp) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMInfoStation: + status |= dot11fPackIeWMMInfoStation(pCtx, ( tDot11fIEWMMInfoStation* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMInfoStation) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMParams: + status |= dot11fPackIeWMMParams(pCtx, ( tDot11fIEWMMParams* )(pSrc + pIe->offset + sizeof(tDot11fIEWMMParams) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWPA: + status |= dot11fPackIeWPA(pCtx, ( tDot11fIEWPA* )(pSrc + pIe->offset + sizeof(tDot11fIEWPA) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWPAOpaque: + status |= dot11fPackIeWPAOpaque(pCtx, ( tDot11fIEWPAOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIEWPAOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWSC: + status |= dot11fPackIeWSC(pCtx, ( tDot11fIEWSC* )(pSrc + pIe->offset + sizeof(tDot11fIEWSC) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscAssocReq: + status |= dot11fPackIeWscAssocReq(pCtx, ( tDot11fIEWscAssocReq* )(pSrc + pIe->offset + sizeof(tDot11fIEWscAssocReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscAssocRes: + status |= dot11fPackIeWscAssocRes(pCtx, ( tDot11fIEWscAssocRes* )(pSrc + pIe->offset + sizeof(tDot11fIEWscAssocRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscBeacon: + status |= dot11fPackIeWscBeacon(pCtx, ( tDot11fIEWscBeacon* )(pSrc + pIe->offset + sizeof(tDot11fIEWscBeacon) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscBeaconProbeRes: + status |= dot11fPackIeWscBeaconProbeRes(pCtx, ( tDot11fIEWscBeaconProbeRes* )(pSrc + pIe->offset + sizeof(tDot11fIEWscBeaconProbeRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscIEOpaque: + status |= dot11fPackIeWscIEOpaque(pCtx, ( tDot11fIEWscIEOpaque* )(pSrc + pIe->offset + sizeof(tDot11fIEWscIEOpaque) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscProbeReq: + status |= dot11fPackIeWscProbeReq(pCtx, ( tDot11fIEWscProbeReq* )(pSrc + pIe->offset + sizeof(tDot11fIEWscProbeReq) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscProbeRes: + status |= dot11fPackIeWscProbeRes(pCtx, ( tDot11fIEWscProbeRes* )(pSrc + pIe->offset + sizeof(tDot11fIEWscProbeRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscReassocRes: + status |= dot11fPackIeWscReassocRes(pCtx, ( tDot11fIEWscReassocRes* )(pSrc + pIe->offset + sizeof(tDot11fIEWscReassocRes) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIeext_chan_switch_ann: + status |= dot11fPackIeext_chan_switch_ann(pCtx, ( tDot11fIEext_chan_switch_ann* )(pSrc + pIe->offset + sizeof(tDot11fIEext_chan_switch_ann) * i ), pBufRemaining, nBufRemaining, &len); + break; + case SigIesec_chan_offset_ele: + status |= dot11fPackIesec_chan_offset_ele(pCtx, ( tDot11fIEsec_chan_offset_ele* )(pSrc + pIe->offset + sizeof(tDot11fIEsec_chan_offset_ele) * 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" + "ug in 'framesc'.\n"), pFf->sig); + return DOT11F_INTERNAL_ERROR; + } + + pBufRemaining += len; + nBufRemaining -= len; + *pnConsumed += len; + } + + ++pIe; + + } + + return status; + +} + +static tANI_U32 PackTlvCore(tpAniSirGlobal pCtx, + tANI_U8 *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed, + const tTLVDefn TLVs[], + tANI_U32 *pidx) +{ + const tTLVDefn *pTlv; + tFRAMES_BOOL *pfFound; + tANI_U8 *pBufRemaining; + tANI_U32 nBufRemaining, status, len; + + DOT11F_PARAMETER_CHECK2(pSrc, pBuf, nBuf, pnConsumed); + + (void)pCtx; + status = DOT11F_PARSE_SUCCESS; + pBufRemaining = pBuf; + nBufRemaining = nBuf; + + pTlv = &( TLVs[0] ); + while ( 0xffff != pTlv->id ) + { + pfFound = (tFRAMES_BOOL*)(pSrc + pTlv->offset + + pTlv->presenceOffset); + if ( *pfFound && pTlv->minSize > nBufRemaining ) + { + FRAMES_LOG3(pCtx, FRLOGE, FRFL("The TLV %s takes at least" + " %d bytes, but there are only %d left in the buffer." + "\n"), pTlv->name, pTlv->minSize, nBufRemaining); + return DOT11F_BUFFER_OVERFLOW; + } + + len = 0U; + + if ( *pfFound ) { + switch ( pTlv->sig ) + { + case SigTlvAuthorizedMACs: + status |= dot11fPackTlvAuthorizedMACs(pCtx, ( tDot11fTLVAuthorizedMACs* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvRequestToEnroll: + status |= dot11fPackTlvRequestToEnroll(pCtx, ( tDot11fTLVRequestToEnroll* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvVersion2: + status |= dot11fPackTlvVersion2(pCtx, ( tDot11fTLVVersion2* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvAPSetupLocked: + status |= dot11fPackTlvAPSetupLocked(pCtx, ( tDot11fTLVAPSetupLocked* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvAssociationState: + status |= dot11fPackTlvAssociationState(pCtx, ( tDot11fTLVAssociationState* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvChannelList: + status |= dot11fPackTlvChannelList(pCtx, ( tDot11fTLVChannelList* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvConfigMethods: + status |= dot11fPackTlvConfigMethods(pCtx, ( tDot11fTLVConfigMethods* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvConfigurationError: + status |= dot11fPackTlvConfigurationError(pCtx, ( tDot11fTLVConfigurationError* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvConfigurationTimeout: + status |= dot11fPackTlvConfigurationTimeout(pCtx, ( tDot11fTLVConfigurationTimeout* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvDeviceName: + status |= dot11fPackTlvDeviceName(pCtx, ( tDot11fTLVDeviceName* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvDevicePasswordID: + status |= dot11fPackTlvDevicePasswordID(pCtx, ( tDot11fTLVDevicePasswordID* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvExtendedListenTiming: + status |= dot11fPackTlvExtendedListenTiming(pCtx, ( tDot11fTLVExtendedListenTiming* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvGOIntent: + status |= dot11fPackTlvGOIntent(pCtx, ( tDot11fTLVGOIntent* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvIntendedP2PInterfaceAddress: + status |= dot11fPackTlvIntendedP2PInterfaceAddress(pCtx, ( tDot11fTLVIntendedP2PInterfaceAddress* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvInvitationFlags: + status |= dot11fPackTlvInvitationFlags(pCtx, ( tDot11fTLVInvitationFlags* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvListenChannel: + status |= dot11fPackTlvListenChannel(pCtx, ( tDot11fTLVListenChannel* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvManufacturer: + status |= dot11fPackTlvManufacturer(pCtx, ( tDot11fTLVManufacturer* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvMinorReasonCode: + status |= dot11fPackTlvMinorReasonCode(pCtx, ( tDot11fTLVMinorReasonCode* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvModelName: + status |= dot11fPackTlvModelName(pCtx, ( tDot11fTLVModelName* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvModelNumber: + status |= dot11fPackTlvModelNumber(pCtx, ( tDot11fTLVModelNumber* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvNoticeOfAbsence: + status |= dot11fPackTlvNoticeOfAbsence(pCtx, ( tDot11fTLVNoticeOfAbsence* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvOperatingChannel: + status |= dot11fPackTlvOperatingChannel(pCtx, ( tDot11fTLVOperatingChannel* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PCapability: + status |= dot11fPackTlvP2PCapability(pCtx, ( tDot11fTLVP2PCapability* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PDeviceId: + status |= dot11fPackTlvP2PDeviceId(pCtx, ( tDot11fTLVP2PDeviceId* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PDeviceInfo: + status |= dot11fPackTlvP2PDeviceInfo(pCtx, ( tDot11fTLVP2PDeviceInfo* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PGroupBssid: + status |= dot11fPackTlvP2PGroupBssid(pCtx, ( tDot11fTLVP2PGroupBssid* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PGroupId: + status |= dot11fPackTlvP2PGroupId(pCtx, ( tDot11fTLVP2PGroupId* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PGroupInfo: + status |= dot11fPackTlvP2PGroupInfo(pCtx, ( tDot11fTLVP2PGroupInfo* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PStatus: + status |= dot11fPackTlvP2PStatus(pCtx, ( tDot11fTLVP2PStatus* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvPrimaryDeviceType: + status |= dot11fPackTlvPrimaryDeviceType(pCtx, ( tDot11fTLVPrimaryDeviceType* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvRFBands: + status |= dot11fPackTlvRFBands(pCtx, ( tDot11fTLVRFBands* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvRequestDeviceType: + status |= dot11fPackTlvRequestDeviceType(pCtx, ( tDot11fTLVRequestDeviceType* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvRequestType: + status |= dot11fPackTlvRequestType(pCtx, ( tDot11fTLVRequestType* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvResponseType: + status |= dot11fPackTlvResponseType(pCtx, ( tDot11fTLVResponseType* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvSelectedRegistrar: + status |= dot11fPackTlvSelectedRegistrar(pCtx, ( tDot11fTLVSelectedRegistrar* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvSelectedRegistrarConfigMethods: + status |= dot11fPackTlvSelectedRegistrarConfigMethods(pCtx, ( tDot11fTLVSelectedRegistrarConfigMethods* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvSerialNumber: + status |= dot11fPackTlvSerialNumber(pCtx, ( tDot11fTLVSerialNumber* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvUUID_E: + status |= dot11fPackTlvUUID_E(pCtx, ( tDot11fTLVUUID_E* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvUUID_R: + status |= dot11fPackTlvUUID_R(pCtx, ( tDot11fTLVUUID_R* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvVendorExtension: + status |= dot11fPackTlvVendorExtension(pCtx, ( tDot11fTLVVendorExtension* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvVersion: + status |= dot11fPackTlvVersion(pCtx, ( tDot11fTLVVersion* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvWPSState: + status |= dot11fPackTlvWPSState(pCtx, ( tDot11fTLVWPSState* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PInterface: + status |= dot11fPackTlvP2PInterface(pCtx, ( tDot11fTLVP2PInterface* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + case SigTlvP2PManageability: + status |= dot11fPackTlvP2PManageability(pCtx, ( tDot11fTLVP2PManageability* )(pSrc + pTlv->offset), pBufRemaining, nBufRemaining, &len); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don't " + "know about the TLV %d; this is most likely a bug in " + "'framesc'.\n"), pTlv->sig); + return DOT11F_INTERNAL_ERROR; + } + + } /* End if on *pfFound */ + pBufRemaining += len; + nBufRemaining -= len; + *pnConsumed += len; + ++pTlv; + if(len) ++*pidx; + } + + return status; + +} diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logApi.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logApi.c new file mode 100644 index 000000000000..57636888a249 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logApi.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * logApi.cc - Handles log messages for all the modules. + * Author: Kevin Nguyen + * Date: 02/27/02 + * History:- + * 02/11/02 Created. + * 03/12/02 Rearrange logDebug parameter list and add more params. + * -------------------------------------------------------------------- + * + */ + +#include +#include +#include +#include + +#include +#include "utilsGlobal.h" +#include "macInitApi.h" +#include "palApi.h" + +#include "vos_trace.h" + +#ifdef ANI_OS_TYPE_ANDROID +#include +#endif + + +// --------------------------------------------------------------------- +/** + * logInit() + * + * FUNCTION: + * This function is called to prepare the logging utility. + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param tpAniSirGlobal Sirius software parameter strucutre pointer + * @return None + */ +tSirRetStatus +logInit(tpAniSirGlobal pMac) +{ + tANI_U32 i; + + // Add code to initialize debug level from CFG module + // For now, enable all logging + for (i = 0; i < LOG_ENTRY_NUM; i++) + { +#ifdef SIR_DEBUG + pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = LOG1; +#else + pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = LOGW; +#endif + } + return eSIR_SUCCESS; + +} /*** logInit() ***/ + +void +logDeinit(tpAniSirGlobal pMac) +{ + return; +} + +/** + * logDbg() + * + *FUNCTION: + * This function is called to log a debug message. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * None. + * + *NOTE: + * + * @param tpAniSirGlobal Sirius software parameter strucutre pointer + * @param ModId 8-bit modID + * @param debugLevel debugging level for this message + * @param pStr string parameter pointer + * @return None + */ + + +void logDbg(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 debugLevel, const char *pStr,...) +{ +#ifdef WLAN_DEBUG + if ( debugLevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( modId )] ) + return; + else + { + va_list marker; + + va_start( marker, pStr ); /* Initialize variable arguments. */ + + logDebug(pMac, modId, debugLevel, pStr, marker); + + va_end( marker ); /* Reset variable arguments. */ + } +#endif +} + + VOS_TRACE_LEVEL getVosDebugLevel(tANI_U32 debugLevel) +{ + switch(debugLevel) + { + case LOGP: + return VOS_TRACE_LEVEL_FATAL; + case LOGE: + return VOS_TRACE_LEVEL_ERROR; + case LOGW: + return VOS_TRACE_LEVEL_WARN; + case LOG1: + return VOS_TRACE_LEVEL_INFO; + case LOG2: + return VOS_TRACE_LEVEL_INFO_HIGH; + case LOG3: + return VOS_TRACE_LEVEL_INFO_MED; + case LOG4: + return VOS_TRACE_LEVEL_INFO_LOW; + default: + return VOS_TRACE_LEVEL_INFO_LOW; + } +} + +static inline VOS_MODULE_ID getVosModuleId(tANI_U8 modId) +{ + switch(modId) + { + case SIR_HAL_MODULE_ID: + case SIR_PHY_MODULE_ID: + return VOS_MODULE_ID_WDA; + case SIR_PMM_MODULE_ID: + return VOS_MODULE_ID_PMC; + + case SIR_LIM_MODULE_ID: + case SIR_SCH_MODULE_ID: + case SIR_CFG_MODULE_ID: + case SIR_MNT_MODULE_ID: + case SIR_DPH_MODULE_ID: + case SIR_DBG_MODULE_ID: + return VOS_MODULE_ID_PE; + + case SIR_SYS_MODULE_ID: + return VOS_MODULE_ID_SYS; + + case SIR_SMS_MODULE_ID: + return VOS_MODULE_ID_SME; + + default: + return VOS_MODULE_ID_SYS; + } +} + +#define LOG_SIZE 256 +void logDebug(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 debugLevel, const char *pStr, va_list marker) +{ + VOS_TRACE_LEVEL vosDebugLevel; + VOS_MODULE_ID vosModuleId; + char logBuffer[LOG_SIZE]; + + vosDebugLevel = getVosDebugLevel(debugLevel); + vosModuleId = getVosModuleId(modId); + + vsnprintf(logBuffer, LOG_SIZE - 1, pStr, marker); + VOS_TRACE(vosModuleId, vosDebugLevel, "%s", logBuffer); + + // The caller must check loglevel + VOS_ASSERT( ( debugLevel <= pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( modId )] ) && ( LOGP != debugLevel ) ); +} /*** end logDebug() ***/ diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logDump.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logDump.c new file mode 100644 index 000000000000..6ae4bd24f031 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/logDump.c @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ +logDump.c +*/ + +/* + * This file contains the utility functions to dump various + * MAC states and to enable/disable certain features during + * debugging. + * Author: Sandesh Goel + * Date: 02/27/02 + * History:- + * 02/11/02 Created. + * -------------------------------------------------------------------- + * + */ + +/* + * @note : Bytes is to print overflow message information. + */ + +#include "palTypes.h" + +#ifdef ANI_LOGDUMP + +#define MAX_OVERFLOW_MSG 400 +#define MAX_LOGDUMP_SIZE ((4*1024) - MAX_OVERFLOW_MSG) + +#if defined(ANI_OS_TYPE_ANDROID) + +#include + +#endif + + +#include "palApi.h" +#include "aniGlobal.h" +#include "sirCommon.h" +#include +#include + +#include +#include +#include +#include +#include +#include "limUtils.h" +#include "schApi.h" + +#include "pmmApi.h" +#include "limSerDesUtils.h" +#include "limAssocUtils.h" +#include "limSendMessages.h" +#include "limSecurityUtils.h" +//#include "halRadar.h" +#include "logDump.h" +#include "sysDebug.h" +#include "wlan_qct_wda.h" + +#define HAL_LOG_DUMP_CMD_START 0 + +/* Dump command id for Host modules starts from 300 onwards, + * hence do not extend the HAL commands beyond 300. + */ +#define HAL_LOG_DUMP_CMD_END 299 + +static int debug; + + void +logPrintf(tpAniSirGlobal pMac, tANI_U32 cmd, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4) +{ + static tANI_U8 buf[MAX_LOGDUMP_SIZE + MAX_OVERFLOW_MSG]; + tANI_U16 bufLen; + pMac->gCurrentLogSize = 0; + + bufLen = (tANI_U16)logRtaiDump(pMac, cmd, arg1, arg2, arg3, arg4, buf); +} + +/** + @brief: This function is used to Aggregate the formated buffer, this + also check the overflow condition and adds the overflow message + to the end of the log Dump buffer reserved of MAX_OVERFLOW_MSG size. + @param: tpAniSirGlobal pMac + @param: char *pBuf + @param: variable arguments... + @return: Returns the number of bytes added to the buffer. + Returns 0 incase of overflow. + + @note: Currently in windows we do not print the Aggregated buffer as there + is a limitation on the number of bytes that can be displayed by DbgPrint + So we print the buffer immediately and we would also aggregate where + the TestDbg might use this buffer to print out at the application level. + */ +int log_sprintf(tpAniSirGlobal pMac, char *pBuf, char *fmt, ...) +{ + tANI_S32 ret = 0; +#ifdef WLAN_DEBUG + + va_list args; + va_start(args, fmt); + + if (pMac->gCurrentLogSize >= MAX_LOGDUMP_SIZE) + return 0; + +#if defined (ANI_OS_TYPE_ANDROID) + ret = vsnprintf(pBuf, (MAX_LOGDUMP_SIZE - pMac->gCurrentLogSize), fmt, args); +#endif + + va_end(args); + + /* If an output error is encountered, a negative value is returned by vsnprintf */ + if (ret < 0) + return 0; + + + if ((tANI_U32) ret > (MAX_LOGDUMP_SIZE - pMac->gCurrentLogSize)) { + pBuf += (MAX_LOGDUMP_SIZE - pMac->gCurrentLogSize); + pMac->gCurrentLogSize = MAX_LOGDUMP_SIZE; + +#if defined (ANI_OS_TYPE_ANDROID) + ret = snprintf(pBuf, MAX_OVERFLOW_MSG, "\n-> ***********" + "\nOutput Exceeded the Buffer Size, message truncated!!\n<- ***********\n"); +#endif + /* If an output error is encountered, a negative value is returned by snprintf */ + if (ret < 0) + return 0; + + if (ret > MAX_OVERFLOW_MSG) + ret = MAX_OVERFLOW_MSG; + } + + pMac->gCurrentLogSize += ret; + + +#endif //for #ifdef WLAN_DEBUG + return ret; +} + + +char* dumpLOG( tpAniSirGlobal pMac, char *p ) +{ + tANI_U32 i; + + for( i = SIR_FIRST_MODULE_ID; i <= SIR_LAST_MODULE_ID; i++ ) { + p += log_sprintf(pMac, p, "[0x%2x]", i); + switch (i) + { + case SIR_HAL_MODULE_ID: p += log_sprintf( pMac, p, "HAL "); break; + case SIR_CFG_MODULE_ID: p += log_sprintf( pMac, p, "CFG "); break; + case SIR_LIM_MODULE_ID: p += log_sprintf( pMac, p, "LIM "); break; + case SIR_ARQ_MODULE_ID: p += log_sprintf( pMac, p, "ARQ "); break; + case SIR_SCH_MODULE_ID: p += log_sprintf( pMac, p, "SCH "); break; + case SIR_PMM_MODULE_ID: p += log_sprintf( pMac, p, "PMM "); break; + case SIR_MNT_MODULE_ID: p += log_sprintf( pMac, p, "MNT "); break; + case SIR_DBG_MODULE_ID: p += log_sprintf( pMac, p, "DBG "); break; + case SIR_DPH_MODULE_ID: p += log_sprintf( pMac, p, "DPH "); break; + case SIR_SYS_MODULE_ID: p += log_sprintf( pMac, p, "SYS "); break; + case SIR_PHY_MODULE_ID: p += log_sprintf( pMac, p, "PHY "); break; + case SIR_DVT_MODULE_ID: p += log_sprintf( pMac, p, "DVT "); break; + case SIR_SMS_MODULE_ID: p += log_sprintf( pMac, p, "SMS "); break; + default: p += log_sprintf( pMac, p, "UNK ", i); break; + } + + p += log_sprintf( pMac, p, + ": debug level is [0x%x] ", + pMac->utils.gLogDbgLevel[i - SIR_FIRST_MODULE_ID]); + + switch( pMac->utils.gLogDbgLevel[i - SIR_FIRST_MODULE_ID] ) + { + case LOGOFF: p += log_sprintf( pMac, p, "LOG disabled\n"); break; + case LOGP: p += log_sprintf( pMac, p, "LOGP(Panic only)\n"); break; + case LOGE: p += log_sprintf( pMac, p, "LOGE(Errors only)\n"); break; + case LOGW: p += log_sprintf( pMac, p, "LOGW(Warnings)\n"); break; + case LOG1: p += log_sprintf( pMac, p, "LOG1(Minimal debug)\n"); break; + case LOG2: p += log_sprintf( pMac, p, "LOG2(Verbose)\n"); break; + case LOG3: p += log_sprintf( pMac, p, "LOG3(Very Verbose)\n"); break; + case LOG4: p += log_sprintf( pMac, p, "LOG4(Very Very Verbose)\n"); break; + default: p += log_sprintf( pMac, p, "Unknown\n"); break; + } + } + + return p; +} + +char* setLOGLevel( tpAniSirGlobal pMac, char *p, tANI_U32 module, tANI_U32 level ) +{ + tANI_U32 i; + + if((module > SIR_LAST_MODULE_ID || module < SIR_FIRST_MODULE_ID) && module != 0xff ) { + p += log_sprintf( pMac, p, "Invalid module id 0x%x\n", module ); + return p; + } + + if( 0xff == module ) { + for( i = SIR_FIRST_MODULE_ID; i <= SIR_LAST_MODULE_ID; i++ ) + pMac->utils.gLogDbgLevel[i - SIR_FIRST_MODULE_ID] = level; + } else { + pMac->utils.gLogDbgLevel[module - SIR_FIRST_MODULE_ID] = level; + } + +#ifdef ANI_PHY_DEBUG + if (module == 0xff || module == SIR_PHY_MODULE_ID) { + pMac->hphy.phy.phyDebugLogLevel = level; + } +#endif + + return dumpLOG( pMac, p ); +} + +static void Log_getCfg(tpAniSirGlobal pMac, tANI_U16 cfgId) +{ +#define CFG_CTL_INT 0x00080000 + if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_INT) != 0) + { + tANI_U32 val; + + // Get integer parameter + if (wlan_cfgGetInt(pMac, (tANI_U16)cfgId, &val) != eSIR_SUCCESS) + { + sysLog(pMac, LOGE, FL("Get cfgId 0x%x failed\n"), cfgId); + } + else + { + sysLog( pMac, LOGE, FL("WNI_CFG_%s(%d 0x%x) = %ld\n"), gCfgParamName[cfgId], cfgId, cfgId, val ); + } + } + else + { + tANI_U8 buf[CFG_MAX_STR_LEN] = {0} ; + tANI_U32 valueLen ; + + // Get string parameter + valueLen = CFG_MAX_STR_LEN ; + if (wlan_cfgGetStr(pMac, cfgId, buf, &valueLen) != eSIR_SUCCESS) + { + sysLog(pMac, LOGE, FL("Get cfgId 0x%x failed\n"), cfgId); + } + else + { + sysLog( pMac, LOGE, FL("WNI_CFG_%s(%d 0x%x) len=%ld\n"), gCfgParamName[cfgId], cfgId, cfgId, valueLen ); + sirDumpBuf(pMac, SIR_WDA_MODULE_ID, LOG1, buf, valueLen) ; + } + } + + return; +} + +static void Log_setCfg(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 val) +{ + sysLog(pMac, LOGE, FL("Set %s(0x%x) to value 0x%x\n"), + gCfgParamName[cfgId], cfgId, val); + + if (cfgSetInt(pMac, (tANI_U16)cfgId, val) != eSIR_SUCCESS) + sysLog(pMac, LOGE, FL("setting cfgId 0x%x to value 0x%x failed \n"), + cfgId, val); + return; +} + + +char * dump_cfg_get( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg2; (void) arg3; (void) arg4; + Log_getCfg(pMac, (tANI_U16) arg1); + return p; +} + +char * dump_cfg_group_get( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + tANI_U32 i, startId, endId; + + (void) arg3; (void) arg4; + + if (arg1 < CFG_PARAM_MAX_NUM) { + startId = arg1; + } else { + p += log_sprintf( pMac, p, "Start CFGID must be less than %d\n", CFG_PARAM_MAX_NUM); + return p; + } + + if ((arg2 == 0) || (arg2 > CFG_PARAM_MAX_NUM)) + arg2 = 30; + + endId = ((startId + arg2) < CFG_PARAM_MAX_NUM) ? (startId + arg2) : CFG_PARAM_MAX_NUM; + + for (i=startId; i < endId; i++) + Log_getCfg(pMac, (tANI_U16) i); + + return p; +} +char * dump_cfg_set( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg3; (void) arg4; + Log_setCfg(pMac, (tANI_U16) arg1, arg2); + return p; +} + +char * dump_log_level_set( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p) +{ + (void) arg1; (void) arg2; (void) arg3; (void) arg4; + p = setLOGLevel( pMac, p, arg1, arg2 ); + return p; +} + + +/* Initialize the index */ +void logDumpInit(tpAniSirGlobal pMac) +{ + pMac->dumpTablecurrentId = 0; + +} + +void logDumpRegisterTable( tpAniSirGlobal pMac, tDumpFuncEntry *pEntry, tANI_U32 nItems ) +{ + + pMac->dumpTableEntry[pMac->dumpTablecurrentId]->nItems = nItems; + pMac->dumpTableEntry[pMac->dumpTablecurrentId]->mindumpid = pEntry->id; + pMac->dumpTableEntry[pMac->dumpTablecurrentId]->maxdumpid = (pEntry + (nItems-1))->id; + pMac->dumpTableEntry[pMac->dumpTablecurrentId]->dumpTable = pEntry; + pMac->dumpTablecurrentId++; +} + + +/* + * print nItems from the menu list ponted to by m + */ +static tANI_U32 print_menu(tpAniSirGlobal pMac, char *p, tANI_U32 startId) +{ + tANI_U32 currentId = 0; + tANI_U32 i, j; + tANI_S32 ret = 0; + tDumpFuncEntry *pEntry = NULL; + tANI_U32 nItems = 0; + + for(i = 0; i < pMac->dumpTablecurrentId; i++) { + pEntry = pMac->dumpTableEntry[i]->dumpTable; + nItems = pMac->dumpTableEntry[i]->nItems; + + for (j = 0; j < nItems; j++, pEntry++) { + if (pEntry->description == NULL) + continue; + + if (pEntry->id == 0) { + ret = log_sprintf( pMac,p, "---- %s\n", pEntry->description); + + if (ret <= 0) + break; + + p += ret; + continue; + } + + if (pEntry->id < startId) + continue; + + ret = log_sprintf(pMac, p, "%4d\t%s\n", pEntry->id, pEntry->description); + + if (ret <= 0) + break; + + currentId = pEntry->id; + p += ret; + } + + if (ret <= 0) + break; + } + + return currentId; +} + +int logRtaiDump( tpAniSirGlobal pMac, tANI_U32 cmd, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, tANI_U8 *pBuf) +{ + char *p = (char *)pBuf; + tANI_U32 i; + tANI_U32 nItems = 0; + tDumpFuncEntry *pEntry = NULL; + + pMac->gCurrentLogSize = 0; + if (debug) { + p += log_sprintf( pMac,p, "Cmd = %d Args (0x%x,0x%x,0x%x,0x%x)\n\n", + cmd, arg1, arg2, arg3, arg4); + } + + if( cmd == MAX_DUMP_CMD || cmd == 0 ) { + pMac->menuCurrent = print_menu(pMac, p, pMac->menuCurrent); + return pMac->gCurrentLogSize; + } + if(cmd <= HAL_LOG_DUMP_CMD_END) + { + WDA_HALDumpCmdReq(pMac, cmd, arg1, arg2, arg3, arg4, p); + } + else + { + for(i = 0; i < pMac->dumpTablecurrentId; i++) { + if( (cmd > pMac->dumpTableEntry[i]->mindumpid) && (cmd <= pMac->dumpTableEntry[i]->maxdumpid)) { + pEntry = pMac->dumpTableEntry[i]->dumpTable; + nItems = pMac->dumpTableEntry[i]->nItems; + break; + } else { + continue; + } + } + + if((nItems > 0) && (pEntry != NULL)) { + for (i = 0; i < nItems; i++, pEntry++) { + if( cmd == pEntry->id ) { + if ( pEntry->func != NULL ) { + pEntry->func(pMac, arg1, arg2, arg3, arg4, p); + } else { + p += log_sprintf( pMac,p, "Cmd not supported\n"); + } + break; + } + } + } else { + p += log_sprintf( pMac,p, "Cmd not found \n"); + } + } + if (debug) + p += log_sprintf( pMac,p, "Returned %d bytes\n", pMac->gCurrentLogSize); + + return pMac->gCurrentLogSize; + +} + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c new file mode 100644 index 000000000000..3b0086976b5b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -0,0 +1,1054 @@ +/* + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file macTrace.c + + \brief implementation for trace related APIs + + \author Sunit Bhatia + + ========================================================================*/ + + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "macTrace.h" +#include "wlan_qct_wda.h" +#include "wlan_qct_wda_msg.h" +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_p2p.h" +#include "csrNeighborRoam.h" +#include "csrInternal.h" +#include "limGlobal.h" +#include "wlan_qct_tl.h" +#include "vos_memory.h" +#include "vos_trace.h" + +#ifdef TRACE_RECORD + +/* --------------------------------------------------------------------------- + \fn macTraceGetHDDWlanConnState + \function to get string equivalent of a value + from the enum eConnectionState. + + \param connState - the value from the enum + \return the string equivalent of connState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetHDDWlanConnState(tANI_U16 connState) +{ + switch(connState) + { + CASE_RETURN_STRING(eConnectionState_NotConnected); + CASE_RETURN_STRING(eConnectionState_Connecting); + CASE_RETURN_STRING(eConnectionState_Associated); + CASE_RETURN_STRING(eConnectionState_IbssDisconnected); + CASE_RETURN_STRING(eConnectionState_IbssConnected); + CASE_RETURN_STRING(eConnectionState_Disconnecting); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +/* --------------------------------------------------------------------------- + \fn macTraceGetP2PConnState + \function to get string equivalent of a value + from the enum tP2PConnectionStatus. + + \param connState - the value from the enum + \return the string equivalent of connState + ---------------------------------------------------------------------------*/ +#ifdef WLAN_FEATURE_P2P_DEBUG +tANI_U8* macTraceGetP2PConnState(tANI_U16 connState) +{ + switch(connState) + { + CASE_RETURN_STRING(P2P_NOT_ACTIVE); + CASE_RETURN_STRING(P2P_GO_NEG_PROCESS); + CASE_RETURN_STRING(P2P_GO_NEG_COMPLETED); + CASE_RETURN_STRING(P2P_CLIENT_CONNECTING_STATE_1); + CASE_RETURN_STRING(P2P_GO_COMPLETED_STATE); + CASE_RETURN_STRING(P2P_CLIENT_CONNECTED_STATE_1); + CASE_RETURN_STRING(P2P_CLIENT_DISCONNECTED_STATE); + CASE_RETURN_STRING(P2P_CLIENT_CONNECTING_STATE_2); + CASE_RETURN_STRING(P2P_CLIENT_COMPLETED_STATE); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} +#endif + +/* --------------------------------------------------------------------------- + \fn macTraceGetNeighbourRoamState + \function to get string equivalent of a value + from the enum eCsrNeighborRoamState. + + \param neighbourRoamState - the value from the enum + \return the string equivalent of neighbourRoamState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetNeighbourRoamState(tANI_U16 neighbourRoamState) +{ + switch(neighbourRoamState) + { + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_CLOSED); + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_INIT); + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED); + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN); + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING); + #ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY); + 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); + #endif /* WLAN_FEATURE_VOWIFI_11R */ + CASE_RETURN_STRING(eNEIGHBOR_STATE_MAX); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +/* --------------------------------------------------------------------------- + \fn macTraceGetcsrRoamState + \function to get string equivalent of a value + from the enum eCsrRoamState. + + \param csrRoamState - the value from the enum + \return the string equivalent of csrRoamState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetcsrRoamState(tANI_U16 csrRoamState) +{ + switch(csrRoamState) + { + CASE_RETURN_STRING(eCSR_ROAMING_STATE_STOP); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_IDLE); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_SCANNING); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_JOINING); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_JOINED); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +/* --------------------------------------------------------------------------- + \fn macTraceGetcsrRoamSubState + \function to get string equivalent of a value + from the enum eCsrRoamSubState. + + \param csrRoamSubState - the value from the enum + \return the string equivalent of csrRoamSubState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetcsrRoamSubState(tANI_U16 csrRoamSubState) +{ + switch(csrRoamSubState) + { + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_NONE); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_START_BSS_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_JOIN_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_REASSOC_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DISASSOC_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_STOP_BSS_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_AUTH_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_CONFIG); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DEAUTH_REQ); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DISASSOC_FORCED); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC); + CASE_RETURN_STRING(eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +/* --------------------------------------------------------------------------- + \fn macTraceGetLimSmeState + \function to get string equivalent of a value + from the enum tLimSmeStates. + + \param limState - the value from the enum + \return the string equivalent of limState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetLimSmeState(tANI_U16 limState) +{ + switch(limState) + { + CASE_RETURN_STRING(eLIM_SME_OFFLINE_STATE); + CASE_RETURN_STRING(eLIM_SME_IDLE_STATE); + CASE_RETURN_STRING(eLIM_SME_SUSPEND_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_SCAN_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_JOIN_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_AUTH_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_ASSOC_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_REASSOC_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_REASSOC_LINK_FAIL_STATE); + CASE_RETURN_STRING(eLIM_SME_JOIN_FAILURE_STATE); + CASE_RETURN_STRING(eLIM_SME_ASSOCIATED_STATE); + CASE_RETURN_STRING(eLIM_SME_REASSOCIATED_STATE); + CASE_RETURN_STRING(eLIM_SME_LINK_EST_STATE); + CASE_RETURN_STRING(eLIM_SME_LINK_EST_WT_SCAN_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_PRE_AUTH_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_DISASSOC_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_DEAUTH_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_START_BSS_STATE); + CASE_RETURN_STRING(eLIM_SME_WT_STOP_BSS_STATE); + CASE_RETURN_STRING(eLIM_SME_NORMAL_STATE); + CASE_RETURN_STRING(eLIM_SME_CHANNEL_SCAN_STATE); + CASE_RETURN_STRING(eLIM_SME_NORMAL_CHANNEL_SCAN_STATE); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +/* --------------------------------------------------------------------------- + \fn macTraceGetLimMlmState + \function to get string equivalent of a value + from the enum tLimMlmStates. + + \param mlmState - the value from the enum + \return the string equivalent of mlmState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetLimMlmState(tANI_U16 mlmState) +{ + switch(mlmState) + { + CASE_RETURN_STRING(eLIM_MLM_OFFLINE_STATE); + CASE_RETURN_STRING(eLIM_MLM_IDLE_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_PROBE_RESP_STATE); + CASE_RETURN_STRING(eLIM_MLM_PASSIVE_SCAN_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_JOIN_BEACON_STATE); + CASE_RETURN_STRING(eLIM_MLM_JOINED_STATE); + CASE_RETURN_STRING(eLIM_MLM_BSS_STARTED_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_AUTH_FRAME2_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_AUTH_FRAME3_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_AUTH_FRAME4_STATE); + CASE_RETURN_STRING(eLIM_MLM_AUTH_RSP_TIMEOUT_STATE); + CASE_RETURN_STRING(eLIM_MLM_AUTHENTICATED_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ASSOC_RSP_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_REASSOC_RSP_STATE); + CASE_RETURN_STRING(eLIM_MLM_ASSOCIATED_STATE); + CASE_RETURN_STRING(eLIM_MLM_REASSOCIATED_STATE); + CASE_RETURN_STRING(eLIM_MLM_LINK_ESTABLISHED_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ASSOC_CNF_STATE); + CASE_RETURN_STRING(eLIM_MLM_LEARN_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_DEL_BSS_RSP_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_ADD_STA_RSP_STATE); + CASE_RETURN_STRING(eLIM_MLM_WT_DEL_STA_RSP_STATE); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +/* --------------------------------------------------------------------------- + \fn macTraceGetTLState + \function to get string equivalent of a value + from the enum WLANTL_STAStateType. + + \param tlState - the value from the enum + \return the string equivalent of tlState + ---------------------------------------------------------------------------*/ +tANI_U8* macTraceGetTLState(tANI_U16 tlState) +{ + switch(tlState) + { + CASE_RETURN_STRING(WLANTL_STA_INIT); + CASE_RETURN_STRING(WLANTL_STA_CONNECTED); + CASE_RETURN_STRING(WLANTL_STA_AUTHENTICATED); + CASE_RETURN_STRING(WLANTL_STA_DISCONNECTED); + CASE_RETURN_STRING(WLANTL_STA_MAX_STATE); + + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +tANI_U8* macTraceGetSmeMsgString( tANI_U16 smeMsg ) +{ + switch( smeMsg ) + { + CASE_RETURN_STRING(eWNI_SME_START_REQ); + CASE_RETURN_STRING(eWNI_SME_START_RSP); + CASE_RETURN_STRING(eWNI_SME_SYS_READY_IND); + CASE_RETURN_STRING(eWNI_SME_SCAN_REQ); + CASE_RETURN_STRING(eWNI_SME_SCAN_ABORT_IND); + CASE_RETURN_STRING(eWNI_SME_SCAN_RSP); +#ifdef FEATURE_OEM_DATA_SUPPORT + CASE_RETURN_STRING(eWNI_SME_OEM_DATA_REQ); + CASE_RETURN_STRING(eWNI_SME_OEM_DATA_RSP); +#endif + CASE_RETURN_STRING(eWNI_SME_JOIN_REQ); + CASE_RETURN_STRING(eWNI_SME_JOIN_RSP); + CASE_RETURN_STRING(eWNI_SME_SETCONTEXT_REQ); + CASE_RETURN_STRING(eWNI_SME_SETCONTEXT_RSP); + CASE_RETURN_STRING(eWNI_SME_REASSOC_REQ); + CASE_RETURN_STRING(eWNI_SME_REASSOC_RSP); + CASE_RETURN_STRING(eWNI_SME_DISASSOC_REQ); + CASE_RETURN_STRING(eWNI_SME_DISASSOC_RSP); + CASE_RETURN_STRING(eWNI_SME_DISASSOC_IND); + CASE_RETURN_STRING(eWNI_SME_DISASSOC_CNF); + CASE_RETURN_STRING(eWNI_SME_DEAUTH_REQ); + CASE_RETURN_STRING(eWNI_SME_DEAUTH_RSP); + CASE_RETURN_STRING(eWNI_SME_DEAUTH_IND); + CASE_RETURN_STRING(eWNI_SME_WM_STATUS_CHANGE_NTF); + CASE_RETURN_STRING(eWNI_SME_IBSS_NEW_PEER_IND); + CASE_RETURN_STRING(eWNI_SME_IBSS_PEER_DEPARTED_IND); + CASE_RETURN_STRING(eWNI_SME_START_BSS_REQ); + CASE_RETURN_STRING(eWNI_SME_START_BSS_RSP); + CASE_RETURN_STRING(eWNI_SME_AUTH_IND); + CASE_RETURN_STRING(eWNI_SME_ASSOC_IND); + CASE_RETURN_STRING(eWNI_SME_ASSOC_CNF); + CASE_RETURN_STRING(eWNI_SME_REASSOC_IND); + CASE_RETURN_STRING(eWNI_SME_REASSOC_CNF); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_REQ); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_RSP); + CASE_RETURN_STRING(eWNI_SME_STOP_BSS_REQ); + CASE_RETURN_STRING(eWNI_SME_STOP_BSS_RSP); + CASE_RETURN_STRING(eWNI_SME_DEL_BA_PEER_IND); + CASE_RETURN_STRING(eWNI_SME_DEFINE_QOS_REQ); + CASE_RETURN_STRING(eWNI_SME_DEFINE_QOS_RSP); + CASE_RETURN_STRING(eWNI_SME_DELETE_QOS_REQ); + CASE_RETURN_STRING(eWNI_SME_DELETE_QOS_RSP); + CASE_RETURN_STRING(eWNI_SME_LINK_TEST_START_REQ); + CASE_RETURN_STRING(eWNI_SME_LINK_TEST_START_RSP); + CASE_RETURN_STRING(eWNI_SME_LINK_TEST_STOP_REQ); + CASE_RETURN_STRING(eWNI_SME_LINK_TEST_STOP_RSP); + CASE_RETURN_STRING(eWNI_SME_LINK_TEST_REPORT_IND); + CASE_RETURN_STRING(eWNI_SME_NEIGHBOR_BSS_IND); + CASE_RETURN_STRING(eWNI_SME_MEASUREMENT_REQ); + CASE_RETURN_STRING(eWNI_SME_MEASUREMENT_RSP); + CASE_RETURN_STRING(eWNI_SME_MEASUREMENT_IND); + CASE_RETURN_STRING(eWNI_SME_SET_WDS_INFO_REQ); + CASE_RETURN_STRING(eWNI_SME_SET_WDS_INFO_RSP); + CASE_RETURN_STRING(eWNI_SME_WDS_INFO_IND); + CASE_RETURN_STRING(eWNI_SME_SET_POWER_REQ); + CASE_RETURN_STRING(eWNI_SME_SET_POWER_RSP); + CASE_RETURN_STRING(eWNI_SME_CLIENT_SIDE_LOAD_BALANCE_REQ); + CASE_RETURN_STRING(eWNI_SME_CLIENT_SIDE_LOAD_BALANCE_RSP); + CASE_RETURN_STRING(eWNI_SME_SELECT_CHANNEL_REQ); + CASE_RETURN_STRING(eWNI_SME_SELECT_CHANNEL_RSP); + CASE_RETURN_STRING(eWNI_SME_SET_PROPRIETARY_IE_REQ); + CASE_RETURN_STRING(eWNI_SME_SET_PROPRIETARY_IE_RSP); // #endif + CASE_RETURN_STRING(eWNI_SME_DISCARD_SKB_NTF); // Used to cleanup SKBs by HDD + CASE_RETURN_STRING(eWNI_SME_DEAUTH_CNF); + CASE_RETURN_STRING(eWNI_SME_MIC_FAILURE_IND); + CASE_RETURN_STRING(eWNI_SME_ADDTS_REQ); + CASE_RETURN_STRING(eWNI_SME_ADDTS_RSP); + CASE_RETURN_STRING(eWNI_SME_ADDTS_CNF); + CASE_RETURN_STRING(eWNI_SME_ADDTS_IND); + CASE_RETURN_STRING(eWNI_SME_DELTS_REQ); + CASE_RETURN_STRING(eWNI_SME_DELTS_RSP); + CASE_RETURN_STRING(eWNI_SME_DELTS_IND); + CASE_RETURN_STRING(eWNI_SME_SET_BACKGROUND_SCAN_MODE_REQ); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_CB_PRIMARY_RSP); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_CB_SECONDARY_RSP); + CASE_RETURN_STRING(eWNI_SME_PROBE_REQ); + CASE_RETURN_STRING(eWNI_SME_STA_STAT_REQ); + CASE_RETURN_STRING(eWNI_SME_STA_STAT_RSP); + CASE_RETURN_STRING(eWNI_SME_AGGR_STAT_REQ); + CASE_RETURN_STRING(eWNI_SME_AGGR_STAT_RSP); + CASE_RETURN_STRING(eWNI_SME_GLOBAL_STAT_REQ); + CASE_RETURN_STRING(eWNI_SME_GLOBAL_STAT_RSP); + CASE_RETURN_STRING(eWNI_SME_STAT_SUMM_REQ); + CASE_RETURN_STRING(eWNI_SME_STAT_SUMM_RSP); + CASE_RETURN_STRING(eWNI_SME_REMOVEKEY_REQ); + CASE_RETURN_STRING(eWNI_SME_REMOVEKEY_RSP); + CASE_RETURN_STRING(eWNI_SME_GET_SCANNED_CHANNEL_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_SCANNED_CHANNEL_RSP); + CASE_RETURN_STRING(eWNI_SME_SET_TX_POWER_REQ); + CASE_RETURN_STRING(eWNI_SME_SET_TX_POWER_RSP); + CASE_RETURN_STRING(eWNI_SME_GET_TX_POWER_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_TX_POWER_RSP); + CASE_RETURN_STRING(eWNI_SME_GET_NOISE_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_NOISE_RSP); + CASE_RETURN_STRING(eWNI_SME_LOW_RSSI_IND); + CASE_RETURN_STRING(eWNI_SME_GET_STATISTICS_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_STATISTICS_RSP); + CASE_RETURN_STRING(eWNI_SME_GET_RSSI_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_ASSOC_STAS_REQ); + CASE_RETURN_STRING(eWNI_SME_TKIP_CNTR_MEAS_REQ); + CASE_RETURN_STRING(eWNI_SME_UPDATE_APWPSIE_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_WPSPBC_SESSION_REQ); + CASE_RETURN_STRING(eWNI_SME_WPS_PBC_PROBE_REQ_IND); + CASE_RETURN_STRING(eWNI_SME_SET_APWPARSNIEs_REQ); + CASE_RETURN_STRING(eWNI_SME_UPPER_LAYER_ASSOC_CNF); + CASE_RETURN_STRING(eWNI_SME_HIDE_SSID_REQ); + CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHANNEL_REQ); + CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_IND); + CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_RSP); + CASE_RETURN_STRING(eWNI_SME_MGMT_FRM_IND); + CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_RDY_IND); + CASE_RETURN_STRING(eWNI_SME_SEND_ACTION_FRAME_IND); + CASE_RETURN_STRING(eWNI_SME_ACTION_FRAME_SEND_CNF); + CASE_RETURN_STRING(eWNI_SME_ABORT_REMAIN_ON_CHAN_IND); + CASE_RETURN_STRING(eWNI_SME_UPDATE_NOA); + CASE_RETURN_STRING(eWNI_SME_CLEAR_DFS_CHANNEL_LIST); + CASE_RETURN_STRING(eWNI_SME_CLEAR_LIM_SCAN_CACHE); + CASE_RETURN_STRING(eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER); + CASE_RETURN_STRING(eWNI_SME_GET_SNR_REQ); + CASE_RETURN_STRING(eWNI_SME_LINK_STATUS_IND); + CASE_RETURN_STRING(eWNI_SME_FW_STATUS_IND); + + CASE_RETURN_STRING(eWNI_PMC_MSG_TYPES_BEGIN); + + //General Power Save Messages + CASE_RETURN_STRING(eWNI_PMC_PWR_SAVE_CFG); + + //BMPS Messages + CASE_RETURN_STRING(eWNI_PMC_ENTER_BMPS_REQ); + CASE_RETURN_STRING(eWNI_PMC_ENTER_BMPS_RSP); + CASE_RETURN_STRING(eWNI_PMC_EXIT_BMPS_REQ); + CASE_RETURN_STRING(eWNI_PMC_EXIT_BMPS_RSP); + CASE_RETURN_STRING(eWNI_PMC_EXIT_BMPS_IND); + + //IMPS Messages. + CASE_RETURN_STRING(eWNI_PMC_ENTER_IMPS_REQ); + CASE_RETURN_STRING(eWNI_PMC_ENTER_IMPS_RSP); + CASE_RETURN_STRING(eWNI_PMC_EXIT_IMPS_REQ); + CASE_RETURN_STRING(eWNI_PMC_EXIT_IMPS_RSP); + + //UAPSD Messages + CASE_RETURN_STRING(eWNI_PMC_ENTER_UAPSD_REQ); + CASE_RETURN_STRING(eWNI_PMC_ENTER_UAPSD_RSP); + CASE_RETURN_STRING(eWNI_PMC_EXIT_UAPSD_REQ); + CASE_RETURN_STRING(eWNI_PMC_EXIT_UAPSD_RSP); + + CASE_RETURN_STRING(eWNI_PMC_SMPS_STATE_IND); + CASE_RETURN_STRING(eWNI_PMC_WOWL_ADD_BCAST_PTRN); + CASE_RETURN_STRING(eWNI_PMC_WOWL_DEL_BCAST_PTRN); + CASE_RETURN_STRING(eWNI_PMC_ENTER_WOWL_REQ); + CASE_RETURN_STRING(eWNI_PMC_ENTER_WOWL_RSP); + CASE_RETURN_STRING(eWNI_PMC_EXIT_WOWL_REQ); + CASE_RETURN_STRING(eWNI_PMC_EXIT_WOWL_RSP); + +#ifdef WLAN_FEATURE_PACKET_FILTERING + CASE_RETURN_STRING(eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP); +#endif // WLAN_FEATURE_PACKET_FILTERING +#if defined WLAN_FEATURE_VOWIFI + CASE_RETURN_STRING(eWNI_SME_RRM_MSG_TYPE_BEGIN); + CASE_RETURN_STRING(eWNI_SME_NEIGHBOR_REPORT_REQ_IND); + CASE_RETURN_STRING(eWNI_SME_NEIGHBOR_REPORT_IND); + CASE_RETURN_STRING(eWNI_SME_BEACON_REPORT_REQ_IND); + CASE_RETURN_STRING(eWNI_SME_BEACON_REPORT_RESP_XMIT_IND); +#endif + CASE_RETURN_STRING(eWNI_SME_ADD_STA_SELF_REQ); + CASE_RETURN_STRING(eWNI_SME_ADD_STA_SELF_RSP); + CASE_RETURN_STRING(eWNI_SME_DEL_STA_SELF_REQ); + CASE_RETURN_STRING(eWNI_SME_DEL_STA_SELF_RSP); +#if defined WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STRING(eWNI_SME_FT_PRE_AUTH_REQ); + CASE_RETURN_STRING(eWNI_SME_FT_PRE_AUTH_RSP); + CASE_RETURN_STRING(eWNI_SME_FT_UPDATE_KEY); + CASE_RETURN_STRING(eWNI_SME_FT_AGGR_QOS_REQ); + CASE_RETURN_STRING(eWNI_SME_FT_AGGR_QOS_RSP); +#endif +#if defined FEATURE_WLAN_ESE + CASE_RETURN_STRING(eWNI_SME_ESE_ADJACENT_AP_REPORT); +#endif + CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_REQ); + CASE_RETURN_STRING(eWNI_SME_COEX_IND); +#ifdef FEATURE_WLAN_SCAN_PNO + CASE_RETURN_STRING(eWNI_SME_PREF_NETWORK_FOUND_IND); +#endif // FEATURE_WLAN_SCAN_PNO + CASE_RETURN_STRING(eWNI_SME_TX_PER_HIT_IND); + CASE_RETURN_STRING(eWNI_SME_CHANGE_COUNTRY_CODE); + CASE_RETURN_STRING(eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE); + CASE_RETURN_STRING(eWNI_SME_PRE_SWITCH_CHL_IND); + CASE_RETURN_STRING(eWNI_SME_POST_SWITCH_CHL_IND); + CASE_RETURN_STRING(eWNI_SME_MAX_ASSOC_EXCEEDED); + CASE_RETURN_STRING(eWNI_SME_BTAMP_LOG_LINK_IND);//to serialize the create/accpet LL req from HCI +#ifdef WLAN_FEATURE_GTK_OFFLOAD + CASE_RETURN_STRING(eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP); +#endif // WLAN_FEATURE_GTK_OFFLOAD +#ifdef WLAN_WAKEUP_EVENTS + CASE_RETURN_STRING(eWNI_SME_WAKE_REASON_IND); +#endif // WLAN_WAKEUP_EVENTS + CASE_RETURN_STRING(eWNI_SME_EXCLUDE_UNENCRYPTED); + CASE_RETURN_STRING(eWNI_SME_RSSI_IND); //RSSI indication from TL to be serialized on MC thread + CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END); + CASE_RETURN_STRING(eWNI_SME_GET_TSM_STATS_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_TSM_STATS_RSP); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CASE_RETURN_STRING(eWNI_SME_ROAM_OFFLOAD_SYNCH_IND); +#endif + CASE_RETURN_STRING(eWNI_SME_LOST_LINK_INFO_IND); + CASE_RETURN_STRING(eWNI_SME_SMPS_FORCE_MODE_IND); + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + + +tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ) +{ + switch( wdaMsg ) + { + CASE_RETURN_STRING(WDA_APP_SETUP_NTF); + CASE_RETURN_STRING(WDA_NIC_OPER_NTF); + CASE_RETURN_STRING(WDA_INIT_START_REQ); + CASE_RETURN_STRING(WDA_RESET_REQ); + CASE_RETURN_STRING(WDA_HDD_ADDBA_REQ); + CASE_RETURN_STRING(WDA_HDD_ADDBA_RSP); + CASE_RETURN_STRING(WDA_DELETEBA_IND); + CASE_RETURN_STRING(WDA_BA_FAIL_IND); + CASE_RETURN_STRING(WDA_TL_FLUSH_AC_REQ); + CASE_RETURN_STRING(WDA_TL_FLUSH_AC_RSP); + + CASE_RETURN_STRING(WDA_ITC_MSG_TYPES_BEGIN); + CASE_RETURN_STRING(WDA_WDT_KAM_RSP); + CASE_RETURN_STRING(WDA_TIMER_TEMP_MEAS_REQ); + CASE_RETURN_STRING(WDA_TIMER_PERIODIC_STATS_COLLECT_REQ); + CASE_RETURN_STRING(WDA_CAL_REQ_NTF); + CASE_RETURN_STRING(WDA_MNT_OPEN_TPC_TEMP_MEAS_REQ); + CASE_RETURN_STRING(WDA_CCA_MONITOR_INTERVAL_TO); + CASE_RETURN_STRING(WDA_CCA_MONITOR_DURATION_TO); + CASE_RETURN_STRING(WDA_CCA_MONITOR_START); + CASE_RETURN_STRING(WDA_CCA_MONITOR_STOP); + CASE_RETURN_STRING(WDA_CCA_CHANGE_MODE); + CASE_RETURN_STRING(WDA_TIMER_WRAP_AROUND_STATS_COLLECT_REQ); + + CASE_RETURN_STRING(WDA_ADD_STA_REQ); + CASE_RETURN_STRING(WDA_ADD_STA_RSP); + CASE_RETURN_STRING(WDA_ADD_STA_SELF_RSP); + CASE_RETURN_STRING(WDA_DEL_STA_SELF_RSP); + CASE_RETURN_STRING(WDA_DELETE_STA_REQ); + CASE_RETURN_STRING(WDA_DELETE_STA_RSP); + CASE_RETURN_STRING(WDA_ADD_BSS_REQ); + CASE_RETURN_STRING(WDA_ADD_BSS_RSP); + CASE_RETURN_STRING(WDA_DELETE_BSS_REQ); + CASE_RETURN_STRING(WDA_DELETE_BSS_RSP); + CASE_RETURN_STRING(WDA_INIT_SCAN_REQ); + CASE_RETURN_STRING(WDA_INIT_SCAN_RSP); + CASE_RETURN_STRING(WDA_START_SCAN_REQ); + CASE_RETURN_STRING(WDA_START_SCAN_RSP); + CASE_RETURN_STRING(WDA_END_SCAN_REQ); + CASE_RETURN_STRING(WDA_END_SCAN_RSP); + CASE_RETURN_STRING(WDA_FINISH_SCAN_REQ); + CASE_RETURN_STRING(WDA_FINISH_SCAN_RSP); + CASE_RETURN_STRING(WDA_SEND_BEACON_REQ); + CASE_RETURN_STRING(WDA_SEND_BEACON_RSP); + + CASE_RETURN_STRING(WDA_INIT_CFG_REQ); + CASE_RETURN_STRING(WDA_INIT_CFG_RSP); + + CASE_RETURN_STRING(WDA_INIT_WM_CFG_REQ); + CASE_RETURN_STRING(WDA_INIT_WM_CFG_RSP); + + CASE_RETURN_STRING(WDA_SET_BSSKEY_REQ); + CASE_RETURN_STRING(WDA_SET_BSSKEY_RSP); + CASE_RETURN_STRING(WDA_SET_STAKEY_REQ); + CASE_RETURN_STRING(WDA_SET_STAKEY_RSP); + CASE_RETURN_STRING(WDA_DPU_STATS_REQ); + CASE_RETURN_STRING(WDA_DPU_STATS_RSP); + CASE_RETURN_STRING(WDA_GET_DPUINFO_REQ); + CASE_RETURN_STRING(WDA_GET_DPUINFO_RSP); + + CASE_RETURN_STRING(WDA_UPDATE_EDCA_PROFILE_IND); + + CASE_RETURN_STRING(WDA_UPDATE_STARATEINFO_REQ); + CASE_RETURN_STRING(WDA_UPDATE_STARATEINFO_RSP); + + CASE_RETURN_STRING(WDA_UPDATE_BEACON_IND); + CASE_RETURN_STRING(WDA_UPDATE_CF_IND); + CASE_RETURN_STRING(WDA_CHNL_SWITCH_REQ); + CASE_RETURN_STRING(WDA_ADD_TS_REQ); + CASE_RETURN_STRING(WDA_DEL_TS_REQ); + CASE_RETURN_STRING(WDA_SOFTMAC_TXSTAT_REPORT); + CASE_RETURN_STRING(WDA_MBOX_SENDMSG_COMPLETE_IND); + CASE_RETURN_STRING(WDA_EXIT_BMPS_REQ); + CASE_RETURN_STRING(WDA_EXIT_BMPS_RSP); + CASE_RETURN_STRING(WDA_EXIT_BMPS_IND); + CASE_RETURN_STRING(WDA_ENTER_BMPS_REQ); + CASE_RETURN_STRING(WDA_ENTER_BMPS_RSP); + CASE_RETURN_STRING(WDA_BMPS_STATUS_IND); + CASE_RETURN_STRING(WDA_MISSED_BEACON_IND); + + CASE_RETURN_STRING(WDA_CFG_RXP_FILTER_REQ); + CASE_RETURN_STRING(WDA_CFG_RXP_FILTER_RSP); + CASE_RETURN_STRING(WDA_SWITCH_CHANNEL_RSP); + CASE_RETURN_STRING(WDA_P2P_NOA_ATTR_IND); + CASE_RETURN_STRING(WDA_P2P_NOA_START_IND); + CASE_RETURN_STRING(WDA_PWR_SAVE_CFG); + + CASE_RETURN_STRING(WDA_REGISTER_PE_CALLBACK); + CASE_RETURN_STRING(WDA_SOFTMAC_MEM_READREQUEST); + CASE_RETURN_STRING(WDA_SOFTMAC_MEM_WRITEREQUEST); + + CASE_RETURN_STRING(WDA_SOFTMAC_MEM_READRESPONSE); + CASE_RETURN_STRING(WDA_SOFTMAC_BULKREGWRITE_CONFIRM); + CASE_RETURN_STRING(WDA_SOFTMAC_BULKREGREAD_RESPONSE); + CASE_RETURN_STRING(WDA_SOFTMAC_HOSTMESG_MSGPROCESSRESULT); + + CASE_RETURN_STRING(WDA_ADDBA_REQ); + CASE_RETURN_STRING(WDA_ADDBA_RSP); + CASE_RETURN_STRING(WDA_DELBA_IND); + CASE_RETURN_STRING(WDA_DEL_BA_IND); + CASE_RETURN_STRING(WDA_MIC_FAILURE_IND); + + CASE_RETURN_STRING(WDA_DELBA_REQ); + CASE_RETURN_STRING(WDA_IBSS_STA_ADD); + CASE_RETURN_STRING(WDA_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND); + CASE_RETURN_STRING(WDA_SET_LINK_STATE); + CASE_RETURN_STRING(WDA_SET_LINK_STATE_RSP); + CASE_RETURN_STRING(WDA_ENTER_IMPS_REQ); + CASE_RETURN_STRING(WDA_ENTER_IMPS_RSP); + CASE_RETURN_STRING(WDA_EXIT_IMPS_RSP); + CASE_RETURN_STRING(WDA_EXIT_IMPS_REQ); + CASE_RETURN_STRING(WDA_SOFTMAC_HOSTMESG_PS_STATUS_IND); + CASE_RETURN_STRING(WDA_POSTPONE_ENTER_IMPS_RSP); + CASE_RETURN_STRING(WDA_STA_STAT_REQ); + CASE_RETURN_STRING(WDA_GLOBAL_STAT_REQ); + CASE_RETURN_STRING(WDA_AGGR_STAT_REQ); + CASE_RETURN_STRING(WDA_STA_STAT_RSP); + CASE_RETURN_STRING(WDA_GLOBAL_STAT_RSP); + CASE_RETURN_STRING(WDA_AGGR_STAT_RSP); + CASE_RETURN_STRING(WDA_STAT_SUMM_REQ); + CASE_RETURN_STRING(WDA_STAT_SUMM_RSP); + CASE_RETURN_STRING(WDA_REMOVE_BSSKEY_REQ); + CASE_RETURN_STRING(WDA_REMOVE_BSSKEY_RSP); + CASE_RETURN_STRING(WDA_REMOVE_STAKEY_REQ); + CASE_RETURN_STRING(WDA_REMOVE_STAKEY_RSP); + CASE_RETURN_STRING(WDA_SET_STA_BCASTKEY_REQ); + CASE_RETURN_STRING(WDA_SET_STA_BCASTKEY_RSP); + CASE_RETURN_STRING(WDA_REMOVE_STA_BCASTKEY_REQ); + CASE_RETURN_STRING(WDA_REMOVE_STA_BCASTKEY_RSP); + CASE_RETURN_STRING(WDA_ADD_TS_RSP); + CASE_RETURN_STRING(WDA_DPU_MIC_ERROR); + + CASE_RETURN_STRING(WDA_TIMER_BA_ACTIVITY_REQ); + CASE_RETURN_STRING(WDA_TIMER_CHIP_MONITOR_TIMEOUT); + CASE_RETURN_STRING(WDA_TIMER_TRAFFIC_ACTIVITY_REQ); + CASE_RETURN_STRING(WDA_TIMER_ADC_RSSI_STATS); +#ifdef FEATURE_WLAN_ESE + CASE_RETURN_STRING(WDA_TSM_STATS_REQ); + CASE_RETURN_STRING(WDA_TSM_STATS_RSP); +#endif + CASE_RETURN_STRING(WDA_UPDATE_UAPSD_IND); + CASE_RETURN_STRING(WDA_SET_MIMOPS_REQ); + CASE_RETURN_STRING(WDA_SET_MIMOPS_RSP); + CASE_RETURN_STRING(WDA_SYS_READY_IND ); + CASE_RETURN_STRING(WDA_SET_TX_POWER_REQ); + CASE_RETURN_STRING(WDA_SET_TX_POWER_RSP); + CASE_RETURN_STRING(WDA_GET_TX_POWER_REQ); + CASE_RETURN_STRING(WDA_GET_NOISE_REQ ); + CASE_RETURN_STRING(WDA_SET_TX_PER_TRACKING_REQ); + + CASE_RETURN_STRING(WDA_TRANSMISSION_CONTROL_IND); + CASE_RETURN_STRING(WDA_INIT_RADAR_IND); + + CASE_RETURN_STRING(WDA_BEACON_PRE_IND ); + CASE_RETURN_STRING(WDA_ENTER_UAPSD_REQ); + CASE_RETURN_STRING(WDA_ENTER_UAPSD_RSP); + CASE_RETURN_STRING(WDA_EXIT_UAPSD_REQ ); + CASE_RETURN_STRING(WDA_EXIT_UAPSD_RSP ); + CASE_RETURN_STRING(WDA_BEACON_FILTER_IND); + CASE_RETURN_STRING(WDA_WOWL_ADD_BCAST_PTRN); + CASE_RETURN_STRING(WDA_WOWL_DEL_BCAST_PTRN); + CASE_RETURN_STRING(WDA_WOWL_ENTER_REQ); + CASE_RETURN_STRING(WDA_WOWL_ENTER_RSP); + CASE_RETURN_STRING(WDA_WOWL_EXIT_REQ ); + CASE_RETURN_STRING(WDA_WOWL_EXIT_RSP ); + CASE_RETURN_STRING(WDA_TX_COMPLETE_IND); + CASE_RETURN_STRING(WDA_TIMER_RA_COLLECT_AND_ADAPT); + CASE_RETURN_STRING(WDA_GET_STATISTICS_REQ); + CASE_RETURN_STRING(WDA_GET_STATISTICS_RSP); + CASE_RETURN_STRING(WDA_SET_KEY_DONE); + + CASE_RETURN_STRING(WDA_BTC_SET_CFG); + CASE_RETURN_STRING(WDA_SIGNAL_BT_EVENT); + CASE_RETURN_STRING(WDA_HANDLE_FW_MBOX_RSP); + CASE_RETURN_STRING(WDA_SEND_PROBE_RSP_TMPL); +#ifdef FEATURE_OEM_DATA_SUPPORT + CASE_RETURN_STRING(WDA_START_OEM_DATA_REQ ); + CASE_RETURN_STRING(WDA_START_OEM_DATA_RSP); + CASE_RETURN_STRING(WDA_FINISH_OEM_DATA_REQ); +#endif //SUPPORT_BEACON_FILTER + CASE_RETURN_STRING(WDA_SET_MAX_TX_POWER_REQ); + CASE_RETURN_STRING(WDA_SET_MAX_TX_POWER_RSP); + CASE_RETURN_STRING(WDA_SEND_MSG_COMPLETE); + CASE_RETURN_STRING(WDA_SET_HOST_OFFLOAD); + CASE_RETURN_STRING(WDA_SET_KEEP_ALIVE); +#ifdef WLAN_NS_OFFLOAD + CASE_RETURN_STRING(WDA_SET_NS_OFFLOAD); +#endif //WLAN_NS_OFFLOAD + CASE_RETURN_STRING(WDA_ADD_STA_SELF_REQ); + CASE_RETURN_STRING(WDA_DEL_STA_SELF_REQ); + CASE_RETURN_STRING(WDA_SET_P2P_GO_NOA_REQ); + CASE_RETURN_STRING(WDA_TX_COMPLETE_TIMEOUT_IND); + CASE_RETURN_STRING(WDA_WLAN_SUSPEND_IND); + CASE_RETURN_STRING(WDA_WLAN_RESUME_REQ); +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + CASE_RETURN_STRING(WDA_WLAN_EXT_WOW); + CASE_RETURN_STRING(WDA_WLAN_SET_APP_TYPE1_PARAMS); + CASE_RETURN_STRING(WDA_WLAN_SET_APP_TYPE2_PARAMS); +#endif + CASE_RETURN_STRING(WDA_MSG_TYPES_END); + CASE_RETURN_STRING(WDA_MMH_TXMB_READY_EVT); + CASE_RETURN_STRING(WDA_MMH_RXMB_DONE_EVT); + CASE_RETURN_STRING(WDA_MMH_MSGQ_NE_EVT); +#ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STRING(WDA_AGGR_QOS_REQ); + CASE_RETURN_STRING(WDA_AGGR_QOS_RSP); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + CASE_RETURN_STRING(WDA_FTM_CMD_REQ); + CASE_RETURN_STRING(WDA_FTM_CMD_RSP); +#ifdef FEATURE_WLAN_SCAN_PNO + CASE_RETURN_STRING(WDA_SET_PNO_REQ); + CASE_RETURN_STRING(WDA_UPDATE_SCAN_PARAMS_REQ); + CASE_RETURN_STRING(WDA_SET_PNO_CHANGED_IND); + CASE_RETURN_STRING(WDA_SME_SCAN_CACHE_UPDATED); +#endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING(WDA_ROAM_SCAN_OFFLOAD_REQ); +#endif +#ifdef WLAN_WAKEUP_EVENTS + CASE_RETURN_STRING(WDA_WAKE_REASON_IND); +#endif // WLAN_WAKEUP_EVENTS +#ifdef WLAN_FEATURE_PACKET_FILTERING + CASE_RETURN_STRING(WDA_8023_MULTICAST_LIST_REQ); + CASE_RETURN_STRING(WDA_RECEIVE_FILTER_SET_FILTER_REQ); + CASE_RETURN_STRING(WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ); + CASE_RETURN_STRING(WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP); + CASE_RETURN_STRING(WDA_RECEIVE_FILTER_CLEAR_FILTER_REQ); +#endif // WLAN_FEATURE_PACKET_FILTERING + CASE_RETURN_STRING(WDA_SET_POWER_PARAMS_REQ); +#ifdef WLAN_FEATURE_GTK_OFFLOAD + CASE_RETURN_STRING(WDA_GTK_OFFLOAD_REQ); + CASE_RETURN_STRING(WDA_GTK_OFFLOAD_GETINFO_REQ); + CASE_RETURN_STRING(WDA_GTK_OFFLOAD_GETINFO_RSP); +#endif //WLAN_FEATURE_GTK_OFFLOAD + CASE_RETURN_STRING(WDA_SET_TM_LEVEL_REQ); +#ifdef WLAN_FEATURE_11AC + CASE_RETURN_STRING(WDA_UPDATE_OP_MODE); + CASE_RETURN_STRING(WDA_UPDATE_MEMBERSHIP); + CASE_RETURN_STRING(WDA_UPDATE_USERPOS); +#endif + CASE_RETURN_STRING(WDA_START_SCAN_OFFLOAD_REQ); + CASE_RETURN_STRING(WDA_STOP_SCAN_OFFLOAD_REQ); + CASE_RETURN_STRING(WDA_UPDATE_CHAN_LIST_REQ); + CASE_RETURN_STRING(WDA_CLI_SET_CMD); +#ifndef REMOVE_PKT_LOG + CASE_RETURN_STRING(WDA_PKTLOG_ENABLE_REQ); +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + CASE_RETURN_STRING(WDA_SET_PLM_REQ); +#endif + CASE_RETURN_STRING(WDA_CONFIG_PARAM_UPDATE_REQ); + CASE_RETURN_STRING(WDA_RATE_UPDATE_IND); +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(WDA_UPDATE_FW_TDLS_STATE); + CASE_RETURN_STRING(WDA_UPDATE_TDLS_PEER_STATE); +#endif + CASE_RETURN_STRING(WDA_ADD_PERIODIC_TX_PTRN_IND); + CASE_RETURN_STRING(WDA_TX_POWER_LIMIT); +#ifdef FEATURE_WLAN_LPHB + CASE_RETURN_STRING(WDA_LPHB_CONF_REQ); +#endif + CASE_RETURN_STRING(WDA_DHCP_START_IND); + CASE_RETURN_STRING(WDA_DHCP_STOP_IND); +#ifdef FEATURE_WLAN_CH_AVOID + CASE_RETURN_STRING(WDA_CH_AVOID_UPDATE_REQ); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + CASE_RETURN_STRING(WDA_SET_AUTO_SHUTDOWN_TIMER_REQ); +#endif + CASE_RETURN_STRING(WDA_INIT_THERMAL_INFO_CMD); + CASE_RETURN_STRING(WDA_SET_THERMAL_LEVEL); + CASE_RETURN_STRING(WDA_SET_SAP_INTRABSS_DIS); + CASE_RETURN_STRING(WDA_FW_STATS_IND); + CASE_RETURN_STRING(WDA_VDEV_STOP_IND); + CASE_RETURN_STRING(WDA_TBTT_UPDATE_IND); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CASE_RETURN_STRING(WDA_ROAM_OFFLOAD_SYNCH_CNF); + CASE_RETURN_STRING(WDA_ROAM_OFFLOAD_SYNCH_FAIL); +#endif + CASE_RETURN_STRING(SIR_HAL_SET_BASE_MACADDR_IND); + CASE_RETURN_STRING(WDA_LINK_STATUS_GET_REQ); + CASE_RETURN_STRING(WDA_GET_FW_STATUS_REQ); +#ifdef DHCP_SERVER_OFFLOAD + CASE_RETURN_STRING(WDA_SET_DHCP_SERVER_OFFLOAD_CMD); +#endif +#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 +#ifdef WLAN_FEATURE_APFIND + CASE_RETURN_STRING(WDA_APFIND_SET_CMD); +#endif /*WLAN_FEATURE_APFIND*/ +#ifdef FEATURE_RUNTIME_PM + CASE_RETURN_STRING(WDA_RUNTIME_PM_SUSPEND_IND); + CASE_RETURN_STRING(WDA_RUNTIME_PM_RESUME_IND); +#endif + CASE_RETURN_STRING(WDA_OCB_SET_CONFIG_CMD); + CASE_RETURN_STRING(WDA_OCB_SET_UTC_TIME_CMD); + CASE_RETURN_STRING(WDA_OCB_START_TIMING_ADVERT_CMD); + CASE_RETURN_STRING(WDA_OCB_STOP_TIMING_ADVERT_CMD); + CASE_RETURN_STRING(WDA_OCB_GET_TSF_TIMER_CMD); + CASE_RETURN_STRING(WDA_DCC_GET_STATS_CMD); + CASE_RETURN_STRING(WDA_DCC_CLEAR_STATS_CMD); + CASE_RETURN_STRING(WDA_DCC_UPDATE_NDL_CMD); + CASE_RETURN_STRING(WNI_CFG_DNLD_REQ); + CASE_RETURN_STRING(WDA_SET_PDEV_IE_REQ); +#ifdef WLAN_FEATURE_11AC + CASE_RETURN_STRING(WDA_UPDATE_RX_NSS); +#endif +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(WDA_TDLS_SET_OFFCHAN_MODE); +#endif + CASE_RETURN_STRING(WDA_DEL_PERIODIC_TX_PTRN_IND); + CASE_RETURN_STRING(WDA_INIT_BAD_PEER_TX_CTL_INFO_CMD); + CASE_RETURN_STRING(WDA_GET_LINK_SPEED); + CASE_RETURN_STRING(WDA_MODEM_POWER_STATE_IND); +#ifdef WLAN_FEATURE_STATS_EXT + CASE_RETURN_STRING(WDA_STATS_EXT_REQUEST); +#endif + CASE_RETURN_STRING(WDA_HIDDEN_SSID_VDEV_RESTART); + CASE_RETURN_STRING(WDA_VDEV_START_RSP_IND); + CASE_RETURN_STRING(WDA_ROAM_PREAUTH_IND); +#ifdef FEATURE_WLAN_EXTSCAN + CASE_RETURN_STRING(WDA_EXTSCAN_START_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_STOP_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_SET_BSSID_HOTLIST_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_RESET_BSSID_HOTLIST_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_SET_SSID_HOTLIST_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_SET_SIGNF_CHANGE_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_RESET_SIGNF_CHANGE_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_GET_CACHED_RESULTS_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_GET_CAPABILITIES_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_STATUS_IND); + CASE_RETURN_STRING(WDA_EXTSCAN_OPERATION_IND); + CASE_RETURN_STRING(WDA_SET_EPNO_LIST_REQ); + CASE_RETURN_STRING(WDA_SET_PASSPOINT_LIST_REQ); + CASE_RETURN_STRING(WDA_RESET_PASSPOINT_LIST_REQ); +#endif + CASE_RETURN_STRING(WDA_SET_SCAN_MAC_OUI_REQ); +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + CASE_RETURN_STRING(WDA_LINK_LAYER_STATS_CLEAR_REQ); + CASE_RETURN_STRING(WDA_LINK_LAYER_STATS_SET_REQ); + CASE_RETURN_STRING(WDA_LINK_LAYER_STATS_GET_REQ); + CASE_RETURN_STRING(WDA_LINK_LAYER_STATS_RESULTS_RSP); +#endif + CASE_RETURN_STRING(SIR_HAL_UNIT_TEST_CMD); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CASE_RETURN_STRING(SIR_HAL_ROAM_INVOKE); +#endif +#ifdef WLAN_FEATURE_NAN + CASE_RETURN_STRING(WDA_NAN_REQUEST); +#endif + CASE_RETURN_STRING(WDA_GET_LINK_STATUS_RSP_IND); + CASE_RETURN_STRING(WDA_GET_TEMPERATURE_REQ); +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + CASE_RETURN_STRING(WDA_LED_FLASHING_REQ); +#endif + CASE_RETURN_STRING(WDA_IPA_OFFLOAD_ENABLE_DISABLE); +#ifdef SAP_AUTH_OFFLOAD + CASE_RETURN_STRING(WDA_SET_SAP_AUTH_OFL); +#endif + CASE_RETURN_STRING(SIR_HAL_SET_MAS); + CASE_RETURN_STRING(SIR_HAL_SET_MIRACAST); + CASE_RETURN_STRING(SIR_HAL_CONFIG_STATS_FACTOR); + CASE_RETURN_STRING(SIR_HAL_CONFIG_GUARD_TIME); + CASE_RETURN_STRING(WDA_FW_MEM_DUMP_REQ); + CASE_RETURN_STRING(SIR_HAL_START_STOP_LOGGING); + CASE_RETURN_STRING(WDA_TSF_GPIO_PIN); + CASE_RETURN_STRING(SIR_HAL_FLUSH_LOG_TO_FW); + CASE_RETURN_STRING(WDA_SET_IE_INFO); + CASE_RETURN_STRING(WDA_SET_RSSI_MONITOR_REQ); + default: + return((tANI_U8*) "UNKNOWN" ); + break; + } +} + +tANI_U8* macTraceGetLimMsgString( tANI_U16 limMsg ) +{ + switch( limMsg ) + { + CASE_RETURN_STRING(SIR_LIM_RETRY_INTERRUPT_MSG); + CASE_RETURN_STRING(SIR_BB_XPORT_MGMT_MSG ); + CASE_RETURN_STRING(SIR_LIM_INV_KEY_INTERRUPT_MSG ); + CASE_RETURN_STRING(SIR_LIM_KEY_ID_INTERRUPT_MSG ); + CASE_RETURN_STRING(SIR_LIM_REPLAY_THRES_INTERRUPT_MSG ); + CASE_RETURN_STRING(SIR_LIM_TD_DUMMY_CALLBACK_MSG ); + CASE_RETURN_STRING(SIR_LIM_SCH_CLEAN_MSG ); + CASE_RETURN_STRING(SIR_LIM_RADAR_DETECT_IND); + CASE_RETURN_STRING(SIR_LIM_DEL_TS_IND); + CASE_RETURN_STRING(SIR_LIM_ADD_BA_IND ); + CASE_RETURN_STRING(SIR_LIM_DEL_BA_ALL_IND); + CASE_RETURN_STRING(SIR_LIM_DELETE_STA_CONTEXT_IND); + CASE_RETURN_STRING(SIR_LIM_DEL_BA_IND ); + CASE_RETURN_STRING(SIR_LIM_UPDATE_BEACON); + CASE_RETURN_STRING(SIR_LIM_MIN_CHANNEL_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_MAX_CHANNEL_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_JOIN_FAIL_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_AUTH_FAIL_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_AUTH_RSP_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_ASSOC_FAIL_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_REASSOC_FAIL_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_HEART_BEAT_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_CHANNEL_SCAN_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_PROBE_HB_FAILURE_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_ADDTS_RSP_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_LINK_TEST_DURATION_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_HASH_MISS_THRES_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_CNF_WAIT_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_KEEPALIVE_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_CHANNEL_SWITCH_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_QUIET_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_QUIET_BSS_TIMEOUT ); + CASE_RETURN_STRING(SIR_LIM_WPS_OVERLAP_TIMEOUT); +#ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STRING(SIR_LIM_FT_PREAUTH_RSP_TIMEOUT); +#endif + CASE_RETURN_STRING(SIR_LIM_REMAIN_CHN_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE); + CASE_RETURN_STRING(SIR_LIM_BEACON_GEN_IND ); + CASE_RETURN_STRING(SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT); +#ifdef FEATURE_WLAN_ESE + CASE_RETURN_STRING(SIR_LIM_ESE_TSM_TIMEOUT); +#endif + 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); + CASE_RETURN_STRING(SIR_LIM_AUTH_RETRY_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_MSG_TYPES_END); + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +tANI_U8* macTraceGetCfgMsgString( tANI_U16 cfgMsg ) +{ + switch( cfgMsg ) + { + CASE_RETURN_STRING(WNI_CFG_PARAM_UPDATE_IND); + CASE_RETURN_STRING(WNI_CFG_DNLD_REQ); + CASE_RETURN_STRING(WNI_CFG_DNLD_CNF); + CASE_RETURN_STRING(WNI_CFG_GET_RSP); + CASE_RETURN_STRING(WNI_CFG_SET_CNF); + CASE_RETURN_STRING(SIR_CFG_PARAM_UPDATE_IND); + CASE_RETURN_STRING(SIR_CFG_DOWNLOAD_COMPLETE_IND); + + CASE_RETURN_STRING(WNI_CFG_SET_REQ_NO_RSP); + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +tANI_U8* macTraceGetInfoLogString( tANI_U16 infoLog ) +{ + switch( infoLog ) + { + CASE_RETURN_STRING(eLOG_NODROP_MISSED_BEACON_SCENARIO); + CASE_RETURN_STRING(eLOG_PROC_DEAUTH_FRAME_SCENARIO); + default: + return( (tANI_U8*)"UNKNOWN" ); + break; + } +} + +tANI_U8* macTraceGetModuleString( tANI_U8 moduleId ) +{ + return ((tANI_U8*)"PE"); + //return gVosTraceInfo[moduleId].moduleNameStr; +} + +void macTraceReset(tpAniSirGlobal pMac) +{ +} + +void macTrace(tpAniSirGlobal pMac, tANI_U8 code, tANI_U16 session, + tANI_U32 data) +{ + /* Today macTrace is being invoked by PE only, + * need to remove this function once PE is migrated to using new trace API. + */ + macTraceNew(pMac, VOS_MODULE_ID_PE, code, session, data); +} + +void macTraceNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 code, + tANI_U16 session, tANI_U32 data) +{ + vos_trace(module, code, session, data); +} + +tANI_U8* macTraceMsgString(tpAniSirGlobal pMac, tANI_U32 msgType) +{ + tANI_U16 msgId = (tANI_U16)MAC_TRACE_GET_MSG_ID(msgType); + tANI_U8 moduleId = (tANI_U8)MAC_TRACE_GET_MODULE_ID(msgType); + + switch(moduleId) + { + case SIR_LIM_MODULE_ID: + if(msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + return macTraceGetLimMsgString((tANI_U16)msgType); + else + return macTraceGetSmeMsgString((tANI_U16)msgType); + break; + case SIR_WDA_MODULE_ID: + return macTraceGetWdaMsgString((tANI_U16)msgType); + case SIR_CFG_MODULE_ID: + return macTraceGetCfgMsgString((tANI_U16)msgType); + default: + return ((tANI_U8*)"Unknown MsgType"); + } +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c new file mode 100644 index 000000000000..7c9128f716d1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c @@ -0,0 +1,5720 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file parserApi.cc contains the code for parsing + * 802.11 messages. + * Author: Pierre Vandwalle + * Date: 03/18/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "sirApi.h" +#include "aniGlobal.h" +#include "parserApi.h" +#include "cfgApi.h" +#include "limUtils.h" +#include "utilsParser.h" +#include "limSerDesUtils.h" +#include "schApi.h" +#include "palApi.h" +#include "wmmApsd.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrmApi.h" +#endif + +#include "regdomain_common.h" + +#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 } +}; + + +//////////////////////////////////////////////////////////////////////// +void dot11fLog(tpAniSirGlobal pMac, int loglevel, const char *pString,...) +{ +#ifdef WLAN_DEBUG + if( (tANI_U32)loglevel > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE( SIR_DBG_MODULE_ID )] ) + { + return; + } + else + { + va_list marker; + + va_start( marker, pString ); /* Initialize variable arguments. */ + + logDebug(pMac, SIR_DBG_MODULE_ID, loglevel, pString, marker); + + va_end( marker ); /* Reset variable arguments. */ + } +#endif +} + +void +swapBitField16(tANI_U16 in, tANI_U16 *out) +{ +# ifdef ANI_LITTLE_BIT_ENDIAN + *out = in; +# else // Big-Endian... + *out = ( ( in & 0x8000 ) >> 15 ) | + ( ( in & 0x4000 ) >> 13 ) | + ( ( in & 0x2000 ) >> 11 ) | + ( ( in & 0x1000 ) >> 9 ) | + ( ( in & 0x0800 ) >> 7 ) | + ( ( in & 0x0400 ) >> 5 ) | + ( ( in & 0x0200 ) >> 3 ) | + ( ( in & 0x0100 ) >> 1 ) | + ( ( in & 0x0080 ) << 1 ) | + ( ( in & 0x0040 ) << 3 ) | + ( ( in & 0x0020 ) << 5 ) | + ( ( in & 0x0010 ) << 7 ) | + ( ( in & 0x0008 ) << 9 ) | + ( ( in & 0x0004 ) << 11 ) | + ( ( in & 0x0002 ) << 13 ) | + ( ( in & 0x0001 ) << 15 ); +# endif // ANI_LITTLE_BIT_ENDIAN +} + +void +swapBitField32(tANI_U32 in, tANI_U32 *out) +{ +# ifdef ANI_LITTLE_BIT_ENDIAN + *out = in; +# else // Big-Endian... + *out = ( ( in & 0x80000000 ) >> 31 ) | + ( ( in & 0x40000000 ) >> 29 ) | + ( ( in & 0x20000000 ) >> 27 ) | + ( ( in & 0x10000000 ) >> 25 ) | + ( ( in & 0x08000000 ) >> 23 ) | + ( ( in & 0x04000000 ) >> 21 ) | + ( ( in & 0x02000000 ) >> 19 ) | + ( ( in & 0x01000000 ) >> 17 ) | + ( ( in & 0x00800000 ) >> 15 ) | + ( ( in & 0x00400000 ) >> 13 ) | + ( ( in & 0x00200000 ) >> 11 ) | + ( ( in & 0x00100000 ) >> 9 ) | + ( ( in & 0x00080000 ) >> 7 ) | + ( ( in & 0x00040000 ) >> 5 ) | + ( ( in & 0x00020000 ) >> 3 ) | + ( ( in & 0x00010000 ) >> 1 ) | + ( ( in & 0x00008000 ) << 1 ) | + ( ( in & 0x00004000 ) << 3 ) | + ( ( in & 0x00002000 ) << 5 ) | + ( ( in & 0x00001000 ) << 7 ) | + ( ( in & 0x00000800 ) << 9 ) | + ( ( in & 0x00000400 ) << 11 ) | + ( ( in & 0x00000200 ) << 13 ) | + ( ( in & 0x00000100 ) << 15 ) | + ( ( in & 0x00000080 ) << 17 ) | + ( ( in & 0x00000040 ) << 19 ) | + ( ( in & 0x00000020 ) << 21 ) | + ( ( in & 0x00000010 ) << 23 ) | + ( ( in & 0x00000008 ) << 25 ) | + ( ( in & 0x00000004 ) << 27 ) | + ( ( in & 0x00000002 ) << 29 ) | + ( ( in & 0x00000001 ) << 31 ); +# endif // ANI_LITTLE_BIT_ENDIAN +} + +inline static void __printWMMParams(tpAniSirGlobal pMac, tDot11fIEWMMParams *pWmm) +{ + limLog(pMac, LOG1, FL("WMM Parameters Received:")); + limLog(pMac, LOG1, + FL("BE: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"), + pWmm->acbe_aifsn, pWmm->acbe_acm, pWmm->acbe_aci, pWmm->acbe_acwmin, + pWmm->acbe_acwmax, pWmm->acbe_txoplimit); + + limLog(pMac, LOG1, + FL("BK: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"), + pWmm->acbk_aifsn, pWmm->acbk_acm, pWmm->acbk_aci, pWmm->acbk_acwmin, + pWmm->acbk_acwmax, pWmm->acbk_txoplimit); + + limLog(pMac, LOG1, + FL("VI: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"), + pWmm->acvi_aifsn, pWmm->acvi_acm, pWmm->acvi_aci, pWmm->acvi_acwmin, + pWmm->acvi_acwmax, pWmm->acvi_txoplimit); + + limLog(pMac, LOG1, + FL("VO: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d"), + pWmm->acvo_aifsn, pWmm->acvo_acm, pWmm->acvo_aci, pWmm->acvo_acwmin, + pWmm->acvo_acwmax, pWmm->acvo_txoplimit); + + return; +} + +//////////////////////////////////////////////////////////////////////// +// Functions for populating "dot11f" style IEs + + +// return: >= 0, the starting location of the IE in rsnIEdata inside tSirRSNie +// < 0, cannot find +int FindIELocation( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tANI_U8 EID) +{ + int idx, ieLen, bytesLeft; + int ret_val = -1; + + // Here's what's going on: 'rsnIe' looks like this: + + // typedef struct sSirRSNie + // { + // tANI_U16 length; + // tANI_U8 rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2]; + // } tSirRSNie, *tpSirRSNie; + + // other code records both the WPA & RSN IEs (including their EIDs & + // lengths) into the array 'rsnIEdata'. We may have: + + // With WAPI support, there may be 3 IEs here + // It can be only WPA IE, or only RSN IE or only WAPI IE + // Or two or all three of them with no particular ordering + + // The if/then/else statements that follow are here to figure out + // whether we have the WPA IE, and where it is if we *do* have it. + + //Save the first IE length + ieLen = pRsnIe->rsnIEdata[ 1 ] + 2; + idx = 0; + bytesLeft = pRsnIe->length; + + while( 1 ) + { + if ( EID == pRsnIe->rsnIEdata[ idx ] ) + { + //Found it + return (idx); + } + else if ( EID != pRsnIe->rsnIEdata[ idx ] && + // & if no more IE, + bytesLeft <= (tANI_U16)( ieLen ) ) + { + dot11fLog(pMac, LOG3, FL("No IE (%d) in FindIELocation."), EID); + return ret_val; + } + bytesLeft -= ieLen; + ieLen = pRsnIe->rsnIEdata[ idx + 1 ] + 2; + idx += ieLen; + } + + return ret_val; +} + + +tSirRetStatus +PopulateDot11fCapabilities(tpAniSirGlobal pMac, + tDot11fFfCapabilities *pDot11f, + tpPESession psessionEntry) +{ + tANI_U16 cfg; + tSirRetStatus nSirStatus; + + nSirStatus = cfgGetCapabilityInfo( pMac, &cfg,psessionEntry ); + if ( eSIR_SUCCESS != nSirStatus ) + { + dot11fLog(pMac, LOGP, + FL("Failed to retrieve the Capabilities bitfield from CFG (%d)"), + nSirStatus); + return nSirStatus; + } + + swapBitField16( cfg, ( tANI_U16* )pDot11f ); + + return eSIR_SUCCESS; +} // End PopulateDot11fCapabilities. + +/** + * populate_dot_11_f_ext_chann_switch_ann() - Function to populate ECS + * @mac_ptr: Pointer to PMAC structure + * @dot_11_ptr: ECS element + * @session_entry: PE session entry + * + * This function is used to populate the extended channel switch element + * + * Return: None + * + */ +void populate_dot_11_f_ext_chann_switch_ann(tpAniSirGlobal mac_ptr, + tDot11fIEext_chan_switch_ann *dot_11_ptr, + tpPESession session_entry) +{ + dot_11_ptr->switch_mode = session_entry->gLimChannelSwitch.switchMode; + dot_11_ptr->new_reg_class = regdm_get_opclass_from_channel( + mac_ptr->scan.countryCodeCurrent, + session_entry->gLimChannelSwitch. + primaryChannel, + session_entry->gLimChannelSwitch. + secondarySubBand); + dot_11_ptr->new_channel = + session_entry->gLimChannelSwitch.primaryChannel; + dot_11_ptr->switch_count = + session_entry->gLimChannelSwitch.switchCount; + dot_11_ptr->present = 1; +} + +void +PopulateDot11fChanSwitchAnn(tpAniSirGlobal pMac, + tDot11fIEChanSwitchAnn *pDot11f, + tpPESession psessionEntry) +{ + pDot11f->switchMode = psessionEntry->gLimChannelSwitch.switchMode; + pDot11f->newChannel = psessionEntry->gLimChannelSwitch.primaryChannel; + pDot11f->switchCount = ( tANI_U8 ) psessionEntry->gLimChannelSwitch.switchCount; + + pDot11f->present = 1; +} // End PopulateDot11fChanSwitchAnn. + +void +populate_dot11_supp_operating_classes(tpAniSirGlobal mac_ptr, + tDot11fIESuppOperatingClasses *dot_11_ptr, + tpPESession session_entry) +{ + uint8_t ch_bandwidth; + + if (session_entry->vhtTxChannelWidthSet == eHT_CHANNEL_WIDTH_80MHZ) + ch_bandwidth = BW80; + else { + switch (session_entry->htSecondaryChannelOffset) { + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + ch_bandwidth = BW40_HIGH_PRIMARY; + break; + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + ch_bandwidth = BW40_LOW_PRIMARY; + break; + default: + ch_bandwidth = BW20; + break; + } + } + + regdm_get_curr_opclasses(&dot_11_ptr->num_classes, + &dot_11_ptr->classes[1]); + dot_11_ptr->classes[0] = regdm_get_opclass_from_channel( + mac_ptr->scan.countryCodeCurrent, + session_entry->currentOperChannel, + ch_bandwidth); + + dot_11_ptr->num_classes++; + dot_11_ptr->present = 1; +} + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +void +populate_dot11f_avoid_channel_ie(tpAniSirGlobal mac_ctx, + tDot11fIEQComVendorIE *dot11f, + tpPESession pe_session) +{ + if (!pe_session->sap_advertise_avoid_ch_ie) + return; + + dot11f->present = true; + dot11f->type = QCOM_VENDOR_IE_MCC_AVOID_CH; + dot11f->channel = pe_session->currentOperChannel; +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +void +PopulateDot11fChanSwitchWrapper(tpAniSirGlobal pMac, + tDot11fIEChannelSwitchWrapper *pDot11f, + tpPESession psessionEntry) +{ + /* + * The new country subelement is present only when + * 1. AP performs Extended Channel switching to new country. + * 2. New Operating Class table or a changed set of operating + * classes relative to the contents of the country element sent + * in the beacons. + * + * In the current scenario Channel Switch wrapper IE is included + * when we a radar is found and the AP does a channel change in + * the same regulatory domain(No country change or Operating class + * table). So, we do not need to include the New Country IE. + * + * Transmit Power Envlope Subelement is optional + * in Channel Switch Wrapper IE. So, not setting + * the TPE subelement. We include only WiderBWChanSwitchAnn. + */ + pDot11f->present = 1; + + /* + * Add the Wide Channel Bandwidth Sublement. + */ + pDot11f->WiderBWChanSwitchAnn.newChanWidth = + psessionEntry->gLimWiderBWChannelSwitch.newChanWidth; + pDot11f->WiderBWChanSwitchAnn.newCenterChanFreq0 = + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0; + pDot11f->WiderBWChanSwitchAnn.newCenterChanFreq1 = + psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1; + pDot11f->WiderBWChanSwitchAnn.present = 1; + +} + +#ifdef WLAN_FEATURE_11AC +void +PopulateDot11fWiderBWChanSwitchAnn(tpAniSirGlobal pMac, + tDot11fIEWiderBWChanSwitchAnn *pDot11f, + tpPESession psessionEntry) +{ + pDot11f->present = 1; + pDot11f->newChanWidth = psessionEntry->gLimWiderBWChannelSwitch.newChanWidth; + pDot11f->newCenterChanFreq0 = psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0; + pDot11f->newCenterChanFreq1 = psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1; +} +#endif + +tSirRetStatus +PopulateDot11fCountry(tpAniSirGlobal pMac, + tDot11fIECountry *pDot11f, + tpPESession psessionEntry) +{ + tANI_U32 len, maxlen, codelen; + tANI_U16 item; + tSirRetStatus nSirStatus; + tSirRFBand rfBand; + tANI_U8 temp[CFG_MAX_STR_LEN], code[3]; + + if (psessionEntry->lim11dEnabled ) + { + limGetRfBand(pMac, &rfBand, psessionEntry); + if (rfBand == SIR_BAND_5_GHZ) + { + item = WNI_CFG_MAX_TX_POWER_5; + maxlen = WNI_CFG_MAX_TX_POWER_5_LEN; + } + else + { + item = WNI_CFG_MAX_TX_POWER_2_4; + maxlen = WNI_CFG_MAX_TX_POWER_2_4_LEN; + } + + CFG_GET_STR( nSirStatus, pMac, item, temp, len, maxlen ); + + if ( 3 > len ) + { + // no limit on tx power, cannot include the IE because at least + // one (channel,num,tx power) must be present + return eSIR_SUCCESS; + } + + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_COUNTRY_CODE, + code, codelen, 3 ); + + vos_mem_copy( pDot11f->country, code, codelen ); + + if(len > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE) + { + dot11fLog(pMac, LOGE, + FL("len:%d is out of bounds, resetting"), len); + len = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE; + } + + pDot11f->num_triplets = ( tANI_U8 ) ( len / 3 ); + vos_mem_copy( ( tANI_U8* )pDot11f->triplets, temp, len ); + + pDot11f->present = 1; + } + + return eSIR_SUCCESS; +} // End PopulateDot11fCountry. + +tSirRetStatus +PopulateDot11fDSParams(tpAniSirGlobal pMac, + tDot11fIEDSParams *pDot11f, tANI_U8 channel, + tpPESession psessionEntry) +{ + if (IS_24G_CH(channel)) { + // .11b/g mode PHY => Include the DS Parameter Set IE: + pDot11f->curr_channel = channel; + pDot11f->present = 1; + } + + return eSIR_SUCCESS; +} // End PopulateDot11fDSParams. + +#define SET_AIFSN(aifsn) (((aifsn) < 2) ? 2 : (aifsn)) + + +void +PopulateDot11fEDCAParamSet(tpAniSirGlobal pMac, + tDot11fIEEDCAParamSet *pDot11f, + tpPESession psessionEntry) +{ + + if ( psessionEntry->limQosEnabled ) + { + //change to bitwise operation, after this is fixed in frames. + pDot11f->qos = (tANI_U8)(0xf0 & (psessionEntry->gLimEdcaParamSetCount << 4) ); + + // Fill each EDCA parameter set in order: be, bk, vi, vo + pDot11f->acbe_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[0].aci.aifsn) ); + pDot11f->acbe_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[0].aci.acm ); + pDot11f->acbe_aci = ( 0x3 & SIR_MAC_EDCAACI_BESTEFFORT ); + pDot11f->acbe_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.min ); + pDot11f->acbe_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.max ); + pDot11f->acbe_txoplimit = psessionEntry->gLimEdcaParamsBC[0].txoplimit; + + pDot11f->acbk_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[1].aci.aifsn) ); + pDot11f->acbk_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[1].aci.acm ); + pDot11f->acbk_aci = ( 0x3 & SIR_MAC_EDCAACI_BACKGROUND ); + pDot11f->acbk_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.min ); + pDot11f->acbk_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.max ); + pDot11f->acbk_txoplimit = psessionEntry->gLimEdcaParamsBC[1].txoplimit; + + pDot11f->acvi_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[2].aci.aifsn) ); + pDot11f->acvi_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[2].aci.acm ); + pDot11f->acvi_aci = ( 0x3 & SIR_MAC_EDCAACI_VIDEO ); + pDot11f->acvi_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.min ); + pDot11f->acvi_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.max ); + pDot11f->acvi_txoplimit = psessionEntry->gLimEdcaParamsBC[2].txoplimit; + + pDot11f->acvo_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[3].aci.aifsn) ); + pDot11f->acvo_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[3].aci.acm ); + pDot11f->acvo_aci = ( 0x3 & SIR_MAC_EDCAACI_VOICE ); + pDot11f->acvo_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.min ); + pDot11f->acvo_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.max ); + pDot11f->acvo_txoplimit = psessionEntry->gLimEdcaParamsBC[3].txoplimit; + + pDot11f->present = 1; + } + +} // End PopluateDot11fEDCAParamSet. + +tSirRetStatus +PopulateDot11fERPInfo(tpAniSirGlobal pMac, + tDot11fIEERPInfo *pDot11f, + tpPESession psessionEntry) +{ + tSirRetStatus nSirStatus; + tANI_U32 val; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + + limGetRfBand(pMac, &rfBand, psessionEntry); + if(SIR_BAND_2_4_GHZ == rfBand) + { + pDot11f->present = 1; + + val = psessionEntry->cfgProtection.fromllb; + if(!val ){ + dot11fLog(pMac, LOGE, + FL("11B protection not enabled. Not populating ERP IE %d"), + val); + return eSIR_SUCCESS; + } + + if (psessionEntry->gLim11bParams.protectionEnabled) + { + pDot11f->non_erp_present = 1; + pDot11f->use_prot = 1; + } + + if ( psessionEntry->gLimOlbcParams.protectionEnabled ) + { + //FIXME_PROTECTION: we should be setting non_erp present also. + //check the test plan first. + pDot11f->use_prot = 1; + } + + + if((psessionEntry->gLimNoShortParams.numNonShortPreambleSta) + || !psessionEntry->beaconParams.fShortPreamble){ + pDot11f->barker_preamble = 1; + + } + // if protection always flag is set, advertise protection enabled + // regardless of legacy stations presence + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_11G_PROTECTION_ALWAYS, val ); + + if ( val ) + { + pDot11f->use_prot = 1; + } + } + + return eSIR_SUCCESS; +} // End PopulateDot11fERPInfo. + +tSirRetStatus +PopulateDot11fExtSuppRates(tpAniSirGlobal pMac, tANI_U8 nChannelNum, + tDot11fIEExtSuppRates *pDot11f, + tpPESession psessionEntry) +{ + tSirRetStatus nSirStatus; + tANI_U32 nRates = 0; + tANI_U8 rates[SIR_MAC_RATESET_EID_MAX]; + + /* Use the ext rates present in session entry whenever nChannelNum is set to OPERATIONAL + else use the ext supported rate set from CFG, which is fixed and does not change dynamically and is used for + sending mgmt frames (lile probe req) which need to go out before any session is present. + */ + if(POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum ) + { + if(psessionEntry != NULL) + { + nRates = psessionEntry->extRateSet.numRates; + vos_mem_copy( rates, psessionEntry->extRateSet.rate, + nRates); + } + else + { + dot11fLog(pMac, LOGE, + FL("no session context exists while populating Operational Rate Set")); + } + } + else if ( HIGHEST_24GHZ_CHANNEL_NUM >= nChannelNum ) + { + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + rates, nRates, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN ); + } + + if ( 0 != nRates ) + { + pDot11f->num_rates = ( tANI_U8 )nRates; + vos_mem_copy( pDot11f->rates, rates, nRates ); + pDot11f->present = 1; + } + + return eSIR_SUCCESS; + +} // End PopulateDot11fExtSuppRates. + +tSirRetStatus +PopulateDot11fExtSuppRates1(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tDot11fIEExtSuppRates *pDot11f) +{ + tANI_U32 nRates; + tSirRetStatus nSirStatus; + tANI_U8 rates[SIR_MAC_MAX_NUMBER_OF_RATES]; + + if ( 14 < nChannelNum ) + { + pDot11f->present = 0; + return eSIR_SUCCESS; + } + + // N.B. I have *no* idea why we're calling 'wlan_cfgGetStr' with an argument + // of WNI_CFG_SUPPORTED_RATES_11A here, but that's what was done + // previously & I'm afraid to change it! + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A, + rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES ); + + if ( 0 != nRates ) + { + pDot11f->num_rates = ( tANI_U8 ) nRates; + vos_mem_copy( pDot11f->rates, rates, nRates ); + pDot11f->present = 1; + } + + return eSIR_SUCCESS; +} // PopulateDot11fExtSuppRates1. + +tSirRetStatus +PopulateDot11fHTCaps(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEHTCaps *pDot11f) +{ + tANI_U32 nCfgValue, nCfgLen; + tANI_U8 nCfgValue8; + tSirRetStatus nSirStatus; + tSirMacHTParametersInfo *pHTParametersInfo; + union { + tANI_U16 nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + tSirMacExtendedHTCapabilityInfo extHtCapInfo; + } uHTCapabilityInfo; + + tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo; + tSirMacASCapabilityInfo *pASCapabilityInfo; + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_CAP_INFO, nCfgValue ); + + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + + pDot11f->mimoPowerSave = uHTCapabilityInfo.htCapInfo.mimoPowerSave; + pDot11f->greenField = uHTCapabilityInfo.htCapInfo.greenField; + pDot11f->delayedBA = uHTCapabilityInfo.htCapInfo.delayedBA; + pDot11f->maximalAMSDUsize = uHTCapabilityInfo.htCapInfo.maximalAMSDUsize; + pDot11f->dsssCckMode40MHz = uHTCapabilityInfo.htCapInfo.dsssCckMode40MHz; + pDot11f->psmp = uHTCapabilityInfo.htCapInfo.psmp; + pDot11f->stbcControlFrame = uHTCapabilityInfo.htCapInfo.stbcControlFrame; + pDot11f->lsigTXOPProtection = uHTCapabilityInfo.htCapInfo.lsigTXOPProtection; + + // All sessionized entries will need the check below + if (psessionEntry == NULL) // Only in case of NO session + { + pDot11f->supportedChannelWidthSet = uHTCapabilityInfo.htCapInfo.supportedChannelWidthSet; + pDot11f->advCodingCap = uHTCapabilityInfo.htCapInfo.advCodingCap; + pDot11f->txSTBC = uHTCapabilityInfo.htCapInfo.txSTBC; + pDot11f->rxSTBC = uHTCapabilityInfo.htCapInfo.rxSTBC; + pDot11f->shortGI20MHz = uHTCapabilityInfo.htCapInfo.shortGI20MHz; + pDot11f->shortGI40MHz = uHTCapabilityInfo.htCapInfo.shortGI40MHz; + } + else + { + pDot11f->advCodingCap = psessionEntry->htConfig.ht_rx_ldpc; + pDot11f->supportedChannelWidthSet = psessionEntry->htSupportedChannelWidthSet; + pDot11f->txSTBC = psessionEntry->htConfig.ht_tx_stbc; + pDot11f->rxSTBC = psessionEntry->htConfig.ht_rx_stbc; + if (psessionEntry->htConfig.ht_sgi) { + pDot11f->shortGI20MHz = + uHTCapabilityInfo.htCapInfo.shortGI20MHz; + pDot11f->shortGI40MHz = + uHTCapabilityInfo.htCapInfo.shortGI40MHz; + } + } + + /* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is + eHT_CHANNEL_WIDTH_20MHZ */ + if(pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) + { + pDot11f->shortGI40MHz = 0; + } + + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_AMPDU_PARAMS, nCfgValue ); + + nCfgValue8 = ( tANI_U8 ) nCfgValue; + pHTParametersInfo = ( tSirMacHTParametersInfo* ) &nCfgValue8; + + pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor; + pDot11f->mpduDensity = pHTParametersInfo->mpduDensity; + pDot11f->reserved1 = pHTParametersInfo->reserved; + + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_MCS_SET, + pDot11f->supportedMCSSet, nCfgLen, + SIZE_OF_SUPPORTED_MCS_SET ); + + if (!pMac->per_band_chainmask_supp) { + if (psessionEntry && (pMac->lteCoexAntShare && + (IS_24G_CH(psessionEntry->currentOperChannel)))) { + if(!(IS_2X2_CHAIN(psessionEntry->chainMask))) { + pDot11f->supportedMCSSet[1] = 0; + if (LIM_IS_STA_ROLE(psessionEntry)) { + pDot11f->mimoPowerSave = psessionEntry->smpsMode; + } + } + } + } else if (psessionEntry && psessionEntry->vdev_nss == NSS_1x1_MODE) { + pDot11f->supportedMCSSet[1] = 0; + } + + /* If STA and mimo power save is enabled include ht smps */ + if (psessionEntry && (!pMac->lteCoexAntShare) && + LIM_IS_STA_ROLE(psessionEntry) && + (psessionEntry->enableHtSmps) && + (!psessionEntry->supported_nss_1x1)) { + limLog(pMac, LOG1, FL("Add SM power save IE :%d"), + psessionEntry->htSmpsvalue); + pDot11f->mimoPowerSave = psessionEntry->htSmpsvalue; + } + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_EXT_HT_CAP_INFO, nCfgValue ); + + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + + pDot11f->pco = uHTCapabilityInfo.extHtCapInfo.pco; + pDot11f->transitionTime = uHTCapabilityInfo.extHtCapInfo.transitionTime; + pDot11f->mcsFeedback = uHTCapabilityInfo.extHtCapInfo.mcsFeedback; + + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_TX_BF_CAP, nCfgValue ); + + pTxBFCapabilityInfo = ( tSirMacTxBFCapabilityInfo* ) &nCfgValue; + pDot11f->txBF = pTxBFCapabilityInfo->txBF; + pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding; + pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding; + pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF; + pDot11f->txZLF = pTxBFCapabilityInfo->txZLF; + pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF; + pDot11f->calibration = pTxBFCapabilityInfo->calibration; + pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF; + pDot11f->explicitUncompressedSteeringMatrix = pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix; + pDot11f->explicitBFCSIFeedback = pTxBFCapabilityInfo->explicitBFCSIFeedback; + pDot11f->explicitUncompressedSteeringMatrixFeedback = pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback; + pDot11f->explicitCompressedSteeringMatrixFeedback = pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback; + pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae; + pDot11f->uncompressedSteeringMatrixBFAntennae = pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae; + pDot11f->compressedSteeringMatrixBFAntennae = pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae; + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_AS_CAP, nCfgValue ); + + nCfgValue8 = ( tANI_U8 ) nCfgValue; + + pASCapabilityInfo = ( tSirMacASCapabilityInfo* ) &nCfgValue8; + pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection; + pDot11f->explicitCSIFeedbackTx = pASCapabilityInfo->explicitCSIFeedbackTx; + pDot11f->antennaIndicesFeedbackTx = pASCapabilityInfo->antennaIndicesFeedbackTx; + pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback; + pDot11f->antennaIndicesFeedback = pASCapabilityInfo->antennaIndicesFeedback; + pDot11f->rxAS = pASCapabilityInfo->rxAS; + pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs; + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} // End PopulateDot11fHTCaps. +#ifdef WLAN_FEATURE_11AC + +void limLogVHTCap(tpAniSirGlobal pMac, + tDot11fIEVHTCaps *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + limLog(pMac, LOG1, FL("maxMPDULen (2): %d"), pDot11f->maxMPDULen); + limLog(pMac, LOG1, FL("supportedChannelWidthSet (2): %d"), + pDot11f->supportedChannelWidthSet); + limLog(pMac, LOG1, FL("ldpcCodingCap (1): %d"), pDot11f->ldpcCodingCap); + limLog(pMac, LOG1, FL("shortGI80MHz (1): %d"), pDot11f->shortGI80MHz); + limLog(pMac, LOG1, FL("shortGI160and80plus80MHz (1): %d"), + pDot11f->shortGI160and80plus80MHz); + limLog(pMac, LOG1, FL("txSTBC (1): %d"), pDot11f->txSTBC); + limLog(pMac, LOG1, FL("rxSTBC (3): %d"), pDot11f->rxSTBC); + limLog(pMac, LOG1, FL("suBeamFormerCap (1): %d"), pDot11f->suBeamFormerCap); + limLog(pMac, LOG1, FL("suBeamformeeCap (1): %d"), pDot11f->suBeamformeeCap); + limLog(pMac, LOG1, FL("csnofBeamformerAntSup (3): %d"), + pDot11f->csnofBeamformerAntSup); + limLog(pMac, LOG1, FL("numSoundingDim (3): %d"), pDot11f->numSoundingDim); + limLog(pMac, LOG1, FL("muBeamformerCap (1): %d"), pDot11f->muBeamformerCap); + limLog(pMac, LOG1, FL("muBeamformeeCap (1): %d"), pDot11f->muBeamformeeCap); + limLog(pMac, LOG1, FL("vhtTXOPPS (1): %d"), pDot11f->vhtTXOPPS); + limLog(pMac, LOG1, FL("htcVHTCap (1): %d"), pDot11f->htcVHTCap); + limLog(pMac, LOG1, FL("maxAMPDULenExp (3): %d"), pDot11f->maxAMPDULenExp); + limLog(pMac, LOG1, FL("vhtLinkAdaptCap (2): %d"), pDot11f->vhtLinkAdaptCap); + limLog(pMac, LOG1, FL("rxAntPattern (1): %d"), pDot11f->vhtLinkAdaptCap); + limLog(pMac, LOG1, FL("txAntPattern (1): %d"), pDot11f->vhtLinkAdaptCap); + limLog(pMac, LOG1, FL("reserved1 (2): %d"), pDot11f->reserved1); + limLog(pMac, LOG1, FL("rxMCSMap (16): %d"), pDot11f->rxMCSMap); + limLog(pMac, LOG1, FL("rxHighSupDataRate (13): %d"), + pDot11f->rxHighSupDataRate); + limLog(pMac, LOG1, FL("reserve (3): %d"), pDot11f->reserved2); + limLog(pMac, LOG1, FL("txMCSMap (16): %d"), pDot11f->txMCSMap); + limLog(pMac, LOG1, FL("txSupDataRate (13): %d"), pDot11f->txSupDataRate); + limLog(pMac, LOG1, FL("reserv (3): %d"), pDot11f->reserved3); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void limLogVHTOperation(tpAniSirGlobal pMac, + tDot11fIEVHTOperation *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + limLog(pMac, LOG1, FL("chanWidth : %d"), pDot11f->chanWidth); + limLog(pMac, LOG1, FL("chanCenterFreqSeg1: %d"), + pDot11f->chanCenterFreqSeg1); + limLog(pMac, LOG1, FL("chanCenterFreqSeg2: %d"), + pDot11f->chanCenterFreqSeg2); + limLog(pMac, LOG1, FL("basicMCSSet: %d"), pDot11f->basicMCSSet); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void limLogVHTExtBssLoad(tpAniSirGlobal pMac, + tDot11fIEVHTExtBssLoad *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + limLog(pMac, LOG1, FL("muMIMOCapStaCount : %d"), + pDot11f->muMIMOCapStaCount); + limLog(pMac, LOG1, FL("ssUnderUtil: %d"), pDot11f->ssUnderUtil); + limLog(pMac, LOG1, FL("FortyMHzUtil: %d"), pDot11f->FortyMHzUtil); + limLog(pMac, LOG1, FL("EightyMHzUtil: %d"), pDot11f->EightyMHzUtil); + limLog(pMac, LOG1, FL("OneSixtyMHzUtil: %d"), pDot11f->OneSixtyMHzUtil); +#endif /* DUMP_MGMT_CNTNTS */ +} + + +void limLogOperatingMode( tpAniSirGlobal pMac, + tDot11fIEOperatingMode *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + limLog(pMac, LOG1, FL("ChanWidth : %d"), pDot11f->chanWidth); + limLog(pMac, LOG1, FL("reserved: %d"), pDot11f->reserved); + limLog(pMac, LOG1, FL("rxNSS: %d"), pDot11f->rxNSS); + limLog(pMac, LOG1, FL("rxNSS Type: %d"), pDot11f->rxNSSType); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void limLogQosMapSet(tpAniSirGlobal pMac, tSirQosMapSet *pQosMapSet) +{ + tANI_U8 i; + if (pQosMapSet->num_dscp_exceptions > 21) + pQosMapSet->num_dscp_exceptions = 21; + limLog(pMac, LOG1, FL("num of dscp exceptions : %d"), + pQosMapSet->num_dscp_exceptions); + for (i = 0; i < pQosMapSet->num_dscp_exceptions; i++) + { + limLog(pMac, LOG1, FL("dscp value: %d"), + pQosMapSet->dscp_exceptions[i][0]); + limLog(pMac, LOG1, FL("User priority value: %d"), + pQosMapSet->dscp_exceptions[i][1]); + } + for (i = 0; i < 8; i++) + { + limLog(pMac, LOG1, FL("dscp low for up %d: %d"),i, + pQosMapSet->dscp_range[i][0]); + limLog(pMac, LOG1, FL("dscp high for up %d: %d"),i, + pQosMapSet->dscp_range[i][1]); + } +} + +tSirRetStatus +PopulateDot11fVHTCaps(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pDot11f) +{ + tSirRetStatus nStatus; + tANI_U32 nCfgValue=0; + + pDot11f->present = 1; + + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MAX_MPDU_LENGTH, nCfgValue ); + pDot11f->maxMPDULen = (nCfgValue & 0x0003); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, + nCfgValue ); + pDot11f->supportedChannelWidthSet = (nCfgValue & 0x0003); + + nCfgValue = 0; + //With VHT it suffices if we just examine HT + if (psessionEntry) + { + if (psessionEntry->htConfig.ht_rx_ldpc) + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_LDPC_CODING_CAP, + nCfgValue ); + + pDot11f->ldpcCodingCap = (nCfgValue & 0x0001); + + if (psessionEntry->vhtTxChannelWidthSet < + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + pDot11f->shortGI80MHz = 0; + } else { + nCfgValue = 0; + if (psessionEntry->htConfig.ht_sgi) + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SHORT_GI_80MHZ, + nCfgValue ); + + pDot11f->shortGI80MHz= (nCfgValue & 0x0001); + } + + if (psessionEntry->vhtTxChannelWidthSet < + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { + pDot11f->shortGI160and80plus80MHz = 0; + } else { + nCfgValue = 0; + if (psessionEntry->htConfig.ht_sgi) + CFG_GET_INT( nStatus, pMac, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + nCfgValue ); + + pDot11f->shortGI160and80plus80MHz = (nCfgValue & 0x0001); + } + + nCfgValue = 0; + if (psessionEntry->htConfig.ht_tx_stbc) + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TXSTBC, nCfgValue ); + + pDot11f->txSTBC = (nCfgValue & 0x0001); + + nCfgValue = 0; + if (psessionEntry->htConfig.ht_rx_stbc) + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RXSTBC, nCfgValue ); + + pDot11f->rxSTBC = (nCfgValue & 0x0007); + + pDot11f->suBeamformeeCap = psessionEntry->txBFIniFeatureEnabled; + if (psessionEntry->txBFIniFeatureEnabled) { + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + nCfgValue ); + pDot11f->muBeamformeeCap = (nCfgValue & 0x0001); + } else { + pDot11f->muBeamformeeCap = 0; + } + } + else + { + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_LDPC_CODING_CAP, nCfgValue ); + pDot11f->ldpcCodingCap = (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SHORT_GI_80MHZ, nCfgValue ); + pDot11f->shortGI80MHz= (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + nCfgValue ); + pDot11f->shortGI160and80plus80MHz = (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TXSTBC, nCfgValue ); + pDot11f->txSTBC = (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RXSTBC, nCfgValue ); + pDot11f->rxSTBC = (nCfgValue & 0x0007); + + pDot11f->suBeamformeeCap = 0; + pDot11f->muBeamformeeCap = 0; + } + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SU_BEAMFORMER_CAP, nCfgValue ); + pDot11f->suBeamFormerCap = (nCfgValue & 0x0001); + + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, + nCfgValue ); + pDot11f->csnofBeamformerAntSup = (nCfgValue & 0x0007); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS, + nCfgValue ); + pDot11f->numSoundingDim = (nCfgValue & 0x0007); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MU_BEAMFORMER_CAP, nCfgValue ); + pDot11f->muBeamformerCap = (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TXOP_PS, nCfgValue ); + pDot11f->vhtTXOPPS = (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_HTC_VHTC_CAP, nCfgValue ); + pDot11f->htcVHTCap = (nCfgValue & 0x0001); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, nCfgValue ); + pDot11f->maxAMPDULenExp = (nCfgValue & 0x0007); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_LINK_ADAPTATION_CAP, nCfgValue ); + pDot11f->vhtLinkAdaptCap = (nCfgValue & 0x0003); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RX_ANT_PATTERN, nCfgValue ); + pDot11f->rxAntPattern = nCfgValue; + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TX_ANT_PATTERN, nCfgValue ); + pDot11f->txAntPattern = nCfgValue; + + pDot11f->reserved1= 0; + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RX_MCS_MAP, nCfgValue ); + pDot11f->rxMCSMap = (nCfgValue & 0x0000FFFF); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + nCfgValue ); + pDot11f->rxHighSupDataRate = (nCfgValue & 0x00001FFF); + + pDot11f->reserved2= 0; + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TX_MCS_MAP, nCfgValue ); + pDot11f->txMCSMap = (nCfgValue & 0x0000FFFF); + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + nCfgValue ); + pDot11f->txSupDataRate = (nCfgValue & 0x00001FFF); + + pDot11f->reserved3= 0; + + if (!pMac->per_band_chainmask_supp) { + if (psessionEntry) { + if (pMac->lteCoexAntShare && + (IS_24G_CH(psessionEntry->currentOperChannel))) { + if(!(IS_2X2_CHAIN(psessionEntry->chainMask))) { + pDot11f->txMCSMap |= DISABLE_NSS2_MCS; + pDot11f->rxMCSMap |= DISABLE_NSS2_MCS; + } + } + } + } else { + if (psessionEntry && psessionEntry->vdev_nss == NSS_1x1_MODE) { + pDot11f->txMCSMap |= DISABLE_NSS2_MCS; + pDot11f->rxMCSMap |= DISABLE_NSS2_MCS; + pDot11f->txSupDataRate = + VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + pDot11f->rxHighSupDataRate = + VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } + } + limLogVHTCap(pMac, pDot11f); + + return eSIR_SUCCESS; +} + +tSirRetStatus +PopulateDot11fVHTOperation(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEVHTOperation *pDot11f) +{ + tSirRetStatus nStatus; + tANI_U32 nCfgValue=0; + + pDot11f->present = 1; + + if (psessionEntry->htSupportedChannelWidthSet) { + pDot11f->chanWidth = psessionEntry->vhtTxChannelWidthSet; + pDot11f->chanCenterFreqSeg1 = psessionEntry->apCenterChan; + } else { + pDot11f->chanWidth = 0; + } + + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2, + nCfgValue ); + pDot11f->chanCenterFreqSeg2 = (tANI_U8)nCfgValue; + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_BASIC_MCS_SET,nCfgValue ); + pDot11f->basicMCSSet = (tANI_U16)nCfgValue; + + limLogVHTOperation(pMac,pDot11f); + + return eSIR_SUCCESS; + +} + +tSirRetStatus +PopulateDot11fVHTExtBssLoad(tpAniSirGlobal pMac, + tDot11fIEVHTExtBssLoad *pDot11f) +{ + tSirRetStatus nStatus; + tANI_U32 nCfgValue=0; + + pDot11f->present = 1; + + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT, + nCfgValue ); + pDot11f->muMIMOCapStaCount = (tANI_U8)nCfgValue; + + nCfgValue = 0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_SS_UNDER_UTIL,nCfgValue ); + pDot11f->ssUnderUtil = (tANI_U8)nCfgValue; + + nCfgValue=0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_40MHZ_UTILIZATION,nCfgValue ); + pDot11f->FortyMHzUtil = (tANI_U8)nCfgValue; + + nCfgValue=0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_80MHZ_UTILIZATION,nCfgValue ); + pDot11f->EightyMHzUtil = (tANI_U8)nCfgValue; + + nCfgValue=0; + CFG_GET_INT( nStatus, pMac, WNI_CFG_VHT_160MHZ_UTILIZATION,nCfgValue ); + pDot11f->EightyMHzUtil = (tANI_U8)nCfgValue; + + limLogVHTExtBssLoad(pMac,pDot11f); + + return eSIR_SUCCESS; +} + +tSirRetStatus +PopulateDot11fExtCap(tpAniSirGlobal pMac, + tANI_BOOLEAN isVHTEnabled, + tDot11fIEExtCap *pDot11f, tpPESession psessionEntry) +{ + tANI_U32 val=0; + struct s_ext_cap *p_ext_cap; + + pDot11f->present = 1; + + if (!psessionEntry) { + limLog(pMac, LOG1, FL("11MC support enabled for non-SAP cases")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + } else if (psessionEntry->sap_dot11mc) { + limLog(pMac, LOG1, FL("11MC support enabled")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + } else { + if (eLIM_AP_ROLE != psessionEntry->limSystemRole) { + limLog(pMac, LOG1, FL("11MC support enabled")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + } else { + limLog(pMac, LOG1, FL("11MC support disabled")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MIN_LEN; + } + } + + p_ext_cap = (struct s_ext_cap *)pDot11f->bytes; +#ifdef WLAN_FEATURE_11AC + if (isVHTEnabled == eANI_BOOLEAN_TRUE) + { + p_ext_cap->operModeNotification = 1; + } +#endif + + if (wlan_cfgGetInt(pMac, WNI_CFG_RTT3_ENABLE, &val) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, + FL("could not retrieve RTT3 Variable from DAT File"));) + return eSIR_FAILURE; + } + + if (val) // If set to true then set RTTv3 + { + if (!psessionEntry || LIM_IS_STA_ROLE(psessionEntry)) { + p_ext_cap->fine_time_meas_initiator = + (pMac->fine_time_meas_cap & FINE_TIME_MEAS_STA_INITIATOR) ? 1 : 0; + p_ext_cap->fine_time_meas_responder = + (pMac->fine_time_meas_cap & FINE_TIME_MEAS_STA_RESPONDER) ? 1 : 0; + } else if (LIM_IS_AP_ROLE(psessionEntry)) { + p_ext_cap->fine_time_meas_initiator = + (pMac->fine_time_meas_cap & FINE_TIME_MEAS_SAP_INITIATOR) ? 1 : 0; + p_ext_cap->fine_time_meas_responder = + (pMac->fine_time_meas_cap & FINE_TIME_MEAS_SAP_RESPONDER) ? 1 : 0; + } + } + +#ifdef QCA_HT_2040_COEX + if (pMac->roam.configParam.obssEnabled) + { + p_ext_cap->bssCoexistMgmtSupport = 1; + } +#endif + p_ext_cap->extChanSwitch = 1; + + return eSIR_SUCCESS; +} + +tSirRetStatus +PopulateDot11fOperatingMode(tpAniSirGlobal pMac, + tDot11fIEOperatingMode *pDot11f, + tpPESession psessionEntry) +{ + pDot11f->present = 1; + + pDot11f->chanWidth = psessionEntry->gLimOperatingMode.chanWidth; + pDot11f->rxNSS = psessionEntry->gLimOperatingMode.rxNSS; + pDot11f->rxNSSType = psessionEntry->gLimOperatingMode.rxNSSType; + + return eSIR_SUCCESS; +} + +#endif +tSirRetStatus +PopulateDot11fHTInfo(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pDot11f, + tpPESession psessionEntry ) +{ + tANI_U32 nCfgValue, nCfgLen; + tANI_U8 htInfoField1; + tANI_U16 htInfoField2; + tSirRetStatus nSirStatus; + tSirMacHTInfoField1 *pHTInfoField1; + tSirMacHTInfoField2 *pHTInfoField2; + union { + tANI_U16 nCfgValue16; + tSirMacHTInfoField3 infoField3; + }uHTInfoField; + union { + tANI_U16 nCfgValue16; + tSirMacHTInfoField2 infoField2; + }uHTInfoField2={0}; + + + #if 0 + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_CURRENT_CHANNEL, nCfgValue ); + #endif // TO SUPPORT BT-AMP + + if (NULL == psessionEntry) + { + PELOGE(limLog(pMac, LOG1, + FL("Invalid session entry in PopulateDot11fHTInfo()"));) + return eSIR_FAILURE; + } + + pDot11f->primaryChannel = psessionEntry->currentOperChannel; + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD1, nCfgValue ); + + htInfoField1 = ( tANI_U8 ) nCfgValue; + + pHTInfoField1 = ( tSirMacHTInfoField1* ) &htInfoField1; + pHTInfoField1->rifsMode = psessionEntry->beaconParams.fRIFSMode; + pHTInfoField1->serviceIntervalGranularity = pMac->lim.gHTServiceIntervalGranularity; + + if (psessionEntry == NULL) + { + PELOGE(limLog(pMac, LOG1, + FL("Keep the value retrieved from cfg for secondary channel offset and recommended Tx Width set"));) + } + else + { + pHTInfoField1->secondaryChannelOffset = psessionEntry->htSecondaryChannelOffset; + pHTInfoField1->recommendedTxWidthSet = psessionEntry->htRecommendedTxWidthSet; + } + + if (psessionEntry && LIM_IS_AP_ROLE(psessionEntry)) { + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD2, nCfgValue ); + + /* This is added for fixing CRs on MDM9K platform - 257951, 259577 */ + uHTInfoField2.nCfgValue16 = nCfgValue & 0xFFFF; + + uHTInfoField2.infoField2.opMode = psessionEntry->htOperMode; + uHTInfoField2.infoField2.nonGFDevicesPresent = + psessionEntry->beaconParams.llnNonGFCoexist; + /* Added for Obss */ + uHTInfoField2.infoField2.obssNonHTStaPresent = + psessionEntry->beaconParams.gHTObssMode; + + uHTInfoField2.infoField2.reserved = 0; + } else { + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD2, nCfgValue ); + + htInfoField2 = ( tANI_U16 ) nCfgValue; + + pHTInfoField2 = ( tSirMacHTInfoField2* ) &htInfoField2; + pHTInfoField2->opMode = pMac->lim.gHTOperMode; + pHTInfoField2->nonGFDevicesPresent = pMac->lim.gHTNonGFDevicesPresent; + + /* Added for Obss */ + pHTInfoField2->obssNonHTStaPresent = pMac->lim.gHTObssMode; + + pHTInfoField2->reserved = 0; + } + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD3, nCfgValue ); + + + uHTInfoField.nCfgValue16 = nCfgValue & 0xFFFF; + + + uHTInfoField.infoField3.basicSTBCMCS = pMac->lim.gHTSTBCBasicMCS; + uHTInfoField.infoField3.dualCTSProtection = pMac->lim.gHTDualCTSProtection; + uHTInfoField.infoField3.secondaryBeacon = pMac->lim.gHTSecondaryBeacon; + uHTInfoField.infoField3.lsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport; + uHTInfoField.infoField3.pcoActive = pMac->lim.gHTPCOActive; + uHTInfoField.infoField3.pcoPhase = pMac->lim.gHTPCOPhase; + uHTInfoField.infoField3.reserved = 0; + + + pDot11f->secondaryChannelOffset = pHTInfoField1->secondaryChannelOffset; + pDot11f->recommendedTxWidthSet = pHTInfoField1->recommendedTxWidthSet; + pDot11f->rifsMode = pHTInfoField1->rifsMode; + pDot11f->controlledAccessOnly = pHTInfoField1->controlledAccessOnly; + pDot11f->serviceIntervalGranularity = pHTInfoField1->serviceIntervalGranularity; + + pDot11f->opMode = uHTInfoField2.infoField2.opMode; + pDot11f->nonGFDevicesPresent = uHTInfoField2.infoField2.nonGFDevicesPresent; + pDot11f->obssNonHTStaPresent = uHTInfoField2.infoField2.obssNonHTStaPresent; + pDot11f->reserved = uHTInfoField2.infoField2.reserved; + + + pDot11f->basicSTBCMCS = uHTInfoField.infoField3.basicSTBCMCS; + pDot11f->dualCTSProtection = uHTInfoField.infoField3.dualCTSProtection; + pDot11f->secondaryBeacon = uHTInfoField.infoField3.secondaryBeacon; + pDot11f->lsigTXOPProtectionFullSupport = uHTInfoField.infoField3.lsigTXOPProtectionFullSupport; + pDot11f->pcoActive = uHTInfoField.infoField3.pcoActive; + pDot11f->pcoPhase = uHTInfoField.infoField3.pcoPhase; + pDot11f->reserved2 = uHTInfoField.infoField3.reserved; + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_BASIC_MCS_SET, + pDot11f->basicMCSSet, nCfgLen, + SIZE_OF_BASIC_MCS_SET ); + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} // End PopulateDot11fHTInfo. + +void +PopulateDot11fIBSSParams(tpAniSirGlobal pMac, + tDot11fIEIBSSParams *pDot11f, tpPESession psessionEntry) +{ + tANI_U32 val = 0; + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + if(wlan_cfgGetInt(pMac, + WNI_CFG_IBSS_ATIM_WIN_SIZE, &val) != eSIR_SUCCESS) + { + PELOGE(limLog(pMac, LOGE, + FL("could not retrieve IBSS ATIM WIN size"));) + } + pDot11f->present = 1; + // ATIM duration is always set to 0 + pDot11f->atim = val; + } + +} // End PopulateDot11fIBSSParams. + + + +void +PopulateDot11fPowerCaps(tpAniSirGlobal pMac, + tDot11fIEPowerCaps *pCaps, + tANI_U8 nAssocType, + tpPESession psessionEntry) +{ + if (nAssocType == LIM_REASSOC) + { + pCaps->minTxPower = psessionEntry->pLimReAssocReq->powerCap.minTxPower; + pCaps->maxTxPower = psessionEntry->pLimReAssocReq->powerCap.maxTxPower; + }else + { + pCaps->minTxPower = psessionEntry->pLimJoinReq->powerCap.minTxPower; + pCaps->maxTxPower = psessionEntry->pLimJoinReq->powerCap.maxTxPower; + + } + + pCaps->present = 1; +} // End PopulateDot11fPowerCaps. + +tSirRetStatus +PopulateDot11fPowerConstraints(tpAniSirGlobal pMac, + tDot11fIEPowerConstraints *pDot11f) +{ + tANI_U32 cfg; + tSirRetStatus nSirStatus; + + CFG_GET_INT( nSirStatus, pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, cfg ); + + pDot11f->localPowerConstraints = ( tANI_U8 )cfg; + pDot11f->present = 1; + + return eSIR_SUCCESS; +} // End PopulateDot11fPowerConstraints. + +void +PopulateDot11fQOSCapsAp(tpAniSirGlobal pMac, + tDot11fIEQOSCapsAp *pDot11f, tpPESession psessionEntry) +{ + pDot11f->count = psessionEntry->gLimEdcaParamSetCount; + pDot11f->reserved = 0; + pDot11f->txopreq = 0; + pDot11f->qreq = 0; + pDot11f->qack = 0; + pDot11f->present = 1; +} // End PopulatedDot11fQOSCaps. + +void +PopulateDot11fQOSCapsStation(tpAniSirGlobal pMac, + tDot11fIEQOSCapsStation *pDot11f) +{ + tANI_U32 val = 0; + + if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max SP Length"));) + + pDot11f->more_data_ack = 0; + pDot11f->max_sp_length = (tANI_U8)val; + pDot11f->qack = 0; + + if (pMac->lim.gUapsdEnable) + { + pDot11f->acbe_uapsd = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); + pDot11f->acbk_uapsd = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); + pDot11f->acvi_uapsd = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); + pDot11f->acvo_uapsd = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); + } + pDot11f->present = 1; +} // End PopulatedDot11fQOSCaps. + +tSirRetStatus +PopulateDot11fRSN(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIERSN *pDot11f) +{ + tANI_U32 status; + int idx; + + if ( pRsnIe->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_RSN ) ) ) + { + status = dot11fUnpackIeRSN( pMac, + pRsnIe->rsnIEdata + idx + 2, //EID, length + pRsnIe->rsnIEdata[ idx + 1 ], + pDot11f ); + if ( DOT11F_FAILED( status ) ) + { + dot11fLog(pMac, LOGE, + FL("Parse failure in PopulateDot11fRSN (0x%08x)"), + status); + return eSIR_FAILURE; + } + dot11fLog(pMac, LOG2, + FL("dot11fUnpackIeRSN returned 0x%08x in PopulateDot11fRSN"), + status); + } + + } + + return eSIR_SUCCESS; +} // End PopulateDot11fRSN. + +tSirRetStatus PopulateDot11fRSNOpaque( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIERSNOpaque *pDot11f ) +{ + int idx; + + if ( pRsnIe->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_RSN ) ) ) + { + pDot11f->present = 1; + pDot11f->num_data = pRsnIe->rsnIEdata[ idx + 1 ]; + vos_mem_copy( pDot11f->data, + pRsnIe->rsnIEdata + idx + 2, // EID, len + pRsnIe->rsnIEdata[ idx + 1 ] ); + } + } + + return eSIR_SUCCESS; + +} // End PopulateDot11fRSNOpaque. + + + +#if defined(FEATURE_WLAN_WAPI) + +tSirRetStatus +PopulateDot11fWAPI(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWAPI *pDot11f) + { + tANI_U32 status; + int idx; + + if ( pRsnIe->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WAPI ) ) ) + { + status = dot11fUnpackIeWAPI( pMac, + pRsnIe->rsnIEdata + idx + 2, //EID, length + pRsnIe->rsnIEdata[ idx + 1 ], + pDot11f ); + if ( DOT11F_FAILED( status ) ) + { + dot11fLog(pMac, LOGE, + FL("Parse failure in PopulateDot11fWAPI (0x%08x)"), + status); + return eSIR_FAILURE; + } + dot11fLog(pMac, LOG2, + FL("dot11fUnpackIeRSN returned 0x%08x in %s"), + status, __func__); + } + } + + return eSIR_SUCCESS; +} // End PopulateDot11fWAPI. + +tSirRetStatus PopulateDot11fWAPIOpaque( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWAPIOpaque *pDot11f ) +{ + int idx; + + if ( pRsnIe->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WAPI ) ) ) + { + pDot11f->present = 1; + pDot11f->num_data = pRsnIe->rsnIEdata[ idx + 1 ]; + vos_mem_copy ( pDot11f->data, + pRsnIe->rsnIEdata + idx + 2, // EID, len + pRsnIe->rsnIEdata[ idx + 1 ] ); + } + } + + return eSIR_SUCCESS; + +} // End PopulateDot11fWAPIOpaque. + + +#endif //defined(FEATURE_WLAN_WAPI) + +void +PopulateDot11fSSID(tpAniSirGlobal pMac, + tSirMacSSid *pInternal, + tDot11fIESSID *pDot11f) +{ + pDot11f->present = 1; + pDot11f->num_ssid = pInternal->length; + if ( pInternal->length ) + { + vos_mem_copy( ( tANI_U8* )pDot11f->ssid, ( tANI_U8* )&pInternal->ssId, + pInternal->length ); + } +} // End PopulateDot11fSSID. + +tSirRetStatus +PopulateDot11fSSID2(tpAniSirGlobal pMac, + tDot11fIESSID *pDot11f) +{ + tANI_U32 nCfg; + tSirRetStatus nSirStatus; + + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SSID, pDot11f->ssid, nCfg, 32 ); + pDot11f->num_ssid = ( tANI_U8 )nCfg; + pDot11f->present = 1; + return eSIR_SUCCESS; +} // End PopulateDot11fSSID2. + +void +PopulateDot11fSchedule(tSirMacScheduleIE *pSchedule, + tDot11fIESchedule *pDot11f) +{ + pDot11f->aggregation = pSchedule->info.aggregation; + pDot11f->tsid = pSchedule->info.tsid; + pDot11f->direction = pSchedule->info.direction; + pDot11f->reserved = pSchedule->info.rsvd; + pDot11f->service_start_time = pSchedule->svcStartTime; + pDot11f->service_interval = pSchedule->svcInterval; + pDot11f->max_service_dur = pSchedule->maxSvcDuration; + pDot11f->spec_interval = pSchedule->specInterval; + + pDot11f->present = 1; +} // End PopulateDot11fSchedule. + +void +PopulateDot11fSuppChannels(tpAniSirGlobal pMac, + tDot11fIESuppChannels *pDot11f, + tANI_U8 nAssocType, + tpPESession psessionEntry) +{ + tANI_U8 i; + tANI_U8 *p; + + if (nAssocType == LIM_REASSOC) + { + p = ( tANI_U8* )psessionEntry->pLimReAssocReq->supportedChannels.channelList; + pDot11f->num_bands = psessionEntry->pLimReAssocReq->supportedChannels.numChnl; + }else + { + p = ( tANI_U8* )psessionEntry->pLimJoinReq->supportedChannels.channelList; + pDot11f->num_bands = psessionEntry->pLimJoinReq->supportedChannels.numChnl; + } + for ( i = 0U; i < pDot11f->num_bands; ++i, ++p) + { + pDot11f->bands[i][0] = *p; + pDot11f->bands[i][1] = 1; + } + + pDot11f->present = 1; + +} // End PopulateDot11fSuppChannels. + +tSirRetStatus +PopulateDot11fSuppRates(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tDot11fIESuppRates *pDot11f,tpPESession psessionEntry) +{ + tSirRetStatus nSirStatus; + tANI_U32 nRates; + tANI_U8 rates[SIR_MAC_MAX_NUMBER_OF_RATES]; + + /* Use the operational rates present in session entry whenever nChannelNum is set to OPERATIONAL + else use the supported rate set from CFG, which is fixed and does not change dynamically and is used for + sending mgmt frames (lile probe req) which need to go out before any session is present. + */ + if(POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum ) + { + #if 0 + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_OPERATIONAL_RATE_SET, + rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES ); + #endif //TO SUPPORT BT-AMP + if(psessionEntry != NULL) + { + nRates = psessionEntry->rateSet.numRates; + vos_mem_copy( rates, psessionEntry->rateSet.rate, + nRates); + } + else + { + dot11fLog(pMac, LOGE, + FL("no session context exists while populating Operational Rate Set")); + nRates = 0; + } + } + else if ( 14 >= nChannelNum ) + { + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11B, + rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES ); + } + else + { + CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A, + rates, nRates, SIR_MAC_MAX_NUMBER_OF_RATES ); + } + + if ( 0 != nRates ) + { + pDot11f->num_rates = ( tANI_U8 )nRates; + vos_mem_copy( pDot11f->rates, rates, nRates ); + pDot11f->present = 1; + } + + return eSIR_SUCCESS; + +} // End PopulateDot11fSuppRates. + +/** + * populate_dot11f_rates_tdls() - populate supported rates and + * extended supported rates IE. + * @p_mac gloabl - header. + * @p_supp_rates - pointer to supported rates IE + * @p_ext_supp_rates - pointer to extended supported rates IE + * + * This function populates the supported rates and extended supported + * rates IE based in the STA capability. If the number of rates + * supported is less than MAX_NUM_SUPPORTED_RATES, only supported rates + * IE is populated. + * + * Return: tSirRetStatus eSIR_SUCCESS on Success and eSIR_FAILURE + * on failure. + */ + +tSirRetStatus +populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, + tDot11fIESuppRates *p_supp_rates, + tDot11fIEExtSuppRates *p_ext_supp_rates) +{ + tSirMacRateSet temp_rateset; + tSirMacRateSet temp_rateset2; + uint32_t val, i; + uint32_t self_dot11mode = 0; + + wlan_cfgGetInt(p_mac, WNI_CFG_DOT11_MODE, &self_dot11mode); + + /** + * Include 11b rates only when the device configured in + * auto, 11a/b/g or 11b_only + */ + if ((self_dot11mode == WNI_CFG_DOT11_MODE_ALL) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11A) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11AC) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11N) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11G) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11B) ) { + val = WNI_CFG_SUPPORTED_RATES_11B_LEN; + wlan_cfgGetStr(p_mac, WNI_CFG_SUPPORTED_RATES_11B, + (tANI_U8 *)&temp_rateset.rate, &val); + temp_rateset.numRates = (tANI_U8) val; + } + else { + temp_rateset.numRates = 0; + } + + /* Include 11a rates when the device configured in non-11b mode */ + if (!IS_DOT11_MODE_11B(self_dot11mode)) { + val = WNI_CFG_SUPPORTED_RATES_11A_LEN; + wlan_cfgGetStr(p_mac, WNI_CFG_SUPPORTED_RATES_11A, + (tANI_U8 *)&temp_rateset2.rate, &val); + temp_rateset2.numRates = (tANI_U8) val; + } else { + temp_rateset2.numRates = 0; + } + + if ((temp_rateset.numRates + temp_rateset2.numRates) > + SIR_MAC_MAX_NUMBER_OF_RATES) { + limLog(p_mac, LOGP, FL("more than %d rates in CFG"), + SIR_MAC_MAX_NUMBER_OF_RATES); + return eSIR_FAILURE; + } + + /** + * copy all rates in temp_rateset, + * there are SIR_MAC_MAX_NUMBER_OF_RATES rates max + */ + for (i = 0; i < temp_rateset2.numRates; i++) + temp_rateset.rate[i + temp_rateset.numRates] = + temp_rateset2.rate[i]; + + temp_rateset.numRates += temp_rateset2.numRates; + + if (temp_rateset.numRates <= MAX_NUM_SUPPORTED_RATES) { + p_supp_rates->num_rates = temp_rateset.numRates; + vos_mem_copy(p_supp_rates->rates, temp_rateset.rate, + p_supp_rates->num_rates); + p_supp_rates->present = 1; + } else { /* Populate extended capability as well */ + p_supp_rates->num_rates = MAX_NUM_SUPPORTED_RATES; + vos_mem_copy(p_supp_rates->rates, temp_rateset.rate, + p_supp_rates->num_rates); + p_supp_rates->present = 1; + + p_ext_supp_rates->num_rates = temp_rateset.numRates - + MAX_NUM_SUPPORTED_RATES; + vos_mem_copy(p_ext_supp_rates->rates, + (tANI_U8 *)temp_rateset.rate + + MAX_NUM_SUPPORTED_RATES, + p_ext_supp_rates->num_rates); + p_ext_supp_rates->present = 1; + } + + return eSIR_SUCCESS; + +} /* End populate_dot11f_rates_tdls */ + +tSirRetStatus +PopulateDot11fTPCReport(tpAniSirGlobal pMac, + tDot11fIETPCReport *pDot11f, + tpPESession psessionEntry) +{ + tANI_U16 staid, txPower; + tSirRetStatus nSirStatus; + + nSirStatus = limGetMgmtStaid( pMac, &staid, psessionEntry); + if ( eSIR_SUCCESS != nSirStatus ) + { + dot11fLog(pMac, LOG1, + FL("Failed to get the STAID in Populate Dot11fTPCReport; limGetMgmtStaid returned status %d"), + nSirStatus); + return eSIR_FAILURE; + } + + // FramesToDo: This function was "misplaced" in the move to Gen4_TVM... + // txPower = halGetRateToPwrValue( pMac, staid, pMac->lim.gLimCurrentChannelId, isBeacon ); + txPower = 0; + pDot11f->tx_power = ( tANI_U8 )txPower; + pDot11f->link_margin = 0; + pDot11f->present = 1; + + return eSIR_SUCCESS; +} // End PopulateDot11fTPCReport. + + +void PopulateDot11fTSInfo(tSirMacTSInfo *pInfo, + tDot11fFfTSInfo *pDot11f) +{ + pDot11f->traffic_type = pInfo->traffic.trafficType; + pDot11f->tsid = pInfo->traffic.tsid; + pDot11f->direction = pInfo->traffic.direction; + pDot11f->access_policy = pInfo->traffic.accessPolicy; + pDot11f->aggregation = pInfo->traffic.aggregation; + pDot11f->psb = pInfo->traffic.psb; + pDot11f->user_priority = pInfo->traffic.userPrio; + pDot11f->tsinfo_ack_pol = pInfo->traffic.ackPolicy; + pDot11f->schedule = pInfo->schedule.schedule; +} // End PopulatedDot11fTSInfo. + +void PopulateDot11fWMM(tpAniSirGlobal pMac, + tDot11fIEWMMInfoAp *pInfo, + tDot11fIEWMMParams *pParams, + tDot11fIEWMMCaps *pCaps, + tpPESession psessionEntry) +{ + if ( psessionEntry->limWmeEnabled ) + { + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + PopulateDot11fWMMInfoAp( pMac, pInfo, psessionEntry ); + } else { + PopulateDot11fWMMParams( pMac, pParams, psessionEntry); + + if (psessionEntry->limWsmEnabled) { + PopulateDot11fWMMCaps( pCaps ); + } + } + } +} // End PopulateDot11fWMM. + +void PopulateDot11fWMMCaps(tDot11fIEWMMCaps *pCaps) +{ + pCaps->version = SIR_MAC_OUI_VERSION_1; + pCaps->qack = 0; + pCaps->queue_request = 1; + pCaps->txop_request = 0; + pCaps->more_ack = 0; + pCaps->present = 1; +} // End PopulateDot11fWmmCaps. + +#ifdef FEATURE_WLAN_ESE +void PopulateDot11fReAssocTspec(tpAniSirGlobal pMac, tDot11fReAssocRequest *pReassoc, tpPESession psessionEntry) +{ + tANI_U8 numTspecs = 0, idx; + tTspecInfo *pTspec = NULL; + + numTspecs = psessionEntry->pLimReAssocReq->eseTspecInfo.numTspecs; + pTspec = &psessionEntry->pLimReAssocReq->eseTspecInfo.tspec[0]; + pReassoc->num_WMMTSPEC = numTspecs; + if (numTspecs) { + for (idx=0; idxtspec, &pReassoc->WMMTSPEC[idx]); + pTspec->tspec.mediumTime = 0; + pTspec++; + } + } +} +#endif + +void PopulateDot11fWMMInfoAp(tpAniSirGlobal pMac, tDot11fIEWMMInfoAp *pInfo, + tpPESession psessionEntry) +{ + pInfo->version = SIR_MAC_OUI_VERSION_1; + + /* WMM Specification 3.1.3, 3.2.3 + * An IBSS staion shall always use its default WMM parameters. + */ + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + pInfo->param_set_count = 0; + pInfo->uapsd = 0; + } else { + pInfo->param_set_count = ( 0xf & psessionEntry->gLimEdcaParamSetCount ); + if (LIM_IS_AP_ROLE(psessionEntry)) { + pInfo->uapsd = ( 0x1 & psessionEntry->apUapsdEnable ); + } else + pInfo->uapsd = ( 0x1 & pMac->lim.gUapsdEnable ); + } + pInfo->present = 1; +} + +void PopulateDot11fWMMInfoStation(tpAniSirGlobal pMac, tDot11fIEWMMInfoStation *pInfo) +{ + tANI_U32 val = 0; + + pInfo->version = SIR_MAC_OUI_VERSION_1; + pInfo->acvo_uapsd = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); + pInfo->acvi_uapsd = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); + pInfo->acbk_uapsd = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); + pInfo->acbe_uapsd = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); + + if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max SP Length"));) + + pInfo->max_sp_length = (tANI_U8)val; + pInfo->present = 1; +} + +void PopulateDot11fWMMInfoStationPerSession(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEWMMInfoStation *pInfo) +{ + tANI_U32 val = 0; + + pInfo->version = SIR_MAC_OUI_VERSION_1; + pInfo->acvo_uapsd = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcBitmask); + pInfo->acvi_uapsd = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcBitmask); + pInfo->acbk_uapsd = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcBitmask); + pInfo->acbe_uapsd = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcBitmask); + + if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max SP Length"));) + + pInfo->max_sp_length = (tANI_U8)val; + pInfo->present = 1; +} + +void PopulateDot11fWMMParams(tpAniSirGlobal pMac, + tDot11fIEWMMParams *pParams, + tpPESession psessionEntry) +{ + pParams->version = SIR_MAC_OUI_VERSION_1; + + if (LIM_IS_AP_ROLE(psessionEntry)) + pParams->qosInfo = + (psessionEntry->apUapsdEnable << 7) | ((tANI_U8)(0x0f & psessionEntry->gLimEdcaParamSetCount)); + else + pParams->qosInfo = + (pMac->lim.gUapsdEnable << 7) | ((tANI_U8)(0x0f & psessionEntry->gLimEdcaParamSetCount)); + + // Fill each EDCA parameter set in order: be, bk, vi, vo + pParams->acbe_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[0].aci.aifsn) ); + pParams->acbe_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[0].aci.acm ); + pParams->acbe_aci = ( 0x3 & SIR_MAC_EDCAACI_BESTEFFORT ); + pParams->acbe_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.min ); + pParams->acbe_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[0].cw.max ); + pParams->acbe_txoplimit = psessionEntry->gLimEdcaParamsBC[0].txoplimit; + + pParams->acbk_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[1].aci.aifsn) ); + pParams->acbk_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[1].aci.acm ); + pParams->acbk_aci = ( 0x3 & SIR_MAC_EDCAACI_BACKGROUND ); + pParams->acbk_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.min ); + pParams->acbk_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[1].cw.max ); + pParams->acbk_txoplimit = psessionEntry->gLimEdcaParamsBC[1].txoplimit; + + if (LIM_IS_AP_ROLE(psessionEntry)) + pParams->acvi_aifsn = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].aci.aifsn ); + else + pParams->acvi_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[2].aci.aifsn) ); + + + + pParams->acvi_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[2].aci.acm ); + pParams->acvi_aci = ( 0x3 & SIR_MAC_EDCAACI_VIDEO ); + pParams->acvi_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.min ); + pParams->acvi_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[2].cw.max ); + pParams->acvi_txoplimit = psessionEntry->gLimEdcaParamsBC[2].txoplimit; + + if (LIM_IS_AP_ROLE(psessionEntry)) + pParams->acvo_aifsn = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].aci.aifsn ); + else + pParams->acvo_aifsn = ( 0xf & SET_AIFSN(psessionEntry->gLimEdcaParamsBC[3].aci.aifsn) ); + + pParams->acvo_acm = ( 0x1 & psessionEntry->gLimEdcaParamsBC[3].aci.acm ); + pParams->acvo_aci = ( 0x3 & SIR_MAC_EDCAACI_VOICE ); + pParams->acvo_acwmin = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.min ); + pParams->acvo_acwmax = ( 0xf & psessionEntry->gLimEdcaParamsBC[3].cw.max ); + pParams->acvo_txoplimit = psessionEntry->gLimEdcaParamsBC[3].txoplimit; + + pParams->present = 1; + +} // End PopulateDot11fWMMParams. + +void PopulateDot11fWMMSchedule(tSirMacScheduleIE *pSchedule, + tDot11fIEWMMSchedule *pDot11f) +{ + pDot11f->version = 1; + pDot11f->aggregation = pSchedule->info.aggregation; + pDot11f->tsid = pSchedule->info.tsid; + pDot11f->direction = pSchedule->info.direction; + pDot11f->reserved = pSchedule->info.rsvd; + pDot11f->service_start_time = pSchedule->svcStartTime; + pDot11f->service_interval = pSchedule->svcInterval; + pDot11f->max_service_dur = pSchedule->maxSvcDuration; + pDot11f->spec_interval = pSchedule->specInterval; + + pDot11f->present = 1; +} // End PopulateDot11fWMMSchedule. + +tSirRetStatus +PopulateDot11fWPA(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWPA *pDot11f) +{ + tANI_U32 status; + int idx; + + if ( pRsnIe->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WPA ) ) ) + { + status = dot11fUnpackIeWPA( pMac, + pRsnIe->rsnIEdata + idx + 2 + 4, // EID, length, OUI + pRsnIe->rsnIEdata[ idx + 1 ] - 4, // OUI + pDot11f ); + if ( DOT11F_FAILED( status ) ) + { + dot11fLog(pMac, LOGE, + FL("Parse failure in PopulateDot11fWPA (0x%08x)"), + status); + return eSIR_FAILURE; + } + } + } + + return eSIR_SUCCESS; +} // End PopulateDot11fWPA. + + + +tSirRetStatus PopulateDot11fWPAOpaque( tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWPAOpaque *pDot11f ) +{ + int idx; + + if ( pRsnIe->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, pRsnIe, DOT11F_EID_WPA ) ) ) + { + pDot11f->present = 1; + pDot11f->num_data = pRsnIe->rsnIEdata[ idx + 1 ] - 4; + vos_mem_copy( pDot11f->data, + pRsnIe->rsnIEdata + idx + 2 + 4, // EID, len, OUI + pRsnIe->rsnIEdata[ idx + 1 ] - 4 ); // OUI + } + } + + return eSIR_SUCCESS; + +} // End PopulateDot11fWPAOpaque. + +//////////////////////////////////////////////////////////////////////// + +tSirRetStatus +sirConvertProbeReqFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tpSirProbeReq pProbeReq) +{ + tANI_U32 status; + tDot11fProbeRequest pr; + + // Ok, zero-init our [out] parameter, + vos_mem_set( (tANI_U8*)pProbeReq, sizeof(tSirProbeReq), 0); + + // delegate to the framesc-generated code, + status = dot11fUnpackProbeRequest(pMac, pFrame, nFrame, &pr); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse a Probe Request (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking a Probe Request (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fProbeRequestto' a 'tSirProbeReq'... + if ( ! pr.SSID.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));) + } + else + { + pProbeReq->ssidPresent = 1; + ConvertSSID( pMac, &pProbeReq->ssId, &pr.SSID ); + } + + if ( ! pr.SuppRates.present ) + { + PELOGW(limLog(pMac, LOGW, + FL("Mandatory IE Supported Rates not present!"));) + return eSIR_FAILURE; + } + else + { + pProbeReq->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pProbeReq->supportedRates, &pr.SuppRates ); + } + + if ( pr.ExtSuppRates.present ) + { + pProbeReq->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pProbeReq->extendedRates, &pr.ExtSuppRates ); + } + + if ( pr.HTCaps.present ) + { + vos_mem_copy( &pProbeReq->HTCaps, &pr.HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if (pr.WscProbeReq.present) { + pProbeReq->wscIePresent = 1; + vos_mem_copy(&pProbeReq->probeReqWscIeInfo, &pr.WscProbeReq, + sizeof(tDot11fIEWscProbeReq)); + } +#ifdef WLAN_FEATURE_11AC + if ( pr.VHTCaps.present ) + { + vos_mem_copy( &pProbeReq->VHTCaps, &pr.VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + } +#endif + + + if ( pr.P2PProbeReq.present ) + { + pProbeReq->p2pIePresent = 1; + } + + return eSIR_SUCCESS; + +} // End sirConvertProbeReqFrame2Struct. + +/** + * sirvalidateandrectifyies checks for the malformed frame. + * The frame would contain fixed IEs of 12 bytes follwed by Variable IEs + * (Tagged elements). + * Every Tagged IE has tag number, tag length and data. Tag length indicates + * the size of data in bytes. + * This function checks for size of Frame recived with the sum of all IEs. + * And also rectifies missing optional fields in IE. + * + * NOTE : Presently this function rectifies RSN capability in RSN IE, can + * extended to rectify other optional fields in other IEs. + */ +tSirRetStatus sirvalidateandrectifyies(tpAniSirGlobal pMac, + tANI_U8 *pMgmtFrame, + tANI_U32 nFrameBytes, + tANI_U32 *nMissingRsnBytes) +{ + tANI_U32 length = SIZE_OF_FIXED_PARAM; + tANI_U8 *refFrame; + + /* Frame contains atleast one IE */ + if (nFrameBytes > (SIZE_OF_FIXED_PARAM + 2)) { + while (length < nFrameBytes) { + /* refFrame points to next IE */ + refFrame = pMgmtFrame + length; + length += (tANI_U32)(SIZE_OF_TAG_PARAM_NUM + SIZE_OF_TAG_PARAM_LEN + + (*(refFrame + SIZE_OF_TAG_PARAM_NUM))); + } + if (length != nFrameBytes) { + /* + * Workaround : Some APs may not include RSN Capability but + * the length of which is included in RSN IE length. + * this may cause in updating RSN Capability with junk value. + * To avoid this, add RSN Capability value with default value. + * Going further we can have such workaround for other IEs + */ + if ((*refFrame == RSNIEID) && + (length == (nFrameBytes + RSNIE_CAPABILITY_LEN))) { + /* Assume RSN Capability as 00 */ + vos_mem_set( ( tANI_U8* ) (pMgmtFrame + (nFrameBytes)), + RSNIE_CAPABILITY_LEN, DEFAULT_RSNIE_CAP_VAL ); + *nMissingRsnBytes = RSNIE_CAPABILITY_LEN; + limLog(pMac, LOG1, + FL("Added RSN Capability to the RSNIE as 0x00 0x00")); + + return eHAL_STATUS_SUCCESS; + } + return eSIR_FAILURE; + } + } + + return eHAL_STATUS_SUCCESS; +} + +tSirRetStatus sirConvertProbeFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tpSirProbeRespBeacon pProbeResp) +{ + tANI_U32 status; + tDot11fProbeResponse *pr; + + // Ok, zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pProbeResp, sizeof(tSirProbeRespBeacon), 0 ); + + pr = vos_mem_malloc(sizeof(tDot11fProbeResponse)); + if ( NULL == pr ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + + vos_mem_set( ( tANI_U8* )pr, sizeof(tDot11fProbeResponse), 0 ); + + // delegate to the framesc-generated code, + status = dot11fUnpackProbeResponse( pMac, pFrame, nFrame, pr ); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse a Probe Response (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + vos_mem_free(pr); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking a Probe Response(0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fProbeResponse' to a 'tSirProbeRespBeacon'... + + // Timestamp + vos_mem_copy( ( tANI_U8* )pProbeResp->timeStamp, ( tANI_U8* )&pr->TimeStamp, + sizeof(tSirMacTimeStamp) ); + + // Beacon Interval + pProbeResp->beaconInterval = pr->BeaconInterval.interval; + + // Capabilities + pProbeResp->capabilityInfo.ess = pr->Capabilities.ess; + pProbeResp->capabilityInfo.ibss = pr->Capabilities.ibss; + pProbeResp->capabilityInfo.cfPollable = pr->Capabilities.cfPollable; + pProbeResp->capabilityInfo.cfPollReq = pr->Capabilities.cfPollReq; + pProbeResp->capabilityInfo.privacy = pr->Capabilities.privacy; + pProbeResp->capabilityInfo.shortPreamble = pr->Capabilities.shortPreamble; + pProbeResp->capabilityInfo.pbcc = pr->Capabilities.pbcc; + pProbeResp->capabilityInfo.channelAgility = pr->Capabilities.channelAgility; + pProbeResp->capabilityInfo.spectrumMgt = pr->Capabilities.spectrumMgt; + pProbeResp->capabilityInfo.qos = pr->Capabilities.qos; + pProbeResp->capabilityInfo.shortSlotTime = pr->Capabilities.shortSlotTime; + pProbeResp->capabilityInfo.apsd = pr->Capabilities.apsd; + pProbeResp->capabilityInfo.rrm = pr->Capabilities.rrm; + pProbeResp->capabilityInfo.dsssOfdm = pr->Capabilities.dsssOfdm; + pProbeResp->capabilityInfo.delayedBA = pr->Capabilities.delayedBA; + pProbeResp->capabilityInfo.immediateBA = pr->Capabilities.immediateBA; + + if ( ! pr->SSID.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));) + } + else + { + pProbeResp->ssidPresent = 1; + ConvertSSID( pMac, &pProbeResp->ssId, &pr->SSID ); + } + + if ( ! pr->SuppRates.present ) + { + PELOGW(limLog(pMac, LOGW, + FL("Mandatory IE Supported Rates not present!"));) + } + else + { + pProbeResp->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pProbeResp->supportedRates, &pr->SuppRates ); + } + + if ( pr->ExtSuppRates.present ) + { + pProbeResp->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pProbeResp->extendedRates, &pr->ExtSuppRates ); + } + + + if ( pr->CFParams.present ) + { + pProbeResp->cfPresent = 1; + ConvertCFParams( pMac, &pProbeResp->cfParamSet, &pr->CFParams ); + } + + if ( pr->Country.present ) + { + pProbeResp->countryInfoPresent = 1; + ConvertCountry( pMac, &pProbeResp->countryInfoParam, &pr->Country ); + } + + if ( pr->EDCAParamSet.present ) + { + pProbeResp->edcaPresent = 1; + ConvertEDCAParam( pMac, &pProbeResp->edcaParams, &pr->EDCAParamSet ); + } + + if ( pr->ChanSwitchAnn.present ) + { + pProbeResp->channelSwitchPresent = 1; + vos_mem_copy( &pProbeResp->channelSwitchIE, &pr->ChanSwitchAnn, + sizeof(pProbeResp->channelSwitchIE) ); + } + + if (pr->ext_chan_switch_ann.present) { + pProbeResp->ext_chan_switch_present = 1; + vos_mem_copy(&pProbeResp->ext_chan_switch, &pr->ext_chan_switch_ann, + sizeof(tDot11fIEext_chan_switch_ann)); + } + + if (pr->SuppOperatingClasses.present) { + pProbeResp->supp_operating_class_present = 1; + vos_mem_copy(&pProbeResp->supp_operating_classes, &pr->SuppOperatingClasses, + sizeof(tDot11fIESuppOperatingClasses)); + } + + if (pr->sec_chan_offset_ele.present) { + pProbeResp->sec_chan_offset_present = 1; + vos_mem_copy(&pProbeResp->sec_chan_offset, &pr->sec_chan_offset_ele, + sizeof(pProbeResp->sec_chan_offset)); + } + + if( pr->TPCReport.present) + { + pProbeResp->tpcReportPresent = 1; + vos_mem_copy( &pProbeResp->tpcReport, &pr->TPCReport, sizeof(tDot11fIETPCReport)); + } + + if( pr->PowerConstraints.present) + { + pProbeResp->powerConstraintPresent = 1; + vos_mem_copy( &pProbeResp->localPowerConstraint, &pr->PowerConstraints, + sizeof(tDot11fIEPowerConstraints)); + } + + if ( pr->Quiet.present ) + { + pProbeResp->quietIEPresent = 1; + vos_mem_copy( &pProbeResp->quietIE, &pr->Quiet, sizeof(tDot11fIEQuiet) ); + } + + if ( pr->HTCaps.present ) + { + vos_mem_copy( &pProbeResp->HTCaps, &pr->HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if ( pr->HTInfo.present ) + { + vos_mem_copy( &pProbeResp->HTInfo, &pr->HTInfo, sizeof( tDot11fIEHTInfo ) ); + } + + if ( pr->DSParams.present ) + { + pProbeResp->dsParamsPresent = 1; + pProbeResp->channelNumber = pr->DSParams.curr_channel; + } + else if(pr->HTInfo.present) + { + pProbeResp->channelNumber = pr->HTInfo.primaryChannel; + } + + if ( pr->RSNOpaque.present ) + { + pProbeResp->rsnPresent = 1; + ConvertRSNOpaque( pMac, &pProbeResp->rsn, &pr->RSNOpaque ); + } + + if ( pr->WPA.present ) + { + pProbeResp->wpaPresent = 1; + ConvertWPA( pMac, &pProbeResp->wpa, &pr->WPA ); + } + + if ( pr->WMMParams.present ) + { + pProbeResp->wmeEdcaPresent = 1; + ConvertWMMParams( pMac, &pProbeResp->edcaParams, &pr->WMMParams ); + PELOG1(limLog(pMac, LOG1, + FL("WMM Parameter present in Probe Response Frame!")); + __printWMMParams(pMac, &pr->WMMParams);) + } + + if ( pr->WMMInfoAp.present ) + { + pProbeResp->wmeInfoPresent = 1; + PELOG1(limLog(pMac, LOG1, + FL("WMM Information Element present in Probe Rsp Frame!"));) + } + + if ( pr->WMMCaps.present ) + { + pProbeResp->wsmCapablePresent = 1; + } + + + if ( pr->ERPInfo.present ) + { + pProbeResp->erpPresent = 1; + ConvertERPInfo( pMac, &pProbeResp->erpIEInfo, &pr->ERPInfo ); + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pr->MobilityDomain.present) + { + // MobilityDomain + pProbeResp->mdiePresent = 1; + vos_mem_copy( (tANI_U8 *)&(pProbeResp->mdie[0]), (tANI_U8 *)&(pr->MobilityDomain.MDID), + sizeof(tANI_U16) ); + pProbeResp->mdie[2] = ((pr->MobilityDomain.overDSCap << 0) | (pr->MobilityDomain.resourceReqCap << 1)); +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(pMac, LOG2, + FL("mdie=%02x%02x%02x"), (unsigned int)pProbeResp->mdie[0], + (unsigned int)pProbeResp->mdie[1], (unsigned int)pProbeResp->mdie[2]); +#endif + } +#endif + +#if defined FEATURE_WLAN_ESE + if (pr->ESEVersion.present) { + pProbeResp->is_ese_ver_ie_present = 1; + } + if (pr->QBSSLoad.present) + { + vos_mem_copy(&pProbeResp->QBSSLoad, &pr->QBSSLoad, sizeof(tDot11fIEQBSSLoad)); + } +#endif + if (pr->P2PProbeRes.present) + { + vos_mem_copy( &pProbeResp->P2PProbeRes, &pr->P2PProbeRes, + sizeof(tDot11fIEP2PProbeRes) ); + } +#ifdef WLAN_FEATURE_11AC + if ( pr->VHTCaps.present ) + { + vos_mem_copy( &pProbeResp->VHTCaps, &pr->VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + } + if ( pr->VHTOperation.present ) + { + vos_mem_copy( &pProbeResp->VHTOperation, &pr->VHTOperation, sizeof( tDot11fIEVHTOperation) ); + } + if ( pr->VHTExtBssLoad.present ) + { + vos_mem_copy( &pProbeResp->VHTExtBssLoad, &pr->VHTExtBssLoad, sizeof( tDot11fIEVHTExtBssLoad) ); + } +#endif + pProbeResp->Vendor1IEPresent = pr->Vendor1IE.present; + pProbeResp->Vendor2IEPresent = pr->Vendor2IE.present; + pProbeResp->Vendor3IEPresent = pr->Vendor3IE.present; + + vos_mem_free(pr); + return eSIR_SUCCESS; + +} // End sirConvertProbeFrame2Struct. + +tSirRetStatus +sirConvertAssocReqFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tpSirAssocReq pAssocReq) +{ + tDot11fAssocRequest *ar; + tANI_U32 status; + + ar = vos_mem_malloc(sizeof(tDot11fAssocRequest)); + if ( NULL == ar ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pAssocReq, sizeof(tSirAssocReq), 0 ); + vos_mem_set( ( tANI_U8* )ar, sizeof( tDot11fAssocRequest ), 0 ); + + // delegate to the framesc-generated code, + status = dot11fUnpackAssocRequest( pMac, pFrame, nFrame, ar ); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse an Association Request (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + vos_mem_free(ar); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking an Assoc Req(0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fAssocRequest' to a 'tSirAssocReq'... + + // make sure this is seen as an assoc request + pAssocReq->reassocRequest = 0; + + // Capabilities + pAssocReq->capabilityInfo.ess = ar->Capabilities.ess; + pAssocReq->capabilityInfo.ibss = ar->Capabilities.ibss; + pAssocReq->capabilityInfo.cfPollable = ar->Capabilities.cfPollable; + pAssocReq->capabilityInfo.cfPollReq = ar->Capabilities.cfPollReq; + pAssocReq->capabilityInfo.privacy = ar->Capabilities.privacy; + pAssocReq->capabilityInfo.shortPreamble = ar->Capabilities.shortPreamble; + pAssocReq->capabilityInfo.pbcc = ar->Capabilities.pbcc; + pAssocReq->capabilityInfo.channelAgility = ar->Capabilities.channelAgility; + pAssocReq->capabilityInfo.spectrumMgt = ar->Capabilities.spectrumMgt; + pAssocReq->capabilityInfo.qos = ar->Capabilities.qos; + pAssocReq->capabilityInfo.shortSlotTime = ar->Capabilities.shortSlotTime; + pAssocReq->capabilityInfo.apsd = ar->Capabilities.apsd; + pAssocReq->capabilityInfo.rrm = ar->Capabilities.rrm; + pAssocReq->capabilityInfo.dsssOfdm = ar->Capabilities.dsssOfdm; + pAssocReq->capabilityInfo.delayedBA = ar->Capabilities.delayedBA; + pAssocReq->capabilityInfo.immediateBA = ar->Capabilities.immediateBA; + + // Listen Interval + pAssocReq->listenInterval = ar->ListenInterval.interval; + + // SSID + if ( ar->SSID.present ) + { + pAssocReq->ssidPresent = 1; + ConvertSSID( pMac, &pAssocReq->ssId, &ar->SSID ); + } + + // Supported Rates + if ( ar->SuppRates.present ) + { + pAssocReq->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pAssocReq->supportedRates, &ar->SuppRates ); + } + + // Extended Supported Rates + if ( ar->ExtSuppRates.present ) + { + pAssocReq->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pAssocReq->extendedRates, &ar->ExtSuppRates ); + } + + // QOS Capabilities: + if ( ar->QOSCapsStation.present ) + { + pAssocReq->qosCapabilityPresent = 1; + ConvertQOSCapsStation( pMac, &pAssocReq->qosCapability, &ar->QOSCapsStation ); + } + + // WPA + if ( ar->WPAOpaque.present ) + { + pAssocReq->wpaPresent = 1; + ConvertWPAOpaque( pMac, &pAssocReq->wpa, &ar->WPAOpaque ); + } + +#ifdef FEATURE_WLAN_WAPI + // WAPI + if ( ar->WAPIOpaque.present ) + { + pAssocReq->wapiPresent = 1; + ConvertWAPIOpaque( pMac, &pAssocReq->wapi, &ar->WAPIOpaque ); + } +#endif + + // RSN + if ( ar->RSNOpaque.present ) + { + pAssocReq->rsnPresent = 1; + ConvertRSNOpaque( pMac, &pAssocReq->rsn, &ar->RSNOpaque ); + } + + // WSC IE + if (ar->WscIEOpaque.present) + { + pAssocReq->addIEPresent = 1; + ConvertWscOpaque(pMac, &pAssocReq->addIE, &ar->WscIEOpaque); + } + + + if(ar->P2PIEOpaque.present) + { + pAssocReq->addIEPresent = 1; + ConvertP2POpaque( pMac, &pAssocReq->addIE, &ar->P2PIEOpaque); + } +#ifdef WLAN_FEATURE_WFD + if(ar->WFDIEOpaque.present) + { + pAssocReq->addIEPresent = 1; + ConvertWFDOpaque( pMac, &pAssocReq->addIE, &ar->WFDIEOpaque); + } +#endif + + // Power Capabilities + if ( ar->PowerCaps.present ) + { + pAssocReq->powerCapabilityPresent = 1; + ConvertPowerCaps( pMac, &pAssocReq->powerCapability, &ar->PowerCaps ); + } + + // Supported Channels + if ( ar->SuppChannels.present ) + { + pAssocReq->supportedChannelsPresent = 1; + ConvertSuppChannels( pMac, &pAssocReq->supportedChannels, &ar->SuppChannels ); + } + + if ( ar->HTCaps.present ) + { + vos_mem_copy( &pAssocReq->HTCaps, &ar->HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if ( ar->WMMInfoStation.present ) + { + pAssocReq->wmeInfoPresent = 1; + vos_mem_copy( &pAssocReq->WMMInfoStation, &ar->WMMInfoStation, + sizeof( tDot11fIEWMMInfoStation ) ); + + } + + + if ( ar->WMMCaps.present ) pAssocReq->wsmCapablePresent = 1; + + if ( ! pAssocReq->ssidPresent ) + { + PELOG2(limLog(pMac, LOG2, FL("Received Assoc without SSID IE."));) + vos_mem_free(ar); + return eSIR_FAILURE; + } + + if ( !pAssocReq->suppRatesPresent && !pAssocReq->extendedRatesPresent ) + { + PELOG2(limLog(pMac, LOG2, FL("Received Assoc without supp rate IE."));) + vos_mem_free(ar); + return eSIR_FAILURE; + } + +#ifdef WLAN_FEATURE_11AC + if ( ar->VHTCaps.present ) + { + vos_mem_copy( &pAssocReq->VHTCaps, &ar->VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + limLog(pMac, LOGW, FL("Received Assoc Req with VHT Cap")); + limLogVHTCap( pMac, &pAssocReq->VHTCaps); + } + if ( ar->OperatingMode.present ) + { + vos_mem_copy( &pAssocReq->operMode, &ar->OperatingMode, sizeof (tDot11fIEOperatingMode)); + limLog(pMac, LOGW, FL("Received Assoc Req with Operating Mode IE")); + limLogOperatingMode( pMac, &pAssocReq->operMode); + } +#endif + if (ar->ExtCap.present) + { + struct s_ext_cap *p_ext_cap; + + vos_mem_copy(&pAssocReq->ExtCap.bytes, &ar->ExtCap.bytes, + ar->ExtCap.num_bytes); + + p_ext_cap = (struct s_ext_cap *)&pAssocReq->ExtCap.bytes; + limLog(pMac, LOG1, + FL("ExtCap present, timingMeas: %d Initiator: %d Responder: %d"), + p_ext_cap->timingMeas, p_ext_cap->fine_time_meas_initiator, + p_ext_cap->fine_time_meas_responder); + } + vos_mem_free(ar); + return eSIR_SUCCESS; + +} // End sirConvertAssocReqFrame2Struct. + +tSirRetStatus +sirConvertAssocRespFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tpSirAssocRsp pAssocRsp) +{ + static tDot11fAssocResponse ar; + tANI_U32 status; + tANI_U8 cnt =0; + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pAssocRsp, sizeof(tSirAssocRsp), 0 ); + + // delegate to the framesc-generated code, + status = dot11fUnpackAssocResponse( pMac, pFrame, nFrame, &ar); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse an Assoc Response (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking an Assoc Rsp (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fAssocResponse' a 'tSirAssocRsp'... + + // Capabilities + pAssocRsp->capabilityInfo.ess = ar.Capabilities.ess; + pAssocRsp->capabilityInfo.ibss = ar.Capabilities.ibss; + pAssocRsp->capabilityInfo.cfPollable = ar.Capabilities.cfPollable; + pAssocRsp->capabilityInfo.cfPollReq = ar.Capabilities.cfPollReq; + pAssocRsp->capabilityInfo.privacy = ar.Capabilities.privacy; + pAssocRsp->capabilityInfo.shortPreamble = ar.Capabilities.shortPreamble; + pAssocRsp->capabilityInfo.pbcc = ar.Capabilities.pbcc; + pAssocRsp->capabilityInfo.channelAgility = ar.Capabilities.channelAgility; + pAssocRsp->capabilityInfo.spectrumMgt = ar.Capabilities.spectrumMgt; + pAssocRsp->capabilityInfo.qos = ar.Capabilities.qos; + pAssocRsp->capabilityInfo.shortSlotTime = ar.Capabilities.shortSlotTime; + pAssocRsp->capabilityInfo.apsd = ar.Capabilities.apsd; + pAssocRsp->capabilityInfo.rrm = ar.Capabilities.rrm; + pAssocRsp->capabilityInfo.dsssOfdm = ar.Capabilities.dsssOfdm; + pAssocRsp->capabilityInfo.delayedBA = ar.Capabilities.delayedBA; + pAssocRsp->capabilityInfo.immediateBA = ar.Capabilities.immediateBA; + + pAssocRsp->statusCode = ar.Status.status; + pAssocRsp->aid = ar.AID.associd; + +#ifdef WLAN_FEATURE_11W + if (ar.TimeoutInterval.present) { + pAssocRsp->TimeoutInterval.present = 1; + pAssocRsp->TimeoutInterval.timeoutType = + ar.TimeoutInterval.timeoutType; + pAssocRsp->TimeoutInterval.timeoutValue = + ar.TimeoutInterval.timeoutValue; + } +#endif + + if ( ! ar.SuppRates.present ) + { + pAssocRsp->suppRatesPresent = 0; + PELOGW(limLog(pMac, LOGW, + FL("Mandatory IE Supported Rates not present!"));) + } + else + { + pAssocRsp->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pAssocRsp->supportedRates, &ar.SuppRates ); + } + + if ( ar.ExtSuppRates.present ) + { + pAssocRsp->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pAssocRsp->extendedRates, &ar.ExtSuppRates ); + } + + if ( ar.EDCAParamSet.present ) + { + pAssocRsp->edcaPresent = 1; + ConvertEDCAParam( pMac, &pAssocRsp->edca, &ar.EDCAParamSet ); + } + + + if ( ar.WMMParams.present ) + { + pAssocRsp->wmeEdcaPresent = 1; + ConvertWMMParams( pMac, &pAssocRsp->edca, &ar.WMMParams); + limLog(pMac, LOG1, FL("WMM Parameter Element present in Association Response Frame!")); + __printWMMParams(pMac, &ar.WMMParams); + } + + if ( ar.HTCaps.present ) + { + limLog(pMac, LOG1, FL("Received Assoc Response with HT Cap")); + vos_mem_copy( &pAssocRsp->HTCaps, &ar.HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if ( ar.HTInfo.present ) + { + limLog(pMac, LOG1, FL("Received Assoc Response with HT Info")); + vos_mem_copy( &pAssocRsp->HTInfo, &ar.HTInfo, sizeof( tDot11fIEHTInfo ) ); + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (ar.MobilityDomain.present) + { + // MobilityDomain + pAssocRsp->mdiePresent = 1; + vos_mem_copy( (tANI_U8 *)&(pAssocRsp->mdie[0]), (tANI_U8 *)&(ar.MobilityDomain.MDID), + sizeof(tANI_U16) ); + pAssocRsp->mdie[2] = ((ar.MobilityDomain.overDSCap << 0) | (ar.MobilityDomain.resourceReqCap << 1)); +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(pMac, LOG1, FL("new mdie=%02x%02x%02x"), (unsigned int)pAssocRsp->mdie[0], + (unsigned int)pAssocRsp->mdie[1], (unsigned int)pAssocRsp->mdie[2]); +#endif + } + + if ( ar.FTInfo.present ) + { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + limLog(pMac, LOG1, FL("FT Info present %d %d %d"), ar.FTInfo.R0KH_ID.num_PMK_R0_ID, + ar.FTInfo.R0KH_ID.present, + ar.FTInfo.R1KH_ID.present); +#endif + pAssocRsp->ftinfoPresent = 1; + vos_mem_copy( &pAssocRsp->FTInfo, &ar.FTInfo, sizeof(tDot11fIEFTInfo) ); + } +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (ar.num_RICDataDesc) { + for (cnt=0; cnt < ar.num_RICDataDesc; cnt++) { + if (ar.RICDataDesc[cnt].present) { + vos_mem_copy( &pAssocRsp->RICData[cnt], &ar.RICDataDesc[cnt], + sizeof(tDot11fIERICDataDesc)); + } + } + pAssocRsp->num_RICData = ar.num_RICDataDesc; + pAssocRsp->ricPresent = TRUE; + } +#endif + +#ifdef FEATURE_WLAN_ESE + if (ar.num_WMMTSPEC) { + pAssocRsp->num_tspecs = ar.num_WMMTSPEC; + for (cnt=0; cnt < ar.num_WMMTSPEC; cnt++) { + vos_mem_copy( &pAssocRsp->TSPECInfo[cnt], &ar.WMMTSPEC[cnt], + (sizeof(tDot11fIEWMMTSPEC)*ar.num_WMMTSPEC)); + } + pAssocRsp->tspecPresent = TRUE; + } + + if(ar.ESETrafStrmMet.present) + { + pAssocRsp->tsmPresent = 1; + vos_mem_copy(&pAssocRsp->tsmIE.tsid, + &ar.ESETrafStrmMet.tsid,sizeof(tSirMacESETSMIE)); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if ( ar.VHTCaps.present ) + { + vos_mem_copy( &pAssocRsp->VHTCaps, &ar.VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + limLog( pMac, LOG1, FL("Received Assoc Response with VHT Cap")); + limLogVHTCap(pMac, &pAssocRsp->VHTCaps); + } + if ( ar.VHTOperation.present ) + { + vos_mem_copy( &pAssocRsp->VHTOperation, &ar.VHTOperation, sizeof( tDot11fIEVHTOperation) ); + limLog( pMac, LOG1, FL("Received Assoc Response with VHT Operation")); + limLogVHTOperation(pMac, &pAssocRsp->VHTOperation); + } +#endif + + if (ar.ExtCap.present) + { + struct s_ext_cap *p_ext_cap; + + vos_mem_copy(&pAssocRsp->ExtCap.bytes, &ar.ExtCap.bytes, + ar.ExtCap.num_bytes); + p_ext_cap = (struct s_ext_cap *)&pAssocRsp->ExtCap.bytes; + limLog(pMac, LOG1, + FL("ExtCap present, timingMeas: %d Initiator: %d Responder: %d"), + p_ext_cap->timingMeas, p_ext_cap->fine_time_meas_initiator, + p_ext_cap->fine_time_meas_responder); + } + + if ( ar.QosMapSet.present ) + { + pAssocRsp->QosMapSet.present = 1; + ConvertQosMapsetFrame( pMac, &pAssocRsp->QosMapSet, &ar.QosMapSet); + limLog( pMac, LOG1, FL("Received Assoc Response with Qos Map Set")); + limLogQosMapSet(pMac, &pAssocRsp->QosMapSet); + } + + return eSIR_SUCCESS; + +} // End sirConvertAssocRespFrame2Struct. + +tSirRetStatus +sirConvertReassocReqFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tpSirAssocReq pAssocReq) +{ + static tDot11fReAssocRequest ar; + tANI_U32 status; + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pAssocReq, sizeof(tSirAssocReq), 0 ); + + // delegate to the framesc-generated code, + status = dot11fUnpackReAssocRequest( pMac, pFrame, nFrame, &ar ); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse a Re-association Req (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking a Re-assoc Req (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fReAssocRequest' to a 'tSirAssocReq'... + + // make sure this is seen as a re-assoc request + pAssocReq->reassocRequest = 1; + + // Capabilities + pAssocReq->capabilityInfo.ess = ar.Capabilities.ess; + pAssocReq->capabilityInfo.ibss = ar.Capabilities.ibss; + pAssocReq->capabilityInfo.cfPollable = ar.Capabilities.cfPollable; + pAssocReq->capabilityInfo.cfPollReq = ar.Capabilities.cfPollReq; + pAssocReq->capabilityInfo.privacy = ar.Capabilities.privacy; + pAssocReq->capabilityInfo.shortPreamble = ar.Capabilities.shortPreamble; + pAssocReq->capabilityInfo.pbcc = ar.Capabilities.pbcc; + pAssocReq->capabilityInfo.channelAgility = ar.Capabilities.channelAgility; + pAssocReq->capabilityInfo.spectrumMgt = ar.Capabilities.spectrumMgt; + pAssocReq->capabilityInfo.qos = ar.Capabilities.qos; + pAssocReq->capabilityInfo.shortSlotTime = ar.Capabilities.shortSlotTime; + pAssocReq->capabilityInfo.apsd = ar.Capabilities.apsd; + pAssocReq->capabilityInfo.rrm = ar.Capabilities.rrm; + pAssocReq->capabilityInfo.dsssOfdm = ar.Capabilities.dsssOfdm; + pAssocReq->capabilityInfo.delayedBA = ar.Capabilities.delayedBA; + pAssocReq->capabilityInfo.immediateBA = ar.Capabilities.immediateBA; + + // Listen Interval + pAssocReq->listenInterval = ar.ListenInterval.interval; + + // SSID + if ( ar.SSID.present ) + { + pAssocReq->ssidPresent = 1; + ConvertSSID( pMac, &pAssocReq->ssId, &ar.SSID ); + } + + // Supported Rates + if ( ar.SuppRates.present ) + { + pAssocReq->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pAssocReq->supportedRates, &ar.SuppRates ); + } + + // Extended Supported Rates + if ( ar.ExtSuppRates.present ) + { + pAssocReq->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pAssocReq->extendedRates, + &ar.ExtSuppRates ); + } + + // QOS Capabilities: + if ( ar.QOSCapsStation.present ) + { + pAssocReq->qosCapabilityPresent = 1; + ConvertQOSCapsStation( pMac, &pAssocReq->qosCapability, &ar.QOSCapsStation ); + } + + // WPA + if ( ar.WPAOpaque.present ) + { + pAssocReq->wpaPresent = 1; + ConvertWPAOpaque( pMac, &pAssocReq->wpa, &ar.WPAOpaque ); + } + + // RSN + if ( ar.RSNOpaque.present ) + { + pAssocReq->rsnPresent = 1; + ConvertRSNOpaque( pMac, &pAssocReq->rsn, &ar.RSNOpaque ); + } + + + // Power Capabilities + if ( ar.PowerCaps.present ) + { + pAssocReq->powerCapabilityPresent = 1; + ConvertPowerCaps( pMac, &pAssocReq->powerCapability, &ar.PowerCaps ); + } + + // Supported Channels + if ( ar.SuppChannels.present ) + { + pAssocReq->supportedChannelsPresent = 1; + ConvertSuppChannels( pMac, &pAssocReq->supportedChannels, &ar.SuppChannels ); + } + + if ( ar.HTCaps.present ) + { + vos_mem_copy( &pAssocReq->HTCaps, &ar.HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if ( ar.WMMInfoStation.present ) + { + pAssocReq->wmeInfoPresent = 1; + vos_mem_copy( &pAssocReq->WMMInfoStation, &ar.WMMInfoStation, + sizeof( tDot11fIEWMMInfoStation ) ); + + } + + if ( ar.WMMCaps.present ) pAssocReq->wsmCapablePresent = 1; + + if ( ! pAssocReq->ssidPresent ) + { + PELOG2(limLog(pMac, LOG2, FL("Received Assoc without SSID IE."));) + return eSIR_FAILURE; + } + + if ( ! pAssocReq->suppRatesPresent && ! pAssocReq->extendedRatesPresent ) + { + PELOG2(limLog(pMac, LOG2, FL("Received Assoc without supp rate IE."));) + return eSIR_FAILURE; + } + + // Why no call to 'updateAssocReqFromPropCapability' here, like + // there is in 'sirConvertAssocReqFrame2Struct'? + + // WSC IE + if (ar.WscIEOpaque.present) + { + pAssocReq->addIEPresent = 1; + ConvertWscOpaque(pMac, &pAssocReq->addIE, &ar.WscIEOpaque); + } + + if(ar.P2PIEOpaque.present) + { + pAssocReq->addIEPresent = 1; + ConvertP2POpaque( pMac, &pAssocReq->addIE, &ar.P2PIEOpaque); + } + +#ifdef WLAN_FEATURE_WFD + if(ar.WFDIEOpaque.present) + { + pAssocReq->addIEPresent = 1; + ConvertWFDOpaque( pMac, &pAssocReq->addIE, &ar.WFDIEOpaque); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if ( ar.VHTCaps.present ) + { + vos_mem_copy( &pAssocReq->VHTCaps, &ar.VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + } + if ( ar.OperatingMode.present ) + { + vos_mem_copy( &pAssocReq->operMode, &ar.OperatingMode, sizeof( tDot11fIEOperatingMode ) ); + limLog(pMac, LOGW, FL("Received Assoc Req with Operating Mode IE")); + limLogOperatingMode( pMac, &pAssocReq->operMode); + } +#endif + + if (ar.ExtCap.present) + { + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) + &ar.ExtCap.bytes; + vos_mem_copy(&pAssocReq->ExtCap.bytes, &ar.ExtCap.bytes, + ar.ExtCap.num_bytes); + limLog(pMac, LOG1, + FL("ExtCap present, timingMeas: %d Initiator: %d Responder: %d"), + p_ext_cap->timingMeas, p_ext_cap->fine_time_meas_initiator, + p_ext_cap->fine_time_meas_responder); + } + + return eSIR_SUCCESS; + +} // End sirConvertReassocReqFrame2Struct. + + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +tSirRetStatus +sirFillBeaconMandatoryIEforEseBcnReport(tpAniSirGlobal pMac, + tANI_U8 *pPayload, + const tANI_U32 nPayload, + tANI_U8 **outIeBuf, + tANI_U32 *pOutIeLen) +{ + tDot11fBeaconIEs *pBies = NULL; + tANI_U32 status = eHAL_STATUS_SUCCESS; + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirEseBcnReportMandatoryIe eseBcnReportMandatoryIe; + + /* To store how many bytes are required to be allocated + for Bcn report mandatory Ies */ + tANI_U16 numBytes = 0, freeBytes = 0; + tANI_U8 *pos = NULL; + + // Zero-init our [out] parameter, + vos_mem_set( (tANI_U8*)&eseBcnReportMandatoryIe, sizeof(eseBcnReportMandatoryIe), 0 ); + pBies = vos_mem_malloc(sizeof(tDot11fBeaconIEs)); + if ( NULL == pBies ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + // delegate to the framesc-generated code, + status = dot11fUnpackBeaconIEs( pMac, pPayload, nPayload, pBies ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, FL("Failed to parse Beacon IEs (0x%08x, %d bytes):"), + status, nPayload); + vos_mem_free(pBies); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking Beacon IEs (0x%08x, %d bytes):"), + status, nPayload); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload);) + } + + // & "transliterate" from a 'tDot11fBeaconIEs' to a 'eseBcnReportMandatoryIe'... + if ( !pBies->SSID.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));) + } + else + { + eseBcnReportMandatoryIe.ssidPresent = 1; + ConvertSSID( pMac, &eseBcnReportMandatoryIe.ssId, &pBies->SSID ); + /* 1 for EID, 1 for length and length bytes */ + numBytes += 1 + 1 + eseBcnReportMandatoryIe.ssId.length; + } + + if ( !pBies->SuppRates.present ) + { + PELOGW(limLog(pMac, LOGW, + FL("Mandatory IE Supported Rates not present!"));) + } + else + { + eseBcnReportMandatoryIe.suppRatesPresent = 1; + ConvertSuppRates( pMac, &eseBcnReportMandatoryIe.supportedRates, &pBies->SuppRates ); + numBytes += 1 + 1 + eseBcnReportMandatoryIe.supportedRates.numRates; + } + + if ( pBies->FHParamSet.present) + { + eseBcnReportMandatoryIe.fhParamPresent = 1; + ConvertFHParams( pMac, &eseBcnReportMandatoryIe.fhParamSet, &pBies->FHParamSet ); + numBytes += 1 + 1 + SIR_MAC_FH_PARAM_SET_EID_MAX; + } + + if ( pBies->DSParams.present ) + { + eseBcnReportMandatoryIe.dsParamsPresent = 1; + eseBcnReportMandatoryIe.dsParamSet.channelNumber = pBies->DSParams.curr_channel; + numBytes += 1 + 1 + SIR_MAC_DS_PARAM_SET_EID_MAX; + } + + if ( pBies->CFParams.present ) + { + eseBcnReportMandatoryIe.cfPresent = 1; + ConvertCFParams( pMac, &eseBcnReportMandatoryIe.cfParamSet, &pBies->CFParams ); + numBytes += 1 + 1 + SIR_MAC_CF_PARAM_SET_EID_MAX; + } + + if ( pBies->IBSSParams.present ) + { + eseBcnReportMandatoryIe.ibssParamPresent = 1; + eseBcnReportMandatoryIe.ibssParamSet.atim = pBies->IBSSParams.atim; + numBytes += 1 + 1 + SIR_MAC_IBSS_PARAM_SET_EID_MAX; + } + + if ( pBies->TIM.present ) + { + eseBcnReportMandatoryIe.timPresent = 1; + eseBcnReportMandatoryIe.tim.dtimCount = pBies->TIM.dtim_count; + eseBcnReportMandatoryIe.tim.dtimPeriod = pBies->TIM.dtim_period; + eseBcnReportMandatoryIe.tim.bitmapControl = pBies->TIM.bmpctl; + /* As per the ESE spec, May truncate and report first 4 octets only */ + numBytes += 1 + 1 + SIR_MAC_TIM_EID_MIN; + } + + if ( pBies->RRMEnabledCap.present ) + { + eseBcnReportMandatoryIe.rrmPresent = 1; + vos_mem_copy( &eseBcnReportMandatoryIe.rmEnabledCapabilities, &pBies->RRMEnabledCap, sizeof( tDot11fIERRMEnabledCap ) ); + numBytes += 1 + 1 + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX; + } + + *outIeBuf = vos_mem_malloc(numBytes); + if (NULL == *outIeBuf) + { + limLog(pMac, LOGP, FL("Memory Allocation failure")); + vos_mem_free(pBies); + return eSIR_FAILURE; + } + pos = *outIeBuf; + *pOutIeLen = numBytes; + freeBytes = numBytes; + + /* Start filling the output Ie with Mandatory IE information */ + /* Fill SSID IE */ + if (eseBcnReportMandatoryIe.ssidPresent) + { + if (freeBytes < (1 + 1 + eseBcnReportMandatoryIe.ssId.length)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy SSID")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_SSID_EID; + pos++; + *pos = eseBcnReportMandatoryIe.ssId.length; + pos++; + vos_mem_copy(pos, + (tANI_U8*)eseBcnReportMandatoryIe.ssId.ssId, + eseBcnReportMandatoryIe.ssId.length); + pos += eseBcnReportMandatoryIe.ssId.length; + freeBytes -= (1 + 1 + eseBcnReportMandatoryIe.ssId.length); + } + + /* Fill Supported Rates IE */ + if (eseBcnReportMandatoryIe.suppRatesPresent) + { + if (freeBytes < (1 + 1 + eseBcnReportMandatoryIe.supportedRates.numRates)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy Rates IE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_RATESET_EID; + pos++; + *pos = eseBcnReportMandatoryIe.supportedRates.numRates; + pos++; + vos_mem_copy(pos, + (tANI_U8*)eseBcnReportMandatoryIe.supportedRates.rate, + eseBcnReportMandatoryIe.supportedRates.numRates); + pos += eseBcnReportMandatoryIe.supportedRates.numRates; + freeBytes -= (1 + 1 + eseBcnReportMandatoryIe.supportedRates.numRates); + } + + /* Fill FH Parameter set IE */ + if (eseBcnReportMandatoryIe.fhParamPresent) + { + if (freeBytes < (1 + 1 + SIR_MAC_FH_PARAM_SET_EID_MAX)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy FHIE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_FH_PARAM_SET_EID; + pos++; + *pos = SIR_MAC_FH_PARAM_SET_EID_MAX; + pos++; + vos_mem_copy(pos, + (tANI_U8*)&eseBcnReportMandatoryIe.fhParamSet, + SIR_MAC_FH_PARAM_SET_EID_MAX); + pos += SIR_MAC_FH_PARAM_SET_EID_MAX; + freeBytes -= (1 + 1 + SIR_MAC_FH_PARAM_SET_EID_MAX); + } + + /* Fill DS Parameter set IE */ + if (eseBcnReportMandatoryIe.dsParamsPresent) + { + if (freeBytes < (1 + 1 + SIR_MAC_DS_PARAM_SET_EID_MAX)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy DS IE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_DS_PARAM_SET_EID; + pos++; + *pos = SIR_MAC_DS_PARAM_SET_EID_MAX; + pos++; + *pos = eseBcnReportMandatoryIe.dsParamSet.channelNumber; + pos += SIR_MAC_DS_PARAM_SET_EID_MAX; + freeBytes -= (1 + 1 + SIR_MAC_DS_PARAM_SET_EID_MAX); + } + + /* Fill CF Parameter set */ + if (eseBcnReportMandatoryIe.cfPresent) + { + if (freeBytes < (1 + 1 + SIR_MAC_CF_PARAM_SET_EID_MAX)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy CF IE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_CF_PARAM_SET_EID; + pos++; + *pos = SIR_MAC_CF_PARAM_SET_EID_MAX; + pos++; + vos_mem_copy(pos, + (tANI_U8*)&eseBcnReportMandatoryIe.cfParamSet, + SIR_MAC_CF_PARAM_SET_EID_MAX); + pos += SIR_MAC_CF_PARAM_SET_EID_MAX; + freeBytes -= (1 + 1 + SIR_MAC_CF_PARAM_SET_EID_MAX); + } + + /* Fill IBSS Parameter set IE */ + if (eseBcnReportMandatoryIe.ibssParamPresent) + { + if (freeBytes < (1 + 1 + SIR_MAC_IBSS_PARAM_SET_EID_MAX)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy IBSS IE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_IBSS_PARAM_SET_EID; + pos++; + *pos = SIR_MAC_IBSS_PARAM_SET_EID_MAX; + pos++; + vos_mem_copy(pos, + (tANI_U8*)&eseBcnReportMandatoryIe.ibssParamSet.atim, + SIR_MAC_IBSS_PARAM_SET_EID_MAX); + pos += SIR_MAC_IBSS_PARAM_SET_EID_MAX; + freeBytes -= (1 + 1 + SIR_MAC_IBSS_PARAM_SET_EID_MAX); + } + + /* Fill TIM IE */ + if (eseBcnReportMandatoryIe.timPresent) + { + if (freeBytes < (1 + 1 + SIR_MAC_TIM_EID_MIN)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy TIM IE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_TIM_EID; + pos++; + *pos = SIR_MAC_TIM_EID_MIN; + pos++; + vos_mem_copy(pos, + (tANI_U8*)&eseBcnReportMandatoryIe.tim, + SIR_MAC_TIM_EID_MIN); + pos += SIR_MAC_TIM_EID_MIN; + freeBytes -= (1 + 1 + SIR_MAC_TIM_EID_MIN); + } + + /* Fill RM Capability IE */ + if (eseBcnReportMandatoryIe.rrmPresent) + { + if (freeBytes < (1 + 1 + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX)) + { + limLog(pMac, LOGP, FL("Insufficient memory to copy RRM IE")); + retStatus = eSIR_FAILURE; + goto err_bcnrep; + } + *pos = SIR_MAC_RM_ENABLED_CAPABILITY_EID; + pos++; + *pos = SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX; + pos++; + vos_mem_copy(pos, + (tANI_U8*)&eseBcnReportMandatoryIe.rmEnabledCapabilities, + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX); + freeBytes -= (1 + 1 + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX); + } + + if (freeBytes != 0) + { + limLog(pMac, LOGP, FL("Mismatch in allocation and copying of IE in Bcn Rep")); + retStatus = eSIR_FAILURE; + } + +err_bcnrep: + /* The message counter would not be incremented in case of + * returning failure and hence next time, this function gets + * called, it would be using the same msg ctr for a different + * BSS.So, it is good to clear the memory allocated for a BSS + * that is returning failure.On success, the caller would take + * care of freeing up the memory*/ + if (retStatus == eSIR_FAILURE) + { + vos_mem_free(*outIeBuf); + *outIeBuf = NULL; + } + + vos_mem_free(pBies); + return retStatus; +} + +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +tSirRetStatus +sirParseBeaconIE(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeaconStruct, + tANI_U8 *pPayload, + tANI_U32 nPayload) +{ + tDot11fBeaconIEs *pBies; + tANI_U32 status; + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pBeaconStruct, sizeof(tSirProbeRespBeacon), 0 ); + + pBies = vos_mem_malloc(sizeof(tDot11fBeaconIEs)); + if ( NULL == pBies ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + // delegate to the framesc-generated code, + status = dot11fUnpackBeaconIEs( pMac, pPayload, nPayload, pBies ); + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse Beacon IEs (0x%08x, %d bytes):"), + status, nPayload); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload);) + vos_mem_free(pBies); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking Beacon IEs (0x%08x, %d bytes):"), + status, nPayload); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload);) + } + + // & "transliterate" from a 'tDot11fBeaconIEs' to a 'tSirProbeRespBeacon'... + if ( ! pBies->SSID.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));) + } + else + { + pBeaconStruct->ssidPresent = 1; + ConvertSSID( pMac, &pBeaconStruct->ssId, &pBies->SSID ); + } + + if ( ! pBies->SuppRates.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE Supported Rates not present!"));) + } + else + { + pBeaconStruct->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pBeaconStruct->supportedRates, &pBies->SuppRates ); + } + + if ( pBies->ExtSuppRates.present ) + { + pBeaconStruct->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pBeaconStruct->extendedRates, &pBies->ExtSuppRates ); + } + + if ( pBies->CFParams.present ) + { + pBeaconStruct->cfPresent = 1; + ConvertCFParams( pMac, &pBeaconStruct->cfParamSet, &pBies->CFParams ); + } + + if ( pBies->TIM.present ) + { + pBeaconStruct->timPresent = 1; + ConvertTIM( pMac, &pBeaconStruct->tim, &pBies->TIM ); + } + + if ( pBies->Country.present ) + { + pBeaconStruct->countryInfoPresent = 1; + ConvertCountry( pMac, &pBeaconStruct->countryInfoParam, &pBies->Country ); + } + + // 11h IEs + if(pBies->TPCReport.present) + { + pBeaconStruct->tpcReportPresent = 1; + vos_mem_copy( &pBeaconStruct->tpcReport, + &pBies->TPCReport, + sizeof( tDot11fIETPCReport)); + } + + if(pBies->PowerConstraints.present) + { + pBeaconStruct->powerConstraintPresent = 1; + vos_mem_copy( &pBeaconStruct->localPowerConstraint, + &pBies->PowerConstraints, + sizeof(tDot11fIEPowerConstraints)); + } +#ifdef FEATURE_WLAN_ESE + if (pBies->ESEVersion.present) { + pBeaconStruct->is_ese_ver_ie_present = 1; + } + if(pBies->ESETxmitPower.present) + { + pBeaconStruct->eseTxPwr.present = 1; + pBeaconStruct->eseTxPwr.power_limit = pBies->ESETxmitPower.power_limit; + } + if (pBies->QBSSLoad.present) + { + vos_mem_copy( &pBeaconStruct->QBSSLoad, &pBies->QBSSLoad, sizeof(tDot11fIEQBSSLoad)); + } +#endif + + if ( pBies->EDCAParamSet.present ) + { + pBeaconStruct->edcaPresent = 1; + ConvertEDCAParam( pMac, &pBeaconStruct->edcaParams, &pBies->EDCAParamSet ); + } + + // QOS Capabilities: + if ( pBies->QOSCapsAp.present ) + { + pBeaconStruct->qosCapabilityPresent = 1; + ConvertQOSCaps( pMac, &pBeaconStruct->qosCapability, &pBies->QOSCapsAp ); + } + + + + if ( pBies->ChanSwitchAnn.present ) + { + pBeaconStruct->channelSwitchPresent = 1; + vos_mem_copy( &pBeaconStruct->channelSwitchIE, &pBies->ChanSwitchAnn, + sizeof(pBeaconStruct->channelSwitchIE)); + } + + if (pBies->SuppOperatingClasses.present) { + pBeaconStruct->supp_operating_class_present = 1; + vos_mem_copy(&pBeaconStruct->supp_operating_classes, + &pBies->SuppOperatingClasses, + sizeof(tDot11fIESuppOperatingClasses)); + } + + if (pBies->ext_chan_switch_ann.present) { + pBeaconStruct->ext_chan_switch_present = 1; + vos_mem_copy(&pBeaconStruct->ext_chan_switch, &pBies->ext_chan_switch_ann, + sizeof(tDot11fIEext_chan_switch_ann)); + } + + if (pBies->sec_chan_offset_ele.present) { + pBeaconStruct->sec_chan_offset_present = 1; + vos_mem_copy(&pBeaconStruct->sec_chan_offset, &pBies->sec_chan_offset_ele, + sizeof(pBeaconStruct->sec_chan_offset)); + } + + if ( pBies->Quiet.present ) + { + pBeaconStruct->quietIEPresent = 1; + vos_mem_copy( &pBeaconStruct->quietIE, &pBies->Quiet, sizeof(tDot11fIEQuiet) ); + } + + if ( pBies->HTCaps.present ) + { + vos_mem_copy( &pBeaconStruct->HTCaps, &pBies->HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if ( pBies->HTInfo.present ) + { + vos_mem_copy( &pBeaconStruct->HTInfo, &pBies->HTInfo, sizeof( tDot11fIEHTInfo ) ); + } + + if ( pBies->DSParams.present ) + { + pBeaconStruct->dsParamsPresent = 1; + pBeaconStruct->channelNumber = pBies->DSParams.curr_channel; + } + else if(pBies->HTInfo.present) + { + pBeaconStruct->channelNumber = pBies->HTInfo.primaryChannel; + } + + if ( pBies->RSN.present ) + { + pBeaconStruct->rsnPresent = 1; + ConvertRSN( pMac, &pBeaconStruct->rsn, &pBies->RSN ); + } + + if ( pBies->WPA.present ) + { + pBeaconStruct->wpaPresent = 1; + ConvertWPA( pMac, &pBeaconStruct->wpa, &pBies->WPA ); + } + + if ( pBies->WMMParams.present ) + { + pBeaconStruct->wmeEdcaPresent = 1; + ConvertWMMParams( pMac, &pBeaconStruct->edcaParams, &pBies->WMMParams ); + } + + if ( pBies->WMMInfoAp.present ) + { + pBeaconStruct->wmeInfoPresent = 1; + } + + if ( pBies->WMMCaps.present ) + { + pBeaconStruct->wsmCapablePresent = 1; + } + + + if ( pBies->ERPInfo.present ) + { + pBeaconStruct->erpPresent = 1; + ConvertERPInfo( pMac, &pBeaconStruct->erpIEInfo, &pBies->ERPInfo ); + } + +#ifdef WLAN_FEATURE_11AC + if ( pBies->VHTCaps.present ) + { + pBeaconStruct->VHTCaps.present = 1; + vos_mem_copy( &pBeaconStruct->VHTCaps, &pBies->VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + } + if ( pBies->VHTOperation.present ) + { + pBeaconStruct->VHTOperation.present = 1; + vos_mem_copy( &pBeaconStruct->VHTOperation, &pBies->VHTOperation, + sizeof( tDot11fIEVHTOperation) ); + } + if ( pBies->VHTExtBssLoad.present ) + { + pBeaconStruct->VHTExtBssLoad.present = 1; + vos_mem_copy( &pBeaconStruct->VHTExtBssLoad, &pBies->VHTExtBssLoad, + sizeof( tDot11fIEVHTExtBssLoad) ); + } + if( pBies->OperatingMode.present) + { + pBeaconStruct->OperatingMode.present = 1; + vos_mem_copy( &pBeaconStruct->OperatingMode, &pBies->OperatingMode, + sizeof( tDot11fIEOperatingMode) ); + } +#endif + + if( pBies->MobilityDomain.present) + { + pBeaconStruct->mdiePresent = 1; + vos_mem_copy( pBeaconStruct->mdie, &pBies->MobilityDomain.MDID, SIR_MDIE_SIZE); + } + + pBeaconStruct->Vendor1IEPresent = pBies->Vendor1IE.present; + pBeaconStruct->Vendor2IEPresent = pBies->Vendor2IE.present; + pBeaconStruct->Vendor3IEPresent = pBies->Vendor3IE.present; + + vos_mem_free(pBies); + return eSIR_SUCCESS; +} // End sirParseBeaconIE. + +tSirRetStatus +sirConvertBeaconFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tpSirProbeRespBeacon pBeaconStruct) +{ + tDot11fBeacon *pBeacon; + tANI_U32 status, nPayload; + tANI_U8 *pPayload; + tpSirMacMgmtHdr pHdr; + tANI_U8 mappedRXCh; + tANI_U8 rfBand; + + pPayload = WDA_GET_RX_MPDU_DATA( pFrame ); + nPayload = WDA_GET_RX_PAYLOAD_LEN( pFrame ); + pHdr = WDA_GET_RX_MAC_HEADER( pFrame ); + mappedRXCh = WDA_GET_RX_CH( pFrame ); + rfBand = WDA_GET_RX_RFBAND( pFrame ); + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pBeaconStruct, sizeof(tSirProbeRespBeacon), 0 ); + + pBeacon = vos_mem_malloc(sizeof(tDot11fBeacon)); + if ( NULL == pBeacon ) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) + { + limLog(pMac, LOGE, FL("Failed to allocate memory")); + return eSIR_FAILURE; + } + + vos_mem_set( ( tANI_U8* )pBeacon, sizeof(tDot11fBeacon), 0 ); + + // get the MAC address out of the BD, + vos_mem_copy( pBeaconStruct->bssid, pHdr->sa, 6 ); + + // delegate to the framesc-generated code, + status = dot11fUnpackBeacon( pMac, pPayload, nPayload, pBeacon ); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, FL("Failed to parse Beacon IEs (0x%08x, %d bytes):"), + status, nPayload); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload);) + vos_mem_free(pBeacon); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while unpacking Beacon IEs (0x%08x, %d bytes):"), + status, nPayload); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload);) + } + + // & "transliterate" from a 'tDot11fBeacon' to a 'tSirProbeRespBeacon'... + // Timestamp + vos_mem_copy( ( tANI_U8* )pBeaconStruct->timeStamp, ( tANI_U8* )&pBeacon->TimeStamp, + sizeof(tSirMacTimeStamp) ); + + // Beacon Interval + pBeaconStruct->beaconInterval = pBeacon->BeaconInterval.interval; + + // Capabilities + pBeaconStruct->capabilityInfo.ess = pBeacon->Capabilities.ess; + pBeaconStruct->capabilityInfo.ibss = pBeacon->Capabilities.ibss; + pBeaconStruct->capabilityInfo.cfPollable = pBeacon->Capabilities.cfPollable; + pBeaconStruct->capabilityInfo.cfPollReq = pBeacon->Capabilities.cfPollReq; + pBeaconStruct->capabilityInfo.privacy = pBeacon->Capabilities.privacy; + pBeaconStruct->capabilityInfo.shortPreamble = pBeacon->Capabilities.shortPreamble; + pBeaconStruct->capabilityInfo.pbcc = pBeacon->Capabilities.pbcc; + pBeaconStruct->capabilityInfo.channelAgility = pBeacon->Capabilities.channelAgility; + pBeaconStruct->capabilityInfo.spectrumMgt = pBeacon->Capabilities.spectrumMgt; + pBeaconStruct->capabilityInfo.qos = pBeacon->Capabilities.qos; + pBeaconStruct->capabilityInfo.shortSlotTime = pBeacon->Capabilities.shortSlotTime; + pBeaconStruct->capabilityInfo.apsd = pBeacon->Capabilities.apsd; + pBeaconStruct->capabilityInfo.rrm = pBeacon->Capabilities.rrm; + pBeaconStruct->capabilityInfo.dsssOfdm = pBeacon->Capabilities.dsssOfdm; + pBeaconStruct->capabilityInfo.delayedBA = pBeacon->Capabilities.delayedBA; + pBeaconStruct->capabilityInfo.immediateBA = pBeacon->Capabilities.immediateBA; + + if ( ! pBeacon->SSID.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE SSID not present!"));) + } + else + { + pBeaconStruct->ssidPresent = 1; + ConvertSSID( pMac, &pBeaconStruct->ssId, &pBeacon->SSID ); + } + + if ( ! pBeacon->SuppRates.present ) + { + PELOGW(limLog(pMac, LOGW, FL("Mandatory IE Supported Rates not present!"));) + } + else + { + pBeaconStruct->suppRatesPresent = 1; + ConvertSuppRates( pMac, &pBeaconStruct->supportedRates, &pBeacon->SuppRates ); + } + + if ( pBeacon->ExtSuppRates.present ) + { + pBeaconStruct->extendedRatesPresent = 1; + ConvertExtSuppRates( pMac, &pBeaconStruct->extendedRates, &pBeacon->ExtSuppRates ); + } + + + if ( pBeacon->CFParams.present ) + { + pBeaconStruct->cfPresent = 1; + ConvertCFParams( pMac, &pBeaconStruct->cfParamSet, &pBeacon->CFParams ); + } + + if ( pBeacon->TIM.present ) + { + pBeaconStruct->timPresent = 1; + ConvertTIM( pMac, &pBeaconStruct->tim, &pBeacon->TIM ); + } + + if ( pBeacon->Country.present ) + { + pBeaconStruct->countryInfoPresent = 1; + ConvertCountry( pMac, &pBeaconStruct->countryInfoParam, &pBeacon->Country ); + } + + // QOS Capabilities: + if ( pBeacon->QOSCapsAp.present ) + { + pBeaconStruct->qosCapabilityPresent = 1; + ConvertQOSCaps( pMac, &pBeaconStruct->qosCapability, &pBeacon->QOSCapsAp ); + } + + if ( pBeacon->EDCAParamSet.present ) + { + pBeaconStruct->edcaPresent = 1; + ConvertEDCAParam( pMac, &pBeaconStruct->edcaParams, &pBeacon->EDCAParamSet ); + } + + if ( pBeacon->ChanSwitchAnn.present ) + { + pBeaconStruct->channelSwitchPresent = 1; + vos_mem_copy( &pBeaconStruct->channelSwitchIE, &pBeacon->ChanSwitchAnn, + sizeof(pBeaconStruct->channelSwitchIE) ); + } + + if (pBeacon->ext_chan_switch_ann.present) { + pBeaconStruct->ext_chan_switch_present = 1; + vos_mem_copy(&pBeaconStruct->ext_chan_switch, &pBeacon->ext_chan_switch_ann, + sizeof(tDot11fIEext_chan_switch_ann)); + } + + if (pBeacon->sec_chan_offset_ele.present) { + pBeaconStruct->sec_chan_offset_present = 1; + vos_mem_copy(&pBeaconStruct->sec_chan_offset, &pBeacon->sec_chan_offset_ele, + sizeof(pBeaconStruct->sec_chan_offset)); + } + + if( pBeacon->TPCReport.present) + { + pBeaconStruct->tpcReportPresent = 1; + vos_mem_copy( &pBeaconStruct->tpcReport, &pBeacon->TPCReport, + sizeof(tDot11fIETPCReport)); + } + + if( pBeacon->PowerConstraints.present) + { + pBeaconStruct->powerConstraintPresent = 1; + vos_mem_copy( &pBeaconStruct->localPowerConstraint, &pBeacon->PowerConstraints, + sizeof(tDot11fIEPowerConstraints)); + } + + if ( pBeacon->Quiet.present ) + { + pBeaconStruct->quietIEPresent = 1; + vos_mem_copy( &pBeaconStruct->quietIE, &pBeacon->Quiet, sizeof(tDot11fIEQuiet)); + } + + if ( pBeacon->HTCaps.present ) + { + vos_mem_copy( &pBeaconStruct->HTCaps, &pBeacon->HTCaps, sizeof( tDot11fIEHTCaps ) ); + } + + if ( pBeacon->HTInfo.present ) + { + vos_mem_copy( &pBeaconStruct->HTInfo, &pBeacon->HTInfo, sizeof( tDot11fIEHTInfo) ); + + } + + if ( pBeacon->DSParams.present ) + { + pBeaconStruct->dsParamsPresent = 1; + pBeaconStruct->channelNumber = pBeacon->DSParams.curr_channel; + } + else if(pBeacon->HTInfo.present) + { + pBeaconStruct->channelNumber = pBeacon->HTInfo.primaryChannel; + } + else + { + if ((!rfBand) || IS_5G_BAND(rfBand)) + pBeaconStruct->channelNumber = limUnmapChannel(mappedRXCh); + else if (IS_24G_BAND(rfBand)) + pBeaconStruct->channelNumber = mappedRXCh; + else + { + /*Only 0, 1, 2 are expected values for RF band from FW + * if FW fixes are not present then rf band value will + * be 0, else either 1 or 2 are expected from FW, 3 is + * not expected from FW */ + PELOGE(limLog(pMac, LOGE, + FL("Channel info is not present in Beacon and" + " mapping is not done correctly"));) + pBeaconStruct->channelNumber = mappedRXCh; + } + } + + if ( pBeacon->RSN.present ) + { + pBeaconStruct->rsnPresent = 1; + ConvertRSN( pMac, &pBeaconStruct->rsn, &pBeacon->RSN ); + } + + if ( pBeacon->WPA.present ) + { + pBeaconStruct->wpaPresent = 1; + ConvertWPA( pMac, &pBeaconStruct->wpa, &pBeacon->WPA ); + } + + if ( pBeacon->WMMParams.present ) + { + pBeaconStruct->wmeEdcaPresent = 1; + ConvertWMMParams( pMac, &pBeaconStruct->edcaParams, &pBeacon->WMMParams ); + PELOG1(limLog(pMac, LOG1, FL("WMM Parameter present in Beacon Frame!")); + __printWMMParams(pMac, &pBeacon->WMMParams); ) + } + + if ( pBeacon->WMMInfoAp.present ) + { + pBeaconStruct->wmeInfoPresent = 1; + PELOG1(limLog(pMac, LOG1, FL("WMM Info present in Beacon Frame!"));) + } + + if ( pBeacon->WMMCaps.present ) + { + pBeaconStruct->wsmCapablePresent = 1; + } + + if ( pBeacon->ERPInfo.present ) + { + pBeaconStruct->erpPresent = 1; + ConvertERPInfo( pMac, &pBeaconStruct->erpIEInfo, &pBeacon->ERPInfo ); + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pBeacon->MobilityDomain.present) + { + // MobilityDomain + pBeaconStruct->mdiePresent = 1; + vos_mem_copy( (tANI_U8 *)&(pBeaconStruct->mdie[0]), + (tANI_U8 *)&(pBeacon->MobilityDomain.MDID), sizeof(tANI_U16) ); + pBeaconStruct->mdie[2] = ((pBeacon->MobilityDomain.overDSCap << 0) | (pBeacon->MobilityDomain.resourceReqCap << 1)); + + } +#endif + +#ifdef FEATURE_WLAN_ESE + if (pBeacon->ESEVersion.present) { + pBeaconStruct->is_ese_ver_ie_present = 1; + } + if (pBeacon->ESETxmitPower.present) + { + /* copy ESE TPC info element */ + pBeaconStruct->eseTxPwr.present = 1; + vos_mem_copy( &pBeaconStruct->eseTxPwr, + &pBeacon->ESETxmitPower, + sizeof(tDot11fIEESETxmitPower)); + } + if (pBeacon->QBSSLoad.present) + { + vos_mem_copy(&pBeaconStruct->QBSSLoad, + &pBeacon->QBSSLoad, + sizeof(tDot11fIEQBSSLoad)); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if ( pBeacon->VHTCaps.present ) + { + vos_mem_copy( &pBeaconStruct->VHTCaps, &pBeacon->VHTCaps, sizeof( tDot11fIEVHTCaps ) ); + } + if ( pBeacon->VHTOperation.present ) + { + vos_mem_copy( &pBeaconStruct->VHTOperation, &pBeacon->VHTOperation, + sizeof( tDot11fIEVHTOperation) ); + } + if ( pBeacon->VHTExtBssLoad.present ) + { + vos_mem_copy( &pBeaconStruct->VHTExtBssLoad, &pBeacon->VHTExtBssLoad, + sizeof( tDot11fIEVHTExtBssLoad) ); + } + if(pBeacon->OperatingMode.present) + { + vos_mem_copy( &pBeaconStruct->OperatingMode, &pBeacon->OperatingMode, + sizeof( tDot11fIEOperatingMode) ); + } + if(pBeacon->WiderBWChanSwitchAnn.present) + { + pBeaconStruct->WiderBWChanSwitchAnnPresent = 1; + vos_mem_copy( &pBeaconStruct->WiderBWChanSwitchAnn, &pBeacon->WiderBWChanSwitchAnn, + sizeof( tDot11fIEWiderBWChanSwitchAnn)); + } +#endif + + /* IBSS Peer Params */ + if(pBeacon->IBSSParams.present) + { + pBeaconStruct->IBSSParams.present = 1; + vos_mem_copy( &pBeaconStruct->IBSSParams, &pBeacon->IBSSParams, + sizeof( tDot11fIEIBSSParams )); + } + + pBeaconStruct->Vendor1IEPresent = pBeacon->Vendor1IE.present; + pBeaconStruct->Vendor2IEPresent = pBeacon->Vendor2IE.present; + pBeaconStruct->Vendor3IEPresent = pBeacon->Vendor3IE.present; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if(pBeacon->QComVendorIE.present) { + pBeaconStruct->AvoidChannelIE.present = + pBeacon->QComVendorIE.present; + pBeaconStruct->AvoidChannelIE.type = + pBeacon->QComVendorIE.type; + pBeaconStruct->AvoidChannelIE.channel = + pBeacon->QComVendorIE.channel; + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + vos_mem_free(pBeacon); + return eSIR_SUCCESS; + +} // End sirConvertBeaconFrame2Struct. + +tSirRetStatus +sirConvertAuthFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tpSirMacAuthFrameBody pAuth) +{ + static tDot11fAuthentication auth; + tANI_U32 status; + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pAuth, sizeof(tSirMacAuthFrameBody), 0 ); + + // delegate to the framesc-generated code, + status = dot11fUnpackAuthentication( pMac, pFrame, nFrame, &auth ); + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, FL("Failed to parse an Authentication frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("Warnings while unpacking an Auth frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fAuthentication' to a 'tSirMacAuthFrameBody'... + pAuth->authAlgoNumber = auth.AuthAlgo.algo; + pAuth->authTransactionSeqNumber = auth.AuthSeqNo.no; + pAuth->authStatusCode = auth.Status.status; + + if ( auth.ChallengeText.present ) + { + pAuth->type = SIR_MAC_CHALLENGE_TEXT_EID; + pAuth->length = auth.ChallengeText.num_text; + vos_mem_copy( pAuth->challengeText, auth.ChallengeText.text, auth.ChallengeText.num_text ); + } + + return eSIR_SUCCESS; + +} // End sirConvertAuthFrame2Struct. + +tSirRetStatus +sirConvertAddtsReq2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tSirAddtsReqInfo *pAddTs) +{ + tDot11fAddTSRequest addts = {{0}}; + tDot11fWMMAddTSRequest wmmaddts = {{0}}; + tANI_U8 j; + tANI_U16 i; + tANI_U32 status; + + if ( SIR_MAC_QOS_ADD_TS_REQ != *( pFrame + 1 ) ) + { + limLog( pMac, LOGE, FL("sirConvertAddtsReq2Struct invoked " + "with an Action of %d; this is not " + "supported & is probably an error."), + *( pFrame + 1 ) ); + return eSIR_FAILURE; + } + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pAddTs, sizeof(tSirAddtsReqInfo), 0 ); + + // delegate to the framesc-generated code, + switch ( *pFrame ) + { + case SIR_MAC_ACTION_QOS_MGMT: + status = dot11fUnpackAddTSRequest( pMac, pFrame, nFrame, &addts ); + break; + case SIR_MAC_ACTION_WME: + status = dot11fUnpackWMMAddTSRequest( pMac, pFrame, nFrame, &wmmaddts ); + break; + default: + limLog( pMac, LOGE, FL("sirConvertAddtsReq2Struct invoked " + "with a Category of %d; this is not" + " supported & is probably an error."), + *pFrame ); + return eSIR_FAILURE; + } + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse an Add TS Request frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, FL("There were warnings while unpacking an Add TS Request frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fAddTSRequest' or a + // 'tDot11WMMAddTSRequest' to a 'tSirMacAddtsReqInfo'... + if ( SIR_MAC_ACTION_QOS_MGMT == *pFrame ) + { + pAddTs->dialogToken = addts.DialogToken.token; + + if ( addts.TSPEC.present ) + { + ConvertTSPEC( pMac, &pAddTs->tspec, &addts.TSPEC ); + } + else + { + limLog(pMac, LOGE, + FL("Mandatory TSPEC element missing in Add TS Request.")); + return eSIR_FAILURE; + } + + if ( addts.num_TCLAS ) + { + pAddTs->numTclas = (tANI_U8)addts.num_TCLAS; + + for ( i = 0U; i < addts.num_TCLAS; ++i ) + { + if ( eSIR_SUCCESS != ConvertTCLAS( pMac, &( pAddTs->tclasInfo[i] ), &( addts.TCLAS[i] ) ) ) + { + limLog(pMac, LOGE, FL("Failed to convert a TCLAS IE.")); + return eSIR_FAILURE; + } + } + } + + if ( addts.TCLASSPROC.present ) + { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.TCLASSPROC.processing; + } + + if ( addts.WMMTSPEC.present ) + { + pAddTs->wsmTspecPresent = 1; + ConvertWMMTSPEC( pMac, &pAddTs->tspec, &addts.WMMTSPEC ); + } + + if ( addts.num_WMMTCLAS ) + { + j = (tANI_U8)(pAddTs->numTclas + addts.num_WMMTCLAS); + if ( SIR_MAC_TCLASIE_MAXNUM > j ) j = SIR_MAC_TCLASIE_MAXNUM; + + for ( i = pAddTs->numTclas; i < j; ++i ) + { + if ( eSIR_SUCCESS != ConvertWMMTCLAS( pMac, &( pAddTs->tclasInfo[i] ), &( addts.WMMTCLAS[i] ) ) ) + { + limLog(pMac, LOGE, FL("Failed to convert a TCLAS IE.")); + return eSIR_FAILURE; + } + } + } + + if ( addts.WMMTCLASPROC.present ) + { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.WMMTCLASPROC.processing; + } + + if ( 1 < pAddTs->numTclas && ( ! pAddTs->tclasProcPresent ) ) + { + limLog(pMac, LOGE, FL("%d TCLAS IE but not TCLASPROC IE."), + pAddTs->numTclas); + return eSIR_FAILURE; + } + } + else + { + pAddTs->dialogToken = wmmaddts.DialogToken.token; + + if ( wmmaddts.WMMTSPEC.present ) + { + pAddTs->wmeTspecPresent = 1; + ConvertWMMTSPEC( pMac, &pAddTs->tspec, &wmmaddts.WMMTSPEC ); + } + else + { + limLog(pMac, LOGE, FL("Mandatory WME TSPEC element missing!")); + return eSIR_FAILURE; + } + } + + return eSIR_SUCCESS; + +} // End sirConvertAddtsReq2Struct. + +tSirRetStatus +sirConvertAddtsRsp2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tSirAddtsRspInfo *pAddTs) +{ + tDot11fAddTSResponse addts = {{0}}; + tDot11fWMMAddTSResponse wmmaddts = {{0}}; + tANI_U8 j; + tANI_U16 i; + tANI_U32 status; + + if ( SIR_MAC_QOS_ADD_TS_RSP != *( pFrame + 1 ) ) + { + limLog( pMac, LOGE, FL("sirConvertAddtsRsp2Struct invoked " + "with an Action of %d; this is not " + "supported & is probably an error."), + *( pFrame + 1 ) ); + return eSIR_FAILURE; + } + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pAddTs, sizeof(tSirAddtsRspInfo), 0 ); + vos_mem_set( ( tANI_U8* )&addts, sizeof(tDot11fAddTSResponse), 0 ); + vos_mem_set( ( tANI_U8* )&wmmaddts, sizeof(tDot11fWMMAddTSResponse), 0 ); + + + // delegate to the framesc-generated code, + switch ( *pFrame ) + { + case SIR_MAC_ACTION_QOS_MGMT: + status = dot11fUnpackAddTSResponse( pMac, pFrame, nFrame, &addts ); + break; + case SIR_MAC_ACTION_WME: + status = dot11fUnpackWMMAddTSResponse( pMac, pFrame, nFrame, &wmmaddts ); + break; + default: + limLog( pMac, LOGE, FL("sirConvertAddtsRsp2Struct invoked " + "with a Category of %d; this is not" + " supported & is probably an error."), + *pFrame ); + return eSIR_FAILURE; + } + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, FL("Failed to parse an Add TS Response frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + limLog(pMac, LOGW, + FL("There were warnings while unpacking an Add TS Response frame (0x%08x,%d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fAddTSResponse' or a + // 'tDot11WMMAddTSResponse' to a 'tSirMacAddtsRspInfo'... + if ( SIR_MAC_ACTION_QOS_MGMT == *pFrame ) + { + pAddTs->dialogToken = addts.DialogToken.token; + pAddTs->status = ( tSirMacStatusCodes )addts.Status.status; + + if ( addts.TSDelay.present ) + { + ConvertTSDelay( pMac, &pAddTs->delay, &addts.TSDelay ); + } + + // TS Delay is present iff status indicates its presence + if ( eSIR_MAC_TS_NOT_CREATED_STATUS == pAddTs->status && ! addts.TSDelay.present ) + { + limLog(pMac, LOGW, FL("Missing TSDelay IE.")); + } + + if ( addts.TSPEC.present ) + { + ConvertTSPEC( pMac, &pAddTs->tspec, &addts.TSPEC ); + } + else + { + limLog(pMac, LOGE, + FL("Mandatory TSPEC element missing in Add TS Response.")); + return eSIR_FAILURE; + } + + if ( addts.num_TCLAS ) + { + pAddTs->numTclas = (tANI_U8)addts.num_TCLAS; + + for ( i = 0U; i < addts.num_TCLAS; ++i ) + { + if ( eSIR_SUCCESS != ConvertTCLAS( pMac, &( pAddTs->tclasInfo[i] ), &( addts.TCLAS[i] ) ) ) + { + limLog(pMac, LOGE, + FL("Failed to convert a TCLAS IE.")); + return eSIR_FAILURE; + } + } + } + + if ( addts.TCLASSPROC.present ) + { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.TCLASSPROC.processing; + } +#ifdef FEATURE_WLAN_ESE + if(addts.ESETrafStrmMet.present) + { + pAddTs->tsmPresent = 1; + vos_mem_copy(&pAddTs->tsmIE.tsid, + &addts.ESETrafStrmMet.tsid,sizeof(tSirMacESETSMIE)); + } +#endif + if ( addts.Schedule.present ) + { + pAddTs->schedulePresent = 1; + ConvertSchedule( pMac, &pAddTs->schedule, &addts.Schedule ); + } + + if ( addts.WMMSchedule.present ) + { + pAddTs->schedulePresent = 1; + ConvertWMMSchedule( pMac, &pAddTs->schedule, &addts.WMMSchedule ); + } + + if ( addts.WMMTSPEC.present ) + { + pAddTs->wsmTspecPresent = 1; + ConvertWMMTSPEC( pMac, &pAddTs->tspec, &addts.WMMTSPEC ); + } + + if ( addts.num_WMMTCLAS ) + { + j = (tANI_U8)(pAddTs->numTclas + addts.num_WMMTCLAS); + if ( SIR_MAC_TCLASIE_MAXNUM > j ) j = SIR_MAC_TCLASIE_MAXNUM; + + for ( i = pAddTs->numTclas; i < j; ++i ) + { + if ( eSIR_SUCCESS != ConvertWMMTCLAS( pMac, &( pAddTs->tclasInfo[i] ), &( addts.WMMTCLAS[i] ) ) ) + { + limLog(pMac, LOGE, FL("Failed to convert a TCLAS IE.")); + return eSIR_FAILURE; + } + } + } + + if ( addts.WMMTCLASPROC.present ) + { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.WMMTCLASPROC.processing; + } + + if ( 1 < pAddTs->numTclas && ( ! pAddTs->tclasProcPresent ) ) + { + limLog(pMac, LOGE, + FL("%d TCLAS IE but not TCLASPROC IE."), + pAddTs->numTclas); + return eSIR_FAILURE; + } + } + else + { + pAddTs->dialogToken = wmmaddts.DialogToken.token; + pAddTs->status = ( tSirMacStatusCodes )wmmaddts.StatusCode.statusCode; + + if ( wmmaddts.WMMTSPEC.present ) + { + pAddTs->wmeTspecPresent = 1; + ConvertWMMTSPEC( pMac, &pAddTs->tspec, &wmmaddts.WMMTSPEC ); + } + else + { + limLog(pMac, LOGE, + FL("Mandatory WME TSPEC element missing!")); + return eSIR_FAILURE; + } + +#ifdef FEATURE_WLAN_ESE + if(wmmaddts.ESETrafStrmMet.present) + { + pAddTs->tsmPresent = 1; + vos_mem_copy(&pAddTs->tsmIE.tsid, + &wmmaddts.ESETrafStrmMet.tsid,sizeof(tSirMacESETSMIE)); + } +#endif + + } + + return eSIR_SUCCESS; + +} // End sirConvertAddtsRsp2Struct. + +tSirRetStatus +sirConvertDeltsReq2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tSirDeltsReqInfo *pDelTs) +{ + tDot11fDelTS delts = {{0}}; + tDot11fWMMDelTS wmmdelts = {{0}}; + tANI_U32 status; + + if ( SIR_MAC_QOS_DEL_TS_REQ != *( pFrame + 1 ) ) + { + limLog( pMac, LOGE, FL("sirConvertDeltsRsp2Struct invoked " + "with an Action of %d; this is not " + "supported & is probably an error."), + *( pFrame + 1 ) ); + return eSIR_FAILURE; + } + + // Zero-init our [out] parameter, + vos_mem_set( ( tANI_U8* )pDelTs, sizeof(tSirDeltsReqInfo), 0 ); + + // delegate to the framesc-generated code, + switch ( *pFrame ) + { + case SIR_MAC_ACTION_QOS_MGMT: + status = dot11fUnpackDelTS( pMac, pFrame, nFrame, &delts ); + break; + case SIR_MAC_ACTION_WME: + status = dot11fUnpackWMMDelTS( pMac, pFrame, nFrame, &wmmdelts ); + break; + default: + limLog( pMac, LOGE, FL("sirConvertDeltsRsp2Struct invoked " + "with a Category of %d; this is not" + " supported & is probably an error."), + *pFrame ); + return eSIR_FAILURE; + } + + if ( DOT11F_FAILED( status ) ) + { + limLog(pMac, LOGE, + FL("Failed to parse an Del TS Request frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + dot11fLog(pMac, LOGW, + FL("Warnings while unpacking an Del TS Req frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + + // & "transliterate" from a 'tDot11fDelTSResponse' or a + // 'tDot11WMMDelTSResponse' to a 'tSirMacDeltsReqInfo'... + if ( SIR_MAC_ACTION_QOS_MGMT == *pFrame ) + { + pDelTs->tsinfo.traffic.trafficType = (tANI_U16)delts.TSInfo.traffic_type; + pDelTs->tsinfo.traffic.tsid = (tANI_U16)delts.TSInfo.tsid; + pDelTs->tsinfo.traffic.direction = (tANI_U16)delts.TSInfo.direction; + pDelTs->tsinfo.traffic.accessPolicy = (tANI_U16)delts.TSInfo.access_policy; + pDelTs->tsinfo.traffic.aggregation = (tANI_U16)delts.TSInfo.aggregation; + pDelTs->tsinfo.traffic.psb = (tANI_U16)delts.TSInfo.psb; + pDelTs->tsinfo.traffic.userPrio = (tANI_U16)delts.TSInfo.user_priority; + pDelTs->tsinfo.traffic.ackPolicy = (tANI_U16)delts.TSInfo.tsinfo_ack_pol; + + pDelTs->tsinfo.schedule.schedule = (tANI_U8)delts.TSInfo.schedule; + } + else + { + if ( wmmdelts.WMMTSPEC.present ) + { + pDelTs->wmeTspecPresent = 1; + ConvertWMMTSPEC( pMac, &pDelTs->tspec, &wmmdelts.WMMTSPEC ); + } + else + { + dot11fLog(pMac, LOGE, + FL("Mandatory WME TSPEC element missing!")); + return eSIR_FAILURE; + } + } + + return eSIR_SUCCESS; + +} // End sirConvertDeltsReq2Struct. + +tSirRetStatus +sirConvertQosMapConfigureFrame2Struct(tpAniSirGlobal pMac, + tANI_U8 *pFrame, + tANI_U32 nFrame, + tSirQosMapSet *pQosMapSet) +{ + tDot11fQosMapConfigure mapConfigure; + tANI_U32 status; + status = dot11fUnpackQosMapConfigure(pMac, pFrame, nFrame, &mapConfigure); + if ( DOT11F_FAILED( status ) ) + { + dot11fLog(pMac, LOGE, + FL("Failed to parse Qos Map Config frame(0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( status ) ) + { + dot11fLog(pMac, LOGW, + FL("Warnings while unpacking Qos Map Configure frame (0x%08x, %d bytes):"), + status, nFrame); + PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) + } + pQosMapSet->present = mapConfigure.QosMapSet.present; + ConvertQosMapsetFrame(pMac->hHdd, pQosMapSet, &mapConfigure.QosMapSet); + limLogQosMapSet(pMac, pQosMapSet); + return eSIR_SUCCESS; +} + + + +void +PopulateDot11fTSPEC(tSirMacTspecIE *pOld, + tDot11fIETSPEC *pDot11f) +{ + pDot11f->traffic_type = pOld->tsinfo.traffic.trafficType; + pDot11f->tsid = pOld->tsinfo.traffic.tsid; + pDot11f->direction = pOld->tsinfo.traffic.direction; + pDot11f->access_policy = pOld->tsinfo.traffic.accessPolicy; + pDot11f->aggregation = pOld->tsinfo.traffic.aggregation; + pDot11f->psb = pOld->tsinfo.traffic.psb; + pDot11f->user_priority = pOld->tsinfo.traffic.userPrio; + pDot11f->tsinfo_ack_pol = pOld->tsinfo.traffic.ackPolicy; + pDot11f->schedule = pOld->tsinfo.schedule.schedule; + /* As defined in IEEE 802.11-2007, section 7.3.2.30 + * Nominal MSDU size: Bit[0:14]=Size, Bit[15]=Fixed + */ + pDot11f->size = ( pOld->nomMsduSz & 0x7fff ); + pDot11f->fixed = ( pOld->nomMsduSz & 0x8000 ) ? 1 : 0; + pDot11f->max_msdu_size = pOld->maxMsduSz; + pDot11f->min_service_int = pOld->minSvcInterval; + pDot11f->max_service_int = pOld->maxSvcInterval; + pDot11f->inactivity_int = pOld->inactInterval; + pDot11f->suspension_int = pOld->suspendInterval; + pDot11f->service_start_time = pOld->svcStartTime; + pDot11f->min_data_rate = pOld->minDataRate; + pDot11f->mean_data_rate = pOld->meanDataRate; + pDot11f->peak_data_rate = pOld->peakDataRate; + pDot11f->burst_size = pOld->maxBurstSz; + pDot11f->delay_bound = pOld->delayBound; + pDot11f->min_phy_rate = pOld->minPhyRate; + pDot11f->surplus_bw_allowance = pOld->surplusBw; + pDot11f->medium_time = pOld->mediumTime; + + pDot11f->present = 1; + +} // End PopulateDot11fTSPEC. + +void +PopulateDot11fWMMTSPEC(tSirMacTspecIE *pOld, + tDot11fIEWMMTSPEC *pDot11f) +{ + pDot11f->traffic_type = pOld->tsinfo.traffic.trafficType; + pDot11f->tsid = pOld->tsinfo.traffic.tsid; + pDot11f->direction = pOld->tsinfo.traffic.direction; + pDot11f->access_policy = pOld->tsinfo.traffic.accessPolicy; + pDot11f->aggregation = pOld->tsinfo.traffic.aggregation; + pDot11f->psb = pOld->tsinfo.traffic.psb; + pDot11f->user_priority = pOld->tsinfo.traffic.userPrio; + pDot11f->tsinfo_ack_pol = pOld->tsinfo.traffic.ackPolicy; + pDot11f->burst_size_defn = pOld->tsinfo.traffic.burstSizeDefn; + /* As defined in IEEE 802.11-2007, section 7.3.2.30 + * Nominal MSDU size: Bit[0:14]=Size, Bit[15]=Fixed + */ + pDot11f->size = ( pOld->nomMsduSz & 0x7fff ); + pDot11f->fixed = ( pOld->nomMsduSz & 0x8000 ) ? 1 : 0; + pDot11f->max_msdu_size = pOld->maxMsduSz; + pDot11f->min_service_int = pOld->minSvcInterval; + pDot11f->max_service_int = pOld->maxSvcInterval; + pDot11f->inactivity_int = pOld->inactInterval; + pDot11f->suspension_int = pOld->suspendInterval; + pDot11f->service_start_time = pOld->svcStartTime; + pDot11f->min_data_rate = pOld->minDataRate; + pDot11f->mean_data_rate = pOld->meanDataRate; + pDot11f->peak_data_rate = pOld->peakDataRate; + pDot11f->burst_size = pOld->maxBurstSz; + pDot11f->delay_bound = pOld->delayBound; + pDot11f->min_phy_rate = pOld->minPhyRate; + pDot11f->surplus_bw_allowance = pOld->surplusBw; + pDot11f->medium_time = pOld->mediumTime; + + pDot11f->version = 1; + pDot11f->present = 1; + +} // End PopulateDot11fWMMTSPEC. + +#if defined(FEATURE_WLAN_ESE) +// Fill the ESE version currently supported +void PopulateDot11fESEVersion(tDot11fIEESEVersion *pESEVersion) +{ + pESEVersion->present = 1; + pESEVersion->version = ESE_VERSION_SUPPORTED; +} +// Fill the ESE ie for the station. +// The State is Normal (1) +// The MBSSID for station is set to 0. +void PopulateDot11fESERadMgmtCap(tDot11fIEESERadMgmtCap *pESERadMgmtCap) +{ + pESERadMgmtCap->present = 1; + pESERadMgmtCap->mgmt_state = RM_STATE_NORMAL; + pESERadMgmtCap->mbssid_mask = 0; + pESERadMgmtCap->reserved = 0; +} +tSirRetStatus PopulateDot11fESECckmOpaque( tpAniSirGlobal pMac, + tpSirCCKMie pCCKMie, + tDot11fIEESECckmOpaque *pDot11f ) +{ + int idx; + if ( pCCKMie->length ) + { + if( 0 <= ( idx = FindIELocation( pMac, (tpSirRSNie)pCCKMie, + DOT11F_EID_ESECCKMOPAQUE ) ) ) + { + pDot11f->present = 1; + // Dont include OUI + pDot11f->num_data = pCCKMie->cckmIEdata[ idx + 1 ] - 4; + vos_mem_copy ( pDot11f->data, + pCCKMie->cckmIEdata + idx + 2 + 4, //EID,len,OUI + pCCKMie->cckmIEdata[ idx + 1 ] - 4 ); // Skip OUI + } + } + return eSIR_SUCCESS; +} // End PopulateDot11fESECckmOpaque. + +void PopulateDot11TSRSIE(tpAniSirGlobal pMac, + tSirMacESETSRSIE *pOld, + tDot11fIEESETrafStrmRateSet *pDot11f, + tANI_U8 rate_length) +{ + pDot11f->tsid = pOld->tsid; + vos_mem_copy(pDot11f->tsrates, pOld->rates,rate_length); + pDot11f->num_tsrates = rate_length; + pDot11f->present = 1; +} +#endif + + +tSirRetStatus +PopulateDot11fTCLAS(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, + tDot11fIETCLAS *pDot11f) +{ + pDot11f->user_priority = pOld->tclas.userPrio; + pDot11f->classifier_type = pOld->tclas.classifierType; + pDot11f->classifier_mask = pOld->tclas.classifierMask; + + switch ( pDot11f->classifier_type ) + { + case SIR_MAC_TCLASTYPE_ETHERNET: + vos_mem_copy( ( tANI_U8* )&pDot11f->info.EthParams.source, + ( tANI_U8* )&pOld->tclasParams.eth.srcAddr, 6 ); + vos_mem_copy( ( tANI_U8* )&pDot11f->info.EthParams.dest, + ( tANI_U8* )&pOld->tclasParams.eth.dstAddr, 6 ); + pDot11f->info.EthParams.type = pOld->tclasParams.eth.type; + break; + case SIR_MAC_TCLASTYPE_TCPUDPIP: + pDot11f->info.IpParams.version = pOld->version; + if ( SIR_MAC_TCLAS_IPV4 == pDot11f->info.IpParams.version ) + { + vos_mem_copy( pDot11f->info.IpParams.params. + IpV4Params.source, + pOld->tclasParams.ipv4.srcIpAddr, 4 ); + vos_mem_copy( pDot11f->info.IpParams.params. + IpV4Params.dest, + pOld->tclasParams.ipv4.dstIpAddr, 4 ); + pDot11f->info.IpParams.params.IpV4Params.src_port = + pOld->tclasParams.ipv4.srcPort; + pDot11f->info.IpParams.params.IpV4Params.dest_port = + pOld->tclasParams.ipv4.dstPort; + pDot11f->info.IpParams.params.IpV4Params.DSCP = + pOld->tclasParams.ipv4.dscp; + pDot11f->info.IpParams.params.IpV4Params.proto = + pOld->tclasParams.ipv4.protocol; + pDot11f->info.IpParams.params.IpV4Params.reserved = + pOld->tclasParams.ipv4.rsvd; + } + else + { + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV6Params.source, + ( tANI_U8* )pOld->tclasParams.ipv6.srcIpAddr, 16 ); + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV6Params.dest, + ( tANI_U8* )pOld->tclasParams.ipv6.dstIpAddr, 16 ); + pDot11f->info.IpParams.params.IpV6Params.src_port = + pOld->tclasParams.ipv6.srcPort; + pDot11f->info.IpParams.params.IpV6Params.dest_port = + pOld->tclasParams.ipv6.dstPort; + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV6Params.flow_label, + ( tANI_U8* )pOld->tclasParams.ipv6.flowLabel, 3 ); + } + break; + case SIR_MAC_TCLASTYPE_8021DQ: + pDot11f->info.Params8021dq.tag_type = pOld->tclasParams.t8021dq.tag; + break; + default: + limLog(pMac, LOGE, + FL("Bad TCLAS type %d in PopulateDot11fTCLAS."), + pDot11f->classifier_type); + return eSIR_FAILURE; + } + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} // End PopulateDot11fTCLAS. + +tSirRetStatus +PopulateDot11fWMMTCLAS(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, + tDot11fIEWMMTCLAS *pDot11f) +{ + pDot11f->version = 1; + pDot11f->user_priority = pOld->tclas.userPrio; + pDot11f->classifier_type = pOld->tclas.classifierType; + pDot11f->classifier_mask = pOld->tclas.classifierMask; + + switch ( pDot11f->classifier_type ) + { + case SIR_MAC_TCLASTYPE_ETHERNET: + vos_mem_copy( ( tANI_U8* )&pDot11f->info.EthParams.source, + ( tANI_U8* )&pOld->tclasParams.eth.srcAddr, 6 ); + vos_mem_copy( ( tANI_U8* )&pDot11f->info.EthParams.dest, + ( tANI_U8* )&pOld->tclasParams.eth.dstAddr, 6 ); + pDot11f->info.EthParams.type = pOld->tclasParams.eth.type; + break; + case SIR_MAC_TCLASTYPE_TCPUDPIP: + pDot11f->info.IpParams.version = pOld->version; + if ( SIR_MAC_TCLAS_IPV4 == pDot11f->info.IpParams.version ) + { + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV4Params.source, + ( tANI_U8* )pOld->tclasParams.ipv4.srcIpAddr, 4 ); + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV4Params.dest, + ( tANI_U8* )pOld->tclasParams.ipv4.dstIpAddr, 4 ); + pDot11f->info.IpParams.params.IpV4Params.src_port = + pOld->tclasParams.ipv4.srcPort; + pDot11f->info.IpParams.params.IpV4Params.dest_port = + pOld->tclasParams.ipv4.dstPort; + pDot11f->info.IpParams.params.IpV4Params.DSCP = + pOld->tclasParams.ipv4.dscp; + pDot11f->info.IpParams.params.IpV4Params.proto = + pOld->tclasParams.ipv4.protocol; + pDot11f->info.IpParams.params.IpV4Params.reserved = + pOld->tclasParams.ipv4.rsvd; + } + else + { + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV6Params.source, + ( tANI_U8* )pOld->tclasParams.ipv6.srcIpAddr, 16 ); + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV6Params.dest, + ( tANI_U8* )pOld->tclasParams.ipv6.dstIpAddr, 16 ); + pDot11f->info.IpParams.params.IpV6Params.src_port = + pOld->tclasParams.ipv6.srcPort; + pDot11f->info.IpParams.params.IpV6Params.dest_port = + pOld->tclasParams.ipv6.dstPort; + vos_mem_copy( ( tANI_U8* )&pDot11f->info.IpParams.params. + IpV6Params.flow_label, + ( tANI_U8* )pOld->tclasParams.ipv6.flowLabel, 3 ); + } + break; + case SIR_MAC_TCLASTYPE_8021DQ: + pDot11f->info.Params8021dq.tag_type = pOld->tclasParams.t8021dq.tag; + break; + default: + limLog(pMac, LOGE, + FL("Bad TCLAS type %d in PopulateDot11fTCLAS."), + pDot11f->classifier_type); + return eSIR_FAILURE; + } + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} // End PopulateDot11fWMMTCLAS. + + +tSirRetStatus PopulateDot11fWsc(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f) +{ + + tANI_U32 wpsState; + + pDot11f->Version.present = 1; + pDot11f->Version.major = 0x01; + pDot11f->Version.minor = 0x00; + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_STATE, &wpsState) != eSIR_SUCCESS) + limLog(pMac, LOGP, "Failed to cfg get id %d", WNI_CFG_WPS_STATE); + + pDot11f->WPSState.present = 1; + pDot11f->WPSState.state = (tANI_U8) wpsState; + + pDot11f->APSetupLocked.present = 0; + + pDot11f->SelectedRegistrar.present = 0; + + pDot11f->DevicePasswordID.present = 0; + + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + pDot11f->UUID_E.present = 0; + + pDot11f->RFBands.present = 0; + + pDot11f->present = 1; + return eSIR_SUCCESS; +} + +tSirRetStatus PopulateDot11fWscRegistrarInfo(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f) +{ + const struct sLimWscIeInfo *const pWscIeInfo = &(pMac->lim.wscIeInfo); + tANI_U32 devicepasswdId; + + + pDot11f->APSetupLocked.present = 1; + pDot11f->APSetupLocked.fLocked = pWscIeInfo->apSetupLocked; + + pDot11f->SelectedRegistrar.present = 1; + pDot11f->SelectedRegistrar.selected = pWscIeInfo->selectedRegistrar; + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_DEVICE_PASSWORD_ID, &devicepasswdId) != eSIR_SUCCESS) + limLog(pMac, LOGP, "Failed to cfg get id %d", + WNI_CFG_WPS_DEVICE_PASSWORD_ID); + + pDot11f->DevicePasswordID.present = 1; + pDot11f->DevicePasswordID.id = (tANI_U16) devicepasswdId; + + pDot11f->SelectedRegistrarConfigMethods.present = 1; + pDot11f->SelectedRegistrarConfigMethods.methods = pWscIeInfo->selectedRegistrarConfigMethods; + + // UUID_E and RF Bands are applicable only for dual band AP + + return eSIR_SUCCESS; +} + +tSirRetStatus DePopulateDot11fWscRegistrarInfo(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f) +{ + pDot11f->APSetupLocked.present = 0; + pDot11f->SelectedRegistrar.present = 0; + pDot11f->DevicePasswordID.present = 0; + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + return eSIR_SUCCESS; +} +tSirRetStatus PopulateDot11fProbeResWPSIEs(tpAniSirGlobal pMac, tDot11fIEWscProbeRes *pDot11f, tpPESession psessionEntry) +{ + + tSirWPSProbeRspIE *pSirWPSProbeRspIE; + + pSirWPSProbeRspIE = &psessionEntry->APWPSIEs.SirWPSProbeRspIE; + + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_VER_PRESENT) + { + pDot11f->present = 1; + pDot11f->Version.present = 1; + pDot11f->Version.major = (tANI_U8) ((pSirWPSProbeRspIE->Version & 0xF0)>>4); + pDot11f->Version.minor = (tANI_U8) (pSirWPSProbeRspIE->Version & 0x0F); + } + else + { + pDot11f->present = 0; + pDot11f->Version.present = 0; + } + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_STATE_PRESENT) + { + + pDot11f->WPSState.present = 1; + pDot11f->WPSState.state = (tANI_U8)pSirWPSProbeRspIE->wpsState; + } + else + pDot11f->WPSState.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_APSETUPLOCK_PRESENT) + { + pDot11f->APSetupLocked.present = 1; + pDot11f->APSetupLocked.fLocked = pSirWPSProbeRspIE->APSetupLocked; + } + else + pDot11f->APSetupLocked.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT) + { + pDot11f->SelectedRegistrar.present = 1; + pDot11f->SelectedRegistrar.selected = pSirWPSProbeRspIE->SelectedRegistra; + } + else + pDot11f->SelectedRegistrar.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_DEVICEPASSWORDID_PRESENT) + { + pDot11f->DevicePasswordID.present = 1; + pDot11f->DevicePasswordID.id = pSirWPSProbeRspIE->DevicePasswordID; + } + else + pDot11f->DevicePasswordID.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT) + { + pDot11f->SelectedRegistrarConfigMethods.present = 1; + pDot11f->SelectedRegistrarConfigMethods.methods = pSirWPSProbeRspIE->SelectedRegistraCfgMethod; + } + else + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_RESPONSETYPE_PRESENT) + { + pDot11f->ResponseType.present = 1; + pDot11f->ResponseType.resType = pSirWPSProbeRspIE->ResponseType; + } + else + pDot11f->ResponseType.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_UUIDE_PRESENT) + { + pDot11f->UUID_E.present = 1; + vos_mem_copy(pDot11f->UUID_E.uuid, pSirWPSProbeRspIE->UUID_E, WNI_CFG_WPS_UUID_LEN); + } + else + pDot11f->UUID_E.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_MANUFACTURE_PRESENT) + { + pDot11f->Manufacturer.present = 1; + pDot11f->Manufacturer.num_name = pSirWPSProbeRspIE->Manufacture.num_name; + vos_mem_copy(pDot11f->Manufacturer.name, pSirWPSProbeRspIE->Manufacture.name, + pSirWPSProbeRspIE->Manufacture.num_name); + } + else + pDot11f->Manufacturer.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_MODELNUMBER_PRESENT) + { + pDot11f->ModelName.present = 1; + pDot11f->ModelName.num_text = pSirWPSProbeRspIE->ModelName.num_text; + vos_mem_copy(pDot11f->ModelName.text, pSirWPSProbeRspIE->ModelName.text, + pDot11f->ModelName.num_text); + } + else + pDot11f->ModelName.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_MODELNUMBER_PRESENT) + { + pDot11f->ModelNumber.present = 1; + pDot11f->ModelNumber.num_text = pSirWPSProbeRspIE->ModelNumber.num_text; + vos_mem_copy(pDot11f->ModelNumber.text, pSirWPSProbeRspIE->ModelNumber.text, + pDot11f->ModelNumber.num_text); + } + else + pDot11f->ModelNumber.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_SERIALNUMBER_PRESENT) + { + pDot11f->SerialNumber.present = 1; + pDot11f->SerialNumber.num_text = pSirWPSProbeRspIE->SerialNumber.num_text; + vos_mem_copy(pDot11f->SerialNumber.text, pSirWPSProbeRspIE->SerialNumber.text, + pDot11f->SerialNumber.num_text); + } + else + pDot11f->SerialNumber.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT) + { + pDot11f->PrimaryDeviceType.present = 1; + vos_mem_copy(pDot11f->PrimaryDeviceType.oui, pSirWPSProbeRspIE->PrimaryDeviceOUI, + sizeof(pSirWPSProbeRspIE->PrimaryDeviceOUI)); + pDot11f->PrimaryDeviceType.primary_category = (tANI_U16)pSirWPSProbeRspIE->PrimaryDeviceCategory; + pDot11f->PrimaryDeviceType.sub_category = (tANI_U16)pSirWPSProbeRspIE->DeviceSubCategory; + } + else + pDot11f->PrimaryDeviceType.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_DEVICENAME_PRESENT) + { + pDot11f->DeviceName.present = 1; + pDot11f->DeviceName.num_text = pSirWPSProbeRspIE->DeviceName.num_text; + vos_mem_copy(pDot11f->DeviceName.text, pSirWPSProbeRspIE->DeviceName.text, + pDot11f->DeviceName.num_text); + } + else + pDot11f->DeviceName.present = 0; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_CONFIGMETHODS_PRESENT) + { + pDot11f->ConfigMethods.present = 1; + pDot11f->ConfigMethods.methods = pSirWPSProbeRspIE->ConfigMethod; + } + else + pDot11f->ConfigMethods.present = 0; + + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_RF_BANDS_PRESENT) + { + pDot11f->RFBands.present = 1; + pDot11f->RFBands.bands = pSirWPSProbeRspIE->RFBand; + } + else + pDot11f->RFBands.present = 0; + + return eSIR_SUCCESS; +} +tSirRetStatus PopulateDot11fAssocResWPSIEs(tpAniSirGlobal pMac, tDot11fIEWscAssocRes *pDot11f, tpPESession psessionEntry) +{ + tSirWPSProbeRspIE *pSirWPSProbeRspIE; + + pSirWPSProbeRspIE = &psessionEntry->APWPSIEs.SirWPSProbeRspIE; + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_VER_PRESENT) + { + pDot11f->present = 1; + pDot11f->Version.present = 1; + pDot11f->Version.major = (tANI_U8) ((pSirWPSProbeRspIE->Version & 0xF0)>>4); + pDot11f->Version.minor = (tANI_U8) (pSirWPSProbeRspIE->Version & 0x0F); + } + else + { + pDot11f->present = 0; + pDot11f->Version.present = 0; + } + + if(pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_RESPONSETYPE_PRESENT) + { + pDot11f->ResponseType.present = 1; + pDot11f->ResponseType.resType = pSirWPSProbeRspIE->ResponseType; + } + else + pDot11f->ResponseType.present = 0; + + return eSIR_SUCCESS; +} + +tSirRetStatus PopulateDot11fBeaconWPSIEs(tpAniSirGlobal pMac, tDot11fIEWscBeacon *pDot11f, tpPESession psessionEntry) +{ + + tSirWPSBeaconIE *pSirWPSBeaconIE; + + pSirWPSBeaconIE = &psessionEntry->APWPSIEs.SirWPSBeaconIE; + + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_PROBRSP_VER_PRESENT) + { + pDot11f->present = 1; + pDot11f->Version.present = 1; + pDot11f->Version.major = (tANI_U8) ((pSirWPSBeaconIE->Version & 0xF0)>>4); + pDot11f->Version.minor = (tANI_U8) (pSirWPSBeaconIE->Version & 0x0F); + } + else + { + pDot11f->present = 0; + pDot11f->Version.present = 0; + } + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_STATE_PRESENT) + { + + pDot11f->WPSState.present = 1; + pDot11f->WPSState.state = (tANI_U8)pSirWPSBeaconIE->wpsState; + } + else + pDot11f->WPSState.present = 0; + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_APSETUPLOCK_PRESENT) + { + pDot11f->APSetupLocked.present = 1; + pDot11f->APSetupLocked.fLocked = pSirWPSBeaconIE->APSetupLocked; + } + else + pDot11f->APSetupLocked.present = 0; + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_SELECTEDREGISTRA_PRESENT) + { + pDot11f->SelectedRegistrar.present = 1; + pDot11f->SelectedRegistrar.selected = pSirWPSBeaconIE->SelectedRegistra; + } + else + pDot11f->SelectedRegistrar.present = 0; + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_DEVICEPASSWORDID_PRESENT) + { + pDot11f->DevicePasswordID.present = 1; + pDot11f->DevicePasswordID.id = pSirWPSBeaconIE->DevicePasswordID; + } + else + pDot11f->DevicePasswordID.present = 0; + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT) + { + pDot11f->SelectedRegistrarConfigMethods.present = 1; + pDot11f->SelectedRegistrarConfigMethods.methods = pSirWPSBeaconIE->SelectedRegistraCfgMethod; + } + else + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_UUIDE_PRESENT) + { + pDot11f->UUID_E.present = 1; + vos_mem_copy(pDot11f->UUID_E.uuid, pSirWPSBeaconIE->UUID_E, WNI_CFG_WPS_UUID_LEN); + } + else + pDot11f->UUID_E.present = 0; + + + if(pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_RF_BANDS_PRESENT) + { + pDot11f->RFBands.present = 1; + pDot11f->RFBands.bands = pSirWPSBeaconIE->RFBand; + } + else + pDot11f->RFBands.present = 0; + + return eSIR_SUCCESS; +} +tSirRetStatus PopulateDot11fWscInProbeRes(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f) +{ + tANI_U32 cfgMethods; + tANI_U32 cfgStrLen; + tANI_U32 val; + tANI_U32 wpsVersion, wpsState; + + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_VERSION, &wpsVersion) != eSIR_SUCCESS) + limLog(pMac, LOGP, "Failed to cfg get id %d", WNI_CFG_WPS_VERSION); + + pDot11f->Version.present = 1; + pDot11f->Version.major = (tANI_U8) ((wpsVersion & 0xF0)>>4); + pDot11f->Version.minor = (tANI_U8) (wpsVersion & 0x0F); + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_STATE, &wpsState) != eSIR_SUCCESS) + limLog(pMac, LOGP, "Failed to cfg get id %d", WNI_CFG_WPS_STATE); + + pDot11f->WPSState.present = 1; + pDot11f->WPSState.state = (tANI_U8) wpsState; + + pDot11f->APSetupLocked.present = 0; + + pDot11f->SelectedRegistrar.present = 0; + + pDot11f->DevicePasswordID.present = 0; + + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + pDot11f->ResponseType.present = 1; + if ((pMac->lim.wscIeInfo.reqType == REQ_TYPE_REGISTRAR) || + (pMac->lim.wscIeInfo.reqType == REQ_TYPE_WLAN_MANAGER_REGISTRAR)){ + pDot11f->ResponseType.resType = RESP_TYPE_ENROLLEE_OPEN_8021X; + } + else{ + pDot11f->ResponseType.resType = RESP_TYPE_AP; + } + + /* UUID is a 16 byte long binary. Still use wlan_cfgGetStr to get it. */ + pDot11f->UUID_E.present = 1; + cfgStrLen = WNI_CFG_WPS_UUID_LEN; + if (wlan_cfgGetStr(pMac, + WNI_CFG_WPS_UUID, + pDot11f->UUID_E.uuid, + &cfgStrLen) != eSIR_SUCCESS) + { + *(pDot11f->UUID_E.uuid) = '\0'; + } + + pDot11f->Manufacturer.present = 1; + cfgStrLen = WNI_CFG_MANUFACTURER_NAME_LEN; + if (wlan_cfgGetStr(pMac, + WNI_CFG_MANUFACTURER_NAME, + pDot11f->Manufacturer.name, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->Manufacturer.num_name = 0; + } else { + pDot11f->Manufacturer.num_name = (tANI_U8) (cfgStrLen & 0x000000FF); + } + + pDot11f->ModelName.present = 1; + cfgStrLen = WNI_CFG_MODEL_NAME_LEN; + if (wlan_cfgGetStr(pMac, + WNI_CFG_MODEL_NAME, + pDot11f->ModelName.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->ModelName.num_text = 0; + } else { + pDot11f->ModelName.num_text = (tANI_U8) (cfgStrLen & 0x000000FF); + } + + pDot11f->ModelNumber.present = 1; + cfgStrLen = WNI_CFG_MODEL_NUMBER_LEN; + if (wlan_cfgGetStr(pMac, + WNI_CFG_MODEL_NUMBER, + pDot11f->ModelNumber.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->ModelNumber.num_text = 0; + } else { + pDot11f->ModelNumber.num_text = (tANI_U8) (cfgStrLen & 0x000000FF); + } + + pDot11f->SerialNumber.present = 1; + cfgStrLen = WNI_CFG_MANUFACTURER_PRODUCT_VERSION_LEN; + if (wlan_cfgGetStr(pMac, + WNI_CFG_MANUFACTURER_PRODUCT_VERSION, + pDot11f->SerialNumber.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->SerialNumber.num_text = 0; + } else { + pDot11f->SerialNumber.num_text = (tANI_U8) (cfgStrLen & 0x000000FF); + } + + pDot11f->PrimaryDeviceType.present = 1; + + if (wlan_cfgGetInt(pMac, WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("cfg get prim device category failed")); + } + else + pDot11f->PrimaryDeviceType.primary_category = (tANI_U16) val; + + if (wlan_cfgGetInt(pMac, WNI_CFG_WPS_PIMARY_DEVICE_OUI, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("cfg get prim device OUI failed")); + } + else + { + *(pDot11f->PrimaryDeviceType.oui) = (tANI_U8)((val >> 24)& 0xff); + *(pDot11f->PrimaryDeviceType.oui+1) = (tANI_U8)((val >> 16)& 0xff); + *(pDot11f->PrimaryDeviceType.oui+2) = (tANI_U8)((val >> 8)& 0xff); + *(pDot11f->PrimaryDeviceType.oui+3) = (tANI_U8)((val & 0xff)); + } + + if (wlan_cfgGetInt(pMac, WNI_CFG_WPS_DEVICE_SUB_CATEGORY, &val) != eSIR_SUCCESS) + { + limLog(pMac, LOGP, FL("cfg get prim device sub category failed")); + } + else + pDot11f->PrimaryDeviceType.sub_category = (tANI_U16) val; + + pDot11f->DeviceName.present = 1; + cfgStrLen = WNI_CFG_MANUFACTURER_PRODUCT_NAME_LEN; + if (wlan_cfgGetStr(pMac, + WNI_CFG_MANUFACTURER_PRODUCT_NAME, + pDot11f->DeviceName.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->DeviceName.num_text = 0; + } else { + pDot11f->DeviceName.num_text = (tANI_U8) (cfgStrLen & 0x000000FF); + } + + if (wlan_cfgGetInt(pMac, + WNI_CFG_WPS_CFG_METHOD, + &cfgMethods) != eSIR_SUCCESS) + { + pDot11f->ConfigMethods.present = 0; + pDot11f->ConfigMethods.methods = 0; + } + else + { + pDot11f->ConfigMethods.present = 1; + pDot11f->ConfigMethods.methods = (tANI_U16) (cfgMethods & 0x0000FFFF); + } + + pDot11f->RFBands.present = 0; + + pDot11f->present = 1; + return eSIR_SUCCESS; +} + +tSirRetStatus PopulateDot11fWscRegistrarInfoInProbeRes(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f) +{ + const struct sLimWscIeInfo *const pWscIeInfo = &(pMac->lim.wscIeInfo); + tANI_U32 devicepasswdId; + + pDot11f->APSetupLocked.present = 1; + pDot11f->APSetupLocked.fLocked = pWscIeInfo->apSetupLocked; + + pDot11f->SelectedRegistrar.present = 1; + pDot11f->SelectedRegistrar.selected = pWscIeInfo->selectedRegistrar; + + if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_DEVICE_PASSWORD_ID, &devicepasswdId) != eSIR_SUCCESS) + limLog(pMac, LOGP, "Failed to cfg get id %d", + WNI_CFG_WPS_DEVICE_PASSWORD_ID); + + pDot11f->DevicePasswordID.present = 1; + pDot11f->DevicePasswordID.id = (tANI_U16) devicepasswdId; + + pDot11f->SelectedRegistrarConfigMethods.present = 1; + pDot11f->SelectedRegistrarConfigMethods.methods = pWscIeInfo->selectedRegistrarConfigMethods; + + // UUID_E and RF Bands are applicable only for dual band AP + + return eSIR_SUCCESS; +} + +tSirRetStatus DePopulateDot11fWscRegistrarInfoInProbeRes(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f) +{ + pDot11f->APSetupLocked.present = 0; + pDot11f->SelectedRegistrar.present = 0; + pDot11f->DevicePasswordID.present = 0; + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + return eSIR_SUCCESS; +} + +tSirRetStatus PopulateDot11fAssocResWscIE(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq) +{ + tDot11fIEWscAssocReq parsedWscAssocReq = { 0, }; + tANI_U8 *wscIe; + + + wscIe = limGetWscIEPtr(pMac, pRcvdAssocReq->addIE.addIEdata, pRcvdAssocReq->addIE.length); + if(wscIe != NULL) + { + // retreive WSC IE from given AssocReq + dot11fUnpackIeWscAssocReq( pMac, + wscIe + 2 + 4, // EID, length, OUI + wscIe[ 1 ] - 4, // length without OUI + &parsedWscAssocReq ); + pDot11f->present = 1; + // version has to be 0x10 + pDot11f->Version.present = 1; + pDot11f->Version.major = 0x1; + pDot11f->Version.minor = 0x0; + + pDot11f->ResponseType.present = 1; + + if ((parsedWscAssocReq.RequestType.reqType == REQ_TYPE_REGISTRAR) || + (parsedWscAssocReq.RequestType.reqType == REQ_TYPE_WLAN_MANAGER_REGISTRAR)) + { + pDot11f->ResponseType.resType = RESP_TYPE_ENROLLEE_OPEN_8021X; + } + else + { + pDot11f->ResponseType.resType = RESP_TYPE_AP; + } + // Version infomration should be taken from our capability as well as peers + // TODO: currently it takes from peers only + if(parsedWscAssocReq.VendorExtension.present && + parsedWscAssocReq.VendorExtension.Version2.present) + { + pDot11f->VendorExtension.present = 1; + pDot11f->VendorExtension.vendorId[0] = 0x00; + pDot11f->VendorExtension.vendorId[1] = 0x37; + pDot11f->VendorExtension.vendorId[2] = 0x2A; + pDot11f->VendorExtension.Version2.present = 1; + pDot11f->VendorExtension.Version2.major = parsedWscAssocReq.VendorExtension.Version2.major; + pDot11f->VendorExtension.Version2.minor = parsedWscAssocReq.VendorExtension.Version2.minor; + } + } + return eSIR_SUCCESS; +} + +tSirRetStatus PopulateDot11AssocResP2PIE(tpAniSirGlobal pMac, + tDot11fIEP2PAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq) +{ + tANI_U8 *p2pIe; + + p2pIe = limGetP2pIEPtr(pMac, pRcvdAssocReq->addIE.addIEdata, pRcvdAssocReq->addIE.length); + if(p2pIe != NULL) + { + pDot11f->present = 1; + pDot11f->P2PStatus.present = 1; + pDot11f->P2PStatus.status = eSIR_SUCCESS; + pDot11f->ExtendedListenTiming.present = 0; + } + return eSIR_SUCCESS; +} + +#if defined WLAN_FEATURE_VOWIFI + +tSirRetStatus PopulateDot11fWFATPC( tpAniSirGlobal pMac, + tDot11fIEWFATPC *pDot11f, tANI_U8 txPower, tANI_U8 linkMargin ) +{ + pDot11f->txPower = txPower; + pDot11f->linkMargin = linkMargin; + pDot11f->present = 1; + + return eSIR_SUCCESS; +} + +tSirRetStatus PopulateDot11fBeaconReport( tpAniSirGlobal pMac, tDot11fIEMeasurementReport *pDot11f, tSirMacBeaconReport *pBeaconReport ) +{ + + pDot11f->report.Beacon.regClass = pBeaconReport->regClass; + pDot11f->report.Beacon.channel = pBeaconReport->channel; + vos_mem_copy( pDot11f->report.Beacon.meas_start_time, pBeaconReport->measStartTime, + sizeof(pDot11f->report.Beacon.meas_start_time) ); + pDot11f->report.Beacon.meas_duration = pBeaconReport->measDuration; + pDot11f->report.Beacon.condensed_PHY = pBeaconReport->phyType; + pDot11f->report.Beacon.reported_frame_type = !pBeaconReport->bcnProbeRsp; + pDot11f->report.Beacon.RCPI = pBeaconReport->rcpi; + pDot11f->report.Beacon.RSNI = pBeaconReport->rsni; + vos_mem_copy( pDot11f->report.Beacon.BSSID, pBeaconReport->bssid, sizeof(tSirMacAddr)); + pDot11f->report.Beacon.antenna_id = pBeaconReport->antennaId; + pDot11f->report.Beacon.parent_TSF = pBeaconReport->parentTSF; + + if( pBeaconReport->numIes ) + { + pDot11f->report.Beacon.BeaconReportFrmBody.present = 1; + vos_mem_copy( pDot11f->report.Beacon.BeaconReportFrmBody.reportedFields, + pBeaconReport->Ies, pBeaconReport->numIes ); + pDot11f->report.Beacon.BeaconReportFrmBody.num_reportedFields = pBeaconReport->numIes; + } + + return eSIR_SUCCESS; + +} + +tSirRetStatus PopulateDot11fRRMIe( tpAniSirGlobal pMac, tDot11fIERRMEnabledCap *pDot11f, tpPESession psessionEntry ) +{ + tpRRMCaps pRrmCaps; + uint8_t *bytes; + + pRrmCaps = rrmGetCapabilities( pMac, psessionEntry ); + + pDot11f->LinkMeasurement = pRrmCaps->LinkMeasurement ; + pDot11f->NeighborRpt = pRrmCaps->NeighborRpt ; + pDot11f->parallel = pRrmCaps->parallel ; + pDot11f->repeated = pRrmCaps->repeated ; + pDot11f->BeaconPassive = pRrmCaps->BeaconPassive ; + pDot11f->BeaconActive = pRrmCaps->BeaconActive ; + pDot11f->BeaconTable = pRrmCaps->BeaconTable ; + pDot11f->BeaconRepCond = pRrmCaps->BeaconRepCond ; + pDot11f->FrameMeasurement = pRrmCaps->FrameMeasurement ; + pDot11f->ChannelLoad = pRrmCaps->ChannelLoad ; + pDot11f->NoiseHistogram = pRrmCaps->NoiseHistogram ; + pDot11f->statistics = pRrmCaps->statistics ; + pDot11f->LCIMeasurement = pRrmCaps->LCIMeasurement ; + pDot11f->LCIAzimuth = pRrmCaps->LCIAzimuth ; + pDot11f->TCMCapability = pRrmCaps->TCMCapability ; + pDot11f->triggeredTCM = pRrmCaps->triggeredTCM ; + pDot11f->APChanReport = pRrmCaps->APChanReport ; + pDot11f->RRMMIBEnabled = pRrmCaps->RRMMIBEnabled ; + pDot11f->operatingChanMax = pRrmCaps->operatingChanMax ; + pDot11f->nonOperatinChanMax = pRrmCaps->nonOperatingChanMax ; + pDot11f->MeasurementPilot = pRrmCaps->MeasurementPilot ; + pDot11f->MeasurementPilotEnabled = pRrmCaps->MeasurementPilotEnabled ; + pDot11f->NeighborTSFOffset = pRrmCaps->NeighborTSFOffset ; + pDot11f->RCPIMeasurement = pRrmCaps->RCPIMeasurement ; + pDot11f->RSNIMeasurement = pRrmCaps->RSNIMeasurement ; + pDot11f->BssAvgAccessDelay = pRrmCaps->BssAvgAccessDelay ; + pDot11f->BSSAvailAdmission = pRrmCaps->BSSAvailAdmission ; + pDot11f->AntennaInformation = pRrmCaps->AntennaInformation ; + pDot11f->fine_time_meas_rpt = pRrmCaps->fine_time_meas_rpt; + pDot11f->lci_capability = pRrmCaps->lci_capability; + + pDot11f->present = 1; + bytes = (uint8_t *) pDot11f + 1; /* ignore present field */ + limLog(pMac, LOG1, FL("RRM Enabled Cap IE: %02x %02x %02x %02x %02x"), + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]); + + return eSIR_SUCCESS; +} +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +void PopulateMDIE( tpAniSirGlobal pMac, + tDot11fIEMobilityDomain *pDot11f, tANI_U8 mdie[SIR_MDIE_SIZE] ) +{ + pDot11f->present = 1; + pDot11f->MDID = (tANI_U16)((mdie[1] << 8) | (mdie[0])); + + // Plugfest fix + pDot11f->overDSCap = (mdie[2] & 0x01); + pDot11f->resourceReqCap = ((mdie[2] >> 1) & 0x01); + +} + +void PopulateFTInfo( tpAniSirGlobal pMac, + tDot11fIEFTInfo *pDot11f ) +{ + pDot11f->present = 1; + pDot11f->IECount = 0; //TODO: put valid data during reassoc. + //All other info is zero. + +} +#endif + +void PopulateDot11fAssocRspRates ( tpAniSirGlobal pMac, tDot11fIESuppRates *pSupp, + tDot11fIEExtSuppRates *pExt, tANI_U16 *_11bRates, tANI_U16 *_11aRates ) +{ + tANI_U8 num_supp = 0, num_ext = 0; + tANI_U8 i,j; + + for( i = 0 ; (i < SIR_NUM_11B_RATES && _11bRates[i]) ; i++, num_supp++ ) + { + pSupp->rates[num_supp] = (tANI_U8)_11bRates[i]; + } + for( j = 0 ; (j < SIR_NUM_11A_RATES && _11aRates[j]) ; j++ ) + { + if( num_supp < 8 ) + pSupp->rates[num_supp++] = (tANI_U8)_11aRates[j]; + else + pExt->rates[num_ext++] = (tANI_U8)_11aRates[j]; + } + + if( num_supp ) + { + pSupp->num_rates = num_supp; + pSupp->present = 1; + } + if( num_ext ) + { + pExt->num_rates = num_ext; + pExt->present = 1; + } +} + +void PopulateDot11fTimeoutInterval( tpAniSirGlobal pMac, + tDot11fIETimeoutInterval *pDot11f, + tANI_U8 type, tANI_U32 value ) +{ + pDot11f->present = 1; + 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!")); + break; + } + } + vos_mem_free(pdot11f_rsn); +} +#endif /* SAP_AUTH_OFFLOAD */ + + +/** + * PopulateDot11fTimingAdvertFrame() - Populate the TA mgmt frame fields + * @pMac: the MAC context + * @frame: pointer to the TA frame + * + * Return: The SIR status. + */ +tSirRetStatus PopulateDot11fTimingAdvertFrame(tpAniSirGlobal mac_ctx, + tDot11fTimingAdvertisementFrame *frame) +{ + uint32_t val, codelen, len; + uint16_t item; + uint8_t temp[CFG_MAX_STR_LEN], code[3]; + tSirRetStatus nSirStatus; + + /* Capabilities */ + wlan_cfgGetInt(mac_ctx, WNI_CFG_PRIVACY_ENABLED, &val); + if (val) + frame->Capabilities.privacy = 1; + + wlan_cfgGetInt(mac_ctx, WNI_CFG_SHORT_PREAMBLE, &val); + if (val) + frame->Capabilities.shortPreamble = 1; + + wlan_cfgGetInt(mac_ctx, WNI_CFG_11H_ENABLED, &val); + if (val) + frame->Capabilities.spectrumMgt = 1; + + wlan_cfgGetInt(mac_ctx, WNI_CFG_QOS_ENABLED, &val); + if (val) + frame->Capabilities.qos = 1; + + wlan_cfgGetInt(mac_ctx, WNI_CFG_APSD_ENABLED, &val); + if (val) + frame->Capabilities.apsd = 1; + + wlan_cfgGetInt(mac_ctx, WNI_CFG_BLOCK_ACK_ENABLED, &val); + frame->Capabilities.delayedBA = + (uint16_t)((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); + frame->Capabilities.immediateBA = + (uint16_t)((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); + + /* Country */ + item = WNI_CFG_MAX_TX_POWER_5; + CFG_GET_STR(nSirStatus, mac_ctx, item, temp, len, + WNI_CFG_MAX_TX_POWER_5_LEN); + item = WNI_CFG_COUNTRY_CODE; + CFG_GET_STR(nSirStatus, mac_ctx, item, code, codelen, 3); + vos_mem_copy(&frame->Country, code, codelen); + if(len > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE) + len = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE; + + frame->Country.num_triplets = (uint8_t)(len / 3); + vos_mem_copy((uint8_t*)&frame->Country.triplets, temp, len); + frame->Country.present = 1; + + /* PowerConstraints */ + wlan_cfgGetInt(mac_ctx, WNI_CFG_LOCAL_POWER_CONSTRAINT, &val); + frame->PowerConstraints.localPowerConstraints = (uint8_t)val; + frame->PowerConstraints.present = 1; + + /* TimeAdvertisement */ + frame->TimeAdvertisement.present = 1; + frame->TimeAdvertisement.timing_capabilities = 1; + + return nSirStatus; +} + +// parserApi.c ends here. diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsApi.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsApi.c new file mode 100644 index 000000000000..6bdd50ee5ba6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsApi.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +//================================================================== +// +// File: utilsApi.cc +// +// Description: Implemention of a few utility routines. +// +// Author: Neelay Das +// +//// +// Change gHistory: +// 12/15/2003 - NDA - Initial version. +// +//=================================================================== + + +#include "utilsApi.h" + + + + + +// ------------------------------------------------------------------- +/** + * sirDumpBuf() + * + * FUNCTION: + * This function is called to dump a buffer with a certain level + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param pBuf: buffer pointer + * @return None. + */ +void +sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size) +{ + tANI_U32 i; + + if (level > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE(modId)]) + return; + + logDbg(pMac, modId, level, FL("Dumping %d bytes in host order\n"), size); + + for (i=0; (i+7)length = pNew->num_ssid; + vos_mem_copy( pOld->ssId, pNew->ssid, pNew->num_ssid ); +} + +void ConvertSuppRates(tpAniSirGlobal pMac, + tSirMacRateSet *pOld, + tDot11fIESuppRates *pNew) +{ + pOld->numRates = pNew->num_rates; + vos_mem_copy( pOld->rate, pNew->rates, pNew->num_rates ); +} + +void ConvertExtSuppRates(tpAniSirGlobal pMac, + tSirMacRateSet *pOld, + tDot11fIEExtSuppRates *pNew) +{ + pOld->numRates = pNew->num_rates; + vos_mem_copy( pOld->rate, pNew->rates, pNew->num_rates ); +} + + +void ConvertQOSCaps(tpAniSirGlobal pMac, + tSirMacQosCapabilityIE *pOld, + tDot11fIEQOSCapsAp *pNew) +{ + pOld->type = 46; + pOld->length = 1; + + pOld->qosInfo.count = pNew->count; +} + + +void ConvertQOSCapsStation(tpAniSirGlobal pMac, + tSirMacQosCapabilityStaIE *pOld, + tDot11fIEQOSCapsStation *pNew) +{ + pOld->type = 46; + pOld->length = 1; + + pOld->qosInfo.moreDataAck = pNew->more_data_ack; + pOld->qosInfo.maxSpLen = pNew->max_sp_length; + pOld->qosInfo.qack = pNew->qack; + pOld->qosInfo.acbe_uapsd = pNew->acbe_uapsd; + pOld->qosInfo.acbk_uapsd = pNew->acbk_uapsd; + pOld->qosInfo.acvi_uapsd = pNew->acvi_uapsd; + pOld->qosInfo.acvo_uapsd = pNew->acvo_uapsd; +} + +tSirRetStatus ConvertWPA(tpAniSirGlobal pMac, + tSirMacWpaInfo *pOld, + tDot11fIEWPA *pNew) +{ + // This is awful, I know, but the old code just rammed the IE into an + // array... + tANI_U8 buffer[257]; + tANI_U32 status, written = 0, nbuffer = 257; + status = dot11fPackIeWPA( pMac, pNew, buffer, nbuffer, &written ); + if ( DOT11F_FAILED( status ) ) + { + dot11fLog(pMac, LOG2, FL("Failed to re-pack the WPA IE (0x%0x" + "8).\n"), status); + return eSIR_FAILURE; + } + + pOld->length = (tANI_U8)written - 2; + vos_mem_copy( pOld->info, buffer + 2, pOld->length ); + + return eSIR_SUCCESS; +} + +tSirRetStatus ConvertWPAOpaque( tpAniSirGlobal pMac, + tSirMacWpaInfo *pOld, + tDot11fIEWPAOpaque *pNew ) +{ + // This is awful, I know, but the old code just rammed the IE into + // an opaque array. Note that we need to explicitly add the OUI! + pOld->length = pNew->num_data + 4; + pOld->info[ 0 ] = 0x00; + pOld->info[ 1 ] = 0x50; + pOld->info[ 2 ] = 0xf2; + pOld->info[ 3 ] = 0x01; + vos_mem_copy( pOld->info + 4, pNew->data, pNew->num_data ); + + return eSIR_SUCCESS; +} + +#ifdef FEATURE_WLAN_WAPI +tSirRetStatus ConvertWAPIOpaque( tpAniSirGlobal pMac, + tSirMacWapiInfo *pOld, + tDot11fIEWAPIOpaque *pNew ) +{ + // This is awful, I know, but the old code just rammed the IE into + // an opaque array. Note that we need to explicitly add the OUI! + pOld->length = pNew->num_data; + vos_mem_copy( pOld->info , pNew->data, pNew->num_data ); + + return eSIR_SUCCESS; +} +#endif + +tSirRetStatus ConvertWscOpaque( tpAniSirGlobal pMac, + tSirAddie *pOld, + tDot11fIEWscIEOpaque *pNew ) +{ + // This is awful, I know, but the old code just rammed the IE into + // an opaque array. Note that we need to explicitly add the vendorIE and OUI ! + tANI_U8 curAddIELen = pOld->length; + + pOld->length = curAddIELen + pNew->num_data + 6; + pOld->addIEdata[ curAddIELen++ ] = 0xdd; + pOld->addIEdata[ curAddIELen++ ] = pNew->num_data + 4; + pOld->addIEdata[ curAddIELen++ ] = 0x00; + pOld->addIEdata[ curAddIELen++ ] = 0x50; + pOld->addIEdata[ curAddIELen++ ] = 0xf2; + pOld->addIEdata[ curAddIELen++ ] = 0x04; + vos_mem_copy( pOld->addIEdata + curAddIELen, pNew->data, pNew->num_data ); + + return eSIR_SUCCESS; +} + +tSirRetStatus ConvertP2POpaque( tpAniSirGlobal pMac, + tSirAddie *pOld, + tDot11fIEP2PIEOpaque *pNew ) +{ + // This is awful, I know, but the old code just rammed the IE into + // an opaque array. Note that we need to explicitly add the vendorIE and OUI ! + tANI_U8 curAddIELen = pOld->length; + + pOld->length = curAddIELen + pNew->num_data + 6; + pOld->addIEdata[ curAddIELen++ ] = 0xdd; + pOld->addIEdata[ curAddIELen++ ] = pNew->num_data + 4; + pOld->addIEdata[ curAddIELen++ ] = 0x50; + pOld->addIEdata[ curAddIELen++ ] = 0x6f; + pOld->addIEdata[ curAddIELen++ ] = 0x9A; + pOld->addIEdata[ curAddIELen++ ] = 0x09; + vos_mem_copy( pOld->addIEdata + curAddIELen, pNew->data, pNew->num_data ); + + return eSIR_SUCCESS; +} + +#ifdef WLAN_FEATURE_WFD +tSirRetStatus ConvertWFDOpaque( tpAniSirGlobal pMac, + tSirAddie *pOld, + tDot11fIEWFDIEOpaque *pNew ) +{ + // This is awful, I know, but the old code just rammed the IE into + // an opaque array. Note that we need to explicitly add the vendorIE and OUI ! + tANI_U8 curAddIELen = pOld->length; + + pOld->length = curAddIELen + pNew->num_data + 6; + pOld->addIEdata[ curAddIELen++ ] = 0xdd; + pOld->addIEdata[ curAddIELen++ ] = pNew->num_data + 4; + pOld->addIEdata[ curAddIELen++ ] = 0x50; + pOld->addIEdata[ curAddIELen++ ] = 0x6f; + pOld->addIEdata[ curAddIELen++ ] = 0x9A; + pOld->addIEdata[ curAddIELen++ ] = 0x0a; + vos_mem_copy( pOld->addIEdata + curAddIELen, pNew->data, pNew->num_data ); + + return eSIR_SUCCESS; +} +#endif + +tSirRetStatus ConvertRSN(tpAniSirGlobal pMac, + tSirMacRsnInfo *pOld, + tDot11fIERSN *pNew) +{ + tANI_U8 buffer[257]; + tANI_U32 status, written = 0, nbuffer = 257; + status = dot11fPackIeRSN( pMac, pNew, buffer, nbuffer, &written ); + if ( DOT11F_FAILED( status ) ) + { + dot11fLog(pMac, LOG2, FL("Failed to re-pack the RSN IE (0x%0x" + "8).\n"), status); + return eSIR_FAILURE; + } + + pOld->length = (tANI_U8)written - 2; + vos_mem_copy( pOld->info, buffer + 2, pOld->length ); + + return eSIR_SUCCESS; +} + +tSirRetStatus ConvertRSNOpaque( tpAniSirGlobal pMac, + tSirMacRsnInfo *pOld, + tDot11fIERSNOpaque *pNew ) +{ + // This is awful, I know, but the old code just rammed the IE into + // an opaque array. + pOld->length = pNew->num_data; + vos_mem_copy( pOld->info, pNew->data, pOld->length ); + + return eSIR_SUCCESS; +} + +void ConvertPowerCaps(tpAniSirGlobal pMac, + tSirMacPowerCapabilityIE *pOld, + tDot11fIEPowerCaps *pNew) +{ + pOld->type = 33; + pOld->length = 2; + pOld->minTxPower = pNew->minTxPower; + pOld->maxTxPower = pNew->maxTxPower; +} + +void ConvertSuppChannels(tpAniSirGlobal pMac, + tSirMacSupportedChannelIE *pOld, + tDot11fIESuppChannels *pNew) +{ + pOld->type = 36; + pOld->length = ( pNew->num_bands * 2 ); + vos_mem_copy( ( tANI_U8* )pOld->supportedChannels, ( tANI_U8* )pNew->bands, pOld->length ); +} + +void ConvertCFParams(tpAniSirGlobal pMac, + tSirMacCfParamSet *pOld, + tDot11fIECFParams *pNew) +{ + pOld->cfpCount = pNew->cfp_count; + pOld->cfpPeriod = pNew->cfp_period; + pOld->cfpMaxDuration = pNew->cfp_maxduration; + pOld->cfpDurRemaining = pNew->cfp_durremaining; +} + +void ConvertFHParams (tpAniSirGlobal pMac, + tSirMacFHParamSet *pOld, + tDot11fIEFHParamSet *pNew) +{ + pOld->dwellTime = pNew->dwell_time; + pOld->hopSet = pNew->hop_set; + pOld->hopPattern = pNew->hop_pattern; + pOld->hopIndex = pNew->hop_index; +} + +void ConvertTIM(tpAniSirGlobal pMac, + tSirMacTim *pOld, + tDot11fIETIM *pNew) +{ + pOld->dtimCount = pNew->dtim_count; + pOld->dtimPeriod = pNew->dtim_period; + pOld->bitmapControl = pNew->bmpctl; + pOld->bitmapLength = pNew->num_vbmp; + + vos_mem_copy( pOld->bitmap, pNew->vbmp, pNew->num_vbmp ); +} + +void ConvertCountry(tpAniSirGlobal pMac, + tSirCountryInformation *pOld, + tDot11fIECountry *pNew) +{ + int i; + + vos_mem_copy( pOld->countryString, pNew->country, COUNTRY_STRING_LENGTH ); + + pOld->numIntervals = pNew->num_triplets; + + for (i = 0; i < pNew->num_triplets; ++i) + { + pOld->channelTransmitPower[i].channelNumber = pNew->triplets[i][0]; + pOld->channelTransmitPower[i].numChannel = pNew->triplets[i][1]; + pOld->channelTransmitPower[i].maxTransmitPower = pNew->triplets[i][2]; + } +} + +void ConvertWMMParams(tpAniSirGlobal pMac, + tSirMacEdcaParamSetIE *pOld, + tDot11fIEWMMParams *pNew) +{ + pOld->type = 221; + pOld->length = 24; + + vos_mem_copy( ( tANI_U8* )&pOld->qosInfo, ( tANI_U8* )&pNew->qosInfo, 1 ); + + pOld->acbe.aci.aifsn = pNew->acbe_aifsn; + pOld->acbe.aci.acm = pNew->acbe_acm; + pOld->acbe.aci.aci = pNew->acbe_aci; + pOld->acbe.cw.min = pNew->acbe_acwmin; + pOld->acbe.cw.max = pNew->acbe_acwmax; + pOld->acbe.txoplimit = pNew->acbe_txoplimit; + + pOld->acbk.aci.aifsn = pNew->acbk_aifsn; + pOld->acbk.aci.acm = pNew->acbk_acm; + pOld->acbk.aci.aci = pNew->acbk_aci; + pOld->acbk.cw.min = pNew->acbk_acwmin; + pOld->acbk.cw.max = pNew->acbk_acwmax; + pOld->acbk.txoplimit = pNew->acbk_txoplimit; + + pOld->acvi.aci.aifsn = pNew->acvi_aifsn; + pOld->acvi.aci.acm = pNew->acvi_acm; + pOld->acvi.aci.aci = pNew->acvi_aci; + pOld->acvi.cw.min = pNew->acvi_acwmin; + pOld->acvi.cw.max = pNew->acvi_acwmax; + pOld->acvi.txoplimit = pNew->acvi_txoplimit; + + pOld->acvo.aci.aifsn = pNew->acvo_aifsn; + pOld->acvo.aci.acm = pNew->acvo_acm; + pOld->acvo.aci.aci = pNew->acvo_aci; + pOld->acvo.cw.min = pNew->acvo_acwmin; + pOld->acvo.cw.max = pNew->acvo_acwmax; + pOld->acvo.txoplimit = pNew->acvo_txoplimit; +} + +void ConvertERPInfo(tpAniSirGlobal pMac, + tSirMacErpInfo *pOld, + tDot11fIEERPInfo *pNew) +{ + pOld->nonErpPresent = pNew->non_erp_present; + pOld->useProtection = pNew->use_prot; + pOld->barkerPreambleMode = pNew->barker_preamble; +} + +void ConvertEDCAParam(tpAniSirGlobal pMac, + tSirMacEdcaParamSetIE *pOld, + tDot11fIEEDCAParamSet *pNew) +{ + pOld->type = 12; + pOld->length = 20; + + vos_mem_copy( ( tANI_U8* )&pOld->qosInfo, ( tANI_U8* )&pNew->qos, 1 ); + + pOld->acbe.aci.aifsn = pNew->acbe_aifsn; + pOld->acbe.aci.acm = pNew->acbe_acm; + pOld->acbe.aci.aci = pNew->acbe_aci; + pOld->acbe.cw.min = pNew->acbe_acwmin; + pOld->acbe.cw.max = pNew->acbe_acwmax; + pOld->acbe.txoplimit = pNew->acbe_txoplimit; + + pOld->acbk.aci.aifsn = pNew->acbk_aifsn; + pOld->acbk.aci.acm = pNew->acbk_acm; + pOld->acbk.aci.aci = pNew->acbk_aci; + pOld->acbk.cw.min = pNew->acbk_acwmin; + pOld->acbk.cw.max = pNew->acbk_acwmax; + pOld->acbk.txoplimit = pNew->acbk_txoplimit; + + pOld->acvi.aci.aifsn = pNew->acvi_aifsn; + pOld->acvi.aci.acm = pNew->acvi_acm; + pOld->acvi.aci.aci = pNew->acvi_aci; + pOld->acvi.cw.min = pNew->acvi_acwmin; + pOld->acvi.cw.max = pNew->acvi_acwmax; + pOld->acvi.txoplimit = pNew->acvi_txoplimit; + + pOld->acvo.aci.aifsn = pNew->acvo_aifsn; + pOld->acvo.aci.acm = pNew->acvo_acm; + pOld->acvo.aci.aci = pNew->acvo_aci; + pOld->acvo.cw.min = pNew->acvo_acwmin; + pOld->acvo.cw.max = pNew->acvo_acwmax; + pOld->acvo.txoplimit = pNew->acvo_txoplimit; + +} + +void ConvertTSPEC(tpAniSirGlobal pMac, + tSirMacTspecIE *pOld, + tDot11fIETSPEC *pNew) +{ + pOld->tsinfo.traffic.trafficType = (tANI_U16)pNew->traffic_type; + pOld->tsinfo.traffic.tsid = (tANI_U16)pNew->tsid; + pOld->tsinfo.traffic.direction = (tANI_U16)pNew->direction; + pOld->tsinfo.traffic.accessPolicy = (tANI_U16)pNew->access_policy; + pOld->tsinfo.traffic.aggregation = (tANI_U16)pNew->aggregation; + pOld->tsinfo.traffic.psb = (tANI_U16)pNew->psb; + pOld->tsinfo.traffic.userPrio = (tANI_U16)pNew->user_priority; + pOld->tsinfo.traffic.ackPolicy = (tANI_U16)pNew->tsinfo_ack_pol; + + pOld->tsinfo.schedule.schedule = (tANI_U8)pNew->schedule; + + pOld->nomMsduSz = pNew->size; + pOld->maxMsduSz = pNew->max_msdu_size; + pOld->minSvcInterval = pNew->min_service_int; + pOld->maxSvcInterval = pNew->max_service_int; + pOld->inactInterval = pNew->inactivity_int; + pOld->suspendInterval = pNew->suspension_int; + pOld->svcStartTime = pNew->service_start_time; + pOld->minDataRate = pNew->min_data_rate; + pOld->meanDataRate = pNew->mean_data_rate; + pOld->peakDataRate = pNew->peak_data_rate; + pOld->maxBurstSz = pNew->burst_size; + pOld->delayBound = pNew->delay_bound; + pOld->minPhyRate = pNew->min_phy_rate; + pOld->surplusBw = pNew->surplus_bw_allowance; + pOld->mediumTime = pNew->medium_time; +} + +tSirRetStatus ConvertTCLAS(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, + tDot11fIETCLAS *pNew) +{ + tANI_U32 length = 0; + + if ( DOT11F_FAILED( dot11fGetPackedIETCLAS( pMac, pNew, &length ) ) ) + { + return eSIR_FAILURE; + } + + pOld->tclas.type = DOT11F_EID_TCLAS; + pOld->tclas.length = (tANI_U8)length; + pOld->tclas.userPrio = pNew->user_priority; + pOld->tclas.classifierType = pNew->classifier_type; + pOld->tclas.classifierMask = pNew->classifier_mask; + + switch ( pNew->classifier_type ) + { + case 0: + vos_mem_copy( pOld->tclasParams.eth.srcAddr, pNew->info.EthParams.source, 6 ); + vos_mem_copy( pOld->tclasParams.eth.dstAddr, pNew->info.EthParams.dest, 6 ); + pOld->tclasParams.eth.type = pNew->info.EthParams.type; + break; + case 1: + pOld->version = pNew->info.IpParams.version; + if ( 4 == pNew->info.IpParams.version ) + { + pOld->tclasParams.ipv4.version = 4; + vos_mem_copy( pOld->tclasParams.ipv4.srcIpAddr, + pNew->info.IpParams.params.IpV4Params.source, 4 ); + vos_mem_copy( pOld->tclasParams.ipv4.dstIpAddr, + pNew->info.IpParams.params.IpV4Params.dest, 4 ); + pOld->tclasParams.ipv4.srcPort = pNew->info.IpParams.params.IpV4Params.src_port; + pOld->tclasParams.ipv4.dstPort = pNew->info.IpParams.params.IpV4Params.dest_port; + pOld->tclasParams.ipv4.dscp = pNew->info.IpParams.params.IpV4Params.DSCP; + pOld->tclasParams.ipv4.protocol = pNew->info.IpParams.params.IpV4Params.proto; + pOld->tclasParams.ipv4.rsvd = pNew->info.IpParams.params.IpV4Params.reserved; + } + else if ( 6 == pNew->info.IpParams.version ) + { + pOld->tclasParams.ipv6.version = 6; + vos_mem_copy( ( tANI_U8* )pOld->tclasParams.ipv6.srcIpAddr, + ( tANI_U8* )pNew->info.IpParams.params.IpV6Params.source, 16 ); + vos_mem_copy( ( tANI_U8* )pOld->tclasParams.ipv6.dstIpAddr, + ( tANI_U8* )pNew->info.IpParams.params.IpV6Params.dest, 16 ); + pOld->tclasParams.ipv6.srcPort = pNew->info.IpParams.params.IpV6Params.src_port; + pOld->tclasParams.ipv6.dstPort = pNew->info.IpParams.params.IpV6Params.dest_port; + vos_mem_copy( ( tANI_U8* )pOld->tclasParams.ipv6.flowLabel, + ( tANI_U8* )pNew->info.IpParams.params.IpV6Params.flow_label, 3 ); + } + else + { + return eSIR_FAILURE; + } + break; + case 2: + pOld->tclasParams.t8021dq.tag = pNew->info.Params8021dq.tag_type; + break; + default: + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +void ConvertWMMTSPEC(tpAniSirGlobal pMac, + tSirMacTspecIE *pOld, + tDot11fIEWMMTSPEC *pNew) +{ + pOld->tsinfo.traffic.trafficType = (tANI_U16)pNew->traffic_type; + pOld->tsinfo.traffic.tsid = (tANI_U16)pNew->tsid; + pOld->tsinfo.traffic.direction = (tANI_U16)pNew->direction; + pOld->tsinfo.traffic.accessPolicy = (tANI_U16)pNew->access_policy; + pOld->tsinfo.traffic.aggregation = (tANI_U16)pNew->aggregation; + pOld->tsinfo.traffic.psb = (tANI_U16)pNew->psb; + pOld->tsinfo.traffic.userPrio = (tANI_U16)pNew->user_priority; + pOld->tsinfo.traffic.ackPolicy = (tANI_U16)pNew->tsinfo_ack_pol; + pOld->nomMsduSz = (pNew->fixed << 15) | pNew->size; + pOld->maxMsduSz = pNew->max_msdu_size; + pOld->minSvcInterval = pNew->min_service_int; + pOld->maxSvcInterval = pNew->max_service_int; + pOld->inactInterval = pNew->inactivity_int; + pOld->suspendInterval = pNew->suspension_int; + pOld->svcStartTime = pNew->service_start_time; + pOld->minDataRate = pNew->min_data_rate; + pOld->meanDataRate = pNew->mean_data_rate; + pOld->peakDataRate = pNew->peak_data_rate; + pOld->maxBurstSz = pNew->burst_size; + pOld->delayBound = pNew->delay_bound; + pOld->minPhyRate = pNew->min_phy_rate; + pOld->surplusBw = pNew->surplus_bw_allowance; + pOld->mediumTime = pNew->medium_time; +} + +tSirRetStatus ConvertWMMTCLAS(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, + tDot11fIEWMMTCLAS *pNew) +{ + tANI_U32 length = 0; + + if ( DOT11F_FAILED( dot11fGetPackedIEWMMTCLAS( pMac, pNew, &length ) ) ) + { + return eSIR_FAILURE; + } + + pOld->tclas.type = DOT11F_EID_WMMTCLAS; + pOld->tclas.length = (tANI_U8)length; + pOld->tclas.userPrio = pNew->user_priority; + pOld->tclas.classifierType = pNew->classifier_type; + pOld->tclas.classifierMask = pNew->classifier_mask; + + switch ( pNew->classifier_type ) + { + case 0: + vos_mem_copy( pOld->tclasParams.eth.srcAddr, pNew->info.EthParams.source, 6 ); + vos_mem_copy( pOld->tclasParams.eth.dstAddr, pNew->info.EthParams.dest, 6 ); + pOld->tclasParams.eth.type = pNew->info.EthParams.type; + break; + case 1: + pOld->version = pNew->info.IpParams.version; + if ( 4 == pNew->info.IpParams.version ) + { + pOld->tclasParams.ipv4.version = 4; + vos_mem_copy( pOld->tclasParams.ipv4.srcIpAddr, + pNew->info.IpParams.params.IpV4Params.source, 4 ); + vos_mem_copy( pOld->tclasParams.ipv4.dstIpAddr, + pNew->info.IpParams.params.IpV4Params.dest, 4 ); + pOld->tclasParams.ipv4.srcPort = pNew->info.IpParams.params.IpV4Params.src_port; + pOld->tclasParams.ipv4.dstPort = pNew->info.IpParams.params.IpV4Params.dest_port; + pOld->tclasParams.ipv4.dscp = pNew->info.IpParams.params.IpV4Params.DSCP; + pOld->tclasParams.ipv4.protocol = pNew->info.IpParams.params.IpV4Params.proto; + pOld->tclasParams.ipv4.rsvd = pNew->info.IpParams.params.IpV4Params.reserved; + } + else if ( 6 == pNew->info.IpParams.version ) + { + pOld->tclasParams.ipv6.version = 6; + vos_mem_copy( ( tANI_U8* )pOld->tclasParams.ipv6.srcIpAddr, + ( tANI_U8* )pNew->info.IpParams.params.IpV6Params.source, 16 ); + vos_mem_copy( ( tANI_U8* )pOld->tclasParams.ipv6.dstIpAddr, + ( tANI_U8* )pNew->info.IpParams.params.IpV6Params.dest, 16 ); + pOld->tclasParams.ipv6.srcPort = pNew->info.IpParams.params.IpV6Params.src_port; + pOld->tclasParams.ipv6.dstPort = pNew->info.IpParams.params.IpV6Params.dest_port; + vos_mem_copy( ( tANI_U8* )pOld->tclasParams.ipv6.flowLabel, + ( tANI_U8* )pNew->info.IpParams.params.IpV6Params.flow_label, 3 ); + } + else + { + return eSIR_FAILURE; + } + break; + case 2: + pOld->tclasParams.t8021dq.tag = pNew->info.Params8021dq.tag_type; + break; + default: + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +void ConvertTSDelay(tpAniSirGlobal pMac, + tSirMacTsDelayIE *pOld, + tDot11fIETSDelay *pNew) +{ + pOld->type = DOT11F_EID_TSDELAY; + pOld->length = 4U; + pOld->delay = pNew->delay; +} + +void ConvertSchedule(tpAniSirGlobal pMac, + tSirMacScheduleIE *pOld, + tDot11fIESchedule *pNew) +{ + pOld->type = DOT11F_EID_SCHEDULE; + pOld->length = DOT11F_IE_SCHEDULE_MIN_LEN; + + pOld->info.aggregation = pNew->aggregation; + pOld->info.tsid = pNew->tsid; + pOld->info.direction = pNew->direction; + + pOld->svcStartTime = pNew->service_start_time; + pOld->svcInterval = pNew->service_interval; + pOld->specInterval = pNew->spec_interval; +} + +void ConvertWMMSchedule(tpAniSirGlobal pMac, + tSirMacScheduleIE *pOld, + tDot11fIEWMMSchedule *pNew) +{ + pOld->type = DOT11F_EID_WMMSCHEDULE; + pOld->length = DOT11F_IE_WMMSCHEDULE_MIN_LEN; + + pOld->info.aggregation = pNew->aggregation; + pOld->info.tsid = pNew->tsid; + pOld->info.direction = pNew->direction; + + pOld->svcStartTime = pNew->service_start_time; + pOld->svcInterval = pNew->service_interval; + pOld->specInterval = pNew->spec_interval; +} + +/** + @brief : This functions converts the given buffer till given size to Big endian format assuming the + bus is 32 bit. The size should be four byte aligned. + @param : ptr to be converted, size + @return : void +*/ + +void ConverttoBigEndian(void *ptr, tANI_U16 size) +{ + tANI_U8 *temp_ptr; + tANI_U32 *dest_ptr; + + dest_ptr = (tANI_U32 *)ptr; + while(size) + { + temp_ptr = (tANI_U8 *) dest_ptr; + *dest_ptr = (temp_ptr[0] << 24) | (temp_ptr[1] << 16) | (temp_ptr[2] << 8) | temp_ptr[3]; + dest_ptr++; + size -= 4; + } +} + + +void CreateScanDataNullFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, + tANI_U8 pwrMgmt, tSirMacAddr bssid, tSirMacAddr selfMacAddr) +{ + + macMgmtHdr->fc.type = SIR_MAC_DATA_FRAME; + macMgmtHdr->fc.subType = SIR_MAC_DATA_NULL; + macMgmtHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + macMgmtHdr->fc.order = 0; + macMgmtHdr->fc.wep = 0; + macMgmtHdr->fc.moreData =0; + macMgmtHdr->fc.powerMgmt = pwrMgmt; + macMgmtHdr->fc.retry = 0; + macMgmtHdr->fc.moreFrag = 0; + macMgmtHdr->fc.fromDS = 0; + macMgmtHdr->fc.toDS = 0; + macMgmtHdr->durationLo = (tANI_U8) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = (tANI_U8) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + macMgmtHdr->seqControl.fragNum = 0; + macMgmtHdr->seqControl.seqNumLo = 0; + macMgmtHdr->seqControl.seqNumHi = 2; + vos_mem_copy( (void *)&macMgmtHdr->da, + (void *)bssid, sizeof(tSirMacAddr)); + vos_mem_copy( (void *)&macMgmtHdr->sa, + (void *)selfMacAddr, sizeof(tSirMacAddr)); + vos_mem_copy( (void *)&macMgmtHdr->bssId, + (void *)bssid, sizeof(tSirMacAddr)); + + return; +} + + +void CreateScanCtsFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, tSirMacAddr selfMac) +{ + macMgmtHdr->fc.type = SIR_MAC_CTRL_FRAME; + macMgmtHdr->fc.subType = SIR_MAC_CTRL_CTS; + macMgmtHdr->fc.order = 0; + macMgmtHdr->fc.wep = 0; + macMgmtHdr->fc.moreData =0; + macMgmtHdr->fc.powerMgmt = 0; + macMgmtHdr->fc.retry = 0; + macMgmtHdr->fc.moreFrag = 0; + macMgmtHdr->fc.fromDS = 0; + macMgmtHdr->fc.toDS = 0; + macMgmtHdr->durationLo = (tANI_U8) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = (tANI_U8) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + vos_mem_copy( (void *)macMgmtHdr->da, (void *)selfMac, sizeof(tSirMacAddr)); + + return; +} + +void ConvertQosMapsetFrame(tpAniSirGlobal pMac, tSirQosMapSet* Qos, tDot11fIEQosMapSet* dot11fIE) +{ + tANI_U8 i,j=0; + if (dot11fIE->num_dscp_exceptions > 58) + dot11fIE->num_dscp_exceptions = 58; + Qos->num_dscp_exceptions = (dot11fIE->num_dscp_exceptions - 16)/2; + for (i = 0; i < Qos->num_dscp_exceptions; i++) + { + Qos->dscp_exceptions[i][0] = dot11fIE->dscp_exceptions[j]; + j++; + Qos->dscp_exceptions[i][1] = dot11fIE->dscp_exceptions[j]; + j++; + } + for (i = 0; i < 8; i++) + { + Qos->dscp_range[i][0] = dot11fIE->dscp_exceptions[j]; + j++; + Qos->dscp_range[i][1] = dot11fIE->dscp_exceptions[j]; + j++; + } +} + +/** + @brief : This functions creates a DATA_NULL/CTS2SELF frame in Big endian format + @param : Global MAC structure, pointer to return the created packet, role which is Station/AP + @return : void +*/ + +void CreateInitScanRawFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, tBssSystemRole role) +{ +#if 0 + tpStaStruct pSta = (tpStaStruct) pMac->hal.halMac.staTable; + + if (role == eSYSTEM_STA_ROLE) + { + macMgmtHdr->fc.type = SIR_MAC_DATA_FRAME; + macMgmtHdr->fc.subType = SIR_MAC_DATA_NULL; + macMgmtHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + macMgmtHdr->fc.order = 0; + macMgmtHdr->fc.wep = 0; + macMgmtHdr->fc.moreData =0; + macMgmtHdr->fc.powerMgmt = 1; // Needed for station + macMgmtHdr->fc.retry = 0; + macMgmtHdr->fc.moreFrag = 0; + macMgmtHdr->fc.fromDS = 0; + macMgmtHdr->fc.toDS = 1; + macMgmtHdr->durationLo = (tANI_U8) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = (tANI_U8) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + macMgmtHdr->seqControl.fragNum = 0; + macMgmtHdr->seqControl.seqNumLo = 0; + macMgmtHdr->seqControl.seqNumHi = 2; + vos_mem_copy( (void *)&macMgmtHdr->da, (void *)pSta[0].bssId, 6); + vos_mem_copy( &macMgmtHdr->sa, pSta[0].staAddr, 6); + vos_mem_copy( (void *)&macMgmtHdr->bssId, (void *)pSta[0].bssId, 6); + } + else if (role == eSYSTEM_AP_ROLE || role == eSYSTEM_STA_IN_IBSS_ROLE) + { + macMgmtHdr->fc.type = SIR_MAC_CTRL_FRAME; + macMgmtHdr->fc.subType = SIR_MAC_CTRL_CTS; + macMgmtHdr->fc.order = 0; + macMgmtHdr->fc.wep = 0; + macMgmtHdr->fc.moreData =0; + macMgmtHdr->fc.powerMgmt = 0; // Needed for station + macMgmtHdr->fc.retry = 0; + macMgmtHdr->fc.moreFrag = 0; + macMgmtHdr->fc.fromDS = 0; + macMgmtHdr->fc.toDS = 0; + macMgmtHdr->durationLo = (tANI_U8) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = (tANI_U8) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + vos_mem_copy( (void *)macMgmtHdr->da, (void *)pSta[0].staAddr, 6); + } + return; +#endif +} + +/** + @brief : This functions creates a DATA_NULL frame in Big endian format + @param : Global MAC structure, pointer to return the created packet, role which is Station/AP + @return : void +*/ + + +void CreateFinishScanRawFrame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, tBssSystemRole role) +{ +#if 0 + tpStaStruct pSta = (tpStaStruct) pMac->hal.halMac.staTable; + + if (role == eSYSTEM_STA_ROLE) + { + macMgmtHdr->fc.type = SIR_MAC_DATA_FRAME; + macMgmtHdr->fc.subType = SIR_MAC_DATA_NULL; + macMgmtHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + macMgmtHdr->fc.order = 0; + macMgmtHdr->fc.wep = 0; + macMgmtHdr->fc.moreData =0; + macMgmtHdr->fc.powerMgmt = 0; // Needed for station + macMgmtHdr->fc.retry = 0; + macMgmtHdr->fc.moreFrag = 0; + macMgmtHdr->fc.fromDS = 0; + macMgmtHdr->fc.toDS = 1; + macMgmtHdr->durationLo = (tANI_U8) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = (tANI_U8) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + macMgmtHdr->seqControl.fragNum = 0; + macMgmtHdr->seqControl.seqNumLo = 0; + macMgmtHdr->seqControl.seqNumHi = 2; + vos_mem_copy( (void *)macMgmtHdr->da, (void *)pSta[0].bssId, 6); + vos_mem_copy( macMgmtHdr->sa, pSta[0].staAddr, 6); + vos_mem_copy( (void *)macMgmtHdr->bssId, (void *)pSta[0].bssId, 6); + + } + + return; +#endif +} + + +// utilsParser.c ends here. diff --git a/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h b/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h new file mode 100644 index 000000000000..cce1f478458b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h @@ -0,0 +1,3012 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef WLAN_QCT_WLANTL_H +#define WLAN_QCT_WLANTL_H + +/*=========================================================================== + + W L A N T R A N S P O R T L A Y E R + E X T E R N A L A P I + + +DESCRIPTION + This file contains the external API exposed by the wlan transport layer + module. +===========================================================================*/ + + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + +when who what, where, why +-------- --- ---------------------------------------------------------- +01/08/10 lti Added TL Data Caching +10/15/09 rnair Modifying STADescType struct +10/06/09 rnair Adding support for WAPI +09/22/09 lti Add deregistration API for management client +02/02/09 sch Add Handoff support +12/09/08 lti Fixes for AMSS compilation +09/05/08 lti Fixes after QOS unit testing +08/06/08 lti Added QOS support +05/01/08 lti Created module. + +===========================================================================*/ + + + +/*=========================================================================== + + INCLUDE FILES FOR MODULE + +===========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "vos_api.h" +#include "vos_packet.h" +#include "sirApi.h" +#include "csrApi.h" +#include "sapApi.h" +#include "adf_nbuf.h" +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + #ifdef __cplusplus + extern "C" { + #endif + +/*Offset of the OUI field inside the LLC/SNAP header*/ +#define WLANTL_LLC_OUI_OFFSET 3 + +/*Size of the OUI type field inside the LLC/SNAP header*/ +#define WLANTL_LLC_OUI_SIZE 3 + +/*Offset of the LLC/SNAP header*/ +#define WLANTL_LLC_SNAP_OFFSET 0 + +/*Size of the LLC/SNAP header*/ +#define WLANTL_LLC_SNAP_SIZE 8 + +/*============================================================================ + * GENERIC STRUCTURES - not belonging to TL + * TO BE MOVED TO A GLOBAL HEADER + ============================================================================*/ +/*Maximum number of ACs */ +#define WLANTL_MAX_AC 4 + +/* Maximum number of station supported by TL, including BC. */ +#define WLAN_MAX_STA_COUNT (HAL_NUM_STA) +#define WLAN_NON32_STA_COUNT 14 +/* The symbolic station ID return to HDD to specify the packet is bc/mc */ +#define WLAN_RX_BCMC_STA_ID (WLAN_MAX_STA_COUNT + 1) + +/* The symbolic station ID return to HDD to specify the packet is to soft-AP itself */ +#define WLAN_RX_SAP_SELF_STA_ID (WLAN_MAX_STA_COUNT + 2) + +/* Used by HDS systme. This station ID is used by TL to tell upper layer that + this packet is for WDS and not for a loopback for an associated station. */ +#define WLANTL_RX_WDS_STAID WLAN_MAX_STA_COUNT + +/* Station ID used for BC traffic. This value will be used when upper layer registers + the broadcast client or allocate station strcuture to keep per-station info.*/ +//#define WLANTL_BC_STA_ID 0x00 + + +#define WLANTL_MAX_TID 15 +/* Default RSSI average Alpha */ +#define WLANTL_HO_DEFAULT_ALPHA 5 +#define WLANTL_HO_TDLS_ALPHA 7 + +// Choose the largest possible value that can be accomodates in 8 bit signed +// variable. +#define SNR_HACK_BMPS (127) +/*-------------------------------------------------------------------------- + Access category enum used by TL + - order must be kept as these values are used to setup the AC mask + --------------------------------------------------------------------------*/ +typedef enum +{ + WLANTL_AC_BK = 0, + WLANTL_AC_BE = 1, + WLANTL_AC_VI = 2, + WLANTL_AC_VO = 3 +}WLANTL_ACEnumType; + +/*--------------------------------------------------------------------------- + STA Type +---------------------------------------------------------------------------*/ +typedef enum +{ + /* Indicates a link to an AP*/ + WLAN_STA_INFRA = 0, + + /* AD-hoc link*/ + WLAN_STA_IBSS, + + /* SoftAP station */ + WLAN_STA_SOFTAP, + +#ifdef FEATURE_WLAN_TDLS + /* TDLS direct link */ + WLAN_STA_TDLS, +#endif + + WLAN_STA_OCB, + + /* Invalid link*/ + WLAN_STA_MAX + +}WLAN_STAType; + +/* Type used to specify LWM threshold unit */ +typedef enum { + WLAN_LWM_THRESHOLD_BYTE = 0, + + WLAN_LWM_THRESHOLD_PACKET +} WLAN_LWM_Threshold_Type; + +/*--------------------------------------------------------------------------- + TL States +---------------------------------------------------------------------------*/ +typedef enum +{ + /* Transition in this state made upon creation*/ + WLANTL_STA_INIT = 0, + + /* Transition happens after Assoc success if second level authentication + is needed*/ + WLANTL_STA_CONNECTED, + + /* Transition happens when second level auth is successful and keys are + properly installed */ + WLANTL_STA_AUTHENTICATED, + + /* Transition happens when connectivity is lost*/ + WLANTL_STA_DISCONNECTED, + + WLANTL_STA_MAX_STATE +}WLANTL_STAStateType; + +/*--------------------------------------------------------------------------- + STA Descriptor Type +---------------------------------------------------------------------------*/ +typedef struct +{ + /*STA unique identifier, originating from HAL*/ + v_U8_t ucSTAId; + + /*STA MAC Address*/ + v_MACADDR_t vSTAMACAddress; + + /*BSSID for IBSS*/ + v_MACADDR_t vBSSIDforIBSS; + + /*Self MAC Address*/ + v_MACADDR_t vSelfMACAddress; + + /*Type of the STA*/ + WLAN_STAType wSTAType; + + /*flag for setting the state of the QOS for the link*/ + v_U8_t ucQosEnabled; + + /*enable FT in TL */ + v_U8_t ucSwFrameTXXlation; + v_U8_t ucSwFrameRXXlation; + + /*Flag for signaling TL if LLC header needs to be added for outgoing + packets*/ + v_U8_t ucAddRmvLLC; + + /*Flag for signaling if the privacy bit needs to be set*/ + v_U8_t ucProtectedFrame; + + /*DPU Signature used for unicast data - used for data caching*/ + v_U8_t ucUcastSig; + /*Flag to indicate if STA is a WAPI STA*/ + v_U8_t ucIsWapiSta; + +#ifdef FEATURE_WLAN_ESE + /*Flag to indicate if STA is a ESE STA*/ + v_U8_t ucIsEseSta; +#endif + + /*DPU Signature used for broadcast data - used for data caching*/ + v_U8_t ucBcastSig; + + /*Initial state at which the STA should be brought up to*/ + WLANTL_STAStateType ucInitState; + /* 1 means replay check is needed for the station, + 0 means replay check is not needed for the station*/ + v_BOOL_t ucIsReplayCheckValid; +}WLAN_STADescType; + +/*--------------------------------------------------------------------------- + TL Configuration +---------------------------------------------------------------------------*/ +typedef struct +{ + /*Delayed trigger frame timmer: - used by TL to send trigger frames less + often when it has established that the App is suspended*/ + v_U32_t uDelayedTriggerFrmInt; + + /* Min Threshold for Processing Frames in TL */ + v_U8_t uMinFramesProcThres; + + /* Ip checksum offload */ + v_BOOL_t ip_checksum_offload; + + /* Rx processing in thread from TL shim */ + v_BOOL_t enable_rxthread; + +}WLANTL_ConfigInfoType; + +/*--------------------------------------------------------------------------- + TSPEC Direction Enum Type +---------------------------------------------------------------------------*/ +typedef enum +{ + /* uplink */ + WLANTL_TX_DIR = 0, + + /* downlink */ + WLANTL_RX_DIR = 1, + + /*bidirectional*/ + WLANTL_BI_DIR = 2, +}WLANTL_TSDirType; + +/*============================================================================ + * GENERIC STRUCTURES - END + ============================================================================*/ + + + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + TL Error Type +---------------------------------------------------------------------------*/ +typedef enum +{ + /* Generic error */ + WLANTL_ERROR = 0, + + /* No rx callback registered for data path */ + WLANTL_NO_RX_DATA_CB, + + /* No rx callback registered for management path*/ + WLANTL_NO_RX_MGMT_CB, + + /* Generic memory error*/ + WLANTL_MEM_ERROR, + + /* Bus error notified by BAL */ + WLANTL_BUS_ERROR + +}WLANTL_ErrorType; + +/*--------------------------------------------------------------------------- + STA priority type +---------------------------------------------------------------------------*/ +typedef enum +{ + /* STA gets to tx every second round*/ + WLANTL_STA_PRI_VERY_LOW = -2, + + /* STA gets to tx every other round*/ + WLANTL_STA_PRI_LOW = -1, + + /* STA gets to tx each time */ + WLANTL_STA_PRI_NORMAL = 0, + + /* STA gets to tx twice each time*/ + WLANTL_STA_PRI_HIGH = 1, + + /* STA gets to tx three times each time*/ + WLANTL_STA_PRI_VERY_HIGH = 2 + +}WLANTL_STAPriorityType; + +/*--------------------------------------------------------------------------- + Meta information requested from HDD by TL +---------------------------------------------------------------------------*/ +typedef struct +{ + /* TID of the packet being sent */ + v_U8_t ucTID; + + /* UP of the packet being sent */ + v_U8_t ucUP; + + /* notifying TL if this is an EAPOL frame or not */ + v_U8_t ucIsEapol; +#ifdef FEATURE_WLAN_WAPI + /* notifying TL if this is a WAI frame or not */ + v_U8_t ucIsWai; +#endif + /* frame is 802.11 and it does not need translation */ + v_U8_t ucDisableFrmXtl; + + /* frame is broadcast */ + v_U8_t ucBcast; + + /* frame is multicast */ + v_U8_t ucMcast; + + /* frame type */ + v_U8_t ucType; + + /* timestamp */ + v_U16_t usTimeStamp; + + /* STA has more packets to send */ + v_BOOL_t bMorePackets; +}WLANTL_MetaInfoType; + +/*--------------------------------------------------------------------------- + Meta information provided by TL to HDD on rx path +---------------------------------------------------------------------------*/ +typedef struct +{ + /* UP of the packet being sent */ + v_U8_t ucUP; + /* Address 3 Index of the received packet */ + v_U16_t ucDesSTAId; + /*Rssi based on the received packet */ + v_S7_t rssiAvg; + #ifdef FEATURE_WLAN_TDLS + /* Packet received on direct link/AP link */ + v_U8_t isStaTdls; + #endif +}WLANTL_RxMetaInfoType; + + +/*--------------------------------------------------------------------------- + Handoff support and statistics defines and enum types +---------------------------------------------------------------------------*/ +/* Threshold crossed event type definitions */ +#define WLANTL_HO_THRESHOLD_NA 0x00 +#define WLANTL_HO_THRESHOLD_DOWN 0x01 +#define WLANTL_HO_THRESHOLD_UP 0x02 +#define WLANTL_HO_THRESHOLD_CROSS 0x04 + +/* Realtime traffic status */ +typedef enum +{ + WLANTL_HO_RT_TRAFFIC_STATUS_OFF, + WLANTL_HO_RT_TRAFFIC_STATUS_ON +} WLANTL_HO_RT_TRAFFIC_STATUS_TYPE; + +/* Non-Realtime traffic status */ +typedef enum +{ + WLANTL_HO_NRT_TRAFFIC_STATUS_OFF, + WLANTL_HO_NRT_TRAFFIC_STATUS_ON +} WLANTL_HO_NRT_TRAFFIC_STATUS_TYPE; + +/* Statistics type TL supported */ +typedef enum +{ + WLANTL_STATIC_TX_UC_FCNT, + WLANTL_STATIC_TX_MC_FCNT, + WLANTL_STATIC_TX_BC_FCNT, + WLANTL_STATIC_TX_UC_BCNT, + WLANTL_STATIC_TX_MC_BCNT, + WLANTL_STATIC_TX_BC_BCNT, + WLANTL_STATIC_RX_UC_FCNT, + WLANTL_STATIC_RX_MC_FCNT, + WLANTL_STATIC_RX_BC_FCNT, + WLANTL_STATIC_RX_UC_BCNT, + WLANTL_STATIC_RX_MC_BCNT, + WLANTL_STATIC_RX_BC_BCNT, + WLANTL_STATIC_RX_BCNT, + WLANTL_STATIC_RX_BCNT_CRC_OK, + WLANTL_STATIC_RX_RATE +} WLANTL_TRANSFER_STATIC_TYPE; + +/*--------------------------------------------------------------------------- + Handoff support and statistics structures +---------------------------------------------------------------------------*/ +typedef struct +{ + WLANTL_HO_RT_TRAFFIC_STATUS_TYPE rtTrafficStatus; + WLANTL_HO_NRT_TRAFFIC_STATUS_TYPE nrtTrafficStatus; +} WLANTL_HO_TRAFFIC_STATUS_TYPE; + +typedef tSap_SoftapStats WLANTL_TRANSFER_STA_TYPE; + +/* Under here not public items, just use for internal */ +/* 3 SME 1 HDD */ +#define WLANTL_MAX_AVAIL_THRESHOLD 5 +#define WLANTL_HS_NUM_CLIENT 2 +#define WLANTL_SINGLE_CLNT_THRESHOLD 4 + +/*---------------------------------------------------------------------------- + * TL callback types + *--------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + DESCRIPTION + Type of the tx complete callback registered with TL. + + TL will call this to notify the client when a transmission for a + packet has ended. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to + TL/HAL/PE/HDD control block can be extracted from + its context + vosDataBuff: pointer to the VOSS data buffer that was transmitted + wTxSTAtus: status of the transmission + + + RETURN VALUE + The result code associated with performing the operation + +----------------------------------------------------------------------------*/ +typedef VOS_STATUS (*WLANTL_TxCompCBType)( v_PVOID_t pvosGCtx, + vos_pkt_t* pFrameDataBuff, + VOS_STATUS wTxSTAtus ); + + +/*---------------------------------------------------------------------------- + INTERACTION WITH HDD + ---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + + DESCRIPTION + Type of the fetch packet callback registered with TL. + + It is called by the TL when the scheduling algorithms allows for + transmission of another packet to the module. + It will be called in the context of the BAL fetch transmit packet + function, initiated by the bus lower layer. + + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle + to TL's or HDD's control block can be extracted + from its context + + IN/OUT + pucSTAId: the Id of the station for which TL is requesting a + packet, in case HDD does not maintain per station + queues it can give the next packet in its queue + and put in the right value for the + pucAC: access category requested by TL, if HDD does not have + packets on this AC it can choose to service another AC + queue in the order of priority + + OUT + vosDataBuff: pointer to the VOSS data buffer that was transmitted + tlMetaInfo: meta info related to the data frame + + + + RETURN VALUE + The result code associated with performing the operation + +----------------------------------------------------------------------------*/ +typedef VOS_STATUS (*WLANTL_STAFetchPktCBType)( + v_PVOID_t pvosGCtx, + v_U8_t* pucSTAId, + WLANTL_ACEnumType ucAC, + vos_pkt_t** vosDataBuff, + WLANTL_MetaInfoType* tlMetaInfo); + + +/*---------------------------------------------------------------------------- + + DESCRIPTION + Type of the receive callback registered with TL. + + TL will call this to notify the client when a packet was received + for a registered STA. This version of rx callback will have HDD + adapter pointer and received data buffer in adf_nbuf format. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to + TL's or HDD's control block can be extracted from + its context + pDataBuff: pointer to the adf_nbuf data buffer that was received + (it may be a linked list) + ucSTAId: station id + + RETURN VALUE + The result code associated with performing the operation + +----------------------------------------------------------------------------*/ +typedef VOS_STATUS (*WLANTL_STARxCBType)(v_PVOID_t pvosGCtx, + adf_nbuf_t pDataBuff, + v_U8_t ucSTAId); + +#ifdef QCA_LL_TX_FLOW_CT +/*---------------------------------------------------------------------------- + + DESCRIPTION + Type of the TX Flow Control callback registered with TL. + + TL will call this to notify the client when TX resource condition + is chnaged + + PARAMETERS + + IN + adapterCtxt: pointer to device apapter context + resume_tx: Ressume OS TX Q + + RETURN VALUE + NONE + +----------------------------------------------------------------------------*/ +typedef void (*WLANTL_TxFlowControlCBType)(void *adapterCtxt, + v_BOOL_t resume_tx); +#endif /* QCA_LL_TX_FLOW_CT */ + +/*---------------------------------------------------------------------------- + INTERACTION WITH PE + ---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + DESCRIPTION + Type of the receive callback registered with TL for PE. + + Upon receipt of a management frame TL will call the registered receive + callback and forward this frame to the interested module, in our case PE. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + vosFrmBuf: pointer to a vOSS buffer containing the management frame + received + + RETURN VALUE + The result code associated with performing the operation + +----------------------------------------------------------------------------*/ +typedef VOS_STATUS (*WLANTL_MgmtFrmRxCBType)( v_PVOID_t pvosGCtx, + v_PVOID_t vosBuff); + + +/*---------------------------------------------------------------------------- + INTERACTION WITH HAL + ---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + DESCRIPTION + Type of the fetch packet callback registered with TL. + + HAL calls this API when it wishes to suspend transmission for a + particular STA. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station for which the request is made; + a value of 0 assumes suspend on all active station + pfnSuspendTxCB: pointer to the suspend result notification in case the + call is asynchronous + + RETURN VALUE + The result code associated with performing the operation + +----------------------------------------------------------------------------*/ +typedef VOS_STATUS (*WLANTL_SuspendCBType)( v_PVOID_t pvosGCtx, + v_U8_t* ucSTAId, + VOS_STATUS vosStatus); + + +/*========================================================================== + + DESCRIPTION + Traffic status changed callback function + Should be registered to let client know that traffic status is changed + REF WLANTL_RegGetTrafficStatus + + PARAMETERS + pAdapter Global handle pointer + trafficStatus RT and NRT current traffic status + pUserCtxt pre registered client context + + RETURN VALUE + VOS_STATUS + + SIDE EFFECTS + NONE + +============================================================================*/ +/* IF traffic status is changed, send notification to SME */ +typedef VOS_STATUS (*WLANTL_TrafficStatusChangedCBType) +( + v_PVOID_t pAdapter, + WLANTL_HO_TRAFFIC_STATUS_TYPE trafficStatus, + v_PVOID_t pUserCtxt +); + +/*========================================================================== + + DESCRIPTION + RSSI threshold crossed notification callback function + REF WLANTL_RegRSSIIndicationCB + + PARAMETERS + pAdapter Global handle pointer + rssiNotification Notification event type + pUserCtxt pre registered client context + + RETURN VALUE + + SIDE EFFECTS + +============================================================================*/ +/* If RSSI realm is changed, send notification to Clients, SME, HDD */ +typedef VOS_STATUS (*WLANTL_RSSICrossThresholdCBType) +( + v_PVOID_t pAdapter, + v_U8_t rssiNotification, + v_PVOID_t pUserCtxt, + v_S7_t avgRssi +); + +typedef struct +{ + // Common for all types are requests + v_U16_t msgType; // message type is same as the request type + v_U16_t msgLen; // length of the entire request + v_U8_t sessionId; //sme Session Id + v_U8_t rssiNotification; + v_U8_t avgRssi; + v_PVOID_t tlCallback; + v_PVOID_t pAdapter; + v_PVOID_t pUserCtxt; +} WLANTL_TlIndicationReq; + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANTL_Open + + DESCRIPTION + Called by HDD at driver initialization. TL will initialize all its + internal resources and will wait for the call to start to register + with the other modules. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + pTLConfig: TL Configuration + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_Open +( + v_PVOID_t pvosGCtx, + WLANTL_ConfigInfoType* pTLConfig +); + +/*========================================================================== + + FUNCTION WLANTL_Start + + DESCRIPTION + Called by HDD as part of the overall start procedure. TL will use this + call to register with BAL as a transport layer entity. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + Other codes can be returned as a result of a BAL failure; see BAL API + for more info + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_Start +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + + FUNCTION WLANTL_Stop + + DESCRIPTION + Called by HDD to stop operation in TL, before close. TL will suspend all + frame transfer operation and will wait for the close request to clean up + its resources. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_Stop +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + + FUNCTION WLANTL_Close + + DESCRIPTION + Called by HDD during general driver close procedure. TL will clean up + all the internal resources. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_Close +( + v_PVOID_t pvosGCtx +); + + +/*---------------------------------------------------------------------------- + INTERACTION WITH HDD + ---------------------------------------------------------------------------*/ +/*========================================================================== + + FUNCTION WLANTL_ConfigureSwFrameTXXlationForAll + + DESCRIPTION + Function to disable/enable frame translation for all association stations. + + DEPENDENCIES + + PARAMETERS + IN + pvosGCtx: VOS context + EnableFrameXlation TRUE means enable SW translation for all stations. + . + + RETURN VALUE + + void. + +============================================================================*/ +void +WLANTL_ConfigureSwFrameTXXlationForAll +( + v_PVOID_t pvosGCtx, + v_BOOL_t enableFrameXlation +); + +/*=========================================================================== + + FUNCTION WLANTL_RegisterSTAClient + + DESCRIPTION + + This function is used by HDD to register as a client for data services + with TL. HDD will call this API for each new station that it adds, + thus having the flexibility of registering different callback for each + STA it services. + + DEPENDENCIES + + TL must have been initialized before this gets called. + + Restriction: + Main thread will have higher priority that Tx and Rx threads thus + guaranteeing that a station will be added before any data can be + received for it. (This enables TL to be lock free) + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + pfnStARx: function pointer to the receive packet handler from HDD + pfnSTATxComp: function pointer to the transmit complete confirmation + handler from HDD + pfnSTAFetchPkt: function pointer to the packet retrieval routine in HDD + wSTADescType: STA Descriptor, contains information related to the + new added STA + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was already registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_RegisterSTAClient +( + v_PVOID_t pvosGCtx, + WLANTL_STARxCBType pfnSTARx, + WLANTL_TxCompCBType pfnSTATxComp, + WLANTL_STAFetchPktCBType pfnSTAFetchPkt, + WLAN_STADescType* wSTADescType , + v_S7_t rssi +); + +/*=========================================================================== + + FUNCTION WLANTL_ClearSTAClient + + DESCRIPTION + + HDD will call this API when it no longer needs data services for the + particular station. + + DEPENDENCIES + + A station must have been registered before the clear registration is + called. + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier for the STA to be cleared + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_ClearSTAClient +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId +); + +/*=========================================================================== + + FUNCTION WLANTL_ChangeSTAState + + DESCRIPTION + + HDD will make this notification whenever a change occurs in the + connectivity state of a particular STA. + + DEPENDENCIES + + A station must have been registered before the change state can be + called. + + RESTRICTION: A station is being notified as authenticated before the + keys are installed in HW. This way if a frame is received + before the keys are installed DPU will drop that frame. + + Main thread has higher priority that Tx and Rx threads thus guaranteeing + the following: + - a station will be in assoc state in TL before TL receives any data + for it + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier for the STA that is pending transmission + tlSTAState: the new state of the connection to the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_ChangeSTAState +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + WLANTL_STAStateType tlSTAState, + v_BOOL_t roamSynchInProgress +); + +/*=========================================================================== + + FUNCTION WLANTL_STAPtkInstalled + + DESCRIPTION + + HDD will make this notification whenever PTK is installed for the STA + + DEPENDENCIES + + A station must have been registered before the change state can be + called. + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier for the STA for which Pairwise key is + installed + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_STAPtkInstalled +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId +); +/*=========================================================================== + + FUNCTION WLANTL_GetSTAState + + DESCRIPTION + + Returns connectivity state of a particular STA. + + DEPENDENCIES + + A station must have been registered before its state can be retrieved. + + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + + OUT + ptlSTAState: the current state of the connection to the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +static inline VOS_STATUS +WLANTL_GetSTAState +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + WLANTL_STAStateType *ptlSTAState +) +{ + return VOS_STATUS_SUCCESS; +} + +/*=========================================================================== + + FUNCTION WLANTL_STAPktPending + + DESCRIPTION + + HDD will call this API when a packet is pending transmission in its + queues. + + DEPENDENCIES + + A station must have been registered before the packet pending + notification can be sent. + + RESTRICTION: TL will not count packets for pending notification. + HDD is expected to send the notification only when + non-empty event gets triggered. Worst case scenario + is that TL might end up making a call when Hdds + queues are actually empty. + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier for the STA that is pending transmission + ucAC: access category of the non-empty queue + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_STAPktPending +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + WLANTL_ACEnumType ucAc +); + +/*=========================================================================== + + FUNCTION WLANTL_SendSTA_DataFrame + + DESCRIPTION + + HDD will call this API when there is a packet to be transmitted + + DEPENDENCIES + + A station must have been registered before sending packet to txrx layer + + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier for the STA that is pending transmission + buf: packet given by uppler layer for tx + + RETURN VALUE + + On success it will return NULL. On failure it will be the + passed buf pointer so that the caller will be able to free + up the buffer. + +============================================================================*/ +adf_nbuf_t WLANTL_SendSTA_DataFrame(v_PVOID_t pvosGCtx, v_U8_t ucSTAId, + adf_nbuf_t buf +#ifdef QCA_PKT_PROTO_TRACE + , v_U8_t proto_type +#endif /* QCA_PKT_PROTO_TRACE */ + ); + +#ifdef IPA_OFFLOAD +/*=========================================================================== + + FUNCTION WLANTL_SendIPA_DataFrame + + DESCRIPTION + + HDD will call this API when there is a packet to be transmitted from IPA + + DEPENDENCIES + + A station must have been registered before sending packet to txrx layer + + + PARAMETERS + + vos_ctx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + vdev: virtual device + buf: packet given by uppler layer for tx + + RETURN VALUE + + On success it will return NULL. On failure it will be the + passed buf pointer so that the caller will be able to free + up the buffer. + +============================================================================*/ +adf_nbuf_t WLANTL_SendIPA_DataFrame(void *vos_ctx, void *vdev, + adf_nbuf_t buf, v_U8_t interface_id); +#endif + + +/*========================================================================== + + FUNCTION WLANTL_SetSTAPriority + + DESCRIPTION + + TL exposes this API to allow upper layers a rough control over the + priority of transmission for a given station when supporting multiple + connections. + + DEPENDENCIES + + A station must have been registered before the change in priority can be + called. + + PARAMETERS + + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier for the STA that has to change priority + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_SetSTAPriority +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + WLANTL_STAPriorityType tlSTAPri +); + +/*---------------------------------------------------------------------------- + INTERACTION WITH SME + ---------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANTL_GetRssi + + DESCRIPTION + TL will extract the RSSI information from every data packet from the + ongoing traffic and will store it. It will provide the result to SME + upon request. + + DEPENDENCIES + + WARNING: the read and write of this value will not be protected + by locks, therefore the information obtained after a read + might not always be consistent. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or SME's control block can be extracted from its context + ucSTAId: station identifier for the requested value + + OUT + puRssi: the average value of the RSSI + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: STA was not yet registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ + +VOS_STATUS +WLANTL_GetRssi +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_S7_t* puRssi, + v_PVOID_t pGetRssiReq +); +/*========================================================================== + + FUNCTION WLANTL_GetSnr + + DESCRIPTION + TL will extract the SNR information from every data packet from the + ongoing traffic and will store it. It will provide the result to SME + upon request. + + DEPENDENCIES + + WARNING: the read and write of this value will not be protected + by locks, therefore the information obtained after a read + might not always be consistent. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or SME's control block can be extracted from its context + ucSTAId: station identifier for the requested value + + OUT + puSnr: the average value of the SNR + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: STA was not yet registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_GetSnr +( + tANI_U8 ucSTAId, + tANI_S8* pSnr +); + +/*========================================================================== + + FUNCTION WLANTL_GetLinkQuality + + DESCRIPTION + TL will extract the LinkQuality information from every data packet from the + ongoing traffic and will store it. It will provide the result to SME + upon request. + + DEPENDENCIES + + WARNING: the read and write of this value will not be protected + by locks, therefore the information obtained after a read + might not always be consistent. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or SME's control block can be extracted from its context + ucSTAId: station identifier for the requested value + + OUT + puLinkQuality: the average value of the LinkQuality + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: STA was not yet registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_GetLinkQuality +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U32_t* puLinkQuality +); + +/*---------------------------------------------------------------------------- + INTERACTION WITH PE + ---------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANTL_RegisterMgmtFrmClient + + DESCRIPTION + Called by PE to register as a client for management frames delivery. + + DEPENDENCIES + TL must be initialized before this API can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to + TL's control block can be extracted from its context + pfnTlMgmtFrmRx: pointer to the receive processing routine for + management frames + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a + page fault + VOS_STATUS_E_EXISTS: Mgmt Frame client was already registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_RegisterMgmtFrmClient +( + v_PVOID_t pvosGCtx, + WLANTL_MgmtFrmRxCBType pfnTlMgmtFrmRx +); + +/*========================================================================== + + FUNCTION WLANTL_DeRegisterMgmtFrmClient + + DESCRIPTION + Called by PE to deregister as a client for management frames delivery. + + DEPENDENCIES + TL must be initialized before this API can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to + TL's control block can be extracted from its context + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a + page fault + VOS_STATUS_E_EXISTS: Mgmt Frame client was never registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_DeRegisterMgmtFrmClient +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + + FUNCTION WLANTL_TxMgmtFrm + + DESCRIPTION + Called by PE when it want to send out a management frame. + HAL will also use this API for the few frames it sends out, they are not + management frames howevere it is accepted that an exception will be + allowed ONLY for the usage of HAL. + Generic data frames SHOULD NOT travel through this function. + + DEPENDENCIES + TL must be initialized before this API can be called. + + RESTRICTION: If PE sends another packet before TL manages to process the + previously sent packet call will end in failure + + Frames comming through here must be 802.11 frames, frame + translation in UMA will be automatically disabled. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context;a handle to TL's + control block can be extracted from its context + vosFrmBuf: pointer to a vOSS buffer containing the management + frame to be transmitted + usFrmLen: the length of the frame to be transmitted; information + is already included in the vOSS buffer + wFrmType: the type of the frame being transmitted + tid: tid used to transmit this frame + pfnCompTxFunc: function pointer to the transmit complete routine + pvBDHeader: pointer to the BD header, if NULL it means it was not + yet constructed and it lies within TL's responsibility + to do so; if not NULL it is expected that it was + already packed inside the vos packet + ucAckResponse: flag notifying it an interrupt is needed for the + acknowledgement received when the frame is sent out + the air and ; the interrupt will be processed by HAL, + only one such frame can be pending in the system at + one time. + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a + page fault + VOS_STATUS_E_EXISTS: Mgmt Frame client was not yet registered + VOS_STATUS_E_BUSY: The previous Mgmt packet was not yet transmitted + VOS_STATUS_SUCCESS: Everything is good :) + + Other failure messages may be returned from the BD header handling + routines, please check apropriate API for more info. + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_TxMgmtFrm +( + v_PVOID_t pvosGCtx, + vos_pkt_t* vosFrmBuf, + v_U16_t usFrmLen, + v_U8_t ucFrmType, + v_U8_t tid, + WLANTL_TxCompCBType pfnCompTxFunc, + v_PVOID_t voosBDHeader, + v_U8_t ucAckResponse +); + + +/*---------------------------------------------------------------------------- + INTERACTION WITH HAL + ---------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANTL_ResetNotification + + DESCRIPTION + HAL notifies TL when the module is being reset. + Currently not used. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a + page fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_ResetNotification +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + + FUNCTION WLANTL_SuspendDataTx + + DESCRIPTION + HAL calls this API when it wishes to suspend transmission for a + particular STA. + + DEPENDENCIES + The STA for which the request is made must be first registered with + TL by HDD. + + RESTRICTION: In case of a suspend, the flag write and read will not be + locked: worst case scenario one more packet can get + through before the flag gets updated (we can make this + write atomic as well to guarantee consistency) + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + pucSTAId: identifier of the station for which the request is made; + a value of NULL assumes suspend on all active station + pfnSuspendTxCB: pointer to the suspend result notification in case the + call is asynchronous + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_SuspendDataTx +( + v_PVOID_t pvosGCtx, + v_U8_t* ucSTAId, + WLANTL_SuspendCBType pfnSuspendTx +); + +/*========================================================================== + + FUNCTION WLANTL_ResumeDataTx + + DESCRIPTION + Called by HAL to resume data transmission for a given STA. + + WARNING: If a station was individually suspended a global resume will + not resume that station + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + pucSTAId: identifier of the station which is being resumed; NULL + translates into global resume + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_ResumeDataTx +( + v_PVOID_t pvosGCtx, + v_U8_t* pucSTAId +); + + +/*---------------------------------------------------------------------------- + CLIENT INDEPENDENT INTERFACE + ---------------------------------------------------------------------------*/ + +/*========================================================================== + + FUNCTION WLANTL_GetTxPktCount + + DESCRIPTION + TL will provide the number of transmitted packets counted per + STA per TID. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + ucTid: identifier of the tspec + + OUT + puTxPktCount: the number of packets tx packet for this STA and TID + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_GetTxPktCount +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U8_t ucTid, + v_U32_t* puTxPktCount +); + +/*========================================================================== + + FUNCTION WLANTL_GetRxPktCount + + DESCRIPTION + TL will provide the number of received packets counted per + STA per TID. + + DEPENDENCIES + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + ucTid: identifier of the tspec + + OUT + puTxPktCount: the number of packets rx packet for this STA and TID + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer + to TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_GetRxPktCount +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U8_t ucTid, + v_U32_t* puRxPktCount +); + +/*========================================================================== + VOSS SCHEDULER INTERACTION + ==========================================================================*/ + +/*========================================================================== + FUNCTION WLANTL_McProcessMsg + + DESCRIPTION + Called by VOSS when a message was serialized for TL through the + main thread/task. + + DEPENDENCIES + The TL must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + message: type and content of the message + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: invalid input parameters + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a + page fault + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_McProcessMsg +( + v_PVOID_t pvosGCtx, + vos_msg_t* message +); + +/*========================================================================== + FUNCTION WLANTL_McFreeMsg + + DESCRIPTION + Called by VOSS to free a given TL message on the Main thread when there + are messages pending in the queue when the whole system is been reset. + For now, TL does not allocate any body so this function shout translate + into a NOOP + + DEPENDENCIES + The TL must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + message: type and content of the message + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_McFreeMsg +( + v_PVOID_t pvosGCtx, + vos_msg_t* message +); + +/*========================================================================== + FUNCTION WLANTL_TxProcessMsg + + DESCRIPTION + Called by VOSS when a message was serialized for TL through the + tx thread/task. + + DEPENDENCIES + The TL must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + message: type and content of the message + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: invalid input parameters + VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a + page fault + VOS_STATUS_SUCCESS: Everything is good :) + + Other values can be returned as a result of a function call, please check + corresponding API for more info. + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_TxProcessMsg +( + v_PVOID_t pvosGCtx, + vos_msg_t* message +); + +/*========================================================================== + FUNCTION WLANTL_McFreeMsg + + DESCRIPTION + Called by VOSS to free a given TL message on the Main thread when there + are messages pending in the queue when the whole system is been reset. + For now, TL does not allocate any body so this function shout translate + into a NOOP + + DEPENDENCIES + The TL must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + message: type and content of the message + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_TxFreeMsg +( + v_PVOID_t pvosGCtx, + vos_msg_t* message +); + + +/*========================================================================== + FUNCTION WLANTL_EnableUAPSDForAC + + DESCRIPTION + Called by HDD to enable UAPSD in TL. TL is in charge for sending trigger + frames. + + DEPENDENCIES + The TL must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: station Id + ucACId: AC for which U-APSD is being enabled + ucTid TSpec Id + uServiceInt: service interval used by TL to send trigger frames + uSuspendInt: suspend interval used by TL to determine that an + app is idle and should start sending trigg frms less often + wTSDir: direction of TSpec + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_EnableUAPSDForAC +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + WLANTL_ACEnumType ucACId, + v_U8_t ucTid, + v_U8_t ucUP, + v_U32_t uServiceInt, + v_U32_t uSuspendInt, + WLANTL_TSDirType wTSDir, + v_U8_t psb, + v_U32_t sessionId +); + + +/*========================================================================== + FUNCTION WLANTL_DisableUAPSDForAC + + DESCRIPTION + Called by HDD to disable UAPSD in TL. TL will stop sending trigger + frames. + + DEPENDENCIES + The TL must be initialized before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: station Id + ucACId: AC for which U-APSD is being enabled + + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_DisableUAPSDForAC +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + WLANTL_ACEnumType ucACId, + v_U32_t sessionId +); + +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING +/*========================================================================== + FUNCTION WLANTL_RegRSSIIndicationCB + + DESCRIPTION Registration function to get notification if RSSI cross + threshold. + Client should register threshold, direction, and notification + callback function pointer + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in rssiValue - RSSI threshold value + in triggerEvent - Cross direction should be notified + UP, DOWN, and CROSS + in crossCBFunction - Notification CB Function + in usrCtxt - user context + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_RegRSSIIndicationCB +( + v_PVOID_t pAdapter, + v_S7_t rssiValue, + v_U8_t triggerEvent, + WLANTL_RSSICrossThresholdCBType crossCBFunction, + VOS_MODULE_ID moduleID, + v_PVOID_t usrCtxt +); + +/*========================================================================== + FUNCTION WLANTL_DeregRSSIIndicationCB + + DESCRIPTION Remove specific threshold from list + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in rssiValue - RSSI threshold value + in triggerEvent - Cross direction should be notified + UP, DOWN, and CROSS + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_DeregRSSIIndicationCB +( + v_PVOID_t pAdapter, + v_S7_t rssiValue, + v_U8_t triggerEvent, + WLANTL_RSSICrossThresholdCBType crossCBFunction, + VOS_MODULE_ID moduleID +); + +/*========================================================================== + + FUNCTION + + DESCRIPTION + + PARAMETERS + + RETURN VALUE + +============================================================================*/ +VOS_STATUS WLANTL_BMPSRSSIRegionChangedNotification +( + v_PVOID_t pAdapter, + tpSirRSSINotification pRSSINotification +); + +/*========================================================================== + FUNCTION WLANTL_SetAlpha + + DESCRIPTION ALPLA is weight value to calculate AVG RSSI + avgRSSI = (ALPHA * historyRSSI) + ((10 - ALPHA) * newRSSI) + avgRSSI has (ALPHA * 10)% of history RSSI weight and + (10 - ALPHA)% of newRSSI weight + This portion is dynamically configurable. + Default is ? + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in valueAlpah - ALPHA + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_SetAlpha +( + v_PVOID_t pAdapter, + v_U8_t valueAlpha +); + +/*========================================================================== + FUNCTION WLANTL_RegGetTrafficStatus + + DESCRIPTION Registration function for traffic status monitoring + During measure period count data frames. + If frame count is larger then IDLE threshold set as traffic ON + or OFF. + And traffic status is changed send report to client with + registered callback function + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in idleThreshold - Traffic on or off threshold + in measurePeriod - Traffic state check period + in trfficStatusCB - traffic status changed notification + CB function + in usrCtxt - user context + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_RegGetTrafficStatus +( + v_PVOID_t pAdapter, + v_U32_t idleThreshold, + v_U32_t measurePeriod, + WLANTL_TrafficStatusChangedCBType trfficStatusCB, + v_PVOID_t usrCtxt +); +#endif +/*========================================================================== + FUNCTION WLANTL_GetStatistics + + DESCRIPTION Get traffic statistics for identified station + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in statType - specific statistics field to reset + out statBuffer - traffic statistics buffer + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_GetStatistics +( + v_PVOID_t pAdapter, + WLANTL_TRANSFER_STA_TYPE *statBuffer, + v_U8_t STAid +); + +/*========================================================================== + FUNCTION WLANTL_ResetStatistics + + DESCRIPTION Reset statistics structure for identified station ID + Reset means set values as 0 + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in statType - specific statistics field to reset + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_ResetStatistics +( + v_PVOID_t pAdapter, + v_U8_t STAid +); + +/*========================================================================== + FUNCTION WLANTL_GetSpecStatistic + + DESCRIPTION Get specific field within statistics structure for + identified station ID + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in statType - specific statistics field to reset + in STAid - Station ID + out buffer - Statistic value + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_GetSpecStatistic +( + v_PVOID_t pAdapter, + WLANTL_TRANSFER_STATIC_TYPE statType, + v_U32_t *buffer, + v_U8_t STAid +); + +/*========================================================================== + FUNCTION WLANTL_ResetSpecStatistic + + DESCRIPTION Reset specific field within statistics structure for + identified station ID + Reset means set as 0 + + DEPENDENCIES NONE + + PARAMETERS in pAdapter - Global handle + in statType - specific statistics field to reset + in STAid - Station ID + + RETURN VALUE VOS_STATUS + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_ResetSpecStatistic +( + v_PVOID_t pAdapter, + WLANTL_TRANSFER_STATIC_TYPE statType, + v_U8_t STAid +); +/*=============================================================================== + FUNCTION WLANTL_IsReplayPacket + + DESCRIPTION This function does replay check for valid stations + + DEPENDENCIES Validity of replay check must be done before the function + is called + + PARAMETERS currentReplayCounter current replay counter taken from RX BD + previousReplayCounter previous replay counter taken from TL CB + + RETRUN VOS_TRUE packet is a replay packet + VOS_FALSE packet is not a replay packet + + SIDE EFFECTS none + ===============================================================================*/ +v_BOOL_t WLANTL_IsReplayPacket +( + v_U64_t currentReplayCounter, + v_U64_t previousReplayCounter +); + +/*=============================================================================== + FUNCTION WLANTL_GetReplayCounterFromRxBD + + DESCRIPTION This function extracts 48-bit replay packet number from RX BD + + DEPENDENCIES Validity of replay check must be done before the function + is called + + PARAMETERS pucRxHeader pointer to RX BD header + + RETRUN v_U64_t Packet number extarcted from RX BD + + SIDE EFFECTS none + ===============================================================================*/ +v_U64_t +WLANTL_GetReplayCounterFromRxBD +( + v_U8_t *pucRxBDHeader +); + + +/*========================================================================== + FUNCTION WLANTL_GetSoftAPStatistics + + DESCRIPTION Collect the cumulative statistics for all Softap stations + + DEPENDENCIES NONE + + PARAMETERS in pvosGCtx - Pointer to the global vos context + bReset - If set TL statistics will be cleared after reading + out statsSum - pointer to collected statistics + + RETURN VALUE VOS_STATUS_SUCCESS : if the Statistics are successfully extracted + + SIDE EFFECTS NONE + +============================================================================*/ +VOS_STATUS WLANTL_GetSoftAPStatistics(v_PVOID_t pAdapter, WLANTL_TRANSFER_STA_TYPE *statsSum, v_BOOL_t bReset); + +#ifdef __cplusplus + } +#endif + + + /*=========================================================================== + + FUNCTION WLANTL_AssocFailed + + DESCRIPTION + + This function is used by PE to notify TL that cache needs to flushed + when association is not successfully completed + + Internally, TL post a message to TX_Thread to serialize the request to + keep lock-free mechanism. + + + DEPENDENCIES + + TL must have been initialized before this gets called. + + + PARAMETERS + + ucSTAId: station id + + RETURN VALUE + + none + + SIDE EFFECTS + There may be race condition that PE call this API and send another association + request immediately with same staId before TX_thread can process the message. + + To avoid this, we might need PE to wait for TX_thread process the message, + but this is not currently implemented. + +============================================================================*/ +void WLANTL_AssocFailed(v_U8_t staId); + + +/*=============================================================================== + FUNCTION WLANTL_PostResNeeded + + DESCRIPTION This function posts message to TL to reserve BD/PDU memory + + DEPENDENCIES None + + PARAMETERS pvosGCtx + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void WLANTL_PostResNeeded(v_PVOID_t pvosGCtx); + +/*=========================================================================== + + FUNCTION WLANTL_Finish_ULA + + DESCRIPTION + This function is used by HDD to notify TL to finish Upper layer authentication + incase the last EAPOL packet is pending in the TL queue. + To avoid the race condition between sme set key and the last EAPOL packet + the HDD module calls this function just before calling the sme_RoamSetKey. + + DEPENDENCIES + + TL must have been initialized before this gets called. + + + PARAMETERS + + callbackRoutine: HDD Callback function. + callbackContext : HDD userdata context. + + RETURN VALUE + + VOS_STATUS_SUCCESS/VOS_STATUS_FAILURE + + SIDE EFFECTS + +============================================================================*/ + +VOS_STATUS WLANTL_Finish_ULA( void (*callbackRoutine) (void *callbackContext), + void *callbackContext); + +/*=============================================================================== + FUNCTION WLANTL_UpdateRssiBmps + + DESCRIPTION This function updates the TL's RSSI (in BMPS mode) + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + rssi RSSI (BMPS mode) RSSI in BMPS mode + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void WLANTL_UpdateRssiBmps(v_PVOID_t pvosGCtx, v_U8_t staId, v_S7_t rssi); + +/*=============================================================================== + FUNCTION WLANTL_UpdateSnrBmps + + DESCRIPTION This function updates the TL's SNR (in BMPS mode) + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + snr SNR (BMPS mode) SNR in BMPS mode + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void WLANTL_UpdateSnrBmps(v_PVOID_t pvosGCtx, v_U8_t staId, v_S7_t snr); + +/*========================================================================== + FUNCTION WLANTL_SetTxXmitPending + + DESCRIPTION + Called by the WDA when it wants to indicate that WDA_DS_TX_START_XMIT msg + is pending in TL msg queue + + DEPENDENCIES + The TL must be registered with WDA before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_SetTxXmitPending +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANTL_IsTxXmitPending + + DESCRIPTION + Called by the WDA when it wants to know whether WDA_DS_TX_START_XMIT msg + is pending in TL msg queue + + DEPENDENCIES + The TL must be registered with WDA before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE + The result code associated with performing the operation + + 0: No WDA_DS_TX_START_XMIT msg pending + 1: Msg WDA_DS_TX_START_XMIT already pending in TL msg queue + + SIDE EFFECTS + +============================================================================*/ + +v_BOOL_t +WLANTL_IsTxXmitPending +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANTL_ClearTxXmitPending + + DESCRIPTION + Called by the WDA when it wants to indicate that no WDA_DS_TX_START_XMIT msg + is pending in TL msg queue + + DEPENDENCIES + The TL must be registered with WDA before this function can be called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_ClearTxXmitPending +( + v_PVOID_t pvosGCtx +); + +/*========================================================================== + FUNCTION WLANTL_UpdateSTABssIdforIBSS + + DESCRIPTION + HDD will call this API to update the BSSID for this Station. + + DEPENDENCIES + The HDD Should registered the staID with TL before calling this function. + + PARAMETERS + + IN + pvosGCtx: Pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + IN + ucSTAId The Station ID for Bssid to be updated + IN + pBssid BSSID to be updated + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANTL_UpdateSTABssIdforIBSS +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U8_t *pBssid +); + + + +/*=============================================================================== + FUNCTION WLANTL_UpdateLinkCapacity + + DESCRIPTION This function updates the STA's Link Capacity in TL + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + linkCapacity linkCapacity Link Capacity + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void +WLANTL_UpdateLinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t staId, + v_U32_t linkCapacity); + +/*=========================================================================== + + FUNCTION WLANTL_GetSTALinkCapacity + + DESCRIPTION + + Returns Link Capacity of a particular STA. + + DEPENDENCIES + + A station must have been registered before its state can be retrieved. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + + OUT + plinkCapacity: the current link capacity the connection to + the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ + +static inline VOS_STATUS +WLANTL_GetSTALinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U32_t *plinkCapacity +) +{ + return VOS_STATUS_SUCCESS; +} +/*=========================================================================== + FUNCTION WLANTL_TxThreadDebugHandler + + DESCRIPTION + Printing TL Snapshot dump, processed under TxThread context, currently + information regarding the global TlCb struture. Dumps information related + to per active STA connection currently in use by TL. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + pvosGCtx: Pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS +============================================================================*/ + +v_VOID_t +WLANTL_TxThreadDebugHandler +( + v_PVOID_t *pvosGCtx +); + +/*========================================================================== + FUNCTION WLANTL_TLDebugMessage + + DESCRIPTION + Post a TL Snapshot request, posts message in TxThread. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + displaySnapshot Boolean showing whether to dump the snapshot or not. + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +static inline v_VOID_t +WLANTL_TLDebugMessage +( + v_BOOL_t displaySnapshot +) +{ + +} + +void WLANTL_PauseUnPauseQs(void *vos_context, v_BOOL_t flag); + +#ifdef QCA_LL_TX_FLOW_CT +/* + * WLANTL_Get_llStats - get the stats for TXRX module + * @sessionId: vdev sessionid. + * @buffer: buffer to update the stats + * @length: lenth of the buffer + * + * HDD will call this API to get the OL-TXRX module stats + * + */ +void WLANTL_Get_llStats +( + v_U8_t sessionId, + char *buffer, + v_U16_t buf_len +); + +/*============================================================================= + FUNCTION WLANTL_GetTxResource + + DESCRIPTION + This function will query WLAN kernel driver TX resource availability. + Per STA/VDEV instance, if TX resource is not available, should back + pressure to OS NET layer. + + DEPENDENCIES + NONE + + PARAMETERS + IN + vos_context : Pointer to VOS global context + sta_id : STA/VDEV instance to query TX resource + low_watermark : Low threashold to block OS Q + high_watermark_offset : Offset to high watermark from low watermark + + RETURN VALUE + VOS_TRUE : Enough resource available, Not need to PAUSE TX OS Q + VOS_FALSE : TX resource is not enough, stop OS TX Q + + SIDE EFFECTS + +==============================================================================*/ +v_BOOL_t WLANTL_GetTxResource +( + void *vos_context, + v_U8_t sessionId, + unsigned int low_watermark, + unsigned int high_watermark_offset +); + +/*============================================================================= + FUNCTION WLANTL_TXFlowControlCb + + DESCRIPTION + This function will be called by TX resource management unit. + If TC resource management unit reserved enough resource for TX session, + Call this function to resume OS TX Q. + + PARAMETERS + IN + tlContext : Pointer to TL SHIM context + peer_idx : peer index belongs to virtual device + sessionId : STA/VDEV instance to query TX resource + resume_tx : Resume OS TX Q or not + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_TXFlowControlCb +( + void *tlContext, + v_U8_t sessionId, + v_BOOL_t resume_tx +); + +/*============================================================================= + FUNCTION WLANTL_RegisterTXFlowControl + + DESCRIPTION + This function will be called by TL client. + Any device want to enable TX flow control, should register Cb function + And needed information into TL SHIM + + PARAMETERS + IN + vos_ctx : Global OS context context + sta_id : STA/VDEV instance index + flowControl : Flow control callback function pointer + sessionId : VDEV ID + adpaterCtxt : VDEV os interface adapter context + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_RegisterTXFlowControl +( + void *vos_ctx, + WLANTL_TxFlowControlCBType flowControl, + v_U8_t sessionId, + void *adpaterCtxt +); + +/*============================================================================= + FUNCTION WLANTL_DeRegisterTXFlowControl + + DESCRIPTION + This function will be called by TL client. + Any device want to close TX flow control, should de-register Cb function + + PARAMETERS + IN + vos_ctx : Global OS context context + sessionId : VDEV instance index + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_DeRegisterTXFlowControl +( + void *vos_ctx, + v_U8_t sessionId +); + +/*============================================================================= + FUNCTION WLANTL_SetAdapterMaxQDepth + + DESCRIPTION + This function will be called by TL client. + Based on the adapter TX available bandwidth, set different TX Pause Q size + Low Bandwidth adapter will have less count of TX Pause Q size to prevent + reserve all TX descriptors which shared with FW. + High Bandwidth adapter will have more count of TX Pause Q size + + PARAMETERS + IN + vos_ctx : Global OS context context + sessionId : adapter instance index + max_q_depth : Max pause Q depth for adapter + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetAdapterMaxQDepth +( + void *vos_ctx, + v_U8_t sessionId, + int max_q_depth +); +#else +static inline void WLANTL_Get_llStats +( + uint8_t sessionId, + char *buffer, + uint16_t length +) {} + +#endif /* QCA_LL_TX_FLOW_CT */ + +#ifdef IPA_UC_OFFLOAD +/*============================================================================= + FUNCTION WLANTL_GetIpaUcResource + + DESCRIPTION + This function will be called by TL client. + Data path resource will be used by FW should be allocated within lower layer. + Shared resource information should be propagated to IPA. + To propagate resource information, client will use this API + + PARAMETERS + IN + vos_ctx : Global OS context context + ce_sr_base_paddr : Copy Engine Source Ring base address + ce_sr_ring_size : Copy Engine Source Ring size + ce_reg_paddr : Copy engine register address + tx_comp_ring_base_paddr : TX COMP ring base address + tx_comp_ring_size : TX COMP ring size + tx_num_alloc_buffer : Number of TX allocated buffer + rx_rdy_ring_base_paddr : RX ready ring base address + rx_rdy_ring_size : RX ready ring size + rx_proc_done_idx_paddr : RX process done index physical address + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_GetIpaUcResource(void *vos_ctx, + v_U32_t *ce_sr_base_paddr, + v_U32_t *ce_sr_ring_size, + v_U32_t *ce_reg_paddr, + v_U32_t *tx_comp_ring_base_paddr, + v_U32_t *tx_comp_ring_size, + v_U32_t *tx_num_alloc_buffer, + v_U32_t *rx_rdy_ring_base_paddr, + v_U32_t *rx_rdy_ring_size, + v_U32_t *rx_proc_done_idx_paddr); + +/*============================================================================= + FUNCTION WLANTL_SetUcDoorbellPaddr + + DESCRIPTION + This function will be called by TL client. + UC controller should provide doorbell register address to firmware + TL client will call this API to pass doorbell register address to firmware + + PARAMETERS + IN + vos_ctx : Global OS context context + ipa_tx_uc_doorbell_paddr : Micro Controller WLAN TX COMP doorbell regiser + ipa_rx_uc_doorbell_paddr : Micro Controller WLAN RX REDY doorbell regiser + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetUcDoorbellPaddr(void *vos_ctx, + v_U32_t ipa_tx_uc_doorbell_paddr, + v_U32_t ipa_rx_uc_doorbell_paddr); + +/*============================================================================= + FUNCTION WLANTL_SetUcActive + + DESCRIPTION + This function will be called by TL client. + Send Micro controller data path active or inactive notification to firmware + + PARAMETERS + IN + vos_ctx : Global OS context context + uc_active : Micro Controller data path is active or not + is_tx : Micro Controller WLAN TX data path is active or not + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_SetUcActive(void *vos_ctx, + v_BOOL_t uc_active, + v_BOOL_t is_tx +); + +/*============================================================================= + FUNCTION WLANTL_RegisterOPCbFnc + + DESCRIPTION + This function will be called by TL client. + + PARAMETERS + IN + vos_ctx : Global OS context context + func : callback function pointer + + RETURN VALUE + NONE + + SIDE EFFECTS + +==============================================================================*/ +void WLANTL_RegisterOPCbFnc(void *vos_ctx, + void (*func)(v_U8_t *op_msg, void *usr_ctxt), void *usr_ctxt); + +/*============================================================================= + FUNCTION WLANTL_disable_intrabss_fwd + + DESCRIPTION + Function to return if Intra-BSS FWD is disabled or not + + PARAMETERS + IN + vdev : vdev handle + + RETURN VALUE + bool : TRUE if Intra-BSS FWD is disabled, FALSE if not + + SIDE EFFECTS + +==============================================================================*/ +bool WLANTL_disable_intrabss_fwd(void *vdev); +#endif /* IPA_UC_OFFLOAD */ + +/*============================================================================= + FUNCTION WLANTL_RegisterOCBPeer + + DESCRIPTION + Function to register the OCB Self Peer + + PARAMETERS + IN + vos_ctx : Global OS context context + mac_addr : MAC address of self peer + + OUT + peer_id : Peer ID + + RETURN VALUE + VOS_STATUS_SUCCESS on success + VOS_STATUS_E_FAILURE on failure + + SIDE EFFECTS + +==============================================================================*/ +VOS_STATUS WLANTL_RegisterOCBPeer(void *vos_ctx, uint8_t *mac_addr, + uint8_t *peer_id); + +void WLANTL_display_datapath_stats(void *vos_ctx, uint16_t bitmap); +void WLANTL_clear_datapath_stats(void *vos_ctx, uint16_t bitmap); + +#endif /* #ifndef WLAN_QCT_WLANTL_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c b/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c new file mode 100644 index 000000000000..8f41688b61a0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c @@ -0,0 +1,4261 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* Host Debug log implementation */ + + +#include "athdefs.h" +#include "a_types.h" +#include "dbglog_host.h" +#include "wmi.h" +#include "wmi_unified_api.h" +#include "wma.h" +#include "ol_defines.h" +#include +#include "vos_diag_core_event.h" +#include "qwlan_version.h" +#include +#include +#include +#include + +#ifdef WLAN_OPEN_SOURCE +#include +#endif /* WLAN_OPEN_SOURCE */ +#include "wmi_unified_priv.h" + +#define CLD_DEBUGFS_DIR "cld" +#define DEBUGFS_BLOCK_NAME "dbglog_block" + +#define ATH_MODULE_NAME fwlog +#include +#define FWLOG_DEBUG ATH_DEBUG_MAKE_MODULE_MASK(0) + +static bool appstarted = FALSE; +static bool senddriverstatus = FALSE; +static bool kd_nl_init = FALSE; +static int cnss_diag_pid = INVALID_PID; +static int get_version = 0; +static int gprint_limiter = 0; +static bool tgt_assert_enable = 0; + +#if defined(DEBUG) + +static ATH_DEBUG_MASK_DESCRIPTION g_fwlogDebugDescription[] = { + {FWLOG_DEBUG,"fwlog"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(fwlog, + "fwlog", + "Firmware Debug Log", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | ATH_DEBUG_ERR, + ATH_DEBUG_DESCRIPTION_COUNT(g_fwlogDebugDescription), + g_fwlogDebugDescription); +#endif + +module_dbg_print mod_print[WLAN_MODULE_ID_MAX]; + +A_UINT32 dbglog_process_type = DBGLOG_PROCESS_NET_RAW; + +A_STATUS +wmi_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param, A_UINT32 val, + A_UINT32 *module_id_bitmap, A_UINT32 bitmap_len); + +const char *dbglog_get_module_str(A_UINT32 module_id) +{ + switch (module_id) { + case WLAN_MODULE_INF: + return "INF"; + case WLAN_MODULE_WMI: + return "WMI"; + case WLAN_MODULE_STA_PWRSAVE: + return "STA PS"; + case WLAN_MODULE_WHAL: + return "WHAL"; + case WLAN_MODULE_COEX: + return "COEX"; + case WLAN_MODULE_ROAM: + return "ROAM"; + case WLAN_MODULE_RESMGR_CHAN_MANAGER: + return "CHANMGR"; + case WLAN_MODULE_RESMGR: + return "RESMGR"; + case WLAN_MODULE_VDEV_MGR: + return "VDEV"; + case WLAN_MODULE_SCAN: + return "SCAN"; + case WLAN_MODULE_RATECTRL: + return "RC"; + case WLAN_MODULE_AP_PWRSAVE: + return "AP PS"; + case WLAN_MODULE_BLOCKACK: + return "BA"; + case WLAN_MODULE_MGMT_TXRX: + return "MGMT"; + case WLAN_MODULE_DATA_TXRX: + return "DATA"; + case WLAN_MODULE_HTT: + return "HTT"; + case WLAN_MODULE_HOST: + return "HOST"; + case WLAN_MODULE_BEACON: + return "BEACON"; + case WLAN_MODULE_OFFLOAD: + return "OFFLOAD"; + case WLAN_MODULE_WAL: + return "WAL"; + case WAL_MODULE_DE: + return "DE"; + case WLAN_MODULE_PCIELP: + return "PCIELP"; + case WLAN_MODULE_RTT: + return "RTT"; + case WLAN_MODULE_DCS: + return "DCS"; + case WLAN_MODULE_CACHEMGR: + return "CACHEMGR"; + case WLAN_MODULE_ANI: + return "ANI"; + case WLAN_MODULE_TEST: + return "TESTPOINT"; + case WLAN_MODULE_STA_SMPS: + return "STA_SMPS"; + case WLAN_MODULE_TDLS: + return "TDLS"; + case WLAN_MODULE_P2P: + return "P2P"; + case WLAN_MODULE_WOW: + return "WoW"; + case WLAN_MODULE_IBSS_PWRSAVE: + return "IBSS PS"; + case WLAN_MODULE_EXTSCAN: + return "ExtScan"; + case WLAN_MODULE_UNIT_TEST: + return "UNIT_TEST"; + case WLAN_MODULE_MLME: + return "MLME"; + case WLAN_MODULE_SUPPL: + return "SUPPLICANT"; + default: + return "UNKNOWN"; + } +} + +char * DBG_MSG_ARR[WLAN_MODULE_ID_MAX][MAX_DBG_MSGS] = +{ + { + "INF_MSG_START", + "INF_ASSERTION_FAILED", + "INF_TARGET_ID", + "INF_MSG_END" + }, + { + "WMI_DBGID_DEFINITION_START", + "WMI_CMD_RX_XTND_PKT_TOO_SHORT", + "WMI_EXTENDED_CMD_NOT_HANDLED", + "WMI_CMD_RX_PKT_TOO_SHORT", + "WMI_CALLING_WMI_EXTENSION_FN", + "WMI_CMD_NOT_HANDLED", + "WMI_IN_SYNC", + "WMI_TARGET_WMI_SYNC_CMD", + "WMI_SET_SNR_THRESHOLD_PARAMS", + "WMI_SET_RSSI_THRESHOLD_PARAMS", + "WMI_SET_LQ_TRESHOLD_PARAMS", + "WMI_TARGET_CREATE_PSTREAM_CMD", + "WMI_WI_DTM_INUSE", + "WMI_TARGET_DELETE_PSTREAM_CMD", + "WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD", + "WMI_TARGET_GET_BIT_RATE_CMD", + "WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS", + "WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD", + "WMI_TARGET_GET_TX_PWR_CMD", + "WMI_FREE_EVBUF_WMIBUF", + "WMI_FREE_EVBUF_DATABUF", + "WMI_FREE_EVBUF_BADFLAG", + "WMI_HTC_RX_ERROR_DATA_PACKET", + "WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX", + "WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT", + "WMI_SENDING_READY_EVENT", + "WMI_SETPOWER_MDOE_TO_MAXPERF", + "WMI_SETPOWER_MDOE_TO_REC", + "WMI_BSSINFO_EVENT_FROM", + "WMI_TARGET_GET_STATS_CMD", + "WMI_SENDING_SCAN_COMPLETE_EVENT", + "WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT ", + "WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT", + "WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT", + "WMI_SENDING_ERROR_REPORT_EVENT", + "WMI_SENDING_CAC_EVENT", + "WMI_TARGET_GET_ROAM_TABLE_CMD", + "WMI_TARGET_GET_ROAM_DATA_CMD", + "WMI_SENDING_GPIO_INTR_EVENT", + "WMI_SENDING_GPIO_ACK_EVENT", + "WMI_SENDING_GPIO_DATA_EVENT", + "WMI_CMD_RX", + "WMI_CMD_RX_XTND", + "WMI_EVENT_SEND", + "WMI_EVENT_SEND_XTND", + "WMI_CMD_PARAMS_DUMP_START", + "WMI_CMD_PARAMS_DUMP_END", + "WMI_CMD_PARAMS", + "WMI_EVENT_ALLOC_FAILURE", + "WMI_DBGID_DCS_PARAM_CMD", + "WMI_SEND_EVENT_WRONG_TLV", + "WMI_SEND_EVENT_NO_TLV_DEF", + "WMI_DBGID_DEFNITION_END", + }, + { + "PS_STA_DEFINITION_START", + "PS_STA_PM_ARB_REQUEST", + "PS_STA_DELIVER_EVENT", + "PS_STA_PSPOLL_SEQ_DONE", + "PS_STA_COEX_MODE", + "PS_STA_PSPOLL_ALLOW", + "PS_STA_SET_PARAM", + "PS_STA_SPECPOLL_TIMER_STARTED", + "PS_STA_SPECPOLL_TIMER_STOPPED", + }, + { + "WHAL_DBGID_DEFINITION_START", + "WHAL_ERROR_ANI_CONTROL", + "WHAL_ERROR_CHIP_TEST1", + "WHAL_ERROR_CHIP_TEST2", + "WHAL_ERROR_EEPROM_CHECKSUM", + "WHAL_ERROR_EEPROM_MACADDR", + "WHAL_ERROR_INTERRUPT_HIU", + "WHAL_ERROR_KEYCACHE_RESET", + "WHAL_ERROR_KEYCACHE_SET", + "WHAL_ERROR_KEYCACHE_TYPE", + "WHAL_ERROR_KEYCACHE_TKIPENTRY", + "WHAL_ERROR_KEYCACHE_WEPLENGTH", + "WHAL_ERROR_PHY_INVALID_CHANNEL", + "WHAL_ERROR_POWER_AWAKE", + "WHAL_ERROR_POWER_SET", + "WHAL_ERROR_RECV_STOPDMA", + "WHAL_ERROR_RECV_STOPPCU", + "WHAL_ERROR_RESET_CHANNF1", + "WHAL_ERROR_RESET_CHANNF2", + "WHAL_ERROR_RESET_PM", + "WHAL_ERROR_RESET_OFFSETCAL", + "WHAL_ERROR_RESET_RFGRANT", + "WHAL_ERROR_RESET_RXFRAME", + "WHAL_ERROR_RESET_STOPDMA", + "WHAL_ERROR_RESET_ERRID", + "WHAL_ERROR_RESET_ADCDCCAL1", + "WHAL_ERROR_RESET_ADCDCCAL2", + "WHAL_ERROR_RESET_TXIQCAL", + "WHAL_ERROR_RESET_RXIQCAL", + "WHAL_ERROR_RESET_CARRIERLEAK", + "WHAL_ERROR_XMIT_COMPUTE", + "WHAL_ERROR_XMIT_NOQUEUE", + "WHAL_ERROR_XMIT_ACTIVEQUEUE", + "WHAL_ERROR_XMIT_BADTYPE", + "WHAL_ERROR_XMIT_STOPDMA", + "WHAL_ERROR_INTERRUPT_BB_PANIC", + "WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW", + "WHAL_ERROR_QCU_HW_PAUSE_MISMATCH", + "WHAL_DBGID_DEFINITION_END", + }, + { + "COEX_DEBUGID_START", + "BTCOEX_DBG_MCI_1", + "BTCOEX_DBG_MCI_2", + "BTCOEX_DBG_MCI_3", + "BTCOEX_DBG_MCI_4", + "BTCOEX_DBG_MCI_5", + "BTCOEX_DBG_MCI_6", + "BTCOEX_DBG_MCI_7", + "BTCOEX_DBG_MCI_8", + "BTCOEX_DBG_MCI_9", + "BTCOEX_DBG_MCI_10", + "COEX_WAL_BTCOEX_INIT", + "COEX_WAL_PAUSE", + "COEX_WAL_RESUME", + "COEX_UPDATE_AFH", + "COEX_HWQ_EMPTY_CB", + "COEX_MCI_TIMER_HANDLER", + "COEX_MCI_RECOVER", + "ERROR_COEX_MCI_ISR", + "ERROR_COEX_MCI_GPM", + "COEX_ProfileType", + "COEX_LinkID", + "COEX_LinkState", + "COEX_LinkRole", + "COEX_LinkRate", + "COEX_VoiceType", + "COEX_TInterval", + "COEX_WRetrx", + "COEX_Attempts", + "COEX_PerformanceState", + "COEX_LinkType", + "COEX_RX_MCI_GPM_VERSION_QUERY", + "COEX_RX_MCI_GPM_VERSION_RESPONSE", + "COEX_RX_MCI_GPM_STATUS_QUERY", + "COEX_STATE_WLAN_VDEV_DOWN", + "COEX_STATE_WLAN_VDEV_START", + "COEX_STATE_WLAN_VDEV_CONNECTED", + "COEX_STATE_WLAN_VDEV_SCAN_STARTED", + "COEX_STATE_WLAN_VDEV_SCAN_END", + "COEX_STATE_WLAN_DEFAULT", + "COEX_CHANNEL_CHANGE", + "COEX_POWER_CHANGE", + "COEX_CONFIG_MGR", + "COEX_TX_MCI_GPM_BT_CAL_REQ", + "COEX_TX_MCI_GPM_BT_CAL_GRANT", + "COEX_TX_MCI_GPM_BT_CAL_DONE", + "COEX_TX_MCI_GPM_WLAN_CAL_REQ", + "COEX_TX_MCI_GPM_WLAN_CAL_GRANT", + "COEX_TX_MCI_GPM_WLAN_CAL_DONE", + "COEX_TX_MCI_GPM_BT_DEBUG", + "COEX_TX_MCI_GPM_VERSION_QUERY", + "COEX_TX_MCI_GPM_VERSION_RESPONSE", + "COEX_TX_MCI_GPM_STATUS_QUERY", + "COEX_TX_MCI_GPM_HALT_BT_GPM", + "COEX_TX_MCI_GPM_WLAN_CHANNELS", + "COEX_TX_MCI_GPM_BT_PROFILE_INFO", + "COEX_TX_MCI_GPM_BT_STATUS_UPDATE", + "COEX_TX_MCI_GPM_BT_UPDATE_FLAGS", + "COEX_TX_MCI_GPM_UNKNOWN", + "COEX_TX_MCI_SYS_WAKING", + "COEX_TX_MCI_LNA_TAKE", + "COEX_TX_MCI_LNA_TRANS", + "COEX_TX_MCI_SYS_SLEEPING", + "COEX_TX_MCI_REQ_WAKE", + "COEX_TX_MCI_REMOTE_RESET", + "COEX_TX_MCI_TYPE_UNKNOWN", + "COEX_WHAL_MCI_RESET", + "COEX_POLL_BT_CAL_DONE_TIMEOUT", + "COEX_WHAL_PAUSE", + "COEX_RX_MCI_GPM_BT_CAL_REQ", + "COEX_RX_MCI_GPM_BT_CAL_DONE", + "COEX_RX_MCI_GPM_BT_CAL_GRANT", + "COEX_WLAN_CAL_START", + "COEX_WLAN_CAL_RESULT", + "COEX_BtMciState", + "COEX_BtCalState", + "COEX_WlanCalState", + "COEX_RxReqWakeCount", + "COEX_RxRemoteResetCount", + "COEX_RESTART_CAL", + "COEX_SENDMSG_QUEUE", + "COEX_RESETSEQ_LNAINFO_TIMEOUT", + "COEX_MCI_ISR_IntRaw", + "COEX_MCI_ISR_Int1Raw", + "COEX_MCI_ISR_RxMsgRaw", + "COEX_WHAL_COEX_RESET", + "COEX_WAL_COEX_INIT", + "COEX_TXRX_CNT_LIMIT_ISR", + "COEX_CH_BUSY", + "COEX_REASSESS_WLAN_STATE", + "COEX_BTCOEX_WLAN_STATE_UPDATE", + "COEX_BT_NUM_OF_PROFILES", + "COEX_BT_NUM_OF_HID_PROFILES", + "COEX_BT_NUM_OF_ACL_PROFILES", + "COEX_BT_NUM_OF_HI_ACL_PROFILES", + "COEX_BT_NUM_OF_VOICE_PROFILES", + "COEX_WLAN_AGGR_LIMIT", + "COEX_BT_LOW_PRIO_BUDGET", + "COEX_BT_HI_PRIO_BUDGET", + "COEX_BT_IDLE_TIME", + "COEX_SET_COEX_WEIGHT", + "COEX_WLAN_WEIGHT_GROUP", + "COEX_BT_WEIGHT_GROUP", + "COEX_BT_INTERVAL_ALLOC", + "COEX_BT_SCHEME", + "COEX_BT_MGR", + "COEX_BT_SM_ERROR", + "COEX_SYSTEM_UPDATE", + "COEX_LOW_PRIO_LIMIT", + "COEX_HI_PRIO_LIMIT", + "COEX_BT_INTERVAL_START", + "COEX_WLAN_INTERVAL_START", + "COEX_NON_LINK_BUDGET", + "COEX_CONTENTION_MSG", + "COEX_SET_NSS", + "COEX_SELF_GEN_MASK", + "COEX_PROFILE_ERROR", + "COEX_WLAN_INIT", + "COEX_BEACON_MISS", + "COEX_BEACON_OK", + "COEX_BTCOEX_SCAN_ACTIVITY", + "COEX_SCAN_ACTIVITY", + "COEX_FORCE_QUIETTIME", + "COEX_BT_MGR_QUIETTIME", + "COEX_BT_INACTIVITY_TRIGGER", + "COEX_BT_INACTIVITY_REPORTED", + "COEX_TX_MCI_GPM_WLAN_PRIO", + "COEX_TX_MCI_GPM_BT_PAUSE_PROFILE", + "COEX_TX_MCI_GPM_WLAN_SET_ACL_INACTIVITY", + "COEX_RX_MCI_GPM_BT_ACL_INACTIVITY_REPORT", + "COEX_GENERIC_ERROR", + "COEX_RX_RATE_THRESHOLD", + "COEX_RSSI", + "COEX_WLAN_VDEV_NOTIF_START", // 133 + "COEX_WLAN_VDEV_NOTIF_UP", // 134 + "COEX_WLAN_VDEV_NOTIF_DOWN", // 135 + "COEX_WLAN_VDEV_NOTIF_STOP", // 136 + "COEX_WLAN_VDEV_NOTIF_ADD_PEER", // 137 + "COEX_WLAN_VDEV_NOTIF_DELETE_PEER", // 138 + "COEX_WLAN_VDEV_NOTIF_CONNECTED_PEER", // 139 + "COEX_WLAN_VDEV_NOTIF_PAUSE", // 140 + "COEX_WLAN_VDEV_NOTIF_UNPAUSED", // 141 + "COEX_STATE_WLAN_VDEV_PEER_ADD", // 142 + "COEX_STATE_WLAN_VDEV_CONNECTED_PEER", // 143 + "COEX_STATE_WLAN_VDEV_DELETE_PEER", // 144 + "COEX_STATE_WLAN_VDEV_PAUSE", // 145 + "COEX_STATE_WLAN_VDEV_UNPAUSED", // 146 + "COEX_SCAN_CALLBACK", // 147 + "COEX_RC_SET_CHAINMASK", // 148 + "COEX_TX_MCI_GPM_WLAN_SET_BT_RXSS_THRES", // 149 + "COEX_TX_MCI_GPM_BT_RXSS_THRES_QUERY", // 150 + "COEX_BT_RXSS_THRES", // 151 + "COEX_BT_PROFILE_ADD_RMV", // 152 + "COEX_BT_SCHED_INFO", // 153 + "COEX_TRF_MGMT", // 154 + "COEX_SCHED_START", // 155 + "COEX_SCHED_RESULT", // 156 + "COEX_SCHED_ERROR", // 157 + "COEX_SCHED_PRE_OP", // 158 + "COEX_SCHED_POST_OP", // 159 + "COEX_RX_RATE", // 160 + "COEX_ACK_PRIORITY", // 161 + "COEX_STATE_WLAN_VDEV_UP", // 162 + "COEX_STATE_WLAN_VDEV_PEER_UPDATE", // 163 + "COEX_STATE_WLAN_VDEV_STOP", // 164 + "COEX_WLAN_PAUSE_PEER", // 165 + "COEX_WLAN_UNPAUSE_PEER", // 166 + "COEX_WLAN_PAUSE_INTERVAL_START", // 167 + "COEX_WLAN_POSTPAUSE_INTERVAL_START", // 168 + "COEX_TRF_FREERUN", // 169 + "COEX_TRF_SHAPE_PM", // 170 + "COEX_TRF_SHAPE_PSP", // 171 + "COEX_TRF_SHAPE_S_CTS", // 172 + "COEX_CHAIN_CONFIG", // 173 + "COEX_SYSTEM_MONITOR", // 174 + "COEX_SINGLECHAIN_INIT", // 175 + "COEX_MULTICHAIN_INIT", // 176 + "COEX_SINGLECHAIN_DBG_1", // 177 + "COEX_SINGLECHAIN_DBG_2", // 178 + "COEX_SINGLECHAIN_DBG_3", // 179 + "COEX_MULTICHAIN_DBG_1", // 180 + "COEX_MULTICHAIN_DBG_2", // 181 + "COEX_MULTICHAIN_DBG_3", // 182 + "COEX_PSP_TX_CB", // 183 + "COEX_PSP_RX_CB", // 184 + "COEX_PSP_STAT_1", // 185 + "COEX_PSP_SPEC_POLL", // 186 + "COEX_PSP_READY_STATE", // 187 + "COEX_PSP_TX_STATUS_STATE", // 188 + "COEX_PSP_RX_STATUS_STATE_1", // 189 + "COEX_PSP_NOT_READY_STATE", // 190 + "COEX_PSP_DISABLED_STATE", // 191 + "COEX_PSP_ENABLED_STATE", // 192 + "COEX_PSP_SEND_PSPOLL", // 193 + "COEX_PSP_MGR_ENTER", // 194 + "COEX_PSP_MGR_RESULT", // 195 + "COEX_PSP_NONWLAN_INTERVAL", // 196 + "COEX_PSP_STAT_2", // 197 + "COEX_PSP_RX_STATUS_STATE_2", // 198 + "COEX_PSP_ERROR", // 199 + "COEX_T2BT", // 200 + "COEX_BT_DURATION", // 201 + "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG", // 202 + "COEX_TX_MCI_GPM_WLAN_SCHED_INFO_TRIG_RSP", // 203 + "COEX_TX_MCI_GPM_SCAN_OP", // 204 + "COEX_TX_MCI_GPM_BT_PAUSE_GPM_TX", // 205 + "COEX_CTS2S_SEND", // 206 + "COEX_CTS2S_RESULT", // 207 + "COEX_ENTER_OCS", // 208 + "COEX_EXIT_OCS", // 209 + "COEX_UPDATE_OCS", // 210 + "COEX_STATUS_OCS", // 211 + "COEX_STATS_BT", // 212 + "COEX_MWS_WLAN_INIT", + "COEX_MWS_WBTMR_SYNC", + "COEX_MWS_TYPE2_RX", + "COEX_MWS_TYPE2_TX", + "COEX_MWS_WLAN_CHAVD", + "COEX_MWS_WLAN_CHAVD_INSERT", + "COEX_MWS_WLAN_CHAVD_MERGE", + "COEX_MWS_WLAN_CHAVD_RPT", + "COEX_MWS_CP_MSG_SEND", + "COEX_MWS_CP_ESCAPE", + "COEX_MWS_CP_UNFRAME", + "COEX_MWS_CP_SYNC_UPDATE", + "COEX_MWS_CP_SYNC", + "COEX_MWS_CP_WLAN_STATE_IND", + "COEX_MWS_CP_SYNCRESP_TIMEOUT", + "COEX_MWS_SCHEME_UPDATE", + "COEX_MWS_WLAN_EVENT", + "COEX_MWS_UART_UNESCAPE", + "COEX_MWS_UART_ENCODE_SEND", + "COEX_MWS_UART_RECV_DECODE", + "COEX_MWS_UL_HDL", + "COEX_MWS_REMOTE_EVENT", + "COEX_MWS_OTHER", + "COEX_MWS_ERROR", + "COEX_MWS_ANT_DIVERSITY", //237 + "COEX_P2P_GO", + "COEX_P2P_CLIENT", + "COEX_SCC_1", + "COEX_SCC_2", + "COEX_MCC_1", + "COEX_MCC_2", + "COEX_TRF_SHAPE_NOA", + "COEX_NOA_ONESHOT", + "COEX_NOA_PERIODIC", + "COEX_LE_1", + "COEX_LE_2", + "COEX_ANT_1", + "COEX_ANT_2", + "COEX_ENTER_NOA", + "COEX_EXIT_NOA", + "COEX_BT_SCAN_PROTECT", // 253 + "COEX_DEBUG_ID_END" // 254 + }, + { + "ROAM_DBGID_DEFINITION_START", + "ROAM_MODULE_INIT", + "ROAM_DEV_START", + "ROAM_CONFIG_RSSI_THRESH", + "ROAM_CONFIG_SCAN_PERIOD", + "ROAM_CONFIG_AP_PROFILE", + "ROAM_CONFIG_CHAN_LIST", + "ROAM_CONFIG_SCAN_PARAMS", + "ROAM_CONFIG_RSSI_CHANGE", + "ROAM_SCAN_TIMER_START", + "ROAM_SCAN_TIMER_EXPIRE", + "ROAM_SCAN_TIMER_STOP", + "ROAM_SCAN_STARTED", + "ROAM_SCAN_COMPLETE", + "ROAM_SCAN_CANCELLED", + "ROAM_CANDIDATE_FOUND", + "ROAM_RSSI_ACTIVE_SCAN", + "ROAM_RSSI_ACTIVE_ROAM", + "ROAM_RSSI_GOOD", + "ROAM_BMISS_FIRST_RECV", + "ROAM_DEV_STOP", + "ROAM_FW_OFFLOAD_ENABLE", + "ROAM_CANDIDATE_SSID_MATCH", + "ROAM_CANDIDATE_SECURITY_MATCH", + "ROAM_LOW_RSSI_INTERRUPT", + "ROAM_HIGH_RSSI_INTERRUPT", + "ROAM_SCAN_REQUESTED", + "ROAM_BETTER_CANDIDATE_FOUND", + "ROAM_BETTER_AP_EVENT", + "ROAM_CANCEL_LOW_PRIO_SCAN", + "ROAM_FINAL_BMISS_RECVD", + "ROAM_CONFIG_SCAN_MODE", + "ROAM_BMISS_FINAL_SCAN_ENABLE", + "ROAM_SUITABLE_AP_EVENT", + "ROAM_RSN_IE_PARSE_ERROR", + "ROAM_WPA_IE_PARSE_ERROR", + "ROAM_SCAN_CMD_FROM_HOST", + "ROAM_HO_SORT_CANDIDATE", + "ROAM_HO_SAVE_CANDIDATE", + "ROAM_HO_GET_CANDIDATE", + "ROAM_HO_OFFLOAD_SET_PARAM", + "ROAM_HO_SM", + "ROAM_HO_HTT_SAVED", + "ROAM_HO_SYNC_START", + "ROAM_HO_START", + "ROAM_HO_COMPLETE", + "ROAM_HO_STOP", + "ROAM_HO_HTT_FORWARD", + "ROAM_DBGID_DEFINITION_END" + }, + { + "RESMGR_CHMGR_DEFINITION_START", + "RESMGR_CHMGR_PAUSE_COMPLETE", + "RESMGR_CHMGR_CHANNEL_CHANGE", + "RESMGR_CHMGR_RESUME_COMPLETE", + "RESMGR_CHMGR_VDEV_PAUSE", + "RESMGR_CHMGR_VDEV_UNPAUSE", + "RESMGR_CHMGR_CTS2S_TX_COMP", + "RESMGR_CHMGR_CFEND_TX_COMP", + "RESMGR_CHMGR_DEFINITION_END" + }, + { + "RESMGR_DEFINITION_START", + "RESMGR_OCS_ALLOCRAM_SIZE", + "RESMGR_OCS_RESOURCES", + "RESMGR_LINK_CREATE", + "RESMGR_LINK_DELETE", + "RESMGR_OCS_CHREQ_CREATE", + "RESMGR_OCS_CHREQ_DELETE", + "RESMGR_OCS_CHREQ_START", + "RESMGR_OCS_CHREQ_STOP", + "RESMGR_OCS_SCHEDULER_INVOKED", + "RESMGR_OCS_CHREQ_GRANT", + "RESMGR_OCS_CHREQ_COMPLETE", + "RESMGR_OCS_NEXT_TSFTIME", + "RESMGR_OCS_TSF_TIMEOUT_US", + "RESMGR_OCS_CURR_CAT_WINDOW", + "RESMGR_OCS_CURR_CAT_WINDOW_REQ", + "RESMGR_OCS_CURR_CAT_WINDOW_TIMESLOT", + "RESMGR_OCS_CHREQ_RESTART", + "RESMGR_OCS_CLEANUP_CH_ALLOCATORS", + "RESMGR_OCS_PURGE_CHREQ", + "RESMGR_OCS_CH_ALLOCATOR_FREE", + "RESMGR_OCS_RECOMPUTE_SCHEDULE", + "RESMGR_OCS_NEW_CAT_WINDOW_REQ", + "RESMGR_OCS_NEW_CAT_WINDOW_TIMESLOT", + "RESMGR_OCS_CUR_CH_ALLOC", + "RESMGR_OCS_WIN_CH_ALLOC", + "RESMGR_OCS_SCHED_CH_CHANGE", + "RESMGR_OCS_CONSTRUCT_CAT_WIN", + "RESMGR_OCS_CHREQ_PREEMPTED", + "RESMGR_OCS_CH_SWITCH_REQ", + "RESMGR_OCS_CHANNEL_SWITCHED", + "RESMGR_OCS_CLEANUP_STALE_REQS", + "RESMGR_OCS_CHREQ_UPDATE", + "RESMGR_OCS_REG_NOA_NOTIF", + "RESMGR_OCS_DEREG_NOA_NOTIF", + "RESMGR_OCS_GEN_PERIODIC_NOA", + "RESMGR_OCS_RECAL_QUOTAS", + "RESMGR_OCS_GRANTED_QUOTA_STATS", + "RESMGR_OCS_ALLOCATED_QUOTA_STATS", + "RESMGR_OCS_REQ_QUOTA_STATS", + "RESMGR_OCS_TRACKING_TIME_FIRED", + "RESMGR_VC_ARBITRATE_ATTRIBUTES", + "RESMGR_OCS_LATENCY_STRICT_TIME_SLOT", + "RESMGR_OCS_CURR_TSF", + "RESMGR_OCS_QUOTA_REM", + "RESMGR_OCS_LATENCY_CASE_NO", + "RESMGR_OCS_WIN_CAT_DUR", + "RESMGR_VC_UPDATE_CUR_VC", + "RESMGR_VC_REG_UNREG_LINK", + "RESMGR_VC_PRINT_LINK", + "RESMGR_OCS_MISS_TOLERANCE", + "RESMGR_DYN_SCH_ALLOCRAM_SIZE", + "RESMGR_DYN_SCH_ENABLE", + "RESMGR_DYN_SCH_ACTIVE", + "RESMGR_DYN_SCH_CH_STATS_START", + "RESMGR_DYN_SCH_CH_SX_STATS", + "RESMGR_DYN_SCH_TOT_UTIL_PER", + "RESMGR_DYN_SCH_HOME_CH_QUOTA", + "RESMGR_OCS_REG_RECAL_QUOTA_NOTIF", + "RESMGR_OCS_DEREG_RECAL_QUOTA_NOTIF", + "RESMGR_DEFINITION_END" + }, + { + "VDEV_MGR_DEBID_DEFINITION_START", /* vdev Mgr */ + "VDEV_MGR_FIRST_BEACON_MISS_DETECTED", + "VDEV_MGR_FINAL_BEACON_MISS_DETECTED", + "VDEV_MGR_BEACON_IN_SYNC", + "VDEV_MGR_AP_KEEPALIVE_IDLE", + "VDEV_MGR_AP_KEEPALIVE_INACTIVE", + "VDEV_MGR_AP_KEEPALIVE_UNRESPONSIVE", + "VDEV_MGR_AP_TBTT_CONFIG", + "VDEV_MGR_FIRST_BCN_RECEIVED", + "VDEV_MGR_VDEV_START", + "VDEV_MGR_VDEV_UP", + "VDEV_MGR_PEER_AUTHORIZED", + "VDEV_MGR_OCS_HP_LP_REQ_POSTED", + "VDEV_MGR_VDEV_START_OCS_HP_REQ_COMPLETE", + "VDEV_MGR_VDEV_START_OCS_HP_REQ_STOP", + "VDEV_MGR_HP_START_TIME", + "VDEV_MGR_VDEV_PAUSE_DELAY_UPDATE", + "VDEV_MGR_VDEV_PAUSE_FAIL", + "VDEV_MGR_GEN_PERIODIC_NOA", + "VDEV_MGR_OFF_CHAN_GO_CH_REQ_SETUP", + "VDEV_MGR_DEFINITION_END", + }, + { + "SCAN_START_COMMAND_FAILED", /* scan */ + "SCAN_STOP_COMMAND_FAILED", + "SCAN_EVENT_SEND_FAILED", + "SCAN_ENGINE_START", + "SCAN_ENGINE_CANCEL_COMMAND", + "SCAN_ENGINE_STOP_DUE_TO_TIMEOUT", + "SCAN_EVENT_SEND_TO_HOST", + "SCAN_FWLOG_EVENT_ADD", + "SCAN_FWLOG_EVENT_REM", + "SCAN_FWLOG_EVENT_PREEMPTED", + "SCAN_FWLOG_EVENT_RESTARTED", + "SCAN_FWLOG_EVENT_COMPLETED", + }, + { + "RATECTRL_DBGID_DEFINITION_START", /* Rate ctrl*/ + "RATECTRL_DBGID_ASSOC", + "RATECTRL_DBGID_NSS_CHANGE", + "RATECTRL_DBGID_CHAINMASK_ERR", + "RATECTRL_DBGID_UNEXPECTED_FRAME", + "RATECTRL_DBGID_WAL_RCQUERY", + "RATECTRL_DBGID_WAL_RCUPDATE", + "RATECTRL_DBGID_GTX_UPDATE", + "RATECTRL_DBGID_DEFINITION_END" + }, + { + "AP_PS_DBGID_DEFINITION_START", + "AP_PS_DBGID_UPDATE_TIM", + "AP_PS_DBGID_PEER_STATE_CHANGE", + "AP_PS_DBGID_PSPOLL", + "AP_PS_DBGID_PEER_CREATE", + "AP_PS_DBGID_PEER_DELETE", + "AP_PS_DBGID_VDEV_CREATE", + "AP_PS_DBGID_VDEV_DELETE", + "AP_PS_DBGID_SYNC_TIM", + "AP_PS_DBGID_NEXT_RESPONSE", + "AP_PS_DBGID_START_SP", + "AP_PS_DBGID_COMPLETED_EOSP", + "AP_PS_DBGID_TRIGGER", + "AP_PS_DBGID_DUPLICATE_TRIGGER", + "AP_PS_DBGID_UAPSD_RESPONSE", + "AP_PS_DBGID_SEND_COMPLETE", + "AP_PS_DBGID_SEND_N_COMPLETE", + "AP_PS_DBGID_DETECT_OUT_OF_SYNC_STA", + "AP_PS_DBGID_DELIVER_CAB", + }, + { + "" /* Block Ack */ + }, + /* Mgmt TxRx */ + { + "MGMT_TXRX_DBGID_DEFINITION_START", + "MGMT_TXRX_FORWARD_TO_HOST", + "MGMT_TXRX_DBGID_DEFINITION_END", + }, + { /* Data TxRx */ + "DATA_TXRX_DBGID_DEFINITION_START", + "DATA_TXRX_DBGID_RX_DATA_SEQ_LEN_INFO", + "DATA_TXRX_DBGID_DEFINITION_END", + }, + { "" /* HTT */ + }, + { "" /* HOST */ + }, + { "" /* BEACON */ + "BEACON_EVENT_SWBA_SEND_FAILED", + "BEACON_EVENT_EARLY_RX_BMISS_STATUS", + "BEACON_EVENT_EARLY_RX_SLEEP_SLOP", + "BEACON_EVENT_EARLY_RX_CONT_BMISS_TIMEOUT", + "BEACON_EVENT_EARLY_RX_PAUSE_SKIP_BCN_NUM", + "BEACON_EVENT_EARLY_RX_CLK_DRIFT", + "BEACON_EVENT_EARLY_RX_AP_DRIFT", + "BEACON_EVENT_EARLY_RX_BCN_TYPE", + }, + { /* Offload Mgr */ + "OFFLOAD_MGR_DBGID_DEFINITION_START", + "OFFLOADMGR_REGISTER_OFFLOAD", + "OFFLOADMGR_DEREGISTER_OFFLOAD", + "OFFLOADMGR_NO_REG_DATA_HANDLERS", + "OFFLOADMGR_NO_REG_EVENT_HANDLERS", + "OFFLOADMGR_REG_OFFLOAD_FAILED", + "OFFLOADMGR_DBGID_DEFINITION_END", + }, + { + "WAL_DBGID_DEFINITION_START", + "WAL_DBGID_FAST_WAKE_REQUEST", + "WAL_DBGID_FAST_WAKE_RELEASE", + "WAL_DBGID_SET_POWER_STATE", + "WAL_DBGID_MISSING", + "WAL_DBGID_CHANNEL_CHANGE_FORCE_RESET", + "WAL_DBGID_CHANNEL_CHANGE", + "WAL_DBGID_VDEV_START", + "WAL_DBGID_VDEV_STOP", + "WAL_DBGID_VDEV_UP", + "WAL_DBGID_VDEV_DOWN", + "WAL_DBGID_SW_WDOG_RESET", + "WAL_DBGID_TX_SCH_REGISTER_TIDQ", + "WAL_DBGID_TX_SCH_UNREGISTER_TIDQ", + "WAL_DBGID_TX_SCH_TICKLE_TIDQ", + "WAL_DBGID_XCESS_FAILURES", + "WAL_DBGID_AST_ADD_WDS_ENTRY", + "WAL_DBGID_AST_DEL_WDS_ENTRY", + "WAL_DBGID_AST_WDS_ENTRY_PEER_CHG", + "WAL_DBGID_AST_WDS_SRC_LEARN_FAIL", + "WAL_DBGID_STA_KICKOUT", + "WAL_DBGID_BAR_TX_FAIL", + "WAL_DBGID_BAR_ALLOC_FAIL", + "WAL_DBGID_LOCAL_DATA_TX_FAIL", + "WAL_DBGID_SECURITY_PM4_QUEUED", + "WAL_DBGID_SECURITY_GM1_QUEUED", + "WAL_DBGID_SECURITY_PM4_SENT", + "WAL_DBGID_SECURITY_ALLOW_DATA", + "WAL_DBGID_SECURITY_UCAST_KEY_SET", + "WAL_DBGID_SECURITY_MCAST_KEY_SET", + "WAL_DBGID_SECURITY_ENCR_EN", + "WAL_DBGID_BB_WDOG_TRIGGERED", + "WAL_DBGID_RX_LOCAL_BUFS_LWM", + "WAL_DBGID_RX_LOCAL_DROP_LARGE_MGMT", + "WAL_DBGID_VHT_ILLEGAL_RATE_PHY_ERR_DETECTED", + "WAL_DBGID_DEV_RESET", + "WAL_DBGID_TX_BA_SETUP", + "WAL_DBGID_RX_BA_SETUP", + "WAL_DBGID_DEV_TX_TIMEOUT", + "WAL_DBGID_DEV_RX_TIMEOUT", + "WAL_DBGID_STA_VDEV_XRETRY", + "WAL_DBGID_DCS", + "WAL_DBGID_MGMT_TX_FAIL", + "WAL_DBGID_SET_M4_SENT_MANUALLY", + "WAL_DBGID_PROCESS_4_WAY_HANDSHAKE", + "WAL_DBGID_WAL_CHANNEL_CHANGE_START", + "WAL_DBGID_WAL_CHANNEL_CHANGE_COMPLETE", + "WAL_DBGID_WHAL_CHANNEL_CHANGE_START", + "WAL_DBGID_WHAL_CHANNEL_CHANGE_COMPLETE", + "WAL_DBGID_TX_MGMT_DESCID_SEQ_TYPE_LEN", + "WAL_DBGID_TX_DATA_MSDUID_SEQ_TYPE_LEN", + "WAL_DBGID_TX_DISCARD", + "WAL_DBGID_TX_MGMT_COMP_DESCID_STATUS", + "WAL_DBGID_TX_DATA_COMP_MSDUID_STATUS", + "WAL_DBGID_RESET_PCU_CYCLE_CNT", + "WAL_DBGID_SETUP_RSSI_INTERRUPTS", + "WAL_DBGID_BRSSI_CONFIG", + "WAL_DBGID_CURRENT_BRSSI_AVE", + "WAL_DBGID_BCN_TX_COMP", + "WAL_DBGID_SET_HW_CHAINMASK", + "WAL_DBGID_SET_HW_CHAINMASK_TXRX_STOP_FAIL", + "WAL_DBGID_GET_HW_CHAINMASK", + "WAL_DBGID_SMPS_DISABLE", + "WAL_DBGID_SMPS_ENABLE_HW_CNTRL", + "WAL_DBGID_SMPS_SWSEL_CHAINMASK", + "WAL_DBGID_DEFINITION_END", + }, + { + "" /* DE */ + }, + { + "" /* pcie lp */ + }, + { + /* RTT */ + "RTT_CALL_FLOW", + "RTT_REQ_SUB_TYPE", + "RTT_MEAS_REQ_HEAD", + "RTT_MEAS_REQ_BODY", + "", + "", + "RTT_INIT_GLOBAL_STATE", + "", + "RTT_REPORT", + "", + "RTT_ERROR_REPORT", + "RTT_TIMER_STOP", + "RTT_SEND_TM_FRAME", + "RTT_V3_RESP_CNT", + "RTT_V3_RESP_FINISH", + "RTT_CHANNEL_SWITCH_REQ", + "RTT_CHANNEL_SWITCH_GRANT", + "RTT_CHANNEL_SWITCH_COMPLETE", + "RTT_CHANNEL_SWITCH_PREEMPT", + "RTT_CHANNEL_SWITCH_STOP", + "RTT_TIMER_START", + }, + { /* RESOURCE */ + "RESOURCE_DBGID_DEFINITION_START", + "RESOURCE_PEER_ALLOC", + "RESOURCE_PEER_FREE", + "RESOURCE_PEER_ALLOC_WAL_PEER", + "RESOURCE_PEER_NBRHOOD_MGMT_ALLOC", + "RESOURCE_PEER_NBRHOOD_MGMT_INFO," + "RESOURCE_DBGID_DEFINITION_END", + }, + { /* DCS */ + "WLAN_DCS_DBGID_INIT", + "WLAN_DCS_DBGID_WMI_CWINT", + "WLAN_DCS_DBGID_TIMER", + "WLAN_DCS_DBGID_CMDG", + "WLAN_DCS_DBGID_CMDS", + "WLAN_DCS_DBGID_DINIT" + }, + { /* CACHEMGR */ + "" + }, + { /* ANI */ + "ANI_DBGID_POLL", + "ANI_DBGID_CONTROL", + "ANI_DBGID_OFDM_PARAMS", + "ANI_DBGID_CCK_PARAMS", + "ANI_DBGID_RESET", + "ANI_DBGID_RESTART", + "ANI_DBGID_OFDM_LEVEL", + "ANI_DBGID_CCK_LEVEL", + "ANI_DBGID_FIRSTEP", + "ANI_DBGID_CYCPWR", + "ANI_DBGID_MRC_CCK", + "ANI_DBGID_SELF_CORR_LOW", + "ANI_DBGID_ENABLE", + "ANI_DBGID_CURRENT_LEVEL", + "ANI_DBGID_POLL_PERIOD", + "ANI_DBGID_LISTEN_PERIOD", + "ANI_DBGID_OFDM_LEVEL_CFG", + "ANI_DBGID_CCK_LEVEL_CFG" + }, + { + "P2P_DBGID_DEFINITION_START", + "P2P_DEV_REGISTER", + "P2P_HANDLE_NOA", + "P2P_UPDATE_SCHEDULE_OPPS", + "P2P_UPDATE_SCHEDULE", + "P2P_UPDATE_START_TIME", + "P2P_UPDATE_START_TIME_DIFF_TSF32", + "P2P_UPDATE_START_TIME_FINAL", + "P2P_SETUP_SCHEDULE_TIMER", + "P2P_PROCESS_SCHEDULE_AFTER_CALC", + "P2P_PROCESS_SCHEDULE_STARTED_TIMER", + "P2P_CALC_SCHEDULES_FIRST_CALL_ALL_NEXT_EVENT", + "P2P_CALC_SCHEDULES_FIRST_VALUE", + "P2P_CALC_SCHEDULES_EARLIEST_NEXT_EVENT", + "P2P_CALC_SCHEDULES_SANITY_COUNT", + "P2P_CALC_SCHEDULES_CALL_ALL_NEXT_EVENT_FROM_WHILE_LOOP", + "P2P_CALC_SCHEDULES_TIMEOUT_1", + "P2P_CALC_SCHEDULES_TIMEOUT_2", + "P2P_FIND_ALL_NEXT_EVENTS_REQ_EXPIRED", + "P2P_FIND_ALL_NEXT_EVENTS_REQ_ACTIVE", + "P2P_FIND_NEXT_EVENT_REQ_NOT_STARTED", + "P2P_FIND_NEXT_EVENT_REQ_COMPLETE_NON_PERIODIC", + "P2P_FIND_NEXT_EVENT_IN_MID_OF_NOA", + "P2P_FIND_NEXT_EVENT_REQ_COMPLETE", + "P2P_SCHEDULE_TIMEOUT", + "P2P_CALC_SCHEDULES_ENTER", + "P2P_PROCESS_SCHEDULE_ENTER", + "P2P_FIND_ALL_NEXT_EVENTS_INDIVIDUAL_REQ_AFTER_CHANGE", + "P2P_FIND_ALL_NEXT_EVENTS_INDIVIDUAL_REQ_BEFORE_CHANGE", + "P2P_FIND_ALL_NEXT_EVENTS_ENTER", + "P2P_FIND_NEXT_EVENT_ENTER", + "P2P_NOA_GO_PRESENT", + "P2P_NOA_GO_ABSENT", + "P2P_GO_NOA_NOTIF", + "P2P_GO_TBTT_OFFSET", + "P2P_GO_GET_NOA_INFO", + "P2P_GO_ADD_ONE_SHOT_NOA", + "P2P_GO_GET_NOA_IE", + "P2P_GO_BCN_TX_COMP", + "P2P_DBGID_DEFINITION_END", + }, + { + "CSA_DBGID_DEFINITION_START", + "CSA_OFFLOAD_POOL_INIT", + "CSA_OFFLOAD_REGISTER_VDEV", + "CSA_OFFLOAD_DEREGISTER_VDEV", + "CSA_DEREGISTER_VDEV_ERROR", + "CSA_OFFLOAD_BEACON_RECEIVED", + "CSA_OFFLOAD_BEACON_CSA_RECV", + "CSA_OFFLOAD_CSA_RECV_ERROR_IE", + "CSA_OFFLOAD_CSA_TIMER_ERROR", + "CSA_OFFLOAD_CSA_TIMER_EXP", + "CSA_OFFLOAD_WMI_EVENT_ERROR", + "CSA_OFFLOAD_WMI_EVENT_SENT", + "CSA_OFFLOAD_WMI_CHANSWITCH_RECV", + "CSA_DBGID_DEFINITION_END", + }, + { /* NLO offload */ + "" + }, + { + "WLAN_CHATTER_DBGID_DEFINITION_START", + "WLAN_CHATTER_ENTER", + "WLAN_CHATTER_EXIT", + "WLAN_CHATTER_FILTER_HIT", + "WLAN_CHATTER_FILTER_MISS", + "WLAN_CHATTER_FILTER_FULL", + "WLAN_CHATTER_FILTER_TM_ADJ", + "WLAN_CHATTER_BUFFER_FULL", + "WLAN_CHATTER_TIMEOUT", + "WLAN_CHATTER_DBGID_DEFINITION_END", + }, + { + "WOW_DBGID_DEFINITION_START", + "WOW_ENABLE_CMDID", + "WOW_RECV_DATA_PKT", + "WOW_WAKE_HOST_DATA", + "WOW_RECV_MGMT", + "WOW_WAKE_HOST_MGMT", + "WOW_RECV_EVENT", + "WOW_WAKE_HOST_EVENT", + "WOW_INIT", + "WOW_RECV_MAGIC_PKT", + "WOW_RECV_BITMAP_PATTERN", + "WOW_AP_VDEV_DISALLOW", + "WOW_STA_VDEV_DISALLOW", + "WOW_P2PGO_VDEV_DISALLOW", + "WOW_NS_OFLD_ENABLE", + "WOW_ARP_OFLD_ENABLE", + "WOW_NS_ARP_OFLD_DISABLE", + "WOW_NS_RECEIVED", + "WOW_NS_REPLIED", + "WOW_ARP_RECEIVED", + "WOW_ARP_REPLIED", + "WOW_DBGID_DEFINITION_END", + }, + { /* WAL VDEV */ + "" + }, + { /* WAL PDEV */ + "" + }, + { /* TEST */ + "TP_CHANGE_CHANNEL", + "TP_LOCAL_SEND", + }, + { /* STA SMPS */ + "STA_SMPS_DBGID_DEFINITION_START", + "STA_SMPS_DBGID_CREATE_PDEV_INSTANCE", + "STA_SMPS_DBGID_CREATE_VIRTUAL_CHAN_INSTANCE", + "STA_SMPS_DBGID_DELETE_VIRTUAL_CHAN_INSTANCE", + "STA_SMPS_DBGID_CREATE_STA_INSTANCE", + "STA_SMPS_DBGID_DELETE_STA_INSTANCE", + "STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_START", + "STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_STOP", + "STA_SMPS_DBGID_SEND_SMPS_ACTION_FRAME", + "STA_SMPS_DBGID_HOST_FORCED_MODE", + "STA_SMPS_DBGID_FW_FORCED_MODE", + "STA_SMPS_DBGID_RSSI_THRESHOLD_CROSSED", + "STA_SMPS_DBGID_SMPS_ACTION_FRAME_COMPLETION", + "STA_SMPS_DBGID_DTIM_EBT_EVENT_CHMASK_UPDATE", + "STA_SMPS_DBGID_DTIM_CHMASK_UPDATE", + "STA_SMPS_DBGID_DTIM_BEACON_EVENT_CHMASK_UPDATE", + "STA_SMPS_DBGID_DTIM_POWER_STATE_CHANGE", + "STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_SLEEP", + "STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_AWAKE", + "SMPS_DBGID_DEFINITION_END", + }, + { /* SWBMISS */ + "SWBMISS_DBGID_DEFINITION_START", + "SWBMISS_ENABLED", + "SWBMISS_DISABLED", + "SWBMISS_DBGID_DEFINITION_END", + }, + { /* WMMAC */ + "" + }, + { /* TDLS */ + "TDLS_DBGID_DEFINITION_START", + "TDLS_DBGID_VDEV_CREATE", + "TDLS_DBGID_VDEV_DELETE", + "TDLS_DBGID_ENABLED_PASSIVE", + "TDLS_DBGID_ENABLED_ACTIVE", + "TDLS_DBGID_DISABLED", + "TDLS_DBGID_CONNTRACK_TIMER", + "TDLS_DBGID_WAL_SET", + "TDLS_DBGID_WAL_GET", + "TDLS_DBGID_WAL_PEER_UPDATE_SET", + "TDLS_DBGID_WAL_PEER_UPDATE_EVT", + "TDLS_DBGID_WAL_VDEV_CREATE", + "TDLS_DBGID_WAL_VDEV_DELETE", + "TDLS_DBGID_WLAN_EVENT", + "TDLS_DBGID_WLAN_PEER_UPDATE_SET", + "TDLS_DBGID_PEER_EVT_DRP_THRESH", + "TDLS_DBGID_PEER_EVT_DRP_RATE", + "TDLS_DBGID_PEER_EVT_DRP_RSSI", + "TDLS_DBGID_PEER_EVT_DISCOVER", + "TDLS_DBGID_PEER_EVT_DELETE", + "TDLS_DBGID_PEER_CAP_UPDATE", + "TDLS_DBGID_UAPSD_SEND_PTI_FRAME", + "TDLS_DBGID_UAPSD_SEND_PTI_FRAME2PEER", + "TDLS_DBGID_UAPSD_START_PTR_TIMER", + "TDLS_DBGID_UAPSD_CANCEL_PTR_TIMER", + "TDLS_DBGID_UAPSD_PTR_TIMER_TIMEOUT", + "TDLS_DBGID_UAPSD_STA_PS_EVENT_HANDLER", + "TDLS_DBGID_UAPSD_PEER_EVENT_HANDLER", + "TDLS_DBGID_UAPSD_PS_DEFAULT_SETTINGS", + "TDLS_DBGID_UAPSD_GENERIC", + }, + { /* HB */ + "WLAN_HB_DBGID_DEFINITION_START", + "WLAN_HB_DBGID_INIT", + "WLAN_HB_DBGID_TCP_GET_TXBUF_FAIL", + "WLAN_HB_DBGID_TCP_SEND_FAIL", + "WLAN_HB_DBGID_BSS_PEER_NULL", + "WLAN_HB_DBGID_UDP_GET_TXBUF_FAIL", + "WLAN_HB_DBGID_UDP_SEND_FAIL", + "WLAN_HB_DBGID_WMI_CMD_INVALID_PARAM", + "WLAN_HB_DBGID_WMI_CMD_INVALID_OP", + "WLAN_HB_DBGID_WOW_NOT_ENTERED", + "WLAN_HB_DBGID_ALLOC_SESS_FAIL", + "WLAN_HB_DBGID_CTX_NULL", + "WLAN_HB_DBGID_CHKSUM_ERR", + "WLAN_HB_DBGID_UDP_TX", + "WLAN_HB_DBGID_TCP_TX", + "WLAN_HB_DBGID_DEFINITION_END", + }, + { /* TXBF */ + "TXBFEE_DBGID_START", + "TXBFEE_DBGID_NDPA_RECEIVED", + "TXBFEE_DBGID_HOST_CONFIG_TXBFEE_TYPE", + "TXBFER_DBGID_SEND_NDPA", + "TXBFER_DBGID_GET_NDPA_BUF_FAIL", + "TXBFER_DBGID_SEND_NDPA_FAIL", + "TXBFER_DBGID_GET_NDP_BUF_FAIL", + "TXBFER_DBGID_SEND_NDP_FAIL", + "TXBFER_DBGID_GET_BRPOLL_BUF_FAIL", + "TXBFER_DBGID_SEND_BRPOLL_FAIL", + "TXBFER_DBGID_HOST_CONFIG_CMDID", + "TXBFEE_DBGID_HOST_CONFIG_CMDID", + "TXBFEE_DBGID_ENABLED_ENABLED_UPLOAD_H", + "TXBFEE_DBGID_UPLOADH_CV_TAG", + "TXBFEE_DBGID_UPLOADH_H_TAG", + "TXBFEE_DBGID_CAPTUREH_RECEIVED", + "TXBFEE_DBGID_PACKET_IS_STEERED", + "TXBFEE_UPLOADH_EVENT_ALLOC_MEM_FAIL", + "TXBFEE_DBGID_END", + }, + { /*BATCH SCAN*/ + }, + { /*THERMAL MGR*/ + "THERMAL_MGR_DBGID_DEFINITION_START", + "THERMAL_MGR_NEW_THRESH", + "THERMAL_MGR_THRESH_CROSSED", + "THERMAL_MGR_DBGID_DEFINITION END", + }, + { /* WLAN_MODULE_PHYERR_DFS */ + "" + }, + { + /* WLAN_MODULE_RMC */ + "RMC_DBGID_DEFINITION_START", + "RMC_CREATE_INSTANCE", + "RMC_DELETE_INSTANCE", + "RMC_LDR_SEL", + "RMC_NO_LDR", + "RMC_LDR_NOT_SEL", + "RMC_LDR_INF_SENT", + "RMC_PEER_ADD", + "RMC_PEER_DELETE", + "RMC_PEER_UNKNOWN", + "RMC_SET_MODE", + "RMC_SET_ACTION_PERIOD", + "RMC_ACRION_FRAME_RX", + "RMC_DBGID_DEFINITION_END", + }, + { + /* WLAN_MODULE_STATS */ + "WLAN_STATS_DBGID_DEFINITION_START", + "WLAN_STATS_DBGID_EST_LINKSPEED_VDEV_EN_DIS", + "WLAN_STATS_DBGID_EST_LINKSPEED_CHAN_TIME_START", + "WLAN_STATS_DBGID_EST_LINKSPEED_CHAN_TIME_END", + "WLAN_STATS_DBGID_EST_LINKSPEED_CALC", + "WLAN_STATS_DBGID_EST_LINKSPEED_UPDATE_HOME_CHAN", + "WLAN_STATS_DBGID_DEFINITION_END", + }, + { + /* WLAN_MODULE_NAN */ + }, + { + /* WLAN_MODULE_IBSS_PWRSAVE */ + "IBSS_PS_DBGID_DEFINITION_START", + "IBSS_PS_DBGID_PEER_CREATE", + "IBSS_PS_DBGID_PEER_DELETE", + "IBSS_PS_DBGID_VDEV_CREATE", + "IBSS_PS_DBGID_VDEV_DELETE", + "IBSS_PS_DBGID_VDEV_EVENT", + "IBSS_PS_DBGID_PEER_EVENT", + "IBSS_PS_DBGID_DELIVER_CAB", + "IBSS_PS_DBGID_DELIVER_UC_DATA", + "IBSS_PS_DBGID_DELIVER_UC_DATA_ERROR", + "IBSS_PS_DBGID_UC_INACTIVITY_TMR_RESTART", + "IBSS_PS_DBGID_MC_INACTIVITY_TMR_RESTART", + "IBSS_PS_DBGID_NULL_TX_COMPLETION", + "IBSS_PS_DBGID_ATIM_TIMER_START", + "IBSS_PS_DBGID_UC_ATIM_SEND", + "IBSS_PS_DBGID_BC_ATIM_SEND", + "IBSS_PS_DBGID_UC_TIMEOUT", + "IBSS_PS_DBGID_PWR_COLLAPSE_ALLOWED", + "IBSS_PS_DBGID_PWR_COLLAPSE_NOT_ALLOWED", + "IBSS_PS_DBGID_SET_PARAM", + "IBSS_PS_DBGID_HOST_TX_PAUSE", + "IBSS_PS_DBGID_HOST_TX_UNPAUSE", + "IBSS_PS_DBGID_PS_DESC_BIN_HWM", + "IBSS_PS_DBGID_PS_DESC_BIN_LWM", + "IBSS_PS_DBGID_PS_KICKOUT_PEER", + "IBSS_PS_DBGID_SET_PEER_PARAM", + "IBSS_PS_DBGID_BCN_ATIM_WIN_MISMATCH", + "IBSS_PS_DBGID_RX_CHAINMASK_CHANGE", + }, + { + /* HIF UART Interface DBGIDs */ + "HIF_UART_DBGID_START", + "HIF_UART_DBGID_POWER_STATE", + "HIF_UART_DBGID_TXRX_FLOW", + "HIF_UART_DBGID_TXRX_CTRL_CHAR", + "HIF_UART_DBGID_TXRX_BUF_DUMP", + }, + { + /* LPI */ + "" + }, + { + /* EXTSCAN DBGIDs */ + "EXTSCAN_START", + "EXTSCAN_STOP", + "EXTSCAN_CLEAR_ENTRY_CONTENT", + "EXTSCAN_GET_FREE_ENTRY_SUCCESS", + "EXTSCAN_GET_FREE_ENTRY_INCONSISTENT", + "EXTSCAN_GET_FREE_ENTRY_NO_MORE_ENTRIES", + "EXTSCAN_CREATE_ENTRY_SUCCESS", + "EXTSCAN_CREATE_ENTRY_ERROR", + "EXTSCAN_SEARCH_SCAN_ENTRY_QUEUE", + "EXTSCAN_SEARCH_SCAN_ENTRY_KEY_FOUND", + "EXTSCAN_SEARCH_SCAN_ENTRY_KEY_NOT_FOUND", + "EXTSCAN_ADD_ENTRY", + "EXTSCAN_BUCKET_SEND_OPERATION_EVENT", + "EXTSCAN_BUCKET_SEND_OPERATION_EVENT_FAILED", + "EXTSCAN_BUCKET_START_SCAN_CYCLE", + "EXTSCAN_BUCKET_PERIODIC_TIMER", + "EXTSCAN_SEND_START_STOP_EVENT", + "EXTSCAN_NOTIFY_WLAN_CHANGE", + "EXTSCAN_NOTIFY_WLAN_HOTLIST_MATCH", + "EXTSCAN_MAIN_RECEIVED_FRAME", + "EXTSCAN_MAIN_NO_SSID_IE", + "EXTSCAN_MAIN_MALFORMED_FRAME", + "EXTSCAN_FIND_BSSID_BY_REFERENCE", + "EXTSCAN_FIND_BSSID_BY_REFERENCE_ERROR", + "EXTSCAN_NOTIFY_TABLE_USAGE", + "EXTSCAN_FOUND_RSSI_ENTRY", + "EXTSCAN_BSSID_FOUND_RSSI_SAMPLE", + "EXTSCAN_BSSID_ADDED_RSSI_SAMPLE", + "EXTSCAN_BSSID_REPLACED_RSSI_SAMPLE", + "EXTSCAN_BSSID_TRANSFER_CURRENT_SAMPLES", + "EXTSCAN_BUCKET_PROCESS_SCAN_EVENT", + "EXTSCAN_BUCKET_CANNOT_FIND_BUCKET", + "EXTSCAN_START_SCAN_REQUEST_FAILED", + "EXTSCAN_BUCKET_STOP_CURRENT_SCANS", + "EXTSCAN_BUCKET_SCAN_STOP_REQUEST", + "EXTSCAN_BUCKET_PERIODIC_TIMER_ERROR", + "EXTSCAN_BUCKET_START_OPERATION", + "EXTSCAN_START_INTERNAL_ERROR", + "EXTSCAN_NOTIFY_HOTLIST_MATCH", + "EXTSCAN_CONFIG_HOTLIST_TABLE", + "EXTSCAN_CONFIG_WLAN_CHANGE_TABLE", + }, + { /* UNIT_TEST */ + "UNIT_TEST_GEN", + }, + { /* MLME */ + "MLME_DEBUG_CMN", + "MLME_IF", + "MLME_AUTH", + "MLME_REASSOC", + "MLME_DEAUTH", + "MLME_DISASSOC", + "MLME_ROAM", + "MLME_RETRY", + "MLME_TIMER", + "MLME_FRMPARSE", + }, + { /*SUPPLICANT */ + "SUPPL_INIT", + "SUPPL_RECV_EAPOL", + "SUPPL_RECV_EAPOL_TIMEOUT", + "SUPPL_SEND_EAPOL", + "SUPPL_MIC_MISMATCH", + "SUPPL_FINISH", + }, +}; + +int dbglog_module_log_enable(wmi_unified_t wmi_handle, A_UINT32 mod_id, + bool isenable) +{ + A_UINT32 val = 0; + + if (mod_id > WLAN_MODULE_ID_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("dbglog_module_log_enable: Invalid module id %d\n", + mod_id)); + return -EINVAL; + } + + WMI_DBGLOG_SET_MODULE_ID(val,mod_id); + if (isenable) { + /* set it to global module level */ + WMI_DBGLOG_SET_LOG_LEVEL(val,DBGLOG_INFO); + } else { + /* set it to ERROR level */ + WMI_DBGLOG_SET_LOG_LEVEL(val,DBGLOG_ERR); + } + wmi_config_debug_module_cmd(wmi_handle, WMI_DEBUG_LOG_PARAM_LOG_LEVEL, val, NULL,0); + + return 0; +} + +int dbglog_vap_log_enable(wmi_unified_t wmi_handle, A_UINT16 vap_id, + bool isenable) +{ + if (vap_id > DBGLOG_MAX_VDEVID) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("dbglog_vap_log_enable:Invalid vap_id %d\n", + vap_id)); + return -EINVAL; + } + + wmi_config_debug_module_cmd(wmi_handle, + isenable ? WMI_DEBUG_LOG_PARAM_VDEV_ENABLE:WMI_DEBUG_LOG_PARAM_VDEV_DISABLE, vap_id, NULL,0 ); + + return 0; +} + +int dbglog_set_log_lvl(wmi_unified_t wmi_handle, DBGLOG_LOG_LVL log_lvl) +{ + A_UINT32 val = 0; + + if (log_lvl > DBGLOG_LVL_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("dbglog_set_log_lvl:Invalid log level %d\n", + log_lvl)); + return -EINVAL; + } + + WMI_DBGLOG_SET_MODULE_ID(val,WMI_DEBUG_LOG_MODULE_ALL); + WMI_DBGLOG_SET_LOG_LEVEL(val,log_lvl); + wmi_config_debug_module_cmd(wmi_handle, WMI_DEBUG_LOG_PARAM_LOG_LEVEL, val, NULL,0); + + return 0; +} + +int dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, A_UINT32 mod_log_lvl) +{ + A_UINT32 val = 0; + /* set the global module level to log_lvl */ + WMI_DBGLOG_SET_MODULE_ID(val,(mod_log_lvl/10)); + WMI_DBGLOG_SET_LOG_LEVEL(val,(mod_log_lvl%10)); + wmi_config_debug_module_cmd(wmi_handle, WMI_DEBUG_LOG_PARAM_LOG_LEVEL, val, NULL,0); + + return 0; +} + +A_STATUS +wmi_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param, A_UINT32 val, + A_UINT32 *module_id_bitmap, A_UINT32 bitmap_len) +{ + wmi_buf_t buf; + wmi_debug_log_config_cmd_fixed_param *configmsg; + A_STATUS status = A_OK; + int i; + int len; + int8_t *buf_ptr; + int32_t *module_id_bitmap_array; /* Used to fomr the second tlv*/ + + + ASSERT(bitmap_len < MAX_MODULE_ID_BITMAP_WORDS); + + /* Allocate size for 2 tlvs - including tlv hdr space for second tlv*/ + len = sizeof(wmi_debug_log_config_cmd_fixed_param) + WMI_TLV_HDR_SIZE + + (sizeof(int32_t) * MAX_MODULE_ID_BITMAP_WORDS); + buf = wmi_buf_alloc(wmi_handle, len); + if (buf == NULL) + return A_NO_MEMORY; + + configmsg = (wmi_debug_log_config_cmd_fixed_param *)(wmi_buf_data(buf)); + buf_ptr = (int8_t *)configmsg; + WMITLV_SET_HDR(&configmsg->tlv_header, + WMITLV_TAG_STRUC_wmi_debug_log_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_debug_log_config_cmd_fixed_param)); + configmsg->dbg_log_param = param; + configmsg->value = val; + /* Filling in the data part of second tlv -- should follow first tlv _ WMI_TLV_HDR_SIZE*/ + module_id_bitmap_array = (A_UINT32*)(buf_ptr + + sizeof(wmi_debug_log_config_cmd_fixed_param) + + WMI_TLV_HDR_SIZE); + WMITLV_SET_HDR(buf_ptr + sizeof(wmi_debug_log_config_cmd_fixed_param), + WMITLV_TAG_ARRAY_UINT32, + sizeof(A_UINT32) * MAX_MODULE_ID_BITMAP_WORDS); + if (module_id_bitmap) { + for(i=0;i TRUE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("dbglog_report_enable:Invalid value %d\n", + isenable)); + return -EINVAL; + } + + if(isenable){ + /* set the vap enable bitmap */ + dbglog_set_vap_enable_bitmap(wmi_handle, 0xFFFF); + bitmap[0] = 0xFFFFFFFF; + bitmap[1] = 0x1F; + /* set the module level bitmap */ + dbglog_set_mod_enable_bitmap(wmi_handle, 0x0, bitmap, 2); + } else { + dbglog_set_vap_enable_bitmap(wmi_handle, bitmap[0]); + dbglog_set_mod_enable_bitmap(wmi_handle, DBGLOG_LVL_MAX, bitmap, 2); + } + return 0; +} + +static char * +dbglog_get_msg(A_UINT32 moduleid, A_UINT32 debugid) +{ + static char unknown_str[64]; + + if (moduleid < WLAN_MODULE_ID_MAX && debugid < MAX_DBG_MSGS) { + char *str = DBG_MSG_ARR[moduleid][debugid]; + if (str && str[0] != '\0') { + return str; + } + } + + snprintf(unknown_str, sizeof(unknown_str), + "UNKNOWN %u:%u", + moduleid, debugid); + + return unknown_str; +} + +void +dbglog_printf( + A_UINT32 timestamp, + A_UINT16 vap_id, + const char *fmt, ...) +{ + char buf[128]; + va_list ap; + + if (vap_id < DBGLOG_MAX_VDEVID) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (DBGLOG_PRINT_PREFIX "[%u] vap-%u ", timestamp, vap_id)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (DBGLOG_PRINT_PREFIX "[%u] ", timestamp)); + } + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s\n", buf)); +} + +void +dbglog_printf_no_line_break( + A_UINT32 timestamp, + A_UINT16 vap_id, + const char *fmt, ...) +{ + char buf[128]; + va_list ap; + + if (vap_id < DBGLOG_MAX_VDEVID) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (DBGLOG_PRINT_PREFIX "[%u] vap-%u ", timestamp, vap_id)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (DBGLOG_PRINT_PREFIX "[%u] ", timestamp)); + } + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s", buf)); +} + +#define USE_NUMERIC 0 + +A_BOOL +dbglog_default_print_handler(A_UINT32 mod_id, A_UINT16 vap_id, A_UINT32 dbg_id, + A_UINT32 timestamp, A_UINT16 numargs, A_UINT32 *args) +{ + int i; + + if (vap_id < DBGLOG_MAX_VDEVID) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (DBGLOG_PRINT_PREFIX "[%u] vap-%u %s ( ", timestamp, vap_id, dbglog_get_msg(mod_id, dbg_id))); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (DBGLOG_PRINT_PREFIX "[%u] %s ( ", timestamp, dbglog_get_msg(mod_id, dbg_id))); + } + + for (i = 0; i < numargs; i++) { +#if USE_NUMERIC + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%u", args[i])); +#else + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%#x", args[i])); +#endif + if ((i + 1) < numargs) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (", ")); + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (" )\n")); + + return TRUE; +} + +#define DBGLOG_PARSE_ARGS_STRING_LENGTH (DBGLOG_NUM_ARGS_MAX * 11 + 10) +static int +dbglog_print_raw_data(A_UINT32 *buffer, A_UINT32 length) +{ + A_UINT32 timestamp; + A_UINT32 debugid; + A_UINT32 moduleid; + A_UINT16 numargs, curArgs; + A_UINT32 count = 0, totalWriteLen, writeLen; + char parseArgsString[DBGLOG_PARSE_ARGS_STRING_LENGTH]; + char *dbgidString; + + while (count < length) { + + debugid = DBGLOG_GET_DBGID(buffer[count + 1]); + moduleid = DBGLOG_GET_MODULEID(buffer[count + 1]); + numargs = DBGLOG_GET_NUMARGS(buffer[count + 1]); + timestamp = DBGLOG_GET_TIME_STAMP(buffer[count]); + + if (moduleid < WLAN_MODULE_ID_MAX && debugid < MAX_DBG_MSGS && numargs <= DBGLOG_NUM_ARGS_MAX) { + + OS_MEMZERO(parseArgsString, sizeof(parseArgsString)); + totalWriteLen = 0; + + for (curArgs = 0; curArgs < numargs; curArgs++){ + // Using sprintf_s instead of sprintf, to avoid length overflow + writeLen = snprintf(parseArgsString + totalWriteLen, DBGLOG_PARSE_ARGS_STRING_LENGTH - totalWriteLen, "%x ", buffer[count + 2 + curArgs]); + totalWriteLen += writeLen; + } + + if (debugid < MAX_DBG_MSGS){ + dbgidString = DBG_MSG_ARR[moduleid][debugid]; + if (dbgidString != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("fw:%s(%x %x):%s\n", + dbgidString, + timestamp, buffer[count+1], + parseArgsString)); + } else { + /* host need sync with FW id */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("fw:%s:m:%x,id:%x(%x %x):%s\n", + "UNKNOWN", moduleid, debugid, + timestamp, buffer[count+1], + parseArgsString)); + } + } else if (debugid == DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG) { + /* specific debugid */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("fw:%s:m:%x,id:%x(%x %x):%s\n", + "DBGLOG_SM_MSG", moduleid, debugid, + timestamp, buffer[count+1], + parseArgsString)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("fw:%s:m:%x,id:%x(%x %x):%s\n", + "UNKNOWN", moduleid, debugid, + timestamp, buffer[count+1], + parseArgsString)); + } + } + + count += numargs + 2; /* 32 bit Time stamp + 32 bit Dbg header*/ + } + + return 0; + +} + +#ifdef WLAN_OPEN_SOURCE +static int +dbglog_debugfs_raw_data(wmi_unified_t wmi_handle, const u_int8_t *buf, A_UINT32 length, A_UINT32 dropped) +{ + struct fwdebug *fwlog = (struct fwdebug *)&wmi_handle->dbglog; + struct dbglog_slot *slot; + struct sk_buff *skb; + size_t slot_len; + + if (WARN_ON(length > ATH6KL_FWLOG_PAYLOAD_SIZE)) + return -ENODEV; + + slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE; + + skb = alloc_skb(slot_len, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + slot = (struct dbglog_slot *) skb_put(skb, slot_len); + slot->diag_type = (A_UINT32)DIAG_TYPE_FW_DEBUG_MSG; + slot->timestamp = cpu_to_le32(jiffies); + slot->length = cpu_to_le32(length); + slot->dropped = cpu_to_le32(dropped); + memcpy(slot->payload, buf, length); + + /* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */ + memset(slot->payload + length, 0, ATH6KL_FWLOG_PAYLOAD_SIZE - length); + + spin_lock(&fwlog->fwlog_queue.lock); + + __skb_queue_tail(&fwlog->fwlog_queue, skb); + + complete(&fwlog->fwlog_completion); + + /* drop oldest entries */ + while (skb_queue_len(&fwlog->fwlog_queue) > + ATH6KL_FWLOG_MAX_ENTRIES) { + skb = __skb_dequeue(&fwlog->fwlog_queue); + kfree_skb(skb); + } + + spin_unlock(&fwlog->fwlog_queue.lock); + + return TRUE; +} +#endif /* WLAN_OPEN_SOURCE */ + +/* + * Package the data from the fw diag WMI event handler. + * Pass this data to cnss-diag service + */ +int +send_fw_diag_nl_data(wmi_unified_t wmi_handle, const u_int8_t *buffer, + A_UINT32 len, A_UINT32 event_type) +{ + struct sk_buff *skb_out; + struct nlmsghdr *nlh; + int res = 0; + + if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) + return -ENODEV; + + if (nl_srv_is_initialized() != 0) + return -EIO; + + if (vos_is_multicast_logging()) + { + skb_out = nlmsg_new(len, 0); + if (!skb_out) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to allocate new skb\n")); + return -1; + } + nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG, len, 0); + memcpy(nlmsg_data(nlh), buffer, len); + + res = nl_srv_bcast(skb_out); + if (res < 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, + ("%s: nl_srv_bcast failed 0x%x \n", __func__, res)); + return res; + } + } + return res; +} + +static int +send_diag_netlink_data(const u_int8_t *buffer, + A_UINT32 len, A_UINT32 cmd) +{ + struct sk_buff *skb_out; + struct nlmsghdr *nlh; + int res = 0; + struct dbglog_slot *slot; + size_t slot_len; + + if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) + return -ENODEV; + + if (nl_srv_is_initialized() != 0) + return -EIO; + + if (vos_is_multicast_logging()) { + slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE; + + skb_out = nlmsg_new(slot_len, 0); + if (!skb_out) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to allocate new skb\n")); + return -1; + } + + nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG, slot_len, 0); + slot = (struct dbglog_slot *) nlmsg_data(nlh); + slot->diag_type = cmd; + slot->timestamp = cpu_to_le32(jiffies); + slot->length = cpu_to_le32(len); + /* Version mapped to get_version here */ + slot->dropped = get_version; + memcpy(slot->payload, buffer, len); + + res = nl_srv_bcast(skb_out); + if (res < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, + ("%s: nl_srv_bcast failed 0x%x \n", __func__, res)); + return res; + } + } + return res; +} + + +int +dbglog_process_netlink_data(wmi_unified_t wmi_handle, const u_int8_t *buffer, + A_UINT32 len, A_UINT32 dropped) +{ + struct sk_buff *skb_out; + struct nlmsghdr *nlh; + int res = 0; + struct dbglog_slot *slot; + size_t slot_len; + + if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) + return -ENODEV; + + if (nl_srv_is_initialized() != 0) + return -EIO; + + if (vos_is_multicast_logging()) + { + slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE; + + skb_out = nlmsg_new(slot_len, 0); + if (!skb_out) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to allocate new skb\n")); + return -1; + } + + nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG, slot_len, 0); + slot = (struct dbglog_slot *) nlmsg_data(nlh); + slot->diag_type = (A_UINT32)DIAG_TYPE_FW_DEBUG_MSG; + slot->timestamp = cpu_to_le32(jiffies); + slot->length = cpu_to_le32(len); + slot->dropped = cpu_to_le32(dropped); + memcpy(slot->payload, buffer, len); + + res = nl_srv_bcast(skb_out); + if (res < 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, + ("%s: nl_srv_bcast failed 0x%x \n", __func__, res)); + return res; + } + } + return res; +} + +/* + * WMI diag data event handler, this function invoked as a CB + * when there DIAG_EVENT, DIAG_MSG, DIAG_DBG to be + * forwarded from the FW. This is the new implementation for + * replacement of fw_dbg and dbg messages + */ + +static int +diag_fw_handler(ol_scn_t scn, u_int8_t *data, u_int32_t datalen) +{ + + tp_wma_handle wma = (tp_wma_handle)scn; + wmitlv_cmd_param_info *param_buf; + u_int8_t *datap; + u_int32_t len = 0; + u_int32_t *buffer; + + if (!wma) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL Pointer assigned\n")); + return -1; + } + /* when fw asser occurs,host can't use TLV format. */ + if (wma->is_fw_assert) { + datap = data; + len = datalen; + wma->is_fw_assert = 0; + } else { + param_buf = (wmitlv_cmd_param_info *) data; + if (!param_buf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Get NULL point message from FW\n")); + return -1; + } + + param_buf = (wmitlv_cmd_param_info *) data; + datap = param_buf->tlv_ptr; + len = param_buf->num_elements; + if (!get_version) { + buffer = (u_int32_t *)datap ; + buffer++; /* skip offset */ + if (WLAN_DIAG_TYPE_CONFIG == DIAG_GET_TYPE(*buffer)) { + buffer++; /* skip */ + if (DIAG_VERSION_INFO == DIAG_GET_ID(*buffer)) { + buffer++; /* skip */ + /* get payload */ + get_version = *buffer; + } + } + } + } + if (dbglog_process_type == DBGLOG_PROCESS_PRINT_RAW) { + if (!gprint_limiter) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NOT Supported" + " only supports net link socket\n")); + gprint_limiter = TRUE; + } + return 0; + } + + if ( dbglog_process_type == DBGLOG_PROCESS_NET_RAW) { + return send_diag_netlink_data((A_UINT8 *)datap, + len, DIAG_TYPE_FW_MSG); + } + +#ifdef WLAN_OPEN_SOURCE + if (dbglog_process_type == DBGLOG_PROCESS_POOL_RAW) { + if (!gprint_limiter) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NOT Supported" + " only supports net link socket\n")); + gprint_limiter = TRUE; + } + return 0; + } +#endif /* WLAN_OPEN_SOURCE */ + if (!gprint_limiter) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NOT Supported" + " only supports net link socket\n")); + gprint_limiter = TRUE; + } + /* Always returns zero */ + return (0); +} + + +/* + * WMI diag data event handler, this function invoked as a CB + * when there DIAG_DATA to be forwarded from the FW. + */ + +int +fw_diag_data_event_handler(ol_scn_t scn, u_int8_t *data, u_int32_t datalen) +{ + + tp_wma_handle wma = (tp_wma_handle)scn; + struct wlan_diag_data *diag_data; + WMI_DIAG_DATA_CONTAINER_EVENTID_param_tlvs *param_buf; + wmi_diag_data_container_event_fixed_param *fixed_param; + u_int8_t *datap; + u_int32_t num_data=0; /* Total events */ + u_int32_t diag_data_len=0; /* each fw diag payload */ + u_int32_t diag_type=0; + u_int32_t i=0; + u_int32_t nl_data_len=0; /* diag hdr + payload */ + + param_buf = (WMI_DIAG_DATA_CONTAINER_EVENTID_param_tlvs *) data; + if (!param_buf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Got NULL point message from FW\n")); + return -1; + } + + if (!wma) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL Pointer assigned\n")); + return -1; + } + + fixed_param = param_buf->fixed_param; + num_data = param_buf->num_bufp; + + datap = (u_int8_t *)param_buf->bufp; + + /* If cnss-diag service started triggered during the init of services */ + if (appstarted) { + for (i = 0; i < num_data; i++) { + diag_data = (struct wlan_diag_data *)datap; + diag_type = WLAN_DIAG_0_TYPE_GET(diag_data->word0); + diag_data_len = WLAN_DIAG_0_LEN_GET(diag_data->word0); + + /* Length of diag struct and len of payload */ + nl_data_len = sizeof(struct wlan_diag_data) + diag_data_len; +#if 0 + print_hex_dump_bytes("payload: ", DUMP_PREFIX_ADDRESS, + diag_data->payload, diag_data_len); +#endif + switch (diag_type) { + case DIAG_TYPE_FW_EVENT: + return send_fw_diag_nl_data((wmi_unified_t)wma->wmi_handle, + datap, nl_data_len, diag_type); + break; + case DIAG_TYPE_FW_LOG: + return send_fw_diag_nl_data((wmi_unified_t)wma->wmi_handle, + datap, nl_data_len, diag_type); + break; + } + /* Move to the next event and send to cnss-diag */ + datap += nl_data_len; + } + } + return 0; +} + + +int +dbglog_parse_debug_logs(ol_scn_t scn, u_int8_t *data, u_int32_t datalen) +{ + tp_wma_handle wma = (tp_wma_handle)scn; + A_UINT32 count; + A_UINT32 *buffer; + A_UINT32 timestamp; + A_UINT32 debugid; + A_UINT32 moduleid; + A_UINT16 vapid; + A_UINT16 numargs; + adf_os_size_t length; + A_UINT32 dropped; + WMI_DEBUG_MESG_EVENTID_param_tlvs *param_buf; + u_int8_t *datap; + u_int32_t len; + + if (!wma) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL Pointer assigned\n")); + return -1; + } + /*when fw asser occurs,host can't use TLV format.*/ + if (wma->is_fw_assert) { + datap = data; + len = datalen; + wma->is_fw_assert = 0; + } else { + param_buf = (WMI_DEBUG_MESG_EVENTID_param_tlvs *) data; + if (!param_buf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Get NULL point message from FW\n")); + return -1; + } + + datap = param_buf->bufp; + len = param_buf->num_bufp; + } + + dropped = *((A_UINT32 *)datap); + if (dropped > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%d log buffers are dropped \n", dropped)); + } + datap += sizeof(dropped); + len -= sizeof(dropped); + + count = 0; + buffer = (A_UINT32 *)datap; + length = (len >> 2); + + if ( dbglog_process_type == DBGLOG_PROCESS_PRINT_RAW) { + return dbglog_print_raw_data(buffer, length); + } + + if ( dbglog_process_type == DBGLOG_PROCESS_NET_RAW) { + if(appstarted){ + return dbglog_process_netlink_data((wmi_unified_t)wma->wmi_handle, + (A_UINT8 *)buffer, + len, dropped); + } else { + return 0; + } + + } + +#ifdef WLAN_OPEN_SOURCE + if (dbglog_process_type == DBGLOG_PROCESS_POOL_RAW) { + return dbglog_debugfs_raw_data((wmi_unified_t)wma->wmi_handle, + (A_UINT8 *)buffer, len, dropped); + } +#endif /* WLAN_OPEN_SOURCE */ + + while ((count + 2) < length) { + timestamp = DBGLOG_GET_TIME_STAMP(buffer[count]); + debugid = DBGLOG_GET_DBGID(buffer[count + 1]); + moduleid = DBGLOG_GET_MODULEID(buffer[count + 1]); + vapid = DBGLOG_GET_VDEVID(buffer[count + 1]); + numargs = DBGLOG_GET_NUMARGS(buffer[count + 1]); + + if ((count + 2 + numargs) > length) + return 0; + + if (moduleid >= WLAN_MODULE_ID_MAX) + return 0; + + if (mod_print[moduleid] == NULL) { + /* No module specific log registered use the default handler*/ + dbglog_default_print_handler(moduleid, vapid, debugid, timestamp, + numargs, + (((A_UINT32 *)buffer) + 2 + count)); + } else { + if(!(mod_print[moduleid](moduleid, vapid, debugid, timestamp, + numargs, + (((A_UINT32 *)buffer) + 2 + count)))) { + /* The message is not handled by the module specific handler*/ + dbglog_default_print_handler(moduleid, vapid, debugid, timestamp, + numargs, + (((A_UINT32 *)buffer) + 2 + count)); + + } + } + + count += numargs + 2; /* 32 bit Time stamp + 32 bit Dbg header*/ + } + /* Always returns zero */ + return (0); +} + +void +dbglog_reg_modprint(A_UINT32 mod_id, module_dbg_print printfn) +{ + if (!mod_print[mod_id]) { + mod_print[mod_id] = printfn; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("module print is already registered for this module %d\n", + mod_id)); + } +} + +void +dbglog_sm_print( + A_UINT32 timestamp, + A_UINT16 vap_id, + A_UINT16 numargs, + A_UINT32 *args, + const char *module_prefix, + const char *states[], A_UINT32 num_states, + const char *events[], A_UINT32 num_events) +{ + A_UINT8 type, arg1, arg2, arg3; + A_UINT32 extra, extra2, extra3; + + if (numargs != 4) { + return; + } + + type = (args[0] >> 24) & 0xff; + arg1 = (args[0] >> 16) & 0xff; + arg2 = (args[0] >> 8) & 0xff; + arg3 = (args[0] >> 0) & 0xff; + + extra = args[1]; + extra2 = args[2]; + extra3 = args[3]; + + switch (type) { + case 0: /* state transition */ + if (arg1 < num_states && arg2 < num_states) { + dbglog_printf(timestamp, vap_id, "%s: %s => %s (%#x, %#x, %#x)", + module_prefix, states[arg1], states[arg2], extra, extra2, extra3); + } else { + dbglog_printf(timestamp, vap_id, "%s: %u => %u (%#x, %#x, %#x)", + module_prefix, arg1, arg2, extra, extra2, extra3); + } + break; + case 1: /* dispatch event */ + if (arg1 < num_states && arg2 < num_events) { + dbglog_printf(timestamp, vap_id, "%s: %s < %s (%#x, %#x, %#x)", + module_prefix, states[arg1], events[arg2], extra, extra2, extra3); + } else { + dbglog_printf(timestamp, vap_id, "%s: %u < %u (%#x, %#x, %#x)", + module_prefix, arg1, arg2, extra, extra2, extra3); + } + break; + case 2: /* warning */ + switch (arg1) { + case 0: /* unhandled event */ + if (arg2 < num_states && arg3 < num_events) { + dbglog_printf(timestamp, vap_id, "%s: unhandled event %s in state %s (%#x, %#x, %#x)", + module_prefix, events[arg3], states[arg2], extra, extra2, extra3); + } else { + dbglog_printf(timestamp, vap_id, "%s: unhandled event %u in state %u (%#x, %#x, %#x)", + module_prefix, arg3, arg2, extra, extra2, extra3); + } + break; + default: + break; + + } + break; + } +} + +A_BOOL +dbglog_sta_powersave_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "IDLE", + "ACTIVE", + "SLEEP_TXQ_FLUSH", + "SLEEP_TX_SENT", + "PAUSE", + "SLEEP_DOZE", + "SLEEP_AWAKE", + "ACTIVE_TXQ_FLUSH", + "ACTIVE_TX_SENT", + "PAUSE_TXQ_FLUSH", + "PAUSE_TX_SENT", + "IDLE_TXQ_FLUSH", + "IDLE_TX_SENT", + }; + + static const char *events[] = { + "START", + "STOP", + "PAUSE", + "UNPAUSE", + "TIM", + "DTIM", + "SEND_COMPLETE", + "PRE_SEND", + "RX", + "HWQ_EMPTY", + "PAUSE_TIMEOUT", + "TXRX_INACTIVITY_TIMEOUT", + "PSPOLL_TIMEOUT", + "UAPSD_TIMEOUT", + "DELAYED_SLEEP_TIMEOUT", + "SEND_N_COMPLETE", + "TIDQ_PAUSE_COMPLETE", + "SEND_PSPOLL", + "SEND_SPEC_PSPOLL", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "STA PS", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + case PS_STA_PM_ARB_REQUEST: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, "PM ARB request flags=%x, last_time=%x %s: %s", + args[1], args[2], dbglog_get_module_str(args[0]), args[3] ? "SLEEP" : "WAKE"); + } + break; + case PS_STA_DELIVER_EVENT: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, "STA PS: %s %s", + (args[0] == 0 ? "PAUSE_COMPLETE" : + (args[0] == 1 ? "UNPAUSE_COMPLETE" : + (args[0] == 2 ? "SLEEP" : + (args[0] == 3 ? "AWAKE" : "UNKNOWN")))), + (args[1] == 0 ? "SUCCESS" : + (args[1] == 1 ? "TXQ_FLUSH_TIMEOUT" : + (args[1] == 2 ? "NO_ACK" : + (args[1] == 3 ? "RX_LEAK_TIMEOUT" : + (args[1] == 4 ? "PSPOLL_UAPSD_BUSY_TIMEOUT" : "UNKNOWN")))))); + } + break; + case PS_STA_PSPOLL_SEQ_DONE: + if (numargs == 5) { + dbglog_printf(timestamp, vap_id, "STA PS poll: queue=%u comp=%u rsp=%u rsp_dur=%u fc=%x qos=%x %s", + args[0], args[1], args[2], args[3], + (args[4] >> 16) & 0xffff, + (args[4] >> 8) & 0xff, + (args[4] & 0xff) == 0 ? "SUCCESS" : + (args[4] & 0xff) == 1 ? "NO_ACK" : + (args[4] & 0xff) == 2 ? "DROPPED" : + (args[4] & 0xff) == 3 ? "FILTERED" : + (args[4] & 0xff) == 4 ? "RSP_TIMEOUT" : "UNKNOWN"); + } + break; + case PS_STA_COEX_MODE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, "STA PS COEX MODE %s", + args[0] ? "ENABLED" : "DISABLED"); + } + break; + case PS_STA_PSPOLL_ALLOW: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, "STA PS-Poll %s flags=%x time=%u", + args[0] ? "ALLOW" : "DISALLOW", args[1], args[2]); + } + break; + case PS_STA_SET_PARAM: + if (numargs == 2) { + struct { + char *name; + int is_time_param; + } params[] = { + { "MAX_SLEEP_ATTEMPTS", 0 }, + { "DELAYED_SLEEP", 1 }, + { "TXRX_INACTIVITY", 1 }, + { "MAX_TX_BEFORE_WAKE", 0 }, + { "UAPSD_TIMEOUT", 1 }, + { "UAPSD_CONFIG", 0 }, + { "PSPOLL_RESPONSE_TIMEOUT", 1 }, + { "MAX_PSPOLL_BEFORE_WAKE", 0 }, + { "RX_WAKE_POLICY", 0 }, + { "DELAYED_PAUSE_RX_LEAK", 1 }, + { "TXRX_INACTIVITY_BLOCKED_RETRY", 1 }, + { "SPEC_WAKE_INTERVAL", 1 }, + { "MAX_SPEC_NODATA_PSPOLL", 0 }, + { "ESTIMATED_PSPOLL_RESP_TIME", 1 }, + { "QPOWER_MAX_PSPOLL_BEFORE_WAKE", 0 }, + { "QPOWER_ENABLE", 0 }, + }; + A_UINT32 param = args[0]; + A_UINT32 value = args[1]; + + if (param < ARRAY_LENGTH(params)) { + if (params[param].is_time_param) { + dbglog_printf(timestamp, vap_id, "STA PS SET_PARAM %s => %u (us)", + params[param].name, value); + } else { + dbglog_printf(timestamp, vap_id, "STA PS SET_PARAM %s => %#x", + params[param].name, value); + } + } else { + dbglog_printf(timestamp, vap_id, "STA PS SET_PARAM %x => %#x", + param, value); + } + } + break; + case PS_STA_SPECPOLL_TIMER_STARTED: + dbglog_printf(timestamp, vap_id, "SPEC Poll Timer Started: Beacon time Remaining:%d wakeup interval:%d", args[0], args[1]); + break; + case PS_STA_SPECPOLL_TIMER_STOPPED: + dbglog_printf(timestamp, vap_id, + "SPEC Poll Timer Stopped"); + break; + default: + return FALSE; + } + + return TRUE; +} +/* IBSS PS sub modules */ +enum wlan_ibss_ps_sub_module { + WLAN_IBSS_PS_SUB_MODULE_IBSS_NW_SM = 0, + WLAN_IBSS_PS_SUB_MODULE_IBSS_SELF_PS = 1, + WLAN_IBSS_PS_SUB_MODULE_IBSS_PEER_PS = 2, + WLAN_IBSS_PS_SUB_MODULE_MAX = 3, +}; + +#define WLAN_IBSS_PS_SUB_MODULE_OFFSET 0x1E + +A_BOOL +dbglog_ibss_powersave_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *nw_states[] = { + "WAIT_FOR_TBTT", + "ATIM_WINDOW_PRE_BCN", + "ATIM_WINDOW_POST_BCN", + "OUT_OF_ATIM_WINDOW", + "PAUSE_PENDING", + "PAUSED", + }; + + static const char *ps_states[] = { + "ACTIVE", + "SLEEP_TX_SEND", + "SLEEP_DOZE_PAUSE_PENDING", + "SLEEP_DOZE", + "SLEEP_AWAKE", + "ACTIVE_TX_SEND", + "PAUSE_TX_SEND", + "PAUSED", + }; + + static const char *peer_ps_states[] = { + "ACTIVE", + "SLEEP_AWAKE", + "SLEEP_DOZE", + "PS_UNKNOWN", + }; + + static const char *events[] = { + "START", + "STOP", + "SWBA", + "TBTT", + "TX_BCN_CMP", + "SEND_COMPLETE", + "SEND_N_COMPLETE", + "PRE_SEND", + "RX", + "UC_INACTIVITY_TIMEOUT", + "BC_INACTIVITY_TIMEOUT", + "ATIM_WINDOW_BEGIN", + "ATIM_WINDOW_END", + "HWQ_EMPTY", + "UC_ATIM_RCVD", + "TRAFFIC_EXCHANGE_DONE", + "POWER_SAVE_STATE_CHANGE", + "NEW_PEER_JOIN", + "IBSS_VDEV_PAUSE_REQUEST", + "IBSS_VDEV_PAUSE_RESPONSE", + "IBSS_VDEV_PAUSE_TIMEOUT", + "IBSS_VDEV_UNPAUSE_REQUEST", + "PS_STATE_CHANGE", + }; + + enum wlan_ibss_ps_sub_module sub_module; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + sub_module = (args[1] >> WLAN_IBSS_PS_SUB_MODULE_OFFSET) & 0x3; + switch(sub_module) + { + case WLAN_IBSS_PS_SUB_MODULE_IBSS_NW_SM: + dbglog_sm_print(timestamp, vap_id, numargs, args, "IBSS PS NW", + nw_states, ARRAY_LENGTH(nw_states), events, + ARRAY_LENGTH(events)); + break; + case WLAN_IBSS_PS_SUB_MODULE_IBSS_SELF_PS: + dbglog_sm_print(timestamp, vap_id, numargs, args, + "IBSS PS Self", ps_states, ARRAY_LENGTH(ps_states), + events, ARRAY_LENGTH(events)); + break; + case WLAN_IBSS_PS_SUB_MODULE_IBSS_PEER_PS: + dbglog_sm_print(timestamp, vap_id, numargs, args, + "IBSS PS Peer", peer_ps_states, + ARRAY_LENGTH(peer_ps_states), events, + ARRAY_LENGTH(events)); + break; + default: + break; + } + break; + case IBSS_PS_DBGID_PEER_CREATE: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: peer alloc failed for peer ID:%u", args[0]); + } else if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: create peer ID=%u", args[0]); + } + break; + case IBSS_PS_DBGID_PEER_DELETE: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: delete peer ID=%u num_peers:%d num_sleeping_peers:%d ps_enabled_for_this_peer:%d", + args[0], args[1], args[2], args[3]); + } + break; + case IBSS_PS_DBGID_VDEV_CREATE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: vdev alloc failed", + args[0]); + } else if (numargs == 0) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: vdev created"); + } + break; + case IBSS_PS_DBGID_VDEV_DELETE: + dbglog_printf(timestamp, vap_id, "IBSS PS: vdev deleted"); + break; + + case IBSS_PS_DBGID_VDEV_EVENT: + if (numargs == 1) { + if (args[0] == 5) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: vdev event for peer add"); + } else if (args[0] == 7) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: vdev event for peer delete"); + } + else { + dbglog_printf(timestamp, vap_id, + "IBSS PS: vdev event %u", args[0]); + } + } + break; + + case IBSS_PS_DBGID_PEER_EVENT: + if (numargs == 4) { + if (args[0] == 0xFFFF) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: pre_send for peer:%u peer_type:%u sm_event_mask:%0x", + args[1], args[3], args[2]); + } else if (args[0] == 0x20000) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: send_complete for peer:%u peer_type:%u sm_event_mask:%0x", + args[1], args[3], args[2]); + } else if (args[0] == 0x10) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: send_n_complete for peer:%u peer_type:%u sm_event_mask:%0x", + args[1], args[3], args[2]); + } else if (args[0] == 0x40) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: rx event for peer:%u peer_type:%u sm_event_mask:%0x", + args[1], args[3], args[2]); + } else if (args[0] == 0x4) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: hw_q_empty for peer:%u peer_type:%u sm_event_mask:%0x", + args[1], args[3], args[2]); + } + } + break; + + case IBSS_PS_DBGID_DELIVER_CAB: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Deliver CAB n_mpdu:%d send_flags:%0x tid_cur:%d q_depth_for_other_tid:%d", + args[0], args[1], args[2], args[3]); + } + break; + + case IBSS_PS_DBGID_DELIVER_UC_DATA: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Deliver UC data peer:%d tid:%d n_mpdu:%d send_flags:%0x", + args[0], args[1], args[2], args[3]); + } + break; + + case IBSS_PS_DBGID_DELIVER_UC_DATA_ERROR: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Deliver UC data error peer:%d tid:%d allowed_tidmask:%0x, pending_tidmap:%0x", + args[0], args[1], args[2], args[3]); + } + break; + + case IBSS_PS_DBGID_UC_INACTIVITY_TMR_RESTART: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: UC timer restart peer:%d timer_val:%0x", + args[0], args[1]); + } + break; + + case IBSS_PS_DBGID_MC_INACTIVITY_TMR_RESTART: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: MC timer restart timer_val:%0x", + args[0]); + } + break; + + case IBSS_PS_DBGID_NULL_TX_COMPLETION: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: null tx completion peer:%d tx_completion_status:%d flags:%0x", + args[0], args[1], args[2]); + } + break; + + case IBSS_PS_DBGID_ATIM_TIMER_START: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: ATIM timer start tsf:%0x %0x tbtt:%0x %0x", + args[0], args[1], args[2], args[3]); + } + break; + + case IBSS_PS_DBGID_UC_ATIM_SEND: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Send ATIM to peer:%d", + args[1]); + } else if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: no peers to send UC ATIM", + args[1]); + } + break; + + case IBSS_PS_DBGID_BC_ATIM_SEND: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: MC Data, num_of_peers:%d bc_atim_sent:%d", + args[1], args[0]); + } + break; + + case IBSS_PS_DBGID_UC_TIMEOUT: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: UC timeout for peer:%d send_null:%d", + args[0], args[1]); + } + break; + + case IBSS_PS_DBGID_PWR_COLLAPSE_ALLOWED: + dbglog_printf(timestamp, vap_id, "IBSS PS: allow power collapse"); + break; + + case IBSS_PS_DBGID_PWR_COLLAPSE_NOT_ALLOWED: + if (numargs == 0) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: power collapse not allowed by INI"); + } else if(numargs == 1) { + dbglog_printf(timestamp, vap_id, "IBSS PS: power collapse not allowed since peer id:%d is not PS capable", + args[0]); + } else if(numargs == 2) { + dbglog_printf(timestamp, vap_id, "IBSS PS: power collapse not allowed - no peers in NW"); + } else if (numargs == 3) { + if (args[0] == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: power collapse not allowed, non-zero qdepth %d %d", + args[1], args[2]); + } else if (args[0] == 3) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: power collapse not allowed by peer:%d peer_flags:%0x", + args[1], args[2]); + } + } else if (numargs == 5) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: power collapse not allowed by state m/c nw_cur_state:%d nw_next_state:%d ps_cur_state:%d flags:%0x", + args[1], args[2], args[3], args[4]); + } + break; + + case IBSS_PS_DBGID_SET_PARAM: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Set Param ID:%0x Value:%0x", + args[0], args[1]); + } + break; + + case IBSS_PS_DBGID_HOST_TX_PAUSE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Pausing host, vdev_map:%0x", + args[0]); + } + break; + + case IBSS_PS_DBGID_HOST_TX_UNPAUSE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Unpausing host, vdev_map:%0x", + args[0]); + } + break; + case IBSS_PS_DBGID_PS_DESC_BIN_LWM: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: LWM, vdev_map:%0x", + args[0]); + } + break; + + case IBSS_PS_DBGID_PS_DESC_BIN_HWM: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: HWM, vdev_map:%0x", + args[0]); + } + break; + + case IBSS_PS_DBGID_PS_KICKOUT_PEER: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "IBSS PS: Kickout peer id:%d atim_fail_cnt:%d status:%d", + args[0], args[1], args[2]); + } + break; + + case IBSS_PS_DBGID_SET_PEER_PARAM: + if(numargs == 3) { + dbglog_printf(timestamp, vap_id, "IBSS PS: Set Peer Id:%d Param ID:%0x Value:%0x", + args[0], args[1], args[2]); + } + break; + + case IBSS_PS_DBGID_BCN_ATIM_WIN_MISMATCH: + if(numargs == 4) { + if(args[0] == 0xDEAD) { + dbglog_printf(timestamp, vap_id, "IBSS PS: ATIM window length mismatch, our's:%d, peer id:%d, peer's:%d", + args[1], args[2], args[3]); + } else if(args[0] == 0xBEEF) { + dbglog_printf(timestamp, vap_id, "IBSS PS: Peer ATIM window length changed, peer id:%d, peer recorded atim window:%d new atim window:%d", + args[1], args[2], args[3]); + } + } + break; + + case IBSS_PS_DBGID_RX_CHAINMASK_CHANGE: + if(numargs == 2) { + if(args[1] == 0x1) { + dbglog_printf(timestamp, vap_id, "IBSS PS: Voting for low power chainmask from :%d", args[0]); + } else { + dbglog_printf(timestamp, vap_id, "IBSS PS: Voting for high power chainmask from :%d", args[0]); + } + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL dbglog_ratectrl_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + switch (dbg_id) { + case RATECTRL_DBGID_ASSOC: + dbglog_printf(timestamp, vap_id, "RATE: ChainMask %d, phymode %d, ni_flags 0x%08x, vht_mcs_set 0x%04x, ht_mcs_set 0x%04x", + args[0], args[1], args[2], args[3], args[4]); + break; + case RATECTRL_DBGID_NSS_CHANGE: + dbglog_printf(timestamp, vap_id, "RATE: NEW NSS %d\n", args[0]); + break; + case RATECTRL_DBGID_CHAINMASK_ERR: + dbglog_printf(timestamp, vap_id, "RATE: Chainmask ERR %d %d %d\n", + args[0], args[1], args[2]); + break; + case RATECTRL_DBGID_UNEXPECTED_FRAME: + dbglog_printf(timestamp, vap_id, "RATE: WARN1: rate %d flags 0x%08x\n", args[0], args[1]); + break; + case RATECTRL_DBGID_WAL_RCQUERY: + dbglog_printf(timestamp, vap_id, "ratectrl_dbgid_wal_rcquery [rix1 %d rix2 %d rix3 %d proberix %d ppduflag 0x%x] ", + args[0], args[1], args[2], args[3], args[4]); + break; + case RATECTRL_DBGID_WAL_RCUPDATE: + dbglog_printf(timestamp, vap_id, "ratectrl_dbgid_wal_rcupdate [numelems %d ppduflag 0x%x] ", + args[0], args[1]); + break; + case RATECTRL_DBGID_GTX_UPDATE: + { + switch (args[0]) { + case 255: + dbglog_printf(timestamp, vap_id, "GtxInitPwrCfg [bw[last %d|cur %d] rtcode 0x%x tpc %d tpc_init_pwr_cfg %d] ", + args[1] >> 8, args[1] & 0xff, args[2], args[3], args[4]); + break; + case 254: + dbglog_printf(timestamp, vap_id, "gtx_cfg_addr [RTMask0@0x%x PERThreshold@0x%x gtxTPCMin@0x%x userGtxMask@0x%x] ", + args[1], args[2], args[3], args[4]); + break; + default: + dbglog_printf(timestamp, vap_id, "gtx_update [act %d bw %d rix 0x%x tpc %d per %d lastrssi %d] ", + args[0], args[1], args[2], args[3], args[4], args[5]); + } + } + break; + } + return TRUE; +} + +A_BOOL dbglog_ani_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + switch (dbg_id) { + case ANI_DBGID_ENABLE: + dbglog_printf(timestamp, vap_id, + "ANI Enable: %d", args[0]); + break; + case ANI_DBGID_POLL: + dbglog_printf(timestamp, vap_id, + "ANI POLLING: AccumListenTime %d ListenTime %d ofdmphyerr %d cckphyerr %d", + args[0], args[1], args[2],args[3]); + break; + case ANI_DBGID_RESTART: + dbglog_printf(timestamp, vap_id,"ANI Restart"); + break; + case ANI_DBGID_CURRENT_LEVEL: + dbglog_printf(timestamp, vap_id, + "ANI CURRENT LEVEL ofdm level %d cck level %d",args[0],args[1]); + break; + case ANI_DBGID_OFDM_LEVEL: + dbglog_printf(timestamp, vap_id, + "ANI UPDATE ofdm level %d firstep %d firstep_low %d cycpwr_thr %d self_corr_low %d", + args[0], args[1],args[2],args[3],args[4]); + break; + case ANI_DBGID_CCK_LEVEL: + dbglog_printf(timestamp, vap_id, + "ANI UPDATE cck level %d firstep %d firstep_low %d mrc_cck %d", + args[0],args[1],args[2],args[3]); + break; + case ANI_DBGID_CONTROL: + dbglog_printf(timestamp, vap_id, + "ANI CONTROL ofdmlevel %d ccklevel %d\n", + args[0]); + + break; + case ANI_DBGID_OFDM_PARAMS: + dbglog_printf(timestamp, vap_id, + "ANI ofdm_control firstep %d cycpwr %d\n", + args[0],args[1]); + break; + case ANI_DBGID_CCK_PARAMS: + dbglog_printf(timestamp, vap_id, + "ANI cck_control mrc_cck %d barker_threshold %d\n", + args[0],args[1]); + break; + case ANI_DBGID_RESET: + dbglog_printf(timestamp, vap_id, + "ANI resetting resetflag %d resetCause %8x channel index %d", + args[0],args[1],args[2]); + break; + case ANI_DBGID_SELF_CORR_LOW: + dbglog_printf(timestamp, vap_id,"ANI self_corr_low %d",args[0]); + break; + case ANI_DBGID_FIRSTEP: + dbglog_printf(timestamp, vap_id,"ANI firstep %d firstep_low %d", + args[0],args[1]); + break; + case ANI_DBGID_MRC_CCK: + dbglog_printf(timestamp, vap_id,"ANI mrc_cck %d",args[0]); + break; + case ANI_DBGID_CYCPWR: + dbglog_printf(timestamp, vap_id,"ANI cypwr_thresh %d",args[0]); + break; + case ANI_DBGID_POLL_PERIOD: + dbglog_printf(timestamp, vap_id,"ANI Configure poll period to %d",args[0]); + break; + case ANI_DBGID_LISTEN_PERIOD: + dbglog_printf(timestamp, vap_id,"ANI Configure listen period to %d",args[0]); + break; + case ANI_DBGID_OFDM_LEVEL_CFG: + dbglog_printf(timestamp, vap_id,"ANI Configure ofdm level to %d",args[0]); + break; + case ANI_DBGID_CCK_LEVEL_CFG: + dbglog_printf(timestamp, vap_id,"ANI Configure cck level to %d",args[0]); + break; + default: + dbglog_printf(timestamp, vap_id,"ANI arg1 %d arg2 %d arg3 %d", + args[0],args[1],args[2]); + break; + } + return TRUE; +} + +A_BOOL +dbglog_ap_powersave_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + switch (dbg_id) { + case AP_PS_DBGID_UPDATE_TIM: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "AP PS: TIM update AID=%u %s", + args[0], args[1] ? "set" : "clear"); + } + break; + case AP_PS_DBGID_PEER_STATE_CHANGE: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u power save %s", + args[0], args[1] ? "enabled" : "disabled"); + } + break; + case AP_PS_DBGID_PSPOLL: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u pspoll response tid=%u flags=%x", + args[0], args[1], args[2]); + } + break; + case AP_PS_DBGID_PEER_CREATE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "AP PS: create peer AID=%u", args[0]); + } + break; + case AP_PS_DBGID_PEER_DELETE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "AP PS: delete peer AID=%u", args[0]); + } + break; + case AP_PS_DBGID_VDEV_CREATE: + dbglog_printf(timestamp, vap_id, "AP PS: vdev create"); + break; + case AP_PS_DBGID_VDEV_DELETE: + dbglog_printf(timestamp, vap_id, "AP PS: vdev delete"); + break; + case AP_PS_DBGID_SYNC_TIM: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u advertised=%#x buffered=%#x", args[0], args[1], args[2]); + } + break; + case AP_PS_DBGID_NEXT_RESPONSE: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u select next response %s%s%s", args[0], + args[1] ? "(usp active) " : "", + args[2] ? "(pending usp) " : "", + args[3] ? "(pending poll response)" : ""); + } + break; + case AP_PS_DBGID_START_SP: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u START SP tsf=%#x (%u)", + args[0], args[1], args[2]); + } + break; + case AP_PS_DBGID_COMPLETED_EOSP: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u EOSP eosp_tsf=%#x trigger_tsf=%#x", + args[0], args[1], args[2]); + } + break; + case AP_PS_DBGID_TRIGGER: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u TRIGGER tsf=%#x %s%s", args[0], args[1], + args[2] ? "(usp active) " : "", + args[3] ? "(send_n in progress)" : ""); + } + break; + case AP_PS_DBGID_DUPLICATE_TRIGGER: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u DUP TRIGGER tsf=%#x seq=%u ac=%u", + args[0], args[1], args[2], args[3]); + } + break; + case AP_PS_DBGID_UAPSD_RESPONSE: + if (numargs == 5) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u UAPSD response tid=%u, n_mpdu=%u flags=%#x max_sp=%u current_sp=%u", + args[0], args[1], args[2], args[3], (args[4] >> 16) & 0xffff, args[4] & 0xffff); + } + break; + case AP_PS_DBGID_SEND_COMPLETE: + if (numargs == 5) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u SEND_COMPLETE fc=%#x qos=%#x %s%s", + args[0], args[1], args[2], + args[3] ? "(usp active) " : "", + args[4] ? "(pending poll response)" : ""); + } + break; + case AP_PS_DBGID_SEND_N_COMPLETE: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u SEND_N_COMPLETE %s%s", + args[0], + args[1] ? "(usp active) " : "", + args[2] ? "(pending poll response)" : ""); + } + break; + case AP_PS_DBGID_DETECT_OUT_OF_SYNC_STA: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "AP PS: AID=%u detected out-of-sync now=%u tx_waiting=%u txq_depth=%u", + args[0], args[1], args[2], args[3]); + } + break; + case AP_PS_DBGID_DELIVER_CAB: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "AP PS: CAB %s n_mpdus=%u, flags=%x, extra=%u", + (args[0] == 17) ? "MGMT" : "DATA", args[1], args[2], args[3]); + } + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL +dbglog_wal_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "ACTIVE", + "WAIT", + "WAIT_FILTER", + "PAUSE", + "PAUSE_SEND_N", + "BLOCK", + }; + + static const char *events[] = { + "PAUSE", + "PAUSE_FILTER", + "UNPAUSE", + + "BLOCK", + "BLOCK_FILTER", + "UNBLOCK", + + "HWQ_EMPTY", + "ALLOW_N", + }; + +#define WAL_VDEV_TYPE(type) \ + (type == 0 ? "AP" : \ + (type == 1 ? "STA" : \ + (type == 2 ? "IBSS" : \ + (type == 2 ? "MONITOR" : \ + "UNKNOWN")))) + +#define WAL_SLEEP_STATE(state) \ + (state == 1 ? "NETWORK SLEEP" : \ + (state == 2 ? "AWAKE" : \ + (state == 3 ? "SYSTEM SLEEP" : \ + "UNKNOWN"))) + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "TID PAUSE", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + case WAL_DBGID_SET_POWER_STATE: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "WAL %s => %s, req_count=%u", + WAL_SLEEP_STATE(args[0]), WAL_SLEEP_STATE(args[1]), + args[2]); + } + break; + case WAL_DBGID_CHANNEL_CHANGE_FORCE_RESET: + if (numargs == 4) { + dbglog_printf(timestamp, vap_id, + "WAL channel change (force reset) freq=%u, flags=%u mode=%u rx_ok=%u tx_ok=%u", + args[0] & 0x0000ffff, (args[0] & 0xffff0000) >> 16, args[1], + args[2], args[3]); + } + break; + case WAL_DBGID_CHANNEL_CHANGE: + if (numargs == 2) { + dbglog_printf(timestamp, vap_id, + "WAL channel change freq=%u, mode=%u flags=%u rx_ok=1 tx_ok=1", + args[0] & 0x0000ffff, (args[0] & 0xffff0000) >> 16, args[1]); + } + break; + case WAL_DBGID_VDEV_START: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, "WAL %s vdev started", + WAL_VDEV_TYPE(args[0])); + } + break; + case WAL_DBGID_VDEV_STOP: + dbglog_printf(timestamp, vap_id, "WAL %s vdev stopped", + WAL_VDEV_TYPE(args[0])); + break; + case WAL_DBGID_VDEV_UP: + dbglog_printf(timestamp, vap_id, "WAL %s vdev up, count=%u", + WAL_VDEV_TYPE(args[0]), args[1]); + break; + case WAL_DBGID_VDEV_DOWN: + dbglog_printf(timestamp, vap_id, "WAL %s vdev down, count=%u", + WAL_VDEV_TYPE(args[0]), args[1]); + break; + case WAL_DBGID_TX_MGMT_DESCID_SEQ_TYPE_LEN: + dbglog_printf(timestamp, vap_id, "WAL Tx Mgmt frame desc_id=0x%x, seq=0x%x, type=0x%x, len=0x%x islocal=0x%x", + args[0], args[1], args[2], (args[3] & 0xffff0000) >> 16, args[3] & 0x0000ffff); + break; + case WAL_DBGID_TX_MGMT_COMP_DESCID_STATUS: + dbglog_printf(timestamp, vap_id, "WAL Tx Mgmt frame completion desc_id=0x%x, status=0x%x, islocal=0x%x", + args[0], args[1], args[2]); + break; + case WAL_DBGID_TX_DATA_MSDUID_SEQ_TYPE_LEN: + dbglog_printf(timestamp, vap_id, "WAL Tx Data frame msdu_id=0x%x, seq=0x%x, type=0x%x, len=0x%x", + args[0], args[1], args[2], args[3]); + break; + case WAL_DBGID_TX_DATA_COMP_MSDUID_STATUS: + dbglog_printf(timestamp, vap_id, "WAL Tx Data frame completion desc_id=0x%x, status=0x%x, seq=0x%x", + args[0], args[1], args[2]); + break; + case WAL_DBGID_RESET_PCU_CYCLE_CNT: + dbglog_printf(timestamp, vap_id, "WAL PCU cycle counter value at reset:%x", args[0]); + break; + case WAL_DBGID_TX_DISCARD: + dbglog_printf(timestamp, vap_id, "WAL Tx enqueue discard msdu_id=0x%x", args[0]); + break; + case WAL_DBGID_SET_HW_CHAINMASK: + dbglog_printf(timestamp, vap_id, "WAL_DBGID_SET_HW_CHAINMASK " + "pdev=%d, txchain=0x%x, rxchain=0x%x", + args[0], args[1], args[2]); + break; + case WAL_DBGID_SET_HW_CHAINMASK_TXRX_STOP_FAIL: + dbglog_printf(timestamp, vap_id, "WAL_DBGID_SET_HW_CHAINMASK_TXRX_STOP_FAIL rxstop=%d, txstop=%d", + args[0], args[1]); + break; + case WAL_DBGID_GET_HW_CHAINMASK: + dbglog_printf(timestamp, vap_id, "WAL_DBGID_GET_HW_CHAINMASK " + "txchain=0x%x, rxchain=0x%x", + args[0], args[1]); + break; + case WAL_DBGID_SMPS_DISABLE: + dbglog_printf(timestamp, vap_id, "WAL_DBGID_SMPS_DISABLE"); + break; + case WAL_DBGID_SMPS_ENABLE_HW_CNTRL: + dbglog_printf(timestamp, vap_id, "WAL_DBGID_SMPS_ENABLE_HW_CNTRL low_pwr_mask=0x%x, high_pwr_mask=0x%x", + args[0], args[1]); + break; + case WAL_DBGID_SMPS_SWSEL_CHAINMASK: + dbglog_printf(timestamp, vap_id, "WAL_DBGID_SMPS_SWSEL_CHAINMASK low_pwr=0x%x, chain_mask=0x%x", + args[0], args[1]); + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL +dbglog_scan_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "IDLE", + "BSSCHAN", + "WAIT_FOREIGN_CHAN", + "FOREIGN_CHANNEL", + "TERMINATING" + }; + + static const char *events[] = { + "REQ", + "STOP", + "BSSCHAN", + "FOREIGN_CHAN", + "CHECK_ACTIVITY", + "REST_TIME_EXPIRE", + "DWELL_TIME_EXPIRE", + "PROBE_TIME_EXPIRE", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "SCAN", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL dbglog_coex_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 * args) +{ + A_UINT8 i; + char * dbg_id_str; + + static const char * wlan_rx_xput_status[] = { + "WLAN_XPUT_NORMAL", + "WLAN_XPUT_UNDER_THRESH", + "WLAN_XPUT_CRITICAL", + "WLAN_XPUT_RECOVERY_TIMEOUT", + }; + + static const char * coex_sched_req[] = { + "SCHED_REQ_NEXT", + "SCHED_REQ_BT", + "SCHED_REQ_WLAN", + "SCHED_REQ_POSTPAUSE", + "SCHED_REQ_UNPAUSE", + }; + + static const char * coex_sched_type[] = { + "SCHED_NONE", + "SCHED_WLAN", + "SCHED_BT", + "SCHED_WLAN_PAUSE", + "SCHED_WLAN_POSTPAUSE", + "SCHED_WLAN_UNPAUSE", + "COEX_SCHED_MWS", + }; + + static const char * coex_trf_mgmt_type[] = { + "TRF_MGMT_FREERUN", + "TRF_MGMT_SHAPE_PM", + "TRF_MGMT_SHAPE_PSP", + "TRF_MGMT_SHAPE_S_CTS", + "TRF_MGMT_SHAPE_OCS", + "TRF_MGMT_SHAPE_FIXED_TIME", + "TRF_MGMT_SHAPE_NOA", + "TRF_MGMT_SHAPE_OCS_CRITICAL", + "TRF_MGMT_NONE", + }; + + static const char * coex_system_status[] = { + "ALL_OFF", + "BTCOEX_NOT_REQD", + "WLAN_IS_IDLE", + "EXECUTE_SCHEME", + "BT_FULL_CONCURRENCY", + "WLAN_SLEEPING", + "WLAN_IS_PAUSED", + "WAIT_FOR_NEXT_ACTION", + "SOC_WAKE", + }; + + static const char * wlan_rssi_type[] = { + "LOW_RSSI", + "MID_RSSI", + "HI_RSSI", + "INVALID_RSSI", + }; + + static const char * coex_bt_scheme[] = { + "IDLE_CTRL", + "ACTIVE_ASYNC_CTRL", + "PASSIVE_SYNC_CTRL", + "ACTIVE_SYNC_CTRL", + "DEFAULT_CTRL", + "CONCURRENCY_CTRL", + }; + + static const char * wal_peer_rx_rate_stats_event_sent[] = { + "PR_RX_EVT_SENT_NONE", + "PR_RX_EVT_SENT_LOWER", + "PR_RX_EVT_SENT_UPPER", + }; + + static const char * wlan_psp_stimulus[] = { + "ENTRY", + "EXIT", + "PS_READY", + "PS_NOT_READY", + "RX_MORE_DATA_RCVD", + "RX_NO_MORE_DATA_RCVD", + "TX_DATA_COMPLT", + "TX_COMPLT", + "TIM_SET", + "REQ", + "DONE_SUCCESS", + "DONE_NO_PS_POLL_ACK", + "DONE_RESPONSE_TMO", + "DONE_DROPPED", + "DONE_FILTERED", + "WLAN_START", + "NONWLAN_START", + "NONWLAN_INTVL_UPDATE", + "NULL_TX", + "NULL_TX_COMPLT", + "BMISS_FIRST", + "NULL_TX_FAIL", + "RX_NO_MORE_DATA_DATAFRM", + }; + + static const char * coex_pspoll_state[] = { + "STATE_DISABLED", + "STATE_NOT_READY", + "STATE_ENABLED", + "STATE_READY", + "STATE_TX_STATUS", + "STATE_RX_STATUS", + }; + + static const char * coex_scheduler_interval[] = { + "COEX_SCHED_NONWLAN_INT", + "COEX_SCHED_WLAN_INT", + }; + + static const char * wlan_weight[] = { + "BT_COEX_BASE", + "BT_COEX_LOW", + "BT_COEX_MID", + "BT_COEX_MID_NONSYNC", + "BT_COEX_HI_NONVOICE", + "BT_COEX_HI", + "BT_COEX_CRITICAL", + }; + + static const char * wlan_power_state[] = { + "SLEEP", + "AWAKE", + "FULL_SLEEP", + }; + + static const char * coex_psp_error_type[] = { + "DISABLED_STATE", + "VDEV_NULL", + "COEX_PSP_ENTRY", + "ZERO_INTERVAL", + "COEX_PSP_EXIT", + "READY_DISABLED", + "READY_NOT_DISABLED", + "POLL_PKT_DROPPED", + "SET_TIMER_PARAM", + }; + + static const char * wlan_phymode[] = { + "A", + "G", + "B", + "G_ONLY", + "NA_HT20", + "NG_HT20", + "NA_HT40", + "NG_HT40", + "AC_VHT20", + "AC_VHT40", + "AC_VHT80", + "AC_VHT20_2G", + "AC_VHT40_2G", + "AC_VHT80_2G", + "UNKNOWN", + }; + + static const char * wlan_curr_band[] = { + "2G", + "5G", + }; + + dbg_id_str = dbglog_get_msg(mod_id, dbg_id); + + switch (dbg_id) { + case COEX_SYSTEM_UPDATE: + if (numargs == 1 && args[0] < 9) { + dbglog_printf(timestamp, vap_id, "%s: %s", dbg_id_str, coex_system_status[args[0]]); + } else if (numargs >= 5 && args[0] < 9 && args[2] < 9) { + dbglog_printf(timestamp, vap_id, "%s: %s, WlanSysState(0x%x), %s, NumChains(%u), AggrLimit(%u)", + dbg_id_str, coex_system_status[args[0]], args[1], coex_trf_mgmt_type[args[2]], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_SCHED_START: + if (numargs >= 5 && args[0] < 5 && args[2] < 9 && args[3] < 4 && args[4] < 4) { + if (args[1] == 0xffffffff) { + dbglog_printf(timestamp, vap_id, "%s: %s, DETERMINE_DURATION, %s, %s, %s", + dbg_id_str, coex_sched_req[args[0]], coex_trf_mgmt_type[args[2]], wlan_rx_xput_status[args[3]], wlan_rssi_type[args[4]]); + } else { + dbglog_printf(timestamp, vap_id, "%s: %s, IntvlDur(%u), %s, %s, %s", + dbg_id_str, coex_sched_req[args[0]], args[1], coex_trf_mgmt_type[args[2]], wlan_rx_xput_status[args[3]], wlan_rssi_type[args[4]]); + } + } else { + return FALSE; + } + break; + case COEX_SCHED_RESULT: + if (numargs >= 5 && args[0] < 5 && args[1] < 9 && args[2] < 9) { + dbglog_printf(timestamp, vap_id, "%s: %s, %s, %s, CoexMgrPolicy(%u), IdleOverride(%u)", + dbg_id_str, coex_sched_req[args[0]], coex_trf_mgmt_type[args[1]], coex_trf_mgmt_type[args[2]], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_BT_SCHEME: + if (numargs >= 1 && args[0] < 6) { + dbglog_printf(timestamp, vap_id, "%s: %s", dbg_id_str, coex_bt_scheme[args[0]]); + } else { + return FALSE; + } + break; + case COEX_TRF_FREERUN: + if (numargs >= 5 && args[0] < 7) { + dbglog_printf(timestamp, vap_id, "%s: %s, AllocatedBtIntvls(%u), BtIntvlCnt(%u), AllocatedWlanIntvls(%u), WlanIntvlCnt(%u)", + dbg_id_str, coex_sched_type[args[0]], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_TRF_SHAPE_PM: // used by ocs now + if (numargs >= 3) { + dbglog_printf(timestamp, vap_id, "%s: IntvlLength(%u), BtDuration(%u), WlanDuration(%u)", + dbg_id_str, args[0], args[1], args[2]); + } else { + return FALSE; + } + break; + case COEX_SYSTEM_MONITOR: + if (numargs >= 5 && args[1] < 4 && args[4] < 4) { + dbglog_printf(timestamp, vap_id, "%s: WlanRxCritical(%u), %s, MinDirectRxRate(%u), MonitorActiveNum(%u), %s", + dbg_id_str, args[0], wlan_rx_xput_status[args[1]], args[2], args[3], wlan_rssi_type[args[4]]); + } else { + return FALSE; + } + break; + case COEX_RX_RATE: + if (numargs >= 5 && args[4] < 3) { + dbglog_printf(timestamp, vap_id, "%s: NumUnderThreshPeers(%u), MinDirectRate(%u), LastRateSample(%u), DeltaT(%u), %s", + dbg_id_str, args[0], args[1], args[2], args[3], wal_peer_rx_rate_stats_event_sent[args[4]]); + } else { + return FALSE; + } + break; + case COEX_WLAN_INTERVAL_START: + if (numargs >= 5) { + dbglog_printf(timestamp, vap_id, "%s: WlanIntvlCnt(%u), Duration(%u), Weight(%u), BaseIdleOverride(%u), WeightMat[0](0x%x)", + dbg_id_str, args[0], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_WLAN_POSTPAUSE_INTERVAL_START: + if (numargs >= 4) { + dbglog_printf(timestamp, vap_id, "%s: WlanPostPauseIntvlCnt(%u), XputMonitorActiveNum(%u), Duration(%u), Weight(%u)", + dbg_id_str, args[0], args[1], args[2], args[3]); + } else { + return FALSE; + } + break; + case COEX_BT_INTERVAL_START: + if (numargs >= 5) { + dbglog_printf(timestamp, vap_id, "%s: BtIntvlCnt(%u), Duration(%u), Weight(%u), BaseIdleOverride(%u), WeightMat[0](0x%x), ", + dbg_id_str, args[0], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_POWER_CHANGE: + if (numargs >= 3 && args[1] < 3 && args[2] < 3) { + dbglog_printf(timestamp, vap_id, "%s: Event(0x%x) %s->%s", + dbg_id_str, args[0], wlan_power_state[args[1]], wlan_power_state[args[2]]); + } else { + return FALSE; + } + break; + case COEX_CHANNEL_CHANGE: + if (numargs >= 5 && args[3] < 2 && args[4] < 15) { + dbglog_printf(timestamp, vap_id, "%s: %uMhz->%uMhz, WlanSysState(0x%x), CurrBand(%s), PhyMode(%s)", + dbg_id_str, args[0], args[1], args[2], wlan_curr_band[args[3]], wlan_phymode[args[4]]); + } else { + return FALSE; + } + break; + case COEX_PSP_MGR_ENTER: + if (numargs >= 5 && args[0] < 23 && args[1] < 6 && args[3] < 2) { + dbglog_printf(timestamp, vap_id, "%s: %s, %s, PsPollAvg(%u), %s, CurrT(%u)", + dbg_id_str, wlan_psp_stimulus[args[0]], coex_pspoll_state[args[1]], args[2], coex_scheduler_interval[args[3]], args[4]); + } else { + return FALSE; + } + break; + //Translate following into decimal + case COEX_SINGLECHAIN_DBG_1: + case COEX_SINGLECHAIN_DBG_2: + case COEX_SINGLECHAIN_DBG_3: + case COEX_MULTICHAIN_DBG_1: + case COEX_MULTICHAIN_DBG_2: + case COEX_MULTICHAIN_DBG_3: + case BTCOEX_DBG_MCI_1: + case BTCOEX_DBG_MCI_2: + case BTCOEX_DBG_MCI_3: + case BTCOEX_DBG_MCI_4: + case BTCOEX_DBG_MCI_5: + case BTCOEX_DBG_MCI_6: + case BTCOEX_DBG_MCI_7: + case BTCOEX_DBG_MCI_8: + case BTCOEX_DBG_MCI_9: + case BTCOEX_DBG_MCI_10: + + if (numargs > 0) { + dbglog_printf_no_line_break(timestamp, vap_id, "%s: %u", + dbg_id_str, args[0]); + for (i = 1; i < numargs; i++) { + printk(", %u", args[i]); + } + printk("\n"); + } else { + return FALSE; + } + break; + case COEX_LinkID: + if (numargs >= 4) { + if (args[0]) { //Add profile + dbglog_printf(timestamp, vap_id, "%s Alloc: LocalID(%u), RemoteID(%u), MinFreeLocalID(%u)", + dbg_id_str, args[1], args[2], args[3]); + } else { //Remove profile + dbglog_printf(timestamp, vap_id, "%s Dealloc: LocalID(%u), RemoteID(%u), MinFreeLocalID(%u)", + dbg_id_str, args[1], args[2], args[3]); + } + } else { + return FALSE; + } + break; + case COEX_PSP_MGR_RESULT: + if (numargs >= 5 && args[0] < 6) { + dbglog_printf(timestamp, vap_id, "%s: %s, PsPollAvg(%u), EstimationOverrun(%u), EstimationUnderun(%u), NotReadyErr(%u)", + dbg_id_str, coex_pspoll_state[args[0]], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_TRF_SHAPE_PSP: + if (numargs >= 5 && args[0] < 7 && args[1] < 7) { + dbglog_printf(timestamp, vap_id, "%s: %s, %s, Dur(%u), BtTriggerRecvd(%u), PspWlanCritical(%u)", + dbg_id_str, coex_sched_type[args[0]], wlan_weight[args[1]], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_PSP_SPEC_POLL: + if (numargs >= 5) { + dbglog_printf(timestamp, vap_id, "%s: PsPollSpecEna(%u), Count(%u), NextTS(%u), AllowSpecPsPollTx(%u), Intvl(%u)", + dbg_id_str, args[0], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_PSP_READY_STATE: + if (numargs >= 5) { + dbglog_printf(timestamp, vap_id, "%s: T2NonWlan(%u), CoexSchedulerEndTS(%u), MoreData(%u), PSPRespExpectedTS(%u), NonWlanIdleT(%u)", + dbg_id_str, args[0], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_PSP_NONWLAN_INTERVAL: + if (numargs >= 4) { + dbglog_printf(timestamp, vap_id, "%s: NonWlanBaseIntvl(%u), NonWlanIdleT(%u), PSPSpecIntvl(%u), ApRespTimeout(%u)", + dbg_id_str, args[0], args[1], args[2], args[3]); + } else { + return FALSE; + } + break; + case COEX_PSP_ERROR: + if (numargs >= 1 && args[0] < 9) { + dbglog_printf_no_line_break(timestamp, vap_id, "%s: %s", + dbg_id_str, coex_psp_error_type[args[0]]); + for (i = 1; i < numargs; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (", %u", args[i])); + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("\n")); + } else { + return FALSE; + } + break; + case COEX_PSP_STAT_1: + if (numargs >= 5) { + dbglog_printf(timestamp, vap_id, "%s: ApResp0(%u), ApResp1(%u), ApResp2(%u), ApResp3(%u), ApResp4(%u)", + dbg_id_str, args[0], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_PSP_STAT_2: + if (numargs >= 5) { + dbglog_printf(timestamp, vap_id, "%s: DataPt(%u), Max(%u), NextApRespIndex(%u), NumOfValidDataPts(%u), PsPollAvg(%u)", + dbg_id_str, args[0], args[1], args[2], args[3], args[4]); + } else { + return FALSE; + } + break; + case COEX_PSP_RX_STATUS_STATE_1: + if (numargs >= 5) { + if (args[2]) { + dbglog_printf(timestamp, vap_id, "%s: RsExpectedTS(%u), RespActualTS(%u), Overrun, RsOverrunT(%u), RsRxDur(%u)", + dbg_id_str, args[0], args[1], args[3], args[4]); + } else { + dbglog_printf(timestamp, vap_id, "%s: RsExpectedTS(%u), RespActualTS(%u), Underrun, RsUnderrunT(%u), RsRxDur(%u)", + dbg_id_str, args[0], args[1], args[3], args[4]); + } + } else { + return FALSE; + } + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL +dbglog_beacon_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "INIT", + "ADJUST_START", + "ADJUSTING", + "ADJUST_HOLD", + }; + + static const char *events[] = { + "ADJUST_START", + "ADJUST_RESTART", + "ADJUST_STOP", + "ADJUST_PAUSE", + "ADJUST_UNPAUSE", + "ADJUST_INC_SLOP_STEP", + "ADJUST_HOLD", + "ADJUST_HOLD_TIME_OUT", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "EARLY_RX", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + case BEACON_EVENT_EARLY_RX_BMISS_STATUS: + if (numargs == 3) { + dbglog_printf(timestamp, vap_id, + "early_rx bmiss status:rcv=%d total=%d miss=%d", + args[0], args[1], args[2]); + } + break; + case BEACON_EVENT_EARLY_RX_SLEEP_SLOP: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "early_rx update sleep_slop:%d", + args[0]); + } + break; + case BEACON_EVENT_EARLY_RX_CONT_BMISS_TIMEOUT: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "early_rx cont bmiss timeout,update sleep_slop:%d", + args[0]); + } + break; + case BEACON_EVENT_EARLY_RX_PAUSE_SKIP_BCN_NUM: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "early_rx skip bcn num:%d", + args[0]); + } + break; + case BEACON_EVENT_EARLY_RX_CLK_DRIFT: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "early_rx clk drift:%d", + args[0]); + } + break; + case BEACON_EVENT_EARLY_RX_AP_DRIFT: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "early_rx ap drift:%d", + args[0]); + } + break; + case BEACON_EVENT_EARLY_RX_BCN_TYPE: + if (numargs == 1) { + dbglog_printf(timestamp, vap_id, + "early_rx bcn type:%d", + args[0]); + } + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL +dbglog_data_txrx_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + switch (dbg_id) { + case DATA_TXRX_DBGID_RX_DATA_SEQ_LEN_INFO: + dbglog_printf(timestamp, vap_id, "DATA RX seq=0x%x, len=0x%x, stored=0x%x, duperr=0x%x", + args[0], args[1], (args[2] & 0xffff0000) >> 16, args[2] & 0x0000ffff); + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL dbglog_smps_print_handler(A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "S_INACTIVE", + "S_STATIC", + "S_DYNAMIC", + "S_STALLED", + "S_INACTIVE_WAIT", + "S_STATIC_WAIT", + "S_DYNAMIC_WAIT", + }; + + static const char *events[] = { + "E_STOP", + "E_STOP_COMPL", + "E_START", + "E_STATIC", + "E_STATIC_COMPL", + "E_DYNAMIC", + "E_DYNAMIC_COMPL", + "E_STALL", + "E_RSSI_ABOVE_THRESH", + "E_RSSI_BELOW_THRESH", + "E_FORCED_NONE", + }; + switch(dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "STA_SMPS SM", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + case STA_SMPS_DBGID_CREATE_PDEV_INSTANCE: + dbglog_printf(timestamp, vap_id, "STA_SMPS Create PDEV ctx %#x", + args[0]); + break; + case STA_SMPS_DBGID_CREATE_VIRTUAL_CHAN_INSTANCE: + dbglog_printf(timestamp, vap_id, "STA_SMPS Create Virtual Chan ctx %#x", + args[0]); + break; + case STA_SMPS_DBGID_DELETE_VIRTUAL_CHAN_INSTANCE: + dbglog_printf(timestamp, vap_id, "STA_SMPS Delete Virtual Chan ctx %#x", + args[0]); + break; + case STA_SMPS_DBGID_CREATE_STA_INSTANCE: + dbglog_printf(timestamp, vap_id, "STA_SMPS Create STA ctx %#x", + args[0]); + break; + case STA_SMPS_DBGID_DELETE_STA_INSTANCE: + dbglog_printf(timestamp, vap_id, "STA_SMPS Delete STA ctx %#x", + args[0]); + break; + case STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_START: + break; + case STA_SMPS_DBGID_VIRTUAL_CHAN_SMPS_STOP: + break; + case STA_SMPS_DBGID_SEND_SMPS_ACTION_FRAME: + dbglog_printf(timestamp, vap_id, "STA_SMPS STA %#x Signal SMPS mode as %s; cb_flags %#x", + args[0], + (args[1] == 0 ? "DISABLED": + (args[1] == 0x1 ? "STATIC" : + (args[1] == 0x3 ? "DYNAMIC" : "UNKNOWN"))), + args[2]); + break; + case STA_SMPS_DBGID_DTIM_EBT_EVENT_CHMASK_UPDATE: + dbglog_printf(timestamp, vap_id, "STA_SMPS_DBGID_DTIM_EBT_EVENT_CHMASK_UPDATE"); + break; + case STA_SMPS_DBGID_DTIM_CHMASK_UPDATE: + dbglog_printf(timestamp, vap_id, "STA_SMPS_DBGID_DTIM_CHMASK_UPDATE " + "tx_mask %#x rx_mask %#x arb_dtim_mask %#x", + args[0], args[1], args[2]); + break; + case STA_SMPS_DBGID_DTIM_BEACON_EVENT_CHMASK_UPDATE: + dbglog_printf(timestamp, vap_id, "STA_SMPS_DBGID_DTIM_BEACON_EVENT_CHMASK_UPDATE"); + break; + case STA_SMPS_DBGID_DTIM_POWER_STATE_CHANGE: + dbglog_printf(timestamp, vap_id, "STA_SMPS_DBGID_DTIM_POWER_STATE_CHANGE cur_pwr_state %s new_pwr_state %s", + (args[0] == 0x1 ? "SLEEP": + (args[0] == 0x2 ? "AWAKE": + (args[0] == 0x3 ? "FULL_SLEEP" : "UNKNOWN"))), + (args[1] == 0x1 ? "SLEEP": + (args[1] == 0x2 ? "AWAKE": + (args[1] == 0x3 ? "FULL_SLEEP" : "UNKNOWN")))); + break; + case STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_SLEEP: + dbglog_printf(timestamp, vap_id, "STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_SLEEP " + "tx_mask %#x rx_mask %#x orig_rx %#x dtim_rx %#x", + args[0], args[1], args[2], args[3]); + break; + case STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_AWAKE: + dbglog_printf(timestamp, vap_id, "STA_SMPS_DBGID_DTIM_CHMASK_UPDATE_AWAKE " + "tx_mask %#x rx_mask %#x orig_rx %#x", + args[0], args[1], args[2]); + break; + default: + dbglog_printf( + timestamp, + vap_id, + "STA_SMPS: UNKNOWN DBGID!"); + return FALSE; + } + + return TRUE; +} + + +A_BOOL +dbglog_p2p_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "ACTIVE", + "DOZE", + "TX_BCN", + "CTWIN", + "OPPPS", + }; + + static const char *events[] = { + "ONESHOT_NOA", + "CTWINDOW", + "PERIODIC_NOA", + "IDLE", + "NOA_CHANGED", + "TBTT", + "TX_BCN_CMP", + "OPPPS_OK", + "OPPPS_CHANGED", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "P2P GO PS", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + default: + return FALSE; + } + + return TRUE; +} + +A_BOOL +dbglog_pcielp_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + static const char *states[] = { + "STOP", + "TX", + "RX", + "SLEEP", + "SUSPEND", + }; + + static const char *events[] = { + "VDEV_UP", + "ALL_VDEV_DOWN", + "AWAKE", + "SLEEP", + "TX_ACTIVITY", + "TX_INACTIVITY", + "TX_AC_CHANGE", + "SUSPEND", + "RESUME", + }; + + switch (dbg_id) { + case DBGLOG_DBGID_SM_FRAMEWORK_PROXY_DBGLOG_MSG: + dbglog_sm_print(timestamp, vap_id, numargs, args, "PCIELP", + states, ARRAY_LENGTH(states), events, ARRAY_LENGTH(events)); + break; + default: + return FALSE; + } + + return TRUE; +} + + +#ifdef WLAN_OPEN_SOURCE +static int dbglog_block_open(struct inode *inode, struct file *file) +{ + struct fwdebug *fwlog = inode->i_private; + + if (fwlog->fwlog_open) + return -EBUSY; + + fwlog->fwlog_open = TRUE; + + file->private_data = inode->i_private; + return 0; +} + +static int dbglog_block_release(struct inode *inode, struct file *file) +{ + struct fwdebug *fwlog = inode->i_private; + + fwlog->fwlog_open = FALSE; + + return 0; +} + +static ssize_t dbglog_block_read(struct file *file, + char __user *user_buf, + size_t count, + loff_t *ppos) +{ + struct fwdebug *fwlog = file->private_data; + struct sk_buff *skb; + ssize_t ret_cnt; + size_t len = 0, not_copied; + char *buf; + int ret; + + buf = vmalloc(count); + if (!buf) + return -ENOMEM; + + spin_lock_bh(&fwlog->fwlog_queue.lock); + + if (skb_queue_len(&fwlog->fwlog_queue) == 0) { + /* we must init under queue lock */ + init_completion(&fwlog->fwlog_completion); + + spin_unlock_bh(&fwlog->fwlog_queue.lock); + + ret = wait_for_completion_interruptible( + &fwlog->fwlog_completion); + if (ret == -ERESTARTSYS) { + vfree(buf); + return ret; + } + + spin_lock_bh(&fwlog->fwlog_queue.lock); + } + + while ((skb = __skb_dequeue(&fwlog->fwlog_queue))) { + if (skb->len > count - len) { + /* not enough space, put skb back and leave */ + __skb_queue_head(&fwlog->fwlog_queue, skb); + break; + } + + memcpy(buf + len, skb->data, skb->len); + len += skb->len; + + kfree_skb(skb); + } + + spin_unlock_bh(&fwlog->fwlog_queue.lock); + + /* FIXME: what to do if len == 0? */ + not_copied = copy_to_user(user_buf, buf, len); + if (not_copied != 0) { + ret_cnt = -EFAULT; + goto out; + } + + *ppos = *ppos + len; + + ret_cnt = len; + +out: + vfree(buf); + + return ret_cnt; +} + +static const struct file_operations fops_dbglog_block = { + .open = dbglog_block_open, + .release = dbglog_block_release, + .read = dbglog_block_read, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +int dbglog_debugfs_init(wmi_unified_t wmi_handle) +{ + + wmi_handle->debugfs_phy = debugfs_create_dir(CLD_DEBUGFS_DIR, NULL); + if (!wmi_handle->debugfs_phy) + return -ENOMEM; + + debugfs_create_file(DEBUGFS_BLOCK_NAME, S_IRUSR, wmi_handle->debugfs_phy, &wmi_handle->dbglog, + &fops_dbglog_block); + + return TRUE; +} +int dbglog_debugfs_remove(wmi_unified_t wmi_handle) +{ + debugfs_remove_recursive(wmi_handle->debugfs_phy); + return TRUE; +} +#endif /* WLAN_OPEN_SOURCE */ + +static void +cnss_diag_event_report(A_UINT16 event_Id, A_UINT16 length, void *pPayload) +{ + A_UINT8 *pBuf, *pBuf1; + event_report_t *pEvent_report; + A_UINT16 total_len; + total_len = sizeof(event_report_t) + length; + pBuf = vos_mem_malloc(total_len); + if (!pBuf){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: vos_mem_malloc failed \n", __func__)); + return; + } + pBuf1 = pBuf; + pEvent_report = (event_report_t*)pBuf; + pEvent_report->diag_type = DIAG_TYPE_EVENTS; + pEvent_report->event_id = event_Id; + pEvent_report->length = length; + pBuf += sizeof(event_report_t); + memcpy(pBuf, pPayload, length); + send_diag_netlink_data((A_UINT8 *) pBuf1, total_len, DIAG_TYPE_HOST_MSG); + vos_mem_free((v_VOID_t*)pBuf1); + return; + +} + +static void cnss_diag_send_driver_loaded(void) +{ + if (appstarted) { + vos_event_wlan_bringup_status_payload_type wlan_bringup_status; + /* Send Driver up command */ + strlcpy(&wlan_bringup_status.driverVersion[0], QWLAN_VERSIONSTR, + sizeof(wlan_bringup_status.driverVersion)); + wlan_bringup_status.wlanStatus = DIAG_WLAN_DRIVER_LOADED; + cnss_diag_event_report(EVENT_WLAN_BRINGUP_STATUS, + sizeof(wlan_bringup_status), &wlan_bringup_status); + senddriverstatus = FALSE; + } + else + senddriverstatus = TRUE; +} + +static void cnss_diag_send_driver_unloaded(void) +{ + vos_event_wlan_bringup_status_payload_type wlan_bringup_status; + /* Send Driver down command */ + memset(&wlan_bringup_status, 0, + sizeof(vos_event_wlan_bringup_status_payload_type)); + wlan_bringup_status.wlanStatus = DIAG_WLAN_DRIVER_UNLOADED; + cnss_diag_event_report(EVENT_WLAN_BRINGUP_STATUS, + sizeof(wlan_bringup_status), &wlan_bringup_status); +} +/**--------------------------------------------------------------------------- + \brief cnss_diag_msg_callback() - Call back invoked by netlink service + + This function gets invoked by netlink service when a message is recevied + from the cnss-diag application in user-space. + + \param - + - skb - skb with netlink message + + \return - 0 for success, non zero for failure +--------------------------------------------------------------------------*/ +int cnss_diag_msg_callback(struct sk_buff *skb) +{ + struct nlmsghdr *nlh; + struct dbglog_slot *slot; + A_UINT8 *msg; + + nlh = (struct nlmsghdr *)skb->data; + if (!nlh) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Netlink header null \n", __func__)); + return -1; + } + + msg = NLMSG_DATA(nlh); + + /* This check added for backward compatability */ + if (!memcmp(msg, "Hello", 5)) { + appstarted = TRUE; + cnss_diag_pid = nlh->nlmsg_pid; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: registered pid %d \n", __func__, cnss_diag_pid)); + if (senddriverstatus) + cnss_diag_send_driver_loaded(); + return 0; + } + else + slot = (struct dbglog_slot *)msg; + switch (slot->diag_type) { + case DIAG_TYPE_CRASH_INJECT: + if (slot->length == 2) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s : DIAG_TYPE_CRASH_INJECT: %d %d\n", __func__, + slot->payload[0], slot->payload[1])); + if (!tgt_assert_enable) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: tgt Assert Disabled\n", __func__)); + return 0; + } + process_wma_set_command_twoargs(0, + (int)GEN_PARAM_CRASH_INJECT, + slot->payload[0], + slot->payload[1], GEN_CMD); + } + else + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("crash_inject cmd error\n")); + break; + default: + break; + } + return 0; + +} +/**--------------------------------------------------------------------------- + \brief cnss_diag_notify_wlan_close() - Notify APP driver closed + + This function notifies the user cnss-diag app that wlan driver is closed. + + \param - + - None + + \return - 0 for success, non zero for failure +--------------------------------------------------------------------------*/ +int cnss_diag_notify_wlan_close() +{ + /* Send nl msg about the wlan close */ + if (0 != cnss_diag_pid) + { + cnss_diag_send_driver_unloaded(); + cnss_diag_pid = 0; + } + return 0; + +} +/**--------------------------------------------------------------------------- + \brief cnss_diag_activate_service() - Activate cnss_diag message handler + + This function registers a handler to receive netlink message from + an cnss-diag application process. + + \param - + - None + + \return - 0 for success, non zero for failure +--------------------------------------------------------------------------*/ +int cnss_diag_activate_service() +{ + int ret = 0; + + /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */ + ret = nl_srv_register(WLAN_NL_MSG_CNSS_DIAG, cnss_diag_msg_callback); + if (ret == -EINVAL) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("CNSS-DIAG Registeration failed \n")); + return ret; + } + kd_nl_init = TRUE; + return 0; +} + +A_BOOL +dbglog_wow_print_handler( + A_UINT32 mod_id, + A_UINT16 vap_id, + A_UINT32 dbg_id, + A_UINT32 timestamp, + A_UINT16 numargs, + A_UINT32 *args) +{ + + switch (dbg_id) { + case WOW_NS_OFLD_ENABLE: + if (4 == numargs) { + dbglog_printf(timestamp, vap_id, + "Enable NS offload, for sender %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + *(A_UINT8*)&args[0], *((A_UINT8*)&args[0]+1), *((A_UINT8*)&args[0]+2), *((A_UINT8*)&args[0]+3), + *(A_UINT8*)&args[1], *((A_UINT8*)&args[1]+1), *((A_UINT8*)&args[1]+2), *((A_UINT8*)&args[1]+3), + *(A_UINT8*)&args[2], *((A_UINT8*)&args[2]+1), *((A_UINT8*)&args[2]+2), *((A_UINT8*)&args[2]+3), + *(A_UINT8*)&args[3], *((A_UINT8*)&args[3]+1), *((A_UINT8*)&args[3]+2), *((A_UINT8*)&args[3]+3)); + } else { + return FALSE; + } + break; + case WOW_ARP_OFLD_ENABLE: + if (1 == numargs) { + dbglog_printf(timestamp, vap_id, + "Enable ARP offload, for sender %d.%d.%d.%d", + *(A_UINT8*)args, *((A_UINT8*)args+1), *((A_UINT8*)args+2), *((A_UINT8*)args+3)); + } else { + return FALSE; + } + break; + case WOW_NS_ARP_OFLD_DISABLE: + if (0 == numargs) { + dbglog_printf(timestamp, vap_id, "disable NS/ARP offload"); + } else { + return FALSE; + } + break; + case WOW_NS_RECEIVED: + if (4 == numargs) { + dbglog_printf(timestamp, vap_id, + "NS requested from %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + *(A_UINT8*)&args[0], *((A_UINT8*)&args[0]+1), *((A_UINT8*)&args[0]+2), *((A_UINT8*)&args[0]+3), + *(A_UINT8*)&args[1], *((A_UINT8*)&args[1]+1), *((A_UINT8*)&args[1]+2), *((A_UINT8*)&args[1]+3), + *(A_UINT8*)&args[2], *((A_UINT8*)&args[2]+1), *((A_UINT8*)&args[2]+2), *((A_UINT8*)&args[2]+3), + *(A_UINT8*)&args[3], *((A_UINT8*)&args[3]+1), *((A_UINT8*)&args[3]+2), *((A_UINT8*)&args[3]+3)); + } else { + return FALSE; + } + break; + case WOW_NS_REPLIED: + if (4 == numargs) { + dbglog_printf(timestamp, vap_id, + "NS replied to %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + *(A_UINT8*)&args[0], *((A_UINT8*)&args[0]+1), *((A_UINT8*)&args[0]+2), *((A_UINT8*)&args[0]+3), + *(A_UINT8*)&args[1], *((A_UINT8*)&args[1]+1), *((A_UINT8*)&args[1]+2), *((A_UINT8*)&args[1]+3), + *(A_UINT8*)&args[2], *((A_UINT8*)&args[2]+1), *((A_UINT8*)&args[2]+2), *((A_UINT8*)&args[2]+3), + *(A_UINT8*)&args[3], *((A_UINT8*)&args[3]+1), *((A_UINT8*)&args[3]+2), *((A_UINT8*)&args[3]+3)); + } else { + return FALSE; + } + break; + case WOW_ARP_RECEIVED: + if (1 == numargs) { + dbglog_printf(timestamp, vap_id, + "ARP requested from %d.%d.%d.%d", + *(A_UINT8*)args, *((A_UINT8*)args+1), *((A_UINT8*)args+2), *((A_UINT8*)args+3)); + } else { + return FALSE; + } + break; + break; + case WOW_ARP_REPLIED: + if (1 == numargs) { + dbglog_printf(timestamp, vap_id, + "ARP replied to %d.%d.%d.%d", + *(A_UINT8*)args, *((A_UINT8*)args+1), *((A_UINT8*)args+2), *((A_UINT8*)args+3)); + } else { + return FALSE; + } + break; + default: + return FALSE; + } + + return TRUE; +} + +int dbglog_parser_type_init(wmi_unified_t wmi_handle, int type) +{ + if(type >= DBGLOG_PROCESS_MAX){ + return A_ERROR; + } + + dbglog_process_type = type; + gprint_limiter = FALSE; + + return A_OK; +} + +int +dbglog_init(wmi_unified_t wmi_handle) +{ + int res = 0; + OS_MEMSET(mod_print, 0, sizeof(mod_print)); + + dbglog_reg_modprint(WLAN_MODULE_STA_PWRSAVE, dbglog_sta_powersave_print_handler); + dbglog_reg_modprint(WLAN_MODULE_AP_PWRSAVE, dbglog_ap_powersave_print_handler); + dbglog_reg_modprint(WLAN_MODULE_WAL, dbglog_wal_print_handler); + dbglog_reg_modprint(WLAN_MODULE_SCAN, dbglog_scan_print_handler); + dbglog_reg_modprint(WLAN_MODULE_RATECTRL, dbglog_ratectrl_print_handler); + dbglog_reg_modprint(WLAN_MODULE_ANI, dbglog_ani_print_handler); + dbglog_reg_modprint(WLAN_MODULE_COEX, dbglog_coex_print_handler); + dbglog_reg_modprint(WLAN_MODULE_BEACON,dbglog_beacon_print_handler); + dbglog_reg_modprint(WLAN_MODULE_WOW, dbglog_wow_print_handler); + dbglog_reg_modprint(WLAN_MODULE_DATA_TXRX,dbglog_data_txrx_print_handler); + dbglog_reg_modprint(WLAN_MODULE_STA_SMPS, dbglog_smps_print_handler); + dbglog_reg_modprint(WLAN_MODULE_P2P, dbglog_p2p_print_handler); + dbglog_reg_modprint(WLAN_MODULE_PCIELP, dbglog_pcielp_print_handler); + dbglog_reg_modprint(WLAN_MODULE_IBSS_PWRSAVE, + dbglog_ibss_powersave_print_handler); + tgt_assert_enable = wmi_handle->tgt_force_assert_enable; + /* Register handler for F3 or debug messages */ + res = wmi_unified_register_event_handler(wmi_handle, WMI_DEBUG_MESG_EVENTID, + dbglog_parse_debug_logs); + if (res != 0) + return res; + + /* Register handler for FW diag events */ + res = wmi_unified_register_event_handler(wmi_handle, + WMI_DIAG_DATA_CONTAINER_EVENTID, + fw_diag_data_event_handler); + if (res != 0) + return res; + + /* Register handler for new FW diag Event, LOG, MSG combined */ + res = wmi_unified_register_event_handler(wmi_handle, WMI_DIAG_EVENTID, + diag_fw_handler); + if (res != 0) + return res; + + cnss_diag_send_driver_loaded(); +#ifdef WLAN_OPEN_SOURCE + /* Initialize the fw debug log queue */ + skb_queue_head_init(&wmi_handle->dbglog.fwlog_queue); + init_completion(&wmi_handle->dbglog.fwlog_completion); + + /* Initialize debugfs */ + dbglog_debugfs_init(wmi_handle); +#endif /* WLAN_OPEN_SOURCE */ + + return res; +} + +int +dbglog_deinit(wmi_unified_t wmi_handle) +{ + int res = 0; + +#ifdef WLAN_OPEN_SOURCE + /* DeInitialize the fw debug log queue */ + skb_queue_purge(&wmi_handle->dbglog.fwlog_queue); + complete(&wmi_handle->dbglog.fwlog_completion); + + /* Deinitialize the debugfs */ + dbglog_debugfs_remove(wmi_handle); +#endif /* WLAN_OPEN_SOURCE */ + + tgt_assert_enable = 0; + res = wmi_unified_unregister_event_handler(wmi_handle, WMI_DEBUG_MESG_EVENTID); + if(res != 0) + return res; + + kd_nl_init = FALSE; + return res; +} diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac.h b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac.h new file mode 100644 index 000000000000..88f5bdfc63c7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2012-2013, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _PKTLOG_AC_H_ +#define _PKTLOG_AC_H_ +#ifndef REMOVE_PKT_LOG + +#include "ol_if_athvar.h" +#include +#include +#include "osdep.h" +#include +#include +#include + +#define NO_REG_FUNCS 4 + +/* Locking interface for pktlog */ +#define PKTLOG_LOCK_INIT(_pl_info) spin_lock_init(&(_pl_info)->log_lock) +#define PKTLOG_LOCK_DESTROY(_pl_info) +#define PKTLOG_LOCK(_pl_info) spin_lock(&(_pl_info)->log_lock) +#define PKTLOG_UNLOCK(_pl_info) spin_unlock(&(_pl_info)->log_lock) + +#define PKTLOG_MODE_SYSTEM 1 +#define PKTLOG_MODE_ADAPTER 2 + +/* + * The proc entry starts with magic number and version field which will be + * used by post processing scripts. These fields are not needed by applications + * that do not use these scripts. This is skipped using the offset value. + */ +#define PKTLOG_READ_OFFSET 8 + +/* Opaque softc */ +struct ol_ath_generic_softc_t; +typedef struct ol_ath_generic_softc_t* ol_ath_generic_softc_handle; +extern void pktlog_disable_adapter_logging(struct ol_softc *scn); +extern int pktlog_alloc_buf(struct ol_softc *scn); +extern void pktlog_release_buf(struct ol_softc *scn); + +ssize_t pktlog_read_proc_entry(char *buf, size_t nbytes, loff_t *ppos, + struct ath_pktlog_info *pl_info, + bool *read_complete); +int pktlog_send_per_pkt_stats_to_user(void); + +struct ol_pl_arch_dep_funcs { + void (*pktlog_init) (struct ol_softc *scn); + int (*pktlog_enable) (struct ol_softc *scn, + int32_t log_state); + int (*pktlog_setsize) (struct ol_softc *scn, + int32_t log_state); + int (*pktlog_disable) (struct ol_softc *scn); +}; + +struct ol_pl_os_dep_funcs { + int (*pktlog_attach) (struct ol_softc *scn); + void (*pktlog_detach) (struct ol_softc *scn); +}; + +struct ath_pktlog_wmi_params { + WMI_PKTLOG_EVENT pktlog_event; + WMI_CMD_ID cmd_id; +}; + +extern struct ol_pl_arch_dep_funcs ol_pl_funcs; +extern struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs; + +/* Pktlog handler to save the state of the pktlogs */ +struct ol_pktlog_dev_t { + struct ol_pl_arch_dep_funcs *pl_funcs; + struct ath_pktlog_info *pl_info; + ol_ath_generic_softc_handle scn; + char *name; + bool tgt_pktlog_enabled; + osdev_t sc_osdev; +}; + +#define PKTLOG_SYSCTL_SIZE 14 + +/* + * Linux specific pktlog state information + */ +struct ath_pktlog_info_lnx { + struct ath_pktlog_info info; + struct ctl_table sysctls[PKTLOG_SYSCTL_SIZE]; + struct proc_dir_entry *proc_entry; + struct ctl_table_header *sysctl_header; +}; + +#define PL_INFO_LNX(_pl_info) ((struct ath_pktlog_info_lnx *)(_pl_info)) + +extern struct ol_pktlog_dev_t ol_pl_dev; + +/* + * WDI related data and functions + * Callback function to the WDI events + */ +void pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data); + +#define ol_pktlog_attach(_scn) \ + do { \ + if (g_ol_pl_os_dep_funcs) { \ + g_ol_pl_os_dep_funcs->pktlog_attach(_scn); \ + } \ + } while (0) + +#define ol_pktlog_detach(_scn) \ + do { \ + if (g_ol_pl_os_dep_funcs) { \ + g_ol_pl_os_dep_funcs->pktlog_detach(_scn); \ + } \ + } while (0) + +void pktlog_init(struct ol_softc *scn); +int pktlog_enable(struct ol_softc *scn, int32_t log_state); +int pktlog_setsize(struct ol_softc *scn, int32_t log_state); +int pktlog_disable(struct ol_softc *scn); +int pktlogmod_init(void *context); +void pktlogmod_exit(void *context); +#else /* REMOVE_PKT_LOG */ +#define ol_pktlog_attach(_scn) ({ (void)_scn; }) +#define ol_pktlog_detach(_scn) ({ (void)_scn; }) +static inline void pktlog_init(struct ol_softc *scn) +{ + return; +} +static int pktlog_enable(struct ol_softc *scn, int32_t log_state) +{ + return 0; +} +static int pktlog_setsize(struct ol_softc *scn, int32_t log_state) +{ + return 0; +} +static int pktlog_disable(struct ol_softc *scn) +{ + return 0; +} +#endif /* REMOVE_PKT_LOG */ +#endif /* _PKTLOG_AC_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_api.h b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_api.h new file mode 100644 index 000000000000..a30aaab2b07b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_api.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * The file is used to define structures that are shared between + * kernel space and user space pktlog application. + */ + +#ifndef _PKTLOG_AC_API_ +#define _PKTLOG_AC_API_ +#ifndef REMOVE_PKT_LOG + +/** + * @typedef ol_pktlog_dev_handle + * @brief opaque handle for pktlog device object + */ +struct ol_pktlog_dev_t; +typedef struct ol_pktlog_dev_t* ol_pktlog_dev_handle; + +/** + * @typedef ol_softc_handle + * @brief opaque handle for ol_softc + */ +struct ol_softc; +typedef struct ol_softc* ol_softc_handle; + +/** + * @typedef net_device_handle + * @brief opaque handle linux phy device object + */ +struct net_device; +typedef struct net_device* net_device_handle; + +void ol_pl_set_name(ol_softc_handle scn, net_device_handle dev); + +void ol_pl_sethandle(ol_pktlog_dev_handle *pl_handle, + ol_softc_handle scn); + +/* Packet log state information */ +#ifndef _PKTLOG_INFO +#define _PKTLOG_INFO +struct ath_pktlog_info { + struct ath_pktlog_buf *buf; + u_int32_t log_state; + u_int32_t saved_state; + u_int32_t options; + + /* Size of buffer in bytes */ + int32_t buf_size; + spinlock_t log_lock; + + /* Threshold of TCP SACK packets for triggered stop */ + int sack_thr; + + /* # of tail packets to log after triggered stop */ + int tail_length; + + /* throuput threshold in bytes for triggered stop */ + u_int32_t thruput_thresh; + + /* (aggregated or single) packet size in bytes */ + u_int32_t pktlen; + + /* a temporary variable for counting TX throughput only */ + /* PER threshold for triggered stop, 10 for 10%, range [1, 99] */ + u_int32_t per_thresh; + + /* Phyerr threshold for triggered stop */ + u_int32_t phyerr_thresh; + + /* time period for counting trigger parameters, in milisecond */ + u_int32_t trigger_interval; + u_int32_t start_time_thruput; + u_int32_t start_time_per; +}; +#endif /* _PKTLOG_INFO */ +#else /* REMOVE_PKT_LOG */ +typedef void* ol_pktlog_dev_handle; +#define ol_pl_sethandle(pl_handle, scn) \ + do { \ + (void)pl_handle; \ + (void)scn; \ + } while (0) + +#define ol_pl_set_name(scn, dev) \ + do { \ + (void)scn; \ + (void)dev; \ + } while (0) + +#endif /* REMOVE_PKT_LOG */ +#endif /* _PKTLOG_AC_API_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_i.h b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_i.h new file mode 100644 index 000000000000..99ee7cdf8a89 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/include/pktlog_ac_i.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _PKTLOG_AC_I_ +#define _PKTLOG_AC_I_ +#ifndef REMOVE_PKT_LOG + +#include +#include + +#define PKTLOG_DEFAULT_BUFSIZE (1024 * 1024) +#define PKTLOG_DEFAULT_SACK_THR 3 +#define PKTLOG_DEFAULT_TAIL_LENGTH 100 +#define PKTLOG_DEFAULT_THRUPUT_THRESH (64 * 1024) +#define PKTLOG_DEFAULT_PER_THRESH 30 +#define PKTLOG_DEFAULT_PHYERR_THRESH 300 +#define PKTLOG_DEFAULT_TRIGGER_INTERVAL 500 +struct ath_pktlog_arg { + struct ath_pktlog_info *pl_info; + u_int32_t flags; + u_int16_t missed_cnt; + u_int16_t log_type; + size_t log_size; + u_int16_t timestamp; + char *buf; +}; + +void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg); +char *pktlog_getbuf(struct ol_pktlog_dev_t *pl_dev, + struct ath_pktlog_info *pl_info, + size_t log_size, + struct ath_pktlog_hdr *pl_hdr); + +A_STATUS process_tx_info(struct ol_txrx_pdev_t *pdev, void *data); +A_STATUS process_rx_info(void *pdev, void *data); +A_STATUS process_rx_info_remote(void *pdev, adf_nbuf_t amsdu); +A_STATUS process_rate_find(void *pdev, void *data); +A_STATUS process_rate_update(void *pdev, void *data); + +#endif /* REMOVE_PKT_LOG */ +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c new file mode 100644 index 000000000000..24404089566c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/linux_ac.c @@ -0,0 +1,1194 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef REMOVE_PKT_LOG +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif +#ifndef __KERNEL__ +#define __KERNEL__ +#endif +/* + * Linux specific implementation of Pktlogs for 802.11ac + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "i_vos_diag_core_log.h" +#include "vos_diag_core_log.h" +#include "aniGlobal.h" + +#define PKTLOG_TAG "ATH_PKTLOG" +#define PKTLOG_DEVNAME_SIZE 32 +#define MAX_WLANDEV 1 + +#define PKTLOG_PROC_DIR "ath_pktlog" + +/* Permissions for creating proc entries */ +#define PKTLOG_PROC_PERM 0444 +#define PKTLOG_PROCSYS_DIR_PERM 0555 +#define PKTLOG_PROCSYS_PERM 0644 + +#ifndef __MOD_INC_USE_COUNT +#define PKTLOG_MOD_INC_USE_COUNT \ + if (!try_module_get(THIS_MODULE)) { \ + printk(KERN_WARNING "try_module_get failed\n"); \ + } + +#define PKTLOG_MOD_DEC_USE_COUNT module_put(THIS_MODULE) +#else +#define PKTLOG_MOD_INC_USE_COUNT MOD_INC_USE_COUNT +#define PKTLOG_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT +#endif + +static struct ath_pktlog_info *g_pktlog_info; + +static struct proc_dir_entry *g_pktlog_pde; + +static int pktlog_attach(struct ol_softc *sc); +static void pktlog_detach(struct ol_softc *sc); +static int pktlog_open(struct inode *i, struct file *f); +static int pktlog_release(struct inode *i, struct file *f); +static int pktlog_mmap(struct file *f, struct vm_area_struct *vma); +static ssize_t pktlog_read(struct file *file, char *buf, size_t nbytes, + loff_t * ppos); + +static struct file_operations pktlog_fops = { + open:pktlog_open, + release:pktlog_release, + mmap:pktlog_mmap, + read:pktlog_read, +}; + +/* + * Linux implementation of helper functions + */ + +static struct ol_pktlog_dev_t *get_pl_handle(struct ol_softc *scn) +{ + if (!scn || !scn->pdev_txrx_handle) + return NULL; + return scn->pdev_txrx_handle->pl_dev; +} + +void ol_pl_set_name(ol_softc_handle scn, net_device_handle dev) +{ + if (scn && scn->pdev_txrx_handle->pl_dev && dev) + scn->pdev_txrx_handle->pl_dev->name = dev->name; +} + +void pktlog_disable_adapter_logging(struct ol_softc *scn) +{ + struct ol_pktlog_dev_t *pl_dev = get_pl_handle(scn); + if (pl_dev) pl_dev->pl_info->log_state = 0; +} + +int pktlog_alloc_buf(struct ol_softc *scn) +{ + u_int32_t page_cnt; + unsigned long vaddr; + struct page *vpg; + struct ath_pktlog_info *pl_info; + + if (!scn || !scn->pdev_txrx_handle->pl_dev) { + printk(PKTLOG_TAG + "%s: Unable to allocate buffer " + "scn or scn->pdev_txrx_handle->pl_dev is null\n", + __func__); + return -EINVAL; + } + + pl_info = scn->pdev_txrx_handle->pl_dev->pl_info; + + page_cnt = (sizeof(*(pl_info->buf)) + pl_info->buf_size) / PAGE_SIZE; + + if ((pl_info->buf = vmalloc((page_cnt + 2) * PAGE_SIZE)) == NULL) { + printk(PKTLOG_TAG + "%s: Unable to allocate buffer " + "(%d pages)\n", __func__, page_cnt); + return -ENOMEM; + } + + pl_info->buf = (struct ath_pktlog_buf *) + (((unsigned long) (pl_info->buf) + PAGE_SIZE - 1) + & PAGE_MASK); + + for (vaddr = (unsigned long) (pl_info->buf); + vaddr < ((unsigned long) (pl_info->buf) + (page_cnt * PAGE_SIZE)); + vaddr += PAGE_SIZE) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)) + vpg = vmalloc_to_page((const void *) vaddr); +#else + vpg = virt_to_page(pktlog_virt_to_logical((void *) vaddr)); +#endif + SetPageReserved(vpg); + } + + return 0; +} + +void pktlog_release_buf(struct ol_softc *scn) +{ + unsigned long page_cnt; + unsigned long vaddr; + struct page *vpg; + struct ath_pktlog_info *pl_info; + + if (!scn || !scn->pdev_txrx_handle->pl_dev) { + printk(PKTLOG_TAG + "%s: Unable to allocate buffer" + "scn or scn->pdev_txrx_handle->pl_dev is null\n", + __func__); + return; + } + + pl_info = scn->pdev_txrx_handle->pl_dev->pl_info; + + page_cnt = ((sizeof(*(pl_info->buf)) + pl_info->buf_size) / + PAGE_SIZE) + 1; + + for (vaddr = (unsigned long) (pl_info->buf); + vaddr < (unsigned long) (pl_info->buf) + (page_cnt * PAGE_SIZE); + vaddr += PAGE_SIZE) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)) + vpg = vmalloc_to_page((const void *) vaddr); +#else + vpg = virt_to_page(pktlog_virt_to_logical((void *) vaddr)); +#endif + ClearPageReserved(vpg); + } + + vfree(pl_info->buf); + pl_info->buf = NULL; +} + +void +pktlog_cleanup(struct ath_pktlog_info *pl_info) +{ + pl_info->log_state = 0; + PKTLOG_LOCK_DESTROY(pl_info); +} + +/* sysctl procfs handler to enable pktlog */ +static int +ATH_SYSCTL_DECL(ath_sysctl_pktlog_enable, ctl, write, filp, buffer, lenp, + ppos) +{ + int ret, enable; + ol_ath_generic_softc_handle scn; + struct ol_pktlog_dev_t *pl_dev; + + scn = (ol_ath_generic_softc_handle) ctl->extra1; + + if (!scn) { + printk("%s: Invalid scn context\n", __func__); + ASSERT(0); + return -EINVAL; + } + + pl_dev = get_pl_handle((struct ol_softc *)scn); + + if (!pl_dev) { + printk("%s: Invalid pktlog context\n", __func__); + ASSERT(0); + return -ENODEV; + } + + ctl->data = &enable; + ctl->maxlen = sizeof(enable); + + if (write) { + ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, + lenp, ppos); + if (ret == 0) + ret = pl_dev->pl_funcs->pktlog_enable( + (struct ol_softc *)scn, + enable); + else + printk(PKTLOG_TAG "%s:proc_dointvec failed\n", + __func__); + } else { + ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, + lenp, ppos); + if (ret) + printk(PKTLOG_TAG "%s:proc_dointvec failed\n", + __func__); + } + + ctl->data = NULL; + ctl->maxlen = 0; + + return ret; +} + +static int get_pktlog_bufsize(struct ol_pktlog_dev_t *pl_dev) +{ + return pl_dev->pl_info->buf_size; +} + +/* sysctl procfs handler to set/get pktlog size */ +static int +ATH_SYSCTL_DECL(ath_sysctl_pktlog_size, ctl, write, filp, buffer, lenp, + ppos) +{ + int ret, size; + ol_ath_generic_softc_handle scn; + struct ol_pktlog_dev_t *pl_dev; + + scn = (ol_ath_generic_softc_handle) ctl->extra1; + + if (!scn) { + printk("%s: Invalid scn context\n", __func__); + ASSERT(0); + return -EINVAL; + } + + pl_dev = get_pl_handle((struct ol_softc *)scn); + + if (!pl_dev) { + printk("%s: Invalid pktlog handle\n", __func__); + ASSERT(0); + return -ENODEV; + } + + ctl->data = &size; + ctl->maxlen = sizeof(size); + + if (write) { + ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, + lenp, ppos); + if (ret == 0) + ret = pl_dev->pl_funcs->pktlog_setsize( + (struct ol_softc *)scn, + size); + } else { + size = get_pktlog_bufsize(pl_dev); + ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, + lenp, ppos); + } + + ctl->data = NULL; + ctl->maxlen = 0; + + return ret; +} + +/* Register sysctl table */ +static int pktlog_sysctl_register(struct ol_softc *scn) +{ + struct ol_pktlog_dev_t *pl_dev = get_pl_handle(scn); + struct ath_pktlog_info_lnx *pl_info_lnx; + char *proc_name; + + if (pl_dev) { + pl_info_lnx = PL_INFO_LNX(pl_dev->pl_info); + proc_name = pl_dev->name; + } else { + pl_info_lnx = PL_INFO_LNX(g_pktlog_info); + proc_name = PKTLOG_PROC_SYSTEM; + } + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31)) +#define set_ctl_name(a, b) /* nothing */ +#else +#define set_ctl_name(a, b) pl_info_lnx->sysctls[a].ctl_name = b +#endif + + /* + * Setup the sysctl table for creating the following sysctl entries: + * /proc/sys/PKTLOG_PROC_DIR//enable for enabling/disabling + * pktlog + * /proc/sys/PKTLOG_PROC_DIR//size for changing the buffer size + */ + memset(pl_info_lnx->sysctls, 0, sizeof(pl_info_lnx->sysctls)); + set_ctl_name(0, CTL_AUTO); + pl_info_lnx->sysctls[0].procname = PKTLOG_PROC_DIR; + pl_info_lnx->sysctls[0].mode = PKTLOG_PROCSYS_DIR_PERM; + pl_info_lnx->sysctls[0].child = &pl_info_lnx->sysctls[2]; + /* [1] is NULL terminator */ + set_ctl_name(2, CTL_AUTO); + pl_info_lnx->sysctls[2].procname = proc_name; + pl_info_lnx->sysctls[2].mode = PKTLOG_PROCSYS_DIR_PERM; + pl_info_lnx->sysctls[2].child = &pl_info_lnx->sysctls[4]; + /* [3] is NULL terminator */ + set_ctl_name(4, CTL_AUTO); + pl_info_lnx->sysctls[4].procname = "enable"; + pl_info_lnx->sysctls[4].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[4].proc_handler = ath_sysctl_pktlog_enable; + pl_info_lnx->sysctls[4].extra1 = scn; + + set_ctl_name(5, CTL_AUTO); + pl_info_lnx->sysctls[5].procname = "size"; + pl_info_lnx->sysctls[5].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[5].proc_handler = ath_sysctl_pktlog_size; + pl_info_lnx->sysctls[5].extra1 = scn; + + set_ctl_name(6, CTL_AUTO); + pl_info_lnx->sysctls[6].procname = "options"; + pl_info_lnx->sysctls[6].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[6].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[6].data = &pl_info_lnx->info.options; + pl_info_lnx->sysctls[6].maxlen = sizeof(pl_info_lnx->info.options); + + set_ctl_name(7, CTL_AUTO); + pl_info_lnx->sysctls[7].procname = "sack_thr"; + pl_info_lnx->sysctls[7].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[7].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[7].data = &pl_info_lnx->info.sack_thr; + pl_info_lnx->sysctls[7].maxlen = sizeof(pl_info_lnx->info.sack_thr); + + set_ctl_name(8, CTL_AUTO); + pl_info_lnx->sysctls[8].procname = "tail_length"; + pl_info_lnx->sysctls[8].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[8].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[8].data = &pl_info_lnx->info.tail_length; + pl_info_lnx->sysctls[8].maxlen = sizeof(pl_info_lnx->info.tail_length); + + set_ctl_name(9, CTL_AUTO); + pl_info_lnx->sysctls[9].procname = "thruput_thresh"; + pl_info_lnx->sysctls[9].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[9].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[9].data = &pl_info_lnx->info.thruput_thresh; + pl_info_lnx->sysctls[9].maxlen = + sizeof(pl_info_lnx->info.thruput_thresh); + + set_ctl_name(10, CTL_AUTO); + pl_info_lnx->sysctls[10].procname = "phyerr_thresh"; + pl_info_lnx->sysctls[10].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[10].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[10].data = &pl_info_lnx->info.phyerr_thresh; + pl_info_lnx->sysctls[10].maxlen = + sizeof(pl_info_lnx->info.phyerr_thresh); + + set_ctl_name(11, CTL_AUTO); + pl_info_lnx->sysctls[11].procname = "per_thresh"; + pl_info_lnx->sysctls[11].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[11].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[11].data = &pl_info_lnx->info.per_thresh; + pl_info_lnx->sysctls[11].maxlen = sizeof(pl_info_lnx->info.per_thresh); + + set_ctl_name(12, CTL_AUTO); + pl_info_lnx->sysctls[12].procname = "trigger_interval"; + pl_info_lnx->sysctls[12].mode = PKTLOG_PROCSYS_PERM; + pl_info_lnx->sysctls[12].proc_handler = proc_dointvec; + pl_info_lnx->sysctls[12].data = &pl_info_lnx->info.trigger_interval; + pl_info_lnx->sysctls[12].maxlen = + sizeof(pl_info_lnx->info.trigger_interval); + /* [13] is NULL terminator */ + + /* and register everything */ + /* register_sysctl_table changed from 2.6.21 onwards */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)) + pl_info_lnx->sysctl_header = + register_sysctl_table(pl_info_lnx->sysctls); +#else + pl_info_lnx->sysctl_header = + register_sysctl_table(pl_info_lnx->sysctls, 1); +#endif + if (!pl_info_lnx->sysctl_header) { + printk("%s: failed to register sysctls!\n", proc_name); + return -1; + } + + return 0; +} + +/* + * Initialize logging for system or adapter + * Parameter scn should be NULL for system wide logging + */ +static int pktlog_attach(struct ol_softc *scn) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info_lnx *pl_info_lnx; + char *proc_name; + struct proc_dir_entry *proc_entry; + + pl_dev = get_pl_handle(scn); + + if (pl_dev != NULL) { + pl_info_lnx = kmalloc(sizeof(*pl_info_lnx), GFP_KERNEL); + if (pl_info_lnx == NULL) { + printk(PKTLOG_TAG "%s:allocation failed for pl_info\n", + __func__); + return -ENOMEM; + } + pl_dev->pl_info = &pl_info_lnx->info; + pl_dev->name = WLANDEV_BASENAME; + proc_name = pl_dev->name; + if (!pl_dev->pl_funcs) + pl_dev->pl_funcs = &ol_pl_funcs; + + /* + * Valid for both direct attach and offload architecture + */ + pl_dev->pl_funcs->pktlog_init(scn); + } + else { + return -1; + } + + /* + * initialize log info + * might be good to move to pktlog_init + */ + /* pl_dev->tgt_pktlog_enabled = false; */ + pl_info_lnx->proc_entry = NULL; + pl_info_lnx->sysctl_header = NULL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + proc_entry = proc_create_data(proc_name, PKTLOG_PROC_PERM, + g_pktlog_pde, &pktlog_fops, + &pl_info_lnx->info); + + if (proc_entry == NULL) { + printk(PKTLOG_TAG "%s: create_proc_entry failed for %s\n", + __func__, proc_name); + goto attach_fail1; + } +#else + proc_entry = create_proc_entry(proc_name, PKTLOG_PROC_PERM, + g_pktlog_pde); + + if (proc_entry == NULL) { + printk(PKTLOG_TAG "%s: create_proc_entry failed for %s\n", + __func__, proc_name); + goto attach_fail1; + } + + proc_entry->data = &pl_info_lnx->info; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + proc_entry->owner = THIS_MODULE; +#endif + proc_entry->proc_fops = &pktlog_fops; +#endif + + pl_info_lnx->proc_entry = proc_entry; + + if (pktlog_sysctl_register(scn)) { + printk(PKTLOG_TAG "%s: sysctl register failed for %s\n", + __func__, proc_name); + goto attach_fail2; + } + return 0; + +attach_fail2: + remove_proc_entry(proc_name, g_pktlog_pde); + +attach_fail1: + if (pl_dev) + kfree(pl_dev->pl_info); + return -1; +} + +static void pktlog_sysctl_unregister(struct ol_pktlog_dev_t *pl_dev) +{ + struct ath_pktlog_info_lnx *pl_info_lnx; + + if (!pl_dev) { + printk("%s: Invalid pktlog context\n", __func__); + ASSERT(0); + return; + } + + pl_info_lnx = (pl_dev) ? PL_INFO_LNX(pl_dev->pl_info) : + PL_INFO_LNX(g_pktlog_info); + + if (pl_info_lnx->sysctl_header) { + unregister_sysctl_table(pl_info_lnx->sysctl_header); + pl_info_lnx->sysctl_header = NULL; + } +} + +static void pktlog_detach(struct ol_softc *scn) +{ + struct ol_pktlog_dev_t *pl_dev = (struct ol_pktlog_dev_t *) + get_pl_handle(scn); + struct ath_pktlog_info *pl_info; + + if (!pl_dev) { + printk("%s: Invalid pktlog context\n", __func__); + ASSERT(0); + return; + } + + pl_info = pl_dev->pl_info; + remove_proc_entry(WLANDEV_BASENAME, g_pktlog_pde); + pktlog_sysctl_unregister(pl_dev); + pktlog_cleanup(pl_info); + + if (pl_info->buf) + pktlog_release_buf(scn); + + if (pl_dev) { + kfree(pl_info); + pl_dev->pl_info = NULL; + } +} + +static int pktlog_open(struct inode *i, struct file *f) +{ + PKTLOG_MOD_INC_USE_COUNT; + return 0; +} + +static int pktlog_release(struct inode *i, struct file *f) +{ + PKTLOG_MOD_DEC_USE_COUNT; + return 0; +} + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/** + * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per + * packet statistics to the user + * + * This function is used to send the per packet statistics to the user + * + * Return: Success if the message is posted to user + * + */ +int pktlog_send_per_pkt_stats_to_user(void) +{ + ssize_t ret_val; + struct vos_log_pktlog_info *pktlog = NULL; + void *vos = vos_get_global_context(VOS_MODULE_ID_HIF, NULL); + ol_txrx_pdev_handle txrx_pdev = + vos_get_context(VOS_MODULE_ID_TXRX, vos); + struct ath_pktlog_info *pl_info; + bool read_complete; + uint32_t num_bytes_read = 0; + + /* + * We do not want to do this packet stats related processing when + * packet log tool is run. i.e., we want this processing to be + * done only when start logging command of packet stats is initiated. + */ + if ((vos_get_ring_log_level(RING_ID_PER_PACKET_STATS) < + WLAN_LOG_LEVEL_ACTIVE)) { + printk(PKTLOG_TAG " %s: Shouldnt happen. Logging not started\n", + __func__); + return -EINVAL; + } + + if (!txrx_pdev) { + printk(PKTLOG_TAG " %s: Invalid TxRx handle\n", __func__); + return -EINVAL; + } + + pl_info = txrx_pdev->pl_dev->pl_info; + + if (!pl_info || !pl_info->buf) { + printk(PKTLOG_TAG " %s: Shouldnt happen. pl_info is invalid\n", + __func__); + return -EINVAL; + } + + if (pl_info->buf->rd_offset == -1) { + printk(PKTLOG_TAG " %s: Shouldnt happen. No write yet!\n", + __func__); + return -EINVAL; + } + + do { + pktlog = (struct vos_log_pktlog_info *) + vos_mem_malloc(sizeof(struct vos_log_pktlog_info) + + VOS_LOG_PKT_LOG_SIZE); + if (!pktlog) { + printk(PKTLOG_TAG " %s: Memory allocation failed\n", + __func__); + return -ENOMEM; + } + + vos_mem_zero(pktlog, VOS_LOG_PKT_LOG_SIZE); + vos_log_set_code(pktlog, LOG_WLAN_PKT_LOG_INFO_C); + + pktlog->buf_len = 0; + pktlog->version = VERSION_LOG_WLAN_PKT_LOG_INFO_C; + + /* + * @ret_val: ret_val gives the actual data read from the buffer. + * When there is no more data to read, this value will be zero + * @offset: offset in the ring buffer. Initially it is zero and + * is incremented during every read based on number of bytes + * read + */ + ret_val = pktlog_read_proc_entry(pktlog->buf, + VOS_LOG_PKT_LOG_SIZE, + &pl_info->buf->offset, + pl_info, &read_complete); + if (ret_val) { + int index = 0; + struct ath_pktlog_hdr *temp; + while (1) { + if ((ret_val - index) < + sizeof(struct ath_pktlog_hdr)) { + /* Partial header */ + pl_info->buf->offset -= + (ret_val - index); + ret_val = index; + break; + } + temp = (struct ath_pktlog_hdr *) + (pktlog->buf + index); + if ((ret_val - index) < (temp->size + + sizeof(struct ath_pktlog_hdr))) { + /* Partial record payload */ + pl_info->buf->offset -= + (ret_val - index); + ret_val = index; + break; + } + index += temp->size + + sizeof(struct ath_pktlog_hdr); + } + } + + /* Data will include message index/seq number and buf length */ + pktlog->buf_len = ret_val; + if (ret_val) { + vos_log_set_length(pktlog, ret_val + + sizeof(struct vos_log_pktlog_info)); + pktlog->seq_no = pl_info->buf->msg_index++; + WLAN_VOS_DIAG_LOG_REPORT(pktlog); + } else { + vos_mem_free(pktlog); + } + num_bytes_read += ret_val; + /* + * If the logger thread is scheduled late and the proc entry + * is having too much data to be read, we might start to starve + * the other threads if we continuously keep reading the proc + * entry. So, having a threshold to break this read from proc + * entry. + */ + if (num_bytes_read > VOS_LOG_PKT_LOG_THRESHOLD) { + read_complete = true; + printk(PKTLOG_TAG " %s: Break read to prevent starve\n", + __func__); + } + } while (read_complete == false); + + return 0; +} + +/** + * pktlog_read_proc_entry() - This function is used to read data from the + * proc entry into the readers buffer + * @buf: Readers buffer + * @nbytes: Number of bytes to read + * @ppos: Offset within the drivers buffer + * @pl_info: Packet log information pointer + * @read_complete: Boolean value indication whether read is complete + * + * This function is used to read data from the proc entry into the readers + * buffer. Its functionality is similar to 'pktlog_read' which does + * copy to user to the user space buffer + * + * Return: Number of bytes read from the buffer + * + */ +ssize_t +pktlog_read_proc_entry(char *buf, size_t nbytes, loff_t *ppos, + struct ath_pktlog_info *pl_info, + bool *read_complete) +{ + size_t bufhdr_size; + size_t count = 0, ret_val = 0; + int rem_len; + int start_offset, end_offset; + int fold_offset, ppos_data, cur_rd_offset, cur_wr_offset; + struct ath_pktlog_buf *log_buf = pl_info->buf; + + *read_complete = false; + + if (log_buf == NULL) { + *read_complete = true; + return 0; + } + + if (*ppos == 0 && pl_info->log_state) { + pl_info->saved_state = pl_info->log_state; + pl_info->log_state = 0; + } + + bufhdr_size = sizeof(log_buf->bufhdr); + + /* copy valid log entries from circular buffer into user space */ + rem_len = nbytes; + count = 0; + + if (*ppos < bufhdr_size) { + count = MIN((bufhdr_size - *ppos), rem_len); + vos_mem_copy(buf, ((char *)&log_buf->bufhdr) + *ppos, + count); + rem_len -= count; + ret_val += count; + } + + start_offset = log_buf->rd_offset; + cur_wr_offset = log_buf->wr_offset; + + if ((rem_len == 0) || (start_offset < 0)) + goto rd_done; + + fold_offset = -1; + cur_rd_offset = start_offset; + + /* Find the last offset and fold-offset if the buffer is folded */ + do { + struct ath_pktlog_hdr *log_hdr; + int log_data_offset; + + log_hdr = (struct ath_pktlog_hdr *) (log_buf->log_data + + cur_rd_offset); + + log_data_offset = cur_rd_offset + sizeof(struct ath_pktlog_hdr); + + if ((fold_offset == -1) + && ((pl_info->buf_size - log_data_offset) + <= log_hdr->size)) + fold_offset = log_data_offset - 1; + + PKTLOG_MOV_RD_IDX(cur_rd_offset, log_buf, pl_info->buf_size); + + if ((fold_offset == -1) && (cur_rd_offset == 0) + && (cur_rd_offset != cur_wr_offset)) + fold_offset = log_data_offset + log_hdr->size - 1; + + end_offset = log_data_offset + log_hdr->size - 1; + } while (cur_rd_offset != cur_wr_offset); + + ppos_data = *ppos + ret_val - bufhdr_size + start_offset; + + if (fold_offset == -1) { + if (ppos_data > end_offset) + goto rd_done; + + count = MIN(rem_len, (end_offset - ppos_data + 1)); + vos_mem_copy(buf + ret_val, + log_buf->log_data + ppos_data, + count); + ret_val += count; + rem_len -= count; + } else { + if (ppos_data <= fold_offset) { + count = MIN(rem_len, (fold_offset - ppos_data + 1)); + vos_mem_copy(buf + ret_val, + log_buf->log_data + ppos_data, + count); + ret_val += count; + rem_len -= count; + } + + if (rem_len == 0) + goto rd_done; + + ppos_data = + *ppos + ret_val - (bufhdr_size + + (fold_offset - start_offset + 1)); + + if (ppos_data <= end_offset) { + count = MIN(rem_len, (end_offset - ppos_data + 1)); + vos_mem_copy(buf + ret_val, + log_buf->log_data + ppos_data, + count); + ret_val += count; + rem_len -= count; + } + } + +rd_done: + if ((ret_val < nbytes) && pl_info->saved_state) { + pl_info->log_state = pl_info->saved_state; + pl_info->saved_state = 0; + } + *ppos += ret_val; + + if (ret_val == 0) { + PKTLOG_LOCK(pl_info); + /* Write pointer might have been updated during the read. + * So, if some data is written into, lets not reset the pointers. + * We can continue to read from the offset position + */ + if (cur_wr_offset != log_buf->wr_offset) { + *read_complete = false; + } else { + pl_info->buf->rd_offset = -1; + pl_info->buf->wr_offset = 0; + pl_info->buf->bytes_written = 0; + pl_info->buf->offset = PKTLOG_READ_OFFSET; + *read_complete = true; + } + PKTLOG_UNLOCK(pl_info); + } + + return ret_val; +} + +static ssize_t +pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) +{ + size_t bufhdr_size; + size_t count = 0, ret_val = 0; + int rem_len; + int start_offset, end_offset; + int fold_offset, ppos_data, cur_rd_offset; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + struct ath_pktlog_info *pl_info = (struct ath_pktlog_info *) + PDE_DATA(file->f_dentry->d_inode); +#else + struct proc_dir_entry *proc_entry = PDE(file->f_dentry->d_inode); + struct ath_pktlog_info *pl_info = (struct ath_pktlog_info *) + proc_entry->data; +#endif + struct ath_pktlog_buf *log_buf = pl_info->buf; + + if (log_buf == NULL) + return 0; + + if (*ppos == 0 && pl_info->log_state) { + pl_info->saved_state = pl_info->log_state; + pl_info->log_state = 0; + } + + bufhdr_size = sizeof(log_buf->bufhdr); + + /* copy valid log entries from circular buffer into user space */ + rem_len = nbytes; + count = 0; + + if (*ppos < bufhdr_size) { + count = MIN((bufhdr_size - *ppos), rem_len); + if (copy_to_user(buf, ((char *)&log_buf->bufhdr) + *ppos, + count)) + return -EFAULT; + rem_len -= count; + ret_val += count; + } + + start_offset = log_buf->rd_offset; + + if ((rem_len == 0) || (start_offset < 0)) + goto rd_done; + + fold_offset = -1; + cur_rd_offset = start_offset; + + /* Find the last offset and fold-offset if the buffer is folded */ + do { + struct ath_pktlog_hdr *log_hdr; + int log_data_offset; + + log_hdr = (struct ath_pktlog_hdr *) (log_buf->log_data + + cur_rd_offset); + + log_data_offset = cur_rd_offset + sizeof(struct ath_pktlog_hdr); + + if ((fold_offset == -1) + && ((pl_info->buf_size - log_data_offset) + <= log_hdr->size)) + fold_offset = log_data_offset - 1; + + PKTLOG_MOV_RD_IDX(cur_rd_offset, log_buf, pl_info->buf_size); + + if ((fold_offset == -1) && (cur_rd_offset == 0) + && (cur_rd_offset != log_buf->wr_offset)) + fold_offset = log_data_offset + log_hdr->size - 1; + + end_offset = log_data_offset + log_hdr->size - 1; + } while (cur_rd_offset != log_buf->wr_offset); + + ppos_data = *ppos + ret_val - bufhdr_size + start_offset; + + if (fold_offset == -1) { + if (ppos_data > end_offset) + goto rd_done; + + count = MIN(rem_len, (end_offset - ppos_data + 1)); + if (copy_to_user(buf + ret_val, + log_buf->log_data + ppos_data, + count)) + return -EFAULT; + ret_val += count; + rem_len -= count; + } else { + if (ppos_data <= fold_offset) { + count = MIN(rem_len, (fold_offset - ppos_data + 1)); + if (copy_to_user(buf + ret_val, + log_buf->log_data + ppos_data, + count)) + return -EFAULT; + ret_val += count; + rem_len -= count; + } + + if (rem_len == 0) + goto rd_done; + + ppos_data = + *ppos + ret_val - (bufhdr_size + + (fold_offset - start_offset + 1)); + + if (ppos_data <= end_offset) { + count = MIN(rem_len, (end_offset - ppos_data + 1)); + if (copy_to_user(buf + ret_val, + log_buf->log_data + ppos_data, + count)) + return -EFAULT; + ret_val += count; + rem_len -= count; + } + } + +rd_done: + if ((ret_val < nbytes) && pl_info->saved_state) { + pl_info->log_state = pl_info->saved_state; + pl_info->saved_state = 0; + } + *ppos += ret_val; + + return ret_val; +} + +#ifndef VMALLOC_VMADDR +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) +/* Convert a kernel virtual address to a kernel logical address */ +static volatile void *pktlog_virt_to_logical(volatile void *addr) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *ptep, pte; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) || \ + (defined(__i386__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))) + pud_t *pud; +#endif + unsigned long vaddr, ret = 0UL; + + vaddr = VMALLOC_VMADDR((unsigned long) addr); + + pgd = pgd_offset_k(vaddr); + + if (!pgd_none(*pgd)) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) || \ + (defined(__i386__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))) + pud = pud_offset(pgd, vaddr); + pmd = pmd_offset(pud, vaddr); +#else + pmd = pmd_offset(pgd, vaddr); +#endif + + if (!pmd_none(*pmd)) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + ptep = pte_offset_map(pmd, vaddr); +#else + ptep = pte_offset(pmd, vaddr); +#endif + pte = *ptep; + + if (pte_present(pte)) { + ret = (unsigned long) + page_address(pte_page(pte)); + ret |= (vaddr & (PAGE_SIZE - 1)); + } + } + } + return (volatile void *)ret; +} +#endif + +/* vma operations for mapping vmalloced area to user space */ +static void pktlog_vopen(struct vm_area_struct *vma) +{ + PKTLOG_MOD_INC_USE_COUNT; +} + +static void pktlog_vclose(struct vm_area_struct *vma) +{ + PKTLOG_MOD_DEC_USE_COUNT; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) +int pktlog_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + unsigned long address = (unsigned long)vmf->virtual_address; + + if (address == 0UL) + return VM_FAULT_NOPAGE; + + if (vmf->pgoff > vma->vm_end) + return VM_FAULT_SIGBUS; + + get_page(virt_to_page((void *)address)); + vmf->page = virt_to_page((void *)address); + return VM_FAULT_MINOR; +} +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +struct page *pktlog_vmmap(struct vm_area_struct *vma, unsigned long addr, + int *type) +#else +struct page *pktlog_vmmap(struct vm_area_struct *vma, unsigned long addr, + int write_access) +#endif +{ + unsigned long offset, vaddr; + struct proc_dir_entry *proc_entry; + struct ath_pktlog_info *pl_info = + + proc_entry = PDE(vma->vm_file->f_dentry->d_inode); + pl_info = (struct ath_pktlog_info *)proc_entry->data; + + offset = addr - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT); + vaddr = (unsigned long) pktlog_virt_to_logical( + (void *)(pl_info->buf) + offset); + + if (vaddr == 0UL) { + printk(PKTLOG_TAG "%s: page fault out of range\n", __func__); + return ((struct page *) 0UL); + } + + /* increment the usage count of the page */ + get_page(virt_to_page((void*)vaddr)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + if (type) + *type = VM_FAULT_MINOR; +#endif + + return virt_to_page((void *)vaddr); +} +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) */ + +static struct vm_operations_struct pktlog_vmops = { + open:pktlog_vopen, + close:pktlog_vclose, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) + fault:pktlog_fault, +#else + nopage:pktlog_vmmap, +#endif +}; + +static int pktlog_mmap(struct file *file, struct vm_area_struct *vma) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + struct ath_pktlog_info *pl_info = (struct ath_pktlog_info *) + PDE_DATA(file->f_dentry->d_inode); +#else + struct proc_dir_entry *proc_entry = PDE(file->f_dentry->d_inode); + struct ath_pktlog_info *pl_info = (struct ath_pktlog_info *) + proc_entry->data; +#endif + + if (vma->vm_pgoff != 0) { + /* Entire buffer should be mapped */ + return -EINVAL; + } + + if (!pl_info->buf) { + printk(PKTLOG_TAG "%s: Log buffer unavailable\n", __func__); + return -ENOMEM; + } + + vma->vm_flags |= VM_LOCKED; + vma->vm_ops = &pktlog_vmops; + pktlog_vopen(vma); + return 0; +} + +int pktlogmod_init(void *context) +{ + int ret; + + /* create the proc directory entry */ + g_pktlog_pde = proc_mkdir(PKTLOG_PROC_DIR, NULL); + + if (g_pktlog_pde == NULL) { + printk(PKTLOG_TAG "%s: proc_mkdir failed\n", __func__); + return -1; + } + + /* Attach packet log */ + if ((ret = pktlog_attach((struct ol_softc *)context))) + goto attach_fail; + + return ret; + +attach_fail: + remove_proc_entry(PKTLOG_PROC_DIR, NULL); + g_pktlog_pde = NULL; + return ret; +} + +void pktlogmod_exit(void *context) +{ + struct ol_softc *scn = (struct ol_softc *)context; + struct ol_pktlog_dev_t *pl_dev = get_pl_handle(scn); + + if (!pl_dev || g_pktlog_pde == NULL) { + printk("%s: pldev or g_pktlog_pde is NULL\n", __func__); + return; + } + + /* + * pktlog already be detached + * avoid to detach and remove proc entry again + */ + if (!pl_dev->pl_info) { + printk("%s: pldev pl_info is NULL\n", __func__); + return; + } + + /* + * Disable firmware side pktlog function + */ + if (pl_dev->tgt_pktlog_enabled) { + if (pl_dev->pl_funcs->pktlog_enable(scn, 0)) { + printk("%s: cannot disable pktlog in the target\n", + __func__); + } + } + + pktlog_detach(scn); + /* + * pdev kill needs to be implemented + */ + remove_proc_entry(PKTLOG_PROC_DIR, NULL); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c new file mode 100644 index 000000000000..3bc0ae1f4222 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef REMOVE_PKT_LOG +#include "adf_os_mem.h" +#include "athdefs.h" +#include "pktlog_ac_i.h" +#include "vos_api.h" +#include "wlan_qct_wda.h" + +wdi_event_subscribe PKTLOG_TX_SUBSCRIBER; +wdi_event_subscribe PKTLOG_RX_SUBSCRIBER; +wdi_event_subscribe PKTLOG_RX_REMOTE_SUBSCRIBER; +wdi_event_subscribe PKTLOG_RCFIND_SUBSCRIBER; +wdi_event_subscribe PKTLOG_RCUPDATE_SUBSCRIBER; + +struct ol_pl_arch_dep_funcs ol_pl_funcs = { + .pktlog_init = pktlog_init, + .pktlog_enable = pktlog_enable, + .pktlog_setsize = pktlog_setsize, + .pktlog_disable = pktlog_disable, /* valid for f/w disable */ +}; + +struct ol_pktlog_dev_t ol_pl_dev = { + .pl_funcs = &ol_pl_funcs, +}; + +void ol_pl_sethandle(ol_pktlog_dev_handle *pl_handle, + struct ol_softc *scn) +{ + ol_pl_dev.scn = (ol_ath_generic_softc_handle)scn; + *pl_handle = &ol_pl_dev; +} + +static A_STATUS pktlog_wma_post_msg(WMI_PKTLOG_EVENT event_types, + WMI_CMD_ID cmd_id) +{ + vos_msg_t msg = {0}; + VOS_STATUS status; + struct ath_pktlog_wmi_params *param; + + param = vos_mem_malloc(sizeof(struct ath_pktlog_wmi_params)); + + if (!param) + return A_NO_MEMORY; + + param->cmd_id = cmd_id; + param->pktlog_event = event_types; + + msg.type = WDA_PKTLOG_ENABLE_REQ; + msg.bodyptr = param; + msg.bodyval = 0; + + status = vos_mq_post_message(VOS_MQ_ID_WDA, &msg); + + if (status != VOS_STATUS_SUCCESS) { + vos_mem_free(param); + return A_ERROR; + } + + return A_OK; +} + +static inline A_STATUS +pktlog_enable_tgt(struct ol_softc *_scn, uint32_t log_state) +{ + uint32_t types = 0; + + if (log_state & ATH_PKTLOG_TX) + types |= WMI_PKTLOG_EVENT_TX; + + if (log_state & ATH_PKTLOG_RX) + types |= WMI_PKTLOG_EVENT_RX; + + if (log_state & ATH_PKTLOG_RCFIND) + types |= WMI_PKTLOG_EVENT_RCF; + + if (log_state & ATH_PKTLOG_RCUPDATE) + types |= WMI_PKTLOG_EVENT_RCU; + + return pktlog_wma_post_msg(types, WMI_PDEV_PKTLOG_ENABLE_CMDID); +} + +static inline A_STATUS +wdi_pktlog_subscribe(struct ol_txrx_pdev_t *txrx_pdev, int32_t log_state) +{ + if (!txrx_pdev) { + printk("Invalid pdev in %s\n", __func__); + return A_ERROR; + } + if (log_state & ATH_PKTLOG_TX) { + if (wdi_event_sub(txrx_pdev, + &PKTLOG_TX_SUBSCRIBER, + WDI_EVENT_TX_STATUS)) { + return A_ERROR; + } + } + if (log_state & ATH_PKTLOG_RX) { + if (wdi_event_sub(txrx_pdev, + &PKTLOG_RX_SUBSCRIBER, + WDI_EVENT_RX_DESC)) { + return A_ERROR; + } + if (wdi_event_sub(txrx_pdev, + &PKTLOG_RX_REMOTE_SUBSCRIBER, + WDI_EVENT_RX_DESC_REMOTE)) { + return A_ERROR; + } + } + if (log_state & ATH_PKTLOG_RCFIND) { + if (wdi_event_sub(txrx_pdev, + &PKTLOG_RCFIND_SUBSCRIBER, + WDI_EVENT_RATE_FIND)) { + return A_ERROR; + } + } + if (log_state & ATH_PKTLOG_RCUPDATE) { + if (wdi_event_sub(txrx_pdev, + &PKTLOG_RCUPDATE_SUBSCRIBER, + WDI_EVENT_RATE_UPDATE)) { + return A_ERROR; + } + } + return A_OK; +} + +void +pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data) +{ + switch (event) { + case WDI_EVENT_TX_STATUS: + { + /* + * process TX message + */ + if (process_tx_info(pdev, log_data)) { + printk("Unable to process TX info\n"); + return; + } + break; + } + case WDI_EVENT_RX_DESC: + { + /* + * process RX message for local frames + */ + if (process_rx_info(pdev, log_data)) { + printk("Unable to process RX info\n"); + return; + } + break; + } + case WDI_EVENT_RX_DESC_REMOTE: + { + /* + * process RX message for remote frames + */ + if (process_rx_info_remote(pdev, log_data)) { + printk("Unable to process RX info\n"); + return; + } + break; + } + case WDI_EVENT_RATE_FIND: + { + /* + * process RATE_FIND message + */ + if (process_rate_find(pdev, log_data)) { + printk("Unable to process RC_FIND info\n"); + return; + } + break; + } + case WDI_EVENT_RATE_UPDATE: + { + /* + * process RATE_UPDATE message + */ + if (process_rate_update(pdev, log_data)) { + printk("Unable to process RC_UPDATE\n"); + return; + } + break; + } + default: + break; + } +} + +static inline A_STATUS +wdi_pktlog_unsubscribe(struct ol_txrx_pdev_t *txrx_pdev, uint32_t log_state) +{ + if (log_state & ATH_PKTLOG_TX) { + if (wdi_event_unsub(txrx_pdev, + &PKTLOG_TX_SUBSCRIBER, + WDI_EVENT_TX_STATUS)) { + return A_ERROR; + } + } + if (log_state & ATH_PKTLOG_RX) { + if (wdi_event_unsub(txrx_pdev, + &PKTLOG_RX_SUBSCRIBER, + WDI_EVENT_RX_DESC)) { + return A_ERROR; + } + if (wdi_event_unsub(txrx_pdev, + &PKTLOG_RX_REMOTE_SUBSCRIBER, + WDI_EVENT_RX_DESC_REMOTE)) { + return A_ERROR; + } + } + if (log_state & ATH_PKTLOG_RCFIND) { + if (wdi_event_unsub(txrx_pdev, + &PKTLOG_RCFIND_SUBSCRIBER, + WDI_EVENT_RATE_FIND)) { + return A_ERROR; + } + } + if (log_state & ATH_PKTLOG_RCUPDATE) { + if (wdi_event_unsub(txrx_pdev, + &PKTLOG_RCUPDATE_SUBSCRIBER, + WDI_EVENT_RATE_UPDATE)) { + return A_ERROR; + } + } + return A_OK; +} + +int +pktlog_disable(struct ol_softc *scn) +{ + struct ol_pktlog_dev_t *pl_dev = scn->pdev_txrx_handle->pl_dev; + struct ath_pktlog_info *pl_info = pl_dev->pl_info; + struct ol_txrx_pdev_t *txrx_pdev = scn->pdev_txrx_handle; + + if (pktlog_wma_post_msg(0, WMI_PDEV_PKTLOG_DISABLE_CMDID)) { + printk("Failed to disable pktlog in target\n"); + return -1; + } + + if (wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state)) { + printk("Cannot unsubscribe pktlog from the WDI\n"); + return -1; + } + + return 0; +} + +void +pktlog_init(struct ol_softc *scn) +{ + struct ath_pktlog_info *pl_info; + + pl_info = scn->pdev_txrx_handle->pl_dev->pl_info; + + OS_MEMZERO(pl_info, sizeof(*pl_info)); + PKTLOG_LOCK_INIT(pl_info); + + pl_info->buf_size = PKTLOG_DEFAULT_BUFSIZE; + pl_info->buf = NULL; + pl_info->log_state = 0; + pl_info->sack_thr = PKTLOG_DEFAULT_SACK_THR; + pl_info->tail_length = PKTLOG_DEFAULT_TAIL_LENGTH; + pl_info->thruput_thresh = PKTLOG_DEFAULT_THRUPUT_THRESH; + pl_info->per_thresh = PKTLOG_DEFAULT_PER_THRESH; + pl_info->phyerr_thresh = PKTLOG_DEFAULT_PHYERR_THRESH; + pl_info->trigger_interval = PKTLOG_DEFAULT_TRIGGER_INTERVAL; + pl_info->pktlen = 0; + pl_info->start_time_thruput = 0; + pl_info->start_time_per = 0; + + PKTLOG_TX_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RX_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RX_REMOTE_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RCFIND_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RCUPDATE_SUBSCRIBER.callback = pktlog_callback; +} + +int +pktlog_enable(struct ol_softc *scn, int32_t log_state) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info *pl_info; + struct ol_txrx_pdev_t *txrx_pdev; + int error; + + if (!scn) { + printk("%s: Invalid scn context\n", __func__); + ASSERT(0); + return -1; + } + + txrx_pdev = scn->pdev_txrx_handle; + if (!txrx_pdev) { + printk("%s: Invalid txrx_pdev context\n", __func__); + ASSERT(0); + return -1; + } + + pl_dev = scn->pdev_txrx_handle->pl_dev; + if (!pl_dev) { + printk("%s: Invalid pktlog context\n", __func__); + ASSERT(0); + return -1; + } + + pl_info = pl_dev->pl_info; + pl_dev->sc_osdev = scn->sc_osdev; + + if (!pl_info) + return 0; + + if (log_state != 0 && !pl_dev->tgt_pktlog_enabled) { + if (pl_info->buf == NULL) { + error = pktlog_alloc_buf(scn); + + if (error != 0) + return error; + + if (!pl_info->buf) { + printk("%s: pktlog buf alloc failed\n", __func__); + ASSERT(0); + return -1; + } + } + + pl_info->buf->bufhdr.version = CUR_PKTLOG_VER; + pl_info->buf->bufhdr.magic_num = PKTLOG_MAGIC_NUM; + pl_info->buf->wr_offset = 0; + pl_info->buf->rd_offset = -1; + /* These below variables are used by per packet stats*/ + pl_info->buf->bytes_written = 0; + pl_info->buf->msg_index = 1; + pl_info->buf->offset = PKTLOG_READ_OFFSET; + + pl_info->start_time_thruput = OS_GET_TIMESTAMP(); + pl_info->start_time_per = pl_info->start_time_thruput; + + /* WDI subscribe */ + if (wdi_pktlog_subscribe(txrx_pdev, log_state)) { + printk("Unable to subscribe to the WDI %s\n", + __func__); + return -1; + } + /* WMI command to enable pktlog on the firmware */ + if (pktlog_enable_tgt(scn, log_state)) { + printk("Device cannot be enabled, %s\n", __func__); + return -1; + } else { + pl_dev->tgt_pktlog_enabled = true; + } + } else if (!log_state && pl_dev->tgt_pktlog_enabled) { + pl_dev->pl_funcs->pktlog_disable(scn); + pl_dev->tgt_pktlog_enabled = false; + if (wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state)) { + printk("Cannot unsubscribe pktlog from the WDI\n"); + return -1; + } + } + + pl_info->log_state = log_state; + return 0; +} + +int +pktlog_setsize(struct ol_softc *scn, int32_t size) +{ + struct ol_pktlog_dev_t *pl_dev = scn->pdev_txrx_handle->pl_dev; + struct ath_pktlog_info *pl_info = pl_dev->pl_info; + + if (size < 0) + return -EINVAL; + + if (size == pl_info->buf_size) + return 0; + + if (pl_info->log_state) { + printk("Logging should be disabled before changing bufer size\n"); + return -EINVAL; + } + + if (pl_info->buf != NULL) + pktlog_release_buf(scn); + + if (size != 0) + pl_info->buf_size = size; + + return 0; +} +#endif /* REMOVE_PKT_LOG */ diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c new file mode 100644 index 000000000000..8f9042fe2ef0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "ol_htt_tx_api.h" +#include "ol_tx_desc.h" +#include "adf_os_mem.h" +#include "htt.h" +#include "htt_internal.h" +#include "pktlog_ac_i.h" +#include "wma_api.h" +#include "wlan_logging_sock_svc.h" + +#define TX_DESC_ID_LOW_MASK 0xffff +#define TX_DESC_ID_LOW_SHIFT 0 +#define TX_DESC_ID_HIGH_MASK 0xffff0000 +#define TX_DESC_ID_HIGH_SHIFT 16 + +#define PER_PACKET_STATS_THRESHOLD 4096 + +void +pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) +{ + struct ath_pktlog_buf *log_buf; + int32_t buf_size; + struct ath_pktlog_hdr *log_hdr; + int32_t cur_wr_offset; + char *log_ptr; + struct ath_pktlog_info *pl_info; + u_int16_t log_type; + size_t log_size; + uint32_t flags; + + if (!plarg) { + printk("Invalid parg in %s\n", __func__); + return; + } + + pl_info = plarg->pl_info; + log_type = plarg->log_type; + log_size = plarg->log_size; + log_buf = pl_info->buf; + flags = plarg->flags; + + if (!log_buf) { + printk("Invalid log_buf in %s\n", __func__); + return; + } + buf_size = pl_info->buf_size; + cur_wr_offset = log_buf->wr_offset; + /* Move read offset to the next entry if there is a buffer overlap */ + if (log_buf->rd_offset >= 0) { + if ((cur_wr_offset <= log_buf->rd_offset) + && (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) > + log_buf->rd_offset) { + PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, + buf_size); + } + } else { + log_buf->rd_offset = cur_wr_offset; + } + + log_hdr = (struct ath_pktlog_hdr *) (log_buf->log_data + cur_wr_offset); + log_hdr->log_type = log_type; + log_hdr->flags = flags; + log_hdr->size = (u_int16_t)log_size; + log_hdr->missed_cnt = plarg->missed_cnt; + log_hdr->timestamp = plarg->timestamp; + + cur_wr_offset += sizeof(*log_hdr); + + if ((buf_size - cur_wr_offset) < log_size) { + while ((cur_wr_offset <= log_buf->rd_offset) + && (log_buf->rd_offset < buf_size)) { + PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, + buf_size); + } + cur_wr_offset = 0; + } + + while ((cur_wr_offset <= log_buf->rd_offset) + && (cur_wr_offset + log_size) > log_buf->rd_offset) { + PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, + buf_size); + } + + log_ptr = &(log_buf->log_data[cur_wr_offset]); + cur_wr_offset += log_hdr->size; + + log_buf->wr_offset = ((buf_size - cur_wr_offset) >= + sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset : 0; + + plarg->buf = log_ptr; +} + +/** + * pktlog_check_threshold() - This function checks threshold for triggering + * packet stats + * @pl_info: Packet log information pointer + * @log_size: Size of current packet log information + * + * This function internally triggers logging of per packet stats when the + * incoming data crosses threshold limit + * + * Return: None + * + */ +void pktlog_check_threshold(struct ath_pktlog_info *pl_info, + size_t log_size) +{ + PKTLOG_LOCK(pl_info); + pl_info->buf->bytes_written += log_size + sizeof(struct ath_pktlog_hdr); + + if (pl_info->buf->bytes_written >= PER_PACKET_STATS_THRESHOLD) { + wlan_logging_set_per_pkt_stats(); + pl_info->buf->bytes_written = 0; + } + PKTLOG_UNLOCK(pl_info); +} + +char * +pktlog_getbuf(struct ol_pktlog_dev_t *pl_dev, + struct ath_pktlog_info *pl_info, + size_t log_size, + struct ath_pktlog_hdr *pl_hdr) +{ + struct ath_pktlog_arg plarg = {0,}; + uint8_t flags = 0; + + plarg.pl_info = pl_info; + plarg.log_type = pl_hdr->log_type; + plarg.log_size = log_size; + plarg.flags = pl_hdr->flags; + plarg.missed_cnt = pl_hdr->missed_cnt; + plarg.timestamp = pl_hdr->timestamp; + + if (flags & PHFLAGS_INTERRUPT_CONTEXT) { + /* + * We are already in interupt context, no need to make it + * intsafe. call the function directly. + */ + pktlog_getbuf_intsafe(&plarg); + } else { + PKTLOG_LOCK(pl_info); + pktlog_getbuf_intsafe(&plarg); + PKTLOG_UNLOCK(pl_info); + } + + /* + * We do not want to do this packet stats related processing when + * packet log tool is run. i.e., we want this processing to be + * done only when start logging command of packet stats is initiated. + */ + if (vos_get_ring_log_level(RING_ID_PER_PACKET_STATS) == + WLAN_LOG_LEVEL_ACTIVE) + pktlog_check_threshold(pl_info, log_size); + + return plarg.buf; +} + +static struct txctl_frm_hdr frm_hdr; + +static void process_ieee_hdr(void *data) +{ + uint8_t dir; + struct ieee80211_frame *wh = (struct ieee80211_frame *)(data); + + frm_hdr.framectrl = *(u_int16_t *)(wh->i_fc); + frm_hdr.seqctrl = *(u_int16_t *)(wh->i_seq); + dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK); + + if (dir == IEEE80211_FC1_DIR_TODS) { + frm_hdr.bssid_tail = (wh->i_addr1[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr1[IEEE80211_ADDR_LEN-1]); + frm_hdr.sa_tail = (wh->i_addr2[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr2[IEEE80211_ADDR_LEN-1]); + frm_hdr.da_tail = (wh->i_addr3[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr3[IEEE80211_ADDR_LEN-1]); + } else if (dir == IEEE80211_FC1_DIR_FROMDS) { + frm_hdr.bssid_tail = (wh->i_addr2[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr2[IEEE80211_ADDR_LEN-1]); + frm_hdr.sa_tail = (wh->i_addr3[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr3[IEEE80211_ADDR_LEN-1]); + frm_hdr.da_tail = (wh->i_addr1[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr1[IEEE80211_ADDR_LEN-1]); + } else { + frm_hdr.bssid_tail = (wh->i_addr3[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr3[IEEE80211_ADDR_LEN-1]); + frm_hdr.sa_tail = (wh->i_addr2[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr2[IEEE80211_ADDR_LEN-1]); + frm_hdr.da_tail = (wh->i_addr1[IEEE80211_ADDR_LEN-2] << 8) | + (wh->i_addr1[IEEE80211_ADDR_LEN-1]); + } +} + +A_STATUS +process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, + void *data) +{ + /* + * Must include to process different types + * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR + */ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + uint32_t *pl_tgt_hdr; + + if (!txrx_pdev) { + printk("Invalid pdev in %s\n", __func__); + return A_ERROR; + } + adf_os_assert(txrx_pdev->pl_dev); + adf_os_assert(data); + pl_dev = txrx_pdev->pl_dev; + + pl_tgt_hdr = (uint32_t *)data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> + ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + + pl_info = pl_dev->pl_info; + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) { + /* Valid only for the TX CTL */ + process_ieee_hdr(data + sizeof(pl_hdr)); + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) { + A_UINT32 desc_id = (A_UINT32) + *((A_UINT32 *)(data + sizeof(pl_hdr))); + A_UINT32 vdev_id = desc_id; + + /* if the pkt log msg is for the bcn frame the vdev id + * is piggybacked in desc_id and the MSB of the desc ID + * would be set to FF + */ +#define BCN_DESC_ID 0xFF + if ((desc_id >> 24) == BCN_DESC_ID) { + void *data; + A_UINT32 buf_size; + + vdev_id &= 0x00FFFFFF; + data = wma_get_beacon_buffer_by_vdev_id(vdev_id, + &buf_size); + if (data) { + process_ieee_hdr(data); + adf_os_mem_free(data); + } + } else { + /* + * TODO: get the hdr content for mgmt frames from + * Tx mgmt desc pool + */ + } + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { + struct ath_pktlog_txctl txctl_log; + size_t log_size = sizeof(txctl_log.priv); + + txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev, + pl_info, + log_size, + &pl_hdr); + + if (!txctl_log.txdesc_hdr_ctl) { + printk("failed to get buf for txctl_log.txdesc_hdr_ctl\n"); + return A_ERROR; + } + + /* + * frm hdr is currently Valid only for local frames + * Add capability to include the fmr hdr for remote frames + */ + txctl_log.priv.frm_hdr = frm_hdr; + adf_os_assert(txctl_log.priv.txdesc_ctl); + adf_os_mem_copy((void *)&txctl_log.priv.txdesc_ctl, + ((void *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + adf_os_assert(txctl_log.txdesc_hdr_ctl); + adf_os_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv, + sizeof(txctl_log.priv)); + /* Add Protocol information and HT specific information */ + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { + struct ath_pktlog_tx_status txstat_log; + size_t log_size = pl_hdr.size; + + txstat_log.ds_status = (void *) + pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); + adf_os_assert(txstat_log.ds_status); + adf_os_mem_copy(txstat_log.ds_status, + ((void *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) { + struct ath_pktlog_msdu_info pl_msdu_info; + uint32_t i; + uint32_t *htt_tx_desc; + size_t log_size; + struct ol_tx_desc_t *tx_desc; + uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET; + uint16_t tx_desc_id; + uint32_t *msdu_id_info = (uint32_t *) + ((void *)data + + sizeof(struct ath_pktlog_hdr)); + uint32_t *msdu_id = (uint32_t *)((char *)msdu_id_info + + msdu_id_offset); + u_int8_t *addr, *vap_addr; + u_int8_t vdev_id; + adf_nbuf_t netbuf; + u_int32_t len; + + adf_os_mem_set(&pl_msdu_info, 0, sizeof(pl_msdu_info)); + + pl_msdu_info.num_msdu = *msdu_id_info; + pl_msdu_info.priv_size = sizeof(uint32_t) * + pl_msdu_info.num_msdu + + sizeof(uint32_t); + log_size = sizeof(pl_msdu_info.priv); + + for (i = 0; i < pl_msdu_info.num_msdu; i++) { + /* + * Handle big endianess + * Increment msdu_id once after retrieving + * lower 16 bits and uppper 16 bits + */ + if (!(i % 2)) { + tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) + >> TX_DESC_ID_LOW_SHIFT); + } else { + tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) + >> TX_DESC_ID_HIGH_SHIFT); + msdu_id += 1; + } + tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); + adf_os_assert(tx_desc); + netbuf = tx_desc->netbuf; + htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc; + adf_os_assert(htt_tx_desc); + + adf_nbuf_peek_header(netbuf, &addr, &len); + + if (len < (2 * IEEE80211_ADDR_LEN)) { + adf_os_print("TX frame does not have a valid address\n"); + return -1; + } + /* Adding header information for the TX data frames */ + vdev_id = (u_int8_t)(*(htt_tx_desc + + HTT_TX_VDEV_ID_WORD) >> + HTT_TX_VDEV_ID_SHIFT) & + HTT_TX_VDEV_ID_MASK; + + vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id); + + frm_hdr.da_tail = (addr[IEEE80211_ADDR_LEN-2] << 8) | + (addr[IEEE80211_ADDR_LEN-1]); + frm_hdr.sa_tail = + (addr[2 * IEEE80211_ADDR_LEN-2] << 8) | + (addr[2 * IEEE80211_ADDR_LEN-1]); + if (vap_addr) { + frm_hdr.bssid_tail = + (vap_addr[IEEE80211_ADDR_LEN-2] << 8) | + (vap_addr[IEEE80211_ADDR_LEN-1]); + } else { + frm_hdr.bssid_tail = 0x0000; + } + pl_msdu_info.priv.msdu_len[i] = *(htt_tx_desc + + HTT_TX_MSDU_LEN_DWORD) + & HTT_TX_MSDU_LEN_MASK; + /* + * Add more information per MSDU + * e.g., protocol information + */ + } + pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + adf_os_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info, + ((void *)data + sizeof(struct ath_pktlog_hdr)), + sizeof(pl_msdu_info.priv.msdu_id_info)); + adf_os_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv, + sizeof(pl_msdu_info.priv)); + } + return A_OK; +} + +A_STATUS +process_rx_info_remote(void *pdev, adf_nbuf_t amsdu) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info *pl_info; + struct htt_host_rx_desc_base *rx_desc; + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_rx_info rxstat_log; + size_t log_size; + adf_nbuf_t msdu; + + if (!pdev) { + printk("Invalid pdev in %s\n", __func__); + return A_ERROR; + } + if (!amsdu) { + printk("Invalid data in %s\n", __func__); + return A_ERROR; + } + pl_dev = ((struct ol_txrx_pdev_t *) pdev)->pl_dev; + pl_info = pl_dev->pl_info; + msdu = amsdu; + + while (msdu) { + rx_desc = (struct htt_host_rx_desc_base *)( + adf_nbuf_data(msdu)) - 1; + log_size = sizeof(*rx_desc) - + sizeof(struct htt_host_fw_desc_base); + + /* + * Construct the pktlog header pl_hdr + * Because desc is DMA'd to the host memory + */ + pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); + pl_hdr.missed_cnt = 0; + pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; + pl_hdr.size = sizeof(*rx_desc) - + sizeof(struct htt_host_fw_desc_base); + pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp; + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + adf_os_mem_copy(rxstat_log.rx_desc, (void *)rx_desc + + sizeof(struct htt_host_fw_desc_base), + pl_hdr.size); + msdu = adf_nbuf_next(msdu); + } + return A_OK; +} + +A_STATUS +process_rx_info(void *pdev, void *data) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info *pl_info; + struct ath_pktlog_rx_info rxstat_log; + struct ath_pktlog_hdr pl_hdr; + size_t log_size; + uint32_t *pl_tgt_hdr; + + if (!pdev) { + printk("Invalid pdev in %s", __func__); + return A_ERROR; + } + pl_dev = ((struct ol_txrx_pdev_t *) pdev)->pl_dev; + pl_info = pl_dev->pl_info; + pl_tgt_hdr = (uint32_t *)data; + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> + ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + log_size = pl_hdr.size; + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + adf_os_mem_copy(rxstat_log.rx_desc, + (void *)data + sizeof(struct ath_pktlog_hdr), + pl_hdr.size); + + return A_OK; +} + +A_STATUS +process_rate_find(void *pdev, void *data) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + size_t log_size; + + /* + * Will be uncommented when the rate control find + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + struct ath_pktlog_rc_find rcf_log; + uint32_t *pl_tgt_hdr; + + if (!pdev) { + adf_os_print("Invalid pdev in %s\n", __func__); + return A_ERROR; + } + if (!data) { + adf_os_print("Invalid data in %s\n", __func__); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> + ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + pl_dev = ((struct ol_txrx_pdev_t *) pdev)->pl_dev; + pl_info = pl_dev->pl_info; + log_size = pl_hdr.size; + rcf_log.rcFind = (void *) pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + adf_os_mem_copy(rcf_log.rcFind, + ((char *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + + return A_OK; +} + +A_STATUS +process_rate_update(void *pdev, void *data) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_hdr pl_hdr; + size_t log_size; + struct ath_pktlog_info *pl_info; + struct ath_pktlog_rc_update rcu_log; + uint32_t *pl_tgt_hdr; + + if (!pdev) { + printk("Invalid pdev in %s\n", __func__); + return A_ERROR; + } + if (!data) { + printk("Invalid data in %s\n", __func__); + return A_ERROR; + } + pl_tgt_hdr = (uint32_t *)data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> + ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + pl_dev = ((struct ol_txrx_pdev_t *) pdev)->pl_dev; + log_size = pl_hdr.size; + pl_info = pl_dev->pl_info; + + /* + * Will be uncommented when the rate control update + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + adf_os_mem_copy(rcu_log.txRateCtrl, + ((char *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + return A_OK; +} +#endif /*REMOVE_PKT_LOG*/ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/event_defs.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/event_defs.h new file mode 100644 index 000000000000..c60476eb5b29 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/event_defs.h @@ -0,0 +1,1918 @@ +/* + * Copyright (c) 2012, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef EVENT_DEFS_H +#define EVENT_DEFS_H + + +typedef enum +{ + EVENT_DROP_ID = 0, + + EVENT_BAND_CLASS_CHANGE = 0x0100, /* Includes band class as payload */ + EVENT_CDMA_CH_CHANGE, /* Includes cdma channel as payload */ + EVENT_BS_P_REV_CHANGE, /* Includes BS p_rev as payload */ + EVENT_P_REV_IN_USE_CHANGE, /* Includes p_rev_in_use as payload */ + EVENT_SID_CHANGE, /* Includes SID as payload */ + EVENT_NID_CHANGE, /* Includes NID as payload */ + EVENT_PZID_CHANGE, /* Includes PZID as payload */ + EVENT_PDE_SESSION_END, /* No payload */ + EVENT_OP_MODE_CHANGE, /* Includes operation mode as payload */ + EVENT_MESSAGE_RECEIVED, /* Includes channel and message ID as + payload */ + EVENT_MESSAGE_TRANSMITTED, /* Includes channel and message ID as + payload */ + EVENT_TIMER_EXPIRED, /* Includes timer ID as payload */ + EVENT_COUNTER_THRESHOLD, /* Includes counter ID as payload */ + EVENT_CALL_PROCESSING_STATE_CHANGE, /* Includes new state and old state as + payload */ + EVENT_CALL_CONTROL_INSTANTIATED, /* Includes con_ref as payload */ + EVENT_CALL_CONTROL_STATE_CHANGE, /* Includes con_ref, old substate and + new substate as payload */ + EVENT_CALL_CONTROL_TERMINATED, /* Includes con_ref as payload */ + EVENT_REG_ZONE_CHANGE, /* Includes reg_zone as payload */ + EVENT_SLOTTED_MODE_OPERATION, /* Includes enter/exit bit as payload */ + EVENT_QPCH_IN_USE, /* Includes enable/disable bit as payload */ + EVENT_IDLE_HANDOFF, /* Includes pn_offset as payload */ + EVENT_ACCESS_HANDOFF, /* Includes pn_offset as payload */ + EVENT_ACCESS_PROBE_HANDOFF, /* Includes pn_offset as payload */ + EVENT_SOFT_HANDOFF, + /* Includes pn_offsets of each BS in aset and indicators whether BS in SCH + aset*/ + EVENT_HARD_HANDOFF_FREQ_CHANGE, + /* Includes pn_offsets of each BS in aset and indicators whether BS in SCH + aset*/ + EVENT_HARD_HANDOFF_FRAME_OFFSET_CHANGE, + /* Includes pn_offsets of each BS in aset and indicators whether BS in SCH + aset*/ + EVENT_HARD_HANDOFF_DISJOINT_ASET, + /* Includes pn_offsets of each BS in aset and indicators whether BS in SCH + aset*/ + EVENT_UNSUCCESSFUL_HARD_HANDOFF, /* No payload */ + EVENT_TMSI_ASSIGNED, /* Includes TMSI as payload */ + EVENT_SERVICE_NEGOTIATION_COMPLETED,/* No payload */ + EVENT_SO_NEGOTIATION_COMPLETED, /* No payload */ + EVENT_ENTER_CONTROL_HOLD_MODE, /* No payload */ + EVENT_EXIT_CONTROL_HOLD_MODE, /* No payload */ + EVENT_START_FWD_SUPP_BURST_ASSGN, /* Includes SCH rate as payload */ + EVENT_END_FWD_SUPP_BURST_ASSGN, /* No payload */ + EVENT_START_REV_SUPP_BURST_ASSGN, /* Includes SCH rate as payload */ + EVENT_END_REV_SUPP_BURST_ASSGN, /* No payload */ + EVENT_DTX, /* No payload */ + EVENT_T_ADD_ABORT, /* No payload */ + EVENT_CH_IND_CHANGE, /* Include ch_ind as payload */ + EVENT_TRANSMITTER_DISABLED, /* No payload */ + EVENT_TRANSMITTER_ENABLED, /* No payload */ + EVENT_SMS_RECEIVED, /* No payload */ + EVENT_SMS_SENT, /* No payload */ + EVENT_INACTIVITY_TIMER_EXPIRED, /* No payload */ + EVENT_DORMANT_TIMER_EXPIRED, /* No payload */ + EVENT_ACCESS_ATTEMPT_FAIL_MAX_PROBES_SENT, /* No payload */ + EVENT_ACCESS_ATTEMPT_FAIL_LOSS_OF_PC_OR_FCCC, /* No payload */ + EVENT_PCH_ACQUIRED, /* Includes pagech and pn_offset + as payload */ + EVENT_BCCH_ACQUIRED, /* Includes walsh code for BCCH and + pn_offset as payload */ + EVENT_FFCH_ACQUIRED, /* Payload: 14 bytes */ + EVENT_FDCCH_ACQUIRED, /* Payload: 14 bytes */ + EVENT_FFCH_PLUS_DCCH_ACQUIRED, /* No payload */ + EVENT_REGISTRATION_PERFORMED, /* Includes reg_type as payload */ + EVENT_NEW_SYSTEM_IDLE_HANDOFF, /* No payload */ + EVENT_SYSTEM_RESELECTION, /* Includes ecio and ps as payload */ + EVENT_RESCAN, /* No payload */ + EVENT_PROTOCOL_MISMATCH, /* No payload */ + EVENT_LOCK, /* No payload */ + EVENT_UNLOCK, /* No payload */ + EVENT_ACCESS_DENIED, /* No payload */ + EVENT_NDSS_OFF, /* No payload */ + EVENT_RELEASE, /* Payload: 1 byte */ + EVENT_ERROR, /* No payload */ + EVENT_REDIRECTION, /* No payload */ + EVENT_REGISTRATION_REJECTED, /* No payload */ + EVENT_WRONG_SYSTEM, /* No payload */ + EVENT_WRONG_NETWORK, /* No payload */ + EVENT_LOSS_OF_ACQ_AFTER_SLEEP, /* No payload */ + EVENT_POWER_DOWN, /* No payload */ + EVENT_CALL_RELEASE_REQUEST, /* No payload */ + EVENT_SERVICE_INACTIVE, /* No payload */ + EVENT_EXTENDED_RELEASE, /* No payload */ + + EVENT_HDR_MSG_RX, /* protocol, msg- 3 bytes */ + EVENT_HDR_RXMSG_IGNORED_STATE, /* protocol, msg- 3 bytes */ + EVENT_HDR_RXMSG_IGNORED_SEQ, /* protocol, msg- 3 bytes */ + EVENT_HDR_TXMSG_ACKED, /* protocol, msg- 3 bytes */ + EVENT_HDR_TXMSG_DROPPED, /* protocol, msg- 3 bytes */ + EVENT_HDR_STATE_CHANGE, /* protocol, from, to - 5 bytes */ + EVENT_HDR_ALMP_OBEYING_REDIRECTION, /* No payload */ + EVENT_HDR_ALMP_CONNECTION_CLOSED, /* No payload */ + EVENT_HDR_ALMP_T_SD_RESELECT, /* No payload */ + EVENT_HDR_ALMP_CONNECTION_OPENED, /* No payload */ + EVENT_HDR_HMP_QUEUED_MSG, /* protocol, msg- 3 bytes */ + EVENT_HDR_HMP_SENT_MSG, /* protocol, msg, chan, is_reliable - 5 bytes */ + EVENT_HDR_HMP_ABORTING_ACMAC_ACTIVATION, /* No payload */ + EVENT_HDR_IDLE_T_CONFIG_RSP, /* No payload */ + EVENT_HDR_IDLE_T_AT_SETUP, /* No payload */ + EVENT_HDR_IDLE_T_SUSPEND, /* No payload */ + EVENT_HDR_IDLE_CONNECTION_DENIED, /* No payload */ + EVENT_HDR_INIT_T_SYNC_ACQ, /* No payload */ + EVENT_HDR_INIT_PROTOCOL_MISMATCH, /* No payload */ + EVENT_HDR_OVHD_INFO_CURRENT, /* No payload */ + EVENT_HDR_OVHD_T_QC_SUPERVISION, /* No payload */ + EVENT_HDR_OVHD_T_SP_SUPERVISION, /* No payload */ + EVENT_HDR_OVHD_T_AP_SUPERVISION, /* No payload */ + EVENT_HDR_OVHD_IGNORED_MSG_UNEXPECTED_LINK, /* msg, exp_link.chan_num, + exp_link.pilot, rx_link.chan_num, + rx_link.pilot - 10 bytes */ + EVENT_HDR_OVHD_IGNORED_SP_MSG_DIFF_SEC_SIG, /* exp_sig, rx_sig - 8 bytes */ + EVENT_HDR_OVHD_IGNORED_AP_MSG_DIFF_ACC_SIG, /* exp_sig, rx_sig - 8 bytes */ + EVENT_HDR_OVHD_IGNORED_SP_MSG_DIFF_SEC_ID, /* No payload */ + EVENT_HDR_OVHD_SP_MSG_RX, /* No payload */ + EVENT_HDR_OVHD_AP_MSG_RX, /* No payload */ + EVENT_HDR_RUP_T_CONNECTION_SETUP, /* No payload */ + EVENT_HDR_SLP_MAX_RETRIES, /* msg - 2 bytes */ + EVENT_HDR_LMAC_ACQ_FAIL_PILOT, /* No payload */ + EVENT_HDR_LMAC_ACQ_SUCCESS, /* No payload */ + EVENT_HDR_LMAC_NETWORK_LOST, /* No payload */ + EVENT_HDR_LMAC_IDLE_HO, /* new_pilot - 2 bytes */ + EVENT_HDR_LMAC_CHAN_CHANGE_COMPLETE, /* No payload */ + EVENT_HDR_LMAC_ACCESS_HO_NEEDED, /* suggested_pilot - 2 bytes */ + EVENT_HDR_LMAC_ACCESS_HO_COMPLETE, /* new_pilot - 2 bytes */ + EVENT_HDR_LMAC_ACQUIRE, /* channel 2 bytes */ + EVENT_HDR_LMAC_CHANGING_CC_HASH, /* cc_hash - 1 byte */ + EVENT_HDR_LMAC_IDLE_CHAN_CHANGE, /* channel - 2 bytes */ + EVENT_HDR_CMAC_T_SUPERVISION, /* No payload */ + EVENT_HDR_AMAC_START_ACCESS, /* No payload */ + EVENT_HDR_AMAC_PROBING_STOPPED, /* No payload */ + EVENT_HDR_AMAC_ACCESS_COMPLETE, /* No payload */ + EVENT_HDR_AMAC_ACCESS_ABORTED, /* No payload */ + EVENT_HDR_AMAC_MAX_PROBES, /* No payload */ + EVENT_HDR_FMAC_DROP_PKT, /* No payload */ + EVENT_HDR_RMAC_T_RATE_LIMIT, /* No payload */ + EVENT_HDR_RMAC_TX_STARTED, /* No payload */ + EVENT_HDR_RMAC_TX_STOPPED, /* No payload */ + EVENT_HDR_SMP_T_KEEP_ALIVE, /* No payload */ + EVENT_HDR_AMP_ASSIGN_MSG_IGNORED_FRESH, /* No payload */ + EVENT_HDR_AMP_T_AT_RESPONSE, /* No payload */ + EVENT_HDR_AMP_T_DUAL_ADDRESS, /* No payload */ + EVENT_HDR_SCP_BEGIN_CONFIGURATION, /* No payload */ + EVENT_HDR_SCP_T_CONFIG_RSP, /* No payload */ + EVENT_HDR_SCP_T_AN_INIT_STATE, /* No payload */ + + EVENT_WCDMA_L1_STATE, /* l1_state - 1 byte */ + EVENT_WCDMA_IMSI, /* IMSI - 9 bytes */ + EVENT_GSM_L1_STATE, /* GSM l1_state - 1 byte */ + EVENT_RANDOM_ACCESS_REQUEST, /* GSM Random Access Request - 4 bytes */ + EVENT_HIGH_LEVEL_CALL_PROCESSING_STATE_CHANGE, /* Puma requested event */ + /* (same payload as CALL_PROCESSING_STATE_CHANGE) */ + EVENT_ENCRYPTION_FAILURE, /* Puma event, no payload */ + EVENT_ACCT_BLOCKED, /* Puma event, no payload */ + EVENT_COMMON_CHANNEL_MONITORED, /* Puma event, 1 byte payload */ + EVENT_SOFT_HANDOFF_V2, /* Puma event, 14 byte payload */ + EVENT_HARD_HANDOFF_FREQ_CHANGE_V2, /* Puma event, 14 byte payload */ + EVENT_HARD_HANDOFF_FRAME_OFFSET_CHANGE_V2, /* Puma event, 14 byte payload */ + EVENT_HARD_HANDOFF_DISJOINT_ASET_V2, /* Puma event, 14 byte payload */ + EVENT_WCDMA_NEW_REFERENCE_CELL, + EVENT_CALL_CONTROL_CONREF_CHANGE, /* Puma event, 2 byte payload */ + + EVENT_GPS_SESSION_BEGIN, + EVENT_GPS_SESSION_END, + EVENT_GPS_WAITING_ON_SA, + EVENT_GPS_PPM_START, + EVENT_GPS_PPM_RESULTS, + EVENT_GPS_PPM_END, + EVENT_GPS_VISIT_BEGIN, + EVENT_GPS_VISIT_END, + EVENT_GPS_CDMA_RESUMED_AFTER_GPS_VISIT, + EVENT_GPS_PD_SESSION_BEGIN, + EVENT_GPS_PD_SESSION_END, /* Payload: 1 byte PDSM substate */ + EVENT_GPS_IS801_RX, /* Payload, 1 byte msg_type */ + EVENT_GPS_IS801_TX, /* Payload: 1 byte msg_type */ + EVENT_POWERUP, + EVENT_WCDMA_ASET, + EVENT_CM_CALL_STATE, /* (1 byte payload: overall call state) */ + EVENT_CM_OPERATIONAL_MODE, /* (1 byte payload: op mode) */ + EVENT_CM_SYSTEM_MODE, /* (1 byte payload: sys_mode) */ + + EVENT_DEEP_SLEEP, /* no payload */ + EVENT_WAKEUP, /* unsigned long (4 bytes) payload */ + EVENT_ACQUISITION_MODE, /* unsigned char (1 byte) payload */ + EVENT_ACQUISITION_TYPE, /* unsigned char (1 byte) payload */ + EVENT_ACP_EXIT, /* unsigned char (1 byte) payload */ + EVENT_CDMA_EXIT, /* unsigned char (1 byte) payload */ + + EVENT_HDR_HYBRID_POWER_SAVE, /* No payload */ + EVENT_HDR_DEEP_SLEEP, /* No payload */ + EVENT_HDR_RESELECTION, /* No payload */ + EVENT_SAM_LOCK_GRANTED, /* +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include +#endif + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + +void vos_event_report_payload(v_U16_t event_Id, v_U16_t length, v_VOID_t *pPayload); +/*--------------------------------------------------------------------------- + Allocate an event payload holder +---------------------------------------------------------------------------*/ +#define WLAN_VOS_DIAG_EVENT_DEF( payload_name, payload_type ) \ + payload_type(payload_name) + +/*--------------------------------------------------------------------------- + Report the event +---------------------------------------------------------------------------*/ +#define WLAN_VOS_DIAG_EVENT_REPORT( payload_ptr, ev_id ) \ + do \ + { \ + vos_event_report_payload( ev_id, \ + sizeof( *(payload_ptr) ), \ + (void *)(payload_ptr) ); \ + \ + } while (0) + +#else /* FEATURE_WLAN_DIAG_SUPPORT */ + +#define WLAN_VOS_DIAG_EVENT_DEF( payload_name, payload_type ) +#define WLAN_VOS_DIAG_EVENT_REPORT( payload_ptr, ev_id ) + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void vos_log_wlock_diag(uint32_t reason, const char *wake_lock_name, + uint32_t timeout, uint32_t status); +#else +static inline void vos_log_wlock_diag(uint32_t reason, + const char *wake_lock_name, + uint32_t timeout, uint32_t status) +{ + +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __I_VOS_DIAG_CORE_EVENT_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_diag_core_log.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_diag_core_log.h new file mode 100644 index 000000000000..04f4c349d3a3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_diag_core_log.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_DIAG_CORE_LOG_H ) +#define __I_VOS_DIAG_CORE_LOG_H + +/**========================================================================= + + \file i_vos_diag_core_event.h + + \brief android-specific definitions for vOSS DIAG logs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include +#endif + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +//FIXME To be removed when DIAG support is added. This definiton should be +//picked from log.h file above. +typedef struct +{ + /* Specifies the length, in bytes of the entry, including this header. */ + v_U16_t len; + + /* Specifies the log code for the entry*/ + v_U16_t code; + + /*Time Stamp lo*/ + v_U32_t ts_lo; + + /*Time Stamp hi*/ + v_U32_t ts_hi; +}__packed log_hdr_type; + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void vos_log_set_code (v_VOID_t *ptr, v_U16_t code); +void vos_log_set_length (v_VOID_t *ptr, v_U16_t length); +void vos_log_set_timestamp (v_VOID_t *plog_hdr_ptr); +void vos_log_submit(v_VOID_t *plog_hdr_ptr); + +/*--------------------------------------------------------------------------- + Allocate an event payload holder +---------------------------------------------------------------------------*/ + +#define WLAN_VOS_DIAG_LOG_ALLOC( payload_ptr, payload_type, log_code ) \ + do \ + { \ + payload_ptr = ( payload_type *)vos_mem_malloc(sizeof(payload_type));\ + \ + if( payload_ptr ) \ + { \ + vos_mem_zero(payload_ptr, sizeof(payload_type)); \ + vos_log_set_code(payload_ptr, log_code); \ + vos_log_set_length(payload_ptr, sizeof(payload_type)); \ + } \ + } while (0) + +/*--------------------------------------------------------------------------- + Report the event +---------------------------------------------------------------------------*/ +#define WLAN_VOS_DIAG_LOG_REPORT( payload_ptr ) \ + do \ + { \ + if( payload_ptr) \ + { \ + vos_log_submit( payload_ptr); \ + vos_mem_free(payload_ptr); \ + } \ + } while (0) + +/*--------------------------------------------------------------------------- + Free the payload +---------------------------------------------------------------------------*/ +#define WLAN_VOS_DIAG_LOG_FREE( payload_ptr ) \ + do \ + { \ + if( payload_ptr) \ + { \ + vos_mem_free(payload_ptr); \ + } \ + } while (0) + + +#else /* FEATURE_WLAN_DIAG_SUPPORT */ + +#define WLAN_VOS_DIAG_LOG_ALLOC( payload_ptr, payload_type, log_code ) +#define WLAN_VOS_DIAG_LOG_REPORT( payload_ptr ) +#define WLAN_VOS_DIAG_LOG_FREE( payload_ptr ) + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __I_VOS_DIAG_CORE_LOG_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_event.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_event.h new file mode 100644 index 000000000000..35afc36e9de6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_event.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_EVENT_H ) +#define __I_VOS_EVENT_H + +/**========================================================================= + + \file i_vos_event.h + + \brief Linux-specific definitions for vOSS Events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define LINUX_EVENT_COOKIE 0x12341234 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) +#define INIT_COMPLETION(event) reinit_completion(&event) +#endif + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +typedef struct evt +{ + struct completion complete; + v_U32_t cookie; +} vos_event_t; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __I_VOS_EVENT_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_list.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_list.h new file mode 100644 index 000000000000..119531c78c3a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_list.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_LIST_H ) +#define __I_VOS_LIST_H + +/**========================================================================= + + \file i_vos_list.h + + \brief Linux-specific definitions for vOSS lists + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +typedef struct vos_linux_list_s +{ + struct list_head anchor; + v_SIZE_t count; + struct mutex lock; + v_U32_t cookie; +} vos_list_t; + +typedef struct list_head vos_list_node_t; + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __I_VOS_LIST_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h new file mode 100644 index 000000000000..f1d29dc06412 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_LOCK_H ) +#define __I_VOS_LOCK_H + +/**========================================================================= + + \file i_vos_lock.h + + \brief Linux-specific definitions for vOSS Locks + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +typedef struct vos_lock_s +{ + struct mutex m_lock; + v_U32_t cookie; + int processID; + v_U32_t state; + v_U8_t refcount; +} vos_lock_t; + +typedef spinlock_t vos_spin_lock_t; + +typedef struct wlan_wake_lock { +#if defined CONFIG_CNSS + struct wakeup_source lock; +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + struct wake_lock lock; +#else + int lock; +#endif +} vos_wake_lock_t; + +typedef void *runtime_pm_context_t; +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __I_VOS_LOCK_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_packet.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_packet.h new file mode 100644 index 000000000000..72f93a3e0b94 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_packet.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_PACKET_H ) +#define __I_VOS_PACKET_H + +/**========================================================================= + + \file i_vos_packet.h + + \brief virtual Operating System Servies (vOSS) + + Network Protocol packet/buffer internal include file + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "adf_os_types.h" +/* + * Rx Packet Struct + * rssi field is normalized to -96 dBm as normal noise floor by adding + * -96 to snr. All the configured thresholds in the driver assume that + * noise floor is -96 dBm. + * rssi_raw field is signal strength of the received frame relative + * to the noise floor recorded in hardware. + */ +typedef struct +{ + u_int8_t channel; + u_int8_t snr; + u_int32_t rssi; + u_int32_t timestamp; + u_int8_t *mpdu_hdr_ptr; + u_int8_t *mpdu_data_ptr; + u_int32_t mpdu_len; + u_int32_t mpdu_hdr_len; + u_int32_t mpdu_data_len; + u_int8_t offloadScanLearn:1; + u_int8_t roamCandidateInd:1; + u_int8_t scan:1; + u_int8_t dpuFeedback; + u_int8_t sessionId; + u_int8_t scan_src; + u_int32_t rssi_raw; + u_int32_t tsf_delta; +}t_packetmeta, *tp_packetmeta; + +/* implementation specific vos packet type */ +struct vos_pkt_t +{ + /* Packet Meta Information */ + t_packetmeta pkt_meta; + + /* Pointer to Packet */ + void *pkt_buf; +}; + +#endif // !defined( __I_VOS_PACKET_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_timer.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_timer.h new file mode 100644 index 000000000000..0c5f797dd2b0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_timer.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_TIMER_H ) +#define __I_VOS_TIMER_H + +/**========================================================================= + + \file i_vos_timer.h + + \brief Linux-specific definitions for vOSS packets + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +typedef struct vos_timer_platform_s +{ + struct timer_list Timer; + int threadID; + v_U32_t cookie; + spinlock_t spinlock; + +} vos_timer_platform_t; + +/* + * TODOs: Need to add deferred timer implementation + * +*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __I_VOS_TIMER_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_trace.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_trace.h new file mode 100644 index 000000000000..b92f98babd77 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_trace.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_TRACE_H ) +#define __I_VOS_TRACE_H + +#if !defined(__printf) +#define __printf(a,b) +#endif + +/**========================================================================= + + \file i_vos_trace.h + + \brief Linux-specific definitions for VOSS trace + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +/**---------------------------------------------------------------------------- + + \brief VOS_TRACE() / vos_trace_msg() - Trace / logging API + + Users wishing to add tracing information to their code should use + VOS_TRACE. VOS_TRACE() will compile into a call to vos_trace_msg() when + tracing is enabled. + + \param module - module identifier. A member of the VOS_MODULE_ID + enumeration that identifies the module issuing the trace message. + + \param level - trace level. A member of the VOS_TRACE_LEVEL + enumeration indicating the severity of the condition causing the + trace message to be issued. More severe conditions are more + likely to be logged. + + \param strFormat - format string. The message to be logged. This format + string contains printf-like replacement parameters, which follow + this parameter in the variable argument list. + + \return nothing + + --------------------------------------------------------------------------*/ +void __printf(3,4) vos_trace_msg( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, + char *strFormat, ... ); + +void vos_trace_hex_dump( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, + void *data, int buf_len ); + +void vos_trace_display(void); + +void vos_trace_setValue( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, v_U8_t on ); + +void vos_trace_set_module_trace_level(VOS_MODULE_ID module, uint32_t level); + +// VOS_TRACE is the macro invoked to add trace messages to code. See the +// documenation for vos_trace_msg() for the parameters etc. for this function. +// +// NOTE: Code VOS_TRACE() macros into the source code. Do not code directly +// to the vos_trace_msg() function. +// +// NOTE 2: vos tracing is totally turned off if WLAN_DEBUG is *not* defined. +// This allows us to build 'performance' builds where we can measure performance +// without being bogged down by all the tracing in the code. +#if defined( WLAN_DEBUG ) +#define VOS_TRACE vos_trace_msg +#define VOS_TRACE_HEX_DUMP vos_trace_hex_dump +#else +#define VOS_TRACE(arg...) +#define VOS_TRACE_HEX_DUMP(arg...) +#endif + + +void __printf(3,4) vos_snprintf(char *strBuffer, unsigned int size, + char *strFormat, ...); +#define VOS_SNPRINTF vos_snprintf + +#ifdef VOS_ENABLE_TRACING + + +#define VOS_ASSERT( _condition ) do { \ + if ( ! ( _condition ) ) \ + { \ + printk(KERN_CRIT "VOS ASSERT in %s Line %d\n", __func__, __LINE__); \ + WARN_ON(1); \ + } \ + } while(0) + +#else + + + // This code will be used for compilation if tracing is to be compiled out + // of the code so these functions/macros are 'do nothing' + VOS_INLINE_FN void vos_trace_msg( VOS_MODULE_ID module, ... ){} + + #define VOS_ASSERT( _condition ) + +#endif + +#ifdef PANIC_ON_BUG +#ifdef CONFIG_X86 +/* BUG_ON does not call panic on x86,so call panic directly */ +#define VOS_BUG( _condition ) do { \ + if ( ! ( _condition ) ) \ + { \ + printk(KERN_CRIT "VOS BUG in %s Line %d\n", __func__, __LINE__); \ + dump_stack(); \ + panic("BUG"); \ + } \ + } while(0) +#else +#define VOS_BUG( _condition ) do { \ + if ( ! ( _condition ) ) \ + { \ + printk(KERN_CRIT "VOS BUG in %s Line %d\n", __func__, __LINE__); \ + BUG_ON(1); \ + } \ + } while(0) +#endif + +#else + +#define VOS_BUG( _condition ) do { \ + if ( ! ( _condition ) ) \ + { \ + printk(KERN_CRIT "VOS BUG in %s Line %d\n", __func__, __LINE__); \ + WARN_ON(1); \ + } \ + } while(0) + +#endif + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_types.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_types.h new file mode 100644 index 000000000000..756234d33189 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_types.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __I_VOS_TYPES_H ) +#define __I_VOS_TYPES_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**========================================================================= + + \file i_vos_Types.h + + \brief virtual Operating System Servies (vOSS) Types + + Linux specific basic type definitions + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +/* + * 1. GNU C/C++ Compiler + * + * How to detect gcc : __GNUC__ + * How to detect gcc version : + * major version : __GNUC__ (2 = 2.x, 3 = 3.x, 4 = 4.x) + * minor version : __GNUC_MINOR__ + * + * 2. Microsoft C/C++ Compiler + * + * How to detect msc : _MSC_VER + * How to detect msc version : + * _MSC_VER (1200 = MSVC 6.0, 1300 = MSVC 7.0, ...) + * + */ + +// MACROs to help with compiler and OS specifics. +// \note: may need to get a little more sophisticated than this and define +// these to specific 'VERSIONS' of the compiler and OS. Until we have a +// need for that, lets go with this. +#if defined( _MSC_VER ) + +#define VOS_COMPILER_MSC +#define VOS_OS_WINMOBILE // assuming that if we build with MSC, OS is WinMobile + +#elif defined( __GNUC__ ) + +#define VOS_COMPILER_GNUC +#define VOS_OS_LINUX // assuming if building with GNUC, OS is Linux + +#endif + + +// VOS definitions (compiler specific) for Packing structures. Note that the +// Windows compiler defines a way to pack a 'range' of code in a file. To +// accomodate this, we have to include a file that has the packing #pragmas +// These files are called +// vos_pack_range_n_start.h where "n" is the packing aligment. For example, +// vos_pack_range_2_start.h is included in the file where you want to +// start packing on a 2 byte alignment. vos_pack_range_end.h is included +// in the file where you want to stop the packing. +// +// Other compilers allow packing individual strucutres so we have a series +// of macros that are added to the structure to define the packing attributes. +// For example, VOS_PACK_STRUCT_2 will add the attributes to pack an +// individual structure on a 2 byte boundary. +// +// So what does a coder have to do to properly pack a structure for all the +// supported compilers? You have to add two includes around *all* the +// structures you want packed the same way and you also have to add the +// VOS_PACK_STRUCT_n macros to the individual structures. +// +// For example to properly pack myStruct on a 2 byte boundary for all +// voss supported compilers, the following needs coded... +// +// +// #include +// +// typedef struct +// { +// unsigned char c; +// long int i; +// } myStruct VOS_PACK_STRUCT_2; +// +// +// note... you can include other structure definitions in here that have the +// same 2 byte packing +// +// #include + + +// /todo: not sure what the flag is to identify the Microsoft compiler for WinMobile +// Let's leave this out for now and just include the defintions for WinMobile. Need +// to address this when we move to support other operating systems. Probably best to +// define some of our own 'types' or preprocessor flags like VOS_COMPILER_TYPE, +// VOS_OS_TYPE, etc. and then all our code can base on those flags/types independent +// of the operating system, compiler, etc. +#if defined( VOS_COMPILER_MSC ) + + +#define VOS_INLINE_FN __inline + +// does nothing on Windows. packing individual structs is not +// supported on the Windows compiler. +#define VOS_PACK_STRUCT_1 +#define VOS_PACK_STRUCT_2 +#define VOS_PACK_STRUCT_4 +#define VOS_PACK_STRUCT_8 +#define VOS_PACK_STRUCT_16 + +#elif defined( VOS_COMPILER_GNUC ) + +#define VOS_INLINE_FN static inline + +#else +#error "Compiling with an unknown compiler!!" +#endif + + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/// unsigned 8-bit types +typedef u8 v_U8_t; +typedef u8 v_UCHAR_t; +typedef u8 v_BYTE_t; + +/// unsigned 16-bit types +typedef u16 v_U16_t; +typedef unsigned short v_USHORT_t; + +/// unsigned 32-bit types +typedef u32 v_U32_t; +// typedef atomic_t v_U32AT_t; +typedef unsigned long v_ULONG_t; + +/// unsigned 64-bit types +typedef u64 v_U64_t; + +/// unsigned integer types +typedef unsigned int v_UINT_t; + +/// signed 8-bit types +typedef s8 v_S7_t; +typedef signed char v_SCHAR_t; + +/// signed 16-bit types +typedef s16 v_S15_t; +typedef signed short v_SSHORT_t; + +/// signed 32-bit types +typedef s32 v_S31_t; +typedef signed long v_SLONG_t; + +/// signed integer types +typedef signed int v_SINT_t; + +/// Boolean types +typedef unsigned char v_BOOL_t; + +/// void type +#define v_VOID_t void + +#endif // __I_VOSS_TYPES_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/log_codes.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/log_codes.h new file mode 100644 index 000000000000..78f2ac2072d2 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/log_codes.h @@ -0,0 +1,2082 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef LOG_CODES_H +#define LOG_CODES_H + +/*=========================================================================== + + Log Code Definitions + +General Description + This file contains log code definitions and is shared with the tools. + +===========================================================================*/ + +/* DO NOT MODIFY THIS FILE WITHOUT PRIOR APPROVAL +** +** Log codes, by design, are a tightly controlled set of values. +** Developers may not create log codes at will. +** +** Request new logs using the following process: +** +** 1. Send email to asw.diag.request requesting log codassignments. +** 2. Identify the log needed by name. +** 3. Provide a brief description for the log. +** +*/ + +/*=========================================================================== + + Edit History + +$Header: //source/qcom/qct/core/services/diag/api/inc/main/latest/log_codes.h#9 $ + +when who what, where, why +-------- --- ---------------------------------------------------------- +07/30/09 dhao Consolidate log_codes_apps.h +07/30/09 dhao Add Last log code definition for Equip ID 11 +06/26/09 dhao Update format the macro +06/24/09 sar Reverted last change. +06/24/09 sar Added log code for LOG_MC_STM_C. +11/02/01 sfh Featurize common NAS log codes for UMTS. +10/30/01 sfh Added log code for LOG_GPS_FATPATH_INFO_C. +10/24/01 sfh Added updates for UMTS equipment ID and log codes. +06/27/01 lad Added multiple equipment ID support. +05/22/01 sfh Reserved log codes 158 - 168. +05/21/01 sfh Keep confusing XXX_BASE_C names for backwards compatibility. +05/16/01 sfh Reserved log code 155. +05/08/01 sfh Reserved log codes 150 - 154. +04/06/01 lad Added definitions of base IDs (such as LOG_WCDMA_BASE_C). + This is currently using temporary ID values in the 0x1000 + range. +02/23/01 lad Created file from DMSS log.h. Log codes only + +===========================================================================*/ +#include + +/* ------------------------------------------------------------------------- + * Data Declarations + * ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- + * Log equipment IDs. + * The most significant 4 bits of the 16 bit log code is the equipment ID. + * Orignally, the mobile was to have an ID, and base stations and other + * IDs. As QCT technology diversifies, new equipment IDs are assigned to new + * technology areas. 0x2000 and 0x3000 are reserved for legacy reasons, so + * the first + * addition starts at 0x4000. + * ------------------------------------------------------------------------- */ + +#define LOG_1X_BASE_C ((v_U16_t) 0x1000) +#define LOG_WCDMA_BASE_C ((v_U16_t) 0x4000) +#define LOG_GSM_BASE_C ((v_U16_t) 0x5000) +#define LOG_LBS_BASE_C ((v_U16_t) 0x6000) +#define LOG_UMTS_BASE_C ((v_U16_t) 0x7000) +#define LOG_TDMA_BASE_C ((v_U16_t) 0x8000) +#define LOG_DTV_BASE_C ((v_U16_t) 0xA000) +#define LOG_APPS_BASE_C ((v_U16_t) 0xB000) +#define LOG_LTE_BASE_C ((v_U16_t) (0xB000 + 0x0010)) +#define LOG_LTE_LAST_C ((v_U16_t) 0xB1FF) +#define LOG_WIMAX_BASE_C ((v_U16_t) 0xB400) +#define LOG_DSP_BASE_C ((v_U16_t) 0xC000) + +#define LOG_TOOLS_BASE_C ((v_U16_t) 0xF000) + +/* LOG_BASE_C is what was used before expanding the use of the equipment ID. + * TODO: Once all targets are using the "core" diag system, this should be + * ommitted. */ +#define LOG_BASE_C LOG_1X_BASE_C + +/* ------------------------------------------------------------------------- + * Log Codes + * These codes identify the kind of information contained in a log entry. + * They are used in conjunction with the 'code' field of the log entry + * header. The data types associated with each code are defined below. + * ------------------------------------------------------------------------- */ + +/* The upper 4 bits of the 16 bit log entry code specify which type + * of equipment created the log entry. */ + +/* 0 Mobile Station temporal analyzer entry */ +#define LOG_TA_C (0x0 + LOG_1X_BASE_C) + +/* 1 AGC values and closed loop power control entry */ +#define LOG_AGC_PCTL_C (0x1 + LOG_1X_BASE_C) + +/* 2 Forward link frame rates and types entry */ +#define LOG_F_MUX1_C (0x2 + LOG_1X_BASE_C) + +/* 3 Reverse link frame rates and types entry */ +#define LOG_R_MUX1_C (0x3 + LOG_1X_BASE_C) + +/* 4 Access channel message entry */ +#define LOG_AC_MSG_C (0x4 + LOG_1X_BASE_C) + +/* 5 Reverse link traffic channel message entry */ +#define LOG_R_TC_MSG_C (0x5 + LOG_1X_BASE_C) + +/* 6 Sync channel message entry */ +#define LOG_SC_MSG_C (0x6 + LOG_1X_BASE_C) + +/* 7 Paging channel message entry */ +#define LOG_PC_MSG_C (0x7 + LOG_1X_BASE_C) + +/* 8 Forward link traffic channel message entry */ +#define LOG_F_TC_MSG_C (0x8 + LOG_1X_BASE_C) + +/* 9 Forward link vocoder packet entry */ +#define LOG_VOC_FOR_C (0x9 + LOG_1X_BASE_C) + +/* 10 Reverse link vocoder packet entry */ +#define LOG_VOC_REV_C (0xA + LOG_1X_BASE_C) + +/* 11 Temporal analyzer finger info only */ +#define LOG_FING_C (0xB + LOG_1X_BASE_C) + +/* 12 Searcher pathlog info (Reused old SRCH logtype) */ +#define LOG_SRCH_C (0xC + LOG_1X_BASE_C) + +/* 13 Position and speed information read from ETAK */ +#define LOG_ETAK_C (0xD + LOG_1X_BASE_C) + +/* 14 Markov frame statistics */ +#define LOG_MAR_C (0xE + LOG_1X_BASE_C) + +/* 15 New and improved temporal analyzer searcher info */ +#define LOG_SRCH2_C (0xF + LOG_1X_BASE_C) + +/* 16 The Fujitsu handset information */ +#define LOG_HANDSET_C (0x10 + LOG_1X_BASE_C) + +/* 17 Vocoder bit error rate mask */ +#define LOG_ERRMASK_C (0x11 + LOG_1X_BASE_C) + +/* 18 Analog voice channel information */ +#define LOG_ANALOG_INFO_C (0x12 + LOG_1X_BASE_C) + +/* 19 Access probe information */ +#define LOG_ACC_INFO_C (0x13 + LOG_1X_BASE_C) + +/* 20 Position & speed info read from GPS receiver */ +#define LOG_GPS_C (0x14 + LOG_1X_BASE_C) + +/* 21 Test Command information */ +#define LOG_TEST_CMD_C (0x15 + LOG_1X_BASE_C) + +/* 22 Sparse (20ms) AGC / closed loop power control entry */ +#define LOG_S_AGC_PCTL_C (0x16 + LOG_1X_BASE_C) + +/* 23 Notification of a band class change */ +#define LOG_BAND_CHANGE_C (0x17 + LOG_1X_BASE_C) + +/* 24 DM debug messages, if being logged via log services */ +#define LOG_DBG_MSG_C (0x18 + LOG_1X_BASE_C) + +/* 25 General temporal analyzer entry */ +#define LOG_GENRL_TA_C (0x19 + LOG_1X_BASE_C) + +/* 26 General temporal analyzer w/supplemental channels */ +#define LOG_GENRL_TA_SUP_CH_C (0x1A + LOG_1X_BASE_C) + +/* Featurization Removal requested by CMI +#ifdef FEATURE_PLT +*/ + +/* 27 Decoder raw bits logging */ +#define LOG_PLT_C (0x1B + LOG_1X_BASE_C) + +/* Featurization Removal requested by CMI +#else +27 EFS Usage Info - No implementation as yet +#define LOG_EFS_INFO_C (0x1B + LOG_1X_BASE_C) +#endif +*/ + +/* 28 Analog Forward Channel */ +#define LOG_ANALOG_FORW_C (0x1C + LOG_1X_BASE_C) + +/* 29 Analog Reverse Channel */ +#define LOG_ANALOG_REVS_C (0x1D + LOG_1X_BASE_C) + +/* 30 Analog Handoff Entry */ +#define LOG_ANALOG_HANDOFF_C (0x1E + LOG_1X_BASE_C) + +/* 31 FM Slot Statistis entry */ +#define LOG_ANALOG_FMSLOT_C (0x1F + LOG_1X_BASE_C) + +/* 32 FOCC Word Sync Count entry */ +#define LOG_ANALOG_WS_COUNT_C (0x20 + LOG_1X_BASE_C) + +/* 33 */ +#define LOG_RLP_PACKET_C (0x21 + LOG_1X_BASE_C) + +/* 34 */ +#define LOG_ASYNC_TCP_SEG_C (0x22 + LOG_1X_BASE_C) + +/* 35 */ +#define LOG_PACKET_DATA_IP_PACKETS_C (0x23 + LOG_1X_BASE_C) + +/* 36 */ +#define LOG_FNBDT_MESSAGE_LOG_C (0x24 + LOG_1X_BASE_C) + +/* Begin IS-2000 LOG features */ + +/* 37 RLP RX Frames logging */ +#define LOG_RLP_RX_FRAMES_C (0x25 + LOG_1X_BASE_C) + +/* 38 RLP TX Frames logging */ +#define LOG_RLP_TX_FRAMES_C (0x26 + LOG_1X_BASE_C) + +/* 39 Reserved for additions to RLP frames */ +#define LOG_RLP_RSVD1_C (0x27 + LOG_1X_BASE_C) + +/* 40 Reserved for additions to RLP frames */ +#define LOG_RLP_RSVD2_C (0x28 + LOG_1X_BASE_C) + +/* 41 Forward Link Frame Types logging */ +#define LOG_FWD_FRAME_TYPES_C (0x29 + LOG_1X_BASE_C) + +/* 42 Reverse Link Frame Types logging */ +#define LOG_REV_FRAME_TYPES_C (0x2A + LOG_1X_BASE_C) + +/* 43 Fast Forward Power Control Parameters logging */ +#define LOG_FFWD_PCTRL_C (0x2B + LOG_1X_BASE_C) + +/* 44 Reverse Power Control Parameters logging */ +#define LOG_REV_PCTRL_C (0x2C + LOG_1X_BASE_C) + +/* 45 Searcher and Finger Information logging */ +#define LOG_SRCH_FING_INFO_C (0x2D + LOG_1X_BASE_C) + +/* 46 Service Configuration logging */ +#define LOG_SVC_CONFIG_C (0x2E + LOG_1X_BASE_C) + +/* 47 Active Set Configuration logging */ +#define LOG_ASET_CONFIG_C (0x2F + LOG_1X_BASE_C) + +/* 48 Quick Paging Channel logging */ +#define LOG_QPCH_C (0x30 + LOG_1X_BASE_C) + +/* 49 RLP Statistics logging */ +#define LOG_RLP_STAT_C (0x31 + LOG_1X_BASE_C) + +/* 50 Simple Test Data Service Option logging */ +#define LOG_STDSO_C (0x32 + LOG_1X_BASE_C) + +/* 51 Pilot Phase Measurement results logging */ +#define LOG_SRCH_PPM_RES_C (0x33 + LOG_1X_BASE_C) + +/* 52 Pilot Phase Measurement Data Base logging */ +#define LOG_SRCH_PPM_DB_C (0x34 + LOG_1X_BASE_C) + +/* 53 Pilot Phase Measurement search results logging */ +#define LOG_SRCH_PPM_C (0x35 + LOG_1X_BASE_C) + +/* 54 IS-801 forward link message */ +#define LOG_GPS_FWD_MSG_C (0x36 + LOG_1X_BASE_C) + +/* 55 IS-801 reverse link message */ +#define LOG_GPS_REV_MSG_C (0x37 + LOG_1X_BASE_C) + +/* 56 GPS search session statistics */ +#define LOG_GPS_STATS_MSG_C (0x38 + LOG_1X_BASE_C) + +/* 57 GPS search results */ +#define LOG_GPS_SRCH_PEAKS_MSG_C (0x39 + LOG_1X_BASE_C) + +/* 58 Factory Testmode logging */ +#define LOG_FTM_C (0x3A + LOG_1X_BASE_C) + +/* 59 Multiple Peak Logging */ +#define LOG_SRCH_GPS_MULTI_PEAKS_INFO_C (0x3B + LOG_1X_BASE_C) + +/* 60 Post processed search results logs */ +#define LOG_SRCH_GPS_POST_PROC_C (0x3C + LOG_1X_BASE_C) + +/* 61 FULL Test Data Service Option logging */ +#define LOG_FTDSO_C (0x3D + LOG_1X_BASE_C) + +/* 62 Bluetooth logging */ +#define LOG_BT_RESERVED_CODES_BASE_C (0x3E + LOG_1X_BASE_C) +/* Keep confusing name for backwards compatibility. */ +#define LOG_BT_BASE_C LOG_BT_RESERVED_CODES_BASE_C + +/* 92 Bluetooth's last log code */ +#define LOG_BT_LAST_C (30 + LOG_BT_RESERVED_CODES_BASE_C) + +/* 93 HDR log codes */ +#define LOG_HDR_RESERVED_CODES_BASE_C (0x5D + LOG_1X_BASE_C) +/* Keep confusing name for backwards compatibility. */ +#define LOG_HDR_BASE_C LOG_HDR_RESERVED_CODES_BASE_C + +/* 143 is HDR's last log code */ +#define LOG_HDR_LAST_C (50 + LOG_HDR_RESERVED_CODES_BASE_C) + +/* 144 IS2000 DCCH Forward link channel */ +#define LOG_FOR_DCCH_MSG_C (0x90 + LOG_1X_BASE_C) +#define LOG_DCCH_FWD_C LOG_FOR_DCCH_MSG_C + +/* 145 IS2000 DCCH Forward link channel */ +#define LOG_REV_DCCH_MSG_C (0x91 + LOG_1X_BASE_C) +#define LOG_DCCH_REV_C LOG_REV_DCCH_MSG_C + +/* 146 IS2000 DCCH Forward link channel */ +#define LOG_ZREX_C (0x92 + LOG_1X_BASE_C) + +/* 147 Active set info logging, similar to ASET_CONFIG, but simpler. */ +#define LOG_ASET_INFO_C (0x93 + LOG_1X_BASE_C) + +/* 148 Pilot Phase Measurement four-shoulder-search resutlts logging */ +#define LOG_SRCH_PPM_4SHOULDER_RES_C (0x94 + LOG_1X_BASE_C) + +/* 149 Extended Pilot Phase Measurement Data Base logging */ +#define LOG_SRCH_EXT_PPM_DB_C (0x95 + LOG_1X_BASE_C) + +/* 150 GPS Visit Parameters */ +#define LOG_GPS_VISIT_PARAMETERS_C (0x96 + LOG_1X_BASE_C) + +/* 151 GPS Measurement */ +#define LOG_GPS_MEASUREMENT_C (0x97 + LOG_1X_BASE_C) + +/* 152 UIM Data */ +#define LOG_UIM_DATA_C (0x98 + LOG_1X_BASE_C) + +/* 153 STDSO plus P2 */ +#define LOG_STDSO_P2_C (0x99 + LOG_1X_BASE_C) + +/* 154 FTDSO plus P2 */ +#define LOG_FTDSO_P2_C (0x9A + LOG_1X_BASE_C) + +/* 155 Search PPM Statistics */ +#define LOG_SRCH_PPM_STATS_C (0x9B + LOG_1X_BASE_C) + +/* 156 PPP Tx Frames */ +#define LOG_PPP_TX_FRAMES_C (0x9C + LOG_1X_BASE_C) + +/* 157 PPP Rx Frames */ +#define LOG_PPP_RX_FRAMES_C (0x9D + LOG_1X_BASE_C) + +/* 158-187 SSL reserved log codes */ +#define LOG_SSL_RESERVED_CODES_BASE_C (0x9E + LOG_1X_BASE_C) +#define LOG_SSL_LAST_C (29 + LOG_SSL_RESERVED_CODES_BASE_C) + +/* 188-199 Puma reserved log codes */ +/* 188 QPCH, version 2 */ +#define LOG_QPCH_VER_2_C (0xBC + LOG_1X_BASE_C) + +/* 189 Enhanced Access Probe */ +#define LOG_EA_PROBE_C (0xBD + LOG_1X_BASE_C) + +/* 190 BCCH Frame Information */ +#define LOG_BCCH_FRAME_INFO_C (0xBE + LOG_1X_BASE_C) + +/* 191 FCCCH Frame Information */ +#define LOG_FCCCH_FRAME_INFO_C (0xBF + LOG_1X_BASE_C) + +/* 192 FDCH Frame Information */ +#define LOG_FDCH_FRAME_INFO_C (0xC0 + LOG_1X_BASE_C) + +/* 193 RDCH Frame Information */ +#define LOG_RDCH_FRAME_INFO_C (0xC1 + LOG_1X_BASE_C) + +/* 194 FFPC Information */ +#define LOG_FFPC_INFO_C (0xC2 + LOG_1X_BASE_C) + +/* 195 RPC Information */ +#define LOG_RPC_INFO_C (0xC3 + LOG_1X_BASE_C) + +/* 196 Searcher and Finger Information */ +#define LOG_SRCH_FING_INFO_VER_2_C (0xC4 + LOG_1X_BASE_C) + +/* 197 Service Configuration, version 2 */ +#define LOG_SRV_CONFIG_VER_2_C (0xC5 + LOG_1X_BASE_C) + +/* 198 Active Set Information, version 2 */ +#define LOG_ASET_INFO_VER_2_C (0xC6 + LOG_1X_BASE_C) + +/* 199 Reduced Active Set */ +#define LOG_REDUCED_ASET_INFO_C (0xC7 + LOG_1X_BASE_C) + +/* 200 Search Triage Info */ +#define LOG_SRCH_TRIAGE_INFO_C (0xC8 + LOG_1X_BASE_C) + +/* 201 RDA Frame Information */ +#define LOG_RDA_FRAME_INFO_C (0xC9 + LOG_1X_BASE_C) + +/* 202 gpsOne fatpath information */ +#define LOG_GPS_FATPATH_INFO_C (0xCA + LOG_1X_BASE_C) + +/* 203 Extended AGC */ +#define LOG_EXTENDED_AGC_C (0xCB + LOG_1X_BASE_C) + +/* 204 Transmit AGC */ +#define LOG_TRANSMIT_AGC_C (0xCC + LOG_1X_BASE_C) + +/* 205 I/Q Offset registers */ +#define LOG_IQ_OFFSET_REGISTERS_C (0xCD + LOG_1X_BASE_C) + +/* 206 DACC I/Q Accumulator registers */ +#define LOG_DACC_IQ_ACCUMULATOR_C (0xCE + LOG_1X_BASE_C) + +/* 207 Register polling results */ +#define LOG_REGISTER_POLLING_RESULTS_C (0xCF + LOG_1X_BASE_C) + +/* 208 System arbitration module */ +#define LOG_AT_SAM_C (0xD0 + LOG_1X_BASE_C) + +/* 209 Diablo searcher finger log */ +#define LOG_DIABLO_SRCH_FING_INFO_C (0xD1 + LOG_1X_BASE_C) + +/* 210 log reserved for dandrus */ +#define LOG_SD20_LAST_ACTION_C (0xD2 + LOG_1X_BASE_C) + +/* 211 log reserved for dandrus */ +#define LOG_SD20_LAST_ACTION_HYBRID_C (0xD3 + LOG_1X_BASE_C) + +/* 212 log reserved for dandrus */ +#define LOG_SD20_SS_OBJECT_C (0xD4 + LOG_1X_BASE_C) + +/* 213 log reserved for dandrus */ +#define LOG_SD20_SS_OBJECT_HYBRID_C (0xD5 + LOG_1X_BASE_C) + +/* 214 log reserved for jpinos */ +#define LOG_BCCH_SIGNALING_C (0xD6 + LOG_1X_BASE_C) + +/* 215 log reserved for jpinos */ +#define LOG_REACH_SIGNALING_C (0xD7 + LOG_1X_BASE_C) + +/* 216 log reserved for jpinos */ +#define LOG_FCCCH_SIGNALING_C (0xD8 + LOG_1X_BASE_C) + +/* 217 RDA Frame Information 2 */ +#define LOG_RDA_FRAME_INFO_2_C (0xD9 + LOG_1X_BASE_C) + +/* 218 */ +#define LOG_GPS_BIT_EDGE_RESULTS_C (0xDA + LOG_1X_BASE_C) + +/* 219 */ +#define LOG_PE_DATA_C (0xDB + LOG_1X_BASE_C) + +/* 220 */ +#define LOG_PE_PARTIAL_DATA_C (0xDC + LOG_1X_BASE_C) + +/* 221 */ +#define LOG_GPS_SINGLE_PEAK_SRCH_RESULTS_C (0xDD + LOG_1X_BASE_C) + +/* 222 */ +#define LOG_SRCH4_SAMPRAM_C (0xDE + LOG_1X_BASE_C) + +/* 223 */ +#define HDR_AN_PPP_TX_FRAMES (0xDF + LOG_1X_BASE_C) + +/* 224 */ +#define HDR_AN_PPP_RX_FRAMES (0xE0 + LOG_1X_BASE_C) + +/* 225 */ +#define LOG_GPS_SCHEDULER_TRACE_C (0xE1 + LOG_1X_BASE_C) + +/* 226 */ +#define LOG_MPEG4_YUV_FRAME_C (0xE2 + LOG_1X_BASE_C) + +/* 227 */ +#define LOG_MPEG4_CLIP_STATS_C (0xE3 + LOG_1X_BASE_C) + +/* 228 */ +#define LOG_MPEG4_CLIP_STATS_VER2_C (0xE4 + LOG_1X_BASE_C) + +/* 226-241 MMEG reserved. */ +#define LOG_MPEG_RESERVED_CODES_BASE_C (0xF1 + LOG_1X_BASE_C) + +/* 242-274 BREW reserved log range */ +#define LOG_BREW_RESERVED_CODES_BASE_C (0xF2 + LOG_1X_BASE_C) +#define LOG_BREW_LAST_C (32 + LOG_BREW_RESERVED_CODES_BASE_C) + +/* 275-339 PPP Extended Frames */ +#define LOG_PPP_FRAMES_RESERVED_CODES_BASE_C (0x113 + LOG_1X_BASE_C) +#define LOG_PPP_FRAMES_LAST_C (64 + LOG_PPP_FRAMES_RESERVED_CODES_BASE_C) + +#define LOG_PPP_EXT_FRAMED_RX_UM_C (0x113 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_FRAMED_RX_RM_C (0x114 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_FRAMED_RX_AN_C (0x115 + LOG_1X_BASE_C) + +#define LOG_PPP_EXT_FRAMED_TX_UM_C (0x123 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_FRAMED_TX_RM_C (0x124 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_FRAMED_TX_AN_C (0x125 + LOG_1X_BASE_C) + +#define LOG_PPP_EXT_UNFRAMED_RX_UM_C (0x133 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_UNFRAMED_RX_RM_C (0x134 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_UNFRAMED_RX_AN_C (0x135 + LOG_1X_BASE_C) + +#define LOG_PPP_EXT_UNFRAMED_TX_UM_C (0x143 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_UNFRAMED_TX_RM_C (0x144 + LOG_1X_BASE_C) +#define LOG_PPP_EXT_UNFRAMED_TX_AN_C (0x145 + LOG_1X_BASE_C) + +/* 340 LOG_PE_DATA_EXT_C */ +#define LOG_PE_DATA_EXT_C (0x154 + LOG_1X_BASE_C) + +/* REX Subsystem logs */ +#define LOG_MEMDEBUG_C (0x155 + LOG_1X_BASE_C) +#define LOG_SYSPROFILE_C (0x156 + LOG_1X_BASE_C) +#define LOG_TASKPROFILE_C (0x157 + LOG_1X_BASE_C) +#define LOG_COREDUMP_C (0x158 + LOG_1X_BASE_C) + +/* 341-349 REX subsystem logs */ +#define LOG_REX_RESERVED_CODES_BASE_C (0x155 + LOG_1X_BASE_C) +#define LOG_REX_LAST_C (8 + LOG_REX_RESERVED_CODES_BASE_C) + +/* 350 LOG_PE_PARTIAL_DATA_EXT_C */ +#define LOG_PE_PARTIAL_DATA_EXT_C (0x15E + LOG_1X_BASE_C) + +/* 351 LOG_DIAG_STRESS_TEST_C */ +#define LOG_DIAG_STRESS_TEST_C (0x15F + LOG_1X_BASE_C) + +/* 352 LOG_WMS_READ_C */ +#define LOG_WMS_READ_C (0x160 + LOG_1X_BASE_C) + +/* 353 Search Triage Info Version 2 */ +#define LOG_SRCH_TRIAGE_INFO2_C (0x161 + LOG_1X_BASE_C) + +/* 354 RLP Rx FDCH Frames */ +#define LOG_RLP_RX_FDCH_FRAMES_C (0x162 + LOG_1X_BASE_C) + + +/* 355 RLP Tx FDCH Frames */ +#define LOG_RLP_TX_FDCH_FRAMES_C (0x163 + LOG_1X_BASE_C) + +/* 356-371 QTV subsystem logs */ +#define LOG_QTV_RESERVED_CODES_BASE_C (0x164 + LOG_1X_BASE_C) +#define LOG_QTV_LAST_C (15 + LOG_QTV_RESERVED_CODES_BASE_C) + +/* 372 Searcher 4 1X */ +#define LOG_SRCH4_1X_C (0x174 + LOG_1X_BASE_C) + +/* 373 Searcher sleep statistics */ +#define LOG_SRCH_SLEEP_STATS_C (0x175 + LOG_1X_BASE_C) + +/* 374 Service Configuration, version 3 */ +#define LOG_SRV_CONFIG_VER_3_C (0x176 + LOG_1X_BASE_C) + +/* 375 Searcher 4 HDR */ +#define LOG_SRCH4_HDR_C (0x177 + LOG_1X_BASE_C) + +/* 376 Searcher 4 AFLT */ +#define LOG_SRCH4_AFLT_C (0x178 + LOG_1X_BASE_C) + +/* 377 Enhanced Finger Information */ +#define LOG_ENH_FING_INFO_C (0x179 + LOG_1X_BASE_C) + +/* 378 DV Information */ +#define LOG_DV_INFO_C (0x17A + LOG_1X_BASE_C) + +/* 379 WMS set routes information */ +#define LOG_WMS_SET_ROUTES_C (0x17B + LOG_1X_BASE_C) + +/* 380 FTM Version 2 Logs */ +#define LOG_FTM_VER_2_C (0x17C + LOG_1X_BASE_C) + +/* 381 GPS Multipeak logging */ +#define LOG_SRCH_GPS_MULTI_PEAKS_SIMPLIFIED_INFO_C (0x17D + LOG_1X_BASE_C) + +/* 382 GPS Multipeak logging */ +#define LOG_SRCH_GPS_MULTI_PEAKS_VERBOSE_INFO_C (0x17E + LOG_1X_BASE_C) + +/* 383-403 HDR reserved logs */ +#define LOG_HDR_RESERVED_CODES_BASE_2_C (0x17F + LOG_1X_BASE_C) +#define LOG_HDR_LAST_2_C (20 + LOG_HDR_RESERVED_CODES_BASE_2_C) + +/* RLP Rx - PDCH partial MuxPDU5 frames */ +#define LOG_RLP_RX_PDCH_PARTIAL_MUXPDU5_FRAMES_C (0x194 + LOG_1X_BASE_C) + +/* RLP Tx - PDCH partial MuxPDU5 frames */ +#define LOG_RLP_TX_PDCH_PARTIAL_MUXPDU5_FRAMES_C (0x195 + LOG_1X_BASE_C) + +/* RLP Rx internal details */ +#define LOG_RLP_RX_INTERNAL_DETAILS_C (0x196 + LOG_1X_BASE_C) + +/* RLP Tx internal details */ +#define LOG_RLP_TX_INTERNAL_DETAILS_C (0x197 + LOG_1X_BASE_C) + +/* MPEG4 Clip Statistics version 3 */ +#define LOG_MPEG4_CLIP_STATS_VER3_C (0x198 + LOG_1X_BASE_C) + +/* Mobile IP Performance */ +#define LOG_MOBILE_IP_PERFORMANCE_C (0x199 + LOG_1X_BASE_C) + +/* 410-430 Searcher reserved logs */ +#define LOG_SEARCHER_RESERVED_CODES_BASE_C (0x19A + LOG_1X_BASE_C) +#define LOG_SEARCHER_LAST_2_C (21 + LOG_SEARCHER_RESERVED_CODES_BASE_C) + +/* 432-480 QTV reserved logs */ +#define LOG_QTV2_RESERVED_CODES_BASE_C (0x1B0 + LOG_1X_BASE_C) +#define LOG_QTV2_LAST_C (48 + LOG_QTV2_RESERVED_CODES_BASE_C) + +#define LOG_QTV_PDS2_STATS (0x1B6 + LOG_1X_BASE_C) +#define LOG_QTV_PDS2_GET_REQUEST (0x1B7 + LOG_1X_BASE_C) +#define LOG_QTV_PDS2_GET_RESP_HEADER (0x1B8 + LOG_1X_BASE_C) +#define LOG_QTV_PDS2_GET_RESP_PCKT (0x1B9 + LOG_1X_BASE_C) +#define LOG_QTV_CMX_AUDIO_INPUT_DATA_C (0x1BA + LOG_1X_BASE_C) +#define LOG_QTV_RTSP_OPTIONS_C (0x1BB + LOG_1X_BASE_C) +#define LOG_QTV_RTSP_GET_PARAMETER_C (0x1BC + LOG_1X_BASE_C) +#define LOG_QTV_RTSP_SET_PARAMETER_C (0x1BD + LOG_1X_BASE_C) +#define LOG_QTV_VIDEO_BITSTREAM (0x1BE + LOG_1X_BASE_C) +#define LOG_ARM_VIDEO_DECODE_STATS (0x1BF + LOG_1X_BASE_C) +#define LOG_QTV_DSP_SLICE_BUFFER_C (0x1C0 + LOG_1X_BASE_C) +#define LOG_QTV_CMD_LOGGING_C (0x1C1 + LOG_1X_BASE_C) +#define LOG_QTV_AUDIO_FRAME_PTS_INFO_C (0x1C2 + LOG_1X_BASE_C) +#define LOG_QTV_VIDEO_FRAME_DECODE_INFO_C (0x1C3 + LOG_1X_BASE_C) +#define LOG_QTV_RTCP_COMPOUND_RR_C (0x1C4 + LOG_1X_BASE_C) +#define LOG_QTV_FRAME_BUFFER_RELEASE_REASON_C (0x1C5 + LOG_1X_BASE_C) +#define LOG_QTV_AUDIO_CHANNEL_SWITCH_FRAME_C (0x1C6 + LOG_1X_BASE_C) +#define LOG_QTV_RTP_DECRYPTED_PKT_C (0x1C7 + LOG_1X_BASE_C) +#define LOG_QTV_PCR_DRIFT_RATE_C (0x1C8 + LOG_1X_BASE_C) + +/* GPS PDSM logs */ +#define LOG_PDSM_POSITION_REPORT_CALLBACK_C (0x1E1 + LOG_1X_BASE_C) +#define LOG_PDSM_PD_EVENT_CALLBACK_C (0x1E2 + LOG_1X_BASE_C) +#define LOG_PDSM_PA_EVENT_CALLBACK_C (0x1E3 + LOG_1X_BASE_C) +#define LOG_PDSM_NOTIFY_VERIFY_REQUEST_C (0x1E4 + LOG_1X_BASE_C) +#define LOG_PDSM_RESERVED1_C (0x1E5 + LOG_1X_BASE_C) +#define LOG_PDSM_RESERVED2_C (0x1E6 + LOG_1X_BASE_C) + +/* Searcher Demodulation Status log */ +#define LOG_SRCH_DEMOD_STATUS_C (0x1E7 + LOG_1X_BASE_C) + +/* Searcher Call Statistics log */ +#define LOG_SRCH_CALL_STATISTICS_C (0x1E8 + LOG_1X_BASE_C) + +/* GPS MS-MPC Forward link */ +#define LOG_MS_MPC_FWD_LINK_C (0x1E9 + LOG_1X_BASE_C) + +/* GPS MS-MPC Reverse link */ +#define LOG_MS_MPC_REV_LINK_C (0x1EA + LOG_1X_BASE_C) + +/* Protocol Services Data */ +#define LOG_DATA_PROTOCOL_LOGGING_C (0x1EB + LOG_1X_BASE_C) + +/* MediaFLO reserved log codes */ +#define LOG_MFLO_RESERVED_CODES_BASE_C (0x1EC + LOG_1X_BASE_C) +#define LOG_MFLO_LAST_C (99 + LOG_MFLO_RESERVED_CODES_BASE_C) + +/* GPS demodulation tracking header info */ +#define LOG_GPS_DEMOD_TRACKING_HEADER_C (0x250 + LOG_1X_BASE_C) + +/* GPS demodulation tracking results */ +#define LOG_GPS_DEMOD_TRACKING_C (0x251 + LOG_1X_BASE_C) + +/* GPS bit edge logs from demod tracking */ +#define LOG_GPS_DEMOD_BIT_EDGE_C (0x252 + LOG_1X_BASE_C) + +/* GPS demodulation soft decisions */ +#define LOG_GPS_DEMOD_SOFT_DECISIONS_C (0x253 + LOG_1X_BASE_C) + +/* GPS post-processed demod tracking results */ +#define LOG_GPS_DEMOD_TRACKING_POST_PROC_C (0x254 + LOG_1X_BASE_C) + +/* GPS subframe log */ +#define LOG_GPS_DEMOD_SUBFRAME_C (0x255 + LOG_1X_BASE_C) + +/* F-CPCCH Quality Information */ +#define LOG_F_CPCCH_QUALITY_INFO_C (0x256 + LOG_1X_BASE_C) + +/* Reverse PDCCH/PDCH Frame Information */ +#define LOG_R_PDCCH_R_PDCH_FRAME_INFO_C (0x257 + LOG_1X_BASE_C) + +/* Forward G Channel Information */ +#define LOG_F_GCH_INFO_C (0x258 + LOG_1X_BASE_C) + +/* Forward G Channel Frame Information */ +#define LOG_F_GCH_FRAME_INFO_C (0x259 + LOG_1X_BASE_C) + +/* Forward RC Channel Information */ +#define LOG_F_RCCH_INFO_C (0x25A + LOG_1X_BASE_C) + +/* Forward ACK Channel Information */ +#define LOG_F_ACKCH_INFO_C (0x25B + LOG_1X_BASE_C) + +/* Forward ACK Channel ACKDA Information */ +#define LOG_F_ACKCH_ACKDA_C (0x25C + LOG_1X_BASE_C) + +/* Reverse REQ Channel Information */ +#define LOG_R_REQCH_INFO_C (0x25D + LOG_1X_BASE_C) + +/* Sleep Task Statistics */ +#define LOG_SLEEP_STATS_C (0x25E + LOG_1X_BASE_C) + +/* Sleep controller statistics 1X */ +#define LOG_1X_SLEEP_CONTROLLER_STATS_C (0x25F + LOG_1X_BASE_C) + +/* Sleep controller statistics HDR */ +#define LOG_HDR_SLEEP_CONTROLLER_STATS_C (0x260 + LOG_1X_BASE_C) + +/* Sleep controller statistics GSM */ +#define LOG_GSM_SLEEP_CONTROLLER_STATS_C (0x261 + LOG_1X_BASE_C) + +/* Sleep controller statistics WCDMA */ +#define LOG_WCDMA_SLEEP_CONTROLLER_STATS_C (0x262 + LOG_1X_BASE_C) + +/* Sleep task and controller reserved logs */ +#define LOG_SLEEP_APPS_STATS_C (0x263 + LOG_1X_BASE_C) +#define LOG_SLEEP_STATS_RESERVED2_C (0x264 + LOG_1X_BASE_C) +#define LOG_SLEEP_STATS_RESERVED3_C (0x265 + LOG_1X_BASE_C) + +/* DV Information placeholder channel logs */ +#define LOG_PDCCH_LO_SELECTED_C (0x266 + LOG_1X_BASE_C) +#define LOG_PDCCH_HI_SELECTED_C (0x267 + LOG_1X_BASE_C) +#define LOG_WALSH_SELECTED_C (0x268 + LOG_1X_BASE_C) +#define LOG_PDCH_BE_SELECTED_C (0x269 + LOG_1X_BASE_C) +#define LOG_PDCCH_LLR_SELECTED_C (0x26A + LOG_1X_BASE_C) +#define LOG_CQI_ACK_LO_SELECTED_C (0x26B + LOG_1X_BASE_C) +#define LOG_CQI_ACK_HI_SELECTED_C (0x26C + LOG_1X_BASE_C) +#define LOG_RL_GAIN_SELECTED_C (0x26D + LOG_1X_BASE_C) +#define LOG_PDCCH0_SNDA_SELECTED_C (0x26E + LOG_1X_BASE_C) +#define LOG_PDCCH1_SNDA_SELECTED_C (0x26F + LOG_1X_BASE_C) + +/* 624 WMS Message List */ +#define LOG_WMS_MESSAGE_LIST_C (0x270 + LOG_1X_BASE_C) + +/* 625 Multimode Generic SIM Driver Interface */ +#define LOG_MM_GENERIC_SIM_DRIVER_C (0x271 + LOG_1X_BASE_C) + +/* 626 Generic SIM Toolkit Task */ +#define LOG_GENERIC_SIM_TOOLKIT_TASK_C (0x272 + LOG_1X_BASE_C) + +/* 627 Call Manager Phone events log */ +#define LOG_CM_PH_EVENT_C (0x273 + LOG_1X_BASE_C) + +/* 628 WMS Set Message List */ +#define LOG_WMS_SET_MESSAGE_LIST_C (0x274 + LOG_1X_BASE_C) + +/* 629-704 HDR reserved logs */ +#define LOG_HDR_RESERVED_CODES_BASE_3_C (0x275 + LOG_1X_BASE_C) +#define LOG_HDR_LAST_3_C (75 + LOG_HDR_RESERVED_CODES_BASE_3_C) + +/* 705 Call Manager call event log */ +#define LOG_CM_CALL_EVENT_C (0x2C1 + LOG_1X_BASE_C) + +/* 706-738 QVP reserved logs */ +#define LOG_QVP_RESERVED_CODES_BASE_C (0x2C2 + LOG_1X_BASE_C) +#define LOG_QVP_LAST_C (32 + LOG_QVP_RESERVED_CODES_BASE_C) + +/* 739 GPS PE Position Report log */ +#define LOG_GPS_PE_POSITION_REPORT_C (0x2E3 + LOG_1X_BASE_C) + +/* 740 GPS PE Position Report Extended log */ +#define LOG_GPS_PE_POSITION_REPORT_EXT_C (0x2E4 + LOG_1X_BASE_C) + +/* 741 log */ +#define LOG_MDDI_HOST_STATS_C (0x2E5 + LOG_1X_BASE_C) + +/* GPS Decoded Ephemeris */ +#define LOG_GPS_DECODED_EPHEMERIS_C (0x2E6 + LOG_1X_BASE_C) + +/* GPS Decoded Almanac */ +#define LOG_GPS_DECODED_ALMANAC_C (0x2E7 + LOG_1X_BASE_C) + +/* Transceiver Resource Manager */ +#define LOG_TRANSCEIVER_RESOURCE_MGR_C (0x2E8 + LOG_1X_BASE_C) + +/* GPS Position Engine Info */ +#define LOG_GPS_POSITION_ENGINE_INFO_C (0x2E9 + LOG_1X_BASE_C) + +/* 746-810 RAPTOR reserved log range */ +#define LOG_RAPTOR_RESERVED_CODES_BASE_C (0x2EA + LOG_1X_BASE_C) +#define LOG_RAPTOR_LAST_C (64 + LOG_RAPTOR_RESERVED_CODES_BASE_C) + +/* QOS Specification Logging */ + +/* QOS Requested Log */ +#define LOG_QOS_REQUESTED_C (0x32B + LOG_1X_BASE_C) + +/* QOS Granted Log */ +#define LOG_QOS_GRANTED_C (0x32C + LOG_1X_BASE_C) + +/* QOS State Log */ +#define LOG_QOS_STATE_C (0x32D + LOG_1X_BASE_C) + +#define LOG_QOS_MODIFIED_C (0x32E + LOG_1X_BASE_C) + +#define LOG_QDJ_ENQUEUE_C (0x32F + LOG_1X_BASE_C) +#define LOG_QDJ_DEQUEUE_C (0x330 + LOG_1X_BASE_C) +#define LOG_QDJ_UPDATE_C (0x331 + LOG_1X_BASE_C) +#define LOG_QDTX_ENCODER_C (0x332 + LOG_1X_BASE_C) +#define LOG_QDTX_DECODER_C (0x333 + LOG_1X_BASE_C) + +#define LOG_PORT_ASSIGNMENT_STATUS_C (0x334 + LOG_1X_BASE_C) + +/* Protocol Services reserved log codes */ +#define LOG_PS_RESERVED_CODES_BASE_C (0x335 + LOG_1X_BASE_C) +#define LOG_PS_LAST_C (25 + LOG_PS_RESERVED_C) + +#define LOG_PS_STAT_IP_C (0x335 + LOG_1X_BASE_C) +#define LOG_PS_STAT_GLOBAL_IPV4_C (0x335 + LOG_1X_BASE_C) +#define LOG_PS_STAT_GLOBAL_IPV6_C (0x336 + LOG_1X_BASE_C) +#define LOG_PS_STAT_GLOBAL_ICMPV4_C (0x337 + LOG_1X_BASE_C) +#define LOG_PS_STAT_GLOBAL_ICMPV6_C (0x338 + LOG_1X_BASE_C) +#define LOG_PS_STAT_GLOBAL_TCP_C (0x339 + LOG_1X_BASE_C) +#define LOG_PS_STAT_GLOBAL_UDP_C (0x33A + LOG_1X_BASE_C) + +/* Protocol Services describe all TCP instances */ +#define LOG_PS_STAT_DESC_ALL_TCP_INST_C (0x33B + LOG_1X_BASE_C) + +/* Protocol Services describe all memory pool instances */ +#define LOG_PS_STAT_DESC_ALL_MEM_POOL_INST_C (0x33C + LOG_1X_BASE_C) + +/* Protocol Services describe all IFACE instances */ +#define LOG_PS_STAT_DESC_ALL_IFACE_INST_C (0x33D + LOG_1X_BASE_C) + +/* Protocol Services describe all PPP instances */ +#define LOG_PS_STAT_DESC_ALL_PPP_INST_C (0x33E + LOG_1X_BASE_C) + +/* Protocol Services describe all ARP instances */ +#define LOG_PS_STAT_DESC_ALL_ARP_INST_C (0x33F + LOG_1X_BASE_C) + +/* Protocol Services describe delta instance */ +#define LOG_PS_STAT_DESC_DELTA_INST_C (0x340 + LOG_1X_BASE_C) + +/* Protocol Services instance TCP statistics */ +#define LOG_PS_STAT_TCP_INST_C (0x341 + LOG_1X_BASE_C) + +/* Protocol Services instance UDP statistics */ +#define LOG_PS_STAT_UDP_INST_C (0x342 + LOG_1X_BASE_C) + +/* Protocol Services instance PPP statistics */ +#define LOG_PS_STAT_PPP_INST_C (0x343 + LOG_1X_BASE_C) + +/* Protocol Services instance IFACE statistics */ +#define LOG_PS_STAT_IFACE_INST_C (0x344 + LOG_1X_BASE_C) + +/* Protocol Services instance memory statistics */ +#define LOG_PS_STAT_MEM_INST_C (0x345 + LOG_1X_BASE_C) + +/* Protocol Services instance flow statistics */ +#define LOG_PS_STAT_FLOW_INST_C (0x346 + LOG_1X_BASE_C) + +/* Protocol Services instance physical link statistics */ +#define LOG_PS_STAT_PHYS_LINK_INST_C (0x347 + LOG_1X_BASE_C) + +/* Protocol Services instance ARP statistics */ +#define LOG_PS_STAT_ARP_INST_C (0x348 + LOG_1X_BASE_C) + +/* Protocol Services instance LLC statistics */ +#define LOG_PS_STAT_LLC_INST_C (0x349 + LOG_1X_BASE_C) + +/* Protocol Services instance IPHC statistics */ +#define LOG_PS_STAT_IPHC_INST_C (0x34A + LOG_1X_BASE_C) + +/* Protocol Services instance ROHC statistics */ +#define LOG_PS_STAT_ROHC_INST_C (0x34B + LOG_1X_BASE_C) + +/* Protocol Services instance RSVP statistics */ +#define LOG_PS_STAT_RSVP_INST_C (0x34C + LOG_1X_BASE_C) + +/* Protocol Services describe all LLC instances */ +#define LOG_PS_STAT_DESC_ALL_LLC_INST_C (0x34D + LOG_1X_BASE_C) + +/* Protocol Services describe all RSVP instances */ +#define LOG_PS_STAT_DESC_ALL_RSVP_INST_C (0x34E + LOG_1X_BASE_C) + +/* Call Manager Serving System event log */ +#define LOG_CM_SS_EVENT_C (0x34F + LOG_1X_BASE_C) + +/* VcTcxo manager�s automatic frequency control log */ +#define LOG_TCXOMGR_AFC_DATA_C (0x350 + LOG_1X_BASE_C) + +/* Clock transactions and general clocks status log */ +#define LOG_CLOCK_C (0x351 + LOG_1X_BASE_C) + +/* GPS search processed peak results and their associated search parameters */ +#define LOG_GPS_PROCESSED_PEAK_C (0x352 + LOG_1X_BASE_C) + +#define LOG_MDSP_LOG_CHUNKS_C (0x353 + LOG_1X_BASE_C) + +/* Periodic RSSI update log */ +#define LOG_WLAN_RSSI_UPDATE_C (0x354 + LOG_1X_BASE_C) + +/* Periodic Link Layer statistics log */ +#define LOG_WLAN_LL_STAT_C (0x355 + LOG_1X_BASE_C) + +/* QOS Extended State Log */ +#define LOG_QOS_STATE_EX_C (0x356 + LOG_1X_BASE_C) + +/* Bluetooth host HCI transmitted data */ +#define LOG_BT_HOST_HCI_TX_C (0x357 + LOG_1X_BASE_C) + +/* Bluetooth host HCI received data */ +#define LOG_BT_HOST_HCI_RX_C (0x358 + LOG_1X_BASE_C) + +/* Internal - GPS PE Position Report Part 3 */ +#define LOG_GPS_PE_POSITION_REPORT_PART3_C (0x359 + LOG_1X_BASE_C) + +/* Extended log code which logs requested QoS */ +#define LOG_QOS_REQUESTED_EX_C (0x35A + LOG_1X_BASE_C) + +/* Extended log code which logs granted QoS */ +#define LOG_QOS_GRANTED_EX_C (0x35B + LOG_1X_BASE_C) + +/* Extended log code which logs modified QoS */ +#define LOG_QOS_MODIFIED_EX_C (0x35C + LOG_1X_BASE_C) + +/* Bus Monitor Profiling Info */ +#define LOG_BUS_MON_PROF_INFO_C (0x35D + LOG_1X_BASE_C) + +/* Pilot Phase Measurement Search results */ +#define LOG_SRCH_PPM_RES_VER_2_C (0x35E + LOG_1X_BASE_C) + +/* Pilot Phase Measurement Data Base */ +#define LOG_SRCH_PPM_DB_VER_2_C (0x35F + LOG_1X_BASE_C) + +/* Pilot Phase Measurement state machine */ +#define LOG_PPM_SM_C (0x360 + LOG_1X_BASE_C) + +/* Robust Header Compression - Compressor */ +#define LOG_ROHC_COMPRESSOR_C (0x361 + LOG_1X_BASE_C) + +/* Robust Header Compression - Decompressor */ +#define LOG_ROHC_DECOMPRESSOR_C (0x362 + LOG_1X_BASE_C) + +/* Robust Header Compression - Feedback Compressor */ +#define LOG_ROHC_FEEDBACK_COMPRESSOR_C (0x363 + LOG_1X_BASE_C) + +/* Robust Header Compression - Feedback Decompressor */ +#define LOG_ROHC_FEEDBACK_DECOMPRESSOR_C (0x364 + LOG_1X_BASE_C) + +/* Bluetooth HCI commands */ +#define LOG_BT_HCI_CMD_C (0x365 + LOG_1X_BASE_C) + +/* Bluetooth HCI events */ +#define LOG_BT_HCI_EV_C (0x366 + LOG_1X_BASE_C) + +/* Bluetooth HCI Transmitted ACL data */ +#define LOG_BT_HCI_TX_ACL_C (0x367 + LOG_1X_BASE_C) + +/* Bluetooth HCI Received ACL data */ +#define LOG_BT_HCI_RX_ACL_C (0x368 + LOG_1X_BASE_C) + +/* Bluetooth SOC H4 Deep Sleep */ +#define LOG_BT_SOC_H4DS_C (0x369 + LOG_1X_BASE_C) + +/* UMTS to CDMA Handover Message */ +#define LOG_UMTS_TO_CDMA_HANDOVER_MSG_C (0x36A + LOG_1X_BASE_C) + +/* Graphic Event Data */ +#define LOG_PROFILER_GRAPHIC_DATA_C (0x36B + LOG_1X_BASE_C) + +/* Audio Event Data */ +#define LOG_PROFILER_AUDIO_DATA_C (0x36C + LOG_1X_BASE_C) + +/* GPS Spectral Information */ +#define LOG_GPS_SPECTRAL_INFO_C (0x36D + LOG_1X_BASE_C) + +/* AHB Performance Monitor LOG data */ +#define LOG_APM_C (0x36E + LOG_1X_BASE_C) + +/* GPS Clock Report */ +#define LOG_CONVERGED_GPS_CLOCK_REPORT_C (0x36F + LOG_1X_BASE_C) + +/* GPS Position Report */ +#define LOG_CONVERGED_GPS_POSITION_REPORT_C (0x370 + LOG_1X_BASE_C) + +/* GPS Measurement Report */ +#define LOG_CONVERGED_GPS_MEASUREMENT_REPORT_C (0x371 + LOG_1X_BASE_C) + +/* GPS RF Status Report */ +#define LOG_CONVERGED_GPS_RF_STATUS_REPORT_C (0x372 + LOG_1X_BASE_C) + +/* VOIP To CDMA Handover Message - Obsoleted by 0x138B - 0x138D */ +#define LOG_VOIP_TO_CDMA_HANDOVER_MSG_C (0x373 + LOG_1X_BASE_C) + +/* GPS Prescribed Dwell Result */ +#define LOG_GPS_PRESCRIBED_DWELL_RESULT_C (0x374 + LOG_1X_BASE_C) + +/* CGPS IPC Data */ +#define LOG_CGPS_IPC_DATA_C (0x375 + LOG_1X_BASE_C) + +/* CGPS Non IPC Data */ +#define LOG_CGPS_NON_IPC_DATA_C (0x376 + LOG_1X_BASE_C) + +/* CGPS Session Report */ +#define LOG_CGPS_REP_EVT_LOG_PACKET_C (0x377 + LOG_1X_BASE_C) + +/* CGPS PDSM Get Position */ +#define LOG_CGPS_PDSM_GET_POSITION_C (0x378 + LOG_1X_BASE_C) + +/* CGPS PDSM Set Parameters */ +#define LOG_CGPS_PDSM_SET_PARAMETERS_C (0x379 + LOG_1X_BASE_C) + +/* CGPS PDSM End Session */ +#define LOG_CGPS_PDSM_END_SESSION_C (0x37A + LOG_1X_BASE_C) + +/* CGPS PDSM Notify Verify Response */ +#define LOG_CGPS_PDSM_NOTIFY_VERIFY_RESP_C (0x37B + LOG_1X_BASE_C) + +/* CGPS PDSM Position Report Callback */ +#define LOG_CGPS_PDSM_POSITION_REPORT_CALLBACK_C (0x37C + LOG_1X_BASE_C) + +/* CGPS PDSM PD Event Callback */ +#define LOG_CGPS_PDSM_PD_EVENT_CALLBACK_C (0x37D + LOG_1X_BASE_C) + +/* CGPS PDSM PA Event Callback */ +#define LOG_CGPS_PDSM_PA_EVENT_CALLBACK_C (0x37E + LOG_1X_BASE_C) + +/* CGPS PDSM Notify Verify Request Callback */ +#define LOG_CGPS_PDSM_NOTIFY_VERIFY_REQUEST_C (0x37F + LOG_1X_BASE_C) + +/* CGPS PDSM PD Command Error Callback */ +#define LOG_CGPS_PDSM_PD_CMD_ERR_CALLBACK_C (0x380 + LOG_1X_BASE_C) + +/* CGPS PDSM PA Command Error Callback */ +#define LOG_CGPS_PDSM_PA_CMD_ERR_CALLBACK_C (0x381 + LOG_1X_BASE_C) + +/* CGPS PDSM Position Error */ +#define LOG_CGPS_PDSM_POS_ERROR_C (0x382 + LOG_1X_BASE_C) + +/* CGPS PDSM Extended Status Position Report */ +#define LOG_CGPS_PDSM_EXT_STATUS_POS_REPORT_C (0x383 + LOG_1X_BASE_C) + +/* CGPS PDSM Extended Status NMEA Report */ +#define LOG_CGPS_PDSM_EXT_STATUS_NMEA_REPORT_C (0x384 + LOG_1X_BASE_C) + +/* CGPS PDSM Extended Status Measurement Report */ +#define LOG_CGPS_PDSM_EXT_STATUS_MEAS_REPORT_C (0x385 + LOG_1X_BASE_C) + +/* CGPS Report Server TX Packet */ +#define LOG_CGPS_REP_SVR_TX_LOG_PACKET_C (0x386 + LOG_1X_BASE_C) + +/* CGPS Report Server RX Packet */ +#define LOG_CGPS_REP_SVR_RX_LOG_PACKET_C (0x387 + LOG_1X_BASE_C) + +/* UMTS To CDMA Handover Paging Channel Message */ +#define LOG_UMTS_TO_CDMA_HANDOVER_PCH_MSG_C (0x388 + LOG_1X_BASE_C) + +/* UMTS To CDMA Handover Traffic Channel Message */ +#define LOG_UMTS_TO_CDMA_HANDOVER_TCH_MSG_C (0x389 + LOG_1X_BASE_C) + +/* Converged GPS IQ Report */ +#define LOG_CONVERGED_GPS_IQ_REPORT_C (0x38A + LOG_1X_BASE_C) + +/* VOIP To CDMA Paging Channel Handover Message */ +#define LOG_VOIP_TO_CDMA_PCH_HANDOVER_MSG_C (0x38B + LOG_1X_BASE_C) + +/* VOIP To CDMA Access Channel Handover Message */ +#define LOG_VOIP_TO_CDMA_ACH_HANDOVER_MSG_C (0x38C + LOG_1X_BASE_C) + +/* VOIP To CDMA Forward Traffic Channel Handover Message */ +#define LOG_VOIP_TO_CDMA_FTC_HANDOVER_MSG_C (0x38D + LOG_1X_BASE_C) + +/* QMI reserved logs */ +#define LOG_QMI_RESERVED_CODES_BASE_C (0x38E + LOG_1X_BASE_C) +#define LOG_QMI_LAST_C (32 + LOG_QMI_RESERVED_CODES_BASE_C) + +/* QOS Info Code Update Log */ +#define LOG_QOS_INFO_CODE_UPDATE_C (0x3AF + LOG_1X_BASE_C) + +/* Transmit(Uplink) Vocoder PCM Packet Log */ +#define LOG_TX_PCM_PACKET_C (0x3B0 + LOG_1X_BASE_C) + +/* Audio Vocoder Data Paths */ +#define LOG_AUDVOC_DATA_PATHS_PACKET_C (0x3B0 + LOG_1X_BASE_C) + +/* Receive(Downlink) Vocoder PCM Packet Log */ +#define LOG_RX_PCM_PACKET_C (0x3B1 + LOG_1X_BASE_C) + +/* CRC of YUV frame log */ +#define LOG_DEC_CRC_FRAME_C (0x3B2 + LOG_1X_BASE_C) + +/* FLUTE Session Information */ +#define LOG_FLUTE_SESSION_INFO_C (0x3B3 + LOG_1X_BASE_C) + +/* FLUTE ADP File Information */ +#define LOG_FLUTE_ADP_FILE_INFO_C (0x3B4 + LOG_1X_BASE_C) + +/* FLUTE File Request Information */ +#define LOG_FLUTE_FILE_REQ_INFO_C (0x3B5 + LOG_1X_BASE_C) + +/* FLUTE FDT Instance Information */ +#define LOG_FLUTE_FDT_INST_C (0x3B6 + LOG_1X_BASE_C) + +/* FLUTE FDT Information */ +#define LOG_FLUTE_FDT_INFO_C (0x3B7 + LOG_1X_BASE_C) + +/* FLUTE File Log Packet Information */ +#define LOG_FLUTE_FILE_INFO_C (0x3B8 + LOG_1X_BASE_C) + +/* 3G 1X Parameter Overhead Information */ +#define LOG_VOIP_TO_CDMA_3G1X_PARAMETERS_C (0x3B9 + LOG_1X_BASE_C) + +/* CGPS ME Job Info */ +#define LOG_CGPS_ME_JOB_INFO_C (0x3BA + LOG_1X_BASE_C) + +/* CGPS ME SV Lists */ +#define LOG_CPGS_ME_SV_LISTS_C (0x3BB + LOG_1X_BASE_C) + +/* Flexible Profiling Status */ +#define LOG_PROFDIAG_GEN_STATUS_C (0x3BC + LOG_1X_BASE_C) + +/* Flexible Profiling Results */ +#define LOG_PROFDIAG_GEN_PROF_C (0x3BD + LOG_1X_BASE_C) + +/* FLUTE ADP File Content Log Packet Information */ +#define LOG_FLUTE_ADP_FILE_C (0x3BE + LOG_1X_BASE_C) + +/* FLUTE FDT Instance File Content Log Packet Information */ +#define LOG_FLUTE_FDT_INST_FILE_C (0x3BF + LOG_1X_BASE_C) + +/* FLUTE FDT Entries Information */ +#define LOG_FLUTE_FDT_ENTRIES_INFO_C (0x3C0 + LOG_1X_BASE_C) + +/* FLUTE File Contents Log Packet Information */ +#define LOG_FLUTE_FILE_C (0x3C1 + LOG_1X_BASE_C) + +/* CGPS ME Time-Transfer Info */ +#define LOG_CGPS_ME_TIME_TRANSFER_INFO_C (0x3C2 + LOG_1X_BASE_C) + +/* CGPS ME UMTS Time-Tagging Info */ +#define LOG_CGPS_ME_UMTS_TIME_TAGGING_INFO_C (0x3C3 + LOG_1X_BASE_C) + +/* CGPS ME Generic Time Estimate Put lnfo */ +#define LOG_CGPS_ME_TIME_EST_PUT_INFO_C (0x3C4 + LOG_1X_BASE_C) + +/* CGPS ME Generic Freq Estimate Put lnfo */ +#define LOG_CGPS_ME_FREQ_EST_PUT_INFO_C (0x3C5 + LOG_1X_BASE_C) + +/* CGPS Slow Clock Report */ +#define LOG_CGPS_SLOW_CLOCK_REPORT_C (0x3C6 + LOG_1X_BASE_C) + +/* Converged GPS Medium Grid */ +#define LOG_CONVERGED_GPS_MEDIUM_GRID_C (0x3C7 + LOG_1X_BASE_C) + +/* Static information about the driver or device */ +#define LOG_SNSD_INFO_C (0x3C8 + LOG_1X_BASE_C) + +/* Dynamic state information about the device or driver */ +#define LOG_SNSD_STATE_C (0x3C9 + LOG_1X_BASE_C) + +/* Data from a driver */ +#define LOG_SNSD_DATA (0x3CA + LOG_1X_BASE_C) +#define LOG_SNSD_DATA_C (0x3CA + LOG_1X_BASE_C) + +/* CGPS Cell DB Cell Change Info */ +#define LOG_CGPS_CELLDB_CELL_CHANGE_INFO_C (0x3CB + LOG_1X_BASE_C) + +/* xScalar YUV frame log */ +#define LOG_DEC_XSCALE_YUV_FRAME_C (0x3CC + LOG_1X_BASE_C) + +/* CRC of xScaled YUV frame log */ +#define LOG_DEC_XSCALE_CRC_FRAME_C (0x3CD + LOG_1X_BASE_C) + +/* CGPS Frequency Estimate Report */ +#define LOG_CGPS_FREQ_EST_REPORT_C (0x3CE + LOG_1X_BASE_C) + +/* GPS DCME Srch Job Completed */ +#define LOG_GPS_DCME_SRCH_JOB_COMPLETED_C (0x3CF + LOG_1X_BASE_C) + +/* CGPS ME Fastscan results */ +#define LOG_CGPS_ME_FASTSCAN_RESULTS_C (0x3D0 + LOG_1X_BASE_C) + +/* XO frequency Estimation log */ +#define LOG_XO_FREQ_EST_C (0x3D1 + LOG_1X_BASE_C) + +/* Tcxomgr field calibration data */ +#define LOG_TCXOMGR_FIELD_CAL_C (0x3D2 + LOG_1X_BASE_C) + +/* UMB Call Processing Connection Attempt */ +#define LOG_UMBCP_CONNECTION_ATTEMPT_C (0x3D3 + LOG_1X_BASE_C) + +/* UMB Call Processing Connection Release */ +#define LOG_UMBCP_CONNECTION_RELEASE_C (0x3D4 + LOG_1X_BASE_C) + +/* UMB Call Processing Page Message */ +#define LOG_UMBCP_PAGE_MESSAGE_C (0x3D5 + LOG_1X_BASE_C) + +/* UMB Call Processing OVHD Information */ +#define LOG_UMBCP_OVHD_INFO_C (0x3D6 + LOG_1X_BASE_C) + +/* UMB Call Processing Session Attempt */ +#define LOG_UMBCP_SESSION_ATTEMPT_C (0x3D7 + LOG_1X_BASE_C) + +/* UMB Call Processing Route Information */ +#define LOG_UMBCP_ROUTE_INFO_C (0x3D8 + LOG_1X_BASE_C) + +/* UMB Call Processing State Information */ +#define LOG_UMBCP_STATE_INFO_C (0x3D9 + LOG_1X_BASE_C) + +/* UMB Call Processing SNP */ +#define LOG_UMBCP_SNP_C (0x3DA + LOG_1X_BASE_C) + +/* CGPS Session Early Exit Decision */ +#define LOG_CGPS_SESSION_EARLY_EXIT_DECISION_C (0x3DB + LOG_1X_BASE_C) + +/* GPS RF Linearity Status */ +#define LOG_CGPS_ME_RF_LINEARITY_INFO_C (0x3DC + LOG_1X_BASE_C) + +/* CGPS ME 5ms IQ Sums */ +#define LOG_CGPS_ME_5MS_IQ_SUMS_C (0x3DD + LOG_1X_BASE_C) + +/* CGPS ME 20ms IQ Sums */ +#define LOG_CPGS_ME_20MS_IQ_SUMS_C (0x3DE + LOG_1X_BASE_C) + +/* ROHC Compressor Statistics */ +#define LOG_ROHC_COMPRESSOR_STATS_C (0x3DF + LOG_1X_BASE_C) + +/* ROHC Decompressor Statistics */ +#define LOG_ROHC_DECOMPRESSOR_STATS_C (0x3E0 + LOG_1X_BASE_C) + +/* Sensors - Kalman filter information */ +#define LOG_SENSOR_KF_INFO_C (0x3E1 + LOG_1X_BASE_C) + +/* Sensors - Integrated measurements */ +#define LOG_SENSOR_INT_MEAS_C (0x3E2 + LOG_1X_BASE_C) + +/* Sensors - Bias calibration values */ +#define LOG_SENSOR_BIAS_CALIBRATION_C (0x3E3 + LOG_1X_BASE_C) + +/* Log codes 0x13E4-0x13E7 are not following standard log naming convention */ + +/* DTV ISDB-T Transport Stream Packets */ +#define LOG_DTV_ISDB_TS_PACKETS (0x3E4 + LOG_1X_BASE_C) + +/* DTV ISDB-T PES Packets */ +#define LOG_DTV_ISDB_PES_PACKETS (0x3E5 + LOG_1X_BASE_C) + +/* DTV ISDB-T Sections */ +#define LOG_DTV_ISDB_SECTIONS (0x3E6 + LOG_1X_BASE_C) + +/* DTV ISDB-T Buffering */ +#define LOG_DTV_ISDB_BUFFERING (0x3E7 + LOG_1X_BASE_C) + +/* WLAN System Acquisition and Handoff */ +#define LOG_WLAN_SYS_ACQ_HO_C (0x3E8 + LOG_1X_BASE_C) + +/* WLAN General Configurable Parameters */ +#define LOG_WLAN_GEN_CONFIG_PARAMS_C (0x3E9 + LOG_1X_BASE_C) + +/* UMB Physical Layer Channel and Interference Estimation */ +#define LOG_UMB_PHY_RX_DPICH_CIE_C (0x3EA + LOG_1X_BASE_C) + +/* UMB Physical Layer MMSE/MRC Demodulated Data Symbols (Low) */ +#define LOG_UMB_PHY_RX_DATA_DEMOD_LOW_C (0x3EB + LOG_1X_BASE_C) + +/* UMB Physical Layer MMSE/MRC Demodulated Data Symbols (High) */ +#define LOG_UMB_PHY_RX_DATA_DEMOD_HIGH_C (0x3EC + LOG_1X_BASE_C) + +/* UMB Physical Layer DCH Decoder */ +#define LOG_UMB_PHY_RX_DCH_DECODER_C (0x3ED + LOG_1X_BASE_C) + +/* UMB Physical Layer DCH Statistics */ +#define LOG_UMB_PHY_DCH_STATISTICS_C (0x3EE + LOG_1X_BASE_C) + +/* UMB Physical Layer CqiPich Processing */ +#define LOG_UMB_PHY_RX_CQIPICH_C (0x3EF + LOG_1X_BASE_C) + +/* UMB Physical Layer MIMO/SIMO in CqiPich (High) */ +#define LOG_UMB_PHY_RX_CQIPICH_CHANTAPS_HIGH_C (0x3F0 + LOG_1X_BASE_C) + +/* UMB Physical Layer MIMO/SIMO in CquiPich (Low) */ +#define LOG_UMB_PHY_RX_CQIPICH_CHANTAPS_LOW_C (0x3F1 + LOG_1X_BASE_C) + +/* UMB Physical Layer Time-Domain Channel Taps (High) */ +#define LOG_UMB_PHY_RX_PPICH_CHAN_EST_HIGH_C (0x3F2 + LOG_1X_BASE_C) + +/* UMB Physical Layer Time-Domain Channel Taps (Low) */ +#define LOG_UMB_PHY_RX_PPICH_CHAN_EST_LOW_C (0x3F3 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator */ +#define LOG_UMB_PHY_TX_PICH_CONFIG_C (0x3F4 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-ACK (High) */ +#define LOG_UMB_PHY_TX_ACK_HIGH_C (0x3F5 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-ACK (Low) */ +#define LOG_UMB_PHY_TX_ACK_LOW_C (0x3F6 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-PICH */ +#define LOG_UMB_PHY_TX_PICH_C (0x3F7 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-ACH (Access) */ +#define LOG_UMB_PHY_TX_ACH_C (0x3F8 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-ODDCCH (High) */ +#define LOG_UMB_PHY_TX_ODCCH_HIGH_C (0x3F9 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-ODDCCH (Low) */ +#define LOG_UMB_PHY_TX_ODCCH_LOW_C (0x3FA + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-CDCCH */ +#define LOG_UMB_PHY_TX_RCDCCH_CONFIG_C (0x3FB + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for CQI sent on RCDCCH */ +#define LOG_UMB_PHY_TX_NONFLSS_CQICH_C (0x3FC + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for CQI sent on RCDCCH */ +#define LOG_UMB_PHY_TX_FLSS_CQICH_C (0x3FD + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for PACH sent on RCDCCH */ +#define LOG_UMB_PHY_TX_PAHCH_C (0x3FE + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for REQ sent on RCDCCH */ +#define LOG_UMB_PHY_TX_REQCH_C (0x3FF + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for PSD sent on RCDCCH */ +#define LOG_UMB_PHY_TX_PSDCH_C (0x400 + LOG_1X_BASE_C) + +/* UMB Physical Layer AT Modulator for R-DCH */ +#define LOG_UMB_PHY_TX_DCH_C (0x401 + LOG_1X_BASE_C) + +/* UMB Physical Layer Time/Frequency/RxPower Estimate */ +#define LOG_UMB_PHY_RX_TIME_FREQ_POWER_ESTIMATE_C (0x402 + LOG_1X_BASE_C) + +/* UMB Physical Layer FLCS Processing */ +#define LOG_UMB_PHY_RX_FLCS_PROCESSING_C (0x403 + LOG_1X_BASE_C) + +/* UMB Physical Layer PBCCH Processing */ +#define LOG_UMB_PHY_RX_PBCCH_PROCESSING_C (0x404 + LOG_1X_BASE_C) + +/* UMB Physical Layer SBCCH Processing */ +#define LOG_UMB_PHY_RX_SBCCH_PROCESSING_C (0x405 + LOG_1X_BASE_C) + +/* UMB Physical Layer QPCH Processing */ +#define LOG_UMB_PHY_RX_QPCH_PROCESSING_C (0x406 + LOG_1X_BASE_C) + +/* UMB Physical Layer MRC Demodulated Data Symbols (Preamble SBCCH/QPCH) */ +#define LOG_UMB_PHY_RX_SBCCH_DEMOD_C (0x407 + LOG_1X_BASE_C) + +/* UMB Physical Layer MRC Demodulated Data Symbols (Preamble PBCCH) */ +#define LOG_UMB_PHY_RX_PBCCH_DEMOD_C (0x408 + LOG_1X_BASE_C) + +/* UMB Physical Layer VCQI */ +#define LOG_UMB_PHY_RX_VCQI_C (0x409 + LOG_1X_BASE_C) + +/* UMB Physical Layer Acquisition Algorithm */ +#define LOG_UMB_PHY_RX_INITIAL_ACQUISITION_C (0x40A + LOG_1X_BASE_C) + +/* UMB Physical Layer Handoff Search Algorithm */ +#define LOG_UMB_PHY_RX_HANDOFF_SEARCH_C (0x40B + LOG_1X_BASE_C) + +/* UMB RF RFFE Configuration Info */ +#define LOG_UMB_AT_RFFE_CONFG_C (0x40C + LOG_1X_BASE_C) + +/* UMB RF Calibrated Values After Powerup */ +#define LOG_UMB_AT_RFFE_RX_CALIB_C (0x40D + LOG_1X_BASE_C) + +/* UMB RF AGC Block in Acquisition Mode */ +#define LOG_UMB_AT_RFFE_RX_ACQ_C (0x40E + LOG_1X_BASE_C) + +/* UMB RF AGC Block in Idle Mode */ +#define LOG_UMB_AT_RFFE_RX_IDLE_C (0x40F + LOG_1X_BASE_C) + +/* UMB RF AGC Block in Connected Mode */ +#define LOG_UMB_AT_RFFE_RX_CONNECTED_C (0x410 + LOG_1X_BASE_C) + +/* UMB RF AGC Block in Connected Mode (FTM) */ +#define LOG_UMB_AT_RFFE_RX_CONNECTED_FTM_C (0x411 + LOG_1X_BASE_C) + +/* UMB RF Jammer Detector Functionality */ +#define LOG_UMB_AT_RFFE_RX_JAMMER_DETECTOR_FUNCTIONALITY_C (0x412 + LOG_1X_BASE_C) + +/* UMB RF Jammer Detector Response */ +#define LOG_UMB_AT_RFFE_RX_JAMMER_DETECTOR_RESPONSE_C (0x413 + LOG_1X_BASE_C) + +/* UMB RF RFFE TX Power Control */ +#define LOG_UMB_AT_RFFE_TX_BETA_SCALING_C (0x414 + LOG_1X_BASE_C) + +/* UMB Searcher Dump */ +#define LOG_UMB_SEARCHER_DUMP_C (0x415 + LOG_1X_BASE_C) + +/* UMB System Acquire */ +#define LOG_UMB_SYSTEM_ACQUIRE_C (0x416 + LOG_1X_BASE_C) + +/* UMB Set Maintenance */ +#define LOG_UMB_SET_MAINTENANCE_C (0x417 + LOG_1X_BASE_C) + +/* UMB QPCH */ +#define LOG_UMB_QPCH_C (0x418 + LOG_1X_BASE_C) + +/* UMB RLL Forward Partial RP Packet */ +#define LOG_UMB_RLL_FORWARD_PARTIAL_RP_C (0x419 + LOG_1X_BASE_C) + +/* UMB RLL Reverse Partial RP Packet */ +#define LOG_UMB_RLL_REVERSE_PARTIAL_RP_C (0x41A + LOG_1X_BASE_C) + +/* UMB RLL Forward Signal Packet */ +#define LOG_UMB_RLL_FORWARD_SIGNAL_C (0x41B + LOG_1X_BASE_C) + +/* UMB RLL Reverse Signal Packet */ +#define LOG_UMB_RLL_REVERSE_SIGNAL_C (0x41C + LOG_1X_BASE_C) + +/* UMB RLL Forward Statistics */ +#define LOG_UMB_RLL_FORWARD_STATS_C (0x41D + LOG_1X_BASE_C) + +/* UMB RLL Reverse Statistics */ +#define LOG_UMB_RLL_REVERSE_STATS_C (0x41E + LOG_1X_BASE_C) + +/* UMB RLL IRTP */ +#define LOG_UMB_RLL_IRTP_C (0x41F + LOG_1X_BASE_C) + +/* UMB AP Forward Link MAC Packets */ +#define LOG_UMB_AP_FL_MAC_PACKET_C (0x420 + LOG_1X_BASE_C) + +/* UMB AP Reverse Link MAC Packets */ +#define LOG_UMB_AP_RL_MAC_PACKET_C (0x421 + LOG_1X_BASE_C) + +/* GPS Performance Statistics log */ +#define LOG_CGPS_PERFORMANCE_STATS_C (0x422 + LOG_1X_BASE_C) + +/* UMB Searcher General Status */ +#define LOG_UMB_SRCH_GENERAL_STATUS_C (0x423 + LOG_1X_BASE_C) + +/* UMB Superframe Scheduler */ +#define LOG_UMB_SUPERFRAME_SCHEDULER_C (0x424 + LOG_1X_BASE_C) + +/* UMB Sector List */ +#define LOG_UMB_SECTOR_LIST_C (0x425 + LOG_1X_BASE_C) + +/* UMB MAC Access Attempt Command */ +#define LOG_UMB_MAC_ACCESS_ATTEMPT_CMD_C (0x426 + LOG_1X_BASE_C) + +/* UMB MAC Access Probe Information */ +#define LOG_UMB_MAC_ACCESS_PROBE_INFO_C (0x427 + LOG_1X_BASE_C) + +/* UMB MAC RTCMAC Package Information */ +#define LOG_UMB_MAC_RTCMAC_PKG_INFO_C (0x428 + LOG_1X_BASE_C) + +/* UMB MAC Super Frame Information */ +#define LOG_UMB_MAC_SI_INFO_C (0x429 + LOG_1X_BASE_C) + +/* UMB MAC Quick Channel Information */ +#define LOG_UMB_MAC_QCI_INFO_C (0x42A + LOG_1X_BASE_C) + +/* UMB MAC Paging Id List */ +#define LOG_UMB_MAC_PAGING_ID_LIST_C (0x42B + LOG_1X_BASE_C) + +/* UMB MAC Quick Paging Channel Information */ +#define LOG_UMB_MAC_QPCH_INFO_C (0x42C + LOG_1X_BASE_C) + +/* UMB MAC FTCMAC Information */ +#define LOG_UMB_MAC_FTCMAC_PKG_INFO_C (0x42D + LOG_1X_BASE_C) + +/* UMB MAC Access Grant Receiving */ +#define LOG_UMB_MAC_ACCESS_GRANT_C (0x42E + LOG_1X_BASE_C) + +/* UMB MAC Generic Debug Log */ +#define LOG_UMB_MAC_GEN_DEBUG_LOG_PKG_C (0x42F + LOG_1X_BASE_C) + +/* CGPS Frequency Bias Estimate */ +#define LOG_CGPS_MC_FREQ_BIAS_EST_C (0x430 + LOG_1X_BASE_C) + +/* UMB MAC Request Report Information Log */ +#define LOG_UMB_MAC_REQCH_REPORT_INFO_C (0x431 + LOG_1X_BASE_C) + +/* UMB MAC Reverse Link QoS Token Bucket Information Log */ +#define LOG_UMB_MAC_RLQOS_TOKEN_BUCKET_INFO_C (0x432 + LOG_1X_BASE_C) + +/* UMB MAC Reverse Link QoS Stream Information Log */ +#define LOG_UMB_MAC_RLQOS_STREAM_INFO_C (0x433 + LOG_1X_BASE_C) + +/* UMB MAC Reverse Link QoS Allotment Information Log */ +#define LOG_UMB_MAC_RLQOS_ALLOTMENT_INFO_C (0x434 + LOG_1X_BASE_C) + +/* UMB Searcher Recent State Machine Transactions */ +#define LOG_UMB_SRCH_STM_ACTIVITY_C (0x435 + LOG_1X_BASE_C) + +/* Performance Counters on ARM11 Profiling Information */ +#define LOG_ARM11_PERF_CNT_INFO_C (0x436 + LOG_1X_BASE_C) + +/* Protocol Services describe all flow instances */ +#define LOG_PS_STAT_DESC_ALL_FLOW_INST_C (0x437 + LOG_1X_BASE_C) + +/* Protocol Services describe all physical link instances */ +#define LOG_PS_STAT_DESC_ALL_PHYS_LINK_INST_C (0x438 + LOG_1X_BASE_C) + +/* Protocol Services describe all UDP instances */ +#define LOG_PS_STAT_DESC_ALL_UDP_INST_C (0x439 + LOG_1X_BASE_C) + +/* Searcher 4 Multi-Carrier HDR */ +#define LOG_SRCH4_MC_HDR_C (0x43A + LOG_1X_BASE_C) + +/* Protocol Services describe all IPHC instances */ +#define LOG_PS_STAT_DESC_ALL_IPHC_INST_C (0x43B + LOG_1X_BASE_C) + +/* Protocol Services describe all ROHC instances */ +#define LOG_PS_STAT_DESC_ALL_ROHC_INST_C (0x43C + LOG_1X_BASE_C) + +/* BCast security add program information */ +#define LOG_BCAST_SEC_ADD_PROGRAM_INFO_C (0x43D + LOG_1X_BASE_C) + +/* BCast security add program complete */ +#define LOG_BCAST_SEC_ADD_PROGRAM_COMPLETE_C (0x43E + LOG_1X_BASE_C) + +/* BCast security SDP parse */ +#define LOG_BCAST_SEC_SDP_PARSE_C (0x43F + LOG_1X_BASE_C) + +/* CGPS ME dynamic power optimization status */ +#define LOG_CGPS_ME_DPO_STATUS_C (0x440 + LOG_1X_BASE_C) + +/* CGPS PDSM on demand session start */ +#define LOG_CGPS_PDSM_ON_DEMAND_SESSION_START_C (0x441 + LOG_1X_BASE_C) + +/* CGPS PDSM on demand session stop */ +#define LOG_CGPS_PDSM_ON_DEMAND_SESSION_STOP_C (0x442 + LOG_1X_BASE_C) + +/* CGPS PDSM on demand session not started */ +#define LOG_CGPS_PDSM_ON_DEMAND_SESSION_NOT_STARTED_C (0x443 + LOG_1X_BASE_C) + +/* CGPS PDSM extern coarse position inject start */ +#define LOG_CGPS_PDSM_EXTERN_COARSE_POS_INJ_START_C (0x444 + LOG_1X_BASE_C) + +/* DTV ISDB-T TMCC information */ +#define LOG_DTV_ISDB_TMCC_C (0x445 + LOG_1X_BASE_C) + +/* RF development */ +#define LOG_RF_DEV_C (0x446 + LOG_1X_BASE_C) + +/* RF RFM API */ +#define LOG_RF_RFM_API_C (0x447 + LOG_1X_BASE_C) + +/* RF RFM state */ +#define LOG_RF_RFM_STATE_C (0x448 + LOG_1X_BASE_C) + +/* 1X RF Warmup */ +#define LOG_1X_RF_WARMUP_C (0x449 + LOG_1X_BASE_C) + +/* 1X RF power limiting */ +#define LOG_1X_RF_PWR_LMT_C (0x44A + LOG_1X_BASE_C) + +/* 1X RF state */ +#define LOG_1X_RF_STATE_C (0x44B + LOG_1X_BASE_C) + +/* 1X RF sleep */ +#define LOG_1X_RF_SLEEP_C (0x44C + LOG_1X_BASE_C) + +/* 1X RF TX state */ +#define LOG_1X_RF_TX_STATE_C (0x44D + LOG_1X_BASE_C) + +/* 1X RF IntelliCeiver state */ +#define LOG_1X_RF_INT_STATE_C (0x44E + LOG_1X_BASE_C) + +/* 1X RF RX ADC clock */ +#define LOG_1X_RF_RX_ADC_CLK_C (0x44F + LOG_1X_BASE_C) + +/* 1X RF LNA switch point */ +#define LOG_1X_RF_LNA_SWITCHP_C (0x450 + LOG_1X_BASE_C) + +/* 1X RF RX calibration */ +#define LOG_1X_RF_RX_CAL_C (0x451 + LOG_1X_BASE_C) + +/* 1X RF API */ +#define LOG_1X_RF_API_C (0x452 + LOG_1X_BASE_C) + +/* 1X RF RX PLL locking status */ +#define LOG_1X_RF_RX_PLL_LOCK_C (0x453 + LOG_1X_BASE_C) + +/* 1X RF voltage regulator */ +#define LOG_1X_RF_VREG_C (0x454 + LOG_1X_BASE_C) + +/* CGPS DIAG successful fix count */ +#define LOG_CGPS_DIAG_SUCCESSFUL_FIX_COUNT_C (0x455 + LOG_1X_BASE_C) + +/* CGPS MC track dynamic power optimization status */ +#define LOG_CGPS_MC_TRACK_DPO_STATUS_C (0x456 + LOG_1X_BASE_C) + +/* CGPS MC SBAS demodulated bits */ +#define LOG_CGPS_MC_SBAS_DEMOD_BITS_C (0x457 + LOG_1X_BASE_C) + +/* CGPS MC SBAS demodulated soft symbols */ +#define LOG_CGPS_MC_SBAS_DEMOD_SOFT_SYMBOLS_C (0x458 + LOG_1X_BASE_C) + +/* Data Services PPP configuration */ +#define LOG_DS_PPP_CONFIG_PARAMS_C (0x459 + LOG_1X_BASE_C) + +/* Data Services physical link configuration */ +#define LOG_DS_PHYS_LINK_CONFIG_PARAMS_C (0x45A + LOG_1X_BASE_C) + +/* Data Services PPP device configuration */ +#define LOG_PS_PPP_DEV_CONFIG_PARAMS_C (0x45B + LOG_1X_BASE_C) + +/* CGPS PDSM GPS state information */ +#define LOG_CGPS_PDSM_GPS_STATE_INFO_C (0x45C + LOG_1X_BASE_C) + +/* CGPS PDSM EXT status GPS state information */ +#define LOG_CGPS_PDSM_EXT_STATUS_GPS_STATE_INFO_C (0x45D + LOG_1X_BASE_C) + +/* CGPS ME Rapid Search Report */ +#define LOG_CGPS_ME_RAPID_SEARCH_REPORT_C (0x45E + LOG_1X_BASE_C) + +/* CGPS PDSM XTRA-T session */ +#define LOG_CGPS_PDSM_XTRA_T_SESSION_C (0x45F + LOG_1X_BASE_C) + +/* CGPS PDSM XTRA-T upload */ +#define LOG_CGPS_PDSM_XTRA_T_UPLOAD_C (0x460 + LOG_1X_BASE_C) + +/* CGPS Wiper Position Report */ +#define LOG_CGPS_WIPER_POSITION_REPORT_C (0x461 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard HTTP Digest Request Info */ +#define LOG_DTV_DVBH_SEC_SC_HTTP_DIGEST_REQ_C (0x462 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard HTTP Digest Response Info */ +#define LOG_DTV_DVBH_SEC_SC_HTTP_DIGEST_RSP_C (0x463 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Services Registration Request Info */ +#define LOG_DTV_DVBH_SEC_SC_SVC_REG_REQ_C (0x464 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Services Registration Complete Info */ +#define LOG_DTV_DVBH_SEC_SC_SVC_REG_COMPLETE_C (0x465 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Services Deregistration Request Info */ +#define LOG_DTV_DVBH_SEC_SC_SVC_DEREG_REQ_C (0x466 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Services Deregistration Complete Info */ +#define LOG_DTV_DVBH_SEC_SC_SVC_DEREG_COMPLETE_C (0x467 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard LTKM Request Info */ +#define LOG_DTV_DVBH_SEC_SC_LTKM_REQ_C (0x468 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard LTKM Request Complete Info */ +#define LOG_DTV_DVBH_SEC_SC_LTKM_REQ_COMPLETE_C (0x469 + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Program Selection Info */ +#define LOG_DTV_DVBH_SEC_SC_PROG_SEL_C (0x46A + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Program Selection Complete Info */ +#define LOG_DTV_DVBH_SEC_SC_PROG_SEL_COMPLETE_C (0x46B + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard LTKM */ +#define LOG_DTV_DVBH_SEC_SC_LTKM_C (0x46C + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard LTKM Verification Message */ +#define LOG_DTV_DVBH_SEC_SC_LTKM_VERIFICATION_C (0x46D + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard Parental Control Message */ +#define LOG_DTV_DVBH_SEC_SC_PARENTAL_CTRL_C (0x46E + LOG_1X_BASE_C) + +/* DTV DVBH Security SmartCard STKM */ +#define LOG_DTV_DVBH_SEC_SC_STKM_C (0x46F + LOG_1X_BASE_C) + +/* Protocol Services Statistics Global Socket */ +#define LOG_PS_STAT_GLOBAL_SOCK_C (0x470 + LOG_1X_BASE_C) + +/* MCS Application Manager */ +#define LOG_MCS_APPMGR_C (0x471 + LOG_1X_BASE_C) + +/* MCS MSGR */ +#define LOG_MCS_MSGR_C (0x472 + LOG_1X_BASE_C) + +/* MCS QTF */ +#define LOG_MCS_QTF_C (0x473 + LOG_1X_BASE_C) + +/* Sensors Stationary Detector Output */ +#define LOG_STATIONARY_DETECTOR_OUTPUT_C (0x474 + LOG_1X_BASE_C) + +/* Print out the ppm data portion */ +#define LOG_CGPS_PDSM_EXT_STATUS_MEAS_REPORT_PPM_C (0x475 + LOG_1X_BASE_C) + +/* GNSS Position Report */ +#define LOG_GNSS_POSITION_REPORT_C (0x476 + LOG_1X_BASE_C) + +/* GNSS GPS Measurement Report */ +#define LOG_GNSS_GPS_MEASUREMENT_REPORT_C (0x477 + LOG_1X_BASE_C) + +/* GNSS Clock Report */ +#define LOG_GNSS_CLOCK_REPORT_C (0x478 + LOG_1X_BASE_C) + +/* GNSS Demod Soft Decision */ +#define LOG_GNSS_DEMOD_SOFT_DECISIONS_C (0x479 + LOG_1X_BASE_C) + +/* GNSS ME 5MS IQ sum */ +#define LOG_GNSS_ME_5MS_IQ_SUMS_C (0x47A + LOG_1X_BASE_C) + +/* GNSS CD DB report */ +#define LOG_GNSS_CD_DB_REPORT_C (0x47B + LOG_1X_BASE_C) + +/* GNSS PE WLS position report */ +#define LOG_GNSS_PE_WLS_POSITION_REPORT_C (0x47C + LOG_1X_BASE_C) + +/* GNSS PE KF position report */ +#define LOG_GNSS_PE_KF_POSITION_REPORT_C (0x47D + LOG_1X_BASE_C) + +/* GNSS PRX RF HW status report */ +#define LOG_GNSS_PRX_RF_HW_STATUS_REPORT_C (0x47E + LOG_1X_BASE_C) + +/* GNSS DRX RF HW status report */ +#define LOG_GNSS_DRX_RF_HW_STATUS_REPORT_C (0x47F + LOG_1X_BASE_C) + +/* GNSS Glonass Measurement report */ +#define LOG_GNSS_GLONASS_MEASUREMENT_REPORT_C (0x480 + LOG_1X_BASE_C) + +/* GNSS GPS HBW RXD measurement */ +#define LOG_GNSS_GPS_HBW_RXD_MEASUREMENT_C (0x481 + LOG_1X_BASE_C) + +/* GNSS PDSM position report callback */ +#define LOG_GNSS_PDSM_POSITION_REPORT_CALLBACK_C (0x482 + LOG_1X_BASE_C) + +/* ISense Request String */ +#define LOG_ISENSE_REQUEST_STR_C (0x483 + LOG_1X_BASE_C) + +/* ISense Response String */ +#define LOG_ISENSE_RESPONSE_STR_C (0x484 + LOG_1X_BASE_C) + +/* Bluetooth SOC General Log Packet*/ +#define LOG_BT_SOC_GENERAL_C (0x485 + LOG_1X_BASE_C) + +/* QCRil Call Flow */ +#define LOG_QCRIL_CALL_FLOW_C (0x486 + LOG_1X_BASE_C) + +/* CGPS Wideband FFT stats */ +#define LOG_CGPS_WB_FFT_STATS_C (0x487 + LOG_1X_BASE_C) + +/* CGPS Slow Clock Calibration Report*/ +#define LOG_CGPS_SLOW_CLOCK_CALIB_REPORT_C (0x488 + LOG_1X_BASE_C) + +/* SNS GPS TIMESTAMP */ +#define LOG_SNS_GPS_TIMESTAMP_C (0x489 + LOG_1X_BASE_C) + +/* GNSS Search Strategy Task Allocation */ +#define LOG_GNSS_SEARCH_STRATEGY_TASK_ALLOCATION_C (0x48A + LOG_1X_BASE_C) + +/* RF MC STM state */ +#define LOG_1XHDR_MC_STATE_C (0x48B + LOG_1X_BASE_C) + +/* Record in the Sparse Network DB */ +#define LOG_CGPS_SNDB_RECORD_C (0x48C + LOG_1X_BASE_C) + +/* Record removed from the DB */ +#define LOG_CGPS_SNDB_REMOVE_C (0x48D + LOG_1X_BASE_C) + +/* CGPS Reserved */ +#define LOG_GNSS_CC_PERFORMANCE_STATS_C (0x48E + LOG_1X_BASE_C) + +/* GNSS PDSM Set Paramerters */ +#define LOG_GNSS_PDSM_SET_PARAMETERS_C (0x48F + LOG_1X_BASE_C) + +/* GNSS PDSM PD Event Callback */ +#define LOG_GNSS_PDSM_PD_EVENT_CALLBACK_C (0x490 + LOG_1X_BASE_C) + +/* GNSS PDSM PA Event Callback */ +#define LOG_GNSS_PDSM_PA_EVENT_CALLBACK_C (0x491 + LOG_1X_BASE_C) + +/* CGPS Reserved */ +#define LOG_CGPS_RESERVED2_C (0x492 + LOG_1X_BASE_C) + +/* CGPS Reserved */ +#define LOG_CGPS_RESERVED3_C (0x493 + LOG_1X_BASE_C) + +/* GNSS PDSM EXT Status MEAS Report */ +#define LOG_GNSS_PDSM_EXT_STATUS_MEAS_REPORT_C (0x494 + LOG_1X_BASE_C) + +/* GNSS SM Error */ +#define LOG_GNSS_SM_ERROR_C (0x495 + LOG_1X_BASE_C) + +/* WLAN Scan */ +#define LOG_WLAN_SCAN_C (0x496 + LOG_1X_BASE_C) + +/* WLAN IBSS */ +#define LOG_WLAN_IBSS_C (0x497 + LOG_1X_BASE_C) + +/* WLAN 802.11d*/ +#define LOG_WLAN_80211D_C (0x498 + LOG_1X_BASE_C) + +/* WLAN Handoff */ +#define LOG_WLAN_HANDOFF_C (0x499 + LOG_1X_BASE_C) + +/* WLAN QoS EDCA */ +#define LOG_WLAN_QOS_EDCA_C (0x49A + LOG_1X_BASE_C) + +/* WLAN Beacon Update */ +#define LOG_WLAN_BEACON_UPDATE_C (0x49B + LOG_1X_BASE_C) + +/* WLAN Power save wow add pattern */ +#define LOG_WLAN_POWERSAVE_WOW_ADD_PTRN_C (0x49C + LOG_1X_BASE_C) + +/* WLAN WCM link metrics */ +#define LOG_WLAN_WCM_LINKMETRICS_C (0x49D + LOG_1X_BASE_C) + +/* WLAN wps scan complete*/ +#define LOG_WLAN_WPS_SCAN_COMPLETE_C (0x49E + LOG_1X_BASE_C) + +/* WLAN WPS WSC Message */ +#define LOG_WLAN_WPS_WSC_MESSAGE_C (0x49F + LOG_1X_BASE_C) + +/* WLAN WPS credentials */ +#define LOG_WLAN_WPS_CREDENTIALS_C (0x4A0 + LOG_1X_BASE_C) + +/* WLAN Linklayer stat*/ +#define LOG_WLAN_LINKLAYER_STAT_C (0x4A1 + LOG_1X_BASE_C) + +/* WLAN Qos TSpec*/ +#define LOG_WLAN_QOS_TSPEC_C (0x4A2 + LOG_1X_BASE_C) + +/* PMIC Vreg Control */ +#define LOG_PM_VREG_CONTROL_C (0x4A3 + LOG_1X_BASE_C) + +/* PMIC Vreg Level */ +#define LOG_PM_VREG_LEVEL_C (0x4A4 + LOG_1X_BASE_C) + +/* PMIC Vreg State */ +#define LOG_PM_VREG_STATE_C (0x4A5 + LOG_1X_BASE_C) + +/* CGPS SM EPH Randomization info */ +#define LOG_CGPS_SM_EPH_RANDOMIZATION_INFO_C (0x4A6 + LOG_1X_BASE_C) + +/* Audio calibration data */ +#define LOG_QACT_DATA_C (0x4A7 + LOG_1X_BASE_C) + +/* Compass 2D Tracked Calibration Set */ +#define LOG_SNS_VCPS_2D_TRACKED_CAL_SET (0x4A8 + LOG_1X_BASE_C) + +/* Compass 3D Tracked Calibration Set */ +#define LOG_SNS_VCPS_3D_TRACKED_CAL_SET (0x4A9 + LOG_1X_BASE_C) + +/* Calibration metric */ +#define LOG_SNS_VCPS_CAL_METRIC (0x4AA + LOG_1X_BASE_C) + +/* Accelerometer distance */ +#define LOG_SNS_VCPS_ACCEL_DIST (0x4AB + LOG_1X_BASE_C) + +/* Plane update */ +#define LOG_SNS_VCPS_PLANE_UPDATE (0x4AC + LOG_1X_BASE_C) + +/* Location report */ +#define LOG_SNS_VCPS_LOC_REPORT (0x4AD + LOG_1X_BASE_C) + +/* CM Active subscription */ +#define LOG_CM_PH_EVENT_SUBSCRIPTION_PREF_INFO_C (0x4AE + LOG_1X_BASE_C) + +/* DSDS version of CM call event */ +#define LOG_CM_DS_CALL_EVENT_C (0x4AF + LOG_1X_BASE_C) + +/* Sensors ?MobiSens Output */ +#define LOG_MOBISENS_OUTPUT_C (0x4B0 + LOG_1X_BASE_C) + +/* Accelerometer Data */ +#define LOG_ACCEL_DATA_C (0x4B1 + LOG_1X_BASE_C) + +/* Accelerometer Compensated Data */ +#define LOG_ACCEL_COMP_DATA_C (0x4B2 + LOG_1X_BASE_C) + +/* Motion State Data */ +#define LOG_MOTION_STATE_DATA_C (0x4B3 + LOG_1X_BASE_C) + +/* Stationary Position Indicator */ +#define LOG_STAT_POS_IND_C (0x4B4 + LOG_1X_BASE_C) + +/* Motion State Features */ +#define LOG_MOTION_STATE_FEATURES_C (0x4B5 + LOG_1X_BASE_C) + +/* Motion State Hard Decision */ +#define LOG_MOTION_STATE_HARD_DECISION_C (0x4B6 + LOG_1X_BASE_C) + +/* Motion State Soft Decision */ +#define LOG_MOTION_STATE_SOFT_DECISION_C (0x4B7 + LOG_1X_BASE_C) + +/* Sensors Software Version */ +#define LOG_SENSORS_SOFTWARE_VERSION_C (0x4B8 + LOG_1X_BASE_C) + +/* MobiSens Stationary Position Indicator Log Packet */ +#define LOG_MOBISENS_SPI_C (0x4B9 + LOG_1X_BASE_C) + +/* XO calibration raw IQ data */ +#define LOG_XO_IQ_DATA_C (0x4BA + LOG_1X_BASE_C) + +/*DTV CMMB Control Tabl Updated*/ +#define LOG_DTV_CMMB_CONTROL_TABLE_UPDATE ((0x4BB) + LOG_1X_BASE_C) + +/*DTV CMMB Media API Buffering Status*/ +#define LOG_DTV_CMMB_MEDIA_BUFFERING_STATUS ((0x4BC) + LOG_1X_BASE_C) + +/*DTV CMMB *Emergency Broadcast Data*/ +#define LOG_DTV_CMMB_CONTROL_EMERGENCY_BCAST ((0x4BD) + LOG_1X_BASE_C) + +/*DTV CMMB EMM/ECM Data*/ +#define LOG_DTV_CMMB_CAS_EMM_ECM ((0x4BE) + LOG_1X_BASE_C) + +/*DTV CMMB HW Status*/ +#define LOG_DTV_CMMB_HW_PERFORMANCE ((0x4BF) + LOG_1X_BASE_C) + +/*DTV CMMB ESSG Program Indication Information*/ +#define LOG_DTV_CMMB_ESG_PROGRAM_INDICATION_INFORMATION ((0x4C0) + LOG_1X_BASE_C) + +/* Sensors �C binary output of converted sensor data */ +#define LOG_CONVERTED_SENSOR_DATA_C ((0x4C1) + LOG_1X_BASE_C) + +/* CM Subscription event */ +#define LOG_CM_SUBSCRIPTION_EVENT_C ((0x4C2) + LOG_1X_BASE_C) + +/* Sensor Ambient Light Data */ +#define LOG_SNS_ALS_DATA_C ((0x4C3) + LOG_1X_BASE_C) + +/*Sensor Ambient Light Adaptive Data */ +#define LOG_SNS_ALS_DATA_ADAPTIVE_C ((0x4C4) + LOG_1X_BASE_C) + +/*Sensor Proximity Distance Data */ +#define LOG_SNS_PRX_DIST_DATA_C ((0x4C5) + LOG_1X_BASE_C) + +/*Sensor Proximity Data */ +#define LOG_SNS_PRX_DATA_C ((0x4C6) + LOG_1X_BASE_C) + +#define LOG_GNSS_SBAS_REPORT_C ((0x4C7) + LOG_1X_BASE_C) + +#define LOG_CPU_MONITOR_MODEM_C ((0x4C8) + LOG_1X_BASE_C) + +#define LOG_CPU_MONITOR_APPS_C ((0x4C9) + LOG_1X_BASE_C) + +#define LOG_BLAST_TASKPROFILE_C ((0x4CA) + LOG_1X_BASE_C) + +#define LOG_BLAST_SYSPROFILE_C ((0x4CB) + LOG_1X_BASE_C) + +#define LOG_FM_RADIO_FTM_C ((0x4CC) + LOG_1X_BASE_C) + +#define LOG_FM_RADIO_C ((0x4CD) + LOG_1X_BASE_C) + +#define LOG_UIM_DS_DATA_C ((0x4CE) + LOG_1X_BASE_C) + +#define LOG_QMI_CALL_FLOW_C ((0x4CF) + LOG_1X_BASE_C) + +#define LOG_APR_MODEM_C ((0x4D0) + LOG_1X_BASE_C) + +#define LOG_APR_APPS_C ((0x4D1) + LOG_1X_BASE_C) + +#define LOG_APR_ADSP_C ((0x4D2) + LOG_1X_BASE_C) + +#define LOG_DATA_MUX_RX_RAW_PACKET_C ((0x4D3) + LOG_1X_BASE_C) + +#define LOG_DATA_MUX_TX_RAW_PACKET_C ((0x4D4) + LOG_1X_BASE_C) + +#define LOG_DATA_MUX_RX_FRAME_PACKET_C ((0x4D5) + LOG_1X_BASE_C) + +#define LOG_DATA_MUX_TX_FRAME_PACKET_C ((0x4D6) + LOG_1X_BASE_C) + +#define LOG_CGPS_PDSM_EXT_STATUS_POS_INJ_REQ_INFO_C ((0x4D7) + LOG_1X_BASE_C) + +#define LOG_TEMPERATURE_MONITOR_C ((0x4D8) + LOG_1X_BASE_C) + +#define LOG_SNS_GESTURES_REST_DETECT_C ((0x4D9) + LOG_1X_BASE_C) + +#define LOG_SNS_GESTURES_ORIENTATION_C ((0x4DA) + LOG_1X_BASE_C) + +#define LOG_SNS_GESTURES_FACING_C ((0x4DB) + LOG_1X_BASE_C) + +#define LOG_SNS_GESTURES_BASIC_C ((0x4DC) + LOG_1X_BASE_C) + +#define LOG_SNS_GESTURES_HINBYE_C ((0x4DD) + LOG_1X_BASE_C) + +#define LOG_GNSS_OEMDRE_MEASUREMENT_REPORT_C ((0x4DE) + LOG_1X_BASE_C) + +#define LOG_GNSS_OEMDRE_POSITION_REPORT_C ((0x4E0) + LOG_1X_BASE_C) + +#define LOG_GNSS_OEMDRE_SVPOLY_REPORT_C ((0x4E1) + LOG_1X_BASE_C) + +#define LOG_GNSS_OEMDRSYNC_C ((0x4E2) + LOG_1X_BASE_C) + +#define LOG_SNS_MGR_EVENT_NOTIFY_C ((0x4E3) + LOG_1X_BASE_C) + +#define LOG_SNS_MGR_EVENT_REGISTER_C ((0x4E4) + LOG_1X_BASE_C) + +#define LOG_GNSS_PDSM_PPM_SESSION_BEGIN_C ((0x4E5) + LOG_1X_BASE_C) + +#define LOG_GNSS_PDSM_PPM_SESSION_PPM_SUSPEND_C ((0x4E6) + LOG_1X_BASE_C) + +#define LOG_GNSS_PDSM_PPM_REPORT_THROTTLED_C ((0x4E7) + LOG_1X_BASE_C) + +#define LOG_GNSS_PDSM_PPM_REPORT_FIRED_C ((0x4E8) + LOG_1X_BASE_C) + +#define LOG_GNSS_PDSM_PPM_SESSION_END_C ((0x4E9) + LOG_1X_BASE_C) + +#define LOG_TRSP_DATA_STALL_C ((0x801) + LOG_1X_BASE_C) + +#define LOG_WLAN_PKT_LOG_INFO_C ((0x8E0) + LOG_1X_BASE_C) + +/* The last defined DMSS log code */ +#define LOG_1X_LAST_C ((0x8E0) + LOG_1X_BASE_C) + + +/* This is only here for old (pre equipment ID update) logging code */ +#define LOG_LAST_C ( LOG_1X_LAST_C & 0xFFF ) + + +/* ------------------------------------------------------------------------- + * APPS LOG definition: + * The max number of 16 log codes is assigned for Apps. + * The last apps log code could be 0xB00F. + * Below definition is consolidated from log_codes_apps.h + * ------------------------------------------------------------------------- */ + +/* ======================== APPS Profiling ======================== */ +#define LOG_APPS_SYSPROFILE_C (0x01 + LOG_APPS_BASE_C) +#define LOG_APPS_TASKPROFILE_C (0x02 + LOG_APPS_BASE_C) + +/* The last defined APPS log code */ +/* Change it to (0x02 + LOG_LTE_LAST_C) to allow LTE log codes */ +#define LOG_APPS_LAST_C (0x02 + LOG_LTE_LAST_C) + +/* ------------------------------------------------------------------------- + * Log Equipment IDs. + * The number is represented by 4 bits. + * ------------------------------------------------------------------------- */ +typedef enum { + LOG_EQUIP_ID_OEM = 0, /* 3rd party OEM (licensee) use */ + LOG_EQUIP_ID_1X = 1, /* Traditional 1X line of products */ + LOG_EQUIP_ID_RSVD2 = 2, + LOG_EQUIP_ID_RSVD3 = 3, + LOG_EQUIP_ID_WCDMA = 4, + LOG_EQUIP_ID_GSM = 5, + LOG_EQUIP_ID_LBS = 6, + LOG_EQUIP_ID_UMTS = 7, + LOG_EQUIP_ID_TDMA = 8, + LOG_EQUIP_ID_BOA = 9, + LOG_EQUIP_ID_DTV = 10, + LOG_EQUIP_ID_APPS = 11, + LOG_EQUIP_ID_DSP = 12, + + LOG_EQUIP_ID_LAST_DEFAULT = LOG_EQUIP_ID_DSP + +} log_equip_id_enum_type; + +#define LOG_EQUIP_ID_MAX 0xF /* The equipment ID is 4 bits */ + +/* Note that these are the official values and are used by default in + diagtune.h. +*/ +#define LOG_EQUIP_ID_0_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_1_LAST_CODE_DEFAULT LOG_1X_LAST_C +#define LOG_EQUIP_ID_2_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_3_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_4_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_5_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_6_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_7_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_8_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_9_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_10_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_11_LAST_CODE_DEFAULT LOG_LTE_LAST_C +#define LOG_EQUIP_ID_12_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_13_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_14_LAST_CODE_DEFAULT 0 +#define LOG_EQUIP_ID_15_LAST_CODE_DEFAULT 0 + +#endif /* LOG_CODES_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_api.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_api.h new file mode 100644 index 000000000000..b3936e0bbc93 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_api.h @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ +#if !defined( __VOS_API_H ) +#define __VOS_API_H + +/**========================================================================= + + \file vos_Api.h + + \brief virtual Operating System Services (vOSS) API + + Header file that inludes all the vOSS API definitions. + + ========================================================================*/ + /*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 06/23/08 hba Added vos_preOpen() + 05/18/08 lac Created module. +===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +// one stop shopping. This brings in the entire vOSS API. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VOS_WDA_TIMEOUT 15000 + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/**-------------------------------------------------------------------------- + + \brief vos_preOpen() - PreOpen the vOSS Module + + The \a vos_preOpen() function allocates the Vos Context, but do not + initialize all the members. This overal initialization will happen + at vos_Open(). + The reason why we need vos_preOpen() is to get a minimum context + where to store BAL and SAL relative data, which happens before + vos_Open() is called. + + \param pVosContext: A pointer to where to store the VOS Context + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_open() + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_preOpen ( v_CONTEXT_t *pVosContext ); + +VOS_STATUS vos_preClose( v_CONTEXT_t *pVosContext ); + + +VOS_STATUS vos_preStart( v_CONTEXT_t vosContext ); + + +VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ); + + + +VOS_STATUS vos_start( v_CONTEXT_t vosContext ); + +VOS_STATUS vos_stop( v_CONTEXT_t vosContext ); + +VOS_STATUS vos_close( v_CONTEXT_t vosContext ); + +/* vos shutdown will not close control transport and will not handshake with Riva */ +VOS_STATUS vos_shutdown( v_CONTEXT_t vosContext ); + +/* the wda interface to shutdown */ +VOS_STATUS vos_wda_shutdown( v_CONTEXT_t vosContext ); + +/**--------------------------------------------------------------------------- + + \brief vos_get_context() - get context data area + + Each module in the system has a context / data area that is allocated + and maanged by voss. This API allows any user to get a pointer to its + allocated context data area from the VOSS global context. + + \param vosContext - the VOSS Global Context. + + \param moduleId - the module ID, who's context data are is being retrived. + + \return - pointer to the context data area. + + - NULL if the context data is not allocated for the module ID + specified + + --------------------------------------------------------------------------*/ +v_VOID_t *vos_get_context( VOS_MODULE_ID moduleId, + v_CONTEXT_t vosContext ); + + +/**--------------------------------------------------------------------------- + + \brief vos_get_global_context() - get VOSS global Context + + This API allows any user to get the VOS Global Context pointer from a + module context data area. + + \param moduleContext - the input module context pointer + + \param moduleId - the module ID who's context pointer is input in + moduleContext. + + \return - pointer to the VOSS global context + + - NULL if the function is unable to retreive the VOSS context. + + --------------------------------------------------------------------------*/ +v_CONTEXT_t vos_get_global_context( VOS_MODULE_ID moduleId, + v_VOID_t *moduleContext ); + +v_U8_t vos_is_logp_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext); +void vos_set_logp_in_progress(VOS_MODULE_ID moduleId, v_U8_t value); + +v_U8_t vos_is_load_unload_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext); +void vos_set_load_unload_in_progress(VOS_MODULE_ID moduleId, v_U8_t value); + +v_U8_t vos_is_unload_in_progress(void); +void vos_set_unload_in_progress(v_U8_t value); + + +bool vos_is_shutdown_in_progress(VOS_MODULE_ID moduleId, + v_VOID_t *moduleContext); +void vos_set_shutdown_in_progress(VOS_MODULE_ID moduleId, + bool value); + +v_U8_t vos_is_reinit_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext); +void vos_set_reinit_in_progress(VOS_MODULE_ID moduleId, v_U8_t value); + +/**--------------------------------------------------------------------------- + + \brief vos_alloc_context() - allocate a context within the VOSS global Context + + This API allows any user to allocate a user context area within the + VOS Global Context. + + \param pVosContext - pointer to the global Vos context + + \param moduleId - the module ID who's context area is being allocated. + + \param ppModuleContext - pointer to location where the pointer to the + allocated context is returned. Note this + output pointer is valid only if the API + returns VOS_STATUS_SUCCESS + + \param size - the size of the context area to be allocated. + + \return - VOS_STATUS_SUCCESS - the context for the module ID has been + allocated successfully. The pointer to the context area + can be found in *ppModuleContext. + \note This function returns VOS_STATUS_SUCCESS if the + module context was already allocated and the size + allocated matches the size on this call. + + VOS_STATUS_E_INVAL - the moduleId is not a valid or does + not identify a module that can have a context allocated. + + VOS_STATUS_E_EXISTS - vos could allocate the requested context + because a context for this module ID already exists and it is + a *different* size that specified on this call. + + VOS_STATUS_E_NOMEM - vos could not allocate memory for the + requested context area. + + \sa vos_get_context(), vos_free_context() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_alloc_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, + v_VOID_t **ppModuleContext, v_SIZE_t size ); + + +/**--------------------------------------------------------------------------- + + \brief vos_free_context() - free an allocated a context within the + VOSS global Context + + This API allows a user to free the user context area within the + VOS Global Context. + + \param pVosContext - pointer to the global Vos context + + \param moduleId - the module ID who's context area is being free + + \param pModuleContext - pointer to module context area to be free'd. + + \return - VOS_STATUS_SUCCESS - the context for the module ID has been + free'd. The pointer to the context area is not longer + available. + + VOS_STATUS_E_FAULT - pVosContext or pModuleContext are not + valid pointers. + + VOS_STATUS_E_INVAL - the moduleId is not a valid or does + not identify a module that can have a context free'd. + + VOS_STATUS_E_EXISTS - vos could not free the requested + context area because a context for this module ID does not + exist in the global vos context. + + \sa vos_get_context() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_free_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, + v_VOID_t *pModuleContext ); + +/** + @brief vos_wlanShutdown() - This API will shutdown WLAN driver + + This function is called when Riva subsystem crashes. There are two + methods (or operations) in WLAN driver to handle Riva crash, + 1. shutdown: Called when Riva goes down, this will shutdown WLAN + driver without handshaking with Riva. + 2. re-init: Next API + + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_wlanShutdown(void); + +/** + @brief vos_wlanReInit() - This API will re-init WLAN driver + + This function is called when Riva subsystem reboots. There are two + methods (or operations) in WLAN driver to handle Riva crash, + 1. shutdown: Previous API + 2. re-init: Called when Riva comes back after the crash. This will + re-initialize WLAN driver. In some cases re-open may be + referred instead of re-init. + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_wlanReInit(void); + +VOS_STATUS vos_get_vdev_types(tVOS_CON_MODE mode, tANI_U32 *type, + tANI_U32 *subType); + +/** + @brief vos_wlanRestart() - This API will reload WLAN driver. + + This function is called if driver detects any fatal state which + can be recovered by a WLAN module reload ( Android framwork initiated ). + Note that this API will not initiate any RIVA subsystem restart. + + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_wlanRestart(void); + +/** + @brief vos_fwDumpReq() + + This function is called to issue dump commands to Firmware + + @param + cmd - Command No. to execute + arg1 - argument 1 to cmd + arg2 - argument 2 to cmd + arg3 - argument 3 to cmd + arg4 - argument 4 to cmd + @return + NONE +*/ +v_VOID_t vos_fwDumpReq(tANI_U32 cmd, tANI_U32 arg1, tANI_U32 arg2, + tANI_U32 arg3, tANI_U32 arg4); + +v_VOID_t vos_flush_work(v_VOID_t *work); +v_VOID_t vos_flush_delayed_work(v_VOID_t *dwork); + +v_BOOL_t vos_is_packet_log_enabled(void); + +v_U64_t vos_get_monotonic_boottime(void); + +void vos_trigger_recovery(void); + +#ifdef FEATURE_WLAN_D0WOW +v_VOID_t vos_pm_control(v_BOOL_t vote); +#endif + +void vos_set_wakelock_logging(bool value); +bool vos_is_wakelock_enabled(void); +void vos_set_ring_log_level(uint32_t ring_id, uint32_t log_level); +enum wifi_driver_log_level vos_get_ring_log_level(uint32_t ring_id); +void vos_set_multicast_logging(uint8_t value); +uint8_t vos_is_multicast_logging(void); +VOS_STATUS vos_set_log_completion(uint32_t is_fatal, + uint32_t type, + uint32_t sub_type); +void vos_get_log_completion(uint32_t *is_fatal, + uint32_t *type, + uint32_t *sub_type); +bool vos_is_log_report_in_progress(void); +void vos_init_log_completion(void); +void vos_deinit_log_completion(void); +VOS_STATUS vos_flush_logs(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code); +void vos_logging_set_fw_flush_complete(void); +#endif // if !defined __VOS_API_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_event.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_event.h new file mode 100644 index 000000000000..c750231a8fba --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_event.h @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_DIAG_CORE_EVENT_H ) +#define __VOS_DIAG_CORE_EVENT_H + +/**========================================================================= + + \file vos_event.h + + \brief virtual Operating System Services (vOSS) DIAG Events + + Definitions for vOSS Events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_types.h" +#include "vos_pack_align.h" +#include "i_vos_diag_core_event.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define WAKE_LOCK_NAME_LEN 80 + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_SECURITY + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t eventId; + v_U8_t authMode; + v_U8_t encryptionModeUnicast; + v_U8_t encryptionModeMulticast; + v_U8_t pmkIDMatch; + v_U8_t bssid[6]; + v_U8_t keyId; + v_U8_t status; +} vos_event_wlan_security_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_STATUS + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t eventId; + v_U8_t ssid[6]; + v_U8_t bssType; + v_U8_t rssi; + v_U8_t channel; + v_U8_t qosCapability; + v_U8_t authType; + v_U8_t encryptionType; + v_U8_t reason; + v_U8_t reasonDisconnect; +} vos_event_wlan_status_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_HANDOFF + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t eventId; + v_U8_t currentApBssid[6]; + v_U8_t currentApRssi; + v_U8_t candidateApBssid[6]; + v_U8_t candidateApRssi; +} vos_event_wlan_handoff_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_VCC + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t eventId; + v_U8_t rssi; + v_U8_t txPer; + v_U8_t rxPer; + int linkQuality; +} vos_event_wlan_vcc_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_QOS + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t eventId; + v_U8_t reasonCode; +} vos_event_wlan_qos_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_PE + ------------------------------------------------------------------------*/ +typedef struct +{ + char bssid[6]; + v_U16_t event_type; + v_U16_t sme_state; + v_U16_t mlm_state; + v_U16_t status; + v_U16_t reason_code; +} vos_event_wlan_pe_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_ADD_BLOCK_ACK_SUCCESS + ------------------------------------------------------------------------*/ +typedef struct +{ + char ucBaPeerMac[6]; + v_U8_t ucBaTid; + v_U8_t ucBaBufferSize; + v_U16_t usBaSSN; + v_U8_t fInitiator; +} vos_event_wlan_add_block_ack_success_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_ADD_BLOCK_ACK_FAILED + ------------------------------------------------------------------------*/ +typedef struct +{ + char ucBaPeerMac[6]; + v_U8_t ucBaTid; + v_U8_t ucReasonCode; + v_U8_t fInitiator; +} vos_event_wlan_add_block_ack_failed_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_DELETE_BLOCK_ACK_SUCCESS + ------------------------------------------------------------------------*/ +typedef struct +{ + char ucBaPeerMac[6]; + v_U8_t ucBaTid; + v_U8_t ucDeleteReasonCode; +} vos_event_wlan_add_block_ack_deleted_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_DELETE_BLOCK_ACK_FAILED + ------------------------------------------------------------------------*/ +typedef struct +{ + char ucBaPeerMac[6]; + v_U8_t ucBaTid; + v_U8_t ucDeleteReasonCode; + v_U8_t ucFailReasonCode; +} vos_event_wlan_add_block_ack_delete_failed_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_BSS_PROTECTION + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t event_type; + v_U8_t prot_type; +} vos_event_wlan_bss_prot_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_BRINGUP_STATUS + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U16_t wlanStatus; + char driverVersion[10]; +} vos_event_wlan_bringup_status_payload_type; + +VOS_PACK_START + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_POWERSAVE_GENERIC + ------------------------------------------------------------------------*/ +typedef VOS_PACK_PRE struct +{ + v_U8_t event_subtype; + v_U32_t imps_period; + v_U8_t full_power_request_reason; + v_U8_t pmc_current_state; + v_U8_t enable_disable_powersave_mode; + v_U8_t winmob_d_power_state; + v_U8_t dtim_period; + v_U16_t final_listen_intv; + v_U16_t bmps_auto_timer_duration; + v_U16_t bmps_period; +} VOS_PACK_POST vos_event_wlan_powersave_payload_type; + +VOS_PACK_END + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_POWERSAVE_WOW + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t event_subtype; + v_U8_t wow_type; + v_U8_t wow_magic_pattern[6]; + v_U8_t wow_del_ptrn_id; + v_U8_t wow_wakeup_cause; + v_U8_t wow_wakeup_cause_pbm_ptrn_id; +} vos_event_wlan_powersave_wow_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_BTC + ------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t eventId; + v_U8_t btAddr[6]; + v_U16_t connHandle; + v_U8_t connStatus; + v_U8_t linkType; + v_U8_t scoInterval; + v_U8_t scoWindow; + v_U8_t retransWindow; + v_U8_t mode; +} vos_event_wlan_btc_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_EAPOL + ------------------------------------------------------------------------*/ +struct vos_event_wlan_eapol +{ + uint8_t event_sub_type; + uint8_t eapol_packet_type; + uint16_t eapol_key_info; + uint16_t eapol_rate; + uint8_t dest_addr[6]; + uint8_t src_addr[6]; +}; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_WAKE_LOCK + ------------------------------------------------------------------------*/ +/** + * struct vos_event_wlan_wake_lock - Structure holding the wakelock information + * @status: Whether the wakelock is taken/released + * @reason: Reason for taking this wakelock + * @timeout: Timeout value in case of timed wakelocks + * @name_len: Length of the name of the wakelock that will follow + * @name: Name of the wakelock + * + * This structure will hold the wakelock informations + */ +struct vos_event_wlan_wake_lock +{ + uint32_t status; + uint32_t reason; + uint32_t timeout; + uint32_t name_len; + char name[WAKE_LOCK_NAME_LEN]; +}; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_LOG_COMPLETE + ------------------------------------------------------------------------*/ +/** + * struct vos_event_wlan_log_complete - Holds log completion details + * @is_fatal: Indicates if the event is fatal or not + * @indicator: Source of the bug report - Framework/Host/Firmware + * @reason_code: Reason for triggering bug report + * @reserved: Reserved field + * + * This structure holds the log completion related information + */ +struct vos_event_wlan_log_complete { + uint32_t is_fatal; + uint32_t indicator; + uint32_t reason_code; + uint32_t reserved; +}; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +enum wifi_connectivity_events { + WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED, + WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED, +}; + +/** + * enum wake_lock_reason - Reason for taking wakelock + * @WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT: Driver initialization + * @WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT: Driver re-initialization + * @WIFI_POWER_EVENT_WAKELOCK_DRIVER_EXIT: Driver shutdown + * @WIFI_POWER_EVENT_WAKELOCK_SCAN: Scan request/response handling + * @WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN: Extended scan request/response handling + * @WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN: Driver resume + * @WIFI_POWER_EVENT_WAKELOCK_ROC: Remain on channel request/response handling + * @WIFI_POWER_EVENT_WAKELOCK_IPA: IPA related handling + * @WIFI_POWER_EVENT_WAKELOCK_ADD_STA: Addition of STA + * @WIFI_POWER_EVENT_WAKELOCK_HOLD_RX: Wakelocks taken for receive + * @WIFI_POWER_EVENT_WAKELOCK_SAP: SoftAP related wakelocks + * @WIFI_POWER_EVENT_WAKELOCK_WOW: WoW feature related + * @WIFI_POWER_EVENT_WAKELOCK_PNO: PNO feature related + * @WIFI_POWER_EVENT_WAKELOCK_DEL_STA: Deletion of a station + * @WIFI_POWER_EVENT_WAKELOCK_DFS: DFS related wakelocks + * @WIFI_POWER_EVENT_WAKELOCK_MISC: Miscellaneous wakelocks + * + * This enum has the reason codes why the wakelocks were taken/released + */ +enum wake_lock_reason { + WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT, + WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT, + WIFI_POWER_EVENT_WAKELOCK_DRIVER_EXIT, + WIFI_POWER_EVENT_WAKELOCK_SCAN, + WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN, + WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN, + WIFI_POWER_EVENT_WAKELOCK_ROC, + WIFI_POWER_EVENT_WAKELOCK_IPA, + WIFI_POWER_EVENT_WAKELOCK_ADD_STA, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX, + WIFI_POWER_EVENT_WAKELOCK_SAP, + WIFI_POWER_EVENT_WAKELOCK_WOW, + WIFI_POWER_EVENT_WAKELOCK_PNO, + WIFI_POWER_EVENT_WAKELOCK_DEL_STA, + WIFI_POWER_EVENT_WAKELOCK_DFS, + WIFI_POWER_EVENT_WAKELOCK_MISC, +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __VOS_DIAG_CORE_EVENT_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_log.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_log.h new file mode 100644 index 000000000000..4503c4236fbb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_diag_core_log.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_DIAG_CORE_LOG_H ) +#define __VOS_DIAG_CORE_LOG_H + +/**========================================================================= + + \file vos_event.h + + \brief virtual Operating System Services (vOSS) DIAG logs + + Definitions for vOSS Events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_types.h" +#include "i_vos_diag_core_log.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define VOS_LOG_MAX_NUM_SSID 21 +#define VOS_LOG_MAX_NUM_BSSID 21 +#define VOS_LOG_MAX_SSID_SIZE 32 +#define VOS_LOG_MAX_BSSID_SIZE 6 +#define VOS_LOG_MAX_NUM_CHANNEL 64 +#define VOS_LOG_MAX_NUM_HO_CANDIDATE_APS 20 +#define VOS_LOG_MAX_WOW_PTRN_SIZE 128 +#define VOS_LOG_MAX_WOW_PTRN_MASK_SIZE 16 +#define VOS_LOG_PKT_LOG_SIZE 2048 +#define VOS_LOG_PKT_LOG_THRESHOLD 40960 + +/* Version to be updated whenever format of vos_log_pktlog_info changes */ +#define VERSION_LOG_WLAN_PKT_LOG_INFO_C 1 + +/*--------------------------------------------------------------------------- + This packet contains the scan results of the recent scan operation + LOG_WLAN_SCAN_C 0x1496 +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U8_t eventId; + v_U8_t numSsid; + v_U8_t ssid[VOS_LOG_MAX_NUM_SSID][VOS_LOG_MAX_SSID_SIZE]; + v_U8_t bssid[VOS_LOG_MAX_NUM_BSSID][VOS_LOG_MAX_BSSID_SIZE]; + v_U8_t totalSsid; + v_U8_t minChnTime; + v_U8_t maxChnTime; + v_U16_t timeBetweenBgScan; + v_U8_t BSSMode; + v_U8_t numChannel; + v_U8_t channels[VOS_LOG_MAX_NUM_CHANNEL]; + v_U16_t status; +} vos_log_scan_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the information related to IBSS connection setup + LOG_WLAN_IBSS_C 0x1497 +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U8_t eventId; + v_U8_t channelSetting; + v_U8_t bssid[VOS_LOG_MAX_BSSID_SIZE]; + v_U8_t peerMacAddr[VOS_LOG_MAX_BSSID_SIZE]; + v_U8_t ssid[VOS_LOG_MAX_SSID_SIZE]; + v_U8_t operatingChannel; + v_U8_t beaconInterval; + v_U8_t status; +} vos_log_ibss_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the information related to 802.11D + LOG_WLAN_80211D_C 0x1498 +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U8_t eventId; + v_U8_t numChannel; + v_U8_t Channels[VOS_LOG_MAX_NUM_CHANNEL]; + v_U8_t TxPwr[VOS_LOG_MAX_NUM_CHANNEL]; + v_U8_t countryCode[3]; + v_U8_t supportMultipleDomain; +} vos_log_802_11d_pkt_type; + +/*--------------------------------------------------------------------------- +This is a log packet which contains below handoff information: +- Current AP + RSSI (if already associated) +- Candidate AP + RSSI (before association and when the list is updated) +- For each BSSID in candidate list, provide RSSI, QoS and security compatibility +LOG_WLAN_HANDOFF_C 0x1499 +---------------------------------------------------------------------------*/ +typedef struct +{ + v_U8_t ssid[9]; + v_U8_t bssid[VOS_LOG_MAX_BSSID_SIZE]; + v_U8_t channel_id; + v_U32_t qos_score; + v_U32_t sec_score; + v_U32_t rssi_score; + v_U32_t overall_score; + v_U32_t tx_per; /* represented as a % */ + v_U32_t rx_per; /* represented as a % */ + +} vos_log_ho_ap_info; + +typedef struct +{ + log_hdr_type hdr; + v_U32_t num_aps; + vos_log_ho_ap_info current_ap_info; + vos_log_ho_ap_info candidate_ap_info[VOS_LOG_MAX_NUM_HO_CANDIDATE_APS]; +} vos_log_ho_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the information related to the EDCA parameters + advertised by the AP + LOG_WLAN_QOS_EDCA_C 0x149A +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U8_t aci_be; + v_U8_t cw_be; + v_U16_t txoplimit_be; + v_U8_t aci_bk; + v_U8_t cw_bk; + v_U16_t txoplimit_bk; + v_U8_t aci_vi; + v_U8_t cw_vi; + v_U16_t txoplimit_vi; + v_U8_t aci_vo; + v_U8_t cw_vo; + v_U16_t txoplimit_vo; +} vos_log_qos_edca_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the total number of beacon received value + LOG_WLAN_BEACON_UPDATE_C 0x149B +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U32_t bcn_rx_cnt; +} vos_log_beacon_update_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the information related to a WoW patern value when set + LOG_WLAN_POWERSAVE_WOW_ADD_PTRN_C 0x149C +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U8_t pattern_id; + v_U8_t pattern_byte_offset; + v_U8_t pattern_size; + v_U8_t pattern[VOS_LOG_MAX_WOW_PTRN_SIZE]; + v_U8_t pattern_mask_size; + v_U8_t pattern_mask[VOS_LOG_MAX_WOW_PTRN_MASK_SIZE]; +} vos_log_powersave_wow_add_ptrn_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the PHY & MAC layer statistics sent by lower layer + _WLAN_LINKLAYER_STAT_C 0x14A1 +---------------------------------------------------------------------------*/ +typedef struct +{ + v_U32_t retry_cnt[4]; + v_U32_t multiple_retry_cnt[4]; + v_U32_t tx_frm_cnt[4]; + v_U32_t rx_frm_cnt; + v_U32_t frm_dup_cnt; + v_U32_t fail_cnt[4]; + v_U32_t rts_fail_cnt; + v_U32_t ack_fail_cnt; + v_U32_t rts_succ_cnt; + v_U32_t rx_discard_cnt; + v_U32_t rx_error_cnt; + v_U32_t tx_byte_cnt; + +} summaryStatsInfo; + +typedef struct +{ + v_U32_t rx_frag_cnt; + v_U32_t promiscuous_rx_frag_cnt; + v_U32_t rx_input_sensitivity; + v_U32_t max_pwr; + v_U32_t sync_fail_cnt; + v_U32_t tx_rate; + +} globalClassAStatsInfo; + +typedef struct +{ + v_U32_t uc_rx_wep_unencrypted_frm_cnt; + v_U32_t uc_rx_mic_fail_cnt; + v_U32_t uc_tkip_icv_err; + v_U32_t uc_aes_ccmp_format_err; + v_U32_t uc_aes_ccmp_replay_cnt; + v_U32_t uc_aes_ccmp_decrpt_err; + v_U32_t uc_wep_undecryptable_cnt; + v_U32_t uc_wep_icv_err; + v_U32_t uc_rx_decrypt_succ_cnt; + v_U32_t uc_rx_decrypt_fail_cnt; + v_U32_t mcbc_rx_wep_unencrypted_frm_cnt; + v_U32_t mcbc_rx_mic_fail_cnt; + v_U32_t mcbc_tkip_icv_err; + v_U32_t mcbc_aes_ccmp_format_err; + v_U32_t mcbc_aes_ccmp_replay_cnt; + v_U32_t mcbc_aes_ccmp_decrpt_err; + v_U32_t mcbc_wep_undecryptable_cnt; + v_U32_t mcbc_wep_icv_err; + v_U32_t mcbc_rx_decrypt_succ_cnt; + v_U32_t mcbc_rx_decrypt_fail_cnt; + +} globalClassBStatsInfo; + +typedef struct +{ + v_U32_t rx_amsdu_cnt; + v_U32_t rx_ampdu_cnt; + v_U32_t tx_20_frm_cnt; + v_U32_t rx_20_frm_cnt; + v_U32_t rx_mpdu_in_ampdu_cnt; + v_U32_t ampdu_delimiter_crc_err; + +} globalClassCStatsInfo; + +typedef struct +{ + v_U32_t tx_uc_frm_cnt; + v_U32_t tx_mc_frm_cnt; + v_U32_t tx_bc_frm_cnt; + v_U32_t rx_uc_frm_cnt; + v_U32_t rx_mc_frm_cnt; + v_U32_t rx_bc_frm_cnt; + v_U32_t tx_uc_byte_cnt[4]; + v_U32_t tx_mc_byte_cnt; + v_U32_t tx_bc_byte_cnt; + v_U32_t rx_uc_byte_cnt[4]; + v_U32_t rx_mc_byte_cnt; + v_U32_t rx_bc_byte_cnt; + v_U32_t rx_byte_cnt; + v_U32_t num_rx_bytes_crc_ok; + v_U32_t rx_rate; + +} globalClassDStatsInfo; + +typedef struct +{ + v_U32_t tx_frag_cnt[4]; + v_U32_t tx_ampdu_cnt; + v_U32_t tx_mpdu_in_ampdu_cnt; +} perStaStatsInfo; + +typedef struct +{ + log_hdr_type hdr; + v_U8_t version; + v_U8_t reserved[3]; + v_U32_t stat_mask; + summaryStatsInfo summaryStats; + globalClassAStatsInfo globalClassAStats; + globalClassBStatsInfo globalClassBStats; + globalClassCStatsInfo globalClassCStats; + globalClassDStatsInfo globalClassDStats; + perStaStatsInfo perStaStats; +} vos_log_statistics_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the Tspec info negotiated with the AP for the + specific AC + LOG_WLAN_QOS_TSPEC_C 0x14A2 +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_U8_t tsinfo[3]; + v_U16_t nominal_msdu_size; + v_U16_t maximum_msdu_size; + v_U32_t min_service_interval; + v_U32_t max_service_interval; + v_U32_t inactivity_interval; + v_U32_t suspension_interval; + v_U32_t svc_start_time; + v_U32_t min_data_rate; + v_U32_t mean_data_rate; + v_U32_t peak_data_rate; + v_U32_t max_burst_size; + v_U32_t delay_bound; + v_U32_t min_phy_rate; + v_U16_t surplus_bw_allowance; + v_U16_t medium_time; +} vos_log_qos_tspec_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains data information when stall detected + LOG_TRSP_DATA_STALL_C 0x1801 +---------------------------------------------------------------------------*/ + +typedef struct +{ + char channelName[4]; + v_U32_t numDesc; + v_U32_t numFreeDesc; + v_U32_t numRsvdDesc; + v_U32_t headDescOrder; + v_U32_t tailDescOrder; + v_U32_t ctrlRegVal; + v_U32_t statRegVal; + v_U32_t numValDesc; + v_U32_t numInvalDesc; +} vos_log_data_stall_channel_type; + +typedef struct +{ + log_hdr_type hdr; + v_U32_t PowerState; + v_U32_t numFreeBd; + vos_log_data_stall_channel_type dxeChannelInfo[4]; +} vos_log_data_stall_type; + +/*--------------------------------------------------------------------------- + This packet contains the rssi value from BSS descriptor + LOG_WLAN_RSSI_UPDATE_C 0x1354 +---------------------------------------------------------------------------*/ +typedef struct +{ + log_hdr_type hdr; + v_S7_t rssi; +} vos_log_rssi_pkt_type; + +/** + * struct vos_log_pktlog_info - Packet log info + * @log_hdr: Log header + * @buf_len: Length of the buffer that follows + * @buf: Buffer containing the packet log info + * + * Structure containing the packet log information + * LOG_WLAN_PKT_LOG_INFO_C 0x18E0 + */ +struct vos_log_pktlog_info { + log_hdr_type log_hdr; + uint32_t version; + uint32_t seq_no; + uint32_t buf_len; + uint8_t buf[]; +}; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __VOS_DIAG_CORE_LOG_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_event.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_event.h new file mode 100644 index 000000000000..8a0bf25a8657 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_event.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_EVENT_H ) +#define __VOS_EVENT_H + +/**========================================================================= + + \file vos_event.h + + \brief virtual Operating System Services (vOSS) Events + + Definitions for vOSS Events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_status.h" +#include "vos_types.h" +#include "i_vos_event.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + + \brief vos_event_init() - initialize a vOSS event + + The \a vos_lock_event() function initializes the specified event. Upon + successful initialization, the state of the event becomes initialized + and not 'signaled. + + An event must be initialized before it may be used in any other lock + functions. + + Attempting to initialize an already initialized event results in + a failure. + + \param lock - pointer to the opaque event object to initialize + + \return VOS_STATUS_SUCCESS - event was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the event + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the event + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to reinitialize the object referenced by event, a previously + initialized, but not yet destroyed, event. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_event_init( vos_event_t *event ); + +/*-------------------------------------------------------------------------- + + \brief vos_event_set() - set a vOSS event + + The state of the specified event is set to 'signalled by calling + \a vos_event_set(). The state of the event remains signalled until an + explicit call to vos_event_reset(). + + Any threads waiting on the event as a result of a vos_event_wait() will + be unblocked and available to be scheduled for execution when the event + is signaled by a call to \a vos_event_set(). + + \param event - the event to set to the signalled state + + \return VOS_STATUS_SUCCESS - the event was successfully signalled. + + VOS_STATUS_E_INVAL - The value specified by event does not refer + to an initialized event object. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_event_set( vos_event_t * event ); + + +/*-------------------------------------------------------------------------- + + \brief vos_event_reset() - reset a vOSS event + + The state of the specified event is set to 'NOT signalled' by calling + \a vos_event_reset(). The state of the event remains NOT signalled until an + explicit call to vos_event_set(). + + This function sets the event to a NOT signalled state even if the event was + signalled multiple times before being signaled. + + \param event - the event to set to the NOT signalled state + + \return VOS_STATUS_SUCCESS - the event state was successfully change to + NOT signalled. + + VOS_STATUS_E_INVAL - The value specified by event does not refer + to an initialized event object. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_event_reset( vos_event_t * event ); + + +/*-------------------------------------------------------------------------- + + \brief vos_event_destroy() - Destroy a vOSS event + + The \a vos_event_destroy() function shall destroy the event object + referenced by event. After a successful return from \a vos_event_destroy() + the event object becomes, in effect, uninitialized. + + A destroyed event object can be reinitialized using vos_event_init(); + the results of otherwise referencing the object after it has been destroyed + are undefined. Calls to vOSS event functions to manipulate the lock such + as vos_event_set() will fail if the event is destroyed. Therefore, + don't use the event after it has been destroyed until it has + been re-initialized. + + \param event - the event object to be destroyed. + + \return VOS_STATUS_SUCCESS - event was successfully destroyed. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by event while it is still being + referenced (there are threads waiting on this event) + + VOS_STATUS_E_INVAL - The value specified by event is invalid. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_event_destroy( vos_event_t *event ); + +/*---------------------------------------------------------------------------- + + \brief vos_wait_single_event() - Waits for a single event to be set. + + This API waits for the event to be set. + + \param pEvent - pointer to an event to wait on. + + \param timeout - Timeout value (in milliseconds). This function returns + if this interval elapses, regardless if any of the events have + been set. An input value of 0 for this timeout parameter means + to wait infinitely, meaning a timeout will never occur. + + \return VOS_STATUS_SUCCESS - the wait was satisifed by the event being + set. + + VOS_STATUS_E_TIMEOUT - the timeout interval elapsed before the + event was set. + + VOS_STATUS_E_INVAL - The value specified by event is invalid. + + VOS_STATUS_E_FAULT - pEvent is an invalid pointer. + + \sa vos_wait_multiple_events() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_wait_single_event( vos_event_t *pEvent, v_U32_t timeout ); + +/*---------------------------------------------------------------------------- + + \brief vos_wait_multiple_events() - Waits for event(s) to be set. + + This API waits for any event in the input array of events to be + set. The caller is blocked waiting any event in the array to be + set or for the timeout to occur. + + If multiple events in the array are set, only one event is identified + in the return from this call as satisfying the wait condition. The + caller is responsible for calling \a vos_wait_events() again to find + the other events that are set. + + \param pEventList - pointer to an array of event pointers + + \param numEvents - Number of events + + \param timeout - Timeout value (in milliseconds). This function returns + if this interval elapses, regardless if any of the events have + been set. An input value of 0 for this timeout parameter means + to wait infinitely, meaning a timeout will never occur. + + \param pEventIndex - This is a pointer to the location where the index of + the event in the event array that satisfied the wait because + the event was set. + + \return VOS_STATUS_SUCCESS - the wait was satisifed by one of the events + in the event array being set. The index into the event arry + that satisfied the wait can be found at *pEventIndex. + + VOS_STATUS_E_TIMEOUT - the timeout interval elapsed before any of + the events were set. + + VOS_STATUS_E_INVAL - At least one of the values specified in the + event array refers to an uninitialized event object. The invalid + event is identified by the index in *pEventIndex. Note that only + the first uninitialized event is detected when this error is + returned. + + VOS_STATUS_E_EMPTY - the events array is empty. This condition + is detected by numEvents being 0 on input. + + VOS_STATUS_E_FAULT - event or pEventIndex is an invalid pointer. + + \sa vos_wait_single_events() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_wait_multiple_events( vos_event_t **pEventList, v_U8_t numEvents, + v_U32_t timeout, v_U8_t *pEventIndex ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __VOSS_EVENT_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_getBin.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_getBin.h new file mode 100644 index 000000000000..c267ac1ce619 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_getBin.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_GETBIN_H ) +#define __VOS_GETBIN_H + +/**========================================================================= + + \file vos_getBin.h + + \brief virtual Operating System Services (vOSS) binary APIs + + Binary retrieval definitions and APIs. + + These APIs allow components to retrieve binary contents (firmware, + configuration data, etc.) from a storage medium on the platform. + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +/// Binary IDs +typedef enum +{ + /// Binary ID for firmware + VOS_BINARY_ID_FIRMWARE, + + /// Binary ID for Configuration data + VOS_BINARY_ID_CONFIG, + + /// Binary ID for country code to regulatory domain mapping + VOS_BINARY_ID_COUNTRY_INFO, + + /// Binary ID for Handoff Configuration data + VOS_BINARY_ID_HO_CONFIG, + + /// Binary ID for Dictionary Configuration data + VOS_BINARY_ID_DICT_CONFIG + +} VOS_BINARY_ID; + + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + + +/**--------------------------------------------------------------------------- + + \brief vos_get_binary_blob() - get binary data from platform + + This API allows components to get binary data from the platform independent + of where the data is stored on the device. + +
    +
  • Firmware +
  • Configuration Data +
+ + \param binaryId - identifies the binary data to return to the caller. + + \param pBuffer - a pointer to the buffer where the binary data will be + retrieved. Memory for this buffer is allocated by the caller + and free'd by the caller. vOSS will fill this buffer with + raw binary data and update the *pBufferSize with the exact + size of the data that has been retreived. + + Input value of NULL is valid and will cause the API to return + the size of the binary data in *pBufferSize. + + \param pBufferSize - pointer to a variable that upon input contains the + size of the data buffer available at pBuffer. Upon success, this + variable is updated with the size of the binary data that was + retreived and written to the buffer at pBuffer. + + Input value of 0 is valid and will cause the API to return + the size of the binary data in *pBufferSize. + + \return VOS_STATUS_SUCCESS - the binary data has been successfully + retreived and written to the buffer. + + VOS_STATUS_E_INVAL - The value specified by binaryId does not + refer to a valid VOS Binary ID. + + VOS_STATUS_E_FAULT - pBufferSize is not a valid pointer to a + variable that the API can write to. + + VOS_STATUS_E_NOMEM - the memory referred to by pBuffer and + *pBufferSize is not big enough to contain the binary. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_get_binary_blob( VOS_BINARY_ID binaryId, + v_VOID_t *pBuffer, v_SIZE_t *pBufferSize ); + +/**---------------------------------------------------------------------------- + \brief vos_get_conparam()- function to read the insmod parameters +-----------------------------------------------------------------------------*/ +tVOS_CON_MODE vos_get_conparam( void ); +tVOS_CONCURRENCY_MODE vos_get_concurrency_mode( void ); +v_BOOL_t vos_concurrent_open_sessions_running(void); +v_BOOL_t vos_max_concurrent_connections_reached(void); +void vos_clear_concurrent_session_count(void); +v_BOOL_t vos_is_multiple_active_sta_sessions (void); +v_BOOL_t vos_is_sta_active_connection_exists (void); + +#ifdef WLAN_FEATURE_MBSSID +v_BOOL_t vos_concurrent_beaconing_sessions_running(v_VOID_t); +#endif +#endif // !defined __VOS_GETBIN_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_list.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_list.h new file mode 100644 index 000000000000..98893c8adfd3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_list.h @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_LIST_H ) +#define __VOS_LIST_H + +/**========================================================================= + + \file vos_list.h + + \brief virtual Operating System Services (vOSS) List APIs + + Definitions for vOSS Linked Lists API + + Lists are implemented as a doubly linked list. An item in a list can + be of any type as long as the datatype contains a field of type + vos_link_t. + + In general, a list is a doubly linked list of items with a pointer + to the front of the list and a pointer to the end of the list. The + list items contain a forward and back link. + + List Nodes + ============= =========================== + +-------+ + | Front |------------->+---------+ +---------+ + +-------+ | Next |---->| Next |---->NULL + | Back |-+ +---------+ +---------+ + +-------+ | NULL<----| Prev |<----| Prev | + | +---------+ +---------+ + | |User Data| |User Data| + | +---------+ +---------+ + | ^ + | | + +---------------------------------+ + + This linked list API is implemented with appropriate locking + mechanisms to assure operations on the list are thread safe. + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/**--------------------------------------------------------------------------- + + \brief vos_list_init() - initialize a vOS Linked List + + The \a vos_list_init() function initializes the specified linked list + 'object'. Upon successful initialization, the state of the list + becomes initialized and available for use through the other vos_list_xxx + APIs. + + A list must be initialized by calling vos_list_init() before it + may be used in any other lock functions. + + Attempting to initialize an already initialized list results in + a failure. + + \param pList - pointer to the opaque list object to initialize + + \return VOS_STATUS_SUCCESS - list was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the list + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the list + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to reinitialize the object referenced by list, a previously + initialized, but not yet destroyed, list. + + VOS_STATUS_E_FAULT - pList is an invalid pointer. + + \sa vos_list_destroy() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_init( vos_list_t *pList ); + + +/**------------------------------------------------------------------------- + + \brief vos_list_destroy() - Destroy a vOSS List + + The \a vos_list_destroy() function shall destroy the list object + referenced by pList. After a successful return from \a vos_list_destroy() + the list object becomes, in effect, uninitialized. + + A destroyed lock object can be reinitialized using vos_list_init(); + the results of otherwise referencing the object after it has been destroyed + are undefined. Calls to vOSS list functions to manipulate the list such + will fail if the list or has not been initialized or is destroyed. + Therefore, don't use the list after it has been destroyed until it has + been re-initialized. + + \param pLlist - pointer to the list object to be destroyed. + + \return VOS_STATUS_SUCCESS - list was successfully destroyed. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by pList that is still has + nodes. The list must be empty before it can be destroyed. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList is an invalid pointer. + \sa + + ----------------------------------------------------------------------------*/ +VOS_STATUS vos_list_destroy( vos_list_t *pList ); + +/*-------------------------------------------------------------------------- + + \brief vos_list_lock() - Lock a vOSS List + + The \a vos_list_lock() function shall lock the list object to prevent + other tasks from operating on this list. The list remains locked until + a call to vos_list_unlock() is made. + + Each list function already operate within a critical section. + However it is sometimes necessary to lock a list over a series of list + function calls. + + For example, when one needs to search a node on a list and insert another + node after it, one would want to lock this list for the entire process + in case another task attempts to manipulate this list. + + \param pLlist - pointer to the list object to be locked. + + \return VOS_STATUS_SUCCESS - list was successfully locked. + + VOS_STATUS_E_FAULT - pList is an invalid pointer. + + \sa vos_list_unlock() + + ----------------------------------------------------------------------------*/ +VOS_STATUS vos_list_lock( vos_list_t *pList ); + +/*-------------------------------------------------------------------------- + + \brief vos_list_unlock() - Unlock a vOSS List + + The \a vos_list_unlock() function shall unlock the list object to allow + other tasks to use this list. This function is only called when + the vos_list_lock() is previously called in the current task. + + \param pLlist - pointer to the list object to be unlocked. + + \return VOS_STATUS_SUCCESS - list was successfully unlocked. + + VOS_STATUS_E_FAULT - pList is an invalid pointer. + + \sa vos_list_lock() + + ----------------------------------------------------------------------------*/ +VOS_STATUS vos_list_unlock( vos_list_t *pList ); + + +/**--------------------------------------------------------------------------- + + \brief vos_list_insert_front() - insert node at front of a linked list + + The vos_list_insert_front() API will insert a node at the front of + a properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be inserted + + \param pNode - Pointer to the list node to be inserted into the list. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the front of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList is an invalid pointer or pNode is an + invalid pointer. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_front( vos_list_t *pList, vos_list_node_t *pNode ); + + +/**--------------------------------------------------------------------------- + + \brief vos_list_insert_back() - insert node at back of a linked list + + The vos_list_insert_back() API will insert a node at the back of + a properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be inserted + + \param pNode - Pointer to the list node to be inserted into the list. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the back of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList is an invalid pointer or pNode is an + invalid pointer. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_back( vos_list_t *pList, vos_list_node_t *pNode ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_insert_back_size() - insert node at back of a linked list and + return the size AFTER the enqueue. This size is determined in a race free + manner i.e. while the list is locked for the enqueue operation + + The vos_list_insert_back_size() API will insert a node at the back of + a properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be inserted + + \param pNode - Pointer to the list node to be inserted into the list. + + \param pSize - Pointer to a size variable, where the size of the + list will be returned. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the back of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList is an invalid pointer or pNode is an + invalid pointer. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_back_size( vos_list_t *pList, vos_list_node_t *pNode, v_SIZE_t *pSize ); + + +/**--------------------------------------------------------------------------- + + \brief vos_list_remove_front() - remove node at front of a linked list + + The vos_list_remove_front() API will remove a node at the front of + a properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be removed + + \param ppNode - Pointer to a pointer to the list node to be removed + from the list. + + \return VOS_STATUS_SUCCESS - list node was successfully removed from + the front of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList is an invalid pointer or ppNode is an + invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_remove_front( vos_list_t *pList, vos_list_node_t **ppNode ); + + +/**--------------------------------------------------------------------------- + + \brief vos_list_remove_back() - remove node at back of a linked list + + The vos_list_remove_back() API will remove a node at the back of + a properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be removed + + \param ppNode - Pointer to a pointer to the list node to be removed + from the list. + + \return VOS_STATUS_SUCCESS - list node was successfully removed from + the back of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList is an invalid pointer or ppNode is an + invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_remove_back( vos_list_t *pList, vos_list_node_t **ppNode ); + + +/*---------------------------------------------------------------------------- + + \brief vos_list_size() - return the size of of a linked list + + The vos_list_size() API will return the number of nodes on the + given vOS List object. + + \param pList - Pointer to list object where the node will be counted + + \param pSize - Pointer to a size variable, where the size of the + list will be returned. + + \return VOS_STATUS_SUCCESS - list size of the properly initialized + vos list object has been returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList or pSize are not valid pointers + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_size( vos_list_t *pList, v_SIZE_t *pSize ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_peek_front() - peek at the node at front of a linked list + + The vos_list_peek_front() API will return a pointer to the node at the + front of a properly initialized vOS List object. The node will *not* be + removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param ppNode - Pointer to a pointer to the list node that exists at + the front of the list. + + \return VOS_STATUS_SUCCESS - list node at the front of the list was + successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList or or ppNode is an invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_peek_front( vos_list_t *pList, vos_list_node_t **ppNode ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_peek_back() - peek at the node at back of a linked list + + The vos_list_peek_back() API will return a pointer to the node at the + back of a properly initialized vOS List object. The node will *not* be + removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param ppNode - Pointer to a pointer to the list node that exists at + the back of the list. + + \return VOS_STATUS_SUCCESS - list node at the back of the list was + successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList or or ppNode is an invalid pointer. + + \sa vos_list_peek_back(), vos_list_remove_back(), vos_list_peek_front(), + vos_list_remove_front() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_peek_back( vos_list_t *pList, vos_list_node_t **ppNode ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_peek_next() - peek at the node after the specified node + + The vos_list_peek_next() API will return a pointer to the node following the + specified node on a properly initialized vOS List object. The node will + *not* be removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param pNode - Pointer to the node that is being 'peeked' + + \param ppNode - Pointer to a pointer to the list node that follows the + pNode node on the list. + + \return VOS_STATUS_SUCCESS - list node following pNode on the properly + initialized list is successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList, pNode or ppNode is an invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_peek_next( vos_list_t *pList, vos_list_node_t *pNode, + vos_list_node_t **ppNode ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_peek_prev() - peek at the node before the specified node + + The vos_list_peek_prev() API will return a pointer to the node before the + specified node on a properly initialized vOS List object. The node will + *not* be removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param pNode - Pointer to the node that is being 'peeked' + + \param ppNode - Pointer to a pointer to the list node before the + pNode node on the list. + + \return VOS_STATUS_SUCCESS - list node before pNode on the properly + initialized list is successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList, pNode or ppNode is an invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_peek_prev( vos_list_t *pList, vos_list_node_t *pNode, + vos_list_node_t **ppNode ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_insert_before() - insert node at front of a specified + list node + + The vos_list_insert_before() API will insert a node onto a properly + initialized vOS List object in front of the specified list node. + + \param pList - Pointer to list object where the node will be inserted + + \param pNodeToInsert - Pointer to the list node to be inserted into the list. + + \param pNode - Pointer to the list node where pNodeToInsert will be inserted + in front of. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the front of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList, pNodeToInsert, or pNode are + invalid pointer(s) + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_before( vos_list_t *pList, vos_list_node_t *pNodeToInsert, + vos_list_node_t *pNode ); + +/**--------------------------------------------------------------------------- + + \brief vos_list_insert_after() - insert node behind a specified list node + + The vos_list_insert_after() API will insert a node onto a properly + initialized vOS List object after the specified list node. + + \param pList - Pointer to list object where the node will be inserted + + \param pNodeToInsert - Pointer to the list node to be inserted into the list. + + \param pNode - Pointer to the list node where pNodeToInsert will be inserted + after. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the front of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList, pNodeToInsert, or pNode are + invalid pointer(s) + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_after( vos_list_t *pList, vos_list_node_t *pNodeToInsert, + vos_list_node_t *pNode ); + + +/**--------------------------------------------------------------------------- + + \brief vos_list_remove_node() - remove specified node from vOS list list + + The vos_list_remove_node() API will remove a specified node from the + properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be removed + + \param ppNode - Pointer to the node to be removed from the list. + + \return VOS_STATUS_SUCCESS - list node was successfully removed from + the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + + VOS_STATUS_E_FAULT - pList or pNodeToRemove is not a valid pointer + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_remove_node( vos_list_t *pList, vos_list_node_t *pNodeToRemove ); + + + +#endif // __VOS_LIST_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_lock.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_lock.h new file mode 100644 index 000000000000..37608982979e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_lock.h @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_LOCK_H ) +#define __VOS_LOCK_H + +/**========================================================================= + + \file vos_lock.h + + \brief virtual Operating System Servies (vOS) Locks + + Definitions for vOSS Locks + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_status.h" +#include "i_vos_lock.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + + \brief vos_lock_init() - initialize a vOSS lock + + The \a vos_lock_init() function initializes the specified lock. Upon + successful initialization, the state of the lock becomes initialized + and unlocked. + + A lock must be initialized by calling vos_lock_init() before it + may be used in any other lock functions. + + Attempting to initialize an already initialized lock results in + a failure. + + \param lock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - lock was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the lock + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the lock + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to reinitialize the object referenced by lock, a previously + initialized, but not yet destroyed, lock. + + VOS_STATUS_E_FAULT - lock is an invalid pointer. + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_init( vos_lock_t *lock ); + +/*-------------------------------------------------------------------------- + + \brief vos_lock_acquire() - acquire a lock + + A lock object is acquired by calling \a vos_lock_acquire(). If the lock + is already locked, the calling thread shall block until the lock becomes + available. This operation shall return with the lock object referenced by + lock in the locked state with the calling thread as its owner. + + \param lock - the lock object to acquire + + \return VOS_STATUS_SUCCESS - the lock was successfully acquired by + the calling thread. + + VOS_STATUS_E_INVAL - The value specified by lock does not refer + to an initialized lock object. + + VOS_STATUS_E_FAULT - lock is an invalid pointer. + + \sa + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_acquire( vos_lock_t * lock ); + + +/*-------------------------------------------------------------------------- + + \brief vos_lock_release() - release a lock + + The \a vos_lock_release() function shall release the lock object + referenced by 'lock'. + + If a thread attempts to release a lock that it unlocked or is not + initialized, an error is returned. + + \param lock - the lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + VOS_STATUS_E_INVAL - The value specified by lock does not refer + to an initialized lock object. + + VOS_STATUS_E_FAULT - The value specified by lock does not refer + to an initialized lock object. + + VOS_STATUS_E_PERM - Operation is not permitted. The calling + thread does not own the lock. + + \sa + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_release( vos_lock_t *lock ); + + +/*-------------------------------------------------------------------------- + + \brief vos_lock_destroy() - Destroy a vOSS Lock + + The \a vos_lock_destroy() function shall destroy the lock object + referenced by lock. After a successful return from \a vos_lock_destroy() + the lock object becomes, in effect, uninitialized. + + A destroyed lock object can be reinitialized using vos_lock_init(); + the results of otherwise referencing the object after it has been destroyed + are undefined. Calls to vOSS lock functions to manipulate the lock such + as vos_lock_acquire() will fail if the lock is destroyed. Therefore, + don't use the lock after it has been destroyed until it has + been re-initialized. + + \param lock - the lock object to be destroyed. + + \return VOS_STATUS_SUCCESS - lock was successfully destroyed. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by lock while it is locked + or still referenced. + + VOS_STATUS_E_INVAL - The value specified by lock is invalid. + + VOS_STATUS_E_FAULT - lock is an invalid pointer. + \sa + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_destroy( vos_lock_t *lock ); + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_init() - initializes a vOSS spin lock + + The vos_spin_lock_init() function initializes the specified spin lock. Upon + successful initialization, the state of the lock becomes initialized + and unlocked. + + A lock must be initialized by calling vos_spin_lock_init() before it + may be used in any other lock functions. + + Attempting to initialize an already initialized lock results in + a failure. + + \param pLock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - spin lock was successfully initialized and + is ready to be used. + --------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_init(vos_spin_lock_t *pLock); + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_acquire() - acquires a spin lock + + A lock object is acquired by calling \a vos_spin_lock_acquire(). If the lock + is already locked, the calling thread shall spin until the lock becomes + available. This operation shall return with the lock object referenced by + lock in the locked state with the calling thread as its owner. + + \param pLock - the lock object to acquire + + \return VOS_STATUS_SUCCESS - the lock was successfully acquired by + the calling thread. + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_acquire(vos_spin_lock_t *pLock); + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_release() - releases a lock + + The \a vos_lock_release() function shall release the spin lock object + referenced by 'lock'. + + If a thread attempts to release a lock that it unlocked or is not + initialized, an error is returned. + + \param pLock - the lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_release(vos_spin_lock_t *pLock); + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_destroy() - releases resource of a lock + + \param pLock - pointer to a lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_destroy(vos_spin_lock_t *pLock); + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_init() - initializes a vOSS wake lock + + \param pLock - the wake lock to initialize + name - wakelock name + + \return VOS_STATUS_SUCCESS - wake lock was successfully initialized and + is ready to be used. + --------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_init(vos_wake_lock_t *pLock, const char *name); + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_acquire() - acquires a wake lock + + \param pLock - the wake lock to acquire + reason - reason for taking wakelock + + \return VOS_STATUS_SUCCESS - the wake lock was successfully acquired + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_acquire(vos_wake_lock_t *pLock, uint32_t reason); + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_timeout_acquire() - acquires a wake lock with a timeout + + \param pLock - the wake lock to acquire + reason - reason for taking wakelock + + \return VOS_STATUS_SUCCESS - the wake lock was successfully acquired + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_timeout_acquire(vos_wake_lock_t *pLock, v_U32_t msec, + uint32_t reason); + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_release() - releases a wake lock + + \param pLock - the wake lock to release + reason - reason for taking wakelock + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason); + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_destroy() - destroys a wake lock + + \param pLock - the wake lock to destroy + + \return VOS_STATUS_SUCCESS - the lock was successfully destroyed + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_destroy(vos_wake_lock_t *pLock); + +VOS_STATUS vos_runtime_pm_prevent_suspend(runtime_pm_context_t context); +VOS_STATUS vos_runtime_pm_allow_suspend(runtime_pm_context_t context); +VOS_STATUS vos_runtime_pm_prevent_suspend_timeout(runtime_pm_context_t context, + unsigned int msec); +void *vos_runtime_pm_prevent_suspend_init(const char *); +void vos_runtime_pm_prevent_suspend_deinit(runtime_pm_context_t); +#endif // __VOSS_LOCK_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_memory.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_memory.h new file mode 100644 index 000000000000..2147f249a378 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_memory.h @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_MEMORY_H ) +#define __VOS_MEMORY_H + +/**========================================================================= + + \file vos_memory.h + + \brief virtual Operating System Servies (vOSS) + + Memory management functions + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#ifdef MEMORY_DEBUG +v_VOID_t vos_mem_init(v_VOID_t); +v_VOID_t vos_mem_exit(v_VOID_t); +void vos_mem_clean(void); +void vos_mem_trace_dump(int level); +#endif + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + \brief vos_mem_malloc() - vOSS Memory Allocation + + This function will dynamicallly allocate the specified number of bytes of + memory. + + \param size - the number of bytes of memory to allocate. + + \return Upon successful allocate, returns a non-NULL pointer to the + allocated memory. If this function is unable to allocate the amount of + memory specified (for any reason) it returns NULL. + + \sa + + --------------------------------------------------------------------------*/ +#ifdef MEMORY_DEBUG +#define vos_mem_malloc(size) vos_mem_malloc_debug(size, __FILE__, __LINE__) +v_VOID_t *vos_mem_malloc_debug(v_SIZE_t size, const char *fileName, + v_U32_t lineNum); +#else +v_VOID_t * vos_mem_malloc( v_SIZE_t size ); +#endif + + +/*---------------------------------------------------------------------------- + + \brief vos_mem_free() - vOSS Free Memory + + This function will free the memory pointed to by 'ptr'. + + \param ptr - pointer to the starting address of the memory to be + free'd. + + \return Nothing + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_free( v_VOID_t *ptr ); + + +/*---------------------------------------------------------------------------- + + \fn vos_mem_set() - set (fill) memory with a specified byte value. + + \param pMemory - pointer to memory that will be set + + \param numBytes - the number of bytes to be set + + \param value - the byte set in memory + + \return - Nothing. + + \sa vos_mem_zero() + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_set( v_VOID_t *ptr, v_SIZE_t numBytes, v_BYTE_t value ); + + +/*---------------------------------------------------------------------------- + + \fn vos_mem_zero() - zero out memory + + This function sets the memory location to all zeros, essentially clearing + the memory. + + \param pMemory - pointer to memory that will be set to zero + + \param numBytes - the number of bytes zero + + \param value - the byte set in memory + + \return - Nothing. + + \sa vos_mem_set() + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_zero( v_VOID_t *ptr, v_SIZE_t numBytes ); + + +/*---------------------------------------------------------------------------- + + \brief vos_mem_copy() - Copy memory + + Copy host memory from one location to another, similar to memcpy in + standard C. Note this function does not specifically handle overlapping + source and destination memory locations. Calling this function with + overlapping source and destination memory locations will result in + unpredictable results. Use vos_mem_move() if the memory locations + for the source and destination are overlapping (or could be overlapping!) + + \param pDst - pointer to destination memory location (to copy to) + + \param pSrc - pointer to source memory location (to copy from) + + \param numBytes - number of bytes to copy. + + \return - Nothing + + \sa vos_mem_move() + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_copy( v_VOID_t *pDst, const v_VOID_t *pSrc, v_SIZE_t numBytes ); + + +/*---------------------------------------------------------------------------- + + \brief vos_mem_move() - Move memory + + Move host memory from one location to another, similar to memmove in + standard C. Note this function *does* handle overlapping + source and destination memory locations. + + \param pDst - pointer to destination memory location (to move to) + + \param pSrc - pointer to source memory location (to move from) + + \param numBytes - number of bytes to move. + + \return - Nothing + + \sa vos_mem_move() + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_move( v_VOID_t *pDst, const v_VOID_t *pSrc, v_SIZE_t numBytes ); + +/** --------------------------------------------------------------------------- + + \fn vos_mem_compare() + + \brief vos_mem_compare() - Memory compare + + Function to compare two pieces of memory, similar to memcmp function + in standard C. + + \param pMemory1 - pointer to one location in memory to compare. + + \param pMemory2 - pointer to second location in memory to compare. + + \param numBytes - the number of bytes to compare. + + \return v_BOOL_t - returns a boolean value that tells if the memory + locations are equal or not equal. + + -------------------------------------------------------------------------------*/ +v_BOOL_t vos_mem_compare(const v_VOID_t *pMemory1, const v_VOID_t *pMemory2, v_U32_t numBytes ); + + +/** --------------------------------------------------------------------------- + + \fn vos_mem_compare2() + + \brief vos_mem_compare2() - Memory compare + + Function to compare two pieces of memory, similar to memcmp function + in standard C. + + \param pMemory1 - pointer to one location in memory to compare. + + \param pMemory2 - pointer to second location in memory to compare. + + \param numBytes - the number of bytes to compare. + + \return v_SINT_t - returns a boolean value that tells if the memory + locations are equal or not equal. + 0 -- equal + < 0 -- *pMemory1 is less than *pMemory2 + > 0 -- *pMemory1 is bigger than *pMemory2 + + -------------------------------------------------------------------------------*/ +v_SINT_t vos_mem_compare2( v_VOID_t *pMemory1, v_VOID_t *pMemory2, v_U32_t numBytes ); + + +/*---------------------------------------------------------------------------- + + \brief vos_mem_dma_malloc() - vOSS DMA Memory Allocation + + This function will dynamicallly allocate the specified number of bytes of + memory. This memory will have special attributes making it DMA friendly i.e. + it will exist in contiguous, 32-byte aligned uncached memory. A normal + vos_mem_malloc does not yield memory with these attributes. + + NOTE: the special DMA friendly memory is very scarce and this API must be + used sparingly + + \param size - the number of bytes of memory to allocate. + + \return Upon successful allocate, returns a non-NULL pointer to the + allocated memory. If this function is unable to allocate the amount of + memory specified (for any reason) it returns NULL. + + \sa + + --------------------------------------------------------------------------*/ +#ifdef MEMORY_DEBUG +#define vos_mem_dma_malloc(size) vos_mem_dma_malloc_debug(size, __FILE__, __LINE__) +v_VOID_t * vos_mem_dma_malloc_debug( v_SIZE_t size, char* fileName, v_U32_t lineNum); +#else +v_VOID_t * vos_mem_dma_malloc( v_SIZE_t size ); +#endif + + +/*---------------------------------------------------------------------------- + + \brief vos_mem_dma_free() - vOSS DMA Free Memory + + This function will free special DMA friendly memory pointed to by 'ptr'. + + \param ptr - pointer to the starting address of the memory to be + free'd. + + \return Nothing + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_dma_free( v_VOID_t *ptr ); + +#ifdef DMA_DIRECT_ACCESS +/*---------------------------------------------------------------------------- + + \brief vos_mem_set_dma_ptr() - vOSS DMA memory poiter set by SAL + + This function will set DMA Physical memory pointer. + + + \param dmaBuffer - pointer to the starting address of the memory to be + free'd. + + \return Nothing + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_set_dma_ptr(unsigned char *dmaBuffer); +#endif /* DMA_DIRECT_ACCESS */ + +/* + * Function to check whether the current context is in + * irq context + */ +v_BOOL_t vos_is_in_irq_context(void); +#endif // __VOSS_LOCK_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h new file mode 100644 index 000000000000..878fe86de235 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_MQ_H ) +#define __VOS_MQ_H + +/**========================================================================= + + \file vos_mq.h + + \brief virtual Operating System Services (vOSS) message queue APIs + + Message Queue Definitions and API + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/// vos Message Type. +/// This represnets a message that can be posted to another module through +/// the voss Message Queues. +/// +/// \note This is mapped directly to the tSirMsgQ for backward +/// compatibility with the legacy MAC code. + +typedef struct vos_msg_s +{ + v_U16_t type; + /* + * This field can be used as sequence number/dialog token for matching + * requests and responses. + */ + v_U16_t reserved; + /** + * Based on the type either a bodyptr pointer into + * memory or bodyval as a 32 bit data is used. + * bodyptr: is always a freeable pointer, one should always + * make sure that bodyptr is always freeable. + * + * Messages should use either bodyptr or bodyval; not both !!!. + */ + void *bodyptr; + + v_U32_t bodyval; + + /* + * Some messages provide a callback function. The function signature + * must be agreed upon between the two entities exchanging the message + */ + void *callback; + +} vos_msg_t; + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/// Message Queue IDs +typedef enum +{ + /// Message Queue ID for messages bound for SME + VOS_MQ_ID_SME = VOS_MODULE_ID_SME, + + /// Message Queue ID for messages bound for PE + VOS_MQ_ID_PE = VOS_MODULE_ID_PE, + + /// Message Queue ID for messages bound for WDA + VOS_MQ_ID_WDA = VOS_MODULE_ID_WDA, + + /// Message Queue ID for messages bound for TL + VOS_MQ_ID_TL = VOS_MODULE_ID_TL, + + /// Message Queue ID for messages bound for the SYS module + VOS_MQ_ID_SYS = VOS_MODULE_ID_SYS, + +} VOS_MQ_ID; + + +/**--------------------------------------------------------------------------- + + \brief vos_mq_post_message() - post a message to a message queue + + This API allows messages to be posted to a specific message queue. Messages + can be posted to the following message queues: + +
    +
  • SME +
  • PE +
  • HAL +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Memory for this message + buffer is allocated by the caller and free'd by the vOSS after the + message is posted to the message queue. If the consumer of the + message needs anything in this message, it needs to copy the contents + before returning from the message queue handler. + + \return VOS_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + VOS_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + VOS_STATUS_E_FAULT - message is an invalid pointer. + + VOS_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_mq_post_message( VOS_MQ_ID msgQueueId, vos_msg_t *message ); + + +/**--------------------------------------------------------------------------- + + \brief vos_tx_mq_serialize() - serialize a message to the Tx execution flow + + This API allows messages to be posted to a specific message queue in the + Tx excution flow. Messages for the Tx execution flow can be posted only + to the following queue. + +
    +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Body memory for this message + buffer is allocated by the caller and free'd by the vOSS after the + message is dispacthed to the appropriate component. If the consumer + of the message needs to keep anything in the body, it needs to copy + the contents before returning from the message handler. + + \return VOS_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + VOS_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + VOS_STATUS_E_FAULT - message is an invalid pointer. + + VOS_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_tx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *message ); + +/**--------------------------------------------------------------------------- + + \brief vos_rx_mq_serialize() - serialize a message to the Rx execution flow + + This API allows messages to be posted to a specific message queue in the + Tx excution flow. Messages for the Rx execution flow can be posted only + to the following queue. + +
    +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Body memory for this message + buffer is allocated by the caller and free'd by the vOSS after the + message is dispacthed to the appropriate component. If the consumer + of the message needs to keep anything in the body, it needs to copy + the contents before returning from the message handler. + + \return VOS_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + VOS_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + VOS_STATUS_E_FAULT - message is an invalid pointer. + + VOS_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_rx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *message ); + + +#endif // if !defined __VOS_MQ_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h new file mode 100644 index 000000000000..495d362f8885 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_NVITEM_H ) +#define __VOS_NVITEM_H + +/**========================================================================= + + \file vos_nvitem.h + + \brief virtual Operating System Services (vOSS): Non-Volatile storage API + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_types.h" +#include "vos_status.h" +#include "wlan_nv.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define VOS_COUNTRY_CODE_LEN 2 +#define VOS_MAC_ADDRESS_LEN 6 + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +// enum of regulatory doamains in WLAN +typedef enum +{ + REGDOMAIN_FCC, + REGDOMAIN_ETSI, + REGDOMAIN_JAPAN, + REGDOMAIN_WORLD, + REGDOMAIN_N_AMER_EXC_FCC, + REGDOMAIN_APAC, + REGDOMAIN_KOREA, + REGDOMAIN_HI_5GHZ, + REGDOMAIN_NO_5GHZ, + // add new regulatory domain here + REGDOMAIN_COUNT +} +v_REGDOMAIN_t; + +typedef enum +{ + COUNTRY_INIT, + COUNTRY_IE, + COUNTRY_USER, + COUNTRY_CELL_BASE, + //add new sources here + COUNTRY_QUERY, + COUNTRY_MAX = COUNTRY_QUERY +} +v_CountryInfoSource_t; + +typedef enum +{ + /* DFS Session refers to successful SAP session operating in DFS channel */ + DFS_CAC_NEVER_DONE, /* CAC was never done for this current ap / ap-ap */ + DFS_CAC_IN_PROGRESS, /* CAC is in progress for this DFS session */ + DFS_CAC_ALREADY_DONE, /* CAC already for SAP starting this DFS session */ +} +eDFS_CAC_STATUS; + +// country code type +typedef v_U8_t v_COUNTRYCODE_t[VOS_COUNTRY_CODE_LEN]; + +/**------------------------------------------------------------------------ + + \brief vos_nv_getRegDomainFromCountryCode() - get the regulatory domain of + a country given its country code + + The \a vos_nv_getRegDomainFromCountryCode() returns the regulatory domain of + a country given its country code. This is done from reading a cached + copy of the binary file. + + \param pRegDomain - pointer to regulatory domain + + \param countryCode - country code + + \param source - source of country code + + \return VOS_STATUS_SUCCESS - regulatory domain is found for the given country + VOS_STATUS_E_FAULT - invalid pointer error + VOS_STATUS_E_EMPTY - country code table is empty + VOS_STATUS_E_EXISTS - given country code does not exist in table + + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getRegDomainFromCountryCode( v_REGDOMAIN_t *pRegDomain, + const v_COUNTRYCODE_t countryCode, v_CountryInfoSource_t source); + +/**------------------------------------------------------------------------ + + \brief vos_nv_getSupportedCountryCode() - get the list of supported + country codes + + The \a vos_nv_getSupportedCountryCode() encodes the list of supported + country codes with paddings in the provided buffer + + \param pBuffer - pointer to buffer where supported country codes + and paddings are encoded; this may be set to NULL + if user wishes to query the required buffer size to + get the country code list + + \param pBufferSize - this is the provided buffer size on input; + this is the required or consumed buffer size on output + + \return VOS_STATUS_SUCCESS - country codes are successfully encoded + VOS_STATUS_E_NOMEM - country codes are not encoded because either + the buffer is NULL or buffer size is + sufficient + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getSupportedCountryCode( v_BYTE_t *pBuffer, v_SIZE_t *pBufferSize, + v_SIZE_t paddingSize ); + +/**------------------------------------------------------------------------ + \brief vos_nv_getDefaultRegDomain() - return the default regulatory domain + \return default regulatory domain + \sa + -------------------------------------------------------------------------*/ +v_REGDOMAIN_t vos_nv_getDefaultRegDomain( void ); + +/**------------------------------------------------------------------------ + \brief vos_nv_getSupportedChannels() - function to return the list of + supported channels + \param p20MhzChannels - list of 20 Mhz channels + \param pNum20MhzChannels - number of 20 Mhz channels + \param p40MhzChannels - list of 20 Mhz channels + \param pNum40MhzChannels - number of 20 Mhz channels + \return status of the NV read operation + \Note: 40Mhz not currently supported + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getSupportedChannels( v_U8_t *p20MhzChannels, int *pNum20MhzChannels, + v_U8_t *p40MhzChannels, int *pNum40MhzChannels); + +/**------------------------------------------------------------------------ + \brief vos_nv_readDefaultCountryTable() - return the default Country table + \param table data - a union to return the default country table data in. + \return status of the NV read operation + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_readDefaultCountryTable( uNvTables *tableData ); + +/**------------------------------------------------------------------------ + \brief vos_nv_getChannelListWithPower() - function to return the list of + supported channels with the power limit info too. + \param pChannels20MHz - list of 20 Mhz channels + \param pNum20MHzChannelsFound - number of 20 Mhz channels + \param pChannels40MHz - list of 20 Mhz channels + \param pNum40MHzChannelsFound - number of 20 Mhz channels + \return status of the NV read operation + \Note: 40Mhz not currently supported + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getChannelListWithPower(tChannelListWithPower *pChannels20MHz /*[NUM_LEGIT_RF_CHANNELS] */, + tANI_U8 *pNum20MHzChannelsFound, + tChannelListWithPower *pChannels40MHz /*[NUM_CHAN_BOND_CHANNELS] */, + tANI_U8 *pNum40MHzChannelsFound + ); + +/**------------------------------------------------------------------------ + + \brief vos_nv_open() - initialize the NV module + + The \a vos_nv_open() initializes the NV module. This function read the binary + file qcom_nv.bin for macaddress,country code,regulatory domain information and etc. + + \return VOS_STATUS_SUCCESS - module is initialized successfully + otherwise - module is not initialized + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_open(void); + +/**------------------------------------------------------------------------ + + \brief vos_nv_close() - uninitialize the NV module + + The \a vos_nv_init() uninitializes the NV module. This function release the binary + file qcom_nv.bin data buffer. + + \return VOS_STATUS_SUCCESS - module is initialized successfully + otherwise - module is not initialized + \sa + + -------------------------------------------------------------------------*/ + +VOS_STATUS vos_nv_close(void); + +/**------------------------------------------------------------------------ + \brief vos_nv_setRegDomain - + \param clientCtxt - Client Context, Not used for PRIMA + regId - Regulatory Domain ID + sendRegHint - send hint to cfg80211 + \return status set REG domain operation + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, + v_BOOL_t sendRegHint); + +/**------------------------------------------------------------------------ + \brief vos_nv_getChannelEnabledState - + \param rfChannel - input channel number to know enabled state + \return eNVChannelEnabledType enabled state for channel + * enabled + * disabled + * DFS + \sa + -------------------------------------------------------------------------*/ +eNVChannelEnabledType vos_nv_getChannelEnabledState(v_U32_t rfChannel); + +uint8_t vos_nv_skip_dfs_and_2g(uint32_t rf_channel); +VOS_STATUS vos_nv_get_dfs_region(uint8_t *dfs_region); +VOS_STATUS vos_nv_set_dfs_region(uint8_t dfs_region); + +#define VOS_IS_DFS_CH(channel) (vos_nv_getChannelEnabledState((channel)) == \ + NV_CHANNEL_DFS) + +VOS_STATUS vos_init_wiphy_from_nv_bin(void); +const char * voss_DomainIdtoString(const v_U8_t domainIdCurrent); +VOS_STATUS vos_init_wiphy_from_eeprom(void); +bool vos_is_dsrc_channel(uint16_t); +#endif // __VOS_NVITEM_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_pack_align.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_pack_align.h new file mode 100644 index 000000000000..7da83bd8af20 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_pack_align.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_PACK_ALIGN_H ) +#define __VOS_PACK_ALIGN_H + +/**========================================================================= + + \file vos_pack_align.h + + \brief virtual Operating System Servies (vOS) pack and align primitives + + Definitions for platform independent means of packing and aligning + data structures + + ========================================================================*/ + +/* + + Place the macro VOS_PACK_START above a structure declaration to pack. We + are not going to allow modifying the pack size because pack size cannot be + specified in AMSS and GNU. Place the macro VOS_PACK_END below a structure + declaration to stop the pack. This requirement is necessitated by Windows + which need pragma based prolog and epilog. + + Pack-size > 1-byte is not supported since gcc and arm do not support that. + + Here are some examples + + 1. Pack-size 1-byte foo_t across all platforms + + VOS_PACK_START + typedef VOS_PACK_PRE struct foo_s { ... } VOS_PACK_POST foo_t; + VOS_PACK_END + + 2. 2-byte alignment for foo_t across all platforms + + typedef VOS_ALIGN_PRE(2) struct foo_s { ... } VOS_ALIGN_POST(2) foo_t; + + 3. Pack-size 1-byte and 2-byte alignment for foo_t across all platforms + + VOS_PACK_START + typedef VOS_PACK_PRE VOS_ALIGN_PRE(2) struct foo_s { ... } VOS_ALIGN_POST(2) VOS_PACK_POST foo_t; + VOS_PACK_END + +*/ + +#if defined __GNUC__ + + #define VOS_PACK_START + #define VOS_PACK_END + + #define VOS_PACK_PRE + #define VOS_PACK_POST __attribute__((__packed__)) + + #define VOS_ALIGN_PRE(__value) + #define VOS_ALIGN_POST(__value) __attribute__((__aligned__(__value))) + +#elif defined __arm + + #define VOS_PACK_START + #define VOS_PACK_END + + #define VOS_PACK_PRE __packed + #define VOS_PACK_POST + + #define VOS_ALIGN_PRE(__value) __align(__value) + #define VOS_ALIGN_POST(__value) + +#elif defined _MSC_VER + +#define VOS_PACK_START __pragma(pack(push,1)) +#define VOS_PACK_END __pragma(pack(pop)) + + #define VOS_PACK_PRE + #define VOS_PACK_POST + + #define VOS_ALIGN_PRE(__value) __declspec(align(__value)) + #define VOS_ALIGN_POST(__value) + +#else + + #error Unsupported compiler!!! + +#endif + +#endif // __VOSS_PACK_ALIGN_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h new file mode 100644 index 000000000000..f6422a82056f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_PKT_H ) +#define __VOS_PKT_H + +/**========================================================================= + + \file vos_packet.h + + \brief virtual Operating System Services (vOSS) network Packet APIs + + Network Protocol packet/buffer support interfaces + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +struct vos_pkt_t; +typedef struct vos_pkt_t vos_pkt_t; + + +#ifdef QCA_PKT_PROTO_TRACE +#include "adf_nbuf.h" + +#define VOS_PKT_TRAC_TYPE_EAPOL NBUF_PKT_TRAC_TYPE_EAPOL +#define VOS_PKT_TRAC_TYPE_DHCP NBUF_PKT_TRAC_TYPE_DHCP +#define VOS_PKT_TRAC_TYPE_MGMT_ACTION NBUF_PKT_TRAC_TYPE_MGMT_ACTION /* Managment action frame */ + +#define VOS_PKT_TRAC_DUMP_CMD 9999 + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_get_proto_type() - + Find protoco type from packet contents + + * skb Packet Pointer + * tracking_map packet type want to track + * dot11_type, frame type when the frame is in dot11 format + +---------------------------------------------------------------------------*/ +v_U8_t vos_pkt_get_proto_type +( + struct sk_buff *skb, + v_U8_t tracking_map, + v_BOOL_t dot11_type +); + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_trace_buf_update() - + Update storage buffer with interest event string + + * event_string Event String may packet type or outstanding event + +---------------------------------------------------------------------------*/ +void vos_pkt_trace_buf_update +( + char *event_string +); + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_trace_buf_dump() - + Dump stored information into kernel log + +---------------------------------------------------------------------------*/ +void vos_pkt_trace_buf_dump +( + void +); + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_proto_trace_init() - + Initialize protocol trace functionality, allocate required resource + +---------------------------------------------------------------------------*/ +void vos_pkt_proto_trace_init +( + void +); + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_proto_trace_close() - + Free required resource + +---------------------------------------------------------------------------*/ +void vos_pkt_proto_trace_close +( + void +); +#endif /* QCA_PKT_PROTO_TRACE */ + +/** + * vos_pkt_return_packet Free the voss Packet + * @ vos Packet + */ +VOS_STATUS vos_pkt_return_packet(vos_pkt_t *packet); + +/** + * vos_pkt_get_packet_length Returns the packet length + * @ vos Packet + */ +VOS_STATUS vos_pkt_get_packet_length( vos_pkt_t *pPacket, + v_U16_t *pPacketSize ); + +/* + * TODO: Remove later + * All the below difinitions are not + * required for Host Driver 2.0 + * once corresponding references are removed + * from HDD and other layers + * below code will be removed + */ +//The size of AMSDU frame per spec can be a max of 3839 bytes +// in BD/PDUs that means 30 (one BD = 128 bytes) +// we must add the size of the 802.11 header to that +#define VPKT_SIZE_BUFFER ((30 * 128) + 32) + +/// voss Packet Types +typedef enum +{ + /// voss Packet is used to transmit 802.11 Management frames. + VOS_PKT_TYPE_TX_802_11_MGMT, + + /// voss Packet is used to transmit 802.11 Data frames. + VOS_PKT_TYPE_TX_802_11_DATA, + + /// voss Packet is used to transmit 802.3 Data frames. + VOS_PKT_TYPE_TX_802_3_DATA, + + /// voss Packet contains Received data of an unknown frame type + VOS_PKT_TYPE_RX_RAW, + + /// Invalid sentinel value + VOS_PKT_TYPE_MAXIMUM + +} VOS_PKT_TYPE; + +/// user IDs. These IDs are needed on the vos_pkt_get/set_user_data_ptr() +/// to identify the user area in the voss Packet. +typedef enum +{ + VOS_PKT_USER_DATA_ID_TL =0, + VOS_PKT_USER_DATA_ID_BAL, + VOS_PKT_USER_DATA_ID_WDA, + VOS_PKT_USER_DATA_ID_HDD, + VOS_PKT_USER_DATA_ID_BSL, + + VOS_PKT_USER_DATA_ID_MAX + +} VOS_PKT_USER_DATA_ID; + +typedef VOS_STATUS ( *vos_pkt_get_packet_callback )( vos_pkt_t *pPacket, + v_VOID_t *userData ); + +VOS_STATUS vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE pktType, + v_SIZE_t *vosFreeBuffer); +VOS_STATUS vos_pkt_get_os_packet( vos_pkt_t *pPacket, + v_VOID_t **ppOSPacket, + v_BOOL_t clearOSPacket ); +VOS_STATUS vos_pkt_wrap_data_packet( vos_pkt_t **ppPacket, + VOS_PKT_TYPE pktType, + v_VOID_t *pOSPacket, + vos_pkt_get_packet_callback callback, + v_VOID_t *userData ); +VOS_STATUS vos_pkt_set_os_packet( vos_pkt_t *pPacket, + v_VOID_t *pOSPacket ); +VOS_STATUS vos_pkt_get_timestamp( vos_pkt_t *pPacket, + v_TIME_t* pTstamp ); +VOS_STATUS vos_pkt_walk_packet_chain( vos_pkt_t *pPacket, + vos_pkt_t **ppChainedPacket, + v_BOOL_t unchainPacket ); +VOS_STATUS vos_pkt_peek_data( vos_pkt_t *pPacket, + v_SIZE_t pktOffset, + v_VOID_t **ppPacketData, + v_SIZE_t numBytes ); +VOS_STATUS vos_pkt_get_packet( vos_pkt_t **ppPacket, + VOS_PKT_TYPE pktType, + v_SIZE_t dataSize, + v_SIZE_t numPackets, + v_BOOL_t zeroBuffer, + vos_pkt_get_packet_callback callback, + v_VOID_t *userData ); +VOS_STATUS vos_pkt_reserve_head( vos_pkt_t *pPacket, + v_VOID_t **ppData, + v_SIZE_t dataSize ); +VOS_STATUS vos_pkt_pop_head( vos_pkt_t *pPacket, + v_VOID_t *pData, + v_SIZE_t dataSize ); +VOS_STATUS vos_pkt_push_head( vos_pkt_t *pPacket, + v_VOID_t *pData, + v_SIZE_t dataSize ); +v_VOID_t vos_pkt_get_user_data_ptr( vos_pkt_t *pPacket, + VOS_PKT_USER_DATA_ID userID, + v_VOID_t **ppUserData ); +v_VOID_t vos_pkt_set_user_data_ptr( vos_pkt_t *pPacket, + VOS_PKT_USER_DATA_ID userID, + v_VOID_t *pUserData ); +VOS_STATUS vos_pkt_extract_data( vos_pkt_t *pPacket, + v_SIZE_t pktOffset, + v_VOID_t *pOutputBuffer, + v_SIZE_t *pOutputBufferSize ); +#endif // !defined( __VOS_PKT_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_status.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_status.h new file mode 100644 index 000000000000..663d626fb151 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_status.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_STATUS_H ) +#define __VOS_STATUS_H + +/**========================================================================= + + \file vos_Status.h + + \brief virtual Operating System Services (vOSS) Status codes + + Basic status codes/definitions used by vOSS + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +typedef enum +{ + /// Request succeeded! + VOS_STATUS_SUCCESS, + + /// Request failed because system resources (other than memory) to + /// fulfill request are not available. + VOS_STATUS_E_RESOURCES, + + /// Request failed because not enough memory is available to + /// fulfill the request. + VOS_STATUS_E_NOMEM, + + /// Request could not be fulfilled at this time. Try again later. + VOS_STATUS_E_AGAIN, + + /// Request failed because there of an invalid request. This is + /// typically the result of invalid parameters on the request. + VOS_STATUS_E_INVAL, + + /// Request failed because handling the request would cause a + /// system fault. This error is typically returned when an + /// invalid pointer to memory is detected. + VOS_STATUS_E_FAULT, + + /// Request refused becayse a request is already in progress and + /// another cannot be handled currently. + VOS_STATUS_E_ALREADY, + + /// Request failed because the message (type) is bad, invalid, or + /// not properly formatted. + VOS_STATUS_E_BADMSG, + + /// Request failed because device or resource is busy. + VOS_STATUS_E_BUSY, + + /// Request did not complete because it was canceled. + VOS_STATUS_E_CANCELED, + + /// Request did not complete because it was aborted. + VOS_STATUS_E_ABORTED, + + /// Request failed because the request is valid, though not supported + /// by the entity processing the request. + VOS_STATUS_E_NOSUPPORT, + + /// Operation is not permitted. + VOS_STATUS_E_PERM, + + /// Request failed because of an empty condition + VOS_STATUS_E_EMPTY, + + /// Existance failure. Operation could not be completed because + /// something exists or does not exist. + VOS_STATUS_E_EXISTS, + + /// Operation timed out + VOS_STATUS_E_TIMEOUT, + + /// Request failed for some unknown reason. Note don't use this + /// status unless nothing else applies + VOS_STATUS_E_FAILURE + +} VOS_STATUS; + +/// Macro to determine if a VOS_STATUS type is success. All callers +/// wanting to interpret VOS_STATUS should use this macro to check +/// for success to protect against the VOS_STATUS definitions +/// changing. +/// +/// Use like this... +/// +/// if ( VOS_STATUS_SUCCESS( vosStatus ) ) ... +/// +#define VOS_IS_STATUS_SUCCESS( status ) ( VOS_STATUS_SUCCESS == ( status ) ) + + + +#endif // if !defined __VOS_STATUS_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_threads.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_threads.h new file mode 100644 index 000000000000..613152e1d0b3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_threads.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_THREADS_H ) +#define __VOS_THREADS_H + +/**========================================================================= + + \file vos_threads.h + + \brief virtual Operating System Services (vOSS) Threading APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + \brief vos_sleep() - sleep + + The \a vos_sleep() function suspends the execution of the current thread + until the specified time out interval elapses. + + \param msInterval - the number of milliseconds to suspend the current thread. + A value of 0 may or may not cause the current thread to yield. + + \return Nothing. + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_sleep( v_U32_t msInterval ); + +/*---------------------------------------------------------------------------- + + \brief vos_sleep_us() - sleep + + The \a vos_sleep_us() function suspends the execution of the current thread + until the specified time out interval elapses. + + \param usInterval - the number of microseconds to suspend the current thread. + A value of 0 may or may not cause the current thread to yield. + + \return Nothing. + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_sleep_us( v_U32_t usInterval ); + + +/*---------------------------------------------------------------------------- + + \brief vos_busy_wait() - busy wait + + The \a vos_busy_wait() function places the current thread in busy wait + until the specified time out interval elapses. If the interval is greater + than 50us on WM, the behaviour is undefined. + + \param usInterval - the number of microseconds to busy wait. + + \return Nothing. + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_busy_wait( v_U32_t usInterval ); + +#endif // __VOS_THREADS_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_timer.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_timer.h new file mode 100644 index 000000000000..96ecfd1934f9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_timer.h @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_TIMER_H ) +#define __VOS_TIMER_H + +/**========================================================================= + + \file vos_timer.h + + \brief virtual Operating System Servies (vOS) + + Definitions for vOSS Timer services + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include + +#ifdef TIMER_MANAGER +#include "wlan_hdd_dp_utils.h" +#endif + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define VOS_TIMER_STATE_COOKIE 0x12 +#define VOS_TIMER_TO_MS_UNIT 1000 +#define VOS_TIMER_TO_SEC_UNIT 1000000 + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +/// vos Timer callback function prototype (well, actually a prototype for +/// a pointer to this callback function) +typedef v_VOID_t ( *vos_timer_callback_t )( v_PVOID_t userData ); + +typedef enum +{ + /// pure software timer. No guarantee the apps processor will + /// awaken when these timers expire. + VOS_TIMER_TYPE_SW, + + /// These timers can awaken the Apps processor from power collapse + /// when these timers expire. + /// \todo I really dont like this name :-) + VOS_TIMER_TYPE_WAKE_APPS + +} VOS_TIMER_TYPE; + +typedef enum +{ + VOS_TIMER_STATE_UNUSED = VOS_TIMER_STATE_COOKIE, + VOS_TIMER_STATE_STOPPED, + VOS_TIMER_STATE_STARTING, + VOS_TIMER_STATE_RUNNING, +} VOS_TIMER_STATE; + +#ifdef TIMER_MANAGER +struct vos_timer_s; +typedef struct timer_node_s +{ + hdd_list_node_t pNode; + char* fileName; + unsigned int lineNum; + struct vos_timer_s *vosTimer; +}timer_node_t; +#endif + +typedef struct vos_timer_s +{ +#ifdef TIMER_MANAGER + timer_node_t *ptimerNode; +#endif + + vos_timer_platform_t platformInfo; + vos_timer_callback_t callback; + v_PVOID_t userData; + vos_lock_t lock; + VOS_TIMER_TYPE type; + VOS_TIMER_STATE state; +} vos_timer_t; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +#ifdef TIMER_MANAGER +void vos_timer_manager_init(void); +void vos_timer_exit(void); +#endif + +/*--------------------------------------------------------------------------- + + \brief vos_timer_getCurrentState() - Get the current state of the timer + + \param pTimer - the timer object + + \return timer state + + \sa + +---------------------------------------------------------------------------*/ +VOS_TIMER_STATE vos_timer_getCurrentState( vos_timer_t *pTimer ); + +/*-------------------------------------------------------------------------- + + \brief vos_timer_init() - Initialize a vOSS timer. + + This API initializes a vOS Timer object. + + The \a vos_timer_init() initializes a vOS Timer object. A timer must be + initialized by calling vos_timer_initialize() before it may be used in + any other timer functions. + + Attempting to initialize timer that is already initialized results in + a failure. A destroyed timer object can be re-initialized with a call to + \a vos_timer_init(). The results of otherwise referencing the object + after it has been destroyed are undefined. + + Calls to vOSS timer functions to manipulate the timer such + as vos_timer_set() will fail if the timer is not initialized or has + been destroyed. Therefore, don't use the timer after it has been + destroyed until it has been re-initialized. + + All callback will be executed within the VOS main thread unless it is + initialized from the Tx thread flow, in which case it will be executed + within the tx thread flow. + + \param timer - pointer to the opaque timer object to initialize + + \param timerType - specifies the type of timer. We have two different + timer types. +
    +
  1. VOS_TIMER_TYPE_SW - Pure software timer. The Apps processor + may not be awoken when this timer expires. +
  2. VOS_TIMER_TYPE_WAKE_APPS - The Apps processor will be awoken + from power collapse when this type of timer expires. +
+ + \param callback - the callback function to be called when the timer + expires. + + \param userData - a user data (or context) that is returned to the + callback function as a parameter when the timer expires. + + \return VOS_STATUS_SUCCESS - timer was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initialize the timer + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the timer + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to initialize the object referenced by timer, a previously + initialized but not yet destroyed timer. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + +---------------------------------------------------------------------------*/ +#ifdef TIMER_MANAGER +#define vos_timer_init(timer, timerType, callback, userdata) \ + vos_timer_init_debug(timer, timerType, callback, userdata, __FILE__, __LINE__) + +VOS_STATUS vos_timer_init_debug( vos_timer_t *timer, VOS_TIMER_TYPE timerType, + vos_timer_callback_t callback, v_PVOID_t userData, + char* fileName, v_U32_t lineNum ); +#else +VOS_STATUS vos_timer_init( vos_timer_t *timer, VOS_TIMER_TYPE timerType, + vos_timer_callback_t callback, v_PVOID_t userData ); +#endif + +/*--------------------------------------------------------------------------- + + \brief vos_timer_destroy() - Destroy a vOSS Timer object + + The \a vos_timer_destroy() function shall destroy the timer object. + After a successful return from \a vos_timer_destroy() the timer + object becomes, in effect, uninitialized. + + A destroyed timer object can be re-initialized by calling + vos_timer_init(). The results of otherwise referencing the object + after it has been destroyed are undefined. + + Calls to vOSS timer functions to manipulate the timer, such + as vos_timer_set() will fail if the lock is destroyed. Therefore, + don't use the timer after it has been destroyed until it has + been re-initialized. + + \param timer - the timer object to be destroyed. + + \return VOS_STATUS_SUCCESS - timer was successfully destroyed. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by timer while it is still + still referenced. The timer must be stopped before it can be + destroyed. + + VOS_STATUS_E_INVAL - The value specified by timer is invalid. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_timer_destroy( vos_timer_t *timer ); + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_start() - Start a vOSS Timer object + + The \a vos_timer_start() function starts a timer to expire after the + specified interval, thus running the timer callback function when + the interval expires. + + A timer only runs once (a one-shot timer). To re-start the + timer, vos_timer_start() has to be called after the timer runs + or has been cancelled. + + \param timer - the timer object to be started + + \param expirationTime - expiration time for the timer (in milliseconds) + The expiration time cannot be less than 10 ms. + + \return VOS_STATUS_SUCCESS - timer was successfully started. + + VOS_STATUS_E_ALREADY - The implementation has detected an attempt + to start a timer while it is already started. The timer must + be stopped or expire before it can be started again. + + VOS_STATUS_E_INVAL - The value specified by timer is invalid. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_timer_start( vos_timer_t *timer, v_U32_t expirationTime ); + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_stop() - Stop a vOSS Timer + + The \a vos_timer_stop() function stops a timer that has been started but + has not expired, essentially cancelling the 'start' request. + + After a timer is stopped, it goes back to the state it was in after it + was created and can be started again via a call to vos_timer_start(). + + \param timer - the timer object to be stopped + + \return VOS_STATUS_SUCCESS - timer was successfully stopped. + + VOS_STATUS_E_EMPTY - The implementation has detected an attempt + to stop a timer that has not been started or has already + expired. + + VOS_STATUS_E_INVAL - The value specified by timer is invalid. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_timer_stop( vos_timer_t *timer ); + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_get_system_ticks() - Get the system time in 10ms ticks + + The \a vos_timer_get_system_ticks() function returns the current number + of timer ticks in 10msec intervals. This function is suitable timestamping + and calculating time intervals by calculating the difference between two + timestamps. + + \returns - The current system tick count (in 10msec intervals). This + function cannot fail. + + \sa + + ------------------------------------------------------------------------*/ +v_TIME_t vos_timer_get_system_ticks( v_VOID_t ); + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_get_system_time() - Get the system time in milliseconds + + The \a vos_timer_get_system_time() function returns the number of milliseconds + that have elapsed since the system was started + + \returns - The current system time in milliseconds. + + \sa + + ------------------------------------------------------------------------*/ +v_TIME_t vos_timer_get_system_time( v_VOID_t ); + + + +#endif // #if !defined __VOSS_TIMER_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_trace.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_trace.h new file mode 100644 index 000000000000..957cf4c1a4d6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_trace.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_TRACE_H ) +#define __VOS_TRACE_H + +/**========================================================================= + + \file vos_trace.h + + \brief virtual Operating System Servies (vOS) + + Trace, logging, and debugging definitions and APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include // For VOS_MODULE_ID... +#include // For va_list... +#include +#include + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +typedef enum +{ + // NONE means NO traces will be logged. This value is in place for the + // vos_trace_setlevel() to allow the user to turn off all traces. + VOS_TRACE_LEVEL_NONE = 0, + + // the following trace levels are the ones that 'callers' of VOS_TRACE() + // can specify in for the VOS_TRACE_LEVEL parameter. Traces are classified + // by severity (FATAL being more serious than INFO for example). + VOS_TRACE_LEVEL_FATAL, + VOS_TRACE_LEVEL_ERROR, + VOS_TRACE_LEVEL_WARN, + VOS_TRACE_LEVEL_INFO, + VOS_TRACE_LEVEL_INFO_HIGH, + VOS_TRACE_LEVEL_INFO_MED, + VOS_TRACE_LEVEL_INFO_LOW, + VOS_TRACE_LEVEL_DEBUG, + + // ALL means all trace levels will be active. This value is in place for the + // vos_trace_setlevel() to allow the user to turn ON all traces. + VOS_TRACE_LEVEL_ALL, + + + // not a real level. Used to identify the maximum number of + // VOS_TRACE_LEVELs defined. + VOS_TRACE_LEVEL_MAX + +} VOS_TRACE_LEVEL; + +/* By default Data Path module will be enabled ERROR and FATAL level + * Too many default log level will break performance + */ +#define VOS_DATA_PATH_TRACE_LEVEL \ + ((1 << VOS_TRACE_LEVEL_FATAL) | (1 << VOS_TRACE_LEVEL_ERROR)) + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define ASSERT_BUFFER_SIZE ( 512 ) + +// below definition is obsolete and is no longer being used in BMP and WM +// TODO: remove this once this is not used on Android +#define VOS_ENABLE_TRACING +#define MAX_VOS_TRACE_RECORDS 4000 +#define INVALID_VOS_TRACE_ADDR 0xffffffff +#define DEFAULT_VOS_TRACE_DUMP_COUNT 0 + +#include + +#ifdef TRACE_RECORD + +#define MTRACE(p) p +#define NO_SESSION 0xFF + +#else +#define MTRACE(p) { } + +#endif + +/*-------------------------------------------------------------------------- + Structure definition + ------------------------------------------------------------------------*/ +typedef struct svosTraceRecord +{ + v_U64_t time; + v_U8_t module; + v_U8_t code; + v_U16_t session; + v_U32_t data; + uint32_t pid; +}tvosTraceRecord, *tpvosTraceRecord; + +typedef struct svosTraceData +{ + // MTRACE logs are stored in ring buffer where head represents the position + // of first record, tail represents the position of last record added till + // now and num is the count of total record added. + v_U32_t head; + v_U32_t tail; + v_U32_t num; + v_U16_t numSinceLastDump; + + //Config for controlling the trace + v_U8_t enable; + v_U16_t dumpCount; //will dump after number of records reach this number. + +}tvosTraceData; + + +#define CASE_RETURN_STRING( str ) \ + case ( ( str ) ): return( (tANI_U8*)(#str) ); + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- + + \brief vos_trace_setLevel() - Set the trace level for a particular module + + This is an external API that allows trace levels to be set for each module. + + \param level - trace level. A member of the VOS_TRACE_LEVEL + enumeration indicating the severity of the condition causing the + trace message to be issued. More severe conditions are more + likely to be logged. + + \return nothing + + \sa + --------------------------------------------------------------------------*/ +void vos_trace_setLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ); + +/**---------------------------------------------------------------------------- + + \brief vos_trace_getLevel() - Get the trace level + + This is an external API that returns a boolean value to signify if a + particular trace level is set for the specified module. + + \param level - trace level. A member of the VOS_TRACE_LEVEL enumeration + indicating the severity of the condition causing the trace + message to be issued. + + Note that individual trace levels are the only valid values + for this API. VOS_TRACE_LEVEL_NONE and VOS_TRACE_LEVEL_ALL + are not valid input and will return FALSE + + \return VOS_FALSE - the specified trace level for the specified module is OFF + + VOS_TRUE - the specified trace level for the specified module is ON + + \sa vos_trace_setLevel() + --------------------------------------------------------------------------*/ +v_BOOL_t vos_trace_getLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ); + +typedef void (*tpvosTraceCb) (void *pMac, tpvosTraceRecord, v_U16_t); +void vos_trace(v_U8_t module, v_U8_t code, v_U16_t session, v_U32_t data); +void vosTraceRegister(VOS_MODULE_ID, tpvosTraceCb); +VOS_STATUS vos_trace_spin_lock_init(void); +void vosTraceInit(void); +void vosTraceEnable(v_U32_t, v_U8_t enable); +void vosTraceDumpAll(void*, v_U8_t, v_U8_t, v_U32_t, v_U32_t); +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_types.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_types.h new file mode 100644 index 000000000000..69f2abe41f61 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_types.h @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_TYPES_H ) +#define __VOS_TYPES_H +/**========================================================================= + \file vos_Types.h + + \brief virtual Operating System Servies (vOS) + + Basic type definitions + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "i_vos_types.h" +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +// macro to get maximum of two values. +#define VOS_MAX( _x, _y ) ( ( (_x) > (_y) ) ? (_x) : (_y) ) + +// macro to get minimum of two values +#define VOS_MIN( _x, _y ) ( ( (_x) < (_y) ) ? (_x) : (_y) ) + +// macro to get the ceiling of an integer division operation... +#define VOS_CEIL_DIV( _a, _b ) (( 0 != (_a) % (_b) ) ? ( (_a) / (_b) + 1 ) : ( (_a) / (_b) )) + +// macro to return the floor of an integer division operation +#define VOS_FLOOR_DIV( _a, _b ) ( ( (_a) - ( (_a) % (_b) ) ) / (_b) ) + +#define VOS_SWAP_U16(_x) \ + ( ( ( (_x) << 8 ) & 0xFF00 ) | ( ( (_x) >> 8 ) & 0x00FF ) ) + +#define VOS_SWAP_U32(_x) \ + (( ( ( (_x) << 24 ) & 0xFF000000 ) | ( ( (_x) >> 24 ) & 0x000000FF ) ) | \ + ( ( ( (_x) << 8 ) & 0x00FF0000 ) | ( ( (_x) >> 8 ) & 0x0000FF00 ) )) + +// Endian operations for Big Endian and Small Endian modes +#ifdef ANI_LITTLE_BYTE_ENDIAN + +#define vos_cpu_to_be32(_x) VOS_SWAP_U32(_x) +#define vos_be32_to_cpu(_x) VOS_SWAP_U32(_x) +#define vos_cpu_to_be16(_x) VOS_SWAP_U16(_x) +#define vos_be16_to_cpu(_x) VOS_SWAP_U16(_x) +#define vos_cpu_to_le32(_x) (_x) +#define vos_le32_to_cpu(_x) (_x) +#define vos_cpu_to_le16(_x) (_x) +#define vos_le16_to_cpu(_x) (_x) + +#endif + +#ifdef ANI_BIG_BYTE_ENDIAN + +#define vos_cpu_to_be32(_x) (_x) +#define vos_be32_to_cpu(_x) (_x) +#define vos_cpu_to_be16(_x) (_x) +#define vos_be16_to_cpu(_x) (_x) +#define vos_cpu_to_le32(_x) VOS_SWAP_U32(_x) +#define vos_le32_to_cpu(_x) VOS_SWAP_U32(_x) +#define vos_cpu_to_le16(_x) VOS_SWAP_U16(_x) +#define vos_le16_to_cpu(_x) VOS_SWAP_U16(_x) + +#endif + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/// Module IDs. These are generic IDs that identify the various modules +/// in the software system. +typedef enum +{ + /* 0 is unused for historical purposes */ + VOS_MODULE_ID_TL = 1, + VOS_MODULE_ID_WDI = 2, + // 3 & 4 are unused for historical purposes + VOS_MODULE_ID_RSV3 = 3, + VOS_MODULE_ID_RSV4 = 4, + VOS_MODULE_ID_HDD = 5, + VOS_MODULE_ID_SME = 6, + VOS_MODULE_ID_PE = 7, + VOS_MODULE_ID_WDA = 8, + VOS_MODULE_ID_SYS = 9, + VOS_MODULE_ID_VOSS = 10, + VOS_MODULE_ID_SAP = 11, + VOS_MODULE_ID_HDD_SOFTAP = 12, + VOS_MODULE_ID_PMC = 13, + VOS_MODULE_ID_HDD_DATA = 14, + VOS_MODULE_ID_HDD_SAP_DATA = 15, + + VOS_MODULE_ID_HIF = 16, + VOS_MODULE_ID_HTC = 17, + VOS_MODULE_ID_TXRX = 18, + VOS_MODULE_ID_ADF = 19, + VOS_MODULE_ID_CFG = 20, + + // not a real module ID. This is used to identify the maxiumum + // number of VOS_MODULE_IDs and should always be at the END of + // this enum. If IDs are added, they need to go in front of this + VOS_MODULE_ID_MAX + +} VOS_MODULE_ID; + + +/// Concurrency role. These are generic IDs that identify the various roles +/// in the software system. +typedef enum +{ /*ON linux maintain 1-1 corespondence with device_mode_t in hdd*/ + VOS_STA_MODE=0, + VOS_STA_SAP_MODE=1, //to support softAp mode . This is misleading. It means AP MODE only. + //The constant name has historical reason + VOS_P2P_CLIENT_MODE, + VOS_P2P_GO_MODE, + VOS_MONITOR_MODE, + VOS_FTM_MODE = 5, + VOS_IBSS_MODE, + VOS_P2P_DEVICE_MODE, + VOS_OCB_MODE, + VOS_MAX_NO_OF_MODE +} tVOS_CON_MODE; + +#ifdef WLAN_OPEN_P2P_INTERFACE +#define VOS_MAX_CONCURRENCY_PERSONA 4 // This should match with WLAN_MAX_INTERFACES +#else +#define VOS_MAX_CONCURRENCY_PERSONA 3 +#endif + +//This is a bit pattern to be set for each mode +//bit 0 - sta mode +//bit 1 - ap mode +//bit 2 - p2p client mode +//bit 3 - p2p go mode +typedef enum +{ + VOS_STA=1, + VOS_SAP=2, + VOS_STA_SAP=3, //to support sta, softAp mode . This means STA+AP mode + VOS_P2P_CLIENT=4, + VOS_P2P_GO=8, +} tVOS_CONCURRENCY_MODE; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +typedef enum +{ + VOS_MCC_TO_SCC_SWITCH_DISABLE = 0, + VOS_MCC_TO_SCC_SWITCH_ENABLE, + VOS_MCC_TO_SCC_SWITCH_FORCE, + VOS_MCC_TO_SCC_SWITCH_MAX +} tVOS_MCC_TO_SCC_SWITCH_MODE; +#endif + +#if !defined( NULL ) +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +enum +{ + VOS_FALSE = 0, + VOS_TRUE = ( !VOS_FALSE ) +}; + +/// pointer to void types +typedef v_VOID_t *v_PVOID_t; + +/// "Size" type... +typedef v_UINT_t v_SIZE_t; + +/// 'Time' type +typedef v_ULONG_t v_TIME_t; + +// typedef for VOSS Context... +typedef v_VOID_t *v_CONTEXT_t; + + +/// MAC address data type and corresponding macros/functions to +/// manipulate MAC addresses... +/// Macro defining the size of a MAC Address... +#define VOS_MAC_ADDR_SIZE ( 6 ) + +typedef struct +{ + /// the bytes that make up the macAddress. + v_BYTE_t bytes[ VOS_MAC_ADDR_SIZE ]; + +} v_MACADDR_t; + + +/// This macro is used to initialize a vOSS MacAddress to the +/// broadcast MacAddress. It is used like this... +/// v_MACADDR_t macAddress = VOS_MAC_ADDR_BROADCAST_INITIALIZER; +#define VOS_MAC_ADDR_BROADCAST_INITIALIZER { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } + +/// This macro is used to initialize a vOSS MacAddress to zero +/// It is used like this... +/// v_MACADDR_t macAddress = VOS_MAC_ADDR_ZERO_INITIALIZER; +#define VOS_MAC_ADDR_ZERO_INITIALIZER { { 0, 0, 0, 0, 0, 0 } } + +#define VOS_IPV4_ADDR_SIZE ( 4 ) + +/*---------------------------------------------------------------------------- + + \brief vos_is_macaddr_equal() - compare two vOSS MacAddress + + This function returns a boolean that tells if a two vOSS MacAddress' + are equivalent. + + \param pMacAddr1 - pointer to one voss MacAddress to compare + \param pMacAddr2 - pointer to the other voss MacAddress to compare + + \return true - the MacAddress's are equal + not true - the MacAddress's are not equal + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_BOOL_t vos_is_macaddr_equal( v_MACADDR_t *pMacAddr1, + v_MACADDR_t *pMacAddr2 ) +{ + return ( 0 == memcmp( pMacAddr1, pMacAddr2, VOS_MAC_ADDR_SIZE ) ); +} + + + +/*---------------------------------------------------------------------------- + + \brief vos_is_macaddr_zero() - check for a MacAddress of all zeros. + + This function returns a boolean that tells if a MacAddress is made up of + all zeros. + + \param pMacAddr - pointer to the v_MACADDR_t to check. + + \return true - the MacAddress is all Zeros + not true - the MacAddress is not all Zeros. + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_BOOL_t vos_is_macaddr_zero( v_MACADDR_t *pMacAddr ) +{ + v_MACADDR_t zeroMacAddr = VOS_MAC_ADDR_ZERO_INITIALIZER; + + return( vos_is_macaddr_equal( pMacAddr, &zeroMacAddr ) ); +} + + +/*---------------------------------------------------------------------------- + + \brief vos_zero_macaddr() - zero out a MacAddress + + This function zeros out a vOSS MacAddress type. + + \param pMacAddr - pointer to the v_MACADDR_t to zero. + + \return nothing + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_VOID_t vos_zero_macaddr( v_MACADDR_t *pMacAddr ) +{ + memset( pMacAddr, 0, VOS_MAC_ADDR_SIZE ); +} + + +/*---------------------------------------------------------------------------- + + \brief vos_is_macaddr_group() - check for a MacAddress is a 'group' address + + This function returns a boolean that tells if a the input vOSS MacAddress + is a "group" address. Group addresses have the 'group address bit' turned + on in the MacAddress. Group addresses are made up of Broadcast and + Multicast addresses. + + \param pMacAddr1 - pointer to the voss MacAddress to check + + \return true - the input MacAddress is a Group address + not true - the input MacAddress is not a Group address + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_BOOL_t vos_is_macaddr_group( v_MACADDR_t *pMacAddr ) +{ + return( pMacAddr->bytes[ 0 ] & 0x01 ); +} + + +/*---------------------------------------------------------------------------- + + \brief vos_is_macaddr_broadcast() - check for a MacAddress is a broadcast address + + This function returns a boolean that tells if a the input vOSS MacAddress + is a "broadcast" address. + + \param pMacAddr - pointer to the voss MacAddress to check + + \return true - the input MacAddress is a broadcast address + not true - the input MacAddress is not a broadcast address + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_BOOL_t vos_is_macaddr_broadcast( v_MACADDR_t *pMacAddr ) +{ + v_MACADDR_t broadcastMacAddr = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + + return( vos_is_macaddr_equal( pMacAddr, &broadcastMacAddr ) ); +} + +/*---------------------------------------------------------------------------- + + \brief vos_is_macaddr_multicast() - check for a MacAddress is a multicast address + + This function returns a boolean that tells if a the input vOSS MacAddress + is a "Multicast" address. + + \param pMacAddr - pointer to the voss MacAddress to check + + \return true - the input MacAddress is a Multicast address + not true - the input MacAddress is not a Multicast address + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_BOOL_t vos_is_macaddr_multicast( v_MACADDR_t *pMacAddr ) +{ + return( vos_is_macaddr_group( pMacAddr ) && + !vos_is_macaddr_broadcast( pMacAddr ) ); +} + + + +/*---------------------------------------------------------------------------- + + \brief vos_is_macaddr_directed() - check for a MacAddress is a directed address + + This function returns a boolean that tells if a the input vOSS MacAddress + is a "directed" address. + + \param pMacAddr - pointer to the voss MacAddress to check + + \return true - the input MacAddress is a directed address + not true - the input MacAddress is not a directed address + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_BOOL_t vos_is_macaddr_directed( v_MACADDR_t *pMacAddr ) +{ + return( !vos_is_macaddr_group( pMacAddr ) ); +} + +/*---------------------------------------------------------------------------- + + \brief vos_copy_macaddr() - copy a vOSS MacAddress + + This function copies a vOSS MacAddress into another vOSS MacAddress. + + \param pDst - pointer to the voss MacAddress to copy TO (the destination) + \param pSrc - pointer to the voss MacAddress to copy FROM (the source) + + \return nothing + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_VOID_t vos_copy_macaddr( v_MACADDR_t *pDst, v_MACADDR_t *pSrc ) +{ + *pDst = *pSrc; +} + + +/*---------------------------------------------------------------------------- + + \brief vos_set_macaddr_broadcast() - set a vOSS MacAddress to the 'broadcast' + + This function sets a vOSS MacAddress to the 'broadcast' MacAddress. Broadcast + MacAddress contains all 0xFF bytes. + + \param pMacAddr - pointer to the voss MacAddress to set to broadcast + + \return nothing + + \sa + + --------------------------------------------------------------------------*/ +VOS_INLINE_FN v_VOID_t vos_set_macaddr_broadcast( v_MACADDR_t *pMacAddr ) +{ + memset( pMacAddr, 0xff, VOS_MAC_ADDR_SIZE ); +} + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_set() - set a variable atomically + + \param pTarget - pointer to the variable to set. + + \param value - the value to set in the variable. + + \return This function returns the value previously in the uintptr_t before + the new value is set. + + \sa vos_atomic_increment_U32(), vos_atomic_decrement_U32() + + --------------------------------------------------------------------------*/ +uintptr_t vos_atomic_set( uintptr_t *pTarget, uintptr_t value ); + + +// TODO: the below function is a stub to perform atomic set on a BYTE +// Clearly the function below is not an atomic function +VOS_INLINE_FN v_U8_t vos_atomic_set_U8( v_U8_t *pVariable, v_U8_t value ) +{ + if (pVariable == NULL) + { + return 0; + } + *pVariable = value; + return value; +} + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_increment_U32() - Increment a U32 variable atomically + + \param pTarget - pointer to the v_U32_t to increment. + + \return This function returns the value of the variable after the + increment occurs. + + \sa vos_atomic_decrement_U32(), vos_atomic_set_U32() + + --------------------------------------------------------------------------*/ +v_U32_t vos_atomic_increment_U32( v_U32_t *pTarget ); + + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_decrement_U32() - Decrement a U32 variable atomically + + \param pTarget - pointer to the v_U32_t to decrement. + + \return This function returns the value of the variable after the + decrement occurs. + + \sa vos_atomic_increment_U32(), vos_atomic_set_U32() + + --------------------------------------------------------------------------*/ +v_U32_t vos_atomic_decrement_U32( v_U32_t *pTarget ); + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_increment_U32_by_value() - Increment a U32 variable atomically + by a given value + + \param pTarget - pointer to the v_U32_t to decrement. + \param value - the value that needs to be added to target + + \return This function returns the value of the variable after the + decrement occurs. + + \sa vos_atomic_increment_U32(), vos_atomic_set_U32() + + --------------------------------------------------------------------------*/ +v_U32_t vos_atomic_increment_U32_by_value( v_U32_t *pTarget, v_U32_t value ); + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_decrement_U32_by_value() - Decrement a U32 variable atomically + by a given value + + \param pTarget - pointer to the v_U32_t to decrement. + \param value - the value that needs to be substracted from target + + \return This function returns the value of the variable after the + decrement occurs. + + \sa vos_atomic_increment_U32(), vos_atomic_set_U32() + + --------------------------------------------------------------------------*/ +v_U32_t vos_atomic_decrement_U32_by_value( v_U32_t *pTarget, v_U32_t value ); + + +v_U32_t vos_get_skip_ssid_check(void); + +v_U32_t vos_get_skip_11e_check(void); + + + +#endif // if !defined __VOSS_TYPES_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h new file mode 100644 index 000000000000..bd3b81489bfe --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2011-2012, 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#if !defined( __VOS_UTILS_H ) +#define __VOS_UTILS_H + +/**========================================================================= + + \file vos_utils.h + + \brief virtual Operating System Services (vOSS) utility APIs + + Various utility functions + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include "aniGlobal.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define VOS_DIGEST_SHA1_SIZE 20 +#define VOS_DIGEST_MD5_SIZE 16 +#define VOS_BAND_2GHZ 1 +#define VOS_BAND_5GHZ 2 + +#define VOS_24_GHZ_BASE_FREQ 2407 +#define VOS_5_GHZ_BASE_FREQ 5000 +#define VOS_24_GHZ_CHANNEL_14 14 +#define VOS_24_GHZ_CHANNEL_15 15 +#define VOS_24_GHZ_CHANNEL_27 27 +#define VOS_5_GHZ_CHANNEL_170 170 +#define VOS_CHAN_SPACING_5MHZ 5 +#define VOS_CHAN_SPACING_20MHZ 20 +#define VOS_CHAN_14_FREQ 2484 +#define VOS_CHAN_15_FREQ 2512 +#define VOS_CHAN_170_FREQ 5852 +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +VOS_STATUS vos_crypto_init( v_U32_t *phCryptProv ); + +VOS_STATUS vos_crypto_deinit( v_U32_t hCryptProv ); + + + +/** + * vos_rand_get_bytes + + * FUNCTION: + * Returns cryptographically secure pseudo-random bytes. + * + * + * @param pbBuf - the caller allocated location where the bytes should be copied + * @param numBytes the number of bytes that should be generated and + * copied + * + * @return VOS_STATUS_SUCCSS if the operation succeeds +*/ +VOS_STATUS vos_rand_get_bytes( v_U32_t handle, v_U8_t *pbBuf, v_U32_t numBytes ); + + +/** + * vos_sha1_hmac_str + * + * FUNCTION: + * Generate the HMAC-SHA1 of a string given a key. + * + * LOGIC: + * Standard HMAC processing from RFC 2104. The code is provided in the + * appendix of the RFC. + * + * ASSUMPTIONS: + * The RFC is correct. + * + * @param text text to be hashed + * @param textLen length of text + * @param key key to use for HMAC + * @param keyLen length of key + * @param digest holds resultant SHA1 HMAC (20B) + * + * @return VOS_STATUS_SUCCSS if the operation succeeds + * + */ +VOS_STATUS vos_sha1_hmac_str(v_U32_t cryptHandle, /* Handle */ + v_U8_t *text, /* pointer to data stream */ + v_U32_t textLen, /* length of data stream */ + v_U8_t *key, /* pointer to authentication key */ + v_U32_t keyLen, /* length of authentication key */ + v_U8_t digest[VOS_DIGEST_SHA1_SIZE]);/* caller digest to be filled in */ + +/** + * vos_md5_hmac_str + * + * FUNCTION: + * Generate the HMAC-MD5 of a string given a key. + * + * LOGIC: + * Standard HMAC processing from RFC 2104. The code is provided in the + * appendix of the RFC. + * + * ASSUMPTIONS: + * The RFC is correct. + * + * @param text text to be hashed + * @param textLen length of text + * @param key key to use for HMAC + * @param keyLen length of key + * @param digest holds resultant MD5 HMAC (16B) + * + * @return VOS_STATUS_SUCCSS if the operation succeeds + * + */ +VOS_STATUS vos_md5_hmac_str(v_U32_t cryptHandle, /* Handle */ + v_U8_t *text, /* pointer to data stream */ + v_U32_t textLen, /* length of data stream */ + v_U8_t *key, /* pointer to authentication key */ + v_U32_t keyLen, /* length of authentication key */ + v_U8_t digest[VOS_DIGEST_MD5_SIZE]);/* caller digest to be filled in */ + + + +VOS_STATUS vos_encrypt_AES(v_U32_t cryptHandle, /* Handle */ + v_U8_t *pText, /* pointer to data stream */ + v_U8_t *Encrypted, + v_U8_t *pKey); /* pointer to authentication key */ + + +VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */ + v_U8_t *pText, /* pointer to data stream */ + v_U8_t *pDecrypted, + v_U8_t *pKey); /* pointer to authentication key */ + +v_U32_t vos_chan_to_freq(v_U8_t chan); +v_U8_t vos_freq_to_chan(v_U32_t freq); +v_U8_t vos_chan_to_band(v_U32_t chan); +#ifdef WLAN_FEATURE_11W +v_BOOL_t vos_is_mmie_valid(v_U8_t *key, v_U8_t *ipn, + v_U8_t* frm, v_U8_t* efrm); +v_BOOL_t vos_attach_mmie(v_U8_t *igtk, v_U8_t *ipn, u_int16_t key_id, + v_U8_t* frm, v_U8_t* efrm, u_int16_t frmLen); +v_U8_t vos_get_mmie_size(void); +#endif /* WLAN_FEATURE_11W */ + +eHalStatus vos_send_flush_logs_cmd_to_fw(tpAniSirGlobal pMac); +#endif // #if !defined __VOSS_UTILS_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/wcnss_api.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/wcnss_api.h new file mode 100644 index 000000000000..71b561489cc7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/wcnss_api.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _WCNSS_API_H_ +#define _WCNSS_API_H_ + + +/* + * Do nothing for non ISOC + */ +#define wcnss_wlan_get_drvdata(dev) NULL + +static inline void wcnss_wlan_register_pm_ops(void *dev, void *pm_ops) +{ +} + +static inline void wcnss_wlan_unregister_pm_ops(void *dev, void *pm_ops) +{ +} + +static inline void wcnss_register_thermal_mitigation(void *dev, void *tmnotify) +{ +} + +static inline void wcnss_unregister_thermal_mitigation(void *tm_notify) +{ +} + +static inline void wcnss_prevent_suspend(void) +{ +} + +static inline void wcnss_allow_suspend(void) +{ +} + +static inline unsigned int wcnss_get_serial_number(void) +{ + return 0; +} + +#if !defined(CONFIG_CNSS) && !defined(HIF_USB) && !defined(HIF_SDIO) +static inline void *wcnss_wlan_crypto_alloc_ahash(const char *alg_name, + unsigned int type, + unsigned int mask) +{ + return NULL; +} + +static inline int wcnss_wlan_crypto_ahash_digest(void *req) +{ + return 0; +} + +static inline void wcnss_wlan_crypto_free_ahash(void *tfm) +{ +} + +static inline int wcnss_wlan_crypto_ahash_setkey(void *tfm, + const u8 *key, + unsigned int keylen) +{ + return 0; +} + +static inline void *wcnss_wlan_crypto_alloc_ablkcipher(const char *alg_name, + u32 type, u32 mask) +{ + return NULL; +} + +static inline void wcnss_wlan_ablkcipher_request_free(void *req) +{ +} + +static inline void wcnss_wlan_crypto_free_ablkcipher(void *tfm) +{ +} +#endif /* !CONFIG_CNSS */ + +static inline int req_riva_power_on_lock(char *driver_name) +{ + return 0; +} + +static inline int free_riva_power_on_lock(char *driver_name) +{ + return 0; +} + + +#endif /* #ifndef _WCNSS_API_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/wlan_hdd_misc.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/wlan_hdd_misc.h new file mode 100644 index 000000000000..8b94ccfadb82 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/wlan_hdd_misc.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WLAN_HDD_MISC_H +#define WLAN_HDD_MISC_H + +#ifdef MSM_PLATFORM +#define WLAN_INI_FILE "wlan/qca_cld/WCNSS_qcom_cfg.ini" +#define WLAN_CFG_FILE "wlan/qca_cld/WCNSS_cfg.dat" +#define WLAN_MAC_FILE "wlan/qca_cld/wlan_mac.bin" +#else +#define WLAN_INI_FILE "wlan/qcom_cfg.ini" +#define WLAN_CFG_FILE "wlan/cfg.dat" +#define WLAN_MAC_FILE "wlan/wlan_mac.bin" +#endif // MSM_PLATFORM + +VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize); + +VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName, v_VOID_t *pBuffer, v_SIZE_t *pBufSize); + +tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void ); + +#endif /* WLAN_HDD_MISC_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c new file mode 100644 index 000000000000..a1c74a0394b4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c @@ -0,0 +1,2959 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file vos_api.c + + \brief Stub file for all virtual Operating System Services (vOSS) APIs + + ========================================================================*/ + /*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 03/29/09 kanand Created module. +===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include "vos_sched.h" +#include +#include "sirTypes.h" +#include "sirApi.h" +#include "sirMacProtDef.h" +#include "sme_Api.h" +#include "macInitApi.h" +#include "wlan_qct_sys.h" +#include "wlan_qct_tl.h" +#include "wlan_hdd_misc.h" +#include "i_vos_packet.h" +#include "vos_nvitem.h" +#include "wlan_qct_wda.h" +#include "wlan_hdd_main.h" +#include +#include "wlan_hdd_cfg80211.h" +#ifdef CONFIG_CNSS +#include +#endif + +#include "sapApi.h" +#include "vos_trace.h" + + + +#include "bmi.h" +#include "ol_fw.h" +#include "ol_if_athvar.h" +#if defined(HIF_PCI) +#include "if_pci.h" +#elif defined(HIF_USB) +#include "if_usb.h" +#elif defined(HIF_SDIO) +#include "if_ath_sdio.h" +#endif +#include "vos_utils.h" +#include "wlan_logging_sock_svc.h" +#include "wma.h" + +/*--------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * ------------------------------------------------------------------------*/ +/* Approximate amount of time to wait for WDA to stop WDI */ +#define VOS_WDA_STOP_TIMEOUT WDA_STOP_TIMEOUT + +/* Approximate amount of time to wait for WDA to issue a DUMP req */ +#define VOS_WDA_RESP_TIMEOUT WDA_STOP_TIMEOUT + +/* Maximum number of vos message queue get wrapper failures to cause panic */ +#define VOS_WRAPPER_MAX_FAIL_COUNT (VOS_CORE_MAX_MESSAGES * 3) + +/*--------------------------------------------------------------------------- + * Data definitions + * ------------------------------------------------------------------------*/ +static VosContextType gVosContext; +static pVosContextType gpVosContext; + +/* Debug variable to detect MC thread stuck */ +static atomic_t vos_wrapper_empty_count; + +static uint8_t vos_multicast_logging; +/*--------------------------------------------------------------------------- + * Forward declaration + * ------------------------------------------------------------------------*/ +v_VOID_t vos_sys_probe_thread_cback ( v_VOID_t *pUserData ); + +v_VOID_t vos_core_return_msg(v_PVOID_t pVContext, pVosMsgWrapper pMsgWrapper); + +v_VOID_t vos_fetch_tl_cfg_parms ( WLANTL_ConfigInfoType *pTLConfig, + hdd_config_t * pConfig ); + + +/*--------------------------------------------------------------------------- + + \brief vos_preOpen() - PreOpen the vOSS Module + + The \a vos_preOpen() function allocates the Vos Context, but do not + initialize all the members. This overal initialization will happen + at vos_Open(). + The reason why we need vos_preOpen() is to get a minimum context + where to store BAL and SAL relative data, which happens before + vos_Open() is called. + + \param pVosContext: A pointer to where to store the VOS Context + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_Open() + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_preOpen ( v_CONTEXT_t *pVosContext ) +{ + if ( pVosContext == NULL) + return VOS_STATUS_E_FAILURE; + + /* Allocate the VOS Context */ + *pVosContext = NULL; + gpVosContext = &gVosContext; + + if (NULL == gpVosContext) + { + /* Critical Error ...Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to allocate VOS Context", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_RESOURCES; + } + + vos_mem_zero(gpVosContext, sizeof(VosContextType)); + + *pVosContext = gpVosContext; + + /* Initialize the spinlock */ + vos_trace_spin_lock_init(); + /* it is the right time to initialize MTRACE structures */ + #if defined(TRACE_RECORD) + vosTraceInit(); + #endif + + return VOS_STATUS_SUCCESS; + +} /* vos_preOpen()*/ + + +/*--------------------------------------------------------------------------- + + \brief vos_preClose() - PreClose the vOSS Module + + The \a vos_preClose() function frees the Vos Context. + + \param pVosContext: A pointer to where the VOS Context was stored + + + \return VOS_STATUS_SUCCESS - Always successful + + + \sa vos_preClose() + \sa vos_close() +---------------------------------------------------------------------------*/ +VOS_STATUS vos_preClose( v_CONTEXT_t *pVosContext ) +{ + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: De-allocating the VOS Context", __func__); + + if (( pVosContext == NULL) || (*pVosContext == NULL)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vOS Context is Null", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (gpVosContext != *pVosContext) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Context mismatch", __func__); + return VOS_STATUS_E_FAILURE; + } + + *pVosContext = gpVosContext = NULL; + + return VOS_STATUS_SUCCESS; + +} /* vos_preClose()*/ + +#ifdef FEATURE_RUNTIME_PM +static inline void vos_runtime_pm_config(struct ol_softc *scn, + hdd_context_t *pHddCtx) +{ + scn->enable_runtime_pm = pHddCtx->cfg_ini->runtime_pm; + scn->runtime_pm_delay = pHddCtx->cfg_ini->runtime_pm_delay; +} +#else +static inline void vos_runtime_pm_config(struct ol_softc *scn, + hdd_context_t *pHddCtx) { } +#endif + +#if defined (FEATURE_SECURE_FIRMWARE) && defined (FEATURE_FW_HASH_CHECK) +static inline void vos_fw_hash_check_config(struct ol_softc *scn, + hdd_context_t *pHddCtx) +{ + scn->enable_fw_hash_check = pHddCtx->cfg_ini->enable_fw_hash_check; +} +#elif defined (FEATURE_SECURE_FIRMWARE) +static inline void vos_fw_hash_check_config(struct ol_softc *scn, + hdd_context_t *pHddCtx) +{ + scn->enable_fw_hash_check = true; +} +#else +static inline void vos_fw_hash_check_config(struct ol_softc *scn, + hdd_context_t *pHddCtx) { } +#endif + +#ifdef WLAN_FEATURE_NAN +/** + * vos_set_nan_enable() - set nan enable flag in mac open param + * @wma_handle: Pointer to mac open param + * @hdd_ctx: Pointer to hdd context + * + * Return: none + */ +static void vos_set_nan_enable(tMacOpenParameters *param, + hdd_context_t *hdd_ctx) +{ + param->is_nan_enabled = hdd_ctx->cfg_ini->enable_nan_support; +} +#else +static void vos_set_nan_enable(tMacOpenParameters *param, + hdd_context_t *pHddCtx) +{ +} +#endif + +/*--------------------------------------------------------------------------- + + \brief vos_open() - Open the vOSS Module + + The \a vos_open() function opens the vOSS Scheduler + Upon successful initialization: + + - All VOS submodules should have been initialized + + - The VOS scheduler should have opened + + - All the WLAN SW components should have been opened. This includes + SYS, MAC, SME, WDA and TL. + + + \param hddContextSize: Size of the HDD context to allocate. + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_preOpen() + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ) + +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + int iter = 0; + tSirRetStatus sirStatus = eSIR_SUCCESS; + tMacOpenParameters macOpenParms; + WLANTL_ConfigInfoType TLConfig; + adf_os_device_t adf_ctx; + HTC_INIT_INFO htcInfo; + struct ol_softc *scn; + v_VOID_t *HTCHandle; + hdd_context_t *pHddCtx; + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Opening VOSS", __func__); + + if (NULL == gpVosContext) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Trying to open VOSS without a PreOpen", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* Initialize the timer module */ + vos_timer_module_init(); + + /* Initialize bug reporting structure */ + vos_init_log_completion(); + + /* Initialize the probe event */ + if (vos_event_init(&gpVosContext->ProbeEvent) != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Unable to init probeEvent", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + if (vos_event_init( &(gpVosContext->wdaCompleteEvent) ) != VOS_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Unable to init wdaCompleteEvent", __func__); + VOS_ASSERT(0); + + goto err_probe_event; + } + + /* Initialize the free message queue */ + vStatus = vos_mq_init(&gpVosContext->freeVosMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to initialize VOS free message queue", __func__); + VOS_ASSERT(0); + goto err_wda_complete_event; + } + + for (iter = 0; iter < VOS_CORE_MAX_MESSAGES; iter++) + { + (gpVosContext->aMsgWrappers[iter]).pVosMsg = + &(gpVosContext->aMsgBuffers[iter]); + INIT_LIST_HEAD(&gpVosContext->aMsgWrappers[iter].msgNode); + vos_mq_put(&gpVosContext->freeVosMq, &(gpVosContext->aMsgWrappers[iter])); + } + + /* Now Open the VOS Scheduler */ + vStatus= vos_sched_open(gpVosContext, &gpVosContext->vosSched, + sizeof(VosSchedContext)); + + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to open VOS Scheduler", __func__); + VOS_ASSERT(0); + goto err_msg_queue; + } + + pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext); + if((NULL == pHddCtx) || + (NULL == pHddCtx->cfg_ini)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Hdd Context is Null", __func__); + VOS_ASSERT(0); + goto err_sched_close; + } + + scn = vos_get_context(VOS_MODULE_ID_HIF, gpVosContext); + if (!scn) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: scn is null!", __func__); + goto err_sched_close; + } + scn->enableuartprint = pHddCtx->cfg_ini->enablefwprint; + scn->enablefwlog = pHddCtx->cfg_ini->enablefwlog; + scn->enableFwSelfRecovery = pHddCtx->cfg_ini->enableFwSelfRecovery; + scn->max_no_of_peers = pHddCtx->cfg_ini->maxNumberOfPeers; +#ifdef WLAN_FEATURE_LPSS + scn->enablelpasssupport = pHddCtx->cfg_ini->enablelpasssupport; +#endif + scn->enableRamdumpCollection = pHddCtx->cfg_ini->is_ramdump_enabled; + scn->enable_self_recovery = pHddCtx->cfg_ini->enableSelfRecovery; + + vos_fw_hash_check_config(scn, pHddCtx); + vos_runtime_pm_config(scn, pHddCtx); + + /* Initialize BMI and Download firmware */ + if (bmi_download_firmware(scn)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: BMI failed to download target", __func__); + goto err_bmi_close; + } + htcInfo.pContext = gpVosContext->pHIFContext; + htcInfo.TargetFailure = ol_target_failure; + htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; + adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, gpVosContext); + + /* Create HTC */ + gpVosContext->htc_ctx = HTCCreate(htcInfo.pContext, &htcInfo, adf_ctx); + if (!gpVosContext->htc_ctx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to Create HTC", __func__); + goto err_bmi_close; + goto err_sched_close; + } + + if (bmi_done(scn)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_htc_close; + } + + /* + ** Need to open WDA first because it calls WDI_Init, which calls wpalOpen + ** The reason that is needed becasue vos_packet_open need to use PAL APIs + */ + + /*Open the WDA module */ + vos_mem_set(&macOpenParms, sizeof(macOpenParms), 0); + /* UMA is supported in hardware for performing the + ** frame translation 802.11 <-> 802.3 + */ + macOpenParms.frameTransRequired = 1; + macOpenParms.driverType = eDRIVER_TYPE_PRODUCTION; + macOpenParms.powersaveOffloadEnabled = + pHddCtx->cfg_ini->enablePowersaveOffload; + macOpenParms.staDynamicDtim = pHddCtx->cfg_ini->enableDynamicDTIM; + macOpenParms.staModDtim = pHddCtx->cfg_ini->enableModulatedDTIM; + macOpenParms.staMaxLIModDtim = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; + macOpenParms.wowEnable = pHddCtx->cfg_ini->wowEnable; + macOpenParms.maxWoWFilters = pHddCtx->cfg_ini->maxWoWFilters; + /* Here olIniInfo is used to store ini status of arp offload + * ns offload and others. Currently 1st bit is used for arp + * off load and 2nd bit for ns offload currently, rest bits are unused + */ + if ( pHddCtx->cfg_ini->fhostArpOffload) + macOpenParms.olIniInfo = macOpenParms.olIniInfo | 0x1; + if ( pHddCtx->cfg_ini->fhostNSOffload) + macOpenParms.olIniInfo = macOpenParms.olIniInfo | 0x2; + /* + * Copy the DFS Phyerr Filtering Offload status. + * This parameter reflects the value of the + * dfsPhyerrFilterOffload flag as set in the ini. + */ + macOpenParms.dfsPhyerrFilterOffload = + pHddCtx->cfg_ini->fDfsPhyerrFilterOffload; + + macOpenParms.ssdp = pHddCtx->cfg_ini->ssdp; + macOpenParms.enable_bcst_ptrn = pHddCtx->cfg_ini->bcastptrn; + +#ifdef FEATURE_WLAN_RA_FILTERING + macOpenParms.RArateLimitInterval = pHddCtx->cfg_ini->RArateLimitInterval; + macOpenParms.IsRArateLimitEnabled = pHddCtx->cfg_ini->IsRArateLimitEnabled; +#endif + + macOpenParms.force_target_assert_enabled = + pHddCtx->cfg_ini->crash_inject_enabled; + macOpenParms.apMaxOffloadPeers = pHddCtx->cfg_ini->apMaxOffloadPeers; + + macOpenParms.apMaxOffloadReorderBuffs = + pHddCtx->cfg_ini->apMaxOffloadReorderBuffs; + + macOpenParms.apDisableIntraBssFwd = pHddCtx->cfg_ini->apDisableIntraBssFwd; + + macOpenParms.dfsRadarPriMultiplier = pHddCtx->cfg_ini->dfsRadarPriMultiplier; + macOpenParms.reorderOffload = pHddCtx->cfg_ini->reorderOffloadSupport; + +#ifdef IPA_UC_OFFLOAD + /* IPA micro controller data path offload resource config item */ + macOpenParms.ucOffloadEnabled = pHddCtx->cfg_ini->IpaUcOffloadEnabled; + macOpenParms.ucTxBufCount = pHddCtx->cfg_ini->IpaUcTxBufCount; + macOpenParms.ucTxBufSize = pHddCtx->cfg_ini->IpaUcTxBufSize; + macOpenParms.ucRxIndRingCount = pHddCtx->cfg_ini->IpaUcRxIndRingCount; + macOpenParms.ucTxPartitionBase = pHddCtx->cfg_ini->IpaUcTxPartitionBase; +#endif /* IPA_UC_OFFLOAD */ + + macOpenParms.tx_chain_mask_cck = pHddCtx->cfg_ini->tx_chain_mask_cck; + macOpenParms.self_gen_frm_pwr = pHddCtx->cfg_ini->self_gen_frm_pwr; + macOpenParms.max_mgmt_tx_fail_count = + pHddCtx->cfg_ini->max_mgmt_tx_fail_count; + +#ifdef WLAN_FEATURE_LPSS + macOpenParms.is_lpass_enabled = pHddCtx->cfg_ini->enablelpasssupport; +#endif + + vos_set_nan_enable(&macOpenParms, pHddCtx); + + vStatus = WDA_open( gpVosContext, gpVosContext->pHDDContext, + hdd_update_tgt_cfg, + hdd_dfs_indicate_radar, + &macOpenParms ); + + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to open WDA module", __func__); + VOS_ASSERT(0); + goto err_htc_close; + } + + /* Number of peers limit differs in each chip version. If peer max + * limit configured in ini exceeds more than supported, WMA adjusts + * and keeps correct limit in macOpenParms.maxStation. So, make sure + * ini entry pHddCtx->cfg_ini->maxNumberOfPeers has adjusted value + */ + pHddCtx->cfg_ini->maxNumberOfPeers = macOpenParms.maxStation; + HTCHandle = vos_get_context(VOS_MODULE_ID_HTC, gpVosContext); + if (!HTCHandle) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: HTCHandle is null!", __func__); + goto err_wda_close; + } + if (HTCWaitTarget(HTCHandle)) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_wda_close; + } + + bmi_target_ready(scn, gpVosContext->cfg_ctx); + /* Open the SYS module */ + vStatus = sysOpen(gpVosContext); + + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to open SYS module", __func__); + VOS_ASSERT(0); + goto err_packet_close; + } + + + /* If we arrive here, both threads dispacthing messages correctly */ + + /* Now proceed to open the MAC */ + + /* UMA is supported in hardware for performing the + frame translation 802.11 <-> 802.3 */ + macOpenParms.frameTransRequired = 1; + + sirStatus = macOpen(&(gpVosContext->pMACContext), gpVosContext->pHDDContext, + &macOpenParms); + + if (eSIR_SUCCESS != sirStatus) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to open MAC", __func__); + VOS_ASSERT(0); + goto err_nv_close; + } + + /* Now proceed to open the SME */ + vStatus = sme_Open(gpVosContext->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to open SME", __func__); + VOS_ASSERT(0); + goto err_mac_close; + } + + /* Now proceed to open TL. Read TL config first */ + vos_fetch_tl_cfg_parms ( &TLConfig, + ((hdd_context_t*)(gpVosContext->pHDDContext))->cfg_ini); + + vStatus = WLANTL_Open(gpVosContext, &TLConfig); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + /* Critical Error ... Cannot proceed further */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to open TL", __func__); + VOS_ASSERT(0); + goto err_sme_close; + } + +#ifdef IPA_UC_OFFLOAD + WLANTL_GetIpaUcResource(gpVosContext, + &((hdd_context_t*)(gpVosContext->pHDDContext))->ce_sr_base_paddr, + &((hdd_context_t*)(gpVosContext->pHDDContext))->ce_sr_ring_size, + &((hdd_context_t*)(gpVosContext->pHDDContext))->ce_reg_paddr, + &((hdd_context_t*)(gpVosContext->pHDDContext))->tx_comp_ring_base_paddr, + &((hdd_context_t*)(gpVosContext->pHDDContext))->tx_comp_ring_size, + &((hdd_context_t*)(gpVosContext->pHDDContext))->tx_num_alloc_buffer, + &((hdd_context_t*)(gpVosContext->pHDDContext))->rx_rdy_ring_base_paddr, + &((hdd_context_t*)(gpVosContext->pHDDContext))->rx_rdy_ring_size, + &((hdd_context_t*)(gpVosContext->pHDDContext))->rx_proc_done_idx_paddr); +#endif /* IPA_UC_OFFLOAD */ + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS successfully Opened", __func__); + + *pVosContext = gpVosContext; + + return VOS_STATUS_SUCCESS; + + +err_sme_close: + sme_Close(gpVosContext->pMACContext); + +err_mac_close: + macClose(gpVosContext->pMACContext); + +err_nv_close: + + sysClose(gpVosContext); + +err_packet_close: +err_wda_close: + WDA_close(gpVosContext); + + wma_wmi_service_close(gpVosContext); + +err_htc_close: + if (gpVosContext->htc_ctx) { + HTCDestroy(gpVosContext->htc_ctx); + gpVosContext->htc_ctx = NULL; + } + +err_bmi_close: + BMICleanup(scn); + +err_sched_close: + vos_sched_close(gpVosContext); + + +err_msg_queue: + vos_mq_deinit(&gpVosContext->freeVosMq); + +err_wda_complete_event: + vos_event_destroy( &gpVosContext->wdaCompleteEvent ); + +err_probe_event: + vos_event_destroy(&gpVosContext->ProbeEvent); + + return VOS_STATUS_E_FAILURE; + +} /* vos_open() */ + +/*--------------------------------------------------------------------------- + + \brief vos_preStart() - + + The \a vos_preStart() function to download CFG. + including: + - ccmStart + + - WDA: triggers the CFG download + + + \param pVosContext: The VOS context + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_start + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_preStart( v_CONTEXT_t vosContext ) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + pVosContextType pVosContext = (pVosContextType)vosContext; + v_VOID_t *scn; + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "vos prestart"); + + if (gpVosContext != pVosContext) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Context mismatch", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + if (pVosContext->pMACContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: MAC NULL context", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + if (pVosContext->pWDAContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: WDA NULL context", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + scn = vos_get_context(VOS_MODULE_ID_HIF, gpVosContext); + if (!scn) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: scn is null!", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* call macPreStart */ + vStatus = macPreStart(gpVosContext->pMACContext); + if ( !VOS_IS_STATUS_SUCCESS(vStatus) ) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, + "Failed at macPreStart "); + return VOS_STATUS_E_FAILURE; + } + + /* call ccmStart */ + ccmStart(gpVosContext->pMACContext); + + /* Reset wda wait event */ + vos_event_reset(&gpVosContext->wdaCompleteEvent); + + + /*call WDA pre start*/ + vStatus = WDA_preStart(gpVosContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, + "Failed to WDA prestart"); + ccmStop(gpVosContext->pMACContext); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + /* Need to update time out of complete */ + vStatus = vos_wait_single_event( &gpVosContext->wdaCompleteEvent, + VOS_WDA_TIMEOUT ); + if ( vStatus != VOS_STATUS_SUCCESS ) + { + if ( vStatus == VOS_STATUS_E_TIMEOUT ) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Timeout occurred before WDA complete", __func__); + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: WDA_preStart reporting other error", __func__); + } + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Test MC thread by posting a probe message to SYS", __func__); + wlan_sys_probe(); + + ccmStop(gpVosContext->pMACContext); + VOS_ASSERT( 0 ); + return VOS_STATUS_E_FAILURE; + } + + vStatus = HTCStart(gpVosContext->htc_ctx); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, + "Failed to Start HTC"); + ccmStop(gpVosContext->pMACContext); + VOS_ASSERT( 0 ); + return VOS_STATUS_E_FAILURE; + } + vStatus = wma_wait_for_ready_event(gpVosContext->pWDAContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, + "Failed to get ready event from target firmware"); + HTCSetTargetToSleep(scn); + ccmStop(gpVosContext->pMACContext); + HTCStop(gpVosContext->htc_ctx); + VOS_ASSERT( 0 ); + return VOS_STATUS_E_FAILURE; + } + + HTCSetTargetToSleep(scn); + + return VOS_STATUS_SUCCESS; +} + +/*--------------------------------------------------------------------------- + + \brief vos_start() - Start the Libra SW Modules + + The \a vos_start() function starts all the components of the Libra SW + including: + - SAL/BAL, which in turn starts SSC + + - the MAC (HAL and PE) + + - SME + + - TL + + - SYS: triggers the CFG download + + + \param pVosContext: The VOS context + + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_preStart() + \sa vos_open() + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_start( v_CONTEXT_t vosContext ) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + tSirRetStatus sirStatus = eSIR_SUCCESS; + pVosContextType pVosContext = (pVosContextType)vosContext; + tHalMacStartParameters halStartParams; + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Starting Libra SW", __func__); + + /* We support only one instance for now ...*/ + if (gpVosContext != pVosContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: mismatch in context", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (( pVosContext->pWDAContext == NULL) || ( pVosContext->pMACContext == NULL) + || ( pVosContext->pTLContext == NULL)) + { + if (pVosContext->pWDAContext == NULL) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: WDA NULL context", __func__); + else if (pVosContext->pMACContext == NULL) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: MAC NULL context", __func__); + else + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: TL NULL context", __func__); + + return VOS_STATUS_E_FAILURE; + } + + + /* Start the WDA */ + vStatus = WDA_start(pVosContext); + if ( vStatus != VOS_STATUS_SUCCESS ) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to start WDA", __func__); + return VOS_STATUS_E_FAILURE; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: WDA correctly started", __func__); + + /* Start the MAC */ + vos_mem_zero((v_PVOID_t)&halStartParams, sizeof(tHalMacStartParameters)); + + /* Start the MAC */ + sirStatus = macStart(pVosContext->pMACContext,(v_PVOID_t)&halStartParams); + + if (eSIR_SUCCESS != sirStatus) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to start MAC", __func__); + goto err_wda_stop; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: MAC correctly started", __func__); + + /* START SME */ + vStatus = sme_Start(pVosContext->pMACContext); + + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to start SME", __func__); + goto err_mac_stop; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: SME correctly started", __func__); + + /** START TL */ + vStatus = WLANTL_Start(pVosContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to start TL", __func__); + goto err_sme_stop; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "TL correctly started"); + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: VOSS Start is successful!!", __func__); + + return VOS_STATUS_SUCCESS; + + +err_sme_stop: + sme_Stop(pVosContext->pMACContext, HAL_STOP_TYPE_SYS_RESET); + +err_mac_stop: + macStop( pVosContext->pMACContext, HAL_STOP_TYPE_SYS_RESET ); + +err_wda_stop: + vos_event_reset( &(gpVosContext->wdaCompleteEvent) ); + vStatus = WDA_stop( pVosContext, HAL_STOP_TYPE_RF_KILL); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop WDA", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vStatus ) ); + WDA_setNeedShutdown(vosContext); + } + else + { + vStatus = vos_wait_single_event( &(gpVosContext->wdaCompleteEvent), + VOS_WDA_TIMEOUT ); + if( vStatus != VOS_STATUS_SUCCESS ) + { + if( vStatus == VOS_STATUS_E_TIMEOUT ) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Timeout occurred before WDA_stop complete", __func__); + + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: WDA_stop reporting other error", __func__); + } + VOS_ASSERT( 0 ); + WDA_setNeedShutdown(vosContext); + } + } + + return VOS_STATUS_E_FAILURE; + +} /* vos_start() */ + + +/* vos_stop function */ +VOS_STATUS vos_stop( v_CONTEXT_t vosContext ) +{ + VOS_STATUS vosStatus; + + /* WDA_Stop is called before the SYS so that the processing of Riva + pending responces will not be handled during uninitialization of WLAN driver */ + vos_event_reset( &(gpVosContext->wdaCompleteEvent) ); + + vosStatus = WDA_stop( vosContext, HAL_STOP_TYPE_RF_KILL ); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop WDA", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + WDA_setNeedShutdown(vosContext); + } + + hif_disable_isr(((VosContextType*)vosContext)->pHIFContext); + hif_reset_soc(((VosContextType*)vosContext)->pHIFContext); + + /* SYS STOP will stop SME and MAC */ + vosStatus = sysStop( vosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop SYS", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = WLANTL_Stop( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to stop TL", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + return VOS_STATUS_SUCCESS; +} + + +/* vos_close function */ +VOS_STATUS vos_close( v_CONTEXT_t vosContext ) +{ + VOS_STATUS vosStatus; + + vosStatus = wma_wmi_work_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_work", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + if (gpVosContext->htc_ctx) + { + HTCStop(gpVosContext->htc_ctx); + HTCDestroy(gpVosContext->htc_ctx); + gpVosContext->htc_ctx = NULL; + } + + vosStatus = WLANTL_Close(vosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close TL", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = sme_Close( ((pVosContextType)vosContext)->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close SME", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close MAC", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + ((pVosContextType)vosContext)->pMACContext = NULL; + + vosStatus = sysClose( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close SYS", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + if ( TRUE == WDA_needShutdown(vosContext )) + { + /* if WDA stop failed, call WDA shutdown to cleanup WDA/WDI */ + vosStatus = WDA_shutdown( vosContext, VOS_TRUE ); + if (VOS_IS_STATUS_SUCCESS( vosStatus ) ) + { + hdd_set_ssr_required( HDD_SSR_REQUIRED ); + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to shutdown WDA", __func__ ); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + } + else + { + vosStatus = WDA_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close WDA", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + } + + vosStatus = wma_wmi_service_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + + vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq); + + vosStatus = vos_event_destroy(&gpVosContext->wdaCompleteEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: failed to destroy wdaCompleteEvent", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = vos_event_destroy(&gpVosContext->ProbeEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: failed to destroy ProbeEvent", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vos_deinit_log_completion(); + + return VOS_STATUS_SUCCESS; +} + + +/**--------------------------------------------------------------------------- + + \brief vos_get_context() - get context data area + + Each module in the system has a context / data area that is allocated + and maanged by voss. This API allows any user to get a pointer to its + allocated context data area from the VOSS global context. + + \param vosContext - the VOSS Global Context. + + \param moduleId - the module ID, who's context data are is being retrived. + + \return - pointer to the context data area. + + - NULL if the context data is not allocated for the module ID + specified + + --------------------------------------------------------------------------*/ +v_VOID_t* vos_get_context( VOS_MODULE_ID moduleId, + v_CONTEXT_t pVosContext ) +{ + v_PVOID_t pModContext = NULL; + + if (pVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vos context pointer is null", __func__); + return NULL; + } + + if (gpVosContext != pVosContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pVosContext != gpVosContext", __func__); + return NULL; + } + + switch(moduleId) + { + case VOS_MODULE_ID_TL: + { + pModContext = gpVosContext->pTLContext; + break; + } + + +#ifndef WLAN_FEATURE_MBSSID + case VOS_MODULE_ID_SAP: + { + pModContext = gpVosContext->pSAPContext; + break; + } +#endif + + case VOS_MODULE_ID_HDD: + { + pModContext = gpVosContext->pHDDContext; + break; + } + + case VOS_MODULE_ID_SME: + case VOS_MODULE_ID_PE: + case VOS_MODULE_ID_PMC: + { + /* + ** In all these cases, we just return the MAC Context + */ + pModContext = gpVosContext->pMACContext; + break; + } + + case VOS_MODULE_ID_WDA: + { + /* For WDA module */ + pModContext = gpVosContext->pWDAContext; + break; + } + + case VOS_MODULE_ID_VOSS: + { + /* For SYS this is VOS itself*/ + pModContext = gpVosContext; + break; + } + + + case VOS_MODULE_ID_HIF: + { + pModContext = gpVosContext->pHIFContext; + break; + } + + case VOS_MODULE_ID_HTC: + { + pModContext = gpVosContext->htc_ctx; + break; + } + + case VOS_MODULE_ID_ADF: + { + pModContext = gpVosContext->adf_ctx; + break; + } + + case VOS_MODULE_ID_TXRX: + { + pModContext = gpVosContext->pdev_txrx_ctx; + break; + } + + case VOS_MODULE_ID_CFG: + { + pModContext = gpVosContext->cfg_ctx; + break; + } + + default: + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Module ID %i " + "does not have its context maintained by VOSS", __func__, moduleId); + VOS_ASSERT(0); + return NULL; + } + } + + if (pModContext == NULL ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Module ID %i " + "context is Null", __func__, moduleId); + } + + return pModContext; + +} /* vos_get_context()*/ + + +/**--------------------------------------------------------------------------- + + \brief vos_get_global_context() - get VOSS global Context + + This API allows any user to get the VOS Global Context pointer from a + module context data area. + + \param moduleContext - the input module context pointer + + \param moduleId - the module ID who's context pointer is input in + moduleContext. + + \return - pointer to the VOSS global context + + - NULL if the function is unable to retreive the VOSS context. + + --------------------------------------------------------------------------*/ +v_CONTEXT_t vos_get_global_context( VOS_MODULE_ID moduleId, + v_VOID_t *moduleContext ) +{ + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + } + + return gpVosContext; + +} /* vos_get_global_context() */ + + +v_U8_t vos_is_logp_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) +{ + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return 1; + } + + return gpVosContext->isLogpInProgress; +} + +void vos_set_logp_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) +{ + hdd_context_t *pHddCtx = NULL; + + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return; + } + gpVosContext->isLogpInProgress = value; + + /* HDD uses it's own context variable to check if SSR in progress, + * instead of modifying all HDD APIs set the HDD context variable + * here */ + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, gpVosContext); + if (!pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: HDD context is Null", __func__); + return; + } + pHddCtx->isLogpInProgress = value; +} + +v_U8_t vos_is_load_unload_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) +{ + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return 0; + } + + return gpVosContext->isLoadUnloadInProgress; +} + +void vos_set_load_unload_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) +{ + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return; + } + gpVosContext->isLoadUnloadInProgress = value; + +#ifdef CONFIG_CNSS + if (value) + cnss_set_driver_status(CNSS_LOAD_UNLOAD); + else + cnss_set_driver_status(CNSS_INITIALIZED); +#endif +} + +/** + * vos_is_unload_in_progress - check if driver unload is in progress + * + * Return: true - unload in progress + * false - unload not in progress + */ +v_U8_t vos_is_unload_in_progress(void) +{ + if (gpVosContext == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return 0; + } + + return gpVosContext->is_unload_in_progress; +} + +/** + * vos_set_unload_in_progress - set driver unload in progress status + * @value: true - driver unload starts + * false - driver unload completes + * + * Return: none + */ +void vos_set_unload_in_progress(v_U8_t value) +{ + if (gpVosContext == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return; + } + + gpVosContext->is_unload_in_progress = value; +} + +v_U8_t vos_is_reinit_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) +{ + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return 1; + } + + return gpVosContext->isReInitInProgress; +} + +void vos_set_reinit_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) +{ + if (gpVosContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return; + } + + gpVosContext->isReInitInProgress = value; +} + + +/** + * vos_set_shutdown_in_progress - set SSR shutdown progress status + * + * @moduleId: the module ID of the caller + * @value: true - CNSS SSR shutdown start + * false - CNSS SSR shutdown completes + * Return: none + */ + +void vos_set_shutdown_in_progress(VOS_MODULE_ID moduleId, bool value) +{ + if (gpVosContext == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return; + } + gpVosContext->is_shutdown_in_progress = value; +} + +/** + * vos_is_shutdown_in_progress - check if SSR shutdown is in progress + * + * @moduleId: the module ID of the caller + * @moduleContext: the input module context pointer + * + * Return: true - shutdown in progress + * false - shutdown is not in progress + */ + +bool vos_is_shutdown_in_progress(VOS_MODULE_ID moduleId, + v_VOID_t *moduleContext) +{ + if (gpVosContext == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: global voss context is NULL", __func__); + return 0; + } + return gpVosContext->is_shutdown_in_progress; +} + +/**--------------------------------------------------------------------------- + + \brief vos_alloc_context() - allocate a context within the VOSS global Context + + This API allows any user to allocate a user context area within the + VOS Global Context. + + \param pVosContext - pointer to the global Vos context + + \param moduleId - the module ID who's context area is being allocated. + + \param ppModuleContext - pointer to location where the pointer to the + allocated context is returned. Note this + output pointer is valid only if the API + returns VOS_STATUS_SUCCESS + + \param size - the size of the context area to be allocated. + + \return - VOS_STATUS_SUCCESS - the context for the module ID has been + allocated successfully. The pointer to the context area + can be found in *ppModuleContext. + \note This function returns VOS_STATUS_SUCCESS if the + module context was already allocated and the size + allocated matches the size on this call. + + VOS_STATUS_E_INVAL - the moduleId is not a valid or does + not identify a module that can have a context allocated. + + VOS_STATUS_E_EXISTS - vos could allocate the requested context + because a context for this module ID already exists and it is + a *different* size that specified on this call. + + VOS_STATUS_E_NOMEM - vos could not allocate memory for the + requested context area. + + \sa vos_get_context(), vos_free_context() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_alloc_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, + v_VOID_t **ppModuleContext, v_SIZE_t size ) +{ + v_VOID_t ** pGpModContext = NULL; + + if ( pVosContext == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is null", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (( gpVosContext != pVosContext) || ( ppModuleContext == NULL)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: context mismatch or null param passed", __func__); + return VOS_STATUS_E_FAILURE; + } + + switch(moduleID) + { + case VOS_MODULE_ID_TL: + { + pGpModContext = &(gpVosContext->pTLContext); + break; + } + + +#ifndef WLAN_FEATURE_MBSSID + case VOS_MODULE_ID_SAP: + { + pGpModContext = &(gpVosContext->pSAPContext); + break; + } +#endif + + case VOS_MODULE_ID_WDA: + { + pGpModContext = &(gpVosContext->pWDAContext); + break; + } + case VOS_MODULE_ID_SME: + case VOS_MODULE_ID_PE: + case VOS_MODULE_ID_PMC: + case VOS_MODULE_ID_HDD: + case VOS_MODULE_ID_HDD_SOFTAP: + default: + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Module ID %i " + "does not have its context allocated by VOSS", __func__, moduleID); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + } + + if ( NULL != *pGpModContext) + { + /* + ** Context has already been allocated! + ** Prevent double allocation + */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Module ID %i context has already been allocated", + __func__, moduleID); + return VOS_STATUS_E_EXISTS; + } + + /* + ** Dynamically allocate the context for module + */ + + *ppModuleContext = kmalloc(size, GFP_KERNEL); + + + if ( *ppModuleContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Failed to " + "allocate Context for module ID %i", __func__, moduleID); + VOS_ASSERT(0); + return VOS_STATUS_E_NOMEM; + } + + if (moduleID==VOS_MODULE_ID_TL) + { + vos_mem_zero(*ppModuleContext, size); + } + + *pGpModContext = *ppModuleContext; + + return VOS_STATUS_SUCCESS; + +} /* vos_alloc_context() */ + + +/**--------------------------------------------------------------------------- + + \brief vos_free_context() - free an allocated a context within the + VOSS global Context + + This API allows a user to free the user context area within the + VOS Global Context. + + \param pVosContext - pointer to the global Vos context + + \param moduleId - the module ID who's context area is being free + + \param pModuleContext - pointer to module context area to be free'd. + + \return - VOS_STATUS_SUCCESS - the context for the module ID has been + free'd. The pointer to the context area is not longer + available. + + VOS_STATUS_E_FAULT - pVosContext or pModuleContext are not + valid pointers. + + VOS_STATUS_E_INVAL - the moduleId is not a valid or does + not identify a module that can have a context free'd. + + VOS_STATUS_E_EXISTS - vos could not free the requested + context area because a context for this module ID does not + exist in the global vos context. + + \sa vos_get_context() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_free_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, + v_VOID_t *pModuleContext ) +{ + v_VOID_t ** pGpModContext = NULL; + + if (( pVosContext == NULL) || ( gpVosContext != pVosContext) || + ( pModuleContext == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params or context mismatch", __func__); + return VOS_STATUS_E_FAILURE; + } + + + switch(moduleID) + { + case VOS_MODULE_ID_TL: + { + pGpModContext = &(gpVosContext->pTLContext); + break; + } + + +#ifndef WLAN_FEATURE_MBSSID + case VOS_MODULE_ID_SAP: + { + pGpModContext = &(gpVosContext->pSAPContext); + break; + } +#endif + + case VOS_MODULE_ID_WDA: + { + pGpModContext = &(gpVosContext->pWDAContext); + break; + } + case VOS_MODULE_ID_HDD: + case VOS_MODULE_ID_SME: + case VOS_MODULE_ID_PE: + case VOS_MODULE_ID_PMC: + case VOS_MODULE_ID_HDD_SOFTAP: + default: + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Module ID %i " + "does not have its context allocated by VOSS", __func__, moduleID); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + } + + if ( NULL == *pGpModContext) + { + /* + ** Context has not been allocated or freed already! + */ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Module ID %i " + "context has not been allocated or freed already", __func__,moduleID); + return VOS_STATUS_E_FAILURE; + } + + if (*pGpModContext != pModuleContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pGpModContext != pModuleContext", __func__); + return VOS_STATUS_E_FAILURE; + } + + if(pModuleContext != NULL) + kfree(pModuleContext); + + *pGpModContext = NULL; + + return VOS_STATUS_SUCCESS; + +} /* vos_free_context() */ + + +/**--------------------------------------------------------------------------- + + \brief vos_mq_post_message() - post a message to a message queue + + This API allows messages to be posted to a specific message queue. Messages + can be posted to the following message queues: + +
    +
  • SME +
  • PE +
  • HAL +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Memory for this message + buffer is allocated by the caller and free'd by the vOSS after the + message is posted to the message queue. If the consumer of the + message needs anything in this message, it needs to copy the contents + before returning from the message queue handler. + + \return VOS_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + VOS_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + VOS_STATUS_E_FAULT - message is an invalid pointer. + + VOS_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_mq_post_message( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) +{ + pVosMqType pTargetMq = NULL; + pVosMsgWrapper pMsgWrapper = NULL; + uint32_t debug_count; + + if ((gpVosContext == NULL) || (pMsg == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params or global vos context is null", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + switch (msgQueueId) + { + /// Message Queue ID for messages bound for SME + case VOS_MQ_ID_SME: + { + pTargetMq = &(gpVosContext->vosSched.smeMcMq); + break; + } + + /// Message Queue ID for messages bound for PE + case VOS_MQ_ID_PE: + { + pTargetMq = &(gpVosContext->vosSched.peMcMq); + break; + } + + /// Message Queue ID for messages bound for WDA + case VOS_MQ_ID_WDA: + { + pTargetMq = &(gpVosContext->vosSched.wdaMcMq); + break; + } + + /// Message Queue ID for messages bound for TL + case VOS_MQ_ID_TL: + { + pTargetMq = &(gpVosContext->vosSched.tlMcMq); + break; + } + + /// Message Queue ID for messages bound for the SYS module + case VOS_MQ_ID_SYS: + { + pTargetMq = &(gpVosContext->vosSched.sysMcMq); + break; + } + + default: + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("%s: Trying to queue msg into unknown MC Msg queue ID %d"), + __func__, msgQueueId); + + return VOS_STATUS_E_FAILURE; + } + + VOS_ASSERT(NULL !=pTargetMq); + if (pTargetMq == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pTargetMq == NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* + ** Try and get a free Msg wrapper + */ + pMsgWrapper = vos_mq_get(&gpVosContext->freeVosMq); + + if (NULL == pMsgWrapper) { + debug_count = atomic_inc_return(&vos_wrapper_empty_count); + if (1 == debug_count) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: VOS Core run out of message wrapper %d", + __func__, debug_count); + + if (VOS_WRAPPER_MAX_FAIL_COUNT == debug_count) { + VOS_BUG(0); + } + + return VOS_STATUS_E_RESOURCES; + } + + atomic_set(&vos_wrapper_empty_count, 0); + + /* + ** Copy the message now + */ + vos_mem_copy( (v_VOID_t*)pMsgWrapper->pVosMsg, + (v_VOID_t*)pMsg, sizeof(vos_msg_t)); + + vos_mq_put(pTargetMq, pMsgWrapper); + + set_bit(MC_POST_EVENT_MASK, &gpVosContext->vosSched.mcEventFlag); + wake_up_interruptible(&gpVosContext->vosSched.mcWaitQueue); + + return VOS_STATUS_SUCCESS; + +} /* vos_mq_post_message()*/ + + +/**--------------------------------------------------------------------------- + + \brief vos_tx_mq_serialize() - serialize a message to the Tx execution flow + + This API allows messages to be posted to a specific message queue in the + Tx excution flow. Messages for the Tx execution flow can be posted only + to the following queue. + +
    +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Body memory for this message + buffer is allocated by the caller and free'd by the vOSS after the + message is dispacthed to the appropriate component. If the consumer + of the message needs to keep anything in the body, it needs to copy + the contents before returning from the message handler. + + \return VOS_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + VOS_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + VOS_STATUS_E_FAULT - message is an invalid pointer. + + VOS_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_tx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) +{ + pVosMqType pTargetMq = NULL; + pVosMsgWrapper pMsgWrapper = NULL; + + if ((gpVosContext == NULL) || (pMsg == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params or global vos context is null", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + switch (msgQueueId) + { + /// Message Queue ID for messages bound for SME + case VOS_MQ_ID_TL: + { + pTargetMq = &(gpVosContext->vosSched.tlTxMq); + break; + } + + /// Message Queue ID for messages bound for the SYS module + case VOS_MQ_ID_SYS: + { + pTargetMq = &(gpVosContext->vosSched.sysTxMq); + break; + } + + default: + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Trying to queue msg into unknown Tx Msg queue ID %d", + __func__, msgQueueId); + + return VOS_STATUS_E_FAILURE; + } + + if (pTargetMq == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pTargetMq == NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + + /* + ** Try and get a free Msg wrapper + */ + pMsgWrapper = vos_mq_get(&gpVosContext->freeVosMq); + + if (NULL == pMsgWrapper) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: VOS Core run out of message wrapper", __func__); + + return VOS_STATUS_E_RESOURCES; + } + + /* + ** Copy the message now + */ + vos_mem_copy( (v_VOID_t*)pMsgWrapper->pVosMsg, + (v_VOID_t*)pMsg, sizeof(vos_msg_t)); + + vos_mq_put(pTargetMq, pMsgWrapper); + + set_bit(TX_POST_EVENT_MASK, &gpVosContext->vosSched.txEventFlag); + wake_up_interruptible(&gpVosContext->vosSched.txWaitQueue); + + return VOS_STATUS_SUCCESS; + +} /* vos_tx_mq_serialize()*/ + +/**--------------------------------------------------------------------------- + + \brief vos_rx_mq_serialize() - serialize a message to the Rx execution flow + + This API allows messages to be posted to a specific message queue in the + Tx excution flow. Messages for the Rx execution flow can be posted only + to the following queue. + +
    +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Body memory for this message + buffer is allocated by the caller and free'd by the vOSS after the + message is dispacthed to the appropriate component. If the consumer + of the message needs to keep anything in the body, it needs to copy + the contents before returning from the message handler. + + \return VOS_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + VOS_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + VOS_STATUS_E_FAULT - message is an invalid pointer. + + VOS_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_rx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) +{ + pVosMqType pTargetMq = NULL; + pVosMsgWrapper pMsgWrapper = NULL; + if ((gpVosContext == NULL) || (pMsg == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params or global vos context is null", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + switch (msgQueueId) + { + + case VOS_MQ_ID_SYS: + { + pTargetMq = &(gpVosContext->vosSched.sysRxMq); + break; + } + + default: + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Trying to queue msg into unknown Rx Msg queue ID %d", + __func__, msgQueueId); + + return VOS_STATUS_E_FAILURE; + } + + if (pTargetMq == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pTargetMq == NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + + + /* + ** Try and get a free Msg wrapper + */ + pMsgWrapper = vos_mq_get(&gpVosContext->freeVosMq); + + if (NULL == pMsgWrapper) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: VOS Core run out of message wrapper", __func__); + + return VOS_STATUS_E_RESOURCES; + } + + /* + ** Copy the message now + */ + vos_mem_copy( (v_VOID_t*)pMsgWrapper->pVosMsg, + (v_VOID_t*)pMsg, sizeof(vos_msg_t)); + + vos_mq_put(pTargetMq, pMsgWrapper); + + set_bit(RX_POST_EVENT_MASK, &gpVosContext->vosSched.rxEventFlag); + wake_up_interruptible(&gpVosContext->vosSched.rxWaitQueue); + + return VOS_STATUS_SUCCESS; + +} /* vos_rx_mq_serialize()*/ + +v_VOID_t +vos_sys_probe_thread_cback +( + v_VOID_t *pUserData +) +{ + if (gpVosContext != pUserData) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosContext != pUserData", __func__); + return; + } + + if (vos_event_set(&gpVosContext->ProbeEvent)!= VOS_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vos_event_set failed", __func__); + return; + } + +} /* vos_sys_probe_thread_cback() */ + +v_VOID_t vos_WDAComplete_cback +( + v_VOID_t *pUserData +) +{ + + if (gpVosContext != pUserData) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosContext != pUserData", __func__); + return; + } + + if (vos_event_set(&gpVosContext->wdaCompleteEvent)!= VOS_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vos_event_set failed", __func__); + return; + } + +} /* vos_WDAComplete_cback() */ + +v_VOID_t vos_core_return_msg +( + v_PVOID_t pVContext, + pVosMsgWrapper pMsgWrapper +) +{ + pVosContextType pVosContext = (pVosContextType) pVContext; + + VOS_ASSERT( gpVosContext == pVosContext); + + if (gpVosContext != pVosContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosContext != pVosContext", __func__); + return; + } + + VOS_ASSERT( NULL !=pMsgWrapper ); + + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper == NULL in function", __func__); + return; + } + + /* + ** Return the message on the free message queue + */ + INIT_LIST_HEAD(&pMsgWrapper->msgNode); + vos_mq_put(&pVosContext->freeVosMq, pMsgWrapper); + +} /* vos_core_return_msg() */ + + +/** + @brief vos_fetch_tl_cfg_parms() - this function will attempt to read the + TL config params from the registry + + @param pAdapter : [inout] pointer to TL config block + + @return + None + +*/ +v_VOID_t +vos_fetch_tl_cfg_parms +( + WLANTL_ConfigInfoType *pTLConfig, + hdd_config_t * pConfig +) +{ + if (pTLConfig == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s NULL ptr passed in!", __func__); + return; + } + + pTLConfig->uDelayedTriggerFrmInt = pConfig->DelayedTriggerFrmInt; + pTLConfig->uMinFramesProcThres = pConfig->MinFramesProcThres; + pTLConfig->ip_checksum_offload = pConfig->enableIPChecksumOffload; + pTLConfig->enable_rxthread = + (WLAN_HDD_RX_HANDLE_RX_THREAD == pConfig->rxhandle) ? 1 : 0; +} + +/*--------------------------------------------------------------------------- + + \brief vos_shutdown() - shutdown VOS + + - All VOS submodules are closed. + + - All the WLAN SW components should have been opened. This includes + SYS, MAC, SME and TL. + + + \param vosContext: Global vos context + + + \return VOS_STATUS_SUCCESS - Operation successfull & vos is shutdown + + VOS_STATUS_E_FAILURE - Failure to close + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_shutdown(v_CONTEXT_t vosContext) +{ + VOS_STATUS vosStatus; + tpAniSirGlobal pMac = (((pVosContextType)vosContext)->pMACContext); + + vosStatus = WLANTL_Close(vosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close TL", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = sme_Close( ((pVosContextType)vosContext)->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close SME", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + /* CAC timer will be initiated and started only when SAP starts on + * DFS channel and it will be stopped and destroyed immediately once the + * radar detected or timedout. So as per design CAC timer should be + * destroyed after stop.*/ + if (pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) { + vos_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + } + + vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close MAC", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + ((pVosContextType)vosContext)->pMACContext = NULL; + + vosStatus = sysClose( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close SYS", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + if (TRUE == WDA_needShutdown(vosContext)) + { + /* If WDA stop failed, call WDA shutdown to cleanup WDA/WDI. */ + vosStatus = WDA_shutdown(vosContext, VOS_TRUE); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to shutdown WDA!", __func__); + VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); + } + } + else + { + vosStatus = WDA_close(vosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close WDA!", __func__); + VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); + } + } + + vosStatus = wma_wmi_work_close(vosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_work!", __func__); + VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); + } + + if (gpVosContext->htc_ctx) + { + HTCStop(gpVosContext->htc_ctx); + HTCDestroy(gpVosContext->htc_ctx); + gpVosContext->htc_ctx = NULL; + } + + vosStatus = wma_wmi_service_close(vosContext); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service!", __func__); + VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); + } + + + vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq); + + vosStatus = vos_event_destroy(&gpVosContext->wdaCompleteEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: failed to destroy wdaCompleteEvent", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + vosStatus = vos_event_destroy(&gpVosContext->ProbeEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: failed to destroy ProbeEvent", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + return VOS_STATUS_SUCCESS; +} + +/*--------------------------------------------------------------------------- + + \brief vos_wda_shutdown() - VOS interface to wda shutdown + + - WDA/WDI shutdown + + \param vosContext: Global vos context + + + \return VOS_STATUS_SUCCESS - Operation successfull + + VOS_STATUS_E_FAILURE - Failure to close + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_wda_shutdown(v_CONTEXT_t vosContext) +{ + VOS_STATUS vosStatus; + vosStatus = WDA_shutdown(vosContext, VOS_FALSE); + + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: failed to shutdown WDA", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + return vosStatus; +} +/** + @brief vos_wlanShutdown() - This API will shutdown WLAN driver + + This function is called when Riva subsystem crashes. There are two + methods (or operations) in WLAN driver to handle Riva crash, + 1. shutdown: Called when Riva goes down, this will shutdown WLAN + driver without handshaking with Riva. + 2. re-init: Next API + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_wlanShutdown(void) +{ + VOS_STATUS vstatus; + vstatus = vos_watchdog_wlan_shutdown(); + return vstatus; +} +/** + @brief vos_wlanReInit() - This API will re-init WLAN driver + + This function is called when Riva subsystem reboots. There are two + methods (or operations) in WLAN driver to handle Riva crash, + 1. shutdown: Previous API + 2. re-init: Called when Riva comes back after the crash. This will + re-initialize WLAN driver. In some cases re-open may be + referred instead of re-init. + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_wlanReInit(void) +{ + VOS_STATUS vstatus; + vstatus = vos_watchdog_wlan_re_init(); + return vstatus; +} +/** + @brief vos_wlanRestart() - This API will reload WLAN driver. + + This function is called if driver detects any fatal state which + can be recovered by a WLAN module reload ( Android framwork initiated ). + Note that this API will not initiate any RIVA subsystem restart. + + The function wlan_hdd_restart_driver protects against re-entrant calls. + + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + VOS_STATUS_E_EMPTY - No configured interface + VOS_STATUS_E_ALREADY - Request already in progress + + +*/ +VOS_STATUS vos_wlanRestart(void) +{ + VOS_STATUS vstatus; + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + + /* Check whether driver load unload is in progress */ + if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Driver load/unload is in progress, retry later.", __func__); + return VOS_STATUS_E_AGAIN; + } + + /* Get the Global VOSS Context */ + pVosContext = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if(!pVosContext) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Global VOS context is Null", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* Get the HDD context */ + 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 VOS_STATUS_E_FAILURE; + } + + /* Reload the driver */ + vstatus = wlan_hdd_restart_driver(pHddCtx); + return vstatus; +} + + +/** + @brief vos_fwDumpReq() + + This function is called to issue dump commands to Firmware + + @param + cmd - Command No. to execute + arg1 - argument 1 to cmd + arg2 - argument 2 to cmd + arg3 - argument 3 to cmd + arg4 - argument 4 to cmd + @return + NONE +*/ +v_VOID_t vos_fwDumpReq(tANI_U32 cmd, tANI_U32 arg1, tANI_U32 arg2, + tANI_U32 arg3, tANI_U32 arg4) +{ + WDA_HALDumpCmdReq(NULL, cmd, arg1, arg2, arg3, arg4, NULL); +} + +VOS_STATUS vos_get_vdev_types(tVOS_CON_MODE mode, tANI_U32 *type, + tANI_U32 *sub_type) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + *type = 0; + *sub_type = 0; + switch (mode) + { + case VOS_STA_MODE: + *type = WMI_VDEV_TYPE_STA; + break; + case VOS_STA_SAP_MODE: + *type = WMI_VDEV_TYPE_AP; + break; + case VOS_P2P_DEVICE_MODE: + *type = WMI_VDEV_TYPE_AP; + *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE; + break; + case VOS_P2P_CLIENT_MODE: + *type = WMI_VDEV_TYPE_STA; + *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT; + break; + case VOS_P2P_GO_MODE: + *type = WMI_VDEV_TYPE_AP; + *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO; + break; + case VOS_OCB_MODE: + *type = WMI_VDEV_TYPE_OCB; + break; + default: + hddLog(VOS_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode); + status = VOS_STATUS_E_INVAL; + break; + } + return status; +} + +v_VOID_t vos_flush_work(v_VOID_t *work) +{ +#if defined (CONFIG_CNSS) + cnss_flush_work(work); +#elif defined (WLAN_OPEN_SOURCE) + cancel_work_sync(work); +#endif +} + +v_VOID_t vos_flush_delayed_work(v_VOID_t *dwork) +{ +#if defined (CONFIG_CNSS) + cnss_flush_delayed_work(dwork); +#elif defined (WLAN_OPEN_SOURCE) + cancel_delayed_work_sync(dwork); +#endif +} + +v_BOOL_t vos_is_packet_log_enabled(void) +{ + hdd_context_t *pHddCtx; + + pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext); + if((NULL == pHddCtx) || + (NULL == pHddCtx->cfg_ini)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Hdd Context is Null", __func__); + return FALSE; + } + + return pHddCtx->cfg_ini->enablePacketLog; +} + +void vos_trigger_recovery(void) +{ + pVosContextType vos_context; + tp_wma_handle wma_handle; + VOS_STATUS status = VOS_STATUS_SUCCESS; + void *runtime_context = NULL; + + vos_context = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "VOS context is invald!"); + return; + } + + wma_handle = (tp_wma_handle)vos_get_context(VOS_MODULE_ID_WDA, + vos_context); + if (!wma_handle) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "WMA context is invald!"); + return; + } + + runtime_context = vos_runtime_pm_prevent_suspend_init("vos_recovery"); + vos_runtime_pm_prevent_suspend(runtime_context); + + wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0); + + status = vos_wait_single_event(&wma_handle->recovery_event, + WMA_CRASH_INJECT_TIMEOUT); + + if (VOS_STATUS_SUCCESS != status) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "CRASH_INJECT command is timed out!"); +#ifdef CONFIG_CNSS + if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "LOGP is in progress, ignore!"); + goto out; + } + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + cnss_schedule_recovery_work(); +#endif + } + +#ifdef CONFIG_CNSS +out: +#endif + vos_runtime_pm_allow_suspend(runtime_context); + vos_runtime_pm_prevent_suspend_deinit(runtime_context); +} + +/** + * @brief vos_get_monotonic_boottime() + * Get kernel boot time. + * @return Time in microseconds + */ + +v_U64_t vos_get_monotonic_boottime(void) +{ +#ifdef CONFIG_CNSS + struct timespec ts; + + cnss_get_monotonic_boottime(&ts); + return (((v_U64_t)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000)); +#else + return ((v_U64_t)adf_os_ticks_to_msecs(adf_os_ticks()) * 1000); +#endif +} + +#ifdef FEATURE_WLAN_D0WOW +v_VOID_t vos_pm_control(v_BOOL_t vote) +{ +#ifdef CONFIG_CNSS + cnss_wlan_pm_control(vote); +#endif +} +#endif + +/** + * vos_set_wakelock_logging() - Logging of wakelock enabled/disabled + * @value: Boolean value + * + * This function is used to set the flag which will indicate whether + * logging of wakelock is enabled or not + * + * Return: None + */ +void vos_set_wakelock_logging(bool value) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "vos context is Invald"); + return; + } + vos_context->is_wakelock_log_enabled = value; +} + +/** + * vos_is_wakelock_enabled() - Check if logging of wakelock is enabled/disabled + * @value: Boolean value + * + * This function is used to check whether logging of wakelock is enabled or not + * + * Return: true if logging of wakelock is enabled + */ +bool vos_is_wakelock_enabled(void) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "vos context is Invald"); + return false; + } + return vos_context->is_wakelock_log_enabled; +} + +/** + * vos_set_ring_log_level() - Convert HLOS values to driver log levels + * @ring_id: ring_id + * @log_levelvalue: Log level specificed + * + * This function sets the log level of a particular ring + * + * Return: None + */ +void vos_set_ring_log_level(uint32_t ring_id, uint32_t log_level) +{ + VosContextType *vos_context; + uint32_t log_val; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invald", __func__); + return; + } + + switch (log_level) { + case LOG_LEVEL_NO_COLLECTION: + log_val = WLAN_LOG_LEVEL_OFF; + break; + case LOG_LEVEL_NORMAL_COLLECT: + log_val = WLAN_LOG_LEVEL_NORMAL; + break; + case LOG_LEVEL_ISSUE_REPRO: + log_val = WLAN_LOG_LEVEL_REPRO; + break; + case LOG_LEVEL_ACTIVE: + default: + log_val = WLAN_LOG_LEVEL_ACTIVE; + break; + } + + if (ring_id == RING_ID_WAKELOCK) { + vos_context->wakelock_log_level = log_val; + return; + } else if (ring_id == RING_ID_CONNECTIVITY) { + vos_context->connectivity_log_level = log_val; + return; + } else if (ring_id == RING_ID_PER_PACKET_STATS) { + vos_context->packet_stats_log_level = log_val; + return; + } else if (ring_id == RIND_ID_DRIVER_DEBUG) { + vos_context->driver_debug_log_level = log_val; + return; + } else if (ring_id == RING_ID_FIRMWARE_DEBUG) { + vos_context->fw_debug_log_level = log_val; + return; + } +} + +/** + * vos_get_ring_log_level() - Get the a ring id's log level + * @ring_id: Ring id + * + * Fetch and return the log level corresponding to a ring id + * + * Return: Log level corresponding to the ring ID + */ +enum wifi_driver_log_level vos_get_ring_log_level(uint32_t ring_id) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invald", __func__); + return WLAN_LOG_LEVEL_OFF; + } + + if (ring_id == RING_ID_WAKELOCK) + return vos_context->wakelock_log_level; + else if (ring_id == RING_ID_CONNECTIVITY) + return vos_context->connectivity_log_level; + else if (ring_id == RING_ID_PER_PACKET_STATS) + return vos_context->packet_stats_log_level; + else if (ring_id == RIND_ID_DRIVER_DEBUG) + return vos_context->driver_debug_log_level; + else if (ring_id == RING_ID_FIRMWARE_DEBUG) + return vos_context->fw_debug_log_level; + + return WLAN_LOG_LEVEL_OFF; +} + +/** + * vos_set_multicast_logging() - Set mutlicast logging value + * @value: Value of multicast logging + * + * Set the multicast logging value which will indicate + * whether to multicast host and fw messages even + * without any registration by userspace entity + * + * Return: None + */ +void vos_set_multicast_logging(uint8_t value) +{ + vos_multicast_logging = value; +} + +/** + * vos_is_multicast_logging() - Get multicast logging value + * + * Get the multicast logging value which will indicate + * whether to multicast host and fw messages even + * without any registration by userspace entity + * + * Return: 0 - Multicast logging disabled, 1 - Multicast logging enabled + */ +uint8_t vos_is_multicast_logging(void) +{ + return vos_multicast_logging; +} + +/* + * vos_init_log_completion() - Initialize log param structure + * + * This function is used to initialize the logging related + * parameters + * + * Return: None + */ +void vos_init_log_completion(void) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invalid", __func__); + return; + } + + vos_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; + vos_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; + vos_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; + vos_context->log_complete.is_report_in_progress = false; + /* Attempting to initialize an already initialized lock + * results in a failure. This must be ok here. + */ + vos_spin_lock_init(&vos_context->bug_report_lock); +} + +/** + * vos_deinit_log_completion() - Deinitialize log param structure + * + * This function is used to deinitialize the logging related + * parameters + * + * Return: None + */ +void vos_deinit_log_completion(void) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invalid", __func__); + return; + } + + vos_spin_lock_destroy(&vos_context->bug_report_lock); +} + +/** + * vos_set_log_completion() - Store the logging params + * @is_fatal: Indicates if the event triggering bug report is fatal or not + * @indicator: Source which trigerred the bug report + * @reason_code: Reason for triggering bug report + * + * This function is used to set the logging parameters based on the + * caller + * + * Return: 0 if setting of params is successful + */ +VOS_STATUS vos_set_log_completion(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invalid", __func__); + return VOS_STATUS_E_FAILURE; + } + + vos_spin_lock_acquire(&vos_context->bug_report_lock); + vos_context->log_complete.is_fatal = is_fatal; + vos_context->log_complete.indicator = indicator; + vos_context->log_complete.reason_code = reason_code; + vos_context->log_complete.is_report_in_progress = true; + vos_spin_lock_release(&vos_context->bug_report_lock); + return VOS_STATUS_SUCCESS; +} + +/** + * vos_get_log_completion() - Get the logging related params + * @is_fatal: Indicates if the event triggering bug report is fatal or not + * @indicator: Source which trigerred the bug report + * @reason_code: Reason for triggering bug report + * + * This function is used to get the logging related parameters + * + * Return: None + */ +void vos_get_log_completion(uint32_t *is_fatal, + uint32_t *indicator, + uint32_t *reason_code) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invalid", __func__); + return; + } + + vos_spin_lock_acquire(&vos_context->bug_report_lock); + *is_fatal = vos_context->log_complete.is_fatal; + *indicator = vos_context->log_complete.indicator; + *reason_code = vos_context->log_complete.reason_code; + vos_context->log_complete.is_report_in_progress = false; + vos_spin_lock_release(&vos_context->bug_report_lock); +} + +/** + * vos_is_log_report_in_progress() - Check if bug reporting is in progress + * + * This function is used to check if the bug reporting is already in progress + * + * Return: true if the bug reporting is in progress + */ +bool vos_is_log_report_in_progress(void) +{ + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invalid", __func__); + return true; + } + return vos_context->log_complete.is_report_in_progress; +} + +/** + * vos_flush_logs() - Report fatal event to userspace + * @is_fatal: Indicates if the event triggering bug report is fatal or not + * @indicator: Source which trigerred the bug report + * @reason_code: Reason for triggering bug report + * + * This function sets the log related params and send the WMI command to the + * FW to flush its logs. On receiving the flush completion event from the FW + * the same will be conveyed to userspace + * + * Return: 0 on success + */ +VOS_STATUS vos_flush_logs(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code) +{ + uint32_t ret; + VOS_STATUS status; + + VosContextType *vos_context; + + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is Invalid", __func__); + return eHAL_STATUS_FAILURE; + } + + if (vos_is_log_report_in_progress() == true) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", + __func__, is_fatal, indicator, reason_code); + return VOS_STATUS_E_FAILURE; + } + + status = vos_set_log_completion(is_fatal, indicator, reason_code); + if (VOS_STATUS_SUCCESS != status) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to set log trigger params", __func__); + return VOS_STATUS_E_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d", + __func__, is_fatal, indicator, reason_code); + + ret = vos_send_flush_logs_cmd_to_fw(vos_context->pMACContext); + if (0 != ret) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to send flush FW log", __func__); + vos_init_log_completion(); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +/** + * vos_logging_set_fw_flush_complete() - Wrapper for FW log flush completion + * + * This function is used to send signal to the logger thread to indicate + * that the flushing of FW logs is complete by the FW + * + * Return: None + * + */ +void vos_logging_set_fw_flush_complete(void) +{ + wlan_logging_set_fw_flush_complete(); +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_diag.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_diag.c new file mode 100644 index 000000000000..ae1253c66ded --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_diag.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/*============================================================================ + FILE: vos_diag.c + + OVERVIEW: This source file contains definitions for vOS diag APIs + + DEPENDENCIES: +============================================================================*/ + +#include "vos_types.h" +#include "i_vos_diag_core_log.h" +#include "i_vos_diag_core_event.h" +#include "wlan_hdd_main.h" +#include "wlan_nlink_common.h" +#include "vos_sched.h" +#include "wlan_ptt_sock_svc.h" +#include "wlan_nlink_srv.h" + +#define PTT_MSG_DIAG_CMDS_TYPE 0x5050 + +#define DIAG_TYPE_LOGS 1 +#define DIAG_TYPE_EVENTS 2 + +#define DIAG_SWAP16(A) ((((tANI_U16)(A) & 0xff00) >> 8) | (((tANI_U16)(A) & 0x00ff) << 8)) + + + +typedef struct event_report_s +{ + v_U32_t diag_type; + v_U16_t event_id; + v_U16_t length; +} event_report_t; + + +/**--------------------------------------------------------------------------- + + \brief vos_log_set_code() - + + This function sets the logging code in the given log record. + + \param - ptr - Pointer to the log header type. + - code - log code. + \return - None + + --------------------------------------------------------------------------*/ + +void vos_log_set_code (v_VOID_t *ptr, v_U16_t code) +{ + if (ptr) + { + /* All log packets are required to start with 'log_header_type'. */ + ((log_hdr_type *) ptr)->code = code; + } + +} + +/**--------------------------------------------------------------------------- + + \brief vos_log_set_length() - + + This function sets the length field in the given log record. + + \param - ptr - Pointer to the log header type. + - length - log length. + + \return - None + + --------------------------------------------------------------------------*/ + +void vos_log_set_length (v_VOID_t *ptr, v_U16_t length) +{ + if(ptr) + { + /* All log packets are required to start with 'log_header_type'. */ + ((log_hdr_type *) ptr)->len = (v_U16_t) length; + } +} + +/**--------------------------------------------------------------------------- + + \brief vos_log_submit() - + + This function sends the log data to the ptt socket app only if it is registered with the driver. + + \param - ptr - Pointer to the log header type. + + \return - None + + --------------------------------------------------------------------------*/ + +void vos_log_submit(v_VOID_t *plog_hdr_ptr) +{ + + log_hdr_type *pHdr = (log_hdr_type*) plog_hdr_ptr; + + tAniHdr *wmsg = NULL; + v_U8_t *pBuf; + struct hdd_context_s *pHddCtx; + v_CONTEXT_t pVosContext= NULL; + v_U16_t data_len; + v_U16_t total_len; + + + /*Get the global context */ + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + /*Get the Hdd Context */ + pHddCtx = ((VosContextType*)(pVosContext))->pHDDContext; + + if ((pHddCtx->isLoadInProgress) || + (pHddCtx->isUnloadInProgress)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return; + } + + if (nl_srv_is_initialized() != 0) + return; + + /* Send the log data to the ptt app only if it is registered + * with the wlan driver + */ + if (vos_is_multicast_logging()) + { + data_len = pHdr->len; + + total_len = sizeof(tAniHdr)+sizeof(v_U32_t)+data_len; + + pBuf = (v_U8_t*)vos_mem_malloc(total_len); + + if(!pBuf) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "vos_mem_malloc failed"); + return; + } + + vos_mem_zero((v_VOID_t*)pBuf,total_len); + + wmsg = (tAniHdr*)pBuf; + wmsg->type = PTT_MSG_DIAG_CMDS_TYPE; + wmsg->length = total_len; + wmsg->length = DIAG_SWAP16(wmsg->length); + pBuf += sizeof(tAniHdr); + + + /* Diag Type events or log */ + *(v_U32_t*)pBuf = DIAG_TYPE_LOGS; + pBuf += sizeof(v_U32_t); + + vos_mem_copy(pBuf, pHdr, data_len); + + if( ptt_sock_send_msg_to_app(wmsg, 0, ANI_NL_MSG_PUMAC, -1) < 0) { + vos_mem_free((v_VOID_t *)wmsg); + return; + } + + vos_mem_free((v_VOID_t*)wmsg); + } + return; +} + +/** + * vos_log_wlock_diag() - This function is used to send wake lock diag events + * @reason: Reason why the wakelock was taken or released + * @wake_lock_name: Function in which the wakelock was taken or released + * @timeout: Timeout value in case of timed wakelocks + * @status: Status field indicating whether the wake lock was taken/released + * + * This function is used to send wake lock diag events to user space + * + * Return: None + * + */ +void vos_log_wlock_diag(uint32_t reason, const char *wake_lock_name, + uint32_t timeout, uint32_t status) +{ + WLAN_VOS_DIAG_EVENT_DEF(wlan_diag_event, + struct vos_event_wlan_wake_lock); + + if ((nl_srv_is_initialized() != 0) || + (vos_is_wakelock_enabled() == false)) + return; + + wlan_diag_event.status = status; + wlan_diag_event.reason = reason; + wlan_diag_event.timeout = timeout; + wlan_diag_event.name_len = strlen(wake_lock_name); + strlcpy(&wlan_diag_event.name[0], + wake_lock_name, + wlan_diag_event.name_len+1); + + WLAN_VOS_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK); +} + +/**--------------------------------------------------------------------------- + + \brief vos_event_report_payload() - + + This function sends the event data to the ptt socket app only if it is registered with the driver. + + \param - ptr - Pointer to the log header type. + + \return - None + + --------------------------------------------------------------------------*/ + +void vos_event_report_payload(v_U16_t event_Id, v_U16_t length, v_VOID_t *pPayload) +{ + + tAniHdr *wmsg = NULL; + v_U8_t *pBuf; + struct hdd_context_s *pHddCtx; + v_CONTEXT_t pVosContext= NULL; + event_report_t *pEvent_report; + v_U16_t total_len; + + /*Get the global context */ + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!pVosContext) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is NULL", __func__); + return; + } + + /*Get the Hdd Context */ + pHddCtx = ((VosContextType*)(pVosContext))->pHDDContext; + if (!pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: hdd context is NULL", __func__); + return; + } + + if (nl_srv_is_initialized() != 0) + return; + + /* Send the log data to the ptt app only if it is registered + * with the wlan driver + */ + if (vos_is_multicast_logging()) + { + total_len = sizeof(tAniHdr)+sizeof(event_report_t)+length; + + pBuf = (v_U8_t*)vos_mem_malloc(total_len); + + if(!pBuf) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "vos_mem_malloc failed"); + return; + } + wmsg = (tAniHdr*)pBuf; + wmsg->type = PTT_MSG_DIAG_CMDS_TYPE; + wmsg->length = total_len; + wmsg->length = DIAG_SWAP16(wmsg->length); + pBuf += sizeof(tAniHdr); + + pEvent_report = (event_report_t*)pBuf; + pEvent_report->diag_type = DIAG_TYPE_EVENTS; + pEvent_report->event_id = event_Id; + pEvent_report->length = length; + + pBuf += sizeof(event_report_t); + + vos_mem_copy(pBuf, pPayload, length); + + if( ptt_sock_send_msg_to_app(wmsg, 0, ANI_NL_MSG_PUMAC, -1) < 0) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("Ptt Socket error sending message to the app!!")); + vos_mem_free((v_VOID_t*)wmsg); + return; + } + + vos_mem_free((v_VOID_t*)wmsg); + } + + return; + +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_event.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_event.c new file mode 100644 index 000000000000..9c4481ad9733 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_event.c @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/*============================================================================ + FILE: vos_event.c + + OVERVIEW: This source file contains definitions for vOS event APIs + The five APIs mentioned in this file are used for + initializing, setting, resetting, destroying an event and + waiting on an occurance of an event among multiple events. + + DEPENDENCIES: +============================================================================*/ + +/*============================================================================ + EDIT HISTORY FOR MODULE + +============================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "vos_event.h" +#include "vos_trace.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + Function Definitions and Documentation + * -------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + + \brief vos_event_init() - initializes a vOSS event + + The vos_event_init() function initializes the specified event. Upon + successful initialization, the state of the event becomes initialized + and not signaled. + + An event must be initialized before it may be used in any other event + functions. + + Attempting to initialize an already initialized event results in + a failure. + + \param lock - pointer to the opaque event object to initialize + + \return VOS_STATUS_SUCCESS - event was successfully initialized and + is ready to be used. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to reinitialize the object referenced by event, a previously + initialized, but not yet destroyed, event. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + + VOS_STATUS_E_FAILURE - event could not be created due to + unknown reasons + + ***VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the event + + ***VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the event + + \sa + + ( *** indicates return values do NOT exist yet ) + -------------------------------------------------------------------------*/ +VOS_STATUS vos_event_init ( vos_event_t* event ) +{ + + // Check for null pointer + if ( NULL == event ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check for 'already initialized' event + if ( LINUX_EVENT_COOKIE == event->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Initialized event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_BUSY; + } + + // initialize new event + init_completion(&event->complete); + event->cookie = LINUX_EVENT_COOKIE; + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_event_set() - sets a vOSS event + + The state of the specified event is set to 'signalled by calling + \a vos_event_set(). + + Any threads waiting on the event as a result of a vos_event_wait() will + be unblocked and available to be scheduled for execution when the event + is signaled by a call to \a vos_event_set(). + + \param event - the event to set to the signalled state + + \return VOS_STATUS_SUCCESS - the event was successfully signalled. + + VOS_STATUS_E_INVAL - The value specified by event does not refer + to an initialized event object. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + + VOS_STATUS_E_FAILURE - event could not be signaled due to + unknown reasons + + \sa + + -------------------------------------------------------------------------*/ + +VOS_STATUS vos_event_set ( vos_event_t* event ) +{ + + // Check for null pointer + if ( NULL == event ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check if event refers to an initialized object + if ( LINUX_EVENT_COOKIE != event->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + complete(&event->complete); + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_event_reset() - resets a vOSS event - This function isn't required + for Linux. Therefore, it doesn't do much. + + The state of the specified event is set to 'NOT signalled' by calling + \a vos_event_reset(). The state of the event remains NOT signalled until an + explicit call to vos_event_set(). + + This function sets the event to a NOT signalled state even if the event was + signalled multiple times before being signaled. + + \param event - the event to set to the NOT signalled state + + \return VOS_STATUS_SUCCESS - the event state was successfully change to + NOT signalled. + + VOS_STATUS_E_INVAL - The value specified by event does not refer + to an initialized event object. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + + VOS_STATUS_E_FAILURE - event could not be signaled due to + unknown reasons + + + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_event_reset ( vos_event_t* event ) +{ + + // check for null pointer + if ( NULL == event ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check to make sure it is an 'already initialized' event + if ( LINUX_EVENT_COOKIE != event->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // (re)initialize event + INIT_COMPLETION(event->complete); + return VOS_STATUS_SUCCESS; +} + + +/*-------------------------------------------------------------------------- + + \brief vos_event_destroy() - Destroys a vOSS event - This function doesn't do + much in Linux. There is no need for the caller to explicitly destroy an event + after use. + + The os_event_destroy() function shall destroy the event object + referenced by event. After a successful return from \a vos_event_destroy() + the event object becomes, in effect, uninitialized. + + A destroyed event object can be reinitialized using vos_event_init(); + the results of otherwise referencing the object after it has been destroyed + are undefined. Calls to vOSS event functions to manipulate the lock such + as vos_event_set() will fail if the event is destroyed. Therefore, + don't use the event after it has been destroyed until it has + been re-initialized. + + \param event - the event object to be destroyed. + + \return VOS_STATUS_SUCCESS - event was successfully destroyed. + + VOS_STATUS_E_INVAL - The value specified by event is invalid. + + VOS_STATUS_E_FAULT - event is an invalid pointer. + + VOS_STATUS_E_FAILURE - event could not be signaled due to + unknown reasons + + ***VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by event while it is still being + referenced (there are threads waiting on this event) + \sa + + ( *** indicates return values do NOT exist yet ) + -------------------------------------------------------------------------*/ + +VOS_STATUS vos_event_destroy ( vos_event_t* event ) +{ + // check for null pointer + if ( NULL == event ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check to make sure it is an 'already initialized' event + if ( LINUX_EVENT_COOKIE != event->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // make sure nobody is waiting on the event + complete_all(&event->complete); + + // destroy the event + memset(event, 0, sizeof(vos_event_t)); + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_wait_single_event() - Waits for a single event to be set. + + This API waits for the event to be set. + + \param pEvent - pointer to an event to wait on. + + \param timeout - Timeout value (in milliseconds). This function returns + if this interval elapses, regardless if any of the events have + been set. An input value of 0 for this timeout parameter means + to wait infinitely, meaning a timeout will never occur. + + \return VOS_STATUS_SUCCESS - the wait was satisifed by the event being + set. + + VOS_STATUS_E_TIMEOUT - the timeout interval elapsed before the + event was set. + + VOS_STATUS_E_INVAL - The value specified by event is invalid. + + VOS_STATUS_E_FAULT - pEvent is an invalid pointer. + + \sa vos_wait_multiple_events() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_wait_single_event ( vos_event_t* event, v_U32_t timeout) +{ + + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s cannot be called from interrupt context!!!", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check for null pointer + if ( NULL == event ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check if cookie is same as that of initialized event + if ( LINUX_EVENT_COOKIE != event->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + if (timeout) + { + long ret; + ret = + wait_for_completion_timeout(&event->complete, + msecs_to_jiffies(timeout)); + if ( 0 >= ret ) + { + return VOS_STATUS_E_TIMEOUT; + } + } + else + { + int ret; + ret = wait_for_completion_interruptible(&event->complete); + if ( 0 != ret ) + { + // negative means interrupted + return VOS_STATUS_E_TIMEOUT; + } + } + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_wait_multiple_events() - Waits for event(s) to be set. + This is a duplicate of vos_wait_events() function. It ends up calling + vos_wait_events() with the params passed in. + + This API waits for any event in the input array of events to be + set. The caller is blocked waiting any event in the array to be + set or for the timeout to occur. + + If multiple events in the array are set, only one event is identified + in the return from this call as satisfying the wait condition. The + caller is responsible for calling \a vos_wait_events() again to find + the other events that are set. + + \param pEventList - pointer to an array of event pointers + + \param numEvents - Number of events + + \param timeout - Timeout value (in milliseconds). This function returns + if this interval elapses, regardless if any of the events have + been set. An input value of 0 for this timeout parameter means + to wait infinitely, meaning a timeout will never occur. + + \param pEventIndex - This is a pointer to the location where the index of + the event in the event array that satisfied the wait because + the event was set. + + \return VOS_STATUS_SUCCESS - the wait was satisifed by one of the events + in the event array being set. The index into the event arry + that satisfied the wait can be found at *pEventIndex. + + VOS_STATUS_E_TIMEOUT - the timeout interval elapsed before any of + the events were set. + + VOS_STATUS_E_INVAL - At least one of the values specified in the + event array refers to an uninitialized event object. The invalid + event is identified by the index in *pEventIndex. Note that only + the first uninitialized event is detected when this error is + returned. + + VOS_STATUS_E_EMPTY - the events array is empty. This condition + is detected by numEvents being 0 on input. + + VOS_STATUS_E_FAULT - event or pEventIndex is an invalid pointer. + + \sa vos_wait_single_events() + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_wait_multiple_events( vos_event_t **events, v_U8_t numEvents, + v_U32_t timeout, v_U8_t *pEventIndex ) +{ + // NO LONGER SUPPORTED + return VOS_STATUS_E_FAILURE; +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_getBin.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_getBin.c new file mode 100644 index 000000000000..9d8425994292 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_getBin.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**============================================================================= + vos_getBin.c + \brief + Description... + ==============================================================================*/ +/* $HEADER$ */ +/**----------------------------------------------------------------------------- + Include files + ----------------------------------------------------------------------------*/ +#include +#include // for softmac direct file i/o +#include +#include +#include +#include +/**----------------------------------------------------------------------------- + Preprocessor definitions and constants + ----------------------------------------------------------------------------*/ +/**----------------------------------------------------------------------------- + Type declarations + ----------------------------------------------------------------------------*/ +extern tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void ); + +/**----------------------------------------------------------------------------- + Function declarations and documenation + ----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + \brief vos_get_binary_blob() - get binary data from platform + This API allows components to get binary data from the platform independent + of where the data is stored on the device. +
    +
  • Firmware +
  • Configuration Data + \param binaryId - identifies the binary data to return to the caller. + raw binary data and update the *pBufferSize with the exact + size of the data that has been retreived. + the size of the binary data in *pBufferSize. + size of the data buffer available at pBuffer. Upon success, this + retreived and written to the buffer at pBuffer. + Input value of 0 is valid and will cause the API to return + the size of the binary data in *pBufferSize. + retreived and written to the buffer. + refer to a valid VOS Binary ID. + variable that the API can write to. + *pBufferSize is not big enough to contain the binary. + \sa + --------------------------------------------------------------------------*/ +VOS_STATUS vos_get_binary_blob( VOS_BINARY_ID binaryId, + v_VOID_t *pBuffer, v_SIZE_t *pBufferSize ) +{ + VOS_STATUS VosSts = VOS_STATUS_SUCCESS; + char *pFileName; + + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS,NULL); + + // get the correct file name from binary Id + switch (binaryId) + { + case VOS_BINARY_ID_CONFIG: + pFileName = WLAN_CFG_FILE; + break; + default: + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "Invalid binaryID"); + return VosSts; + } + if(0 == *pBufferSize ) + { + /* just a file size request. set the value and return VOS_STATUS_E_NOMEM*/ + VosSts = hdd_get_cfg_file_size(((VosContextType*)(pVosContext))->pHDDContext,pFileName,pBufferSize); + + if ( !VOS_IS_STATUS_SUCCESS( VosSts )) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s : vos_open failed",__func__); + + return VOS_STATUS_E_FAILURE; + } + VosSts = VOS_STATUS_E_NOMEM; + } + else + { + if(NULL != pBuffer) { + // read the contents into the buffer + VosSts = hdd_read_cfg_file(((VosContextType*)(pVosContext))->pHDDContext,pFileName,pBuffer,pBufferSize); + } + else { + VosSts = VOS_STATUS_E_FAILURE; + } + } + + return VosSts; +} + + +tVOS_CON_MODE vos_get_conparam( void ) +{ + tVOS_CON_MODE con_mode; + con_mode = hdd_get_conparam ( ); + return con_mode; +} +tVOS_CONCURRENCY_MODE vos_get_concurrency_mode( void ) +{ + tVOS_CONCURRENCY_MODE con_mode; + con_mode = hdd_get_concurrency_mode ( ); + return con_mode; +} + +v_BOOL_t vos_concurrent_open_sessions_running(void) +{ + v_U8_t i=0; + v_U8_t j=0; + hdd_context_t *pHddCtx; + v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); + + if (NULL != pVosContext) + { + pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) + { + for (i=0; i < VOS_MAX_NO_OF_MODE; i++) + { + j += pHddCtx->no_of_open_sessions[i]; + } + } + } + + return (j>1); +} + +#ifdef WLAN_FEATURE_MBSSID +v_BOOL_t vos_concurrent_beaconing_sessions_running(v_VOID_t) +{ + v_U8_t i=0; + hdd_context_t *pHddCtx; + v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); + + if (NULL != pVosContext) + { + pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) + { + i = pHddCtx->no_of_open_sessions[VOS_STA_SAP_MODE] + + pHddCtx->no_of_open_sessions[VOS_P2P_GO_MODE] + + pHddCtx->no_of_open_sessions[VOS_IBSS_MODE]; + } + } + + return (i>1); +} +#endif + + +/**--------------------------------------------------------------------------- + * + * \brief vos_max_concurrent_connections_reached() + * + * This function checks for presence of concurrency where more than + * one connection exists and it returns TRUE if the max concurrency is + * reached. + * + * Example: + * STA + STA (wlan0 and wlan1 are connected) - returns TRUE + * STA + STA (wlan0 connected and wlan1 disconnected) - returns FALSE + * DUT with P2P-GO + P2P-CLIENT connection) - returns TRUE + * + * \param - None + * + * \return - VOS_TRUE or VOS_FALSE + * + * --------------------------------------------------------------------------*/ +v_BOOL_t vos_max_concurrent_connections_reached (void) +{ + v_U8_t i = 0, j = 0; + hdd_context_t *pHddCtx; + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + + if (NULL != pVosContext) { + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) { + for (i = 0; i < VOS_MAX_NO_OF_MODE; i++) + j += pHddCtx->no_of_active_sessions[i]; + + return (j > (pHddCtx->cfg_ini->gMaxConcurrentActiveSessions - 1)); + } + } + + return VOS_FALSE; +} + +void vos_clear_concurrent_session_count(void) +{ + v_U8_t i = 0; + hdd_context_t *pHddCtx; + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + + if (NULL != pVosContext) { + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) { + for (i = 0; i < VOS_MAX_NO_OF_MODE; i++) + pHddCtx->no_of_active_sessions[i] = 0; + } + } +} + +/**--------------------------------------------------------------------------- + * + * \brief vos_is_multiple_active_sta_sessions() + * + * This function checks for presence of multiple active sta connections + * and it returns TRUE if the more than 1 active sta connection exists. + * + * \param - None + * + * \return - TRUE or FALSE + * + * --------------------------------------------------------------------------*/ +v_BOOL_t vos_is_multiple_active_sta_sessions (void) +{ + hdd_context_t *pHddCtx; + v_U8_t j = 0; + + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + if (NULL != pVosContext) { + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) { + j = pHddCtx->no_of_active_sessions[VOS_STA_MODE]; + } + } + + return (j > 1); +} + +/**--------------------------------------------------------------------------- + * + * \brief vos_is_sta_active_connection_exists() + * + * This function checks for the presence of active sta connection + * and it returns TRUE if exists. + * + * \param - None + * + * \return - VOS_TRUE or VOS_FALSE + * + * --------------------------------------------------------------------------*/ +v_BOOL_t vos_is_sta_active_connection_exists (void) +{ + hdd_context_t *pHddCtx; + v_U8_t j = 0; + + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + if (NULL != pVosContext) { + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (NULL != pHddCtx) { + j = pHddCtx->no_of_active_sessions[VOS_STA_MODE]; + } + } + + return (j ? VOS_TRUE : VOS_FALSE); +} + diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_list.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_list.c new file mode 100644 index 000000000000..2ce881343bed --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_list.c @@ -0,0 +1,945 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**============================================================================= + + vos_list.c + + \brief + + Description... + + ==============================================================================**/ +/* $HEADER$ */ + +/**----------------------------------------------------------------------------- + Include files + ----------------------------------------------------------------------------*/ +#include +#include + +/**----------------------------------------------------------------------------- + Preprocessor definitions and constants + ----------------------------------------------------------------------------*/ +#define VOS_LIST_COOKIE 0xabadfeed + + +/**----------------------------------------------------------------------------- + Type declarations + ----------------------------------------------------------------------------*/ + +/**----------------------------------------------------------------------------- + Function declarations and documenation + ----------------------------------------------------------------------------*/ +VOS_STATUS vos_list_init( vos_list_t *pList ) +{ + if ( pList == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie == VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: already initialized list", __func__); + return VOS_STATUS_E_BUSY; + } + + mutex_init(&pList->lock); + + INIT_LIST_HEAD( &pList->anchor ); + + pList->count = 0; + pList->cookie = VOS_LIST_COOKIE; + + return( VOS_STATUS_SUCCESS ); +} + + +VOS_STATUS vos_list_destroy( vos_list_t *pList ) +{ + int rc; + if (pList == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->count !=0 ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list length not equal to zero", __func__); + return VOS_STATUS_E_BUSY; + } + + // clear the cookie. This indicates the list is destroyed. + pList->cookie = 0; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + + +VOS_STATUS vos_list_insert_front( vos_list_t *pList, vos_list_node_t *pNode ) +{ + int rc; + + if ( ( pList == NULL) || ( pNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + list_add( pNode, &pList->anchor ); + + pList->count++; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_list_insert_back( vos_list_t *pList, vos_list_node_t *pNode ) +{ + int rc; + + if ( ( pList == NULL) || ( pNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + list_add_tail( pNode, &pList->anchor ); + + pList->count++; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + + +VOS_STATUS vos_list_insert_back_size( vos_list_t *pList, vos_list_node_t *pNode, v_SIZE_t *pSize ) +{ + int rc; + if ( ( pList == NULL) || ( pNode == NULL) || (pSize == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + list_add_tail( pNode, &pList->anchor ); + + pList->count++; + *pSize = pList->count; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + + +VOS_STATUS vos_list_remove_front( vos_list_t *pList, vos_list_node_t **ppNode ) +{ + struct list_head * listptr; + int rc; + + // the assumption here is that pList is the head of the list (dummy + // node) and points to first and last element in circular linked list + if ( ( pList == NULL ) || ( ppNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty( &pList->anchor ) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + listptr = pList->anchor.next; + + *ppNode = listptr; + + list_del(pList->anchor.next); + + pList->count--; + mutex_unlock(&pList->lock); + return VOS_STATUS_SUCCESS; +} + + + +VOS_STATUS vos_list_remove_back( vos_list_t *pList, vos_list_node_t **ppNode ) +{ + struct list_head * listptr; + int rc; + + // the assumption here is that pList is the head of the list (dummy node) and points to first and + // last element in circular linked list + if ( ( pList == NULL ) || ( ppNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty( &pList->anchor ) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + listptr = pList->anchor.prev; + + *ppNode = listptr; + + list_del(pList->anchor.prev); + + pList->count--; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_list_size( vos_list_t *pList, v_SIZE_t *pSize ) +{ + int rc; + if ( ( pList ==NULL) || ( pSize == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + *pSize = pList->count; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + + \brief vos_list_peek_front() - peek at the node at front of a linked list + + The vos_list_peek_front() API will return a pointer to the node at the + front of a properly initialized vOS List object. The node will *not* be + removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param ppNode - Pointer to a pointer to the list node that exists at + the front of the list. + + \return VOS_STATUS_SUCCESS - list node at the front of the list was + successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList or or ppNode is an invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_list_peek_front( vos_list_t *pList, vos_list_node_t **ppNode ) +{ + struct list_head * listptr; + int rc; + + if ( ( pList == NULL) || ( ppNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + listptr = pList->anchor.next; + *ppNode = listptr; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_list_peek_back() - peek at the node at back of a linked list + + The vos_list_peek_back() API will return a pointer to the node at the + back of a properly initialized vOS List object. The node will *not* be + removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param ppNode - Pointer to a pointer to the list node that exists at + the back of the list. + + \return VOS_STATUS_SUCCESS - list node at the back of the list was + successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + VOS_STATUS_E_FAULT - pList or or ppNode is an invalid pointer. + + \sa vos_list_peek_back(), vos_list_remove_back(), vos_list_peek_front(), + vos_list_remove_front() + + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_list_peek_back( vos_list_t *pList, vos_list_node_t **ppNode ) +{ + struct list_head * listptr; + int rc; + + if ( ( pList == NULL) || ( ppNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + listptr = pList->anchor.prev; + *ppNode = listptr; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_list_peek_next() - peek at the node after the specified node + + The vos_list_peek_next() API will return a pointer to the node following the + specified node on a properly initialized vOS List object. The node will + *not* be removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param pNode - Pointer to the node that is being 'peeked' + + \param ppNode - Pointer to a pointer to the list node that follows the + pNode node on the list. + + \return VOS_STATUS_SUCCESS - list node following pNode on the properly + initialized list is successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - There is no 'next' node (the input node is + at the back of the list). + + VOS_STATUS_E_FAULT - pList, pNode or ppNode is an invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_list_peek_next( vos_list_t *pList, vos_list_node_t *pNode, + vos_list_node_t **ppNode ) +{ + struct list_head * listptr; + int rc, found = 0; + vos_list_node_t *tmp; + + if ( ( pList == NULL) || ( pNode == NULL) || (ppNode == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + // verify that pNode is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNode) + { + found = 1; + break; + } + } + if (found == 0) + return VOS_STATUS_E_INVAL; + + listptr = pNode->next; + if (listptr == &pList->anchor) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + *ppNode = listptr; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_list_peek_prev() - peek at the node before the specified node + + The vos_list_peek_prev() API will return a pointer to the node before the + specified node on a properly initialized vOS List object. The node will + *not* be removed from the list. + + \param pList - Pointer to list object of the list to be 'peeked' + + \param pNode - Pointer to the node that is being 'peeked' + + \param ppNode - Pointer to a pointer to the list node before the + pNode node on the list. + + \return VOS_STATUS_SUCCESS - list node before pNode on the properly + initialized list is successfully returned. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - There is no 'previous' node (the input node is + at the front of the list). + + VOS_STATUS_E_FAULT - pList, pNode or ppNode is an invalid pointer. + + \sa vos_list_remove_back() + + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_list_peek_prev( vos_list_t *pList, vos_list_node_t *pNode, + vos_list_node_t **ppNode ) +{ + struct list_head * listptr; + int rc, found = 0; + vos_list_node_t *tmp; + + if ( ( pList == NULL) || ( pNode == NULL) || (ppNode == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + // verify that pNode is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNode) + { + found = 1; + break; + } + } + if (found == 0) + return VOS_STATUS_E_INVAL; + + listptr = pNode->prev; + + if (listptr == &pList->anchor) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + *ppNode = listptr; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_list_insert_before() - insert node at front of a specified + list node + + The vos_list_insert_before() API will insert a node onto a properly + initialized vOS List object in front of the specified list node. + + \param pList - Pointer to list object where the node will be inserted + + \param pNodeToInsert - Pointer to the list node to be inserted into the list. + + \param pNode - Pointer to the list node where pNodeToInsert will be inserted + in front of. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the front of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList, pNodeToInsert, or pNode are + invalid pointer(s) + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_before( vos_list_t *pList, vos_list_node_t *pNodeToInsert, + vos_list_node_t *pNode ) +{ + int rc, found = 0; + vos_list_node_t *tmp; + + if ( ( pList == NULL) || ( pNode == NULL) || (pNodeToInsert == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + // verify that pNode is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNode) + { + found = 1; + break; + } + } + if (found == 0) + return VOS_STATUS_E_INVAL; + + list_add(pNodeToInsert, pNode); + pList->count++; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + + \brief vos_list_insert_after() - insert node behind a specified list node + + The vos_list_insert_after() API will insert a node onto a properly + initialized vOS List object after the specified list node. + + \param pList - Pointer to list object where the node will be inserted + + \param pNodeToInsert - Pointer to the list node to be inserted into the list. + + \param pNode - Pointer to the list node where pNodeToInsert will be inserted + after. + + \return VOS_STATUS_SUCCESS - list node was successfully inserted onto + the front of the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_FAULT - pList, pNodeToInsert, or pNode are + invalid pointer(s) + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_insert_after( vos_list_t *pList, vos_list_node_t *pNodeToInsert, + vos_list_node_t *pNode ) +{ + int rc, found = 0; + vos_list_node_t *tmp; + + if ( ( pList == NULL) || ( pNode == NULL) || (pNodeToInsert == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + // verify that pNode is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNode) + { + found = 1; + break; + } + } + if (found == 0) + return VOS_STATUS_E_INVAL; + + list_add_tail(pNodeToInsert, pNode); + pList->count++; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + + \brief vos_list_remove_node() - remove specified node from vOS list list + + The vos_list_remove_node() API will remove a specified node from the + properly initialized vOS List object. + + \param pList - Pointer to list object where the node will be removed + + \param ppNode - Pointer to the node to be removed from the list. + + \return VOS_STATUS_SUCCESS - list node was successfully removed from + the list. + + VOS_STATUS_E_INVAL - The value specified by pList is not a valid, + initialized list object. + + VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be + removed. + + + VOS_STATUS_E_FAULT - pList or pNodeToRemove is not a valid pointer + + \sa + + --------------------------------------------------------------------------*/ +VOS_STATUS vos_list_remove_node( vos_list_t *pList, vos_list_node_t *pNodeToRemove ) +{ + int rc, found = 0; + vos_list_node_t *tmp; + + if ( ( pList == NULL ) || ( pNodeToRemove == NULL) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( pList->cookie != VOS_LIST_COOKIE ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list not initialized", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + rc = mutex_lock_interruptible(&pList->lock); + if (rc) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( list_empty(&pList->anchor) ) + { + mutex_unlock(&pList->lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: list empty", __func__); + return VOS_STATUS_E_EMPTY; + } + + // verify that pNodeToRemove is indeed part of list pList + list_for_each(tmp, &pList->anchor) + { + if (tmp == pNodeToRemove) + { + found = 1; + break; + } + } + if (found == 0) + return VOS_STATUS_E_INVAL; + + list_del(pNodeToRemove); + pList->count--; + mutex_unlock(&pList->lock); + + return VOS_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c new file mode 100644 index 000000000000..3428686fb26d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c @@ -0,0 +1,739 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*============================================================================ + FILE: vos_lock.c + + OVERVIEW: This source file contains definitions for vOS lock APIs + The four APIs mentioned in this file are used for + initializing , acquiring, releasing and destroying a lock. + the lock are implemented using critical sections + + DEPENDENCIES: +============================================================================*/ + +/*============================================================================ + EDIT HISTORY FOR MODULE + +============================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + +#include "vos_lock.h" +#include "vos_memory.h" +#include "vos_trace.h" +#include "vos_api.h" +#include "hif.h" +#include "i_vos_diag_core_event.h" +#ifdef CONFIG_CNSS +#include +#endif +#include "vos_api.h" +#include "aniGlobal.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT 0 +#define WIFI_POWER_EVENT_WAKELOCK_TAKEN 0 +#define WIFI_POWER_EVENT_WAKELOCK_RELEASED 1 + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +#define LINUX_LOCK_COOKIE 0x12345678 +enum +{ + LOCK_RELEASED = 0x11223344, + LOCK_ACQUIRED, + LOCK_DESTROYED +}; + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + Function Definitions and Documentation + * -------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + + \brief vos_lock_init() - initializes a vOSS lock + + The vos_lock_init() function initializes the specified lock. Upon + successful initialization, the state of the lock becomes initialized + and unlocked. + + A lock must be initialized by calling vos_lock_init() before it + may be used in any other lock functions. + + Attempting to initialize an already initialized lock results in + a failure. + + \param lock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - lock was successfully initialized and + is ready to be used. + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the lock + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to reinitialize the object referenced by lock, a previously + initialized, but not yet destroyed, lock. + + VOS_STATUS_E_FAULT - lock is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the lock + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_init ( vos_lock_t *lock ) +{ + + //check for invalid pointer + if ( lock == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in",__func__); + return VOS_STATUS_E_FAULT; + } + // check for 'already initialized' lock + if ( LINUX_LOCK_COOKIE == lock->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: already initialized lock",__func__); + return VOS_STATUS_E_BUSY; + } + + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + return VOS_STATUS_E_FAULT; + } + + // initialize new lock + mutex_init( &lock->m_lock ); + lock->cookie = LINUX_LOCK_COOKIE; + lock->state = LOCK_RELEASED; + lock->processID = 0; + lock->refcount = 0; + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_lock_acquire() - acquires a lock + + A lock object is acquired by calling \a vos_lock_acquire(). If the lock + is already locked, the calling thread shall block until the lock becomes + available. This operation shall return with the lock object referenced by + lock in the locked state with the calling thread as its owner. + + \param lock - the lock object to acquire + + \return VOS_STATUS_SUCCESS - the lock was successfully acquired by + the calling thread. + + VOS_STATUS_E_INVAL - The value specified by lock does not refer + to an initialized lock object. + + VOS_STATUS_E_FAULT - lock is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_acquire ( vos_lock_t* lock ) +{ + int rc; + //Check for invalid pointer + if ( lock == NULL ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + // check if lock refers to an initialized object + if ( LINUX_LOCK_COOKIE != lock->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: uninitialized lock",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + if ((lock->processID == current->pid) && + (lock->state == LOCK_ACQUIRED)) + { + lock->refcount++; +#ifdef VOS_NESTED_LOCK_DEBUG + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: %x %d %d", __func__, lock, current->pid, lock->refcount); +#endif + return VOS_STATUS_SUCCESS; + } + // Acquire a Lock + mutex_lock( &lock->m_lock ); + rc = mutex_is_locked( &lock->m_lock ); + if (rc == 0) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock mutex (rc = %d)", __func__, rc); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + + +#ifdef VOS_NESTED_LOCK_DEBUG + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: %x %d", __func__, lock, current->pid); +#endif + if ( LOCK_DESTROYED != lock->state ) + { + lock->processID = current->pid; + lock->refcount++; + lock->state = LOCK_ACQUIRED; + return VOS_STATUS_SUCCESS; + } + else + { + // lock is already destroyed + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Lock is already destroyed", __func__); + mutex_unlock(&lock->m_lock); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } +} + + +/*-------------------------------------------------------------------------- + + \brief vos_lock_release() - releases a lock + + The \a vos_lock_release() function shall release the lock object + referenced by 'lock'. + + If a thread attempts to release a lock that it unlocked or is not + initialized, an error is returned. + + \param lock - the lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + VOS_STATUS_E_INVAL - The value specified by lock does not refer + to an initialized lock object. + + VOS_STATUS_E_FAULT - The value specified by lock does not refer + to an initialized lock object. + + VOS_STATUS_E_PERM - Operation is not permitted. The calling + thread does not own the lock. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_release ( vos_lock_t *lock ) +{ + //Check for invalid pointer + if ( lock == NULL ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // check if lock refers to an uninitialized object + if ( LINUX_LOCK_COOKIE != lock->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: uninitialized lock",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // CurrentThread = GetCurrentThreadId(); + // Check thread ID of caller against thread ID + // of the thread which acquire the lock + if ( lock->processID != current->pid ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: current task pid does not match original task pid!!",__func__); +#ifdef VOS_NESTED_LOCK_DEBUG + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: Lock held by=%d being released by=%d", __func__, lock->processID, current->pid); +#endif + + VOS_ASSERT(0); + return VOS_STATUS_E_PERM; + } + if ((lock->processID == current->pid) && + (lock->state == LOCK_ACQUIRED)) + { + if (lock->refcount > 0) lock->refcount--; + } +#ifdef VOS_NESTED_LOCK_DEBUG + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: %x %d %d", __func__, lock, lock->processID, lock->refcount); +#endif + if (lock->refcount) return VOS_STATUS_SUCCESS; + + lock->processID = 0; + lock->refcount = 0; + lock->state = LOCK_RELEASED; + // Release a Lock + mutex_unlock( &lock->m_lock ); +#ifdef VOS_NESTED_LOCK_DEBUG + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: Freeing lock %x %d %d", lock, lock->processID, lock->refcount); +#endif + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_lock_destroy() - Destroys a vOSS Lock - probably not required + for Linux. It may not be required for the caller to destroy a lock after + usage. + + The \a vos_lock_destroy() function shall destroy the lock object + referenced by lock. After a successful return from \a vos_lock_destroy() + the lock object becomes, in effect, uninitialized. + + A destroyed lock object can be reinitialized using vos_lock_init(); + the results of otherwise referencing the object after it has been destroyed + are undefined. Calls to vOSS lock functions to manipulate the lock such + as vos_lock_acquire() will fail if the lock is destroyed. Therefore, + don't use the lock after it has been destroyed until it has + been re-initialized. + + \param lock - the lock object to be destroyed. + + \return VOS_STATUS_SUCCESS - lock was successfully destroyed. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by lock while it is locked + or still referenced. + + VOS_STATUS_E_INVAL - The value specified by lock is invalid. + + VOS_STATUS_E_FAULT - lock is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_lock_destroy( vos_lock_t *lock ) +{ + //Check for invalid pointer + if ( NULL == lock ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in", __func__); + return VOS_STATUS_E_FAULT; + } + + if ( LINUX_LOCK_COOKIE != lock->cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: uninitialized lock", __func__); + return VOS_STATUS_E_INVAL; + } + + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + return VOS_STATUS_E_FAULT; + } + + // check if lock is released + if (!mutex_trylock(&lock->m_lock)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: lock is not released", __func__); + return VOS_STATUS_E_BUSY; + } + lock->cookie = 0; + lock->state = LOCK_DESTROYED; + lock->processID = 0; + lock->refcount = 0; + + mutex_unlock(&lock->m_lock); + + + return VOS_STATUS_SUCCESS; +} + + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_init() - initializes a vOSS spin lock + + The vos_spin_lock_init() function initializes the specified spin lock. Upon + successful initialization, the state of the lock becomes initialized + and unlocked. + + A lock must be initialized by calling vos_spin_lock_init() before it + may be used in any other lock functions. + + Attempting to initialize an already initialized lock results in + a failure. + + \param pLock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - spin lock was successfully initialized and + is ready to be used. + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_spin_lock_init(vos_spin_lock_t *pLock) +{ + spin_lock_init(pLock); + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_acquire() - acquires a spin lock + + A lock object is acquired by calling \a vos_spin_lock_acquire(). If the lock + is already locked, the calling thread shall spin until the lock becomes + available. This operation shall return with the lock object referenced by + lock in the locked state with the calling thread as its owner. + + \param pLock - the lock object to acquire + + \return VOS_STATUS_SUCCESS - the lock was successfully acquired by + the calling thread. + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_acquire(vos_spin_lock_t *pLock) +{ + spin_lock(pLock); + return VOS_STATUS_SUCCESS; +} +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_release() - releases a lock + + The \a vos_lock_release() function shall release the spin lock object + referenced by 'lock'. + + If a thread attempts to release a lock that it unlocked or is not + initialized, an error is returned. + + \param pLock - the lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_release(vos_spin_lock_t *pLock) +{ + spin_unlock(pLock); + return VOS_STATUS_SUCCESS; +} + + +/*-------------------------------------------------------------------------- + + \brief vos_spin_lock_destroy() - releases resource of a lock + + \param pLock - the pointer to a lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + \sa + ------------------------------------------------------------------------*/ +VOS_STATUS vos_spin_lock_destroy(vos_spin_lock_t *pLock) +{ + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_init() - initializes a vOSS wake lock + + \param pLock - the wake lock to initialize + name - wakelock name + + \return VOS_STATUS_SUCCESS - wake lock was successfully initialized and + is ready to be used. + --------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_init(vos_wake_lock_t *pLock, const char *name) +{ +#if defined CONFIG_CNSS + cnss_pm_wake_lock_init(&pLock->lock, name); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_init(&pLock->lock, WAKE_LOCK_SUSPEND, name); +#endif + + return VOS_STATUS_SUCCESS; +} + +/** + * vos_wake_lock_name() - This function returns the name of the wakelock + * @pLock: Pointer to the wakelock + * + * This function returns the name of the wakelock + * + * Return: Pointer to the name if it is valid or a default string + * + */ +static const char* vos_wake_lock_name(vos_wake_lock_t *pLock) +{ +#if defined CONFIG_CNSS + if (pLock->lock.name) + return pLock->lock.name; +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + if (pLock->lock.ws.name) + return pLock->lock.ws.name; +#endif + return "UNNAMED_WAKELOCK"; +} + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_acquire() - acquires a wake lock + + \param pLock - the wake lock to acquire + + \return VOS_STATUS_SUCCESS - the wake lock was successfully acquired + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_acquire(vos_wake_lock_t *pLock, + uint32_t reason) +{ + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); + +#if defined CONFIG_CNSS + cnss_pm_wake_lock(&pLock->lock); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock(&pLock->lock); +#endif + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_timeout_acquire() - acquires a wake lock with a timeout + + \param pLock - the wake lock to acquire + + \return VOS_STATUS_SUCCESS - the wake lock was successfully acquired + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_timeout_acquire(vos_wake_lock_t *pLock, v_U32_t msec, + uint32_t reason) +{ + /* Wakelock for Rx is frequent. + * It is reported only during active debug + */ + if (((vos_get_ring_log_level(RING_ID_WAKELOCK) >= WLAN_LOG_LEVEL_ACTIVE) + && (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX == reason)) || + (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX != reason)) { + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), msec, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); + } + +#if defined CONFIG_CNSS + cnss_pm_wake_lock_timeout(&pLock->lock, msec); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_timeout(&pLock->lock, msecs_to_jiffies(msec)); +#endif + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_release() - releases a wake lock + + \param pLock - the wake lock to release + + \return VOS_STATUS_SUCCESS - the lock was successfully released + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason) +{ + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_RELEASED); +#if defined CONFIG_CNSS + cnss_pm_wake_lock_release(&pLock->lock); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_unlock(&pLock->lock); +#endif + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_wake_lock_destroy() - destroys a wake lock + + \param pLock - the wake lock to destroy + + \return VOS_STATUS_SUCCESS - the lock was successfully destroyed + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_wake_lock_destroy(vos_wake_lock_t *pLock) +{ +#if defined CONFIG_CNSS + cnss_pm_wake_lock_destroy(&pLock->lock); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_destroy(&pLock->lock); +#endif + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_runtime_pm_prevent_suspend(runtime_pm_context_t runtime_pm_ctx) +{ + void *ol_sc; + int ret = 0; + + ol_sc = vos_get_context(VOS_MODULE_ID_HIF, + vos_get_global_context(VOS_MODULE_ID_SYS, NULL)); + + if (ol_sc == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return VOS_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_prevent_suspend(ol_sc, runtime_pm_ctx); + + if (ret) + return VOS_STATUS_E_FAILURE; + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_runtime_pm_allow_suspend(runtime_pm_context_t runtime_pm_ctx) +{ + void *ol_sc; + int ret = 0; + + ol_sc = vos_get_context(VOS_MODULE_ID_HIF, + vos_get_global_context(VOS_MODULE_ID_SYS, NULL)); + + if (ol_sc == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return VOS_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_allow_suspend(ol_sc, runtime_pm_ctx); + + if (ret) + return VOS_STATUS_E_FAILURE; + + return VOS_STATUS_SUCCESS; +} + +/** + * vos_runtime_pm_prevent_suspend_timeout() - Prevent runtime suspend timeout + * msec: Timeout in milliseconds + * + * Prevent runtime suspend with a timeout after which runtime suspend would be + * allowed. This API uses a single timer to allow the suspend and timer is + * modified if the timeout is changed before timer fires. + * If the timeout is less than autosuspend_delay then use mark_last_busy instead + * of starting the timer. + * + * It is wise to try not to use this API and correct the design if possible. + * + * Return: VOS_STATUS + */ +VOS_STATUS vos_runtime_pm_prevent_suspend_timeout(runtime_pm_context_t context, + unsigned int msec) +{ + void *ol_sc; + int ret = 0; + + ol_sc = vos_get_context(VOS_MODULE_ID_HIF, + vos_get_global_context(VOS_MODULE_ID_SYS, NULL)); + + if (ol_sc == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return VOS_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_prevent_suspend_timeout(ol_sc, context, msec); + if (ret) + return VOS_STATUS_E_FAILURE; + + return VOS_STATUS_SUCCESS; +} + +/** + * vos_runtime_pm_prevent_suspend_init() - Runtime PM Prevent Suspend Ctx init + * @name: name of the context + * + * Through out driver this API should be called to initialize the runtime pm + * instance. + * + * Return: void* + */ +void *vos_runtime_pm_prevent_suspend_init(const char *name) +{ + return hif_runtime_pm_prevent_suspend_init(name); +} + +/** + * vos_runtime_pm_prevent_suspend_deinit() - Runtime PM Prevent context deinit + * @data: Runtime PM context pointer + * + * This API should be called to release the Runtime PM context. + * + * Return: void + */ +void vos_runtime_pm_prevent_suspend_deinit(runtime_pm_context_t data) +{ + hif_runtime_pm_prevent_suspend_deinit(data); +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_memory.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_memory.c new file mode 100644 index 000000000000..3abb8fa17141 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_memory.c @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + @file vos_memory.c + + @brief Virtual Operating System Services Memory API +===========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + +===========================================================================*/ + +/*--------------------------------------------------------------------------- + * Include Files + * ------------------------------------------------------------------------*/ +#include "vos_memory.h" +#include "vos_trace.h" + +#ifdef CONFIG_CNSS +#include +#endif + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC +#include +#endif + +#ifdef MEMORY_DEBUG +#include "wlan_hdd_dp_utils.h" + +hdd_list_t vosMemList; + +static v_U8_t WLAN_MEM_HEADER[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68 }; +static v_U8_t WLAN_MEM_TAIL[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87}; + +#define VOS_MEM_MAX_STACK_TRACE 16 + +struct s_vos_mem_struct +{ + hdd_list_node_t pNode; + const char *fileName; + unsigned int lineNum; + unsigned int size; +#ifdef WLAN_OPEN_SOURCE + unsigned long stack_trace[VOS_MEM_MAX_STACK_TRACE]; + struct stack_trace trace; +#endif + v_U8_t header[8]; +}; + +#ifdef MEM_USAGE_TRACE +#define MIN_TRACE_SIZE (50 * 1024) +#define MAX_USAGE_TRACE_BUF_NUM 20 +struct s_vos_mem_usage_struct { + const char *fileName; + unsigned int lineNum; + unsigned int size; + unsigned int peakCount; + unsigned int activeCount; +}; +static unsigned int g_usage_index = 0; +static struct s_vos_mem_usage_struct g_usage_mem_buf[MAX_USAGE_TRACE_BUF_NUM]; +#endif +#endif + +/*--------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Type Declarations + * ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Data definitions + * ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * External Function implementation + * ------------------------------------------------------------------------*/ +#ifdef MEMORY_DEBUG +#ifdef MEM_USAGE_TRACE +static void +init_trace_usage(void) +{ + g_usage_index = 0; + memset(&g_usage_mem_buf[0], 0, sizeof(g_usage_mem_buf)); + pr_info("%s: Mem Usage Trace Enabled ******\n", __func__); +} + +static void +alloc_trace_usage(const char *fileName, unsigned int lineNum, + unsigned int size) +{ + unsigned int i; + struct s_vos_mem_usage_struct *p; + + if (size < MIN_TRACE_SIZE) + return; + + for (i = 0 ; i < g_usage_index; i++) { + p = &g_usage_mem_buf[i]; + if (p->fileName == fileName && p->lineNum == lineNum && + p->size == size) { + p->activeCount++; + if (p->activeCount > p->peakCount) { + p->peakCount = p->activeCount; + } + return; + } + } + + if (g_usage_index >= MAX_USAGE_TRACE_BUF_NUM) { + pr_err("usage trace buf overflow\n"); + return; + } + i = g_usage_index; + g_usage_index++; + + p = &g_usage_mem_buf[i]; + p->fileName = fileName; + p->lineNum = lineNum; + p->size = size; + p->activeCount = 1; + p->peakCount = 1; +} + +static void +free_trace_usage(const char *fileName, unsigned int lineNum, + unsigned int size) +{ + unsigned int i; + struct s_vos_mem_usage_struct *p; + + if (size < MIN_TRACE_SIZE) + return; + + for (i = 0 ; i < g_usage_index; i++) { + p = &g_usage_mem_buf[i]; + if (p->fileName == fileName && p->lineNum == lineNum && + p->size == size) { + p->activeCount--; + return; + } + } +} + +static void dump_trace_usage(void) +{ + unsigned int i; + struct s_vos_mem_usage_struct *p; + + for (i = 0 ; i < g_usage_index; i++) { + p = &g_usage_mem_buf[i]; + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: size %d active %d peak %d file %s %d", + __func__, p->size, p->activeCount, p->peakCount, + p->fileName, p->lineNum); + } +} +#else +static inline void init_trace_usage(void) +{ + return; +} + +static inline void +alloc_trace_usage(const char *fileName, unsigned int lineNum, + unsigned int size) +{ + return; +} + +static inline void +free_trace_usage(const char *fileName, unsigned int lineNum, + unsigned int size) +{ + return; +} + +static inline void dump_trace_usage(void) +{ + return; +} +#endif + +void vos_mem_trace_dump(int level) +{ + hdd_list_node_t *pNode; + hdd_list_node_t *pNodeNext = NULL; + unsigned int totalUsed = 0; + int i = 0; + VOS_STATUS vosStatus; + struct s_vos_mem_struct *memStruct; + + spin_lock(&vosMemList.lock); + hdd_list_peek_front(&vosMemList, &pNodeNext); + do { + if (pNodeNext == NULL) + break; + pNode = pNodeNext; + memStruct = (struct s_vos_mem_struct *)pNode; + totalUsed += memStruct->size; + if (level >= 1) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "vos_mem [%04d] @ File %s, @Line %d, size %d", + i, memStruct->fileName, memStruct->lineNum, + memStruct->size); + } + i++; + pNodeNext = NULL; + } while ((vosStatus = hdd_list_peek_next(&vosMemList, + pNode, &pNodeNext)) == VOS_STATUS_SUCCESS); + spin_unlock(&vosMemList.lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "vos_mem [total active] count %d size %d", i, totalUsed); + + dump_trace_usage(); +} + +void vos_mem_init() +{ + /* Initalizing the list with maximum size of 60000 */ + hdd_list_init(&vosMemList, 60000); + init_trace_usage(); + pr_info("%s: Memory Debug Enabled ******\n", __func__); + return; +} + +#ifdef WLAN_OPEN_SOURCE +/** + * vos_mem_save_stack_trace() - Save stack trace of the caller + * @mem_struct: Pointer to the memory structure where to save the stack trace + * + * Return: None + */ +static inline void vos_mem_save_stack_trace(struct s_vos_mem_struct* mem_struct) +{ + struct stack_trace *trace = &mem_struct->trace; + + trace->nr_entries = 0; + trace->max_entries = VOS_MEM_MAX_STACK_TRACE; + trace->entries = mem_struct->stack_trace; + trace->skip = 2; + + save_stack_trace(trace); +} + +/** + * vos_mem_print_stack_trace() - Print saved stack trace + * @mem_struct: Pointer to the memory structure which has the saved stack trace + * to be printed + * + * Return: None + */ +static inline void vos_mem_print_stack_trace(struct s_vos_mem_struct* mem_struct) +{ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Call stack for the source of leaked memory:"); + + print_stack_trace(&mem_struct->trace, 1); +} +#else +static inline void vos_mem_save_stack_trace(struct s_vos_mem_struct* mem_struct) +{ + +} +static inline void vos_mem_print_stack_trace(struct s_vos_mem_struct* mem_struct) +{ + +} +#endif + +void vos_mem_clean() +{ + v_SIZE_t listSize; + hdd_list_size(&vosMemList, &listSize); + + if(listSize) + { + hdd_list_node_t* pNode; + VOS_STATUS vosStatus; + + struct s_vos_mem_struct* memStruct; + const char *prev_mleak_file = ""; + unsigned int prev_mleak_lineNum = 0; + unsigned int prev_mleak_sz = 0; + unsigned int mleak_cnt = 0; + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: List is not Empty. listSize %d ", __func__, (int)listSize); + + do + { + spin_lock(&vosMemList.lock); + vosStatus = hdd_list_remove_front(&vosMemList, &pNode); + spin_unlock(&vosMemList.lock); + if(VOS_STATUS_SUCCESS == vosStatus) + { + memStruct = (struct s_vos_mem_struct*)pNode; + + /* Take care to log only once multiple memory leaks from + * the same place */ + if(strcmp(prev_mleak_file, memStruct->fileName) || + (prev_mleak_lineNum != memStruct->lineNum) || + (prev_mleak_sz != memStruct->size)) + { + if(mleak_cnt != 0) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%d Time Memory Leak@ File %s, @Line %d, size %d", + mleak_cnt, prev_mleak_file, prev_mleak_lineNum, + prev_mleak_sz); + } + prev_mleak_file = memStruct->fileName; + prev_mleak_lineNum = memStruct->lineNum; + prev_mleak_sz = memStruct->size; + mleak_cnt = 0; + } + mleak_cnt++; + + vos_mem_print_stack_trace(memStruct); + + kfree((v_VOID_t*)memStruct); + } + }while(vosStatus == VOS_STATUS_SUCCESS); + + /* Print last memory leak from the module */ + if(mleak_cnt) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%d Time memory Leak@ File %s, @Line %d, size %d", + mleak_cnt, prev_mleak_file, prev_mleak_lineNum, + prev_mleak_sz); + } + + +#ifdef CONFIG_HALT_KMEMLEAK + BUG_ON(0); +#endif + } + + dump_trace_usage(); +} + +void vos_mem_exit() +{ + vos_mem_clean(); + hdd_list_destroy(&vosMemList); +} + +v_VOID_t *vos_mem_malloc_debug(v_SIZE_t size, const char *fileName, + v_U32_t lineNum) +{ + struct s_vos_mem_struct* memStruct; + v_VOID_t* memPtr = NULL; + v_SIZE_t new_size; + int flags = GFP_KERNEL; + unsigned long IrqFlags; + + + if (size > (1024*1024)|| size == 0) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: called with invalid arg %u !!!", __func__, size); + return NULL; + } + + if (in_interrupt() || in_atomic() || irqs_disabled()) + { + flags = GFP_ATOMIC; + } + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + if (size > WCNSS_PRE_ALLOC_GET_THRESHOLD) + { + v_VOID_t *pmem; + pmem = wcnss_prealloc_get(size); + if (NULL != pmem) { + memset(pmem, 0, size); + return pmem; + } + } +#endif + + new_size = size + sizeof(struct s_vos_mem_struct) + 8; + + memStruct = (struct s_vos_mem_struct*)kmalloc(new_size, flags); + + if(memStruct != NULL) + { + VOS_STATUS vosStatus; + + memStruct->fileName = fileName; + memStruct->lineNum = lineNum; + memStruct->size = size; + + vos_mem_save_stack_trace(memStruct); + + vos_mem_copy(&memStruct->header[0], &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER)); + vos_mem_copy( (v_U8_t*)(memStruct + 1) + size, &WLAN_MEM_TAIL[0], sizeof(WLAN_MEM_TAIL)); + + spin_lock_irqsave(&vosMemList.lock, IrqFlags); + vosStatus = hdd_list_insert_front(&vosMemList, &memStruct->pNode); + alloc_trace_usage(fileName, lineNum, size); + spin_unlock_irqrestore(&vosMemList.lock, IrqFlags); + if(VOS_STATUS_SUCCESS != vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to insert node into List vosStatus %d", __func__, vosStatus); + } + + memPtr = (v_VOID_t*)(memStruct + 1); + } + return memPtr; +} + +v_VOID_t vos_mem_free( v_VOID_t *ptr ) +{ + unsigned long IrqFlags; + + if (ptr != NULL) + { + VOS_STATUS vosStatus; + struct s_vos_mem_struct* memStruct = ((struct s_vos_mem_struct*)ptr) - 1; + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + if (wcnss_prealloc_put(ptr)) + return; +#endif + + spin_lock_irqsave(&vosMemList.lock, IrqFlags); + vosStatus = hdd_list_remove_node(&vosMemList, &memStruct->pNode); + free_trace_usage(memStruct->fileName, memStruct->lineNum, + memStruct->size); + spin_unlock_irqrestore(&vosMemList.lock, IrqFlags); + + if(VOS_STATUS_SUCCESS == vosStatus) + { + if(0 == vos_mem_compare(memStruct->header, &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER)) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Memory Header is corrupted. MemInfo: Filename %s, LineNum %d", + memStruct->fileName, (int)memStruct->lineNum); + VOS_BUG(0); + } + if(0 == vos_mem_compare( (v_U8_t*)ptr + memStruct->size, &WLAN_MEM_TAIL[0], sizeof(WLAN_MEM_TAIL ) ) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Memory Trailer is corrupted. MemInfo: Filename %s, LineNum %d", + memStruct->fileName, (int)memStruct->lineNum); + VOS_BUG(0); + } + kfree((v_VOID_t*)memStruct); + } + else + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Unallocated memory (double free?)", __func__); + VOS_BUG(0); + } + } +} +#else +v_VOID_t * vos_mem_malloc( v_SIZE_t size ) +{ + int flags = GFP_KERNEL; +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + v_VOID_t* pmem; +#endif + if (size > (1024*1024) || size == 0) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: called with invalid arg %u !!", __func__, size); + return NULL; + } + if (in_interrupt() || irqs_disabled() || in_atomic()) + { + flags = GFP_ATOMIC; + } +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + if(size > WCNSS_PRE_ALLOC_GET_THRESHOLD) + { + pmem = wcnss_prealloc_get(size); + if(NULL != pmem) { + memset(pmem, 0, size); + return pmem; + } + } +#endif + return kmalloc(size, flags); +} + +v_VOID_t vos_mem_free( v_VOID_t *ptr ) +{ + if (ptr == NULL) + return; + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + if(wcnss_prealloc_put(ptr)) + return; +#endif + + kfree(ptr); +} +#endif + +v_BOOL_t vos_is_in_irq_context(void) +{ + if(in_interrupt()) + return VOS_TRUE; + else + return VOS_FALSE; +} + +v_VOID_t vos_mem_set( v_VOID_t *ptr, v_SIZE_t numBytes, v_BYTE_t value ) +{ + if (ptr == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s called with NULL parameter ptr", __func__); + return; + } + memset(ptr, value, numBytes); +} + +v_VOID_t vos_mem_zero( v_VOID_t *ptr, v_SIZE_t numBytes ) +{ + if (0 == numBytes) + { + // special case where ptr can be NULL + return; + } + + if (ptr == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s called with NULL parameter ptr", __func__); + return; + } + memset(ptr, 0, numBytes); + +} + +v_VOID_t vos_mem_copy( v_VOID_t *pDst, const v_VOID_t *pSrc, v_SIZE_t numBytes ) +{ + if (0 == numBytes) + { + // special case where pDst or pSrc can be NULL + return; + } + + if ((pDst == NULL) || (pSrc==NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, source:%p destination:%p", + __func__, pSrc, pDst); + VOS_ASSERT(0); + return; + } + memcpy(pDst, pSrc, numBytes); +} + +v_VOID_t vos_mem_move( v_VOID_t *pDst, const v_VOID_t *pSrc, v_SIZE_t numBytes ) +{ + if (0 == numBytes) + { + // special case where pDst or pSrc can be NULL + return; + } + + if ((pDst == NULL) || (pSrc==NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, source:%p destination:%p", + __func__, pSrc, pDst); + VOS_ASSERT(0); + return; + } + memmove(pDst, pSrc, numBytes); +} + +v_BOOL_t vos_mem_compare(const v_VOID_t *pMemory1, const v_VOID_t *pMemory2, v_U32_t numBytes ) +{ + if (0 == numBytes) + { + // special case where pMemory1 or pMemory2 can be NULL + return VOS_TRUE; + } + + if ((pMemory1 == NULL) || (pMemory2==NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, p1:%p p2:%p", + __func__, pMemory1, pMemory2); + VOS_ASSERT(0); + return VOS_FALSE; + } + return (memcmp(pMemory1, pMemory2, numBytes)?VOS_FALSE:VOS_TRUE); +} + + +v_SINT_t vos_mem_compare2( v_VOID_t *pMemory1, v_VOID_t *pMemory2, v_U32_t numBytes ) + +{ + return( (v_SINT_t) memcmp( pMemory1, pMemory2, numBytes ) ); +} + +/*---------------------------------------------------------------------------- + + \brief vos_mem_dma_malloc() - vOSS DMA Memory Allocation + + This function will dynamicallly allocate the specified number of bytes of + memory. This memory will have special attributes making it DMA friendly i.e. + it will exist in contiguous, 32-byte aligned uncached memory. A normal + vos_mem_malloc does not yield memory with these attributes. + + NOTE: the special DMA friendly memory is very scarce and this API must be + used sparingly + + On WM, there is nothing special about this memory. SDHC allocates the + DMA friendly buffer and copies the data into it + + \param size - the number of bytes of memory to allocate. + + \return Upon successful allocate, returns a non-NULL pointer to the + allocated memory. If this function is unable to allocate the amount of + memory specified (for any reason) it returns NULL. + + \sa + + --------------------------------------------------------------------------*/ +#ifdef MEMORY_DEBUG +v_VOID_t * vos_mem_dma_malloc_debug( v_SIZE_t size, char* fileName, v_U32_t lineNum) +{ + struct s_vos_mem_struct* memStruct; + v_VOID_t* memPtr = NULL; + v_SIZE_t new_size; + + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + return NULL; + } + + new_size = size + sizeof(struct s_vos_mem_struct) + 8; + + memStruct = (struct s_vos_mem_struct*)kmalloc(new_size,GFP_KERNEL); + + if(memStruct != NULL) + { + VOS_STATUS vosStatus; + + memStruct->fileName = fileName; + memStruct->lineNum = lineNum; + memStruct->size = size; + + vos_mem_copy(&memStruct->header[0], &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER)); + vos_mem_copy( (v_U8_t*)(memStruct + 1) + size, &WLAN_MEM_TAIL[0], sizeof(WLAN_MEM_TAIL)); + + spin_lock(&vosMemList.lock); + vosStatus = hdd_list_insert_front(&vosMemList, &memStruct->pNode); + alloc_trace_usage(fileName, lineNum, size); + spin_unlock(&vosMemList.lock); + if(VOS_STATUS_SUCCESS != vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to insert node into List vosStatus %d", __func__, vosStatus); + } + + memPtr = (v_VOID_t*)(memStruct + 1); + } + + return memPtr; +} + +v_VOID_t vos_mem_dma_free( v_VOID_t *ptr ) +{ + if (ptr != NULL) + { + VOS_STATUS vosStatus; + struct s_vos_mem_struct* memStruct = ((struct s_vos_mem_struct*)ptr) - 1; + + spin_lock(&vosMemList.lock); + vosStatus = hdd_list_remove_node(&vosMemList, &memStruct->pNode); + free_trace_usage(memStruct->fileName, memStruct->lineNum, + memStruct->size); + spin_unlock(&vosMemList.lock); + + if(VOS_STATUS_SUCCESS == vosStatus) + { + if(0 == vos_mem_compare(memStruct->header, &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER)) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Memory Header is corrupted. MemInfo: Filename %s, LineNum %d", + memStruct->fileName, (int)memStruct->lineNum); + } + if(0 == vos_mem_compare( (v_U8_t*)ptr + memStruct->size, &WLAN_MEM_TAIL[0], sizeof(WLAN_MEM_TAIL ) ) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Memory Trailer is corrupted. MemInfo: Filename %s, LineNum %d", + memStruct->fileName, (int)memStruct->lineNum); + } + kfree((v_VOID_t*)memStruct); + } + } +} +#else +v_VOID_t* vos_mem_dma_malloc( v_SIZE_t size ) +{ + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + return NULL; + } + return kmalloc(size, GFP_KERNEL); +} + +/*---------------------------------------------------------------------------- + + \brief vos_mem_dma_free() - vOSS DMA Free Memory + + This function will free special DMA friendly memory pointed to by 'ptr'. + + On WM, there is nothing special about the memory being free'd. SDHC will + take care of free'ing the DMA friendly buffer + + \param ptr - pointer to the starting address of the memory to be + free'd. + + \return Nothing + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_mem_dma_free( v_VOID_t *ptr ) +{ + if (ptr == NULL) + return; + kfree(ptr); +} +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c new file mode 100644 index 000000000000..b585064f39fb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file vos_mq.c + + \brief virtual Operating System Services (vOSS) message queue APIs + + Message Queue Definitions and API + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include "vos_sched.h" +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + + \brief vos_mq_init() - Initialize the vOSS Scheduler + + The \a vos_mq_init() function initializes the Message queue. + + \param pMq - pointer to the message queue + + \return VOS_STATUS_SUCCESS - Message queue was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - Invalid parameter passed to the message + queue initialize function. + + \sa vos_mq_init() + +---------------------------------------------------------------------------*/ +__inline VOS_STATUS vos_mq_init(pVosMqType pMq) +{ + + /* Some quick sanity check*/ + if (pMq == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed",__func__); + return VOS_STATUS_E_FAILURE; + } + + /* + ** Now initialize the lock + */ + spin_lock_init(&pMq->mqLock); + + /* + ** Now initialize the List data structure + */ + INIT_LIST_HEAD(&pMq->mqList); + + return VOS_STATUS_SUCCESS; + +} /* vos_mq_init()*/ + +/*--------------------------------------------------------------------------- + + \brief vos_mq_deinit() - DeInitialize the vOSS Scheduler + + The \a vos_mq_init() function de-initializes the Message queue. + + \param pMq - pointer to the message queue + + \return None + + \sa vos_mq_deinit() + +---------------------------------------------------------------------------*/ +__inline void vos_mq_deinit(pVosMqType pMq) +{ + /* + ** Some quick sanity check + */ + if (pMq == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed",__func__); + return ; + } + + /* we don't have to do anything with the embedded list or spinlock */ + +}/* vos_mq_deinit() */ + + +/*--------------------------------------------------------------------------- + + \brief vos_mq_put() - Add a message to the message queue + + The \a vos_mq_put() function add a message to the Message queue. + + \param pMq - pointer to the message queue + + \param pMsgWrapper - Msg Wrapper containing the message + + \return None + + \sa vos_mq_put() + +---------------------------------------------------------------------------*/ +__inline void vos_mq_put(pVosMqType pMq, pVosMsgWrapper pMsgWrapper) +{ + unsigned long flags; + + /* + ** Some quick sanity check + */ + if ((pMq == NULL) || (pMsgWrapper == NULL)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed",__func__); + return ; + } + + spin_lock_irqsave(&pMq->mqLock, flags); + + list_add_tail(&pMsgWrapper->msgNode, &pMq->mqList); + + spin_unlock_irqrestore(&pMq->mqLock, flags); + +} /* vos_mq_put() */ + + +/*--------------------------------------------------------------------------- + + \brief vos_mq_get() - Get a message with its wrapper from a message queue + + The \a vos_mq_get() function retrieve a message with its wrapper from + the Message queue. + + \param pMq - pointer to the message queue + + \return pointer to the Message Wrapper + + \sa vos_mq_get() + +---------------------------------------------------------------------------*/ +__inline pVosMsgWrapper vos_mq_get(pVosMqType pMq) +{ + pVosMsgWrapper pMsgWrapper = NULL; + + /* + ** Some quick sanity check + */ + struct list_head * listptr; + unsigned long flags; + + if (pMq == NULL) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed",__func__); + return NULL; + } + + spin_lock_irqsave(&pMq->mqLock, flags); + + if( list_empty(&pMq->mqList) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + "%s: VOS Message Queue is empty",__func__); + } + else + { + listptr = pMq->mqList.next; + pMsgWrapper = (pVosMsgWrapper)list_entry(listptr, VosMsgWrapper, msgNode); + list_del(pMq->mqList.next); + } + + spin_unlock_irqrestore(&pMq->mqLock, flags); + + return pMsgWrapper; + +} /* vos_mq_get() */ + + +/*--------------------------------------------------------------------------- + + \brief vos_is_mq_empty() - Return if the MQ is empty + + The \a vos_is_mq_empty() returns true if the queue is empty + + \param pMq - pointer to the message queue + + \return pointer to the Message Wrapper + + \sa vos_mq_get() + +---------------------------------------------------------------------------*/ +__inline v_BOOL_t vos_is_mq_empty(pVosMqType pMq) +{ + v_BOOL_t state = VOS_FALSE; + unsigned long flags; + + /* + ** Some quick sanity check + */ + if (pMq == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed",__func__); + return VOS_STATUS_E_FAILURE; + } + + spin_lock_irqsave(&pMq->mqLock, flags); + state = list_empty(&pMq->mqList)?VOS_TRUE:VOS_FALSE; + spin_unlock_irqrestore(&pMq->mqLock, flags); + + return state; + +} /* vos_mq_get() */ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c new file mode 100644 index 000000000000..f2950a9c20b0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c @@ -0,0 +1,1898 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/*============================================================================ + FILE: vos_nvitem.c + OVERVIEW: This source file contains definitions for vOS NV Item APIs + DEPENDENCIES: NV, remote API client, WinCE REX +============================================================================*/ +/*============================================================================ + EDIT HISTORY FOR MODULE +============================================================================*/ +// the following is used to disable warning for having too many labels in +// the 'nv_items_enum_type' + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "vos_types.h" +#include "aniGlobal.h" +#include "vos_nvitem.h" +#include "vos_trace.h" +#include "vos_api.h" +#include "wlan_hdd_misc.h" +#include "vos_sched.h" +#include "sme_Api.h" +#include "wlan_hdd_main.h" +#include +#include "regdomain.h" +#include "regdomain_common.h" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)) && !defined(WITH_BACKPORTS) +#define IEEE80211_CHAN_NO_80MHZ 1<<7 +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) +#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR +#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR +#endif + +static v_REGDOMAIN_t temp_reg_domain = REGDOMAIN_COUNT; +/* true if init happens thru init time driver hint */ +static v_BOOL_t init_by_driver = VOS_FALSE; +/* true if init happens thru init time callback from regulatory core. + this should be set to true during driver reload */ +static v_BOOL_t init_by_reg_core = VOS_FALSE; + + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define MAX_COUNTRY_COUNT 300 +#define REG_WAIT_TIME 50 +/* + * This is a set of common rules used by our world regulatory domains. + * We have 12 world regulatory domains. To save space we consolidate + * the regulatory domains in 5 structures by frequency and change + * the flags on our reg_notifier() on a case by case basis. + */ + +#define REG_RULE_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + +#define REG_RULE_2467_2472 REG_RULE(2467-10, 2472+10, 40, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN) + +#define REG_RULE_2484 REG_RULE(2484-10, 2484+10, 40, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) + +#define REG_RULE_5180_5320 REG_RULE(5180-10, 5320+10, 80, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + +#define REG_RULE_5500_5720 REG_RULE(5500-10, 5720+10, 80, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + +#define REG_RULE_5745_5925 REG_RULE(5745-10, 5925+10, 80, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + +#define REG_RULE_2GHZ_CH01_11 REG_RULE_2412_2462 + +#define REG_RULE_2GHZ_CH12_13 REG_RULE_2467_2472 + +#define REG_RULE_2GHZ_ALL REG_RULE_2412_2462,\ + REG_RULE_2467_2472,\ + REG_RULE_2484 + +#define REG_RULE_5GHZ_ALL REG_RULE_5180_5320,\ + REG_RULE_5500_5720,\ + REG_RULE_5745_5925 + +#define REG_RULE_5GHZ_NO_MIDBAND REG_RULE_5180_5320,\ + REG_RULE_5745_5925 + + +#define WORLD_SKU_MASK 0x00F0 +#define WORLD_SKU_PREFIX 0x0060 + +static const struct ieee80211_regdomain vos_world_regdom_60_61_62 = { + .n_reg_rules = 6, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2GHZ_ALL, + REG_RULE_5GHZ_ALL, + } +}; + +static const struct ieee80211_regdomain vos_world_regdom_63_65 = { + .n_reg_rules = 4, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2GHZ_CH01_11, + REG_RULE_2GHZ_CH12_13, + REG_RULE_5GHZ_NO_MIDBAND, + } +}; + +static const struct ieee80211_regdomain vos_world_regdom_64 = { + .n_reg_rules = 3, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2GHZ_CH01_11, + REG_RULE_5GHZ_NO_MIDBAND, + } +}; + +static const struct ieee80211_regdomain vos_world_regdom_66_69 = { + .n_reg_rules = 4, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2GHZ_CH01_11, + REG_RULE_5GHZ_ALL, + } +}; + +static const struct ieee80211_regdomain vos_world_regdom_67_68_6A_6C = { + .n_reg_rules = 5, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2GHZ_CH01_11, + REG_RULE_2GHZ_CH12_13, + REG_RULE_5GHZ_ALL, + } +}; + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +// this wrapper structure is identical to nv_cmd_type except the +// data_ptr type is changed void* to avoid exceeding the debug information +// module size as there are too many elements within nv_items_type union + +// structure for code and regulatory domain of a single country +typedef struct +{ + v_U8_t regDomain; + v_COUNTRYCODE_t countryCode; +} CountryInfo_t; +// structure of table to map country code and regulatory domain +typedef struct +{ + v_U16_t countryCount; + CountryInfo_t countryInfo[MAX_COUNTRY_COUNT]; +} CountryInfoTable_t; +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ +// cache of country info table; +// this is re-initialized from data on binary file +// loaded on driver initialization if available + + +static CountryInfoTable_t countryInfoTable = +{ + /* the first entry in the table is always the world domain */ + 138, + { + {REGDOMAIN_WORLD, {'0', '0'}}, // WORLD DOMAIN + {REGDOMAIN_FCC, {'A', 'D'}}, // ANDORRA + {REGDOMAIN_ETSI, {'A', 'E'}}, //UAE + {REGDOMAIN_ETSI, {'A', 'L'}}, //ALBANIA + {REGDOMAIN_ETSI, {'A', 'M'}}, //ARMENIA + {REGDOMAIN_ETSI, {'A', 'N'}}, //NETHERLANDS ANTILLES + {REGDOMAIN_FCC, {'A', 'R'}}, //ARGENTINA + {REGDOMAIN_FCC, {'A', 'S'}}, //AMERICAN SOMOA + {REGDOMAIN_ETSI, {'A', 'T'}}, //AUSTRIA + {REGDOMAIN_FCC, {'A', 'U'}}, //AUSTRALIA + {REGDOMAIN_ETSI , {'A', 'W'}}, //ARUBA + {REGDOMAIN_ETSI, {'A', 'Z'}}, //AZERBAIJAN + {REGDOMAIN_ETSI, {'B', 'A'}}, //BOSNIA AND HERZEGOVINA + {REGDOMAIN_FCC, {'B', 'B'}}, //BARBADOS + {REGDOMAIN_ETSI, {'B', 'D'}}, //BANGLADESH + {REGDOMAIN_ETSI, { 'B', 'E'}}, //BELGIUM + {REGDOMAIN_ETSI, {'B', 'G'}}, //BULGARIA + {REGDOMAIN_ETSI, {'B', 'H'}}, //BAHRAIN + {REGDOMAIN_ETSI, {'B', 'L'}}, // + {REGDOMAIN_FCC, {'B', 'M'}}, //BERMUDA + {REGDOMAIN_ETSI, {'B', 'N'}}, //BRUNEI DARUSSALAM + {REGDOMAIN_ETSI, {'B', 'O'}}, //BOLIVIA + {REGDOMAIN_ETSI, {'B', 'R'}}, //BRAZIL + {REGDOMAIN_FCC, {'B', 'S'}}, //BAHAMAS + {REGDOMAIN_ETSI, {'B', 'Y'}}, //BELARUS + {REGDOMAIN_ETSI, {'B', 'Z'}}, //BELIZE + {REGDOMAIN_FCC, {'C', 'A'}}, //CANADA + {REGDOMAIN_ETSI, {'C', 'H'}}, //SWITZERLAND + {REGDOMAIN_ETSI, {'C', 'L'}}, //CHILE + {REGDOMAIN_FCC, {'C', 'N'}}, //CHINA + {REGDOMAIN_FCC, {'C', 'O'}}, //COLOMBIA + {REGDOMAIN_ETSI, {'C', 'R'}}, //COSTA RICA + {REGDOMAIN_ETSI, {'C', 'S'}}, + {REGDOMAIN_ETSI, {'C', 'Y'}}, //CYPRUS + {REGDOMAIN_ETSI, {'C', 'Z'}}, //CZECH REPUBLIC + {REGDOMAIN_ETSI, {'D', 'E'}}, //GERMANY + {REGDOMAIN_ETSI, {'D', 'K'}}, //DENMARK + {REGDOMAIN_FCC, {'D', 'O'}}, //DOMINICAN REPUBLIC + {REGDOMAIN_ETSI, {'D', 'Z'}}, //ALGERIA + {REGDOMAIN_ETSI, {'E', 'C'}}, //ECUADOR + {REGDOMAIN_ETSI, {'E', 'E'}}, //ESTONIA + {REGDOMAIN_ETSI, {'E', 'G'}}, //EGYPT + {REGDOMAIN_ETSI, {'E', 'S'}}, //SPAIN + {REGDOMAIN_ETSI, {'F', 'I'}}, //FINLAND + {REGDOMAIN_ETSI, {'F', 'R'}}, //FRANCE + {REGDOMAIN_ETSI, {'G', 'B'}}, //UNITED KINGDOM + {REGDOMAIN_FCC, {'G', 'D'}}, //GRENADA + {REGDOMAIN_ETSI, {'G', 'E'}}, //GEORGIA + {REGDOMAIN_ETSI, {'G', 'F'}}, //FRENCH GUIANA + {REGDOMAIN_ETSI, {'G', 'L'}}, //GREENLAND + {REGDOMAIN_ETSI, {'G', 'P'}}, //GUADELOUPE + {REGDOMAIN_ETSI, {'G', 'R'}}, //GREECE + {REGDOMAIN_FCC, {'G', 'T'}}, //GUATEMALA + {REGDOMAIN_FCC, {'G', 'U'}}, //GUAM + {REGDOMAIN_ETSI, {'H', 'U'}}, //HUNGARY + {REGDOMAIN_FCC, {'I', 'D'}}, //INDONESIA + {REGDOMAIN_ETSI, {'I', 'E'}}, //IRELAND + {REGDOMAIN_ETSI, {'I', 'L'}}, //ISRAEL + {REGDOMAIN_ETSI, {'I', 'N'}}, //INDIA + {REGDOMAIN_ETSI, {'I', 'R'}}, //IRAN, ISLAMIC REPUBLIC OF + {REGDOMAIN_ETSI, {'I', 'S'}}, //ICELNAD + {REGDOMAIN_ETSI, {'I', 'T'}}, //ITALY + {REGDOMAIN_FCC, {'J', 'M'}}, //JAMAICA + {REGDOMAIN_JAPAN, {'J', 'P'}}, //JAPAN + {REGDOMAIN_ETSI, {'J', 'O'}}, //JORDAN + {REGDOMAIN_ETSI, {'K', 'E'}}, //KENYA + {REGDOMAIN_ETSI, {'K', 'H'}}, //CAMBODIA + {REGDOMAIN_ETSI, {'K', 'P'}}, //KOREA, DEMOCRATIC PEOPLE's REPUBLIC OF + {REGDOMAIN_ETSI, {'K', 'R'}}, //KOREA, REPUBLIC OF + {REGDOMAIN_ETSI, {'K', 'W'}}, //KUWAIT + {REGDOMAIN_ETSI, {'K', 'Z'}}, //KAZAKHSTAN + {REGDOMAIN_ETSI, {'L', 'B'}}, //LEBANON + {REGDOMAIN_ETSI, {'L', 'I'}}, //LIECHTENSTEIN + {REGDOMAIN_ETSI, {'L', 'K'}}, //SRI-LANKA + {REGDOMAIN_ETSI, {'L', 'T'}}, //LITHUANIA + {REGDOMAIN_ETSI, {'L', 'U'}}, //LUXEMBOURG + {REGDOMAIN_ETSI, {'L','V'}}, //LATVIA + {REGDOMAIN_ETSI, {'M', 'A'}}, //MOROCCO + {REGDOMAIN_ETSI, {'M', 'C'}}, //MONACO + {REGDOMAIN_ETSI, {'M', 'K'}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF + {REGDOMAIN_FCC, {'M','N'}}, //MONGOLIA + {REGDOMAIN_FCC, {'M', 'O'}}, //MACAO + {REGDOMAIN_FCC, {'M', 'P'}}, //NORTHERN MARIANA ISLANDS + {REGDOMAIN_ETSI, {'M', 'Q'}}, //MARTINIQUE + {REGDOMAIN_FCC, {'M', 'T'}}, //MALTA + {REGDOMAIN_ETSI, {'M', 'U'}}, //MAURITIUS + {REGDOMAIN_ETSI, {'M', 'W'}}, //MALAWI + {REGDOMAIN_FCC, {'M', 'X'}}, //MEXICO + {REGDOMAIN_ETSI, {'M', 'Y'}}, //MALAYSIA + {REGDOMAIN_ETSI, {'N', 'G'}}, //NIGERIA + {REGDOMAIN_FCC, {'N', 'I'}}, //NICARAGUA + {REGDOMAIN_ETSI, {'N', 'L'}}, //NETHERLANDS + {REGDOMAIN_ETSI, {'N', 'O'}}, //NORWAY + {REGDOMAIN_ETSI, {'N', 'P'}}, //NEPAL + {REGDOMAIN_FCC, {'N', 'Z'}}, //NEW-ZEALAND + {REGDOMAIN_FCC, {'O', 'M'}}, //OMAN + {REGDOMAIN_FCC, {'P', 'A'}}, //PANAMA + {REGDOMAIN_ETSI, {'P', 'E'}}, //PERU + {REGDOMAIN_ETSI, {'P', 'F'}}, //FRENCH POLYNESIA + {REGDOMAIN_ETSI, {'P', 'G'}}, //PAPUA NEW GUINEA + {REGDOMAIN_FCC, {'P', 'H'}}, //PHILIPPINES + {REGDOMAIN_ETSI, {'P', 'K'}}, //PAKISTAN + {REGDOMAIN_ETSI, {'P', 'L'}}, //POLAND + {REGDOMAIN_FCC, {'P', 'R'}}, //PUERTO RICO + {REGDOMAIN_FCC, {'P', 'S'}}, //PALESTINIAN TERRITORY, OCCUPIED + {REGDOMAIN_ETSI, {'P', 'T'}}, //PORTUGAL + {REGDOMAIN_FCC, {'P', 'Y'}}, //PARAGUAY + {REGDOMAIN_ETSI, {'Q', 'A'}}, //QATAR + {REGDOMAIN_ETSI, {'R', 'E'}}, //REUNION + {REGDOMAIN_ETSI, {'R', 'O'}}, //ROMAINIA + {REGDOMAIN_ETSI, {'R', 'S'}}, //SERBIA + {REGDOMAIN_ETSI, {'R', 'U'}}, //RUSSIA + {REGDOMAIN_FCC, {'R', 'W'}}, //RWANDA + {REGDOMAIN_ETSI, {'S', 'A'}}, //SAUDI ARABIA + {REGDOMAIN_ETSI, {'S', 'E'}}, //SWEDEN + {REGDOMAIN_ETSI, {'S', 'G'}}, //SINGAPORE + {REGDOMAIN_ETSI, {'S', 'I'}}, //SLOVENNIA + {REGDOMAIN_ETSI, {'S', 'K'}}, //SLOVAKIA + {REGDOMAIN_ETSI, {'S', 'V'}}, //EL SALVADOR + {REGDOMAIN_ETSI, {'S', 'Y'}}, //SYRIAN ARAB REPUBLIC + {REGDOMAIN_ETSI, {'T', 'H'}}, //THAILAND + {REGDOMAIN_ETSI, {'T', 'N'}}, //TUNISIA + {REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY + {REGDOMAIN_ETSI, {'T', 'T'}}, //TRINIDAD AND TOBAGO + {REGDOMAIN_FCC, {'T', 'W'}}, //TAIWAN, PRIVINCE OF CHINA + {REGDOMAIN_FCC, {'T', 'Z'}}, //TANZANIA, UNITED REPUBLIC OF + {REGDOMAIN_ETSI, {'U', 'A'}}, //UKRAINE + {REGDOMAIN_ETSI, {'U', 'G'}}, //UGANDA + {REGDOMAIN_FCC, {'U', 'S'}}, //USA + {REGDOMAIN_ETSI, {'U', 'Y'}}, //URUGUAY + {REGDOMAIN_FCC, {'U', 'Z'}}, //UZBEKISTAN + {REGDOMAIN_ETSI, {'V', 'E'}}, //VENEZUELA + {REGDOMAIN_FCC, {'V', 'I'}}, //VIRGIN ISLANDS, US + {REGDOMAIN_ETSI, {'V', 'N'}}, //VIETNAM + {REGDOMAIN_ETSI, {'Y', 'E'}}, //YEMEN + {REGDOMAIN_ETSI, {'Y', 'T'}}, //MAYOTTE + {REGDOMAIN_ETSI, {'Z', 'A'}}, //SOUTH AFRICA + {REGDOMAIN_ETSI, {'Z', 'W'}}, //ZIMBABWE + } +}; + +typedef struct nvEFSTable_s +{ + sHalNv halnv; +} nvEFSTable_t; + +static nvEFSTable_t *pnvEFSTable; + +const tRfChannelProps rfChannels[NUM_RF_CHANNELS] = +{ + //RF_SUBBAND_2_4_GHZ + //freq, chan#, band + { 2412, 1 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_1, + { 2417, 2 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_2, + { 2422, 3 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_3, + { 2427, 4 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_4, + { 2432, 5 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_5, + { 2437, 6 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_6, + { 2442, 7 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_7, + { 2447, 8 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_8, + { 2452, 9 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_9, + { 2457, 10 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_10, + { 2462, 11 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_11, + { 2467, 12 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_12, + { 2472, 13 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_13, + { 2484, 14 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_14, + { 4920, 240, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_240, + { 4940, 244, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_244, + { 4960, 248, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_248, + { 4980, 252, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_252, + { 5040, 208, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_208, + { 5060, 212, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_212, + { 5080, 216, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_216, + { 5180, 36 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_36, + { 5200, 40 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_40, + { 5220, 44 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_44, + { 5240, 48 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_48, + { 5260, 52 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_52, + { 5280, 56 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_56, + { 5300, 60 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_60, + { 5320, 64 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_64, + { 5500, 100, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_100, + { 5520, 104, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_104, + { 5540, 108, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_108, + { 5560, 112, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_112, + { 5580, 116, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_116, + { 5600, 120, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_120, + { 5620, 124, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_124, + { 5640, 128, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_128, + { 5660, 132, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_132, + { 5680, 136, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_136, + { 5700, 140, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_140, +#ifdef FEATURE_WLAN_CH144 + { 5720, 144, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_144, +#endif /* FEATURE_WLAN_CH144 */ + { 5745, 149, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_149, + { 5765, 153, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_153, + { 5785, 157, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_157, + { 5805, 161, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_161, + { 5825, 165, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_165, + + /* 5.9GHz 10 MHz bandwidth (802.11p) */ + { 5852, 170, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_170, + { 5855, 171, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_171, + { 5860, 172, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_172, + { 5865, 173, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_173, + { 5870, 174, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_174, + { 5875, 175, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_175, + { 5880, 176, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_176, + { 5885, 177, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_177, + { 5890, 178, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_178, + { 5895, 179, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_179, + { 5900, 180, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_180, + { 5905, 181, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_181, + { 5910, 182, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_182, + { 5915, 183, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_183, + { 5920, 184, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_184, + + { 2422, 3 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_3, + { 2427, 4 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_4, + { 2432, 5 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_5, + { 2437, 6 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_6, + { 2442, 7 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_7, + { 2447, 8 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_8, + { 2452, 9 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_9, + { 2457, 10 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_10, + { 2462, 11 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_11, + { 4930, 242, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_242, + { 4950, 246, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_246, + { 4970, 250, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_250, + { 5050, 210, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_210, + { 5070, 214, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_214, + { 5190, 38 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_38, + { 5210, 42 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_42, + { 5230, 46 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_46, + { 5250, 50 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_50, + { 5270, 54 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_54, + { 5290, 58 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_58, + { 5310, 62 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_62, + { 5510, 102, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_102, + { 5530, 106, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_106, + { 5550, 110, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_110, + { 5570, 114, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_114, + { 5590, 118, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_118, + { 5610, 122, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_122, + { 5630, 126, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_126, + { 5650, 130, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_130, + { 5670, 134, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_134, + { 5690, 138, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_138, +#ifdef FEATURE_WLAN_CH144 + { 5710, 142, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_142, +#endif /* FEATURE_WLAN_CH144 */ + { 5755, 151, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_151, + { 5775, 155, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_155, + { 5795, 159, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_159, + { 5815, 163, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_163, +}; + +extern const sHalNv nvDefaults; + +const sRegulatoryChannel * regChannels = nvDefaults.tables.regDomains[0].channels; + +static inline bool is_wwr_sku(u16 regd) +{ + return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && + (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || + (regd == WORLD)); +} + +bool is_world_regd(u_int32_t regd) +{ + return is_wwr_sku(regd & ~WORLDWIDE_ROAMING_FLAG); +} + +static const struct ieee80211_regdomain *vos_default_world_regdomain(void) +{ + /* this is the most restrictive */ + return &vos_world_regdom_64; +} + +static const struct ieee80211_regdomain *vos_custom_world_regdomain(void) +{ + /* this is the most restrictive */ + return &vos_world_regdom_60_61_62; +} + +/** + * voss_DomainIdtoString(): converts Reg domain enum to string. + * @domainIdCurrent: Reg domain enum value. + */ +const char * voss_DomainIdtoString(v_U8_t domainIdCurrent) +{ + switch (domainIdCurrent) + { + CASE_RETURN_STRING( REGDOMAIN_FCC ); + CASE_RETURN_STRING( REGDOMAIN_ETSI ); + CASE_RETURN_STRING( REGDOMAIN_JAPAN ); + CASE_RETURN_STRING( REGDOMAIN_WORLD ); + CASE_RETURN_STRING( REGDOMAIN_N_AMER_EXC_FCC ); + CASE_RETURN_STRING( REGDOMAIN_APAC ); + CASE_RETURN_STRING( REGDOMAIN_KOREA ); + CASE_RETURN_STRING( REGDOMAIN_HI_5GHZ ); + CASE_RETURN_STRING( REGDOMAIN_NO_5GHZ ); + CASE_RETURN_STRING( REGDOMAIN_COUNT ); + default: + return "Regulation Domain Unknown"; + } +} + +static const +struct ieee80211_regdomain *vos_world_regdomain(struct regulatory *reg) +{ + REG_DMN_PAIR_MAPPING *regpair; + regpair = (REG_DMN_PAIR_MAPPING *)reg->regpair; + switch (regpair->regDmnEnum) { + case 0x60: + case 0x61: + case 0x62: + return &vos_world_regdom_60_61_62; + case 0x63: + case 0x65: + return &vos_world_regdom_63_65; + case 0x64: + return &vos_world_regdom_64; + case 0x66: + case 0x69: + return &vos_world_regdom_66_69; + case 0x67: + case 0x68: + case 0x6A: + case 0x6C: + return &vos_world_regdom_67_68_6A_6C; + default: + WARN_ON(1); + return vos_default_world_regdomain(); + } +} + + +static int regd_init_wiphy(hdd_context_t *pHddCtx, struct regulatory *reg, + struct wiphy *wiphy) +{ + const struct ieee80211_regdomain *regd; + + if (is_world_regd(reg->reg_domain)) { + regd = vos_world_regdomain(reg); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +#else + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#endif + } else if (pHddCtx->cfg_ini->fRegChangeDefCountry) { + regd = vos_custom_world_regdomain(); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +#else + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#endif + + } else { + regd = vos_default_world_regdomain(); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_STRICT_REG; +#else + wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; +#endif + } + + /* + * save the original driver regulatory flags + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + pHddCtx->reg.reg_flags = wiphy->regulatory_flags; +#else + pHddCtx->reg.reg_flags = wiphy->flags; +#endif + + wiphy_apply_custom_regulatory(wiphy, regd); + + /* + * restore the driver regulatory flags since + * wiphy_apply_custom_regulatory may have + * changed them + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags = pHddCtx->reg.reg_flags; +#else + wiphy->flags = pHddCtx->reg.reg_flags; +#endif + + return 0; +} + +static int reg_init_from_eeprom(hdd_context_t *pHddCtx, struct regulatory *reg, + struct wiphy *wiphy) +{ + int ret_val = 0; + + ret_val = regdmn_get_country_alpha2(reg); + if (ret_val) { + adf_os_print(KERN_ERR "Error in getting country code\n"); + return ret_val; + } + + reg->cc_src = COUNTRY_CODE_SET_BY_DRIVER; + + /* update default country code */ + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0] = + reg->alpha2[0]; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1] = + reg->alpha2[1]; + + regd_init_wiphy(pHddCtx, reg, wiphy); + + return ret_val; +} + +static void vos_update_reg_info(hdd_context_t *pHddCtx) +{ + u_int32_t country_code; + country_code = regdmn_find_ctry_by_name(pHddCtx->reg.alpha2); + pHddCtx->reg.reg_domain = COUNTRY_ERD_FLAG; + pHddCtx->reg.reg_domain |= country_code; + regdmn_get_country_alpha2(&pHddCtx->reg); + return; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_open() - Open NV operation + Read NV bin file and prepare NV common structure + \return VOS_STATUS_SUCCESS - module is initialized successfully + otherwise - module is not initialized + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_open(void) +{ + /* Allocate memory to global NV table */ + pnvEFSTable = (nvEFSTable_t *)vos_mem_malloc(sizeof(nvEFSTable_t)); + if ( NULL == pnvEFSTable ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s : failed to allocate memory for NV", __func__); + return VOS_STATUS_E_NOMEM; + } + + /*Copying the NV defaults */ + vos_mem_copy(&(pnvEFSTable->halnv), &nvDefaults, sizeof(sHalNv)); + + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_nv_close(void) +{ + vos_mem_free(pnvEFSTable); + pnvEFSTable=NULL; + return VOS_STATUS_SUCCESS; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_getSupportedCountryCode() - get the list of supported + country codes + The \a vos_nv_getSupportedCountryCode() encodes the list of supported + country codes with paddings in the provided buffer + \param pBuffer - pointer to buffer where supported country codes + and paddings are encoded; this may be set to NULL + if user wishes to query the required buffer size to + get the country code list + \param pBufferSize - this is the provided buffer size on input; + this is the required or consumed buffer size on output + \return VOS_STATUS_SUCCESS - country codes are successfully encoded + VOS_STATUS_E_NOMEM - country codes are not encoded because either + the buffer is NULL or buffer size is + sufficient + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getSupportedCountryCode( v_BYTE_t *pBuffer, v_SIZE_t *pBufferSize, + v_SIZE_t paddingSize ) +{ + v_SIZE_t providedBufferSize = *pBufferSize; + int i; + // pBufferSize now points to the required buffer size + *pBufferSize = countryInfoTable.countryCount * (VOS_COUNTRY_CODE_LEN + paddingSize ); + if ( NULL == pBuffer || providedBufferSize < *pBufferSize ) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + ("Insufficient memory for country code list")); + return VOS_STATUS_E_NOMEM; + } + for (i = 0; i < countryInfoTable.countryCount; i++) { + vos_mem_copy(pBuffer, countryInfoTable.countryInfo[i].countryCode, + VOS_COUNTRY_CODE_LEN); + pBuffer += (VOS_COUNTRY_CODE_LEN + paddingSize ); + } + return VOS_STATUS_SUCCESS; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_getChannelListWithPower() - function to return the list of + supported channels with the power limit info too. + \param pChannels20MHz - list of 20 Mhz channels + \param pNum20MHzChannelsFound - number of 20 Mhz channels + \param pChannels40MHz - list of 20 Mhz channels + \param pNum40MHzChannelsFound - number of 20 Mhz channels + \return status of the NV read operation + \Note: 40Mhz not currently supported + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getChannelListWithPower(tChannelListWithPower *channels20MHz /*[NUM_LEGIT_RF_CHANNELS] */, + tANI_U8 *num20MHzChannelsFound, + tChannelListWithPower *channels40MHz /*[NUM_CHAN_BOND_CHANNELS] */, + tANI_U8 *num40MHzChannelsFound + ) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + int i, count; + + //TODO: Dont want to use pMac here...can we instead store the curRegDomain in NV + // or pass it as a parameter to NV from SME? + + if( channels20MHz && num20MHzChannelsFound ) + { + count = 0; + for( i = 0; i <= RF_CHAN_14; i++ ) + { + if( regChannels[i].enabled ) + { + channels20MHz[count].chanId = rfChannels[i].channelNum; + channels20MHz[count++].pwr = regChannels[i].pwrLimit; + } + } + for( i = RF_CHAN_36; i <= RF_CHAN_184; i++ ) + { + if( regChannels[i].enabled ) + { + channels20MHz[count].chanId = rfChannels[i].channelNum; + channels20MHz[count++].pwr = regChannels[i].pwrLimit; + } + } + *num20MHzChannelsFound = (tANI_U8)count; + } + + if( channels40MHz && num40MHzChannelsFound ) + { + count = 0; + //center channels for 2.4 Ghz 40 MHz channels + for( i = RF_CHAN_BOND_3; i <= RF_CHAN_BOND_11; i++ ) + { + + if( regChannels[i].enabled ) + { + channels40MHz[count].chanId = rfChannels[i].channelNum; + channels40MHz[count++].pwr = regChannels[i].pwrLimit; + } + } + //center channels for 5 Ghz 40 MHz channels + for( i = RF_CHAN_BOND_38; i <= RF_CHAN_BOND_163; i++ ) + { + + if( regChannels[i].enabled ) + { + channels40MHz[count].chanId = rfChannels[i].channelNum; + channels40MHz[count++].pwr = regChannels[i].pwrLimit; + } + } + *num40MHzChannelsFound = (tANI_U8)count; + } + return (status); +} + +/**------------------------------------------------------------------------ + \brief vos_nv_getDefaultRegDomain() - return the default regulatory domain + \return default regulatory domain + \sa + -------------------------------------------------------------------------*/ + +v_REGDOMAIN_t vos_nv_getDefaultRegDomain( void ) +{ + return countryInfoTable.countryInfo[0].regDomain; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_getSupportedChannels() - function to return the list of + supported channels + \param p20MhzChannels - list of 20 Mhz channels + \param pNum20MhzChannels - number of 20 Mhz channels + \param p40MhzChannels - list of 40 Mhz channels + \param pNum40MhzChannels - number of 40 Mhz channels + \return status of the NV read operation + \Note: 40Mhz not currently supported + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getSupportedChannels( v_U8_t *p20MhzChannels, int *pNum20MhzChannels, + v_U8_t *p40MhzChannels, int *pNum40MhzChannels) +{ + VOS_STATUS status = VOS_STATUS_E_INVAL; + int i, count = 0; + + if( p20MhzChannels && pNum20MhzChannels ) + { + if( *pNum20MhzChannels >= NUM_RF_CHANNELS ) + { + for( i = 0; i <= RF_CHAN_14; i++ ) + { + p20MhzChannels[count++] = rfChannels[i].channelNum; + } + for( i = RF_CHAN_36; i <= RF_CHAN_184; i++ ) + { + p20MhzChannels[count++] = rfChannels[i].channelNum; + } + status = VOS_STATUS_SUCCESS; + } + *pNum20MhzChannels = count; + } + + return (status); +} + +/**------------------------------------------------------------------------ + \brief vos_nv_readDefaultCountryTable() - return the default Country table + \param table data - a union to return the default country table data in. + \return status of the NV read operation + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_readDefaultCountryTable( uNvTables *tableData ) +{ + + VOS_STATUS status = VOS_STATUS_SUCCESS; + vos_mem_copy(&tableData->defaultCountryTable, + &pnvEFSTable->halnv.tables.defaultCountryTable, + sizeof(sDefaultCountry)); + pr_info("DefaultCountry is %c%c\n", + tableData->defaultCountryTable.countryCode[0], + tableData->defaultCountryTable.countryCode[1]); + return status; +} + +/** + * vos_nv_skip_dfs_and_2g() - skip dfs and 2g band channels + * @rf_channel: input channel enum to know, whether to skip or add the channel + * + * Return: true or false + */ +uint8_t vos_nv_skip_dfs_and_2g(uint32_t rf_channel) +{ + uint32_t channel_loop; + eRfChannels channel_enum = INVALID_RF_CHANNEL; + uint8_t ret = false; + + for (channel_loop = RF_CHAN_36; + channel_loop <= RF_CHAN_184; channel_loop++) { + if (rfChannels[channel_loop].channelNum == rf_channel) { + channel_enum = (eRfChannels)channel_loop; + break; + } + } + + if (INVALID_RF_CHANNEL == channel_enum) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + FL("Invalid channel %d"), rf_channel); + ret = true; + goto exit_ok; + } + + if (NV_CHANNEL_DFS == regChannels[channel_enum].enabled) + ret = true; +exit_ok: + return ret; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_getChannelEnabledState - + \param rfChannel - input channel enum to know evabled state + \return eNVChannelEnabledType enabled state for channel + * enabled + * disabled + * DFS + \sa + -------------------------------------------------------------------------*/ +eNVChannelEnabledType vos_nv_getChannelEnabledState +( + v_U32_t rfChannel +) +{ + v_U32_t channelLoop; + eRfChannels channelEnum = INVALID_RF_CHANNEL; + + for(channelLoop = 0; channelLoop <= RF_CHAN_184; channelLoop++) + { + if(rfChannels[channelLoop].channelNum == rfChannel) + { + channelEnum = (eRfChannels)channelLoop; + break; + } + } + + if(INVALID_RF_CHANNEL == channelEnum) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "vos_nv_getChannelEnabledState, invalid channel %d", rfChannel); + return NV_CHANNEL_INVALID; + } + + return regChannels[channelEnum].enabled; +} + +/****************************************************************** + Add CRDA regulatory support +*******************************************************************/ + +static int bw20_ch_index_to_bw40_ch_index(int k) +{ + int m = -1; + if (k >= RF_CHAN_1 && k <= RF_CHAN_13) + { + /* + * Channel bonding not valid for channel 14, + * So dont consider it + */ + m = k - RF_CHAN_1 + RF_CHAN_BOND_3 ; + if (m > RF_CHAN_BOND_11) + m = RF_CHAN_BOND_11; + } + else if (k >= RF_CHAN_240 && k <= RF_CHAN_216) + { + m = k - RF_CHAN_240 + RF_CHAN_BOND_242 ; + if (m > RF_CHAN_BOND_214) + m = RF_CHAN_BOND_214; + } + else if (k >= RF_CHAN_36 && k <= RF_CHAN_64) + { + m = k - RF_CHAN_36 + RF_CHAN_BOND_38; + if (m > RF_CHAN_BOND_62) + m = RF_CHAN_BOND_62; + } +#ifdef FEATURE_WLAN_CH144 + else if (k >= RF_CHAN_100 && k <= RF_CHAN_144) +#else + else if (k >= RF_CHAN_100 && k <= RF_CHAN_140) +#endif /* FEATURE_WLAN_CH144 */ + { + m = k - RF_CHAN_100 + RF_CHAN_BOND_102; +#ifdef FEATURE_WLAN_CH144 + if (m > RF_CHAN_BOND_142) + m = RF_CHAN_BOND_142; +#else + if (m > RF_CHAN_BOND_138) + m = RF_CHAN_BOND_138; +#endif /* FEATURE_WLAN_CH144 */ + } + else if (k >= RF_CHAN_149 && k <= RF_CHAN_165) + { + m = k - RF_CHAN_149 + RF_CHAN_BOND_151; + if (m > RF_CHAN_BOND_163) + m = RF_CHAN_BOND_163; + } + return m; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_setRegDomain - + \param clientCtxt - Client Context, Not used for PRIMA + regId - Regulatory Domain ID + sendRegHint - send hint to nl80211 + \return status set REG domain operation + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, + v_BOOL_t sendRegHint) +{ + + if (regId >= REGDOMAIN_COUNT) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "VOS set reg domain, invalid REG domain ID %d", regId); + return VOS_STATUS_E_INVAL; + } + + /* Set correct channel information based on REG Domain */ + regChannels = pnvEFSTable->halnv.tables.regDomains[regId].channels; + + return VOS_STATUS_SUCCESS; +} + +/* vos_nv_set_dfs_region() - set the dfs_region + * + * @dfs_region: the dfs_region to set + * + * Return: VOS_STATUS_SUCCESS if dfs_region set correctly + * VOS_STATUS_E_EXISTS if vos_context not found + */ +VOS_STATUS vos_nv_set_dfs_region(uint8_t dfs_region) +{ + v_CONTEXT_t vos_ctx_ptr = NULL; + hdd_context_t *hdd_ctx_ptr= NULL; + + vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL == vos_ctx_ptr) + return VOS_STATUS_E_EXISTS; + + hdd_ctx_ptr = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx_ptr); + + if (NULL == hdd_ctx_ptr) + return VOS_STATUS_E_EXISTS; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) + + hdd_ctx_ptr->reg.dfs_region = dfs_region; + +#else + + /* remap the ctl code to dfs region code */ + switch(hdd_ctx_ptr->reg.ctl_5g) { + case FCC: + hdd_ctx_ptr->reg.dfs_region = DFS_FCC_DOMAIN; + break; + case ETSI: + hdd_ctx_ptr->reg.dfs_region = DFS_ETSI_DOMAIN; + break; + case MKK: + hdd_ctx_ptr->reg.dfs_region = DFS_MKK4_DOMAIN; + break; + default: + /* set default dfs_region to FCC */ + hdd_ctx_ptr->reg.dfs_region = DFS_FCC_DOMAIN; + break; + } +#endif + return VOS_STATUS_SUCCESS; +} + +/* vos_nv_get_dfs_region() - get the dfs_region + * + * @dfs_region: the dfs_region to return + * + * Return: VOS_STATUS_SUCCESS if dfs_region set correctly + * VOS_STATUS_E_EXISTS if vos_context not found + */ +VOS_STATUS vos_nv_get_dfs_region(uint8_t *dfs_region) +{ + v_CONTEXT_t vos_ctx_ptr = NULL; + hdd_context_t *hdd_ctx_ptr = NULL; + + vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL == vos_ctx_ptr) + return VOS_STATUS_E_EXISTS; + + hdd_ctx_ptr = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx_ptr); + + if (NULL == hdd_ctx_ptr) + return VOS_STATUS_E_EXISTS; + + *dfs_region = hdd_ctx_ptr->reg.dfs_region; + + return VOS_STATUS_SUCCESS; +} + +/**------------------------------------------------------------------------ + \brief vos_nv_getRegDomainFromCountryCode() - get the regulatory domain of + a country given its country code + The \a vos_nv_getRegDomainFromCountryCode() returns the regulatory domain of + a country given its country code. This is done from reading a cached + copy of the binary file. + \param pRegDomain - pointer to regulatory domain + \param countryCode - country code + \param source - source of the country code + \return VOS_STATUS_SUCCESS - regulatory domain is found for the given country + VOS_STATUS_E_FAULT - invalid pointer error + VOS_STATUS_E_EMPTY - country code table is empty + VOS_STATUS_E_EXISTS - given country code does not exist in table + \sa + -------------------------------------------------------------------------*/ +VOS_STATUS vos_nv_getRegDomainFromCountryCode( v_REGDOMAIN_t *pRegDomain, + const v_COUNTRYCODE_t country_code, v_CountryInfoSource_t source) +{ + + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + struct wiphy *wiphy = NULL; + int i; + + /* sanity checks */ + if (NULL == pRegDomain) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid reg domain pointer") ); + return VOS_STATUS_E_FAULT; + } + + *pRegDomain = REGDOMAIN_COUNT; + + if (NULL == country_code) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Country code array is NULL")); + return VOS_STATUS_E_FAULT; + } + + if (0 == countryInfoTable.countryCount) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Reg domain table is empty") ); + return VOS_STATUS_E_EMPTY; + } + + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL != pVosContext) + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + else + return VOS_STATUS_E_EXISTS; + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer") ); + return VOS_STATUS_E_FAULT; + } + + if (pHddCtx->isLogpInProgress) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + (" SSR in progress, return") ); + *pRegDomain = temp_reg_domain; + return VOS_STATUS_SUCCESS; + } + + wiphy = pHddCtx->wiphy; + + if (false == wiphy->registered) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("wiphy is not yet registered with the kernel") ); + return VOS_STATUS_E_FAULT; + } + + temp_reg_domain = REGDOMAIN_COUNT; + /* lookup the country in the local database */ + for (i = 0; i < countryInfoTable.countryCount && + REGDOMAIN_COUNT == temp_reg_domain; i++) + { + if (memcmp(country_code, countryInfoTable.countryInfo[i].countryCode, + VOS_COUNTRY_CODE_LEN) == 0) + { + /* country code is found */ + /* record the temporary regulatory_domain as well */ + temp_reg_domain = countryInfoTable.countryInfo[i].regDomain; + break; + } + } + + if (REGDOMAIN_COUNT == temp_reg_domain) { + + /* the country was not found in the driver database */ + /* so we will return the REGDOMAIN_WORLD to SME/CSR */ + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Country does not map to any Regulatory domain")); + + temp_reg_domain = REGDOMAIN_WORLD; + } + + if (COUNTRY_QUERY == source) { + *pRegDomain = temp_reg_domain; + return VOS_STATUS_SUCCESS; + } + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + ("regdomain request")); + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN, + (" get country information from kernel db")); + + if ((COUNTRY_INIT == source) && (VOS_FALSE == init_by_reg_core)) { + init_by_driver = VOS_TRUE; + + if (('0' != country_code[0]) || ('0' != country_code[1])) { + INIT_COMPLETION(pHddCtx->reg_init); + regulatory_hint(wiphy, country_code); + wait_for_completion_timeout(&pHddCtx->reg_init, + msecs_to_jiffies(REG_WAIT_TIME)); + } + + } else if (COUNTRY_IE == source || COUNTRY_USER == source) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + regulatory_hint_user(country_code, NL80211_USER_REG_HINT_USER); +#else + regulatory_hint_user(country_code); +#endif + } + + *pRegDomain = temp_reg_domain; + return VOS_STATUS_SUCCESS; +} + +#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS +#define DEFAULT_11P_POWER (30) +#endif + +/* vos_is_dsrc_channel() - is the channel DSRC + * + * @center_freq: center freq of the channel + * + * Return: true if dsrc channel + * false otherwise + */ +bool vos_is_dsrc_channel(uint16_t center_freq) +{ + switch (center_freq) { + case 5852: + case 5860: + case 5870: + case 5880: + case 5890: + case 5900: + case 5910: + case 5920: + case 5875: + case 5905: + return 1; + } + return 0; +} + + +/* create_linux_regulatory_entry to populate internal structures from wiphy */ +static int create_linux_regulatory_entry(struct wiphy *wiphy, + v_U8_t nBandCapability, + bool reset) +{ + int i, j, m; + int k = 0, n = 0; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)) && !defined(WITH_BACKPORTS) + int err; +#endif + const struct ieee80211_reg_rule *reg_rule; + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL != pVosContext) + { + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer") ); + } + else + { + pHddCtx->isVHT80Allowed = 0; + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pVosContext pointer") ); + } + + /* 20MHz channels */ + if (nBandCapability == eCSR_BAND_24) + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "BandCapability is set to 2G only"); + + for (i = 0, m = 0; ibands[i] == NULL) + continue; + + /* internal channels[] is one continous array for both 2G and 5G bands + m is internal starting channel index for each band */ + + if (i == 0) + m = 0; + else + m = wiphy->bands[i-1]->n_channels + m; + + if (pnvEFSTable == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "error: pnvEFSTable is NULL, probably not parsed nv.bin yet"); + return -1; + } + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + /* k = (m + j) is internal current channel index for 20MHz channel + n is internal channel index for corresponding 40MHz channel */ + + k = m + j; + n = bw20_ch_index_to_bw40_ch_index(k); + + /* If the regulatory rules for a country do not explicilty + * require a passive scan on a frequency, lift the passive + * scan restriction + * When getting the regulatory rule, specify the smallest bandwidth. + * That's 5 MHz. A larger bandwidth may not fit into the frequency range. */ + + if ((!reset) && +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) { +#else + (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) { +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(wiphy->bands[i]-> + channels[j].center_freq)); +#else + err = freq_reg_info(wiphy, MHZ_TO_KHZ(wiphy->bands[i]-> + channels[j].center_freq), + 0, ®_rule); +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + if (!IS_ERR(reg_rule)) { +#else + if (0 == err) { +#endif + wiphy->bands[i]->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + + if (!(reg_rule->flags & NL80211_RRF_DFS)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Remove passive scan restriction for %u", + __func__, wiphy->bands[i]->channels[j].center_freq); + wiphy->bands[i]->channels[j].flags &= ~IEEE80211_CHAN_RADAR; + } + + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Remove passive scan restriction for %u", + __func__, wiphy->bands[i]->channels[j].center_freq); + wiphy->bands[i]->channels[j].flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } + + if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Remove no ibss restriction for %u", + __func__, wiphy->bands[i]->channels[j].center_freq); + wiphy->bands[i]->channels[j].flags &= ~IEEE80211_CHAN_NO_IBSS; + } + + wiphy->bands[i]->channels[j].max_power = + (int) MBM_TO_DBM(reg_rule->power_rule.max_eirp); + } + } + +#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS + if (vos_is_dsrc_channel(wiphy->bands[i]->channels[j].center_freq)) + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain]. + channels[k].enabled = NV_CHANNEL_ENABLE; + + /* max_power is in dBm */ + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit = + DEFAULT_11P_POWER; + } + else +#endif + if (wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_DISABLED) + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].enabled = + NV_CHANNEL_DISABLE; + if (n != -1) + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = + NV_CHANNEL_DISABLE; + } + + /* nv cannot distinguish between DFS and passive channels */ + else if (wiphy->bands[i]->channels[j].flags & + (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN | + IEEE80211_CHAN_INDOOR_ONLY)) + { + + if (wiphy->bands[i]->channels[j].flags & + IEEE80211_CHAN_INDOOR_ONLY) + wiphy->bands[i]->channels[j].flags |= + IEEE80211_CHAN_PASSIVE_SCAN; + + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].enabled = + NV_CHANNEL_DFS; + + /* max_power is in mBm = 100 * dBm */ + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit = + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)); + + /* Disable the center channel if neither HT40+ nor HT40- is allowed + */ + if (n != -1) + { + if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40 ) + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = + NV_CHANNEL_DISABLE; + } + else + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = + NV_CHANNEL_DFS; + + /* 40MHz channel power is half of 20MHz (-3dB) ?? */ + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].pwrLimit = + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power))-3); + } + } + if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_80MHZ) == 0) + { + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer") ); + } + else + { + pHddCtx->isVHT80Allowed = 1; + } + } + } + else /* Enable is only last flag we support */ + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain]. + channels[k].enabled = NV_CHANNEL_ENABLE; + + /* max_power is in dBm */ + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit = + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)); + + /* Disable the center channel if neither HT40+ nor HT40- is allowed + */ + if (n != -1) + { + if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40 ) + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = + NV_CHANNEL_DISABLE; + } + else + { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled = + NV_CHANNEL_ENABLE; + /* 40MHz channel power is half of 20MHz (-3dB) */ + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].pwrLimit = + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power))-3); + } + } + if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_80MHZ) == 0) + { + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer") ); + } + else + { + pHddCtx->isVHT80Allowed = 1; + } + } + + } + + /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain + is real gain which should be provided by the real design */ + } + } + +#ifdef FEATURE_WLAN_CH144 + /* Disable RF_CHAN_144 entry if FW does not support channel 144. */ + if (pHddCtx && + (0 == (pHddCtx->reg.eeprom_rd_ext & (1 << WHAL_REG_EXT_FCC_CH_144)))) { + pnvEFSTable->halnv.tables.regDomains[temp_reg_domain]. + channels[RF_CHAN_144].enabled = NV_CHANNEL_DISABLE; + } +#endif + + if (k == 0) + return -1; + + return 0; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)) && !defined(WITH_BACKPORTS) +/* restore_custom_reg_settings() - restore custom reg settings + * + * @wiphy: wiphy structure + * + * Return: void + */ +static void restore_custom_reg_settings(struct wiphy *wiphy) +{ + + struct ieee80211_supported_band *sband; + enum ieee80211_band band; + struct ieee80211_channel *chan; + int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + chan->flags = chan->orig_flags; + chan->max_antenna_gain = chan->orig_mag; + chan->max_power = chan->orig_mpwr; + } + } +} +#endif + +/* + * Function: wlan_hdd_linux_reg_notifier + * This function is called from cfg80211 core to provide regulatory settings + * after new country is requested or intersected (init, user input or 11d) + * This function is used to create a CRDA regulatory settings entry into internal + * regulatory setting table. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) +void __wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +#else +int __wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +#endif +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + eCsrBand nBandCapability = eCSR_BAND_ALL; + v_COUNTRYCODE_t country_code; + int i; + v_BOOL_t isVHT80Allowed; + bool reset = false; + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + FL("country: %c%c, initiator %d, dfs_region: %d"), + request->alpha2[0], + request->alpha2[1], + request->initiator, + request->dfs_region); + + if (TRUE == isWDresetInProgress()) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("SSR is in progress") ); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + return; +#else + return 0; +#endif + } + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer") ); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + return; +#else + return 0; +#endif + } + + if (pHddCtx->isUnloadInProgress || + pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading or SSR in Progress, Ignore!!!", __func__); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + return; +#else + return 0; +#endif + } + + sme_GetFreqBand(pHddCtx->hHal, &nBandCapability); + + /* first check if this callback is in response to the driver callback */ + + switch (request->initiator) + { + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: + + if ((VOS_FALSE == init_by_driver) && + (VOS_FALSE == init_by_reg_core)) { + + if (NL80211_REGDOM_SET_BY_CORE == request->initiator) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + return; +#else + return 0; +#endif + } + init_by_reg_core = VOS_TRUE; + } + + if ((NL80211_REGDOM_SET_BY_DRIVER == request->initiator) && + (VOS_TRUE == init_by_driver)) { + + /* + * restore the driver regulatory flags since + * regulatory_hint may have + * changed them + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags = pHddCtx->reg.reg_flags;; +#else + wiphy->flags = pHddCtx->reg.reg_flags; +#endif + } + if (NL80211_REGDOM_SET_BY_CORE == request->initiator) { + pHddCtx->reg.cc_src = COUNTRY_CODE_SET_BY_CORE; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) +#else + if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) +#endif + reset = true; + } else if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) { + pHddCtx->reg.cc_src = COUNTRY_CODE_SET_BY_DRIVER; + } else { + pHddCtx->reg.cc_src = COUNTRY_CODE_SET_BY_USER; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)) && !defined(WITH_BACKPORTS) + if ((request->alpha2[0] == '0') && + (request->alpha2[1] == '0') && + (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) + { + restore_custom_reg_settings(wiphy); + reset = true; + } +#endif + } + + /* first lookup the country in the local database */ + country_code[0] = request->alpha2[0]; + country_code[1] = request->alpha2[1]; + + pHddCtx->reg.alpha2[0] = request->alpha2[0]; + pHddCtx->reg.alpha2[1] = request->alpha2[1]; + + vos_update_reg_info(pHddCtx); + + temp_reg_domain = REGDOMAIN_COUNT; + for (i = 0; i < countryInfoTable.countryCount && + REGDOMAIN_COUNT == temp_reg_domain; i++) + { + if (memcmp(country_code, countryInfoTable.countryInfo[i].countryCode, + VOS_COUNTRY_CODE_LEN) == 0) + { + /* country code is found */ + /* record the temporary regulatory_domain as well */ + temp_reg_domain = countryInfoTable.countryInfo[i].regDomain; + break; + } + } + + if (REGDOMAIN_COUNT == temp_reg_domain) + temp_reg_domain = REGDOMAIN_WORLD; + + isVHT80Allowed = pHddCtx->isVHT80Allowed; + + if (create_linux_regulatory_entry(wiphy, + nBandCapability, + reset) == 0) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + (" regulatory entry created")); + } + + if (pHddCtx->isVHT80Allowed != isVHT80Allowed) + hdd_checkandupdate_phymode( pHddCtx); + + if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) + complete(&pHddCtx->reg_init); + + /* now pass the new country information to sme */ + if (request->alpha2[0] == '0' && request->alpha2[1] == '0') + { + sme_GenericChangeCountryCode(pHddCtx->hHal, country_code, + REGDOMAIN_COUNT); + } + else + { + sme_GenericChangeCountryCode(pHddCtx->hHal, country_code, + temp_reg_domain); + } + + /* send CTL info to firmware */ + regdmn_set_regval(&pHddCtx->reg); + + /* set dfs_region info */ + vos_nv_set_dfs_region(request->dfs_region); + + regdmn_set_dfs_region(&pHddCtx->reg); + + default: + break; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) || defined(WITH_BACKPORTS) + return; +#else + return 0; +#endif +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) +void wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + vos_ssr_protect(__func__); + __wlan_hdd_linux_reg_notifier(wiphy, request); + vos_ssr_unprotect(__func__); + return; +} +#else +int wlan_hdd_linux_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + int ret; + vos_ssr_protect(__func__); + ret = __wlan_hdd_linux_reg_notifier(wiphy, request); + vos_ssr_unprotect(__func__); + return ret; +} +#endif + +/* initialize wiphy from EEPROM */ +VOS_STATUS vos_init_wiphy_from_eeprom(void) +{ + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + struct wiphy *wiphy = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (!pVosContext) + return VOS_STATUS_E_EXISTS; + + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + if (!pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer")); + return VOS_STATUS_E_FAULT; + } + + wiphy = pHddCtx->wiphy; + + if (reg_init_from_eeprom(pHddCtx, &pHddCtx->reg, wiphy)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Error during regulatory init from EEPROM")); + return VOS_STATUS_E_FAULT; + } + + if (is_world_regd(pHddCtx->reg.reg_domain)) { + temp_reg_domain = REGDOMAIN_WORLD; + if (create_linux_regulatory_entry(wiphy, + pHddCtx->cfg_ini->nBandCapability, + true) != 0) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Error while creating regulatory entry")); + return VOS_STATUS_E_FAULT; + } + } + + init_completion(&pHddCtx->reg_init); + + /* send CTL info to firmware */ + regdmn_set_regval(&pHddCtx->reg); + + return VOS_STATUS_SUCCESS; +} + +/* initialize wiphy from NV.bin */ +VOS_STATUS vos_init_wiphy_from_nv_bin(void) +{ + int i, j, m; + int k = 0; + v_REGDOMAIN_t reg_domain; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + struct wiphy *wiphy = NULL; + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL != pVosContext) + pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext); + else + return VOS_STATUS_E_EXISTS; + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer") ); + return VOS_STATUS_E_FAULT; + } + + wiphy = pHddCtx->wiphy; + + /* Update regulatory structure in HDD */ + pHddCtx->reg.alpha2[0] = + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0]; + pHddCtx->reg.alpha2[1] = + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1]; + pHddCtx->reg.cc_src = COUNTRY_CODE_SET_BY_DRIVER; + + vos_update_reg_info(pHddCtx); + + if (('0' == pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0]) + && + ('0' == pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1])) + { + /* default country is world roaming */ + + reg_domain = REGDOMAIN_WORLD; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +#else + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#endif + } + else if (REGDOMAIN_WORLD == + pnvEFSTable->halnv.tables.defaultCountryTable.regDomain) { + + reg_domain = pnvEFSTable->halnv.tables.defaultCountryTable.regDomain; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +#else + wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; +#endif + } + else { + + reg_domain = pnvEFSTable->halnv.tables.defaultCountryTable.regDomain; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) + wiphy->regulatory_flags |= REGULATORY_STRICT_REG; +#else + wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; +#endif + } + m = 0; + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + { + + if (wiphy->bands[i] == NULL) + continue; + + /* internal channels[] is one continous array for both 2G and 5G bands + m is internal starting channel index for each band */ + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + /* k = (m + j) is internal current channel index */ + k = m + j; + + if (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].enabled == + NV_CHANNEL_DISABLE) + wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED; + + else if (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].enabled == + NV_CHANNEL_DFS) { + + wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; + + wiphy->bands[i]->channels[j].max_power = + (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].pwrLimit)*100; + } + + else if (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].enabled == + NV_CHANNEL_ENABLE) { + + wiphy->bands[i]->channels[j].max_power = + (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].pwrLimit)*100; + } + } + + m += wiphy->bands[i]->n_channels; + } + + return VOS_STATUS_SUCCESS; +} + diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c new file mode 100644 index 000000000000..ec4c17b39ee9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file vos_packet.c + + \brief virtual Operating System Services (vOSS) network Packet APIs + + Network Protocol packet/buffer support interfaces + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "adf_nbuf.h" +#include "vos_memory.h" +#include "adf_os_mem.h" + +#ifdef QCA_PKT_PROTO_TRACE +/* Protocol specific packet tracking feature */ +#define VOS_PKT_TRAC_ETH_TYPE_OFFSET 12 +#define VOS_PKT_TRAC_IP_OFFSET 14 +#define VOS_PKT_TRAC_IP_HEADER_SIZE 20 +#define VOS_PKT_TRAC_DHCP_SRV_PORT 67 +#define VOS_PKT_TRAC_DHCP_CLI_PORT 68 +#define VOS_PKT_TRAC_EAPOL_ETH_TYPE 0x888E +#define VOS_PKT_TRAC_MAX_STRING_LEN 12 +#define VOS_PKT_TRAC_MAX_TRACE_BUF 50 +#define VOS_PKT_TRAC_MAX_STRING_BUF 64 + +/* protocol Storage Structure */ +typedef struct +{ + v_U32_t order; + v_TIME_t event_time; + char event_string[VOS_PKT_TRAC_MAX_STRING_LEN]; +} vos_pkt_proto_trace_t; + +vos_pkt_proto_trace_t *trace_buffer = NULL; +unsigned int trace_buffer_order = 0; +vos_spin_lock_t trace_buffer_lock; +#endif /* QCA_PKT_PROTO_TRACE */ + +/** + * vos_pkt_return_packet Free the voss Packet + * @ vos Packet + */ +VOS_STATUS vos_pkt_return_packet(vos_pkt_t *packet) +{ + // Validate the input parameter pointer + if (unlikely(packet == NULL)) { + return VOS_STATUS_E_INVAL; + } + + /* Free up the Adf nbuf */ + adf_nbuf_free(packet->pkt_buf); + + packet->pkt_buf = NULL; + + /* Free up the Rx packet */ + vos_mem_free(packet); + + return VOS_STATUS_SUCCESS; +} + +/**-------------------------------------------------------------------------- + + \brief vos_pkt_get_packet_length() - Get packet length for a voss Packet + + This API returns the total length of the data in a voss Packet. + + \param pPacket - the voss Packet to get the packet length from. + + \param pPacketSize - location to return the total size of the data contained + in the voss Packet. + \return + + \sa + + ---------------------------------------------------------------------------*/ +VOS_STATUS vos_pkt_get_packet_length( vos_pkt_t *pPacket, + v_U16_t *pPacketSize ) +{ + // Validate the parameter pointers + if (unlikely((pPacket == NULL) || (pPacketSize == NULL)) || + (pPacket->pkt_buf == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "VPKT [%d]: NULL pointer", __LINE__); + return VOS_STATUS_E_INVAL; + } + + // return the requested information + *pPacketSize = adf_nbuf_len(pPacket->pkt_buf); + return VOS_STATUS_SUCCESS; +} + +/* + * TODO: Remove below later since all the below + * definitions are not required for Host + * driver 2.0 (still references from HDD and + * other layers are yet to be removed) + */ +VOS_STATUS vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE pktType, + v_SIZE_t *vosFreeBuffer) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_get_os_packet( vos_pkt_t *pPacket, + v_VOID_t **ppOSPacket, + v_BOOL_t clearOSPacket ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_wrap_data_packet( vos_pkt_t **ppPacket, + VOS_PKT_TYPE pktType, + v_VOID_t *pOSPacket, + vos_pkt_get_packet_callback callback, + v_VOID_t *userData ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_set_os_packet( vos_pkt_t *pPacket, + v_VOID_t *pOSPacket ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_get_timestamp( vos_pkt_t *pPacket, + v_TIME_t* pTstamp ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_walk_packet_chain( vos_pkt_t *pPacket, + vos_pkt_t **ppChainedPacket, + v_BOOL_t unchainPacket ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_peek_data( vos_pkt_t *pPacket, + v_SIZE_t pktOffset, + v_VOID_t **ppPacketData, + v_SIZE_t numBytes ) +{ + return VOS_STATUS_SUCCESS; +} +VOS_STATUS vos_pkt_get_packet( vos_pkt_t **ppPacket, + VOS_PKT_TYPE pktType, + v_SIZE_t dataSize, + v_SIZE_t numPackets, + v_BOOL_t zeroBuffer, + vos_pkt_get_packet_callback callback, + v_VOID_t *userData ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_reserve_head( vos_pkt_t *pPacket, + v_VOID_t **ppData, + v_SIZE_t dataSize ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_pop_head( vos_pkt_t *pPacket, + v_VOID_t *pData, + v_SIZE_t dataSize ) +{ + return VOS_STATUS_SUCCESS; +} + +VOS_STATUS vos_pkt_push_head( vos_pkt_t *pPacket, + v_VOID_t *pData, + v_SIZE_t dataSize ) +{ + return VOS_STATUS_SUCCESS; +} + +v_VOID_t vos_pkt_set_user_data_ptr( vos_pkt_t *pPacket, + VOS_PKT_USER_DATA_ID userID, + v_VOID_t *pUserData ) +{ + return; +} + +v_VOID_t vos_pkt_get_user_data_ptr( vos_pkt_t *pPacket, + VOS_PKT_USER_DATA_ID userID, + v_VOID_t **ppUserData ) +{ + return; +} + +VOS_STATUS vos_pkt_extract_data( vos_pkt_t *pPacket, + v_SIZE_t pktOffset, + v_VOID_t *pOutputBuffer, + v_SIZE_t *pOutputBufferSize ) +{ + return VOS_STATUS_SUCCESS; +} + +#ifdef QCA_PKT_PROTO_TRACE +/*--------------------------------------------------------------------------- + + * brief vos_pkt_get_proto_type() - + Find protoco type from packet contents + + * skb Packet Pointer + * tracking_map packet type want to track + * dot11_type, type of dot11 frame + +---------------------------------------------------------------------------*/ +v_U8_t vos_pkt_get_proto_type +( + struct sk_buff *skb, + v_U8_t tracking_map, + v_U8_t dot11_type +) +{ + v_U8_t pkt_proto_type = 0; + v_U16_t ether_type; + v_U16_t SPort; + v_U16_t DPort; + + if (dot11_type) + { + if (dot11_type == (VOS_PKT_TRAC_TYPE_MGMT_ACTION & tracking_map)) + pkt_proto_type |= VOS_PKT_TRAC_TYPE_MGMT_ACTION; + + /* Protocol type map */ + return pkt_proto_type; + } + + /* EAPOL Tracking enabled */ + if (VOS_PKT_TRAC_TYPE_EAPOL & tracking_map) + { + ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_TRAC_ETH_TYPE_OFFSET)); + if (VOS_PKT_TRAC_EAPOL_ETH_TYPE == VOS_SWAP_U16(ether_type)) + { + pkt_proto_type |= VOS_PKT_TRAC_TYPE_EAPOL; + } + } + + /* DHCP Tracking enabled */ + if (VOS_PKT_TRAC_TYPE_DHCP & tracking_map) + { + SPort = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_TRAC_IP_OFFSET + + VOS_PKT_TRAC_IP_HEADER_SIZE)); + DPort = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_TRAC_IP_OFFSET + + VOS_PKT_TRAC_IP_HEADER_SIZE + sizeof(v_U16_t))); + if (((VOS_PKT_TRAC_DHCP_SRV_PORT == VOS_SWAP_U16(SPort)) && + (VOS_PKT_TRAC_DHCP_CLI_PORT == VOS_SWAP_U16(DPort))) || + ((VOS_PKT_TRAC_DHCP_CLI_PORT == VOS_SWAP_U16(SPort)) && + (VOS_PKT_TRAC_DHCP_SRV_PORT == VOS_SWAP_U16(DPort)))) + { + pkt_proto_type |= VOS_PKT_TRAC_TYPE_DHCP; + } + } + + /* Protocol type map */ + return pkt_proto_type; +} + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_trace_buf_update() - + Update storage buffer with interest event string + + * event_string Event String may packet type or outstanding event + +---------------------------------------------------------------------------*/ +void vos_pkt_trace_buf_update +( + char *event_string +) +{ + v_U32_t slot; + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s %d, %s", __func__, __LINE__, event_string); + vos_spin_lock_acquire(&trace_buffer_lock); + slot = trace_buffer_order % VOS_PKT_TRAC_MAX_TRACE_BUF; + trace_buffer[slot].order = trace_buffer_order; + trace_buffer[slot].event_time = vos_timer_get_system_time(); + vos_mem_zero(trace_buffer[slot].event_string, + sizeof(trace_buffer[slot].event_string)); + vos_mem_copy(trace_buffer[slot].event_string, + event_string, + (VOS_PKT_TRAC_MAX_STRING_LEN < strlen(event_string))? + VOS_PKT_TRAC_MAX_STRING_LEN:strlen(event_string)); + trace_buffer_order++; + vos_spin_lock_release(&trace_buffer_lock); + + return; +} + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_trace_buf_dump() - + Dump stored information into kernel log + +---------------------------------------------------------------------------*/ +void vos_pkt_trace_buf_dump +( + void +) +{ + v_U32_t slot, idx; + + vos_spin_lock_acquire(&trace_buffer_lock); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "PACKET TRACE DUMP START Current Timestamp %u", + (unsigned int)vos_timer_get_system_time()); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "ORDER : TIME : EVT"); + if (VOS_PKT_TRAC_MAX_TRACE_BUF > trace_buffer_order) + { + for (slot = 0 ; slot < trace_buffer_order; slot++) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%5d :%12u : %s", + trace_buffer[slot].order, + (unsigned int)trace_buffer[slot].event_time, + trace_buffer[slot].event_string); + } + } + else + { + for (idx = 0 ; idx < VOS_PKT_TRAC_MAX_TRACE_BUF; idx++) + { + slot = (trace_buffer_order + idx) % VOS_PKT_TRAC_MAX_TRACE_BUF; + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%5d :%12u : %s", + trace_buffer[slot].order, + (unsigned int)trace_buffer[slot].event_time, + trace_buffer[slot].event_string); + } + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "PACKET TRACE DUMP END"); + vos_spin_lock_release(&trace_buffer_lock); + + return; +} + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_proto_trace_init() - + Initialize protocol trace functionality, allocate required resource + +---------------------------------------------------------------------------*/ +void vos_pkt_proto_trace_init +( + void +) +{ + /* Init spin lock to protect global memory */ + vos_spin_lock_init(&trace_buffer_lock); + trace_buffer_order = 0; + trace_buffer = vos_mem_malloc( + VOS_PKT_TRAC_MAX_TRACE_BUF * sizeof(vos_pkt_proto_trace_t)); + vos_mem_zero((void *)trace_buffer, + VOS_PKT_TRAC_MAX_TRACE_BUF * sizeof(vos_pkt_proto_trace_t)); + + /* Register callback function to NBUF + * Lower layer event also will be reported to here */ + adf_nbuf_reg_trace_cb(vos_pkt_trace_buf_update); + return; +} + +/*--------------------------------------------------------------------------- + + * brief vos_pkt_proto_trace_close() - + Free required resource + +---------------------------------------------------------------------------*/ +void vos_pkt_proto_trace_close +( + void +) +{ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s %d", __func__, __LINE__); + vos_mem_free(trace_buffer); + vos_spin_lock_destroy(&trace_buffer_lock); + + return; +} +#endif /* QCA_PKT_PROTO_TRACE */ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c new file mode 100644 index 000000000000..a55c129d1e83 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c @@ -0,0 +1,2562 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + @file vos_sched.c + @brief VOS Scheduler Implementation +===========================================================================*/ +/*=========================================================================== + EDIT HISTORY FOR FILE + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + $Header:$ $DateTime: $ $Author: $ + + when who what, where, why + -------- --- -------------------------------------------------------- +===========================================================================*/ +/*--------------------------------------------------------------------------- + * Include Files + * ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vos_sched.h" +#include +#include "wlan_qct_wda.h" +#include +#include +#include +#include +#if defined(QCA_CONFIG_SMP) && defined(CONFIG_CNSS) +#include +#endif +/*--------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * ------------------------------------------------------------------------*/ +#define VOS_SCHED_THREAD_HEART_BEAT INFINITE +/* Milli seconds to delay SSR thread when an Entry point is Active */ +#define SSR_WAIT_SLEEP_TIME 200 +/* MAX iteration count to wait for Entry point to exit before + * we proceed with SSR in WD Thread + */ +#define MAX_SSR_WAIT_ITERATIONS 200 +#define MAX_SSR_PROTECT_LOG (16) + +static atomic_t ssr_protect_entry_count; + +struct ssr_protect { + const char* func; + bool free; + uint32_t pid; +}; + +static spinlock_t ssr_protect_lock; +static struct ssr_protect ssr_protect_log[MAX_SSR_PROTECT_LOG]; + +/*--------------------------------------------------------------------------- + * Type Declarations + * ------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------- + * Data definitions + * ------------------------------------------------------------------------*/ +static pVosSchedContext gpVosSchedContext; +static pVosWatchdogContext gpVosWatchdogContext; + +/*--------------------------------------------------------------------------- + * Forward declaration + * ------------------------------------------------------------------------*/ +static int VosMCThread(void *Arg); +static int VosWDThread(void *Arg); +static int VosTXThread(void *Arg); +static int VosRXThread(void *Arg); +#ifdef QCA_CONFIG_SMP +static int VosTlshimRxThread(void *arg); +static unsigned long affine_cpu = 0; +static VOS_STATUS vos_alloc_tlshim_pkt_freeq(pVosSchedContext pSchedContext); +#endif +void vos_sched_flush_rx_mqs(pVosSchedContext SchedContext); +extern v_VOID_t vos_core_return_msg(v_PVOID_t pVContext, pVosMsgWrapper pMsgWrapper); + + +#ifdef QCA_CONFIG_SMP + +/*Maximum 2 clusters supported*/ +#define VOS_MAX_CPU_CLUSTERS 2 + +#define VOS_CPU_CLUSTER_TYPE_LITTLE 0 +#define VOS_CPU_CLUSTER_TYPE_PERF 1 + +static int vos_set_cpus_allowed_ptr(struct task_struct *task, + unsigned long cpu) +{ +#ifdef WLAN_OPEN_SOURCE + return set_cpus_allowed_ptr(task, cpumask_of(cpu)); +#elif defined(CONFIG_CNSS) + return cnss_set_cpus_allowed_ptr(task, cpu); +#else + return 0; +#endif +} + +/** + * vos_sched_find_attach_cpu - find available cores and attach to required core + * @pSchedContext: wlan scheduler context + * @high_throughput: high throughput is required or not + * + * Find current online cores. + * high troughput required and PERF core online, then attach to last PERF core + * low throughput required or only little cores online, the attach any little + * core + * + * Return: 0 success + * 1 fail + */ +static int vos_sched_find_attach_cpu(pVosSchedContext pSchedContext, + bool high_throughput) +{ + unsigned long *online_perf_cpu = NULL; + unsigned long *online_litl_cpu = NULL; + unsigned char perf_core_count = 0; + unsigned char litl_core_count = 0; + int vosMaxClusterId = 0; +#if defined(WLAN_OPEN_SOURCE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + struct cpumask litl_mask; + unsigned long cpus; + int i; +#endif + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_LOW, + "%s: num possible cpu %d", + __func__, num_possible_cpus()); + + + online_perf_cpu = vos_mem_malloc( + num_possible_cpus() * sizeof(unsigned long)); + if (!online_perf_cpu) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: perf cpu cache alloc fail", __func__); + return 1; + } + vos_mem_zero(online_perf_cpu, + num_possible_cpus() * sizeof(unsigned long)); + + online_litl_cpu = vos_mem_malloc( + num_possible_cpus() * sizeof(unsigned long)); + if (!online_litl_cpu) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: lttl cpu cache alloc fail", __func__); + vos_mem_free(online_perf_cpu); + return 1; + } + vos_mem_zero(online_litl_cpu, + num_possible_cpus() * sizeof(unsigned long)); + + /* Get Online perf CPU count */ +#if defined(WLAN_OPEN_SOURCE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + for_each_online_cpu(cpus) { + if ( topology_physical_package_id(cpus) > VOS_MAX_CPU_CLUSTERS) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: can handle max %d clusters, returning...", + __func__, VOS_MAX_CPU_CLUSTERS); + goto err; + } + + if (topology_physical_package_id(cpus) == VOS_CPU_CLUSTER_TYPE_PERF) { + online_perf_cpu[perf_core_count] = cpus; + perf_core_count++; + } else { + online_litl_cpu[litl_core_count] = cpus; + litl_core_count++; + } + vosMaxClusterId = topology_physical_package_id(cpus); + } +#else + vosMaxClusterId = 0; +#endif + + /* Single cluster system, not need to handle this */ + if (0 == vosMaxClusterId) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_LOW, + "%s: single cluster system. returning", __func__); + goto success; + } + + if ((!litl_core_count) && (!perf_core_count)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Both Cluster off, do nothing", __func__); + goto success; + } + + if ((high_throughput && perf_core_count) || (!litl_core_count)) { + /* Attach RX thread to PERF CPU */ + if (pSchedContext->rx_thread_cpu != + online_perf_cpu[perf_core_count - 1]) { + if (vos_set_cpus_allowed_ptr( + pSchedContext->TlshimRxThread, + online_perf_cpu[perf_core_count - 1])) { + VOS_TRACE(VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_ERROR, + "%s: rx thread perf core set fail", + __func__); + goto err; + } + pSchedContext->rx_thread_cpu = + online_perf_cpu[perf_core_count - 1]; + } + } else { + +#if defined(WLAN_OPEN_SOURCE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + /* Attach to any little core + * Final decision should made by scheduler */ + + cpumask_clear(&litl_mask); + for (i = 0; + i < litl_core_count; + i++) { + cpumask_set_cpu(online_litl_cpu[i], &litl_mask); + } + + set_cpus_allowed_ptr(pSchedContext->TlshimRxThread, &litl_mask); + pSchedContext->rx_thread_cpu = 0; +#else + /* Attach RX thread to last little core CPU */ + if (pSchedContext->rx_thread_cpu != + online_litl_cpu[litl_core_count - 1]) { + if (vos_set_cpus_allowed_ptr( + pSchedContext->TlshimRxThread, + online_litl_cpu[litl_core_count - 1])) { + VOS_TRACE(VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_ERROR, + "%s: rx thread litl core set fail", + __func__); + goto err; + } + pSchedContext->rx_thread_cpu = + online_litl_cpu[litl_core_count - 1]; + } +#endif + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: NUM PERF CORE %d, HIGH TPUTR REQ %d, RX THRE CPU %lu", + __func__, perf_core_count, + (int)pSchedContext->high_throughput_required, + pSchedContext->rx_thread_cpu); +success: + vos_mem_free(online_perf_cpu); + vos_mem_free(online_litl_cpu); + return 0; + +err: + vos_mem_free(online_perf_cpu); + vos_mem_free(online_litl_cpu); + return 1; + +} + +/** + * vos_sched_handle_cpu_hot_plug - cpu hotplug event handler + * + * cpu hotplug indication handler + * will find online cores and will assign proper core based on perf requirement + * + * Return: 0 success + * 1 fail + */ +int vos_sched_handle_cpu_hot_plug(void) +{ + pVosSchedContext pSchedContext = get_vos_sched_ctxt(); + + if (!pSchedContext) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return 1; + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL) || + (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL))) + return 0; + + vos_lock_acquire(&pSchedContext->affinity_lock); + if (vos_sched_find_attach_cpu(pSchedContext, + pSchedContext->high_throughput_required)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: handle hot plug fail", __func__); + vos_lock_release(&pSchedContext->affinity_lock); + return 1; + } + vos_lock_release(&pSchedContext->affinity_lock); + return 0; +} + +/** + * vos_sched_handle_throughput_req - cpu throughput requirement handler + * @high_tput_required: high throughput is required or not + * + * high or low throughput indication ahndler + * will find online cores and will assign proper core based on perf requirement + * + * Return: 0 success + * 1 fail + */ +int vos_sched_handle_throughput_req(bool high_tput_required) +{ + pVosSchedContext pSchedContext = get_vos_sched_ctxt(); + + if (!pSchedContext) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return 1; + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL) || + (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL))) + return 0; + + vos_lock_acquire(&pSchedContext->affinity_lock); + pSchedContext->high_throughput_required = high_tput_required; + if (vos_sched_find_attach_cpu(pSchedContext, high_tput_required)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: handle throughput req fail", __func__); + vos_lock_release(&pSchedContext->affinity_lock); + return 1; + } + vos_lock_release(&pSchedContext->affinity_lock); + return 0; +} + +/** + * __vos_cpu_hotplug_notify - cpu core on-off notification handler + * @block: notifier block + * @state: state of core + * @hcpu: target cpu core + * + * pre-registered core status change notify callback function + * will handle only ONLINE, OFFLINE notification + * based on cpu architecture, rx thread affinity will be different + * + * Return: 0 success + * 1 fail + */ +static int __vos_cpu_hotplug_notify(struct notifier_block *block, + unsigned long state, void *hcpu) +{ + unsigned long cpu = (unsigned long) hcpu; + unsigned long pref_cpu = 0; + pVosSchedContext pSchedContext = get_vos_sched_ctxt(); + int i; + unsigned int multi_cluster; + unsigned int num_cpus; +#if defined(WLAN_OPEN_SOURCE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + int cpus; +#endif + + if ((NULL == pSchedContext) || (NULL == pSchedContext->TlshimRxThread)) + return NOTIFY_OK; + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL) || + (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL))) + return NOTIFY_OK; + + num_cpus = num_possible_cpus(); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_LOW, + "%s: RX CORE %d, STATE %d, NUM CPUS %d", + __func__, (int)affine_cpu, (int)state, num_cpus); + multi_cluster = 0; + +#if defined(WLAN_OPEN_SOURCE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + + for_each_online_cpu(cpus) { + multi_cluster = topology_physical_package_id(cpus); + } +#endif + + if ((multi_cluster) && + ((CPU_ONLINE == state) || (CPU_DEAD == state))) { + vos_sched_handle_cpu_hot_plug(); + return NOTIFY_OK; + } + + switch (state) { + case CPU_ONLINE: + if (affine_cpu != 0) + return NOTIFY_OK; + + for_each_online_cpu(i) { + if (i == 0) + continue; + pref_cpu = i; + break; + } + break; + case CPU_DEAD: + if (cpu != affine_cpu) + return NOTIFY_OK; + + affine_cpu = 0; + for_each_online_cpu(i) { + if (i == 0) + continue; + pref_cpu = i; + break; + } + } + + if (pref_cpu == 0) + return NOTIFY_OK; + + if (!vos_set_cpus_allowed_ptr(pSchedContext->TlshimRxThread, pref_cpu)) + affine_cpu = pref_cpu; + + return NOTIFY_OK; +} + +/** + * vos_cpu_hotplug_notify - cpu core on-off notification handler wrapper + * @block: notifier block + * @state: state of core + * @hcpu: target cpu core + * + * pre-registered core status change notify callback function + * will handle only ONLINE, OFFLINE notification + * based on cpu architecture, rx thread affinity will be different + * wrapper function + * + * Return: 0 success + * 1 fail + */ +static int vos_cpu_hotplug_notify(struct notifier_block *block, + unsigned long state, void *hcpu) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __vos_cpu_hotplug_notify(block, state, hcpu); + vos_ssr_unprotect(__func__); + + return ret; +} + +static struct notifier_block vos_cpu_hotplug_notifier = { + .notifier_call = vos_cpu_hotplug_notify, +}; +#endif + +/*--------------------------------------------------------------------------- + * External Function implementation + * ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + \brief vos_sched_open() - initialize the vOSS Scheduler + The \a vos_sched_open() function initializes the vOSS Scheduler + Upon successful initialization: + - All the message queues are initialized + - The Main Controller thread is created and ready to receive and + dispatch messages. + - The Tx thread is created and ready to receive and dispatch messages + + \param pVosContext - pointer to the global vOSS Context + \param pVosSchedContext - pointer to a previously allocated buffer big + enough to hold a scheduler context. + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the scheduler + VOS_STATUS_E_INVAL - Invalid parameter passed to the scheduler Open + function + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + \sa vos_sched_open() + -------------------------------------------------------------------------*/ +VOS_STATUS +vos_sched_open +( + v_PVOID_t pVosContext, + pVosSchedContext pSchedContext, + v_SIZE_t SchedCtxSize +) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; +/*-------------------------------------------------------------------------*/ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Opening the VOSS Scheduler",__func__); + // Sanity checks + if ((pVosContext == NULL) || (pSchedContext == NULL)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params being passed",__func__); + return VOS_STATUS_E_FAILURE; + } + if (sizeof(VosSchedContext) != SchedCtxSize) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Incorrect VOS Sched Context size passed",__func__); + return VOS_STATUS_E_INVAL; + } + vos_mem_zero(pSchedContext, sizeof(VosSchedContext)); + pSchedContext->pVContext = pVosContext; + vStatus = vos_sched_init_mqs(pSchedContext); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to initialize VOS Scheduler MQs",__func__); + return vStatus; + } + // Initialize the helper events and event queues + init_completion(&pSchedContext->McStartEvent); + init_completion(&pSchedContext->TxStartEvent); + init_completion(&pSchedContext->RxStartEvent); + init_completion(&pSchedContext->McShutdown); + init_completion(&pSchedContext->TxShutdown); + init_completion(&pSchedContext->RxShutdown); + init_completion(&pSchedContext->ResumeMcEvent); + init_completion(&pSchedContext->ResumeTxEvent); + init_completion(&pSchedContext->ResumeRxEvent); + + spin_lock_init(&pSchedContext->McThreadLock); + spin_lock_init(&pSchedContext->TxThreadLock); + spin_lock_init(&pSchedContext->RxThreadLock); +#ifdef QCA_CONFIG_SMP + spin_lock_init(&pSchedContext->TlshimRxThreadLock); +#endif + + init_waitqueue_head(&pSchedContext->mcWaitQueue); + pSchedContext->mcEventFlag = 0; + init_waitqueue_head(&pSchedContext->txWaitQueue); + pSchedContext->txEventFlag= 0; + init_waitqueue_head(&pSchedContext->rxWaitQueue); + pSchedContext->rxEventFlag= 0; + +#ifdef QCA_CONFIG_SMP + init_waitqueue_head(&pSchedContext->tlshimRxWaitQueue); + init_completion(&pSchedContext->TlshimRxStartEvent); + init_completion(&pSchedContext->SuspndTlshimRxEvent); + init_completion(&pSchedContext->ResumeTlshimRxEvent); + init_completion(&pSchedContext->TlshimRxShutdown); + pSchedContext->tlshimRxEvtFlg = 0; + spin_lock_init(&pSchedContext->TlshimRxQLock); + spin_lock_init(&pSchedContext->VosTlshimPktFreeQLock); + INIT_LIST_HEAD(&pSchedContext->tlshimRxQueue); + spin_lock_bh(&pSchedContext->VosTlshimPktFreeQLock); + INIT_LIST_HEAD(&pSchedContext->VosTlshimPktFreeQ); + if (vos_alloc_tlshim_pkt_freeq(pSchedContext) != VOS_STATUS_SUCCESS) + { + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); + return VOS_STATUS_E_FAILURE; + } + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); + register_hotcpu_notifier(&vos_cpu_hotplug_notifier); + pSchedContext->cpuHotPlugNotifier = &vos_cpu_hotplug_notifier; + vos_lock_init(&pSchedContext->affinity_lock); + pSchedContext->high_throughput_required = false; +#endif + + + /* + ** This initialization is critical as the threads will later access the + ** global contexts normally, + ** + ** I shall put some memory barrier here after the next piece of code but + ** I am keeping it simple for now. + */ + gpVosSchedContext = pSchedContext; + + //Create the VOSS Main Controller thread + pSchedContext->McThread = kthread_create(VosMCThread, pSchedContext, + "VosMCThread"); + if (IS_ERR(pSchedContext->McThread)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Could not Create VOSS Main Thread Controller",__func__); + goto MC_THREAD_START_FAILURE; + } + wake_up_process(pSchedContext->McThread); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS Main Controller thread Created",__func__); + + pSchedContext->TxThread = kthread_create(VosTXThread, pSchedContext, + "VosTXThread"); + if (IS_ERR(pSchedContext->TxThread)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Could not Create VOSS TX Thread",__func__); + goto TX_THREAD_START_FAILURE; + } + wake_up_process(pSchedContext->TxThread); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + ("VOSS TX thread Created")); + + pSchedContext->RxThread = kthread_create(VosRXThread, pSchedContext, + "VosRXThread"); + if (IS_ERR(pSchedContext->RxThread)) + { + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Could not Create VOSS RX Thread",__func__); + goto RX_THREAD_START_FAILURE; + + } + wake_up_process(pSchedContext->RxThread); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + ("VOSS RX thread Created")); + +#ifdef QCA_CONFIG_SMP + pSchedContext->TlshimRxThread = kthread_create(VosTlshimRxThread, + pSchedContext, + "VosTlshimRxThread"); + if (IS_ERR(pSchedContext->TlshimRxThread)) + { + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Could not Create VOSS Tlshim RX Thread", __func__); + goto TLSHIM_RX_THREAD_START_FAILURE; + + } + wake_up_process(pSchedContext->TlshimRxThread); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + ("VOSS Tlshim RX thread Created")); +#endif + /* + ** Now make sure all threads have started before we exit. + ** Each thread should normally ACK back when it starts. + */ + wait_for_completion_interruptible(&pSchedContext->McStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS MC Thread has started",__func__); + wait_for_completion_interruptible(&pSchedContext->TxStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS Tx Thread has started",__func__); + wait_for_completion_interruptible(&pSchedContext->RxStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS Rx Thread has started",__func__); +#ifdef QCA_CONFIG_SMP + wait_for_completion_interruptible(&pSchedContext->TlshimRxStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS Tlshim Rx Thread has started", __func__); +#endif + /* + ** We're good now: Let's get the ball rolling!!! + */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS Scheduler successfully Opened",__func__); + return VOS_STATUS_SUCCESS; + + +#ifdef QCA_CONFIG_SMP +TLSHIM_RX_THREAD_START_FAILURE: + //Try and force the Rx thread controller to exit + set_bit(RX_SHUTDOWN_EVENT_MASK, &pSchedContext->rxEventFlag); + set_bit(RX_POST_EVENT_MASK, &pSchedContext->rxEventFlag); + wake_up_interruptible(&pSchedContext->rxWaitQueue); + //Wait for RX to exit + wait_for_completion_interruptible(&pSchedContext->RxShutdown); +#endif +RX_THREAD_START_FAILURE: + //Try and force the Tx thread controller to exit + set_bit(MC_SHUTDOWN_EVENT_MASK, &pSchedContext->txEventFlag); + set_bit(MC_POST_EVENT_MASK, &pSchedContext->txEventFlag); + wake_up_interruptible(&pSchedContext->txWaitQueue); + //Wait for TX to exit + wait_for_completion_interruptible(&pSchedContext->TxShutdown); + +TX_THREAD_START_FAILURE: + //Try and force the Main thread controller to exit + set_bit(MC_SHUTDOWN_EVENT_MASK, &pSchedContext->mcEventFlag); + set_bit(MC_POST_EVENT_MASK, &pSchedContext->mcEventFlag); + wake_up_interruptible(&pSchedContext->mcWaitQueue); + //Wait for MC to exit + wait_for_completion_interruptible(&pSchedContext->McShutdown); + +MC_THREAD_START_FAILURE: + //De-initialize all the message queues + vos_sched_deinit_mqs(pSchedContext); + + +#ifdef QCA_CONFIG_SMP + unregister_hotcpu_notifier(&vos_cpu_hotplug_notifier); + vos_free_tlshim_pkt_freeq(gpVosSchedContext); +#endif + + return VOS_STATUS_E_RESOURCES; + +} /* vos_sched_open() */ + +VOS_STATUS vos_watchdog_open +( + v_PVOID_t pVosContext, + pVosWatchdogContext pWdContext, + v_SIZE_t wdCtxSize +) +{ +/*-------------------------------------------------------------------------*/ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Opening the VOSS Watchdog module",__func__); + //Sanity checks + if ((pVosContext == NULL) || (pWdContext == NULL)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params being passed",__func__); + return VOS_STATUS_E_FAILURE; + } + if (sizeof(VosWatchdogContext) != wdCtxSize) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Incorrect VOS Watchdog Context size passed",__func__); + return VOS_STATUS_E_INVAL; + } + vos_mem_zero(pWdContext, sizeof(VosWatchdogContext)); + pWdContext->pVContext = pVosContext; + gpVosWatchdogContext = pWdContext; + + //Initialize the helper events and event queues + init_completion(&pWdContext->WdStartEvent); + init_completion(&pWdContext->WdShutdown); + init_waitqueue_head(&pWdContext->wdWaitQueue); + pWdContext->wdEventFlag = 0; + + // Initialize the lock + spin_lock_init(&pWdContext->wdLock); + + //Create the Watchdog thread + pWdContext->WdThread = kthread_create(VosWDThread, pWdContext,"VosWDThread"); + + if (IS_ERR(pWdContext->WdThread)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Could not Create Watchdog thread",__func__); + return VOS_STATUS_E_RESOURCES; + } + else + { + wake_up_process(pWdContext->WdThread); + } + /* + ** Now make sure thread has started before we exit. + ** Each thread should normally ACK back when it starts. + */ + wait_for_completion_interruptible(&pWdContext->WdStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: VOSS Watchdog Thread has started",__func__); + return VOS_STATUS_SUCCESS; +} /* vos_watchdog_open() */ +/*--------------------------------------------------------------------------- + \brief VosMcThread() - The VOSS Main Controller thread + The \a VosMcThread() is the VOSS main controller thread: + \param Arg - pointer to the global vOSS Sched Context + \return Thread exit code + \sa VosMcThread() + -------------------------------------------------------------------------*/ +static int +VosMCThread +( + void * Arg +) +{ + pVosSchedContext pSchedContext = (pVosSchedContext)Arg; + pVosMsgWrapper pMsgWrapper = NULL; + tpAniSirGlobal pMacContext = NULL; + tSirRetStatus macStatus = eSIR_SUCCESS; + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + int retWaitStatus = 0; + v_BOOL_t shutdown = VOS_FALSE; + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + + if (Arg == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Bad Args passed", __func__); + return 0; + } + set_user_nice(current, -2); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) + daemonize("MC_Thread"); +#endif + + /* + ** Ack back to the context from which the main controller thread has been + ** created. + */ + complete(&pSchedContext->McStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: MC Thread %d (%s) starting up",__func__, current->pid, current->comm); + + /* Get the Global VOSS Context */ + 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 0; + } + + /* Get the HDD context */ + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return 0; + } + + while(!shutdown) + { + // This implements the execution model algorithm + retWaitStatus = wait_event_interruptible(pSchedContext->mcWaitQueue, + test_bit(MC_POST_EVENT_MASK, &pSchedContext->mcEventFlag) || + test_bit(MC_SUSPEND_EVENT_MASK, &pSchedContext->mcEventFlag)); + + if(retWaitStatus == -ERESTARTSYS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: wait_event_interruptible returned -ERESTARTSYS", __func__); + VOS_BUG(0); + } + clear_bit(MC_POST_EVENT_MASK, &pSchedContext->mcEventFlag); + + while(1) + { + // Check if MC needs to shutdown + if(test_bit(MC_SHUTDOWN_EVENT_MASK, &pSchedContext->mcEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: MC thread signaled to shutdown", __func__); + shutdown = VOS_TRUE; + /* Check for any Suspend Indication */ + if(test_bit(MC_SUSPEND_EVENT_MASK, &pSchedContext->mcEventFlag)) + { + clear_bit(MC_SUSPEND_EVENT_MASK, &pSchedContext->mcEventFlag); + + /* Unblock anyone waiting on suspend */ + complete(&pHddCtx->mc_sus_event_var); + } + break; + } + + // Check the SYS queue first + if (!vos_is_mq_empty(&pSchedContext->sysMcMq)) + { + // Service the SYS message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS SYS MC Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->sysMcMq); + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + vStatus = sysMcProcessMsg(pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing SYS message",__func__); + } + //return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + // Check the WDA queue + if (!vos_is_mq_empty(&pSchedContext->wdaMcMq)) + { + // Service the WDA message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS WDA MC Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->wdaMcMq); + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + vStatus = WDA_McProcessMsg( pSchedContext->pVContext, pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing WDA message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + // Check the PE queue + if (!vos_is_mq_empty(&pSchedContext->peMcMq)) + { + // Service the PE message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS PE MC Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->peMcMq); + if (NULL == pMsgWrapper) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + + /* Need some optimization*/ + pMacContext = vos_get_context(VOS_MODULE_ID_PE, pSchedContext->pVContext); + if (NULL == pMacContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "MAC Context not ready yet"); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + + macStatus = peProcessMessages( pMacContext, (tSirMsgQ*)pMsgWrapper->pVosMsg); + if (eSIR_SUCCESS != macStatus) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing PE message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + /** Check the SME queue **/ + if (!vos_is_mq_empty(&pSchedContext->smeMcMq)) + { + /* Service the SME message queue */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS SME MC Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->smeMcMq); + if (NULL == pMsgWrapper) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + + /* Need some optimization*/ + pMacContext = vos_get_context(VOS_MODULE_ID_SME, pSchedContext->pVContext); + if (NULL == pMacContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "MAC Context not ready yet"); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + + vStatus = sme_ProcessMsg( (tHalHandle)pMacContext, pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing SME message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + /** Check the TL queue **/ + if (!vos_is_mq_empty(&pSchedContext->tlMcMq)) + { + // Service the TL message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + ("Servicing the VOS TL MC Message queue")); + pMsgWrapper = vos_mq_get(&pSchedContext->tlMcMq); + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + vStatus = WLANTL_McProcessMsg( pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing TL message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + /* Check for any Suspend Indication */ + if(test_bit(MC_SUSPEND_EVENT_MASK, &pSchedContext->mcEventFlag)) + { + clear_bit(MC_SUSPEND_EVENT_MASK, &pSchedContext->mcEventFlag); + spin_lock(&pSchedContext->McThreadLock); + + /* Mc Thread Suspended */ + complete(&pHddCtx->mc_sus_event_var); + + INIT_COMPLETION(pSchedContext->ResumeMcEvent); + spin_unlock(&pSchedContext->McThreadLock); + + /* Wait foe Resume Indication */ + wait_for_completion_interruptible(&pSchedContext->ResumeMcEvent); + } + break; //All queues are empty now + } // while message loop processing + } // while TRUE + // If we get here the MC thread must exit + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: MC Thread exiting!!!!", __func__); + complete_and_exit(&pSchedContext->McShutdown, 0); +} /* VosMCThread() */ + +v_BOOL_t isWDresetInProgress(void) +{ + if(gpVosWatchdogContext!=NULL) + { + return gpVosWatchdogContext->resetInProgress; + } + else + { + return FALSE; + } +} +/*--------------------------------------------------------------------------- + \brief VosWdThread() - The VOSS Watchdog thread + The \a VosWdThread() is the Watchdog thread: + \param Arg - pointer to the global vOSS Sched Context + \return Thread exit code + \sa VosMcThread() + -------------------------------------------------------------------------*/ +static int +VosWDThread +( + void * Arg +) +{ + pVosWatchdogContext pWdContext = (pVosWatchdogContext)Arg; + int retWaitStatus = 0; + v_BOOL_t shutdown = VOS_FALSE; + int count = 0; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + set_user_nice(current, -3); + + if (Arg == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Bad Args passed", __func__); + return 0; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) + daemonize("WD_Thread"); +#endif + + /* + ** Ack back to the context from which the Watchdog thread has been + ** created. + */ + complete(&pWdContext->WdStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Watchdog Thread %d (%s) starting up",__func__, current->pid, current->comm); + + while(!shutdown) + { + // This implements the Watchdog execution model algorithm + retWaitStatus = wait_event_interruptible(pWdContext->wdWaitQueue, + test_bit(WD_POST_EVENT_MASK, &pWdContext->wdEventFlag)); + if(retWaitStatus == -ERESTARTSYS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: wait_event_interruptible returned -ERESTARTSYS", __func__); + break; + } + clear_bit(WD_POST_EVENT_MASK, &pWdContext->wdEventFlag); + while(1) + { + /* Check for any Active Entry Points + * If active, delay SSR until no entry point is active or + * delay until count is decremented to ZERO + */ + count = MAX_SSR_WAIT_ITERATIONS; + while (count) + { + if (!atomic_read(&ssr_protect_entry_count)) + { + /* no external threads are executing */ + break; + } + /* at least one external thread is executing */ + if (--count) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Waiting for active entry points to exit", __func__); + msleep(SSR_WAIT_SLEEP_TIME); + } + } + /* at least one external thread is executing */ + if (!count) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Continuing SSR when %d Entry points are still active", + __func__, atomic_read(&ssr_protect_entry_count)); + } + // Check if Watchdog needs to shutdown + if(test_bit(WD_SHUTDOWN_EVENT_MASK, &pWdContext->wdEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Watchdog thread signaled to shutdown", __func__); + + clear_bit(WD_SHUTDOWN_EVENT_MASK, &pWdContext->wdEventFlag); + shutdown = VOS_TRUE; + break; + } + /* subsystem restart: shutdown event handler */ + else if(test_bit(WD_WLAN_SHUTDOWN_EVENT_MASK, &pWdContext->wdEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Watchdog thread signaled to perform WLAN shutdown",__func__); + clear_bit(WD_WLAN_SHUTDOWN_EVENT_MASK, &pWdContext->wdEventFlag); + + //Perform WLAN shutdown + if(!pWdContext->resetInProgress) + { + pWdContext->resetInProgress = true; + vosStatus = hdd_wlan_shutdown(); + + if (! VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to shutdown WLAN",__func__); + VOS_ASSERT(0); + goto err_reset; + } + } + } + /* subsystem restart: re-init event handler */ + else if(test_bit(WD_WLAN_REINIT_EVENT_MASK, &pWdContext->wdEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Watchdog thread signaled to perform WLAN re-init",__func__); + clear_bit(WD_WLAN_REINIT_EVENT_MASK, &pWdContext->wdEventFlag); + + //Perform WLAN re-init + if(!pWdContext->resetInProgress) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Trying to do WLAN re-init when it is not shutdown !!",__func__); + } + vosStatus = hdd_wlan_re_init(NULL); + + if (! VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to re-init WLAN",__func__); + VOS_ASSERT(0); + goto err_reset; + } + pWdContext->resetInProgress = false; + } + else + { + //Unnecessary wakeup - Should never happen!! + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Watchdog thread woke up unnecessarily",__func__); + } + break; + } // while message loop processing + } // while shutdown + + // If we get here the Watchdog thread must exit + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Watchdog Thread exiting !!!!", __func__); + complete_and_exit(&pWdContext->WdShutdown, 0); + +err_reset: + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Watchdog Thread Failed to Reset, Exiting!!!!", __func__); + return 0; + +} /* VosMCThread() */ + +/*--------------------------------------------------------------------------- + \brief VosTXThread() - The VOSS Main Tx thread + The \a VosTxThread() is the VOSS main controller thread: + \param Arg - pointer to the global vOSS Sched Context + + \return Thread exit code + \sa VosTxThread() + -------------------------------------------------------------------------*/ +static int VosTXThread ( void * Arg ) +{ + pVosSchedContext pSchedContext = (pVosSchedContext)Arg; + pVosMsgWrapper pMsgWrapper = NULL; + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + int retWaitStatus = 0; + v_BOOL_t shutdown = VOS_FALSE; + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + + set_user_nice(current, -1); + +#ifdef WLAN_FEATURE_11AC_HIGH_TP + set_wake_up_idle(true); +#endif + + if (Arg == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s Bad Args passed", __func__); + return 0; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) + daemonize("TX_Thread"); +#endif + + /* + ** Ack back to the context from which the main controller thread has been + ** created. + */ + complete(&pSchedContext->TxStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: TX Thread %d (%s) starting up!",__func__, current->pid, current->comm); + + /* Get the Global VOSS Context */ + 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 0; + } + + /* Get the HDD context */ + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return 0; + } + + + while(!shutdown) + { + // This implements the execution model algorithm + retWaitStatus = wait_event_interruptible(pSchedContext->txWaitQueue, + test_bit(TX_POST_EVENT_MASK, &pSchedContext->txEventFlag) || + test_bit(TX_SUSPEND_EVENT_MASK, &pSchedContext->txEventFlag)); + + + if(retWaitStatus == -ERESTARTSYS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: wait_event_interruptible returned -ERESTARTSYS", __func__); + break; + } + clear_bit(TX_POST_EVENT_MASK, &pSchedContext->txEventFlag); + + while(1) + { + if(test_bit(TX_SHUTDOWN_EVENT_MASK, &pSchedContext->txEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: TX thread signaled to shutdown", __func__); + shutdown = VOS_TRUE; + /* Check for any Suspend Indication */ + if(test_bit(TX_SUSPEND_EVENT_MASK, &pSchedContext->txEventFlag)) + { + clear_bit(TX_SUSPEND_EVENT_MASK, &pSchedContext->txEventFlag); + + /* Unblock anyone waiting on suspend */ + complete(&pHddCtx->tx_sus_event_var); + } + break; + } + // Check the SYS queue first + if (!vos_is_mq_empty(&pSchedContext->sysTxMq)) + { + // Service the SYS message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS SYS TX Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->sysTxMq); + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + vStatus = sysTxProcessMsg( pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing TX SYS message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + // Check now the TL queue + if (!vos_is_mq_empty(&pSchedContext->tlTxMq)) + { + // Service the TL message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS TL TX Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->tlTxMq); + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + vStatus = WLANTL_TxProcessMsg( pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing TX TL message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + + /* Check for any Suspend Indication */ + if(test_bit(TX_SUSPEND_EVENT_MASK, &pSchedContext->txEventFlag)) + { + clear_bit(TX_SUSPEND_EVENT_MASK, &pSchedContext->txEventFlag); + spin_lock(&pSchedContext->TxThreadLock); + + /* Tx Thread Suspended */ + complete(&pHddCtx->tx_sus_event_var); + + INIT_COMPLETION(pSchedContext->ResumeTxEvent); + spin_unlock(&pSchedContext->TxThreadLock); + + /* Wait foe Resume Indication */ + wait_for_completion_interruptible(&pSchedContext->ResumeTxEvent); + } + + break; //All queues are empty now + } // while message loop processing + } // while TRUE + // If we get here the TX thread must exit + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: TX Thread exiting!!!!", __func__); + complete_and_exit(&pSchedContext->TxShutdown, 0); +} /* VosTxThread() */ + +/*--------------------------------------------------------------------------- + \brief VosRXThread() - The VOSS Main Rx thread + The \a VosRxThread() is the VOSS Rx controller thread: + \param Arg - pointer to the global vOSS Sched Context + + \return Thread exit code + \sa VosRxThread() + -------------------------------------------------------------------------*/ + +static int VosRXThread ( void * Arg ) +{ + pVosSchedContext pSchedContext = (pVosSchedContext)Arg; + pVosMsgWrapper pMsgWrapper = NULL; + int retWaitStatus = 0; + v_BOOL_t shutdown = VOS_FALSE; + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = NULL; + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + + set_user_nice(current, -1); + +#ifdef WLAN_FEATURE_11AC_HIGH_TP + set_wake_up_idle(true); +#endif + + if (Arg == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s Bad Args passed", __func__); + return 0; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) + daemonize("RX_Thread"); +#endif + + /* + ** Ack back to the context from which the main controller thread has been + ** created. + */ + complete(&pSchedContext->RxStartEvent); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: RX Thread %d (%s) starting up!",__func__, current->pid, current->comm); + + /* Get the Global VOSS Context */ + 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 0; + } + + /* Get the HDD context */ + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + if(!pHddCtx) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); + return 0; + } + + while(!shutdown) + { + // This implements the execution model algorithm + retWaitStatus = wait_event_interruptible(pSchedContext->rxWaitQueue, + test_bit(RX_POST_EVENT_MASK, &pSchedContext->rxEventFlag) || + test_bit(RX_SUSPEND_EVENT_MASK, &pSchedContext->rxEventFlag)); + + + if(retWaitStatus == -ERESTARTSYS) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: wait_event_interruptible returned -ERESTARTSYS", __func__); + break; + } + clear_bit(RX_POST_EVENT_MASK, &pSchedContext->rxEventFlag); + + while(1) + { + if(test_bit(RX_SHUTDOWN_EVENT_MASK, &pSchedContext->rxEventFlag)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: RX thread signaled to shutdown", __func__); + shutdown = VOS_TRUE; + /* Check for any Suspend Indication */ + if(test_bit(RX_SUSPEND_EVENT_MASK, &pSchedContext->rxEventFlag)) + { + clear_bit(RX_SUSPEND_EVENT_MASK, &pSchedContext->rxEventFlag); + + /* Unblock anyone waiting on suspend */ + complete(&pHddCtx->rx_sus_event_var); + } + break; + } + + + // Check the SYS queue first + if (!vos_is_mq_empty(&pSchedContext->sysRxMq)) + { + // Service the SYS message queue + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Servicing the VOS SYS RX Message queue",__func__); + pMsgWrapper = vos_mq_get(&pSchedContext->sysRxMq); + if (pMsgWrapper == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", __func__); + VOS_ASSERT(0); + break; + } + vStatus = sysRxProcessMsg( pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Issue Processing TX SYS message",__func__); + } + // return message to the Core + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + continue; + } + + /* Check for any Suspend Indication */ + if(test_bit(RX_SUSPEND_EVENT_MASK, &pSchedContext->rxEventFlag)) + { + clear_bit(RX_SUSPEND_EVENT_MASK, &pSchedContext->rxEventFlag); + spin_lock(&pSchedContext->RxThreadLock); + + /* Rx Thread Suspended */ + complete(&pHddCtx->rx_sus_event_var); + + INIT_COMPLETION(pSchedContext->ResumeRxEvent); + spin_unlock(&pSchedContext->RxThreadLock); + + /* Wait for Resume Indication */ + wait_for_completion_interruptible(&pSchedContext->ResumeRxEvent); + } + + break; //All queues are empty now + } // while message loop processing + } // while TRUE + // If we get here the RX thread must exit + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: RX Thread exiting!!!!", __func__); + complete_and_exit(&pSchedContext->RxShutdown, 0); +} /* VosRxThread() */ + +#ifdef QCA_CONFIG_SMP +/*--------------------------------------------------------------------------- + \brief vos_free_tlshim_pkt_freeq() - Free voss buffer free queue + The \a vos_free_tlshim_pkt_freeq() does mem free of the buffers + available in free vos buffer queue which is used for Data rx processing + from Tlshim. + \param pSchedContext - pointer to the global vOSS Sched Context + + \return Nothing + \sa vos_free_tlshim_pkt_freeq() + -------------------------------------------------------------------------*/ +void vos_free_tlshim_pkt_freeq(pVosSchedContext pSchedContext) +{ + struct VosTlshimPkt *pkt; + + spin_lock_bh(&pSchedContext->VosTlshimPktFreeQLock); + while (!list_empty(&pSchedContext->VosTlshimPktFreeQ)) { + pkt = list_entry((&pSchedContext->VosTlshimPktFreeQ)->next, + typeof(*pkt), list); + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); + vos_mem_free(pkt); + spin_lock_bh(&pSchedContext->VosTlshimPktFreeQLock); + } + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); + +} + +/*--------------------------------------------------------------------------- + \brief vos_alloc_tlshim_pkt_freeq() - Function to allocate free buffer queue + The \a vos_alloc_tlshim_pkt_freeq() allocates VOSS_MAX_TLSHIM_PKT + number of vos message buffers which are used for Rx data processing + from Tlshim. + \param pSchedContext - pointer to the global vOSS Sched Context + + \return status of memory allocation + \sa vos_alloc_tlshim_pkt_freeq() + -------------------------------------------------------------------------*/ +static VOS_STATUS vos_alloc_tlshim_pkt_freeq(pVosSchedContext pSchedContext) +{ + struct VosTlshimPkt *pkt, *tmp; + int i; + + for (i = 0; i < VOSS_MAX_TLSHIM_PKT; i++) { + pkt = vos_mem_malloc(sizeof(*pkt)); + if (!pkt) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s Vos packet allocation for tlshim thread failed", + __func__); + goto free; + } + memset(pkt, 0, sizeof(*pkt)); + list_add_tail(&pkt->list, &pSchedContext->VosTlshimPktFreeQ); + } + + return VOS_STATUS_SUCCESS; + +free: + list_for_each_entry_safe(pkt, tmp, &pSchedContext->VosTlshimPktFreeQ, list) { + list_del(&pkt->list); + vos_mem_free(pkt); + } + return VOS_STATUS_E_NOMEM; +} + +/*--------------------------------------------------------------------------- + \brief vos_free_tlshim_pkt() - API to release vos message to the freeq + The \a vos_free_tlshim_pkt() returns the vos message used for Rx data + to the free queue. + \param pSchedContext - pointer to the global vOSS Sched Context + \param pkt - Vos message buffer to be returned to free queue. + + \return Nothing + \sa vos_free_tlshim_pkt() + -------------------------------------------------------------------------*/ +void vos_free_tlshim_pkt(pVosSchedContext pSchedContext, + struct VosTlshimPkt *pkt) +{ + memset(pkt, 0, sizeof(*pkt)); + spin_lock_bh(&pSchedContext->VosTlshimPktFreeQLock); + list_add_tail(&pkt->list, &pSchedContext->VosTlshimPktFreeQ); + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); +} + +/*--------------------------------------------------------------------------- + \brief vos_alloc_tlshim_pkt() - API to return next available vos message + The \a vos_alloc_tlshim_pkt() returns next available vos message buffer + used for Rx Data processing. + \param pSchedContext - pointer to the global vOSS Sched Context + + \return pointer to vos message buffer + \sa vos_alloc_tlshim_pkt() + -------------------------------------------------------------------------*/ +struct VosTlshimPkt *vos_alloc_tlshim_pkt(pVosSchedContext pSchedContext) +{ + struct VosTlshimPkt *pkt; + + spin_lock_bh(&pSchedContext->VosTlshimPktFreeQLock); + if (list_empty(&pSchedContext->VosTlshimPktFreeQ)) { + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); + return NULL; + } + pkt = list_first_entry(&pSchedContext->VosTlshimPktFreeQ, + struct VosTlshimPkt, list); + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->VosTlshimPktFreeQLock); + return pkt; +} + +/*--------------------------------------------------------------------------- + \brief vos_indicate_rxpkt() - API to Indicate rx data packet + The \a vos_indicate_rxpkt() enqueues the rx packet onto tlshimRxQueue + and notifies VosTlshimRxThread(). + \param Arg - pointer to the global vOSS Sched Context + \param pkt - Vos data message buffer + + \return Nothing + \sa vos_indicate_rxpkt() + -------------------------------------------------------------------------*/ +void vos_indicate_rxpkt(pVosSchedContext pSchedContext, + struct VosTlshimPkt *pkt) +{ + spin_lock_bh(&pSchedContext->TlshimRxQLock); + list_add_tail(&pkt->list, &pSchedContext->tlshimRxQueue); + spin_unlock_bh(&pSchedContext->TlshimRxQLock); + set_bit(RX_POST_EVENT_MASK, &pSchedContext->tlshimRxEvtFlg); + wake_up_interruptible(&pSchedContext->tlshimRxWaitQueue); +} + +/*--------------------------------------------------------------------------- + \brief vos_drop_rxpkt_by_staid() - API to drop pending Rx packets for a sta + The \a vos_drop_rxpkt_by_staid() drops queued packets for a station, to drop + all the pending packets the caller has to send WLAN_MAX_STA_COUNT as staId. + \param pSchedContext - pointer to the global vOSS Sched Context + \param staId - Station Id + + \return Nothing + \sa vos_drop_rxpkt_by_staid() + -------------------------------------------------------------------------*/ +void vos_drop_rxpkt_by_staid(pVosSchedContext pSchedContext, u_int16_t staId) +{ + struct list_head local_list; + struct VosTlshimPkt *pkt, *tmp; + adf_nbuf_t buf, next_buf; + + INIT_LIST_HEAD(&local_list); + spin_lock_bh(&pSchedContext->TlshimRxQLock); + if (list_empty(&pSchedContext->tlshimRxQueue)) { + spin_unlock_bh(&pSchedContext->TlshimRxQLock); + return; + } + list_for_each_entry_safe(pkt, tmp, &pSchedContext->tlshimRxQueue, list) { + if (pkt->staId == staId || staId == WLAN_MAX_STA_COUNT) + list_move_tail(&pkt->list, &local_list); + } + spin_unlock_bh(&pSchedContext->TlshimRxQLock); + + list_for_each_entry_safe(pkt, tmp, &local_list, list) { + list_del(&pkt->list); + buf = pkt->Rxpkt; + while (buf) { + next_buf = adf_nbuf_queue_next(buf); + adf_nbuf_free(buf); + buf = next_buf; + } + vos_free_tlshim_pkt(pSchedContext, pkt); + } +} + +/*--------------------------------------------------------------------------- + \brief vos_rx_from_queue() - Function to process pending Rx packets + The \a vos_rx_from_queue() traverses the pending buffer list and calling + the callback. This callback would essentially send the packet to HDD. + \param pSchedContext - pointer to the global vOSS Sched Context + + \return Nothing + \sa vos_rx_from_queue() + -------------------------------------------------------------------------*/ +static void vos_rx_from_queue(pVosSchedContext pSchedContext) +{ + struct VosTlshimPkt *pkt; + u_int16_t sta_id; + + spin_lock_bh(&pSchedContext->TlshimRxQLock); + while (!list_empty(&pSchedContext->tlshimRxQueue)) { + pkt = list_first_entry(&pSchedContext->tlshimRxQueue, + struct VosTlshimPkt, list); + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->TlshimRxQLock); + sta_id = pkt->staId; + pkt->callback(pkt->context, pkt->Rxpkt, sta_id); + vos_free_tlshim_pkt(pSchedContext, pkt); + spin_lock_bh(&pSchedContext->TlshimRxQLock); + } + spin_unlock_bh(&pSchedContext->TlshimRxQLock); +} + +/*--------------------------------------------------------------------------- + \brief VosTlshimRxThread() - The VOSS Main Tlshim Rx thread + The \a VosTlshimRxThread() is the thread for Tlshim Data packet processing. + \param Arg - pointer to the global vOSS Sched Context + + \return Thread exit code + \sa VosTlshimRxThread() + -------------------------------------------------------------------------*/ +static int VosTlshimRxThread(void *arg) +{ + pVosSchedContext pSchedContext = (pVosSchedContext)arg; + unsigned long pref_cpu = 0; + bool shutdown = false; + int status, i; + + set_user_nice(current, -1); +#ifdef MSM_PLATFORM + set_wake_up_idle(true); +#endif + + /* Find the available cpu core other than cpu 0 and + * bind the thread */ + for_each_online_cpu(i) { + if (i == 0) + continue; + pref_cpu = i; + break; + } + if (pref_cpu != 0 && (!vos_set_cpus_allowed_ptr(current, pref_cpu))) + affine_cpu = pref_cpu; + + if (!arg) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Bad Args passed", __func__); + return 0; + } + + complete(&pSchedContext->TlshimRxStartEvent); + + while (!shutdown) { + status = wait_event_interruptible(pSchedContext->tlshimRxWaitQueue, + test_bit(RX_POST_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg) || + test_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg)); + if (status == -ERESTARTSYS) + break; + + clear_bit(RX_POST_EVENT_MASK, &pSchedContext->tlshimRxEvtFlg); + while (true) { + if (test_bit(RX_SHUTDOWN_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg)) { + clear_bit(RX_SHUTDOWN_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg); + if (test_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg)) { + clear_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg); + complete(&pSchedContext->SuspndTlshimRxEvent); + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Shutting down tl shim Tlshim rx thread", __func__); + shutdown = true; + break; + } + vos_rx_from_queue(pSchedContext); + + if (test_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg)) { + clear_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->tlshimRxEvtFlg); + spin_lock(&pSchedContext->TlshimRxThreadLock); + complete(&pSchedContext->SuspndTlshimRxEvent); + INIT_COMPLETION(pSchedContext->ResumeTlshimRxEvent); + spin_unlock(&pSchedContext->TlshimRxThreadLock); + wait_for_completion_interruptible( + &pSchedContext->ResumeTlshimRxEvent); + } + break; + } + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Exiting VOSS Tlshim rx thread", __func__); + complete_and_exit(&pSchedContext->TlshimRxShutdown, 0); +} +#endif + +/*--------------------------------------------------------------------------- + \brief vos_sched_close() - Close the vOSS Scheduler + The \a vos_sched_closes() function closes the vOSS Scheduler + Upon successful closing: + - All the message queues are flushed + - The Main Controller thread is closed + - The Tx thread is closed + + \param pVosContext - pointer to the global vOSS Context + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + VOS_STATUS_E_INVAL - Invalid parameter passed to the scheduler Open + function + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + \sa vos_sched_close() +---------------------------------------------------------------------------*/ +VOS_STATUS vos_sched_close ( v_PVOID_t pVosContext ) +{ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: invoked", __func__); + if (gpVosSchedContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosSchedContext == NULL",__func__); + return VOS_STATUS_E_FAILURE; + } + + // shut down MC Thread + set_bit(MC_SHUTDOWN_EVENT_MASK, &gpVosSchedContext->mcEventFlag); + set_bit(MC_POST_EVENT_MASK, &gpVosSchedContext->mcEventFlag); + wake_up_interruptible(&gpVosSchedContext->mcWaitQueue); + //Wait for MC to exit + wait_for_completion(&gpVosSchedContext->McShutdown); + gpVosSchedContext->McThread = 0; + + // shut down TX Thread + set_bit(TX_SHUTDOWN_EVENT_MASK, &gpVosSchedContext->txEventFlag); + set_bit(TX_POST_EVENT_MASK, &gpVosSchedContext->txEventFlag); + wake_up_interruptible(&gpVosSchedContext->txWaitQueue); + //Wait for TX to exit + wait_for_completion(&gpVosSchedContext->TxShutdown); + gpVosSchedContext->TxThread = 0; + + // shut down RX Thread + set_bit(RX_SHUTDOWN_EVENT_MASK, &gpVosSchedContext->rxEventFlag); + set_bit(RX_POST_EVENT_MASK, &gpVosSchedContext->rxEventFlag); + wake_up_interruptible(&gpVosSchedContext->rxWaitQueue); + //Wait for RX to exit + wait_for_completion(&gpVosSchedContext->RxShutdown); + gpVosSchedContext->RxThread = 0; + + //Clean up message queues of TX and MC thread + vos_sched_flush_mc_mqs(gpVosSchedContext); + vos_sched_flush_tx_mqs(gpVosSchedContext); + vos_sched_flush_rx_mqs(gpVosSchedContext); + + //Deinit all the queues + vos_sched_deinit_mqs(gpVosSchedContext); + +#ifdef QCA_CONFIG_SMP + vos_lock_destroy(&gpVosSchedContext->affinity_lock); + // Shut down Tlshim Rx thread + set_bit(RX_SHUTDOWN_EVENT_MASK, &gpVosSchedContext->tlshimRxEvtFlg); + set_bit(RX_POST_EVENT_MASK, &gpVosSchedContext->tlshimRxEvtFlg); + wake_up_interruptible(&gpVosSchedContext->tlshimRxWaitQueue); + wait_for_completion(&gpVosSchedContext->TlshimRxShutdown); + gpVosSchedContext->TlshimRxThread = NULL; + vos_drop_rxpkt_by_staid(gpVosSchedContext, WLAN_MAX_STA_COUNT); + vos_free_tlshim_pkt_freeq(gpVosSchedContext); + unregister_hotcpu_notifier(&vos_cpu_hotplug_notifier); +#endif + return VOS_STATUS_SUCCESS; +} /* vox_sched_close() */ + +VOS_STATUS vos_watchdog_close ( v_PVOID_t pVosContext ) +{ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: vos_watchdog closing now", __func__); + if (gpVosWatchdogContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosWatchdogContext is NULL",__func__); + return VOS_STATUS_E_FAILURE; + } + set_bit(WD_SHUTDOWN_EVENT_MASK, &gpVosWatchdogContext->wdEventFlag); + set_bit(WD_POST_EVENT_MASK, &gpVosWatchdogContext->wdEventFlag); + wake_up_interruptible(&gpVosWatchdogContext->wdWaitQueue); + //Wait for Watchdog thread to exit + wait_for_completion(&gpVosWatchdogContext->WdShutdown); + return VOS_STATUS_SUCCESS; +} /* vos_watchdog_close() */ + +/*--------------------------------------------------------------------------- + \brief vos_sched_init_mqs: Initialize the vOSS Scheduler message queues + The \a vos_sched_init_mqs() function initializes the vOSS Scheduler + message queues. + \param pVosSchedContext - pointer to the Scheduler Context. + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + + \sa vos_sched_init_mqs() + -------------------------------------------------------------------------*/ +VOS_STATUS vos_sched_init_mqs ( pVosSchedContext pSchedContext ) +{ + VOS_STATUS vStatus = VOS_STATUS_SUCCESS; + // Now intialize all the message queues + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the WDA MC Message queue",__func__); + vStatus = vos_mq_init(&pSchedContext->wdaMcMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init WDA MC Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the PE MC Message queue",__func__); + vStatus = vos_mq_init(&pSchedContext->peMcMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init PE MC Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the SME MC Message queue", __func__); + vStatus = vos_mq_init(&pSchedContext->smeMcMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init SME MC Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the TL MC Message queue",__func__); + vStatus = vos_mq_init(&pSchedContext->tlMcMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init TL MC Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the SYS MC Message queue",__func__); + vStatus = vos_mq_init(&pSchedContext->sysMcMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init SYS MC Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the TL Tx Message queue",__func__); + vStatus = vos_mq_init(&pSchedContext->tlTxMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init TL TX Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the SYS Tx Message queue",__func__); + vStatus = vos_mq_init(&pSchedContext->sysTxMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init SYS TX Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + + vStatus = vos_mq_init(&pSchedContext->sysRxMq); + if (! VOS_IS_STATUS_SUCCESS(vStatus)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to init SYS RX Message queue",__func__); + VOS_ASSERT(0); + return vStatus; + } + return VOS_STATUS_SUCCESS; +} /* vos_sched_init_mqs() */ + +/*--------------------------------------------------------------------------- + \brief vos_sched_deinit_mqs: Deinitialize the vOSS Scheduler message queues + The \a vos_sched_init_mqs() function deinitializes the vOSS Scheduler + message queues. + \param pVosSchedContext - pointer to the Scheduler Context. + \return None + \sa vos_sched_deinit_mqs() + -------------------------------------------------------------------------*/ +void vos_sched_deinit_mqs ( pVosSchedContext pSchedContext ) +{ + // Now de-intialize all message queues + // MC WDA + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the WDA MC Message queue",__func__); + vos_mq_deinit(&pSchedContext->wdaMcMq); + //MC PE + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the PE MC Message queue",__func__); + vos_mq_deinit(&pSchedContext->peMcMq); + //MC SME + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the SME MC Message queue",__func__); + vos_mq_deinit(&pSchedContext->smeMcMq); + //MC TL + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the TL MC Message queue",__func__); + vos_mq_deinit(&pSchedContext->tlMcMq); + //MC SYS + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the SYS MC Message queue",__func__); + vos_mq_deinit(&pSchedContext->sysMcMq); + + //Tx TL + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the TL Tx Message queue",__func__); + vos_mq_deinit(&pSchedContext->tlTxMq); + + //Tx SYS + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: DeInitializing the SYS Tx Message queue",__func__); + vos_mq_deinit(&pSchedContext->sysTxMq); + + //Rx SYS + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: DeInitializing the SYS Rx Message queue",__func__); + vos_mq_deinit(&pSchedContext->sysRxMq); +} /* vos_sched_deinit_mqs() */ + +/*------------------------------------------------------------------------- + this helper function flushes all the MC message queues + -------------------------------------------------------------------------*/ +void vos_sched_flush_mc_mqs ( pVosSchedContext pSchedContext ) +{ + pVosMsgWrapper pMsgWrapper = NULL; + pVosContextType vosCtx; + + /* + ** Here each of the MC thread MQ shall be drained and returned to the + ** Core. Before returning a wrapper to the Core, the VOS message shall be + ** freed first + */ + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + ("Flushing the MC Thread message queue") ); + + if (NULL == pSchedContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pSchedContext is NULL", __func__); + return; + } + + vosCtx = (pVosContextType)(pSchedContext->pVContext); + if (NULL == vosCtx) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vosCtx is NULL", __func__); + return; + } + + /* Flush the SYS Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->sysMcMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing MC SYS message type %d ",__func__, + pMsgWrapper->pVosMsg->type ); + sysMcFreeMsg(pSchedContext->pVContext, pMsgWrapper->pVosMsg); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + /* Flush the WDA Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->wdaMcMq) )) + { + if(pMsgWrapper->pVosMsg != NULL) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "%s: Freeing MC WDA MSG message type %d", + __func__, pMsgWrapper->pVosMsg->type ); + if (pMsgWrapper->pVosMsg->bodyptr) { + vos_mem_free((v_VOID_t*)pMsgWrapper->pVosMsg->bodyptr); + } + + pMsgWrapper->pVosMsg->bodyptr = NULL; + pMsgWrapper->pVosMsg->bodyval = 0; + pMsgWrapper->pVosMsg->type = 0; + } + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + + /* Flush the PE Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->peMcMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing MC PE MSG message type %d",__func__, + pMsgWrapper->pVosMsg->type ); + peFreeMsg(vosCtx->pMACContext, (tSirMsgQ*)pMsgWrapper->pVosMsg); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + /* Flush the SME Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->smeMcMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing MC SME MSG message type %d", __func__, + pMsgWrapper->pVosMsg->type ); + sme_FreeMsg(vosCtx->pMACContext, pMsgWrapper->pVosMsg); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + /* Flush the TL Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->tlMcMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing MC TL message type %d",__func__, + pMsgWrapper->pVosMsg->type ); + WLANTL_McFreeMsg(pSchedContext->pVContext, pMsgWrapper->pVosMsg); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } +} /* vos_sched_flush_mc_mqs() */ + +/*------------------------------------------------------------------------- + This helper function flushes all the TX message queues + ------------------------------------------------------------------------*/ +void vos_sched_flush_tx_mqs ( pVosSchedContext pSchedContext ) +{ + pVosMsgWrapper pMsgWrapper = NULL; + /* + ** Here each of the TX thread MQ shall be drained and returned to the + ** Core. Before returning a wrapper to the Core, the VOS message shall + ** be freed first + */ + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Flushing the TX Thread message queue",__func__); + + if (NULL == pSchedContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pSchedContext is NULL", __func__); + return; + } + + /* Flush the SYS Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->sysTxMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing TX SYS message type %d",__func__, + pMsgWrapper->pVosMsg->type ); + sysTxFreeMsg(pSchedContext->pVContext, pMsgWrapper->pVosMsg); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + /* Flush the TL Mq */ + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->tlTxMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing TX TL MSG message type %d",__func__, + pMsgWrapper->pVosMsg->type ); + WLANTL_TxFreeMsg(pSchedContext->pVContext, pMsgWrapper->pVosMsg); + vos_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } +} /* vos_sched_flush_tx_mqs() */ +/*------------------------------------------------------------------------- + This helper function flushes all the RX message queues + ------------------------------------------------------------------------*/ +void vos_sched_flush_rx_mqs ( pVosSchedContext pSchedContext ) +{ + pVosMsgWrapper pMsgWrapper = NULL; + /* + ** Here each of the RX thread MQ shall be drained and returned to the + ** Core. Before returning a wrapper to the Core, the VOS message shall + ** be freed first + */ + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Flushing the RX Thread message queue",__func__); + + if (NULL == pSchedContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: pSchedContext is NULL", __func__); + return; + } + + while( NULL != (pMsgWrapper = vos_mq_get(&pSchedContext->sysRxMq) )) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, + VOS_TRACE_LEVEL_INFO, + "%s: Freeing RX SYS MSG message type %d",__func__, + pMsgWrapper->pVosMsg->type ); + sysTxFreeMsg(pSchedContext->pVContext, pMsgWrapper->pVosMsg); + } + +}/* vos_sched_flush_rx_mqs() */ + +/*------------------------------------------------------------------------- + This helper function helps determine if thread id is of TX thread + ------------------------------------------------------------------------*/ +int vos_sched_is_tx_thread(int threadID) +{ + // Make sure that Vos Scheduler context has been initialized + VOS_ASSERT( NULL != gpVosSchedContext); + if (gpVosSchedContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosSchedContext == NULL",__func__); + return 0; + } + return ((gpVosSchedContext->TxThread) && (threadID == gpVosSchedContext->TxThread->pid)); +} +/*------------------------------------------------------------------------- + This helper function helps determine if thread id is of RX thread + ------------------------------------------------------------------------*/ +int vos_sched_is_rx_thread(int threadID) +{ + // Make sure that Vos Scheduler context has been initialized + VOS_ASSERT( NULL != gpVosSchedContext); + if (gpVosSchedContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosSchedContext == NULL",__func__); + return 0; + } + return ((gpVosSchedContext->RxThread) && (threadID == gpVosSchedContext->RxThread->pid)); +} +/*------------------------------------------------------------------------- + Helper function to get the scheduler context + ------------------------------------------------------------------------*/ +pVosSchedContext get_vos_sched_ctxt(void) +{ + //Make sure that Vos Scheduler context has been initialized + if (gpVosSchedContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosSchedContext == NULL",__func__); + } + return (gpVosSchedContext); +} +/*------------------------------------------------------------------------- + Helper function to get the watchdog context + ------------------------------------------------------------------------*/ +pVosWatchdogContext get_vos_watchdog_ctxt(void) +{ + //Make sure that Vos Scheduler context has been initialized + if (gpVosWatchdogContext == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: gpVosWatchdogContext == NULL",__func__); + } + return (gpVosWatchdogContext); +} +/** + @brief vos_watchdog_wlan_shutdown() + + This function is called to shutdown WLAN driver during SSR. + Adapters are disabled, and the watchdog task will be signalled + to shutdown WLAN driver. + + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_watchdog_wlan_shutdown(void) +{ + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: WLAN driver is shutting down ", __func__); + if (NULL == gpVosWatchdogContext) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Watchdog not enabled. LOGP ignored.", __func__); + return VOS_STATUS_E_FAILURE; + } + + pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL); + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Invalid HDD Context", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* Take the lock here */ + spin_lock(&gpVosWatchdogContext->wdLock); + + /* reuse the existing 'reset in progress' */ + if (gpVosWatchdogContext->resetInProgress) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Shutdown already in Progress. Ignoring signaling Watchdog", + __func__); + /* Release the lock here */ + spin_unlock(&gpVosWatchdogContext->wdLock); + return VOS_STATUS_E_FAILURE; + } + /* reuse the existing 'logp in progress', eventhough it is not + * exactly the same */ + else if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: shutdown/re-init already in Progress. Ignoring signaling Watchdog", + __func__); + /* Release the lock here */ + spin_unlock(&gpVosWatchdogContext->wdLock); + return VOS_STATUS_E_FAILURE; + } + + /* Set the flags so that all future CMD53 and Wext commands get blocked right away */ + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE); + pHddCtx->isLogpInProgress = TRUE; + + /* Release the lock here */ + spin_unlock(&gpVosWatchdogContext->wdLock); + + if ((pHddCtx->isLoadInProgress) || + (pHddCtx->isUnloadInProgress)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Load/unload in Progress. Ignoring signaling Watchdog", + __func__); + /* wcnss has crashed, and SSR has alredy been started by Kernel driver. + * So disable SSR from WLAN driver */ + hdd_set_ssr_required( HDD_SSR_DISABLED ); + return VOS_STATUS_E_FAILURE; + } + /* Update Riva Reset Statistics */ + pHddCtx->hddRivaResetStats++; +#ifdef CONFIG_HAS_EARLYSUSPEND + if(VOS_STATUS_SUCCESS != hdd_wlan_reset_initialization()) + { + VOS_ASSERT(0); + } +#endif + + set_bit(WD_WLAN_SHUTDOWN_EVENT_MASK, &gpVosWatchdogContext->wdEventFlag); + set_bit(WD_POST_EVENT_MASK, &gpVosWatchdogContext->wdEventFlag); + wake_up_interruptible(&gpVosWatchdogContext->wdWaitQueue); + + return VOS_STATUS_SUCCESS; +} + +/** + @brief vos_watchdog_wlan_re_init() + + This function is called to re-initialize WLAN driver, and this is + called when Riva SS reboots. + + @param + NONE + @return + VOS_STATUS_SUCCESS - Operation completed successfully. + VOS_STATUS_E_FAILURE - Operation failed. + +*/ +VOS_STATUS vos_watchdog_wlan_re_init(void) +{ + /* watchdog task is still running, it is not closed in shutdown */ + set_bit(WD_WLAN_REINIT_EVENT_MASK, &gpVosWatchdogContext->wdEventFlag); + set_bit(WD_POST_EVENT_MASK, &gpVosWatchdogContext->wdEventFlag); + wake_up_interruptible(&gpVosWatchdogContext->wdWaitQueue); + + return VOS_STATUS_SUCCESS; +} + +/** + * vos_ssr_protect_init() - initialize ssr protection debug functionality + * + * Return: + * void + */ +void vos_ssr_protect_init(void) +{ + int i = 0; + + spin_lock_init(&ssr_protect_lock); + + while (i < MAX_SSR_PROTECT_LOG) { + ssr_protect_log[i].func = NULL; + ssr_protect_log[i].free = true; + ssr_protect_log[i].pid = 0; + i++; + } +} + +/** + * vos_print_external_threads() - print external threads stuck in driver + * + * Return: + * void + */ + +static void vos_print_external_threads(void) +{ + int i = 0; + unsigned long irq_flags; + + spin_lock_irqsave(&ssr_protect_lock, irq_flags); + + while (i < MAX_SSR_PROTECT_LOG) { + if (!ssr_protect_log[i].free) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "PID %d is stuck at %s", ssr_protect_log[i].pid, + ssr_protect_log[i].func); + } + i++; + } + + spin_unlock_irqrestore(&ssr_protect_lock, irq_flags); +} + + +/** + @brief vos_ssr_protect() + + This function is called to keep track of active driver entry points + + @param + caller_func - Name of calling function. + @return + void +*/ +void vos_ssr_protect(const char *caller_func) +{ + int count; + int i = 0; + bool status = false; + unsigned long irq_flags; + + count = atomic_inc_return(&ssr_protect_entry_count); + + spin_lock_irqsave(&ssr_protect_lock, irq_flags); + + while (i < MAX_SSR_PROTECT_LOG) { + if (ssr_protect_log[i].free) { + ssr_protect_log[i].func = caller_func; + ssr_protect_log[i].free = false; + ssr_protect_log[i].pid = current->pid; + status = true; + break; + } + i++; + } + + spin_unlock_irqrestore(&ssr_protect_lock, irq_flags); + + if (!status) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Could not track PID %d call %s: log is full", + current->pid, caller_func); + +} + +/** + @brief vos_ssr_unprotect() + + @param + caller_func - Name of calling function. + @return + void +*/ +void vos_ssr_unprotect(const char *caller_func) +{ + int count; + int i = 0; + bool status = false; + unsigned long irq_flags; + + count = atomic_dec_return(&ssr_protect_entry_count); + + spin_lock_irqsave(&ssr_protect_lock, irq_flags); + + while (i < MAX_SSR_PROTECT_LOG) { + if (!ssr_protect_log[i].free) { + if ((ssr_protect_log[i].pid == current->pid) && + !strcmp(ssr_protect_log[i].func, caller_func)) { + ssr_protect_log[i].func = NULL; + ssr_protect_log[i].free = true; + ssr_protect_log[i].pid = 0; + status = true; + break; + } + } + i++; + } + + spin_unlock_irqrestore(&ssr_protect_lock, irq_flags); + + if (!status) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Untracked call %s", caller_func); +} + +/** + @brief vos_is_ssr_ready() + + This function will check if the calling execution can + proceed with SSR. + + @param + caller_func - Name of calling function. + @return + true or false +*/ +bool vos_is_ssr_ready(const char *caller_func) +{ + int count = MAX_SSR_WAIT_ITERATIONS; + + while (count) { + + if (!atomic_read(&ssr_protect_entry_count)) + break; + + if (--count) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Waiting for active entry points to exit", __func__); + msleep(SSR_WAIT_SLEEP_TIME); + } + } + /* at least one external thread is executing */ + if (!count) { + vos_print_external_threads(); + return false; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Allowing SSR for %s", caller_func); + + return true; +} + +/** + * vos_get_gfp_flags(): get GFP flags + * + * Based on the scheduled context, return GFP flags + * Return: gfp flags + */ +int vos_get_gfp_flags(void) +{ + int flags = GFP_KERNEL; + + if (in_interrupt() || in_atomic() || irqs_disabled()) + flags = GFP_ATOMIC; + + return flags; +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h new file mode 100644 index 000000000000..ba2792de7d5e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h @@ -0,0 +1,680 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __VOS_SCHED_H ) +#define __VOS_SCHED_H + +/**========================================================================= + + \file vos_sched.h + + \brief virtual Operating System Servies (vOSS) + + Definitions for some of the internal data type that is internally used + by the vOSS scheduler on Windows Mobile. + + This file defines a vOSS message queue on Win Mobile and give some + insights about how the scheduler implements the execution model supported + by vOSS. + + ========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 09/15/08 lac Removed hardcoded #define for VOS_TRACE. + 06/12/08 hba Created module. + +===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include "i_vos_types.h" +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif +#include +#include +#include + +#define TX_POST_EVENT_MASK 0x001 +#define TX_SUSPEND_EVENT_MASK 0x002 +#define MC_POST_EVENT_MASK 0x001 +#define MC_SUSPEND_EVENT_MASK 0x002 +#define RX_POST_EVENT_MASK 0x001 +#define RX_SUSPEND_EVENT_MASK 0x002 +#define TX_SHUTDOWN_EVENT_MASK 0x010 +#define MC_SHUTDOWN_EVENT_MASK 0x010 +#define RX_SHUTDOWN_EVENT_MASK 0x010 +#define WD_POST_EVENT_MASK 0x001 +#define WD_SHUTDOWN_EVENT_MASK 0x002 +#define WD_CHIP_RESET_EVENT_MASK 0x004 +#define WD_WLAN_SHUTDOWN_EVENT_MASK 0x008 +#define WD_WLAN_REINIT_EVENT_MASK 0x010 + + + +/* +** Maximum number of messages in the system +** These are buffers to account for all current messages +** with some accounting of what we think is a +** worst-case scenario. Must be able to handle all +** incoming frames, as well as overhead for internal +** messaging +** +** Increased to 8000 to handle more RX frames +*/ +#define VOS_CORE_MAX_MESSAGES 8000 + +#ifdef QCA_CONFIG_SMP +/* +** Maximum number of vos messages to be allocated for +** Tlshim Rx thread. +*/ +#define VOSS_MAX_TLSHIM_PKT 4000 + +typedef void (*vos_tlshim_cb) (void *context, void *rxpkt, u_int16_t staid); +#endif + +/* +** vOSS Message queue definition. +*/ +typedef struct _VosMqType +{ + /* Lock use to synchronize access to this message queue */ + spinlock_t mqLock; + + /* List of vOS Messages waiting on this queue */ + struct list_head mqList; + +} VosMqType, *pVosMqType; + +#ifdef QCA_CONFIG_SMP +/* +** VOSS message wrapper for data rx from Tlshim. +*/ +typedef struct VosTlshimPkt +{ + struct list_head list; + + /* Tlshim context */ + void *context; + + /* Rx skb */ + void *Rxpkt; + + /* Station id to which this packet is destined */ + u_int16_t staId; + + /* Call back to further send this packet to tlshim layer */ + vos_tlshim_cb callback; + +} *pVosTlshimPkt; +#endif + +/* +** vOSS Scheduler context +** The scheduler context contains the following: +** ** the messages queues +** ** the handle to the tread +** ** pointer to the events that gracefully shutdown the MC and Tx threads +** +*/ +typedef struct _VosSchedContext +{ + /* Place holder to the VOSS Context */ + v_PVOID_t pVContext; + /* WDA Message queue on the Main thread*/ + VosMqType wdaMcMq; + + + + /* PE Message queue on the Main thread*/ + VosMqType peMcMq; + + /* SME Message queue on the Main thread*/ + VosMqType smeMcMq; + + /* TL Message queue on the Main thread */ + VosMqType tlMcMq; + + /* SYS Message queue on the Main thread */ + VosMqType sysMcMq; + + /* TL Message queue on the Tx thread */ + VosMqType tlTxMq; + + /* SYS Message queue on the Tx thread */ + VosMqType sysTxMq; + + VosMqType sysRxMq; + + /* Handle of Event for MC thread to signal startup */ + struct completion McStartEvent; + + /* Handle of Event for Tx thread to signal startup */ + struct completion TxStartEvent; + + /* Handle of Event for Rx thread to signal startup */ + struct completion RxStartEvent; + + struct task_struct* McThread; + + /* TX Thread handle */ + + struct task_struct* TxThread; + + /* RX Thread handle */ + struct task_struct* RxThread; + + + /* completion object for MC thread shutdown */ + struct completion McShutdown; + + /* completion object for Tx thread shutdown */ + struct completion TxShutdown; + + /* completion object for Rx thread shutdown */ + struct completion RxShutdown; + + /* Wait queue for MC thread */ + wait_queue_head_t mcWaitQueue; + + unsigned long mcEventFlag; + + /* Wait queue for Tx thread */ + wait_queue_head_t txWaitQueue; + + unsigned long txEventFlag; + + /* Wait queue for Rx thread */ + wait_queue_head_t rxWaitQueue; + + unsigned long rxEventFlag; + + /* Completion object to resume Mc thread */ + struct completion ResumeMcEvent; + + /* Completion object to resume Tx thread */ + struct completion ResumeTxEvent; + + /* Completion object to resume Rx thread */ + struct completion ResumeRxEvent; + + /* lock to make sure that McThread and TxThread Suspend/resume mechanism is in sync*/ + spinlock_t McThreadLock; + spinlock_t TxThreadLock; + spinlock_t RxThreadLock; +#ifdef QCA_CONFIG_SMP + spinlock_t TlshimRxThreadLock; + + /* Tlshim Rx thread handle */ + struct task_struct *TlshimRxThread; + + /* Handle of Event for Rx thread to signal startup */ + struct completion TlshimRxStartEvent; + + /* Completion object to suspend tlshim rx thread */ + struct completion SuspndTlshimRxEvent; + + /* Completion objext to resume tlshim rx thread */ + struct completion ResumeTlshimRxEvent; + + /* Completion object for Tlshim Rxthread shutdown */ + struct completion TlshimRxShutdown; + + /* Waitq for tlshim Rx thread */ + wait_queue_head_t tlshimRxWaitQueue; + + unsigned long tlshimRxEvtFlg; + + /* Rx buffer queue */ + struct list_head tlshimRxQueue; + + /* Spinlock to synchronize between tasklet and thread */ + spinlock_t TlshimRxQLock; + + /* Rx queue length */ + unsigned int TlshimRxQlen; + + /* Lock to synchronize free buffer queue access */ + spinlock_t VosTlshimPktFreeQLock; + + /* Free message queue for Tlshim Rx processing */ + struct list_head VosTlshimPktFreeQ; + + /* cpu hotplug notifier */ + struct notifier_block *cpuHotPlugNotifier; + + /* affinity lock */ + vos_lock_t affinity_lock; + + /* rx thread affinity cpu */ + unsigned long rx_thread_cpu; + + /* high throughput required */ + bool high_throughput_required; +#endif +} VosSchedContext, *pVosSchedContext; + +/* +** VOSS watchdog context +** The watchdog context contains the following: +** The messages queues and events +** The handle to the thread +** +*/ +typedef struct _VosWatchdogContext +{ + + /* Place holder to the VOSS Context */ + v_PVOID_t pVContext; + + /* Handle of Event for Watchdog thread to signal startup */ + struct completion WdStartEvent; + + /* Watchdog Thread handle */ + + struct task_struct* WdThread; + + /* completion object for Watchdog thread shutdown */ + struct completion WdShutdown; + + /* Wait queue for Watchdog thread */ + wait_queue_head_t wdWaitQueue; + + /* Event flag for events handled by Watchdog */ + unsigned long wdEventFlag; + + v_BOOL_t resetInProgress; + + /* Lock for preventing multiple reset being triggered simultaneously */ + spinlock_t wdLock; + +} VosWatchdogContext, *pVosWatchdogContext; + +/* +** vOSS Sched Msg Wrapper +** Wrapper messages so that they can be chained to their respective queue +** in the scheduler. +*/ +typedef struct _VosMsgWrapper +{ + /* Message node */ + struct list_head msgNode; + + /* the Vos message it is associated to */ + vos_msg_t *pVosMsg; + +} VosMsgWrapper, *pVosMsgWrapper; + +/** + * struct vos_log_complete - Log completion internal structure + * @is_fatal: Type is fatal or not + * @indicator: Source of bug report + * @reason_code: Reason code for bug report + * @is_report_in_progress: If bug report is in progress + * + * This structure internally stores the log related params + */ +struct vos_log_complete { + uint32_t is_fatal; + uint32_t indicator; + uint32_t reason_code; + bool is_report_in_progress; +}; + +typedef struct _VosContextType +{ + /* Messages buffers */ + vos_msg_t aMsgBuffers[VOS_CORE_MAX_MESSAGES]; + + VosMsgWrapper aMsgWrappers[VOS_CORE_MAX_MESSAGES]; + + /* Free Message queue*/ + VosMqType freeVosMq; + + /* Scheduler Context */ + VosSchedContext vosSched; + + /* Watchdog Context */ + VosWatchdogContext vosWatchdog; + + /* HDD Module Context */ + v_VOID_t *pHDDContext; + + /* TL Module Context */ + v_VOID_t *pTLContext; + + /* MAC Module Context */ + v_VOID_t *pMACContext; + +#ifndef WLAN_FEATURE_MBSSID + /* SAP Context */ + v_VOID_t *pSAPContext; +#endif + + vos_event_t ProbeEvent; + + volatile v_U8_t isLogpInProgress; + + vos_event_t wdaCompleteEvent; + + /* WDA Context */ + v_VOID_t *pWDAContext; + + v_VOID_t *pHIFContext; + + v_VOID_t *htc_ctx; + + /* + * adf_ctx will be used by adf + * while allocating dma memory + * to access dev information. + */ + adf_os_device_t adf_ctx; + + v_VOID_t *pdev_txrx_ctx; + + /* Configuration handle used to get system configuration */ + v_VOID_t *cfg_ctx; + + volatile v_U8_t isLoadUnloadInProgress; + volatile v_U8_t is_unload_in_progress; + + /* SSR re-init in progress */ + volatile v_U8_t isReInitInProgress; + + /* SSR shutdown in progress */ + v_U8_t is_shutdown_in_progress; + + bool is_wakelock_log_enabled; + uint32_t wakelock_log_level; + uint32_t connectivity_log_level; + uint32_t packet_stats_log_level; + uint32_t driver_debug_log_level; + uint32_t fw_debug_log_level; + + struct vos_log_complete log_complete; + vos_spin_lock_t bug_report_lock; +} VosContextType, *pVosContextType; + + + +/*--------------------------------------------------------------------------- + Function declarations and documenation +---------------------------------------------------------------------------*/ + +#ifdef QCA_CONFIG_SMP +int vos_sched_handle_cpu_hot_plug(void); +int vos_sched_handle_throughput_req(bool high_tput_required); + +/*--------------------------------------------------------------------------- + \brief vos_drop_rxpkt_by_staid() - API to drop pending Rx packets for a sta + The \a vos_drop_rxpkt_by_staid() drops queued packets for a station, to drop + all the pending packets the caller has to send WLAN_MAX_STA_COUNT as staId. + \param pSchedContext - pointer to the global vOSS Sched Context + \param staId - Station Id + + \return Nothing + \sa vos_drop_rxpkt_by_staid() + -------------------------------------------------------------------------*/ +void vos_drop_rxpkt_by_staid(pVosSchedContext pSchedContext, u_int16_t staId); + +/*--------------------------------------------------------------------------- + \brief vos_indicate_rxpkt() - API to Indicate rx data packet + The \a vos_indicate_rxpkt() enqueues the rx packet onto tlshimRxQueue + and notifies VosTlshimRxThread(). + \param Arg - pointer to the global vOSS Sched Context + \param pkt - Vos data message buffer + + \return Nothing + \sa vos_indicate_rxpkt() + -------------------------------------------------------------------------*/ +void vos_indicate_rxpkt(pVosSchedContext pSchedContext, + struct VosTlshimPkt *pkt); + +/*--------------------------------------------------------------------------- + \brief vos_alloc_tlshim_pkt() - API to return next available vos message + The \a vos_alloc_tlshim_pkt() returns next available vos message buffer + used for Rx Data processing. + \param pSchedContext - pointer to the global vOSS Sched Context + + \return pointer to vos message buffer + \sa vos_alloc_tlshim_pkt() + -------------------------------------------------------------------------*/ +struct VosTlshimPkt *vos_alloc_tlshim_pkt(pVosSchedContext pSchedContext); + +/*--------------------------------------------------------------------------- + \brief vos_free_tlshim_pkt() - API to release vos message to the freeq + The \a vos_free_tlshim_pkt() returns the vos message used for Rx data + to the free queue. + \param pSchedContext - pointer to the global vOSS Sched Context + \param pkt - Vos message buffer to be returned to free queue. + + \return Nothing + \sa vos_free_tlshim_pkt() + -------------------------------------------------------------------------*/ +void vos_free_tlshim_pkt(pVosSchedContext pSchedContext, + struct VosTlshimPkt *pkt); +/*--------------------------------------------------------------------------- + \brief vos_free_tlshim_pkt_freeq() - Free voss buffer free queue + The \a vos_free_tlshim_pkt_freeq() does mem free of the buffers + available in free vos buffer queue which is used for Data rx processing + from Tlshim. + \param pSchedContext - pointer to the global vOSS Sched Context + + \return Nothing + \sa vos_free_tlshim_pkt_freeq() + -------------------------------------------------------------------------*/ +void vos_free_tlshim_pkt_freeq(pVosSchedContext pSchedContext); +#else +static inline int vos_sched_handle_throughput_req( + bool high_tput_required) +{ + return 0; +} +#endif + +int vos_sched_is_tx_thread(int threadID); +int vos_sched_is_rx_thread(int threadID); +/*--------------------------------------------------------------------------- + + \brief vos_sched_open() - initialize the vOSS Scheduler + + The \a vos_sched_open() function initializes the vOSS Scheduler + Upon successful initialization: + + - All the message queues are initialized + + - The Main Controller thread is created and ready to receive and + dispatch messages. + + - The Tx thread is created and ready to receive and dispatch messages + + + \param pVosContext - pointer to the global vOSS Context + + \param pVosSchedContext - pointer to a previously allocated buffer big + enough to hold a scheduler context. + \ + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the scheduler + + VOS_STATUS_E_INVAL - Invalid parameter passed to the scheduler Open + function + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_sched_open() + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_sched_open( v_PVOID_t pVosContext, + pVosSchedContext pSchedCxt, + v_SIZE_t SchedCtxSize); + +/*--------------------------------------------------------------------------- + + \brief vos_watchdog_open() - initialize the vOSS watchdog + + The \a vos_watchdog_open() function initializes the vOSS watchdog. Upon successful + initialization, the watchdog thread is created and ready to receive and process messages. + + + \param pVosContext - pointer to the global vOSS Context + + \param pWdContext - pointer to a previously allocated buffer big + enough to hold a watchdog context. + + \return VOS_STATUS_SUCCESS - Watchdog was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the Watchdog + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the Watchdog + + VOS_STATUS_E_INVAL - Invalid parameter passed to the Watchdog Open + function + + VOS_STATUS_E_FAILURE - Failure to initialize the Watchdog/ + + \sa vos_watchdog_open() + + -------------------------------------------------------------------------*/ + +VOS_STATUS vos_watchdog_open + +( + v_PVOID_t pVosContext, + pVosWatchdogContext pWdContext, + v_SIZE_t wdCtxSize +); + +/*--------------------------------------------------------------------------- + + \brief vos_sched_close() - Close the vOSS Scheduler + + The \a vos_sched_closes() function closes the vOSS Scheduler + Upon successful closing: + + - All the message queues are flushed + + - The Main Controller thread is closed + + - The Tx thread is closed + + + \param pVosContext - pointer to the global vOSS Context + + \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + VOS_STATUS_E_INVAL - Invalid parameter passed to the scheduler Open + function + + VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa vos_sched_close() + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_sched_close( v_PVOID_t pVosContext); + +/*--------------------------------------------------------------------------- + + \brief vos_watchdog_close() - Close the vOSS Watchdog + + The \a vos_watchdog_close() function closes the vOSS Watchdog + Upon successful closing: + + - The Watchdog thread is closed + + + \param pVosContext - pointer to the global vOSS Context + + \return VOS_STATUS_SUCCESS - Watchdog was successfully initialized and + is ready to be used. + + VOS_STATUS_E_INVAL - Invalid parameter passed + + VOS_STATUS_E_FAILURE - Failure to initialize the Watchdog/ + + \sa vos_watchdog_close() + +---------------------------------------------------------------------------*/ +VOS_STATUS vos_watchdog_close ( v_PVOID_t pVosContext ); + +/* Helper routines provided to other VOS API's */ +VOS_STATUS vos_mq_init(pVosMqType pMq); +void vos_mq_deinit(pVosMqType pMq); +void vos_mq_put(pVosMqType pMq, pVosMsgWrapper pMsgWrapper); +pVosMsgWrapper vos_mq_get(pVosMqType pMq); +v_BOOL_t vos_is_mq_empty(pVosMqType pMq); +pVosSchedContext get_vos_sched_ctxt(void); +pVosWatchdogContext get_vos_watchdog_ctxt(void); +VOS_STATUS vos_sched_init_mqs (pVosSchedContext pSchedContext); +void vos_sched_deinit_mqs (pVosSchedContext pSchedContext); +void vos_sched_flush_mc_mqs (pVosSchedContext pSchedContext); +void vos_sched_flush_tx_mqs (pVosSchedContext pSchedContext); +void vos_sched_flush_rx_mqs (pVosSchedContext pSchedContext); +void clearWlanResetReason(void); + +void vos_timer_module_init( void ); +VOS_STATUS vos_watchdog_wlan_shutdown(void); +VOS_STATUS vos_watchdog_wlan_re_init(void); +v_BOOL_t isWDresetInProgress(void); +void vos_ssr_protect_init(void); +void vos_ssr_protect(const char *caller_func); +void vos_ssr_unprotect(const char *caller_func); +bool vos_is_ssr_ready(const char *caller_func); +int vos_get_gfp_flags(void); + +#define vos_wait_for_work_thread_completion(func) vos_is_ssr_ready(func) + +#endif // #if !defined __VOSS_SCHED_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_threads.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_threads.c new file mode 100644 index 000000000000..afbc9e9888da --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_threads.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file vos_threads.c + + \brief virtual Operating System Services (vOSS) Threading APIs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + \brief vos_sleep() - sleep + + The \a vos_sleep() function suspends the execution of the current thread + until the specified time out interval elapses. + + \param msInterval - the number of milliseconds to suspend the current thread. + A value of 0 may or may not cause the current thread to yield. + + \return Nothing. + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_sleep( v_U32_t msInterval ) +{ + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + return; + } + msleep_interruptible(msInterval); +} + +/*---------------------------------------------------------------------------- + + \brief vos_sleep_us() - sleep + + The \a vos_sleep_us() function suspends the execution of the current thread + until the specified time out interval elapses. + + \param usInterval - the number of microseconds to suspend the current thread. + A value of 0 may or may not cause the current thread to yield. + + \return Nothing. + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_sleep_us( v_U32_t usInterval ) +{ + unsigned long timeout = usecs_to_jiffies(usInterval) + 1; + if (in_interrupt()) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__); + return; + } + while (timeout && !signal_pending(current)) + timeout = schedule_timeout_interruptible(timeout); +} + + +/*---------------------------------------------------------------------------- + + \brief vos_busy_wait() - busy wait + + The \a vos_busy_wait() function places the current thread in busy wait + until the specified time out interval elapses. If the interval is greater + than 50us on WM, the behaviour is undefined. + + \param usInterval - the number of microseconds to busy wait. + + \return Nothing. + + \sa + + --------------------------------------------------------------------------*/ +v_VOID_t vos_busy_wait( v_U32_t usInterval ) +{ + udelay(usInterval); +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_timer.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_timer.c new file mode 100644 index 000000000000..ef9de7d7d2ec --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_timer.c @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2012-2013, 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file vos_timer.c + + \brief virtual Operating System Servies (vOS) + + Definitions for vOSS Timer services + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include "wlan_qct_sys.h" +#include "vos_sched.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#define LINUX_TIMER_COOKIE 0x12341234 +#define LINUX_INVALID_TIMER_COOKIE 0xfeedface +#define TMR_INVALID_ID ( 0 ) + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ +static unsigned int persistentTimerCount; +static vos_lock_t persistentTimerCountLock; +// static sleep_okts_handle sleepClientHandle; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +// TBD: Need to add code for deferred timers implementation + +// clean up timer states after it has been deactivated +// check and try to allow sleep after a timer has been stopped or expired +static void tryAllowingSleep( VOS_TIMER_TYPE type ) +{ + if ( VOS_TIMER_TYPE_WAKE_APPS == type ) + { + // vos_lock_acquire( &persistentTimerCountLock ); + persistentTimerCount--; + if ( 0 == persistentTimerCount ) + { + // since the number of persistent timers has decreased from 1 to 0, + // the timer should allow sleep + //sleep_assert_okts( sleepClientHandle ); + } + //vos_lock_release( &persistentTimerCountLock ); + } +} + + +/*---------------------------------------------------------------------------- + + \brief vos_linux_timer_callback() - internal vos entry point which is + called when the timer interval expires + + This function in turn calls the vOS client callback and changes the + state of the timer from running (ACTIVE) to expired (INIT). + + + \param data - pointer to the timer control block which describes the + timer that expired + + \return nothing + + Note: function signature is defined by the Linux kernel. The fact + that the argument is "unsigned long" instead of "void *" is + unfortunately imposed upon us. But we can safely pass a pointer via + this parameter for LP32 and LP64 architectures. + + --------------------------------------------------------------------------*/ + +static void vos_linux_timer_callback (unsigned long data) +{ + vos_timer_t *timer = ( vos_timer_t *)data; + vos_msg_t msg; + VOS_STATUS vStatus; + unsigned long flags; + + vos_timer_callback_t callback=NULL; + v_PVOID_t userData=NULL; + int threadId; + VOS_TIMER_TYPE type=VOS_TIMER_TYPE_SW; + + VOS_ASSERT(timer); + + if (timer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s Null pointer passed in!",__func__); + return; + } + + threadId = timer->platformInfo.threadID; + spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); + + switch ( timer->state ) + { + case VOS_TIMER_STATE_STARTING: + // we are in this state because someone just started the timer, MM timer + // got started and expired, but the time content have not bee updated + // this is a rare race condition! + timer->state = VOS_TIMER_STATE_STOPPED; + vStatus = VOS_STATUS_E_ALREADY; + break; + case VOS_TIMER_STATE_STOPPED: + vStatus = VOS_STATUS_E_ALREADY; + break; + case VOS_TIMER_STATE_UNUSED: + vStatus = VOS_STATUS_E_EXISTS; + break; + case VOS_TIMER_STATE_RUNNING: + // need to go to stop state here because the call-back function may restart + // timer (to emulate periodic timer) + timer->state = VOS_TIMER_STATE_STOPPED; + // copy the relevant timer information to local variables; + // once we exist from this critical section, the timer content may be modified + // by other tasks + callback = timer->callback; + userData = timer->userData; + threadId = timer->platformInfo.threadID; + type = timer->type; + vStatus = VOS_STATUS_SUCCESS; + break; + default: + VOS_ASSERT(0); + vStatus = VOS_STATUS_E_FAULT; + break; + } + + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + + if ( VOS_STATUS_SUCCESS != vStatus ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "TIMER callback called in a wrong state=%d", timer->state); + return; + } + + tryAllowingSleep( type ); + + if (callback == NULL) + { + VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: No TIMER callback, Could not enqueue timer to any queue", + __func__); + return; + } + // If timer has expired then call vos_client specific callback + if ( vos_sched_is_tx_thread( threadId ) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "TIMER callback: running on TX thread"); + + //Serialize to the Tx thread + sysBuildMessageHeader( SYS_MSG_ID_TX_TIMER, &msg ); + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; + + if(vos_tx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) + return; + } + else if ( vos_sched_is_rx_thread( threadId ) ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "TIMER callback: running on RX thread"); + + //Serialize to the Rx thread + sysBuildMessageHeader( SYS_MSG_ID_RX_TIMER, &msg ); + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; + + if(vos_rx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) + return; + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "TIMER callback: running on MC thread"); + + // Serialize to the MC thread + sysBuildMessageHeader( SYS_MSG_ID_MC_TIMER, &msg ); + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; + + if(vos_mq_post_message( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) + return; + } + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Could not enqueue timer to any queue", __func__); + VOS_ASSERT(0); +} + +/*--------------------------------------------------------------------------- + + \brief vos_timer_getCurrentState() - Get the current state of the timer + + \param pTimer - the timer object + + \return timer state + + \sa + +---------------------------------------------------------------------------*/ +VOS_TIMER_STATE vos_timer_getCurrentState( vos_timer_t *pTimer ) +{ + if ( NULL == pTimer ) + { + VOS_ASSERT(0); + return VOS_TIMER_STATE_UNUSED; + } + + switch ( pTimer->state ) + { + case VOS_TIMER_STATE_STOPPED: + case VOS_TIMER_STATE_STARTING: + case VOS_TIMER_STATE_RUNNING: + case VOS_TIMER_STATE_UNUSED: + return pTimer->state; + default: + VOS_ASSERT(0); + return VOS_TIMER_STATE_UNUSED; + } +} + +/*---------------------------------------------------------------------------- + + \brief vos_timer_module_init() - Initializes a vOSS timer module. + + This API initializes the VOSS timer module. This needs to be called + exactly once prior to using any VOSS timers. + + \sa + + --------------------------------------------------------------------------*/ + +void vos_timer_module_init( void ) +{ + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, + "Initializing the VOSS timer module"); + vos_lock_init( &persistentTimerCountLock ); +} + +#ifdef TIMER_MANAGER +#include "wlan_hdd_dp_utils.h" + +hdd_list_t vosTimerList; + +static void vos_timer_clean(void); + +void vos_timer_manager_init() +{ + /* Initalizing the list with maximum size of 60000 */ + hdd_list_init(&vosTimerList, 1000); + return; +} + +static void vos_timer_clean() +{ + v_SIZE_t listSize; + unsigned long flags; + + hdd_list_size(&vosTimerList, &listSize); + + if (listSize) + { + hdd_list_node_t* pNode; + VOS_STATUS vosStatus; + + timer_node_t *ptimerNode; + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: List is not Empty. listSize %d ", + __func__, (int)listSize); + + do + { + spin_lock_irqsave(&vosTimerList.lock, flags); + vosStatus = hdd_list_remove_front(&vosTimerList, &pNode); + spin_unlock_irqrestore(&vosTimerList.lock, flags); + if (VOS_STATUS_SUCCESS == vosStatus) + { + ptimerNode = (timer_node_t*)pNode; + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "Timer Leak@ File %s, @Line %d", + ptimerNode->fileName, (int)ptimerNode->lineNum); + + vos_mem_free(ptimerNode); + } + } while (vosStatus == VOS_STATUS_SUCCESS); + } +} + +void vos_timer_exit() +{ + vos_timer_clean(); + hdd_list_destroy(&vosTimerList); +} +#endif + +/*-------------------------------------------------------------------------- + + \brief vos_timer_init() - Initialize a vOSS timer. + + This API initializes a vOS Timer object. + + The \a vos_timer_init() initializes a vOS Timer object. A timer must be + initialized by calling vos_timer_initialize() before it may be used in + any other timer functions. + + Attempting to initialize timer that is already initialized results in + a failure. A destroyed timer object can be re-initialized with a call to + \a vos_timer_init(). The results of otherwise referencing the object + after it has been destroyed are undefined. + + Calls to vOSS timer functions to manipulate the timer such + as vos_timer_set() will fail if the timer is not initialized or has + been destroyed. Therefore, don't use the timer after it has been + destroyed until it has been re-initialized. + + All callback will be executed within the VOS main thread unless it is + initialized from the Tx thread flow, in which case it will be executed + within the tx thread flow. + + \param timer - pointer to the opaque timer object to initialize + + \param timerType - specifies the type of timer. We have two different + timer types. +
      +
    1. VOS_TIMER_TYPE_SW - Pure software timer. The Apps processor + may not be awoken when this timer expires. +
    2. VOS_TIMER_TYPE_WAKE_APPS - The Apps processor will be awoken + from power collapse when this type of timer expires. +
    + + \param callback - the callback function to be called when the timer + expires. + + \param userData - a user data (or context) that is returned to the + callback function as a parameter when the timer expires. + + \return VOS_STATUS_SUCCESS - timer was successfully initialized and + is ready to be used. + + VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initialize the timer + + VOS_STATUS_E_NOMEM - insufficient memory exists to initialize + the timer + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to initialize the object referenced by timer, a previously + initialized but not yet destroyed timer. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + +---------------------------------------------------------------------------*/ +#ifdef TIMER_MANAGER +VOS_STATUS vos_timer_init_debug( vos_timer_t *timer, VOS_TIMER_TYPE timerType, + vos_timer_callback_t callback, v_PVOID_t userData, + char* fileName, v_U32_t lineNum ) +{ + VOS_STATUS vosStatus; + unsigned long flags; + // Check for invalid pointer + if ((timer == NULL) || (callback == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params being passed",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + timer->ptimerNode = vos_mem_malloc(sizeof(timer_node_t)); + + if(timer->ptimerNode == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for timeNode",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + vos_mem_set(timer->ptimerNode, sizeof(timer_node_t), 0); + + timer->ptimerNode->fileName = fileName; + timer->ptimerNode->lineNum = lineNum; + timer->ptimerNode->vosTimer = timer; + + spin_lock_irqsave(&vosTimerList.lock, flags); + vosStatus = hdd_list_insert_front(&vosTimerList, &timer->ptimerNode->pNode); + spin_unlock_irqrestore(&vosTimerList.lock, flags); + if(VOS_STATUS_SUCCESS != vosStatus) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to insert node into List vosStatus %d", __func__, vosStatus); + } + + // set the various members of the timer structure + // with arguments passed or with default values + spin_lock_init(&timer->platformInfo.spinlock); + if (VOS_TIMER_TYPE_SW == timerType) + init_timer_deferrable(&(timer->platformInfo.Timer)); + else + init_timer(&(timer->platformInfo.Timer)); + timer->platformInfo.Timer.function = vos_linux_timer_callback; + timer->platformInfo.Timer.data = (unsigned long)timer; + timer->callback = callback; + timer->userData = userData; + timer->type = timerType; + timer->platformInfo.cookie = LINUX_TIMER_COOKIE; + timer->platformInfo.threadID = 0; + timer->state = VOS_TIMER_STATE_STOPPED; + + return VOS_STATUS_SUCCESS; +} +#else +VOS_STATUS vos_timer_init( vos_timer_t *timer, VOS_TIMER_TYPE timerType, + vos_timer_callback_t callback, v_PVOID_t userData ) +{ + // Check for invalid pointer + if ((timer == NULL) || (callback == NULL)) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null params being passed",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // set the various members of the timer structure + // with arguments passed or with default values + spin_lock_init(&timer->platformInfo.spinlock); + if (VOS_TIMER_TYPE_SW == timerType) + init_timer_deferrable(&(timer->platformInfo.Timer)); + else + init_timer(&(timer->platformInfo.Timer)); + timer->platformInfo.Timer.function = vos_linux_timer_callback; + timer->platformInfo.Timer.data = (unsigned long)timer; + timer->callback = callback; + timer->userData = userData; + timer->type = timerType; + timer->platformInfo.cookie = LINUX_TIMER_COOKIE; + timer->platformInfo.threadID = 0; + timer->state = VOS_TIMER_STATE_STOPPED; + + return VOS_STATUS_SUCCESS; +} +#endif + + +/*--------------------------------------------------------------------------- + + \brief vos_timer_destroy() - Destroy a vOSS Timer object + + The \a vos_timer_destroy() function shall destroy the timer object. + After a successful return from \a vos_timer_destroy() the timer + object becomes, in effect, uninitialized. + + A destroyed timer object can be re-initialized by calling + vos_timer_init(). The results of otherwise referencing the object + after it has been destroyed are undefined. + + Calls to vOSS timer functions to manipulate the timer, such + as vos_timer_set() will fail if the lock is destroyed. Therefore, + don't use the timer after it has been destroyed until it has + been re-initialized. + + \param timer - the timer object to be destroyed. + + \return VOS_STATUS_SUCCESS - timer was successfully destroyed. + + VOS_STATUS_E_BUSY - The implementation has detected an attempt + to destroy the object referenced by timer while it is still + still referenced. The timer must be stopped before it can be + destroyed. + + VOS_STATUS_E_INVAL - The value specified by timer is invalid. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + +---------------------------------------------------------------------------*/ +#ifdef TIMER_MANAGER +VOS_STATUS vos_timer_destroy ( vos_timer_t *timer ) +{ + VOS_STATUS vStatus=VOS_STATUS_SUCCESS; + unsigned long flags; + + // Check for invalid pointer + if ( NULL == timer ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null timer pointer being passed",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // Check if timer refers to an uninitialized object + if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot destroy uninitialized timer",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + spin_lock_irqsave(&vosTimerList.lock, flags); + vStatus = hdd_list_remove_node(&vosTimerList, &timer->ptimerNode->pNode); + spin_unlock_irqrestore(&vosTimerList.lock, flags); + if(vStatus != VOS_STATUS_SUCCESS) + { + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + vos_mem_free(timer->ptimerNode); + + + spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); + + switch ( timer->state ) + { + case VOS_TIMER_STATE_STARTING: + vStatus = VOS_STATUS_E_BUSY; + break; + case VOS_TIMER_STATE_RUNNING: + /* Stop the timer first */ + del_timer(&(timer->platformInfo.Timer)); + vStatus = VOS_STATUS_SUCCESS; + break; + case VOS_TIMER_STATE_STOPPED: + vStatus = VOS_STATUS_SUCCESS; + break; + case VOS_TIMER_STATE_UNUSED: + vStatus = VOS_STATUS_E_ALREADY; + break; + default: + vStatus = VOS_STATUS_E_FAULT; + break; + } + + if ( VOS_STATUS_SUCCESS == vStatus ) + { + timer->platformInfo.cookie = LINUX_INVALID_TIMER_COOKIE; + timer->state = VOS_TIMER_STATE_UNUSED; + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + return vStatus; + } + + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot destroy timer in state = %d",__func__, timer->state); + VOS_ASSERT(0); + + return vStatus; +} + +#else +VOS_STATUS vos_timer_destroy ( vos_timer_t *timer ) +{ + VOS_STATUS vStatus=VOS_STATUS_SUCCESS; + unsigned long flags; + + // Check for invalid pointer + if ( NULL == timer ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Null timer pointer being passed",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_FAULT; + } + + // Check if timer refers to an uninitialized object + if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot destroy uninitialized timer",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); + + switch ( timer->state ) + { + case VOS_TIMER_STATE_STARTING: + vStatus = VOS_STATUS_E_BUSY; + break; + case VOS_TIMER_STATE_RUNNING: + /* Stop the timer first */ + del_timer(&(timer->platformInfo.Timer)); + vStatus = VOS_STATUS_SUCCESS; + break; + case VOS_TIMER_STATE_STOPPED: + vStatus = VOS_STATUS_SUCCESS; + break; + case VOS_TIMER_STATE_UNUSED: + vStatus = VOS_STATUS_E_ALREADY; + break; + default: + vStatus = VOS_STATUS_E_FAULT; + break; + } + + if ( VOS_STATUS_SUCCESS == vStatus ) + { + timer->platformInfo.cookie = LINUX_INVALID_TIMER_COOKIE; + timer->state = VOS_TIMER_STATE_UNUSED; + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + return vStatus; + } + + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot destroy timer in state = %d",__func__, timer->state); + VOS_ASSERT(0); + + return vStatus; +} +#endif + +/*-------------------------------------------------------------------------- + + \brief vos_timer_start() - Start a vOSS Timer object + + The \a vos_timer_start() function starts a timer to expire after the + specified interval, thus running the timer callback function when + the interval expires. + + A timer only runs once (a one-shot timer). To re-start the + timer, vos_timer_start() has to be called after the timer runs + or has been cancelled. + + \param timer - the timer object to be started + + \param expirationTime - expiration time for the timer (in milliseconds) + + \return VOS_STATUS_SUCCESS - timer was successfully started. + + VOS_STATUS_E_ALREADY - The implementation has detected an attempt + to start a timer while it is already started. The timer must + be stopped or expire before it can be started again. + + VOS_STATUS_E_INVAL - The value specified by timer is invalid. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + + -------------------------------------------------------------------------*/ +VOS_STATUS vos_timer_start( vos_timer_t *timer, v_U32_t expirationTime ) +{ + unsigned long flags; + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "Timer Addr inside voss_start : 0x%p ", timer ); + + // Check for invalid pointer + if ( NULL == timer ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s Null timer pointer being passed", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // Check if timer refers to an uninitialized object + if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot start uninitialized timer",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // Check if timer has expiration time less than 10 ms + if ( expirationTime < 10 ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot start a " + "timer with expiration less than 10 ms", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // make sure the remainer of the logic isn't interrupted + spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); + + // Ensure if the timer can be started + if ( VOS_TIMER_STATE_STOPPED != timer->state ) + { + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Cannot start timer in state = %d ",__func__, timer->state); + return VOS_STATUS_E_ALREADY; + } + + // Start the timer + mod_timer( &(timer->platformInfo.Timer), + jiffies + msecs_to_jiffies(expirationTime)); + + timer->state = VOS_TIMER_STATE_RUNNING; + + // Get the thread ID on which the timer is being started + timer->platformInfo.threadID = current->pid; + + if ( VOS_TIMER_TYPE_WAKE_APPS == timer->type ) + { + persistentTimerCount++; + if ( 1 == persistentTimerCount ) + { + // Since we now have one persistent timer, we need to disallow sleep + // sleep_negate_okts( sleepClientHandle ); + } + } + + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + + return VOS_STATUS_SUCCESS; +} + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_stop() - Stop a vOSS Timer + + The \a vos_timer_stop() function stops a timer that has been started but + has not expired, essentially cancelling the 'start' request. + + After a timer is stopped, it goes back to the state it was in after it + was created and can be started again via a call to vos_timer_start(). + + \param timer - the timer object to be stopped + + \return VOS_STATUS_SUCCESS - timer was successfully stopped. + + VOS_STATUS_E_INVAL - The value specified by timer is invalid. + + VOS_STATUS_E_FAULT - timer is an invalid pointer. + \sa + + ------------------------------------------------------------------------*/ +VOS_STATUS vos_timer_stop ( vos_timer_t *timer ) +{ + unsigned long flags; + + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Timer Addr inside voss_stop : 0x%p",__func__,timer ); + + // Check for invalid pointer + if ( NULL == timer ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s Null timer pointer being passed", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // Check if timer refers to an uninitialized object + if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot stop uninitialized timer",__func__); + VOS_ASSERT(0); + return VOS_STATUS_E_INVAL; + } + + // Ensure the timer state is correct + spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); + + if ( VOS_TIMER_STATE_RUNNING != timer->state ) + { + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Cannot stop timer in state = %d", + __func__, timer->state); + return VOS_STATUS_SUCCESS; + } + + timer->state = VOS_TIMER_STATE_STOPPED; + + del_timer(&(timer->platformInfo.Timer)); + + spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); + + tryAllowingSleep( timer->type ); + + return VOS_STATUS_SUCCESS; +} + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_get_system_ticks() - Get the system time in 10ms ticks + + The \a vos_timer_get_system_ticks() function returns the current number + of timer ticks in 10msec intervals. This function is suitable timestamping + and calculating time intervals by calculating the difference between two + timestamps. + + \returns - The current system tick count (in 10msec intervals). This + function cannot fail. + + \sa + + ------------------------------------------------------------------------*/ +v_TIME_t vos_timer_get_system_ticks( v_VOID_t ) +{ + return( jiffies_to_msecs(jiffies) / 10 ); +} + + +/*-------------------------------------------------------------------------- + + \brief vos_timer_get_system_time() - Get the system time in milliseconds + + The \a vos_timer_get_system_time() function returns the number of milliseconds + that have elapsed since the system was started + + \returns - The current system time in milliseconds. + + \sa + + ------------------------------------------------------------------------*/ +v_TIME_t vos_timer_get_system_time( v_VOID_t ) +{ + struct timeval tv; + do_gettimeofday(&tv); + return tv.tv_sec*1000 + tv.tv_usec/1000; +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_trace.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_trace.c new file mode 100644 index 000000000000..a6b382e056ae --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_trace.c @@ -0,0 +1,701 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/**========================================================================= + + \file vos_trace.c + + \brief virtual Operating System Servies (vOS) + + Trace, logging, and debugging definitions and APIs + + ========================================================================*/ + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + + when who what, where, why + -------- --- -------------------------------------------------------- + 09/16/08 hvm Adding ability to set multiple trace levels per component + 09/11/08 lac Added trace levels per component. Cleanup from review. + 08/14/08 vpai Particular modules and desired level can be selected + 06/20/08 vpai Created Module +===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include "adf_os_time.h" +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#define VOS_TRACE_BUFFER_SIZE ( 512 ) + +// macro to map vos trace levels into the bitmask +#define VOS_TRACE_LEVEL_TO_MODULE_BITMASK( _level ) ( ( 1 << (_level) ) ) + +typedef struct +{ + // Trace level for a module, as a bitmask. The bits in this mask + // are ordered by VOS_TRACE_LEVEL. For example, each bit represents + // one of the bits in VOS_TRACE_LEVEL that may be turned on to have + // traces at that level logged, i.e. if VOS_TRACE_LEVEL_ERROR is + // == 2, then if bit 2 (low order) is turned ON, then ERROR traces + // will be printed to the trace log. + // + // Note that all bits turned OFF means no traces. + v_U16_t moduleTraceLevel; + + // 3 character string name for the module + unsigned char moduleNameStr[ 4 ]; // 3 chars plus the NULL + +} moduleTraceInfo; + +#define VOS_DEFAULT_TRACE_LEVEL \ + ((1<= VOS_TRACE_LEVEL_MAX ) + { + pr_err("%s: Invalid trace level %d passed in!\n", __func__, level); + return; + } + + // Treat 'none' differently. NONE means we have to run off all + // the bits in the bit mask so none of the traces appear. Anything other + // than 'none' means we need to turn ON a bit in the bitmask. + if ( VOS_TRACE_LEVEL_NONE == level ) + { + gVosTraceInfo[ module ].moduleTraceLevel = VOS_TRACE_LEVEL_NONE; + } + else + { + // Set the desired bit in the bit mask for the module trace level. + gVosTraceInfo[ module ].moduleTraceLevel |= VOS_TRACE_LEVEL_TO_MODULE_BITMASK( level ); + } +} + +/** + * vos_trace_set_module_trace_level() - Set module trace level + * @module: Module id + * @level: Trace level for a module, as a bitmask as per 'moduleTraceInfo' + * + * Sets the module trace level where the trace level is given as a bit mask + * + * Return: None + */ +void vos_trace_set_module_trace_level(VOS_MODULE_ID module, uint32_t level) +{ + if (module < 0 || module >= VOS_MODULE_ID_MAX) { + pr_err("%s: Invalid module id %d passed\n", __func__, module); + return; + } + + gVosTraceInfo[module].moduleTraceLevel = level; +} + +void vos_trace_setValue( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, v_U8_t on) +{ + // Make sure the caller is passing in a valid LEVEL. + if ( level < 0 || level >= VOS_TRACE_LEVEL_MAX ) + { + pr_err("%s: Invalid trace level %d passed in!\n", __func__, level); + return; + } + + // Make sure the caller is passing in a valid module. + if ( module < 0 || module >= VOS_MODULE_ID_MAX ) + { + pr_err("%s: Invalid module id %d passed in!\n", __func__, module); + return; + } + + // Treat 'none' differently. NONE means we have to turn off all + // the bits in the bit mask so none of the traces appear. + if ( VOS_TRACE_LEVEL_NONE == level ) + { + gVosTraceInfo[ module ].moduleTraceLevel = VOS_TRACE_LEVEL_NONE; + } + // Treat 'All' differently. All means we have to turn on all + // the bits in the bit mask so all of the traces appear. + else if ( VOS_TRACE_LEVEL_ALL == level ) + { + gVosTraceInfo[ module ].moduleTraceLevel = 0xFFFF; + } + + else + { + if (on) + // Set the desired bit in the bit mask for the module trace level. + gVosTraceInfo[ module ].moduleTraceLevel |= VOS_TRACE_LEVEL_TO_MODULE_BITMASK( level ); + else + // Clear the desired bit in the bit mask for the module trace level. + gVosTraceInfo[ module ].moduleTraceLevel &= ~(VOS_TRACE_LEVEL_TO_MODULE_BITMASK( level )); + } +} + + +v_BOOL_t vos_trace_getLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ) +{ + v_BOOL_t traceOn = VOS_FALSE; + + if ( ( VOS_TRACE_LEVEL_NONE == level ) || + ( VOS_TRACE_LEVEL_ALL == level ) || + ( level >= VOS_TRACE_LEVEL_MAX ) ) + { + traceOn = VOS_FALSE; + } + else + { + traceOn = ( level & gVosTraceInfo[ module ].moduleTraceLevel ) ? VOS_TRUE : VOS_FALSE; + } + + return( traceOn ); +} + +void vos_snprintf(char *strBuffer, unsigned int size, char *strFormat, ...) +{ + va_list val; + + va_start( val, strFormat ); + snprintf (strBuffer, size, strFormat, val); + va_end( val ); +} + +#ifdef VOS_ENABLE_TRACING + +/*---------------------------------------------------------------------------- + + \brief vos_trace_msg() - Externally called trace function + + Checks the level of severity and accordingly prints the trace messages + + \param module - module identifier. A member of the VOS_MODULE_ID + enumeration that identifies the module issuing the trace message. + + \param level - trace level. A member of the VOS_TRACE_LEVEL + enumeration indicating the severity of the condition causing the + trace message to be issued. More severe conditions are more + likely to be logged. + + \param strFormat - format string. The message to be logged. This format + string contains printf-like replacement parameters, which follow + this parameter in the variable argument list. + + \return nothing + + \sa + + --------------------------------------------------------------------------*/ +void vos_trace_msg( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, char *strFormat, ... ) +{ + char strBuffer[VOS_TRACE_BUFFER_SIZE]; + int n; + + // Print the trace message when the desired level bit is set in the module + // tracel level mask. + if ( gVosTraceInfo[ module ].moduleTraceLevel & VOS_TRACE_LEVEL_TO_MODULE_BITMASK( level ) ) + { + // the trace level strings in an array. these are ordered in the same order + // as the trace levels are defined in the enum (see VOS_TRACE_LEVEL) so we + // can index into this array with the level and get the right string. The + // vos trace levels are... + // none, Fatal, Error, Warning, Info, InfoHigh, InfoMed, InfoLow, Debug + static const char * TRACE_LEVEL_STR[] = { " ", "F ", "E ", "W ", "I ", "IH", "IM", "IL", "D" }; + va_list val; + va_start(val, strFormat); + + // print the prefix string into the string buffer... + n = snprintf(strBuffer, VOS_TRACE_BUFFER_SIZE, "wlan: [%d:%2s:%3s] ", + in_interrupt() ? 0 : current->pid, + (char *) TRACE_LEVEL_STR[ level ], + (char *) gVosTraceInfo[ module ].moduleNameStr ); + + // print the formatted log message after the prefix string. + if ((n >= 0) && (n < VOS_TRACE_BUFFER_SIZE)) + { + vsnprintf(strBuffer + n, VOS_TRACE_BUFFER_SIZE - n, strFormat, val ); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_log_to_user(level, (char *)strBuffer, strlen(strBuffer)); +#else + pr_err("%s\n", strBuffer); +#endif + } + va_end(val); + } +} + +void vos_trace_display(void) +{ + VOS_MODULE_ID moduleId; + + pr_err(" 1)FATAL 2)ERROR 3)WARN 4)INFO 5)INFO_H 6)INFO_M 7)INFO_L 8)DEBUG\n"); + for (moduleId = 0; moduleId < VOS_MODULE_ID_MAX; ++moduleId) + { + pr_err("%2d)%s %s %s %s %s %s %s %s %s\n", + (int)moduleId, + gVosTraceInfo[moduleId].moduleNameStr, + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_FATAL)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_ERROR)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_WARN)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_INFO)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_INFO_HIGH)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_INFO_MED)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_INFO_LOW)) ? "X":" ", + (gVosTraceInfo[moduleId].moduleTraceLevel & (1 << VOS_TRACE_LEVEL_DEBUG)) ? "X":" " + ); + } +} + +/*---------------------------------------------------------------------------- + + \brief vos_trace_hex_dump() - Externally called hex dump function + + Checks the level of severity and accordingly prints the trace messages + + \param module - module identifier. A member of the VOS_MODULE_ID + enumeration that identifies the module issuing the trace message. + + \param level - trace level. A member of the VOS_TRACE_LEVEL + enumeration indicating the severity of the condition causing the + trace message to be issued. More severe conditions are more + likely to be logged. + + \param data - . The base address of the buffer to be logged. + + \param buf_len - . The size of the buffer to be logged. + + \return nothing + + \sa + --------------------------------------------------------------------------*/ +void vos_trace_hex_dump( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, + void *data, int buf_len ) +{ + char *buf = (char *)data; + int i; + + if (!(gVosTraceInfo[module].moduleTraceLevel & + VOS_TRACE_LEVEL_TO_MODULE_BITMASK(level))) + return; + + for (i=0; (i+15)< buf_len; i+=16) + { + vos_trace_msg( module, level, + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + buf[i], + buf[i+1], + buf[i+2], + buf[i+3], + buf[i+4], + buf[i+5], + buf[i+6], + buf[i+7], + buf[i+8], + buf[i+9], + buf[i+10], + buf[i+11], + buf[i+12], + buf[i+13], + buf[i+14], + buf[i+15]); + } + + // Dump the bytes in the last line + for (; i < buf_len; i++) + { + vos_trace_msg( module, level, "%02x ", buf[i]); + } + +} + +#endif + +/*----------------------------------------------------------------------------- + \brief vosTraceEnable() - Enable MTRACE for specific modules whose bits are + set in bitmask and enable is true. if enable is false it disables MTRACE for + that module. set the bitmask according to enum value of the modules. + + this functions will be called when you issue ioctl as mentioned following + [iwpriv wlan0 setdumplog ]. + - Decimal number, i.e. 64 decimal value shows only SME module, + 128 decimal value shows only PE module, 192 decimal value shows PE and SME. + + \param - bitmask_of_moduleId - as explained above set bitmask according to + enum of the modules. + 32 [dec] = 0010 0000 [bin] + 64 [dec] = 0100 0000 [bin] + 128 [dec] = 1000 0000 [bin] + \param - enable - can be true or false. + True implies enabling MTRACE, false implies disabling MTRACE. + ---------------------------------------------------------------------------*/ +void vosTraceEnable(v_U32_t bitmask_of_moduleId, v_U8_t enable) +{ + int i; + if (bitmask_of_moduleId) + { + for (i = 0; i < VOS_MODULE_ID_MAX; i++) + { + if (((bitmask_of_moduleId >> i) & 1 )) + { + if (enable) + { + if (NULL != vostraceRestoreCBTable[i]) + { + vostraceCBTable[i] = vostraceRestoreCBTable[i]; + } + } + else + { + vostraceRestoreCBTable[i] = vostraceCBTable[i]; + vostraceCBTable[i] = NULL; + } + } + } + } + else + { + if (enable) + { + for (i = 0; i < VOS_MODULE_ID_MAX; i++) + { + if (NULL != vostraceRestoreCBTable[i]) + { + vostraceCBTable[i] = vostraceRestoreCBTable[i]; + } + } + } + else + { + for (i = 0; i < VOS_MODULE_ID_MAX; i++) + { + vostraceRestoreCBTable[i] = vostraceCBTable[i]; + vostraceCBTable[i] = NULL; + } + } + } +} + +/*----------------------------------------------------------------------------- + \brief vosTraceInit() - Initializes vos trace structures and variables. + + Called immediately after vos_preopen, so that we can start recording HDD + events ASAP. + ----------------------------------------------------------------------------*/ +void vosTraceInit() +{ + v_U8_t i; + gvosTraceData.head = INVALID_VOS_TRACE_ADDR; + gvosTraceData.tail = INVALID_VOS_TRACE_ADDR; + gvosTraceData.num = 0; + gvosTraceData.enable = TRUE; + gvosTraceData.dumpCount = DEFAULT_VOS_TRACE_DUMP_COUNT; + gvosTraceData.numSinceLastDump = 0; + + for (i=0; i MAX_VOS_TRACE_RECORDS) + { + gvosTraceData.num = MAX_VOS_TRACE_RECORDS; + } + + if (INVALID_VOS_TRACE_ADDR == gvosTraceData.head) + { + /* first record */ + gvosTraceData.head = 0; + gvosTraceData.tail = 0; + } + else + { + /* queue is not empty */ + v_U32_t tail = gvosTraceData.tail + 1; + + if (MAX_VOS_TRACE_RECORDS == tail) + { + tail = 0; + } + + if (gvosTraceData.head == tail) + { + /* full */ + if (MAX_VOS_TRACE_RECORDS == ++gvosTraceData.head) + { + gvosTraceData.head = 0; + } + } + + gvosTraceData.tail = tail; + } + + rec = &gvosTraceTbl[gvosTraceData.tail]; + rec->code = code; + rec->session = session; + rec->data = data; + rec->time = adf_get_boottime(); + rec->module = module; + rec->pid = (in_interrupt() ? 0 : current->pid); + gvosTraceData.numSinceLastDump ++; + spin_unlock_irqrestore(<raceLock, flags); +} + + +/*----------------------------------------------------------------------------- + \brief vos_trace_spin_lock_init() - Initializes the lock variable before use + + This function will be called from vos_preOpen, we will have lock available + to use ASAP. + ----------------------------------------------------------------------------*/ +VOS_STATUS vos_trace_spin_lock_init() +{ + spin_lock_init(<raceLock); + + return VOS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------- + \brief vosTraceRegister() - Registers the call back functions to display the + messages in particular format mentioned in these call back functions. + + this functions should be called by interested module in their init part as + we will be ready to register as soon as modules are up. + + \param moduleID - enum value of module + \param vostraceCb - call back functions to display the messages in particular + format. + ----------------------------------------------------------------------------*/ +void vosTraceRegister(VOS_MODULE_ID moduleID, tpvosTraceCb vostraceCb) +{ + vostraceCBTable[moduleID] = vostraceCb; +} + +/*------------------------------------------------------------------------------ + \brief vosTraceDumpAll() - Dump data from ring buffer via call back functions + registered with VOSS + + This function will be called up on issueing ioctl call as mentioned following + [iwpriv wlan0 dumplog 0 0 ] + + - number lines to dump starting from tail to head. + + - if anybody wants to know how many messages were recorded + for particular module/s mentioned by setbit in bitmask from last messages. + it is optional, if you don't provide then it will dump everything from buffer. + + \param pMac - context of particular module + \param code - + \param session - + \param count - number of lines to dump starting from tail to head + ----------------------------------------------------------------------------*/ +void vosTraceDumpAll(void *pMac, v_U8_t code, v_U8_t session, + v_U32_t count, v_U32_t bitmask_of_module) +{ + tvosTraceRecord pRecord; + tANI_S32 i, tail; + + + if (!gvosTraceData.enable) + { + VOS_TRACE( VOS_MODULE_ID_SYS, + VOS_TRACE_LEVEL_ERROR, "Tracing Disabled"); + return; + } + + VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, + "Total Records: %d, Head: %d, Tail: %d", + gvosTraceData.num, gvosTraceData.head, gvosTraceData.tail); + + /* Aquire the lock so that only one thread at a time can read the ring buffer */ + spin_lock(<raceLock); + + if (gvosTraceData.head != INVALID_VOS_TRACE_ADDR) + { + i = gvosTraceData.head; + tail = gvosTraceData.tail; + + if (count) + { + if (count > gvosTraceData.num) + { + count = gvosTraceData.num; + } + if (tail >= (count - 1)) + { + i = tail - count + 1; + } + else if (count != MAX_VOS_TRACE_RECORDS) + { + i = MAX_VOS_TRACE_RECORDS - ((count - 1) - tail); + } + } + + pRecord = gvosTraceTbl[i]; + /* right now we are not using numSinceLastDump member but in future + we might re-visit and use this member to track how many latest + messages got added while we were dumping from ring buffer */ + gvosTraceData.numSinceLastDump = 0; + spin_unlock(<raceLock); + for (;;) + { + if ((code == 0 || (code == pRecord.code)) && + (vostraceCBTable[pRecord.module] != NULL)) + { + if (0 == bitmask_of_module) + { + vostraceCBTable[pRecord.module](pMac, &pRecord, (v_U16_t)i); + } + else + { + if (bitmask_of_module & (1 << pRecord.module)) + { + vostraceCBTable[pRecord.module](pMac, &pRecord, (v_U16_t)i); + } + } + } + + if (i == tail) + { + break; + } + i += 1; + + spin_lock(<raceLock); + if (MAX_VOS_TRACE_RECORDS == i) + { + i = 0; + pRecord= gvosTraceTbl[0]; + } + else + { + pRecord = gvosTraceTbl[i]; + } + spin_unlock(<raceLock); + } + } + else + { + spin_unlock(<raceLock); + } +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_types.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_types.c new file mode 100644 index 000000000000..b7182162ba11 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_types.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/**========================================================================= + + \file vos_Types.c + + \brief virtual Operating System Servies (vOS) + + Basic type definitions + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "vos_types.h" +#include "vos_trace.h" + +//#include "wlan_libra_config.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_set - set a variable atomically + + \param pTarget - pointer to the uintptr_t to set. + + \param value - the value to set in the uintptr_t variable. + + \return This function returns the value previously in the uintptr_t before + the new value is set. + + \sa vos_atomic_increment_U32(), vos_atomic_decrement_U32() + + --------------------------------------------------------------------------*/ +uintptr_t vos_atomic_set( uintptr_t *pTarget, uintptr_t value ) +{ + uintptr_t oldval; + unsigned long flags; + + if (pTarget == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "NULL ptr passed into %s",__func__); + return 0; + } + local_irq_save(flags); + oldval = *pTarget; + *pTarget = value; + local_irq_restore(flags); + // v_U32_t prev = atomic_read(pTarget); + // atomic_set(pTarget, value); + return oldval; +} + + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_increment_U32() - Increment a U32 variable atomically + + \param pTarget - pointer to the v_U32_t to increment. + + \return This function returns the value of the variable after the + increment occurs. + + \sa vos_atomic_decrement_U32(), vos_atomic_set_U32() + + --------------------------------------------------------------------------*/ +v_U32_t vos_atomic_increment_U32( v_U32_t *pTarget ) +{ + unsigned long flags; + if (pTarget == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "NULL ptr passed into %s",__func__); + return 0; + } + local_irq_save(flags); + ++*pTarget; + local_irq_restore(flags); + return *pTarget; + // return atomic_inc_return(pTarget); +} + + +/*---------------------------------------------------------------------------- + + \brief vos_atomic_decrement_U32() - Decrement a U32 variable atomically + + \param pTarget - pointer to the v_U32_t to decrement. + + \return This function returns the value of the variable after the + decrement occurs. + + \sa vos_atomic_increment_U32(), vos_atomic_set_U32() + + --------------------------------------------------------------------------*/ +v_U32_t vos_atomic_decrement_U32( v_U32_t *pTarget ) +{ + unsigned long flags; + if (pTarget == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "NULL ptr passed into %s",__func__); + return 0; + } + // return atomic_dec_return(pTarget); + local_irq_save(flags); + --*pTarget; + local_irq_restore(flags); + return (*pTarget); +} + +v_U32_t vos_atomic_increment_U32_by_value( v_U32_t *pTarget, v_U32_t value ) +{ + unsigned long flags; + if (pTarget == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "NULL ptr passed into %s",__func__); + return 0; + } + local_irq_save(flags); + *pTarget += value ; + local_irq_restore(flags); + return (*pTarget); +} + +v_U32_t vos_atomic_decrement_U32_by_value( v_U32_t *pTarget, v_U32_t value ) +{ + unsigned long flags; + if (pTarget == NULL) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "NULL ptr passed into %s",__func__); + return 0; + } + local_irq_save(flags); + *pTarget -= value ; + local_irq_restore(flags); + return (*pTarget); + +} + + +v_U32_t vos_get_skip_ssid_check(void) +{ +/**This is needed by only AMSS for interoperatability **/ + + return 1; +} + + +v_U32_t vos_get_skip_11e_check(void) +{ + /* this is needed only for AMSS for interopratability **/ + return 1; +} diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c new file mode 100644 index 000000000000..6dff1b8d068a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c @@ -0,0 +1,1232 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + + +/*============================================================================ + FILE: vos_utils.c + + OVERVIEW: This source file contains definitions for vOS crypto APIs + The four APIs mentioned in this file are used for + initializing, and de-initializing a crypto context, and + obtaining truly random data (for keys), as well as + SHA1 HMAC, and AES encrypt and decrypt routines. + + The routines include: + vos_crypto_init() - Initializes Crypto module + vos_crypto_deinit() - De-initializes Crypto module + vos_rand_get_bytes() - Generates random byte + vos_sha1_hmac_str() - Generate the HMAC-SHA1 of a string given a key + vos_encrypt_AES() - Generate AES Encrypted byte stream + vos_decrypt_AES() - Decrypts an AES Encrypted byte stream + + DEPENDENCIES: +============================================================================*/ + +/*============================================================================ + EDIT HISTORY FOR MODULE + +============================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + +#include "vos_trace.h" +#include "vos_utils.h" +#include "vos_memory.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#endif + +#include "ieee80211_common.h" +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define AAD_LEN 20 +#define IV_SIZE_AES_128 16 +#define CMAC_IPN_LEN 6 + + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + Function Definitions and Documentation + * -------------------------------------------------------------------------*/ +#ifndef CONFIG_CNSS +#if defined(WLAN_FEATURE_11W) && (defined(HIF_USB) || defined(HIF_SDIO)) +#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ + +static inline void xor_128(const u8 *a, const u8 *b, u8 *out) +{ + u8 i; + + for (i = 0; i < AES_BLOCK_SIZE; i++) + out[i] = a[i] ^ b[i]; +} + +static inline void leftshift_onebit(const u8 *input, u8 *output) +{ + int i, overflow = 0; + + for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) { + output[i] = input[i] << 1; + output[i] |= overflow; + overflow = (input[i] & 0x80) ? 1 : 0; + } + return; +} + +static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2) +{ + u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; + u8 const_rb[AES_BLOCK_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; + u8 const_zero[AES_BLOCK_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + crypto_cipher_encrypt_one(tfm, l, const_zero); + + if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */ + leftshift_onebit(l, k1); + } else { /* Else k1 = ( l << 1 ) (+) Rb */ + leftshift_onebit(l, tmp); + xor_128(tmp, const_rb, k1); + } + + if ((k1[0] & 0x80) == 0) { + leftshift_onebit(k1, k2); + } else { + leftshift_onebit(k1, tmp); + xor_128(tmp, const_rb, k2); + } +} + +static inline void padding(u8 *lastb, u8 *pad, u16 length) +{ + u8 j; + + /* original last block */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + if (j < length) + pad[j] = lastb[j]; + else if (j == length) + pad[j] = 0x80; + else + pad[j] = 0x00; + } +} + +void cmac_calc_mic(struct crypto_cipher *tfm, u8 *m, + u16 length, u8 *mac) +{ + u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE]; + u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE]; + u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128]; + int cmpBlk; + int i, nBlocks = (length + 15)/AES_BLOCK_SIZE; + + generate_subkey(tfm, k1, k2); + + if (nBlocks == 0) { + nBlocks = 1; + cmpBlk = 0; + } else { + cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0; + } + + if (cmpBlk) { /* Last block is complete block */ + xor_128(&m[AES_BLOCK_SIZE * (nBlocks - 1)], k1, m_last); + } else { /* Last block is not complete block */ + padding(&m[AES_BLOCK_SIZE * (nBlocks - 1)], padded, + length % AES_BLOCK_SIZE); + xor_128(padded, k2, m_last); + } + + for (i = 0; i < AES_BLOCK_SIZE; i++) + x[i] = 0; + + for (i = 0; i < (nBlocks - 1); i++) { + xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */ + crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */ + } + + xor_128(x, m_last, y); + crypto_cipher_encrypt_one(tfm, x, y); + + vos_mem_copy(mac, x, CMAC_TLEN); +} +#endif +#endif + +/*-------------------------------------------------------------------------- + + \brief vos_crypto_init() - Initializes Crypto module + + The vos_crypto_init() function initializes Crypto module. + + \param phCryptProv - pointer to the Crypt handle + + \return VOS_STATUS_SUCCESS - Successfully generated random memory. + + VOS_STATUS_E_FAULT - pbBuf is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ +VOS_STATUS vos_crypto_init( v_U32_t *phCryptProv ) +{ + VOS_STATUS uResult = VOS_STATUS_E_FAILURE; + + // This implementation doesn't require a crypto context + *phCryptProv = 0; + uResult = VOS_STATUS_SUCCESS; + return ( uResult ); +} + +VOS_STATUS vos_crypto_deinit( v_U32_t hCryptProv ) +{ + VOS_STATUS uResult = VOS_STATUS_E_FAILURE; + + // CryptReleaseContext succeeded + uResult = VOS_STATUS_SUCCESS; + + return ( uResult ); +} + +/*-------------------------------------------------------------------------- + + \brief vos_rand_get_bytes() - Generates random byte + + The vos_rand_get_bytes() function generate random bytes. + + Buffer should be allocated before calling vos_rand_get_bytes(). + + Attempting to initialize an already initialized lock results in + a failure. + + \param lock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - Successfully generated random memory. + + VOS_STATUS_E_FAULT - pbBuf is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ +VOS_STATUS vos_rand_get_bytes( v_U32_t cryptHandle, v_U8_t *pbBuf, v_U32_t numBytes ) +{ + VOS_STATUS uResult = VOS_STATUS_E_FAILURE; + + //check for invalid pointer + if ( NULL == pbBuf ) + { + uResult = VOS_STATUS_E_FAULT; + return ( uResult ); + } + + get_random_bytes( pbBuf, numBytes); + // "Random sequence generated." + uResult = VOS_STATUS_SUCCESS; + return ( uResult ); +} + + +#ifdef WLAN_FEATURE_11W +v_U8_t vos_get_mmie_size() +{ + return sizeof(struct ieee80211_mmie); +} + +/*-------------------------------------------------------------------------- + + \brief vos_increase_seq() - Increase the IPN aka Sequence number by one unit + + The vos_increase_seq() function increases the IPN by one unit. + + \param ipn - pointer to the IPN aka Sequence number [6 bytes] + + --------------------------------------------------------------------------*/ +static void +vos_increase_seq(v_U8_t *ipn) +{ + v_U64_t value = 0; + if (ipn) + { + value = (0xffffffffffff)& (*((v_U64_t *)ipn)); + value = value + 1; + vos_mem_copy(ipn, &value, IEEE80211_MMIE_IPNLEN); + } +} + +/*-------------------------------------------------------------------------- + + \brief vos_attach_mmie() - attches the complete MMIE at the end of frame + + The vos_attach_mmie() calculates the entire MMIE and attaches at the end + of Broadcast/Multicast robust management frames. + + \param igtk - pointer group key which will be used to calculate + the 8 byte MIC. + \param ipn - pointer ipn, it is also known as sequence number + \param key_id - key identication number + \param frm - pointer to the start of the frame. + \param efrm - pointer to the end of the frame. + \param frmLen - size of the entire frame. + + \return - this function will return VOS_TRUE on success and VOS_FALSE on + failure. + + --------------------------------------------------------------------------*/ + +v_BOOL_t +vos_attach_mmie(v_U8_t *igtk, v_U8_t *ipn, u_int16_t key_id, + v_U8_t* frm, v_U8_t* efrm, u_int16_t frmLen) +{ + struct ieee80211_mmie *mmie; + struct ieee80211_frame *wh; + v_U8_t aad[AAD_LEN], mic[CMAC_TLEN], *input = NULL; + v_U8_t previous_ipn[IEEE80211_MMIE_IPNLEN] = {0}; + v_U16_t nBytes = 0; + int ret = 0; + struct crypto_cipher *tfm; + + /* This is how received frame look like + * + * <------------frmLen----------------------------> + * + * +---------------+----------------------+-------+ + * | 802.11 HEADER | Management framebody | MMIE | + * +---------------+----------------------+-------+ + * ^ + * | + * efrm + * This is how MMIE from above frame look like + * + * + * <------------ 18 Bytes-----------------------------> + * +--------+---------+---------+-----------+---------+ + * |Element | Length | Key id | IPN | MIC | + * | id | | | | | + * +--------+---------+---------+-----------+---------+ + * Octet 1 1 2 6 8 + * + */ + + /* Check if frame is invalid length */ + if (((efrm - frm) != frmLen) || (frmLen < sizeof(*wh))) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid frame length", __func__); + return VOS_FALSE; + } + mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie)); + + /* Copy Element id */ + mmie->element_id = IEEE80211_ELEMID_MMIE; + + /* Copy Length */ + mmie->length = sizeof(*mmie)-2; + + /* Copy Key id */ + mmie->key_id = key_id; + + /* + * In case of error, revert back to original IPN + * to do that copy the original IPN into previous_ipn + */ + vos_mem_copy(&previous_ipn[0], ipn, IEEE80211_MMIE_IPNLEN); + vos_increase_seq(ipn); + vos_mem_copy(mmie->sequence_number, ipn, IEEE80211_MMIE_IPNLEN); + + /* + * Calculate MIC and then copy + */ +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC); +#else + tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC); +#endif + if (IS_ERR(tfm)) + { + ret = PTR_ERR(tfm); + tfm = NULL; + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, + "%s: crypto_alloc_cipher failed (%d)", __func__, ret); + goto err_tfm; + } + + ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128); + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, + "%s: crypto_cipher_setkey failed (%d)", __func__, ret); + goto err_tfm; + } + + /* Construct AAD */ + wh = (struct ieee80211_frame *)frm; + + /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */ + + /* FC type/subtype */ + aad[0] = wh->i_fc[0]; + /* Mask FC Retry, PwrMgt, MoreData flags to zero */ + aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT | + IEEE80211_FC1_MORE_DATA); + /* A1 || A2 || A3 */ + vos_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN); + + /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ + nBytes = AAD_LEN + (frmLen - sizeof(struct ieee80211_frame)); + input = (v_U8_t *)vos_mem_malloc(nBytes); + if (NULL == input) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Memory allocation failed", __func__); + ret = VOS_STATUS_E_NOMEM; + goto err_tfm; + } + + /* + * Copy the AAD, Management frame body, and + * MMIE with 8 bit MIC zeroed out + */ + vos_mem_zero(input, nBytes); + vos_mem_copy(input, aad, AAD_LEN); + /* Copy Management Frame Body and MMIE without MIC*/ + vos_mem_copy(input+AAD_LEN, + (v_U8_t*)(efrm-(frmLen-sizeof(struct ieee80211_frame))), + nBytes - AAD_LEN - CMAC_TLEN); + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + cmac_calc_mic(tfm, input, nBytes, mic); +#else + wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic); +#endif + vos_mem_free(input); + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, + "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X", + mic[0], mic[1], mic[2], mic[3], + mic[4], mic[5], mic[6], mic[7]); + vos_mem_copy(mmie->mic, mic, IEEE80211_MMIE_MICLEN); + + +err_tfm: + if (ret) + { + vos_mem_copy(ipn, previous_ipn, IEEE80211_MMIE_IPNLEN); + } + + if (tfm) +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + crypto_free_cipher(tfm); +#else + wcnss_wlan_crypto_free_cipher(tfm); +#endif + return !ret?VOS_TRUE:VOS_FALSE; +} + +v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn, + v_U8_t* frm, v_U8_t* efrm) +{ + struct ieee80211_mmie *mmie; + struct ieee80211_frame *wh; + v_U8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input; + v_U16_t nBytes = 0; + int ret = 0; + struct crypto_cipher *tfm; + + /* Check if frame is invalid length */ + if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "Invalid frame length"); + return VOS_FALSE; + } + + mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie)); + + /* Check Element ID */ + if ((mmie->element_id != IEEE80211_ELEMID_MMIE) || + (mmie->length != (sizeof(*mmie)-2))) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "IE is not Mgmt MIC IE or Invalid length"); + /* IE is not Mgmt MIC IE or invalid length */ + return VOS_FALSE; + } + + /* Validate IPN */ + rx_ipn = mmie->sequence_number; + if (OS_MEMCMP(rx_ipn, ipn, CMAC_IPN_LEN) <= 0) + { + /* Replay error */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "Replay error mmie ipn %02X %02X %02X %02X %02X %02X" + " drvr ipn %02X %02X %02X %02X %02X %02X", + rx_ipn[0], rx_ipn[1], rx_ipn[2], rx_ipn[3], rx_ipn[4], rx_ipn[5], + ipn[0], ipn[1], ipn[2], ipn[3], ipn[4], ipn[5]); + return VOS_FALSE; + } + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC); +#else + tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC); +#endif + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + tfm = NULL; + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, + "crypto_alloc_cipher failed (%d)", ret); + goto err_tfm; + } + + ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128); + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, + "crypto_cipher_setkey failed (%d)", ret); + goto err_tfm; + } + + /* Construct AAD */ + wh = (struct ieee80211_frame *)frm; + + /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */ + + /* FC type/subtype */ + aad[0] = wh->i_fc[0]; + /* Mask FC Retry, PwrMgt, MoreData flags to zero */ + aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT | + IEEE80211_FC1_MORE_DATA); + /* A1 || A2 || A3 */ + vos_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN); + + /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ + nBytes = AAD_LEN + (efrm - (v_U8_t*)(wh+1)); + input = (v_U8_t *)vos_mem_malloc(nBytes); + if (NULL == input) + { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "Memory allocation failed"); + ret = VOS_STATUS_E_NOMEM; + goto err_tfm; + } + + /* Copy the AAD, MMIE with 8 bit MIC zeroed out */ + vos_mem_zero(input, nBytes); + vos_mem_copy(input, aad, AAD_LEN); + vos_mem_copy(input+AAD_LEN, (v_U8_t*)(wh+1), nBytes - AAD_LEN - CMAC_TLEN); + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + cmac_calc_mic(tfm, input, nBytes, mic); +#else + wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic); +#endif + vos_mem_free(input); + + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X", + mic[0], mic[1], mic[2], mic[3], + mic[4], mic[5], mic[6], mic[7]); + + if (OS_MEMCMP(mic, mmie->mic, CMAC_TLEN) != 0) { + /* MMIE MIC mismatch */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "BC/MC MGMT frame MMIE MIC check Failed" + " rmic %02X %02X %02X %02X %02X %02X %02X %02X" + " cmic %02X %02X %02X %02X %02X %02X %02X %02X", + mmie->mic[0], mmie->mic[1], mmie->mic[2], mmie->mic[3], + mmie->mic[4], mmie->mic[5], mmie->mic[6], mmie->mic[7], + mic[0], mic[1], mic[2], mic[3], + mic[4], mic[5], mic[6], mic[7]); + return VOS_FALSE; + } + + /* Update IPN */ + vos_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN); + +err_tfm: + if (tfm) +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + crypto_free_cipher(tfm); +#else + wcnss_wlan_crypto_free_cipher(tfm); +#endif + + return !ret?VOS_TRUE:VOS_FALSE; +} + +#endif /* WLAN_FEATURE_11W */ +/** + * vos_sha1_hmac_str + * + * FUNCTION: + * Generate the HMAC-SHA1 of a string given a key. + * + * LOGIC: + * Standard HMAC processing from RFC 2104. The code is provided in the + * appendix of the RFC. + * + * ASSUMPTIONS: + * The RFC is correct. + * + * @param text text to be hashed + * @param textLen length of text + * @param key key to use for HMAC + * @param keyLen length of key + * @param digest holds resultant SHA1 HMAC (20B) + * + * @return VOS_STATUS_SUCCSS if the operation succeeds + * + */ + +struct hmac_sha1_result { + struct completion completion; + int err; +}; + +static void hmac_sha1_complete(struct crypto_async_request *req, int err) +{ + struct hmac_sha1_result *r = req->data; + if (err == -EINPROGRESS) + return; + r->err = err; + complete(&r->completion); +} + +int hmac_sha1(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, + v_U8_t *output, v_U8_t outlen) +{ + int ret = 0; + struct crypto_ahash *tfm; + struct scatterlist sg; + struct ahash_request *req; + struct hmac_sha1_result tresult; + void *hash_buff = NULL; + + unsigned char hash_result[64]; + int i; + + memset(output, 0, outlen); + + init_completion(&tresult.completion); + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + tfm = crypto_alloc_ahash("hmac(sha1)", CRYPTO_ALG_TYPE_AHASH, + CRYPTO_ALG_TYPE_AHASH_MASK); +#else + tfm = wcnss_wlan_crypto_alloc_ahash("hmac(sha1)", CRYPTO_ALG_TYPE_AHASH, + CRYPTO_ALG_TYPE_AHASH_MASK); +#endif + if (IS_ERR(tfm)) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to allocate request for hmac(sha1)"); + ret = -ENOMEM; + goto err_req; + } + + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + hmac_sha1_complete, &tresult); + + hash_buff = kzalloc(psize, GFP_KERNEL); + if (!hash_buff) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to kzalloc hash_buff"); + ret = -ENOMEM; + goto err_hash_buf; + } + + memset(hash_result, 0, 64); + vos_mem_copy(hash_buff, plaintext, psize); + sg_init_one(&sg, hash_buff, psize); + + if (ksize) { + crypto_ahash_clear_flags(tfm, ~0); +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + ret = crypto_ahash_setkey(tfm, key, ksize); +#else + ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize); +#endif + + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed"); + goto err_setkey; + } + } + + ahash_request_set_crypt(req, &sg, hash_result, psize); +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + ret = crypto_ahash_digest(req); +#else + ret = wcnss_wlan_crypto_ahash_digest(req); +#endif + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); + + switch (ret) { + case 0: + for (i=0; i< outlen; i++) + output[i] = hash_result[i]; + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible(&tresult.completion); + if (!ret && !tresult.err) { + for (i = 0; i < outlen; i++) + output[i] = hash_result[i]; + INIT_COMPLETION(tresult.completion); + break; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "wait_for_completion_interruptible failed"); + if (!ret) + ret = tresult.err; + goto out; + } + default: + goto out; + } + +out: +err_setkey: + kfree(hash_buff); +err_hash_buf: + ahash_request_free(req); +err_req: +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + crypto_free_ahash(tfm); +#else + wcnss_wlan_crypto_free_ahash(tfm); +#endif +err_tfm: + return ret; +} + +VOS_STATUS vos_sha1_hmac_str(v_U32_t cryptHandle, /* Handle */ + v_U8_t *pText, /* pointer to data stream */ + v_U32_t textLen, /* length of data stream */ + v_U8_t *pKey, /* pointer to authentication key */ + v_U32_t keyLen, /* length of authentication key */ + v_U8_t digest[VOS_DIGEST_SHA1_SIZE])/* caller digest to be filled in */ +{ + int ret = 0; + + ret = hmac_sha1( + pKey, //v_U8_t *key, + (v_U8_t) keyLen, //v_U8_t ksize, + (char *)pText, //char *plaintext, + (v_U8_t) textLen, //v_U8_t psize, + digest, //v_U8_t *output, + VOS_DIGEST_SHA1_SIZE //v_U8_t outlen + ); + + if (ret != 0) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"hmac_sha1() call failed"); + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_SUCCESS; +} + +/** + * vos_md5_hmac_str + * + * FUNCTION: + * Generate the HMAC-MD5 of a string given a key. + * + * LOGIC: + * Standard HMAC processing from RFC 2104. The code is provided in the + * appendix of the RFC. + * + * ASSUMPTIONS: + * The RFC is correct. + * + * @param text text to be hashed + * @param textLen length of text + * @param key key to use for HMAC + * @param keyLen length of key + * @param digest holds resultant MD5 HMAC (20B) + * + * @return VOS_STATUS_SUCCSS if the operation succeeds + * + */ +struct hmac_md5_result { + struct completion completion; + int err; +}; + +static void hmac_md5_complete(struct crypto_async_request *req, int err) +{ + struct hmac_md5_result *r = req->data; + if (err == -EINPROGRESS) + return; + r->err = err; + complete(&r->completion); +} + +int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, + v_U8_t *output, v_U8_t outlen) +{ + int ret = 0; + struct crypto_ahash *tfm; + struct scatterlist sg; + struct ahash_request *req; + struct hmac_md5_result tresult = {.err = 0}; + void *hash_buff = NULL; + + unsigned char hash_result[64]; + int i; + + memset(output, 0, outlen); + + init_completion(&tresult.completion); + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + tfm = crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, + CRYPTO_ALG_TYPE_AHASH_MASK); +#else + tfm = wcnss_wlan_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, + CRYPTO_ALG_TYPE_AHASH_MASK); +#endif + if (IS_ERR(tfm)) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to allocate request for hmac(md5)"); + ret = -ENOMEM; + goto err_req; + } + + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + hmac_md5_complete, &tresult); + + hash_buff = kzalloc(psize, GFP_KERNEL); + if (!hash_buff) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to kzalloc hash_buff"); + ret = -ENOMEM; + goto err_hash_buf; + } + + memset(hash_result, 0, 64); + vos_mem_copy(hash_buff, plaintext, psize); + sg_init_one(&sg, hash_buff, psize); + + if (ksize) { + crypto_ahash_clear_flags(tfm, ~0); +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + ret = crypto_ahash_setkey(tfm, key, ksize); +#else + ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize); +#endif + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed"); + goto err_setkey; + } + } + + ahash_request_set_crypt(req, &sg, hash_result, psize); +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + ret = crypto_ahash_digest(req); +#else + ret = wcnss_wlan_crypto_ahash_digest(req); +#endif + + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); + + switch (ret) { + case 0: + for (i=0; i< outlen; i++) + output[i] = hash_result[i]; + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible(&tresult.completion); + if (!ret && !tresult.err) { + for (i = 0; i < outlen; i++) + output[i] = hash_result[i]; + INIT_COMPLETION(tresult.completion); + break; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "wait_for_completion_interruptible failed"); + if (!ret) + ret = tresult.err; + goto out; + } + default: + goto out; + } + +out: +err_setkey: + kfree(hash_buff); +err_hash_buf: + ahash_request_free(req); +err_req: +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + crypto_free_ahash(tfm); +#else + wcnss_wlan_crypto_free_ahash(tfm); +#endif +err_tfm: + return ret; +} + +VOS_STATUS vos_md5_hmac_str(v_U32_t cryptHandle, /* Handle */ + v_U8_t *pText, /* pointer to data stream */ + v_U32_t textLen, /* length of data stream */ + v_U8_t *pKey, /* pointer to authentication key */ + v_U32_t keyLen, /* length of authentication key */ + v_U8_t digest[VOS_DIGEST_MD5_SIZE])/* caller digest to be filled in */ +{ + int ret = 0; + + ret = hmac_md5( + pKey, //v_U8_t *key, + (v_U8_t) keyLen, //v_U8_t ksize, + (char *)pText, //char *plaintext, + (v_U8_t) textLen, //v_U8_t psize, + digest, //v_U8_t *output, + VOS_DIGEST_MD5_SIZE //v_U8_t outlen + ); + + if (ret != 0) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"hmac_md5() call failed"); + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_SUCCESS; +} + + +struct ecb_aes_result { + struct completion completion; + int err; +}; + +static void ecb_aes_complete(struct crypto_async_request *req, int err) +{ + struct ecb_aes_result *r = req->data; + if (err == -EINPROGRESS) + return; + r->err = err; + complete(&r->completion); +} + + +/*-------------------------------------------------------------------------- + + \brief vos_encrypt_AES() - Generate AES Encrypted byte stream + + The vos_encrypt_AES() function generates the encrypted byte stream for given text. + + Buffer should be allocated before calling vos_rand_get_bytes(). + + Attempting to initialize an already initialized lock results in + a failure. + + \param lock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - Successfully generated random memory. + + VOS_STATUS_E_FAULT - pbBuf is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_encrypt_AES(v_U32_t cryptHandle, /* Handle */ + v_U8_t *pPlainText, /* pointer to data stream */ + v_U8_t *pCiphertext, + v_U8_t *pKey) /* pointer to authentication key */ +{ + struct ecb_aes_result result; + struct ablkcipher_request *req; + struct crypto_ablkcipher *tfm; + int ret = 0; + char iv[IV_SIZE_AES_128]; + struct scatterlist sg_in; + struct scatterlist sg_out; + + init_completion(&result.completion); + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + tfm = crypto_alloc_ablkcipher( "cbc(aes)", 0, 0); +#else + tfm = wcnss_wlan_crypto_alloc_ablkcipher( "cbc(aes)", 0, 0); +#endif + if (IS_ERR(tfm)) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ablkcipher failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ablkcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "Failed to allocate request for cbc(aes)"); + ret = -ENOMEM; + goto err_req; + } + + ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + ecb_aes_complete, &result); + + + crypto_ablkcipher_clear_flags(tfm, ~0); + + ret = crypto_ablkcipher_setkey(tfm, pKey, AES_KEYSIZE_128); + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_cipher_setkey failed"); + goto err_setkey; + } + + memset(iv, 0, IV_SIZE_AES_128); + + sg_init_one(&sg_in, pPlainText, AES_BLOCK_SIZE); + + sg_init_one(&sg_out, pCiphertext, AES_BLOCK_SIZE); + + ablkcipher_request_set_crypt(req, &sg_in, &sg_out, AES_BLOCK_SIZE, iv); + + crypto_ablkcipher_encrypt(req); + + + +// ------------------------------------- +err_setkey: +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + ablkcipher_request_free(req); +#else + wcnss_wlan_ablkcipher_request_free(req); +#endif +err_req: +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + crypto_free_ablkcipher(tfm); +#else + wcnss_wlan_crypto_free_ablkcipher(tfm); +#endif +err_tfm: + //return ret; + if (ret != 0) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"%s() call failed", __func__); + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief vos_decrypt_AES() - Decrypts an AES Encrypted byte stream + + The vos_decrypt_AES() function decrypts the encrypted byte stream. + + Buffer should be allocated before calling vos_rand_get_bytes(). + + Attempting to initialize an already initialized lock results in + a failure. + + \param lock - pointer to the opaque lock object to initialize + + \return VOS_STATUS_SUCCESS - Successfully generated random memory. + + VOS_STATUS_E_FAULT - pbBuf is an invalid pointer. + + VOS_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***VOS_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ + +VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, /* Handle */ + v_U8_t *pText, /* pointer to data stream */ + v_U8_t *pDecrypted, + v_U8_t *pKey) /* pointer to authentication key */ +{ +// VOS_STATUS uResult = VOS_STATUS_E_FAILURE; + struct ecb_aes_result result; + struct ablkcipher_request *req; + struct crypto_ablkcipher *tfm; + int ret = 0; + char iv[IV_SIZE_AES_128]; + struct scatterlist sg_in; + struct scatterlist sg_out; + + init_completion(&result.completion); + +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + tfm = crypto_alloc_ablkcipher( "cbc(aes)", 0, 0); +#else + tfm = wcnss_wlan_crypto_alloc_ablkcipher( "cbc(aes)", 0, 0); +#endif + if (IS_ERR(tfm)) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ablkcipher failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ablkcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "Failed to allocate request for cbc(aes)"); + ret = -ENOMEM; + goto err_req; + } + + ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + ecb_aes_complete, &result); + + + crypto_ablkcipher_clear_flags(tfm, ~0); + + ret = crypto_ablkcipher_setkey(tfm, pKey, AES_KEYSIZE_128); + if (ret) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_cipher_setkey failed"); + goto err_setkey; + } + + memset(iv, 0, IV_SIZE_AES_128); + + sg_init_one(&sg_in, pText, AES_BLOCK_SIZE); + + sg_init_one(&sg_out, pDecrypted, AES_BLOCK_SIZE); + + ablkcipher_request_set_crypt(req, &sg_in, &sg_out, AES_BLOCK_SIZE, iv); + + crypto_ablkcipher_decrypt(req); + + + +// ------------------------------------- +err_setkey: +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + ablkcipher_request_free(req); +#else + wcnss_wlan_ablkcipher_request_free(req); +#endif +err_req: +#if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) + crypto_free_ablkcipher(tfm); +#else + wcnss_wlan_crypto_free_ablkcipher(tfm); +#endif +err_tfm: + //return ret; + if (ret != 0) { + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"%s() call failed", __func__); + return VOS_STATUS_E_FAULT; + } + + return VOS_STATUS_SUCCESS; +} + +v_U32_t vos_chan_to_freq(v_U8_t chan) +{ + if (chan < VOS_24_GHZ_CHANNEL_14) // ch 0 - ch 13 + return VOS_24_GHZ_BASE_FREQ + chan * VOS_CHAN_SPACING_5MHZ; + else if (chan == VOS_24_GHZ_CHANNEL_14) // ch 14 + return VOS_CHAN_14_FREQ; + else if (chan < VOS_24_GHZ_CHANNEL_27) // ch 15 - ch 26 + return VOS_CHAN_15_FREQ + + (chan - VOS_24_GHZ_CHANNEL_15) * VOS_CHAN_SPACING_20MHZ; + else if (chan == VOS_5_GHZ_CHANNEL_170) + return VOS_CHAN_170_FREQ; + else + return VOS_5_GHZ_BASE_FREQ + chan * VOS_CHAN_SPACING_5MHZ; +} + +v_U8_t vos_freq_to_chan(v_U32_t freq) +{ + v_U8_t chan; + + if (freq > VOS_24_GHZ_BASE_FREQ && freq < VOS_CHAN_14_FREQ) + chan = ((freq - VOS_24_GHZ_BASE_FREQ)/VOS_CHAN_SPACING_5MHZ); + else if (freq == VOS_CHAN_14_FREQ) + chan = VOS_24_GHZ_CHANNEL_14; + else if ((freq > VOS_24_GHZ_BASE_FREQ) && (freq < VOS_5_GHZ_BASE_FREQ)) + chan = (((freq - VOS_CHAN_15_FREQ)/VOS_CHAN_SPACING_20MHZ) + + VOS_24_GHZ_CHANNEL_15); + else + chan = (freq - VOS_5_GHZ_BASE_FREQ)/VOS_CHAN_SPACING_5MHZ; + return chan; +} + + +v_U8_t vos_chan_to_band(v_U32_t chan) +{ + if (chan <= VOS_24_GHZ_CHANNEL_14) + return VOS_BAND_2GHZ; + + return VOS_BAND_5GHZ; +} diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h new file mode 100644 index 000000000000..7598cca2d326 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h @@ -0,0 +1,1639 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef _HALMSGAPI_H_ +#define _HALMSGAPI_H_ + +#include "halTypes.h" +#include "sirApi.h" +#include "sirParams.h" + +#define HAL_NUM_BSSID 2 +/* operMode in ADD BSS message */ +#define BSS_OPERATIONAL_MODE_AP 0 +#define BSS_OPERATIONAL_MODE_STA 1 +#define BSS_OPERATIONAL_MODE_IBSS 2 + +/* STA entry type in add sta message */ +#define STA_ENTRY_SELF 0 +#define STA_ENTRY_OTHER 1 +#define STA_ENTRY_BSSID 2 +#define STA_ENTRY_BCAST 3 //Special station id for transmitting broadcast frames. +#define STA_ENTRY_PEER STA_ENTRY_OTHER +#ifdef FEATURE_WLAN_TDLS +#define STA_ENTRY_TDLS_PEER 4 +#endif /* FEATURE_WLAN_TDLS */ + +#define STA_ENTRY_TRANSMITTER STA_ENTRY_SELF +#define STA_ENTRY_RECEIVER STA_ENTRY_OTHER + +#define HAL_STA_INVALID_IDX 0xFF +#define HAL_BSS_INVALID_IDX 0xFF + +#define HAL_BSSPERSONA_INVALID_IDX 0xFF + +#define WLAN_BSS_PROTECTION_ON 1 +#define WLAN_BSS_PROTECTION_OFF 0 + +/* Station index allocation after Broadcast station */ +#define HAL_MAX_NUM_BCAST_STATIONS 1 +#define HAL_MIN_BCAST_STA_INDEX ((HAL_MAX_NUM_BCAST_STATIONS>0)?0:HAL_STA_INVALID_IDX) +#define HAL_MAX_BCAST_STA_INDEX ((HAL_MAX_NUM_BCAST_STATIONS>0)?(HAL_MAX_NUM_BCAST_STATIONS - 1):HAL_STA_INVALID_IDX) +#define HAL_MIN_STA_INDEX ((HAL_MAX_BCAST_STA_INDEX!=HAL_STA_INVALID_IDX)?(HAL_MAX_BCAST_STA_INDEX+1):0) +#define HAL_MAX_STA_INDEX (HAL_NUM_STA) + +/* Compilation flags for enabling disabling selfSta and bcastSta per BSS */ +#define HAL_SELF_STA_PER_BSS 1 +#define HAL_BCAST_STA_PER_BSS 1 + +//invalid channel id. +#define HAL_INVALID_CHANNEL_ID 0 + +/* 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. + */ +#define BSSIDX_INVALID 254 + +#ifdef SAP_AUTH_OFFLOAD +#define MAX_CONNECT_REQ_LENGTH 512 +#endif + +#define HAL_IS_VALID_BSS_INDEX(pMac, bssIdx) ((BSSIDX_INVALID != (bssIdx)) && ((bssIdx) < (pMac)->hal.memMap.maxBssids)) + +// Beacon structure +typedef __ani_attr_pre_packed struct sAniBeaconStruct +{ + tANI_U32 beaconLength; // Indicates the beacon length + tSirMacMgmtHdr macHdr; // MAC Header for beacon + // Beacon body follows here +} __ani_attr_packed tAniBeaconStruct, *tpAniBeaconStruct; + +// probeRsp template structure +typedef __ani_attr_pre_packed struct sAniProbeRspStruct +{ + tSirMacMgmtHdr macHdr; // MAC Header for probeRsp + // probeRsp body follows here +} __ani_attr_packed tAniProbeRspStruct, *tpAniProbeRspStruct; + + +// Per TC parameters +typedef struct +{ + tANI_U8 disableTx; + tANI_U8 disableRx; + tANI_U8 rxCompBA; // 1: expect to see frames with compressed BA coming from this peer MAC + tANI_U8 rxBApolicy; // immediate ACK or delayed ACK for frames from this peer MAC + tANI_U8 txCompBA; // 1: using compressed BA to send to this peer MAC + tANI_U8 txBApolicy; // immediate ACK or delayed ACK for frames to this peer MAC + tANI_U8 rxUseBA; + tANI_U8 txUseBA; + tANI_U8 rxBufferSize; + tANI_U8 txBufferSize; + tANI_U16 txBAWaitTimeout; + tANI_U16 rxBAWaitTimeout; +} tTCParams; + + +typedef struct +{ + // First two fields bssid and assocId are used to find staid for sta. + // BSSID of STA + tSirMacAddr bssId; + + // ASSOC ID, as assigned by PE/LIM. This needs to be assigned + // on a per BSS basis + tANI_U16 assocId; + + // 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. + tANI_U8 staType; // 0 - Self, 1 other/remote, 2 - bssid + + tANI_U8 shortPreambleSupported; + + // MAC Address of STA + tSirMacAddr staMac; + + // Listen interval. + tANI_U16 listenInterval; + + // Support for 11e/WMM + tANI_U8 wmmEnabled; + + // + // U-APSD Flags: 1b per AC + // Encoded as follows: + // b7 b6 b5 b4 b3 b2 b1 b0 + // X X X X BE BK VI VO + // + tANI_U8 uAPSD; + + // Max SP Length + tANI_U8 maxSPLen; + + // 11n HT capable STA + tANI_U8 htCapable; + + // 11n Green Field preamble support + // 0 - Not supported, 1 - Supported + // Add it to RA related fields of sta entry in HAL + tANI_U8 greenFieldCapable; + + // TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz + tANI_U8 txChannelWidthSet; + + // MIMO Power Save + tSirMacHTMIMOPowerSaveState mimoPS; + + // RIFS mode: 0 - NA, 1 - Allowed + tANI_U8 rifsMode; + + // L-SIG TXOP Protection mechanism + // 0 - No Support, 1 - Supported + // SG - there is global field. + tANI_U8 lsigTxopProtection; + + // delayed ba support + tANI_U8 delBASupport; + // delayed ba support... TBD + + + // FIXME + //Add these fields to message + tANI_U8 us32MaxAmpduDuration; //in units of 32 us. + tANI_U8 maxAmpduSize; // 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k + tANI_U8 maxAmpduDensity; // 3 : 0~7 : 2^(11nAMPDUdensity -4) + tANI_U8 maxAmsduSize; // 1 : 3839 bytes, 0 : 7935 bytes + + // TC parameters + tTCParams staTCParams[STACFG_MAX_TC]; + + // Compression and Concat parameters for DPU + tANI_U16 deCompEnable; + tANI_U16 compEnable; + tANI_U16 concatSeqRmv; + tANI_U16 concatSeqIns; + + + //11n Parameters + + /** + HT STA should set it to 1 if it is enabled in BSS + HT STA should set it to 0 if AP does not support it. + This indication is sent to HAL and HAL uses this flag + to pickup up appropriate 40Mhz rates. + */ + tANI_U8 fDsssCckMode40Mhz; + + + //short GI support for 40Mhz packets + tANI_U8 fShortGI40Mhz; + + //short GI support for 20Mhz packets + tANI_U8 fShortGI20Mhz; + + + + /* + * All the legacy and airgo supported rates. + * These rates are the intersection of peer and self capabilities. + */ + tSirSupportedRates supportedRates; + + + + + + /* + * Following parameters are for returning status and station index from HAL to PE + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_ADD_STA_REQ is reported here + eHalStatus status; + // Station index; valid only when 'status' field value is eHAL_STATUS_SUCCESS + tANI_U8 staIdx; + + //BSSID of BSS to which the station is associated. + //This should be filled back in by HAL, and sent back to LIM as part of + //the response message, so LIM can cache it in the station entry of hash table. + //When station is deleted, LIM will make use of this bssIdx to delete + //BSS from hal tables and from softmac. + tANI_U8 bssIdx; + + /* this requires change in testDbg. I will change it later after coordinating with Diag team. + tANI_U8 fFwdTrigerSOSPtoHost; //trigger to start service period + tANI_U8 fFwdTrigerEOSPtoHost; //trigger to end service period + */ + + //HAL should update the existing STA entry, if this flag is set. + //PE will set this flag in case of reassoc, where we want to resue the + //the old staID and still return success. + tANI_U8 updateSta; + //A flag to indicate to HAL if the response message is required. + tANI_U8 respReqd; + + /* Robust Management Frame (RMF) enabled/disabled */ + tANI_U8 rmfEnabled; + + /* The unicast encryption type in the association */ + tANI_U32 encryptType; + + /*The DPU signatures will be sent eventually to TL to help it determine the + association to which a packet belongs to*/ + /*Unicast DPU index*/ + tANI_U8 ucUcastSig; + + /*Broadcast DPU index*/ + tANI_U8 ucBcastSig; + + tANI_U8 sessionId; //PE session id for PE<->HAL interface + // HAL just sends back what it receives. + + /*if this is a P2P Capable Sta*/ + tANI_U8 p2pCapableSta; + + /*CSA offload enable flag */ + tANI_U8 csaOffloadEnable; + +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtCapable; + tANI_U8 vhtTxChannelWidthSet; + tANI_U8 vhtSupportedRxNss; + tANI_U8 vhtTxBFCapable; + tANI_U8 vhtTxMUBformeeCapable; + tANI_U8 enableVhtpAid; + tANI_U8 enableVhtGid; +#endif + tANI_U8 enableAmpduPs; + tANI_U8 enableHtSmps; + tANI_U8 htSmpsconfig; + + tANI_U8 htLdpcCapable; + tANI_U8 vhtLdpcCapable; + tANI_U8 smesessionId; + tANI_U8 wpa_rsn; + tANI_U16 capab_info; + tANI_U16 ht_caps; + tANI_U32 vht_caps; + tSirNwType nwType; + tPowerdBm maxTxPower; + /* + * Peer Atim Info, Valid only + * for IBSS Mode. + */ + tANI_U8 atimIePresent; + tANI_U32 peerAtimWindowLength; + tANI_U8 nonRoamReassoc; + uint32_t nss; /* Number of spatial streams supported */ + tANI_U8 max_amsdu_num; +} tAddStaParams, *tpAddStaParams; + + +typedef struct +{ + // Station index + tANI_U16 staIdx; + tANI_U16 templIdx; + tANI_U8 rateIdx; + + // The return status of SIR_HAL_UPDATE_STARATEINFO_REQ is reported here + eHalStatus status; + + //A flag to indicate to HAL if the response message is required. + tANI_U8 respReqd; + +} tUpdateTxCmdTemplParams, *tpUpdateTxCmdTemplParams; +//FIXME: change the structure name + + + + + + + + +typedef struct +{ + // index of STA to delete - this should be the same as the index returned + // as part of the AddSta + tANI_U16 staIdx; + tANI_U16 assocId; + eHalStatus status; // Status of SIR_HAL_DELETE_STA_REQ is reported here + tANI_U8 respReqd; + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // PE session id now added to all HAL<->PE transacations + // HAL sends it back unmodified. + tANI_U8 smesessionId; + tANI_U8 staType; + tSirMacAddr staMac; +} tDeleteStaParams, * tpDeleteStaParams; + +/* + * This is used by PE to configure the key information on a given station. + * When the secType is WEP40 or WEP104, the defWEPIdx is used to locate + * a preconfigured key from a BSS the station assoicated with; otherwise + * a new key descriptor is created based on the key field. + */ +typedef struct +{ + tANI_U16 staIdx; + tAniEdType encType; // Encryption/Decryption type + tAniWepType wepType; // valid only for WEP + tANI_U8 defWEPIdx; // Default WEP key, valid only for static WEP, must between 0 and 3 + tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; // valid only for non-static WEP encyrptions + tANI_U8 singleTidRc; // 1=Single TID based Replay Count, 0=Per TID based RC + tANI_U8 smesessionId; + tSirMacAddr peerMacAddr; + /* + * Following parameter is for returning status + * via response message. HAL does not read them. + */ + eHalStatus status; // status of SIR_HAL_SET_STAKEY_REQ is reported here + tANI_U8 sessionId; // PE session id for PE<->HAL interface + + // PE session id now added to all HAL<->PE transacations + // HAL sends back response with no modification + tANI_U8 sendRsp; +} tSetStaKeyParams, *tpSetStaKeyParams; + +typedef struct sLimMlmSetKeysReq +{ + tSirMacAddr peerMacAddr; + tANI_U8 sessionId; //Added For BT-AMP Support + tANI_U8 smesessionId; // Added for drivers based on wmi interface + tANI_U16 aid; + tAniEdType edType; // Encryption/Decryption type + tANI_U8 numKeys; + tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; +} tLimMlmSetKeysReq, *tpLimMlmSetKeysReq; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_ADD_BSS_REQ +// +typedef struct +{ + // MAC Address/BSSID + tSirMacAddr bssId; +#ifdef HAL_SELF_STA_PER_BSS + // Self Mac Address + tSirMacAddr selfMacAddr; +#endif + // BSS type + // FIXME - Is this reqd? Do we want to isolate BSS/IBSS parameters? + tSirBssType bssType; + + // AP - 0; STA - 1 ; + tANI_U8 operMode; + + // Network type - b/g/a/MixedMode/GreenField/Legacy + // TODO - This enum to be updated for HT support + // Review FIXME - Why is this needed? + tSirNwType nwType; + + tANI_U8 shortSlotTimeSupported; + tANI_U8 llaCoexist; + tANI_U8 llbCoexist; + tANI_U8 llgCoexist; + tANI_U8 ht20Coexist; + tANI_U8 llnNonGFCoexist; + tANI_U8 fLsigTXOPProtectionFullSupport; + tANI_U8 fRIFSMode; + + // Beacon Interval + tSirMacBeaconInterval beaconInterval; + + // DTIM period + tANI_U8 dtimPeriod; + + // CF Param Set + // Review FIXME - Does HAL need this? + tSirMacCfParamSet cfParamSet; + + // MAC Rate Set + // Review FIXME - Does HAL need this? + tSirMacRateSet rateSet; + + // 802.11n related HT parameters that are dynamic + + // Enable/Disable HT capabilities + tANI_U8 htCapable; + + // Enable/Disable OBSS protection + tANI_U8 obssProtEnabled; + + // RMF enabled/disabled + tANI_U8 rmfEnabled; + + // HT Operating Mode + // Review FIXME - Does HAL need this? + tSirMacHTOperatingMode htOperMode; + + // Dual CTS Protection: 0 - Unused, 1 - Used + tANI_U8 dualCTSProtection; + + // TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz + tANI_U8 txChannelWidthSet; + + // Current Operating Channel + tANI_U8 currentOperChannel; + + // Current Extension Channel, if applicable + tANI_U8 currentExtChannel; + + // Add a STA entry for "itself" - + // On AP - Add the AP itself in an "STA context" + // On STA - Add the AP to which this STA is joining in an "STA context" + tAddStaParams staContext; + + /* + * Following parameters are for returning status and station index from HAL to PE + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_ADD_BSS_REQ is reported here + eHalStatus status; + // BSS index allocated by HAL. + // valid only when 'status' field is eHAL_STATUS_SUCCESS + tANI_U16 bssIdx; + + // Broadcast DPU descriptor index allocated by HAL and used for broadcast/multicast packets. + // valid only when 'status' field is eHAL_STATUS_SUCCESS + tANI_U8 bcastDpuDescIndx; + + // DPU signature to be used for broadcast/multicast packets + // valid only when 'status' field is eHAL_STATUS_SUCCESS + tANI_U8 bcastDpuSignature; + + // DPU descriptor index allocated by HAL, used for bcast/mcast management packets + tANI_U8 mgmtDpuDescIndx; + + // DPU signature to be used for bcast/mcast management packets + tANI_U8 mgmtDpuSignature; + + //HAL should update the existing BSS entry, if this flag is set. + //PE will set this flag in case of reassoc, where we want to resue the + //the old bssID and still return success. + tANI_U8 updateBss; + + // Add BSSID info for rxp filter in IBSS mode + tSirMacSSid ssId; + + //HAL will send the response message to LIM only when this flag is set. + //LIM will set this flag, whereas DVT will not set this flag. + tANI_U8 respReqd; + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // PE session id now added to all HAL<->PE transacations + // HAL Sends the sessionId unmodified. + +#if defined WLAN_FEATURE_VOWIFI + tPowerdBm txMgmtPower; //HAL fills in the tx power used for mgmt frames in this field. + tPowerdBm maxTxPower; //max power to be used after applying the power constraint, if any +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + tANI_U8 extSetStaKeyParamValid; //Ext Bss Config Msg if set + tSetStaKeyParams extSetStaKeyParam; //SetStaKeyParams for ext bss msg +#endif + + tANI_U8 ucMaxProbeRespRetryLimit; //probe Response Max retries + tANI_U8 bHiddenSSIDEn; //To Enable Hidden ssid. + tANI_U8 bProxyProbeRespEn; //To Enable Disable FW Proxy Probe Resp + tANI_U8 halPersona; //Persona for the BSS can be STA,AP,GO,CLIENT value same as tVOS_CON_MODE + + //Spectrum Management Capability, 1 - Enabled, 0 - Disabled. + tANI_U8 bSpectrumMgtEnabled; +#ifdef WLAN_FEATURE_11AC + tANI_U8 vhtCapable; + tANI_U8 vhtTxChannelWidthSet; +#endif + tANI_U8 reassocReq; // Set only during roaming reassociation + tANI_U16 chainMask; + tANI_U16 smpsMode; + tANI_U8 dot11_mode; + tANI_U8 nonRoamReassoc; + uint8_t wps_state; + uint8_t nss_2g; + uint8_t nss_5g; +} tAddBssParams, * tpAddBssParams; + +typedef struct +{ + tANI_U8 bssIdx; + // The return status of SIR_HAL_DELETE_BSS_REQ is reported here + eHalStatus status; + //HAL will send the response message to LIM only when this flag is set. + //LIM will set this flag, whereas DVT will not set this flag. + tANI_U8 respReqd; + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // HAL sends it back unmodified. + tSirMacAddr bssid; // Will be removed for PE-HAL integration + tANI_U8 smesessionId; +} tDeleteBssParams, * tpDeleteBssParams; + +// +// UAPSD AC mask: 1b per AC +// LSB 4 bits for delivery enabled setting. msb 4 bits for trigger enabled settings. +// Encoded as follows: +// b7 b6 b5 b4 b3 b2 b1 b0 +// BE BK VI VO BE BK VI VO + +typedef struct +{ + tANI_U8 staIdx; + tANI_U8 uapsdACMask; + tANI_U8 maxSpLen; +} tUpdateUapsdParams, * tpUpdateUapsdParams; + +typedef struct sSirScanEntry +{ + tANI_U8 bssIdx[HAL_NUM_BSSID]; + tANI_U8 activeBSScnt; +}tSirScanEntry, *ptSirScanEntry; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_INIT_SCAN_REQ +// +typedef struct { + + eHalSysMode scanMode; + + tSirMacAddr bssid; + + tANI_U8 notifyBss; + + tANI_U8 useNoA; + + // If this flag is set HAL notifies PE when SMAC returns status. + tANI_U8 notifyHost; + + tANI_U8 frameLength; + tANI_U8 frameType; // Data NULL or CTS to self + + // Indicates the scan duration (in ms) + tANI_U16 scanDuration; + + // For creation of CTS-to-Self and Data-NULL MAC packets + tSirMacMgmtHdr macMgmtHdr; + + tSirScanEntry scanEntry; + + // when this flag is set, HAL should check for link traffic prior to scan + tSirLinkTrafficCheck checkLinkTraffic; + + /* + * Following parameters are for returning status and station index from HAL to PE + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_INIT_SCAN_REQ is reported here + eHalStatus status; + +} tInitScanParams, * tpInitScanParams; + +typedef enum eDelStaReasonCode{ + HAL_DEL_STA_REASON_CODE_KEEP_ALIVE = 0x1, + HAL_DEL_STA_REASON_CODE_TIM_BASED = 0x2, + HAL_DEL_STA_REASON_CODE_RA_BASED = 0x3, + HAL_DEL_STA_REASON_CODE_UNKNOWN_A2 = 0x4 +}tDelStaReasonCode; + +typedef enum eSmpsModeValue{ + STATIC_SMPS_MODE = 0x0, + DYNAMIC_SMPS_MODE = 0x1, + SMPS_MODE_RESERVED = 0x2, + SMPS_MODE_DISABLED = 0x3 +}tSmpsModeValue; + +// +// Msg header is used from tSirMsgQ +// Msg Type = SIR_LIM_DELETE_STA_CONTEXT_IND +// +typedef struct { + bool is_tdls; + tANI_U8 vdev_id; + tANI_U16 assocId; + tANI_U16 staId; + tSirMacAddr bssId; // TO SUPPORT BT-AMP + // HAL copies bssid from the sta table. + tSirMacAddr addr2; // + tANI_U16 reasonCode; // To unify the keepalive / unknown A2 / tim-based disa + tANI_S8 rssi; +} tDeleteStaContext, * tpDeleteStaContext; + + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_START_SCAN_REQ +// FIXME - Can we just use tSirMsgQ directly, instead of using this structure? +// +typedef struct { + + // Indicates the current scan channel + tANI_U8 scanChannel; + + /* + * Following parameters are for returning status and station index from HAL to PE + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_START_SCAN_REQ is reported here + eHalStatus status; + +#if defined WLAN_FEATURE_VOWIFI + tANI_U32 startTSF[2]; + tPowerdBm txMgmtPower; //HAL fills in the tx power used for mgmt frames in this field. +#endif +} tStartScanParams, * tpStartScanParams; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_END_SCAN_REQ +// FIXME - Can we just use tSirMsgQ directly, instead of using this structure? +// +typedef struct { + + // Indicates the current scan channel + tANI_U8 scanChannel; + + /* + * Following parameters are for returning status and station index from HAL to PE + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_END_SCAN_REQ is reported here + eHalStatus status; + +} tEndScanParams, * tpEndScanParams; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_FINISH_SCAN_REQ +// +typedef struct { + + // Identifies the operational state of the AP/STA. + // In case of the STA, only if the operState is non-zero will the rest of + // the parameters that follow be decoded + // In case of the AP, all parameters are valid + // + // 0 - Idle state, 1 - Link Established + + eHalSysMode scanMode; + + tSirMacAddr bssid; + + // Current operating channel + tANI_U8 currentOperChannel; + + // If 20/40 MHz is operational, this will indicate the 40 MHz extension + // channel in combination with the control channel + ePhyChanBondState cbState; + + // For an STA, indicates if a Data NULL frame needs to be sent + // to the AP with FrameControl.PwrMgmt bit set to 0 + tANI_U8 notifyBss; + + tANI_U8 notifyHost; + + tANI_U8 frameLength; + tANI_U8 frameType; // Data NULL or CTS to self + + // For creation of CTS-to-Self and Data-NULL MAC packets + tSirMacMgmtHdr macMgmtHdr; + + tSirScanEntry scanEntry; + + /* + * Following parameters are for returning status and station index from HAL to PE + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_FINISH_SCAN_REQ is reported here + eHalStatus status; + +} tFinishScanParams, * tpFinishScanParams; + +#ifdef FEATURE_OEM_DATA_SUPPORT + +#ifndef OEM_DATA_REQ_SIZE +#define OEM_DATA_REQ_SIZE 280 +#endif +#ifndef OEM_DATA_RSP_SIZE +#define OEM_DATA_RSP_SIZE 1724 +#endif + +typedef struct +{ + tSirMacAddr selfMacAddr; + eHalStatus status; + tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; +} tStartOemDataReq, *tpStartOemDataReq; + +typedef struct +{ + tANI_U8 oemDataRsp[OEM_DATA_RSP_SIZE]; +} tStartOemDataRsp, *tpStartOemDataRsp; +#endif + +typedef struct sBeaconGenStaInfo { + tANI_U16 assocId; + tANI_U32 staTxAckCnt; +}tBeaconGenStaInfo, *tpBeaconGenStaInfo; +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_LIM_BEACON_GEN_IND +// + +typedef struct sBeaconGenParams { + // Identifies the BSSID for which it is time to generate a beacon + tANI_U8 bssIdx; + tSirMacAddr bssId; +#ifdef FIXME_VOLANS + tANI_U8 numOfSta; /* Number of stations in power save, who have data pending*/ + tANI_U8 numOfStaWithoutData; /* Number of stations in power save, who don't have any data pending*/ + tANI_U8 fBroadcastTrafficPending ; + tANI_U8 dtimCount; +#endif + tANI_U8 rsvd[3]; /** Align the Structure to 4 bytes as unalligned access will happen if + the staInfo is being Accessed */ +/** NOTE: tBeaconGenStaInfo staInfo[xx]; Depending on the Number of STA in PS, Every time + this array is being allocated and piled up at the End*/ +} tBeaconGenParams, * tpBeaconGenParams; + +typedef struct { + tSirMacAddr bssId; + tANI_U8 *beacon; // Beacon data. + tANI_U32 beaconLength; //length of the template. + tANI_U32 timIeOffset; //TIM IE offset from the beginning of the template. + tANI_U16 p2pIeOffset; //P2P IE offset from the begining of the template +} tSendbeaconParams, * tpSendbeaconParams; + +typedef struct sSendProbeRespParams { + tSirMacAddr bssId; + tANI_U8 *pProbeRespTemplate; + tANI_U32 probeRespTemplateLen; + tANI_U32 ucProxyProbeReqValidIEBmap[8]; +} tSendProbeRespParams, * tpSendProbeRespParams; + +/* + * This is used by PE to create a set of WEP keys for a given BSS. + */ +typedef struct +{ + tANI_U8 bssIdx; + tAniEdType encType; + tANI_U8 numKeys; + tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; + tANI_U8 singleTidRc; // 1=Single TID based Replay Count, 0=Per TID based RC + tANI_U8 smesessionId; + /* + * Following parameter is for returning status + * via response message. HAL does not read them. + */ + eHalStatus status; // status of SIR_HAL_SET_BSSKEY_REQ is reported here + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // HAL sends this unmodified in the response +} tSetBssKeyParams, *tpSetBssKeyParams; + +/* + * This is used by PE to Remove the key information on a given station. + */ +typedef struct +{ + tANI_U16 staIdx; + tAniEdType encType; // Encryption/Decryption type + tANI_U8 keyId; + tANI_BOOLEAN unicast; + /* + * Following parameter is for returning status + * via response message. HAL does not read them. + */ + eHalStatus status; // return status of SIR_HAL_REMOVE_STAKEY_REQ + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // HAL Sends back the PE session + // id unmodified +} tRemoveStaKeyParams, *tpRemoveStaKeyParams; + +/* + * This is used by PE to remove keys for a given BSS. + */ +typedef struct +{ + tANI_U8 bssIdx; + tAniEdType encType; + tANI_U8 keyId; + tANI_U8 wepType; + /* + * Following parameter is for returning status + * via response message. HAL does not read them. + */ + eHalStatus status; // return status of SIR_HAL_REMOVE_BSSKEY_REQ + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // HAL Sends back the PE session + // id unmodified +} tRemoveBssKeyParams, *tpRemoveBssKeyParams; + +typedef struct +{ + // index of STA to get the statistics from + tANI_U16 staIdx; + tANI_U8 encMode; + // The return status of SIR_HAL_DPU_STATS_REQ is reported here + eHalStatus status; + // The return statistics + tANI_U32 sendBlocks; + tANI_U32 recvBlocks; + tANI_U32 replays; + tANI_U8 micErrorCnt; + tANI_U32 protExclCnt; + tANI_U16 formatErrCnt; + tANI_U16 unDecryptableCnt; + tANI_U32 decryptErrCnt; + tANI_U32 decryptOkCnt; + +} tDpuStatsParams, * tpDpuStatsParams; + + +/* + * Get the DPU signature based on a given staId + */ +typedef struct +{ + tANI_U16 staIdx; + /* + * Following parameter is for returning status + * via response message. HAL does not read them. + */ + // The return status of SIR_HAL_SET_BSSKEY_REQ is reported here + eHalStatus status; + tANI_U8 dpuDescIndx; + tANI_U8 dpuSignature; +} tGetDpuParams, *tpGetDpuParams; + + + +//HAL MSG: SIR_HAL_UPDATE_BEACON_IND +typedef struct +{ + + tANI_U8 bssIdx; + + //shortPreamble mode. HAL should update all the STA rates when it + //receives this message + tANI_U8 fShortPreamble; + //short Slot time. + tANI_U8 fShortSlotTime; + //Beacon Interval + tANI_U16 beaconInterval; + //Protection related + tANI_U8 llaCoexist; + tANI_U8 llbCoexist; + tANI_U8 llgCoexist; + tANI_U8 ht20MhzCoexist; + tANI_U8 llnNonGFCoexist; + tANI_U8 fLsigTXOPProtectionFullSupport; + tANI_U8 fRIFSMode; + + tANI_U16 paramChangeBitmap; + tANI_U8 smeSessionId; +}tUpdateBeaconParams, *tpUpdateBeaconParams; + +#ifdef WLAN_FEATURE_11AC +typedef struct +{ + tANI_U16 opMode; + tANI_U16 staId; + tANI_U16 smesessionId; + tSirMacAddr peer_mac; +}tUpdateVHTOpMode, *tpUpdateVHTOpMode; + +typedef struct +{ + tANI_U16 rxNss; + tANI_U16 staId; + tANI_U16 smesessionId; + tSirMacAddr peer_mac; +}tUpdateRxNss, *tpUpdateRxNss; + +typedef struct +{ + tANI_U32 membership; + tANI_U16 staId; + tANI_U16 smesessionId; + tSirMacAddr peer_mac; +}tUpdateMembership, *tpUpdateMembership; + +typedef struct +{ + tANI_U32 userPos; + tANI_U16 staId; + tANI_U16 smesessionId; + tSirMacAddr peer_mac; +}tUpdateUserPos, *tpUpdateUserPos; + +#endif + +//HAL MSG: SIR_HAL_UPDATE_CF_IND +typedef struct +{ + + tANI_U8 bssIdx; + + /* + * cfpCount indicates how many DTIMs (including the current frame) appear before the next CFP start. + * A CFPCount of 0 indicates that the current DTIM marks the start of the CFP. + */ + tANI_U8 cfpCount; + + /* cfpPeriod indicates the number of DTIM intervals between the start of CFPs. */ + tANI_U8 cfpPeriod; + +}tUpdateCFParams, *tpUpdateCFParams; + + + +//HAL MSG: SIR_HAL_UPDATE_DTIM_IND +//This message not required, as Softmac is supposed to read these values from the beacon. +//PE should not look at TIM element + +/* +typedef struct +{ + tANI_U8 bssIdx; + + + //The DTIM Count field indicates how many beacons (including the current frame) appear before the next + // DTIM. A DTIM Count of 0 indicates that the current TIM is a DTIM. + // + tANI_U8 dtimCount; + + + // The DTIM Period field indicates the number of Beacon intervals between successive DTIMs. If all TIMs are + // DTIMs, the DTIM Period field has the value 1. The DTIM Period value 0 is reserved. + // + tANI_U8 dtimPeriod; + +}tUpdateDtimParams, *tpUpdateDtimParams; +*/ + + +//HAL MSG: SIR_HAL_CHNL_SWITCH_REQ +typedef struct +{ + tANI_U8 channelNumber; +#ifndef WLAN_FEATURE_VOWIFI + tANI_U8 localPowerConstraint; +#endif /* WLAN_FEATURE_VOWIFI */ + ePhyChanBondState secondaryChannelOffset; + tANI_U8 peSessionId; +#if defined WLAN_FEATURE_VOWIFI + tPowerdBm txMgmtPower; //HAL fills in the tx power used for mgmt frames in this field. + tPowerdBm maxTxPower; +#endif + tSirMacAddr selfStaMacAddr; + //the request has power constraints, this should be applied only to that session + /* VO Wifi comment: BSSID is needed to identify which session issued this request. As the + request has power constraints, this should be applied only to that session */ + /* V IMP: Keep bssId field at the end of this msg. It is used to mantain backward compatbility + * by way of ignoring if using new host/old FW or old host/new FW since it is at the end of this struct + */ + tSirMacAddr bssId; + + eHalStatus status; + + tANI_U16 chainMask; + + tANI_U16 smpsMode; + + tANI_U8 isDfsChannel; + + tANI_U8 vhtCapable; + + tANI_U8 dot11_mode; + + uint8_t restart_on_chan_switch; +}tSwitchChannelParams, *tpSwitchChannelParams; + +typedef struct CSAOffloadParams { + tANI_U8 channel; + tANI_U8 switchmode; + tANI_U8 sec_chan_offset; + tANI_U8 new_ch_width; /* New channel width */ + tANI_U8 new_ch_freq_seg1; /* Channel Center frequency 1 */ + tANI_U8 new_ch_freq_seg2; /* Channel Center frequency 2 */ + tANI_U32 ies_present_flag; /* WMI_CSA_EVENT_IES_PRESENT_FLAG */ + tSirMacAddr bssId; +}*tpCSAOffloadParams, tCSAOffloadParams; + +typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam, + bool status); + +typedef struct sLinkStateParams +{ + // SIR_HAL_SET_LINK_STATE + tSirMacAddr bssid; + tSirMacAddr selfMacAddr; + tSirLinkState state; + tpSetLinkStateCallback callback; + void *callbackArg; +#ifdef WLAN_FEATURE_VOWIFI_11R + int ft; + void * session; +#endif + v_BOOL_t status; +} tLinkStateParams, * tpLinkStateParams; + + +typedef struct +{ + tANI_U16 staIdx; + tANI_U16 tspecIdx; //TSPEC handler uniquely identifying a TSPEC for a STA in a BSS + tSirMacTspecIE tspec; + eHalStatus status; + tANI_U8 sessionId; //PE session id for PE<->HAL interface +#ifdef FEATURE_WLAN_ESE + tANI_U16 tsm_interval; // TSM interval period passed from lim to wda +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tANI_U8 setRICparams; +#endif + uint8_t sme_session_id; +} tAddTsParams, *tpAddTsParams; + +typedef struct +{ + tANI_U16 staIdx; + tANI_U16 tspecIdx; //TSPEC identifier uniquely identifying a TSPEC for a STA in a BSS + tSirMacAddr bssId; //TO SUPPORT BT-AMP + tANI_U8 sessionId; + tANI_U8 userPrio; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tSirDeltsReqInfo delTsInfo; + tANI_U8 setRICparams; +#endif +} tDelTsParams, *tpDelTsParams; + +#ifdef WLAN_FEATURE_VOWIFI_11R + +#define HAL_QOS_NUM_TSPEC_MAX 2 +#define HAL_QOS_NUM_AC_MAX 4 + +typedef struct +{ + tANI_U16 staIdx; + tANI_U16 tspecIdx; //TSPEC handler uniquely identifying a TSPEC for a STA in a BSS + tSirMacTspecIE tspec[HAL_QOS_NUM_AC_MAX]; + eHalStatus status[HAL_QOS_NUM_AC_MAX]; + tANI_U8 sessionId; //PE session id for PE<->HAL interface +}tAggrAddTsParams, *tpAggrAddTsParams; + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + +typedef tSirRetStatus (*tHalMsgCallback)(tpAniSirGlobal pMac, tANI_U32 mesgId, void *mesgParam ); + + +typedef struct +{ + tANI_U16 bssIdx; + tSirMacEdcaParamRecord acbe; // best effort + tSirMacEdcaParamRecord acbk; // background + tSirMacEdcaParamRecord acvi; // video + tSirMacEdcaParamRecord acvo; // voice +} tEdcaParams, *tpEdcaParams; + +/* +* Function Prototypes +*/ + +eHalStatus halMsg_setPromiscMode(tpAniSirGlobal pMac); + + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_ADDBA_REQ +// +typedef struct sAddBAParams +{ + + // Station Index + tANI_U16 staIdx; + + // Peer MAC Address + tSirMacAddr peerMacAddr; + + // ADDBA Action Frame dialog token + // HAL will not interpret this object + tANI_U8 baDialogToken; + + // TID for which the BA is being setup + // This identifies the TC or TS of interest + tANI_U8 baTID; + + // 0 - Delayed BA (Not supported) + // 1 - Immediate BA + tANI_U8 baPolicy; + + // Indicates the number of buffers for this TID (baTID) + // NOTE - This is the requested buffer size. When this + // is processed by HAL and subsequently by HDD, it is + // possible that HDD may change this buffer size. Any + // change in the buffer size should be noted by PE and + // advertized appropriately in the ADDBA response + tANI_U16 baBufferSize; + + // BA timeout in TU's + // 0 means no timeout will occur + tANI_U16 baTimeout; + + // b0..b3 - Fragment Number - Always set to 0 + // b4..b15 - Starting Sequence Number of first MSDU + // for which this BA is setup + tANI_U16 baSSN; + + // ADDBA direction + // 1 - Originator + // 0 - Recipient + tANI_U8 baDirection; + + // + // Following parameters are for returning status from + // HAL to PE via response message. HAL does not read them + // + // The return status of SIR_HAL_ADDBA_REQ is reported + // in the SIR_HAL_ADDBA_RSP message + eHalStatus status; + + // Indicating to HAL whether a response message is required. + tANI_U8 respReqd; + tANI_U8 sessionId; // PE session id for PE<->HAL interface + // HAL Sends back the PE session + // id unmodified + +} tAddBAParams, * tpAddBAParams; + + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_DELBA_IND +// +typedef struct sDelBAParams +{ + + // Station Index + tANI_U16 staIdx; + + // TID for which the BA session is being deleted + tANI_U8 baTID; + + // DELBA direction + // 1 - Originator + // 0 - Recipient + tANI_U8 baDirection; + + // FIXME - Do we need a response for this? + // Maybe just the IND/REQ will suffice? + // + // Following parameters are for returning status from + // HAL to PE via response message. HAL does not read them + // + // The return status of SIR_HAL_DELBA_REQ is reported + // in the SIR_HAL_DELBA_RSP message + //eHalStatus status; + +} tDelBAParams, * tpDelBAParams; + + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_SET_MIMOPS_REQ +// +typedef struct sSet_MIMOPS +{ + // Station Index + tANI_U16 staIdx; + + // MIMO Power Save State + tSirMacHTMIMOPowerSaveState htMIMOPSState; + // The return status of SIR_HAL_SET_MIMOPS_REQ is reported + // in the SIR_HAL_SET_MIMOPS_RSP message + eHalStatus status; + tANI_U8 fsendRsp; + + tSirMacAddr peerMac; + tANI_U8 sessionId; +} tSetMIMOPS, * tpSetMIMOPS; + + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_EXIT_BMPS_REQ +// +typedef struct sExitBmpsParams +{ + tANI_U8 sendDataNull; + eHalStatus status; + tANI_U8 bssIdx; +} tExitBmpsParams, *tpExitBmpsParams; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_ENTER_UAPSD_REQ +// +typedef struct sUapsdParams +{ + tANI_U8 bkDeliveryEnabled:1; + tANI_U8 beDeliveryEnabled:1; + tANI_U8 viDeliveryEnabled:1; + tANI_U8 voDeliveryEnabled:1; + tANI_U8 bkTriggerEnabled:1; + tANI_U8 beTriggerEnabled:1; + tANI_U8 viTriggerEnabled:1; + tANI_U8 voTriggerEnabled:1; + eHalStatus status; + tANI_U8 bssIdx; +}tUapsdParams, *tpUapsdParams; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_EXIT_UAPSD_REQ +// +typedef struct sExitUapsdParams +{ + eHalStatus status; + tANI_U8 bssIdx; +}tExitUapsdParams, *tpExitUapsdParams; + +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_LIM_DEL_BA_IND +// +typedef struct sBADeleteParams +{ + + // Station Index + tANI_U16 staIdx; + + // Peer MAC Address, whose BA session has timed out + tSirMacAddr peerMacAddr; + + // TID for which a BA session timeout is being triggered + tANI_U8 baTID; + + // DELBA direction + // 1 - Originator + // 0 - Recipient + tANI_U8 baDirection; + + tANI_U32 reasonCode; + + tSirMacAddr bssId; // TO SUPPORT BT-AMP + // HAL copies the sta bssid to this. +} tBADeleteParams, * tpBADeleteParams; + + +// Mesg Type = SIR_LIM_ADD_BA_IND +typedef struct sBaActivityInd +{ + tANI_U16 baCandidateCnt; + //baCandidateCnt is followed by BA Candidate List ( tAddBaCandidate) + + tSirMacAddr bssId; // TO SUPPORT BT-AMP +} tBaActivityInd, * tpBaActivityInd; + + +// Mesg Type = SIR_LIM_IBSS_PEER_INACTIVITY_IND +typedef struct sIbssPeerInactivityInd +{ + tANI_U8 bssIdx; + tANI_U8 staIdx; + tSirMacAddr staAddr; +}tIbssPeerInactivityInd, *tpIbssPeerInactivityInd; + + +typedef struct tHalIndCB +{ + + tHalMsgCallback pHalIndCB; + +}tHalIndCB,*tpHalIndCB; + +/** Max number of bytes required for stations bitmap aligned at 4 bytes boundary */ +#define HALMSG_NUMBYTES_STATION_BITMAP(x) (((x / 32) + ((x % 32)?1:0)) * 4) + +typedef struct sControlTxParams +{ + tANI_BOOLEAN stopTx; + /* Master flag to stop or resume all transmission, Once this flag is set, + * softmac doesnt look for any other details. + */ + tANI_U8 fCtrlGlobal; + /* If this flag is set, staBitmap[] is valid */ + tANI_U8 ctrlSta; + /* If this flag is set, bssBitmap and beaconBitmap is valid */ + tANI_U8 ctrlBss; + + /* When ctrlBss is set, this bitmap contains bitmap of BSS indices to be + * stopped for resumed for transmission. + * This is 32 bit bitmap, not array of bytes. + */ + tANI_U32 bssBitmap; + /* When ctrlBss is set, this bitmap contains bitmap of BSS indices to be + * stopped for resumed for beacon transmission. + */ + tANI_U32 beaconBitmap; + + /** + * Memory for the station bitmap will be allocated later based on + * the number of station supported. + */ +} tTxControlParams, * tpTxControlParams; + +typedef struct sEnterBmpsParams +{ + //TBTT value derived from the last beacon + tANI_U8 bssIdx; + tANI_U64 tbtt; + tANI_U8 dtimCount; + //DTIM period given to HAL during association may not be valid, + //if association is based on ProbeRsp instead of beacon. + tANI_U8 dtimPeriod; + + // For ESE and 11R Roaming + tANI_U8 bRssiFilterEnable; + tANI_U32 rssiFilterPeriod; + tANI_U32 numBeaconPerRssiAverage; + + eHalStatus status; + tANI_U8 respReqd; +}tEnterBmpsParams, *tpEnterBmpsParams; + +//BMPS response +typedef struct sEnterBmpsRspParams +{ + /* success or failure */ + tANI_U32 status; + tANI_U8 bssIdx; +}tEnterBmpsRspParams, *tpEnterBmpsRspParams; +// +// Mesg header is used from tSirMsgQ +// Mesg Type = SIR_HAL_SET_MAX_TX_POWER_REQ +// +typedef struct sMaxTxPowerParams +{ + tSirMacAddr bssId; // BSSID is needed to identify which session issued this request. As + //the request has power constraints, this should be applied only to that session + tSirMacAddr selfStaMacAddr; + //In request, + //power == MaxTx power to be used. + //In response, + //power == tx power used for management frames. + tPowerdBm power; + tVOS_CON_MODE dev_mode; +}tMaxTxPowerParams, *tpMaxTxPowerParams; + +typedef struct sMaxTxPowerPerBandParams +{ + eCsrBand bandInfo; + tPowerdBm power; +}tMaxTxPowerPerBandParams, *tpMaxTxPowerPerBandParams; + +typedef struct sAddStaSelfParams +{ + tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; + tANI_U32 type; + tANI_U32 subType; + tANI_U8 sessionId; + tANI_U32 status; + tANI_U16 pkt_err_disconn_th; + uint8_t nss_2g; + uint8_t nss_5g; +}tAddStaSelfParams, *tpAddStaSelfParams; + +/** + * struct set_ie_param - set IE params structure + * @pdev_id: pdev id + * @ie_type: IE type + * @nss: Nss value + * @ie_len: IE length + * @*ie_ptr: Pointer to IE data + * + * Holds the set pdev IE req data. + */ +struct set_ie_param { + uint8_t pdev_id; + uint8_t ie_type; + uint8_t nss; + uint8_t ie_len; + uint8_t *ie_ptr; +}; + +#define DOT11_HT_IE 1 +#define DOT11_VHT_IE 2 + +#ifdef FEATURE_WLAN_TDLS + +#define HAL_TDLS_MAX_SUPP_CHANNELS 128 +#define HAL_TDLS_MAX_SUPP_OPER_CLASSES 32 + +typedef struct { + tANI_U8 isPeerResponder; + tANI_U8 peerUapsdQueue; + tANI_U8 peerMaxSp; + tANI_U8 peerBuffStaSupport; + tANI_U8 peerOffChanSupport; + tANI_U8 peerCurrOperClass; + tANI_U8 selfCurrOperClass; + tANI_U8 peerChanLen; + tSirUpdateChanParam peerChan[HAL_TDLS_MAX_SUPP_CHANNELS]; + tANI_U8 peerOperClassLen; + tANI_U8 peerOperClass[HAL_TDLS_MAX_SUPP_OPER_CLASSES]; + tANI_U8 prefOffChanNum; + tANI_U8 prefOffChanBandwidth; + tANI_U8 opClassForPrefOffChan; +} tTdlsPeerCapParams; + +typedef struct sTdlsPeerStateParams +{ + tANI_U32 vdevId; + tSirMacAddr peerMacAddr; + tANI_U32 peerState; + tTdlsPeerCapParams peerCap; +}tTdlsPeerStateParams; + +typedef struct sTdlsChanSwitchParams +{ + tANI_U32 vdevId; + tSirMacAddr peerMacAddr; + tANI_U16 tdlsOffChBwOffset;/* Target Off Channel Bandwidth offset */ + tANI_U8 tdlsOffCh; /* Target Off Channel */ + tANI_U8 tdlsSwMode; /* TDLS Off Channel Mode */ + tANI_U8 operClass; /* Operating class corresponding to target channel */ + tANI_U8 is_responder;/* responder or initiator */ +}tTdlsChanSwitchParams; +#endif /* FEATURE_WLAN_TDLS */ + +typedef struct sAbortScanParams +{ + tANI_U8 SessionId; +}tAbortScanParams, *tpAbortScanParams; + +typedef struct sDelStaSelfParams +{ + tSirMacAddr selfMacAddr; + tANI_U8 sessionId; + tANI_U32 status; +}tDelStaSelfParams, *tpDelStaSelfParams; + +typedef struct sP2pPsParams +{ + tANI_U8 opp_ps; + tANI_U32 ctWindow; + tANI_U8 count; + tANI_U32 duration; + tANI_U32 interval; + tANI_U32 single_noa_duration; + tANI_U8 psSelection; + tANI_U8 sessionId; +}tP2pPsParams, *tpP2pPsParams; + +#define HAL_MAX_SUPP_CHANNELS 128 +#define HAL_MAX_SUPP_OPER_CLASSES 32 + +typedef struct sTdlsLinkEstablishParams +{ + tANI_U16 staIdx; + tANI_U8 isResponder; + tANI_U8 uapsdQueues; + tANI_U8 maxSp; + tANI_U8 isBufsta; + tANI_U8 isOffChannelSupported; + tANI_U8 peerCurrOperClass; + tANI_U8 selfCurrOperClass; + tANI_U8 validChannelsLen; + tANI_U8 validChannels[HAL_MAX_SUPP_CHANNELS]; + tANI_U8 validOperClassesLen; + tANI_U8 validOperClasses[HAL_MAX_SUPP_OPER_CLASSES]; + tANI_U32 status; +}tTdlsLinkEstablishParams, *tpTdlsLinkEstablishParams; + +typedef struct tHalHiddenSsidVdevRestart +{ + tANI_U8 ssidHidden; + tANI_U8 sessionId; +}tHalHiddenSsidVdevRestart,*tpHalHiddenSsidVdevRestart; + +static inline void halGetTxTSFtimer(tpAniSirGlobal pMac, + tSirMacTimeStamp *pTime) +{ +} + +extern void SysProcessMmhMsg(tpAniSirGlobal pMac, tSirMsgQ* pMsg); + +/* Beacon Filtering data structures */ +typedef __ani_attr_pre_packed struct sBeaconFilterMsg +{ + tANI_U16 capabilityInfo; + tANI_U16 capabilityMask; + tANI_U16 beaconInterval; + tANI_U16 ieNum; + tANI_U8 bssIdx; + tANI_U8 reserved; +} __ani_attr_packed tBeaconFilterMsg, *tpBeaconFilterMsg; + +typedef __ani_attr_pre_packed struct sEidByteInfo +{ + tANI_U8 offset; + tANI_U8 value; + tANI_U8 bitMask; + tANI_U8 ref; +} __ani_attr_packed tEidByteInfo, *tpEidByteInfo; + + +/* The above structure would be followed by multiple of below mentioned +structure */ +typedef __ani_attr_pre_packed struct sBeaconFilterIe +{ + tANI_U8 elementId; + tANI_U8 checkIePresence; + tEidByteInfo byte; +} __ani_attr_packed tBeaconFilterIe, *tpBeaconFilterIe; + +typedef __ani_attr_pre_packed struct sRemBeaconFilterMsg +{ + tANI_U8 ucIeCount; + tANI_U8 ucRemIeId[1]; +} __ani_attr_packed tRemBeaconFilterMsg, *tpRemBeaconFilterMsg; + +typedef __ani_attr_pre_packed struct sDisableIntraBssFwd +{ + tANI_U16 sessionId; + tANI_BOOLEAN disableintrabssfwd; +} __ani_attr_packed tDisableIntraBssFwd, *tpDisableIntraBssFwd; + +#ifdef WLAN_FEATURE_STATS_EXT +typedef struct sStatsExtRequest +{ + tANI_U32 vdev_id; + tANI_U32 request_data_len; + tANI_U8 request_data[]; +} tStatsExtRequest, *tpStatsExtRequest; +#endif + +#ifdef WLAN_FEATURE_NAN +typedef struct sNanRequest +{ + tANI_U16 request_data_len; + tANI_U8 request_data[]; +} tNanRequest, *tpNanRequest; +#endif + +#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 */ + +#ifdef WLAN_FEATURE_APFIND +struct hal_apfind_request +{ + u_int16_t request_data_len; + u_int8_t request_data[]; +}; +#endif + +#endif /* _HALMSGAPI_H_ */ diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halTypes.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halTypes.h new file mode 100644 index 000000000000..c0bb0359ec92 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halTypes.h @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file halTypes.h + + \brief This header captures types that must be shared in common with individual + module headers before inclusion into halCommonApi.h. + + $Id$========================================================================== */ + +#ifndef HALTYPES_H +#define HALTYPES_H +#ifndef WINXP_APPS_BUILD //TODO: this header dependency does not belong in this file + +#endif /* WINXP_APPS_BUILD */ + +#include "palTypes.h" +#include "wlan_nv.h" + +#define OFFSET_OF(structType,fldName) (&((structType*)0)->fldName) + +/** ------------------------------------------------------------------------- * + + \typedef tHalHandle + + \brief Handle to the HAL. The HAL handle is returned by the HAL after it + is opened (by calling halOpen). + + -------------------------------------------------------------------------- */ +typedef void *tHalHandle; + +// define a value for an invalid HAL handle..... +#define HAL_INVALID_HAL_HANDLE ( NULL ) + + +/** ------------------------------------------------------------------------- * + + \enum eHalStatus + + \brief Enumeration of all status codes returned by the higher level + HAL interface functions. + + -------------------------------------------------------------------------- */ +typedef enum +{ + eHAL_STATUS_SUCCESS, + + // general failure. This status applies to all failure that are not covered + // by more specific return codes. + eHAL_STATUS_FAILURE, + eHAL_STATUS_FAILED_ALLOC, + eHAL_STATUS_RESOURCES, + + // the HAL has not been opened and a HAL function is being attempted. + eHAL_STATUS_NOT_OPEN, + + // function failed due to the card being removed... + eHAL_STATUS_CARD_NOT_PRESENT, + + //halInterrupt status + eHAL_STATUS_INTERRUPT_ENABLED, + eHAL_STATUS_INTERRUPT_DISABLED, + eHAL_STATUS_NO_INTERRUPTS, + eHAL_STATUS_INTERRUPT_PRESENT, + eHAL_STATUS_ALL_INTERRUPTS_PROCESSED, + eHAL_STATUS_INTERRUPT_NOT_PROCESSED, //interrupt cleared but no Isr to process + + // a parameter on the PAL function call is not valid. + eHAL_STATUS_INVALID_PARAMETER, + + // the PAL has not been initialized... + eHAL_STATUS_NOT_INITIALIZED, + + // Error codes for PE-HAL message API + eHAL_STATUS_INVALID_STAIDX, + eHAL_STATUS_INVALID_BSSIDX, + eHAL_STATUS_STA_TABLE_FULL, // No space to add more STA, sta table full. + eHAL_STATUS_BSSID_TABLE_FULL, + eHAL_STATUS_DUPLICATE_BSSID, + eHAL_STATUS_DUPLICATE_STA, + eHAL_STATUS_BSSID_INVALID, + eHAL_STATUS_STA_INVALID, + eHAL_STATUS_INVALID_KEYID, + eHAL_STATUS_INVALID_SIGNATURE, + + //DXE + eHAL_STATUS_DXE_FAILED_NO_DESCS, + eHAL_STATUS_DXE_CHANNEL_NOT_CONFIG, // Channel not configured + eHAL_STATUS_DXE_CHANNEL_MISUSE, // Specified operation inconsistent w/ configuration + eHAL_STATUS_DXE_VIRTUAL_MEM_ALLOC_ERROR, // + eHAL_STATUS_DXE_SHARED_MEM_ALLOC_ERROR, // + eHAL_STATUS_DXE_INVALID_CHANNEL, + eHAL_STATUS_DXE_INVALID_CALLBACK, + eHAL_STATUS_DXE_INCONSISTENT_DESC_COUNT, + eHAL_STATUS_DXE_XFR_QUEUE_ERROR, + eHAL_STATUS_DXE_INVALID_BUFFER, + eHAL_STATUS_DXE_INCOMPLETE_PACKET, + eHAL_STATUS_DXE_INVALID_PARAMETER, + eHAL_STATUS_DXE_CH_ALREADY_CONFIGURED, + eHAL_STATUS_DXE_USB_INVALID_EP, + eHAL_STATUS_DXE_GEN_ERROR, + + + // status codes added for the ImageValidate library + eHAL_STATUS_E_NULL_VALUE, + eHAL_STATUS_E_FILE_NOT_FOUND, + eHAL_STATUS_E_FILE_INVALID_CONTENT, + eHAL_STATUS_E_MALLOC_FAILED, + eHAL_STATUS_E_FILE_READ_FAILED, + eHAL_STATUS_E_IMAGE_INVALID, + eHAL_STATUS_E_IMAGE_UNSUPPORTED, + + // status code returned by device memory calls when memory is + // not aligned correctly. + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED, // memory access is not aligned on a 4 byte boundary + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR, // memory access is not a multiple of 4 bytes + + // Generic status code to indicate network congestion. + eHAL_STATUS_NET_CONGESTION, + + // various status codes for Rx packet dropped conditions... Note the Min and Max + // enums that bracked the Rx Packet Dropped status codes. There is code that + // looks at the various packet dropped conditions so make sure these min / max + // enums remain accurate. + eHAL_STATUS_RX_PACKET_DROPPED, + eHAL_STATUS_RX_PACKET_DROPPED_MIN = eHAL_STATUS_RX_PACKET_DROPPED, + eHAL_STATUS_RX_PACKET_DROPPED_NULL_DATA, + eHAL_STATUS_RX_PACKET_DROPPED_WDS_FRAME, + eHAL_STATUS_RX_PACKET_DROPPED_FILTERED, + eHAL_STATUS_RX_PACKET_DROPPED_GROUP_FROM_SELF, + eHAL_STATUS_RX_PACKET_DROPPED_MAX = eHAL_STATUS_RX_PACKET_DROPPED_GROUP_FROM_SELF, + + // Status indicating that PMU did not power up and hence indicative of the fact that the clocks are not on + eHAL_STATUS_PMU_NOT_POWERED_UP, + + // Queuing code for BA message API + eHAL_STATUS_BA_ENQUEUED, // packets have been buffered in Host + eHAL_STATUS_BA_INVALID, + + // A-MPDU/BA related Error codes + eHAL_STATUS_BA_RX_BUFFERS_FULL, + eHAL_STATUS_BA_RX_MAX_SESSIONS_REACHED, + eHAL_STATUS_BA_RX_INVALID_SESSION_ID, + + // !!LAC - can we rework the code so these are not needed? + eHAL_STATUS_BA_RX_DROP_FRAME, + eHAL_STATUS_BA_RX_INDICATE_FRAME, + eHAL_STATUS_BA_RX_ENQUEUE_FRAME, + + // PMC return codes. + eHAL_STATUS_PMC_PENDING, + eHAL_STATUS_PMC_DISABLED, + eHAL_STATUS_PMC_NOT_NOW, + eHAL_STATUS_PMC_AC_POWER, + eHAL_STATUS_PMC_SYS_ERROR, + eHAL_STATUS_PMC_CANNOT_ENTER_IMPS, + eHAL_STATUS_PMC_ALREADY_IN_IMPS, + + eHAL_STATUS_HEARTBEAT_TMOUT, + eHAL_STATUS_NTH_BEACON_DELIVERY, + + //CSR + eHAL_STATUS_CSR_WRONG_STATE, + + // DPU + eHAL_STATUS_DPU_DESCRIPTOR_TABLE_FULL, + eHAL_STATUS_DPU_MICKEY_TABLE_FULL, + + // HAL-FW messages + eHAL_STATUS_FW_MSG_FAILURE, // Error in Hal-FW message interface + eHAL_STATUS_FW_MSG_TIMEDOUT, + eHAL_STATUS_FW_MSG_INVALID, + eHAL_STATUS_FW_SEND_MSG_FAILED, + eHAL_STATUS_FW_PS_BUSY, + + eHAL_STATUS_TIMER_START_FAILED, + eHAL_STATUS_TIMER_STOP_FAILED, + + eHAL_STATUS_TL_SUSPEND_TIMEOUT, + + eHAL_STATUS_UMA_DESCRIPTOR_TABLE_FULL, + + eHAL_STATUS_SET_CHAN_ALREADY_ON_REQUESTED_CHAN, + +#ifdef WLAN_FEATURE_VOWIFI_11R + eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS, + eHAL_STATUS_FT_PREAUTH_KEY_FAILED, +#endif + //CMD not Queued in SME + eHAL_STATUS_CMD_NOT_QUEUED, + // not a real status. Just a way to mark the maximum in the enum. + eHAL_STATUS_MAX + +} eHalStatus; + +typedef enum +{ + HAL_STOP_TYPE_SYS_RESET, + HAL_STOP_TYPE_SYS_DEEP_SLEEP, + HAL_STOP_TYPE_RF_KILL, +}tHalStopType; + +// macro to check for SUCCESS value of the halStatus +#define HAL_STATUS_SUCCESS( variable ) ( eHAL_STATUS_SUCCESS == ( variable ) ) + +/// Bit value data structure +typedef enum sHalBitVal // For Bit operations +{ + eHAL_CLEAR, + eHAL_SET +}tHalBitVal; + +// ------------------------------------------------------------- +/// MMH APIs +enum { + eHI_PRI, + ePROT, + eDBG +}; + +/// System role definition on a per BSS +typedef enum eBssSystemRole +{ + eSYSTEM_UNKNOWN_ROLE, + eSYSTEM_AP_ROLE, + eSYSTEM_STA_IN_IBSS_ROLE, + eSYSTEM_STA_ROLE, + eSYSTEM_BTAMP_STA_ROLE, + eSYSTEM_BTAMP_AP_ROLE, + + eSYSTEM_LAST_ROLE, + eSYSTEM_MULTI_BSS_ROLE = eSYSTEM_LAST_ROLE +} tBssSystemRole; + + +// --------------------------------------- +// Channel Bonding Sideband configuration +// --------------------------------------- +typedef enum sHalCBsidebandType +{ + eHAL_SIDEBAND_CENTER=0, + eHAL_SIDEBAND_LOWER, + eHAL_SIDEBAND_UPPER, + eHAL_SIDEBAND_COPY +}tHalCBsidebandType; + + +/// HAL states +typedef enum { + eHAL_IDLE, + eHAL_INIT, + eHAL_CFG, //CFG download completed. + eHAL_STARTED, //halProcessStartEvent compelted. + eHAL_SYS_READY, //Sys_ready msg received from HDD. + eHAL_NORMAL, //Sys_ready msg received from HDD and halProcessStartEvent completed. +} tHAL_STATE; + + + + +// Type to define softmac mode (also system mode) +typedef enum +{ + //3- Promisc, 2 - Scan, 1 - Learn 0 - Normal + eHAL_SYS_MODE_NORMAL = 0, + eHAL_SYS_MODE_LEARN, + eHAL_SYS_MODE_SCAN, + eHAL_SYS_MODE_PROMISC, + eHAL_SYS_MODE_SUSPEND_LINK, + eHAL_SYS_MODE_ROAM_SCAN, + eHAL_SYS_MODE_ROAM_SUSPEND_LINK, +} eHalSysMode; + + + + +// HAL frame types. Used on the TxRx APIs and the +// corresponding PAL routines. +typedef enum { + + HAL_TXRX_FRM_RAW, + HAL_TXRX_FRM_ETH2, + HAL_TXRX_FRM_802_3, + HAL_TXRX_FRM_802_11_MGMT, + HAL_TXRX_FRM_802_11_CTRL, + HAL_TXRX_FRM_802_11_DATA, + HAL_TXRX_FRM_IGNORED, //This frame will be dropped + HAL_TXRX_FRM_MAX + +} eFrameType; + + +typedef enum +{ + ANI_TXDIR_IBSS = 0, + ANI_TXDIR_TODS, + ANI_TXDIR_FROMDS, + ANI_TXDIR_WDS + +} eFrameTxDir; + +typedef enum +{ + eRF_BAND_UNKNOWN = 0, + eRF_BAND_2_4_GHZ = 1, + eRF_BAND_5_GHZ = 2 +} eRfBandMode; + + +#ifndef __offsetof +#define __offsetof(type, field) ((tANI_U32)(&((type *)0)->field)) +#endif + +#ifndef offsetof +#define offsetof(type, field) __offsetof(type, field) +#endif + +#define HAL_MAX_TXPOWER_INVALID 127 + +/* These are the min/max tx power (non virtual rates) range + * supported by rome/prima hardware + */ +#define MIN_TX_PWR_CAP 8 +#define MAX_TX_PWR_CAP 22 + +/* Moving the miscellaneous defination required by UMAC are moved here from + * volansdefs.h */ + +/* + * Volans supports 8 stations in hardware + * + * Volans without Virtual STA feature can only support 8 stations: + * 1 Broadcast STA (hard) + * 1 "Self" STA (hard) + * 6 Soft AP Stations (hard) + * + * Volans with Virtual STA feature supports 14 stations: + * 1 Broadcast STA (hard) + * 1 "Self" STA (hard) + * 2 General Purpose Stations to support Virtual STAs (hard) + * 10 Soft AP Stations (4 hard/6 virtual) + */ + +#define HAL_INVALID_BSSIDX (HAL_NUM_BSSID + 1) +#define HAL_NUM_UMA_DESC_ENTRIES 8 +#define MAX_NUM_OF_BACKOFFS 8 + +#define IS_VALID_BSSIDX(__x) \ + ((__x) < HAL_NUM_BSSID) + +#ifdef WLAN_SOFTAP_VSTA_FEATURE +#define HAL_NUM_ASSOC_STA 32 +#define HAL_NUM_STA 41 +#define HAL_NUM_HW_STA 16 +#define HAL_NUM_GPSTA 4 +#define HAL_NUM_VSTA (HAL_NUM_STA - HAL_NUM_HW_STA) + +#define QWLANFW_MAX_NUM_VSTA HAL_NUM_VSTA +#define QWLANFW_VSTA_INVALID_IDX (HAL_NUM_STA + 1) +#define QWLAN_VSTA_MIN_IDX HAL_NUM_HW_STA +#define QWLANFW_NUM_GPSTA HAL_NUM_GPSTA + + +#define IS_VSTA_VALID_IDX(__x) \ + ((__x) != QWLANFW_VSTA_INVALID_IDX) + +#define IS_VSTA_IDX(__x) \ + (((__x) >= QWLAN_VSTA_MIN_IDX) && ((__x) < HAL_NUM_STA)) + + +// is the STA a General Purpose STA? +#define IS_GPSTA_IDX(__x) \ + (((__x) >= (HAL_NUM_HW_STA-HAL_NUM_GPSTA)) && \ + ((__x) < HAL_NUM_HW_STA)) + +// is the STA a HW STA (excluding GP STAs) +#define IS_HWSTA_IDX(__x) \ + ((__x) < (HAL_NUM_HW_STA-HAL_NUM_GPSTA)) + +#else +/*In prima 12 HW stations are supported including BCAST STA(staId 0) + and SELF STA(staId 1) so total ASSOC stations which can connect to Prima + SoftAP = 12 - 1(Self STa) - 1(Bcast Sta) = 10 Stations. */ +#define HAL_NUM_STA 12 +#define HAL_NUM_ASSOC_STA 10 +#define HAL_NUM_HW_STA 12 +#endif + +/* + * From NOVA Mac Arch document + * Encryp. mode The encryption mode + * 000: Encryption functionality is not enabled + * 001: Encryption is set to WEP + * 010: Encryption is set to WEP 104 + * 011: Encryption is set to TKIP + * 100: Encryption is set to AES + * 101 - 111: Reserved for future + */ + +#define HAL_ENC_POLICY_NULL 0 +#define HAL_ENC_POLICY_WEP40 1 +#define HAL_ENC_POLICY_WEP104 2 +#define HAL_ENC_POLICY_TKIP 3 +#define HAL_ENC_POLICY_AES_CCM 4 + +#define STACFG_MAX_TC 8 + + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/palTypes.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/palTypes.h new file mode 100644 index 000000000000..c5163e20027a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/palTypes.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( PALTYPES_H__ ) +#define PALTYPES_H__ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file palTypes.h + + \brief Exports and types for the Platform Abstraction Layer typedefs. + These are common typedefs that can be used across Platforms (OS/compiler + and bus types). All common code should adhere to these common types. + + $Id$... description... + + ========================================================================== */ +#ifndef WINXP_APPS_BUILD +#include "vos_types.h" +#include "vos_api.h" +#endif /* WINXP_APPS_BUILD */ + +#include "halLegacyPalTypes.h" + +#ifndef MK_IMAGE_HDR + +// +// Validate the OS Type being built... +// + +#if defined(ANI_OS_TYPE_ANDROID) // ANDROID + +#if defined(ANI_OS_TYPE_QNX) +#error "more than one ANI_OS_TYPE_xxx is defined for this build" +#endif + +#elif defined( ANI_OS_TYPE_QNX ) // QNX + +#if defined(ANI_OS_TYPE_ANDROID) +#error "more than one ANI_OS_TYPE_xxx is defined for this build" +#endif + + +#elif !defined(ANI_OS_TYPE_ANDROID) && !defined(ANI_OS_TYPE_QNX) // NONE +#error "NONE of the ANI_OS_TYPE_xxx are defined for this build" +#endif + + +// +// Validate the compiler... +// +#if ( defined( ANI_COMPILER_TYPE_MSVC ) && defined( ANI_COMPILER_TYPE_GCC ) && defined( ANI_COMPILER_TYPE_RVCT ) ) +#error "more than one ANI_COMPILER_TYPE_xxx is defined for this build" + +#elif !( defined( ANI_COMPILER_TYPE_MSVC ) || defined( ANI_COMPILER_TYPE_GCC ) || defined( ANI_COMPILER_TYPE_RVCT ) ) +#error "NONE of the ANI_COMPILER_TYPE_xxx are defined for this build" + +#endif + + + +// some differences related to the compiler being used... +#if defined ( ANI_COMPILER_TYPE_GCC ) + +#define ANI_INLINE_FUNCTION static __inline__ + +#elif defined( ANI_COMPILER_TYPE_MSVC ) + +#define ANI_INLINE_FUNCTION __inline + +#elif defined( ANI_COMPILER_TYPE_RVCT ) + +#define ANI_INLINE_FUNCTION INLINE + +#else + +#error "invalid ANI_COMPILER_TYPE definition" + +#endif +#endif + + + + +// Common type definitions... + + +typedef tANI_U32 tANI_U32_OR_PTR; + +// Buffer address; could be virt or phys; could be 32- or 64-bit depending on compile option +typedef tANI_U32_OR_PTR tANI_BUFFER_ADDR; +// which boolean is the most usefule...or both ? + +typedef enum tagAniBoolean +{ + eANI_BOOLEAN_FALSE = 0, + eANI_BOOLEAN_TRUE, + + eANI_BOOLEAN_OFF = 0, + eANI_BOOLEAN_ON = 1, +} eAniBoolean; + + + +// +// MAC address data type... +// +// review the usefulness of this type. I suspect this type is not +// real useful unless we provide some 'helper' functions to manage +// the MAC addresses. +// +#define ANI_MAC_ADDR_SIZE ( 6 ) +typedef tANI_U8 tAniMacAddr[ ANI_MAC_ADDR_SIZE ]; + + + + + +/** ------------------------------------------------------------------------- * + + \typedef tHddHandle + + \brief Handle to the HDD. The HDD handle is given to the HAL from + the HDD on halOpen. The HDD handle is an input to all HDD/PAL function + calls and represents an opaque handle to the HDD instance that is tied + to the HAL instance, opened through halOpen. + + The HDD must be able to derive it's internal instance structure pointer + through this handle. hint hint... + + -------------------------------------------------------------------------- */ +typedef void *tHddHandle; +// define a value for an invalid HAL handle..... +#define HDD_INVALID_HDD_HANDLE ( NULL ) + + +// For packet classification routines +#define PAL_BIT_MASK(offset) (1 << (offset)) +#define PAL_PKT_FLD_DSCP_OFFSET 0 +#define PAL_PKT_FLD_8021P_OFFSET 1 + +#define PAL_PKT_FLD_DSCP_MASK PAL_BIT_MASK(PAL_PKT_FLD_DSCP_OFFSET) +#define PAL_PKT_FLD_8021P_MASK PAL_BIT_MASK(PAL_PKT_FLD_8021P_OFFSET) + + + +/* +This represent an object for a spin lock and it is platform dependant +*/ +//User of this variable must initialize it to PAL_INVALID_SPINLOCK_HANDLE in order for validation to work. +typedef void * tPalSpinLockHandle; + +#define PAL_INVALID_SPINLOCK_HANDLE (NULL) + +/* + * This represent an object for a semaphore and it is platform dependant + */ +typedef void * tPalSemaphoreHandle; + + +#define PAL_TICKS_PER_SECOND 100 + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/wlan_qct_hal.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/wlan_qct_hal.h new file mode 100644 index 000000000000..7091d2e8dd30 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/wlan_qct_hal.h @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +/* + * + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ +#ifndef WLAN_QCT_HAL_H +#define WLAN_QCT_HAL_H +#include "vos_status.h" +#include "halTypes.h" +#ifndef PALTYPES_H__ + + +/// unsigned 8-bit types +#define tANI_U8 v_U8_t + +/// unsigned 16-bit types +#define tANI_U16 v_U16_t + +/// unsigned 32-bit types +#define tANI_U32 v_U32_t + +/// signed 8-bit types +#define tANI_S8 v_S7_t + +/// signed 16-bit types +#define tANI_S16 v_S15_t + +/// signed 32-bit types +#define tANI_S32 v_S31_t + +#define eHalStatus VOS_STATUS + +#endif +#define QWLAN_HAL_DXE0_MASTERID 5 + +typedef struct sHalBdGeneric { + /* 0x00 */ + // ENDIAN BEGIN + tANI_U32 dpuRF : 8; + tANI_U32 dpuSignature:3; /* Signature on RA's DPU descriptor */ + tANI_U32 staSignature:3; + tANI_U32 reserved : 14; + tANI_U32 dpuNE : 1; + tANI_U32 dpuNC : 1; + tANI_U32 bdt : 2; /* BD type */ + // ENDIAN END + + /* 0x04 */ + // ENDIAN BEGIN + tANI_U32 reserved1:32; + // ENDIAN END + + + /* 0x08 */ + // ENDIAN BEGIN + tANI_U32 headPduIdx : 16; /* Head PDU index */ + tANI_U32 tailPduIdx : 16; /* Tail PDU index */ + // ENDIAN END + + /* 0x0c */ + // ENDIAN BEGIN + tANI_U32 mpduHeaderLength : 8; /* MPDU header length */ + tANI_U32 mpduHeaderOffset : 8; /* MPDU header start offset */ + tANI_U32 mpduDataOffset : 9; /* MPDU data start offset */ + tANI_U32 pduCount : 7; /* PDU count */ + // ENDIAN END + + /* 0x10 */ + // ENDIAN BEGIN + tANI_U32 mpduLength : 16; /* MPDU length */ + tANI_U32 reserved3:4; /* DPU compression feedback */ + tANI_U32 tid : 4; /* Traffic identifier, tid */ + tANI_U32 rateIndex : 8; + // ENDIAN END + + /* 0x14 */ + // ENDIAN BEGIN + tANI_U32 dpuDescIdx : 8; + tANI_U32 addr1Index : 8; //A1 index after RxP binary search + tANI_U32 addr2Index : 8; //A2 index after RxP binary search + tANI_U32 addr3Index : 8; //A3 index after RxP binary search + // ENDIAN END +//}__ani_attr_packed __ani_attr_aligned_4 tHalBdGeneric, *tpHalBdGeneric; +} tHalBdGeneric, *tpHalBdGeneric; + + +/* + * PDU without BD + */ + +typedef struct sHalPdu { + tANI_U8 payload[124]; + tANI_U32 nextPduIdx; /* LSB 16 bits */ +//} __ani_attr_packed __ani_attr_aligned_4 tHalPdu, *tpHalPdu; +} tHalPdu, *tpHalPdu; + +/* UAPSD parameters passed per AC to HAL from TL */ +typedef struct sUapsdInfo { + tANI_U8 staidx; // STA index + tANI_U8 ac; // Access Category + tANI_U8 up; // User Priority + tANI_U32 srvInterval; // Service Interval + tANI_U32 susInterval; // Suspend Interval + tANI_U32 delayInterval; // Delay Interval +} tUapsdInfo, tpUapsdInfo; + +#define HAL_TXBD_BDRATE_DEFAULT 0 +#define HAL_TXBD_BDRATE_FIRST 1 +#define HAL_TXBD_BDRATE_SECOND 2 +#define HAL_TXBD_BDRATE_THIRD 3 + +#define HAL_FRAME_TYPE_MASK 0x30 +#define HAL_FRAME_TYPE_OFFSET 0x4 +#define HAL_FRAME_SUBTYPE_MASK 0x0F + +#define HAL_TXBD_BD_SSN_FILL_HOST 0 +#define HAL_TXBD_BD_SSN_FILL_DPU_NON_QOS 1 +#define HAL_TXBD_BD_SSN_FILL_DPU_QOS 2 + +#define HAL_ACKPOLICY_ACK_REQUIRED 0 +#define HAL_ACKPOLICY_ACK_NOTREQUIRED 1 + +#define HAL_BDRATE_BCDATA_FRAME 1 +#define HAL_BDRATE_BCMGMT_FRAME 2 +#define HAL_BDRATE_CTRL_FRAME 3 + +/* Default values for FillTx BD */ +#define HAL_DEFAULT_UNICAST_ENABLED 1 +#define HAL_RMF_DISABLED 0 +#define HAL_RMF_ENABLED 1 +#define HAL_NO_ENCRYPTION_DISABLED 0 +#define HAL_NO_ENCRYPTION_ENABLED 1 + +#define WLANHAL_RX_BD_ADDR3_SELF_IDX 0 + +// Should not use tHalTxBd nor tHalRxBd. UMAC doesn't know these HAL structure. +#define WLANHAL_TX_BD_HEADER_SIZE 40 +#define WLANHAL_RX_BD_HEADER_SIZE 76 + + +#define WLANHAL_RX_BD_HEADER_OFFSET 0 + +#define WLANHAL_RX_BD_GET_MPDU_H_OFFSET( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->mpduHeaderOffset) + +#define WLANHAL_RX_BD_GET_MPDU_D_OFFSET( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->mpduDataOffset) + +#define WLANHAL_RX_BD_GET_MPDU_LEN( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->mpduLength) + +#define WLANHAL_RX_BD_GET_MPDU_H_LEN( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->mpduHeaderLength) + +#define WLANHAL_RX_BD_GET_FT( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->ft) + +#define WLANHAL_RX_BD_GET_LLC( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->llc) + +#define WLANHAL_RX_BD_GET_TID( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->tid) + +#define WLANHAL_RX_BD_GET_ASF( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->asf) + +#define WLANHAL_RX_BD_GET_AEF( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->aef) + +#define WLANHAL_RX_BD_GET_LSF( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->lsf) + +#define WLANHAL_RX_BD_GET_ESF( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->esf) + +#define WLANHAL_RX_BD_GET_STA_ID( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->addr2Index) +#define WLANHAL_RX_BD_GET_ADDR3_IDX( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->addr3Index) +#define WLANHAL_RX_BD_GET_ADDR1_IDX( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->addr1Index) + +#define WLANHAL_TX_BD_GET_TID( _pvBDHeader ) (((tpHalTxBd)_pvBDHeader)->tid) +#define WLANHAL_TX_BD_GET_STA_ID( _pvBDHeader ) (((tpHalTxBd)_pvBDHeader)->staIndex) + +#define WLANHAL_RX_BD_GET_DPU_SIG( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->dpuSignature) + +#define WLANHAL_FC_RX_BD_REPORT_CONTENT_SIZE (2 * HAL_NUM_STA * sizeof(tANI_U8)) // size of fcSTATxQLen[HAL_NUM_STA]+fcSTACurTxRate[HAL_NUM_STA] +#define WLANHAL_FC_TX_BD_HEADER_SIZE sizeof(tHalFcTxBd) +#define WLANHAL_RX_BD_GET_FC( _pvBDHeader ) (((tpHalFcRxBd)_pvBDHeader)->fc) +#define WLANHAL_RX_BD_GET_RX_TIME_STAMP( _pvBDHeader ) (((tpHalFcRxBd)_pvBDHeader)->mclkRxTimestamp) +#define WLANHAL_RX_BD_GET_STA_VALID_MASK( _pvBDHeader ) (((tpHalFcRxBd)_pvBDHeader)->fcSTAValidMask) +#define WLANHAL_RX_BD_GET_STA_PS_STATE( _pvBDHeader ) (((tpHalFcRxBd)_pvBDHeader)->fcSTAPwrSaveStateMask) +#define WLANHAL_RX_BD_GET_STA_TH_IND( _pvBDHeader ) (((tpHalFcRxBd)_pvBDHeader)->fcSTAThreshIndMask) +#define WLANHAL_RX_BD_GET_STA_TXQ_STATUS( _pvBDHeader ) (((tpHalFcRxBd)_pvBDHeader)->fcSTATxQStatus) +#define WLANHAL_RX_BD_GET_STA_TXQ_LEN( _pvBDHeader, staIdx ) (((tpHalFcRxBd)_pvBDHeader)->fcSTATxQLen[staIdx]) +#define WLANHAL_RX_BD_GET_STA_CUR_TX_RATE( _pvBDHeader, staIdx ) (((tpHalFcRxBd)_pvBDHeader)->fcSTACurTxRate[staIdx]) + +#define WLANHAL_TX_BD_GET_RMF(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->rmf) + +#define WLANHAL_TX_BD_GET_UB(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->ub) + +#define WLANHAL_RX_BD_GET_RMF(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->rmf) + +#define WLANHAL_RX_BD_GET_UB(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->ub) + +#define WLANHAL_RX_BD_GET_RATEINDEX(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->rateIndex) + +#define WLANHAL_RX_BD_GET_TIMESTAMP(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->mclkRxTimestamp) + +#define tHalFcRxBd halFcRxBd_type +#define tpHalFcRxBd phalFcRxBd_type +#define tHalFcTxBd halFcTxBd_type +#define tpHalFcTxBd pHalFcTxBd_type +#define tHalFcTxParams tFcTxParams_type +#define tHalFcRxParams tFcRxParams_type +#define tpHalFcTxParams pFcTxParams_type +#define tpHalFcRxParams pFcRxParams_type + +/*------------ RSSI and SNR Information extraction -------------*/ +#define WLANHAL_RX_BD_GET_RSSI0( _pvBDHeader ) \ + (((((tpHalRxBd)_pvBDHeader)->phyStats0) >> 24) & 0xff) +#define WLANHAL_RX_BD_GET_RSSI1( _pvBDHeader ) \ + (((((tpHalRxBd)_pvBDHeader)->phyStats0) >> 16) & 0xff) +#define WLANHAL_RX_BD_GET_RSSI2( _pvBDHeader ) \ + (((((tpHalRxBd)_pvBDHeader)->phyStats0) >> 0) & 0xff) +#define WLANHAL_RX_BD_GET_RSSI3( _pvBDHeader ) \ + ((((tpHalRxBd)_pvBDHeader)->phyStats0) & 0xff) + +// Get the average of the 4 values. +#define WLANHAL_GET_RSSI_AVERAGE( _pvBDHeader ) \ + (((WLANHAL_RX_BD_GET_RSSI0(_pvBDHeader)) + \ + (WLANHAL_RX_BD_GET_RSSI1(_pvBDHeader)) + \ + (WLANHAL_RX_BD_GET_RSSI2(_pvBDHeader)) + \ + (WLANHAL_RX_BD_GET_RSSI3(_pvBDHeader))) / 4) + +// Get the SNR value from PHY Stats +#define WLANHAL_RX_BD_GET_SNR( _pvBDHeader ) \ + (((((tpHalRxBd)_pvBDHeader)->phyStats1) >> 24) & 0xff) +/*-----------------------------------------------------------------*/ +#define WLANHAL_RX_BD_GET_DPU_SIG( _pvBDHeader ) (((tpHalRxBd)_pvBDHeader)->dpuSignature) + + +#define WLANHAL_TX_BD_SET_MPDU_DATA_OFFSET( _bd, _off ) (((tpHalTxBd)_bd)->mpduDataOffset = _off) + +#define WLANHAL_TX_BD_SET_MPDU_HEADER_OFFSET( _bd, _off ) (((tpHalTxBd)_bd)->mpduHeaderOffset = _off) + +#define WLANHAL_TX_BD_SET_MPDU_HEADER_LEN( _bd, _len ) (((tpHalTxBd)_bd)->mpduHeaderLength = _len) + +#define WLANHAL_TX_BD_SET_MPDU_LEN( _bd, _len ) (((tpHalTxBd)_bd)->mpduLength = _len) + +#define WLANHAL_RX_BD_GET_BA_OPCODE(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->reorderOpcode) + +#define WLANHAL_RX_BD_GET_BA_FI(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->reorderFwdIdx) + +#define WLANHAL_RX_BD_GET_BA_SI(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->reorderSlotIdx) + +#define WLANHAL_RX_BD_GET_BA_CSN(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->currentPktSeqNo) + +#define WLANHAL_RX_BD_GET_BA_ESN(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->expectedPktSeqNo) + +#define WLANHAL_RX_BD_GET_RXP_FLAGS(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->rxpFlags) + +#define WLANHAL_RX_BD_GET_TYPE_SUBTYPE(_pvBDHeader) (((tpHalRxBd)_pvBDHeader)->frameTypeSubtype) +#define WLANHAL_RX_BD_SET_TYPE_SUBTYPE( _bd, _typeSubtype ) (((tpHalRxBd)_bd)->frameTypeSubtype = _typeSubtype) + + +#define WLANHAL_RX_BD_ASF_SET 1 /*The value of the field when set and pkt is AMSDU*/ + +#define WLANHAL_RX_BD_FSF_SET 1 + +#define WLANHAL_RX_BD_LSF_SET 1 + +#define WLANHAL_RX_BD_AEF_SET 1 + + +#define WLANHAL_RX_BD_LLC_PRESENT 0 /*The value of the field when LLC is present*/ + +#define WLANHAL_RX_BD_FT_DONE 1 /* The value of the field when frame xtl was done*/ + +/*DPU_FEEDBACK_WPI_UNPROTECTED macro defined in volansdefs.h which is not available + for UMAC in prima so declared it here */ +#define DPU_FEEDBACK_WPI_UNPROTECTED 0x20 +#define WLANHAL_RX_IS_UNPROTECTED_WPI_FRAME(_pvBDHeader) \ + (DPU_FEEDBACK_WPI_UNPROTECTED == ((WDI_RxBdType *)_pvBDHeader)->dpuFeedback) + +/*========================================================================== + + FUNCTION WLANHAL_RxBD_GetFrameTypeSubType + + DESCRIPTION + Called by TL to retrieve the type/subtype of the received frame. + + DEPENDENCIES + TL should pass a valid RxBD buffer pointer. + + PARAMETERS + + IN + pvBDHeader: Void pointer to the RxBD buffer. + usFrmCtrl:the frame ctrl of the 802.11 header + + RETURN VALUE + A byte which contains both type and subtype info. LSB four bytes (b0 to b3) + is subtype and b5-b6 is type info. + + SIDE EFFECTS + +============================================================================*/ + +tANI_U8 WLANHAL_RxBD_GetFrameTypeSubType(v_PVOID_t _pvBDHeader, tANI_U16 usFrmCtrl); + + +#define HAL_TXCOMP_REQUESTED_MASK 0x1 //bit 0 for TxComp intr requested. +#define HAL_USE_SELF_STA_REQUESTED_MASK 0x2 //bit 1 for STA overwrite with selfSta Requested. +#define HAL_TX_NO_ENCRYPTION_MASK 0x4 //bit 2. If set, the frame is not to be encrypted +#if defined(LIBRA_WAPI_SUPPORT) +#define HAL_WAPI_STA_MASK 0x8 //bit 3. If set, this frame is for WAPI station +#endif + +#define HAL_TRIGGER_ENABLED_AC_MASK 0x10 //bit 4 for data frames belonging to trigger enabled AC +#define HAL_USE_NO_ACK_REQUESTED_MASK 0x20 + +#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames +#define HAL_USE_PEER_STA_REQUESTED_MASK 0x80 //bit 7 will be used to control frames for p2p interface + +#ifdef FEATURE_WLAN_TDLS +#define HAL_TDLS_PEER_STA_MASK 0x80 //bit 7 set for TDLS peer station +#endif + +/*========================================================================== + + FUNCTION WLANHAL_FillTxBd + + DESCRIPTION + Called by PE to register as a client for management frames delivery. + + DEPENDENCIES + TL must be initialized before this API can be called. + + PARAMETERS + + IN + pAdapter: pointer to the global adapter context;a handle to TL's + control block can be extracted from its context + vosFrmBuf: pointer to a vOSS buffer containing the management + frame to be transmitted + usFrmLen: the length of the frame to be transmitted; information + is already included in the vOSS buffer + wFrmType: the type of the frame being transmitted + tid: tid used to transmit this frame + pfnCompTxFunc: function pointer to the transmit complete routine + voosBDHeader: pointer to the BD header + txFlag: can have appropriate bit setting as required + + #define HAL_TXCOMP_REQUESTED_MASK 0x1 //bit 0 for TxComp intr requested. + #define HAL_USE_SELF_STA_REQUESTED_MASK 0x2 //bit 1 for STA overwrite with selfSta Requested. + #define HAL_TX_NO_ENCRYPTION_MASK 0x4 //bit 2. If set, the frame is not to be encrypted +#if defined(FEATURE_WLAN_WAPI) + #define HAL_WAPI_STA_MASK 0x8 //bit 3. If set, this frame is for WAPI station +#endif + + uTimestamp: pkt timestamp + + + RETURN VALUE + The result code associated with performing the operation + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS WLANHAL_FillTxBd(void *pAdapter, tANI_U8 typeSubtype, void *pDestMacAddr, void *pAddr2, + tANI_U8* ptid, tANI_U8 disableFrmXtl, void *pTxBd, tANI_U8 txFlag, tANI_U32 timeStamp); + +VOS_STATUS WLANHAL_FillFcTxBd(void *pVosGCtx, void *pFcParams, void *pFcTxBd); +/** To swap the report part of FC RxBD */ +void WLANHAL_SwapFcRxBd(tANI_U8 *pBd); + +/* To swap the data */ +void WLANHAL_Swap32Bytes(tANI_U8* pData, tANI_U32 size); + +/** To swap the RxBD */ +void WLANHAL_SwapRxBd(tANI_U8 *pBd); +void WLANHAL_RxAmsduBdFix(void *pVosGCtx,v_PVOID_t _pvBDHeader); + +#ifdef WLAN_PERF +tANI_U32 WLANHAL_TxBdFastFwd(void *pAdapter, tANI_U8 *pDestMac, tANI_U8 tid, tANI_U8 unicastDst, void *pTxBd, tANI_U16); +#endif + +VOS_STATUS WLANHAL_EnableUapsdAcParams(void* pVosGCtx, tANI_U8 staIdx, tUapsdInfo *pUapsdInfo); +VOS_STATUS WLANHAL_DisableUapsdAcParams(void* pVosGCtx, tANI_U8 staIdx, tANI_U8 ac); + +VOS_STATUS WLANHAL_EnableIdleBdPduInterrupt(void* pVosGCtx, tANI_U8 idleBdPduThreshold); + +#ifdef FEATURE_ON_CHIP_REORDERING +tANI_U8 WLANHAL_IsOnChipReorderingEnabledForTID(void* pVosGCtx, tANI_U8 staIdx, tANI_U8 tid); +#endif + +#ifdef WLAN_SOFTAP_VSTA_FEATURE +v_BOOL_t WLANHAL_IsHwFrameTxTranslationCapable(v_PVOID_t pVosGCtx, tANI_U8 staIdx); +#endif + +#define tHalRxBd halRxBd_type +#define tpHalRxBd phalRxBd_type + +#define tHalTxBd halTxBd_type +#define tpHalTxBd pHalTxBd_type + +#ifdef BA_PARAM_STRUCTURE +#else +#define BA_PARAM_STRUCTURE +// +// HAL --> TL +// Messages indicating the setup and/or teardown of +// A-MPDU/BA sessions with a given peer HT MAC entity +// + +// +// A data structure identifying all of the variables +// in a typical A-MPDU/BA setup +// +typedef struct sBAParams +{ + + // A unique BA Session ID that has been assigned by HAL + // for the curent BA Session + tANI_U16 baSessionID; + + // TID for which the BA session has been setup + tANI_U8 baTID; + + // BA Buffer Size allocated for the current BA session //Should be deleted. needs TL change. use winSize instead + tANI_U8 baBufferSize; + + tANI_U16 SSN; + tANI_U8 winSize; + tANI_U8 STAID; + +} tBAParams, *tpBAParams; + +// +// TL -> HAL +// tSirMsgQ.type = SIR_HAL_HDD_ADDBA_RSP +// +typedef struct sAddBARsp +{ + // Message Type + tANI_U16 mesgType; + + // Message Length + tANI_U16 mesgLen; + + //BA session ID + tANI_U16 baSessionID; + + tANI_U16 replyWinSize; +}tAddBARsp, *tpAddBARsp; + +// +// HAL -> TL +// tSirMsgQ.type = SIR_HAL_ADDBA_IND +// tSirMsgQ.reserved = 0 +// tSirMsgQ.body = "allocated" instance of tpAddBAInd +// +typedef struct sAddBAInd +{ + + // Message Type + tANI_U16 mesgType; + + // Message Length + tANI_U16 mesgLen; + + tBAParams baSession; + +} tAddBAInd, *tpAddBAInd; + +// +// HAL -> TL +// tSirMsgQ.type = SIR_HAL_DELBA_IND +// tSirMsgQ.reserved = 0 +// tSirMsgQ.body = "allocated" instance of tpDelBAInd +// +// TL -> HAL +// tSirMsgQ.type = SIR_HAL_BA_FAIL_IND +// tSirMsgQ.reserved = 0 +// tSirMsgQ.body = "allocated" instance of tpDelBAInd +// +typedef struct sDelBAInd +{ + tANI_U8 staIdx; + + tANI_U8 baTID; + // Message Type + tANI_U16 mesgType; + + // Message Length + tANI_U16 mesgLen; + +} tDelBAInd, *tpDelBAInd; +#endif + +/*=============================================== + * + * TL <-> HAL structures + * + *=============================================== + */ +// +// TL -> HAL +// tSirMsgQ.type = SIR_HAL_TL_FLUSH_AC_REQ +// +typedef struct sFlushACReq +{ + // Message Type + tANI_U16 mesgType; + + // Message Length + tANI_U16 mesgLen; + + // Station Index. originates from HAL + tANI_U8 ucSTAId; + + // TID for which the transmit queue is being flushed + tANI_U8 ucTid; + +} tFlushACReq, *tpFlushACReq; + +// +// +// HAL -> TL +// tSirMsgQ.type = SIR_HAL_TL_FLUSH_AC_RSP +// +typedef struct sFlushACRsp +{ + // Message Type + tANI_U16 mesgType; + + // Message Length + tANI_U16 mesgLen; + + // Station Index. originates from HAL + tANI_U8 ucSTAId; + + // TID for which the transmit queue is being flushed + tANI_U8 ucTid; + + // status of the Flush operation + tANI_U8 status; +} tFlushACRsp, *tpFlushACRsp; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h new file mode 100644 index 000000000000..dcfc4a4121b5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h @@ -0,0 +1,1256 @@ +/* + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + + +#ifndef WLAN_QCT_WDA_H +#define WLAN_QCT_WDA_H + +/*=========================================================================== + + W L A N DEVICE ADAPTATION L A Y E R + E X T E R N A L A P I + + +DESCRIPTION + This file contains the external API exposed by the wlan adaptation layer for Prima + and Volans. + + For Volans this layer is actually a thin layer that maps all WDA messages and + functions to equivalent HAL messages and functions. The reason this layer was introduced + was to keep the UMAC identical across Prima and Volans. This layer provides the glue + between SME, PE , TL and HAL. +===========================================================================*/ + + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + +when who what, where, why +-------- --- ---------------------------------------------- +10/05/2011 haparna Adding support for Keep Alive Feature +01/27/2011 rnair Adding WDA support for Volans. +12/08/2010 seokyoun Move down HAL interfaces from TL to WDA + for UMAC convergence btween Volans/Libra and Prima +08/25/2010 adwivedi WDA Context and exposed API's +=========================================================================== */ + +#include "aniGlobal.h" + +#include "wma_api.h" +#include "wma_stub.h" +#include "i_vos_packet.h" + +/* Add Include */ + +typedef enum +{ + WDA_INIT_STATE, + WDA_START_STATE, + WDA_READY_STATE, + WDA_PRE_ASSOC_STATE, + WDA_BA_UPDATE_TL_STATE, + WDA_BA_UPDATE_LIM_STATE, + WDA_STOP_STATE, + WDA_CLOSE_STATE +}WDA_state; + +typedef enum +{ + WDA_PROCESS_SET_LINK_STATE, + WDA_IGNORE_SET_LINK_STATE +}WDA_processSetLinkStateStatus; + +typedef enum +{ + WDA_DISABLE_BA, + WDA_ENABLE_BA +}WDA_BaEnableFlags; + +typedef enum +{ + WDA_INVALID_STA_INDEX, + WDA_VALID_STA_INDEX +}WDA_ValidStaIndex; +typedef enum +{ + eWDA_AUTH_TYPE_NONE, //never used + // MAC layer authentication types + eWDA_AUTH_TYPE_OPEN_SYSTEM, + // Upper layer authentication types + eWDA_AUTH_TYPE_WPA, + eWDA_AUTH_TYPE_WPA_PSK, + + eWDA_AUTH_TYPE_RSN, + eWDA_AUTH_TYPE_RSN_PSK, + eWDA_AUTH_TYPE_FT_RSN, + eWDA_AUTH_TYPE_FT_RSN_PSK, + eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE, + eWDA_AUTH_TYPE_WAPI_WAI_PSK, + eWDA_AUTH_TYPE_CCKM_WPA, + eWDA_AUTH_TYPE_CCKM_RSN, + eWDA_AUTH_TYPE_WPA_NONE, + eWDA_AUTH_TYPE_AUTOSWITCH, + eWDA_AUTH_TYPE_SHARED_KEY, + eWDA_NUM_OF_SUPPORT_AUTH_TYPE, + eWDA_AUTH_TYPE_FAILED = 0xff, + eWDA_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED, +}WDA_AuthType; + +#ifdef FEATURE_WLAN_TDLS +typedef enum +{ + WDA_TDLS_PEER_STATE_PEERING, + WDA_TDLS_PEER_STATE_CONNECTED, + WDA_TDLS_PEER_STATE_TEARDOWN, + WDA_TDLS_PEER_ADD_MAC_ADDR, + WDA_TDLS_PEER_REMOVE_MAC_ADDR, +} WDA_TdlsPeerState; +/* WMI_TDLS_SET_OFFCHAN_MODE_CMDID */ +typedef enum +{ + WDA_TDLS_ENABLE_OFFCHANNEL, + WDA_TDLS_DISABLE_OFFCHANNEL +}WDA_TdlsOffchanMode; +#endif /* FEATURE_WLAN_TDLS */ + +/*-------------------------------------------------------------------------- + Utilities + --------------------------------------------------------------------------*/ + +#define WDA_TLI_CEIL( _a, _b) (( 0 != (_a)%(_b))? (_a)/(_b) + 1: (_a)/(_b)) + + +#define IS_MCC_SUPPORTED 1 +#define IS_FEATURE_SUPPORTED_BY_FW(feat_enum_value) wma_getFwWlanFeatCaps(feat_enum_value) + +#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE +#define IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE 1 +#else +#define IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE 0 +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 1 +#else +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 0 +#endif + +#define IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE 1 + +#ifdef FEATURE_WLAN_TDLS +#define IS_ADVANCE_TDLS_ENABLE 0 +#endif + + +/*-------------------------------------------------------------------------- + Definitions for Data path APIs + --------------------------------------------------------------------------*/ + +/*As per 802.11 spec */ +#define WDA_TLI_MGMT_FRAME_TYPE 0x00 +#define WDA_TLI_CTRL_FRAME_TYPE 0x10 +#define WDA_TLI_DATA_FRAME_TYPE 0x20 + +/*802.3 header definitions*/ +#define WDA_TLI_802_3_HEADER_LEN 14 +/*802.11 header definitions - header len without QOS ctrl field*/ +#define WDA_TLI_802_11_HEADER_LEN 24 + +/*Determines the header len based on the disable xtl field*/ +#define WDA_TLI_MAC_HEADER_LEN( _dxtl) \ + ( ( 0 == _dxtl )? \ + WDA_TLI_802_3_HEADER_LEN:WDA_TLI_802_11_HEADER_LEN ) + +/* TX channel enum type: + + We have five types of TX packets so far and want to block/unblock each + traffic individually according to, for example, low resouce condition. + Define five TX channels for UMAC here. WDA can map these logical + channels to physical DXE channels if needed. +*/ +typedef enum +{ + WDA_TXFLOW_AC_BK = 0, + WDA_TXFLOW_AC_BE = 1, + WDA_TXFLOW_AC_VI = 2, + WDA_TXFLOW_AC_VO = 3, + WDA_TXFLOW_MGMT = 4, + WDA_TXFLOW_BAP = 1, /* BAP is sent as BE */ + WDA_TXFLOW_FC = 1, /* FC is sent as BE */ + WDA_TXFLOW_MAX +} WDA_TXFlowEnumType; + +#define WDA_TXFLOWMASK 0x1F /* 1~4bit:low priority ch / 5bit: high */ + +/* --------------------------------------------------------------------- + Libra and Volans specifics + + TODO Consider refactoring it and put it into two separate headers, + one for Prima and one for Volans + ----------------------------------------------------------------------*/ + +/* For backward compatability with SDIO. It's BAL header size for SDIO + interface. It's nothing for integrated SOC */ +#define WDA_DXE_HEADER_SIZE 0 + + +/*Minimum resources needed - arbitrary*/ + +/*DXE + SD*/ +#define WDA_WLAN_LIBRA_HEADER_LEN (20 + 8) + +#define WDA_TLI_BD_PDU_RESERVE_THRESHOLD 10 + + +# define WDA_TLI_MIN_RES_MF 1 +# define WDA_TLI_MIN_RES_BAP 2 +# define WDA_TLI_MIN_RES_DATA 3 + +# define WDA_NUM_STA 8 + +/* For backward compatability with SDIO. + + For SDIO interface, calculate the TX frame length and number of PDU + to transfter the frame. + + _vosBuff: IN VOS pakcet buffer pointer + _usPktLen: OUT VOS packet length in bytes + _uResLen: OUT Number of PDU to hold this VOS packet + _uTotalPktLen: OUT Totoal packet length including BAL header size + + For integrated SOC, _usPktLen and _uTotalPktLen is VOS pakcet length + which does include BD header length. _uResLen is hardcoded 2. + */ + +#ifdef WINDOWS_DT +#define WDA_TLI_PROCESS_FRAME_LEN( _vosBuff, _usPktLen, \ + _uResLen, _uTotalPktLen) \ + do \ + { \ + _usPktLen = wpalPacketGetFragCount((wpt_packet*)_vosBuff) + 1/*BD*/;\ + _uResLen = _usPktLen; \ + _uTotalPktLen = _usPktLen; \ + } \ + while ( 0 ) +#else /* WINDOWS_DT */ +#define WDA_TLI_PROCESS_FRAME_LEN( _vosBuff, _usPktLen, \ + _uResLen, _uTotalPktLen) \ + do \ + { \ + _usPktLen = 2; /* Need 1 descriptor per a packet + packet*/ \ + _uResLen = 2; /* Assume that we spends two DXE descriptor */ \ + _uTotalPktLen = _usPktLen; \ + } \ + while ( 0 ) +#endif /* WINDOWS_DT */ + + + +/*-------------------------------------------------------------------------- + Message Definitions + --------------------------------------------------------------------------*/ + +/* TX Tranmit request message. It serializes TX request to TX thread. + The message is processed in TL. +*/ +#define WDA_DS_TX_START_XMIT WLANTL_TX_START_XMIT +#define WDA_DS_FINISH_ULA WLANTL_FINISH_ULA + +#define VOS_TO_WPAL_PKT(_vos_pkt) ((wpt_packet*)_vos_pkt) + +#define WDA_TX_PACKET_FREED 0X0 + +/* Approximate amount of time to wait for WDA to stop WDI considering 1 pendig req too*/ +#define WDA_STOP_TIMEOUT ( (WDI_RESPONSE_TIMEOUT * 2) + WDI_SET_POWER_STATE_TIMEOUT + 5) +/*-------------------------------------------------------------------------- + Functions + --------------------------------------------------------------------------*/ +typedef void (*pWDATxRxCompFunc)( v_PVOID_t pContext, void *pData, + v_BOOL_t bFreeData ); + +//callback function for TX complete +//parameter 1 - global pMac pointer +//parameter 2 - txComplete status : 1- success, 0 - failure. +typedef eHalStatus (*pWDAAckFnTxComp)(tpAniSirGlobal, tANI_U32); + +/* generic callback for updating parameters from target to UMAC */ +typedef void (*wda_tgt_cfg_cb) (void *context, void *param); + +/* + * callback for Indicating Radar to HDD and disable Tx Queues + * to stop accepting data Tx packets from netif as radar is + * found on the current operating channel + */ +typedef bool (*wda_dfs_radar_indication_cb) (void *context, void *param); + +typedef struct +{ + tANI_U16 ucValidStaIndex ; + /* + * each bit in ucUseBaBitmap represent BA is enabled or not for this tid + * tid0 ..bit0, tid1..bit1 and so on.. + */ + tANI_U8 ucUseBaBitmap ; + tANI_U8 bssIdx; + tANI_U32 framesTxed[STACFG_MAX_TC]; +}tWdaStaInfo, *tpWdaStaInfo ; + +/* group all the WDA timers into this structure */ +typedef struct +{ + /* BA activity check timer */ + TX_TIMER baActivityChkTmr ; + + /* Tx Complete Timeout timer */ + TX_TIMER TxCompleteTimer ; + + /* Traffic Stats timer */ + TX_TIMER trafficStatsTimer ; +}tWdaTimers ; +#ifdef WLAN_SOFTAP_VSTA_FEATURE +#define WDA_MAX_STA (41) +#else +#define WDA_MAX_STA (16) +#endif +typedef struct +{ + v_PVOID_t pVosContext; /* global VOSS context*/ + v_PVOID_t pWdiContext; /* WDI context */ + WDA_state wdaState ; /* WDA state tracking */ + v_PVOID_t wdaWdiCfgApiMsgParam ; /* WDI API paramter tracking */ + vos_event_t wdaWdiEvent; /* WDI API sync event */ + + /* Event to wait for tx completion */ + vos_event_t txFrameEvent; + + /* call back function for tx complete*/ + pWDATxRxCompFunc pTxCbFunc; + /* call back function for tx packet ack */ + pWDAAckFnTxComp pAckTxCbFunc; + tANI_U32 frameTransRequired; + tSirMacAddr macBSSID; /*BSSID of the network */ + tSirMacAddr macSTASelf; /*Self STA MAC*/ + + + tWdaStaInfo wdaStaInfo[WDA_MAX_STA]; + + tANI_U8 wdaMaxSta; + tWdaTimers wdaTimers; + + /* driver mode, PRODUCTION or FTM */ + tDriverType driverMode; + + /* FTM Command Request tracking */ + v_PVOID_t wdaFTMCmdReq; + + /* Event to wait for suspend data tx*/ + vos_event_t suspendDataTxEvent; + /* Status frm TL after suspend/resume Tx */ + tANI_U8 txStatus; + /* Flag set to true when TL suspend timesout.*/ + tANI_U8 txSuspendTimedOut; + + vos_event_t waitOnWdiIndicationCallBack; + + /* version information */ + tSirVersionType wcnssWlanCompiledVersion; + tSirVersionType wcnssWlanReportedVersion; + tSirVersionString wcnssSoftwareVersionString; + tSirVersionString wcnssHardwareVersionString; + + + tSirLinkState linkState; + /* set, when BT AMP session is going on */ + v_BOOL_t wdaAmpSessionOn; + v_U32_t VosPacketToFree; + v_BOOL_t needShutdown; + v_BOOL_t wdiFailed; + v_BOOL_t wdaTimersCreated; + + /* Event to wait for WDA stop on FTM mode */ + vos_event_t ftmStopDoneEvent; + +} tWDA_CbContext ; + +typedef struct +{ + v_PVOID_t pWdaContext; /* pointer to WDA context*/ + v_PVOID_t wdaMsgParam; /* PE parameter tracking */ + v_PVOID_t wdaWdiApiMsgParam; /* WDI API paramter tracking */ +} tWDA_ReqParams; + +typedef struct { + v_UINT_t param_id; + v_UINT_t param_value; + v_UINT_t param_sec_value; + v_UINT_t param_vdev_id; + v_UINT_t param_vp_dev; +} wda_cli_set_cmd_t; + +/* + * FUNCTION: WDA_MgmtDSTxPacket + * Forward TX management frame to WDI + */ + +VOS_STATUS WDA_TxPacket(void *pWDA, + void *pFrmBuf, + tANI_U16 frmLen, + eFrameType frmType, + eFrameTxDir txDir, + tANI_U8 tid, + pWDATxRxCompFunc pCompFunc, + void *pData, + pWDAAckFnTxComp pAckTxComp, + tANI_U8 txFlag, + tANI_U8 sessionId, + bool tdlsflag); + +/* + * FUNCTION: WDA_open + * open WDA context + */ + +VOS_STATUS WDA_open(v_PVOID_t pVosContext, v_PVOID_t pOSContext, + wda_tgt_cfg_cb pTgtUpdCB, + wda_dfs_radar_indication_cb radar_ind_cb, + tMacOpenParameters *pMacParams ) ; + +#define WDA_start wma_start +#define WDA_MapChannel wma_map_channel + +#define WDA_NVDownload_Start(x) ({ VOS_STATUS_SUCCESS; }) + +#define WDA_preStart wma_pre_start +#define WDA_stop wma_stop +#define WDA_close wma_close +#define WDA_shutdown wma_shutdown +#define WDA_setNeedShutdown wma_setneedshutdown +#define WDA_needShutdown wma_needshutdown +#define WDA_McProcessMsg wma_mc_process_msg + +#define DPU_FEEDBACK_UNPROTECTED_ERROR 0x0F + + +#define WDA_GET_RX_MAC_HEADER(pRxMeta) \ + (tpSirMacMgmtHdr)(((t_packetmeta *)pRxMeta)->mpdu_hdr_ptr) + +#define WDA_GET_RX_MPDUHEADER3A(pRxMeta) \ + (tpSirMacDataHdr3a)(((t_packetmeta *)pRxMeta)->mpdu_hdr_ptr) + +#define WDA_GET_RX_MPDU_HEADER_LEN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_hdr_len) + +#define WDA_GET_RX_MPDU_LEN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_len) + +#define WDA_GET_RX_PAYLOAD_LEN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_data_len) + +#define WDA_GET_RX_TSF_DELTA(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->tsf_delta) + +#define WDA_GET_RX_MAC_RATE_IDX(pRxMeta) 0 + +#define WDA_GET_RX_MPDU_DATA(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_data_ptr) + +#define WDA_GET_RX_MPDU_HEADER_OFFSET(pRxMeta) 0 + +#define WDA_GET_RX_UNKNOWN_UCAST(pRxMeta) 0 + +#define WDA_GET_RX_CH(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->channel) + +#define WDA_IS_RX_BCAST(pRxMeta) 0 + +#define WDA_GET_RX_FT_DONE(pRxMeta) 0 + +#define WDA_GET_RX_DPU_FEEDBACK(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->dpuFeedback) + +#define WDA_GET_RX_BEACON_SENT(pRxMeta) 0 + +#define WDA_GET_RX_TSF_LATER(pRxMeta) 0 + +#define WDA_GET_RX_TIMESTAMP(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->timestamp) + +#define WDA_IS_RX_IN_SCAN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->scan) + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define WDA_GET_OFFLOADSCANLEARN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->offloadScanLearn) +#define WDA_GET_ROAMCANDIDATEIND(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->roamCandidateInd) +#define WDA_GET_SESSIONID(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->sessionId) +#define WMA_GET_SCAN_SRC(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->scan_src) +#endif + +#ifdef FEATURE_WLAN_EXTSCAN +#define WMA_IS_EXTSCAN_SCAN_SRC(pRxMeta) \ + ((((t_packetmeta *)pRxMeta)->scan_src) & WMI_MGMT_RX_HDR_EXTSCAN) +#define WMA_IS_EPNO_SCAN_SRC(pRxMeta) \ + ((((t_packetmeta *)pRxMeta)->scan_src) & WMI_MGMT_RX_HDR_ENLO) +#endif /* FEATURE_WLAN_EXTSCAN */ + +#define WDA_GET_RX_SNR(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->snr) + +#define WDA_GetWcnssWlanCompiledVersion WMA_GetWcnssWlanCompiledVersion +#define WDA_GetWcnssWlanReportedVersion WMA_GetWcnssWlanReportedVersion +#define WDA_GetWcnssSoftwareVersion WMA_GetWcnssSoftwareVersion +#define WDA_GetWcnssHardwareVersion WMA_GetWcnssHardwareVersion + +#define WDA_GET_RX_RFBAND(pRxMeta) 0 + + +tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); + + +#define WDA_MAX_TXPOWER_INVALID HAL_MAX_TXPOWER_INVALID + +/* rssi value normalized to noise floor of -96 dBm */ +#define WDA_GET_RX_RSSI_NORMALIZED(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->rssi) + +/* raw rssi based on actual noise floor in hardware */ +#define WDA_GET_RX_RSSI_RAW(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->rssi_raw) + +//WDA Messages to HAL messages Mapping +#if 0 +//Required by SME +//#define WDA_SIGNAL_BT_EVENT SIR_HAL_SIGNAL_BT_EVENT - this is defined in sirParams.h +//#define WDA_BTC_SET_CFG SIR_HAL_BTC_SET_CFG + +//Required by PE +#define WDA_HOST_MSG_START SIR_HAL_HOST_MSG_START +#define WDA_INITIAL_CAL_FAILED_NTF SIR_HAL_INITIAL_CAL_FAILED_NTF +#define WDA_SHUTDOWN_REQ SIR_HAL_SHUTDOWN_REQ +#define WDA_SHUTDOWN_CNF SIR_HAL_SHUTDOWN_CNF +#define WDA_RADIO_ON_OFF_IND SIR_HAL_RADIO_ON_OFF_IND +#define WDA_RESET_CNF SIR_HAL_RESET_CNF +#define WDA_SetRegDomain \ + (eHalStatus halPhySetRegDomain(tHalHandle hHal, eRegDomainId regDomain)) +#endif + +#define WDA_APP_SETUP_NTF SIR_HAL_APP_SETUP_NTF +#define WDA_NIC_OPER_NTF SIR_HAL_NIC_OPER_NTF +#define WDA_INIT_START_REQ SIR_HAL_INIT_START_REQ +#define WDA_RESET_REQ SIR_HAL_RESET_REQ +#define WDA_HDD_ADDBA_REQ SIR_HAL_HDD_ADDBA_REQ +#define WDA_HDD_ADDBA_RSP SIR_HAL_HDD_ADDBA_RSP +#define WDA_DELETEBA_IND SIR_HAL_DELETEBA_IND +#define WDA_BA_FAIL_IND SIR_HAL_BA_FAIL_IND +#define WDA_TL_FLUSH_AC_REQ SIR_TL_HAL_FLUSH_AC_REQ +#define WDA_TL_FLUSH_AC_RSP SIR_HAL_TL_FLUSH_AC_RSP + +#define WDA_MSG_TYPES_BEGIN SIR_HAL_MSG_TYPES_BEGIN +#define WDA_ITC_MSG_TYPES_BEGIN SIR_HAL_ITC_MSG_TYPES_BEGIN +#define WDA_RADAR_DETECTED_IND SIR_HAL_RADAR_DETECTED_IND +#define WDA_WDT_KAM_RSP SIR_HAL_WDT_KAM_RSP +#define WDA_TIMER_TEMP_MEAS_REQ SIR_HAL_TIMER_TEMP_MEAS_REQ +#define WDA_TIMER_PERIODIC_STATS_COLLECT_REQ SIR_HAL_TIMER_PERIODIC_STATS_COLLECT_REQ +#define WDA_CAL_REQ_NTF SIR_HAL_CAL_REQ_NTF +#define WDA_MNT_OPEN_TPC_TEMP_MEAS_REQ SIR_HAL_MNT_OPEN_TPC_TEMP_MEAS_REQ +#define WDA_CCA_MONITOR_INTERVAL_TO SIR_HAL_CCA_MONITOR_INTERVAL_TO +#define WDA_CCA_MONITOR_DURATION_TO SIR_HAL_CCA_MONITOR_DURATION_TO +#define WDA_CCA_MONITOR_START SIR_HAL_CCA_MONITOR_START +#define WDA_CCA_MONITOR_STOP SIR_HAL_CCA_MONITOR_STOP +#define WDA_CCA_CHANGE_MODE SIR_HAL_CCA_CHANGE_MODE +#define WDA_TIMER_WRAP_AROUND_STATS_COLLECT_REQ SIR_HAL_TIMER_WRAP_AROUND_STATS_COLLECT_REQ + +#define WDA_ADD_STA_REQ SIR_HAL_ADD_STA_REQ +#define WDA_ADD_STA_RSP SIR_HAL_ADD_STA_RSP +#define WDA_ADD_STA_SELF_RSP SIR_HAL_ADD_STA_SELF_RSP +#define WDA_DEL_STA_SELF_RSP SIR_HAL_DEL_STA_SELF_RSP +#define WDA_DELETE_STA_REQ SIR_HAL_DELETE_STA_REQ +#define WDA_DELETE_STA_RSP SIR_HAL_DELETE_STA_RSP +#define WDA_ADD_BSS_REQ SIR_HAL_ADD_BSS_REQ +#define WDA_ADD_BSS_RSP SIR_HAL_ADD_BSS_RSP +#define WDA_DELETE_BSS_REQ SIR_HAL_DELETE_BSS_REQ +#define WDA_DELETE_BSS_RSP SIR_HAL_DELETE_BSS_RSP +#define WDA_INIT_SCAN_REQ SIR_HAL_INIT_SCAN_REQ +#define WDA_INIT_SCAN_RSP SIR_HAL_INIT_SCAN_RSP +#define WDA_START_SCAN_REQ SIR_HAL_START_SCAN_REQ +#define WDA_START_SCAN_RSP SIR_HAL_START_SCAN_RSP +#define WDA_END_SCAN_REQ SIR_HAL_END_SCAN_REQ +#define WDA_END_SCAN_RSP SIR_HAL_END_SCAN_RSP +#define WDA_FINISH_SCAN_REQ SIR_HAL_FINISH_SCAN_REQ +#define WDA_FINISH_SCAN_RSP SIR_HAL_FINISH_SCAN_RSP +#define WDA_SEND_BEACON_REQ SIR_HAL_SEND_BEACON_REQ +#define WDA_SEND_BEACON_RSP SIR_HAL_SEND_BEACON_RSP +#define WDA_SEND_PROBE_RSP_TMPL SIR_HAL_SEND_PROBE_RSP_TMPL + +#define WDA_INIT_CFG_REQ SIR_HAL_INIT_CFG_REQ +#define WDA_INIT_CFG_RSP SIR_HAL_INIT_CFG_RSP + +#define WDA_INIT_WM_CFG_REQ SIR_HAL_INIT_WM_CFG_REQ +#define WDA_INIT_WM_CFG_RSP SIR_HAL_INIT_WM_CFG_RSP + +#define WDA_SET_BSSKEY_REQ SIR_HAL_SET_BSSKEY_REQ +#define WDA_SET_BSSKEY_RSP SIR_HAL_SET_BSSKEY_RSP +#define WDA_SET_STAKEY_REQ SIR_HAL_SET_STAKEY_REQ +#define WDA_SET_STAKEY_RSP SIR_HAL_SET_STAKEY_RSP +#define WDA_DPU_STATS_REQ SIR_HAL_DPU_STATS_REQ +#define WDA_DPU_STATS_RSP SIR_HAL_DPU_STATS_RSP +#define WDA_GET_DPUINFO_REQ SIR_HAL_GET_DPUINFO_REQ +#define WDA_GET_DPUINFO_RSP SIR_HAL_GET_DPUINFO_RSP + +#define WDA_UPDATE_EDCA_PROFILE_IND SIR_HAL_UPDATE_EDCA_PROFILE_IND + +#define WDA_UPDATE_STARATEINFO_REQ SIR_HAL_UPDATE_STARATEINFO_REQ +#define WDA_UPDATE_STARATEINFO_RSP SIR_HAL_UPDATE_STARATEINFO_RSP + +#define WDA_UPDATE_BEACON_IND SIR_HAL_UPDATE_BEACON_IND +#define WDA_UPDATE_CF_IND SIR_HAL_UPDATE_CF_IND +#define WDA_CHNL_SWITCH_REQ SIR_HAL_CHNL_SWITCH_REQ +#define WDA_ADD_TS_REQ SIR_HAL_ADD_TS_REQ +#define WDA_DEL_TS_REQ SIR_HAL_DEL_TS_REQ +#define WDA_SOFTMAC_TXSTAT_REPORT SIR_HAL_SOFTMAC_TXSTAT_REPORT + +#define WDA_MBOX_SENDMSG_COMPLETE_IND SIR_HAL_MBOX_SENDMSG_COMPLETE_IND +#define WDA_EXIT_BMPS_REQ SIR_HAL_EXIT_BMPS_REQ +#define WDA_EXIT_BMPS_RSP SIR_HAL_EXIT_BMPS_RSP +#define WDA_EXIT_BMPS_IND SIR_HAL_EXIT_BMPS_IND +#define WDA_ENTER_BMPS_REQ SIR_HAL_ENTER_BMPS_REQ +#define WDA_ENTER_BMPS_RSP SIR_HAL_ENTER_BMPS_RSP +#define WDA_BMPS_STATUS_IND SIR_HAL_BMPS_STATUS_IND +#define WDA_MISSED_BEACON_IND SIR_HAL_MISSED_BEACON_IND + +#define WDA_SMPS_FORCE_MODE_IND SIR_HAL_SMPS_FORCE_MODE_IND + +#define WDA_CFG_RXP_FILTER_REQ SIR_HAL_CFG_RXP_FILTER_REQ +#define WDA_CFG_RXP_FILTER_RSP SIR_HAL_CFG_RXP_FILTER_RSP + +#define WDA_SWITCH_CHANNEL_RSP SIR_HAL_SWITCH_CHANNEL_RSP +#define WDA_P2P_NOA_ATTR_IND SIR_HAL_P2P_NOA_ATTR_IND +#define WDA_P2P_NOA_START_IND SIR_HAL_P2P_NOA_START_IND +#define WDA_PWR_SAVE_CFG SIR_HAL_PWR_SAVE_CFG + +#define WDA_REGISTER_PE_CALLBACK SIR_HAL_REGISTER_PE_CALLBACK +#define WDA_SOFTMAC_MEM_READREQUEST SIR_HAL_SOFTMAC_MEM_READREQUEST +#define WDA_SOFTMAC_MEM_WRITEREQUEST SIR_HAL_SOFTMAC_MEM_WRITEREQUEST + +#define WDA_SOFTMAC_MEM_READRESPONSE SIR_HAL_SOFTMAC_MEM_READRESPONSE +#define WDA_SOFTMAC_BULKREGWRITE_CONFIRM SIR_HAL_SOFTMAC_BULKREGWRITE_CONFIRM +#define WDA_SOFTMAC_BULKREGREAD_RESPONSE SIR_HAL_SOFTMAC_BULKREGREAD_RESPONSE +#define WDA_SOFTMAC_HOSTMESG_MSGPROCESSRESULT SIR_HAL_SOFTMAC_HOSTMESG_MSGPROCESSRESULT + +#define WDA_ADDBA_REQ SIR_HAL_ADDBA_REQ +#define WDA_ADDBA_RSP SIR_HAL_ADDBA_RSP +#define WDA_DELBA_IND SIR_HAL_DELBA_IND +#define WDA_DEL_BA_IND SIR_HAL_DEL_BA_IND +#define WDA_MIC_FAILURE_IND SIR_HAL_MIC_FAILURE_IND + +//message from sme to initiate delete block ack session. +#define WDA_DELBA_REQ SIR_HAL_DELBA_REQ +#define WDA_IBSS_STA_ADD SIR_HAL_IBSS_STA_ADD +#define WDA_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND SIR_HAL_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND +#define WDA_SET_LINK_STATE SIR_HAL_SET_LINK_STATE +#define WDA_SET_LINK_STATE_RSP SIR_HAL_SET_LINK_STATE_RSP +#define WDA_ENTER_IMPS_REQ SIR_HAL_ENTER_IMPS_REQ +#define WDA_ENTER_IMPS_RSP SIR_HAL_ENTER_IMPS_RSP +#define WDA_EXIT_IMPS_RSP SIR_HAL_EXIT_IMPS_RSP +#define WDA_EXIT_IMPS_REQ SIR_HAL_EXIT_IMPS_REQ +#define WDA_SOFTMAC_HOSTMESG_PS_STATUS_IND SIR_HAL_SOFTMAC_HOSTMESG_PS_STATUS_IND +#define WDA_POSTPONE_ENTER_IMPS_RSP SIR_HAL_POSTPONE_ENTER_IMPS_RSP +#define WDA_STA_STAT_REQ SIR_HAL_STA_STAT_REQ +#define WDA_GLOBAL_STAT_REQ SIR_HAL_GLOBAL_STAT_REQ +#define WDA_AGGR_STAT_REQ SIR_HAL_AGGR_STAT_REQ +#define WDA_STA_STAT_RSP SIR_HAL_STA_STAT_RSP +#define WDA_GLOBAL_STAT_RSP SIR_HAL_GLOBAL_STAT_RSP +#define WDA_AGGR_STAT_RSP SIR_HAL_AGGR_STAT_RSP +#define WDA_STAT_SUMM_REQ SIR_HAL_STAT_SUMM_REQ +#define WDA_STAT_SUMM_RSP SIR_HAL_STAT_SUMM_RSP +#define WDA_REMOVE_BSSKEY_REQ SIR_HAL_REMOVE_BSSKEY_REQ +#define WDA_REMOVE_BSSKEY_RSP SIR_HAL_REMOVE_BSSKEY_RSP +#define WDA_REMOVE_STAKEY_REQ SIR_HAL_REMOVE_STAKEY_REQ +#define WDA_REMOVE_STAKEY_RSP SIR_HAL_REMOVE_STAKEY_RSP +#define WDA_SET_STA_BCASTKEY_REQ SIR_HAL_SET_STA_BCASTKEY_REQ +#define WDA_SET_STA_BCASTKEY_RSP SIR_HAL_SET_STA_BCASTKEY_RSP +#define WDA_REMOVE_STA_BCASTKEY_REQ SIR_HAL_REMOVE_STA_BCASTKEY_REQ +#define WDA_REMOVE_STA_BCASTKEY_RSP SIR_HAL_REMOVE_STA_BCASTKEY_RSP +#define WDA_ADD_TS_RSP SIR_HAL_ADD_TS_RSP +#define WDA_DPU_MIC_ERROR SIR_HAL_DPU_MIC_ERROR +#define WDA_TIMER_BA_ACTIVITY_REQ SIR_HAL_TIMER_BA_ACTIVITY_REQ +#define WDA_TIMER_CHIP_MONITOR_TIMEOUT SIR_HAL_TIMER_CHIP_MONITOR_TIMEOUT +#define WDA_TIMER_TRAFFIC_ACTIVITY_REQ SIR_HAL_TIMER_TRAFFIC_ACTIVITY_REQ +#define WDA_TIMER_ADC_RSSI_STATS SIR_HAL_TIMER_ADC_RSSI_STATS +#define WDA_TIMER_TRAFFIC_STATS_IND SIR_HAL_TRAFFIC_STATS_IND + +#ifdef WLAN_FEATURE_11W +#define WDA_EXCLUDE_UNENCRYPTED_IND SIR_HAL_EXCLUDE_UNENCRYPTED_IND +#endif + +#ifdef FEATURE_WLAN_ESE +#define WDA_TSM_STATS_REQ SIR_HAL_TSM_STATS_REQ +#define WDA_TSM_STATS_RSP SIR_HAL_TSM_STATS_RSP +#endif +#define WDA_UPDATE_PROBE_RSP_IE_BITMAP_IND SIR_HAL_UPDATE_PROBE_RSP_IE_BITMAP_IND +#define WDA_UPDATE_UAPSD_IND SIR_HAL_UPDATE_UAPSD_IND + +#define WDA_SET_MIMOPS_REQ SIR_HAL_SET_MIMOPS_REQ +#define WDA_SET_MIMOPS_RSP SIR_HAL_SET_MIMOPS_RSP +#define WDA_SYS_READY_IND SIR_HAL_SYS_READY_IND +#define WDA_SET_TX_POWER_REQ SIR_HAL_SET_TX_POWER_REQ +#define WDA_SET_TX_POWER_RSP SIR_HAL_SET_TX_POWER_RSP +#define WDA_GET_TX_POWER_REQ SIR_HAL_GET_TX_POWER_REQ +#define WDA_GET_NOISE_REQ SIR_HAL_GET_NOISE_REQ +#define WDA_SET_TX_PER_TRACKING_REQ SIR_HAL_SET_TX_PER_TRACKING_REQ + +/* Messages to support transmit_halt and transmit_resume */ +#define WDA_TRANSMISSION_CONTROL_IND SIR_HAL_TRANSMISSION_CONTROL_IND +/* Indication from LIM to HAL to Initialize radar interrupt */ +#define WDA_INIT_RADAR_IND SIR_HAL_INIT_RADAR_IND +/* Messages to support transmit_halt and transmit_resume */ + + +#define WDA_BEACON_PRE_IND SIR_HAL_BEACON_PRE_IND +#define WDA_ENTER_UAPSD_REQ SIR_HAL_ENTER_UAPSD_REQ +#define WDA_ENTER_UAPSD_RSP SIR_HAL_ENTER_UAPSD_RSP +#define WDA_EXIT_UAPSD_REQ SIR_HAL_EXIT_UAPSD_REQ +#define WDA_EXIT_UAPSD_RSP SIR_HAL_EXIT_UAPSD_RSP +#define WDA_BEACON_FILTER_IND SIR_HAL_BEACON_FILTER_IND +/// PE <-> HAL WOWL messages +#define WDA_WOWL_ADD_BCAST_PTRN SIR_HAL_WOWL_ADD_BCAST_PTRN +#define WDA_WOWL_DEL_BCAST_PTRN SIR_HAL_WOWL_DEL_BCAST_PTRN +#define WDA_WOWL_ENTER_REQ SIR_HAL_WOWL_ENTER_REQ +#define WDA_WOWL_ENTER_RSP SIR_HAL_WOWL_ENTER_RSP +#define WDA_WOWL_EXIT_REQ SIR_HAL_WOWL_EXIT_REQ +#define WDA_WOWL_EXIT_RSP SIR_HAL_WOWL_EXIT_RSP +#define WDA_TX_COMPLETE_IND SIR_HAL_TX_COMPLETE_IND +#define WDA_TIMER_RA_COLLECT_AND_ADAPT SIR_HAL_TIMER_RA_COLLECT_AND_ADAPT +/// PE <-> HAL statistics messages +#define WDA_GET_STATISTICS_REQ SIR_HAL_GET_STATISTICS_REQ +#define WDA_GET_STATISTICS_RSP SIR_HAL_GET_STATISTICS_RSP +#define WDA_SET_KEY_DONE SIR_HAL_SET_KEY_DONE + +/// PE <-> HAL BTC messages +#define WDA_BTC_SET_CFG SIR_HAL_BTC_SET_CFG +#define WDA_SIGNAL_BT_EVENT SIR_HAL_SIGNAL_BT_EVENT +#define WDA_HANDLE_FW_MBOX_RSP SIR_HAL_HANDLE_FW_MBOX_RSP + +#ifdef FEATURE_OEM_DATA_SUPPORT +/* PE <-> HAL OEM_DATA RELATED MESSAGES */ +#define WDA_START_OEM_DATA_REQ SIR_HAL_START_OEM_DATA_REQ +#define WDA_START_OEM_DATA_RSP SIR_HAL_START_OEM_DATA_RSP +#define WDA_FINISH_OEM_DATA_REQ SIR_HAL_FINISH_OEM_DATA_REQ +#endif + +#define WDA_SET_MAX_TX_POWER_REQ SIR_HAL_SET_MAX_TX_POWER_REQ +#define WDA_SET_MAX_TX_POWER_RSP SIR_HAL_SET_MAX_TX_POWER_RSP +#define WDA_SET_TX_POWER_REQ SIR_HAL_SET_TX_POWER_REQ + +#define WDA_SET_MAX_TX_POWER_PER_BAND_REQ \ + SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ +#define WDA_SET_MAX_TX_POWER_PER_BAND_RSP \ + SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP + +#define WDA_SEND_MSG_COMPLETE SIR_HAL_SEND_MSG_COMPLETE + +/// PE <-> HAL Host Offload message +#define WDA_SET_HOST_OFFLOAD SIR_HAL_SET_HOST_OFFLOAD + +/// PE <-> HAL Keep Alive message +#define WDA_SET_KEEP_ALIVE SIR_HAL_SET_KEEP_ALIVE + +#ifdef WLAN_NS_OFFLOAD +#define WDA_SET_NS_OFFLOAD SIR_HAL_SET_NS_OFFLOAD +#endif //WLAN_NS_OFFLOAD +#define WDA_ADD_STA_SELF_REQ SIR_HAL_ADD_STA_SELF_REQ +#define WDA_DEL_STA_SELF_REQ SIR_HAL_DEL_STA_SELF_REQ + +#define WDA_SET_P2P_GO_NOA_REQ SIR_HAL_SET_P2P_GO_NOA_REQ +#define WDA_SET_TDLS_LINK_ESTABLISH_REQ SIR_HAL_TDLS_LINK_ESTABLISH_REQ +#define WDA_SET_TDLS_LINK_ESTABLISH_REQ_RSP SIR_HAL_TDLS_LINK_ESTABLISH_REQ_RSP + +#define WDA_TX_COMPLETE_TIMEOUT_IND (WDA_MSG_TYPES_END - 1) +#define WDA_WLAN_SUSPEND_IND SIR_HAL_WLAN_SUSPEND_IND +#define WDA_WLAN_RESUME_REQ SIR_HAL_WLAN_RESUME_REQ +#define WDA_MSG_TYPES_END SIR_HAL_MSG_TYPES_END + +#define WDA_MMH_TXMB_READY_EVT SIR_HAL_MMH_TXMB_READY_EVT +#define WDA_MMH_RXMB_DONE_EVT SIR_HAL_MMH_RXMB_DONE_EVT +#define WDA_MMH_MSGQ_NE_EVT SIR_HAL_MMH_MSGQ_NE_EVT + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define WDA_AGGR_QOS_REQ SIR_HAL_AGGR_QOS_REQ +#define WDA_AGGR_QOS_RSP SIR_HAL_AGGR_QOS_RSP +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* FTM CMD MSG */ +#define WDA_FTM_CMD_REQ SIR_PTT_MSG_TYPES_BEGIN +#define WDA_FTM_CMD_RSP SIR_PTT_MSG_TYPES_END +#define WDA_CSA_OFFLOAD_EVENT SIR_CSA_OFFLOAD_EVENT + +#ifdef FEATURE_WLAN_SCAN_PNO +/*Requests sent to lower driver*/ +#define WDA_SET_PNO_REQ SIR_HAL_SET_PNO_REQ +#define WDA_UPDATE_SCAN_PARAMS_REQ SIR_HAL_UPDATE_SCAN_PARAMS + +/*Indication comming from lower driver*/ +#define WDA_SET_PNO_CHANGED_IND SIR_HAL_SET_PNO_CHANGED_IND +#endif // FEATURE_WLAN_SCAN_PNO + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define WDA_SET_PLM_REQ SIR_HAL_SET_PLM_REQ +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define WDA_ROAM_SCAN_OFFLOAD_REQ SIR_HAL_ROAM_SCAN_OFFLOAD_REQ +#define WDA_ROAM_SCAN_OFFLOAD_RSP SIR_HAL_ROAM_SCAN_OFFLOAD_RSP +#define WDA_START_ROAM_CANDIDATE_LOOKUP_REQ SIR_HAL_START_ROAM_CANDIDATE_LOOKUP_REQ +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define WDA_ROAM_OFFLOAD_SYNCH_CNF SIR_HAL_ROAM_OFFLOAD_SYNCH_CNF +#define WDA_ROAM_OFFLOAD_SYNCH_IND SIR_HAL_ROAM_OFFLOAD_SYNCH_IND +#define WDA_ROAM_OFFLOAD_SYNCH_FAIL SIR_HAL_ROAM_OFFLOAD_SYNCH_FAIL +#endif +#ifdef WLAN_WAKEUP_EVENTS +#define WDA_WAKE_REASON_IND SIR_HAL_WAKE_REASON_IND +#endif // WLAN_WAKEUP_EVENTS + +#ifdef WLAN_FEATURE_PACKET_FILTERING +#define WDA_8023_MULTICAST_LIST_REQ SIR_HAL_8023_MULTICAST_LIST_REQ +#define WDA_RECEIVE_FILTER_SET_FILTER_REQ SIR_HAL_RECEIVE_FILTER_SET_FILTER_REQ +#define WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ +#define WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP +#define WDA_RECEIVE_FILTER_CLEAR_FILTER_REQ SIR_HAL_RECEIVE_FILTER_CLEAR_FILTER_REQ +#endif // WLAN_FEATURE_PACKET_FILTERING + +#define WDA_SET_POWER_PARAMS_REQ SIR_HAL_SET_POWER_PARAMS_REQ +#define WDA_DHCP_START_IND SIR_HAL_DHCP_START_IND +#define WDA_DHCP_STOP_IND SIR_HAL_DHCP_STOP_IND + +#define WDA_HIDDEN_SSID_VDEV_RESTART SIR_HAL_HIDE_SSID_VDEV_RESTART + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define WDA_GTK_OFFLOAD_REQ SIR_HAL_GTK_OFFLOAD_REQ +#define WDA_GTK_OFFLOAD_GETINFO_REQ SIR_HAL_GTK_OFFLOAD_GETINFO_REQ +#define WDA_GTK_OFFLOAD_GETINFO_RSP SIR_HAL_GTK_OFFLOAD_GETINFO_RSP +#endif //WLAN_FEATURE_GTK_OFFLOAD + +#define WDA_SET_TM_LEVEL_REQ SIR_HAL_SET_TM_LEVEL_REQ + +#ifdef WLAN_FEATURE_11AC +#define WDA_UPDATE_OP_MODE SIR_HAL_UPDATE_OP_MODE +#define WDA_UPDATE_RX_NSS SIR_HAL_UPDATE_RX_NSS +#define WDA_UPDATE_MEMBERSHIP SIR_HAL_UPDATE_MEMBERSHIP +#define WDA_UPDATE_USERPOS SIR_HAL_UPDATE_USERPOS +#endif + +#ifdef WLAN_FEATURE_NAN +#define WDA_NAN_REQUEST SIR_HAL_NAN_REQUEST +#endif + +#define WDA_START_SCAN_OFFLOAD_REQ SIR_HAL_START_SCAN_OFFLOAD_REQ +#define WDA_START_SCAN_OFFLOAD_RSP SIR_HAL_START_SCAN_OFFLOAD_RSP +#define WDA_STOP_SCAN_OFFLOAD_REQ SIR_HAL_STOP_SCAN_OFFLOAD_REQ +#define WDA_STOP_SCAN_OFFLOAD_RSP SIR_HAL_STOP_SCAN_OFFLOAD_RSP +#define WDA_UPDATE_CHAN_LIST_REQ SIR_HAL_UPDATE_CHAN_LIST_REQ +#define WDA_UPDATE_CHAN_LIST_RSP SIR_HAL_UPDATE_CHAN_LIST_RSP +#define WDA_RX_SCAN_EVENT SIR_HAL_RX_SCAN_EVENT +#define WDA_IBSS_PEER_INACTIVITY_IND SIR_HAL_IBSS_PEER_INACTIVITY_IND + +#define WDA_CLI_SET_CMD SIR_HAL_CLI_SET_CMD +#define WDA_CLI_GET_CMD SIR_HAL_CLI_GET_CMD +#define WDA_SET_PDEV_IE_REQ SIR_HAL_SET_PDEV_IE_REQ +#ifdef FEATURE_WLAN_SCAN_PNO +#define WDA_SME_SCAN_CACHE_UPDATED SIR_HAL_SME_SCAN_CACHE_UPDATED +#endif + +#ifndef REMOVE_PKT_LOG +#define WDA_PKTLOG_ENABLE_REQ SIR_HAL_PKTLOG_ENABLE_REQ +#endif + +#ifdef FEATURE_WLAN_LPHB +#define WDA_LPHB_CONF_REQ SIR_HAL_LPHB_CONF_IND +#define WDA_LPHB_WAIT_EXPIRE_IND SIR_HAL_LPHB_WAIT_EXPIRE_IND +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_CH_AVOID +#define WDA_CH_AVOID_UPDATE_REQ SIR_HAL_CH_AVOID_UPDATE_REQ +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +#define WDA_SET_AUTO_SHUTDOWN_TIMER_REQ SIR_HAL_SET_AUTO_SHUTDOWN_TIMER_REQ +#endif + +#define WDA_ADD_PERIODIC_TX_PTRN_IND SIR_HAL_ADD_PERIODIC_TX_PTRN_IND +#define WDA_DEL_PERIODIC_TX_PTRN_IND SIR_HAL_DEL_PERIODIC_TX_PTRN_IND + +#define WDA_TX_POWER_LIMIT SIR_HAL_SET_TX_POWER_LIMIT + +#define WDA_RATE_UPDATE_IND SIR_HAL_RATE_UPDATE_IND + +#define WDA_INIT_THERMAL_INFO_CMD SIR_HAL_INIT_THERMAL_INFO_CMD +#define WDA_SET_THERMAL_LEVEL SIR_HAL_SET_THERMAL_LEVEL + +#define WDA_RMC_ENABLE_IND SIR_HAL_RMC_ENABLE_IND +#define WDA_RMC_DISABLE_IND SIR_HAL_RMC_DISABLE_IND +#define WDA_RMC_ACTION_PERIOD_IND SIR_HAL_RMC_ACTION_PERIOD_IND + +#define WDA_GET_IBSS_PEER_INFO_REQ SIR_HAL_IBSS_PEER_INFO_REQ +#define WDA_GET_IBSS_PEER_INFO_RSP SIR_HAL_IBSS_PEER_INFO_RSP + +#define WDA_IBSS_CESIUM_ENABLE_IND SIR_HAL_IBSS_CESIUM_ENABLE_IND +#define WDA_INIT_BAD_PEER_TX_CTL_INFO_CMD SIR_HAL_BAD_PEER_TX_CTL_INI_CMD + +#ifdef FEATURE_WLAN_TDLS +#define WDA_UPDATE_FW_TDLS_STATE SIR_HAL_UPDATE_FW_TDLS_STATE +#define WDA_UPDATE_TDLS_PEER_STATE SIR_HAL_UPDATE_TDLS_PEER_STATE +#define WDA_TDLS_SHOULD_DISCOVER SIR_HAL_TDLS_SHOULD_DISCOVER +#define WDA_TDLS_SHOULD_TEARDOWN SIR_HAL_TDLS_SHOULD_TEARDOWN +#define WDA_TDLS_PEER_DISCONNECTED SIR_HAL_TDLS_PEER_DISCONNECTED +#define WDA_TDLS_SET_OFFCHAN_MODE SIR_HAL_TDLS_SET_OFFCHAN_MODE +#endif +#define WDA_SET_SAP_INTRABSS_DIS SIR_HAL_SET_SAP_INTRABSS_DIS + +/* Message to Indicate Radar Presence on SAP Channel */ +#define WDA_DFS_RADAR_IND SIR_HAL_DFS_RADAR_IND + +/* Message to indicate beacon tx completion after beacon template update + * beacon offload case + */ +#define WDA_DFS_BEACON_TX_SUCCESS_IND SIR_HAL_BEACON_TX_SUCCESS_IND +#define WDA_FW_STATS_IND SIR_HAL_FW_STATS_IND +#define WDA_DISASSOC_TX_COMP SIR_HAL_DISASSOC_TX_COMP +#define WDA_DEAUTH_TX_COMP SIR_HAL_DEAUTH_TX_COMP +#define WDA_GET_LINK_SPEED SIR_HAL_GET_LINK_SPEED + +#define WDA_GET_RSSI SIR_HAL_GET_RSSI + +#define WDA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND + +#define WDA_VDEV_STOP_IND SIR_HAL_VDEV_STOP_IND + +#ifdef WLAN_FEATURE_STATS_EXT +#define WDA_STATS_EXT_REQUEST SIR_HAL_STATS_EXT_REQUEST +#endif + +#define WDA_VDEV_START_RSP_IND SIR_HAL_VDEV_START_RSP_IND +#define WDA_IPA_OFFLOAD_ENABLE_DISABLE SIR_HAL_IPA_OFFLOAD_ENABLE_DISABLE + +#define WDA_ROAM_PREAUTH_IND SIR_HAL_ROAM_PREAUTH_IND + +#define WDA_TBTT_UPDATE_IND SIR_HAL_TBTT_UPDATE_IND + +#define WDA_GET_TEMPERATURE_REQ SIR_HAL_GET_TEMPERATURE_REQ + +#ifdef FEATURE_WLAN_EXTSCAN +#define WDA_EXTSCAN_GET_CAPABILITIES_REQ SIR_HAL_EXTSCAN_GET_CAPABILITIES_REQ +#define WDA_EXTSCAN_START_REQ SIR_HAL_EXTSCAN_START_REQ +#define WDA_EXTSCAN_STOP_REQ SIR_HAL_EXTSCAN_STOP_REQ +#define WDA_EXTSCAN_SET_BSSID_HOTLIST_REQ SIR_HAL_EXTSCAN_SET_BSS_HOTLIST_REQ +#define WDA_EXTSCAN_RESET_BSSID_HOTLIST_REQ SIR_HAL_EXTSCAN_RESET_BSS_HOTLIST_REQ +#define WDA_EXTSCAN_SET_SIGNF_CHANGE_REQ SIR_HAL_EXTSCAN_SET_SIGNF_CHANGE_REQ +#define WDA_EXTSCAN_RESET_SIGNF_CHANGE_REQ SIR_HAL_EXTSCAN_RESET_SIGNF_CHANGE_REQ +#define WDA_EXTSCAN_GET_CACHED_RESULTS_REQ SIR_HAL_EXTSCAN_GET_CACHED_RESULTS_REQ +#define WDA_SET_EPNO_LIST_REQ SIR_HAL_SET_EPNO_LIST_REQ +#define WDA_SET_PASSPOINT_LIST_REQ SIR_HAL_SET_PASSPOINT_LIST_REQ +#define WDA_RESET_PASSPOINT_LIST_REQ SIR_HAL_RESET_PASSPOINT_LIST_REQ +#define WDA_EXTSCAN_SET_SSID_HOTLIST_REQ SIR_HAL_EXTSCAN_SET_SSID_HOTLIST_REQ +#define WDA_EXTSCAN_STATUS_IND SIR_HAL_EXTSCAN_STATUS_IND +#define WDA_EXTSCAN_OPERATION_IND SIR_HAL_EXTSCAN_OPERATION_IND + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +#define WDA_LINK_LAYER_STATS_CLEAR_REQ SIR_HAL_LL_STATS_CLEAR_REQ +#define WDA_LINK_LAYER_STATS_SET_REQ SIR_HAL_LL_STATS_SET_REQ +#define WDA_LINK_LAYER_STATS_GET_REQ SIR_HAL_LL_STATS_GET_REQ +#define WDA_LINK_LAYER_STATS_RESULTS_RSP SIR_HAL_LL_STATS_RESULTS_RSP +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#define WDA_LINK_STATUS_GET_REQ SIR_HAL_LINK_STATUS_GET_REQ +#define WDA_GET_LINK_STATUS_RSP_IND SIR_HAL_GET_LINK_STATUS_RSP_IND + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define WDA_WLAN_EXT_WOW SIR_HAL_CONFIG_EXT_WOW +#define WDA_WLAN_SET_APP_TYPE1_PARAMS SIR_HAL_CONFIG_APP_TYPE1_PARAMS +#define WDA_WLAN_SET_APP_TYPE2_PARAMS SIR_HAL_CONFIG_APP_TYPE2_PARAMS +#endif + +#define WDA_SET_SCAN_MAC_OUI_REQ SIR_HAL_SET_SCAN_MAC_OUI_REQ +#define WDA_GET_FW_STATUS_REQ SIR_HAL_GET_FW_STATUS_REQ + +#ifdef DHCP_SERVER_OFFLOAD +#define WDA_SET_DHCP_SERVER_OFFLOAD_CMD SIR_HAL_SET_DHCP_SERVER_OFFLOAD +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +#define WDA_LED_FLASHING_REQ SIR_HAL_LED_FLASHING_REQ +#endif + +#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 */ + +#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 +#define WDA_SET_CLIENT_BLOCK_INFO SIR_HAL_SET_CLIENT_BLOCK_INFO +#endif /* SAP_AUTH_OFFLOAD */ + +#ifdef WLAN_FEATURE_APFIND +#define WDA_APFIND_SET_CMD SIR_HAL_APFIND_SET_CMD +#endif /* WLAN_FEATURE_APFIND */ + +#define WDA_OCB_SET_CONFIG_CMD SIR_HAL_OCB_SET_CONFIG_CMD +#define WDA_OCB_SET_UTC_TIME_CMD SIR_HAL_OCB_SET_UTC_TIME_CMD +#define WDA_OCB_START_TIMING_ADVERT_CMD SIR_HAL_OCB_START_TIMING_ADVERT_CMD +#define WDA_OCB_STOP_TIMING_ADVERT_CMD SIR_HAL_OCB_STOP_TIMING_ADVERT_CMD +#define WDA_OCB_GET_TSF_TIMER_CMD SIR_HAL_OCB_GET_TSF_TIMER_CMD +#define WDA_DCC_GET_STATS_CMD SIR_HAL_DCC_GET_STATS_CMD +#define WDA_DCC_CLEAR_STATS_CMD SIR_HAL_DCC_CLEAR_STATS_CMD +#define WDA_DCC_UPDATE_NDL_CMD SIR_HAL_DCC_UPDATE_NDL_CMD + +#ifdef FEATURE_RUNTIME_PM +#define WDA_RUNTIME_PM_SUSPEND_IND SIR_HAL_RUNTIME_PM_SUSPEND_IND +#define WDA_RUNTIME_PM_RESUME_IND SIR_HAL_RUNTIME_PM_RESUME_IND +#endif + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define WDA_UPDATE_Q2Q_IE_IND SIR_HAL_UPDATE_Q2Q_IE_IND +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#define WDA_FW_MEM_DUMP_REQ SIR_HAL_FW_MEM_DUMP_REQ +#define WDA_TSF_GPIO_PIN SIR_HAL_TSF_GPIO_PIN_REQ +#define WDA_SET_RSSI_MONITOR_REQ SIR_HAL_SET_RSSI_MONITOR_REQ + +#define WDA_SET_IE_INFO SIR_HAL_SET_IE_INFO + +#define WDA_SET_UDP_RESP_OFFLOAD SIR_HAL_SET_UDP_RESP_OFFLOAD + +#define WDA_UPDATE_WEP_DEFAULT_KEY SIR_HAL_UPDATE_WEP_DEFAULT_KEY + + + +tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +#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, sessionid) \ + (eHalStatus)( WDA_TxPacket(\ + vos_get_context(VOS_MODULE_ID_WDA,\ + vos_get_global_context(VOS_MODULE_ID_WDA, (hHal))),\ + (pFrmBuf),\ + (frmLen),\ + (frmType),\ + (txDir),\ + (tid),\ + (pCompFunc),\ + (pData),\ + (NULL), \ + (txFlag),\ + (sessionid),\ + (false)) ) + +#define halTxFrameWithTxComplete(hHal, pFrmBuf, frmLen, frmType, txDir, tid,\ + pCompFunc, pData, pCBackFnTxComp, txFlag, sessionid, tdlsflag) \ + (eHalStatus)( WDA_TxPacket(\ + vos_get_context(VOS_MODULE_ID_WDA,\ + vos_get_global_context(VOS_MODULE_ID_WDA, (hHal))),\ + (pFrmBuf),\ + (frmLen),\ + (frmType),\ + (txDir),\ + (tid),\ + (pCompFunc),\ + (pData),\ + (pCBackFnTxComp), \ + (txFlag),\ + (sessionid),\ + (tdlsflag)) ) + + +#define WDA_SetRegDomain WMA_SetRegDomain +#define WDA_SetHTConfig wma_set_htconfig +#define WDA_UpdateRssiBmps WMA_UpdateRssiBmps + +VOS_STATUS WDA_SetIdlePsConfig(void *wda_handle, tANI_U32 idle_ps); +VOS_STATUS WDA_notify_modem_power_state(void *wda_handle, tANI_U32 value); +VOS_STATUS WDA_GetSnr(tAniGetSnrReq *psnr_req); +static inline void WDA_UpdateSnrBmps(v_PVOID_t pvosGCtx, v_U8_t staId, + v_S7_t snr) +{ + +} + +static inline void WDA_UpdateLinkCapacity(v_PVOID_t pvosGCtx, v_U8_t staId, + v_U32_t linkCapacity) +{ + +} + +/*========================================================================== + FUNCTION WDA_DS_PeekRxPacketInfo + + DESCRIPTION + Return RX metainfo pointer for for integrated SOC. + + Same function will return BD header pointer. + + DEPENDENCIES + + PARAMETERS + + IN + vosDataBuff vos data buffer + + pvDestMacAddr destination MAC address ponter + bSwap Want to swap BD header? For backward compatability + It does nothing for integrated SOC + OUT + *ppRxHeader RX metainfo pointer + + RETURN VALUE + VOS_STATUS_E_FAULT: pointer is NULL and other errors + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WDA_DS_PeekRxPacketInfo +( + vos_pkt_t *vosDataBuff, + v_PVOID_t *ppRxHeader, + v_BOOL_t bSwap +); + + +#define WDA_HALDumpCmdReq WMA_HALDumpCmdReq + +#define WDA_featureCapsExchange WMA_featureCapsExchange +#define WDA_disableCapablityFeature WMA_disableCapablityFeature +#define WDA_getFwWlanFeatCaps wma_getFwWlanFeatCaps + +#define WDA_TransportChannelDebug(mac, disp_snapshot, \ + toggle_stall_detect) ({ \ + (void)mac; \ + (void)disp_snapshot; \ + (void)toggle_stall_detect; \ +}) + +#define WDA_TrafficStatsTimerActivate WMA_TrafficStatsTimerActivate +#define WDA_SetEnableSSR(enable_ssr) (void)enable_ssr +void WDA_TxAbort(v_U8_t vdev_id); + + +/* Powersave Offload Changes */ +typedef struct sUapsd_Params +{ + tANI_U8 bkDeliveryEnabled:1; + tANI_U8 beDeliveryEnabled:1; + tANI_U8 viDeliveryEnabled:1; + tANI_U8 voDeliveryEnabled:1; + tANI_U8 bkTriggerEnabled:1; + tANI_U8 beTriggerEnabled:1; + tANI_U8 viTriggerEnabled:1; + tANI_U8 voTriggerEnabled:1; +}tUapsd_Params, *tpUapsd_Params; + +/* Enable PowerSave Params */ +typedef struct sEnablePsParams +{ + tSirAddonPsReq psSetting; + + tUapsd_Params uapsdParams; + + tSirMacAddr bssid; + + /* SmeSession Id or Vdev Id */ + tANI_U32 sessionid; + + /* Beacon DTIM Period */ + tANI_U8 bcnDtimPeriod; + + /* success or failure */ + tANI_U32 status; +}tEnablePsParams, *tpEnablePsParams; + +/* Disable PowerSave Params */ +typedef struct sDisablePsParams +{ + tSirAddonPsReq psSetting; + + tSirMacAddr bssid; + + /* SmeSession Id or Vdev Id */ + tANI_U32 sessionid; + + /* success or failure */ + tANI_U32 status; +}tDisablePsParams, *tpDisablePsParams; + +/* Enable Uapsd Params */ +typedef struct sEnableUapsdParams +{ + tUapsd_Params uapsdParams; + + tSirMacAddr bssid; + + /* SmeSession Id or Vdev Id */ + tANI_U32 sessionid; + + /* success or failure */ + tANI_U32 status; +}tEnableUapsdParams, *tpEnableUapsdParams; + +/* Disable Uapsd Params */ +typedef struct sDisableUapsdParams +{ + tSirMacAddr bssid; + + /* SmeSession Id or Vdev Id */ + tANI_U32 sessionid; + + /* success or failure */ + tANI_U32 status; +}tDisableUapsdParams, *tpDisableUapsdParams; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda_msg.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda_msg.h new file mode 100644 index 000000000000..d104ac6f776a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda_msg.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WLAN_QCT_MSG_MAP_H +#define WLAN_QCT_MSG_MAP_H + +/*=========================================================================== + + W L A N DEVICE ADAPTATION L A Y E R + MSG MAPPING + + +DESCRIPTION + This file contains the external API exposed by the wlan adaptation layer +===========================================================================*/ + + +/*=========================================================================== + + EDIT HISTORY FOR FILE + + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + + $Header:$ $DateTime: $ $Author: $ + + +when who what, where, why +-------- --- ---------------------------------------------- +25/08/2010 adwivedi MAP WDA messages on Legacy HAL messages +=========================================================================== */ + +/* Add Include */ + +#define WDA_CONFIG_PARAM_UPDATE_REQ SIR_CFG_PARAM_UPDATE_IND + +#define ALIGNED_WORD_SIZE 4 + +/* Config format required by HAL for each CFG item*/ +typedef struct +{ + /* Cfg Id. The Id required by HAL is exported by HAL + * in shared header file between UMAC and HAL.*/ + tANI_U16 type; + + /* Length of the Cfg. This parameter is used to go to next cfg + * in the TLV format.*/ + tANI_U16 length; + + /* Padding bytes for unaligned address's */ + tANI_U16 padBytes; + + /* Reserve bytes for making cfgVal to align address */ + tANI_U16 reserved; + + /* Following the uCfgLen field there should be a 'uCfgLen' bytes + * containing the uCfgValue ; tANI_U8 uCfgValue[uCfgLen] */ +}__attribute__((__packed__)) tHalCfg, *tpHalCfg; + +#endif diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.c b/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.c new file mode 100644 index 000000000000..eceff1f7c5ed --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + wlan_qct_wda_debug.c + + OVERVIEW: + + This software unit holds the implementation of the WLAN Device Adaptation + Layer for debugging APIs. + + The functions externalized by this module are to be called ONLY by other + WLAN modules that properly register with the Transport Layer initially. + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + + +#include "palTypes.h" +#include "wlan_qct_wda_debug.h" + +void wdaLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) { + va_list marker; + + if(loglevel > pMac->utils.gLogDbgLevel[WDA_DEBUG_LOGIDX]) + return; + + va_start( marker, pString ); /* Initialize variable arguments. */ + + logDebug(pMac, SIR_WDA_MODULE_ID, loglevel, pString, marker); + + va_end( marker ); /* Reset variable arguments. */ +} diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.h b/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.h new file mode 100644 index 000000000000..d741d7b21041 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_debug.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WDA_DEBUG_H__ +#define __WDA_DEBUG_H__ +#if !defined (ANI_OS_TYPE_ANDROID) +#include +#endif +#include + +#include "utilsApi.h" +#include "sirDebug.h" +#include "sirParams.h" +#define WDA_DEBUG_LOGIDX ( LOG_INDEX_FOR_MODULE(SIR_WDA_MODULE_ID) ) + + + +#ifdef WLAN_DEBUG + +#define WDALOGP(x0) x0 +#define WDALOGE(x0) x0 +#define WDALOGW(x0) x0 +#define WDALOG1(x0) x0 + +#ifdef HAL_DEBUG_LOG2 +#define WDALOG2(x0) x0 +#else + #define WDALOG2(x0) +#endif + +#ifdef HAL_DEBUG_LOG3 +#define WDALOG3(x0) x0 +#else + #define WDALOG3(x0) +#endif + +#ifdef HAL_DEBUG_LOG4 +#define WDALOG4(x0) x0 +#else + #define WDALOG4(x0) +#endif + +#define STR(x) x + +#else + +#define WDALOGP(x) x +#define WDALOGE(x) {} +#define WDALOGW(x) {} +#define WDALOG1(x) {} +#define WDALOG2(x) {} +#define WDALOG3(x) {} +#define WDALOG4(x) {} +#define STR(x) "" +#endif + +void wdaLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...); + +#endif // __WDA_DEBUG_H__ diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_legacy.c b/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_legacy.c new file mode 100644 index 000000000000..6ef18cf50206 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/src/wlan_qct_wda_legacy.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + wlan_qct_wda_legacy.c + + OVERVIEW: + + This software unit holds the implementation of the WLAN Device Adaptation + Layer for the legacy functionalities that were part of the old HAL. + + The functions externalized by this module are to be called ONLY by other + WLAN modules that properly register with the Transport Layer initially. + + DEPENDENCIES: + + Are listed for each API below. +===========================================================================*/ + +/* Standard include files */ +/* Application Specific include files */ +#include "limApi.h" +#include "pmmApi.h" +#include "cfgApi.h" +#include "wlan_qct_wda_debug.h" + +/* Locally used Defines */ + +#define HAL_MMH_MB_MSG_TYPE_MASK 0xFF00 + +// ------------------------------------------------------------- +/** + * wdaPostCtrlMsg + * + * FUNCTION: + * Posts WDA messages to MC thread + * + * LOGIC: + * + * ASSUMPTIONS:pl + * + * + * NOTE: + * + * @param tpAniSirGlobal MAC parameters structure + * @param pMsg pointer with message + * @return Success or Failure + */ + +tSirRetStatus +wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_WDA, (vos_msg_t *) pMsg)) + return eSIR_FAILURE; + else + return eSIR_SUCCESS; +} // halPostMsg() + +/** + * wdaPostCfgMsg + * + * FUNCTION: + * Posts MNT messages to gSirMntMsgQ + * + * LOGIC: + * + * ASSUMPTIONS: + * + * + * NOTE: + * + * @param tpAniSirGlobal MAC parameters structure + * @param pMsg A pointer to the msg + * @return Success or Failure + */ + +tSirRetStatus +wdaPostCfgMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + tSirRetStatus rc = eSIR_SUCCESS; + + do + { + // For Windows based MAC, instead of posting message to different + // queues we will call the handler routines directly + + cfgProcessMbMsg(pMac, (tSirMbMsg*)pMsg->bodyptr); + rc = eSIR_SUCCESS; + } while (0); + + return rc; +} // halMntPostMsg() + + +// ------------------------------------------------------------- +/** + * uMacPostCtrlMsg + * + * FUNCTION: + * Forwards the completely received message to the respective + * modules for further processing. + * + * LOGIC: + * + * ASSUMPTIONS: + * Freeing up of the message buffer is left to the destination module. + * + * NOTE: + * This function has been moved to the API file because for MAC running + * on Windows host, the host module will call this routine directly to + * send any mailbox messages. Making this function an API makes sure that + * outside world (any module outside MMH) only calls APIs to use MMH + * services and not an internal function. + * + * @param pMb A pointer to the maibox message + * @return NONE + */ + +tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal)pSirGlobal; + + + tSirMbMsg* pMbLocal; + msg.type = pMb->type; + msg.bodyval = 0; + + WDALOG3(wdaLog(pMac, LOG3, FL("msgType %d, msgLen %d" ), + pMb->type, pMb->msgLen)); + + // copy the message from host buffer to firmware buffer + // this will make sure that firmware allocates, uses and frees + // it's own buffers for mailbox message instead of working on + // host buffer + + // second parameter, 'wait option', to palAllocateMemory is ignored on Windows + pMbLocal = vos_mem_malloc(pMb->msgLen); + if ( NULL == pMbLocal ) + { + WDALOGE( wdaLog(pMac, LOGE, FL("Buffer Allocation failed!"))); + return eSIR_FAILURE; + } + + vos_mem_copy((void *)pMbLocal, (void *)pMb, pMb->msgLen); + msg.bodyptr = pMbLocal; + + switch (msg.type & HAL_MMH_MB_MSG_TYPE_MASK) + { + case WDA_MSG_TYPES_BEGIN: // Posts a message to the HAL MsgQ + wdaPostCtrlMsg(pMac, &msg); + break; + + case SIR_LIM_MSG_TYPES_BEGIN: // Posts a message to the LIM MsgQ + limPostMsgApi(pMac, &msg); + break; + + case SIR_CFG_MSG_TYPES_BEGIN: // Posts a message to the CFG MsgQ + wdaPostCfgMsg(pMac, &msg); + break; + + case SIR_PMM_MSG_TYPES_BEGIN: // Posts a message to the PMM MsgQ + pmmPostMessage(pMac, &msg); + break; + + case SIR_PTT_MSG_TYPES_BEGIN: + WDALOGW( wdaLog(pMac, LOGW, FL("%s:%d: message type = 0x%X"), + __func__, __LINE__, msg.type)); + vos_mem_free(msg.bodyptr); + break; + + + default: + WDALOGW( wdaLog(pMac, LOGW, FL("Unknown message type = " + "0x%X"), + msg.type)); + + // Release the memory. + vos_mem_free(msg.bodyptr); + break; + } + + return eSIR_SUCCESS; + +} // uMacPostCtrlMsg() diff --git a/drivers/staging/qcacld-2.0/Kbuild b/drivers/staging/qcacld-2.0/Kbuild new file mode 100644 index 000000000000..9fb7084a9485 --- /dev/null +++ b/drivers/staging/qcacld-2.0/Kbuild @@ -0,0 +1,1444 @@ +# We can build either as part of a standalone Kernel build or as +# an external module. Determine which mechanism is being used +ifeq ($(MODNAME),) + KERNEL_BUILD := 1 +else + KERNEL_BUILD := 0 +endif + +ifeq ($(CONFIG_CLD_HL_SDIO_CORE), y) + CONFIG_QCA_WIFI_SDIO := 1 +endif + +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) + CONFIG_ROME_IF = sdio +endif + +ifndef CONFIG_ROME_IF + #use pci as default interface + CONFIG_ROME_IF = pci +endif + +ifeq ($(KERNEL_BUILD),1) + # These are provided in external module based builds + # Need to explicitly define for Kernel-based builds + MODNAME := wlan + WLAN_ROOT := drivers/staging/qcacld-2.0 + WLAN_OPEN_SOURCE := 1 +endif + +ifeq ($(KERNEL_BUILD), 0) + # These are configurable via Kconfig for kernel-based builds + # Need to explicitly configure for Android-based builds + + ifeq ($(CONFIG_ARCH_MDM9630), y) + CONFIG_MOBILE_ROUTER := y + endif + + ifeq ($(CONFIG_ARCH_MDM9640), y) + CONFIG_MOBILE_ROUTER := y + endif + + ifeq ($(CONFIG_ARCH_MDMCALIFORNIUM), y) + CONFIG_MOBILE_ROUTER := y + endif + + ifeq ($(CONFIG_ARCH_MDMFERMIUM), y) + CONFIG_MOBILE_ROUTER := y + endif + + #Flag to enable Legacy Fast Roaming3(LFR3) + CONFIG_QCACLD_WLAN_LFR3 := y + + #JB kernel has PMKSA patches, hence enabling this flag + CONFIG_PRIMA_WLAN_OKC := y + + # JB kernel has CPU enablement patches, so enable + ifeq ($(CONFIG_ROME_IF),pci) + CONFIG_PRIMA_WLAN_11AC_HIGH_TP := y + endif + ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_PRIMA_WLAN_11AC_HIGH_TP := n + endif + ifeq ($(CONFIG_ROME_IF),sdio) + CONFIG_PRIMA_WLAN_11AC_HIGH_TP := n + endif + + ifneq ($(CONFIG_MOBILE_ROUTER), y) + #Flag to enable TDLS feature + CONFIG_QCOM_TDLS := y + endif + + #Flag to enable Fast Transition (11r) feature + CONFIG_QCOM_VOWIFI_11R := y + + ifneq ($(CONFIG_QCA_CLD_WLAN),) + ifeq ($(CONFIG_CNSS),y) + #Flag to enable Protected Managment Frames (11w) feature + CONFIG_WLAN_FEATURE_11W := y + #Flag to enable LTE CoEx feature + CONFIG_QCOM_LTE_COEX := y + ifneq ($(CONFIG_MOBILE_ROUTER), y) + #Flag to enable LPSS feature + CONFIG_WLAN_FEATURE_LPSS := y + endif + endif + endif + + + #Flag to enable Protected Managment Frames (11w) feature + ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_WLAN_FEATURE_11W := y + endif + ifeq ($(CONFIG_ROME_IF),sdio) + CONFIG_WLAN_FEATURE_11W := y + endif + + ifneq ($(CONFIG_MOBILE_ROUTER), y) + #Flag to enable NAN + CONFIG_WLAN_FEATURE_NAN := y + endif + + #Flag to enable Linux QCMBR feature as default feature + ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_LINUX_QCMBR :=y + endif + + ifneq ($(CONFIG_ARCH_MDMFERMIUM), y) + #Flag to enable memdump feature + CONFIG_WLAN_FEATURE_MEMDUMP := y + + #Flag to enable offload packets feature + CONFIG_WLAN_OFFLOAD_PACKETS := y + endif +endif + +ifdef CPTCFG_QCA_CLD_WLAN + WLAN_ROOT := $(BACKPORT_PWD)/drivers/staging/qcacld-2.0 + CONFIG_QCA_CLD_WLAN=$(CPTCFG_QCA_CLD_WLAN) +endif + +ifeq ($(CONFIG_X86), y) +CONFIG_NON_QC_PLATFORM := y +endif + +ifneq ($(CONFIG_MOBILE_ROUTER), y) +# To enable ESE upload, dependent config +# CONFIG_QCOM_ESE must be enabled. +CONFIG_QCOM_ESE := y +CONFIG_QCOM_ESE_UPLOAD := y +endif + +# Feature flags which are not (currently) configurable via Kconfig + +#Whether to build debug version +BUILD_DEBUG_VERSION := 1 + +#Enable this flag to build driver in diag version +BUILD_DIAG_VERSION := 1 + +#Do we panic on bug? default is to warn +PANIC_ON_BUG := 1 + +#Re-enable wifi on WDI timeout +RE_ENABLE_WIFI_ON_WDI_TIMEOUT := 0 + +#Enable OS specific ADF abstraction +CONFIG_ADF_SUPPORT := 1 + +#Enable OL debug and wmi unified functions +CONFIG_ATH_PERF_PWR_OFFLOAD := 1 + +#Disable packet log +CONFIG_REMOVE_PKT_LOG := 0 + +#Enable 11AC TX +ifeq ($(CONFIG_ROME_IF),pci) + CONFIG_ATH_11AC_TXCOMPACT := 1 +endif +ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_ATH_11AC_TXCOMPACT := 0 +endif +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) +CONFIG_ATH_11AC_TXCOMPACT := 0 +endif + +#Enable per vdev Tx desc pool +ifeq ($(CONFIG_ROME_IF),pci) + CONFIG_PER_VDEV_TX_DESC_POOL := 0 +endif +ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_PER_VDEV_TX_DESC_POOL := 1 +endif +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) + CONFIG_PER_VDEV_TX_DESC_POOL := 0 +endif +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) + CONFIG_TX_DESC_HI_PRIO_RESERVE := 1 +endif + + +#Enable OS specific IRQ abstraction +CONFIG_ATH_SUPPORT_SHARED_IRQ := 1 + +#Enable message based HIF instead of RAW access in BMI +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) +CONFIG_HIF_MESSAGE_BASED := 0 +else +CONFIG_HIF_MESSAGE_BASED := 1 +endif + +#Enable PCI specific APIS (dma, etc) +ifeq ($(CONFIG_ROME_IF),pci) + CONFIG_HIF_PCI := 1 +endif +#Enable USB specific APIS +ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_HIF_USB := 1 +endif + +#Enable pci read/write config functions +ifeq ($(CONFIG_ROME_IF),pci) + CONFIG_ATH_PCI := 1 +endif +ifeq ($(CONFIG_ROME_IF),usb) +#CONFIG_ATH_PCI := 1 +endif + +ifneq ($(CONFIG_MOBILE_ROUTER), y) +#Enable IBSS support on CLD +CONFIG_QCA_IBSS_SUPPORT := 1 +endif + +#Enable MDNS Offload +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) +ifneq ($(CONFIG_ARCH_MDMFERMIUM), y) +CONFIG_MDNS_OFFLOAD_SUPPORT := 1 +endif +endif + +#Enable power management suspend/resume functionality to PCI +CONFIG_ATH_BUS_PM := 1 + +#Enable dword alignment for IP header +CONFIG_IP_HDR_ALIGNMENT := 0 + +#Enable FLOWMAC module support +CONFIG_ATH_SUPPORT_FLOWMAC_MODULE := 0 + +#Enable spectral support +CONFIG_ATH_SUPPORT_SPECTRAL := 0 + +#Enable HOST statistics support +CONFIG_SUPPORT_HOST_STATISTICS := 0 + +#Enable WDI Event support +CONFIG_WDI_EVENT_ENABLE := 1 + +#Endianess selection +CONFIG_LITTLE_ENDIAN := 1 + +#Enable TX reclaim support +CONFIG_TX_CREDIT_RECLAIM_SUPPORT := 0 + +#Enable FTM support +CONFIG_QCA_WIFI_FTM := 1 + +#Enable Checksum Offload +CONFIG_CHECKSUM_OFFLOAD := 1 + +#Enable GTK offload +CONFIG_GTK_OFFLOAD := 1 + +#Enable EXT WOW +ifeq ($(CONFIG_ROME_IF),pci) + CONFIG_EXT_WOW := 1 +endif + +#Set this to 1 to catch erroneous Target accesses during debug. +CONFIG_ATH_PCIE_ACCESS_DEBUG := 0 + +#Enable IPA offload +ifeq ($(CONFIG_IPA), y) +CONFIG_IPA_OFFLOAD := 1 +CONFIG_IPA_UC_OFFLOAD := 1 +endif + +#Enable Signed firmware support for split binary format +CONFIG_QCA_SIGNED_SPLIT_BINARY_SUPPORT := 0 + +#Enable single firmware binary format +CONFIG_QCA_SINGLE_BINARY_SUPPORT := 0 + +#Enable collecting target RAM dump after kernel panic +CONFIG_TARGET_RAMDUMP_AFTER_KERNEL_PANIC := 1 + +#Flag to enable Stats Ext implementation +CONFIG_FEATURE_STATS_EXT := 1 + +#Flag to force the inclusion of the 802.11p channels because support +#for these channels has not yet been added to the kernel. +CONFIG_STATICALLY_ADD_11P_CHANNELS := n + +ifeq ($(CONFIG_CFG80211),y) +HAVE_CFG80211 := 1 +else +ifeq ($(CONFIG_CFG80211),m) +HAVE_CFG80211 := 1 +else +HAVE_CFG80211 := 0 +endif +endif + +############ COMMON ############ +COMMON_DIR := CORE/SERVICES/COMMON +COMMON_INC := -I$(WLAN_ROOT)/$(COMMON_DIR) + +############ ADF ############## +ADF_DIR := $(COMMON_DIR)/adf +ADF_INC := -I$(WLAN_ROOT)/$(ADF_DIR) \ + -I$(WLAN_ROOT)/$(ADF_DIR)/linux \ + -I$(WLAN_ROOT)/$(COMMON_DIR)/asf + +ADF_OBJS := $(ADF_DIR)/adf_nbuf.o \ + $(ADF_DIR)/adf_os_lock.o \ + $(ADF_DIR)/adf_os_mem.o \ + $(ADF_DIR)/linux/adf_os_defer_pvt.o \ + $(ADF_DIR)/linux/adf_os_lock_pvt.o + +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) +############ HIF ############ +HIF_DIR := CORE/SERVICES/HIF +HIF_DIR_OBJS := $(HIF_DIR)/ath_procfs.o + +HIF_COMMON_DIR := CORE/SERVICES/HIF/common +HIF_COMMON_OBJS := $(HIF_COMMON_DIR)/hif_bmi_reg_access.o \ + $(HIF_COMMON_DIR)/hif_diag_reg_access.o + +HIF_SDIO_DIR := CORE/SERVICES/HIF/sdio +HIF_SDIO_OBJS := $(HIF_SDIO_DIR)/hif_sdio_send.o \ + $(HIF_SDIO_DIR)/hif_sdio_dev.o \ + $(HIF_SDIO_DIR)/hif_sdio.o \ + $(HIF_SDIO_DIR)/hif_sdio_recv.o \ + $(HIF_SDIO_DIR)/regtable.o \ + +HIF_SDIO_LINUX_DIR := $(HIF_SDIO_DIR)/linux +HIF_SDIO_LINUX_OBJS := $(HIF_SDIO_LINUX_DIR)/if_ath_sdio.o + + +HIF_SDIO_NATIVE_DIR := $(HIF_SDIO_LINUX_DIR)/native_sdio +HIF_SDIO_NATIVE_INC_DIR := $(HIF_SDIO_NATIVE_DIR)/include +HIF_SDIO_NATIVE_SRC_DIR := $(HIF_SDIO_NATIVE_DIR)/src + +HIF_SDIO_NATIVE_OBJS := $(HIF_SDIO_NATIVE_SRC_DIR)/hif.o \ + $(HIF_SDIO_NATIVE_SRC_DIR)/hif_scatter.o + +HIF_INC := -I$(WLAN_ROOT)/$(HIF_COMMON_DIR) \ + -I$(WLAN_ROOT)/$(HIF_SDIO_DIR) \ + -I$(WLAN_ROOT)/$(HIF_SDIO_LINUX_DIR) \ + -I$(WLAN_ROOT)/$(HIF_SDIO_NATIVE_INC_DIR) \ + -I$(WLAN_ROOT)/$(HIF_SDIO_NATIVE_SRC_DIR) + +HIF_OBJS := $(HIF_DIR_OBJS) \ + $(HIF_COMMON_OBJS) \ + $(HIF_SDIO_OBJS) \ + $(HIF_SDIO_LINUX_OBJS) \ + $(HIF_SDIO_NATIVE_OBJS) +endif + +############ HDD ############ +HDD_DIR := CORE/HDD +HDD_INC_DIR := $(HDD_DIR)/inc +HDD_SRC_DIR := $(HDD_DIR)/src + +HDD_INC := -I$(WLAN_ROOT)/$(HDD_INC_DIR) \ + -I$(WLAN_ROOT)/$(HDD_SRC_DIR) + +HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ + $(HDD_SRC_DIR)/wlan_hdd_cfg.o \ + $(HDD_SRC_DIR)/wlan_hdd_debugfs.o \ + $(HDD_SRC_DIR)/wlan_hdd_dev_pwr.o \ + $(HDD_SRC_DIR)/wlan_hdd_dp_utils.o \ + $(HDD_SRC_DIR)/wlan_hdd_early_suspend.o \ + $(HDD_SRC_DIR)/wlan_hdd_ftm.o \ + $(HDD_SRC_DIR)/wlan_hdd_hostapd.o \ + $(HDD_SRC_DIR)/wlan_hdd_main.o \ + $(HDD_SRC_DIR)/wlan_hdd_ocb.o \ + $(HDD_SRC_DIR)/wlan_hdd_oemdata.o \ + $(HDD_SRC_DIR)/wlan_hdd_scan.o \ + $(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.o \ + $(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \ + $(HDD_SRC_DIR)/wlan_hdd_trace.o \ + $(HDD_SRC_DIR)/wlan_hdd_wext.o \ + $(HDD_SRC_DIR)/wlan_hdd_wmm.o \ + $(HDD_SRC_DIR)/wlan_hdd_wowl.o + +ifeq ($(CONFIG_IPA_OFFLOAD), 1) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_ipa.o +endif + +ifeq ($(CONFIG_MDNS_OFFLOAD_SUPPORT), 1) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_mdns_offload.o +endif + +ifeq ($(HAVE_CFG80211),1) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_cfg80211.o \ + $(HDD_SRC_DIR)/wlan_hdd_p2p.o +endif + +ifeq ($(CONFIG_QCOM_TDLS),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o +endif + +ifeq ($(CONFIG_WLAN_SYNC_TSF),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tsf.o +endif + +ifeq ($(CONFIG_WLAN_FEATURE_MEMDUMP),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_memdump.o +endif + +############ EPPING ############ +EPPING_DIR := CORE/EPPING +EPPING_INC_DIR := $(EPPING_DIR)/inc +EPPING_SRC_DIR := $(EPPING_DIR)/src + +EPPING_INC := -I$(WLAN_ROOT)/$(EPPING_INC_DIR) + +EPPING_OBJS := $(EPPING_SRC_DIR)/epping_main.o \ + $(EPPING_SRC_DIR)/epping_txrx.o \ + $(EPPING_SRC_DIR)/epping_tx.o \ + $(EPPING_SRC_DIR)/epping_rx.o \ + $(EPPING_SRC_DIR)/epping_helper.o \ + + +############ MAC ############ +MAC_DIR := CORE/MAC +MAC_INC_DIR := $(MAC_DIR)/inc +MAC_SRC_DIR := $(MAC_DIR)/src + +MAC_INC := -I$(WLAN_ROOT)/$(MAC_INC_DIR) \ + -I$(WLAN_ROOT)/$(MAC_SRC_DIR)/dph \ + -I$(WLAN_ROOT)/$(MAC_SRC_DIR)/include \ + -I$(WLAN_ROOT)/$(MAC_SRC_DIR)/pe/include \ + -I$(WLAN_ROOT)/$(MAC_SRC_DIR)/pe/lim + +MAC_CFG_OBJS := $(MAC_SRC_DIR)/cfg/cfgApi.o \ + $(MAC_SRC_DIR)/cfg/cfgDebug.o \ + $(MAC_SRC_DIR)/cfg/cfgParamName.o \ + $(MAC_SRC_DIR)/cfg/cfgProcMsg.o \ + $(MAC_SRC_DIR)/cfg/cfgSendMsg.o + +MAC_DPH_OBJS := $(MAC_SRC_DIR)/dph/dphHashTable.o + +MAC_LIM_OBJS := $(MAC_SRC_DIR)/pe/lim/limAIDmgmt.o \ + $(MAC_SRC_DIR)/pe/lim/limAdmitControl.o \ + $(MAC_SRC_DIR)/pe/lim/limApi.o \ + $(MAC_SRC_DIR)/pe/lim/limAssocUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limDebug.o \ + $(MAC_SRC_DIR)/pe/lim/limFT.o \ + $(MAC_SRC_DIR)/pe/lim/limIbssPeerMgmt.o \ + $(MAC_SRC_DIR)/pe/lim/limLinkMonitoringAlgo.o \ + $(MAC_SRC_DIR)/pe/lim/limLogDump.o \ + $(MAC_SRC_DIR)/pe/lim/limP2P.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessActionFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessAssocReqFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessAssocRspFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessAuthFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessBeaconFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessCfgUpdates.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessDeauthFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessDisassocFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessMessageQueue.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessMlmReqMessages.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessMlmRspMessages.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessProbeReqFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessProbeRspFrame.o \ + $(MAC_SRC_DIR)/pe/lim/limProcessSmeReqMessages.o \ + $(MAC_SRC_DIR)/pe/lim/limPropExtsUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limRoamingAlgo.o \ + $(MAC_SRC_DIR)/pe/lim/limScanResultUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limSecurityUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limSendManagementFrames.o \ + $(MAC_SRC_DIR)/pe/lim/limSendMessages.o \ + $(MAC_SRC_DIR)/pe/lim/limSendSmeRspMessages.o \ + $(MAC_SRC_DIR)/pe/lim/limSerDesUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limSession.o \ + $(MAC_SRC_DIR)/pe/lim/limSessionUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limSmeReqUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limStaHashApi.o \ + $(MAC_SRC_DIR)/pe/lim/limTimerUtils.o \ + $(MAC_SRC_DIR)/pe/lim/limTrace.o \ + $(MAC_SRC_DIR)/pe/lim/limUtils.o + +ifeq ($(CONFIG_QCOM_ESE),y) +ifneq ($(CONFIG_QCOM_ESE_UPLOAD),y) +MAC_LIM_OBJS += $(MAC_SRC_DIR)/pe/lim/limProcessEseFrame.o +endif +endif + +ifeq ($(CONFIG_QCOM_TDLS),y) +MAC_LIM_OBJS += $(MAC_SRC_DIR)/pe/lim/limProcessTdls.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 + +MAC_SCH_OBJS := $(MAC_SRC_DIR)/pe/sch/schApi.o \ + $(MAC_SRC_DIR)/pe/sch/schBeaconGen.o \ + $(MAC_SRC_DIR)/pe/sch/schBeaconProcess.o \ + $(MAC_SRC_DIR)/pe/sch/schDebug.o \ + $(MAC_SRC_DIR)/pe/sch/schMessage.o + +MAC_RRM_OBJS := $(MAC_SRC_DIR)/pe/rrm/rrmApi.o + +MAC_OBJS := $(MAC_CFG_OBJS) \ + $(MAC_DPH_OBJS) \ + $(MAC_LIM_OBJS) \ + $(MAC_PMM_OBJS) \ + $(MAC_SCH_OBJS) \ + $(MAC_RRM_OBJS) + +############ SAP ############ +SAP_DIR := CORE/SAP +SAP_INC_DIR := $(SAP_DIR)/inc +SAP_SRC_DIR := $(SAP_DIR)/src + +SAP_INC := -I$(WLAN_ROOT)/$(SAP_INC_DIR) \ + -I$(WLAN_ROOT)/$(SAP_SRC_DIR) + +SAP_OBJS := $(SAP_SRC_DIR)/sapApiLinkCntl.o \ + $(SAP_SRC_DIR)/sapChSelect.o \ + $(SAP_SRC_DIR)/sapFsm.o \ + $(SAP_SRC_DIR)/sapModule.o + +############ DFS ############ 350 +DFS_DIR := CORE/SERVICES/DFS +DFS_INC_DIR := $(DFS_DIR)/inc +DFS_SRC_DIR := $(DFS_DIR)/src + +DFS_INC := -I$(WLAN_ROOT)/$(DFS_INC_DIR) \ + -I$(WLAN_ROOT)/$(DFS_SRC_DIR) + +DFS_OBJS := $(DFS_SRC_DIR)/dfs_bindetects.o \ + $(DFS_SRC_DIR)/dfs.o \ + $(DFS_SRC_DIR)/dfs_debug.o\ + $(DFS_SRC_DIR)/dfs_fcc_bin5.o\ + $(DFS_SRC_DIR)/dfs_init.o\ + $(DFS_SRC_DIR)/dfs_misc.o\ + $(DFS_SRC_DIR)/dfs_nol.o\ + $(DFS_SRC_DIR)/dfs_phyerr_tlv.o\ + $(DFS_SRC_DIR)/dfs_process_phyerr.o\ + $(DFS_SRC_DIR)/dfs_process_radarevent.o\ + $(DFS_SRC_DIR)/dfs_staggered.o + +############ SME ############ +SME_DIR := CORE/SME +SME_INC_DIR := $(SME_DIR)/inc +SME_SRC_DIR := $(SME_DIR)/src + +SME_INC := -I$(WLAN_ROOT)/$(SME_INC_DIR) \ + -I$(WLAN_ROOT)/$(SME_SRC_DIR)/csr + +SME_CCM_OBJS := $(SME_SRC_DIR)/ccm/ccmApi.o \ + $(SME_SRC_DIR)/ccm/ccmLogDump.o + +SME_CSR_OBJS := $(SME_SRC_DIR)/csr/csrApiRoam.o \ + $(SME_SRC_DIR)/csr/csrApiScan.o \ + $(SME_SRC_DIR)/csr/csrCmdProcess.o \ + $(SME_SRC_DIR)/csr/csrLinkList.o \ + $(SME_SRC_DIR)/csr/csrLogDump.o \ + $(SME_SRC_DIR)/csr/csrNeighborRoam.o \ + $(SME_SRC_DIR)/csr/csrUtil.o + +ifeq ($(CONFIG_QCOM_ESE),y) +ifneq ($(CONFIG_QCOM_ESE_UPLOAD),y) +SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csrEse.o +endif +endif + +ifeq ($(CONFIG_QCOM_TDLS),y) +SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csrTdlsProcess.o +endif + +SME_PMC_OBJS := $(SME_SRC_DIR)/pmc/pmcApi.o \ + $(SME_SRC_DIR)/pmc/pmc.o \ + $(SME_SRC_DIR)/pmc/pmcLogDump.o + +SME_QOS_OBJS := $(SME_SRC_DIR)/QoS/sme_Qos.o + +SME_CMN_OBJS := $(SME_SRC_DIR)/sme_common/sme_Api.o \ + $(SME_SRC_DIR)/sme_common/sme_FTApi.o \ + $(SME_SRC_DIR)/sme_common/sme_Trace.o + +SME_BTC_OBJS := $(SME_SRC_DIR)/btc/btcApi.o + +SME_OEM_DATA_OBJS := $(SME_SRC_DIR)/oemData/oemDataApi.o + +SME_P2P_OBJS = $(SME_SRC_DIR)/p2p/p2p_Api.o + +SME_RRM_OBJS := $(SME_SRC_DIR)/rrm/sme_rrm.o + +ifeq ($(CONFIG_WLAN_FEATURE_NAN),y) +SME_NAN_OBJS = $(SME_SRC_DIR)/nan/nan_Api.o +endif + +SME_OBJS := $(SME_BTC_OBJS) \ + $(SME_CCM_OBJS) \ + $(SME_CMN_OBJS) \ + $(SME_CSR_OBJS) \ + $(SME_OEM_DATA_OBJS) \ + $(SME_P2P_OBJS) \ + $(SME_PMC_OBJS) \ + $(SME_QOS_OBJS) \ + $(SME_RRM_OBJS) \ + $(SME_NAN_OBJS) + +############ SVC ############ +SVC_DIR := CORE/SVC +SVC_INC_DIR := $(SVC_DIR)/inc +SVC_SRC_DIR := $(SVC_DIR)/src + +SVC_INC := -I$(WLAN_ROOT)/$(SVC_INC_DIR) \ + -I$(WLAN_ROOT)/$(SVC_DIR)/external + +BTC_SRC_DIR := $(SVC_SRC_DIR)/btc +BTC_OBJS := $(BTC_SRC_DIR)/wlan_btc_svc.o + +NLINK_SRC_DIR := $(SVC_SRC_DIR)/nlink +NLINK_OBJS := $(NLINK_SRC_DIR)/wlan_nlink_srv.o + +PTT_SRC_DIR := $(SVC_SRC_DIR)/ptt +PTT_OBJS := $(PTT_SRC_DIR)/wlan_ptt_sock_svc.o + +WLAN_LOGGING_SRC_DIR := $(SVC_SRC_DIR)/logging +WLAN_LOGGING_OBJS := $(WLAN_LOGGING_SRC_DIR)/wlan_logging_sock_svc.o + +SVC_OBJS := $(BTC_OBJS) \ + $(NLINK_OBJS) \ + $(PTT_OBJS) \ + $(WLAN_LOGGING_OBJS) + +############ SYS ############ +SYS_DIR := CORE/SYS + +SYS_INC := -I$(WLAN_ROOT)/$(SYS_DIR)/common/inc \ + -I$(WLAN_ROOT)/$(SYS_DIR)/legacy/src/pal/inc \ + -I$(WLAN_ROOT)/$(SYS_DIR)/legacy/src/platform/inc \ + -I$(WLAN_ROOT)/$(SYS_DIR)/legacy/src/system/inc \ + -I$(WLAN_ROOT)/$(SYS_DIR)/legacy/src/utils/inc + +SYS_COMMON_SRC_DIR := $(SYS_DIR)/common/src +SYS_LEGACY_SRC_DIR := $(SYS_DIR)/legacy/src +SYS_OBJS := $(SYS_COMMON_SRC_DIR)/wlan_qct_sys.o \ + $(SYS_LEGACY_SRC_DIR)/pal/src/palApiComm.o \ + $(SYS_LEGACY_SRC_DIR)/platform/src/VossWrapper.o \ + $(SYS_LEGACY_SRC_DIR)/system/src/macInitApi.o \ + $(SYS_LEGACY_SRC_DIR)/system/src/sysEntryFunc.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/dot11f.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/logApi.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/logDump.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/macTrace.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/parserApi.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/utilsApi.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/utilsParser.o + +############ TL ############ +TL_DIR := CORE/TL +TL_INC_DIR := $(TL_DIR)/inc + +TL_INC := -I$(WLAN_ROOT)/$(TL_INC_DIR) + +############ VOSS ############ +VOSS_DIR := CORE/VOSS +VOSS_INC_DIR := $(VOSS_DIR)/inc +VOSS_SRC_DIR := $(VOSS_DIR)/src + +VOSS_INC := -I$(WLAN_ROOT)/$(VOSS_INC_DIR) \ + -I$(WLAN_ROOT)/$(VOSS_SRC_DIR) + +VOSS_OBJS := $(VOSS_SRC_DIR)/vos_api.o \ + $(VOSS_SRC_DIR)/vos_event.o \ + $(VOSS_SRC_DIR)/vos_getBin.o \ + $(VOSS_SRC_DIR)/vos_list.o \ + $(VOSS_SRC_DIR)/vos_lock.o \ + $(VOSS_SRC_DIR)/vos_memory.o \ + $(VOSS_SRC_DIR)/vos_mq.o \ + $(VOSS_SRC_DIR)/vos_nvitem.o \ + $(VOSS_SRC_DIR)/vos_packet.o \ + $(VOSS_SRC_DIR)/vos_sched.o \ + $(VOSS_SRC_DIR)/vos_threads.o \ + $(VOSS_SRC_DIR)/vos_timer.o \ + $(VOSS_SRC_DIR)/vos_trace.o \ + $(VOSS_SRC_DIR)/vos_types.o \ + $(VOSS_SRC_DIR)/vos_utils.o + +ifeq ($(BUILD_DIAG_VERSION),1) +VOSS_OBJS += $(VOSS_SRC_DIR)/vos_diag.o +endif + +########### BMI ########### +BMI_DIR := CORE/SERVICES/BMI + +BMI_INC := -I$(WLAN_ROOT)/$(BMI_DIR) + +BMI_OBJS := $(BMI_DIR)/bmi.o \ + $(BMI_DIR)/ol_fw.o + +########### WMI ########### +WMI_DIR := CORE/SERVICES/WMI + +WMI_INC := -I$(WLAN_ROOT)/$(WMI_DIR) + +WMI_OBJS := $(WMI_DIR)/wmi_unified.o \ + $(WMI_DIR)/wmi_tlv_helper.o + +########### FWLOG ########### +FWLOG_DIR := CORE/UTILS/FWLOG + +FWLOG_INC := -I$(WLAN_ROOT)/$(FWLOG_DIR) + +FWLOG_OBJS := $(FWLOG_DIR)/dbglog_host.o + +############ TLSHIM ############ +TLSHIM_DIR := CORE/CLD_TXRX/TLSHIM +TLSHIM_INC := -I$(WLAN_ROOT)/$(TLSHIM_DIR) + +TLSHIM_OBJS := $(TLSHIM_DIR)/tl_shim.o + +############ TXRX ############ +TXRX_DIR := CORE/CLD_TXRX/TXRX +TXRX_INC := -I$(WLAN_ROOT)/$(TXRX_DIR) + +TXRX_OBJS := $(TXRX_DIR)/ol_txrx.o \ + $(TXRX_DIR)/ol_cfg.o \ + $(TXRX_DIR)/ol_rx.o \ + $(TXRX_DIR)/ol_rx_fwd.o \ + $(TXRX_DIR)/ol_txrx.o \ + $(TXRX_DIR)/ol_rx_defrag.o \ + $(TXRX_DIR)/ol_tx_desc.o \ + $(TXRX_DIR)/ol_tx_classify.o \ + $(TXRX_DIR)/ol_tx.o \ + $(TXRX_DIR)/ol_rx_reorder_timeout.o \ + $(TXRX_DIR)/ol_rx_reorder.o \ + $(TXRX_DIR)/ol_rx_pn.o \ + $(TXRX_DIR)/ol_tx_queue.o \ + $(TXRX_DIR)/ol_txrx_peer_find.o \ + $(TXRX_DIR)/ol_txrx_event.o \ + $(TXRX_DIR)/ol_txrx_encap.o \ + $(TXRX_DIR)/ol_tx_send.o \ + $(TXRX_DIR)/ol_tx_sched.o + +############ PKTLOG ############ +PKTLOG_DIR := CORE/UTILS/PKTLOG +PKTLOG_INC := -I$(WLAN_ROOT)/$(PKTLOG_DIR)/include + +PKTLOG_OBJS := $(PKTLOG_DIR)/pktlog_ac.o \ + $(PKTLOG_DIR)/pktlog_internal.o \ + $(PKTLOG_DIR)/linux_ac.o + +############ HTT ############ +HTT_DIR := CORE/CLD_TXRX/HTT +HTT_INC := -I$(WLAN_ROOT)/$(HTT_DIR) + +HTT_OBJS := $(HTT_DIR)/htt_tx.o \ + $(HTT_DIR)/htt.o \ + $(HTT_DIR)/htt_t2h.o \ + $(HTT_DIR)/htt_h2t.o \ + $(HTT_DIR)/htt_fw_stats.o \ + $(HTT_DIR)/htt_rx.o + +############## HTC ########## +HTC_DIR := CORE/SERVICES/HTC +HTC_INC := -I$(WLAN_ROOT)/$(HTC_DIR) + +HTC_OBJS := $(HTC_DIR)/htc.o \ + $(HTC_DIR)/htc_send.o \ + $(HTC_DIR)/htc_recv.o \ + $(HTC_DIR)/htc_services.o + +ifneq ($(CONFIG_QCA_WIFI_SDIO), 1) +########### HIF ########### +HIF_DIR := CORE/SERVICES/HIF +ifeq ($(CONFIG_HIF_PCI), 1) +HIF_PCIE_DIR := $(HIF_DIR)/PCIe + +HIF_INC := -I$(WLAN_ROOT)/$(HIF_PCIE_DIR) + +HIF_OBJS := $(HIF_DIR)/ath_procfs.o + +HIF_PCIE_OBJS := $(HIF_PCIE_DIR)/copy_engine.o \ + $(HIF_PCIE_DIR)/hif_pci.o \ + $(HIF_PCIE_DIR)/if_pci.o \ + $(HIF_PCIE_DIR)/regtable.o \ + $(HIF_PCIE_DIR)/mp_dev.o + +HIF_OBJS += $(HIF_PCIE_OBJS) +endif +ifeq ($(CONFIG_HIF_USB), 1) +HIF_USB_DIR := $(HIF_DIR)/USB + +HIF_INC := -I$(WLAN_ROOT)/$(HIF_USB_DIR) + +HIF_OBJS := $(HIF_DIR)/ath_procfs.o + +HIF_USB_OBJS := $(HIF_USB_DIR)/usbdrv.o \ + $(HIF_USB_DIR)/hif_usb.o \ + $(HIF_USB_DIR)/if_usb.o \ + $(HIF_USB_DIR)/regtable.o + +HIF_OBJS += $(HIF_USB_OBJS) +endif +endif + +############ WMA ############ +WMA_DIR := CORE/SERVICES/WMA + +WMA_INC := -I$(WLAN_ROOT)/$(WMA_DIR) + +WMA_OBJS := $(WMA_DIR)/regdomain.o \ + $(WMA_DIR)/wlan_nv.o \ + $(WMA_DIR)/wma.o \ + $(WMA_DIR)/wma_dfs_interface.o \ + $(WMA_DIR)/wma_ocb.o + + +############ WDA ############ +WDA_DIR := CORE/WDA +WDA_INC_DIR := $(WDA_DIR)/inc +WDA_SRC_DIR := $(WDA_DIR)/src + +WDA_INC := -I$(WLAN_ROOT)/$(WDA_INC_DIR) \ + -I$(WLAN_ROOT)/$(WDA_INC_DIR)/legacy \ + -I$(WLAN_ROOT)/$(WDA_SRC_DIR) + +WDA_OBJS := $(WDA_SRC_DIR)/wlan_qct_wda_debug.o \ + $(WDA_SRC_DIR)/wlan_qct_wda_legacy.o + +############ WDI ############ +WDI_DIR := CORE/WDI + +WDI_CP_INC := -I$(WLAN_ROOT)/$(WDI_DIR)/CP/inc/ + +WDI_DP_INC := -I$(WLAN_ROOT)/$(WDI_DIR)/DP/inc/ + +WDI_TRP_INC := -I$(WLAN_ROOT)/$(WDI_DIR)/TRP/CTS/inc/ \ + -I$(WLAN_ROOT)/$(WDI_DIR)/TRP/DTS/inc/ + +WDI_WPAL_INC := -I$(WLAN_ROOT)/$(WDI_DIR)/WPAL/inc + +WDI_INC := $(WDI_CP_INC) \ + $(WDI_DP_INC) \ + $(WDI_TRP_INC) \ + $(WDI_WPAL_INC) + +WCNSS_INC := -I$(WLAN_ROOT)/wcnss/inc + +LINUX_INC := -Iinclude/linux + +INCS := $(HDD_INC) \ + $(EPPING_INC) \ + $(LINUX_INC) \ + $(MAC_INC) \ + $(WCNSS_INC) \ + $(SAP_INC) \ + $(SME_INC) \ + $(SVC_INC) \ + $(SYS_INC) \ + $(TL_INC) \ + $(VOSS_INC) \ + $(WDA_INC) \ + $(WDI_INC) \ + $(DFS_INC) + +INCS += $(WMA_INC) \ + $(COMMON_INC) \ + $(WMI_INC) \ + $(FWLOG_INC) \ + $(ADF_INC) \ + $(TLSHIM_INC) \ + $(TXRX_INC) \ + $(PKTLOG_INC) \ + $(HTT_INC) \ + $(HTC_INC) \ + $(DFS_INC) + +INCS += $(HIF_INC) \ + $(BMI_INC) + +ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) +INCS += $(PKTLOG_INC) +endif + +OBJS := $(HDD_OBJS) \ + $(EPPING_OBJS) \ + $(MAC_OBJS) \ + $(SAP_OBJS) \ + $(SME_OBJS) \ + $(SVC_OBJS) \ + $(SYS_OBJS) \ + $(VOSS_OBJS) \ + $(WDA_OBJS) \ + $(DFS_OBJS) + +OBJS += $(WMA_OBJS) \ + $(TLSHIM_OBJS) \ + $(TXRX_OBJS) \ + $(WMI_OBJS) \ + $(FWLOG_OBJS) \ + $(HTC_OBJS) \ + $(ADF_OBJS) \ + $(DFS_OBJS) + +OBJS += $(HIF_OBJS) \ + $(BMI_OBJS) \ + $(HTT_OBJS) + +ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) +OBJS += $(PKTLOG_OBJS) +endif + +EXTRA_CFLAGS += $(INCS) + +CDEFINES := -DANI_LITTLE_BYTE_ENDIAN \ + -DANI_LITTLE_BIT_ENDIAN \ + -DQC_WLAN_CHIPSET_QCA_CLD \ + -DDOT11F_LITTLE_ENDIAN_HOST \ + -DANI_COMPILER_TYPE_GCC \ + -DANI_OS_TYPE_ANDROID=6 \ + -DANI_LOGDUMP \ + -DWLAN_PERF \ + -DPTT_SOCK_SVC_ENABLE \ + -Wall\ + -Werror\ + -D__linux__ \ + -DHAL_SELF_STA_PER_BSS=1 \ + -DWLAN_FEATURE_VOWIFI_11R \ + -DWLAN_FEATURE_NEIGHBOR_ROAMING \ + -DWLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG \ + -DWLAN_FEATURE_VOWIFI_11R_DEBUG \ + -DFEATURE_WLAN_WAPI \ + -DFEATURE_OEM_DATA_SUPPORT\ + -DSOFTAP_CHANNEL_RANGE \ + -DWLAN_AP_STA_CONCURRENCY \ + -DFEATURE_WLAN_SCAN_PNO \ + -DWLAN_FEATURE_PACKET_FILTERING \ + -DWLAN_FEATURE_VOWIFI \ + -DWLAN_FEATURE_11AC \ + -DWLAN_FEATURE_P2P_DEBUG \ + -DWLAN_ENABLE_AGEIE_ON_SCAN_RESULTS \ + -DWLANTL_DEBUG\ + -DWLAN_NS_OFFLOAD \ + -DWLAN_ACTIVEMODE_OFFLOAD_FEATURE \ + -DWLAN_SOFTAP_VSTA_FEATURE \ + -DWLAN_FEATURE_ROAM_SCAN_OFFLOAD \ + -DWLAN_FEATURE_GTK_OFFLOAD \ + -DWLAN_WAKEUP_EVENTS \ + -DFEATURE_WLAN_RA_FILTERING\ + -DWLAN_KD_READY_NOTIFIER \ + -DWLAN_NL80211_TESTMODE \ + -DFEATURE_WLAN_LPHB \ + -DFEATURE_WLAN_PAL_TIMER_DISABLE \ + -DFEATURE_WLAN_PAL_MEM_DISABLE \ + -DQCA_SUPPORT_TX_THROTTLE \ + -DWMI_INTERFACE_EVENT_LOGGING \ + -DATH_SUPPORT_WAPI \ + -DWLAN_FEATURE_LINK_LAYER_STATS \ + -DWLAN_LOGGING_SOCK_SVC_ENABLE \ + -DFEATURE_WLAN_EXTSCAN \ + -DFEATURE_WLAN_LFR \ + -DFEATURE_WLAN_CH144 \ + -DHTC_CRP_DEBUG + +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) +CDEFINES += -DCONFIG_HL_SUPPORT \ + -DCONFIG_AR6320_SUPPORT \ + -DSDIO_3_0 \ + -DHIF_SDIO \ + -DCONFIG_ATH_PROCFS_DIAG_SUPPORT \ + -DFEATURE_HL_GROUP_CREDIT_FLOW_CONTROL \ + -DHIF_MBOX_SLEEP_WAR \ + -DDEBUG_HL_LOGGING +endif + +ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) +CDEFINES += -DFEATURE_WLAN_FORCE_SAP_SCC +ifneq ($(CONFIG_ARCH_MDMFERMIUM), y) +CDEFINES += -DDHCP_SERVER_OFFLOAD +CDEFINES += -DWLAN_FEATURE_GPIO_LED_FLASHING +CDEFINES += -DWLAN_FEATURE_APFIND +endif +ifneq ($(CONFIG_NON_QC_PLATFORM), y) +CDEFINES += -DDFS_MASTER_OFFLOAD_IND_SUPPORT +endif +endif + +ifeq ($(CONFIG_MDNS_OFFLOAD_SUPPORT), 1) +CDEFINES += -DMDNS_OFFLOAD +endif + +ifeq ($(CONFIG_ARCH_MSM), y) +CDEFINES += -DMSM_PLATFORM +endif + +ifeq ($(CONFIG_MOBILE_ROUTER), y) +CDEFINES += -DMDM_PLATFORM +endif + +CDEFINES += -DOSIF_NEED_RX_PEER_ID \ + -DQCA_SUPPORT_TXRX_LOCAL_PEER_ID +ifeq ($(CONFIG_ROME_IF),pci) +ifneq ($(CONFIG_MOBILE_ROUTER),y) +CDEFINES += -DQCA_LL_TX_FLOW_CT +endif +CDEFINES += -DQCA_SUPPORT_TXRX_VDEV_PAUSE_LL \ + -DQCA_SUPPORT_TXRX_VDEV_LL_TXQ +endif + +ifneq ($(CONFIG_QCA_CLD_WLAN),) +CDEFINES += -DWCN_PRONTO +CDEFINES += -DWCN_PRONTO_V1 +endif + +CDEFINES += -DTRACE_RECORD \ + -DLIM_TRACE_RECORD \ + -DSME_TRACE_RECORD \ + -DHDD_TRACE_RECORD + +ifeq ($(BUILD_DEBUG_VERSION),1) +CDEFINES += -DWLAN_DEBUG \ + -DPE_DEBUG_LOGW \ + -DPE_DEBUG_LOGE \ + -DDEBUG +endif + +ifeq ($(CONFIG_SLUB_DEBUG_ON),y) +CDEFINES += -DTIMER_MANAGER +CDEFINES += -DMEMORY_DEBUG +endif + +ifeq ($(HAVE_CFG80211),1) +CDEFINES += -DWLAN_FEATURE_P2P +CDEFINES += -DWLAN_FEATURE_WFD +ifeq ($(CONFIG_QCOM_VOWIFI_11R),y) +CDEFINES += -DKERNEL_SUPPORT_11R_CFG80211 +CDEFINES += -DUSE_80211_WMMTSPEC_FOR_RIC +endif +endif + +ifeq ($(CONFIG_QCOM_ESE),y) +CDEFINES += -DFEATURE_WLAN_ESE +CDEFINES += -DQCA_COMPUTE_TX_DELAY +CDEFINES += -DQCA_COMPUTE_TX_DELAY_PER_TID +ifeq ($(CONFIG_QCOM_ESE_UPLOAD),y) +CDEFINES += -DFEATURE_WLAN_ESE_UPLOAD +endif +endif + +#normally, TDLS negative behavior is not needed +ifeq ($(CONFIG_QCOM_TDLS),y) +CDEFINES += -DFEATURE_WLAN_TDLS +CDEFINES += -DCONFIG_TDLS_IMPLICIT +endif + +ifeq ($(CONFIG_QCACLD_WLAN_LFR3),y) +CDEFINES += -DWLAN_FEATURE_ROAM_OFFLOAD +endif + +ifeq ($(CONFIG_PRIMA_WLAN_OKC),y) +CDEFINES += -DFEATURE_WLAN_OKC +endif + +ifeq ($(CONFIG_PRIMA_WLAN_11AC_HIGH_TP),y) +CDEFINES += -DWLAN_FEATURE_11AC_HIGH_TP +endif + +ifeq ($(BUILD_DIAG_VERSION),1) +CDEFINES += -DFEATURE_WLAN_DIAG_SUPPORT +CDEFINES += -DFEATURE_WLAN_DIAG_SUPPORT_CSR +CDEFINES += -DFEATURE_WLAN_DIAG_SUPPORT_LIM +ifeq ($(CONFIG_HIF_PCI), 1) +CDEFINES += -DCONFIG_ATH_PROCFS_DIAG_SUPPORT +endif +endif + +ifeq ($(CONFIG_HIF_USB), 1) +CDEFINES += -DCONFIG_ATH_PROCFS_DIAG_SUPPORT +CDEFINES += -DQCA_SUPPORT_OL_RX_REORDER_TIMEOUT +CDEFINES += -DCONFIG_ATH_PCIE_MAX_PERF=0 -DCONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD=0 -DCONFIG_DISABLE_CDC_MAX_PERF_WAR=0 +CDEFINES += -DQCA_TX_HTT2_SUPPORT +CDEFINES += -DCONFIG_HDD_INIT_WITH_RTNL_LOCK +ifeq ($(CONFIG_HIF_USB_TASKLET), 1) +CDEFINES += -DHIF_USB_TASKLET +endif +endif + +ifneq ($(TARGET_BUILD_VARIANT),user) +CDEFINES += -DDEBUG_RX_RING_BUFFER +endif + +# enable the MAC Address auto-generation feature +CDEFINES += -DWLAN_AUTOGEN_MACADDR_FEATURE + +ifeq ($(CONFIG_WLAN_FEATURE_11W),y) +CDEFINES += -DWLAN_FEATURE_11W +endif + +ifeq ($(CONFIG_QCOM_LTE_COEX),y) +CDEFINES += -DFEATURE_WLAN_CH_AVOID +endif + +ifeq ($(CONFIG_WLAN_FEATURE_LPSS),y) +CDEFINES += -DWLAN_FEATURE_LPSS +endif + +ifeq ($(PANIC_ON_BUG),1) +CDEFINES += -DPANIC_ON_BUG +endif + +ifeq ($(RE_ENABLE_WIFI_ON_WDI_TIMEOUT),1) +CDEFINES += -DWDI_RE_ENABLE_WIFI_ON_WDI_TIMEOUT +endif + +ifeq ($(WLAN_OPEN_SOURCE), 1) +CDEFINES += -DWLAN_OPEN_SOURCE +endif + +ifeq ($(CONFIG_FEATURE_STATS_EXT), 1) +CDEFINES += -DWLAN_FEATURE_STATS_EXT +endif + +ifeq ($(CONFIG_WLAN_FEATURE_NAN),y) +CDEFINES += -DWLAN_FEATURE_NAN +endif + +ifeq ($(CONFIG_QCA_IBSS_SUPPORT), 1) +CDEFINES += -DQCA_IBSS_SUPPORT +endif + +#Enable the OS specific ADF abstraction +ifeq ($(CONFIG_ADF_SUPPORT), 1) +CDEFINES += -DADF_SUPPORT +endif + +#Enable OL debug and wmi unified functions +ifeq ($(CONFIG_ATH_PERF_PWR_OFFLOAD), 1) +CDEFINES += -DATH_PERF_PWR_OFFLOAD +endif + +#Disable packet log +ifeq ($(CONFIG_REMOVE_PKT_LOG), 1) +CDEFINES += -DREMOVE_PKT_LOG +endif + +#Enable 11AC TX +ifeq ($(CONFIG_ATH_11AC_TXCOMPACT), 1) +CDEFINES += -DATH_11AC_TXCOMPACT +endif + +#Enable per vdev Tx desc pool +ifeq ($(CONFIG_PER_VDEV_TX_DESC_POOL), 1) +CDEFINES += -DCONFIG_PER_VDEV_TX_DESC_POOL +endif + +#Enable Tx mgmt desc reserve +ifeq ($(CONFIG_TX_DESC_HI_PRIO_RESERVE), 1) +CDEFINES += -DCONFIG_TX_DESC_HI_PRIO_RESERVE +endif + + +#Enable OS specific IRQ abstraction +ifeq ($(CONFIG_ATH_SUPPORT_SHARED_IRQ), 1) +CDEFINES += -DATH_SUPPORT_SHARED_IRQ +endif + +#Enable message based HIF instead of RAW access in BMI +ifeq ($(CONFIG_HIF_MESSAGE_BASED), 1) +CDEFINES += -DHIF_MESSAGE_BASED +endif + +#Enable PCI specific APIS (dma, etc) +ifeq ($(CONFIG_HIF_PCI), 1) +CDEFINES += -DHIF_PCI +endif + +#Enable USB specific APIS +ifeq ($(CONFIG_HIF_USB), 1) +CDEFINES += -DHIF_USB +CDEFINES += -DCONFIG_HL_SUPPORT +endif + +#Enable FW logs through ini +CDEFINES += -DCONFIG_FW_LOGS_BASED_ON_INI + +#Enable pci read/write config functions +ifeq ($(CONFIG_ATH_PCI), 1) +CDEFINES += -DATH_PCI +endif + +#Enable power management suspend/resume functionality +ifeq ($(CONFIG_ATH_BUS_PM), 1) +CDEFINES += -DATH_BUS_PM +endif + +#Enable dword alignment for IP header +ifeq ($(CONFIG_IP_HDR_ALIGNMENT), 1) +CDEFINES += -DPERE_IP_HDR_ALIGNMENT_WAR +endif + +#Enable FLOWMAC module support +ifeq ($(CONFIG_ATH_SUPPORT_FLOWMAC_MODULE), 1) +CDEFINES += -DATH_SUPPORT_FLOWMAC_MODULE +endif + +#Enable spectral support +ifeq ($(CONFIG_ATH_SUPPORT_SPECTRAL), 1) +CDEFINES += -DATH_SUPPORT_SPECTRAL +endif + +#Enable WDI Event support +ifeq ($(CONFIG_WDI_EVENT_ENABLE), 1) +CDEFINES += -DWDI_EVENT_ENABLE +endif + +#Endianess selection +ifeq ($(CONFIG_LITTLE_ENDIAN), 1) +AH_LITTLE_ENDIAN=1234 +CDEFINES += -DAH_BYTE_ORDER=$(AH_LITTLE_ENDIAN) +else +AH_BIG_ENDIAN=4321 +CDEFINES += -DAH_BYTE_ORDER=$(AH_BIG_ENDIAN) +CDEFINES += -DBIG_ENDIAN_HOST +endif + +#Enable TX reclaim support +ifeq ($(CONFIG_TX_CREDIT_RECLAIM_SUPPORT), 1) +CDEFINES += -DTX_CREDIT_RECLAIM_SUPPORT +endif + +#Enable FTM support +ifeq ($(CONFIG_QCA_WIFI_FTM), 1) +CDEFINES += -DQCA_WIFI_FTM +endif + +#Enable Checksum Offload support +ifeq ($(CONFIG_CHECKSUM_OFFLOAD), 1) +CDEFINES += -DCHECKSUM_OFFLOAD +endif + +#Enable Checksum Offload support +ifeq ($(CONFIG_IPA_OFFLOAD), 1) +CDEFINES += -DIPA_OFFLOAD -DHDD_IPA_USE_IPA_RM_TIMER +endif + +ifneq ($(CONFIG_ARCH_MDM9630), y) +ifeq ($(CONFIG_IPA_UC_OFFLOAD), 1) +CDEFINES += -DIPA_UC_OFFLOAD +ifeq ($(CONFIG_ARCH_MDM9640), y) +CDEFINES += -DIPA_UC_STA_OFFLOAD +CDEFINES += -DINTRA_BSS_FWD_OFFLOAD +else +CDEFINES += -DQCA_CONFIG_SMP +endif +endif +endif + +#Enable GTK Offload +ifeq ($(CONFIG_GTK_OFFLOAD), 1) +CDEFINES += -DWLAN_FEATURE_GTK_OFFLOAD +CDEFINES += -DIGTK_OFFLOAD +endif + +#Enable GTK Offload +ifeq ($(CONFIG_EXT_WOW), 1) +CDEFINES += -DWLAN_FEATURE_EXTWOW_SUPPORT +endif + +#Mark it as SMP Kernel +ifeq ($(CONFIG_SMP),y) +CDEFINES += -DQCA_CONFIG_SMP +endif + +#rps feature +ifeq ($(CONFIG_RPS),y) +CDEFINES += -DQCA_FEATURE_RPS +endif + +#Enable Channel Matrix restriction for all targets +CDEFINES += -DWLAN_ENABLE_CHNL_MATRIX_RESTRICTION + +#features specific to mobile router use case +ifeq ($(CONFIG_MOBILE_ROUTER), y) + +#enable MCC TO SCC switch +CDEFINES += -DFEATURE_WLAN_MCC_TO_SCC_SWITCH + +ifneq ($(CONFIG_ARCH_MDMFERMIUM), y) +#enable wlan auto shutdown feature +CDEFINES += -DFEATURE_WLAN_AUTO_SHUTDOWN + +#Enable 4address scheme +CDEFINES += -DFEATURE_WLAN_STA_4ADDR_SCHEME + +#MDM Device only, to optimize MSM skb cb memory usage +CDEFINES += -DQCA_MDM_DEVICE +endif + +#enable for MBSSID +CDEFINES += -DWLAN_FEATURE_MBSSID + +#enable AP-AP ACS Optimization +CDEFINES += -DFEATURE_WLAN_AP_AP_ACS_OPTIMIZE + +#Green AP feature +CDEFINES += -DFEATURE_GREEN_AP + +#Disable STA-AP Mode DFS support +CDEFINES += -DFEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + +#Enable OBSS feature +CDEFINES += -DQCA_HT_2040_COEX + +#Disable HT40 in 2.4GHZ STA mode +CDEFINES += -DQCA_HT_20_24G_STA_ONLY + +else #CONFIG_MOBILE_ROUTER + +#Open P2P device interface only for non-Mobile router use cases +CDEFINES += -DWLAN_OPEN_P2P_INTERFACE + +#Enable 2.4 GHz social channels in 5 GHz only mode for p2p usage +CDEFINES += -DWLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY + +endif #CONFIG_MOBILE_ROUTER + +#Enable RX Full re-order OL feature only "LL and NON-MDM9630 platform" +ifneq ($(CONFIG_ARCH_MDM9630), y) +ifeq ($(CONFIG_HIF_PCI), 1) +CDEFINES += -DWLAN_FEATURE_RX_FULL_REORDER_OL +endif +endif + +#Enable Signed firmware support for split binary format +ifeq ($(CONFIG_QCA_SIGNED_SPLIT_BINARY_SUPPORT), 1) +CDEFINES += -DQCA_SIGNED_SPLIT_BINARY_SUPPORT +endif + +#Enable single firmware binary format +ifeq ($(CONFIG_QCA_SINGLE_BINARY_SUPPORT), 1) +CDEFINES += -DQCA_SINGLE_BINARY_SUPPORT +endif + +#Enable collecting target RAM dump after kernel panic +ifeq ($(CONFIG_TARGET_RAMDUMP_AFTER_KERNEL_PANIC), 1) +CDEFINES += -DTARGET_RAMDUMP_AFTER_KERNEL_PANIC +endif + +#Enable/disable secure firmware feature +ifeq ($(CONFIG_CNSS_SECURE_FW), y) +CDEFINES += -DFEATURE_SECURE_FIRMWARE +endif + +#Enable/disable FW hash check for secure firmware feature +ifeq ($(CONFIG_CLD_DEBUG), y) +CDEFINES += -DFEATURE_FW_HASH_CHECK +endif + +ifeq ($(CONFIG_ATH_PCIE_ACCESS_DEBUG), 1) +CDEFINES += -DCONFIG_ATH_PCIE_ACCESS_DEBUG +endif + +#Flag to enable/disable WLAN D0-WOW +ifeq ($(CONFIG_PCI_MSM), y) +CDEFINES += -DFEATURE_WLAN_D0WOW +endif + +# Flag to enable bus auto suspend +ifeq ($(CONFIG_BUS_AUTO_SUSPEND), y) +CDEFINES += -DFEATURE_RUNTIME_PM +endif + +# Some kernel include files are being moved. Check to see if +# the old version of the files are present + +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/mach-msm/include/mach/msm_smd.h),) +CDEFINES += -DEXISTS_MSM_SMD +endif + +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/mach-msm/include/mach/msm_smsm.h),) +CDEFINES += -DEXISTS_MSM_SMSM +endif + +# Enable feature support fo Linux version QCMBR +ifeq ($(CONFIG_LINUX_QCMBR),y) +CDEFINES += -DLINUX_QCMBR +endif + +# Enable feature Software AP Authentication Offload +ifeq ($(SAP_AUTH_OFFLOAD),1) +CDEFINES += -DSAP_AUTH_OFFLOAD +endif + +# Enable featue sync tsf between multi devices +ifeq ($(CONFIG_WLAN_SYNC_TSF),y) +CDEFINES += -DWLAN_FEATURE_TSF +endif + +# Enable target dump for non-qualcomm platform +ifeq ($(CONFIG_NON_QC_PLATFORM), y) +CDEFINES += -DCONFIG_NON_QC_PLATFORM +ifeq ($(CONFIG_CLD_HL_SDIO_CORE), y) +CDEFINES += -DTARGET_DUMP_FOR_NON_QC_PLATFORM +endif +endif + +ifeq ($(CONFIG_ARCH_MDM9640), y) +CDEFINES += -DFEATURE_AP_MCC_CH_AVOIDANCE +endif + +ifdef CPTCFG_QCA_CLD_WLAN +CDEFINES += -DWITH_BACKPORTS +#Enable OBSS feature +CDEFINES += -DQCA_HT_2040_COEX +endif + +ifdef CPTCFG_QCA_CLD_WLAN +CDEFINES += -DTARGET_DUMP_FOR_9X15_PLATFORM +endif + +ifeq ($(CONFIG_STATICALLY_ADD_11P_CHANNELS),y) +CDEFINES += -DFEATURE_STATICALLY_ADD_11P_CHANNELS +endif + +ifeq ($(CONFIG_WLAN_FEATURE_MEMDUMP),y) +CDEFINES += -DWLAN_FEATURE_MEMDUMP +endif + +ifeq ($(CONFIG_WLAN_OFFLOAD_PACKETS),y) +CDEFINES += -DWLAN_FEATURE_OFFLOAD_PACKETS +endif + + +ifeq ($(CONFIG_WLAN_UDP_RESPONSE_OFFLOAD),y) +CDEFINES += -DWLAN_FEATURE_UDP_RESPONSE_OFFLOAD +endif + +ifeq ($(CONFIG_WLAN_FEATURE_RX_WAKELOCK), y) +CDEFINES += -DWLAN_FEATURE_HOLD_RX_WAKELOCK +endif + + +KBUILD_CPPFLAGS += $(CDEFINES) + +# Currently, for versions of gcc which support it, the kernel Makefile +# is disabling the maybe-uninitialized warning. Re-enable it for the +# WLAN driver. Note that we must use EXTRA_CFLAGS here so that it +# will override the kernel settings. +ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y) +EXTRA_CFLAGS += -Wmaybe-uninitialized +endif + +# Module information used by KBuild framework +obj-$(CONFIG_QCA_CLD_WLAN) += $(MODNAME).o +$(MODNAME)-y := $(OBJS) diff --git a/drivers/staging/qcacld-2.0/Kconfig b/drivers/staging/qcacld-2.0/Kconfig new file mode 100644 index 000000000000..2adf384f1b2a --- /dev/null +++ b/drivers/staging/qcacld-2.0/Kconfig @@ -0,0 +1,72 @@ +comment "Qualcomm Atheros CLD WLAN module" + +config QCA_CLD_WLAN + + tristate "Qualcomm Atheros CLD WLAN module" + default n + help + Add support for the Qualcomm Atheros CLD WLAN module + +if QCA_CLD_WLAN != n + +config QCACLD_WLAN_LFR3 + bool "Enable the WLAN Legacy Fast Roaming feature Version 3" + default n + +config PRIMA_WLAN_OKC + bool "Enable the Prima WLAN Opportunistic Key Caching feature" + default n + +config PRIMA_WLAN_11AC_HIGH_TP + bool "Enable the Prima WLAN 802.11ac High Throughput option (depends upon kernel support)" + default n + +config WLAN_FEATURE_11W + bool "Enable the WLAN 802.11w Protected Management Frames feature" + default n + +config WLAN_FEATURE_LPSS + bool "Enable the WLAN LPSS feature" + default n + +config QCOM_VOWIFI_11R + bool "Enable Fast Transition (11r) feature" + default n + +config WLAN_FEATURE_NAN + bool "Enable NAN feature" + default n + +config QCOM_TDLS + bool "Enable TDLS feature" + default n + +config QCOM_LTE_COEX + bool "Enable QCOM LTE Coex feature" + default n + +config WLAN_SYNC_TSF + bool "Enable QCOM sync multi devices tsf feature" + default n + +config WLAN_FEATURE_MEMDUMP + bool "Enable MEMDUMP feature" + default n + +config WLAN_OFFLOAD_PACKETS + bool "Enable offload packets feature" + default n + +config QCA_WIFI_AUTOMOTIVE_CONC + bool "Enable 3 port concurrency feature" + default n + +config WLAN_UDP_RESPONSE_OFFLOAD + bool "Enable UDP response offload feature" + default n + +config WLAN_FEATURE_RX_WAKELOCK + bool "Enable RX wake lock feature" + default n + +endif # QCA_CLD_WLAN diff --git a/drivers/staging/qcacld-2.0/Makefile b/drivers/staging/qcacld-2.0/Makefile new file mode 100644 index 000000000000..c05b00f26c57 --- /dev/null +++ b/drivers/staging/qcacld-2.0/Makefile @@ -0,0 +1,28 @@ +KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build + +KBUILD_OPTIONS := WLAN_ROOT=$(PWD) +KBUILD_OPTIONS += MODNAME=wlan + +# Determine if the driver license is Open source or proprietary +# This is determined under the assumption that LICENSE doesn't change. +# Please change here if driver license text changes. +LICENSE_FILE ?= $(PWD)/$(WLAN_ROOT)/CORE/HDD/src/wlan_hdd_main.c +WLAN_OPEN_SOURCE = $(shell if grep -q "MODULE_LICENSE(\"Dual BSD/GPL\")" \ + $(LICENSE_FILE); then echo 1; else echo 0; fi) + +#By default build for CLD +WLAN_SELECT := CONFIG_QCA_CLD_WLAN=m +KBUILD_OPTIONS += CONFIG_QCA_WIFI_ISOC=0 +KBUILD_OPTIONS += CONFIG_QCA_WIFI_2_0=1 +KBUILD_OPTIONS += $(WLAN_SELECT) +KBUILD_OPTIONS += WLAN_OPEN_SOURCE=$(WLAN_OPEN_SOURCE) +KBUILD_OPTIONS += $(KBUILD_EXTRA) # Extra config if any + +all: + $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) + +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install + +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean diff --git a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_cfg.dat b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_cfg.dat new file mode 100755 index 0000000000000000000000000000000000000000..08aaf2bfd38bca3f47114ad603e133c2348b9333 GIT binary patch literal 10234 zcmeI033yc1701uZyktTW=1vrGmoXxVfV{92kSaW^vWQFEz!jrJL<~48C@Sg$gGG%v zRVbiUK*fFSYOPDGXi;lxty>kBx|J#_rD!c5pY(U$ceq8wF+{EadGB!|0_?2auJ2a1!G zQjjvKSgKUq8c(|WyUHFg0>(gLjq!^hUTfT9=l~^9nlVxa9U%cGZ6pchuti|}EwP=_ z#@z}!!`843YzyO4F{w|-WV?(f+h;ug%v7Z`q$_0(?2z_kZcyp(m?@Q=GDf;UN=#~J zF>Xa*++Cn6^w=hUfT1&DG7e_JP0*k5kI#t9sF`sYkTLE+*aHT^_gUMXuve4jE0Cv%8BBdhlMx?= zHW_zs>6BfXounb;;)lk&HUc$kwuMhSR)^#ZJ90rHO=qAq}!#qbY|B-MM9NlF6 zW9S>vQ0X6=IY`C^o_}20xV34|KYp?2pMZU0$^d`d;vs%rx`%&adWb(B|4ECx_!D3S zeILNd#7(R={wYuolVCEO3TZeEPKPsK3QUDF;VhU2XTv#gE=-5>;C#3M0+<0a;X-JD zS#S~j5N5;0%zp`7nl^qT_A;0Qm#00+)ENIqa0Ofmb73C*80Oa)SpW;+D!3Yc0@uK` zY0q5*i(v^|2iKGHhP3fzR@`42823iFNsQbK;|t?*3-+XcbH+)8_5hq&B^ zJ*6Zrw+s7I8u#xY$DME&+zt1@PhnDH-2WN&=kN>oCHxBRg+!H$)?kyEr$#YM6I=->4 zc@!-=Wfuw{2r*^IZ06=(AeUIDI7RGhFLxw+CC)r|Y&w z=jCxN8#ZJ;cF7uNOYRu;NBgy{$E*8ei_WXLbq}>@dOJqv*LuBmL=K*(Ro-I5H6U8g zH^3gI#wwq(2&Ie;#TNB#s`zwjxSi8lJ!ajnl4dZiV(h$X_1xG!4yfxOd%m<8mg4NW zwE3+&YHeS#*~yS_PIpaB%iPg;tp}iM+$jgUKHM$E=5KK{SM>NbhaRt#+IO=#_1UFkmtwU}%J99}v$?Kq zjkmPQgEQLBt*0L1O^8$T>w8xF^*EyM=YV!}oPJ*fAM_7>`kdA86dkWIdak0ec2Bh5 z*0rBz7^ha}3iq52Js*ntEzx+*VRNYsW7KM~W5RYezvk8wT~lsdU+>Yi*?v8?s6U*K z+%4~C4Wy`FbL1B7)*Jyu^Qd3fs_!1P_IT~QZCN|FwK~XWtj!f#l4*Zi<87SI7p;f; z7LLnqpv`an8XLey|Hit#Ml?p>^Y&dIo+BLtHK6^v58Ad?>-ru@Vb?dK*G_c(c1|6i zi;ma#y!v(j?7LjQch$!ya=7PxusY8L*l3QroVI=k?z2xtg-GANC7ew+R^SxJi*!k( z(j(K1Iun|K>@1y2-GXANkgnToQC43&qFQ8E`nu6qDe=OXGeCBe>Yi0y{XGZvt0*mU z3VL<#7B6&TWhEVoC)6c6PMeahpWP5lUpRkW!$dwR zVb7hk3N@EVy zn3xdSDdEKAKvy`85$&|8gVu zcM+2vE6dB}RQ6Wm<1!v+Jlts^KAk83X?gOWo+tkqdGb%mlYc6Hz3PT=0mZrup{1o< z&Llr)eJtx|oz3eXTP|l2jo)MaEWUaDUb#$*<~JMn=j`VE8+6|y{&TYH|4jaKv+K{v zZ{$4D>mgk~p)Qy{ZHhF`Zb-|;;uJWJ<2o^?$SHJ+ow!rtba2X?QYYbbbhFIQLs-0fa&*>urr9VGr28l0&Wde`RG$(eNOyNeIF0-Yif#QWn^1iya`(wfnjjd5JtL;1zfkUWYf} zEq;f+CmqX5xxq~0j#sn)RKxo>y$kfzh8kWE^gEL(NTSQ}vWlfl%7wz3&uVy~eph4s zR{CA7aa-wknTUSJ@9r)6?cWKzRXQP^VQbh1wuS9rd@8Hqq2I|4nbsQKj_J}+!`lfB zFVyeIjeeJ^KquHGK)-{Ce&<$kMP>CnBOA3lPkNz6d4Z8?=E!Pyo~U-0)$Ba!&l(57 zz#t)e5SLHG8^n04;i1{NXm;*iFc^lgHXnvIdFXeQ^5M+5>`gt??3#@1+hp8f*x`U? z=Z_@Uei_dlh20+xz>i+%9>luP>*QcK1P;Z2820eMq}GzR1Whgl{b7GN0j9wmxB>2i zr{Nt~4_lzwRl#5w&H4_*j$vI#knc!1iusOi^890%=UC<+3&%lilktzIZz3Ar321oZ z0uQauxF@1jg<2hU6&l?HG`y41@Ft?+oq~o}kA61^KBX@?b$~yaxNl6at2X{6a49sx zWzekG`I$6&9c#G)u7tU1Pv+Gm(CZTDbqRj~EQG57z0S|-bqTq)CLxPpF)V@W;Cl7} zz0O?%~qA@oY8u#ph!bsS6b}c zUx%(|b7@{ZX8kbLuTe!yzIEyO(eG$2f&O8D`dY;oi}<-d+RqU1dTi0{bX0e;tW@mn9JBQ^@_$7PnHKxOKEtcFg(KzkX`)zY+-wu4+=e&KZZvQBI z&seLO>~+@GUf902X3UMZ*QK>~j9#8~wy_DT`ScNL^$4|JRqxa3>@nE<--O<$bJZX( z=;Te$Igk6Y&o&jSuUM@qQg&DO@L)pMr%Z*3UI zpHQ!|wJNe_sD9FK@s8=c500 zE^V0k-PQm{b3Kni;;bnDKhpvunp{K+L^|_tey2A_VXPo literal 0 HcmV?d00001 diff --git a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini new file mode 100755 index 000000000000..a128d61d2313 --- /dev/null +++ b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini @@ -0,0 +1,665 @@ +# This file allows user to override the factory + +# defaults for the WLAN Driver + + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan +gEnableIdleScan=0 + + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + + +# Enable BMPS or not +gEnableBmps=1 + +# Enable suspend or not + +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter + +gEnableSuspend=3 + +# Phy Mode (auto, b, g, n, etc) +# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac +# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only +# 7 = 11b only 8 = 11ac only. +gDot11Mode=0 + + +# CSR Roaming Enable(1) Disable(0) + +gRoamingTime=0 + + +# Assigned MAC Addresses - This will be used until NV items are in place + +# Each byte of MAC address is represented in Hex format as XX + +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD + +Intf3MacAddress=000AF58989FC + + +# UAPSD service interval for VO,VI, BE, BK traffic + +InfraUapsdVoSrvIntv=0 + +InfraUapsdViSrvIntv=0 + +InfraUapsdBeSrvIntv=0 + +InfraUapsdBkSrvIntv=0 + +# Flag to allow STA send AddTspec even when ACM is Off +gAddTSWhenACMIsOff=1 + +# Make 1x1 the default antenna configuration + +gNumRxAnt=1 + + +# Beacon filtering frequency (unit in beacon intervals) + +gNthBeaconFilter=50 + + +# Enable WAPI or not + +# WAPIIsEnabled=0 + + +# Flags to filter Mcast abd Bcast RX packets. + +# Value 0: No filtering, 1: Filter all Multicast. + +# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast + +McastBcastFilter=3 + + +#Flag to enable HostARPOffload feature or not + +hostArpOffload=1 + +#Flag to enable TCPChkSumOffld feature or not + +gEnableTCPChkSumOffld=1 + +#Flag to enable HostNSOffload feature or not + +hostNSOffload=1 + +#Flag to enable IPChkSumOffld feature or not + +gEnableIPChecksumOffload=1 + +#SoftAP Related Parameters + +# AP MAc addr + +gAPMacAddr=000AF589dcab + + +# 802.11n Protection flag + +gEnableApProt=1 + + +#Enable OBSS protection + +gEnableApOBSSProt=1 + + +#Enable/Disable UAPSD for SoftAP + +gEnableApUapsd=1 + + +# Fixed Rate + +gFixedRate=0 + + +# Maximum Tx power + +# gTxPowerCap=30 + + +# Fragmentation Threshold + +# gFragmentationThreshold=2346 + + +# RTS threshold + +RTSThreshold=1048576 + + +# Intra-BSS forward + +gDisableIntraBssFwd=0 + + +# WMM Enable/Disable + +WmmIsEnabled=0 + + +# 802.11d support + +g11dSupportEnabled=0 + +# 802.11h support + +g11hSupportEnabled=1 + +# DFS Master Capability +gEnableDFSMasterCap=1 + +# ESE Support and fast transition +EseEnabled=1 +ImplicitQosIsEnabled=0 +gNeighborScanTimerPeriod=200 + +gNeighborLookupThreshold=76 +gNeighborReassocThreshold=81 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 +gMaxNeighborReqTries=3 + +# Legacy (non-ESE, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1 +# To disable, set FastRoamEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=3 + +# If the RSSI of any available candidate is better than currently associated +# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without +# registering for reassoc threshold). +# NOTE: Value of 0 means that we would register for reassoc threshold. +gImmediateRoamRssiDiff=10 + +# To enable, set gRoamIntraBand=1 (Roaming within band) +# To disable, set gRoamIntraBand=0 (Roaming across band) +gRoamIntraBand=0 + +# SAP Country code + +# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. + +# Example + +# US Indoor, USI + +# Korea Outdoor, KRO + +# Japan without optional byte, JP + +# France without optional byte, FR + +#gAPCntryCode=USI + + +#Short Guard Interval Enable/disable + +gShortGI20Mhz=1 + +gShortGI40Mhz=1 + + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled + +gAPAutoShutOff=0 + +#Auto Shutdown wlan : Value in Seconds. 0 means disabled. Max 1 day = 86400 sec +gWlanAutoShutdown = 0 + + +# Listen Energy Detect Mode Configuration + +# Valid values 0-128 + +# 128 means disable Energy Detect feature + +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. + +# 10-128 are reserved. + +# The EDET threshold mapping is as follows in 3dB step: + +# 0 = -60 dBm + +# 1 = -63 dBm + +# 2 = -66 dBm + +# ... + +# 7 = -81 dBm + +# 8 = -84 dBm + +# 9 = -87 dBm + +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: + +# + +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. + +# + +gEnablePhyAgcListenMode=128 + + +#Preferred band (both or 2.4 only or 5 only) + +BandCapability=0 + + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) + +enableBeaconEarlyTermination=0 + +beaconEarlyTerminationWakeInterval=3 + + +#Channel Bonding +gChannelBondingMode5GHz=1 + + +#Enable Keep alive with non-zero period value + +gStaKeepAlivePeriod = 30 + +#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). +#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) +#For both active and power save clients. + +#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. +#If doesn't honor for 5 seconds then DUT remove client. + +#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on +#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. +#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. + +#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period +#where we send NULL frame. + +gApLinkMonitorPeriod = 30 + +gGoLinkMonitorPeriod = 10 + +#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. +#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. + + +gGoKeepAlivePeriod = 3 + +gApKeepAlivePeriod = 10 + + +#If set will start with active scan after driver load, otherwise will start with + +#passive scan to find out the domain + +gEnableBypass11d=1 + + +#If set to 0, will not scan DFS channels + +gEnableDFSChnlScan=1 + +# Enable DFS channel roam +# 0: DISABLE, 1: ENABLED_NORMAL, 2: ENABLED_ACTIVE +gAllowDFSChannelRoam=1 + +gVhtChannelWidth=2 + + +# Enable Automatic Tx Power control + +gEnableAutomaticTxPowerControl=1 + +# 0 for OLPC 1 for CLPC and SCPC +gEnableCloseLoop=1 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +# VHT Tx/Rx MCS values +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS=2 +gVhtTxMCS=2 + +# VHT Tx/Rx MCS values for 2x2 +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS2x2=2 +gVhtTxMCS2x2=2 + + +# Valid chain mask values +# 01 - enables chain0 +# 02 - enables chain1 +# 03 - enables both chain 0 and chain 1 +# if set to 0 or 1 then all vdevs comes up in 1x1 mode in that band. +gChainMask_2g=3 +gChainMask_5g=3 + +# NSS cfg bit definition. +# STA BIT[0:1] +# SAP BIT[2:3] +# P2P_GO BIT[4:5] +# P2P_CLIENT BIT[6:7] +# IBSS BIT[8:9] +# TDLS BIT[10:11] +# P2P_DEVICE BIT[12:13] +# OCB BIT[14:15] +# Valid values are 1 or 2 for each two bit configuration. +# if 2-bit value is set to 1 then the corresponidng vdev comes up in 1x1 mode +# in the band, if set to 2 then that vdev comes up in 2x2 mode in that band. +gVdevTypeNss_2g=43690 +gVdevTypeNss_5g=43690 + +# Scan Timing Parameters +# gPassiveMaxChannelTime=110 +# gPassiveMinChannelTime=60 +gActiveMaxChannelTime=80 +gActiveMinChannelTime=40 + +#If set to 0, MCC is not allowed. +gEnableMCCMode=1 + +# MCC to SCC Switch mode: 0-Disable 1-Enable 2-Force SCC if same band +gWlanMccToSccSwitchMode = 0 + +# 1=enable STBC; 0=disable STBC +gEnableRXSTBC=1 + +# 1=enable tx STBC; 0=disable +gEnableTXSTBC=1 + +# 1=enable rx LDPC; 0=disable +gEnableRXLDPC=1 + +# Enable Tx beamforming in VHT20MHz +# Valid values are 0,1. If commented out, the default value is 0. +# 0=disable, 1=enable +gEnableTxBFin20MHz=1 + +# Enable Active mode offload +gEnableActiveModeOffload=1 + +#Enable Scan Results Aging based on timer +#Timer value is in seconds +#If Set to 0 it will not enable the feature +gScanAgingTime=0 + +#Enable Scan Results Aging based on number of scans +gScanResultAgeCount=1 + +#Enable Power saving mechanism Based on Android Framework +#If set to 0 Driver internally control the Power saving mechanism +#If set to 1 Android Framwrok control the Power saving mechanism +isAndroidPsEn=0 + +#Enable thermal mitigation +gThermalMitigationEnable=0 + +gEnableFastRoamInConcurrency=1 + +#List of Country codes for which 11ac needs to be disabled +#Each country code must be delimited by comma(,) +gListOfNon11acCountryCode=RU,UA,ZA + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + +#Scan offload +gEnableDirectedScanOffload=1 + +#FlexConnect Power Factor +#Default is set to 0 (disable) +gFlexConnectPowerFactor=0 + +#Disable split scan, the FW will take care of it +gNumChanCombinedConc=60 + +#Enable Power Save offload +gEnablePowerSaveOffload=2 + +#Enable firmware uart print +gEnablefwprint=0 + +#Enable firmware log +gEnablefwlog=1 +# Additional firmware log levels +gFwDebugLogLevel=4 +gFwDebugModuleLoglevel=1,0,2,0,4,0,5,0,6,0,7,4,8,0,9,0,11,0,13,0,17,0,18,0,19,0,27,0,29,0,31,0,35,0,36,0,38,0 + +#IPA config +gIPAConfig=0 +gIPADescSize=800 +gIPAPreFilterEnable=1 +gIPARMEnable=1 +gIPAIPv6Enable=1 + +#P2P Listen offload +gEnableP2pListenOffload=1 + +# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) +gVhtMpduLen=2 + +# Maximum number of wow filters required +#gMaxWoWFilters=22 + +# WOW Enable/Disable. +# 0 - Disable both magic pattern match and pattern byte match. +# 1 - Enable magic pattern match on all interfaces. +# 2 - Enable pattern byte match on all interfaces. +# 3 - Enable both magic patter and pattern byte match on all interfaces. +# Default value of gEnableWoW is 3. +# gEnableWoW=0 + +# Enable or Disable MCC Adaptive Scheduler at the FW +# 1=Enable (default), 0=Disable +gEnableMCCAdaptiveScheduler=1 + +#Enable or Disable p2p device address administered +isP2pDeviceAddrAdministrated=1 + +# RX packet handling options +# 0: no rx thread, no RPS, for MDM +# 1: RX thread +# 2: RPS +rxhandle=2 + +# Set RPS CPU MAP as 0xe for the 4 RX queues +# This allows use of CPU1-CPU3 but not CPU0 for 4 RX queues +rpsRxQueueCpuMapList=c + +# Set Thermal Power limit +TxPower2g=10 +TxPower5g=10 + +# Remove Overlap channel restriction +gEnableOverLapCh=0 + +#Enable VHT on 2.4Ghz +gEnableVhtFor24GHzBand=1 + +#Enable or Disable 5G early beacon termination +gEnable5gEBT=1 + +#Maximum number of offload peers supported +# gMaxOffloadPeers=2 + +# controlling the following offload patterns +# through ini parameter. Default value is 1 +# to disable set it to zero. ssdp = 0 +# Setup multicast pattern for mDNS 224.0.0.251, +# SSDP 239.255.255.250 and LLMNR 224.0.0.252 + + +ssdp = 0 + +#Enable Memory Deep Sleep +gEnableMemDeepSleep=1 + +# Bus bandwidth threshold values in terms of number of packets +gBusBandwidthHighThreshold=2000 +gBusBandwidthMediumThreshold=500 +gBusBandwidthLowThreshold=150 + +# IPA bandwidth voting +gIPAHighBandwidthMbps=800 +gIPAMediumBandwidthMbps=400 +gIPALowBandwidthMbps=200 + +# Bus bandwidth compute timeout value in ms +gBusBandwidthComputeInterval=100 + +# Regulatory Setting; 0=STRICT; 1=CUSTOM +gRegulatoryChangeCountry=1 +# RA filtering rate limit param, the current value would not +# help if the lifetime in RA is less than 3*60=3min. Then +# we need to change it, though it is uncommon. +# gRAFilterEnable=0 +gRArateLimitInterval=600 + +# Maximum number of concurrent connections +gMaxConcurrentActiveSessions=2 + +# Disable/Enable GreenAP +# 0 to disable, 1 to enable, default: 1 +gEnableGreenAp=1 + +# Radar PRI multiplier +gDFSradarMappingPriMultiplier=4 + +gPNOScanSupport=0 + +# Enable/Disable RX full reorder offload +gReorderOffloadSupported=1 + +# Enable/Disable LPASS support +# 0 to disable, 1 to enable +gEnableLpassSupport=1 + +# Whether userspace country code setting shld have priority +gCountryCodePriority=1 + +# Enable(1)/Disable(0) SIFS burst +gEnableSifsBurst=1 + +# Enable/Disable channel avoidance for SAP in SCC scenario +# 0 - disable +# 1 - enable +gSapSccChanAvoidance=0 + +# Inactivity time (in ms) to end TX Service Period while in IBSS power save mode +gIbssTxSpEndInactivityTime=10 + +# Enable/Disable Roaming Offload Support (a.k.a Key Management Offload) +# 0 to disable, 1 to enable +gRoamOffloadEnabled=0 + +# Enable support for TDLS +# 0 - disable +# 1 - enable +gEnableTDLSSupport=1 + +# Enable support for Implicit Trigger of TDLS. That is, wlan driver shall +# initiate TDLS Discovery towards a peer whenever setup criteria (throughput +# and RSSI) is met and then will initiate teardown when teardown criteria +# (idle packet count and RSSI) is met. +# 0 - disable +# 1 - enable +gEnableTDLSImplicitTrigger=1 + +# Enable TDLS External Control. That is, user space application has to +# first configure a peer MAC in wlan driver towards which TDLS is desired. +# Device will establish TDLS only towards those configured peers whenever +# TDLS criteria (throughput and RSSI threshold) is met and teardown TDLS +# when teardown criteria (idle packet count and RSSI) is met. However, +# device will accept TDLS connection if it is initiated from any other peer, +# even if that peer is not configured. +# 0 - disable +# 1 - enable +# For TDLS External Control, Implicit Trigger must also be enabled. +gTDLSExternalControl=1 + +# Enable support for TDLS off-channel operation +# 0 - disable +# 1 - enable +# TDLS off-channel operation will be invoked when there is only one +# TDLS connection. +gEnableTDLSOffChannel=1 + +IpaUcOffloadEnabled=1 +gIpaUcStaOffload=1 + +gEnableSelfRecovery=1 + +# Enable or Disable Random MAC (Spoofing) +# 1=Enable, 0=Disable (default) +gEnableMacAddrSpoof=0 + +# Enable Auto suspend feature +# When this feature is enabled, it will shutdown the PCIe link +# when inactivity is detected in STA disconnected mode. +# 0 - disable +# 1 - enable +gEnableBusAutoSuspend=0 + +# Enable Runtime PM Feature. +# Enabling this feature will put target wow and shutdown pcie link +# when inactivity is detected in WLAN Driver. +# This feature is inactive when beaconing interfaces are active with +# clients associated. +# 0 - disable +# 1 - enable + +gRuntimePM=1 +# When gRuntimePM is disabled gRuntimeAutoTime won't take effect. +# The Time is in msec. +# 100 is min, 10000 is max, 500 is default. + +gRuntimePMDelay=500 + +# Enable to check FW hash if secure FW feature is enabled. It's for defconfig +# builds only since it will be ignored in performance/release builds. +gEnableFWHashCheck=1 + +# Enable FW to filter out broadcast packets and wakeup host during runtime PM. +# As APPS is awake during runtime PM, if any application needs the broadcast +# packets OEM's can enable this flag. +# FW will filters the broadcast packets and wakeup host to deliver them during +# runtime suspend. +# This flag will take affect when Runtime PM is enabled +gRuntimePmEnableBcastPattern=0 +END + +# Note: Configuration parser would not read anything past the END marker + diff --git a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini new file mode 100644 index 000000000000..0a7422f2c2e7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini @@ -0,0 +1,550 @@ +# This file allows user to override the factory + +# defaults for the WLAN Driver + + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan + +gEnableIdleScan=0 + + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + + +# Enable BMPS or not +gEnableBmps=1 + +# Enable suspend or not + +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter + +gEnableSuspend=3 + + +# Phy Mode (auto, b, g, n, etc) +# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac +# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only +# 7 = 11b only 8 = 11ac only. +gDot11Mode=0 + + +# CSR Roaming Enable(1) Disable(0) + +gRoamingTime=0 + + +# Assigned MAC Addresses - This will be used until NV items are in place + +# Each byte of MAC address is represented in Hex format as XX + +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD + +Intf3MacAddress=000AF58989FC + + +# UAPSD service interval for VO,VI, BE, BK traffic + +InfraUapsdVoSrvIntv=0 + +InfraUapsdViSrvIntv=0 + +InfraUapsdBeSrvIntv=0 + +InfraUapsdBkSrvIntv=0 + +# Flag to allow STA send AddTspec even when ACM is Off +gAddTSWhenACMIsOff=1 + +# Make 1x1 the default antenna configuration + +gNumRxAnt=1 + + +# Beacon filtering frequency (unit in beacon intervals) + +gNthBeaconFilter=50 + + +# Enable WAPI or not + +# WAPIIsEnabled=0 + + +# Flags to filter Mcast abd Bcast RX packets. + +# Value 0: No filtering, 1: Filter all Multicast. + +# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast + +McastBcastFilter=3 + + +#Flag to enable HostARPOffload feature or not + +hostArpOffload=1 + +#Flag to enable TCPChkSumOffld feature or not + +gEnableTCPChkSumOffld=1 + +#Flag to enable HostNSOffload feature or not + +hostNSOffload=1 + +#Flag to enable IPChkSumOffld feature or not + +gEnableIPChecksumOffload=0 + +#SoftAP Related Parameters + +# AP MAc addr + +gAPMacAddr=000AF589dcab + + +# 802.11n Protection flag + +gEnableApProt=1 + + +#Enable OBSS protection + +gEnableApOBSSProt=1 + + +#Enable/Disable UAPSD for SoftAP + +gEnableApUapsd=1 + + +# Fixed Rate + +gFixedRate=0 + + +# Maximum Tx power + +# gTxPowerCap=30 + + +# Fragmentation Threshold + +# gFragmentationThreshold=2346 + + +# RTS threshold + +RTSThreshold=192000 + + +# Intra-BSS forward + +gDisableIntraBssFwd=0 + + +# WMM Enable/Disable + +WmmIsEnabled=0 + + +# 802.11d support + +g11dSupportEnabled=1 + +# 802.11h support + +g11hSupportEnabled=1 + +# ESE Support and fast transition +EseEnabled=0 +ImplicitQosIsEnabled=0 +gNeighborScanTimerPeriod=200 + +gNeighborLookupThreshold=76 +gNeighborReassocThreshold=81 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 +gMaxNeighborReqTries=3 + +# Legacy (non-ESE, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1 +# To disable, set FastRoamEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=3 + +# If the RSSI of any available candidate is better than currently associated +# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without +# registering for reassoc threshold). +# NOTE: Value of 0 means that we would register for reassoc threshold. +gImmediateRoamRssiDiff=10 + +# To enable, set gRoamIntraBand=1 (Roaming within band) +# To disable, set gRoamIntraBand=0 (Roaming across band) +gRoamIntraBand=0 + +# SAP Country code + +# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. + +# Example + +# US Indoor, USI + +# Korea Outdoor, KRO + +# Japan without optional byte, JP + +# France without optional byte, FR + +#gAPCntryCode=USI + + +#Short Guard Interval Enable/disable + +gShortGI20Mhz=1 + +gShortGI40Mhz=1 + + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled + +gAPAutoShutOff=0 + + +# SAP auto channel selection configuration + +# 0 = disable auto channel selection + +# 1 = enable auto channel selection, channel provided by supplicant will be ignored + +gApAutoChannelSelection=0 + + +# Listen Energy Detect Mode Configuration + +# Valid values 0-128 + +# 128 means disable Energy Detect feature + +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. + +# 10-128 are reserved. + +# The EDET threshold mapping is as follows in 3dB step: + +# 0 = -60 dBm + +# 1 = -63 dBm + +# 2 = -66 dBm + +# ... + +# 7 = -81 dBm + +# 8 = -84 dBm + +# 9 = -87 dBm + +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: + +# + +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. + +# + +gEnablePhyAgcListenMode=128 + + +#Preferred band (both or 2.4 only or 5 only) + +BandCapability=0 + + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) + +enableBeaconEarlyTermination=0 + +beaconEarlyTerminationWakeInterval=3 + + +#SOFTAP Channel Range selection + +gAPChannelSelectStartChannel=1 + +gAPChannelSelectEndChannel=11 + + +#SOFTAP Channel Range selection Operating band + +# 0:2.4GHZ 1: LOW-5GHZ 2:MID-5GHZ 3:HIGH-5GHZ 4: 4.9HZ BAND + +gAPChannelSelectOperatingBand=0 + + +#Channel Bonding +gChannelBondingMode5GHz=1 + + +#Enable Keep alive with non-zero period value + +gStaKeepAlivePeriod = 30 + +#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). +#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) +#For both active and power save clients. + +#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. +#If doesn't honor for 5 seconds then DUT remove client. + +#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on +#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. +#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. + +#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period +#where we send NULL frame. + +#gApLinkMonitorPeriod = 10 + +#gGoLinkMonitorPeriod = 10 + +#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. +#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. + + +gGoKeepAlivePeriod = 20 + +gApKeepAlivePeriod = 20 + + +#If set will start with active scan after driver load, otherwise will start with + +#passive scan to find out the domain + +gEnableBypass11d=1 + + +#If set to 0, will not scan DFS channels + +gEnableDFSChnlScan=1 + + +gVhtChannelWidth=2 +gEnableLogp=1 + + +# Enable Automatic Tx Power control + +gEnableAutomaticTxPowerControl=1 + +# 0 for OLPC 1 for CLPC and SCPC +gEnableCloseLoop=1 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +# VHT Tx/Rx MCS values +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS=2 +gVhtTxMCS=2 + +# VHT Tx/Rx MCS values for 2x2 +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gEnable2x2=1 +gVhtRxMCS2x2=0 +gVhtTxMCS2x2=2 + +# Scan Timing Parameters +# gPassiveMaxChannelTime=110 +# gPassiveMinChannelTime=60 +# gActiveMaxChannelTime=40 +# gActiveMinChannelTime=20 + +#If set to 0, MCC is not allowed. +gEnableMCCMode=1 + +# 1=enable STBC; 0=disable STBC +gEnableRXSTBC=1 + +# 1=enable tx STBC; 0=disable +gEnableTXSTBC=1 + +# 1=enable rx LDPC; 0=disable +gEnableRXLDPC=1 + +# Enable Active mode offload +gEnableActiveModeOffload=1 + +#Enable Scan Results Aging based on timer +#Timer value is in seconds +#If Set to 0 it will not enable the feature +gScanAgingTime=0 + +#Enable Power saving mechanism Based on Android Framework +#If set to 0 Driver internally control the Power saving mechanism +#If set to 1 Android Framwrok control the Power saving mechanism +isAndroidPsEn=0 + +#disable LDPC in STA mode if the AP is TXBF capable +gDisableLDPCWithTxbfAP=1 + +#Enable thermal mitigation +gThermalMitigationEnable=1 +gThermalTempMinLevel1=90 +gThermalTempMaxLevel0=110 +gThermalTempMaxLevel1=115 +gThrottlePeriod=100 + +gEnableFastRoamInConcurrency=1 + +#List of Country codes for which 11ac needs to be disabled +#Each country code must be delimited by comma(,) +gListOfNon11acCountryCode=RU,UA,ZA + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + +#Scan offload +gEnableDirectedScanOffload=1 + +#FlexConnect Power Factor +#Default is set to 0 (disable) +gFlexConnectPowerFactor=0 + +#Disable split scan, the FW will take care of it +gNumChanCombinedConc=60 + +#Enable Power Save offload +gEnablePowerSaveOffload=1 + +#Enable firmware uart print +gEnablefwprint=0 + +#Enable firmware log +gEnablefwlog=1 + +#IPA config +gIPAEnable=1 +gIPADescSize=800 +gIPAPreFilterEnable=1 +gIPARMEnable=1 + +#P2P Listen offload +gEnableP2pListenOffload=1 + +# Maximum Receive AMPDU size (VHT only. Valid values: 0->8k 1->16k 2->32k 3->64k 4->128k) +gVhtAmpduLenExponent=7 + +# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) +gVhtMpduLen=0 + +# Maximum number of wow filters required +#gMaxWoWFilters=22 + +# WOW Enable/Disable. +# 0 - Disable both magic pattern match and pattern byte match. +# 1 - Enable magic pattern match on all interfaces. +# 2 - Enable pattern byte match on all interfaces. +# 3 - Enable both magic patter and pattern byte match on all interfaces. +# Default value of gEnableWoW is 3. +# gEnableWoW=0 + +# Enable or Disable MCC Adaptive Scheduler at the FW +# 1=Enable (default), 0=Disable +gEnableMCCAdaptiveScheduler=1 + +#Enable or Disable p2p device address administered +isP2pDeviceAddrAdministrated=0 + +#Disable scan_pno by default +gPNOScanSupport=0 + +#Enable TDLS +gEnableTDLSSupport=1 + +# Regulatory Setting; 0=STRICT; 1=CUSTOM +gRegulatoryChangeCountry=1 + +# Disable FW log function by default +gFwDebugLogType=0 +gFwDebugModuleLoglevel=0,0 + +# Enable or Disable Rx thread +# 1=Enable (default), 0=Disable +gEnableRxThread=0 + +# Enable or Disable FW self-recovery +# Currently, It's for USB only. +# 1=Enable, 0=Disable (default) +gEnableFwSelfRecovery=0 + +# Enable or Disable SAP suspend +# 1=Enable (default), 0=Disable +gEnableSapSuspend=0 + +# Enable TxBF +gTxBFEnable=1 + +# 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 10 +#gDHCPMaxNumClients=10 +# 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) +#gDHCPServerIP=192,168,1,2 + +# gEnableSAPAuthOffload: Enable Software AP Authentication Offload feature +# 1=Enable, 0=Disable (default) +gEnableSAPAuthOffload=0 +# gSAPAuthOffloadSec: Software AP Authentication Offload security Type, 0: disabled, 1: WPA2-PSK CCMP +# gSAPAuthOffloadSec=1 +# gSAPAuthOffloadKey: Passphrase of Security +# gSAPAuthOffloadKey=12345678 + + +# Enable or Disable UDP response offload feature +# 1=Enable, 0=Disable (default) +gudp_resp_offload_support=0 +# Set UDP packet dest port +# It's value is between 0 and 65535 +# Default is 0 +# gudp_resp_offload_dest_port=0 +# Set UDP payload filter +# It is only include Arabic numerals and English letter +# It's length should be between 1 and 127 +# gudp_resp_offload_payload_filter=require status +# Set UDP response payload +# It is only include Arabic numerals and English letter +# It's length should be between 1 and 127 +# gudp_resp_offload_response_payload=status=off + + +END + +# Note: Configuration parser would not read anything past the END marker + diff --git a/drivers/staging/qcacld-2.0/wcnss/inc/halCompiler.h b/drivers/staging/qcacld-2.0/wcnss/inc/halCompiler.h new file mode 100644 index 000000000000..2c4762d3139a --- /dev/null +++ b/drivers/staging/qcacld-2.0/wcnss/inc/halCompiler.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*========================================================================== + * + * @file: aniCompiler.h + * + * @brief: This file tries to abstract the differences among compilers. + * Supported compilers are: + * ARM RVCT compiler + * + * @author: Kumar Anand + * + * + *=========================================================================*/ +#ifndef __ANI_COMPILER_ABSTRACT_H +#define __ANI_COMPILER_ABSTRACT_H + +/* + * 1. GNU C/C++ Compiler + * + * How to detect gcc : __GNUC__ + * How to detect gcc version : + * major version : __GNUC__ (2 = 2.x, 3 = 3.x, 4 = 4.x) + * minor version : __GNUC_MINOR__ + * + * 2. Microsoft C/C++ Compiler + * + * How to detect msc : _MSC_VER + * How to detect msc version : + * _MSC_VER (1200 = MSVC 6.0, 1300 = MSVC 7.0, ...) + * + * 3. Intel C/C++ Compiler + * + * How to detect icc : __INTEL_COMPILER, __ICC (legacy), __ECC (legacy) + * How to detect icc version : + * __INTEL_COMPILER, __ICC, __ECC (700 = 7.0, 900 = 9.0, ...) + * + * 4. Other compilers (not supported) + * + * Borland : __BORLANDC__ + * Greenhills : __ghs + * Metrowerks : __MWERKS__ + * SGI MIPSpro : __sgi + */ + +/* + * Packing directives : These are used to force compiler to pack bits and + * bytes in the data structure. C standard does not regulate this strictly, + * and many things are to compiler implementation. Many compilers support + * compiler specific directives or options that allow different packing + * and alignment. + * + * Alignment directives : Compiler may think packed data structures have + * no specific alignment requirement. Then compiler may generate multiple + * byte accesses to access two byte or four bytes data structures. This + * affects on performance especially for RISC systems. If some data + * structure is located on specific alignment always, alignment directives + * help compiler generate more efficient codes. + */ + +#undef __ANI_COMPILER_PRAGMA_PACK_STACK +#undef __ANI_COMPILER_PRAGMA_PACK + +#if defined(_MSC_VER) +#define __ANI_COMPILER_PRAGMA_PACK_STACK 1 +#define __ANI_COMPILER_PRAGMA_PACK 1 +#define __ani_attr_pre_packed +#define __ani_attr_packed +#define __ani_attr_aligned_2 +#define __ani_attr_aligned_4 +#define __ani_attr_aligned_8 +#define __ani_attr_aligned_16 +#define __ani_attr_aligned_32 +#define PACKED +#define PACKED_POST +#define ALIGN(__value) +#elif defined(__INTEL_COMPILER) || defined(__ICC) || defined(__ECC) +#define __ANI_COMPILER_PRAGMA_PACK 1 +#define __ani_attr_pre_packed +#define __ani_attr_packed +#define __ani_attr_aligned_2 +#define __ani_attr_aligned_4 +#define __ani_attr_aligned_8 +#define __ani_attr_aligned_16 +#define __ani_attr_aligned_32 +#define PACKED +#define PACKED_POST +#define ALIGN(__value) +#elif defined(__GNUC__) +#define __ani_attr_pre_packed +#define __ani_attr_packed __attribute__((packed)) +#define __ani_attr_aligned_2 __attribute__((aligned(2))) +#define __ani_attr_aligned_4 __attribute__((aligned(4))) +#define __ani_attr_aligned_8 __attribute__((aligned(8))) +#define __ani_attr_aligned_16 __attribute__((aligned(16))) +#define __ani_attr_aligned_32 __attribute__((aligned(32))) +#ifndef PACKED +#define PACKED +#endif +#ifndef PACKED_POST +#define PACKED_POST __attribute__((packed)) +#endif +#ifndef ALIGN +#define ALIGN(__value) __attribute__((aligned(__value))) +#endif +#elif defined(ANI_COMPILER_TYPE_RVCT) +/* Nothing defined so far */ + +/* + * RIVA 1.2 and Pronto uses ARMCT5.1 compiler and it throws lot of warning when __align() is used in structure definitions. + * __attribute__((aligned())) is GNU compiler attribute that is accepted by ARM compiler and resolves the warnings. + */ +#if (__ARMCC_VERSION > 400000) +#define __ani_attr_packed +#define __ani_attr_pre_packed __packed +#define __ani_attr_aligned_2 __attribute__((aligned(2))) +#define __ani_attr_aligned_4 __attribute__((aligned(4))) +#define __ani_attr_aligned_8 __attribute__((aligned(8))) +#define __ani_attr_aligned_16 __attribute__((aligned(16))) +#define __ani_attr_aligned_32 __attribute__((aligned(32))) +#define PACKED __packed +#define PACKED_POST +#define ALIGN(__value) __align(__value) +#define PREPACK __packed +#define POSTPACK +#else +#define __ani_attr_packed +#define __ani_attr_pre_packed __packed +#define __ani_attr_aligned_2 __align(2) +#define __ani_attr_aligned_4 __align(4) +#define __ani_attr_aligned_8 __align(8) +#define __ani_attr_aligned_16 __align(16) +#define __ani_attr_aligned_32 __align(32) +#define PACKED __packed +#define PACKED_POST +#define ALIGN(__value) __align(__value) +#endif + +#else +#error "Unknown compiler" +#endif + +#ifndef PACKED_PRE +#define PACKED_PRE __ani_attr_pre_packed +#endif + +#ifndef ALIGN_4 +#define ALIGN_4 __ani_attr_aligned_4 +#endif + +#endif //__ANI_COMPILER_ABSTRACT_H + diff --git a/drivers/staging/qcacld-2.0/wcnss/inc/halLegacyPalTypes.h b/drivers/staging/qcacld-2.0/wcnss/inc/halLegacyPalTypes.h new file mode 100644 index 000000000000..e2090dbc39ef --- /dev/null +++ b/drivers/staging/qcacld-2.0/wcnss/inc/halLegacyPalTypes.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined( __LEGACYPALTYPES_H__ ) +#define __LEGACYPALTYPES_H__ + +/*========================================================================== + * + * @file: halLegacyPalTypes.h + * + * @brief: Exports and types for the Platform Abstraction Layer typedefs. + * + * @author: Kumar Anand + * + * + *=========================================================================*/ + +#include "wlan_types.h" + +/* Common type definitions */ +typedef uint8 tANI_U8; +typedef int8 tANI_S8; +typedef uint16 tANI_U16; +typedef int16 tANI_S16; +typedef uint32 tANI_U32; +typedef int32 tANI_S32; + +#ifndef BUILD_QWPTTSTATIC +typedef uint64 tANI_U64; +#endif + +typedef byte tANI_BYTE; +typedef boolean tANI_BOOLEAN; +typedef uint32 tANI_TIMESTAMP; + +#endif /*__LEGACYPALTYPES_H__*/ diff --git a/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h b/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h new file mode 100644 index 000000000000..5c00fbe57e62 --- /dev/null +++ b/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h @@ -0,0 +1,837 @@ +/* + * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file wlan_nv.h + + \brief Types for NV implementation + Anything that needs to be publicly available should + be in this file + + $Id$========================================================================== */ + +#if !defined( __WLAN_NV_H ) +#define __WLAN_NV_H + +#include "halLegacyPalTypes.h" +#include "halCompiler.h" + +//From HAL/inc/halNv.h +typedef enum +{ + //Common Nv Fields + NV_COMMON_PRODUCT_ID, // 0 + NV_COMMON_PRODUCT_BANDS, // 1 + NV_COMMON_NUM_OF_TX_CHAINS, // 2 + NV_COMMON_NUM_OF_RX_CHAINS, // 3 + NV_COMMON_MAC_ADDR, // 4 + NV_COMMON_MFG_SERIAL_NUMBER, // 5 + NV_COMMON_WLAN_NV_REV_ID, // 6 + NV_COMMON_COUPLER_TYPE, // 7 + NV_COMMON_NV_VERSION, // 8 + NV_COMMON_RESERVED, // 9 + + NUM_NV_FIELDS, + NV_MAX_FIELD = 0x7FFFFFFF /* define as 4 bytes data */ + +}eNvField; + + +#define NV_FIELD_MAC_ADDR_SIZE 6 +#define NV_FIELD_MFG_SN_SIZE 40 +typedef enum +{ + PRODUCT_BAND_11_B_G = 0, //Gen6.0 is only this setting + PRODUCT_BAND_11_A_B_G = 1, + PRODUCT_BAND_11_A = 2, + + NUM_PRODUCT_BANDS, + NUM_PRODUCT_BANDS_INVALID = 0x7FFFFFFF /* define as 4 bytes data */ +}eNvProductBands; //NV_COMMON_PRODUCT_BANDS + +#define EXTERNAL_PA 1 +#define INTERNAL_PA 0 + +#define EXTERNAL_LNA 1 +#define INTERNAL_LNA 0 + +#define EXTERNAL_COUPLER 1 +#define INTERNAL_COUPLER 0 + +#define EXTERNAL_PDET 1 +#define INTERNAL_PDET 0 + +#define DPD_ENABLED 1 +#define DPD_DISABLED 0 + +#define TPC_MODE_OPEN_LOOP 0 +#define TPC_MODE_SCPC 1 +#define TPC_MODE_CLPC_MODE2 2 +#define TPC_MODE_CLPC_MODE3 3 + +#define PA_POLARITY_TX_UNUSED 0 +#define PA_POLARITY_TX_POSITIVE 1 +#define PA_POLARITY_TX_NEGATIVE 2 +#define PA_POLARITY_RX_UNUSED 0 +#define PA_POLARITY_RX_POSITIVE 1 +#define PA_POLARITY_RX_NEGATIVE 2 + +#define NV_VERSION_INVALID 0xFF +#define NV_VERSION_11N_11AC_COUPER_TYPE 0 +#define NV_VERSION_11N_11AC_FW_CONFIG 1 +#define NV_VERSION_LPDC_FW_CONFIG 2 +#ifdef FEATURE_WLAN_CH144 +#define NV_VERSION_CH144_CONFIG 3 +#endif /* FEATURE_WLAN_CH144 */ + +#ifdef WCN_PRONTO +#ifdef FEATURE_WLAN_CH144 +#define WLAN_NV_VERSION NV_VERSION_CH144_CONFIG +#else +#define WLAN_NV_VERSION NV_VERSION_LPDC_FW_CONFIG +#endif /* FEATURE_WLAN_CH144 */ +#else //WCN_PRONTO +#define WLAN_NV_VERSION NV_VERSION_11N_11AC_FW_CONFIG +#endif //WCN_PRONTO + +typedef PACKED_PRE struct PACKED_POST +{ + uint8 macAddr1[NV_FIELD_MAC_ADDR_SIZE]; /* Default, not change name for compatibility */ + uint8 macAddr2[NV_FIELD_MAC_ADDR_SIZE]; + uint8 macAddr3[NV_FIELD_MAC_ADDR_SIZE]; + uint8 macAddr4[NV_FIELD_MAC_ADDR_SIZE]; +} sMacAddr; + +typedef PACKED_PRE union PACKED_POST +{ + //common NV fields + uint16 productId; + uint8 productBands; + uint8 wlanNvRevId; + uint8 numOfTxChains; + uint8 numOfRxChains; + sMacAddr macAddr; + uint8 mfgSN[NV_FIELD_MFG_SN_SIZE]; + uint8 couplerType; + uint8 nvVersion; +} uNvFields; + + +//format of common part of nv +typedef PACKED_PRE struct PACKED_POST +{ + //always ensure fields are aligned to 32-bit boundaries + uint16 productId; + uint8 productBands; + uint8 wlanNvRevId; //0: WCN1312, 1: WCN1314, 2: WCN3660 + + uint8 numOfTxChains; + uint8 numOfRxChains; + uint8 macAddr[NV_FIELD_MAC_ADDR_SIZE]; /* Default, not change name for compatibility */ + uint8 macAddr2[NV_FIELD_MAC_ADDR_SIZE]; + uint8 macAddr3[NV_FIELD_MAC_ADDR_SIZE]; + uint8 macAddr4[NV_FIELD_MAC_ADDR_SIZE]; + uint8 mfgSN[NV_FIELD_MFG_SN_SIZE]; + uint8 couplerType; + uint8 nvVersion; +} sNvFields; + + +//From wlanfw/inc/halPhyTypes.h + +typedef int8 tPowerdBm; //power in signed 8-bit integer, no decimal places + +typedef PACKED_PRE union PACKED_POST +{ + uint32 measurement; //measured values can be passed to pttApi, but are maintained to 2 decimal places internally + int16 reported; //used internally only - reported values only maintain 2 decimals places +}uAbsPwrPrecision; + +typedef enum +{ + PHY_TX_CHAIN_0 = 0, + + NUM_PHY_MAX_TX_CHAINS = 1, + PHY_MAX_TX_CHAINS = NUM_PHY_MAX_TX_CHAINS, + PHY_ALL_TX_CHAINS, + + //possible tx chain combinations + PHY_NO_TX_CHAINS, + PHY_TX_CHAIN_INVALID = 0x7FFFFFFF /* define as 4 bytes data */ +}ePhyTxChains; + +//From wlanfw/inc/halRfTypes.h + +typedef enum +{ + REG_DOMAIN_FCC, + REG_DOMAIN_ETSI, + REG_DOMAIN_JAPAN, + REG_DOMAIN_WORLD, + REG_DOMAIN_N_AMER_EXC_FCC, + REG_DOMAIN_APAC, + REG_DOMAIN_KOREA, + REG_DOMAIN_HI_5GHZ, + REG_DOMAIN_NO_5GHZ, + + NUM_REG_DOMAINS, + NUM_REG_DOMAINS_INVALID = 0x7FFFFFFF /* define as 4 bytes data */ +}eRegDomainId; + +typedef enum +{ + RF_SUBBAND_2_4_GHZ = 0, + RF_SUBBAND_5_LOW_GHZ = 1, //Low & Mid U-NII + RF_SUBBAND_5_MID_GHZ = 2, //ETSI + RF_SUBBAND_5_HIGH_GHZ = 3, //High U-NII + RF_SUBBAND_4_9_GHZ = 4, //Japanese + + + NUM_RF_SUBBANDS, + + MAX_RF_SUBBANDS, + INVALID_RF_SUBBAND, + + RF_BAND_2_4_GHZ = 0, + RF_BAND_5_GHZ = 1, + NUM_RF_BANDS, + BOTH_RF_BANDS, + RF_SUBBAND_INVALID = 0x7FFFFFFF /* define as 4 bytes data */ +}eRfSubBand; + +typedef enum +{ + //2.4GHz Band + RF_CHAN_1 = 0, + RF_CHAN_2, + RF_CHAN_3, + RF_CHAN_4, + RF_CHAN_5, + RF_CHAN_6, + RF_CHAN_7, + RF_CHAN_8, + RF_CHAN_9, + RF_CHAN_10, + RF_CHAN_11, + RF_CHAN_12, + RF_CHAN_13, + RF_CHAN_14, + + //4.9GHz Band + RF_CHAN_240, + RF_CHAN_244, + RF_CHAN_248, + RF_CHAN_252, + RF_CHAN_208, + RF_CHAN_212, + RF_CHAN_216, + + //5GHz Low & Mid U-NII Band + RF_CHAN_36, + RF_CHAN_40, + RF_CHAN_44, + RF_CHAN_48, + RF_CHAN_52, + RF_CHAN_56, + RF_CHAN_60, + RF_CHAN_64, + + //5GHz Mid Band - ETSI & FCC + RF_CHAN_100, + RF_CHAN_104, + RF_CHAN_108, + RF_CHAN_112, + RF_CHAN_116, + RF_CHAN_120, + RF_CHAN_124, + RF_CHAN_128, + RF_CHAN_132, + RF_CHAN_136, + RF_CHAN_140, +#ifdef FEATURE_WLAN_CH144 + RF_CHAN_144, +#endif /* FEATURE_WLAN_CH144 */ + + //5GHz High U-NII Band + RF_CHAN_149, + RF_CHAN_153, + RF_CHAN_157, + RF_CHAN_161, + RF_CHAN_165, + + // 802.11p + RF_CHAN_170, + RF_CHAN_171, + RF_CHAN_172, + RF_CHAN_173, + RF_CHAN_174, + RF_CHAN_175, + RF_CHAN_176, + RF_CHAN_177, + RF_CHAN_178, + RF_CHAN_179, + RF_CHAN_180, + RF_CHAN_181, + RF_CHAN_182, + RF_CHAN_183, + RF_CHAN_184, + + //CHANNEL BONDED CHANNELS + RF_CHAN_BOND_3, + RF_CHAN_BOND_4, + RF_CHAN_BOND_5, + RF_CHAN_BOND_6, + RF_CHAN_BOND_7, + RF_CHAN_BOND_8, + RF_CHAN_BOND_9, + RF_CHAN_BOND_10, + RF_CHAN_BOND_11, + RF_CHAN_BOND_242, //4.9GHz Band + RF_CHAN_BOND_246, + RF_CHAN_BOND_250, + RF_CHAN_BOND_210, + RF_CHAN_BOND_214, + RF_CHAN_BOND_38, //5GHz Low & Mid U-NII Band + RF_CHAN_BOND_42, + RF_CHAN_BOND_46, + RF_CHAN_BOND_50, + RF_CHAN_BOND_54, + RF_CHAN_BOND_58, + RF_CHAN_BOND_62, + RF_CHAN_BOND_102, //5GHz Mid Band - ETSI & FCC + RF_CHAN_BOND_106, + RF_CHAN_BOND_110, + RF_CHAN_BOND_114, + RF_CHAN_BOND_118, + RF_CHAN_BOND_122, + RF_CHAN_BOND_126, + RF_CHAN_BOND_130, + RF_CHAN_BOND_134, + RF_CHAN_BOND_138, +#ifdef FEATURE_WLAN_CH144 + RF_CHAN_BOND_142, +#endif /* FEATURE_WLAN_CH144 */ + RF_CHAN_BOND_151, //5GHz High U-NII Band + RF_CHAN_BOND_155, + RF_CHAN_BOND_159, + RF_CHAN_BOND_163, + + NUM_RF_CHANNELS, + + MIN_2_4GHZ_CHANNEL = RF_CHAN_1, + MAX_2_4GHZ_CHANNEL = RF_CHAN_14, + + MIN_5GHZ_CHANNEL = RF_CHAN_240, + MAX_5GHZ_CHANNEL = RF_CHAN_184, + NUM_5GHZ_CHANNELS = (MAX_5GHZ_CHANNEL - MIN_5GHZ_CHANNEL + 1), + + MIN_20MHZ_RF_CHANNEL = RF_CHAN_1, + MAX_20MHZ_RF_CHANNEL = RF_CHAN_184, + NUM_20MHZ_RF_CHANNELS = (MAX_20MHZ_RF_CHANNEL - MIN_20MHZ_RF_CHANNEL + 1), + + MIN_40MHZ_RF_CHANNEL = RF_CHAN_BOND_3, + MAX_40MHZ_RF_CHANNEL = RF_CHAN_BOND_163, + NUM_40MHZ_RF_CHANNELS = (MAX_40MHZ_RF_CHANNEL - MIN_40MHZ_RF_CHANNEL + 1), + + MIN_CB_2_4GHZ_CHANNEL = RF_CHAN_BOND_3, + MAX_CB_2_4GHZ_CHANNEL = RF_CHAN_BOND_11, + + MIN_CB_5GHZ_CHANNEL = RF_CHAN_BOND_242, + MAX_CB_5GHZ_CHANNEL = RF_CHAN_BOND_163, + + NUM_TPC_2_4GHZ_CHANNELS = 14, + NUM_TPC_5GHZ_CHANNELS = NUM_5GHZ_CHANNELS, + + INVALID_RF_CHANNEL = 0xBAD, + RF_CHANNEL_INVALID_MAX_FIELD = 0x7FFFFFFF /* define as 4 bytes data */ +}eRfChannels; + +typedef enum +{ + RF_CHAN_1_1 = RF_CHAN_1, + RF_CHAN_2_1 = RF_CHAN_2, + RF_CHAN_3_1 = RF_CHAN_3, + RF_CHAN_4_1 = RF_CHAN_4, + RF_CHAN_5_1 = RF_CHAN_5, + RF_CHAN_6_1 = RF_CHAN_6, + RF_CHAN_7_1 = RF_CHAN_7, + RF_CHAN_8_1 = RF_CHAN_8, + RF_CHAN_9_1 = RF_CHAN_9, + RF_CHAN_10_1 = RF_CHAN_10, + RF_CHAN_11_1 = RF_CHAN_11, + RF_CHAN_12_1 = RF_CHAN_12, + RF_CHAN_13_1 = RF_CHAN_13, + RF_CHAN_14_1 = RF_CHAN_14, +// The above params are used for scripts. + NUM_2_4GHZ_CHANNELS, +}eRfChannels_2_4GHz; + +enum +{ + NV_CHANNEL_DISABLE, + NV_CHANNEL_ENABLE, + NV_CHANNEL_DFS, + NV_CHANNEL_INVALID +}; +typedef uint8 eNVChannelEnabledType; + +typedef PACKED_PRE struct PACKED_POST +{ + eNVChannelEnabledType enabled; + tPowerdBm pwrLimit; +}sRegulatoryChannel; + +typedef PACKED_PRE struct PACKED_POST +{ + sRegulatoryChannel channels[NUM_RF_CHANNELS]; + uAbsPwrPrecision antennaGain[NUM_RF_SUBBANDS]; + uAbsPwrPrecision bRatePowerOffset[NUM_2_4GHZ_CHANNELS]; + uAbsPwrPrecision gnRatePowerOffset[NUM_RF_CHANNELS]; +}ALIGN_4 sRegulatoryDomains; + +typedef PACKED_PRE struct PACKED_POST +{ + int16 bRssiOffset[NUM_RF_CHANNELS]; + int16 gnRssiOffset[NUM_RF_CHANNELS]; +}ALIGN_4 sRssiChannelOffsets; + +typedef PACKED_PRE struct PACKED_POST +{ + uint16 targetFreq; //number in MHz + uint16 channelNum; //channel number as in the eRfChannels enumeration + eRfSubBand band; //band that this channel belongs to +}tRfChannelProps; + +typedef enum +{ + MODE_802_11B = 0, + MODE_802_11AG = 1, + MODE_802_11N = 2, + NUM_802_11_MODES, + MODE_802_11_INVALID = 0x7FFFFFFF /* define as 4 bytes data */ +} e80211Modes; + +#define HW_CAL_VALUES_VALID_BMAP_UNUSED 0 //Value +//Bit mask +#define HW_VAL_VALUES_VALID_BMAP_SLEEP_TIME_OVERHEAD_2G_MASK 0x1 +#define HW_VAL_VALUES_VALID_BMAP_SLEEP_TIME_OVERHEAD_5G_MASK 0x2 +#define HW_VAL_VALUES_VALID_BMAP_SLEEP_TIME_OVERHEAD_xLNA_5G_MASK 0x4 +#define HW_VAL_VALUES_VALID_TXBBF_SEL_9MHZ_MASK 0x8 +#define HW_VAL_VALUES_VALID_CUSTOM_TCXO_REG8_MASK 0x10 +#define HW_VAL_VALUES_VALID_CUSTOM_TCXO_REG9_MASK 0x20 + +//From wlanfw/inc/halPhyCalMemory.h +typedef PACKED_PRE struct PACKED_POST +{ + uint16 psSlpTimeOvrHd2G; + uint16 psSlpTimeOvrHd5G; + + uint16 psSlpTimeOvrHdxLNA5G; + uint8 nv_TxBBFSel9MHz : 1; + uint8 hwParam1 : 7; + uint8 hwParam2; + + uint16 custom_tcxo_reg8; + uint16 custom_tcxo_reg9; + + uint32 hwParam3; + uint32 hwParam4; + uint32 hwParam5; + uint32 hwParam6; + uint32 hwParam7; + uint32 hwParam8; + uint32 hwParam9; + uint32 hwParam10; + uint32 hwParam11; +}sCalData; + +typedef PACKED_PRE struct PACKED_POST +{ + uint32 validBmap; //use eNvCalID + sCalData calData; +}sHwCalValues; + +typedef PACKED_PRE struct PACKED_POST +{ + uint32 txFirFilterMode; +}sTxBbFilterMode; + +typedef PACKED_PRE struct PACKED_POST +{ + int16 ofdmPwrOffset; + int16 rsvd; +}sOfdmCmdPwrOffset; + +//From wlanfw/inc/halPhyCfg.h +typedef uint8 tTpcLutValue; + +#define MAX_TPC_CAL_POINTS (8) + +typedef uint8 tPowerDetect; //7-bit power detect reading + +typedef PACKED_PRE struct PACKED_POST +{ + tPowerDetect pwrDetAdc; //= SENSED_PWR register, which reports the 8-bit ADC + // the stored ADC value gets shifted to 7-bits as the index to the LUT + tPowerDetect adjustedPwrDet; //7-bit value that goes into the LUT at the LUT[pwrDet] location + //MSB set if extraPrecision.hi8_adjustedPwrDet is used +}tTpcCaldPowerPoint; + +typedef tTpcCaldPowerPoint tTpcCaldPowerTable[NUM_PHY_MAX_TX_CHAINS][MAX_TPC_CAL_POINTS]; + +typedef PACKED_PRE struct PACKED_POST +{ + tTpcCaldPowerTable empirical; //calibrated power points +}tTpcConfig; + +//From wlanfw/inc/phyTxPower.h +#ifndef TPC_MEM_POWER_LUT_DEPTH +#define TPC_MEM_POWER_LUT_DEPTH 256 +#endif + +typedef tTpcLutValue tTpcPowerTable[NUM_PHY_MAX_TX_CHAINS][TPC_MEM_POWER_LUT_DEPTH]; + +typedef PACKED_PRE struct PACKED_POST +{ + tTpcConfig *pwrSampled; //points to CLPC data in calMemory +}tPhyTxPowerBand; + +//From halPhyRates.h +typedef enum +{ + //802.11b Rates + HAL_PHY_RATE_11B_LONG_1_MBPS, + HAL_PHY_RATE_11B_LONG_2_MBPS, + HAL_PHY_RATE_11B_LONG_5_5_MBPS, + HAL_PHY_RATE_11B_LONG_11_MBPS, + HAL_PHY_RATE_11B_SHORT_2_MBPS, + HAL_PHY_RATE_11B_SHORT_5_5_MBPS, + HAL_PHY_RATE_11B_SHORT_11_MBPS, + + //Spica_Virgo 11A 20MHz Rates + HAL_PHY_RATE_11A_6_MBPS, + HAL_PHY_RATE_11A_9_MBPS, + HAL_PHY_RATE_11A_12_MBPS, + HAL_PHY_RATE_11A_18_MBPS, + HAL_PHY_RATE_11A_24_MBPS, + HAL_PHY_RATE_11A_36_MBPS, + HAL_PHY_RATE_11A_48_MBPS, + HAL_PHY_RATE_11A_54_MBPS, + + // 11A 20MHz Rates + HAL_PHY_RATE_11A_DUP_6_MBPS, + HAL_PHY_RATE_11A_DUP_9_MBPS, + HAL_PHY_RATE_11A_DUP_12_MBPS, + HAL_PHY_RATE_11A_DUP_18_MBPS, + HAL_PHY_RATE_11A_DUP_24_MBPS, + HAL_PHY_RATE_11A_DUP_36_MBPS, + HAL_PHY_RATE_11A_DUP_48_MBPS, + HAL_PHY_RATE_11A_DUP_54_MBPS, + + //MCS Index #0-7 (20/40MHz) + HAL_PHY_RATE_MCS_1NSS_6_5_MBPS, + HAL_PHY_RATE_MCS_1NSS_13_MBPS, + HAL_PHY_RATE_MCS_1NSS_19_5_MBPS, + HAL_PHY_RATE_MCS_1NSS_26_MBPS, + HAL_PHY_RATE_MCS_1NSS_39_MBPS, + HAL_PHY_RATE_MCS_1NSS_52_MBPS, + HAL_PHY_RATE_MCS_1NSS_58_5_MBPS, + HAL_PHY_RATE_MCS_1NSS_65_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_7_2_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_14_4_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_21_7_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_28_9_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_43_3_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_57_8_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_65_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_72_2_MBPS, + + //MCS Index #8-15 (20/40MHz) + HAL_PHY_RATE_MCS_1NSS_CB_13_5_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_27_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_40_5_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_54_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_81_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_108_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_121_5_MBPS, + HAL_PHY_RATE_MCS_1NSS_CB_135_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_15_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_30_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_45_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_60_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_90_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_120_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_135_MBPS, + HAL_PHY_RATE_MCS_1NSS_MM_SG_CB_150_MBPS, + +#ifdef WLAN_FEATURE_11AC + /*11A duplicate 80MHz Rates*/ + HAL_PHY_RATE_11AC_DUP_6_MBPS, + HAL_PHY_RATE_11AC_DUP_9_MBPS, + HAL_PHY_RATE_11AC_DUP_12_MBPS, + HAL_PHY_RATE_11AC_DUP_18_MBPS, + HAL_PHY_RATE_11AC_DUP_24_MBPS, + HAL_PHY_RATE_11AC_DUP_36_MBPS, + HAL_PHY_RATE_11AC_DUP_48_MBPS, + HAL_PHY_RATE_11AC_DUP_54_MBPS, + + /*11AC rate 20MHZ Normal GI*/ + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_6_5_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_13_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_19_5_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_26_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_39_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_52_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_58_5_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_65_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_78_MBPS, +#ifdef WCN_PRONTO + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_NGI_86_5_MBPS, +#endif + + /*11AC rate 20MHZ Shortl GI*/ + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_7_2_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_14_4_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_21_6_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_28_8_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_43_3_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_57_7_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_65_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_72_2_MBPS, + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_86_6_MBPS, +#ifdef WCN_PRONTO + HAL_PHY_RATE_VHT_20MHZ_MCS_1NSS_SGI_96_1_MBPS, +#endif + + /*11AC rates 40MHZ normal GI*/ + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_13_5_MBPS , + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_27_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_40_5_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_54_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_81_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_108_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_121_5_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_135_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_162_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_NGI_180_MBPS, + + /*11AC rates 40MHZ short GI*/ + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_15_MBPS , + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_30_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_45_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_60_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_90_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_120_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_135_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_150_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_180_MBPS, + HAL_PHY_RATE_VHT_40MHZ_MCS_1NSS_CB_SGI_200_MBPS, + + /*11AC rates 80 MHZ normal GI*/ + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_29_3_MBPS , + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_58_5_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_87_8_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_117_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_175_5_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_234_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_263_3_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_292_5_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_351_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_NGI_390_MBPS, + + /*11AC rates 80 MHZ short GI*/ + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_32_5_MBPS , + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_65_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_97_5_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_130_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_195_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_260_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_292_5_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_325_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_390_MBPS, + HAL_PHY_RATE_VHT_80MHZ_MCS_1NSS_CB_SGI_433_3_MBPS, +#endif //WLAN_FEATURE_11AC + + NUM_HAL_PHY_RATES, + HAL_PHY_RATE_INVALID, + MIN_RATE_INDEX = 0, + MAX_RATE_INDEX = NUM_HAL_PHY_RATES - 1, + HAL_PHY_RATE_INVALID_MAX_FIELD = 0x7FFFFFFF /* define as 4 bytes data */ +}eHalPhyRates; + +#define NUM_RATE_POWER_GROUPS NUM_HAL_PHY_RATES //total number of rate power groups including the CB_RATE_POWER_OFFSET +typedef uAbsPwrPrecision tRateGroupPwr[NUM_HAL_PHY_RATES]; + +//From halNvTables.h +#define NV_FIELD_COUNTRY_CODE_SIZE 3 +typedef PACKED_PRE struct PACKED_POST +{ + uint8 regDomain; //from eRegDomainId + uint8 countryCode[NV_FIELD_COUNTRY_CODE_SIZE]; // string identifier +}sDefaultCountry; + + +#define GF_PA_BIAS_SELECT_MASK 0X7 //(3 bits) +#define TSMC_PA_BIAS_SELECT_MASK 0x7 //(3 bits) + +#define GF_PA_BIAS_SELECT_1 0X0 +#define GF_PA_BIAS_SELECT_2 0X1 + +#define TSMC_PA_BIAS_SELECT_1 0X0 +#define TSMC_PA_BIAS_SELECT_2 0X1 +#define TSMC_PA_BIAS_SELECT_3 0x2 + + +#define EXT_PA_CTRL_POLARITY_DEFAULT 0X0 +#define EXT_PA_CTRL_POLARITY_VALID 0X80 + +#define EXT_PA_CTRL0_POLARITY_MASK 0X3 +#define EXT_PA_CTRL0_POLARITY_OFFSET 0X0 +#define EXT_PA_CTRL1_POLARITY_MASK 0XC +#define EXT_PA_CTRL1_POLARITY_OFFSET 0X2 + +#define EXT_PA_CTRL_POLARITY_ZERO 0X1 +#define EXT_PA_CTRL_POLARITY_ONE 0X2 + +typedef PACKED_PRE struct PACKED_POST +{ + uint8 skuID; + uint8 tpcMode2G; + uint8 tpcMode5G; + uint8 configItem1; + + uint8 xPA2G; + uint8 xPA5G; + uint8 extPaCtrl0Polarity; + uint8 extPaCtrl1Polarity; + + uint8 xLNA2G; + uint8 xLNA5G; + uint8 xCoupler2G; + uint8 xCoupler5G; + + uint8 xPdet2G; + uint8 xPdet5G; + uint8 enableDPD2G; + uint8 enableDPD5G; + + uint8 pdadcSelect2G; + uint8 pdadcSelect5GLow; + uint8 pdadcSelect5GMid; + uint8 pdadcSelect5GHigh; + + uint32 configItem2; + uint32 configItem3; + uint32 configItem4; +}sFwConfig; + + +#define NUM_RF_VR_RATE 13 +typedef uAbsPwrPrecision tRateGroupPwrVR[NUM_RF_VR_RATE]; + +typedef PACKED_PRE union PACKED_POST +{ + tRateGroupPwr pwrOptimum[NUM_RF_SUBBANDS]; // NV_TABLE_RATE_POWER_SETTINGS + sRegulatoryDomains regDomains[NUM_REG_DOMAINS]; // NV_TABLE_REGULATORY_DOMAINS + sDefaultCountry defaultCountryTable; // NV_TABLE_DEFAULT_COUNTRY + tTpcPowerTable plutCharacterized[NUM_RF_CHANNELS]; // NV_TABLE_TPC_POWER_TABLE + int16 plutPdadcOffset[NUM_RF_CHANNELS]; // NV_TABLE_TPC_PDADC_OFFSETS + tRateGroupPwrVR pwrOptimum_virtualRate[NUM_RF_SUBBANDS]; // NV_TABLE_VIRTUAL_RATE + sFwConfig fwConfig; // NV_TABLE_FW_CONFIG + sRssiChannelOffsets rssiChanOffsets[2]; // NV_TABLE_RSSI_CHANNEL_OFFSETS + sHwCalValues hwCalValues; // NV_TABLE_HW_CAL_VALUES + int16 antennaPathLoss[NUM_RF_CHANNELS]; // NV_TABLE_ANTENNA_PATH_LOSS + int16 pktTypePwrLimits[NUM_802_11_MODES][NUM_RF_CHANNELS]; // NV_TABLE_PACKET_TYPE_POWER_LIMITS + sOfdmCmdPwrOffset ofdmCmdPwrOffset; // NV_TABLE_OFDM_CMD_PWR_OFFSET + sTxBbFilterMode txbbFilterMode; // NV_TABLE_TX_BB_FILTER_MODE +}ALIGN_4 uNvTables; + +//From halPhy.h +typedef tPowerdBm tChannelPwrLimit; + +typedef PACKED_PRE struct PACKED_POST +{ + uint8 chanId; + tChannelPwrLimit pwr; +} ALIGN_4 tChannelListWithPower; + +//From HAL/inc/halNvTables.h +typedef enum +{ + NV_FIELDS_IMAGE = 0, //contains all fields + + NV_TABLE_RATE_POWER_SETTINGS = 2, + NV_TABLE_REGULATORY_DOMAINS = 3, + NV_TABLE_DEFAULT_COUNTRY = 4, + NV_TABLE_TPC_POWER_TABLE = 5, + NV_TABLE_TPC_PDADC_OFFSETS = 6, + NV_TABLE_HW_CAL_VALUES = 7, + NV_TABLE_RSSI_CHANNEL_OFFSETS = 9, + NV_TABLE_CAL_MEMORY = 10, //cal memory structure from halPhyCalMemory.h preceded by status + NV_TABLE_FW_CONFIG = 11, + NV_TABLE_ANTENNA_PATH_LOSS = 12, + NV_TABLE_PACKET_TYPE_POWER_LIMITS = 13, + NV_TABLE_OFDM_CMD_PWR_OFFSET = 14, + NV_TABLE_TX_BB_FILTER_MODE = 15, + NV_TABLE_VIRTUAL_RATE = 18, + + NUM_NV_TABLE_IDS, + NV_ALL_TABLES = 0xFFF, + NV_BINARY_IMAGE = 0x1000, + NV_MAX_TABLE = 0x7FFFFFFF /* define as 4 bytes data */ +}eNvTable; + +typedef PACKED_PRE struct PACKED_POST +{ + tRateGroupPwr pwrOptimum[NUM_RF_SUBBANDS]; // NV_TABLE_RATE_POWER_SETTINGS + sRegulatoryDomains regDomains[NUM_REG_DOMAINS]; // NV_TABLE_REGULATORY_DOMAINS + sDefaultCountry defaultCountryTable; // NV_TABLE_DEFAULT_COUNTRY + tTpcPowerTable plutCharacterized[NUM_RF_CHANNELS]; // NV_TABLE_TPC_POWER_TABLE + int16 plutPdadcOffset[NUM_RF_CHANNELS]; // NV_TABLE_TPC_PDADC_OFFSETS + tRateGroupPwrVR pwrOptimum_virtualRate[NUM_RF_SUBBANDS]; // NV_TABLE_VIRTUAL_RATE + sFwConfig fwConfig; // NV_TABLE_FW_CONFIG + sRssiChannelOffsets rssiChanOffsets[2]; // NV_TABLE_RSSI_CHANNEL_OFFSETS + sHwCalValues hwCalValues; // NV_TABLE_HW_CAL_VALUES + int16 antennaPathLoss[NUM_RF_CHANNELS]; // NV_TABLE_ANTENNA_PATH_LOSS + int16 pktTypePwrLimits[NUM_802_11_MODES][NUM_RF_CHANNELS]; // NV_TABLE_PACKET_TYPE_POWER_LIMITS + sOfdmCmdPwrOffset ofdmCmdPwrOffset; // NV_TABLE_OFDM_CMD_PWR_OFFSET + sTxBbFilterMode txbbFilterMode; // NV_TABLE_TX_BB_FILTER_MODE +}ALIGN_4 sNvTables; + +typedef PACKED_PRE struct PACKED_POST +{ + sNvFields fields; + sNvTables tables; +}ALIGN_4 sHalNv; + +extern const sHalNv nvDefaults; + +#endif + From 5d9745b7374378395caf49a1843f039537f5a96c Mon Sep 17 00:00:00 2001 From: dianlujitao Date: Thu, 16 Jun 2016 11:35:51 +0800 Subject: [PATCH 082/203] staging: qcacld-2.0: Clean up unused files Change-Id: Ief809f36ba236552eddece01e516bce006367fa3 --- drivers/staging/qcacld-2.0/Android.mk | 113 --- .../qcacld-2.0/firmware_bin/WCNSS_cfg.dat | Bin 10234 -> 0 bytes .../firmware_bin/WCNSS_qcom_cfg.ini | 665 ------------------ .../firmware_bin/WCNSS_qcom_cfg.usb.ini | 550 --------------- 4 files changed, 1328 deletions(-) delete mode 100644 drivers/staging/qcacld-2.0/Android.mk delete mode 100755 drivers/staging/qcacld-2.0/firmware_bin/WCNSS_cfg.dat delete mode 100755 drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini delete mode 100644 drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini diff --git a/drivers/staging/qcacld-2.0/Android.mk b/drivers/staging/qcacld-2.0/Android.mk deleted file mode 100644 index 2ae160a2b766..000000000000 --- a/drivers/staging/qcacld-2.0/Android.mk +++ /dev/null @@ -1,113 +0,0 @@ -# Android makefile for the WLAN Module - -# Assume no targets will be supported -WLAN_CHIPSET := - -ifeq ($(BOARD_HAS_QCOM_WLAN), true) -# Build/Package options for 8084/8092/8960/8992/8994/msm8996 targets -ifeq ($(call is-board-platform-in-list, apq8084 mpq8092 msm8952 msm8960 msm8992 msm8994 msm8996),true) -WLAN_CHIPSET := qca_cld -WLAN_SELECT := CONFIG_QCA_CLD_WLAN=m -endif - -# Build/Package only in case of supported target -ifneq ($(WLAN_CHIPSET),) - -LOCAL_PATH := $(call my-dir) - -# This makefile is only for DLKM -ifneq ($(findstring vendor,$(LOCAL_PATH)),) - -# Determine if we are Proprietary or Open Source -ifneq ($(findstring opensource,$(LOCAL_PATH)),) - WLAN_PROPRIETARY := 0 - WLAN_OPEN_SOURCE := 1 -else - WLAN_PROPRIETARY := 1 - WLAN_OPEN_SOURCE := 0 -endif - -ifeq ($(WLAN_PROPRIETARY),1) - WLAN_BLD_DIR := vendor/qcom/proprietary/wlan-noship -else - WLAN_BLD_DIR := vendor/qcom/opensource/wlan -endif - -# DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) -ifeq ($(call is-platform-sdk-version-at-least,16),true) - DLKM_DIR := $(TOP)/device/qcom/common/dlkm -else - DLKM_DIR := build/dlkm -endif - -# Copy WCNSS_cfg.dat and WCNSS_qcom_cfg.ini file from firmware_bin/ folder to target out directory. -ifeq ($(call is-board-platform-in-list, msm8960),true) -$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/WCNSS_cfg.dat) -$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini) -$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT_ETC)/firmware/wlan/qca_cld) -$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_qcom_cfg.ini $(TARGET_OUT_ETC)/firmware/wlan/qca_cld) -endif - -########################################################### -# This is set once per LOCAL_PATH, not per (kernel) module -KBUILD_OPTIONS := WLAN_ROOT=../$(WLAN_BLD_DIR)/qcacld-2.0 -# We are actually building wlan.ko here, as per the -# requirement we are specifying _wlan.ko as LOCAL_MODULE. -# This means we need to rename the module to _wlan.ko -# after wlan.ko is built. -KBUILD_OPTIONS += MODNAME=wlan -KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) -KBUILD_OPTIONS += $(WLAN_SELECT) -KBUILD_OPTIONS += WLAN_OPEN_SOURCE=$(WLAN_OPEN_SOURCE) - -include $(CLEAR_VARS) -LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko -LOCAL_MODULE_KBUILD_NAME := wlan.ko -LOCAL_MODULE_TAGS := debug -LOCAL_MODULE_DEBUG_ENABLE := true -LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) -include $(DLKM_DIR)/AndroidKernelModule.mk -########################################################### - -# Create Symbolic link for built _wlan.ko driver from -# standard module location. -# TO-DO: This step needs to be moved to a post-build make target instead -# TO-DO: as this may run multiple times -$(shell mkdir -p $(TARGET_OUT)/lib/modules; \ - ln -sf /system/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ - $(TARGET_OUT)/lib/modules/wlan.ko) -$(shell ln -sf /persist/wlan_mac.bin $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/wlan_mac.bin) - -ifeq ($(call is-board-platform-in-list, msm8960),true) -$(shell ln -sf /firmware/image/bdwlan20.bin $(TARGET_OUT_ETC)/firmware/fakeboar.bin) -$(shell ln -sf /firmware/image/otp20.bin $(TARGET_OUT_ETC)/firmware/otp.bin) -$(shell ln -sf /firmware/image/utf20.bin $(TARGET_OUT_ETC)/firmware/utf.bin) -$(shell ln -sf /firmware/image/qwlan20.bin $(TARGET_OUT_ETC)/firmware/athwlan.bin) - -$(shell ln -sf /firmware/image/bdwlan20.bin $(TARGET_OUT_ETC)/firmware/bdwlan20.bin) -$(shell ln -sf /firmware/image/otp20.bin $(TARGET_OUT_ETC)/firmware/otp20.bin) -$(shell ln -sf /firmware/image/utf20.bin $(TARGET_OUT_ETC)/firmware/utf20.bin) -$(shell ln -sf /firmware/image/qwlan20.bin $(TARGET_OUT_ETC)/firmware/qwlan20.bin) - -$(shell ln -sf /firmware/image/bdwlan30.bin $(TARGET_OUT_ETC)/firmware/bdwlan30.bin) -$(shell ln -sf /firmware/image/otp30.bin $(TARGET_OUT_ETC)/firmware/otp30.bin) -$(shell ln -sf /firmware/image/utf30.bin $(TARGET_OUT_ETC)/firmware/utf30.bin) -$(shell ln -sf /firmware/image/qwlan30.bin $(TARGET_OUT_ETC)/firmware/qwlan30.bin) -endif - -# Copy config ini files to target -ifeq ($(call is-board-platform-in-list, msm8994),false) -ifeq ($(WLAN_PROPRIETARY),1) -$(shell mkdir -p $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_CHIPSET)) -$(shell mkdir -p $(TARGET_OUT)/etc/wifi) -$(shell rm -f $(TARGET_OUT)/etc/wifi/WCNSS_qcom_cfg.ini) -$(shell rm -f $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_SHIPSET)/WCNSS_cfg.dat) -$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_qcom_cfg.ini $(TARGET_OUT)/etc/wifi) -$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_CHIPSET)) -endif -endif - -endif # DLKM check - -endif # supported target check -endif # WLAN enabled check diff --git a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_cfg.dat b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_cfg.dat deleted file mode 100755 index 08aaf2bfd38bca3f47114ad603e133c2348b9333..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10234 zcmeI033yc1701uZyktTW=1vrGmoXxVfV{92kSaW^vWQFEz!jrJL<~48C@Sg$gGG%v zRVbiUK*fFSYOPDGXi;lxty>kBx|J#_rD!c5pY(U$ceq8wF+{EadGB!|0_?2auJ2a1!G zQjjvKSgKUq8c(|WyUHFg0>(gLjq!^hUTfT9=l~^9nlVxa9U%cGZ6pchuti|}EwP=_ z#@z}!!`843YzyO4F{w|-WV?(f+h;ug%v7Z`q$_0(?2z_kZcyp(m?@Q=GDf;UN=#~J zF>Xa*++Cn6^w=hUfT1&DG7e_JP0*k5kI#t9sF`sYkTLE+*aHT^_gUMXuve4jE0Cv%8BBdhlMx?= zHW_zs>6BfXounb;;)lk&HUc$kwuMhSR)^#ZJ90rHO=qAq}!#qbY|B-MM9NlF6 zW9S>vQ0X6=IY`C^o_}20xV34|KYp?2pMZU0$^d`d;vs%rx`%&adWb(B|4ECx_!D3S zeILNd#7(R={wYuolVCEO3TZeEPKPsK3QUDF;VhU2XTv#gE=-5>;C#3M0+<0a;X-JD zS#S~j5N5;0%zp`7nl^qT_A;0Qm#00+)ENIqa0Ofmb73C*80Oa)SpW;+D!3Yc0@uK` zY0q5*i(v^|2iKGHhP3fzR@`42823iFNsQbK;|t?*3-+XcbH+)8_5hq&B^ zJ*6Zrw+s7I8u#xY$DME&+zt1@PhnDH-2WN&=kN>oCHxBRg+!H$)?kyEr$#YM6I=->4 zc@!-=Wfuw{2r*^IZ06=(AeUIDI7RGhFLxw+CC)r|Y&w z=jCxN8#ZJ;cF7uNOYRu;NBgy{$E*8ei_WXLbq}>@dOJqv*LuBmL=K*(Ro-I5H6U8g zH^3gI#wwq(2&Ie;#TNB#s`zwjxSi8lJ!ajnl4dZiV(h$X_1xG!4yfxOd%m<8mg4NW zwE3+&YHeS#*~yS_PIpaB%iPg;tp}iM+$jgUKHM$E=5KK{SM>NbhaRt#+IO=#_1UFkmtwU}%J99}v$?Kq zjkmPQgEQLBt*0L1O^8$T>w8xF^*EyM=YV!}oPJ*fAM_7>`kdA86dkWIdak0ec2Bh5 z*0rBz7^ha}3iq52Js*ntEzx+*VRNYsW7KM~W5RYezvk8wT~lsdU+>Yi*?v8?s6U*K z+%4~C4Wy`FbL1B7)*Jyu^Qd3fs_!1P_IT~QZCN|FwK~XWtj!f#l4*Zi<87SI7p;f; z7LLnqpv`an8XLey|Hit#Ml?p>^Y&dIo+BLtHK6^v58Ad?>-ru@Vb?dK*G_c(c1|6i zi;ma#y!v(j?7LjQch$!ya=7PxusY8L*l3QroVI=k?z2xtg-GANC7ew+R^SxJi*!k( z(j(K1Iun|K>@1y2-GXANkgnToQC43&qFQ8E`nu6qDe=OXGeCBe>Yi0y{XGZvt0*mU z3VL<#7B6&TWhEVoC)6c6PMeahpWP5lUpRkW!$dwR zVb7hk3N@EVy zn3xdSDdEKAKvy`85$&|8gVu zcM+2vE6dB}RQ6Wm<1!v+Jlts^KAk83X?gOWo+tkqdGb%mlYc6Hz3PT=0mZrup{1o< z&Llr)eJtx|oz3eXTP|l2jo)MaEWUaDUb#$*<~JMn=j`VE8+6|y{&TYH|4jaKv+K{v zZ{$4D>mgk~p)Qy{ZHhF`Zb-|;;uJWJ<2o^?$SHJ+ow!rtba2X?QYYbbbhFIQLs-0fa&*>urr9VGr28l0&Wde`RG$(eNOyNeIF0-Yif#QWn^1iya`(wfnjjd5JtL;1zfkUWYf} zEq;f+CmqX5xxq~0j#sn)RKxo>y$kfzh8kWE^gEL(NTSQ}vWlfl%7wz3&uVy~eph4s zR{CA7aa-wknTUSJ@9r)6?cWKzRXQP^VQbh1wuS9rd@8Hqq2I|4nbsQKj_J}+!`lfB zFVyeIjeeJ^KquHGK)-{Ce&<$kMP>CnBOA3lPkNz6d4Z8?=E!Pyo~U-0)$Ba!&l(57 zz#t)e5SLHG8^n04;i1{NXm;*iFc^lgHXnvIdFXeQ^5M+5>`gt??3#@1+hp8f*x`U? z=Z_@Uei_dlh20+xz>i+%9>luP>*QcK1P;Z2820eMq}GzR1Whgl{b7GN0j9wmxB>2i zr{Nt~4_lzwRl#5w&H4_*j$vI#knc!1iusOi^890%=UC<+3&%lilktzIZz3Ar321oZ z0uQauxF@1jg<2hU6&l?HG`y41@Ft?+oq~o}kA61^KBX@?b$~yaxNl6at2X{6a49sx zWzekG`I$6&9c#G)u7tU1Pv+Gm(CZTDbqRj~EQG57z0S|-bqTq)CLxPpF)V@W;Cl7} zz0O?%~qA@oY8u#ph!bsS6b}c zUx%(|b7@{ZX8kbLuTe!yzIEyO(eG$2f&O8D`dY;oi}<-d+RqU1dTi0{bX0e;tW@mn9JBQ^@_$7PnHKxOKEtcFg(KzkX`)zY+-wu4+=e&KZZvQBI z&seLO>~+@GUf902X3UMZ*QK>~j9#8~wy_DT`ScNL^$4|JRqxa3>@nE<--O<$bJZX( z=;Te$Igk6Y&o&jSuUM@qQg&DO@L)pMr%Z*3UI zpHQ!|wJNe_sD9FK@s8=c500 zE^V0k-PQm{b3Kni;;bnDKhpvunp{K+L^|_tey2A_VXPo diff --git a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini deleted file mode 100755 index a128d61d2313..000000000000 --- a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.ini +++ /dev/null @@ -1,665 +0,0 @@ -# This file allows user to override the factory - -# defaults for the WLAN Driver - - -# Enable IMPS or not -gEnableImps=1 - -# Enable/Disable Idle Scan -gEnableIdleScan=0 - - -# Increase sleep duration (seconds) during IMPS -# 0 implies no periodic wake up from IMPS. Periodic wakeup is -# unnecessary if Idle Scan is disabled. -gImpsModSleepTime=0 - - -# Enable BMPS or not -gEnableBmps=1 - -# Enable suspend or not - -# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter - -gEnableSuspend=3 - -# Phy Mode (auto, b, g, n, etc) -# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac -# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only -# 7 = 11b only 8 = 11ac only. -gDot11Mode=0 - - -# CSR Roaming Enable(1) Disable(0) - -gRoamingTime=0 - - -# Assigned MAC Addresses - This will be used until NV items are in place - -# Each byte of MAC address is represented in Hex format as XX - -Intf0MacAddress=000AF58989FF -Intf1MacAddress=000AF58989FE -Intf2MacAddress=000AF58989FD - -Intf3MacAddress=000AF58989FC - - -# UAPSD service interval for VO,VI, BE, BK traffic - -InfraUapsdVoSrvIntv=0 - -InfraUapsdViSrvIntv=0 - -InfraUapsdBeSrvIntv=0 - -InfraUapsdBkSrvIntv=0 - -# Flag to allow STA send AddTspec even when ACM is Off -gAddTSWhenACMIsOff=1 - -# Make 1x1 the default antenna configuration - -gNumRxAnt=1 - - -# Beacon filtering frequency (unit in beacon intervals) - -gNthBeaconFilter=50 - - -# Enable WAPI or not - -# WAPIIsEnabled=0 - - -# Flags to filter Mcast abd Bcast RX packets. - -# Value 0: No filtering, 1: Filter all Multicast. - -# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast - -McastBcastFilter=3 - - -#Flag to enable HostARPOffload feature or not - -hostArpOffload=1 - -#Flag to enable TCPChkSumOffld feature or not - -gEnableTCPChkSumOffld=1 - -#Flag to enable HostNSOffload feature or not - -hostNSOffload=1 - -#Flag to enable IPChkSumOffld feature or not - -gEnableIPChecksumOffload=1 - -#SoftAP Related Parameters - -# AP MAc addr - -gAPMacAddr=000AF589dcab - - -# 802.11n Protection flag - -gEnableApProt=1 - - -#Enable OBSS protection - -gEnableApOBSSProt=1 - - -#Enable/Disable UAPSD for SoftAP - -gEnableApUapsd=1 - - -# Fixed Rate - -gFixedRate=0 - - -# Maximum Tx power - -# gTxPowerCap=30 - - -# Fragmentation Threshold - -# gFragmentationThreshold=2346 - - -# RTS threshold - -RTSThreshold=1048576 - - -# Intra-BSS forward - -gDisableIntraBssFwd=0 - - -# WMM Enable/Disable - -WmmIsEnabled=0 - - -# 802.11d support - -g11dSupportEnabled=0 - -# 802.11h support - -g11hSupportEnabled=1 - -# DFS Master Capability -gEnableDFSMasterCap=1 - -# ESE Support and fast transition -EseEnabled=1 -ImplicitQosIsEnabled=0 -gNeighborScanTimerPeriod=200 - -gNeighborLookupThreshold=76 -gNeighborReassocThreshold=81 - -gNeighborScanChannelMinTime=20 -gNeighborScanChannelMaxTime=30 -gMaxNeighborReqTries=3 - -# Legacy (non-ESE, non-802.11r) Fast Roaming Support -# To enable, set FastRoamEnabled=1 -# To disable, set FastRoamEnabled=0 -FastRoamEnabled=1 - -#Check if the AP to which we are roaming is better than current AP in terms of RSSI. -#Checking is disabled if set to Zero.Otherwise it will use this value as to how better -#the RSSI of the new/roamable AP should be for roaming -RoamRssiDiff=3 - -# If the RSSI of any available candidate is better than currently associated -# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without -# registering for reassoc threshold). -# NOTE: Value of 0 means that we would register for reassoc threshold. -gImmediateRoamRssiDiff=10 - -# To enable, set gRoamIntraBand=1 (Roaming within band) -# To disable, set gRoamIntraBand=0 (Roaming across band) -gRoamIntraBand=0 - -# SAP Country code - -# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. - -# Example - -# US Indoor, USI - -# Korea Outdoor, KRO - -# Japan without optional byte, JP - -# France without optional byte, FR - -#gAPCntryCode=USI - - -#Short Guard Interval Enable/disable - -gShortGI20Mhz=1 - -gShortGI40Mhz=1 - - -#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled - -gAPAutoShutOff=0 - -#Auto Shutdown wlan : Value in Seconds. 0 means disabled. Max 1 day = 86400 sec -gWlanAutoShutdown = 0 - - -# Listen Energy Detect Mode Configuration - -# Valid values 0-128 - -# 128 means disable Energy Detect feature - -# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. - -# 10-128 are reserved. - -# The EDET threshold mapping is as follows in 3dB step: - -# 0 = -60 dBm - -# 1 = -63 dBm - -# 2 = -66 dBm - -# ... - -# 7 = -81 dBm - -# 8 = -84 dBm - -# 9 = -87 dBm - -# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: - -# - -# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. - -# - -gEnablePhyAgcListenMode=128 - - -#Preferred band (both or 2.4 only or 5 only) - -BandCapability=0 - - -#Beacon Early Termination (1 = enable the BET feature, 0 = disable) - -enableBeaconEarlyTermination=0 - -beaconEarlyTerminationWakeInterval=3 - - -#Channel Bonding -gChannelBondingMode5GHz=1 - - -#Enable Keep alive with non-zero period value - -gStaKeepAlivePeriod = 30 - -#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). -#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) -#For both active and power save clients. - -#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. -#If doesn't honor for 5 seconds then DUT remove client. - -#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on -#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. -#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. - -#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period -#where we send NULL frame. - -gApLinkMonitorPeriod = 30 - -gGoLinkMonitorPeriod = 10 - -#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. -#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. - - -gGoKeepAlivePeriod = 3 - -gApKeepAlivePeriod = 10 - - -#If set will start with active scan after driver load, otherwise will start with - -#passive scan to find out the domain - -gEnableBypass11d=1 - - -#If set to 0, will not scan DFS channels - -gEnableDFSChnlScan=1 - -# Enable DFS channel roam -# 0: DISABLE, 1: ENABLED_NORMAL, 2: ENABLED_ACTIVE -gAllowDFSChannelRoam=1 - -gVhtChannelWidth=2 - - -# Enable Automatic Tx Power control - -gEnableAutomaticTxPowerControl=1 - -# 0 for OLPC 1 for CLPC and SCPC -gEnableCloseLoop=1 - -#Data Inactivity Timeout when in powersave (in ms) -gDataInactivityTimeout=200 - -# VHT Tx/Rx MCS values -# Valid values are 0,1,2. If commented out, the default value is 0. -# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 -gVhtRxMCS=2 -gVhtTxMCS=2 - -# VHT Tx/Rx MCS values for 2x2 -# Valid values are 0,1,2. If commented out, the default value is 0. -# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 -gVhtRxMCS2x2=2 -gVhtTxMCS2x2=2 - - -# Valid chain mask values -# 01 - enables chain0 -# 02 - enables chain1 -# 03 - enables both chain 0 and chain 1 -# if set to 0 or 1 then all vdevs comes up in 1x1 mode in that band. -gChainMask_2g=3 -gChainMask_5g=3 - -# NSS cfg bit definition. -# STA BIT[0:1] -# SAP BIT[2:3] -# P2P_GO BIT[4:5] -# P2P_CLIENT BIT[6:7] -# IBSS BIT[8:9] -# TDLS BIT[10:11] -# P2P_DEVICE BIT[12:13] -# OCB BIT[14:15] -# Valid values are 1 or 2 for each two bit configuration. -# if 2-bit value is set to 1 then the corresponidng vdev comes up in 1x1 mode -# in the band, if set to 2 then that vdev comes up in 2x2 mode in that band. -gVdevTypeNss_2g=43690 -gVdevTypeNss_5g=43690 - -# Scan Timing Parameters -# gPassiveMaxChannelTime=110 -# gPassiveMinChannelTime=60 -gActiveMaxChannelTime=80 -gActiveMinChannelTime=40 - -#If set to 0, MCC is not allowed. -gEnableMCCMode=1 - -# MCC to SCC Switch mode: 0-Disable 1-Enable 2-Force SCC if same band -gWlanMccToSccSwitchMode = 0 - -# 1=enable STBC; 0=disable STBC -gEnableRXSTBC=1 - -# 1=enable tx STBC; 0=disable -gEnableTXSTBC=1 - -# 1=enable rx LDPC; 0=disable -gEnableRXLDPC=1 - -# Enable Tx beamforming in VHT20MHz -# Valid values are 0,1. If commented out, the default value is 0. -# 0=disable, 1=enable -gEnableTxBFin20MHz=1 - -# Enable Active mode offload -gEnableActiveModeOffload=1 - -#Enable Scan Results Aging based on timer -#Timer value is in seconds -#If Set to 0 it will not enable the feature -gScanAgingTime=0 - -#Enable Scan Results Aging based on number of scans -gScanResultAgeCount=1 - -#Enable Power saving mechanism Based on Android Framework -#If set to 0 Driver internally control the Power saving mechanism -#If set to 1 Android Framwrok control the Power saving mechanism -isAndroidPsEn=0 - -#Enable thermal mitigation -gThermalMitigationEnable=0 - -gEnableFastRoamInConcurrency=1 - -#List of Country codes for which 11ac needs to be disabled -#Each country code must be delimited by comma(,) -gListOfNon11acCountryCode=RU,UA,ZA - -#Maxium Channel time in msec -gMaxMediumTime = 6000 - -# 802.11K support -gRrmEnable=1 -gRrmOperChanMax=8 -gRrmNonOperChanMax=8 -gRrmRandIntvl=100 - -#Scan offload -gEnableDirectedScanOffload=1 - -#FlexConnect Power Factor -#Default is set to 0 (disable) -gFlexConnectPowerFactor=0 - -#Disable split scan, the FW will take care of it -gNumChanCombinedConc=60 - -#Enable Power Save offload -gEnablePowerSaveOffload=2 - -#Enable firmware uart print -gEnablefwprint=0 - -#Enable firmware log -gEnablefwlog=1 -# Additional firmware log levels -gFwDebugLogLevel=4 -gFwDebugModuleLoglevel=1,0,2,0,4,0,5,0,6,0,7,4,8,0,9,0,11,0,13,0,17,0,18,0,19,0,27,0,29,0,31,0,35,0,36,0,38,0 - -#IPA config -gIPAConfig=0 -gIPADescSize=800 -gIPAPreFilterEnable=1 -gIPARMEnable=1 -gIPAIPv6Enable=1 - -#P2P Listen offload -gEnableP2pListenOffload=1 - -# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) -gVhtMpduLen=2 - -# Maximum number of wow filters required -#gMaxWoWFilters=22 - -# WOW Enable/Disable. -# 0 - Disable both magic pattern match and pattern byte match. -# 1 - Enable magic pattern match on all interfaces. -# 2 - Enable pattern byte match on all interfaces. -# 3 - Enable both magic patter and pattern byte match on all interfaces. -# Default value of gEnableWoW is 3. -# gEnableWoW=0 - -# Enable or Disable MCC Adaptive Scheduler at the FW -# 1=Enable (default), 0=Disable -gEnableMCCAdaptiveScheduler=1 - -#Enable or Disable p2p device address administered -isP2pDeviceAddrAdministrated=1 - -# RX packet handling options -# 0: no rx thread, no RPS, for MDM -# 1: RX thread -# 2: RPS -rxhandle=2 - -# Set RPS CPU MAP as 0xe for the 4 RX queues -# This allows use of CPU1-CPU3 but not CPU0 for 4 RX queues -rpsRxQueueCpuMapList=c - -# Set Thermal Power limit -TxPower2g=10 -TxPower5g=10 - -# Remove Overlap channel restriction -gEnableOverLapCh=0 - -#Enable VHT on 2.4Ghz -gEnableVhtFor24GHzBand=1 - -#Enable or Disable 5G early beacon termination -gEnable5gEBT=1 - -#Maximum number of offload peers supported -# gMaxOffloadPeers=2 - -# controlling the following offload patterns -# through ini parameter. Default value is 1 -# to disable set it to zero. ssdp = 0 -# Setup multicast pattern for mDNS 224.0.0.251, -# SSDP 239.255.255.250 and LLMNR 224.0.0.252 - - -ssdp = 0 - -#Enable Memory Deep Sleep -gEnableMemDeepSleep=1 - -# Bus bandwidth threshold values in terms of number of packets -gBusBandwidthHighThreshold=2000 -gBusBandwidthMediumThreshold=500 -gBusBandwidthLowThreshold=150 - -# IPA bandwidth voting -gIPAHighBandwidthMbps=800 -gIPAMediumBandwidthMbps=400 -gIPALowBandwidthMbps=200 - -# Bus bandwidth compute timeout value in ms -gBusBandwidthComputeInterval=100 - -# Regulatory Setting; 0=STRICT; 1=CUSTOM -gRegulatoryChangeCountry=1 -# RA filtering rate limit param, the current value would not -# help if the lifetime in RA is less than 3*60=3min. Then -# we need to change it, though it is uncommon. -# gRAFilterEnable=0 -gRArateLimitInterval=600 - -# Maximum number of concurrent connections -gMaxConcurrentActiveSessions=2 - -# Disable/Enable GreenAP -# 0 to disable, 1 to enable, default: 1 -gEnableGreenAp=1 - -# Radar PRI multiplier -gDFSradarMappingPriMultiplier=4 - -gPNOScanSupport=0 - -# Enable/Disable RX full reorder offload -gReorderOffloadSupported=1 - -# Enable/Disable LPASS support -# 0 to disable, 1 to enable -gEnableLpassSupport=1 - -# Whether userspace country code setting shld have priority -gCountryCodePriority=1 - -# Enable(1)/Disable(0) SIFS burst -gEnableSifsBurst=1 - -# Enable/Disable channel avoidance for SAP in SCC scenario -# 0 - disable -# 1 - enable -gSapSccChanAvoidance=0 - -# Inactivity time (in ms) to end TX Service Period while in IBSS power save mode -gIbssTxSpEndInactivityTime=10 - -# Enable/Disable Roaming Offload Support (a.k.a Key Management Offload) -# 0 to disable, 1 to enable -gRoamOffloadEnabled=0 - -# Enable support for TDLS -# 0 - disable -# 1 - enable -gEnableTDLSSupport=1 - -# Enable support for Implicit Trigger of TDLS. That is, wlan driver shall -# initiate TDLS Discovery towards a peer whenever setup criteria (throughput -# and RSSI) is met and then will initiate teardown when teardown criteria -# (idle packet count and RSSI) is met. -# 0 - disable -# 1 - enable -gEnableTDLSImplicitTrigger=1 - -# Enable TDLS External Control. That is, user space application has to -# first configure a peer MAC in wlan driver towards which TDLS is desired. -# Device will establish TDLS only towards those configured peers whenever -# TDLS criteria (throughput and RSSI threshold) is met and teardown TDLS -# when teardown criteria (idle packet count and RSSI) is met. However, -# device will accept TDLS connection if it is initiated from any other peer, -# even if that peer is not configured. -# 0 - disable -# 1 - enable -# For TDLS External Control, Implicit Trigger must also be enabled. -gTDLSExternalControl=1 - -# Enable support for TDLS off-channel operation -# 0 - disable -# 1 - enable -# TDLS off-channel operation will be invoked when there is only one -# TDLS connection. -gEnableTDLSOffChannel=1 - -IpaUcOffloadEnabled=1 -gIpaUcStaOffload=1 - -gEnableSelfRecovery=1 - -# Enable or Disable Random MAC (Spoofing) -# 1=Enable, 0=Disable (default) -gEnableMacAddrSpoof=0 - -# Enable Auto suspend feature -# When this feature is enabled, it will shutdown the PCIe link -# when inactivity is detected in STA disconnected mode. -# 0 - disable -# 1 - enable -gEnableBusAutoSuspend=0 - -# Enable Runtime PM Feature. -# Enabling this feature will put target wow and shutdown pcie link -# when inactivity is detected in WLAN Driver. -# This feature is inactive when beaconing interfaces are active with -# clients associated. -# 0 - disable -# 1 - enable - -gRuntimePM=1 -# When gRuntimePM is disabled gRuntimeAutoTime won't take effect. -# The Time is in msec. -# 100 is min, 10000 is max, 500 is default. - -gRuntimePMDelay=500 - -# Enable to check FW hash if secure FW feature is enabled. It's for defconfig -# builds only since it will be ignored in performance/release builds. -gEnableFWHashCheck=1 - -# Enable FW to filter out broadcast packets and wakeup host during runtime PM. -# As APPS is awake during runtime PM, if any application needs the broadcast -# packets OEM's can enable this flag. -# FW will filters the broadcast packets and wakeup host to deliver them during -# runtime suspend. -# This flag will take affect when Runtime PM is enabled -gRuntimePmEnableBcastPattern=0 -END - -# Note: Configuration parser would not read anything past the END marker - diff --git a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini b/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini deleted file mode 100644 index 0a7422f2c2e7..000000000000 --- a/drivers/staging/qcacld-2.0/firmware_bin/WCNSS_qcom_cfg.usb.ini +++ /dev/null @@ -1,550 +0,0 @@ -# This file allows user to override the factory - -# defaults for the WLAN Driver - - -# Enable IMPS or not -gEnableImps=1 - -# Enable/Disable Idle Scan - -gEnableIdleScan=0 - - -# Increase sleep duration (seconds) during IMPS -# 0 implies no periodic wake up from IMPS. Periodic wakeup is -# unnecessary if Idle Scan is disabled. -gImpsModSleepTime=0 - - -# Enable BMPS or not -gEnableBmps=1 - -# Enable suspend or not - -# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter - -gEnableSuspend=3 - - -# Phy Mode (auto, b, g, n, etc) -# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac -# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only -# 7 = 11b only 8 = 11ac only. -gDot11Mode=0 - - -# CSR Roaming Enable(1) Disable(0) - -gRoamingTime=0 - - -# Assigned MAC Addresses - This will be used until NV items are in place - -# Each byte of MAC address is represented in Hex format as XX - -Intf0MacAddress=000AF58989FF -Intf1MacAddress=000AF58989FE -Intf2MacAddress=000AF58989FD - -Intf3MacAddress=000AF58989FC - - -# UAPSD service interval for VO,VI, BE, BK traffic - -InfraUapsdVoSrvIntv=0 - -InfraUapsdViSrvIntv=0 - -InfraUapsdBeSrvIntv=0 - -InfraUapsdBkSrvIntv=0 - -# Flag to allow STA send AddTspec even when ACM is Off -gAddTSWhenACMIsOff=1 - -# Make 1x1 the default antenna configuration - -gNumRxAnt=1 - - -# Beacon filtering frequency (unit in beacon intervals) - -gNthBeaconFilter=50 - - -# Enable WAPI or not - -# WAPIIsEnabled=0 - - -# Flags to filter Mcast abd Bcast RX packets. - -# Value 0: No filtering, 1: Filter all Multicast. - -# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast - -McastBcastFilter=3 - - -#Flag to enable HostARPOffload feature or not - -hostArpOffload=1 - -#Flag to enable TCPChkSumOffld feature or not - -gEnableTCPChkSumOffld=1 - -#Flag to enable HostNSOffload feature or not - -hostNSOffload=1 - -#Flag to enable IPChkSumOffld feature or not - -gEnableIPChecksumOffload=0 - -#SoftAP Related Parameters - -# AP MAc addr - -gAPMacAddr=000AF589dcab - - -# 802.11n Protection flag - -gEnableApProt=1 - - -#Enable OBSS protection - -gEnableApOBSSProt=1 - - -#Enable/Disable UAPSD for SoftAP - -gEnableApUapsd=1 - - -# Fixed Rate - -gFixedRate=0 - - -# Maximum Tx power - -# gTxPowerCap=30 - - -# Fragmentation Threshold - -# gFragmentationThreshold=2346 - - -# RTS threshold - -RTSThreshold=192000 - - -# Intra-BSS forward - -gDisableIntraBssFwd=0 - - -# WMM Enable/Disable - -WmmIsEnabled=0 - - -# 802.11d support - -g11dSupportEnabled=1 - -# 802.11h support - -g11hSupportEnabled=1 - -# ESE Support and fast transition -EseEnabled=0 -ImplicitQosIsEnabled=0 -gNeighborScanTimerPeriod=200 - -gNeighborLookupThreshold=76 -gNeighborReassocThreshold=81 - -gNeighborScanChannelMinTime=20 -gNeighborScanChannelMaxTime=30 -gMaxNeighborReqTries=3 - -# Legacy (non-ESE, non-802.11r) Fast Roaming Support -# To enable, set FastRoamEnabled=1 -# To disable, set FastRoamEnabled=0 -FastRoamEnabled=1 - -#Check if the AP to which we are roaming is better than current AP in terms of RSSI. -#Checking is disabled if set to Zero.Otherwise it will use this value as to how better -#the RSSI of the new/roamable AP should be for roaming -RoamRssiDiff=3 - -# If the RSSI of any available candidate is better than currently associated -# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without -# registering for reassoc threshold). -# NOTE: Value of 0 means that we would register for reassoc threshold. -gImmediateRoamRssiDiff=10 - -# To enable, set gRoamIntraBand=1 (Roaming within band) -# To disable, set gRoamIntraBand=0 (Roaming across band) -gRoamIntraBand=0 - -# SAP Country code - -# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. - -# Example - -# US Indoor, USI - -# Korea Outdoor, KRO - -# Japan without optional byte, JP - -# France without optional byte, FR - -#gAPCntryCode=USI - - -#Short Guard Interval Enable/disable - -gShortGI20Mhz=1 - -gShortGI40Mhz=1 - - -#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled - -gAPAutoShutOff=0 - - -# SAP auto channel selection configuration - -# 0 = disable auto channel selection - -# 1 = enable auto channel selection, channel provided by supplicant will be ignored - -gApAutoChannelSelection=0 - - -# Listen Energy Detect Mode Configuration - -# Valid values 0-128 - -# 128 means disable Energy Detect feature - -# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. - -# 10-128 are reserved. - -# The EDET threshold mapping is as follows in 3dB step: - -# 0 = -60 dBm - -# 1 = -63 dBm - -# 2 = -66 dBm - -# ... - -# 7 = -81 dBm - -# 8 = -84 dBm - -# 9 = -87 dBm - -# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: - -# - -# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. - -# - -gEnablePhyAgcListenMode=128 - - -#Preferred band (both or 2.4 only or 5 only) - -BandCapability=0 - - -#Beacon Early Termination (1 = enable the BET feature, 0 = disable) - -enableBeaconEarlyTermination=0 - -beaconEarlyTerminationWakeInterval=3 - - -#SOFTAP Channel Range selection - -gAPChannelSelectStartChannel=1 - -gAPChannelSelectEndChannel=11 - - -#SOFTAP Channel Range selection Operating band - -# 0:2.4GHZ 1: LOW-5GHZ 2:MID-5GHZ 3:HIGH-5GHZ 4: 4.9HZ BAND - -gAPChannelSelectOperatingBand=0 - - -#Channel Bonding -gChannelBondingMode5GHz=1 - - -#Enable Keep alive with non-zero period value - -gStaKeepAlivePeriod = 30 - -#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). -#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) -#For both active and power save clients. - -#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. -#If doesn't honor for 5 seconds then DUT remove client. - -#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on -#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. -#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. - -#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period -#where we send NULL frame. - -#gApLinkMonitorPeriod = 10 - -#gGoLinkMonitorPeriod = 10 - -#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. -#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. - - -gGoKeepAlivePeriod = 20 - -gApKeepAlivePeriod = 20 - - -#If set will start with active scan after driver load, otherwise will start with - -#passive scan to find out the domain - -gEnableBypass11d=1 - - -#If set to 0, will not scan DFS channels - -gEnableDFSChnlScan=1 - - -gVhtChannelWidth=2 -gEnableLogp=1 - - -# Enable Automatic Tx Power control - -gEnableAutomaticTxPowerControl=1 - -# 0 for OLPC 1 for CLPC and SCPC -gEnableCloseLoop=1 - -#Data Inactivity Timeout when in powersave (in ms) -gDataInactivityTimeout=200 - -# VHT Tx/Rx MCS values -# Valid values are 0,1,2. If commented out, the default value is 0. -# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 -gVhtRxMCS=2 -gVhtTxMCS=2 - -# VHT Tx/Rx MCS values for 2x2 -# Valid values are 0,1,2. If commented out, the default value is 0. -# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 -gEnable2x2=1 -gVhtRxMCS2x2=0 -gVhtTxMCS2x2=2 - -# Scan Timing Parameters -# gPassiveMaxChannelTime=110 -# gPassiveMinChannelTime=60 -# gActiveMaxChannelTime=40 -# gActiveMinChannelTime=20 - -#If set to 0, MCC is not allowed. -gEnableMCCMode=1 - -# 1=enable STBC; 0=disable STBC -gEnableRXSTBC=1 - -# 1=enable tx STBC; 0=disable -gEnableTXSTBC=1 - -# 1=enable rx LDPC; 0=disable -gEnableRXLDPC=1 - -# Enable Active mode offload -gEnableActiveModeOffload=1 - -#Enable Scan Results Aging based on timer -#Timer value is in seconds -#If Set to 0 it will not enable the feature -gScanAgingTime=0 - -#Enable Power saving mechanism Based on Android Framework -#If set to 0 Driver internally control the Power saving mechanism -#If set to 1 Android Framwrok control the Power saving mechanism -isAndroidPsEn=0 - -#disable LDPC in STA mode if the AP is TXBF capable -gDisableLDPCWithTxbfAP=1 - -#Enable thermal mitigation -gThermalMitigationEnable=1 -gThermalTempMinLevel1=90 -gThermalTempMaxLevel0=110 -gThermalTempMaxLevel1=115 -gThrottlePeriod=100 - -gEnableFastRoamInConcurrency=1 - -#List of Country codes for which 11ac needs to be disabled -#Each country code must be delimited by comma(,) -gListOfNon11acCountryCode=RU,UA,ZA - -#Maxium Channel time in msec -gMaxMediumTime = 6000 - -# 802.11K support -gRrmEnable=1 -gRrmOperChanMax=8 -gRrmNonOperChanMax=8 -gRrmRandIntvl=100 - -#Scan offload -gEnableDirectedScanOffload=1 - -#FlexConnect Power Factor -#Default is set to 0 (disable) -gFlexConnectPowerFactor=0 - -#Disable split scan, the FW will take care of it -gNumChanCombinedConc=60 - -#Enable Power Save offload -gEnablePowerSaveOffload=1 - -#Enable firmware uart print -gEnablefwprint=0 - -#Enable firmware log -gEnablefwlog=1 - -#IPA config -gIPAEnable=1 -gIPADescSize=800 -gIPAPreFilterEnable=1 -gIPARMEnable=1 - -#P2P Listen offload -gEnableP2pListenOffload=1 - -# Maximum Receive AMPDU size (VHT only. Valid values: 0->8k 1->16k 2->32k 3->64k 4->128k) -gVhtAmpduLenExponent=7 - -# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) -gVhtMpduLen=0 - -# Maximum number of wow filters required -#gMaxWoWFilters=22 - -# WOW Enable/Disable. -# 0 - Disable both magic pattern match and pattern byte match. -# 1 - Enable magic pattern match on all interfaces. -# 2 - Enable pattern byte match on all interfaces. -# 3 - Enable both magic patter and pattern byte match on all interfaces. -# Default value of gEnableWoW is 3. -# gEnableWoW=0 - -# Enable or Disable MCC Adaptive Scheduler at the FW -# 1=Enable (default), 0=Disable -gEnableMCCAdaptiveScheduler=1 - -#Enable or Disable p2p device address administered -isP2pDeviceAddrAdministrated=0 - -#Disable scan_pno by default -gPNOScanSupport=0 - -#Enable TDLS -gEnableTDLSSupport=1 - -# Regulatory Setting; 0=STRICT; 1=CUSTOM -gRegulatoryChangeCountry=1 - -# Disable FW log function by default -gFwDebugLogType=0 -gFwDebugModuleLoglevel=0,0 - -# Enable or Disable Rx thread -# 1=Enable (default), 0=Disable -gEnableRxThread=0 - -# Enable or Disable FW self-recovery -# Currently, It's for USB only. -# 1=Enable, 0=Disable (default) -gEnableFwSelfRecovery=0 - -# Enable or Disable SAP suspend -# 1=Enable (default), 0=Disable -gEnableSapSuspend=0 - -# Enable TxBF -gTxBFEnable=1 - -# 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 10 -#gDHCPMaxNumClients=10 -# 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) -#gDHCPServerIP=192,168,1,2 - -# gEnableSAPAuthOffload: Enable Software AP Authentication Offload feature -# 1=Enable, 0=Disable (default) -gEnableSAPAuthOffload=0 -# gSAPAuthOffloadSec: Software AP Authentication Offload security Type, 0: disabled, 1: WPA2-PSK CCMP -# gSAPAuthOffloadSec=1 -# gSAPAuthOffloadKey: Passphrase of Security -# gSAPAuthOffloadKey=12345678 - - -# Enable or Disable UDP response offload feature -# 1=Enable, 0=Disable (default) -gudp_resp_offload_support=0 -# Set UDP packet dest port -# It's value is between 0 and 65535 -# Default is 0 -# gudp_resp_offload_dest_port=0 -# Set UDP payload filter -# It is only include Arabic numerals and English letter -# It's length should be between 1 and 127 -# gudp_resp_offload_payload_filter=require status -# Set UDP response payload -# It is only include Arabic numerals and English letter -# It's length should be between 1 and 127 -# gudp_resp_offload_response_payload=status=off - - -END - -# Note: Configuration parser would not read anything past the END marker - From 537599dd5688d84ac7d87c3ce24424f812ba514e Mon Sep 17 00:00:00 2001 From: dianlujitao Date: Mon, 27 Jun 2016 21:26:41 +0800 Subject: [PATCH 083/203] qcacld-2.0: Update to LA.HB.1.3.2-15400-8x96.0 Change-Id: Iad2e4b1b2413c1d585eb4d565de68f5015aec539 --- .../qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c | 32 +- .../qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c | 33 +- .../CORE/CLD_TXRX/TXRX/ol_tx_queue.c | 3 +- .../qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c | 14 +- .../qcacld-2.0/CORE/EPPING/src/epping_main.c | 3 + .../qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h | 4 +- .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h | 9 +- .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h | 42 +- .../CORE/HDD/inc/wlan_hdd_cfg80211.h | 19 + .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h | 28 +- .../CORE/HDD/inc/wlan_hdd_memdump.h | 2 +- .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h | 5 +- .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h | 14 +- .../CORE/HDD/inc/wlan_hdd_tgt_cfg.h | 3 +- .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h | 12 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c | 167 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c | 29 +- .../CORE/HDD/src/wlan_hdd_cfg80211.c | 178 +- .../CORE/HDD/src/wlan_hdd_early_suspend.c | 5 + .../CORE/HDD/src/wlan_hdd_hostapd.c | 104 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c | 6 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c | 1634 ++++++++++++++--- .../CORE/HDD/src/wlan_hdd_memdump.c | 9 + .../CORE/HDD/src/wlan_hdd_oemdata.c | 13 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c | 83 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c | 161 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c | 322 +++- .../qcacld-2.0/CORE/MAC/inc/aniGlobal.h | 12 +- .../qcacld-2.0/CORE/MAC/inc/qwlan_version.h | 4 +- .../staging/qcacld-2.0/CORE/MAC/inc/sirApi.h | 124 +- .../staging/qcacld-2.0/CORE/MAC/inc/wniApi.h | 8 +- .../qcacld-2.0/CORE/MAC/inc/wniCfgAp.h | 15 +- .../qcacld-2.0/CORE/MAC/inc/wniCfgSta.h | 11 +- .../qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c | 2 +- .../qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c | 10 +- .../CORE/MAC/src/include/parserApi.h | 5 +- .../CORE/MAC/src/include/sirParams.h | 14 + .../CORE/MAC/src/pe/include/limApi.h | 3 + .../CORE/MAC/src/pe/include/limGlobal.h | 3 +- .../qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c | 21 + .../CORE/MAC/src/pe/lim/limAssocUtils.c | 9 +- .../qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c | 23 +- .../qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c | 107 +- .../MAC/src/pe/lim/limProcessActionFrame.c | 42 +- .../MAC/src/pe/lim/limProcessAssocRspFrame.c | 3 + .../MAC/src/pe/lim/limProcessBeaconFrame.c | 1 + .../MAC/src/pe/lim/limProcessDisassocFrame.c | 5 +- .../MAC/src/pe/lim/limProcessMessageQueue.c | 23 +- .../MAC/src/pe/lim/limProcessMlmReqMessages.c | 37 +- .../MAC/src/pe/lim/limProcessMlmRspMessages.c | 7 +- .../MAC/src/pe/lim/limProcessProbeRspFrame.c | 4 +- .../MAC/src/pe/lim/limProcessSmeReqMessages.c | 191 +- .../CORE/MAC/src/pe/lim/limProcessTdls.c | 237 ++- .../MAC/src/pe/lim/limSendManagementFrames.c | 61 +- .../MAC/src/pe/lim/limSendSmeRspMessages.c | 58 +- .../CORE/MAC/src/pe/lim/limSession.c | 4 + .../CORE/MAC/src/pe/lim/limTimerUtils.c | 5 +- .../qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h | 9 + .../qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c | 135 +- .../qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h | 6 + .../qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c | 42 +- .../CORE/MAC/src/pe/sch/schBeaconGen.c | 118 +- .../staging/qcacld-2.0/CORE/SAP/inc/sapApi.h | 13 +- .../qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c | 34 +- .../qcacld-2.0/CORE/SAP/src/sapChSelect.c | 63 +- .../staging/qcacld-2.0/CORE/SAP/src/sapFsm.c | 66 +- .../qcacld-2.0/CORE/SAP/src/sapModule.c | 28 + .../CORE/SERVICES/COMMON/ol_txrx_dbg.h | 5 +- .../SERVICES/COMMON/wlan_tgt_def_config.h | 4 - .../SERVICES/COMMON/wlan_tgt_def_config_hl.h | 5 - .../CORE/SERVICES/COMMON/wmi_unified.h | 2 + .../CORE/SERVICES/COMMON/wmi_version.h | 2 +- .../CORE/SERVICES/HIF/PCIe/if_pci.c | 48 +- .../HIF/sdio/linux/native_sdio/src/hif.c | 2 +- .../qcacld-2.0/CORE/SERVICES/HTC/htc_send.c | 30 +- .../CORE/SERVICES/WMA/regdomain_common.h | 19 +- .../qcacld-2.0/CORE/SERVICES/WMA/wma.c | 927 +++++++++- .../qcacld-2.0/CORE/SERVICES/WMA/wma.h | 13 +- .../CORE/SERVICES/WMI/wmi_unified.c | 93 +- .../staging/qcacld-2.0/CORE/SME/inc/csrApi.h | 10 +- .../qcacld-2.0/CORE/SME/inc/oemDataApi.h | 3 +- .../qcacld-2.0/CORE/SME/inc/smeInternal.h | 13 + .../staging/qcacld-2.0/CORE/SME/inc/sme_Api.h | 83 + .../qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c | 122 +- .../CORE/SME/src/csr/csrNeighborRoam.c | 5 +- .../qcacld-2.0/CORE/SME/src/csr/csrUtil.c | 4 +- .../CORE/SME/src/oemData/oemDataApi.c | 75 +- .../qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c | 65 +- .../qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c | 46 +- .../CORE/SME/src/sme_common/sme_Api.c | 583 +++++- .../SVC/src/logging/wlan_logging_sock_svc.c | 3 +- .../CORE/SYS/legacy/src/utils/src/macTrace.c | 13 +- .../CORE/SYS/legacy/src/utils/src/parserApi.c | 33 +- .../qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h | 11 +- .../qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h | 1 + .../staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h | 17 +- .../qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h | 2 +- .../qcacld-2.0/CORE/VOSS/inc/vos_utils.h | 2 + .../qcacld-2.0/CORE/VOSS/src/vos_api.c | 98 +- .../qcacld-2.0/CORE/VOSS/src/vos_lock.c | 99 +- .../staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c | 25 +- .../qcacld-2.0/CORE/VOSS/src/vos_nvitem.c | 25 +- .../qcacld-2.0/CORE/VOSS/src/vos_sched.c | 4 +- .../qcacld-2.0/CORE/VOSS/src/vos_sched.h | 1 + .../qcacld-2.0/CORE/VOSS/src/vos_utils.c | 16 + .../CORE/WDA/inc/legacy/halMsgApi.h | 3 +- .../qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h | 11 +- drivers/staging/qcacld-2.0/Kbuild | 3 +- .../staging/qcacld-2.0/wcnss/inc/wlan_nv.h | 4 +- 109 files changed, 5540 insertions(+), 1487 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c index 82858c140f46..c96f7be08a18 100644 --- a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c @@ -50,6 +50,8 @@ #include /* ol_tx_msdu_id_storage */ #include +#include + #ifdef IPA_UC_OFFLOAD /* IPA Micro controler TX data packet HTT Header Preset */ /* 31 | 30 29 | 28 | 27 | 26 22 | 21 16 | 15 13 | 12 8 | 7 0 @@ -714,11 +716,13 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, unsigned int uc_tx_partition_base) { unsigned int tx_buffer_count; + unsigned int tx_buffer_count_pwr2; adf_nbuf_t buffer_vaddr; u_int32_t buffer_paddr; u_int32_t *header_ptr; u_int32_t *ring_vaddr; int return_code = 0; + uint16_t idx; /* Allocate CE Write Index WORD */ pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr = @@ -802,7 +806,33 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, ring_vaddr++; } - pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count; + /* + * Tx complete ring buffer count should be power of 2. + * So, allocated Tx buffer count should be one less than ring buffer size. + */ + tx_buffer_count_pwr2 = vos_rounddown_pow_of_two(tx_buffer_count + 1) - 1; + if (tx_buffer_count > tx_buffer_count_pwr2) { + adf_os_print("%s: Allocated Tx buffer count %d is rounded down to %d", + __func__, tx_buffer_count, tx_buffer_count_pwr2); + + /* Free over allocated buffers below power of 2 */ + for(idx = tx_buffer_count_pwr2; idx < tx_buffer_count; idx++) { + if (pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx]) { + adf_nbuf_unmap(pdev->osdev, + pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx], + ADF_OS_DMA_FROM_DEVICE); + adf_nbuf_free(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx]); + } + } + } + + if (tx_buffer_count_pwr2 < 0) { + adf_os_print("%s: Failed to round down Tx buffer count %d", + __func__, tx_buffer_count_pwr2); + goto free_tx_comp_base; + } + + pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count_pwr2; return 0; diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c index 281eb4114b89..0890e28f5ff4 100644 --- a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -1787,9 +1787,9 @@ VOS_STATUS WLANTL_Start(void *vos_ctx) VOS_STATUS WLANTL_Close(void *vos_ctx) { struct txrx_tl_shim_ctx *tl_shim; -#if defined(QCA_LL_TX_FLOW_CT) || defined(QCA_SUPPORT_TXRX_VDEV_PAUSE_LL) - u_int8_t i; -#endif /* QCA_LL_TX_FLOW_CT */ + struct tlshim_buf *cache_buf, *tmp; + struct tlshim_sta_info *sta_info; + u_int16_t i; ENTER(); tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_ctx); @@ -1821,7 +1821,19 @@ VOS_STATUS WLANTL_Close(void *vos_ctx) vos_flush_work(&tl_shim->iapp_work.deferred_work); #endif vos_flush_work(&tl_shim->cache_flush_work); - + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + sta_info = &tl_shim->sta_info[i]; + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + list_for_each_entry_safe(cache_buf, tmp, + &sta_info->cached_bufq, list) { + list_del(&cache_buf->list); + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + adf_nbuf_free(cache_buf->buf); + adf_os_mem_free(cache_buf); + adf_os_spin_lock_bh(&tl_shim->bufq_lock); + } + adf_os_spin_unlock_bh(&tl_shim->bufq_lock); + } wdi_in_pdev_detach(((pVosContextType) vos_ctx)->pdev_txrx_ctx, 1); // Delete beacon buffer hanging off tl_shim if (tl_shim->last_beacon_data) { @@ -2052,8 +2064,9 @@ WLANTL_PauseUnPauseQs(void *vos_context, v_BOOL_t flag) * * HDD will call this API to get the OL-TXRX module stats * + * Return: VOS_STATUS */ -void WLANTL_Get_llStats +VOS_STATUS WLANTL_Get_llStats ( uint8_t sessionId, char *buffer, @@ -2065,24 +2078,22 @@ void WLANTL_Get_llStats struct ol_txrx_vdev_t *vdev; if (!vos_context) { - return; + return VOS_STATUS_E_FAILURE; } tl_shim = vos_get_context(VOS_MODULE_ID_TL, vos_context); if (!tl_shim) { TLSHIM_LOGD("%s, tl_shim is NULL", __func__); - return; + return VOS_STATUS_E_FAILURE; } vdev = tl_shim->session_flow_control[sessionId].vdev; if (!vdev) { TLSHIM_LOGE("%s, vdev is NULL", __func__); - return; + return VOS_STATUS_E_FAILURE; } - ol_txrx_stats(vdev, buffer, (unsigned)length); - return; - + return ol_txrx_stats(vdev, buffer, (unsigned)length); } /*============================================================================= diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c index 26ce39279999..2385e3455e74 100644 --- a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c @@ -884,7 +884,8 @@ ol_txrx_peer_link_status_handler( return; } - TX_SCHED_DEBUG_PRINT_ALWAYS("%s: peer_num %d\n", __func__, peer_num); + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_DEBUG, + "%s: peer_num %d", __func__, peer_num); for (i = 0; i < peer_num; i++) { u_int16_t peer_limit, peer_id; diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c index 48d215d0f76f..68ca4cec2b79 100644 --- a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -2240,12 +2240,14 @@ ol_txrx_peer_display(ol_txrx_peer_handle peer, int indent) * * * to update the stats * - * Return: None + * Return: VOS_STATUS */ -void +VOS_STATUS ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, unsigned buf_len) { - snprintf(buffer, buf_len, + int ret; + + ret = snprintf(buffer, buf_len, "\nTXRX stats:\n" "\nllQueue State : %s" "\n pause %u unpause %u" @@ -2257,6 +2259,12 @@ ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, unsigned buf_len) vdev->ll_pause.q_overflow_cnt, ((vdev->ll_pause.is_q_timer_on == FALSE) ? "NOT-RUNNING" : "RUNNING")); + if (ret >= buf_len) { + VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, + "Insufficient buffer:%d, %d", buf_len, ret); + return VOS_STATUS_E_NOMEM; + } + return VOS_STATUS_SUCCESS; } #if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF diff --git a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c index 574cacc3e2a1..593edf0b42f5 100644 --- a/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c @@ -69,6 +69,7 @@ #include "if_ath_sdio.h" #endif #include "epping_main.h" +#include "wlan_hdd_memdump.h" #include "epping_internal.h" #ifdef TIMER_MANAGER @@ -214,6 +215,7 @@ void epping_exit(v_CONTEXT_t pVosContext) __func__); return; } + memdump_deinit(); if (pEpping_ctx->epping_adapter) { epping_destroy_adapter(pEpping_ctx->epping_adapter); pEpping_ctx->epping_adapter = NULL; @@ -416,6 +418,7 @@ int epping_wlan_startup(struct device *parent_dev, v_VOID_t *hif_sc) } } #endif /* HIF_PCI */ + memdump_init(); EPPING_LOG(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__); complete(&pEpping_ctx->wlan_start_comp); return ret; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h index 45284c7dae17..2c8e556f96f0 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -268,7 +268,7 @@ enum { QCASAP_SET_RADAR_DBG, }; -int iw_softap_get_channel_list(struct net_device *dev, +int iw_get_channel_list(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h index 7a965e9cd2f8..8a500506fe30 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -46,6 +46,9 @@ In Rome case, IBSS uses the 2nd peer as bss peer */ #define IBSS_BROADCAST_STAID 1 +/* Timeout in ms for peer info request completion */ +#define IBSS_PEER_INFO_REQ_TIMOEUT 1000 + typedef enum { /** Not associated in Infra or participating in an IBSS / Ad-hoc network.*/ @@ -150,9 +153,11 @@ int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType ); int hdd_set_csr_auth_type( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType ); VOS_STATUS hdd_roamRegisterTDLSSTA(hdd_adapter_t *pAdapter, const tANI_U8 *peerMac, tANI_U16 staId, - tANI_U8 ucastSig); + tANI_U8 ucastSig, uint8_t qos); void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter); +VOS_STATUS hdd_roamDeregisterTDLSSTA(hdd_adapter_t *adapter, uint8_t staId); + void hdd_SendPeerStatusIndToOemApp(v_MACADDR_t *peerMac, tANI_U8 peerStatus, tANI_U8 peerTimingMeasCap, diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h index 71e679a0b3f9..4958056d7f38 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1094,8 +1094,13 @@ enum #define CFG_ROAM_RESCAN_RSSI_DIFF_MAX (100) #define CFG_ROAM_RESCAN_RSSI_DIFF_DEFAULT (5) +/* + * This parameter is the continuous packets dropping threshold that will trigger + * kickout peer event from fw. + * MIN value will disable the kickout feature. + */ #define CFG_DROPPED_PKT_DISCONNECT_TH_NAME "gDroppedPktDisconnectTh" -#define CFG_DROPPED_PKT_DISCONNECT_TH_MIN (48) +#define CFG_DROPPED_PKT_DISCONNECT_TH_MIN (0) #define CFG_DROPPED_PKT_DISCONNECT_TH_MAX (1024) #define CFG_DROPPED_PKT_DISCONNECT_TH_DEFAULT (512) @@ -2648,12 +2653,12 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_SET_TXPOWER_LIMIT2G_NAME "TxPower2g" #define CFG_SET_TXPOWER_LIMIT2G_MIN ( 0 ) #define CFG_SET_TXPOWER_LIMIT2G_MAX ( 30 ) -#define CFG_SET_TXPOWER_LIMIT2G_DEFAULT ( 15 ) +#define CFG_SET_TXPOWER_LIMIT2G_DEFAULT ( 30 ) #define CFG_SET_TXPOWER_LIMIT5G_NAME "TxPower5g" #define CFG_SET_TXPOWER_LIMIT5G_MIN ( 0 ) #define CFG_SET_TXPOWER_LIMIT5G_MAX ( 30 ) -#define CFG_SET_TXPOWER_LIMIT5G_DEFAULT ( 15 ) +#define CFG_SET_TXPOWER_LIMIT5G_DEFAULT ( 30 ) #ifdef QCA_LL_TX_FLOW_CT /* Default, single interface case flow control parameters */ @@ -2869,6 +2874,7 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_IPA_UC_OFFLOAD_ENABLED_MAX ( 1 ) #define CFG_IPA_UC_OFFLOAD_ENABLED_DEFAULT ( 0 ) +/* IpaUcTxBufCount should be power of 2 */ #define CFG_IPA_UC_TX_BUF_COUNT_NAME "IpaUcTxBufCount" #define CFG_IPA_UC_TX_BUF_COUNT_MIN ( 0 ) #define CFG_IPA_UC_TX_BUF_COUNT_MAX ( 2048 ) @@ -2879,6 +2885,7 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_IPA_UC_TX_BUF_SIZE_MAX ( 4096 ) #define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT ( 2048 ) +/* IpaUcRxIndRingCount should be power of 2 */ #define CFG_IPA_UC_RX_IND_RING_COUNT_NAME "IpaUcRxIndRingCount" #define CFG_IPA_UC_RX_IND_RING_COUNT_MIN ( 0 ) #define CFG_IPA_UC_RX_IND_RING_COUNT_MAX ( 2048 ) @@ -2909,9 +2916,15 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_WLAN_LOGGING_NUM_BUF_DEFAULT ( 256 ) #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ +/* + * Sifs burst feature configuration + * gEnableSifsBurst = 0 means sifs burst toally disable + * gEnableSifsBurst = 1 means sifs burst enabled but disabled for legacy mode + * gEnableSifsBurst = 3 means sifs burst enabled and also for legacy mode + */ #define CFG_ENABLE_SIFS_BURST "gEnableSifsBurst" #define CFG_ENABLE_SIFS_BURST_MIN ( 0 ) -#define CFG_ENABLE_SIFS_BURST_MAX ( 1 ) +#define CFG_ENABLE_SIFS_BURST_MAX (3) #define CFG_ENABLE_SIFS_BURST_DEFAULT ( 0 ) #ifdef WLAN_FEATURE_LPSS @@ -3384,6 +3397,22 @@ enum dot11p_mode { #define CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX (-30) #define CFG_FIRST_SCAN_BUCKET_THRESHOLD_DEFAULT (-30) +/* + * sap tx leakage threshold + * customer can set this value from 100 to 1000 which means + * sap tx leakage threshold is -10db to -100db + */ +#define CFG_SAP_TX_LEAKAGE_THRESHOLD_NAME "gsap_tx_leakage_threshold" +#define CFG_SAP_TX_LEAKAGE_THRESHOLD_MIN (100) +#define CFG_SAP_TX_LEAKAGE_THRESHOLD_MAX (1000) +#define CFG_SAP_TX_LEAKAGE_THRESHOLD_DEFAULT (310) + +#define CFG_TGT_GTX_USR_CFG_NAME "tgt_gtx_usr_cfg" +#define CFG_TGT_GTX_USR_CFG_MIN (0) +#define CFG_TGT_GTX_USR_CFG_MAX (32) +#define CFG_TGT_GTX_USR_CFG_DEFAULT (32) + + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3968,7 +3997,7 @@ typedef struct v_U32_t wlanLoggingNumBuf; #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ - v_BOOL_t enableSifsBurst; + v_U8_t enableSifsBurst; #ifdef WLAN_FEATURE_LPSS v_BOOL_t enablelpasssupport; @@ -4080,6 +4109,9 @@ typedef struct uint16_t max_mgmt_tx_fail_count; int8_t first_scan_bucket_threshold; uint8_t ht_mpdu_density; + uint16_t sap_tx_leakage_threshold; + /* parameter to control GTX */ + uint32_t tgt_gtx_usr_cfg; } hdd_config_t; #ifdef WLAN_FEATURE_MBSSID diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h index 4b78b372f643..48b24e0486cb 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -1466,6 +1466,7 @@ enum qca_wlan_vendor_config { QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM, QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, + QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = @@ -1738,4 +1739,22 @@ backported_cfg80211_vendor_event_alloc(struct wiphy *wiphy, #define cfg80211_vendor_event_alloc backported_cfg80211_vendor_event_alloc #endif +#if defined(CFG80211_DISCONNECTED_V2) || \ +(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) +static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, + bool from_ap, + int reason) +{ + cfg80211_disconnected(dev, reason, NULL, 0, + from_ap, GFP_KERNEL); +} +#else +static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, + bool from_ap, + int reason) +{ + cfg80211_disconnected(dev, reason, NULL, 0, + GFP_KERNEL); +} +#endif #endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h index aeb1a6136ea3..65aed10d6466 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h @@ -126,7 +126,7 @@ #define WLAN_WAIT_TIME_SESSIONOPENCLOSE 15000 #define WLAN_WAIT_TIME_ABORTSCAN 2000 #define WLAN_WAIT_TIME_EXTSCAN 1000 -#define WLAN_WAIT_TIME_LL_STATS 5000 +#define WLAN_WAIT_TIME_LL_STATS 800 #define WLAN_WAIT_SMPS_FORCE_MODE 500 @@ -231,6 +231,9 @@ #define HDD_MAC_ADDR_LEN 6 #define HDD_SESSION_ID_ANY 50 //This should be same as CSR_SESSION_ID_ANY +/* This should be same as CSR_ROAM_SESSION_MAX */ +#define HDD_SESSION_MAX 5 + #define HDD_MIN_TX_POWER (-100) // minimum tx power #define HDD_MAX_TX_POWER (+100) // maximum tx power @@ -707,6 +710,8 @@ struct hdd_station_ctx /*Save the wep/wpa-none keys*/ tCsrRoamSetKey ibss_enc_key; + tSirPeerInfoRspParams ibss_peer_info; + v_BOOL_t hdd_ReassocScenario; /* STA ctx debug variables */ @@ -986,6 +991,8 @@ struct hdd_adapter_s eHalStatus tdlsAddStaStatus; #endif + struct completion ibss_peer_info_comp; + /* Track whether the linkup handling is needed */ v_BOOL_t isLinkUpSvcNeeded; @@ -1634,6 +1641,7 @@ struct hdd_context_s vos_timer_t memdump_cleanup_timer; struct mutex memdump_lock; bool memdump_in_progress; + bool memdump_init_done; #endif /* WLAN_FEATURE_MEMDUMP */ /* number of rf chains supported by target */ @@ -1661,6 +1669,11 @@ struct hdd_context_s uint8_t supp_5g_chain_mask; /* Current number of TX X RX chains being used */ enum antenna_mode current_antenna_mode; + /* + * place to store FTM capab of target. This allows changing of FTM capab + * at runtime and intersecting it with target capab before updating. + */ + uint32_t fine_time_meas_cap_target; }; /*--------------------------------------------------------------------------- @@ -1766,6 +1779,7 @@ int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, tANI_U8 s void hdd_ipv6_notifier_work_queue(struct work_struct *work); #endif +v_MACADDR_t* hdd_wlan_get_ibss_mac_addr_from_staid(hdd_adapter_t *pAdapter, v_U8_t staIdx); void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx); @@ -1935,9 +1949,9 @@ wlan_hdd_clean_tx_flow_control_timer(hdd_context_t *hddctx, #endif void hdd_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 * resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp); + tCsrRoamInfo *roam_info, const u8 *req_ie, + size_t req_ie_len, const u8 * resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp); int wlan_hdd_init_tx_rx_histogram(hdd_context_t *pHddCtx); void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *pHddCtx); @@ -1946,8 +1960,14 @@ void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *pHddCtx); void hdd_runtime_suspend_init(hdd_context_t *); void hdd_runtime_suspend_deinit(hdd_context_t *); +void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind); +hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx, + uint32_t sme_session_id); int wlan_hdd_update_txrx_chain_mask(hdd_context_t *hdd_ctx, uint8_t chain_mask); +void +hdd_get_ibss_peer_info_cb(v_VOID_t *pUserData, + tSirPeerInfoRspParams *pPeerInfo); #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h index c3fa8391a9ea..c56e384c948d 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_memdump.h @@ -64,7 +64,7 @@ enum qca_wlan_vendor_attr_memory_dump { #define FW_DRAM_LOCATION 0x00400000 #define FW_MEM_DUMP_REQ_ID 1 #define FW_MEM_DUMP_NUM_SEG 1 -#define MEMDUMP_COMPLETION_TIME_MS 5000 +#define MEMDUMP_COMPLETION_TIME_MS 800 int memdump_init(void); void memdump_deinit(void); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h index 7d9f01b7b716..249674dd3059 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -127,13 +127,14 @@ int hdd_setP2pPs( struct net_device *dev, void *msgData ); int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command ); int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command ); -void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, +void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, tANI_U32 nFrameLength, tANI_U8* pbFrames, tANI_U8 frameType, tANI_U32 rxChan, tANI_S8 rxRssi); void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ); void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess ); +void hdd_send_action_cnf_cb(uint32_t session_id, bool status); int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter); void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h index 86558bfbd95b..b181f130e5aa 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h @@ -217,7 +217,6 @@ typedef struct { tANI_U32 discovery_sent_cnt; tANI_S8 ap_rssi; struct _hddTdlsPeer_t *curr_candidate; - struct work_struct implicit_setup; v_U32_t magic; } tdlsCtx_t; @@ -237,6 +236,7 @@ typedef struct _hddTdlsPeer_t { tANI_U16 rx_pkt; tANI_U8 uapsdQueues; tANI_U8 maxSp; + uint8_t qos; tANI_U8 isBufSta; tANI_U8 isOffChannelSupported; tANI_U8 supported_channels_len; @@ -321,7 +321,8 @@ int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, const u8 *mac, tCsrStaParams *StaParams, tANI_BOOLEAN isBufSta, - tANI_BOOLEAN isOffChannelSupported); + tANI_BOOLEAN isOffChannelSupported, + bool is_qos_wmm_sta); int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, const u8 *mac, tANI_S8 rxRssi); @@ -379,10 +380,7 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, hddTdlsPeer_t *curr_peer, tANI_U16 reason); -#ifdef CONFIG_TDLS_IMPLICIT -void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t *pHddTdlsCtx, - hddTdlsPeer_t *curr_candidate); -#endif +void wlan_hdd_tdls_implicit_send_discovery_request(tdlsCtx_t *pHddTdlsCtx); int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, const uint8_t *mac, @@ -451,6 +449,10 @@ static inline int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx, { return 0; } +static inline void +wlan_hdd_tdls_implicit_send_discovery_request(void *pHddTdlsCtx) +{ +} #endif #endif // __HDD_TDSL_H diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h index 7fe2aa6c5e2c..c39d27f81aeb 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -105,6 +105,7 @@ struct hdd_tgt_cfg { v_U8_t lpss_support; #endif uint8_t ap_arpns_support; + uint32_t fine_time_measurement_cap; }; struct hdd_dfs_radar_ind { diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h index 0dd4beaf2eb4..e18f7f25b663 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -145,12 +145,6 @@ typedef enum HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK = 1, } hdd_wlan_wmm_ts_info_ack_policy_e; -/** vendor element ID */ -#define IE_EID_VENDOR ( 221 ) /* 0xDD */ -#define IE_LEN_SIZE 1 -#define IE_EID_SIZE 1 -#define IE_VENDOR_OUI_SIZE 4 - /** Maximum Length of WPA/RSN IE */ #define MAX_WPA_RSN_IE_LEN 40 @@ -340,6 +334,8 @@ typedef struct hdd_wext_state_s v_BOOL_t isESEConnection; eCsrAuthType collectedAuthType; /* Collected from ALL SIOCSIWAUTH Ioctls. Will be negotiatedAuthType - in tCsrProfile */ #endif + /* Wireless statistics */ + struct iw_statistics iw_stats; }hdd_wext_state_t; typedef struct ccp_freq_chan_map_s{ @@ -369,7 +365,7 @@ extern int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, extern void hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu, char *extra); -extern void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, +extern int hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, char *buffer, v_U16_t buf_len); extern void hdd_wlan_dump_stats(hdd_adapter_t *pAdapter, int value); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c index 6ba25063e076..20d320eacf3f 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -109,6 +109,23 @@ v_U8_t ccpRSNOui08[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; #define BEACON_FRAME_IES_OFFSET 12 +#define NUM_BITS_IN_INT 32 +static const int beacon_filter_table[] = { + SIR_MAC_DS_PARAM_SET_EID, + SIR_MAC_ERP_INFO_EID, + SIR_MAC_EDCA_PARAM_SET_EID, + SIR_MAC_QOS_CAPABILITY_EID, + SIR_MAC_CHNL_SWITCH_ANN_EID, + SIR_MAC_HT_INFO_EID, +#if defined WLAN_FEATURE_VOWIFI + SIR_MAC_PWR_CONSTRAINT_EID, +#endif +#ifdef WLAN_FEATURE_11AC + SIR_MAC_VHT_OPMODE_EID, + SIR_MAC_VHT_OPERATION_EID, +#endif +}; + static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, @@ -256,6 +273,48 @@ static inline void hdd_connSaveConnectedBssType( hdd_station_ctx_t *pHddStaCtx, } +/** + * hdd_unset_beacon_filter() - remove beacon filter + * @adapter: Pointer to the hdd adapter + * + * Return: 0 on success and errno on failure + */ +static int hdd_unset_beacon_filter(hdd_adapter_t *adapter) +{ + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + + vos_status = sme_unset_beacon_filter(adapter->sessionId); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + return -EFAULT; + + return 0; +} + +/** + * hdd_set_beacon_filter() - set beacon filter + * @adapter: Pointer to the hdd adapter + * + * Return: 0 on success and errno on failure + */ +static int hdd_set_beacon_filter(hdd_adapter_t *adapter) +{ + int i; + uint32_t ie_map[8] = {0}; + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + + for (i = 0; i < ARRAY_SIZE(beacon_filter_table); i++) { + __set_bit((beacon_filter_table[i] - 1), + (unsigned long int *)ie_map); + } + vos_status = sme_set_beacon_filter(adapter->sessionId, ie_map); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, "%s: failed to set beacon filter", + __func__); + return -EFAULT; + } + return 0; +} + static void hdd_connSaveConnectInfo(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType) @@ -844,8 +903,9 @@ static VOS_STATUS hdd_roamDeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId // Need to cleanup all queues only if the last peer leaves if (eConnectionState_IbssDisconnected == pHddStaCtx->conn_info.connState) { - netif_tx_disable(pAdapter->dev); - netif_carrier_off(pAdapter->dev); + /* Do not set the carrier off when the last peer leaves. + * We will set the carrier off while stopping the IBSS. + */ hdd_disconnect_tx_rx(pAdapter); } else @@ -913,7 +973,7 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * /* HDD has initiated disconnect, do not send disconnect indication * to kernel. Sending disconnected event to kernel for userspace - * initiated disconnect will be handled by hdd_DisConnectHandler call + * initiated disconnect will be handled by diconnect handler call * to cfg80211_disconnected */ if ((eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState) || @@ -959,12 +1019,12 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * pr_info( "wlan: disconnected due to poor signal, rssi is %d dB\n", pRoamInfo->rxRssi); - cfg80211_disconnected(dev, pRoamInfo->reasonCode, NULL, 0, - GFP_KERNEL); + wlan_hdd_cfg80211_indicate_disconnect(dev, true, + WLAN_REASON_UNSPECIFIED); } else - cfg80211_disconnected(dev, WLAN_REASON_UNSPECIFIED, NULL, 0, - GFP_KERNEL); + wlan_hdd_cfg80211_indicate_disconnect(dev, true, + WLAN_REASON_UNSPECIFIED); hddLog(VOS_TRACE_LEVEL_INFO_HIGH, FL("sent disconnected event to nl80211, reason code %d"), @@ -1036,6 +1096,10 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * #if defined(WLAN_FEATURE_VOWIFI_11R) sme_FTReset(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId); #endif + if (hdd_unset_beacon_filter(pAdapter) != 0) + hddLog(LOGE, + FL("hdd_unset_beacon_filter() failed")); + if (eCSR_ROAM_IBSS_LEAVE == roamStatus) { v_U8_t i; @@ -1573,6 +1637,7 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs hdd_adapter_t *sap_adapter; hdd_ap_ctx_t *hdd_ap_ctx; uint8_t default_sap_channel = 6; + u16 reason_code; #ifdef WLAN_FEATURE_ROAM_OFFLOAD if (pRoamInfo && pRoamInfo->roamSynchInProgress) { /* change logging before release */ @@ -1611,6 +1676,11 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs // Save the connection info from CSR... hdd_connSaveConnectInfo( pAdapter, pRoamInfo, eCSR_BSS_TYPE_INFRASTRUCTURE ); + + if (hdd_set_beacon_filter(pAdapter) != 0) + hddLog(LOGE, + FL("hdd_set_beacon_filter() failed")); + #ifdef FEATURE_WLAN_WAPI if ( pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE || pRoamInfo->u.pConnectedProfile->AuthType == eCSR_AUTH_TYPE_WAPI_WAI_PSK ) @@ -1831,7 +1901,7 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs hddLog(LOG1, "%s ft_carrier_on is %d, sending connect " "indication", __FUNCTION__, ft_carrier_on); - hdd_connect_result(dev, pRoamInfo->bssid, + hdd_connect_result(dev, pRoamInfo->bssid, pRoamInfo, pFTAssocReq, assocReqlen, pFTAssocRsp, assocRsplen, WLAN_STATUS_SUCCESS, @@ -1861,12 +1931,12 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs { hddLog(VOS_TRACE_LEVEL_INFO, - "%s: sending connect indication to nl80211:for bssid " MAC_ADDRESS_STR " reason:%d and Status:%d", + "%s: sending connect indication to nl80211:for bssid " MAC_ADDRESS_STR " result:%d and Status:%d", __func__, MAC_ADDR_ARRAY(pRoamInfo->bssid), roamResult, roamStatus); /* inform connect result to nl80211 */ - hdd_connect_result(dev, pRoamInfo->bssid, + hdd_connect_result(dev, pRoamInfo->bssid, pRoamInfo, reqRsnIe, reqRsnLength, rspRsnIe, rspRsnLength, WLAN_STATUS_SUCCESS, @@ -1978,12 +2048,12 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); if (pRoamInfo) pr_info("wlan: connection failed with " MAC_ADDRESS_STR - " reason:%d and Status:%d\n", + " result:%d and Status:%d\n", MAC_ADDR_ARRAY(pRoamInfo->bssid), roamResult, roamStatus); else pr_info("wlan: connection failed with " MAC_ADDRESS_STR - " reason:%d and Status:%d\n", + " result:%d and Status:%d\n", MAC_ADDR_ARRAY(pWextState->req_bssId), roamResult, roamStatus); @@ -2048,56 +2118,41 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs { if (pRoamInfo) hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: send connect failure to nl80211: for bssid " MAC_ADDRESS_STR" reason:%d and Status:%d " , + "%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); + roamResult, roamStatus, pRoamInfo->reasonCode); else hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: connect failed: for bssid " MAC_ADDRESS_STR " reason:%d and Status:%d " , + "%s: connect failed: for bssid " MAC_ADDRESS_STR " result:%d and Status:%d " , __func__, MAC_ADDR_ARRAY(pWextState->req_bssId), roamResult, roamStatus); - /* Clear the roam profile */ - hdd_clearRoamProfileIe(pAdapter); - /* inform association failure event to nl80211 */ if ( eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL == roamResult ) { if (pRoamInfo) - hdd_connect_result(dev, pRoamInfo->bssid, + hdd_connect_result(dev, pRoamInfo->bssid, NULL, NULL, 0, NULL, 0, WLAN_STATUS_ASSOC_DENIED_UNSPEC, GFP_KERNEL); else - hdd_connect_result(dev, pWextState->req_bssId, + hdd_connect_result(dev, pWextState->req_bssId, NULL, NULL, 0, NULL, 0, WLAN_STATUS_ASSOC_DENIED_UNSPEC, GFP_KERNEL); } else { - if (pRoamInfo) { - eCsrAuthType authType = - pWextState->roamProfile.AuthType.authType[0]; - v_BOOL_t isWep = (authType == eCSR_AUTH_TYPE_OPEN_SYSTEM) || - (authType == eCSR_AUTH_TYPE_SHARED_KEY); - - /* In case of OPEN-WEP or SHARED-WEP authentication, - * send exact protocol reason code. This enables user - * applications to reconnect the station with correct - * configuration. - */ - hdd_connect_result(dev, pRoamInfo->bssid, - NULL, 0, NULL, 0, - isWep ? pRoamInfo->reasonCode : - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - } else - hdd_connect_result(dev, pWextState->req_bssId, - NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); + reason_code = WLAN_STATUS_UNSPECIFIED_FAILURE; + if (pRoamInfo && pRoamInfo->reasonCode) + reason_code = (u16)pRoamInfo->reasonCode; + + cfg80211_connect_result(dev, pWextState->req_bssId, + NULL, 0, NULL, 0, reason_code, GFP_KERNEL); } + /* Clear the roam profile */ + hdd_clearRoamProfileIe(pAdapter); + } if (pRoamInfo) { @@ -2287,6 +2342,10 @@ static void hdd_RoamIbssIndicationHandler( hdd_adapter_t *pAdapter, pAdapter->dev->name, (int)pRoamInfo->pBssDesc->channelId); #else + + netif_carrier_on(pAdapter->dev); + netif_tx_start_all_queues(pAdapter->dev); + cfg80211_ibss_joined(pAdapter->dev, bss->bssid, GFP_KERNEL); #endif cfg80211_put_bss( @@ -2788,7 +2847,7 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t ===========================================================================*/ VOS_STATUS hdd_roamRegisterTDLSSTA(hdd_adapter_t *pAdapter, const tANI_U8 *peerMac, tANI_U16 staId, - tANI_U8 ucastSig) + tANI_U8 ucastSig, uint8_t qos) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; @@ -2819,8 +2878,7 @@ VOS_STATUS hdd_roamRegisterTDLSSTA(hdd_adapter_t *pAdapter, vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent ); /* set the QoS field appropriately ..*/ - (hdd_wmm_is_active(pAdapter)) ? (staDesc.ucQosEnabled = 1) - : (staDesc.ucQosEnabled = 0) ; + staDesc.ucQosEnabled = qos; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "HDD register TL QoS_enabled=%d", staDesc.ucQosEnabled ); @@ -2880,7 +2938,7 @@ VOS_STATUS hdd_roamRegisterTDLSSTA(hdd_adapter_t *pAdapter, return( vosStatus ); } -static VOS_STATUS hdd_roamDeregisterTDLSSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) +VOS_STATUS hdd_roamDeregisterTDLSSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) { VOS_STATUS vosStatus; vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId ); @@ -3182,7 +3240,9 @@ hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter, curr_peer->isForcedPeer, pRoamInfo->reasonCode); } - wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer); + pHddTdlsCtx->curr_candidate = curr_peer; + + wlan_hdd_tdls_implicit_send_discovery_request(pHddTdlsCtx); } status = eHAL_STATUS_SUCCESS; } @@ -3969,22 +4029,9 @@ hdd_smeRoamCallback(void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, } break; #endif - - case eCSR_ROAM_INDICATE_MGMT_FRAME: - hdd_indicateMgmtFrame( pAdapter, - pRoamInfo->nFrameLength, - pRoamInfo->pbFrames, - pRoamInfo->frameType, - pRoamInfo->rxChan, - pRoamInfo->rxRssi ); - break; case eCSR_ROAM_REMAIN_CHAN_READY: hdd_remainChanReadyHandler( pAdapter ); break; - case eCSR_ROAM_SEND_ACTION_CNF: - hdd_sendActionCnf( pAdapter, - (roamResult == eCSR_ROAM_RESULT_NONE) ? TRUE : FALSE ); - break; #ifdef FEATURE_WLAN_TDLS case eCSR_ROAM_TDLS_STATUS_UPDATE: halStatus = hdd_RoamTdlsStatusUpdateHandler( pAdapter, pRoamInfo, diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c index 52be11dd330f..2904284e8f9c 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c @@ -4194,6 +4194,21 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_FIRST_SCAN_BUCKET_THRESHOLD_DEFAULT, CFG_FIRST_SCAN_BUCKET_THRESHOLD_MIN, CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX), + + REG_VARIABLE(CFG_SAP_TX_LEAKAGE_THRESHOLD_NAME, + WLAN_PARAM_Integer, + hdd_config_t, sap_tx_leakage_threshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_TX_LEAKAGE_THRESHOLD_DEFAULT, + CFG_SAP_TX_LEAKAGE_THRESHOLD_MIN, + CFG_SAP_TX_LEAKAGE_THRESHOLD_MAX), + + REG_VARIABLE(CFG_TGT_GTX_USR_CFG_NAME, WLAN_PARAM_Integer, + hdd_config_t, tgt_gtx_usr_cfg, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TGT_GTX_USR_CFG_DEFAULT, + CFG_TGT_GTX_USR_CFG_MIN, + CFG_TGT_GTX_USR_CFG_MAX), }; #ifdef WLAN_FEATURE_MBSSID @@ -4879,6 +4894,9 @@ void print_hdd_cfg(hdd_context_t *pHddCtx) hddLog(LOG2, "Name = [gIdleTimeConc] Value = [%u]", pHddCtx->cfg_ini->idle_time_conc); + hddLog(LOG2, "Name = [%s] Value = [%u]", + CFG_TGT_GTX_USR_CFG_NAME, + pHddCtx->cfg_ini->tgt_gtx_usr_cfg); } #define CFG_VALUE_MAX_LEN 256 @@ -5720,7 +5738,7 @@ VOS_STATUS hdd_hex_string_to_u16_array(char *str, uint16_t *int_array, uint8_t *len, uint8_t int_array_max_len) { char *s = str; - int val = 0; + uint32_t val = 0; if (str == NULL || int_array == NULL || len == NULL) return VOS_STATUS_E_INVAL; @@ -6433,6 +6451,15 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) fStatus = FALSE; hddLog(LOGE, "Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"); } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TGT_GTX_USR_CFG, + pConfig->tgt_gtx_usr_cfg, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_TGT_GTX_USR_CFG to CCM"); + } + return fStatus; } diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c index df76d87a0bfe..1c9405cfd568 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -8231,6 +8231,7 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, u32 modulated_dtim; u16 stats_avg_factor; u32 guard_time; + u32 ftm_capab; eHalStatus status; if (VOS_FTM_MODE == hdd_get_conparam()) { @@ -8251,6 +8252,19 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, return -EINVAL; } + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) { + ftm_capab = nla_get_u32(tb[ + QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]); + pHddCtx->cfg_ini->fine_time_meas_cap = + pHddCtx->fine_time_meas_cap_target & ftm_capab; + sme_update_fine_time_measurement_capab(pHddCtx->hHal, + pHddCtx->cfg_ini->fine_time_meas_cap); + hddLog(LOG1, + "FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x", + ftm_capab, pHddCtx->fine_time_meas_cap_target, + pHddCtx->cfg_ini->fine_time_meas_cap); + } + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) { modulated_dtim = nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]); @@ -9520,8 +9534,7 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = .info.vendor_id = QCA_NL80211_VENDOR_ID, .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | - WIPHY_VENDOR_CMD_NEED_NETDEV | - WIPHY_VENDOR_CMD_NEED_RUNNING, + WIPHY_VENDOR_CMD_NEED_NETDEV, .doit = is_driver_dfs_capable }, @@ -10185,7 +10198,11 @@ int wlan_hdd_cfg80211_init(struct device *dev, } wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - if (true == hdd_is_5g_supported(pHddCtx)) + if (true == hdd_is_5g_supported(pHddCtx) && + ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) || + (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) || + (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) || + (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) { wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; } @@ -10315,6 +10332,11 @@ void wlan_hdd_cfg80211_register_frames(hdd_adapter_t* pAdapter) v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4); ENTER(); + /* Register frame indication call back */ + sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame); + + /* Register for p2p ack indication */ + sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb); /* Right now we are registering these frame when driver is getting initialized. Once we will move to 2.6.37 kernel, in which we have @@ -10899,6 +10921,8 @@ int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter) return -ENOMEM; } + wlan_hdd_add_extra_ie(pHostapdAdapter, genie, &total_ielen, + WLAN_EID_VHT_TX_POWER_ENVELOPE); if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie, &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE)) { @@ -12425,10 +12449,6 @@ static int __wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, TRACE_CODE_HDD_CFG80211_STOP_AP, pAdapter->sessionId, pAdapter->device_mode)); - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) - return ret; if (VOS_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); @@ -12444,6 +12464,20 @@ static int __wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, hdd_device_mode_to_string(pAdapter->device_mode), pAdapter->device_mode); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + if (pHddCtx->isUnloadInProgress) { + /* + * Unloading the driver so free the memory for ch_list, + * otherwise it will result in memory leak + */ + if (pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) + vos_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list); + } + return ret; + } + status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) { staAdapter = pAdapterNode->pAdapter; @@ -13564,6 +13598,7 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, tCsrStaParams StaParams = {0}; tANI_U8 isBufSta = 0; tANI_U8 isOffChannelSupported = 0; + bool is_qos_wmm_sta = false; #endif int ret; @@ -13737,9 +13772,18 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, } } + if (pHddCtx->cfg_ini->fEnableTDLSWmmMode && + (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))) + is_qos_wmm_sta = true; + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("%s: TDLS Peer is QOS capable is_qos_wmm_sta= %d HTcapPresent = %d"), + __func__, is_qos_wmm_sta, StaParams.htcap_present); + status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac, &StaParams, isBufSta, - isOffChannelSupported); + isOffChannelSupported, + is_qos_wmm_sta); if (VOS_STATUS_SUCCESS != status) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("wlan_hdd_tdls_set_peer_caps failed!")); @@ -15344,6 +15388,7 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, hdd_adapter_t *con_sap_adapter; uint16_t con_dfs_ch; bool is_p2p_scan = false; + uint8_t num_chan = 0; ENTER(); @@ -15550,14 +15595,25 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, } for (i = 0, len = 0; i < request->n_channels ; i++ ) { - channelList[i] = request->channels[i]->hw_value; - len += snprintf(chList+len, 5, "%d ", channelList[i]); + if (!vos_is_dsrc_channel(vos_chan_to_freq( + request->channels[i]->hw_value))) { + channelList[num_chan] = request->channels[i]->hw_value; + len += snprintf(chList+len, 5, "%d ", channelList[i]); + num_chan++; + } } hddLog(VOS_TRACE_LEVEL_INFO, "Channel-List: %s", chList); } - scanRequest.ChannelInfo.numOfChannels = request->n_channels; + + if (!num_chan) { + hddLog(LOGE, FL("Received zero non-dsrc channels")); + status = -EINVAL; + goto free_mem; + } + + scanRequest.ChannelInfo.numOfChannels = num_chan; scanRequest.ChannelInfo.ChannelList = channelList; /* set requestType to full scan */ @@ -15755,6 +15811,14 @@ void hdd_select_cbmode(hdd_adapter_t *pAdapter, v_U8_t operationChannel, iniDot11Mode); *vht_channel_width = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->vhtChannelWidth; + /* + * In IBSS mode while operating in 2.4 GHz, + * the device will be configured to CBW 20 + */ + if ((WLAN_HDD_IBSS == pAdapter->device_mode) && + (SIR_11B_CHANNEL_END >= operationChannel)) + *vht_channel_width = eHT_CHANNEL_WIDTH_20MHZ; + switch ( iniDot11Mode ) { case eHDD_DOT11_MODE_AUTO: @@ -17003,11 +17067,6 @@ static int __wlan_hdd_cfg80211_connect( struct wiphy *wiphy, if (0 != status) return status; - if (vos_max_concurrent_connections_reached()) { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Reached max concurrent connections")); - return -ECONNREFUSED; - } - #if defined(FEATURE_WLAN_LFR) && defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) wlan_hdd_disable_roaming(pAdapter); #endif @@ -17030,6 +17089,12 @@ static int __wlan_hdd_cfg80211_connect( struct wiphy *wiphy, return -EALREADY; } + /* Check for max concurrent connections after doing disconnect if any */ + if (vos_max_concurrent_connections_reached()) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Reached max concurrent connections")); + return -ECONNREFUSED; + } + /*initialise security parameters*/ status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); @@ -17150,8 +17215,9 @@ int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) * is handled by __cfg80211_disconnect call to __cfg80211_disconnected */ hddLog(LOG1, FL("Send disconnected event to userspace")); - cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, - NULL, 0, GFP_KERNEL); + + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false, + WLAN_REASON_UNSPECIFIED); #endif EXIT(); @@ -17647,6 +17713,7 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); int status; eHalStatus hal_status; + tSirUpdateIE updateIE; ENTER(); @@ -17678,6 +17745,22 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, return -EINVAL; } + /* Clearing add IE of beacon */ + vos_mem_copy(updateIE.bssid, pAdapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = pAdapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = VOS_TRUE; + updateIE.notify = VOS_TRUE; + if (sme_UpdateAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, eUPDATE_IE_PROBE_BCN) == eHAL_STATUS_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE")); + } + + /* Reset WNI_CFG_PROBE_RSP Flags */ + wlan_hdd_reset_prob_rspies(pAdapter); + /* Issue Disconnect request */ INIT_COMPLETION(pAdapter->disconnect_comp_var); hal_status = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), @@ -17688,6 +17771,15 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, 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; } @@ -19442,23 +19534,26 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, break; } - valid_ch[num_ch++] = request->channels[i]->hw_value; - len += snprintf(chList+len, 5, "%d ", - request->channels[i]->hw_value); - break ; + if (!vos_is_dsrc_channel(vos_chan_to_freq( + request->channels[i]->hw_value))) { + valid_ch[num_ch++] = request->channels[i]->hw_value; + len += snprintf(chList+len, 5, "%d ", + request->channels[i]->hw_value); + } + break ; } } } - hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList); - /*If all channels are DFS and dropped, then ignore the PNO request*/ - if (num_ignore_dfs_ch == request->n_channels) - { + if (!num_ch) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s : All requested channels are DFS channels", __func__); + "%s : Channel list empty due to filtering of DSRC,DFS channels", + __func__); ret = -EINVAL; goto error; } + + hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList); } /* Filling per profile params */ @@ -19913,6 +20008,7 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, /* For explicit trigger of DIS_REQ come out of BMPS for successfully receiving DIS_RSP from peer. */ if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || + (SIR_MAC_TDLS_SETUP_CNF== action_code) || (SIR_MAC_TDLS_DIS_RSP == action_code) || (SIR_MAC_TDLS_DIS_REQ == action_code)) { @@ -19988,8 +20084,10 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, if ((0 == rc) || (TRUE != pAdapter->mgmtTxCompletionStatus)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Mgmt Tx Completion timed out TxCompletion %u", - __func__, pAdapter->mgmtTxCompletionStatus); + "%s: %s rc %ld mgmtTxCompletionStatus %u", + __func__, + !rc ? "Mgmt Tx Completion timed out" :"Mgmt Tx Completion failed", + rc, pAdapter->mgmtTxCompletionStatus); if (pHddCtx->isLogpInProgress) { @@ -20333,6 +20431,11 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, return -EINVAL; } + wlan_hdd_tdls_set_cap(pAdapter, peer, eTDLS_CAP_SUPPORTED); + + vos_mem_set(&tdlsLinkEstablishParams, + sizeof(tCsrTdlsLinkEstablishParams), 0); + if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status) { if (IS_ADVANCE_TDLS_ENABLE) { @@ -20363,10 +20466,25 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED, eTDLS_LINK_SUCCESS); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : tdlsLinkEstablishParams of peer " MAC_ADDRESS_STR "uapsdQueues: %d" + " qos: %d maxSp: %d isBufSta: %d isOffChannelSupported: %d" + " isResponder: %d peerstaId: %d", + __func__, MAC_ADDR_ARRAY(tdlsLinkEstablishParams.peerMac), + tdlsLinkEstablishParams.uapsdQueues, + tdlsLinkEstablishParams.qos, + tdlsLinkEstablishParams.maxSp, + tdlsLinkEstablishParams.isBufSta, + tdlsLinkEstablishParams.isOffChannelSupported, + tdlsLinkEstablishParams.isResponder, + pTdlsPeer->staId); + /* start TDLS client registration with TL */ status = hdd_roamRegisterTDLSSTA(pAdapter, peer, pTdlsPeer->staId, - pTdlsPeer->signature); + pTdlsPeer->signature, + tdlsLinkEstablishParams.qos); if (VOS_STATUS_SUCCESS == status) { tANI_U8 i; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c index d4a785df6ffe..87df3d6ce129 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -76,6 +76,7 @@ #ifdef IPA_OFFLOAD #include #endif +#include /**----------------------------------------------------------------------------- * Preprocessor definitions and constants @@ -2217,6 +2218,10 @@ VOS_STATUS hdd_wlan_re_init(void *hif_sc) goto err_unregister_pmops; } vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE); + + /* Register for p2p ack indication */ + sme_register_p2p_ack_ind_callback(pHddCtx->hHal, hdd_send_action_cnf_cb); + #ifdef FEATURE_WLAN_EXTSCAN sme_ExtScanRegisterCallback(pHddCtx->hHal, wlan_hdd_cfg80211_extscan_callback); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c index 3367c97b4b34..0cb56142a711 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -969,7 +969,7 @@ static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter, hdd_context_t *hdd_ctx) { tHalHandle hal_handle; - uint32_t roam_id; + uint32_t roam_id = 0; if (NULL == sta_adapter) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -1902,22 +1902,9 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa vos_mem_free(pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas);// Release caller allocated memory here pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas = NULL; return VOS_STATUS_SUCCESS; - case eSAP_INDICATE_MGMT_FRAME: - hdd_indicateMgmtFrame( pHostapdAdapter, - pSapEvent->sapevt.sapManagementFrameInfo.nFrameLength, - pSapEvent->sapevt.sapManagementFrameInfo.pbFrames, - pSapEvent->sapevt.sapManagementFrameInfo.frameType, - pSapEvent->sapevt.sapManagementFrameInfo.rxChan, 0); - return VOS_STATUS_SUCCESS; case eSAP_REMAIN_CHAN_READY: hdd_remainChanReadyHandler( pHostapdAdapter ); return VOS_STATUS_SUCCESS; - case eSAP_SEND_ACTION_CNF: - hdd_sendActionCnf( pHostapdAdapter, - ( eSAP_STATUS_SUCCESS == - pSapEvent->sapevt.sapActionCnf.actionSendSuccess ) ? - TRUE : FALSE ); - return VOS_STATUS_SUCCESS; case eSAP_UNKNOWN_STA_JOIN: snprintf(unknownSTAEvent, IW_CUSTOM_MAX, "JOIN_UNKNOWN_STA-%02x:%02x:%02x:%02x:%02x:%02x", pSapEvent->sapevt.sapUnknownSTAJoin.macaddr.bytes[0], @@ -2706,6 +2693,12 @@ static __iw_softap_setparam(struct net_device *dev, return -EINVAL; } + if (VOS_STATUS_SUCCESS != sme_is_session_valid(hHal, + pHostapdAdapter->sessionId)) { + hddLog(LOGE, FL("session id is not valid %d"), + pHostapdAdapter->sessionId); + return -EINVAL; + } pVosContext = pHddCtx->pvosContext; if (!pVosContext) { hddLog(LOGE, FL("Vos ctx is null")); @@ -3466,6 +3459,12 @@ static __iw_softap_getparam(struct net_device *dev, if (0 != ret) return ret; + if (VOS_STATUS_SUCCESS != sme_is_session_valid(hHal, + pHostapdAdapter->sessionId)) { + hddLog(LOGE, FL("session id is not valid %d"), + pHostapdAdapter->sessionId); + return -EINVAL; + } switch (sub_cmd) { case QCSAP_PARAM_MAX_ASSOC: @@ -4143,7 +4142,7 @@ static __iw_softap_ap_stats(struct net_device *dev, hddLog(LOG1, "unable to allocate memory"); return -ENOMEM; } - len = scnprintf(pstatbuf, wrqu->data.length, + len = snprintf(pstatbuf, wrqu->data.length, "RUF=%d RMF=%d RBF=%d " "RUB=%d RMB=%d RBB=%d " "TUF=%d TMF=%d TBF=%d " @@ -4155,14 +4154,18 @@ static __iw_softap_ap_stats(struct net_device *dev, (int)statBuffer.txBCFcnt, (int)statBuffer.txUCBcnt, (int)statBuffer.txMCBcnt, (int)statBuffer.txBCBcnt); - if (len > wrqu->data.length || - copy_to_user((void *)wrqu->data.pointer, (void *)pstatbuf, len)) - { + if (len >= wrqu->data.length) { + hddLog(LOG1, "%s: Insufficient buffer:%d, %d", + __func__, wrqu->data.length, len); + kfree(pstatbuf); + return -E2BIG; + } + if (copy_to_user((void *)wrqu->data.pointer, (void *)pstatbuf, len)) { hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); kfree(pstatbuf); return -EFAULT; } - wrqu->data.length -= len; + wrqu->data.length = len; kfree(pstatbuf); EXIT(); return 0; @@ -4208,9 +4211,8 @@ static __iw_get_char_setnone(struct net_device *dev, { case QCSAP_GET_STATS: { - hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + return hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), extra, WE_MAX_STR_LEN); - break; } } return 0; @@ -4267,7 +4269,7 @@ static int iw_softap_set_force_acs_ch_range(struct net_device *dev, return ret; } -static int __iw_softap_get_channel_list(struct net_device *dev, +static int __iw_get_channel_list(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -4281,6 +4283,7 @@ static int __iw_softap_get_channel_list(struct net_device *dev, eCsrBand curBand = eCSR_BAND_ALL; hdd_context_t *hdd_ctx; int ret; + int is_dfs_mode_enabled = 0; ENTER(); @@ -4307,43 +4310,53 @@ static int __iw_softap_get_channel_list(struct net_device *dev, bandStartChannel = RF_CHAN_36; bandEndChannel = RF_CHAN_184; } + if (curBand != eCSR_BAND_24) { + if (hdd_ctx->cfg_ini->dot11p_mode) { + bandEndChannel = RF_CHAN_184; + } else { + bandEndChannel = RF_CHAN_165; + } + } + if (pHostapdAdapter->device_mode == WLAN_HDD_INFRA_STATION && + hdd_ctx->cfg_ini->enableDFSChnlScan) { + is_dfs_mode_enabled = 1; + } else if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP && + hdd_ctx->cfg_ini->enableDFSMasterCap) { + is_dfs_mode_enabled = 1; + } hddLog(LOG1, FL("curBand = %d, bandStartChannel = %hu, " - "bandEndChannel = %hu "), curBand, - bandStartChannel, bandEndChannel ); + "bandEndChannel = %hu is_dfs_mode_enabled = %d "), curBand, + bandStartChannel, bandEndChannel, is_dfs_mode_enabled); for( i = bandStartChannel; i <= bandEndChannel; i++ ) { if ((NV_CHANNEL_ENABLE == regChannels[i].enabled) || - (NV_CHANNEL_DFS == regChannels[i].enabled)) + (is_dfs_mode_enabled && + NV_CHANNEL_DFS == regChannels[i].enabled)) + { channel_list->channels[num_channels] = rfChannels[i].channelNum; num_channels++; } } - hddLog(LOG1,FL(" number of channels %d"), num_channels); - if (num_channels > IW_MAX_FREQUENCIES) - { - num_channels = IW_MAX_FREQUENCIES; - } - channel_list->num_channels = num_channels; EXIT(); return 0; } -int iw_softap_get_channel_list(struct net_device *dev, +int iw_get_channel_list(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_channel_list(dev, info, wrqu, extra); + ret = __iw_get_channel_list(dev, info, wrqu, extra); vos_ssr_unprotect(__func__); return ret; @@ -5640,7 +5653,7 @@ static int iw_softap_version(struct net_device *dev, return ret; } -static VOS_STATUS +static int hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int buf_len) { v_U8_t i; @@ -5663,7 +5676,11 @@ hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int buf_len) if (0 != ret) return ret; - len = scnprintf(pBuf, buf_len, sta_info_header); + len = snprintf(pBuf, buf_len, sta_info_header); + if (len >= buf_len) { + hddLog(LOGE, FL("Insufficient buffer:%d, %d"), buf_len, len); + return -E2BIG; + } pBuf += len; buf_len -= len; @@ -5681,6 +5698,10 @@ hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int buf_len) pAdapter->aStaInfo[i].macAddrSTA.bytes[3], pAdapter->aStaInfo[i].macAddrSTA.bytes[4], pAdapter->aStaInfo[i].macAddrSTA.bytes[5]); + if (len >= buf_len) { + hddLog(LOGE, FL("Insufficient buffer:%d, %d"), buf_len, len); + return -E2BIG; + } pBuf += len; buf_len -= len; } @@ -5690,7 +5711,7 @@ hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int buf_len) } } EXIT(); - return VOS_STATUS_SUCCESS; + return 0; } static int __iw_softap_get_sta_info(struct net_device *dev, @@ -5699,7 +5720,6 @@ static int __iw_softap_get_sta_info(struct net_device *dev, char *extra) { hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); - VOS_STATUS status; hdd_context_t *hdd_ctx; int ret; @@ -5710,10 +5730,10 @@ static int __iw_softap_get_sta_info(struct net_device *dev, if (0 != ret) return ret; - status = hdd_softap_get_sta_info(pHostapdAdapter, extra, WE_SAP_MAX_STA_INFO); - if ( !VOS_IS_STATUS_SUCCESS( status ) ) { + ret = hdd_softap_get_sta_info(pHostapdAdapter, extra, WE_SAP_MAX_STA_INFO); + if (ret) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!",__func__); - return -EINVAL; + return ret; } wrqu->data.length = strlen(extra); EXIT(); @@ -6779,7 +6799,7 @@ static const iw_handler hostapd_private[] = { [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = iw_softap_set_force_acs_ch_range, [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV] = iw_softap_modify_acl, - [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = iw_softap_get_channel_list, + [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = iw_get_channel_list, [QCSAP_IOCTL_GET_STA_INFO - SIOCIWFIRSTPRIV] = iw_softap_get_sta_info, [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_softap_linkspeed, [QCSAP_IOCTL_PRIV_GET_RSSI - SIOCIWFIRSTPRIV] = iw_get_peer_rssi, diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c index 37e5a0ebdee8..a70067cf2adf 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c @@ -3723,9 +3723,6 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, if (type >= IPA_WLAN_EVENT_MAX) return -EINVAL; - if (WARN_ON(is_zero_ether_addr(mac_addr))) - return -EINVAL; - if (!hdd_ipa || !hdd_ipa_is_enabled(hdd_ipa->hdd_ctx)) { HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "IPA OFFLOAD NOT ENABLED"); return -EINVAL; @@ -3740,6 +3737,9 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, return 0; } + if (WARN_ON(is_zero_ether_addr(mac_addr))) + return -EINVAL; + /* During IPA UC resource loading/unloading * new event issued. * Store event seperatly and handle later */ diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c index 58d731f47940..45d335d7e686 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -207,6 +207,14 @@ DEFINE_SPINLOCK(hdd_context_lock); #define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */ #define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */ +/* + * Ibss prop IE from command will be of size: + * size = sizeof(oui) + sizeof(oui_data) + 1(Element ID) + 1(EID Length) + * OUI_DATA should be at least 3 bytes long + */ +#define WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH (3) + + #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) #define TID_MIN_VALUE 0 #define TID_MAX_VALUE 15 @@ -229,6 +237,8 @@ DEFINE_SPINLOCK(hdd_context_lock); */ #define NUM_OF_STA_DATA_TO_PRINT 16 +#define WLAN_NLINK_CESIUM 30 + /* * Android DRIVER command structures */ @@ -282,6 +292,17 @@ static const struct wiphy_wowlan_support wowlan_support_reg_init = { static int hdd_driver_init(void); static void hdd_driver_exit(void); +/* Internal function declarations */ + +static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo); + +static struct sock *cesium_nl_srv_sock; +static v_U16_t cesium_pid; + +static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue, + tANI_U8 *tx_fail_count, + tANI_U16 *pid); + void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback); struct completion wlan_start_comp; @@ -1178,6 +1199,353 @@ hdd_checkandupdate_dfssetting(hdd_adapter_t *pAdapter, char *country_code) } +/* Function header is left blank intentionally */ +static int hdd_parse_setrmcenable_command(tANI_U8 *pValue, tANI_U8 *pRmcEnable) +{ + tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + char buf[32]; + *pRmcEnable = 0; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + + if (NULL == inPtr) + { + return 0; + } + + else if (SPACE_ASCII_VALUE != *inPtr) + { + return 0; + } + + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + if ('\0' == *inPtr) + { + return 0; + } + + sscanf(inPtr, "%32s ", buf); + v = kstrtos32(buf, 10, &tempInt); + if ( v < 0) + { + return -EINVAL; + } + + *pRmcEnable = tempInt; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "ucRmcEnable: %d", *pRmcEnable); + + return 0; +} + +/* Function header is left blank intentionally */ +static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue, + tANI_U32 *pActionPeriod) +{ + tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + char buf[32]; + *pActionPeriod = 0; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + + if (NULL == inPtr) + { + return -EINVAL; + } + + else if (SPACE_ASCII_VALUE != *inPtr) + { + return -EINVAL; + } + + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + if ('\0' == *inPtr) + { + return 0; + } + + sscanf(inPtr, "%32s ", buf); + v = kstrtos32(buf, 10, &tempInt); + if ( v < 0) + { + return -EINVAL; + } + + if ( (tempInt < WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN) || + (tempInt > WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX) ) + { + return -EINVAL; + } + + *pActionPeriod = tempInt; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "uActionPeriod: %d", *pActionPeriod); + + return 0; +} + +/* Function header is left blank intentionally */ +static int hdd_parse_setrmcrate_command(tANI_U8 *pValue, + tANI_U32 *pRate, tTxrateinfoflags *pTxFlags) +{ + tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + char buf[32]; + *pRate = 0; + *pTxFlags = 0; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + + if (NULL == inPtr) + { + return -EINVAL; + } + + else if (SPACE_ASCII_VALUE != *inPtr) + { + return -EINVAL; + } + + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + if ('\0' == *inPtr) + { + return 0; + } + + sscanf(inPtr, "%32s ", buf); + v = kstrtos32(buf, 10, &tempInt); + if ( v < 0) + { + return -EINVAL; + } + + switch (tempInt) + { + default: + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "Unsupported rate: %d", tempInt); + return -EINVAL; + case 0: + case 6: + case 9: + case 12: + case 18: + case 24: + case 36: + case 48: + case 54: + *pTxFlags = eHAL_TX_RATE_LEGACY; + *pRate = tempInt * 10; + break; + case 65: + *pTxFlags = eHAL_TX_RATE_HT20; + *pRate = tempInt * 10; + break; + case 72: + *pTxFlags = eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; + *pRate = 722; + break; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Rate: %d", *pRate); + + return 0; +} + + +/** + * hdd_get_ibss_peer_info_cb() - IBSS peer Info request callback + * @UserData: Adapter private data + * @pPeerInfoRsp: Peer info response + * + * This is an asynchronous callback function from SME when the peer info + * is received + * + * Return: 0 for success non-zero for failure + */ +void +hdd_get_ibss_peer_info_cb(v_VOID_t *pUserData, + tSirPeerInfoRspParams *pPeerInfo) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)pUserData; + hdd_station_ctx_t *pStaCtx; + v_U8_t i; + + /*Sanity check*/ + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter or adapter has invalid magic"); + return; + } + + pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if (NULL != pPeerInfo && eHAL_STATUS_SUCCESS == pPeerInfo->status) { + /* validate number of peers */ + if (pPeerInfo->numPeers < HDD_MAX_NUM_IBSS_STA) { + pStaCtx->ibss_peer_info.status = pPeerInfo->status; + pStaCtx->ibss_peer_info.numPeers = pPeerInfo->numPeers; + + for (i = 0; i < pPeerInfo->numPeers; i++) { + pStaCtx->ibss_peer_info.peerInfoParams[i] = + pPeerInfo->peerInfoParams[i]; + } + hddLog(LOG1, FL("Peer Info copied in HDD")); + } else { + hddLog(LOG1, + FL("Number of peers %d returned is more than limit %d"), + pPeerInfo->numPeers, HDD_MAX_NUM_IBSS_STA); + } + } else { + hddLog(LOG1, FL("peerInfo returned is NULL")); + } + + complete(&pAdapter->ibss_peer_info_comp); +} + +/**--------------------------------------------------------------------------- + + \brief hdd_cfg80211_get_ibss_peer_info_all() - + + Request function to get IBSS peer info from lower layers + + \pAdapter -> Adapter context + + \return - 0 for success non-zero for failure + --------------------------------------------------------------------------*/ +static +VOS_STATUS hdd_cfg80211_get_ibss_peer_info_all(hdd_adapter_t *pAdapter) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + VOS_STATUS retStatus = VOS_STATUS_E_FAILURE; + unsigned long rc; + + INIT_COMPLETION(pAdapter->ibss_peer_info_comp); + + retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter, + hdd_get_ibss_peer_info_cb, + VOS_TRUE, 0xFF); + + if (VOS_STATUS_SUCCESS == retStatus) + { + rc = wait_for_completion_timeout + (&pAdapter->ibss_peer_info_comp, + msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); + + /* status will be 0 if timed out */ + if (!rc) { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT", + __func__); + retStatus = VOS_STATUS_E_FAILURE; + return retStatus; + } + } + else + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); + } + + return retStatus; +} + +/**--------------------------------------------------------------------------- + + \brief hdd_cfg80211_get_ibss_peer_info() - + + Request function to get IBSS peer info from lower layers + + \pAdapter -> Adapter context + \staIdx -> Sta index for which the peer info is requested + + \return - 0 for success non-zero for failure + --------------------------------------------------------------------------*/ +static VOS_STATUS +hdd_cfg80211_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx) +{ + unsigned long rc; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + VOS_STATUS retStatus = VOS_STATUS_E_FAILURE; + + INIT_COMPLETION(pAdapter->ibss_peer_info_comp); + + retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter, + hdd_get_ibss_peer_info_cb, + VOS_FALSE, staIdx); + + if (VOS_STATUS_SUCCESS == retStatus) + { + rc = wait_for_completion_timeout + (&pAdapter->ibss_peer_info_comp, + msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); + + /* status = 0 on timeout */ + if (!rc) { + hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT", + __func__); + retStatus = VOS_STATUS_E_FAILURE; + return retStatus; + } + } + else + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); + } + + return retStatus; +} + +/* Function header is left blank intentionally */ +static VOS_STATUS +hdd_parse_get_ibss_peer_info(tANI_U8 *pValue, v_MACADDR_t *pPeerMacAddr) +{ + tANI_U8 *inPtr = pValue; + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + + if (NULL == inPtr) + { + return VOS_STATUS_E_FAILURE;; + } + + else if (SPACE_ASCII_VALUE != *inPtr) + { + return VOS_STATUS_E_FAILURE;; + } + + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + if ('\0' == *inPtr) + { + return VOS_STATUS_E_FAILURE;; + } + + if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || + inPtr[11] != ':' || inPtr[14] != ':') + { + return VOS_STATUS_E_FAILURE;; + } + sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", + (unsigned int *)&pPeerMacAddr->bytes[0], + (unsigned int *)&pPeerMacAddr->bytes[1], + (unsigned int *)&pPeerMacAddr->bytes[2], + (unsigned int *)&pPeerMacAddr->bytes[3], + (unsigned int *)&pPeerMacAddr->bytes[4], + (unsigned int *)&pPeerMacAddr->bytes[5]); + + return VOS_STATUS_SUCCESS; +} + #ifdef IPA_UC_STA_OFFLOAD static void hdd_set_thermal_level_cb(hdd_context_t *pHddCtx, u_int8_t level) { @@ -1757,16 +2125,15 @@ hdd_parse_send_action_frame_v1_data(const tANI_U8 *pValue, static int hdd_sendactionframe(hdd_adapter_t *pAdapter, const tANI_U8 *bssid, const tANI_U8 channel, const tANI_U8 dwell_time, - const tANI_U8 payload_len, const tANI_U8 *payload) + const int payload_len, const tANI_U8 *payload) { struct ieee80211_channel chan; - tANI_U8 frame_len; + int frame_len, ret = 0; tANI_U8 *frame; struct ieee80211_hdr_3addr *hdr; u64 cookie; hdd_station_ctx_t *pHddStaCtx; hdd_context_t *pHddCtx; - int ret = 0; tpSirMacVendorSpecificFrameHdr pVendorSpecific = (tpSirMacVendorSpecificFrameHdr) payload; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) || defined(WITH_BACKPORTS) @@ -1923,45 +2290,57 @@ hdd_parse_sendactionframe_v1(hdd_adapter_t *pAdapter, const char *command) return ret; } -/* - \brief hdd_parse_sendactionframe_v2() - parse version 2 of the - SENDACTIONFRAME command - - This function parses the v2 SENDACTIONFRAME command with the format +/** + * hdd_parse_sendactionframe_v2() - parse version 2 of the + * SENDACTIONFRAME 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 command + * + * This function parses the v2 SENDACTIONFRAME command with the format + * SENDACTIONFRAME + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_sendactionframe_v2(hdd_adapter_t *pAdapter, + const char *command, int total_len) +{ + struct android_wifi_af_params *params; + tSirMacAddr bssid; + int ret; - SENDACTIONFRAME + /* The params are located after "SENDACTIONFRAME " */ + total_len -= 16; + params = (struct android_wifi_af_params *)(command + 16); - \param - pAdapter - Adapter upon which the command was received - \param - command - command that was received, ASCII command followed - by binary data + if (params->len <= 0 || params->len > ANDROID_WIFI_ACTION_FRAME_SIZE || + (params->len > total_len)) { + hddLog(LOGE, FL("Invalid payload length: %d"), params->len); + return -EINVAL; + } - \return - 0 for success non-zero for failure + if (!mac_pton(params->bssid, (u8 *)&bssid)) { + hddLog(LOGE, FL("MAC address parsing failed")); + return -EINVAL; + } - --------------------------------------------------------------------------*/ -static int -hdd_parse_sendactionframe_v2(hdd_adapter_t *pAdapter, - const char *command) -{ - struct android_wifi_af_params *params; - tSirMacAddr bssid; - int ret; + if (params->channel < 0 || + params->channel > WNI_CFG_CURRENT_CHANNEL_STAMAX) { + hddLog(LOGE, FL("Invalid channel: %d"), params->channel); + return -EINVAL; + } - /* params are large so keep off the stack */ - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) return -ENOMEM; + if (params->dwell_time < 0) { + hddLog(LOGE, FL("Invalid dwell_time: %d"), params->dwell_time); + return -EINVAL; + } - /* The params are located after "SENDACTIONFRAME " */ - memcpy(params, command + 16, sizeof(*params)); + ret = hdd_sendactionframe(pAdapter, bssid, params->channel, + params->dwell_time, params->len, params->data); - if (!mac_pton(params->bssid, (u8 *)&bssid)) { - hddLog(LOGE, "%s: MAC address parsing failed", __func__); - ret = -EINVAL; - } else { - ret = hdd_sendactionframe(pAdapter, bssid, params->channel, - params->dwell_time, params->len, params->data); - } - kfree(params); - return ret; + return ret; } /* @@ -1981,7 +2360,8 @@ hdd_parse_sendactionframe_v2(hdd_adapter_t *pAdapter, --------------------------------------------------------------------------*/ static int -hdd_parse_sendactionframe(hdd_adapter_t *pAdapter, const char *command) +hdd_parse_sendactionframe(hdd_adapter_t *pAdapter, const char *command, + int total_len) { int ret; @@ -1997,11 +2377,19 @@ hdd_parse_sendactionframe(hdd_adapter_t *pAdapter, const char *command) * SENDACTIONFRAME xx:xx:xx:xx:xx:xx* * 111111111122222222223333 * 0123456789012345678901234567890123 + * + * For both the commands, a valid command must have atleast first 34 length + * of data. */ + if (total_len < 34) { + hddLog(LOGE, FL("Invalid command (total_len=%d)"), total_len); + return -EINVAL; + } + if (command[33]) { ret = hdd_parse_sendactionframe_v1(pAdapter, command); } else { - ret = hdd_parse_sendactionframe_v2(pAdapter, command); + ret = hdd_parse_sendactionframe_v2(pAdapter, command, total_len); } return ret; @@ -2274,150 +2662,51 @@ hdd_parse_set_roam_scan_channels_v2(hdd_adapter_t *pAdapter, \brief hdd_parse_set_roam_scan_channels() - parse the SETROAMSCANCHANNELS command - There are two different versions of the SETROAMSCANCHANNELS command. - Version 1 of the command contains a parameter list that is ASCII - characters whereas version 2 contains a binary payload. Determine - if a version 1 or a version 2 command is being parsed by examining - the parameters, and then dispatch the parser that is appropriate for - the command. - - \param - pAdapter - Adapter upon which the command was received - \param - command - command that was received - - \return - 0 for success non-zero for failure - - --------------------------------------------------------------------------*/ -static int -hdd_parse_set_roam_scan_channels(hdd_adapter_t *pAdapter, - const char *command) -{ - const char *cursor; - char ch; - bool v1; - int ret; - - /* start after "SETROAMSCANCHANNELS " */ - cursor = command + 20; - - /* assume we have a version 1 command until proven otherwise */ - v1 = true; - - /* v1 params will only contain ASCII digits and space */ - while ((ch = *cursor++) && v1) { - if (!(isdigit(ch) || isspace(ch))) { - v1 = false; - } - } - if (v1) { - ret = hdd_parse_set_roam_scan_channels_v1(pAdapter, command); - } else { - ret = hdd_parse_set_roam_scan_channels_v2(pAdapter, command); - } - - return ret; -} - -#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ - -/**--------------------------------------------------------------------------- - - \brief hdd_parse_setrmcrate_command() - HDD Parse reliable multicast - set rate command - - This function parses the SETRMCTXRATE command passed in the format - SETRMCTXRATEX(multicast rate in Mbps) - For example input commands: - 1) SETRMCTXRATE 6 -> This is translated into set RMC multicast rate - to 6 Mbps - 1) SETRMCTXRATE 0 -> This is translated into disabling fixed multicast rate - and enabling multicast RA in firmware - - \param - pValue Pointer to SETRMCTXRATE command - \param - pRate Pointer to local RMC multicast rate variable - \param - pTxFlags Pointer to local RMC multicast rate variable - - \return - 0 for success non-zero for failure - - --------------------------------------------------------------------------*/ -static int hdd_parse_setrmcrate_command(tANI_U8 *pValue, - tANI_U32 *pRate, tTxrateinfoflags *pTxFlags) -{ - tANI_U8 *inPtr = pValue; - int tempInt; - int v = 0; - char buf[32]; - *pRate = 0; - *pTxFlags = 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; - } - - /* - * getting the first argument which sets multicast rate. - */ - sscanf(inPtr, "%32s ", buf); - v = kstrtos32(buf, 10, &tempInt); - if ( v < 0) - { - return -EINVAL; - } - - /* - * Validate the multicast rate. - */ - switch (tempInt) - { - default: - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "Unsupported rate: %d", tempInt); - return -EINVAL; - case 0: - case 6: - case 9: - case 12: - case 18: - case 24: - case 36: - case 48: - case 54: - *pTxFlags = eHAL_TX_RATE_LEGACY; - *pRate = tempInt * 10; - break; - case 65: - *pTxFlags = eHAL_TX_RATE_HT20; - *pRate = tempInt * 10; - break; - case 72: - *pTxFlags = eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; - *pRate = 722; /* fractional rate 72.2 Mbps */ - break; - } - - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Rate: %d", *pRate); + There are two different versions of the SETROAMSCANCHANNELS command. + Version 1 of the command contains a parameter list that is ASCII + characters whereas version 2 contains a binary payload. Determine + if a version 1 or a version 2 command is being parsed by examining + the parameters, and then dispatch the parser that is appropriate for + the command. - return 0; + \param - pAdapter - Adapter upon which the command was received + \param - command - command that was received + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +static int +hdd_parse_set_roam_scan_channels(hdd_adapter_t *pAdapter, + const char *command) +{ + const char *cursor; + char ch; + bool v1; + int ret; + + /* start after "SETROAMSCANCHANNELS " */ + cursor = command + 20; + + /* assume we have a version 1 command until proven otherwise */ + v1 = true; + + /* v1 params will only contain ASCII digits and space */ + while ((ch = *cursor++) && v1) { + if (!(isdigit(ch) || isspace(ch))) { + v1 = false; + } + } + if (v1) { + ret = hdd_parse_set_roam_scan_channels_v1(pAdapter, command); + } else { + ret = hdd_parse_set_roam_scan_channels_v2(pAdapter, command); + } + + return ret; } +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ + #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) /**--------------------------------------------------------------------------- @@ -2653,8 +2942,9 @@ static eHalStatus hdd_parse_plm_cmd(tANI_U8 *pValue, tSirPlmReq *pPlmRequest) if (content < 0) return eHAL_STATUS_FAILURE; + content = VOS_MIN(content, WNI_CFG_VALID_CHANNEL_LIST_LEN); pPlmRequest->plmNumCh = content; - hddLog(VOS_TRACE_LEVEL_DEBUG, "numch %d", pPlmRequest->plmNumCh); + hddLog(LOG1, FL("Numch: %d"), pPlmRequest->plmNumCh); /* Channel numbers */ for (count = 0; count < pPlmRequest->plmNumCh; count++) @@ -2672,10 +2962,9 @@ static eHalStatus hdd_parse_plm_cmd(tANI_U8 *pValue, tSirPlmReq *pPlmRequest) if (1 != ret) return eHAL_STATUS_FAILURE; ret = kstrtos32(buf, 10, &content); - if ( ret < 0) return eHAL_STATUS_FAILURE; - - if (content <= 0) - return eHAL_STATUS_FAILURE; + if (ret < 0 || content <= 0 || + content > WNI_CFG_CURRENT_CHANNEL_STAMAX) + return eHAL_STATUS_FAILURE; pPlmRequest->plmChList[count]= content; hddLog(VOS_TRACE_LEVEL_DEBUG, " ch- %d", @@ -3223,6 +3512,59 @@ static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) return ret; } +/** + * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to + * user space + * @frame_ind: Management frame data to be informed. + * + * This function is used to indicate management frame to + * user space + * + * Return: None + * + */ +void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind) +{ + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + v_CONTEXT_t vos_context; + int i; + + /* Get the global VOSS context.*/ + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + hddLog(LOGE, FL("Global VOS context is Null")); + return; + } + /* Get the HDD context.*/ + hdd_ctx = + (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context); + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return; + + if (HDD_SESSION_ID_ANY == frame_ind->sessionId) { + for (i = 0; i < HDD_SESSION_MAX; i++) { + adapter = + hdd_get_adapter_by_sme_session_id(hdd_ctx, i); + if (adapter) + break; + } + } else { + adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx, + frame_ind->sessionId); + } + + if ((NULL != adapter) && + (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)) + __hdd_indicate_mgmt_frame(adapter, + frame_ind->frame_len, + frame_ind->frameBuf, + frame_ind->frameType, + frame_ind->rxChan, + frame_ind->rxRssi); + return; +} static void hdd_GetLink_statusCB(v_U8_t status, void *pContext) { @@ -3511,6 +3853,50 @@ int hdd_set_miracast_mode(hdd_adapter_t *pAdapter, tANI_U8 *command) return 0; } +/* Function header is left blank intentionally */ +static int hdd_parse_set_ibss_oui_data_command(uint8_t *command, uint8_t *ie, + int32_t *oui_length, int32_t limit) +{ + uint8_t len; + uint8_t data; + + while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command)) { + command++; + limit--; + } + + len = 2; + + while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) && + (limit > 1)) { + sscanf(command, "%02x", (unsigned int *)&data); + ie[len++] = data; + command += 2; + limit -= 2; + } + + *oui_length = len - 2; + + while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command)) { + command++; + limit--; + } + + while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) && + (limit > 1)) { + sscanf(command, "%02x", (unsigned int *)&data); + ie[len++] = data; + command += 2; + limit -= 2; + } + + ie[0] = IE_EID_VENDOR; + ie[1] = len - 2; + + return len; +} + + /** * hdd_set_mas() - Function to set MAS value to UMAC * @adapter: Pointer to HDD adapter @@ -3760,17 +4146,17 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, /* no argument followed by spaces */ if ('\0' == *inPtr) return -EINVAL; - /* Getting the first argument ie measurement token */ + /* Getting the first argument ie Number of IE fields */ v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; v = kstrtos32(buf, 10, &tempInt); if (v < 0) return -EINVAL; + tempInt = VOS_MIN(tempInt, SIR_ESE_MAX_MEAS_IE_REQS); pEseBcnReq->numBcnReqIe = tempInt; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, - "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe); + hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe); for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++) { for (i = 0; i < 4; i++) { @@ -5419,7 +5805,8 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, } else if (strncmp(command, "SENDACTIONFRAME", 15) == 0) { - ret = hdd_parse_sendactionframe(pAdapter, command); + ret = hdd_parse_sendactionframe(pAdapter, command, + priv_data.total_len); } else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0) { @@ -5993,16 +6380,7 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, if (VOS_TRUE == vos_mem_compare(targetApBssid, pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) { - /* Reassoc to same AP, only supported for Open Security*/ - if ((pHddStaCtx->conn_info.ucEncryptionType || - pHddStaCtx->conn_info.mcEncryptionType)) { - hddLog(LOGE, - FL("Reassoc to same AP, only supported for Open Security")); - ret = -ENOTSUPP; - goto exit; - } - hddLog(LOG1, - FL("Reassoc BSSID is same as currently associated AP bssid")); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__); sme_GetModifyProfileFields(hHal, pAdapter->sessionId, &modProfileFields); sme_RoamReassoc(hHal, pAdapter->sessionId, @@ -6041,11 +6419,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { tANI_U8 *value = command; eHalStatus status = eHAL_STATUS_SUCCESS; - tpSirPlmReq pPlmRequest = NULL; + tpSirPlmReq pPlmRequest; pPlmRequest = vos_mem_malloc(sizeof(tSirPlmReq)); if (NULL == pPlmRequest){ - ret = -EINVAL; + ret = -ENOMEM; goto exit; } @@ -6315,28 +6693,447 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, char extra[32]; tANI_U8 len = 0; - memset(extra, 0, sizeof(extra)); - ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len); - len = VOS_MIN(priv_data.total_len, len + 1); - if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) - { + memset(extra, 0, sizeof(extra)); + ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len); + len = VOS_MIN(priv_data.total_len, len + 1); + if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + ret = len; + } + else if (strncmp(command, "SETDWELLTIME", 12) == 0) + { + ret = hdd_set_dwell_time(pAdapter, command); + } + else if ( strncasecmp(command, "MIRACAST", 8) == 0 ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received MIRACAST command", __func__); + + ret = hdd_set_miracast_mode(pAdapter, command); + } + else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) && + (WLAN_HDD_IBSS == pAdapter->device_mode)) + { + int i = 0; + uint8_t *ibss_ie; + int32_t command_len; + int32_t oui_length = 0; + uint8_t *value = command; + uint32_t ibss_ie_length; + tSirModifyIE ibssModifyIE; + tCsrRoamProfile *pRoamProfile; + hdd_wext_state_t *pWextState = + WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + int status; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: received command %s", __func__, ((char *) value)); + + /* validate argument of command */ + if (strlen(value) <= 21) { + hddLog(LOGE, + FL("No arguements in command length %zu"), strlen(value)); + ret = -EFAULT; + goto exit; + } + + /* moving to arguments of commands */ + value = value + 21; + command_len = strlen(value); + + /* oui_data can't be less than 3 bytes */ + if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) { + hddLog(LOGE, + FL("Invalid SETIBSSBEACONOUIDATA command length %d"), + command_len); + ret = -EFAULT; + goto exit; + } + + ibss_ie = vos_mem_malloc(command_len); + if (!ibss_ie) { + hddLog(LOGE, + FL("Could not allocate memory for command length %d"), + command_len); + ret = -ENOMEM; + goto exit; + } + vos_mem_zero(ibss_ie, command_len); + + ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie, + &oui_length, command_len); + if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) { + hddLog(LOGE, FL("Could not parse command %s return length %d"), + value, ibss_ie_length); + ret = -EFAULT; + vos_mem_free(ibss_ie); + goto exit; + } + + pRoamProfile = &pWextState->roamProfile; + + vos_mem_copy(ibssModifyIE.bssid, + pRoamProfile->BSSIDs.bssid, + VOS_MAC_ADDR_SIZE); + + ibssModifyIE.smeSessionId = pAdapter->sessionId; + ibssModifyIE.notify = TRUE; + ibssModifyIE.ieID = IE_EID_VENDOR; + ibssModifyIE.ieIDLen = ibss_ie_length; + ibssModifyIE.ieBufferlength = ibss_ie_length; + ibssModifyIE.pIEBuffer = ibss_ie; + ibssModifyIE.oui_length = oui_length; + + hddLog(LOGW, FL("ibss_ie length %d oui_length %d ibss_ie:"), + ibss_ie_length, oui_length); + while (i < ibssModifyIE.ieBufferlength) { + hddLog(LOGW, FL("0x%x"), ibss_ie[i++]); + } + + /* Probe Bcn modification */ + sme_ModifyAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &ibssModifyIE, + eUPDATE_IE_PROBE_BCN); + + /* Populating probe resp frame */ + sme_ModifyAddIE(WLAN_HDD_GET_HAL_CTX(pAdapter), + &ibssModifyIE, + eUPDATE_IE_PROBE_RESP); + /* free ibss_ie */ + vos_mem_free(ibss_ie); + + status = sme_SendCesiumEnableInd( (tHalHandle)(pHddCtx->hHal), + pAdapter->sessionId ); + if (VOS_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("cesium enable indication failed %d"), + status); + ret = -EINVAL; + goto exit; + } + + } + else if (strncasecmp(command, "SETRMCENABLE", 12) == 0) + { + tANI_U8 *value = command; + tANI_U8 ucRmcEnable = 0; + int status; + + if ((WLAN_HDD_IBSS != pAdapter->device_mode) && + (WLAN_HDD_SOFTAP != pAdapter->device_mode)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Received SETRMCENABLE command in invalid mode %d" + "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode", + pAdapter->device_mode); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_setrmcenable_command(value, &ucRmcEnable); + if (status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid SETRMCENABLE command "); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: ucRmcEnable %d ", __func__, ucRmcEnable); + + if (TRUE == ucRmcEnable) { + status = sme_enable_rmc((tHalHandle)(pHddCtx->hHal), + pAdapter->sessionId); + } + else if(FALSE == ucRmcEnable) { + status = sme_disable_rmc((tHalHandle)(pHddCtx->hHal), + pAdapter->sessionId); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid SETRMCENABLE command %d", ucRmcEnable); + ret = -EINVAL; + goto exit; + } + + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: SETRMC %d failed status %d", __func__, ucRmcEnable, + status); + ret = -EINVAL; + goto exit; + } + } + else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0) + { + tANI_U8 *value = command; + tANI_U32 uActionPeriod = 0; + int status; + + if ((WLAN_HDD_IBSS != pAdapter->device_mode) && + (WLAN_HDD_SOFTAP != pAdapter->device_mode)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Received SETRMC command in invalid mode %d" + "SETRMC command is only allowed in IBSS or SOFTAP mode", + pAdapter->device_mode); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod); + if (status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid SETRMCACTIONPERIOD command "); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: uActionPeriod %d ", __func__, uActionPeriod); + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, + uActionPeriod, NULL, eANI_BOOLEAN_FALSE)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod); + ret = -EINVAL; + goto exit; + } + + status = sme_SendRmcActionPeriod( (tHalHandle)(pHddCtx->hHal), + pAdapter->sessionId ); + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Could not send cesium enable indication %d", status); + ret = -EINVAL; + goto exit; + } + + } + else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0) + { + /* Peer Info All Command */ + int status = eHAL_STATUS_SUCCESS; + hdd_station_ctx_t *pHddStaCtx = NULL; + char *extra = NULL; + int idx = 0, length = 0; + uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; + v_U32_t numOfBytestoPrint = 0; + + if (WLAN_HDD_IBSS == pAdapter->device_mode) + { + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: pAdapter is not valid for this device mode", + __func__); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received GETIBSSPEERINFOALL Command", __func__); + + /* Handle the command */ + status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter); + if (VOS_STATUS_SUCCESS == status) + { + /* The variable extra needed to be allocated on the heap since + * amount of memory required to copy the data for 32 devices + * exceeds the size of 1024 bytes of default stack size. On + * 64 bit devices, the default max stack size of 2048 bytes + */ + extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL); + + if (NULL == extra) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:kmalloc failed", __func__); + ret = -EINVAL; + goto exit; + } + + /* Copy number of stations */ + length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ", + pHddStaCtx->ibss_peer_info.numPeers); + numOfBytestoPrint = length; + for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numPeers; idx++) { + int8_t rssi; + uint32_t tx_rate; + + vos_mem_copy(mac_addr, + pHddStaCtx->ibss_peer_info.peerInfoParams[idx].mac_addr, + sizeof(mac_addr)); + + tx_rate = + pHddStaCtx->ibss_peer_info.peerInfoParams[idx].txRate; + rssi = pHddStaCtx->ibss_peer_info.peerInfoParams[idx].rssi; + + length += scnprintf((extra + length), + WLAN_MAX_BUF_SIZE - length, + "%02x:%02x:%02x:%02x:%02x:%02x %d %d ", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5], + tx_rate, rssi); + /* + * VOS_TRACE() macro has limitation of 512 bytes for the print + * buffer. Hence printing the data in two chunks. The first + * chunk will have the data for 16 devices and the second + * chunk will have the rest. + */ + if (idx < NUM_OF_STA_DATA_TO_PRINT) + numOfBytestoPrint = length; + } + + /* + * Copy the data back into buffer, if the data to copy is + * more than 512 bytes than we will split the data and do + * it in two shots + */ + if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Copy into user data buffer failed ", __func__); + ret = -EFAULT; + goto exit; + } + priv_data.buf[numOfBytestoPrint] = '\0'; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "%s", priv_data.buf); + + if (length > numOfBytestoPrint) + { + if (copy_to_user(priv_data.buf + numOfBytestoPrint, + extra + numOfBytestoPrint, + length - numOfBytestoPrint + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Copy into user data buffer failed ", __func__); + ret = -EFAULT; + goto exit; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "%s", &priv_data.buf[numOfBytestoPrint]); + } + + /* Free temporary buffer */ + kfree(extra); + } + + else + { + /* Command failed, log error */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: GETIBSSPEERINFOALL command failed with status code %d", + __func__, status); + ret = -EINVAL; + goto exit; + } + ret = 0; + } + else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0) + { + /* Peer Info command */ + tANI_U8 *value = command; + VOS_STATUS status; + hdd_station_ctx_t *pHddStaCtx = NULL; + char extra[128] = { 0 }; + v_U32_t length = 0; + v_U8_t staIdx = 0; + v_MACADDR_t peerMacAddr; + + if (WLAN_HDD_IBSS == pAdapter->device_mode) + { + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: pAdapter is not valid for this device mode", + __func__); + ret = -EINVAL; + goto exit; + } + + /* if there are no peers, no need to continue with the command */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received GETIBSSPEERINFO Command", __func__); + + if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s:No IBSS Peers coalesced", __func__); + ret = -EINVAL; + goto exit; + } + + /* Parse the incoming command buffer */ + status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr); + if (VOS_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid GETIBSSPEERINFO command", __func__); + ret = -EINVAL; + goto exit; + } + + /* Get station index for the peer mac address and sanitize it */ + hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx); + + if (staIdx > HDD_MAX_NUM_IBSS_STA) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid StaIdx %d returned", __func__, staIdx); + ret = -EINVAL; + goto exit; + } + + /* Handle the command */ + status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx); + if (VOS_STATUS_SUCCESS == status) + { + v_U32_t txRate = pHddStaCtx->ibss_peer_info.peerInfoParams[0].txRate; + + length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRate, + (int)pHddStaCtx->ibss_peer_info.peerInfoParams[0].rssi); + + /* Copy the data back into buffer */ + if (copy_to_user(priv_data.buf, &extra, length+ 1)) + { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: failed to copy data to user buffer", __func__); + "%s: copy data to user buffer failed GETIBSSPEERINFO command", + __func__); ret = -EFAULT; goto exit; - } - ret = len; - } - else if (strncmp(command, "SETDWELLTIME", 12) == 0) - { - ret = hdd_set_dwell_time(pAdapter, command); - } - else if ( strncasecmp(command, "MIRACAST", 8) == 0 ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: Received MIRACAST command", __func__); + } + } + else + { + /* Command failed, log error */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: GETIBSSPEERINFO command failed with status code %d", + __func__, status); + ret = -EINVAL; + goto exit; + } - ret = hdd_set_miracast_mode(pAdapter, command); + /* Success ! */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, + "%s", priv_data.buf); + ret = 0; } else if (strncmp(command, "SETRMCTXRATE", 12) == 0) { @@ -6387,6 +7184,64 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), &rateUpdateParams); } + else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0) + { + char *value; + tANI_U8 tx_fail_count = 0; + tANI_U16 pid = 0; + + value = command; + + ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid); + + if (0 != ret) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Failed to parse SETIBSSTXFAILEVENT arguments", + __func__); + goto exit; + } + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu", + __func__, tx_fail_count, pid); + + if (0 == tx_fail_count) + { + // Disable TX Fail Indication + if (eHAL_STATUS_SUCCESS == + sme_TXFailMonitorStartStopInd(pHddCtx->hHal, + tx_fail_count, + NULL)) + { + cesium_pid = 0; + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to disable TX Fail Event ", __func__); + ret = -EINVAL; + } + } + else + { + if (eHAL_STATUS_SUCCESS == + sme_TXFailMonitorStartStopInd(pHddCtx->hHal, + tx_fail_count, + (void*)hdd_tx_fail_ind_callback)) + { + cesium_pid = pid; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Registered Cesium pid %u", __func__, + cesium_pid); + } + else + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to enable TX Fail Monitoring", __func__); + ret = -EINVAL; + } + } + } #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0) { @@ -7150,8 +8005,8 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, cfg->per_band_chainmask_supp); #ifdef FEATURE_WLAN_TDLS cfg_ini->fEnableTDLSSupport &= cfg->en_tdls; - cfg_ini->fEnableTDLSOffChannel &= cfg->en_tdls_offchan; - cfg_ini->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta; + cfg_ini->fEnableTDLSOffChannel &= (uint32_t)cfg->en_tdls_offchan; + cfg_ini->fEnableTDLSBufferSta &= (uint32_t)cfg->en_tdls_uapsd_buf_sta; if (cfg_ini->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) { cfg_ini->fEnableTDLSSleepSta = TRUE; @@ -7827,6 +8682,10 @@ void hdd_update_tgt_cfg(void *context, void *param) HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1; hddLog(LOG1, FL("Current antenna mode: %d"), hdd_ctx->current_antenna_mode); + hdd_ctx->cfg_ini->fine_time_meas_cap &= cfg->fine_time_measurement_cap; + hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap; + hddLog(LOG1, FL("fine_time_measurement_cap: 0x%x"), + hdd_ctx->cfg_ini->fine_time_meas_cap); } /* This function is invoked in atomic context when a radar @@ -7940,16 +8799,16 @@ static int __hdd_open(struct net_device *dev) hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; VOS_STATUS status; - int ret; v_BOOL_t in_standby = TRUE; MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, pAdapter->sessionId, pAdapter->device_mode)); - ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); - return ret; + /* Don't validate for load/unload and logp as if we return + failure we may endup in scan/connection related issues */ + if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini) { + hddLog(LOG1, FL("HDD context is Null")); + return -ENODEV; } status = hdd_get_front_adapter (pHddCtx, &pAdapterNode); @@ -7978,7 +8837,7 @@ static int __hdd_open(struct net_device *dev) netif_tx_start_all_queues(dev); } - return ret; + return 0; } /** @@ -8308,6 +9167,7 @@ static void __hdd_uninit(struct net_device *dev) /* After uninit our adapter structure will no longer be valid */ pAdapter->dev = NULL; pAdapter->magic = 0; + pAdapter->pHddCtx = NULL; EXIT(); } @@ -8352,6 +9212,192 @@ void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status) } } +static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo) +{ + int payload_len; + struct sk_buff *skb; + struct nlmsghdr *nlh; + v_U8_t *data; + + payload_len = ETH_ALEN; + + if (0 == cesium_pid) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered", + __func__); + return; + } + + if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: nlmsg_new() failed for msg size[%d]", + __func__, NLMSG_SPACE(payload_len)); + return; + } + + nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST); + + if (NULL == nlh) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: nlmsg_put() failed for msg size[%d]", + __func__, NLMSG_SPACE(payload_len)); + + kfree_skb(skb); + return; + } + + data = nlmsg_data(nlh); + memcpy(data, MacAddr, ETH_ALEN); + + if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]", + __func__, NLMSG_SPACE(payload_len)); + } + + return; +} + +/**--------------------------------------------------------------------------- + \brief hdd_ParseuserParams - return a pointer to the next argument + + \return - status + +--------------------------------------------------------------------------*/ +static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg) +{ + tANI_U8 *pVal; + + pVal = strchr(pValue, ' '); + + if (NULL == pVal) + { + /* no argument remains */ + return -EINVAL; + } + else if (SPACE_ASCII_VALUE != *pVal) + { + /* no space after the current argument */ + return -EINVAL; + } + + pVal++; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal)) + { + pVal++; + } + + /* no argument followed by spaces */ + if ('\0' == *pVal) + { + return -EINVAL; + } + + *ppArg = pVal; + + return 0; +} + +/**---------------------------------------------------------------------------- + \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT + + \return - status + +------------------------------------------------------------------------------*/ +static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue, + tANI_U8 *tx_fail_count, + tANI_U16 *pid) +{ + tANI_U8 *param = NULL; + int ret; + + ret = hdd_ParseUserParams(pValue, ¶m); + + if (0 == ret && NULL != param) + { + if (1 != sscanf(param, "%hhu", tx_fail_count)) + { + ret = -EINVAL; + goto done; + } + } + else + { + goto done; + } + + if (0 == *tx_fail_count) + { + *pid = 0; + goto done; + } + + pValue = param; + pValue++; + + ret = hdd_ParseUserParams(pValue, ¶m); + + if (0 == ret) + { + if (1 != sscanf(param, "%hu", pid)) + { + ret = -EINVAL; + goto done; + } + } + else + { + goto done; + } + +done: + return ret; +} + +static int hdd_open_cesium_nl_sock(void) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + struct netlink_kernel_cfg cfg = { + .groups = WLAN_NLINK_MCAST_GRP_ID, + .input = NULL + }; +#endif + int ret = 0; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) + THIS_MODULE, +#endif + &cfg); +#else + cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM, + WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE); +#endif + + if (cesium_nl_srv_sock == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "NLINK: cesium netlink_kernel_create failed"); + ret = -ECONNREFUSED; + } + + return ret; +} + +static void hdd_close_cesium_nl_sock(void) +{ + if (NULL != cesium_nl_srv_sock) + { + netlink_kernel_release(cesium_nl_srv_sock); + cesium_nl_srv_sock = NULL; + } +} + /**--------------------------------------------------------------------------- \brief hdd_get_cfg_file_size() - @@ -8809,6 +9855,7 @@ static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMac init_completion(&pAdapter->tdls_link_establish_req_comp); #endif + init_completion(&pAdapter->ibss_peer_info_comp); init_completion(&pHddCtx->mc_sus_event_var); init_completion(&pHddCtx->tx_sus_event_var); init_completion(&pHddCtx->rx_sus_event_var); @@ -8945,6 +9992,33 @@ static eHalStatus hdd_smeCloseSessionCallback(void *pContext) return eHAL_STATUS_SUCCESS; } +/** + * hdd_close_tx_queues() - close tx queues + * @hdd_ctx: hdd global context + * + * Return: None + */ +static void hdd_close_tx_queues(hdd_context_t *hdd_ctx) +{ + VOS_STATUS status; + hdd_adapter_t *adapter; + hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL; + /* Not validating hdd_ctx as it's already done by the caller */ + ENTER(); + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { + adapter = adapter_node->pAdapter; + if (adapter && adapter->dev) { + netif_tx_disable (adapter->dev); + netif_carrier_off(adapter->dev); + } + status = hdd_get_next_adapter(hdd_ctx, adapter_node, + &next_adapter); + adapter_node = next_adapter; + } + EXIT(); +} + VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ) { struct net_device *pWlanDev = pAdapter->dev; @@ -10367,6 +11441,7 @@ VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) * hdd_connect_result() - API to send connection status to supplicant * @dev: network device * @bssid: bssid to which we want to associate + * @roam_info: information about connected bss * @req_ie: Request Information Element * @req_ie_len: len of the req IE * @resp_ie: Response IE @@ -10379,9 +11454,55 @@ VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) * * Return: Void */ +#if defined CFG80211_CONNECT_BSS +void hdd_connect_result(struct net_device *dev, + const u8 *bssid, + tCsrRoamInfo *roam_info, + const u8 *req_ie, + size_t req_ie_len, + const u8 *resp_ie, + size_t resp_ie_len, + u16 status, + gfp_t gfp) +{ + hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev); + struct cfg80211_bss *bss = NULL; + + if (WLAN_STATUS_SUCCESS == status) { + struct ieee80211_channel *chan; + int freq; + int chan_no = roam_info->pBssDesc->channelId;; + + if (chan_no <= 14) + freq = ieee80211_channel_to_frequency(chan_no, + IEEE80211_BAND_2GHZ); + else + freq = ieee80211_channel_to_frequency(chan_no, + IEEE80211_BAND_5GHZ); + + chan = ieee80211_get_channel(padapter->wdev.wiphy, freq); + bss = cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid, + roam_info->u.pConnectedProfile->SSID.ssId, + roam_info->u.pConnectedProfile->SSID.length, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \ + && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY) + WLAN_CAPABILITY_ESS + WLAN_CAPABILITY_ESS); +#else + IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); +#endif + } + + cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, + resp_ie, resp_ie_len, status, gfp); + vos_runtime_pm_allow_suspend(padapter->runtime_context.connect); +} +#else void hdd_connect_result(struct net_device *dev, const u8 *bssid, + tCsrRoamInfo *roam_info, const u8 *req_ie, size_t req_ie_len, const u8 * resp_ie, @@ -10396,7 +11517,7 @@ void hdd_connect_result(struct net_device *dev, vos_runtime_pm_allow_suspend(padapter->runtime_context.connect); } - +#endif VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) { @@ -10447,8 +11568,8 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; /* indicate disconnected event to nl80211 */ - cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, - NULL, 0, GFP_KERNEL); + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true, + WLAN_REASON_UNSPECIFIED); } else if (eConnectionState_Connecting == connState) { @@ -10456,7 +11577,7 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) * Indicate connect failure to supplicant if we were in the * process of connecting */ - hdd_connect_result(pAdapter->dev, NULL, + hdd_connect_result(pAdapter->dev, NULL, NULL, NULL, 0, NULL, 0, WLAN_STATUS_ASSOC_DENIED_UNSPEC, GFP_KERNEL); @@ -11022,6 +12143,43 @@ hdd_adapter_t *hdd_get_adapter_by_vdev( hdd_context_t *pHddCtx, return NULL; } +/** + * hdd_get_adapter_by_sme_session_id() - Return adapter with + * the sessionid + * @hdd_ctx: hdd cntx. + * @sme_session_id: sme session is for the adapter to get. + * + * This function is used to get the adapter with provided session id + * + * Return: adapter pointer if found + * + */ +hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx, + uint32_t sme_session_id) +{ + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + hdd_adapter_t *adapter; + VOS_STATUS vos_status; + + + vos_status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + + while ((NULL != adapter_node) && + (VOS_STATUS_SUCCESS == vos_status)) { + adapter = adapter_node->pAdapter; + + if (adapter && + adapter->sessionId == sme_session_id) + return adapter; + + vos_status = + hdd_get_next_adapter(hdd_ctx, + adapter_node, &next); + adapter_node = next; + } + return NULL; +} + hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode ) { hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; @@ -11726,6 +12884,7 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) nl_srv_exit(); #endif /* WLAN_KD_READY_NOTIFIER */ + hdd_close_cesium_nl_sock(); hdd_runtime_suspend_deinit(pHddCtx); hdd_close_all_adapters( pHddCtx ); @@ -11821,7 +12980,9 @@ void __hdd_wlan_exit(void) wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); #endif + hdd_close_tx_queues(pHddCtx); //Do all the cleanup before deregistering the driver + memdump_deinit(); hdd_wlan_exit(pHddCtx); EXIT(); } @@ -13155,6 +14316,7 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE); pHddCtx->isLoadInProgress = FALSE; + memdump_init(); hddLog(LOGE, FL("FTM driver loaded")); complete(&wlan_start_comp); return VOS_STATUS_SUCCESS; @@ -13293,6 +14455,10 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) /* Fwr capabilities received, Set the Dot11 mode */ sme_SetDefDot11Mode(pHddCtx->hHal); + + wlansap_set_tx_leakage_threshold(pHddCtx->hHal, + pHddCtx->cfg_ini->sap_tx_leakage_threshold); + /* Register with platform driver as client for Suspend/Resume */ status = hddRegisterPmOps(pHddCtx); if ( !VOS_IS_STATUS_SUCCESS( status ) ) @@ -13372,6 +14538,12 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) } #endif + if (hdd_open_cesium_nl_sock() < 0) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__); + goto err_nl_srv; + } + //Initialize the CNSS-DIAG service if (cnss_diag_activate_service() < 0) { @@ -13590,6 +14762,8 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) nl_srv_exit(); #endif /* WLAN_KD_READY_NOTIFIER */ + hdd_close_cesium_nl_sock(); + err_reg_netdev: if (rtnl_lock_enable == TRUE) { rtnl_lock_enable = FALSE; @@ -13824,7 +14998,6 @@ static int hdd_driver_init( void) ret_status = -ENODEV; break; } else { - memdump_init(); pr_info("%s: driver loaded in %lld\n", WLAN_MODULE_NAME, adf_get_boottime() - start); return 0; @@ -13951,7 +15124,6 @@ static void hdd_driver_exit(void) } vos_wait_for_work_thread_completion(__func__); - memdump_deinit(); hif_unregister_driver(); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c index 6d02cdd82fde..f3b6c6ef0229 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c @@ -601,6 +601,7 @@ int memdump_init(void) } mutex_init(&hdd_ctx->memdump_lock); + hdd_ctx->memdump_init_done = true; return 0; } @@ -637,6 +638,12 @@ void memdump_deinit(void) { return; } + if (!hdd_ctx->memdump_init_done) { + hddLog(LOGE, FL("MemDump not initialized")); + return; + } + + hdd_ctx->memdump_init_done = false; adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, hdd_ctx->pvosContext); if (!adf_ctx) { hddLog(LOGE, FL("ADF context is NULL")); @@ -654,7 +661,9 @@ void memdump_deinit(void) { hdd_ctx->fw_dump_loc = NULL; hdd_ctx->memdump_in_progress = false; } + mutex_unlock(&hdd_ctx->memdump_lock); + mutex_destroy(&hdd_ctx->memdump_lock); if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&hdd_ctx->memdump_cleanup_timer)) { diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c index 104e54efe692..14eb877b02b0 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -408,7 +408,14 @@ static eHalStatus oem_process_data_req_msg(int oemDataLen, char *oemData) vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig)); - vos_mem_copy((&oemDataReqConfig)->oemDataReq, oemData, oemDataLen); + oemDataReqConfig.data = vos_mem_malloc(oemDataLen); + if (!oemDataReqConfig.data) { + hddLog(LOGE, FL("malloc failed for data req buffer")); + return eHAL_STATUS_FAILED_ALLOC; + } + + oemDataReqConfig.data_len = oemDataLen; + vos_mem_copy(oemDataReqConfig.data, oemData, oemDataLen); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: calling sme_OemDataReq", __func__); @@ -417,6 +424,8 @@ static eHalStatus oem_process_data_req_msg(int oemDataLen, char *oemData) pAdapter->sessionId, &oemDataReqConfig, &oemDataReqID); + + vos_mem_free(oemDataReqConfig.data); return status; } diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c index 81e457f249fa..d1040bb8d6b5 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -192,6 +192,7 @@ wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer); cfgState->remain_on_chan_ctx = NULL; + /* * Resetting the roc in progress early ensures that the subsequent * roc requests are immediately processed without being queued @@ -205,7 +206,6 @@ wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, * Basically, the system must not go into suspend while roc is in progress. */ hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); - mutex_unlock(&cfgState->remain_on_chan_ctx_lock); if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { @@ -229,6 +229,7 @@ wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, GFP_KERNEL); pAdapter->lastRocTs = vos_timer_get_system_time(); } + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); /* Schedule any pending RoC: Any new roc request during this time * would have got queued in 'wlan_hdd_request_remain_on_channel' @@ -245,13 +246,17 @@ wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, ) { tANI_U8 sessionId = pAdapter->sessionId; + mutex_lock(&cfgState->remain_on_chan_ctx_lock); if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); sme_DeregisterMgmtFrame( hHal, sessionId, (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ); } + else + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); } else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) || ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) @@ -268,6 +273,7 @@ wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, } + mutex_lock(&cfgState->remain_on_chan_ctx_lock); if(pRemainChanCtx->action_pkt_buff.frame_ptr != NULL && pRemainChanCtx->action_pkt_buff.frame_length != 0 ) { @@ -276,6 +282,7 @@ wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx, pRemainChanCtx->action_pkt_buff.frame_length = 0; } vos_mem_free( pRemainChanCtx ); + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); complete(&pAdapter->cancel_rem_on_chan_var); if (eHAL_STATUS_SUCCESS != status) complete(&pAdapter->rem_on_chan_ready_event); @@ -300,6 +307,12 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter) hdd_remain_on_chan_timer); pRemainChanCtx = cfgState->remain_on_chan_ctx; + if (NULL == pRemainChanCtx) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(LOGE, FL("pRemainChanCtx is NULL")); + return; + } if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE) { mutex_unlock(&cfgState->remain_on_chan_ctx_lock); @@ -418,6 +431,12 @@ void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter) mutex_lock(&cfgState->remain_on_chan_ctx_lock); roc_ctx = cfgState->remain_on_chan_ctx; + if (roc_ctx == NULL) + { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(LOG1, FL("roc_ctx is NULL!")); + return; + } if (roc_ctx->hdd_remain_on_chan_cancel_in_progress == true) { mutex_unlock(&cfgState->remain_on_chan_ctx_lock); hddLog(LOG1, FL("roc cancel already in progress")); @@ -1505,13 +1524,17 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET])); } - if (pAdapter->device_mode == WLAN_HDD_SOFTAP) { + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) && + (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))) { home_ch = pAdapter->sessionCtx.ap.operatingChannel; - } else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) { + } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) && + (pAdapter->sessionCtx.station.conn_info.connState == + eConnectionState_Associated)) { home_ch = pAdapter->sessionCtx.station.conn_info.operationChannel; } else { goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO ); - if (goAdapter) + if (goAdapter && + (test_bit(SOFTAP_BSS_STARTED, &goAdapter->event_flags))) home_ch = goAdapter->sessionCtx.ap.operatingChannel; } @@ -1553,7 +1576,9 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, goto send_frame; } else { - if(pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE) + if( (pRemainChanCtx != NULL) && + (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == + TRUE)) { mutex_unlock(&cfgState->remain_on_chan_ctx_lock); hddLog(VOS_TRACE_LEVEL_INFO, @@ -1972,6 +1997,48 @@ void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess complete(&pAdapter->tx_action_cnf_event); } +/** + * hdd_send_action_cnf_cb - action confirmation callback + * @session_id: SME session ID + * @tx_completed: ack status + * + * This function invokes hdd_sendActionCnf to update ack status to + * supplicant. + */ +void hdd_send_action_cnf_cb(uint32_t session_id, bool tx_completed) +{ + v_CONTEXT_t vos_context; + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + + ENTER(); + + /* Get the global VOSS context */ + vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + if (!vos_context) { + hddLog(LOGE, FL("Global VOS context is Null")); + return; + } + + /* Get the HDD context.*/ + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_context); + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return; + + adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx, session_id); + if (NULL == adapter) { + hddLog(LOGE, FL("adapter not found")); + return; + } + + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + hddLog(LOGE, FL("adapter has invalid magic")); + return; + } + + hdd_sendActionCnf(adapter, tx_completed) ; +} + /** * hdd_setP2pNoa * @@ -2543,12 +2610,12 @@ void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, return ; } -void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, +void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, tANI_U32 nFrameLength, tANI_U8* pbFrames, tANI_U8 frameType, tANI_U32 rxChan, - tANI_S8 rxRssi ) + tANI_S8 rxRssi) { tANI_U16 freq; tANI_U16 extend_time; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c index f46e26b359ec..ca400e540cee 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c @@ -44,12 +44,10 @@ #include #include "wlan_hdd_tdls.h" #include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_assoc.h" +#include "sme_Api.h" #include "vos_sched.h" -#ifdef CONFIG_TDLS_IMPLICIT -static void wlan_hdd_tdls_pre_setup(struct work_struct *work); -#endif - /** * wlan_hdd_tdls_determine_channel_opclass() - determine channel and opclass * @hddctx: pointer to hdd context @@ -106,7 +104,7 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) { u16 connected_tdls_peers = 0; u8 staidx; - hddTdlsPeer_t *curr_peer = NULL; + hddTdlsPeer_t *curr_peer; hdd_adapter_t *adapter = NULL; if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) { @@ -123,8 +121,10 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) connected_tdls_peers = wlan_hdd_tdlsConnectedPeers(adapter); - if (!connected_tdls_peers) + if (!connected_tdls_peers) { + hddLog(LOG1, FL("No TDLS connected peers to delete")); return ; + } /* TDLS is not supported in case of concurrency. * Disable TDLS Offchannel in FW to avoid more @@ -143,6 +143,10 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) TDLS_SEC_OFFCHAN_OFFSET_40PLUS); hdd_set_tdls_offchannelmode(adapter, DISABLE_CHANSWITCH); + /* Send Msg to PE for deleting all the TDLS peers */ + sme_delete_all_tdls_peers(hddctx->hHal, adapter->sessionId); + + for (staidx = 0; staidx < hddctx->max_num_tdls_sta; staidx++) { if (!hddctx->tdlsConnInfo[staidx].staId) @@ -150,18 +154,34 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) curr_peer = wlan_hdd_tdls_find_all_peer(hddctx, hddctx->tdlsConnInfo[staidx].peerMac.bytes); - if (!curr_peer) continue; hddLog(LOG1, FL("indicate TDLS teardown (staId %d)"), - curr_peer->staId); + curr_peer->staId); + /* Indicate teardown to supplicant */ wlan_hdd_tdls_indicate_teardown( - curr_peer->pHddTdlsCtx->pAdapter, - curr_peer, - eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + curr_peer->pHddTdlsCtx->pAdapter, + curr_peer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + + /* + * Del Sta happened already as part of sme_delete_all_tdls_peers + * Hence clear hdd data structure. + */ + hdd_roamDeregisterTDLSSTA(adapter, + hddctx->tdlsConnInfo[staidx].staId); + wlan_hdd_tdls_decrement_peer_count(adapter); + wlan_hdd_tdls_reset_peer(adapter, curr_peer->peerMac); + + hddctx->tdlsConnInfo[staidx].staId = 0; + hddctx->tdlsConnInfo[staidx].sessionId = 255; + + vos_mem_zero(&hddctx->tdlsConnInfo[staidx].peerMac, + sizeof(v_MACADDR_t)); } + wlan_hdd_tdls_check_bmps(adapter); } /** @@ -176,41 +196,6 @@ void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, hdd_context_t *hddctx) wlan_hdd_tdls_disable_offchan_and_teardown_links(hddctx); } -#ifdef CONFIG_TDLS_IMPLICIT -void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx, - hddTdlsPeer_t *curr_candidate) -{ - if (!pHddTdlsCtx || !curr_candidate) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: either pHddTdlsCtx or curr_candidate is null", - __func__); - return; - } - - if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic) - { - /* When TDLS discovery attempt for a peer reaches to max configured - * threshold then tdls support for that peer would be disabled and - * in that case, ignore discovery trigger from FW for that peer. - */ - if (eTDLS_CAP_NOT_SUPPORTED == curr_candidate->tdls_support) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, - "%s: tdls_support is marked disabled for peer: " - MAC_ADDRESS_STR ", ignore pre_setup_init_work", - __func__, MAC_ADDR_ARRAY(curr_candidate->peerMac)); - return; - } - - pHddTdlsCtx->curr_candidate = curr_candidate; - pHddTdlsCtx->magic = TDLS_CTX_MAGIC; - - schedule_work(&pHddTdlsCtx->implicit_setup); - } -} -#endif - /* Caller has to take the lock before calling this function */ static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx) { @@ -345,7 +330,8 @@ static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData) return; } -static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) +static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx, + bool del_forced_peer) { int i; struct list_head *head; @@ -363,6 +349,9 @@ static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) head = &pHddTdlsCtx->peer_list[i]; list_for_each_safe (pos, q, head) { tmp = list_entry(pos, hddTdlsPeer_t, node); + /* Don't delete TDLS forced peers during STA disconnection */ + if (!del_forced_peer && tmp->isForcedPeer) + continue; list_del(pos); vos_mem_free(tmp); tmp = NULL; @@ -567,16 +556,6 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED; } -#ifdef CONFIG_TDLS_IMPLICIT -#ifdef CONFIG_CNSS - cnss_init_work(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); -#else -#ifdef WLAN_OPEN_SOURCE - INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); -#endif -#endif -#endif - #ifdef CONFIG_CNSS cnss_init_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, wlan_hdd_tdls_schedule_scan); @@ -742,14 +721,13 @@ void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) goto done; } - vos_flush_work(&pHddTdlsCtx->implicit_setup); vos_flush_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work); /* must stop timer here before freeing peer list, because peerIdleTimer is part of peer list structure. */ wlan_hdd_tdls_timers_destroy(pHddTdlsCtx); - wlan_hdd_tdls_free_list(pHddTdlsCtx); + wlan_hdd_tdls_free_list(pHddTdlsCtx, true); mutex_unlock(&pHddCtx->tdls_lock); @@ -1165,7 +1143,8 @@ int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, const u8 *mac, tCsrStaParams *StaParams, tANI_BOOLEAN isBufSta, - tANI_BOOLEAN isOffChannelSupported) + tANI_BOOLEAN isOffChannelSupported, + bool is_qos_wmm_sta) { hddTdlsPeer_t *curr_peer; @@ -1195,6 +1174,9 @@ int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, curr_peer->supported_oper_classes_len = StaParams->supported_oper_classes_len; + + curr_peer->qos = is_qos_wmm_sta; + return 0; } @@ -1232,6 +1214,9 @@ int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter, tdlsLinkEstablishParams->supportedOperClassesLen = curr_peer->supported_oper_classes_len; + + tdlsLinkEstablishParams->qos = curr_peer->qos; + return 0; } @@ -2131,7 +2116,7 @@ void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter) wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx); - wlan_hdd_tdls_free_list(pHddTdlsCtx); + wlan_hdd_tdls_free_list(pHddTdlsCtx, false); pHddTdlsCtx->curr_candidate = NULL; @@ -2353,26 +2338,19 @@ hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, return NULL; } -static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) +void wlan_hdd_tdls_implicit_send_discovery_request(tdlsCtx_t * pHddTdlsCtx) { - tdlsCtx_t *pHddTdlsCtx = - container_of(work, tdlsCtx_t, implicit_setup); hdd_context_t *pHddCtx; hddTdlsPeer_t *curr_peer; hddTdlsPeer_t *temp_peer; - int status; tSirMacAddr peer_mac; ENTER(); if (NULL == pHddTdlsCtx) - return; - - if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: tdls magic number mis-match %u", - __func__, pHddTdlsCtx->magic); + FL("pHddTdlsCtx is NULL")); return; } @@ -2465,36 +2443,16 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) eTDLS_LINK_DISCOVERING, eTDLS_LINK_SUCCESS); - status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy, - pHddTdlsCtx->pAdapter->dev, - peer_mac); - - mutex_lock(&pHddCtx->tdls_lock); - - if (NULL == pHddTdlsCtx->curr_candidate) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: current candidate Not valid any more", __func__); - goto done; - } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Implicit TDLS, Send Discovery request event", __func__); - curr_peer = pHddTdlsCtx->curr_candidate; + cfg80211_tdls_oper_request(pHddTdlsCtx->pAdapter->dev, + curr_peer->peerMac, + NL80211_TDLS_DISCOVERY_REQ, + FALSE, + GFP_KERNEL); - if (0 != status) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: " MAC_ADDRESS_STR " discovery could not sent", - __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); - if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) - { - mutex_unlock(&pHddCtx->tdls_lock); - wlan_hdd_tdls_set_peer_link_status(curr_peer, - eTDLS_LINK_IDLE, - eTDLS_LINK_UNSPECIFIED); - mutex_lock(&pHddCtx->tdls_lock); - } - goto done; - } + mutex_lock(&pHddCtx->tdls_lock); pHddTdlsCtx->discovery_sent_cnt++; @@ -2519,13 +2477,6 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) return; } -static void wlan_hdd_tdls_pre_setup(struct work_struct *work) -{ - vos_ssr_protect(__func__); - __wlan_hdd_tdls_pre_setup(work); - vos_ssr_unprotect(__func__); -} - int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, struct wiphy *wiphy, #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) && !defined(WITH_BACKPORTS) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c index 9b7d3a7d7547..1ae10f9d4b53 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c @@ -341,6 +341,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_GET_11W_INFO 9 #endif #define WE_GET_STATES 10 +#define WE_GET_IBSS_STA_INFO 11 #define WE_GET_PHYMODE 12 #ifdef FEATURE_OEM_DATA_SUPPORT #define WE_GET_OEM_DATA_CAP 13 @@ -353,6 +354,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_DISPLAY_DXE_SNAP_SHOT 7 #define WE_SET_REASSOC_TRIGGER 8 #define WE_DISPLAY_DATAPATH_SNAP_SHOT 9 +#define WE_IBSS_GET_PEER_INFO_ALL 10 #define WE_DUMP_AGC_START 11 #define WE_DUMP_AGC 12 #define WE_DUMP_CHANINFO_START 13 @@ -375,7 +377,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #ifdef FEATURE_WLAN_TDLS #define WE_TDLS_CONFIG_PARAMS 5 #endif - +#define WE_IBSS_GET_PEER_INFO 6 #define WE_UNIT_TEST_CMD 7 #define WE_MTRACE_DUMP_CMD 8 @@ -688,17 +690,18 @@ int hdd_priv_get_data(struct iw_point *p_priv_data, extra - Pointer to char - \return - none + \return - zero on success, non zero value on failure --------------------------------------------------------------------------*/ -void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, +int hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, char *buffer, v_U16_t buf_len) { hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats; v_U32_t len; __u32 total_rxPkt = 0, total_rxDropped = 0; __u32 total_rxDelv = 0, total_rxRefused = 0; - int i = 0; + int i = 0, ret; + VOS_STATUS status; for (; i < NUM_CPUS; i++) { total_rxPkt += pStats->rxPackets[i]; @@ -732,14 +735,25 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, pStats->txCompleted, total_rxPkt, total_rxDropped, total_rxDelv, total_rxRefused); + if (len >= buf_len) { + hddLog(LOGE,FL("Insufficient buffer:%d, %d"), buf_len, len); + return -E2BIG; + } + for (i = 0; i < NUM_CPUS; i++) { - len += snprintf(buffer+len, buf_len-len, + ret = snprintf(buffer+len, buf_len-len, "\nReceive CPU: %d" "\n packets %u, dropped %u, delivered %u, refused %u", i, pStats->rxPackets[i], pStats->rxDropped[i], pStats->rxDelivered[i], pStats->rxRefused[i]); + if (ret >= (buf_len-len)) { + hddLog(LOGE,FL("Insufficient buffer:%d, %d"), (buf_len-len), ret); + return -E2BIG; + } + len += ret; } - len += snprintf(buffer+len, buf_len-len, + + ret = snprintf(buffer+len, buf_len-len, "\n" "\nNetQueue State : %s" "\n disable %u, enable %u" @@ -756,10 +770,23 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, pStats->txflow_unpause_cnt ); - WLANTL_Get_llStats(pAdapter->sessionId, + if (ret >= (buf_len-len)) { + hddLog(LOGE,FL("Insufficient buffer:%d, %d"), (buf_len-len), ret); + return -E2BIG; + } + len += ret; + + status = WLANTL_Get_llStats(pAdapter->sessionId, &buffer[len], (buf_len - len)); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE,FL("Error in getting stats:%d"), ret); + ret = (status == VOS_STATUS_E_NOMEM) ? -E2BIG: -EINVAL; + return ret; + } *length = strlen(buffer) + 1; + + return 0; } /**--------------------------------------------------------------------------- @@ -863,6 +890,116 @@ void hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu, return; } +v_MACADDR_t* hdd_wlan_get_ibss_mac_addr_from_staid(hdd_adapter_t *pAdapter, v_U8_t staIdx) +{ + v_U8_t idx; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) + { + if ( 0 != pHddStaCtx->conn_info.staId[ idx ] && + staIdx == pHddStaCtx->conn_info.staId[ idx ]) + { + return (&pHddStaCtx->conn_info.peerMacAddress[ idx ]); + } + } + return NULL; +} + +eHalStatus hdd_wlan_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tSirPeerInfoRspParams *pPeerInfo = &pStaCtx->ibss_peer_info; + + status = sme_RequestIBSSPeerInfo(hHal, pAdapter, hdd_get_ibss_peer_info_cb, + VOS_FALSE, staIdx); + + INIT_COMPLETION(pAdapter->ibss_peer_info_comp); + + if (eHAL_STATUS_SUCCESS == status) + { + unsigned long rc; + rc = wait_for_completion_timeout + (&pAdapter->ibss_peer_info_comp, + msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed wait on ibss_peer_info_comp")); + return eHAL_STATUS_FAILURE; + } + + /** Print the peer info */ + pr_info("pPeerInfo->numIBSSPeers = %d ", pPeerInfo->numPeers); + pr_info("============================================================"); + { + uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; + uint32_t tx_rate = pPeerInfo->peerInfoParams[0].txRate; + + vos_mem_copy(mac_addr, pPeerInfo->peerInfoParams[0].mac_addr, + sizeof(mac_addr)); + pr_info("PEER ADDR : %pM TxRate: %d Mbps RSSI: %d", + mac_addr, (int)tx_rate, (int)pPeerInfo->peerInfoParams[0].rssi); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); + } + + return status; +} + +eHalStatus hdd_wlan_get_ibss_peer_info_all(hdd_adapter_t *pAdapter) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tSirPeerInfoRspParams *pPeerInfo = &pStaCtx->ibss_peer_info; + int i; + + status = sme_RequestIBSSPeerInfo(hHal, pAdapter, hdd_get_ibss_peer_info_cb, + VOS_TRUE, 0xFF); + INIT_COMPLETION(pAdapter->ibss_peer_info_comp); + + if (eHAL_STATUS_SUCCESS == status) + { + unsigned long rc; + rc = wait_for_completion_timeout + (&pAdapter->ibss_peer_info_comp, + msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); + if (!rc) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed wait on ibss_peer_info_comp")); + return eHAL_STATUS_FAILURE; + } + + /** Print the peer info */ + pr_info("pPeerInfo->numIBSSPeers = %d ", (int)pPeerInfo->numPeers); + pr_info("============================================================"); + for (i = 0; i < pPeerInfo->numPeers; i++) { + uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; + uint32_t tx_rate; + + tx_rate = pPeerInfo->peerInfoParams[i].txRate; + vos_mem_copy(mac_addr, pPeerInfo->peerInfoParams[i].mac_addr, + sizeof(mac_addr)); + + pr_info(" PEER ADDR : %pM TxRate: %d Mbps RSSI: %d", + mac_addr, (int)tx_rate, (int)pPeerInfo->peerInfoParams[i].rssi); + } + } + else + { + hddLog(VOS_TRACE_LEVEL_WARN, + "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); + } + + return status; +} + int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) { tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -902,7 +1039,7 @@ int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) } int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) { - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tHalHandle hHal; v_U32_t threshold = 0, ret; hdd_context_t *hdd_ctx; @@ -914,6 +1051,7 @@ int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) return -EINVAL; } + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -4630,12 +4768,48 @@ static int iw_get_nick(struct net_device *dev, * __get_wireless_stats() - get wireless stats * @dev: pointer to net_device * - * Return: %NULL + * Return: pointer to iw_statistics on success, NULL otherwise */ static struct iw_statistics *__get_wireless_stats(struct net_device *dev) { + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); + hdd_station_ctx_t *hdd_sta_ctx; + v_S7_t snr = 0, rssi = 0; + int status; + ENTER(); - return NULL; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return NULL; + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (eConnectionState_Associated != hdd_sta_ctx->conn_info.connState) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("not in associated state: %d"), + hdd_sta_ctx->conn_info.connState); + return NULL; + } + + wlan_hdd_get_station_stats(adapter); + wlan_hdd_get_snr(adapter, &snr); + wlan_hdd_get_rssi(adapter, &rssi); + + vos_mem_zero(&wext_state->iw_stats, sizeof(wext_state->iw_stats)); + wext_state->iw_stats.status = 0; + wext_state->iw_stats.qual.qual = snr; + wext_state->iw_stats.qual.level = rssi; + wext_state->iw_stats.qual.noise = rssi - snr; + wext_state->iw_stats.discard.code = 0; + wext_state->iw_stats.discard.retries = 0; + wext_state->iw_stats.miss.beacon = 0; + wext_state->iw_stats.qual.updated = + IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; + + EXIT(); + return &(wext_state->iw_stats); } /** @@ -4656,7 +4830,6 @@ static struct iw_statistics *get_wireless_stats(struct net_device *dev) return iw_stats; } - /** * __iw_set_encode() - SIOCSIWENCODE ioctl handler * @dev: device upon which the ioctl was received @@ -5458,12 +5631,34 @@ static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info, } int process_wma_set_command(int sessid, int paramid, - int sval, int vpdev) + int sval, int vpdev) { int ret = 0; vos_msg_t msg = {0}; - wda_cli_set_cmd_t *iwcmd = (wda_cli_set_cmd_t *)vos_mem_malloc( + v_CONTEXT_t vos_context = vos_get_global_context(0, NULL); + hdd_context_t *hdd_ctx; + wda_cli_set_cmd_t *iwcmd; + + /* Skip session validation in FTM mode and for PDEV commands */ + if (vpdev == PDEV_CMD || VOS_FTM_MODE == hdd_get_conparam()) + goto skip_ftm; + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_context); + if (!hdd_ctx) { + hddLog(LOGE,FL("hdd context is not valid!")); + return -EINVAL; + } + + if (vpdev != PDEV_CMD && + VOS_STATUS_SUCCESS != sme_is_session_valid(hdd_ctx->hHal, + sessid)) { + hddLog(LOGE, FL("SME session id is not valid %d"), sessid); + return -EINVAL; + } + +skip_ftm: + iwcmd = (wda_cli_set_cmd_t *)vos_mem_malloc( sizeof(wda_cli_set_cmd_t)); if (NULL == iwcmd) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_mem_alloc failed", __func__); @@ -5479,7 +5674,7 @@ int process_wma_set_command(int sessid, int paramid, msg.bodyptr = (void *)iwcmd; if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " "Not able to post wda_cli_set_cmd message to WDA", __func__); vos_mem_free(iwcmd); @@ -5493,7 +5688,29 @@ int process_wma_set_command_twoargs(int sessid, int paramid, { int ret = 0; vos_msg_t msg = {0}; - wda_cli_set_cmd_t *iwcmd = vos_mem_malloc(sizeof(*iwcmd)); + wda_cli_set_cmd_t *iwcmd; + + v_CONTEXT_t vos_context = vos_get_global_context(0, NULL); + hdd_context_t *hdd_ctx; + /* Skip session validation in FTM mode and for PDEV commands */ + if (vpdev == PDEV_CMD || VOS_FTM_MODE == hdd_get_conparam()) + goto skip_ftm; + + hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_context); + + if (!hdd_ctx) { + hddLog(LOGE,FL("hdd context is not valid!")); + return -EINVAL; + } + + if (VOS_STATUS_SUCCESS != sme_is_session_valid(hdd_ctx->hHal, + sessid)) { + hddLog(LOGE, FL("SME session id is not valid %d"), sessid); + return -EINVAL; + } + +skip_ftm: + iwcmd = vos_mem_malloc(sizeof(*iwcmd)); if (NULL == iwcmd) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_mem_alloc failed!", __func__); @@ -7413,6 +7630,12 @@ static int __iw_setnone_getint(struct net_device *dev, if (0 != ret) return ret; + if (VOS_STATUS_SUCCESS != sme_is_session_valid(hHal, + pAdapter->sessionId)) { + hddLog(LOGE, FL("session id is not valid %d"), pAdapter->sessionId); + return -EINVAL; + } + switch (value[0]) { case WE_GET_11D_STATE: @@ -8035,9 +8258,8 @@ static int __iw_get_char_setnone(struct net_device *dev, case WE_GET_STATS: { - hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + return hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), extra, WE_MAX_STR_LEN); - break; } /* The case prints the current state of the HDD, SME, CSR, PE, TL @@ -8248,7 +8470,7 @@ static int __iw_get_char_setnone(struct net_device *dev, tChannelListInfo channel_list; memset(&channel_list, 0, sizeof(channel_list)); - status = iw_softap_get_channel_list(dev, info, wrqu, (char *)&channel_list); + status = iw_get_channel_list(dev, info, wrqu, (char *)&channel_list); if (!VOS_IS_STATUS_SUCCESS(status)) { hddLog(LOGE, FL("GetChannelList Failed!!!")); return -EINVAL; @@ -8308,6 +8530,35 @@ static int __iw_get_char_setnone(struct net_device *dev, break; } #endif + case WE_GET_IBSS_STA_INFO: + { + hdd_station_ctx_t *pHddStaCtx = + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int idx = 0; + int length = 0, buf = 0; + + for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++) + { + if (0 != pHddStaCtx->conn_info.staId[ idx ]) + { + buf = snprintf + ( + (extra + length), WE_MAX_STR_LEN - length, + "\n%d .%02x:%02x:%02x:%02x:%02x:%02x\n", + pHddStaCtx->conn_info.staId[ idx ], + pHddStaCtx->conn_info.peerMacAddress[idx].bytes[0], + pHddStaCtx->conn_info.peerMacAddress[idx].bytes[1], + pHddStaCtx->conn_info.peerMacAddress[idx].bytes[2], + pHddStaCtx->conn_info.peerMacAddress[idx].bytes[3], + pHddStaCtx->conn_info.peerMacAddress[idx].bytes[4], + pHddStaCtx->conn_info.peerMacAddress[idx].bytes[5] + ); + length += buf; + } + } + wrqu->data.length = strlen(extra)+1; + break; + } case WE_GET_PHYMODE: { v_BOOL_t ch_bond24 = VOS_FALSE, ch_bond5g = VOS_FALSE; @@ -8499,6 +8750,12 @@ static int __iw_setnone_getnone(struct net_device *dev, break; } + case WE_IBSS_GET_PEER_INFO_ALL: + { + hdd_wlan_get_ibss_peer_info_all(pAdapter); + break; + } + case WE_ENABLE_DXE_STALL_DETECT: { tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -8524,15 +8781,6 @@ static int __iw_setnone_getnone(struct net_device *dev, tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); v_U32_t roamId = 0; tCsrRoamModifyProfileFields modProfileFields; - hdd_station_ctx_t *pHddStaCtx = - WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - /* Reassoc to same AP, only supported for Open Security*/ - if ((pHddStaCtx->conn_info.ucEncryptionType || - pHddStaCtx->conn_info.mcEncryptionType)) { - hddLog(LOGE, - FL("Reassoc to same AP, only supported for Open Security")); - return -ENOTSUPP; - } sme_GetModifyProfileFields(hHal, pAdapter->sessionId, &modProfileFields); sme_RoamReassoc(hHal, pAdapter->sessionId, @@ -8720,6 +8968,12 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, } break; + case WE_IBSS_GET_PEER_INFO: + { + pr_info ( "Station ID = %d\n",apps_args[0]); + hdd_wlan_get_ibss_peer_info(pAdapter, apps_args[0]); + } + break; case WE_P2P_NOA_CMD: { @@ -12006,6 +12260,11 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, "getPMFInfo" }, #endif + { + WE_GET_IBSS_STA_INFO, + 0, + IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, + "getIbssSTAs" }, { WE_GET_PHYMODE, 0, IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, @@ -12028,6 +12287,11 @@ static const struct iw_priv_args we_private_args[] = { "" }, /* handlers for sub-ioctl */ + { + WE_IBSS_GET_PEER_INFO_ALL, + 0, + 0, + "ibssPeerInfoAll" }, { WE_GET_RECOVERY_STAT, 0, 0, @@ -12090,6 +12354,10 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, "dump" }, + { WE_IBSS_GET_PEER_INFO, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "ibssPeerInfo" }, /* handlers for sub-ioctl */ { WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD, diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h index 22c95bbd8f19..f5ecebefa911 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -289,6 +289,13 @@ enum wifi_logging_ring_id { RING_ID_FIRMWARE_DEBUG, }; +/* vendor element ID */ +#define IE_EID_VENDOR (221) /* 0xDD */ +#define IE_LEN_SIZE (1) +#define IE_EID_SIZE (1) +/* Minimum size of vendor IE = 3 bytes of oui_data + 1 byte of data */ +#define IE_VENDOR_OUI_SIZE (4) + // ------------------------------------------------------------------- // Change channel generic scheme typedef void (*CHANGE_CHANNEL_CALLBACK)(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, @@ -980,6 +987,7 @@ tLimMlmOemDataRsp *gpLimMlmOemDataRsp; tSirRemainOnChnReq *gpLimRemainOnChanReq; //hold remain on chan request in this buf vos_list_t gLimMgmtFrameRegistratinQueue; tANI_U32 mgmtFrameSessionId; + uint32_t tdls_frm_session_id; tSirBackgroundScanMode gLimBackgroundScanMode; #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) @@ -1253,6 +1261,8 @@ typedef struct sAniSirGlobal t_auth_ack_status auth_ack_status; bool first_scan_done; int8_t first_scan_bucket_threshold; + sir_mgmt_frame_ind_callback mgmt_frame_ind_cb; + sir_p2p_ack_ind_callback p2p_ack_ind_cb; } tAniSirGlobal; typedef enum diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h index c92227a1ed7d..95b5be903ee3 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h @@ -42,9 +42,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MINOR 4 #define QWLAN_VERSION_PATCH 31 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 52 +#define QWLAN_VERSION_BUILD 76 -#define QWLAN_VERSIONSTR "4.4.31.52" +#define QWLAN_VERSIONSTR "4.4.31.76" #define AR6320_REV1_VERSION 0x5000000 diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h index c786b8aa1893..fd3b24fe1ab9 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h @@ -967,10 +967,11 @@ typedef struct sSirSmeScanChanReq typedef struct sSirOemDataReq { - tANI_U16 messageType; //eWNI_SME_OEM_DATA_REQ + tANI_U16 messageType; /* eWNI_SME_OEM_DATA_REQ */ tANI_U16 messageLen; tSirMacAddr selfMacAddr; - tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tSirOemDataReq, *tpSirOemDataReq; typedef struct sSirOemDataRsp @@ -2281,6 +2282,14 @@ typedef struct sAniDHCPStopInd } tAniDHCPInd, *tpAniDHCPInd; +typedef struct sAniTXFailMonitorInd +{ + tANI_U16 msgType; // message type is same as the request type + tANI_U16 msgLen; // length of the entire request + tANI_U8 tx_fail_count; + void *txFailIndCallback; +} tAniTXFailMonitorInd, *tpAniTXFailMonitorInd; + typedef struct sAniSummaryStatsInfo { tANI_U32 retry_cnt[4]; //Total number of packets(per AC) that were successfully transmitted with retries @@ -3487,8 +3496,7 @@ typedef struct sSirSmeCoexInd typedef struct sSirSmeMgmtFrameInd { - tANI_U16 mesgType; - tANI_U16 mesgLen; + uint16_t frame_len; tANI_U32 rxChan; tANI_U8 sessionId; tANI_U8 frameType; @@ -3496,6 +3504,36 @@ typedef struct sSirSmeMgmtFrameInd tANI_U8 frameBuf[1]; //variable }tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd; + +typedef void (*sir_mgmt_frame_ind_callback)(tSirSmeMgmtFrameInd *frame_ind); +/** + * struct sir_sme_mgmt_frame_cb_req - Register a + * management frame callback req + * @message_type: message id + * @length: msg length + * @callback: callback for management frame indication + */ +struct sir_sme_mgmt_frame_cb_req { + uint16_t message_type; + uint16_t length; + sir_mgmt_frame_ind_callback callback; +}; + +typedef void (*sir_p2p_ack_ind_callback)(uint32_t session_id, + bool tx_completion_status); + +/** + * struct sir_p2p_ack_ind_cb_req - Register a p2p ack ind callback req + * @message_type: message id + * @length: msg length + * @callback: callback for p2p ack indication + */ +struct sir_sme_p2p_ack_ind_cb_req { + uint16_t message_type; + uint16_t length; + sir_p2p_ack_ind_callback callback; +}; + #ifdef WLAN_FEATURE_11W typedef struct sSirSmeUnprotMgmtFrameInd { @@ -3778,6 +3816,8 @@ struct roam_ext_params { typedef struct sSirRoamOffloadScanReq { + uint16_t message_type; + uint16_t length; eAniBoolean RoamScanOffloadEnabled; eAniBoolean MAWCEnabled; tANI_S8 LookupThreshold; @@ -3849,14 +3889,6 @@ typedef struct sSirRoamOffloadScanRsp tANI_U32 reason; } tSirRoamOffloadScanRsp, *tpSirRoamOffloadScanRsp; -struct sir_sme_roam_restart_req -{ - tANI_U16 message_type; - tANI_U16 length; - tANI_U8 sme_session_id; - tANI_U8 command; - tANI_U8 reason; -}; #endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #define SIR_NOCHANGE_POWER_VALUE 0xFFFFFFFF @@ -4571,6 +4603,48 @@ typedef struct sSirDelPeriodicTxPtrn tANI_U8 ucPtrnId; // Pattern ID } tSirDelPeriodicTxPtrn, *tpSirDelPeriodicTxPtrn; +/*--------------------------------------------------------------------------- +* tSirIbssGetPeerInfoReqParams +*--------------------------------------------------------------------------*/ +typedef struct +{ + tANI_BOOLEAN allPeerInfoReqd; // If set, all IBSS peers stats are reported + tANI_U8 staIdx; // If allPeerInfoReqd is not set, only stats + // of peer with staIdx is reported +}tSirIbssGetPeerInfoReqParams, *tpSirIbssGetPeerInfoReqParams; + +/** + * typedef struct - tSirIbssGetPeerInfoParams + * @mac_addr: mac address received from target + * @txRate: TX rate + * @mcsIndex: MCS index + * @txRateFlags: TX rate flags + * @rssi: RSSI + */ +typedef struct { + uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; + uint32_t txRate; + uint32_t mcsIndex; + uint32_t txRateFlags; + int8_t rssi; +}tSirIbssPeerInfoParams; + +typedef struct +{ + tANI_U32 status; + tANI_U8 numPeers; + tSirIbssPeerInfoParams peerInfoParams[32]; +}tSirPeerInfoRspParams, *tpSirIbssPeerInfoRspParams; + +/*--------------------------------------------------------------------------- +* tSirIbssGetPeerInfoRspParams +*--------------------------------------------------------------------------*/ +typedef struct +{ + tANI_U16 mesgType; + tANI_U16 mesgLen; + tSirPeerInfoRspParams ibssPeerInfoRspParams; +} tSirIbssGetPeerInfoRspParams, *tpSirIbssGetPeerInfoRspParams; typedef struct { @@ -4716,6 +4790,7 @@ typedef struct sSirModifyIE tANI_U8 ieIDLen; /*ie length as per spec*/ tANI_U16 ieBufferlength; tANI_U8 *pIEBuffer; + int32_t oui_length; }tSirModifyIE, *tpSirModifyIE; @@ -6497,6 +6572,17 @@ struct udp_resp_offload { }; +/** + * struct beacon_filter_param - parameters for beacon filtering + * @vdev_id: vdev id + * @ie_map: bitwise map of IEs that needs to be filtered + * + */ +struct beacon_filter_param { + uint32_t vdev_id; + uint32_t ie_map[8]; +}; + /** * struct smps_force_mode_event - smps force mode event param * @message_type: Type of message @@ -6511,4 +6597,18 @@ struct sir_smps_force_mode_event { uint8_t vdev_id; uint8_t status; }; + + +/** + * struct sir_del_all_tdls_peers - delete all tdls peers + * @msg_type: type of message + * @msg_len: length of message + * bssid: bssid of peer device + */ +struct sir_del_all_tdls_peers { + uint16_t msg_type; + uint16_t msg_len; + tSirMacAddr bssid; +}; + #endif /* __SIR_API_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h index e027c116705a..0635735b8ba6 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h @@ -202,10 +202,8 @@ enum eWniMsgTypes eWNI_SME_REMAIN_ON_CHANNEL_REQ, eWNI_SME_REMAIN_ON_CHN_IND, eWNI_SME_REMAIN_ON_CHN_RSP, - eWNI_SME_MGMT_FRM_IND, eWNI_SME_REMAIN_ON_CHN_RDY_IND, eWNI_SME_SEND_ACTION_FRAME_IND, - eWNI_SME_ACTION_FRAME_SEND_CNF, eWNI_SME_ABORT_REMAIN_ON_CHAN_IND, eWNI_SME_UPDATE_NOA, eWNI_SME_CLEAR_DFS_CHANNEL_LIST, @@ -339,6 +337,7 @@ enum eWniMsgTypes eWNI_SME_LPHB_IND, #endif /* FEATURE_WLAN_LPHB */ + eWNI_SME_IBSS_PEER_INFO_RSP, eWNI_SME_GET_TSM_STATS_REQ, eWNI_SME_GET_TSM_STATS_RSP, eWNI_SME_TSM_IE_IND, @@ -399,8 +398,11 @@ enum eWniMsgTypes eWNI_SME_EXT_CHANGE_CHANNEL_IND, eWNI_SME_LOST_LINK_INFO_IND, eWNI_SME_GET_RSSI_IND, - eWNI_SME_ROAM_RESTART_REQ, + eWNI_SME_ROAM_SCAN_OFFLOAD_REQ, eWNI_SME_SMPS_FORCE_MODE_IND, + eWNI_SME_DEL_ALL_TDLS_PEERS, + eWNI_SME_REGISTER_MGMT_FRAME_CB, + eWNI_SME_REGISTER_P2P_ACK_CB, eWNI_SME_MSG_TYPES_END }; diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h index 268d7496066a..a99db6140104 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -342,6 +342,7 @@ #define WNI_CFG_DFS_MASTER_ENABLED 295 #define WNI_CFG_VHT_ENABLE_TXBF_20MHZ 296 #define WNI_CFG_TDLS_WMM_MODE_ENABLED 297 +#define WNI_CFG_TGT_GTX_USR_CFG 298 /* * String parameter lengths @@ -2507,10 +2508,18 @@ #define WNI_CFG_TDLS_WMM_MODE_ENABLED_APMAX 1 #define WNI_CFG_TDLS_WMM_MODE_ENABLED_APDEF 0 -#define CFG_PARAM_MAX_NUM 298 +#define WNI_CFG_TGT_GTX_USR_CFG_STAMIN 0 +#define WNI_CFG_TGT_GTX_USR_CFG_STAMAX 32 +#define WNI_CFG_TGT_GTX_USR_CFG_STADEF 32 + +#define WNI_CFG_TGT_GTX_USR_CFG_APMIN 0 +#define WNI_CFG_TGT_GTX_USR_CFG_APMAX 32 +#define WNI_CFG_TGT_GTX_USR_CFG_APDEF 32 + +#define CFG_PARAM_MAX_NUM 299 #define CFG_AP_IBUF_MAX_SIZE 246 #define CFG_AP_SBUF_MAX_SIZE 3233 -#define CFG_STA_IBUF_MAX_SIZE 241 +#define CFG_STA_IBUF_MAX_SIZE 242 #define CFG_STA_SBUF_MAX_SIZE 3199 #define CFG_SEM_MAX_NUM 19 diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h index d0ff9c25de60..cfeafbc91051 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -336,6 +336,7 @@ #define WNI_CFG_DFS_MASTER_ENABLED 295 #define WNI_CFG_VHT_ENABLE_TXBF_20MHZ 296 #define WNI_CFG_TDLS_WMM_MODE_ENABLED 297 +#define WNI_CFG_TGT_GTX_USR_CFG 298 /* * String parameter lengths @@ -1604,8 +1605,12 @@ #define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX 1 #define WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF 0 -#define CFG_PARAM_MAX_NUM 298 -#define CFG_STA_IBUF_MAX_SIZE 241 +#define WNI_CFG_TGT_GTX_USR_CFG_STAMIN 0 +#define WNI_CFG_TGT_GTX_USR_CFG_STAMAX 32 +#define WNI_CFG_TGT_GTX_USR_CFG_STADEF 32 + +#define CFG_PARAM_MAX_NUM 299 +#define CFG_STA_IBUF_MAX_SIZE 242 #define CFG_STA_SBUF_MAX_SIZE 3199 #define CFG_SEM_MAX_NUM 19 diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c index 993974753b81..87cd511ddeec 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgApi.c @@ -973,7 +973,7 @@ cfgGetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 *pCap,tpPESession sessionEntr #if defined WLAN_FEATURE_VOWIFI pCapInfo->rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; #if defined WLAN_VOWIFI_DEBUG - cfgLog( pMac, LOGE, "RRM = %d", pCapInfo->rrm); + cfgLog( pMac, LOG1, "RRM = %d", pCapInfo->rrm); #endif #endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c index 4b53a83ec3e4..b14ee505cfd0 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -1899,7 +1899,13 @@ struct cgstatic cfg_static[CFG_PARAM_MAX_NUM] = { CFG_CTL_NTF_LIM, WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMIN, WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX, - WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF} + WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF}, + + {WNI_CFG_TGT_GTX_USR_CFG, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_TGT_GTX_USR_CFG_STAMIN, + WNI_CFG_TGT_GTX_USR_CFG_STAMAX, + WNI_CFG_TGT_GTX_USR_CFG_STADEF} }; struct cfgstatic_string cfg_static_string[CFG_MAX_STATIC_STRING] = { diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h index dd75d5e7b123..072b09cb3b40 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -805,7 +805,8 @@ PopulateDot11fSuppRates(tpAniSirGlobal pMac, tSirRetStatus populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, tDot11fIESuppRates *p_supp_rates, - tDot11fIEExtSuppRates *p_ext_supp_rates); + tDot11fIEExtSuppRates *p_ext_supp_rates, + uint8_t curr_oper_channel); tSirRetStatus PopulateDot11fTPCReport(tpAniSirGlobal pMac, tDot11fIETPCReport *pDot11f, diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h index 63d1f5b5d339..ed0a40cd171a 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h @@ -523,6 +523,10 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209) #define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 210) +/* For IBSS peer info related messages */ +#define SIR_HAL_IBSS_PEER_INFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 215) +#define SIR_HAL_IBSS_PEER_INFO_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 216) + #define SIR_HAL_RATE_UPDATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 217) #define SIR_HAL_FLUSH_LOG_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 218) @@ -553,6 +557,8 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP \ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 233) +#define SIR_HAL_TX_FAIL_MONITOR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 234) + #ifdef WLAN_FEATURE_11AC #define SIR_HAL_UPDATE_MEMBERSHIP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 235) #define SIR_HAL_UPDATE_USERPOS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 236) @@ -570,6 +576,12 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_BEACON_TX_SUCCESS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 242) #define SIR_HAL_DFS_RADAR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 243) +#define SIR_HAL_IBSS_CESIUM_ENABLE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 244) + +#define SIR_HAL_RMC_ENABLE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 245) +#define SIR_HAL_RMC_DISABLE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 246) +#define SIR_HAL_RMC_ACTION_PERIOD_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 247) + #define SIR_HAL_INIT_THERMAL_INFO_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 248) #define SIR_HAL_SET_THERMAL_LEVEL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 249) @@ -735,6 +747,8 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_SET_UDP_RESP_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 336) #define SIR_HAL_UPDATE_WEP_DEFAULT_KEY (SIR_HAL_ITC_MSG_TYPES_BEGIN + 337) +#define SIR_HAL_ADD_BCN_FILTER_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 346) +#define SIR_HAL_REMOVE_BCN_FILTER_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 347) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h index 45a6e1cb3e39..558f39eeaa56 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h @@ -125,6 +125,9 @@ void limDumpInit(tpAniSirGlobal pMac); extern void limCleanup(tpAniSirGlobal); /// Function to post messages to LIM thread extern tANI_U32 limPostMsgApi(tpAniSirGlobal, tSirMsgQ *); +uint32_t +lim_post_msg_high_pri(tpAniSirGlobal mac, tSirMsgQ *msg); + /** * Function to process messages posted to LIM thread * and dispatch to various sub modules within LIM module. diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h index 94807df42c70..af37b2b7882f 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h @@ -323,7 +323,8 @@ struct tLimScanResultNode typedef struct sLimMlmOemDataReq { tSirMacAddr selfMacAddr; - tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tLimMlmOemDataReq, *tpLimMlmOemDataReq; typedef struct sLimMlmOemDataRsp diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c index 2827fc77b26d..c95e5bf7a23a 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c @@ -291,6 +291,7 @@ static void __limInitVars(tpAniSirGlobal pMac) /* Init SAP deffered Q Head */ lim_init_sap_deferred_msg_queue(pMac); #endif + pMac->lim.gpLimMlmOemDataReq = NULL; } static void __limInitAssocVars(tpAniSirGlobal pMac) @@ -988,6 +989,7 @@ tSirRetStatus peOpen(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam) pMac->lim.maxStation, 0); pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; pMac->lim.deferredMsgCnt = 0; if (!VOS_IS_STATUS_SUCCESS(vos_lock_init(&pMac->lim.lkPeGlobalLock))) { @@ -1047,6 +1049,10 @@ tSirRetStatus peClose(tpAniSirGlobal pMac) pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; if (pMac->lim.gpLimMlmOemDataReq) { + if (pMac->lim.gpLimMlmOemDataReq->data) { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq->data); + pMac->lim.gpLimMlmOemDataReq->data = NULL; + } vos_mem_free(pMac->lim.gpLimMlmOemDataReq); pMac->lim.gpLimMlmOemDataReq = NULL; } @@ -1233,6 +1239,21 @@ limPostMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg) } /*** end limPostMsgApi() ***/ +/** + * lim_post_msg_high_pri() - posts high priority pe message + * @mac: mac context + * @msg: message to be posted + * + * This function is used to post high priority pe message + * + * Return: returns value returned by vos_mq_post_message_by_priority + */ +uint32_t +lim_post_msg_high_pri(tpAniSirGlobal mac, tSirMsgQ *msg) +{ + return vos_mq_post_message_by_priority(VOS_MQ_ID_PE, (vos_msg_t *)msg, + HIGH_PRIORITY); +} /*-------------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c index 7606aad9fa98..efe9c52c6825 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c @@ -656,10 +656,10 @@ limCleanupRxPath(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession psessionE */ if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + limDelSta(pMac, pStaDs, false, psessionEntry); limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry); } limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId,psessionEntry); - return retCode; } } @@ -1660,7 +1660,8 @@ tSirRetStatus limPopulateVhtMcsSet(tpAniSirGlobal pMac, pMac->roam.configParam.enable2x2, nss, pRates->vhtRxMCSMap, pRates->vhtTxMCSMap); - if (psessionEntry) { + /* Check if VHT caps present to determine session NSS */ + if ((psessionEntry) && (pPeerVHTCaps->present)) { psessionEntry->supported_nss_1x1 = ((pRates->vhtTxMCSMap & VHT_MCS_1x1) == VHT_MCS_1x1) ? true : false; @@ -2013,8 +2014,8 @@ limPopulatePeerRateSet(tpAniSirGlobal pMac, psessionEntry->supported_nss_1x1 = ((pRates->supportedMCSSet[1] != 0) ? false : true); - PELOG1(limLog(pMac, LOG1, FL("HT supported nss 1x1 : %d "), - psessionEntry->supported_nss_1x1);) + limLog(pMac, LOG1, FL("HT supported nss 1x1 : %d "), + psessionEntry->supported_nss_1x1); } #ifdef WLAN_FEATURE_11AC diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c index 9e5df46402eb..416a56b92da2 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c @@ -1004,9 +1004,19 @@ void limFillFTSession(tpAniSirGlobal pMac, pftSessionEntry->htSupportedChannelWidthSet; pftSessionEntry->enableHtSmps = psessionEntry->enableHtSmps; - pftSessionEntry->smpsMode = psessionEntry->smpsMode; - limLog(pMac, LOG1, FL("FT session enable smps: %d mode: %d"), - pftSessionEntry->enableHtSmps, pftSessionEntry->smpsMode); + pftSessionEntry->htSmpsvalue = psessionEntry->htSmpsvalue; + /* + * By default supported NSS 1x1 is set to true + * and later on updated while determining session + * supported rates which is the intersection of + * self and peer rates + */ + pftSessionEntry->supported_nss_1x1 = true; + limLog(pMac, LOG1, + FL("FT enable smps: %d mode: %d supported nss 1x1: %d"), + pftSessionEntry->enableHtSmps, + pftSessionEntry->htSmpsvalue, + pftSessionEntry->supported_nss_1x1); vos_mem_free(pBeaconStruct); } @@ -1263,6 +1273,7 @@ void limHandleFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status, vos_mem_copy(&(pftSessionEntry->htConfig), &(psessionEntry->htConfig), sizeof(psessionEntry->htConfig)); pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + pftSessionEntry->smpsMode = psessionEntry->smpsMode; PELOGE(limLog(pMac, LOG1, "%s:created session (%p) with id = %d", __func__, pftSessionEntry, pftSessionEntry->peSessionId);) @@ -1429,6 +1440,12 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, vos_mem_free(pMlmReassocReq); goto end; } + + lim_update_caps_info_for_bss(pMac, &caps, + psessionEntry->pLimReAssocReq->bssDescription.capabilityInfo); + + limLog(pMac, LOG1, FL("Capabilities info FT Reassoc: 0x%X"), caps); + pMlmReassocReq->capabilityInfo = caps; /* Update PE sessionId*/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c index 3938a819fd55..6174c193149b 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -80,7 +80,6 @@ extern tSirRetStatus limSetLinkState( tpSetLinkStateCallback callback, void *callbackArg); static tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession); -eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess); /*------------------------------------------------------------------ * * Below function is callback function, it is called when @@ -603,7 +602,7 @@ void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data) * indicaiton confirmation with status failure */ if (pMac->lim.mgmtFrameSessionId != 0xff) { - limP2PActionCnf(pMac, 0); + limP2PActionCnf(pMac, false); } return; @@ -621,7 +620,6 @@ void limSendSmeMgmtFrameInd( tANI_U32 rxChannel, tpPESession psessionEntry, tANI_S8 rxRssi) { - tSirMsgQ mmhMsg; tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL; tANI_U16 length; @@ -636,8 +634,7 @@ void limSendSmeMgmtFrameInd( } vos_mem_set((void*)pSirSmeMgmtFrame, length, 0); - pSirSmeMgmtFrame->mesgType = eWNI_SME_MGMT_FRM_IND; - pSirSmeMgmtFrame->mesgLen = length; + pSirSmeMgmtFrame->frame_len = frameLen; pSirSmeMgmtFrame->sessionId = sessionId; pSirSmeMgmtFrame->frameType = frameType; pSirSmeMgmtFrame->rxRssi = rxRssi; @@ -710,11 +707,13 @@ void limSendSmeMgmtFrameInd( vos_mem_zero(pSirSmeMgmtFrame->frameBuf,frameLen); vos_mem_copy(pSirSmeMgmtFrame->frameBuf,frame,frameLen); - mmhMsg.type = eWNI_SME_MGMT_FRM_IND; - mmhMsg.bodyptr = pSirSmeMgmtFrame; - mmhMsg.bodyval = 0; + if (pMac->mgmt_frame_ind_cb) + pMac->mgmt_frame_ind_cb(pSirSmeMgmtFrame); + else + limLog(pMac, LOGW, + FL("Management indication callback not registered!!")); + vos_mem_free(pSirSmeMgmtFrame); - limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); return; } /*** end limSendSmeListenRsp() ***/ @@ -725,9 +724,9 @@ eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess) { /* The session entry might be invalid(0xff) action confirmation received after * remain on channel timer expired */ - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - (txCompleteSuccess ? eSIR_SME_SUCCESS : eSIR_SME_SEND_ACTION_FAIL), - pMac->lim.mgmtFrameSessionId, 0); + if (pMac->p2p_ack_ind_cb) + pMac->p2p_ack_ind_cb(pMac->lim.mgmtFrameSessionId, + txCompleteSuccess); pMac->lim.mgmtFrameSessionId = 0xff; } @@ -769,8 +768,7 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { limLog(pMac, LOGE, FL("Remain on channel is not running")); - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + limP2PActionCnf(pMac, false); return; } smeSessionId = pMbMsg->sessionId; @@ -807,8 +805,7 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) } if( !isSessionActive ) { - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + limP2PActionCnf(pMac, false); return; } } @@ -966,8 +963,7 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { limLog(pMac, LOGE, FL("Failed to Send Action frame")); - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); + limP2PActionCnf(pMac, false); return; } } @@ -1006,61 +1002,29 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { vos_mem_copy(pFrame, pMbMsg->data, nBytes); } - #ifdef WLAN_FEATURE_11W pActionHdr = (tpSirMacActionFrameHdr) (pFrame + sizeof(tSirMacMgmtHdr)); - + pMacHdr = (tpSirMacMgmtHdr)pFrame; /* - * Setting Protected bit for SA_QUERY Action Frame + * Setting Protected bit only for Robust Action Frames * This has to be based on the current Connection with the station - * limSetProtectedBit API will set the protected bit if connection if PMF + * limSetProtectedBit API will set the protected bit if connection is PMF */ + psessionEntry = peFindSessionByBssid(pMac, + (tANI_U8*)pMbMsg->data + BSSID_OFFSET, &sessionId); - if ((SIR_MAC_MGMT_ACTION == pFc->subType) && - (SIR_MAC_ACTION_SA_QUERY == pActionHdr->category)) - { - pMacHdr = (tpSirMacMgmtHdr ) pFrame; - psessionEntry = peFindSessionByBssid(pMac, - (tANI_U8*)pMbMsg->data + BSSID_OFFSET, &sessionId); - - /* Check for session corresponding to ADDR2 ss supplicant is filling - ADDR2 with BSSID */ - if(NULL == psessionEntry) - { - psessionEntry = peFindSessionByBssid(pMac, - (tANI_U8*)pMbMsg->data + ADDR2_OFFSET, &sessionId); - } - - if(NULL != psessionEntry) - { - limSetProtectedBit(pMac, psessionEntry, pMacHdr->da, pMacHdr); - } - else - { - limLog(pMac, LOGE, - FL("Dropping SA Query frame - Unable to find PE Session")); - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); - palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, - ( void* ) pFrame, ( void* ) pPacket ); - return; - } - - /* - * If wep bit is not set in MAC header then we are trying to - * send SA Query via non PMF connection. Drop the packet. - */ - - if(0 == pMacHdr->fc.wep) - { - limLog(pMac, LOGE, - FL("Dropping SA Query frame due to non PMF connection")); - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0); - palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, - ( void* ) pFrame, ( void* ) pPacket ); - return; - } + /* + * Check for session corresponding to ADDR2 ss supplicant is filling + * ADDR2 with BSSID + */ + if (NULL == psessionEntry) + psessionEntry = peFindSessionByBssid(pMac, + (tANI_U8*)pMbMsg->data + ADDR2_OFFSET, &sessionId); + + if (psessionEntry && (SIR_MAC_MGMT_ACTION == pFc->subType) && + psessionEntry->limRmfEnabled && (!limIsGroupAddr(pMacHdr->da)) && + lim_is_robust_mgmt_action_frame(pActionHdr->category)) { + limSetProtectedBit(pMac, psessionEntry, pMacHdr->da, pMacHdr); } #endif @@ -1080,8 +1044,8 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) if (!pMbMsg->noack) { - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - halstatus, pMbMsg->sessionId, 0); + limP2PActionCnf(pMac, (HAL_STATUS_SUCCESS(halstatus)) ? + true : false); } pMac->lim.mgmtFrameSessionId = 0xff; } @@ -1096,8 +1060,7 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("could not send action frame!" )); - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, halstatus, - pMbMsg->sessionId, 0); + limP2PActionCnf(pMac, false); pMac->lim.mgmtFrameSessionId = 0xff; } else diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c index 5122856c4342..7fc993728835 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c @@ -2168,19 +2168,24 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps { tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); tpSirMacActionFrameHdr pActionHdr = (tpSirMacActionFrameHdr) pBody; + tANI_U32 frameLen; #ifdef WLAN_FEATURE_11W tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + + if (lim_is_robust_mgmt_action_frame(pActionHdr->category) && + limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, + pActionHdr->category)) { + limLog(pMac, LOGE, + FL("Don't send unprotect action frame to upper layer categ %d "), + pActionHdr->category); + return; + } #endif - tANI_U32 frameLen; frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); switch (pActionHdr->category) { case SIR_MAC_ACTION_QOS_MGMT: -#ifdef WLAN_FEATURE_11W - if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) - break; -#endif if ( (psessionEntry->limQosEnabled) || (pActionHdr->actionID == SIR_MAC_QOS_MAP_CONFIGURE) ) { @@ -2212,10 +2217,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps break; case SIR_MAC_ACTION_SPECTRUM_MGMT: -#ifdef WLAN_FEATURE_11W - if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) - break; -#endif switch (pActionHdr->actionID) { case SIR_MAC_ACTION_CHANNEL_SWITCH_ID: @@ -2265,10 +2266,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps case SIR_MAC_ACTION_BLKACK: // Determine the "type" of BA Action Frame -#ifdef WLAN_FEATURE_11W - if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) - break; -#endif switch(pActionHdr->actionID) { case SIR_MAC_BLKACK_ADD_REQ: @@ -2303,17 +2300,8 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps case SIR_MAC_ACTION_WNM: { -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL - ("Dropping unprotected Action category %d frame since RMF is enabled."), - pActionHdr->category);) - break; - } -#endif - PELOGE(limLog(pMac, LOG1, FL("WNM Action category %d action %d."), - pActionHdr->category, pActionHdr->actionID);) + limLog(pMac, LOG1, FL("WNM Action category %d action %d."), + pActionHdr->category, pActionHdr->actionID); switch (pActionHdr->actionID) { case SIR_MAC_WNM_BSS_TM_QUERY: @@ -2343,10 +2331,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps } #if defined WLAN_FEATURE_VOWIFI case SIR_MAC_ACTION_RRM: -#ifdef WLAN_FEATURE_11W - if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) - break; -#endif if( pMac->rrm.rrmPEContext.rrmEnable ) { switch(pActionHdr->actionID) { @@ -2490,8 +2474,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps case SIR_MAC_ACTION_SA_QUERY: { PELOGE(limLog(pMac, LOG1, FL("SA Query Action category %d action %d."), pActionHdr->category, pActionHdr->actionID);) - if (limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr, pActionHdr->category)) - break; switch (pActionHdr->actionID) { case SIR_MAC_SA_QUERY_REQ: diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c index 12324b1166de..ca72b9416b00 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -520,6 +520,7 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub "and setting NULL")); vos_mem_free(psessionEntry->assocRsp); psessionEntry->assocRsp = NULL; + psessionEntry->assocRspLen = 0; } psessionEntry->assocRsp = vos_mem_malloc(frameLen); @@ -539,6 +540,7 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub { vos_mem_free(psessionEntry->ricData); psessionEntry->ricData = NULL; + psessionEntry->RICDataLen = 0; } if(pAssocRsp->ricPresent) { psessionEntry->RICDataLen = @@ -584,6 +586,7 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub { vos_mem_free(psessionEntry->tspecIes); psessionEntry->tspecIes = NULL; + psessionEntry->tspecLen = 0; } if(pAssocRsp->tspecPresent) { limLog(pMac, LOG1, FL("Tspec EID present in assoc rsp")); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c index bdc4ddf51a85..b86eb352b2df 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c @@ -171,6 +171,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps { vos_mem_free(psessionEntry->beacon); psessionEntry->beacon = NULL; + psessionEntry->bcnLen = 0; } psessionEntry->bcnLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); psessionEntry->beacon = vos_mem_malloc(psessionEntry->bcnLen); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c index 4e89e3de5ce7..d0fbfc9db049 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 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. * @@ -249,6 +249,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession case eSIR_MAC_RSN_IE_MISMATCH_REASON: case eSIR_MAC_1X_AUTH_FAILURE_REASON: case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON: + case eSIR_MAC_PEER_REJECT_MECHANISIM_REASON: // Valid reasonCode in received Disassociation frame break; @@ -272,7 +273,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession FL("received Disassoc frame with invalid reasonCode " "%d from "MAC_ADDRESS_STR), reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) - return; + break; } } else diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c index bc7b78d4b452..c5602595cf9e 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -139,6 +139,18 @@ defMsgDecision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) (limMsg->type != WDA_START_OEM_DATA_RSP) && #endif (limMsg->type != WDA_ADD_TS_RSP) && + /* + * LIM won't process any defer queue commands if gLimAddtsSent is set to + * TRUE. gLimAddtsSent will be set TRUE to while sending ADDTS REQ. Say, + * when deferring is enabled, if SIR_LIM_ADDTS_RSP_TIMEOUT is posted + * (because of not receiving ADDTS RSP) then this command will be added + * to defer queue and as gLimAddtsSent is set TRUE LIM will never + * process any commands from defer queue, including + * SIR_LIM_ADDTS_RSP_TIMEOUT. Hence allowing SIR_LIM_ADDTS_RSP_TIMEOUT + * command to be processed with deferring enabled, so that this will be + * processed immediately and sets gLimAddtsSent to FALSE. + */ + (limMsg->type != SIR_LIM_ADDTS_RSP_TIMEOUT) && /* Allow processing of RX frames while awaiting reception of ADD TS response over the air. This logic particularly handles the case when host sends ADD BA request to FW after ADD TS request @@ -1421,7 +1433,9 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) case eWNI_SME_GET_TSM_STATS_REQ: #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ case eWNI_SME_EXT_CHANGE_CHANNEL: - case eWNI_SME_ROAM_RESTART_REQ: + case eWNI_SME_ROAM_SCAN_OFFLOAD_REQ: + case eWNI_SME_REGISTER_MGMT_FRAME_CB: + case eWNI_SME_REGISTER_P2P_ACK_CB: // These messages are from HDD limProcessNormalHddMsg(pMac, limMsg, false); //no need to response to hdd break; @@ -2157,6 +2171,13 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) lim_sap_offload_del_sta(pMac, limMsg); break; #endif /* SAP_AUTH_OFFLOAD */ + + case eWNI_SME_DEL_ALL_TDLS_PEERS: + lim_process_sme_del_all_tdls_peers(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/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c index ae1c6e580db2..1dbacdf5e18d 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -1352,32 +1352,37 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) tpStartOemDataReq pStartOemDataReq = NULL; tSirRetStatus rc = eSIR_SUCCESS; tpLimMlmOemDataRsp pMlmOemDataRsp; - tANI_U32 reqLen = 0; if(NULL == pMac->lim.gpLimMlmOemDataReq) { PELOGE(limLog(pMac, LOGE, FL("Null pointer"));) goto error; } - reqLen = sizeof(tStartOemDataReq); - - pStartOemDataReq = vos_mem_malloc(reqLen); + pStartOemDataReq = vos_mem_malloc(sizeof(*pStartOemDataReq)); if ( NULL == pStartOemDataReq ) { PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq"));) goto error; } - vos_mem_set((tANI_U8*)(pStartOemDataReq), reqLen, 0); + pStartOemDataReq->data = + vos_mem_malloc(pMac->lim.gpLimMlmOemDataReq->data_len); + if (!pStartOemDataReq->data) { + limLog(pMac, LOGE, FL("memory allocation failed")); + vos_mem_free(pStartOemDataReq); + goto error; + } //Now copy over the information to the OEM DATA REQ to HAL vos_mem_copy(pStartOemDataReq->selfMacAddr, pMac->lim.gpLimMlmOemDataReq->selfMacAddr, sizeof(tSirMacAddr)); - vos_mem_copy(pStartOemDataReq->oemDataReq, - pMac->lim.gpLimMlmOemDataReq->oemDataReq, - OEM_DATA_REQ_SIZE); + pStartOemDataReq->data_len = + pMac->lim.gpLimMlmOemDataReq->data_len; + vos_mem_copy(pStartOemDataReq->data, + pMac->lim.gpLimMlmOemDataReq->data, + pMac->lim.gpLimMlmOemDataReq->data_len); //Create the message to be passed to HAL msg.type = WDA_START_OEM_DATA_REQ; @@ -1394,8 +1399,9 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + vos_mem_free(pStartOemDataReq->data); vos_mem_free(pStartOemDataReq); - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_START_OEM_DATA_REQ to HAL failed"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_pStartOemDataReq to HAL failed"));) error: pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; @@ -1410,6 +1416,10 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) if(NULL != pMac->lim.gpLimMlmOemDataReq) { + if (NULL != pMac->lim.gpLimMlmOemDataReq->data) { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq->data); + pMac->lim.gpLimMlmOemDataReq->data = NULL; + } vos_mem_free(pMac->lim.gpLimMlmOemDataReq); pMac->lim.gpLimMlmOemDataReq = NULL; } @@ -1989,6 +1999,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { tLimMlmOemDataRsp* pMlmOemDataRsp; + tLimMlmOemDataReq *data_req = (tLimMlmOemDataReq *)pMsgBuf; if (((pMac->lim.gLimMlmState == eLIM_MLM_IDLE_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_JOINED_STATE) || @@ -2003,12 +2014,16 @@ static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * second OEM data request */ if (pMac->lim.gpLimMlmOemDataReq) { + if (pMac->lim.gpLimMlmOemDataReq->data) { + vos_mem_free(pMac->lim.gpLimMlmOemDataReq->data); + pMac->lim.gpLimMlmOemDataReq->data = NULL; + } vos_mem_free(pMac->lim.gpLimMlmOemDataReq); pMac->lim.gpLimMlmOemDataReq = NULL; } - pMac->lim.gpLimMlmOemDataReq = (tLimMlmOemDataReq*)pMsgBuf; - + pMac->lim.gpLimMlmOemDataReq = data_req; + pMac->lim.gpLimMlmOemDataReq->data = data_req->data; pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState; PELOG2(limLog(pMac, LOG2, diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c index 416ae572d77a..e78980722a09 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -2038,6 +2038,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA; psessionEntry->staId = pAddStaParams->staIdx; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; goto end; } } @@ -2126,6 +2127,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess mlmAssocCnf.resultCode = (tSirResultCodes)eSIR_SME_FT_REASSOC_FAILURE; else mlmAssocCnf.resultCode = (tSirResultCodes)eSIR_SME_REFUSED; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; } end: if( 0 != limMsgQ->bodyptr ) @@ -3279,6 +3281,7 @@ limProcessStaMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession ps } else { limLog(pMac, LOGP, FL("SessionId:%d ADD_BSS failed!"), psessionEntry->peSessionId); + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; /* Return Assoc confirm to SME with failure */ // Return Assoc confirm to SME with failure if(eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == psessionEntry->limMlmState) @@ -5067,9 +5070,7 @@ void limProcessRxScanEvent(tpAniSirGlobal pMac, void *buf) * pending then indicate confirmation with status failure */ if (pMac->lim.mgmtFrameSessionId != 0xff) { - limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, - eSIR_SME_SEND_ACTION_FAIL, - pMac->lim.mgmtFrameSessionId, 0); + limP2PActionCnf(pMac, false); pMac->lim.mgmtFrameSessionId = 0xff; } diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c index 44ea55c6b01b..e6c2d4b39d93 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -79,6 +79,7 @@ limValidateIEInformationInProbeRspFrame (tpAniSirGlobal pMac, if ( status == eSIR_SUCCESS ) { WDA_GET_RX_MPDU_LEN(pRxPacketInfo) += nMissingRsnBytes; + WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) += nMissingRsnBytes; } return status; @@ -235,6 +236,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession { vos_mem_free(psessionEntry->beacon); psessionEntry->beacon = NULL; + psessionEntry->bcnLen = 0; } psessionEntry->bcnLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index 30caa7e1c2ad..c6d2760f2984 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -111,6 +111,10 @@ static void limUpdateAddIEBuffer(tpAniSirGlobal pMac, tANI_U16 *pDstDataLen, tANI_U8 *pSrcData_buff, tANI_U16 srcDataLen); +static tANI_BOOLEAN limUpdateIBssPropAddIEs(tpAniSirGlobal pMac, + tANI_U8 **pDstData_buff, + tANI_U16 *pDstDataLen, + tSirModifyIE *pModifyIE); static void limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg); static void limProcessUpdateAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg); @@ -1720,20 +1724,28 @@ static void __limProcessSmeOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pOemDataReq = (tpSirOemDataReq) pMsgBuf; //post the lim mlm message now - pMlmOemDataReq = vos_mem_malloc(sizeof(tLimMlmOemDataReq)); + pMlmOemDataReq = vos_mem_malloc(sizeof(*pMlmOemDataReq)); if ( NULL == pMlmOemDataReq ) { limLog(pMac, LOGP, FL("AllocateMemory failed for mlmOemDataReq")); return; } - //Initialize this buffer - vos_mem_set( pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)), 0); + pMlmOemDataReq->data = vos_mem_malloc(pOemDataReq->data_len); + if (!pMlmOemDataReq->data) { + limLog(pMac, LOGP, FL("memory allocation failed")); + vos_mem_free(pMlmOemDataReq); + return; + } vos_mem_copy( pMlmOemDataReq->selfMacAddr, pOemDataReq->selfMacAddr, sizeof(tSirMacAddr)); - vos_mem_copy( pMlmOemDataReq->oemDataReq, pOemDataReq->oemDataReq, - OEM_DATA_REQ_SIZE); + + pMlmOemDataReq->data_len = pOemDataReq->data_len; + vos_mem_copy(pMlmOemDataReq->data, pOemDataReq->data, + pOemDataReq->data_len); + /* buffer from SME copied, free it now */ + vos_mem_free(pOemDataReq->data); //Issue LIM_MLM_OEM_DATA_REQ to MLM limPostMlmMessage(pMac, LIM_MLM_OEM_DATA_REQ, (tANI_U32*)pMlmOemDataReq); @@ -1954,10 +1966,19 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->enableAmpduPs = pSmeJoinReq->enableAmpduPs; psessionEntry->enableHtSmps = pSmeJoinReq->enableHtSmps; psessionEntry->htSmpsvalue = pSmeJoinReq->htSmps; + /* + * By default supported NSS 1x1 is set to true + * and later on updated while determining session + * supported rates which is the intersection of + * self and peer rates + */ + psessionEntry->supported_nss_1x1 = true; - limLog(pMac, LOG1, FL("enableHtSmps: %d htSmps: %d"), + limLog(pMac, LOG1, + FL("enableHtSmps: %d htSmps: %d supported NSS 1x1: %d"), psessionEntry->enableHtSmps, - psessionEntry->htSmpsvalue); + psessionEntry->htSmpsvalue, + psessionEntry->supported_nss_1x1); /*Store Persona */ psessionEntry->pePersona = pSmeJoinReq->staPersona; @@ -2432,9 +2453,10 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->enableHtSmps = pReassocReq->enableHtSmps; psessionEntry->htSmpsvalue = pReassocReq->htSmps; - limLog(pMac, LOG1, FL("enableHtSmps: %d htSmps: %d"), + limLog(pMac, LOG1, FL("enableHtSmps: %d htSmps: %d supported nss 1x1: %d"), psessionEntry->enableHtSmps, - psessionEntry->htSmpsvalue); + psessionEntry->htSmpsvalue, + psessionEntry->supported_nss_1x1); /** * Reassociate request is expected @@ -2593,6 +2615,12 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limLog(pMac, LOGP, FL("could not retrieve Capabilities value")); } + + lim_update_caps_info_for_bss(pMac, &caps, + pReassocReq->bssDescription.capabilityInfo); + + limLog(pMac, LOG1, FL("Capabilities info Reassoc: 0x%X"), caps); + pMlmReassocReq->capabilityInfo = caps; /* Update PE sessionId*/ @@ -4817,37 +4845,35 @@ limSendVdevRestart(tpAniSirGlobal pMac, vos_mem_free(pHalHiddenSsidVdevRestart); } } -static void __lim_process_roam_restart_req(tpAniSirGlobal mac_ctx, + +static void __lim_process_roam_scan_offload_req(tpAniSirGlobal mac_ctx, tANI_U32 *msg_buf) { - struct sir_sme_roam_restart_req *msg; - tSirRoamOffloadScanReq *req_buffer; tpPESession pe_session; tSirMsgQ wma_msg; tSirRetStatus status; + tSirRoamOffloadScanReq *msg, *req_buffer; - msg = (struct sir_sme_roam_restart_req *)msg_buf; + msg = (tSirRoamOffloadScanReq *)msg_buf; pe_session = pe_find_session_by_sme_session_id(mac_ctx, - msg->sme_session_id); - if (NULL == pe_session) { - limLog(mac_ctx, LOGE, - FL("session does not exist for sme_session: %d"), - msg->sme_session_id); - return; - } - /* Add log for unset of the flag */ + msg->sessionId); + + /* Set roaming_in_progress flag according to the command */ + if ( pe_session && (msg->Command == ROAM_SCAN_OFFLOAD_START || + msg->Command == ROAM_SCAN_OFFLOAD_RESTART || + msg->Command == ROAM_SCAN_OFFLOAD_STOP)) pe_session->roaming_in_progress = false; + req_buffer = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq)); if (NULL == req_buffer) { limLog(mac_ctx, LOGE, FL("Mem Alloc failed for req buffer")); return; } - vos_mem_zero(req_buffer, sizeof(tSirRoamOffloadScanReq)); + + *req_buffer = *msg; + vos_mem_zero(&wma_msg, sizeof(tSirMsgQ)); - req_buffer->Command = msg->command; - req_buffer->reason = msg->reason; - req_buffer->sessionId = msg->sme_session_id; wma_msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; wma_msg.bodyptr = req_buffer; @@ -5714,6 +5740,59 @@ __limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) return; } +/* lim_register_p2p_ack_ind_cb() - Save the p2p ack indication callback. + * @mac_ctx: Mac pointer + * @msg_buf: Msg pointer containing the callback + * + * This function is used to save the p2p ack indication callback in PE. + * + * Return: None + */ +static void lim_register_p2p_ack_ind_cb(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + struct sir_sme_p2p_ack_ind_cb_req *sme_req = + (struct sir_sme_p2p_ack_ind_cb_req *)msg_buf; + + if (NULL == msg_buf) { + limLog(mac_ctx, LOGE, FL("msg_buf is null")); + return; + } + if (sme_req->callback) + mac_ctx->p2p_ack_ind_cb = + sme_req->callback; + else + limLog(mac_ctx, LOGE, FL("sme_req->callback is null")); +} + +/** + * lim_register_mgmt_frame_ind_cb() - Save the Management frame + * indication callback in PE. + * @mac_ctx: Mac pointer + * @msg_buf: Msg pointer containing the callback + * + * This function is used save the Management frame + * indication callback in PE. + * + * Return: None + */ +static void lim_register_mgmt_frame_ind_cb(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + struct sir_sme_mgmt_frame_cb_req *sme_req = + (struct sir_sme_mgmt_frame_cb_req *)msg_buf; + + if (NULL == msg_buf) { + limLog(mac_ctx, LOGE, FL("msg_buf is null")); + return; + } + if (sme_req->callback) + mac_ctx->mgmt_frame_ind_cb = + sme_req->callback; + else + limLog(mac_ctx, LOGE, FL("sme_req->callback is null")); +} + /** * limProcessSmeReqMessages() * @@ -5948,8 +6027,8 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_HIDE_SSID_REQ: __limProcessSmeHideSSID(pMac, pMsgBuf); break; - case eWNI_SME_ROAM_RESTART_REQ: - __lim_process_roam_restart_req(pMac, pMsgBuf); + case eWNI_SME_ROAM_SCAN_OFFLOAD_REQ: + __lim_process_roam_scan_offload_req(pMac, pMsgBuf); break; case eWNI_SME_UPDATE_APWPSIE_REQ: __limProcessSmeUpdateAPWPSIEs(pMac, pMsgBuf); @@ -6053,6 +6132,12 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_PDEV_SET_HT_VHT_IE: lim_process_set_pdev_IEs(pMac, pMsgBuf); break; + case eWNI_SME_REGISTER_MGMT_FRAME_CB: + lim_register_mgmt_frame_ind_cb(pMac, pMsgBuf); + break; + case eWNI_SME_REGISTER_P2P_ACK_CB: + lim_register_p2p_ack_ind_cb(pMac, pMsgBuf); + break; default: vos_mem_free((v_VOID_t*)pMsg->bodyptr); pMsg->bodyptr = NULL; @@ -6382,6 +6467,44 @@ limUpdateAddIEBuffer(tpAniSirGlobal pMac, } +/** + * limUpdateIBssPropAddIEs() - update IBSS prop IE + * @pMac : Pointer to Global MAC structure + * @pDstData_buff : A pointer to pointer of tANI_U8 dst buffer + * @pDstDataLen : A pointer to pointer of tANI_U16 dst buffer length + * @pModifyIE : A pointer to tSirModifyIE + * + * This function replaces previous ibss prop_ie with new ibss prop_ie. + * + * Return: + * True or false depending upon whether IE is updated or not + */ +static tANI_BOOLEAN +limUpdateIBssPropAddIEs(tpAniSirGlobal pMac, tANI_U8 **pDstData_buff, + tANI_U16 *pDstDataLen, tSirModifyIE *pModifyIE) +{ + int32_t oui_length; + uint8_t *ibss_ie = NULL; + + ibss_ie = pModifyIE->pIEBuffer; + oui_length = pModifyIE->oui_length; + + if ((0 == oui_length) || (NULL == ibss_ie)) { + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + FL("Invalid set IBSS vendor IE comamnd length %d ibss_ie %p"), + oui_length, ibss_ie); + return FALSE; + } + + limUpdateAddIEBuffer(pMac, + pDstData_buff, + pDstDataLen, + pModifyIE->pIEBuffer, + pModifyIE->ieBufferlength); + + return TRUE; +} + /****************************************************************************** * limProcessModifyAddIEs() * @@ -6402,7 +6525,7 @@ static void limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) { tpSirModifyIEsInd pModifyAddIEs = (tpSirModifyIEsInd)pMsg; - tANI_U8 sessionId; + tANI_U8 sessionId; tANI_BOOLEAN ret = FALSE; /* Incoming message has smeSession, use BSSID to find PE session*/ @@ -6422,6 +6545,12 @@ limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) case eUPDATE_IE_PROBE_RESP: { /* Probe resp */ + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + limUpdateIBssPropAddIEs(pMac, + &psessionEntry->addIeParams.probeRespData_buff, + &psessionEntry->addIeParams.probeRespDataLen, + &pModifyAddIEs->modifyIE); + } break; } case eUPDATE_IE_ASSOC_RESP: @@ -6437,6 +6566,12 @@ limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) case eUPDATE_IE_PROBE_BCN: { /*probe beacon IE*/ + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + ret = limUpdateIBssPropAddIEs(pMac, + &psessionEntry->addIeParams.probeRespBCNData_buff, + &psessionEntry->addIeParams.probeRespBCNDataLen, + &pModifyAddIEs->modifyIE); + } if (ret == TRUE && pModifyAddIEs->modifyIE.notify) { limHandleParamUpdate(pMac, pModifyAddIEs->updateType); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c index 5ce5580f58f5..e30334340fac 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c @@ -341,27 +341,37 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, return(header_offset += PAYLOAD_TYPE_TDLS_SIZE) ; } -/* - * TX Complete for Management frames +/** + * lim_mgmt_tdls_tx_complete - callback to indicate Tx completion + * @mac_ctx: pointer to mac structure + * @tx_complete: indicates tx sucess/failure + * + * function will be invoked on receiving tx completion indication + * + * return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE */ - eHalStatus limMgmtTXComplete(tpAniSirGlobal pMac, - tANI_U32 txCompleteSuccess) +eHalStatus lim_mgmt_tdls_tx_complete(tpAniSirGlobal mac_ctx, + uint32_t tx_complete) { - tpPESession psessionEntry = NULL ; + tpPESession session_entry = NULL ; - if (0xff != pMac->lim.mgmtFrameSessionId) - { - psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.mgmtFrameSessionId); - if (NULL == psessionEntry) - { - limLog(pMac, LOGE, FL("sessionID %d is not found"), - pMac->lim.mgmtFrameSessionId); - return eHAL_STATUS_FAILURE; - } - limSendSmeMgmtTXCompletion(pMac, psessionEntry, txCompleteSuccess); - pMac->lim.mgmtFrameSessionId = 0xff; - } - return eHAL_STATUS_SUCCESS; + limLog(mac_ctx, LOG1, FL("tdls_frm_session_id %x tx_complete %x"), + mac_ctx->lim.tdls_frm_session_id, tx_complete); + + if (0xff != mac_ctx->lim.tdls_frm_session_id) { + session_entry = peFindSessionBySessionId(mac_ctx, + mac_ctx->lim.tdls_frm_session_id); + if (NULL == session_entry) { + limLog(mac_ctx, LOGE, FL("session id %d is not found"), + mac_ctx->lim.tdls_frm_session_id); + return eHAL_STATUS_FAILURE; + } + + limSendSmeMgmtTXCompletion(mac_ctx, session_entry, tx_complete); + mac_ctx->lim.tdls_frm_session_id = 0xff; + } + + return eHAL_STATUS_SUCCESS; } /* @@ -531,18 +541,18 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_REQ), MAC_ADDR_ARRAY(peer_mac)); - pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + pMac->lim.tdls_frm_session_id = psessionEntry->peSessionId; halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, false ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; limLog(pMac, LOGE, FL("could not send TDLS Discovery Request frame")); return eSIR_FAILURE; } @@ -715,7 +725,8 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, /* populate supported rate and ext supported rate IE */ if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac, &tdlsDisRsp.SuppRates, - &tdlsDisRsp.ExtSuppRates)) + &tdlsDisRsp.ExtSuppRates, + psessionEntry->currentOperChannel)) limLog(pMac, LOGE, FL("could not populate supported data rates")); @@ -847,7 +858,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, MAC_ADDR_ARRAY(peerMac)); - pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + pMac->lim.tdls_frm_session_id = psessionEntry->peSessionId; /* * Transmit Discovery response and watch if this is delivered to * peer STA. @@ -861,11 +872,11 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, ANI_TXDIR_IBSS, 0, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_SELF_STA_REQUESTED_MASK, smeSessionId, false ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; limLog(pMac, LOGE, FL("could not send TDLS Discovery Response frame!")); return eSIR_FAILURE; } @@ -965,9 +976,13 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, } swapBitField16(caps, ( tANI_U16* )&tdlsSetupReq.Capabilities ); + limLog(pMac, LOG1, FL("Sending operating channel %d and dotl11mode %d\n"), + psessionEntry->currentOperChannel, psessionEntry->dot11mode); + /* populate supported rate and ext supported rate IE */ populate_dot11f_rates_tdls(pMac, &tdlsSetupReq.SuppRates, - &tdlsSetupReq.ExtSuppRates); + &tdlsSetupReq.ExtSuppRates, + psessionEntry->currentOperChannel); /* Populate extended supported rates */ PopulateDot11fTdlsExtCapability(pMac, psessionEntry, &tdlsSetupReq.ExtCap); @@ -1157,14 +1172,14 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_REQ), MAC_ADDR_ARRAY(peerMac)); - pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + pMac->lim.tdls_frm_session_id = psessionEntry->peSessionId; #if defined(CONFIG_HL_SUPPORT) halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, true ); #else @@ -1173,13 +1188,13 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, false ); #endif if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; limLog(pMac, LOGE, FL("could not send TDLS Setup Request frame!")); return eSIR_FAILURE; } @@ -1366,14 +1381,14 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, "AP": "DIRECT"), MAC_ADDR_ARRAY(peerMac)); - pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + pMac->lim.tdls_frm_session_id = psessionEntry->peSessionId; #if defined(CONFIG_HL_SUPPORT) halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? true : false ); @@ -1383,14 +1398,14 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, false ); #endif if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; limLog(pMac, LOGE, FL("could not send TDLS Teardown frame")); return eSIR_FAILURE; @@ -1459,7 +1474,8 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, /* populate supported rate and ext supported rate IE */ populate_dot11f_rates_tdls(pMac, &tdlsSetupRsp.SuppRates, - &tdlsSetupRsp.ExtSuppRates); + &tdlsSetupRsp.ExtSuppRates, + psessionEntry->currentOperChannel); /* Populate extended supported rates */ PopulateDot11fTdlsExtCapability(pMac, psessionEntry, &tdlsSetupRsp.ExtCap); @@ -1644,14 +1660,14 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_RSP), MAC_ADDR_ARRAY(peerMac)); - pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + pMac->lim.tdls_frm_session_id = psessionEntry->peSessionId; #if defined(CONFIG_HL_SUPPORT) halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, true ); #else @@ -1660,13 +1676,13 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, false ); #endif if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; limLog(pMac, LOGE, FL("could not send TDLS Setup Response")); return eSIR_FAILURE; } @@ -1875,14 +1891,14 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_CNF), MAC_ADDR_ARRAY(peerMac)); - pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + pMac->lim.tdls_frm_session_id = psessionEntry->peSessionId; #if defined(CONFIG_HL_SUPPORT) halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, true ); #else @@ -1891,14 +1907,14 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, ANI_TXDIR_TODS, TID_AC_VI, limTxComplete, pFrame, - limMgmtTXComplete, + lim_mgmt_tdls_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, smeSessionId, false ); #endif if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.tdls_frm_session_id = 0xff; limLog(pMac, LOGE, FL("could not send TDLS Setup Confirm frame")); return eSIR_FAILURE; @@ -2636,19 +2652,22 @@ void PopulateDot11fTdlsOffchannelParams(tpAniSirGlobal pMac, /* validating the channel list for DFS and 2G channels */ for (i = 0U; i < numChans; i++) { - if (band == eCSR_BAND_24) { - if (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(validChan[i])) { + if ((band == eCSR_BAND_5G) && (NSS_2x2_MODE == nss_5g) && + (NSS_1x1_MODE == nss_2g) && + (true == vos_nv_skip_dsrc_dfs_2g(validChan[i], + NV_CHANNEL_SKIP_2G))) { + limLog(pMac, LOG1, + FL("skipping channel %d, nss_5g: %d, nss_2g: %d"), + validChan[i], nss_5g, nss_2g); + continue; + } else { + if (true == vos_nv_skip_dsrc_dfs_2g(validChan[i], + NV_CHANNEL_SKIP_DSRC)) { limLog(pMac, LOG1, - FL("skipping DFS channel %d from the valid channel list"), + FL("skipping channel %d from the valid channel list"), validChan[i]); continue; } - } else if ((NSS_2x2_MODE == nss_5g) && (NSS_1x1_MODE == nss_2g) && - (true == vos_nv_skip_dfs_and_2g(validChan[i]))){ - limLog(pMac, LOG1, - FL("skipping channel %d, nss_5g: %d, nss_2g: %d"), - validChan[i], nss_5g, nss_2g); - continue; } if (valid_count >= @@ -3282,11 +3301,64 @@ tSirRetStatus limProcesSmeTdlsLinkEstablishReq(tpAniSirGlobal pMac, } +/** + * lim_check_aid_and_delete_peer - Funtion to check aid and delete peer + * @p_mac: pointer to mac context + * @session_entry: pointer to PE session + * + * Function verifies aid and delete's peer with that aid from hash table + * + * return: none + */ +static void lim_check_aid_and_delete_peer(tpAniSirGlobal p_mac, + tpPESession session_entry) +{ + tpDphHashNode sta_ds = NULL ; + int i, aid; + + /* + * Check all the set bit in peerAIDBitmap and delete the + * peer (with that aid) entry from the hash table and add + * the aid in free pool + */ + for (i = 0; i < sizeof(session_entry->peerAIDBitmap)/sizeof(uint32_t); + i++) { + for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) { + if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid)) + continue; + + sta_ds = dphGetHashEntry(p_mac, + (aid + i*(sizeof(uint32_t) << 3)), + &session_entry->dph.dphHashTable); + + if (NULL == sta_ds) + goto skip; + + limLog(p_mac, LOG1, + FL("Deleting "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(sta_ds->staAddr)); + limSendDeauthMgmtFrame(p_mac, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + sta_ds->staAddr, session_entry, + FALSE); + limTdlsDelSta(p_mac, sta_ds->staAddr, + session_entry); + dphDeleteHashEntry(p_mac, + sta_ds->staAddr, + sta_ds->assocId, + &session_entry->dph.dphHashTable); +skip: + limReleasePeerIdx(p_mac, + (aid + i*(sizeof(uint32_t) << 3)), + session_entry); + CLEAR_BIT(session_entry->peerAIDBitmap[i], aid); + } + } +} + /* Delete all the TDLS peer connected before leaving the BSS */ tSirRetStatus limDeleteTDLSPeers(tpAniSirGlobal pMac, tpPESession psessionEntry) { - tpDphHashNode pStaDs = NULL ; - int i, aid; if (NULL == psessionEntry) { @@ -3294,33 +3366,44 @@ tSirRetStatus limDeleteTDLSPeers(tpAniSirGlobal pMac, tpPESession psessionEntry) return eSIR_FAILURE; } - /* Check all the set bit in peerAIDBitmap and delete the peer (with that aid) entry - from the hash table and add the aid in free pool */ - for (i = 0; i < sizeof(psessionEntry->peerAIDBitmap)/sizeof(tANI_U32); i++) - { - for (aid = 0; aid < (sizeof(tANI_U32) << 3); aid++) - { - if (CHECK_BIT(psessionEntry->peerAIDBitmap[i], aid)) - { - pStaDs = dphGetHashEntry(pMac, (aid + i*(sizeof(tANI_U32) << 3)), &psessionEntry->dph.dphHashTable); - - if (NULL != pStaDs) - { - limLog(pMac, LOGE, FL("Deleting "MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pStaDs->staAddr)); + lim_check_aid_and_delete_peer(pMac, psessionEntry); - limSendDeauthMgmtFrame(pMac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, - pStaDs->staAddr, psessionEntry, FALSE); - dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, &psessionEntry->dph.dphHashTable); - } - limReleasePeerIdx(pMac, (aid + i*(sizeof(tANI_U32) << 3)), psessionEntry) ; - CLEAR_BIT(psessionEntry->peerAIDBitmap[i], aid); - } - } - } limSendSmeTDLSDeleteAllPeerInd(pMac, psessionEntry); return eSIR_SUCCESS; } +/** + * lim_process_sme_del_all_tdls_peers: process delete tdls peers + * @p_mac: pointer to mac context + * @msg_buf: message buffer + * + * Function processes request to delete tdls peers + * + * Return: Sucess: eSIR_SUCCESS Failure: Error value + */ +tSirRetStatus lim_process_sme_del_all_tdls_peers(tpAniSirGlobal p_mac, + uint32_t *msg_buf) +{ + struct sir_del_all_tdls_peers *msg; + tpPESession session_entry; + uint8_t session_id; + + msg = (struct sir_del_all_tdls_peers *)msg_buf; + if (msg == NULL) { + limLog(p_mac, LOGE, FL("NULL msg")); + return eSIR_FAILURE; + } + + session_entry = peFindSessionByBssid(p_mac, msg->bssid, &session_id); + if (NULL == session_entry) { + limLog(p_mac, LOGE, FL("NULL psessionEntry")); + return eSIR_FAILURE; + } + + lim_check_aid_and_delete_peer(p_mac, session_entry); + + return eSIR_SUCCESS; +} + #endif diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c index dca9f844d348..3a60c497eaa7 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -240,7 +240,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, { tDot11fProbeRequest pr; tANI_U32 nStatus, nBytes, nPayload; - tSirRetStatus nSirStatus, extcap_status; + tSirRetStatus nSirStatus; tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; @@ -251,6 +251,8 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, tANI_U8 smeSessionId = 0; bool isVHTEnabled = false; uint16_t addn_ielen = nAdditionalIELen; + bool extracted_ext_cap_flag = false; + tDot11fIEExtCap extracted_ext_cap; @@ -395,14 +397,24 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, "0x%08x)."), nStatus ); } - /* Strip extended capability IE (if present). FW will add that IE */ if (addn_ielen) { - extcap_status = lim_strip_extcap_ie(pMac, pAdditionalIE, &addn_ielen, - NULL); - if (eSIR_SUCCESS != extcap_status) - limLog(pMac, LOGE, - FL("Error:(%d) stripping extcap IE"), extcap_status); + vos_mem_set((tANI_U8 *)&extracted_ext_cap, + sizeof(tDot11fIEExtCap), 0); + nSirStatus = lim_strip_extcap_update_struct(pMac, pAdditionalIE, + &addn_ielen, + &extracted_ext_cap); + if (eSIR_SUCCESS != nSirStatus) { + limLog(pMac, LOG1, + FL("Unable to Stripoff ExtCap IE from Probe Req")); + } else { + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) + extracted_ext_cap.bytes; + if (p_ext_cap->interworkingService) + p_ext_cap->qosMap = 1; + + extracted_ext_cap_flag = lim_is_ext_cap_ie_present(p_ext_cap); + } } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + addn_ielen; @@ -434,6 +446,10 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, return nSirStatus; // allocated! } + /* merge the ExtCap struct*/ + if (extracted_ext_cap_flag) + lim_merge_extcap_struct(&pr.ExtCap, &extracted_ext_cap); + // That done, pack the Probe Request: nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame + sizeof( tSirMacMgmtHdr ), @@ -579,7 +595,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, tANI_U8 smeSessionId = 0; tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; tDot11fIEExtCap extractedExtCap; - tANI_BOOLEAN extractedExtCapFlag = eANI_BOOLEAN_TRUE; + tANI_BOOLEAN extractedExtCapFlag = eANI_BOOLEAN_FALSE; if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) { /* We don't answer requests in this case */ @@ -787,9 +803,10 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, &extractedExtCap ); if(eSIR_SUCCESS != nSirStatus ) { - extractedExtCapFlag = eANI_BOOLEAN_FALSE; limLog(pMac, LOG1, FL("Unable to Stripoff ExtCap IE from Probe Rsp")); + } else { + extractedExtCapFlag = eANI_BOOLEAN_TRUE; } nBytes = nBytes + totalAddnIeLen; @@ -2052,20 +2069,9 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, { struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) extractedExtCap.bytes; - if (p_ext_cap->interworkingService || - p_ext_cap->bssTransition) + if (p_ext_cap->interworkingService) p_ext_cap->qosMap = 1; - else { - /* No need to merge the EXT Cap from Supplicant - * if interworkingService or bsstransition is not set, - * as currently driver is only interested in - * interworkingService and bsstransition capability from - * supplicant. - * if in future any other EXT Cap info is required from - * supplicant it needs to be handled here. - */ - extractedExtCapFlag = eANI_BOOLEAN_FALSE; - } + extractedExtCapFlag = lim_is_ext_cap_ie_present(p_ext_cap); } } else { limLog(pMac, LOG1, FL("No additional IE for Assoc Request")); @@ -2133,7 +2139,8 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, &pFrm->ExtSuppRates, psessionEntry ); #if defined WLAN_FEATURE_VOWIFI - if (pMac->rrm.rrmPEContext.rrmEnable) + if (pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(psessionEntry->limCurrentBssCaps)) PopulateDot11fRRMIe(pMac, &pFrm->RRMEnabledCap, psessionEntry); #endif // The join request *should* contain zero or one of the WPA and RSN @@ -2533,7 +2540,8 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, &frm.ExtSuppRates, psessionEntry ); #if defined WLAN_FEATURE_VOWIFI - if (pMac->rrm.rrmPEContext.rrmEnable) + if (pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(psessionEntry->limCurrentBssCaps)) PopulateDot11fRRMIe(pMac, &frm.RRMEnabledCap, psessionEntry); #endif @@ -3037,7 +3045,8 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, &frm.ExtSuppRates, psessionEntry ); #if defined WLAN_FEATURE_VOWIFI - if (pMac->rrm.rrmPEContext.rrmEnable) + if (pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(psessionEntry->limCurrentBssCaps)) PopulateDot11fRRMIe(pMac, &frm.RRMEnabledCap, psessionEntry); #endif // The join request *should* contain zero or one of the WPA and RSN diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c index 6a7bd0b625d4..484f87cc3ef6 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -469,41 +469,53 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, pSirSmeJoinRsp->beaconLength); vos_mem_free( psessionEntry->beacon); psessionEntry->beacon = NULL; + psessionEntry->bcnLen = 0; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("Beacon=%d"), psessionEntry->bcnLen);) + PELOG1(limLog(pMac, LOG1, FL("Beacon=%d"), + pSirSmeJoinRsp->beaconLength);) #endif } if(psessionEntry->assocReq != NULL) { pSirSmeJoinRsp->assocReqLength = psessionEntry->assocReqLen; - vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen, - psessionEntry->assocReq, pSirSmeJoinRsp->assocReqLength); + vos_mem_copy(pSirSmeJoinRsp->frames + + pSirSmeJoinRsp->beaconLength, + psessionEntry->assocReq, + pSirSmeJoinRsp->assocReqLength); vos_mem_free( psessionEntry->assocReq); psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d"), psessionEntry->assocReqLen);) + PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d"), + pSirSmeJoinRsp->assocReqLength);) #endif } if(psessionEntry->assocRsp != NULL) { pSirSmeJoinRsp->assocRspLength = psessionEntry->assocRspLen; - vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen + - psessionEntry->assocReqLen, - psessionEntry->assocRsp, - pSirSmeJoinRsp->assocRspLength); + vos_mem_copy(pSirSmeJoinRsp->frames + + pSirSmeJoinRsp->beaconLength + + pSirSmeJoinRsp->assocReqLength, + psessionEntry->assocRsp, + pSirSmeJoinRsp->assocRspLength); vos_mem_free( psessionEntry->assocRsp); psessionEntry->assocRsp = NULL; + psessionEntry->assocRspLen = 0; } #ifdef WLAN_FEATURE_VOWIFI_11R if(psessionEntry->ricData != NULL) { pSirSmeJoinRsp->parsedRicRspLen = psessionEntry->RICDataLen; - vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen + - psessionEntry->assocReqLen + psessionEntry->assocRspLen, - psessionEntry->ricData, pSirSmeJoinRsp->parsedRicRspLen); + vos_mem_copy(pSirSmeJoinRsp->frames + + pSirSmeJoinRsp->beaconLength + + pSirSmeJoinRsp->assocReqLength + + pSirSmeJoinRsp->assocRspLength, + psessionEntry->ricData, + pSirSmeJoinRsp->parsedRicRspLen); vos_mem_free(psessionEntry->ricData); psessionEntry->ricData = NULL; + psessionEntry->RICDataLen = 0; PELOG1(limLog(pMac, LOG1, FL("RicLength=%d"), pSirSmeJoinRsp->parsedRicRspLen);) } #endif @@ -511,18 +523,24 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, if(psessionEntry->tspecIes != NULL) { pSirSmeJoinRsp->tspecIeLen = psessionEntry->tspecLen; - vos_mem_copy( pSirSmeJoinRsp->frames + psessionEntry->bcnLen + - psessionEntry->assocReqLen + psessionEntry->assocRspLen + - psessionEntry->RICDataLen, - psessionEntry->tspecIes, pSirSmeJoinRsp->tspecIeLen); + vos_mem_copy(pSirSmeJoinRsp->frames + + pSirSmeJoinRsp->beaconLength + + pSirSmeJoinRsp->assocReqLength + + pSirSmeJoinRsp->assocRspLength + + pSirSmeJoinRsp->parsedRicRspLen, + psessionEntry->tspecIes, + pSirSmeJoinRsp->tspecIeLen); vos_mem_free(psessionEntry->tspecIes); psessionEntry->tspecIes = NULL; - PELOG1(limLog(pMac, LOG1, FL("ESE-TspecLen=%d"), psessionEntry->tspecLen);) + psessionEntry->tspecLen = 0; + PELOG1(limLog(pMac, LOG1, FL("ESE-TspecLen=%d"), + pSirSmeJoinRsp->tspecIeLen);) } #endif pSirSmeJoinRsp->aid = psessionEntry->limAID; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d"), psessionEntry->assocRspLen);) + PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d"), + pSirSmeJoinRsp->assocRspLength);) #endif if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == psessionEntry->apChanWidth) { @@ -567,18 +585,21 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, { vos_mem_free(psessionEntry->beacon); psessionEntry->beacon = NULL; + psessionEntry->bcnLen = 0; } if(psessionEntry->assocReq != NULL) { vos_mem_free( psessionEntry->assocReq); psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; } if(psessionEntry->assocRsp != NULL) { vos_mem_free( psessionEntry->assocRsp); psessionEntry->assocRsp = NULL; + psessionEntry->assocRspLen = 0; } #ifdef WLAN_FEATURE_VOWIFI_11R @@ -586,6 +607,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, { vos_mem_free( psessionEntry->ricData); psessionEntry->ricData = NULL; + psessionEntry->RICDataLen = 0; } #endif @@ -594,6 +616,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, { vos_mem_free(psessionEntry->tspecIes); psessionEntry->tspecIes = NULL; + psessionEntry->tspecLen = 0; } #endif } @@ -2956,6 +2979,7 @@ void limHandleDeleteBssRsp(tpAniSirGlobal pMac,tpSirMsgQ MsgQ) { limLog(pMac, LOGE,FL("Session Does not exist for given sessionID %d"), pDelBss->sessionId); + vos_mem_free(MsgQ->bodyptr); return; } if (LIM_IS_IBSS_ROLE(psessionEntry)) { diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c index d11b729d008a..4ffdf9686bf8 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c @@ -158,6 +158,7 @@ void pe_reset_protection_callback(void *ptr) old_op_mode = pe_session_entry->htOperMode; pe_session_entry->htOperMode = eSIR_HT_OP_MODE_PURE; + mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; vos_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); /* index 0, is self node, peers start from 1 */ @@ -661,18 +662,21 @@ void peDeleteSession(tpAniSirGlobal pMac, tpPESession psessionEntry) { vos_mem_free( psessionEntry->beacon); psessionEntry->beacon = NULL; + psessionEntry->bcnLen = 0; } if (psessionEntry->assocReq != NULL) { vos_mem_free( psessionEntry->assocReq); psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; } if (psessionEntry->assocRsp != NULL) { vos_mem_free( psessionEntry->assocRsp); psessionEntry->assocRsp = NULL; + psessionEntry->assocRspLen = 0; } diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c index 9b1dd118bd6a..dbdf80590e0c 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c @@ -40,7 +40,7 @@ #include "limAssocUtils.h" #include "limSecurityUtils.h" #include "pmmApi.h" - +#include "limApi.h" // default value 5000 ms for background scan period when it is disabled #define LIM_BACKGROUND_SCAN_PERIOD_DEFAULT_MS 5000 @@ -828,7 +828,8 @@ limTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyptr = NULL; msg.bodyval = 0; - if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) + statusCode = lim_post_msg_high_pri(pMac, &msg); + if (statusCode != eSIR_SUCCESS) limLog(pMac, LOGE, FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h index 87d7c1604b97..18c7866b6fb8 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h @@ -727,6 +727,15 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, tpPESession); tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, tSirMacAddr peerMac, tANI_U16 reason, tANI_U8 responder, tpPESession psessionEntry, tANI_U8 *addIe, tANI_U16 addIeLen); +tSirRetStatus lim_process_sme_del_all_tdls_peers(tpAniSirGlobal p_mac, + uint32_t *msg_buf); +#else +static inline tSirRetStatus +lim_process_sme_del_all_tdls_peers(tpAniSirGlobal p_mac, + uint32_t *msg_buf) +{ + return eSIR_SUCCESS; +} #endif // Algorithms & Link Monitoring related functions diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c index d0e9e49ebf23..9b859830b45b 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c @@ -766,30 +766,25 @@ limCleanupMlm(tpAniSirGlobal pMac) * each STA associated per BSSId and deactivate/delete * the pmfSaQueryTimer for it */ - if (vos_is_logp_in_progress(VOS_MODULE_ID_PE, NULL)) + for (bss_entry = 0; bss_entry < pMac->lim.maxBssId; bss_entry++) { - VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - FL("SSR is detected, proceed to clean up pmfSaQueryTimer")); - for (bss_entry = 0; bss_entry < pMac->lim.maxBssId; bss_entry++) - { - if (pMac->lim.gpSession[bss_entry].valid) + if (pMac->lim.gpSession[bss_entry].valid) + { + for (sta_entry = 1; sta_entry < pMac->lim.gLimAssocStaLimit; + sta_entry++) { - for (sta_entry = 1; sta_entry < pMac->lim.gLimAssocStaLimit; - sta_entry++) - { - psessionEntry = &pMac->lim.gpSession[bss_entry]; - pStaDs = dphGetHashEntry(pMac, sta_entry, - &psessionEntry->dph.dphHashTable); - if (NULL == pStaDs) - { - continue; - } - VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - FL("Deleting pmfSaQueryTimer for staid[%d]"), - pStaDs->staIndex) ; - tx_timer_deactivate(&pStaDs->pmfSaQueryTimer); - tx_timer_delete(&pStaDs->pmfSaQueryTimer); - } + psessionEntry = &pMac->lim.gpSession[bss_entry]; + pStaDs = dphGetHashEntry(pMac, sta_entry, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) + { + continue; + } + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, + FL("Deleting pmfSaQueryTimer for staid[%d]"), + pStaDs->staIndex) ; + tx_timer_deactivate(&pStaDs->pmfSaQueryTimer); + tx_timer_delete(&pStaDs->pmfSaQueryTimer); } } } @@ -8676,3 +8671,99 @@ lim_get_80Mhz_center_channel(uint8_t primary_channel) return HAL_INVALID_CHANNEL_ID; } + +/** + * lim_is_ext_cap_ie_present - checks if ext ie is present + * @ext_cap: extended IEs structure + * + * Return: true if ext IEs are present else false + */ +bool lim_is_ext_cap_ie_present (struct s_ext_cap *ext_cap) +{ + int i, size; + uint8_t *tmp_buf; + + tmp_buf = (uint8_t *) ext_cap; + size = sizeof(*ext_cap); + + for (i = 0; i < size; i++) + if (tmp_buf[i]) + return true; + + return false; +} + +/** + * lim_is_robust_mgmt_action_frame() - Check if action catagory is + * robust action frame + * @action_catagory: Action frame catagory. + * + * This function is used to check if given action catagory is robust + * action frame. + * + * Return: bool + */ +bool lim_is_robust_mgmt_action_frame(uint8_t action_catagory) +{ + switch (action_catagory) { + /* + * NOTE: This function doesn't take care of the DMG + * (Directional Multi-Gigatbit) BSS case as 8011ad + * support is not yet added. In future, if the support + * is required then this function need few more arguments + * and little change in logic. + */ + case SIR_MAC_ACTION_SPECTRUM_MGMT: + case SIR_MAC_ACTION_QOS_MGMT: + case SIR_MAC_ACTION_DLP: + case SIR_MAC_ACTION_BLKACK: + case SIR_MAC_ACTION_RRM: + case SIR_MAC_ACTION_FAST_BSS_TRNST: + case SIR_MAC_ACTION_SA_QUERY: + case SIR_MAC_ACTION_PROT_DUAL_PUB: + case SIR_MAC_ACTION_WNM: + case SIR_MAC_ACITON_MESH: + case SIR_MAC_ACTION_MHF: + case SIR_MAC_ACTION_FST: + return true; + default: + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + FL("non-PMF action category[%d] "), + action_catagory); + break; + } + return false; +} + +/** + * lim_update_caps_info_for_bss - Update capability info for this BSS + * + * @mac_ctx: mac context + * @caps: Pointer to capability info to be updated + * @bss_caps: Capability info of the BSS + * + * Update the capability info in Assoc/Reassoc request frames and reset + * the spectrum management, short preamble, immediate block ack bits + * if the BSS doesnot support it + * + * Return: None + */ +void lim_update_caps_info_for_bss(tpAniSirGlobal mac_ctx, + uint16_t *caps, uint16_t bss_caps) +{ + if (!(bss_caps & LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) { + *caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK); + limLog(mac_ctx, LOG1, FL("Clearing spectrum management:no AP support")); + } + + if (!(bss_caps & LIM_SHORT_PREAMBLE_BIT_MASK)) { + *caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK); + limLog(mac_ctx, LOG1, FL("Clearing short preamble:no AP support")); + } + + if (!(bss_caps & LIM_IMMEDIATE_BLOCK_ACK_MASK)) { + *caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK); + limLog(mac_ctx, LOG1, FL("Clearing Immed Blk Ack:no AP support")); + } +} + diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h index 83081c3453e1..bfb9dbf9d2a7 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h @@ -664,4 +664,10 @@ tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx, void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src); uint8_t lim_get_80Mhz_center_channel(uint8_t primary_channel); +bool lim_is_ext_cap_ie_present (struct s_ext_cap *ext_cap); +bool lim_is_robust_mgmt_action_frame(uint8_t action_catagory); +void lim_update_caps_info_for_bss(tpAniSirGlobal mac_ctx, + uint16_t *caps, uint16_t bss_caps); +eHalStatus limP2PActionCnf(tpAniSirGlobal mac_ctx, + uint32_t tx_complete_success); #endif /* __LIM_UTILS_H */ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c index 8052338b18bd..4820f645685f 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -57,6 +57,7 @@ #include "schSysParams.h" #include "limTrace.h" #include "limTypes.h" +#include "limUtils.h" #include "wlan_qct_wda.h" @@ -414,12 +415,16 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn tANI_U32 nPayload,nBytes,nStatus; tpSirMacMgmtHdr pMacHdr; tANI_U32 addnIEPresent = VOS_FALSE; - tANI_U32 addnIELen=0; tSirRetStatus nSirStatus; tANI_U8 *addIE = NULL; tANI_U8 *addIeWoP2pIe = NULL; tANI_U32 addnIELenWoP2pIe = 0; tANI_U32 retStatus; + tDot11fIEExtCap extracted_extcap; + bool extcap_present = false; + tDot11fProbeResponse *prb_rsp_frm; + tSirRetStatus status; + uint16_t addn_ielen = 0; nStatus = dot11fGetPackedProbeResponseSize( pMac, &psessionEntry->probeRespFrame, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) @@ -479,24 +484,35 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn vos_mem_free(addIeWoP2pIe); return retCode; } - addnIELen = addnIELenWoP2pIe; + addn_ielen = addnIELenWoP2pIe; - if (addnIELen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addnIELen && - (nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) + if (addn_ielen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addn_ielen && + (nBytes + addn_ielen) <= SIR_MAX_PACKET_SIZE) { vos_mem_copy(addIE, addIeWoP2pIe, addnIELenWoP2pIe); } vos_mem_free(addIeWoP2pIe); + + vos_mem_set((uint8_t *)&extracted_extcap, sizeof(tDot11fIEExtCap), 0); + status = lim_strip_extcap_update_struct(pMac, addIE, &addn_ielen, + &extracted_extcap); + if (eSIR_SUCCESS != status) { + limLog(pMac, LOG1, FL("extcap not extracted")); + } else { + extcap_present = true; + } + } if (addnIEPresent) { - if ((nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE ) - nBytes += addnIELen; + if ((nBytes + addn_ielen) <= SIR_MAX_PACKET_SIZE ) + nBytes += addn_ielen; else addnIEPresent = false; //Dont include the IE. } + // Paranoia: vos_mem_set(pFrame2Hal, nBytes, 0); @@ -518,6 +534,11 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); + /* merge extcap IE */ + prb_rsp_frm = &psessionEntry->probeRespFrame; + if (extcap_present) + lim_merge_extcap_struct(&prb_rsp_frm->ExtCap, &extracted_extcap); + // That done, pack the Probe Response: nStatus = dot11fPackProbeResponse( pMac, &psessionEntry->probeRespFrame, pFrame2Hal + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); @@ -537,10 +558,7 @@ tANI_U32 limSendProbeRspTemplateToHal(tpAniSirGlobal pMac,tpPESession psessionEn } if (addnIEPresent) - { - vos_mem_copy ( &pFrame2Hal[nBytes - addnIELen], - &addIE[0], addnIELen); - } + vos_mem_copy(&pFrame2Hal[nBytes - addn_ielen], &addIE[0], addn_ielen); /* free the allocated Memory */ vos_mem_free(addIE); @@ -661,4 +679,4 @@ int schGenTimingAdvertFrame(tpAniSirGlobal mac_ctx, tSirMacAddr self_addr, if (*buf) vos_mem_free(*buf); return status; -} \ No newline at end of file +} diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c index 9dac92550e6c..6969d29322db 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -95,58 +95,51 @@ tSirRetStatus schGetP2pIeOffset(tANI_U8 *pExtraIe, tANI_U32 extraIeLen, tANI_U16 tSirRetStatus schAppendAddnIE(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 *pFrame, tANI_U32 maxBeaconSize, - tANI_U32 *nBytes) + tANI_U32 *nBytes, uint8_t *addn_ie, + uint16_t addn_ielen) { tSirRetStatus status = eSIR_FAILURE; - tANI_U32 present, len; tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN]; - present = (psessionEntry->addIeParams.probeRespBCNDataLen != 0); - if(present) + if(addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && addn_ielen && + ((addn_ielen + *nBytes) <= maxBeaconSize)) { - len = psessionEntry->addIeParams.probeRespBCNDataLen; - if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len && - ((len + *nBytes) <= maxBeaconSize)) - { - - vos_mem_copy(&addIE[0], - psessionEntry->addIeParams.probeRespBCNData_buff, len); + vos_mem_copy(&addIE[0], addn_ie, addn_ielen); + { + tANI_U8* pP2pIe = limGetP2pIEPtr(pMac, &addIE[0], addn_ielen); + if ((pP2pIe != NULL) && !pMac->beacon_offload) { - tANI_U8* pP2pIe = limGetP2pIEPtr(pMac, &addIE[0], len); - if ((pP2pIe != NULL) && !pMac->beacon_offload) + tANI_U8 noaLen = 0; + tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + //get NoA attribute stream P2P IE + noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry); + if(noaLen) { - tANI_U8 noaLen = 0; - tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; - //get NoA attribute stream P2P IE - noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry); - if(noaLen) + if ((noaLen + addn_ielen) <= + WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) { + vos_mem_copy(&addIE[addn_ielen], noaStream, noaLen); + addn_ielen += noaLen; + /* Update IE Len */ + pP2pIe[1] += noaLen; + } + else { - if ((noaLen + len) <= - WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) { - vos_mem_copy(&addIE[len], noaStream, noaLen); - len += noaLen; - /* Update IE Len */ - pP2pIe[1] += noaLen; - } - else - { - schLog(pMac, LOGE, - FL("Not able to insert NoA because of length constraint")); - } + schLog(pMac, LOGE, + FL("Not able to insert NoA because of addn_ielength constraint")); } } - if(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) - { - vos_mem_copy(pFrame, &addIE[0], len); - *nBytes = *nBytes + len; - } - else - { - schLog(pMac, LOGW, FL("Not able to insert because of" - " length constraint %d"), len); - } + } + if(addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) + { + vos_mem_copy(pFrame, &addIE[0], addn_ielen); + *nBytes = *nBytes + addn_ielen; + } + else + { + schLog(pMac, LOGW, FL("Not able to insert because of" + " addn_ielength constraint %d"), addn_ielen); } } } @@ -188,6 +181,10 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn tANI_U16 p2pIeOffset = 0; tSirRetStatus status = eSIR_SUCCESS; tANI_BOOLEAN isVHTEnabled = eANI_BOOLEAN_FALSE; + uint16_t addn_ielen = 0; + uint8_t *addn_ie = NULL; + tDot11fIEExtCap extracted_extcap; + bool extcap_present = true, addnie_present = false; pBcn1 = vos_mem_malloc(sizeof(tDot11fBeacon1)); if ( NULL == pBcn1 ) @@ -387,7 +384,8 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn } #endif - PopulateDot11fExtCap(pMac, isVHTEnabled, &pBcn2->ExtCap, psessionEntry); + if (psessionEntry->limSystemRole != eLIM_STA_IN_IBSS_ROLE) + PopulateDot11fExtCap(pMac, isVHTEnabled, &pBcn2->ExtCap, psessionEntry); PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL, &pBcn2->ExtSuppRates, psessionEntry ); @@ -470,6 +468,34 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn } + addnie_present = (psessionEntry->addIeParams.probeRespBCNDataLen != 0); + if (addnie_present) { + addn_ielen = psessionEntry->addIeParams.probeRespBCNDataLen; + addn_ie = vos_mem_malloc(addn_ielen); + if (!addn_ie) { + schLog(pMac, LOGE, FL("addn_ie malloc failed")); + vos_mem_free(pBcn1); + vos_mem_free(pBcn2); + vos_mem_free(pWscProbeRes); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy(addn_ie, psessionEntry->addIeParams.probeRespBCNData_buff, + addn_ielen); + + vos_mem_set((uint8_t *)&extracted_extcap, sizeof(tDot11fIEExtCap), 0); + status = lim_strip_extcap_update_struct(pMac, addn_ie, &addn_ielen, + &extracted_extcap); + if (eSIR_SUCCESS != status) { + extcap_present = false; + schLog(pMac, LOG1, FL("extcap not extracted")); + } + /* merge extcap IE */ + if (extcap_present && + psessionEntry->limSystemRole != eLIM_STA_IN_IBSS_ROLE) + lim_merge_extcap_struct(&pBcn2->ExtCap, &extracted_extcap); + + } + nStatus = dot11fPackBeacon2( pMac, pBcn2, psessionEntry->pSchBeaconFrameEnd, SCH_MAX_BEACON_SIZE, &nBytes ); @@ -480,6 +506,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn vos_mem_free(pBcn1); vos_mem_free(pBcn2); vos_mem_free(pWscProbeRes); + vos_mem_free(addn_ie); return eSIR_FAILURE; } else if ( DOT11F_WARNED( nStatus ) ) @@ -491,10 +518,10 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn pExtraIe = psessionEntry->pSchBeaconFrameEnd + nBytes; extraIeOffset = nBytes; - //TODO: Append additional IE here. - schAppendAddnIE(pMac, psessionEntry, + if (addn_ielen > 0) + schAppendAddnIE(pMac, psessionEntry, psessionEntry->pSchBeaconFrameEnd + nBytes, - SCH_MAX_BEACON_SIZE, &nBytes); + SCH_MAX_BEACON_SIZE, &nBytes, addn_ie, addn_ielen); psessionEntry->schBeaconOffsetEnd = ( tANI_U16 )nBytes; @@ -522,6 +549,7 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn vos_mem_free(pBcn1); vos_mem_free(pBcn2); vos_mem_free(pWscProbeRes); + vos_mem_free(addn_ie); return eSIR_SUCCESS; } diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h b/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h index 9fd1c101f53a..52df92410852 100644 --- a/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h +++ b/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -173,9 +173,7 @@ typedef enum { eSAP_ASSOC_STA_CALLBACK_EVENT, /*Event sent when user called WLANSAP_GetAssocStations */ eSAP_GET_WPSPBC_SESSION_EVENT, /* Event send when user call WLANSAP_getWpsSessionOverlap */ eSAP_WPS_PBC_PROBE_REQ_EVENT, /* Event send on WPS PBC probe request is received */ - eSAP_INDICATE_MGMT_FRAME, eSAP_REMAIN_CHAN_READY, - eSAP_SEND_ACTION_CNF, eSAP_DISCONNECT_ALL_P2P_CLIENT, eSAP_MAC_TRIG_STOP_BSS_EVENT, eSAP_UNKNOWN_STA_JOIN, /* Event send when a STA in neither white list or black list tries to associate in softap mode */ @@ -413,8 +411,7 @@ typedef struct sap_Event_s { tSap_AssocStaListEvent sapAssocStaListEvent; /*SAP_ASSOC_STA_CALLBACK_EVENT */ tSap_GetWPSPBCSessionEvent sapGetWPSPBCSessionEvent; /*SAP_GET_WPSPBC_SESSION_EVENT */ tSap_WPSPBCProbeReqEvent sapPBCProbeReqEvent; /*eSAP_WPS_PBC_PROBE_REQ_EVENT */ - tSap_ManagementFrameInfo sapManagementFrameInfo; /*eSAP_INDICATE_MGMT_FRAME*/ - tSap_SendActionCnf sapActionCnf; /* eSAP_SEND_ACTION_CNF */ + tSap_SendActionCnf sapActionCnf; tSap_UnknownSTAJoinEvent sapUnknownSTAJoin; /* eSAP_UNKNOWN_STA_JOIN */ tSap_MaxAssocExceededEvent sapMaxAssocExceeded; /* eSAP_MAX_ASSOC_EXCEEDED */ tSap_DfsNolInfo sapDfsNolInfo; /*eSAP_DFS_NOL_XXX */ @@ -631,6 +628,7 @@ typedef struct sSapDfsInfo * channel switch is disabled. */ v_U8_t disable_dfs_ch_switch; + uint16_t tx_leakage_threshold; } tSapDfsInfo; typedef struct tagSapCtxList @@ -2377,6 +2375,11 @@ WLANSAP_ACS_CHSelect(v_PVOID_t pvosGCtx, eCsrPhyMode wlansap_get_phymode(v_PVOID_t pctx); + +VOS_STATUS wlansap_set_tx_leakage_threshold(tHalHandle hal, + uint16 tx_leakage_threshold); + + #ifdef __cplusplus } #endif diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c index 3a7f689f1284..50a10feddb1a 100644 --- a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -685,15 +685,6 @@ WLANSAP_RoamCallback FL("CSR roamStatus = %s (%d)"), "eCSR_ROAM_WPS_PBC_PROBE_REQ_IND", roamStatus); break; - - case eCSR_ROAM_INDICATE_MGMT_FRAME: - VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, - FL("CSR roamStatus = %s (%d)"), - "eCSR_ROAM_INDICATE_MGMT_FRAME", roamStatus); - sapSignalHDDevent(sapContext, pCsrRoamInfo, - eSAP_INDICATE_MGMT_FRAME, - (v_PVOID_t) eSAP_STATUS_SUCCESS); - break; case eCSR_ROAM_REMAIN_CHAN_READY: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, FL("CSR roamStatus = %s (%d)"), @@ -702,15 +693,6 @@ WLANSAP_RoamCallback eSAP_REMAIN_CHAN_READY, (v_PVOID_t) eSAP_STATUS_SUCCESS); break; - case eCSR_ROAM_SEND_ACTION_CNF: - VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, - FL("CSR roamStatus = %s (%d)"), - "eCSR_ROAM_SEND_ACTION_CNF", roamStatus); - sapSignalHDDevent(sapContext, pCsrRoamInfo, - eSAP_SEND_ACTION_CNF, - (v_PVOID_t)((eSapStatus)((roamResult == eCSR_ROAM_RESULT_NONE) - ? eSAP_STATUS_SUCCESS : eSAP_STATUS_FAILURE))); - break; case eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, @@ -1083,6 +1065,7 @@ WLANSAP_RoamCallback */ vos_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = false; /* * User space is already indicated the CAC start and if @@ -1100,8 +1083,6 @@ WLANSAP_RoamCallback */ } - pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; - sapEvent.event = eSAP_DFS_CHANNEL_CAC_RADAR_FOUND; sapEvent.params = 0; sapEvent.u1 = 0; @@ -1391,9 +1372,16 @@ WLANSAP_RoamCallback * channel due to the presence of radar but our channel change * failed, stop the BSS operation completely and inform hostapd */ - sapContext->sapsMachine = eSAP_DISCONNECTED; + sapEvent.event = eWNI_SME_CHANNEL_CHANGE_RSP; + sapEvent.params = 0; + sapEvent.u1 = eCSR_ROAM_INFRA_IND; + sapEvent.u2 = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE; - /* Inform cfg80211 and hostapd that BSS is not alive anymore */ + vosStatus = sapFsm(sapContext, &sapEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + halStatus = eHAL_STATUS_FAILURE; + } + break; } case eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND: { diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c index 39db899d5993..ce830391b747 100644 --- a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c @@ -1543,6 +1543,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, v_U32_t ieLen = 0; tSirProbeRespBeacon *pBeaconStruct; tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tSapSpectChInfo *pSpectChStartAddr = pSpectInfoParams->pSpectCh; + tSapSpectChInfo *pSpectChEndAddr = + pSpectInfoParams->pSpectCh + pSpectInfoParams->numSpectChans; pBeaconStruct = vos_mem_malloc(sizeof(tSirProbeRespBeacon)); if ( NULL == pBeaconStruct ) @@ -1626,7 +1629,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, tSapSpectChInfo *pExtSpectCh = NULL; case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: // Above the Primary Channel pExtSpectCh = (pSpectCh + 1); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1642,7 +1647,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: // Below the Primary channel pExtSpectCh = (pSpectCh - 1); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) @@ -1661,7 +1668,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, { tSapSpectChInfo *pExtSpectCh = NULL; pExtSpectCh = (pSpectCh + 1); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1673,7 +1682,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh + 2); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; @@ -1685,7 +1696,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh + 3); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; @@ -1701,7 +1714,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, { tSapSpectChInfo *pExtSpectCh = NULL; pExtSpectCh = (pSpectCh - 1 ); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1713,7 +1728,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh + 1); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1725,7 +1742,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh + 2); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; @@ -1741,7 +1760,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, { tSapSpectChInfo *pExtSpectCh = NULL; pExtSpectCh = (pSpectCh - 1 ); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1753,7 +1774,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh - 2); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; @@ -1765,7 +1788,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh + 1); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1781,7 +1806,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, { tSapSpectChInfo *pExtSpectCh = NULL; pExtSpectCh = (pSpectCh - 1 ); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; @@ -1793,7 +1820,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh - 2); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; @@ -1805,7 +1834,9 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } pExtSpectCh = (pSpectCh - 3); - if(pExtSpectCh != NULL) + if( pExtSpectCh != NULL && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) { ++pExtSpectCh->bssCount; rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; @@ -2293,9 +2324,9 @@ void sapSortChlWeightAll(ptSapContext pSapCtx, #else /* Sorting the channels as per weights */ - for (i = 0; i < SPECT_24GHZ_CH_COUNT; i++) { + for (i = 0; i < pSpectInfoParams->numSpectChans; i++) { minWeightIndex = i; - for( j = i + 1; j < SPECT_24GHZ_CH_COUNT; j++) { + for( j = i + 1; j < pSpectInfoParams->numSpectChans; j++) { if(pSpectCh[j].weight < pSpectCh[minWeightIndex].weight) { minWeightIndex = j; } diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c index eeac1a8d1053..4d747095e7a0 100644 --- a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1050,7 +1050,16 @@ sapMarkChannelsLeakingIntoNOL(ptSapContext sapContext, v_U32_t j = 0; v_U32_t k = 0; v_U8_t dfs_nol_channel; + tHalHandle hal = VOS_GET_HAL_CB(sapContext->pvosGCtx); + tpAniSirGlobal mac; + if (NULL == hal) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + mac = PMAC_STRUCT(hal); /* traverse target_chan_matrix and */ for (i = 0; i < NUM_5GHZ_CHANNELS ; i++) { @@ -1091,7 +1100,8 @@ sapMarkChannelsLeakingIntoNOL(ptSapContext sapContext, k++; } else { /* check leakage from candidate channel to NOL channel */ - if (target_chan_matrix[k].leak_lvl <= SAP_TX_LEAKAGE_THRES) + if (target_chan_matrix[k].leak_lvl <= + mac->sap.SapDfsInfo.tx_leakage_threshold) { /* * this means that candidate channel will have bad @@ -2876,35 +2886,12 @@ sapSignalHDDevent pCsrRoamInfo->u.pWPSPBCProbeReq, sizeof(tSirWPSPBCProbeReq)); break; - - case eSAP_INDICATE_MGMT_FRAME: - VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, - FL("SAP event callback event = %s"), - "eSAP_INDICATE_MGMT_FRAME"); - sapApAppEvent.sapHddEventCode = eSAP_INDICATE_MGMT_FRAME; - sapApAppEvent.sapevt.sapManagementFrameInfo.nFrameLength - = pCsrRoamInfo->nFrameLength; - sapApAppEvent.sapevt.sapManagementFrameInfo.pbFrames - = pCsrRoamInfo->pbFrames; - sapApAppEvent.sapevt.sapManagementFrameInfo.frameType - = pCsrRoamInfo->frameType; - sapApAppEvent.sapevt.sapManagementFrameInfo.rxChan - = pCsrRoamInfo->rxChan; - - break; case eSAP_REMAIN_CHAN_READY: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, FL("SAP event callback event = %s"), "eSAP_REMAIN_CHAN_READY"); sapApAppEvent.sapHddEventCode = eSAP_REMAIN_CHAN_READY; break; - case eSAP_SEND_ACTION_CNF: - VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, - FL("SAP event callback event = %s"), - "eSAP_SEND_ACTION_CNF"); - sapApAppEvent.sapHddEventCode = eSAP_SEND_ACTION_CNF; - sapApAppEvent.sapevt.sapActionCnf.actionSendSuccess = (eSapStatus)context; - break; case eSAP_DISCONNECT_ALL_P2P_CLIENT: VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, @@ -3888,6 +3875,17 @@ sapFsm "In %s, Sending DFS eWNI_SME_CHANNEL_CHANGE_REQ", __func__); } + else if (msg == eWNI_SME_CHANNEL_CHANGE_RSP) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED, + "In %s, in state %s, event msg %d result %d", + __func__, "eSAP_DISCONNECTING ", msg, sapEvent->u2); + + if (sapEvent->u2 == eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE) + { + vosStatus = sapGotoDisconnecting(sapContext); + } + } else { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, @@ -4644,13 +4642,18 @@ void sapDfsCacTimerCallback(void *data) return; } + /* + * SAP may not be in CAC wait state, when the timer runs out. + * if following flag is set, then timer is in initialized state, + * destroy timer here. + */ + if (pMac->sap.SapDfsInfo.is_dfs_cac_timer_running == true) { + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = false; + } /* Check to ensure that SAP is in DFS WAIT state*/ if (sapContext->sapsMachine == eSAP_DFS_CAC_WAIT) { - vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); - pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = VOS_FALSE; - - /* * CAC Complete, post eSAP_DFS_CHANNEL_CAC_END to sapFsm */ @@ -4695,6 +4698,7 @@ static int sapStopDfsCacTimer(ptSapContext sapContext) vos_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); return 0; } @@ -4776,11 +4780,13 @@ int sapStartDfsCacTimer(ptSapContext sapContext) status = vos_timer_start(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer, cacTimeOut); if (status == VOS_STATUS_SUCCESS) { - pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = VOS_TRUE; + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = true; return 1; } else { + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = false; + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); return 0; } } diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c index a1e4547548af..ac7f658faef1 100644 --- a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c @@ -3970,3 +3970,31 @@ wlansap_get_phymode(v_PVOID_t pctx) } return psapctx->csrRoamProfile.phyMode; } + +/** + * wlansap_set_tx_leakage_threshold() - set sap tx leakage threshold. + * @hal: HAL pointer + * @tx_leakage_threshold: sap tx leakage threshold + * + * This function set sap tx leakage threshold. + * + * Return: VOS_STATUS. + */ +VOS_STATUS wlansap_set_tx_leakage_threshold(tHalHandle hal, + uint16 tx_leakage_threshold) +{ + tpAniSirGlobal mac; + + if (NULL == hal) { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid hal pointer", __func__); + return VOS_STATUS_E_FAULT; + } + + mac = PMAC_STRUCT(hal); + mac->sap.SapDfsInfo.tx_leakage_threshold = tx_leakage_threshold; + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "%s: leakage_threshold %d", __func__, + mac->sap.SapDfsInfo.tx_leakage_threshold); + return VOS_STATUS_SUCCESS; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h index 168658d6edd3..dd1b7e8e8c3c 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 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. * @@ -36,6 +36,7 @@ #include /* adf_os_mutex_t */ #include /* htt_dbg_stats_type */ #include /* ol_txrx_stats */ +#include "vos_status.h" typedef void (*ol_txrx_stats_callback)( void *ctxt, @@ -141,7 +142,7 @@ void ol_txrx_peer_display(ol_txrx_peer_handle peer, int indent); #endif /*--- txrx stats display debug functions ---*/ -void ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, +VOS_STATUS ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, unsigned length); #if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h index 8989f03207e7..80fb5ab04f51 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h @@ -216,10 +216,6 @@ * vht enable highest MCS by default */ #define CFG_TGT_DEFAULT_GTX_VHT_MASK 0x80200 -/* - * resv for furture use, bit 30 is used for fix tpc, bit0-3 for Power save balance - */ -#define CFG_TGT_DEFAULT_GTX_USR_CFG 0xa /* * threshold to enable GTX */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h index f9e9654643c4..61e7ed7a38ca 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h @@ -254,11 +254,6 @@ * vht enable highest MCS by default */ #define CFG_TGT_DEFAULT_GTX_VHT_MASK 0x80200 -/* - * resv for furture use, bit 30 is used for fix tpc, bit0-3 for Power save - * balance - */ -#define CFG_TGT_DEFAULT_GTX_USR_CFG 0xa /* * threshold to enable GTX */ diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h index 3f469e342f70..e1f7334aea29 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h @@ -6564,6 +6564,7 @@ typedef enum event_type_e { WOW_IOAC_REV_KA_FAIL_EVENT, WOW_IOAC_SOCK_EVENT, WOW_NLO_SCAN_COMPLETE_EVENT, + WOW_TDLS_CONN_TRACKER_EVENT, } WOW_WAKE_EVENT_TYPE; typedef enum wake_reason_e { @@ -6607,6 +6608,7 @@ typedef enum wake_reason_e { WOW_REASON_REASSOC_REQ_RECV, WOW_REASON_REASSOC_RES_RECV, WOW_REASON_ACTION_FRAME_RECV, + WOW_REASON_TDLS_CONN_TRACKER_EVENT, WOW_REASON_DEBUG_TEST = 0xFF, } WOW_WAKE_REASON_TYPE; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h index 56e34cd96530..0491f2d9c251 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 183 +#define __WMI_REVISION_ 184 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c index 079cef799978..262115fee01a 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -80,7 +80,7 @@ #define MAX_REG_READ_RETRIES 10 unsigned int msienable = 0; -module_param(msienable, int, 0644); +module_param(msienable, int, S_IRUSR | S_IRGRP | S_IROTH); int hif_pci_configure(struct hif_pci_softc *sc, hif_handle_t *hif_hdl); void hif_nointrs(struct hif_pci_softc *sc); @@ -134,8 +134,14 @@ static struct pci_device_id hif_pci_id_table[] = { /* HIF IRQ History */ typedef enum { HIF_IRQ, + HIF_IRQ_END, HIF_TASKLET, + HIF_TASKLET_END, HIF_CRASH, + HIF_SUSPEND_START, + HIF_SUSPEND_AFTER_WOW, + HIF_SUSPEND_END, + HIF_RESUME, } hif_irq_type; #ifdef CONFIG_SLUB_DEBUG_ON @@ -144,6 +150,9 @@ typedef struct { A_UINT64 time; A_UINT32 irq_summary; A_UINT32 fw_indicator; + A_UINT32 irq_enable; + A_UINT32 irq_cause; + A_UINT32 irq_clear; } hif_irq_history; #define HIF_IRQ_HISTORY_MAX 1024 @@ -158,16 +167,32 @@ void hif_irq_record(hif_irq_type type, struct hif_pci_softc *sc) if (HIF_IRQ_HISTORY_MAX <= g_hif_irq_history_idx) g_hif_irq_history_idx = 0; - hif_irq_history_buffer[g_hif_irq_history_idx].type = type; - hif_irq_history_buffer[g_hif_irq_history_idx].time = adf_get_boottime(); + if (HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE) < 0) { + adf_os_mem_zero(&hif_irq_history_buffer[g_hif_irq_history_idx], + sizeof(hif_irq_history)); + goto out; + } - HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE); hif_irq_history_buffer[g_hif_irq_history_idx].irq_summary = CE_INTERRUPT_SUMMARY(targid); hif_irq_history_buffer[g_hif_irq_history_idx].fw_indicator = A_TARGET_READ(targid, hif_state->fw_indicator_address); + hif_irq_history_buffer[g_hif_irq_history_idx].irq_enable = + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_ENABLE_ADDRESS); + hif_irq_history_buffer[g_hif_irq_history_idx].irq_cause = + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CAUSE_ADDRESS); + hif_irq_history_buffer[g_hif_irq_history_idx].irq_clear = + A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CLR_ADDRESS); + HIFTargetSleepStateAdjust(hif_state->targid, TRUE, FALSE); +out: + hif_irq_history_buffer[g_hif_irq_history_idx].type = type; + hif_irq_history_buffer[g_hif_irq_history_idx].time = adf_get_boottime(); + g_hif_irq_history_idx++; } #else @@ -239,6 +264,7 @@ hif_pci_interrupt_handler(int irq, void *arg) tasklet_schedule(&sc->intr_tq); if (sc->hif_init_done == TRUE) { + hif_irq_record(HIF_IRQ_END, sc); adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); } return IRQ_HANDLED; @@ -816,8 +842,10 @@ wlan_tasklet(unsigned long data) } } - if (hif_init_done == TRUE) + if (hif_init_done == TRUE) { + hif_irq_record(HIF_TASKLET_END, sc); adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + } adf_os_atomic_set(&sc->ce_suspend, 1); } @@ -2506,6 +2534,7 @@ void hif_pci_crash_shutdown(struct pci_dev *pdev) return; } + hif_pci_pm_runtime_exit(sc); adf_os_spin_lock_irqsave(&hif_state->suspend_lock); hif_irq_record(HIF_CRASH, sc); @@ -2553,6 +2582,8 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) u32 tmp; int ret = -EBUSY; + hif_irq_record(HIF_SUSPEND_START, sc); + if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL)) return ret; @@ -2612,6 +2643,8 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) msleep(10); } + hif_irq_record(HIF_SUSPEND_AFTER_WOW, sc); + #ifdef FEATURE_WLAN_D0WOW if (wma_get_client_count(temp_module)) { if (enable_irq_wake(pdev->irq)) { @@ -2643,6 +2676,8 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) VOS_ASSERT(0); } + hif_irq_record(HIF_SUSPEND_END, sc); + if (HIFTargetSleepStateAdjust(targid, TRUE, FALSE) < 0) { adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); goto out; @@ -2744,6 +2779,9 @@ __hif_pci_resume(struct pci_dev *pdev, bool runtime_pm) A_MDELAY(1); retry++; } + + hif_irq_record(HIF_RESUME, sc); + if (HIFTargetSleepStateAdjust(targid, TRUE, FALSE) < 0) goto out; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c index 2fce4023c268..7fb5b37ca182 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c @@ -293,7 +293,7 @@ __HIFReadWrite(HIF_DEVICE *device, { A_UINT8 opcode; A_STATUS status = A_OK; - int ret; + int ret = 0; A_UINT8 *tbuffer; A_BOOL bounced = FALSE; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c index f343ff03d7e4..29c65cdb7494 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HTC/htc_send.c @@ -674,21 +674,12 @@ static A_STATUS HTCIssuePackets(HTC_TARGET *target, } } - if (adf_os_unlikely(A_FAILED(status))) { - while (!HTC_QUEUE_EMPTY(pPktQueue)) { - if (status != A_NO_RESOURCE) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCIssuePackets, failed pkt:0x%p status:%d \n",pPacket,status)); - } - pPacket = HTC_PACKET_DEQUEUE(pPktQueue); - if (pPacket) { - pPacket->Status = status; - hif_pm_runtime_put(target->hif_dev); - SendPacketCompletion(target,pPacket); - } - } - } + if (adf_os_unlikely(A_FAILED(status))) + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("htc_issue_packets, failed pkt:0x%p status:%d", + pPacket, status)); - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCIssuePackets \n")); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCIssuePackets\n")); return status; } @@ -1133,7 +1124,16 @@ static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET *target, UNLOCK_HTC_TX(target); /* send what we can */ - HTCIssuePackets(target,pEndpoint,&sendQueue); + result = HTCIssuePackets(target, pEndpoint, &sendQueue); + if (result) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("htc_issue_packets, failed status:%d put it back to head of callers SendQueue", + result)); + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, + &sendQueue); + LOCK_HTC_TX(target); + break; + } if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { tx_resources = HIFGetFreeQueueNumber(target->hif_dev,pEndpoint->UL_PipeID); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h index 46daf2fac44c..a50b19543f5c 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h @@ -260,6 +260,7 @@ enum EnumRd { APL10 = 0x1050, /* Korea. After 11/2007. For STAs only */ APL11 = 0x1150, /* Specific AP Customer 5GHz, For APs Only */ APL12 = 0x1160, /* Kenya */ + APL13 = 0x1170, /* Algeria */ ETSI1 = 0x0130, /* Europe & others */ ETSI2 = 0x0230, /* Europe & others */ @@ -372,6 +373,7 @@ static const REG_DMN_PAIR_MAPPING ahCmnRegDomainPairs[] = { {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, + {APL13_WORLD, APL13, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL7_FCCA, APL7, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 }, @@ -481,8 +483,8 @@ static const REG_DMN_PAIR_MAPPING ahCmnRegDomainPairs[] = { static const COUNTRY_CODE_TO_ENUM_RD ahCmnAllCountries[] = { {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, - {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, - {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ALBANIA, ETSI1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_ALGERIA, APL13_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, {CTRY_ARGENTINA, FCC3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES, YES, YES, YES, YES, 7000 }, {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, {CTRY_ARUBA, ETSI1_WORLD, "AW", "ARUBA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, @@ -492,7 +494,7 @@ static const COUNTRY_CODE_TO_ENUM_RD ahCmnAllCountries[] = { {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_BAHAMAS, FCC3_WORLD, "BS", "BAHAMAS", YES, YES, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES, YES, NO, NO, 7000 }, - {CTRY_BANGLADESH, NULL1_WORLD, "BD", "BANGLADESH", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, + {CTRY_BANGLADESH, APL1_WORLD, "BD", "BANGLADESH", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, {CTRY_BARBADOS, FCC2_WORLD, "BB", "BARBADOS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, @@ -671,7 +673,7 @@ static const COUNTRY_CODE_TO_ENUM_RD ahCmnAllCountries[] = { {CTRY_VENEZUELA, FCC1_WORLD, "VE", "VENEZUELA", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_VIET_NAM, ETSI3_WORLD, "VN", "VIET NAM", YES, NO, YES, YES, YES, YES, YES, YES, 7000 }, {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES, NO, NO, NO, 7000 }, - {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES, YES, NO, NO, NO, 7000 } + {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES, YES, NO, NO, NO, 7000 } }; @@ -1295,6 +1297,15 @@ static const REG_DOMAIN ahCmnRegDomains[] = { CHAN_TURBO_G_BMZERO }, + {APL13, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB, + BM(F5_5180_5240, F1_5500_5560, F1_5745_5765, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO + }, + {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, BM(F2_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1), BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c index 38686d5bdd04..630625f6482a 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c @@ -170,6 +170,8 @@ #define WMI_MAX_HOST_CREDITS 2 #define WMI_WOW_REQUIRED_CREDITS 1 +#define WMI_MAX_MHF_ENTRIES 32 + #ifdef FEATURE_WLAN_D0WOW #define DISABLE_PCIE_POWER_COLLAPSE 1 #define ENABLE_PCIE_POWER_COLLAPSE 0 @@ -1259,6 +1261,9 @@ static int wma_vdev_start_rsp_ind(tp_wma_handle wma, u_int8_t *buf) params->chainMask = resp_event->chain_mask; params->smpsMode = host_map_smps_mode(resp_event->smps_mode); params->status = resp_event->status; + if (wma->interfaces[resp_event->vdev_id].is_channel_switch) + wma->interfaces[resp_event->vdev_id].is_channel_switch = + VOS_FALSE; if (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT && (iface->type == WMI_VDEV_TYPE_STA)) { @@ -1516,7 +1521,7 @@ static int32_t wmi_unified_peer_delete_send(wmi_unified_t wmi, if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_DELETE_CMDID)) { WMA_LOGP("%s: Failed to send peer delete command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); @@ -1549,7 +1554,7 @@ static int32_t wmi_unified_peer_flush_tids_send(wmi_unified_t wmi, if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_FLUSH_TIDS_CMDID)) { WMA_LOGP("%s: Failed to send flush tid command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); @@ -1773,7 +1778,7 @@ static int wmi_unified_vdev_down_send(wmi_unified_t wmi, u_int8_t vdev_id) cmd->vdev_id = vdev_id; if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_DOWN_CMDID)) { WMA_LOGP("%s: Failed to send vdev down", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } WMA_LOGD("%s: vdev_id %d", __func__, vdev_id); @@ -2018,7 +2023,7 @@ void wma_hidden_ssid_vdev_restart_on_vdev_stop(tp_wma_handle wma_handle, u_int8_ if (ret < 0) { WMA_LOGE("%s: Failed to send vdev restart command", __func__); adf_os_atomic_set(&intr[sessionId].vdev_restart_params.hidden_ssid_restart_in_progress,0); - adf_nbuf_free(buf); + wmi_buf_free(buf); } } @@ -4249,7 +4254,7 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, wmi_rate_stats *rate_stats; tSirLLStatsResults *link_stats_results; u_int8_t *results, *t_peer_stats, *t_rate_stats; - u_int32_t count, num_rates=0; + u_int32_t count, num_rates=0, rate_cnt; u_int32_t next_res_offset, next_peer_offset, next_rate_offset; size_t peer_info_size, peer_stats_size, rate_stats_size; size_t link_stats_results_size; @@ -4337,7 +4342,7 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, next_res_offset = peer_stats_size; next_peer_offset = WMI_TLV_HDR_SIZE; next_rate_offset = WMI_TLV_HDR_SIZE; - for (count = 0; count < fixed_param->num_peers; count++) { + for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) { WMA_LOGD("Peer Info:"); WMA_LOGD("peer_type %u capabilities %u num_rates %u", peer_stats->peer_type, peer_stats->capabilities, @@ -4865,7 +4870,7 @@ static void wma_send_bcn_buf_ll(tp_wma_handle wma, ret = adf_nbuf_map_single(pdev->osdev, bcn->buf, ADF_OS_DMA_TO_DEVICE); if (ret != A_STATUS_OK) { - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); WMA_LOGE("%s: failed map beacon buf to DMA region", __func__); adf_os_spin_unlock_bh(&bcn->lock); @@ -7171,6 +7176,8 @@ static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, if (!generateRsp) { WMA_LOGE("Call txrx detach w/o callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); + iface->handle = NULL; + wma_handle->interfaces[vdev_id].is_vdev_valid = false; adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); goto out; } @@ -7187,6 +7194,8 @@ static VOS_STATUS wma_vdev_detach(tp_wma_handle wma_handle, } WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); + iface->handle = NULL; + wma_handle->interfaces[vdev_id].is_vdev_valid = false; wma_vdev_detach_callback(iface); adf_os_spin_unlock_bh(&wma_handle->vdev_detach_lock); return status; @@ -7229,7 +7238,7 @@ static int wmi_unified_peer_create_send(wmi_unified_t wmi, if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_CREATE_CMDID)) { WMA_LOGP("%s: failed to send WMI_PEER_CREATE_CMDID", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); @@ -7343,7 +7352,7 @@ static void wma_set_sta_keep_alive(tp_wma_handle wma, u_int8_t vdev_id, WMA_LOGE("%s: received null pointer, hostv4addr:%p " "destv4addr:%p destmac:%p ", __func__, hostv4addr, destv4addr, destmac); - adf_nbuf_free(buf); + wmi_buf_free(buf); return; } @@ -7360,7 +7369,7 @@ static void wma_set_sta_keep_alive(tp_wma_handle wma, u_int8_t vdev_id, if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_STA_KEEPALIVE_CMDID)) { WMA_LOGE("Failed to set KeepAlive"); - adf_nbuf_free(buf); + wmi_buf_free(buf); } WMA_LOGD("%s: Exit", __func__); @@ -7473,7 +7482,7 @@ static VOS_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(tANI_U32 mcc_ada if (ret) { WMA_LOGP("%s: Failed to send enable/disable MCC" " adaptive scheduler command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); } return VOS_STATUS_SUCCESS; } @@ -7579,7 +7588,7 @@ static VOS_STATUS wma_set_mcc_channel_time_latency if (ret) { WMA_LOGE("%s: Failed to send MCC Channel Time Latency command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } @@ -7709,7 +7718,7 @@ static VOS_STATUS wma_set_mcc_channel_time_quota WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID); if (ret) { WMA_LOGE("Failed to send MCC Channel Time Quota command"); - adf_nbuf_free(buf); + wmi_buf_free(buf); VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } @@ -7737,6 +7746,7 @@ static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, tANI_U16 val16; int ret; tSirMacHTCapabilityInfo *phtCapInfo; + u_int8_t vdev_id; if (NULL == mac) { WMA_LOGE("%s: Failed to get mac",__func__); @@ -7756,6 +7766,7 @@ static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, status = VOS_STATUS_E_RESOURCES; goto end; } + vdev_id = self_sta_req->sessionId; txrx_vdev_type = wma_get_txrx_vdev_type(self_sta_req->type); @@ -7782,6 +7793,8 @@ static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, self_sta_req->sessionId); goto end; } + + wma_handle->interfaces[self_sta_req->sessionId].vdev_active = TRUE; wma_handle->interfaces[self_sta_req->sessionId].handle = txrx_vdev_handle; wma_handle->interfaces[self_sta_req->sessionId].ptrn_match_enable = @@ -7856,6 +7869,8 @@ static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, self_sta_req->sessionId); } } + wma_handle->interfaces[vdev_id].is_vdev_valid = true; + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, self_sta_req->sessionId, WMI_VDEV_PARAM_DISCONNECT_TH, @@ -8260,7 +8275,10 @@ VOS_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, cmd->scan_ctrl_flags |= WMI_SCAN_ADD_BCAST_PROBE_REQ; if (scan_req->scanType == eSIR_PASSIVE_SCAN) cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; + + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_TPC_IE_IN_PROBE_REQ; cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ; + /* * Decide burst_duration and dwell_time_active based on * what type of devices are active. @@ -8703,7 +8721,7 @@ static VOS_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id) error: if (buf) - adf_nbuf_free(buf); + wmi_buf_free(buf); return vos_status; } @@ -8756,7 +8774,7 @@ static VOS_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id) error: if (buf) - adf_nbuf_free(buf); + wmi_buf_free(buf); return vos_status; } #else @@ -8873,7 +8891,7 @@ VOS_STATUS wma_start_scan(tp_wma_handle wma_handle, error: wma_reset_scan_info(wma_handle, cmd->vdev_id); if (buf) - adf_nbuf_free(buf); + wmi_buf_free(buf); error0: /* Stop the timer for scan completion */ if (vos_timer_stop(&wma_handle->wma_scan_comp_timer) @@ -8941,7 +8959,7 @@ static VOS_STATUS wma_stop_scan(tp_wma_handle wma_handle, return VOS_STATUS_SUCCESS; error: if (buf) - adf_nbuf_free(buf); + wmi_buf_free(buf); error1: return vos_status; } @@ -11186,7 +11204,12 @@ static WLAN_PHY_MODE wma_chan_to_mode(u8 chan, ePhyChanBondState chan_offset, if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) { switch (chan_offset) { case PHY_SINGLE_CHANNEL_CENTERED: - phymode = vht_capable ? MODE_11AC_VHT20 :MODE_11NA_HT20; + if (dot11_mode == WNI_CFG_DOT11_MODE_11A) + phymode = MODE_11A; + else + phymode = vht_capable ? MODE_11AC_VHT20 : + MODE_11NA_HT20; + break; case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: @@ -11291,7 +11314,15 @@ VOS_STATUS wma_vdev_start(tp_wma_handle wma, intr[cmd->vdev_id].vht_capable = req->vht_capable; intr[cmd->vdev_id].config.gtx_info.gtxRTMask[0] = CFG_TGT_DEFAULT_GTX_HT_MASK; intr[cmd->vdev_id].config.gtx_info.gtxRTMask[1] = CFG_TGT_DEFAULT_GTX_VHT_MASK; - intr[cmd->vdev_id].config.gtx_info.gtxUsrcfg = CFG_TGT_DEFAULT_GTX_USR_CFG; + + if (wlan_cfgGetInt(pmac, WNI_CFG_TGT_GTX_USR_CFG, + &intr[cmd->vdev_id].config.gtx_info.gtxUsrcfg) + != eSIR_SUCCESS) { + WMA_LOGE("Failed to read target gtx user config"); + intr[cmd->vdev_id].config.gtx_info.gtxUsrcfg = + WNI_CFG_TGT_GTX_USR_CFG_STADEF; + } + intr[cmd->vdev_id].config.gtx_info.gtxPERThreshold = CFG_TGT_DEFAULT_GTX_PER_THRESHOLD; intr[cmd->vdev_id].config.gtx_info.gtxPERMargin = CFG_TGT_DEFAULT_GTX_PER_MARGIN; intr[cmd->vdev_id].config.gtx_info.gtxTPCstep = CFG_TGT_DEFAULT_GTX_TPC_STEP; @@ -11372,7 +11403,7 @@ VOS_STATUS wma_vdev_start(tp_wma_handle wma, " Failed to send VDEV START command", __func__, __LINE__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return VOS_STATUS_E_FAILURE; } @@ -11474,7 +11505,7 @@ VOS_STATUS wma_vdev_start(tp_wma_handle wma, if (ret < 0) { WMA_LOGP("%s: Failed to send vdev start command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return VOS_STATUS_E_FAILURE; } @@ -11539,6 +11570,12 @@ void wma_vdev_resp_timer(void *data) adf_os_spin_lock_bh(&wma->roam_preauth_lock); wma->roam_preauth_scan_id = -1; adf_os_spin_unlock_bh(&wma->roam_preauth_lock); + if (wma->interfaces[tgt_req->vdev_id].is_channel_switch) + wma->interfaces[tgt_req->vdev_id].is_channel_switch = + VOS_FALSE; + if (wma->interfaces[tgt_req->vdev_id].is_channel_switch) + wma->interfaces[tgt_req->vdev_id].is_channel_switch = + VOS_FALSE; } else if (tgt_req->msg_type == WDA_DELETE_BSS_REQ) { tpDeleteBssParams params = (tpDeleteBssParams)tgt_req->user_data; @@ -12035,8 +12072,6 @@ static void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) goto send_resp; } - if (wma->interfaces[req.vdev_id].is_channel_switch) - wma->interfaces[req.vdev_id].is_channel_switch = VOS_FALSE; return; send_resp: WMA_LOGD("%s: channel %d offset %d txpower %d status %d", __func__, @@ -12324,15 +12359,16 @@ static int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, if (params->htCapable) { cmd->peer_flags |= (WMI_PEER_HT | WMI_PEER_QOS); cmd->peer_rate_caps |= WMI_RC_HT_FLAG; - } - if (params->txChannelWidthSet) { - cmd->peer_flags |= WMI_PEER_40MHZ; - cmd->peer_rate_caps |= WMI_RC_CW40_FLAG; - if (params->fShortGI40Mhz) + if (params->txChannelWidthSet) { + cmd->peer_flags |= WMI_PEER_40MHZ; + cmd->peer_rate_caps |= WMI_RC_CW40_FLAG; + if (params->fShortGI40Mhz) + cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; + } else if (params->fShortGI20Mhz) { cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; - } else if (params->fShortGI20Mhz) - cmd->peer_rate_caps |= WMI_RC_SGI_FLAG; + } + } #ifdef WLAN_FEATURE_11AC if (params->vhtCapable) { @@ -12411,7 +12447,7 @@ static int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, FALSE); if (ret) { WMA_LOGE("Set WMI_VDEV_PARAM_DROP_UNENCRY Param status:%d\n", ret); - adf_nbuf_free(buf); + wmi_buf_free(buf); return ret; } } @@ -12500,7 +12536,7 @@ static int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, if (ret != EOK) { WMA_LOGP("%s: Failed to send peer assoc command ret = %d", __func__, ret); - adf_nbuf_free(buf); + wmi_buf_free(buf); } return ret; } @@ -12580,7 +12616,7 @@ VOS_STATUS wma_get_link_speed(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID)) { WMA_LOGE("%s: failed to send link speed command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -13060,7 +13096,7 @@ static int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle, WMI_STA_POWERSAVE_PARAM_CMDID)) { WMA_LOGE("Set Sta Ps param Failed vdevId %d Param %d val %d", vdev_id, param, value); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } /* Store the PS Status */ @@ -13096,7 +13132,7 @@ static int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID)) { WMA_LOGE("Set Green AP PS param Failed val %d", value); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } return 0; @@ -13165,7 +13201,7 @@ static void wma_send_echo_request(tp_wma_handle wma) if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_ECHO_CMDID)) { WMA_LOGE("Failed to send Echo cmd to firmware"); - adf_nbuf_free(buf); + wmi_buf_free(buf); } } @@ -13249,6 +13285,10 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, switch (privcmd->param_vp_dev) { case VDEV_CMD: + if (!wma->interfaces[privcmd->param_vdev_id].is_vdev_valid) { + WMA_LOGE("%s Vdev id is not valid", __func__); + return ; + } WMA_LOGD("vdev id %d pid %d pval %d", privcmd->param_vdev_id, privcmd->param_id, privcmd->param_value); ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, @@ -15029,7 +15069,7 @@ static int wmi_unified_vdev_up_send(wmi_unified_t wmi, WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid, &cmd->vdev_bssid); if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_UP_CMDID)) { WMA_LOGP("%s: Failed to send vdev up command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } return 0; @@ -15061,7 +15101,7 @@ static int32_t wmi_unified_set_ap_ps_param(void *wma_ctx, u_int32_t vdev_id, sizeof(*cmd), WMI_AP_PS_PEER_PARAM_CMDID); if (err) { WMA_LOGE("Failed to send set_ap_ps_param cmd"); - adf_os_mem_free(buf); + wmi_buf_free(buf); return -EIO; } return 0; @@ -16035,7 +16075,7 @@ static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, default: /* TODO: MFP ? */ WMA_LOGE("%s:Invalid encryption type:%d", __func__, key_params->key_type); - adf_nbuf_free(buf); + wmi_buf_free(buf); return NULL; } @@ -16192,7 +16232,7 @@ static void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info) status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_VDEV_INSTALL_KEY_CMDID); if (status) { - adf_nbuf_free(buf); + wmi_buf_free(buf); WMA_LOGE("%s:Failed to send install key command", __func__); key_info->status = eHAL_STATUS_FAILURE; goto out; @@ -16272,7 +16312,7 @@ static void wma_set_ibsskey_helper(tp_wma_handle wma_handle, tpSetBssKeyParams k status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_VDEV_INSTALL_KEY_CMDID); if (status) { - adf_nbuf_free(buf); + wmi_buf_free(buf); WMA_LOGE("%s:Failed to send install key command", __func__); } } @@ -16378,7 +16418,7 @@ static void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info) status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_VDEV_INSTALL_KEY_CMDID); if (status) { - adf_nbuf_free(buf); + wmi_buf_free(buf); WMA_LOGE("%s:Failed to send install key command", __func__); key_info->status = eHAL_STATUS_FAILURE; goto out; @@ -16599,7 +16639,7 @@ static int32_t wmi_unified_vdev_stop_send(wmi_unified_t wmi, u_int8_t vdev_id) cmd->vdev_id = vdev_id; if (wmi_unified_cmd_send(wmi, buf, len, WMI_VDEV_STOP_CMDID)) { WMA_LOGP("%s: Failed to send vdev stop command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } return 0; @@ -17517,14 +17557,18 @@ static void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__); return; } - if (!wma->interfaces[vdev_id].vdev_up) { - if (wmi_unified_vdev_up_send(wma->wmi_handle, vdev_id, 0, - bcn_info->bssId) < 0) { - WMA_LOGE("%s : failed to send vdev up", __func__); - return; - } - wma->interfaces[vdev_id].vdev_up = TRUE; - wma_set_sap_keepalive(wma, vdev_id); + if (!((adf_os_atomic_read( + &wma->interfaces[vdev_id].vdev_restart_params.hidden_ssid_restart_in_progress)) || + (wma->interfaces[vdev_id].is_channel_switch))) { + if (!wma->interfaces[vdev_id].vdev_up) { + if (wmi_unified_vdev_up_send(wma->wmi_handle, vdev_id, 0, + bcn_info->bssId) < 0) { + WMA_LOGE("%s : failed to send vdev up", __func__); + return; + } + wma->interfaces[vdev_id].vdev_up = TRUE; + wma_set_sap_keepalive(wma, vdev_id); + } } } @@ -17635,7 +17679,7 @@ static int32_t wmi_unified_set_sta_ps(wmi_unified_t wmi_handle, { WMA_LOGE("Set Sta Mode Ps Failed vdevId %d val %d", vdev_id, val); - adf_nbuf_free(buf); + wmi_buf_free(buf); return -EIO; } return 0; @@ -19614,6 +19658,9 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, tp_wma_handle wma = (tp_wma_handle) handle; WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf; WOW_EVENT_INFO_fixed_param *wake_info; +#ifdef FEATURE_WLAN_TDLS + WMI_TDLS_PEER_EVENTID_param_tlvs tdls_param; +#endif #ifdef FEATURE_WLAN_SCAN_PNO struct wma_txrx_node *node; #endif @@ -19848,6 +19895,20 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, } break; +#ifdef FEATURE_WLAN_TDLS + case WOW_REASON_TDLS_CONN_TRACKER_EVENT: + if (param_buf->wow_packet_buffer) { + WMA_LOGD("Host woken up because of TDLS event"); + tdls_param.fixed_param = + (wmi_tdls_peer_event_fixed_param *) + (param_buf->wow_packet_buffer + 4); + wma_tdls_event_handler(handle, + (u_int8_t *)&tdls_param, sizeof(tdls_param)); + } else { + WMA_LOGD("No wow_packet_buffer present"); + } + break; +#endif default: break; } @@ -19933,6 +19994,8 @@ static const u8 *wma_wow_wakeup_event_str(WOW_WAKE_EVENT_TYPE event) return "WOW_IOAC_SOCK_EVENT"; case WOW_NLO_SCAN_COMPLETE_EVENT: return "WOW_NLO_SCAN_COMPLETE_EVENT"; + case WOW_TDLS_CONN_TRACKER_EVENT: + return "WOW_TDLS_CONN_TRACKER_EVENT"; default: return "UNSPECIFIED_EVENT"; } @@ -20351,6 +20414,7 @@ int wma_enable_wow_in_fw(WMA_HANDLE handle, int runtime_pm) WMA_LOGE("Credits:%d; Pending_Cmds: %d", wmi_get_host_credits(wma->wmi_handle), wmi_get_pending_cmds(wma->wmi_handle)); + wmi_set_target_suspend(wma->wmi_handle, FALSE); if (!vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { #ifdef CONFIG_CNSS if (pMac->sme.enableSelfRecovery) { @@ -20365,7 +20429,6 @@ int wma_enable_wow_in_fw(WMA_HANDLE handle, int runtime_pm) WMA_LOGE("%s: LOGP is in progress, ignore!", __func__); } - wmi_set_target_suspend(wma->wmi_handle, FALSE); return VOS_STATUS_E_FAILURE; } @@ -20990,6 +21053,11 @@ static VOS_STATUS wma_feed_wow_config_to_fw(tp_wma_handle wma, wma_add_wow_wakeup_event(wma, WOW_EXTSCAN_EVENT, extscan_in_progress); #endif +#ifdef FEATURE_WLAN_TDLS + /* configure TDLS based wakeup */ + wma_add_wow_wakeup_event(wma, WOW_TDLS_CONN_TRACKER_EVENT, TRUE); +#endif + /* Enable wow wakeup events in FW */ ret = wma_send_wakeup_mask(wma, TRUE); if (ret) { @@ -21856,7 +21924,7 @@ static void wma_start_oem_data_req(tp_wma_handle wma_handle, WMA_LOGD("%s: Send OEM Data Request to target", __func__); - if (!startOemDataReq) { + if (!startOemDataReq || !startOemDataReq->data) { WMA_LOGE("%s: startOemDataReq is null", __func__); goto out; } @@ -21867,7 +21935,7 @@ static void wma_start_oem_data_req(tp_wma_handle wma_handle, } buf = wmi_buf_alloc(wma_handle->wmi_handle, - (OEM_DATA_REQ_SIZE + WMI_TLV_HDR_SIZE)); + (startOemDataReq->data_len + WMI_TLV_HDR_SIZE)); if (!buf) { WMA_LOGE("%s:wmi_buf_alloc failed", __func__); goto out; @@ -21876,27 +21944,31 @@ static void wma_start_oem_data_req(tp_wma_handle wma_handle, cmd = (u_int8_t *)wmi_buf_data(buf); WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, - OEM_DATA_REQ_SIZE); + startOemDataReq->data_len); cmd += WMI_TLV_HDR_SIZE; - vos_mem_copy(cmd, &startOemDataReq->oemDataReq[0], OEM_DATA_REQ_SIZE); + vos_mem_copy(cmd, &startOemDataReq->data[0], + startOemDataReq->data_len); WMA_LOGI("%s: Sending OEM Data Request to target, data len (%d)", - __func__, OEM_DATA_REQ_SIZE); + __func__, startOemDataReq->data_len); ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, - (OEM_DATA_REQ_SIZE + + (startOemDataReq->data_len + WMI_TLV_HDR_SIZE), WMI_OEM_REQ_CMDID); if (ret != EOK) { WMA_LOGE("%s:wmi cmd send failed", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); } out: /* free oem data req buffer received from UMAC */ - if (startOemDataReq) + if (startOemDataReq) { + if (startOemDataReq->data) + vos_mem_free(startOemDataReq->data); vos_mem_free(startOemDataReq); + } /* Now send data resp back to PE/SME with message sub-type of * WMI_OEM_INTERNAL_RSP. This is required so that PE/SME clears @@ -22093,7 +22165,7 @@ static void wma_set_ric_req(tp_wma_handle wma, void *msg, tANI_U8 is_add_ts) WMA_LOGP("%s: Failed to send vdev Set RIC Req command", __func__); if(is_add_ts) ((tAddTsParams *)msg)->status = eHAL_STATUS_FAILURE; - adf_nbuf_free(buf); + wmi_buf_free(buf); } } #endif @@ -22121,7 +22193,7 @@ static void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg) if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_VDEV_WMM_DELTS_CMDID)) { WMA_LOGP("%s: Failed to send vdev DELTS command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); } #ifdef WLAN_FEATURE_ROAM_OFFLOAD @@ -22180,7 +22252,7 @@ static void wma_aggr_qos_req(tp_wma_handle wma, tAggrAddTsParams *pAggrQosRspMsg WMI_VDEV_WMM_ADDTS_CMDID)) { WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__); pAggrQosRspMsg->status[i] = eHAL_STATUS_FAILURE; - adf_nbuf_free(buf); + wmi_buf_free(buf); } } } @@ -22236,7 +22308,7 @@ static void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg) WMI_VDEV_WMM_ADDTS_CMDID)) { WMA_LOGP("%s: Failed to send vdev ADDTS command", __func__); msg->status = eHAL_STATUS_FAILURE; - adf_nbuf_free(buf); + wmi_buf_free(buf); } #ifdef WLAN_FEATURE_ROAM_OFFLOAD @@ -22387,7 +22459,7 @@ static int wma_set_base_macaddr_indicate(tp_wma_handle wma_handle, sizeof(*cmd), WMI_PDEV_SET_BASE_MACADDR_CMDID); if (err) { WMA_LOGE("Failed to send set_base_macaddr cmd"); - adf_os_mem_free(buf); + wmi_buf_free(buf); return -EIO; } WMA_LOGD("Base MAC Addr: "MAC_ADDRESS_STR, @@ -22528,7 +22600,7 @@ static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id, sizeof(*cmd), WMI_SET_MCASTBCAST_FILTER_CMDID); if (err) { WMA_LOGE("Failed to send set_param cmd"); - adf_os_mem_free(buf); + wmi_buf_free(buf); return -EIO; } WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d\n", @@ -23527,6 +23599,357 @@ static void wma_process_update_userpos(tp_wma_handle wma_handle, } #endif +/* + * FUNCTION: wma_find_ibss_vdev + * This function finds vdev_id based on input type + */ +int32_t wma_find_vdev_by_type(tp_wma_handle wma, int32_t type) +{ + int32_t vdev_id = 0; + struct wma_txrx_node *intf = wma->interfaces; + + for(vdev_id = 0; vdev_id < wma->max_bssid ; vdev_id++) + { + if (NULL != intf) + { + if (intf[vdev_id].type == type) + return vdev_id; + } + } + + return -1; +} + +/* + * FUNCTION: wma_process_cesium_enable_ind + * This function enables cesium functionality in target + */ +VOS_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma) +{ + int32_t ret; + int32_t vdev_id; + + vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS); + if (vdev_id < 0) + { + WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium", + __func__); + return VOS_STATUS_E_FAILURE; + } + + /* Send enable cesium command to target */ + WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id); + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_ENABLE_RMC, 1); + if (ret) + { + WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id); + return VOS_STATUS_E_FAILURE; + } + return VOS_STATUS_SUCCESS; +} + +/* + * FUNCTION: wma_process_get_peer_info_req + * This function sends get peer info cmd to target + */ +VOS_STATUS wma_process_get_peer_info_req +( + tp_wma_handle wma, + tSirIbssGetPeerInfoReqParams *pReq +) +{ + int32_t ret; + u_int8_t *p; + u_int16_t len; + wmi_buf_t buf; + int32_t vdev_id; + ol_txrx_pdev_handle pdev; + struct ol_txrx_peer_t *peer; + u_int8_t peer_mac[IEEE80211_ADDR_LEN]; + wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd; + u_int8_t bcast_mac[IEEE80211_ADDR_LEN] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS); + if (vdev_id < 0) + { + WMA_LOGE("%s: IBSS vdev does not exist could not get peer info", + __func__); + return VOS_STATUS_E_FAILURE; + } + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev context", __func__); + return VOS_STATUS_E_FAILURE; + } + + if (0xFF == pReq->staIdx) + { + /*get info for all peers*/ + vos_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN); + } + else + { + /*get info for a single peer*/ + peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx); + if (!peer) + { + WMA_LOGE("%s: Failed to get peer handle using peer id %d", + __func__, pReq->staIdx); + return VOS_STATUS_E_FAILURE; + } + WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x", + __func__, pReq->staIdx, peer->mac_addr.raw[0], peer->mac_addr.raw[1], + peer->mac_addr.raw[2], peer->mac_addr.raw[3], peer->mac_addr.raw[4], + peer->mac_addr.raw[5]); + vos_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN); + } + + len = sizeof(wmi_peer_info_req_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) + { + WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__); + return VOS_STATUS_E_FAILURE; + } + + p = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(p, len); + p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *)p; + + WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_peer_info_req_cmd_fixed_param)); + + p_get_peer_info_cmd->vdev_id = vdev_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,&p_get_peer_info_cmd->peer_mac_address); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PEER_INFO_REQ_CMDID); + + WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d" + " command id: %d, status: %d", len, p_get_peer_info_cmd->vdev_id, + WMI_PEER_INFO_REQ_CMDID, ret); + + return VOS_STATUS_SUCCESS; +} + +/* + * FUNCTION: wma_process_tx_fail_monitor_ind + * This function sends tx fail monitor cmd to target + */ +VOS_STATUS wma_process_tx_fail_monitor_ind +( + tp_wma_handle wma, + tAniTXFailMonitorInd *pReq) +{ + int32_t ret; + int32_t vdev_id; + + vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS); + if (vdev_id < 0) + { + WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail" + " monitor indication message to target", __func__); + return VOS_STATUS_E_FAILURE; + } + + /* Send enable cesium command to target */ + WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d", + vdev_id, pReq->tx_fail_count); + + if (0 == pReq->tx_fail_count) + { + wma->hddTxFailCb = NULL; + } + else + { + wma->hddTxFailCb = pReq->txFailIndCallback; + } + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR, pReq->tx_fail_count); + if (ret) + { + WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id); + return VOS_STATUS_E_FAILURE; + } + + return VOS_STATUS_SUCCESS; +} + +/* + * FUNCTION: wma_process_rmc_enable_ind + * This function enables RMC functionality in target + */ +VOS_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma) +{ + int ret; + u_int8_t *p; + u_int16_t len; + wmi_buf_t buf; + int32_t vdev_id; + wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd; + + vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS); + if (vdev_id < 0) + { + WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC", + __func__); + return VOS_STATUS_E_FAILURE; + } + + len = sizeof(wmi_rmc_set_mode_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) + { + WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__); + return VOS_STATUS_E_FAILURE; + } + + p = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(p, len); + p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *)p; + + WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_rmc_set_mode_cmd_fixed_param)); + + p_rmc_enable_cmd->vdev_id = vdev_id; + p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RMC_SET_MODE_CMDID); + + WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d," + " status: %d", len, p_rmc_enable_cmd->vdev_id, WMI_RMC_SET_MODE_CMDID, + ret); + + return VOS_STATUS_SUCCESS; +} + + + +/* + * FUNCTION: wma_process_rmc_disable_ind + * This function disables cesium functionality in target + */ +VOS_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma) +{ + int ret; + u_int8_t *p; + u_int16_t len; + wmi_buf_t buf; + int32_t vdev_id; + wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd; + + vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS); + if (vdev_id < 0) + { + WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC", + __func__); + return VOS_STATUS_E_FAILURE; + } + + len = sizeof(wmi_rmc_set_mode_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) + { + WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__); + return VOS_STATUS_E_FAILURE; + } + + p = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(p, len); + p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *)p; + + WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_rmc_set_mode_cmd_fixed_param)); + + p_rmc_disable_cmd->vdev_id = vdev_id; + p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RMC_SET_MODE_CMDID); + + WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d," + " status: %d", len, p_rmc_disable_cmd->vdev_id, WMI_RMC_SET_MODE_CMDID, + ret); + + return VOS_STATUS_SUCCESS; +} + + + +/* + * FUNCTION: wma_process_rmc_action_period_ind + * This function sends RMC action period to target + */ +VOS_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma) +{ + int ret; + u_int8_t *p; + u_int16_t len; + u_int32_t val; + wmi_buf_t buf; + int32_t vdev_id; + wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd; + struct sAniSirGlobal *mac = + (struct sAniSirGlobal*)vos_get_context(VOS_MODULE_ID_PE, + wma->vos_context); + + if (NULL == mac) { + WMA_LOGE("%s: MAC mac does not exist", __func__); + return VOS_STATUS_E_FAILURE; + } + + vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS); + if (vdev_id < 0) + { + WMA_LOGE("%s: IBSS vdev does not exist could not send" + " RMC action period to target", __func__); + return VOS_STATUS_E_FAILURE; + } + + len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) + { + WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__); + return VOS_STATUS_E_FAILURE; + } + + p = (u_int8_t *) wmi_buf_data(buf); + vos_mem_zero(p, len); + p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *)p; + + WMITLV_SET_HDR(&p_rmc_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_rmc_set_action_period_cmd_fixed_param)); + + if (wlan_cfgGetInt(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val) + != eSIR_SUCCESS) + { + WMA_LOGE("Failed to get value for RMC action period using default"); + val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF; + } + + p_rmc_cmd->vdev_id = vdev_id; + p_rmc_cmd->periodicity_msec = val; + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RMC_SET_ACTION_PERIOD_CMDID); + + WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d" + " command id: %d, status: %d", p_rmc_cmd->periodicity_msec, len, + p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret); + + return VOS_STATUS_SUCCESS; +} + /* function : wma_process_init_thermal_info * Description : This function initializes the thermal management table in WMA, sends down the initial temperature thresholds to the firmware and @@ -23805,7 +24228,7 @@ VOS_STATUS wma_set_peer_rate_report_condition(WMA_HANDLE handle, status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID); if (status) { - adf_nbuf_free(buf); + wmi_buf_free(buf); WMA_LOGE("%s:Failed to send peer_set_report_cond command", __func__); return eHAL_STATUS_FAILURE; @@ -23915,7 +24338,7 @@ VOS_STATUS wma_ProcessAddPeriodicTxPtrnInd(WMA_HANDLE handle, pAddPeriodicTxPtrnParams->macAddress, &vdev_id)) { WMA_LOGE("%s: Failed to find vdev id for %pM",__func__, pAddPeriodicTxPtrnParams->macAddress); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_INVAL; } buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); @@ -23946,7 +24369,7 @@ VOS_STATUS wma_ProcessAddPeriodicTxPtrnInd(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID)) { WMA_LOGE("%s: failed to add pattern set state command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -23980,7 +24403,7 @@ VOS_STATUS wma_ProcessDelPeriodicTxPtrnInd(WMA_HANDLE handle, pDelPeriodicTxPtrnParams->macAddress, &vdev_id)) { WMA_LOGE("%s: Failed to find vdev id for %pM",__func__, pDelPeriodicTxPtrnParams->macAddress); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_INVAL; } cmd = (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)wmi_buf_data(wmi_buf); @@ -23997,7 +24420,7 @@ VOS_STATUS wma_ProcessDelPeriodicTxPtrnInd(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID)) { WMA_LOGE("%s: failed to send del pattern command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -24427,6 +24850,11 @@ static VOS_STATUS wma_process_ll_stats_getReq return VOS_STATUS_E_FAILURE; } + if (!wma->interfaces[getReq->staId].vdev_active) { + WMA_LOGE("%s: vdev not created yet", __func__); + return VOS_STATUS_E_FAILURE; + } + len = sizeof(*cmd); buf = wmi_buf_alloc(wma->wmi_handle, len); @@ -24731,7 +25159,7 @@ VOS_STATUS wma_start_extscan(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_EXTSCAN_START_CMDID)) { WMA_LOGE("%s: failed to send command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return VOS_STATUS_E_FAILURE; } @@ -24779,7 +25207,7 @@ VOS_STATUS wma_stop_extscan(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_EXTSCAN_STOP_CMDID)) { WMA_LOGE("%s: failed to command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } @@ -24925,7 +25353,7 @@ VOS_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) { WMA_LOGE("%s: failed to send command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return VOS_STATUS_E_FAILURE; } index = index + min_entries; @@ -25018,7 +25446,7 @@ VOS_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) { WMA_LOGE("%s: failed to command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -25123,7 +25551,7 @@ wma_set_ssid_hotlist(tp_wma_handle wma, (wma->wmi_handle, wmi_buf, len, WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID)) { WMA_LOGE("%s: failed to send command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -25230,7 +25658,7 @@ VOS_STATUS wma_extscan_start_change_monitor(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) { WMA_LOGE("%s: failed to send command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -25290,7 +25718,7 @@ VOS_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) { WMA_LOGE("%s: failed to command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -25336,7 +25764,7 @@ VOS_STATUS wma_extscan_get_cached_results(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID)) { WMA_LOGE("%s: failed to command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -25380,7 +25808,7 @@ VOS_STATUS wma_extscan_get_capabilities(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_EXTSCAN_GET_CAPABILITIES_CMDID)) { WMA_LOGE("%s: failed to command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -25676,6 +26104,11 @@ VOS_STATUS wma_ipa_offload_enable_disable(tp_wma_handle wma, return VOS_STATUS_E_INVAL; } + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + WMA_LOGE("%s: Driver load/unload in progress", __func__); + return VOS_STATUS_E_INVAL; + } + len = sizeof(*cmd); wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); if (!wmi_buf) { @@ -25837,7 +26270,7 @@ static void wma_process_unit_test_cmd(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_UNIT_TEST_CMDID)) { WMA_LOGP("%s: failed to send unit test command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return; } return; @@ -25880,7 +26313,7 @@ VOS_STATUS wma_scan_probe_setoui(tp_wma_handle wma, if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, WMI_SCAN_PROB_REQ_OUI_CMDID)) { WMA_LOGE("%s: failed to send command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return VOS_STATUS_E_FAILURE; } return VOS_STATUS_SUCCESS; @@ -26025,7 +26458,7 @@ static void wma_process_roam_invoke(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_ROAM_INVOKE_CMDID)) { WMA_LOGP("%s: failed to send roam invoke command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return; } return; @@ -27033,6 +27466,120 @@ static VOS_STATUS wma_update_wep_default_key(tp_wma_handle wma, return VOS_STATUS_SUCCESS; } +/** +* wma_set_beacon_filter() - Issue WMI command to set beacon filter +* @wma: wma handler +* @filter_params: beacon_filter_param to set +* +* Return: Return VOS_STATUS +*/ +static VOS_STATUS wma_set_beacon_filter(tp_wma_handle wma, + struct beacon_filter_param *filter_params) +{ + int i; + wmi_buf_t wmi_buf; + u_int8_t *buf; + A_UINT32 *ie_map; + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + wmi_add_bcn_filter_cmd_fixed_param *cmd; + int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param); + + len += WMI_TLV_HDR_SIZE; + len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32); + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue set beacon filter", + __func__); + return VOS_STATUS_E_INVAL; + } + + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + + buf = (u_int8_t *) wmi_buf_data(wmi_buf); + + cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf); + cmd->vdev_id = filter_params->vdev_id; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_add_bcn_filter_cmd_fixed_param)); + + buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param); + + WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32, + (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t))); + + ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE); + for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) { + ie_map[i] = filter_params->ie_map[i]; + WMA_LOGA("beacon filter ie map = %u", ie_map[i]); + } + + vos_status = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_ADD_BCN_FILTER_CMDID); + if (vos_status < 0) { + WMA_LOGE("Failed to send wmi add beacon filter = %d", + vos_status); + wmi_buf_free(wmi_buf); + return VOS_STATUS_E_FAILURE; + } + WMA_LOGA("added beacon filter = %d", vos_status); + + return vos_status; +} + +/** +* wma_remove_beacon_filter() - Issue WMI command to remove beacon filter +* @wma: wma handler +* @filter_params: beacon_filter_params +* +* Return: Return VOS_STATUS +*/ +static VOS_STATUS wma_remove_beacon_filter(tp_wma_handle wma, + struct beacon_filter_param *filter_params) +{ + wmi_buf_t buf; + wmi_rmv_bcn_filter_cmd_fixed_param *cmd; + int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param); + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter", + __func__); + return VOS_STATUS_E_INVAL; + } + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return VOS_STATUS_E_NOMEM; + } + cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf); + cmd->vdev_id = filter_params->vdev_id; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_rmv_bcn_filter_cmd_fixed_param)); + + vos_status = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_RMV_BCN_FILTER_CMDID); + if (vos_status < 0) { + WMA_LOGE("Failed to send wmi remove beacon filter = %d", + vos_status); + wmi_buf_free(buf); + return VOS_STATUS_E_FAILURE; + } + WMA_LOGA("removed beacon filter = %d", vos_status); + + return vos_status; +} + /* * function : wma_mc_process_msg * Description : @@ -27415,6 +27962,29 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) vos_mem_free(msg->bodyptr); break; + case WDA_IBSS_CESIUM_ENABLE_IND: + wma_process_cesium_enable_ind(wma_handle); + break; + case WDA_GET_IBSS_PEER_INFO_REQ: + wma_process_get_peer_info_req(wma_handle, + (tSirIbssGetPeerInfoReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_TX_FAIL_MONITOR_IND: + wma_process_tx_fail_monitor_ind(wma_handle, + (tAniTXFailMonitorInd *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + + case WDA_RMC_ENABLE_IND: + wma_process_rmc_enable_ind(wma_handle); + break; + case WDA_RMC_DISABLE_IND: + wma_process_rmc_disable_ind(wma_handle); + break; + case WDA_RMC_ACTION_PERIOD_IND: + wma_process_rmc_action_period_ind(wma_handle); + break; case WDA_INIT_THERMAL_INFO_CMD: wma_process_init_thermal_info(wma_handle, (t_thermal_mgmt *)msg->bodyptr); @@ -27819,6 +28389,15 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) (struct wep_update_default_key_idx *)msg->bodyptr); vos_mem_free(msg->bodyptr); break; + case WDA_ADD_BCN_FILTER_CMDID: + wma_set_beacon_filter(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + case WDA_REMOVE_BCN_FILTER_CMDID: + wma_remove_beacon_filter(wma_handle, msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; + default: WMA_LOGD("unknow msg type %x", msg->type); /* Do Nothing? MSG Body should be freed at here */ @@ -28150,9 +28729,6 @@ static VOS_STATUS wma_tx_detach(tp_wma_handle wma_handle) txrx_pdev); } } - /* Destroy Tx Frame Complete event */ - vos_event_destroy(&wma_handle->tx_frm_download_comp_event); - /* Tx queue empty check event (dummy event) */ vos_event_destroy(&wma_handle->tx_queue_empty_event); @@ -28575,7 +29151,7 @@ static VOS_STATUS wma_set_thermal_mgmt(tp_wma_handle wma_handle, status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_THERMAL_MGMT_CMDID); if (status) { - adf_nbuf_free(buf); + wmi_buf_free(buf); WMA_LOGE("%s:Failed to send thermal mgmt command", __func__); return eHAL_STATUS_FAILURE; } @@ -28825,6 +29401,126 @@ VOS_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle, } #endif /* FEATURE_WLAN_CH_AVOID */ +/* Handle IBSS peer info event from FW */ +static int wma_ibss_peer_info_event_handler(void *handle, u_int8_t *data, + u_int32_t len) +{ + vos_msg_t vosMsg; + wmi_peer_info *peer_info; + ol_txrx_pdev_handle pdev; + tSirIbssPeerInfoParams *pSmeRsp; + u_int32_t count, num_peers, status; + tSirIbssGetPeerInfoRspParams *pRsp; + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PEER_INFO_EVENTID_param_tlvs *param_tlvs; + wmi_peer_info_event_fixed_param *fix_param; + u_int8_t peer_mac[IEEE80211_ADDR_LEN]; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); + if (NULL == pdev) { + WMA_LOGE("%s: could not get pdev context", __func__); + return 0; + } + + param_tlvs = (WMI_PEER_INFO_EVENTID_param_tlvs *)data; + fix_param = param_tlvs->fixed_param; + peer_info = param_tlvs->peer_info; + num_peers = fix_param->num_peers; + status = 0; + + WMA_LOGE("%s: num_peers %d", __func__, num_peers); + + pRsp = vos_mem_malloc(sizeof(tSirIbssGetPeerInfoRspParams)); + if (NULL == pRsp ) + { + WMA_LOGE("%s: could not allocate memory for ibss peer info rsp len %zu", + __func__, sizeof(tSirIbssGetPeerInfoRspParams)); + return 0; + } + + /*sanity check*/ + if ((num_peers > 32) || (NULL == peer_info)) + { + WMA_LOGE("%s: Invalid event data from target num_peers %d peer_info %p", + __func__, num_peers, peer_info); + status = 1; + goto send_response; + } + + for (count = 0; count < num_peers; count++) + { + pSmeRsp = &pRsp->ibssPeerInfoRspParams.peerInfoParams[count]; + + WMI_MAC_ADDR_TO_CHAR_ARRAY (&peer_info->peer_mac_address, peer_mac); + vos_mem_copy(pSmeRsp->mac_addr, peer_mac, + sizeof(pSmeRsp->mac_addr)); + pSmeRsp->mcsIndex = 0; + pSmeRsp->rssi = peer_info->rssi + WMA_TGT_NOISE_FLOOR_DBM; + pSmeRsp->txRate = peer_info->data_rate; + pSmeRsp->txRateFlags = 0; + + WMA_LOGE("%s: peer " MAC_ADDRESS_STR "rssi %d txRate %d", __func__, + MAC_ADDR_ARRAY(peer_mac), pSmeRsp->rssi, pSmeRsp->txRate); + + peer_info++; + } + +send_response: + /* message header */ + pRsp->mesgType = eWNI_SME_IBSS_PEER_INFO_RSP; + pRsp->mesgLen = sizeof(tSirIbssGetPeerInfoRspParams); + pRsp->ibssPeerInfoRspParams.status = status; + pRsp->ibssPeerInfoRspParams.numPeers = num_peers; + + /* vos message wrapper */ + vosMsg.type = eWNI_SME_IBSS_PEER_INFO_RSP; + vosMsg.bodyptr = (void *)pRsp; + vosMsg.bodyval = 0; + + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vosMsg)) + { + WMA_LOGE("%s: could not post peer info rsp msg to SME", __func__); + /* free the mem and return */ + vos_mem_free((v_VOID_t *) pRsp); + } + + return 0; +} + +/* Handle fast tx failure indication event from FW */ +static int wma_fast_tx_fail_event_handler(void *handle, u_int8_t *data, + u_int32_t len) +{ + u_int8_t tx_fail_cnt; + u_int8_t peer_mac[IEEE80211_ADDR_LEN]; + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PEER_TX_FAIL_CNT_THR_EVENTID_param_tlvs *param_tlvs; + wmi_peer_tx_fail_cnt_thr_event_fixed_param *fix_param; + + param_tlvs = (WMI_PEER_TX_FAIL_CNT_THR_EVENTID_param_tlvs *)data; + fix_param = param_tlvs->fixed_param; + + WMI_MAC_ADDR_TO_CHAR_ARRAY (&fix_param->peer_mac_address, peer_mac); + WMA_LOGE("%s: received fast tx failure event for peer" + " 0x:%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x seq No %d", __func__, + peer_mac[0], peer_mac[1], peer_mac[2], peer_mac[3], + peer_mac[4], peer_mac[5], fix_param->seq_no); + + tx_fail_cnt = fix_param->seq_no; + + /*call HDD callback*/ + if (NULL != wma->hddTxFailCb) + { + wma->hddTxFailCb(peer_mac, tx_fail_cnt); + } + else + { + WMA_LOGE("%s: HDD callback is %p", __func__, wma->hddTxFailCb); + } + + return 0; +} + /* function : wma_scan_completion_timeout * Description : * Args : @@ -29192,6 +29888,37 @@ VOS_STATUS wma_start(v_VOID_t *vos_ctx) goto end; #endif + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_RMC)) + { + + WMA_LOGD("FW supports cesium network, registering event handlers"); + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_INFO_EVENTID, + wma_ibss_peer_info_event_handler); + if (status) + { + WMA_LOGE("Failed to register ibss peer info event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_TX_FAIL_CNT_THR_EVENTID, + wma_fast_tx_fail_event_handler); + if (status) + { + WMA_LOGE("Failed to register peer fast tx failure event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + } + else + { + WMA_LOGE("Target does not support cesium network"); + } + vos_status = wma_tx_attach(wma_handle); if(vos_status != VOS_STATUS_SUCCESS) { WMA_LOGP("%s: Failed to register tx management", __func__); @@ -29560,6 +30287,10 @@ VOS_STATUS wma_close(v_VOID_t *vos_ctx) vos_event_destroy(&wma_handle->wow_tx_complete); vos_event_destroy(&wma_handle->runtime_suspend); vos_event_destroy(&wma_handle->recovery_event); + + /* Destroy Tx Frame Complete event */ + vos_event_destroy(&wma_handle->tx_frm_download_comp_event); + wma_cleanup_vdev_resp(wma_handle); for(idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { adf_os_mem_free_consistent( @@ -29918,6 +30649,8 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) hdd_tgt_cfg.lpss_support = wma_handle->lpss_support; #endif hdd_tgt_cfg.ap_arpns_support = wma_handle->ap_arpns_support; + hdd_tgt_cfg.fine_time_measurement_cap = + wma_handle->fine_time_measurement_cap; wma_handle->tgt_cfg_update_cb(hdd_ctx, &hdd_tgt_cfg); } static wmi_buf_t wma_setup_wmi_init_msg(tp_wma_handle wma_handle, @@ -29964,7 +30697,7 @@ static wmi_buf_t wma_setup_wmi_init_msg(tp_wma_handle wma_handle, /* allocate memory requested by FW */ if (ev->num_mem_reqs > WMI_MAX_MEM_REQS) { VOS_ASSERT(0); - adf_nbuf_free(buf); + wmi_buf_free(buf); return NULL; } @@ -30077,6 +30810,8 @@ v_VOID_t wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) wma_handle->target_fw_version = ev->fw_build_vers; + wma_handle->fine_time_measurement_cap = ev->wmi_fw_sub_feat_caps; + WMA_LOGD(FL("FW fine time meas cap: 0x%x"), ev->wmi_fw_sub_feat_caps); WMA_LOGE("%s: Firmware build version : %08x", __func__, ev->fw_build_vers); @@ -30303,7 +31038,7 @@ int wma_set_peer_param(void *wma_ctx, u_int8_t *peer_addr, u_int32_t param_id, WMI_PEER_SET_PARAM_CMDID); if (err) { WMA_LOGE("Failed to send set_param cmd"); - adf_os_mem_free(buf); + wmi_buf_free(buf); return -EIO; } @@ -30952,7 +31687,7 @@ int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) vos_event_reset(&wma_handle->target_suspend); if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len, WMI_PDEV_SUSPEND_CMDID)) { - adf_nbuf_free(wmibuf); + wmi_buf_free(wmibuf); return -1; } @@ -31533,7 +32268,7 @@ void wma_send_regdomain_info(u_int32_t reg_dmn, u_int16_t regdmn2G, WMI_PDEV_SET_REGDOMAIN_CMDID)) { WMA_LOGP("%s: Failed to send pdev set regdomain command", __func__); - adf_nbuf_free(buf); + wmi_buf_free(buf); } if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) || @@ -31763,7 +32498,7 @@ static int wma_set_tdls_offchan_mode(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_TDLS_SET_OFFCHAN_MODE_CMDID)) { WMA_LOGP("%s: failed to send tdls off chan command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); ret = -EIO; } @@ -31869,7 +32604,7 @@ static int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_TDLS_SET_STATE_CMDID)) { WMA_LOGP("%s: failed to send tdls set state command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); ret = -EIO; goto end_fw_tdls_state; } @@ -32063,7 +32798,7 @@ static int wma_update_tdls_peer_state(WMA_HANDLE handle, WMI_TDLS_PEER_UPDATE_CMDID)) { WMA_LOGE("%s: failed to send tdls peer update state command", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); ret = -EIO; goto end_tdls_peer_state; } @@ -32848,7 +33583,7 @@ void wma_process_roam_synch_complete(WMA_HANDLE handle, if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_ROAM_SYNCH_COMPLETE)) { WMA_LOGP("%s: failed to send roam synch confirmation", __func__); - adf_nbuf_free(wmi_buf); + wmi_buf_free(wmi_buf); return; } return; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h index 04abb6401340..dc9737d21390 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -533,6 +533,7 @@ struct wma_txrx_node { tANI_U8 vht_capable; tANI_U8 ht_capable; A_UINT32 mhz; /* channel frequency in KHZ */ + bool vdev_active; v_BOOL_t vdev_up; u_int64_t tsfadjust; void *addBssStaContext; @@ -574,6 +575,8 @@ struct wma_txrx_node { uint8_t nss_5g; uint8_t wep_default_key_idx; + bool is_vdev_valid; + }; #if defined(QCA_WIFI_FTM) @@ -762,6 +765,9 @@ typedef struct wma_handle { /*DFS umac interface information*/ struct ieee80211com *dfs_ic; + + txFailIndCallback hddTxFailCb; + #ifdef FEATURE_WLAN_SCAN_PNO vos_wake_lock_t pno_wake_lock; #endif @@ -802,6 +808,10 @@ typedef struct wma_handle { u_int8_t staModDtim; u_int8_t staDynamicDtim; + u_int8_t enable_mhf_offload; + /* timestamp when last entries where set */ + v_TIME_t last_mhf_entries_timestamp; + int32_t dfs_pri_multiplier; u_int32_t hw_bd_id; @@ -841,6 +851,7 @@ typedef struct wma_handle { uint16_t max_mgmt_tx_fail_count; struct wma_runtime_pm_context runtime_context; + uint32_t fine_time_measurement_cap; }t_wma_handle, *tp_wma_handle; struct wma_target_cap { diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c index 7bbd217a47b4..8e62ca2fb5df 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c @@ -665,6 +665,77 @@ inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle) } #endif +/** + * wmi_set_htc_tx_tag() - set HTC TX tag for WMI commands + * @wmi_handle: WMI handle + * @buf: WMI buffer + * @cmd_id: WMI command Id + * + * Return htc_tx_tag + */ +static uint16_t wmi_set_htc_tx_tag(wmi_unified_t wmi_handle, + wmi_buf_t buf, + WMI_CMD_ID cmd_id) +{ + uint16_t htc_tx_tag = 0; + uint16_t cur_tx_tag = 0; + wmi_vdev_set_param_cmd_fixed_param *set_cmd; + wmi_sta_powersave_param_cmd_fixed_param *ps_cmd; + + switch(cmd_id) { + case WMI_WOW_ENABLE_CMDID: + case WMI_PDEV_SUSPEND_CMDID: + case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID: + case WMI_WOW_ADD_WAKE_PATTERN_CMDID: + case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID: + case WMI_PDEV_RESUME_CMDID: + case WMI_WOW_DEL_WAKE_PATTERN_CMDID: +#ifdef FEATURE_WLAN_D0WOW + case WMI_D0_WOW_ENABLE_DISABLE_CMDID: +#endif + htc_tx_tag = HTC_TX_PACKET_TAG_AUTO_PM; + case WMI_FORCE_FW_HANG_CMDID: + if (wmi_handle->tag_crash_inject) { + htc_tx_tag = HTC_TX_PACKET_TAG_AUTO_PM; + wmi_handle->tag_crash_inject = false; + } + default: + break; + } + + if(!adf_os_atomic_read(&wmi_handle->is_target_suspended)) + cur_tx_tag = HTC_TX_PACKET_TAG_AUTO_PM; + + if(cmd_id == WMI_VDEV_SET_PARAM_CMDID) + { + set_cmd = (wmi_vdev_set_param_cmd_fixed_param *) + wmi_buf_data(buf); + + switch(set_cmd->param_id) { + case WMI_VDEV_PARAM_LISTEN_INTERVAL: + case WMI_VDEV_PARAM_DTIM_POLICY: + htc_tx_tag = cur_tx_tag; + default: + break; + } + } + + if(cmd_id == WMI_STA_POWERSAVE_PARAM_CMDID) + { + ps_cmd = (wmi_sta_powersave_param_cmd_fixed_param *) + wmi_buf_data(buf); + + switch(ps_cmd->param) { + case WMI_STA_PS_ENABLE_QPOWER: + htc_tx_tag = cur_tx_tag; + default: + break; + } + } + + return htc_tx_tag; +} + /* WMI command API */ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, WMI_CMD_ID cmd_id) @@ -695,26 +766,8 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, goto dont_tag; skip_suspend_check: - switch(cmd_id) { - case WMI_WOW_ENABLE_CMDID: - case WMI_PDEV_SUSPEND_CMDID: - case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID: - case WMI_WOW_ADD_WAKE_PATTERN_CMDID: - case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID: - case WMI_PDEV_RESUME_CMDID: - case WMI_WOW_DEL_WAKE_PATTERN_CMDID: -#ifdef FEATURE_WLAN_D0WOW - case WMI_D0_WOW_ENABLE_DISABLE_CMDID: -#endif - htc_tag = HTC_TX_PACKET_TAG_AUTO_PM; - case WMI_FORCE_FW_HANG_CMDID: - if (wmi_handle->tag_crash_inject) { - htc_tag = HTC_TX_PACKET_TAG_AUTO_PM; - wmi_handle->tag_crash_inject = false; - } - default: - break; - } + htc_tag = (A_UINT16) wmi_set_htc_tx_tag(wmi_handle, + buf, cmd_id); dont_tag: /* Do sanity check on the TLV parameter structure */ diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h index 86635069c0f6..dca9e4bbef6b 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -499,9 +499,7 @@ typedef enum eCSR_ROAM_FT_RESPONSE, #endif eCSR_ROAM_FT_START, - eCSR_ROAM_INDICATE_MGMT_FRAME, eCSR_ROAM_REMAIN_CHAN_READY, - eCSR_ROAM_SEND_ACTION_CNF, //this mean error happens before association_start or roaming_start is called. eCSR_ROAM_SESSION_OPENED, eCSR_ROAM_FT_REASSOC_FAILED, @@ -525,6 +523,8 @@ typedef enum eCSR_ROAM_UNPROT_MGMT_FRAME_IND, #endif + eCSR_ROAM_IBSS_PEER_INFO_COMPLETE, + #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) eCSR_ROAM_TSM_IE_IND, eCSR_ROAM_CCKM_PREAUTH_NOTIFY, @@ -631,6 +631,9 @@ typedef enum eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED, #endif + eCSR_ROAM_RESULT_IBSS_PEER_INFO_SUCCESS, + eCSR_ROAM_RESULT_IBSS_PEER_INFO_FAILED, + eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND, eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS, eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE, @@ -1563,6 +1566,7 @@ typedef struct tagCsrLinkEstablishParams tSirMacAddr peerMac; tANI_U8 uapsdQueues; tANI_U8 maxSp; + uint8_t qos; tANI_U8 isBufSta; tANI_U8 isOffChannelSupported; tANI_U8 isResponder; diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h index 80c7af56f884..70f21ffe1ca5 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h @@ -61,7 +61,8 @@ typedef struct tagOemDataReq { tANI_U8 sessionId; - tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tOemDataReq, tOemDataReqConfig; /************************************************************************************************************* diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h index ab4b59137900..fd5ac882ff99 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h @@ -111,6 +111,18 @@ typedef enum eSmeState #define SME_IS_START(pMac) (SME_STATE_STOP != (pMac)->sme.state) #define SME_IS_READY(pMac) (SME_STATE_READY == (pMac)->sme.state) +/* HDD Callback function */ +typedef void(*pIbssPeerInfoCb)(void *pUserData, + tSirPeerInfoRspParams *infoParam); + +/* Peer info */ +typedef struct tagSmePeerInfoHddCbkInfo +{ + void *pUserData; + pIbssPeerInfoCb peerInfoCbk; +}tSmePeerInfoHddCbkInfo; + + typedef struct sStatsExtEvent { tANI_U32 vdev_id; tANI_U32 event_data_len; @@ -153,6 +165,7 @@ typedef struct tagSmeStruct tDblLinkList smeScanCmdPendingList; //active scan command list tDblLinkList smeScanCmdActiveList; + tSmePeerInfoHddCbkInfo peerInfoParams; #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR vos_event_wlan_status_payload_type eventPayload; #endif diff --git a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h index cd46e0e7de23..3ee45c6a08c4 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h @@ -1752,6 +1752,28 @@ eHalStatus sme_GenericChangeCountryCode( tHalHandle hHal, tANI_U8 *pCountry, v_REGDOMAIN_t reg_domain); +/* --------------------------------------------------------------------------- + + \fn sme_TXFailMonitorStartStopInd + + \brief Indicate FW about TX Fail Monitor Indication` + + \param hHal - The handle returned by macOpen. + + \param tx_fail_count number of failures after which the firmware sends + an indication to host + + \param txFailIndCallback function to be called after receiving TX Fail + indication + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_TXFailMonitorStartStopInd(tHalHandle hHal, + tANI_U8 tx_fail_count, + void * txFailIndCallback); + /* --------------------------------------------------------------------------- \fn sme_DHCPStartInd @@ -3578,6 +3600,33 @@ eHalStatus sme_DelPeriodicTxPtrn(tHalHandle hHal, tSirDelPeriodicTxPtrn void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, tANI_U8 nNumP2PChan); +/** + * sme_enable_rmc() - enable RMC + * @hHal: handle + * @sessionId: session id + * + * Return: eHalStatus + */ +eHalStatus sme_enable_rmc(tHalHandle hHal, tANI_U32 sessionId); + +/** + * sme_disable_rmc() - disable RMC + * @hHal: handle + * @sessionId: session id + * + * Return: eHalStatus + */ +eHalStatus sme_disable_rmc(tHalHandle hHal, tANI_U32 sessionId); + +/* --------------------------------------------------------------------------- + \fn sme_SendRmcActionPeriod + \brief Used to send RMC action period param to fw + \param hHal + \param sessionId + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SendRmcActionPeriod(tHalHandle hHal, tANI_U32 sessionId); + /* --------------------------------------------------------------------------- \fn sme_SendRateUpdateInd \brief API to Update rate @@ -3587,6 +3636,28 @@ void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, ---------------------------------------------------------------------------*/ eHalStatus sme_SendRateUpdateInd(tHalHandle hHal, tSirRateUpdateInd *rateUpdateParams); +/* --------------------------------------------------------------------------- + \fn sme_GetIBSSPeerInfo + \brief Used to disable RMC + setting will not persist over reboots + \param hHal + \param ibssPeerInfoReq multicast Group IP address + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_RequestIBSSPeerInfo(tHalHandle hHal, void *pUserData, + pIbssPeerInfoCb peerInfoCbk, + tANI_BOOLEAN allPeerInfoReqd, + tANI_U8 staIdx); + +/* --------------------------------------------------------------------------- + \fn sme_SendCesiumEnableInd + \brief Used to send proprietary cesium enable indication to fw + \param hHal + \param sessionId + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SendCesiumEnableInd(tHalHandle hHal, tANI_U32 sessionId); + /* * sme API to trigger fast BSS roam to a given BSSID independent of RSSI * triggers @@ -4016,6 +4087,9 @@ eHalStatus sme_ExtScanRegisterCallback (tHalHandle hHal, #endif /* FEATURE_WLAN_EXTSCAN */ +VOS_STATUS sme_set_beacon_filter(uint32_t vdev_id, uint32_t *ie_map); +VOS_STATUS sme_unset_beacon_filter(uint32_t vdev_id); + #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD /* --------------------------------------------------------------------------- \fn sme_abortRoamScan @@ -4335,6 +4409,8 @@ sme_set_tsf_gpio(tHalHandle hHal, uint32_t pinvalue) #endif bool smeNeighborMiddleOfRoaming(tHalHandle hHal, tANI_U8 sessionId); +eHalStatus sme_register_mgmt_frame_ind_callback(tHalHandle hal, + sir_mgmt_frame_ind_callback callback); eHalStatus sme_update_nss(tHalHandle h_hal, uint8_t nss); void sme_enable_phy_error_logs(tHalHandle hal, bool enable_log); @@ -4403,4 +4479,11 @@ eHalStatus sme_update_mimo_power_save(tHalHandle hHal, bool sme_is_sta_smps_allowed(tHalHandle hHal, uint8_t session_id); +void sme_update_fine_time_measurement_capab(tHalHandle hal, uint32_t val); + +eHalStatus sme_delete_all_tdls_peers(tHalHandle hal, uint8_t session_id); + +VOS_STATUS sme_is_session_valid(tHalHandle hal_handle, uint8_t session_id); +eHalStatus sme_register_p2p_ack_ind_callback(tHalHandle hal, + sir_p2p_ack_ind_callback callback); #endif //#if !defined( __SME_API_H ) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c index cbc3acf3a404..3251b13d6d3e 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c @@ -489,6 +489,9 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) for (i = 0; i < pScan->base20MHzChannels.numChannels; i++) { + if (vos_is_dsrc_channel(vos_chan_to_freq( + pScan->base20MHzChannels.channelList[i]))) + continue; if (pScan->fcc_constraint) { if (pScan->base20MHzChannels.channelList[i] == 12) continue; @@ -1748,18 +1751,9 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa { pMac->roam.configParam.nPassiveMinChnTimeConc = pParam->nPassiveMinChnTimeConc; } - if (pParam->nRestTimeConc) - { - pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc; - } - if (pParam->min_rest_time_conc) - { - pMac->roam.configParam.min_rest_time_conc = pParam->min_rest_time_conc; - } - if (pParam->idle_time_conc) - { - pMac->roam.configParam.idle_time_conc = pParam->idle_time_conc; - } + pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc; + pMac->roam.configParam.min_rest_time_conc = pParam->min_rest_time_conc; + pMac->roam.configParam.idle_time_conc = pParam->idle_time_conc; if (pParam->nNumStaChanCombinedConc) { pMac->roam.configParam.nNumStaChanCombinedConc = pParam->nNumStaChanCombinedConc; @@ -2133,6 +2127,8 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pMac->roam.configParam.sendDeauthBeforeCon; pParam->first_scan_bucket_threshold = pMac->first_scan_bucket_threshold; + pParam->enableHtSmps = pMac->roam.configParam.enableHtSmps; + pParam->htSmps = pMac->roam.configParam.htSmps; status = eHAL_STATUS_SUCCESS; } return (status); @@ -8557,12 +8553,20 @@ static void csrRoamRoamingStateReassocRspProcessor( tpAniSirGlobal pMac, tpSirSm &pMac->roam.neighborRoamInfo[pSmeJoinRsp->sessionId]; tCsrRoamInfo roamInfo; tANI_U32 roamId = 0; + tCsrRoamSession *csr_session; if ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode ) { VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, FL("CSR SmeReassocReq Successful")); result = eCsrReassocSuccess; + csr_session = CSR_GET_SESSION(pMac, pSmeJoinRsp->sessionId); + if(NULL != csr_session) { + csr_session->supported_nss_1x1 = pSmeJoinRsp->supported_nss_1x1; + smsLog(pMac, LOG1, FL("SME session supported nss: %d"), + csr_session->supported_nss_1x1); + } + /* Defeaturize this part later if needed */ #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING /* @@ -9013,6 +9017,16 @@ void csrRoamingStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) case eWNI_SME_DEAUTH_RSP: // or the Deauthentication response message... if ( CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ( pMac, pSmeRsp->sessionId ) ) { + /* + * Lets remove eSmeCommandWmStatusChange command from pending + * list as SME got DEAUTH_RSP msg from PE which means that PE + * already has deleted the session and there is no need to + * send Diassoc/Deauth CNF mesg to PE + */ + csrRemoveCmdWithSessionIdFromPendingList(pMac, + pSmeRsp->sessionId, + &pMac->sme.smeScanCmdPendingList, + eSmeCommandWmStatusChange); csrRoamRoamingStateDeauthRspProcessor( pMac, (tSirSmeDeauthRsp *)pSmeRsp ); } break; @@ -11832,6 +11846,13 @@ static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRo cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; } + if (IS_24G_CH(operationChn) && + (false == pMac->roam.configParam.enableVhtFor24GHz) && + (eCSR_CFG_DOT11_MODE_11AC == cfgDot11Mode || + eCSR_CFG_DOT11_MODE_11AC_ONLY == cfgDot11Mode)) { + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + } + /* 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]) || @@ -11890,10 +11911,25 @@ eHalStatus csrRoamIssueStopBss( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoa //pNumChan is a caller allocated space with the sizeof pChannels eHalStatus csrGetCfgValidChannels(tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U32 *pNumChan) { + uint8_t num_chan_temp = 0; + int i; + eHalStatus status; - return (ccmCfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + status = ccmCfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, (tANI_U8 *)pChannels, - pNumChan)); + pNumChan); + if (status != eHAL_STATUS_SUCCESS) + return status; + + for (i = 0; i < *pNumChan; i++) { + if (!vos_is_dsrc_channel(vos_chan_to_freq(pChannels[i]))) { + pChannels[num_chan_temp] = pChannels[i]; + num_chan_temp++; + } + } + + *pNumChan = num_chan_temp; + return status; } tPowerdBm csrGetCfgMaxTxPower (tpAniSirGlobal pMac, tANI_U8 channel) @@ -16680,6 +16716,8 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste pTlStats = (WLANTL_TRANSFER_STA_TYPE *)vos_mem_malloc(sizeof(WLANTL_TRANSFER_STA_TYPE)); if (NULL != pTlStats) { + vos_mem_set(pTlStats, sizeof(*pTlStats), 0); + //req TL for class D stats if(WLANTL_GetStatistics(pMac->roam.gVosContext, pTlStats, staId)) { @@ -16741,6 +16779,8 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste pTlStats = (WLANTL_TRANSFER_STA_TYPE *)vos_mem_malloc(sizeof(WLANTL_TRANSFER_STA_TYPE)); if (NULL != pTlStats) { + vos_mem_set(pTlStats, sizeof(*pTlStats), 0); + //req TL for class D stats if(!VOS_IS_STATUS_SUCCESS(WLANTL_GetStatistics(pMac->roam.gVosContext, pTlStats, staId))) { @@ -17094,36 +17134,25 @@ bool csr_is_RSO_cmd_allowed(tpAniSirGlobal mac_ctx, uint8_t command, return ret_val; } -void csr_roam_send_restart_cmd(tpAniSirGlobal pMac, tANI_U8 session_id, - tANI_U8 command, tANI_U8 reason) +VOS_STATUS csr_roam_send_rso_cmd(tpAniSirGlobal pMac, tANI_U8 session_id, + tSirRoamOffloadScanReq *pRequestBuf) { - struct sir_sme_roam_restart_req *msg; eHalStatus status; - msg = vos_mem_malloc(sizeof(struct sir_sme_roam_restart_req)); - if (msg == NULL) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - FL("Memory allocation failed")); - VOS_ASSERT(msg); - return; - } - vos_mem_set(msg, sizeof(struct sir_sme_roam_restart_req), 0); - msg->message_type = eWNI_SME_ROAM_RESTART_REQ; - msg->length = sizeof(struct sir_sme_roam_restart_req); - msg->sme_session_id = session_id; - msg->command = command; - msg->reason = reason; - status = palSendMBMessage(pMac->hHdd, msg); + pRequestBuf->message_type = eWNI_SME_ROAM_SCAN_OFFLOAD_REQ; + pRequestBuf->length = sizeof(*pRequestBuf); + status = palSendMBMessage(pMac->hHdd, pRequestBuf); + if (eHAL_STATUS_FAILURE == status) { VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - FL("Sending msg eWNI_SME_ROAM_RESTART_REQ failed")); - vos_mem_free(msg); + FL("Send RSO from CSR failed")); + return VOS_STATUS_E_FAILURE; } + return VOS_STATUS_SUCCESS; } eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 sessionId, tANI_U8 command, tANI_U8 reason) { - vos_msg_t msg; tSirRoamOffloadScanReq *pRequestBuf; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; @@ -17172,10 +17201,6 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 sessionId, command, pNeighborRoamInfo->lastSentCmd); return eHAL_STATUS_FAILURE; } - if (ROAM_SCAN_OFFLOAD_RESTART == command) { - csr_roam_send_restart_cmd(pMac, sessionId, command, reason); - goto cmd_sent; - } if ((VOS_TRUE == bRoamScanOffloadStarted) && (ROAM_SCAN_OFFLOAD_START == command)) { smsLog( pMac, LOGE,"Roam Scan Offload is already started"); @@ -17551,13 +17576,11 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 sessionId, MAC_ADDR_ARRAY(roam_params_dst->bssid_favored[i]), roam_params_dst->bssid_favored_factor[i]); } - msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; - msg.reserved = 0; - msg.bodyptr = pRequestBuf; - if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) + + if (!VOS_IS_STATUS_SUCCESS(csr_roam_send_rso_cmd(pMac, + sessionId, pRequestBuf))) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_ROAM_SCAN_OFFLOAD_REQ message to WDA", __func__); - vos_mem_free(pRequestBuf); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_ROAM_SCAN_OFFLOAD_REQ message to PE", __func__); return eHAL_STATUS_FAILURE; } else @@ -17567,7 +17590,6 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 sessionId, else if (ROAM_SCAN_OFFLOAD_STOP == command) bRoamScanOffloadStarted = VOS_FALSE; } -cmd_sent: /* update the last sent cmd */ pNeighborRoamInfo->lastSentCmd = command; @@ -18867,10 +18889,11 @@ VOS_STATUS csrRoamReadTSF(tpAniSirGlobal pMac, tANI_U8 *pTimestamp, tANI_U8 sessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; - tCsrNeighborRoamBSSInfo handoffNode; + tCsrNeighborRoamBSSInfo handoffNode = {{0}}; tANI_U32 timer_diff = 0; tANI_U32 timeStamp[2]; tpSirBssDescription pBssDescription = NULL; + csrNeighborRoamGetHandoffAPInfo(pMac, &handoffNode, sessionId); pBssDescription = handoffNode.pBssDescription; // Get the time diff in milli seconds @@ -18916,6 +18939,12 @@ csrRoamChannelChangeReq(tpAniSirGlobal pMac, tCsrBssid bssid, pMsg->dot11mode = csrTranslateToWNICfgDot11Mode(pMac,pMac->roam.configParam.uCfgDot11Mode); + if (IS_24G_CH(pMsg->targetChannel) && + (false == pMac->roam.configParam.enableVhtFor24GHz) && + (WNI_CFG_DOT11_MODE_11AC == pMsg->dot11mode || + WNI_CFG_DOT11_MODE_11AC_ONLY == pMsg->dot11mode)) { + pMsg->dot11mode = WNI_CFG_DOT11_MODE_11N; + } vos_mem_copy(pMsg->bssid, bssid, VOS_MAC_ADDR_SIZE); vos_mem_copy((void*)&pMsg->operational_rateset, (void*)¶m.operationalRateSet, sizeof(tSirMacRateSet)); @@ -19008,6 +19037,7 @@ csrRoamModifyAddIEs(tpAniSirGlobal pMac, pModifyAddIEInd->modifyIE.ieIDLen = pModifyIE->ieIDLen; pModifyAddIEInd->modifyIE.pIEBuffer = pLocalBuffer; pModifyAddIEInd->modifyIE.ieBufferlength = pModifyIE->ieBufferlength; + pModifyAddIEInd->modifyIE.oui_length = pModifyIE->oui_length; pModifyAddIEInd->updateType = updateType; diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c index e983f9e125ed..ebb9d7d24a83 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -6029,7 +6029,8 @@ eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg) if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) || (pNeighborRoamInfo->uOsRequestedHandoff)) { - smsLog(pMac, LOGE, FL("Received in not CONNECTED state OR uOsRequestedHandoff is set. Ignore it")); + smsLog(pMac, LOGE, FL("Received in not CONNECTED state(%d) or uOsRequestedHandoff(%d) is not set. Ignore it "), + pNeighborRoamInfo->neighborRoamState, pNeighborRoamInfo->uOsRequestedHandoff); status = eHAL_STATUS_FAILURE; } else diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c index b0668b3357c6..d288d91577a9 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -455,9 +455,7 @@ get_eRoamCmdStatus_str(eRoamCmdStatus val) CASE_RETURN_STR(eCSR_ROAM_FT_RESPONSE); #endif CASE_RETURN_STR(eCSR_ROAM_FT_START); - CASE_RETURN_STR(eCSR_ROAM_INDICATE_MGMT_FRAME); CASE_RETURN_STR(eCSR_ROAM_REMAIN_CHAN_READY); - CASE_RETURN_STR(eCSR_ROAM_SEND_ACTION_CNF); CASE_RETURN_STR(eCSR_ROAM_SESSION_OPENED); CASE_RETURN_STR(eCSR_ROAM_FT_REASSOC_FAILED); #ifdef FEATURE_WLAN_LFR diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c b/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c index d0d6df07cc79..a8a4534477ed 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c @@ -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. * @@ -109,8 +109,11 @@ void oemData_ReleaseOemDataReqCommand(tpAniSirGlobal pMac, tSmeCmd *pOemDataCmd, //First take this command out of the active list if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, &pOemDataCmd->Link, LL_ACCESS_LOCK)) { - vos_mem_set(&(pOemDataCmd->u.oemDataCmd), sizeof(tOemDataCmd), 0); - + if (pOemDataCmd->u.oemDataCmd.oemDataReq.data) { + vos_mem_free(pOemDataCmd->u.oemDataCmd.oemDataReq.data); + pOemDataCmd->u.oemDataCmd.oemDataReq.data = NULL; + } + vos_mem_zero(&(pOemDataCmd->u.oemDataCmd), sizeof(tOemDataCmd)); /* Now put this command back on the available command list */ smeReleaseCommand(pMac, pOemDataCmd); } @@ -135,6 +138,7 @@ eHalStatus oemData_OemDataReq(tHalHandle hHal, eHalStatus status = eHAL_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); tSmeCmd *pOemDataCmd = NULL; + tOemDataReq *cmd_req; do { @@ -144,13 +148,8 @@ eHalStatus oemData_OemDataReq(tHalHandle hHal, break; } - pMac->oemData.oemDataReqConfig.sessionId = sessionId; pMac->oemData.oemDataReqID = *(pOemDataReqID); - vos_mem_copy((v_VOID_t*)(pMac->oemData.oemDataReqConfig.oemDataReq), - (v_VOID_t*)(oemDataReqConfig->oemDataReq), - OEM_DATA_REQ_SIZE); - pMac->oemData.oemDataReqActive = eANI_BOOLEAN_FALSE; pOemDataCmd = smeGetCommandBuffer(pMac); @@ -161,11 +160,20 @@ eHalStatus oemData_OemDataReq(tHalHandle hHal, pOemDataCmd->command = eSmeCommandOemDataReq; pOemDataCmd->u.oemDataCmd.oemDataReqID = pMac->oemData.oemDataReqID; - //set the oem data request - pOemDataCmd->u.oemDataCmd.oemDataReq.sessionId = pMac->oemData.oemDataReqConfig.sessionId; - vos_mem_copy((v_VOID_t*)(pOemDataCmd->u.oemDataCmd.oemDataReq.oemDataReq), - (v_VOID_t*)(pMac->oemData.oemDataReqConfig.oemDataReq), - OEM_DATA_REQ_SIZE); + cmd_req = &(pOemDataCmd->u.oemDataCmd.oemDataReq); + /* set the oem data request */ + cmd_req->sessionId = sessionId; + cmd_req->data_len = oemDataReqConfig->data_len; + cmd_req->data = vos_mem_malloc(cmd_req->data_len); + + if (!cmd_req->data) { + smsLog(pMac, LOGE, FL("memory alloc failed")); + status = eHAL_STATUS_FAILED_ALLOC; + break; + } + + vos_mem_copy(cmd_req->data, oemDataReqConfig->data, + cmd_req->data_len); } else { @@ -201,30 +209,34 @@ eHalStatus oemData_SendMBOemDataReq(tpAniSirGlobal pMac, tOemDataReq *pOemDataRe eHalStatus status = eHAL_STATUS_SUCCESS; tSirOemDataReq* pMsg; tANI_U16 msgLen; - tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pOemDataReq->sessionId ); + tCsrRoamSession *pSession; smsLog(pMac, LOGW, "OEM_DATA: entering Function %s", __func__); - msgLen = (tANI_U16)(sizeof(tSirOemDataReq)); + if (!pOemDataReq) { + smsLog(pMac, LOGE, FL("oem data req is NULL")); + return eHAL_STATUS_INVALID_PARAMETER; + } - pMsg = vos_mem_malloc(msgLen); - if ( NULL == pMsg ) - status = eHAL_STATUS_FAILURE; - else - status = eHAL_STATUS_SUCCESS; - if(HAL_STATUS_SUCCESS(status)) - { - vos_mem_set(pMsg, msgLen, 0); - pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_OEM_DATA_REQ); - pMsg->messageLen = pal_cpu_to_be16(msgLen); - vos_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr, sizeof(tSirMacAddr) ); - vos_mem_copy(pMsg->oemDataReq, pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE); - smsLog(pMac, LOGW, "OEM_DATA: sending message to pe%s", __func__); - status = palSendMBMessage(pMac->hHdd, pMsg); + pSession = CSR_GET_SESSION(pMac, pOemDataReq->sessionId); + pMsg = vos_mem_malloc(sizeof(*pMsg)); + if (NULL == pMsg) { + smsLog(pMac, LOGE, "Memory Allocation failed. %s", __func__); + return eHAL_STATUS_FAILURE; } - smsLog(pMac, LOGW, "OEM_DATA: exiting Function %s", __func__); + msgLen = (uint16_t) (sizeof(*pMsg) + pOemDataReq->data_len); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_OEM_DATA_REQ); + pMsg->messageLen = pal_cpu_to_be16(msgLen); + vos_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr, sizeof(tSirMacAddr) ); + pMsg->data_len = pOemDataReq->data_len; + /* Incoming buffer ptr saved, set to null to avoid free by caller */ + pMsg->data = pOemDataReq->data; + pOemDataReq->data = NULL; + smsLog(pMac, LOGW, "OEM_DATA: sending message to pe%s", __func__); + status = palSendMBMessage(pMac->hHdd, pMsg); + smsLog(pMac, LOGW, "OEM_DATA: exiting Function %s", __func__); return status; } @@ -282,6 +294,7 @@ eHalStatus sme_HandleOemDataRsp(tHalHandle hHal, tANI_U8* pMsg) tListElem *pEntry = NULL; tSmeCmd *pCommand = NULL; tSirOemDataRsp* pOemDataRsp = NULL; + tOemDataReq *req; tANI_U32 *msgSubType; pMac = PMAC_STRUCT(hHal); @@ -314,6 +327,8 @@ eHalStatus sme_HandleOemDataRsp(tHalHandle hHal, tANI_U8* pMsg) { vos_mem_set(&(pCommand->u.oemDataCmd), sizeof(tOemDataCmd), 0); + req = &(pCommand->u.oemDataCmd.oemDataReq); + vos_mem_free(req->data); smeReleaseCommand(pMac, pCommand); } } diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c b/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c index cd26f5002603..f30075a217ac 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c @@ -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. * @@ -186,49 +186,6 @@ eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg) return status; } - -/*------------------------------------------------------------------ - * - * Handle the Mgmt frm ind from LIM and forward to HDD. - * - *------------------------------------------------------------------*/ - -eHalStatus sme_mgmtFrmInd( tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - eHalStatus status = eHAL_STATUS_SUCCESS; - tCsrRoamInfo pRoamInfo = {0}; - tANI_U8 i = 0; - tANI_U32 SessionId = pSmeMgmtFrm->sessionId; - - pRoamInfo.nFrameLength = pSmeMgmtFrm->mesgLen - sizeof(tSirSmeMgmtFrameInd); - pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; - pRoamInfo.frameType = pSmeMgmtFrm->frameType; - pRoamInfo.rxChan = pSmeMgmtFrm->rxChan; - pRoamInfo.rxRssi = pSmeMgmtFrm->rxRssi; - if(CSR_IS_SESSION_ANY(SessionId)) - { - for(i = 0; i < CSR_ROAM_SESSION_MAX; i++) - { - if(CSR_IS_SESSION_VALID(pMac, i)) - { - SessionId = i; - break; - } - } - } - - if (i == CSR_ROAM_SESSION_MAX) { - smsLog(pMac, LOGE, FL("No valid sessions found.")); - return eHAL_STATUS_FAILURE; - } - /* forward the mgmt frame to HDD */ - csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_INDICATE_MGMT_FRAME, 0); - - return status; -} - - /*------------------------------------------------------------------ * * Handle the remain on channel ready indication from PE @@ -264,26 +221,6 @@ eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg) return status; } - -eHalStatus sme_sendActionCnf( tHalHandle hHal, tANI_U8* pMsg) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - eHalStatus status = eHAL_STATUS_SUCCESS; - tCsrRoamInfo RoamInfo; - tSirSmeRsp* pSmeRsp = (tSirSmeRsp*)pMsg; - - /* forward the indication to HDD */ - //RoamInfo can be passed as NULL....todo - csrRoamCallCallback(pMac, pSmeRsp->sessionId, &RoamInfo, 0, - eCSR_ROAM_SEND_ACTION_CNF, - (pSmeRsp->statusCode == eSIR_SME_SUCCESS) ? 0: - eCSR_ROAM_RESULT_SEND_ACTION_FAIL); - return status; -} - - - - eHalStatus sme_p2pOpen( tHalHandle hHal ) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c index 9652bde3f5a3..1d10b10e6c19 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -531,6 +531,7 @@ static eHalStatus sme_RrmSendScanResult( tpAniSirGlobal pMac, #endif } + smsLog(pMac, LOG1, FL("RRM Measurement Done %d"), measurementDone); if (NULL == pResult) { /* @@ -590,6 +591,8 @@ static eHalStatus sme_RrmSendScanResult( tpAniSirGlobal pMac, while (pScanResult) { pNextResult = sme_ScanResultGetNext(pMac, pResult); + smsLog(pMac, LOG1, "Scan res timer:%lu, rrm scan timer:%lu", + pScanResult->timer, RRM_scan_timer); if(pScanResult->timer >= RRM_scan_timer) { pScanResultsArr[counter++] = pScanResult; @@ -597,27 +600,30 @@ static eHalStatus sme_RrmSendScanResult( tpAniSirGlobal pMac, pScanResult = pNextResult; //sme_ScanResultGetNext(hHal, pResult); if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC) break; - } + } - if (counter) - { - smsLog(pMac, LOG1, " Number of BSS Desc with RRM Scan %d ", counter); + smsLog(pMac, LOG1, " Number of BSS Desc with RRM Scan %d ", counter); + /* + * The beacon report should be sent whether the counter is zero or non-zero. + * There might be a few scan results in the cache but not actually are a + * result of this scan. During that scenario, the counter will be zero. + * The report should be sent and LIM will further cleanup the RRM to + * accept the further incoming requests + * In case the counter is Zero, the pScanResultsArr will be NULL. + * The next level routine does a check for the measurementDone to determine + * whether to send a report or not. + */ + if (counter || measurementDone) { #if defined(FEATURE_WLAN_ESE_UPLOAD) - if (eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource) - { - status = sme_EseSendBeaconReqScanResults(pMac, - sessionId, - chanList[0], - pScanResultsArr, - measurementDone, - counter); - } - else -#endif /*FEATURE_WLAN_ESE_UPLOAD*/ - status = sme_RrmSendBeaconReportXmitInd( pMac, - pScanResultsArr, - measurementDone, - counter); + if (eRRM_MSG_SOURCE_ESE_UPLOAD == pSmeRrmContext->msgSource) + status = sme_EseSendBeaconReqScanResults(pMac, sessionId, + chanList[0], pScanResultsArr, + measurementDone, counter); + else +#endif + status = sme_RrmSendBeaconReportXmitInd(pMac, + pScanResultsArr, + measurementDone, counter); } sme_ScanResultPurge(pMac, pResult); diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c index 7a7cdb04ff8b..b364a303e82b 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c @@ -92,9 +92,7 @@ extern void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ); extern void csr_release_roc_req_cmd(tpAniSirGlobal mac_ctx); extern eHalStatus p2pProcessRemainOnChannelCmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn); extern eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg); -extern eHalStatus sme_mgmtFrmInd( tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm); extern eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg); -extern eHalStatus sme_sendActionCnf( tHalHandle hHal, tANI_U8* pMsg); extern eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd); static eHalStatus initSmeCmdList(tpAniSirGlobal pMac); @@ -1192,8 +1190,17 @@ tANI_BOOLEAN smeProcessCommand( tpAniSirGlobal pMac ) VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "sending TDLS Command 0x%x to PE", pCommand->command); - csrLLUnlock( &pMac->sme.smeCmdActiveList ); - status = csrTdlsProcessCmd( pMac, pCommand ); + csrLLUnlock(&pMac->sme.smeCmdActiveList); + status = csrTdlsProcessCmd(pMac, pCommand); + if (!HAL_STATUS_SUCCESS(status)) { + if (csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, + LL_ACCESS_LOCK)) { + vos_mem_zero(&pCommand->u.tdlsCmd, + sizeof(tTdlsCmd)); + csrReleaseCommand(pMac, pCommand); + } + } } break ; #endif @@ -2499,6 +2506,27 @@ static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal pMac, vos_msg_t* pMsg) { } #endif +eHalStatus sme_IbssPeerInfoResponseHandleer( tHalHandle hHal, + tpSirIbssGetPeerInfoRspParams pIbssPeerInfoParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return eHAL_STATUS_FAILURE; + } + if (pMac->sme.peerInfoParams.peerInfoCbk == NULL) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: HDD callback is null", __func__); + return eHAL_STATUS_FAILURE; + } + pMac->sme.peerInfoParams.peerInfoCbk(pMac->sme.peerInfoParams.pUserData, + &pIbssPeerInfoParams->ibssPeerInfoRspParams); + return eHAL_STATUS_SUCCESS; +} /*-------------------------------------------------------------------------- @@ -2685,28 +2713,6 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RDY_IND), nothing to process"); } break; - case eWNI_SME_MGMT_FRM_IND: - if(pMsg->bodyptr) - { - sme_mgmtFrmInd(pMac, pMsg->bodyptr); - vos_mem_free(pMsg->bodyptr); - } - else - { - smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_MGMT_FRM_IND), nothing to process"); - } - break; - case eWNI_SME_ACTION_FRAME_SEND_CNF: - if(pMsg->bodyptr) - { - status = sme_sendActionCnf(pMac, pMsg->bodyptr); - vos_mem_free(pMsg->bodyptr); - } - else - { - smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_ACTION_FRAME_SEND_CNF), nothing to process"); - } - break; case eWNI_SME_COEX_IND: if(pMsg->bodyptr) { @@ -2902,6 +2908,20 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) break; #endif /* FEATURE_WLAN_LPHB */ + case eWNI_SME_IBSS_PEER_INFO_RSP: + if (pMsg->bodyptr) + { + sme_IbssPeerInfoResponseHandleer(pMac, pMsg->bodyptr); + vos_mem_free(pMsg->bodyptr); + } + else + { + smsLog(pMac, LOGE, + "Empty rsp message for (eWNI_SME_IBSS_PEER_INFO_RSP)," + " nothing to process"); + } + break ; + case eWNI_SME_READY_TO_SUSPEND_IND: if (pMsg->bodyptr) { @@ -6608,6 +6628,62 @@ eHalStatus sme_DHCPStopInd( tHalHandle hHal, return (status); } +/*--------------------------------------------------------------------------- + + \fn sme_TXFailMonitorStopInd + + \brief API to signal the FW to start monitoring TX failures + + \return eHalStatus SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + --------------------------------------------------------------------------*/ +eHalStatus sme_TXFailMonitorStartStopInd(tHalHandle hHal, tANI_U8 tx_fail_count, + void * txFailIndCallback) +{ + eHalStatus status; + VOS_STATUS vosStatus; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tAniTXFailMonitorInd *pMsg; + + status = sme_AcquireGlobalLock(&pMac->sme); + if ( eHAL_STATUS_SUCCESS == status) + { + pMsg = (tAniTXFailMonitorInd*) + vos_mem_malloc(sizeof(tAniTXFailMonitorInd)); + if (NULL == pMsg) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to allocate memory", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + pMsg->msgType = WDA_TX_FAIL_MONITOR_IND; + pMsg->msgLen = (tANI_U16)sizeof(tAniTXFailMonitorInd); + + //tx_fail_count = 0 should disable the Monitoring in FW + pMsg->tx_fail_count = tx_fail_count; + pMsg->txFailIndCallback = txFailIndCallback; + + vosMessage.type = WDA_TX_FAIL_MONITOR_IND; + vosMessage.bodyptr = pMsg; + vosMessage.reserved = 0; + + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage ); + if ( !VOS_IS_STATUS_SUCCESS(vosStatus) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post TX Fail monitor Start MSG fail", __func__); + vos_mem_free(pMsg); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return (status); +} + /* --------------------------------------------------------------------------- \fn sme_BtcSignalBtEvent \brief API to signal Bluetooth (BT) event to the WLAN driver. Based on the @@ -7481,6 +7557,88 @@ eHalStatus sme_GetOperationChannel(tHalHandle hHal, tANI_U32 *pChannel, tANI_U8 return eHAL_STATUS_FAILURE; }// sme_GetOperationChannel ends here +/** + * sme_register_p2p_ack_ind_callback() - p2p ack indication callback + * @hal: hal pointer + * @callback: callback pointer to be registered + * + * This function is used to register a callback to PE for p2p ack + * indication + * + * Return: Success if msg is posted to PE else Failure. + */ +eHalStatus sme_register_p2p_ack_ind_callback(tHalHandle hal, + sir_p2p_ack_ind_callback callback) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct sir_sme_p2p_ack_ind_cb_req *msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(mac_ctx, LOG1, FL(": ENTER")); + + if (eHAL_STATUS_SUCCESS == + sme_AcquireGlobalLock(&mac_ctx->sme)) { + msg = vos_mem_malloc(sizeof(*msg)); + if (NULL == msg) { + smsLog(mac_ctx, LOGE, + FL("Failed to allocate memory")); + sme_ReleaseGlobalLock(&mac_ctx->sme); + return eHAL_STATUS_FAILURE; + } + vos_mem_set(msg, sizeof(*msg), 0); + msg->message_type = eWNI_SME_REGISTER_P2P_ACK_CB; + msg->length = sizeof(*msg); + + msg->callback = callback; + status = palSendMBMessage(mac_ctx->hHdd, msg); + sme_ReleaseGlobalLock(&mac_ctx->sme); + return status; + } + return eHAL_STATUS_FAILURE; +} + +/** + * sme_register_mgmt_frame_ind_callback() - Register a callback for + * management frame indication to PE. + * + * @hal: hal pointer + * @callback: callback pointer to be registered + * + * This function is used to register a callback for management + * frame indication to PE. + * + * Return: Success if msg is posted to PE else Failure. + */ +eHalStatus sme_register_mgmt_frame_ind_callback(tHalHandle hal, + sir_mgmt_frame_ind_callback callback) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct sir_sme_mgmt_frame_cb_req *msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + + smsLog(mac_ctx, LOG1, FL(": ENTER")); + + if (eHAL_STATUS_SUCCESS == + sme_AcquireGlobalLock(&mac_ctx->sme)) { + msg = vos_mem_malloc(sizeof(*msg)); + if (NULL == msg) { + smsLog(mac_ctx, LOGE, + FL("Not able to allocate memory for eWNI_SME_REGISTER_MGMT_FRAME_CB")); + sme_ReleaseGlobalLock(&mac_ctx->sme); + return eHAL_STATUS_FAILURE; + } + vos_mem_set(msg, sizeof(*msg), 0); + msg->message_type = eWNI_SME_REGISTER_MGMT_FRAME_CB; + msg->length = sizeof(*msg); + + msg->callback = callback; + status = palSendMBMessage(mac_ctx->hHdd, msg); + sme_ReleaseGlobalLock(&mac_ctx->sme); + return status; + } + return eHAL_STATUS_FAILURE; +} + /* --------------------------------------------------------------------------- \fn sme_RegisterMgtFrame @@ -11815,15 +11973,16 @@ eHalStatus sme_UpdateTdlsPeerState(tHalHandle hHal, csrGetCfgMaxTxPower(pMac, chanId); if (vos_nv_getChannelEnabledState(chanId) == NV_CHANNEL_DFS) - { - pTdlsPeerStateParams->peerCap.peerChan[num].dfsSet = - VOS_TRUE; - } + continue; else { pTdlsPeerStateParams->peerCap.peerChan[num].dfsSet = VOS_FALSE; } + + if (vos_nv_skip_dsrc_dfs_2g(chanId, NV_CHANNEL_SKIP_DSRC)) + continue; + num++; } } @@ -12489,7 +12648,6 @@ void sme_set_pdev_ht_vht_ies(tHalHandle hal, bool enable2x2) if (eHAL_STATUS_SUCCESS != status) { smsLog(mac_ctx, LOGE, FL( "SME_PDEV_SET_HT_VHT_IE msg to PE failed")); - vos_mem_free(ht_vht_cfg); } sme_ReleaseGlobalLock(&mac_ctx->sme); } @@ -12782,6 +12940,190 @@ sme_DelPeriodicTxPtrn(tHalHandle hal, return status; } +/** + * sme_enable_rmc() - enable RMC + * @hHal: handle + * @sessionId: session id + * + * @Return: eHalStatus + */ +eHalStatus sme_enable_rmc(tHalHandle hHal, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t vosMessage; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + smsLog(pMac, LOG1, FL("enable RMC")); + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_RMC_ENABLE_IND; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: failed to post message to WDA", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + +/** + * sme_disable_rmc() - disable RMC + * @hHal: handle + * @sessionId: session id + * + * @Return: eHalStatus + */ +eHalStatus sme_disable_rmc(tHalHandle hHal, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t vosMessage; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + + smsLog(pMac, LOG1, FL("disable RMC")); + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_RMC_DISABLE_IND; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: failed to post message to WDA", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return status; +} + + +/* --------------------------------------------------------------------------- + \fn sme_SendRmcActionPeriod + \brief Used to send RMC action period param to fw + \param hHal + \param sessionId + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SendRmcActionPeriod(tHalHandle hHal, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_RMC_ACTION_PERIOD_IND; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: failed to post message to WDA", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} + +/* --------------------------------------------------------------------------- + \fn sme_GetIBSSPeerInfo + \brief Used to disable RMC + setting will not persist over reboots + \param hHal + \param ibssPeerInfoReq multicast Group IP address + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_RequestIBSSPeerInfo(tHalHandle hHal, void *pUserData, + pIbssPeerInfoCb peerInfoCbk, + tANI_BOOLEAN allPeerInfoReqd, + tANI_U8 staIdx) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + vos_msg_t vosMessage; + tSirIbssGetPeerInfoReqParams *pIbssInfoReqParams; + + status = sme_AcquireGlobalLock(&pMac->sme); + if ( eHAL_STATUS_SUCCESS == status) + { + pMac->sme.peerInfoParams.peerInfoCbk = peerInfoCbk; + pMac->sme.peerInfoParams.pUserData = pUserData; + + pIbssInfoReqParams = (tSirIbssGetPeerInfoReqParams *) + vos_mem_malloc(sizeof(tSirIbssGetPeerInfoReqParams)); + if (NULL == pIbssInfoReqParams) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for dhcp start", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + pIbssInfoReqParams->allPeerInfoReqd = allPeerInfoReqd; + pIbssInfoReqParams->staIdx = staIdx; + + vosMessage.type = WDA_GET_IBSS_PEER_INFO_REQ; + vosMessage.bodyptr = pIbssInfoReqParams; + vosMessage.reserved = 0; + + vosStatus = vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage ); + if ( VOS_STATUS_SUCCESS != vosStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post WDA_GET_IBSS_PEER_INFO_REQ MSG failed", __func__); + vos_mem_free(pIbssInfoReqParams); + vosStatus = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return (vosStatus); +} + +/* --------------------------------------------------------------------------- + \fn sme_SendCesiumEnableInd + \brief Used to send proprietary cesium enable indication to fw + \param hHal + \param sessionId + \- return eHalStatus + -------------------------------------------------------------------------*/ +eHalStatus sme_SendCesiumEnableInd(tHalHandle hHal, tANI_U32 sessionId) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + vosMessage.bodyptr = NULL; + vosMessage.type = WDA_IBSS_CESIUM_ENABLE_IND; + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: failed to post message to WDA", __func__); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + + return(status); +} + void smeGetCommandQStatus( tHalHandle hHal ) { tSmeCmd *pTempCmd = NULL; @@ -13996,8 +14338,13 @@ eHalStatus sme_set_miracast(tHalHandle hal, uint8_t filter_type) uint32_t *val; tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); + if (NULL == mac_ptr) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid MAC pointer", __func__); + return eHAL_STATUS_FAILURE; + } val = vos_mem_malloc(sizeof(*val)); - if (NULL == val || NULL == mac_ptr) { + if (NULL == val) { VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Invalid pointer", __func__); return eHAL_STATUS_E_MALLOC_FAILED; @@ -14012,7 +14359,7 @@ eHalStatus sme_set_miracast(tHalHandle hal, uint8_t filter_type) if (!VOS_IS_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_MAS_ENABLE_DISABLE to WMA!", + "%s: Not able to post SIR_HAL_SET_MIRACAST to WMA!", __func__); vos_mem_free(val); return eHAL_STATUS_FAILURE; @@ -17431,17 +17778,177 @@ bool sme_is_sta_smps_allowed(tHalHandle hal, uint8_t session_id) return false; } - if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { - smsLog(mac_ctx, LOGE, "CSR session not valid: %d", session_id); - return false; - } - csr_session = CSR_GET_SESSION(mac_ctx, session_id); if (NULL == csr_session) { smsLog(mac_ctx, LOGE, "SME session not valid: %d", session_id); return false; } + if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { + smsLog(mac_ctx, LOGE, "CSR session not valid: %d", session_id); + return false; + } + return (csr_session->supported_nss_1x1 == true) ? false : true; } +/** + * sme_set_beacon_filter() - set the beacon filter configuration + * @vdev_id: vdev index id + * @ie_map: bitwise array of IEs + * + * Return: Return VOS_STATUS, otherwise appropriate failure code + */ +VOS_STATUS sme_set_beacon_filter(uint32_t vdev_id, uint32_t *ie_map) +{ + vos_msg_t vos_message; + VOS_STATUS vos_status; + struct beacon_filter_param *filter_param; + + filter_param = vos_mem_malloc(sizeof(*filter_param)); + if (NULL == filter_param) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: fail to alloc filter_param", __func__); + return VOS_STATUS_E_FAILURE; + } + + filter_param->vdev_id = vdev_id; + + vos_mem_copy(filter_param->ie_map, ie_map, + BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(uint32_t)); + + vos_message.type = WDA_ADD_BCN_FILTER_CMDID; + vos_message.bodyptr = filter_param; + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, + &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post msg to WDA!", + __func__); + + vos_mem_free(filter_param); + } + return vos_status; +} + +/** + * sme_unset_beacon_filter() - set the beacon filter configuration + * @vdev_id: vdev index id + * + * Return: Return VOS_STATUS, otherwise appropriate failure code + */ +VOS_STATUS sme_unset_beacon_filter(uint32_t vdev_id) +{ + vos_msg_t vos_message; + VOS_STATUS vos_status; + struct beacon_filter_param *filter_param; + + filter_param = vos_mem_malloc(sizeof(*filter_param)); + if (NULL == filter_param) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: fail to alloc filter_param", __func__); + return VOS_STATUS_E_FAILURE; + } + + filter_param->vdev_id = vdev_id; + + vos_message.type = WDA_REMOVE_BCN_FILTER_CMDID; + vos_message.bodyptr = filter_param; + vos_status = vos_mq_post_message(VOS_MODULE_ID_WDA, + &vos_message); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post msg to WDA!", + __func__); + + vos_mem_free(filter_param); + } + return vos_status; +} + +/** + * sme_update_fine_time_measurement_capab() - Update the FTM capab from incoming + * val + * @hal: Handle for Hal layer + * @val: New FTM capability value + * + * Return: None + */ +void sme_update_fine_time_measurement_capab(tHalHandle hal, uint32_t val) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + mac_ctx->fine_time_meas_cap = val; + if (val == 0) { + mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 0; + ((tpRRMCaps)mac_ctx->rrm.rrmSmeContext. + rrmConfig.rm_capability)->fine_time_meas_rpt = 0; + } else { + mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 1; + ((tpRRMCaps)mac_ctx->rrm.rrmSmeContext. + rrmConfig.rm_capability)->fine_time_meas_rpt = 1; + } +} + + +/** + * sme_delete_all_tdls_peers: send request to delete tdls peers + * @hal: handler for HAL + * @sessionId: session id + * + * Functtion send's request to lim to delete tdls peers + * + * Return: Success: eHAL_STATUS_SUCCESS Failure: Error value + */ +eHalStatus sme_delete_all_tdls_peers(tHalHandle hal, uint8_t session_id) +{ + struct sir_del_all_tdls_peers *msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal p_mac = PMAC_STRUCT(hal); + tCsrRoamSession *session = CSR_GET_SESSION(p_mac, session_id); + + msg = vos_mem_malloc(sizeof(*msg)); + if (NULL == msg) { + smsLog(p_mac, LOGE, FL("memory alloc failed")); + return eHAL_STATUS_FAILURE; + } + + vos_mem_set(msg, sizeof(*msg), 0); + + msg->msg_type = pal_cpu_to_be16((uint16_t)eWNI_SME_DEL_ALL_TDLS_PEERS); + msg->msg_len = pal_cpu_to_be16((uint16_t)sizeof(*msg)); + + vos_mem_copy(msg->bssid, session->connectedProfile.bssid, + sizeof(tSirMacAddr)); + + status = palSendMBMessage(p_mac->hHdd, msg); + + if(status != eHAL_STATUS_SUCCESS) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("palSendMBMessage Failed")); + status = eHAL_STATUS_FAILURE; + } + + return status; +} + +/* + * sme_is_session_valid(): verify a sme session + * @param hal_handle: hal handle for getting global mac struct. + * @param session_id: sme_session_id + * Return: eHAL_STATUS_SUCCESS or non-zero on failure. + */ +VOS_STATUS sme_is_session_valid(tHalHandle hal_handle, uint8_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + + if (NULL == mac_ctx) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("mac_ctx is null!!")); + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } + if (CSR_IS_SESSION_VALID(mac_ctx, session_id)) + return VOS_STATUS_SUCCESS; + + return VOS_STATUS_E_FAILURE; +} diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c index 8e5517ef7d9b..e264c54e7970 100644 --- a/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -274,7 +274,8 @@ int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) uint64_t ts; uint32_t rem; - if (!vos_is_multicast_logging()) { + if ((!vos_is_multicast_logging()) || + (!gwlan_logging.is_active)) { /* * This is to make sure that we print the logs to kmsg console * when no logger app is running. This is also needed to diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c index 3b0086976b5b..b9ba59a8d4eb 100644 --- a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -427,10 +427,8 @@ tANI_U8* macTraceGetSmeMsgString( tANI_U16 smeMsg ) CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHANNEL_REQ); CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_IND); CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_RSP); - CASE_RETURN_STRING(eWNI_SME_MGMT_FRM_IND); CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_RDY_IND); CASE_RETURN_STRING(eWNI_SME_SEND_ACTION_FRAME_IND); - CASE_RETURN_STRING(eWNI_SME_ACTION_FRAME_SEND_CNF); CASE_RETURN_STRING(eWNI_SME_ABORT_REMAIN_ON_CHAN_IND); CASE_RETURN_STRING(eWNI_SME_UPDATE_NOA); CASE_RETURN_STRING(eWNI_SME_CLEAR_DFS_CHANNEL_LIST); @@ -516,6 +514,7 @@ tANI_U8* macTraceGetSmeMsgString( tANI_U16 smeMsg ) #endif // WLAN_WAKEUP_EVENTS CASE_RETURN_STRING(eWNI_SME_EXCLUDE_UNENCRYPTED); CASE_RETURN_STRING(eWNI_SME_RSSI_IND); //RSSI indication from TL to be serialized on MC thread + CASE_RETURN_STRING(eWNI_SME_REGISTER_P2P_ACK_CB); CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END); CASE_RETURN_STRING(eWNI_SME_GET_TSM_STATS_REQ); CASE_RETURN_STRING(eWNI_SME_GET_TSM_STATS_RSP); @@ -524,6 +523,7 @@ tANI_U8* macTraceGetSmeMsgString( tANI_U16 smeMsg ) #endif CASE_RETURN_STRING(eWNI_SME_LOST_LINK_INFO_IND); CASE_RETURN_STRING(eWNI_SME_SMPS_FORCE_MODE_IND); + CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB); default: return( (tANI_U8*)"UNKNOWN" ); break; @@ -804,6 +804,15 @@ tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ) #ifdef FEATURE_WLAN_AUTO_SHUTDOWN CASE_RETURN_STRING(WDA_SET_AUTO_SHUTDOWN_TIMER_REQ); #endif + + CASE_RETURN_STRING(WDA_IBSS_CESIUM_ENABLE_IND); + CASE_RETURN_STRING(WDA_GET_IBSS_PEER_INFO_REQ); + CASE_RETURN_STRING(WDA_TX_FAIL_MONITOR_IND); + + CASE_RETURN_STRING(WDA_RMC_ENABLE_IND); + CASE_RETURN_STRING(WDA_RMC_DISABLE_IND); + CASE_RETURN_STRING(WDA_RMC_ACTION_PERIOD_IND); + CASE_RETURN_STRING(WDA_INIT_THERMAL_INFO_CMD); CASE_RETURN_STRING(WDA_SET_THERMAL_LEVEL); CASE_RETURN_STRING(WDA_SET_SAP_INTRABSS_DIS); diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c index 7c9128f716d1..8b9070d03a2d 100644 --- a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c @@ -747,7 +747,7 @@ PopulateDot11fHTCaps(tpAniSirGlobal pMac, } /* If STA and mimo power save is enabled include ht smps */ - if (psessionEntry && (!pMac->lteCoexAntShare) && + if (psessionEntry && LIM_IS_STA_ROLE(psessionEntry) && (psessionEntry->enableHtSmps) && (!psessionEntry->supported_nss_1x1)) { @@ -1203,18 +1203,18 @@ PopulateDot11fExtCap(tpAniSirGlobal pMac, return eSIR_FAILURE; } - if (val) // If set to true then set RTTv3 + if (val) { if (!psessionEntry || LIM_IS_STA_ROLE(psessionEntry)) { p_ext_cap->fine_time_meas_initiator = - (pMac->fine_time_meas_cap & FINE_TIME_MEAS_STA_INITIATOR) ? 1 : 0; + (pMac->fine_time_meas_cap & WMI_FW_STA_RTT_INITR) ? 1 : 0; p_ext_cap->fine_time_meas_responder = - (pMac->fine_time_meas_cap & FINE_TIME_MEAS_STA_RESPONDER) ? 1 : 0; + (pMac->fine_time_meas_cap & WMI_FW_STA_RTT_RESPR) ? 1 : 0; } else if (LIM_IS_AP_ROLE(psessionEntry)) { p_ext_cap->fine_time_meas_initiator = - (pMac->fine_time_meas_cap & FINE_TIME_MEAS_SAP_INITIATOR) ? 1 : 0; + (pMac->fine_time_meas_cap & WMI_FW_AP_RTT_INITR) ? 1 : 0; p_ext_cap->fine_time_meas_responder = - (pMac->fine_time_meas_cap & FINE_TIME_MEAS_SAP_RESPONDER) ? 1 : 0; + (pMac->fine_time_meas_cap & WMI_FW_AP_RTT_RESPR) ? 1 : 0; } } @@ -1721,7 +1721,8 @@ PopulateDot11fSuppRates(tpAniSirGlobal pMac, tSirRetStatus populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, tDot11fIESuppRates *p_supp_rates, - tDot11fIEExtSuppRates *p_ext_supp_rates) + tDot11fIEExtSuppRates *p_ext_supp_rates, + uint8_t curr_oper_channel) { tSirMacRateSet temp_rateset; tSirMacRateSet temp_rateset2; @@ -1731,15 +1732,23 @@ populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, wlan_cfgGetInt(p_mac, WNI_CFG_DOT11_MODE, &self_dot11mode); /** - * Include 11b rates only when the device configured in - * auto, 11a/b/g or 11b_only - */ - if ((self_dot11mode == WNI_CFG_DOT11_MODE_ALL) || + * Include 11b rates only when the device configured in + * auto, 11a/b/g or 11b_only and also if current base + * channel is 5 GHz then no need to advertise the 11b rates. + * If devices move to 2.4GHz off-channel then they can communicate + * in 11g rates i.e. (6, 9, 12, 18, 24, 36 and 54). + */ + limLog(p_mac, LOG1, + FL("Current operating channel %d self_dot11mode = %d"), + curr_oper_channel, self_dot11mode); + + if ((curr_oper_channel <= SIR_11B_CHANNEL_END) && + ((self_dot11mode == WNI_CFG_DOT11_MODE_ALL) || (self_dot11mode == WNI_CFG_DOT11_MODE_11A) || (self_dot11mode == WNI_CFG_DOT11_MODE_11AC) || (self_dot11mode == WNI_CFG_DOT11_MODE_11N) || (self_dot11mode == WNI_CFG_DOT11_MODE_11G) || - (self_dot11mode == WNI_CFG_DOT11_MODE_11B) ) { + (self_dot11mode == WNI_CFG_DOT11_MODE_11B))) { val = WNI_CFG_SUPPORTED_RATES_11B_LEN; wlan_cfgGetStr(p_mac, WNI_CFG_SUPPORTED_RATES_11B, (tANI_U8 *)&temp_rateset.rate, &val); diff --git a/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h b/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h index cce1f478458b..6c8d527ae618 100644 --- a/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h +++ b/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2695,7 +2695,7 @@ void WLANTL_PauseUnPauseQs(void *vos_context, v_BOOL_t flag); * HDD will call this API to get the OL-TXRX module stats * */ -void WLANTL_Get_llStats +VOS_STATUS WLANTL_Get_llStats ( v_U8_t sessionId, char *buffer, @@ -2846,12 +2846,15 @@ void WLANTL_SetAdapterMaxQDepth int max_q_depth ); #else -static inline void WLANTL_Get_llStats +static inline VOS_STATUS WLANTL_Get_llStats ( uint8_t sessionId, char *buffer, uint16_t length -) {} +) +{ + return VOS_STATUS_SUCCESS; +} #endif /* QCA_LL_TX_FLOW_CT */ diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h index f1d29dc06412..ca93571daaf8 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.h @@ -79,6 +79,7 @@ typedef struct wlan_wake_lock { #else int lock; #endif + bool is_initialized; } vos_wake_lock_t; typedef void *runtime_pm_context_t; diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h index 878fe86de235..80646a6bfaa4 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -115,6 +115,12 @@ typedef enum } VOS_MQ_ID; +#define HIGH_PRIORITY 1 +#define LOW_PRIORITY 0 +VOS_STATUS vos_mq_post_message_by_priority(VOS_MQ_ID msg_queue_id, + vos_msg_t *message, + int is_high_priority); + /**--------------------------------------------------------------------------- \brief vos_mq_post_message() - post a message to a message queue @@ -129,7 +135,7 @@ typedef enum
  • TL
- \param msgQueueId - identifies the message queue upon which the message + \param msg_queue_id - identifies the message queue upon which the message will be posted. \param message - a pointer to a message buffer. Memory for this message @@ -152,7 +158,12 @@ typedef enum \sa --------------------------------------------------------------------------*/ -VOS_STATUS vos_mq_post_message( VOS_MQ_ID msgQueueId, vos_msg_t *message ); +static inline VOS_STATUS vos_mq_post_message(VOS_MQ_ID msg_queue_id, + vos_msg_t *message) +{ + return vos_mq_post_message_by_priority (msg_queue_id, message, + LOW_PRIORITY); +} /**--------------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h index 495d362f8885..7bc8088a41a8 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_nvitem.h @@ -244,7 +244,7 @@ VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, -------------------------------------------------------------------------*/ eNVChannelEnabledType vos_nv_getChannelEnabledState(v_U32_t rfChannel); -uint8_t vos_nv_skip_dfs_and_2g(uint32_t rf_channel); +uint8_t vos_nv_skip_dsrc_dfs_2g(uint32_t rf_channel, int32_t skip_group); VOS_STATUS vos_nv_get_dfs_region(uint8_t *dfs_region); VOS_STATUS vos_nv_set_dfs_region(uint8_t dfs_region); diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h index bd3b81489bfe..76bb1ce09e42 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h @@ -182,4 +182,6 @@ v_U8_t vos_get_mmie_size(void); #endif /* WLAN_FEATURE_11W */ eHalStatus vos_send_flush_logs_cmd_to_fw(tpAniSirGlobal pMac); +unsigned long vos_rounddown_pow_of_two(unsigned long n); + #endif // #if !defined __VOSS_UTILS_H diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c index a1c74a0394b4..53e62f8f8a08 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c @@ -92,6 +92,8 @@ #include "wlan_logging_sock_svc.h" #include "wma.h" +#include "vos_utils.h" + /*--------------------------------------------------------------------------- * Preprocessor Definitions and Constants * ------------------------------------------------------------------------*/ @@ -496,8 +498,42 @@ VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ) #ifdef IPA_UC_OFFLOAD /* IPA micro controller data path offload resource config item */ macOpenParms.ucOffloadEnabled = pHddCtx->cfg_ini->IpaUcOffloadEnabled; + + if (!is_power_of_2(pHddCtx->cfg_ini->IpaUcTxBufCount)) { + /* IpaUcTxBufCount should be power of 2 */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Round down IpaUcTxBufCount %d to nearest power of two", + __func__, pHddCtx->cfg_ini->IpaUcTxBufCount); + pHddCtx->cfg_ini->IpaUcTxBufCount = + vos_rounddown_pow_of_two(pHddCtx->cfg_ini->IpaUcTxBufCount); + if (!pHddCtx->cfg_ini->IpaUcTxBufCount) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to round down IpaUcTxBufCount", __func__); + goto err_htc_close; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: IpaUcTxBufCount rounded down to %d", __func__, + pHddCtx->cfg_ini->IpaUcTxBufCount); + } macOpenParms.ucTxBufCount = pHddCtx->cfg_ini->IpaUcTxBufCount; macOpenParms.ucTxBufSize = pHddCtx->cfg_ini->IpaUcTxBufSize; + + if (!is_power_of_2(pHddCtx->cfg_ini->IpaUcRxIndRingCount)) { + /* IpaUcRxIndRingCount should be power of 2 */ + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Round down IpaUcRxIndRingCount %d to nearest power of two", + __func__, pHddCtx->cfg_ini->IpaUcRxIndRingCount); + pHddCtx->cfg_ini->IpaUcRxIndRingCount = + vos_rounddown_pow_of_two(pHddCtx->cfg_ini->IpaUcRxIndRingCount); + if (!pHddCtx->cfg_ini->IpaUcRxIndRingCount) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: Failed to round down IpaUcRxIndRingCount", __func__); + goto err_htc_close; + } + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: IpaUcRxIndRingCount rounded down to %d", __func__, + pHddCtx->cfg_ini->IpaUcRxIndRingCount); + } macOpenParms.ucRxIndRingCount = pHddCtx->cfg_ini->IpaUcRxIndRingCount; macOpenParms.ucTxPartitionBase = pHddCtx->cfg_ini->IpaUcTxPartitionBase; #endif /* IPA_UC_OFFLOAD */ @@ -1702,45 +1738,22 @@ VOS_STATUS vos_free_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, } /* vos_free_context() */ - -/**--------------------------------------------------------------------------- - - \brief vos_mq_post_message() - post a message to a message queue - - This API allows messages to be posted to a specific message queue. Messages - can be posted to the following message queues: - -
    -
  • SME -
  • PE -
  • HAL -
  • TL -
- - \param msgQueueId - identifies the message queue upon which the message - will be posted. - - \param message - a pointer to a message buffer. Memory for this message - buffer is allocated by the caller and free'd by the vOSS after the - message is posted to the message queue. If the consumer of the - message needs anything in this message, it needs to copy the contents - before returning from the message queue handler. - - \return VOS_STATUS_SUCCESS - the message has been successfully posted - to the message queue. - - VOS_STATUS_E_INVAL - The value specified by msgQueueId does not - refer to a valid Message Queue Id. - - VOS_STATUS_E_FAULT - message is an invalid pointer. - - VOS_STATUS_E_FAILURE - the message queue handler has reported - an unknown failure. - - \sa - - --------------------------------------------------------------------------*/ -VOS_STATUS vos_mq_post_message( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) +/** + * vos_mq_post_message_by_priority() - posts message using priority + * to message queue + * @msgQueueId: message queue id + * @pMsg: message to be posted + * @is_high_priority: wheather message is high priority + * + * This function is used to post high priority message to message queue + * + * Return: VOS_STATUS_SUCCESS on success + * VOS_STATUS_E_FAILURE on failure + * VOS_STATUS_E_RESOURCES on resource allocation failure + */ +VOS_STATUS vos_mq_post_message_by_priority(VOS_MQ_ID msgQueueId, + vos_msg_t *pMsg, + int is_high_priority) { pVosMqType pTargetMq = NULL; pVosMsgWrapper pMsgWrapper = NULL; @@ -1835,14 +1848,17 @@ VOS_STATUS vos_mq_post_message( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) vos_mem_copy( (v_VOID_t*)pMsgWrapper->pVosMsg, (v_VOID_t*)pMsg, sizeof(vos_msg_t)); - vos_mq_put(pTargetMq, pMsgWrapper); + if (is_high_priority) + vos_mq_put_front(pTargetMq, pMsgWrapper); + else + vos_mq_put(pTargetMq, pMsgWrapper); set_bit(MC_POST_EVENT_MASK, &gpVosContext->vosSched.mcEventFlag); wake_up_interruptible(&gpVosContext->vosSched.mcWaitQueue); return VOS_STATUS_SUCCESS; -} /* vos_mq_post_message()*/ +} /**--------------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c index 3428686fb26d..f08c9e45a2ea 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c @@ -505,13 +505,19 @@ VOS_STATUS vos_spin_lock_destroy(vos_spin_lock_t *pLock) --------------------------------------------------------------------------*/ VOS_STATUS vos_wake_lock_init(vos_wake_lock_t *pLock, const char *name) { + if (!pLock->is_initialized) { #if defined CONFIG_CNSS - cnss_pm_wake_lock_init(&pLock->lock, name); + cnss_pm_wake_lock_init(&pLock->lock, name); #elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) - wake_lock_init(&pLock->lock, WAKE_LOCK_SUSPEND, name); + wake_lock_init(&pLock->lock, WAKE_LOCK_SUSPEND, name); #endif - - return VOS_STATUS_SUCCESS; + pLock->is_initialized = true; + return VOS_STATUS_SUCCESS; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + FL("wakelock is already intialized")); + return VOS_STATUS_E_INVAL; + } } /** @@ -526,10 +532,10 @@ VOS_STATUS vos_wake_lock_init(vos_wake_lock_t *pLock, const char *name) static const char* vos_wake_lock_name(vos_wake_lock_t *pLock) { #if defined CONFIG_CNSS - if (pLock->lock.name) + if ((pLock->is_initialized) && (pLock->lock.name)) return pLock->lock.name; #elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) - if (pLock->lock.ws.name) + if ((pLock->is_initialized) && (pLock->lock.ws.name)) return pLock->lock.ws.name; #endif return "UNNAMED_WAKELOCK"; @@ -547,16 +553,21 @@ static const char* vos_wake_lock_name(vos_wake_lock_t *pLock) VOS_STATUS vos_wake_lock_acquire(vos_wake_lock_t *pLock, uint32_t reason) { - vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), - WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, - WIFI_POWER_EVENT_WAKELOCK_TAKEN); - + if (pLock->is_initialized) { + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); #if defined CONFIG_CNSS - cnss_pm_wake_lock(&pLock->lock); + cnss_pm_wake_lock(&pLock->lock); #elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) - wake_lock(&pLock->lock); + wake_lock(&pLock->lock); #endif - return VOS_STATUS_SUCCESS; + return VOS_STATUS_SUCCESS; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + FL("wakelock is not intialized yet")); + return VOS_STATUS_E_INVAL; + } } /*-------------------------------------------------------------------------- @@ -571,22 +582,27 @@ VOS_STATUS vos_wake_lock_acquire(vos_wake_lock_t *pLock, VOS_STATUS vos_wake_lock_timeout_acquire(vos_wake_lock_t *pLock, v_U32_t msec, uint32_t reason) { - /* Wakelock for Rx is frequent. - * It is reported only during active debug - */ - if (((vos_get_ring_log_level(RING_ID_WAKELOCK) >= WLAN_LOG_LEVEL_ACTIVE) - && (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX == reason)) || - (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX != reason)) { - vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), msec, - WIFI_POWER_EVENT_WAKELOCK_TAKEN); - } - + if (pLock->is_initialized) { + /* Wakelock for Rx is frequent. + * It is reported only during active debug + */ + if (((vos_get_ring_log_level(RING_ID_WAKELOCK) >= WLAN_LOG_LEVEL_ACTIVE) + && (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX == reason)) || + (WIFI_POWER_EVENT_WAKELOCK_HOLD_RX != reason)) { + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), msec, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); + } #if defined CONFIG_CNSS - cnss_pm_wake_lock_timeout(&pLock->lock, msec); + cnss_pm_wake_lock_timeout(&pLock->lock, msec); #elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) - wake_lock_timeout(&pLock->lock, msecs_to_jiffies(msec)); + wake_lock_timeout(&pLock->lock, msecs_to_jiffies(msec)); #endif - return VOS_STATUS_SUCCESS; + return VOS_STATUS_SUCCESS; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + FL("wakelock is not intialized yet")); + return VOS_STATUS_E_INVAL; + } } /*-------------------------------------------------------------------------- @@ -600,16 +616,22 @@ VOS_STATUS vos_wake_lock_timeout_acquire(vos_wake_lock_t *pLock, v_U32_t msec, ------------------------------------------------------------------------*/ VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason) { - vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), - WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, - WIFI_POWER_EVENT_WAKELOCK_RELEASED); + if (pLock->is_initialized) { + vos_log_wlock_diag(reason, vos_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_RELEASED); #if defined CONFIG_CNSS - cnss_pm_wake_lock_release(&pLock->lock); + cnss_pm_wake_lock_release(&pLock->lock); #elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) - wake_unlock(&pLock->lock); + wake_unlock(&pLock->lock); #endif + return VOS_STATUS_SUCCESS; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + FL("wakelock is not intialized yet")); + return VOS_STATUS_E_INVAL; - return VOS_STATUS_SUCCESS; + } } /*-------------------------------------------------------------------------- @@ -623,12 +645,19 @@ VOS_STATUS vos_wake_lock_release(vos_wake_lock_t *pLock, uint32_t reason) ------------------------------------------------------------------------*/ VOS_STATUS vos_wake_lock_destroy(vos_wake_lock_t *pLock) { + if (pLock->is_initialized) { #if defined CONFIG_CNSS - cnss_pm_wake_lock_destroy(&pLock->lock); + cnss_pm_wake_lock_destroy(&pLock->lock); #elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) - wake_lock_destroy(&pLock->lock); + wake_lock_destroy(&pLock->lock); #endif - return VOS_STATUS_SUCCESS; + pLock->is_initialized = false; + return VOS_STATUS_SUCCESS; + } else { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + FL("wakelock is not intialized yet")); + return VOS_STATUS_E_INVAL; + } } VOS_STATUS vos_runtime_pm_prevent_suspend(runtime_pm_context_t runtime_pm_ctx) diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c index b585064f39fb..81c43598594e 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 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. * @@ -162,6 +162,29 @@ __inline void vos_mq_put(pVosMqType pMq, pVosMsgWrapper pMsgWrapper) } /* vos_mq_put() */ +/** + * vos_mq_put_front() - adds a message to the head of message queue + * @mq: message queue + * @msg_wrapper: message wrapper + * + * This function is used to add a message to the head of message queue + * + * Return: None + */ +void vos_mq_put_front(pVosMqType mq, pVosMsgWrapper msg_wrapper) +{ + unsigned long flags; + + if ((mq == NULL) || (msg_wrapper == NULL)) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed", __func__); + return; + } + + spin_lock_irqsave(&mq->mqLock, flags); + list_add(&msg_wrapper->msgNode, &mq->mqList); + spin_unlock_irqrestore(&mq->mqLock, flags); +} /*--------------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c index f2950a9c20b0..1faebc9bd76c 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c @@ -837,19 +837,36 @@ VOS_STATUS vos_nv_readDefaultCountryTable( uNvTables *tableData ) } /** - * vos_nv_skip_dfs_and_2g() - skip dfs and 2g band channels + * vos_nv_skip_dsrc_dfs_2g() - skip dsrc, dfs and 2g band channels * @rf_channel: input channel enum to know, whether to skip or add the channel + * @skip_group: group to skip * * Return: true or false */ -uint8_t vos_nv_skip_dfs_and_2g(uint32_t rf_channel) +uint8_t vos_nv_skip_dsrc_dfs_2g(uint32_t rf_channel, int32_t skip_group) { uint32_t channel_loop; eRfChannels channel_enum = INVALID_RF_CHANNEL; uint8_t ret = false; + int32_t start_channel, end_channel; - for (channel_loop = RF_CHAN_36; - channel_loop <= RF_CHAN_184; channel_loop++) { + switch (skip_group){ + case NV_CHANNEL_SKIP_DSRC: + start_channel = RF_CHAN_1; + end_channel = RF_CHAN_165; + break; + case NV_CHANNEL_SKIP_2G: + start_channel = RF_CHAN_36; + end_channel = RF_CHAN_165; + break; + default: + start_channel = RF_CHAN_1; + end_channel = RF_CHAN_184; + break; + } + + for (channel_loop = start_channel; + channel_loop <= end_channel; channel_loop++) { if (rfChannels[channel_loop].channelNum == rf_channel) { channel_enum = (eRfChannels)channel_loop; break; diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c index a55c129d1e83..e097ce759fd8 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.c @@ -1011,10 +1011,10 @@ VosMCThread clear_bit(MC_SUSPEND_EVENT_MASK, &pSchedContext->mcEventFlag); spin_lock(&pSchedContext->McThreadLock); + INIT_COMPLETION(pSchedContext->ResumeMcEvent); /* Mc Thread Suspended */ complete(&pHddCtx->mc_sus_event_var); - INIT_COMPLETION(pSchedContext->ResumeMcEvent); spin_unlock(&pSchedContext->McThreadLock); /* Wait foe Resume Indication */ @@ -1778,8 +1778,8 @@ static int VosTlshimRxThread(void *arg) clear_bit(RX_SUSPEND_EVENT_MASK, &pSchedContext->tlshimRxEvtFlg); spin_lock(&pSchedContext->TlshimRxThreadLock); - complete(&pSchedContext->SuspndTlshimRxEvent); INIT_COMPLETION(pSchedContext->ResumeTlshimRxEvent); + complete(&pSchedContext->SuspndTlshimRxEvent); spin_unlock(&pSchedContext->TlshimRxThreadLock); wait_for_completion_interruptible( &pSchedContext->ResumeTlshimRxEvent); diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h index ba2792de7d5e..5fe18ffa82c5 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h @@ -654,6 +654,7 @@ VOS_STATUS vos_watchdog_close ( v_PVOID_t pVosContext ); VOS_STATUS vos_mq_init(pVosMqType pMq); void vos_mq_deinit(pVosMqType pMq); void vos_mq_put(pVosMqType pMq, pVosMsgWrapper pMsgWrapper); +void vos_mq_put_front(pVosMqType mq, pVosMsgWrapper msg_wrapper); pVosMsgWrapper vos_mq_get(pVosMqType pMq); v_BOOL_t vos_is_mq_empty(pVosMqType pMq); pVosSchedContext get_vos_sched_ctxt(void); diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c index 6dff1b8d068a..adf15999f495 100644 --- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c @@ -1230,3 +1230,19 @@ v_U8_t vos_chan_to_band(v_U32_t chan) return VOS_BAND_5GHZ; } + +/** + * vos_rounddown_pow_of_two() - Round down to nearest power of two + * @n: number to be tested + * + * Test if the input number is power of two, and return the nearest power of two + * + * Return: number rounded down to the nearest power of two + */ +unsigned long vos_rounddown_pow_of_two(unsigned long n) +{ + if (is_power_of_2(n)) + return n; /* already a power of 2 */ + + return __rounddown_pow_of_two(n); +} diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h index 7598cca2d326..fe2d200f731f 100644 --- a/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h @@ -749,7 +749,8 @@ typedef struct { tSirMacAddr selfMacAddr; eHalStatus status; - tANI_U8 oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tStartOemDataReq, *tpStartOemDataReq; typedef struct diff --git a/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h index dcfc4a4121b5..cb1b1e61e2a5 100644 --- a/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h @@ -306,6 +306,8 @@ typedef void (*pWDATxRxCompFunc)( v_PVOID_t pContext, void *pData, //parameter 2 - txComplete status : 1- success, 0 - failure. typedef eHalStatus (*pWDAAckFnTxComp)(tpAniSirGlobal, tANI_U32); +typedef void (*WDA_txFailIndCallback)(tANI_U8 *, tANI_U8); + /* generic callback for updating parameters from target to UMAC */ typedef void (*wda_tgt_cfg_cb) (void *context, void *param); @@ -403,7 +405,8 @@ typedef struct /* Event to wait for WDA stop on FTM mode */ vos_event_t ftmStopDoneEvent; -} tWDA_CbContext ; + WDA_txFailIndCallback txFailIndCallback; +} tWDA_CbContext ; typedef struct { @@ -860,6 +863,8 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_DHCP_START_IND SIR_HAL_DHCP_START_IND #define WDA_DHCP_STOP_IND SIR_HAL_DHCP_STOP_IND +#define WDA_TX_FAIL_MONITOR_IND SIR_HAL_TX_FAIL_MONITOR_IND + #define WDA_HIDDEN_SSID_VDEV_RESTART SIR_HAL_HIDE_SSID_VDEV_RESTART #ifdef WLAN_FEATURE_GTK_OFFLOAD @@ -928,10 +933,12 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_RMC_DISABLE_IND SIR_HAL_RMC_DISABLE_IND #define WDA_RMC_ACTION_PERIOD_IND SIR_HAL_RMC_ACTION_PERIOD_IND +/* IBSS peer info related message */ #define WDA_GET_IBSS_PEER_INFO_REQ SIR_HAL_IBSS_PEER_INFO_REQ #define WDA_GET_IBSS_PEER_INFO_RSP SIR_HAL_IBSS_PEER_INFO_RSP #define WDA_IBSS_CESIUM_ENABLE_IND SIR_HAL_IBSS_CESIUM_ENABLE_IND + #define WDA_INIT_BAD_PEER_TX_CTL_INFO_CMD SIR_HAL_BAD_PEER_TX_CTL_INI_CMD #ifdef FEATURE_WLAN_TDLS @@ -1066,6 +1073,8 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_UPDATE_WEP_DEFAULT_KEY SIR_HAL_UPDATE_WEP_DEFAULT_KEY +#define WDA_ADD_BCN_FILTER_CMDID SIR_HAL_ADD_BCN_FILTER_CMDID +#define WDA_REMOVE_BCN_FILTER_CMDID SIR_HAL_REMOVE_BCN_FILTER_CMDID tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); diff --git a/drivers/staging/qcacld-2.0/Kbuild b/drivers/staging/qcacld-2.0/Kbuild index 9fb7084a9485..60e5260301bc 100644 --- a/drivers/staging/qcacld-2.0/Kbuild +++ b/drivers/staging/qcacld-2.0/Kbuild @@ -949,7 +949,8 @@ CDEFINES := -DANI_LITTLE_BYTE_ENDIAN \ -DFEATURE_WLAN_EXTSCAN \ -DFEATURE_WLAN_LFR \ -DFEATURE_WLAN_CH144 \ - -DHTC_CRP_DEBUG + -DHTC_CRP_DEBUG \ + -DWLAN_VOWIFI_DEBUG ifeq ($(CONFIG_QCA_WIFI_SDIO), 1) CDEFINES += -DCONFIG_HL_SUPPORT \ diff --git a/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h b/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h index 5c00fbe57e62..c274858771bc 100644 --- a/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h +++ b/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h @@ -398,7 +398,9 @@ enum NV_CHANNEL_DISABLE, NV_CHANNEL_ENABLE, NV_CHANNEL_DFS, - NV_CHANNEL_INVALID + NV_CHANNEL_INVALID, + NV_CHANNEL_SKIP_DSRC, + NV_CHANNEL_SKIP_2G }; typedef uint8 eNVChannelEnabledType; From fce3fc18ff25da9ca380140a876a52c3d5f38178 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Tue, 7 Jun 2016 03:41:15 -0700 Subject: [PATCH 084/203] qcacld-2.0: Chillax the spammy logging * Driver is hardcoded to build with -DDEBUG which upgrades all pr_debugs to be visible regardless of loglevel. This is incredibly spammy and expensive. * Add a kconfig to allow doing this if you really want it, otherwise these messages can be easily enabled using the dynamic debug mechanism. Change-Id: I6c763ca5338bb480a15de6d18dea99e1c81e1dbc --- drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c | 2 ++ drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c | 2 +- drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c | 2 ++ .../staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c | 5 +---- drivers/staging/qcacld-2.0/Kbuild | 9 ++++++--- drivers/staging/qcacld-2.0/Kconfig | 4 ++++ 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c index 245d9cc83ee5..93f0e6f30196 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -1121,7 +1121,9 @@ VOS_STATUS hdd_Ibss_GetStaId(hdd_station_ctx_t *pHddStaCtx, v_MACADDR_t *pMacAdd */ static void __hdd_tx_timeout(struct net_device *dev) { +#if defined( WLAN_DEBUG ) hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); +#endif struct netdev_queue *txq; int i = 0; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c index 1ae10f9d4b53..fbeaa482988e 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c @@ -11289,7 +11289,7 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); int *value = (int *)extra; int sub_cmd = value[0]; - int ret; + int ret = 0; hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c index 69b3152c8e98..733cab96a563 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c @@ -960,7 +960,9 @@ int ol_copy_ramdump(struct ol_softc *scn) static void ramdump_work_handler(struct work_struct *ramdump) { #if !defined(HIF_SDIO) +#ifdef DEBUG int ret; +#endif #endif u_int32_t host_interest_address; u_int32_t dram_dump_values[4]; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c index 262115fee01a..373fd29c4147 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -2653,7 +2653,7 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) goto out; } - pr_info("%s: Suspend completes (D0WOW)\n", __func__); + pr_debug("%s: Suspend completes (D0WOW)\n", __func__); ret = 0; goto out; } @@ -2710,9 +2710,6 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) __func__, runtime_pm ? " for runtime pm" : "", wma_is_wow_mode_selected(temp_module) ? " wow" : " pdev", state.event, val); - printk("%s: Suspend completes%s\n", __func__, - runtime_pm ? " for runtime pm" : ""); - ret = 0; out: diff --git a/drivers/staging/qcacld-2.0/Kbuild b/drivers/staging/qcacld-2.0/Kbuild index 60e5260301bc..41a30f4154df 100644 --- a/drivers/staging/qcacld-2.0/Kbuild +++ b/drivers/staging/qcacld-2.0/Kbuild @@ -132,7 +132,7 @@ endif # Feature flags which are not (currently) configurable via Kconfig #Whether to build debug version -BUILD_DEBUG_VERSION := 1 +BUILD_DEBUG_VERSION ?= 1 #Enable this flag to build driver in diag version BUILD_DIAG_VERSION := 1 @@ -1010,8 +1010,11 @@ CDEFINES += -DTRACE_RECORD \ ifeq ($(BUILD_DEBUG_VERSION),1) CDEFINES += -DWLAN_DEBUG \ -DPE_DEBUG_LOGW \ - -DPE_DEBUG_LOGE \ - -DDEBUG + -DPE_DEBUG_LOGE +endif + +ifeq ($(CONFIG_QCACLD_SPAMMY_DEBUG),y) +CDEFINES += -DDEBUG endif ifeq ($(CONFIG_SLUB_DEBUG_ON),y) diff --git a/drivers/staging/qcacld-2.0/Kconfig b/drivers/staging/qcacld-2.0/Kconfig index 2adf384f1b2a..a925b6464d9e 100644 --- a/drivers/staging/qcacld-2.0/Kconfig +++ b/drivers/staging/qcacld-2.0/Kconfig @@ -9,6 +9,10 @@ config QCA_CLD_WLAN if QCA_CLD_WLAN != n +config CONFIG_QCACLD_SPAMMY_DEBUG + bool "Verbose debug logging" + default n + config QCACLD_WLAN_LFR3 bool "Enable the WLAN Legacy Fast Roaming feature Version 3" default n From fc8a2c9efdc6dee1a109038ccf97f99aed37a73e Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 23 Feb 2016 14:12:49 -0800 Subject: [PATCH 085/203] Silences WLAN, PCIe, and CPU suspend state kernel messages Bug: 27134656 Change-Id: I681ec2171472514489365ca4bfc4ef16d9b344fe --- drivers/pci/host/pci-msm.c | 12 ++++++------ drivers/power/qcom/msm-pm.c | 2 +- .../qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c | 4 ++-- kernel/cpu.c | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index f257c50090ad..220125e4be7d 100755 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -3912,7 +3912,7 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) /* assert PCIe reset link to keep EP in reset */ - PCIE_INFO(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", + PCIE_DBG(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", dev->rc_idx); gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, dev->gpio[MSM_PCIE_GPIO_PERST].on); @@ -4021,7 +4021,7 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) dev->rc_idx, retries); if (pcie_phy_is_ready(dev)) - PCIE_INFO(dev, "PCIe RC%d PHY is ready!\n", dev->rc_idx); + PCIE_DBG(dev, "PCIe RC%d PHY is ready!\n", dev->rc_idx); else { PCIE_ERR(dev, "PCIe PHY RC%d failed to come up!\n", dev->rc_idx); @@ -4041,7 +4041,7 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) /* de-assert PCIe reset link to bring EP out of reset */ - PCIE_INFO(dev, "PCIe: Release the reset of endpoint of RC%d.\n", + PCIE_DBG(dev, "PCIe: Release the reset of endpoint of RC%d.\n", dev->rc_idx); gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, 1 - dev->gpio[MSM_PCIE_GPIO_PERST].on); @@ -4069,9 +4069,9 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) msm_pcie_confirm_linkup(dev, false, false)) { PCIE_DBG(dev, "Link is up after %d checkings\n", link_check_count); - PCIE_INFO(dev, "PCIe RC%d link initialized\n", dev->rc_idx); + PCIE_DBG(dev, "PCIe RC%d link initialized\n", dev->rc_idx); } else { - PCIE_INFO(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", + PCIE_DBG(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", dev->rc_idx); gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, dev->gpio[MSM_PCIE_GPIO_PERST].on); @@ -4144,7 +4144,7 @@ void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options) dev->power_on = false; dev->link_turned_off_counter++; - PCIE_INFO(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", + PCIE_DBG(dev, "PCIe: Assert the reset of endpoint of RC%d.\n", dev->rc_idx); gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, diff --git a/drivers/power/qcom/msm-pm.c b/drivers/power/qcom/msm-pm.c index 040dbf402e6b..c9a8368142c8 100644 --- a/drivers/power/qcom/msm-pm.c +++ b/drivers/power/qcom/msm-pm.c @@ -51,7 +51,7 @@ #define MAX_BUF_SIZE 1024 -static int msm_pm_debug_mask = 1; +static int msm_pm_debug_mask = 0; module_param_named( debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP ); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c index 373fd29c4147..21cda46fe5db 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -2706,7 +2706,7 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) } skip: - pr_info("%s: Suspend completes%s in%s mode event:%d device_state:%d\n", + pr_debug("%s: Suspend completes%s in%s mode event:%d device_state:%d\n", __func__, runtime_pm ? " for runtime pm" : "", wma_is_wow_mode_selected(temp_module) ? " wow" : " pdev", state.event, val); @@ -2846,7 +2846,7 @@ __hif_pci_resume(struct pci_dev *pdev, bool runtime_pm) } #endif - pr_info("%s: Resume completes%s in%s mode\n", __func__, + pr_debug("%s: Resume completes%s in%s mode\n", __func__, runtime_pm ? " for runtime pm" : "", wma_is_wow_mode_selected(temp_module) ? " wow" : " pdev"); out: diff --git a/kernel/cpu.c b/kernel/cpu.c index 8f06b107fd12..68bf4ee8a289 100755 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -565,7 +565,7 @@ int disable_nonboot_cpus(void) */ cpumask_clear(frozen_cpus); - pr_info("Disabling non-boot CPUs ...\n"); + pr_debug("Disabling non-boot CPUs ...\n"); sched_set_boost(0);//Wujialong 20160314 disable sched_boost when going to sleep for_each_online_cpu(cpu) { if (cpu == first_cpu) @@ -610,7 +610,7 @@ void __ref enable_nonboot_cpus(void) if (cpumask_empty(frozen_cpus)) goto out; - pr_info("Enabling non-boot CPUs ...\n"); + pr_debug("Enabling non-boot CPUs ...\n"); arch_enable_nonboot_cpus_begin(); @@ -619,7 +619,7 @@ void __ref enable_nonboot_cpus(void) error = _cpu_up(cpu, 1); trace_suspend_resume(TPS("CPU_ON"), cpu, false); if (!error) { - pr_info("CPU%d is up\n", cpu); + pr_debug("CPU%d is up\n", cpu); continue; } pr_warn("Error taking CPU%d up: %d\n", cpu, error); From 5a1b15bfc37fa7b8b4ffb9f8a28bc7d00523e797 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sat, 2 Jul 2016 23:57:59 -0700 Subject: [PATCH 086/203] qcacld-2.0: Release LA.HB.1.3.2-16800-8x96.0 Change-Id: Ifdd7d7ed0a4ab8d9fbd2fd6ec8bf964ba3626003 --- .../qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h | 6 +++--- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c | 6 +++--- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 2 +- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c | 2 +- .../CORE/MAC/src/pe/lim/limProcessTdls.c | 14 +++++++++++++- .../qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c | 1 - .../qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c | 3 ++- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h index 48b24e0486cb..985297b79711 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -1742,15 +1742,15 @@ backported_cfg80211_vendor_event_alloc(struct wiphy *wiphy, #if defined(CFG80211_DISCONNECTED_V2) || \ (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, - bool from_ap, + bool locally_generated, int reason) { cfg80211_disconnected(dev, reason, NULL, 0, - from_ap, GFP_KERNEL); + locally_generated, GFP_KERNEL); } #else static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, - bool from_ap, + bool locally_generated, int reason) { cfg80211_disconnected(dev, reason, NULL, 0, diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c index 20d320eacf3f..5e01b79c7eec 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c @@ -1019,11 +1019,11 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * pr_info( "wlan: disconnected due to poor signal, rssi is %d dB\n", pRoamInfo->rxRssi); - wlan_hdd_cfg80211_indicate_disconnect(dev, true, - WLAN_REASON_UNSPECIFIED); + wlan_hdd_cfg80211_indicate_disconnect(dev, false, + pRoamInfo->reasonCode); } else - wlan_hdd_cfg80211_indicate_disconnect(dev, true, + wlan_hdd_cfg80211_indicate_disconnect(dev, false, WLAN_REASON_UNSPECIFIED); hddLog(VOS_TRACE_LEVEL_INFO_HIGH, diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c index 1c9405cfd568..e667889b60f6 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -17216,7 +17216,7 @@ int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) */ hddLog(LOG1, FL("Send disconnected event to userspace")); - wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false, + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true, WLAN_REASON_UNSPECIFIED); #endif diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c index 45d335d7e686..bcfcc93d9a9d 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -11568,7 +11568,7 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; /* indicate disconnected event to nl80211 */ - wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true, + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false, WLAN_REASON_UNSPECIFIED); } else if (eConnectionState_Connecting == connState) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c index e30334340fac..dbbbd2405578 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c @@ -2340,8 +2340,20 @@ static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs, * base channel should be less than or equal to channel width of * STA-AP link. So take this setting from the psessionEntry. */ + limLog(pMac, LOG1, + FL("supportedChannelWidthSet %x htSupportedChannelWidthSet %x"), + htCaps->supportedChannelWidthSet, + psessionEntry->htSupportedChannelWidthSet); + pStaDs->htSupportedChannelWidthSet = - psessionEntry->htSupportedChannelWidthSet; + (htCaps->supportedChannelWidthSet < + psessionEntry->htSupportedChannelWidthSet) ? + htCaps->supportedChannelWidthSet : + psessionEntry->htSupportedChannelWidthSet; + + limLog(pMac, LOG1, FL("pStaDs->htSupportedChannelWidthSet %x"), + pStaDs->htSupportedChannelWidthSet); + pStaDs->htMIMOPSState = htCaps->mimoPowerSave ; pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize; pStaDs->htAMpduDensity = htCaps->mpduDensity; diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c index 21cda46fe5db..ceecdcb19f64 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -2534,7 +2534,6 @@ void hif_pci_crash_shutdown(struct pci_dev *pdev) return; } - hif_pci_pm_runtime_exit(sc); adf_os_spin_lock_irqsave(&hif_state->suspend_lock); hif_irq_record(HIF_CRASH, sc); diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c b/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c index 8f41688b61a0..6b4e47910b68 100644 --- a/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c @@ -1377,7 +1377,8 @@ wmi_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param, A_UINT32 } } - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("wmi_dbg_cfg_send: param 0x%x val 0x%x \n ", param, val)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("wmi_dbg_cfg_send: param 0x%x val 0x%x \n", + param, val)); status = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_DBGLOG_CFG_CMDID); From 547a68a41a5c9749e995d221c308305e6839b46f Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Fri, 15 Jul 2016 23:49:34 -0700 Subject: [PATCH 087/203] qcacld-2.0: Update to release LA.HB.1.3.2-19000-8x96.0 Change-Id: I2ff68b64cb2fe07f5e2bfc005957720f7b1a28f5 --- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c | 2 +- .../CORE/HDD/src/wlan_hdd_hostapd.c | 2 +- .../qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c | 5 + .../CORE/SERVICES/HIF/PCIe/if_pci.c | 137 ++++++++++++------ 4 files changed, 102 insertions(+), 44 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c index 2904284e8f9c..1a669d9bfa3e 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c @@ -4974,7 +4974,7 @@ static VOS_STATUS hdd_cfg_get_config(REG_TABLE_ENTRY *reg_table, // ideally we want to return the config to the application // however the config is too big so we just printk() for now #ifdef RETURN_IN_BUFFER - if (curlen <= buflen) + if (curlen < buflen) { // copy string + '\0' memcpy(pCur, configStr, curlen+1); diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c index 0cb56142a711..b4958e9bf554 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c @@ -5955,7 +5955,7 @@ __iw_get_softap_linkspeed(struct net_device *dev, struct iw_request_info *info, kfree(pmacAddress); return -EFAULT; } - pmacAddress[MAC_ADDRESS_STR_LEN] = '\0'; + pmacAddress[MAC_ADDRESS_STR_LEN -1] = '\0'; status = hdd_string_to_hex (pmacAddress, MAC_ADDRESS_STR_LEN, macAddress ); kfree(pmacAddress); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c index 416a56b92da2..d916c1147e52 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c @@ -1275,6 +1275,11 @@ void limHandleFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status, pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; pftSessionEntry->smpsMode = psessionEntry->smpsMode; + if (IS_5G_CH(psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum)) + pftSessionEntry->vdev_nss = pMac->vdev_type_nss_5g.sta; + else + pftSessionEntry->vdev_nss = pMac->vdev_type_nss_2g.sta; + PELOGE(limLog(pMac, LOG1, "%s:created session (%p) with id = %d", __func__, pftSessionEntry, pftSessionEntry->peSessionId);) diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c index ceecdcb19f64..566679558eac 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -2505,63 +2505,116 @@ void hif_pci_shutdown(struct pci_dev *pdev) printk("%s: WLAN host driver shutting down completed!\n", __func__); } -void hif_pci_crash_shutdown(struct pci_dev *pdev) -{ #ifdef TARGET_RAMDUMP_AFTER_KERNEL_PANIC - struct hif_pci_softc *sc; - struct ol_softc *scn; - struct HIF_CE_state *hif_state; - - sc = pci_get_drvdata(pdev); - if (!sc) - return; +#ifdef FEATURE_RUNTIME_PM +static bool is_hif_runtime_active(struct hif_pci_softc *sc) +{ + int pm_state = adf_os_atomic_read(&sc->pm_state); - hif_state = (struct HIF_CE_state *)sc->hif_device; - if (!hif_state) - return; + if (pm_state == HIF_PM_RUNTIME_STATE_ON || + pm_state == HIF_PM_RUNTIME_STATE_NONE) + return true; - scn = sc->ol_sc; - if (!scn) - return; + return false; +} +#else /* ELSE FEATURE_RUNTIME_PM */ +static bool is_hif_runtime_active(struct hif_pci_softc *sc) +{ + return true; +} +#endif /* END FEATURE_RUNTIME_PM */ - if (OL_TRGET_STATUS_RESET == scn->target_status) { - printk("%s: Target is already asserted, ignore!\n", __func__); - return; - } +#ifdef WLAN_DEBUG +static void hif_dump_soc_and_ce_registers(struct hif_pci_softc *sc) +{ + int ret; + struct ol_softc *scn = sc->ol_sc; - if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { - pr_info("%s: Load/unload is in progress, ignore!\n", __func__); - return; - } + ret = hif_pci_check_soc_status(sc); - adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + if (ret) { + pr_err("%s: SOC wakeup Failed\n", __func__); + return; + } - hif_irq_record(HIF_CRASH, sc); + ret = dump_CE_register(scn); -#ifdef DEBUG - if (hif_pci_check_soc_status(scn->hif_sc) - || dump_CE_register(scn)) { - goto out; - } + if (ret) { + pr_err("%s: Failed to dump Copy Engine Registers\n", __func__); + return; + } - dump_CE_debug_register(scn->hif_sc); + dump_CE_debug_register(sc); +} +#else +static void hif_dump_soc_and_ce_registers(struct hif_pci_softc *sc) +{ +} #endif - if (ol_copy_ramdump(scn)) { - goto out; - } +static void hif_dump_crash_debug_info(struct hif_pci_softc *sc) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; + struct ol_softc *scn = sc->ol_sc; + int ret; + + if (!hif_state) + return; + + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + hif_irq_record(HIF_CRASH, sc); + hif_dump_soc_and_ce_registers(sc); - printk("%s: RAM dump collecting completed!\n", __func__); + ret = ol_copy_ramdump(scn); + if (ret) { + pr_err("%s: Failed to Copy Target Memory to Host DDR\n", + __func__); + goto out; + } + + pr_info("%s: RAM dump collecting completed!\n", __func__); out: - adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); - return; -#else - printk("%s: Collecting target RAM dump after kernel panic is disabled!\n", - __func__); - return; -#endif + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); +} + +void hif_pci_crash_shutdown(struct pci_dev *pdev) +{ + struct hif_pci_softc *sc; + struct ol_softc *scn; + + sc = pci_get_drvdata(pdev); + if (!sc) + return; + + scn = sc->ol_sc; + if (!scn) + return; + + if (OL_TRGET_STATUS_RESET == scn->target_status) { + pr_info("%s: Target is already asserted, ignore!\n", __func__); + return; + } + + if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HIF, NULL)) { + pr_info("%s: Target is already asserted, ignore!\n", __func__); + return; + } + + if (is_hif_runtime_active(sc)) + hif_dump_crash_debug_info(sc); + else + pr_info("%s: Runtime Suspended; Ramdump Collection disabled\n", + __func__); + + pr_info("%s: Crash Shutdown Complete\n", __func__); } +#else /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */ +void hif_pci_crash_shutdown(struct pci_dev *pdev) +{ + pr_info("%s: QCA Ramdump Collected Disabled!\n", __func__); +} +#endif #endif #define OL_ATH_PCI_PM_CONTROL 0x44 From 85e23198389c8b1187f8dae0ecfd81869d02e8df Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Tue, 19 Apr 2016 11:45:56 -0700 Subject: [PATCH 088/203] qcacld-2.0: Fix IPV6 IPA Rx property setting During the IPA interface registration, IPV6 Rx property attribute doesn't set properly. This will cause incorrect IPA CM Routing table setting. Change-Id: Iae3ed9338470d2bce59e95b51b34fe5e5561b2c8 CRs-fixed: 1008144 --- drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c index a70067cf2adf..7101626e666c 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ipa.c @@ -3259,10 +3259,10 @@ static int hdd_ipa_register_interface(struct hdd_ipa_priv *hdd_ipa, rx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; #endif - rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA; - rx_prop[IPA_IP_v4].attrib.meta_data = + rx_prop[IPA_IP_v6].attrib.attrib_mask = IPA_FLT_META_DATA; + rx_prop[IPA_IP_v6].attrib.meta_data = htonl(iface_context->adapter->sessionId<< 16); - rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000); + rx_prop[IPA_IP_v6].attrib.meta_data_mask = htonl(0x00FF0000); rx_intf.num_props++; } From c103245a587017911589c4975986cd4d16fd34f7 Mon Sep 17 00:00:00 2001 From: qiliu Date: Mon, 21 Mar 2016 14:40:21 +0800 Subject: [PATCH 089/203] qcacld-2.0: Fix set all-zero address mcast filter There are IPv4/IPv6 filters, we just use IPv4 filter for RXFILTER-ADD/REMOVE now. Correctly update the filters from mc_addr_list. Change-Id: I3457b206fe24e2484ec1f5a6240cbd0bc4a5825a CRs-Fixed: 992500 --- .../staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c index bcfcc93d9a9d..8573cdc381fc 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -4490,7 +4490,7 @@ static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, uint8_t pattern) { int ret; - uint8_t i; + uint8_t i, j; tHalHandle handle; tSirRcvFltMcAddrList *filter; hdd_context_t* hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -4529,19 +4529,20 @@ static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, } vos_mem_zero(filter, sizeof(*filter)); filter->action = action; - for (i = 0; i < adapter->mc_addr_list.mc_cnt; i++) { + for (i = 0, j = 0; i < adapter->mc_addr_list.mc_cnt; i++) { if (!memcmp(adapter->mc_addr_list.addr[i], &pattern, 1)) { - memcpy(filter->multicastAddr[i], + memcpy(filter->multicastAddr[j], adapter->mc_addr_list.addr[i], sizeof(adapter->mc_addr_list.addr[i])); - filter->ulMulticastAddrCnt++; hddLog(LOG1, "%s RX filter : addr =" MAC_ADDRESS_STR, action ? "setting" : "clearing", - MAC_ADDR_ARRAY(filter->multicastAddr[i])); + MAC_ADDR_ARRAY(filter->multicastAddr[j])); + j++; } } + filter->ulMulticastAddrCnt = j; /* Set rx filter */ sme_8023MulticastList(handle, adapter->sessionId, filter); vos_mem_free(filter); From fcd0419f6cfebc8d60ec1e761ef99da60629fe8d Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Mon, 6 Jun 2016 12:16:03 -0700 Subject: [PATCH 090/203] qcacld-2.0: Increase multicast filter count * Firmware actually supports up to 16 addresses. Change-Id: I017a7fd7b2b521d2ea3569a8b5f012c486fa92c7 --- .../qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h | 2 +- .../qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h index 80fb5ab04f51..93db994b2bdf 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h @@ -153,7 +153,7 @@ #define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 2 #endif -#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 5 +#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 16 /* * Specify how much memory the target should allocate for a debug log of * tx PPDU meta-information (how large the PPDU was, when it was sent, diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h index 61e7ed7a38ca..f59da18ee3b3 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h @@ -236,7 +236,7 @@ */ #define CFG_TGT_NUM_TDLS_CONC_BUFFER_STAS 1 -#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 5 +#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 16 /* * Maximum number of VDEV that beacon tx offload will support */ From 25c663f2a29b4c3b14cf32678ed91a22682bb939 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sat, 13 Aug 2016 02:33:02 -0700 Subject: [PATCH 091/203] qcacld-2.0: Update to LA.HB.1.3.2-22100-8x96.0 Change-Id: I78f018d6f03ebfd46367fc8becb338e3af8b68ff --- .../qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c | 4 +++ .../CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++-- .../CORE/HDD/src/wlan_hdd_early_suspend.c | 9 ++--- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c | 8 ++--- .../qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c | 15 ++++++++ .../qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c | 36 ++++++++++++++----- .../MAC/src/pe/lim/limProcessAssocRspFrame.c | 29 +++++++++++++-- .../SVC/src/logging/wlan_logging_sock_svc.c | 24 +++++++------ 8 files changed, 99 insertions(+), 32 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c index 0890e28f5ff4..7d36602b6646 100644 --- a/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -709,6 +709,10 @@ static int tlshim_mgmt_rx_process(void *context, u_int8_t *data, adf_nbuf_pull_head(wbuf, IEEE80211_CCMP_HEADERLEN); adf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN); + /* wh is moved, restore wh with relocated + * ieee80211_frame header. + */ + wh = (struct ieee80211_frame *) adf_nbuf_data(wbuf); rx_pkt->pkt_meta.mpdu_hdr_ptr = adf_nbuf_data(wbuf); rx_pkt->pkt_meta.mpdu_len = adf_nbuf_len(wbuf); rx_pkt->pkt_meta.mpdu_data_len = diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c index e667889b60f6..492db4e42068 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -10199,9 +10199,9 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; if (true == hdd_is_5g_supported(pHddCtx) && - ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) || - (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) || - (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) || + ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) && + (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) && + (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) && (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) { wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c index 87df3d6ce129..c59b0fc5e8bf 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -1812,10 +1812,6 @@ VOS_STATUS hdd_wlan_shutdown(void) hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__); -#ifdef WLAN_FEATURE_LPSS - wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); -#endif - /* If SSR never completes, then do kernel panic. */ hdd_ssr_timer_init(); hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME); @@ -2002,6 +1998,11 @@ VOS_STATUS hdd_wlan_shutdown(void) hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock", __func__); } + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); +#endif + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete" ,__func__); return VOS_STATUS_SUCCESS; diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c index 8573cdc381fc..5a8f7215ca40 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -12878,6 +12878,10 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) if (VOS_FTM_MODE != hdd_get_conparam()) wlan_hdd_logging_sock_deactivate_svc(pHddCtx); +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); +#endif + #ifdef WLAN_KD_READY_NOTIFIER cnss_diag_notify_wlan_close(); nl_srv_exit(pHddCtx->ptt_pid); @@ -12977,10 +12981,6 @@ void __hdd_wlan_exit(void) vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); vos_set_unload_in_progress(TRUE); -#ifdef WLAN_FEATURE_LPSS - wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); -#endif - hdd_close_tx_queues(pHddCtx); //Do all the cleanup before deregistering the driver memdump_deinit(); diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c index d916c1147e52..258208fbd30a 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c @@ -825,6 +825,7 @@ void limFillFTSession(tpAniSirGlobal pMac, tSchBeaconStruct *pBeaconStruct; tANI_U32 selfDot11Mode; ePhyChanBondState cbEnabledMode; + VOS_STATUS vosStatus; pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); if (NULL == pBeaconStruct) { @@ -987,6 +988,20 @@ void limFillFTSession(tpAniSirGlobal pMac, pftSessionEntry->encryptType = psessionEntry->encryptType; #ifdef WLAN_FEATURE_11W pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled; + + if (psessionEntry->limRmfEnabled) { + psessionEntry->pmfComebackTimerInfo.pMac = pMac; + psessionEntry->pmfComebackTimerInfo.sessionID = + psessionEntry->smeSessionId; + vosStatus = vos_timer_init(&psessionEntry->pmfComebackTimer, + VOS_TIMER_TYPE_SW, + limPmfComebackTimerCallback, + (void *)&psessionEntry->pmfComebackTimerInfo); + if (VOS_STATUS_SUCCESS != vosStatus) { + limLog(pMac, LOGP, + FL("cannot init pmf comeback timer.")); + } + } #endif if (pftSessionEntry->limRFBand == SIR_BAND_2_4_GHZ) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c index 6174c193149b..f14f4ea00d2d 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c @@ -717,20 +717,38 @@ void limSendSmeMgmtFrameInd( return; } /*** end limSendSmeListenRsp() ***/ - +/** + * limP2PActionCnf() - handle P2P Action frame confirmation + * @pMac: mac context + * @txCompleteSuccess: P2P Action frame status + * + * Return: 0 on success or error code on failure + */ eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess) { - if (pMac->lim.mgmtFrameSessionId != 0xff) - { - /* The session entry might be invalid(0xff) action confirmation received after - * remain on channel timer expired */ - if (pMac->p2p_ack_ind_cb) - pMac->p2p_ack_ind_cb(pMac->lim.mgmtFrameSessionId, - txCompleteSuccess); + eHalStatus status; + uint32_t mgmt_frame_sessionId; + + status = pe_AcquireGlobalLock(&pMac->lim); + if (HAL_STATUS_SUCCESS(status)) { + mgmt_frame_sessionId = pMac->lim.mgmtFrameSessionId; pMac->lim.mgmtFrameSessionId = 0xff; + pe_ReleaseGlobalLock(&pMac->lim); + if (mgmt_frame_sessionId != 0xff) { + /* + * The session entry might be invalid(0xff) + * action confirmation received after + * remain on channel timer expired + */ + limLog(pMac, LOG1, + FL("mgmt_frame_sessionId %d"), mgmt_frame_sessionId); + if (pMac->p2p_ack_ind_cb) + pMac->p2p_ack_ind_cb(mgmt_frame_sessionId, + txCompleteSuccess); + } } - return eHAL_STATUS_SUCCESS; + return status; } diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c index ca72b9416b00..b53a055c7f11 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -659,8 +659,15 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub if (pAssocRsp->statusCode != eSIR_MAC_SUCCESS_STATUS #ifdef WLAN_FEATURE_11W + /* + * Consider eSIR_MAC_TRY_AGAIN_LATER as failure in re-assoc + * case as waiting for come back time and retrying reassociation + * again will increase roam time. Its better to allow supplicant + * to select new candiadte + */ && (!psessionEntry->limRmfEnabled || - pAssocRsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER) + pAssocRsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER || + (subType == LIM_REASSOC)) #endif /* WLAN_FEATURE_11W */ ) { @@ -730,11 +737,29 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub timeout_value)) { PELOGE(limLog(pMac, LOGE, FL("Failed to start comeback timer."));) + + mlmAssocCnf.resultCode = eSIR_SME_ASSOC_REFUSED; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + /* Delete Pre-auth context for the associated BSS */ + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); + + goto assocReject; } } else { PELOGE(limLog(pMac, LOG1, FL("ASSOC response with eSIR_MAC_TRY_AGAIN_LATER recvd." "But try again time interval IE is wrong."));) + + mlmAssocCnf.resultCode = eSIR_SME_ASSOC_REFUSED; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + /* Delete Pre-auth context for the associated BSS */ + if (limSearchPreAuthList(pMac, pHdr->sa)) + limDeletePreAuthNode(pMac, pHdr->sa); + + goto assocReject; } /* callback will send Assoc again */ /* DO NOT send ASSOC CNF to MLM state machine */ diff --git a/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c index e264c54e7970..1171f070a60b 100644 --- a/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 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. * @@ -42,7 +42,7 @@ #include #include #include "pktlog_ac.h" - +#include #define LOGGING_TRACE(level, args...) \ VOS_TRACE(VOS_MODULE_ID_HDD, level, ## args) @@ -271,8 +271,9 @@ int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) unsigned int *pfilled_length; bool wake_up_thread = false; unsigned long flags; - uint64_t ts; - uint32_t rem; + struct timeval tv; + struct rtc_time tm; + unsigned long local_time; if ((!vos_is_multicast_logging()) || (!gwlan_logging.is_active)) { @@ -287,12 +288,15 @@ int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) pr_info("%s\n", to_be_sent); } else { - /* Format the Log time [Seconds.microseconds] */ - ts = adf_get_boottime(); - rem = do_div(ts, VOS_TIMER_TO_SEC_UNIT); - tlen = snprintf(tbuf, sizeof(tbuf), "[%s][%lu.%06lu] ", - current->comm, - (unsigned long) ts, (unsigned long)rem); + /* Format the Log time [hr:min:sec.microsec] */ + do_gettimeofday(&tv); + /* Convert rtc to local time */ + local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60)); + rtc_time_to_tm(local_time, &tm); + tlen = snprintf(tbuf, sizeof(tbuf), + "[%s][%02d:%02d:%02d.%06lu] ", + current->comm, tm.tm_hour, tm.tm_min, tm.tm_sec, + tv.tv_usec); /* 1+1 indicate '\n'+'\0' */ total_log_len = length + tlen + 1 + 1; From 179599dea9b92ec56e294efcfd92cf7525f03f6a Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Sat, 16 Jul 2016 21:33:45 -0700 Subject: [PATCH 092/203] input: synaptics: s3320: Actually set BTN_TOOL_FINGER keybit This driver is setting BTN_TOOL_FINGER, so we need to set the keybit to make it do anything. Change-Id: I40d258e3a8eb98c849caa724c21aeb59d53b129f Signed-off-by: Sultanxda Signed-off-by: flar2 --- drivers/input/touchscreen/synaptics_driver_s3320.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index b62bb868f7e7..b3adb548d67d 100644 --- a/drivers/input/touchscreen/synaptics_driver_s3320.c +++ b/drivers/input/touchscreen/synaptics_driver_s3320.c @@ -2376,6 +2376,7 @@ static int synaptics_input_init(struct synaptics_ts_data *ts) input_set_capability(ts->input_dev, EV_KEY, KEY_POWER); #endif #endif + set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit); /* For multi touch */ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, (ts->max_x-1), 0, 0); From 824007c1526ec63a379357ab234c3e6a7e9f3020 Mon Sep 17 00:00:00 2001 From: andip71 Date: Mon, 5 Sep 2016 12:35:15 +0200 Subject: [PATCH 093/203] block: add zen scheduler Signed-off-by: flar2 --- block/Kconfig.iosched | 11 ++ block/Makefile | 1 + block/zen-iosched.c | 288 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 block/zen-iosched.c diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 3437270ec213..fa0689ea4d6d 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -89,6 +89,13 @@ config CGROUP_BFQIO filesystem interface. The name of the subsystem will be bfqio. +config IOSCHED_ZEN + tristate "Zen I/O scheduler" + default y + ---help--- + FCFS, dispatches are back-inserted, deadlines ensure fairness. + Should work best with devices where there is no travel delay. + choice prompt "Default I/O scheduler" default DEFAULT_CFQ @@ -121,6 +128,9 @@ choice config DEFAULT_FIOPS bool "FIOPS" if IOSCHED_FIOPS=y + config DEFAULT_ZEN + bool "ZEN" if IOSCHED_ZEN=y + endchoice config DEFAULT_IOSCHED @@ -131,6 +141,7 @@ config DEFAULT_IOSCHED default "noop" if DEFAULT_NOOP default "fiops" if DEFAULT_FIOPS default "sio" if DEFAULT_SIO + default "zen" if DEFAULT_ZEN endmenu diff --git a/block/Makefile b/block/Makefile index dda63b1e3252..2e5c330fec8c 100644 --- a/block/Makefile +++ b/block/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o obj-$(CONFIG_IOSCHED_FIOPS) += fiops-iosched.o obj-$(CONFIG_IOSCHED_SIO) += sio-iosched.o obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o +obj-$(CONFIG_IOSCHED_ZEN) += zen-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o diff --git a/block/zen-iosched.c b/block/zen-iosched.c new file mode 100644 index 000000000000..fa37e4d73de9 --- /dev/null +++ b/block/zen-iosched.c @@ -0,0 +1,288 @@ +/* + * Zen IO scheduler + * Primarily based on Noop, deadline, and SIO IO schedulers. + * + * Copyright (C) 2012 Brandon Berhent + * + * FCFS, dispatches are back-inserted, deadlines ensure fairness. + * Should work best with devices where there is no travel delay. + */ +#include +#include +#include +#include +#include +#include + +enum zen_data_dir { ASYNC, SYNC }; + +static const int sync_expire = HZ / 2; /* max time before a sync is submitted. */ +static const int async_expire = 5 * HZ; /* ditto for async, these limits are SOFT! */ +static const int fifo_batch = 1; + +struct zen_data { + /* Runtime Data */ + /* Requests are only present on fifo_list */ + struct list_head fifo_list[2]; + + unsigned int batching; /* number of sequential requests made */ + + /* tunables */ + int fifo_expire[2]; + int fifo_batch; +}; + +static inline struct zen_data * +zen_get_data(struct request_queue *q) { + return q->elevator->elevator_data; +} + +static void zen_dispatch(struct zen_data *, struct request *); + +static void +zen_merged_requests(struct request_queue *q, struct request *req, + struct request *next) +{ + /* + * if next expires before rq, assign its expire time to arq + * and move into next position (next will be deleted) in fifo + */ + if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) { + if (time_before(next->fifo_time, req->fifo_time)) { + list_move(&req->queuelist, &next->queuelist); + req->fifo_time = next->fifo_time; + } + } + + /* next request is gone */ + rq_fifo_clear(next); +} + +static void zen_add_request(struct request_queue *q, struct request *rq) +{ + struct zen_data *zdata = zen_get_data(q); + const int sync = rq_is_sync(rq); + + if (zdata->fifo_expire[sync]) { + rq->fifo_time = jiffies + zdata->fifo_expire[sync]; + list_add_tail(&rq->queuelist, &zdata->fifo_list[sync]); + } +} + +static void zen_dispatch(struct zen_data *zdata, struct request *rq) +{ + /* Remove request from list and dispatch it */ + rq_fifo_clear(rq); + elv_dispatch_add_tail(rq->q, rq); + + /* Increment # of sequential requests */ + zdata->batching++; +} + +/* + * get the first expired request in direction ddir + */ +static struct request * +zen_expired_request(struct zen_data *zdata, int ddir) +{ + struct request *rq; + + if (list_empty(&zdata->fifo_list[ddir])) + return NULL; + + rq = rq_entry_fifo(zdata->fifo_list[ddir].next); + if (time_after(jiffies, rq->fifo_time)) + return rq; + + return NULL; +} + +/* + * zen_check_fifo returns 0 if there are no expired requests on the fifo, + * otherwise it returns the next expired request + */ +static struct request * +zen_check_fifo(struct zen_data *zdata) +{ + struct request *rq_sync = zen_expired_request(zdata, SYNC); + struct request *rq_async = zen_expired_request(zdata, ASYNC); + + if (rq_async && rq_sync) { + if (time_after(rq_async->fifo_time, rq_sync->fifo_time)) + return rq_sync; + } else if (rq_sync) { + return rq_sync; + } else if (rq_async) { + return rq_async; + } + + return 0; +} + +static struct request * +zen_choose_request(struct zen_data *zdata) +{ + /* + * Retrieve request from available fifo list. + * Synchronous requests have priority over asynchronous. + */ + if (!list_empty(&zdata->fifo_list[SYNC])) + return rq_entry_fifo(zdata->fifo_list[SYNC].next); + if (!list_empty(&zdata->fifo_list[ASYNC])) + return rq_entry_fifo(zdata->fifo_list[ASYNC].next); + + return NULL; +} + +static int zen_dispatch_requests(struct request_queue *q, int force) +{ + struct zen_data *zdata = zen_get_data(q); + struct request *rq = NULL; + + /* Check for and issue expired requests */ + if (zdata->batching > zdata->fifo_batch) { + zdata->batching = 0; + rq = zen_check_fifo(zdata); + } + + if (!rq) { + rq = zen_choose_request(zdata); + if (!rq) + return 0; + } + + zen_dispatch(zdata, rq); + + return 1; +} + +static int zen_init_queue(struct request_queue *q, struct elevator_type *e) +{ + struct zen_data *zdata; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; + + zdata = kmalloc_node(sizeof(*zdata), GFP_KERNEL, q->node); + if (!zdata) { + kobject_put(&eq->kobj); + return -ENOMEM; + } + eq->elevator_data = zdata; + + INIT_LIST_HEAD(&zdata->fifo_list[SYNC]); + INIT_LIST_HEAD(&zdata->fifo_list[ASYNC]); + zdata->fifo_expire[SYNC] = sync_expire; + zdata->fifo_expire[ASYNC] = async_expire; + zdata->fifo_batch = fifo_batch; + + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); + return 0; +} + +static void zen_exit_queue(struct elevator_queue *e) +{ + struct zen_data *zdata = e->elevator_data; + + BUG_ON(!list_empty(&zdata->fifo_list[SYNC])); + BUG_ON(!list_empty(&zdata->fifo_list[ASYNC])); + kfree(zdata); +} + +/* Sysfs */ +static ssize_t +zen_var_show(int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +zen_var_store(int *var, const char *page, size_t count) +{ + *var = simple_strtol(page, NULL, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct zen_data *zdata = e->elevator_data; \ + int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return zen_var_show(__data, (page)); \ +} +SHOW_FUNCTION(zen_sync_expire_show, zdata->fifo_expire[SYNC], 1); +SHOW_FUNCTION(zen_async_expire_show, zdata->fifo_expire[ASYNC], 1); +SHOW_FUNCTION(zen_fifo_batch_show, zdata->fifo_batch, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct zen_data *zdata = e->elevator_data; \ + int __data; \ + int ret = zen_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(zen_sync_expire_store, &zdata->fifo_expire[SYNC], 0, INT_MAX, 1); +STORE_FUNCTION(zen_async_expire_store, &zdata->fifo_expire[ASYNC], 0, INT_MAX, 1); +STORE_FUNCTION(zen_fifo_batch_store, &zdata->fifo_batch, 0, INT_MAX, 0); +#undef STORE_FUNCTION + +#define DD_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, zen_##name##_show, \ + zen_##name##_store) + +static struct elv_fs_entry zen_attrs[] = { + DD_ATTR(sync_expire), + DD_ATTR(async_expire), + DD_ATTR(fifo_batch), + __ATTR_NULL +}; + +static struct elevator_type iosched_zen = { + .ops = { + .elevator_merge_req_fn = zen_merged_requests, + .elevator_dispatch_fn = zen_dispatch_requests, + .elevator_add_req_fn = zen_add_request, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_init_fn = zen_init_queue, + .elevator_exit_fn = zen_exit_queue, + }, + .elevator_attrs = zen_attrs, + .elevator_name = "zen", + .elevator_owner = THIS_MODULE, +}; + +static int __init zen_init(void) +{ + return elv_register(&iosched_zen); +} + +static void __exit zen_exit(void) +{ + elv_unregister(&iosched_zen); +} + +module_init(zen_init); +module_exit(zen_exit); + + +MODULE_AUTHOR("Brandon Berhent"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Zen IO scheduler"); +MODULE_VERSION("1.0"); From d53c2ee78a180c1f87deb1733532c792ad78ade6 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 9 Sep 2016 00:23:16 -0400 Subject: [PATCH 094/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index c62061e041e1..d647bd495019 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -276,6 +276,7 @@ CONFIG_BLOCK_COMPAT=y CONFIG_IOSCHED_NOOP=y # CONFIG_IOSCHED_TEST is not set CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_ZEN=y CONFIG_IOSCHED_CFQ=y CONFIG_IOSCHED_FIOPS=y CONFIG_IOSCHED_SIO=y @@ -287,6 +288,7 @@ CONFIG_CGROUP_BFQIO=y # CONFIG_DEFAULT_NOOP is not set # CONFIG_DEFAULT_SIO is not set CONFIG_DEFAULT_FIOPS=y +# CONFIG_DEFAULT_ZEN is not set CONFIG_DEFAULT_IOSCHED="fiops" CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y @@ -3602,6 +3604,27 @@ CONFIG_ION_MSM=y # CONFIG_DGAP is not set # CONFIG_GS_FPGABOOT is not set +# +# Qualcomm Atheros CLD WLAN module +# +CONFIG_QCA_CLD_WLAN=m +# CONFIG_CONFIG_QCACLD_SPAMMY_DEBUG is not set +CONFIG_QCACLD_WLAN_LFR3=y +CONFIG_PRIMA_WLAN_OKC=y +CONFIG_PRIMA_WLAN_11AC_HIGH_TP=y +CONFIG_WLAN_FEATURE_11W=y +CONFIG_WLAN_FEATURE_LPSS=y +CONFIG_QCOM_VOWIFI_11R=y +CONFIG_WLAN_FEATURE_NAN=y +CONFIG_QCOM_TDLS=y +CONFIG_QCOM_LTE_COEX=y +# CONFIG_WLAN_SYNC_TSF is not set +CONFIG_WLAN_FEATURE_MEMDUMP=y +CONFIG_WLAN_OFFLOAD_PACKETS=y +CONFIG_QCA_WIFI_AUTOMOTIVE_CONC=y +CONFIG_WLAN_UDP_RESPONSE_OFFLOAD=y +CONFIG_WLAN_FEATURE_RX_WAKELOCK=y + # # Qualcomm MSM specific device drivers # From d74a8982cf44441c7490056f7cfa071dcbafabf2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 10 Jul 2016 10:04:02 +0200 Subject: [PATCH 095/203] BACKPORT: tcp: make challenge acks less predictable (cherry picked from commit 75ff39ccc1bd5d3c455b6822ab09e533c551f758) Yue Cao claims that current host rate limiting of challenge ACKS (RFC 5961) could leak enough information to allow a patient attacker to hijack TCP sessions. He will soon provide details in an academic paper. This patch increases the default limit from 100 to 1000, and adds some randomization so that the attacker can no longer hijack sessions without spending a considerable amount of probes. Based on initial analysis and patch from Linus. Note that we also have per socket rate limiting, so it is tempting to remove the host limit in the future. v2: randomize the count of challenge acks per second, not the period. Fixes: 282f23c6ee34 ("tcp: implement RFC 5961 3.2") Reported-by: Yue Cao Signed-off-by: Eric Dumazet Suggested-by: Linus Torvalds Cc: Yuchung Cheng Cc: Neal Cardwell Acked-by: Neal Cardwell Acked-by: Yuchung Cheng Signed-off-by: David S. Miller Change-Id: Ib46ba66f5e4a5a7c81bfccd7b0aa83c3d9e1b3bb Bug: 30809774 --- net/ipv4/tcp_input.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 055b7ddf9fb8..212fe15905e4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -88,7 +88,7 @@ int sysctl_tcp_adv_win_scale __read_mostly = 1; EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); /* rfc5961 challenge ack rate limiting */ -int sysctl_tcp_challenge_ack_limit = 100; +int sysctl_tcp_challenge_ack_limit = 1000; int sysctl_tcp_stdurg __read_mostly; int sysctl_tcp_rfc1337 __read_mostly; @@ -3326,12 +3326,18 @@ static void tcp_send_challenge_ack(struct sock *sk) static u32 challenge_timestamp; static unsigned int challenge_count; u32 now = jiffies / HZ; + u32 count; if (now != challenge_timestamp) { + u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1; + challenge_timestamp = now; - challenge_count = 0; + WRITE_ONCE(challenge_count, half + + prandom_u32_max(sysctl_tcp_challenge_ack_limit)); } - if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { + count = READ_ONCE(challenge_count); + if (count > 0) { + WRITE_ONCE(challenge_count, count - 1); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); tcp_send_ack(sk); } From ff0682f3de30866be4fca2d1b7d4b0bf284aae49 Mon Sep 17 00:00:00 2001 From: Whoopie Date: Fri, 19 Aug 2016 18:56:22 +0200 Subject: [PATCH 096/203] usb: gadget: mass_storage: added sysfs entry for cdrom to LUNs This patch adds a "cdrom" sysfs entry for each mass_storage LUN, just like "ro" sysfs entry. This allows switching between USB and CD-ROM emulation without reinserting the module or recompiling the kernel. The patch is based on http://review.cyanogenmod.org/#/c/110711/, but adopted for kernel 3.18. The changes storage_common.c are already available in kernel 3.18 (commit 864328ef8e735403f85b768284001a4187d6868f). Change-Id: Idf83c74815b1ad370428ab9d3e5503d5f7bcd3b6 --- drivers/usb/gadget/function/f_mass_storage.c | 27 ++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index d07f6682bcfd..5619181e16e6 100755 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3020,6 +3020,13 @@ static int fsg_main_thread(void *common_) /*************************** DEVICE ATTRIBUTES ***************************/ +static ssize_t cdrom_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + + return fsg_show_cdrom(curlun, buf); +} + static ssize_t ro_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fsg_lun *curlun = fsg_lun_from_dev(dev); @@ -3044,6 +3051,15 @@ static ssize_t file_show(struct device *dev, struct device_attribute *attr, return fsg_show_file(curlun, filesem, buf); } +static ssize_t cdrom_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + + return fsg_store_cdrom(curlun, filesem, buf, count); +} + static ssize_t ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -3070,12 +3086,12 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr, return fsg_store_file(curlun, filesem, buf, count); } +static DEVICE_ATTR_RW(cdrom); static DEVICE_ATTR_RW(ro); static DEVICE_ATTR_RW(nofua); static DEVICE_ATTR_RW(file); static DEVICE_ATTR(perf, 0644, fsg_show_perf, fsg_store_perf); -static struct device_attribute dev_attr_ro_cdrom = __ATTR_RO(ro); static struct device_attribute dev_attr_file_nonremovable = __ATTR_RO(file); @@ -3221,6 +3237,7 @@ static inline void fsg_common_remove_sysfs(struct fsg_lun *lun) * so we don't differentiate between removing e.g. dev_attr_ro_cdrom * and dev_attr_ro */ + device_remove_file(&lun->dev, &dev_attr_cdrom); device_remove_file(&lun->dev, &dev_attr_ro); device_remove_file(&lun->dev, &dev_attr_file); device_remove_file(&lun->dev, &dev_attr_perf); @@ -3346,10 +3363,10 @@ static inline int fsg_common_add_sysfs(struct fsg_common *common, return rc; } - rc = device_create_file(&lun->dev, - lun->cdrom - ? &dev_attr_ro_cdrom - : &dev_attr_ro); + rc = device_create_file(&lun->dev, &dev_attr_cdrom); + if (rc) + goto error; + rc = device_create_file(&lun->dev, &dev_attr_ro); if (rc) goto error; rc = device_create_file(&lun->dev, From d84e4c53c880263555954d9c1f103a730e2ee81d Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 9 Sep 2016 22:01:57 -0400 Subject: [PATCH 097/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index d647bd495019..341c1a71299b 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.16" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.17" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From eba5b70b972ede9de49e078c9ee2220f485ab99e Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 11 Sep 2016 15:17:49 -0400 Subject: [PATCH 098/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 341c1a71299b..9bf38c8af27e 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.17" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.18" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From cd9bd184b066b9b78dca31ae9b0c0e98ea02ef25 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 11 Sep 2016 15:50:07 -0400 Subject: [PATCH 099/203] cpufreq; add elementalx governor --- drivers/cpufreq/Kconfig | 20 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq_elementalx.c | 562 +++++++++++++++++++++++++++ drivers/cpufreq/cpufreq_governor.c | 27 +- drivers/cpufreq/cpufreq_governor.h | 20 + 5 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 drivers/cpufreq/cpufreq_elementalx.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index a5bb7dc7ef55..08d7ac2219cb 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -122,6 +122,13 @@ config CPU_FREQ_DEFAULT_GOV_INTERACTIVE loading your cpufreq low-level hardware driver, using the 'interactive' governor for latency-sensitive workloads. +config CPU_FREQ_DEFAULT_GOV_ELEMENTALX + bool "elementalx" + select CPU_FREQ_GOV_ELEMENTALX + select CPU_FREQ_GOV_PERFORMANCE + help + Use the CPUFreq governor 'elementalx' as default. + endchoice config CPU_FREQ_GOV_PERFORMANCE @@ -196,6 +203,19 @@ config CPU_FREQ_GOV_INTERACTIVE If in doubt, say N. +config CPU_FREQ_GOV_ELEMENTALX + tristate "'elementalx' cpufreq policy governor" + select CPU_FREQ_TABLE + help + 'elementalx' - This driver adds a dynamic cpufreq policy governor. + + To compile this driver as a module, choose M here: the + module will be called cpufreq_elementalx. + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + config CPU_FREQ_GOV_CONSERVATIVE tristate "'conservative' cpufreq governor" depends on CPU_FREQ diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 66a9e4c6da65..e8a5092dddaa 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o +obj-$(CONFIG_CPU_FREQ_GOV_ELEMENTALX) += cpufreq_elementalx.o obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_BOOST) += cpu-boost.o diff --git a/drivers/cpufreq/cpufreq_elementalx.c b/drivers/cpufreq/cpufreq_elementalx.c new file mode 100644 index 000000000000..8d203e79a958 --- /dev/null +++ b/drivers/cpufreq/cpufreq_elementalx.c @@ -0,0 +1,562 @@ +/* + * drivers/cpufreq/cpufreq_elementalx.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi + * Jun Nakajima + * (C) 2015 Aaron Segaert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "cpufreq_governor.h" + +/* elementalx governor macros */ +#define DEF_FREQUENCY_UP_THRESHOLD (90) +#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (20) +#define DEF_ACTIVE_FLOOR_FREQ (960000) +#define MIN_SAMPLING_RATE (10000) +#define DEF_SAMPLING_DOWN_FACTOR (4) +#define MAX_SAMPLING_DOWN_FACTOR (20) +#define FREQ_NEED_BURST(x) (x < 800000 ? 1 : 0) +#define MAX(x,y) (x > y ? x : y) +#define MIN(x,y) (x < y ? x : y) +#define TABLE_SIZE 12 +#define TABLE_NUM 6 + +static DEFINE_PER_CPU(struct ex_cpu_dbs_info_s, ex_cpu_dbs_info); + +static DEFINE_PER_CPU(struct ex_dbs_tuners *, cached_tuners); + +static unsigned int up_threshold_level[2] __read_mostly = {95, 85}; + +static struct ex_governor_data { + unsigned int active_floor_freq; + unsigned int prev_load; +} ex_data = { + .active_floor_freq = DEF_ACTIVE_FLOOR_FREQ, + .prev_load = 0, +}; + +static unsigned int tblmap[TABLE_NUM][TABLE_SIZE] __read_mostly = { + + //table 0 + { + 616400, + 757200, + 840000, + 960000, + 1248000, + 1324800, + 1478400, + 1593600, + 1632000, + 1728000, + 1824000, + 1996000, + }, + + //table 1 + { + 773040, + 899760, + 1014960, + 1072560, + 1248000, + 1324800, + 1478400, + 1593600, + 1632000, + 1728000, + 1824000, + 1996000, + }, + + //table 2 + { + 851100, + 956700, + 1052700, + 1100700, + 1350400, + 1416000, + 1593600, + 1708800, + 1824000, + 1996000, + 2073000, + 2150000, + }, + + //table 3 + { + 616400, + 757200, + 840000, + 960000, + 1248000, + 1324800, + 1478400, + 1593600, + 1593600, + 1593600, + 1593600, + 1593600, + }, + + //table 4 + { + 773040, + 899760, + 1014960, + 1072560, + 1248000, + 1324800, + 1478400, + 1593600, + 1593600, + 1593600, + 1593600, + 1593600, + }, + + //table 5 + { + 851100, + 956700, + 1052700, + 1100700, + 1324800, + 1416000, + 1593600, + 1708800, + 1708800, + 1708800, + 1708800, + 1708800, + } + +}; + +static inline int get_cpu_freq_index(unsigned int freq, struct dbs_data *dbs_data) +{ + static int saved_index = 0; + int index; + + if (!dbs_data->freq_table) { + pr_warn("tbl is NULL, use previous value %d\n", saved_index); + return saved_index; + } + + for (index = 0; (dbs_data->freq_table[index].frequency != CPUFREQ_TABLE_END); index++) { + if (dbs_data->freq_table[index].frequency >= freq) { + saved_index = index; + break; + } + } + + return index; +} + +static inline unsigned int ex_freq_increase(struct cpufreq_policy *p, unsigned int freq) +{ + if (freq > p->max) { + return p->max; + } + + return freq; +} + +static void ex_check_cpu(int cpu, unsigned int load) +{ + struct ex_cpu_dbs_info_s *dbs_info = &per_cpu(ex_cpu_dbs_info, cpu); + struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy; + struct dbs_data *dbs_data = policy->governor_data; + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int max_load_freq = 0, freq_next = 0; + unsigned int j, avg_load, cur_freq, max_freq, target_freq = 0; + + cur_freq = policy->cur; + max_freq = policy->max; + + for_each_cpu(j, policy->cpus) { + if (load > max_load_freq) + max_load_freq = load * policy->cur; + } + avg_load = (ex_data.prev_load + load) >> 1; + + if (max_load_freq > up_threshold_level[1] * cur_freq) { + int index = get_cpu_freq_index(cur_freq, dbs_data); + + if (FREQ_NEED_BURST(cur_freq) && + load > up_threshold_level[0]) { + freq_next = max_freq; + } + + else if (avg_load > up_threshold_level[0]) { + freq_next = tblmap[2 + ex_tuners->powersave][index]; + } + + else if (avg_load <= up_threshold_level[1]) { + freq_next = tblmap[0 + ex_tuners->powersave][index]; + } + + else { + if (load > up_threshold_level[0]) { + freq_next = tblmap[2 + ex_tuners->powersave][index]; + } + + else { + freq_next = tblmap[1 + ex_tuners->powersave][index]; + } + } + + target_freq = ex_freq_increase(policy, freq_next); + + __cpufreq_driver_target(policy, target_freq, CPUFREQ_RELATION_H); + + if (target_freq > ex_data.active_floor_freq) + dbs_info->down_floor = 0; + + goto finished; + } + + if (cur_freq == policy->min) + goto finished; + + if (cur_freq >= ex_data.active_floor_freq) { + if (++dbs_info->down_floor > ex_tuners->sampling_down_factor) + dbs_info->down_floor = 0; + } else { + dbs_info->down_floor = 0; + } + + if (max_load_freq < + (ex_tuners->up_threshold - ex_tuners->down_differential) * + cur_freq) { + + freq_next = max_load_freq / + (ex_tuners->up_threshold - + ex_tuners->down_differential); + + if (dbs_info->down_floor) { + freq_next = MAX(freq_next, ex_data.active_floor_freq); + } else { + freq_next = MAX(freq_next, policy->min); + if (freq_next < ex_data.active_floor_freq) + dbs_info->down_floor = ex_tuners->sampling_down_factor; + } + + __cpufreq_driver_target(policy, freq_next, + CPUFREQ_RELATION_L); + } + +finished: + ex_data.prev_load = load; + return; +} + +static void ex_dbs_timer(struct work_struct *work) +{ + struct ex_cpu_dbs_info_s *dbs_info = container_of(work, + struct ex_cpu_dbs_info_s, cdbs.work.work); + unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; + struct ex_cpu_dbs_info_s *core_dbs_info = &per_cpu(ex_cpu_dbs_info, + cpu); + struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data; + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + int delay = delay_for_sampling_rate(ex_tuners->sampling_rate); + bool modify_all = true; + + mutex_lock(&core_dbs_info->cdbs.timer_mutex); + if (!need_load_eval(&core_dbs_info->cdbs, ex_tuners->sampling_rate)) + modify_all = false; + else + dbs_check_cpu(dbs_data, cpu); + + gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all); + mutex_unlock(&core_dbs_info->cdbs.timer_mutex); +} + +/************************** sysfs interface ************************/ +static struct common_dbs_data ex_dbs_cdata; + +static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + ex_tuners->sampling_rate = max(input, dbs_data->min_sampling_rate); + return count; +} + +static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 100 || input <= ex_tuners->down_differential) + return -EINVAL; + + ex_tuners->up_threshold = input; + return count; +} + +static ssize_t store_down_differential(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 100 || input >= ex_tuners->up_threshold) + return -EINVAL; + + ex_tuners->down_differential = input; + return count; +} + +static ssize_t store_active_floor_freq(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + ex_tuners->active_floor_freq = input; + ex_data.active_floor_freq = ex_tuners->active_floor_freq; + return count; +} + +static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 0) + return -EINVAL; + + ex_tuners->sampling_down_factor = input; + return count; +} + +static ssize_t store_powersave(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 1) + return -EINVAL; + + if (input == 0) + ex_tuners->powersave = input; + else if (input == 1) + ex_tuners->powersave = 3; + + return count; +} + +show_store_one(ex, sampling_rate); +show_store_one(ex, up_threshold); +show_store_one(ex, down_differential); +show_store_one(ex, active_floor_freq); +show_store_one(ex, sampling_down_factor); +show_store_one(ex, powersave); +declare_show_sampling_rate_min(ex); + +gov_sys_pol_attr_rw(sampling_rate); +gov_sys_pol_attr_rw(up_threshold); +gov_sys_pol_attr_rw(down_differential); +gov_sys_pol_attr_rw(active_floor_freq); +gov_sys_pol_attr_rw(sampling_down_factor); +gov_sys_pol_attr_rw(powersave); +gov_sys_pol_attr_ro(sampling_rate_min); + +static struct attribute *dbs_attributes_gov_sys[] = { + &sampling_rate_min_gov_sys.attr, + &sampling_rate_gov_sys.attr, + &up_threshold_gov_sys.attr, + &down_differential_gov_sys.attr, + &active_floor_freq_gov_sys.attr, + &sampling_down_factor_gov_sys.attr, + &powersave_gov_sys.attr, + NULL +}; + +static struct attribute_group ex_attr_group_gov_sys = { + .attrs = dbs_attributes_gov_sys, + .name = "elementalx", +}; + +static struct attribute *dbs_attributes_gov_pol[] = { + &sampling_rate_min_gov_pol.attr, + &sampling_rate_gov_pol.attr, + &up_threshold_gov_pol.attr, + &down_differential_gov_pol.attr, + &active_floor_freq_gov_pol.attr, + &sampling_down_factor_gov_pol.attr, + &powersave_gov_pol.attr, + NULL +}; + +static struct attribute_group ex_attr_group_gov_pol = { + .attrs = dbs_attributes_gov_pol, + .name = "elementalx", +}; + +/************************** sysfs end ************************/ + +static void save_tuners(struct cpufreq_policy *policy, + struct ex_dbs_tuners *tuners) +{ + int cpu; + + if (have_governor_per_policy()) + cpu = cpumask_first(policy->related_cpus); + else + cpu = 0; + + WARN_ON(per_cpu(cached_tuners, cpu) && + per_cpu(cached_tuners, cpu) != tuners); + per_cpu(cached_tuners, cpu) = tuners; +} + +static struct ex_dbs_tuners *alloc_tuners(struct cpufreq_policy *policy) +{ + struct ex_dbs_tuners *tuners; + + tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); + if (!tuners) { + pr_err("%s: kzalloc failed\n", __func__); + return ERR_PTR(-ENOMEM); + } + + tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; + tuners->down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL; + tuners->ignore_nice_load = 0; + tuners->active_floor_freq = DEF_ACTIVE_FLOOR_FREQ; + tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; + tuners->powersave = 0; + + save_tuners(policy, tuners); + + return tuners; +} + +static struct ex_dbs_tuners *restore_tuners(struct cpufreq_policy *policy) +{ + int cpu; + + if (have_governor_per_policy()) + cpu = cpumask_first(policy->related_cpus); + else + cpu = 0; + + return per_cpu(cached_tuners, cpu); +} + +static int ex_init(struct dbs_data *dbs_data, struct cpufreq_policy *policy) +{ + struct ex_dbs_tuners *tuners; + + tuners = restore_tuners(policy); + if (!tuners) { + tuners = alloc_tuners(policy); + if (IS_ERR(tuners)) + return PTR_ERR(tuners); + } + + dbs_data->tuners = tuners; + dbs_data->min_sampling_rate = MIN_SAMPLING_RATE; + dbs_data->freq_table = cpufreq_frequency_get_table(policy->cpu); + + mutex_init(&dbs_data->mutex); + + return 0; +} + +static void ex_exit(struct dbs_data *dbs_data) +{ + //nothing to do +} + +define_get_cpu_dbs_routines(ex_cpu_dbs_info); + +static struct common_dbs_data ex_dbs_cdata = { + .governor = GOV_ELEMENTALX, + .attr_group_gov_sys = &ex_attr_group_gov_sys, + .attr_group_gov_pol = &ex_attr_group_gov_pol, + .get_cpu_cdbs = get_cpu_cdbs, + .get_cpu_dbs_info_s = get_cpu_dbs_info_s, + .gov_dbs_timer = ex_dbs_timer, + .gov_check_cpu = ex_check_cpu, + .init_ex = ex_init, + .exit = ex_exit, +}; + +static int ex_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &ex_dbs_cdata, event); +} + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ELEMENTALX +static +#endif +struct cpufreq_governor cpufreq_gov_elementalx = { + .name = "elementalx", + .governor = ex_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_elementalx); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + int cpu; + + cpufreq_unregister_governor(&cpufreq_gov_elementalx); + for_each_possible_cpu(cpu) { + kfree(per_cpu(cached_tuners, cpu)); + per_cpu(cached_tuners, cpu) = NULL; + } + +} + +MODULE_AUTHOR("Aaron Segaert "); +MODULE_DESCRIPTION("'cpufreq_elementalx' - multiphase cpufreq governor"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ELEMENTALX +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 1b44496b2d2b..de2e98ca9273 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -35,6 +35,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu); struct od_dbs_tuners *od_tuners = dbs_data->tuners; struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; struct cpufreq_policy *policy; unsigned int sampling_rate; unsigned int max_load = 0; @@ -55,6 +56,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) sampling_rate *= od_dbs_info->rate_mult; ignore_nice = od_tuners->ignore_nice_load; + } else if (dbs_data->cdata->governor == GOV_ELEMENTALX) { + sampling_rate = ex_tuners->sampling_rate; + ignore_nice = ex_tuners->ignore_nice_load; } else { sampling_rate = cs_tuners->sampling_rate; ignore_nice = cs_tuners->ignore_nice_load; @@ -233,6 +237,9 @@ static void set_sampling_rate(struct dbs_data *dbs_data, if (dbs_data->cdata->governor == GOV_CONSERVATIVE) { struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; cs_tuners->sampling_rate = sampling_rate; + } else if (dbs_data->cdata->governor == GOV_ELEMENTALX) { + struct ex_dbs_tuners *ex_tuners = dbs_data->tuners; + ex_tuners->sampling_rate = sampling_rate; } else { struct od_dbs_tuners *od_tuners = dbs_data->tuners; od_tuners->sampling_rate = sampling_rate; @@ -245,9 +252,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, struct dbs_data *dbs_data; struct od_cpu_dbs_info_s *od_dbs_info = NULL; struct cs_cpu_dbs_info_s *cs_dbs_info = NULL; + struct ex_cpu_dbs_info_s *ex_dbs_info = NULL; struct od_ops *od_ops = NULL; struct od_dbs_tuners *od_tuners = NULL; struct cs_dbs_tuners *cs_tuners = NULL; + struct ex_dbs_tuners *ex_tuners = NULL; struct cpu_dbs_common_info *cpu_cdbs; unsigned int sampling_rate, latency, ignore_nice, j, cpu = policy->cpu; int io_busy = 0; @@ -278,7 +287,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_data->cdata = cdata; dbs_data->usage_count = 1; - rc = cdata->init(dbs_data); + + if (cdata->governor == GOV_ELEMENTALX) + rc = cdata->init_ex(dbs_data, policy); + else + rc = cdata->init(dbs_data); + if (rc) { pr_err("%s: POLICY_INIT: init() failed\n", __func__); kfree(dbs_data); @@ -353,6 +367,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); sampling_rate = cs_tuners->sampling_rate; ignore_nice = cs_tuners->ignore_nice_load; + } else if (dbs_data->cdata->governor == GOV_ELEMENTALX) { + ex_tuners = dbs_data->tuners; + ex_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); + sampling_rate = ex_tuners->sampling_rate; + ignore_nice = ex_tuners->ignore_nice_load; } else { od_tuners = dbs_data->tuners; od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); @@ -397,6 +416,9 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, cs_dbs_info->down_skip = 0; cs_dbs_info->enable = 1; cs_dbs_info->requested_freq = policy->cur; + } else if (dbs_data->cdata->governor == GOV_ELEMENTALX) { + ex_dbs_info->down_floor = 0; + ex_dbs_info->enable = 1; } else { od_dbs_info->rate_mult = 1; od_dbs_info->sample_type = OD_NORMAL_SAMPLE; @@ -416,6 +438,9 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (dbs_data->cdata->governor == GOV_CONSERVATIVE) cs_dbs_info->enable = 0; + if (dbs_data->cdata->governor == GOV_ELEMENTALX) + ex_dbs_info->enable = 0; + gov_cancel_work(dbs_data, policy); mutex_lock(&dbs_data->mutex); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index cc401d147e72..203e618f27e2 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -126,6 +126,7 @@ static void *get_cpu_dbs_info_s(int cpu) \ * cdbs: common dbs * od_*: On-demand governor * cs_*: Conservative governor + * ex_*: ElementalX governor */ /* Per cpu structures */ @@ -169,6 +170,12 @@ struct cs_cpu_dbs_info_s { unsigned int enable:1; }; +struct ex_cpu_dbs_info_s { + struct cpu_dbs_common_info cdbs; + unsigned int down_floor; + unsigned int enable:1; +}; + /* Per policy Governors sysfs tunables */ struct od_dbs_tuners { unsigned int ignore_nice_load; @@ -188,12 +195,23 @@ struct cs_dbs_tuners { unsigned int freq_step; }; +struct ex_dbs_tuners { + unsigned int ignore_nice_load; + unsigned int sampling_rate; + unsigned int up_threshold; + unsigned int down_differential; + unsigned int active_floor_freq; + unsigned int sampling_down_factor; + unsigned int powersave; +}; + /* Common Governor data across policies */ struct dbs_data; struct common_dbs_data { /* Common across governors */ #define GOV_ONDEMAND 0 #define GOV_CONSERVATIVE 1 + #define GOV_ELEMENTALX 2 int governor; struct attribute_group *attr_group_gov_sys; /* one governor - system */ struct attribute_group *attr_group_gov_pol; /* one governor - policy */ @@ -209,6 +227,7 @@ struct common_dbs_data { void (*gov_dbs_timer)(struct work_struct *work); void (*gov_check_cpu)(int cpu, unsigned int load); int (*init)(struct dbs_data *dbs_data); + int (*init_ex)(struct dbs_data *dbs_data, struct cpufreq_policy *policy); void (*exit)(struct dbs_data *dbs_data); /* Governor specific ops, see below */ @@ -219,6 +238,7 @@ struct common_dbs_data { struct dbs_data { struct common_dbs_data *cdata; unsigned int min_sampling_rate; + struct cpufreq_frequency_table *freq_table; int usage_count; void *tuners; From bdffcf3714fbf1fc33b2ec3ba46c88a3e2c481fe Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 30 Jul 2016 13:41:05 -0400 Subject: [PATCH 100/203] msm_adreno_tz: add adrenoboost parameter This scales up way too easily, it needs to be tuned. Signed-off-by: flar2 --- drivers/devfreq/governor_msm_adreno_tz.c | 31 +++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index 5ebd32fbb38d..1e9551d5f808 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -56,6 +56,7 @@ static DEFINE_SPINLOCK(suspend_lock); #define TAG "msm_adreno_tz: " +static unsigned int adrenoboost = 10000; static u64 suspend_time; static u64 suspend_start; static unsigned long acc_total, acc_relative_busy; @@ -86,6 +87,30 @@ u64 suspend_time_ms(void) return time_diff; } +static ssize_t adrenoboost_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", adrenoboost); + + return count; +} + +static ssize_t adrenoboost_save(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int input; + sscanf(buf, "%d ", &input); + if (input < 0 || input > 50000) { + adrenoboost = 0; + } else { + adrenoboost = input; + } + + return count; +} + + static ssize_t gpu_load_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -131,6 +156,9 @@ static ssize_t suspend_time_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%llu\n", time_diff); } +static DEVICE_ATTR(adrenoboost, 0644, + adrenoboost_show, adrenoboost_save); + static DEVICE_ATTR(gpu_load, 0444, gpu_load_show, NULL); static DEVICE_ATTR(suspend_time, 0444, @@ -140,6 +168,7 @@ static DEVICE_ATTR(suspend_time, 0444, static const struct device_attribute *adreno_tz_attr_list[] = { &dev_attr_gpu_load, &dev_attr_suspend_time, + &dev_attr_adrenoboost, NULL }; @@ -317,7 +346,7 @@ static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq, scm_data[0] = level; scm_data[1] = priv->bin.total_time; - scm_data[2] = priv->bin.busy_time; + scm_data[2] = priv->bin.busy_time + (level * adrenoboost); __secure_tz_update_entry3(scm_data, sizeof(scm_data), &val, sizeof(val), priv->is_64); } From 7683111a100590083c415e90b2308532c9e3f9d3 Mon Sep 17 00:00:00 2001 From: tbalden Date: Sat, 30 Jul 2016 12:48:59 -0700 Subject: [PATCH 101/203] adrenoboost: finetuning algorithm - scale it a bit down Values range from 0-3, 0 off, 3 most aggressive. Scales back nicely in 2d to 133mhz. Only scale up and count if MIN_VALUE crossed Signed-off-by: flar2 --- drivers/devfreq/governor_msm_adreno_tz.c | 25 ++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index 1e9551d5f808..c952782116dd 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -56,7 +56,10 @@ static DEFINE_SPINLOCK(suspend_lock); #define TAG "msm_adreno_tz: " -static unsigned int adrenoboost = 10000; +#if 1 +static unsigned int adrenoboost = 1; +#endif + static u64 suspend_time; static u64 suspend_start; static unsigned long acc_total, acc_relative_busy; @@ -87,6 +90,7 @@ u64 suspend_time_ms(void) return time_diff; } +#if 1 static ssize_t adrenoboost_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -101,7 +105,7 @@ static ssize_t adrenoboost_save(struct device *dev, { int input; sscanf(buf, "%d ", &input); - if (input < 0 || input > 50000) { + if (input < 0 || input > 3) { adrenoboost = 0; } else { adrenoboost = input; @@ -109,7 +113,7 @@ static ssize_t adrenoboost_save(struct device *dev, return count; } - +#endif static ssize_t gpu_load_show(struct device *dev, struct device_attribute *attr, @@ -156,8 +160,10 @@ static ssize_t suspend_time_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%llu\n", time_diff); } +#if 1 static DEVICE_ATTR(adrenoboost, 0644, adrenoboost_show, adrenoboost_save); +#endif static DEVICE_ATTR(gpu_load, 0444, gpu_load_show, NULL); @@ -168,7 +174,9 @@ static DEVICE_ATTR(suspend_time, 0444, static const struct device_attribute *adreno_tz_attr_list[] = { &dev_attr_gpu_load, &dev_attr_suspend_time, +#if 1 &dev_attr_adrenoboost, +#endif NULL }; @@ -314,7 +322,16 @@ static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq, *freq = stats.current_frequency; priv->bin.total_time += stats.total_time; +#if 1 + // scale busy time up based on adrenoboost parameter, only if MIN_BUSY exceeded... + if ((unsigned int)(priv->bin.busy_time + stats.busy_time) >= MIN_BUSY) { + priv->bin.busy_time += stats.busy_time * (1 + (adrenoboost*3)/2); + } else { + priv->bin.busy_time += stats.busy_time; + } +#else priv->bin.busy_time += stats.busy_time; +#endif /* Update the GPU load statistics */ compute_work_load(&stats, priv, devfreq); @@ -346,7 +363,7 @@ static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq, scm_data[0] = level; scm_data[1] = priv->bin.total_time; - scm_data[2] = priv->bin.busy_time + (level * adrenoboost); + scm_data[2] = priv->bin.busy_time; __secure_tz_update_entry3(scm_data, sizeof(scm_data), &val, sizeof(val), priv->is_64); } From 216ef48b5684062c6fc8312eefe6474a8d8d6f01 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 11 Sep 2016 16:09:11 -0400 Subject: [PATCH 102/203] adrenoboost: disable by default --- drivers/devfreq/governor_msm_adreno_tz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index c952782116dd..7a111e43749e 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -57,7 +57,7 @@ static DEFINE_SPINLOCK(suspend_lock); #define TAG "msm_adreno_tz: " #if 1 -static unsigned int adrenoboost = 1; +static unsigned int adrenoboost = 0; #endif static u64 suspend_time; From ba0040ae167bce32408e49ee40a12fa4e670e367 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 5 Dec 2015 21:12:48 -0500 Subject: [PATCH 103/203] msm_performance: Make input boosting optional Signed-off-by: flar2 --- drivers/soc/qcom/msm_performance.c | 35 ++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 71f2810713aa..31ddc079001f 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -28,7 +28,7 @@ static unsigned int use_input_evts_with_hi_slvt_detect; static struct mutex managed_cpus_lock; - +static int touchboost = 1; /* Maximum number to clusters that this module will manage*/ static unsigned int num_clusters; @@ -189,6 +189,29 @@ static struct input_handler *handler; /**************************sysfs start********************************/ +static int set_touchboost(const char *buf, const struct kernel_param *kp) +{ + int val; + + if (sscanf(buf, "%d\n", &val) != 1) + return -EINVAL; + + touchboost = val; + + return 0; +} + +static int get_touchboost(char *buf, const struct kernel_param *kp) +{ + return snprintf(buf, PAGE_SIZE, "%d", touchboost); +} + +static const struct kernel_param_ops param_ops_touchboost = { + .set = set_touchboost, + .get = get_touchboost, +}; +device_param_cb(touchboost, ¶m_ops_touchboost, NULL, 0644); + static int set_num_clusters(const char *buf, const struct kernel_param *kp) { unsigned int val; @@ -378,6 +401,10 @@ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) struct cpufreq_policy policy; cpumask_var_t limit_mask; int ret; + const char *reset = "0:0 4:0"; + + if (touchboost == 0) + cp = reset; while ((cp = strpbrk(cp + 1, " :"))) ntokens++; @@ -386,7 +413,11 @@ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) if (!(ntokens % 2)) return -EINVAL; - cp = buf; + if (touchboost == 0) + cp = reset; + else + cp = buf; + cpumask_clear(limit_mask); for (i = 0; i < ntokens; i += 2) { if (sscanf(cp, "%u:%u", &cpu, &val) != 2) From 1dac24df9e3f45ee305d9607f8ee70d0dab72e57 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 11 Sep 2016 16:11:30 -0400 Subject: [PATCH 104/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 9bf38c8af27e..5d450ed9883a 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.18" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.19" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -276,12 +276,12 @@ CONFIG_BLOCK_COMPAT=y CONFIG_IOSCHED_NOOP=y # CONFIG_IOSCHED_TEST is not set CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_ZEN=y CONFIG_IOSCHED_CFQ=y CONFIG_IOSCHED_FIOPS=y CONFIG_IOSCHED_SIO=y CONFIG_IOSCHED_BFQ=y CONFIG_CGROUP_BFQIO=y +CONFIG_IOSCHED_ZEN=y # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_BFQ is not set @@ -507,11 +507,13 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ELEMENTALX is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_ELEMENTALX=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_CPUFREQ_DT is not set CONFIG_CPU_BOOST=y From 517c3fdbfab1f8ae6795ce7af2c9d9b91a9bb9cb Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 13 Sep 2016 00:24:58 -0400 Subject: [PATCH 105/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 5d450ed9883a..a51fb19176bc 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.19" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.20" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 71cd9e4d58c597ecf80c872d5e12f0c492c7fbde Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 13 Sep 2016 00:44:20 -0400 Subject: [PATCH 106/203] msm: mdss: KCAL: disable igc update --- drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c index 74abe54846b0..4ea14ea58e0e 100644 --- a/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c +++ b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c @@ -383,7 +383,7 @@ static ssize_t kcal_enable_store(struct device *dev, mdss_mdp_kcal_update_pcc(lut_data); mdss_mdp_kcal_update_pa(lut_data); - mdss_mdp_kcal_update_igc(lut_data); + //mdss_mdp_kcal_update_igc(lut_data); mdss_mdp_kcal_display_commit(); return count; @@ -408,10 +408,11 @@ static ssize_t kcal_invert_store(struct device *dev, (lut_data->invert == kcal_invert)) return -EINVAL; - lut_data->invert = kcal_invert; + //disable + lut_data->invert = 0; - mdss_mdp_kcal_update_igc(lut_data); - mdss_mdp_kcal_display_commit(); + //mdss_mdp_kcal_update_igc(lut_data); + //mdss_mdp_kcal_display_commit(); return count; } From 9effa2075fbb768ee382eb33cc4cf95ac22e33c7 Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 13 Sep 2016 00:44:30 -0400 Subject: [PATCH 107/203] zen-iosched: change fifo_batch to 16 --- block/zen-iosched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/zen-iosched.c b/block/zen-iosched.c index fa37e4d73de9..2d3e11d1add4 100644 --- a/block/zen-iosched.c +++ b/block/zen-iosched.c @@ -18,7 +18,7 @@ enum zen_data_dir { ASYNC, SYNC }; static const int sync_expire = HZ / 2; /* max time before a sync is submitted. */ static const int async_expire = 5 * HZ; /* ditto for async, these limits are SOFT! */ -static const int fifo_batch = 1; +static const int fifo_batch = 16; struct zen_data { /* Runtime Data */ From a2b70865948a7c1bc5e1a2a69797aa865c96d45e Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 20 Sep 2016 21:48:59 -0400 Subject: [PATCH 108/203] msm_performance: fix big cluster value --- drivers/soc/qcom/msm_performance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 31ddc079001f..415508c13d1a 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -401,7 +401,7 @@ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) struct cpufreq_policy policy; cpumask_var_t limit_mask; int ret; - const char *reset = "0:0 4:0"; + const char *reset = "0:0 2:0"; if (touchboost == 0) cp = reset; From c775412961fda0313b0ec4c29932886314aa8c09 Mon Sep 17 00:00:00 2001 From: Subhani Shaik Date: Tue, 7 Jun 2016 08:16:46 -0700 Subject: [PATCH 109/203] qcacld-2.0: Fix stack corruption issue in sme_RrmProcessNeighborReport When STA process Neighbor report from AP, session_id is declared as one byte variable and its overwritten with four bytes value in csrRoamGetSessionIdFromBSSID. This is observed on enabling stack protection in kernel config(CONFIG_CC_STACKPROTECTOR). Fix is to declare session_id as four bytes variable. Change-Id: Ieda0d13e2ccbe11dc9e56ad653430aa39306c707 CRs-Fixed: 1025272 Bug: 29194700 Signed-off-by: Subhani Shaik --- drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c index 1d10b10e6c19..0d4d26594bc0 100644 --- a/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c @@ -1191,11 +1191,11 @@ eHalStatus sme_RrmProcessNeighborReport(tpAniSirGlobal pMac, void *pMsgBuf) tpRrmNeighborReportDesc pNeighborReportDesc; tANI_U8 i = 0; VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; - tANI_U8 sessionId; + tANI_U32 sessionId; /* Get the session id */ status = csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)pNeighborRpt->bssId, - (tANI_U32*) &sessionId); + &sessionId); if (HAL_STATUS_SUCCESS(status)) { #ifdef FEATURE_WLAN_ESE /* Clear the cache for ESE. */ From b383f8ac9e01c743732d380b3c9870e7b210eed8 Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 20 Sep 2016 21:57:27 -0400 Subject: [PATCH 110/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index a51fb19176bc..db08511cea18 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.20" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.21" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From a44fe344abf3f58a4ffaf9e396931a43c7734644 Mon Sep 17 00:00:00 2001 From: flar2 Date: Wed, 21 Sep 2016 20:00:26 -0400 Subject: [PATCH 111/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index db08511cea18..6e4e8c7d930d 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.21" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.22" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From fcfeadb0eb9bfb2d75b9b6b7795c90976cda1629 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 23 Sep 2016 23:15:24 -0400 Subject: [PATCH 112/203] ASoC: wcd9335: prevent speaker gain from being reset --- sound/soc/codecs/tfa9890/tfa_dsp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/codecs/tfa9890/tfa_dsp.c b/sound/soc/codecs/tfa9890/tfa_dsp.c index e99c8c9beff7..8af196a6f8ab 100644 --- a/sound/soc/codecs/tfa9890/tfa_dsp.c +++ b/sound/soc/codecs/tfa9890/tfa_dsp.c @@ -1212,12 +1212,20 @@ int float_to_int(u32 x) return (int)((m >> e) & -(e < 32)); } +#ifdef CONFIG_SOUND_CONTROL +int tfa98xx_get_volume(struct tfa98xx *tfa98xx, s64 *pVoldB); +#endif + int tfa98xx_set_volume(struct tfa98xx *tfa98xx, u32 voldB) { struct snd_soc_codec *codec = tfa98xx->codec; u16 value; int volume_value; +#ifdef CONFIG_SOUND_CONTROL + s64 cur_volume; + tfa98xx_get_volume(tfa98xx, &cur_volume); +#endif value = snd_soc_read(codec, TFA98XX_AUDIO_CTR); /* @@ -1233,6 +1241,11 @@ int tfa98xx_set_volume(struct tfa98xx *tfa98xx, u32 voldB) pr_debug("%d, attenuation -%d dB\n", volume_value, float_to_int(voldB)); +#ifdef CONFIG_SOUND_CONTROL + if (cur_volume < 0) + return 0; +#endif + /* volume value is in the top 8 bits of the register */ value = (value & 0x00FF) | (u16)(volume_value << 8); snd_soc_write(codec, TFA98XX_AUDIO_CTR, value); From f9cc52d45bea0e68425421cc2a32310cb7673ed4 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 23 Sep 2016 23:16:03 -0400 Subject: [PATCH 113/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 6e4e8c7d930d..573619b29594 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.22" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.23" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 7701e3f3bed291d43310a8cd0750fe977ea2be7d Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 26 Sep 2016 06:12:41 +0200 Subject: [PATCH 114/203] msm: kgsl: Defer adding the mem entry to a process If we add the mem entry pointer in the process mem_idr too early other threads can do operations on the entry by guessing the ID or GPU address before the object gets returned by the creating operation. Allocate an ID for the object but don't assign the pointer until right before the creating function returns ensuring that another operation can't access it until it is ready. CRs-Fixed: 1002974 Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 0149d1bf49c3..57bc580e838b 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -388,6 +388,17 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, kgsl_mmu_put_gpuaddr(pagetable, &entry->memdesc); } +/* Commit the entry to the process so it can be accessed by other operations */ +static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry) +{ + if (!entry) + return; + + spin_lock(&entry->priv->mem_lock); + idr_replace(&entry->priv->mem_idr, entry, entry->id); + spin_unlock(&entry->priv->mem_lock); +} + /** * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process * @entry: the memory entry @@ -413,8 +424,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, return -EBADF; idr_preload(GFP_KERNEL); spin_lock(&process->mem_lock); - id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT); - spin_unlock(&process->mem_lock); + /* Allocate the ID but don't attach the pointer just yet */ + id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT); spin_unlock(&process->mem_lock); idr_preload_end(); if (id < 0) { @@ -2305,6 +2316,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, trace_kgsl_mem_map(entry, fd); + kgsl_mem_entry_commit_process(entry); return 0; unmap: @@ -2576,6 +2588,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, trace_kgsl_mem_map(entry, param->fd); + kgsl_mem_entry_commit_process(entry); return result; error_attach: @@ -2982,6 +2995,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( entry->memdesc.size); trace_kgsl_mem_alloc(entry); + kgsl_mem_entry_commit_process(entry); return entry; err: kfree(entry); From dc78c4609fcdacc9e87790d136b9bbe66d591153 Mon Sep 17 00:00:00 2001 From: flar2 Date: Tue, 27 Sep 2016 20:19:01 -0400 Subject: [PATCH 115/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 573619b29594..6a015b4ca12a 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.23" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.24" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 291a4cadc49538eca0ecc5f6b340f1735050bb48 Mon Sep 17 00:00:00 2001 From: flar2 Date: Fri, 30 Sep 2016 23:14:03 -0400 Subject: [PATCH 116/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 6a015b4ca12a..ada19cae365a 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.24" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.25" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 501a8531749d63975a0dfc9dbb1445bc5fee14cc Mon Sep 17 00:00:00 2001 From: Tahsin Erdogan Date: Tue, 19 May 2015 13:55:21 -0700 Subject: [PATCH 117/203] block: Make CFQ default to IOPS mode on SSDs CFQ idling causes reduced IOPS throughput on non-rotational disks. Since disk head seeking is not applicable to SSDs, it doesn't really help performance by anticipating future near-by IO requests. By turning off idling (and switching to IOPS mode), we allow other processes to dispatch IO requests down to the driver and so increase IO throughput. Following FIO benchmark results were taken on a cloud SSD offering with idling on and off: Idling iops avg-lat(ms) stddev bw ------------------------------------------------------ On 7054 90.107 38.697 28217KB/s Off 29255 21.836 11.730 117022KB/s fio --name=temp --size=100G --time_based --ioengine=libaio \ --randrepeat=0 --direct=1 --invalidate=1 --verify=0 \ --verify_fatal=0 --rw=randread --blocksize=4k --group_reporting=1 \ --filename=/dev/sdb --runtime=10 --iodepth=64 --numjobs=10 And the following is from a local SSD run: Idling iops avg-lat(ms) stddev bw ------------------------------------------------------ On 19320 33.043 14.068 77281KB/s Off 21626 29.465 12.662 86507KB/s fio --name=temp --size=5G --time_based --ioengine=libaio \ --randrepeat=0 --direct=1 --invalidate=1 --verify=0 \ --verify_fatal=0 --rw=randread --blocksize=4k --group_reporting=1 \ --filename=/fio_data --runtime=10 --iodepth=64 --numjobs=10 Reviewed-by: Nauman Rafique Signed-off-by: Tahsin Erdogan Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5da8e6e9ab4b..402be0139122 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4460,7 +4460,7 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e) cfqd->cfq_slice[1] = cfq_slice_sync; cfqd->cfq_target_latency = cfq_target_latency; cfqd->cfq_slice_async_rq = cfq_slice_async_rq; - cfqd->cfq_slice_idle = cfq_slice_idle; + cfqd->cfq_slice_idle = blk_queue_nonrot(q) ? 0 : cfq_slice_idle; cfqd->cfq_group_idle = cfq_group_idle; cfqd->cfq_latency = 1; cfqd->hw_tag = -1; From 6dcfd485c67c26dec0ed78c6ab56e1ab95779ecd Mon Sep 17 00:00:00 2001 From: fluxi Date: Sun, 12 Jun 2016 21:59:49 +0200 Subject: [PATCH 118/203] net: sch_generic: Allow devices to opt-out net watchdog This enables QCOM commit 43b54948 "net: rmnet_data: Remove watchdog_timeo". If no watchdog_timeo value is set, we end up with a 5*HZ check interval instead of disabling the rmnet watchdog entirely (as obviously intended). Change-Id: Ia59f093e940bda9bcd4115d4641d10481158886f --- net/sched/sch_generic.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5d936bd6aa52..b04698515ff9 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -278,6 +278,9 @@ static void dev_watchdog(unsigned long arg) struct net_device *dev = (struct net_device *)arg; netif_tx_lock(dev); + if (!dev->watchdog_timeo) + return; + if (!qdisc_tx_is_noop(dev)) { if (netif_device_present(dev) && netif_running(dev) && @@ -321,8 +324,11 @@ static void dev_watchdog(unsigned long arg) void __netdev_watchdog_up(struct net_device *dev) { + if (!dev->watchdog_timeo) + return; + if (dev->netdev_ops->ndo_tx_timeout) { - if (dev->watchdog_timeo <= 0) + if (dev->watchdog_timeo < 0) dev->watchdog_timeo = 5*HZ; if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + dev->watchdog_timeo))) From 09e04efc3015bf8e00ba7adaf8c7e3637a535a7a Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Mon, 29 Feb 2016 13:27:50 +0530 Subject: [PATCH 119/203] msm: msm_bus: remove the buspm module from kernel Remove the buspm module from msm_bus since it adds no functionality to the bus bandwidth aggregation driver. It is a loadable module used for profiling purposes. Change-Id: Ia0d21eb7e48d3cb2a74d4fae5ee4fb2fd449ea9f Signed-off-by: Kiran Gunda --- arch/arm/configs/msm8937-perf_defconfig | 1 - arch/arm/configs/msm8937_defconfig | 1 - arch/arm/configs/msmcortex-perf_defconfig | 1 - arch/arm/configs/msmcortex_defconfig | 1 - arch/arm64/configs/msm-perf_defconfig | 1 - arch/arm64/configs/msm8937-perf_defconfig | 1 - arch/arm64/configs/msm8937_defconfig | 1 - arch/arm64/configs/msm_defconfig | 1 - arch/arm64/configs/msmcortex-perf_defconfig | 1 - arch/arm64/configs/msmcortex_defconfig | 1 - drivers/platform/msm/Kconfig | 9 - drivers/platform/msm/msm_bus/Makefile | 1 - drivers/platform/msm/msm_bus/msm-buspm-dev.c | 368 ------------------ .../msm/msm_bus/msm_buspm_coresight_adhoc.c | 1 + 14 files changed, 1 insertion(+), 388 deletions(-) delete mode 100644 drivers/platform/msm/msm_bus/msm-buspm-dev.c diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig index 976b28dc3bb6..1b08857943eb 100644 --- a/arch/arm/configs/msm8937-perf_defconfig +++ b/arch/arm/configs/msm8937-perf_defconfig @@ -470,7 +470,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig index 5a8a617577d4..781a1f7dadc5 100644 --- a/arch/arm/configs/msm8937_defconfig +++ b/arch/arm/configs/msm8937_defconfig @@ -474,7 +474,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm/configs/msmcortex-perf_defconfig b/arch/arm/configs/msmcortex-perf_defconfig index 1ce06e8c423a..c6f3b919f2d0 100644 --- a/arch/arm/configs/msmcortex-perf_defconfig +++ b/arch/arm/configs/msmcortex-perf_defconfig @@ -468,7 +468,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index 0b637acb0d4d..9cecb4c981f5 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -466,7 +466,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 638dcf62ee58..fdbddde855c4 100755 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -492,7 +492,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig index ef9bff30263d..ba0617097d82 100644 --- a/arch/arm64/configs/msm8937-perf_defconfig +++ b/arch/arm64/configs/msm8937-perf_defconfig @@ -484,7 +484,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig index 732ac4fc2060..b8c9a5c4aeba 100644 --- a/arch/arm64/configs/msm8937_defconfig +++ b/arch/arm64/configs/msm8937_defconfig @@ -487,7 +487,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index a1e103576839..88259efb6372 100755 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -512,7 +512,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_DEBUG_BUS_VOTER=y CONFIG_QPNP_POWER_ON=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index def8206e85ab..b65009176f0c 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -486,7 +486,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 9e28fa2d808e..1ed885d6db42 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -488,7 +488,6 @@ CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -CONFIG_MSM_BUSPM_DEV=m CONFIG_BUS_TOPOLOGY_ADHOC=y CONFIG_QPNP_POWER_ON=y CONFIG_QPNP_REVID=y diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 966a58107ffe..c4d2983c5d0e 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -16,15 +16,6 @@ config MSM_BUS_SCALING for the active devices needs without keeping the clocks at max frequency when a slower speed is sufficient. -config MSM_BUSPM_DEV - tristate "MSM Bus Performance Monitor Kernel Module" - depends on MSM_BUS_SCALING - help - This kernel module is used to mmap() hardware registers for the - performance monitors, counters, etc. The module can also be used to - allocate physical memory which is used by bus performance hardware to - dump performance data - config BUS_TOPOLOGY_ADHOC bool "ad-hoc bus scaling topology" help diff --git a/drivers/platform/msm/msm_bus/Makefile b/drivers/platform/msm/msm_bus/Makefile index fec45375de87..a58994d6023b 100644 --- a/drivers/platform/msm/msm_bus/Makefile +++ b/drivers/platform/msm/msm_bus/Makefile @@ -24,4 +24,3 @@ endif obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o -obj-$(CONFIG_MSM_BUSPM_DEV) += msm-buspm-dev.o diff --git a/drivers/platform/msm/msm_bus/msm-buspm-dev.c b/drivers/platform/msm/msm_bus/msm-buspm-dev.c deleted file mode 100644 index 4d9262b676b7..000000000000 --- a/drivers/platform/msm/msm_bus/msm-buspm-dev.c +++ /dev/null @@ -1,368 +0,0 @@ -/* Copyright (c) 2011-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 - * 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. - */ - -/* #define DEBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MSM_BUSPM_DRV_NAME "msm-buspm-dev" - -#ifdef CONFIG_COMPAT -static long -msm_buspm_dev_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); -#else -#define msm_buspm_dev_compat_ioctl NULL -#endif - -static long -msm_buspm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -static int msm_buspm_dev_mmap(struct file *filp, struct vm_area_struct *vma); -static int msm_buspm_dev_release(struct inode *inode, struct file *filp); -static int msm_buspm_dev_open(struct inode *inode, struct file *filp); - -static const struct file_operations msm_buspm_dev_fops = { - .owner = THIS_MODULE, - .mmap = msm_buspm_dev_mmap, - .open = msm_buspm_dev_open, - .unlocked_ioctl = msm_buspm_dev_ioctl, - .compat_ioctl = msm_buspm_dev_compat_ioctl, - .llseek = noop_llseek, - .release = msm_buspm_dev_release, -}; - -struct miscdevice msm_buspm_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = MSM_BUSPM_DRV_NAME, - .fops = &msm_buspm_dev_fops, -}; - - -enum msm_buspm_spdm_res { - SPDM_RES_ID = 0, - SPDM_RES_TYPE = 0x63707362, - SPDM_KEY = 0x00006e65, - SPDM_SIZE = 4, -}; -/* - * Allocate kernel buffer. - * Currently limited to one buffer per file descriptor. If alloc() is - * called twice for the same descriptor, the original buffer is freed. - * There is also no locking protection so the same descriptor can not be shared. - */ - -static inline void *msm_buspm_dev_get_vaddr(struct file *filp) -{ - struct msm_buspm_map_dev *dev = filp->private_data; - - return (dev) ? dev->vaddr : NULL; -} - -static inline unsigned int msm_buspm_dev_get_buflen(struct file *filp) -{ - struct msm_buspm_map_dev *dev = filp->private_data; - - return dev ? dev->buflen : 0; -} - -static inline unsigned long msm_buspm_dev_get_paddr(struct file *filp) -{ - struct msm_buspm_map_dev *dev = filp->private_data; - - return (dev) ? dev->paddr : 0L; -} - -static void msm_buspm_dev_free(struct file *filp) -{ - struct msm_buspm_map_dev *dev = filp->private_data; - - if (dev && dev->vaddr) { - pr_debug("freeing memory at 0x%p\n", dev->vaddr); - dma_free_coherent(msm_buspm_misc.this_device, dev->buflen, - dev->vaddr, dev->paddr); - dev->paddr = 0L; - dev->vaddr = NULL; - } -} - -static int msm_buspm_dev_open(struct inode *inode, struct file *filp) -{ - struct msm_buspm_map_dev *dev; - - if (capable(CAP_SYS_ADMIN)) { - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev) - filp->private_data = dev; - else - return -ENOMEM; - } else { - return -EPERM; - } - - return 0; -} - -static int -msm_buspm_dev_alloc(struct file *filp, struct buspm_alloc_params data) -{ - dma_addr_t paddr; - void *vaddr; - struct msm_buspm_map_dev *dev = filp->private_data; - - /* If buffer already allocated, then free it */ - if (dev->vaddr) - msm_buspm_dev_free(filp); - - /* Allocate uncached memory */ - vaddr = dma_alloc_coherent(msm_buspm_misc.this_device, data.size, - &paddr, GFP_KERNEL); - - if (vaddr == NULL) { - pr_err("allocation of 0x%zu bytes failed", data.size); - return -ENOMEM; - } - - dev->vaddr = vaddr; - dev->paddr = paddr; - dev->buflen = data.size; - filp->f_pos = 0; - pr_debug("virt addr = 0x%p\n", dev->vaddr); - pr_debug("phys addr = 0x%lx\n", dev->paddr); - - return 0; -} - -static int msm_bus_rpm_req(u32 rsc_type, u32 key, u32 hwid, - int ctx, u32 val) -{ - struct msm_rpm_request *rpm_req; - int ret, msg_id; - - rpm_req = msm_rpm_create_request(ctx, rsc_type, SPDM_RES_ID, 1); - if (rpm_req == NULL) { - pr_err("RPM: Couldn't create RPM Request\n"); - return -ENXIO; - } - - ret = msm_rpm_add_kvp_data(rpm_req, key, (const uint8_t *)&val, - (int)(sizeof(uint32_t))); - if (ret) { - pr_err("RPM: Add KVP failed for RPM Req:%u\n", - rsc_type); - goto err; - } - - pr_debug("Added Key: %d, Val: %u, size: %zu\n", key, - (uint32_t)val, sizeof(uint32_t)); - msg_id = msm_rpm_send_request(rpm_req); - if (!msg_id) { - pr_err("RPM: No message ID for req\n"); - ret = -ENXIO; - goto err; - } - - ret = msm_rpm_wait_for_ack(msg_id); - if (ret) { - pr_err("RPM: Ack failed\n"); - goto err; - } - -err: - msm_rpm_free_request(rpm_req); - return ret; -} - -static int msm_buspm_ioc_cmds(uint32_t arg) -{ - switch (arg) { - case MSM_BUSPM_SPDM_CLK_DIS: - case MSM_BUSPM_SPDM_CLK_EN: - return msm_bus_rpm_req(SPDM_RES_TYPE, SPDM_KEY, 0, - MSM_RPM_CTX_ACTIVE_SET, arg); - default: - pr_warn("Unsupported ioctl command: %d\n", arg); - return -EINVAL; - } -} - - - -static long -msm_buspm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct buspm_xfer_req xfer; - struct buspm_alloc_params alloc_data; - unsigned long paddr; - int retval = 0; - void *buf = msm_buspm_dev_get_vaddr(filp); - unsigned int buflen = msm_buspm_dev_get_buflen(filp); - unsigned char *dbgbuf = buf; - - if (_IOC_TYPE(cmd) != MSM_BUSPM_IOC_MAGIC) { - pr_err("Wrong IOC_MAGIC.Exiting\n"); - return -ENOTTY; - } - - switch (cmd) { - case MSM_BUSPM_IOC_FREE: - pr_debug("cmd = 0x%x (FREE)\n", cmd); - msm_buspm_dev_free(filp); - break; - - case MSM_BUSPM_IOC_ALLOC: - pr_debug("cmd = 0x%x (ALLOC)\n", cmd); - retval = __get_user(alloc_data.size, (uint32_t __user *)arg); - - if (retval == 0) - retval = msm_buspm_dev_alloc(filp, alloc_data); - break; - - case MSM_BUSPM_IOC_RD_PHYS_ADDR: - pr_debug("Read Physical Address\n"); - paddr = msm_buspm_dev_get_paddr(filp); - if (paddr == 0L) { - retval = -EINVAL; - } else { - pr_debug("phys addr = 0x%lx\n", paddr); - retval = __put_user(paddr, - (unsigned long __user *)arg); - } - break; - - case MSM_BUSPM_IOC_RDBUF: - if (!buf) { - retval = -EINVAL; - break; - } - - pr_debug("Read Buffer: 0x%x%x%x%x\n", - dbgbuf[0], dbgbuf[1], dbgbuf[2], dbgbuf[3]); - - if (copy_from_user(&xfer, (void __user *)arg, sizeof(xfer))) { - retval = -EFAULT; - break; - } - - if ((xfer.size <= buflen) && - (copy_to_user((void __user *)xfer.data, buf, - xfer.size))) { - retval = -EFAULT; - break; - } - break; - - case MSM_BUSPM_IOC_WRBUF: - pr_debug("Write Buffer\n"); - - if (!buf) { - retval = -EINVAL; - break; - } - - if (copy_from_user(&xfer, (void __user *)arg, sizeof(xfer))) { - retval = -EFAULT; - break; - } - - if ((buflen <= xfer.size) && - (copy_from_user(buf, (void __user *)xfer.data, - xfer.size))) { - retval = -EFAULT; - break; - } - break; - - case MSM_BUSPM_IOC_CMD: - pr_debug("IOCTL command: cmd: %d arg: %lu\n", cmd, arg); - retval = msm_buspm_ioc_cmds(arg); - break; - - default: - pr_debug("Unknown command 0x%x\n", cmd); - retval = -EINVAL; - break; - } - - return retval; -} - -static int msm_buspm_dev_release(struct inode *inode, struct file *filp) -{ - struct msm_buspm_map_dev *dev = filp->private_data; - - msm_buspm_dev_free(filp); - kfree(dev); - filp->private_data = NULL; - - return 0; -} - -static int msm_buspm_dev_mmap(struct file *filp, struct vm_area_struct *vma) -{ - pr_debug("vma = 0x%p\n", vma); - - /* Mappings are uncached */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EFAULT; - - return 0; -} - -#ifdef CONFIG_COMPAT -static long -msm_buspm_dev_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - return msm_buspm_dev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - -static int __init msm_buspm_dev_init(void) -{ - int ret = 0; - - ret = misc_register(&msm_buspm_misc); - if (ret < 0) { - WARN_ON(1); - return ret; - } - - if (msm_buspm_misc.this_device->coherent_dma_mask == 0) - msm_buspm_misc.this_device->coherent_dma_mask = - DMA_BIT_MASK(32); - - return ret; -} - -static void __exit msm_buspm_dev_exit(void) -{ - misc_deregister(&msm_buspm_misc); -} -module_init(msm_buspm_dev_init); -module_exit(msm_buspm_dev_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_VERSION("1.0"); -MODULE_ALIAS("platform:"MSM_BUSPM_DRV_NAME); diff --git a/drivers/platform/msm/msm_bus/msm_buspm_coresight_adhoc.c b/drivers/platform/msm/msm_bus/msm_buspm_coresight_adhoc.c index 9aec82463f6c..8d20b624259b 100644 --- a/drivers/platform/msm/msm_bus/msm_buspm_coresight_adhoc.c +++ b/drivers/platform/msm/msm_bus/msm_buspm_coresight_adhoc.c @@ -135,6 +135,7 @@ int msmbus_coresight_init_adhoc(struct platform_device *pdev, return PTR_ERR(pdata); drvdata = platform_get_drvdata(pdev); + dev_dbg(dev, "info: removed buspm module from kernel space\n"); if (IS_ERR_OR_NULL(drvdata)) { drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { From 463c07a5f661cbdd6dbde6adce24f7049949b6e9 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 17 Aug 2016 16:00:08 -0700 Subject: [PATCH 120/203] binder: prevent kptr leak by using %pK format specifier Works in conjunction with kptr_restrict. Bug: 30143283 Change-Id: I2b3ce22f4e206e74614d51453a1d59b7080ab05a --- drivers/staging/android/binder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index a6cd39586d75..3aa007572d75 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -3358,7 +3358,7 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) { - seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n", + seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n", ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ", ref->node->debug_id, ref->strong, ref->weak, ref->death); } From e5a3f2167ad2fcb1cca25351469ca11ab3f7c492 Mon Sep 17 00:00:00 2001 From: Mohamad Ayyash Date: Tue, 24 May 2016 15:33:56 -0700 Subject: [PATCH 121/203] Replace %p with %pK to prevent leaking kernel address BUG: 27532522 Change-Id: Ic0710a9a8cfc682acd88ecf3bbfeece2d798c4a4 Signed-off-by: Mohamad Ayyash --- net/netfilter/xt_qtaguid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 45df66f62f7d..bd27e833e9db 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1979,7 +1979,7 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v) ); f_count = atomic_long_read( &sock_tag_entry->socket->file->f_count); - seq_printf(m, "sock=%p tag=0x%llx (uid=%u) pid=%u " + seq_printf(m, "sock=%pK tag=0x%llx (uid=%u) pid=%u " "f_count=%lu\n", sock_tag_entry->sk, sock_tag_entry->tag, uid, From 3502ec6bbaceb35aa99035a2caaa65a1d50179f5 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Fri, 22 Jul 2016 04:52:08 +0900 Subject: [PATCH 122/203] fs: import sdcardfs from G930FXXU1APF2 Signed-off-by: Park Ju Hyung Signed-off-by: engstk --- fs/Kconfig | 1 + fs/Makefile | 1 + fs/sdcardfs/Kconfig | 24 + fs/sdcardfs/Makefile | 8 + fs/sdcardfs/dentry.c | 187 ++++++++ fs/sdcardfs/derived_perm.c | 299 +++++++++++++ fs/sdcardfs/file.c | 359 +++++++++++++++ fs/sdcardfs/inode.c | 895 +++++++++++++++++++++++++++++++++++++ fs/sdcardfs/lookup.c | 379 ++++++++++++++++ fs/sdcardfs/main.c | 440 ++++++++++++++++++ fs/sdcardfs/mmap.c | 81 ++++ fs/sdcardfs/multiuser.h | 37 ++ fs/sdcardfs/packagelist.c | 359 +++++++++++++++ fs/sdcardfs/sdcardfs.h | 549 +++++++++++++++++++++++ fs/sdcardfs/super.c | 297 ++++++++++++ fs/sdcardfs/version.h | 28 ++ fs/sdcardfs/xattr.c | 89 ++++ 17 files changed, 4033 insertions(+) create mode 100644 fs/sdcardfs/Kconfig create mode 100644 fs/sdcardfs/Makefile create mode 100644 fs/sdcardfs/dentry.c create mode 100644 fs/sdcardfs/derived_perm.c create mode 100644 fs/sdcardfs/file.c create mode 100644 fs/sdcardfs/inode.c create mode 100644 fs/sdcardfs/lookup.c create mode 100644 fs/sdcardfs/main.c create mode 100644 fs/sdcardfs/mmap.c create mode 100644 fs/sdcardfs/multiuser.h create mode 100644 fs/sdcardfs/packagelist.c create mode 100644 fs/sdcardfs/sdcardfs.h create mode 100644 fs/sdcardfs/super.c create mode 100644 fs/sdcardfs/version.h create mode 100644 fs/sdcardfs/xattr.c diff --git a/fs/Kconfig b/fs/Kconfig index 5e0c0bcd2d88..7c3634dc5a99 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -13,6 +13,7 @@ if BLOCK source "fs/ext2/Kconfig" source "fs/ext3/Kconfig" source "fs/ext4/Kconfig" +source "fs/sdcardfs/Kconfig" config FS_XIP # execute in place diff --git a/fs/Makefile b/fs/Makefile index 0f8ac3d51a95..a149a5f5044b 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_EXT2_FS) += ext2/ # We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 # unless explicitly requested by rootfstype obj-$(CONFIG_EXT4_FS) += ext4/ +obj-$(CONFIG_SDCARD_FS) += sdcardfs/ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_CRAMFS) += cramfs/ diff --git a/fs/sdcardfs/Kconfig b/fs/sdcardfs/Kconfig new file mode 100644 index 000000000000..d1b1af1562e2 --- /dev/null +++ b/fs/sdcardfs/Kconfig @@ -0,0 +1,24 @@ +config SDCARD_FS + tristate "sdcard file system" + default y + help + Sdcardfs is based on Wrapfs file system. + +config SDCARD_FS_FADV_NOACTIVE + bool "sdcardfs fadvise noactive support" + depends on FADV_NOACTIVE + default y + help + Sdcardfs supports fadvise noactive mode. + +config SDCARD_FS_CI_SEARCH + tristate "sdcardfs case-insensitive search support" + depends on SDCARD_FS + default y + +config SDCARD_FS_XATTR + bool "Sdcardfs extended attribute" + default y + depends on SDCARD_FS + help + Modification of sdcard file system for xattr diff --git a/fs/sdcardfs/Makefile b/fs/sdcardfs/Makefile new file mode 100644 index 000000000000..8f6ac296f8bd --- /dev/null +++ b/fs/sdcardfs/Makefile @@ -0,0 +1,8 @@ +ifeq ($(CONFIG_SDCARD_FS_XATTR),y) +EXTRA_CFLAGS += -DSDCARD_FS_XATTR +endif + +obj-$(CONFIG_SDCARD_FS) += sdcardfs.o + +sdcardfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o packagelist.o derived_perm.o +sdcardfs-$(CONFIG_SDCARD_FS_XATTR) += xattr.o diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c new file mode 100644 index 000000000000..be072c25e05f --- /dev/null +++ b/fs/sdcardfs/dentry.c @@ -0,0 +1,187 @@ +/* + * fs/sdcardfs/dentry.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" +#include "linux/ctype.h" + +/* + * returns: -ERRNO if error (returned to user) + * 0: tell VFS to invalidate dentry + * 1: dentry is valid + */ +static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + int err = 1; + struct path parent_lower_path, lower_path; + struct dentry *parent_dentry = NULL; + struct dentry *parent_lower_dentry = NULL; + struct dentry *lower_cur_parent_dentry = NULL; + struct dentry *lower_dentry = NULL; + + if (flags & LOOKUP_RCU) + return -ECHILD; + + spin_lock(&dentry->d_lock); + if (IS_ROOT(dentry)) { + spin_unlock(&dentry->d_lock); + return 1; + } + spin_unlock(&dentry->d_lock); + + /* check uninitialized obb_dentry and + * whether the base obbpath has been changed or not */ + if (is_obbpath_invalid(dentry)) { + d_drop(dentry); + return 0; + } + + parent_dentry = dget_parent(dentry); + sdcardfs_get_lower_path(parent_dentry, &parent_lower_path); + sdcardfs_get_real_lower(dentry, &lower_path); + parent_lower_dentry = parent_lower_path.dentry; + lower_dentry = lower_path.dentry; + lower_cur_parent_dentry = dget_parent(lower_dentry); + + spin_lock(&lower_dentry->d_lock); + if (d_unhashed(lower_dentry)) { + spin_unlock(&lower_dentry->d_lock); + d_drop(dentry); + err = 0; + goto out; + } + spin_unlock(&lower_dentry->d_lock); + + if (parent_lower_dentry != lower_cur_parent_dentry) { + d_drop(dentry); + err = 0; + goto out; + } + + if (dentry == lower_dentry) { + err = 0; + panic("sdcardfs: dentry is equal to lower_dentry\n"); + goto out; + } + + if (dentry < lower_dentry) { + spin_lock(&dentry->d_lock); + spin_lock(&lower_dentry->d_lock); + } else { + spin_lock(&lower_dentry->d_lock); + spin_lock(&dentry->d_lock); + } + + if (dentry->d_name.len != lower_dentry->d_name.len) { + __d_drop(dentry); + err = 0; + } else if (strncasecmp(dentry->d_name.name, lower_dentry->d_name.name, + dentry->d_name.len) != 0) { + __d_drop(dentry); + err = 0; + } + + if (dentry < lower_dentry) { + spin_unlock(&lower_dentry->d_lock); + spin_unlock(&dentry->d_lock); + } else { + spin_unlock(&dentry->d_lock); + spin_unlock(&lower_dentry->d_lock); + } + +out: + dput(parent_dentry); + dput(lower_cur_parent_dentry); + sdcardfs_put_lower_path(parent_dentry, &parent_lower_path); + sdcardfs_put_real_lower(dentry, &lower_path); + return err; +} + +static void sdcardfs_d_release(struct dentry *dentry) +{ + /* release and reset the lower paths */ + if(has_graft_path(dentry)) { + sdcardfs_put_reset_orig_path(dentry); + } + sdcardfs_put_reset_lower_path(dentry); + free_dentry_private_data(dentry); + return; +} + +static int sdcardfs_hash_ci(const struct dentry *dentry, + struct qstr *qstr) +{ + /* + * This function is copy of vfat_hashi. + * FIXME Should we support national language? + * Refer to vfat_hashi() + * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; + */ + const unsigned char *name; + unsigned int len; + unsigned long hash; + + name = qstr->name; + //len = vfat_striptail_len(qstr); + len = qstr->len; + + hash = init_name_hash(); + while (len--) + //hash = partial_name_hash(nls_tolower(t, *name++), hash); + hash = partial_name_hash(tolower(*name++), hash); + qstr->hash = end_name_hash(hash); + + return 0; +} + +/* + * Case insensitive compare of two vfat names. + */ +static int sdcardfs_cmp_ci(const struct dentry *parent, + const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + /* This function is copy of vfat_cmpi */ + // FIXME Should we support national language? + //struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io; + //unsigned int alen, blen; + + /* A filename cannot end in '.' or we treat it like it has none */ + /* + alen = vfat_striptail_len(name); + blen = __vfat_striptail_len(len, str); + if (alen == blen) { + if (nls_strnicmp(t, name->name, str, alen) == 0) + return 0; + } + */ + if (name->len == len) { + if (strncasecmp(name->name, str, len) == 0) + return 0; + } + return 1; +} + +const struct dentry_operations sdcardfs_ci_dops = { + .d_revalidate = sdcardfs_d_revalidate, + .d_release = sdcardfs_d_release, + .d_hash = sdcardfs_hash_ci, + .d_compare = sdcardfs_cmp_ci, +}; + diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c new file mode 100644 index 000000000000..65cc66e5b335 --- /dev/null +++ b/fs/sdcardfs/derived_perm.c @@ -0,0 +1,299 @@ +/* + * fs/sdcardfs/derived_perm.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" + +/* copy derived state from parent inode */ +static void inherit_derived_state(struct inode *parent, struct inode *child) +{ + struct sdcardfs_inode_info *pi = SDCARDFS_I(parent); + struct sdcardfs_inode_info *ci = SDCARDFS_I(child); + + ci->perm = PERM_INHERIT; + ci->userid = pi->userid; + ci->d_uid = pi->d_uid; + ci->d_gid = pi->d_gid; + ci->under_android = pi->under_android; +} + +/* helper function for derived state */ +void setup_derived_state(struct inode *inode, perm_t perm, + userid_t userid, uid_t uid, gid_t gid, bool under_android) +{ + struct sdcardfs_inode_info *info = SDCARDFS_I(inode); + + info->perm = perm; + info->userid = userid; + info->d_uid = uid; + info->d_gid = gid; + info->under_android = under_android; +} + +void get_derived_permission(struct dentry *parent, struct dentry *dentry) +{ + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode); + struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode); +#ifdef CONFIG_SDP + struct sdcardfs_dentry_info *parent_dinfo = SDCARDFS_D(parent); +#endif + appid_t appid; + + /* By default, each inode inherits from its parent. + * the properties are maintained on its private fields + * because the inode attributes will be modified with that of + * its lower inode. + * The derived state will be updated on the last + * stage of each system call by fix_derived_permission(inode). + */ + + inherit_derived_state(parent->d_inode, dentry->d_inode); + + //printk(KERN_INFO "sdcardfs: derived: %s, %s, %d\n", parent->d_name.name, + // dentry->d_name.name, parent_info->perm); + + /* Derive custom permissions based on parent and current node */ + switch (parent_info->perm) { + case PERM_INHERIT: + /* Already inherited above */ + break; + case PERM_PRE_ROOT: + /* Legacy internal layout places users at top level */ + info->perm = PERM_ROOT; + info->userid = simple_strtoul(dentry->d_name.name, NULL, 10); +#ifdef CONFIG_SDP + if(parent_dinfo->under_knox && (parent_dinfo->userid >= 0)) { + info->userid = parent_dinfo->userid; + } +#endif + break; + case PERM_ROOT: + /* Assume masked off by default. */ + if (!strcasecmp(dentry->d_name.name, "Android")) { + /* App-specific directories inside; let anyone traverse */ + info->perm = PERM_ANDROID; + info->under_android = true; + } + break; + case PERM_ANDROID: + if (!strcasecmp(dentry->d_name.name, "data")) { + /* App-specific directories inside; let anyone traverse */ + info->perm = PERM_ANDROID_DATA; + } else if (!strcasecmp(dentry->d_name.name, "obb")) { + /* App-specific directories inside; let anyone traverse */ + info->perm = PERM_ANDROID_OBB; + // FIXME : this feature will be implemented later. + /* Single OBB directory is always shared */ + } else if (!strcasecmp(dentry->d_name.name, "media")) { + /* App-specific directories inside; let anyone traverse */ + info->perm = PERM_ANDROID_MEDIA; + } + break; + /* same policy will be applied on PERM_ANDROID_DATA + * and PERM_ANDROID_OBB */ + case PERM_ANDROID_DATA: + case PERM_ANDROID_OBB: + case PERM_ANDROID_MEDIA: + appid = get_appid(sbi->pkgl_id, dentry->d_name.name); + if (appid != 0) { + info->d_uid = multiuser_get_uid(parent_info->userid, appid); + } + break; + } +} + +/* set vfs_inode from sdcardfs_inode */ +void fix_derived_permission(struct inode *inode) { + struct sdcardfs_inode_info *info = SDCARDFS_I(inode); + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(inode->i_sb); + struct sdcardfs_mount_options *opts = &sbi->options; + mode_t visible_mode; + mode_t owner_mode; + mode_t filtered_mode; + + inode->i_uid = make_kuid(current_user_ns(), info->d_uid); + + if (info->d_gid == AID_SDCARD_RW) { + /* As an optimization, certain trusted system components only run + * as owner but operate across all users. Since we're now handing + * out the sdcard_rw GID only to trusted apps, we're okay relaxing + * the user boundary enforcement for the default view. The UIDs + * assigned to app directories are still multiuser aware. */ + inode->i_gid = make_kgid(current_user_ns(), AID_SDCARD_RW); + } else { + inode->i_gid = make_kgid(current_user_ns(), multiuser_get_uid(info->userid, info->d_gid)); + } + + visible_mode = 00775 & ~opts->mask; + if (info->perm == PERM_PRE_ROOT) { + /* Top of multi-user view should always be visible to ensure + * secondary users can traverse inside. */ + visible_mode = 00711; + } else if (info->under_android) { + if (info->d_gid == AID_SDCARD_RW) { + visible_mode = visible_mode & ~00006; + } else { + visible_mode = visible_mode & ~00007; + } + } + + owner_mode = inode->i_mode & 0700; + filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6)); + inode->i_mode = ((inode->i_mode & S_IFMT) | filtered_mode); +} + +/* main function for updating derived permission */ +inline void update_derived_permission(struct dentry *dentry) +{ + struct dentry *parent; + + if(!dentry || !dentry->d_inode) { + printk(KERN_ERR "sdcardfs: %s: invalid dentry\n", __func__); + return; + } + /* FIXME: + * 1. need to check whether the dentry is updated or not + * 2. remove the root dentry update + */ + if(IS_ROOT(dentry)) { + //setup_default_pre_root_state(dentry->d_inode); + } else { + parent = dget_parent(dentry); + if(parent) { + get_derived_permission(parent, dentry); + dput(parent); + } + } + fix_derived_permission(dentry->d_inode); +} + +int need_graft_path(struct dentry *dentry) +{ + int ret = 0; + struct dentry *parent = dget_parent(dentry); + struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode); + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + + if(parent_info->perm == PERM_ANDROID && + !strcasecmp(dentry->d_name.name, "obb") && + sbi->options.multi_user) { + ret = 1; + } + dput(parent); + return ret; +} + +int is_obbpath_invalid(struct dentry *dent) +{ + int ret = 0; + struct sdcardfs_dentry_info *di = SDCARDFS_D(dent); + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dent->d_sb); + char *path_buf, *obbpath_s; + + /* check the base obbpath has been changed. + * this routine can check an uninitialized obb dentry as well. + * regarding the uninitialized obb, refer to the sdcardfs_mkdir() */ + spin_lock(&di->lock); + if(di->orig_path.dentry) { + if(!di->lower_path.dentry) { + ret = 1; + } else { + path_get(&di->lower_path); + //lower_parent = lock_parent(lower_path->dentry); + + path_buf = kmalloc(PATH_MAX, GFP_ATOMIC); + if(!path_buf) { + ret = 1; + printk(KERN_ERR "sdcardfs: " + "fail to allocate path_buf in %s.\n", __func__); + } else { + obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX); + if (d_unhashed(di->lower_path.dentry) || + strcasecmp(sbi->obbpath_s, obbpath_s)) { + ret = 1; + } + kfree(path_buf); + } + + //unlock_dir(lower_parent); + path_put(&di->lower_path); + } + } + spin_unlock(&di->lock); + return ret; +} + +int is_base_obbpath(struct dentry *dentry) +{ + int ret = 0; + struct dentry *parent = dget_parent(dentry); + struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode); + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + + spin_lock(&SDCARDFS_D(dentry)->lock); + /* if multi_user is true */ + if(sbi->options.multi_user && parent_info->perm == PERM_PRE_ROOT && + !strcasecmp(dentry->d_name.name, "obb")) { + ret = 1; + } + /* if multi_user is false, /Android/obb is the base obbpath */ + else if (!sbi->options.multi_user && parent_info->perm == PERM_ANDROID && + !strcasecmp(dentry->d_name.name, "obb")) { + ret = 1; + } + spin_unlock(&SDCARDFS_D(dentry)->lock); + dput(parent); + return ret; +} + +/* The lower_path will be stored to the dentry's orig_path + * and the base obbpath will be copyed to the lower_path variable. + * if an error returned, there's no change in the lower_path + * returns: -ERRNO if error (0: no error) */ +int setup_obb_dentry(struct dentry *dentry, struct path *lower_path) +{ + int err = 0; + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + struct path obbpath; + + /* A local obb dentry must have its own orig_path to support rmdir + * and mkdir of itself. Usually, we expect that the sbi->obbpath + * is avaiable on this stage. */ + sdcardfs_set_orig_path(dentry, lower_path); + + err = kern_path(sbi->obbpath_s, + LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath); + + if(!err) { + /* the obbpath base has been found */ + printk(KERN_INFO "sdcardfs: " + "the sbi->obbpath is found\n"); + pathcpy(lower_path, &obbpath); + } else { + /* if the sbi->obbpath is not available, we can optionally + * setup the lower_path with its orig_path. + * but, the current implementation just returns an error + * because the sdcard daemon also regards this case as + * a lookup fail. */ + printk(KERN_INFO "sdcardfs: " + "the sbi->obbpath is not available\n"); + } + return err; +} diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c new file mode 100644 index 000000000000..444b0bf18c26 --- /dev/null +++ b/fs/sdcardfs/file.c @@ -0,0 +1,359 @@ +/* + * fs/sdcardfs/file.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" +#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE +#include +#endif + +static ssize_t sdcardfs_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int err; + struct file *lower_file; + struct dentry *dentry = file->f_path.dentry; +#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE + struct backing_dev_info *bdi; +#endif + + lower_file = sdcardfs_lower_file(file); + +#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE + if (file->f_mode & FMODE_NOACTIVE) { + if (!(lower_file->f_mode & FMODE_NOACTIVE)) { + bdi = lower_file->f_mapping->backing_dev_info; + lower_file->f_ra.ra_pages = bdi->ra_pages * 2; + spin_lock(&lower_file->f_lock); + lower_file->f_mode |= FMODE_NOACTIVE; + spin_unlock(&lower_file->f_lock); + } + } +#endif + + err = vfs_read(lower_file, buf, count, ppos); + /* update our inode atime upon a successful lower read */ + if (err >= 0) + fsstack_copy_attr_atime(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + + return err; +} + +static ssize_t sdcardfs_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int err = 0; + struct file *lower_file; + struct dentry *dentry = file->f_path.dentry; + + /* check disk space */ + if (!check_min_free_space(dentry, count, 0)) { + printk(KERN_INFO "No minimum free space.\n"); + return -ENOSPC; + } + + lower_file = sdcardfs_lower_file(file); + err = vfs_write(lower_file, buf, count, ppos); + /* update our inode times+sizes upon a successful lower write */ + if (err >= 0) { + fsstack_copy_inode_size(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + fsstack_copy_attr_times(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + } + + return err; +} + +static int sdcardfs_readdir(struct file *file, struct dir_context *ctx) +{ + int err = 0; + struct file *lower_file = NULL; + struct dentry *dentry = file->f_path.dentry; + + lower_file = sdcardfs_lower_file(file); + + lower_file->f_pos = file->f_pos; + err = iterate_dir(lower_file, ctx); + file->f_pos = lower_file->f_pos; + if (err >= 0) /* copy the atime */ + fsstack_copy_attr_atime(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + return err; +} + +static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long err = -ENOTTY; + struct file *lower_file; + + lower_file = sdcardfs_lower_file(file); + + /* XXX: use vfs_ioctl if/when VFS exports it */ + if (!lower_file || !lower_file->f_op) + goto out; + if (lower_file->f_op->unlocked_ioctl) + err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); + +out: + return err; +} + +#ifdef CONFIG_COMPAT +static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long err = -ENOTTY; + struct file *lower_file; + + lower_file = sdcardfs_lower_file(file); + + /* XXX: use vfs_ioctl if/when VFS exports it */ + if (!lower_file || !lower_file->f_op) + goto out; + if (lower_file->f_op->compat_ioctl) + err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); + +out: + return err; +} +#endif + +static int sdcardfs_mmap(struct file *file, struct vm_area_struct *vma) +{ + int err = 0; + bool willwrite; + struct file *lower_file; + const struct vm_operations_struct *saved_vm_ops = NULL; + /* this might be deferred to mmap's writepage */ + willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags); + + /* + * File systems which do not implement ->writepage may use + * generic_file_readonly_mmap as their ->mmap op. If you call + * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL. + * But we cannot call the lower ->mmap op, so we can't tell that + * writeable mappings won't work. Therefore, our only choice is to + * check if the lower file system supports the ->writepage, and if + * not, return EINVAL (the same error that + * generic_file_readonly_mmap returns in that case). + */ + lower_file = sdcardfs_lower_file(file); + if (willwrite && !lower_file->f_mapping->a_ops->writepage) { + err = -EINVAL; + printk(KERN_ERR "sdcardfs: lower file system does not " + "support writeable mmap\n"); + goto out; + } + + /* + * find and save lower vm_ops. + * + * XXX: the VFS should have a cleaner way of finding the lower vm_ops + */ + if (!SDCARDFS_F(file)->lower_vm_ops) { + err = lower_file->f_op->mmap(lower_file, vma); + if (err) { + printk(KERN_ERR "sdcardfs: lower mmap failed %d\n", err); + goto out; + } + saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */ + err = do_munmap(current->mm, vma->vm_start, + vma->vm_end - vma->vm_start); + if (err) { + printk(KERN_ERR "sdcardfs: do_munmap failed %d\n", err); + goto out; + } + } + + /* + * Next 3 lines are all I need from generic_file_mmap. I definitely + * don't want its test for ->readpage which returns -ENOEXEC. + */ + file_accessed(file); + vma->vm_ops = &sdcardfs_vm_ops; + + file->f_mapping->a_ops = &sdcardfs_aops; /* set our aops */ + if (!SDCARDFS_F(file)->lower_vm_ops) /* save for our ->fault */ + SDCARDFS_F(file)->lower_vm_ops = saved_vm_ops; + +out: + return err; +} + +static int sdcardfs_open(struct inode *inode, struct file *file) +{ + int err = 0; + struct file *lower_file = NULL; + struct path lower_path; + struct dentry *dentry = file->f_path.dentry; + struct dentry *parent = dget_parent(dentry); + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + const struct cred *saved_cred = NULL; + + /* don't open unhashed/deleted files */ + if (d_unhashed(dentry)) { + err = -ENOENT; + goto out_err; + } + + if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + err = -EACCES; + goto out_err; + } + + /* save current_cred and override it */ + OVERRIDE_CRED(sbi, saved_cred); + + file->f_mode |= FMODE_NONMAPPABLE; + file->private_data = + kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); + if (!SDCARDFS_F(file)) { + err = -ENOMEM; + goto out_revert_cred; + } + + /* open lower object and link sdcardfs's file struct to lower's */ + sdcardfs_copy_lower_path(file->f_path.dentry, &lower_path); + lower_file = dentry_open(&lower_path, file->f_flags, current_cred()); + if (IS_ERR(lower_file)) { + err = PTR_ERR(lower_file); + lower_file = sdcardfs_lower_file(file); + if (lower_file) { + sdcardfs_set_lower_file(file, NULL); + fput(lower_file); /* fput calls dput for lower_dentry */ + } + } else { + sdcardfs_set_lower_file(file, lower_file); + } + + if (err) + kfree(SDCARDFS_F(file)); + else { + mutex_lock(&inode->i_mutex); + sdcardfs_copy_inode_attr(inode, sdcardfs_lower_inode(inode)); + fix_derived_permission(inode); + mutex_unlock(&inode->i_mutex); + } + +out_revert_cred: + REVERT_CRED(saved_cred); +out_err: + dput(parent); + return err; +} + +static int sdcardfs_flush(struct file *file, fl_owner_t id) +{ + int err = 0; + struct file *lower_file = NULL; + + lower_file = sdcardfs_lower_file(file); + if (lower_file && lower_file->f_op && lower_file->f_op->flush) + err = lower_file->f_op->flush(lower_file, id); + + return err; +} + +/* release all lower object references & free the file info structure */ +static int sdcardfs_file_release(struct inode *inode, struct file *file) +{ + struct file *lower_file; + + lower_file = sdcardfs_lower_file(file); + if (lower_file) { + sdcardfs_set_lower_file(file, NULL); + fput(lower_file); + } + + kfree(SDCARDFS_F(file)); + return 0; +} + +static int +sdcardfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) +{ + int err; + struct file *lower_file; + struct path lower_path; + struct dentry *dentry = file->f_path.dentry; + + lower_file = sdcardfs_lower_file(file); + sdcardfs_get_lower_path(dentry, &lower_path); + err = vfs_fsync_range(lower_file, start, end, datasync); + sdcardfs_put_lower_path(dentry, &lower_path); + + return err; +} + +static int sdcardfs_fasync(int fd, struct file *file, int flag) +{ + int err = 0; + struct file *lower_file = NULL; + + lower_file = sdcardfs_lower_file(file); + if (lower_file->f_op && lower_file->f_op->fasync) + err = lower_file->f_op->fasync(fd, lower_file, flag); + + return err; +} + +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, + .write = sdcardfs_write, + .unlocked_ioctl = sdcardfs_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sdcardfs_compat_ioctl, +#endif + .mmap = sdcardfs_mmap, + .open = sdcardfs_open, + .flush = sdcardfs_flush, + .release = sdcardfs_file_release, + .fsync = sdcardfs_fsync, + .fasync = sdcardfs_fasync, + .get_lower_file = sdcardfs_get_lower_file, +}; + +/* trimmed directory options */ +const struct file_operations sdcardfs_dir_fops = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = sdcardfs_readdir, + .unlocked_ioctl = sdcardfs_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sdcardfs_compat_ioctl, +#endif + .open = sdcardfs_open, + .release = sdcardfs_file_release, + .flush = sdcardfs_flush, + .fsync = sdcardfs_fsync, + .fasync = sdcardfs_fasync, + .get_lower_file = sdcardfs_get_lower_file, +}; diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c new file mode 100644 index 000000000000..2f462b464372 --- /dev/null +++ b/fs/sdcardfs/inode.c @@ -0,0 +1,895 @@ +/* + * fs/sdcardfs/inode.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" + +/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ +const struct cred * override_fsids(uid_t fsuid, gid_t fsgid) +{ + struct cred * cred; + const struct cred * old_cred; + + cred = prepare_creds(); + if (!cred) + return NULL; + + cred->fsuid = make_kuid(current_user_ns(), fsuid); + cred->fsgid = make_kgid(current_user_ns(), fsgid); + + old_cred = override_creds(cred); + + return old_cred; +} + +/* Do not directly use this function, use REVERT_CRED() instead. */ +void revert_fsids(const struct cred * old_cred) +{ + const struct cred * cur_cred; + + cur_cred = current->cred; + revert_creds(old_cred); + put_cred(cur_cred); +} + +static int sdcardfs_create(struct inode *dir, struct dentry *dentry, + umode_t mode, bool excl) +{ + int err = 0; + struct dentry *lower_dentry; + struct dentry *lower_parent_dentry = NULL; + struct path lower_path; + const struct cred *saved_cred = NULL; + + if(!check_caller_access_to_name(dir, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + err = -EACCES; + goto out_eacces; + } + + /* save current_cred and override it */ + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + lower_parent_dentry = lock_parent(lower_dentry); + + err = mnt_want_write(lower_path.mnt); + if (err) + goto out_unlock; + + /* set last 16bytes of mode field to 0664 */ + mode = (mode & S_IFMT) | 00664; + err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, true); + + if (err) + goto out; + + err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); + if (err) + goto out; + fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); + fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); + +out: + mnt_drop_write(lower_path.mnt); +out_unlock: + unlock_dir(lower_parent_dentry); + sdcardfs_put_lower_path(dentry, &lower_path); + REVERT_CRED(saved_cred); +out_eacces: + return err; +} + +#if 0 +static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *new_dentry) +{ + struct dentry *lower_old_dentry; + struct dentry *lower_new_dentry; + struct dentry *lower_dir_dentry; + u64 file_size_save; + int err; + struct path lower_old_path, lower_new_path; + + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); + + file_size_save = i_size_read(old_dentry->d_inode); + sdcardfs_get_lower_path(old_dentry, &lower_old_path); + sdcardfs_get_lower_path(new_dentry, &lower_new_path); + lower_old_dentry = lower_old_path.dentry; + lower_new_dentry = lower_new_path.dentry; + lower_dir_dentry = lock_parent(lower_new_dentry); + + err = mnt_want_write(lower_new_path.mnt); + if (err) + goto out_unlock; + + err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, + lower_new_dentry); + if (err || !lower_new_dentry->d_inode) + goto out; + + err = sdcardfs_interpose(new_dentry, dir->i_sb, &lower_new_path); + if (err) + goto out; + fsstack_copy_attr_times(dir, lower_new_dentry->d_inode); + fsstack_copy_inode_size(dir, lower_new_dentry->d_inode); + set_nlink(old_dentry->d_inode, + sdcardfs_lower_inode(old_dentry->d_inode)->i_nlink); + i_size_write(new_dentry->d_inode, file_size_save); +out: + mnt_drop_write(lower_new_path.mnt); +out_unlock: + unlock_dir(lower_dir_dentry); + sdcardfs_put_lower_path(old_dentry, &lower_old_path); + sdcardfs_put_lower_path(new_dentry, &lower_new_path); + REVERT_CRED(); + return err; +} +#endif + +static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) +{ + int err; + struct dentry *lower_dentry; + struct inode *lower_dir_inode = sdcardfs_lower_inode(dir); + struct dentry *lower_dir_dentry; + struct path lower_path; + const struct cred *saved_cred = NULL; + + if(!check_caller_access_to_name(dir, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + err = -EACCES; + goto out_eacces; + } + + /* save current_cred and override it */ + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + dget(lower_dentry); + lower_dir_dentry = lock_parent(lower_dentry); + + err = mnt_want_write(lower_path.mnt); + if (err) + goto out_unlock; + err = vfs_unlink(lower_dir_inode, lower_dentry, NULL); + + /* + * Note: unlinking on top of NFS can cause silly-renamed files. + * Trying to delete such files results in EBUSY from NFS + * below. Silly-renamed files will get deleted by NFS later on, so + * we just need to detect them here and treat such EBUSY errors as + * if the upper file was successfully deleted. + */ + if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) + err = 0; + if (err) + goto out; + fsstack_copy_attr_times(dir, lower_dir_inode); + fsstack_copy_inode_size(dir, lower_dir_inode); + set_nlink(dentry->d_inode, + sdcardfs_lower_inode(dentry->d_inode)->i_nlink); + dentry->d_inode->i_ctime = dir->i_ctime; + d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ +out: + mnt_drop_write(lower_path.mnt); +out_unlock: + unlock_dir(lower_dir_dentry); + dput(lower_dentry); + sdcardfs_put_lower_path(dentry, &lower_path); + REVERT_CRED(saved_cred); +out_eacces: + return err; +} + +#if 0 +static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry, + const char *symname) +{ + int err = 0; + struct dentry *lower_dentry; + struct dentry *lower_parent_dentry = NULL; + struct path lower_path; + + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + lower_parent_dentry = lock_parent(lower_dentry); + + err = mnt_want_write(lower_path.mnt); + if (err) + goto out_unlock; + err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname); + if (err) + goto out; + err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); + if (err) + goto out; + fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); + fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); + +out: + mnt_drop_write(lower_path.mnt); +out_unlock: + unlock_dir(lower_parent_dentry); + sdcardfs_put_lower_path(dentry, &lower_path); + REVERT_CRED(); + return err; +} +#endif + +static int touch(char *abs_path, mode_t mode) { + struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode); + if (IS_ERR(filp)) { + if (PTR_ERR(filp) == -EEXIST) { + return 0; + } + else { + printk(KERN_ERR "sdcardfs: failed to open(%s): %ld\n", + abs_path, PTR_ERR(filp)); + return PTR_ERR(filp); + } + } + filp_close(filp, current->files); + return 0; +} + +static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + int err = 0; + int make_nomedia_in_obb = 0; + struct dentry *lower_dentry; + struct dentry *lower_parent_dentry = NULL; + struct path lower_path; + const struct cred *saved_cred = NULL; + struct sdcardfs_inode_info *pi = SDCARDFS_I(dir); + char *page_buf; + char *nomedia_dir_name; + char *nomedia_fullpath; + int fullpath_namelen; + int touch_err = 0; + + if(!check_caller_access_to_name(dir, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + err = -EACCES; + goto out_eacces; + } + + /* save current_cred and override it */ + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); + + /* check disk space */ + if (!check_min_free_space(dentry, 0, 1)) { + printk(KERN_INFO "sdcardfs: No minimum free space.\n"); + err = -ENOSPC; + goto out_revert; + } + + /* the lower_dentry is negative here */ + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + lower_parent_dentry = lock_parent(lower_dentry); + + err = mnt_want_write(lower_path.mnt); + if (err) { + unlock_dir(lower_parent_dentry); + goto out_unlock; + } + + /* set last 16bytes of mode field to 0775 */ + mode = (mode & S_IFMT) | 00775; + err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode); + + if (err) { + unlock_dir(lower_parent_dentry); + goto out; + } + + /* if it is a local obb dentry, setup it with the base obbpath */ + if(need_graft_path(dentry)) { + err = setup_obb_dentry(dentry, &lower_path); + if(err) { + /* if the sbi->obbpath is not available, the lower_path won't be + * changed by setup_obb_dentry() but the lower path is saved to + * its orig_path. this dentry will be revalidated later. + * but now, the lower_path should be NULL */ + sdcardfs_put_reset_lower_path(dentry); + + /* the newly created lower path which saved to its orig_path or + * the lower_path is the base obbpath. + * therefore, an additional path_get is required */ + path_get(&lower_path); + } else + make_nomedia_in_obb = 1; + } + + err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); + if (err) { + unlock_dir(lower_parent_dentry); + goto out; + } + + fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); + fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); + /* update number of links on parent directory */ + set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink); + + unlock_dir(lower_parent_dentry); + + if (!strcasecmp(dentry->d_name.name, "obb") && (pi->perm == PERM_ANDROID)) + make_nomedia_in_obb = 1; + + /* When creating /Android/data and /Android/obb, mark them as .nomedia */ + if (make_nomedia_in_obb || + ((pi->perm == PERM_ANDROID) && (!strcasecmp(dentry->d_name.name, "data")))) { + + page_buf = (char *)__get_free_page(GFP_KERNEL); + if (!page_buf) { + printk(KERN_ERR "sdcardfs: failed to allocate page buf\n"); + goto out; + } + + nomedia_dir_name = d_absolute_path(&lower_path, page_buf, PAGE_SIZE); + if (IS_ERR(nomedia_dir_name)) { + free_page((unsigned long)page_buf); + printk(KERN_ERR "sdcardfs: failed to get .nomedia dir name\n"); + goto out; + } + + fullpath_namelen = page_buf + PAGE_SIZE - nomedia_dir_name - 1; + fullpath_namelen += strlen("/.nomedia"); + nomedia_fullpath = kzalloc(fullpath_namelen + 1, GFP_KERNEL); + if (!nomedia_fullpath) { + free_page((unsigned long)page_buf); + printk(KERN_ERR "sdcardfs: failed to allocate .nomedia fullpath buf\n"); + goto out; + } + + strcpy(nomedia_fullpath, nomedia_dir_name); + free_page((unsigned long)page_buf); + strcat(nomedia_fullpath, "/.nomedia"); + touch_err = touch(nomedia_fullpath, 0664); + if (touch_err) { + printk(KERN_ERR "sdcardfs: failed to touch(%s): %d\n", + nomedia_fullpath, touch_err); + kfree(nomedia_fullpath); + goto out; + } + kfree(nomedia_fullpath); + } +out: + mnt_drop_write(lower_path.mnt); +out_unlock: + sdcardfs_put_lower_path(dentry, &lower_path); +out_revert: + REVERT_CRED(saved_cred); +out_eacces: + return err; +} + +static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct dentry *lower_dentry; + struct dentry *lower_dir_dentry; + int err; + struct path lower_path; + const struct cred *saved_cred = NULL; + //char *path_s = NULL; + + if(!check_caller_access_to_name(dir, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + err = -EACCES; + goto out_eacces; + } + + /* save current_cred and override it */ + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); + + /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry + * the dentry on the original path should be deleted. */ + sdcardfs_get_real_lower(dentry, &lower_path); + + lower_dentry = lower_path.dentry; + lower_dir_dentry = lock_parent(lower_dentry); + + err = mnt_want_write(lower_path.mnt); + if (err) + goto out_unlock; + err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); + if (err) + goto out; + + d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ + if (dentry->d_inode) + clear_nlink(dentry->d_inode); + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); + fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); + set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); + +out: + mnt_drop_write(lower_path.mnt); +out_unlock: + unlock_dir(lower_dir_dentry); + sdcardfs_put_real_lower(dentry, &lower_path); + REVERT_CRED(saved_cred); +out_eacces: + return err; +} + +#if 0 +static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, + dev_t dev) +{ + int err = 0; + struct dentry *lower_dentry; + struct dentry *lower_parent_dentry = NULL; + struct path lower_path; + + OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + lower_parent_dentry = lock_parent(lower_dentry); + + err = mnt_want_write(lower_path.mnt); + if (err) + goto out_unlock; + err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev); + if (err) + goto out; + + err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path); + if (err) + goto out; + fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); + fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); + +out: + mnt_drop_write(lower_path.mnt); +out_unlock: + unlock_dir(lower_parent_dentry); + sdcardfs_put_lower_path(dentry, &lower_path); + REVERT_CRED(); + return err; +} +#endif + +/* + * The locking rules in sdcardfs_rename are complex. We could use a simpler + * superblock-level name-space lock for renames and copy-ups. + */ +static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) +{ + int err = 0; + struct dentry *lower_old_dentry = NULL; + struct dentry *lower_new_dentry = NULL; + struct dentry *lower_old_dir_dentry = NULL; + struct dentry *lower_new_dir_dentry = NULL; + struct dentry *trap = NULL; + struct dentry *new_parent = NULL; + struct dentry *old_parent = NULL; + struct path lower_old_path, lower_new_path; + const struct cred *saved_cred = NULL; + + if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name) || + !check_caller_access_to_name(new_dir, new_dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " new_dentry: %s, task:%s\n", + __func__, new_dentry->d_name.name, current->comm); + err = -EACCES; + goto out_eacces; + } + + /* save current_cred and override it */ + OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred); + + sdcardfs_get_real_lower(old_dentry, &lower_old_path); + sdcardfs_get_lower_path(new_dentry, &lower_new_path); + lower_old_dentry = lower_old_path.dentry; + lower_new_dentry = lower_new_path.dentry; + lower_old_dir_dentry = dget_parent(lower_old_dentry); + lower_new_dir_dentry = dget_parent(lower_new_dentry); + + trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); + /* source should not be ancestor of target */ + if (trap == lower_old_dentry) { + err = -EINVAL; + goto out; + } + /* target should not be ancestor of source */ + if (trap == lower_new_dentry) { + err = -ENOTEMPTY; + goto out; + } + + err = mnt_want_write(lower_old_path.mnt); + if (err) + goto out; + err = mnt_want_write(lower_new_path.mnt); + if (err) + goto out_drop_old_write; + + err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, + lower_new_dir_dentry->d_inode, lower_new_dentry, NULL, flags); + if (err) + goto out_err; + + /* Copy attrs from lower dir, but i_uid/i_gid */ + sdcardfs_copy_inode_attr(new_dir, lower_new_dir_dentry->d_inode); + fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode); + fix_derived_permission(new_dir); + if (new_dir != old_dir) { + sdcardfs_copy_inode_attr(old_dir, lower_old_dir_dentry->d_inode); + fsstack_copy_inode_size(old_dir, lower_old_dir_dentry->d_inode); + fix_derived_permission(old_dir); + /* update the derived permission of the old_dentry + * with its new parent + */ + new_parent = dget_parent(new_dentry); + if(new_parent) { + if(old_dentry->d_inode) { + get_derived_permission(new_parent, old_dentry); + fix_derived_permission(old_dentry->d_inode); + } + dput(new_parent); + } + /* if RENAME_EXCHANGE, + * update the derived permission of the new_dentry also + * because new_dentry will survive under old_parent after rename + */ + if (flags & RENAME_EXCHANGE) { + old_parent = dget_parent(old_dentry); + if(old_parent) { + if(new_dentry->d_inode) { + get_derived_permission(old_parent, new_dentry); + fix_derived_permission(new_dentry->d_inode); + } + dput(old_parent); + } + } + } + +out_err: + mnt_drop_write(lower_new_path.mnt); +out_drop_old_write: + mnt_drop_write(lower_old_path.mnt); +out: + unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); + dput(lower_old_dir_dentry); + dput(lower_new_dir_dentry); + sdcardfs_put_real_lower(old_dentry, &lower_old_path); + sdcardfs_put_lower_path(new_dentry, &lower_new_path); + REVERT_CRED(saved_cred); +out_eacces: + return err; +} + +#if 0 +static int sdcardfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) +{ + int err; + struct dentry *lower_dentry; + struct path lower_path; + /* XXX readlink does not requires overriding credential */ + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + if (!lower_dentry->d_inode->i_op || + !lower_dentry->d_inode->i_op->readlink) { + err = -EINVAL; + goto out; + } + + err = lower_dentry->d_inode->i_op->readlink(lower_dentry, + buf, bufsiz); + if (err < 0) + goto out; + fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); + +out: + sdcardfs_put_lower_path(dentry, &lower_path); + return err; +} +#endif + +#if 0 +static void *sdcardfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + char *buf; + int len = PAGE_SIZE, err; + mm_segment_t old_fs; + + /* This is freed by the put_link method assuming a successful call. */ + buf = kmalloc(len, GFP_KERNEL); + if (!buf) { + buf = ERR_PTR(-ENOMEM); + goto out; + } + + /* read the symlink, and then we will follow it */ + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sdcardfs_readlink(dentry, buf, len); + set_fs(old_fs); + if (err < 0) { + kfree(buf); + buf = ERR_PTR(err); + } else { + buf[err] = '\0'; + } +out: + nd_set_link(nd, buf); + return NULL; +} +#endif + +#if 0 +/* this @nd *IS* still used */ +static void sdcardfs_put_link(struct dentry *dentry, struct nameidata *nd, + void *cookie) +{ + char *buf = nd_get_link(nd); + if (!IS_ERR(buf)) /* free the char* */ + kfree(buf); +} +#endif + +static int sdcardfs_permission(struct inode *inode, int mask) +{ + int err; + + /* + * Permission check on sdcardfs inode. + * Calling process should have AID_SDCARD_RW permission + */ + err = generic_permission(inode, mask); + + /* XXX + * Original sdcardfs code calls inode_permission(lower_inode,.. ) + * for checking inode permission. But doing such things here seems + * duplicated work, because the functions called after this func, + * such as vfs_create, vfs_unlink, vfs_rename, and etc, + * does exactly same thing, i.e., they calls inode_permission(). + * So we just let they do the things. + * If there are any security hole, just uncomment following if block. + */ +#if 0 + if (!err) { + /* + * Permission check on lower_inode(=EXT4). + * we check it with AID_MEDIA_RW permission + */ + struct inode *lower_inode; + OVERRIDE_CRED(SDCARDFS_SB(inode->sb)); + + lower_inode = sdcardfs_lower_inode(inode); + err = inode_permission(lower_inode, mask); + + REVERT_CRED(); + } +#endif + return err; + +} + +static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) +{ + struct dentry *lower_dentry; + struct inode *inode; + struct inode *lower_inode; + struct path lower_path; + struct dentry *parent; + + parent = dget_parent(dentry); + if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + dput(parent); + return -EACCES; + } + dput(parent); + + inode = dentry->d_inode; + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + lower_inode = sdcardfs_lower_inode(inode); + + /* need to get inode->i_mutex */ + mutex_lock(&inode->i_mutex); + sdcardfs_copy_inode_attr(inode, lower_inode); + fsstack_copy_inode_size(inode, lower_inode); + /* if the dentry has been moved from other location + * so, on this stage, its derived permission must be + * rechecked from its private field. + */ + fix_derived_permission(inode); + mutex_unlock(&inode->i_mutex); + + generic_fillattr(inode, stat); + sdcardfs_put_lower_path(dentry, &lower_path); + return 0; +} + +static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia) +{ + int err = 0; + struct dentry *lower_dentry; + struct inode *inode; + struct inode *lower_inode; + struct path lower_path; + struct iattr lower_ia; + struct dentry *parent; + + inode = dentry->d_inode; + + /* + * Check if user has permission to change inode. We don't check if + * this user can change the lower inode: that should happen when + * calling notify_change on the lower inode. + */ + err = inode_change_ok(inode, ia); + + /* no vfs_XXX operations required, cred overriding will be skipped. wj*/ + if (!err) { + /* check the Android group ID */ + parent = dget_parent(dentry); + if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) { + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + err = -EACCES; + } + dput(parent); + } + + if (err) + goto out_err; + + sdcardfs_get_lower_path(dentry, &lower_path); + lower_dentry = lower_path.dentry; + lower_inode = sdcardfs_lower_inode(inode); + + /* prepare our own lower struct iattr (with the lower file) */ + memcpy(&lower_ia, ia, sizeof(lower_ia)); + if (ia->ia_valid & ATTR_FILE) + lower_ia.ia_file = sdcardfs_lower_file(ia->ia_file); + + lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE); + + /* + * If shrinking, first truncate upper level to cancel writing dirty + * pages beyond the new eof; and also if its' maxbytes is more + * limiting (fail with -EFBIG before making any change to the lower + * level). There is no need to vmtruncate the upper level + * afterwards in the other cases: we fsstack_copy_inode_size from + * the lower level. + */ + if (ia->ia_valid & ATTR_SIZE) { + err = inode_newsize_ok(inode, ia->ia_size); + if (err) + goto out; + truncate_setsize(inode, ia->ia_size); + } + + /* + * mode change is for clearing setuid/setgid bits. Allow lower fs + * to interpret this in its own way. + */ + if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) + lower_ia.ia_valid &= ~ATTR_MODE; + + /* notify the (possibly copied-up) lower inode */ + /* + * Note: we use lower_dentry->d_inode, because lower_inode may be + * unlinked (no inode->i_sb and i_ino==0. This happens if someone + * tries to open(), unlink(), then ftruncate() a file. + */ + mutex_lock(&lower_dentry->d_inode->i_mutex); + err = notify_change(lower_dentry, &lower_ia, NULL); /* note: lower_ia */ + mutex_unlock(&lower_dentry->d_inode->i_mutex); + if (err) + goto out; + + /* get attributes from the lower inode, i_mutex held */ + sdcardfs_copy_inode_attr(inode, lower_inode); + /* update derived permission of the upper inode */ + fix_derived_permission(inode); + + /* + * Not running fsstack_copy_inode_size(inode, lower_inode), because + * VFS should update our inode size, and notify_change on + * lower_inode should update its size. + */ + +out: + sdcardfs_put_lower_path(dentry, &lower_path); +out_err: + return err; +} + +const struct inode_operations sdcardfs_symlink_iops = { + .permission = sdcardfs_permission, + .setattr = sdcardfs_setattr, +#ifdef SDCARD_FS_XATTR + .setxattr = sdcardfs_setxattr, + .getxattr = sdcardfs_getxattr, + .listxattr = sdcardfs_listxattr, + .removexattr = sdcardfs_removexattr, +#endif // SDCARD_FS_XATTR + /* XXX Following operations are implemented, + * but FUSE(sdcard) or FAT does not support them + * These methods are *NOT* perfectly tested. + .readlink = sdcardfs_readlink, + .follow_link = sdcardfs_follow_link, + .put_link = sdcardfs_put_link, + */ +}; + +const struct inode_operations sdcardfs_dir_iops = { + .create = sdcardfs_create, + .lookup = sdcardfs_lookup, + .permission = sdcardfs_permission, + .unlink = sdcardfs_unlink, + .mkdir = sdcardfs_mkdir, + .rmdir = sdcardfs_rmdir, + .rename2 = sdcardfs_rename, + .setattr = sdcardfs_setattr, + .getattr = sdcardfs_getattr, +#ifdef SDCARD_FS_XATTR + .setxattr = sdcardfs_setxattr, + .getxattr = sdcardfs_getxattr, + .listxattr = sdcardfs_listxattr, + .removexattr = sdcardfs_removexattr, +#endif // SDCARD_FS_XATTR + /* XXX Following operations are implemented, + * but FUSE(sdcard) or FAT does not support them + * These methods are *NOT* perfectly tested. + .symlink = sdcardfs_symlink, + .link = sdcardfs_link, + .mknod = sdcardfs_mknod, + */ +}; + +const struct inode_operations sdcardfs_main_iops = { + .permission = sdcardfs_permission, + .setattr = sdcardfs_setattr, + .getattr = sdcardfs_getattr, +#ifdef SDCARD_FS_XATTR + .setxattr = sdcardfs_setxattr, + .getxattr = sdcardfs_getxattr, + .listxattr = sdcardfs_listxattr, + .removexattr = sdcardfs_removexattr, +#endif // SDCARDFS_XATTR +}; diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c new file mode 100644 index 000000000000..fc5672bcc8f7 --- /dev/null +++ b/fs/sdcardfs/lookup.c @@ -0,0 +1,379 @@ +/* + * fs/sdcardfs/lookup.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" +#include "linux/delay.h" +#include "../internal.h" + +/* The dentry cache is just so we have properly sized dentries */ +static struct kmem_cache *sdcardfs_dentry_cachep; + +int sdcardfs_init_dentry_cache(void) +{ + sdcardfs_dentry_cachep = + kmem_cache_create("sdcardfs_dentry", + sizeof(struct sdcardfs_dentry_info), + 0, SLAB_RECLAIM_ACCOUNT, NULL); + + return sdcardfs_dentry_cachep ? 0 : -ENOMEM; +} + +void sdcardfs_destroy_dentry_cache(void) +{ + if (sdcardfs_dentry_cachep) + kmem_cache_destroy(sdcardfs_dentry_cachep); +} + +void free_dentry_private_data(struct dentry *dentry) +{ + if (!dentry || !dentry->d_fsdata) + return; + kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata); + dentry->d_fsdata = NULL; +} + +/* allocate new dentry private data */ +int new_dentry_private_data(struct dentry *dentry) +{ + struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry); + + /* use zalloc to init dentry_info.lower_path */ + info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC); + if (!info) + return -ENOMEM; + + spin_lock_init(&info->lock); + dentry->d_fsdata = info; + + return 0; +} + +static int sdcardfs_inode_test(struct inode *inode, void *candidate_lower_inode) +{ + /* if a lower_inode should have many upper inodes, (like obb) + sdcardfs_iget() will offer many inodes + because test func always will return fail although they have same hash */ + return 0; +} + +static int sdcardfs_inode_set(struct inode *inode, void *lower_inode) +{ + /* we do actual inode initialization in sdcardfs_iget */ + return 0; +} + +static struct inode *sdcardfs_iget(struct super_block *sb, + struct inode *lower_inode) +{ + struct sdcardfs_inode_info *info; + struct inode *inode; /* the new inode to return */ + int err; + + inode = iget5_locked(sb, /* our superblock */ + /* + * hashval: we use inode number, but we can + * also use "(unsigned long)lower_inode" + * instead. + */ + lower_inode->i_ino, /* hashval */ + sdcardfs_inode_test, /* inode comparison function */ + sdcardfs_inode_set, /* inode init function */ + lower_inode); /* data passed to test+set fxns */ + if (!inode) { + err = -EACCES; + iput(lower_inode); + return ERR_PTR(err); + } + /* if found a cached inode, then just return it */ + if (!(inode->i_state & I_NEW)) + return inode; + + /* initialize new inode */ + info = SDCARDFS_I(inode); + + inode->i_ino = lower_inode->i_ino; + if (!igrab(lower_inode)) { + err = -ESTALE; + return ERR_PTR(err); + } + sdcardfs_set_lower_inode(inode, lower_inode); + + inode->i_version++; + + /* use different set of inode ops for symlinks & directories */ + if (S_ISDIR(lower_inode->i_mode)) + inode->i_op = &sdcardfs_dir_iops; + else if (S_ISLNK(lower_inode->i_mode)) + inode->i_op = &sdcardfs_symlink_iops; + else + inode->i_op = &sdcardfs_main_iops; + + /* use different set of file ops for directories */ + if (S_ISDIR(lower_inode->i_mode)) + inode->i_fop = &sdcardfs_dir_fops; + else + inode->i_fop = &sdcardfs_main_fops; + + inode->i_mapping->a_ops = &sdcardfs_aops; + + inode->i_atime.tv_sec = 0; + inode->i_atime.tv_nsec = 0; + inode->i_mtime.tv_sec = 0; + inode->i_mtime.tv_nsec = 0; + inode->i_ctime.tv_sec = 0; + inode->i_ctime.tv_nsec = 0; + + /* properly initialize special inodes */ + if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || + S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) + init_special_inode(inode, lower_inode->i_mode, + lower_inode->i_rdev); + + /* all well, copy inode attributes, don't need to hold i_mutex here */ + sdcardfs_copy_inode_attr(inode, lower_inode); + fsstack_copy_inode_size(inode, lower_inode); + + fix_derived_permission(inode); + + unlock_new_inode(inode); + return inode; +} + +/* + * Connect a sdcardfs inode dentry/inode with several lower ones. This is + * the classic stackable file system "vnode interposition" action. + * + * @dentry: sdcardfs's dentry which interposes on lower one + * @sb: sdcardfs's super_block + * @lower_path: the lower path (caller does path_get/put) + */ +int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, + struct path *lower_path) +{ + int err = 0; + struct inode *inode; + struct inode *lower_inode; + struct super_block *lower_sb; + + lower_inode = lower_path->dentry->d_inode; + lower_sb = sdcardfs_lower_super(sb); + + /* check that the lower file system didn't cross a mount point */ + if (lower_inode->i_sb != lower_sb) { + err = -EXDEV; + goto out; + } + + /* + * We allocate our new inode below by calling sdcardfs_iget, + * which will initialize some of the new inode's fields + */ + + /* inherit lower inode number for sdcardfs's inode */ + inode = sdcardfs_iget(sb, lower_inode); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + + d_add(dentry, inode); + update_derived_permission(dentry); +out: + return err; +} + +/* + * Main driver function for sdcardfs's lookup. + * + * Returns: NULL (ok), ERR_PTR if an error occurred. + * Fills in lower_parent_path with on success. + */ +static struct dentry *__sdcardfs_lookup(struct dentry *dentry, + unsigned int flags, struct path *lower_parent_path) +{ + int err = 0; + struct vfsmount *lower_dir_mnt; + struct dentry *lower_dir_dentry = NULL; + struct dentry *lower_dentry; + const char *name; + struct path lower_path; + struct qstr this; + struct sdcardfs_sb_info *sbi; + + sbi = SDCARDFS_SB(dentry->d_sb); + /* must initialize dentry operations */ + d_set_d_op(dentry, &sdcardfs_ci_dops); + + if (IS_ROOT(dentry)) + goto out; + + name = dentry->d_name.name; + + /* now start the actual lookup procedure */ + lower_dir_dentry = lower_parent_path->dentry; + lower_dir_mnt = lower_parent_path->mnt; + + /* Use vfs_path_lookup to check if the dentry exists or not */ + if (sbi->options.lower_fs == LOWER_FS_EXT4) { + err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, + LOOKUP_CASE_INSENSITIVE, &lower_path); + } else if (sbi->options.lower_fs == LOWER_FS_FAT) { + err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, + &lower_path); + } + + /* no error: handle positive dentries */ + if (!err) { + /* check if the dentry is an obb dentry + * if true, the lower_inode must be replaced with + * the inode of the graft path */ + + if(need_graft_path(dentry)) { + + /* setup_obb_dentry() + * The lower_path will be stored to the dentry's orig_path + * and the base obbpath will be copyed to the lower_path variable. + * if an error returned, there's no change in the lower_path + * returns: -ERRNO if error (0: no error) */ + err = setup_obb_dentry(dentry, &lower_path); + + if(err) { + /* if the sbi->obbpath is not available, we can optionally + * setup the lower_path with its orig_path. + * but, the current implementation just returns an error + * because the sdcard daemon also regards this case as + * a lookup fail. */ + printk(KERN_INFO "sdcardfs: base obbpath is not available\n"); + sdcardfs_put_reset_orig_path(dentry); + goto out; + } + } + + sdcardfs_set_lower_path(dentry, &lower_path); + err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path); + if (err) /* path_put underlying path on error */ + sdcardfs_put_reset_lower_path(dentry); + goto out; + } + + /* + * We don't consider ENOENT an error, and we want to return a + * negative dentry. + */ + if (err && err != -ENOENT) + goto out; + + /* instatiate a new negative dentry */ + this.name = name; + this.len = strlen(name); + this.hash = full_name_hash(this.name, this.len); + lower_dentry = d_lookup(lower_dir_dentry, &this); + if (lower_dentry) + goto setup_lower; + + lower_dentry = d_alloc(lower_dir_dentry, &this); + if (!lower_dentry) { + err = -ENOMEM; + goto out; + } + d_add(lower_dentry, NULL); /* instantiate and hash */ + +setup_lower: + lower_path.dentry = lower_dentry; + lower_path.mnt = mntget(lower_dir_mnt); + sdcardfs_set_lower_path(dentry, &lower_path); + + /* + * If the intent is to create a file, then don't return an error, so + * the VFS will continue the process of making this negative dentry + * into a positive one. + */ + err = 0; + +out: + return ERR_PTR(err); +} + +/* + * On success: + * fills dentry object appropriate values and returns NULL. + * On fail (== error) + * returns error ptr + * + * @dir : Parent inode. It is locked (dir->i_mutex) + * @dentry : Target dentry to lookup. we should set each of fields. + * (dentry->d_name is initialized already) + * @nd : nameidata of parent inode + */ +struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + struct dentry *ret = NULL, *parent; + struct path lower_parent_path; + int err = 0; + const struct cred *saved_cred = NULL; + + parent = dget_parent(dentry); + + if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) { + ret = ERR_PTR(-EACCES); + printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" + " dentry: %s, task:%s\n", + __func__, dentry->d_name.name, current->comm); + goto out_err; + } + + /* save current_cred and override it */ + OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred); + + sdcardfs_get_lower_path(parent, &lower_parent_path); + + /* allocate dentry private data. We free it in ->d_release */ + err = new_dentry_private_data(dentry); + if (err) { + ret = ERR_PTR(err); + goto out; + } + + ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path); + if (IS_ERR(ret)) + { + goto out; + } + if (ret) + dentry = ret; + if (dentry->d_inode) { + fsstack_copy_attr_times(dentry->d_inode, + sdcardfs_lower_inode(dentry->d_inode)); + /* get drived permission */ + get_derived_permission(parent, dentry); + fix_derived_permission(dentry->d_inode); + } + /* update parent directory's atime */ + fsstack_copy_attr_atime(parent->d_inode, + sdcardfs_lower_inode(parent->d_inode)); + +out: + sdcardfs_put_lower_path(parent, &lower_parent_path); + REVERT_CRED(saved_cred); +out_err: + dput(parent); + return ret; +} diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c new file mode 100644 index 000000000000..ba30d49cfc7a --- /dev/null +++ b/fs/sdcardfs/main.c @@ -0,0 +1,440 @@ +/* + * fs/sdcardfs/main.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" +#include "version.h" +#include +#include +#include +#include "../internal.h" + +enum { + Opt_low_uid, + Opt_low_gid, + Opt_gid, + Opt_userid, + Opt_debug, + Opt_lower_fs, + Opt_reserved_mb, + Opt_mask, + Opt_multi_user, + Opt_label, + Opt_type, + Opt_err, +}; + +static const match_table_t sdcardfs_tokens = { + {Opt_low_uid, "low_uid=%u"}, + {Opt_low_gid, "low_gid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_userid, "userid=%u"}, + {Opt_debug, "debug"}, + {Opt_lower_fs, "lower_fs=%s"}, + {Opt_reserved_mb, "reserved_mb=%u"}, + {Opt_mask, "mask=%o"}, + {Opt_multi_user, "multi_user"}, + {Opt_label, "label=%s"}, + {Opt_type, "type=%s"}, + {Opt_err, NULL} +}; + +static int parse_options(struct super_block *sb, char *options, int silent, + int *debug, struct sdcardfs_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + char *string_option; + char *label; + + /* by default, we use AID_MEDIA_RW as low_uid, low_gid */ + opts->fs_low_uid = AID_MEDIA_RW; + opts->fs_low_gid = AID_MEDIA_RW; + /* by default, userid is 0, gid is AID_EVERYBODY */ + opts->gid = AID_EVERYBODY; + opts->userid = 0; + /* by default, we use LOWER_FS_EXT4 as lower fs type */ + opts->lower_fs = LOWER_FS_EXT4; + /* by default, 0MB is reserved */ + opts->reserved_mb = 0; + /* by default, mask is 0 */ + opts->mask = 0; + /* by default, multi_user is false */ + opts->multi_user = false; + opts->label = NULL; + opts->type = TYPE_NONE; + + *debug = 0; + + if (!options) + return 0; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + if (!*p) + continue; + + token = match_token(p, sdcardfs_tokens, args); + + switch (token) { + case Opt_debug: + *debug = 1; + break; + case Opt_low_uid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_low_uid = option; + break; + case Opt_low_gid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_low_gid = option; + break; + case Opt_gid: + if (match_int(&args[0], &option)) + goto invalid_option; + opts->gid = option; + break; + case Opt_userid: + if (match_int(&args[0], &option)) + goto invalid_option; + opts->userid = option; + break; + case Opt_lower_fs: + string_option = match_strdup(&args[0]); + if (!string_option) + return -ENOMEM; + if (!strcmp("ext4", string_option)) { + opts->lower_fs = LOWER_FS_EXT4; + } else if (!strcmp("fat", string_option)) { + opts->lower_fs = LOWER_FS_FAT; + } else { + kfree(string_option); + goto invalid_option; + } + kfree(string_option); + break; + case Opt_reserved_mb: + if (match_int(&args[0], &option)) + return 0; + opts->reserved_mb = option; + break; + case Opt_mask: + if (match_octal(&args[0], &option)) + goto invalid_option; + opts->mask = option; + break; + case Opt_multi_user: + opts->multi_user = true; + break; + case Opt_label: + label = match_strdup(&args[0]); + if (!label) + return -ENOMEM; + opts->label = label; + break; + case Opt_type: + string_option = match_strdup(&args[0]); + if (!string_option) + return -ENOMEM; + if (!strcmp("default", string_option)) { + opts->type = TYPE_DEFAULT; + } else if (!strcmp("read", string_option)) { + opts->type = TYPE_READ; + } else if (!strcmp("write", string_option)) { + opts->type = TYPE_WRITE; + } else { + kfree(string_option); + goto invalid_option; + } + kfree(string_option); + break; + /* unknown option */ + default: +invalid_option: + if (!silent) { + printk( KERN_ERR "Unrecognized mount option \"%s\" " + "or missing value", p); + } + return -EINVAL; + } + } + + if (*debug) { + printk( KERN_INFO "sdcardfs : options - debug:%d\n", *debug); + printk( KERN_INFO "sdcardfs : options - uid:%d\n", + opts->fs_low_uid); + printk( KERN_INFO "sdcardfs : options - gid:%d\n", + opts->fs_low_gid); + } + + return 0; +} + +/* + * our custom d_alloc_root work-alike + * + * we can't use d_alloc_root if we want to use our own interpose function + * unchanged, so we simply call our own "fake" d_alloc_root + */ +static struct dentry *sdcardfs_d_alloc_root(struct super_block *sb) +{ + struct dentry *ret = NULL; + + if (sb) { + static const struct qstr name = { + .name = "/", + .len = 1 + }; + + ret = __d_alloc(sb, &name); + if (ret) { + d_set_d_op(ret, &sdcardfs_ci_dops); + ret->d_parent = ret; + } + } + return ret; +} + +/* + * There is no need to lock the sdcardfs_super_info's rwsem as there is no + * way anyone can have a reference to the superblock at this point in time. + */ +static int sdcardfs_read_super(struct super_block *sb, const char *dev_name, + void *raw_data, int silent) +{ + int err = 0; + int debug; + struct super_block *lower_sb; + struct path lower_path; + struct sdcardfs_sb_info *sb_info; + void *pkgl_id; + + printk(KERN_INFO "sdcardfs: version %s\n", SDCARDFS_VERSION); + + if (!dev_name) { + printk(KERN_ERR + "sdcardfs: read_super: missing dev_name argument\n"); + err = -EINVAL; + goto out; + } + + printk(KERN_INFO "sdcardfs: dev_name -> %s\n", dev_name); + printk(KERN_INFO "sdcardfs: options -> %s\n", (char *)raw_data); + + /* parse lower path */ + err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, + &lower_path); + if (err) { + printk(KERN_ERR "sdcardfs: error accessing " + "lower directory '%s'\n", dev_name); + goto out; + } + + /* allocate superblock private data */ + sb->s_fs_info = kzalloc(sizeof(struct sdcardfs_sb_info), GFP_KERNEL); + if (!SDCARDFS_SB(sb)) { + printk(KERN_CRIT "sdcardfs: read_super: out of memory\n"); + err = -ENOMEM; + goto out_free; + } + + sb_info = sb->s_fs_info; + + /* parse options */ + err = parse_options(sb, raw_data, silent, &debug, &sb_info->options); + if (err) { + printk(KERN_ERR "sdcardfs: invalid options or out of memory\n"); + goto out_freesbi; + } + + pkgl_id = packagelist_create(); + if(IS_ERR(pkgl_id)) + goto out_freesbi; + else + sb_info->pkgl_id = pkgl_id; + + /* set the lower superblock field of upper superblock */ + lower_sb = lower_path.dentry->d_sb; + atomic_inc(&lower_sb->s_active); + sdcardfs_set_lower_super(sb, lower_sb); + + /* inherit maxbytes from lower file system */ + sb->s_maxbytes = lower_sb->s_maxbytes; + + /* + * Our c/m/atime granularity is 1 ns because we may stack on file + * systems whose granularity is as good. + */ + sb->s_time_gran = 1; + + sb->s_magic = SDCARDFS_SUPER_MAGIC; + if (sb_info->options.type != TYPE_NONE) + sb->s_op = &sdcardfs_multimount_sops; + else + sb->s_op = &sdcardfs_sops; + + /* see comment next to the definition of sdcardfs_d_alloc_root */ + sb->s_root = sdcardfs_d_alloc_root(sb); + if (!sb->s_root) { + err = -ENOMEM; + goto out_sput; + } + + /* link the upper and lower dentries */ + sb->s_root->d_fsdata = NULL; + err = new_dentry_private_data(sb->s_root); + if (err) + goto out_freeroot; + + /* set the lower dentries for s_root */ + sdcardfs_set_lower_path(sb->s_root, &lower_path); + + /* call interpose to create the upper level inode */ + err = sdcardfs_interpose(sb->s_root, sb, &lower_path); + if (!err) { + /* setup permission policy */ + if(sb_info->options.multi_user){ + setup_derived_state(sb->s_root->d_inode, + PERM_PRE_ROOT, sb_info->options.userid, AID_ROOT, sb_info->options.gid, false); + sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL); + snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name); + err = prepare_dir(sb_info->obbpath_s, + sb_info->options.fs_low_uid, + sb_info->options.fs_low_gid, 00775); + } else { + setup_derived_state(sb->s_root->d_inode, + PERM_ROOT, sb_info->options.userid, AID_ROOT, sb_info->options.gid, false); + sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL); + snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name); + } + fix_derived_permission(sb->s_root->d_inode); + + sb_info->devpath = kzalloc(PATH_MAX, GFP_KERNEL); + if(sb_info->devpath && dev_name) + strncpy(sb_info->devpath, dev_name, strlen(dev_name)); + + if (!silent && !err) + printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n", + dev_name, lower_sb->s_type->name); + goto out; + } + /* else error: fall through */ + + free_dentry_private_data(sb->s_root); +out_freeroot: + dput(sb->s_root); +out_sput: + /* drop refs we took earlier */ + atomic_dec(&lower_sb->s_active); + packagelist_destroy(sb_info->pkgl_id); +out_freesbi: + kfree(SDCARDFS_SB(sb)); + sb->s_fs_info = NULL; +out_free: + path_put(&lower_path); + +out: + return err; +} + +/* A feature which supports mount_nodev() with options */ +static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + int (*fill_super)(struct super_block *, const char *, void *, int)) + +{ + int error; + struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL); + + if (IS_ERR(s)) + return ERR_CAST(s); + + s->s_flags = flags; + + error = fill_super(s, dev_name, data, flags & MS_SILENT ? 1 : 0); + if (error) { + deactivate_locked_super(s); + return ERR_PTR(error); + } + s->s_flags |= MS_ACTIVE; + return dget(s->s_root); +} + +struct dentry *sdcardfs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data) +{ + /* + * dev_name is a lower_path_name, + * raw_data is a option string. + */ + return mount_nodev_with_options(fs_type, flags, dev_name, + raw_data, sdcardfs_read_super); +} + +static struct file_system_type sdcardfs_fs_type = { + .owner = THIS_MODULE, + .name = SDCARDFS_NAME, + .mount = sdcardfs_mount, + .kill_sb = generic_shutdown_super, + .fs_flags = 0, +}; + +static int __init init_sdcardfs_fs(void) +{ + int err; + + pr_info("Registering sdcardfs " SDCARDFS_VERSION "\n"); + + err = sdcardfs_init_inode_cache(); + if (err) + goto out; + err = sdcardfs_init_dentry_cache(); + if (err) + goto out; + err = packagelist_init(); + if (err) + goto out; + err = register_filesystem(&sdcardfs_fs_type); +out: + if (err) { + sdcardfs_destroy_inode_cache(); + sdcardfs_destroy_dentry_cache(); + packagelist_exit(); + } + return err; +} + +static void __exit exit_sdcardfs_fs(void) +{ + sdcardfs_destroy_inode_cache(); + sdcardfs_destroy_dentry_cache(); + packagelist_exit(); + unregister_filesystem(&sdcardfs_fs_type); + pr_info("Completed sdcardfs module unload\n"); +} + +MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil" + " System Memory Lab., Samsung Electronics"); +MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION); +MODULE_LICENSE("GPL"); + +module_init(init_sdcardfs_fs); +module_exit(exit_sdcardfs_fs); diff --git a/fs/sdcardfs/mmap.c b/fs/sdcardfs/mmap.c new file mode 100644 index 000000000000..5fdb4842913e --- /dev/null +++ b/fs/sdcardfs/mmap.c @@ -0,0 +1,81 @@ +/* + * fs/sdcardfs/mmap.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" + +static int sdcardfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + int err; + struct file *file, *lower_file; + const struct vm_operations_struct *lower_vm_ops; + struct vm_area_struct lower_vma; + + memcpy(&lower_vma, vma, sizeof(struct vm_area_struct)); + file = lower_vma.vm_file; + lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops; + BUG_ON(!lower_vm_ops); + + lower_file = sdcardfs_lower_file(file); + /* + * XXX: vm_ops->fault may be called in parallel. Because we have to + * resort to temporarily changing the vma->vm_file to point to the + * lower file, a concurrent invocation of sdcardfs_fault could see a + * different value. In this workaround, we keep a different copy of + * the vma structure in our stack, so we never expose a different + * value of the vma->vm_file called to us, even temporarily. A + * better fix would be to change the calling semantics of ->fault to + * take an explicit file pointer. + */ + lower_vma.vm_file = lower_file; + err = lower_vm_ops->fault(&lower_vma, vmf); + return err; +} + +static ssize_t sdcardfs_direct_IO(int rw, struct kiocb *iocb, + struct iov_iter *iter, loff_t offset) +{ + /* + * This function returns zero on purpose in order to support direct IO. + * __dentry_open checks a_ops->direct_IO and returns EINVAL if it is null. + * + * However, this function won't be called by certain file operations + * including generic fs functions. * reads and writes are delivered to + * the lower file systems and the direct IOs will be handled by them. + * + * NOTE: exceptionally, on the recent kernels (since Linux 3.8.x), + * swap_writepage invokes this function directly. + */ + printk(KERN_INFO "%s, operation is not supported\n", __func__); + return 0; +} + +/* + * XXX: the default address_space_ops for sdcardfs is empty. We cannot set + * our inode->i_mapping->a_ops to NULL because too many code paths expect + * the a_ops vector to be non-NULL. + */ +const struct address_space_operations sdcardfs_aops = { + /* empty on purpose */ + .direct_IO = sdcardfs_direct_IO, +}; + +const struct vm_operations_struct sdcardfs_vm_ops = { + .fault = sdcardfs_fault, +}; diff --git a/fs/sdcardfs/multiuser.h b/fs/sdcardfs/multiuser.h new file mode 100644 index 000000000000..923ba101dfa9 --- /dev/null +++ b/fs/sdcardfs/multiuser.h @@ -0,0 +1,37 @@ +/* + * fs/sdcardfs/multiuser.h + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#define MULTIUSER_APP_PER_USER_RANGE 100000 + +typedef uid_t userid_t; +typedef uid_t appid_t; + +static inline userid_t multiuser_get_user_id(uid_t uid) { + return uid / MULTIUSER_APP_PER_USER_RANGE; +} + +static inline appid_t multiuser_get_app_id(uid_t uid) { + return uid % MULTIUSER_APP_PER_USER_RANGE; +} + +static inline uid_t multiuser_get_uid(userid_t userId, appid_t appId) { + return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE); +} + diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c new file mode 100644 index 000000000000..0119430d67c0 --- /dev/null +++ b/fs/sdcardfs/packagelist.c @@ -0,0 +1,359 @@ +/* + * fs/sdcardfs/packagelist.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" +#include +#include +#include +#include +#include + +#define STRING_BUF_SIZE (512) + +struct hashtable_entry { + struct hlist_node hlist; + void *key; + int value; +}; + +struct packagelist_data { + DECLARE_HASHTABLE(package_to_appid,8); + struct mutex hashtable_lock; + struct task_struct *thread_id; + char read_buf[STRING_BUF_SIZE]; + char event_buf[STRING_BUF_SIZE]; + char app_name_buf[STRING_BUF_SIZE]; + char gids_buf[STRING_BUF_SIZE]; +}; + +static struct kmem_cache *hashtable_entry_cachep; + +/* Path to system-provided mapping of package name to appIds */ +static const char* const kpackageslist_file = "/data/system/packages.list"; +/* Supplementary groups to execute with */ +static const gid_t kgroups[1] = { AID_PACKAGE_INFO }; + +static unsigned int str_hash(void *key) { + int i; + unsigned int h = strlen(key); + char *data = (char *)key; + + for (i = 0; i < strlen(key); i++) { + h = h * 31 + *data; + data++; + } + return h; +} + +appid_t get_appid(void *pkgl_id, const char *app_name) +{ + struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id; + struct hashtable_entry *hash_cur; + unsigned int hash = str_hash((void *)app_name); + appid_t ret_id; + + //printk(KERN_INFO "sdcardfs: %s: %s, %u\n", __func__, (char *)app_name, hash); + mutex_lock(&pkgl_dat->hashtable_lock); + hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) { + //printk(KERN_INFO "sdcardfs: %s: %s\n", __func__, (char *)hash_cur->key); + if (!strcasecmp(app_name, hash_cur->key)) { + ret_id = (appid_t)hash_cur->value; + mutex_unlock(&pkgl_dat->hashtable_lock); + //printk(KERN_INFO "=> app_id: %d\n", (int)ret_id); + return ret_id; + } + } + mutex_unlock(&pkgl_dat->hashtable_lock); + //printk(KERN_INFO "=> app_id: %d\n", 0); + return 0; +} + +/* Kernel has already enforced everything we returned through + * derive_permissions_locked(), so this is used to lock down access + * even further, such as enforcing that apps hold sdcard_rw. */ +int check_caller_access_to_name(struct inode *parent_node, const char* name) { + /* Always block security-sensitive files at root */ + if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) { + if (!strcasecmp(name, "autorun.inf") + || !strcasecmp(name, ".android_secure") + || !strcasecmp(name, "android_secure")) { + return 0; + } + } + + /* Root always has access; access for any other UIDs should always + * be controlled through packages.list. */ + if (uid_eq(current_fsuid(), make_kuid(current_user_ns(), 0))) { + return 1; + } + + /* No extra permissions to enforce */ + return 1; +} + +/* This function is used when file opening. The open flags must be + * checked before calling check_caller_access_to_name() */ +int open_flags_to_access_mode(int open_flags) { + if((open_flags & O_ACCMODE) == O_RDONLY) { + return 0; /* R_OK */ + } else if ((open_flags & O_ACCMODE) == O_WRONLY) { + return 1; /* W_OK */ + } else { + /* Probably O_RDRW, but treat as default to be safe */ + return 1; /* R_OK | W_OK */ + } +} + +static int insert_str_to_int(struct packagelist_data *pkgl_dat, void *key, int value) { + struct hashtable_entry *hash_cur; + struct hashtable_entry *new_entry; + unsigned int hash = str_hash(key); + + //printk(KERN_INFO "sdcardfs: %s: %s: %d, %u\n", __func__, (char *)key, value, hash); + hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) { + if (!strcasecmp(key, hash_cur->key)) { + hash_cur->value = value; + return 0; + } + } + new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL); + if (!new_entry) + return -ENOMEM; + new_entry->key = kstrdup(key, GFP_KERNEL); + new_entry->value = value; + hash_add(pkgl_dat->package_to_appid, &new_entry->hlist, hash); + return 0; +} + +static void remove_str_to_int(struct hashtable_entry *h_entry) { + //printk(KERN_INFO "sdcardfs: %s: %s: %d\n", __func__, (char *)h_entry->key, h_entry->value); + kfree(h_entry->key); + kmem_cache_free(hashtable_entry_cachep, h_entry); +} + +/*static void remove_int_to_null(struct hashtable_entry *h_entry) { + //printk(KERN_INFO "sdcardfs: %s: %d: %d\n", __func__, (int)h_entry->key, h_entry->value); + kmem_cache_free(hashtable_entry_cachep, h_entry); +}*/ + +static void remove_all_hashentrys(struct packagelist_data *pkgl_dat) +{ + struct hashtable_entry *hash_cur; + struct hlist_node *h_t; + int i; + + hash_for_each_safe(pkgl_dat->package_to_appid, i, h_t, hash_cur, hlist) + remove_str_to_int(hash_cur); + + hash_init(pkgl_dat->package_to_appid); +} + +static int read_package_list(struct packagelist_data *pkgl_dat) { + int ret; + int fd; + int read_amount; + + printk(KERN_INFO "sdcardfs: read_package_list\n"); + + mutex_lock(&pkgl_dat->hashtable_lock); + + remove_all_hashentrys(pkgl_dat); + + fd = sys_open(kpackageslist_file, O_RDONLY, 0); + if (fd < 0) { + printk(KERN_ERR "sdcardfs: failed to open package list\n"); + mutex_unlock(&pkgl_dat->hashtable_lock); + return fd; + } + + while ((read_amount = sys_read(fd, pkgl_dat->read_buf, + sizeof(pkgl_dat->read_buf))) > 0) { + int appid; + int one_line_len = 0; + int additional_read; + + while (one_line_len < read_amount) { + if (pkgl_dat->read_buf[one_line_len] == '\n') { + one_line_len++; + break; + } + one_line_len++; + } + additional_read = read_amount - one_line_len; + if (additional_read > 0) + sys_lseek(fd, -additional_read, SEEK_CUR); + + if (sscanf(pkgl_dat->read_buf, "%s %d %*d %*s %*s %s", + pkgl_dat->app_name_buf, &appid, + pkgl_dat->gids_buf) == 3) { + ret = insert_str_to_int(pkgl_dat, pkgl_dat->app_name_buf, appid); + if (ret) { + sys_close(fd); + mutex_unlock(&pkgl_dat->hashtable_lock); + return ret; + } + } + } + + sys_close(fd); + mutex_unlock(&pkgl_dat->hashtable_lock); + return 0; +} + +static int packagelist_reader(void *thread_data) +{ + struct packagelist_data *pkgl_dat = (struct packagelist_data *)thread_data; + struct inotify_event *event; + bool active = false; + int event_pos; + int event_size; + int res = 0; + int nfd; + + allow_signal(SIGINT); + + nfd = sys_inotify_init(); + if (nfd < 0) { + printk(KERN_ERR "sdcardfs: inotify_init failed: %d\n", nfd); + return nfd; + } + + while (!kthread_should_stop()) { + if (signal_pending(current)) { + ssleep(1); + continue; + } + + if (!active) { + res = sys_inotify_add_watch(nfd, kpackageslist_file, IN_DELETE_SELF); + if (res < 0) { + if (res == -ENOENT || res == -EACCES) { + /* Framework may not have created yet, sleep and retry */ + printk(KERN_ERR "sdcardfs: missing packages.list; retrying\n"); + ssleep(2); + printk(KERN_ERR "sdcardfs: missing packages.list_end; retrying\n"); + continue; + } else { + printk(KERN_ERR "sdcardfs: inotify_add_watch failed: %d\n", res); + goto interruptable_sleep; + } + } + /* Watch above will tell us about any future changes, so + * read the current state. */ + res = read_package_list(pkgl_dat); + if (res) { + printk(KERN_ERR "sdcardfs: read_package_list failed: %d\n", res); + goto interruptable_sleep; + } + active = true; + } + + event_pos = 0; + res = sys_read(nfd, pkgl_dat->event_buf, sizeof(pkgl_dat->event_buf)); + if (res < (int) sizeof(*event)) { + if (res == -EINTR) + continue; + printk(KERN_ERR "sdcardfs: failed to read inotify event: %d\n", res); + goto interruptable_sleep; + } + + while (res >= (int) sizeof(*event)) { + event = (struct inotify_event *) (pkgl_dat->event_buf + event_pos); + + printk(KERN_INFO "sdcardfs: inotify event: %08x\n", event->mask); + if ((event->mask & IN_IGNORED) == IN_IGNORED) { + /* Previously watched file was deleted, probably due to move + * that swapped in new data; re-arm the watch and read. */ + active = false; + } + + event_size = sizeof(*event) + event->len; + res -= event_size; + event_pos += event_size; + } + continue; + +interruptable_sleep: + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + flush_signals(current); + sys_close(nfd); + return res; +} + +void * packagelist_create(void) +{ + struct packagelist_data *pkgl_dat; + struct task_struct *packagelist_thread; + + pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO); + if (!pkgl_dat) { + printk(KERN_ERR "sdcardfs: creating kthread failed\n"); + return ERR_PTR(-ENOMEM); + } + + mutex_init(&pkgl_dat->hashtable_lock); + hash_init(pkgl_dat->package_to_appid); + + packagelist_thread = kthread_run(packagelist_reader, (void *)pkgl_dat, "pkgld"); + if (IS_ERR(packagelist_thread)) { + printk(KERN_ERR "sdcardfs: creating kthread failed\n"); + kfree(pkgl_dat); + return packagelist_thread; + } + pkgl_dat->thread_id = packagelist_thread; + + printk(KERN_INFO "sdcardfs: created packagelist pkgld/%d\n", + (int)pkgl_dat->thread_id->pid); + + return (void *)pkgl_dat; +} + +void packagelist_destroy(void *pkgl_id) +{ + struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id; + pid_t pkgl_pid = pkgl_dat->thread_id->pid; + + force_sig_info(SIGINT, SEND_SIG_PRIV, pkgl_dat->thread_id); + kthread_stop(pkgl_dat->thread_id); + remove_all_hashentrys(pkgl_dat); + printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld/%d\n", (int)pkgl_pid); + kfree(pkgl_dat); +} + +int packagelist_init(void) +{ + hashtable_entry_cachep = + kmem_cache_create("packagelist_hashtable_entry", + sizeof(struct hashtable_entry), 0, 0, NULL); + if (!hashtable_entry_cachep) { + printk(KERN_ERR "sdcardfs: failed creating pkgl_hashtable entry slab cache\n"); + return -ENOMEM; + } + + return 0; +} + +void packagelist_exit(void) +{ + if (hashtable_entry_cachep) + kmem_cache_destroy(hashtable_entry_cachep); +} diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h new file mode 100644 index 000000000000..210bc1623a33 --- /dev/null +++ b/fs/sdcardfs/sdcardfs.h @@ -0,0 +1,549 @@ +/* + * fs/sdcardfs/sdcardfs.h + * + * The sdcardfs v2.0 + * This file system replaces the sdcard daemon on Android + * On version 2.0, some of the daemon functions have been ported + * to support the multi-user concepts of Android 4.4 + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#ifndef _SDCARDFS_H_ +#define _SDCARDFS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "multiuser.h" + +/* the file system magic number */ +#define SDCARDFS_SUPER_MAGIC 0xb550ca10 + +/* the file system name */ +#define SDCARDFS_NAME "sdcardfs" + +/* sdcardfs root inode number */ +#define SDCARDFS_ROOT_INO 1 + +/* useful for tracking code reachability */ +#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) + +#define SDCARDFS_DIRENT_SIZE 256 + +/* temporary static uid settings for development */ +#define AID_ROOT 0 /* uid for accessing /mnt/sdcard & extSdcard */ +#define AID_MEDIA_RW 1023 /* internal media storage write access */ + +#define AID_SDCARD_RW 1015 /* external storage write access */ +#define AID_SDCARD_R 1028 /* external storage read access */ +#define AID_SDCARD_PICS 1033 /* external storage photos access */ +#define AID_SDCARD_AV 1034 /* external storage audio/video access */ +#define AID_SDCARD_ALL 1035 /* access all users external storage */ + +#define AID_PACKAGE_INFO 1027 +#define AID_EVERYBODY 9997 + +/* OVERRIDE_CRED() and REVERT_CRED() + * OVERRID_CRED() + * backup original task->cred + * and modifies task->cred->fsuid/fsgid to specified value. + * REVERT_CRED() + * restore original task->cred->fsuid/fsgid. + * These two macro should be used in pair, and OVERRIDE_CRED() should be + * placed at the beginning of a function, right after variable declaration. + */ +#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred) \ + saved_cred = override_fsids(sdcardfs_sbi->options.fs_low_uid, \ + sdcardfs_sbi->options.fs_low_gid); \ + if (!saved_cred) { return -ENOMEM; } + +#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred) \ + saved_cred = override_fsids(sdcardfs_sbi->options.fs_low_uid, \ + sdcardfs_sbi->options.fs_low_gid); \ + if (!saved_cred) { return ERR_PTR(-ENOMEM); } + +#define OVERRIDE_ROOT_CRED(saved_cred) \ + saved_cred = override_fsids(0, 0); \ + if (!saved_cred) { return -ENOMEM; } + +#define REVERT_CRED(saved_cred) revert_fsids(saved_cred) + +#define DEBUG_CRED() \ + printk("KAKJAGI: %s:%d fsuid %d fsgid %d\n", \ + __FUNCTION__, __LINE__, \ + (int)current->cred->fsuid, \ + (int)current->cred->fsgid); + +/* Permission mode for a specific node. Controls how file permissions + * are derived for children nodes. */ +typedef enum { + /* Nothing special; this node should just inherit from its parent. */ + PERM_INHERIT, + /* This node is one level above a normal root; used for legacy layouts + * which use the first level to represent user_id. */ + PERM_PRE_ROOT, + /* This node is "/" */ + PERM_ROOT, + /* This node is "/Android" */ + PERM_ANDROID, + /* This node is "/Android/data" */ + PERM_ANDROID_DATA, + /* This node is "/Android/obb" */ + PERM_ANDROID_OBB, + /* This node is "/Android/media" */ + PERM_ANDROID_MEDIA, +} perm_t; + +typedef enum { + LOWER_FS_EXT4, + LOWER_FS_FAT, +} lower_fs_t; + +typedef enum { + TYPE_NONE, + TYPE_DEFAULT, + TYPE_READ, + TYPE_WRITE, +} type_t; + +struct sdcardfs_sb_info; +struct sdcardfs_mount_options; + +/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ +const struct cred * override_fsids(uid_t fsuid, gid_t fsgid); +/* Do not directly use this function, use REVERT_CRED() instead. */ +void revert_fsids(const struct cred * old_cred); + +/* operations vectors defined in specific files */ +extern const struct file_operations sdcardfs_main_fops; +extern const struct file_operations sdcardfs_dir_fops; +extern const struct inode_operations sdcardfs_main_iops; +extern const struct inode_operations sdcardfs_dir_iops; +extern const struct inode_operations sdcardfs_symlink_iops; +extern const struct super_operations sdcardfs_sops; +extern const struct super_operations sdcardfs_multimount_sops; +extern const struct dentry_operations sdcardfs_ci_dops; +extern const struct address_space_operations sdcardfs_aops, sdcardfs_dummy_aops; +extern const struct vm_operations_struct sdcardfs_vm_ops; + +extern int sdcardfs_init_inode_cache(void); +extern void sdcardfs_destroy_inode_cache(void); +extern int sdcardfs_init_dentry_cache(void); +extern void sdcardfs_destroy_dentry_cache(void); +extern int new_dentry_private_data(struct dentry *dentry); +extern void free_dentry_private_data(struct dentry *dentry); +extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags); +extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, + struct path *lower_path); + +#ifdef SDCARD_FS_XATTR +extern int sdcardfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); +extern ssize_t sdcardfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size); +extern ssize_t sdcardfs_listxattr(struct dentry *dentry, char *list, size_t size); +extern int sdcardfs_removexattr(struct dentry *dentry, const char *name); +#endif // SDCARD_FS_XATTR +/* file private data */ +struct sdcardfs_file_info { + struct file *lower_file; + const struct vm_operations_struct *lower_vm_ops; +}; + +/* sdcardfs inode data in memory */ +struct sdcardfs_inode_info { + struct inode *lower_inode; + /* state derived based on current position in hierachy + */ + perm_t perm; + userid_t userid; + uid_t d_uid; + gid_t d_gid; + bool under_android; + + struct inode vfs_inode; +}; + +/* sdcardfs dentry data in memory */ +struct sdcardfs_dentry_info { + spinlock_t lock; /* protects lower_path */ + struct path lower_path; + struct path orig_path; +#ifdef CONFIG_SDP + int under_knox; + int userid; +#endif +}; + +struct sdcardfs_mount_options { + uid_t fs_low_uid; + gid_t fs_low_gid; + gid_t gid; + userid_t userid; + lower_fs_t lower_fs; + unsigned int reserved_mb; + mode_t mask; + bool multi_user; + char *label; + type_t type; +}; + +/* sdcardfs super-block data in memory */ +struct sdcardfs_sb_info { + struct super_block *lower_sb; + /* derived perm policy : some of options have been added + * to sdcardfs_mount_options (Android 4.4 support) */ + struct sdcardfs_mount_options options; + spinlock_t lock; /* protects obbpath */ + char *obbpath_s; + struct path obbpath; + void *pkgl_id; + char *devpath; +}; + +/* + * inode to private data + * + * Since we use containers and the struct inode is _inside_ the + * sdcardfs_inode_info structure, SDCARDFS_I will always (given a non-NULL + * inode pointer), return a valid non-NULL pointer. + */ +static inline struct sdcardfs_inode_info *SDCARDFS_I(const struct inode *inode) +{ + return container_of(inode, struct sdcardfs_inode_info, vfs_inode); +} + +/* dentry to private data */ +#define SDCARDFS_D(dent) ((struct sdcardfs_dentry_info *)(dent)->d_fsdata) + +/* superblock to private data */ +#define SDCARDFS_SB(super) ((struct sdcardfs_sb_info *)(super)->s_fs_info) + +/* file to private Data */ +#define SDCARDFS_F(file) ((struct sdcardfs_file_info *)((file)->private_data)) + +/* file to lower file */ +static inline struct file *sdcardfs_lower_file(const struct file *f) +{ + return SDCARDFS_F(f)->lower_file; +} + +static inline void sdcardfs_set_lower_file(struct file *f, struct file *val) +{ + SDCARDFS_F(f)->lower_file = val; +} + +/* inode to lower inode. */ +static inline struct inode *sdcardfs_lower_inode(const struct inode *i) +{ + return SDCARDFS_I(i)->lower_inode; +} + +static inline void sdcardfs_set_lower_inode(struct inode *i, struct inode *val) +{ + SDCARDFS_I(i)->lower_inode = val; +} + +/* copy the inode attrs from src to dest except uid and gid */ +static inline void sdcardfs_copy_inode_attr(struct inode *dest, const struct inode *src) +{ + dest->i_mode = src->i_mode; + dest->i_rdev = src->i_rdev; + dest->i_atime = src->i_atime; + dest->i_mtime = src->i_mtime; + dest->i_ctime = src->i_ctime; + dest->i_blkbits = src->i_blkbits; + dest->i_flags = src->i_flags; + set_nlink(dest, src->i_nlink); +} + +/* superblock to lower superblock */ +static inline struct super_block *sdcardfs_lower_super( + const struct super_block *sb) +{ + return SDCARDFS_SB(sb)->lower_sb; +} + +static inline void sdcardfs_set_lower_super(struct super_block *sb, + struct super_block *val) +{ + SDCARDFS_SB(sb)->lower_sb = val; +} + +/* path based (dentry/mnt) macros */ +static inline void pathcpy(struct path *dst, const struct path *src) +{ + dst->dentry = src->dentry; + dst->mnt = src->mnt; +} + +/* sdcardfs_get_pname functions calls path_get() + * therefore, the caller must call "proper" path_put functions + */ +#define SDCARDFS_DENT_FUNC(pname) \ +static inline void sdcardfs_get_##pname(const struct dentry *dent, \ + struct path *pname) \ +{ \ + spin_lock(&SDCARDFS_D(dent)->lock); \ + pathcpy(pname, &SDCARDFS_D(dent)->pname); \ + path_get(pname); \ + spin_unlock(&SDCARDFS_D(dent)->lock); \ + return; \ +} \ +static inline void sdcardfs_put_##pname(const struct dentry *dent, \ + struct path *pname) \ +{ \ + path_put(pname); \ + return; \ +} \ +static inline void sdcardfs_set_##pname(const struct dentry *dent, \ + struct path *pname) \ +{ \ + spin_lock(&SDCARDFS_D(dent)->lock); \ + pathcpy(&SDCARDFS_D(dent)->pname, pname); \ + spin_unlock(&SDCARDFS_D(dent)->lock); \ + return; \ +} \ +static inline void sdcardfs_reset_##pname(const struct dentry *dent) \ +{ \ + spin_lock(&SDCARDFS_D(dent)->lock); \ + SDCARDFS_D(dent)->pname.dentry = NULL; \ + SDCARDFS_D(dent)->pname.mnt = NULL; \ + spin_unlock(&SDCARDFS_D(dent)->lock); \ + return; \ +} \ +static inline void sdcardfs_put_reset_##pname(const struct dentry *dent) \ +{ \ + struct path pname; \ + spin_lock(&SDCARDFS_D(dent)->lock); \ + if(SDCARDFS_D(dent)->pname.dentry) { \ + pathcpy(&pname, &SDCARDFS_D(dent)->pname); \ + SDCARDFS_D(dent)->pname.dentry = NULL; \ + SDCARDFS_D(dent)->pname.mnt = NULL; \ + spin_unlock(&SDCARDFS_D(dent)->lock); \ + path_put(&pname); \ + } else \ + spin_unlock(&SDCARDFS_D(dent)->lock); \ + return; \ +} + +SDCARDFS_DENT_FUNC(lower_path) +SDCARDFS_DENT_FUNC(orig_path) + +static inline void sdcardfs_copy_lower_path(const struct dentry *dent, + struct path *lower_path) +{ + spin_lock(&SDCARDFS_D(dent)->lock); + pathcpy(lower_path, &SDCARDFS_D(dent)->lower_path); + spin_unlock(&SDCARDFS_D(dent)->lock); + return; +} + +static inline int has_graft_path(const struct dentry *dent) +{ + int ret = 0; + + spin_lock(&SDCARDFS_D(dent)->lock); + if (SDCARDFS_D(dent)->orig_path.dentry != NULL) + ret = 1; + spin_unlock(&SDCARDFS_D(dent)->lock); + + return ret; +} + +static inline void sdcardfs_get_real_lower(const struct dentry *dent, + struct path *real_lower) +{ + /* in case of a local obb dentry + * the orig_path should be returned + */ + if(has_graft_path(dent)) + sdcardfs_get_orig_path(dent, real_lower); + else + sdcardfs_get_lower_path(dent, real_lower); +} + +static inline void sdcardfs_put_real_lower(const struct dentry *dent, + struct path *real_lower) +{ + if(has_graft_path(dent)) + sdcardfs_put_orig_path(dent, real_lower); + else + sdcardfs_put_lower_path(dent, real_lower); +} + +/* for packagelist.c */ +extern appid_t get_appid(void *pkgl_id, const char *app_name); +extern int check_caller_access_to_name(struct inode *parent_node, const char* name); +extern int open_flags_to_access_mode(int open_flags); +extern void *packagelist_create(void); +extern void packagelist_destroy(void *pkgl_id); +extern int packagelist_init(void); +extern void packagelist_exit(void); + +/* for derived_perm.c */ +extern void setup_derived_state(struct inode *inode, perm_t perm, + userid_t userid, uid_t uid, gid_t gid, bool under_android); +extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); +extern void fix_derived_permission(struct inode *inode); +extern void update_derived_permission(struct dentry *dentry); +extern int need_graft_path(struct dentry *dentry); +extern int is_base_obbpath(struct dentry *dentry); +extern int is_obbpath_invalid(struct dentry *dentry); +extern int setup_obb_dentry(struct dentry *dentry, struct path *lower_path); + +/* locking helpers */ +static inline struct dentry *lock_parent(struct dentry *dentry) +{ + struct dentry *dir = dget_parent(dentry); + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); + return dir; +} + +static inline void unlock_dir(struct dentry *dir) +{ + mutex_unlock(&dir->d_inode->i_mutex); + dput(dir); +} + +static inline int prepare_dir(const char *path_s, uid_t uid, gid_t gid, mode_t mode) +{ + int err; + struct dentry *dent; + struct path path; + struct iattr attrs; + + dent = kern_path_create(AT_FDCWD, path_s, &path, LOOKUP_DIRECTORY); + + if (IS_ERR(dent)) { + err = PTR_ERR(dent); + if (err == -EEXIST) + err = 0; + return err; + } + + err = mnt_want_write(path.mnt); + if (err) + goto out; + + err = vfs_mkdir(path.dentry->d_inode, dent, mode); + if (err) { + if (err == -EEXIST) + err = 0; + goto out_drop; + } + + attrs.ia_uid = make_kuid(current_user_ns(), uid); + attrs.ia_gid = make_kgid(current_user_ns(), gid); + attrs.ia_valid = ATTR_UID | ATTR_GID; + mutex_lock(&dent->d_inode->i_mutex); + notify_change(dent, &attrs, NULL); + mutex_unlock(&dent->d_inode->i_mutex); + +out_drop: + mnt_drop_write(path.mnt); + +out: + dput(dent); + /* parent dentry locked by kern_path_create */ + mutex_unlock(&path.dentry->d_inode->i_mutex); + path_put(&path); + return err; +} + +/* + * Return 1, if a disk has enough free space, otherwise 0. + * We assume that any files can not be overwritten. + */ +static inline int check_min_free_space(struct dentry *dentry, size_t size, int dir) +{ + int err; + struct path lower_path; + struct kstatfs statfs; + u64 avail; + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + + if (sbi->options.reserved_mb) { + /* Get fs stat of lower filesystem. */ + sdcardfs_get_lower_path(dentry, &lower_path); + err = vfs_statfs(&lower_path, &statfs); + sdcardfs_put_lower_path(dentry, &lower_path); + + if (unlikely(err)) + goto out_invalid; + + /* Invalid statfs informations. */ + if (unlikely(statfs.f_bsize == 0)) + goto out_invalid; + + /* if you are checking directory, set size to f_bsize. */ + if (unlikely(dir)) + size = statfs.f_bsize; + + /* available size */ + avail = statfs.f_bavail * statfs.f_bsize; + + /* not enough space */ + if ((u64)size > avail) + goto out_nospc; + + /* enough space */ + if ((avail - size) > (sbi->options.reserved_mb * 1024 * 1024)) + return 1; + goto out_nospc; + } else + return 1; + +out_invalid: + printk(KERN_INFO "statfs : invalid return\n"); + printk(KERN_INFO "vfs_statfs error# : %d\n", err); + printk(KERN_INFO "statfs.f_type : 0x%X\n", (u32)statfs.f_type); + printk(KERN_INFO "statfs.f_blocks : %llu blocks\n", statfs.f_blocks); + printk(KERN_INFO "statfs.f_bfree : %llu blocks\n", statfs.f_bfree); + printk(KERN_INFO "statfs.f_files : %llu\n", statfs.f_files); + printk(KERN_INFO "statfs.f_ffree : %llu\n", statfs.f_ffree); + printk(KERN_INFO "statfs.f_fsid.val[1] : 0x%X\n", (u32)statfs.f_fsid.val[1]); + printk(KERN_INFO "statfs.f_fsid.val[0] : 0x%X\n", (u32)statfs.f_fsid.val[0]); + printk(KERN_INFO "statfs.f_namelen : %ld\n", statfs.f_namelen); + printk(KERN_INFO "statfs.f_frsize : %ld\n", statfs.f_frsize); + printk(KERN_INFO "statfs.f_flags : %ld\n", statfs.f_flags); + printk(KERN_INFO "sdcardfs reserved_mb : %u\n", sbi->options.reserved_mb); + if (sbi->devpath) + printk(KERN_INFO "sdcardfs source path : %s\n", sbi->devpath); + +out_nospc: + printk_ratelimited(KERN_INFO "statfs.f_bavail : %llu blocks / " + "statfs.f_bsize : %ld bytes / " + "required size : %llu byte\n" + ,statfs.f_bavail, statfs.f_bsize, (u64)size); + return 0; +} +#endif /* not _SDCARDFS_H_ */ diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c new file mode 100644 index 000000000000..4723b5eda5a0 --- /dev/null +++ b/fs/sdcardfs/super.c @@ -0,0 +1,297 @@ +/* + * fs/sdcardfs/super.c + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, + * Sunghwan Yun, Sungjong Seo + * + * This program has been developed as a stackable file system based on + * the WrapFS which written by + * + * Copyright (c) 1998-2011 Erez Zadok + * Copyright (c) 2009 Shrikar Archak + * Copyright (c) 2003-2011 Stony Brook University + * Copyright (c) 2003-2011 The Research Foundation of SUNY + * + * This file is dual licensed. It may be redistributed and/or modified + * under the terms of the Apache 2.0 License OR version 2 of the GNU + * General Public License. + */ + +#include "sdcardfs.h" + +/* + * The inode cache is used with alloc_inode for both our inode info and the + * vfs inode. + */ +static struct kmem_cache *sdcardfs_inode_cachep; + +/* final actions when unmounting a file system */ +static void sdcardfs_put_super(struct super_block *sb) +{ + struct sdcardfs_sb_info *spd; + struct super_block *s; + + spd = SDCARDFS_SB(sb); + if (!spd) + return; + + printk(KERN_ERR "sdcardfs: umounted dev_name %s\n", + spd->devpath ? spd->devpath : ""); + if(spd->devpath) + kfree(spd->devpath); + + if(spd->obbpath_s) { + kfree(spd->obbpath_s); + path_put(&spd->obbpath); + } + + if(spd->options.label) + kfree(spd->options.label); + + /* decrement lower super references */ + s = sdcardfs_lower_super(sb); + sdcardfs_set_lower_super(sb, NULL); + atomic_dec(&s->s_active); + + if(spd->pkgl_id) + packagelist_destroy(spd->pkgl_id); + + kfree(spd); + sb->s_fs_info = NULL; +} + +static int sdcardfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + int err; + struct path lower_path; + u32 min_blocks; + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); + + sdcardfs_get_lower_path(dentry, &lower_path); + err = vfs_statfs(&lower_path, buf); + sdcardfs_put_lower_path(dentry, &lower_path); + + if (sbi->options.reserved_mb) { + /* Invalid statfs informations. */ + if (buf->f_bsize == 0) { + printk(KERN_ERR "Returned block size is zero.\n"); + return -EINVAL; + } + + min_blocks = ((sbi->options.reserved_mb * 1024 * 1024)/buf->f_bsize); + buf->f_blocks -= min_blocks; + + if (buf->f_bavail > min_blocks) + buf->f_bavail -= min_blocks; + else + buf->f_bavail = 0; + + /* Make reserved blocks invisiable to media storage */ + buf->f_bfree = buf->f_bavail; + } + + /* set return buf to our f/s to avoid confusing user-level utils */ + buf->f_type = SDCARDFS_SUPER_MAGIC; + + return err; +} + +/* + * @flags: numeric mount options + * @options: mount options string + */ +static int sdcardfs_remount_fs(struct super_block *sb, int *flags, char *options) +{ + int err = 0; + + /* + * The VFS will take care of "ro" and "rw" flags among others. We + * can safely accept a few flags (RDONLY, MANDLOCK), and honor + * SILENT, but anything else left over is an error. + */ + if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) { + printk(KERN_ERR + "sdcardfs: remount flags 0x%x unsupported\n", *flags); + err = -EINVAL; + } + + return err; +} + +/* + * Called by iput() when the inode reference count reached zero + * and the inode is not hashed anywhere. Used to clear anything + * that needs to be, before the inode is completely destroyed and put + * on the inode free list. + */ +static void sdcardfs_evict_inode(struct inode *inode) +{ + struct inode *lower_inode; + + truncate_inode_pages(&inode->i_data, 0); + clear_inode(inode); + /* + * Decrement a reference to a lower_inode, which was incremented + * by our read_inode when it was created initially. + */ + lower_inode = sdcardfs_lower_inode(inode); + sdcardfs_set_lower_inode(inode, NULL); + iput(lower_inode); +} + +static struct inode *sdcardfs_alloc_inode(struct super_block *sb) +{ + struct sdcardfs_inode_info *i; + + i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL); + if (!i) + return NULL; + + /* memset everything up to the inode to 0 */ + memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode)); + + i->vfs_inode.i_version = 1; + return &i->vfs_inode; +} + +static void sdcardfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode)); +} + +/* sdcardfs inode cache constructor */ +static void init_once(void *obj) +{ + struct sdcardfs_inode_info *i = obj; + + inode_init_once(&i->vfs_inode); +} + +int sdcardfs_init_inode_cache(void) +{ + int err = 0; + + sdcardfs_inode_cachep = + kmem_cache_create("sdcardfs_inode_cache", + sizeof(struct sdcardfs_inode_info), 0, + SLAB_RECLAIM_ACCOUNT, init_once); + if (!sdcardfs_inode_cachep) + err = -ENOMEM; + return err; +} + +/* sdcardfs inode cache destructor */ +void sdcardfs_destroy_inode_cache(void) +{ + if (sdcardfs_inode_cachep) + kmem_cache_destroy(sdcardfs_inode_cachep); +} + +/* + * Used only in nfs, to kill any pending RPC tasks, so that subsequent + * code can actually succeed and won't leave tasks that need handling. + */ + +static long sdcardfs_propagate_lookup(struct super_block *sb, char* pathname) { + long ret = 0; + char *propagate_path = NULL; + struct sdcardfs_sb_info *sbi; + struct path sibling_path; + const struct cred *saved_cred = NULL; + + sbi = SDCARDFS_SB(sb); + propagate_path = kmalloc(PATH_MAX, GFP_KERNEL); + OVERRIDE_ROOT_CRED(saved_cred); + if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_DEFAULT) { + snprintf(propagate_path, PATH_MAX, "/mnt/runtime/default/%s%s", + sbi->options.label, pathname); + ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); + if (!ret) + path_put(&sibling_path); + } + + if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_READ) { + snprintf(propagate_path, PATH_MAX, "/mnt/runtime/read/%s%s", + sbi->options.label, pathname); + ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); + if (!ret) + path_put(&sibling_path); + } + + if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_WRITE) { + snprintf(propagate_path, PATH_MAX, "/mnt/runtime/write/%s%s", + sbi->options.label, pathname); + ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); + if (!ret) + path_put(&sibling_path); + } + + if (sbi->options.type != TYPE_NONE) { + snprintf(propagate_path, PATH_MAX, "/storage/%s%s", + sbi->options.label, pathname); + ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); + if (!ret) + path_put(&sibling_path); + } + REVERT_CRED(saved_cred); + kfree(propagate_path); + return ret; +} + +static void sdcardfs_umount_begin(struct super_block *sb) +{ + struct super_block *lower_sb; + + lower_sb = sdcardfs_lower_super(sb); + if (lower_sb && lower_sb->s_op && lower_sb->s_op->umount_begin) + lower_sb->s_op->umount_begin(lower_sb); +} + +static int sdcardfs_show_options(struct seq_file *m, struct dentry *root) +{ + struct sdcardfs_sb_info *sbi = SDCARDFS_SB(root->d_sb); + struct sdcardfs_mount_options *opts = &sbi->options; + + if (opts->fs_low_uid != 0) + seq_printf(m, ",low_uid=%u", opts->fs_low_uid); + if (opts->fs_low_gid != 0) + seq_printf(m, ",low_gid=%u", opts->fs_low_gid); + if (opts->gid != 0) + seq_printf(m, ",gid=%u", opts->gid); + if (opts->userid != 0) + seq_printf(m, ",userid=%u", opts->userid); + if (opts->multi_user) + seq_printf(m, ",multi_user"); + if (opts->mask != 0) + seq_printf(m, ",mask=%04o", opts->mask); + if (opts->reserved_mb != 0) + seq_printf(m, ",reserved=%uMB", opts->reserved_mb); + + return 0; +}; + +const struct super_operations sdcardfs_sops = { + .put_super = sdcardfs_put_super, + .statfs = sdcardfs_statfs, + .remount_fs = sdcardfs_remount_fs, + .evict_inode = sdcardfs_evict_inode, + .umount_begin = sdcardfs_umount_begin, + .show_options = sdcardfs_show_options, + .alloc_inode = sdcardfs_alloc_inode, + .destroy_inode = sdcardfs_destroy_inode, + .drop_inode = generic_delete_inode, +}; + +const struct super_operations sdcardfs_multimount_sops = { + .put_super = sdcardfs_put_super, + .statfs = sdcardfs_statfs, + .remount_fs = sdcardfs_remount_fs, + .evict_inode = sdcardfs_evict_inode, + .umount_begin = sdcardfs_umount_begin, + .show_options = sdcardfs_show_options, + .alloc_inode = sdcardfs_alloc_inode, + .destroy_inode = sdcardfs_destroy_inode, + .drop_inode = generic_delete_inode, + .unlink_callback = sdcardfs_propagate_lookup, +}; diff --git a/fs/sdcardfs/version.h b/fs/sdcardfs/version.h new file mode 100644 index 000000000000..ee2b8dd9e079 --- /dev/null +++ b/fs/sdcardfs/version.h @@ -0,0 +1,28 @@ +/* + * The sdcardfs + * + * Copyright (c) 2013 Samsung Electronics Co. Ltd + * Authors: Daeho Jeong, Woojoong Lee, Kitae Lee, Yeongjin Gil + * + * Revision History + * 2014.06.24 : Release Version 2.1.0 + * - Add sdcardfs version + * - Add kernel log when put_super + * 2014.07.21 : Release Version 2.1.1 + * - Add sdcardfs_copy_inode_attr() to fix permission issue + * - Delete mmap_sem lock in sdcardfs_setattr() to avoid deadlock + * 2014.11.12 : Release Version 2.1.2 + * - Add get_lower_file function pointer in file_operations + * 2014.11.25 : Release Version 2.1.3 + * - Add error handling routine in sdcardfs_d_revalidate + * when dentry is equal to lower_dentry + * 2015.03.25 : Release Version 2.1.4 + * - Add FMODE_NONMAPPABLE, FMODE_NONCACHEABLE flag to file->f_mode + * - Modify do_mmap_pgoff because of new f_mode flags + * 2015.07. : Release Version 3.0.0 + * 2015.11.24 : Release Version 3.1.0 + * - Add unlink_callback(), get_lower_inode() + * - Add mount option type, label + */ + +#define SDCARDFS_VERSION "3.1.0" diff --git a/fs/sdcardfs/xattr.c b/fs/sdcardfs/xattr.c new file mode 100644 index 000000000000..4fad9882ebf8 --- /dev/null +++ b/fs/sdcardfs/xattr.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include "sdcardfs.h" + +static struct dentry * +sdcardfs_dentry_to_lower(struct dentry *dentry) +{ + struct dentry* ret; + + ret = ((struct sdcardfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry; + return ret; +} + +int +sdcardfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) +{ + int rc = 0; + struct dentry *lower_dentry; + + lower_dentry = sdcardfs_dentry_to_lower(dentry); + if (!lower_dentry->d_inode->i_op->setxattr) { + rc = -EOPNOTSUPP; + goto out; + } + + rc = vfs_setxattr(lower_dentry, name, value, size, flags); +out: + return rc; +} + +static ssize_t +sdcardfs_getxattr_lower(struct dentry *lower_dentry, const char *name, void *value, size_t size) +{ + int rc = 0; + + if (!lower_dentry->d_inode->i_op->getxattr) { + rc = -EOPNOTSUPP; + goto out; + } + rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value, + size); +out: + return rc; +} + +ssize_t +sdcardfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) +{ + ssize_t ret; + ret = sdcardfs_getxattr_lower(sdcardfs_dentry_to_lower(dentry), name, + value, size); + return ret; +} + +ssize_t +sdcardfs_listxattr(struct dentry *dentry, char *list, size_t size) +{ + int rc = 0; + struct dentry *lower_dentry; + + lower_dentry = sdcardfs_dentry_to_lower(dentry); + if (!lower_dentry->d_inode->i_op->listxattr) { + rc = -EOPNOTSUPP; + goto out; + } + rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size); +out: + return rc; +} + +int +sdcardfs_removexattr(struct dentry *dentry, const char *name) +{ + int rc = 0; + struct dentry *lower_dentry; + + lower_dentry = sdcardfs_dentry_to_lower(dentry); + if (!lower_dentry->d_inode->i_op->removexattr) { + rc = -EOPNOTSUPP; + goto out; + } + mutex_lock(&lower_dentry->d_inode->i_mutex); + rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name); + mutex_unlock(&lower_dentry->d_inode->i_mutex); +out: + return rc; +} From 49b578aaf296a8db24cb3635dd2fa1637b2c1590 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Fri, 22 Jul 2016 05:01:48 +0900 Subject: [PATCH 123/203] fs: fix sdcardfs compilation errors Signed-off-by: Park Ju Hyung Signed-off-by: engstk --- fs/namei.c | 12 ++++++++++++ include/linux/fs.h | 8 ++++++++ include/linux/namei.h | 1 + mm/mmap.c | 3 +++ 4 files changed, 24 insertions(+) diff --git a/fs/namei.c b/fs/namei.c index 5384007de6f8..16fdb29f7908 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3743,6 +3743,8 @@ static long do_unlinkat(int dfd, const char __user *pathname) struct inode *inode = NULL; struct inode *delegated_inode = NULL; unsigned int lookup_flags = 0; + char *path_buf = NULL; + char *propagate_path = NULL; retry: name = user_path_parent(dfd, pathname, &nd, lookup_flags); if (IS_ERR(name)) @@ -3767,6 +3769,12 @@ static long do_unlinkat(int dfd, const char __user *pathname) inode = dentry->d_inode; if (d_is_negative(dentry)) goto slashes; + + if (inode->i_sb->s_op->unlink_callback) { + path_buf = kmalloc(PATH_MAX, GFP_KERNEL); + propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX); + } + ihold(inode); error = security_path_unlink(&nd.path, dentry); if (error) @@ -3776,6 +3784,10 @@ static long do_unlinkat(int dfd, const char __user *pathname) dput(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + if (path_buf && !error) { + inode->i_sb->s_op->unlink_callback(inode->i_sb, propagate_path); + kfree(path_buf); + } if (inode) iput(inode); /* truncate the inode here */ inode = NULL; diff --git a/include/linux/fs.h b/include/linux/fs.h index 6894e9ecc982..908198eedde1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -133,6 +133,12 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* Has write method(s) */ #define FMODE_CAN_WRITE ((__force fmode_t)0x40000) +/* File hasn't page cache and can't be mmaped, for stackable filesystem */ +#define FMODE_NONMAPPABLE ((__force fmode_t)0x400000) + +/* File page don't need to be cached, for stackable filesystem's lower file */ +#define FMODE_NONCACHEABLE ((__force fmode_t)0x800000) + /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) @@ -1521,6 +1527,7 @@ struct file_operations { long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); int (*show_fdinfo)(struct seq_file *m, struct file *f); + struct file* (*get_lower_file)(struct file *f); }; struct inode_operations { @@ -1601,6 +1608,7 @@ struct super_operations { int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t); long (*nr_cached_objects)(struct super_block *, int); long (*free_cached_objects)(struct super_block *, long, int); + long (*unlink_callback)(struct super_block *, char *); }; /* diff --git a/include/linux/namei.h b/include/linux/namei.h index 492de72560fa..d80f3f874fa4 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -55,6 +55,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_JUMPED 0x1000 #define LOOKUP_ROOT 0x2000 #define LOOKUP_EMPTY 0x4000 +#define LOOKUP_CASE_INSENSITIVE 0x8000 extern int user_path_at(int, const char __user *, unsigned, struct path *); extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty); diff --git a/mm/mmap.c b/mm/mmap.c index 45d54faf80e6..52b16146b979 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1276,6 +1276,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, *populate = 0; + while (file && (file->f_mode & FMODE_NONMAPPABLE)) + file = file->f_op->get_lower_file(file); + #ifdef CONFIG_MSM_APP_SETTINGS if (file && file->f_path.dentry) { const char *name = file->f_path.dentry->d_name.name; From 1c64755713536719ae8b495a46fdaa6019d8ef43 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Fri, 22 Jul 2016 19:03:26 +0900 Subject: [PATCH 124/203] sdcardfs: merge version 3.2.0 Signed-off-by: Park Ju Hyung Signed-off-by: engstk --- fs/sdcardfs/inode.c | 13 ++++++++++++- fs/sdcardfs/packagelist.c | 2 +- fs/sdcardfs/version.h | 8 +++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 2f462b464372..258a6dc76df8 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -797,10 +797,21 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia) * the lower level. */ if (ia->ia_valid & ATTR_SIZE) { + loff_t oldsize; err = inode_newsize_ok(inode, ia->ia_size); if (err) goto out; - truncate_setsize(inode, ia->ia_size); + /* This code from truncate_setsize(). We need to add spin_lock + * to avoid race condition with fsstack_copy_inode_size() */ + oldsize = i_size_read(inode); + if (sizeof(ia->ia_size) > sizeof(long)) + spin_lock(&inode->i_lock); + i_size_write(inode, ia->ia_size); + if (sizeof(ia->ia_size) > sizeof(long)) + spin_unlock(&inode->i_lock); + if (ia->ia_size > oldsize) + pagecache_isize_extended(inode, oldsize, ia->ia_size); + truncate_pagecache(inode, ia->ia_size); } /* diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c index 0119430d67c0..d4dc0cb54712 100644 --- a/fs/sdcardfs/packagelist.c +++ b/fs/sdcardfs/packagelist.c @@ -237,7 +237,7 @@ static int packagelist_reader(void *thread_data) while (!kthread_should_stop()) { if (signal_pending(current)) { - ssleep(1); + msleep(100); continue; } diff --git a/fs/sdcardfs/version.h b/fs/sdcardfs/version.h index ee2b8dd9e079..e96685d701d4 100644 --- a/fs/sdcardfs/version.h +++ b/fs/sdcardfs/version.h @@ -23,6 +23,12 @@ * 2015.11.24 : Release Version 3.1.0 * - Add unlink_callback(), get_lower_inode() * - Add mount option type, label + * 2016.02. : Release Version 3.2.0 + * - remove get_lower_inode(), make sdcardfs use only unlink_callback() + * - modify name hash creation because it's different with vfat's + * - obb will be used only multi_user option is enabled + * - modify sdcardfs_setattr because it changes i_size without spinlock + * it can make race condition with fsstack_copy_inode_size() */ -#define SDCARDFS_VERSION "3.1.0" +#define SDCARDFS_VERSION "3.2.0" From 53720d596cff683e1af811286700ca2ffb638583 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Fri, 22 Jul 2016 19:03:41 +0900 Subject: [PATCH 125/203] sdcardfs: reserve 20MB by default Signed-off-by: Park Ju Hyung Signed-off-by: engstk --- fs/sdcardfs/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index ba30d49cfc7a..0cd0bd0f45e4 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -72,8 +72,8 @@ static int parse_options(struct super_block *sb, char *options, int silent, opts->userid = 0; /* by default, we use LOWER_FS_EXT4 as lower fs type */ opts->lower_fs = LOWER_FS_EXT4; - /* by default, 0MB is reserved */ - opts->reserved_mb = 0; + /* by default, 20MB is reserved */ + opts->reserved_mb = 20; /* by default, mask is 0 */ opts->mask = 0; /* by default, multi_user is false */ From f9c9b00a636dc061b41c461d6abc0574abd05e7a Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 27 Apr 2016 15:31:29 -0700 Subject: [PATCH 126/203] sdcardfs: replace LOOKUP_CASE_INSENSITIVE Signed-off-by: Daniel Rosenberg Signed-off-by: engstk --- fs/sdcardfs/lookup.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index fc5672bcc8f7..60187a3cc87a 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -231,12 +231,32 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry, lower_dir_mnt = lower_parent_path->mnt; /* Use vfs_path_lookup to check if the dentry exists or not */ + err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, + &lower_path); + + /* check for other cases */ if (sbi->options.lower_fs == LOWER_FS_EXT4) { - err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, - LOOKUP_CASE_INSENSITIVE, &lower_path); - } else if (sbi->options.lower_fs == LOWER_FS_FAT) { - err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, - &lower_path); + if (err == -ENOENT) { + struct dentry *child; + struct dentry *match = NULL; + spin_lock(&lower_dir_dentry->d_lock); + list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) { + if (child && child->d_inode) { + if (strcasecmp(child->d_name.name, name)==0) { + match = dget(child); + break; + } + } + } + spin_unlock(&lower_dir_dentry->d_lock); + if (match) { + err = vfs_path_lookup(lower_dir_dentry, + lower_dir_mnt, + match->d_name.name, 0, + &lower_path); + dput(match); + } + } } /* no error: handle positive dentries */ From 22694027da15f1d9ed3c58cf9fde46cb6f7069f1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Wed, 13 Apr 2016 16:38:34 -0700 Subject: [PATCH 127/203] sdcardfs: override umask on mkdir and create The mode on files created on the lower fs should not be affected by the umask of the calling task's fs_struct. Instead, we create a copy and modify it as needed. This also lets us avoid the string shenanigans around .nomedia files. Bug: 27992761 Change-Id: Ia3a6e56c24c6e19b3b01c1827e46403bb71c2f4c Signed-off-by: Daniel Rosenberg Signed-off-by: engstk --- fs/sdcardfs/inode.c | 62 ++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 258a6dc76df8..77c0b1cfe60b 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -19,6 +19,7 @@ */ #include "sdcardfs.h" +#include /* Do not directly use this function. Use OVERRIDE_CRED() instead. */ const struct cred * override_fsids(uid_t fsuid, gid_t fsgid) @@ -56,6 +57,8 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, struct dentry *lower_parent_dentry = NULL; struct path lower_path; const struct cred *saved_cred = NULL; + struct fs_struct *saved_fs; + struct fs_struct *copied_fs; if(!check_caller_access_to_name(dir, dentry->d_name.name)) { printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" @@ -78,6 +81,13 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, /* set last 16bytes of mode field to 0664 */ mode = (mode & S_IFMT) | 00664; + + /* temporarily change umask for lower fs write */ + saved_fs = current->fs; + copied_fs = copy_fs_struct(current->fs); + current->fs = copied_fs; + current->fs->umask = 0; + err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, true); if (err) @@ -90,6 +100,8 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); out: + current->fs = saved_fs; + free_fs_struct(copied_fs); mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_parent_dentry); @@ -267,11 +279,9 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode struct path lower_path; const struct cred *saved_cred = NULL; struct sdcardfs_inode_info *pi = SDCARDFS_I(dir); - char *page_buf; - char *nomedia_dir_name; - char *nomedia_fullpath; - int fullpath_namelen; int touch_err = 0; + struct fs_struct *saved_fs; + struct fs_struct *copied_fs; if(!check_caller_access_to_name(dir, dentry->d_name.name)) { printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" @@ -304,6 +314,13 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode /* set last 16bytes of mode field to 0775 */ mode = (mode & S_IFMT) | 00775; + + /* temporarily change umask for lower fs write */ + saved_fs = current->fs; + copied_fs = copy_fs_struct(current->fs); + current->fs = copied_fs; + current->fs->umask = 0; + err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode); if (err) { @@ -348,42 +365,17 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode /* When creating /Android/data and /Android/obb, mark them as .nomedia */ if (make_nomedia_in_obb || ((pi->perm == PERM_ANDROID) && (!strcasecmp(dentry->d_name.name, "data")))) { - - page_buf = (char *)__get_free_page(GFP_KERNEL); - if (!page_buf) { - printk(KERN_ERR "sdcardfs: failed to allocate page buf\n"); - goto out; - } - - nomedia_dir_name = d_absolute_path(&lower_path, page_buf, PAGE_SIZE); - if (IS_ERR(nomedia_dir_name)) { - free_page((unsigned long)page_buf); - printk(KERN_ERR "sdcardfs: failed to get .nomedia dir name\n"); - goto out; - } - - fullpath_namelen = page_buf + PAGE_SIZE - nomedia_dir_name - 1; - fullpath_namelen += strlen("/.nomedia"); - nomedia_fullpath = kzalloc(fullpath_namelen + 1, GFP_KERNEL); - if (!nomedia_fullpath) { - free_page((unsigned long)page_buf); - printk(KERN_ERR "sdcardfs: failed to allocate .nomedia fullpath buf\n"); - goto out; - } - - strcpy(nomedia_fullpath, nomedia_dir_name); - free_page((unsigned long)page_buf); - strcat(nomedia_fullpath, "/.nomedia"); - touch_err = touch(nomedia_fullpath, 0664); + set_fs_pwd(current->fs, &lower_path); + touch_err = touch(".nomedia", 0664); if (touch_err) { - printk(KERN_ERR "sdcardfs: failed to touch(%s): %d\n", - nomedia_fullpath, touch_err); - kfree(nomedia_fullpath); + printk(KERN_ERR "sdcardfs: failed to create .nomedia in %s: %d\n", + lower_path.dentry->d_name.name, touch_err); goto out; } - kfree(nomedia_fullpath); } out: + current->fs = saved_fs; + free_fs_struct(copied_fs); mnt_drop_write(lower_path.mnt); out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); From 59e64e6b6f009d10213d613aabcb6f244cad71a1 Mon Sep 17 00:00:00 2001 From: fluxi Date: Thu, 20 Oct 2016 14:35:35 +0200 Subject: [PATCH 128/203] soc: qcom: Update oneplus project_info for newer firmwares oneplus added the soc id to their project_info structure which let the scm call during initialization fail. Change-Id: I1791c1de01a08ccce841ef3a2d3850a94b66e059 --- drivers/soc/qcom/op_rf_cable_monitor.c | 10 ++++++++- drivers/soc/qcom/project_info.c | 30 +++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/op_rf_cable_monitor.c b/drivers/soc/qcom/op_rf_cable_monitor.c index c96f1958c14c..209984f70d2c 100755 --- a/drivers/soc/qcom/op_rf_cable_monitor.c +++ b/drivers/soc/qcom/op_rf_cable_monitor.c @@ -42,6 +42,7 @@ struct project_info{ uint32 ddr_raw; uint32 ddr_column; uint32 ddr_reserve_info; + uint32 platform_id; }; static struct project_info * project_info_desc; @@ -101,11 +102,18 @@ uint32 get_hw_version(void) 0, SMEM_ANY_HOST_FLAG); + if (IS_ERR_OR_NULL(project_info_desc)) + /* Retry for old fw version */ + project_info_desc = smem_find(SMEM_PROJECT_INFO, + sizeof(struct project_info) - + sizeof(uint32), 0, + SMEM_ANY_HOST_FLAG); + if (IS_ERR_OR_NULL(project_info_desc)) pr_err("%s: get project_info failure\n",__func__); else { - pr_err("%s: hw version: %d\n",__func__, project_info_desc->hw_version); + pr_info("%s: hw version: %d\n",__func__, project_info_desc->hw_version); return project_info_desc->hw_version; } return 0; diff --git a/drivers/soc/qcom/project_info.c b/drivers/soc/qcom/project_info.c index 1917df4652bd..72f253e09931 100755 --- a/drivers/soc/qcom/project_info.c +++ b/drivers/soc/qcom/project_info.c @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -31,6 +32,7 @@ struct project_info{ uint32 ddr_raw; uint32 ddr_column; uint32 ddr_reserve_info; + uint32 platform_id; }; struct component_info{ @@ -60,6 +62,7 @@ static DEVICE_ATTR(ddr_raw, S_IRUGO, project_info_get, NULL); static DEVICE_ATTR(ddr_column, S_IRUGO, project_info_get, NULL); static DEVICE_ATTR(ddr_reserve_info, S_IRUGO, project_info_get, NULL); static DEVICE_ATTR(secboot_status, S_IRUGO, project_info_get, NULL); +static DEVICE_ATTR(platform_id, S_IRUGO, project_info_get, NULL); uint32 get_secureboot_fuse_status(void) { @@ -104,6 +107,8 @@ static ssize_t project_info_get(struct device *dev, //return sprintf(buf, "%d\n", project_info_desc->ddr_reserve_info); return sprintf(buf, "%d\n",get_secureboot_fuse_status()); } + if (attr == &dev_attr_platform_id) + return sprintf(buf, "%d\n", socinfo_get_id()); return -EINVAL; @@ -122,6 +127,7 @@ static struct attribute *project_info_sysfs_entries[] = { &dev_attr_ddr_column.attr, &dev_attr_ddr_reserve_info.attr, &dev_attr_secboot_status.attr, + &dev_attr_platform_id.attr, NULL, }; @@ -354,6 +360,7 @@ int __init init_project_info(void) { static bool project_info_init_done; int ddr_size; + int fw_version = 1; if (project_info_init_done) return 0; @@ -363,12 +370,24 @@ int __init init_project_info(void) 0, SMEM_ANY_HOST_FLAG); - if (IS_ERR_OR_NULL(project_info_desc)) + if (IS_ERR_OR_NULL(project_info_desc)) { + /* Retry for old fw version */ + project_info_desc = smem_find(SMEM_PROJECT_INFO, + sizeof(struct project_info) - + sizeof(uint32), 0, + SMEM_ANY_HOST_FLAG); + + fw_version = 0; + } + + if (IS_ERR_OR_NULL(project_info_desc)) { pr_err("%s: get project_info failure\n",__func__); - else - pr_err("%s: project_name: %s hw_version: %d rf_v1: %d rf_v2: %d: rf_v3: %d\n", - __func__, project_info_desc->project_name, project_info_desc->hw_version, - project_info_desc->rf_v1, project_info_desc->rf_v2, project_info_desc->rf_v3); + goto error; + } else { + pr_info("%s: project_name: %s, fw_version: %d, hw_version: %d, rf_v1: %d, rf_v2: %d, rf_v3: %d\n", + __func__, project_info_desc->project_name, fw_version, project_info_desc->hw_version, + project_info_desc->rf_v1, project_info_desc->rf_v2, project_info_desc->rf_v3); + } //snprintf(mainboard_version, sizeof(mainboard_version), "%d",project_info_desc->hw_version); switch(project_info_desc->hw_version) { @@ -429,6 +448,7 @@ int __init init_project_info(void) snprintf(ddr_version, sizeof(ddr_version), "size_%dG_r_%d_c_%d", ddr_size, project_info_desc->ddr_raw,project_info_desc->ddr_column); push_component_info(DDR,ddr_version, ddr_manufacture); +error: project_info_init_done = true; return 0; From e9ee3d9a27f78dc0846fc676debf369f9b6c603b Mon Sep 17 00:00:00 2001 From: Sultanxda Date: Fri, 21 Oct 2016 01:37:16 -0700 Subject: [PATCH 129/203] proc: Remove verifiedbootstate flag from /proc/cmdline Userspace parses this and sets the ro.boot.verifiedbootstate prop according to the value that this flag has. When ro.boot.verifiedbootstate is not 'green', SafetyNet is tripped and fails the CTS test. Hide verifiedbootstate from /proc/cmdline in order to fix the failed SafetyNet CTS check. Signed-off-by: Sultanxda --- fs/proc/cmdline.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c index cbd82dff7e81..47fead689b2c 100644 --- a/fs/proc/cmdline.c +++ b/fs/proc/cmdline.c @@ -2,10 +2,13 @@ #include #include #include +#include + +static char new_command_line[COMMAND_LINE_SIZE]; static int cmdline_proc_show(struct seq_file *m, void *v) { - seq_printf(m, "%s\n", saved_command_line); + seq_printf(m, "%s\n", new_command_line); return 0; } @@ -23,6 +26,29 @@ static const struct file_operations cmdline_proc_fops = { static int __init proc_cmdline_init(void) { + char *offset_addr, *cmd = new_command_line; + + strcpy(cmd, saved_command_line); + + /* + * Remove 'androidboot.verifiedbootstate' flag from command line seen + * by userspace in order to pass SafetyNet CTS check. + */ + offset_addr = strstr(cmd, "androidboot.verifiedbootstate="); + if (offset_addr) { + size_t i, len, offset; + + len = strlen(cmd); + offset = offset_addr - cmd; + + for (i = 1; i < (len - offset); i++) { + if (cmd[offset + i] == ' ') + break; + } + + memmove(offset_addr, &cmd[offset + i + 1], len - i - offset); + } + proc_create("cmdline", 0, NULL, &cmdline_proc_fops); return 0; } From 7fb7abdae88b41f078788a32b9fb78ba3b1ad53d Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Tue, 12 Jul 2016 16:01:21 -0700 Subject: [PATCH 130/203] mdss: move to a kthread for vsync_retire_work_handler vsync_retire_work_handler is in the critical display path and should never be delayed because of other non-FIFO work. bug 30115868 Change-Id: Ic97744a81198ff303f9c87e1cf7c2468b4356a25 --- drivers/video/msm/mdss/mdss_mdp.h | 6 +++++- drivers/video/msm/mdss/mdss_mdp_overlay.c | 25 ++++++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h index ff54b3d787ae..b6dd3a131a2e 100644 --- a/drivers/video/msm/mdss/mdss_mdp.h +++ b/drivers/video/msm/mdss/mdss_mdp.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "mdss.h" #include "mdss_mdp_hwio.h" @@ -693,7 +694,6 @@ struct mdss_overlay_private { struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; - struct work_struct retire_work; int retire_cnt; bool kickoff_released; u32 cursor_ndx[2]; @@ -701,6 +701,10 @@ struct mdss_overlay_private { u32 bl_events; u32 ad_events; u32 ad_bl_events; + + struct kthread_worker worker; + struct kthread_work vsync_work; + struct task_struct *thread; }; struct mdss_mdp_set_ot_params { diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index 5a4bef795598..2506d12b49fa 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -4740,7 +4740,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) * retire_signal api checks for retire_cnt with sync_mutex lock. */ - flush_work(&mdp5_data->retire_work); + flush_kthread_work(&mdp5_data->vsync_work); } ctl_stop: @@ -4944,13 +4944,13 @@ static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t) } mdp5_data = mfd_to_mdp5_data(mfd); - schedule_work(&mdp5_data->retire_work); + queue_kthread_work(&mdp5_data->worker, &mdp5_data->vsync_work); } -static void __vsync_retire_work_handler(struct work_struct *work) +static void __vsync_retire_work_handler(struct kthread_work *work) { struct mdss_overlay_private *mdp5_data = - container_of(work, typeof(*mdp5_data), retire_work); + container_of(work, typeof(*mdp5_data), vsync_work); if (!mdp5_data->ctl || !mdp5_data->ctl->mfd) return; @@ -5038,6 +5038,7 @@ static int __vsync_retire_setup(struct msm_fb_data_type *mfd) { struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); char name[24]; + struct sched_param param = { .sched_priority = 5 }; snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index); mdp5_data->vsync_timeline = sw_sync_timeline_create(name); @@ -5045,12 +5046,26 @@ static int __vsync_retire_setup(struct msm_fb_data_type *mfd) pr_err("cannot vsync create time line"); return -ENOMEM; } + + init_kthread_worker(&mdp5_data->worker); + init_kthread_work(&mdp5_data->vsync_work, __vsync_retire_work_handler); + + mdp5_data->thread = kthread_run(kthread_worker_fn, + &mdp5_data->worker, "vsync_retire_work"); + + if (IS_ERR(mdp5_data->thread)) { + pr_err("unable to start vsync thread\n"); + mdp5_data->thread = NULL; + return -ENOMEM; + } + + sched_setscheduler(mdp5_data->thread, SCHED_FIFO, ¶m); + mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence; mdp5_data->vsync_retire_handler.vsync_handler = __vsync_retire_handle_vsync; mdp5_data->vsync_retire_handler.cmd_post_flush = false; - INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler); return 0; } From 030654bb8e45c0d5eff4b357947062c6a9811386 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Mon, 25 Jul 2016 19:21:17 -0700 Subject: [PATCH 131/203] kgsl: convert some workqueues to use kthreads adreno_dispatch_work and _kgsl_event_worker are both low-latency low-runtime functions that are in the critical path of GPU rendering. Moving them out of workqueues and into a dedicated FIFO kthread avoids significant jitter. bug 30342017 Change-Id: I5feb4e829064d422b4b9af2acb449afd1f981899 --- drivers/gpu/msm/adreno_dispatch.c | 6 +++--- drivers/gpu/msm/adreno_dispatch.h | 2 +- drivers/gpu/msm/kgsl.c | 14 ++++++++++++++ drivers/gpu/msm/kgsl.h | 6 +++++- drivers/gpu/msm/kgsl_events.c | 8 ++++---- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index d7a85f8cdf1f..3ec198f50576 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -2079,7 +2079,7 @@ int adreno_dispatch_process_cmdqueue(struct adreno_device *adreno_dev, * * Process expired commands and send new ones. */ -static void adreno_dispatcher_work(struct work_struct *work) +static void adreno_dispatcher_work(struct kthread_work *work) { struct adreno_dispatcher *dispatcher = container_of(work, struct adreno_dispatcher, work); @@ -2184,7 +2184,7 @@ void adreno_dispatcher_schedule(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - kgsl_schedule_work(&dispatcher->work); + queue_kthread_work(&kgsl_driver.worker, &dispatcher->work); } /** @@ -2469,7 +2469,7 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev) setup_timer(&dispatcher->preempt_timer, adreno_dispatcher_preempt_timer, (unsigned long) adreno_dev); - INIT_WORK(&dispatcher->work, adreno_dispatcher_work); + init_kthread_work(&dispatcher->work, adreno_dispatcher_work); init_completion(&dispatcher->idle_gate); complete_all(&dispatcher->idle_gate); diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h index 2699e9d537e5..8d56b70d916c 100644 --- a/drivers/gpu/msm/adreno_dispatch.h +++ b/drivers/gpu/msm/adreno_dispatch.h @@ -119,7 +119,7 @@ struct adreno_dispatcher { atomic_t fault; struct plist_head pending; spinlock_t plist_lock; - struct work_struct work; + struct kthread_work work; struct kobject kobj; struct completion idle_gate; atomic_t preemption_state; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 57bc580e838b..86ffe77a5a9d 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4025,6 +4025,8 @@ static void kgsl_core_exit(void) static int __init kgsl_core_init(void) { int result = 0; + struct sched_param param = { .sched_priority = 2 }; + /* alloc major and minor device numbers */ result = alloc_chrdev_region(&kgsl_driver.major, 0, KGSL_DEVICE_MAX, "kgsl"); @@ -4088,6 +4090,18 @@ static int __init kgsl_core_init(void) kgsl_driver.mem_workqueue = create_singlethread_workqueue("kgsl-mementry"); + init_kthread_worker(&kgsl_driver.worker); + + kgsl_driver.worker_thread = kthread_run(kthread_worker_fn, + &kgsl_driver.worker, "kgsl_worker_thread"); + + if (IS_ERR(kgsl_driver.worker_thread)) { + pr_err("unable to start kgsl thread\n"); + goto err; + } + + sched_setscheduler(kgsl_driver.worker_thread, SCHED_FIFO, ¶m); + kgsl_events_init(); result = kgsl_cmdbatch_init(); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index f675c4446081..a43de3a9495f 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -27,6 +27,7 @@ #include #include #include +#include /* The number of memstore arrays limits the number of contexts allowed. * If more contexts are needed, update multiple for MEMSTORE_SIZE @@ -106,6 +107,9 @@ struct kgsl_driver { unsigned int full_cache_threshold; struct workqueue_struct *workqueue; struct workqueue_struct *mem_workqueue; + + struct kthread_worker worker; + struct task_struct *worker_thread; }; extern struct kgsl_driver kgsl_driver; @@ -242,7 +246,7 @@ struct kgsl_event { void *priv; struct list_head node; unsigned int created; - struct work_struct work; + struct kthread_work work; int result; struct kgsl_event_group *group; }; diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c index e1f9ad17d0ff..256ed2883288 100644 --- a/drivers/gpu/msm/kgsl_events.c +++ b/drivers/gpu/msm/kgsl_events.c @@ -32,7 +32,7 @@ static inline void signal_event(struct kgsl_device *device, { list_del(&event->node); event->result = result; - queue_work(device->events_wq, &event->work); + queue_kthread_work(&kgsl_driver.worker, &event->work); } /** @@ -42,7 +42,7 @@ static inline void signal_event(struct kgsl_device *device, * Each event callback has its own work struct and is run on a event specific * workqeuue. This is the worker that queues up the event callback function. */ -static void _kgsl_event_worker(struct work_struct *work) +static void _kgsl_event_worker(struct kthread_work *work) { struct kgsl_event *event = container_of(work, struct kgsl_event, work); int id = KGSL_CONTEXT_ID(event->context); @@ -269,7 +269,7 @@ int kgsl_add_event(struct kgsl_device *device, struct kgsl_event_group *group, event->created = jiffies; event->group = group; - INIT_WORK(&event->work, _kgsl_event_worker); + init_kthread_work(&event->work, _kgsl_event_worker); trace_kgsl_register_event(KGSL_CONTEXT_ID(context), timestamp, func); @@ -284,7 +284,7 @@ int kgsl_add_event(struct kgsl_device *device, struct kgsl_event_group *group, if (timestamp_cmp(retired, timestamp) >= 0) { event->result = KGSL_EVENT_RETIRED; - queue_work(device->events_wq, &event->work); + queue_kthread_work(&kgsl_driver.worker, &event->work); spin_unlock(&group->lock); return 0; } From 46d7fe9f802e925f173619829d84e44cf443fac3 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 23 Oct 2016 22:17:17 -0400 Subject: [PATCH 132/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index ada19cae365a..dc24dab1d519 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -3632,7 +3632,6 @@ CONFIG_WLAN_FEATURE_RX_WAKELOCK=y # CONFIG_MSM_AVTIMER=y CONFIG_MSM_BUS_SCALING=y -# CONFIG_MSM_BUSPM_DEV is not set CONFIG_BUS_TOPOLOGY_ADHOC=y # CONFIG_DEBUG_BUS_VOTER is not set CONFIG_QPNP_POWER_ON=y @@ -3898,6 +3897,9 @@ CONFIG_EXT4_FS=y # CONFIG_EXT4_FS_POSIX_ACL is not set CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set +CONFIG_SDCARD_FS=y +CONFIG_SDCARD_FS_CI_SEARCH=y +CONFIG_SDCARD_FS_XATTR=y CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_JBD2=y From b7cfd0b0b965b8f225c94aa542c3ff451ce38e92 Mon Sep 17 00:00:00 2001 From: flar2 Date: Thu, 27 Oct 2016 20:23:51 -0400 Subject: [PATCH 133/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index dc24dab1d519..79b00f299685 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.25" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.26" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From d01c62d6a0875b58434f958b12e533710a03d89e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 13 Oct 2016 13:07:36 -0700 Subject: [PATCH 134/203] mm: remove gup_flags FOLL_WRITE games from __get_user_pages() commit 19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619 upstream. This is an ancient bug that was actually attempted to be fixed once (badly) by me eleven years ago in commit 4ceb5db9757a ("Fix get_user_pages() race for write access") but that was then undone due to problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug"). In the meantime, the s390 situation has long been fixed, and we can now fix it by checking the pte_dirty() bit properly (and do it better). The s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement software dirty bits") which made it into v3.9. Earlier kernels will have to look at the page state itself. Also, the VM has become more scalable, and what used a purely theoretical race back then has become easier to trigger. To fix it, we introduce a new internal FOLL_COW flag to mark the "yes, we already did a COW" rather than play racy games with FOLL_WRITE that is very fundamental, and then use the pte dirty flag to validate that the FOLL_COW flag is still valid. Change-Id: I83a08fd1f9c8928c0ed95286f737c27cc7811576 Reported-and-tested-by: Phil "not Paul" Oester Acked-by: Hugh Dickins Reviewed-by: Michal Hocko Cc: Andy Lutomirski Cc: Kees Cook Cc: Oleg Nesterov Cc: Willy Tarreau Cc: Nick Piggin Cc: Greg Thelen Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds [wt: s/gup.c/memory.c; s/follow_page_pte/follow_page_mask; s/faultin_page/__get_user_page] Signed-off-by: Willy Tarreau --- include/linux/mm.h | 1 + mm/gup.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 4a2a4a446fef..08d7b2103f3c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2034,6 +2034,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ +#define FOLL_COW 0x4000 /* internal GUP flag */ typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, void *data); diff --git a/mm/gup.c b/mm/gup.c index 377a5a796242..3cec4df06e6b 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -32,6 +32,16 @@ static struct page *no_page_table(struct vm_area_struct *vma, return NULL; } +/* + * FOLL_FORCE can write to even unwritable pte's, but only + * after we've gone through a COW cycle and they are dirty. + */ +static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) +{ + return pte_write(pte) || + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); +} + static struct page *follow_page_pte(struct vm_area_struct *vma, unsigned long address, pmd_t *pmd, unsigned int flags) { @@ -66,7 +76,7 @@ static struct page *follow_page_pte(struct vm_area_struct *vma, } if ((flags & FOLL_NUMA) && pte_numa(pte)) goto no_page; - if ((flags & FOLL_WRITE) && !pte_write(pte)) { + if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) { pte_unmap_unlock(ptep, ptl); return NULL; } @@ -315,7 +325,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, * reCOWed by userspace write). */ if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE)) - *flags &= ~FOLL_WRITE; + *flags |= FOLL_COW; return 0; } From 9c4bf0d9528e54b6ca1b1b0728321ea7b35edfe4 Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 29 Oct 2016 12:12:46 -0400 Subject: [PATCH 135/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 79b00f299685..a6d62b3b4ec6 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.26" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.27" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 90676c4ddbca522ca6b2b15864e65e7e246bf177 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 10 Jun 2015 08:01:20 -0600 Subject: [PATCH 136/203] cfq-iosched: fix the setting of IOPS mode on SSDs A previous commit wanted to make CFQ default to IOPS mode on non-rotational storage, however it did so when the queue was initialized and the non-rotational flag is only set later on in the probe. Add an elevator hook that gets called off the add_disk() path, at that point we know that feature probing has finished, and we can reliably check for the various flags that drivers can set. Change-Id: Ieaf0beed1efc0ace7e61766e725647c6509e9852 Fixes: 41c0126b ("block: Make CFQ default to IOPS mode on SSDs") Tested-by: Romain Francoise Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 15 ++++++++++++++- block/elevator.c | 2 ++ include/linux/elevator.h | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 402be0139122..a8ad4f16e10a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4460,7 +4460,7 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e) cfqd->cfq_slice[1] = cfq_slice_sync; cfqd->cfq_target_latency = cfq_target_latency; cfqd->cfq_slice_async_rq = cfq_slice_async_rq; - cfqd->cfq_slice_idle = blk_queue_nonrot(q) ? 0 : cfq_slice_idle; + cfqd->cfq_slice_idle = cfq_slice_idle; cfqd->cfq_group_idle = cfq_group_idle; cfqd->cfq_latency = 1; cfqd->hw_tag = -1; @@ -4477,6 +4477,18 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e) return ret; } +static void cfq_registered_queue(struct request_queue *q) +{ + struct elevator_queue *e = q->elevator; + struct cfq_data *cfqd = e->elevator_data; + + /* + * Default to IOPS mode with no idling for SSDs + */ + if (blk_queue_nonrot(q)) + cfqd->cfq_slice_idle = 0; +} + /* * sysfs parts below --> */ @@ -4592,6 +4604,7 @@ static struct elevator_type iosched_cfq = { .elevator_may_queue_fn = cfq_may_queue, .elevator_init_fn = cfq_init_queue, .elevator_exit_fn = cfq_exit_queue, + .elevator_registered_fn = cfq_registered_queue, }, .icq_size = sizeof(struct cfq_io_cq), .icq_align = __alignof__(struct cfq_io_cq), diff --git a/block/elevator.c b/block/elevator.c index c73f01da4631..a5c5678246ab 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -810,6 +810,8 @@ int elv_register_queue(struct request_queue *q) } kobject_uevent(&e->kobj, KOBJ_ADD); e->registered = 1; + if (e->type->ops.elevator_registered_fn) + e->type->ops.elevator_registered_fn(q); } return error; } diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 45a91474487d..638b324f0291 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -39,6 +39,7 @@ typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct reques typedef int (elevator_init_fn) (struct request_queue *, struct elevator_type *e); typedef void (elevator_exit_fn) (struct elevator_queue *); +typedef void (elevator_registered_fn) (struct request_queue *); struct elevator_ops { @@ -68,6 +69,7 @@ struct elevator_ops elevator_init_fn *elevator_init_fn; elevator_exit_fn *elevator_exit_fn; + elevator_registered_fn *elevator_registered_fn; }; #define ELV_NAME_MAX (16) From dcd87e0f110593ec965694bcf546aa9ede1678de Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Dec 2015 01:34:26 +0000 Subject: [PATCH 137/203] KEYS: Fix race between read and revoke commit b4a1b4f5047e4f54e194681125c74c0aa64d637d upstream. This fixes CVE-2015-7550. There's a race between keyctl_read() and keyctl_revoke(). If the revoke happens between keyctl_read() checking the validity of a key and the key's semaphore being taken, then the key type read method will see a revoked key. This causes a problem for the user-defined key type because it assumes in its read method that there will always be a payload in a non-revoked key and doesn't check for a NULL pointer. Fix this by making keyctl_read() check the validity of a key after taking semaphore instead of before. I think the bug was introduced with the original keyrings code. This was discovered by a multithreaded test program generated by syzkaller (http://github.com/google/syzkaller). Here's a cleaned up version: #include #include #include void *thr0(void *arg) { key_serial_t key = (unsigned long)arg; keyctl_revoke(key); return 0; } void *thr1(void *arg) { key_serial_t key = (unsigned long)arg; char buffer[16]; keyctl_read(key, buffer, 16); return 0; } int main() { key_serial_t key = add_key("user", "%", "foo", 3, KEY_SPEC_USER_KEYRING); pthread_t th[5]; pthread_create(&th[0], 0, thr0, (void *)(unsigned long)key); pthread_create(&th[1], 0, thr1, (void *)(unsigned long)key); pthread_create(&th[2], 0, thr0, (void *)(unsigned long)key); pthread_create(&th[3], 0, thr1, (void *)(unsigned long)key); pthread_join(th[0], 0); pthread_join(th[1], 0); pthread_join(th[2], 0); pthread_join(th[3], 0); return 0; } Build as: cc -o keyctl-race keyctl-race.c -lkeyutils -lpthread Run as: while keyctl-race; do :; done as it may need several iterations to crash the kernel. The crash can be summarised as: BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 IP: [] user_read+0x56/0xa3 ... Call Trace: [] keyctl_read_key+0xb6/0xd7 [] SyS_keyctl+0x83/0xe0 [] entry_SYSCALL_64_fastpath+0x12/0x6f Change-Id: I7650e04b254ba73cf97d34dfb1410cb30f64b209 Reported-by: Dmitry Vyukov Signed-off-by: David Howells Tested-by: Dmitry Vyukov Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman Signed-off-by: engstk --- security/keys/keyctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4743d71e4aa6..fee27fe2b30f 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -757,16 +757,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) /* the key is probably readable - now try to read it */ can_read_key: - ret = key_validate(key); - if (ret == 0) { - ret = -EOPNOTSUPP; - if (key->type->read) { - /* read the data with the semaphore held (since we - * might sleep) */ - down_read(&key->sem); + ret = -EOPNOTSUPP; + if (key->type->read) { + /* Read the data with the semaphore held (since we might sleep) + * to protect against the key being updated or revoked. + */ + down_read(&key->sem); + ret = key_validate(key); + if (ret == 0) ret = key->type->read(key, buffer, buflen); - up_read(&key->sem); - } + up_read(&key->sem); } error2: From 4e5ac21658ed15474034f2b4e75437282d7693da Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Jun 2016 15:48:57 +0100 Subject: [PATCH 138/203] KEYS: potential uninitialized variable [ Upstream commit 38327424b40bcebe2de92d07312c89360ac9229a ] If __key_link_begin() failed then "edit" would be uninitialized. I've added a check to fix that. This allows a random user to crash the kernel, though it's quite difficult to achieve. There are three ways it can be done as the user would have to cause an error to occur in __key_link(): (1) Cause the kernel to run out of memory. In practice, this is difficult to achieve without ENOMEM cropping up elsewhere and aborting the attempt. (2) Revoke the destination keyring between the keyring ID being looked up and it being tested for revocation. In practice, this is difficult to time correctly because the KEYCTL_REJECT function can only be used from the request-key upcall process. Further, users can only make use of what's in /sbin/request-key.conf, though this does including a rejection debugging test - which means that the destination keyring has to be the caller's session keyring in practice. (3) Have just enough key quota available to create a key, a new session keyring for the upcall and a link in the session keyring, but not then sufficient quota to create a link in the nominated destination keyring so that it fails with EDQUOT. The bug can be triggered using option (3) above using something like the following: echo 80 >/proc/sys/kernel/keys/root_maxbytes keyctl request2 user debug:fred negate @t The above sets the quota to something much lower (80) to make the bug easier to trigger, but this is dependent on the system. Note also that the name of the keyring created contains a random number that may be between 1 and 10 characters in size, so may throw the test off by changing the amount of quota used. Assuming the failure occurs, something like the following will be seen: kfree_debugcheck: out of range ptr 6b6b6b6b6b6b6b68h ------------[ cut here ]------------ kernel BUG at ../mm/slab.c:2821! ... RIP: 0010:[] kfree_debugcheck+0x20/0x25 RSP: 0018:ffff8804014a7de8 EFLAGS: 00010092 RAX: 0000000000000034 RBX: 6b6b6b6b6b6b6b68 RCX: 0000000000000000 RDX: 0000000000040001 RSI: 00000000000000f6 RDI: 0000000000000300 RBP: ffff8804014a7df0 R08: 0000000000000001 R09: 0000000000000000 R10: ffff8804014a7e68 R11: 0000000000000054 R12: 0000000000000202 R13: ffffffff81318a66 R14: 0000000000000000 R15: 0000000000000001 ... Call Trace: kfree+0xde/0x1bc assoc_array_cancel_edit+0x1f/0x36 __key_link_end+0x55/0x63 key_reject_and_link+0x124/0x155 keyctl_reject_key+0xb6/0xe0 keyctl_negate_key+0x10/0x12 SyS_keyctl+0x9f/0xe7 do_syscall_64+0x63/0x13a entry_SYSCALL64_slow_path+0x25/0x25 Fixes: f70e2e06196a ('KEYS: Do preallocation for __key_link()') Signed-off-by: Dan Carpenter Signed-off-by: David Howells cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: engstk --- security/keys/key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/key.c b/security/keys/key.c index e17ba6aefdc0..f8bde20bed5d 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -580,7 +580,7 @@ int key_reject_and_link(struct key *key, mutex_unlock(&key_construction_mutex); - if (keyring) + if (keyring && link_ret == 0) __key_link_end(keyring, &key->index_key, edit); /* wake up anyone waiting for a key to be constructed */ From 53ac86116525623d07bac21296b87e3522c9daf8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Sep 2016 14:03:45 +0100 Subject: [PATCH 139/203] KEYS: Fix short sprintf buffer in /proc/keys show function Fix a short sprintf buffer in proc_keys_show(). If the gcc stack protector is turned on, this can cause a panic due to stack corruption. The problem is that xbuf[] is not big enough to hold a 64-bit timeout rendered as weeks: (gdb) p 0xffffffffffffffffULL/(60*60*24*7) $2 = 30500568904943 That's 14 chars plus NUL, not 11 chars plus NUL. Expand the buffer to 16 chars. I think the unpatched code apparently works if the stack-protector is not enabled because on a 32-bit machine the buffer won't be overflowed and on a 64-bit machine there's a 64-bit aligned pointer at one side and an int that isn't checked again on the other side. The panic incurred looks something like: Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81352ebe CPU: 0 PID: 1692 Comm: reproducer Not tainted 4.7.2-201.fc24.x86_64 #1 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 0000000000000086 00000000fbbd2679 ffff8800a044bc00 ffffffff813d941f ffffffff81a28d58 ffff8800a044bc98 ffff8800a044bc88 ffffffff811b2cb6 ffff880000000010 ffff8800a044bc98 ffff8800a044bc30 00000000fbbd2679 Call Trace: [] dump_stack+0x63/0x84 [] panic+0xde/0x22a [] ? proc_keys_show+0x3ce/0x3d0 [] __stack_chk_fail+0x19/0x30 [] proc_keys_show+0x3ce/0x3d0 [] ? key_validate+0x50/0x50 [] ? key_default_cmp+0x20/0x20 [] seq_read+0x2cc/0x390 [] proc_reg_read+0x42/0x70 [] __vfs_read+0x37/0x150 [] ? security_file_permission+0xa0/0xc0 [] vfs_read+0x96/0x130 [] SyS_read+0x55/0xc0 [] entry_SYSCALL_64_fastpath+0x1a/0xa4 Change-Id: I0787d5a38c730ecb75d3c08f28f0ab36295d59e7 Reported-by: Ondrej Kozina Signed-off-by: David Howells Tested-by: Ondrej Kozina Signed-off-by: engstk --- security/keys/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/proc.c b/security/keys/proc.c index 972eeb336b81..9962535ef9ad 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -187,7 +187,7 @@ static int proc_keys_show(struct seq_file *m, void *v) struct timespec now; unsigned long timo; key_ref_t key_ref, skey_ref; - char xbuf[12]; + char xbuf[16]; int rc; struct keyring_search_context ctx = { From 07537b4bae3065d936a58211da097fdc84c199ea Mon Sep 17 00:00:00 2001 From: myfluxi Date: Wed, 1 Jan 2014 11:31:16 +0100 Subject: [PATCH 140/203] msm: kgsl: Report correct GPU frequency in sysfs Change-Id: I1aac90d0554b9de0511ffb78042177a5a23855ce --- drivers/gpu/msm/kgsl_pwrctrl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index fbd476c25ac9..2fc9ae407bff 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -712,12 +712,19 @@ 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; - return snprintf(buf, PAGE_SIZE, "%ld\n", kgsl_pwrctrl_active_freq(pwr)); + + 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); } static ssize_t __timer_store(struct device *dev, struct device_attribute *attr, From a1448d86fcdc0f5379705427bb44134e6326bb8c Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Fri, 18 Sep 2015 23:41:23 +0200 Subject: [PATCH 141/203] BACKPORT: security: fix typo in security_task_prctl Signed-off-by: Jann Horn Reviewed-by: Andy Lutomirski Signed-off-by: Linus Torvalds (cherry picked from commit b7f76ea2ef6739ee484a165ffbac98deb855d3d3) Test: Builds. Change-Id: I6a45b878e7f2aeb9d926630cc724dc4ada79b4d1 Signed-off-by: Jorge Lucangeli Obes Signed-off-by: engstk --- include/linux/security.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/security.h b/include/linux/security.h index 00902806a289..c0855c22e310 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2527,7 +2527,7 @@ static inline int security_task_prctl(int option, unsigned long arg2, unsigned long arg4, unsigned long arg5) { - return cap_task_prctl(option, arg2, arg3, arg3, arg5); + return cap_task_prctl(option, arg2, arg3, arg4, arg5); } static inline void security_task_to_inode(struct task_struct *p, struct inode *inode) From 0136101227540e45a0dc8e24bcb39a2db781cd06 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 16 Mar 2016 13:26:17 +0100 Subject: [PATCH 142/203] USB: usb_driver_claim_interface: add sanity checking commit 0b818e3956fc1ad976bee791eadcbb3b5fec5bfd upstream. Attacks that trick drivers into passing a NULL pointer to usb_driver_claim_interface() using forged descriptors are known. This thwarts them by sanity checking. Change-Id: I3428403c47fc53394f85e59ca17dd6974a579d73 Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings --- drivers/usb/core/driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 104bd3b738d9..9697b556c061 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -499,11 +499,15 @@ static int usb_unbind_interface(struct device *dev) int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) { - struct device *dev = &iface->dev; + struct device *dev; struct usb_device *udev; int retval = 0; int lpm_disable_error; + if (!iface) + return -ENODEV; + + dev = &iface->dev; if (dev->driver) return -EBUSY; From 8e488d23f2ea3b8628867c03d2e7352142a5e2da Mon Sep 17 00:00:00 2001 From: flar2 Date: Sun, 20 Nov 2016 00:29:55 -0500 Subject: [PATCH 143/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index a6d62b3b4ec6..eec40ccded9c 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.27" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.28" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y From 7641e153475f912d82352777a8143725d32b72d3 Mon Sep 17 00:00:00 2001 From: Stepan Moskovchenko Date: Thu, 12 Jun 2014 18:55:06 -0700 Subject: [PATCH 144/203] arm64: Log the machine name string during boot up The change to refactor kernel/setup.c to use the common of_flat_dt_get_machine_name() API has apparently removed the line which prints the device tree model string during boot. Having the model string in the kernel log is helpful, so add it back in. This change was already merged in past but possibly got overridden during upmerge. Add it back. While at it, add back print for the processor name and its rev id as well. Change-Id: I7dccc3ab00f5b67753cdd256846a522596c5058f Signed-off-by: Stepan Moskovchenko Signed-off-by: Kaushal Kumar --- arch/arm64/kernel/setup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index da9b13f9ec8c..ce72c0ee4ddd 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -353,9 +353,10 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) } machine_name = of_flat_dt_get_machine_name(); - dump_stack_set_arch_desc("%s (DT)", machine_name); - if (machine_name) + if (machine_name) { + dump_stack_set_arch_desc("%s (DT)", machine_name); pr_info("Machine: %s\n", machine_name); + } } /* From 15e66a6fbb114cd1262d93cc0ab2901012857b85 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Fri, 18 Sep 2015 23:41:23 +0200 Subject: [PATCH 145/203] BACKPORT: security: fix typo in security_task_prctl Signed-off-by: Jann Horn Reviewed-by: Andy Lutomirski Signed-off-by: Linus Torvalds (cherry picked from commit b7f76ea2ef6739ee484a165ffbac98deb855d3d3) Test: Builds. Change-Id: I6a45b878e7f2aeb9d926630cc724dc4ada79b4d1 Signed-off-by: Jorge Lucangeli Obes Signed-off-by: engstk --- include/linux/security.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/security.h b/include/linux/security.h index 00902806a289..c0855c22e310 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2527,7 +2527,7 @@ static inline int security_task_prctl(int option, unsigned long arg2, unsigned long arg4, unsigned long arg5) { - return cap_task_prctl(option, arg2, arg3, arg3, arg5); + return cap_task_prctl(option, arg2, arg3, arg4, arg5); } static inline void security_task_to_inode(struct task_struct *p, struct inode *inode) From 4becca7d981f5a1018aead8a7a43dbc1501a96f1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Dec 2015 01:34:26 +0000 Subject: [PATCH 146/203] KEYS: Fix race between read and revoke commit b4a1b4f5047e4f54e194681125c74c0aa64d637d upstream. This fixes CVE-2015-7550. There's a race between keyctl_read() and keyctl_revoke(). If the revoke happens between keyctl_read() checking the validity of a key and the key's semaphore being taken, then the key type read method will see a revoked key. This causes a problem for the user-defined key type because it assumes in its read method that there will always be a payload in a non-revoked key and doesn't check for a NULL pointer. Fix this by making keyctl_read() check the validity of a key after taking semaphore instead of before. I think the bug was introduced with the original keyrings code. This was discovered by a multithreaded test program generated by syzkaller (http://github.com/google/syzkaller). Here's a cleaned up version: #include #include #include void *thr0(void *arg) { key_serial_t key = (unsigned long)arg; keyctl_revoke(key); return 0; } void *thr1(void *arg) { key_serial_t key = (unsigned long)arg; char buffer[16]; keyctl_read(key, buffer, 16); return 0; } int main() { key_serial_t key = add_key("user", "%", "foo", 3, KEY_SPEC_USER_KEYRING); pthread_t th[5]; pthread_create(&th[0], 0, thr0, (void *)(unsigned long)key); pthread_create(&th[1], 0, thr1, (void *)(unsigned long)key); pthread_create(&th[2], 0, thr0, (void *)(unsigned long)key); pthread_create(&th[3], 0, thr1, (void *)(unsigned long)key); pthread_join(th[0], 0); pthread_join(th[1], 0); pthread_join(th[2], 0); pthread_join(th[3], 0); return 0; } Build as: cc -o keyctl-race keyctl-race.c -lkeyutils -lpthread Run as: while keyctl-race; do :; done as it may need several iterations to crash the kernel. The crash can be summarised as: BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 IP: [] user_read+0x56/0xa3 ... Call Trace: [] keyctl_read_key+0xb6/0xd7 [] SyS_keyctl+0x83/0xe0 [] entry_SYSCALL_64_fastpath+0x12/0x6f Change-Id: I7650e04b254ba73cf97d34dfb1410cb30f64b209 Reported-by: Dmitry Vyukov Signed-off-by: David Howells Tested-by: Dmitry Vyukov Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman Signed-off-by: engstk --- security/keys/keyctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4743d71e4aa6..fee27fe2b30f 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -757,16 +757,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) /* the key is probably readable - now try to read it */ can_read_key: - ret = key_validate(key); - if (ret == 0) { - ret = -EOPNOTSUPP; - if (key->type->read) { - /* read the data with the semaphore held (since we - * might sleep) */ - down_read(&key->sem); + ret = -EOPNOTSUPP; + if (key->type->read) { + /* Read the data with the semaphore held (since we might sleep) + * to protect against the key being updated or revoked. + */ + down_read(&key->sem); + ret = key_validate(key); + if (ret == 0) ret = key->type->read(key, buffer, buflen); - up_read(&key->sem); - } + up_read(&key->sem); } error2: From 4b872e9dcc1d46151678bbce60d9eb346b11c378 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Tue, 23 Feb 2016 13:11:20 +0530 Subject: [PATCH 147/203] leds: qpnp-flash: check power supply variable in flash led driver Check the power supply variable if it is NULL or not, in flash led driver while enabling the flash led. This change is added to avoid crash in flash led driver. CRs-Fixed: 944997 Change-Id: Ide1a9151d2a7c9a6686268a53ec9e38a4b087808 Signed-off-by: Shantanu Jain --- drivers/leds/leds-qpnp-flash.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index f615a6a07b98..0d11181f5b5b 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -1409,12 +1409,18 @@ static void qpnp_flash_led_work(struct work_struct *work) max_curr_avail_ma += flash_node->max_current; psy_prop.intval = true; - rc = led->battery_psy->set_property(led->battery_psy, + if (led->battery_psy) { + rc = led->battery_psy->set_property(led->battery_psy, POWER_SUPPLY_PROP_FLASH_ACTIVE, - &psy_prop); - if (rc) { + &psy_prop); + if (rc) { + dev_err(&led->spmi_dev->dev, + "Failed to setup OTG pulse skip enable\n"); + goto exit_flash_led_work; + } + } else { dev_err(&led->spmi_dev->dev, - "Failed to setup OTG pulse skip enable\n"); + "led->battery_psy is NULL\n"); goto exit_flash_led_work; } From 4db4c6f60083e5355cfd5276ed55f15d4518d3e5 Mon Sep 17 00:00:00 2001 From: Srinivasarao P Date: Tue, 1 Mar 2016 12:16:03 +0530 Subject: [PATCH 148/203] perf: duplicate deletion of perf event a malicious app can open a perf event with constraint_duplicate bit set, disable the event, and close the fd. On closing the fd, the perf_release() modification causes the kernel to clean up the event as if it still were enabled, leading to the event being removed from a list twice. CRs-Fixed: 977563 Change-Id: I5fbec3722407d2f3d0ff0d9f7097c5889e31fd62 Signed-off-by: Srinivasarao P --- kernel/events/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index cd82f5d55ec3..83dbf36ab7a8 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7305,6 +7305,9 @@ SYSCALL_DEFINE5(perf_event_open, if (err) return err; + if (attr.constraint_duplicate || attr.__reserved_1) + return -EINVAL; + if (!attr.exclude_kernel) { if (perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) return -EACCES; From 2302bb0f1cd88e626860a0c1fca209a9d38efa64 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Fri, 4 Mar 2016 09:52:50 +0800 Subject: [PATCH 149/203] ASoc: soundwire: add null check before using map Pointer map returned from dev_get_name may be null. Add null check before derefering. CRs-Fixed: 985337 Change-Id: I952ae63e9b909dde763b3024d90fe4553e852860 Signed-off-by: Meng Wang --- drivers/base/regmap/regmap-swr.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/base/regmap/regmap-swr.c b/drivers/base/regmap/regmap-swr.c index 20804cc36ad0..bc172c649f61 100644 --- a/drivers/base/regmap/regmap-swr.c +++ b/drivers/base/regmap/regmap-swr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-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 @@ -68,10 +68,10 @@ static int regmap_swr_raw_multi_reg_write(void *context, const void *data, struct device *dev = context; struct swr_device *swr = to_swr_device(dev); struct regmap *map = dev_get_regmap(dev, NULL); - size_t addr_bytes = map->format.reg_bytes; - size_t val_bytes = map->format.val_bytes; - size_t pad_bytes = map->format.pad_bytes; - size_t num_regs = (count / (addr_bytes + val_bytes + pad_bytes)); + size_t addr_bytes; + size_t val_bytes; + size_t pad_bytes; + size_t num_regs; int i = 0; int ret = 0; u16 *reg; @@ -83,6 +83,21 @@ static int regmap_swr_raw_multi_reg_write(void *context, const void *data, return -EINVAL; } + if (map == NULL) { + dev_err(dev, "%s: regmap is NULL\n", __func__); + return -EINVAL; + } + + addr_bytes = map->format.reg_bytes; + val_bytes = map->format.val_bytes; + pad_bytes = map->format.pad_bytes; + + if (addr_bytes + val_bytes + pad_bytes == 0) { + dev_err(dev, "%s: sum of addr, value and pad is 0\n", __func__); + return -EINVAL; + } + num_regs = count / (addr_bytes + val_bytes + pad_bytes); + reg = kcalloc(num_regs, sizeof(u16), GFP_KERNEL); if (!reg) return -ENOMEM; From bd409b149fa3f6250a71dc2ae583ea5c51576764 Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Wed, 9 Mar 2016 11:49:08 +0530 Subject: [PATCH 150/203] msm: ADSPRPC: Fix buffer overflow for session Fix to check the session count before accessing the session buffer. Change-Id: Iff98b6504c331d65f46c7934e09720f4522ea225 Acked-by: Bharath Kumar Signed-off-by: Sathish Ambley --- drivers/char/adsprpc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index cfc8cbf22278..0ba1b05fefd2 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2051,6 +2051,9 @@ static int fastrpc_cb_legacy_probe(struct device *dev) &disable_htw); VERIFY(err, !arm_iommu_attach_device(first_sess->dev, first_sess->smmu.mapping)); + if (err) + goto bail; + VERIFY(err, (sids_size/sizeof(unsigned int)) <= NUM_SESSIONS); if (err) goto bail; for (i = 0; i < sids_size/sizeof(unsigned int); i++) { From c281b5a840be464cfc3457c1ff82e7d5d68e5bb3 Mon Sep 17 00:00:00 2001 From: Dibyendu Roy Date: Wed, 23 Mar 2016 14:00:19 +0530 Subject: [PATCH 151/203] Bluetooth: Replace %p with %pK The %pK restrictions are used to eliminate exposing kernel addresses. When kptr_restrict is set to "0" there are no restrictions. When kptr_restrict is set to "1", kernel pointers printed using the %pK format specifier will be replaced with 0's unless the user has CAP_SYSLOG. When kptr_restrict is set to "2", kernel pointers printed using %pK will be replaced with 0's regardless of privileges. Change-Id: Iacd8f7b7cdafed3a111507d3da899be9261ff09f Signed-off-by: Dibyendu Roy --- drivers/bluetooth/hci_h4.c | 8 +- drivers/bluetooth/hci_ibs.c | 30 +++--- drivers/bluetooth/hci_ldisc.c | 12 +-- net/bluetooth/af_bluetooth.c | 18 ++-- net/bluetooth/bnep/core.c | 2 +- net/bluetooth/bnep/netdev.c | 4 +- net/bluetooth/bnep/sock.c | 4 +- net/bluetooth/cmtp/capi.c | 31 +++--- net/bluetooth/cmtp/core.c | 10 +- net/bluetooth/cmtp/sock.c | 4 +- net/bluetooth/hci_conn.c | 44 ++++---- net/bluetooth/hci_core.c | 48 ++++----- net/bluetooth/hci_event.c | 10 +- net/bluetooth/hci_sock.c | 20 ++-- net/bluetooth/hci_sysfs.c | 4 +- net/bluetooth/hidp/core.c | 21 ++-- net/bluetooth/hidp/sock.c | 4 +- net/bluetooth/l2cap_core.c | 191 +++++++++++++++++----------------- net/bluetooth/l2cap_sock.c | 38 +++---- net/bluetooth/lib.c | 4 +- net/bluetooth/mgmt.c | 16 +-- net/bluetooth/rfcomm/core.c | 130 +++++++++++------------ net/bluetooth/rfcomm/sock.c | 47 +++++---- net/bluetooth/rfcomm/tty.c | 48 ++++----- net/bluetooth/sco.c | 64 ++++++------ net/bluetooth/smp.c | 42 ++++---- 26 files changed, 429 insertions(+), 425 deletions(-) diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 66db9a803373..e5062552e90e 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -60,7 +60,7 @@ static int h4_open(struct hci_uart *hu) { struct h4_struct *h4; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); h4 = kzalloc(sizeof(*h4), GFP_KERNEL); if (!h4) @@ -77,7 +77,7 @@ static int h4_flush(struct hci_uart *hu) { struct h4_struct *h4 = hu->priv; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); skb_queue_purge(&h4->txq); @@ -91,7 +91,7 @@ static int h4_close(struct hci_uart *hu) hu->priv = NULL; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); skb_queue_purge(&h4->txq); @@ -108,7 +108,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) { struct h4_struct *h4 = hu->priv; - BT_DBG("hu %p skb %p", hu, skb); + BT_DBG("hu %pK skb %pK", hu, skb); /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c index 96f362ebeb55..6e202b5a2241 100644 --- a/drivers/bluetooth/hci_ibs.c +++ b/drivers/bluetooth/hci_ibs.c @@ -226,7 +226,7 @@ static int send_hci_ibs_cmd(u8 cmd, struct hci_uart *hu) struct ibs_struct *ibs = hu->priv; struct hci_ibs_cmd *hci_ibs_packet; - BT_DBG("hu %p cmd 0x%x", hu, cmd); + BT_DBG("hu %pK cmd 0x%x", hu, cmd); /* allocate packet */ skb = bt_skb_alloc(1, GFP_ATOMIC); @@ -254,7 +254,7 @@ static void ibs_wq_awake_device(struct work_struct *work) struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu; unsigned long flags; - BT_DBG(" %p ", hu); + BT_DBG(" %pK ", hu); /* Vote for serial clock */ ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu); @@ -281,7 +281,7 @@ static void ibs_wq_awake_rx(struct work_struct *work) struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu; unsigned long flags; - BT_DBG(" %p ", hu); + BT_DBG(" %pK ", hu); ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu); @@ -309,7 +309,7 @@ static void ibs_wq_serial_rx_clock_vote_off(struct work_struct *work) ws_rx_vote_off); struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu; - BT_DBG(" %p ", hu); + BT_DBG(" %pK ", hu); ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu); @@ -321,7 +321,7 @@ static void ibs_wq_serial_tx_clock_vote_off(struct work_struct *work) ws_tx_vote_off); struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu; - BT_DBG(" %p ", hu); + BT_DBG(" %pK ", hu); hci_uart_tx_wakeup(hu); /* run HCI tx handling unlocked */ @@ -337,7 +337,7 @@ static void hci_ibs_tx_idle_timeout(unsigned long arg) struct ibs_struct *ibs = hu->priv; unsigned long flags; - BT_DBG("hu %p idle timeout in %lu state", hu, ibs->tx_ibs_state); + BT_DBG("hu %pK idle timeout in %lu state", hu, ibs->tx_ibs_state); spin_lock_irqsave_nested(&ibs->hci_ibs_lock, flags, SINGLE_DEPTH_NESTING); @@ -371,7 +371,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg) unsigned long flags; unsigned long retransmit = 0; - BT_DBG("hu %p wake retransmit timeout in %lu state", + BT_DBG("hu %pK wake retransmit timeout in %lu state", hu, ibs->tx_ibs_state); spin_lock_irqsave_nested(&ibs->hci_ibs_lock, @@ -404,7 +404,7 @@ static int ibs_open(struct hci_uart *hu) { struct ibs_struct *ibs; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); ibs = kzalloc(sizeof(*ibs), GFP_ATOMIC); if (!ibs) @@ -500,7 +500,7 @@ static int ibs_flush(struct hci_uart *hu) { struct ibs_struct *ibs = hu->priv; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); skb_queue_purge(&ibs->tx_wait_q); skb_queue_purge(&ibs->txq); @@ -513,7 +513,7 @@ static int ibs_close(struct hci_uart *hu) { struct ibs_struct *ibs = hu->priv; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); skb_queue_purge(&ibs->tx_wait_q); skb_queue_purge(&ibs->txq); @@ -542,7 +542,7 @@ static void ibs_device_want_to_wakeup(struct hci_uart *hu) unsigned long flags; struct ibs_struct *ibs = hu->priv; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); /* lock hci_ibs state */ spin_lock_irqsave(&ibs->hci_ibs_lock, flags); @@ -591,7 +591,7 @@ static void ibs_device_want_to_sleep(struct hci_uart *hu) unsigned long flags; struct ibs_struct *ibs = hu->priv; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); /* lock hci_ibs state */ spin_lock_irqsave(&ibs->hci_ibs_lock, flags); @@ -627,7 +627,7 @@ static void ibs_device_woke_up(struct hci_uart *hu) struct ibs_struct *ibs = hu->priv; struct sk_buff *skb = NULL; - BT_DBG("hu %p", hu); + BT_DBG("hu %pK", hu); /* lock hci_ibs state */ spin_lock_irqsave(&ibs->hci_ibs_lock, flags); @@ -672,7 +672,7 @@ static int ibs_enqueue(struct hci_uart *hu, struct sk_buff *skb) unsigned long flags = 0; struct ibs_struct *ibs = hu->priv; - BT_DBG("hu %p skb %p", hu, skb); + BT_DBG("hu %pK skb %pK", hu, skb); /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); @@ -752,7 +752,7 @@ static int ibs_recv(struct hci_uart *hu, void *data, int count) struct hci_sco_hdr *sh; register int len, type, dlen; - BT_DBG("hu %p count %d rx_state %ld rx_count %ld", + BT_DBG("hu %pK count %d rx_state %ld rx_count %ld", hu, count, ibs->rx_state, ibs->rx_count); ptr = data; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index c3a244c46ebc..f78b6204d5f2 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -154,7 +154,7 @@ static void hci_uart_write_work(struct work_struct *work) struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; - BT_DBG("hu %p hdev %p tty %p", hu, hdev, tty); + BT_DBG("hu %pK hdev %pK tty %pK", hu, hdev, tty); /* REVISIT: should we cope with bad skbs or ->write() returning * and error value ? @@ -219,7 +219,7 @@ int hci_uart_init_ready(struct hci_uart *hu) /* Initialize device */ static int hci_uart_open(struct hci_dev *hdev) { - BT_DBG("%s %p", hdev->name, hdev); + BT_DBG("%s %pK", hdev->name, hdev); /* Nothing to do for UART driver */ @@ -234,7 +234,7 @@ static int hci_uart_flush(struct hci_dev *hdev) struct hci_uart *hu = hci_get_drvdata(hdev); struct tty_struct *tty = hu->tty; - BT_DBG("hdev %p tty %p", hdev, tty); + BT_DBG("hdev %pK tty %pK", hdev, tty); if (hu->tx_skb) { kfree_skb(hu->tx_skb); hu->tx_skb = NULL; @@ -253,7 +253,7 @@ static int hci_uart_flush(struct hci_dev *hdev) /* Close device */ static int hci_uart_close(struct hci_dev *hdev) { - BT_DBG("hdev %p", hdev); + BT_DBG("hdev %pK", hdev); if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; @@ -294,7 +294,7 @@ static int hci_uart_tty_open(struct tty_struct *tty) { struct hci_uart *hu; - BT_DBG("tty %p", tty); + BT_DBG("tty %pK", tty); /* Error if the tty has no write op instead of leaving an exploitable hole */ @@ -339,7 +339,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) struct hci_uart *hu = (void *)tty->disc_data; struct hci_dev *hdev; - BT_DBG("tty %p", tty); + BT_DBG("tty %pK", tty); /* Detach from the tty */ tty->disc_data = NULL; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 786fc3f620a0..34a47d04117d 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -184,7 +184,7 @@ EXPORT_SYMBOL(bt_sock_unlink); */ void bt_accept_enqueue(struct sock *parent, struct sock *sk) { - BT_DBG("parent %p, sk %p", parent, sk); + BT_DBG("parent %pK, sk %pK", parent, sk); sock_hold(sk); bt_sk(sk)->parent = parent; @@ -195,7 +195,7 @@ EXPORT_SYMBOL(bt_accept_enqueue); void bt_accept_unlink(struct sock *sk) { - BT_DBG("sk %p state %d", sk, sk->sk_state); + BT_DBG("sk %pK state %d", sk, sk->sk_state); if (!bt_sk(sk)->parent) return; @@ -214,7 +214,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) struct list_head *p, *n; struct sock *sk; - BT_DBG("parent %p", parent); + BT_DBG("parent %pK", parent); list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); @@ -247,7 +247,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, size_t copied; int err; - BT_DBG("sock %p sk %p len %zu", sock, sk, len); + BT_DBG("sock %pK sk %pK len %zu", sock, sk, len); if (flags & (MSG_OOB)) return -EOPNOTSUPP; @@ -322,7 +322,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & MSG_OOB) return -EOPNOTSUPP; - BT_DBG("sk %p size %zu", sk, size); + BT_DBG("sk %pK size %zu", sk, size); lock_sock(sk); @@ -438,7 +438,7 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk; unsigned int mask = 0; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); poll_wait(file, sk_sleep(sk), wait); @@ -482,7 +482,7 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) long amount; int err; - BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg); + BT_DBG("sk %pK cmd %x arg %lx", sk, cmd, arg); switch (cmd) { case TIOCOUTQ: @@ -529,7 +529,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) DECLARE_WAITQUEUE(wait, current); int err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); add_wait_queue(sk_sleep(sk), &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -566,7 +566,7 @@ int bt_sock_wait_ready(struct sock *sk, unsigned long flags) unsigned long timeo; int err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 85bcc21e84d2..ec2cf37c7c94 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -394,7 +394,7 @@ static int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb) int len = 0, il = 0; u8 type = 0; - BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type); + BT_DBG("skb %pK dev %pK type %d", skb, skb->dev, skb->pkt_type); if (!skb->dev) { /* Control frame sent by us */ diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 4b488ec26105..601b7b21ab58 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -156,7 +156,7 @@ static int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s) return 0; } - BT_DBG("BNEP: filtered skb %p, proto 0x%.4x", skb, proto); + BT_DBG("BNEP: filtered skb %pK, proto 0x%.4x", skb, proto); return 1; } #endif @@ -167,7 +167,7 @@ static netdev_tx_t bnep_net_xmit(struct sk_buff *skb, struct bnep_session *s = netdev_priv(dev); struct sock *sk = s->sock->sk; - BT_DBG("skb %p, dev %p", skb, dev); + BT_DBG("skb %pK, dev %pK", skb, dev); #ifdef CONFIG_BT_BNEP_MC_FILTER if (bnep_net_mc_filter(skb, s)) { diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5f051290daba..9340bf18063c 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -37,7 +37,7 @@ static int bnep_sock_release(struct socket *sock) { struct sock *sk = sock->sk; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (!sk) return 0; @@ -190,7 +190,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 1ca8a87a0787..c53e11ed7112 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c @@ -74,7 +74,7 @@ static struct cmtp_application *cmtp_application_add(struct cmtp_session *sessio { struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL); - BT_DBG("session %p application %p appl %d", session, app, appl); + BT_DBG("session %pK application %pK appl %d", session, app, appl); if (!app) return NULL; @@ -89,7 +89,7 @@ static struct cmtp_application *cmtp_application_add(struct cmtp_session *sessio static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app) { - BT_DBG("session %p application %p", session, app); + BT_DBG("session %pK application %pK", session, app); if (app) { list_del(&app->list); @@ -137,7 +137,7 @@ static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb) { struct cmtp_scb *scb = (void *) skb->cb; - BT_DBG("session %p skb %p len %d", session, skb, skb->len); + BT_DBG("session %pK skb %pK len %d", session, skb, skb->len); scb->id = -1; scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3); @@ -154,7 +154,8 @@ static void cmtp_send_interopmsg(struct cmtp_session *session, struct sk_buff *skb; unsigned char *s; - BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum); + BT_DBG("session %pK subcmd 0x%02x appl %d msgnum %d", + session, subcmd, appl, msgnum); skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC); if (!skb) { @@ -190,7 +191,7 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s __u16 appl, msgnum, func, info; __u32 controller; - BT_DBG("session %p skb %p len %d", session, skb, skb->len); + BT_DBG("session %pK skb %pK len %d", session, skb, skb->len); switch (CAPIMSG_SUBCOMMAND(skb->data)) { case CAPI_CONF: @@ -329,7 +330,7 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) __u16 appl; __u32 contr; - BT_DBG("session %p skb %p len %d", session, skb, skb->len); + BT_DBG("session %pK skb %pK len %d", session, skb, skb->len); if (skb->len < CAPI_MSG_BASELEN) return; @@ -367,7 +368,7 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) { - BT_DBG("ctrl %p data %p", ctrl, data); + BT_DBG("ctrl %pK data %pK", ctrl, data); return 0; } @@ -376,7 +377,7 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl) { struct cmtp_session *session = ctrl->driverdata; - BT_DBG("ctrl %p", ctrl); + BT_DBG("ctrl %pK", ctrl); capi_ctr_down(ctrl); @@ -393,8 +394,8 @@ static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_ unsigned char buf[8]; int err = 0, nconn, want = rp->level3cnt; - BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d", - ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); + BT_DBG("ctrl %pK appl %d level3cnt %d datablkcnt %d datablklen %d", + ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); application = cmtp_application_add(session, appl); if (!application) { @@ -458,7 +459,7 @@ static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl) struct cmtp_session *session = ctrl->driverdata; struct cmtp_application *application; - BT_DBG("ctrl %p appl %d", ctrl, appl); + BT_DBG("ctrl %pK appl %d", ctrl, appl); application = cmtp_application_get(session, CMTP_APPLID, appl); if (!application) { @@ -484,7 +485,7 @@ static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) __u16 appl; __u32 contr; - BT_DBG("ctrl %p skb %p", ctrl, skb); + BT_DBG("ctrl %pK skb %pK", ctrl, skb); appl = CAPIMSG_APPID(skb->data); contr = CAPIMSG_CONTROL(skb->data); @@ -549,7 +550,7 @@ int cmtp_attach_device(struct cmtp_session *session) unsigned char buf[4]; long ret; - BT_DBG("session %p", session); + BT_DBG("session %pK", session); capimsg_setu32(buf, 0, 0); @@ -591,7 +592,7 @@ int cmtp_attach_device(struct cmtp_session *session) session->num = session->ctrl.cnr; - BT_DBG("session %p num %d", session, session->num); + BT_DBG("session %pK num %d", session, session->num); capimsg_setu32(buf, 0, 1); @@ -612,7 +613,7 @@ int cmtp_attach_device(struct cmtp_session *session) void cmtp_detach_device(struct cmtp_session *session) { - BT_DBG("session %p", session); + BT_DBG("session %pK", session); detach_capi_ctr(&session->ctrl); } diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 67fe5e84e68f..1d1b5daede19 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -108,7 +108,7 @@ static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const struct sk_buff *skb = session->reassembly[id], *nskb; int size; - BT_DBG("session %p buf %p count %d", session, buf, count); + BT_DBG("session %pK buf %pK count %d", session, buf, count); size = (skb) ? skb->len + count : count; @@ -133,7 +133,7 @@ static inline int cmtp_recv_frame(struct cmtp_session *session, struct sk_buff * __u8 hdr, hdrlen, id; __u16 len; - BT_DBG("session %p skb %p len %d", session, skb, skb->len); + BT_DBG("session %pK skb %pK len %d", session, skb, skb->len); while (skb->len > 0) { hdr = skb->data[0]; @@ -196,7 +196,7 @@ static int cmtp_send_frame(struct cmtp_session *session, unsigned char *data, in struct kvec iv = { data, len }; struct msghdr msg; - BT_DBG("session %p data %p len %d", session, data, len); + BT_DBG("session %pK data %pK len %d", session, data, len); if (!len) return 0; @@ -212,7 +212,7 @@ static void cmtp_process_transmit(struct cmtp_session *session) unsigned char *hdr; unsigned int size, tail; - BT_DBG("session %p", session); + BT_DBG("session %pK", session); nskb = alloc_skb(session->mtu, GFP_ATOMIC); if (!nskb) { @@ -282,7 +282,7 @@ static int cmtp_session(void *arg) struct sk_buff *skb; wait_queue_t wait; - BT_DBG("session %p", session); + BT_DBG("session %pK", session); set_user_nice(current, -15); diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index d82787d417bd..8d7d3c16c8b6 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -50,7 +50,7 @@ static int cmtp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (!sk) return 0; @@ -200,7 +200,7 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index eab4ceedd933..c930923a94ba 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -69,7 +69,7 @@ static void hci_acl_create_connection(struct hci_conn *conn) struct inquiry_entry *ie; struct hci_cp_create_conn cp; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); conn->state = BT_CONNECT; conn->out = true; @@ -112,7 +112,7 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn) { struct hci_cp_create_conn_cancel cp; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2) return; @@ -135,7 +135,7 @@ int hci_disconnect(struct hci_conn *conn, __u8 reason) { struct hci_cp_disconnect cp; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); /* When we are master of an established connection and it enters * the disconnect timeout, then go ahead and try to read the @@ -161,7 +161,7 @@ static void hci_amp_disconn(struct hci_conn *conn) { struct hci_cp_disconn_phy_link cp; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); conn->state = BT_DISCONN; @@ -176,7 +176,7 @@ static void hci_add_sco(struct hci_conn *conn, __u16 handle) struct hci_dev *hdev = conn->hdev; struct hci_cp_add_sco cp; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); conn->state = BT_CONNECT; conn->out = true; @@ -195,7 +195,7 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) struct hci_cp_setup_sync_conn cp; const struct sco_param *param; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); conn->state = BT_CONNECT; conn->out = true; @@ -281,7 +281,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand, struct hci_dev *hdev = conn->hdev; struct hci_cp_le_start_enc cp; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); memset(&cp, 0, sizeof(cp)); @@ -301,7 +301,7 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) if (!sco) return; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (!status) { if (lmp_esco_capable(conn->hdev)) @@ -320,7 +320,7 @@ static void hci_conn_timeout(struct work_struct *work) disc_work.work); int refcnt = atomic_read(&conn->refcnt); - BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); + BT_DBG("hcon %pK state %s", conn, state_to_string(conn->state)); WARN_ON(refcnt < 0); @@ -368,7 +368,7 @@ static void hci_conn_idle(struct work_struct *work) idle_work.work); struct hci_dev *hdev = conn->hdev; - BT_DBG("hcon %p mode %d", conn, conn->mode); + BT_DBG("hcon %pK mode %d", conn, conn->mode); if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) return; @@ -507,7 +507,7 @@ int hci_conn_del(struct hci_conn *conn) struct hci_dev *hdev = conn->hdev; __u8 type; - BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); + BT_DBG("%s hcon %pK handle %d", hdev->name, conn, conn->handle); cancel_delayed_work_sync(&conn->disc_work); cancel_delayed_work_sync(&conn->auto_accept_work); @@ -921,7 +921,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, /* Check link security requirement */ int hci_conn_check_link_mode(struct hci_conn *conn) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); /* In Secure Connections Only mode, it is required that Secure * Connections is used and the link is encrypted with AES-CCM @@ -944,7 +944,7 @@ int hci_conn_check_link_mode(struct hci_conn *conn) /* Authenticate remote device */ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (conn->pending_sec_level > sec_level) sec_level = conn->pending_sec_level; @@ -981,7 +981,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) /* Encrypt the the link */ static void hci_conn_encrypt(struct hci_conn *conn) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { struct hci_cp_set_conn_encrypt cp; @@ -996,7 +996,7 @@ static void hci_conn_encrypt(struct hci_conn *conn) int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, bool initiator) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (conn->type == LE_LINK) return smp_conn_security(conn, sec_level); @@ -1065,7 +1065,7 @@ EXPORT_SYMBOL(hci_conn_security); /* Check secure link requirement */ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); /* Accept if non-secure or higher security level is required */ if (sec_level != BT_SECURITY_HIGH && sec_level != BT_SECURITY_FIPS) @@ -1084,7 +1084,7 @@ EXPORT_SYMBOL(hci_conn_check_secure); /* Change link key */ int hci_conn_change_link_key(struct hci_conn *conn) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { struct hci_cp_change_conn_link_key cp; @@ -1099,7 +1099,7 @@ int hci_conn_change_link_key(struct hci_conn *conn) /* Switch role */ int hci_conn_switch_role(struct hci_conn *conn, __u8 role) { - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); if (role == conn->role) return 1; @@ -1138,7 +1138,7 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) { struct hci_dev *hdev = conn->hdev; - BT_DBG("hcon %p mode %d", conn, conn->mode); + BT_DBG("hcon %pK mode %d", conn, conn->mode); if (conn->mode != HCI_CM_SNIFF) goto timer; @@ -1318,7 +1318,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) struct hci_dev *hdev = conn->hdev; struct hci_chan *chan; - BT_DBG("%s hcon %p", hdev->name, conn); + BT_DBG("%s hcon %pK", hdev->name, conn); if (test_bit(HCI_CONN_DROP, &conn->flags)) { BT_DBG("Refusing to create new hci_chan"); @@ -1343,7 +1343,7 @@ void hci_chan_del(struct hci_chan *chan) struct hci_conn *conn = chan->conn; struct hci_dev *hdev = conn->hdev; - BT_DBG("%s hcon %p chan %p", hdev->name, conn, chan); + BT_DBG("%s hcon %pK chan %pK", hdev->name, conn, chan); list_del_rcu(&chan->list); @@ -1362,7 +1362,7 @@ void hci_chan_list_flush(struct hci_conn *conn) { struct hci_chan *chan, *n; - BT_DBG("hcon %p", conn); + BT_DBG("hcon %pK", conn); list_for_each_entry_safe(chan, n, &conn->chan_list, list) hci_chan_del(chan); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 733a8d6f662f..ad481457a3b4 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2065,7 +2065,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, struct discovery_state *cache = &hdev->discovery; struct inquiry_entry *e; - BT_DBG("cache %p, %pMR", cache, bdaddr); + BT_DBG("cache %pK, %pMR", cache, bdaddr); list_for_each_entry(e, &cache->all, all) { if (!bacmp(&e->data.bdaddr, bdaddr)) @@ -2081,7 +2081,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev, struct discovery_state *cache = &hdev->discovery; struct inquiry_entry *e; - BT_DBG("cache %p, %pMR", cache, bdaddr); + BT_DBG("cache %pK, %pMR", cache, bdaddr); list_for_each_entry(e, &cache->unknown, list) { if (!bacmp(&e->data.bdaddr, bdaddr)) @@ -2098,7 +2098,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev, struct discovery_state *cache = &hdev->discovery; struct inquiry_entry *e; - BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state); + BT_DBG("cache %pK bdaddr %pMR state %d", cache, bdaddr, state); list_for_each_entry(e, &cache->resolve, list) { if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state) @@ -2136,7 +2136,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, struct inquiry_entry *ie; u32 flags = 0; - BT_DBG("cache %p, %pMR", cache, &data->bdaddr); + BT_DBG("cache %pK, %pMR", cache, &data->bdaddr); hci_remove_remote_oob_data(hdev, &data->bdaddr); @@ -2215,7 +2215,7 @@ static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) copied++; } - BT_DBG("cache %p, copied %d", cache, copied); + BT_DBG("cache %pK, copied %d", cache, copied); return copied; } @@ -2336,7 +2336,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) { int ret = 0; - BT_DBG("%s %p", hdev->name, hdev); + BT_DBG("%s %pK", hdev->name, hdev); hci_req_lock(hdev); @@ -2552,7 +2552,7 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) static int hci_dev_do_close(struct hci_dev *hdev) { - BT_DBG("%s %p", hdev->name, hdev); + BT_DBG("%s %pK", hdev->name, hdev); /* do not call cancel_delayed_work_sync for power_off here as * hci_dev_do_close function is called from work handler which might @@ -3002,7 +3002,7 @@ static int hci_rfkill_set_block(void *data, bool blocked) { struct hci_dev *hdev = data; - BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); + BT_DBG("%pK name %s blocked %d", hdev, hdev->name, blocked); if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) return -EBUSY; @@ -4087,7 +4087,7 @@ int hci_register_dev(struct hci_dev *hdev) sprintf(hdev->name, "hci%d", id); hdev->id = id; - BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); + BT_DBG("%pK name %s bus %d", hdev, hdev->name, hdev->bus); hdev->workqueue = alloc_workqueue("%s", WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1, hdev->name); @@ -4168,7 +4168,7 @@ void hci_unregister_dev(struct hci_dev *hdev) { int i, id; - BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); + BT_DBG("%pK name %s bus %d", hdev, hdev->name, hdev->bus); set_bit(HCI_UNREGISTER, &hdev->dev_flags); @@ -4421,7 +4421,7 @@ EXPORT_SYMBOL(hci_recv_stream_fragment); int hci_register_cb(struct hci_cb *cb) { - BT_DBG("%p name %s", cb, cb->name); + BT_DBG("%pK name %s", cb, cb->name); write_lock(&hci_cb_list_lock); list_add(&cb->list, &hci_cb_list); @@ -4433,7 +4433,7 @@ EXPORT_SYMBOL(hci_register_cb); int hci_unregister_cb(struct hci_cb *cb) { - BT_DBG("%p name %s", cb, cb->name); + BT_DBG("%pK name %s", cb, cb->name); write_lock(&hci_cb_list_lock); list_del(&cb->list); @@ -4660,12 +4660,12 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, list = skb_shinfo(skb)->frag_list; if (!list) { /* Non fragmented */ - BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); + BT_DBG("%s nonfrag skb %pK len %d", hdev->name, skb, skb->len); skb_queue_tail(queue, skb); } else { /* Fragmented */ - BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); + BT_DBG("%s frag %pK len %d", hdev->name, skb, skb->len); skb_shinfo(skb)->frag_list = NULL; @@ -4682,7 +4682,7 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; hci_add_acl_hdr(skb, conn->handle, flags); - BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); + BT_DBG("%s frag %pK len %d", hdev->name, skb, skb->len); __skb_queue_tail(queue, skb); } while (list); @@ -4695,7 +4695,7 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) { struct hci_dev *hdev = chan->conn->hdev; - BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); + BT_DBG("%s chan %pK flags 0x%4.4x", hdev->name, chan, flags); hci_queue_acl(chan, &chan->data_q, skb, flags); @@ -4782,7 +4782,7 @@ static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, } else *quote = 0; - BT_DBG("conn %p quote %d", conn, *quote); + BT_DBG("conn %pK quote %d", conn, *quote); return conn; } @@ -4885,7 +4885,7 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, q = cnt / num; *quote = q ? q : 1; - BT_DBG("chan %p quote %d", chan, *quote); + BT_DBG("chan %pK quote %d", chan, *quote); return chan; } @@ -4927,7 +4927,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) skb->priority = HCI_PRIO_MAX - 1; - BT_DBG("chan %p skb %p promoted to %d", chan, skb, + BT_DBG("chan %pK skb %pK promoted to %d", chan, skb, skb->priority); } @@ -4969,7 +4969,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev) (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { u32 priority = (skb_peek(&chan->data_q))->priority; while (quote-- && (skb = skb_peek(&chan->data_q))) { - BT_DBG("chan %p skb %p len %d priority %u", chan, skb, + BT_DBG("chan %pK skb %pK len %d priority %u", chan, skb, skb->len, skb->priority); /* Stop if priority has changed */ @@ -5017,7 +5017,7 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) while (quote > 0 && (skb = skb_peek(&chan->data_q))) { int blocks; - BT_DBG("chan %p skb %p len %d priority %u", chan, skb, + BT_DBG("chan %pK skb %pK len %d priority %u", chan, skb, skb->len, skb->priority); /* Stop if priority has changed */ @@ -5085,7 +5085,7 @@ static void hci_sched_sco(struct hci_dev *hdev) while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) { - BT_DBG("skb %p len %d", skb, skb->len); + BT_DBG("skb %pK len %d", skb, skb->len); hci_send_frame(hdev, skb); conn->sent++; @@ -5109,7 +5109,7 @@ static void hci_sched_esco(struct hci_dev *hdev) while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, "e))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) { - BT_DBG("skb %p len %d", skb, skb->len); + BT_DBG("skb %pK len %d", skb, skb->len); hci_send_frame(hdev, skb); conn->sent++; @@ -5143,7 +5143,7 @@ static void hci_sched_le(struct hci_dev *hdev) while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { u32 priority = (skb_peek(&chan->data_q))->priority; while (quote-- && (skb = skb_peek(&chan->data_q))) { - BT_DBG("chan %p skb %p len %d priority %u", chan, skb, + BT_DBG("chan %pK skb %pK len %d priority %u", chan, skb, skb->len, skb->priority); /* Stop if priority has changed */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0922f04872df..dad587e1240b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1406,7 +1406,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); - BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); + BT_DBG("%s bdaddr %pMR hcon %pK", hdev->name, &cp->bdaddr, conn); if (status) { if (conn && conn->state == BT_CONNECT) { @@ -3016,7 +3016,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) break; default: - BT_ERR("Unknown type %d conn %p", conn->type, conn); + BT_ERR("Unknown type %d conn %pK", conn->type, conn); break; } } @@ -3087,7 +3087,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) break; default: - BT_ERR("Unknown type %d conn %p", conn->type, conn); + BT_ERR("Unknown type %d conn %pK", conn->type, conn); break; } } @@ -4026,7 +4026,7 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev, return; } - BT_DBG("hcon %p mgr %p", hcon, hcon->amp_mgr); + BT_DBG("hcon %pK mgr %pK", hcon, hcon->amp_mgr); mgr = hcon->amp_mgr; if (!(mgr && mgr->l2cap_conn && mgr->l2cap_conn->hcon)) { @@ -4072,7 +4072,7 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hchan->handle = le16_to_cpu(ev->handle); - BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); + BT_DBG("hcon %pK mgr %pK hchan %pK", hcon, hcon->amp_mgr, hchan); mgr = hcon->amp_mgr; if (mgr && mgr->bredr_chan) { diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 115f149362ba..80732d33c5de 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -131,7 +131,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) struct sock *sk; struct sk_buff *skb_copy = NULL; - BT_DBG("hdev %p len %d", hdev, skb->len); + BT_DBG("hdev %pK len %d", hdev, skb->len); read_lock(&hci_sk_list.lock); @@ -226,7 +226,7 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) if (!atomic_read(&monitor_promisc)) return; - BT_DBG("hdev %p len %d", hdev, skb->len); + BT_DBG("hdev %pK len %d", hdev, skb->len); switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: @@ -458,7 +458,7 @@ static int hci_sock_release(struct socket *sock) struct sock *sk = sock->sk; struct hci_dev *hdev; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (!sk) return 0; @@ -649,7 +649,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, struct hci_dev *hdev = NULL; int len, err = 0; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (!addr) return -EINVAL; @@ -791,7 +791,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, struct hci_dev *hdev; int err = 0; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (peer) return -EOPNOTSUPP; @@ -859,7 +859,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; int copied, err; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (flags & (MSG_OOB)) return -EOPNOTSUPP; @@ -904,7 +904,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; int err; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; @@ -1023,7 +1023,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; int err = 0, opt = 0; - BT_DBG("sk %p, opt %d", sk, optname); + BT_DBG("sk %pK, opt %d", sk, optname); lock_sock(sk); @@ -1106,7 +1106,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; int len, opt, err = 0; - BT_DBG("sk %p, opt %d", sk, optname); + BT_DBG("sk %pK, opt %d", sk, optname); if (get_user(len, optlen)) return -EFAULT; @@ -1196,7 +1196,7 @@ static int hci_sock_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 555982a78a58..4f78b28686ff 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -77,7 +77,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); conn->dev.type = &bt_link; conn->dev.class = bt_class; @@ -90,7 +90,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 1b7d605706aa..a34ea5176978 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -100,7 +100,7 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock, struct sk_buff *skb; struct sock *sk = sock->sk; - BT_DBG("session %p data %p size %d", session, data, size); + BT_DBG("session %pK data %pK size %d", session, data, size); if (atomic_read(&session->terminate)) return -EIO; @@ -144,7 +144,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned char newleds; unsigned char hdr, data[2]; - BT_DBG("session %p type %d code %d value %d", + BT_DBG("session %pK type %d code %d value %d", session, type, code, value); if (type != EV_LED) @@ -428,7 +428,7 @@ static void hidp_process_report(struct hidp_session *session, static void hidp_process_handshake(struct hidp_session *session, unsigned char param) { - BT_DBG("session %p param 0x%02x", session, param); + BT_DBG("session %pK param 0x%02x", session, param); session->output_report_success = 0; /* default condition */ switch (param) { @@ -471,7 +471,7 @@ static void hidp_process_handshake(struct hidp_session *session, static void hidp_process_hid_control(struct hidp_session *session, unsigned char param) { - BT_DBG("session %p param 0x%02x", session, param); + BT_DBG("session %pK param 0x%02x", session, param); if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) { /* Flush the transmit queues */ @@ -487,7 +487,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param) { int done_with_skb = 1; - BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param); + BT_DBG("session %pK skb %pK len %d param 0x%02x", + session, skb, skb->len, param); switch (param) { case HIDP_DATA_RTYPE_INPUT: @@ -532,7 +533,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session, unsigned char hdr, type, param; int free_skb = 1; - BT_DBG("session %p skb %p len %d", session, skb, skb->len); + BT_DBG("session %pK skb %pK len %d", session, skb, skb->len); hdr = skb->data[0]; skb_pull(skb, 1); @@ -568,7 +569,7 @@ static void hidp_recv_intr_frame(struct hidp_session *session, { unsigned char hdr; - BT_DBG("session %p skb %p len %d", session, skb, skb->len); + BT_DBG("session %pK skb %pK len %d", session, skb, skb->len); hdr = skb->data[0]; skb_pull(skb, 1); @@ -596,7 +597,7 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len) struct kvec iv = { data, len }; struct msghdr msg; - BT_DBG("sock %p data %p len %d", sock, data, len); + BT_DBG("sock %pK data %pK len %d", sock, data, len); if (!len) return 0; @@ -614,7 +615,7 @@ static void hidp_process_transmit(struct hidp_session *session, struct sk_buff *skb; int ret; - BT_DBG("session %p", session); + BT_DBG("session %pK", session); while ((skb = skb_dequeue(transmit))) { ret = hidp_send_frame(sock, skb->data, skb->len); @@ -1234,7 +1235,7 @@ static int hidp_session_thread(void *arg) struct hidp_session *session = arg; wait_queue_t ctrl_wait, intr_wait; - BT_DBG("session %p", session); + BT_DBG("session %pK", session); /* initialize runtime environment */ hidp_session_get(session); diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index cb3fdde1968a..5b7abfad038b 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -33,7 +33,7 @@ static int hidp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; - BT_DBG("sock %p sk %p", sock, sk); + BT_DBG("sock %pK sk %pK", sock, sk); if (!sk) return 0; @@ -230,7 +230,7 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9da04224e5e9..281fcd2419e9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -240,7 +240,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) static void l2cap_state_change(struct l2cap_chan *chan, int state) { - BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), + BT_DBG("chan %pK %s -> %s", chan, state_to_string(chan->state), state_to_string(state)); chan->state = state; @@ -391,7 +391,7 @@ static void l2cap_chan_timeout(struct work_struct *work) struct l2cap_conn *conn = chan->conn; int reason; - BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); + BT_DBG("chan %pK state %s", chan, state_to_string(chan->state)); mutex_lock(&conn->chan_lock); l2cap_chan_lock(chan); @@ -437,7 +437,7 @@ struct l2cap_chan *l2cap_chan_create(void) /* This flag is cleared in l2cap_chan_ready() */ set_bit(CONF_NOT_COMPLETE, &chan->conf_state); - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); return chan; } @@ -447,7 +447,7 @@ static void l2cap_chan_destroy(struct kref *kref) { struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); write_lock(&chan_list_lock); list_del(&chan->global_l); @@ -458,14 +458,14 @@ static void l2cap_chan_destroy(struct kref *kref) void l2cap_chan_hold(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); + BT_DBG("chan %pK orig refcnt %d", c, atomic_read(&c->kref.refcount)); kref_get(&c->kref); } void l2cap_chan_put(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); + BT_DBG("chan %pK orig refcnt %d", c, atomic_read(&c->kref.refcount)); kref_put(&c->kref, l2cap_chan_destroy); } @@ -504,7 +504,7 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan) void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { - BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, + BT_DBG("conn %pK, psm 0x%2.2x, dcid 0x%4.4x", conn, __le16_to_cpu(chan->psm), chan->dcid); conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; @@ -567,7 +567,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) __clear_chan_timer(chan); - BT_DBG("chan %p, conn %p, err %d", chan, conn, err); + BT_DBG("chan %pK, conn %pK, err %d", chan, conn, err); chan->ops->teardown(chan, err); @@ -595,7 +595,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) if (chan->hs_hchan) { struct hci_chan *hs_hchan = chan->hs_hchan; - BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan); + BT_DBG("chan %pK disconnect hs_hchan %pK", chan, hs_hchan); amp_disconnect_logical_link(hs_hchan); } @@ -698,7 +698,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) { struct l2cap_conn *conn = chan->conn; - BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); + BT_DBG("chan %pK state %s", chan, state_to_string(chan->state)); switch (chan->state) { case BT_LISTEN: @@ -858,7 +858,7 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) struct hci_conn *hcon = chan->conn->hcon; u16 flags; - BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, + BT_DBG("chan %pK, skb %pK len %d priority %u", chan, skb, skb->len, skb->priority); if (chan->hs_hcon && !__chan_is_moving(chan)) { @@ -1040,7 +1040,7 @@ static void l2cap_send_sframe(struct l2cap_chan *chan, struct sk_buff *skb; u32 control_field; - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); if (!control->sframe) return; @@ -1079,7 +1079,7 @@ static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll) { struct l2cap_ctrl control; - BT_DBG("chan %p, poll %d", chan, poll); + BT_DBG("chan %pK, poll %d", chan, poll); memset(&control, 0, sizeof(control)); control.sframe = 1; @@ -1168,7 +1168,7 @@ static void l2cap_move_setup(struct l2cap_chan *chan) { struct sk_buff *skb; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (chan->mode != L2CAP_MODE_ERTM) return; @@ -1202,7 +1202,7 @@ static void l2cap_move_setup(struct l2cap_chan *chan) static void l2cap_move_done(struct l2cap_chan *chan) { u8 move_role = chan->move_role; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); chan->move_state = L2CAP_MOVE_STABLE; chan->move_role = L2CAP_MOVE_ROLE_NONE; @@ -1274,7 +1274,7 @@ static void l2cap_le_start(struct l2cap_chan *chan) static void l2cap_start_connection(struct l2cap_chan *chan) { if (__amp_capable(chan)) { - BT_DBG("chan %p AMP capable: discover AMPs", chan); + BT_DBG("chan %pK AMP capable: discover AMPs", chan); a2mp_discover_amp(chan); } else if (chan->conn->hcon->type == LE_LINK) { l2cap_le_start(chan); @@ -1371,7 +1371,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) { struct l2cap_chan *chan, *tmp; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); mutex_lock(&conn->chan_lock); @@ -1449,7 +1449,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) struct hci_conn *hcon = conn->hcon; struct hci_dev *hdev = hcon->hdev; - BT_DBG("%s conn %p", hdev->name, conn); + BT_DBG("%s conn %pK", hdev->name, conn); /* For outgoing pairing which doesn't necessarily have an * associated socket (e.g. mgmt_pair_device). @@ -1482,7 +1482,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) struct l2cap_chan *chan; struct hci_conn *hcon = conn->hcon; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (hcon->type == ACL_LINK) l2cap_request_info(conn); @@ -1523,7 +1523,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) { struct l2cap_chan *chan; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); mutex_lock(&conn->chan_lock); @@ -1637,7 +1637,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) if (!conn) return; - BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); + BT_DBG("hcon %pK conn %pK, err %d", hcon, conn, err); kfree_skb(conn->rx_skb); @@ -1765,7 +1765,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) struct l2cap_chan *chan = container_of(work, struct l2cap_chan, monitor_timer.work); - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); l2cap_chan_lock(chan); @@ -1786,7 +1786,7 @@ static void l2cap_retrans_timeout(struct work_struct *work) struct l2cap_chan *chan = container_of(work, struct l2cap_chan, retrans_timer.work); - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); l2cap_chan_lock(chan); @@ -1807,7 +1807,7 @@ static void l2cap_streaming_send(struct l2cap_chan *chan, struct sk_buff *skb; struct l2cap_ctrl *control; - BT_DBG("chan %p, skbs %p", chan, skbs); + BT_DBG("chan %pK, skbs %pK", chan, skbs); if (__chan_is_moving(chan)) return; @@ -1846,7 +1846,7 @@ static int l2cap_ertm_send(struct l2cap_chan *chan) struct l2cap_ctrl *control; int sent = 0; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (chan->state != BT_CONNECTED) return -ENOTCONN; @@ -1917,7 +1917,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) struct sk_buff *tx_skb; u16 seq; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) return; @@ -1994,7 +1994,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) static void l2cap_retransmit(struct l2cap_chan *chan, struct l2cap_ctrl *control) { - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); l2cap_seq_list_append(&chan->retrans_list, control->reqseq); l2cap_ertm_resend(chan); @@ -2005,7 +2005,7 @@ static void l2cap_retransmit_all(struct l2cap_chan *chan, { struct sk_buff *skb; - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); if (control->poll) set_bit(CONN_SEND_FBIT, &chan->conn_state); @@ -2041,7 +2041,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan) chan->last_acked_seq); int threshold; - BT_DBG("chan %p last_acked_seq %d buffer_seq %d", + BT_DBG("chan %pK last_acked_seq %d buffer_seq %d", chan, chan->last_acked_seq, chan->buffer_seq); memset(&control, 0, sizeof(control)); @@ -2137,7 +2137,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; struct l2cap_hdr *lh; - BT_DBG("chan %p psm 0x%2.2x len %zu", chan, + BT_DBG("chan %pK psm 0x%2.2x len %zu", chan, __le16_to_cpu(chan->psm), len); count = min_t(unsigned int, (conn->mtu - hlen), len); @@ -2169,7 +2169,7 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, int err, count; struct l2cap_hdr *lh; - BT_DBG("chan %p len %zu", chan, len); + BT_DBG("chan %pK len %zu", chan, len); count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); @@ -2200,7 +2200,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, int err, count, hlen; struct l2cap_hdr *lh; - BT_DBG("chan %p len %zu", chan, len); + BT_DBG("chan %pK len %zu", chan, len); if (!conn) return ERR_PTR(-ENOTCONN); @@ -2254,7 +2254,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, size_t pdu_len; u8 sar; - BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); + BT_DBG("chan %pK, msg %pK, len %zu", chan, msg, len); /* It is critical that ERTM PDUs fit in a single HCI fragment, * so fragmented skbs are not used. The HCI layer's handling @@ -2321,7 +2321,7 @@ static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, int err, count, hlen; struct l2cap_hdr *lh; - BT_DBG("chan %p len %zu", chan, len); + BT_DBG("chan %pK len %zu", chan, len); if (!conn) return ERR_PTR(-ENOTCONN); @@ -2363,7 +2363,7 @@ static int l2cap_segment_le_sdu(struct l2cap_chan *chan, size_t pdu_len; u16 sdu_len; - BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); + BT_DBG("chan %pK, msg %pK, len %zu", chan, msg, len); sdu_len = len; pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; @@ -2529,7 +2529,7 @@ static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) struct l2cap_ctrl control; u16 seq; - BT_DBG("chan %p, txseq %u", chan, txseq); + BT_DBG("chan %pK, txseq %u", chan, txseq); memset(&control, 0, sizeof(control)); control.sframe = 1; @@ -2551,7 +2551,7 @@ static void l2cap_send_srej_tail(struct l2cap_chan *chan) { struct l2cap_ctrl control; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR) return; @@ -2569,7 +2569,7 @@ static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq) u16 initial_head; u16 seq; - BT_DBG("chan %p, txseq %u", chan, txseq); + BT_DBG("chan %pK, txseq %u", chan, txseq); memset(&control, 0, sizeof(control)); control.sframe = 1; @@ -2594,7 +2594,7 @@ static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) struct sk_buff *acked_skb; u16 ackseq; - BT_DBG("chan %p, reqseq %u", chan, reqseq); + BT_DBG("chan %pK, reqseq %u", chan, reqseq); if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq) return; @@ -2623,7 +2623,7 @@ static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq) static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan) { - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); chan->expected_tx_seq = chan->buffer_seq; l2cap_seq_list_clear(&chan->srej_list); @@ -2635,7 +2635,7 @@ static void l2cap_tx_state_xmit(struct l2cap_chan *chan, struct l2cap_ctrl *control, struct sk_buff_head *skbs, u8 event) { - BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, + BT_DBG("chan %pK, control %pK, skbs %pK, event %d", chan, control, skbs, event); switch (event) { @@ -2707,7 +2707,7 @@ static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, struct l2cap_ctrl *control, struct sk_buff_head *skbs, u8 event) { - BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs, + BT_DBG("chan %pK, control %pK, skbs %pK, event %d", chan, control, skbs, event); switch (event) { @@ -2784,7 +2784,7 @@ static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, struct sk_buff_head *skbs, u8 event) { - BT_DBG("chan %p, control %p, skbs %p, event %d, state %d", + BT_DBG("chan %pK, control %pK, skbs %pK, event %d, state %d", chan, control, skbs, event, chan->tx_state); switch (chan->tx_state) { @@ -2803,14 +2803,14 @@ static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, static void l2cap_pass_to_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control) { - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT); } static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, struct l2cap_ctrl *control) { - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT); } @@ -2820,7 +2820,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) struct sk_buff *nskb; struct l2cap_chan *chan; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); mutex_lock(&conn->chan_lock); @@ -2851,7 +2851,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, struct l2cap_hdr *lh; int len, count; - BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", + BT_DBG("conn %pK, code 0x%2.2x, ident 0x%2.2x, len %u", conn, code, ident, dlen); if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) @@ -3010,7 +3010,7 @@ static void l2cap_ack_timeout(struct work_struct *work) ack_timer.work); u16 frames_to_ack; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); l2cap_chan_lock(chan); @@ -3152,7 +3152,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) void *ptr = req->data; u16 size; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (chan->num_conf_req || chan->num_conf_rsp) goto done; @@ -3281,7 +3281,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) u16 result = L2CAP_CONF_SUCCESS; u16 size; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&req, &type, &olen, &val); @@ -3490,7 +3490,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; struct l2cap_conf_efs efs; - BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); + BT_DBG("chan %pK, rsp %pK, len %d, req %pK", chan, rsp, len, data); while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); @@ -3595,7 +3595,7 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); rsp->scid = cpu_to_le16(chan->dcid); rsp->result = cpu_to_le16(result); @@ -3609,7 +3609,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) struct l2cap_le_conn_rsp rsp; struct l2cap_conn *conn = chan->conn; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); rsp.dcid = cpu_to_le16(chan->scid); rsp.mtu = cpu_to_le16(chan->imtu); @@ -3640,7 +3640,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) l2cap_chan_check_security(chan, false); - BT_DBG("chan %p rsp_code %u", chan, rsp_code); + BT_DBG("chan %pK rsp_code %u", chan, rsp_code); l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp); @@ -3668,7 +3668,7 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), }; - BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); + BT_DBG("chan %pK, rsp %pK, len %d", chan, rsp, len); if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) return; @@ -3973,7 +3973,7 @@ static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, { struct l2cap_conn *conn = chan->conn; - BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, + BT_DBG("conn %pK chan %pK ident %d flags 0x%4.4x", conn, chan, ident, flags); clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); @@ -4474,7 +4474,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, return 0; } - BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); + BT_DBG("mgr %pK bredr_chan %pK hs_hcon %pK", + mgr, chan, hs_hcon); mgr->bredr_chan = chan; chan->hs_hcon = hs_hcon; @@ -4503,7 +4504,7 @@ static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) struct l2cap_move_chan_req req; u8 ident; - BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id); + BT_DBG("chan %pK, dest_amp_id %d", chan, dest_amp_id); ident = l2cap_get_ident(chan->conn); chan->ident = ident; @@ -4521,7 +4522,7 @@ static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result) { struct l2cap_move_chan_rsp rsp; - BT_DBG("chan %p, result 0x%4.4x", chan, result); + BT_DBG("chan %pK, result 0x%4.4x", chan, result); rsp.icid = cpu_to_le16(chan->dcid); rsp.result = cpu_to_le16(result); @@ -4534,7 +4535,7 @@ static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result) { struct l2cap_move_chan_cfm cfm; - BT_DBG("chan %p, result 0x%4.4x", chan, result); + BT_DBG("chan %pK, result 0x%4.4x", chan, result); chan->ident = l2cap_get_ident(chan->conn); @@ -4551,7 +4552,7 @@ static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) { struct l2cap_move_chan_cfm cfm; - BT_DBG("conn %p, icid 0x%4.4x", conn, icid); + BT_DBG("conn %pK, icid 0x%4.4x", conn, icid); cfm.icid = cpu_to_le16(icid); cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); @@ -4671,7 +4672,7 @@ static void l2cap_logical_finish_move(struct l2cap_chan *chan, void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, u8 status) { - BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status); + BT_DBG("chan %pK, hchan %pK, status %d", chan, hchan, status); if (status) { l2cap_logical_fail(chan); @@ -4690,7 +4691,7 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, void l2cap_move_start(struct l2cap_chan *chan) { - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (chan->local_amp_id == AMP_ID_BREDR) { if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) @@ -4710,7 +4711,7 @@ void l2cap_move_start(struct l2cap_chan *chan) static void l2cap_do_create(struct l2cap_chan *chan, int result, u8 local_amp_id, u8 remote_amp_id) { - BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), + BT_DBG("chan %pK state %s %u -> %u", chan, state_to_string(chan->state), local_amp_id, remote_amp_id); chan->fcs = L2CAP_FCS_NONE; @@ -4819,7 +4820,7 @@ void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) u8 local_amp_id = chan->local_amp_id; u8 remote_amp_id = chan->remote_amp_id; - BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", + BT_DBG("chan %pK, result %d, local_amp_id %d, remote_amp_id %d", chan, result, local_amp_id, remote_amp_id); if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { @@ -5705,7 +5706,7 @@ static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) { struct l2cap_ctrl control; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); memset(&control, 0, sizeof(control)); control.sframe = 1; @@ -5860,7 +5861,7 @@ static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) * until a gap is encountered. */ - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { struct sk_buff *skb; @@ -5892,7 +5893,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan, { struct sk_buff *skb; - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); if (control->reqseq == chan->next_tx_seq) { BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); @@ -5950,7 +5951,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan, { struct sk_buff *skb; - BT_DBG("chan %p, control %p", chan, control); + BT_DBG("chan %pK, control %pK", chan, control); if (control->reqseq == chan->next_tx_seq) { BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); @@ -5984,7 +5985,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan, static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) { - BT_DBG("chan %p, txseq %d", chan, txseq); + BT_DBG("chan %pK, txseq %d", chan, txseq); BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq, chan->expected_tx_seq); @@ -6075,7 +6076,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, int err = 0; bool skb_in_use = false; - BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, + BT_DBG("chan %pK, control %pK, skb %pK, event %d", chan, control, skb, event); switch (event) { @@ -6131,7 +6132,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, */ skb_queue_tail(&chan->srej_q, skb); skb_in_use = true; - BT_DBG("Queued %p (queue len %d)", skb, + BT_DBG("Queued %pK (queue len %d)", skb, skb_queue_len(&chan->srej_q)); clear_bit(CONN_SREJ_ACT, &chan->conn_state); @@ -6195,7 +6196,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, } if (skb && !skb_in_use) { - BT_DBG("Freeing %p", skb); + BT_DBG("Freeing %pK", skb); kfree_skb(skb); } @@ -6210,7 +6211,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, u16 txseq = control->txseq; bool skb_in_use = false; - BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, + BT_DBG("chan %pK, control %pK, skb %pK, event %d", chan, control, skb, event); switch (event) { @@ -6221,7 +6222,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, l2cap_pass_to_tx(chan, control); skb_queue_tail(&chan->srej_q, skb); skb_in_use = true; - BT_DBG("Queued %p (queue len %d)", skb, + BT_DBG("Queued %pK (queue len %d)", skb, skb_queue_len(&chan->srej_q)); chan->expected_tx_seq = __next_seq(chan, txseq); @@ -6232,7 +6233,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, l2cap_pass_to_tx(chan, control); skb_queue_tail(&chan->srej_q, skb); skb_in_use = true; - BT_DBG("Queued %p (queue len %d)", skb, + BT_DBG("Queued %pK (queue len %d)", skb, skb_queue_len(&chan->srej_q)); err = l2cap_rx_queued_iframes(chan); @@ -6247,7 +6248,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, */ skb_queue_tail(&chan->srej_q, skb); skb_in_use = true; - BT_DBG("Queued %p (queue len %d)", skb, + BT_DBG("Queued %pK (queue len %d)", skb, skb_queue_len(&chan->srej_q)); l2cap_pass_to_tx(chan, control); @@ -6261,7 +6262,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, */ skb_queue_tail(&chan->srej_q, skb); skb_in_use = true; - BT_DBG("Queued %p (queue len %d)", skb, + BT_DBG("Queued %pK (queue len %d)", skb, skb_queue_len(&chan->srej_q)); l2cap_pass_to_tx(chan, control); @@ -6338,7 +6339,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, } if (skb && !skb_in_use) { - BT_DBG("Freeing %p", skb); + BT_DBG("Freeing %pK", skb); kfree_skb(skb); } @@ -6347,7 +6348,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, static int l2cap_finish_move(struct l2cap_chan *chan) { - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); chan->rx_state = L2CAP_RX_STATE_RECV; @@ -6365,7 +6366,7 @@ static int l2cap_rx_state_wait_p(struct l2cap_chan *chan, { int err; - BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb, + BT_DBG("chan %pK, control %pK, skb %pK, event %d", chan, control, skb, event); if (!control->poll) @@ -6449,7 +6450,7 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, { int err = 0; - BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan, + BT_DBG("chan %pK, control %pK, skb %pK, event %d, state %d", chan, control, skb, event, chan->rx_state); if (__valid_reqseq(chan, control->reqseq)) { @@ -6486,7 +6487,7 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, { int err = 0; - BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, + BT_DBG("chan %pK, control %pK, skb %pK, state %d", chan, control, skb, chan->rx_state); if (l2cap_classify_txseq(chan, control->txseq) == @@ -6508,7 +6509,7 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, chan->sdu_len = 0; if (skb) { - BT_DBG("Freeing %p", skb); + BT_DBG("Freeing %pK", skb); kfree_skb(skb); } } @@ -6621,7 +6622,7 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) return_credits = le_max_credits - chan->rx_credits; - BT_DBG("chan %p returning %u credits to sender", chan, return_credits); + BT_DBG("chan %pK returning %u credits to sender", chan, return_credits); chan->rx_credits += return_credits; @@ -6746,7 +6747,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, } } - BT_DBG("chan %p, len %d", chan, skb->len); + BT_DBG("chan %pK, len %d", chan, skb->len); if (chan->state != BT_CONNECTED) goto drop; @@ -6779,7 +6780,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, goto done; default: - BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); + BT_DBG("chan %pK: bad mode 0x%2.2x", chan, chan->mode); break; } @@ -6804,7 +6805,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, if (!chan) goto free_skb; - BT_DBG("chan %p, len %d", chan, skb->len); + BT_DBG("chan %pK, len %d", chan, skb->len); if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) goto drop; @@ -6917,7 +6918,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) conn->hcon = hci_conn_get(hcon); conn->hchan = hchan; - BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); + BT_DBG("hcon %pK conn %pK hchan %pK", hcon, conn, hchan); switch (hcon->type) { case LE_LINK: @@ -7201,7 +7202,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) struct l2cap_chan *pchan; u8 dst_type; - BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); + BT_DBG("hcon %pK bdaddr %pMR status %d", hcon, &hcon->dst, status); if (status) { l2cap_conn_del(hcon, bt_to_errno(status)); @@ -7257,7 +7258,7 @@ int l2cap_disconn_ind(struct hci_conn *hcon) { struct l2cap_conn *conn = hcon->l2cap_data; - BT_DBG("hcon %p", hcon); + BT_DBG("hcon %pK", hcon); if (!conn) return HCI_ERROR_REMOTE_USER_TERM; @@ -7266,7 +7267,7 @@ int l2cap_disconn_ind(struct hci_conn *hcon) void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) { - BT_DBG("hcon %p reason %d", hcon, reason); + BT_DBG("hcon %pK reason %d", hcon, reason); l2cap_conn_del(hcon, bt_to_errno(reason)); } @@ -7296,14 +7297,14 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (!conn) return 0; - BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt); + BT_DBG("conn %pK status 0x%2.2x encrypt %u", conn, status, encrypt); mutex_lock(&conn->chan_lock); list_for_each_entry(chan, &conn->chan_l, list) { l2cap_chan_lock(chan); - BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, + BT_DBG("chan %pK scid 0x%4.4x state %s", chan, chan->scid, state_to_string(chan->state)); if (chan->scid == L2CAP_CID_A2MP) { @@ -7396,7 +7397,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) if (!conn) goto drop; - BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); + BT_DBG("conn %pK len %d flags 0x%x", conn, skb->len, flags); switch (flags) { case ACL_START: diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 86212c20af9d..1389bdec055a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -84,7 +84,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) struct sockaddr_l2 la; int len, err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (!addr || addr->sa_family != AF_BLUETOOTH) return -EINVAL; @@ -178,7 +178,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, struct sockaddr_l2 la; int len, err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (!addr || alen < sizeof(addr->sa_family) || addr->sa_family != AF_BLUETOOTH) @@ -254,7 +254,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) struct l2cap_chan *chan = l2cap_pi(sk)->chan; int err = 0; - BT_DBG("sk %p backlog %d", sk, backlog); + BT_DBG("sk %pK backlog %d", sk, backlog); lock_sock(sk); @@ -305,7 +305,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); - BT_DBG("sk %p timeo %ld", sk, timeo); + BT_DBG("sk %pK timeo %ld", sk, timeo); /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk_sleep(sk), &wait); @@ -343,7 +343,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, newsock->state = SS_CONNECTED; - BT_DBG("new socket %p", nsk); + BT_DBG("new socket %pK", nsk); done: release_sock(sk); @@ -357,7 +357,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, struct sock *sk = sock->sk; struct l2cap_chan *chan = l2cap_pi(sk)->chan; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (peer && sk->sk_state != BT_CONNECTED && sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2 && @@ -393,7 +393,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, int len, err = 0; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (get_user(len, optlen)) return -EFAULT; @@ -495,7 +495,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, struct bt_power pwr; int len, err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (level == SOL_L2CAP) return l2cap_sock_getsockopt_old(sock, optname, optval, optlen); @@ -631,7 +631,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, int len, err = 0; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); lock_sock(sk); @@ -745,7 +745,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, int len, err = 0; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (level == SOL_L2CAP) return l2cap_sock_setsockopt_old(sock, optname, optval, optlen); @@ -946,7 +946,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct l2cap_chan *chan = l2cap_pi(sk)->chan; int err; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); err = sock_error(sk); if (err) @@ -1040,7 +1040,7 @@ static void l2cap_sock_kill(struct sock *sk) if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) return; - BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state)); + BT_DBG("sk %pK state %s", sk, state_to_string(sk->sk_state)); /* Kill poor orphan */ @@ -1111,7 +1111,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) struct l2cap_conn *conn; int err = 0; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (!sk) return 0; @@ -1169,7 +1169,7 @@ static int l2cap_sock_release(struct socket *sock) struct sock *sk = sock->sk; int err; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (!sk) return 0; @@ -1187,7 +1187,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent) { struct sock *sk; - BT_DBG("parent %p", parent); + BT_DBG("parent %pK", parent); /* Close not yet accepted channels */ while ((sk = bt_accept_dequeue(parent, NULL))) { @@ -1368,7 +1368,7 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) parent = bt_sk(sk)->parent; - BT_DBG("sk %p, parent %p", sk, parent); + BT_DBG("sk %pK, parent %pK", sk, parent); sk->sk_state = BT_CONNECTED; sk->sk_state_change(sk); @@ -1448,7 +1448,7 @@ static const struct l2cap_ops l2cap_chan_ops = { static void l2cap_sock_destruct(struct sock *sk) { - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (l2cap_pi(sk)->chan) l2cap_chan_put(l2cap_pi(sk)->chan); @@ -1479,7 +1479,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) { struct l2cap_chan *chan = l2cap_pi(sk)->chan; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (parent) { struct l2cap_chan *pchan = l2cap_pi(parent)->chan; @@ -1586,7 +1586,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); sock->state = SS_UNCONNECTED; diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index b36bc0415854..dc5b753d47b9 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -145,7 +145,7 @@ void bt_info(const char *format, ...) vaf.fmt = format; vaf.va = &args; - pr_info("%pV", &vaf); + pr_info("%pKV", &vaf); va_end(args); } @@ -161,7 +161,7 @@ void bt_err(const char *format, ...) vaf.fmt = format; vaf.va = &args; - pr_err("%pV", &vaf); + pr_err("%pKV", &vaf); va_end(args); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index efb71b022ab6..bb41fd1f0d21 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -248,7 +248,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) struct mgmt_ev_cmd_status *ev; int err; - BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status); + BT_DBG("sock %pK, index %u, cmd %u, status %u", sk, index, cmd, status); skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL); if (!skb) @@ -279,7 +279,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, struct mgmt_ev_cmd_complete *ev; int err; - BT_DBG("sock %p", sk); + BT_DBG("sock %pK", sk); skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL); if (!skb) @@ -310,7 +310,7 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data, { struct mgmt_rp_read_version rp; - BT_DBG("sock %p", sk); + BT_DBG("sock %pK", sk); rp.version = MGMT_VERSION; rp.revision = cpu_to_le16(MGMT_REVISION); @@ -329,7 +329,7 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data, size_t rp_size; int i, err; - BT_DBG("sock %p", sk); + BT_DBG("sock %pK", sk); rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16)); @@ -362,7 +362,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, u16 count; int err; - BT_DBG("sock %p", sk); + BT_DBG("sock %pK", sk); read_lock(&hci_dev_list_lock); @@ -422,7 +422,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, u16 count; int err; - BT_DBG("sock %p", sk); + BT_DBG("sock %pK", sk); read_lock(&hci_dev_list_lock); @@ -523,7 +523,7 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev, struct mgmt_rp_read_config_info rp; u32 options = 0; - BT_DBG("sock %p %s", sk, hdev->name); + BT_DBG("sock %pK %s", sk, hdev->name); hci_dev_lock(hdev); @@ -1157,7 +1157,7 @@ static int read_controller_info(struct sock *sk, struct hci_dev *hdev, { struct mgmt_rp_read_info rp; - BT_DBG("sock %p %s", sk, hdev->name); + BT_DBG("sock %pK %s", sk, hdev->name); hci_dev_lock(hdev); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index af73bc3acb40..955ec192a033 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -182,13 +182,13 @@ static inline int __check_fcs(u8 *data, int type, u8 fcs) /* ---- L2CAP callbacks ---- */ static void rfcomm_l2state_change(struct sock *sk) { - BT_DBG("%p state %d", sk, sk->sk_state); + BT_DBG("%pK state %d", sk, sk->sk_state); rfcomm_schedule(); } static void rfcomm_l2data_ready(struct sock *sk) { - BT_DBG("%p", sk); + BT_DBG("%pK", sk); rfcomm_schedule(); } @@ -235,7 +235,7 @@ static void rfcomm_session_timeout(unsigned long arg) { struct rfcomm_session *s = (void *) arg; - BT_DBG("session %p state %ld", s, s->state); + BT_DBG("session %pK state %ld", s, s->state); set_bit(RFCOMM_TIMED_OUT, &s->flags); rfcomm_schedule(); @@ -243,14 +243,14 @@ static void rfcomm_session_timeout(unsigned long arg) static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout) { - BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout); + BT_DBG("session %pK state %ld timeout %ld", s, s->state, timeout); mod_timer(&s->timer, jiffies + timeout); } static void rfcomm_session_clear_timer(struct rfcomm_session *s) { - BT_DBG("session %p state %ld", s, s->state); + BT_DBG("session %pK state %ld", s, s->state); del_timer_sync(&s->timer); } @@ -260,7 +260,7 @@ static void rfcomm_dlc_timeout(unsigned long arg) { struct rfcomm_dlc *d = (void *) arg; - BT_DBG("dlc %p state %ld", d, d->state); + BT_DBG("dlc %pK state %ld", d, d->state); set_bit(RFCOMM_TIMED_OUT, &d->flags); rfcomm_dlc_put(d); @@ -269,7 +269,7 @@ static void rfcomm_dlc_timeout(unsigned long arg) static void rfcomm_dlc_set_timer(struct rfcomm_dlc *d, long timeout) { - BT_DBG("dlc %p state %ld timeout %ld", d, d->state, timeout); + BT_DBG("dlc %pK state %ld timeout %ld", d, d->state, timeout); if (!mod_timer(&d->timer, jiffies + timeout)) rfcomm_dlc_hold(d); @@ -277,7 +277,7 @@ static void rfcomm_dlc_set_timer(struct rfcomm_dlc *d, long timeout) static void rfcomm_dlc_clear_timer(struct rfcomm_dlc *d) { - BT_DBG("dlc %p state %ld", d, d->state); + BT_DBG("dlc %pK state %ld", d, d->state); if (del_timer(&d->timer)) rfcomm_dlc_put(d); @@ -285,7 +285,7 @@ static void rfcomm_dlc_clear_timer(struct rfcomm_dlc *d) static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d) { - BT_DBG("%p", d); + BT_DBG("%pK", d); d->state = BT_OPEN; d->flags = 0; @@ -313,14 +313,14 @@ struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio) rfcomm_dlc_clear_state(d); - BT_DBG("%p", d); + BT_DBG("%pK", d); return d; } void rfcomm_dlc_free(struct rfcomm_dlc *d) { - BT_DBG("%p", d); + BT_DBG("%pK", d); skb_queue_purge(&d->tx_queue); kfree(d); @@ -328,7 +328,7 @@ void rfcomm_dlc_free(struct rfcomm_dlc *d) static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d) { - BT_DBG("dlc %p session %p", d, s); + BT_DBG("dlc %pK session %pK", d, s); rfcomm_session_clear_timer(s); rfcomm_dlc_hold(d); @@ -340,7 +340,7 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d) { struct rfcomm_session *s = d->session; - BT_DBG("dlc %p refcnt %d session %p", d, atomic_read(&d->refcnt), s); + BT_DBG("dlc %pK refcnt %d session %pK", d, atomic_read(&d->refcnt), s); list_del(&d->list); d->session = NULL; @@ -372,7 +372,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, int err = 0; u8 dlci; - BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", + BT_DBG("dlc %pK state %ld %pMR -> %pMR channel %d", d, d->state, src, dst, channel); if (rfcomm_check_channel(channel)) @@ -452,8 +452,8 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) if (!s) return 0; - BT_DBG("dlc %p state %ld dlci %d err %d session %p", - d, d->state, d->dlci, err, s); + BT_DBG("dlc %pK state %ld dlci %d err %d session %pK", + d, d->state, d->dlci, err, s); switch (d->state) { case BT_CONNECT: @@ -503,7 +503,7 @@ int rfcomm_dlc_close(struct rfcomm_dlc *d, int err) struct rfcomm_dlc *d_list; struct rfcomm_session *s, *s_list; - BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err); + BT_DBG("dlc %pK state %ld dlci %d err %d", d, d->state, d->dlci, err); rfcomm_lock(); @@ -557,7 +557,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) if (d->state != BT_CONNECTED) return -ENOTCONN; - BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len); + BT_DBG("dlc %pK mtu %d len %d", d, d->mtu, len); if (len > d->mtu) return -EINVAL; @@ -574,7 +574,7 @@ void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb) { int len = skb->len; - BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len); + BT_DBG("dlc %pK mtu %d len %d", d, d->mtu, len); rfcomm_make_uih(skb, d->addr); skb_queue_tail(&d->tx_queue, skb); @@ -586,7 +586,7 @@ void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb) void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) { - BT_DBG("dlc %p state %ld", d, d->state); + BT_DBG("dlc %pK state %ld", d, d->state); if (!d->cfc) { d->v24_sig |= RFCOMM_V24_FC; @@ -597,7 +597,7 @@ void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) { - BT_DBG("dlc %p state %ld", d, d->state); + BT_DBG("dlc %pK state %ld", d, d->state); if (!d->cfc) { d->v24_sig &= ~RFCOMM_V24_FC; @@ -613,8 +613,8 @@ void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) */ int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig) { - BT_DBG("dlc %p state %ld v24_sig 0x%x", - d, d->state, v24_sig); + BT_DBG("dlc %pK state %ld v24_sig 0x%x", + d, d->state, v24_sig); if (test_bit(RFCOMM_RX_THROTTLED, &d->flags)) v24_sig |= RFCOMM_V24_FC; @@ -631,8 +631,8 @@ int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig) int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig) { - BT_DBG("dlc %p state %ld v24_sig 0x%x", - d, d->state, d->v24_sig); + BT_DBG("dlc %pK state %ld v24_sig 0x%x", + d, d->state, d->v24_sig); *v24_sig = d->v24_sig; return 0; @@ -646,7 +646,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state) if (!s) return NULL; - BT_DBG("session %p sock %p", s, sock); + BT_DBG("session %pK sock %pK", s, sock); setup_timer(&s->timer, rfcomm_session_timeout, (unsigned long) s); @@ -674,7 +674,7 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s) { int state = s->state; - BT_DBG("session %p state %ld", s, s->state); + BT_DBG("session %pK state %ld", s, s->state); list_del(&s->list); @@ -712,7 +712,7 @@ static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s, s->state = BT_CLOSED; - BT_DBG("session %p state %ld err %d", s, s->state, err); + BT_DBG("session %pK state %ld err %d", s, s->state, err); /* Close all dlcs */ list_for_each_safe(p, n, &s->dlcs) { @@ -798,7 +798,7 @@ static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len) struct kvec iv = { data, len }; struct msghdr msg; - BT_DBG("session %p len %d", s, len); + BT_DBG("session %pK len %d", s, len); memset(&msg, 0, sizeof(msg)); @@ -807,7 +807,7 @@ static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len) static int rfcomm_send_cmd(struct rfcomm_session *s, struct rfcomm_cmd *cmd) { - BT_DBG("%p cmd %u", s, cmd->ctrl); + BT_DBG("%pK cmd %u", s, cmd->ctrl); return rfcomm_send_frame(s, (void *) cmd, sizeof(*cmd)); } @@ -816,7 +816,7 @@ static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci) { struct rfcomm_cmd cmd; - BT_DBG("%p dlci %d", s, dlci); + BT_DBG("%pK dlci %d", s, dlci); cmd.addr = __addr(s->initiator, dlci); cmd.ctrl = __ctrl(RFCOMM_SABM, 1); @@ -830,7 +830,7 @@ static int rfcomm_send_ua(struct rfcomm_session *s, u8 dlci) { struct rfcomm_cmd cmd; - BT_DBG("%p dlci %d", s, dlci); + BT_DBG("%pK dlci %d", s, dlci); cmd.addr = __addr(!s->initiator, dlci); cmd.ctrl = __ctrl(RFCOMM_UA, 1); @@ -844,7 +844,7 @@ static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci) { struct rfcomm_cmd cmd; - BT_DBG("%p dlci %d", s, dlci); + BT_DBG("%pK dlci %d", s, dlci); cmd.addr = __addr(s->initiator, dlci); cmd.ctrl = __ctrl(RFCOMM_DISC, 1); @@ -859,7 +859,7 @@ static int rfcomm_queue_disc(struct rfcomm_dlc *d) struct rfcomm_cmd *cmd; struct sk_buff *skb; - BT_DBG("dlc %p dlci %d", d, d->dlci); + BT_DBG("dlc %pK dlci %d", d, d->dlci); skb = alloc_skb(sizeof(*cmd), GFP_KERNEL); if (!skb) @@ -880,7 +880,7 @@ static int rfcomm_send_dm(struct rfcomm_session *s, u8 dlci) { struct rfcomm_cmd cmd; - BT_DBG("%p dlci %d", s, dlci); + BT_DBG("%pK dlci %d", s, dlci); cmd.addr = __addr(!s->initiator, dlci); cmd.ctrl = __ctrl(RFCOMM_DM, 1); @@ -896,7 +896,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type) struct rfcomm_mcc *mcc; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d type %d", s, cr, type); + BT_DBG("%pK cr %d type %d", s, cr, type); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -922,7 +922,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d struct rfcomm_pn *pn; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d dlci %d mtu %d", s, cr, d->dlci, d->mtu); + BT_DBG("%pK cr %d dlci %d mtu %d", s, cr, d->dlci, d->mtu); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -967,10 +967,9 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, struct rfcomm_rpn *rpn; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x" - " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", - s, cr, dlci, bit_rate, data_bits, stop_bits, parity, - flow_ctrl_settings, xon_char, xoff_char, param_mask); + BT_DBG("%pK cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", + s, cr, dlci, bit_rate, data_bits, stop_bits, parity, + flow_ctrl_settings, xon_char, xoff_char, param_mask); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -1002,7 +1001,7 @@ static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status) struct rfcomm_rls *rls; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d status 0x%x", s, cr, status); + BT_DBG("%pK cr %d status 0x%x", s, cr, status); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -1029,7 +1028,7 @@ static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig struct rfcomm_msc *msc; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d v24 0x%x", s, cr, v24_sig); + BT_DBG("%pK cr %d v24 0x%x", s, cr, v24_sig); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -1055,7 +1054,7 @@ static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr) struct rfcomm_mcc *mcc; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d", s, cr); + BT_DBG("%pK cr %d", s, cr); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -1077,7 +1076,7 @@ static int rfcomm_send_fcon(struct rfcomm_session *s, int cr) struct rfcomm_mcc *mcc; u8 buf[16], *ptr = buf; - BT_DBG("%p cr %d", s, cr); + BT_DBG("%pK cr %d", s, cr); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = __addr(s->initiator, 0); @@ -1103,7 +1102,7 @@ static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int l if (len > 125) return -EINVAL; - BT_DBG("%p cr %d", s, cr); + BT_DBG("%pK cr %d", s, cr); hdr[0] = __addr(s->initiator, 0); hdr[1] = __ctrl(RFCOMM_UIH, 0); @@ -1130,7 +1129,7 @@ static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits) struct rfcomm_hdr *hdr; u8 buf[16], *ptr = buf; - BT_DBG("%p addr %d credits %d", s, addr, credits); + BT_DBG("%pK addr %d credits %d", s, addr, credits); hdr = (void *) ptr; ptr += sizeof(*hdr); hdr->addr = addr; @@ -1167,7 +1166,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) /* ---- RFCOMM frame reception ---- */ static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) { - BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); + BT_DBG("session %pK state %ld dlci %d", s, s->state, dlci); if (dlci) { /* Data channel */ @@ -1221,7 +1220,7 @@ static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) { int err = 0; - BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); + BT_DBG("session %pK state %ld dlci %d", s, s->state, dlci); if (dlci) { /* Data DLC */ @@ -1251,7 +1250,7 @@ static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s, { int err = 0; - BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); + BT_DBG("session %pK state %ld dlci %d", s, s->state, dlci); if (dlci) { struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci); @@ -1286,7 +1285,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) struct sock *sk = d->session->sock->sk; struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; - BT_DBG("dlc %p", d); + BT_DBG("dlc %pK", d); rfcomm_send_ua(d->session, d->dlci); @@ -1327,7 +1326,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci) struct rfcomm_dlc *d; u8 channel; - BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); + BT_DBG("session %pK state %ld dlci %d", s, s->state, dlci); if (!dlci) { rfcomm_send_ua(s, 0); @@ -1368,8 +1367,8 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) { struct rfcomm_session *s = d->session; - BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d", - d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits); + BT_DBG("dlc %pK state %ld dlci %d mtu %d fc 0x%x credits %d", + d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits); if ((pn->flow_ctrl == 0xf0 && s->cfc != RFCOMM_CFC_DISABLED) || pn->flow_ctrl == 0xe0) { @@ -1399,7 +1398,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) struct rfcomm_dlc *d; u8 dlci = pn->dlci; - BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); + BT_DBG("session %pK state %ld dlci %d", s, s->state, dlci); if (!dlci) return 0; @@ -1615,7 +1614,7 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb) type = __get_mcc_type(mcc->type); len = __get_mcc_len(mcc->len); - BT_DBG("%p type 0x%x cr %d", s, type, cr); + BT_DBG("%pK type 0x%x cr %d", s, type, cr); skb_pull(skb, 2); @@ -1670,7 +1669,7 @@ static int rfcomm_recv_data(struct rfcomm_session *s, u8 dlci, int pf, struct sk { struct rfcomm_dlc *d; - BT_DBG("session %p state %ld dlci %d pf %d", s, s->state, dlci, pf); + BT_DBG("session %pK state %ld dlci %d pf %d", s, s->state, dlci, pf); d = rfcomm_dlc_get(s, dlci); if (!d) { @@ -1772,7 +1771,7 @@ static void rfcomm_process_connect(struct rfcomm_session *s) struct rfcomm_dlc *d; struct list_head *p, *n; - BT_DBG("session %p state %ld", s, s->state); + BT_DBG("session %pK state %ld", s, s->state); list_for_each_safe(p, n, &s->dlcs) { d = list_entry(p, struct rfcomm_dlc, list); @@ -1796,8 +1795,8 @@ static int rfcomm_process_tx(struct rfcomm_dlc *d) struct sk_buff *skb; int err; - BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d", - d, d->state, d->cfc, d->rx_credits, d->tx_credits); + BT_DBG("dlc %pK state %ld cfc %d rx_credits %d tx_credits %d", + d, d->state, d->cfc, d->rx_credits, d->tx_credits); /* Send pending MSC */ if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags)) @@ -1844,7 +1843,7 @@ static void rfcomm_process_dlcs(struct rfcomm_session *s) struct rfcomm_dlc *d; struct list_head *p, *n; - BT_DBG("session %p state %ld", s, s->state); + BT_DBG("session %pK state %ld", s, s->state); list_for_each_safe(p, n, &s->dlcs) { d = list_entry(p, struct rfcomm_dlc, list); @@ -1905,7 +1904,8 @@ static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s) struct sock *sk = sock->sk; struct sk_buff *skb; - BT_DBG("session %p state %ld qlen %d", s, s->state, skb_queue_len(&sk->sk_receive_queue)); + BT_DBG("session %pK state %ld qlen %d", s, s->state, + skb_queue_len(&sk->sk_receive_queue)); /* Get data directly from socket receive queue without copying it. */ while ((skb = skb_dequeue(&sk->sk_receive_queue))) { @@ -1935,7 +1935,7 @@ static void rfcomm_accept_connection(struct rfcomm_session *s) if (list_empty(&bt_sk(sock->sk)->accept_q)) return; - BT_DBG("session %p", s); + BT_DBG("session %pK", s); err = kernel_accept(sock, &nsock, O_NONBLOCK); if (err < 0) @@ -1961,7 +1961,7 @@ static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s) { struct sock *sk = s->sock->sk; - BT_DBG("%p state %ld", s, s->state); + BT_DBG("%pK state %ld", s, s->state); switch (sk->sk_state) { case BT_CONNECTED: @@ -2116,7 +2116,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) struct rfcomm_dlc *d; struct list_head *p, *n; - BT_DBG("conn %p status 0x%02x encrypt 0x%02x", conn, status, encrypt); + BT_DBG("conn %pK status 0x%02x encrypt 0x%02x", conn, status, encrypt); s = rfcomm_session_get(&conn->hdev->bdaddr, &conn->dst); if (!s) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 8bbbb5ec468c..128644c0cfe8 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -68,7 +68,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) if (!sk) return; - BT_DBG("dlc %p state %ld err %d", d, d->state, err); + BT_DBG("dlc %pK state %ld err %d", d, d->state, err); local_irq_save(flags); bh_lock_sock(sk); @@ -156,7 +156,7 @@ static void rfcomm_sock_destruct(struct sock *sk) { struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; - BT_DBG("sk %p dlc %p", sk, d); + BT_DBG("sk %pK dlc %pK", sk, d); skb_queue_purge(&sk->sk_receive_queue); skb_queue_purge(&sk->sk_write_queue); @@ -176,7 +176,7 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent) { struct sock *sk; - BT_DBG("parent %p", parent); + BT_DBG("parent %pK", parent); /* Close not yet accepted dlcs */ while ((sk = bt_accept_dequeue(parent, NULL))) { @@ -196,7 +196,8 @@ static void rfcomm_sock_kill(struct sock *sk) if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) return; - BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, atomic_read(&sk->sk_refcnt)); + BT_DBG("sk %pK state %d refcnt %d", sk, sk->sk_state, + atomic_read(&sk->sk_refcnt)); /* Kill poor orphan */ bt_sock_unlink(&rfcomm_sk_list, sk); @@ -208,7 +209,7 @@ static void __rfcomm_sock_close(struct sock *sk) { struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; - BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); + BT_DBG("sk %pK state %d socket %pK", sk, sk->sk_state, sk->sk_socket); switch (sk->sk_state) { case BT_LISTEN: @@ -241,7 +242,7 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent) { struct rfcomm_pinfo *pi = rfcomm_pi(sk); - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (parent) { sk->sk_type = parent->sk_type; @@ -306,7 +307,7 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int bt_sock_link(&rfcomm_sk_list, sk); - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); return sk; } @@ -315,7 +316,7 @@ static int rfcomm_sock_create(struct net *net, struct socket *sock, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); sock->state = SS_UNCONNECTED; @@ -339,7 +340,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr int chan = sa->rc_channel; int err = 0; - BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); + BT_DBG("sk %pK %pMR", sk, &sa->rc_bdaddr); if (!addr || addr->sa_family != AF_BLUETOOTH) return -EINVAL; @@ -381,7 +382,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; int err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (alen < sizeof(struct sockaddr_rc) || addr->sa_family != AF_BLUETOOTH) @@ -422,7 +423,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) struct sock *sk = sock->sk; int err = 0; - BT_DBG("sk %p backlog %d", sk, backlog); + BT_DBG("sk %pK backlog %d", sk, backlog); lock_sock(sk); @@ -482,7 +483,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); - BT_DBG("sk %p timeo %ld", sk, timeo); + BT_DBG("sk %pK timeo %ld", sk, timeo); /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk_sleep(sk), &wait); @@ -520,7 +521,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f newsock->state = SS_CONNECTED; - BT_DBG("new socket %p", nsk); + BT_DBG("new socket %pK", nsk); done: release_sock(sk); @@ -532,7 +533,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; struct sock *sk = sock->sk; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (peer && sk->sk_state != BT_CONNECTED && sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) @@ -567,7 +568,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_shutdown & SEND_SHUTDOWN) return -EPIPE; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); lock_sock(sk); @@ -647,7 +648,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u int err = 0; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); lock_sock(sk); @@ -690,7 +691,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c size_t len; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (level == SOL_RFCOMM) return rfcomm_sock_setsockopt_old(sock, optname, optval, optlen); @@ -759,7 +760,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u int len, err = 0; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (get_user(len, optlen)) return -EFAULT; @@ -831,7 +832,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c struct bt_security sec; int len, err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (level == SOL_RFCOMM) return rfcomm_sock_getsockopt_old(sock, optname, optval, optlen); @@ -886,7 +887,7 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon struct sock *sk __maybe_unused = sock->sk; int err; - BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg); + BT_DBG("sk %pK cmd %x arg %lx", sk, cmd, arg); err = bt_sock_ioctl(sock, cmd, arg); @@ -908,7 +909,7 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) struct sock *sk = sock->sk; int err = 0; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (!sk) return 0; @@ -931,7 +932,7 @@ static int rfcomm_sock_release(struct socket *sock) struct sock *sk = sock->sk; int err; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (!sk) return 0; @@ -953,7 +954,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * bdaddr_t src, dst; int result = 0; - BT_DBG("session %p channel %d", s, channel); + BT_DBG("session %pK channel %d", s, channel); rfcomm_session_getaddr(s, &src, &dst); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 8e385a0ae60e..71f8126be12b 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -83,7 +83,7 @@ static void rfcomm_dev_destruct(struct tty_port *port) struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); struct rfcomm_dlc *dlc = dev->dlc; - BT_DBG("dev %p dlc %p", dev, dlc); + BT_DBG("dev %pK dlc %pK", dev, dlc); rfcomm_dlc_lock(dlc); /* Detach DLC if it's owned by this dev */ @@ -396,7 +396,7 @@ static int __rfcomm_create_dev(struct sock *sk, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags); + BT_DBG("sk %pK dev_id %d flags 0x%x", sk, req.dev_id, req.flags); if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) return -EPERM; @@ -581,7 +581,7 @@ static int rfcomm_get_dev_info(void __user *arg) int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) { - BT_DBG("cmd %d arg %p", cmd, arg); + BT_DBG("cmd %d arg %pK", cmd, arg); switch (cmd) { case RFCOMMCREATEDEV: @@ -615,7 +615,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) return; } - BT_DBG("dlc %p len %d", dlc, skb->len); + BT_DBG("dlc %pK len %d", dlc, skb->len); tty_insert_flip_string(&dev->port, skb->data, skb->len); tty_flip_buffer_push(&dev->port); @@ -629,7 +629,7 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) if (!dev) return; - BT_DBG("dlc %p dev %p err %d", dlc, dev, err); + BT_DBG("dlc %pK dev %pK err %d", dlc, dev, err); dev->err = err; if (dlc->state == BT_CONNECTED) { @@ -646,7 +646,7 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig) if (!dev) return; - BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig); + BT_DBG("dlc %pK dev %pK v24_sig 0x%02x", dlc, dev, v24_sig); if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) tty_port_tty_hangup(&dev->port, true); @@ -664,7 +664,7 @@ static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev) struct sk_buff *skb; int inserted = 0; - BT_DBG("dev %p", dev); + BT_DBG("dev %pK", dev); rfcomm_dlc_lock(dev->dlc); @@ -749,9 +749,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) struct rfcomm_dev *dev = tty->driver_data; int err; - BT_DBG("tty %p id %d", tty, tty->index); + BT_DBG("tty %pK id %d", tty, tty->index); - BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst, + BT_DBG("dev %pK dst %pMR channel %d opened %d", dev, &dev->dst, dev->channel, dev->port.count); err = tty_port_open(&dev->port, tty, filp); @@ -774,8 +774,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, - dev->port.count); + BT_DBG("tty %pK dev %pK dlc %pK opened %d", tty, dev, dev->dlc, + dev->port.count); tty_port_close(&dev->port, tty, filp); } @@ -787,7 +787,7 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in struct sk_buff *skb; int sent = 0, size; - BT_DBG("tty %p count %d", tty, count); + BT_DBG("tty %pK count %d", tty, count); while (count) { size = min_t(uint, count, dlc->mtu); @@ -817,14 +817,14 @@ static int rfcomm_tty_write_room(struct tty_struct *tty) if (dev && dev->dlc) room = rfcomm_room(dev); - BT_DBG("tty %p room %d", tty, room); + BT_DBG("tty %pK room %d", tty, room); return room; } static int rfcomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - BT_DBG("tty %p cmd 0x%02x", tty, cmd); + BT_DBG("tty %pK cmd 0x%02x", tty, cmd); switch (cmd) { case TCGETS: @@ -878,7 +878,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p termios %p", tty, old); + BT_DBG("tty %pK termios %pK", tty, old); if (!dev || !dev->dlc || !dev->dlc->session) return; @@ -1010,7 +1010,7 @@ static void rfcomm_tty_throttle(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p", tty, dev); + BT_DBG("tty %pK dev %pK", tty, dev); rfcomm_dlc_throttle(dev->dlc); } @@ -1019,7 +1019,7 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p", tty, dev); + BT_DBG("tty %pK dev %pK", tty, dev); rfcomm_dlc_unthrottle(dev->dlc); } @@ -1028,7 +1028,7 @@ static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p", tty, dev); + BT_DBG("tty %pK dev %pK", tty, dev); if (!dev || !dev->dlc) return 0; @@ -1043,7 +1043,7 @@ static void rfcomm_tty_flush_buffer(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p", tty, dev); + BT_DBG("tty %pK dev %pK", tty, dev); if (!dev || !dev->dlc) return; @@ -1054,19 +1054,19 @@ static void rfcomm_tty_flush_buffer(struct tty_struct *tty) static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch) { - BT_DBG("tty %p ch %c", tty, ch); + BT_DBG("tty %pK ch %c", tty, ch); } static void rfcomm_tty_wait_until_sent(struct tty_struct *tty, int timeout) { - BT_DBG("tty %p timeout %d", tty, timeout); + BT_DBG("tty %pK timeout %d", tty, timeout); } static void rfcomm_tty_hangup(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p", tty, dev); + BT_DBG("tty %pK dev %pK", tty, dev); tty_port_hangup(&dev->port); } @@ -1075,7 +1075,7 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; - BT_DBG("tty %p dev %p", tty, dev); + BT_DBG("tty %pK dev %pK", tty, dev); return dev->modem_status; } @@ -1086,7 +1086,7 @@ static int rfcomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigne struct rfcomm_dlc *dlc = dev->dlc; u8 v24_sig; - BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear); + BT_DBG("tty %pK dev %pK set 0x%02x clear 0x%02x", tty, dev, set, clear); rfcomm_dlc_get_modem_status(dlc, &v24_sig); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 7ee9e4ab00f8..fcf31a4d10c3 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -76,7 +76,7 @@ static void sco_sock_timeout(unsigned long arg) { struct sock *sk = (struct sock *) arg; - BT_DBG("sock %p state %d", sk, sk->sk_state); + BT_DBG("sock %pK state %d", sk, sk->sk_state); bh_lock_sock(sk); sk->sk_err = ETIMEDOUT; @@ -89,13 +89,13 @@ static void sco_sock_timeout(unsigned long arg) static void sco_sock_set_timer(struct sock *sk, long timeout) { - BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout); + BT_DBG("sock %pK state %d timeout %ld", sk, sk->sk_state, timeout); sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); } static void sco_sock_clear_timer(struct sock *sk) { - BT_DBG("sock %p state %d", sk, sk->sk_state); + BT_DBG("sock %pK state %d", sk, sk->sk_state); sk_stop_timer(sk, &sk->sk_timer); } @@ -122,7 +122,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) else conn->mtu = 60; - BT_DBG("hcon %p conn %p", hcon, conn); + BT_DBG("hcon %pK conn %pK", hcon, conn); return conn; } @@ -135,7 +135,7 @@ static void sco_chan_del(struct sock *sk, int err) conn = sco_pi(sk)->conn; - BT_DBG("sk %p, conn %p, err %d", sk, conn, err); + BT_DBG("sk %pK, conn %pK, err %d", sk, conn, err); if (conn) { sco_conn_lock(conn); @@ -162,7 +162,7 @@ static int sco_conn_del(struct hci_conn *hcon, int err) if (!conn) return 0; - BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); + BT_DBG("hcon %pK conn %pK, err %d", hcon, conn, err); /* Kill socket */ sco_conn_lock(conn); @@ -184,7 +184,7 @@ static int sco_conn_del(struct hci_conn *hcon, int err) static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) { - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); sco_pi(sk)->conn = conn; conn->sk = sk; @@ -279,7 +279,7 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) if (len > conn->mtu) return -EINVAL; - BT_DBG("sk %p len %d", sk, len); + BT_DBG("sk %pK len %d", sk, len); skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) @@ -306,7 +306,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) if (!sk) goto drop; - BT_DBG("sk %p len %d", sk, skb->len); + BT_DBG("sk %pK len %d", sk, skb->len); if (sk->sk_state != BT_CONNECTED) goto drop; @@ -363,7 +363,7 @@ static struct sock *sco_get_sock_listen(bdaddr_t *src) static void sco_sock_destruct(struct sock *sk) { - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); skb_queue_purge(&sk->sk_receive_queue); skb_queue_purge(&sk->sk_write_queue); @@ -373,7 +373,7 @@ static void sco_sock_cleanup_listen(struct sock *parent) { struct sock *sk; - BT_DBG("parent %p", parent); + BT_DBG("parent %pK", parent); /* Close not yet accepted channels */ while ((sk = bt_accept_dequeue(parent, NULL))) { @@ -393,7 +393,7 @@ static void sco_sock_kill(struct sock *sk) if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) return; - BT_DBG("sk %p state %d", sk, sk->sk_state); + BT_DBG("sk %pK state %d", sk, sk->sk_state); /* Kill poor orphan */ bt_sock_unlink(&sco_sk_list, sk); @@ -403,7 +403,7 @@ static void sco_sock_kill(struct sock *sk) static void __sco_sock_close(struct sock *sk) { - BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); + BT_DBG("sk %pK state %d socket %pK", sk, sk->sk_state, sk->sk_socket); switch (sk->sk_state) { case BT_LISTEN: @@ -445,7 +445,7 @@ static void sco_sock_close(struct sock *sk) static void sco_sock_init(struct sock *sk, struct sock *parent) { - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (parent) { sk->sk_type = parent->sk_type; @@ -492,7 +492,7 @@ static int sco_sock_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; - BT_DBG("sock %p", sock); + BT_DBG("sock %pK", sock); sock->state = SS_UNCONNECTED; @@ -515,7 +515,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le struct sock *sk = sock->sk; int err = 0; - BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr); + BT_DBG("sk %pK %pMR", sk, &sa->sco_bdaddr); if (!addr || addr->sa_family != AF_BLUETOOTH) return -EINVAL; @@ -547,7 +547,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen struct sock *sk = sock->sk; int err; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (alen < sizeof(struct sockaddr_sco) || addr->sa_family != AF_BLUETOOTH) @@ -582,7 +582,7 @@ static int sco_sock_listen(struct socket *sock, int backlog) bdaddr_t *src = &sco_pi(sk)->src; int err = 0; - BT_DBG("sk %p backlog %d", sk, backlog); + BT_DBG("sk %pK backlog %d", sk, backlog); lock_sock(sk); @@ -627,7 +627,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); - BT_DBG("sk %p timeo %ld", sk, timeo); + BT_DBG("sk %pK timeo %ld", sk, timeo); /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk_sleep(sk), &wait); @@ -665,7 +665,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag newsock->state = SS_CONNECTED; - BT_DBG("new socket %p", ch); + BT_DBG("new socket %pK", ch); done: release_sock(sk); @@ -677,7 +677,7 @@ static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len struct sockaddr_sco *sa = (struct sockaddr_sco *) addr; struct sock *sk = sock->sk; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); addr->sa_family = AF_BLUETOOTH; *len = sizeof(struct sockaddr_sco); @@ -696,7 +696,7 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct sock *sk = sock->sk; int err; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); err = sock_error(sk); if (err) @@ -720,7 +720,7 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) { struct hci_dev *hdev = conn->hdev; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); conn->state = BT_CONFIG; @@ -789,7 +789,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char struct bt_voice voice; u32 opt; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); lock_sock(sk); @@ -853,7 +853,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user struct sco_conninfo cinfo; int len, err = 0; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (get_user(len, optlen)) return -EFAULT; @@ -912,7 +912,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char int len, err = 0; struct bt_voice voice; - BT_DBG("sk %p", sk); + BT_DBG("sk %pK", sk); if (level == SOL_SCO) return sco_sock_getsockopt_old(sock, optname, optval, optlen); @@ -959,7 +959,7 @@ static int sco_sock_shutdown(struct socket *sock, int how) struct sock *sk = sock->sk; int err = 0; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (!sk) return 0; @@ -984,7 +984,7 @@ static int sco_sock_release(struct socket *sock) struct sock *sk = sock->sk; int err = 0; - BT_DBG("sock %p, sk %p", sock, sk); + BT_DBG("sock %pK, sk %pK", sock, sk); if (!sk) return 0; @@ -1008,7 +1008,7 @@ static void sco_conn_ready(struct sco_conn *conn) struct sock *parent; struct sock *sk = conn->sk; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (sk) { sco_sock_clear_timer(sk); @@ -1087,7 +1087,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) void sco_connect_cfm(struct hci_conn *hcon, __u8 status) { - BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); + BT_DBG("hcon %pK bdaddr %pMR status %d", hcon, &hcon->dst, status); if (!status) { struct sco_conn *conn; @@ -1100,7 +1100,7 @@ void sco_connect_cfm(struct hci_conn *hcon, __u8 status) void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) { - BT_DBG("hcon %p reason %d", hcon, reason); + BT_DBG("hcon %pK reason %d", hcon, reason); sco_conn_del(hcon, bt_to_errno(reason)); } @@ -1112,7 +1112,7 @@ int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) if (!conn) goto drop; - BT_DBG("conn %p len %d", conn, skb->len); + BT_DBG("conn %pK len %d", conn, skb->len); if (skb->len) { sco_recv_frame(conn, skb); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 9ebc394ea5e5..b2829319ffd0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -88,7 +88,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) int err; if (tfm == NULL) { - BT_ERR("tfm %p", tfm); + BT_ERR("tfm %pK", tfm); return -EINVAL; } @@ -545,7 +545,7 @@ static u8 smp_confirm(struct smp_chan *smp) struct smp_cmd_pairing_confirm cp; int ret; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); ret = smp_c1(smp, smp->tk, smp->prnd, smp->preq, smp->prsp, conn->hcon->init_addr_type, &conn->hcon->init_addr, @@ -576,7 +576,7 @@ static u8 smp_random(struct smp_chan *smp) if (IS_ERR_OR_NULL(smp->tfm_aes)) return SMP_UNSPECIFIED; - BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); + BT_DBG("conn %pK %s", conn, conn->hcon->out ? "master" : "slave"); ret = smp_c1(smp, smp->tk, smp->rrnd, smp->preq, smp->prsp, hcon->init_addr_type, &hcon->init_addr, @@ -723,7 +723,7 @@ static void smp_distribute_keys(struct smp_chan *smp) struct hci_dev *hdev = hcon->hdev; __u8 *keydist; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); rsp = (void *) &smp->prsp[1]; @@ -833,7 +833,7 @@ static void smp_timeout(struct work_struct *work) security_timer.work); struct l2cap_conn *conn = smp->conn; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); hci_disconnect(conn->hcon, HCI_ERROR_REMOTE_USER_TERM); } @@ -935,7 +935,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) u8 key_size, auth, sec_level; int ret; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(*req)) return SMP_INVALID_PARAMS; @@ -1010,7 +1010,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) u8 key_size, auth; int ret; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(*rsp)) return SMP_INVALID_PARAMS; @@ -1068,7 +1068,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) struct l2cap_chan *chan = conn->smp; struct smp_chan *smp = chan->data; - BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); + BT_DBG("conn %pK %s", conn, conn->hcon->out ? "master" : "slave"); if (skb->len < sizeof(smp->pcnf)) return SMP_INVALID_PARAMS; @@ -1096,7 +1096,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) struct l2cap_chan *chan = conn->smp; struct smp_chan *smp = chan->data; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(smp->rrnd)) return SMP_INVALID_PARAMS; @@ -1162,7 +1162,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) struct smp_chan *smp; u8 sec_level, auth; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(*rp)) return SMP_INVALID_PARAMS; @@ -1216,7 +1216,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) __u8 authreq; int ret; - BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); + BT_DBG("conn %pK hcon %pK level 0x%2.2x", conn, hcon, sec_level); /* This may be NULL if there's an unexpected disconnection */ if (!conn) @@ -1290,7 +1290,7 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) struct l2cap_chan *chan = conn->smp; struct smp_chan *smp = chan->data; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(*rp)) return SMP_INVALID_PARAMS; @@ -1314,7 +1314,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) struct smp_ltk *ltk; u8 authenticated; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(*rp)) return SMP_INVALID_PARAMS; @@ -1430,7 +1430,7 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) struct hci_dev *hdev = conn->hcon->hdev; struct smp_csrk *csrk; - BT_DBG("conn %p", conn); + BT_DBG("conn %pK", conn); if (skb->len < sizeof(*rp)) return SMP_INVALID_PARAMS; @@ -1563,7 +1563,7 @@ static void smp_teardown_cb(struct l2cap_chan *chan, int err) { struct l2cap_conn *conn = chan->conn; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (chan->data) smp_chan_destroy(conn); @@ -1578,7 +1578,7 @@ static void smp_resume_cb(struct l2cap_chan *chan) struct l2cap_conn *conn = chan->conn; struct hci_conn *hcon = conn->hcon; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); if (!smp) return; @@ -1595,7 +1595,7 @@ static void smp_ready_cb(struct l2cap_chan *chan) { struct l2cap_conn *conn = chan->conn; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); conn->smp = chan; l2cap_chan_hold(chan); @@ -1605,7 +1605,7 @@ static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { int err; - BT_DBG("chan %p", chan); + BT_DBG("chan %pK", chan); err = smp_sig_channel(chan, skb); if (err) { @@ -1658,7 +1658,7 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) { struct l2cap_chan *chan; - BT_DBG("pchan %p", pchan); + BT_DBG("pchan %pK", pchan); chan = l2cap_chan_create(); if (!chan) @@ -1672,7 +1672,7 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) chan->omtu = pchan->omtu; chan->mode = pchan->mode; - BT_DBG("created chan %p", chan); + BT_DBG("created chan %pK", chan); return chan; } @@ -1742,7 +1742,7 @@ void smp_unregister(struct hci_dev *hdev) if (!chan) return; - BT_DBG("%s chan %p", hdev->name, chan); + BT_DBG("%s chan %pK", hdev->name, chan); tfm_aes = chan->data; if (tfm_aes) { From d4bdbf71d3f3cdb5eacad2289b049e85589c9d20 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Tue, 19 Apr 2016 13:16:15 -0700 Subject: [PATCH 152/203] diag: Use correct index while accessing DCI channel Use correct index value while accessing DCI channel status. Change-Id: I97456326a40c6d24c208307a9e8e6a55fc5b9d59 Signed-off-by: Sreelakshmi Gownipalli --- drivers/char/diag/diag_dci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index a54eb5dea527..3bc09927ea90 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -213,7 +213,7 @@ static void dci_chk_handshake(unsigned long data) { int index = (int)data; - if (index < 0 || index > NUM_DCI_PROC) + if (index < 0 || index >= NUM_DCI_PROC) return; queue_work(driver->diag_dci_wq, From 7cb1f0dc7949991358044b2c52a4b2f35d26e71d Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Tue, 3 May 2016 16:46:24 -0400 Subject: [PATCH 153/203] net: fix infoleak in rtnetlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stack object “map” has a total size of 32 bytes. Its last 4 bytes are padding generated by compiler. These padding bytes are not initialized and sent out via “nla_put”. Conflicts: net/core/rtnetlink.c b/28620102 Signed-off-by: Kangjie Lu Signed-off-by: David S. Miller Signed-off-by: Dennis Cagle Git-commit: 5f8e44741f9f216e33736ea4ec65ca9ac03036e6 Git-repo: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git (cherry picked from commit 5f8e44741f9f216e33736ea4ec65ca9ac03036e6) Change-Id: I41f4745f24720c7af5ab08dc4274224d7fe4dcfe --- net/core/rtnetlink.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index c522f7a00eab..6bda044c3a2a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1026,6 +1026,14 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, .dma = dev->dma, .port = dev->if_port, }; + memset(&map, 0, sizeof(map)); + map.mem_start = dev->mem_start; + map.mem_end = dev->mem_end; + map.base_addr = dev->base_addr; + map.irq = dev->irq; + map.dma = dev->dma; + map.port = dev->if_port; + if (nla_put(skb, IFLA_MAP, sizeof(map), &map)) goto nla_put_failure; } From 02b6d282ed39dc6b8218ec8e3efb902b2b54116f Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Thu, 19 May 2016 14:43:25 -0700 Subject: [PATCH 154/203] msm: ADSPRPC: Validate the SMMU session count Make sure that the session count does not exceed the maximum sessions to avoid buffer overflow. Change-Id: I1a9830a6f859d7d525247d27d0a143997998d997 Acked-by: Bharath Kumar Signed-off-by: Sathish Ambley --- drivers/char/adsprpc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 0ba1b05fefd2..ba4f9ab4f10f 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2057,6 +2057,9 @@ static int fastrpc_cb_legacy_probe(struct device *dev) if (err) goto bail; for (i = 0; i < sids_size/sizeof(unsigned int); i++) { + VERIFY(err, chan->sesscount < NUM_SESSIONS); + if (err) + goto bail; sess = &chan->session[chan->sesscount]; sess->smmu.cb = sids[i]; sess->dev = first_sess->dev; From b46a4d44fb03d6adcb3048f39f1943114dafd6de Mon Sep 17 00:00:00 2001 From: Mohamad Ayyash Date: Tue, 24 May 2016 15:33:56 -0700 Subject: [PATCH 155/203] Replace %p with %pK to prevent leaking kernel address BUG: 27532522 Change-Id: Ic0710a9a8cfc682acd88ecf3bbfeece2d798c4a4 Signed-off-by: Mohamad Ayyash --- net/netfilter/xt_qtaguid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 45df66f62f7d..bd27e833e9db 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1979,7 +1979,7 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v) ); f_count = atomic_long_read( &sock_tag_entry->socket->file->f_count); - seq_printf(m, "sock=%p tag=0x%llx (uid=%u) pid=%u " + seq_printf(m, "sock=%pK tag=0x%llx (uid=%u) pid=%u " "f_count=%lu\n", sock_tag_entry->sk, sock_tag_entry->tag, uid, From e2ca84f7f6e6aed440b874490067e7cf27ef4221 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Jun 2016 15:48:57 +0100 Subject: [PATCH 156/203] KEYS: potential uninitialized variable [ Upstream commit 38327424b40bcebe2de92d07312c89360ac9229a ] If __key_link_begin() failed then "edit" would be uninitialized. I've added a check to fix that. This allows a random user to crash the kernel, though it's quite difficult to achieve. There are three ways it can be done as the user would have to cause an error to occur in __key_link(): (1) Cause the kernel to run out of memory. In practice, this is difficult to achieve without ENOMEM cropping up elsewhere and aborting the attempt. (2) Revoke the destination keyring between the keyring ID being looked up and it being tested for revocation. In practice, this is difficult to time correctly because the KEYCTL_REJECT function can only be used from the request-key upcall process. Further, users can only make use of what's in /sbin/request-key.conf, though this does including a rejection debugging test - which means that the destination keyring has to be the caller's session keyring in practice. (3) Have just enough key quota available to create a key, a new session keyring for the upcall and a link in the session keyring, but not then sufficient quota to create a link in the nominated destination keyring so that it fails with EDQUOT. The bug can be triggered using option (3) above using something like the following: echo 80 >/proc/sys/kernel/keys/root_maxbytes keyctl request2 user debug:fred negate @t The above sets the quota to something much lower (80) to make the bug easier to trigger, but this is dependent on the system. Note also that the name of the keyring created contains a random number that may be between 1 and 10 characters in size, so may throw the test off by changing the amount of quota used. Assuming the failure occurs, something like the following will be seen: kfree_debugcheck: out of range ptr 6b6b6b6b6b6b6b68h ------------[ cut here ]------------ kernel BUG at ../mm/slab.c:2821! ... RIP: 0010:[] kfree_debugcheck+0x20/0x25 RSP: 0018:ffff8804014a7de8 EFLAGS: 00010092 RAX: 0000000000000034 RBX: 6b6b6b6b6b6b6b68 RCX: 0000000000000000 RDX: 0000000000040001 RSI: 00000000000000f6 RDI: 0000000000000300 RBP: ffff8804014a7df0 R08: 0000000000000001 R09: 0000000000000000 R10: ffff8804014a7e68 R11: 0000000000000054 R12: 0000000000000202 R13: ffffffff81318a66 R14: 0000000000000000 R15: 0000000000000001 ... Call Trace: kfree+0xde/0x1bc assoc_array_cancel_edit+0x1f/0x36 __key_link_end+0x55/0x63 key_reject_and_link+0x124/0x155 keyctl_reject_key+0xb6/0xe0 keyctl_negate_key+0x10/0x12 SyS_keyctl+0x9f/0xe7 do_syscall_64+0x63/0x13a entry_SYSCALL64_slow_path+0x25/0x25 Fixes: f70e2e06196a ('KEYS: Do preallocation for __key_link()') Signed-off-by: Dan Carpenter Signed-off-by: David Howells cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: engstk --- security/keys/key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/key.c b/security/keys/key.c index e17ba6aefdc0..f8bde20bed5d 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -580,7 +580,7 @@ int key_reject_and_link(struct key *key, mutex_unlock(&key_construction_mutex); - if (keyring) + if (keyring && link_ret == 0) __key_link_end(keyring, &key->index_key, edit); /* wake up anyone waiting for a key to be constructed */ From a5d6e5455369cdd0cc93711f4a81085c771d97fd Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 10 Jul 2016 10:04:02 +0200 Subject: [PATCH 157/203] BACKPORT: tcp: make challenge acks less predictable (cherry picked from commit 75ff39ccc1bd5d3c455b6822ab09e533c551f758) Yue Cao claims that current host rate limiting of challenge ACKS (RFC 5961) could leak enough information to allow a patient attacker to hijack TCP sessions. He will soon provide details in an academic paper. This patch increases the default limit from 100 to 1000, and adds some randomization so that the attacker can no longer hijack sessions without spending a considerable amount of probes. Based on initial analysis and patch from Linus. Note that we also have per socket rate limiting, so it is tempting to remove the host limit in the future. v2: randomize the count of challenge acks per second, not the period. Fixes: 282f23c6ee34 ("tcp: implement RFC 5961 3.2") Reported-by: Yue Cao Signed-off-by: Eric Dumazet Suggested-by: Linus Torvalds Cc: Yuchung Cheng Cc: Neal Cardwell Acked-by: Neal Cardwell Acked-by: Yuchung Cheng Signed-off-by: David S. Miller Change-Id: Ib46ba66f5e4a5a7c81bfccd7b0aa83c3d9e1b3bb Bug: 30809774 --- net/ipv4/tcp_input.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 055b7ddf9fb8..212fe15905e4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -88,7 +88,7 @@ int sysctl_tcp_adv_win_scale __read_mostly = 1; EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); /* rfc5961 challenge ack rate limiting */ -int sysctl_tcp_challenge_ack_limit = 100; +int sysctl_tcp_challenge_ack_limit = 1000; int sysctl_tcp_stdurg __read_mostly; int sysctl_tcp_rfc1337 __read_mostly; @@ -3326,12 +3326,18 @@ static void tcp_send_challenge_ack(struct sock *sk) static u32 challenge_timestamp; static unsigned int challenge_count; u32 now = jiffies / HZ; + u32 count; if (now != challenge_timestamp) { + u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1; + challenge_timestamp = now; - challenge_count = 0; + WRITE_ONCE(challenge_count, half + + prandom_u32_max(sysctl_tcp_challenge_ack_limit)); } - if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { + count = READ_ONCE(challenge_count); + if (count > 0) { + WRITE_ONCE(challenge_count, count - 1); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); tcp_send_ack(sk); } From fa5ceb1ee7122d0830a075211b4ce4963c441b7f Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Tue, 16 Aug 2016 11:24:00 -0600 Subject: [PATCH 158/203] soc: qcom: smp2p: Fix kernel address leak Change format string to %pK instead of %p in the debug statements. This change fixes kernel address leaks from the usage of %p. CRs-Fixed: 1052825 Change-Id: Ib95f691919a2977f5436cd4c6ac4a002d70dd729 Signed-off-by: Chris Lew Signed-off-by: Karthikeyan Ramasubramanian --- drivers/gpio/gpio-msm-smp2p.c | 2 +- drivers/soc/qcom/smp2p.c | 6 +++--- drivers/soc/qcom/smp2p_debug.c | 4 ++-- drivers/soc/qcom/smp2p_test_common.h | 5 +++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-msm-smp2p.c b/drivers/gpio/gpio-msm-smp2p.c index bde81f0473bd..b426a804c0fa 100644 --- a/drivers/gpio/gpio-msm-smp2p.c +++ b/drivers/gpio/gpio-msm-smp2p.c @@ -368,7 +368,7 @@ static int smp2p_irq_map(struct irq_domain *domain_ptr, unsigned int virq, chip = domain_ptr->host_data; if (!chip) { - SMP2P_ERR("%s: invalid domain ptr %p\n", __func__, domain_ptr); + SMP2P_ERR("%s: invalid domain ptr\n", __func__); return -ENODEV; } diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index fc5688b4bc8c..79b8ffbc5ee7 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -1,6 +1,6 @@ /* drivers/soc/qcom/smp2p.c * - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-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 @@ -519,8 +519,8 @@ static void smp2p_find_entry_v1(struct smp2p_smem __iomem *item, char entry_name[SMP2P_MAX_ENTRY_NAME]; if (!item || !name || !entry_ptr) { - SMP2P_ERR("%s: invalid arguments %p, %p, %p\n", - __func__, item, name, entry_ptr); + SMP2P_ERR("%s: invalid arguments %d %d %d\n", + __func__, !item, !name, !entry_ptr); return; } diff --git a/drivers/soc/qcom/smp2p_debug.c b/drivers/soc/qcom/smp2p_debug.c index 4deb05a08139..8d98d07c1adf 100644 --- a/drivers/soc/qcom/smp2p_debug.c +++ b/drivers/soc/qcom/smp2p_debug.c @@ -1,6 +1,6 @@ /* drivers/soc/qcom/smp2p_debug.c * - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-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 @@ -41,7 +41,7 @@ static void smp2p_int_stats(struct seq_file *s) pid != SMP2P_REMOTE_MOCK_PROC) continue; - seq_printf(s, "| %5s (%d) | %11u | %10u | %10u | %p | %08x |\n", + seq_printf(s, "| %5s (%d) | %11u | %10u | %10u | %pK | %08x |\n", int_cfg[pid].name, pid, int_cfg[pid].in_int_id, int_cfg[pid].in_interrupt_count, diff --git a/drivers/soc/qcom/smp2p_test_common.h b/drivers/soc/qcom/smp2p_test_common.h index 747a812d82c5..3be519bc0c96 100644 --- a/drivers/soc/qcom/smp2p_test_common.h +++ b/drivers/soc/qcom/smp2p_test_common.h @@ -1,6 +1,6 @@ /* drivers/soc/qcom/smp2p_test_common.h * - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-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 @@ -49,7 +49,8 @@ void *a_tmp = (a); \ void *b_tmp = (b); \ if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%p) " #cmp " " #b "(%p)\n", \ + seq_printf(s, "%s:%d Fail: " #a "(%pK) " #cmp \ + " " #b "(%pK)\n", \ __func__, __LINE__, \ a_tmp, b_tmp); \ failed = 1; \ From 16a2db12d2516d2ce651b8363b2cd2050b30d719 Mon Sep 17 00:00:00 2001 From: Siena Richard Date: Tue, 16 Aug 2016 13:03:56 -0700 Subject: [PATCH 159/203] misc: qcom: qdsp6v2: initialize wma_config_32 Not all memebers of wma_config_32 are set before they are used which might lead to invalid values being passed and used. To fix this issue initialize all member variables of struct wma_config_32 to 0 before assigning specific values individually. Change-Id: Ibb082ce691625527e9a9ffd4978dea7ba4df9e84 CRs-Fixed: 1054352 Signed-off-by: Siena Richard --- drivers/misc/qcom/qdsp6v2/audio_wma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/qcom/qdsp6v2/audio_wma.c b/drivers/misc/qcom/qdsp6v2/audio_wma.c index 3d57d38d0fd1..4389c0ffea05 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_wma.c +++ b/drivers/misc/qcom/qdsp6v2/audio_wma.c @@ -166,6 +166,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_wma_config_v2 *wma_config; struct msm_audio_wma_config_v2_32 wma_config_32; + memset(&wma_config_32, 0, sizeof(wma_config_32)); + wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg; wma_config_32.format_tag = wma_config->format_tag; wma_config_32.numchannels = wma_config->numchannels; From 9512dc7de033253c1ec5424f64f6b30feeb7b653 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 17 Aug 2016 16:00:08 -0700 Subject: [PATCH 160/203] binder: prevent kptr leak by using %pK format specifier Works in conjunction with kptr_restrict. Bug: 30143283 Change-Id: I2b3ce22f4e206e74614d51453a1d59b7080ab05a Signed-off-by: engstk --- drivers/staging/android/binder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index a6cd39586d75..3aa007572d75 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -3358,7 +3358,7 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) { - seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n", + seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n", ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ", ref->node->debug_id, ref->strong, ref->weak, ref->death); } From 5621f34e7749c58bb41bb03f2280c375f461024e Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Mon, 29 Aug 2016 21:58:32 +0530 Subject: [PATCH 161/203] misc: qcom: qdsp6v2: initialize config_32 Not all members of config_32 are set before they are used which might lead to invalid values being passed and used. To fix this issue initialize all member variables of struct config_32 to 0 before assigning specific values individually. CRs-Fixed: 1058826 Change-Id: Ifea3a6e8bf45481c65a4455ee64318304798fee2 Signed-off-by: Laxminath Kasam --- drivers/misc/qcom/qdsp6v2/aac_in.c | 4 +++- drivers/misc/qcom/qdsp6v2/amrnb_in.c | 4 +++- drivers/misc/qcom/qdsp6v2/amrwb_in.c | 2 ++ drivers/misc/qcom/qdsp6v2/audio_alac.c | 2 ++ drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c | 4 ++++ drivers/misc/qcom/qdsp6v2/audio_ape.c | 2 ++ drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 2 ++ drivers/misc/qcom/qdsp6v2/audio_multi_aac.c | 2 ++ drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 1 + drivers/misc/qcom/qdsp6v2/audio_wmapro.c | 2 ++ drivers/misc/qcom/qdsp6v2/evrc_in.c | 4 +++- drivers/misc/qcom/qdsp6v2/qcelp_in.c | 4 +++- 12 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/misc/qcom/qdsp6v2/aac_in.c b/drivers/misc/qcom/qdsp6v2/aac_in.c index c9d5dbb0b313..7176c114f85b 100644 --- a/drivers/misc/qcom/qdsp6v2/aac_in.c +++ b/drivers/misc/qcom/qdsp6v2/aac_in.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-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 @@ -421,6 +421,8 @@ static long aac_in_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_aac_enc_config cfg; struct msm_audio_aac_enc_config32 cfg_32; + memset(&cfg_32, 0, sizeof(cfg_32)); + cmd = AUDIO_GET_AAC_ENC_CONFIG; rc = aac_in_ioctl_shared(file, cmd, &cfg); if (rc) { diff --git a/drivers/misc/qcom/qdsp6v2/amrnb_in.c b/drivers/misc/qcom/qdsp6v2/amrnb_in.c index eb92137f0671..9d4cf5cff5da 100644 --- a/drivers/misc/qcom/qdsp6v2/amrnb_in.c +++ b/drivers/misc/qcom/qdsp6v2/amrnb_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, 2014 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-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 @@ -221,6 +221,8 @@ static long amrnb_in_compat_ioctl(struct file *file, struct msm_audio_amrnb_enc_config_v2 *amrnb_config; struct msm_audio_amrnb_enc_config_v2_32 amrnb_config_32; + memset(&amrnb_config_32, 0, sizeof(amrnb_config_32)); + amrnb_config = (struct msm_audio_amrnb_enc_config_v2 *)audio->enc_cfg; amrnb_config_32.band_mode = amrnb_config->band_mode; diff --git a/drivers/misc/qcom/qdsp6v2/amrwb_in.c b/drivers/misc/qcom/qdsp6v2/amrwb_in.c index 4cea3dc63389..71adbce0e257 100644 --- a/drivers/misc/qcom/qdsp6v2/amrwb_in.c +++ b/drivers/misc/qcom/qdsp6v2/amrwb_in.c @@ -216,6 +216,8 @@ static long amrwb_in_compat_ioctl(struct file *file, struct msm_audio_amrwb_enc_config *amrwb_config; struct msm_audio_amrwb_enc_config_32 amrwb_config_32; + memset(&amrwb_config_32, 0, sizeof(amrwb_config_32)); + amrwb_config = (struct msm_audio_amrwb_enc_config *)audio->enc_cfg; amrwb_config_32.band_mode = amrwb_config->band_mode; diff --git a/drivers/misc/qcom/qdsp6v2/audio_alac.c b/drivers/misc/qcom/qdsp6v2/audio_alac.c index 9748db30fac3..87b09939f9a1 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_alac.c +++ b/drivers/misc/qcom/qdsp6v2/audio_alac.c @@ -196,6 +196,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_alac_config *alac_config; struct msm_audio_alac_config_32 alac_config_32; + memset(&alac_config_32, 0, sizeof(alac_config_32)); + alac_config = (struct msm_audio_alac_config *)audio->codec_cfg; alac_config_32.frameLength = alac_config->frameLength; alac_config_32.compatVersion = diff --git a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c index ee5991177687..025ccfdc39be 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c +++ b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c @@ -205,6 +205,10 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_amrwbplus_config_v2 *amrwbplus_config; struct msm_audio_amrwbplus_config_v2_32 amrwbplus_config_32; + + memset(&amrwbplus_config_32, 0, + sizeof(amrwbplus_config_32)); + amrwbplus_config = (struct msm_audio_amrwbplus_config_v2 *) audio->codec_cfg; diff --git a/drivers/misc/qcom/qdsp6v2/audio_ape.c b/drivers/misc/qcom/qdsp6v2/audio_ape.c index b4c2ddb947de..cf9ff72ebc93 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_ape.c +++ b/drivers/misc/qcom/qdsp6v2/audio_ape.c @@ -180,6 +180,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_ape_config *ape_config; struct msm_audio_ape_config_32 ape_config_32; + memset(&ape_config_32, 0, sizeof(ape_config_32)); + ape_config = (struct msm_audio_ape_config *)audio->codec_cfg; ape_config_32.compatibleVersion = ape_config->compatibleVersion; ape_config_32.compressionLevel = diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index 3ba20cadcbfd..2ba85c6b56e0 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -628,6 +628,8 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, case AUDIO_EFFECTS_GET_BUF_AVAIL32: { struct msm_hwacc_buf_avail32 buf_avail; + memset(&buf_avail, 0, sizeof(buf_avail)); + buf_avail.input_num_avail = atomic_read(&effects->in_count); buf_avail.output_num_avail = atomic_read(&effects->out_count); pr_debug("%s: write buf avail: %d, read buf avail: %d\n", diff --git a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c index a15fd87c7be8..bd2a8b219fb3 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c +++ b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c @@ -302,6 +302,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_aac_config *aac_config; struct msm_audio_aac_config32 aac_config_32; + memset(&aac_config_32, 0, sizeof(aac_config_32)); + aac_config = (struct msm_audio_aac_config *)audio->codec_cfg; aac_config_32.format = aac_config->format; aac_config_32.audio_object = aac_config->audio_object; diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c index 884fbbb828b2..0ab245106c4d 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c @@ -2032,6 +2032,7 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, audio->buf_cfg.frames_per_buf); mutex_lock(&audio->lock); + memset(&cfg_32, 0, sizeof(cfg_32)); cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable; cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf; if (copy_to_user((void *)arg, &cfg_32, diff --git a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c index 8d96b99d8f84..711867f80566 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c +++ b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c @@ -217,6 +217,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, struct msm_audio_wmapro_config *wmapro_config; struct msm_audio_wmapro_config32 wmapro_config_32; + memset(&wmapro_config_32, 0, sizeof(wmapro_config_32)); + wmapro_config = (struct msm_audio_wmapro_config *)audio->codec_cfg; wmapro_config_32.armdatareqthr = wmapro_config->armdatareqthr; diff --git a/drivers/misc/qcom/qdsp6v2/evrc_in.c b/drivers/misc/qcom/qdsp6v2/evrc_in.c index 2f931be226c6..aab8e27c0094 100644 --- a/drivers/misc/qcom/qdsp6v2/evrc_in.c +++ b/drivers/misc/qcom/qdsp6v2/evrc_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-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 @@ -224,6 +224,8 @@ static long evrc_in_compat_ioctl(struct file *file, struct msm_audio_evrc_enc_config32 cfg_32; struct msm_audio_evrc_enc_config *enc_cfg; + memset(&cfg_32, 0, sizeof(cfg_32)); + enc_cfg = audio->enc_cfg; cfg_32.cdma_rate = enc_cfg->cdma_rate; cfg_32.min_bit_rate = enc_cfg->min_bit_rate; diff --git a/drivers/misc/qcom/qdsp6v2/qcelp_in.c b/drivers/misc/qcom/qdsp6v2/qcelp_in.c index b5d5ad113722..aabf5d33a507 100644 --- a/drivers/misc/qcom/qdsp6v2/qcelp_in.c +++ b/drivers/misc/qcom/qdsp6v2/qcelp_in.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-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 @@ -225,6 +225,8 @@ static long qcelp_in_compat_ioctl(struct file *file, struct msm_audio_qcelp_enc_config32 cfg_32; struct msm_audio_qcelp_enc_config *enc_cfg; + memset(&cfg_32, 0, sizeof(cfg_32)); + enc_cfg = (struct msm_audio_qcelp_enc_config *)audio->enc_cfg; cfg_32.cdma_rate = enc_cfg->cdma_rate; cfg_32.min_bit_rate = enc_cfg->min_bit_rate; From c50276f0723ea73563e42f6278260b86d0ec97b0 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Mon, 29 Aug 2016 17:31:10 -0700 Subject: [PATCH 162/203] UPSTREAM: Input: powermate - fix oops with malicious USB descriptors The powermate driver expects at least one valid USB endpoint in its probe function. If given malicious descriptors that specify 0 for the number of endpoints, it will crash. Validate the number of endpoints on the interface before using them. The full report for this issue can be found here: http://seclists.org/bugtraq/2016/Mar/85 BUG: 28242610 Reported-by: Ralf Spenneberg Signed-off-by: Josh Boyer Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Badhri Jagan Sridharan Change-Id: I1cb956a35f3bba73324240d5bd0a029f49d3c456 --- drivers/input/misc/powermate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 63b539d3daba..84909a12ff36 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -307,6 +307,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i int error = -ENOMEM; interface = intf->cur_altsetting; + if (interface->desc.bNumEndpoints < 1) + return -EINVAL; + endpoint = &interface->endpoint[0].desc; if (!usb_endpoint_is_int_in(endpoint)) return -EIO; From 48bc7b89fcfb4b5eb97c05fa23b4beda7566e9bd Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Mon, 29 Aug 2016 17:33:52 -0700 Subject: [PATCH 163/203] UPSTREAM: USB: cypress_m8: add endpoint sanity check commit c55aee1bf0e6b6feec8b2927b43f7a09a6d5f754 upstream. An attack using missing endpoints exists. CVE-2016-3137 BUG: 28242610 Signed-off-by: Oliver Neukum Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Badhri Jagan Sridharan Change-Id: I1cc7957a5924175d24f12fdc41162ece67c907e5 --- drivers/usb/serial/cypress_m8.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 01bf53392819..244acb1299a9 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -447,6 +447,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct cypress_private *priv; + if (!port->interrupt_out_urb || !port->interrupt_in_urb) { + dev_err(&port->dev, "required endpoint is missing\n"); + return -ENODEV; + } + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -606,12 +611,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) cypress_set_termios(tty, port, &priv->tmp_termios); /* setup the port and start reading from the device */ - if (!port->interrupt_in_urb) { - dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", - __func__); - return -1; - } - usb_fill_int_urb(port->interrupt_in_urb, serial->dev, usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, From 0fd99e19c96d1e4fc97aa643ec415160c0c0a205 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Tue, 30 Aug 2016 13:33:55 -0700 Subject: [PATCH 164/203] UPSTREAM: USB: mct_u232: add sanity checking in probe commit 4e9a0b05257f29cf4b75f3209243ed71614d062e upstream. An attack using the lack of sanity checking in probe is known. This patch checks for the existence of a second port. CVE-2016-3136 BUG: 28242610 Signed-off-by: Oliver Neukum [johan: add error message ] Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Badhri Jagan Sridharan Change-Id: I284ad648c2087c34a098d67e0cc6d948a568413c --- drivers/usb/serial/mct_u232.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index fd707d6a10e2..89726f702202 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -376,14 +376,21 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, static int mct_u232_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct mct_u232_private *priv; + /* check first to simplify error handling */ + if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) { + dev_err(&port->dev, "expected endpoint missing\n"); + return -ENODEV; + } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; /* Use second interrupt-in endpoint for reading. */ - priv->read_urb = port->serial->port[1]->interrupt_in_urb; + priv->read_urb = serial->port[1]->interrupt_in_urb; priv->read_urb->context = port; spin_lock_init(&priv->lock); From eeb85e407db9cac11d9153c797df1ee968bbc33c Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Tue, 30 Aug 2016 13:35:32 -0700 Subject: [PATCH 165/203] UPSTREAM: USB: usb_driver_claim_interface: add sanity checking commit 0b818e3956fc1ad976bee791eadcbb3b5fec5bfd upstream. Attacks that trick drivers into passing a NULL pointer to usb_driver_claim_interface() using forged descriptors are known. This thwarts them by sanity checking. BUG: 28242610 Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman Signed-off-by: Badhri Jagan Sridharan Change-Id: Ib43ec5edb156985a9db941785a313f6801df092a --- drivers/usb/core/driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 104bd3b738d9..9697b556c061 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -499,11 +499,15 @@ static int usb_unbind_interface(struct device *dev) int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) { - struct device *dev = &iface->dev; + struct device *dev; struct usb_device *udev; int retval = 0; int lpm_disable_error; + if (!iface) + return -ENODEV; + + dev = &iface->dev; if (dev->driver) return -EBUSY; From 1d44322203c0bfbd3c524e22bdf6392808e3f40e Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Tue, 30 Aug 2016 13:37:07 -0700 Subject: [PATCH 166/203] UPSTREAM: USB: iowarrior: fix oops with malicious USB descriptors commit 4ec0ef3a82125efc36173062a50624550a900ae0 upstream. The iowarrior driver expects at least one valid endpoint. If given malicious descriptors that specify 0 for the number of endpoints, it will crash in the probe function. Ensure there is at least one endpoint on the interface before using it. The full report of this issue can be found here: http://seclists.org/bugtraq/2016/Mar/87 BUG: 28242610 Reported-by: Ralf Spenneberg Signed-off-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Badhri Jagan Sridharan Change-Id: If5161c23928e9ef77cb3359cba9b36622b1908df --- drivers/usb/misc/iowarrior.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index c6bfd13f6c92..1950e87b4219 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -787,6 +787,12 @@ static int iowarrior_probe(struct usb_interface *interface, iface_desc = interface->cur_altsetting; dev->product_id = le16_to_cpu(udev->descriptor.idProduct); + if (iface_desc->desc.bNumEndpoints < 1) { + dev_err(&interface->dev, "Invalid number of endpoints\n"); + retval = -EINVAL; + goto error; + } + /* set up the endpoint information */ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; From 2ad4ad015d8829b0b1580a702035ba566fb99505 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Tue, 30 Aug 2016 13:39:02 -0700 Subject: [PATCH 167/203] UPSTREAM: USB: cdc-acm: more sanity checking commit 8835ba4a39cf53f705417b3b3a94eb067673f2c9 upstream. An attack has become available which pretends to be a quirky device circumventing normal sanity checks and crashes the kernel by an insufficient number of interfaces. This patch adds a check to the code path for quirky devices. BUG: 28242610 Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman Signed-off-by: Badhri Jagan Sridharan Change-Id: I9a5f7f3c704b65e866335054f470451fcfae9d1c --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7d8c3d4ede20..14ffcd3f4e98 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1108,6 +1108,9 @@ static int acm_probe(struct usb_interface *intf, if (quirks == NO_UNION_NORMAL) { data_interface = usb_ifnum_to_if(usb_dev, 1); control_interface = usb_ifnum_to_if(usb_dev, 0); + /* we would crash */ + if (!data_interface || !control_interface) + return -ENODEV; goto skip_normal_probe; } From d28fdfacd6532eaa9151f76ee25436448b8a68d0 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Sep 2016 14:03:45 +0100 Subject: [PATCH 168/203] KEYS: Fix short sprintf buffer in /proc/keys show function Fix a short sprintf buffer in proc_keys_show(). If the gcc stack protector is turned on, this can cause a panic due to stack corruption. The problem is that xbuf[] is not big enough to hold a 64-bit timeout rendered as weeks: (gdb) p 0xffffffffffffffffULL/(60*60*24*7) $2 = 30500568904943 That's 14 chars plus NUL, not 11 chars plus NUL. Expand the buffer to 16 chars. I think the unpatched code apparently works if the stack-protector is not enabled because on a 32-bit machine the buffer won't be overflowed and on a 64-bit machine there's a 64-bit aligned pointer at one side and an int that isn't checked again on the other side. The panic incurred looks something like: Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81352ebe CPU: 0 PID: 1692 Comm: reproducer Not tainted 4.7.2-201.fc24.x86_64 #1 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 0000000000000086 00000000fbbd2679 ffff8800a044bc00 ffffffff813d941f ffffffff81a28d58 ffff8800a044bc98 ffff8800a044bc88 ffffffff811b2cb6 ffff880000000010 ffff8800a044bc98 ffff8800a044bc30 00000000fbbd2679 Call Trace: [] dump_stack+0x63/0x84 [] panic+0xde/0x22a [] ? proc_keys_show+0x3ce/0x3d0 [] __stack_chk_fail+0x19/0x30 [] proc_keys_show+0x3ce/0x3d0 [] ? key_validate+0x50/0x50 [] ? key_default_cmp+0x20/0x20 [] seq_read+0x2cc/0x390 [] proc_reg_read+0x42/0x70 [] __vfs_read+0x37/0x150 [] ? security_file_permission+0xa0/0xc0 [] vfs_read+0x96/0x130 [] SyS_read+0x55/0xc0 [] entry_SYSCALL_64_fastpath+0x1a/0xa4 Change-Id: I0787d5a38c730ecb75d3c08f28f0ab36295d59e7 Reported-by: Ondrej Kozina Signed-off-by: David Howells Tested-by: Ondrej Kozina Signed-off-by: engstk --- security/keys/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/proc.c b/security/keys/proc.c index 972eeb336b81..9962535ef9ad 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -187,7 +187,7 @@ static int proc_keys_show(struct seq_file *m, void *v) struct timespec now; unsigned long timo; key_ref_t key_ref, skey_ref; - char xbuf[12]; + char xbuf[16]; int rc; struct keyring_search_context ctx = { From 2e2cd1554e9982dad04246fdf6e5af445e6a06ba Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 13 Oct 2016 13:07:36 -0700 Subject: [PATCH 169/203] mm: remove gup_flags FOLL_WRITE games from __get_user_pages() commit 19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619 upstream. This is an ancient bug that was actually attempted to be fixed once (badly) by me eleven years ago in commit 4ceb5db9757a ("Fix get_user_pages() race for write access") but that was then undone due to problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug"). In the meantime, the s390 situation has long been fixed, and we can now fix it by checking the pte_dirty() bit properly (and do it better). The s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement software dirty bits") which made it into v3.9. Earlier kernels will have to look at the page state itself. Also, the VM has become more scalable, and what used a purely theoretical race back then has become easier to trigger. To fix it, we introduce a new internal FOLL_COW flag to mark the "yes, we already did a COW" rather than play racy games with FOLL_WRITE that is very fundamental, and then use the pte dirty flag to validate that the FOLL_COW flag is still valid. Change-Id: I83a08fd1f9c8928c0ed95286f737c27cc7811576 Reported-and-tested-by: Phil "not Paul" Oester Acked-by: Hugh Dickins Reviewed-by: Michal Hocko Cc: Andy Lutomirski Cc: Kees Cook Cc: Oleg Nesterov Cc: Willy Tarreau Cc: Nick Piggin Cc: Greg Thelen Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds [wt: s/gup.c/memory.c; s/follow_page_pte/follow_page_mask; s/faultin_page/__get_user_page] Signed-off-by: Willy Tarreau --- include/linux/mm.h | 1 + mm/gup.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 4a2a4a446fef..08d7b2103f3c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2034,6 +2034,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ +#define FOLL_COW 0x4000 /* internal GUP flag */ typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, void *data); diff --git a/mm/gup.c b/mm/gup.c index 377a5a796242..3cec4df06e6b 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -32,6 +32,16 @@ static struct page *no_page_table(struct vm_area_struct *vma, return NULL; } +/* + * FOLL_FORCE can write to even unwritable pte's, but only + * after we've gone through a COW cycle and they are dirty. + */ +static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) +{ + return pte_write(pte) || + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); +} + static struct page *follow_page_pte(struct vm_area_struct *vma, unsigned long address, pmd_t *pmd, unsigned int flags) { @@ -66,7 +76,7 @@ static struct page *follow_page_pte(struct vm_area_struct *vma, } if ((flags & FOLL_NUMA) && pte_numa(pte)) goto no_page; - if ((flags & FOLL_WRITE) && !pte_write(pte)) { + if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) { pte_unmap_unlock(ptep, ptl); return NULL; } @@ -315,7 +325,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, * reCOWed by userspace write). */ if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE)) - *flags &= ~FOLL_WRITE; + *flags |= FOLL_COW; return 0; } From 8f246c9dd17c1c2d50aa1341ca643ea21c018c6f Mon Sep 17 00:00:00 2001 From: Agrawal Ashish Date: Mon, 11 Jan 2016 22:48:16 +0530 Subject: [PATCH 170/203] qcacld-2.0: Dont include ext caps in Assoc request if AP doesn't support prima to qcacld-2.0 propagation Some AP doesn't announce Extended Capabilities IE in Probe Response. Device should not send extended Capabilities if AP doesn't support. Change-Id: I53215b866cb90f4addf45e3b6ed8af435eb57842 CRs-Fixed: 930199 --- .../CORE/MAC/src/include/parserApi.h | 1 + .../CORE/MAC/src/pe/include/limSession.h | 1 + .../CORE/MAC/src/pe/lim/limPropExtsUtils.c | 5 ++++- .../MAC/src/pe/lim/limSendManagementFrames.c | 19 +++++++++++-------- .../CORE/SYS/legacy/src/utils/src/parserApi.c | 5 +++++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h index 072b09cb3b40..6184e10b27da 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h @@ -165,6 +165,7 @@ typedef struct sSirProbeRespBeacon tDot11fIEVHTCaps VHTCaps; tDot11fIEVHTOperation VHTOperation; tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEExtCap ExtCap; tDot11fIEOperatingMode OperatingMode; tANI_U8 WiderBWChanSwitchAnnPresent; tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h index c4bf4058daaf..e3809d2b1b6b 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h @@ -498,6 +498,7 @@ typedef struct sPESession // Added to Support BT-AMP /* Supported NSS is intersection of self and peer NSS */ bool supported_nss_1x1; bool add_bss_failed; + bool is_ext_caps_present; } tPESession, *tpPESession; /*------------------------------------------------------------------------- diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c index 4fa31061d6c0..047eb5b8cbf9 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-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. * @@ -225,6 +225,9 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, if (pBeaconStruct->countryInfoPresent) psessionEntry->countryInfoPresent = TRUE; } + /* Check if Extended caps are present in probe resp or not */ + if (pBeaconStruct->ExtCap.present) + psessionEntry->is_ext_caps_present = true; vos_mem_free(pBeaconStruct); return; } /****** end limExtractApCapability() ******/ diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c index 3a60c497eaa7..d775e7e6421a 100644 --- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -2054,11 +2054,11 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, vos_mem_set( ( tANI_U8* )pFrm, sizeof( tDot11fAssocRequest ), 0 ); - if (nAddIELen) { + if (nAddIELen && psessionEntry->is_ext_caps_present) { vos_mem_set(( tANI_U8* )&extractedExtCap, sizeof( tDot11fIEExtCap ), 0); nSirStatus = lim_strip_extcap_update_struct(pMac, pAddIE, - &nAddIELen, - &extractedExtCap ); + &nAddIELen, + &extractedExtCap ); if(eSIR_SUCCESS != nSirStatus ) { extractedExtCapFlag = eANI_BOOLEAN_FALSE; @@ -2074,7 +2074,8 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, extractedExtCapFlag = lim_is_ext_cap_ie_present(p_ext_cap); } } else { - limLog(pMac, LOG1, FL("No additional IE for Assoc Request")); + limLog(pMac, LOG1, + FL("No addn IE or peer dosen't support addnIE for Assoc Req")); extractedExtCapFlag = eANI_BOOLEAN_FALSE; } @@ -2215,8 +2216,8 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, isVHTEnabled = eANI_BOOLEAN_TRUE; } #endif - - PopulateDot11fExtCap( pMac, isVHTEnabled, &pFrm->ExtCap, psessionEntry); + if (psessionEntry->is_ext_caps_present) + PopulateDot11fExtCap( pMac, isVHTEnabled, &pFrm->ExtCap, psessionEntry); #if defined WLAN_FEATURE_VOWIFI_11R if (psessionEntry->pLimJoinReq->is11Rconnection) @@ -2685,8 +2686,9 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, limLog( pMac, LOG1, FL("Populate VHT IEs in Re-Assoc Request")); PopulateDot11fVHTCaps( pMac, psessionEntry, &frm.VHTCaps ); isVHTEnabled = eANI_BOOLEAN_TRUE; - PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); } + if (psessionEntry->is_ext_caps_present) + PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); #endif nStatus = dot11fGetPackedReAssocRequestSize( pMac, &frm, &nPayload ); @@ -3117,7 +3119,8 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, } #endif - PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); + if (psessionEntry->is_ext_caps_present) + PopulateDot11fExtCap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); nStatus = dot11fGetPackedReAssocRequestSize( pMac, &frm, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c index 8b9070d03a2d..a9ad11acd3ec 100644 --- a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c @@ -3681,6 +3681,11 @@ sirParseBeaconIE(tpAniSirGlobal pMac, pBeaconStruct->Vendor1IEPresent = pBies->Vendor1IE.present; pBeaconStruct->Vendor2IEPresent = pBies->Vendor2IE.present; pBeaconStruct->Vendor3IEPresent = pBies->Vendor3IE.present; + if (pBies->ExtCap.present) { + pBeaconStruct->ExtCap.present = 1; + vos_mem_copy( &pBeaconStruct->ExtCap, &pBies->ExtCap, + sizeof(tDot11fIEExtCap)); + } vos_mem_free(pBies); return eSIR_SUCCESS; From 06c9e00fb2c672c1bda281288e1d667988f41134 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 7 Jun 2016 08:51:34 -0700 Subject: [PATCH 171/203] qcacld-2.0: Validate CCXBEACONREQ IE fields Validate CCXBEACONREQ IE fields. Change-Id: Ie64a642abdd7923e91801186aa5743094a739fc9 CRs-Fixed: 1025185 --- .../qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c index 5a8f7215ca40..0e34590da5c6 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -4127,7 +4127,8 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, tCsrEseBeaconReq *pEseBcnReq) { tANI_U8 *inPtr = pValue; - int tempInt = 0; + uint8_t input = 0; + uint32_t tempInt = 0; int j = 0, i = 0, v = 0; char buf[32]; @@ -4150,11 +4151,11 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; - v = kstrtos32(buf, 10, &tempInt); + v = kstrtou8(buf, 10, &input); if (v < 0) return -EINVAL; - tempInt = VOS_MIN(tempInt, SIR_ESE_MAX_MEAS_IE_REQS); - pEseBcnReq->numBcnReqIe = tempInt; + input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS); + pEseBcnReq->numBcnReqIe = input; hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe); @@ -4175,24 +4176,24 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, v = sscanf(inPtr, "%31s ", buf); if (1 != v) return -EINVAL; - v = kstrtos32(buf, 10, &tempInt); + v = kstrtou32(buf, 10, &tempInt); if (v < 0) return -EINVAL; switch (i) { case 0: /* Measurement token */ - if (tempInt <= 0) { + if (!tempInt) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid Measurement Token(%d)", tempInt); + "Invalid Measurement Token: %d", tempInt); return -EINVAL; } pEseBcnReq->bcnReq[j].measurementToken = tempInt; break; case 1: /* Channel number */ - if ((tempInt <= 0) || + if ((!tempInt) || (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid Channel Number(%d)", tempInt); + "Invalid Channel Number: %d", tempInt); return -EINVAL; } pEseBcnReq->bcnReq[j].channel = tempInt; @@ -4202,19 +4203,18 @@ static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue, if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt); + "Invalid Scan Mode: %d Expected{0|1|2}", tempInt); return -EINVAL; } pEseBcnReq->bcnReq[j].scanMode= tempInt; break; case 3: /* Measurement duration */ - if (((tempInt <= 0) && + if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) || - ((tempInt < 0) && - (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE))) { + ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Invalid Measurement Duration(%d)", tempInt); + "Invalid Measurement Duration: %d", tempInt); return -EINVAL; } pEseBcnReq->bcnReq[j].measurementDuration = tempInt; From 665615d8f69b060f04482242107c9013976187ff Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Sat, 30 Jul 2016 18:08:09 +0530 Subject: [PATCH 172/203] qcacld-2.0: Fix scan failure issue due to stale PE session If roaming is initiated by firmware, after getting the candidate list the CSR will start preauth with the candidates and thus preauth will be the active command in SME. Now if at the same time connect is issued from supplicant, HDD will queue disconnect cmd in SME queue and wait for disconnect to get complete for 2 sec. Now there is a chance that channel change along with preauth timeout can take more than 2 secs. In this scenareo the disconnect will timeout in HDD and will return connect failure to supplicant. Next supplicant will issue disconnect which is ignored by HDD as disconnect is already been queued in SME. Now if supplicant again sends the connect command, as part of connect command CSR will remove the disconnect command from the SME queue and queue this connect command. On preauth timeout the preauth state machine checks if disconnect is queued and if it is queued it will abort preauth. But in this case disconnect is removed by the connect request and thus preauth retry continues and if preauth is success handoff will be queued in SME queue. Now the connect request is processed and if this connect request's BSSID is same as the BSSID of the roam candidate, as all the CSR states for this BSSID session indicate roaming, instead of join it will try to reassociate and continue changing the CSR states again. Eventually this connect will fail. Next the handoff command is processed and as part of handoff it will try to cleanup original session, but as CSR states are changed by connect request the original session is not cleaned up properly. This results in stale PE session entry which does not allow the scan to be sent to firmware, returning the cached results and thus 0 scan results. To fix this: - Increase the WLAN_WAIT_TIME_DISCONNECT to 5 sec to make sure all sessions are cleaned up before allowing the new connect to proceed. - Increase the priority of preauth scans. Change-Id: Id7cc1e6f3c31df8a8c8955eb3ff48cb60e5b5ab2 CRs-Fixed: 1048394 --- drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h | 2 +- drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h index 65aed10d6466..72df9c0bb848 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h @@ -115,7 +115,7 @@ #define ACS_IN_PROGRESS (0) /** Maximum time(ms)to wait for disconnect to complete **/ -#define WLAN_WAIT_TIME_DISCONNECT 2000 +#define WLAN_WAIT_TIME_DISCONNECT 5000 #define WLAN_WAIT_TIME_STATS 800 #define WLAN_WAIT_TIME_POWER 800 #define WLAN_WAIT_TIME_COUNTRY 1000 diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c index 630625f6482a..869cdb8d18ea 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c @@ -8848,7 +8848,7 @@ VOS_STATUS wma_start_scan(tp_wma_handle wma_handle, cmd->min_rest_time = WMA_ROAM_PREAUTH_REST_TIME; cmd->max_rest_time = WMA_ROAM_PREAUTH_REST_TIME; cmd->max_scan_time = WMA_ROAM_PREAUTH_MAX_SCAN_TIME; - cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH; + cmd->scan_priority = WMI_SCAN_PRIORITY_VERY_HIGH; adf_os_spin_lock_bh(&wma_handle->roam_preauth_lock); cmd->scan_id = ( (cmd->scan_id & WMA_MAX_SCAN_ID) | WMA_HOST_ROAM_SCAN_REQID_PREFIX); From 3f17bca12e2c1124b96b42ff70105a0131ae5272 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 10 Aug 2016 11:51:03 +0530 Subject: [PATCH 173/203] qcacld-2.0: Discard pktlog message for invalid msdu id During HOST AP offload case fw is sending pktlog tx info with invalid MSDU id. This will result in invalid de-reference tx descriptor. Discard pktlog msg for invalid msdu id to handle the above scenario. Change-Id: I2dae296fd0c63c916b6470567ded672cf73bf435 CRs-Fixed: 1052684 --- .../qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c | 21 +++++++++++-------- .../CORE/UTILS/PKTLOG/pktlog_internal.c | 7 ++++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c index 3bc0ae1f4222..fa296a21c96c 100644 --- a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -312,7 +312,7 @@ pktlog_enable(struct ol_softc *scn, int32_t log_state) if (!scn) { printk("%s: Invalid scn context\n", __func__); ASSERT(0); - return -1; + return A_ERROR; } txrx_pdev = scn->pdev_txrx_handle; @@ -326,7 +326,7 @@ pktlog_enable(struct ol_softc *scn, int32_t log_state) if (!pl_dev) { printk("%s: Invalid pktlog context\n", __func__); ASSERT(0); - return -1; + return A_ERROR; } pl_info = pl_dev->pl_info; @@ -345,7 +345,7 @@ pktlog_enable(struct ol_softc *scn, int32_t log_state) if (!pl_info->buf) { printk("%s: pktlog buf alloc failed\n", __func__); ASSERT(0); - return -1; + return A_ERROR; } } @@ -365,12 +365,13 @@ pktlog_enable(struct ol_softc *scn, int32_t log_state) if (wdi_pktlog_subscribe(txrx_pdev, log_state)) { printk("Unable to subscribe to the WDI %s\n", __func__); - return -1; + return A_ERROR; } /* WMI command to enable pktlog on the firmware */ if (pktlog_enable_tgt(scn, log_state)) { - printk("Device cannot be enabled, %s\n", __func__); - return -1; + adf_os_print("Device cannot be enabled, %s\n", __func__); + wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state); + return A_ERROR; } else { pl_dev->tgt_pktlog_enabled = true; } @@ -378,13 +379,15 @@ pktlog_enable(struct ol_softc *scn, int32_t log_state) pl_dev->pl_funcs->pktlog_disable(scn); pl_dev->tgt_pktlog_enabled = false; if (wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state)) { - printk("Cannot unsubscribe pktlog from the WDI\n"); - return -1; + adf_os_print("%s: Cannot unsubscribe pktlog from the WDI\n", + __func__); + return A_ERROR; } } pl_info->log_state = log_state; return 0; + } int diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c index 8f9042fe2ef0..5f50f77c97aa 100644 --- a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c @@ -375,6 +375,11 @@ process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, >> TX_DESC_ID_HIGH_SHIFT); msdu_id += 1; } + if (tx_desc_id >= ol_cfg_target_tx_credit(txrx_pdev->ctrl_pdev)) { + adf_os_print("%s: drop due to invalid msdu id = %x\n", + __func__, tx_desc_id); + return A_ERROR; + } tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); adf_os_assert(tx_desc); netbuf = tx_desc->netbuf; @@ -385,7 +390,7 @@ process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, if (len < (2 * IEEE80211_ADDR_LEN)) { adf_os_print("TX frame does not have a valid address\n"); - return -1; + return A_ERROR; } /* Adding header information for the TX data frames */ vdev_id = (u_int8_t)(*(htt_tx_desc + From 4d7bedf0615712e03cb662395985010140e8b8a1 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Sun, 23 Oct 2016 12:12:39 +0900 Subject: [PATCH 174/203] gpio_keys: call oem_check_force_dump_key() later Calling this on every input causes un-wanted latency Signed-off-by: Park Ju Hyung --- drivers/input/keyboard/gpio_keys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a9b64e9a2eb0..47011bb0a594 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -343,8 +343,6 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) state = (__gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; - oem_check_force_dump_key(button->code,state); - if (type == EV_ABS) { if (state) input_event(input, type, button->code, button->value); @@ -352,6 +350,8 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) input_event(input, type, button->code, !!state); } input_sync(input); + + oem_check_force_dump_key(button->code,state); } static void gpio_keys_gpio_work_func(struct work_struct *work) From e5e6c0a562c15d4a184c3e46501f39fef71e6b5a Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 1 Aug 2016 13:05:30 -0700 Subject: [PATCH 175/203] BACKPORT: f2fs: add a max block check for get_data_block_bmap (cherry pick from commit 179448bfe4cd201e98e728391c6b01b25c849fe8) This patch adds a max block check for get_data_block_bmap. Trinity test program will send a block number as parameter into ioctl_fibmap, which will be used in get_node_path(), when the block number large than f2fs max blocks, it will trigger kernel bug. Signed-off-by: Yunlei He Signed-off-by: Xue Liu [Jaegeuk Kim: fix missing condition, pointed by Chao Yu] Signed-off-by: Jaegeuk Kim Bug: 28271368 (cherry pick from commit 3c714201e02ec08652be4b9544a5267e79bde3a9) Change-Id: Ifea304827826d8e85873532a49998f481b3873fd Signed-off-by: Dennis Cagle --- fs/f2fs/data.c | 11 ++++++++++- fs/f2fs/f2fs.h | 1 + fs/f2fs/super.c | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index f988b01b6f89..b813373bb5e1 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -724,6 +724,15 @@ static int get_data_block(struct inode *inode, sector_t iblock, return __get_data_block(inode, iblock, bh_result, create, false); } +static int get_data_block_bmap(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + /* Block number less than F2FS MAX BLOCKS */ + if (unlikely(iblock >= max_file_size(0))) + return -EFBIG; + return __get_data_block(inode, iblock, bh_result, create, false); +} + static int get_data_block_fiemap(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { @@ -1153,7 +1162,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) if (f2fs_has_inline_data(inode)) return 0; - return generic_block_bmap(mapping, block, get_data_block); + return generic_block_bmap(mapping, block, get_data_block_bmap); } const struct address_space_operations f2fs_dblock_aops = { diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 8171e80b2ee9..2f73c62e58db 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1246,6 +1246,7 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode) /* * super.c */ +loff_t max_file_size(unsigned bits); int f2fs_sync_fs(struct super_block *, int); extern __printf(3, 4) void f2fs_msg(struct super_block *, const char *, const char *, ...); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 41d6f700f4ee..50cb921ecede 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -752,7 +752,7 @@ static const struct export_operations f2fs_export_ops = { .get_parent = f2fs_get_parent, }; -static loff_t max_file_size(unsigned bits) +loff_t max_file_size(unsigned bits) { loff_t result = (DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS); loff_t leaf_count = ADDRS_PER_BLOCK; From 03bef1df83d1b3317ff085f94783043e5bd32a41 Mon Sep 17 00:00:00 2001 From: engstk Date: Wed, 23 Nov 2016 11:56:56 +0000 Subject: [PATCH 176/203] fs: merge OP3T updates Signed-off-by: engstk --- fs/f2fs/checkpoint.c | 2 +- fs/fs_struct.c | 1 + fs/namei.c | 47 ++++++++++++++++++++++++++++++++------ fs/proc/generic.c | 8 +++++-- fs/sdcardfs/Kconfig | 5 ---- fs/sdcardfs/derived_perm.c | 2 +- fs/sdcardfs/inode.c | 23 ++++++++----------- fs/sdcardfs/lookup.c | 40 +++++++++++++++----------------- fs/sdcardfs/main.c | 26 +++------------------ fs/sdcardfs/packagelist.c | 2 +- fs/sdcardfs/sdcardfs.h | 8 +------ fs/sdcardfs/super.c | 18 +++------------ fs/sdcardfs/version.h | 8 +------ include/linux/fs.h | 24 ++++++++++++++++--- include/linux/namei.h | 1 - mm/mmap.c | 3 +++ 16 files changed, 111 insertions(+), 107 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index dd10a031c052..097dea0add1a 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -820,7 +820,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) if (!get_pages(sbi, F2FS_WRITEBACK)) break; - io_schedule(); + io_schedule_timeout(msecs_to_jiffies(5000)); } finish_wait(&sbi->cp_wait, &wait); } diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 7dca743b2ce1..005dcb401369 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -127,6 +127,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) } return fs; } +EXPORT_SYMBOL_GPL(copy_fs_struct); int unshare_fs_struct(void) { diff --git a/fs/namei.c b/fs/namei.c index 16fdb29f7908..4e7e8cea4b02 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -39,6 +39,10 @@ #include "internal.h" #include "mount.h" +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09 , Support sdcardfs filesystem in kernel */ +#include "sdcardfs/sdcardfs.h" +#endif /* [Feb-1997 T. Schoebel-Theuer] * Fundamental changes in the pathname lookup mechanisms (namei) @@ -3734,7 +3738,12 @@ EXPORT_SYMBOL(vfs_unlink); * writeout happening, and we don't want to prevent access to the directory * while waiting on the I/O. */ +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ +long do_unlinkat(int dfd, const char __user *pathname, bool propagate) +#else static long do_unlinkat(int dfd, const char __user *pathname) +#endif { int error; struct filename *name; @@ -3743,8 +3752,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) struct inode *inode = NULL; struct inode *delegated_inode = NULL; unsigned int lookup_flags = 0; +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ char *path_buf = NULL; char *propagate_path = NULL; +#endif retry: name = user_path_parent(dfd, pathname, &nd, lookup_flags); if (IS_ERR(name)) @@ -3769,12 +3781,20 @@ static long do_unlinkat(int dfd, const char __user *pathname) inode = dentry->d_inode; if (d_is_negative(dentry)) goto slashes; - - if (inode->i_sb->s_op->unlink_callback) { - path_buf = kmalloc(PATH_MAX, GFP_KERNEL); - propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ + if (inode->i_sb->s_op->unlink_callback && propagate) { + struct inode *lower_inode = inode; + while (lower_inode->i_op->get_lower_inode) { + if (inode->i_sb->s_magic == SDCARDFS_SUPER_MAGIC + && SDCARDFS_SB(inode->i_sb)->options.label) { + path_buf = kmalloc(PATH_MAX, GFP_KERNEL); + propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX); + } + lower_inode = lower_inode->i_op->get_lower_inode(lower_inode); + } } - +#endif ihold(inode); error = security_path_unlink(&nd.path, dentry); if (error) @@ -3784,10 +3804,13 @@ static long do_unlinkat(int dfd, const char __user *pathname) dput(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - if (path_buf && !error) { - inode->i_sb->s_op->unlink_callback(inode->i_sb, propagate_path); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ + if (path_buf && !IS_ERR(path_buf) && !error && propagate) { + inode->i_sb->s_op->unlink_callback(inode, propagate_path); kfree(path_buf); } +#endif if (inode) iput(inode); /* truncate the inode here */ inode = NULL; @@ -3825,12 +3848,22 @@ SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag) if (flag & AT_REMOVEDIR) return do_rmdir(dfd, pathname); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ + return do_unlinkat(dfd, pathname, true); +#else return do_unlinkat(dfd, pathname); +#endif } SYSCALL_DEFINE1(unlink, const char __user *, pathname) { +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ + return do_unlinkat(AT_FDCWD, pathname, true); +#else return do_unlinkat(AT_FDCWD, pathname); +#endif } int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 7b95b6a9cf89..312657bfb801 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -576,8 +576,12 @@ EXPORT_SYMBOL_GPL(proc_get_parent_data); void proc_remove(struct proc_dir_entry *de) { - if (de) - remove_proc_subtree(de->name, de->parent); + int rc; + if (de){ + rc = remove_proc_subtree(de->name, de->parent); + if(rc < 0) + pr_info("proc_remove %s fail\n",de->name); + } } EXPORT_SYMBOL(proc_remove); diff --git a/fs/sdcardfs/Kconfig b/fs/sdcardfs/Kconfig index d1b1af1562e2..1498fa906f1a 100644 --- a/fs/sdcardfs/Kconfig +++ b/fs/sdcardfs/Kconfig @@ -11,11 +11,6 @@ config SDCARD_FS_FADV_NOACTIVE help Sdcardfs supports fadvise noactive mode. -config SDCARD_FS_CI_SEARCH - tristate "sdcardfs case-insensitive search support" - depends on SDCARD_FS - default y - config SDCARD_FS_XATTR bool "Sdcardfs extended attribute" default y diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c index 65cc66e5b335..b5f9d0f8219c 100644 --- a/fs/sdcardfs/derived_perm.c +++ b/fs/sdcardfs/derived_perm.c @@ -212,7 +212,7 @@ int is_obbpath_invalid(struct dentry *dent) * regarding the uninitialized obb, refer to the sdcardfs_mkdir() */ spin_lock(&di->lock); if(di->orig_path.dentry) { - if(!di->lower_path.dentry) { + if(!di->lower_path.dentry) { ret = 1; } else { path_get(&di->lower_path); diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 77c0b1cfe60b..2709d8a59518 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -279,9 +279,9 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode struct path lower_path; const struct cred *saved_cred = NULL; struct sdcardfs_inode_info *pi = SDCARDFS_I(dir); - int touch_err = 0; struct fs_struct *saved_fs; struct fs_struct *copied_fs; + int touch_err = 0; if(!check_caller_access_to_name(dir, dentry->d_name.name)) { printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" @@ -789,21 +789,10 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia) * the lower level. */ if (ia->ia_valid & ATTR_SIZE) { - loff_t oldsize; err = inode_newsize_ok(inode, ia->ia_size); if (err) goto out; - /* This code from truncate_setsize(). We need to add spin_lock - * to avoid race condition with fsstack_copy_inode_size() */ - oldsize = i_size_read(inode); - if (sizeof(ia->ia_size) > sizeof(long)) - spin_lock(&inode->i_lock); - i_size_write(inode, ia->ia_size); - if (sizeof(ia->ia_size) > sizeof(long)) - spin_unlock(&inode->i_lock); - if (ia->ia_size > oldsize) - pagecache_isize_extended(inode, oldsize, ia->ia_size); - truncate_pagecache(inode, ia->ia_size); + truncate_setsize(inode, ia->ia_size); } /* @@ -842,6 +831,11 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia) return err; } +static struct inode *sdcardfs_get_lower_inode(struct inode *i) +{ + return sdcardfs_lower_inode(i); +} + const struct inode_operations sdcardfs_symlink_iops = { .permission = sdcardfs_permission, .setattr = sdcardfs_setattr, @@ -851,6 +845,7 @@ const struct inode_operations sdcardfs_symlink_iops = { .listxattr = sdcardfs_listxattr, .removexattr = sdcardfs_removexattr, #endif // SDCARD_FS_XATTR + .get_lower_inode = sdcardfs_get_lower_inode, /* XXX Following operations are implemented, * but FUSE(sdcard) or FAT does not support them * These methods are *NOT* perfectly tested. @@ -876,6 +871,7 @@ const struct inode_operations sdcardfs_dir_iops = { .listxattr = sdcardfs_listxattr, .removexattr = sdcardfs_removexattr, #endif // SDCARD_FS_XATTR + .get_lower_inode = sdcardfs_get_lower_inode, /* XXX Following operations are implemented, * but FUSE(sdcard) or FAT does not support them * These methods are *NOT* perfectly tested. @@ -895,4 +891,5 @@ const struct inode_operations sdcardfs_main_iops = { .listxattr = sdcardfs_listxattr, .removexattr = sdcardfs_removexattr, #endif // SDCARDFS_XATTR + .get_lower_inode = sdcardfs_get_lower_inode, }; diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index 60187a3cc87a..425058ec8cba 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -232,30 +232,28 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry, /* Use vfs_path_lookup to check if the dentry exists or not */ err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, - &lower_path); + &lower_path); /* check for other cases */ - if (sbi->options.lower_fs == LOWER_FS_EXT4) { - if (err == -ENOENT) { - struct dentry *child; - struct dentry *match = NULL; - spin_lock(&lower_dir_dentry->d_lock); - list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) { - if (child && child->d_inode) { - if (strcasecmp(child->d_name.name, name)==0) { - match = dget(child); - break; - } + if (err == -ENOENT) { + struct dentry *child; + struct dentry *match = NULL; + spin_lock(&lower_dir_dentry->d_lock); + list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) { + if (child && child->d_inode) { + if (strcasecmp(child->d_name.name, name)==0) { + match = dget(child); + break; } } - spin_unlock(&lower_dir_dentry->d_lock); - if (match) { - err = vfs_path_lookup(lower_dir_dentry, - lower_dir_mnt, - match->d_name.name, 0, - &lower_path); - dput(match); - } + } + spin_unlock(&lower_dir_dentry->d_lock); + if (match) { + err = vfs_path_lookup(lower_dir_dentry, + lower_dir_mnt, + match->d_name.name, 0, + &lower_path); + dput(match); } } @@ -268,7 +266,7 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry, if(need_graft_path(dentry)) { /* setup_obb_dentry() - * The lower_path will be stored to the dentry's orig_path + * The lower_path will be stored to the dentry's orig_path * and the base obbpath will be copyed to the lower_path variable. * if an error returned, there's no change in the lower_path * returns: -ERRNO if error (0: no error) */ diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 0cd0bd0f45e4..dbfb9b52e5d2 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -46,7 +46,6 @@ static const match_table_t sdcardfs_tokens = { {Opt_gid, "gid=%u"}, {Opt_userid, "userid=%u"}, {Opt_debug, "debug"}, - {Opt_lower_fs, "lower_fs=%s"}, {Opt_reserved_mb, "reserved_mb=%u"}, {Opt_mask, "mask=%o"}, {Opt_multi_user, "multi_user"}, @@ -70,10 +69,8 @@ static int parse_options(struct super_block *sb, char *options, int silent, /* by default, userid is 0, gid is AID_EVERYBODY */ opts->gid = AID_EVERYBODY; opts->userid = 0; - /* by default, we use LOWER_FS_EXT4 as lower fs type */ - opts->lower_fs = LOWER_FS_EXT4; - /* by default, 20MB is reserved */ - opts->reserved_mb = 20; + /* by default, 0MB is reserved */ + opts->reserved_mb = 0; /* by default, mask is 0 */ opts->mask = 0; /* by default, multi_user is false */ @@ -117,20 +114,6 @@ static int parse_options(struct super_block *sb, char *options, int silent, goto invalid_option; opts->userid = option; break; - case Opt_lower_fs: - string_option = match_strdup(&args[0]); - if (!string_option) - return -ENOMEM; - if (!strcmp("ext4", string_option)) { - opts->lower_fs = LOWER_FS_EXT4; - } else if (!strcmp("fat", string_option)) { - opts->lower_fs = LOWER_FS_FAT; - } else { - kfree(string_option); - goto invalid_option; - } - kfree(string_option); - break; case Opt_reserved_mb: if (match_int(&args[0], &option)) return 0; @@ -286,10 +269,7 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name, sb->s_time_gran = 1; sb->s_magic = SDCARDFS_SUPER_MAGIC; - if (sb_info->options.type != TYPE_NONE) - sb->s_op = &sdcardfs_multimount_sops; - else - sb->s_op = &sdcardfs_sops; + sb->s_op = &sdcardfs_sops; /* see comment next to the definition of sdcardfs_d_alloc_root */ sb->s_root = sdcardfs_d_alloc_root(sb); diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c index d4dc0cb54712..0119430d67c0 100644 --- a/fs/sdcardfs/packagelist.c +++ b/fs/sdcardfs/packagelist.c @@ -237,7 +237,7 @@ static int packagelist_reader(void *thread_data) while (!kthread_should_stop()) { if (signal_pending(current)) { - msleep(100); + ssleep(1); continue; } diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 210bc1623a33..b8b68e191473 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -123,11 +123,6 @@ typedef enum { PERM_ANDROID_MEDIA, } perm_t; -typedef enum { - LOWER_FS_EXT4, - LOWER_FS_FAT, -} lower_fs_t; - typedef enum { TYPE_NONE, TYPE_DEFAULT, @@ -150,7 +145,6 @@ extern const struct inode_operations sdcardfs_main_iops; extern const struct inode_operations sdcardfs_dir_iops; extern const struct inode_operations sdcardfs_symlink_iops; extern const struct super_operations sdcardfs_sops; -extern const struct super_operations sdcardfs_multimount_sops; extern const struct dentry_operations sdcardfs_ci_dops; extern const struct address_space_operations sdcardfs_aops, sdcardfs_dummy_aops; extern const struct vm_operations_struct sdcardfs_vm_ops; @@ -165,6 +159,7 @@ extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, struct path *lower_path); +extern long sdcardfs_propagate_unlink(struct inode *parent, char* pathname); #ifdef SDCARD_FS_XATTR extern int sdcardfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); @@ -208,7 +203,6 @@ struct sdcardfs_mount_options { gid_t fs_low_gid; gid_t gid; userid_t userid; - lower_fs_t lower_fs; unsigned int reserved_mb; mode_t mask; bool multi_user; diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index 4723b5eda5a0..3d3e082766a6 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -193,14 +193,14 @@ void sdcardfs_destroy_inode_cache(void) * code can actually succeed and won't leave tasks that need handling. */ -static long sdcardfs_propagate_lookup(struct super_block *sb, char* pathname) { +long sdcardfs_propagate_unlink(struct inode *parent, char* pathname) { long ret = 0; char *propagate_path = NULL; struct sdcardfs_sb_info *sbi; struct path sibling_path; const struct cred *saved_cred = NULL; - sbi = SDCARDFS_SB(sb); + sbi = SDCARDFS_SB(parent->i_sb); propagate_path = kmalloc(PATH_MAX, GFP_KERNEL); OVERRIDE_ROOT_CRED(saved_cred); if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_DEFAULT) { @@ -281,17 +281,5 @@ const struct super_operations sdcardfs_sops = { .alloc_inode = sdcardfs_alloc_inode, .destroy_inode = sdcardfs_destroy_inode, .drop_inode = generic_delete_inode, -}; - -const struct super_operations sdcardfs_multimount_sops = { - .put_super = sdcardfs_put_super, - .statfs = sdcardfs_statfs, - .remount_fs = sdcardfs_remount_fs, - .evict_inode = sdcardfs_evict_inode, - .umount_begin = sdcardfs_umount_begin, - .show_options = sdcardfs_show_options, - .alloc_inode = sdcardfs_alloc_inode, - .destroy_inode = sdcardfs_destroy_inode, - .drop_inode = generic_delete_inode, - .unlink_callback = sdcardfs_propagate_lookup, + .unlink_callback = sdcardfs_propagate_unlink, }; diff --git a/fs/sdcardfs/version.h b/fs/sdcardfs/version.h index e96685d701d4..ee2b8dd9e079 100644 --- a/fs/sdcardfs/version.h +++ b/fs/sdcardfs/version.h @@ -23,12 +23,6 @@ * 2015.11.24 : Release Version 3.1.0 * - Add unlink_callback(), get_lower_inode() * - Add mount option type, label - * 2016.02. : Release Version 3.2.0 - * - remove get_lower_inode(), make sdcardfs use only unlink_callback() - * - modify name hash creation because it's different with vfat's - * - obb will be used only multi_user option is enabled - * - modify sdcardfs_setattr because it changes i_size without spinlock - * it can make race condition with fsstack_copy_inode_size() */ -#define SDCARDFS_VERSION "3.2.0" +#define SDCARDFS_VERSION "3.1.0" diff --git a/include/linux/fs.h b/include/linux/fs.h index 908198eedde1..371aaf7e65a7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -133,11 +133,14 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* Has write method(s) */ #define FMODE_CAN_WRITE ((__force fmode_t)0x40000) +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ /* File hasn't page cache and can't be mmaped, for stackable filesystem */ -#define FMODE_NONMAPPABLE ((__force fmode_t)0x400000) +#define FMODE_NONMAPPABLE ((__force fmode_t)0x400000) /* File page don't need to be cached, for stackable filesystem's lower file */ -#define FMODE_NONCACHEABLE ((__force fmode_t)0x800000) +#define FMODE_NONCACHEABLE ((__force fmode_t)0x800000) +#endif /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) @@ -1433,6 +1436,10 @@ extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); extern int vfs_whiteout(struct inode *, struct dentry *); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ +extern long do_unlinkat(int, const char __user *, bool); +#endif /* * VFS dentry helper functions. @@ -1527,7 +1534,10 @@ struct file_operations { long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); int (*show_fdinfo)(struct seq_file *m, struct file *f); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ struct file* (*get_lower_file)(struct file *f); +#endif }; struct inode_operations { @@ -1567,6 +1577,11 @@ struct inode_operations { /* WARNING: probably going away soon, do not use! */ int (*dentry_open)(struct dentry *, struct file *, const struct cred *); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ + struct inode * (*get_lower_inode)(struct inode *); +#endif + } ____cacheline_aligned; ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, @@ -1608,7 +1623,10 @@ struct super_operations { int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t); long (*nr_cached_objects)(struct super_block *, int); long (*free_cached_objects)(struct super_block *, long, int); - long (*unlink_callback)(struct super_block *, char *); +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ + long (*unlink_callback)(struct inode *, char *); +#endif }; /* diff --git a/include/linux/namei.h b/include/linux/namei.h index d80f3f874fa4..492de72560fa 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -55,7 +55,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_JUMPED 0x1000 #define LOOKUP_ROOT 0x2000 #define LOOKUP_EMPTY 0x4000 -#define LOOKUP_CASE_INSENSITIVE 0x8000 extern int user_path_at(int, const char __user *, unsigned, struct path *); extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty); diff --git a/mm/mmap.c b/mm/mmap.c index 16e54a011d3a..b18086f67437 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1276,8 +1276,11 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, *populate = 0; +#ifdef CONFIG_SDCARD_FS +/* liochen@filesystem, 2016/08/09, Support sdcardfs filesystem in kernel */ while (file && (file->f_mode & FMODE_NONMAPPABLE)) file = file->f_op->get_lower_file(file); +#endif #ifdef CONFIG_MSM_APP_SETTINGS if (use_app_setting) From 95b3a17de4fbf9ea0f3e176d7db4b02646c43a97 Mon Sep 17 00:00:00 2001 From: flar2 Date: Mon, 28 Nov 2016 13:55:24 -0500 Subject: [PATCH 177/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index eec40ccded9c..205074279879 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.28" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.29" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -3898,7 +3898,6 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set CONFIG_SDCARD_FS=y -CONFIG_SDCARD_FS_CI_SEARCH=y CONFIG_SDCARD_FS_XATTR=y CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set From 5ee953aea21ec235d38448874235ebb2076b0263 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 25 Sep 2015 16:30:08 +0100 Subject: [PATCH 178/203] KEYS: Fix race between key destruction and finding a keyring by name [ Upstream commit 94c4554ba07adbdde396748ee7ae01e86cf2d8d7 ] There appears to be a race between: (1) key_gc_unused_keys() which frees key->security and then calls keyring_destroy() to unlink the name from the name list (2) find_keyring_by_name() which calls key_permission(), thus accessing key->security, on a key before checking to see whether the key usage is 0 (ie. the key is dead and might be cleaned up). Fix this by calling ->destroy() before cleaning up the core key data - including key->security. Reported-by: Petr Matousek Signed-off-by: David Howells Signed-off-by: Sasha Levin --- security/keys/gc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/keys/gc.c b/security/keys/gc.c index c7952375ac53..39eac1fd5706 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -134,6 +134,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kdebug("- %u", key->serial); key_check(key); + /* Throw away the key data */ + if (key->type->destroy) + key->type->destroy(key); + security_key_free(key); /* deal with the user's key tracking and quota */ @@ -148,10 +152,6 @@ static noinline void key_gc_unused_keys(struct list_head *keys) if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) atomic_dec(&key->user->nikeys); - /* now throw away the key memory */ - if (key->type->destroy) - key->type->destroy(key); - key_user_put(key->user); kfree(key->description); From 1a8f29e7fe9e04f0f23d3fdf3848d99935ad9a43 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 15 Oct 2015 17:21:37 +0100 Subject: [PATCH 179/203] KEYS: Fix crash when attempt to garbage collect an uninstantiated keyring [ Upstream commit f05819df10d7b09f6d1eb6f8534a8f68e5a4fe61 ] The following sequence of commands: i=`keyctl add user a a @s` keyctl request2 keyring foo bar @t keyctl unlink $i @s tries to invoke an upcall to instantiate a keyring if one doesn't already exist by that name within the user's keyring set. However, if the upcall fails, the code sets keyring->type_data.reject_error to -ENOKEY or some other error code. When the key is garbage collected, the key destroy function is called unconditionally and keyring_destroy() uses list_empty() on keyring->type_data.link - which is in a union with reject_error. Subsequently, the kernel tries to unlink the keyring from the keyring names list - which oopses like this: BUG: unable to handle kernel paging request at 00000000ffffff8a IP: [] keyring_destroy+0x3d/0x88 ... Workqueue: events key_garbage_collector ... RIP: 0010:[] keyring_destroy+0x3d/0x88 RSP: 0018:ffff88003e2f3d30 EFLAGS: 00010203 RAX: 00000000ffffff82 RBX: ffff88003bf1a900 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 000000003bfc6901 RDI: ffffffff81a73a40 RBP: ffff88003e2f3d38 R08: 0000000000000152 R09: 0000000000000000 R10: ffff88003e2f3c18 R11: 000000000000865b R12: ffff88003bf1a900 R13: 0000000000000000 R14: ffff88003bf1a908 R15: ffff88003e2f4000 ... CR2: 00000000ffffff8a CR3: 000000003e3ec000 CR4: 00000000000006f0 ... Call Trace: [] key_gc_unused_keys.constprop.1+0x5d/0x10f [] key_garbage_collector+0x1fa/0x351 [] process_one_work+0x28e/0x547 [] worker_thread+0x26e/0x361 [] ? rescuer_thread+0x2a8/0x2a8 [] kthread+0xf3/0xfb [] ? kthread_create_on_node+0x1c2/0x1c2 [] ret_from_fork+0x3f/0x70 [] ? kthread_create_on_node+0x1c2/0x1c2 Note the value in RAX. This is a 32-bit representation of -ENOKEY. The solution is to only call ->destroy() if the key was successfully instantiated. Reported-by: Dmitry Vyukov Signed-off-by: David Howells Tested-by: Dmitry Vyukov Signed-off-by: Sasha Levin --- security/keys/gc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/security/keys/gc.c b/security/keys/gc.c index 39eac1fd5706..addf060399e0 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -134,8 +134,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kdebug("- %u", key->serial); key_check(key); - /* Throw away the key data */ - if (key->type->destroy) + /* Throw away the key data if the key is instantiated */ + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && + !test_bit(KEY_FLAG_NEGATIVE, &key->flags) && + key->type->destroy) key->type->destroy(key); security_key_free(key); From 5659fd3e6199cf09038fa4ffe37c2d1113bc6f95 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Nov 2015 21:36:31 +0000 Subject: [PATCH 180/203] KEYS: Fix handling of stored error in a negatively instantiated user key [ Upstream commit 096fe9eaea40a17e125569f9e657e34cdb6d73bd ] If a user key gets negatively instantiated, an error code is cached in the payload area. A negatively instantiated key may be then be positively instantiated by updating it with valid data. However, the ->update key type method must be aware that the error code may be there. The following may be used to trigger the bug in the user key type: keyctl request2 user user "" @u keyctl add user user "a" @u which manifests itself as: BUG: unable to handle kernel paging request at 00000000ffffff8a IP: [] __call_rcu.constprop.76+0x1f/0x280 kernel/rcu/tree.c:3046 PGD 7cc30067 PUD 0 Oops: 0002 [#1] SMP Modules linked in: CPU: 3 PID: 2644 Comm: a.out Not tainted 4.3.0+ #49 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 task: ffff88003ddea700 ti: ffff88003dd88000 task.ti: ffff88003dd88000 RIP: 0010:[] [] __call_rcu.constprop.76+0x1f/0x280 [] __call_rcu.constprop.76+0x1f/0x280 kernel/rcu/tree.c:3046 RSP: 0018:ffff88003dd8bdb0 EFLAGS: 00010246 RAX: 00000000ffffff82 RBX: 0000000000000000 RCX: 0000000000000001 RDX: ffffffff81e3fe40 RSI: 0000000000000000 RDI: 00000000ffffff82 RBP: ffff88003dd8bde0 R08: ffff88007d2d2da0 R09: 0000000000000000 R10: 0000000000000000 R11: ffff88003e8073c0 R12: 00000000ffffff82 R13: ffff88003dd8be68 R14: ffff88007d027600 R15: ffff88003ddea700 FS: 0000000000b92880(0063) GS:ffff88007fd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00000000ffffff8a CR3: 000000007cc5f000 CR4: 00000000000006e0 Stack: ffff88003dd8bdf0 ffffffff81160a8a 0000000000000000 00000000ffffff82 ffff88003dd8be68 ffff88007d027600 ffff88003dd8bdf0 ffffffff810a39e5 ffff88003dd8be20 ffffffff812a31ab ffff88007d027600 ffff88007d027620 Call Trace: [] kfree_call_rcu+0x15/0x20 kernel/rcu/tree.c:3136 [] user_update+0x8b/0xb0 security/keys/user_defined.c:129 [< inline >] __key_update security/keys/key.c:730 [] key_create_or_update+0x291/0x440 security/keys/key.c:908 [< inline >] SYSC_add_key security/keys/keyctl.c:125 [] SyS_add_key+0x101/0x1e0 security/keys/keyctl.c:60 [] entry_SYSCALL_64_fastpath+0x12/0x6a arch/x86/entry/entry_64.S:185 Note the error code (-ENOKEY) in EDX. A similar bug can be tripped by: keyctl request2 trusted user "" @u keyctl add trusted user "a" @u This should also affect encrypted keys - but that has to be correctly parameterised or it will fail with EINVAL before getting to the bit that will crashes. Reported-by: Dmitry Vyukov Signed-off-by: David Howells Acked-by: Mimi Zohar Signed-off-by: James Morris Signed-off-by: Sasha Levin --- security/keys/encrypted-keys/encrypted.c | 2 ++ security/keys/trusted.c | 5 ++++- security/keys/user_defined.c | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 7bed4ad7cd76..0a374a2ce030 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -845,6 +845,8 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) size_t datalen = prep->datalen; int ret = 0; + if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) + return -ENOKEY; if (datalen <= 0 || datalen > 32767 || !prep->data) return -EINVAL; diff --git a/security/keys/trusted.c b/security/keys/trusted.c index c0594cb07ada..aeb38f1a12e7 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -984,13 +984,16 @@ static void trusted_rcu_free(struct rcu_head *rcu) */ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) { - struct trusted_key_payload *p = key->payload.data; + struct trusted_key_payload *p; struct trusted_key_payload *new_p; struct trusted_key_options *new_o; size_t datalen = prep->datalen; char *datablob; int ret = 0; + if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) + return -ENOKEY; + p = key->payload.data; if (!p->migratable) return -EPERM; if (datalen <= 0 || datalen > 32767 || !prep->data) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 36b47bbd3d8c..7cf22260bdff 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -120,7 +120,10 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) if (ret == 0) { /* attach the new data, displacing the old */ - zap = key->payload.data; + if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) + zap = key->payload.data; + else + zap = NULL; rcu_assign_keypointer(key, upayload); key->expiry = 0; } From fef83685249d7a33015f1932309b6155619b48d5 Mon Sep 17 00:00:00 2001 From: Vladis Dronov Date: Tue, 1 Dec 2015 13:09:17 -0800 Subject: [PATCH 181/203] Input: aiptek - fix crash on detecting device without endpoints The aiptek driver crashes in aiptek_probe() when a specially crafted USB device without endpoints is detected. This fix adds a check that the device has proper configuration expected by the driver. Also an error return value is changed to more matching one in one of the error paths. Change-Id: I02fa4ffcbe9a71948947ef5baeb72632688d9d07 Reported-by: Ralf Spenneberg Signed-off-by: Vladis Dronov Signed-off-by: Dmitry Torokhov Signed-off-by: Francisco Franco --- drivers/input/tablet/aiptek.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index e7f966da6efa..78ca44840d60 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1819,6 +1819,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); + /* Verify that a device really has an endpoint */ + if (intf->altsetting[0].desc.bNumEndpoints < 1) { + dev_err(&intf->dev, + "interface has %d endpoints, but must have minimum 1\n", + intf->altsetting[0].desc.bNumEndpoints); + err = -EINVAL; + goto fail3; + } endpoint = &intf->altsetting[0].endpoint[0].desc; /* Go set up our URB, which is called when the tablet receives @@ -1861,6 +1869,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) if (i == ARRAY_SIZE(speeds)) { dev_info(&intf->dev, "Aiptek tried all speeds, no sane response\n"); + err = -EINVAL; goto fail3; } From 6a0a113983b8db9e8520acdd29253a7cf5df68ed Mon Sep 17 00:00:00 2001 From: AnilKumar Chimata Date: Wed, 10 Feb 2016 19:30:50 +0530 Subject: [PATCH 182/203] qseecom: Fix stack out of bounds issue While copying the request buffer to temporary buffer large size of request buffer is copied which leads to accessing stack out of its size. <3>[ 24.265116] ================================================================== <3>[ 24.271333] BUG: KASAN: stack-out-of-bounds in memcpy+0x28/0x54 at addr ffffffc05890b744 <3>[ 24.279388] Read of size 4096 by task vold/362 <0>[ 24.283819] page:ffffffba494e3790 count:0 mapcount:0 mapping: (null) index:0x0 <0>[ 24.291800] flags: 0x0() <1>[ 24.294318] page dumped because: kasan: bad access detected <6>[ 24.299884] CPU: 1 PID: 362 Comm: vold Not tainted 3.18.20-g7bb9977 #1 <6>[ 24.299895] Hardware name: Qualcomm Technologies, Inc. MSM8937-PMI8950 MTP (DT) <0>[ 24.299904] Call trace: <6>[ 24.302314] [] dump_backtrace+0x0/0x284 <6>[ 24.302329] [] show_stack+0x10/0x1c <6>[ 24.302345] [] dump_stack+0x74/0xfc <6>[ 24.302362] [] kasan_report+0x3b4/0x504 <6>[ 24.302376] [] __asan_loadN+0x20/0x14c <6>[ 24.302389] [] memcpy+0x24/0x54 <6>[ 24.302406] [] qseecom_scm_call2+0xec0/0x1c94 <6>[ 24.302421] [] qseecom_scm_call.constprop.41+0x64/0x7c <6>[ 24.302436] [] qseecom_create_key+0x304/0x680 <6>[ 24.302450] [] qseecom_ioctl+0x2fb8/0x4944 <6>[ 24.302464] [] do_vfs_ioctl+0x9c8/0xb0c <6>[ 24.302476] [] SyS_ioctl+0x58/0x8c <3>[ 24.302484] Memory state around the buggy address: <3>[ 24.307080] ffffffc05890b680: f2 f2 f2 f2 00 04 f4 f4 f2 f2 f2 f2 00 00 00 00 <3>[ 24.314283] ffffffc05890b700: 04 f4 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00 <3>[ 24.321488] >ffffffc05890b780: 00 f4 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00 <3>[ 24.328690] ^ <3>[ 24.332164] ffffffc05890b800: 00 00 04 f4 f3 f3 f3 f3 00 00 00 00 00 00 00 00 <3>[ 24.339369] ffffffc05890b880: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 <3>[ 24.346571] ================================================================== <4>[ 24.353777] Disabling lock debugging due to kernel taint <3>[ 24.533597] QSEECOM: __qseecom_process_incomplete_cmd: fail:resp res= -65,app_id = 0,lstr = 12288 <6>[ 24.541522] get_ice_device_from_storage_type: found ice device ffffffc05bd61f80 <3>[ 24.545296] ================================================================== <3>[ 24.551503] BUG: KASAN: stack-out-of-bounds in memcpy+0x28/0x54 at addr ffffffc05890b7c4 <3>[ 24.559558] Read of size 4096 by task vold/362 <0>[ 24.563989] page:ffffffba494e3790 count:0 mapcount:0 mapping: (null) index:0x0 <0>[ 24.571966] flags: 0x0() <1>[ 24.574485] page dumped because: kasan: bad access detected <6>[ 24.580050] CPU: 1 PID: 362 Comm: vold Tainted: G B 3.18.20-g7bb9977 #1 <6>[ 24.580060] Hardware name: Qualcomm Technologies, Inc. MSM8937-PMI8950 MTP (DT) <0>[ 24.580069] Call trace: <6>[ 24.582482] [] dump_backtrace+0x0/0x284 <6>[ 24.582497] [] show_stack+0x10/0x1c <6>[ 24.582513] [] dump_stack+0x74/0xfc <6>[ 24.582529] [] kasan_report+0x3b4/0x504 <6>[ 24.582543] [] __asan_loadN+0x20/0x14c <6>[ 24.582556] [] memcpy+0x24/0x54 <6>[ 24.582574] [] qseecom_scm_call2+0x1068/0x1c94 <6>[ 24.582588] [] qseecom_scm_call.constprop.41+0x64/0x7c <6>[ 24.582603] [] __qseecom_set_clear_ce_key+0xf4/0x2fc <6>[ 24.582616] [] qseecom_create_key+0x4fc/0x680 <6>[ 24.582630] [] qseecom_ioctl+0x2fb8/0x4944 <6>[ 24.582644] [] do_vfs_ioctl+0x9c8/0xb0c <6>[ 24.582656] [] SyS_ioctl+0x58/0x8c <3>[ 24.582664] Memory state around the buggy address: <3>[ 24.587250] ffffffc05890b700: 04 f4 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00 <3>[ 24.594453] ffffffc05890b780: 00 f4 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00 <3>[ 24.601656] >ffffffc05890b800: 00 00 04 f4 f3 f3 f3 f3 00 00 00 00 00 00 00 00 <3>[ 24.608860] ^ <3>[ 24.612596] ffffffc05890b880: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 <3>[ 24.619802] ffffffc05890b900: 04 f4 f4 f4 f2 f2 f2 f2 00 f4 f4 f4 f2 f2 f2 f2 <3>[ 24.627001] ================================================================== <6>[ 24.799462] get_ice_device_from_storage_type: found ice device ffffffc05bd61f80 <3>[ 24.803065] QSEECOM: qseecom_create_key: Set the key successfully Change-Id: Id683067d29531686dafe94114ba3329f87292923 Signed-off-by: AnilKumar Chimata Signed-off-by: Francisco Franco --- drivers/misc/qseecom.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 7f81ba4e12b0..f324af07ff75 100755 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -639,7 +639,9 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, if (!tzbuf) return -ENOMEM; memset(tzbuf, 0, tzbuflen); - memcpy(tzbuf, req_buf + sizeof(uint32_t), tzbuflen); + memcpy(tzbuf, req_buf + sizeof(uint32_t), + (sizeof(struct qseecom_key_generate_ireq) - + sizeof(uint32_t))); dmac_flush_range(tzbuf, tzbuf + tzbuflen); smc_id = TZ_OS_KS_GEN_KEY_ID; desc.arginfo = TZ_OS_KS_GEN_KEY_ID_PARAM_ID; @@ -661,7 +663,9 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, return -ENOMEM; } memset(tzbuf, 0, tzbuflen); - memcpy(tzbuf, req_buf + sizeof(uint32_t), tzbuflen); + memcpy(tzbuf, req_buf + sizeof(uint32_t), + (sizeof(struct qseecom_key_delete_ireq) - + sizeof(uint32_t))); dmac_flush_range(tzbuf, tzbuf + tzbuflen); smc_id = TZ_OS_KS_DEL_KEY_ID; desc.arginfo = TZ_OS_KS_DEL_KEY_ID_PARAM_ID; @@ -683,7 +687,9 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, return -ENOMEM; } memset(tzbuf, 0, tzbuflen); - memcpy(tzbuf, req_buf + sizeof(uint32_t), tzbuflen); + memcpy(tzbuf, req_buf + sizeof(uint32_t), + (sizeof(struct qseecom_key_select_ireq) - + sizeof(uint32_t))); dmac_flush_range(tzbuf, tzbuf + tzbuflen); smc_id = TZ_OS_KS_SET_PIPE_KEY_ID; desc.arginfo = TZ_OS_KS_SET_PIPE_KEY_ID_PARAM_ID; @@ -705,7 +711,9 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, return -ENOMEM; } memset(tzbuf, 0, tzbuflen); - memcpy(tzbuf, req_buf + sizeof(uint32_t), tzbuflen); + memcpy(tzbuf, req_buf + sizeof(uint32_t), (sizeof + (struct qseecom_key_userinfo_update_ireq) - + sizeof(uint32_t))); dmac_flush_range(tzbuf, tzbuf + tzbuflen); smc_id = TZ_OS_KS_UPDATE_KEY_ID; desc.arginfo = TZ_OS_KS_UPDATE_KEY_ID_PARAM_ID; From 7c230da90bc2e4da114588e2dbc2b2bca6532b21 Mon Sep 17 00:00:00 2001 From: Sivanesan Rajapupathi Date: Fri, 26 Feb 2016 09:54:44 -0500 Subject: [PATCH 183/203] crypto: msm: crypto driver performance improvement To minimize spinlock, the qce50 client is assumed that it can only issue request to qce50 driver one at a time. After a request is issued to qce50 from qcrypto. Without waiting for completion, other requests can still be issued until the maximum limit of outstanding requests in qce50 reaches. To cut down the chance of udp socket receive buffer overflow the following schemes are provided - The number of bunched requests in qce50 is based on the data length of the current request to cut down delay for smaller packets. In turn, with smaller delay, the number of completed requests to process in seq_response() completion function is less. The scheduling of qcrypto requests are changed from least use to round robin. This way, the distribution of requests to each engine is more even. As the result, reordering of completed requests will be less. Completed requests to handle in completion callback is less at a time. Change-Id: I723bac2f9427cddb5248101c9ac3f2b595ad0379 Acked-by: Che-Min Hsieh Signed-off-by: Sivanesan Rajapupathi Signed-off-by: Francisco Franco --- drivers/crypto/msm/qce50.c | 114 +++++++------ drivers/crypto/msm/qce50.h | 3 +- drivers/crypto/msm/qcrypto.c | 303 +++++++++++++++++++++++++---------- 3 files changed, 289 insertions(+), 131 deletions(-) diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 36949f4b3f14..eb0e8fa1fbb2 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -1,6 +1,6 @@ /* Qualcomm Crypto Engine driver. * - * 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 @@ -69,7 +69,7 @@ static LIST_HEAD(qce50_bam_list); /* Max number of request supported */ #define MAX_QCE_BAM_REQ 8 /* Interrupt flag will be set for every SET_INTR_AT_REQ request */ -#define SET_INTR_AT_REQ (MAX_QCE_BAM_REQ - 2) +#define SET_INTR_AT_REQ (MAX_QCE_BAM_REQ / 2) /* To create extra request space to hold dummy request */ #define MAX_QCE_BAM_REQ_WITH_DUMMY_REQ (MAX_QCE_BAM_REQ + 1) /* Allocate the memory for MAX_QCE_BAM_REQ + 1 (for dummy request) */ @@ -84,6 +84,12 @@ static LIST_HEAD(qce50_bam_list); /* Index to point the dummy request */ #define DUMMY_REQ_INDEX MAX_QCE_BAM_REQ +enum qce_owner { + QCE_OWNER_NONE = 0, + QCE_OWNER_CLIENT = 1, + QCE_OWNER_TIMEOUT = 2 +}; + struct dummy_request { struct qce_sha_req sreq; uint8_t *in_buf; @@ -133,9 +139,8 @@ struct qce_device { struct ce_bam_info ce_bam_info; struct ce_request_info ce_request_info[MAX_QCE_ALLOC_BAM_REQ]; unsigned int ce_request_index; - spinlock_t lock; - spinlock_t sps_lock; - unsigned int no_of_queued_req; + enum qce_owner owner; + atomic_t no_of_queued_req; struct timer_list timer; struct dummy_request dummyreq; unsigned int mode; @@ -144,6 +149,7 @@ struct qce_device { struct qce_driver_stats qce_stats; atomic_t bunch_cmd_seq; atomic_t last_intr_seq; + bool cadence_flag; }; static void print_notify_debug(struct sps_event_notify *notify); @@ -2477,7 +2483,6 @@ static int _qce_sps_add_cmd(struct qce_device *pce_dev, uint32_t flag, static int _qce_sps_transfer(struct qce_device *pce_dev, int req_info) { int rc = 0; - unsigned long flags; struct ce_sps_data *pce_sps_data; pce_sps_data = &pce_dev->ce_request_info[req_info].ce_sps; @@ -2489,7 +2494,6 @@ static int _qce_sps_transfer(struct qce_device *pce_dev, int req_info) (unsigned int) req_info)); _qce_dump_descr_fifos_dbg(pce_dev, req_info); - spin_lock_irqsave(&pce_dev->sps_lock, flags); if (pce_sps_data->in_transfer.iovec_count) { rc = sps_transfer(pce_dev->ce_bam_info.consumer.pipe, &pce_sps_data->in_transfer); @@ -2508,7 +2512,6 @@ static int _qce_sps_transfer(struct qce_device *pce_dev, int req_info) ret: if (rc) _qce_dump_descr_fifos(pce_dev, req_info); - spin_unlock_irqrestore(&pce_dev->sps_lock, flags); return rc; } @@ -2892,23 +2895,20 @@ static inline int qce_alloc_req_info(struct qce_device *pce_dev) } } pr_warn("pcedev %d no reqs available no_of_queued_req %d\n", - pce_dev->dev_no, pce_dev->no_of_queued_req); + pce_dev->dev_no, atomic_read( + &pce_dev->no_of_queued_req)); return -EBUSY; } static inline void qce_free_req_info(struct qce_device *pce_dev, int req_info, bool is_complete) { - unsigned long flags; - - spin_lock_irqsave(&pce_dev->lock, flags); pce_dev->ce_request_info[req_info].xfer_type = QCE_XFER_TYPE_LAST; if (xchg(&pce_dev->ce_request_info[req_info].in_use, false) == true) { if (req_info < MAX_QCE_BAM_REQ && is_complete) - pce_dev->no_of_queued_req--; + atomic_dec(&pce_dev->no_of_queued_req); } else pr_warn("request info %d free already\n", req_info); - spin_unlock_irqrestore(&pce_dev->lock, flags); } static void print_notify_debug(struct sps_event_notify *notify) @@ -2955,7 +2955,6 @@ static void qce_multireq_timeout(unsigned long data) { struct qce_device *pce_dev = (struct qce_device *)data; int ret = 0; - unsigned long flags; int last_seq; last_seq = atomic_read(&pce_dev->bunch_cmd_seq); @@ -2966,27 +2965,29 @@ static void qce_multireq_timeout(unsigned long data) return; } /* last bunch mode command time out */ - spin_lock_irqsave(&pce_dev->lock, flags); + if (cmpxchg(&pce_dev->owner, QCE_OWNER_NONE, QCE_OWNER_TIMEOUT) + != QCE_OWNER_NONE) { + mod_timer(&(pce_dev->timer), (jiffies + DELAY_IN_JIFFIES)); + return; + } del_timer(&(pce_dev->timer)); pce_dev->mode = IN_INTERRUPT_MODE; pce_dev->qce_stats.no_of_timeouts++; pr_debug("pcedev %d mode switch to INTR\n", pce_dev->dev_no); - spin_unlock_irqrestore(&pce_dev->lock, flags); ret = qce_dummy_req(pce_dev); if (ret) pr_warn("pcedev %d: Failed to insert dummy req\n", pce_dev->dev_no); + cmpxchg(&pce_dev->owner, QCE_OWNER_TIMEOUT, QCE_OWNER_NONE); } void qce_get_driver_stats(void *handle) { - unsigned long flags; struct qce_device *pce_dev = (struct qce_device *) handle; if (!_qce50_disp_stats) return; - spin_lock_irqsave(&pce_dev->lock, flags); pr_info("Engine %d timeout occuured %d\n", pce_dev->dev_no, pce_dev->qce_stats.no_of_timeouts); pr_info("Engine %d dummy request inserted %d\n", pce_dev->dev_no, @@ -2996,20 +2997,16 @@ void qce_get_driver_stats(void *handle) else pr_info("Engine %d is in INTERRUPT MODE\n", pce_dev->dev_no); pr_info("Engine %d outstanding request %d\n", pce_dev->dev_no, - pce_dev->no_of_queued_req); - spin_unlock_irqrestore(&pce_dev->lock, flags); + atomic_read(&pce_dev->no_of_queued_req)); } EXPORT_SYMBOL(qce_get_driver_stats); void qce_clear_driver_stats(void *handle) { - unsigned long flags; struct qce_device *pce_dev = (struct qce_device *) handle; - spin_lock_irqsave(&pce_dev->lock, flags); pce_dev->qce_stats.no_of_timeouts = 0; pce_dev->qce_stats.no_of_dummy_reqs = 0; - spin_unlock_irqrestore(&pce_dev->lock, flags); } EXPORT_SYMBOL(qce_clear_driver_stats); @@ -3021,7 +3018,6 @@ static void _sps_producer_callback(struct sps_event_notify *notify) unsigned int req_info; struct ce_sps_data *pce_sps_data; struct ce_request_info *preq_info; - unsigned long flags; print_notify_debug(notify); @@ -3050,10 +3046,8 @@ static void _sps_producer_callback(struct sps_event_notify *notify) &pce_sps_data->out_transfer); _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); - spin_lock_irqsave(&pce_dev->sps_lock, flags); rc = sps_transfer(pce_dev->ce_bam_info.producer.pipe, &pce_sps_data->out_transfer); - spin_unlock_irqrestore(&pce_dev->sps_lock, flags); if (rc) { pr_err("sps_xfr() fail (producer pipe=0x%lx) rc = %d\n", (uintptr_t)pce_dev->ce_bam_info.producer.pipe, @@ -4527,18 +4521,27 @@ static int qce_dummy_req(struct qce_device *pce_dev) static int select_mode(struct qce_device *pce_dev, struct ce_request_info *preq_info) { - unsigned long flags; struct ce_sps_data *pce_sps_data = &preq_info->ce_sps; + unsigned int no_of_queued_req; + unsigned int cadence; if (!pce_dev->no_get_around) { _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); return 0; } - spin_lock_irqsave(&pce_dev->lock, flags); - pce_dev->no_of_queued_req++; + /* + * claim ownership of device + */ +again: + if (cmpxchg(&pce_dev->owner, QCE_OWNER_NONE, QCE_OWNER_CLIENT) + != QCE_OWNER_NONE) { + ndelay(40); + goto again; + } + no_of_queued_req = atomic_inc_return(&pce_dev->no_of_queued_req); if (pce_dev->mode == IN_INTERRUPT_MODE) { - if (pce_dev->no_of_queued_req >= MAX_BUNCH_MODE_REQ) { + if (no_of_queued_req >= MAX_BUNCH_MODE_REQ) { pce_dev->mode = IN_BUNCH_MODE; pr_debug("pcedev %d mode switch to BUNCH\n", pce_dev->dev_no); @@ -4555,17 +4558,21 @@ static int select_mode(struct qce_device *pce_dev, } } else { pce_dev->intr_cadence++; - if (pce_dev->intr_cadence >= SET_INTR_AT_REQ) { + cadence = (preq_info->req_len >> 7) + 1; + if (cadence > SET_INTR_AT_REQ) + cadence = SET_INTR_AT_REQ; + if (pce_dev->intr_cadence < cadence || ((pce_dev->intr_cadence + == cadence) && pce_dev->cadence_flag)) + atomic_inc(&pce_dev->bunch_cmd_seq); + else { _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); pce_dev->intr_cadence = 0; atomic_set(&pce_dev->bunch_cmd_seq, 0); atomic_set(&pce_dev->last_intr_seq, 0); - } else { - atomic_inc(&pce_dev->bunch_cmd_seq); + pce_dev->cadence_flag = ~pce_dev->cadence_flag; } } - spin_unlock_irqrestore(&pce_dev->lock, flags); return 0; } @@ -4675,6 +4682,7 @@ static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_AEAD; + preq_info->req_len = totallen_in; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -4712,6 +4720,7 @@ static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req) SPS_IOVEC_FLAG_INT); pce_sps_data->producer_state = QCE_PIPE_STATE_COMP; } + rc = _qce_sps_transfer(pce_dev, req_info); } else { if (_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen, &pce_sps_data->in_transfer)) @@ -4758,8 +4767,9 @@ static int _qce_aead_ccm_req(void *handle, struct qce_req *q_req) _qce_ccm_get_around_output(pce_dev, preq_info, q_req->dir); select_mode(pce_dev, preq_info); + rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); } - rc = _qce_sps_transfer(pce_dev, req_info); if (rc) goto bad; return 0; @@ -4949,6 +4959,7 @@ int qce_aead_req(void *handle, struct qce_req *q_req) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_AEAD; + preq_info->req_len = totallen; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -4989,6 +5000,7 @@ int qce_aead_req(void *handle, struct qce_req *q_req) SPS_IOVEC_FLAG_INT); pce_sps_data->producer_state = QCE_PIPE_STATE_COMP; } + rc = _qce_sps_transfer(pce_dev, req_info); } else { if (_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen, &pce_sps_data->in_transfer)) @@ -5028,8 +5040,9 @@ int qce_aead_req(void *handle, struct qce_req *q_req) pce_sps_data->producer_state = QCE_PIPE_STATE_IDLE; } select_mode(pce_dev, preq_info); + rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); } - rc = _qce_sps_transfer(pce_dev, req_info); if (rc) goto bad; return 0; @@ -5123,6 +5136,7 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_CIPHERING; + preq_info->req_len = areq->nbytes; _qce_sps_iovec_count_init(pce_dev, req_info); if (pce_dev->support_cmd_dscr) @@ -5154,8 +5168,8 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) } select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc) goto bad; @@ -5227,6 +5241,7 @@ int qce_process_sha_req(void *handle, struct qce_sha_req *sreq) /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_HASHING; + preq_info->req_len = sreq->size; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -5255,11 +5270,14 @@ int qce_process_sha_req(void *handle, struct qce_sha_req *sreq) &pce_sps_data->out_transfer)) goto bad; - if (is_dummy) + if (is_dummy) { _qce_set_flag(&pce_sps_data->out_transfer, SPS_IOVEC_FLAG_INT); - else + rc = _qce_sps_transfer(pce_dev, req_info); + } else { select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); + } if (rc) goto bad; return 0; @@ -5347,6 +5365,7 @@ int qce_f8_req(void *handle, struct qce_f8_req *req, /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_F8; + preq_info->req_len = req->data_len; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -5372,8 +5391,8 @@ int qce_f8_req(void *handle, struct qce_f8_req *req, &pce_sps_data->out_transfer); select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc) goto bad; return 0; @@ -5462,6 +5481,7 @@ int qce_f8_multi_pkt_req(void *handle, struct qce_f8_multi_pkt_req *mreq, /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_F8; + preq_info->req_len = total; _qce_sps_iovec_count_init(pce_dev, req_info); @@ -5486,8 +5506,8 @@ int qce_f8_multi_pkt_req(void *handle, struct qce_f8_multi_pkt_req *mreq, &pce_sps_data->out_transfer); select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc == 0) return 0; @@ -5548,6 +5568,7 @@ int qce_f9_req(void *handle, struct qce_f9_req *req, void *cookie, /* setup xfer type for producer callback handling */ preq_info->xfer_type = QCE_XFER_F9; + preq_info->req_len = req->msize; _qce_sps_iovec_count_init(pce_dev, req_info); if (pce_dev->support_cmd_dscr) @@ -5567,8 +5588,8 @@ int qce_f9_req(void *handle, struct qce_f9_req *req, void *cookie, &pce_sps_data->out_transfer); select_mode(pce_dev, preq_info); - rc = _qce_sps_transfer(pce_dev, req_info); + cmpxchg(&pce_dev->owner, QCE_OWNER_CLIENT, QCE_OWNER_NONE); if (rc) goto bad; return 0; @@ -5933,9 +5954,7 @@ void *qce_open(struct platform_device *pdev, int *rc) qce_setup_ce_sps_data(pce_dev); qce_disable_clk(pce_dev); setup_dummy_req(pce_dev); - spin_lock_init(&pce_dev->lock); - spin_lock_init(&pce_dev->sps_lock); - pce_dev->no_of_queued_req = 0; + atomic_set(&pce_dev->no_of_queued_req, 0); pce_dev->mode = IN_INTERRUPT_MODE; init_timer(&(pce_dev->timer)); pce_dev->timer.function = qce_multireq_timeout; @@ -5944,6 +5963,7 @@ void *qce_open(struct platform_device *pdev, int *rc) pce_dev->intr_cadence = 0; pce_dev->dev_no = pcedev_no; pcedev_no++; + pce_dev->owner = QCE_OWNER_NONE; mutex_unlock(&qce_iomap_mutex); return pce_dev; err: diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h index 19f6edf21878..d3d558b22988 100644 --- a/drivers/crypto/msm/qce50.h +++ b/drivers/crypto/msm/qce50.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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 @@ -228,6 +228,7 @@ struct ce_request_info { dma_addr_t phy_ota_src; dma_addr_t phy_ota_dst; unsigned int ota_size; + unsigned int req_len; }; struct qce_driver_stats { diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index ddd3812c74b1..be3d3fcdebf5 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -51,7 +52,7 @@ #include "qce.h" #define DEBUG_MAX_FNAME 16 -#define DEBUG_MAX_RW_BUF 2048 +#define DEBUG_MAX_RW_BUF 4096 #define QCRYPTO_BIG_NUMBER 9999999 /* a big number */ /* @@ -131,6 +132,7 @@ struct qcrypto_req_control { struct crypto_engine *pce; struct crypto_async_request *req; struct qcrypto_resp_ctx *arsp; + int res; /* execution result */ }; struct crypto_engine { @@ -167,8 +169,14 @@ struct crypto_engine { unsigned int max_req; struct qcrypto_req_control *preq_pool; atomic_t req_count; + bool issue_req; /* an request is being issued to qce */ + bool first_engine; /* this engine is the first engine or not */ + unsigned int irq_cpu; /* the cpu running the irq of this engine */ + unsigned int max_req_used; /* debug stats */ }; +#define MAX_SMP_CPU 8 + struct crypto_priv { /* CE features supported by target device*/ struct msm_ce_hw_support platform_support; @@ -208,21 +216,37 @@ struct crypto_priv { enum resp_workq_sts sched_resp_workq_status; enum req_processing_sts ce_req_proc_sts; int cpu_getting_irqs_frm_first_ce; + struct crypto_engine *first_engine; + struct crypto_engine *scheduled_eng; /* last engine scheduled */ + + /* debug stats */ + unsigned no_avail; + unsigned resp_stop; + unsigned resp_start; + unsigned max_qlen; + unsigned int queue_work_eng3; + unsigned int queue_work_not_eng3; + unsigned int queue_work_not_eng3_nz; + unsigned int max_resp_qlen; + unsigned int max_reorder_cnt; + unsigned int cpu_req[MAX_SMP_CPU+1]; }; static struct crypto_priv qcrypto_dev; static struct crypto_engine *_qcrypto_static_assign_engine( struct crypto_priv *cp); static struct crypto_engine *_avail_eng(struct crypto_priv *cp); - static struct qcrypto_req_control *qcrypto_alloc_req_control( struct crypto_engine *pce) { int i; struct qcrypto_req_control *pqcrypto_req_control = pce->preq_pool; + unsigned int req_count; for (i = 0; i < pce->max_req; i++) { if (xchg(&pqcrypto_req_control->in_use, true) == false) { - atomic_inc(&pce->req_count); + req_count = atomic_inc_return(&pce->req_count); + if (req_count > pce->max_req_used) + pce->max_req_used = req_count; return pqcrypto_req_control; } pqcrypto_req_control++; @@ -233,11 +257,13 @@ static struct qcrypto_req_control *qcrypto_alloc_req_control( static void qcrypto_free_req_control(struct crypto_engine *pce, struct qcrypto_req_control *preq) { + /* do this before free req */ + preq->req = NULL; + preq->arsp = NULL; + /* free req */ if (xchg(&preq->in_use, false) == false) { pr_warn("request info %p free already\n", preq); } else { - preq->req = NULL; - preq->arsp = NULL; atomic_dec(&pce->req_count); } } @@ -441,7 +467,9 @@ struct qcrypto_cipher_req_ctx { #define SHA_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE #define MSM_QCRYPTO_REQ_QUEUE_LENGTH 768 -#define COMPLETION_CB_BACKLOG_LENGTH 768 +#define COMPLETION_CB_BACKLOG_LENGTH_STOP 400 +#define COMPLETION_CB_BACKLOG_LENGTH_START \ + (COMPLETION_CB_BACKLOG_LENGTH_STOP / 2) static uint8_t _std_init_vector_sha1_uint8[] = { 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, 0x89, @@ -1050,6 +1078,7 @@ static int _disp_stats(int id) unsigned long flags; struct crypto_priv *cp = &qcrypto_dev; struct crypto_engine *pe; + int i; pstat = &_qcrypto_stat; len = scnprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1, @@ -1171,6 +1200,18 @@ static int _disp_stats(int id) len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, " AHASH operation fail : %llu\n", pstat->ahash_op_fail); + len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " resp start, resp stop, max rsp queue reorder-cnt : %u %u %u %u\n", + cp->resp_start, cp->resp_stop, + cp->max_resp_qlen, cp->max_reorder_cnt); + len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " max queue legnth, no avail : %u %u\n", + cp->max_qlen, cp->no_avail); + len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " work queue : %u %u %u\n", + cp->queue_work_eng3, + cp->queue_work_not_eng3, + cp->queue_work_not_eng3_nz); len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, "\n"); spin_lock_irqsave(&cp->lock, flags); @@ -1178,8 +1219,9 @@ static int _disp_stats(int id) len += scnprintf( _debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1, - " Engine %4d Req : %llu\n", + " Engine %4d Req max %d : %llu\n", pe->unit, + pe->max_req_used, pe->total_req ); len += scnprintf( @@ -1192,6 +1234,14 @@ static int _disp_stats(int id) qce_get_driver_stats(pe->qce); } spin_unlock_irqrestore(&cp->lock, flags); + + for (i = 0; i < MAX_SMP_CPU+1; i++) + if (cp->cpu_req[i]) + len += scnprintf( + _debug_read_buf + len, + DEBUG_MAX_RW_BUF - len - 1, + "CPU %d Issue Req : %d\n", + i, cp->cpu_req[i]); return len; } @@ -1201,13 +1251,25 @@ static void _qcrypto_remove_engine(struct crypto_engine *pengine) struct qcrypto_alg *q_alg; struct qcrypto_alg *n; unsigned long flags; + struct crypto_engine *pe; cp = pengine->pcp; spin_lock_irqsave(&cp->lock, flags); list_del(&pengine->elist); + if (pengine->first_engine) { + cp->first_engine = NULL; + pe = list_first_entry(&cp->engine_list, struct crypto_engine, + elist); + if (pe) { + pe->first_engine = true; + cp->first_engine = pe; + } + } if (cp->next_engine == pengine) cp->next_engine = NULL; + if (cp->scheduled_eng == pengine) + cp->scheduled_eng = NULL; spin_unlock_irqrestore(&cp->lock, flags); cp->total_units--; @@ -1414,41 +1476,15 @@ static int _qcrypto_setkey_3des(struct crypto_ablkcipher *cipher, const u8 *key, return 0; }; -static struct crypto_engine *eng_sel_avoid_first(struct crypto_priv *cp) -{ - /* - * This function need not be spinlock protected when called from - * the seq_response workq as it will not have any contentions when all - * request processing is stopped. - */ - struct crypto_engine *p; - struct crypto_engine *q = NULL; - int max_user = QCRYPTO_BIG_NUMBER; - int use_cnt; - - if (unlikely(list_empty(&cp->engine_list))) { - pr_err("%s: no valid ce to schedule\n", __func__); - return NULL; - } - - p = list_first_entry(&cp->engine_list, struct crypto_engine, - elist); - list_for_each_entry_continue(p, &cp->engine_list, elist) { - use_cnt = atomic_read(&p->req_count); - if ((use_cnt < p->max_req) && (use_cnt < max_user)) { - q = p; - max_user = use_cnt; - } - } - return q; -} - static void seq_response(struct work_struct *work) { struct crypto_priv *cp = container_of(work, struct crypto_priv, resp_work); struct llist_node *list; struct llist_node *rev = NULL; + struct crypto_engine *pengine; + unsigned long flags; + int total_unit; again: list = llist_del_all(&cp->ordered_resp_list); @@ -1467,7 +1503,6 @@ static void seq_response(struct work_struct *work) while (rev) { struct qcrypto_resp_ctx *arsp; struct crypto_async_request *areq; - struct crypto_engine *pengine; arsp = container_of(rev, struct qcrypto_resp_ctx, llist); rev = llist_next(rev); @@ -1477,12 +1512,20 @@ static void seq_response(struct work_struct *work) areq->complete(areq, arsp->res); local_bh_enable(); atomic_dec(&cp->resp_cnt); - if (ACCESS_ONCE(cp->ce_req_proc_sts) == STOPPED && - atomic_read(&cp->resp_cnt) <= - (COMPLETION_CB_BACKLOG_LENGTH / 2)) { - pengine = eng_sel_avoid_first(cp); + } + + if (atomic_read(&cp->resp_cnt) < COMPLETION_CB_BACKLOG_LENGTH_START && + (cmpxchg(&cp->ce_req_proc_sts, STOPPED, IN_PROGRESS) + == STOPPED)) { + cp->resp_start++; + for (total_unit = cp->total_units; total_unit-- > 0;) { + spin_lock_irqsave(&cp->lock, flags); + pengine = _avail_eng(cp); + spin_unlock_irqrestore(&cp->lock, flags); if (pengine) _start_qcrypto_process(cp, pengine); + else + break; } } end: @@ -1494,12 +1537,19 @@ static void seq_response(struct work_struct *work) goto end; } -static void _qcrypto_tfm_complete(struct crypto_priv *cp, u32 type, - void *tfm_ctx) +#define SCHEUDLE_RSP_QLEN_THRESHOLD 64 + +static void _qcrypto_tfm_complete(struct crypto_engine *pengine, u32 type, + void *tfm_ctx, + struct qcrypto_resp_ctx *cur_arsp, + int res) { + struct crypto_priv *cp = pengine->pcp; unsigned long flags; struct qcrypto_resp_ctx *arsp; struct list_head *plist; + unsigned int resp_qlen; + unsigned int cnt = 0; switch (type) { case CRYPTO_ALG_TYPE_AHASH: @@ -1513,6 +1563,8 @@ static void _qcrypto_tfm_complete(struct crypto_priv *cp, u32 type, } spin_lock_irqsave(&cp->lock, flags); + + cur_arsp->res = res; while (!list_empty(plist)) { arsp = list_first_entry(plist, struct qcrypto_resp_ctx, list); @@ -1521,16 +1573,51 @@ static void _qcrypto_tfm_complete(struct crypto_priv *cp, u32 type, else { list_del(&arsp->list); llist_add(&arsp->llist, &cp->ordered_resp_list); + atomic_inc(&cp->resp_cnt); + cnt++; } } + resp_qlen = atomic_read(&cp->resp_cnt); + if (resp_qlen > cp->max_resp_qlen) + cp->max_resp_qlen = resp_qlen; + if (cnt > cp->max_reorder_cnt) + cp->max_reorder_cnt = cnt; + if ((resp_qlen >= COMPLETION_CB_BACKLOG_LENGTH_STOP) && + cmpxchg(&cp->ce_req_proc_sts, IN_PROGRESS, + STOPPED) == IN_PROGRESS) { + cp->resp_stop++; + } + spin_unlock_irqrestore(&cp->lock, flags); retry: if (!llist_empty(&cp->ordered_resp_list)) { + unsigned int cpu; + + if (pengine->first_engine) { + cpu = WORK_CPU_UNBOUND; + cp->queue_work_eng3++; + } else { + cp->queue_work_not_eng3++; + cpu = cp->cpu_getting_irqs_frm_first_ce; + /* + * If source not the first engine, and there + * are outstanding requests going on first engine, + * skip scheduling of work queue to anticipate + * more may be coming. If the response queue + * length exceeds threshold, to avoid further + * delay, schedule work queue immediately. + */ + if (cp->first_engine && atomic_read( + &cp->first_engine->req_count)) { + if (resp_qlen < SCHEUDLE_RSP_QLEN_THRESHOLD) + return; + cp->queue_work_not_eng3_nz++; + } + } if (cmpxchg(&cp->sched_resp_workq_status, NOT_SCHEDULED, IS_SCHEDULED) == NOT_SCHEDULED) - queue_work_on(cp->cpu_getting_irqs_frm_first_ce, - cp->resp_wq, &cp->resp_work); + queue_work_on(cpu, cp->resp_wq, &cp->resp_work); else if (cmpxchg(&cp->sched_resp_workq_status, IS_SCHEDULED, SCHEDULE_AGAIN) == NOT_SCHEDULED) goto retry; @@ -1541,36 +1628,34 @@ static void req_done(struct qcrypto_req_control *pqcrypto_req_control) { struct crypto_engine *pengine; struct crypto_async_request *areq; - struct crypto_engine *pe; struct crypto_priv *cp; - unsigned long flags; struct qcrypto_resp_ctx *arsp; u32 type = 0; void *tfm_ctx = NULL; + unsigned int cpu; + int res; pengine = pqcrypto_req_control->pce; cp = pengine->pcp; - spin_lock_irqsave(&cp->lock, flags); areq = pqcrypto_req_control->req; arsp = pqcrypto_req_control->arsp; + res = pqcrypto_req_control->res; qcrypto_free_req_control(pengine, pqcrypto_req_control); if (areq) { type = crypto_tfm_alg_type(areq->tfm); tfm_ctx = crypto_tfm_ctx(areq->tfm); } - pe = list_first_entry(&cp->engine_list, struct crypto_engine, elist); - if (pe == pengine) - if (cp->cpu_getting_irqs_frm_first_ce != smp_processor_id()) - cp->cpu_getting_irqs_frm_first_ce = smp_processor_id(); - spin_unlock_irqrestore(&cp->lock, flags); - if (atomic_read(&cp->resp_cnt) <= COMPLETION_CB_BACKLOG_LENGTH) { - cmpxchg(&cp->ce_req_proc_sts, STOPPED, IN_PROGRESS); - _start_qcrypto_process(cp, pengine); - } else - cmpxchg(&cp->ce_req_proc_sts, IN_PROGRESS, STOPPED); + cpu = smp_processor_id(); + pengine->irq_cpu = cpu; + if (pengine->first_engine) { + if (cpu != cp->cpu_getting_irqs_frm_first_ce) + cp->cpu_getting_irqs_frm_first_ce = cpu; + } if (areq) - _qcrypto_tfm_complete(cp, type, tfm_ctx); + _qcrypto_tfm_complete(pengine, type, tfm_ctx, arsp, res); + if (ACCESS_ONCE(cp->ce_req_proc_sts) == IN_PROGRESS) + _start_qcrypto_process(cp, pengine); } static void _qce_ahash_complete(void *cookie, unsigned char *digest, @@ -1620,10 +1705,10 @@ static void _qce_ahash_complete(void *cookie, unsigned char *digest, rctx->first_blk = 0; if (ret) { - pqcrypto_req_control->arsp->res = -ENXIO; + pqcrypto_req_control->res = -ENXIO; pstat->ahash_op_fail++; } else { - pqcrypto_req_control->arsp->res = 0; + pqcrypto_req_control->res = 0; pstat->ahash_op_success++; } if (cp->ce_support.aligned_only) { @@ -1665,10 +1750,10 @@ static void _qce_ablk_cipher_complete(void *cookie, unsigned char *icb, memcpy(ctx->iv, iv, crypto_ablkcipher_ivsize(ablk)); if (ret) { - pqcrypto_req_control->arsp->res = -ENXIO; + pqcrypto_req_control->res = -ENXIO; pstat->ablk_cipher_op_fail++; } else { - pqcrypto_req_control->arsp->res = 0; + pqcrypto_req_control->res = 0; pstat->ablk_cipher_op_success++; } @@ -1811,7 +1896,7 @@ static void _qce_aead_complete(void *cookie, unsigned char *icv, else pstat->aead_op_success++; - pqcrypto_req_control->arsp->res = ret; + pqcrypto_req_control->res = ret; req_done(pqcrypto_req_control); } @@ -2272,12 +2357,24 @@ static int _start_qcrypto_process(struct crypto_priv *cp, struct aead_request *aead_req; struct qcrypto_resp_ctx *arsp; struct qcrypto_req_control *pqcrypto_req_control; + unsigned int cpu = MAX_SMP_CPU; + + if (ACCESS_ONCE(cp->ce_req_proc_sts) == STOPPED) + return 0; + + if (in_interrupt()) { + cpu = smp_processor_id(); + if (cpu >= MAX_SMP_CPU) + cpu = MAX_SMP_CPU - 1; + } else + cpu = MAX_SMP_CPU; pstat = &_qcrypto_stat; again: spin_lock_irqsave(&cp->lock, flags); - if (atomic_read(&pengine->req_count) >= (pengine->max_req)) { + if (pengine->issue_req || + atomic_read(&pengine->req_count) >= (pengine->max_req)) { spin_unlock_irqrestore(&cp->lock, flags); return 0; } @@ -2348,7 +2445,6 @@ static int _start_qcrypto_process(struct crypto_priv *cp, break; } - atomic_inc(&cp->resp_cnt); arsp->res = -EINPROGRESS; arsp->async_req = async_req; pqcrypto_req_control->pce = pengine; @@ -2357,6 +2453,10 @@ static int _start_qcrypto_process(struct crypto_priv *cp, pengine->active_seq++; pengine->check_flag = true; + pengine->issue_req = true; + cp->cpu_req[cpu]++; + smp_mb(); /* make it visible */ + spin_unlock_irqrestore(&cp->lock, flags); if (backlog_eng) backlog_eng->complete(backlog_eng, -EINPROGRESS); @@ -2376,9 +2476,12 @@ static int _start_qcrypto_process(struct crypto_priv *cp, default: ret = -EINVAL; }; + + pengine->issue_req = false; + smp_mb(); /* make it visible */ + pengine->total_req++; if (ret) { - arsp->res = ret; pengine->err_req++; qcrypto_free_req_control(pengine, pqcrypto_req_control); @@ -2390,32 +2493,48 @@ static int _start_qcrypto_process(struct crypto_priv *cp, else pstat->aead_op_fail++; - _qcrypto_tfm_complete(cp, type, tfm_ctx); + _qcrypto_tfm_complete(pengine, type, tfm_ctx, arsp, ret); goto again; }; return ret; } +static inline struct crypto_engine *_next_eng(struct crypto_priv *cp, + struct crypto_engine *p) +{ + + if (p == NULL || list_is_last(&p->elist, &cp->engine_list)) + p = list_first_entry(&cp->engine_list, struct crypto_engine, + elist); + else + p = list_entry(p->elist.next, struct crypto_engine, elist); + return p; +} static struct crypto_engine *_avail_eng(struct crypto_priv *cp) { /* call this function with spinlock set */ - struct crypto_engine *p; struct crypto_engine *q = NULL; - int max_user = QCRYPTO_BIG_NUMBER; - int use_cnt; + struct crypto_engine *p = cp->scheduled_eng; + struct crypto_engine *q1; + int eng_cnt = cp->total_units; if (unlikely(list_empty(&cp->engine_list))) { pr_err("%s: no valid ce to schedule\n", __func__); return NULL; } - list_for_each_entry(p, &cp->engine_list, elist) { - use_cnt = atomic_read(&p->req_count); - if ((use_cnt < p->max_req) && (use_cnt < max_user)) { + p = _next_eng(cp, p); + q1 = p; + while (eng_cnt-- > 0) { + if (!p->issue_req && atomic_read(&p->req_count) < p->max_req) { q = p; - max_user = use_cnt; + break; } + p = _next_eng(cp, p); + if (q1 == p) + break; } + cp->scheduled_eng = q; return q; } @@ -2433,6 +2552,8 @@ static int _qcrypto_queue_req(struct crypto_priv *cp, } else { ret = crypto_enqueue_request(&cp->req_queue, req); pengine = _avail_eng(cp); + if (cp->req_queue.qlen > cp->max_qlen) + cp->max_qlen = cp->req_queue.qlen; } if (pengine) { switch (pengine->bw_state) { @@ -2458,16 +2579,12 @@ static int _qcrypto_queue_req(struct crypto_priv *cp, pengine = NULL; break; } + } else { + cp->no_avail++; } spin_unlock_irqrestore(&cp->lock, flags); - if (pengine) { - if (atomic_read(&cp->resp_cnt) <= - COMPLETION_CB_BACKLOG_LENGTH) { - cmpxchg(&cp->ce_req_proc_sts, STOPPED, IN_PROGRESS); - _start_qcrypto_process(cp, pengine); - } else - cmpxchg(&cp->ce_req_proc_sts, IN_PROGRESS, STOPPED); - } + if (pengine && (ACCESS_ONCE(cp->ce_req_proc_sts) == IN_PROGRESS)) + _start_qcrypto_process(cp, pengine); return ret; } @@ -5082,6 +5199,8 @@ static int _qcrypto_probe(struct platform_device *pdev) pengine->active_seq = 0; pengine->last_active_seq = 0; pengine->check_flag = false; + pengine->max_req_used = 0; + pengine->issue_req = false; crypto_init_queue(&pengine->req_queue, MSM_QCRYPTO_REQ_QUEUE_LENGTH); @@ -5090,6 +5209,9 @@ static int _qcrypto_probe(struct platform_device *pdev) pengine->unit = cp->total_units; spin_lock_irqsave(&cp->lock, flags); + pengine->first_engine = list_empty(&cp->engine_list); + if (pengine->first_engine) + cp->first_engine = pengine; list_add_tail(&pengine->elist, &cp->engine_list); cp->next_engine = pengine; spin_unlock_irqrestore(&cp->lock, flags); @@ -5613,6 +5735,7 @@ static ssize_t _debug_stats_write(struct file *file, const char __user *buf, unsigned long flags; struct crypto_priv *cp = &qcrypto_dev; struct crypto_engine *pe; + int i; memset((char *)&_qcrypto_stat, 0, sizeof(struct crypto_stat)); spin_lock_irqsave(&cp->lock, flags); @@ -5620,7 +5743,19 @@ static ssize_t _debug_stats_write(struct file *file, const char __user *buf, pe->total_req = 0; pe->err_req = 0; qce_clear_driver_stats(pe->qce); + pe->max_req_used = 0; } + cp->max_qlen = 0; + cp->resp_start = 0; + cp->resp_stop = 0; + cp->no_avail = 0; + cp->max_resp_qlen = 0; + cp->queue_work_eng3 = 0; + cp->queue_work_not_eng3 = 0; + cp->queue_work_not_eng3_nz = 0; + cp->max_reorder_cnt = 0; + for (i = 0; i < MAX_SMP_CPU + 1; i++) + cp->cpu_req[i] = 0; spin_unlock_irqrestore(&cp->lock, flags); return count; } @@ -5683,6 +5818,8 @@ static int __init _qcrypto_init(void) pcp->total_units = 0; pcp->platform_support.bus_scale_table = NULL; pcp->next_engine = NULL; + pcp->scheduled_eng = NULL; + pcp->ce_req_proc_sts = IN_PROGRESS; crypto_init_queue(&pcp->req_queue, MSM_QCRYPTO_REQ_QUEUE_LENGTH); return platform_driver_register(&_qualcomm_crypto); } From 4e9fdb9ff4efb8a9e25587eb2637d88c53bffdea Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 23 Feb 2016 11:03:12 +0000 Subject: [PATCH 184/203] KEYS: Fix ASN.1 indefinite length object parsing This fixes CVE-2016-0758. In the ASN.1 decoder, when the length field of an ASN.1 value is extracted, it isn't validated against the remaining amount of data before being added to the cursor. With a sufficiently large size indicated, the check: datalen - dp < 2 may then fail due to integer overflow. Fix this by checking the length indicated against the amount of remaining data in both places a definite length is determined. Whilst we're at it, make the following changes: (1) Check the maximum size of extended length does not exceed the capacity of the variable it's being stored in (len) rather than the type that variable is assumed to be (size_t). (2) Compare the EOC tag to the symbolic constant ASN1_EOC rather than the integer 0. (3) To reduce confusion, move the initialisation of len outside of: for (len = 0; n > 0; n--) { since it doesn't have anything to do with the loop counter n. Change-Id: Ic6e9294f6203c9a9dddc2505fd71f34a6863b3d3 Signed-off-by: David Howells Reviewed-by: Mimi Zohar Acked-by: David Woodhouse Acked-by: Peter Jones Signed-off-by: Francisco Franco --- lib/asn1_decoder.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 1a000bb050f9..2937ba5e5e09 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -69,7 +69,7 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen /* Extract a tag from the data */ tag = data[dp++]; - if (tag == 0) { + if (tag == ASN1_EOC) { /* It appears to be an EOC. */ if (data[dp++] != 0) goto invalid_eoc; @@ -91,10 +91,8 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen /* Extract the length */ len = data[dp++]; - if (len <= 0x7f) { - dp += len; - goto next_tag; - } + if (len <= 0x7f) + goto check_length; if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { /* Indefinite length */ @@ -105,14 +103,18 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen } n = len - 0x80; - if (unlikely(n > sizeof(size_t) - 1)) + if (unlikely(n > sizeof(len) - 1)) goto length_too_long; if (unlikely(n > datalen - dp)) goto data_overrun_error; - for (len = 0; n > 0; n--) { + len = 0; + for (; n > 0; n--) { len <<= 8; len |= data[dp++]; } +check_length: + if (len > datalen - dp) + goto data_overrun_error; dp += len; goto next_tag; From 6af857887ec32d2fd4a16defcc6b67dde5e25424 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 10 Mar 2016 01:56:23 +0100 Subject: [PATCH 185/203] netfilter: x_tables: check for size overflow Ben Hawkes says: integer overflow in xt_alloc_table_info, which on 32-bit systems can lead to small structure allocation and a copy_from_user based heap corruption. Change-Id: I13c554c630651a37e3f6a195e9a5f40cddcb29a1 Reported-by: Ben Hawkes Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso (cherry picked from commit a1627c03b448f49b8ed6b72a7a5dbd47a08cc58f) Signed-off-by: Francisco Franco --- net/netfilter/x_tables.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 133eb4772f12..902f7d9dc599 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -660,6 +660,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) { struct xt_table_info *newinfo; int cpu; + size_t sz = sizeof(*newinfo) + size; + + if (sz < sizeof(*newinfo)) + return NULL; /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages) From cc7a4bf4da2bc150c78a9703fbf180dfb20e5bd4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 14 Mar 2016 09:56:35 -0300 Subject: [PATCH 186/203] net: Fix use after free in the recvmmsg exit path The syzkaller fuzzer hit the following use-after-free: Call Trace: [] __asan_report_load8_noabort+0x3e/0x40 mm/kasan/report.c:295 [] __sys_recvmmsg+0x6fa/0x7f0 net/socket.c:2261 [< inline >] SYSC_recvmmsg net/socket.c:2281 [] SyS_recvmmsg+0x16f/0x180 net/socket.c:2270 [] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185 And, as Dmitry rightly assessed, that is because we can drop the reference and then touch it when the underlying recvmsg calls return some packets and then hit an error, which will make recvmmsg to set sock->sk->sk_err, oops, fix it. Reported-and-Tested-by: Dmitry Vyukov Cc: Alexander Potapenko Cc: Eric Dumazet Cc: Kostya Serebryany Cc: Sasha Levin Fixes: a2e2725541fa ("net: Introduce recvmmsg socket syscall") http://lkml.kernel.org/r/20160122211644.GC2470@redhat.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller Change-Id: I447302392f46841f31c374bdb560fe5ee9c2d687 Git-repo: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git Git-commit: 34b88a68f26a75e4fded796f1a49c40f82234b7d Signed-off-by: Dennis Cagle Signed-off-by: Francisco Franco --- net/socket.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/net/socket.c b/net/socket.c index 6c0bfab8c727..abb3c75b3f9a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2455,31 +2455,31 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, break; } -out_put: - fput_light(sock->file, fput_needed); - if (err == 0) - return datagrams; + goto out_put; - if (datagrams != 0) { + if (datagrams == 0) { + datagrams = err; + goto out_put; + } + + /* + * We may return less entries than requested (vlen) if the + * sock is non block and there aren't enough datagrams... + */ + if (err != -EAGAIN) { /* - * We may return less entries than requested (vlen) if the - * sock is non block and there aren't enough datagrams... + * ... or if recvmsg returns an error after we + * received some datagrams, where we record the + * error to return on the next call or if the + * app asks about it using getsockopt(SO_ERROR). */ - if (err != -EAGAIN) { - /* - * ... or if recvmsg returns an error after we - * received some datagrams, where we record the - * error to return on the next call or if the - * app asks about it using getsockopt(SO_ERROR). - */ - sock->sk->sk_err = -err; - } - - return datagrams; + sock->sk->sk_err = -err; } +out_put: + fput_light(sock->file, fput_needed); - return err; + return datagrams; } SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, From 2682f291ae3440d68b21838363664fd0718a0873 Mon Sep 17 00:00:00 2001 From: William Clark Date: Thu, 17 Mar 2016 16:32:18 -0700 Subject: [PATCH 187/203] crypto: fix pointer dereference Fix a few possible NULL pointer dereferences. Change-Id: Idc992d61952fc125e2898e1fc84f9ffecf9be737 Signed-off-by: William Clark Signed-off-by: Francisco Franco --- drivers/crypto/msm/ota_crypto.c | 6 +++++- drivers/crypto/msm/qce50.c | 23 ++++++++++++++++++++--- drivers/crypto/msm/qcrypto.c | 22 ++++++++++++++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c index 9b4a001bec95..8aa0d04f14fd 100644 --- a/drivers/crypto/msm/ota_crypto.c +++ b/drivers/crypto/msm/ota_crypto.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-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 @@ -239,6 +239,10 @@ static void req_done(unsigned long data) if (!list_empty(&podev->ready_commands)) { new_req = container_of(podev->ready_commands.next, struct ota_async_req, rlist); + if (NULL == new_req) { + pr_err("ota_crypto: req_done, new_req = NULL"); + return; + } list_del(&new_req->rlist); pqce->active_command = new_req; spin_unlock_irqrestore(&podev->lock, flags); diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index eb0e8fa1fbb2..c1df97fa3554 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -213,8 +213,13 @@ static int count_sg(struct scatterlist *sg, int nbytes) { int i; - for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg)) + for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg)) { + if (NULL == sg) { + pr_err("qce50.c: count_sg, sg = NULL"); + break; + } nbytes -= sg->length; + } return i; } @@ -224,6 +229,10 @@ static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int i; for (i = 0; i < nents; ++i) { + if (NULL == sg) { + pr_err("qce50.c: qce_dma_map_sg, sg = NULL"); + break; + } dma_map_sg(dev, sg, 1, direction); sg = scatterwalk_sg_next(sg); } @@ -237,6 +246,10 @@ static int qce_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int i; for (i = 0; i < nents; ++i) { + if (NULL == sg) { + pr_err("qce50.c: qce_dma_unmap_sg, sg = NULL"); + break; + } dma_unmap_sg(dev, sg, 1, direction); sg = scatterwalk_sg_next(sg); } @@ -339,7 +352,7 @@ static int _ce_setup_hash(struct qce_device *pce_dev, struct qce_sha_req *sreq, struct qce_cmdlist_info *cmdlistinfo) { - uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)]; + uint32_t auth32[(SHA256_DIGEST_SIZE / sizeof(uint32_t))+1]; uint32_t diglen; int i; uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = { @@ -1174,7 +1187,7 @@ static void _qce_dump_descr_fifos_dbg(struct qce_device *pce_dev, int req_info) static int _ce_setup_hash_direct(struct qce_device *pce_dev, struct qce_sha_req *sreq) { - uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)]; + uint32_t auth32[(SHA256_DIGEST_SIZE / sizeof(uint32_t))+1]; uint32_t diglen; bool use_hw_key = false; bool use_pipe_key = false; @@ -2428,6 +2441,10 @@ static int _qce_sps_add_sg_data(struct qce_device *pce_dev, sps_bam_pipe->iovec_count; while (nbytes > 0) { + if (NULL == sg_src) { + pr_err("qce50.c: _qce_sps_add_sg_data, sg_src = NULL"); + break; + } len = min(nbytes, sg_dma_len(sg_src)); nbytes -= len; addr = sg_dma_address(sg_src); diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index be3d3fcdebf5..8bdf9da4d654 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -742,6 +742,10 @@ static size_t qcrypto_sg_copy_from_buffer(struct scatterlist *sgl, size_t offset, len; for (i = 0, offset = 0; i < nents; ++i) { + if (NULL == sgl) { + pr_err("qcrypto.c: qcrypto_sg_copy_from_buffer, sgl = NULL"); + break; + } len = sg_copy_from_buffer(sgl, 1, buf, buflen); buf += len; buflen -= len; @@ -759,6 +763,10 @@ static size_t qcrypto_sg_copy_to_buffer(struct scatterlist *sgl, size_t offset, len; for (i = 0, offset = 0; i < nents; ++i) { + if (NULL == sgl) { + pr_err("qcrypto.c: qcrypto_sg_copy_from_buffer, sgl = NULL"); + break; + } len = sg_copy_to_buffer(sgl, 1, buf, buflen); buf += len; buflen -= len; @@ -4010,6 +4018,10 @@ static int _sha_update(struct ahash_request *req, uint32_t sha_block_size) break; len += sg_last->length; sg_last = scatterwalk_sg_next(sg_last); + if (NULL == sg_last) { + pr_err("qcrypto.c: _sha_update, sg_last = NULL"); + break; + } } if (rctx->trailing_buf_len) { if (cp->ce_support.aligned_only) { @@ -4031,7 +4043,10 @@ static int _sha_update(struct ahash_request *req, uint32_t sha_block_size) req->src = rctx->sg; sg_mark_end(&rctx->sg[0]); } else { - sg_mark_end(sg_last); + if (sg_last) + sg_mark_end(sg_last); + else + pr_err("qcrypto: _sha_update, sg_last= NULL"); memset(rctx->sg, 0, sizeof(rctx->sg)); sg_set_buf(&rctx->sg[0], staging, rctx->trailing_buf_len); @@ -4040,7 +4055,10 @@ static int _sha_update(struct ahash_request *req, uint32_t sha_block_size) req->src = rctx->sg; } } else - sg_mark_end(sg_last); + if (sg_last) + sg_mark_end(sg_last); + else + pr_err("qcrypto.c: _sha_update, sg_last = NULL"); req->nbytes = nbytes; rctx->trailing_buf_len = trailing_buf_len; From d737bc206fa4801958178afe8fbf1bb6c1a49b5d Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Thu, 16 Jun 2016 18:55:47 -0700 Subject: [PATCH 188/203] msm: mdss: Fix memleak in panel_debug_reg_write Free panel buffer or register buffer if either allocation fails. Change-Id: I600c646a0c23b654392d8e00a829bfd88b71c38c Signed-off-by: Krishna Srinivas Signed-off-by: Francisco Franco --- drivers/video/msm/mdss/mdss_debug.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index 8e76af30d150..7b1620035da4 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -200,6 +200,7 @@ static ssize_t panel_debug_base_reg_read(struct file *file, struct mdss_panel_data *panel_data = ctl->panel_data; struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data); + int rc = -EFAULT; if (!dbg) return -ENODEV; @@ -218,7 +219,8 @@ static ssize_t panel_debug_base_reg_read(struct file *file, if (!rx_buf || !panel_reg_buf) { pr_err("not enough memory to hold panel reg dump\n"); - return -ENOMEM; + rc = -ENOMEM; + goto read_reg_fail; } if (mdata->debug_inf.debug_enable_clock) @@ -253,8 +255,7 @@ static ssize_t panel_debug_base_reg_read(struct file *file, read_reg_fail: kfree(rx_buf); kfree(panel_reg_buf); - return -EFAULT; - + return rc; } static const struct file_operations panel_off_fops = { From f1aba600087274ebeb2f6867b55292338acdc8b2 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 5 Jul 2016 22:12:36 -0700 Subject: [PATCH 189/203] UPSTREAM: ppp: defer netns reference release for ppp channel (cherry pick from commit 205e1e255c479f3fd77446415706463b282f94e4) Matt reported that we have a NULL pointer dereference in ppp_pernet() from ppp_connect_channel(), i.e. pch->chan_net is NULL. This is due to that a parallel ppp_unregister_channel() could happen while we are in ppp_connect_channel(), during which pch->chan_net set to NULL. Since we need a reference to net per channel, it makes sense to sync the refcnt with the life time of the channel, therefore we should release this reference when we destroy it. Fixes: 1f461dcdd296 ("ppp: take reference on channels netns") Reported-by: Matt Bennett Cc: Paul Mackerras Cc: linux-ppp@vger.kernel.org Cc: Guillaume Nault Cc: Cyrill Gorcunov Signed-off-by: Cong Wang Reviewed-by: Cyrill Gorcunov Signed-off-by: David S. Miller Fixes: Change-Id: Iee0015eca5bd181954bb4896a3720f7549c5ed0b ("UPSTREAM: ppp: take reference on channels netns") Signed-off-by: Amit Pundir Change-Id: I24d0bb6f349ab3829f63cfe935ed97b6913a3508 Signed-off-by: Francisco Franco --- drivers/net/ppp/ppp_generic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 6d6c20c3ef7e..30023ef2887e 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -2957,6 +2957,9 @@ ppp_disconnect_channel(struct channel *pch) */ static void ppp_destroy_channel(struct channel *pch) { + put_net(pch->chan_net); + pch->chan_net = NULL; + atomic_dec(&channel_count); if (!pch->file.dead) { From aa20ca9fc64c6b649fefa7ef02b6363646906992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Fri, 12 Aug 2016 16:04:28 -0700 Subject: [PATCH 190/203] ANDROID: binder: Clear binder and cookie when setting handle in flat binder struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevents leaking pointers between processes BUG: 30768347 Change-Id: Id898076926f658a1b8b27a3ccb848756b36de4ca Signed-off-by: Arve Hjønnevåg Git-repo: https://android.googlesource.com/kernel/msm.git Git-commit: 11032d745836280574827bb1db5e64a94945180e Signed-off-by: Dennis Cagle Signed-off-by: Francisco Franco --- drivers/staging/android/binder.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 3aa007572d75..54107f75ed07 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1577,7 +1577,9 @@ static void binder_transaction(struct binder_proc *proc, fp->type = BINDER_TYPE_HANDLE; else fp->type = BINDER_TYPE_WEAK_HANDLE; + fp->binder = 0; fp->handle = ref->desc; + fp->cookie = 0; binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo); @@ -1623,7 +1625,9 @@ static void binder_transaction(struct binder_proc *proc, return_error = BR_FAILED_REPLY; goto err_binder_get_ref_for_node_failed; } + fp->binder = 0; fp->handle = new_ref->desc; + fp->cookie = 0; binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); trace_binder_transaction_ref_to_ref(t, ref, new_ref); @@ -1675,6 +1679,7 @@ static void binder_transaction(struct binder_proc *proc, binder_debug(BINDER_DEBUG_TRANSACTION, " fd %d -> %d\n", fp->handle, target_fd); /* TODO: fput? */ + fp->binder = 0; fp->handle = target_fd; } break; From 5dc164307fd9364320ca8bccb6770e9243742597 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Thu, 8 Jan 2015 11:42:59 +0000 Subject: [PATCH 191/203] UPSTREAM: arm64: make sys_call_table const As with x86, mark the sys_call_table const such that it will be placed in the .rodata section. This will cause attempts to modify the table (accidental or deliberate) to fail when strict page permissions are in place. In the absence of strict page permissions, there should be no functional change. Signed-off-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Catalin Marinas Bug: 31660652 Signed-off-by: Jeff Vander Stoep (cherry picked from commit c623b33b4e9599c6ac5076f7db7369eb9869aa04) Change-Id: I8c5aa13b8adfdb71e3c574a59e5bf63f8cee42c5 Signed-off-by: Francisco Franco --- arch/arm64/kernel/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c index 3fa98ff14f0e..df20b7918854 100644 --- a/arch/arm64/kernel/sys.c +++ b/arch/arm64/kernel/sys.c @@ -50,7 +50,7 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, * The sys_call_table array must be 4K aligned to be accessible from * kernel/entry.S. */ -void *sys_call_table[__NR_syscalls] __aligned(4096) = { +void * const sys_call_table[__NR_syscalls] __aligned(4096) = { [0 ... __NR_syscalls - 1] = sys_ni_syscall, #include }; From c617cfea3d597e79dde4e61d75145859f50fa919 Mon Sep 17 00:00:00 2001 From: Amit Pundir Date: Tue, 11 Aug 2015 12:34:45 +0530 Subject: [PATCH 192/203] usb: gadget: f_mtp: simplify ptp NULL pointer check Simplify MTP/PTP dev NULL pointer check introduced in Change-Id: Ic44a699d96df2e13467fc081bff88b97dcc5afb2 and restrict it to MTP/PTP function level only. Return ERR_PTR() instead of NULL from mtp_ptp function to skip doing NULL pointer checks all the way up to configfs.c Signed-off-by: Amit Pundir Signed-off-by: Dmitry Shmidt Signed-off-by: engstk --- drivers/usb/gadget/configfs.c | 5 ----- drivers/usb/gadget/function/f_mtp.c | 2 +- drivers/usb/gadget/functions.c | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 77b2ea7431f0..8ea58f08ab68 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -436,11 +436,6 @@ static int config_usb_cfg_link( } f = usb_get_function(fi); - if (f == NULL) { - /* Are we trying to symlink PTP without MTP function? */ - ret = -EINVAL; /* Invalid Configuration */ - goto out; - } if (IS_ERR(f)) { ret = PTR_ERR(f); goto out; diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index c0b6fa581c05..da021bea2e2f 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -1930,7 +1930,7 @@ struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi, pr_err("\t2: Create MTP function\n"); pr_err("\t3: Create and symlink PTP function" " with a gadget configuration\n"); - return NULL; + return ERR_PTR(-EINVAL); /* Invalid Configuration */ } dev = fi_mtp->dev; diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c index 389c1f3d0fee..b13f839e7368 100644 --- a/drivers/usb/gadget/functions.c +++ b/drivers/usb/gadget/functions.c @@ -58,7 +58,7 @@ struct usb_function *usb_get_function(struct usb_function_instance *fi) struct usb_function *f; f = fi->fd->alloc_func(fi); - if ((f == NULL) || IS_ERR(f)) + if (IS_ERR(f)) return f; f->fi = fi; return f; From 394f29fcd850ef6af1f54252bddbf7e15efcbbbe Mon Sep 17 00:00:00 2001 From: Jonathan Hamilton Date: Wed, 21 Sep 2016 12:40:51 -0700 Subject: [PATCH 193/203] ANDROID: video: adf: Avoid directly referencing user pointers Enabling KASAN on a kernel using ADF causes a number of places where user-supplied pointers to ioctls pointers are directly dereferenced without copy_from_user or access_ok. Bug: 31806036 Signed-off-by: Jonathan Hamilton Change-Id: I6e86237aaa6cec0f6e1c385336aefcc5332080ae Signed-off-by: engstk --- drivers/video/adf/adf_fops.c | 73 +++++++++++++++--------------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/drivers/video/adf/adf_fops.c b/drivers/video/adf/adf_fops.c index 7fbf33e1cb39..d5c1e5466cff 100644 --- a/drivers/video/adf/adf_fops.c +++ b/drivers/video/adf/adf_fops.c @@ -132,7 +132,7 @@ static int adf_eng_get_data(struct adf_overlay_engine *eng, eng->ops->n_supported_formats)); mutex_lock(&dev->client_lock); - ret = adf_obj_copy_custom_data_to_user(&eng->base, arg->custom_data, + ret = adf_obj_copy_custom_data_to_user(&eng->base, data.custom_data, &data.custom_data_size); mutex_unlock(&dev->client_lock); @@ -144,7 +144,7 @@ static int adf_eng_get_data(struct adf_overlay_engine *eng, goto done; } - if (supported_formats && copy_to_user(arg->supported_formats, + if (supported_formats && copy_to_user(data.supported_formats, supported_formats, n_supported_formats * sizeof(supported_formats[0]))) ret = -EFAULT; @@ -220,56 +220,45 @@ static int adf_device_post_config(struct adf_device *dev, int complete_fence_fd; struct adf_buffer *bufs = NULL; struct adf_interface **intfs = NULL; - size_t n_intfs, n_bufs, i; + struct adf_post_config data; + size_t i; void *custom_data = NULL; - size_t custom_data_size; int ret = 0; + if (copy_from_user(&data, arg, sizeof(data))) + return -EFAULT; + complete_fence_fd = get_unused_fd(); if (complete_fence_fd < 0) return complete_fence_fd; - if (get_user(n_intfs, &arg->n_interfaces)) { - ret = -EFAULT; - goto err_get_user; - } - - if (n_intfs > ADF_MAX_INTERFACES) { + if (data.n_interfaces > ADF_MAX_INTERFACES) { ret = -EINVAL; goto err_get_user; } - if (get_user(n_bufs, &arg->n_bufs)) { - ret = -EFAULT; - goto err_get_user; - } - - if (n_bufs > ADF_MAX_BUFFERS) { + if (data.n_bufs > ADF_MAX_BUFFERS) { ret = -EINVAL; goto err_get_user; } - if (get_user(custom_data_size, &arg->custom_data_size)) { - ret = -EFAULT; - goto err_get_user; - } - - if (custom_data_size > ADF_MAX_CUSTOM_DATA_SIZE) { + if (data.custom_data_size > ADF_MAX_CUSTOM_DATA_SIZE) { ret = -EINVAL; goto err_get_user; } - if (n_intfs) { - intfs = kmalloc(sizeof(intfs[0]) * n_intfs, GFP_KERNEL); + if (data.n_interfaces) { + intfs = kmalloc(sizeof(intfs[0]) * data.n_interfaces, + GFP_KERNEL); if (!intfs) { ret = -ENOMEM; goto err_get_user; } } - for (i = 0; i < n_intfs; i++) { + for (i = 0; i < data.n_interfaces; i++) { u32 intf_id; - if (get_user(intf_id, &arg->interfaces[i])) { + if (get_user(intf_id, &data.interfaces[i])) { ret = -EFAULT; goto err_get_user; } @@ -281,31 +270,31 @@ static int adf_device_post_config(struct adf_device *dev, } } - if (n_bufs) { - bufs = kzalloc(sizeof(bufs[0]) * n_bufs, GFP_KERNEL); + if (data.n_bufs) { + bufs = kzalloc(sizeof(bufs[0]) * data.n_bufs, GFP_KERNEL); if (!bufs) { ret = -ENOMEM; goto err_get_user; } } - for (i = 0; i < n_bufs; i++) { - ret = adf_buffer_import(dev, &arg->bufs[i], &bufs[i]); + for (i = 0; i < data.n_bufs; i++) { + ret = adf_buffer_import(dev, &data.bufs[i], &bufs[i]); if (ret < 0) { memset(&bufs[i], 0, sizeof(bufs[i])); goto err_import; } } - if (custom_data_size) { - custom_data = kzalloc(custom_data_size, GFP_KERNEL); + if (data.custom_data_size) { + custom_data = kzalloc(data.custom_data_size, GFP_KERNEL); if (!custom_data) { ret = -ENOMEM; goto err_import; } - if (copy_from_user(custom_data, arg->custom_data, - custom_data_size)) { + if (copy_from_user(custom_data, data.custom_data, + data.custom_data_size)) { ret = -EFAULT; goto err_import; } @@ -316,8 +305,8 @@ static int adf_device_post_config(struct adf_device *dev, goto err_import; } - complete_fence = adf_device_post_nocopy(dev, intfs, n_intfs, bufs, - n_bufs, custom_data, custom_data_size); + complete_fence = adf_device_post_nocopy(dev, intfs, data.n_interfaces, + bufs, data.n_bufs, custom_data, data.custom_data_size); if (IS_ERR(complete_fence)) { ret = PTR_ERR(complete_fence); goto err_import; @@ -327,7 +316,7 @@ static int adf_device_post_config(struct adf_device *dev, return 0; err_import: - for (i = 0; i < n_bufs; i++) + for (i = 0; i < data.n_bufs; i++) adf_buffer_cleanup(&bufs[i]); err_get_user: @@ -481,19 +470,19 @@ static int adf_device_get_data(struct adf_device *dev, data.n_allowed_attachments); mutex_lock(&dev->client_lock); - ret = adf_obj_copy_custom_data_to_user(&dev->base, arg->custom_data, + ret = adf_obj_copy_custom_data_to_user(&dev->base, data.custom_data, &data.custom_data_size); mutex_unlock(&dev->client_lock); if (ret < 0) goto done; - ret = adf_copy_attachment_list_to_user(arg->attachments, + ret = adf_copy_attachment_list_to_user(data.attachments, data.n_attachments, attach, n_attach); if (ret < 0) goto done; - ret = adf_copy_attachment_list_to_user(arg->allowed_attachments, + ret = adf_copy_attachment_list_to_user(data.allowed_attachments, data.n_allowed_attachments, allowed_attach, n_allowed_attach); if (ret < 0) @@ -592,7 +581,7 @@ static int adf_intf_get_data(struct adf_interface *intf, data.n_available_modes = intf->n_modes; read_unlock_irqrestore(&intf->hotplug_modelist_lock, flags); - if (copy_to_user(arg->available_modes, modelist, modelist_size)) { + if (copy_to_user(data.available_modes, modelist, modelist_size)) { ret = -EFAULT; goto done; } @@ -601,7 +590,7 @@ static int adf_intf_get_data(struct adf_interface *intf, memcpy(&data.current_mode, &intf->current_mode, sizeof(intf->current_mode)); - ret = adf_obj_copy_custom_data_to_user(&intf->base, arg->custom_data, + ret = adf_obj_copy_custom_data_to_user(&intf->base, data.custom_data, &data.custom_data_size); done: mutex_unlock(&dev->client_lock); From 4322405c3223ece089bed347c5b3db8a4d2f0c54 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 6 Oct 2016 15:58:08 -0700 Subject: [PATCH 194/203] diag: dci: avoid out of bounds memory access Bug: 31864832 Change-Id: I7ef183b218d49ad19e0c33d77a52669306471a49 Signed-off-by: Francisco Franco --- drivers/char/diag/diag_dci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 3bc09927ea90..b4e84e791631 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -2943,7 +2943,7 @@ int diag_dci_write_proc(uint8_t peripheral, int pkt_type, char *buf, int len) DIAG_LOG(DIAG_DEBUG_DCI, "buf: 0x%p, p: %d, len: %d, f_mask: %d\n", buf, peripheral, len, - driver->feature[peripheral].rcvd_feature_mask); + driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask); return -EINVAL; } From 5dd3b251adb0b6b248ae50c6edec0202a217dab5 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 7 Oct 2016 10:56:13 -0700 Subject: [PATCH 195/203] binder: blacklist %p kptr_restrict Bug: 31495231 Change-Id: Iebc150f6bc939b56e021424ee44fb30ce8d732fd Signed-off-by: Francisco Franco --- drivers/staging/android/binder.c | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 54107f75ed07..e5a78b33dd94 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -473,7 +473,7 @@ static void binder_insert_free_buffer(struct binder_proc *proc, new_buffer_size = binder_buffer_size(proc, new_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: add free buffer, size %zd, at %p\n", + "%d: add free buffer, size %zd, at %pK\n", proc->pid, new_buffer_size, new_buffer); while (*p) { @@ -551,7 +551,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, struct mm_struct *mm; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: %s pages %p-%p\n", proc->pid, + "%d: %s pages %pK-%pK\n", proc->pid, allocate ? "allocate" : "free", start, end); if (end <= start) @@ -591,7 +591,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, BUG_ON(*page); *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { - pr_err("%d: binder_alloc_buf failed for page at %p\n", + pr_err("%d: binder_alloc_buf failed for page at %pK\n", proc->pid, page_addr); goto err_alloc_page_failed; } @@ -600,7 +600,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, flush_cache_vmap((unsigned long)page_addr, (unsigned long)page_addr + PAGE_SIZE); if (ret != 1) { - pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n", + pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", proc->pid, page_addr); goto err_map_kernel_failed; } @@ -709,7 +709,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", + "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", proc->pid, size, buffer, buffer_size); has_page_addr = @@ -739,7 +739,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, binder_insert_free_buffer(proc, new_buffer); } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got %p\n", + "%d: binder_alloc_buf size %zd got %pK\n", proc->pid, size, buffer); buffer->data_size = data_size; buffer->offsets_size = offsets_size; @@ -779,7 +779,7 @@ static void binder_delete_free_buffer(struct binder_proc *proc, if (buffer_end_page(prev) == buffer_end_page(buffer)) free_page_end = 0; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p share page with %p\n", + "%d: merge free, buffer %pK share page with %pK\n", proc->pid, buffer, prev); } @@ -792,14 +792,14 @@ static void binder_delete_free_buffer(struct binder_proc *proc, buffer_start_page(buffer)) free_page_start = 0; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p share page with %p\n", + "%d: merge free, buffer %pK share page with %pK\n", proc->pid, buffer, prev); } } list_del(&buffer->entry); if (free_page_start || free_page_end) { binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: merge free, buffer %p do not share page%s%s with %p or %p\n", + "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n", proc->pid, buffer, free_page_start ? "" : " end", free_page_end ? "" : " start", prev, next); binder_update_page_range(proc, 0, free_page_start ? @@ -820,7 +820,7 @@ static void binder_free_buf(struct binder_proc *proc, ALIGN(buffer->offsets_size, sizeof(void *)); binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_free_buf %p size %zd buffer_size %zd\n", + "%d: binder_free_buf %pK size %zd buffer_size %zd\n", proc->pid, buffer, size, buffer_size); BUG_ON(buffer->free); @@ -1246,7 +1246,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, int debug_id = buffer->debug_id; binder_debug(BINDER_DEBUG_TRANSACTION, - "%d buffer release %d, size %zd-%zd, failed at %p\n", + "%d buffer release %d, size %zd-%zd, failed at %pK\n", proc->pid, buffer->debug_id, buffer->data_size, buffer->offsets_size, failed_at); @@ -2092,7 +2092,7 @@ static int binder_thread_write(struct binder_proc *proc, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", + "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", proc->pid, thread->pid, (u64)cookie, death); if (death == NULL) { @@ -2901,7 +2901,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) #ifdef CONFIG_CPU_CACHE_VIPT if (cache_is_vipt_aliasing()) { while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) { - pr_info("binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); + pr_info("binder_mmap: %d %lx-%lx maps %pK bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); vma->vm_start += PAGE_SIZE; } } @@ -2933,7 +2933,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) proc->vma = vma; proc->vma_vm_mm = vma->vm_mm; - /*pr_info("binder_mmap: %d %lx-%lx maps %p\n", + /*pr_info("binder_mmap: %d %lx-%lx maps %pK\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ return 0; @@ -3159,7 +3159,7 @@ static void binder_deferred_release(struct binder_proc *proc) page_addr = proc->buffer + i * PAGE_SIZE; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%s: %d: page %d at %p not freed\n", + "%s: %d: page %d at %pK not freed\n", __func__, proc->pid, i, page_addr); unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); __free_page(proc->pages[i]); @@ -3238,7 +3238,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, struct binder_transaction *t) { seq_printf(m, - "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", + "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", prefix, t->debug_id, t, t->from ? t->from->proc->pid : 0, t->from ? t->from->pid : 0, @@ -3252,7 +3252,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, if (t->buffer->target_node) seq_printf(m, " node %d", t->buffer->target_node->debug_id); - seq_printf(m, " size %zd:%zd data %p\n", + seq_printf(m, " size %zd:%zd data %pK\n", t->buffer->data_size, t->buffer->offsets_size, t->buffer->data); } @@ -3260,7 +3260,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, static void print_binder_buffer(struct seq_file *m, const char *prefix, struct binder_buffer *buffer) { - seq_printf(m, "%s %d: %p size %zd:%zd %s\n", + seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", prefix, buffer->debug_id, buffer->data, buffer->data_size, buffer->offsets_size, buffer->transaction ? "active" : "delivered"); From 84b29cd3c3ea9f1d510f505bb7166830ae8c7d9f Mon Sep 17 00:00:00 2001 From: Siqi Lin Date: Tue, 11 Oct 2016 11:50:01 -0700 Subject: [PATCH 196/203] msm: camera: Avoid exposing kernel addresses Usage of %p exposes the kernel addresses, an easy target to kernel write vulnerabilities. With this patch currently %pK prints only Zeros as address. If you need actual address echo 0 > /proc/sys/kernel/kptr_restrict CRs-Fixed: 987011 Change-Id: I6c79f82376936fc646b723872a96a6694fe47cd9 Signed-off-by: Azam Sadiq Pasha Kapatrala Syed Signed-off-by: Siqi Lin Bug: 29464815 Signed-off-by: Francisco Franco --- drivers/media/platform/msm/camera_v2/isp/msm_isp40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index fb360501f42a..c0dcec82481b 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -1123,7 +1123,7 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev, rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0 || !buf) { - pr_err("%s: No fetch buffer rc= %d buf= %p\n", + pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); return -EINVAL; } From c3423919718cb8d911ecbbca1432584e17455d99 Mon Sep 17 00:00:00 2001 From: Steve Pfetsch Date: Fri, 14 Oct 2016 15:36:59 -0700 Subject: [PATCH 197/203] drivers: video: Add bounds checking in fb_cmap_to_user Verify that unsigned int value will not become negative before cast to signed int. Bug: 31651010 Change-Id: I548a200f678762042617f11100b6966a405a3920 Signed-off-by: Francisco Franco --- drivers/video/fbdev/core/fbcmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c index f06b7e52bd83..8bfba4242791 100644 --- a/drivers/video/fbdev/core/fbcmap.c +++ b/drivers/video/fbdev/core/fbcmap.c @@ -190,6 +190,9 @@ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) int tooff = 0, fromoff = 0; int size; + if ((int)(to->start) < 0) + return -EINVAL; + if (to->start > from->start) fromoff = to->start - from->start; else From ad5735531a5f30961fb524c341bf0d2ef0f4c00f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 5 Dec 2016 12:10:29 -0800 Subject: [PATCH 198/203] shmem: fix shm fallocate() list corruption The shmem hole punching with fallocate(FALLOC_FL_PUNCH_HOLE) does not want to race with generating new pages by faulting them in. However, the wait-queue used to delay the page faulting has a serious problem: the wait queue head (in shmem_fallocate()) is allocated on the stack, and the code expects that "wake_up_all()" will make sure that all the queue entries are gone before the stack frame is de-allocated. And that is not at all necessarily the case. Yes, a normal wake-up sequence will remove the wait-queue entry that caused the wakeup (see "autoremove_wake_function()"), but the key wording there is "that caused the wakeup". When there are multiple possible wakeup sources, the wait queue entry may well stay around. And _particularly_ in a page fault path, we may be faulting in new pages from user space while we also have other things going on, and there may well be other pending wakeups. So despite the "wake_up_all()", it's not at all guaranteed that all list entries are removed from the wait queue head on the stack. Fix this by introducing a new wakeup function that removes the list entry unconditionally, even if the target process had already woken up for other reasons. Use that "synchronous" function to set up the waiters in shmem_fault(). This problem has never been seen in the wild afaik, but Dave Jones has reported it on and off while running trinity. We thought we fixed the stack corruption with the blk-mq rq_list locking fix (commit 7fe311302f7d: "blk-mq: update hardware and software queues for sleeping alloc"), but it turns out there was _another_ stack corruptor hiding in the trinity runs. Vegard Nossum (also running trinity) was able to trigger this one fairly consistently, and made us look once again at the shmem code due to the faults often being in that area. Reported-and-tested-by: Vegard Nossum . Reported-by: Dave Jones Signed-off-by: Linus Torvalds Signed-off-by: Francisco Franco --- mm/shmem.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mm/shmem.c b/mm/shmem.c index 26472ff651b7..33421523ef01 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1275,6 +1275,18 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, return error; } +/* + * This is like autoremove_wake_function, but it removes the wait queue + * entry unconditionally - even if something else had already woken the + * target. + */ +static int synchronous_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) +{ + int ret = default_wake_function(wait, mode, sync, key); + list_del_init(&wait->task_list); + return ret; +} + static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct inode *inode = file_inode(vma->vm_file); @@ -1308,7 +1320,7 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) vmf->pgoff >= shmem_falloc->start && vmf->pgoff < shmem_falloc->next) { wait_queue_head_t *shmem_falloc_waitq; - DEFINE_WAIT(shmem_fault_wait); + DEFINE_WAIT_FUNC(shmem_fault_wait, synchronous_wake_function); ret = VM_FAULT_NOPAGE; if ((vmf->flags & FAULT_FLAG_ALLOW_RETRY) && @@ -2092,6 +2104,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, spin_lock(&inode->i_lock); inode->i_private = NULL; wake_up_all(&shmem_falloc_waitq); + WARN_ON_ONCE(!list_empty(&shmem_falloc_waitq.task_list)); spin_unlock(&inode->i_lock); error = 0; goto out; From 498e0a8565be1e598306581b81ea4f88bf9deaeb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 27 Oct 2016 09:49:19 -0600 Subject: [PATCH 199/203] blk-mq: update hardware and software queues for sleeping alloc If we end up sleeping due to running out of requests, we should update the hardware and software queues in the map ctx structure. Otherwise we could end up having rq->mq_ctx point to the pre-sleep context, and risk corrupting ctx->rq_list since we'll be grabbing the wrong lock when inserting the request. Reported-by: Dave Jones Reported-by: Chris Mason Tested-by: Chris Mason Fixes: 63581af3f31e ("blk-mq: remove non-blocking pass in blk_mq_map_request") Signed-off-by: Jens Axboe Signed-off-by: Francisco Franco --- block/blk-mq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 691959ecb80f..444e84bea39d 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1127,9 +1127,9 @@ static struct request *blk_mq_map_request(struct request_queue *q, hctx = alloc_data.hctx; } - hctx->queued++; - data->hctx = hctx; - data->ctx = ctx; + data->hctx = alloc_data.hctx; + data->ctx = alloc_data.ctx; + data->hctx->queued++; return rq; } From 04d9b5f9bb5e688a5dac060468f6cb34219edefa Mon Sep 17 00:00:00 2001 From: flar2 Date: Wed, 7 Dec 2016 20:23:42 -0500 Subject: [PATCH 200/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 205074279879..84b50f93efd0 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.29" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.31" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -103,7 +103,10 @@ CONFIG_RCU_FANOUT_LEAF=16 CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set # CONFIG_RCU_BOOST is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +# CONFIG_RCU_NOCB_CPU_NONE is not set +# CONFIG_RCU_NOCB_CPU_ZERO is not set +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set From 7d7b4bb14de72150a7689142ccc0753bdd1d90e3 Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Mon, 21 Nov 2016 21:57:51 +0900 Subject: [PATCH 201/203] input: synaptics: s3320: elevate workqueues to high-priority Measured latency within the kernel driver has been fluctuating between 2~7ms. Elevating the workqueues has made it more consistently in the 2~4ms range. alloc_ordered_workqueue() still makes the workqueue singlethreaded (internal __WQ_ORDERED flag), so this commit only adds WQ_HIGHPRI additionally. Signed-off-by: Park Ju Hyung --- drivers/input/touchscreen/synaptics_driver_s3320.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index 9d37cab19380..285c3a4fb6d3 100644 --- a/drivers/input/touchscreen/synaptics_driver_s3320.c +++ b/drivers/input/touchscreen/synaptics_driver_s3320.c @@ -4138,20 +4138,20 @@ static int synaptics_ts_probe(struct i2c_client *client, const struct i2c_device //push_component_info(TP, ts->fw_id, ts->manu_name); - synaptics_wq = create_singlethread_workqueue("synaptics_wq"); + synaptics_wq = alloc_ordered_workqueue("synaptics_wq", WQ_HIGHPRI); if( !synaptics_wq ){ ret = -ENOMEM; goto exit_createworkqueue_failed; } INIT_DELAYED_WORK(&ts->speed_up_work,speedup_synaptics_resume); - synaptics_report = create_singlethread_workqueue("synaptics_report"); + synaptics_report = alloc_ordered_workqueue("synaptics_report", WQ_HIGHPRI); if( !synaptics_report ){ ret = -ENOMEM; goto exit_createworkqueue_failed; } - get_base_report = create_singlethread_workqueue("get_base_report"); + get_base_report = alloc_ordered_workqueue("get_base_report", WQ_HIGHPRI); if( !get_base_report ){ ret = -ENOMEM; goto exit_createworkqueue_failed; From a17890cebd63873ea76e4364c1b8f9f9aae3b879 Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Wed, 21 Sep 2016 13:11:25 -0700 Subject: [PATCH 202/203] cpuidle: don't disable cpuidle when entering suspend cpuidle was disabled while entering suspend as part of commit 8651f97bd951d0bb1c10fa24e3fa3455193f3548 in order to work around some ACPI bugs. However, there's no reason to do this on modern platforms. Leaving cpuidle enabled can result in improved power consumption if dpm_resume_noirq runs for a significant time. Change-Id: Ie182785b176f448698c0264eba554d1e315e8a06 Signed-off-by: Francisco Franco --- drivers/base/power/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index ef5d2797fceb..230ab8d0ce67 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -606,7 +605,6 @@ void dpm_resume_noirq(pm_message_t state) async_synchronize_full(); dpm_show_time(starttime, state, "noirq"); resume_device_irqs(); - cpuidle_resume(); trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false); } @@ -1142,7 +1140,6 @@ int dpm_suspend_noirq(pm_message_t state) int error = 0; trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true); - cpuidle_pause(); suspend_device_irqs(); mutex_lock(&dpm_list_mtx); pm_transition = state; From bc849c58c0f3e2f71f59999c728c09e42238671e Mon Sep 17 00:00:00 2001 From: flar2 Date: Sat, 17 Dec 2016 23:55:02 -0500 Subject: [PATCH 203/203] update defconfig --- arch/arm64/configs/elementalx_defconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig index 84b50f93efd0..893cbd2bee6b 100644 --- a/arch/arm64/configs/elementalx_defconfig +++ b/arch/arm64/configs/elementalx_defconfig @@ -36,7 +36,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-ElementalX-OP3-0.31" +CONFIG_LOCALVERSION="-ElementalX-OP3-0.32" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -790,7 +790,7 @@ CONFIG_NF_NAT_H323=y CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y -# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_RPFILTER=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y @@ -827,7 +827,7 @@ CONFIG_IP6_NF_IPTABLES=y # CONFIG_IP6_NF_MATCH_HL is not set # CONFIG_IP6_NF_MATCH_IPV6HEADER is not set # CONFIG_IP6_NF_MATCH_MH is not set -# CONFIG_IP6_NF_MATCH_RPFILTER is not set +CONFIG_IP6_NF_MATCH_RPFILTER=y # CONFIG_IP6_NF_MATCH_RT is not set # CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_FILTER=y